summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/accessibility/braille/braille_console.c13
-rw-r--r--drivers/acpi/Kconfig5
-rw-r--r--drivers/acpi/dispatcher/dsobject.c2
-rw-r--r--drivers/acpi/glue.c118
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_perflib.c2
-rw-r--r--drivers/acpi/sbshc.c7
-rw-r--r--drivers/acpi/sleep/proc.c10
-rw-r--r--drivers/acpi/tables.c2
-rw-r--r--drivers/acpi/toshiba_acpi.c261
-rw-r--r--drivers/ata/Kconfig9
-rw-r--r--drivers/ata/ahci.c46
-rw-r--r--drivers/ata/ata_piix.c186
-rw-r--r--drivers/ata/libata-core.c252
-rw-r--r--drivers/ata/libata-eh.c375
-rw-r--r--drivers/ata/libata-scsi.c114
-rw-r--r--drivers/ata/libata-sff.c5
-rw-r--r--drivers/ata/libata.h5
-rw-r--r--drivers/ata/pata_bf54x.c34
-rw-r--r--drivers/ata/pata_marvell.c51
-rw-r--r--drivers/ata/pata_of_platform.c2
-rw-r--r--drivers/ata/pata_pcmcia.c168
-rw-r--r--drivers/ata/pata_sil680.c5
-rw-r--r--drivers/ata/sata_fsl.c26
-rw-r--r--drivers/ata/sata_inic162x.c11
-rw-r--r--drivers/ata/sata_mv.c31
-rw-r--r--drivers/ata/sata_nv.c43
-rw-r--r--drivers/ata/sata_promise.c16
-rw-r--r--drivers/ata/sata_qstor.c12
-rw-r--r--drivers/ata/sata_sil.c16
-rw-r--r--drivers/ata/sata_sil24.c12
-rw-r--r--drivers/ata/sata_sis.c28
-rw-r--r--drivers/ata/sata_svw.c10
-rw-r--r--drivers/ata/sata_uli.c24
-rw-r--r--drivers/ata/sata_via.c24
-rw-r--r--drivers/ata/sata_vsc.c10
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/fore200e.c410
-rw-r--r--drivers/atm/fore200e.h7
-rw-r--r--drivers/atm/horizon.c8
-rw-r--r--drivers/atm/idt77252.c32
-rw-r--r--drivers/atm/idt77252.h4
-rw-r--r--drivers/atm/zatm.c6
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c54
-rw-r--r--drivers/base/class.c136
-rw-r--r--drivers/base/core.c36
-rw-r--r--drivers/base/dd.c3
-rw-r--r--drivers/base/firmware_class.c24
-rw-r--r--drivers/base/platform.c80
-rw-r--r--drivers/base/power/main.c9
-rw-r--r--drivers/block/aoe/aoe.h9
-rw-r--r--drivers/block/aoe/aoeblk.c14
-rw-r--r--drivers/block/aoe/aoechr.c14
-rw-r--r--drivers/block/aoe/aoecmd.c104
-rw-r--r--drivers/block/aoe/aoedev.c14
-rw-r--r--drivers/block/aoe/aoemain.c1
-rw-r--r--drivers/block/aoe/aoenet.c9
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/cciss.c8
-rw-r--r--drivers/block/cciss_scsi.c151
-rw-r--r--drivers/block/cciss_scsi.h4
-rw-r--r--drivers/block/cpqarray.c2
-rw-r--r--drivers/block/floppy.c33
-rw-r--r--drivers/block/hd.c9
-rw-r--r--drivers/block/nbd.c4
-rw-r--r--drivers/block/paride/pg.c5
-rw-r--r--drivers/block/paride/pt.c10
-rw-r--r--drivers/block/pktcdvd.c9
-rw-r--r--drivers/block/ps3disk.c11
-rw-r--r--drivers/block/sunvdc.c4
-rw-r--r--drivers/block/ub.c3
-rw-r--r--drivers/block/viodasd.c3
-rw-r--r--drivers/block/virtio_blk.c14
-rw-r--r--drivers/block/xen-blkfront.c78
-rw-r--r--drivers/bluetooth/bluecard_cs.c8
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/bt3c_cs.c125
-rw-r--r--drivers/bluetooth/btuart_cs.c126
-rw-r--r--drivers/bluetooth/btusb.c36
-rw-r--r--drivers/bluetooth/dtl1_cs.c67
-rw-r--r--drivers/bluetooth/hci_bcsp.c18
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/bluetooth/hci_usb.h10
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/cdrom/gdrom.c4
-rw-r--r--drivers/char/Kconfig13
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/agp.h5
-rw-r--r--drivers/char/agp/alpha-agp.c2
-rw-r--r--drivers/char/agp/amd-k7-agp.c40
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/ati-agp.c2
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/agp/generic.c97
-rw-r--r--drivers/char/agp/hp-agp.c2
-rw-r--r--drivers/char/agp/i460-agp.c2
-rw-r--r--drivers/char/agp/intel-agp.c46
-rw-r--r--drivers/char/agp/nvidia-agp.c24
-rw-r--r--drivers/char/agp/parisc-agp.c2
-rw-r--r--drivers/char/agp/sis-agp.c2
-rw-r--r--drivers/char/agp/sworks-agp.c2
-rw-r--r--drivers/char/agp/uninorth-agp.c4
-rw-r--r--drivers/char/agp/via-agp.c4
-rw-r--r--drivers/char/amiserial.c6
-rw-r--r--drivers/char/applicom.c8
-rw-r--r--drivers/char/bsr.c5
-rw-r--r--drivers/char/cyclades.c21
-rw-r--r--drivers/char/ds1286.c4
-rw-r--r--drivers/char/dsp56k.c4
-rw-r--r--drivers/char/epca.c5
-rw-r--r--drivers/char/generic_serial.c21
-rw-r--r--drivers/char/hpet.c159
-rw-r--r--drivers/char/hvc_console.c14
-rw-r--r--drivers/char/hvc_xen.c6
-rw-r--r--drivers/char/hw_random/n2-drv.c2
-rw-r--r--drivers/char/hw_random/omap-rng.c33
-rw-r--r--drivers/char/ip2/Makefile2
-rw-r--r--drivers/char/ip2/i2ellis.c32
-rw-r--r--drivers/char/ip2/i2ellis.h2
-rw-r--r--drivers/char/ip2/ip2base.c108
-rw-r--r--drivers/char/ip2/ip2main.c550
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/isicom.c61
-rw-r--r--drivers/char/istallion.c118
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/lp.c4
-rw-r--r--drivers/char/mem.c6
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/moxa.c63
-rw-r--r--drivers/char/mxser.c193
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/n_r3964.c8
-rw-r--r--drivers/char/n_tty.c125
-rw-r--r--drivers/char/nozomi.c5
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c75
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c83
-rw-r--r--drivers/char/pcmcia/ipwireless/main.c54
-rw-r--r--drivers/char/pcmcia/ipwireless/tty.c19
-rw-r--r--drivers/char/pcmcia/synclink_cs.c2
-rw-r--r--drivers/char/ppdev.c5
-rw-r--r--drivers/char/pty.c335
-rw-r--r--drivers/char/random.c27
-rw-r--r--drivers/char/raw.c7
-rw-r--r--drivers/char/rtc.c32
-rw-r--r--drivers/char/snsc.c4
-rw-r--r--drivers/char/stallion.c143
-rw-r--r--drivers/char/sx.c4
-rw-r--r--drivers/char/sysrq.c31
-rw-r--r--drivers/char/tpm/Kconfig1
-rw-r--r--drivers/char/tpm/tpm.c132
-rw-r--r--drivers/char/tpm/tpm.h3
-rw-r--r--drivers/char/tpm/tpm_tis.c14
-rw-r--r--drivers/char/tty_audit.c2
-rw-r--r--drivers/char/tty_buffer.c511
-rw-r--r--drivers/char/tty_io.c1401
-rw-r--r--drivers/char/tty_ioctl.c212
-rw-r--r--drivers/char/tty_port.c96
-rw-r--r--drivers/char/vc_screen.c12
-rw-r--r--drivers/char/viotape.c8
-rw-r--r--drivers/char/vt.c91
-rw-r--r--drivers/char/vt_ioctl.c2
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c3
-rw-r--r--drivers/clocksource/acpi_pm.c53
-rw-r--r--drivers/cpufreq/cpufreq.c30
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c5
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c147
-rw-r--r--drivers/cpufreq/cpufreq_performance.c4
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c4
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c4
-rw-r--r--drivers/crypto/talitos.c6
-rw-r--r--drivers/dca/dca-sysfs.c8
-rw-r--r--drivers/dma/dw_dmac.c2
-rw-r--r--drivers/edac/i5000_edac.c196
-rw-r--r--drivers/edac/i82443bxgx_edac.c63
-rw-r--r--drivers/edac/mpc85xx_edac.c33
-rw-r--r--drivers/firewire/fw-card.c56
-rw-r--r--drivers/firewire/fw-cdev.c6
-rw-r--r--drivers/firewire/fw-device.c37
-rw-r--r--drivers/firewire/fw-sbp2.c116
-rw-r--r--drivers/firewire/fw-transaction.c48
-rw-r--r--drivers/firewire/fw-transaction.h9
-rw-r--r--drivers/firmware/dmi_scan.c22
-rw-r--r--drivers/firmware/iscsi_ibft.c21
-rw-r--r--drivers/gpio/gpiolib.c111
-rw-r--r--drivers/gpio/max7301.c24
-rw-r--r--drivers/gpio/max732x.c5
-rw-r--r--drivers/gpio/mcp23s08.c5
-rw-r--r--drivers/gpio/pca953x.c5
-rw-r--r--drivers/gpio/pcf857x.c5
-rw-r--r--drivers/gpu/drm/Kconfig3
-rw-r--r--drivers/gpu/drm/Makefile5
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c52
-rw-r--r--drivers/gpu/drm/drm_cache.c69
-rw-r--r--drivers/gpu/drm/drm_drv.c6
-rw-r--r--drivers/gpu/drm/drm_fops.c8
-rw-r--r--drivers/gpu/drm/drm_gem.c421
-rw-r--r--drivers/gpu/drm/drm_irq.c464
-rw-r--r--drivers/gpu/drm/drm_memory.c2
-rw-r--r--drivers/gpu/drm/drm_mm.c5
-rw-r--r--drivers/gpu/drm/drm_proc.c135
-rw-r--r--drivers/gpu/drm/drm_stub.c11
-rw-r--r--drivers/gpu/drm/drm_sysfs.c2
-rw-r--r--drivers/gpu/drm/i915/Makefile7
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c336
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c476
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1180
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2558
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debug.c201
-rw-r--r--drivers/gpu/drm/i915/i915_gem_proc.c292
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c257
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c514
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c371
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1417
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c509
-rw-r--r--drivers/gpu/drm/mga/mga_drv.c29
-rw-r--r--drivers/gpu/drm/mga/mga_drv.h6
-rw-r--r--drivers/gpu/drm/mga/mga_irq.c74
-rw-r--r--drivers/gpu/drm/mga/mga_state.c2
-rw-r--r--drivers/gpu/drm/r128/r128_drv.c29
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h11
-rw-r--r--drivers/gpu/drm/r128/r128_irq.c55
-rw-r--r--drivers/gpu/drm/r128/r128_state.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c57
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c32
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h57
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq.c268
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c2
-rw-r--r--drivers/gpu/drm/sis/sis_mm.c10
-rw-r--r--drivers/gpu/drm/via/via_drv.c26
-rw-r--r--drivers/gpu/drm/via/via_drv.h16
-rw-r--r--drivers/gpu/drm/via/via_irq.c105
-rw-r--r--drivers/gpu/drm/via/via_mm.c3
-rw-r--r--drivers/hid/Kconfig197
-rw-r--r--drivers/hid/Makefile35
-rw-r--r--drivers/hid/hid-a4tech.c162
-rw-r--r--drivers/hid/hid-apple.c484
-rw-r--r--drivers/hid/hid-belkin.c105
-rw-r--r--drivers/hid/hid-bright.c71
-rw-r--r--drivers/hid/hid-cherry.c87
-rw-r--r--drivers/hid/hid-chicony.c80
-rw-r--r--drivers/hid/hid-core.c1183
-rw-r--r--drivers/hid/hid-cypress.c158
-rw-r--r--drivers/hid/hid-dell.c75
-rw-r--r--drivers/hid/hid-dummy.c72
-rw-r--r--drivers/hid/hid-ezkey.c95
-rw-r--r--drivers/hid/hid-gyration.c96
-rw-r--r--drivers/hid/hid-ids.h406
-rw-r--r--drivers/hid/hid-input-quirks.c484
-rw-r--r--drivers/hid/hid-input.c915
-rw-r--r--drivers/hid/hid-lg.c342
-rw-r--r--drivers/hid/hid-lg.h18
-rw-r--r--drivers/hid/hid-lg2ff.c (renamed from drivers/hid/usbhid/hid-lg2ff.c)14
-rw-r--r--drivers/hid/hid-lgff.c (renamed from drivers/hid/usbhid/hid-lgff.c)34
-rw-r--r--drivers/hid/hid-microsoft.c219
-rw-r--r--drivers/hid/hid-monterey.c82
-rw-r--r--drivers/hid/hid-petalynx.c122
-rw-r--r--drivers/hid/hid-pl.c (renamed from drivers/hid/usbhid/hid-plff.c)83
-rw-r--r--drivers/hid/hid-samsung.c100
-rw-r--r--drivers/hid/hid-sony.c110
-rw-r--r--drivers/hid/hid-sunplus.c82
-rw-r--r--drivers/hid/hid-tmff.c (renamed from drivers/hid/usbhid/hid-tmff.c)138
-rw-r--r--drivers/hid/hid-zpff.c (renamed from drivers/hid/usbhid/hid-zpff.c)71
-rw-r--r--drivers/hid/hidraw.c13
-rw-r--r--drivers/hid/usbhid/Kconfig75
-rw-r--r--drivers/hid/usbhid/Makefile18
-rw-r--r--drivers/hid/usbhid/hid-core.c463
-rw-r--r--drivers/hid/usbhid/hid-ff.c95
-rw-r--r--drivers/hid/usbhid/hid-pidff.c5
-rw-r--r--drivers/hid/usbhid/hid-quirks.c934
-rw-r--r--drivers/hid/usbhid/hiddev.c20
-rw-r--r--drivers/hid/usbhid/usbhid.h4
-rw-r--r--drivers/hid/usbhid/usbkbd.c12
-rw-r--r--drivers/hid/usbhid/usbmouse.c8
-rw-r--r--drivers/hwmon/Kconfig24
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/abituguru3.c3
-rw-r--r--drivers/hwmon/ad7414.c2
-rw-r--r--drivers/hwmon/adm1026.c17
-rw-r--r--drivers/hwmon/adm1029.c5
-rw-r--r--drivers/hwmon/ams/ams-core.c82
-rw-r--r--drivers/hwmon/ams/ams-i2c.c60
-rw-r--r--drivers/hwmon/ams/ams-input.c63
-rw-r--r--drivers/hwmon/ams/ams-pmu.c18
-rw-r--r--drivers/hwmon/ams/ams.h6
-rw-r--r--drivers/hwmon/atxp1.c18
-rw-r--r--drivers/hwmon/dme1737.c320
-rw-r--r--drivers/hwmon/hwmon.c4
-rw-r--r--drivers/hwmon/ibmaem.c7
-rw-r--r--drivers/hwmon/ibmpex.c6
-rw-r--r--drivers/hwmon/it87.c85
-rw-r--r--drivers/hwmon/lm78.c270
-rw-r--r--drivers/hwmon/lm85.c352
-rw-r--r--drivers/hwmon/lm87.c33
-rw-r--r--drivers/hwmon/lm90.c444
-rw-r--r--drivers/hwmon/max1111.c244
-rw-r--r--drivers/hwmon/max1619.c17
-rw-r--r--drivers/hwmon/ultra45_env.c320
-rw-r--r--drivers/hwmon/w83781d.c976
-rw-r--r--drivers/hwmon/w83791d.c324
-rw-r--r--drivers/i2c/busses/Kconfig20
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-highlander.c498
-rw-r--r--drivers/i2c/busses/i2c-mpc.c1
-rw-r--r--drivers/i2c/busses/i2c-omap.c12
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c39
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c22
-rw-r--r--drivers/i2c/busses/i2c-powermac.c33
-rw-r--r--drivers/i2c/busses/i2c-pxa.c94
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c271
-rw-r--r--drivers/i2c/busses/i2c-viapro.c17
-rw-r--r--drivers/i2c/chips/Kconfig11
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/isp1301_omap.c141
-rw-r--r--drivers/i2c/chips/mcu_mpc8349emitx.c209
-rw-r--r--drivers/i2c/chips/tps65010.c12
-rw-r--r--drivers/i2c/i2c-core.c35
-rw-r--r--drivers/i2c/i2c-dev.c10
-rw-r--r--drivers/ide/Kconfig97
-rw-r--r--drivers/ide/Makefile24
-rw-r--r--drivers/ide/arm/icside.c28
-rw-r--r--drivers/ide/arm/palm_bk3710.c16
-rw-r--r--drivers/ide/h8300/ide-h8300.c2
-rw-r--r--drivers/ide/ide-acpi.c18
-rw-r--r--drivers/ide/ide-atapi.c405
-rw-r--r--drivers/ide/ide-cd.c337
-rw-r--r--drivers/ide/ide-cd.h1
-rw-r--r--drivers/ide/ide-disk.c586
-rw-r--r--drivers/ide/ide-disk.h32
-rw-r--r--drivers/ide/ide-disk_ioctl.c29
-rw-r--r--drivers/ide/ide-disk_proc.c129
-rw-r--r--drivers/ide/ide-dma-sff.c356
-rw-r--r--drivers/ide/ide-dma.c519
-rw-r--r--drivers/ide/ide-floppy.c954
-rw-r--r--drivers/ide/ide-floppy.h62
-rw-r--r--drivers/ide/ide-floppy_ioctl.c293
-rw-r--r--drivers/ide/ide-floppy_proc.c33
-rw-r--r--drivers/ide/ide-generic.c102
-rw-r--r--drivers/ide/ide-io.c344
-rw-r--r--drivers/ide/ide-ioctls.c299
-rw-r--r--drivers/ide/ide-iops.c318
-rw-r--r--drivers/ide/ide-lib.c75
-rw-r--r--drivers/ide/ide-park.c121
-rw-r--r--drivers/ide/ide-probe.c463
-rw-r--r--drivers/ide/ide-proc.c310
-rw-r--r--drivers/ide/ide-tape.c622
-rw-r--r--drivers/ide/ide-taskfile.c250
-rw-r--r--drivers/ide/ide-timings.c22
-rw-r--r--drivers/ide/ide.c351
-rw-r--r--drivers/ide/legacy/ali14xx.c3
-rw-r--r--drivers/ide/legacy/buddha.c1
-rw-r--r--drivers/ide/legacy/dtc2278.c1
-rw-r--r--drivers/ide/legacy/falconide.c1
-rw-r--r--drivers/ide/legacy/gayle.c1
-rw-r--r--drivers/ide/legacy/ht6560b.c10
-rw-r--r--drivers/ide/legacy/ide-4drives.c2
-rw-r--r--drivers/ide/legacy/ide-cs.c159
-rw-r--r--drivers/ide/legacy/macide.c1
-rw-r--r--drivers/ide/legacy/q40ide.c2
-rw-r--r--drivers/ide/legacy/qd65xx.c25
-rw-r--r--drivers/ide/legacy/umc8672.c1
-rw-r--r--drivers/ide/mips/Makefile1
-rw-r--r--drivers/ide/mips/au1xxx-ide.c34
-rw-r--r--drivers/ide/mips/swarm.c196
-rw-r--r--drivers/ide/pci/aec62xx.c13
-rw-r--r--drivers/ide/pci/alim15x3.c24
-rw-r--r--drivers/ide/pci/amd74xx.c16
-rw-r--r--drivers/ide/pci/atiixp.c9
-rw-r--r--drivers/ide/pci/cmd640.c51
-rw-r--r--drivers/ide/pci/cmd64x.c15
-rw-r--r--drivers/ide/pci/cs5520.c7
-rw-r--r--drivers/ide/pci/cs5530.c25
-rw-r--r--drivers/ide/pci/cs5535.c22
-rw-r--r--drivers/ide/pci/cy82c693.c126
-rw-r--r--drivers/ide/pci/delkin_cb.c7
-rw-r--r--drivers/ide/pci/generic.c9
-rw-r--r--drivers/ide/pci/hpt34x.c11
-rw-r--r--drivers/ide/pci/hpt366.c121
-rw-r--r--drivers/ide/pci/it8213.c9
-rw-r--r--drivers/ide/pci/it821x.c104
-rw-r--r--drivers/ide/pci/jmicron.c9
-rw-r--r--drivers/ide/pci/ns87415.c30
-rw-r--r--drivers/ide/pci/opti621.c15
-rw-r--r--drivers/ide/pci/pdc202xx_new.c21
-rw-r--r--drivers/ide/pci/pdc202xx_old.c25
-rw-r--r--drivers/ide/pci/piix.c51
-rw-r--r--drivers/ide/pci/rz1000.c7
-rw-r--r--drivers/ide/pci/sc1200.c27
-rw-r--r--drivers/ide/pci/scc_pata.c34
-rw-r--r--drivers/ide/pci/serverworks.c17
-rw-r--r--drivers/ide/pci/sgiioc4.c60
-rw-r--r--drivers/ide/pci/siimage.c34
-rw-r--r--drivers/ide/pci/sis5513.c11
-rw-r--r--drivers/ide/pci/sl82c105.c15
-rw-r--r--drivers/ide/pci/slc90e66.c9
-rw-r--r--drivers/ide/pci/tc86c001.c8
-rw-r--r--drivers/ide/pci/triflex.c18
-rw-r--r--drivers/ide/pci/trm290.c11
-rw-r--r--drivers/ide/pci/via82cxxx.c16
-rw-r--r--drivers/ide/ppc/pmac.c77
-rw-r--r--drivers/ide/setup-pci.c33
-rw-r--r--drivers/ieee1394/csr1212.c2
-rw-r--r--drivers/ieee1394/dv1394.c10
-rw-r--r--drivers/ieee1394/eth1394.c2
-rw-r--r--drivers/ieee1394/nodemgr.c279
-rw-r--r--drivers/ieee1394/nodemgr.h2
-rw-r--r--drivers/ieee1394/raw1394-private.h1
-rw-r--r--drivers/ieee1394/raw1394.c238
-rw-r--r--drivers/ieee1394/sbp2.c218
-rw-r--r--drivers/ieee1394/sbp2.h33
-rw-r--r--drivers/ieee1394/video1394.c13
-rw-r--r--drivers/infiniband/core/cm.c8
-rw-r--r--drivers/infiniband/core/mad.c5
-rw-r--r--drivers/infiniband/core/user_mad.c12
-rw-r--r--drivers/infiniband/core/uverbs_main.c9
-rw-r--r--drivers/infiniband/hw/amso1100/c2_provider.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c9
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h14
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c225
-rw-r--r--drivers/infiniband/hw/ehca/ehca_reqs.c211
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c7
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c9
-rw-r--r--drivers/infiniband/hw/mthca/mthca_catas.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c51
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c59
-rw-r--r--drivers/infiniband/hw/nes/nes.c95
-rw-r--r--drivers/infiniband/hw/nes/nes.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c52
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c205
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h6
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c122
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c88
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c30
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c77
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c62
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c3
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c2
-rw-r--r--drivers/input/gameport/gameport.c88
-rw-r--r--drivers/input/joystick/a3d.c3
-rw-r--r--drivers/input/joystick/adi.c3
-rw-r--r--drivers/input/joystick/analog.c4
-rw-r--r--drivers/input/joystick/cobra.c3
-rw-r--r--drivers/input/joystick/gf2k.c3
-rw-r--r--drivers/input/joystick/grip.c3
-rw-r--r--drivers/input/joystick/grip_mp.c3
-rw-r--r--drivers/input/joystick/guillemot.c3
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c36
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c14
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c8
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c2
-rw-r--r--drivers/input/joystick/interact.c3
-rw-r--r--drivers/input/joystick/joydump.c3
-rw-r--r--drivers/input/joystick/sidewinder.c3
-rw-r--r--drivers/input/joystick/tmdc.c3
-rw-r--r--drivers/input/joystick/xpad.c6
-rw-r--r--drivers/input/keyboard/atkbd.c30
-rw-r--r--drivers/input/keyboard/bf54x-keys.c13
-rw-r--r--drivers/input/keyboard/corgikbd.c6
-rw-r--r--drivers/input/keyboard/gpio_keys.c42
-rw-r--r--drivers/input/keyboard/omap-keypad.c29
-rw-r--r--drivers/input/keyboard/spitzkbd.c6
-rw-r--r--drivers/input/keyboard/tosakbd.c6
-rw-r--r--drivers/input/misc/Kconfig13
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ati_remote.c20
-rw-r--r--drivers/input/misc/ati_remote2.c263
-rw-r--r--drivers/input/misc/cm109.c882
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c10
-rw-r--r--drivers/input/misc/map_to_7segment.h189
-rw-r--r--drivers/input/misc/sparcspkr.c4
-rw-r--r--drivers/input/misc/wistron_btns.c19
-rw-r--r--drivers/input/misc/yealink.c5
-rw-r--r--drivers/input/mouse/Kconfig10
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/alps.c1
-rw-r--r--drivers/input/mouse/appletouch.c299
-rw-r--r--drivers/input/mouse/bcm5974.c87
-rw-r--r--drivers/input/mouse/hgpk.c477
-rw-r--r--drivers/input/mouse/hgpk.h49
-rw-r--r--drivers/input/mouse/logips2pp.c4
-rw-r--r--drivers/input/mouse/psmouse-base.c81
-rw-r--r--drivers/input/mouse/psmouse.h14
-rw-r--r--drivers/input/mouse/trackpoint.c8
-rw-r--r--drivers/input/serio/hp_sdc.c2
-rw-r--r--drivers/input/serio/i8042-io.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h9
-rw-r--r--drivers/input/serio/serio_raw.c6
-rw-r--r--drivers/input/tablet/acecad.c3
-rw-r--r--drivers/input/tablet/aiptek.c79
-rw-r--r--drivers/input/tablet/gtco.c4
-rw-r--r--drivers/input/tablet/kbtab.c3
-rw-r--r--drivers/input/tablet/wacom_sys.c3
-rw-r--r--drivers/input/touchscreen/Kconfig1
-rw-r--r--drivers/input/touchscreen/ads7846.c162
-rw-r--r--drivers/input/touchscreen/atmel_tsadcc.c37
-rw-r--r--drivers/input/touchscreen/jornada720_ts.c4
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c5
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c382
-rw-r--r--drivers/input/touchscreen/wm9705.c5
-rw-r--r--drivers/input/touchscreen/wm9712.c5
-rw-r--r--drivers/input/touchscreen/wm9713.c5
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c5
-rw-r--r--drivers/input/xen-kbdfront.c4
-rw-r--r--drivers/isdn/capi/capi.c5
-rw-r--r--drivers/isdn/capi/kcapi.c4
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c27
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c85
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_pci.h4
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c23
-rw-r--r--drivers/isdn/hisax/avma1_cs.c81
-rw-r--r--drivers/isdn/hisax/elsa_cs.c79
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c197
-rw-r--r--drivers/isdn/hisax/teles_cs.c79
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c352
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c4
-rw-r--r--drivers/isdn/mISDN/timerdev.c24
-rw-r--r--drivers/leds/Kconfig22
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/led-class.c4
-rw-r--r--drivers/leds/leds-corgi.c124
-rw-r--r--drivers/leds/leds-fsg.c28
-rw-r--r--drivers/leds/leds-pca955x.c70
-rw-r--r--drivers/leds/leds-spitz.c131
-rw-r--r--drivers/leds/leds-sunfire.c273
-rw-r--r--drivers/macintosh/adb.c3
-rw-r--r--drivers/md/Kconfig14
-rw-r--r--drivers/md/bitmap.c45
-rw-r--r--drivers/md/dm-crypt.c109
-rw-r--r--drivers/md/dm-exception-store.c29
-rw-r--r--drivers/md/dm-ioctl.c10
-rw-r--r--drivers/md/dm-mpath.c68
-rw-r--r--drivers/md/dm-mpath.h2
-rw-r--r--drivers/md/dm-raid1.c4
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-table.c97
-rw-r--r--drivers/md/dm.c52
-rw-r--r--drivers/md/dm.h10
-rw-r--r--drivers/md/faulty.c2
-rw-r--r--drivers/md/linear.c143
-rw-r--r--drivers/md/md.c106
-rw-r--r--drivers/md/multipath.c21
-rw-r--r--drivers/md/raid0.c15
-rw-r--r--drivers/md/raid1.c14
-rw-r--r--drivers/md/raid10.c20
-rw-r--r--drivers/md/raid5.c117
-rw-r--r--drivers/md/raid6.h9
-rw-r--r--drivers/media/common/ir-keymaps.c280
-rw-r--r--drivers/media/common/saa7146_core.c2
-rw-r--r--drivers/media/common/saa7146_fops.c2
-rw-r--r--drivers/media/common/saa7146_video.c4
-rw-r--r--drivers/media/common/tuners/mt2060.c38
-rw-r--r--drivers/media/common/tuners/mt2131.c2
-rw-r--r--drivers/media/common/tuners/mt2131.h2
-rw-r--r--drivers/media/common/tuners/mt2131_priv.h2
-rw-r--r--drivers/media/common/tuners/mxl5005s.c14
-rw-r--r--drivers/media/common/tuners/mxl5005s.h2
-rw-r--r--drivers/media/common/tuners/mxl5007t.c1
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c1
-rw-r--r--drivers/media/common/tuners/tda827x.c12
-rw-r--r--drivers/media/common/tuners/tda827x.h1
-rw-r--r--drivers/media/common/tuners/tda8290.c4
-rw-r--r--drivers/media/common/tuners/tda8290.h1
-rw-r--r--drivers/media/common/tuners/tda9887.c1
-rw-r--r--drivers/media/common/tuners/tuner-simple.c38
-rw-r--r--drivers/media/common/tuners/tuner-types.c55
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c74
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.h11
-rw-r--r--drivers/media/common/tuners/xc5000.c182
-rw-r--r--drivers/media/common/tuners/xc5000.h18
-rw-r--r--drivers/media/common/tuners/xc5000_priv.h37
-rw-r--r--drivers/media/dvb/Kconfig5
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c4
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c12
-rw-r--r--drivers/media/dvb/bt8xx/dst.c4
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c2
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig85
-rw-r--r--drivers/media/dvb/cinergyT2/Makefile3
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c1105
-rw-r--r--drivers/media/dvb/dm1105/Kconfig18
-rw-r--r--drivers/media/dvb/dm1105/Makefile3
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c923
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c17
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c4
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c734
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h33
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c5
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h4
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig42
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile10
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-remote.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-script.h2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.c23
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c1474
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h524
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c30
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2-core.c268
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2-fe.c351
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2.h95
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c506
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c115
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c204
-rw-r--r--drivers/media/dvb/dvb-usb/dtv5100.c240
-rw-r--r--drivers/media/dvb/dvb-usb/dtv5100.h51
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h30
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c584
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.h1
-rw-r--r--drivers/media/dvb/frontends/Kconfig47
-rw-r--r--drivers/media/dvb/frontends/Makefile7
-rw-r--r--drivers/media/dvb/frontends/af9013.c1685
-rw-r--r--drivers/media/dvb/frontends/af9013.h107
-rw-r--r--drivers/media/dvb/frontends/af9013_priv.h869
-rw-r--r--drivers/media/dvb/frontends/au8522.c180
-rw-r--r--drivers/media/dvb/frontends/au8522.h28
-rw-r--r--drivers/media/dvb/frontends/cx22702.c508
-rw-r--r--drivers/media/dvb/frontends/cx22702.h22
-rw-r--r--drivers/media/dvb/frontends/cx24110.h15
-rw-r--r--drivers/media/dvb/frontends/cx24116.c1470
-rw-r--r--drivers/media/dvb/frontends/cx24116.h54
-rw-r--r--drivers/media/dvb/frontends/cx24123.c234
-rw-r--r--drivers/media/dvb/frontends/cx24123.h12
-rw-r--r--drivers/media/dvb/frontends/dib0070.h8
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c6
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c3
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h41
-rw-r--r--drivers/media/dvb/frontends/drx397xD.c288
-rw-r--r--drivers/media/dvb/frontends/drx397xD.h6
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c11
-rw-r--r--drivers/media/dvb/frontends/eds1547.h133
-rw-r--r--drivers/media/dvb/frontends/lgs8gl5.c454
-rw-r--r--drivers/media/dvb/frontends/lgs8gl5.h45
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c4
-rw-r--r--drivers/media/dvb/frontends/or51211.c2
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c141
-rw-r--r--drivers/media/dvb/frontends/s5h1409.h17
-rw-r--r--drivers/media/dvb/frontends/s5h1411.c11
-rw-r--r--drivers/media/dvb/frontends/s5h1411.h2
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c14
-rw-r--r--drivers/media/dvb/frontends/s5h1420.h8
-rw-r--r--drivers/media/dvb/frontends/si21xx.c974
-rw-r--r--drivers/media/dvb/frontends/si21xx.h37
-rw-r--r--drivers/media/dvb/frontends/sp887x.c3
-rw-r--r--drivers/media/dvb/frontends/stb6000.c255
-rw-r--r--drivers/media/dvb/frontends/stb6000.h51
-rw-r--r--drivers/media/dvb/frontends/stv0288.c618
-rw-r--r--drivers/media/dvb/frontends/stv0288.h67
-rw-r--r--drivers/media/dvb/frontends/stv0299.c2
-rw-r--r--drivers/media/dvb/frontends/stv0299.h13
-rw-r--r--drivers/media/dvb/frontends/tda10048.c104
-rw-r--r--drivers/media/dvb/frontends/tda10048.h2
-rw-r--r--drivers/media/dvb/frontends/tdhd1.h73
-rw-r--r--drivers/media/dvb/frontends/z0194a.h16
-rw-r--r--drivers/media/dvb/siano/sms-cards.c10
-rw-r--r--drivers/media/dvb/siano/sms-cards.h2
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c2
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h2
-rw-r--r--drivers/media/dvb/siano/smsdvb.c2
-rw-r--r--drivers/media/dvb/siano/smsusb.c2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig1
-rw-r--r--drivers/media/dvb/ttpci/av7110.c127
-rw-r--r--drivers/media/dvb/ttpci/av7110.h1
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c3
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c8
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c7
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c6
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c12
-rw-r--r--drivers/media/dvb/ttpci/budget.c28
-rw-r--r--drivers/media/dvb/ttpci/budget.h2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c16
-rw-r--r--drivers/media/radio/Kconfig14
-rw-r--r--drivers/media/radio/Makefile5
-rw-r--r--drivers/media/radio/dsbr100.c43
-rw-r--r--drivers/media/radio/miropcm20-radio.c266
-rw-r--r--drivers/media/radio/miropcm20-rds-core.c211
-rw-r--r--drivers/media/radio/miropcm20-rds-core.h19
-rw-r--r--drivers/media/radio/miropcm20-rds.c136
-rw-r--r--drivers/media/radio/radio-aimslab.c37
-rw-r--r--drivers/media/radio/radio-aztech.c43
-rw-r--r--drivers/media/radio/radio-cadet.c3
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c44
-rw-r--r--drivers/media/radio/radio-gemtek.c40
-rw-r--r--drivers/media/radio/radio-maestro.c37
-rw-r--r--drivers/media/radio/radio-maxiradio.c68
-rw-r--r--drivers/media/radio/radio-mr800.c628
-rw-r--r--drivers/media/radio/radio-rtrack2.c37
-rw-r--r--drivers/media/radio/radio-sf16fmi.c36
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c34
-rw-r--r--drivers/media/radio/radio-si470x.c262
-rw-r--r--drivers/media/radio/radio-terratec.c37
-rw-r--r--drivers/media/radio/radio-trust.c20
-rw-r--r--drivers/media/radio/radio-typhoon.c35
-rw-r--r--drivers/media/radio/radio-zoltrix.c54
-rw-r--r--drivers/media/video/Kconfig235
-rw-r--r--drivers/media/video/Makefile13
-rw-r--r--drivers/media/video/adv7170.c251
-rw-r--r--drivers/media/video/adv7175.c243
-rw-r--r--drivers/media/video/arv.c29
-rw-r--r--drivers/media/video/au0828/Kconfig1
-rw-r--r--drivers/media/video/au0828/au0828-cards.c16
-rw-r--r--drivers/media/video/au0828/au0828-cards.h3
-rw-r--r--drivers/media/video/au0828/au0828-core.c7
-rw-r--r--drivers/media/video/au0828/au0828-dvb.c75
-rw-r--r--drivers/media/video/au0828/au0828-i2c.c2
-rw-r--r--drivers/media/video/au0828/au0828-reg.h2
-rw-r--r--drivers/media/video/au0828/au0828.h5
-rw-r--r--drivers/media/video/bt819.c321
-rw-r--r--drivers/media/video/bt856.c224
-rw-r--r--drivers/media/video/bt866.c255
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c100
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c69
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c62
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c3
-rw-r--r--drivers/media/video/bt8xx/bttv.h2
-rw-r--r--drivers/media/video/bt8xx/bttvp.h5
-rw-r--r--drivers/media/video/btcx-risc.c6
-rw-r--r--drivers/media/video/btcx-risc.h2
-rw-r--r--drivers/media/video/bw-qcam.c29
-rw-r--r--drivers/media/video/bw-qcam.h1
-rw-r--r--drivers/media/video/c-qcam.c26
-rw-r--r--drivers/media/video/cafe_ccic.c20
-rw-r--r--drivers/media/video/cpia.c21
-rw-r--r--drivers/media/video/cpia2/cpia2_core.c10
-rw-r--r--drivers/media/video/cpia2/cpia2_usb.c7
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c20
-rw-r--r--drivers/media/video/cx18/Makefile2
-rw-r--r--drivers/media/video/cx18/cx18-audio.c5
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c23
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h2
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c35
-rw-r--r--drivers/media/video/cx18/cx18-cards.c101
-rw-r--r--drivers/media/video/cx18/cx18-driver.c57
-rw-r--r--drivers/media/video/cx18/cx18-driver.h71
-rw-r--r--drivers/media/video/cx18/cx18-dvb.c7
-rw-r--r--drivers/media/video/cx18/cx18-dvb.h2
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c47
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c140
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c17
-rw-r--r--drivers/media/video/cx18/cx18-gpio.h2
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c49
-rw-r--r--drivers/media/video/cx18/cx18-io.c254
-rw-r--r--drivers/media/video/cx18/cx18-io.h378
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c34
-rw-r--r--drivers/media/video/cx18/cx18-irq.c47
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c45
-rw-r--r--drivers/media/video/cx18/cx18-queue.c135
-rw-r--r--drivers/media/video/cx18/cx18-queue.h2
-rw-r--r--drivers/media/video/cx18/cx18-scb.c131
-rw-r--r--drivers/media/video/cx18/cx18-streams.c70
-rw-r--r--drivers/media/video/cx18/cx18-version.h2
-rw-r--r--drivers/media/video/cx18/cx23418.h2
-rw-r--r--drivers/media/video/cx2341x.c5
-rw-r--r--drivers/media/video/cx23885/Kconfig1
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c15
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c238
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c282
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c281
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c49
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-vbi.c14
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c64
-rw-r--r--drivers/media/video/cx23885/cx23885.h30
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c2
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c5
-rw-r--r--drivers/media/video/cx88/Kconfig4
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c9
-rw-r--r--drivers/media/video/cx88/cx88-cards.c358
-rw-r--r--drivers/media/video/cx88/cx88-core.c3
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c547
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c33
-rw-r--r--drivers/media/video/cx88/cx88-input.c33
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c22
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c11
-rw-r--r--drivers/media/video/cx88/cx88-video.c67
-rw-r--r--drivers/media/video/cx88/cx88.h18
-rw-r--r--drivers/media/video/dabusb.c8
-rw-r--r--drivers/media/video/dpc7146.c408
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c12
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c59
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c16
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c35
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c60
-rw-r--r--drivers/media/video/em28xx/em28xx.h6
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c15
-rw-r--r--drivers/media/video/gspca/Kconfig215
-rw-r--r--drivers/media/video/gspca/Makefile75
-rw-r--r--drivers/media/video/gspca/conex.c31
-rw-r--r--drivers/media/video/gspca/etoms.c33
-rw-r--r--drivers/media/video/gspca/finepix.c466
-rw-r--r--drivers/media/video/gspca/gspca.c364
-rw-r--r--drivers/media/video/gspca/gspca.h43
-rw-r--r--drivers/media/video/gspca/m5602/Kconfig11
-rw-r--r--drivers/media/video/gspca/m5602/Makefile11
-rw-r--r--drivers/media/video/gspca/m5602/m5602_bridge.h143
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c309
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c345
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.h1019
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c546
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h502
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c400
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.h508
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c463
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.h369
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c423
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.h482
-rw-r--r--drivers/media/video/gspca/m5602/m5602_sensor.h76
-rw-r--r--drivers/media/video/gspca/mars.c61
-rw-r--r--drivers/media/video/gspca/ov519.c1172
-rw-r--r--drivers/media/video/gspca/pac207.c91
-rw-r--r--drivers/media/video/gspca/pac7311.c1114
-rw-r--r--drivers/media/video/gspca/pac_common.h60
-rw-r--r--drivers/media/video/gspca/sonixb.c597
-rw-r--r--drivers/media/video/gspca/sonixj.c611
-rw-r--r--drivers/media/video/gspca/spca500.c23
-rw-r--r--drivers/media/video/gspca/spca501.c19
-rw-r--r--drivers/media/video/gspca/spca505.c19
-rw-r--r--drivers/media/video/gspca/spca506.c23
-rw-r--r--drivers/media/video/gspca/spca508.c24
-rw-r--r--drivers/media/video/gspca/spca561.c733
-rw-r--r--drivers/media/video/gspca/stk014.c25
-rw-r--r--drivers/media/video/gspca/sunplus.c170
-rw-r--r--drivers/media/video/gspca/t613.c829
-rw-r--r--drivers/media/video/gspca/tv8532.c23
-rw-r--r--drivers/media/video/gspca/vc032x.c37
-rw-r--r--drivers/media/video/gspca/zc3xx.c92
-rw-r--r--drivers/media/video/ir-kbd-i2c.c64
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c14
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h10
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c23
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c72
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c38
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c44
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-version.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c1
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c78
-rw-r--r--drivers/media/video/ks0127.c497
-rw-r--r--drivers/media/video/meye.c15
-rw-r--r--drivers/media/video/meye.h1
-rw-r--r--drivers/media/video/mt9m001.c55
-rw-r--r--drivers/media/video/mt9m111.c973
-rw-r--r--drivers/media/video/mt9v022.c52
-rw-r--r--drivers/media/video/mxb.c477
-rw-r--r--drivers/media/video/ov511.c144
-rw-r--r--drivers/media/video/ov511.h3
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c6
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_priv.h6
-rw-r--r--drivers/media/video/pms.c36
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.h2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h9
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c340
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h13
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c7
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c46
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c42
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c23
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c94
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c19
-rw-r--r--drivers/media/video/pwc/pwc-if.c12
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c2
-rw-r--r--drivers/media/video/pxa_camera.c60
-rw-r--r--drivers/media/video/s2255drv.c575
-rw-r--r--drivers/media/video/saa5246a.c556
-rw-r--r--drivers/media/video/saa5246a.h359
-rw-r--r--drivers/media/video/saa5249.c704
-rw-r--r--drivers/media/video/saa7110.c242
-rw-r--r--drivers/media/video/saa7111.c224
-rw-r--r--drivers/media/video/saa7114.c364
-rw-r--r--drivers/media/video/saa7115.c47
-rw-r--r--drivers/media/video/saa7127.c2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c440
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c13
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c261
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c62
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c258
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c63
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c210
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c56
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c63
-rw-r--r--drivers/media/video/saa7134/saa7134.h21
-rw-r--r--drivers/media/video/saa7185.c210
-rw-r--r--drivers/media/video/se401.c46
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c101
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c35
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h41
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131r.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0360.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mt9v111.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110d.c1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c1
-rw-r--r--drivers/media/video/soc_camera_platform.c20
-rw-r--r--drivers/media/video/stk-webcam.c113
-rw-r--r--drivers/media/video/stk-webcam.h3
-rw-r--r--drivers/media/video/stradis.c7
-rw-r--r--drivers/media/video/stv680.c10
-rw-r--r--drivers/media/video/tda9840.c260
-rw-r--r--drivers/media/video/tda9840.h21
-rw-r--r--drivers/media/video/tea6415c.c131
-rw-r--r--drivers/media/video/tea6420.c147
-rw-r--r--drivers/media/video/tuner-3036.c214
-rw-r--r--drivers/media/video/tuner-core.c13
-rw-r--r--drivers/media/video/tvaudio.c2
-rw-r--r--drivers/media/video/tveeprom.c2
-rw-r--r--drivers/media/video/usbvideo/ibmcam.c84
-rw-r--r--drivers/media/video/usbvideo/konicawc.c25
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c17
-rw-r--r--drivers/media/video/usbvideo/ultracam.c29
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c166
-rw-r--r--drivers/media/video/usbvideo/vicam.c19
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c7
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c3
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c131
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c187
-rw-r--r--drivers/media/video/uvc/uvc_driver.c51
-rw-r--r--drivers/media/video/uvc/uvc_status.c11
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c17
-rw-r--r--drivers/media/video/uvc/uvc_video.c12
-rw-r--r--drivers/media/video/uvc/uvcvideo.h4
-rw-r--r--drivers/media/video/v4l1-compat.c4
-rw-r--r--drivers/media/video/v4l2-common.c187
-rw-r--r--drivers/media/video/v4l2-dev.c305
-rw-r--r--drivers/media/video/v4l2-ioctl.c16
-rw-r--r--drivers/media/video/videobuf-dvb.c201
-rw-r--r--drivers/media/video/vino.c30
-rw-r--r--drivers/media/video/vivi.c337
-rw-r--r--drivers/media/video/vpx3220.c330
-rw-r--r--drivers/media/video/w9966.c31
-rw-r--r--drivers/media/video/w9968cf.c6
-rw-r--r--drivers/media/video/wm8739.c4
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c15
-rw-r--r--drivers/media/video/zc0301/zc0301_sensor.h19
-rw-r--r--drivers/media/video/zoran/Kconfig73
-rw-r--r--drivers/media/video/zoran/Makefile6
-rw-r--r--drivers/media/video/zoran/videocodec.c (renamed from drivers/media/video/videocodec.c)0
-rw-r--r--drivers/media/video/zoran/videocodec.h (renamed from drivers/media/video/videocodec.h)0
-rw-r--r--drivers/media/video/zoran/zoran.h (renamed from drivers/media/video/zoran.h)0
-rw-r--r--drivers/media/video/zoran/zoran_card.c (renamed from drivers/media/video/zoran_card.c)3
-rw-r--r--drivers/media/video/zoran/zoran_card.h (renamed from drivers/media/video/zoran_card.h)0
-rw-r--r--drivers/media/video/zoran/zoran_device.c (renamed from drivers/media/video/zoran_device.c)6
-rw-r--r--drivers/media/video/zoran/zoran_device.h (renamed from drivers/media/video/zoran_device.h)8
-rw-r--r--drivers/media/video/zoran/zoran_driver.c (renamed from drivers/media/video/zoran_driver.c)29
-rw-r--r--drivers/media/video/zoran/zoran_procfs.c (renamed from drivers/media/video/zoran_procfs.c)0
-rw-r--r--drivers/media/video/zoran/zoran_procfs.h (renamed from drivers/media/video/zoran_procfs.h)0
-rw-r--r--drivers/media/video/zoran/zr36016.c (renamed from drivers/media/video/zr36016.c)0
-rw-r--r--drivers/media/video/zoran/zr36016.h (renamed from drivers/media/video/zr36016.h)0
-rw-r--r--drivers/media/video/zoran/zr36050.c (renamed from drivers/media/video/zr36050.c)0
-rw-r--r--drivers/media/video/zoran/zr36050.h (renamed from drivers/media/video/zr36050.h)0
-rw-r--r--drivers/media/video/zoran/zr36057.h (renamed from drivers/media/video/zr36057.h)0
-rw-r--r--drivers/media/video/zoran/zr36060.c (renamed from drivers/media/video/zr36060.c)0
-rw-r--r--drivers/media/video/zoran/zr36060.h (renamed from drivers/media/video/zr36060.h)0
-rw-r--r--drivers/media/video/zr364xx.c87
-rw-r--r--drivers/memstick/core/memstick.c10
-rw-r--r--drivers/memstick/core/mspro_block.c35
-rw-r--r--drivers/memstick/host/jmb38x_ms.c39
-rw-r--r--drivers/message/i2o/Makefile2
-rw-r--r--drivers/message/i2o/device.c2
-rw-r--r--drivers/message/i2o/exec-osm.c4
-rw-r--r--drivers/message/i2o/i2o_config.c31
-rw-r--r--drivers/message/i2o/iop.c2
-rw-r--r--drivers/message/i2o/memory.c313
-rw-r--r--drivers/message/i2o/pci.c16
-rw-r--r--drivers/mfd/Kconfig51
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/asic3.c2
-rw-r--r--drivers/mfd/ucb1400_core.c106
-rw-r--r--drivers/mfd/wm8350-core.c1273
-rw-r--r--drivers/mfd/wm8350-gpio.c222
-rw-r--r--drivers/mfd/wm8350-i2c.c120
-rw-r--r--drivers/mfd/wm8350-regmap.c1347
-rw-r--r--drivers/mfd/wm8400-core.c455
-rw-r--r--drivers/misc/Kconfig3
-rw-r--r--drivers/misc/acer-wmi.c3
-rw-r--r--drivers/misc/eeepc-laptop.c16
-rw-r--r--drivers/misc/fujitsu-laptop.c7
-rw-r--r--drivers/misc/hp-wmi.c93
-rw-r--r--drivers/misc/phantom.c6
-rw-r--r--drivers/misc/sgi-gru/gru.h4
-rw-r--r--drivers/misc/sgi-gru/gru_instructions.h10
-rw-r--r--drivers/misc/sgi-gru/grufault.c11
-rw-r--r--drivers/misc/sgi-gru/grufile.c11
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h5
-rw-r--r--drivers/misc/sgi-gru/grukservices.c3
-rw-r--r--drivers/misc/sgi-gru/grumain.c29
-rw-r--r--drivers/misc/thinkpad_acpi.c1
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/card/Kconfig3
-rw-r--r--drivers/mmc/card/block.c71
-rw-r--r--drivers/mmc/card/mmc_test.c4
-rw-r--r--drivers/mmc/card/queue.c23
-rw-r--r--drivers/mmc/core/mmc_ops.c8
-rw-r--r--drivers/mmc/core/sdio.c52
-rw-r--r--drivers/mmc/core/sdio_irq.c16
-rw-r--r--drivers/mmc/host/Kconfig30
-rw-r--r--drivers/mmc/host/at91_mci.c20
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h6
-rw-r--r--drivers/mmc/host/atmel-mci.c1364
-rw-r--r--drivers/mmc/host/mmc_spi.c32
-rw-r--r--drivers/mmc/host/omap.c11
-rw-r--r--drivers/mmc/host/pxamci.c4
-rw-r--r--drivers/mmc/host/sdhci-pci.c5
-rw-r--r--drivers/mmc/host/sdhci.c46
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/mmc/host/tmio_mmc.h4
-rw-r--r--drivers/mtd/ftl.c24
-rw-r--r--drivers/mtd/maps/pcmciamtd.c34
-rw-r--r--drivers/mtd/maps/sun_uflash.c75
-rw-r--r--drivers/mtd/mtd_blkdevs.c16
-rw-r--r--drivers/mtd/mtdchar.c26
-rw-r--r--drivers/mtd/mtdpart.c2
-rw-r--r--drivers/mtd/nand/alauda.c4
-rw-r--r--drivers/mtd/nand/ams-delta.c4
-rw-r--r--drivers/mtd/nand/atmel_nand_ecc.h3
-rw-r--r--drivers/mtd/nand/cafe_nand.c6
-rw-r--r--drivers/mtd/nand/cmx270_nand.c2
-rw-r--r--drivers/mtd/nand/tmio_nand.c8
-rw-r--r--drivers/net/3c501.c12
-rw-r--r--drivers/net/3c505.c4
-rw-r--r--drivers/net/3c509.c2
-rw-r--r--drivers/net/3c515.c2
-rw-r--r--drivers/net/8139cp.c14
-rw-r--r--drivers/net/8139too.c14
-rw-r--r--drivers/net/Kconfig78
-rw-r--r--drivers/net/Makefile6
-rw-r--r--drivers/net/appletalk/cops.c2
-rw-r--r--drivers/net/arcnet/arcnet.c18
-rw-r--r--drivers/net/arcnet/com20020.c16
-rw-r--r--drivers/net/atl1e/atl1e_hw.c6
-rw-r--r--drivers/net/atl1e/atl1e_main.c2
-rw-r--r--drivers/net/atlx/Makefile2
-rw-r--r--drivers/net/atlx/atl1.c32
-rw-r--r--drivers/net/atlx/atl2.c3119
-rw-r--r--drivers/net/atlx/atl2.h529
-rw-r--r--drivers/net/atlx/atlx.c1
-rw-r--r--drivers/net/au1000_eth.c67
-rw-r--r--drivers/net/au1000_eth.h2
-rw-r--r--drivers/net/ax88796.c14
-rw-r--r--drivers/net/bfin_mac.c59
-rw-r--r--drivers/net/bfin_mac.h2
-rw-r--r--drivers/net/bnx2.c229
-rw-r--r--drivers/net/bnx2.h15
-rw-r--r--drivers/net/bnx2_fw.h8654
-rw-r--r--drivers/net/bnx2x.h5
-rw-r--r--drivers/net/bnx2x_main.c125
-rw-r--r--drivers/net/bonding/bond_alb.c28
-rw-r--r--drivers/net/bonding/bond_main.c12
-rw-r--r--drivers/net/bonding/bonding.h10
-rw-r--r--drivers/net/cassini.c56
-rw-r--r--drivers/net/cassini.h1522
-rw-r--r--drivers/net/cpmac.c51
-rw-r--r--drivers/net/cs89x0.c27
-rw-r--r--drivers/net/cxgb3/adapter.h9
-rw-r--r--drivers/net/cxgb3/ael1002.c1074
-rw-r--r--drivers/net/cxgb3/common.h87
-rw-r--r--drivers/net/cxgb3/cxgb3_ctl_defs.h2
-rw-r--r--drivers/net/cxgb3/cxgb3_defs.h2
-rw-r--r--drivers/net/cxgb3/cxgb3_ioctl.h4
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c390
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c10
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.h2
-rw-r--r--drivers/net/cxgb3/firmware_exports.h2
-rw-r--r--drivers/net/cxgb3/l2t.c41
-rw-r--r--drivers/net/cxgb3/l2t.h5
-rw-r--r--drivers/net/cxgb3/mc5.c2
-rw-r--r--drivers/net/cxgb3/regs.h4
-rw-r--r--drivers/net/cxgb3/sge.c112
-rw-r--r--drivers/net/cxgb3/t3_cpl.h2
-rw-r--r--drivers/net/cxgb3/t3_hw.c243
-rw-r--r--drivers/net/cxgb3/t3cdev.h2
-rw-r--r--drivers/net/cxgb3/version.h4
-rw-r--r--drivers/net/cxgb3/vsc8211.c208
-rw-r--r--drivers/net/cxgb3/xgmac.c2
-rw-r--r--drivers/net/e100.c6
-rw-r--r--drivers/net/e1000/e1000.h17
-rw-r--r--drivers/net/e1000/e1000_hw.c23
-rw-r--r--drivers/net/e1000/e1000_main.c476
-rw-r--r--drivers/net/e1000e/82571.c153
-rw-r--r--drivers/net/e1000e/defines.h15
-rw-r--r--drivers/net/e1000e/e1000.h36
-rw-r--r--drivers/net/e1000e/es2lan.c2
-rw-r--r--drivers/net/e1000e/ethtool.c69
-rw-r--r--drivers/net/e1000e/hw.h15
-rw-r--r--drivers/net/e1000e/ich8lan.c253
-rw-r--r--drivers/net/e1000e/lib.c8
-rw-r--r--drivers/net/e1000e/netdev.c571
-rw-r--r--drivers/net/e1000e/param.c57
-rw-r--r--drivers/net/e1000e/phy.c194
-rw-r--r--drivers/net/eexpress.c2
-rw-r--r--drivers/net/ehea/ehea.h4
-rw-r--r--drivers/net/ehea/ehea_phyp.c2
-rw-r--r--drivers/net/ehea/ehea_qmr.c3
-rw-r--r--drivers/net/enc28j60.c56
-rw-r--r--drivers/net/enic/Makefile5
-rw-r--r--drivers/net/enic/cq_desc.h79
-rw-r--r--drivers/net/enic/cq_enet_desc.h169
-rw-r--r--drivers/net/enic/enic.h114
-rw-r--r--drivers/net/enic/enic_main.c1935
-rw-r--r--drivers/net/enic/enic_res.c370
-rw-r--r--drivers/net/enic/enic_res.h151
-rw-r--r--drivers/net/enic/rq_enet_desc.h60
-rw-r--r--drivers/net/enic/vnic_cq.c89
-rw-r--r--drivers/net/enic/vnic_cq.h113
-rw-r--r--drivers/net/enic/vnic_dev.c674
-rw-r--r--drivers/net/enic/vnic_dev.h120
-rw-r--r--drivers/net/enic/vnic_devcmd.h282
-rw-r--r--drivers/net/enic/vnic_enet.h47
-rw-r--r--drivers/net/enic/vnic_intr.c62
-rw-r--r--drivers/net/enic/vnic_intr.h92
-rw-r--r--drivers/net/enic/vnic_nic.h65
-rw-r--r--drivers/net/enic/vnic_resource.h63
-rw-r--r--drivers/net/enic/vnic_rq.c199
-rw-r--r--drivers/net/enic/vnic_rq.h204
-rw-r--r--drivers/net/enic/vnic_rss.h32
-rw-r--r--drivers/net/enic/vnic_stats.h70
-rw-r--r--drivers/net/enic/vnic_wq.c184
-rw-r--r--drivers/net/enic/vnic_wq.h154
-rw-r--r--drivers/net/enic/wq_enet_desc.h98
-rw-r--r--drivers/net/fealnx.c6
-rw-r--r--drivers/net/fec_mpc52xx_phy.c8
-rw-r--r--drivers/net/forcedeth.c26
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c22
-rw-r--r--drivers/net/fs_enet/fs_enet.h2
-rw-r--r--drivers/net/fs_enet/mac-fcc.c12
-rw-r--r--drivers/net/fs_enet/mac-fec.c30
-rw-r--r--drivers/net/fs_enet/mac-scc.c26
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c9
-rw-r--r--drivers/net/fs_enet/mii-fec.c8
-rw-r--r--drivers/net/gianfar.c3
-rw-r--r--drivers/net/gianfar_mii.c27
-rw-r--r--drivers/net/hp-plus.c8
-rw-r--r--drivers/net/ibm_newemac/Kconfig14
-rw-r--r--drivers/net/ibm_newemac/core.c60
-rw-r--r--drivers/net/ibm_newemac/core.h11
-rw-r--r--drivers/net/ibm_newemac/mal.c60
-rw-r--r--drivers/net/ibm_newemac/mal.h38
-rw-r--r--drivers/net/ibm_newemac/phy.c86
-rw-r--r--drivers/net/ibm_newemac/phy.h2
-rw-r--r--drivers/net/ibmlana.c2
-rw-r--r--drivers/net/igb/igb_main.c12
-rw-r--r--drivers/net/irda/kingsun-sir.c3
-rw-r--r--drivers/net/irda/ks959-sir.c3
-rw-r--r--drivers/net/irda/ksdazzle-sir.c3
-rw-r--r--drivers/net/irda/pxaficp_ir.c8
-rw-r--r--drivers/net/irda/sir_dongle.c2
-rw-r--r--drivers/net/irda/stir4200.c18
-rw-r--r--drivers/net/irda/vlsi_ir.c2
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_main.c8
-rw-r--r--drivers/net/ixgbe/ixgbe.h103
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c628
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c1060
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h58
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c302
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c1934
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c244
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.h63
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h563
-rw-r--r--drivers/net/jme.c3038
-rw-r--r--drivers/net/jme.h1229
-rw-r--r--drivers/net/lib8390.c4
-rw-r--r--drivers/net/macb.c49
-rw-r--r--drivers/net/macb.h2
-rw-r--r--drivers/net/macmace.c2
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/mipsnet.c2
-rw-r--r--drivers/net/mlx4/alloc.c1
-rw-r--r--drivers/net/mlx4/mr.c10
-rw-r--r--drivers/net/mv643xx_eth.c1471
-rw-r--r--drivers/net/myri10ge/myri10ge.c185
-rw-r--r--drivers/net/myri_sbus.c198
-rw-r--r--drivers/net/myri_sbus.h2
-rw-r--r--drivers/net/natsemi.c8
-rw-r--r--drivers/net/ne.c281
-rw-r--r--drivers/net/netx-eth.c2
-rw-r--r--drivers/net/netxen/netxen_nic.h2
-rw-r--r--drivers/net/netxen/netxen_nic_main.c30
-rw-r--r--drivers/net/niu.c58
-rw-r--r--drivers/net/pci-skeleton.c4
-rw-r--r--drivers/net/pcmcia/3c574_cs.c7
-rw-r--r--drivers/net/pcmcia/3c589_cs.c9
-rw-r--r--drivers/net/pcmcia/Kconfig2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c81
-rw-r--r--drivers/net/pcmcia/com20020_cs.c8
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c21
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c2
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c4
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c88
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c151
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c85
-rw-r--r--drivers/net/phy/fixed.c33
-rw-r--r--drivers/net/phy/mdio-bitbang.c4
-rw-r--r--drivers/net/phy/mdio-ofgpio.c11
-rw-r--r--drivers/net/phy/mdio_bus.c232
-rw-r--r--drivers/net/phy/phy.c60
-rw-r--r--drivers/net/phy/phy_device.c58
-rw-r--r--drivers/net/ppp_generic.c27
-rw-r--r--drivers/net/pppol2tp.c2
-rw-r--r--drivers/net/pppox.c9
-rw-r--r--drivers/net/qlge/Makefile7
-rw-r--r--drivers/net/qlge/qlge.h1593
-rw-r--r--drivers/net/qlge/qlge_dbg.c858
-rw-r--r--drivers/net/qlge/qlge_ethtool.c414
-rw-r--r--drivers/net/qlge/qlge_main.c3956
-rw-r--r--drivers/net/qlge/qlge_mpi.c150
-rw-r--r--drivers/net/r6040.c6
-rw-r--r--drivers/net/r8169.c966
-rw-r--r--drivers/net/s2io.c62
-rw-r--r--drivers/net/s2io.h1
-rw-r--r--drivers/net/sb1250-mac.c48
-rw-r--r--drivers/net/sfc/bitfield.h178
-rw-r--r--drivers/net/sfc/boards.c12
-rw-r--r--drivers/net/sfc/boards.h2
-rw-r--r--drivers/net/sfc/efx.c489
-rw-r--r--drivers/net/sfc/efx.h14
-rw-r--r--drivers/net/sfc/enum.h9
-rw-r--r--drivers/net/sfc/ethtool.c184
-rw-r--r--drivers/net/sfc/falcon.c1019
-rw-r--r--drivers/net/sfc/falcon.h17
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h80
-rw-r--r--drivers/net/sfc/falcon_io.h1
-rw-r--r--drivers/net/sfc/falcon_xmac.c346
-rw-r--r--drivers/net/sfc/mac.h4
-rw-r--r--drivers/net/sfc/mdio_10g.c16
-rw-r--r--drivers/net/sfc/mdio_10g.h13
-rw-r--r--drivers/net/sfc/net_driver.h144
-rw-r--r--drivers/net/sfc/phy.h10
-rw-r--r--drivers/net/sfc/rx.c78
-rw-r--r--drivers/net/sfc/rx.h4
-rw-r--r--drivers/net/sfc/selftest.c391
-rw-r--r--drivers/net/sfc/selftest.h13
-rw-r--r--drivers/net/sfc/sfe4001.c248
-rw-r--r--drivers/net/sfc/spi.h89
-rw-r--r--drivers/net/sfc/tenxpress.c149
-rw-r--r--drivers/net/sfc/tx.c385
-rw-r--r--drivers/net/sfc/tx.h2
-rw-r--r--drivers/net/sfc/workarounds.h4
-rw-r--r--drivers/net/sfc/xfp_phy.c12
-rw-r--r--drivers/net/sh_eth.c4
-rw-r--r--drivers/net/skfp/pmf.c29
-rw-r--r--drivers/net/skge.c26
-rw-r--r--drivers/net/sky2.c181
-rw-r--r--drivers/net/smc911x.c77
-rw-r--r--drivers/net/smc911x.h14
-rw-r--r--drivers/net/smc91x.c52
-rw-r--r--drivers/net/smc91x.h15
-rw-r--r--drivers/net/sunbmac.c206
-rw-r--r--drivers/net/sunbmac.h4
-rw-r--r--drivers/net/sundance.c95
-rw-r--r--drivers/net/sunhme.c322
-rw-r--r--drivers/net/sunhme.h7
-rw-r--r--drivers/net/sunlance.c180
-rw-r--r--drivers/net/sunqe.c162
-rw-r--r--drivers/net/sunqe.h4
-rw-r--r--drivers/net/sunvnet.c4
-rw-r--r--drivers/net/tc35815.c45
-rw-r--r--drivers/net/tehuti.h8
-rw-r--r--drivers/net/tg3.c157
-rw-r--r--drivers/net/tg3.h3
-rw-r--r--drivers/net/tlan.c3
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tsi108_eth.c6
-rw-r--r--drivers/net/tulip/de2104x.c2
-rw-r--r--drivers/net/tulip/de4x5.c38
-rw-r--r--drivers/net/tulip/dmfe.c4
-rw-r--r--drivers/net/ucc_geth.c116
-rw-r--r--drivers/net/ucc_geth_mii.c9
-rw-r--r--drivers/net/usb/Kconfig8
-rw-r--r--drivers/net/usb/Makefile4
-rw-r--r--drivers/net/usb/catc.c8
-rw-r--r--drivers/net/usb/hso.c335
-rw-r--r--drivers/net/usb/kaweth.c27
-rw-r--r--drivers/net/usb/mcs7830.c2
-rw-r--r--drivers/net/usb/pegasus.c31
-rw-r--r--drivers/net/usb/rtl8150.c31
-rw-r--r--drivers/net/usb/smsc95xx.c1225
-rw-r--r--drivers/net/usb/smsc95xx.h253
-rw-r--r--drivers/net/usb/usbnet.c3
-rw-r--r--drivers/net/via-rhine.c8
-rw-r--r--drivers/net/via-velocity.c6
-rw-r--r--drivers/net/via-velocity.h2
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/net/wan/cosa.c4
-rw-r--r--drivers/net/wan/cycx_drv.c6
-rw-r--r--drivers/net/wan/cycx_x25.c12
-rw-r--r--drivers/net/wan/dscc4.c2
-rw-r--r--drivers/net/wan/hdlc_x25.c8
-rw-r--r--drivers/net/wan/lmc/lmc_main.c31
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wan/z85230.c3
-rw-r--r--drivers/net/wan/z85230.h2
-rw-r--r--drivers/net/wireless/Kconfig17
-rw-r--r--drivers/net/wireless/Makefile4
-rw-r--r--drivers/net/wireless/adm8211.c23
-rw-r--r--drivers/net/wireless/airo.c18
-rw-r--r--drivers/net/wireless/airo_cs.c224
-rw-r--r--drivers/net/wireless/airport.c3
-rw-r--r--drivers/net/wireless/ath5k/Makefile12
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h619
-rw-r--r--drivers/net/wireless/ath5k/attach.c359
-rw-r--r--drivers/net/wireless/ath5k/base.c574
-rw-r--r--drivers/net/wireless/ath5k/base.h10
-rw-r--r--drivers/net/wireless/ath5k/caps.c193
-rw-r--r--drivers/net/wireless/ath5k/debug.c4
-rw-r--r--drivers/net/wireless/ath5k/desc.c692
-rw-r--r--drivers/net/wireless/ath5k/desc.h (renamed from drivers/net/wireless/ath5k/hw.h)400
-rw-r--r--drivers/net/wireless/ath5k/dma.c605
-rw-r--r--drivers/net/wireless/ath5k/eeprom.c466
-rw-r--r--drivers/net/wireless/ath5k/eeprom.h215
-rw-r--r--drivers/net/wireless/ath5k/gpio.c176
-rw-r--r--drivers/net/wireless/ath5k/hw.c4529
-rw-r--r--drivers/net/wireless/ath5k/initvals.c22
-rw-r--r--drivers/net/wireless/ath5k/pcu.c1014
-rw-r--r--drivers/net/wireless/ath5k/phy.c12
-rw-r--r--drivers/net/wireless/ath5k/qcu.c488
-rw-r--r--drivers/net/wireless/ath5k/reg.h679
-rw-r--r--drivers/net/wireless/ath5k/reset.c931
-rw-r--r--drivers/net/wireless/ath9k/Kconfig3
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h64
-rw-r--r--drivers/net/wireless/ath9k/beacon.c394
-rw-r--r--drivers/net/wireless/ath9k/core.c423
-rw-r--r--drivers/net/wireless/ath9k/core.h296
-rw-r--r--drivers/net/wireless/ath9k/hw.c320
-rw-r--r--drivers/net/wireless/ath9k/hw.h120
-rw-r--r--drivers/net/wireless/ath9k/main.c1291
-rw-r--r--drivers/net/wireless/ath9k/phy.h12
-rw-r--r--drivers/net/wireless/ath9k/rc.c280
-rw-r--r--drivers/net/wireless/ath9k/rc.h222
-rw-r--r--drivers/net/wireless/ath9k/recv.c103
-rw-r--r--drivers/net/wireless/ath9k/reg.h6
-rw-r--r--drivers/net/wireless/ath9k/xmit.c422
-rw-r--r--drivers/net/wireless/atmel.c2
-rw-r--r--drivers/net/wireless/atmel_cs.c121
-rw-r--r--drivers/net/wireless/b43/Kconfig12
-rw-r--r--drivers/net/wireless/b43/Makefile7
-rw-r--r--drivers/net/wireless/b43/b43.h146
-rw-r--r--drivers/net/wireless/b43/debugfs.c79
-rw-r--r--drivers/net/wireless/b43/lo.c120
-rw-r--r--drivers/net/wireless/b43/lo.h4
-rw-r--r--drivers/net/wireless/b43/main.c404
-rw-r--r--drivers/net/wireless/b43/pcmcia.c16
-rw-r--r--drivers/net/wireless/b43/phy.h340
-rw-r--r--drivers/net/wireless/b43/phy_a.c643
-rw-r--r--drivers/net/wireless/b43/phy_a.h130
-rw-r--r--drivers/net/wireless/b43/phy_common.c381
-rw-r--r--drivers/net/wireless/b43/phy_common.h413
-rw-r--r--drivers/net/wireless/b43/phy_g.c (renamed from drivers/net/wireless/b43/phy.c)4420
-rw-r--r--drivers/net/wireless/b43/phy_g.h209
-rw-r--r--drivers/net/wireless/b43/phy_lp.c155
-rw-r--r--drivers/net/wireless/b43/phy_lp.h540
-rw-r--r--drivers/net/wireless/b43/phy_n.c (renamed from drivers/net/wireless/b43/nphy.c)154
-rw-r--r--drivers/net/wireless/b43/phy_n.h (renamed from drivers/net/wireless/b43/nphy.h)54
-rw-r--r--drivers/net/wireless/b43/rfkill.c28
-rw-r--r--drivers/net/wireless/b43/sysfs.c23
-rw-r--r--drivers/net/wireless/b43/tables.c43
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c4
-rw-r--r--drivers/net/wireless/b43/wa.c2
-rw-r--r--drivers/net/wireless/b43/xmit.c14
-rw-r--r--drivers/net/wireless/b43legacy/main.c38
-rw-r--r--drivers/net/wireless/b43legacy/phy.c36
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c18
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c12
-rw-r--r--drivers/net/wireless/hermes.c124
-rw-r--r--drivers/net/wireless/hermes.h45
-rw-r--r--drivers/net/wireless/hermes_dld.c730
-rw-r--r--drivers/net/wireless/hermes_dld.h48
-rw-r--r--drivers/net/wireless/hermes_rid.h17
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c237
-rw-r--r--drivers/net/wireless/ipw2100.c2
-rw-r--r--drivers/net/wireless/ipw2200.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-debug.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-io.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c200
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c205
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c91
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c330
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c310
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c75
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c181
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h108
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c102
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c168
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c43
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c94
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c250
-rw-r--r--drivers/net/wireless/libertas/assoc.c750
-rw-r--r--drivers/net/wireless/libertas/assoc.h18
-rw-r--r--drivers/net/wireless/libertas/cmd.c432
-rw-r--r--drivers/net/wireless/libertas/cmd.h22
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c80
-rw-r--r--drivers/net/wireless/libertas/decl.h1
-rw-r--r--drivers/net/wireless/libertas/defs.h41
-rw-r--r--drivers/net/wireless/libertas/dev.h11
-rw-r--r--drivers/net/wireless/libertas/host.h51
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h84
-rw-r--r--drivers/net/wireless/libertas/if_cs.c17
-rw-r--r--drivers/net/wireless/libertas/if_usb.c182
-rw-r--r--drivers/net/wireless/libertas/if_usb.h5
-rw-r--r--drivers/net/wireless/libertas/main.c41
-rw-r--r--drivers/net/wireless/libertas/scan.c5
-rw-r--r--drivers/net/wireless/libertas/wext.c363
-rw-r--r--drivers/net/wireless/libertas_tf/Makefile6
-rw-r--r--drivers/net/wireless/libertas_tf/cmd.c669
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.c766
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.h98
-rw-r--r--drivers/net/wireless/libertas_tf/libertas_tf.h514
-rw-r--r--drivers/net/wireless/libertas_tf/main.c662
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c217
-rw-r--r--drivers/net/wireless/netwave_cs.c7
-rw-r--r--drivers/net/wireless/orinoco.c1961
-rw-r--r--drivers/net/wireless/orinoco.h61
-rw-r--r--drivers/net/wireless/orinoco_cs.c175
-rw-r--r--drivers/net/wireless/orinoco_nortel.c3
-rw-r--r--drivers/net/wireless/orinoco_pci.c3
-rw-r--r--drivers/net/wireless/orinoco_plx.c3
-rw-r--r--drivers/net/wireless/orinoco_tmd.c3
-rw-r--r--drivers/net/wireless/p54/p54.h55
-rw-r--r--drivers/net/wireless/p54/p54common.c696
-rw-r--r--drivers/net/wireless/p54/p54common.h124
-rw-r--r--drivers/net/wireless/p54/p54pci.c427
-rw-r--r--drivers/net/wireless/p54/p54pci.h20
-rw-r--r--drivers/net/wireless/p54/p54usb.c203
-rw-r--r--drivers/net/wireless/p54/p54usb.h11
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c8
-rw-r--r--drivers/net/wireless/ray_cs.c6
-rw-r--r--drivers/net/wireless/rndis_wlan.c3
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig128
-rw-r--r--drivers/net/wireless/rt2x00/Makefile1
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c58
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.h22
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c59
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.h17
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c68
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.h17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h90
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c16
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c215
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c97
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c129
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h49
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c245
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c137
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h82
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00reg.h24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00rfkill.c63
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c21
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c447
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h38
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c457
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.h38
-rw-r--r--drivers/net/wireless/rtl8180.h31
-rw-r--r--drivers/net/wireless/rtl8180_dev.c49
-rw-r--r--drivers/net/wireless/rtl8187.h6
-rw-r--r--drivers/net/wireless/rtl8187_dev.c23
-rw-r--r--drivers/net/wireless/rtl818x.h35
-rw-r--r--drivers/net/wireless/spectrum_cs.c595
-rw-r--r--drivers/net/wireless/wavelan.c2
-rw-r--r--drivers/net/wireless/wavelan.p.h2
-rw-r--r--drivers/net/wireless/wavelan_cs.c18
-rw-r--r--drivers/net/wireless/wl3501_cs.c14
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.c100
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.h95
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c67
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h65
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
-rw-r--r--drivers/net/xen-netfront.c13
-rw-r--r--drivers/nubus/nubus.c2
-rw-r--r--drivers/of/base.c136
-rw-r--r--drivers/of/gpio.c81
-rw-r--r--drivers/oprofile/buffer_sync.c209
-rw-r--r--drivers/oprofile/cpu_buffer.c74
-rw-r--r--drivers/oprofile/cpu_buffer.h2
-rw-r--r--drivers/parport/ChangeLog2
-rw-r--r--drivers/parport/ieee1284.c2
-rw-r--r--drivers/parport/parport_cs.c70
-rw-r--r--drivers/parport/parport_sunbpp.c49
-rw-r--r--drivers/parport/probe.c2
-rw-r--r--drivers/parport/share.c2
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/dmar.c401
-rw-r--r--drivers/pci/hotplug/fakephp.c6
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c2
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c4
-rw-r--r--drivers/pci/intel-iommu.c280
-rw-r--r--drivers/pci/intel-iommu.h344
-rw-r--r--drivers/pci/intr_remapping.c471
-rw-r--r--drivers/pci/intr_remapping.h8
-rw-r--r--drivers/pci/iova.c2
-rw-r--r--drivers/pci/iova.h52
-rw-r--r--drivers/pci/pci-sysfs.c19
-rw-r--r--drivers/pci/pcie/aspm.c2
-rw-r--r--drivers/pci/probe.c68
-rw-r--r--drivers/pci/quirks.c3
-rw-r--r--drivers/pci/search.c6
-rw-r--r--drivers/pci/setup-bus.c20
-rw-r--r--drivers/pcmcia/Kconfig3
-rw-r--r--drivers/pcmcia/Makefile21
-rw-r--r--drivers/pcmcia/au1000_generic.c2
-rw-r--r--drivers/pcmcia/au1000_generic.h2
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c1
-rw-r--r--drivers/pcmcia/au1000_xxs1500.c1
-rw-r--r--drivers/pcmcia/cardbus.c2
-rw-r--r--drivers/pcmcia/cistpl.c297
-rw-r--r--drivers/pcmcia/cs.c78
-rw-r--r--drivers/pcmcia/cs_internal.h226
-rw-r--r--drivers/pcmcia/ds.c262
-rw-r--r--drivers/pcmcia/ds_internal.h23
-rw-r--r--drivers/pcmcia/hd64465_ss.c1
-rw-r--r--drivers/pcmcia/i82365.c2
-rw-r--r--drivers/pcmcia/m32r_cfc.c4
-rw-r--r--drivers/pcmcia/m32r_pcc.c4
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c4
-rw-r--r--drivers/pcmcia/o2micro.h10
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c120
-rw-r--r--drivers/pcmcia/pcmcia_resource.c381
-rw-r--r--drivers/pcmcia/pxa2xx_base.c45
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x255.c154
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c14
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x2xx.c49
-rw-r--r--drivers/pcmcia/pxa2xx_palmld.c151
-rw-r--r--drivers/pcmcia/pxa2xx_trizeps4.c256
-rw-r--r--drivers/pcmcia/pxa2xx_viper.c179
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c67
-rw-r--r--drivers/pcmcia/soc_common.c8
-rw-r--r--drivers/pcmcia/soc_common.h3
-rw-r--r--drivers/pcmcia/socket_sysfs.c13
-rw-r--r--drivers/pcmcia/tcic.c2
-rw-r--r--drivers/pcmcia/ti113x.h78
-rw-r--r--drivers/pcmcia/yenta_socket.c86
-rw-r--r--drivers/pnp/Makefile5
-rw-r--r--drivers/pnp/base.h4
-rw-r--r--drivers/pnp/core.c11
-rw-r--r--drivers/pnp/driver.c1
-rw-r--r--drivers/pnp/interface.c37
-rw-r--r--drivers/pnp/isapnp/core.c2
-rw-r--r--drivers/pnp/pnpacpi/core.c2
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c2
-rw-r--r--drivers/pnp/pnpbios/core.c6
-rw-r--r--drivers/pnp/quirks.c5
-rw-r--r--drivers/pnp/resource.c4
-rw-r--r--drivers/power/Kconfig8
-rw-r--r--drivers/power/Makefile2
-rw-r--r--drivers/power/olpc_battery.c20
-rw-r--r--drivers/power/palmtx_battery.c198
-rw-r--r--drivers/power/power_supply_core.c4
-rw-r--r--drivers/power/wm97xx_battery.c272
-rw-r--r--drivers/regulator/Kconfig24
-rw-r--r--drivers/regulator/Makefile3
-rw-r--r--drivers/regulator/bq24022.c21
-rw-r--r--drivers/regulator/core.c508
-rw-r--r--drivers/regulator/da903x.c513
-rw-r--r--drivers/regulator/wm8350-regulator.c1431
-rw-r--r--drivers/regulator/wm8400-regulator.c368
-rw-r--r--drivers/rtc/Kconfig71
-rw-r--r--drivers/rtc/Makefile6
-rw-r--r--drivers/rtc/rtc-at91rm9200.c4
-rw-r--r--drivers/rtc/rtc-bq4802.c230
-rw-r--r--drivers/rtc/rtc-cmos.c165
-rw-r--r--drivers/rtc/rtc-dev.c27
-rw-r--r--drivers/rtc/rtc-ds1286.c410
-rw-r--r--drivers/rtc/rtc-ds1307.c308
-rw-r--r--drivers/rtc/rtc-ds1374.c21
-rw-r--r--drivers/rtc/rtc-ds1511.c13
-rw-r--r--drivers/rtc/rtc-ds1553.c12
-rw-r--r--drivers/rtc/rtc-ds1672.c114
-rw-r--r--drivers/rtc/rtc-ds3234.c290
-rw-r--r--drivers/rtc/rtc-lib.c5
-rw-r--r--drivers/rtc/rtc-m41t80.c43
-rw-r--r--drivers/rtc/rtc-m48t35.c235
-rw-r--r--drivers/rtc/rtc-m48t59.c68
-rw-r--r--drivers/rtc/rtc-max6900.c223
-rw-r--r--drivers/rtc/rtc-pcf8563.c58
-rw-r--r--drivers/rtc/rtc-pl030.c11
-rw-r--r--drivers/rtc/rtc-pl031.c14
-rw-r--r--drivers/rtc/rtc-rs5c372.c228
-rw-r--r--drivers/rtc/rtc-sh.c7
-rw-r--r--drivers/rtc/rtc-starfire.c120
-rw-r--r--drivers/rtc/rtc-stk17ta8.c12
-rw-r--r--drivers/rtc/rtc-sun4v.c153
-rw-r--r--drivers/s390/block/dasd.c32
-rw-r--r--drivers/s390/block/dasd_3990_erp.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c28
-rw-r--r--drivers/s390/block/dasd_diag.c2
-rw-r--r--drivers/s390/block/dasd_eckd.c134
-rw-r--r--drivers/s390/block/dasd_eer.c6
-rw-r--r--drivers/s390/block/dasd_fba.c6
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_proc.c5
-rw-r--r--drivers/s390/block/dcssblk.c520
-rw-r--r--drivers/s390/block/xpram.c37
-rw-r--r--drivers/s390/char/con3215.c53
-rw-r--r--drivers/s390/char/con3270.c27
-rw-r--r--drivers/s390/char/fs3270.c17
-rw-r--r--drivers/s390/char/raw3270.c14
-rw-r--r--drivers/s390/char/sclp_con.c24
-rw-r--r--drivers/s390/char/sclp_vt220.c26
-rw-r--r--drivers/s390/char/tape_3590.c132
-rw-r--r--drivers/s390/char/tape_block.c2
-rw-r--r--drivers/s390/char/tape_class.c6
-rw-r--r--drivers/s390/char/tape_core.c21
-rw-r--r--drivers/s390/char/tape_proc.c2
-rw-r--r--drivers/s390/char/tape_std.c13
-rw-r--r--drivers/s390/char/vmlogrdr.c11
-rw-r--r--drivers/s390/char/vmur.c11
-rw-r--r--drivers/s390/cio/blacklist.c11
-rw-r--r--drivers/s390/cio/ccwgroup.c7
-rw-r--r--drivers/s390/cio/chp.c10
-rw-r--r--drivers/s390/cio/chsc_sch.c2
-rw-r--r--drivers/s390/cio/cio.c61
-rw-r--r--drivers/s390/cio/cio.h4
-rw-r--r--drivers/s390/cio/css.c36
-rw-r--r--drivers/s390/cio/device.c118
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c13
-rw-r--r--drivers/s390/cio/device_ops.c2
-rw-r--r--drivers/s390/cio/io_sch.h22
-rw-r--r--drivers/s390/cio/ioasm.h49
-rw-r--r--drivers/s390/cio/qdio.h11
-rw-r--r--drivers/s390/cio/qdio_debug.c2
-rw-r--r--drivers/s390/cio/qdio_main.c32
-rw-r--r--drivers/s390/cio/qdio_setup.c55
-rw-r--r--drivers/s390/crypto/ap_bus.c4
-rw-r--r--drivers/s390/kvm/kvm_virtio.c15
-rw-r--r--drivers/s390/net/claw.c36
-rw-r--r--drivers/s390/net/claw.h2
-rw-r--r--drivers/s390/net/ctcm_main.c22
-rw-r--r--drivers/s390/net/ctcm_main.h2
-rw-r--r--drivers/s390/net/ctcm_mpc.c2
-rw-r--r--drivers/s390/net/lcs.c34
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/s390/net/qeth_core.h10
-rw-r--r--drivers/s390/net/qeth_core_main.c14
-rw-r--r--drivers/s390/net/qeth_l2_main.c14
-rw-r--r--drivers/s390/net/qeth_l3_main.c8
-rw-r--r--drivers/s390/s390_rdev.c2
-rw-r--r--drivers/s390/scsi/zfcp_aux.c149
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c51
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c75
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h1
-rw-r--r--drivers/s390/scsi/zfcp_def.h185
-rw-r--r--drivers/s390/scsi/zfcp_erp.c231
-rw-r--r--drivers/s390/scsi/zfcp_ext.h27
-rw-r--r--drivers/s390/scsi/zfcp_fc.c252
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c650
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h87
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c68
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c28
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c62
-rw-r--r--drivers/sbus/Makefile4
-rw-r--r--drivers/sbus/char/Kconfig29
-rw-r--r--drivers/sbus/char/Makefile6
-rw-r--r--drivers/sbus/char/bbc_envctrl.c121
-rw-r--r--drivers/sbus/char/bbc_i2c.c267
-rw-r--r--drivers/sbus/char/bbc_i2c.h75
-rw-r--r--drivers/sbus/char/bpp.c1055
-rw-r--r--drivers/sbus/char/cpwatchdog.c858
-rw-r--r--drivers/sbus/char/display7seg.c251
-rw-r--r--drivers/sbus/char/envctrl.c147
-rw-r--r--drivers/sbus/char/flash.c130
-rw-r--r--drivers/sbus/char/rtc.c275
-rw-r--r--drivers/sbus/char/uctrl.c216
-rw-r--r--drivers/sbus/char/vfc.h171
-rw-r--r--drivers/sbus/char/vfc_dev.c736
-rw-r--r--drivers/sbus/char/vfc_i2c.c335
-rw-r--r--drivers/sbus/char/vfc_i2c.h44
-rw-r--r--drivers/sbus/dvma.c136
-rw-r--r--drivers/sbus/sbus.c316
-rw-r--r--drivers/scsi/Kconfig19
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/atari_dma_emul.c468
-rw-r--r--drivers/scsi/atari_scsi.c27
-rw-r--r--drivers/scsi/ch.c6
-rw-r--r--drivers/scsi/constants.c3
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c15
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c12
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c8
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c11
-rw-r--r--drivers/scsi/dpt_i2o.c2
-rw-r--r--drivers/scsi/esp_scsi.h3
-rw-r--r--drivers/scsi/gdth.c60
-rw-r--r--drivers/scsi/gdth.h2
-rw-r--r--drivers/scsi/gdth_proc.c66
-rw-r--r--drivers/scsi/gdth_proc.h3
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/ide-scsi.c220
-rw-r--r--drivers/scsi/ipr.c3
-rw-r--r--drivers/scsi/ips.c2
-rw-r--r--drivers/scsi/iscsi_tcp.c44
-rw-r--r--drivers/scsi/libiscsi.c202
-rw-r--r--drivers/scsi/libsas/sas_ata.c10
-rw-r--r--drivers/scsi/libsas/sas_internal.h2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c30
-rw-r--r--drivers/scsi/lpfc/lpfc.h96
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c1375
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h51
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c20
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c400
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h23
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1712
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c241
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h183
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c924
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c624
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c116
-rw-r--r--drivers/scsi/lpfc/lpfc_nl.h163
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c24
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c514
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c1715
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c168
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c6
-rw-r--r--drivers/scsi/ncr53c8xx.c4
-rw-r--r--drivers/scsi/osst.c3
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c58
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c37
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c194
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c47
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c46
-rw-r--r--drivers/scsi/qla1280.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h13
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h71
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c30
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c32
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c37
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c338
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c8
-rw-r--r--drivers/scsi/qlogicpti.c147
-rw-r--r--drivers/scsi/qlogicpti.h2
-rw-r--r--drivers/scsi/scsi.c111
-rw-r--r--drivers/scsi/scsi_error.c164
-rw-r--r--drivers/scsi/scsi_lib.c165
-rw-r--r--drivers/scsi/scsi_netlink.c523
-rw-r--r--drivers/scsi/scsi_priv.h8
-rw-r--r--drivers/scsi/scsi_proc.c8
-rw-r--r--drivers/scsi/scsi_scan.c24
-rw-r--r--drivers/scsi/scsi_sysfs.c8
-rw-r--r--drivers/scsi/scsi_tgt_lib.c8
-rw-r--r--drivers/scsi/scsi_transport_fc.c107
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c23
-rw-r--r--drivers/scsi/scsi_transport_spi.c4
-rw-r--r--drivers/scsi/sd.c139
-rw-r--r--drivers/scsi/sd.h21
-rw-r--r--drivers/scsi/sd_dif.c42
-rw-r--r--drivers/scsi/sg.c677
-rw-r--r--drivers/scsi/sr.c7
-rw-r--r--drivers/scsi/st.c11
-rw-r--r--drivers/scsi/sun_esp.c267
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c4
-rw-r--r--drivers/scsi/tmscsim.c4
-rw-r--r--drivers/serial/8250.c88
-rw-r--r--drivers/serial/8250.h1
-rw-r--r--drivers/serial/8250_pci.c4
-rw-r--r--drivers/serial/Kconfig53
-rw-r--r--drivers/serial/Makefile16
-rw-r--r--drivers/serial/atmel_serial.c32
-rw-r--r--drivers/serial/bfin_5xx.c123
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c3
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c6
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c6
-rw-r--r--drivers/serial/crisv10.c5
-rw-r--r--drivers/serial/imx.c27
-rw-r--r--drivers/serial/mcfserial.c1965
-rw-r--r--drivers/serial/mcfserial.h74
-rw-r--r--drivers/serial/mpc52xx_uart.c181
-rw-r--r--drivers/serial/pxa.c5
-rw-r--r--drivers/serial/s3c2400.c2
-rw-r--r--drivers/serial/s3c2410.c2
-rw-r--r--drivers/serial/s3c2412.c2
-rw-r--r--drivers/serial/s3c2440.c2
-rw-r--r--drivers/serial/samsung.c2
-rw-r--r--drivers/serial/serial_core.c12
-rw-r--r--drivers/serial/serial_cs.c302
-rw-r--r--drivers/serial/serial_ks8695.c61
-rw-r--r--drivers/serial/sunhv.c2
-rw-r--r--drivers/serial/sunsab.c2
-rw-r--r--drivers/serial/sunsu.c2
-rw-r--r--drivers/serial/sunzilog.c2
-rw-r--r--drivers/serial/ucc_uart.c4
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c61
-rw-r--r--drivers/spi/omap2_mcspi.c18
-rw-r--r--drivers/spi/omap_uwire.c23
-rw-r--r--drivers/spi/orion_spi.c7
-rw-r--r--drivers/spi/pxa2xx_spi.c170
-rw-r--r--drivers/spi/spi.c24
-rw-r--r--drivers/spi/spi_mpc83xx.c26
-rw-r--r--drivers/spi/spi_s3c24xx.c12
-rw-r--r--drivers/spi/spidev.c7
-rw-r--r--drivers/ssb/main.c1
-rw-r--r--drivers/ssb/pci.c84
-rw-r--r--drivers/ssb/pcmcia.c22
-rw-r--r--drivers/staging/Kconfig46
-rw-r--r--drivers/staging/Makefile15
-rw-r--r--drivers/staging/at76_usb/Kconfig8
-rw-r--r--drivers/staging/at76_usb/Makefile1
-rw-r--r--drivers/staging/at76_usb/TODO2
-rw-r--r--drivers/staging/at76_usb/at76_usb.c5559
-rw-r--r--drivers/staging/at76_usb/at76_usb.h619
-rw-r--r--drivers/staging/echo/Kconfig9
-rw-r--r--drivers/staging/echo/Makefile1
-rw-r--r--drivers/staging/echo/TODO10
-rw-r--r--drivers/staging/echo/bit_operations.h253
-rw-r--r--drivers/staging/echo/echo.c632
-rw-r--r--drivers/staging/echo/echo.h220
-rw-r--r--drivers/staging/echo/fir.h369
-rw-r--r--drivers/staging/echo/mmx.h288
-rw-r--r--drivers/staging/et131x/Kconfig18
-rw-r--r--drivers/staging/et131x/Makefile18
-rw-r--r--drivers/staging/et131x/README25
-rw-r--r--drivers/staging/et131x/et1310_address_map.h2399
-rw-r--r--drivers/staging/et131x/et1310_eeprom.c480
-rw-r--r--drivers/staging/et131x/et1310_eeprom.h89
-rw-r--r--drivers/staging/et131x/et1310_jagcore.c220
-rw-r--r--drivers/staging/et131x/et1310_jagcore.h112
-rw-r--r--drivers/staging/et131x/et1310_mac.c792
-rw-r--r--drivers/staging/et131x/et1310_mac.h93
-rw-r--r--drivers/staging/et131x/et1310_phy.c1281
-rw-r--r--drivers/staging/et131x/et1310_phy.h910
-rw-r--r--drivers/staging/et131x/et1310_pm.c207
-rw-r--r--drivers/staging/et131x/et1310_pm.h125
-rw-r--r--drivers/staging/et131x/et1310_rx.c1391
-rw-r--r--drivers/staging/et131x/et1310_rx.h373
-rw-r--r--drivers/staging/et131x/et1310_tx.c1525
-rw-r--r--drivers/staging/et131x/et1310_tx.h242
-rw-r--r--drivers/staging/et131x/et131x_adapter.h347
-rw-r--r--drivers/staging/et131x/et131x_config.c325
-rw-r--r--drivers/staging/et131x/et131x_config.h67
-rw-r--r--drivers/staging/et131x/et131x_debug.c218
-rw-r--r--drivers/staging/et131x/et131x_debug.h201
-rw-r--r--drivers/staging/et131x/et131x_defs.h128
-rw-r--r--drivers/staging/et131x/et131x_initpci.c1046
-rw-r--r--drivers/staging/et131x/et131x_initpci.h73
-rw-r--r--drivers/staging/et131x/et131x_isr.c488
-rw-r--r--drivers/staging/et131x/et131x_isr.h65
-rw-r--r--drivers/staging/et131x/et131x_netdev.c856
-rw-r--r--drivers/staging/et131x/et131x_netdev.h64
-rw-r--r--drivers/staging/et131x/et131x_version.h81
-rw-r--r--drivers/staging/go7007/Kconfig25
-rw-r--r--drivers/staging/go7007/Makefile18
-rw-r--r--drivers/staging/go7007/README11
-rw-r--r--drivers/staging/go7007/go7007-driver.c688
-rw-r--r--drivers/staging/go7007/go7007-fw.c1639
-rw-r--r--drivers/staging/go7007/go7007-i2c.c309
-rw-r--r--drivers/staging/go7007/go7007-priv.h279
-rw-r--r--drivers/staging/go7007/go7007-usb.c1229
-rw-r--r--drivers/staging/go7007/go7007-v4l2.c1499
-rw-r--r--drivers/staging/go7007/go7007.h114
-rw-r--r--drivers/staging/go7007/saa7134-go7007.c484
-rw-r--r--drivers/staging/go7007/snd-go7007.c305
-rw-r--r--drivers/staging/go7007/wis-i2c.h55
-rw-r--r--drivers/staging/go7007/wis-ov7640.c130
-rw-r--r--drivers/staging/go7007/wis-saa7113.c358
-rw-r--r--drivers/staging/go7007/wis-saa7115.c491
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c742
-rw-r--r--drivers/staging/go7007/wis-tw2804.c380
-rw-r--r--drivers/staging/go7007/wis-tw9903.c362
-rw-r--r--drivers/staging/go7007/wis-uda1342.c136
-rw-r--r--drivers/staging/me4000/Kconfig10
-rw-r--r--drivers/staging/me4000/Makefile1
-rw-r--r--drivers/staging/me4000/README13
-rw-r--r--drivers/staging/me4000/me4000.c6133
-rw-r--r--drivers/staging/me4000/me4000.h954
-rw-r--r--drivers/staging/me4000/me4000_firmware.h10033
-rw-r--r--drivers/staging/me4000/me4610_firmware.h5409
-rw-r--r--drivers/staging/slicoss/Kconfig14
-rw-r--r--drivers/staging/slicoss/Makefile1
-rw-r--r--drivers/staging/slicoss/README19
-rw-r--r--drivers/staging/slicoss/gbdownload.h8215
-rw-r--r--drivers/staging/slicoss/gbrcvucode.h238
-rw-r--r--drivers/staging/slicoss/oasisdbgdownload.h6850
-rw-r--r--drivers/staging/slicoss/oasisdownload.h6848
-rw-r--r--drivers/staging/slicoss/oasisrcvucode.h205
-rw-r--r--drivers/staging/slicoss/slic.h598
-rw-r--r--drivers/staging/slicoss/slic_os.h84
-rw-r--r--drivers/staging/slicoss/slicbuild.h96
-rw-r--r--drivers/staging/slicoss/slicdbg.h100
-rw-r--r--drivers/staging/slicoss/slicdump.h278
-rw-r--r--drivers/staging/slicoss/slichw.h845
-rw-r--r--drivers/staging/slicoss/slicinc.h185
-rw-r--r--drivers/staging/slicoss/slicoss.c5936
-rw-r--r--drivers/staging/staging.c19
-rw-r--r--drivers/staging/sxg/Kconfig10
-rw-r--r--drivers/staging/sxg/Makefile1
-rw-r--r--drivers/staging/sxg/README13
-rw-r--r--drivers/staging/sxg/saharadbgdownload.h4854
-rw-r--r--drivers/staging/sxg/sxg.c3624
-rw-r--r--drivers/staging/sxg/sxg.h773
-rw-r--r--drivers/staging/sxg/sxg_os.h154
-rw-r--r--drivers/staging/sxg/sxgdbg.h190
-rw-r--r--drivers/staging/sxg/sxghif.h861
-rw-r--r--drivers/staging/sxg/sxghw.h734
-rw-r--r--drivers/staging/sxg/sxgphycode.h349
-rw-r--r--drivers/staging/usbip/Kconfig36
-rw-r--r--drivers/staging/usbip/Makefile12
-rw-r--r--drivers/staging/usbip/README6
-rw-r--r--drivers/staging/usbip/stub.h95
-rw-r--r--drivers/staging/usbip/stub_dev.c483
-rw-r--r--drivers/staging/usbip/stub_main.c300
-rw-r--r--drivers/staging/usbip/stub_rx.c615
-rw-r--r--drivers/staging/usbip/stub_tx.c371
-rw-r--r--drivers/staging/usbip/usbip_common.c997
-rw-r--r--drivers/staging/usbip/usbip_common.h406
-rw-r--r--drivers/staging/usbip/usbip_event.c141
-rw-r--r--drivers/staging/usbip/vhci.h142
-rw-r--r--drivers/staging/usbip/vhci_hcd.c1275
-rw-r--r--drivers/staging/usbip/vhci_rx.c251
-rw-r--r--drivers/staging/usbip/vhci_sysfs.c250
-rw-r--r--drivers/staging/usbip/vhci_tx.c239
-rw-r--r--drivers/staging/winbond/Kconfig7
-rw-r--r--drivers/staging/winbond/Makefile18
-rw-r--r--drivers/staging/winbond/README10
-rw-r--r--drivers/staging/winbond/adapter.h23
-rw-r--r--drivers/staging/winbond/bss_f.h59
-rw-r--r--drivers/staging/winbond/bssdscpt.h156
-rw-r--r--drivers/staging/winbond/ds_tkip.h33
-rw-r--r--drivers/staging/winbond/gl_80211.h125
-rw-r--r--drivers/staging/winbond/ioctls.h678
-rw-r--r--drivers/staging/winbond/linux/common.h143
-rw-r--r--drivers/staging/winbond/linux/sysdef.h73
-rw-r--r--drivers/staging/winbond/linux/wb35reg.c747
-rw-r--r--drivers/staging/winbond/linux/wb35reg_f.h56
-rw-r--r--drivers/staging/winbond/linux/wb35reg_s.h170
-rw-r--r--drivers/staging/winbond/linux/wb35rx.c337
-rw-r--r--drivers/staging/winbond/linux/wb35rx_f.h17
-rw-r--r--drivers/staging/winbond/linux/wb35rx_s.h48
-rw-r--r--drivers/staging/winbond/linux/wb35tx.c313
-rw-r--r--drivers/staging/winbond/linux/wb35tx_f.h20
-rw-r--r--drivers/staging/winbond/linux/wb35tx_s.h47
-rw-r--r--drivers/staging/winbond/linux/wbusb.c404
-rw-r--r--drivers/staging/winbond/linux/wbusb_f.h34
-rw-r--r--drivers/staging/winbond/linux/wbusb_s.h42
-rw-r--r--drivers/staging/winbond/localpara.h275
-rw-r--r--drivers/staging/winbond/mac_structures.h670
-rw-r--r--drivers/staging/winbond/mds.c630
-rw-r--r--drivers/staging/winbond/mds_f.h33
-rw-r--r--drivers/staging/winbond/mds_s.h183
-rw-r--r--drivers/staging/winbond/mlme_mib.h84
-rw-r--r--drivers/staging/winbond/mlme_s.h195
-rw-r--r--drivers/staging/winbond/mlmetxrx.c150
-rw-r--r--drivers/staging/winbond/mlmetxrx_f.h52
-rw-r--r--drivers/staging/winbond/mto.c1229
-rw-r--r--drivers/staging/winbond/mto.h265
-rw-r--r--drivers/staging/winbond/mto_f.h7
-rw-r--r--drivers/staging/winbond/os_common.h2
-rw-r--r--drivers/staging/winbond/phy_calibration.c1759
-rw-r--r--drivers/staging/winbond/phy_calibration.h101
-rw-r--r--drivers/staging/winbond/reg.c2683
-rw-r--r--drivers/staging/winbond/rxisr.c30
-rw-r--r--drivers/staging/winbond/scan_s.h115
-rw-r--r--drivers/staging/winbond/sme_api.c13
-rw-r--r--drivers/staging/winbond/sme_api.h265
-rw-r--r--drivers/staging/winbond/sme_s.h228
-rw-r--r--drivers/staging/winbond/wb35_ver.h30
-rw-r--r--drivers/staging/winbond/wbhal.c878
-rw-r--r--drivers/staging/winbond/wbhal_f.h122
-rw-r--r--drivers/staging/winbond/wbhal_s.h615
-rw-r--r--drivers/staging/winbond/wblinux.c277
-rw-r--r--drivers/staging/winbond/wblinux_f.h23
-rw-r--r--drivers/staging/winbond/wblinux_s.h45
-rw-r--r--drivers/staging/wlan-ng/Kconfig10
-rw-r--r--drivers/staging/wlan-ng/Makefile9
-rw-r--r--drivers/staging/wlan-ng/README8
-rw-r--r--drivers/staging/wlan-ng/hfa384x.c4018
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h3067
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c5027
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c683
-rw-r--r--drivers/staging/wlan-ng/p80211conv.h186
-rw-r--r--drivers/staging/wlan-ng/p80211hdr.h299
-rw-r--r--drivers/staging/wlan-ng/p80211ioctl.h123
-rw-r--r--drivers/staging/wlan-ng/p80211meta.h169
-rw-r--r--drivers/staging/wlan-ng/p80211metadef.h2524
-rw-r--r--drivers/staging/wlan-ng/p80211metamib.h105
-rw-r--r--drivers/staging/wlan-ng/p80211metamsg.h105
-rw-r--r--drivers/staging/wlan-ng/p80211metastruct.h644
-rw-r--r--drivers/staging/wlan-ng/p80211mgmt.h575
-rw-r--r--drivers/staging/wlan-ng/p80211mod.c216
-rw-r--r--drivers/staging/wlan-ng/p80211msg.h102
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c1502
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h336
-rw-r--r--drivers/staging/wlan-ng/p80211req.c329
-rw-r--r--drivers/staging/wlan-ng/p80211req.h68
-rw-r--r--drivers/staging/wlan-ng/p80211types.h675
-rw-r--r--drivers/staging/wlan-ng/p80211wep.c317
-rw-r--r--drivers/staging/wlan-ng/p80211wext.c2048
-rw-r--r--drivers/staging/wlan-ng/prism2_cs.c1487
-rw-r--r--drivers/staging/wlan-ng/prism2_pci.c332
-rw-r--r--drivers/staging/wlan-ng/prism2_plx.c472
-rw-r--r--drivers/staging/wlan-ng/prism2_usb.c361
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c2956
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h182
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c3799
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c2502
-rw-r--r--drivers/staging/wlan-ng/version.h64
-rw-r--r--drivers/staging/wlan-ng/wlan_compat.h757
-rw-r--r--drivers/telephony/ixj.c2
-rw-r--r--drivers/telephony/ixj_pcmcia.c72
-rw-r--r--drivers/uio/Kconfig13
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio.c26
-rw-r--r--drivers/uio/uio_pdrv.c2
-rw-r--r--drivers/uio/uio_sercos3.c243
-rw-r--r--drivers/usb/atm/usbatm.c15
-rw-r--r--drivers/usb/atm/usbatm.h10
-rw-r--r--drivers/usb/atm/xusbatm.c2
-rw-r--r--drivers/usb/class/Kconfig10
-rw-r--r--drivers/usb/class/Makefile1
-rw-r--r--drivers/usb/class/cdc-acm.c26
-rw-r--r--drivers/usb/class/cdc-wdm.c48
-rw-r--r--drivers/usb/class/usblp.c25
-rw-r--r--drivers/usb/class/usbtmc.c1087
-rw-r--r--drivers/usb/core/Kconfig2
-rw-r--r--drivers/usb/core/devio.c18
-rw-r--r--drivers/usb/core/driver.c3
-rw-r--r--drivers/usb/core/endpoint.c3
-rw-r--r--drivers/usb/core/file.c11
-rw-r--r--drivers/usb/core/hcd.c12
-rw-r--r--drivers/usb/core/hcd.h6
-rw-r--r--drivers/usb/core/hub.c141
-rw-r--r--drivers/usb/core/inode.c20
-rw-r--r--drivers/usb/core/message.c3
-rw-r--r--drivers/usb/core/sysfs.c24
-rw-r--r--drivers/usb/core/urb.c169
-rw-r--r--drivers/usb/gadget/Kconfig315
-rw-r--r--drivers/usb/gadget/Makefile24
-rw-r--r--drivers/usb/gadget/cdc2.c26
-rw-r--r--drivers/usb/gadget/composite.c68
-rw-r--r--drivers/usb/gadget/dummy_hcd.c33
-rw-r--r--drivers/usb/gadget/ether.c30
-rw-r--r--drivers/usb/gadget/f_ecm.c108
-rw-r--r--drivers/usb/gadget/f_loopback.c35
-rw-r--r--drivers/usb/gadget/f_obex.c493
-rw-r--r--drivers/usb/gadget/f_sourcesink.c1
-rw-r--r--drivers/usb/gadget/f_subset.c44
-rw-r--r--drivers/usb/gadget/file_storage.c35
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c2760
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.h437
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c178
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h21
-rw-r--r--drivers/usb/gadget/gadget_chips.h9
-rw-r--r--drivers/usb/gadget/gmidi.c17
-rw-r--r--drivers/usb/gadget/net2280.c40
-rw-r--r--drivers/usb/gadget/net2280.h1
-rw-r--r--drivers/usb/gadget/omap_udc.c11
-rw-r--r--drivers/usb/gadget/printer.c24
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c1
-rw-r--r--drivers/usb/gadget/rndis.c115
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c2
-rw-r--r--drivers/usb/gadget/serial.c33
-rw-r--r--drivers/usb/gadget/u_ether.c11
-rw-r--r--drivers/usb/gadget/u_serial.h1
-rw-r--r--drivers/usb/gadget/zero.c17
-rw-r--r--drivers/usb/host/ehci-dbg.c56
-rw-r--r--drivers/usb/host/ehci-hcd.c74
-rw-r--r--drivers/usb/host/ehci-hub.c27
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c2
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c201
-rw-r--r--drivers/usb/host/ehci-sched.c32
-rw-r--r--drivers/usb/host/ehci.h161
-rw-r--r--drivers/usb/host/isp116x-hcd.c13
-rw-r--r--drivers/usb/host/isp1760-if.c7
-rw-r--r--drivers/usb/host/ohci-dbg.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c10
-rw-r--r--drivers/usb/host/ohci-hub.c87
-rw-r--r--drivers/usb/host/ohci-omap.c20
-rw-r--r--drivers/usb/host/ohci-pnx4008.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c259
-rw-r--r--drivers/usb/host/ohci.h8
-rw-r--r--drivers/usb/host/r8a66597-hcd.c101
-rw-r--r--drivers/usb/host/sl811-hcd.c15
-rw-r--r--drivers/usb/host/sl811_cs.c133
-rw-r--r--drivers/usb/host/uhci-hcd.c10
-rw-r--r--drivers/usb/host/uhci-q.c41
-rw-r--r--drivers/usb/image/mdc800.c61
-rw-r--r--drivers/usb/misc/Kconfig24
-rw-r--r--drivers/usb/misc/Makefile2
-rw-r--r--drivers/usb/misc/adutux.c22
-rw-r--r--drivers/usb/misc/appledisplay.c26
-rw-r--r--drivers/usb/misc/cypress_cy7c63.c6
-rw-r--r--drivers/usb/misc/cytherm.c9
-rw-r--r--drivers/usb/misc/emi26.c17
-rw-r--r--drivers/usb/misc/emi62.c4
-rw-r--r--drivers/usb/misc/ftdi-elan.c10
-rw-r--r--drivers/usb/misc/idmouse.c5
-rw-r--r--drivers/usb/misc/legousbtower.c23
-rw-r--r--drivers/usb/misc/phidgetkit.c5
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c5
-rw-r--r--drivers/usb/misc/phidgetservo.c5
-rw-r--r--drivers/usb/misc/rio500.c11
-rw-r--r--drivers/usb/misc/trancevibrator.c3
-rw-r--r--drivers/usb/misc/usblcd.c13
-rw-r--r--drivers/usb/misc/usbsevseg.c394
-rw-r--r--drivers/usb/misc/uss720.c19
-rw-r--r--drivers/usb/misc/vstusb.c782
-rw-r--r--drivers/usb/mon/mon_bin.c6
-rw-r--r--drivers/usb/mon/mon_main.c2
-rw-r--r--drivers/usb/musb/Kconfig5
-rw-r--r--drivers/usb/musb/cppi_dma.h4
-rw-r--r--drivers/usb/musb/davinci.c20
-rw-r--r--drivers/usb/musb/musb_core.c45
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c24
-rw-r--r--drivers/usb/musb/musb_host.c19
-rw-r--r--drivers/usb/musb/musb_io.h4
-rw-r--r--drivers/usb/musb/musbhsdma.c306
-rw-r--r--drivers/usb/musb/omap2430.c4
-rw-r--r--drivers/usb/musb/omap2430.h4
-rw-r--r--drivers/usb/serial/aircable.c23
-rw-r--r--drivers/usb/serial/belkin_sa.c42
-rw-r--r--drivers/usb/serial/console.c10
-rw-r--r--drivers/usb/serial/cp2101.c6
-rw-r--r--drivers/usb/serial/cyberjack.c31
-rw-r--r--drivers/usb/serial/cypress_m8.c26
-rw-r--r--drivers/usb/serial/digi_acceleport.c87
-rw-r--r--drivers/usb/serial/empeg.c19
-rw-r--r--drivers/usb/serial/ezusb.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c110
-rw-r--r--drivers/usb/serial/ftdi_sio.h10
-rw-r--r--drivers/usb/serial/garmin_gps.c6
-rw-r--r--drivers/usb/serial/generic.c3
-rw-r--r--drivers/usb/serial/hp4x.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c62
-rw-r--r--drivers/usb/serial/io_ti.c29
-rw-r--r--drivers/usb/serial/ipaq.c33
-rw-r--r--drivers/usb/serial/ipw.c6
-rw-r--r--drivers/usb/serial/ir-usb.c6
-rw-r--r--drivers/usb/serial/iuu_phoenix.c6
-rw-r--r--drivers/usb/serial/keyspan.c80
-rw-r--r--drivers/usb/serial/keyspan_pda.c33
-rw-r--r--drivers/usb/serial/kl5kusb105.c72
-rw-r--r--drivers/usb/serial/kobil_sct.c7
-rw-r--r--drivers/usb/serial/mct_u232.c48
-rw-r--r--drivers/usb/serial/mos7720.c58
-rw-r--r--drivers/usb/serial/mos7840.c36
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/omninet.c32
-rw-r--r--drivers/usb/serial/option.c62
-rw-r--r--drivers/usb/serial/oti6858.c7
-rw-r--r--drivers/usb/serial/pl2303.c17
-rw-r--r--drivers/usb/serial/safe_serial.c39
-rw-r--r--drivers/usb/serial/sierra.c100
-rw-r--r--drivers/usb/serial/spcp8x5.c13
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c50
-rw-r--r--drivers/usb/serial/usb-serial.c54
-rw-r--r--drivers/usb/serial/visor.c35
-rw-r--r--drivers/usb/serial/whiteheat.c129
-rw-r--r--drivers/usb/storage/Kconfig12
-rw-r--r--drivers/usb/storage/Makefile3
-rw-r--r--drivers/usb/storage/onetouch.c9
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h30
-rw-r--r--drivers/usb/storage/usb.c2
-rw-r--r--drivers/video/Kconfig142
-rw-r--r--drivers/video/Makefile4
-rw-r--r--drivers/video/am200epd.c295
-rw-r--r--drivers/video/atmel_lcdfb.c105
-rw-r--r--drivers/video/aty/radeon_accel.c313
-rw-r--r--drivers/video/aty/radeon_backlight.c2
-rw-r--r--drivers/video/aty/radeon_base.c35
-rw-r--r--drivers/video/aty/radeon_i2c.c4
-rw-r--r--drivers/video/aty/radeon_pm.c6
-rw-r--r--drivers/video/aty/radeonfb.h53
-rw-r--r--drivers/video/backlight/Kconfig15
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/corgi_lcd.c641
-rw-r--r--drivers/video/backlight/lcd.c18
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c4
-rw-r--r--drivers/video/backlight/tdo24m.c396
-rw-r--r--drivers/video/bw2.c2
-rw-r--r--drivers/video/carminefb.c2
-rw-r--r--drivers/video/cg14.c2
-rw-r--r--drivers/video/cg3.c2
-rw-r--r--drivers/video/cg6.c38
-rw-r--r--drivers/video/cirrusfb.c636
-rw-r--r--drivers/video/console/Kconfig16
-rw-r--r--drivers/video/console/fbcon.c53
-rw-r--r--drivers/video/console/fbcon.h2
-rw-r--r--drivers/video/console/mdacon.c2
-rw-r--r--drivers/video/console/sticon.c4
-rw-r--r--drivers/video/console/vgacon.c43
-rw-r--r--drivers/video/display/display-sysfs.c9
-rw-r--r--drivers/video/efifb.c191
-rw-r--r--drivers/video/fbmem.c23
-rw-r--r--drivers/video/fbmon.c8
-rw-r--r--drivers/video/ffb.c2
-rw-r--r--drivers/video/imacfb.c376
-rw-r--r--drivers/video/intelfb/intelfb.h7
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c7
-rw-r--r--drivers/video/intelfb/intelfbhw.c7
-rw-r--r--drivers/video/leo.c96
-rw-r--r--drivers/video/matrox/matroxfb_base.c9
-rw-r--r--drivers/video/metronomefb.c288
-rw-r--r--drivers/video/neofb.c60
-rw-r--r--drivers/video/omap/dispc.c21
-rw-r--r--drivers/video/omap/dispc.h2
-rw-r--r--drivers/video/omap/lcd_h4.c4
-rw-r--r--drivers/video/omap/lcd_inn1610.c22
-rw-r--r--drivers/video/omap/lcd_osk.c10
-rw-r--r--drivers/video/omap/lcd_sx1.c99
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/lcdc.h2
-rw-r--r--drivers/video/omap/omapfb_main.c15
-rw-r--r--drivers/video/omap/rfbi.c9
-rw-r--r--drivers/video/omap/sossi.c8
-rw-r--r--drivers/video/p9100.c2
-rw-r--r--drivers/video/s1d13xxxfb.c23
-rw-r--r--drivers/video/tcx.c2
-rw-r--r--drivers/video/tdfxfb.c51
-rw-r--r--drivers/video/tmiofb.c1050
-rw-r--r--drivers/video/uvesafb.c11
-rw-r--r--drivers/video/vga16fb.c11
-rw-r--r--drivers/video/via/Makefile7
-rw-r--r--drivers/video/via/accel.c279
-rw-r--r--drivers/video/via/accel.h169
-rw-r--r--drivers/video/via/chip.h190
-rw-r--r--drivers/video/via/debug.h41
-rw-r--r--drivers/video/via/dvi.c682
-rw-r--r--drivers/video/via/dvi.h64
-rw-r--r--drivers/video/via/global.c60
-rw-r--r--drivers/video/via/global.h90
-rw-r--r--drivers/video/via/hw.c2865
-rw-r--r--drivers/video/via/hw.h933
-rw-r--r--drivers/video/via/iface.c78
-rw-r--r--drivers/video/via/iface.h38
-rw-r--r--drivers/video/via/ioctl.c112
-rw-r--r--drivers/video/via/ioctl.h210
-rw-r--r--drivers/video/via/lcd.c1821
-rw-r--r--drivers/video/via/lcd.h94
-rw-r--r--drivers/video/via/lcdtbl.h591
-rw-r--r--drivers/video/via/share.h1105
-rw-r--r--drivers/video/via/tbl1636.c71
-rw-r--r--drivers/video/via/tbl1636.h34
-rw-r--r--drivers/video/via/tblDPASetting.c109
-rw-r--r--drivers/video/via/tblDPASetting.h47
-rw-r--r--drivers/video/via/via_i2c.c177
-rw-r--r--drivers/video/via/via_i2c.h46
-rw-r--r--drivers/video/via/via_utility.c253
-rw-r--r--drivers/video/via/via_utility.h35
-rw-r--r--drivers/video/via/viafbdev.c2571
-rw-r--r--drivers/video/via/viafbdev.h112
-rw-r--r--drivers/video/via/viamode.c1086
-rw-r--r--drivers/video/via/viamode.h177
-rw-r--r--drivers/video/via/vt1636.c306
-rw-r--r--drivers/video/via/vt1636.h44
-rw-r--r--drivers/video/xen-fbfront.c4
-rw-r--r--drivers/w1/masters/ds1wm.c10
-rw-r--r--drivers/w1/masters/ds2490.c348
-rw-r--r--drivers/w1/slaves/w1_ds2431.c312
-rw-r--r--drivers/w1/slaves/w1_therm.c72
-rw-r--r--drivers/w1/w1.c423
-rw-r--r--drivers/w1/w1.h34
-rw-r--r--drivers/w1/w1_family.c13
-rw-r--r--drivers/w1/w1_family.h3
-rw-r--r--drivers/w1/w1_int.c88
-rw-r--r--drivers/w1/w1_io.c85
-rw-r--r--drivers/watchdog/Kconfig43
-rw-r--r--drivers/watchdog/Makefile7
-rw-r--r--drivers/watchdog/at91sam9_wdt.c328
-rw-r--r--drivers/watchdog/cpwd.c695
-rw-r--r--drivers/watchdog/geodewdt.c6
-rw-r--r--drivers/watchdog/ibmasr.c1
-rw-r--r--drivers/watchdog/it87_wdt.c725
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c4
-rw-r--r--drivers/watchdog/omap_wdt.c337
-rw-r--r--drivers/watchdog/omap_wdt.h28
-rw-r--r--drivers/watchdog/orion5x_wdt.c245
-rw-r--r--drivers/watchdog/pnx4008_wdt.c4
-rw-r--r--drivers/watchdog/rc32434_wdt.c6
-rw-r--r--drivers/watchdog/rdc321x_wdt.c6
-rw-r--r--drivers/watchdog/riowd.c (renamed from drivers/sbus/char/riowatchdog.c)236
-rw-r--r--drivers/watchdog/w83697ug_wdt.c392
-rw-r--r--drivers/watchdog/wdt285.c15
-rw-r--r--drivers/xen/Makefile1
-rw-r--r--drivers/xen/balloon.c177
-rw-r--r--drivers/xen/cpu_hotplug.c90
-rw-r--r--drivers/xen/events.c40
-rw-r--r--drivers/xen/grant-table.c2
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c8
2340 files changed, 342974 insertions, 81716 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 59f33fa6af3..d19b6f5a110 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -101,4 +101,6 @@ source "drivers/auxdisplay/Kconfig"
source "drivers/uio/Kconfig"
source "drivers/xen/Kconfig"
+
+source "drivers/staging/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 2735bde7347..46c8681a07f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -99,3 +99,4 @@ obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
obj-$(CONFIG_VIRTIO) += virtio/
obj-$(CONFIG_REGULATOR) += regulator/
+obj-$(CONFIG_STAGING) += staging/
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index 0a5f6b2114c..d672cfe7ca5 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -376,6 +376,8 @@ int braille_register_console(struct console *console, int index,
console->flags |= CON_ENABLED;
console->index = index;
braille_co = console;
+ register_keyboard_notifier(&keyboard_notifier_block);
+ register_vt_notifier(&vt_notifier_block);
return 0;
}
@@ -383,15 +385,8 @@ int braille_unregister_console(struct console *console)
{
if (braille_co != console)
return -EINVAL;
+ unregister_keyboard_notifier(&keyboard_notifier_block);
+ unregister_vt_notifier(&vt_notifier_block);
braille_co = NULL;
return 0;
}
-
-static int __init braille_init(void)
-{
- register_keyboard_notifier(&keyboard_notifier_block);
- register_vt_notifier(&vt_notifier_block);
- return 0;
-}
-
-console_initcall(braille_init);
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 735f5ea1747..da49b006bcc 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -259,7 +259,10 @@ config ACPI_ASUS
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
- depends on X86
+ depends on X86 && INPUT
+ select INPUT_POLLDEV
+ select NET
+ select RFKILL
select BACKLIGHT_CLASS_DEVICE
---help---
This driver adds support for access to certain system settings
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 1022e38994c..0f280589921 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -496,7 +496,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
arg = arg->common.next;
}
- ACPI_ERROR((AE_INFO,
+ ACPI_WARNING((AE_INFO,
"Package List length (%X) larger than NumElements count (%X), truncated\n",
i, element_count));
} else if (i < element_count) {
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 084109507c9..24649ada08d 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
- if (acpi_dev->wakeup.flags.valid)
+ if (acpi_dev->wakeup.flags.valid) {
device_set_wakeup_capable(dev, true);
+ device_set_wakeup_enable(dev,
+ acpi_dev->wakeup.state.enabled);
+ }
}
return 0;
@@ -257,116 +260,3 @@ static int __init init_acpi_device_notify(void)
}
arch_initcall(init_acpi_device_notify);
-
-
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
-
-#ifdef CONFIG_PM
-static u32 rtc_handler(void *context)
-{
- acpi_clear_event(ACPI_EVENT_RTC);
- acpi_disable_event(ACPI_EVENT_RTC, 0);
- return ACPI_INTERRUPT_HANDLED;
-}
-
-static inline void rtc_wake_setup(void)
-{
- acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
- /*
- * After the RTC handler is installed, the Fixed_RTC event should
- * be disabled. Only when the RTC alarm is set will it be enabled.
- */
- acpi_clear_event(ACPI_EVENT_RTC);
- acpi_disable_event(ACPI_EVENT_RTC, 0);
-}
-
-static void rtc_wake_on(struct device *dev)
-{
- acpi_clear_event(ACPI_EVENT_RTC);
- acpi_enable_event(ACPI_EVENT_RTC, 0);
-}
-
-static void rtc_wake_off(struct device *dev)
-{
- acpi_disable_event(ACPI_EVENT_RTC, 0);
-}
-#else
-#define rtc_wake_setup() do{}while(0)
-#define rtc_wake_on NULL
-#define rtc_wake_off NULL
-#endif
-
-/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
- * its device node and pass extra config data. This helps its driver use
- * capabilities that the now-obsolete mc146818 didn't have, and informs it
- * that this board's RTC is wakeup-capable (per ACPI spec).
- */
-#include <linux/mc146818rtc.h>
-
-static struct cmos_rtc_board_info rtc_info;
-
-
-/* PNP devices are registered in a subsys_initcall();
- * ACPI specifies the PNP IDs to use.
- */
-#include <linux/pnp.h>
-
-static int __init pnp_match(struct device *dev, void *data)
-{
- static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
- struct pnp_dev *pnp = to_pnp_dev(dev);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ids); i++) {
- if (compare_pnp_id(pnp->id, ids[i]) != 0)
- return 1;
- }
- return 0;
-}
-
-static struct device *__init get_rtc_dev(void)
-{
- return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
-}
-
-static int __init acpi_rtc_init(void)
-{
- struct device *dev = get_rtc_dev();
-
- if (acpi_disabled)
- return 0;
-
- if (dev) {
- rtc_wake_setup();
- rtc_info.wake_on = rtc_wake_on;
- rtc_info.wake_off = rtc_wake_off;
-
- /* workaround bug in some ACPI tables */
- if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
- DBG("bogus FADT month_alarm\n");
- acpi_gbl_FADT.month_alarm = 0;
- }
-
- rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
- rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
- rtc_info.rtc_century = acpi_gbl_FADT.century;
-
- /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */
- if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
- printk(PREFIX "RTC can wake from S4\n");
-
-
- dev->platform_data = &rtc_info;
-
- /* RTC always wakes from S1/S2/S3, and often S4/STD */
- device_init_wakeup(dev, 1);
-
- put_device(dev);
- } else
- DBG("RTC unavailable?\n");
- return 0;
-}
-/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
-fs_initcall(acpi_rtc_init);
-
-#endif
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index d3f0a62efcc..ee68ac54c0d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -138,7 +138,7 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
{
set_no_mwait, "Extensa 5220", {
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
- DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
{},
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 80e32093e97..80c251ec6d2 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -71,7 +71,7 @@ static DEFINE_MUTEX(performance_mutex);
* 1 -> ignore _PPC totally -> forced by user through boot param
*/
static int ignore_ppc = -1;
-module_param(ignore_ppc, uint, 0644);
+module_param(ignore_ppc, int, 0644);
MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
"limited by BIOS, this should help");
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index bcf2c70fca8..a4e3767b8c6 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -107,6 +107,13 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
if (wait_event_timeout(hc->wait, smb_check_done(hc),
msecs_to_jiffies(timeout)))
return 0;
+ /*
+ * After the timeout happens, OS will try to check the status of SMbus.
+ * If the status is what OS expected, it will be regarded as the bogus
+ * timeout.
+ */
+ if (smb_check_done(hc))
+ return 0;
else
return -ETIME;
}
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 4ebbba2b6b1..bf5b04de02d 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
return 0;
}
+static void physical_device_enable_wakeup(struct acpi_device *adev)
+{
+ struct device *dev = acpi_get_physical_device(adev->handle);
+
+ if (dev && device_can_wakeup(dev))
+ device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
+}
+
static ssize_t
acpi_system_write_wakeup_device(struct file *file,
const char __user * buffer,
@@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file,
}
}
if (found_dev) {
+ physical_device_enable_wakeup(found_dev);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev = container_of(node,
struct
@@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file,
dev->pnp.bus_id, found_dev->pnp.bus_id);
dev->wakeup.state.enabled =
found_dev->wakeup.state.enabled;
+ physical_device_enable_wakeup(dev);
}
}
}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index c3419182c9a..775c97a282b 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -300,6 +300,8 @@ int __init acpi_table_init(void)
static int __init acpi_parse_apic_instance(char *str)
{
+ if (!str)
+ return -EINVAL;
acpi_apic_instance = simple_strtoul(str, NULL, 0);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 0a43c8e0eff..8a649f40d16 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -3,6 +3,7 @@
*
*
* Copyright (C) 2002-2004 John Belmonte
+ * Copyright (C) 2008 Philip Langdale
*
* 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
@@ -33,7 +34,7 @@
*
*/
-#define TOSHIBA_ACPI_VERSION "0.18"
+#define TOSHIBA_ACPI_VERSION "0.19"
#define PROC_INTERFACE_VERSION 1
#include <linux/kernel.h>
@@ -42,6 +43,9 @@
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+#include <linux/input-polldev.h>
#include <asm/uaccess.h>
@@ -90,6 +94,7 @@ MODULE_LICENSE("GPL");
#define HCI_VIDEO_OUT 0x001c
#define HCI_HOTKEY_EVENT 0x001e
#define HCI_LCD_BRIGHTNESS 0x002a
+#define HCI_WIRELESS 0x0056
/* field definitions */
#define HCI_LCD_BRIGHTNESS_BITS 3
@@ -98,9 +103,14 @@ MODULE_LICENSE("GPL");
#define HCI_VIDEO_OUT_LCD 0x1
#define HCI_VIDEO_OUT_CRT 0x2
#define HCI_VIDEO_OUT_TV 0x4
+#define HCI_WIRELESS_KILL_SWITCH 0x01
+#define HCI_WIRELESS_BT_PRESENT 0x0f
+#define HCI_WIRELESS_BT_ATTACH 0x40
+#define HCI_WIRELESS_BT_POWER 0x80
static const struct acpi_device_id toshiba_device_ids[] = {
{"TOS6200", 0},
+ {"TOS6208", 0},
{"TOS1900", 0},
{"", 0},
};
@@ -193,7 +203,7 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
return status;
}
-/* common hci tasks (get or set one value)
+/* common hci tasks (get or set one or two value)
*
* In addition to the ACPI status, the HCI system returns a result which
* may be useful (such as "not supported").
@@ -218,6 +228,152 @@ static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
return status;
}
+static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result)
+{
+ u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(in, out);
+ *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ return status;
+}
+
+static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
+{
+ u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(in, out);
+ *out1 = out[2];
+ *out2 = out[3];
+ *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ return status;
+}
+
+struct toshiba_acpi_dev {
+ struct platform_device *p_dev;
+ struct rfkill *rfk_dev;
+ struct input_polled_dev *poll_dev;
+
+ const char *bt_name;
+ const char *rfk_name;
+
+ bool last_rfk_state;
+
+ struct mutex mutex;
+};
+
+static struct toshiba_acpi_dev toshiba_acpi = {
+ .bt_name = "Toshiba Bluetooth",
+ .rfk_name = "Toshiba RFKill Switch",
+ .last_rfk_state = false,
+};
+
+/* Bluetooth rfkill handlers */
+
+static u32 hci_get_bt_present(bool *present)
+{
+ u32 hci_result;
+ u32 value, value2;
+
+ value = 0;
+ value2 = 0;
+ hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ if (hci_result == HCI_SUCCESS)
+ *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
+
+ return hci_result;
+}
+
+static u32 hci_get_bt_on(bool *on)
+{
+ u32 hci_result;
+ u32 value, value2;
+
+ value = 0;
+ value2 = 0x0001;
+ hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ if (hci_result == HCI_SUCCESS)
+ *on = (value & HCI_WIRELESS_BT_POWER) &&
+ (value & HCI_WIRELESS_BT_ATTACH);
+
+ return hci_result;
+}
+
+static u32 hci_get_radio_state(bool *radio_state)
+{
+ u32 hci_result;
+ u32 value, value2;
+
+ value = 0;
+ value2 = 0x0001;
+ hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+
+ *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
+ return hci_result;
+}
+
+static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state)
+{
+ u32 result1, result2;
+ u32 value;
+ bool radio_state;
+ struct toshiba_acpi_dev *dev = data;
+
+ value = (state == RFKILL_STATE_UNBLOCKED);
+
+ if (hci_get_radio_state(&radio_state) != HCI_SUCCESS)
+ return -EFAULT;
+
+ switch (state) {
+ case RFKILL_STATE_UNBLOCKED:
+ if (!radio_state)
+ return -EPERM;
+ break;
+ case RFKILL_STATE_SOFT_BLOCKED:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->mutex);
+ hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
+ hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
+ mutex_unlock(&dev->mutex);
+
+ if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
+ return -EFAULT;
+
+ return 0;
+}
+
+static void bt_poll_rfkill(struct input_polled_dev *poll_dev)
+{
+ bool state_changed;
+ bool new_rfk_state;
+ bool value;
+ u32 hci_result;
+ struct toshiba_acpi_dev *dev = poll_dev->private;
+
+ hci_result = hci_get_radio_state(&value);
+ if (hci_result != HCI_SUCCESS)
+ return; /* Can't do anything useful */
+
+ new_rfk_state = value;
+
+ mutex_lock(&dev->mutex);
+ state_changed = new_rfk_state != dev->last_rfk_state;
+ dev->last_rfk_state = new_rfk_state;
+ mutex_unlock(&dev->mutex);
+
+ if (unlikely(state_changed)) {
+ rfkill_force_state(dev->rfk_dev,
+ new_rfk_state ?
+ RFKILL_STATE_SOFT_BLOCKED :
+ RFKILL_STATE_HARD_BLOCKED);
+ input_report_switch(poll_dev->input, SW_RFKILL_ALL,
+ new_rfk_state);
+ }
+}
+
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
static struct backlight_device *toshiba_backlight_device;
static int force_fan;
@@ -547,6 +703,14 @@ static struct backlight_ops toshiba_backlight_data = {
static void toshiba_acpi_exit(void)
{
+ if (toshiba_acpi.poll_dev) {
+ input_unregister_polled_device(toshiba_acpi.poll_dev);
+ input_free_polled_device(toshiba_acpi.poll_dev);
+ }
+
+ if (toshiba_acpi.rfk_dev)
+ rfkill_unregister(toshiba_acpi.rfk_dev);
+
if (toshiba_backlight_device)
backlight_device_unregister(toshiba_backlight_device);
@@ -555,6 +719,8 @@ static void toshiba_acpi_exit(void)
if (toshiba_proc_dir)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ platform_device_unregister(toshiba_acpi.p_dev);
+
return;
}
@@ -562,6 +728,10 @@ static int __init toshiba_acpi_init(void)
{
acpi_status status = AE_OK;
u32 hci_result;
+ bool bt_present;
+ bool bt_on;
+ bool radio_on;
+ int ret = 0;
if (acpi_disabled)
return -ENODEV;
@@ -578,6 +748,18 @@ static int __init toshiba_acpi_init(void)
TOSHIBA_ACPI_VERSION);
printk(MY_INFO " HCI method: %s\n", method_hci);
+ mutex_init(&toshiba_acpi.mutex);
+
+ toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi",
+ -1, NULL, 0);
+ if (IS_ERR(toshiba_acpi.p_dev)) {
+ ret = PTR_ERR(toshiba_acpi.p_dev);
+ printk(MY_ERR "unable to register platform device\n");
+ toshiba_acpi.p_dev = NULL;
+ toshiba_acpi_exit();
+ return ret;
+ }
+
force_fan = 0;
key_event_valid = 0;
@@ -586,19 +768,23 @@ static int __init toshiba_acpi_init(void)
toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
if (!toshiba_proc_dir) {
- status = AE_ERROR;
+ toshiba_acpi_exit();
+ return -ENODEV;
} else {
toshiba_proc_dir->owner = THIS_MODULE;
status = add_device();
- if (ACPI_FAILURE(status))
- remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ if (ACPI_FAILURE(status)) {
+ toshiba_acpi_exit();
+ return -ENODEV;
+ }
}
- toshiba_backlight_device = backlight_device_register("toshiba",NULL,
+ toshiba_backlight_device = backlight_device_register("toshiba",
+ &toshiba_acpi.p_dev->dev,
NULL,
&toshiba_backlight_data);
if (IS_ERR(toshiba_backlight_device)) {
- int ret = PTR_ERR(toshiba_backlight_device);
+ ret = PTR_ERR(toshiba_backlight_device);
printk(KERN_ERR "Could not register toshiba backlight device\n");
toshiba_backlight_device = NULL;
@@ -607,7 +793,66 @@ static int __init toshiba_acpi_init(void)
}
toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
- return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
+ /* Register rfkill switch for Bluetooth */
+ if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
+ toshiba_acpi.rfk_dev = rfkill_allocate(&toshiba_acpi.p_dev->dev,
+ RFKILL_TYPE_BLUETOOTH);
+ if (!toshiba_acpi.rfk_dev) {
+ printk(MY_ERR "unable to allocate rfkill device\n");
+ toshiba_acpi_exit();
+ return -ENOMEM;
+ }
+
+ toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name;
+ toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio;
+ toshiba_acpi.rfk_dev->user_claim_unsupported = 1;
+ toshiba_acpi.rfk_dev->data = &toshiba_acpi;
+
+ if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) {
+ toshiba_acpi.rfk_dev->state = RFKILL_STATE_UNBLOCKED;
+ } else if (hci_get_radio_state(&radio_on) == HCI_SUCCESS &&
+ radio_on) {
+ toshiba_acpi.rfk_dev->state = RFKILL_STATE_SOFT_BLOCKED;
+ } else {
+ toshiba_acpi.rfk_dev->state = RFKILL_STATE_HARD_BLOCKED;
+ }
+
+ ret = rfkill_register(toshiba_acpi.rfk_dev);
+ if (ret) {
+ printk(MY_ERR "unable to register rfkill device\n");
+ toshiba_acpi_exit();
+ return -ENOMEM;
+ }
+ }
+
+ /* Register input device for kill switch */
+ toshiba_acpi.poll_dev = input_allocate_polled_device();
+ if (!toshiba_acpi.poll_dev) {
+ printk(MY_ERR "unable to allocate kill-switch input device\n");
+ toshiba_acpi_exit();
+ return -ENOMEM;
+ }
+ toshiba_acpi.poll_dev->private = &toshiba_acpi;
+ toshiba_acpi.poll_dev->poll = bt_poll_rfkill;
+ toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */
+
+ toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name;
+ toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST;
+ toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */
+ set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit);
+ set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit);
+ input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE);
+
+ ret = input_register_polled_device(toshiba_acpi.poll_dev);
+ if (ret) {
+ printk(MY_ERR "unable to register kill-switch input device\n");
+ rfkill_free(toshiba_acpi.rfk_dev);
+ toshiba_acpi.rfk_dev = NULL;
+ toshiba_acpi_exit();
+ return ret;
+ }
+
+ return 0;
}
module_init(toshiba_acpi_init);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ae8494944c4..78fbec8ceda 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -7,7 +7,6 @@ menuconfig ATA
depends on HAS_IOMEM
depends on BLOCK
depends on !(M32R || M68K) || BROKEN
- depends on !SUN4 || BROKEN
select SCSI
---help---
If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
@@ -448,8 +447,10 @@ config PATA_MARVELL
tristate "Marvell PATA support via legacy mode"
depends on PCI
help
- This option enables limited support for the Marvell 88SE6145 ATA
- controller.
+ This option enables limited support for the Marvell 88SE61xx ATA
+ controllers. If you wish to use only the SATA ports then select
+ the AHCI driver alone. If you wish to the use the PATA port or
+ both SATA and PATA include this driver.
If unsure, say N.
@@ -661,7 +662,7 @@ config HAVE_PATA_PLATFORM
config PATA_PLATFORM
tristate "Generic platform device PATA support"
- depends on EMBEDDED || ARCH_RPC || PPC || HAVE_PATA_PLATFORM
+ depends on EMBEDDED || PPC || HAVE_PATA_PLATFORM
help
This option enables support for generic directly connected ATA
devices commonly found on embedded systems.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c729e6988bb..aeadd00411a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -267,8 +267,8 @@ struct ahci_port_priv {
* per PM slot */
};
-static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
@@ -316,6 +316,7 @@ static struct device_attribute *ahci_shost_attrs[] = {
static struct device_attribute *ahci_sdev_attrs[] = {
&dev_attr_sw_activity,
+ &dev_attr_unload_heads,
NULL
};
@@ -420,7 +421,7 @@ static const struct ata_port_info ahci_port_info[] = {
/* board_ahci_mv */
{
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
- AHCI_HFLAG_MV_PATA),
+ AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
.pio_mask = 0x1f, /* pio0-4 */
@@ -487,7 +488,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -610,6 +613,15 @@ module_param(ahci_em_messages, int, 0444);
MODULE_PARM_DESC(ahci_em_messages,
"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
+#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
+static int marvell_enable;
+#else
+static int marvell_enable = 1;
+#endif
+module_param(marvell_enable, int, 0644);
+MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
+
+
static inline int ahci_nr_ports(u32 cap)
{
return (cap & 0x1f) + 1;
@@ -732,6 +744,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
"MV_AHCI HACK: port_map %x -> %x\n",
port_map,
port_map & mv);
+ dev_printk(KERN_ERR, &pdev->dev,
+ "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
port_map &= mv;
}
@@ -807,10 +821,10 @@ static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
return 0;
}
-static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
- void __iomem *port_mmio = ahci_port_base(ap);
- int offset = ahci_scr_offset(ap, sc_reg);
+ void __iomem *port_mmio = ahci_port_base(link->ap);
+ int offset = ahci_scr_offset(link->ap, sc_reg);
if (offset) {
*val = readl(port_mmio + offset);
@@ -819,10 +833,10 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return -EINVAL;
}
-static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
- void __iomem *port_mmio = ahci_port_base(ap);
- int offset = ahci_scr_offset(ap, sc_reg);
+ void __iomem *port_mmio = ahci_port_base(link->ap);
+ int offset = ahci_scr_offset(link->ap, sc_reg);
if (offset) {
writel(val, port_mmio + offset);
@@ -960,7 +974,7 @@ static void ahci_disable_alpm(struct ata_port *ap)
writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
/* go ahead and clean out PhyRdy Change from Serror too */
- ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+ ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
/*
* Clear flag to indicate that we should ignore all PhyRdy
@@ -1924,8 +1938,8 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
/* AHCI needs SError cleared; otherwise, it might lock up */
- ahci_scr_read(ap, SCR_ERROR, &serror);
- ahci_scr_write(ap, SCR_ERROR, serror);
+ ahci_scr_read(&ap->link, SCR_ERROR, &serror);
+ ahci_scr_write(&ap->link, SCR_ERROR, serror);
host_ehi->serror |= serror;
/* some controllers set IRQ_IF_ERR on device errors, ignore it */
@@ -2014,7 +2028,7 @@ static void ahci_port_intr(struct ata_port *ap)
if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
(status & PORT_IRQ_PHYRDY)) {
status &= ~PORT_IRQ_PHYRDY;
- ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+ ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
}
if (unlikely(status & PORT_IRQ_ERROR)) {
@@ -2533,6 +2547,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* The AHCI driver can only drive the SATA ports, the PATA driver
+ can drive them all so if both drivers are selected make sure
+ AHCI stays out of the way */
+ if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
+ return -ENODEV;
+
/* acquire resources */
rc = pcim_enable_device(pdev);
if (rc)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index b1d08a8f500..e9e32ed6b1a 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -165,8 +165,10 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
+static int piix_sidpr_scr_read(struct ata_link *link,
+ unsigned int reg, u32 *val);
+static int piix_sidpr_scr_write(struct ata_link *link,
+ unsigned int reg, u32 val);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -278,12 +280,15 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* SATA Controller IDE (PCH) */
+ { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (PCH) */
+ { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
-
{ } /* terminate list */
};
@@ -582,6 +587,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
+ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
{ 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */
{ 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
@@ -885,23 +891,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* Serial ATA Index/Data Pair Superset Registers access
*
* Beginning from ICH8, there's a sane way to access SCRs using index
- * and data register pair located at BAR5. This creates an
- * interesting problem of mapping two SCRs to one port.
- *
- * Although they have separate SCRs, the master and slave aren't
- * independent enough to be treated as separate links - e.g. softreset
- * resets both. Also, there's no protocol defined for hard resetting
- * singled device sharing the virtual port (no defined way to acquire
- * device signature). This is worked around by merging the SCR values
- * into one sensible value and requesting follow-up SRST after
- * hardreset.
- *
- * SCR merging is perfomed in nibbles which is the unit contents in
- * SCRs are organized. If two values are equal, the value is used.
- * When they differ, merge table which lists precedence of possible
- * values is consulted and the first match or the last entry when
- * nothing matches is used. When there's no merge table for the
- * specific nibble, value from the first port is used.
+ * and data register pair located at BAR5 which means that we have
+ * separate SCRs for master and slave. This is handled using libata
+ * slave_link facility.
*/
static const int piix_sidx_map[] = {
[SCR_STATUS] = 0,
@@ -909,120 +901,38 @@ static const int piix_sidx_map[] = {
[SCR_CONTROL] = 1,
};
-static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
+static void piix_sidpr_sel(struct ata_link *link, unsigned int reg)
{
- struct ata_port *ap = dev->link->ap;
+ struct ata_port *ap = link->ap;
struct piix_host_priv *hpriv = ap->host->private_data;
- iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
+ iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg],
hpriv->sidpr + PIIX_SIDPR_IDX);
}
-static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
-{
- struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
- piix_sidpr_sel(dev, reg);
- return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
-{
- struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
- piix_sidpr_sel(dev, reg);
- iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
-{
- u32 val = 0;
- int i, mi;
-
- for (i = 0, mi = 0; i < 32 / 4; i++) {
- u8 c0 = (val0 >> (i * 4)) & 0xf;
- u8 c1 = (val1 >> (i * 4)) & 0xf;
- u8 merged = c0;
- const int *cur;
-
- /* if no merge preference, assume the first value */
- cur = merge_tbl[mi];
- if (!cur)
- goto done;
- mi++;
-
- /* if two values equal, use it */
- if (c0 == c1)
- goto done;
-
- /* choose the first match or the last from the merge table */
- while (*cur != -1) {
- if (c0 == *cur || c1 == *cur)
- break;
- cur++;
- }
- if (*cur == -1)
- cur--;
- merged = *cur;
- done:
- val |= merged << (i * 4);
- }
-
- return val;
-}
-
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
+static int piix_sidpr_scr_read(struct ata_link *link,
+ unsigned int reg, u32 *val)
{
- const int * const sstatus_merge_tbl[] = {
- /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
- /* SPD */ (const int []){ 2, 1, 0, -1 },
- /* IPM */ (const int []){ 6, 2, 1, 0, -1 },
- NULL,
- };
- const int * const scontrol_merge_tbl[] = {
- /* DET */ (const int []){ 1, 0, 4, 0, -1 },
- /* SPD */ (const int []){ 0, 2, 1, 0, -1 },
- /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
- NULL,
- };
- u32 v0, v1;
+ struct piix_host_priv *hpriv = link->ap->host->private_data;
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
- if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
- *val = piix_sidpr_read(&ap->link.device[0], reg);
- return 0;
- }
-
- v0 = piix_sidpr_read(&ap->link.device[0], reg);
- v1 = piix_sidpr_read(&ap->link.device[1], reg);
-
- switch (reg) {
- case SCR_STATUS:
- *val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
- break;
- case SCR_ERROR:
- *val = v0 | v1;
- break;
- case SCR_CONTROL:
- *val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
- break;
- }
-
+ piix_sidpr_sel(link, reg);
+ *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
return 0;
}
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
+static int piix_sidpr_scr_write(struct ata_link *link,
+ unsigned int reg, u32 val)
{
+ struct piix_host_priv *hpriv = link->ap->host->private_data;
+
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
- piix_sidpr_write(&ap->link.device[0], reg, val);
-
- if (ap->flags & ATA_FLAG_SLAVE_POSS)
- piix_sidpr_write(&ap->link.device[1], reg, val);
-
+ piix_sidpr_sel(link, reg);
+ iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
return 0;
}
@@ -1363,28 +1273,28 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
return map;
}
-static void __devinit piix_init_sidpr(struct ata_host *host)
+static int __devinit piix_init_sidpr(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
struct piix_host_priv *hpriv = host->private_data;
- struct ata_device *dev0 = &host->ports[0]->link.device[0];
+ struct ata_link *link0 = &host->ports[0]->link;
u32 scontrol;
- int i;
+ int i, rc;
/* check for availability */
for (i = 0; i < 4; i++)
if (hpriv->map[i] == IDE)
- return;
+ return 0;
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
- return;
+ return 0;
if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
- return;
+ return 0;
if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
- return;
+ return 0;
hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
@@ -1392,7 +1302,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
* Give it a test drive by inhibiting power save modes which
* we'll do anyway.
*/
- scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+ piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
/* if IPM is already 3, SCR access is probably working. Don't
* un-inhibit power save modes as BIOS might have inhibited
@@ -1400,18 +1310,30 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
*/
if ((scontrol & 0xf00) != 0x300) {
scontrol |= 0x300;
- piix_sidpr_write(dev0, SCR_CONTROL, scontrol);
- scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+ piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol);
+ piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
if ((scontrol & 0xf00) != 0x300) {
dev_printk(KERN_INFO, host->dev, "SCR access via "
"SIDPR is available but doesn't work\n");
- return;
+ return 0;
}
}
- host->ports[0]->ops = &piix_sidpr_sata_ops;
- host->ports[1]->ops = &piix_sidpr_sata_ops;
+ /* okay, SCRs available, set ops and ask libata for slave_link */
+ for (i = 0; i < 2; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ ap->ops = &piix_sidpr_sata_ops;
+
+ if (ap->flags & ATA_FLAG_SLAVE_POSS) {
+ rc = ata_slave_link_init(ap);
+ if (rc)
+ return rc;
+ }
+ }
+
+ return 0;
}
static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
@@ -1499,7 +1421,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
* off.
*/
if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) {
- int rc = piix_disable_ahci(pdev);
+ rc = piix_disable_ahci(pdev);
if (rc)
return rc;
}
@@ -1521,7 +1443,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
/* initialize controller */
if (port_flags & ATA_FLAG_SATA) {
piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
- piix_init_sidpr(host);
+ rc = piix_init_sidpr(host);
+ if (rc)
+ return rc;
}
/* apply IOCFG bit18 quirk */
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 79e3a8e7a84..1ee9499bd34 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -163,6 +163,67 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+/*
+ * Iterator helpers. Don't use directly.
+ *
+ * LOCKING:
+ * Host lock or EH context.
+ */
+struct ata_link *__ata_port_next_link(struct ata_port *ap,
+ struct ata_link *link, bool dev_only)
+{
+ /* NULL link indicates start of iteration */
+ if (!link) {
+ if (dev_only && sata_pmp_attached(ap))
+ return ap->pmp_link;
+ return &ap->link;
+ }
+
+ /* we just iterated over the host master link, what's next? */
+ if (link == &ap->link) {
+ if (!sata_pmp_attached(ap)) {
+ if (unlikely(ap->slave_link) && !dev_only)
+ return ap->slave_link;
+ return NULL;
+ }
+ return ap->pmp_link;
+ }
+
+ /* slave_link excludes PMP */
+ if (unlikely(link == ap->slave_link))
+ return NULL;
+
+ /* iterate to the next PMP link */
+ if (++link < ap->pmp_link + ap->nr_pmp_links)
+ return link;
+ return NULL;
+}
+
+/**
+ * ata_dev_phys_link - find physical link for a device
+ * @dev: ATA device to look up physical link for
+ *
+ * Look up physical link which @dev is attached to. Note that
+ * this is different from @dev->link only when @dev is on slave
+ * link. For all other cases, it's the same as @dev->link.
+ *
+ * LOCKING:
+ * Don't care.
+ *
+ * RETURNS:
+ * Pointer to the found physical link.
+ */
+struct ata_link *ata_dev_phys_link(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->link->ap;
+
+ if (!ap->slave_link)
+ return dev->link;
+ if (!dev->devno)
+ return &ap->link;
+ return ap->slave_link;
+}
+
/**
* ata_force_cbl - force cable type according to libata.force
* @ap: ATA port of interest
@@ -206,7 +267,8 @@ void ata_force_cbl(struct ata_port *ap)
* the host link and all fan-out ports connected via PMP. If the
* device part is specified as 0 (e.g. 1.00:), it specifies the
* first fan-out link not the host link. Device number 15 always
- * points to the host link whether PMP is attached or not.
+ * points to the host link whether PMP is attached or not. If the
+ * controller has slave link, device number 16 points to it.
*
* LOCKING:
* EH context.
@@ -214,12 +276,11 @@ void ata_force_cbl(struct ata_port *ap)
static void ata_force_link_limits(struct ata_link *link)
{
bool did_spd = false;
- int linkno, i;
+ int linkno = link->pmp;
+ int i;
if (ata_is_host_link(link))
- linkno = 15;
- else
- linkno = link->pmp;
+ linkno += 15;
for (i = ata_force_tbl_size - 1; i >= 0; i--) {
const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -266,9 +327,9 @@ static void ata_force_xfermask(struct ata_device *dev)
int alt_devno = devno;
int i;
- /* allow n.15 for the first device attached to host port */
- if (ata_is_host_link(dev->link) && devno == 0)
- alt_devno = 15;
+ /* allow n.15/16 for devices attached to host port */
+ if (ata_is_host_link(dev->link))
+ alt_devno += 15;
for (i = ata_force_tbl_size - 1; i >= 0; i--) {
const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -320,9 +381,9 @@ static void ata_force_horkage(struct ata_device *dev)
int alt_devno = devno;
int i;
- /* allow n.15 for the first device attached to host port */
- if (ata_is_host_link(dev->link) && devno == 0)
- alt_devno = 15;
+ /* allow n.15/16 for devices attached to host port */
+ if (ata_is_host_link(dev->link))
+ alt_devno += 15;
for (i = 0; i < ata_force_tbl_size; i++) {
const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -2681,7 +2742,7 @@ static void sata_print_link_status(struct ata_link *link)
return;
sata_scr_read(link, SCR_CONTROL, &scontrol);
- if (ata_link_online(link)) {
+ if (ata_phys_link_online(link)) {
tmp = (sstatus >> 4) & 0xf;
ata_link_printk(link, KERN_INFO,
"SATA link up %s (SStatus %X SControl %X)\n",
@@ -3372,6 +3433,12 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
unsigned long nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT);
int warned = 0;
+ /* Slave readiness can't be tested separately from master. On
+ * M/S emulation configuration, this function should be called
+ * only on the master and it will handle both master and slave.
+ */
+ WARN_ON(link == link->ap->slave_link);
+
if (time_after(nodev_deadline, deadline))
nodev_deadline = deadline;
@@ -3593,7 +3660,7 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
}
/* no point in trying softreset on offline link */
- if (ata_link_offline(link))
+ if (ata_phys_link_offline(link))
ehc->i.action &= ~ATA_EH_SOFTRESET;
return 0;
@@ -3671,7 +3738,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
if (rc)
goto out;
/* if link is offline nothing more to do */
- if (ata_link_offline(link))
+ if (ata_phys_link_offline(link))
goto out;
/* Link is online. From this point, -ENODEV too is an error. */
@@ -4868,10 +4935,8 @@ int sata_scr_valid(struct ata_link *link)
int sata_scr_read(struct ata_link *link, int reg, u32 *val)
{
if (ata_is_host_link(link)) {
- struct ata_port *ap = link->ap;
-
if (sata_scr_valid(link))
- return ap->ops->scr_read(ap, reg, val);
+ return link->ap->ops->scr_read(link, reg, val);
return -EOPNOTSUPP;
}
@@ -4897,10 +4962,8 @@ int sata_scr_read(struct ata_link *link, int reg, u32 *val)
int sata_scr_write(struct ata_link *link, int reg, u32 val)
{
if (ata_is_host_link(link)) {
- struct ata_port *ap = link->ap;
-
if (sata_scr_valid(link))
- return ap->ops->scr_write(ap, reg, val);
+ return link->ap->ops->scr_write(link, reg, val);
return -EOPNOTSUPP;
}
@@ -4925,13 +4988,12 @@ int sata_scr_write(struct ata_link *link, int reg, u32 val)
int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
{
if (ata_is_host_link(link)) {
- struct ata_port *ap = link->ap;
int rc;
if (sata_scr_valid(link)) {
- rc = ap->ops->scr_write(ap, reg, val);
+ rc = link->ap->ops->scr_write(link, reg, val);
if (rc == 0)
- rc = ap->ops->scr_read(ap, reg, &val);
+ rc = link->ap->ops->scr_read(link, reg, &val);
return rc;
}
return -EOPNOTSUPP;
@@ -4941,7 +5003,7 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
}
/**
- * ata_link_online - test whether the given link is online
+ * ata_phys_link_online - test whether the given link is online
* @link: ATA link to test
*
* Test whether @link is online. Note that this function returns
@@ -4952,20 +5014,20 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
* None.
*
* RETURNS:
- * 1 if the port online status is available and online.
+ * True if the port online status is available and online.
*/
-int ata_link_online(struct ata_link *link)
+bool ata_phys_link_online(struct ata_link *link)
{
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
(sstatus & 0xf) == 0x3)
- return 1;
- return 0;
+ return true;
+ return false;
}
/**
- * ata_link_offline - test whether the given link is offline
+ * ata_phys_link_offline - test whether the given link is offline
* @link: ATA link to test
*
* Test whether @link is offline. Note that this function
@@ -4976,16 +5038,68 @@ int ata_link_online(struct ata_link *link)
* None.
*
* RETURNS:
- * 1 if the port offline status is available and offline.
+ * True if the port offline status is available and offline.
*/
-int ata_link_offline(struct ata_link *link)
+bool ata_phys_link_offline(struct ata_link *link)
{
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
(sstatus & 0xf) != 0x3)
- return 1;
- return 0;
+ return true;
+ return false;
+}
+
+/**
+ * ata_link_online - test whether the given link is online
+ * @link: ATA link to test
+ *
+ * Test whether @link is online. This is identical to
+ * ata_phys_link_online() when there's no slave link. When
+ * there's a slave link, this function should only be called on
+ * the master link and will return true if any of M/S links is
+ * online.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * True if the port online status is available and online.
+ */
+bool ata_link_online(struct ata_link *link)
+{
+ struct ata_link *slave = link->ap->slave_link;
+
+ WARN_ON(link == slave); /* shouldn't be called on slave link */
+
+ return ata_phys_link_online(link) ||
+ (slave && ata_phys_link_online(slave));
+}
+
+/**
+ * ata_link_offline - test whether the given link is offline
+ * @link: ATA link to test
+ *
+ * Test whether @link is offline. This is identical to
+ * ata_phys_link_offline() when there's no slave link. When
+ * there's a slave link, this function should only be called on
+ * the master link and will return true if both M/S links are
+ * offline.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * True if the port offline status is available and offline.
+ */
+bool ata_link_offline(struct ata_link *link)
+{
+ struct ata_link *slave = link->ap->slave_link;
+
+ WARN_ON(link == slave); /* shouldn't be called on slave link */
+
+ return ata_phys_link_offline(link) &&
+ (!slave || ata_phys_link_offline(slave));
}
#ifdef CONFIG_PM
@@ -5127,11 +5241,11 @@ int ata_port_start(struct ata_port *ap)
*/
void ata_dev_init(struct ata_device *dev)
{
- struct ata_link *link = dev->link;
+ struct ata_link *link = ata_dev_phys_link(dev);
struct ata_port *ap = link->ap;
unsigned long flags;
- /* SATA spd limit is bound to the first device */
+ /* SATA spd limit is bound to the attached device, reset together */
link->sata_spd_limit = link->hw_sata_spd_limit;
link->sata_spd = 0;
@@ -5264,6 +5378,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
+ init_completion(&ap->park_req_pending);
init_timer_deferrable(&ap->fastdrain_timer);
ap->fastdrain_timer.function = ata_eh_fastdrain_timerfn;
ap->fastdrain_timer.data = (unsigned long)ap;
@@ -5294,6 +5409,7 @@ static void ata_host_release(struct device *gendev, void *res)
scsi_host_put(ap->scsi_host);
kfree(ap->pmp_link);
+ kfree(ap->slave_link);
kfree(ap);
host->ports[i] = NULL;
}
@@ -5414,6 +5530,68 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
return host;
}
+/**
+ * ata_slave_link_init - initialize slave link
+ * @ap: port to initialize slave link for
+ *
+ * Create and initialize slave link for @ap. This enables slave
+ * link handling on the port.
+ *
+ * In libata, a port contains links and a link contains devices.
+ * There is single host link but if a PMP is attached to it,
+ * there can be multiple fan-out links. On SATA, there's usually
+ * a single device connected to a link but PATA and SATA
+ * controllers emulating TF based interface can have two - master
+ * and slave.
+ *
+ * However, there are a few controllers which don't fit into this
+ * abstraction too well - SATA controllers which emulate TF
+ * interface with both master and slave devices but also have
+ * separate SCR register sets for each device. These controllers
+ * need separate links for physical link handling
+ * (e.g. onlineness, link speed) but should be treated like a
+ * traditional M/S controller for everything else (e.g. command
+ * issue, softreset).
+ *
+ * slave_link is libata's way of handling this class of
+ * controllers without impacting core layer too much. For
+ * anything other than physical link handling, the default host
+ * link is used for both master and slave. For physical link
+ * handling, separate @ap->slave_link is used. All dirty details
+ * are implemented inside libata core layer. From LLD's POV, the
+ * only difference is that prereset, hardreset and postreset are
+ * called once more for the slave link, so the reset sequence
+ * looks like the following.
+ *
+ * prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) ->
+ * softreset(M) -> postreset(M) -> postreset(S)
+ *
+ * Note that softreset is called only for the master. Softreset
+ * resets both M/S by definition, so SRST on master should handle
+ * both (the standard method will work just fine).
+ *
+ * LOCKING:
+ * Should be called before host is registered.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int ata_slave_link_init(struct ata_port *ap)
+{
+ struct ata_link *link;
+
+ WARN_ON(ap->slave_link);
+ WARN_ON(ap->flags & ATA_FLAG_PMP);
+
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link)
+ return -ENOMEM;
+
+ ata_link_init(ap, link, 1);
+ ap->slave_link = link;
+ return 0;
+}
+
static void ata_host_stop(struct device *gendev, void *res)
{
struct ata_host *host = dev_get_drvdata(gendev);
@@ -5640,6 +5818,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* init sata_spd_limit to the current value */
sata_link_init_spd(&ap->link);
+ if (ap->slave_link)
+ sata_link_init_spd(ap->slave_link);
/* print per-port info to dmesg */
xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
@@ -6260,10 +6440,12 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops);
EXPORT_SYMBOL_GPL(sata_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_info);
+EXPORT_SYMBOL_GPL(__ata_port_next_link);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_host_init);
EXPORT_SYMBOL_GPL(ata_host_alloc);
EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
+EXPORT_SYMBOL_GPL(ata_slave_link_init);
EXPORT_SYMBOL_GPL(ata_host_start);
EXPORT_SYMBOL_GPL(ata_host_register);
EXPORT_SYMBOL_GPL(ata_host_activate);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c1db2f234d2..a93247cc395 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -33,6 +33,7 @@
*/
#include <linux/kernel.h>
+#include <linux/blkdev.h>
#include <linux/pci.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -79,6 +80,8 @@ enum {
*/
ATA_EH_PRERESET_TIMEOUT = 10000,
ATA_EH_FASTDRAIN_INTERVAL = 3000,
+
+ ATA_EH_UA_TRIES = 5,
};
/* The following table determines how we sequence resets. Each entry
@@ -457,29 +460,29 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev,
* RETURNS:
* EH_HANDLED or EH_NOT_HANDLED
*/
-enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct ata_port *ap = ata_shost_to_port(host);
unsigned long flags;
struct ata_queued_cmd *qc;
- enum scsi_eh_timer_return ret;
+ enum blk_eh_timer_return ret;
DPRINTK("ENTER\n");
if (ap->ops->error_handler) {
- ret = EH_NOT_HANDLED;
+ ret = BLK_EH_NOT_HANDLED;
goto out;
}
- ret = EH_HANDLED;
+ ret = BLK_EH_HANDLED;
spin_lock_irqsave(ap->lock, flags);
qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc) {
WARN_ON(qc->scsicmd != cmd);
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
qc->err_mask |= AC_ERR_TIMEOUT;
- ret = EH_NOT_HANDLED;
+ ret = BLK_EH_NOT_HANDLED;
}
spin_unlock_irqrestore(ap->lock, flags);
@@ -831,7 +834,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
* Note that ATA_QCFLAG_FAILED is unconditionally set after
* this function completes.
*/
- scsi_req_abort_cmd(qc->scsicmd);
+ blk_abort_request(qc->scsicmd->request);
}
/**
@@ -1357,6 +1360,37 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
}
/**
+ * atapi_eh_tur - perform ATAPI TEST_UNIT_READY
+ * @dev: target ATAPI device
+ * @r_sense_key: out parameter for sense_key
+ *
+ * Perform ATAPI TEST_UNIT_READY.
+ *
+ * LOCKING:
+ * EH context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, AC_ERR_* mask on failure.
+ */
+static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
+{
+ u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 };
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+
+ ata_tf_init(dev, &tf);
+
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.command = ATA_CMD_PACKET;
+ tf.protocol = ATAPI_PROT_NODATA;
+
+ err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0);
+ if (err_mask == AC_ERR_DEV)
+ *r_sense_key = tf.feature >> 4;
+ return err_mask;
+}
+
+/**
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @dev: device to perform REQUEST_SENSE to
* @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
@@ -1756,7 +1790,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
static unsigned int ata_eh_speed_down(struct ata_device *dev,
unsigned int eflags, unsigned int err_mask)
{
- struct ata_link *link = dev->link;
+ struct ata_link *link = ata_dev_phys_link(dev);
int xfer_ok = 0;
unsigned int verdict;
unsigned int action = 0;
@@ -1880,7 +1914,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
+ if (!(qc->flags & ATA_QCFLAG_FAILED) ||
+ ata_dev_phys_link(qc->dev) != link)
continue;
/* inherit upper level err_mask */
@@ -1967,6 +2002,23 @@ void ata_eh_autopsy(struct ata_port *ap)
ata_port_for_each_link(link, ap)
ata_eh_link_autopsy(link);
+ /* Handle the frigging slave link. Autopsy is done similarly
+ * but actions and flags are transferred over to the master
+ * link and handled from there.
+ */
+ if (ap->slave_link) {
+ struct ata_eh_context *mehc = &ap->link.eh_context;
+ struct ata_eh_context *sehc = &ap->slave_link->eh_context;
+
+ ata_eh_link_autopsy(ap->slave_link);
+
+ ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
+ mehc->i.action |= sehc->i.action;
+ mehc->i.dev_action[1] |= sehc->i.dev_action[1];
+ mehc->i.flags |= sehc->i.flags;
+ ata_eh_done(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
+ }
+
/* Autopsy of fanout ports can affect host link autopsy.
* Perform host link autopsy last.
*/
@@ -2001,7 +2053,8 @@ static void ata_eh_link_report(struct ata_link *link)
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
- if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link ||
+ if (!(qc->flags & ATA_QCFLAG_FAILED) ||
+ ata_dev_phys_link(qc->dev) != link ||
((qc->flags & ATA_QCFLAG_QUIET) &&
qc->err_mask == AC_ERR_DEV))
continue;
@@ -2068,7 +2121,7 @@ static void ata_eh_link_report(struct ata_link *link)
char cdb_buf[70] = "";
if (!(qc->flags & ATA_QCFLAG_FAILED) ||
- qc->dev->link != link || !qc->err_mask)
+ ata_dev_phys_link(qc->dev) != link || !qc->err_mask)
continue;
if (qc->dma_dir != DMA_NONE) {
@@ -2160,12 +2213,14 @@ void ata_eh_report(struct ata_port *ap)
}
static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
- unsigned int *classes, unsigned long deadline)
+ unsigned int *classes, unsigned long deadline,
+ bool clear_classes)
{
struct ata_device *dev;
- ata_link_for_each_dev(dev, link)
- classes[dev->devno] = ATA_DEV_UNKNOWN;
+ if (clear_classes)
+ ata_link_for_each_dev(dev, link)
+ classes[dev->devno] = ATA_DEV_UNKNOWN;
return reset(link, classes, deadline);
}
@@ -2187,17 +2242,20 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
struct ata_port *ap = link->ap;
+ struct ata_link *slave = ap->slave_link;
struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_eh_context *sehc = &slave->eh_context;
unsigned int *classes = ehc->classes;
unsigned int lflags = link->flags;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
int max_tries = 0, try = 0;
+ struct ata_link *failed_link;
struct ata_device *dev;
unsigned long deadline, now;
ata_reset_fn_t reset;
unsigned long flags;
u32 sstatus;
- int nr_known, rc;
+ int nr_unknown, rc;
/*
* Prepare to reset
@@ -2252,8 +2310,30 @@ int ata_eh_reset(struct ata_link *link, int classify,
}
if (prereset) {
- rc = prereset(link,
- ata_deadline(jiffies, ATA_EH_PRERESET_TIMEOUT));
+ unsigned long deadline = ata_deadline(jiffies,
+ ATA_EH_PRERESET_TIMEOUT);
+
+ if (slave) {
+ sehc->i.action &= ~ATA_EH_RESET;
+ sehc->i.action |= ehc->i.action;
+ }
+
+ rc = prereset(link, deadline);
+
+ /* If present, do prereset on slave link too. Reset
+ * is skipped iff both master and slave links report
+ * -ENOENT or clear ATA_EH_RESET.
+ */
+ if (slave && (rc == 0 || rc == -ENOENT)) {
+ int tmp;
+
+ tmp = prereset(slave, deadline);
+ if (tmp != -ENOENT)
+ rc = tmp;
+
+ ehc->i.action |= sehc->i.action;
+ }
+
if (rc) {
if (rc == -ENOENT) {
ata_link_printk(link, KERN_DEBUG,
@@ -2302,25 +2382,51 @@ int ata_eh_reset(struct ata_link *link, int classify,
else
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
- rc = ata_do_reset(link, reset, classes, deadline);
- if (rc && rc != -EAGAIN)
+ rc = ata_do_reset(link, reset, classes, deadline, true);
+ if (rc && rc != -EAGAIN) {
+ failed_link = link;
goto fail;
+ }
+
+ /* hardreset slave link if existent */
+ if (slave && reset == hardreset) {
+ int tmp;
+
+ if (verbose)
+ ata_link_printk(slave, KERN_INFO,
+ "hard resetting link\n");
+ ata_eh_about_to_do(slave, NULL, ATA_EH_RESET);
+ tmp = ata_do_reset(slave, reset, classes, deadline,
+ false);
+ switch (tmp) {
+ case -EAGAIN:
+ rc = -EAGAIN;
+ case 0:
+ break;
+ default:
+ failed_link = slave;
+ rc = tmp;
+ goto fail;
+ }
+ }
+
+ /* perform follow-up SRST if necessary */
if (reset == hardreset &&
ata_eh_followup_srst_needed(link, rc, classes)) {
- /* okay, let's do follow-up softreset */
reset = softreset;
if (!reset) {
ata_link_printk(link, KERN_ERR,
"follow-up softreset required "
"but no softreset avaliable\n");
+ failed_link = link;
rc = -EINVAL;
goto fail;
}
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
- rc = ata_do_reset(link, reset, classes, deadline);
+ rc = ata_do_reset(link, reset, classes, deadline, true);
}
} else {
if (verbose)
@@ -2341,7 +2447,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
dev->pio_mode = XFER_PIO_0;
dev->flags &= ~ATA_DFLAG_SLEEPING;
- if (ata_link_offline(link))
+ if (ata_phys_link_offline(ata_dev_phys_link(dev)))
continue;
/* apply class override */
@@ -2354,6 +2460,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
/* record current link speed */
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
link->sata_spd = (sstatus >> 4) & 0xf;
+ if (slave && sata_scr_read(slave, SCR_STATUS, &sstatus) == 0)
+ slave->sata_spd = (sstatus >> 4) & 0xf;
/* thaw the port */
if (ata_is_host_link(link))
@@ -2366,12 +2474,17 @@ int ata_eh_reset(struct ata_link *link, int classify,
* reset and here. This race is mediated by cross checking
* link onlineness and classification result later.
*/
- if (postreset)
+ if (postreset) {
postreset(link, classes);
+ if (slave)
+ postreset(slave, classes);
+ }
/* clear cached SError */
spin_lock_irqsave(link->ap->lock, flags);
link->eh_info.serror = 0;
+ if (slave)
+ slave->eh_info.serror = 0;
spin_unlock_irqrestore(link->ap->lock, flags);
/* Make sure onlineness and classification result correspond.
@@ -2381,19 +2494,21 @@ int ata_eh_reset(struct ata_link *link, int classify,
* link onlineness and classification result, those conditions
* can be reliably detected and retried.
*/
- nr_known = 0;
+ nr_unknown = 0;
ata_link_for_each_dev(dev, link) {
/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
- if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+ if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
classes[dev->devno] = ATA_DEV_NONE;
- else
- nr_known++;
+ if (ata_phys_link_online(ata_dev_phys_link(dev)))
+ nr_unknown++;
+ }
}
- if (classify && !nr_known && ata_link_online(link)) {
+ if (classify && nr_unknown) {
if (try < max_tries) {
ata_link_printk(link, KERN_WARNING, "link online but "
"device misclassified, retrying\n");
+ failed_link = link;
rc = -EAGAIN;
goto fail;
}
@@ -2404,6 +2519,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
/* reset successful, schedule revalidation */
ata_eh_done(link, NULL, ATA_EH_RESET);
+ if (slave)
+ ata_eh_done(slave, NULL, ATA_EH_RESET);
ehc->last_reset = jiffies;
ehc->i.action |= ATA_EH_REVALIDATE;
@@ -2411,6 +2528,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
out:
/* clear hotplug flag */
ehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
+ if (slave)
+ sehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_RESETTING;
@@ -2431,7 +2550,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
if (time_before(now, deadline)) {
unsigned long delta = deadline - now;
- ata_link_printk(link, KERN_WARNING,
+ ata_link_printk(failed_link, KERN_WARNING,
"reset failed (errno=%d), retrying in %u secs\n",
rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
@@ -2439,13 +2558,92 @@ int ata_eh_reset(struct ata_link *link, int classify,
delta = schedule_timeout_uninterruptible(delta);
}
- if (rc == -EPIPE || try == max_tries - 1)
+ if (try == max_tries - 1) {
sata_down_spd_limit(link);
+ if (slave)
+ sata_down_spd_limit(slave);
+ } else if (rc == -EPIPE)
+ sata_down_spd_limit(failed_link);
+
if (hardreset)
reset = hardreset;
goto retry;
}
+static inline void ata_eh_pull_park_action(struct ata_port *ap)
+{
+ struct ata_link *link;
+ struct ata_device *dev;
+ unsigned long flags;
+
+ /*
+ * This function can be thought of as an extended version of
+ * ata_eh_about_to_do() specially crafted to accommodate the
+ * requirements of ATA_EH_PARK handling. Since the EH thread
+ * does not leave the do {} while () loop in ata_eh_recover as
+ * long as the timeout for a park request to *one* device on
+ * the port has not expired, and since we still want to pick
+ * up park requests to other devices on the same port or
+ * timeout updates for the same device, we have to pull
+ * ATA_EH_PARK actions from eh_info into eh_context.i
+ * ourselves at the beginning of each pass over the loop.
+ *
+ * Additionally, all write accesses to &ap->park_req_pending
+ * through INIT_COMPLETION() (see below) or complete_all()
+ * (see ata_scsi_park_store()) are protected by the host lock.
+ * As a result we have that park_req_pending.done is zero on
+ * exit from this function, i.e. when ATA_EH_PARK actions for
+ * *all* devices on port ap have been pulled into the
+ * respective eh_context structs. If, and only if,
+ * park_req_pending.done is non-zero by the time we reach
+ * wait_for_completion_timeout(), another ATA_EH_PARK action
+ * has been scheduled for at least one of the devices on port
+ * ap and we have to cycle over the do {} while () loop in
+ * ata_eh_recover() again.
+ */
+
+ spin_lock_irqsave(ap->lock, flags);
+ INIT_COMPLETION(ap->park_req_pending);
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link) {
+ struct ata_eh_info *ehi = &link->eh_info;
+
+ link->eh_context.i.dev_action[dev->devno] |=
+ ehi->dev_action[dev->devno] & ATA_EH_PARK;
+ ata_eh_clear_action(link, dev, ehi, ATA_EH_PARK);
+ }
+ }
+ spin_unlock_irqrestore(ap->lock, flags);
+}
+
+static void ata_eh_park_issue_cmd(struct ata_device *dev, int park)
+{
+ struct ata_eh_context *ehc = &dev->link->eh_context;
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+
+ ata_tf_init(dev, &tf);
+ if (park) {
+ ehc->unloaded_mask |= 1 << dev->devno;
+ tf.command = ATA_CMD_IDLEIMMEDIATE;
+ tf.feature = 0x44;
+ tf.lbal = 0x4c;
+ tf.lbam = 0x4e;
+ tf.lbah = 0x55;
+ } else {
+ ehc->unloaded_mask &= ~(1 << dev->devno);
+ tf.command = ATA_CMD_CHK_POWER;
+ }
+
+ tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf.protocol |= ATA_PROT_NODATA;
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ if (park && (err_mask || tf.lbal != 0xc4)) {
+ ata_dev_printk(dev, KERN_ERR, "head unload failed!\n");
+ ehc->unloaded_mask &= ~(1 << dev->devno);
+ }
+}
+
static int ata_eh_revalidate_and_attach(struct ata_link *link,
struct ata_device **r_failed_dev)
{
@@ -2472,7 +2670,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
WARN_ON(dev->class == ATA_DEV_PMP);
- if (ata_link_offline(link)) {
+ if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
rc = -EIO;
goto err;
}
@@ -2610,6 +2808,53 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
return rc;
}
+/**
+ * atapi_eh_clear_ua - Clear ATAPI UNIT ATTENTION after reset
+ * @dev: ATAPI device to clear UA for
+ *
+ * Resets and other operations can make an ATAPI device raise
+ * UNIT ATTENTION which causes the next operation to fail. This
+ * function clears UA.
+ *
+ * LOCKING:
+ * EH context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int atapi_eh_clear_ua(struct ata_device *dev)
+{
+ int i;
+
+ for (i = 0; i < ATA_EH_UA_TRIES; i++) {
+ u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+ u8 sense_key = 0;
+ unsigned int err_mask;
+
+ err_mask = atapi_eh_tur(dev, &sense_key);
+ if (err_mask != 0 && err_mask != AC_ERR_DEV) {
+ ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY "
+ "failed (err_mask=0x%x)\n", err_mask);
+ return -EIO;
+ }
+
+ if (!err_mask || sense_key != UNIT_ATTENTION)
+ return 0;
+
+ err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_WARNING, "failed to clear "
+ "UNIT ATTENTION (err_mask=0x%x)\n", err_mask);
+ return -EIO;
+ }
+ }
+
+ ata_dev_printk(dev, KERN_WARNING,
+ "UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES);
+
+ return 0;
+}
+
static int ata_link_nr_enabled(struct ata_link *link)
{
struct ata_device *dev;
@@ -2697,7 +2942,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
/* This is the last chance, better to slow
* down than lose it.
*/
- sata_down_spd_limit(dev->link);
+ sata_down_spd_limit(ata_dev_phys_link(dev));
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
@@ -2707,7 +2952,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
ata_dev_disable(dev);
/* detach if offline */
- if (ata_link_offline(dev->link))
+ if (ata_phys_link_offline(ata_dev_phys_link(dev)))
ata_eh_detach_dev(dev);
/* schedule probe if necessary */
@@ -2755,7 +3000,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
struct ata_device *dev;
int nr_failed_devs;
int rc;
- unsigned long flags;
+ unsigned long flags, deadline;
DPRINTK("ENTER\n");
@@ -2829,6 +3074,56 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
}
}
+ do {
+ unsigned long now;
+
+ /*
+ * clears ATA_EH_PARK in eh_info and resets
+ * ap->park_req_pending
+ */
+ ata_eh_pull_park_action(ap);
+
+ deadline = jiffies;
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link) {
+ struct ata_eh_context *ehc = &link->eh_context;
+ unsigned long tmp;
+
+ if (dev->class != ATA_DEV_ATA)
+ continue;
+ if (!(ehc->i.dev_action[dev->devno] &
+ ATA_EH_PARK))
+ continue;
+ tmp = dev->unpark_deadline;
+ if (time_before(deadline, tmp))
+ deadline = tmp;
+ else if (time_before_eq(tmp, jiffies))
+ continue;
+ if (ehc->unloaded_mask & (1 << dev->devno))
+ continue;
+
+ ata_eh_park_issue_cmd(dev, 1);
+ }
+ }
+
+ now = jiffies;
+ if (time_before_eq(deadline, now))
+ break;
+
+ deadline = wait_for_completion_timeout(&ap->park_req_pending,
+ deadline - now);
+ } while (deadline);
+ ata_port_for_each_link(link, ap) {
+ ata_link_for_each_dev(dev, link) {
+ if (!(link->eh_context.unloaded_mask &
+ (1 << dev->devno)))
+ continue;
+
+ ata_eh_park_issue_cmd(dev, 0);
+ ata_eh_done(link, dev, ATA_EH_PARK);
+ }
+ }
+
/* the rest */
ata_port_for_each_link(link, ap) {
struct ata_eh_context *ehc = &link->eh_context;
@@ -2852,6 +3147,20 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ehc->i.flags &= ~ATA_EHI_SETMODE;
}
+ /* If reset has been issued, clear UA to avoid
+ * disrupting the current users of the device.
+ */
+ if (ehc->i.flags & ATA_EHI_DID_RESET) {
+ ata_link_for_each_dev(dev, link) {
+ if (dev->class != ATA_DEV_ATAPI)
+ continue;
+ rc = atapi_eh_clear_ua(dev);
+ if (rc)
+ goto dev_fail;
+ }
+ }
+
+ /* configure link power saving */
if (ehc->i.action & ATA_EH_LPM)
ata_link_for_each_dev(dev, link)
ata_dev_enable_pm(dev, ap->pm_policy);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b9d3ba423cb..5d312dc9be9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -183,6 +183,105 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
ata_scsi_lpm_show, ata_scsi_lpm_put);
EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
+static ssize_t ata_scsi_park_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(device);
+ struct ata_port *ap;
+ struct ata_link *link;
+ struct ata_device *dev;
+ unsigned long flags;
+ unsigned int uninitialized_var(msecs);
+ int rc = 0;
+
+ ap = ata_shost_to_port(sdev->host);
+
+ spin_lock_irqsave(ap->lock, flags);
+ dev = ata_scsi_find_dev(ap, sdev);
+ if (!dev) {
+ rc = -ENODEV;
+ goto unlock;
+ }
+ if (dev->flags & ATA_DFLAG_NO_UNLOAD) {
+ rc = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ link = dev->link;
+ if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS &&
+ link->eh_context.unloaded_mask & (1 << dev->devno) &&
+ time_after(dev->unpark_deadline, jiffies))
+ msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies);
+ else
+ msecs = 0;
+
+unlock:
+ spin_unlock_irq(ap->lock);
+
+ return rc ? rc : snprintf(buf, 20, "%u\n", msecs);
+}
+
+static ssize_t ata_scsi_park_store(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct scsi_device *sdev = to_scsi_device(device);
+ struct ata_port *ap;
+ struct ata_device *dev;
+ long int input;
+ unsigned long flags;
+ int rc;
+
+ rc = strict_strtol(buf, 10, &input);
+ if (rc || input < -2)
+ return -EINVAL;
+ if (input > ATA_TMOUT_MAX_PARK) {
+ rc = -EOVERFLOW;
+ input = ATA_TMOUT_MAX_PARK;
+ }
+
+ ap = ata_shost_to_port(sdev->host);
+
+ spin_lock_irqsave(ap->lock, flags);
+ dev = ata_scsi_find_dev(ap, sdev);
+ if (unlikely(!dev)) {
+ rc = -ENODEV;
+ goto unlock;
+ }
+ if (dev->class != ATA_DEV_ATA) {
+ rc = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ if (input >= 0) {
+ if (dev->flags & ATA_DFLAG_NO_UNLOAD) {
+ rc = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ dev->unpark_deadline = ata_deadline(jiffies, input);
+ dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_PARK;
+ ata_port_schedule_eh(ap);
+ complete(&ap->park_req_pending);
+ } else {
+ switch (input) {
+ case -1:
+ dev->flags &= ~ATA_DFLAG_NO_UNLOAD;
+ break;
+ case -2:
+ dev->flags |= ATA_DFLAG_NO_UNLOAD;
+ break;
+ }
+ }
+unlock:
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ return rc ? rc : len;
+}
+DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
+ ata_scsi_park_show, ata_scsi_park_store);
+EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
+
static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
@@ -269,6 +368,12 @@ DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show,
ata_scsi_activity_store);
EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
+struct device_attribute *ata_common_sdev_attrs[] = {
+ &dev_attr_unload_heads,
+ NULL
+};
+EXPORT_SYMBOL_GPL(ata_common_sdev_attrs);
+
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
@@ -398,7 +503,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[0] = ATA_16;
scsi_cmd[4] = args[2];
- if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+ if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too */
scsi_cmd[6] = args[3];
scsi_cmd[8] = args[1];
scsi_cmd[10] = 0x4f;
@@ -954,6 +1059,9 @@ static int atapi_drain_needed(struct request *rq)
static int ata_scsi_dev_config(struct scsi_device *sdev,
struct ata_device *dev)
{
+ if (!ata_id_has_unload(dev->id))
+ dev->flags |= ATA_DFLAG_NO_UNLOAD;
+
/* configure max sectors */
blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
@@ -977,6 +1085,10 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
} else {
+ if (ata_id_is_ssd(dev->id))
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT,
+ sdev->request_queue);
+
/* ATA devices must be sector aligned */
blk_queue_update_dma_alignment(sdev->request_queue,
ATA_SECT_SIZE - 1);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 304fdc6f1dc..2a4c516894f 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1315,11 +1315,6 @@ fsm_start:
break;
case HSM_ST_ERR:
- /* make sure qc->err_mask is available to
- * know what's wrong and recover
- */
- WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
-
ap->hsm_task_state = HSM_ST_IDLE;
/* complete taskfile transaction */
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index ade5c75b614..fe2839e5877 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -70,6 +70,7 @@ extern int atapi_passthru16;
extern int libata_fua;
extern int libata_noacpi;
extern int libata_allow_tpm;
+extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
extern void ata_force_cbl(struct ata_port *ap);
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
@@ -107,6 +108,8 @@ extern void ata_qc_issue(struct ata_queued_cmd *qc);
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int atapi_check_dma(struct ata_queued_cmd *qc);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern bool ata_phys_link_online(struct ata_link *link);
+extern bool ata_phys_link_offline(struct ata_link *link);
extern void ata_dev_init(struct ata_device *dev);
extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
extern int sata_link_init_spd(struct ata_link *link);
@@ -152,7 +155,7 @@ extern int ata_bus_probe(struct ata_port *ap);
/* libata-eh.c */
extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
-extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap);
extern void ata_eh_fastdrain_timerfn(unsigned long arg);
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index d3932901a3b..1266924c11f 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1632,6 +1632,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
return -ENODEV;
}
+ dev_set_drvdata(&pdev->dev, host);
+
return 0;
}
@@ -1648,6 +1650,7 @@ static int __devexit bfin_atapi_remove(struct platform_device *pdev)
struct ata_host *host = dev_get_drvdata(dev);
ata_host_detach(host);
+ dev_set_drvdata(&pdev->dev, NULL);
peripheral_free_list(atapi_io_port);
@@ -1655,27 +1658,44 @@ static int __devexit bfin_atapi_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state)
+static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state)
{
- return 0;
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ if (host)
+ return ata_host_suspend(host, state);
+ else
+ return 0;
}
-int bfin_atapi_resume(struct platform_device *pdev)
+static int bfin_atapi_resume(struct platform_device *pdev)
{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ int ret;
+
+ if (host) {
+ ret = bfin_reset_controller(host);
+ if (ret) {
+ printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+ return ret;
+ }
+ ata_host_resume(host);
+ }
+
return 0;
}
+#else
+#define bfin_atapi_suspend NULL
+#define bfin_atapi_resume NULL
#endif
static struct platform_driver bfin_atapi_driver = {
.probe = bfin_atapi_probe,
.remove = __devexit_p(bfin_atapi_remove),
+ .suspend = bfin_atapi_suspend,
+ .resume = bfin_atapi_resume,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .suspend = bfin_atapi_suspend,
- .resume = bfin_atapi_resume,
-#endif
},
};
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 24a011b2502..0d87eec8496 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -20,29 +20,30 @@
#include <linux/ata.h>
#define DRV_NAME "pata_marvell"
-#define DRV_VERSION "0.1.4"
+#define DRV_VERSION "0.1.6"
/**
- * marvell_pre_reset - check for 40/80 pin
- * @link: link
- * @deadline: deadline jiffies for the operation
+ * marvell_pata_active - check if PATA is active
+ * @pdev: PCI device
*
- * Perform the PATA port setup we need.
+ * Returns 1 if the PATA port may be active. We know how to check this
+ * for the 6145 but not the other devices
*/
-static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+static int marvell_pata_active(struct pci_dev *pdev)
{
- struct ata_port *ap = link->ap;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int i;
u32 devices;
void __iomem *barp;
- int i;
- /* Check if our port is enabled */
+ /* We don't yet know how to do this for other devices */
+ if (pdev->device != 0x6145)
+ return 1;
barp = pci_iomap(pdev, 5, 0x10);
if (barp == NULL)
return -ENOMEM;
+
printk("BAR5:");
for(i = 0; i <= 0x0F; i++)
printk("%02X:%02X ", i, ioread8(barp + i));
@@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
devices = ioread32(barp + 0x0C);
pci_iounmap(pdev, barp);
- if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
- (!(devices & 0x10))) /* PATA enable ? */
- return -ENOENT;
+ if (devices & 0x10)
+ return 1;
+ return 0;
+}
+
+/**
+ * marvell_pre_reset - check for 40/80 pin
+ * @link: link
+ * @deadline: deadline jiffies for the operation
+ *
+ * Perform the PATA port setup we need.
+ */
+
+static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ if (pdev->device == 0x6145 && ap->port_no == 0 &&
+ !marvell_pata_active(pdev)) /* PATA enable ? */
+ return -ENOENT;
return ata_sff_prereset(link, deadline);
}
@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
if (pdev->device == 0x6101)
ppi[1] = &ata_dummy_port_info;
+#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
+ if (!marvell_pata_active(pdev)) {
+ printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
+ return -ENODEV;
+ }
+#endif
return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
}
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 408da30594c..1f18ad9e4fe 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
ret = of_irq_to_resource(dn, 0, &irq_res);
if (ret == NO_IRQ)
- irq_res.start = irq_res.end = -1;
+ irq_res.start = irq_res.end = 0;
else
irq_res.flags = 0;
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 41b4361bbf6..02b596b9cf6 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -148,6 +148,64 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+struct pcmcia_config_check {
+ unsigned long ctl_base;
+ int skip_vcc;
+ int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ struct pcmcia_config_check *stk = priv_data;
+
+ /* Check for matching Vcc, unless we're desperate */
+ if (!stk->skip_vcc) {
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ pdev->io.BasePort1 = io->win[0].base;
+ pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ if (io->nwin == 2) {
+ pdev->io.NumPorts1 = 8;
+ pdev->io.BasePort2 = io->win[1].base;
+ pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort2;
+ } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+ pdev->io.NumPorts1 = io->win[0].len;
+ pdev->io.NumPorts2 = 0;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+ } else
+ return -ENODEV;
+ /* If we've got this far, we're done */
+ return 0;
+ }
+ return -ENODEV;
+}
+
/**
* pcmcia_init_one - attach a PCMCIA interface
* @pdev: pcmcia device
@@ -161,19 +219,11 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
struct ata_host *host;
struct ata_port *ap;
struct ata_pcmcia_info *info;
- tuple_t tuple;
- struct {
- unsigned short buf[128];
- cisparse_t parse;
- config_info_t conf;
- cistpl_cftable_entry_t dflt;
- } *stk = NULL;
- cistpl_cftable_entry_t *cfg;
- int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
+ struct pcmcia_config_check *stk = NULL;
+ int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
unsigned long io_base, ctl_base;
void __iomem *io_addr, *ctl_addr;
int n_ports = 1;
-
struct ata_port_operations *ops = &pcmcia_port_ops;
info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -193,96 +243,27 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
pdev->conf.Attributes = CONF_ENABLE_IRQ;
pdev->conf.IntType = INT_MEMORY_AND_IO;
- /* Allocate resoure probing structures */
-
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk)
- goto out1;
-
- cfg = &stk->parse.cftable_entry;
-
- /* Tuples we are walking */
- tuple.TupleData = (cisdata_t *)&stk->buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
-
/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
is_kme = ((pdev->manf_id == MANFID_KME) &&
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf));
-/* link->conf.Vcc = stk->conf.Vcc; */
-
- pass = io_base = ctl_base = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
-
- /* Now munch the resources looking for a suitable set */
- while (1) {
- if (pcmcia_get_tuple_data(pdev, &tuple) != 0)
- goto next_entry;
- if (pcmcia_parse_tuple(pdev, &tuple, &stk->parse) != 0)
- goto next_entry;
- /* Check for matching Vcc, unless we're desperate */
- if (!pass) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- }
- }
+ /* Allocate resoure probing structures */
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
- pdev->conf.ConfigIndex = cfg->index;
- pdev->io.BasePort1 = io->win[0].base;
- pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (!(io->flags & CISTPL_IO_16BIT))
- pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- if (io->nwin == 2) {
- pdev->io.NumPorts1 = 8;
- pdev->io.BasePort2 = io->win[1].base;
- pdev->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(pdev, &pdev->io) != 0)
- goto next_entry;
- io_base = pdev->io.BasePort1;
- ctl_base = pdev->io.BasePort2;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- pdev->io.NumPorts1 = io->win[0].len;
- pdev->io.NumPorts2 = 0;
- if (pcmcia_request_io(pdev, &pdev->io) != 0)
- goto next_entry;
- io_base = pdev->io.BasePort1;
- ctl_base = pdev->io.BasePort1 + 0x0e;
- } else
- goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
-next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
- if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple));
- } else if (pcmcia_get_next_tuple(pdev, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
- memset(&stk->dflt, 0, sizeof(stk->dflt));
- pass++;
- }
- }
+ stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+ if (!stk)
+ goto out1;
+ stk->is_kme = is_kme;
+ stk->skip_vcc = io_base = ctl_base = 0;
+ if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
+ stk->skip_vcc = 1;
+ if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+ goto failed; /* No suitable config found */
+ }
+ io_base = pdev->io.BasePort1;
+ ctl_base = stk->ctl_base;
CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
@@ -384,6 +365,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
+ PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
@@ -404,9 +386,9 @@ static struct pcmcia_device_id pcmcia_devices[] = {
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("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+ PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 720b8645f58..a598bb36aaf 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -230,7 +230,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
tmpbyte & 1, tmpbyte & 0x30);
*try_mmio = 0;
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
if (machine_is(cell))
*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
#endif
@@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
/* Try to acquire MMIO resources and fallback to PIO if
* that fails
*/
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
if (rc)
goto use_ioports;
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 3924e7209a4..1a56db92ff7 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -469,10 +469,10 @@ static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc)
return true;
}
-static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
- u32 val)
+static int sata_fsl_scr_write(struct ata_link *link,
+ unsigned int sc_reg_in, u32 val)
{
- struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ struct sata_fsl_host_priv *host_priv = link->ap->host->private_data;
void __iomem *ssr_base = host_priv->ssr_base;
unsigned int sc_reg;
@@ -493,10 +493,10 @@ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
return 0;
}
-static int sata_fsl_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
- u32 *val)
+static int sata_fsl_scr_read(struct ata_link *link,
+ unsigned int sc_reg_in, u32 *val)
{
- struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+ struct sata_fsl_host_priv *host_priv = link->ap->host->private_data;
void __iomem *ssr_base = host_priv->ssr_base;
unsigned int sc_reg;
@@ -645,12 +645,12 @@ static int sata_fsl_port_start(struct ata_port *ap)
* Workaround for 8315DS board 3gbps link-up issue,
* currently limit SATA port to GEN1 speed
*/
- sata_fsl_scr_read(ap, SCR_CONTROL, &temp);
+ sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
temp &= ~(0xF << 4);
temp |= (0x1 << 4);
- sata_fsl_scr_write(ap, SCR_CONTROL, temp);
+ sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp);
- sata_fsl_scr_read(ap, SCR_CONTROL, &temp);
+ sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n",
temp);
#endif
@@ -868,7 +868,7 @@ issue_srst:
ioread32(CQ + hcr_base),
ioread32(CA + hcr_base), ioread32(CC + hcr_base));
- sata_fsl_scr_read(ap, SCR_ERROR, &Serror);
+ sata_fsl_scr_read(&ap->link, SCR_ERROR, &Serror);
DPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
DPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
@@ -972,9 +972,9 @@ static void sata_fsl_error_intr(struct ata_port *ap)
* Handle & Clear SError
*/
- sata_fsl_scr_read(ap, SCR_ERROR, &SError);
+ sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
if (unlikely(SError & 0xFFFF0000)) {
- sata_fsl_scr_write(ap, SCR_ERROR, SError);
+ sata_fsl_scr_write(&ap->link, SCR_ERROR, SError);
}
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
@@ -1091,7 +1091,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
hstatus = ioread32(hcr_base + HSTATUS);
- sata_fsl_scr_read(ap, SCR_ERROR, &SError);
+ sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
if (unlikely(SError & 0xFFFF0000)) {
DPRINTK("serror @host_intr : 0x%x\n", SError);
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 3ead02fe379..fbbd87c96f1 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -96,6 +96,7 @@ enum {
PORT_SCR = 0x20,
/* HOST_CTL bits */
+ HCTL_LEDEN = (1 << 3), /* enable LED operation */
HCTL_IRQOFF = (1 << 8), /* global IRQ off */
HCTL_FTHD0 = (1 << 10), /* fifo threshold 0 */
HCTL_FTHD1 = (1 << 11), /* fifo threshold 1*/
@@ -268,9 +269,9 @@ static void inic_reset_port(void __iomem *port_base)
writeb(0xff, port_base + PORT_IRQ_STAT);
}
-static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
{
- void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
+ void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
void __iomem *addr;
if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -285,9 +286,9 @@ static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
return 0;
}
-static int inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+static int inic_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
{
- void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
+ void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
return -EINVAL;
@@ -540,7 +541,7 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
void __iomem *port_base = inic_port_base(ap);
/* fire up the ADMA engine */
- writew(HCTL_FTHD0, port_base + HOST_CTL);
+ writew(HCTL_FTHD0 | HCTL_LEDEN, port_base + HOST_CTL);
writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
writeb(0, port_base + PORT_CPB_PTQFIFO);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 13c1d2af18a..2b24ae58b52 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -493,10 +493,10 @@ struct mv_hw_ops {
void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
};
-static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
-static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
-static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val);
+static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val);
+static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val);
+static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val);
static int mv_port_start(struct ata_port *ap);
static void mv_port_stop(struct ata_port *ap);
static int mv_qc_defer(struct ata_queued_cmd *qc);
@@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
- /* RocketRAID 1740/174x have different identifiers */
+ /* RocketRAID 1720/174x have different identifiers */
+ { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
@@ -1069,23 +1070,23 @@ static unsigned int mv_scr_offset(unsigned int sc_reg_in)
return ofs;
}
-static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
+static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val)
{
unsigned int ofs = mv_scr_offset(sc_reg_in);
if (ofs != 0xffffffffU) {
- *val = readl(mv_ap_base(ap) + ofs);
+ *val = readl(mv_ap_base(link->ap) + ofs);
return 0;
} else
return -EINVAL;
}
-static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
{
unsigned int ofs = mv_scr_offset(sc_reg_in);
if (ofs != 0xffffffffU) {
- writelfl(val, mv_ap_base(ap) + ofs);
+ writelfl(val, mv_ap_base(link->ap) + ofs);
return 0;
} else
return -EINVAL;
@@ -2250,11 +2251,11 @@ static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
return ofs;
}
-static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
+static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val)
{
- struct mv_host_priv *hpriv = ap->host->private_data;
+ struct mv_host_priv *hpriv = link->ap->host->private_data;
void __iomem *mmio = hpriv->base;
- void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
+ void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no);
unsigned int ofs = mv5_scr_offset(sc_reg_in);
if (ofs != 0xffffffffU) {
@@ -2264,11 +2265,11 @@ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
return -EINVAL;
}
-static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
{
- struct mv_host_priv *hpriv = ap->host->private_data;
+ struct mv_host_priv *hpriv = link->ap->host->private_data;
void __iomem *mmio = hpriv->base;
- void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
+ void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no);
unsigned int ofs = mv5_scr_offset(sc_reg_in);
if (ofs != 0xffffffffU) {
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 858f70610ed..fae3841de0d 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -302,8 +302,8 @@ static void nv_ck804_host_stop(struct ata_host *host);
static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
-static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
@@ -405,28 +405,45 @@ static struct scsi_host_template nv_swncq_sht = {
.slave_configure = nv_swncq_slave_config,
};
-static struct ata_port_operations nv_generic_ops = {
+/* OSDL bz3352 reports that some nv controllers can't determine device
+ * signature reliably and nv_hardreset is implemented to work around
+ * the problem. This was reported on nf3 and it's unclear whether any
+ * other controllers are affected. However, the workaround has been
+ * applied to all variants and there isn't much to gain by trying to
+ * find out exactly which ones are affected at this point especially
+ * because NV has moved over to ahci for newer controllers.
+ */
+static struct ata_port_operations nv_common_ops = {
.inherits = &ata_bmdma_port_ops,
.hardreset = nv_hardreset,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
};
+/* OSDL bz11195 reports that link doesn't come online after hardreset
+ * on generic nv's and there have been several other similar reports
+ * on linux-ide. Disable hardreset for generic nv's.
+ */
+static struct ata_port_operations nv_generic_ops = {
+ .inherits = &nv_common_ops,
+ .hardreset = ATA_OP_NULL,
+};
+
static struct ata_port_operations nv_nf2_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_common_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
};
static struct ata_port_operations nv_ck804_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_common_ops,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
.host_stop = nv_ck804_host_stop,
};
static struct ata_port_operations nv_adma_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_common_ops,
.check_atapi_dma = nv_adma_check_atapi_dma,
.sff_tf_read = nv_adma_tf_read,
@@ -450,7 +467,7 @@ static struct ata_port_operations nv_adma_ops = {
};
static struct ata_port_operations nv_swncq_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_common_ops,
.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
@@ -1494,21 +1511,21 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
return ret;
}
-static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
+ *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
-static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
@@ -2201,9 +2218,9 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
if (!pp->qc_active)
return;
- if (ap->ops->scr_read(ap, SCR_ERROR, &serror))
+ if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror))
return;
- ap->ops->scr_write(ap, SCR_ERROR, serror);
+ ap->ops->scr_write(&ap->link, SCR_ERROR, serror);
if (ata_stat & ATA_ERR) {
ata_ehi_clear_desc(ehi);
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 030665ba76b..750d8cdc00c 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -137,8 +137,8 @@ struct pdc_port_priv {
dma_addr_t pkt_dma;
};
-static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int pdc_common_port_start(struct ata_port *ap);
static int pdc_sata_port_start(struct ata_port *ap);
@@ -386,19 +386,21 @@ static int pdc_sata_cable_detect(struct ata_port *ap)
return ATA_CBL_SATA;
}
-static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int pdc_sata_scr_read(struct ata_link *link,
+ unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4));
+ *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
-static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int pdc_sata_scr_write(struct ata_link *link,
+ unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
@@ -731,7 +733,7 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
if (sata_scr_valid(&ap->link)) {
u32 serror;
- pdc_sata_scr_read(ap, SCR_ERROR, &serror);
+ pdc_sata_scr_read(&ap->link, SCR_ERROR, &serror);
ehi->serror |= serror;
}
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 1600107047c..a000c86ac85 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -111,8 +111,8 @@ struct qs_port_priv {
qs_state_t state;
};
-static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int qs_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int qs_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int qs_port_start(struct ata_port *ap);
static void qs_host_stop(struct ata_host *host);
@@ -242,11 +242,11 @@ static int qs_prereset(struct ata_link *link, unsigned long deadline)
return ata_sff_prereset(link, deadline);
}
-static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int qs_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = readl(ap->ioaddr.scr_addr + (sc_reg * 8));
+ *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 8));
return 0;
}
@@ -256,11 +256,11 @@ static void qs_error_handler(struct ata_port *ap)
ata_std_error_handler(ap);
}
-static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int qs_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- writel(val, ap->ioaddr.scr_addr + (sc_reg * 8));
+ writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 8));
return 0;
}
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 88bf4212590..031d7b7dee3 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -115,8 +115,8 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int sil_pci_device_resume(struct pci_dev *pdev);
#endif
static void sil_dev_config(struct ata_device *dev);
-static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed);
static void sil_freeze(struct ata_port *ap);
static void sil_thaw(struct ata_port *ap);
@@ -317,9 +317,9 @@ static inline void __iomem *sil_scr_addr(struct ata_port *ap,
return NULL;
}
-static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
- void __iomem *mmio = sil_scr_addr(ap, sc_reg);
+ void __iomem *mmio = sil_scr_addr(link->ap, sc_reg);
if (mmio) {
*val = readl(mmio);
@@ -328,9 +328,9 @@ static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return -EINVAL;
}
-static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
- void __iomem *mmio = sil_scr_addr(ap, sc_reg);
+ void __iomem *mmio = sil_scr_addr(link->ap, sc_reg);
if (mmio) {
writel(val, mmio);
@@ -352,8 +352,8 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
* controllers continue to assert IRQ as long as
* SError bits are pending. Clear SError immediately.
*/
- sil_scr_read(ap, SCR_ERROR, &serror);
- sil_scr_write(ap, SCR_ERROR, serror);
+ sil_scr_read(&ap->link, SCR_ERROR, &serror);
+ sil_scr_write(&ap->link, SCR_ERROR, serror);
/* Sometimes spurious interrupts occur, double check
* it's PHYRDY CHG.
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 84ffcc26a74..4621807a1a6 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -340,8 +340,8 @@ struct sil24_port_priv {
};
static void sil24_dev_config(struct ata_device *dev);
-static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
-static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val);
+static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val);
static int sil24_qc_defer(struct ata_queued_cmd *qc);
static void sil24_qc_prep(struct ata_queued_cmd *qc);
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
@@ -504,9 +504,9 @@ static int sil24_scr_map[] = {
[SCR_ACTIVE] = 3,
};
-static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
{
- void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+ void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
void __iomem *addr;
@@ -517,9 +517,9 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
return -EINVAL;
}
-static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
{
- void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+ void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
void __iomem *addr;
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 1010b3069bd..9c43b4e7c4a 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -64,8 +64,8 @@ enum {
};
static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static const struct pci_device_id sis_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */
@@ -134,10 +134,11 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
return addr;
}
-static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static u32 sis_scr_cfg_read(struct ata_link *link,
+ unsigned int sc_reg, u32 *val)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg);
u32 val2 = 0;
u8 pmr;
@@ -158,10 +159,11 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0;
}
-static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int sis_scr_cfg_write(struct ata_link *link,
+ unsigned int sc_reg, u32 val)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg);
u8 pmr;
if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
@@ -178,8 +180,9 @@ static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
return 0;
}
-static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
+ struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 pmr;
@@ -187,7 +190,7 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return -EINVAL;
if (ap->flags & SIS_FLAG_CFGSCR)
- return sis_scr_cfg_read(ap, sc_reg, val);
+ return sis_scr_cfg_read(link, sc_reg, val);
pci_read_config_byte(pdev, SIS_PMR, &pmr);
@@ -202,8 +205,9 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
return 0;
}
-static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
+ struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 pmr;
@@ -213,7 +217,7 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
pci_read_config_byte(pdev, SIS_PMR, &pmr);
if (ap->flags & SIS_FLAG_CFGSCR)
- return sis_scr_cfg_write(ap, sc_reg, val);
+ return sis_scr_cfg_write(link, sc_reg, val);
else {
iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index fb13b82aacb..609d147813a 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -123,20 +123,22 @@ static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc)
}
}
-static int k2_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int k2_sata_scr_read(struct ata_link *link,
+ unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4));
+ *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
-static int k2_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int k2_sata_scr_write(struct ata_link *link,
+ unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index db529b84994..019575bb3e0 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -57,8 +57,8 @@ struct uli_priv {
};
static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static const struct pci_device_id uli_pci_tbl[] = {
{ PCI_VDEVICE(AL, 0x5289), uli_5289 },
@@ -107,39 +107,39 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg);
}
-static u32 uli_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg)
+static u32 uli_scr_cfg_read(struct ata_link *link, unsigned int sc_reg)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg);
u32 val;
pci_read_config_dword(pdev, cfg_addr, &val);
return val;
}
-static void uli_scr_cfg_write(struct ata_port *ap, unsigned int scr, u32 val)
+static void uli_scr_cfg_write(struct ata_link *link, unsigned int scr, u32 val)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap, scr);
+ struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
+ unsigned int cfg_addr = get_scr_cfg_addr(link->ap, scr);
pci_write_config_dword(pdev, cfg_addr, val);
}
-static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = uli_scr_cfg_read(ap, sc_reg);
+ *val = uli_scr_cfg_read(link, sc_reg);
return 0;
}
-static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
return -EINVAL;
- uli_scr_cfg_write(ap, sc_reg, val);
+ uli_scr_cfg_write(link, sc_reg, val);
return 0;
}
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 96deeb354e1..1cfa74535d9 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -68,8 +68,8 @@ enum {
};
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static void svia_noop_freeze(struct ata_port *ap);
static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
static int vt6421_pata_cable_detect(struct ata_port *ap);
@@ -152,19 +152,19 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = ioread32(ap->ioaddr.scr_addr + (4 * sc_reg));
+ *val = ioread32(link->ap->ioaddr.scr_addr + (4 * sc_reg));
return 0;
}
-static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- iowrite32(val, ap->ioaddr.scr_addr + (4 * sc_reg));
+ iowrite32(val, link->ap->ioaddr.scr_addr + (4 * sc_reg));
return 0;
}
@@ -210,20 +210,20 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
goto skip_scr;
/* Resume phy. This is the old SATA resume sequence */
- svia_scr_write(ap, SCR_CONTROL, 0x300);
- svia_scr_read(ap, SCR_CONTROL, &scontrol); /* flush */
+ svia_scr_write(link, SCR_CONTROL, 0x300);
+ svia_scr_read(link, SCR_CONTROL, &scontrol); /* flush */
/* wait for phy to become ready, if necessary */
do {
msleep(200);
- svia_scr_read(ap, SCR_STATUS, &sstatus);
+ svia_scr_read(link, SCR_STATUS, &sstatus);
if ((sstatus & 0xf) != 1)
break;
} while (time_before(jiffies, timeout));
/* open code sata_print_link_status() */
- svia_scr_read(ap, SCR_STATUS, &sstatus);
- svia_scr_read(ap, SCR_CONTROL, &scontrol);
+ svia_scr_read(link, SCR_STATUS, &sstatus);
+ svia_scr_read(link, SCR_CONTROL, &scontrol);
online = (sstatus & 0xf) == 0x3;
@@ -232,7 +232,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
online ? "up" : "down", sstatus, scontrol);
/* SStatus is read one more time */
- svia_scr_read(ap, SCR_STATUS, &sstatus);
+ svia_scr_read(link, SCR_STATUS, &sstatus);
if (!online) {
/* tell EH to bail */
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index f3d635c0a2e..c57cdff9e6b 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -98,20 +98,22 @@ enum {
VSC_SATA_INT_PHY_CHANGE),
};
-static int vsc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int vsc_sata_scr_read(struct ata_link *link,
+ unsigned int sc_reg, u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4));
+ *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
-static int vsc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int vsc_sata_scr_write(struct ata_link *link,
+ unsigned int sc_reg, u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
- writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 41b2204ebc6..5503bfc8e13 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1270,7 +1270,7 @@ static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre,
if (*pre < 3) (*pre)++; /* else fail later */
div = pre_div[*pre]*-*pcr;
DPRINTK("max div %d\n",div);
- *res = (TS_CLOCK+div-1)/div-1;
+ *res = DIV_ROUND_UP(TS_CLOCK, div)-1;
}
if (*res < 0) *res = 0;
if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 73338d231db..937c9c0ef4c 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -47,8 +47,9 @@
#include <asm/atomic.h>
#ifdef CONFIG_SBUS
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/idprom.h>
-#include <asm/sbus.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/pgtable.h>
@@ -661,249 +662,189 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page)
#ifdef CONFIG_SBUS
-static u32
-fore200e_sba_read(volatile u32 __iomem *addr)
+static u32 fore200e_sba_read(volatile u32 __iomem *addr)
{
return sbus_readl(addr);
}
-
-static void
-fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
+static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
{
sbus_writel(val, addr);
}
-
-static u32
-fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction)
+static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction)
{
- u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction);
+ struct of_device *op = fore200e->bus_dev;
+ u32 dma_addr;
- DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n",
- virt_addr, size, direction, dma_addr);
+ dma_addr = dma_map_single(&op->dev, virt_addr, size, direction);
+
+ DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n",
+ virt_addr, size, direction, dma_addr);
- return dma_addr;
+ return dma_addr;
}
-
-static void
-fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
+static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n",
- dma_addr, size, direction);
+ struct of_device *op = fore200e->bus_dev;
- sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
-}
+ DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n",
+ dma_addr, size, direction);
+ dma_unmap_single(&op->dev, dma_addr, size, direction);
+}
-static void
-fore200e_sba_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
+static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
+ struct of_device *op = fore200e->bus_dev;
+
+ DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
- sbus_dma_sync_single_for_cpu((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
+ dma_sync_single_for_cpu(&op->dev, dma_addr, size, direction);
}
-static void
-fore200e_sba_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
+static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
-
- sbus_dma_sync_single_for_device((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
-}
+ struct of_device *op = fore200e->bus_dev;
+ DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
-/* allocate a DVMA consistent chunk of memory intended to act as a communication mechanism
- (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
+ dma_sync_single_for_device(&op->dev, dma_addr, size, direction);
+}
-static int
-fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
- int size, int nbr, int alignment)
+/* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism
+ * (to hold descriptors, status, queues, etc.) shared by the driver and the adapter.
+ */
+static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk,
+ int size, int nbr, int alignment)
{
- chunk->alloc_size = chunk->align_size = size * nbr;
+ struct of_device *op = fore200e->bus_dev;
- /* returned chunks are page-aligned */
- chunk->alloc_addr = sbus_alloc_consistent((struct sbus_dev*)fore200e->bus_dev,
- chunk->alloc_size,
- &chunk->dma_addr);
+ chunk->alloc_size = chunk->align_size = size * nbr;
- if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0))
- return -ENOMEM;
+ /* returned chunks are page-aligned */
+ chunk->alloc_addr = dma_alloc_coherent(&op->dev, chunk->alloc_size,
+ &chunk->dma_addr, GFP_ATOMIC);
- chunk->align_addr = chunk->alloc_addr;
+ if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0))
+ return -ENOMEM;
+
+ chunk->align_addr = chunk->alloc_addr;
- return 0;
+ return 0;
}
-
/* free a DVMA consistent chunk of memory */
-
-static void
-fore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
+static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk)
{
- sbus_free_consistent((struct sbus_dev*)fore200e->bus_dev,
- chunk->alloc_size,
- chunk->alloc_addr,
- chunk->dma_addr);
-}
+ struct of_device *op = fore200e->bus_dev;
+ dma_free_coherent(&op->dev, chunk->alloc_size,
+ chunk->alloc_addr, chunk->dma_addr);
+}
-static void
-fore200e_sba_irq_enable(struct fore200e* fore200e)
+static void fore200e_sba_irq_enable(struct fore200e *fore200e)
{
- u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
- fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr);
+ u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
+ fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr);
}
-
-static int
-fore200e_sba_irq_check(struct fore200e* fore200e)
+static int fore200e_sba_irq_check(struct fore200e *fore200e)
{
- return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ;
+ return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ;
}
-
-static void
-fore200e_sba_irq_ack(struct fore200e* fore200e)
+static void fore200e_sba_irq_ack(struct fore200e *fore200e)
{
- u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
- fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr);
+ u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
+ fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr);
}
-
-static void
-fore200e_sba_reset(struct fore200e* fore200e)
+static void fore200e_sba_reset(struct fore200e *fore200e)
{
- fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr);
- fore200e_spin(10);
- fore200e->bus->write(0, fore200e->regs.sba.hcr);
+ fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr);
+ fore200e_spin(10);
+ fore200e->bus->write(0, fore200e->regs.sba.hcr);
}
-
-static int __init
-fore200e_sba_map(struct fore200e* fore200e)
+static int __init fore200e_sba_map(struct fore200e *fore200e)
{
- struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;
- unsigned int bursts;
+ struct of_device *op = fore200e->bus_dev;
+ unsigned int bursts;
- /* gain access to the SBA specific registers */
- fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
- fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
- fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
- fore200e->virt_base = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
+ /* gain access to the SBA specific registers */
+ fore200e->regs.sba.hcr = of_ioremap(&op->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
+ fore200e->regs.sba.bsr = of_ioremap(&op->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
+ fore200e->regs.sba.isr = of_ioremap(&op->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
+ fore200e->virt_base = of_ioremap(&op->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
- if (fore200e->virt_base == NULL) {
- printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
- return -EFAULT;
- }
+ if (!fore200e->virt_base) {
+ printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
+ return -EFAULT;
+ }
- DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
+ DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
- fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */
+ fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */
- /* get the supported DVMA burst sizes */
- bursts = prom_getintdefault(sbus_dev->bus->prom_node, "burst-sizes", 0x00);
+ /* get the supported DVMA burst sizes */
+ bursts = of_getintprop_default(op->node->parent, "burst-sizes", 0x00);
- if (sbus_can_dma_64bit(sbus_dev))
- sbus_set_sbus64(sbus_dev, bursts);
+ if (sbus_can_dma_64bit())
+ sbus_set_sbus64(&op->dev, bursts);
- fore200e->state = FORE200E_STATE_MAP;
- return 0;
+ fore200e->state = FORE200E_STATE_MAP;
+ return 0;
}
-
-static void
-fore200e_sba_unmap(struct fore200e* fore200e)
+static void fore200e_sba_unmap(struct fore200e *fore200e)
{
- sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
- sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
- sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
- sbus_iounmap(fore200e->virt_base, SBA200E_RAM_LENGTH);
-}
+ struct of_device *op = fore200e->bus_dev;
+ of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
+ of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
+ of_iounmap(&op->resource[2], fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
+ of_iounmap(&op->resource[3], fore200e->virt_base, SBA200E_RAM_LENGTH);
+}
-static int __init
-fore200e_sba_configure(struct fore200e* fore200e)
+static int __init fore200e_sba_configure(struct fore200e *fore200e)
{
- fore200e->state = FORE200E_STATE_CONFIGURE;
- return 0;
+ fore200e->state = FORE200E_STATE_CONFIGURE;
+ return 0;
}
-
-static struct fore200e* __init
-fore200e_sba_detect(const struct fore200e_bus* bus, int index)
+static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom)
{
- struct fore200e* fore200e;
- struct sbus_bus* sbus_bus;
- struct sbus_dev* sbus_dev = NULL;
-
- unsigned int count = 0;
-
- for_each_sbus (sbus_bus) {
- for_each_sbusdev (sbus_dev, sbus_bus) {
- if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) {
- if (count >= index)
- goto found;
- count++;
- }
- }
- }
- return NULL;
-
- found:
- if (sbus_dev->num_registers != 4) {
- printk(FORE200E "this %s device has %d instead of 4 registers\n",
- bus->model_name, sbus_dev->num_registers);
- return NULL;
- }
-
- fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
- if (fore200e == NULL)
- return NULL;
+ struct of_device *op = fore200e->bus_dev;
+ const u8 *prop;
+ int len;
- fore200e->bus = bus;
- fore200e->bus_dev = sbus_dev;
- fore200e->irq = sbus_dev->irqs[ 0 ];
+ prop = of_get_property(op->node, "madaddrlo2", &len);
+ if (!prop)
+ return -ENODEV;
+ memcpy(&prom->mac_addr[4], prop, 4);
- fore200e->phys_base = (unsigned long)sbus_dev;
+ prop = of_get_property(op->node, "madaddrhi4", &len);
+ if (!prop)
+ return -ENODEV;
+ memcpy(&prom->mac_addr[2], prop, 4);
- sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
+ prom->serial_number = of_getintprop_default(op->node, "serialnumber", 0);
+ prom->hw_revision = of_getintprop_default(op->node, "promversion", 0);
- return fore200e;
+ return 0;
}
-
-static int __init
-fore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom)
+static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page)
{
- struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev;
- int len;
-
- len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4);
- if (len < 0)
- return -EBUSY;
-
- len = prom_getproperty(sbus_dev->prom_node, "macaddrhi4", &prom->mac_addr[ 2 ], 4);
- if (len < 0)
- return -EBUSY;
-
- prom_getproperty(sbus_dev->prom_node, "serialnumber",
- (char*)&prom->serial_number, sizeof(prom->serial_number));
-
- prom_getproperty(sbus_dev->prom_node, "promversion",
- (char*)&prom->hw_revision, sizeof(prom->hw_revision));
-
- return 0;
-}
+ struct of_device *op = fore200e->bus_dev;
+ const struct linux_prom_registers *regs;
+ regs = of_get_property(op->node, "reg", NULL);
-static int
-fore200e_sba_proc_read(struct fore200e* fore200e, char *page)
-{
- struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;
-
- return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name);
+ return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n",
+ (regs ? regs->which_io : 0), op->node->name);
}
#endif /* CONFIG_SBUS */
@@ -2572,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
device = &((struct pci_dev *) fore200e->bus_dev)->dev;
#ifdef CONFIG_SBUS
else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0)
- device = &((struct sbus_dev *) fore200e->bus_dev)->ofdev.dev;
+ device = &((struct of_device *) fore200e->bus_dev)->dev;
#endif
else
return err;
@@ -2701,6 +2642,66 @@ fore200e_init(struct fore200e* fore200e)
return 0;
}
+#ifdef CONFIG_SBUS
+static int __devinit fore200e_sba_probe(struct of_device *op,
+ const struct of_device_id *match)
+{
+ const struct fore200e_bus *bus = match->data;
+ struct fore200e *fore200e;
+ static int index = 0;
+ int err;
+
+ fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
+ if (!fore200e)
+ return -ENOMEM;
+
+ fore200e->bus = bus;
+ fore200e->bus_dev = op;
+ fore200e->irq = op->irqs[0];
+ fore200e->phys_base = op->resource[0].start;
+
+ sprintf(fore200e->name, "%s-%d", bus->model_name, index);
+
+ err = fore200e_init(fore200e);
+ if (err < 0) {
+ fore200e_shutdown(fore200e);
+ kfree(fore200e);
+ return err;
+ }
+
+ index++;
+ dev_set_drvdata(&op->dev, fore200e);
+
+ return 0;
+}
+
+static int __devexit fore200e_sba_remove(struct of_device *op)
+{
+ struct fore200e *fore200e = dev_get_drvdata(&op->dev);
+
+ fore200e_shutdown(fore200e);
+ kfree(fore200e);
+
+ return 0;
+}
+
+static const struct of_device_id fore200e_sba_match[] = {
+ {
+ .name = SBA200E_PROM_NAME,
+ .data = (void *) &fore200e_bus[1],
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, fore200e_sba_match);
+
+static struct of_platform_driver fore200e_sba_driver = {
+ .name = "fore_200e",
+ .match_table = fore200e_sba_match,
+ .probe = fore200e_sba_probe,
+ .remove = __devexit_p(fore200e_sba_remove),
+};
+#endif
+
#ifdef CONFIG_PCI
static int __devinit
fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
@@ -2784,67 +2785,40 @@ static struct pci_driver fore200e_pca_driver = {
};
#endif
-
-static int __init
-fore200e_module_init(void)
+static int __init fore200e_module_init(void)
{
- const struct fore200e_bus* bus;
- struct fore200e* fore200e;
- int index;
-
- printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
+ int err;
- /* for each configured bus interface */
- for (bus = fore200e_bus; bus->model_name; bus++) {
+ printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
- /* detect all boards present on that bus */
- for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) {
-
- printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
- fore200e->bus->model_name,
- fore200e->phys_base, fore200e_irq_itoa(fore200e->irq));
-
- sprintf(fore200e->name, "%s-%d", bus->model_name, index);
-
- if (fore200e_init(fore200e) < 0) {
-
- fore200e_shutdown(fore200e);
- break;
- }
-
- list_add(&fore200e->entry, &fore200e_boards);
- }
- }
+#ifdef CONFIG_SBUS
+ err = of_register_driver(&fore200e_sba_driver, &of_bus_type);
+ if (err)
+ return err;
+#endif
#ifdef CONFIG_PCI
- if (!pci_register_driver(&fore200e_pca_driver))
- return 0;
+ err = pci_register_driver(&fore200e_pca_driver);
#endif
- if (!list_empty(&fore200e_boards))
- return 0;
+#ifdef CONFIG_SBUS
+ if (err)
+ of_unregister_driver(&fore200e_sba_driver);
+#endif
- return -ENODEV;
+ return err;
}
-
-static void __exit
-fore200e_module_cleanup(void)
+static void __exit fore200e_module_cleanup(void)
{
- struct fore200e *fore200e, *next;
-
#ifdef CONFIG_PCI
- pci_unregister_driver(&fore200e_pca_driver);
+ pci_unregister_driver(&fore200e_pca_driver);
+#endif
+#ifdef CONFIG_SBUS
+ of_unregister_driver(&fore200e_sba_driver);
#endif
-
- list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) {
- fore200e_shutdown(fore200e);
- kfree(fore200e);
- }
- DPRINTK(1, "module being removed\n");
}
-
static int
fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
{
@@ -3163,7 +3137,6 @@ static const struct fore200e_bus fore200e_bus[] = {
fore200e_pca_dma_sync_for_device,
fore200e_pca_dma_chunk_alloc,
fore200e_pca_dma_chunk_free,
- NULL,
fore200e_pca_configure,
fore200e_pca_map,
fore200e_pca_reset,
@@ -3185,7 +3158,6 @@ static const struct fore200e_bus fore200e_bus[] = {
fore200e_sba_dma_sync_for_device,
fore200e_sba_dma_chunk_alloc,
fore200e_sba_dma_chunk_free,
- fore200e_sba_detect,
fore200e_sba_configure,
fore200e_sba_map,
fore200e_sba_reset,
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
index 5c6e7adcb19..7f97c09aaea 100644
--- a/drivers/atm/fore200e.h
+++ b/drivers/atm/fore200e.h
@@ -778,9 +778,9 @@ typedef struct fore200e_pca_regs {
/* SBA-200E registers */
typedef struct fore200e_sba_regs {
- volatile u32 __iomem *hcr; /* address of host control register */
- volatile u32 __iomem *bsr; /* address of burst transfer size register */
- volatile u32 __iomem *isr; /* address of interrupt level selection register */
+ u32 __iomem *hcr; /* address of host control register */
+ u32 __iomem *bsr; /* address of burst transfer size register */
+ u32 __iomem *isr; /* address of interrupt level selection register */
} fore200e_sba_regs_t;
@@ -810,7 +810,6 @@ typedef struct fore200e_bus {
void (*dma_sync_for_device)(struct fore200e*, u32, int, int);
int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int);
void (*dma_chunk_free)(struct fore200e*, struct chunk*);
- struct fore200e* (*detect)(const struct fore200e_bus*, int);
int (*configure)(struct fore200e*);
int (*map)(struct fore200e*);
void (*reset)(struct fore200e*);
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index c0ac728dc56..615412364e9 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -635,7 +635,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
// take care of rounding
switch (r) {
case round_down:
- pre = (br+(c<<div)-1)/(c<<div);
+ pre = DIV_ROUND_UP(br, c<<div);
// but p must be non-zero
if (!pre)
pre = 1;
@@ -668,7 +668,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
// take care of rounding
switch (r) {
case round_down:
- pre = (br+(c<<div)-1)/(c<<div);
+ pre = DIV_ROUND_UP(br, c<<div);
break;
case round_nearest:
pre = (br+(c<<div)/2)/(c<<div);
@@ -698,7 +698,7 @@ got_it:
if (bits)
*bits = (div<<CLOCK_SELECT_SHIFT) | (pre-1);
if (actual) {
- *actual = (br + (pre<<div) - 1) / (pre<<div);
+ *actual = DIV_ROUND_UP(br, pre<<div);
PRINTD (DBG_QOS, "actual rate: %u", *actual);
}
return 0;
@@ -1967,7 +1967,7 @@ static int __devinit hrz_init (hrz_dev * dev) {
// Set the max AAL5 cell count to be just enough to contain the
// largest AAL5 frame that the user wants to receive
wr_regw (dev, MAX_AAL5_CELL_COUNT_OFF,
- (max_rx_size + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD);
+ DIV_ROUND_UP(max_rx_size + ATM_AAL5_TRAILER, ATM_CELL_PAYLOAD));
// Enable receive
wr_regw (dev, RX_CONFIG_OFF, rd_regw (dev, RX_CONFIG_OFF) | RX_ENABLE);
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 3a504e94a4d..e33ae0025b1 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -1114,11 +1114,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
rpp = &vc->rcv.rx_pool;
+ __skb_queue_tail(&rpp->queue, skb);
rpp->len += skb->len;
- if (!rpp->count++)
- rpp->first = skb;
- *rpp->last = skb;
- rpp->last = &skb->next;
if (stat & SAR_RSQE_EPDU) {
unsigned char *l1l2;
@@ -1145,7 +1142,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
atomic_inc(&vcc->stats->rx_err);
return;
}
- if (rpp->count > 1) {
+ if (skb_queue_len(&rpp->queue) > 1) {
struct sk_buff *sb;
skb = dev_alloc_skb(rpp->len);
@@ -1161,12 +1158,9 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
dev_kfree_skb(skb);
return;
}
- sb = rpp->first;
- for (i = 0; i < rpp->count; i++) {
+ skb_queue_walk(&rpp->queue, sb)
memcpy(skb_put(skb, sb->len),
sb->data, sb->len);
- sb = sb->next;
- }
recycle_rx_pool_skb(card, rpp);
@@ -1180,7 +1174,6 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
return;
}
- skb->next = NULL;
flush_rx_pool(card, rpp);
if (!atm_charge(vcc, skb->truesize)) {
@@ -1918,25 +1911,18 @@ recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb)
static void
flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp)
{
+ skb_queue_head_init(&rpp->queue);
rpp->len = 0;
- rpp->count = 0;
- rpp->first = NULL;
- rpp->last = &rpp->first;
}
static void
recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp)
{
- struct sk_buff *skb, *next;
- int i;
+ struct sk_buff *skb, *tmp;
- skb = rpp->first;
- for (i = 0; i < rpp->count; i++) {
- next = skb->next;
- skb->next = NULL;
+ skb_queue_walk_safe(&rpp->queue, skb, tmp)
recycle_rx_skb(card, skb);
- skb = next;
- }
+
flush_rx_pool(card, rpp);
}
@@ -2537,7 +2523,7 @@ idt77252_close(struct atm_vcc *vcc)
waitfor_idle(card);
spin_unlock_irqrestore(&card->cmd_lock, flags);
- if (vc->rcv.rx_pool.count) {
+ if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
DPRINTK("%s: closing a VC with pending rx buffers.\n",
card->name);
@@ -2970,7 +2956,7 @@ close_card_oam(struct idt77252_dev *card)
waitfor_idle(card);
spin_unlock_irqrestore(&card->cmd_lock, flags);
- if (vc->rcv.rx_pool.count) {
+ if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
DPRINTK("%s: closing a VC "
"with pending rx buffers.\n",
card->name);
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h
index e83eaf120da..5042bb2dab1 100644
--- a/drivers/atm/idt77252.h
+++ b/drivers/atm/idt77252.h
@@ -173,10 +173,8 @@ struct scq_info
};
struct rx_pool {
- struct sk_buff *first;
- struct sk_buff **last;
+ struct sk_buff_head queue;
unsigned int len;
- unsigned int count;
};
struct aal1 {
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 58583c6ac5b..752b1ba81f7 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -496,8 +496,8 @@ static int open_rx_first(struct atm_vcc *vcc)
vcc->qos.rxtp.max_sdu = 65464;
/* fix this - we may want to receive 64kB SDUs
later */
- cells = (vcc->qos.rxtp.max_sdu+ATM_AAL5_TRAILER+
- ATM_CELL_PAYLOAD-1)/ATM_CELL_PAYLOAD;
+ cells = DIV_ROUND_UP(vcc->qos.rxtp.max_sdu + ATM_AAL5_TRAILER,
+ ATM_CELL_PAYLOAD);
zatm_vcc->pool = pool_index(cells*ATM_CELL_PAYLOAD);
}
else {
@@ -820,7 +820,7 @@ static int alloc_shaper(struct atm_dev *dev,int *pcr,int min,int max,int ubr)
}
else {
i = 255;
- m = (ATM_OC3_PCR*255+max-1)/max;
+ m = DIV_ROUND_UP(ATM_OC3_PCR*255, max);
}
}
if (i > m) {
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 6318f6b5736..d8e8c49c0cb 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL
such firmware, and do not wish to use an initrd.
This single option controls the inclusion of firmware for
- every driver which usees request_firmare() and ships its
+ every driver which uses request_firmare() and ships its
firmware in the kernel source tree, to avoid a proliferation
of 'Include firmware for xxx device' options.
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 31dc0cd84af..0a5f055dffb 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -54,7 +54,7 @@ struct driver_private {
*/
struct class_private {
struct kset class_subsys;
- struct list_head class_devices;
+ struct klist class_devices;
struct list_head class_interfaces;
struct kset class_dirs;
struct mutex class_mutex;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ef522ae5548..5aee1c0169e 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data)
{
const char *name = data;
- if (strcmp(name, dev->bus_id) == 0)
- return 1;
- return 0;
+ return sysfs_streq(name, dev->bus_id);
}
/**
@@ -982,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
}
EXPORT_SYMBOL_GPL(bus_get_device_klist);
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily. It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process. It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void device_insertion_sort_klist(struct device *a, struct list_head *list,
+ int (*compare)(const struct device *a,
+ const struct device *b))
+{
+ struct list_head *pos;
+ struct klist_node *n;
+ struct device *b;
+
+ list_for_each(pos, list) {
+ n = container_of(pos, struct klist_node, n_node);
+ b = container_of(n, struct device, knode_bus);
+ if (compare(a, b) <= 0) {
+ list_move_tail(&a->knode_bus.n_node,
+ &b->knode_bus.n_node);
+ return;
+ }
+ }
+ list_move_tail(&a->knode_bus.n_node, list);
+}
+
+void bus_sort_breadthfirst(struct bus_type *bus,
+ int (*compare)(const struct device *a,
+ const struct device *b))
+{
+ LIST_HEAD(sorted_devices);
+ struct list_head *pos, *tmp;
+ struct klist_node *n;
+ struct device *dev;
+ struct klist *device_klist;
+
+ device_klist = bus_get_device_klist(bus);
+
+ spin_lock(&device_klist->k_lock);
+ list_for_each_safe(pos, tmp, &device_klist->k_list) {
+ n = container_of(pos, struct klist_node, n_node);
+ dev = container_of(n, struct device, knode_bus);
+ device_insertion_sort_klist(dev, &sorted_devices, compare);
+ }
+ list_splice(&sorted_devices, &device_klist->k_list);
+ spin_unlock(&device_klist->k_lock);
+}
+EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+
int __init buses_init(void)
{
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index cc5e28c8885..eb85e431230 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -135,6 +135,20 @@ static void remove_class_attrs(struct class *cls)
}
}
+static void klist_class_dev_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_class);
+
+ get_device(dev);
+}
+
+static void klist_class_dev_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_class);
+
+ put_device(dev);
+}
+
int __class_register(struct class *cls, struct lock_class_key *key)
{
struct class_private *cp;
@@ -145,7 +159,7 @@ int __class_register(struct class *cls, struct lock_class_key *key)
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
if (!cp)
return -ENOMEM;
- INIT_LIST_HEAD(&cp->class_devices);
+ klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put);
INIT_LIST_HEAD(&cp->class_interfaces);
kset_init(&cp->class_dirs);
__mutex_init(&cp->class_mutex, "struct class mutex", key);
@@ -269,6 +283,71 @@ char *make_class_name(const char *name, struct kobject *kobj)
#endif
/**
+ * class_dev_iter_init - initialize class device iterator
+ * @iter: class iterator to initialize
+ * @class: the class we wanna iterate over
+ * @start: the device to start iterating from, if any
+ * @type: device_type of the devices to iterate over, NULL for all
+ *
+ * Initialize class iterator @iter such that it iterates over devices
+ * of @class. If @start is set, the list iteration will start there,
+ * otherwise if it is NULL, the iteration starts at the beginning of
+ * the list.
+ */
+void class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
+ struct device *start, const struct device_type *type)
+{
+ struct klist_node *start_knode = NULL;
+
+ if (start)
+ start_knode = &start->knode_class;
+ klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode);
+ iter->type = type;
+}
+EXPORT_SYMBOL_GPL(class_dev_iter_init);
+
+/**
+ * class_dev_iter_next - iterate to the next device
+ * @iter: class iterator to proceed
+ *
+ * Proceed @iter to the next device and return it. Returns NULL if
+ * iteration is complete.
+ *
+ * The returned device is referenced and won't be released till
+ * iterator is proceed to the next device or exited. The caller is
+ * free to do whatever it wants to do with the device including
+ * calling back into class code.
+ */
+struct device *class_dev_iter_next(struct class_dev_iter *iter)
+{
+ struct klist_node *knode;
+ struct device *dev;
+
+ while (1) {
+ knode = klist_next(&iter->ki);
+ if (!knode)
+ return NULL;
+ dev = container_of(knode, struct device, knode_class);
+ if (!iter->type || iter->type == dev->type)
+ return dev;
+ }
+}
+EXPORT_SYMBOL_GPL(class_dev_iter_next);
+
+/**
+ * class_dev_iter_exit - finish iteration
+ * @iter: class iterator to finish
+ *
+ * Finish an iteration. Always call this function after iteration is
+ * complete whether the iteration ran till the end or not.
+ */
+void class_dev_iter_exit(struct class_dev_iter *iter)
+{
+ klist_iter_exit(&iter->ki);
+}
+EXPORT_SYMBOL_GPL(class_dev_iter_exit);
+
+/**
* class_for_each_device - device iterator
* @class: the class we're iterating
* @start: the device to start with in the list, if any.
@@ -283,13 +362,13 @@ char *make_class_name(const char *name, struct kobject *kobj)
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
- * Note, we hold class->class_mutex in this function, so it can not be
- * re-acquired in @fn, otherwise it will self-deadlocking. For
- * example, calls to add or remove class members would be verboten.
+ * @fn is allowed to do anything including calling back into class
+ * code. There's no locking restriction.
*/
int class_for_each_device(struct class *class, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
+ struct class_dev_iter iter;
struct device *dev;
int error = 0;
@@ -301,20 +380,13 @@ int class_for_each_device(struct class *class, struct device *start,
return -EINVAL;
}
- mutex_lock(&class->p->class_mutex);
- list_for_each_entry(dev, &class->p->class_devices, node) {
- if (start) {
- if (start == dev)
- start = NULL;
- continue;
- }
- dev = get_device(dev);
+ class_dev_iter_init(&iter, class, start, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
error = fn(dev, data);
- put_device(dev);
if (error)
break;
}
- mutex_unlock(&class->p->class_mutex);
+ class_dev_iter_exit(&iter);
return error;
}
@@ -337,16 +409,15 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
*
* Note, you will need to drop the reference with put_device() after use.
*
- * We hold class->class_mutex in this function, so it can not be
- * re-acquired in @match, otherwise it will self-deadlocking. For
- * example, calls to add or remove class members would be verboten.
+ * @fn is allowed to do anything including calling back into class
+ * code. There's no locking restriction.
*/
struct device *class_find_device(struct class *class, struct device *start,
void *data,
int (*match)(struct device *, void *))
{
+ struct class_dev_iter iter;
struct device *dev;
- int found = 0;
if (!class)
return NULL;
@@ -356,29 +427,23 @@ struct device *class_find_device(struct class *class, struct device *start,
return NULL;
}
- mutex_lock(&class->p->class_mutex);
- list_for_each_entry(dev, &class->p->class_devices, node) {
- if (start) {
- if (start == dev)
- start = NULL;
- continue;
- }
- dev = get_device(dev);
+ class_dev_iter_init(&iter, class, start, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
if (match(dev, data)) {
- found = 1;
+ get_device(dev);
break;
- } else
- put_device(dev);
+ }
}
- mutex_unlock(&class->p->class_mutex);
+ class_dev_iter_exit(&iter);
- return found ? dev : NULL;
+ return dev;
}
EXPORT_SYMBOL_GPL(class_find_device);
int class_interface_register(struct class_interface *class_intf)
{
struct class *parent;
+ struct class_dev_iter iter;
struct device *dev;
if (!class_intf || !class_intf->class)
@@ -391,8 +456,10 @@ int class_interface_register(struct class_interface *class_intf)
mutex_lock(&parent->p->class_mutex);
list_add_tail(&class_intf->node, &parent->p->class_interfaces);
if (class_intf->add_dev) {
- list_for_each_entry(dev, &parent->p->class_devices, node)
+ class_dev_iter_init(&iter, parent, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter)))
class_intf->add_dev(dev, class_intf);
+ class_dev_iter_exit(&iter);
}
mutex_unlock(&parent->p->class_mutex);
@@ -402,6 +469,7 @@ int class_interface_register(struct class_interface *class_intf)
void class_interface_unregister(struct class_interface *class_intf)
{
struct class *parent = class_intf->class;
+ struct class_dev_iter iter;
struct device *dev;
if (!parent)
@@ -410,8 +478,10 @@ void class_interface_unregister(struct class_interface *class_intf)
mutex_lock(&parent->p->class_mutex);
list_del_init(&class_intf->node);
if (class_intf->remove_dev) {
- list_for_each_entry(dev, &parent->p->class_devices, node)
+ class_dev_iter_init(&iter, parent, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter)))
class_intf->remove_dev(dev, class_intf);
+ class_dev_iter_exit(&iter);
}
mutex_unlock(&parent->p->class_mutex);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d021c98605b..8c2cc2648f5 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n)
* device_initialize - init device structure.
* @dev: device.
*
- * This prepares the device for use by other layers,
- * including adding it to the device hierarchy.
+ * This prepares the device for use by other layers by initializing
+ * its fields.
* It is the first half of device_register(), if called by
- * that, though it can also be called separately, so one
- * may use @dev's fields (e.g. the refcount).
+ * that function, though it can also be called separately, so one
+ * may use @dev's fields. In particular, get_device()/put_device()
+ * may be used for reference counting of @dev after calling this
+ * function.
+ *
+ * NOTE: Use put_device() to give up your reference instead of freeing
+ * @dev directly once you have called this function.
*/
void device_initialize(struct device *dev)
{
@@ -536,7 +541,6 @@ void device_initialize(struct device *dev)
klist_init(&dev->klist_children, klist_children_get,
klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools);
- INIT_LIST_HEAD(&dev->node);
init_MUTEX(&dev->sem);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
@@ -836,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev)
* This is part 2 of device_register(), though may be called
* separately _iff_ device_initialize() has been called separately.
*
- * This adds it to the kobject hierarchy via kobject_add(), adds it
+ * This adds @dev to the kobject hierarchy via kobject_add(), adds it
* to the global and sibling lists for the device, then
* adds it to the other relevant subsystems of the driver model.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up your
+ * reference instead.
*/
int device_add(struct device *dev)
{
@@ -916,7 +924,8 @@ int device_add(struct device *dev)
if (dev->class) {
mutex_lock(&dev->class->p->class_mutex);
/* tie the class to the device */
- list_add_tail(&dev->node, &dev->class->p->class_devices);
+ klist_add_tail(&dev->knode_class,
+ &dev->class->p->class_devices);
/* notify any interfaces that the device is here */
list_for_each_entry(class_intf,
@@ -965,6 +974,10 @@ done:
* I.e. you should only call the two helpers separately if
* have a clearly defined need to use and refcount the device
* before it is added to the hierarchy.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up the
+ * reference initialized in this function instead.
*/
int device_register(struct device *dev)
{
@@ -1032,7 +1045,7 @@ void device_del(struct device *dev)
if (class_intf->remove_dev)
class_intf->remove_dev(dev, class_intf);
/* remove the device from the class list */
- list_del_init(&dev->node);
+ klist_del(&dev->knode_class);
mutex_unlock(&dev->class->p->class_mutex);
}
device_remove_file(dev, &uevent_attr);
@@ -1243,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
return dev;
error:
- kfree(dev);
+ put_device(dev);
return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(device_create_vargs);
@@ -1314,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
* device_rename - renames a device
* @dev: the pointer to the struct device to be renamed
* @new_name: the new name of the device
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of device_rename
+ * on the same device to ensure that new_name is valid and
+ * won't conflict with other devices.
*/
int device_rename(struct device *dev, char *new_name)
{
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3ac443b2ac0..20febc00a52 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data)
* is an error.
*/
+ if (drv->bus->match && !drv->bus->match(dev, drv))
+ return 0;
+
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index c9c92b00fd5..b7e571031ec 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -164,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev,
}
/* fallthrough */
default:
- printk(KERN_ERR "%s: unexpected value (%d)\n", __func__,
- loading);
+ dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
/* fallthrough */
case -1:
fw_load_abort(fw_priv);
@@ -309,7 +308,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
*dev_p = NULL;
if (!fw_priv || !f_dev) {
- printk(KERN_ERR "%s: kmalloc failed\n", __func__);
+ dev_err(device, "%s: kmalloc failed\n", __func__);
retval = -ENOMEM;
goto error_kfree;
}
@@ -329,8 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
f_dev->uevent_suppress = 1;
retval = device_register(f_dev);
if (retval) {
- printk(KERN_ERR "%s: device_register failed\n",
- __func__);
+ dev_err(device, "%s: device_register failed\n", __func__);
goto error_kfree;
}
*dev_p = f_dev;
@@ -363,15 +361,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
fw_priv->fw = fw;
retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
if (retval) {
- printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
- __func__);
+ dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
goto error_unreg;
}
retval = device_create_file(f_dev, &dev_attr_loading);
if (retval) {
- printk(KERN_ERR "%s: device_create_file failed\n",
- __func__);
+ dev_err(device, "%s: device_create_file failed\n", __func__);
goto error_unreg;
}
@@ -401,8 +397,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
- printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
- __func__);
+ dev_err(device, "%s: kmalloc(struct firmware) failed\n",
+ __func__);
retval = -ENOMEM;
goto out;
}
@@ -411,15 +407,15 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
builtin++) {
if (strcmp(name, builtin->name))
continue;
- printk(KERN_INFO "firmware: using built-in firmware %s\n",
- name);
+ dev_info(device, "firmware: using built-in firmware %s\n",
+ name);
firmware->size = builtin->size;
firmware->data = builtin->data;
return 0;
}
if (uevent)
- printk(KERN_INFO "firmware: requesting %s\n", name);
+ dev_info(device, "firmware: requesting %s\n", name);
retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
if (retval)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3f940393d6c..dfcbfe50486 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -42,10 +42,8 @@ struct resource *platform_get_resource(struct platform_device *dev,
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
- if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
- IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
- if (num-- == 0)
- return r;
+ if (type == resource_type(r) && num-- == 0)
+ return r;
}
return NULL;
}
@@ -78,10 +76,8 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
- if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
- IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
- if (!strcmp(r->name, name))
- return r;
+ if (type == resource_type(r) && !strcmp(r->name, name))
+ return r;
}
return NULL;
}
@@ -259,9 +255,9 @@ int platform_device_add(struct platform_device *pdev)
p = r->parent;
if (!p) {
- if (r->flags & IORESOURCE_MEM)
+ if (resource_type(r) == IORESOURCE_MEM)
p = &iomem_resource;
- else if (r->flags & IORESOURCE_IO)
+ else if (resource_type(r) == IORESOURCE_IO)
p = &ioport_resource;
}
@@ -282,9 +278,14 @@ int platform_device_add(struct platform_device *pdev)
return ret;
failed:
- while (--i >= 0)
- if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
- release_resource(&pdev->resource[i]);
+ while (--i >= 0) {
+ struct resource *r = &pdev->resource[i];
+ unsigned long type = resource_type(r);
+
+ if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+ release_resource(r);
+ }
+
return ret;
}
EXPORT_SYMBOL_GPL(platform_device_add);
@@ -306,7 +307,9 @@ void platform_device_del(struct platform_device *pdev)
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
- if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
+ unsigned long type = resource_type(r);
+
+ if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
release_resource(r);
}
}
@@ -391,6 +394,53 @@ error:
}
EXPORT_SYMBOL_GPL(platform_device_register_simple);
+/**
+ * platform_device_register_data
+ * @parent: parent device for the device we're adding
+ * @name: base name of the device we're adding
+ * @id: instance id
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * This function creates a simple platform device that requires minimal
+ * resource and memory management. Canned release function freeing memory
+ * allocated for the device allows drivers using such devices to be
+ * unloaded without waiting for the last reference to the device to be
+ * dropped.
+ */
+struct platform_device *platform_device_register_data(
+ struct device *parent,
+ const char *name, int id,
+ const void *data, size_t size)
+{
+ struct platform_device *pdev;
+ int retval;
+
+ pdev = platform_device_alloc(name, id);
+ if (!pdev) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ pdev->dev.parent = parent;
+
+ if (size) {
+ retval = platform_device_add_data(pdev, data, size);
+ if (retval)
+ goto error;
+ }
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto error;
+
+ return pdev;
+
+error:
+ platform_device_put(pdev);
+ return ERR_PTR(retval);
+}
+
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
@@ -862,7 +912,7 @@ static int platform_pm_restore_noirq(struct device *dev)
#endif /* !CONFIG_HIBERNATION */
-struct pm_ext_ops platform_pm_ops = {
+static struct pm_ext_ops platform_pm_ops = {
.base = {
.prepare = platform_pm_prepare,
.complete = platform_pm_complete,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 273a944d404..692c20ba514 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -83,7 +83,7 @@ void device_pm_add(struct device *dev)
* transition is in progress in order to avoid leaving them
* unhandled down the road
*/
- WARN_ON(true);
+ dev_WARN(dev, "Parentless device registered during a PM transaction\n");
}
list_add_tail(&dev->power.entry, &dpm_list);
@@ -778,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend);
void __suspend_report_result(const char *function, void *fn, int ret)
{
- if (ret) {
- printk(KERN_ERR "%s(): ", function);
- print_fn_descriptor_symbol("%s returns ", fn);
- printk("%d\n", ret);
- }
+ if (ret)
+ printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
}
EXPORT_SYMBOL_GPL(__suspend_report_result);
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 5b4c6e649c1..93f3690396a 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -159,11 +159,8 @@ struct aoedev {
sector_t ssize;
struct timer_list timer;
spinlock_t lock;
- struct sk_buff *sendq_hd; /* packets needing to be sent, list head */
- struct sk_buff *sendq_tl;
- struct sk_buff *skbpool_hd;
- struct sk_buff *skbpool_tl;
- int nskbpool;
+ struct sk_buff_head sendq;
+ struct sk_buff_head skbpool;
mempool_t *bufpool; /* for deadlock-free Buf allocation */
struct list_head bufq; /* queue of bios to work on */
struct buf *inprocess; /* the one we're currently working on */
@@ -199,7 +196,7 @@ int aoedev_flush(const char __user *str, size_t size);
int aoenet_init(void);
void aoenet_exit(void);
-void aoenet_xmit(struct sk_buff *);
+void aoenet_xmit(struct sk_buff_head *);
int is_aoe_netif(struct net_device *ifp);
int set_aoe_iflist(const char __user *str, size_t size);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 0c39782b266..b82654e883a 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -109,12 +109,12 @@ static const struct attribute_group attr_group = {
static int
aoedisk_add_sysfs(struct aoedev *d)
{
- return sysfs_create_group(&d->gd->dev.kobj, &attr_group);
+ return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group);
}
void
aoedisk_rm_sysfs(struct aoedev *d)
{
- sysfs_remove_group(&d->gd->dev.kobj, &attr_group);
+ sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group);
}
static int
@@ -158,9 +158,9 @@ aoeblk_release(struct inode *inode, struct file *filp)
static int
aoeblk_make_request(struct request_queue *q, struct bio *bio)
{
+ struct sk_buff_head queue;
struct aoedev *d;
struct buf *buf;
- struct sk_buff *sl;
ulong flags;
blk_queue_bounce(q, &bio);
@@ -213,11 +213,11 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
list_add_tail(&buf->bufs, &d->bufq);
aoecmd_work(d);
- sl = d->sendq_hd;
- d->sendq_hd = d->sendq_tl = NULL;
+ __skb_queue_head_init(&queue);
+ skb_queue_splice_init(&d->sendq, &queue);
spin_unlock_irqrestore(&d->lock, flags);
- aoenet_xmit(sl);
+ aoenet_xmit(&queue);
return 0;
}
@@ -276,7 +276,7 @@ aoeblk_gdalloc(void *vp)
gd->first_minor = d->sysminor * AOE_PARTITIONS;
gd->fops = &aoe_bdops;
gd->private_data = d;
- gd->capacity = d->ssize;
+ set_capacity(gd, d->ssize);
snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
d->aoemajor, d->aoeminor);
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 181ebb85f0b..200efc4d2c1 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -9,6 +9,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
+#include <linux/skbuff.h>
#include "aoe.h"
enum {
@@ -103,7 +104,12 @@ loop:
spin_lock_irqsave(&d->lock, flags);
goto loop;
}
- aoenet_xmit(skb);
+ if (skb) {
+ struct sk_buff_head queue;
+ __skb_queue_head_init(&queue);
+ __skb_queue_tail(&queue, skb);
+ aoenet_xmit(&queue);
+ }
aoecmd_cfg(major, minor);
return 0;
}
@@ -278,9 +284,9 @@ aoechr_init(void)
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- device_create_drvdata(aoe_class, NULL,
- MKDEV(AOE_MAJOR, chardevs[i].minor),
- NULL, chardevs[i].name);
+ device_create(aoe_class, NULL,
+ MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
+ chardevs[i].name);
return 0;
}
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 2f1746295d0..71ff78c9e4d 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -114,29 +114,22 @@ ifrotate(struct aoetgt *t)
static void
skb_pool_put(struct aoedev *d, struct sk_buff *skb)
{
- if (!d->skbpool_hd)
- d->skbpool_hd = skb;
- else
- d->skbpool_tl->next = skb;
- d->skbpool_tl = skb;
+ __skb_queue_tail(&d->skbpool, skb);
}
static struct sk_buff *
skb_pool_get(struct aoedev *d)
{
- struct sk_buff *skb;
+ struct sk_buff *skb = skb_peek(&d->skbpool);
- skb = d->skbpool_hd;
if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) {
- d->skbpool_hd = skb->next;
- skb->next = NULL;
+ __skb_unlink(skb, &d->skbpool);
return skb;
}
- if (d->nskbpool < NSKBPOOLMAX
- && (skb = new_skb(ETH_ZLEN))) {
- d->nskbpool++;
+ if (skb_queue_len(&d->skbpool) < NSKBPOOLMAX &&
+ (skb = new_skb(ETH_ZLEN)))
return skb;
- }
+
return NULL;
}
@@ -293,29 +286,22 @@ aoecmd_ata_rw(struct aoedev *d)
skb->dev = t->ifp->nd;
skb = skb_clone(skb, GFP_ATOMIC);
- if (skb) {
- if (d->sendq_hd)
- d->sendq_tl->next = skb;
- else
- d->sendq_hd = skb;
- d->sendq_tl = skb;
- }
+ if (skb)
+ __skb_queue_tail(&d->sendq, skb);
return 1;
}
/* some callers cannot sleep, and they can call this function,
* transmitting the packets later, when interrupts are on
*/
-static struct sk_buff *
-aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
+static void
+aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *queue)
{
struct aoe_hdr *h;
struct aoe_cfghdr *ch;
- struct sk_buff *skb, *sl, *sl_tail;
+ struct sk_buff *skb;
struct net_device *ifp;
- sl = sl_tail = NULL;
-
read_lock(&dev_base_lock);
for_each_netdev(&init_net, ifp) {
dev_hold(ifp);
@@ -329,8 +315,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
}
skb_put(skb, sizeof *h + sizeof *ch);
skb->dev = ifp;
- if (sl_tail == NULL)
- sl_tail = skb;
+ __skb_queue_tail(queue, skb);
h = (struct aoe_hdr *) skb_mac_header(skb);
memset(h, 0, sizeof *h + sizeof *ch);
@@ -342,16 +327,10 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
h->minor = aoeminor;
h->cmd = AOECMD_CFG;
- skb->next = sl;
- sl = skb;
cont:
dev_put(ifp);
}
read_unlock(&dev_base_lock);
-
- if (tail != NULL)
- *tail = sl_tail;
- return sl;
}
static void
@@ -406,11 +385,7 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
skb = skb_clone(skb, GFP_ATOMIC);
if (skb == NULL)
return;
- if (d->sendq_hd)
- d->sendq_tl->next = skb;
- else
- d->sendq_hd = skb;
- d->sendq_tl = skb;
+ __skb_queue_tail(&d->sendq, skb);
}
static int
@@ -508,16 +483,15 @@ ata_scnt(unsigned char *packet) {
static void
rexmit_timer(ulong vp)
{
+ struct sk_buff_head queue;
struct aoedev *d;
struct aoetgt *t, **tt, **te;
struct aoeif *ifp;
struct frame *f, *e;
- struct sk_buff *sl;
register long timeout;
ulong flags, n;
d = (struct aoedev *) vp;
- sl = NULL;
/* timeout is always ~150% of the moving average */
timeout = d->rttavg;
@@ -589,7 +563,7 @@ rexmit_timer(ulong vp)
}
}
- if (d->sendq_hd) {
+ if (!skb_queue_empty(&d->sendq)) {
n = d->rttavg <<= 1;
if (n > MAXTIMER)
d->rttavg = MAXTIMER;
@@ -600,15 +574,15 @@ rexmit_timer(ulong vp)
aoecmd_work(d);
}
- sl = d->sendq_hd;
- d->sendq_hd = d->sendq_tl = NULL;
+ __skb_queue_head_init(&queue);
+ skb_queue_splice_init(&d->sendq, &queue);
d->timer.expires = jiffies + TIMERTICK;
add_timer(&d->timer);
spin_unlock_irqrestore(&d->lock, flags);
- aoenet_xmit(sl);
+ aoenet_xmit(&queue);
}
/* enters with d->lock held */
@@ -645,7 +619,7 @@ aoecmd_sleepwork(struct work_struct *work)
unsigned long flags;
u64 ssize;
- ssize = d->gd->capacity;
+ ssize = get_capacity(d->gd);
bd = bdget_disk(d->gd, 0);
if (bd) {
@@ -707,7 +681,7 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
return;
if (d->gd != NULL) {
- d->gd->capacity = ssize;
+ set_capacity(d->gd, ssize);
d->flags |= DEVFL_NEWSIZE;
} else
d->flags |= DEVFL_GDALLOC;
@@ -756,23 +730,28 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector
unsigned long n_sect = bio->bi_size >> 9;
const int rw = bio_data_dir(bio);
struct hd_struct *part;
+ int cpu;
+
+ cpu = part_stat_lock();
+ part = disk_map_sector_rcu(disk, sector);
+
+ part_stat_inc(cpu, part, ios[rw]);
+ part_stat_add(cpu, part, ticks[rw], duration);
+ part_stat_add(cpu, part, sectors[rw], n_sect);
+ part_stat_add(cpu, part, io_ticks, duration);
- part = get_part(disk, sector);
- all_stat_inc(disk, part, ios[rw], sector);
- all_stat_add(disk, part, ticks[rw], duration, sector);
- all_stat_add(disk, part, sectors[rw], n_sect, sector);
- all_stat_add(disk, part, io_ticks, duration, sector);
+ part_stat_unlock();
}
void
aoecmd_ata_rsp(struct sk_buff *skb)
{
+ struct sk_buff_head queue;
struct aoedev *d;
struct aoe_hdr *hin, *hout;
struct aoe_atahdr *ahin, *ahout;
struct frame *f;
struct buf *buf;
- struct sk_buff *sl;
struct aoetgt *t;
struct aoeif *ifp;
register long n;
@@ -893,21 +872,21 @@ aoecmd_ata_rsp(struct sk_buff *skb)
aoecmd_work(d);
xmit:
- sl = d->sendq_hd;
- d->sendq_hd = d->sendq_tl = NULL;
+ __skb_queue_head_init(&queue);
+ skb_queue_splice_init(&d->sendq, &queue);
spin_unlock_irqrestore(&d->lock, flags);
- aoenet_xmit(sl);
+ aoenet_xmit(&queue);
}
void
aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
{
- struct sk_buff *sl;
+ struct sk_buff_head queue;
- sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL);
-
- aoenet_xmit(sl);
+ __skb_queue_head_init(&queue);
+ aoecmd_cfg_pkts(aoemajor, aoeminor, &queue);
+ aoenet_xmit(&queue);
}
struct sk_buff *
@@ -1076,7 +1055,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
spin_unlock_irqrestore(&d->lock, flags);
- aoenet_xmit(sl);
+ if (sl) {
+ struct sk_buff_head queue;
+ __skb_queue_head_init(&queue);
+ __skb_queue_tail(&queue, sl);
+ aoenet_xmit(&queue);
+ }
}
void
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index a1d813ab0d6..cc250577d40 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -91,7 +91,7 @@ aoedev_downdev(struct aoedev *d)
}
if (d->gd)
- d->gd->capacity = 0;
+ set_capacity(d->gd, 0);
d->flags &= ~DEVFL_UP;
}
@@ -188,14 +188,12 @@ skbfree(struct sk_buff *skb)
static void
skbpoolfree(struct aoedev *d)
{
- struct sk_buff *skb;
+ struct sk_buff *skb, *tmp;
- while ((skb = d->skbpool_hd)) {
- d->skbpool_hd = skb->next;
- skb->next = NULL;
+ skb_queue_walk_safe(&d->skbpool, skb, tmp)
skbfree(skb);
- }
- d->skbpool_tl = NULL;
+
+ __skb_queue_head_init(&d->skbpool);
}
/* find it or malloc it */
@@ -217,6 +215,8 @@ aoedev_by_sysminor_m(ulong sysminor)
goto out;
INIT_WORK(&d->work, aoecmd_sleepwork);
spin_lock_init(&d->lock);
+ skb_queue_head_init(&d->sendq);
+ skb_queue_head_init(&d->skbpool);
init_timer(&d->timer);
d->timer.data = (ulong) d;
d->timer.function = dummy_timer;
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index 7b15a5e9cec..7f83ad90e76 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -7,6 +7,7 @@
#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/module.h>
+#include <linux/skbuff.h>
#include "aoe.h"
MODULE_LICENSE("GPL");
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 0c81ca73128..9157d64270c 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -95,13 +95,12 @@ mac_addr(char addr[6])
}
void
-aoenet_xmit(struct sk_buff *sl)
+aoenet_xmit(struct sk_buff_head *queue)
{
- struct sk_buff *skb;
+ struct sk_buff *skb, *tmp;
- while ((skb = sl)) {
- sl = sl->next;
- skb->next = skb->prev = NULL;
+ skb_queue_walk_safe(queue, skb, tmp) {
+ __skb_unlink(skb, queue);
dev_queue_xmit(skb);
}
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 49f274197b1..432cf401829 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1882,10 +1882,6 @@ static int __init atari_floppy_init (void)
/* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
return -ENODEV;
- if (MACH_IS_HADES)
- /* Hades doesn't have Atari-compatible floppy */
- return -ENODEV;
-
if (register_blkdev(FLOPPY_MAJOR,"fd"))
return -EBUSY;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b73116ef923..1e1f9153000 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3460,8 +3460,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not");
hba[i]->cmd_pool_bits =
- kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG -
- 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
+ kmalloc(DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG)
+ * sizeof(unsigned long), GFP_KERNEL);
hba[i]->cmd_pool = (CommandList_struct *)
pci_alloc_consistent(hba[i]->pdev,
hba[i]->nr_cmds * sizeof(CommandList_struct),
@@ -3493,8 +3493,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* command and error info recs zeroed out before
they are used */
memset(hba[i]->cmd_pool_bits, 0,
- ((hba[i]->nr_cmds + BITS_PER_LONG -
- 1) / BITS_PER_LONG) * sizeof(unsigned long));
+ DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG)
+ * sizeof(unsigned long));
hba[i]->num_luns = 0;
hba[i]->highest_lun = -1;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e1233aabda7..a3fd87b4144 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -365,7 +365,7 @@ struct scsi2map {
static int
cciss_scsi_add_entry(int ctlr, int hostno,
- unsigned char *scsi3addr, int devtype,
+ struct cciss_scsi_dev_t *device,
struct scsi2map *added, int *nadded)
{
/* assumes hba[ctlr]->scsi_ctlr->lock is held */
@@ -384,12 +384,12 @@ cciss_scsi_add_entry(int ctlr, int hostno,
lun = 0;
/* Is this device a non-zero lun of a multi-lun device */
/* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
- if (scsi3addr[4] != 0) {
+ if (device->scsi3addr[4] != 0) {
/* Search through our list and find the device which */
/* has the same 8 byte LUN address, excepting byte 4. */
/* Assign the same bus and target for this new LUN. */
/* Use the logical unit number from the firmware. */
- memcpy(addr1, scsi3addr, 8);
+ memcpy(addr1, device->scsi3addr, 8);
addr1[4] = 0;
for (i = 0; i < n; i++) {
sd = &ccissscsi[ctlr].dev[i];
@@ -399,7 +399,7 @@ cciss_scsi_add_entry(int ctlr, int hostno,
if (memcmp(addr1, addr2, 8) == 0) {
bus = sd->bus;
target = sd->target;
- lun = scsi3addr[4];
+ lun = device->scsi3addr[4];
break;
}
}
@@ -420,8 +420,12 @@ cciss_scsi_add_entry(int ctlr, int hostno,
added[*nadded].lun = sd->lun;
(*nadded)++;
- memcpy(&sd->scsi3addr[0], scsi3addr, 8);
- sd->devtype = devtype;
+ memcpy(sd->scsi3addr, device->scsi3addr, 8);
+ memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
+ memcpy(sd->revision, device->revision, sizeof(sd->revision));
+ memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
+ sd->devtype = device->devtype;
+
ccissscsi[ctlr].ndevices++;
/* initially, (before registering with scsi layer) we don't
@@ -487,6 +491,22 @@ static void fixup_botched_add(int ctlr, char *scsi3addr)
CPQ_TAPE_UNLOCK(ctlr, flags);
}
+static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
+ struct cciss_scsi_dev_t *dev2)
+{
+ return dev1->devtype == dev2->devtype &&
+ memcmp(dev1->scsi3addr, dev2->scsi3addr,
+ sizeof(dev1->scsi3addr)) == 0 &&
+ memcmp(dev1->device_id, dev2->device_id,
+ sizeof(dev1->device_id)) == 0 &&
+ memcmp(dev1->vendor, dev2->vendor,
+ sizeof(dev1->vendor)) == 0 &&
+ memcmp(dev1->model, dev2->model,
+ sizeof(dev1->model)) == 0 &&
+ memcmp(dev1->revision, dev2->revision,
+ sizeof(dev1->revision)) == 0;
+}
+
static int
adjust_cciss_scsi_table(int ctlr, int hostno,
struct cciss_scsi_dev_t sd[], int nsds)
@@ -532,7 +552,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
for (j=0;j<nsds;j++) {
if (SCSI3ADDR_EQ(sd[j].scsi3addr,
csd->scsi3addr)) {
- if (sd[j].devtype == csd->devtype)
+ if (device_is_the_same(&sd[j], csd))
found=2;
else
found=1;
@@ -548,22 +568,26 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
cciss_scsi_remove_entry(ctlr, hostno, i,
removed, &nremoved);
/* remove ^^^, hence i not incremented */
- }
- else if (found == 1) { /* device is different kind */
+ } else if (found == 1) { /* device is different in some way */
changes++;
- printk("cciss%d: device c%db%dt%dl%d type changed "
- "(device type now %s).\n",
- ctlr, hostno, csd->bus, csd->target, csd->lun,
- scsi_device_type(csd->devtype));
+ printk("cciss%d: device c%db%dt%dl%d has changed.\n",
+ ctlr, hostno, csd->bus, csd->target, csd->lun);
cciss_scsi_remove_entry(ctlr, hostno, i,
removed, &nremoved);
/* remove ^^^, hence i not incremented */
- if (cciss_scsi_add_entry(ctlr, hostno,
- &sd[j].scsi3addr[0], sd[j].devtype,
+ if (cciss_scsi_add_entry(ctlr, hostno, &sd[j],
added, &nadded) != 0)
/* we just removed one, so add can't fail. */
BUG();
csd->devtype = sd[j].devtype;
+ memcpy(csd->device_id, sd[j].device_id,
+ sizeof(csd->device_id));
+ memcpy(csd->vendor, sd[j].vendor,
+ sizeof(csd->vendor));
+ memcpy(csd->model, sd[j].model,
+ sizeof(csd->model));
+ memcpy(csd->revision, sd[j].revision,
+ sizeof(csd->revision));
} else /* device is same as it ever was, */
i++; /* so just move along. */
}
@@ -577,7 +601,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
csd = &ccissscsi[ctlr].dev[j];
if (SCSI3ADDR_EQ(sd[i].scsi3addr,
csd->scsi3addr)) {
- if (sd[i].devtype == csd->devtype)
+ if (device_is_the_same(&sd[i], csd))
found=2; /* found device */
else
found=1; /* found a bug. */
@@ -586,16 +610,14 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
}
if (!found) {
changes++;
- if (cciss_scsi_add_entry(ctlr, hostno,
-
- &sd[i].scsi3addr[0], sd[i].devtype,
+ if (cciss_scsi_add_entry(ctlr, hostno, &sd[i],
added, &nadded) != 0)
break;
} else if (found == 1) {
/* should never happen... */
changes++;
- printk("cciss%d: device unexpectedly changed type\n",
- ctlr);
+ printk(KERN_WARNING "cciss%d: device "
+ "unexpectedly changed\n", ctlr);
/* but if it does happen, we just ignore that device */
}
}
@@ -1012,7 +1034,8 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
- unsigned char *buf, unsigned char bufsize)
+ unsigned char page, unsigned char *buf,
+ unsigned char bufsize)
{
int rc;
CommandList_struct *cp;
@@ -1032,8 +1055,8 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
ei = cp->err_info;
cdb[0] = CISS_INQUIRY;
- cdb[1] = 0;
- cdb[2] = 0;
+ cdb[1] = (page != 0);
+ cdb[2] = page;
cdb[3] = 0;
cdb[4] = bufsize;
cdb[5] = 0;
@@ -1053,6 +1076,25 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
return rc;
}
+/* Get the device id from inquiry page 0x83 */
+static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr,
+ unsigned char *device_id, int buflen)
+{
+ int rc;
+ unsigned char *buf;
+
+ if (buflen > 16)
+ buflen = 16;
+ buf = kzalloc(64, GFP_KERNEL);
+ if (!buf)
+ return -1;
+ rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64);
+ if (rc == 0)
+ memcpy(device_id, &buf[8], buflen);
+ kfree(buf);
+ return rc != 0;
+}
+
static int
cciss_scsi_do_report_phys_luns(ctlr_info_t *c,
ReportLunData_struct *buf, int bufsize)
@@ -1142,25 +1184,21 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
ctlr_info_t *c;
__u32 num_luns=0;
unsigned char *ch;
- /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */
- struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
+ struct cciss_scsi_dev_t *currentsd, *this_device;
int ncurrent=0;
int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
int i;
c = (ctlr_info_t *) hba[cntl_num];
ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
- if (ld_buff == NULL) {
- printk(KERN_ERR "cciss: out of memory\n");
- return;
- }
inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
- if (inq_buff == NULL) {
- printk(KERN_ERR "cciss: out of memory\n");
- kfree(ld_buff);
- return;
+ currentsd = kzalloc(sizeof(*currentsd) *
+ (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
+ if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto out;
}
-
+ this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) {
ch = &ld_buff->LUNListLength[0];
num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
@@ -1179,23 +1217,34 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
/* adjust our table of devices */
- for(i=0; i<num_luns; i++)
- {
- int devtype;
-
+ for (i = 0; i < num_luns; i++) {
/* for each physical lun, do an inquiry */
if (ld_buff->LUN[i][3] & 0xC0) continue;
memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
- if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
- (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
+ if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff,
+ (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
/* Inquiry failed (msg printed already) */
- devtype = 0; /* so we will skip this device. */
- } else /* what kind of device is this? */
- devtype = (inq_buff[0] & 0x1f);
-
- switch (devtype)
+ continue; /* so we will skip this device. */
+
+ this_device->devtype = (inq_buff[0] & 0x1f);
+ this_device->bus = -1;
+ this_device->target = -1;
+ this_device->lun = -1;
+ memcpy(this_device->scsi3addr, scsi3addr, 8);
+ memcpy(this_device->vendor, &inq_buff[8],
+ sizeof(this_device->vendor));
+ memcpy(this_device->model, &inq_buff[16],
+ sizeof(this_device->model));
+ memcpy(this_device->revision, &inq_buff[32],
+ sizeof(this_device->revision));
+ memset(this_device->device_id, 0,
+ sizeof(this_device->device_id));
+ cciss_scsi_get_device_id(hba[cntl_num], scsi3addr,
+ this_device->device_id, sizeof(this_device->device_id));
+
+ switch (this_device->devtype)
{
case 0x05: /* CD-ROM */ {
@@ -1220,15 +1269,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
printk(KERN_INFO "cciss%d: %s ignored, "
"too many devices.\n", cntl_num,
- scsi_device_type(devtype));
+ scsi_device_type(this_device->devtype));
break;
}
- memcpy(&currentsd[ncurrent].scsi3addr[0],
- &scsi3addr[0], 8);
- currentsd[ncurrent].devtype = devtype;
- currentsd[ncurrent].bus = -1;
- currentsd[ncurrent].target = -1;
- currentsd[ncurrent].lun = -1;
+ currentsd[ncurrent] = *this_device;
ncurrent++;
break;
default:
@@ -1240,6 +1284,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
out:
kfree(inq_buff);
kfree(ld_buff);
+ kfree(currentsd);
return;
}
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index d9c2c586502..7b750245ae7 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -66,6 +66,10 @@ struct cciss_scsi_dev_t {
int devtype;
int bus, target, lun; /* as presented to the OS */
unsigned char scsi3addr[8]; /* as presented to the HW */
+ unsigned char device_id[16]; /* from inquiry pg. 0x83 */
+ unsigned char vendor[8]; /* bytes 8-15 of inquiry data */
+ unsigned char model[16]; /* bytes 16-31 of inquiry data */
+ unsigned char revision[4]; /* bytes 32-35 of inquiry data */
};
struct cciss_scsi_hba_t {
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 09c14341e6e..3d967525e9a 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -424,7 +424,7 @@ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t),
&(hba[i]->cmd_pool_dhandle));
hba[i]->cmd_pool_bits = kcalloc(
- (NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG, sizeof(unsigned long),
+ DIV_ROUND_UP(NR_CMDS, BITS_PER_LONG), sizeof(unsigned long),
GFP_KERNEL);
if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 395f8ea7981..2cea27aba9a 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -423,8 +423,15 @@ static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
* 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
* side 0 is on physical side 0 (but with the misnamed sector IDs).
* 'stretch' should probably be renamed to something more general, like
- * 'options'. Other parameters should be self-explanatory (see also
- * setfdprm(8)).
+ * 'options'.
+ *
+ * Bits 2 through 9 of 'stretch' tell the number of the first sector.
+ * The LSB (bit 2) is flipped. For most disks, the first sector
+ * is 1 (represented by 0x00<<2). For some CP/M and music sampler
+ * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2).
+ * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2).
+ *
+ * Other parameters should be self-explanatory (see also setfdprm(8)).
*/
/*
Size
@@ -1355,20 +1362,20 @@ static void fdc_specify(void)
}
/* Convert step rate from microseconds to milliseconds and 4 bits */
- srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR);
if (slow_floppy) {
srt = srt / 4;
}
SUPBOUND(srt, 0xf);
INFBOUND(srt, 0);
- hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR);
if (hlt < 0x01)
hlt = 0x01;
else if (hlt > 0x7f)
hlt = hlt_max_code;
- hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+ hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR);
if (hut < 0x1)
hut = 0x1;
else if (hut > 0xf)
@@ -2236,9 +2243,9 @@ static void setup_format_params(int track)
}
}
}
- if (_floppy->stretch & FD_ZEROBASED) {
+ if (_floppy->stretch & FD_SECTBASEMASK) {
for (count = 0; count < F_SECT_PER_TRACK; count++)
- here[count].sect--;
+ here[count].sect += FD_SECTBASE(_floppy) - 1;
}
}
@@ -2385,7 +2392,7 @@ static void rw_interrupt(void)
#ifdef FLOPPY_SANITY_CHECK
if (nr_sectors / ssize >
- (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
+ DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
DPRINT("long rw: %x instead of %lx\n",
nr_sectors, current_count_sectors);
printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
@@ -2649,7 +2656,7 @@ static int make_raw_rw_request(void)
}
HEAD = fsector_t / _floppy->sect;
- if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
+ if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
max_sector = _floppy->sect;
@@ -2679,7 +2686,7 @@ static int make_raw_rw_request(void)
CODE2SIZE;
SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
- ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
+ FD_SECTBASE(_floppy);
/* tracksize describes the size which can be filled up with sectors
* of size ssize.
@@ -3311,7 +3318,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
g->head <= 0 ||
g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
/* check if reserved bits are set */
- (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
+ (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
return -EINVAL;
if (type) {
if (!capable(CAP_SYS_ADMIN))
@@ -3356,7 +3363,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
if (DRS->maxblock > user_params[drive].sect ||
DRS->maxtrack ||
((user_params[drive].sect ^ oldStretch) &
- (FD_SWAPSIDES | FD_ZEROBASED)))
+ (FD_SWAPSIDES | FD_SECTBASEMASK)))
invalidate_drive(bdev);
else
process_fd_request();
@@ -4165,7 +4172,7 @@ static int __init floppy_init(void)
int i, unit, drive;
int err, dr;
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
if (check_legacy_ioport(FDC1))
return -ENODEV;
#endif
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 682243bf2e4..482c0c4b964 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -39,6 +39,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/blkpg.h>
+#include <linux/ata.h>
#include <linux/hdreg.h>
#define REALLY_SLOW_IO
@@ -370,7 +371,7 @@ repeat:
struct hd_i_struct *disk = &hd_info[i];
disk->special_op = disk->recalibrate = 1;
hd_out(disk, disk->sect, disk->sect, disk->head-1,
- disk->cyl, WIN_SPECIFY, &reset_hd);
+ disk->cyl, ATA_CMD_INIT_DEV_PARAMS, &reset_hd);
if (reset)
goto repeat;
} else
@@ -558,7 +559,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
{
if (disk->recalibrate) {
disk->recalibrate = 0;
- hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
+ hd_out(disk, disk->sect, 0, 0, 0, ATA_CMD_RESTORE, &recal_intr);
return reset;
}
if (disk->head > 16) {
@@ -631,13 +632,13 @@ repeat:
if (blk_fs_request(req)) {
switch (rq_data_dir(req)) {
case READ:
- hd_out(disk, nsect, sec, head, cyl, WIN_READ,
+ hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ,
&read_intr);
if (reset)
goto repeat;
break;
case WRITE:
- hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
+ hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_WRITE,
&write_intr);
if (reset)
goto repeat;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 1778e4a2c67..7b3351260d5 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -403,7 +403,7 @@ static int nbd_do_it(struct nbd_device *lo)
BUG_ON(lo->magic != LO_MAGIC);
lo->pid = current->pid;
- ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr);
+ ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
if (ret) {
printk(KERN_ERR "nbd: sysfs_create_file failed!");
return ret;
@@ -412,7 +412,7 @@ static int nbd_do_it(struct nbd_device *lo)
while ((req = nbd_read_stat(lo)) != NULL)
nbd_end_request(req);
- sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr);
+ sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index d731ca42f80..9dfa2716300 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -686,9 +686,8 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present)
- device_create_drvdata(pg_class, NULL,
- MKDEV(major, unit), NULL,
- "pg%u", unit);
+ device_create(pg_class, NULL, MKDEV(major, unit), NULL,
+ "pg%u", unit);
}
err = 0;
goto out;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 673b8b2fd33..5ae229656ea 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -979,12 +979,10 @@ static int __init pt_init(void)
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- device_create_drvdata(pt_class, NULL,
- MKDEV(major, unit), NULL,
- "pt%d", unit);
- device_create_drvdata(pt_class, NULL,
- MKDEV(major, unit + 128), NULL,
- "pt%dn", unit);
+ device_create(pt_class, NULL, MKDEV(major, unit), NULL,
+ "pt%d", unit);
+ device_create(pt_class, NULL, MKDEV(major, unit + 128),
+ NULL, "pt%dn", unit);
}
goto out;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 29b7a648cc6..195ca7c720f 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -302,9 +302,8 @@ static struct kobj_type kobj_pkt_type_wqueue = {
static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
{
if (class_pktcdvd) {
- pd->dev = device_create_drvdata(class_pktcdvd, NULL,
- pd->pkt_dev, NULL,
- "%s", pd->name);
+ pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL,
+ "%s", pd->name);
if (IS_ERR(pd->dev))
pd->dev = NULL;
}
@@ -2544,7 +2543,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
if (last_zone != zone) {
BUG_ON(last_zone != zone + pd->settings.size);
first_sectors = last_zone - bio->bi_sector;
- bp = bio_split(bio, bio_split_pool, first_sectors);
+ bp = bio_split(bio, first_sectors);
BUG_ON(!bp);
pkt_make_request(q, &bp->bio1);
pkt_make_request(q, &bp->bio2);
@@ -2911,7 +2910,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
if (!disk->queue)
goto out_mem2;
- pd->pkt_dev = MKDEV(disk->major, disk->first_minor);
+ pd->pkt_dev = MKDEV(pktdev_major, idx);
ret = pkt_new_dev(pd, dev);
if (ret)
goto out_new_dev;
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index d797e209951..936466f62af 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -199,7 +199,8 @@ static void ps3disk_do_request(struct ps3_storage_device *dev,
if (blk_fs_request(req)) {
if (ps3disk_submit_request_sg(dev, req))
break;
- } else if (req->cmd_type == REQ_TYPE_FLUSH) {
+ } else if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
+ req->cmd[0] == REQ_LB_OP_FLUSH) {
if (ps3disk_submit_flush_request(dev, req))
break;
} else {
@@ -257,7 +258,8 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
- if (req->cmd_type == REQ_TYPE_FLUSH) {
+ if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
+ req->cmd[0] == REQ_LB_OP_FLUSH) {
read = 0;
num_sectors = req->hard_cur_sectors;
op = "flush";
@@ -405,7 +407,8 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
- req->cmd_type = REQ_TYPE_FLUSH;
+ req->cmd_type = REQ_TYPE_LINUX_BLOCK;
+ req->cmd[0] = REQ_LB_OP_FLUSH;
}
static unsigned long ps3disk_mask;
@@ -538,7 +541,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev)
struct ps3disk_private *priv = dev->sbd.core.driver_data;
mutex_lock(&ps3disk_mask_mutex);
- __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS,
+ __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
&ps3disk_mask);
mutex_unlock(&ps3disk_mask_mutex);
del_gendisk(priv->gendisk);
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index a8de037ecd4..953c0b83d75 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -1,6 +1,6 @@
/* sunvdc.c: Sun LDOM Virtual Disk Client.
*
- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
*/
#include <linux/module.h>
@@ -834,7 +834,7 @@ static int vdc_port_remove(struct vio_dev *vdev)
return 0;
}
-static struct vio_device_id vdc_port_match[] = {
+static const struct vio_device_id vdc_port_match[] = {
{
.type = "vdc-port",
},
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 3a281ef11ff..f60e41833f6 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -349,8 +349,6 @@ struct ub_dev {
struct work_struct reset_work;
wait_queue_head_t reset_wait;
-
- int sg_stat[6];
};
/*
@@ -685,7 +683,6 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
goto drop;
}
urq->nsg = n_elem;
- sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
if (blk_pc_request(rq)) {
ub_cmd_build_packet(sc, lun, cmd, urq);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f1c8feb5510..1730d29e604 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -249,7 +249,6 @@ static int send_request(struct request *req)
struct HvLpEvent *hev;
struct scatterlist sg[VIOMAXBLOCKDMA];
int sgindex;
- int statindex;
struct viodasd_device *d;
unsigned long flags;
@@ -258,11 +257,9 @@ static int send_request(struct request *req)
if (rq_data_dir(req) == READ) {
direction = DMA_FROM_DEVICE;
viocmd = viomajorsubtype_blockio | vioblockread;
- statindex = 0;
} else {
direction = DMA_TO_DEVICE;
viocmd = viomajorsubtype_blockio | vioblockwrite;
- statindex = 1;
}
d = req->rq_disk->private_data;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 42251095134..6ec5fc05278 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -47,20 +47,20 @@ static void blk_done(struct virtqueue *vq)
spin_lock_irqsave(&vblk->lock, flags);
while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
- int uptodate;
+ int error;
switch (vbr->status) {
case VIRTIO_BLK_S_OK:
- uptodate = 1;
+ error = 0;
break;
case VIRTIO_BLK_S_UNSUPP:
- uptodate = -ENOTTY;
+ error = -ENOTTY;
break;
default:
- uptodate = 0;
+ error = -EIO;
break;
}
- end_dequeued_request(vbr->req, uptodate);
+ __blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req));
list_del(&vbr->list);
mempool_free(vbr, vblk->pool);
}
@@ -84,11 +84,11 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
if (blk_fs_request(vbr->req)) {
vbr->out_hdr.type = 0;
vbr->out_hdr.sector = vbr->req->sector;
- vbr->out_hdr.ioprio = vbr->req->ioprio;
+ vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
} else if (blk_pc_request(vbr->req)) {
vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
vbr->out_hdr.sector = 0;
- vbr->out_hdr.ioprio = vbr->req->ioprio;
+ vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
} else {
/* We don't put anything else in the queue. */
BUG();
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 3ca643cafcc..1a50ae70f71 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -105,15 +105,17 @@ static DEFINE_SPINLOCK(blkif_io_lock);
#define GRANT_INVALID_REF 0
#define PARTS_PER_DISK 16
+#define PARTS_PER_EXT_DISK 256
#define BLKIF_MAJOR(dev) ((dev)>>8)
#define BLKIF_MINOR(dev) ((dev) & 0xff)
-#define DEV_NAME "xvd" /* name in /dev */
+#define EXT_SHIFT 28
+#define EXTENDED (1<<EXT_SHIFT)
+#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
+#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
-/* Information about our VBDs. */
-#define MAX_VBDS 64
-static LIST_HEAD(vbds_list);
+#define DEV_NAME "xvd" /* name in /dev */
static int get_id_from_freelist(struct blkfront_info *info)
{
@@ -386,31 +388,60 @@ static int xlvbd_barrier(struct blkfront_info *info)
}
-static int xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity,
- int vdevice, u16 vdisk_info, u16 sector_size,
- struct blkfront_info *info)
+static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
+ struct blkfront_info *info,
+ u16 vdisk_info, u16 sector_size)
{
struct gendisk *gd;
int nr_minors = 1;
int err = -ENODEV;
+ unsigned int offset;
+ int minor;
+ int nr_parts;
BUG_ON(info->gd != NULL);
BUG_ON(info->rq != NULL);
- if ((minor % PARTS_PER_DISK) == 0)
- nr_minors = PARTS_PER_DISK;
+ if ((info->vdevice>>EXT_SHIFT) > 1) {
+ /* this is above the extended range; something is wrong */
+ printk(KERN_WARNING "blkfront: vdevice 0x%x is above the extended range; ignoring\n", info->vdevice);
+ return -ENODEV;
+ }
+
+ if (!VDEV_IS_EXTENDED(info->vdevice)) {
+ minor = BLKIF_MINOR(info->vdevice);
+ nr_parts = PARTS_PER_DISK;
+ } else {
+ minor = BLKIF_MINOR_EXT(info->vdevice);
+ nr_parts = PARTS_PER_EXT_DISK;
+ }
+
+ if ((minor % nr_parts) == 0)
+ nr_minors = nr_parts;
gd = alloc_disk(nr_minors);
if (gd == NULL)
goto out;
- if (nr_minors > 1)
- sprintf(gd->disk_name, "%s%c", DEV_NAME,
- 'a' + minor / PARTS_PER_DISK);
- else
- sprintf(gd->disk_name, "%s%c%d", DEV_NAME,
- 'a' + minor / PARTS_PER_DISK,
- minor % PARTS_PER_DISK);
+ offset = minor / nr_parts;
+
+ if (nr_minors > 1) {
+ if (offset < 26)
+ sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset);
+ else
+ sprintf(gd->disk_name, "%s%c%c", DEV_NAME,
+ 'a' + ((offset / 26)-1), 'a' + (offset % 26));
+ } else {
+ if (offset < 26)
+ sprintf(gd->disk_name, "%s%c%d", DEV_NAME,
+ 'a' + offset,
+ minor & (nr_parts - 1));
+ else
+ sprintf(gd->disk_name, "%s%c%c%d", DEV_NAME,
+ 'a' + ((offset / 26) - 1),
+ 'a' + (offset % 26),
+ minor & (nr_parts - 1));
+ }
gd->major = XENVBD_MAJOR;
gd->first_minor = minor;
@@ -699,8 +730,13 @@ static int blkfront_probe(struct xenbus_device *dev,
err = xenbus_scanf(XBT_NIL, dev->nodename,
"virtual-device", "%i", &vdevice);
if (err != 1) {
- xenbus_dev_fatal(dev, err, "reading virtual-device");
- return err;
+ /* go looking in the extended area instead */
+ err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext",
+ "%i", &vdevice);
+ if (err != 1) {
+ xenbus_dev_fatal(dev, err, "reading virtual-device");
+ return err;
+ }
}
info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -861,9 +897,7 @@ static void blkfront_connect(struct blkfront_info *info)
if (err)
info->feature_barrier = 0;
- err = xlvbd_alloc_gendisk(BLKIF_MINOR(info->vdevice),
- sectors, info->vdevice,
- binfo, sector_size, info);
+ err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
if (err) {
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
info->xbdev->otherend);
@@ -1032,7 +1066,7 @@ static struct xenbus_driver blkfront = {
static int __init xlblk_init(void)
{
- if (!is_running_on_xen())
+ if (!xen_domain())
return -ENODEV;
if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index bcf57927b7a..e6ee21d99d9 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -901,23 +901,23 @@ static int bluecard_config(struct pcmcia_device *link)
for (n = 0; n < 0x400; n += 0x40) {
link->io.BasePort1 = n ^ 0x300;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
+ if (i == 0)
break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
goto failed;
}
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 1e55a658e6c..32f3a8ed8d3 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -256,7 +256,6 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -298,7 +297,6 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 27058477cc8..2cbe70b6647 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -678,101 +678,78 @@ static void bt3c_detach(struct pcmcia_device *link)
kfree(info);
}
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int bt3c_check_config(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i;
-
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
- return i;
-
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ unsigned long try = (unsigned long) priv_data;
+
+ if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+ (cf->io.win[0].base != 0)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = (try == 0) ? 16 :
+ cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
}
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+ for (j = 0; j < 5; j++) {
+ p_dev->io.BasePort1 = base[j];
+ p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
}
static int bt3c_config(struct pcmcia_device *link)
{
- static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
bt3c_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- int i, j, try;
-
- /* First pass: look for a config entry that looks normal. */
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- /* Two tries: without IO aliases, then with aliases */
- for (try = 0; try < 2; try++) {
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i != CS_SUCCESS)
- goto next_entry;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
-next_entry:
- i = next_tuple(link, &tuple, &parse);
- }
- }
+ int i;
+ unsigned long try;
+
+ /* First pass: look for a config entry that looks normal.
+ Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++)
+ if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try))
+ goto found_port;
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- link->conf.ConfigIndex = cf->index;
- for (j = 0; j < 5; j++) {
- link->io.BasePort1 = base[j];
- link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- }
- i = next_tuple(link, &tuple, &parse);
- }
+ if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
+ goto found_port;
-found_port:
- if (i != CS_SUCCESS) {
- BT_ERR("No usable port range found");
- cs_error(link, RequestIO, i);
- goto failed;
- }
+ BT_ERR("No usable port range found");
+ cs_error(link, RequestIO, -ENODEV);
+ goto failed;
+found_port:
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
goto failed;
}
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 68d1d258e6a..8e556b7ff9f 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -607,102 +607,78 @@ static void btuart_detach(struct pcmcia_device *link)
kfree(info);
}
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i;
-
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
- return i;
-
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ int *try = priv_data;
+
+ if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+ (cf->io.win[0].base != 0)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = (*try == 0) ? 16 :
+ cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
}
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+ for (j = 0; j < 5; j++) {
+ p_dev->io.BasePort1 = base[j];
+ p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
}
static int btuart_config(struct pcmcia_device *link)
{
- static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
btuart_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- int i, j, try;
-
- /* First pass: look for a config entry that looks normal. */
- tuple.TupleData = (cisdata_t *) buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- /* Two tries: without IO aliases, then with aliases */
- for (try = 0; try < 2; try++) {
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i != CS_SUCCESS)
- goto next_entry;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
-next_entry:
- i = next_tuple(link, &tuple, &parse);
- }
- }
+ int i;
+ int try;
+
+ /* First pass: look for a config entry that looks normal.
+ Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++)
+ if (!pcmcia_loop_config(link, btuart_check_config, &try))
+ goto found_port;
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
- && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- link->conf.ConfigIndex = cf->index;
- for (j = 0; j < 5; j++) {
- link->io.BasePort1 = base[j];
- link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- }
- i = next_tuple(link, &tuple, &parse);
- }
+ if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
+ goto found_port;
-found_port:
- if (i != CS_SUCCESS) {
- BT_ERR("No usable port range found");
- cs_error(link, RequestIO, i);
- goto failed;
- }
+ BT_ERR("No usable port range found");
+ cs_error(link, RequestIO, -ENODEV);
+ goto failed;
+found_port:
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
goto failed;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 6a010681ecf..af472e05273 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -102,14 +102,19 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
/* Broadcom BCM2046 */
+ { USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },
{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
+ /* Apple MacBook Pro with Broadcom chip */
+ { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET },
+
/* IBM/Lenovo ThinkPad with Broadcom chip */
{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
/* Targus ACB10US */
{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },
/* ANYCOM Bluetooth USB-200 and USB-250 */
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET },
@@ -147,6 +152,9 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ /* Belkin F8T016 device */
+ { USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET },
+
/* Digianswer devices */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
@@ -169,6 +177,7 @@ static struct usb_device_id blacklist_table[] = {
struct btusb_data {
struct hci_dev *hdev;
struct usb_device *udev;
+ struct usb_interface *intf;
struct usb_interface *isoc;
spinlock_t lock;
@@ -267,7 +276,6 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -350,7 +358,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -471,7 +478,6 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -516,7 +522,7 @@ static int btusb_open(struct hci_dev *hdev)
err = btusb_submit_intr_urb(hdev);
if (err < 0) {
- clear_bit(BTUSB_INTR_RUNNING, &hdev->flags);
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
}
@@ -532,8 +538,10 @@ static int btusb_close(struct hci_dev *hdev)
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
+ cancel_work_sync(&data->work);
+
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
- usb_kill_anchored_urbs(&data->intr_anchor);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->bulk_anchor);
@@ -821,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf,
}
data->udev = interface_to_usbdev(intf);
+ data->intf = intf;
spin_lock_init(&data->lock);
@@ -889,7 +898,7 @@ static int btusb_probe(struct usb_interface *intf,
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
- data->isoc, NULL);
+ data->isoc, data);
if (err < 0) {
hci_free_dev(hdev);
kfree(data);
@@ -921,13 +930,22 @@ static void btusb_disconnect(struct usb_interface *intf)
hdev = data->hdev;
- if (data->isoc)
- usb_driver_release_interface(&btusb_driver, data->isoc);
+ __hci_dev_hold(hdev);
- usb_set_intfdata(intf, NULL);
+ usb_set_intfdata(data->intf, NULL);
+
+ if (data->isoc)
+ usb_set_intfdata(data->isoc, NULL);
hci_unregister_dev(hdev);
+ if (intf == data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->intf);
+ else if (data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->isoc);
+
+ __hci_dev_put(hdev);
+
hci_free_dev(hdev);
}
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index dae45cdf02b..e6e6b037695 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -590,75 +590,40 @@ static void dtl1_detach(struct pcmcia_device *link)
kfree(info);
}
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int dtl1_confcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i;
-
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
- return i;
-
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
- if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.NumPorts1 = cf->io.win[0].len; /*yo */
+ p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
}
static int dtl1_config(struct pcmcia_device *link)
{
dtl1_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
int i;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
/* Look for a generic full-sized window */
link->io.NumPorts1 = 8;
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.NumPorts1 = cf->io.win[0].len; /*yo */
- link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- break;
- }
- i = next_tuple(link, &tuple, &parse);
- }
-
- if (i != CS_SUCCESS) {
- cs_error(link, RequestIO, i);
+ if (!pcmcia_loop_config(link, dtl1_confcheck, NULL))
goto failed;
- }
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
goto failed;
}
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 4d37bb312ee..7938062c1cc 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -352,14 +352,14 @@ static int bcsp_flush(struct hci_uart *hu)
/* Remove ack'ed packets */
static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
{
+ struct sk_buff *skb, *tmp;
unsigned long flags;
- struct sk_buff *skb;
int i, pkts_to_be_removed;
u8 seqno;
spin_lock_irqsave(&bcsp->unack.lock, flags);
- pkts_to_be_removed = bcsp->unack.qlen;
+ pkts_to_be_removed = skb_queue_len(&bcsp->unack);
seqno = bcsp->msgq_txseq;
while (pkts_to_be_removed) {
@@ -373,19 +373,19 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
BT_ERR("Peer acked invalid packet");
BT_DBG("Removing %u pkts out of %u, up to seqno %u",
- pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
+ pkts_to_be_removed, skb_queue_len(&bcsp->unack),
+ (seqno - 1) & 0x07);
- for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
- && skb != (struct sk_buff *) &bcsp->unack; i++) {
- struct sk_buff *nskb;
+ i = 0;
+ skb_queue_walk_safe(&bcsp->unack, skb, tmp) {
+ if (i++ >= pkts_to_be_removed)
+ break;
- nskb = skb->next;
__skb_unlink(skb, &bcsp->unack);
kfree_skb(skb);
- skb = nskb;
}
- if (bcsp->unack.qlen == 0)
+ if (skb_queue_empty(&bcsp->unack))
del_timer(&bcsp->tbcsp);
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 8dfcf77cb71..4426bb552bd 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -484,7 +484,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return -EUNATCH;
default:
- err = n_tty_ioctl(tty, file, cmd, arg);
+ err = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
};
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 1790cc8e431..8e659914523 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -70,8 +70,8 @@ static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
- /* _urb_unlink needs to know which spinlock to use, thus mb(). */
- _urb->queue = q; mb(); list_add(&_urb->list, &q->head);
+ /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */
+ _urb->queue = q; smp_mb(); list_add(&_urb->list, &q->head);
spin_unlock_irqrestore(&q->lock, flags);
}
@@ -79,8 +79,8 @@ static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
- /* _urb_unlink needs to know which spinlock to use, thus mb(). */
- _urb->queue = q; mb(); list_add_tail(&_urb->list, &q->head);
+ /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */
+ _urb->queue = q; smp_mb(); list_add_tail(&_urb->list, &q->head);
spin_unlock_irqrestore(&q->lock, flags);
}
@@ -89,7 +89,7 @@ static inline void _urb_unlink(struct _urb *_urb)
struct _urb_queue *q;
unsigned long flags;
- mb();
+ smp_mb();
q = _urb->queue;
/* If q is NULL, it will die at easy-to-debug NULL pointer dereference.
No need to BUG(). */
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 74031de517e..d47f2f80acc 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2097,7 +2097,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
len = nr * CD_FRAMESIZE_RAW;
- ret = blk_rq_map_user(q, rq, ubuf, len);
+ ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
if (ret)
break;
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 1231d95aa69..d6ba77a2dd7 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -624,14 +624,14 @@ static void gdrom_readdisk_dma(struct work_struct *work)
ctrl_outb(1, GDROM_DMA_STATUS_REG);
wait_event_interruptible_timeout(request_queue,
gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
- err = gd.transfer;
+ err = gd.transfer ? -EIO : 0;
gd.transfer = 0;
gd.pending = 0;
/* now seek to take the request spinlock
* before handling ending the request */
spin_lock(&gdrom_lock);
list_del_init(&req->queuelist);
- end_dequeued_request(req, 1 - err);
+ __blk_end_request(req, err, blk_rq_bytes(req));
}
spin_unlock(&gdrom_lock);
kfree(read_command);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index caff85149b9..122254155ae 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -350,7 +350,7 @@ config STALDRV
config STALLION
tristate "Stallion EasyIO or EC8/32 support"
- depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
+ depends on STALDRV && (ISA || EISA || PCI)
help
If you have an EasyIO or EasyConnection 8/32 multiport Stallion
card, then this is for you; say Y. Make sure to read
@@ -361,7 +361,7 @@ config STALLION
config ISTALLION
tristate "Stallion EC8/64, ONboard, Brumby support"
- depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
+ depends on STALDRV && (ISA || EISA || PCI)
help
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
serial multiport card, say Y here. Make sure to read
@@ -1043,15 +1043,6 @@ config HPET
open selects one of the timers supported by the HPET. The timers are
non-periodic and/or periodic.
-config HPET_RTC_IRQ
- bool
- default HPET_EMULATE_RTC
- depends on RTC && HPET
- help
- If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It
- is assumed the platform called hpet_alloc with the RTC IRQ values for
- the HPET timers.
-
config HPET_MMAP
bool "Allow mmap of HPET"
default y
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6850f6da757..1a4247dccac 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -7,7 +7,7 @@
#
FONTMAPFILE = cp437.uni
-obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o
+obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 4bada0e8b81..46f50753117 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -116,7 +116,9 @@ struct agp_bridge_driver {
struct agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type)(struct agp_memory *);
void *(*agp_alloc_page)(struct agp_bridge_data *);
+ int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
void (*agp_destroy_page)(void *, int flags);
+ void (*agp_destroy_pages)(struct agp_memory *);
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
void (*chipset_flush)(struct agp_bridge_data *);
};
@@ -277,7 +279,10 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
void agp_generic_free_by_type(struct agp_memory *curr);
void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
+int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
+ struct agp_memory *memory, size_t page_count);
void agp_generic_destroy_page(void *addr, int flags);
+void agp_generic_destroy_pages(struct agp_memory *memory);
void agp_free_key(int key);
int agp_num_entries(void);
u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index 5da89f6c6c2..5ea4da8e995 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -143,7 +143,9 @@ struct agp_bridge_driver alpha_core_agp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e280531843b..3f98254b911 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -223,12 +223,14 @@ static int amd_irongate_configure(void)
current_size = A_SIZE_LVL2(agp_bridge->current_size);
- /* Get the memory mapped registers */
- pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
- temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
- if (!amd_irongate_private.registers)
- return -ENOMEM;
+ if (!amd_irongate_private.registers) {
+ /* Get the memory mapped registers */
+ pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
+ temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ if (!amd_irongate_private.registers)
+ return -ENOMEM;
+ }
/* Write out the address of the gatt table */
writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE);
@@ -386,7 +388,9 @@ static const struct agp_bridge_driver amd_irongate_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -490,6 +494,26 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
+
+static int agp_amdk7_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int agp_amdk7_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ return amd_irongate_driver.configure();
+}
+
+#endif /* CONFIG_PM */
+
/* must be the same order as name table above */
static struct pci_device_id agp_amdk7_pci_table[] = {
{
@@ -526,6 +550,10 @@ static struct pci_driver agp_amdk7_pci_driver = {
.id_table = agp_amdk7_pci_table,
.probe = agp_amdk7_probe,
.remove = agp_amdk7_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_amdk7_suspend,
+ .resume = agp_amdk7_resume,
+#endif
};
static int __init agp_amdk7_init(void)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 7495c522d8e..2812ee2b165 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -224,7 +224,9 @@ static const struct agp_bridge_driver amd_8151_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 6ecbcafb34b..ae2791b926b 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -418,7 +418,9 @@ static const struct agp_bridge_driver ati_generic_bridge = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 8ca6f262ef8..453543a1f29 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -335,7 +335,9 @@ static const struct agp_bridge_driver efficeon_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 118dbde25dc..10d6cbd7c05 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -201,14 +201,22 @@ void agp_free_memory(struct agp_memory *curr)
return;
}
if (curr->page_count != 0) {
- for (i = 0; i < curr->page_count; i++) {
- curr->memory[i] = (unsigned long)gart_to_virt(curr->memory[i]);
- curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
- AGP_PAGE_DESTROY_UNMAP);
- }
- for (i = 0; i < curr->page_count; i++) {
- curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
- AGP_PAGE_DESTROY_FREE);
+ if (curr->bridge->driver->agp_destroy_pages) {
+ curr->bridge->driver->agp_destroy_pages(curr);
+ } else {
+
+ for (i = 0; i < curr->page_count; i++) {
+ curr->memory[i] = (unsigned long)gart_to_virt(
+ curr->memory[i]);
+ curr->bridge->driver->agp_destroy_page(
+ (void *)curr->memory[i],
+ AGP_PAGE_DESTROY_UNMAP);
+ }
+ for (i = 0; i < curr->page_count; i++) {
+ curr->bridge->driver->agp_destroy_page(
+ (void *)curr->memory[i],
+ AGP_PAGE_DESTROY_FREE);
+ }
}
}
agp_free_key(curr->key);
@@ -264,6 +272,15 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
if (new == NULL)
return NULL;
+ if (bridge->driver->agp_alloc_pages) {
+ if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) {
+ agp_free_memory(new);
+ return NULL;
+ }
+ new->bridge = bridge;
+ return new;
+ }
+
for (i = 0; i < page_count; i++) {
void *addr = bridge->driver->agp_alloc_page(bridge);
@@ -1203,6 +1220,39 @@ EXPORT_SYMBOL(agp_generic_alloc_user);
* against a maximum value.
*/
+int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
+{
+ struct page * page;
+ int i, ret = -ENOMEM;
+
+ for (i = 0; i < num_pages; i++) {
+ page = alloc_page(GFP_KERNEL | GFP_DMA32);
+ /* agp_free_memory() needs gart address */
+ if (page == NULL)
+ goto out;
+
+#ifndef CONFIG_X86
+ map_page_into_agp(page);
+#endif
+ get_page(page);
+ atomic_inc(&agp_bridge->current_memory_agp);
+
+ /* set_memory_array_uc() needs virtual address */
+ mem->memory[i] = (unsigned long)page_address(page);
+ mem->page_count++;
+ }
+
+#ifdef CONFIG_X86
+ set_memory_array_uc(mem->memory, num_pages);
+#endif
+ ret = 0;
+out:
+ for (i = 0; i < mem->page_count; i++)
+ mem->memory[i] = virt_to_gart((void *)mem->memory[i]);
+ return ret;
+}
+EXPORT_SYMBOL(agp_generic_alloc_pages);
+
void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
@@ -1219,6 +1269,37 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
}
EXPORT_SYMBOL(agp_generic_alloc_page);
+void agp_generic_destroy_pages(struct agp_memory *mem)
+{
+ int i;
+ void *addr;
+ struct page *page;
+
+ if (!mem)
+ return;
+
+ for (i = 0; i < mem->page_count; i++)
+ mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]);
+
+#ifdef CONFIG_X86
+ set_memory_array_wb(mem->memory, mem->page_count);
+#endif
+
+ for (i = 0; i < mem->page_count; i++) {
+ addr = (void *)mem->memory[i];
+ page = virt_to_page(addr);
+
+#ifndef CONFIG_X86
+ unmap_page_from_agp(page);
+#endif
+
+ put_page(page);
+ free_page((unsigned long)addr);
+ atomic_dec(&agp_bridge->current_memory_agp);
+ mem->memory[i] = 0;
+ }
+}
+EXPORT_SYMBOL(agp_generic_destroy_pages);
void agp_generic_destroy_page(void *addr, int flags)
{
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 80d7317f85c..183ac3fe44f 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -435,7 +435,9 @@ const struct agp_bridge_driver hp_zx1_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
.cant_use_aperture = true,
};
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index e587eebebc6..10da687d131 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -575,7 +575,9 @@ const struct agp_bridge_driver intel_i460_driver = {
.insert_memory = i460_insert_memory_small_io_page,
.remove_memory = i460_remove_memory_small_io_page,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
#endif
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 016fdf0623a..1108665913e 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -54,8 +54,7 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
@@ -63,7 +62,8 @@
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB)
extern int agp_memory_reserved;
@@ -214,8 +214,8 @@ static int intel_i810_configure(void)
if (agp_bridge->driver->needs_scratch_page) {
for (i = 0; i < current_size->num_entries; i++) {
writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
}
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */
}
global_cache_flush();
return 0;
@@ -525,8 +525,10 @@ static void intel_i830_init_gtt_entries(void)
size += 4;
} else if (IS_G4X) {
/* On 4 series hardware, GTT stolen is separate from graphics
- * stolen, ignore it in stolen gtt entries counting */
- size = 0;
+ * stolen, ignore it in stolen gtt entries counting. However,
+ * 4KB of the stolen memory doesn't get mapped to the GTT.
+ */
+ size = 4;
} else {
/* On previous hardware, the GTT size was just what was
* required to map the aperture.
@@ -773,8 +775,8 @@ static int intel_i830_configure(void)
if (agp_bridge->driver->needs_scratch_page) {
for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
}
global_cache_flush();
@@ -989,8 +991,8 @@ static int intel_i915_configure(void)
if (agp_bridge->driver->needs_scratch_page) {
for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
writel(agp_bridge->scratch_page, intel_private.gtt+i);
- readl(intel_private.gtt+i); /* PCI Posting. */
}
+ readl(intel_private.gtt+i-1); /* PCI Posting. */
}
global_cache_flush();
@@ -1711,7 +1713,9 @@ static const struct agp_bridge_driver intel_generic_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1736,7 +1740,9 @@ static const struct agp_bridge_driver intel_810_driver = {
.alloc_by_type = intel_i810_alloc_by_type,
.free_by_type = intel_i810_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1760,7 +1766,9 @@ static const struct agp_bridge_driver intel_815_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1785,7 +1793,9 @@ static const struct agp_bridge_driver intel_830_driver = {
.alloc_by_type = intel_i830_alloc_by_type,
.free_by_type = intel_i810_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
.chipset_flush = intel_i830_chipset_flush,
};
@@ -1810,7 +1820,9 @@ static const struct agp_bridge_driver intel_820_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1834,7 +1846,9 @@ static const struct agp_bridge_driver intel_830mp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1858,7 +1872,9 @@ static const struct agp_bridge_driver intel_840_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1882,7 +1898,9 @@ static const struct agp_bridge_driver intel_845_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
.chipset_flush = intel_i830_chipset_flush,
};
@@ -1907,7 +1925,9 @@ static const struct agp_bridge_driver intel_850_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1931,7 +1951,9 @@ static const struct agp_bridge_driver intel_860_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -1956,7 +1978,9 @@ static const struct agp_bridge_driver intel_915_driver = {
.alloc_by_type = intel_i830_alloc_by_type,
.free_by_type = intel_i810_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
.chipset_flush = intel_i915_chipset_flush,
};
@@ -1982,7 +2006,9 @@ static const struct agp_bridge_driver intel_i965_driver = {
.alloc_by_type = intel_i830_alloc_by_type,
.free_by_type = intel_i810_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
.chipset_flush = intel_i915_chipset_flush,
};
@@ -2007,7 +2033,9 @@ static const struct agp_bridge_driver intel_7505_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -2032,7 +2060,9 @@ static const struct agp_bridge_driver intel_g33_driver = {
.alloc_by_type = intel_i830_alloc_by_type,
.free_by_type = intel_i810_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
.chipset_flush = intel_i915_chipset_flush,
};
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index eaceb61ba2d..5bbed3d79db 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -201,10 +201,15 @@ extern int agp_memory_reserved;
static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
int i, j;
+ int mask_type;
- if ((type != 0) || (mem->type != 0))
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
if ((pg_start + mem->page_count) >
(nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE))
return -EINVAL;
@@ -220,10 +225,13 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type),
+ mem->memory[i], mask_type),
agp_bridge->gatt_table+nvidia_private.pg_offset+j);
- readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j); /* PCI Posting. */
}
+
+ /* PCI Posting. */
+ readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j - 1);
+
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -233,9 +241,15 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type
{
int i;
- if ((type != 0) || (mem->type != 0))
+ int mask_type;
+
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++)
writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i);
@@ -312,7 +326,9 @@ static const struct agp_bridge_driver nvidia_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index 8c42dcc5958..f2492ecf082 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -224,7 +224,9 @@ static const struct agp_bridge_driver parisc_agp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
.cant_use_aperture = true,
};
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 2587ef96a96..6c3837a0184 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -140,7 +140,9 @@ static struct agp_bridge_driver sis_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 2fb27fe4c10..6224df8b7f0 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -437,7 +437,9 @@ static const struct agp_bridge_driver sworks_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index eef72709ec5..0f004b65ec0 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -509,7 +509,9 @@ const struct agp_bridge_driver uninorth_agp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
.cant_use_aperture = true,
};
@@ -534,7 +536,9 @@ const struct agp_bridge_driver u3_agp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
.cant_use_aperture = true,
.needs_scratch_page = true,
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 7b36476dff4..9f4d49e1b59 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -190,7 +190,9 @@ static const struct agp_bridge_driver via_agp3_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
@@ -214,7 +216,9 @@ static const struct agp_bridge_driver via_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 6e763e3f5a8..98821f97583 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -837,9 +837,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
struct async_struct *info;
unsigned long flags;
- if (!tty)
- return 0;
-
info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
@@ -892,9 +889,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
struct async_struct *info;
unsigned long flags;
- if (!tty)
- return 0;
-
info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_write"))
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 31d08b641f5..05674febb0c 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -478,7 +478,7 @@ static int do_ac_read(int IndexCard, char __user *buf,
struct st_ram_io *st_loc, struct mailbox *mailbox)
{
void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
- unsigned char *to = (unsigned char *)&mailbox;
+ unsigned char *to = (unsigned char *)mailbox;
#ifdef DEBUG
int c;
#endif
@@ -712,8 +712,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
IndexCard = adgl->num_card-1;
- if(cmd != 0 && cmd != 6 &&
- ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
+ if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
static int warncount = 10;
if (warncount) {
printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
@@ -832,8 +831,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
}
break;
default:
- printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ;
- ret = -EINVAL;
+ ret = -ENOTTY;
break;
}
Dummy = readb(apbs[IndexCard].RamIO + VERS);
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index b650b4e48e5..456f54db73e 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -229,9 +229,8 @@ static int bsr_create_devs(struct device_node *bn)
if (result)
goto out_err;
- cur->bsr_device = device_create_drvdata(bsr_class, NULL,
- cur->bsr_dev,
- cur, cur->bsr_name);
+ cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
+ cur, cur->bsr_name);
if (!cur->bsr_device) {
printk(KERN_ERR "device_create failed for %s\n",
cur->bsr_name);
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index fe6d774fe2e..5e5b1dc1a0a 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -4993,12 +4993,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
card_name = "Cyclom-Y";
- addr0 = pci_iomap(pdev, 0, CyPCI_Yctl);
+ addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+ CyPCI_Yctl);
if (addr0 == NULL) {
dev_err(&pdev->dev, "can't remap ctl region\n");
goto err_reg;
}
- addr2 = pci_iomap(pdev, 2, CyPCI_Ywin);
+ addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+ CyPCI_Ywin);
if (addr2 == NULL) {
dev_err(&pdev->dev, "can't remap base region\n");
goto err_unmap;
@@ -5013,7 +5015,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
struct RUNTIME_9060 __iomem *ctl_addr;
- ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl);
+ ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+ CyPCI_Zctl);
if (addr0 == NULL) {
dev_err(&pdev->dev, "can't remap ctl region\n");
goto err_reg;
@@ -5026,8 +5029,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
mailbox = (u32)readl(&ctl_addr->mail_box_0);
- addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ?
- CyPCI_Ze_win : CyPCI_Zwin);
+ addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+ mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
if (addr2 == NULL) {
dev_err(&pdev->dev, "can't remap base region\n");
goto err_unmap;
@@ -5159,9 +5162,9 @@ err_null:
cy_card[card_no].base_addr = NULL;
free_irq(irq, &cy_card[card_no]);
err_unmap:
- pci_iounmap(pdev, addr0);
+ iounmap(addr0);
if (addr2)
- pci_iounmap(pdev, addr2);
+ iounmap(addr2);
err_reg:
pci_release_regions(pdev);
err_dis:
@@ -5186,9 +5189,9 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
cy_writew(cinfo->ctl_addr + 0x68,
readw(cinfo->ctl_addr + 0x68) & ~0x0900);
- pci_iounmap(pdev, cinfo->base_addr);
+ iounmap(cinfo->base_addr);
if (cinfo->ctl_addr)
- pci_iounmap(pdev, cinfo->ctl_addr);
+ iounmap(cinfo->ctl_addr);
if (cinfo->irq
#ifndef CONFIG_CYZ_INTR
&& !IS_CYC_Z(*cinfo)
diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c
index fb584938c9c..5329d482b58 100644
--- a/drivers/char/ds1286.c
+++ b/drivers/char/ds1286.c
@@ -443,7 +443,6 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
{
unsigned char save_control;
unsigned long flags;
- unsigned long uip_watchdog = jiffies;
/*
* read RTC once any update in progress is done. The update
@@ -456,8 +455,7 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
*/
if (ds1286_is_updating() != 0)
- while (time_before(jiffies, uip_watchdog + 2*HZ/100))
- barrier();
+ msleep(20);
/*
* Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index ca7c72a486b..85832ab924e 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -508,8 +508,8 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
- NULL, "dsp56k");
+ device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
+ "dsp56k");
printk(banner);
goto out;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 456e4ede049..4998b2761e8 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1376,6 +1376,7 @@ static void post_fep_init(unsigned int crd)
unsigned long flags;
u16 tseg, rseg;
+ tty_port_init(&ch->port);
ch->brdchan = bc;
ch->mailbox = gd;
INIT_WORK(&ch->tqueue, do_softint);
@@ -1510,10 +1511,6 @@ static void post_fep_init(unsigned int crd)
ch->fepstopca = 0;
ch->close_delay = 50;
- ch->port.count = 0;
- ch->port.blocked_open = 0;
- init_waitqueue_head(&ch->port.open_wait);
- init_waitqueue_head(&ch->port.close_wait);
spin_unlock_irqrestore(&epca_lock, flags);
}
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 19d3afb0e50..c6090f84a2e 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -54,8 +54,6 @@ int gs_put_char(struct tty_struct * tty, unsigned char ch)
func_enter ();
- if (!tty) return 0;
-
port = tty->driver_data;
if (!port) return 0;
@@ -97,8 +95,6 @@ int gs_write(struct tty_struct * tty,
func_enter ();
- if (!tty) return 0;
-
port = tty->driver_data;
if (!port) return 0;
@@ -185,7 +181,6 @@ static int gs_real_chars_in_buffer(struct tty_struct *tty)
struct gs_port *port;
func_enter ();
- if (!tty) return 0;
port = tty->driver_data;
if (!port->rd) return 0;
@@ -274,8 +269,6 @@ void gs_flush_buffer(struct tty_struct *tty)
func_enter ();
- if (!tty) return;
-
port = tty->driver_data;
if (!port) return;
@@ -296,8 +289,6 @@ void gs_flush_chars(struct tty_struct * tty)
func_enter ();
- if (!tty) return;
-
port = tty->driver_data;
if (!port) return;
@@ -321,8 +312,6 @@ void gs_stop(struct tty_struct * tty)
func_enter ();
- if (!tty) return;
-
port = tty->driver_data;
if (!port) return;
@@ -341,8 +330,6 @@ void gs_start(struct tty_struct * tty)
{
struct gs_port *port;
- if (!tty) return;
-
port = tty->driver_data;
if (!port) return;
@@ -393,8 +380,6 @@ void gs_hangup(struct tty_struct *tty)
func_enter ();
- if (!tty) return;
-
port = tty->driver_data;
tty = port->port.tty;
if (!tty)
@@ -426,8 +411,6 @@ int gs_block_til_ready(void *port_, struct file * filp)
tty = port->port.tty;
- if (!tty) return 0;
-
gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
/*
* If the device is in the middle of being closed, then block
@@ -523,8 +506,6 @@ void gs_close(struct tty_struct * tty, struct file * filp)
func_enter ();
- if (!tty) return;
-
port = (struct gs_port *) tty->driver_data;
if (!port) return;
@@ -621,8 +602,6 @@ void gs_set_termios (struct tty_struct * tty,
func_enter();
- if (!tty) return;
-
port = tty->driver_data;
if (!port) return;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index b3f5dbc6d88..f3cfb4c7612 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -53,6 +53,11 @@
#define HPET_RANGE_SIZE 1024 /* from HPET spec */
+
+/* WARNING -- don't get confused. These macros are never used
+ * to write the (single) counter, and rarely to read it.
+ * They're badly named; to fix, someday.
+ */
#if BITS_PER_LONG == 64
#define write_counter(V, MC) writeq(V, MC)
#define read_counter(MC) readq(MC)
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
.rating = 250,
.read = read_hpet,
.mask = CLOCKSOURCE_MASK(64),
- .mult = 0, /*to be caluclated*/
+ .mult = 0, /* to be calculated */
.shift = 10,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
/* A lock for concurrent access by app and isr hpet activity. */
static DEFINE_SPINLOCK(hpet_lock);
-/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
-static DEFINE_SPINLOCK(hpet_task_lock);
#define HPET_DEV_NAME (7)
@@ -99,7 +102,6 @@ struct hpet_dev {
unsigned long hd_irqdata;
wait_queue_head_t hd_waitqueue;
struct fasync_struct *hd_async_queue;
- struct hpet_task *hd_task;
unsigned int hd_flags;
unsigned int hd_irq;
unsigned int hd_hdwirq;
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
writel(isr, &devp->hd_hpet->hpet_isr);
spin_unlock(&hpet_lock);
- spin_lock(&hpet_task_lock);
- if (devp->hd_task)
- devp->hd_task->ht_func(devp->hd_task->ht_data);
- spin_unlock(&hpet_task_lock);
-
wake_up_interruptible(&devp->hd_waitqueue);
kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
@@ -185,6 +182,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
+static void hpet_timer_set_irq(struct hpet_dev *devp)
+{
+ unsigned long v;
+ int irq, gsi;
+ struct hpet_timer __iomem *timer;
+
+ spin_lock_irq(&hpet_lock);
+ if (devp->hd_hdwirq) {
+ spin_unlock_irq(&hpet_lock);
+ return;
+ }
+
+ timer = devp->hd_timer;
+
+ /* we prefer level triggered mode */
+ v = readl(&timer->hpet_config);
+ if (!(v & Tn_INT_TYPE_CNF_MASK)) {
+ v |= Tn_INT_TYPE_CNF_MASK;
+ writel(v, &timer->hpet_config);
+ }
+ spin_unlock_irq(&hpet_lock);
+
+ v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
+ Tn_INT_ROUTE_CAP_SHIFT;
+
+ /*
+ * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
+ * legacy device. In IO APIC mode, we skip all the legacy IRQS.
+ */
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+ v &= ~0xf3df;
+ else
+ v &= ~0xffff;
+
+ for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
+ irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
+
+ if (irq >= NR_IRQS) {
+ irq = HPET_MAX_IRQ;
+ break;
+ }
+
+ gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
+ ACPI_ACTIVE_LOW);
+ if (gsi > 0)
+ break;
+
+ /* FIXME: Setup interrupt source table */
+ }
+
+ if (irq < HPET_MAX_IRQ) {
+ spin_lock_irq(&hpet_lock);
+ v = readl(&timer->hpet_config);
+ v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
+ writel(v, &timer->hpet_config);
+ devp->hd_hdwirq = gsi;
+ spin_unlock_irq(&hpet_lock);
+ }
+ return;
+}
+
static int hpet_open(struct inode *inode, struct file *file)
{
struct hpet_dev *devp;
@@ -199,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
for (i = 0; i < hpetp->hp_ntimer; i++)
- if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
- || hpetp->hp_dev[i].hd_task)
+ if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
continue;
else {
devp = &hpetp->hp_dev[i];
@@ -219,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file)
spin_unlock_irq(&hpet_lock);
unlock_kernel();
+ hpet_timer_set_irq(devp);
+
return 0;
}
@@ -441,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
devp->hd_irq = irq;
t = devp->hd_ireqfreq;
v = readq(&timer->hpet_config);
- g = v | Tn_INT_ENB_CNF_MASK;
+
+ /* 64-bit comparators are not yet supported through the ioctls,
+ * so force this into 32-bit mode if it supports both modes
+ */
+ g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
if (devp->hd_flags & HPET_PERIODIC) {
write_counter(t, &timer->hpet_compare);
@@ -451,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
v |= Tn_VAL_SET_CNF_MASK;
writeq(v, &timer->hpet_config);
local_irq_save(flags);
+
+ /* NOTE: what we modify here is a hidden accumulator
+ * register supported by periodic-capable comparators.
+ * We never want to modify the (single) counter; that
+ * would affect all the comparators.
+ */
m = read_counter(&hpet->hpet_mc);
write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
} else {
@@ -604,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
return 0;
}
-static inline int hpet_tpcheck(struct hpet_task *tp)
-{
- struct hpet_dev *devp;
- struct hpets *hpetp;
-
- devp = tp->ht_opaque;
-
- if (!devp)
- return -ENXIO;
-
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (devp >= hpetp->hp_dev
- && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
- && devp->hd_hpet == hpetp->hp_hpet)
- return 0;
-
- return -ENXIO;
-}
-
-#if 0
-int hpet_unregister(struct hpet_task *tp)
-{
- struct hpet_dev *devp;
- struct hpet_timer __iomem *timer;
- int err;
-
- if ((err = hpet_tpcheck(tp)))
- return err;
-
- spin_lock_irq(&hpet_task_lock);
- spin_lock(&hpet_lock);
-
- devp = tp->ht_opaque;
- if (devp->hd_task != tp) {
- spin_unlock(&hpet_lock);
- spin_unlock_irq(&hpet_task_lock);
- return -ENXIO;
- }
-
- timer = devp->hd_timer;
- writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
- &timer->hpet_config);
- devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
- devp->hd_task = NULL;
- spin_unlock(&hpet_lock);
- spin_unlock_irq(&hpet_task_lock);
-
- return 0;
-}
-#endif /* 0 */
-
static ctl_table hpet_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
@@ -746,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp)
static struct hpets *last = NULL;
unsigned long period;
unsigned long long temp;
+ u32 remainder;
/*
* hpet_alloc can be called by platform dependent code.
@@ -809,9 +828,13 @@ int hpet_alloc(struct hpet_data *hdp)
printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
printk("\n");
- printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
- hpetp->hp_which, hpetp->hp_ntimer,
- cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
+ temp = hpetp->hp_tick_freq;
+ remainder = do_div(temp, 1000000);
+ printk(KERN_INFO
+ "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
+ hpetp->hp_which, hpetp->hp_ntimer,
+ cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
+ (unsigned) temp, remainder);
mcfg = readq(&hpet->hpet_config);
if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
@@ -874,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
hdp->hd_address = ioremap(addr.minimum, addr.address_length);
if (hpet_is_known(hdp)) {
- printk(KERN_DEBUG "%s: 0x%lx is busy\n",
- __func__, hdp->hd_phys_address);
iounmap(hdp->hd_address);
return AE_ALREADY_EXISTS;
}
@@ -891,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
HPET_RANGE_SIZE);
if (hpet_is_known(hdp)) {
- printk(KERN_DEBUG "%s: 0x%lx is busy\n",
- __func__, hdp->hd_phys_address);
iounmap(hdp->hd_address);
return AE_ALREADY_EXISTS;
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index fd64137b1ab..bf70450a49c 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
spin_lock_irqsave(&hp->lock, flags);
if (--hp->count == 0) {
- if (hp->ops->notifier_del)
- hp->ops->notifier_del(hp, hp->data);
-
/* We are done with the tty pointer now. */
hp->tty = NULL;
spin_unlock_irqrestore(&hp->lock, flags);
+ if (hp->ops->notifier_del)
+ hp->ops->notifier_del(hp, hp->data);
+
/*
* Chain calls chars_in_buffer() and returns immediately if
* there is no buffered data otherwise sleeps on a wait queue
@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct *tty)
hp->n_outbuf = 0;
hp->tty = NULL;
+ spin_unlock_irqrestore(&hp->lock, flags);
+
if (hp->ops->notifier_del)
hp->ops->notifier_del(hp, hp->data);
- spin_unlock_irqrestore(&hp->lock, flags);
-
while(temp_open_count) {
--temp_open_count;
kref_put(&hp->kref, destroy_hvc_struct);
@@ -819,11 +819,11 @@ static int hvc_init(void)
hvc_driver = drv;
return 0;
-put_tty:
- put_tty_driver(hvc_driver);
stop_thread:
kthread_stop(hvc_task);
hvc_task = NULL;
+put_tty:
+ put_tty_driver(drv);
out:
return err;
}
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c
index 6b70aa66a58..538ceea5e7d 100644
--- a/drivers/char/hvc_xen.c
+++ b/drivers/char/hvc_xen.c
@@ -108,8 +108,8 @@ static int __init xen_init(void)
{
struct hvc_struct *hp;
- if (!is_running_on_xen() ||
- is_initial_xendomain() ||
+ if (!xen_pv_domain() ||
+ xen_initial_domain() ||
!xen_start_info->console.domU.evtchn)
return -ENODEV;
@@ -142,7 +142,7 @@ static void __exit xen_fini(void)
static int xen_cons_init(void)
{
- if (!is_running_on_xen())
+ if (!xen_pv_domain())
return 0;
hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 5220f541df2..8859aeac2d2 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -736,7 +736,7 @@ static int __devexit n2rng_remove(struct of_device *op)
return 0;
}
-static struct of_device_id n2rng_match[] = {
+static const struct of_device_id n2rng_match[] = {
{
.name = "random-number-generator",
.compatible = "SUNW,n2-rng",
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 51738bdd834..d4e7dca06e4 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -118,18 +118,21 @@ static int __init omap_rng_probe(struct platform_device *pdev)
mem = request_mem_region(res->start, res->end - res->start + 1,
pdev->name);
- if (mem == NULL)
- return -EBUSY;
+ if (mem == NULL) {
+ ret = -EBUSY;
+ goto err_region;
+ }
dev_set_drvdata(&pdev->dev, mem);
- rng_base = (u32 __force __iomem *)io_p2v(res->start);
+ rng_base = ioremap(res->start, res->end - res->start + 1);
+ if (!rng_base) {
+ ret = -ENOMEM;
+ goto err_ioremap;
+ }
ret = hwrng_register(&omap_rng_ops);
- if (ret) {
- release_resource(mem);
- rng_base = NULL;
- return ret;
- }
+ if (ret)
+ goto err_register;
dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
omap_rng_read_reg(RNG_REV_REG));
@@ -138,6 +141,18 @@ static int __init omap_rng_probe(struct platform_device *pdev)
rng_dev = pdev;
return 0;
+
+err_register:
+ iounmap(rng_base);
+ rng_base = NULL;
+err_ioremap:
+ release_resource(mem);
+err_region:
+ if (cpu_is_omap24xx()) {
+ clk_disable(rng_ick);
+ clk_put(rng_ick);
+ }
+ return ret;
}
static int __exit omap_rng_remove(struct platform_device *pdev)
@@ -148,6 +163,8 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
omap_rng_write_reg(RNG_MASK_REG, 0x0);
+ iounmap(rng_base);
+
if (cpu_is_omap24xx()) {
clk_disable(rng_ick);
clk_put(rng_ick);
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile
index 939618f62fe..bc397d92b49 100644
--- a/drivers/char/ip2/Makefile
+++ b/drivers/char/ip2/Makefile
@@ -4,5 +4,5 @@
obj-$(CONFIG_COMPUTONE) += ip2.o
-ip2-objs := ip2base.o ip2main.o
+ip2-objs := ip2main.o
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index 3601017f58c..29db44de399 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -69,38 +69,6 @@ static DEFINE_RWLOCK(Dl_spinlock);
//=======================================================
//******************************************************************************
-// Function: iiEllisInit()
-// Parameters: None
-//
-// Returns: Nothing
-//
-// Description:
-//
-// This routine performs any required initialization of the iiEllis subsystem.
-//
-//******************************************************************************
-static void
-iiEllisInit(void)
-{
-}
-
-//******************************************************************************
-// Function: iiEllisCleanup()
-// Parameters: None
-//
-// Returns: Nothing
-//
-// Description:
-//
-// This routine performs any required cleanup of the iiEllis subsystem.
-//
-//******************************************************************************
-static void
-iiEllisCleanup(void)
-{
-}
-
-//******************************************************************************
// Function: iiSetAddress(pB, address, delay)
// Parameters: pB - pointer to the board structure
// address - the purported I/O address of the board
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h
index c88a64e527a..fb6df245601 100644
--- a/drivers/char/ip2/i2ellis.h
+++ b/drivers/char/ip2/i2ellis.h
@@ -511,7 +511,6 @@ typedef void (*delayFunc_t)(unsigned int);
//
// Initialization of a board & structure is in four (five!) parts:
//
-// 0) iiEllisInit() - Initialize iiEllis subsystem.
// 1) iiSetAddress() - Define the board address & delay function for a board.
// 2) iiReset() - Reset the board (provided it exists)
// -- Note you may do this to several boards --
@@ -523,7 +522,6 @@ typedef void (*delayFunc_t)(unsigned int);
// loadware. To change loadware, you must begin again with step 2, resetting
// the board again (step 1 not needed).
-static void iiEllisInit(void);
static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
static int iiReset(i2eBordStrPtr);
static int iiResetDelay(i2eBordStrPtr);
diff --git a/drivers/char/ip2/ip2base.c b/drivers/char/ip2/ip2base.c
deleted file mode 100644
index 8155e247c04..00000000000
--- a/drivers/char/ip2/ip2base.c
+++ /dev/null
@@ -1,108 +0,0 @@
-// ip2.c
-// This is a dummy module to make the firmware available when needed
-// and allows it to be unloaded when not. Rumor is the __initdata
-// macro doesn't always works on all platforms so we use this kludge.
-// If not compiled as a module it just makes fip_firm avaliable then
-// __initdata should work as advertized
-//
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-
-#ifndef __init
-#define __init
-#endif
-#ifndef __initfunc
-#define __initfunc(a) a
-#endif
-#ifndef __initdata
-#define __initdata
-#endif
-
-#include "ip2types.h"
-
-int
-ip2_loadmain(int *, int *); // ref into ip2main.c
-
-/* Note: Add compiled in defaults to these arrays, not to the structure
- in ip2.h any longer. That structure WILL get overridden
- by these values, or command line values, or insmod values!!! =mhw=
-*/
-static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
-
-static int poll_only = 0;
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards");
-module_param(poll_only, bool, 0);
-MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
-
-
-static int __init ip2_init(void)
-{
- if( poll_only ) {
- /* Hard lock the interrupts to zero */
- irq[0] = irq[1] = irq[2] = irq[3] = 0;
- }
-
- return ip2_loadmain(io, irq);
-}
-module_init(ip2_init);
-
-MODULE_LICENSE("GPL");
-
-#ifndef MODULE
-/******************************************************************************
- * ip2_setup:
- * str: kernel command line string
- *
- * Can't autoprobe the boards so user must specify configuration on
- * kernel command line. Sane people build it modular but the others
- * come here.
- *
- * Alternating pairs of io,irq for up to 4 boards.
- * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
- *
- * io=0 => No board
- * io=1 => PCI
- * io=2 => EISA
- * else => ISA I/O address
- *
- * irq=0 or invalid for ISA will revert to polling mode
- *
- * Any value = -1, do not overwrite compiled in value.
- *
- ******************************************************************************/
-static int __init ip2_setup(char *str)
-{
- int ints[10]; /* 4 boards, 2 parameters + 2 */
- int i, j;
-
- str = get_options (str, ARRAY_SIZE(ints), ints);
-
- for( i = 0, j = 1; i < 4; i++ ) {
- if( j > ints[0] ) {
- break;
- }
- if( ints[j] >= 0 ) {
- io[i] = ints[j];
- }
- j++;
- if( j > ints[0] ) {
- break;
- }
- if( ints[j] >= 0 ) {
- irq[i] = ints[j];
- }
- j++;
- }
- return 1;
-}
-__setup("ip2=", ip2_setup);
-#endif /* !MODULE */
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 689f9dcd3b8..70e0ebc30bd 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
/*************/
/* String constants to identify ourselves */
-static char *pcName = "Computone IntelliPort Plus multiport driver";
-static char *pcVersion = "1.2.14";
+static const char pcName[] = "Computone IntelliPort Plus multiport driver";
+static const char pcVersion[] = "1.2.14";
/* String constants for port names */
-static char *pcDriver_name = "ip2";
-static char *pcIpl = "ip2ipl";
-
-// cheezy kludge or genius - you decide?
-int ip2_loadmain(int *, int *);
+static const char pcDriver_name[] = "ip2";
+static const char pcIpl[] = "ip2ipl";
/***********************/
/* Function Prototypes */
@@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = {
.open = ip2_ipl_open,
};
-static unsigned long irq_counter = 0;
-static unsigned long bh_counter = 0;
+static unsigned long irq_counter;
+static unsigned long bh_counter;
// Use immediate queue to service interrupts
#define USE_IQI
@@ -252,7 +249,6 @@ static unsigned long bh_counter = 0;
*/
#define POLL_TIMEOUT (jiffies + 1)
static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-static char TimerOn;
#ifdef IP2DEBUG_TRACE
/* Trace (debug) buffer data */
@@ -268,8 +264,8 @@ static int tracewrap;
/**********/
#if defined(MODULE) && defined(IP2DEBUG_OPEN)
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
- tty->name,(pCh->flags),ip2_tty_driver->refcount, \
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+ tty->name,(pCh->flags), \
tty->count,/*GET_USE_COUNT(module)*/0,s)
#else
#define DBG_CNT(s)
@@ -287,8 +283,9 @@ static int tracewrap;
MODULE_AUTHOR("Doug McNash");
MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+MODULE_LICENSE("GPL");
-static int poll_only = 0;
+static int poll_only;
static int Eisa_irq;
static int Eisa_slot;
@@ -297,34 +294,46 @@ static int iindx;
static char rirqs[IP2_MAX_BOARDS];
static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
+/* Note: Add compiled in defaults to these arrays, not to the structure
+ in ip2.h any longer. That structure WILL get overridden
+ by these values, or command line values, or insmod values!!! =mhw=
+*/
+static int io[IP2_MAX_BOARDS];
+static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
+module_param(poll_only, bool, 0);
+MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
+
/* for sysfs class support */
static struct class *ip2_class;
-// Some functions to keep track of what irq's we have
+/* Some functions to keep track of what irqs we have */
-static int
-is_valid_irq(int irq)
+static int __init is_valid_irq(int irq)
{
int *i = Valid_Irqs;
- while ((*i != 0) && (*i != irq)) {
+ while (*i != 0 && *i != irq)
i++;
- }
- return (*i);
+
+ return *i;
}
-static void
-mark_requested_irq( char irq )
+static void __init mark_requested_irq(char irq)
{
rirqs[iindx++] = irq;
}
-#ifdef MODULE
-static int
-clear_requested_irq( char irq )
+static int __exit clear_requested_irq(char irq)
{
int i;
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
if (rirqs[i] == irq) {
rirqs[i] = 0;
return 1;
@@ -332,17 +341,15 @@ clear_requested_irq( char irq )
}
return 0;
}
-#endif
-static int
-have_requested_irq( char irq )
+static int have_requested_irq(char irq)
{
- // array init to zeros so 0 irq will not be requested as a side effect
+ /* array init to zeros so 0 irq will not be requested as a side
+ * effect */
int i;
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+ for (i = 0; i < IP2_MAX_BOARDS; ++i)
if (rirqs[i] == irq)
return 1;
- }
return 0;
}
@@ -361,53 +368,45 @@ have_requested_irq( char irq )
/* handle subsequent installations of the driver. All memory allocated by the */
/* driver should be returned since it may be unloaded from memory. */
/******************************************************************************/
-#ifdef MODULE
-void __exit
-ip2_cleanup_module(void)
+static void __exit ip2_cleanup_module(void)
{
int err;
int i;
-#ifdef IP2DEBUG_INIT
- printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
-#endif
- /* Stop poll timer if we had one. */
- if ( TimerOn ) {
- del_timer ( &PollTimer );
- TimerOn = 0;
- }
+ del_timer_sync(&PollTimer);
/* Reset the boards we have. */
- for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( i2BoardPtrTable[i] ) {
- iiReset( i2BoardPtrTable[i] );
- }
- }
+ for (i = 0; i < IP2_MAX_BOARDS; i++)
+ if (i2BoardPtrTable[i])
+ iiReset(i2BoardPtrTable[i]);
/* The following is done at most once, if any boards were installed. */
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( i2BoardPtrTable[i] ) {
- iiResetDelay( i2BoardPtrTable[i] );
+ for (i = 0; i < IP2_MAX_BOARDS; i++) {
+ if (i2BoardPtrTable[i]) {
+ iiResetDelay(i2BoardPtrTable[i]);
/* free io addresses and Tibet */
- release_region( ip2config.addr[i], 8 );
+ release_region(ip2config.addr[i], 8);
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
- device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+ device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
+ 4 * i + 1));
}
/* Disable and remove interrupt handler. */
- if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {
- free_irq ( ip2config.irq[i], (void *)&pcName);
- clear_requested_irq( ip2config.irq[i]);
+ if (ip2config.irq[i] > 0 &&
+ have_requested_irq(ip2config.irq[i])) {
+ free_irq(ip2config.irq[i], (void *)&pcName);
+ clear_requested_irq(ip2config.irq[i]);
}
}
class_destroy(ip2_class);
- if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
- printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
- }
+ err = tty_unregister_driver(ip2_tty_driver);
+ if (err)
+ printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
+ err);
put_tty_driver(ip2_tty_driver);
unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
remove_proc_entry("ip2mem", NULL);
- // free memory
+ /* free memory */
for (i = 0; i < IP2_MAX_BOARDS; i++) {
void *pB;
#ifdef CONFIG_PCI
@@ -417,24 +416,18 @@ ip2_cleanup_module(void)
ip2config.pci_dev[i] = NULL;
}
#endif
- if ((pB = i2BoardPtrTable[i]) != 0 ) {
- kfree ( pB );
+ pB = i2BoardPtrTable[i];
+ if (pB != NULL) {
+ kfree(pB);
i2BoardPtrTable[i] = NULL;
}
- if ((DevTableMem[i]) != NULL ) {
- kfree ( DevTableMem[i] );
+ if (DevTableMem[i] != NULL) {
+ kfree(DevTableMem[i]);
DevTableMem[i] = NULL;
}
}
-
- /* Cleanup the iiEllis subsystem. */
- iiEllisCleanup();
-#ifdef IP2DEBUG_INIT
- printk (KERN_DEBUG "IP2 Unloaded\n" );
-#endif
}
module_exit(ip2_cleanup_module);
-#endif /* MODULE */
static const struct tty_operations ip2_ops = {
.open = ip2_open,
@@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void)
return fw;
}
-int
-ip2_loadmain(int *iop, int *irqp)
+#ifndef MODULE
+/******************************************************************************
+ * ip2_setup:
+ * str: kernel command line string
+ *
+ * Can't autoprobe the boards so user must specify configuration on
+ * kernel command line. Sane people build it modular but the others
+ * come here.
+ *
+ * Alternating pairs of io,irq for up to 4 boards.
+ * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
+ *
+ * io=0 => No board
+ * io=1 => PCI
+ * io=2 => EISA
+ * else => ISA I/O address
+ *
+ * irq=0 or invalid for ISA will revert to polling mode
+ *
+ * Any value = -1, do not overwrite compiled in value.
+ *
+ ******************************************************************************/
+static int __init ip2_setup(char *str)
+{
+ int j, ints[10]; /* 4 boards, 2 parameters + 2 */
+ unsigned int i;
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
+ for (i = 0, j = 1; i < 4; i++) {
+ if (j > ints[0])
+ break;
+ if (ints[j] >= 0)
+ io[i] = ints[j];
+ j++;
+ if (j > ints[0])
+ break;
+ if (ints[j] >= 0)
+ irq[i] = ints[j];
+ j++;
+ }
+ return 1;
+}
+__setup("ip2=", ip2_setup);
+#endif /* !MODULE */
+
+static int __init ip2_loadmain(void)
{
int i, j, box;
int err = 0;
- static int loaded;
i2eBordStrPtr pB = NULL;
int rc = -1;
- static struct pci_dev *pci_dev_i = NULL;
+ struct pci_dev *pdev = NULL;
const struct firmware *fw = NULL;
- ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
+ if (poll_only) {
+ /* Hard lock the interrupts to zero */
+ irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
+ }
+
+ ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
/* process command line arguments to modprobe or
insmod i.e. iop & irqp */
/* irqp and iop should ALWAYS be specified now... But we check
them individually just to be sure, anyways... */
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if (iop) {
- ip2config.addr[i] = iop[i];
- if (irqp) {
- if( irqp[i] >= 0 ) {
- ip2config.irq[i] = irqp[i];
- } else {
- ip2config.irq[i] = 0;
- }
- // This is a little bit of a hack. If poll_only=1 on command
- // line back in ip2.c OR all IRQs on all specified boards are
- // explicitly set to 0, then drop to poll only mode and override
- // PCI or EISA interrupts. This superceeds the old hack of
- // triggering if all interrupts were zero (like da default).
- // Still a hack but less prone to random acts of terrorism.
- //
- // What we really should do, now that the IRQ default is set
- // to -1, is to use 0 as a hard coded, do not probe.
- //
- // /\/\|=mhw=|\/\/
- poll_only |= irqp[i];
- }
- }
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ ip2config.addr[i] = io[i];
+ if (irq[i] >= 0)
+ ip2config.irq[i] = irq[i];
+ else
+ ip2config.irq[i] = 0;
+ /* This is a little bit of a hack. If poll_only=1 on command
+ line back in ip2.c OR all IRQs on all specified boards are
+ explicitly set to 0, then drop to poll only mode and override
+ PCI or EISA interrupts. This superceeds the old hack of
+ triggering if all interrupts were zero (like da default).
+ Still a hack but less prone to random acts of terrorism.
+
+ What we really should do, now that the IRQ default is set
+ to -1, is to use 0 as a hard coded, do not probe.
+
+ /\/\|=mhw=|\/\/
+ */
+ poll_only |= irq[i];
}
poll_only = !poll_only;
/* Announce our presence */
- printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
-
- // ip2 can be unloaded and reloaded for no good reason
- // we can't let that happen here or bad things happen
- // second load hoses board but not system - fixme later
- if (loaded) {
- printk( KERN_INFO "Still loaded\n" );
- return 0;
- }
- loaded++;
+ printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
if (!ip2_tty_driver)
return -ENOMEM;
- /* Initialise the iiEllis subsystem. */
- iiEllisInit();
-
- /* Initialize arrays. */
- memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
- memset( DevTable, 0, sizeof DevTable );
-
/* Initialise all the boards we can find (up to the maximum). */
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- switch ( ip2config.addr[i] ) {
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ switch (ip2config.addr[i]) {
case 0: /* skip this slot even if card is present */
break;
default: /* ISA */
/* ISA address must be specified */
- if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
- printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
- i, ip2config.addr[i] );
+ if (ip2config.addr[i] < 0x100 ||
+ ip2config.addr[i] > 0x3f8) {
+ printk(KERN_ERR "IP2: Bad ISA board %d "
+ "address %x\n", i,
+ ip2config.addr[i]);
ip2config.addr[i] = 0;
- } else {
- ip2config.type[i] = ISA;
-
- /* Check for valid irq argument, set for polling if invalid */
- if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
- printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
- ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
- }
+ break;
+ }
+ ip2config.type[i] = ISA;
+
+ /* Check for valid irq argument, set for polling if
+ * invalid */
+ if (ip2config.irq[i] &&
+ !is_valid_irq(ip2config.irq[i])) {
+ printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
+ ip2config.irq[i]);
+ /* 0 is polling and is valid in that sense */
+ ip2config.irq[i] = 0;
}
break;
case PCI:
#ifdef CONFIG_PCI
- {
- int status;
+ {
+ u32 addr;
+ int status;
- pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
- PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
- if (pci_dev_i != NULL) {
- unsigned int addr;
-
- if (pci_enable_device(pci_dev_i)) {
- printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
- pci_name(pci_dev_i));
- break;
- }
- ip2config.type[i] = PCI;
- ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
- status =
- pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
- if ( addr & 1 ) {
- ip2config.addr[i]=(USHORT)(addr&0xfffe);
- } else {
- printk( KERN_ERR "IP2: PCI I/O address error\n");
- }
+ pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
+ PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
+ if (pdev == NULL) {
+ ip2config.addr[i] = 0;
+ printk(KERN_ERR "IP2: PCI board %d not "
+ "found\n", i);
+ break;
+ }
-// If the PCI BIOS assigned it, lets try and use it. If we
-// can't acquire it or it screws up, deal with it then.
-
-// if (!is_valid_irq(pci_irq)) {
-// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
-// pci_irq = 0;
-// }
- ip2config.irq[i] = pci_dev_i->irq;
- } else { // ann error
- ip2config.addr[i] = 0;
- printk(KERN_ERR "IP2: PCI board %d not found\n", i);
- }
+ if (pci_enable_device(pdev)) {
+ dev_err(&pdev->dev, "can't enable device\n");
+ break;
}
+ ip2config.type[i] = PCI;
+ ip2config.pci_dev[i] = pci_dev_get(pdev);
+ status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
+ &addr);
+ if (addr & 1)
+ ip2config.addr[i] = (USHORT)(addr & 0xfffe);
+ else
+ dev_err(&pdev->dev, "I/O address error\n");
+
+ ip2config.irq[i] = pdev->irq;
+ }
#else
- printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
- printk( KERN_ERR "IP2: configured in this kernel.\n");
- printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
+ printk(KERN_ERR "IP2: PCI card specified but PCI "
+ "support not enabled.\n");
+ printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
+ "defined!\n");
#endif /* CONFIG_PCI */
break;
case EISA:
- if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
+ ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
+ if (ip2config.addr[i] != 0) {
/* Eisa_irq set as side effect, boo */
ip2config.type[i] = EISA;
}
@@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp)
break;
} /* switch */
} /* for */
- if (pci_dev_i)
- pci_dev_put(pci_dev_i);
+ pci_dev_put(pdev);
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( ip2config.addr[i] ) {
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ if (ip2config.addr[i]) {
pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
if (pB) {
i2BoardPtrTable[i] = pB;
- iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
- iiReset( pB );
- } else {
- printk(KERN_ERR "IP2: board memory allocation error\n");
- }
+ iiSetAddress(pB, ip2config.addr[i],
+ ii2DelayTimer);
+ iiReset(pB);
+ } else
+ printk(KERN_ERR "IP2: board memory allocation "
+ "error\n");
}
}
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
- iiResetDelay( pB );
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ pB = i2BoardPtrTable[i];
+ if (pB != NULL) {
+ iiResetDelay(pB);
break;
}
}
- for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
/* We don't want to request the firmware unless we have at
least one board */
- if ( i2BoardPtrTable[i] != NULL ) {
+ if (i2BoardPtrTable[i] != NULL) {
if (!fw)
fw = ip2_request_firmware();
if (!fw)
@@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp)
if (fw)
release_firmware(fw);
- ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
+ ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
ip2_tty_driver->owner = THIS_MODULE;
ip2_tty_driver->name = "ttyF";
@@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp)
ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL;
ip2_tty_driver->init_termios = tty_std_termios;
ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
- ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(ip2_tty_driver, &ip2_ops);
- ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
+ ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
- /* Register the tty devices. */
- if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) {
- printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
+ err = tty_register_driver(ip2_tty_driver);
+ if (err) {
+ printk(KERN_ERR "IP2: failed to register tty driver\n");
put_tty_driver(ip2_tty_driver);
- return -EINVAL;
- } else
- /* Register the IPL driver. */
- if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
- printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
+ return err; /* leaking resources */
+ }
+
+ err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
+ if (err) {
+ printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
+ err);
} else {
/* create the sysfs class */
ip2_class = class_create(THIS_MODULE, "ip2");
@@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp)
/* Register the read_procmem thing */
if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
printk(KERN_ERR "IP2: failed to register read_procmem\n");
- } else {
+ return -EIO; /* leaking resources */
+ }
- ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
- /* Register the interrupt handler or poll handler, depending upon the
- * specified interrupt.
- */
+ ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
+ /* Register the interrupt handler or poll handler, depending upon the
+ * specified interrupt.
+ */
- for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( 0 == ip2config.addr[i] ) {
- continue;
- }
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ if (ip2config.addr[i] == 0)
+ continue;
- if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- device_create_drvdata(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i),
- NULL, "ipl%d", i);
- device_create_drvdata(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
- NULL, "stat%d", i);
-
- for ( box = 0; box < ABS_MAX_BOXES; ++box )
- {
- for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
- {
- if ( pB->i2eChannelMap[box] & (1 << j) )
- {
- tty_register_device(ip2_tty_driver,
- j + ABS_BIGGEST_BOX *
- (box+i*ABS_MAX_BOXES), NULL);
- }
- }
- }
- }
+ pB = i2BoardPtrTable[i];
+ if (pB != NULL) {
+ device_create(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i),
+ NULL, "ipl%d", i);
+ device_create(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+ NULL, "stat%d", i);
+
+ for (box = 0; box < ABS_MAX_BOXES; box++)
+ for (j = 0; j < ABS_BIGGEST_BOX; j++)
+ if (pB->i2eChannelMap[box] & (1 << j))
+ tty_register_device(
+ ip2_tty_driver,
+ j + ABS_BIGGEST_BOX *
+ (box+i*ABS_MAX_BOXES),
+ NULL);
+ }
- if (poll_only) {
-// Poll only forces driver to only use polling and
-// to ignore the probed PCI or EISA interrupts.
- ip2config.irq[i] = CIR_POLL;
- }
- if ( ip2config.irq[i] == CIR_POLL ) {
+ if (poll_only) {
+ /* Poll only forces driver to only use polling and
+ to ignore the probed PCI or EISA interrupts. */
+ ip2config.irq[i] = CIR_POLL;
+ }
+ if (ip2config.irq[i] == CIR_POLL) {
retry:
- if (!TimerOn) {
- PollTimer.expires = POLL_TIMEOUT;
- add_timer ( &PollTimer );
- TimerOn = 1;
- printk( KERN_INFO "IP2: polling\n");
- }
- } else {
- if (have_requested_irq(ip2config.irq[i]))
- continue;
- rc = request_irq( ip2config.irq[i], ip2_interrupt,
- IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
- pcName, i2BoardPtrTable[i]);
- if (rc) {
- printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
- ip2config.irq[i] = CIR_POLL;
- printk( KERN_INFO "IP2: Polling %ld/sec.\n",
- (POLL_TIMEOUT - jiffies));
- goto retry;
- }
- mark_requested_irq(ip2config.irq[i]);
- /* Initialise the interrupt handler bottom half (aka slih). */
+ if (!timer_pending(&PollTimer)) {
+ mod_timer(&PollTimer, POLL_TIMEOUT);
+ printk(KERN_INFO "IP2: polling\n");
}
- }
- for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
- if ( i2BoardPtrTable[i] ) {
- set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
+ } else {
+ if (have_requested_irq(ip2config.irq[i]))
+ continue;
+ rc = request_irq(ip2config.irq[i], ip2_interrupt,
+ IP2_SA_FLAGS |
+ (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
+ pcName, i2BoardPtrTable[i]);
+ if (rc) {
+ printk(KERN_ERR "IP2: request_irq failed: "
+ "error %d\n", rc);
+ ip2config.irq[i] = CIR_POLL;
+ printk(KERN_INFO "IP2: Polling %ld/sec.\n",
+ (POLL_TIMEOUT - jiffies));
+ goto retry;
}
+ mark_requested_irq(ip2config.irq[i]);
+ /* Initialise the interrupt handler bottom half
+ * (aka slih). */
}
}
- ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
- goto out;
+
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ if (i2BoardPtrTable[i]) {
+ /* set and enable board interrupt */
+ set_irq(i, ip2config.irq[i]);
+ }
+ }
+
+ ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
+
+ return 0;
out_chrdev:
unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-out:
+ /* unregister and put tty here */
return err;
}
+module_init(ip2_loadmain);
/******************************************************************************/
/* Function: ip2_init_board() */
@@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void)
{
int i;
i2eBordStrPtr pB;
- const int irq = 0;
- ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
+ ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
/* Service just the boards on the list using this irq */
for( i = 0; i < i2nBoards; ++i ) {
@@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void)
// Only process those boards which match our IRQ.
// IRQ = 0 for polled boards, we won't poll "IRQ" boards
- if ( pB && (pB->i2eUsingIrq == irq) ) {
+ if (pB && pB->i2eUsingIrq == 0)
ip2_irq_work(pB);
- }
}
++irq_counter;
@@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg)
{
ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
- TimerOn = 0; // it's the truth but not checked in service
-
// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
// It will NOT poll boards handled by hard interrupts.
// The issue of queued BH interrupts is handled in ip2_interrupt().
ip2_polled_interrupt();
- PollTimer.expires = POLL_TIMEOUT;
- add_timer( &PollTimer );
- TimerOn = 1;
+ mod_timer(&PollTimer, POLL_TIMEOUT);
ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
}
@@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
case 13:
switch ( cmd ) {
case 64: /* Driver - ip2stat */
- rc = put_user(ip2_tty_driver->refcount, pIndex++ );
+ rc = put_user(-1, pIndex++ );
rc = put_user(irq_counter, pIndex++ );
rc = put_user(bh_counter, pIndex++ );
break;
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 64e1c169e82..835a33c8d5f 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
entry->dev = dev;
mutex_lock(&reg_list_mutex);
- device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
+ device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
list_add(&entry->link, &reg_list);
mutex_unlock(&reg_list_mutex);
}
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 8e8afb6141f..3123bf57ad9 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2695,7 +2695,7 @@ static __devinit void default_find_bmc(void)
for (i = 0; ; i++) {
if (!ipmi_defaults[i].port)
break;
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
if (check_legacy_ioport(ipmi_defaults[i].port))
continue;
#endif
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 8f7cc190b62..7d30ee1d3fc 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -421,17 +421,16 @@ static void isicom_tx(unsigned long _data)
if (retries >= 100)
goto unlock;
+ tty = tty_port_tty_get(&port->port);
+ if (tty == NULL)
+ goto put_unlock;
+
for (; count > 0; count--, port++) {
/* port not active or tx disabled to force flow control */
if (!(port->port.flags & ASYNC_INITIALIZED) ||
!(port->status & ISI_TXOK))
continue;
- tty = port->port.tty;
-
- if (tty == NULL)
- continue;
-
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
if (txcount <= 0 || tty->stopped || tty->hw_stopped)
continue;
@@ -489,6 +488,8 @@ static void isicom_tx(unsigned long _data)
tty_wakeup(tty);
}
+put_unlock:
+ tty_kref_put(tty);
unlock:
spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
/* schedule another tx for hopefully in about 10ms */
@@ -547,7 +548,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty == NULL) {
word_count = byte_count >> 1;
while (byte_count > 1) {
@@ -588,7 +589,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
}
if (port->port.flags & ASYNC_CTS_FLOW) {
- if (port->port.tty->hw_stopped) {
+ if (tty->hw_stopped) {
if (header & ISI_CTS) {
port->port.tty->hw_stopped = 0;
/* start tx ing */
@@ -597,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
tty_wakeup(tty);
}
} else if (!(header & ISI_CTS)) {
- port->port.tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
/* stop tx ing */
port->status &= ~(ISI_TXOK | ISI_CTS);
}
@@ -660,24 +661,21 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
}
outw(0x0000, base+0x04); /* enable interrupts */
spin_unlock(&card->card_lock);
+ tty_kref_put(tty);
return IRQ_HANDLED;
}
-static void isicom_config_port(struct isi_port *port)
+static void isicom_config_port(struct tty_struct *tty)
{
+ struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card;
- struct tty_struct *tty;
unsigned long baud;
unsigned long base = card->base;
u16 channel_setup, channel = port->channel,
shift_count = card->shift_count;
unsigned char flow_ctrl;
- tty = port->port.tty;
-
- if (tty == NULL)
- return;
/* FIXME: Switch to new tty baud API */
baud = C_BAUD(tty);
if (baud & CBAUDEX) {
@@ -690,7 +688,7 @@ static void isicom_config_port(struct isi_port *port)
/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
if (baud < 1 || baud > 4)
- port->port.tty->termios->c_cflag &= ~CBAUDEX;
+ tty->termios->c_cflag &= ~CBAUDEX;
else
baud += 15;
}
@@ -797,8 +795,9 @@ static inline void isicom_setup_board(struct isi_board *bp)
spin_unlock_irqrestore(&bp->card_lock, flags);
}
-static int isicom_setup_port(struct isi_port *port)
+static int isicom_setup_port(struct tty_struct *tty)
{
+ struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card;
unsigned long flags;
@@ -808,8 +807,7 @@ static int isicom_setup_port(struct isi_port *port)
return -ENOMEM;
spin_lock_irqsave(&card->card_lock, flags);
- if (port->port.tty)
- clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
+ clear_bit(TTY_IO_ERROR, &tty->flags);
if (port->port.count == 1)
card->count++;
@@ -823,7 +821,7 @@ static int isicom_setup_port(struct isi_port *port)
InterruptTheCard(card->base);
}
- isicom_config_port(port);
+ isicom_config_port(tty);
port->port.flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&card->card_lock, flags);
@@ -934,8 +932,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
port->port.count++;
tty->driver_data = port;
- port->port.tty = tty;
- error = isicom_setup_port(port);
+ tty_port_tty_set(&port->port, tty);
+ error = isicom_setup_port(tty);
if (error == 0)
error = block_til_ready(tty, filp, port);
return error;
@@ -955,15 +953,17 @@ static void isicom_shutdown_port(struct isi_port *port)
struct isi_board *card = port->card;
struct tty_struct *tty;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
- if (!(port->port.flags & ASYNC_INITIALIZED))
+ if (!(port->port.flags & ASYNC_INITIALIZED)) {
+ tty_kref_put(tty);
return;
+ }
tty_port_free_xmit_buf(&port->port);
port->port.flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
/*Fix done by Anil .S on 30-04-2001
remote login through isi port has dtr toggle problem
@@ -1243,9 +1243,10 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int isicom_set_serial_info(struct isi_port *port,
- struct serial_struct __user *info)
+static int isicom_set_serial_info(struct tty_struct *tty,
+ struct serial_struct __user *info)
{
+ struct isi_port *port = tty->driver_data;
struct serial_struct newinfo;
int reconfig_port;
@@ -1276,7 +1277,7 @@ static int isicom_set_serial_info(struct isi_port *port,
if (reconfig_port) {
unsigned long flags;
spin_lock_irqsave(&port->card->card_lock, flags);
- isicom_config_port(port);
+ isicom_config_port(tty);
spin_unlock_irqrestore(&port->card->card_lock, flags);
}
unlock_kernel();
@@ -1318,7 +1319,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
return isicom_get_serial_info(port, argp);
case TIOCSSERIAL:
- return isicom_set_serial_info(port, argp);
+ return isicom_set_serial_info(tty, argp);
default:
return -ENOIOCTLCMD;
@@ -1341,7 +1342,7 @@ static void isicom_set_termios(struct tty_struct *tty,
return;
spin_lock_irqsave(&port->card->card_lock, flags);
- isicom_config_port(port);
+ isicom_config_port(tty);
spin_unlock_irqrestore(&port->card->card_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
@@ -1419,7 +1420,7 @@ static void isicom_hangup(struct tty_struct *tty)
port->port.count = 0;
port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
wake_up_interruptible(&port->port.open_wait);
}
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 843a2afaf20..44e5d60f517 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -623,24 +623,25 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
static void stli_poll(unsigned long arg);
static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
-static int stli_initopen(struct stlibrd *brdp, struct stliport *portp);
+static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
-static int stli_setport(struct stliport *portp);
+static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
+ struct stliport *portp, struct file *filp);
+static int stli_setport(struct tty_struct *tty);
static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
-static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
+static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
static long stli_mktiocm(unsigned long sigvalue);
static void stli_read(struct stlibrd *brdp, struct stliport *portp);
static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
-static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
+static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
static int stli_getbrdstats(combrd_t __user *bp);
-static int stli_getportstats(struct stliport *portp, comstats_t __user *cp);
-static int stli_portcmdstats(struct stliport *portp);
+static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
+static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
static int stli_getportstruct(struct stliport __user *arg);
static int stli_getbrdstruct(struct stlibrd __user *arg);
@@ -731,12 +732,16 @@ static void stli_cleanup_ports(struct stlibrd *brdp)
{
struct stliport *portp;
unsigned int j;
+ struct tty_struct *tty;
for (j = 0; j < STL_MAXPORTS; j++) {
portp = brdp->ports[j];
if (portp != NULL) {
- if (portp->port.tty != NULL)
- tty_hangup(portp->port.tty);
+ tty = tty_port_tty_get(&portp->port);
+ if (tty != NULL) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
kfree(portp);
}
}
@@ -824,7 +829,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
* requires several commands to the board we will need to wait for any
* other open that is already initializing the port.
*/
- portp->port.tty = tty;
+ tty_port_tty_set(&portp->port, tty);
tty->driver_data = portp;
portp->port.count++;
@@ -835,7 +840,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
set_bit(ST_INITIALIZING, &portp->state);
- if ((rc = stli_initopen(brdp, portp)) >= 0) {
+ if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
portp->port.flags |= ASYNC_INITIALIZED;
clear_bit(TTY_IO_ERROR, &tty->flags);
}
@@ -864,7 +869,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
* then also we might have to wait for carrier.
*/
if (!(filp->f_flags & O_NONBLOCK)) {
- if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)
+ if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0)
return rc;
}
portp->port.flags |= ASYNC_NORMAL_ACTIVE;
@@ -930,7 +935,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
stli_flushbuffer(tty);
tty->closing = 0;
- portp->port.tty = NULL;
+ tty_port_tty_set(&portp->port, NULL);
if (portp->openwaitcnt) {
if (portp->close_delay)
@@ -952,9 +957,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
* this still all happens pretty quickly.
*/
-static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
+static int stli_initopen(struct tty_struct *tty,
+ struct stlibrd *brdp, struct stliport *portp)
{
- struct tty_struct *tty;
asynotify_t nt;
asyport_t aport;
int rc;
@@ -969,10 +974,7 @@ static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
sizeof(asynotify_t), 0)) < 0)
return rc;
- tty = portp->port.tty;
- if (tty == NULL)
- return -ENODEV;
- stli_mkasyport(portp, &aport, tty->termios);
+ stli_mkasyport(tty, portp, &aport, tty->termios);
if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
sizeof(asyport_t), 0)) < 0)
return rc;
@@ -1161,22 +1163,21 @@ static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned l
* waiting for the command to complete - so must have user context.
*/
-static int stli_setport(struct stliport *portp)
+static int stli_setport(struct tty_struct *tty)
{
+ struct stliport *portp = tty->driver_data;
struct stlibrd *brdp;
asyport_t aport;
if (portp == NULL)
return -ENODEV;
- if (portp->port.tty == NULL)
- return -ENODEV;
if (portp->brdnr >= stli_nrbrds)
return -ENODEV;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
return -ENODEV;
- stli_mkasyport(portp, &aport, portp->port.tty->termios);
+ stli_mkasyport(tty, portp, &aport, tty->termios);
return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
}
@@ -1187,7 +1188,8 @@ static int stli_setport(struct stliport *portp)
* maybe because if we are clocal then we don't need to wait...
*/
-static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
+static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
+ struct stliport *portp, struct file *filp)
{
unsigned long flags;
int rc, doclocal;
@@ -1195,7 +1197,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct
rc = 0;
doclocal = 0;
- if (portp->port.tty->termios->c_cflag & CLOCAL)
+ if (tty->termios->c_cflag & CLOCAL)
doclocal++;
spin_lock_irqsave(&stli_lock, flags);
@@ -1373,8 +1375,6 @@ static void stli_flushchars(struct tty_struct *tty)
stli_txcookrealsize = 0;
stli_txcooktty = NULL;
- if (tty == NULL)
- return;
if (cooktty == NULL)
return;
if (tty != cooktty)
@@ -1572,10 +1572,11 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s
* just quietly ignore any requests to change irq, etc.
*/
-static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
+static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
{
struct serial_struct sio;
int rc;
+ struct stliport *portp = tty->driver_data;
if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
return -EFAULT;
@@ -1594,7 +1595,7 @@ static int stli_setserial(struct stliport *portp, struct serial_struct __user *s
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
- if ((rc = stli_setport(portp)) < 0)
+ if ((rc = stli_setport(tty)) < 0)
return rc;
return 0;
}
@@ -1685,17 +1686,17 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
rc = stli_getserial(portp, argp);
break;
case TIOCSSERIAL:
- rc = stli_setserial(portp, argp);
+ rc = stli_setserial(tty, argp);
break;
case STL_GETPFLAG:
rc = put_user(portp->pflag, (unsigned __user *)argp);
break;
case STL_SETPFLAG:
if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
- stli_setport(portp);
+ stli_setport(tty);
break;
case COM_GETPORTSTATS:
- rc = stli_getportstats(portp, argp);
+ rc = stli_getportstats(tty, portp, argp);
break;
case COM_CLRPORTSTATS:
rc = stli_clrportstats(portp, argp);
@@ -1729,8 +1730,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
struct ktermios *tiosp;
asyport_t aport;
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1742,7 +1741,7 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
tiosp = tty->termios;
- stli_mkasyport(portp, &aport, tiosp);
+ stli_mkasyport(tty, portp, &aport, tiosp);
stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
@@ -1854,7 +1853,7 @@ static void stli_hangup(struct tty_struct *tty)
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
- portp->port.tty = NULL;
+ tty_port_tty_set(&portp->port, NULL);
portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
portp->port.count = 0;
spin_unlock_irqrestore(&stli_lock, flags);
@@ -1935,8 +1934,6 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
struct stliport *portp;
unsigned long tend;
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1998,7 +1995,7 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn
char *sp, *uart;
int rc, cnt;
- rc = stli_portcmdstats(portp);
+ rc = stli_portcmdstats(NULL, portp);
uart = "UNKNOWN";
if (brdp->state & BST_STARTED) {
@@ -2188,7 +2185,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
if (test_bit(ST_RXSTOP, &portp->state))
return;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (tty == NULL)
return;
@@ -2230,6 +2227,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
set_bit(ST_RXING, &portp->state);
tty_schedule_flip(tty);
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -2362,7 +2360,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
if (ap->notify) {
nt = ap->changed;
ap->notify = 0;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (nt.signal & SG_DCD) {
oldsigs = portp->sigs;
@@ -2399,6 +2397,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
tty_schedule_flip(tty);
}
}
+ tty_kref_put(tty);
if (nt.data & DT_RXBUSY) {
donerx++;
@@ -2535,14 +2534,15 @@ static void stli_poll(unsigned long arg)
* the slave.
*/
-static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
+static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
+ asyport_t *pp, struct ktermios *tiosp)
{
memset(pp, 0, sizeof(asyport_t));
/*
* Start of by setting the baud, char size, parity and stop bit info.
*/
- pp->baudout = tty_get_baud_rate(portp->port.tty);
+ pp->baudout = tty_get_baud_rate(tty);
if ((tiosp->c_cflag & CBAUD) == B38400) {
if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
pp->baudout = 57600;
@@ -2695,7 +2695,7 @@ static int stli_initports(struct stlibrd *brdp)
printk("STALLION: failed to allocate port structure\n");
continue;
}
-
+ tty_port_init(&portp->port);
portp->magic = STLI_PORTMAGIC;
portp->portnr = i;
portp->brdnr = brdp->brdnr;
@@ -4220,7 +4220,7 @@ static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
* what port to get stats for (used through board control device).
*/
-static int stli_portcmdstats(struct stliport *portp)
+static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
{
unsigned long flags;
struct stlibrd *brdp;
@@ -4249,15 +4249,15 @@ static int stli_portcmdstats(struct stliport *portp)
stli_comstats.flags = portp->port.flags;
spin_lock_irqsave(&brd_lock, flags);
- if (portp->port.tty != NULL) {
- if (portp->port.tty->driver_data == portp) {
- stli_comstats.ttystate = portp->port.tty->flags;
+ if (tty != NULL) {
+ if (portp->port.tty == tty) {
+ stli_comstats.ttystate = tty->flags;
stli_comstats.rxbuffered = -1;
- if (portp->port.tty->termios != NULL) {
- stli_comstats.cflags = portp->port.tty->termios->c_cflag;
- stli_comstats.iflags = portp->port.tty->termios->c_iflag;
- stli_comstats.oflags = portp->port.tty->termios->c_oflag;
- stli_comstats.lflags = portp->port.tty->termios->c_lflag;
+ if (tty->termios != NULL) {
+ stli_comstats.cflags = tty->termios->c_cflag;
+ stli_comstats.iflags = tty->termios->c_iflag;
+ stli_comstats.oflags = tty->termios->c_oflag;
+ stli_comstats.lflags = tty->termios->c_lflag;
}
}
}
@@ -4294,7 +4294,8 @@ static int stli_portcmdstats(struct stliport *portp)
* what port to get stats for (used through board control device).
*/
-static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
+static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
+ comstats_t __user *cp)
{
struct stlibrd *brdp;
int rc;
@@ -4312,7 +4313,7 @@ static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
if (!brdp)
return -ENODEV;
- if ((rc = stli_portcmdstats(portp)) < 0)
+ if ((rc = stli_portcmdstats(tty, portp)) < 0)
return rc;
return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
@@ -4427,7 +4428,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
switch (cmd) {
case COM_GETPORTSTATS:
- rc = stli_getportstats(NULL, argp);
+ rc = stli_getportstats(NULL, NULL, argp);
done++;
break;
case COM_CLRPORTSTATS:
@@ -4599,9 +4600,8 @@ static int __init istallion_module_init(void)
istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++)
- device_create_drvdata(istallion_class, NULL,
- MKDEV(STL_SIOMEMMAJOR, i),
- NULL, "staliomem%d", i);
+ device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_deinit:
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 7b3a212c86b..de26a978fbd 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1249,7 +1249,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
return;
}
- if (keycode > NR_KEYS)
+ if (keycode >= NR_KEYS)
if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
else
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 3f2719b9f77..e444c2dba16 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -813,8 +813,8 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
- "lp%d", nr);
+ device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+ "lp%d", nr);
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 672b08e694d..6431f6921a6 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -992,9 +992,9 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++)
- device_create_drvdata(mem_class, NULL,
- MKDEV(MEM_MAJOR, devlist[i].minor),
- NULL, devlist[i].name);
+ device_create(mem_class, NULL,
+ MKDEV(MEM_MAJOR, devlist[i].minor), NULL,
+ devlist[i].name);
return 0;
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 999aa779c08..a5e0db9d766 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->this_device = device_create_drvdata(misc_class, misc->parent,
- dev, NULL, "%s", misc->name);
+ misc->this_device = device_create(misc_class, misc->parent, dev, NULL,
+ "%s", misc->name);
if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->this_device);
goto out;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index d3d7864e0c1..12d327a2c9b 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -205,7 +205,7 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
static void moxa_poll(unsigned long);
static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
static void moxa_setup_empty_event(struct tty_struct *);
-static void moxa_shut_down(struct moxa_port *);
+static void moxa_shut_down(struct tty_struct *);
/*
* moxa board interface functions:
*/
@@ -217,7 +217,7 @@ static void MoxaPortLineCtrl(struct moxa_port *, int, int);
static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
static int MoxaPortLineStatus(struct moxa_port *);
static void MoxaPortFlushData(struct moxa_port *, int);
-static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int);
+static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
static int MoxaPortReadData(struct moxa_port *);
static int MoxaPortTxQueue(struct moxa_port *);
static int MoxaPortRxQueue(struct moxa_port *);
@@ -332,6 +332,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
for (i = 0; i < MAX_BOARDS; i++) {
p = moxa_boards[i].ports;
for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+ struct tty_struct *ttyp;
memset(&tmp, 0, sizeof(tmp));
if (!moxa_boards[i].ready)
goto copy;
@@ -344,10 +345,12 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
if (status & 4)
tmp.dcd = 1;
- if (!p->port.tty || !p->port.tty->termios)
+ ttyp = tty_port_tty_get(&p->port);
+ if (!ttyp || !ttyp->termios)
tmp.cflag = p->cflag;
else
- tmp.cflag = p->port.tty->termios->c_cflag;
+ tmp.cflag = ttyp->termios->c_cflag;
+ tty_kref_put(tty);
copy:
if (copy_to_user(argm, &tmp, sizeof(tmp))) {
mutex_unlock(&moxa_openlock);
@@ -510,7 +513,7 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
size_t len)
{
void __iomem *baseAddr = brd->basemem;
- const u16 *uptr = ptr;
+ const __le16 *uptr = ptr;
size_t wlen, len2, j;
unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
unsigned int i, retry;
@@ -880,8 +883,14 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
/* pci hot-un-plug support */
for (a = 0; a < brd->numPorts; a++)
- if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
- tty_hangup(brd->ports[a].port.tty);
+ if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
+ struct tty_struct *tty = tty_port_tty_get(
+ &brd->ports[a].port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
+ }
while (1) {
opened = 0;
for (a = 0; a < brd->numPorts; a++)
@@ -1096,13 +1105,14 @@ static void __exit moxa_exit(void)
module_init(moxa_init);
module_exit(moxa_exit);
-static void moxa_close_port(struct moxa_port *ch)
+static void moxa_close_port(struct tty_struct *tty)
{
- moxa_shut_down(ch);
+ struct moxa_port *ch = tty->driver_data;
+ moxa_shut_down(tty);
MoxaPortFlushData(ch, 2);
ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- ch->port.tty->driver_data = NULL;
- ch->port.tty = NULL;
+ tty->driver_data = NULL;
+ tty_port_tty_set(&ch->port, NULL);
}
static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
@@ -1161,7 +1171,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
ch->port.count++;
tty->driver_data = ch;
- ch->port.tty = tty;
+ tty_port_tty_set(&ch->port, tty);
if (!(ch->port.flags & ASYNC_INITIALIZED)) {
ch->statusflags = 0;
moxa_set_tty_param(tty, tty->termios);
@@ -1179,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
if (retval) {
if (ch->port.count) /* 0 means already hung up... */
if (--ch->port.count == 0)
- moxa_close_port(ch);
+ moxa_close_port(tty);
} else
ch->port.flags |= ASYNC_NORMAL_ACTIVE;
mutex_unlock(&moxa_openlock);
@@ -1219,7 +1229,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */
}
- moxa_close_port(ch);
+ moxa_close_port(tty);
unlock:
mutex_unlock(&moxa_openlock);
}
@@ -1234,7 +1244,7 @@ static int moxa_write(struct tty_struct *tty,
return 0;
spin_lock_bh(&moxa_lock);
- len = MoxaPortWriteData(ch, buf, count);
+ len = MoxaPortWriteData(tty, buf, count);
spin_unlock_bh(&moxa_lock);
ch->statusflags |= LOWWAIT;
@@ -1409,7 +1419,7 @@ static void moxa_hangup(struct tty_struct *tty)
return;
}
ch->port.count = 0;
- moxa_close_port(ch);
+ moxa_close_port(tty);
mutex_unlock(&moxa_openlock);
wake_up_interruptible(&ch->port.open_wait);
@@ -1417,11 +1427,14 @@ static void moxa_hangup(struct tty_struct *tty)
static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
{
+ struct tty_struct *tty;
dcd = !!dcd;
- if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) {
- if (!dcd)
- tty_hangup(p->port.tty);
+ if (dcd != p->DCDState) {
+ tty = tty_port_tty_get(&p->port);
+ if (tty && C_CLOCAL(tty) && !dcd)
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
p->DCDState = dcd;
}
@@ -1429,7 +1442,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
u16 __iomem *ip)
{
- struct tty_struct *tty = p->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&p->port);
void __iomem *ofsAddr;
unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
u16 intr;
@@ -1476,6 +1489,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
tty_insert_flip_char(tty, 0, TTY_BREAK);
tty_schedule_flip(tty);
}
+ tty_kref_put(tty);
if (intr & IntrLine)
moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
@@ -1560,9 +1574,9 @@ static void moxa_setup_empty_event(struct tty_struct *tty)
spin_unlock_bh(&moxa_lock);
}
-static void moxa_shut_down(struct moxa_port *ch)
+static void moxa_shut_down(struct tty_struct *tty)
{
- struct tty_struct *tp = ch->port.tty;
+ struct moxa_port *ch = tty->driver_data;
if (!(ch->port.flags & ASYNC_INITIALIZED))
return;
@@ -1572,7 +1586,7 @@ static void moxa_shut_down(struct moxa_port *ch)
/*
* If we're a modem control device and HUPCL is on, drop RTS & DTR.
*/
- if (C_HUPCL(tp))
+ if (C_HUPCL(tty))
MoxaPortLineCtrl(ch, 0, 0);
spin_lock_bh(&moxa_lock);
@@ -1953,9 +1967,10 @@ static int MoxaPortLineStatus(struct moxa_port *port)
return val;
}
-static int MoxaPortWriteData(struct moxa_port *port,
+static int MoxaPortWriteData(struct tty_struct *tty,
const unsigned char *buffer, int len)
{
+ struct moxa_port *port = tty->driver_data;
void __iomem *baseAddr, *ofsAddr, *ofs;
unsigned int c, total;
u16 head, tail, tx_mask, spage, epage;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index b638403e8e9..8beef50f95a 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -610,15 +610,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
return 0;
}
-static int mxser_set_baud(struct mxser_port *info, long newspd)
+static int mxser_set_baud(struct tty_struct *tty, long newspd)
{
+ struct mxser_port *info = tty->driver_data;
int quot = 0, baud;
unsigned char cval;
- if (!info->port.tty || !info->port.tty->termios)
- return -1;
-
- if (!(info->ioaddr))
+ if (!info->ioaddr)
return -1;
if (newspd > info->max_baud)
@@ -626,13 +624,13 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
if (newspd == 134) {
quot = 2 * info->baud_base / 269;
- tty_encode_baud_rate(info->port.tty, 134, 134);
+ tty_encode_baud_rate(tty, 134, 134);
} else if (newspd) {
quot = info->baud_base / newspd;
if (quot == 0)
quot = 1;
baud = info->baud_base/quot;
- tty_encode_baud_rate(info->port.tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
} else {
quot = 0;
}
@@ -658,7 +656,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
#ifdef BOTHER
- if (C_BAUD(info->port.tty) == BOTHER) {
+ if (C_BAUD(tty) == BOTHER) {
quot = info->baud_base % newspd;
quot *= 8;
if (quot % newspd > newspd / 2) {
@@ -679,21 +677,20 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static int mxser_change_speed(struct mxser_port *info,
- struct ktermios *old_termios)
+static int mxser_change_speed(struct tty_struct *tty,
+ struct ktermios *old_termios)
{
+ struct mxser_port *info = tty->driver_data;
unsigned cflag, cval, fcr;
int ret = 0;
unsigned char status;
- if (!info->port.tty || !info->port.tty->termios)
- return ret;
- cflag = info->port.tty->termios->c_cflag;
- if (!(info->ioaddr))
+ cflag = tty->termios->c_cflag;
+ if (!info->ioaddr)
return ret;
- if (mxser_set_baud_method[info->port.tty->index] == 0)
- mxser_set_baud(info, tty_get_baud_rate(info->port.tty));
+ if (mxser_set_baud_method[tty->index] == 0)
+ mxser_set_baud(tty, tty_get_baud_rate(tty));
/* byte size and parity */
switch (cflag & CSIZE) {
@@ -762,9 +759,9 @@ static int mxser_change_speed(struct mxser_port *info,
info->MCR |= UART_MCR_AFE;
} else {
status = inb(info->ioaddr + UART_MSR);
- if (info->port.tty->hw_stopped) {
+ if (tty->hw_stopped) {
if (status & UART_MSR_CTS) {
- info->port.tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
if (info->type != PORT_16550A &&
!info->board->chip_flag) {
outb(info->IER & ~UART_IER_THRI,
@@ -774,11 +771,11 @@ static int mxser_change_speed(struct mxser_port *info,
outb(info->IER, info->ioaddr +
UART_IER);
}
- tty_wakeup(info->port.tty);
+ tty_wakeup(tty);
}
} else {
if (!(status & UART_MSR_CTS)) {
- info->port.tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
if ((info->type != PORT_16550A) &&
(!info->board->chip_flag)) {
info->IER &= ~UART_IER_THRI;
@@ -804,21 +801,21 @@ static int mxser_change_speed(struct mxser_port *info,
* Set up parity check flag
*/
info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (I_INPCK(info->port.tty))
+ if (I_INPCK(tty))
info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+ if (I_BRKINT(tty) || I_PARMRK(tty))
info->read_status_mask |= UART_LSR_BI;
info->ignore_status_mask = 0;
- if (I_IGNBRK(info->port.tty)) {
+ if (I_IGNBRK(tty)) {
info->ignore_status_mask |= UART_LSR_BI;
info->read_status_mask |= UART_LSR_BI;
/*
* If we're ignore parity and break indicators, ignore
* overruns too. (For real raw support).
*/
- if (I_IGNPAR(info->port.tty)) {
+ if (I_IGNPAR(tty)) {
info->ignore_status_mask |=
UART_LSR_OE |
UART_LSR_PE |
@@ -830,16 +827,16 @@ static int mxser_change_speed(struct mxser_port *info,
}
}
if (info->board->chip_flag) {
- mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->port.tty));
- mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->port.tty));
- if (I_IXON(info->port.tty)) {
+ mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
+ mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
+ if (I_IXON(tty)) {
mxser_enable_must_rx_software_flow_control(
info->ioaddr);
} else {
mxser_disable_must_rx_software_flow_control(
info->ioaddr);
}
- if (I_IXOFF(info->port.tty)) {
+ if (I_IXOFF(tty)) {
mxser_enable_must_tx_software_flow_control(
info->ioaddr);
} else {
@@ -855,7 +852,8 @@ static int mxser_change_speed(struct mxser_port *info,
return ret;
}
-static void mxser_check_modem_status(struct mxser_port *port, int status)
+static void mxser_check_modem_status(struct tty_struct *tty,
+ struct mxser_port *port, int status)
{
/* update input line counters */
if (status & UART_MSR_TERI)
@@ -874,10 +872,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
wake_up_interruptible(&port->port.open_wait);
}
+ tty = tty_port_tty_get(&port->port);
if (port->port.flags & ASYNC_CTS_FLOW) {
- if (port->port.tty->hw_stopped) {
+ if (tty->hw_stopped) {
if (status & UART_MSR_CTS) {
- port->port.tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
if ((port->type != PORT_16550A) &&
(!port->board->chip_flag)) {
@@ -887,11 +886,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
outb(port->IER, port->ioaddr +
UART_IER);
}
- tty_wakeup(port->port.tty);
+ tty_wakeup(tty);
}
} else {
if (!(status & UART_MSR_CTS)) {
- port->port.tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
if (port->type != PORT_16550A &&
!port->board->chip_flag) {
port->IER &= ~UART_IER_THRI;
@@ -903,8 +902,9 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
}
}
-static int mxser_startup(struct mxser_port *info)
+static int mxser_startup(struct tty_struct *tty)
{
+ struct mxser_port *info = tty->driver_data;
unsigned long page;
unsigned long flags;
@@ -921,8 +921,7 @@ static int mxser_startup(struct mxser_port *info)
}
if (!info->ioaddr || !info->type) {
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+ set_bit(TTY_IO_ERROR, &tty->flags);
free_page(page);
spin_unlock_irqrestore(&info->slock, flags);
return 0;
@@ -952,8 +951,8 @@ static int mxser_startup(struct mxser_port *info)
if (inb(info->ioaddr + UART_LSR) == 0xff) {
spin_unlock_irqrestore(&info->slock, flags);
if (capable(CAP_SYS_ADMIN)) {
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
return 0;
} else
return -ENODEV;
@@ -991,14 +990,13 @@ static int mxser_startup(struct mxser_port *info)
(void) inb(info->ioaddr + UART_IIR);
(void) inb(info->ioaddr + UART_MSR);
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+ clear_bit(TTY_IO_ERROR, &tty->flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
/*
* and set the speed of the serial port
*/
- mxser_change_speed(info, NULL);
+ mxser_change_speed(tty, NULL);
info->port.flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&info->slock, flags);
@@ -1009,8 +1007,9 @@ static int mxser_startup(struct mxser_port *info)
* This routine will shutdown a serial port; interrupts maybe disabled, and
* DTR is dropped if the hangup on close termio flag is on.
*/
-static void mxser_shutdown(struct mxser_port *info)
+static void mxser_shutdown(struct tty_struct *tty)
{
+ struct mxser_port *info = tty->driver_data;
unsigned long flags;
if (!(info->port.flags & ASYNC_INITIALIZED))
@@ -1035,7 +1034,7 @@ static void mxser_shutdown(struct mxser_port *info)
info->IER = 0;
outb(0x00, info->ioaddr + UART_IER);
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
+ if (tty->termios->c_cflag & HUPCL)
info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
outb(info->MCR, info->ioaddr + UART_MCR);
@@ -1051,8 +1050,7 @@ static void mxser_shutdown(struct mxser_port *info)
/* read data port to reset things */
(void) inb(info->ioaddr + UART_RX);
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+ set_bit(TTY_IO_ERROR, &tty->flags);
info->port.flags &= ~ASYNC_INITIALIZED;
@@ -1084,14 +1082,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
tty->driver_data = info;
- info->port.tty = tty;
+ tty_port_tty_set(&info->port, tty);
/*
* Start up serial port
*/
spin_lock_irqsave(&info->slock, flags);
info->port.count++;
spin_unlock_irqrestore(&info->slock, flags);
- retval = mxser_startup(info);
+ retval = mxser_startup(tty);
if (retval)
return retval;
@@ -1209,13 +1207,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
break;
}
}
- mxser_shutdown(info);
+ mxser_shutdown(tty);
mxser_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
- info->port.tty = NULL;
+ tty_port_tty_set(&info->port, NULL);
if (info->port.blocked_open) {
if (info->port.close_delay)
schedule_timeout_interruptible(info->port.close_delay);
@@ -1337,12 +1335,13 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
* friends of mxser_ioctl()
* ------------------------------------------------------------
*/
-static int mxser_get_serial_info(struct mxser_port *info,
+static int mxser_get_serial_info(struct tty_struct *tty,
struct serial_struct __user *retinfo)
{
+ struct mxser_port *info = tty->driver_data;
struct serial_struct tmp = {
.type = info->type,
- .line = info->port.tty->index,
+ .line = tty->index,
.port = info->ioaddr,
.irq = info->board->irq,
.flags = info->port.flags,
@@ -1357,9 +1356,10 @@ static int mxser_get_serial_info(struct mxser_port *info,
return 0;
}
-static int mxser_set_serial_info(struct mxser_port *info,
+static int mxser_set_serial_info(struct tty_struct *tty,
struct serial_struct __user *new_info)
{
+ struct mxser_port *info = tty->driver_data;
struct serial_struct new_serial;
speed_t baud;
unsigned long sl_flags;
@@ -1393,14 +1393,14 @@ static int mxser_set_serial_info(struct mxser_port *info,
(new_serial.flags & ASYNC_FLAGS));
info->port.close_delay = new_serial.close_delay * HZ / 100;
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
- info->port.tty->low_latency =
- (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY)
+ ? 1 : 0;
if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(new_serial.baud_base != info->baud_base ||
new_serial.custom_divisor !=
info->custom_divisor)) {
baud = new_serial.baud_base / new_serial.custom_divisor;
- tty_encode_baud_rate(info->port.tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
}
}
@@ -1411,11 +1411,11 @@ static int mxser_set_serial_info(struct mxser_port *info,
if (info->port.flags & ASYNC_INITIALIZED) {
if (flags != (info->port.flags & ASYNC_SPD_MASK)) {
spin_lock_irqsave(&info->slock, sl_flags);
- mxser_change_speed(info, NULL);
+ mxser_change_speed(tty, NULL);
spin_unlock_irqrestore(&info->slock, sl_flags);
}
} else
- retval = mxser_startup(info);
+ retval = mxser_startup(tty);
return retval;
}
@@ -1461,7 +1461,7 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
spin_lock_irqsave(&info->slock, flags);
status = inb(info->ioaddr + UART_MSR);
if (status & UART_MSR_ANY_DELTA)
- mxser_check_modem_status(info, status);
+ mxser_check_modem_status(tty, info, status);
spin_unlock_irqrestore(&info->slock, flags);
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
@@ -1606,6 +1606,7 @@ static int __init mxser_read_register(int port, unsigned short *regs)
static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
{
struct mxser_port *port;
+ struct tty_struct *tty;
int result, status;
unsigned int i, j;
int ret = 0;
@@ -1643,12 +1644,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
if (!port->ioaddr)
goto copy;
+
+ tty = tty_port_tty_get(&port->port);
- if (!port->port.tty || !port->port.tty->termios)
+ if (!tty || !tty->termios)
ms.cflag = port->normal_termios.c_cflag;
else
- ms.cflag = port->port.tty->termios->c_cflag;
-
+ ms.cflag = tty->termios->c_cflag;
+ tty_kref_put(tty);
status = inb(port->ioaddr + UART_MSR);
if (status & UART_MSR_DCD)
ms.dcd = 1;
@@ -1704,15 +1707,18 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
me->up_txcnt[p] = port->mon_data.up_txcnt;
me->modem_status[p] =
port->mon_data.modem_status;
- me->baudrate[p] = tty_get_baud_rate(port->port.tty);
+ tty = tty_port_tty_get(&port->port);
- if (!port->port.tty || !port->port.tty->termios) {
+ if (!tty || !tty->termios) {
cflag = port->normal_termios.c_cflag;
iflag = port->normal_termios.c_iflag;
+ me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios);
} else {
- cflag = port->port.tty->termios->c_cflag;
- iflag = port->port.tty->termios->c_iflag;
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
+ me->baudrate[p] = tty_get_baud_rate(tty);
}
+ tty_kref_put(tty);
me->databits[p] = cflag & CSIZE;
me->stopbits[p] = cflag & CSTOPB;
@@ -1822,12 +1828,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
switch (cmd) {
case TIOCGSERIAL:
lock_kernel();
- retval = mxser_get_serial_info(info, argp);
+ retval = mxser_get_serial_info(tty, argp);
unlock_kernel();
return retval;
case TIOCSSERIAL:
lock_kernel();
- retval = mxser_set_serial_info(info, argp);
+ retval = mxser_set_serial_info(tty, argp);
unlock_kernel();
return retval;
case TIOCSERGETLSR: /* Get line status register */
@@ -1896,7 +1902,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
lock_kernel();
status = mxser_get_msr(info->ioaddr, 1, tty->index);
- mxser_check_modem_status(info, status);
+ mxser_check_modem_status(tty, info, status);
mcr = inb(info->ioaddr + UART_MCR);
if (mcr & MOXA_MUST_MCR_XON_FLAG)
@@ -1909,7 +1915,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
else
info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
- if (info->port.tty->hw_stopped)
+ if (tty->hw_stopped)
info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
else
info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
@@ -1958,7 +1964,7 @@ static void mxser_stoprx(struct tty_struct *tty)
}
}
- if (info->port.tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios->c_cflag & CRTSCTS) {
info->MCR &= ~UART_MCR_RTS;
outb(info->MCR, info->ioaddr + UART_MCR);
}
@@ -1995,7 +2001,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
}
}
- if (info->port.tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios->c_cflag & CRTSCTS) {
info->MCR |= UART_MCR_RTS;
outb(info->MCR, info->ioaddr + UART_MCR);
}
@@ -2040,7 +2046,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
- mxser_change_speed(info, old_termios);
+ mxser_change_speed(tty, old_termios);
spin_unlock_irqrestore(&info->slock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
@@ -2138,10 +2144,10 @@ static void mxser_hangup(struct tty_struct *tty)
struct mxser_port *info = tty->driver_data;
mxser_flush_buffer(tty);
- mxser_shutdown(info);
+ mxser_shutdown(tty);
info->port.count = 0;
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
+ tty_port_tty_set(&info->port, NULL);
wake_up_interruptible(&info->port.open_wait);
}
@@ -2164,9 +2170,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)
return 0;
}
-static void mxser_receive_chars(struct mxser_port *port, int *status)
+static void mxser_receive_chars(struct tty_struct *tty,
+ struct mxser_port *port, int *status)
{
- struct tty_struct *tty = port->port.tty;
unsigned char ch, gdl;
int ignored = 0;
int cnt = 0;
@@ -2174,9 +2180,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
int max = 256;
recv_room = tty->receive_room;
- if ((recv_room == 0) && (!port->ldisc_stop_rx))
+ if (recv_room == 0 && !port->ldisc_stop_rx)
mxser_stoprx(tty);
-
if (port->board->chip_flag != MOXA_OTHER_UART) {
if (*status & UART_LSR_SPECIAL)
@@ -2253,7 +2258,7 @@ intr_old:
} while (*status & UART_LSR_DR);
end_intr:
- mxvar_log.rxcnt[port->port.tty->index] += cnt;
+ mxvar_log.rxcnt[tty->index] += cnt;
port->mon_data.rxcnt += cnt;
port->mon_data.up_rxcnt += cnt;
@@ -2267,14 +2272,14 @@ end_intr:
spin_lock(&port->slock);
}
-static void mxser_transmit_chars(struct mxser_port *port)
+static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
{
int count, cnt;
if (port->x_char) {
outb(port->x_char, port->ioaddr + UART_TX);
port->x_char = 0;
- mxvar_log.txcnt[port->port.tty->index]++;
+ mxvar_log.txcnt[tty->index]++;
port->mon_data.txcnt++;
port->mon_data.up_txcnt++;
port->icount.tx++;
@@ -2284,8 +2289,8 @@ static void mxser_transmit_chars(struct mxser_port *port)
if (port->port.xmit_buf == NULL)
return;
- if ((port->xmit_cnt <= 0) || port->port.tty->stopped ||
- (port->port.tty->hw_stopped &&
+ if (port->xmit_cnt <= 0 || tty->stopped ||
+ (tty->hw_stopped &&
(port->type != PORT_16550A) &&
(!port->board->chip_flag))) {
port->IER &= ~UART_IER_THRI;
@@ -2302,14 +2307,14 @@ static void mxser_transmit_chars(struct mxser_port *port)
if (--port->xmit_cnt <= 0)
break;
} while (--count > 0);
- mxvar_log.txcnt[port->port.tty->index] += (cnt - port->xmit_cnt);
+ mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
port->mon_data.txcnt += (cnt - port->xmit_cnt);
port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
port->icount.tx += (cnt - port->xmit_cnt);
- if (port->xmit_cnt < WAKEUP_CHARS)
- tty_wakeup(port->port.tty);
+ if (port->xmit_cnt < WAKEUP_CHARS && tty)
+ tty_wakeup(tty);
if (port->xmit_cnt <= 0) {
port->IER &= ~UART_IER_THRI;
@@ -2328,6 +2333,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
int max, irqbits, bits, msr;
unsigned int int_cnt, pass_counter = 0;
int handled = IRQ_NONE;
+ struct tty_struct *tty;
for (i = 0; i < MXSER_BOARDS; i++)
if (dev_id == &mxser_boards[i]) {
@@ -2360,13 +2366,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
if (iir & UART_IIR_NO_INT)
break;
iir &= MOXA_MUST_IIR_MASK;
- if (!port->port.tty ||
+ tty = tty_port_tty_get(&port->port);
+ if (!tty ||
(port->port.flags & ASYNC_CLOSING) ||
!(port->port.flags &
ASYNC_INITIALIZED)) {
status = inb(port->ioaddr + UART_LSR);
outb(0x27, port->ioaddr + UART_FCR);
inb(port->ioaddr + UART_MSR);
+ tty_kref_put(tty);
break;
}
@@ -2387,27 +2395,28 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
iir == MOXA_MUST_IIR_RDA ||
iir == MOXA_MUST_IIR_RTO ||
iir == MOXA_MUST_IIR_LSR)
- mxser_receive_chars(port,
+ mxser_receive_chars(tty, port,
&status);
} else {
status &= port->read_status_mask;
if (status & UART_LSR_DR)
- mxser_receive_chars(port,
+ mxser_receive_chars(tty, port,
&status);
}
msr = inb(port->ioaddr + UART_MSR);
if (msr & UART_MSR_ANY_DELTA)
- mxser_check_modem_status(port, msr);
+ mxser_check_modem_status(tty, port, msr);
if (port->board->chip_flag) {
if (iir == 0x02 && (status &
UART_LSR_THRE))
- mxser_transmit_chars(port);
+ mxser_transmit_chars(tty, port);
} else {
if (status & UART_LSR_THRE)
- mxser_transmit_chars(port);
+ mxser_transmit_chars(tty, port);
}
+ tty_kref_put(tty);
} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
spin_unlock(&port->slock);
}
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 69ec6399c71..bacb3e2872a 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -764,7 +764,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
break;
default:
- error = n_tty_ioctl (tty, file, cmd, arg);
+ error = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
}
return error;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index ae377aa473b..4a8215a89ad 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -372,14 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
static void put_char(struct r3964_info *pInfo, unsigned char ch)
{
struct tty_struct *tty = pInfo->tty;
-
- if (tty == NULL)
- return;
-
/* FIXME: put_char should not be called from an IRQ */
- if (tty->ops->put_char) {
- tty->ops->put_char(tty, ch);
- }
+ tty_put_char(tty, ch);
pInfo->bcc ^= ch;
}
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 708c2b1dbe5..efbfe961265 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -26,7 +26,7 @@
*
* 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to
* waiting writing processes-Sapan Bhatia <sapan@corewars.org>.
- * Also fixed a bug in BLOCKING mode where write_chan returns
+ * Also fixed a bug in BLOCKING mode where n_tty_write returns
* EAGAIN
*/
@@ -99,6 +99,7 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
static void n_tty_set_room(struct tty_struct *tty)
{
+ /* tty->read_cnt is not read locked ? */
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
/*
@@ -121,6 +122,16 @@ static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
}
}
+/**
+ * put_tty_queue - add character to tty
+ * @c: character
+ * @tty: tty device
+ *
+ * Add a character to the tty read_buf queue. This is done under the
+ * read_lock to serialize character addition and also to protect us
+ * against parallel reads or flushes
+ */
+
static void put_tty_queue(unsigned char c, struct tty_struct *tty)
{
unsigned long flags;
@@ -137,14 +148,11 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)
* check_unthrottle - allow new receive data
* @tty; tty device
*
- * Check whether to call the driver.unthrottle function.
- * We test the TTY_THROTTLED bit first so that it always
- * indicates the current state. The decision about whether
- * it is worth allowing more input has been taken by the caller.
+ * Check whether to call the driver unthrottle functions
+ *
* Can sleep, may be called under the atomic_read_lock mutex but
* this is not guaranteed.
*/
-
static void check_unthrottle(struct tty_struct *tty)
{
if (tty->count)
@@ -158,6 +166,8 @@ static void check_unthrottle(struct tty_struct *tty)
* Reset the read buffer counters, clear the flags,
* and make sure the driver is unthrottled. Called
* from n_tty_open() and n_tty_flush_buffer().
+ *
+ * Locking: tty_read_lock for read fields.
*/
static void reset_buffer_flags(struct tty_struct *tty)
{
@@ -181,7 +191,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
* at hangup) or when the N_TTY line discipline internally has to
* clean the pending queue (for example some signals).
*
- * Locking: ctrl_lock
+ * Locking: ctrl_lock, read_lock.
*/
static void n_tty_flush_buffer(struct tty_struct *tty)
@@ -207,6 +217,8 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
*
* Report the number of characters buffered to be delivered to user
* at this instant in time.
+ *
+ * Locking: read_lock
*/
static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
@@ -346,7 +358,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
* the simple cases normally found and helps to generate blocks of
* symbols for the console driver and thus improve performance.
*
- * Called from write_chan under the tty layer write lock. Relies
+ * Called from n_tty_write under the tty layer write lock. Relies
* on lock_kernel for the tty->column state.
*/
@@ -410,6 +422,8 @@ break_out:
*
* Echo user input back onto the screen. This must be called only when
* L_ECHO(tty) is true. Called from the driver receive_buf path.
+ *
+ * Relies on BKL for tty column locking
*/
static void echo_char(unsigned char c, struct tty_struct *tty)
@@ -422,6 +436,12 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
opost(c, tty);
}
+/**
+ * finsh_erasing - complete erase
+ * @tty: tty doing the erase
+ *
+ * Relies on BKL for tty column locking
+ */
static inline void finish_erasing(struct tty_struct *tty)
{
if (tty->erasing) {
@@ -439,6 +459,8 @@ static inline void finish_erasing(struct tty_struct *tty)
* Perform erase and necessary output when an erase character is
* present in the stream from the driver layer. Handles the complexities
* of UTF-8 multibyte symbols.
+ *
+ * Locking: read_lock for tty buffers, BKL for column/erasing state
*/
static void eraser(unsigned char c, struct tty_struct *tty)
@@ -447,6 +469,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
int head, seen_alnums, cnt;
unsigned long flags;
+ /* FIXME: locking needed ? */
if (tty->read_head == tty->canon_head) {
/* opost('\a', tty); */ /* what do you think? */
return;
@@ -481,6 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
}
seen_alnums = 0;
+ /* FIXME: Locking ?? */
while (tty->read_head != tty->canon_head) {
head = tty->read_head;
@@ -583,6 +607,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
* may caus terminal flushing to take place according to the termios
* settings and character used. Called from the driver receive_buf
* path so serialized.
+ *
+ * Locking: ctrl_lock, read_lock (both via flush buffer)
*/
static inline void isig(int sig, struct tty_struct *tty, int flush)
@@ -1007,12 +1033,26 @@ int is_ignored(int sig)
* and is protected from re-entry by the tty layer. The user is
* guaranteed that this function will not be re-entered or in progress
* when the ldisc is closed.
+ *
+ * Locking: Caller holds tty->termios_mutex
*/
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
- if (!tty)
- return;
+ int canon_change = 1;
+ BUG_ON(!tty);
+
+ if (old)
+ canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
+ if (canon_change) {
+ memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ tty->canon_head = tty->read_tail;
+ tty->canon_data = 0;
+ tty->erasing = 0;
+ }
+
+ if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+ wake_up_interruptible(&tty->read_wait);
tty->icanon = (L_ICANON(tty) != 0);
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
@@ -1143,7 +1183,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
* @b: user data
* @nr: size of data
*
- * Helper function to speed up read_chan. It is only called when
+ * Helper function to speed up n_tty_read. It is only called when
* ICANON is off; it copies characters straight from the tty queue to
* user space directly. It can be profitably called twice; once to
* drain the space from the tail pointer to the (physical) end of the
@@ -1210,7 +1250,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
if (file->f_op->write != redirected_tty_write &&
current->signal->tty == tty) {
if (!tty->pgrp)
- printk(KERN_ERR "read_chan: no tty->pgrp!\n");
+ printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) {
if (is_ignored(SIGTTIN) ||
is_current_pgrp_orphaned())
@@ -1225,7 +1265,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
/**
- * read_chan - read function for tty
+ * n_tty_read - read function for tty
* @tty: tty device
* @file: file object
* @buf: userspace buffer pointer
@@ -1239,7 +1279,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
* This code must be sure never to sleep through a hangup.
*/
-static ssize_t read_chan(struct tty_struct *tty, struct file *file,
+static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
unsigned char __user *b = buf;
@@ -1254,10 +1294,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
do_it_again:
- if (!tty->read_buf) {
- printk(KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n");
- return -EIO;
- }
+ BUG_ON(!tty->read_buf);
c = job_control(tty, file);
if (c < 0)
@@ -1444,7 +1481,7 @@ do_it_again:
}
/**
- * write_chan - write function for tty
+ * n_tty_write - write function for tty
* @tty: tty device
* @file: file object
* @buf: userspace buffer pointer
@@ -1458,7 +1495,7 @@ do_it_again:
* This code must be sure never to sleep through a hangup.
*/
-static ssize_t write_chan(struct tty_struct *tty, struct file *file,
+static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr)
{
const unsigned char *b = buf;
@@ -1532,7 +1569,7 @@ break_out:
}
/**
- * normal_poll - poll method for N_TTY
+ * n_tty_poll - poll method for N_TTY
* @tty: terminal device
* @file: file accessing it
* @wait: poll table
@@ -1545,7 +1582,7 @@ break_out:
* Called without the kernel lock held - fine
*/
-static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
+static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
poll_table *wait)
{
unsigned int mask = 0;
@@ -1573,6 +1610,44 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
return mask;
}
+static unsigned long inq_canon(struct tty_struct *tty)
+{
+ int nr, head, tail;
+
+ if (!tty->canon_data)
+ return 0;
+ head = tty->canon_head;
+ tail = tty->read_tail;
+ nr = (head - tail) & (N_TTY_BUF_SIZE-1);
+ /* Skip EOF-chars.. */
+ while (head != tail) {
+ if (test_bit(tail, tty->read_flags) &&
+ tty->read_buf[tail] == __DISABLED_CHAR)
+ nr--;
+ tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+ }
+ return nr;
+}
+
+static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int retval;
+
+ switch (cmd) {
+ case TIOCOUTQ:
+ return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
+ case TIOCINQ:
+ /* FIXME: Locking */
+ retval = tty->read_cnt;
+ if (L_ICANON(tty))
+ retval = inq_canon(tty);
+ return put_user(retval, (unsigned int __user *) arg);
+ default:
+ return n_tty_ioctl_helper(tty, file, cmd, arg);
+ }
+}
+
struct tty_ldisc_ops tty_ldisc_N_TTY = {
.magic = TTY_LDISC_MAGIC,
.name = "n_tty",
@@ -1580,11 +1655,11 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
.close = n_tty_close,
.flush_buffer = n_tty_flush_buffer,
.chars_in_buffer = n_tty_chars_in_buffer,
- .read = read_chan,
- .write = write_chan,
+ .read = n_tty_read,
+ .write = n_tty_write,
.ioctl = n_tty_ioctl,
.set_termios = n_tty_set_termios,
- .poll = normal_poll,
+ .poll = n_tty_poll,
.receive_buf = n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup
};
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 66a0f931c66..9a34a193528 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1599,7 +1599,10 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
return 0;
}
-/* Called when the userspace process close the tty, /dev/noz*. */
+/* Called when the userspace process close the tty, /dev/noz*. Also
+ called immediately if ntty_open fails in which case tty->driver_data
+ will be NULL an we exit by the first return */
+
static void ntty_close(struct tty_struct *tty, struct file *file)
{
struct nozomi *dc = get_dc_by_tty(tty);
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index f070ae7bd91..dbb91257456 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
/*==== Interface to PCMCIA Layer =======================================*/
+static int cm4000_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (!cfg->io.nwin)
+ return -ENODEV;
+
+ /* Get the IOaddr */
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ p_dev->io.NumPorts1 = cfg->io.win[0].len;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(cfg->io.flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(cfg->io.flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;
- tuple_t tuple;
- cisparse_t parse;
- u_char buf[64];
- int fail_fn, fail_rc;
- int rc;
/* read the config-tuples */
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
- link->io.BasePort2 = 0;
- link->io.NumPorts2 = 0;
- link->io.Attributes2 = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(link, &tuple);
- rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
-
- rc = pcmcia_get_tuple_data(link, &tuple);
- if (rc != CS_SUCCESS)
- continue;
- rc = pcmcia_parse_tuple(link, &tuple, &parse);
- if (rc != CS_SUCCESS)
- continue;
-
- link->conf.ConfigIndex = parse.cftable_entry.index;
-
- if (!parse.cftable_entry.io.nwin)
- continue;
-
- /* Get the IOaddr */
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = parse.cftable_entry.io.flags
- & CISTPL_IO_LINES_MASK;
-
- rc = pcmcia_request_io(link, &link->io);
- if (rc == CS_SUCCESS)
- break; /* we are done */
- }
- if (rc != CS_SUCCESS)
+ if (pcmcia_loop_config(link, cm4000_config_check, NULL))
goto cs_release;
link->conf.IntType = 00000002;
- if ((fail_rc =
- pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
- fail_fn = RequestConfiguration;
+ if (pcmcia_request_configuration(link, &link->conf))
goto cs_release;
- }
dev = link->priv;
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
@@ -1896,7 +1871,7 @@ static int cm4000_probe(struct pcmcia_device *link)
return ret;
}
- device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
+ device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 0b5934bef7a..4f0723b0797 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return;
}
-static int reader_config(struct pcmcia_device *link, int devno)
+static int cm4040_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- struct reader_dev *dev;
- tuple_t tuple;
- cisparse_t parse;
- u_char buf[64];
- int fail_fn, fail_rc;
int rc;
+ if (!cfg->io.nwin)
+ return -ENODEV;
+
+ /* Get the IOaddr */
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ p_dev->io.NumPorts1 = cfg->io.win[0].len;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(cfg->io.flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(cfg->io.flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+ rc = pcmcia_request_io(p_dev, &p_dev->io);
+ dev_printk(KERN_INFO, &handle_to_dev(p_dev),
+ "pcmcia_request_io returned 0x%x\n", rc);
+ return rc;
+}
+
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
+static int reader_config(struct pcmcia_device *link, int devno)
+{
+ struct reader_dev *dev;
+ int fail_rc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(link, &tuple);
- rc == CS_SUCCESS;
- rc = pcmcia_get_next_tuple(link, &tuple)) {
- rc = pcmcia_get_tuple_data(link, &tuple);
- if (rc != CS_SUCCESS)
- continue;
- rc = pcmcia_parse_tuple(link, &tuple, &parse);
- if (rc != CS_SUCCESS)
- continue;
-
- link->conf.ConfigIndex = parse.cftable_entry.index;
-
- if (!parse.cftable_entry.io.nwin)
- continue;
-
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = parse.cftable_entry.io.flags
- & CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(link, &link->io);
-
- dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
- if (rc == CS_SUCCESS)
- break;
- else
- dev_printk(KERN_INFO, &handle_to_dev(link),
- "pcmcia_request_io failed 0x%x\n", rc);
- }
- if (rc != CS_SUCCESS)
+
+ if (pcmcia_loop_config(link, cm4040_config_check, NULL))
goto cs_release;
link->conf.IntType = 00000002;
- if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
- !=CS_SUCCESS) {
- fail_fn = RequestConfiguration;
+ fail_rc = pcmcia_request_configuration(link, &link->conf);
+ if (fail_rc != 0) {
dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_configuration failed 0x%x\n",
fail_rc);
@@ -653,8 +637,7 @@ static int reader_probe(struct pcmcia_device *link)
return ret;
}
- device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
- "cmx%d", i);
+ device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 5eca7a99afe..5216fce0c62 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -65,9 +65,9 @@ static void signalled_reboot_work(struct work_struct *work_reboot)
struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
work_reboot);
struct pcmcia_device *link = ipw->link;
- int ret = pccard_reset_card(link->socket);
+ int ret = pcmcia_reset_card(link->socket);
- if (ret != CS_SUCCESS)
+ if (ret != 0)
cs_error(link, ResetCard, ret);
}
@@ -83,7 +83,6 @@ static int config_ipwireless(struct ipw_dev *ipw)
{
struct pcmcia_device *link = ipw->link;
int ret;
- config_info_t conf;
tuple_t tuple;
unsigned short buf[64];
cisparse_t parse;
@@ -105,7 +104,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
while (ret == 0) {
ret = pcmcia_get_tuple_data(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit0;
}
@@ -116,21 +115,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_get_first_tuple(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetFirstTuple, ret);
goto exit0;
}
ret = pcmcia_get_tuple_data(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit0;
}
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
+ ret = pcmcia_parse_tuple(&tuple, &parse);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, ParseTuple, ret);
goto exit0;
}
@@ -152,21 +151,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_get_first_tuple(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetFirstTuple, ret);
goto exit0;
}
ret = pcmcia_get_tuple_data(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit0;
}
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
+ ret = pcmcia_parse_tuple(&tuple, &parse);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit0;
}
@@ -181,7 +180,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_request_io(link, &link->io);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestIO, ret);
goto exit0;
}
@@ -195,21 +194,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_get_first_tuple(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetFirstTuple, ret);
goto exit1;
}
ret = pcmcia_get_tuple_data(link, &tuple);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit1;
}
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
+ ret = pcmcia_parse_tuple(&tuple, &parse);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, ParseTuple, ret);
goto exit1;
}
@@ -227,7 +226,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_request_window(&link, &ipw->request_common_memory,
&ipw->handle_common_memory);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestWindow, ret);
goto exit1;
}
@@ -239,7 +238,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_map_mem_page(ipw->handle_common_memory,
&memreq_common_memory);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, MapMemPage, ret);
goto exit1;
}
@@ -261,7 +260,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
&ipw->handle_attr_memory);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestWindow, ret);
goto exit2;
}
@@ -272,7 +271,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
&memreq_attr_memory);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, MapMemPage, ret);
goto exit2;
}
@@ -292,20 +291,11 @@ static int config_ipwireless(struct ipw_dev *ipw)
ret = pcmcia_request_irq(link, &link->irq);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestIRQ, ret);
goto exit3;
}
- /* Look up current Vcc */
-
- ret = pcmcia_get_configuration_info(link, &conf);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetConfigurationInfo, ret);
- goto exit4;
- }
-
printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
ipw->is_v2_card ? "V2/V3" : "V1");
printk(KERN_INFO IPWIRELESS_PCCARD_NAME
@@ -341,7 +331,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
*/
ret = pcmcia_request_configuration(link, &link->conf);
- if (ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestConfiguration, ret);
goto exit4;
}
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
index 3a23e7694d5..569f2f7743a 100644
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -276,6 +276,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)
struct ipw_tty *tty = linux_tty->driver_data;
int room;
+ /* FIXME: Exactly how is the tty object locked here .. */
if (!tty)
return -ENODEV;
@@ -397,6 +398,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set,
static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
{
struct ipw_tty *tty = linux_tty->driver_data;
+ /* FIXME: Exactly how is the tty object locked here .. */
if (!tty)
return -ENODEV;
@@ -412,6 +414,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct ipw_tty *tty = linux_tty->driver_data;
+ /* FIXME: Exactly how is the tty object locked here .. */
if (!tty)
return -ENODEV;
@@ -433,6 +436,8 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
if (!tty->open_count)
return -EINVAL;
+ /* FIXME: Exactly how is the tty object locked here .. */
+
switch (cmd) {
case TIOCGSERIAL:
return ipwireless_get_serial_info(tty, (void __user *) arg);
@@ -467,13 +472,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
}
return 0;
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(linux_tty, file, cmd, arg);
-
- case TCFLSH:
- return n_tty_ioctl(linux_tty, file, cmd, arg);
-
case FIONREAD:
{
int val = 0;
@@ -482,10 +480,11 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
return -EFAULT;
}
return 0;
+ case TCFLSH:
+ return tty_perform_flush(linux_tty, arg);
}
}
-
- return -ENOIOCTLCMD;
+ return tty_mode_ioctl(linux_tty, file, cmd , arg);
}
static int add_tty(dev_node_t *nodesp, int j,
@@ -588,6 +587,8 @@ void ipwireless_tty_free(struct ipw_tty *tty)
tty_hangup(ttyj->linux_tty);
/* Wait till the tty_hangup has completed */
flush_scheduled_work();
+ /* FIXME: Exactly how is the tty object locked here
+ against a parallel ioctl etc */
mutex_lock(&ttyj->ipw_tty_mutex);
}
while (ttyj->open_count)
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index c240562c218..9a626e50b79 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -601,7 +601,7 @@ static int mgslpc_config(struct pcmcia_device *link)
cfg = &(parse.cftable_entry);
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0)
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index bee39fdfba7..c84c34fb123 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -760,9 +760,8 @@ static const struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- device_create_drvdata(ppdev_class, port->dev,
- MKDEV(PP_MAJOR, port->number),
- NULL, "parport%d", port->number);
+ device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
+ NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 76b27932d22..6d4582712b1 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -8,10 +8,12 @@
* Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
* waiting writers -- Sapan Bhatia <sapan@corewars.org>
*
- *
+ * When reading this code see also fs/devpts. In particular note that the
+ * driver_data field is used by the devpts side as a binding to the devpts
+ * inode.
*/
-#include <linux/module.h> /* For EXPORT_SYMBOL */
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
@@ -23,26 +25,25 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <linux/devpts_fs.h>
+#include <asm/system.h>
+
/* These are global because they are accessed in tty_io.c */
#ifdef CONFIG_UNIX98_PTYS
struct tty_driver *ptm_driver;
static struct tty_driver *pts_driver;
#endif
-static void pty_close(struct tty_struct * tty, struct file * filp)
+static void pty_close(struct tty_struct *tty, struct file *filp)
{
- if (!tty)
- return;
- if (tty->driver->subtype == PTY_TYPE_MASTER) {
- if (tty->count > 1)
- printk("master pty_close: count = %d!!\n", tty->count);
- } else {
+ BUG_ON(!tty);
+ if (tty->driver->subtype == PTY_TYPE_MASTER)
+ WARN_ON(tty->count > 1);
+ else {
if (tty->count > 2)
return;
}
@@ -59,7 +60,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver)
- devpts_pty_kill(tty->index);
+ devpts_pty_kill(tty->link);
#endif
tty_vhangup(tty->link);
}
@@ -69,13 +70,13 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
* The unthrottle routine is called by the line discipline to signal
* that it can receive more characters. For PTY's, the TTY_THROTTLED
* flag is always set, to force the line discipline to always call the
- * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
+ * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
* characters in the queue. This is necessary since each time this
* happens, we need to wake up any sleeping processes that could be
* (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
* for the pty buffer to be drained.
*/
-static void pty_unthrottle(struct tty_struct * tty)
+static void pty_unthrottle(struct tty_struct *tty)
{
struct tty_struct *o_tty = tty->link;
@@ -87,7 +88,7 @@ static void pty_unthrottle(struct tty_struct * tty)
}
/*
- * WSH 05/24/97: modified to
+ * WSH 05/24/97: modified to
* (1) use space in tty->flip instead of a shared temp buffer
* The flip buffers aren't being used for a pty, so there's lots
* of space available. The buffer is protected by a per-pty
@@ -100,7 +101,8 @@ static void pty_unthrottle(struct tty_struct * tty)
* not our partners. We can't just take the other one blindly without
* risking deadlocks.
*/
-static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count)
+static int pty_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
{
struct tty_struct *to = tty->link;
int c;
@@ -112,7 +114,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun
if (c > count)
c = count;
to->ldisc.ops->receive_buf(to, buf, NULL, c);
-
+
return c;
}
@@ -128,17 +130,17 @@ static int pty_write_room(struct tty_struct *tty)
/*
* WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior
- * The chars_in_buffer() value is used by the ldisc select() function
+ * The chars_in_buffer() value is used by the ldisc select() function
* to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
* The pty driver chars_in_buffer() Master/Slave must behave differently:
*
* The Master side needs to allow typed-ahead commands to accumulate
* while being canonicalized, so we report "our buffer" as empty until
* some threshold is reached, and then report the count. (Any count >
- * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock
- * the count returned must be 0 if no canonical data is available to be
+ * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock
+ * the count returned must be 0 if no canonical data is available to be
* read. (The N_TTY ldisc.chars_in_buffer now knows this.)
- *
+ *
* The Slave side passes all characters in raw mode to the Master side's
* buffer where they can be read immediately, so in this case we can
* return the true count in the buffer.
@@ -155,21 +157,22 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
/* The ldisc must report 0 if no characters available to be read */
count = to->ldisc.ops->chars_in_buffer(to);
- if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
+ if (tty->driver->subtype == PTY_TYPE_SLAVE)
+ return count;
- /* Master side driver ... if the other side's read buffer is less than
+ /* Master side driver ... if the other side's read buffer is less than
* half full, return 0 to allow writers to proceed; otherwise return
- * the count. This leaves a comfortable margin to avoid overflow,
+ * the count. This leaves a comfortable margin to avoid overflow,
* and still allows half a buffer's worth of typed-ahead commands.
*/
- return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
+ return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
}
/* Set the lock flag on a pty */
-static int pty_set_lock(struct tty_struct *tty, int __user * arg)
+static int pty_set_lock(struct tty_struct *tty, int __user *arg)
{
int val;
- if (get_user(val,arg))
+ if (get_user(val, arg))
return -EFAULT;
if (val)
set_bit(TTY_PTY_LOCK, &tty->flags);
@@ -182,13 +185,13 @@ static void pty_flush_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
unsigned long flags;
-
+
if (!to)
return;
-
+
if (to->ldisc.ops->flush_buffer)
to->ldisc.ops->flush_buffer(to);
-
+
if (to->packet) {
spin_lock_irqsave(&tty->ctrl_lock, flags);
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
@@ -197,7 +200,7 @@ static void pty_flush_buffer(struct tty_struct *tty)
}
}
-static int pty_open(struct tty_struct *tty, struct file * filp)
+static int pty_open(struct tty_struct *tty, struct file *filp)
{
int retval = -ENODEV;
@@ -220,13 +223,65 @@ out:
return retval;
}
-static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+static void pty_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios)
+{
+ tty->termios->c_cflag &= ~(CSIZE | PARENB);
+ tty->termios->c_cflag |= (CS8 | CREAD);
+}
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{
- tty->termios->c_cflag &= ~(CSIZE | PARENB);
- tty->termios->c_cflag |= (CS8 | CREAD);
+ struct tty_struct *o_tty;
+ int idx = tty->index;
+ int retval;
+
+ o_tty = alloc_tty_struct();
+ if (!o_tty)
+ return -ENOMEM;
+ if (!try_module_get(driver->other->owner)) {
+ /* This cannot in fact currently happen */
+ free_tty_struct(o_tty);
+ return -ENOMEM;
+ }
+ initialize_tty_struct(o_tty, driver->other, idx);
+
+ /* We always use new tty termios data so we can do this
+ the easy way .. */
+ retval = tty_init_termios(tty);
+ if (retval)
+ goto free_mem_out;
+
+ retval = tty_init_termios(o_tty);
+ if (retval) {
+ tty_free_termios(tty);
+ goto free_mem_out;
+ }
+
+ /*
+ * Everything allocated ... set up the o_tty structure.
+ */
+ driver->other->ttys[idx] = o_tty;
+ tty_driver_kref_get(driver->other);
+ if (driver->subtype == PTY_TYPE_MASTER)
+ o_tty->count++;
+ /* Establish the links in both directions */
+ tty->link = o_tty;
+ o_tty->link = tty;
+
+ tty_driver_kref_get(driver);
+ tty->count++;
+ driver->ttys[idx] = tty;
+ return 0;
+free_mem_out:
+ module_put(o_tty->driver->owner);
+ free_tty_struct(o_tty);
+ return -ENOMEM;
}
+
static const struct tty_operations pty_ops = {
+ .install = pty_install,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -329,8 +384,11 @@ static inline void legacy_pty_init(void) { }
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
*/
int pty_limit = NR_UNIX98_PTY_DEFAULT;
-static int pty_limit_min = 0;
+static int pty_limit_min;
static int pty_limit_max = NR_UNIX98_PTY_MAX;
+static int pty_count;
+
+static struct cdev ptmx_cdev;
static struct ctl_table pty_table[] = {
{
@@ -348,6 +406,7 @@ static struct ctl_table pty_table[] = {
.procname = "nr",
.maxlen = sizeof(int),
.mode = 0444,
+ .data = &pty_count,
.proc_handler = &proc_dointvec,
}, {
.ctl_name = 0
@@ -388,7 +447,127 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
return -ENOIOCTLCMD;
}
+/**
+ * ptm_unix98_lookup - find a pty master
+ * @driver: ptm driver
+ * @idx: tty index
+ *
+ * Look up a pty master device. Called under the tty_mutex for now.
+ * This provides our locking.
+ */
+
+static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
+ struct inode *ptm_inode, int idx)
+{
+ struct tty_struct *tty = devpts_get_tty(ptm_inode, idx);
+ if (tty)
+ tty = tty->link;
+ return tty;
+}
+
+/**
+ * pts_unix98_lookup - find a pty slave
+ * @driver: pts driver
+ * @idx: tty index
+ *
+ * Look up a pty master device. Called under the tty_mutex for now.
+ * This provides our locking.
+ */
+
+static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
+ struct inode *pts_inode, int idx)
+{
+ struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
+ /* Master must be open before slave */
+ if (!tty)
+ return ERR_PTR(-EIO);
+ return tty;
+}
+
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+ /* We have our own method as we don't use the tty index */
+ kfree(tty->termios);
+}
+
+/* We have no need to install and remove our tty objects as devpts does all
+ the work for us */
+
+static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct tty_struct *o_tty;
+ int idx = tty->index;
+
+ o_tty = alloc_tty_struct();
+ if (!o_tty)
+ return -ENOMEM;
+ if (!try_module_get(driver->other->owner)) {
+ /* This cannot in fact currently happen */
+ free_tty_struct(o_tty);
+ return -ENOMEM;
+ }
+ initialize_tty_struct(o_tty, driver->other, idx);
+
+ tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (tty->termios == NULL)
+ goto free_mem_out;
+ *tty->termios = driver->init_termios;
+ tty->termios_locked = tty->termios + 1;
+
+ o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (o_tty->termios == NULL)
+ goto free_mem_out;
+ *o_tty->termios = driver->other->init_termios;
+ o_tty->termios_locked = o_tty->termios + 1;
+
+ tty_driver_kref_get(driver->other);
+ if (driver->subtype == PTY_TYPE_MASTER)
+ o_tty->count++;
+ /* Establish the links in both directions */
+ tty->link = o_tty;
+ o_tty->link = tty;
+ /*
+ * All structures have been allocated, so now we install them.
+ * Failures after this point use release_tty to clean up, so
+ * there's no need to null out the local pointers.
+ */
+ tty_driver_kref_get(driver);
+ tty->count++;
+ pty_count++;
+ return 0;
+free_mem_out:
+ kfree(o_tty->termios);
+ module_put(o_tty->driver->owner);
+ free_tty_struct(o_tty);
+ kfree(tty->termios);
+ return -ENOMEM;
+}
+
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+ pty_count--;
+}
+
+static const struct tty_operations ptm_unix98_ops = {
+ .lookup = ptm_unix98_lookup,
+ .install = pty_unix98_install,
+ .remove = pty_unix98_remove,
+ .open = pty_open,
+ .close = pty_close,
+ .write = pty_write,
+ .write_room = pty_write_room,
+ .flush_buffer = pty_flush_buffer,
+ .chars_in_buffer = pty_chars_in_buffer,
+ .unthrottle = pty_unthrottle,
+ .set_termios = pty_set_termios,
+ .ioctl = pty_unix98_ioctl,
+ .shutdown = pty_unix98_shutdown
+};
+
static const struct tty_operations pty_unix98_ops = {
+ .lookup = pts_unix98_lookup,
+ .install = pty_unix98_install,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -397,9 +576,73 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .ioctl = pty_unix98_ioctl
+ .shutdown = pty_unix98_shutdown
};
+/**
+ * ptmx_open - open a unix 98 pty master
+ * @inode: inode of device file
+ * @filp: file pointer to tty
+ *
+ * Allocate a unix98 pty master device from the ptmx driver.
+ *
+ * Locking: tty_mutex protects the init_dev work. tty->count should
+ * protect the rest.
+ * allocated_ptys_lock handles the list of free pty numbers
+ */
+
+static int __ptmx_open(struct inode *inode, struct file *filp)
+{
+ struct tty_struct *tty;
+ int retval;
+ int index;
+
+ nonseekable_open(inode, filp);
+
+ /* find a device that is not in use. */
+ index = devpts_new_index(inode);
+ if (index < 0)
+ return index;
+
+ mutex_lock(&tty_mutex);
+ tty = tty_init_dev(ptm_driver, index, 1);
+ mutex_unlock(&tty_mutex);
+
+ if (IS_ERR(tty)) {
+ retval = PTR_ERR(tty);
+ goto out;
+ }
+
+ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+ filp->private_data = tty;
+ file_move(filp, &tty->tty_files);
+
+ retval = devpts_pty_new(inode, tty->link);
+ if (retval)
+ goto out1;
+
+ retval = ptm_driver->ops->open(tty, filp);
+ if (!retval)
+ return 0;
+out1:
+ tty_release_dev(filp);
+ return retval;
+out:
+ devpts_kill_index(inode, index);
+ return retval;
+}
+
+static int ptmx_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+
+ lock_kernel();
+ ret = __ptmx_open(inode, filp);
+ unlock_kernel();
+ return ret;
+}
+
+static struct file_operations ptmx_fops;
static void __init unix98_pty_init(void)
{
@@ -427,7 +670,7 @@ static void __init unix98_pty_init(void)
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
ptm_driver->other = pts_driver;
- tty_set_operations(ptm_driver, &pty_unix98_ops);
+ tty_set_operations(ptm_driver, &ptm_unix98_ops);
pts_driver->owner = THIS_MODULE;
pts_driver->driver_name = "pty_slave";
@@ -443,16 +686,26 @@ static void __init unix98_pty_init(void)
pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
pts_driver->other = ptm_driver;
- tty_set_operations(pts_driver, &pty_ops);
-
+ tty_set_operations(pts_driver, &pty_unix98_ops);
+
if (tty_register_driver(ptm_driver))
panic("Couldn't register Unix98 ptm driver");
if (tty_register_driver(pts_driver))
panic("Couldn't register Unix98 pts driver");
- pty_table[1].data = &ptm_driver->refcount;
register_sysctl_table(pty_root_table);
+
+ /* Now create the /dev/ptmx special device */
+ tty_default_fops(&ptmx_fops);
+ ptmx_fops.open = ptmx_open;
+
+ cdev_init(&ptmx_cdev, &ptmx_fops);
+ if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
+ register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
+ panic("Couldn't register /dev/ptmx driver\n");
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
}
+
#else
static inline void unix98_pty_init(void) { }
#endif
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1838aa3d24f..c8752eaad48 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -407,7 +407,7 @@ struct entropy_store {
/* read-write data: */
spinlock_t lock;
unsigned add_ptr;
- int entropy_count;
+ int entropy_count; /* Must at no time exceed ->POOLBITS! */
int input_rotate;
};
@@ -520,6 +520,7 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
unsigned long flags;
+ int entropy_count;
if (!nbits)
return;
@@ -527,20 +528,20 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
spin_lock_irqsave(&r->lock, flags);
DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
- r->entropy_count += nbits;
- if (r->entropy_count < 0) {
+ entropy_count = r->entropy_count;
+ entropy_count += nbits;
+ if (entropy_count < 0) {
DEBUG_ENT("negative entropy/overflow\n");
- r->entropy_count = 0;
- } else if (r->entropy_count > r->poolinfo->POOLBITS)
- r->entropy_count = r->poolinfo->POOLBITS;
+ entropy_count = 0;
+ } else if (entropy_count > r->poolinfo->POOLBITS)
+ entropy_count = r->poolinfo->POOLBITS;
+ r->entropy_count = entropy_count;
/* should we wake readers? */
- if (r == &input_pool &&
- r->entropy_count >= random_read_wakeup_thresh) {
+ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
-
spin_unlock_irqrestore(&r->lock, flags);
}
@@ -660,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk)
if (!disk || !disk->random)
return;
/* first major is 1, so we get >= 0x200 here */
- DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor);
+ DEBUG_ENT("disk event %d:%d\n",
+ MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
- add_timer_randomness(disk->random,
- 0x100 + MKDEV(disk->major, disk->first_minor));
+ add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
}
#endif
@@ -1204,7 +1205,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos);
}
-static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
+static int uuid_strategy(ctl_table *table,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 47b8cf281d4..e139372d0e6 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
- NULL, "raw%d", rq->raw_minor);
+ device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
+ "raw%d", rq->raw_minor);
}
/*
@@ -283,8 +283,7 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class);
goto error_region;
}
- device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
- "rawctl");
+ device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
return 0;
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index f53d4d00faf..17683de9571 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -88,15 +88,15 @@
#endif
#ifdef CONFIG_SPARC32
-#include <linux/pci.h>
-#include <linux/jiffies.h>
-#include <asm/ebus.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <asm/io.h>
static unsigned long rtc_port;
-static int rtc_irq = PCI_IRQ_NONE;
+static int rtc_irq;
#endif
-#ifdef CONFIG_HPET_RTC_IRQ
+#ifdef CONFIG_HPET_EMULATE_RTC
#undef RTC_IRQ
#endif
@@ -973,8 +973,8 @@ static int __init rtc_init(void)
char *guess = NULL;
#endif
#ifdef CONFIG_SPARC32
- struct linux_ebus *ebus;
- struct linux_ebus_device *edev;
+ struct device_node *ebus_dp;
+ struct of_device *op;
#else
void *r;
#ifdef RTC_IRQ
@@ -983,12 +983,16 @@ static int __init rtc_init(void)
#endif
#ifdef CONFIG_SPARC32
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (strcmp(edev->prom_node->name, "rtc") == 0) {
- rtc_port = edev->resource[0].start;
- rtc_irq = edev->irqs[0];
- goto found;
+ for_each_node_by_name(ebus_dp, "ebus") {
+ struct device_node *dp;
+ for (dp = ebus_dp; dp; dp = dp->sibling) {
+ if (!strcmp(dp->name, "rtc")) {
+ op = of_find_device_by_node(dp);
+ if (op) {
+ rtc_port = op->resource[0].start;
+ rtc_irq = op->irqs[0];
+ goto found;
+ }
}
}
}
@@ -997,7 +1001,7 @@ static int __init rtc_init(void)
return -EIO;
found:
- if (rtc_irq == PCI_IRQ_NONE) {
+ if (!rtc_irq) {
rtc_has_irq = 0;
goto no_irq;
}
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 3ce60df14c0..32b74de18f5 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -444,8 +444,8 @@ scdrv_init(void)
continue;
}
- device_create_drvdata(snsc_class, NULL, dev, NULL,
- "%s", devname);
+ device_create(snsc_class, NULL, dev, NULL,
+ "%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
0 /*ignored */ ,
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 19db1eb87c2..963b03fb29e 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -405,9 +405,9 @@ static unsigned int stl_baudrates[] = {
static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
static int stl_brdinit(struct stlbrd *brdp);
-static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
+static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-static int stl_waitcarrier(struct stlport *portp, struct file *filp);
+static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
/*
* CD1400 uart specific handling functions.
@@ -612,8 +612,9 @@ static struct class *stallion_class;
static void stl_cd_change(struct stlport *portp)
{
unsigned int oldsigs = portp->sigs;
+ struct tty_struct *tty = tty_port_tty_get(&portp->port);
- if (!portp->port.tty)
+ if (!tty)
return;
portp->sigs = stl_getsignals(portp);
@@ -623,7 +624,8 @@ static void stl_cd_change(struct stlport *portp)
if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
if (portp->port.flags & ASYNC_CHECK_CD)
- tty_hangup(portp->port.tty);
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/*
@@ -734,7 +736,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
* On the first open of the device setup the port hardware, and
* initialize the per port data structure.
*/
- portp->port.tty = tty;
+ tty_port_tty_set(&portp->port, tty);
tty->driver_data = portp;
portp->port.count++;
@@ -774,7 +776,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
* then also we might have to wait for carrier.
*/
if (!(filp->f_flags & O_NONBLOCK))
- if ((rc = stl_waitcarrier(portp, filp)) != 0)
+ if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
return rc;
portp->port.flags |= ASYNC_NORMAL_ACTIVE;
@@ -789,7 +791,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
* maybe because if we are clocal then we don't need to wait...
*/
-static int stl_waitcarrier(struct stlport *portp, struct file *filp)
+static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
+ struct file *filp)
{
unsigned long flags;
int rc, doclocal;
@@ -801,7 +804,7 @@ static int stl_waitcarrier(struct stlport *portp, struct file *filp)
spin_lock_irqsave(&stallion_lock, flags);
- if (portp->port.tty->termios->c_cflag & CLOCAL)
+ if (tty->termios->c_cflag & CLOCAL)
doclocal++;
portp->openwaitcnt++;
@@ -846,8 +849,6 @@ static void stl_flushbuffer(struct tty_struct *tty)
pr_debug("stl_flushbuffer(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -865,8 +866,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -949,7 +948,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
tty_ldisc_flush(tty);
tty->closing = 0;
- portp->port.tty = NULL;
+ tty_port_tty_set(&portp->port, NULL);
if (portp->openwaitcnt) {
if (portp->close_delay)
@@ -1033,8 +1032,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch)
pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
- if (tty == NULL)
- return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
return -EINVAL;
@@ -1070,8 +1067,6 @@ static void stl_flushchars(struct tty_struct *tty)
pr_debug("stl_flushchars(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1090,8 +1085,6 @@ static int stl_writeroom(struct tty_struct *tty)
pr_debug("stl_writeroom(tty=%p)\n", tty);
- if (tty == NULL)
- return 0;
portp = tty->driver_data;
if (portp == NULL)
return 0;
@@ -1122,8 +1115,6 @@ static int stl_charsinbuffer(struct tty_struct *tty)
pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
- if (tty == NULL)
- return 0;
portp = tty->driver_data;
if (portp == NULL)
return 0;
@@ -1183,8 +1174,9 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
* just quietly ignore any requests to change irq, etc.
*/
-static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
+static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
{
+ struct stlport * portp = tty->driver_data;
struct serial_struct sio;
pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
@@ -1205,7 +1197,7 @@ static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
portp->close_delay = sio.close_delay;
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
- stl_setport(portp, portp->port.tty->termios);
+ stl_setport(portp, tty->termios);
return 0;
}
@@ -1215,8 +1207,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
{
struct stlport *portp;
- if (tty == NULL)
- return -ENODEV;
portp = tty->driver_data;
if (portp == NULL)
return -ENODEV;
@@ -1232,8 +1222,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
struct stlport *portp;
int rts = -1, dtr = -1;
- if (tty == NULL)
- return -ENODEV;
portp = tty->driver_data;
if (portp == NULL)
return -ENODEV;
@@ -1262,8 +1250,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
arg);
- if (tty == NULL)
- return -ENODEV;
portp = tty->driver_data;
if (portp == NULL)
return -ENODEV;
@@ -1282,10 +1268,10 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
rc = stl_getserial(portp, argp);
break;
case TIOCSSERIAL:
- rc = stl_setserial(portp, argp);
+ rc = stl_setserial(tty, argp);
break;
case COM_GETPORTSTATS:
- rc = stl_getportstats(portp, argp);
+ rc = stl_getportstats(tty, portp, argp);
break;
case COM_CLRPORTSTATS:
rc = stl_clrportstats(portp, argp);
@@ -1317,8 +1303,6 @@ static void stl_start(struct tty_struct *tty)
pr_debug("stl_start(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1334,8 +1318,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1369,8 +1351,6 @@ static void stl_throttle(struct tty_struct *tty)
pr_debug("stl_throttle(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1389,8 +1369,6 @@ static void stl_unthrottle(struct tty_struct *tty)
pr_debug("stl_unthrottle(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1410,8 +1388,6 @@ static void stl_stop(struct tty_struct *tty)
pr_debug("stl_stop(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1432,8 +1408,6 @@ static void stl_hangup(struct tty_struct *tty)
pr_debug("stl_hangup(tty=%p)\n", tty);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1452,7 +1426,7 @@ static void stl_hangup(struct tty_struct *tty)
portp->tx.head = NULL;
portp->tx.tail = NULL;
}
- portp->port.tty = NULL;
+ tty_port_tty_set(&portp->port, NULL);
portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
portp->port.count = 0;
wake_up_interruptible(&portp->port.open_wait);
@@ -1466,8 +1440,6 @@ static int stl_breakctl(struct tty_struct *tty, int state)
pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
- if (tty == NULL)
- return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
return -EINVAL;
@@ -1484,8 +1456,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
- if (tty == NULL)
- return;
portp = tty->driver_data;
if (portp == NULL)
return;
@@ -1805,7 +1775,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
"(size=%Zd)\n", sizeof(struct stlport));
break;
}
-
+ tty_port_init(&portp->port);
portp->magic = STL_PORTMAGIC;
portp->portnr = i;
portp->brdnr = panelp->brdnr;
@@ -1832,6 +1802,7 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
struct stlpanel *panelp;
struct stlport *portp;
unsigned int j, k;
+ struct tty_struct *tty;
for (j = 0; j < STL_MAXPANELS; j++) {
panelp = brdp->panels[j];
@@ -1841,8 +1812,11 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
portp = panelp->ports[k];
if (portp == NULL)
continue;
- if (portp->port.tty != NULL)
- stl_hangup(portp->port.tty);
+ tty = tty_port_tty_get(&portp->port);
+ if (tty != NULL) {
+ stl_hangup(tty);
+ tty_kref_put(tty);
+ }
kfree(portp->tx.buf);
kfree(portp);
}
@@ -2498,7 +2472,7 @@ static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
* what port to get stats for (used through board control device).
*/
-static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
+static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
{
comstats_t stl_comstats;
unsigned char *head, *tail;
@@ -2525,18 +2499,17 @@ static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
portp->stats.rxbuffered = 0;
spin_lock_irqsave(&stallion_lock, flags);
- if (portp->port.tty != NULL)
- if (portp->port.tty->driver_data == portp) {
- portp->stats.ttystate = portp->port.tty->flags;
- /* No longer available as a statistic */
- portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
- if (portp->port.tty->termios != NULL) {
- portp->stats.cflags = portp->port.tty->termios->c_cflag;
- portp->stats.iflags = portp->port.tty->termios->c_iflag;
- portp->stats.oflags = portp->port.tty->termios->c_oflag;
- portp->stats.lflags = portp->port.tty->termios->c_lflag;
- }
+ if (tty != NULL && portp->port.tty == tty) {
+ portp->stats.ttystate = tty->flags;
+ /* No longer available as a statistic */
+ portp->stats.rxbuffered = 1; /*tty->flip.count; */
+ if (tty->termios != NULL) {
+ portp->stats.cflags = tty->termios->c_cflag;
+ portp->stats.iflags = tty->termios->c_iflag;
+ portp->stats.oflags = tty->termios->c_oflag;
+ portp->stats.lflags = tty->termios->c_lflag;
}
+ }
spin_unlock_irqrestore(&stallion_lock, flags);
head = portp->tx.head;
@@ -2640,7 +2613,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
switch (cmd) {
case COM_GETPORTSTATS:
- rc = stl_getportstats(NULL, argp);
+ rc = stl_getportstats(NULL, NULL, argp);
break;
case COM_CLRPORTSTATS:
rc = stl_clrportstats(NULL, argp);
@@ -3243,7 +3216,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
if (portp == NULL)
return;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (tty == NULL)
return;
@@ -3288,6 +3261,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -3305,7 +3279,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
if (portp == NULL)
return;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (tty == NULL)
return;
@@ -3325,6 +3299,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
}
BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -3478,6 +3453,7 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
int len, stlen;
char *head, *tail;
unsigned char ioack, srer;
+ struct tty_struct *tty;
pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
@@ -3504,8 +3480,11 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- if (portp->port.tty)
- tty_wakeup(portp->port.tty);
+ tty = tty_port_tty_get(&portp->port);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
}
if (len == 0) {
@@ -3569,7 +3548,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
return;
}
portp = panelp->ports[(ioack >> 3)];
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
outb((RDCR + portp->uartaddr), ioaddr);
@@ -3633,10 +3612,12 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
}
} else {
printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
+ tty_kref_put(tty);
return;
}
stl_rxalldone:
+ tty_kref_put(tty);
outb((EOSRR + portp->uartaddr), ioaddr);
outb(0, (ioaddr + EREG_DATA));
}
@@ -4175,7 +4156,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
if (portp == NULL)
return;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (tty == NULL)
return;
@@ -4226,6 +4207,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -4244,7 +4226,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
if (portp == NULL)
return;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
if (tty == NULL)
return;
@@ -4269,6 +4251,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
}
BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -4408,6 +4391,7 @@ static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
static void stl_sc26198txisr(struct stlport *portp)
{
+ struct tty_struct *tty;
unsigned int ioaddr;
unsigned char mr0;
int len, stlen;
@@ -4422,8 +4406,11 @@ static void stl_sc26198txisr(struct stlport *portp)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- if (portp->port.tty)
- tty_wakeup(portp->port.tty);
+ tty = tty_port_tty_get(&portp->port);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
}
if (len == 0) {
@@ -4476,7 +4463,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
ioaddr = portp->ioaddr;
outb(GIBCR, (ioaddr + XP_ADDR));
len = inb(ioaddr + XP_DATA) + 1;
@@ -4515,6 +4502,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
stl_sc26198txunflow(portp, tty);
}
}
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -4528,7 +4516,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
struct tty_struct *tty;
unsigned int ioaddr;
- tty = portp->port.tty;
+ tty = tty_port_tty_get(&portp->port);
ioaddr = portp->ioaddr;
if (status & SR_RXPARITY)
@@ -4566,6 +4554,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
if (status == 0)
portp->stats.rxtotal++;
}
+ tty_kref_put(tty);
}
/*****************************************************************************/
@@ -4754,8 +4743,8 @@ static int __init stallion_module_init(void)
if (IS_ERR(stallion_class))
printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
- device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
- NULL, "staliomem%d", i);
+ device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_unrtty:
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index c385206f9db..5b8d7a1aa3e 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,
del_timer(&board->timer);
if (pdev) {
#ifdef CONFIG_PCI
- pci_iounmap(pdev, board->base);
+ pci_iounmap(pdev, board->base2);
pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
#endif
} else {
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
return 0;
err_unmap:
- pci_iounmap(pdev, board->base);
+ pci_iounmap(pdev, board->base2);
err_reg:
pci_release_region(pdev, reg);
err_flag:
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 8fdfe9c871e..dce4cc0e695 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -23,6 +23,7 @@
#include <linux/reboot.h>
#include <linux/sysrq.h>
#include <linux/kbd_kern.h>
+#include <linux/proc_fs.h>
#include <linux/quotaops.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -326,6 +327,7 @@ static struct sysrq_key_op sysrq_moom_op = {
.handler = sysrq_handle_moom,
.help_msg = "Full",
.action_msg = "Manual OOM execution",
+ .enable_mask = SYSRQ_ENABLE_SIGNAL,
};
static void sysrq_handle_kill(int key, struct tty_struct *tty)
@@ -533,3 +535,32 @@ int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
return __sysrq_swap_key_ops(key, NULL, op_p);
}
EXPORT_SYMBOL(unregister_sysrq_key);
+
+#ifdef CONFIG_PROC_FS
+/*
+ * writing 'C' to /proc/sysrq-trigger is like sysrq-C
+ */
+static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ char c;
+
+ if (get_user(c, buf))
+ return -EFAULT;
+ __handle_sysrq(c, NULL, 0);
+ }
+ return count;
+}
+
+static const struct file_operations proc_sysrq_trigger_operations = {
+ .write = write_sysrq_trigger,
+};
+
+static int __init sysrq_init(void)
+{
+ proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
+ return 0;
+}
+module_init(sysrq_init);
+#endif
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 3738cfa209f..f5fc64f89c5 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -6,6 +6,7 @@ menuconfig TCG_TPM
tristate "TPM Hardware Support"
depends on HAS_IOMEM
depends on EXPERIMENTAL
+ select SECURITYFS
---help---
If you have a TPM security chip in your system, which
implements the Trusted Computing Group's specification,
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index ae766d86845..e70d13defde 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -525,19 +525,19 @@ void tpm_get_timeouts(struct tpm_chip *chip)
timeout =
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
if (timeout)
- chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ chip->vendor.timeout_a = usecs_to_jiffies(timeout);
timeout =
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
if (timeout)
- chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ chip->vendor.timeout_b = usecs_to_jiffies(timeout);
timeout =
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
if (timeout)
- chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ chip->vendor.timeout_c = usecs_to_jiffies(timeout);
timeout =
be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
if (timeout)
- chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+ chip->vendor.timeout_d = usecs_to_jiffies(timeout);
duration:
memcpy(data, tpm_cap, sizeof(tpm_cap));
@@ -554,15 +554,22 @@ duration:
return;
chip->vendor.duration[TPM_SHORT] =
- msecs_to_jiffies(be32_to_cpu
+ usecs_to_jiffies(be32_to_cpu
(*((__be32 *) (data +
TPM_GET_CAP_RET_UINT32_1_IDX))));
+ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
+ * value wrong and apparently reports msecs rather than usecs. So we
+ * fix up the resulting too-small TPM_SHORT value to make things work.
+ */
+ if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
+ chip->vendor.duration[TPM_SHORT] = HZ;
+
chip->vendor.duration[TPM_MEDIUM] =
- msecs_to_jiffies(be32_to_cpu
+ usecs_to_jiffies(be32_to_cpu
(*((__be32 *) (data +
TPM_GET_CAP_RET_UINT32_2_IDX))));
chip->vendor.duration[TPM_LONG] =
- msecs_to_jiffies(be32_to_cpu
+ usecs_to_jiffies(be32_to_cpu
(*((__be32 *) (data +
TPM_GET_CAP_RET_UINT32_3_IDX))));
}
@@ -954,72 +961,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel);
/*
* Device file system interface to the TPM
+ *
+ * It's assured that the chip will be opened just once,
+ * by the check of is_open variable, which is protected
+ * by driver_lock.
*/
int tpm_open(struct inode *inode, struct file *file)
{
- int rc = 0, minor = iminor(inode);
+ int minor = iminor(inode);
struct tpm_chip *chip = NULL, *pos;
- lock_kernel();
- spin_lock(&driver_lock);
-
- list_for_each_entry(pos, &tpm_chip_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
if (pos->vendor.miscdev.minor == minor) {
chip = pos;
+ get_device(chip->dev);
break;
}
}
+ rcu_read_unlock();
- if (chip == NULL) {
- rc = -ENODEV;
- goto err_out;
- }
+ if (!chip)
+ return -ENODEV;
- if (chip->num_opens) {
+ if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->dev, "Another process owns this TPM\n");
- rc = -EBUSY;
- goto err_out;
+ put_device(chip->dev);
+ return -EBUSY;
}
- chip->num_opens++;
- get_device(chip->dev);
-
- spin_unlock(&driver_lock);
-
chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
if (chip->data_buffer == NULL) {
- chip->num_opens--;
+ clear_bit(0, &chip->is_open);
put_device(chip->dev);
- unlock_kernel();
return -ENOMEM;
}
atomic_set(&chip->data_pending, 0);
file->private_data = chip;
- unlock_kernel();
return 0;
-
-err_out:
- spin_unlock(&driver_lock);
- unlock_kernel();
- return rc;
}
EXPORT_SYMBOL_GPL(tpm_open);
+/*
+ * Called on file close
+ */
int tpm_release(struct inode *inode, struct file *file)
{
struct tpm_chip *chip = file->private_data;
+ del_singleshot_timer_sync(&chip->user_read_timer);
flush_scheduled_work();
- spin_lock(&driver_lock);
file->private_data = NULL;
- del_singleshot_timer_sync(&chip->user_read_timer);
atomic_set(&chip->data_pending, 0);
- chip->num_opens--;
- put_device(chip->dev);
kfree(chip->data_buffer);
- spin_unlock(&driver_lock);
+ clear_bit(0, &chip->is_open);
+ put_device(chip->dev);
return 0;
}
EXPORT_SYMBOL_GPL(tpm_release);
@@ -1093,13 +1091,11 @@ void tpm_remove_hardware(struct device *dev)
}
spin_lock(&driver_lock);
-
- list_del(&chip->list);
-
+ list_del_rcu(&chip->list);
spin_unlock(&driver_lock);
+ synchronize_rcu();
misc_deregister(&chip->vendor.miscdev);
-
sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
@@ -1144,25 +1140,33 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);
+/* In case vendor provided release function, call it too.*/
+
+void tpm_dev_vendor_release(struct tpm_chip *chip)
+{
+ if (chip->vendor.release)
+ chip->vendor.release(chip->dev);
+
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip->vendor.miscdev.name);
+}
+EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
+
+
/*
* Once all references to platform device are down to 0,
* release all allocated structures.
- * In case vendor provided release function,
- * call it too.
*/
static void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
- if (chip->vendor.release)
- chip->vendor.release(dev);
+ tpm_dev_vendor_release(chip);
chip->release(dev);
-
- clear_bit(chip->dev_num, dev_mask);
- kfree(chip->vendor.miscdev.name);
kfree(chip);
}
+EXPORT_SYMBOL_GPL(tpm_dev_release);
/*
* Called from tpm_<specific>.c probe function only for devices
@@ -1171,8 +1175,8 @@ static void tpm_dev_release(struct device *dev)
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
- *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev,
+ const struct tpm_vendor_specific *entry)
{
#define DEVNAME_SIZE 7
@@ -1183,11 +1187,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
- if (chip == NULL || devname == NULL) {
- kfree(chip);
- kfree(devname);
- return NULL;
- }
+ if (chip == NULL || devname == NULL)
+ goto out_free;
mutex_init(&chip->buffer_mutex);
mutex_init(&chip->tpm_mutex);
@@ -1204,8 +1205,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
- kfree(chip);
- return NULL;
+ goto out_free;
} else if (chip->dev_num == 0)
chip->vendor.miscdev.minor = TPM_MINOR;
else
@@ -1231,22 +1231,26 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
return NULL;
}
- spin_lock(&driver_lock);
-
- list_add(&chip->list, &tpm_chip_list);
-
- spin_unlock(&driver_lock);
-
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
- list_del(&chip->list);
misc_deregister(&chip->vendor.miscdev);
put_device(chip->dev);
+
return NULL;
}
chip->bios_dir = tpm_bios_log_setup(devname);
+ /* Make chip available */
+ spin_lock(&driver_lock);
+ list_add_rcu(&chip->list, &tpm_chip_list);
+ spin_unlock(&driver_lock);
+
return chip;
+
+out_free:
+ kfree(chip);
+ kfree(devname);
+ return NULL;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e885148b4cf..8e30df4a438 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -90,7 +90,7 @@ struct tpm_chip {
struct device *dev; /* Device stuff */
int dev_num; /* /dev/tpm# */
- int num_opens; /* only one allowed */
+ unsigned long is_open; /* only one allowed */
int time_expired;
/* Data passed to and from the tpm via the read/write calls */
@@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
+extern void tpm_dev_vendor_release(struct tpm_chip *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
loff_t *);
extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index ed1879c0dd8..717af7ad1bd 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
{"", 0} /* Terminator */
};
+static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
+{
+ struct tpm_chip *chip = pnp_get_drvdata(dev);
+
+ tpm_dev_vendor_release(chip);
+
+ kfree(chip);
+}
+
+
static struct pnp_driver tis_pnp_driver = {
.name = "tpm_tis",
.id_table = tpm_pnp_tbl,
.probe = tpm_tis_pnp_init,
.suspend = tpm_tis_pnp_suspend,
.resume = tpm_tis_pnp_resume,
+ .remove = tpm_tis_pnp_remove,
};
#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
@@ -683,6 +694,7 @@ static void __exit cleanup_tis(void)
spin_lock(&tis_lock);
list_for_each_entry_safe(i, j, &tis_chips, list) {
chip = to_tpm_chip(i);
+ tpm_remove_hardware(chip->dev);
iowrite32(~TPM_GLOBAL_INT_ENABLE &
ioread32(chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.
@@ -694,9 +706,9 @@ static void __exit cleanup_tis(void)
free_irq(chip->vendor.irq, chip);
iounmap(i->iobase);
list_del(&i->list);
- tpm_remove_hardware(chip->dev);
}
spin_unlock(&tis_lock);
+
if (force) {
platform_device_unregister(pdev);
driver_unregister(&tis_drv);
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index 3582f43345a..5787249934c 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -93,7 +93,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
get_task_comm(name, tsk);
audit_log_untrustedstring(ab, name);
audit_log_format(ab, " data=");
- audit_log_n_untrustedstring(ab, buf->data, buf->valid);
+ audit_log_n_hex(ab, buf->data, buf->valid);
audit_log_end(ab);
}
buf->valid = 0;
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
new file mode 100644
index 00000000000..810ee25d66a
--- /dev/null
+++ b/drivers/char/tty_buffer.c
@@ -0,0 +1,511 @@
+/*
+ * Tty buffer allocation management
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
+void tty_buffer_free_all(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ while ((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ kfree(thead);
+ }
+ while ((thead = tty->buf.free) != NULL) {
+ tty->buf.free = thead->next;
+ kfree(thead);
+ }
+ tty->buf.tail = NULL;
+ tty->buf.memory_used = 0;
+}
+
+/**
+ * tty_buffer_alloc - allocate a tty buffer
+ * @tty: tty device
+ * @size: desired size (characters)
+ *
+ * Allocate a new tty buffer to hold the desired number of characters.
+ * Return NULL if out of memory or the allocation would exceed the
+ * per device queue
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *p;
+
+ if (tty->buf.memory_used + size > 65536)
+ return NULL;
+ p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ if (p == NULL)
+ return NULL;
+ p->used = 0;
+ p->size = size;
+ p->next = NULL;
+ p->commit = 0;
+ p->read = 0;
+ p->char_buf_ptr = (char *)(p->data);
+ p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+ tty->buf.memory_used += size;
+ return p;
+}
+
+/**
+ * tty_buffer_free - free a tty buffer
+ * @tty: tty owning the buffer
+ * @b: the buffer to free
+ *
+ * Free a tty buffer, or add it to the free list according to our
+ * internal strategy
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+ /* Dumb strategy for now - should keep some stats */
+ tty->buf.memory_used -= b->size;
+ WARN_ON(tty->buf.memory_used < 0);
+
+ if (b->size >= 512)
+ kfree(b);
+ else {
+ b->next = tty->buf.free;
+ tty->buf.free = b;
+ }
+}
+
+/**
+ * __tty_buffer_flush - flush full tty buffers
+ * @tty: tty to flush
+ *
+ * flush all the buffers containing receive data. Caller must
+ * hold the buffer lock and must have ensured no parallel flush to
+ * ldisc is running.
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static void __tty_buffer_flush(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+
+ while ((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ tty_buffer_free(tty, thead);
+ }
+ tty->buf.tail = NULL;
+}
+
+/**
+ * tty_buffer_flush - flush full tty buffers
+ * @tty: tty to flush
+ *
+ * flush all the buffers containing receive data. If the buffer is
+ * being processed by flush_to_ldisc then we defer the processing
+ * to that function
+ *
+ * Locking: none
+ */
+
+void tty_buffer_flush(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+
+ /* If the data is being pushed to the tty layer then we can't
+ process it here. Instead set a flag and the flush_to_ldisc
+ path will process the flush request before it exits */
+ if (test_bit(TTY_FLUSHING, &tty->flags)) {
+ set_bit(TTY_FLUSHPENDING, &tty->flags);
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ wait_event(tty->read_wait,
+ test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+ return;
+ } else
+ __tty_buffer_flush(tty);
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+}
+
+/**
+ * tty_buffer_find - find a free tty buffer
+ * @tty: tty owning the buffer
+ * @size: characters wanted
+ *
+ * Locate an existing suitable tty buffer or if we are lacking one then
+ * allocate a new one. We round our buffers off in 256 character chunks
+ * to get better allocation behaviour.
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer **tbh = &tty->buf.free;
+ while ((*tbh) != NULL) {
+ struct tty_buffer *t = *tbh;
+ if (t->size >= size) {
+ *tbh = t->next;
+ t->next = NULL;
+ t->used = 0;
+ t->commit = 0;
+ t->read = 0;
+ tty->buf.memory_used += t->size;
+ return t;
+ }
+ tbh = &((*tbh)->next);
+ }
+ /* Round the buffer size out */
+ size = (size + 0xFF) & ~0xFF;
+ return tty_buffer_alloc(tty, size);
+ /* Should possibly check if this fails for the largest buffer we
+ have queued and recycle that ? */
+}
+
+/**
+ * tty_buffer_request_room - grow tty buffer if needed
+ * @tty: tty structure
+ * @size: size desired
+ *
+ * Make at least size bytes of linear space available for the tty
+ * buffer. If we fail return the size we managed to find.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *b, *n;
+ int left;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+
+ /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ remove this conditional if its worth it. This would be invisible
+ to the callers */
+ if ((b = tty->buf.tail) != NULL)
+ left = b->size - b->used;
+ else
+ left = 0;
+
+ if (left < size) {
+ /* This is the slow path - looking for new buffers to use */
+ if ((n = tty_buffer_find(tty, size)) != NULL) {
+ if (b != NULL) {
+ b->next = n;
+ b->commit = b->used;
+ } else
+ tty->buf.head = n;
+ tty->buf.tail = n;
+ } else
+ size = left;
+ }
+
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ return size;
+}
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+/**
+ * tty_insert_flip_string - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. All the characters
+ * passed are marked as without error. Returns the number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+ size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if (unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ } while (unlikely(size > copied));
+ return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string);
+
+/**
+ * tty_insert_flip_string_flags - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @flags: flag bytes
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. For each character
+ * the flags array indicates the status of the character. Returns the
+ * number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+ const unsigned char *chars, const char *flags, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if (unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ flags += space;
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ } while (unlikely(size > copied));
+ return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string_flags);
+
+/**
+ * tty_schedule_flip - push characters to ldisc
+ * @tty: tty to push from
+ *
+ * Takes any pending buffers and transfers their ownership to the
+ * ldisc side of the queue. It then schedules those characters for
+ * processing by the line discipline.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+
+void tty_schedule_flip(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL)
+ tty->buf.tail->commit = tty->buf.tail->used;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
+
+/**
+ * tty_prepare_flip_string - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @size: desired size
+ *
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for normal characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
+ size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ }
+ return space;
+}
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/**
+ * tty_prepare_flip_string_flags - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @flags: return pointer for status flag write area
+ * @size: desired size
+ *
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty,
+ unsigned char **chars, char **flags, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ *flags = tb->flag_buf_ptr + tb->used;
+ tb->used += space;
+ }
+ return space;
+}
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/**
+ * flush_to_ldisc
+ * @work: tty structure passed from work queue.
+ *
+ * This routine is called out of the software interrupt to flush data
+ * from the buffer chain to the line discipline.
+ *
+ * Locking: holds tty->buf.lock to guard buffer list. Drops the lock
+ * while invoking the line discipline receive_buf method. The
+ * receive_buf method is single threaded for each tty instance.
+ */
+
+static void flush_to_ldisc(struct work_struct *work)
+{
+ struct tty_struct *tty =
+ container_of(work, struct tty_struct, buf.work.work);
+ unsigned long flags;
+ struct tty_ldisc *disc;
+ struct tty_buffer *tbuf, *head;
+ char *char_buf;
+ unsigned char *flag_buf;
+
+ disc = tty_ldisc_ref(tty);
+ if (disc == NULL) /* !TTY_LDISC */
+ return;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ /* So we know a flush is running */
+ set_bit(TTY_FLUSHING, &tty->flags);
+ head = tty->buf.head;
+ if (head != NULL) {
+ tty->buf.head = NULL;
+ for (;;) {
+ int count = head->commit - head->read;
+ if (!count) {
+ if (head->next == NULL)
+ break;
+ tbuf = head;
+ head = head->next;
+ tty_buffer_free(tty, tbuf);
+ continue;
+ }
+ /* Ldisc or user is trying to flush the buffers
+ we are feeding to the ldisc, stop feeding the
+ line discipline as we want to empty the queue */
+ if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+ break;
+ if (!tty->receive_room) {
+ schedule_delayed_work(&tty->buf.work, 1);
+ break;
+ }
+ if (count > tty->receive_room)
+ count = tty->receive_room;
+ char_buf = head->char_buf_ptr + head->read;
+ flag_buf = head->flag_buf_ptr + head->read;
+ head->read += count;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ disc->ops->receive_buf(tty, char_buf,
+ flag_buf, count);
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ }
+ /* Restore the queue head */
+ tty->buf.head = head;
+ }
+ /* We may have a deferred request to flush the input buffer,
+ if so pull the chain under the lock and empty the queue */
+ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
+ __tty_buffer_flush(tty);
+ clear_bit(TTY_FLUSHPENDING, &tty->flags);
+ wake_up(&tty->read_wait);
+ }
+ clear_bit(TTY_FLUSHING, &tty->flags);
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+ tty_ldisc_deref(disc);
+}
+
+/**
+ * tty_flip_buffer_push - terminal
+ * @tty: tty to push
+ *
+ * Queue a push of the terminal flip buffers to the line discipline. This
+ * function must not be called from IRQ context if tty->low_latency is set.
+ *
+ * In the event of the queue being busy for flipping the work will be
+ * held off and retried later.
+ *
+ * Locking: tty buffer lock. Driver locks in low latency mode.
+ */
+
+void tty_flip_buffer_push(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL)
+ tty->buf.tail->commit = tty->buf.tail->used;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+ if (tty->low_latency)
+ flush_to_ldisc(&tty->buf.work.work);
+ else
+ schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_flip_buffer_push);
+
+/**
+ * tty_buffer_init - prepare a tty buffer structure
+ * @tty: tty to initialise
+ *
+ * Set up the initial state of the buffer management for a tty device.
+ * Must be called before the other tty buffer functions are used.
+ *
+ * Locking: none
+ */
+
+void tty_buffer_init(struct tty_struct *tty)
+{
+ spin_lock_init(&tty->buf.lock);
+ tty->buf.head = NULL;
+ tty->buf.tail = NULL;
+ tty->buf.free = NULL;
+ tty->buf.memory_used = 0;
+ INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
+}
+
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index daeb8f76697..59f472143f0 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -49,7 +49,7 @@
* implement CONFIG_VT and generalize console device interface.
* -- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
*
- * Rewrote init_dev and release_dev to eliminate races.
+ * Rewrote tty_init_dev and tty_release_dev to eliminate races.
* -- Bill Hawes <whawes@star.net>, June 97
*
* Added devfs support.
@@ -136,13 +136,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);
-#ifdef CONFIG_UNIX98_PTYS
-extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
-static int ptmx_open(struct inode *, struct file *);
-#endif
-
-static void initialize_tty_struct(struct tty_struct *tty);
-
static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -171,13 +164,11 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
* Locking: none
*/
-static struct tty_struct *alloc_tty_struct(void)
+struct tty_struct *alloc_tty_struct(void)
{
return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
}
-static void tty_buffer_free_all(struct tty_struct *);
-
/**
* free_tty_struct - free a disused tty
* @tty: tty struct to free
@@ -187,7 +178,7 @@ static void tty_buffer_free_all(struct tty_struct *);
* Locking: none. Must be called after tty is definitely unused
*/
-static inline void free_tty_struct(struct tty_struct *tty)
+void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
tty_buffer_free_all(tty);
@@ -263,398 +254,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
return 0;
}
-/*
- * Tty buffer allocation management
- */
-
-/**
- * tty_buffer_free_all - free buffers used by a tty
- * @tty: tty to free from
- *
- * Remove all the buffers pending on a tty whether queued with data
- * or in the free ring. Must be called when the tty is no longer in use
- *
- * Locking: none
- */
-
-static void tty_buffer_free_all(struct tty_struct *tty)
-{
- struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- kfree(thead);
- }
- while ((thead = tty->buf.free) != NULL) {
- tty->buf.free = thead->next;
- kfree(thead);
- }
- tty->buf.tail = NULL;
- tty->buf.memory_used = 0;
-}
-
-/**
- * tty_buffer_init - prepare a tty buffer structure
- * @tty: tty to initialise
- *
- * Set up the initial state of the buffer management for a tty device.
- * Must be called before the other tty buffer functions are used.
- *
- * Locking: none
- */
-
-static void tty_buffer_init(struct tty_struct *tty)
-{
- spin_lock_init(&tty->buf.lock);
- tty->buf.head = NULL;
- tty->buf.tail = NULL;
- tty->buf.free = NULL;
- tty->buf.memory_used = 0;
-}
-
-/**
- * tty_buffer_alloc - allocate a tty buffer
- * @tty: tty device
- * @size: desired size (characters)
- *
- * Allocate a new tty buffer to hold the desired number of characters.
- * Return NULL if out of memory or the allocation would exceed the
- * per device queue
- *
- * Locking: Caller must hold tty->buf.lock
- */
-
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
-{
- struct tty_buffer *p;
-
- if (tty->buf.memory_used + size > 65536)
- return NULL;
- p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
- if (p == NULL)
- return NULL;
- p->used = 0;
- p->size = size;
- p->next = NULL;
- p->commit = 0;
- p->read = 0;
- p->char_buf_ptr = (char *)(p->data);
- p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
- tty->buf.memory_used += size;
- return p;
-}
-
-/**
- * tty_buffer_free - free a tty buffer
- * @tty: tty owning the buffer
- * @b: the buffer to free
- *
- * Free a tty buffer, or add it to the free list according to our
- * internal strategy
- *
- * Locking: Caller must hold tty->buf.lock
- */
-
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
-{
- /* Dumb strategy for now - should keep some stats */
- tty->buf.memory_used -= b->size;
- WARN_ON(tty->buf.memory_used < 0);
-
- if (b->size >= 512)
- kfree(b);
- else {
- b->next = tty->buf.free;
- tty->buf.free = b;
- }
-}
-
-/**
- * __tty_buffer_flush - flush full tty buffers
- * @tty: tty to flush
- *
- * flush all the buffers containing receive data. Caller must
- * hold the buffer lock and must have ensured no parallel flush to
- * ldisc is running.
- *
- * Locking: Caller must hold tty->buf.lock
- */
-
-static void __tty_buffer_flush(struct tty_struct *tty)
-{
- struct tty_buffer *thead;
-
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
- }
- tty->buf.tail = NULL;
-}
-
-/**
- * tty_buffer_flush - flush full tty buffers
- * @tty: tty to flush
- *
- * flush all the buffers containing receive data. If the buffer is
- * being processed by flush_to_ldisc then we defer the processing
- * to that function
- *
- * Locking: none
- */
-
-static void tty_buffer_flush(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
-
- /* If the data is being pushed to the tty layer then we can't
- process it here. Instead set a flag and the flush_to_ldisc
- path will process the flush request before it exits */
- if (test_bit(TTY_FLUSHING, &tty->flags)) {
- set_bit(TTY_FLUSHPENDING, &tty->flags);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- wait_event(tty->read_wait,
- test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
- return;
- } else
- __tty_buffer_flush(tty);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
-}
-
-/**
- * tty_buffer_find - find a free tty buffer
- * @tty: tty owning the buffer
- * @size: characters wanted
- *
- * Locate an existing suitable tty buffer or if we are lacking one then
- * allocate a new one. We round our buffers off in 256 character chunks
- * to get better allocation behaviour.
- *
- * Locking: Caller must hold tty->buf.lock
- */
-
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
-{
- struct tty_buffer **tbh = &tty->buf.free;
- while ((*tbh) != NULL) {
- struct tty_buffer *t = *tbh;
- if (t->size >= size) {
- *tbh = t->next;
- t->next = NULL;
- t->used = 0;
- t->commit = 0;
- t->read = 0;
- tty->buf.memory_used += t->size;
- return t;
- }
- tbh = &((*tbh)->next);
- }
- /* Round the buffer size out */
- size = (size + 0xFF) & ~0xFF;
- return tty_buffer_alloc(tty, size);
- /* Should possibly check if this fails for the largest buffer we
- have queued and recycle that ? */
-}
-
-/**
- * tty_buffer_request_room - grow tty buffer if needed
- * @tty: tty structure
- * @size: size desired
- *
- * Make at least size bytes of linear space available for the tty
- * buffer. If we fail return the size we managed to find.
- *
- * Locking: Takes tty->buf.lock
- */
-int tty_buffer_request_room(struct tty_struct *tty, size_t size)
-{
- struct tty_buffer *b, *n;
- int left;
- unsigned long flags;
-
- spin_lock_irqsave(&tty->buf.lock, flags);
-
- /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
- remove this conditional if its worth it. This would be invisible
- to the callers */
- if ((b = tty->buf.tail) != NULL)
- left = b->size - b->used;
- else
- left = 0;
-
- if (left < size) {
- /* This is the slow path - looking for new buffers to use */
- if ((n = tty_buffer_find(tty, size)) != NULL) {
- if (b != NULL) {
- b->next = n;
- b->commit = b->used;
- } else
- tty->buf.head = n;
- tty->buf.tail = n;
- } else
- size = left;
- }
-
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- return size;
-}
-EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-
-/**
- * tty_insert_flip_string - Add characters to the tty buffer
- * @tty: tty structure
- * @chars: characters
- * @size: size
- *
- * Queue a series of bytes to the tty buffering. All the characters
- * passed are marked as without error. Returns the number added.
- *
- * Locking: Called functions may take tty->buf.lock
- */
-
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
- size_t size)
-{
- int copied = 0;
- do {
- int space = tty_buffer_request_room(tty, size - copied);
- struct tty_buffer *tb = tty->buf.tail;
- /* If there is no space then tb may be NULL */
- if (unlikely(space == 0))
- break;
- memcpy(tb->char_buf_ptr + tb->used, chars, space);
- memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
- tb->used += space;
- copied += space;
- chars += space;
- /* There is a small chance that we need to split the data over
- several buffers. If this is the case we must loop */
- } while (unlikely(size > copied));
- return copied;
-}
-EXPORT_SYMBOL(tty_insert_flip_string);
-
-/**
- * tty_insert_flip_string_flags - Add characters to the tty buffer
- * @tty: tty structure
- * @chars: characters
- * @flags: flag bytes
- * @size: size
- *
- * Queue a series of bytes to the tty buffering. For each character
- * the flags array indicates the status of the character. Returns the
- * number added.
- *
- * Locking: Called functions may take tty->buf.lock
- */
-
-int tty_insert_flip_string_flags(struct tty_struct *tty,
- const unsigned char *chars, const char *flags, size_t size)
-{
- int copied = 0;
- do {
- int space = tty_buffer_request_room(tty, size - copied);
- struct tty_buffer *tb = tty->buf.tail;
- /* If there is no space then tb may be NULL */
- if (unlikely(space == 0))
- break;
- memcpy(tb->char_buf_ptr + tb->used, chars, space);
- memcpy(tb->flag_buf_ptr + tb->used, flags, space);
- tb->used += space;
- copied += space;
- chars += space;
- flags += space;
- /* There is a small chance that we need to split the data over
- several buffers. If this is the case we must loop */
- } while (unlikely(size > copied));
- return copied;
-}
-EXPORT_SYMBOL(tty_insert_flip_string_flags);
-
-/**
- * tty_schedule_flip - push characters to ldisc
- * @tty: tty to push from
- *
- * Takes any pending buffers and transfers their ownership to the
- * ldisc side of the queue. It then schedules those characters for
- * processing by the line discipline.
- *
- * Locking: Takes tty->buf.lock
- */
-
-void tty_schedule_flip(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- schedule_delayed_work(&tty->buf.work, 1);
-}
-EXPORT_SYMBOL(tty_schedule_flip);
-
-/**
- * tty_prepare_flip_string - make room for characters
- * @tty: tty
- * @chars: return pointer for character write area
- * @size: desired size
- *
- * Prepare a block of space in the buffer for data. Returns the length
- * available and buffer pointer to the space which is now allocated and
- * accounted for as ready for normal characters. This is used for drivers
- * that need their own block copy routines into the buffer. There is no
- * guarantee the buffer is a DMA target!
- *
- * Locking: May call functions taking tty->buf.lock
- */
-
-int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
- size_t size)
-{
- int space = tty_buffer_request_room(tty, size);
- if (likely(space)) {
- struct tty_buffer *tb = tty->buf.tail;
- *chars = tb->char_buf_ptr + tb->used;
- memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
- tb->used += space;
- }
- return space;
-}
-
-EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
-
-/**
- * tty_prepare_flip_string_flags - make room for characters
- * @tty: tty
- * @chars: return pointer for character write area
- * @flags: return pointer for status flag write area
- * @size: desired size
- *
- * Prepare a block of space in the buffer for data. Returns the length
- * available and buffer pointer to the space which is now allocated and
- * accounted for as ready for characters. This is used for drivers
- * that need their own block copy routines into the buffer. There is no
- * guarantee the buffer is a DMA target!
- *
- * Locking: May call functions taking tty->buf.lock
- */
-
-int tty_prepare_flip_string_flags(struct tty_struct *tty,
- unsigned char **chars, char **flags, size_t size)
-{
- int space = tty_buffer_request_room(tty, size);
- if (likely(space)) {
- struct tty_buffer *tb = tty->buf.tail;
- *chars = tb->char_buf_ptr + tb->used;
- *flags = tb->flag_buf_ptr + tb->used;
- tb->used += space;
- }
- return space;
-}
-
-EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
-
-
-
/**
* get_tty_driver - find device of a tty
* @dev_t: device identifier
@@ -675,7 +274,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
if (device < base || device >= base + p->num)
continue;
*index = device - base;
- return p;
+ return tty_driver_kref_get(p);
}
return NULL;
}
@@ -695,13 +294,23 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
{
struct tty_driver *p, *res = NULL;
int tty_line = 0;
+ int len;
char *str;
+ for (str = name; *str; str++)
+ if ((*str >= '0' && *str <= '9') || *str == ',')
+ break;
+ if (!*str)
+ return NULL;
+
+ len = str - name;
+ tty_line = simple_strtoul(str, &str, 10);
+
mutex_lock(&tty_mutex);
/* Search through the tty devices to look for a match */
list_for_each_entry(p, &tty_drivers, tty_drivers) {
- str = name + strlen(p->name);
- tty_line = simple_strtoul(str, &str, 10);
+ if (strncmp(name, p->name, len) != 0)
+ continue;
if (*str == ',')
str++;
if (*str == '\0')
@@ -709,7 +318,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
if (tty_line >= 0 && tty_line <= p->num && p->ops &&
p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
- res = p;
+ res = tty_driver_kref_get(p);
*line = tty_line;
break;
}
@@ -809,20 +418,6 @@ static const struct file_operations tty_fops = {
.fasync = tty_fasync,
};
-#ifdef CONFIG_UNIX98_PTYS
-static const struct file_operations ptmx_fops = {
- .llseek = no_llseek,
- .read = tty_read,
- .write = tty_write,
- .poll = tty_poll,
- .unlocked_ioctl = tty_ioctl,
- .compat_ioctl = tty_compat_ioctl,
- .open = ptmx_open,
- .release = tty_release,
- .fasync = tty_fasync,
-};
-#endif
-
static const struct file_operations console_fops = {
.llseek = no_llseek,
.read = tty_read,
@@ -943,6 +538,7 @@ static void do_tty_hangup(struct work_struct *work)
struct tty_ldisc *ld;
int closecount = 0, n;
unsigned long flags;
+ int refs = 0;
if (!tty)
return;
@@ -1009,8 +605,12 @@ static void do_tty_hangup(struct work_struct *work)
if (tty->session) {
do_each_pid_task(tty->session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock);
- if (p->signal->tty == tty)
+ if (p->signal->tty == tty) {
p->signal->tty = NULL;
+ /* We defer the dereferences outside fo
+ the tasklist lock */
+ refs++;
+ }
if (!p->signal->leader) {
spin_unlock_irq(&p->sighand->siglock);
continue;
@@ -1036,6 +636,10 @@ static void do_tty_hangup(struct work_struct *work)
tty->ctrl_status = 0;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ /* Account for the p->signal references we killed */
+ while (refs--)
+ tty_kref_put(tty);
+
/*
* If one of the devices matches a console pointer, we
* cannot just call hangup() because that will cause
@@ -1105,6 +709,23 @@ void tty_vhangup(struct tty_struct *tty)
EXPORT_SYMBOL(tty_vhangup);
/**
+ * tty_vhangup_self - process vhangup for own ctty
+ *
+ * Perform a vhangup on the current controlling tty
+ */
+
+void tty_vhangup_self(void)
+{
+ struct tty_struct *tty;
+
+ tty = get_current_tty();
+ if (tty) {
+ tty_vhangup(tty);
+ tty_kref_put(tty);
+ }
+}
+
+/**
* tty_hung_up_p - was tty hung up
* @filp: file pointer of tty
*
@@ -1157,16 +778,14 @@ void disassociate_ctty(int on_exit)
struct pid *tty_pgrp = NULL;
- mutex_lock(&tty_mutex);
tty = get_current_tty();
if (tty) {
tty_pgrp = get_pid(tty->pgrp);
lock_kernel();
- mutex_unlock(&tty_mutex);
- /* XXX: here we race, there is nothing protecting tty */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
unlock_kernel();
+ tty_kref_put(tty);
} else if (on_exit) {
struct pid *old_pgrp;
spin_lock_irq(&current->sighand->siglock);
@@ -1178,7 +797,6 @@ void disassociate_ctty(int on_exit)
kill_pgrp(old_pgrp, SIGCONT, on_exit);
put_pid(old_pgrp);
}
- mutex_unlock(&tty_mutex);
return;
}
if (tty_pgrp) {
@@ -1193,8 +811,6 @@ void disassociate_ctty(int on_exit)
current->signal->tty_old_pgrp = NULL;
spin_unlock_irq(&current->sighand->siglock);
- mutex_lock(&tty_mutex);
- /* It is possible that do_tty_hangup has free'd this tty */
tty = get_current_tty();
if (tty) {
unsigned long flags;
@@ -1204,13 +820,13 @@ void disassociate_ctty(int on_exit)
tty->session = NULL;
tty->pgrp = NULL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ tty_kref_put(tty);
} else {
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
" = NULL", tty);
#endif
}
- mutex_unlock(&tty_mutex);
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
@@ -1410,19 +1026,19 @@ static inline ssize_t do_tty_write(
/* write_buf/write_cnt is protected by the atomic_write_lock mutex */
if (tty->write_cnt < chunk) {
- unsigned char *buf;
+ unsigned char *buf_chunk;
if (chunk < 1024)
chunk = 1024;
- buf = kmalloc(chunk, GFP_KERNEL);
- if (!buf) {
+ buf_chunk = kmalloc(chunk, GFP_KERNEL);
+ if (!buf_chunk) {
ret = -ENOMEM;
goto out;
}
kfree(tty->write_buf);
tty->write_cnt = chunk;
- tty->write_buf = buf;
+ tty->write_buf = buf_chunk;
}
/* Do the write .. */
@@ -1456,6 +1072,31 @@ out:
return ret;
}
+/**
+ * tty_write_message - write a message to a certain tty, not just the console.
+ * @tty: the destination tty_struct
+ * @msg: the message to write
+ *
+ * This is used for messages that need to be redirected to a specific tty.
+ * We don't put it into the syslog queue right now maybe in the future if
+ * really needed.
+ *
+ * We must still hold the BKL and test the CLOSING flag for the moment.
+ */
+
+void tty_write_message(struct tty_struct *tty, char *msg)
+{
+ lock_kernel();
+ if (tty) {
+ mutex_lock(&tty->atomic_write_lock);
+ if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags))
+ tty->ops->write(tty, msg, strlen(msg));
+ tty_write_unlock(tty);
+ }
+ unlock_kernel();
+ return;
+}
+
/**
* tty_write - write method for tty device file
@@ -1523,42 +1164,6 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,
return tty_write(file, buf, count, ppos);
}
-void tty_port_init(struct tty_port *port)
-{
- memset(port, 0, sizeof(*port));
- init_waitqueue_head(&port->open_wait);
- init_waitqueue_head(&port->close_wait);
- mutex_init(&port->mutex);
- port->close_delay = (50 * HZ) / 100;
- port->closing_wait = (3000 * HZ) / 100;
-}
-EXPORT_SYMBOL(tty_port_init);
-
-int tty_port_alloc_xmit_buf(struct tty_port *port)
-{
- /* We may sleep in get_zeroed_page() */
- mutex_lock(&port->mutex);
- if (port->xmit_buf == NULL)
- port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
- mutex_unlock(&port->mutex);
- if (port->xmit_buf == NULL)
- return -ENOMEM;
- return 0;
-}
-EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
-
-void tty_port_free_xmit_buf(struct tty_port *port)
-{
- mutex_lock(&port->mutex);
- if (port->xmit_buf != NULL) {
- free_page((unsigned long)port->xmit_buf);
- port->xmit_buf = NULL;
- }
- mutex_unlock(&port->mutex);
-}
-EXPORT_SYMBOL(tty_port_free_xmit_buf);
-
-
static char ptychar[] = "pqrstuvwxyzabcde";
/**
@@ -1582,7 +1187,7 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
}
/**
- * pty_line_name - generate name for a tty
+ * tty_line_name - generate name for a tty
* @driver: the tty driver in use
* @index: the minor number
* @p: output buffer of at least 7 bytes
@@ -1598,10 +1203,148 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
}
/**
- * init_dev - initialise a tty device
+ * tty_driver_lookup_tty() - find an existing tty, if any
+ * @driver: the driver for the tty
+ * @idx: the minor number
+ *
+ * Return the tty, if found or ERR_PTR() otherwise.
+ *
+ * Locking: tty_mutex must be held. If tty is found, the mutex must
+ * be held until the 'fast-open' is also done. Will change once we
+ * have refcounting in the driver and per driver locking
+ */
+struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
+ struct inode *inode, int idx)
+{
+ struct tty_struct *tty;
+
+ if (driver->ops->lookup)
+ return driver->ops->lookup(driver, inode, idx);
+
+ tty = driver->ttys[idx];
+ return tty;
+}
+
+/**
+ * tty_init_termios - helper for termios setup
+ * @tty: the tty to set up
+ *
+ * Initialise the termios structures for this tty. Thus runs under
+ * the tty_mutex currently so we can be relaxed about ordering.
+ */
+
+int tty_init_termios(struct tty_struct *tty)
+{
+ struct ktermios *tp;
+ int idx = tty->index;
+
+ tp = tty->driver->termios[idx];
+ if (tp == NULL) {
+ tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (tp == NULL)
+ return -ENOMEM;
+ memcpy(tp, &tty->driver->init_termios,
+ sizeof(struct ktermios));
+ tty->driver->termios[idx] = tp;
+ }
+ tty->termios = tp;
+ tty->termios_locked = tp + 1;
+
+ /* Compatibility until drivers always set this */
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+ return 0;
+}
+
+/**
+ * tty_driver_install_tty() - install a tty entry in the driver
+ * @driver: the driver for the tty
+ * @tty: the tty
+ *
+ * Install a tty object into the driver tables. The tty->index field
+ * will be set by the time this is called. This method is responsible
+ * for ensuring any need additional structures are allocated and
+ * configured.
+ *
+ * Locking: tty_mutex for now
+ */
+static int tty_driver_install_tty(struct tty_driver *driver,
+ struct tty_struct *tty)
+{
+ int idx = tty->index;
+
+ if (driver->ops->install)
+ return driver->ops->install(driver, tty);
+
+ if (tty_init_termios(tty) == 0) {
+ tty_driver_kref_get(driver);
+ tty->count++;
+ driver->ttys[idx] = tty;
+ return 0;
+ }
+ return -ENOMEM;
+}
+
+/**
+ * tty_driver_remove_tty() - remove a tty from the driver tables
+ * @driver: the driver for the tty
+ * @idx: the minor number
+ *
+ * Remvoe a tty object from the driver tables. The tty->index field
+ * will be set by the time this is called.
+ *
+ * Locking: tty_mutex for now
+ */
+static void tty_driver_remove_tty(struct tty_driver *driver,
+ struct tty_struct *tty)
+{
+ if (driver->ops->remove)
+ driver->ops->remove(driver, tty);
+ else
+ driver->ttys[tty->index] = NULL;
+}
+
+/*
+ * tty_reopen() - fast re-open of an open tty
+ * @tty - the tty to open
+ *
+ * Return 0 on success, -errno on error.
+ *
+ * Locking: tty_mutex must be held from the time the tty was found
+ * till this open completes.
+ */
+static int tty_reopen(struct tty_struct *tty)
+{
+ struct tty_driver *driver = tty->driver;
+
+ if (test_bit(TTY_CLOSING, &tty->flags))
+ return -EIO;
+
+ if (driver->type == TTY_DRIVER_TYPE_PTY &&
+ driver->subtype == PTY_TYPE_MASTER) {
+ /*
+ * special case for PTY masters: only one open permitted,
+ * and the slave side open count is incremented as well.
+ */
+ if (tty->count)
+ return -EIO;
+
+ tty->link->count++;
+ }
+ tty->count++;
+ tty->driver = driver; /* N.B. why do this every time?? */
+
+ WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
+
+ return 0;
+}
+
+/**
+ * tty_init_dev - initialise a tty device
* @driver: tty driver we are opening a device on
* @idx: device index
- * @tty: returned tty structure
+ * @ret_tty: returned tty structure
+ * @first_ok: ok to open a new device (used by ptmx)
*
* Prepare a tty device. This may not be a "new" clean device but
* could also be an active device. The pty drivers require special
@@ -1621,37 +1364,16 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
* relaxed for the (most common) case of reopening a tty.
*/
-static int init_dev(struct tty_driver *driver, int idx,
- struct tty_struct **ret_tty)
+struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
+ int first_ok)
{
- struct tty_struct *tty, *o_tty;
- struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
- int retval = 0;
+ struct tty_struct *tty;
+ int retval;
- /* check whether we're reopening an existing tty */
- if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
- tty = devpts_get_tty(idx);
- /*
- * If we don't have a tty here on a slave open, it's because
- * the master already started the close process and there's
- * no relation between devpts file and tty anymore.
- */
- if (!tty && driver->subtype == PTY_TYPE_SLAVE) {
- retval = -EIO;
- goto end_init;
- }
- /*
- * It's safe from now on because init_dev() is called with
- * tty_mutex held and release_dev() won't change tty->count
- * or tty->flags without having to grab tty_mutex
- */
- if (tty && driver->subtype == PTY_TYPE_MASTER)
- tty = tty->link;
- } else {
- tty = driver->ttys[idx];
- }
- if (tty) goto fast_track;
+ /* Check if pty master is being opened multiple times */
+ if (driver->subtype == PTY_TYPE_MASTER &&
+ (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok)
+ return ERR_PTR(-EIO);
/*
* First time open is complex, especially for PTY devices.
@@ -1661,189 +1383,69 @@ static int init_dev(struct tty_driver *driver, int idx,
* and locked termios may be retained.)
*/
- if (!try_module_get(driver->owner)) {
- retval = -ENODEV;
- goto end_init;
- }
-
- o_tty = NULL;
- tp = o_tp = NULL;
- ltp = o_ltp = NULL;
+ if (!try_module_get(driver->owner))
+ return ERR_PTR(-ENODEV);
tty = alloc_tty_struct();
if (!tty)
goto fail_no_mem;
- initialize_tty_struct(tty);
- tty->driver = driver;
- tty->ops = driver->ops;
- tty->index = idx;
- tty_line_name(driver, idx, tty->name);
-
- if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
- tp_loc = &tty->termios;
- ltp_loc = &tty->termios_locked;
- } else {
- tp_loc = &driver->termios[idx];
- ltp_loc = &driver->termios_locked[idx];
- }
+ initialize_tty_struct(tty, driver, idx);
- if (!*tp_loc) {
- tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
- if (!tp)
- goto free_mem_out;
- *tp = driver->init_termios;
- }
-
- if (!*ltp_loc) {
- ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
- if (!ltp)
- goto free_mem_out;
- }
-
- if (driver->type == TTY_DRIVER_TYPE_PTY) {
- o_tty = alloc_tty_struct();
- if (!o_tty)
- goto free_mem_out;
- initialize_tty_struct(o_tty);
- o_tty->driver = driver->other;
- o_tty->ops = driver->ops;
- o_tty->index = idx;
- tty_line_name(driver->other, idx, o_tty->name);
-
- if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
- o_tp_loc = &o_tty->termios;
- o_ltp_loc = &o_tty->termios_locked;
- } else {
- o_tp_loc = &driver->other->termios[idx];
- o_ltp_loc = &driver->other->termios_locked[idx];
- }
-
- if (!*o_tp_loc) {
- o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
- if (!o_tp)
- goto free_mem_out;
- *o_tp = driver->other->init_termios;
- }
-
- if (!*o_ltp_loc) {
- o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
- if (!o_ltp)
- goto free_mem_out;
- }
-
- /*
- * Everything allocated ... set up the o_tty structure.
- */
- if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM))
- driver->other->ttys[idx] = o_tty;
- if (!*o_tp_loc)
- *o_tp_loc = o_tp;
- if (!*o_ltp_loc)
- *o_ltp_loc = o_ltp;
- o_tty->termios = *o_tp_loc;
- o_tty->termios_locked = *o_ltp_loc;
- driver->other->refcount++;
- if (driver->subtype == PTY_TYPE_MASTER)
- o_tty->count++;
-
- /* Establish the links in both directions */
- tty->link = o_tty;
- o_tty->link = tty;
+ retval = tty_driver_install_tty(driver, tty);
+ if (retval < 0) {
+ free_tty_struct(tty);
+ module_put(driver->owner);
+ return ERR_PTR(retval);
}
/*
- * All structures have been allocated, so now we install them.
- * Failures after this point use release_tty to clean up, so
- * there's no need to null out the local pointers.
- */
- if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM))
- driver->ttys[idx] = tty;
-
- if (!*tp_loc)
- *tp_loc = tp;
- if (!*ltp_loc)
- *ltp_loc = ltp;
- tty->termios = *tp_loc;
- tty->termios_locked = *ltp_loc;
- /* Compatibility until drivers always set this */
- tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
- tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
- driver->refcount++;
- tty->count++;
-
- /*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
* to decrement the use counts, as release_tty doesn't care.
*/
- retval = tty_ldisc_setup(tty, o_tty);
-
+ retval = tty_ldisc_setup(tty, tty->link);
if (retval)
goto release_mem_out;
- goto success;
-
- /*
- * This fast open can be used if the tty is already open.
- * No memory is allocated, and the only failures are from
- * attempting to open a closing tty or attempting multiple
- * opens on a pty master.
- */
-fast_track:
- if (test_bit(TTY_CLOSING, &tty->flags)) {
- retval = -EIO;
- goto end_init;
- }
- if (driver->type == TTY_DRIVER_TYPE_PTY &&
- driver->subtype == PTY_TYPE_MASTER) {
- /*
- * special case for PTY masters: only one open permitted,
- * and the slave side open count is incremented as well.
- */
- if (tty->count) {
- retval = -EIO;
- goto end_init;
- }
- tty->link->count++;
- }
- tty->count++;
- tty->driver = driver; /* N.B. why do this every time?? */
-
- /* FIXME */
- if (!test_bit(TTY_LDISC, &tty->flags))
- printk(KERN_ERR "init_dev but no ldisc\n");
-success:
- *ret_tty = tty;
-
- /* All paths come through here to release the mutex */
-end_init:
- return retval;
-
- /* Release locally allocated memory ... nothing placed in slots */
-free_mem_out:
- kfree(o_tp);
- if (o_tty)
- free_tty_struct(o_tty);
- kfree(ltp);
- kfree(tp);
- free_tty_struct(tty);
+ return tty;
fail_no_mem:
module_put(driver->owner);
- retval = -ENOMEM;
- goto end_init;
+ return ERR_PTR(-ENOMEM);
/* call the tty release_tty routine to clean out this slot */
release_mem_out:
if (printk_ratelimit())
- printk(KERN_INFO "init_dev: ldisc open failed, "
+ printk(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
- goto end_init;
+ return ERR_PTR(retval);
+}
+
+void tty_free_termios(struct tty_struct *tty)
+{
+ struct ktermios *tp;
+ int idx = tty->index;
+ /* Kill this flag and push into drivers for locking etc */
+ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+ /* FIXME: Locking on ->termios array */
+ tp = tty->termios;
+ tty->driver->termios[idx] = NULL;
+ kfree(tp);
+ }
}
+EXPORT_SYMBOL(tty_free_termios);
+
+void tty_shutdown(struct tty_struct *tty)
+{
+ tty_driver_remove_tty(tty->driver, tty);
+ tty_free_termios(tty);
+}
+EXPORT_SYMBOL(tty_shutdown);
/**
* release_one_tty - release tty structure memory
+ * @kref: kref of tty we are obliterating
*
* Releases memory associated with a tty structure, and clears out the
* driver table slots. This function is called when a device is no longer
@@ -1853,31 +1455,19 @@ release_mem_out:
* tty_mutex - sometimes only
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
- * FIXME: should we require tty_mutex is held here ??
*/
-static void release_one_tty(struct tty_struct *tty, int idx)
+static void release_one_tty(struct kref *kref)
{
- int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
- struct ktermios *tp;
-
- if (!devpts)
- tty->driver->ttys[idx] = NULL;
-
- if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- tp = tty->termios;
- if (!devpts)
- tty->driver->termios[idx] = NULL;
- kfree(tp);
-
- tp = tty->termios_locked;
- if (!devpts)
- tty->driver->termios_locked[idx] = NULL;
- kfree(tp);
- }
-
+ struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
+ struct tty_driver *driver = tty->driver;
+ if (tty->ops->shutdown)
+ tty->ops->shutdown(tty);
+ else
+ tty_shutdown(tty);
tty->magic = 0;
- tty->driver->refcount--;
+ tty_driver_kref_put(driver);
+ module_put(driver->owner);
file_list_lock();
list_del_init(&tty->tty_files);
@@ -1887,6 +1477,21 @@ static void release_one_tty(struct tty_struct *tty, int idx)
}
/**
+ * tty_kref_put - release a tty kref
+ * @tty: tty device
+ *
+ * Release a reference to a tty device and if need be let the kref
+ * layer destruct the object for us
+ */
+
+void tty_kref_put(struct tty_struct *tty)
+{
+ if (tty)
+ kref_put(&tty->kref, release_one_tty);
+}
+EXPORT_SYMBOL(tty_kref_put);
+
+/**
* release_tty - release tty structure memory
*
* Release both @tty and a possible linked partner (think pty pair),
@@ -1897,15 +1502,16 @@ static void release_one_tty(struct tty_struct *tty, int idx)
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
* FIXME: should we require tty_mutex is held here ??
+ *
*/
static void release_tty(struct tty_struct *tty, int idx)
{
- struct tty_driver *driver = tty->driver;
+ /* This should always be true but check for the moment */
+ WARN_ON(tty->index != idx);
if (tty->link)
- release_one_tty(tty->link, idx);
- release_one_tty(tty, idx);
- module_put(driver->owner);
+ tty_kref_put(tty->link);
+ tty_kref_put(tty);
}
/*
@@ -1916,20 +1522,21 @@ static void release_tty(struct tty_struct *tty, int idx)
* WSH 09/09/97: rewritten to avoid some nasty race conditions that could
* lead to double frees or releasing memory still in use.
*/
-static void release_dev(struct file *filp)
+void tty_release_dev(struct file *filp)
{
struct tty_struct *tty, *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
int devpts;
int idx;
char buf[64];
+ struct inode *inode;
+ inode = filp->f_path.dentry->d_inode;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode,
- "release_dev"))
+ if (tty_paranoia_check(tty, inode, "tty_release_dev"))
return;
- check_tty_count(tty, "release_dev");
+ check_tty_count(tty, "tty_release_dev");
tty_fasync(-1, filp, 0);
@@ -1941,33 +1548,27 @@ static void release_dev(struct file *filp)
#ifdef TTY_PARANOIA_CHECK
if (idx < 0 || idx >= tty->driver->num) {
- printk(KERN_DEBUG "release_dev: bad idx when trying to "
+ printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
"free (%s)\n", tty->name);
return;
}
- if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+ if (!devpts) {
if (tty != tty->driver->ttys[idx]) {
- printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
+ printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
"for (%s)\n", idx, tty->name);
return;
}
if (tty->termios != tty->driver->termios[idx]) {
- printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
+ printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
"for (%s)\n",
idx, tty->name);
return;
}
- if (tty->termios_locked != tty->driver->termios_locked[idx]) {
- printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
- "termios_locked for (%s)\n",
- idx, tty->name);
- return;
- }
}
#endif
#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "release_dev of %s (tty count=%d)...",
+ printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...",
tty_name(tty, buf), tty->count);
#endif
@@ -1975,26 +1576,19 @@ static void release_dev(struct file *filp)
if (tty->driver->other &&
!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
if (o_tty != tty->driver->other->ttys[idx]) {
- printk(KERN_DEBUG "release_dev: other->table[%d] "
+ printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
"not o_tty for (%s)\n",
idx, tty->name);
return;
}
if (o_tty->termios != tty->driver->other->termios[idx]) {
- printk(KERN_DEBUG "release_dev: other->termios[%d] "
+ printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
"not o_termios for (%s)\n",
idx, tty->name);
return;
}
- if (o_tty->termios_locked !=
- tty->driver->other->termios_locked[idx]) {
- printk(KERN_DEBUG "release_dev: other->termios_locked["
- "%d] not o_termios_locked for (%s)\n",
- idx, tty->name);
- return;
- }
if (o_tty->link != tty) {
- printk(KERN_DEBUG "release_dev: bad pty pointers\n");
+ printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
return;
}
}
@@ -2052,7 +1646,7 @@ static void release_dev(struct file *filp)
if (!do_sleep)
break;
- printk(KERN_WARNING "release_dev: %s: read/write wait queue "
+ printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
mutex_unlock(&tty_mutex);
schedule();
@@ -2065,14 +1659,14 @@ static void release_dev(struct file *filp)
*/
if (pty_master) {
if (--o_tty->count < 0) {
- printk(KERN_WARNING "release_dev: bad pty slave count "
+ printk(KERN_WARNING "tty_release_dev: bad pty slave count "
"(%d) for %s\n",
o_tty->count, tty_name(o_tty, buf));
o_tty->count = 0;
}
}
if (--tty->count < 0) {
- printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n",
+ printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n",
tty->count, tty_name(tty, buf));
tty->count = 0;
}
@@ -2135,11 +1729,11 @@ static void release_dev(struct file *filp)
/* Make this pty number available for reallocation */
if (devpts)
- devpts_kill_index(idx);
+ devpts_kill_index(inode, idx);
}
/**
- * tty_open - open a tty device
+ * __tty_open - open a tty device
* @inode: inode of device file
* @filp: file pointer to tty
*
@@ -2154,14 +1748,14 @@ static void release_dev(struct file *filp)
* The termios state of a pty is reset on first open so that
* settings don't persist across reuse.
*
- * Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ * Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work.
* tty->count should protect the rest.
* ->siglock protects ->signal/->sighand
*/
static int __tty_open(struct inode *inode, struct file *filp)
{
- struct tty_struct *tty;
+ struct tty_struct *tty = NULL;
int noctty, retval;
struct tty_driver *driver;
int index;
@@ -2183,23 +1777,25 @@ retry_open:
mutex_unlock(&tty_mutex);
return -ENXIO;
}
- driver = tty->driver;
+ driver = tty_driver_kref_get(tty->driver);
index = tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
+ /* FIXME: Should we take a driver reference ? */
+ tty_kref_put(tty);
goto got_driver;
}
#ifdef CONFIG_VT
if (device == MKDEV(TTY_MAJOR, 0)) {
extern struct tty_driver *console_driver;
- driver = console_driver;
+ driver = tty_driver_kref_get(console_driver);
index = fg_console;
noctty = 1;
goto got_driver;
}
#endif
if (device == MKDEV(TTYAUX_MAJOR, 1)) {
- driver = console_device(&index);
+ driver = tty_driver_kref_get(console_device(&index));
if (driver) {
/* Don't let /dev/console block */
filp->f_flags |= O_NONBLOCK;
@@ -2216,10 +1812,25 @@ retry_open:
return -ENODEV;
}
got_driver:
- retval = init_dev(driver, index, &tty);
+ if (!tty) {
+ /* check whether we're reopening an existing tty */
+ tty = tty_driver_lookup_tty(driver, inode, index);
+
+ if (IS_ERR(tty))
+ return PTR_ERR(tty);
+ }
+
+ if (tty) {
+ retval = tty_reopen(tty);
+ if (retval)
+ tty = ERR_PTR(retval);
+ } else
+ tty = tty_init_dev(driver, index, 0);
+
mutex_unlock(&tty_mutex);
- if (retval)
- return retval;
+ tty_driver_kref_put(driver);
+ if (IS_ERR(tty))
+ return PTR_ERR(tty);
filp->private_data = tty;
file_move(filp, &tty->tty_files);
@@ -2247,7 +1858,7 @@ got_driver:
printk(KERN_DEBUG "error %d in opening %s...", retval,
tty->name);
#endif
- release_dev(filp);
+ tty_release_dev(filp);
if (retval != -ERESTARTSYS)
return retval;
if (signal_pending(current))
@@ -2286,69 +1897,6 @@ static int tty_open(struct inode *inode, struct file *filp)
-#ifdef CONFIG_UNIX98_PTYS
-/**
- * ptmx_open - open a unix 98 pty master
- * @inode: inode of device file
- * @filp: file pointer to tty
- *
- * Allocate a unix98 pty master device from the ptmx driver.
- *
- * Locking: tty_mutex protects theinit_dev work. tty->count should
- * protect the rest.
- * allocated_ptys_lock handles the list of free pty numbers
- */
-
-static int __ptmx_open(struct inode *inode, struct file *filp)
-{
- struct tty_struct *tty;
- int retval;
- int index;
-
- nonseekable_open(inode, filp);
-
- /* find a device that is not in use. */
- index = devpts_new_index();
- if (index < 0)
- return index;
-
- mutex_lock(&tty_mutex);
- retval = init_dev(ptm_driver, index, &tty);
- mutex_unlock(&tty_mutex);
-
- if (retval)
- goto out;
-
- set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
- filp->private_data = tty;
- file_move(filp, &tty->tty_files);
-
- retval = devpts_pty_new(tty->link);
- if (retval)
- goto out1;
-
- check_tty_count(tty, "ptmx_open");
- retval = ptm_driver->ops->open(tty, filp);
- if (!retval)
- return 0;
-out1:
- release_dev(filp);
- return retval;
-out:
- devpts_kill_index(index);
- return retval;
-}
-
-static int ptmx_open(struct inode *inode, struct file *filp)
-{
- int ret;
-
- lock_kernel();
- ret = __ptmx_open(inode, filp);
- unlock_kernel();
- return ret;
-}
-#endif
/**
* tty_release - vfs callback for close
@@ -2359,13 +1907,13 @@ static int ptmx_open(struct inode *inode, struct file *filp)
* this tty. There may however be several such references.
*
* Locking:
- * Takes bkl. See release_dev
+ * Takes bkl. See tty_release_dev
*/
static int tty_release(struct inode *inode, struct file *filp)
{
lock_kernel();
- release_dev(filp);
+ tty_release_dev(filp);
unlock_kernel();
return 0;
}
@@ -2514,7 +2062,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
/* For a PTY we need to lock the tty side */
mutex_lock(&real_tty->termios_mutex);
- if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
+ if (!memcmp(ws, &real_tty->winsize, sizeof(*ws)))
goto done;
/* Get the PID values and reference them so we can
avoid holding the tty ctrl lock while sending signals */
@@ -2986,7 +2534,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCSTI:
return tiocsti(tty, p);
case TIOCGWINSZ:
- return tiocgwinsz(tty, p);
+ return tiocgwinsz(real_tty, p);
case TIOCSWINSZ:
return tiocswinsz(tty, real_tty, p);
case TIOCCONS:
@@ -3016,10 +2564,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(tty->ldisc.ops->num, (int __user *)p);
case TIOCSETD:
return tiocsetd(tty, p);
-#ifdef CONFIG_VT
- case TIOCLINUX:
- return tioclinux(tty, arg);
-#endif
/*
* Break handling
*/
@@ -3210,113 +2754,6 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
/**
- * flush_to_ldisc
- * @work: tty structure passed from work queue.
- *
- * This routine is called out of the software interrupt to flush data
- * from the buffer chain to the line discipline.
- *
- * Locking: holds tty->buf.lock to guard buffer list. Drops the lock
- * while invoking the line discipline receive_buf method. The
- * receive_buf method is single threaded for each tty instance.
- */
-
-static void flush_to_ldisc(struct work_struct *work)
-{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, buf.work.work);
- unsigned long flags;
- struct tty_ldisc *disc;
- struct tty_buffer *tbuf, *head;
- char *char_buf;
- unsigned char *flag_buf;
-
- disc = tty_ldisc_ref(tty);
- if (disc == NULL) /* !TTY_LDISC */
- return;
-
- spin_lock_irqsave(&tty->buf.lock, flags);
- /* So we know a flush is running */
- set_bit(TTY_FLUSHING, &tty->flags);
- head = tty->buf.head;
- if (head != NULL) {
- tty->buf.head = NULL;
- for (;;) {
- int count = head->commit - head->read;
- if (!count) {
- if (head->next == NULL)
- break;
- tbuf = head;
- head = head->next;
- tty_buffer_free(tty, tbuf);
- continue;
- }
- /* Ldisc or user is trying to flush the buffers
- we are feeding to the ldisc, stop feeding the
- line discipline as we want to empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags))
- break;
- if (!tty->receive_room) {
- schedule_delayed_work(&tty->buf.work, 1);
- break;
- }
- if (count > tty->receive_room)
- count = tty->receive_room;
- char_buf = head->char_buf_ptr + head->read;
- flag_buf = head->flag_buf_ptr + head->read;
- head->read += count;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- disc->ops->receive_buf(tty, char_buf,
- flag_buf, count);
- spin_lock_irqsave(&tty->buf.lock, flags);
- }
- /* Restore the queue head */
- tty->buf.head = head;
- }
- /* We may have a deferred request to flush the input buffer,
- if so pull the chain under the lock and empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
- __tty_buffer_flush(tty);
- clear_bit(TTY_FLUSHPENDING, &tty->flags);
- wake_up(&tty->read_wait);
- }
- clear_bit(TTY_FLUSHING, &tty->flags);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
-
- tty_ldisc_deref(disc);
-}
-
-/**
- * tty_flip_buffer_push - terminal
- * @tty: tty to push
- *
- * Queue a push of the terminal flip buffers to the line discipline. This
- * function must not be called from IRQ context if tty->low_latency is set.
- *
- * In the event of the queue being busy for flipping the work will be
- * held off and retried later.
- *
- * Locking: tty buffer lock. Driver locks in low latency mode.
- */
-
-void tty_flip_buffer_push(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
-
- if (tty->low_latency)
- flush_to_ldisc(&tty->buf.work.work);
- else
- schedule_delayed_work(&tty->buf.work, 1);
-}
-
-EXPORT_SYMBOL(tty_flip_buffer_push);
-
-
-/**
* initialize_tty_struct
* @tty: tty to initialize
*
@@ -3326,9 +2763,11 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
* Locking: none - tty in question must not be exposed at this point
*/
-static void initialize_tty_struct(struct tty_struct *tty)
+void initialize_tty_struct(struct tty_struct *tty,
+ struct tty_driver *driver, int idx)
{
memset(tty, 0, sizeof(struct tty_struct));
+ kref_init(&tty->kref);
tty->magic = TTY_MAGIC;
tty_ldisc_init(tty);
tty->session = NULL;
@@ -3336,7 +2775,6 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty->overrun_time = jiffies;
tty->buf.head = tty->buf.tail = NULL;
tty_buffer_init(tty);
- INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
mutex_init(&tty->termios_mutex);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
@@ -3347,6 +2785,11 @@ static void initialize_tty_struct(struct tty_struct *tty)
spin_lock_init(&tty->ctrl_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_WORK(&tty->SAK_work, do_SAK_work);
+
+ tty->driver = driver;
+ tty->ops = driver->ops;
+ tty->index = idx;
+ tty_line_name(driver, idx, tty->name);
}
/**
@@ -3367,10 +2810,9 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch)
return tty->ops->put_char(tty, ch);
return tty->ops->write(tty, &ch, 1);
}
-
EXPORT_SYMBOL_GPL(tty_put_char);
-static struct class *tty_class;
+struct class *tty_class;
/**
* tty_register_device - register a tty device
@@ -3408,8 +2850,9 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
else
tty_line_name(driver, index, name);
- return device_create_drvdata(tty_class, device, dev, NULL, name);
+ return device_create(tty_class, device, dev, NULL, name);
}
+EXPORT_SYMBOL(tty_register_device);
/**
* tty_unregister_device - unregister a tty device
@@ -3427,8 +2870,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
device_destroy(tty_class,
MKDEV(driver->major, driver->minor_start) + index);
}
-
-EXPORT_SYMBOL(tty_register_device);
EXPORT_SYMBOL(tty_unregister_device);
struct tty_driver *alloc_tty_driver(int lines)
@@ -3437,27 +2878,65 @@ struct tty_driver *alloc_tty_driver(int lines)
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
+ kref_init(&driver->kref);
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
}
return driver;
}
+EXPORT_SYMBOL(alloc_tty_driver);
-void put_tty_driver(struct tty_driver *driver)
+static void destruct_tty_driver(struct kref *kref)
{
+ struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
+ int i;
+ struct ktermios *tp;
+ void *p;
+
+ if (driver->flags & TTY_DRIVER_INSTALLED) {
+ /*
+ * Free the termios and termios_locked structures because
+ * we don't want to get memory leaks when modular tty
+ * drivers are removed from the kernel.
+ */
+ for (i = 0; i < driver->num; i++) {
+ tp = driver->termios[i];
+ if (tp) {
+ driver->termios[i] = NULL;
+ kfree(tp);
+ }
+ if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
+ tty_unregister_device(driver, i);
+ }
+ p = driver->ttys;
+ proc_tty_unregister_driver(driver);
+ driver->ttys = NULL;
+ driver->termios = NULL;
+ kfree(p);
+ cdev_del(&driver->cdev);
+ }
kfree(driver);
}
+void tty_driver_kref_put(struct tty_driver *driver)
+{
+ kref_put(&driver->kref, destruct_tty_driver);
+}
+EXPORT_SYMBOL(tty_driver_kref_put);
+
void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op)
{
driver->ops = op;
};
+EXPORT_SYMBOL(tty_set_operations);
-EXPORT_SYMBOL(alloc_tty_driver);
+void put_tty_driver(struct tty_driver *d)
+{
+ tty_driver_kref_put(d);
+}
EXPORT_SYMBOL(put_tty_driver);
-EXPORT_SYMBOL(tty_set_operations);
/*
* Called by a tty driver to register itself.
@@ -3469,11 +2948,8 @@ int tty_register_driver(struct tty_driver *driver)
dev_t dev;
void **p = NULL;
- if (driver->flags & TTY_DRIVER_INSTALLED)
- return 0;
-
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
- p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+ p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
if (!p)
return -ENOMEM;
}
@@ -3497,12 +2973,9 @@ int tty_register_driver(struct tty_driver *driver)
if (p) {
driver->ttys = (struct tty_struct **)p;
driver->termios = (struct ktermios **)(p + driver->num);
- driver->termios_locked = (struct ktermios **)
- (p + driver->num * 2);
} else {
driver->ttys = NULL;
driver->termios = NULL;
- driver->termios_locked = NULL;
}
cdev_init(&driver->cdev, &tty_fops);
@@ -3511,7 +2984,7 @@ int tty_register_driver(struct tty_driver *driver)
if (error) {
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
- driver->termios = driver->termios_locked = NULL;
+ driver->termios = NULL;
kfree(p);
return error;
}
@@ -3525,6 +2998,7 @@ int tty_register_driver(struct tty_driver *driver)
tty_register_device(driver, i, NULL);
}
proc_tty_register_driver(driver);
+ driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
}
@@ -3535,46 +3009,19 @@ EXPORT_SYMBOL(tty_register_driver);
*/
int tty_unregister_driver(struct tty_driver *driver)
{
- int i;
- struct ktermios *tp;
- void *p;
-
+#if 0
+ /* FIXME */
if (driver->refcount)
return -EBUSY;
-
+#endif
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
driver->num);
mutex_lock(&tty_mutex);
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);
-
- /*
- * Free the termios and termios_locked structures because
- * we don't want to get memory leaks when modular tty
- * drivers are removed from the kernel.
- */
- for (i = 0; i < driver->num; i++) {
- tp = driver->termios[i];
- if (tp) {
- driver->termios[i] = NULL;
- kfree(tp);
- }
- tp = driver->termios_locked[i];
- if (tp) {
- driver->termios_locked[i] = NULL;
- kfree(tp);
- }
- if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
- tty_unregister_device(driver, i);
- }
- p = driver->ttys;
- proc_tty_unregister_driver(driver);
- driver->ttys = NULL;
- driver->termios = driver->termios_locked = NULL;
- kfree(p);
- cdev_del(&driver->cdev);
return 0;
}
+
EXPORT_SYMBOL(tty_unregister_driver);
dev_t tty_devnum(struct tty_struct *tty)
@@ -3585,9 +3032,13 @@ EXPORT_SYMBOL(tty_devnum);
void proc_clear_tty(struct task_struct *p)
{
- spin_lock_irq(&p->sighand->siglock);
+ unsigned long flags;
+ struct tty_struct *tty;
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ tty = p->signal->tty;
p->signal->tty = NULL;
- spin_unlock_irq(&p->sighand->siglock);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ tty_kref_put(tty);
}
/* Called under the sighand lock */
@@ -3603,9 +3054,13 @@ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
tty->pgrp = get_pid(task_pgrp(tsk));
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
tty->session = get_pid(task_session(tsk));
+ if (tsk->signal->tty) {
+ printk(KERN_DEBUG "tty not NULL!!\n");
+ tty_kref_put(tsk->signal->tty);
+ }
}
put_pid(tsk->signal->tty_old_pgrp);
- tsk->signal->tty = tty;
+ tsk->signal->tty = tty_kref_get(tty);
tsk->signal->tty_old_pgrp = NULL;
}
@@ -3619,18 +3074,20 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
struct tty_struct *get_current_tty(void)
{
struct tty_struct *tty;
- WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
- tty = current->signal->tty;
- /*
- * session->tty can be changed/cleared from under us, make sure we
- * issue the load. The obtained pointer, when not NULL, is valid as
- * long as we hold tty_mutex.
- */
- barrier();
+ unsigned long flags;
+
+ spin_lock_irqsave(&current->sighand->siglock, flags);
+ tty = tty_kref_get(current->signal->tty);
+ spin_unlock_irqrestore(&current->sighand->siglock, flags);
return tty;
}
EXPORT_SYMBOL_GPL(get_current_tty);
+void tty_default_fops(struct file_operations *fops)
+{
+ *fops = tty_fops;
+}
+
/*
* Initialize the console device. This is called *early*, so
* we can't necessarily depend on lots of kernel help here.
@@ -3668,12 +3125,6 @@ postcore_initcall(tty_class_init);
/* 3/2004 jmc: why do these devices exist? */
static struct cdev tty_cdev, console_cdev;
-#ifdef CONFIG_UNIX98_PTYS
-static struct cdev ptmx_cdev;
-#endif
-#ifdef CONFIG_VT
-static struct cdev vc0_cdev;
-#endif
/*
* Ok, now we can initialize the rest of the tty devices and can count
@@ -3685,32 +3136,18 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
- device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
"tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
- device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+ device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
"console");
-#ifdef CONFIG_UNIX98_PTYS
- cdev_init(&ptmx_cdev, &ptmx_fops);
- if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
- register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
- panic("Couldn't register /dev/ptmx driver\n");
- device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
-#endif
-
#ifdef CONFIG_VT
- cdev_init(&vc0_cdev, &console_fops);
- if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
- register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
- panic("Couldn't register /dev/tty0 driver\n");
- device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
-
- vty_init();
+ vty_init(&console_fops);
#endif
return 0;
}
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index bf34e459742..a408c8e487e 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -40,6 +40,15 @@
#define TERMIOS_OLD 8
+/**
+ * tty_chars_in_buffer - characters pending
+ * @tty: terminal
+ *
+ * Return the number of bytes of data in the device private
+ * output queue. If no private method is supplied there is assumed
+ * to be no queue on the device.
+ */
+
int tty_chars_in_buffer(struct tty_struct *tty)
{
if (tty->ops->chars_in_buffer)
@@ -47,26 +56,49 @@ int tty_chars_in_buffer(struct tty_struct *tty)
else
return 0;
}
-
EXPORT_SYMBOL(tty_chars_in_buffer);
+/**
+ * tty_write_room - write queue space
+ * @tty: terminal
+ *
+ * Return the number of bytes that can be queued to this device
+ * at the present time. The result should be treated as a guarantee
+ * and the driver cannot offer a value it later shrinks by more than
+ * the number of bytes written. If no method is provided 2K is always
+ * returned and data may be lost as there will be no flow control.
+ */
+
int tty_write_room(struct tty_struct *tty)
{
if (tty->ops->write_room)
return tty->ops->write_room(tty);
return 2048;
}
-
EXPORT_SYMBOL(tty_write_room);
+/**
+ * tty_driver_flush_buffer - discard internal buffer
+ * @tty: terminal
+ *
+ * Discard the internal output buffer for this device. If no method
+ * is provided then either the buffer cannot be hardware flushed or
+ * there is no buffer driver side.
+ */
void tty_driver_flush_buffer(struct tty_struct *tty)
{
if (tty->ops->flush_buffer)
tty->ops->flush_buffer(tty);
}
-
EXPORT_SYMBOL(tty_driver_flush_buffer);
+/**
+ * tty_throttle - flow control
+ * @tty: terminal
+ *
+ * Indicate that a tty should stop transmitting data down the stack.
+ */
+
void tty_throttle(struct tty_struct *tty)
{
/* check TTY_THROTTLED first so it indicates our state */
@@ -76,6 +108,13 @@ void tty_throttle(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_throttle);
+/**
+ * tty_unthrottle - flow control
+ * @tty: terminal
+ *
+ * Indicate that a tty may continue transmitting data down the stack.
+ */
+
void tty_unthrottle(struct tty_struct *tty)
{
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
@@ -112,6 +151,11 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
}
EXPORT_SYMBOL(tty_wait_until_sent);
+
+/*
+ * Termios Helper Methods
+ */
+
static void unset_locked_termios(struct ktermios *termios,
struct ktermios *old,
struct ktermios *locked)
@@ -346,6 +390,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
}
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
+/**
+ * tty_encode_baud_rate - set baud rate of the tty
+ * @ibaud: input baud rate
+ * @obad: output baud rate
+ *
+ * Update the current termios data for the tty with the new speed
+ * settings. The caller must hold the termios_mutex for the tty in
+ * question.
+ */
+
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
{
tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
@@ -430,12 +484,11 @@ EXPORT_SYMBOL(tty_termios_hw_change);
* is a bit of layering violation here with n_tty in terms of the
* internal knowledge of this function.
*
- * Locking: termios_sem
+ * Locking: termios_mutex
*/
static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
{
- int canon_change;
struct ktermios old_termios;
struct tty_ldisc *ld;
unsigned long flags;
@@ -451,18 +504,6 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
old_termios = *tty->termios;
*tty->termios = *new_termios;
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
- canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
- if (canon_change) {
- memset(&tty->read_flags, 0, sizeof tty->read_flags);
- tty->canon_head = tty->read_tail;
- tty->canon_data = 0;
- tty->erasing = 0;
- }
-
- /* This bit should be in the ldisc code */
- if (canon_change && !L_ICANON(tty) && tty->read_cnt)
- /* Get characters left over from canonical mode. */
- wake_up_interruptible(&tty->read_wait);
/* See if packet mode change of state. */
if (tty->link && tty->link->packet) {
@@ -508,7 +549,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
* functions before using change_termios to do the actual changes.
*
* Locking:
- * Called functions take ldisc and termios_sem locks
+ * Called functions take ldisc and termios_mutex locks
*/
static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
@@ -579,25 +620,51 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio)
return 0;
}
-static unsigned long inq_canon(struct tty_struct *tty)
+
+#ifdef TCGETX
+
+/**
+ * set_termiox - set termiox fields if possible
+ * @tty: terminal
+ * @arg: termiox structure from user
+ * @opt: option flags for ioctl type
+ *
+ * Implement the device calling points for the SYS5 termiox ioctl
+ * interface in Linux
+ */
+
+static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
{
- int nr, head, tail;
+ struct termiox tnew;
+ struct tty_ldisc *ld;
- if (!tty->canon_data || !tty->read_buf)
- return 0;
- head = tty->canon_head;
- tail = tty->read_tail;
- nr = (head - tail) & (N_TTY_BUF_SIZE-1);
- /* Skip EOF-chars.. */
- while (head != tail) {
- if (test_bit(tail, tty->read_flags) &&
- tty->read_buf[tail] == __DISABLED_CHAR)
- nr--;
- tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+ if (tty->termiox == NULL)
+ return -EINVAL;
+ if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
+ return -EFAULT;
+
+ ld = tty_ldisc_ref(tty);
+ if (ld != NULL) {
+ if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
+ ld->ops->flush_buffer(tty);
+ tty_ldisc_deref(ld);
}
- return nr;
+ if (opt & TERMIOS_WAIT) {
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ }
+
+ mutex_lock(&tty->termios_mutex);
+ if (tty->ops->set_termiox)
+ tty->ops->set_termiox(tty, &tnew);
+ mutex_unlock(&tty->termios_mutex);
+ return 0;
}
+#endif
+
+
#ifdef TIOCGETP
/*
* These are deprecated, but there is limited support..
@@ -671,7 +738,7 @@ static void set_sgflags(struct ktermios *termios, int flags)
* Updates a terminal from the legacy BSD style terminal information
* structure.
*
- * Locking: termios_sem
+ * Locking: termios_mutex
*/
static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
@@ -849,6 +916,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
{
struct tty_struct *real_tty;
void __user *p = (void __user *)arg;
+ int ret = 0;
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
@@ -884,18 +952,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_OLD);
#ifndef TCGETS2
case TCGETS:
+ mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
#else
case TCGETS:
+ mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
case TCGETS2:
+ mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
case TCSETSF2:
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
case TCSETSW2:
@@ -913,34 +987,59 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_TERMIO);
#ifndef TCGETS2
case TIOCGLCKTRMIOS:
+ mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ mutex_lock(&real_tty->termios_mutex);
if (user_termios_to_kernel_termios(real_tty->termios_locked,
(struct termios __user *) arg))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
#else
case TIOCGLCKTRMIOS:
+ mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ ret = -EPERM;
+ mutex_lock(&real_tty->termios_mutex);
if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
(struct termios __user *) arg))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
#endif
+#ifdef TCGETX
+ case TCGETX:
+ if (real_tty->termiox == NULL)
+ return -EINVAL;
+ mutex_lock(&real_tty->termios_mutex);
+ if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
+ ret = -EFAULT;
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
+ case TCSETX:
+ return set_termiox(real_tty, p, 0);
+ case TCSETXW:
+ return set_termiox(real_tty, p, TERMIOS_WAIT);
+ case TCSETXF:
+ return set_termiox(real_tty, p, TERMIOS_FLUSH);
+#endif
case TIOCGSOFTCAR:
- /* FIXME: for correctness we may need to take the termios
- lock here - review */
- return put_user(C_CLOCAL(real_tty) ? 1 : 0,
+ mutex_lock(&real_tty->termios_mutex);
+ ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
(int __user *)arg);
+ mutex_unlock(&real_tty->termios_mutex);
+ return ret;
case TIOCSSOFTCAR:
if (get_user(arg, (unsigned int __user *) arg))
return -EFAULT;
@@ -980,7 +1079,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
}
EXPORT_SYMBOL_GPL(tty_perform_flush);
-int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned long flags;
@@ -1018,13 +1117,6 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
return 0;
case TCFLSH:
return tty_perform_flush(tty, arg);
- case TIOCOUTQ:
- return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
- case TIOCINQ:
- retval = tty->read_cnt;
- if (L_ICANON(tty))
- retval = inq_canon(tty);
- return put_user(retval, (unsigned int __user *) arg);
case TIOCPKT:
{
int pktmode;
@@ -1050,4 +1142,4 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
return tty_mode_ioctl(tty, file, cmd, arg);
}
}
-EXPORT_SYMBOL(n_tty_ioctl);
+EXPORT_SYMBOL(n_tty_ioctl_helper);
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
new file mode 100644
index 00000000000..553b0e9d8d1
--- /dev/null
+++ b/drivers/char/tty_port.c
@@ -0,0 +1,96 @@
+/*
+ * Tty port functions
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+void tty_port_init(struct tty_port *port)
+{
+ memset(port, 0, sizeof(*port));
+ init_waitqueue_head(&port->open_wait);
+ init_waitqueue_head(&port->close_wait);
+ mutex_init(&port->mutex);
+ spin_lock_init(&port->lock);
+ port->close_delay = (50 * HZ) / 100;
+ port->closing_wait = (3000 * HZ) / 100;
+}
+EXPORT_SYMBOL(tty_port_init);
+
+int tty_port_alloc_xmit_buf(struct tty_port *port)
+{
+ /* We may sleep in get_zeroed_page() */
+ mutex_lock(&port->mutex);
+ if (port->xmit_buf == NULL)
+ port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+ mutex_unlock(&port->mutex);
+ if (port->xmit_buf == NULL)
+ return -ENOMEM;
+ return 0;
+}
+EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
+
+void tty_port_free_xmit_buf(struct tty_port *port)
+{
+ mutex_lock(&port->mutex);
+ if (port->xmit_buf != NULL) {
+ free_page((unsigned long)port->xmit_buf);
+ port->xmit_buf = NULL;
+ }
+ mutex_unlock(&port->mutex);
+}
+EXPORT_SYMBOL(tty_port_free_xmit_buf);
+
+
+/**
+ * tty_port_tty_get - get a tty reference
+ * @port: tty port
+ *
+ * Return a refcount protected tty instance or NULL if the port is not
+ * associated with a tty (eg due to close or hangup)
+ */
+
+struct tty_struct *tty_port_tty_get(struct tty_port *port)
+{
+ unsigned long flags;
+ struct tty_struct *tty;
+
+ spin_lock_irqsave(&port->lock, flags);
+ tty = tty_kref_get(port->tty);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return tty;
+}
+EXPORT_SYMBOL(tty_port_tty_get);
+
+/**
+ * tty_port_tty_set - set the tty of a port
+ * @port: tty port
+ * @tty: the tty
+ *
+ * Associate the port and tty pair. Manages any internal refcounts.
+ * Pass NULL to deassociate a port
+ */
+
+void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (port->tty)
+ tty_kref_put(port->tty);
+ port->tty = tty;
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+EXPORT_SYMBOL(tty_port_tty_set);
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index c2ae52dd53d..4f3b3f95fc4 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -481,10 +481,10 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty)
{
- device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
- NULL, "vcs%u", tty->index + 1);
- device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
- NULL, "vcsa%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL,
+ "vcs%u", tty->index + 1);
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL,
+ "vcsa%u", tty->index + 1);
}
void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@ int __init vcs_init(void)
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc");
- device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 7a70a40ad63..ffc9254f7e0 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
- device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
- NULL, "iseries!vt%d", i);
- device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
- NULL, "iseries!nvt%d", i);
+ device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ "iseries!vt%d", i);
+ device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL,
+ "iseries!nvt%d", i);
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
"resource %10.10s type %4.4s, model %3.3s\n",
i, viotape_unitinfo[i].rsrcname,
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 60359c36091..d8f83e26e4a 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -59,7 +59,7 @@
* by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
*
* Removed old-style timers, introduced console_timer, made timer
- * deletion SMP-safe. 17Jun00, Andrew Morton <andrewm@uow.edu.au>
+ * deletion SMP-safe. 17Jun00, Andrew Morton
*
* Removed console_lock, enabled interrupts across all console operations
* 13 March 2001, Andrew Morton
@@ -100,10 +100,10 @@
#include <linux/font.h>
#include <linux/bitops.h>
#include <linux/notifier.h>
-
-#include <asm/io.h>
+#include <linux/device.h>
+#include <linux/io.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#define MAX_NR_CON_DRIVER 16
@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
- scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char,
+ scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
vc->vc_size_row * nr);
}
@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
step = vc->vc_cols * nr;
scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
- scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step);
+ scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
}
static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -434,7 +434,6 @@ static void update_attr(struct vc_data *vc)
vc->vc_blink, vc->vc_underline,
vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
- vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' ';
}
/* Note: inverting the screen twice should revert to the original state */
@@ -2136,27 +2135,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
release_console_sem();
return 0;
}
- release_console_sem();
-
orig_buf = buf;
orig_count = count;
- /* At this point 'buf' is guaranteed to be a kernel buffer
- * and therefore no access to userspace (and therefore sleeping)
- * will be needed. The con_buf_mtx serializes all tty based
- * console rendering and vcs write/read operations. We hold
- * the console spinlock during the entire write.
- */
-
- acquire_console_sem();
-
- vc = tty->driver_data;
- if (vc == NULL) {
- printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
- release_console_sem();
- goto out;
- }
-
himask = vc->vc_hi_font_mask;
charmask = himask ? 0x1ff : 0xff;
@@ -2370,8 +2351,6 @@ rescan_last_byte:
FLUSH
console_conditional_schedule();
release_console_sem();
-
-out:
notify_update(vc);
return n;
#undef FLUSH
@@ -2583,8 +2562,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
int lines;
int ret;
- if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE)
- return -EINVAL;
if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN))
return -EPERM;
if (get_user(type, p))
@@ -2778,6 +2755,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
ret = vc_allocate(currcons);
if (ret == 0) {
struct vc_data *vc = vc_cons[currcons].d;
+
+ /* Still being freed */
+ if (vc->vc_tty) {
+ release_console_sem();
+ return -ERESTARTSYS;
+ }
tty->driver_data = vc;
vc->vc_tty = tty;
@@ -2798,34 +2781,20 @@ static int con_open(struct tty_struct *tty, struct file *filp)
return ret;
}
-/*
- * We take tty_mutex in here to prevent another thread from coming in via init_dev
- * and taking a ref against the tty while we're in the process of forgetting
- * about it and cleaning things up.
- *
- * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
- */
static void con_close(struct tty_struct *tty, struct file *filp)
{
- mutex_lock(&tty_mutex);
- acquire_console_sem();
- if (tty && tty->count == 1) {
- struct vc_data *vc = tty->driver_data;
+ /* Nothing to do - we defer to shutdown */
+}
- if (vc)
- vc->vc_tty = NULL;
- tty->driver_data = NULL;
- vcs_remove_sysfs(tty);
- release_console_sem();
- mutex_unlock(&tty_mutex);
- /*
- * tty_mutex is released, but we still hold BKL, so there is
- * still exclusion against init_dev()
- */
- return;
- }
+static void con_shutdown(struct tty_struct *tty)
+{
+ struct vc_data *vc = tty->driver_data;
+ BUG_ON(vc == NULL);
+ acquire_console_sem();
+ vc->vc_tty = NULL;
+ vcs_remove_sysfs(tty);
release_console_sem();
- mutex_unlock(&tty_mutex);
+ tty_shutdown(tty);
}
static int default_italic_color = 2; // green (ASCII)
@@ -2950,10 +2919,19 @@ static const struct tty_operations con_ops = {
.throttle = con_throttle,
.unthrottle = con_unthrottle,
.resize = vt_resize,
+ .shutdown = con_shutdown
};
-int __init vty_init(void)
+static struct cdev vc0_cdev;
+
+int __init vty_init(const struct file_operations *console_fops)
{
+ cdev_init(&vc0_cdev, console_fops);
+ if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
+ register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
+ panic("Couldn't register /dev/tty0 driver\n");
+ device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+
vcs_init();
console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
@@ -2972,7 +2950,6 @@ int __init vty_init(void)
tty_set_operations(console_driver, &con_ops);
if (tty_register_driver(console_driver))
panic("Couldn't register console driver\n");
-
kbd_init();
console_map_init();
#ifdef CONFIG_PROM_CONSOLE
@@ -3466,7 +3443,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
- con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
+ con_driver->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con_driver->node),
NULL, "vtcon%i",
con_driver->node);
@@ -3577,7 +3554,7 @@ static int __init vtconsole_class_init(void)
struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->dev) {
- con->dev = device_create_drvdata(vtconsole_class, NULL,
+ con->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con->node),
NULL, "vtcon%i",
con->node);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index c904e9ad4a7..8944ce508e2 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -395,6 +395,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
kbd = kbd_table + console;
switch (cmd) {
+ case TIOCLINUX:
+ return tioclinux(tty, arg);
case KIOCSOUND:
if (!perm)
goto eperm;
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 278c9857bcf..ed132fe55d3 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -657,8 +657,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
goto failed3;
}
- device_create_drvdata(icap_class, dev, devt, NULL,
- "%s%d", DRIVER_NAME, id);
+ device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
return 0; /* success */
failed3:
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 5ca1d80de18..71d2ac4e3f4 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -21,6 +21,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/delay.h>
#include <asm/io.h>
/*
@@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
*/
static int verify_pmtmr_rate(void)
{
- u32 value1, value2;
+ cycle_t value1, value2;
unsigned long count, delta;
mach_prepare_counter();
- value1 = read_pmtmr();
+ value1 = clocksource_acpi_pm.read();
mach_countup(&count);
- value2 = read_pmtmr();
+ value2 = clocksource_acpi_pm.read();
delta = (value2 - value1) & ACPI_PM_MASK;
/* Check that the PMTMR delta is within 5% of what we expect */
@@ -175,10 +176,15 @@ static int verify_pmtmr_rate(void)
#define verify_pmtmr_rate() (0)
#endif
+/* Number of monotonicity checks to perform during initialization */
+#define ACPI_PM_MONOTONICITY_CHECKS 10
+/* Number of reads we try to get two different values */
+#define ACPI_PM_READ_CHECKS 10000
+
static int __init init_acpi_pm_clocksource(void)
{
- u32 value1, value2;
- unsigned int i;
+ cycle_t value1, value2;
+ unsigned int i, j = 0;
if (!pmtmr_ioport)
return -ENODEV;
@@ -187,24 +193,29 @@ static int __init init_acpi_pm_clocksource(void)
clocksource_acpi_pm.shift);
/* "verify" this timing source: */
- value1 = read_pmtmr();
- for (i = 0; i < 10000; i++) {
- value2 = read_pmtmr();
- if (value2 == value1)
- continue;
- if (value2 > value1)
- goto pm_good;
- if ((value2 < value1) && ((value2) < 0xFFF))
- goto pm_good;
- printk(KERN_INFO "PM-Timer had inconsistent results:"
- " 0x%#x, 0x%#x - aborting.\n", value1, value2);
- return -EINVAL;
+ for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
+ udelay(100 * j);
+ value1 = clocksource_acpi_pm.read();
+ for (i = 0; i < ACPI_PM_READ_CHECKS; i++) {
+ value2 = clocksource_acpi_pm.read();
+ if (value2 == value1)
+ continue;
+ if (value2 > value1)
+ break;
+ if ((value2 < value1) && ((value2) < 0xFFF))
+ break;
+ printk(KERN_INFO "PM-Timer had inconsistent results:"
+ " 0x%#llx, 0x%#llx - aborting.\n",
+ value1, value2);
+ return -EINVAL;
+ }
+ if (i == ACPI_PM_READ_CHECKS) {
+ printk(KERN_INFO "PM-Timer failed consistency check "
+ " (0x%#llx) - aborting.\n", value1);
+ return -ENODEV;
+ }
}
- printk(KERN_INFO "PM-Timer had no reasonable result:"
- " 0x%#x - aborting.\n", value1);
- return -ENODEV;
-pm_good:
if (verify_pmtmr_rate() != 0)
return -ENODEV;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8a67f16987d..31d6f535a79 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1467,25 +1467,27 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- int ret;
+ int ret = -EINVAL;
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
- return -EINVAL;
+ goto no_policy;
if (unlikely(lock_policy_rwsem_write(policy->cpu)))
- return -EINVAL;
+ goto fail;
ret = __cpufreq_driver_target(policy, target_freq, relation);
unlock_policy_rwsem_write(policy->cpu);
+fail:
cpufreq_cpu_put(policy);
+no_policy:
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
-int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
+int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
{
int ret = 0;
@@ -1493,8 +1495,8 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
if (!policy)
return -EINVAL;
- if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
- ret = cpufreq_driver->getavg(policy->cpu);
+ if (cpu_online(cpu) && cpufreq_driver->getavg)
+ ret = cpufreq_driver->getavg(policy, cpu);
cpufreq_cpu_put(policy);
return ret;
@@ -1717,13 +1719,17 @@ int cpufreq_update_policy(unsigned int cpu)
{
struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
struct cpufreq_policy policy;
- int ret = 0;
+ int ret;
- if (!data)
- return -ENODEV;
+ if (!data) {
+ ret = -ENODEV;
+ goto no_policy;
+ }
- if (unlikely(lock_policy_rwsem_write(cpu)))
- return -EINVAL;
+ if (unlikely(lock_policy_rwsem_write(cpu))) {
+ ret = -EINVAL;
+ goto fail;
+ }
dprintk("updating policy for CPU %u\n", cpu);
memcpy(&policy, data, sizeof(struct cpufreq_policy));
@@ -1750,7 +1756,9 @@ int cpufreq_update_policy(unsigned int cpu)
unlock_policy_rwsem_write(cpu);
+fail:
cpufreq_cpu_put(data);
+no_policy:
return ret;
}
EXPORT_SYMBOL(cpufreq_update_policy);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index ac0bbf2d234..e2657837d95 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -460,6 +460,7 @@ static void do_dbs_timer(struct work_struct *work)
static inline void dbs_timer_init(void)
{
+ init_timer_deferrable(&dbs_work.timer);
schedule_delayed_work(&dbs_work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
return;
@@ -575,13 +576,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return 0;
}
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
+static
+#endif
struct cpufreq_governor cpufreq_gov_conservative = {
.name = "conservative",
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_conservative);
static int __init cpufreq_gov_dbs_init(void)
{
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 33855cb3cf1..2ab3c12b88a 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -18,13 +18,19 @@
#include <linux/jiffies.h>
#include <linux/kernel_stat.h>
#include <linux/mutex.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/ktime.h>
/*
* dbs is used in this file as a shortform for demandbased switching
* It helps to keep variable names smaller, simpler
*/
+#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10)
#define DEF_FREQUENCY_UP_THRESHOLD (80)
+#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3)
+#define MICRO_FREQUENCY_UP_THRESHOLD (95)
#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
@@ -57,6 +63,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
struct cpu_dbs_info_s {
cputime64_t prev_cpu_idle;
cputime64_t prev_cpu_wall;
+ cputime64_t prev_cpu_nice;
struct cpufreq_policy *cur_policy;
struct delayed_work work;
struct cpufreq_frequency_table *freq_table;
@@ -86,21 +93,24 @@ static struct workqueue_struct *kondemand_wq;
static struct dbs_tuners {
unsigned int sampling_rate;
unsigned int up_threshold;
+ unsigned int down_differential;
unsigned int ignore_nice;
unsigned int powersave_bias;
} dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+ .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
.ignore_nice = 0,
.powersave_bias = 0,
};
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
+static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
+ cputime64_t *wall)
{
cputime64_t idle_time;
- cputime64_t cur_jiffies;
+ cputime64_t cur_wall_time;
cputime64_t busy_time;
- cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+ cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
kstat_cpu(cpu).cpustat.system);
@@ -113,7 +123,37 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
kstat_cpu(cpu).cpustat.nice);
}
- idle_time = cputime64_sub(cur_jiffies, busy_time);
+ idle_time = cputime64_sub(cur_wall_time, busy_time);
+ if (wall)
+ *wall = cur_wall_time;
+
+ return idle_time;
+}
+
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+{
+ u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+
+ if (idle_time == -1ULL)
+ return get_cpu_idle_time_jiffy(cpu, wall);
+
+ if (dbs_tuners_ins.ignore_nice) {
+ cputime64_t cur_nice;
+ unsigned long cur_nice_jiffies;
+ struct cpu_dbs_info_s *dbs_info;
+
+ dbs_info = &per_cpu(cpu_dbs_info, cpu);
+ cur_nice = cputime64_sub(kstat_cpu(cpu).cpustat.nice,
+ dbs_info->prev_cpu_nice);
+ /*
+ * Assumption: nice time between sampling periods will be
+ * less than 2^32 jiffies for 32 bit sys
+ */
+ cur_nice_jiffies = (unsigned long)
+ cputime64_to_jiffies64(cur_nice);
+ dbs_info->prev_cpu_nice = kstat_cpu(cpu).cpustat.nice;
+ return idle_time + jiffies_to_usecs(cur_nice_jiffies);
+ }
return idle_time;
}
@@ -277,8 +317,8 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
for_each_online_cpu(j) {
struct cpu_dbs_info_s *dbs_info;
dbs_info = &per_cpu(cpu_dbs_info, j);
- dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
- dbs_info->prev_cpu_wall = get_jiffies_64();
+ dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+ &dbs_info->prev_cpu_wall);
}
mutex_unlock(&dbs_mutex);
@@ -334,9 +374,7 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
{
- unsigned int idle_ticks, total_ticks;
- unsigned int load = 0;
- cputime64_t cur_jiffies;
+ unsigned int max_load_freq;
struct cpufreq_policy *policy;
unsigned int j;
@@ -346,13 +384,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
this_dbs_info->freq_lo = 0;
policy = this_dbs_info->cur_policy;
- cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
- total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
- this_dbs_info->prev_cpu_wall);
- this_dbs_info->prev_cpu_wall = get_jiffies_64();
- if (!total_ticks)
- return;
/*
* Every sampling_rate, we check, if current idle time is less
* than 20% (default), then we try to increase frequency
@@ -365,27 +397,44 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
* 5% (default) of current frequency
*/
- /* Get Idle Time */
- idle_ticks = UINT_MAX;
+ /* Get Absolute Load - in terms of freq */
+ max_load_freq = 0;
+
for_each_cpu_mask_nr(j, policy->cpus) {
- cputime64_t total_idle_ticks;
- unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
+ cputime64_t cur_wall_time, cur_idle_time;
+ unsigned int idle_time, wall_time;
+ unsigned int load, load_freq;
+ int freq_avg;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- total_idle_ticks = get_cpu_idle_time(j);
- tmp_idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks,
+
+ cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+ wall_time = (unsigned int) cputime64_sub(cur_wall_time,
+ j_dbs_info->prev_cpu_wall);
+ j_dbs_info->prev_cpu_wall = cur_wall_time;
+
+ idle_time = (unsigned int) cputime64_sub(cur_idle_time,
j_dbs_info->prev_cpu_idle);
- j_dbs_info->prev_cpu_idle = total_idle_ticks;
+ j_dbs_info->prev_cpu_idle = cur_idle_time;
+
+ if (unlikely(!wall_time || wall_time < idle_time))
+ continue;
+
+ load = 100 * (wall_time - idle_time) / wall_time;
+
+ freq_avg = __cpufreq_driver_getavg(policy, j);
+ if (freq_avg <= 0)
+ freq_avg = policy->cur;
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
+ load_freq = load * freq_avg;
+ if (load_freq > max_load_freq)
+ max_load_freq = load_freq;
}
- if (likely(total_ticks > idle_ticks))
- load = (100 * (total_ticks - idle_ticks)) / total_ticks;
/* Check for frequency increase */
- if (load > dbs_tuners_ins.up_threshold) {
+ if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
/* if we are already at full speed then break out early */
if (!dbs_tuners_ins.powersave_bias) {
if (policy->cur == policy->max)
@@ -412,15 +461,13 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
* can support the current CPU usage without triggering the up
* policy. To be safe, we focus 10 points under the threshold.
*/
- if (load < (dbs_tuners_ins.up_threshold - 10)) {
- unsigned int freq_next, freq_cur;
-
- freq_cur = __cpufreq_driver_getavg(policy);
- if (!freq_cur)
- freq_cur = policy->cur;
-
- freq_next = (freq_cur * load) /
- (dbs_tuners_ins.up_threshold - 10);
+ if (max_load_freq <
+ (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
+ policy->cur) {
+ unsigned int freq_next;
+ freq_next = max_load_freq /
+ (dbs_tuners_ins.up_threshold -
+ dbs_tuners_ins.down_differential);
if (!dbs_tuners_ins.powersave_bias) {
__cpufreq_driver_target(policy, freq_next,
@@ -526,8 +573,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
- j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
- j_dbs_info->prev_cpu_wall = get_jiffies_64();
+ j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
+ &j_dbs_info->prev_cpu_wall);
}
this_dbs_info->cpu = cpu;
/*
@@ -579,22 +626,42 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return 0;
}
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
+#endif
struct cpufreq_governor cpufreq_gov_ondemand = {
.name = "ondemand",
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_ondemand);
static int __init cpufreq_gov_dbs_init(void)
{
+ int err;
+ cputime64_t wall;
+ u64 idle_time;
+ int cpu = get_cpu();
+
+ idle_time = get_cpu_idle_time_us(cpu, &wall);
+ put_cpu();
+ if (idle_time != -1ULL) {
+ /* Idle micro accounting is supported. Use finer thresholds */
+ dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+ dbs_tuners_ins.down_differential =
+ MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+ }
+
kondemand_wq = create_workqueue("kondemand");
if (!kondemand_wq) {
printk(KERN_ERR "Creation of kondemand failed\n");
return -EFAULT;
}
- return cpufreq_register_governor(&cpufreq_gov_ondemand);
+ err = cpufreq_register_governor(&cpufreq_gov_ondemand);
+ if (err)
+ destroy_workqueue(kondemand_wq);
+
+ return err;
}
static void __exit cpufreq_gov_dbs_exit(void)
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index e8e1451ef1c..7e2e515087f 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -36,12 +36,14 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
return 0;
}
+#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE
+static
+#endif
struct cpufreq_governor cpufreq_gov_performance = {
.name = "performance",
.governor = cpufreq_governor_performance,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_performance);
static int __init cpufreq_gov_performance_init(void)
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 88d2f44fba4..e6db5faf3eb 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -35,12 +35,14 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
return 0;
}
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
+static
+#endif
struct cpufreq_governor cpufreq_gov_powersave = {
.name = "powersave",
.governor = cpufreq_governor_powersave,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_powersave);
static int __init cpufreq_gov_powersave_init(void)
{
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 32244aa7cc0..1442bbada05 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -187,6 +187,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
}
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
+static
+#endif
struct cpufreq_governor cpufreq_gov_userspace = {
.name = "userspace",
.governor = cpufreq_governor_userspace,
@@ -194,7 +197,6 @@ struct cpufreq_governor cpufreq_gov_userspace = {
.show_setspeed = show_speed,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_userspace);
static int __init cpufreq_gov_userspace_init(void)
{
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index ee827a7f7c6..b6ad3ac5916 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1157,6 +1157,8 @@ static int aead_authenc_givencrypt(
edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
memcpy(req->giv, ctx->iv, crypto_aead_ivsize(authenc));
+ /* avoid consecutive packets going out with same IV */
+ *(__be64 *)req->giv ^= cpu_to_be64(req->seq);
return ipsec_esp(edesc, areq, req->giv, req->seq,
ipsec_esp_encrypt_done);
@@ -1449,6 +1451,8 @@ static int talitos_probe(struct of_device *ofdev,
priv->ofdev = ofdev;
+ INIT_LIST_HEAD(&priv->alg_list);
+
tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev);
tasklet_init(&priv->error_task, talitos_error, (unsigned long)dev);
@@ -1575,8 +1579,6 @@ static int talitos_probe(struct of_device *ofdev,
}
/* register crypto algorithms the device supports */
- INIT_LIST_HEAD(&priv->alg_list);
-
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
struct talitos_crypto_alg *t_alg;
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 7af4b403bd2..bb538b9690e 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -15,9 +15,8 @@ int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
struct device *cd;
static int req_count;
- cd = device_create_drvdata(dca_class, dca->cd,
- MKDEV(0, slot + 1), NULL,
- "requester%d", req_count++);
+ cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1), NULL,
+ "requester%d", req_count++);
if (IS_ERR(cd))
return PTR_ERR(cd);
return 0;
@@ -48,8 +47,7 @@ idr_try_again:
return err;
}
- cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
- "dca%d", dca->id);
+ cd = device_create(dca_class, dev, MKDEV(0, 0), NULL, "dca%d", dca->id);
if (IS_ERR(cd)) {
spin_lock(&dca_idr_lock);
idr_remove(&dca_idr, dca->id);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 94df9177124..0778d99aea7 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -364,7 +364,7 @@ static void dw_dma_tasklet(unsigned long data)
int i;
status_block = dma_readl(dw, RAW.BLOCK);
- status_xfer = dma_readl(dw, RAW.BLOCK);
+ status_xfer = dma_readl(dw, RAW.XFER);
status_err = dma_readl(dw, RAW.ERROR);
dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 4a16b5b61cf..f0d9b415db5 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -119,6 +119,7 @@
#define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \
FERR_NF_M11ERR | \
FERR_NF_M10ERR | \
+ FERR_NF_M9ERR | \
FERR_NF_M8ERR | \
FERR_NF_M7ERR | \
FERR_NF_M6ERR | \
@@ -301,6 +302,9 @@ static char *numcol_toString[] = {
};
#endif
+/* enables the report of miscellaneous messages as CE errors - default off */
+static int misc_messages;
+
/* Enumeration of supported devices */
enum i5000_chips {
I5000P = 0,
@@ -466,7 +470,8 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
struct i5000_error_info *info,
int handle_errors)
{
- char msg[EDAC_MC_LABEL_LEN + 1 + 90];
+ char msg[EDAC_MC_LABEL_LEN + 1 + 160];
+ char *specific = NULL;
u32 allErrors;
int branch;
int channel;
@@ -480,11 +485,6 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
if (!allErrors)
return; /* if no error, return now */
- /* ONLY ONE of the possible error bits will be set, as per the docs */
- i5000_mc_printk(mci, KERN_ERR,
- "FATAL ERRORS Found!!! 1st FATAL Err Reg= 0x%x\n",
- allErrors);
-
branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
channel = branch;
@@ -501,28 +501,42 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
rdwr ? "Write" : "Read", ras, cas);
/* Only 1 bit will be on */
- if (allErrors & FERR_FAT_M1ERR) {
- i5000_mc_printk(mci, KERN_ERR,
- "Alert on non-redundant retry or fast "
- "reset timeout\n");
-
- } else if (allErrors & FERR_FAT_M2ERR) {
- i5000_mc_printk(mci, KERN_ERR,
- "Northbound CRC error on non-redundant "
- "retry\n");
-
- } else if (allErrors & FERR_FAT_M3ERR) {
- i5000_mc_printk(mci, KERN_ERR,
- ">Tmid Thermal event with intelligent "
- "throttling disabled\n");
+ switch (allErrors) {
+ case FERR_FAT_M1ERR:
+ specific = "Alert on non-redundant retry or fast "
+ "reset timeout";
+ break;
+ case FERR_FAT_M2ERR:
+ specific = "Northbound CRC error on non-redundant "
+ "retry";
+ break;
+ case FERR_FAT_M3ERR:
+ {
+ static int done;
+
+ /*
+ * This error is generated to inform that the intelligent
+ * throttling is disabled and the temperature passed the
+ * specified middle point. Since this is something the BIOS
+ * should take care of, we'll warn only once to avoid
+ * worthlessly flooding the log.
+ */
+ if (done)
+ return;
+ done++;
+
+ specific = ">Tmid Thermal event with intelligent "
+ "throttling disabled";
+ }
+ break;
}
/* Form out message */
snprintf(msg, sizeof(msg),
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d "
- "FATAL Err=0x%x)",
+ "FATAL Err=0x%x (%s))",
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
- allErrors);
+ allErrors, specific);
/* Call the helper to output message */
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
@@ -539,7 +553,8 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
struct i5000_error_info *info,
int handle_errors)
{
- char msg[EDAC_MC_LABEL_LEN + 1 + 90];
+ char msg[EDAC_MC_LABEL_LEN + 1 + 170];
+ char *specific = NULL;
u32 allErrors;
u32 ue_errors;
u32 ce_errors;
@@ -557,10 +572,6 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
return; /* if no error, return now */
/* ONLY ONE of the possible error bits will be set, as per the docs */
- i5000_mc_printk(mci, KERN_WARNING,
- "NON-FATAL ERRORS Found!!! 1st NON-FATAL Err "
- "Reg= 0x%x\n", allErrors);
-
ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
if (ue_errors) {
debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
@@ -579,12 +590,47 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
rank, channel, channel + 1, branch >> 1, bank,
rdwr ? "Write" : "Read", ras, cas);
+ switch (ue_errors) {
+ case FERR_NF_M12ERR:
+ specific = "Non-Aliased Uncorrectable Patrol Data ECC";
+ break;
+ case FERR_NF_M11ERR:
+ specific = "Non-Aliased Uncorrectable Spare-Copy "
+ "Data ECC";
+ break;
+ case FERR_NF_M10ERR:
+ specific = "Non-Aliased Uncorrectable Mirrored Demand "
+ "Data ECC";
+ break;
+ case FERR_NF_M9ERR:
+ specific = "Non-Aliased Uncorrectable Non-Mirrored "
+ "Demand Data ECC";
+ break;
+ case FERR_NF_M8ERR:
+ specific = "Aliased Uncorrectable Patrol Data ECC";
+ break;
+ case FERR_NF_M7ERR:
+ specific = "Aliased Uncorrectable Spare-Copy Data ECC";
+ break;
+ case FERR_NF_M6ERR:
+ specific = "Aliased Uncorrectable Mirrored Demand "
+ "Data ECC";
+ break;
+ case FERR_NF_M5ERR:
+ specific = "Aliased Uncorrectable Non-Mirrored Demand "
+ "Data ECC";
+ break;
+ case FERR_NF_M4ERR:
+ specific = "Uncorrectable Data ECC on Replay";
+ break;
+ }
+
/* Form out message */
snprintf(msg, sizeof(msg),
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
- "CAS=%d, UE Err=0x%x)",
+ "CAS=%d, UE Err=0x%x (%s))",
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
- ue_errors);
+ ue_errors, specific);
/* Call the helper to output message */
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
@@ -616,51 +662,74 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
rank, channel, branch >> 1, bank,
rdwr ? "Write" : "Read", ras, cas);
+ switch (ce_errors) {
+ case FERR_NF_M17ERR:
+ specific = "Correctable Non-Mirrored Demand Data ECC";
+ break;
+ case FERR_NF_M18ERR:
+ specific = "Correctable Mirrored Demand Data ECC";
+ break;
+ case FERR_NF_M19ERR:
+ specific = "Correctable Spare-Copy Data ECC";
+ break;
+ case FERR_NF_M20ERR:
+ specific = "Correctable Patrol Data ECC";
+ break;
+ }
+
/* Form out message */
snprintf(msg, sizeof(msg),
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
- "CAS=%d, CE Err=0x%x)", branch >> 1, bank,
- rdwr ? "Write" : "Read", ras, cas, ce_errors);
+ "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank,
+ rdwr ? "Write" : "Read", ras, cas, ce_errors,
+ specific);
/* Call the helper to output message */
edac_mc_handle_fbd_ce(mci, rank, channel, msg);
}
- /* See if any of the thermal errors have fired */
- misc_errors = allErrors & FERR_NF_THERMAL;
- if (misc_errors) {
- i5000_printk(KERN_WARNING, "\tTHERMAL Error, bits= 0x%x\n",
- misc_errors);
- }
-
- /* See if any of the thermal errors have fired */
- misc_errors = allErrors & FERR_NF_NON_RETRY;
- if (misc_errors) {
- i5000_printk(KERN_WARNING, "\tNON-Retry Errors, bits= 0x%x\n",
- misc_errors);
- }
+ if (!misc_messages)
+ return;
- /* See if any of the thermal errors have fired */
- misc_errors = allErrors & FERR_NF_NORTH_CRC;
+ misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC |
+ FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE);
if (misc_errors) {
- i5000_printk(KERN_WARNING,
- "\tNORTHBOUND CRC Error, bits= 0x%x\n",
- misc_errors);
- }
+ switch (misc_errors) {
+ case FERR_NF_M13ERR:
+ specific = "Non-Retry or Redundant Retry FBD Memory "
+ "Alert or Redundant Fast Reset Timeout";
+ break;
+ case FERR_NF_M14ERR:
+ specific = "Non-Retry or Redundant Retry FBD "
+ "Configuration Alert";
+ break;
+ case FERR_NF_M15ERR:
+ specific = "Non-Retry or Redundant Retry FBD "
+ "Northbound CRC error on read data";
+ break;
+ case FERR_NF_M21ERR:
+ specific = "FBD Northbound CRC error on "
+ "FBD Sync Status";
+ break;
+ case FERR_NF_M22ERR:
+ specific = "SPD protocol error";
+ break;
+ case FERR_NF_M27ERR:
+ specific = "DIMM-spare copy started";
+ break;
+ case FERR_NF_M28ERR:
+ specific = "DIMM-spare copy completed";
+ break;
+ }
+ branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
- /* See if any of the thermal errors have fired */
- misc_errors = allErrors & FERR_NF_SPD_PROTOCOL;
- if (misc_errors) {
- i5000_printk(KERN_WARNING,
- "\tSPD Protocol Error, bits= 0x%x\n",
- misc_errors);
- }
+ /* Form out message */
+ snprintf(msg, sizeof(msg),
+ "(Branch=%d Err=%#x (%s))", branch >> 1,
+ misc_errors, specific);
- /* See if any of the thermal errors have fired */
- misc_errors = allErrors & FERR_NF_DIMM_SPARE;
- if (misc_errors) {
- i5000_printk(KERN_WARNING, "\tDIMM-Spare Error, bits= 0x%x\n",
- misc_errors);
+ /* Call the helper to output message */
+ edac_mc_handle_fbd_ce(mci, 0, 0, msg);
}
}
@@ -1497,3 +1566,6 @@ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+module_param(misc_messages, int, 0444);
+MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
+
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c
index c5305e3ee43..577760a82a0 100644
--- a/drivers/edac/i82443bxgx_edac.c
+++ b/drivers/edac/i82443bxgx_edac.c
@@ -114,6 +114,12 @@ struct i82443bxgx_edacmc_error_info {
static struct edac_pci_ctl_info *i82443bxgx_pci;
+static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has
+ * already registered driver
+ */
+
+static int i82443bxgx_registered = 1;
+
static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci,
struct i82443bxgx_edacmc_error_info
*info)
@@ -345,10 +351,17 @@ EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1);
static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ int rc;
+
debugf0("MC: " __FILE__ ": %s()\n", __func__);
/* don't need to call pci_device_enable() */
- return i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
+ rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
+
+ if (mci_pdev == NULL)
+ mci_pdev = pci_dev_get(pdev);
+
+ return rc;
}
static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
@@ -387,15 +400,61 @@ static struct pci_driver i82443bxgx_edacmc_driver = {
static int __init i82443bxgx_edacmc_init(void)
{
+ int pci_rc;
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
- return pci_register_driver(&i82443bxgx_edacmc_driver);
+ pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver);
+ if (pci_rc < 0)
+ goto fail0;
+
+ if (mci_pdev == NULL) {
+ const struct pci_device_id *id = &i82443bxgx_pci_tbl[0];
+ int i = 0;
+ i82443bxgx_registered = 0;
+
+ while (mci_pdev == NULL && id->vendor != 0) {
+ mci_pdev = pci_get_device(id->vendor,
+ id->device, NULL);
+ i++;
+ id = &i82443bxgx_pci_tbl[i];
+ }
+ if (!mci_pdev) {
+ debugf0("i82443bxgx pci_get_device fail\n");
+ pci_rc = -ENODEV;
+ goto fail1;
+ }
+
+ pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl);
+
+ if (pci_rc < 0) {
+ debugf0("i82443bxgx init fail\n");
+ pci_rc = -ENODEV;
+ goto fail1;
+ }
+ }
+
+ return 0;
+
+fail1:
+ pci_unregister_driver(&i82443bxgx_edacmc_driver);
+
+fail0:
+ if (mci_pdev != NULL)
+ pci_dev_put(mci_pdev);
+
+ return pci_rc;
}
static void __exit i82443bxgx_edacmc_exit(void)
{
pci_unregister_driver(&i82443bxgx_edacmc_driver);
+
+ if (!i82443bxgx_registered)
+ i82443bxgx_edacmc_remove_one(mci_pdev);
+
+ if (mci_pdev)
+ pci_dev_put(mci_pdev);
}
module_init(i82443bxgx_edacmc_init);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 2265d9ca153..0cfcb2d075a 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/edac.h>
+#include <linux/smp.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
@@ -40,7 +41,7 @@ static u32 orig_pci_err_en;
#endif
static u32 orig_l2_err_disable;
-static u32 orig_hid1;
+static u32 orig_hid1[2];
/************************ MC SYSFS parts ***********************************/
@@ -647,6 +648,9 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
{
.compatible = "fsl,8568-l2-cache-controller",
},
+ {
+ .compatible = "fsl,mpc8572-l2-cache-controller",
+ },
{},
};
@@ -912,7 +916,8 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
/* register interrupts */
pdata->irq = irq_of_parse_and_map(op->node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_mc_isr, IRQF_DISABLED,
+ mpc85xx_mc_isr,
+ IRQF_DISABLED | IRQF_SHARED,
"[EDAC] MC err", mci);
if (res < 0) {
printk(KERN_ERR "%s: Unable to request irq %d for "
@@ -980,6 +985,9 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
{
.compatible = "fsl,8568-memory-controller",
},
+ {
+ .compatible = "fsl,mpc8572-memory-controller",
+ },
{},
};
@@ -995,6 +1003,14 @@ static struct of_platform_driver mpc85xx_mc_err_driver = {
},
};
+
+static void __init mpc85xx_mc_clear_rfxe(void *data)
+{
+ orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
+ mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000));
+}
+
+
static int __init mpc85xx_mc_init(void)
{
int res = 0;
@@ -1030,19 +1046,22 @@ static int __init mpc85xx_mc_init(void)
* need to clear HID1[RFXE] to disable machine check int
* so we can catch it
*/
- if (edac_op_state == EDAC_OPSTATE_INT) {
- orig_hid1 = mfspr(SPRN_HID1);
- mtspr(SPRN_HID1, (orig_hid1 & ~0x20000));
- }
+ if (edac_op_state == EDAC_OPSTATE_INT)
+ on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
return 0;
}
module_init(mpc85xx_mc_init);
+static void __exit mpc85xx_mc_restore_hid1(void *data)
+{
+ mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
+}
+
static void __exit mpc85xx_mc_exit(void)
{
- mtspr(SPRN_HID1, orig_hid1);
+ on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
#ifdef CONFIG_PCI
of_unregister_platform_driver(&mpc85xx_pci_err_driver);
#endif
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index bbd73a406e5..418c18f07e9 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -189,39 +189,16 @@ static const char gap_count_table[] = {
63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
};
-struct bm_data {
- struct fw_transaction t;
- struct {
- __be32 arg;
- __be32 data;
- } lock;
- u32 old;
- int rcode;
- struct completion done;
-};
-
-static void
-complete_bm_lock(struct fw_card *card, int rcode,
- void *payload, size_t length, void *data)
-{
- struct bm_data *bmd = data;
-
- if (rcode == RCODE_COMPLETE)
- bmd->old = be32_to_cpu(*(__be32 *) payload);
- bmd->rcode = rcode;
- complete(&bmd->done);
-}
-
static void
fw_card_bm_work(struct work_struct *work)
{
struct fw_card *card = container_of(work, struct fw_card, work.work);
struct fw_device *root_device;
struct fw_node *root_node, *local_node;
- struct bm_data bmd;
unsigned long flags;
- int root_id, new_root_id, irm_id, gap_count, generation, grace;
+ int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
bool do_reset = false;
+ __be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags);
local_node = card->local_node;
@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
goto pick_me;
}
- bmd.lock.arg = cpu_to_be32(0x3f);
- bmd.lock.data = cpu_to_be32(local_node->node_id);
+ lock_data[0] = cpu_to_be32(0x3f);
+ lock_data[1] = cpu_to_be32(local_node->node_id);
spin_unlock_irqrestore(&card->lock, flags);
- init_completion(&bmd.done);
- fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
- irm_id, generation,
- SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
- &bmd.lock, sizeof(bmd.lock),
- complete_bm_lock, &bmd);
- wait_for_completion(&bmd.done);
+ rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+ irm_id, generation, SCODE_100,
+ CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
+ lock_data, sizeof(lock_data));
- if (bmd.rcode == RCODE_GENERATION) {
- /*
- * Another bus reset happened. Just return,
- * the BM work has been rescheduled.
- */
+ if (rcode == RCODE_GENERATION)
+ /* Another bus reset, BM work has been rescheduled. */
goto out;
- }
- if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
+ if (rcode == RCODE_COMPLETE &&
+ lock_data[0] != cpu_to_be32(0x3f))
/* Somebody else is BM, let them do the work. */
goto out;
spin_lock_irqsave(&card->lock, flags);
- if (bmd.rcode != RCODE_COMPLETE) {
+
+ if (rcode != RCODE_COMPLETE) {
/*
* The lock request failed, maybe the IRM
* isn't really IRM capable after all. Let's
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 2e6d5848d21..ed03234cbea 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
#define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
#define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
#define GET_SKIP(v) (((v) >> 17) & 0x01)
-#define GET_TAG(v) (((v) >> 18) & 0x02)
-#define GET_SY(v) (((v) >> 20) & 0x04)
+#define GET_TAG(v) (((v) >> 18) & 0x03)
+#define GET_SY(v) (((v) >> 20) & 0x0f)
#define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
static int ioctl_queue_iso(struct client *client, void *buffer)
@@ -913,7 +913,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
return -EFAULT;
}
- return 0;
+ return retval;
}
static long
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 0855fb5568e..3fccdd48410 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = {
__ATTR_NULL,
};
-struct read_quadlet_callback_data {
- struct completion done;
- int rcode;
- u32 data;
-};
-
-static void
-complete_transaction(struct fw_card *card, int rcode,
- void *payload, size_t length, void *data)
-{
- struct read_quadlet_callback_data *callback_data = data;
-
- if (rcode == RCODE_COMPLETE)
- callback_data->data = be32_to_cpu(*(__be32 *)payload);
- callback_data->rcode = rcode;
- complete(&callback_data->done);
-}
-
static int
read_rom(struct fw_device *device, int generation, int index, u32 *data)
{
- struct read_quadlet_callback_data callback_data;
- struct fw_transaction t;
- u64 offset;
+ int rcode;
/* device->node_id, accessed below, must not be older than generation */
smp_rmb();
- init_completion(&callback_data.done);
-
- offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
- fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+ rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
device->node_id, generation, device->max_speed,
- offset, NULL, 4, complete_transaction, &callback_data);
-
- wait_for_completion(&callback_data.done);
-
- *data = callback_data.data;
+ (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
+ data, 4);
+ be32_to_cpus(data);
- return callback_data.rcode;
+ return rcode;
}
#define READ_BIB_ROM_SIZE 256
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index aaff50ebba1..ef0b9b419c2 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -29,6 +29,7 @@
*/
#include <linux/blkdev.h>
+#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
@@ -181,10 +182,16 @@ struct sbp2_target {
#define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */
#define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */
#define SBP2_ORB_NULL 0x80000000
-#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
#define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */
+/*
+ * The default maximum s/g segment size of a FireWire controller is
+ * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
+ * be quadlet-aligned, we set the length limit to 0xffff & ~3.
+ */
+#define SBP2_MAX_SEG_SIZE 0xfffc
+
/* Unit directory keys */
#define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a
#define SBP2_CSR_FIRMWARE_REVISION 0x3c
@@ -621,25 +628,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
return retval;
}
-static void
-complete_agent_reset_write(struct fw_card *card, int rcode,
- void *payload, size_t length, void *done)
-{
- complete(done);
-}
-
static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
{
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- DECLARE_COMPLETION_ONSTACK(done);
- struct fw_transaction t;
- static u32 z;
+ __be32 d = 0;
- fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
- lu->tgt->node_id, lu->generation, device->max_speed,
- lu->command_block_agent_address + SBP2_AGENT_RESET,
- &z, sizeof(z), complete_agent_reset_write, &done);
- wait_for_completion(&done);
+ fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+ lu->tgt->node_id, lu->generation, device->max_speed,
+ lu->command_block_agent_address + SBP2_AGENT_RESET,
+ &d, sizeof(d));
}
static void
@@ -653,7 +650,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
{
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct fw_transaction *t;
- static u32 z;
+ static __be32 d;
t = kmalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL)
@@ -662,7 +659,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed,
lu->command_block_agent_address + SBP2_AGENT_RESET,
- &z, sizeof(z), complete_agent_reset_write_no_wait, t);
+ &d, sizeof(d), complete_agent_reset_write_no_wait, t);
}
static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation)
@@ -823,13 +820,6 @@ static void sbp2_target_put(struct sbp2_target *tgt)
kref_put(&tgt->kref, sbp2_release_target);
}
-static void
-complete_set_busy_timeout(struct fw_card *card, int rcode,
- void *payload, size_t length, void *done)
-{
- complete(done);
-}
-
/*
* Write retransmit retry values into the BUSY_TIMEOUT register.
* - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -849,17 +839,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
{
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- DECLARE_COMPLETION_ONSTACK(done);
- struct fw_transaction t;
- static __be32 busy_timeout;
-
- busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+ __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
- fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
- lu->tgt->node_id, lu->generation, device->max_speed,
- CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout,
- sizeof(busy_timeout), complete_set_busy_timeout, &done);
- wait_for_completion(&done);
+ fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+ lu->tgt->node_id, lu->generation, device->max_speed,
+ CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
+ &d, sizeof(d));
}
static void sbp2_reconnect(struct work_struct *work);
@@ -1121,6 +1106,10 @@ static int sbp2_probe(struct device *dev)
struct Scsi_Host *shost;
u32 model, firmware_revision;
+ if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
+ BUG_ON(dma_set_max_seg_size(device->card->device,
+ SBP2_MAX_SEG_SIZE));
+
shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
if (shost == NULL)
return -ENOMEM;
@@ -1369,14 +1358,12 @@ static int
sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
struct sbp2_logical_unit *lu)
{
- struct scatterlist *sg;
- int sg_len, l, i, j, count;
- dma_addr_t sg_addr;
-
- sg = scsi_sglist(orb->cmd);
- count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
- orb->cmd->sc_data_direction);
- if (count == 0)
+ struct scatterlist *sg = scsi_sglist(orb->cmd);
+ int i, n;
+
+ n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
+ orb->cmd->sc_data_direction);
+ if (n == 0)
goto fail;
/*
@@ -1386,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
* as the second generation iPod which doesn't support page
* tables.
*/
- if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+ if (n == 1) {
orb->request.data_descriptor.high =
cpu_to_be32(lu->tgt->address_high);
orb->request.data_descriptor.low =
@@ -1396,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
return 0;
}
- /*
- * Convert the scatterlist to an sbp2 page table. If any
- * scatterlist entries are too big for sbp2, we split them as we
- * go. Even if we ask the block I/O layer to not give us sg
- * elements larger than 65535 bytes, some IOMMUs may merge sg elements
- * during DMA mapping, and Linux currently doesn't prevent this.
- */
- for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
- sg_len = sg_dma_len(sg);
- sg_addr = sg_dma_address(sg);
- while (sg_len) {
- /* FIXME: This won't get us out of the pinch. */
- if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
- fw_error("page table overflow\n");
- goto fail_page_table;
- }
- l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
- orb->page_table[j].low = cpu_to_be32(sg_addr);
- orb->page_table[j].high = cpu_to_be32(l << 16);
- sg_addr += l;
- sg_len -= l;
- j++;
- }
+ for_each_sg(sg, sg, n, i) {
+ orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
+ orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
}
orb->page_table_bus =
@@ -1437,13 +1404,13 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus);
orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
- COMMAND_ORB_DATA_SIZE(j));
+ COMMAND_ORB_DATA_SIZE(n));
return 0;
fail_page_table:
- dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
- orb->cmd->sc_data_direction);
+ dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
+ scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
fail:
return -ENOMEM;
}
@@ -1456,7 +1423,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_command_orb *orb;
unsigned int max_payload;
- int retval = SCSI_MLQUEUE_HOST_BUSY;
+ int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
/*
* Bidirectional commands are not yet implemented, and unknown
@@ -1500,6 +1467,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
if (cmd->sc_data_direction == DMA_FROM_DEVICE)
orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
+ generation = device->generation;
+ smp_rmb(); /* sbp2_map_scatterlist looks at tgt->address_high */
+
if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
goto out;
@@ -1512,7 +1482,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
if (dma_mapping_error(device->card->device, orb->base.request_bus))
goto out;
- sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation,
+ sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
lu->command_block_agent_address + SBP2_ORB_POINTER);
retval = 0;
out:
@@ -1564,6 +1534,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+ blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
+
return 0;
}
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index e5d1a0b64fc..022ac4fabb6 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
*/
void
fw_send_request(struct fw_card *card, struct fw_transaction *t,
- int tcode, int node_id, int generation, int speed,
+ int tcode, int destination_id, int generation, int speed,
unsigned long long offset,
void *payload, size_t length,
fw_transaction_callback_t callback, void *callback_data)
@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel);
- t->node_id = node_id;
+ t->node_id = destination_id;
t->tlabel = tlabel;
t->callback = callback;
t->callback_data = callback_data;
- fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
- generation, speed, offset, payload, length);
+ fw_fill_request(&t->packet, tcode, t->tlabel,
+ destination_id, card->node_id, generation,
+ speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
list_add_tail(&t->link, &card->transaction_list);
@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
}
EXPORT_SYMBOL(fw_send_request);
+struct transaction_callback_data {
+ struct completion done;
+ void *payload;
+ int rcode;
+};
+
+static void transaction_callback(struct fw_card *card, int rcode,
+ void *payload, size_t length, void *data)
+{
+ struct transaction_callback_data *d = data;
+
+ if (rcode == RCODE_COMPLETE)
+ memcpy(d->payload, payload, length);
+ d->rcode = rcode;
+ complete(&d->done);
+}
+
+/**
+ * fw_run_transaction - send request and sleep until transaction is completed
+ *
+ * Returns the RCODE.
+ */
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+ int generation, int speed, unsigned long long offset,
+ void *data, size_t length)
+{
+ struct transaction_callback_data d;
+ struct fw_transaction t;
+
+ init_completion(&d.done);
+ d.payload = data;
+ fw_send_request(card, &t, tcode, destination_id, generation, speed,
+ offset, data, length, transaction_callback, &d);
+ wait_for_completion(&d.done);
+
+ return d.rcode;
+}
+EXPORT_SYMBOL(fw_run_transaction);
+
static DEFINE_MUTEX(phy_config_mutex);
static DECLARE_COMPLETION(phy_config_done);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 2ae1b0d6cb7..027f58ce81a 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
void
fw_send_request(struct fw_card *card, struct fw_transaction *t,
- int tcode, int node_id, int generation, int speed,
- unsigned long long offset,
- void *data, size_t length,
+ int tcode, int destination_id, int generation, int speed,
+ unsigned long long offset, void *data, size_t length,
fw_transaction_callback_t callback, void *callback_data);
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+ int generation, int speed, unsigned long long offset,
+ void *data, size_t length);
+
int fw_cancel_transaction(struct fw_card *card,
struct fw_transaction *transaction);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 455575be356..3e526b6d00c 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -15,6 +15,11 @@
*/
static char dmi_empty_string[] = " ";
+/*
+ * Catch too early calls to dmi_check_system():
+ */
+static int dmi_initialized;
+
static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
{
const u8 *bp = ((u8 *) dm) + dm->length;
@@ -366,7 +371,7 @@ void __init dmi_scan_machine(void)
if (efi_enabled) {
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
- goto out;
+ goto error;
/* This is called as a core_initcall() because it isn't
* needed during early boot. This also means we can
@@ -374,13 +379,13 @@ void __init dmi_scan_machine(void)
*/
p = dmi_ioremap(efi.smbios, 32);
if (p == NULL)
- goto out;
+ goto error;
rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
dmi_iounmap(p, 32);
if (!rc) {
dmi_available = 1;
- return;
+ goto out;
}
}
else {
@@ -391,19 +396,22 @@ void __init dmi_scan_machine(void)
*/
p = dmi_ioremap(0xF0000, 0x10000);
if (p == NULL)
- goto out;
+ goto error;
for (q = p; q < p + 0x10000; q += 16) {
rc = dmi_present(q);
if (!rc) {
dmi_available = 1;
dmi_iounmap(p, 0x10000);
- return;
+ goto out;
}
}
dmi_iounmap(p, 0x10000);
}
- out: printk(KERN_INFO "DMI not present or invalid.\n");
+ error:
+ printk(KERN_INFO "DMI not present or invalid.\n");
+ out:
+ dmi_initialized = 1;
}
/**
@@ -424,6 +432,8 @@ int dmi_check_system(const struct dmi_system_id *list)
int i, count = 0;
const struct dmi_system_id *d = list;
+ WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+
while (d->ident) {
for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
int s = d->matches[i].slot;
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 8024e3bfd87..deb154aa47c 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -334,9 +334,9 @@ static void ibft_release(struct kobject *kobj)
/*
* Routines for parsing the iBFT data to be human readable.
*/
-ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
- struct ibft_attribute *attr,
- char *buf)
+static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+ struct ibft_attribute *attr,
+ char *buf)
{
struct ibft_initiator *initiator = entry->initiator;
void *ibft_loc = entry->header;
@@ -376,9 +376,9 @@ ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
return str - buf;
}
-ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
- struct ibft_attribute *attr,
- char *buf)
+static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+ struct ibft_attribute *attr,
+ char *buf)
{
struct ibft_nic *nic = entry->nic;
void *ibft_loc = entry->header;
@@ -440,9 +440,9 @@ ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
return str - buf;
};
-ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
- struct ibft_attribute *attr,
- char *buf)
+static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+ struct ibft_attribute *attr,
+ char *buf)
{
struct ibft_tgt *tgt = entry->tgt;
void *ibft_loc = entry->header;
@@ -669,8 +669,7 @@ static int __init ibft_register_kobjects(struct ibft_table_header *header,
control = (void *)header + sizeof(*header);
end = (void *)control + control->hdr.length;
- eot_offset = (void *)header + header->length -
- (void *)control - sizeof(*header);
+ eot_offset = (void *)header + header->length - (void *)control;
rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
sizeof(*control));
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8d2940517c9..9112830107a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -67,17 +67,28 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
* when setting direction, and otherwise illegal. Until board setup code
* and drivers use explicit requests everywhere (which won't happen when
* those calls have no teeth) we can't avoid autorequesting. This nag
- * message should motivate switching to explicit requests...
+ * message should motivate switching to explicit requests... so should
+ * the weaker cleanup after faults, compared to gpio_request().
*/
-static void gpio_ensure_requested(struct gpio_desc *desc)
+static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
{
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
- pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
+ struct gpio_chip *chip = desc->chip;
+ int gpio = chip->base + offset;
+
+ if (!try_module_get(chip->owner)) {
+ pr_err("GPIO-%d: module can't be gotten \n", gpio);
+ clear_bit(FLAG_REQUESTED, &desc->flags);
+ /* lose */
+ return -EIO;
+ }
+ pr_warning("GPIO-%d autorequested\n", gpio);
desc_set_label(desc, "[auto]");
- if (!try_module_get(desc->chip->owner))
- pr_err("GPIO-%d: module can't be gotten \n",
- (int)(desc - gpio_desc));
+ /* caller must chip->request() w/o spinlock */
+ if (chip->request)
+ return 1;
}
+ return 0;
}
/* caller holds gpio_lock *OR* gpio is marked as requested */
@@ -752,6 +763,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
int gpio_request(unsigned gpio, const char *label)
{
struct gpio_desc *desc;
+ struct gpio_chip *chip;
int status = -EINVAL;
unsigned long flags;
@@ -760,14 +772,15 @@ int gpio_request(unsigned gpio, const char *label)
if (!gpio_is_valid(gpio))
goto done;
desc = &gpio_desc[gpio];
- if (desc->chip == NULL)
+ chip = desc->chip;
+ if (chip == NULL)
goto done;
- if (!try_module_get(desc->chip->owner))
+ if (!try_module_get(chip->owner))
goto done;
/* NOTE: gpio_request() can be called in early boot,
- * before IRQs are enabled.
+ * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
*/
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
@@ -775,7 +788,20 @@ int gpio_request(unsigned gpio, const char *label)
status = 0;
} else {
status = -EBUSY;
- module_put(desc->chip->owner);
+ module_put(chip->owner);
+ }
+
+ if (chip->request) {
+ /* chip->request may sleep */
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ status = chip->request(chip, gpio - chip->base);
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ if (status < 0) {
+ desc_set_label(desc, NULL);
+ module_put(chip->owner);
+ clear_bit(FLAG_REQUESTED, &desc->flags);
+ }
}
done:
@@ -791,6 +817,9 @@ void gpio_free(unsigned gpio)
{
unsigned long flags;
struct gpio_desc *desc;
+ struct gpio_chip *chip;
+
+ might_sleep();
if (!gpio_is_valid(gpio)) {
WARN_ON(extra_checks);
@@ -802,9 +831,17 @@ void gpio_free(unsigned gpio)
spin_lock_irqsave(&gpio_lock, flags);
desc = &gpio_desc[gpio];
- if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
+ chip = desc->chip;
+ if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
+ if (chip->free) {
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ might_sleep_if(extra_checks && chip->can_sleep);
+ chip->free(chip, gpio - chip->base);
+ spin_lock_irqsave(&gpio_lock, flags);
+ }
desc_set_label(desc, NULL);
module_put(desc->chip->owner);
+ clear_bit(FLAG_REQUESTED, &desc->flags);
} else
WARN_ON(extra_checks);
@@ -869,7 +906,9 @@ int gpio_direction_input(unsigned gpio)
gpio -= chip->base;
if (gpio >= chip->ngpio)
goto fail;
- gpio_ensure_requested(desc);
+ status = gpio_ensure_requested(desc, gpio);
+ if (status < 0)
+ goto fail;
/* now we know the gpio is valid and chip won't vanish */
@@ -877,9 +916,22 @@ int gpio_direction_input(unsigned gpio)
might_sleep_if(extra_checks && chip->can_sleep);
+ if (status) {
+ status = chip->request(chip, gpio);
+ if (status < 0) {
+ pr_debug("GPIO-%d: chip request fail, %d\n",
+ chip->base + gpio, status);
+ /* and it's not available to anyone else ...
+ * gpio_request() is the fully clean solution.
+ */
+ goto lose;
+ }
+ }
+
status = chip->direction_input(chip, gpio);
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
+lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
@@ -907,7 +959,9 @@ int gpio_direction_output(unsigned gpio, int value)
gpio -= chip->base;
if (gpio >= chip->ngpio)
goto fail;
- gpio_ensure_requested(desc);
+ status = gpio_ensure_requested(desc, gpio);
+ if (status < 0)
+ goto fail;
/* now we know the gpio is valid and chip won't vanish */
@@ -915,9 +969,22 @@ int gpio_direction_output(unsigned gpio, int value)
might_sleep_if(extra_checks && chip->can_sleep);
+ if (status) {
+ status = chip->request(chip, gpio);
+ if (status < 0) {
+ pr_debug("GPIO-%d: chip request fail, %d\n",
+ chip->base + gpio, status);
+ /* and it's not available to anyone else ...
+ * gpio_request() is the fully clean solution.
+ */
+ goto lose;
+ }
+ }
+
status = chip->direction_output(chip, gpio, value);
if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags);
+lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
@@ -1008,6 +1075,24 @@ int __gpio_cansleep(unsigned gpio)
}
EXPORT_SYMBOL_GPL(__gpio_cansleep);
+/**
+ * __gpio_to_irq() - return the IRQ corresponding to a GPIO
+ * @gpio: gpio whose IRQ will be returned (already requested)
+ * Context: any
+ *
+ * This is used directly or indirectly to implement gpio_to_irq().
+ * It returns the number of the IRQ signaled by this (input) GPIO,
+ * or a negative errno.
+ */
+int __gpio_to_irq(unsigned gpio)
+{
+ struct gpio_chip *chip;
+
+ chip = gpio_to_chip(gpio);
+ return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
+}
+EXPORT_SYMBOL_GPL(__gpio_to_irq);
+
/* There's no value in making it easy to inline GPIO calls that may sleep.
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
index 39c795ad831..8b24d784db9 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/max7301.c
@@ -255,10 +255,6 @@ static int __devinit max7301_probe(struct spi_device *spi)
ts->chip.dev = &spi->dev;
ts->chip.owner = THIS_MODULE;
- ret = gpiochip_add(&ts->chip);
- if (ret)
- goto exit_destroy;
-
/*
* tristate all pins in hardware and cache the
* register values for later use.
@@ -269,17 +265,19 @@ static int __devinit max7301_probe(struct spi_device *spi)
max7301_write(spi, 0x08 + i, 0xAA);
ts->port_config[i] = 0xAA;
for (j = 0; j < 4; j++) {
- int idx = ts->chip.base + (i - 1) * 4 + j;
- ret = gpio_direction_input(idx);
+ int offset = (i - 1) * 4 + j;
+ ret = max7301_direction_input(&ts->chip, offset);
if (ret)
- goto exit_remove;
- gpio_free(idx);
+ goto exit_destroy;
}
}
+
+ ret = gpiochip_add(&ts->chip);
+ if (ret)
+ goto exit_destroy;
+
return ret;
-exit_remove:
- gpiochip_remove(&ts->chip);
exit_destroy:
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&ts->lock);
@@ -325,13 +323,15 @@ static int __init max7301_init(void)
{
return spi_register_driver(&max7301_driver);
}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max7301_init);
static void __exit max7301_exit(void)
{
spi_unregister_driver(&max7301_driver);
}
-
-module_init(max7301_init);
module_exit(max7301_exit);
MODULE_AUTHOR("Juergen Beisert");
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
index b51c8135ca2..55ae9a41897 100644
--- a/drivers/gpio/max732x.c
+++ b/drivers/gpio/max732x.c
@@ -372,7 +372,10 @@ static int __init max732x_init(void)
{
return i2c_add_driver(&max732x_driver);
}
-module_init(max732x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max732x_init);
static void __exit max732x_exit(void)
{
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 8a1b405fefd..89c1d222e9d 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -419,7 +419,10 @@ static int __init mcp23s08_init(void)
{
return spi_register_driver(&mcp23s08_driver);
}
-module_init(mcp23s08_init);
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mcp23s08_init);
static void __exit mcp23s08_exit(void)
{
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index cc8468692ae..9ceeb89f132 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -289,7 +289,10 @@ static int __init pca953x_init(void)
{
return i2c_add_driver(&pca953x_driver);
}
-module_init(pca953x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pca953x_init);
static void __exit pca953x_exit(void)
{
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index fc9c6ae739e..4bc2070dd4a 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -351,7 +351,10 @@ static int __init pcf857x_init(void)
{
return i2c_add_driver(&pcf857x_driver);
}
-module_init(pcf857x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pcf857x_init);
static void __exit pcf857x_exit(void)
{
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 610d6fd5bb5..9097500de5f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -6,7 +6,7 @@
#
menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
- depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
+ depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && SHMEM
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
@@ -87,6 +87,7 @@ config DRM_MGA
config DRM_SIS
tristate "SiS video cards"
depends on DRM && AGP
+ depends on FB_SIS || FB_SIS=n
help
Choose this option if you have a SiS 630 or compatible video
chipset. If M is selected the module will be called sis. AGP
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e9f9a97ae00..74da99495e2 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -4,8 +4,9 @@
ccflags-y := -Iinclude/drm
-drm-y := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
- drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
+drm-y := drm_auth.o drm_bufs.o drm_cache.o \
+ drm_context.o drm_dma.o drm_drawable.o \
+ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index aefa5ac4c0b..3d33b8252b5 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -33,6 +33,7 @@
#include "drmP.h"
#include <linux/module.h>
+#include <asm/agp.h>
#if __OS_HAS_AGP
@@ -452,4 +453,53 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
return agp_unbind_memory(handle);
}
-#endif /* __OS_HAS_AGP */
+/**
+ * Binds a collection of pages into AGP memory at the given offset, returning
+ * the AGP memory structure containing them.
+ *
+ * No reference is held on the pages during this time -- it is up to the
+ * caller to handle that.
+ */
+DRM_AGP_MEM *
+drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ u32 type)
+{
+ DRM_AGP_MEM *mem;
+ int ret, i;
+
+ DRM_DEBUG("\n");
+
+ mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages,
+ type);
+ if (mem == NULL) {
+ DRM_ERROR("Failed to allocate memory for %ld pages\n",
+ num_pages);
+ return NULL;
+ }
+
+ for (i = 0; i < num_pages; i++)
+ mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
+ mem->page_count = num_pages;
+
+ mem->is_flushed = true;
+ ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
+ if (ret != 0) {
+ DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
+ agp_free_memory(mem);
+ return NULL;
+ }
+
+ return mem;
+}
+EXPORT_SYMBOL(drm_agp_bind_pages);
+
+void drm_agp_chipset_flush(struct drm_device *dev)
+{
+ agp_flush_chipset(dev->agp->bridge);
+}
+EXPORT_SYMBOL(drm_agp_chipset_flush);
+
+#endif /* __OS_HAS_AGP */
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
new file mode 100644
index 00000000000..0e994a0e46d
--- /dev/null
+++ b/drivers/gpu/drm/drm_cache.c
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+
+#if defined(CONFIG_X86)
+static void
+drm_clflush_page(struct page *page)
+{
+ uint8_t *page_virtual;
+ unsigned int i;
+
+ if (unlikely(page == NULL))
+ return;
+
+ page_virtual = kmap_atomic(page, KM_USER0);
+ for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+ clflush(page_virtual + i);
+ kunmap_atomic(page_virtual, KM_USER0);
+}
+#endif
+
+void
+drm_clflush_pages(struct page *pages[], unsigned long num_pages)
+{
+
+#if defined(CONFIG_X86)
+ if (cpu_has_clflush) {
+ unsigned long i;
+
+ mb();
+ for (i = 0; i < num_pages; ++i)
+ drm_clflush_page(*pages++);
+ mb();
+
+ return;
+ }
+
+ wbinvd();
+#endif
+}
+EXPORT_SYMBOL(drm_clflush_pages);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 452c2d866ec..96f416afc3f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -116,7 +116,13 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+
DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 851a53f1acc..0d46627663b 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -246,7 +246,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
memset(priv, 0, sizeof(*priv));
filp->private_data = priv;
priv->filp = filp;
- priv->uid = current->euid;
+ priv->uid = current_euid();
priv->pid = task_pid_nr(current);
priv->minor = idr_find(&drm_minors_idr, minor_id);
priv->ioctl_count = 0;
@@ -256,6 +256,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
INIT_LIST_HEAD(&priv->lhead);
+ if (dev->driver->driver_features & DRIVER_GEM)
+ drm_gem_open(dev, priv);
+
if (dev->driver->open) {
ret = dev->driver->open(dev, priv);
if (ret < 0)
@@ -400,6 +403,9 @@ int drm_release(struct inode *inode, struct file *filp)
dev->driver->reclaim_buffers(dev, file_priv);
}
+ if (dev->driver->driver_features & DRIVER_GEM)
+ drm_gem_release(dev, file_priv);
+
drm_fasync(-1, filp, 0);
mutex_lock(&dev->ctxlist_mutex);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
new file mode 100644
index 00000000000..ccd1afdede0
--- /dev/null
+++ b/drivers/gpu/drm/drm_gem.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include "drmP.h"
+
+/** @file drm_gem.c
+ *
+ * This file provides some of the base ioctls and library routines for
+ * the graphics memory manager implemented by each device driver.
+ *
+ * Because various devices have different requirements in terms of
+ * synchronization and migration strategies, implementing that is left up to
+ * the driver, and all that the general API provides should be generic --
+ * allocating objects, reading/writing data with the cpu, freeing objects.
+ * Even there, platform-dependent optimizations for reading/writing data with
+ * the CPU mean we'll likely hook those out to driver-specific calls. However,
+ * the DRI2 implementation wants to have at least allocate/mmap be generic.
+ *
+ * The goal was to have swap-backed object allocation managed through
+ * struct file. However, file descriptors as handles to a struct file have
+ * two major failings:
+ * - Process limits prevent more than 1024 or so being used at a time by
+ * default.
+ * - Inability to allocate high fds will aggravate the X Server's select()
+ * handling, and likely that of many GL client applications as well.
+ *
+ * This led to a plan of using our own integer IDs (called handles, following
+ * DRM terminology) to mimic fds, and implement the fd syscalls we need as
+ * ioctls. The objects themselves will still include the struct file so
+ * that we can transition to fds if the required kernel infrastructure shows
+ * up at a later date, and as our interface with shmfs for memory allocation.
+ */
+
+/**
+ * Initialize the GEM device fields
+ */
+
+int
+drm_gem_init(struct drm_device *dev)
+{
+ spin_lock_init(&dev->object_name_lock);
+ idr_init(&dev->object_name_idr);
+ atomic_set(&dev->object_count, 0);
+ atomic_set(&dev->object_memory, 0);
+ atomic_set(&dev->pin_count, 0);
+ atomic_set(&dev->pin_memory, 0);
+ atomic_set(&dev->gtt_count, 0);
+ atomic_set(&dev->gtt_memory, 0);
+ return 0;
+}
+
+/**
+ * Allocate a GEM object of the specified size with shmfs backing store
+ */
+struct drm_gem_object *
+drm_gem_object_alloc(struct drm_device *dev, size_t size)
+{
+ struct drm_gem_object *obj;
+
+ BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+ obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
+
+ obj->dev = dev;
+ obj->filp = shmem_file_setup("drm mm object", size, 0);
+ if (IS_ERR(obj->filp)) {
+ kfree(obj);
+ return NULL;
+ }
+
+ kref_init(&obj->refcount);
+ kref_init(&obj->handlecount);
+ obj->size = size;
+ if (dev->driver->gem_init_object != NULL &&
+ dev->driver->gem_init_object(obj) != 0) {
+ fput(obj->filp);
+ kfree(obj);
+ return NULL;
+ }
+ atomic_inc(&dev->object_count);
+ atomic_add(obj->size, &dev->object_memory);
+ return obj;
+}
+EXPORT_SYMBOL(drm_gem_object_alloc);
+
+/**
+ * Removes the mapping from handle to filp for this object.
+ */
+static int
+drm_gem_handle_delete(struct drm_file *filp, int handle)
+{
+ struct drm_device *dev;
+ struct drm_gem_object *obj;
+
+ /* This is gross. The idr system doesn't let us try a delete and
+ * return an error code. It just spews if you fail at deleting.
+ * So, we have to grab a lock around finding the object and then
+ * doing the delete on it and dropping the refcount, or the user
+ * could race us to double-decrement the refcount and cause a
+ * use-after-free later. Given the frequency of our handle lookups,
+ * we may want to use ida for number allocation and a hash table
+ * for the pointers, anyway.
+ */
+ spin_lock(&filp->table_lock);
+
+ /* Check if we currently have a reference on the object */
+ obj = idr_find(&filp->object_idr, handle);
+ if (obj == NULL) {
+ spin_unlock(&filp->table_lock);
+ return -EINVAL;
+ }
+ dev = obj->dev;
+
+ /* Release reference and decrement refcount. */
+ idr_remove(&filp->object_idr, handle);
+ spin_unlock(&filp->table_lock);
+
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_handle_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+/**
+ * Create a handle for this object. This adds a handle reference
+ * to the object, which includes a regular reference count. Callers
+ * will likely want to dereference the object afterwards.
+ */
+int
+drm_gem_handle_create(struct drm_file *file_priv,
+ struct drm_gem_object *obj,
+ int *handlep)
+{
+ int ret;
+
+ /*
+ * Get the user-visible handle using idr.
+ */
+again:
+ /* ensure there is space available to allocate a handle */
+ if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+
+ /* do the allocation under our spinlock */
+ spin_lock(&file_priv->table_lock);
+ ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
+ spin_unlock(&file_priv->table_lock);
+ if (ret == -EAGAIN)
+ goto again;
+
+ if (ret != 0)
+ return ret;
+
+ drm_gem_object_handle_reference(obj);
+ return 0;
+}
+EXPORT_SYMBOL(drm_gem_handle_create);
+
+/** Returns a reference to the object named by the handle. */
+struct drm_gem_object *
+drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
+ int handle)
+{
+ struct drm_gem_object *obj;
+
+ spin_lock(&filp->table_lock);
+
+ /* Check if we currently have a reference on the object */
+ obj = idr_find(&filp->object_idr, handle);
+ if (obj == NULL) {
+ spin_unlock(&filp->table_lock);
+ return NULL;
+ }
+
+ drm_gem_object_reference(obj);
+
+ spin_unlock(&filp->table_lock);
+
+ return obj;
+}
+EXPORT_SYMBOL(drm_gem_object_lookup);
+
+/**
+ * Releases the handle to an mm object.
+ */
+int
+drm_gem_close_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_gem_close *args = data;
+ int ret;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ ret = drm_gem_handle_delete(file_priv, args->handle);
+
+ return ret;
+}
+
+/**
+ * Create a global name for an object, returning the name.
+ *
+ * Note that the name does not hold a reference; when the object
+ * is freed, the name goes away.
+ */
+int
+drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_gem_flink *args = data;
+ struct drm_gem_object *obj;
+ int ret;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EBADF;
+
+again:
+ if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+
+ spin_lock(&dev->object_name_lock);
+ if (obj->name) {
+ args->name = obj->name;
+ spin_unlock(&dev->object_name_lock);
+ return 0;
+ }
+ ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+ &obj->name);
+ spin_unlock(&dev->object_name_lock);
+ if (ret == -EAGAIN)
+ goto again;
+
+ if (ret != 0) {
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+
+ /*
+ * Leave the reference from the lookup around as the
+ * name table now holds one
+ */
+ args->name = (uint64_t) obj->name;
+
+ return 0;
+}
+
+/**
+ * Open an object using the global name, returning a handle and the size.
+ *
+ * This handle (of course) holds a reference to the object, so the object
+ * will not go away until the handle is deleted.
+ */
+int
+drm_gem_open_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_gem_open *args = data;
+ struct drm_gem_object *obj;
+ int ret;
+ int handle;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ spin_lock(&dev->object_name_lock);
+ obj = idr_find(&dev->object_name_idr, (int) args->name);
+ if (obj)
+ drm_gem_object_reference(obj);
+ spin_unlock(&dev->object_name_lock);
+ if (!obj)
+ return -ENOENT;
+
+ ret = drm_gem_handle_create(file_priv, obj, &handle);
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ args->handle = handle;
+ args->size = obj->size;
+
+ return 0;
+}
+
+/**
+ * Called at device open time, sets up the structure for handling refcounting
+ * of mm objects.
+ */
+void
+drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
+{
+ idr_init(&file_private->object_idr);
+ spin_lock_init(&file_private->table_lock);
+}
+
+/**
+ * Called at device close to release the file's
+ * handle references on objects.
+ */
+static int
+drm_gem_object_release_handle(int id, void *ptr, void *data)
+{
+ struct drm_gem_object *obj = ptr;
+
+ drm_gem_object_handle_unreference(obj);
+
+ return 0;
+}
+
+/**
+ * Called at close time when the filp is going away.
+ *
+ * Releases any remaining references on objects by this filp.
+ */
+void
+drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
+{
+ mutex_lock(&dev->struct_mutex);
+ idr_for_each(&file_private->object_idr,
+ &drm_gem_object_release_handle, NULL);
+
+ idr_destroy(&file_private->object_idr);
+ mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * Called after the last reference to the object has been lost.
+ *
+ * Frees the object
+ */
+void
+drm_gem_object_free(struct kref *kref)
+{
+ struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+ struct drm_device *dev = obj->dev;
+
+ BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ if (dev->driver->gem_free_object != NULL)
+ dev->driver->gem_free_object(obj);
+
+ fput(obj->filp);
+ atomic_dec(&dev->object_count);
+ atomic_sub(obj->size, &dev->object_memory);
+ kfree(obj);
+}
+EXPORT_SYMBOL(drm_gem_object_free);
+
+/**
+ * Called after the last handle to the object has been closed
+ *
+ * Removes any name for the object. Note that this must be
+ * called before drm_gem_object_free or we'll be touching
+ * freed memory
+ */
+void
+drm_gem_object_handle_free(struct kref *kref)
+{
+ struct drm_gem_object *obj = container_of(kref,
+ struct drm_gem_object,
+ handlecount);
+ struct drm_device *dev = obj->dev;
+
+ /* Remove any name for this object */
+ spin_lock(&dev->object_name_lock);
+ if (obj->name) {
+ idr_remove(&dev->object_name_idr, obj->name);
+ spin_unlock(&dev->object_name_lock);
+ /*
+ * The object name held a reference to this object, drop
+ * that now.
+ */
+ drm_gem_object_unreference(obj);
+ } else
+ spin_unlock(&dev->object_name_lock);
+
+}
+EXPORT_SYMBOL(drm_gem_object_handle_free);
+
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 53f0e5af1cc..4091b9e291f 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -63,7 +63,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
return -EINVAL;
- p->irq = dev->irq;
+ p->irq = dev->pdev->irq;
DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
p->irq);
@@ -71,25 +71,137 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
return 0;
}
+static void vblank_disable_fn(unsigned long arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ unsigned long irqflags;
+ int i;
+
+ if (!dev->vblank_disable_allowed)
+ return;
+
+ for (i = 0; i < dev->num_crtcs; i++) {
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+ dev->vblank_enabled[i]) {
+ DRM_DEBUG("disabling vblank on crtc %d\n", i);
+ dev->last_vblank[i] =
+ dev->driver->get_vblank_counter(dev, i);
+ dev->driver->disable_vblank(dev, i);
+ dev->vblank_enabled[i] = 0;
+ }
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ }
+}
+
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+ /* Bail if the driver didn't call drm_vblank_init() */
+ if (dev->num_crtcs == 0)
+ return;
+
+ del_timer(&dev->vblank_disable_timer);
+
+ vblank_disable_fn((unsigned long)dev);
+
+ drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+
+ dev->num_crtcs = 0;
+}
+
+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+ int i, ret = -ENOMEM;
+
+ setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
+ (unsigned long)dev);
+ spin_lock_init(&dev->vbl_lock);
+ atomic_set(&dev->vbl_signal_pending, 0);
+ dev->num_crtcs = num_crtcs;
+
+ dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vbl_queue)
+ goto err;
+
+ dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vbl_sigs)
+ goto err;
+
+ dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->_vblank_count)
+ goto err;
+
+ dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_refcount)
+ goto err;
+
+ dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_enabled)
+ goto err;
+
+ dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+ if (!dev->last_vblank)
+ goto err;
+
+ dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_inmodeset)
+ goto err;
+
+ /* Zero per-crtc vblank stuff */
+ for (i = 0; i < num_crtcs; i++) {
+ init_waitqueue_head(&dev->vbl_queue[i]);
+ INIT_LIST_HEAD(&dev->vbl_sigs[i]);
+ atomic_set(&dev->_vblank_count[i], 0);
+ atomic_set(&dev->vblank_refcount[i], 0);
+ }
+
+ dev->vblank_disable_allowed = 0;
+
+ return 0;
+
+err:
+ drm_vblank_cleanup(dev);
+ return ret;
+}
+EXPORT_SYMBOL(drm_vblank_init);
+
/**
* Install IRQ handler.
*
* \param dev DRM device.
- * \param irq IRQ number.
*
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * Initializes the IRQ related data. Installs the handler, calling the driver
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
* before and after the installation.
*/
-static int drm_irq_install(struct drm_device * dev)
+int drm_irq_install(struct drm_device *dev)
{
- int ret;
+ int ret = 0;
unsigned long sh_flags = 0;
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
- if (dev->irq == 0)
+ if (dev->pdev->irq == 0)
return -EINVAL;
mutex_lock(&dev->struct_mutex);
@@ -107,18 +219,7 @@ static int drm_irq_install(struct drm_device * dev)
dev->irq_enabled = 1;
mutex_unlock(&dev->struct_mutex);
- DRM_DEBUG("irq=%d\n", dev->irq);
-
- if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
- init_waitqueue_head(&dev->vbl_queue);
-
- spin_lock_init(&dev->vbl_lock);
-
- INIT_LIST_HEAD(&dev->vbl_sigs);
- INIT_LIST_HEAD(&dev->vbl_sigs2);
-
- dev->vbl_pending = 0;
- }
+ DRM_DEBUG("irq=%d\n", dev->pdev->irq);
/* Before installing handler */
dev->driver->irq_preinstall(dev);
@@ -127,8 +228,9 @@ static int drm_irq_install(struct drm_device * dev)
if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
sh_flags = IRQF_SHARED;
- ret = request_irq(dev->irq, dev->driver->irq_handler,
+ ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler,
sh_flags, dev->devname, dev);
+
if (ret < 0) {
mutex_lock(&dev->struct_mutex);
dev->irq_enabled = 0;
@@ -137,10 +239,16 @@ static int drm_irq_install(struct drm_device * dev)
}
/* After installing handler */
- dev->driver->irq_postinstall(dev);
+ ret = dev->driver->irq_postinstall(dev);
+ if (ret < 0) {
+ mutex_lock(&dev->struct_mutex);
+ dev->irq_enabled = 0;
+ mutex_unlock(&dev->struct_mutex);
+ }
- return 0;
+ return ret;
}
+EXPORT_SYMBOL(drm_irq_install);
/**
* Uninstall the IRQ handler.
@@ -164,17 +272,18 @@ int drm_irq_uninstall(struct drm_device * dev)
if (!irq_enabled)
return -EINVAL;
- DRM_DEBUG("irq=%d\n", dev->irq);
+ DRM_DEBUG("irq=%d\n", dev->pdev->irq);
dev->driver->irq_uninstall(dev);
- free_irq(dev->irq, dev);
+ free_irq(dev->pdev->irq, dev);
+
+ drm_vblank_cleanup(dev);
dev->locked_tasklet_func = NULL;
return 0;
}
-
EXPORT_SYMBOL(drm_irq_uninstall);
/**
@@ -201,7 +310,7 @@ int drm_control(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
- ctl->irq != dev->irq)
+ ctl->irq != dev->pdev->irq)
return -EINVAL;
return drm_irq_install(dev);
case DRM_UNINST_HANDLER:
@@ -214,6 +323,174 @@ int drm_control(struct drm_device *dev, void *data,
}
/**
+ * drm_vblank_count - retrieve "cooked" vblank counter value
+ * @dev: DRM device
+ * @crtc: which counter to retrieve
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity.
+ */
+u32 drm_vblank_count(struct drm_device *dev, int crtc)
+{
+ return atomic_read(&dev->_vblank_count[crtc]);
+}
+EXPORT_SYMBOL(drm_vblank_count);
+
+/**
+ * drm_update_vblank_count - update the master vblank counter
+ * @dev: DRM device
+ * @crtc: counter to update
+ *
+ * Call back into the driver to update the appropriate vblank counter
+ * (specified by @crtc). Deal with wraparound, if it occurred, and
+ * update the last read value so we can deal with wraparound on the next
+ * call if necessary.
+ *
+ * Only necessary when going from off->on, to account for frames we
+ * didn't get an interrupt for.
+ *
+ * Note: caller must hold dev->vbl_lock since this reads & writes
+ * device vblank fields.
+ */
+static void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+ u32 cur_vblank, diff;
+
+ /*
+ * Interrupts were disabled prior to this call, so deal with counter
+ * wrap if needed.
+ * NOTE! It's possible we lost a full dev->max_vblank_count events
+ * here if the register is small or we had vblank interrupts off for
+ * a long time.
+ */
+ cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+ diff = cur_vblank - dev->last_vblank[crtc];
+ if (cur_vblank < dev->last_vblank[crtc]) {
+ diff += dev->max_vblank_count;
+
+ DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
+ crtc, dev->last_vblank[crtc], cur_vblank, diff);
+ }
+
+ DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
+ crtc, diff);
+
+ atomic_add(diff, &dev->_vblank_count[crtc]);
+}
+
+/**
+ * drm_vblank_get - get a reference count on vblank events
+ * @dev: DRM device
+ * @crtc: which CRTC to own
+ *
+ * Acquire a reference count on vblank events to avoid having them disabled
+ * while in use.
+ *
+ * RETURNS
+ * Zero on success, nonzero on failure.
+ */
+int drm_vblank_get(struct drm_device *dev, int crtc)
+{
+ unsigned long irqflags;
+ int ret = 0;
+
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ /* Going from 0->1 means we have to enable interrupts again */
+ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
+ !dev->vblank_enabled[crtc]) {
+ ret = dev->driver->enable_vblank(dev, crtc);
+ DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+ if (ret)
+ atomic_dec(&dev->vblank_refcount[crtc]);
+ else {
+ dev->vblank_enabled[crtc] = 1;
+ drm_update_vblank_count(dev, crtc);
+ }
+ }
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_vblank_get);
+
+/**
+ * drm_vblank_put - give up ownership of vblank events
+ * @dev: DRM device
+ * @crtc: which counter to give up
+ *
+ * Release ownership of a given vblank counter, turning off interrupts
+ * if possible.
+ */
+void drm_vblank_put(struct drm_device *dev, int crtc)
+{
+ /* Last user schedules interrupt disable */
+ if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
+ mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
+}
+EXPORT_SYMBOL(drm_vblank_put);
+
+/**
+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
+ * @DRM_IOCTL_ARGS: standard ioctl arguments
+ *
+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
+ * ioctls around modesetting so that any lost vblank events are accounted for.
+ *
+ * Generally the counter will reset across mode sets. If interrupts are
+ * enabled around this call, we don't have to do anything since the counter
+ * will have already been incremented.
+ */
+int drm_modeset_ctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_modeset_ctl *modeset = data;
+ unsigned long irqflags;
+ int crtc, ret = 0;
+
+ /* If drm_vblank_init() hasn't been called yet, just no-op */
+ if (!dev->num_crtcs)
+ goto out;
+
+ crtc = modeset->crtc;
+ if (crtc >= dev->num_crtcs) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * To avoid all the problems that might happen if interrupts
+ * were enabled/disabled around or between these calls, we just
+ * have the kernel take a reference on the CRTC (just once though
+ * to avoid corrupting the count if multiple, mismatch calls occur),
+ * so that interrupts remain enabled in the interim.
+ */
+ switch (modeset->cmd) {
+ case _DRM_PRE_MODESET:
+ if (!dev->vblank_inmodeset[crtc]) {
+ dev->vblank_inmodeset[crtc] = 1;
+ drm_vblank_get(dev, crtc);
+ }
+ break;
+ case _DRM_POST_MODESET:
+ if (dev->vblank_inmodeset[crtc]) {
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ dev->vblank_disable_allowed = 1;
+ dev->vblank_inmodeset[crtc] = 0;
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ drm_vblank_put(dev, crtc);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+out:
+ return ret;
+}
+
+/**
* Wait for VBLANK.
*
* \param inode device inode.
@@ -232,14 +509,14 @@ int drm_control(struct drm_device *dev, void *data,
*
* If a signal is not requested, then calls vblank_wait().
*/
-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_wait_vblank(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
union drm_wait_vblank *vblwait = data;
- struct timeval now;
int ret = 0;
- unsigned int flags, seq;
+ unsigned int flags, seq, crtc;
- if ((!dev->irq) || (!dev->irq_enabled))
+ if ((!dev->pdev->irq) || (!dev->irq_enabled))
return -EINVAL;
if (vblwait->request.type &
@@ -251,13 +528,17 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
}
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+ crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
- if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
- DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+ if (crtc >= dev->num_crtcs)
return -EINVAL;
- seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
- : &dev->vbl_received);
+ ret = drm_vblank_get(dev, crtc);
+ if (ret) {
+ DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
+ return ret;
+ }
+ seq = drm_vblank_count(dev, crtc);
switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
case _DRM_VBLANK_RELATIVE:
@@ -266,7 +547,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
case _DRM_VBLANK_ABSOLUTE:
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
@@ -276,8 +558,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
- struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
- ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+ struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
struct drm_vbl_sig *vbl_sig;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -298,22 +579,29 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
}
}
- if (dev->vbl_pending >= 100) {
+ if (atomic_read(&dev->vbl_signal_pending) >= 100) {
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- return -EBUSY;
+ ret = -EBUSY;
+ goto done;
}
- dev->vbl_pending++;
-
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- if (!
- (vbl_sig =
- drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
- return -ENOMEM;
+ vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
+ DRM_MEM_DRIVER);
+ if (!vbl_sig) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ ret = drm_vblank_get(dev, crtc);
+ if (ret) {
+ drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
+ DRM_MEM_DRIVER);
+ return ret;
}
- memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+ atomic_inc(&dev->vbl_signal_pending);
vbl_sig->sequence = vblwait->request.sequence;
vbl_sig->info.si_signo = vblwait->request.signal;
@@ -327,20 +615,29 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
vblwait->reply.sequence = seq;
} else {
- if (flags & _DRM_VBLANK_SECONDARY) {
- if (dev->driver->vblank_wait2)
- ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
- } else if (dev->driver->vblank_wait)
- ret =
- dev->driver->vblank_wait(dev,
- &vblwait->request.sequence);
-
- do_gettimeofday(&now);
- vblwait->reply.tval_sec = now.tv_sec;
- vblwait->reply.tval_usec = now.tv_usec;
+ DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
+ vblwait->request.sequence, crtc);
+ DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
+ ((drm_vblank_count(dev, crtc)
+ - vblwait->request.sequence) <= (1 << 23)));
+
+ if (ret != -EINTR) {
+ struct timeval now;
+
+ do_gettimeofday(&now);
+
+ vblwait->reply.tval_sec = now.tv_sec;
+ vblwait->reply.tval_usec = now.tv_usec;
+ vblwait->reply.sequence = drm_vblank_count(dev, crtc);
+ DRM_DEBUG("returning %d to client\n",
+ vblwait->reply.sequence);
+ } else {
+ DRM_DEBUG("vblank wait interrupted by signal\n");
+ }
}
- done:
+done:
+ drm_vblank_put(dev, crtc);
return ret;
}
@@ -348,44 +645,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
* Send the VBLANK signals.
*
* \param dev DRM device.
+ * \param crtc CRTC where the vblank event occurred
*
* Sends a signal for each task in drm_device::vbl_sigs and empties the list.
*
* If a signal is not requested, then calls vblank_wait().
*/
-void drm_vbl_send_signals(struct drm_device * dev)
+static void drm_vbl_send_signals(struct drm_device *dev, int crtc)
{
+ struct drm_vbl_sig *vbl_sig, *tmp;
+ struct list_head *vbl_sigs;
+ unsigned int vbl_seq;
unsigned long flags;
- int i;
spin_lock_irqsave(&dev->vbl_lock, flags);
- for (i = 0; i < 2; i++) {
- struct drm_vbl_sig *vbl_sig, *tmp;
- struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
- unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
- &dev->vbl_received);
+ vbl_sigs = &dev->vbl_sigs[crtc];
+ vbl_seq = drm_vblank_count(dev, crtc);
- list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
- if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
- vbl_sig->info.si_code = vbl_seq;
- send_sig_info(vbl_sig->info.si_signo,
- &vbl_sig->info, vbl_sig->task);
+ list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+ if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+ vbl_sig->info.si_code = vbl_seq;
+ send_sig_info(vbl_sig->info.si_signo,
+ &vbl_sig->info, vbl_sig->task);
- list_del(&vbl_sig->head);
-
- drm_free(vbl_sig, sizeof(*vbl_sig),
- DRM_MEM_DRIVER);
+ list_del(&vbl_sig->head);
- dev->vbl_pending--;
- }
- }
+ drm_free(vbl_sig, sizeof(*vbl_sig),
+ DRM_MEM_DRIVER);
+ atomic_dec(&dev->vbl_signal_pending);
+ drm_vblank_put(dev, crtc);
+ }
}
spin_unlock_irqrestore(&dev->vbl_lock, flags);
}
-EXPORT_SYMBOL(drm_vbl_send_signals);
+/**
+ * drm_handle_vblank - handle a vblank event
+ * @dev: DRM device
+ * @crtc: where this event occurred
+ *
+ * Drivers should call this routine in their vblank interrupt handlers to
+ * update the vblank counter and send any signals that may be pending.
+ */
+void drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+ atomic_inc(&dev->_vblank_count[crtc]);
+ DRM_WAKEUP(&dev->vbl_queue[crtc]);
+ drm_vbl_send_signals(dev, crtc);
+}
+EXPORT_SYMBOL(drm_handle_vblank);
/**
* Tasklet wrapper function.
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index 0177012845c..803bc9e7ce3 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -133,6 +133,7 @@ int drm_free_agp(DRM_AGP_MEM * handle, int pages)
{
return drm_agp_free_memory(handle) ? 0 : -EINVAL;
}
+EXPORT_SYMBOL(drm_free_agp);
/** Wrapper around agp_bind_memory() */
int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
@@ -145,6 +146,7 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
{
return drm_agp_unbind_memory(handle);
}
+EXPORT_SYMBOL(drm_unbind_agp);
#else /* __OS_HAS_AGP */
static inline void *agp_remap(unsigned long offset, unsigned long size,
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index dcff9e9b52e..217ad7dc707 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -169,6 +169,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
return child;
}
+EXPORT_SYMBOL(drm_mm_get_block);
/*
* Put a block. Merge with the previous and / or next block if they are free.
@@ -217,6 +218,7 @@ void drm_mm_put_block(struct drm_mm_node * cur)
drm_free(cur, sizeof(*cur), DRM_MEM_MM);
}
}
+EXPORT_SYMBOL(drm_mm_put_block);
struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
unsigned long size,
@@ -265,6 +267,7 @@ int drm_mm_clean(struct drm_mm * mm)
return (head->next->next == head);
}
+EXPORT_SYMBOL(drm_mm_search_free);
int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
{
@@ -273,7 +276,7 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
return drm_mm_create_tail_node(mm, start, size);
}
-
+EXPORT_SYMBOL(drm_mm_init);
void drm_mm_takedown(struct drm_mm * mm)
{
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index 93b1e0475c9..d490db4c0de 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -49,6 +49,10 @@ static int drm_queues_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
static int drm_bufs_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
#if DRM_DEBUG_CODE
static int drm_vma_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
@@ -60,13 +64,16 @@ static int drm_vma_info(char *buf, char **start, off_t offset,
static struct drm_proc_list {
const char *name; /**< file name */
int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
+ u32 driver_features; /**< Required driver features for this entry */
} drm_proc_list[] = {
- {"name", drm_name_info},
- {"mem", drm_mem_info},
- {"vm", drm_vm_info},
- {"clients", drm_clients_info},
- {"queues", drm_queues_info},
- {"bufs", drm_bufs_info},
+ {"name", drm_name_info, 0},
+ {"mem", drm_mem_info, 0},
+ {"vm", drm_vm_info, 0},
+ {"clients", drm_clients_info, 0},
+ {"queues", drm_queues_info, 0},
+ {"bufs", drm_bufs_info, 0},
+ {"gem_names", drm_gem_name_info, DRIVER_GEM},
+ {"gem_objects", drm_gem_object_info, DRIVER_GEM},
#if DRM_DEBUG_CODE
{"vma", drm_vma_info},
#endif
@@ -90,8 +97,9 @@ static struct drm_proc_list {
int drm_proc_init(struct drm_minor *minor, int minor_id,
struct proc_dir_entry *root)
{
+ struct drm_device *dev = minor->dev;
struct proc_dir_entry *ent;
- int i, j;
+ int i, j, ret;
char name[64];
sprintf(name, "%d", minor_id);
@@ -102,23 +110,42 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,
}
for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+ u32 features = drm_proc_list[i].driver_features;
+
+ if (features != 0 &&
+ (dev->driver->driver_features & features) != features)
+ continue;
+
ent = create_proc_entry(drm_proc_list[i].name,
S_IFREG | S_IRUGO, minor->dev_root);
if (!ent) {
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
name, drm_proc_list[i].name);
- for (j = 0; j < i; j++)
- remove_proc_entry(drm_proc_list[i].name,
- minor->dev_root);
- remove_proc_entry(name, root);
- minor->dev_root = NULL;
- return -1;
+ ret = -1;
+ goto fail;
}
ent->read_proc = drm_proc_list[i].f;
ent->data = minor;
}
+ if (dev->driver->proc_init) {
+ ret = dev->driver->proc_init(minor);
+ if (ret) {
+ DRM_ERROR("DRM: Driver failed to initialize "
+ "/proc/dri.\n");
+ goto fail;
+ }
+ }
+
return 0;
+ fail:
+
+ for (j = 0; j < i; j++)
+ remove_proc_entry(drm_proc_list[i].name,
+ minor->dev_root);
+ remove_proc_entry(name, root);
+ minor->dev_root = NULL;
+ return ret;
}
/**
@@ -133,12 +160,16 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,
*/
int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
{
+ struct drm_device *dev = minor->dev;
int i;
char name[64];
if (!root || !minor->dev_root)
return 0;
+ if (dev->driver->proc_cleanup)
+ dev->driver->proc_cleanup(minor);
+
for (i = 0; i < DRM_PROC_ENTRIES; i++)
remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
sprintf(name, "%d", minor->index);
@@ -480,6 +511,84 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
return ret;
}
+struct drm_gem_name_info_data {
+ int len;
+ char *buf;
+ int eof;
+};
+
+static int drm_gem_one_name_info(int id, void *ptr, void *data)
+{
+ struct drm_gem_object *obj = ptr;
+ struct drm_gem_name_info_data *nid = data;
+
+ DRM_INFO("name %d size %d\n", obj->name, obj->size);
+ if (nid->eof)
+ return 0;
+
+ nid->len += sprintf(&nid->buf[nid->len],
+ "%6d%9d%8d%9d\n",
+ obj->name, obj->size,
+ atomic_read(&obj->handlecount.refcount),
+ atomic_read(&obj->refcount.refcount));
+ if (nid->len > DRM_PROC_LIMIT) {
+ nid->eof = 1;
+ return 0;
+ }
+ return 0;
+}
+
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ struct drm_gem_name_info_data nid;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ nid.len = sprintf(buf, " name size handles refcount\n");
+ nid.buf = buf;
+ nid.eof = 0;
+ idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
+
+ *start = &buf[offset];
+ *eof = 0;
+ if (nid.len > request + offset)
+ return request;
+ *eof = 1;
+ return nid.len - offset;
+}
+
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
+ DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
+ DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
+ DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
+ DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
+ DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
#if DRM_DEBUG_CODE
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index c2f584f3b46..141e33004a7 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -107,7 +107,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
#ifdef __alpha__
dev->hose = pdev->sysdata;
#endif
- dev->irq = pdev->irq;
if (drm_ht_create(&dev->map_hash, 12)) {
return -ENOMEM;
@@ -152,6 +151,15 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
goto error_out_unreg;
}
+ if (driver->driver_features & DRIVER_GEM) {
+ retcode = drm_gem_init(dev);
+ if (retcode) {
+ DRM_ERROR("Cannot initialize graphics execution "
+ "manager (GEM)\n");
+ goto error_out_unreg;
+ }
+ }
+
return 0;
error_out_unreg:
@@ -317,6 +325,7 @@ int drm_put_dev(struct drm_device * dev)
int drm_put_minor(struct drm_minor **minor_p)
{
struct drm_minor *minor = *minor_p;
+
DRM_DEBUG("release secondary minor %d\n", minor->index);
if (minor->type == DRM_MINOR_LEGACY)
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index af211a0ef17..1611b9bcbe7 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -184,7 +184,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
err_out_files:
if (i > 0)
for (j = 0; j < i; j++)
- device_remove_file(&minor->kdev, &device_attrs[i]);
+ device_remove_file(&minor->kdev, &device_attrs[j]);
device_unregister(&minor->kdev);
err_out:
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a9e60464df7..5ba78e4fd2b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -3,7 +3,12 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ccflags-y := -Iinclude/drm
-i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \
+ i915_suspend.o \
+ i915_gem.o \
+ i915_gem_debug.o \
+ i915_gem_proc.o \
+ i915_gem_tiling.o
i915-$(CONFIG_COMPAT) += i915_ioc32.o
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 88974342933..db34780edbb 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -40,40 +40,96 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
- u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
+ u32 last_acthd = I915_READ(acthd_reg);
+ u32 acthd;
+ u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
int i;
- for (i = 0; i < 10000; i++) {
- ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ for (i = 0; i < 100000; i++) {
+ ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+ acthd = I915_READ(acthd_reg);
ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0)
ring->space += ring->Size;
if (ring->space >= n)
return 0;
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
if (ring->head != last_head)
i = 0;
+ if (acthd != last_acthd)
+ i = 0;
last_head = ring->head;
+ last_acthd = acthd;
+ msleep_interruptible(10);
+
}
return -EBUSY;
}
+/**
+ * Sets up the hardware status page for devices that need a physical address
+ * in the register.
+ */
+static int i915_init_phys_hws(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ /* Program Hardware Status Page */
+ dev_priv->status_page_dmah =
+ drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+ if (!dev_priv->status_page_dmah) {
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return -ENOMEM;
+ }
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+ I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+ DRM_DEBUG("Enabled hardware status page\n");
+ return 0;
+}
+
+/**
+ * Frees the hardware status page, whether it's a physical address or a virtual
+ * address set up by the X Server.
+ */
+static void i915_free_hws(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ if (dev_priv->status_page_dmah) {
+ drm_pci_free(dev, dev_priv->status_page_dmah);
+ dev_priv->status_page_dmah = NULL;
+ }
+
+ if (dev_priv->status_gfx_addr) {
+ dev_priv->status_gfx_addr = 0;
+ drm_core_ioremapfree(&dev_priv->hws_map, dev);
+ }
+
+ /* Need to rewrite hardware status page */
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+}
+
void i915_kernel_lost_context(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
- ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+ ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+ ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0)
ring->space += ring->Size;
- if (ring->head == ring->tail)
+ if (ring->head == ring->tail && dev_priv->sarea_priv)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
@@ -84,28 +140,19 @@ static int i915_dma_cleanup(struct drm_device * dev)
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if (dev->irq)
+ if (dev->irq_enabled)
drm_irq_uninstall(dev);
if (dev_priv->ring.virtual_start) {
drm_core_ioremapfree(&dev_priv->ring.map, dev);
- dev_priv->ring.virtual_start = 0;
- dev_priv->ring.map.handle = 0;
+ dev_priv->ring.virtual_start = NULL;
+ dev_priv->ring.map.handle = NULL;
dev_priv->ring.map.size = 0;
}
- if (dev_priv->status_page_dmah) {
- drm_pci_free(dev, dev_priv->status_page_dmah);
- dev_priv->status_page_dmah = NULL;
- /* Need to rewrite hardware status page */
- I915_WRITE(0x02080, 0x1ffff000);
- }
-
- if (dev_priv->status_gfx_addr) {
- dev_priv->status_gfx_addr = 0;
- drm_core_ioremapfree(&dev_priv->hws_map, dev);
- I915_WRITE(0x2080, 0x1ffff000);
- }
+ /* Clear the HWS virtual address at teardown */
+ if (I915_NEED_GFX_HWS(dev))
+ i915_free_hws(dev);
return 0;
}
@@ -121,34 +168,34 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
return -EINVAL;
}
- dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
- if (!dev_priv->mmio_map) {
- i915_dma_cleanup(dev);
- DRM_ERROR("can not find mmio map!\n");
- return -EINVAL;
- }
-
dev_priv->sarea_priv = (drm_i915_sarea_t *)
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
- dev_priv->ring.Start = init->ring_start;
- dev_priv->ring.End = init->ring_end;
- dev_priv->ring.Size = init->ring_size;
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+ if (init->ring_size != 0) {
+ if (dev_priv->ring.ring_obj != NULL) {
+ i915_dma_cleanup(dev);
+ DRM_ERROR("Client tried to initialize ringbuffer in "
+ "GEM mode\n");
+ return -EINVAL;
+ }
- dev_priv->ring.map.offset = init->ring_start;
- dev_priv->ring.map.size = init->ring_size;
- dev_priv->ring.map.type = 0;
- dev_priv->ring.map.flags = 0;
- dev_priv->ring.map.mtrr = 0;
+ dev_priv->ring.Size = init->ring_size;
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
- drm_core_ioremap(&dev_priv->ring.map, dev);
+ dev_priv->ring.map.offset = init->ring_start;
+ dev_priv->ring.map.size = init->ring_size;
+ dev_priv->ring.map.type = 0;
+ dev_priv->ring.map.flags = 0;
+ dev_priv->ring.map.mtrr = 0;
- if (dev_priv->ring.map.handle == NULL) {
- i915_dma_cleanup(dev);
- DRM_ERROR("can not ioremap virtual address for"
- " ring buffer\n");
- return -ENOMEM;
+ drm_core_ioremap(&dev_priv->ring.map, dev);
+
+ if (dev_priv->ring.map.handle == NULL) {
+ i915_dma_cleanup(dev);
+ DRM_ERROR("can not ioremap virtual address for"
+ " ring buffer\n");
+ return -ENOMEM;
+ }
}
dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
@@ -159,34 +206,10 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
dev_priv->current_page = 0;
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
- /* We are using separate values as placeholders for mechanisms for
- * private backbuffer/depthbuffer usage.
- */
- dev_priv->use_mi_batchbuffer_start = 0;
- if (IS_I965G(dev)) /* 965 doesn't support older method */
- dev_priv->use_mi_batchbuffer_start = 1;
-
/* Allow hardware batchbuffers unless told otherwise.
*/
dev_priv->allow_batchbuffer = 1;
- /* Program Hardware Status Page */
- if (!I915_NEED_GFX_HWS(dev)) {
- dev_priv->status_page_dmah =
- drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-
- if (!dev_priv->status_page_dmah) {
- i915_dma_cleanup(dev);
- DRM_ERROR("Can not allocate hardware status page\n");
- return -ENOMEM;
- }
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
- dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(0x02080, dev_priv->dma_status_page);
- }
- DRM_DEBUG("Enabled hardware status page\n");
return 0;
}
@@ -201,11 +224,6 @@ static int i915_dma_resume(struct drm_device * dev)
return -EINVAL;
}
- if (!dev_priv->mmio_map) {
- DRM_ERROR("can not find mmio map!\n");
- return -EINVAL;
- }
-
if (dev_priv->ring.map.handle == NULL) {
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
@@ -220,9 +238,9 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
if (dev_priv->status_gfx_addr != 0)
- I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+ I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
else
- I915_WRITE(0x02080, dev_priv->dma_status_page);
+ I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
return 0;
@@ -367,9 +385,10 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
return 0;
}
-static int i915_emit_box(struct drm_device * dev,
- struct drm_clip_rect __user * boxes,
- int i, int DR1, int DR4)
+int
+i915_emit_box(struct drm_device *dev,
+ struct drm_clip_rect __user *boxes,
+ int i, int DR1, int DR4)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_clip_rect box;
@@ -415,14 +434,15 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
+ dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+ dev_priv->counter = 0;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
BEGIN_LP_RING(4);
- OUT_RING(CMD_STORE_DWORD_IDX);
- OUT_RING(20);
+ OUT_RING(MI_STORE_DWORD_INDEX);
+ OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
OUT_RING(dev_priv->counter);
OUT_RING(0);
ADVANCE_LP_RING();
@@ -486,7 +506,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
return ret;
}
- if (dev_priv->use_mi_batchbuffer_start) {
+ if (!IS_I830(dev) && !IS_845G(dev)) {
BEGIN_LP_RING(2);
if (IS_I965G(dev)) {
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
@@ -516,15 +536,18 @@ static int i915_dispatch_flip(struct drm_device * dev)
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
+ if (!dev_priv->sarea_priv)
+ return -EINVAL;
+
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
- __FUNCTION__,
+ __func__,
dev_priv->current_page,
dev_priv->sarea_priv->pf_current_page);
i915_kernel_lost_context(dev);
BEGIN_LP_RING(2);
- OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(MI_FLUSH | MI_READ_FLUSH);
OUT_RING(0);
ADVANCE_LP_RING();
@@ -549,8 +572,8 @@ static int i915_dispatch_flip(struct drm_device * dev)
dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
BEGIN_LP_RING(4);
- OUT_RING(CMD_STORE_DWORD_IDX);
- OUT_RING(20);
+ OUT_RING(MI_STORE_DWORD_INDEX);
+ OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
OUT_RING(dev_priv->counter);
OUT_RING(0);
ADVANCE_LP_RING();
@@ -570,9 +593,15 @@ static int i915_quiescent(struct drm_device * dev)
static int i915_flush_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ int ret;
- return i915_quiescent(dev);
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_quiescent(dev);
+ mutex_unlock(&dev->struct_mutex);
+
+ return ret;
}
static int i915_batchbuffer(struct drm_device *dev, void *data,
@@ -593,16 +622,19 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
batch->start, batch->used, batch->num_cliprects);
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
batch->num_cliprects *
sizeof(struct drm_clip_rect)))
return -EFAULT;
+ mutex_lock(&dev->struct_mutex);
ret = i915_dispatch_batchbuffer(dev, batch);
+ mutex_unlock(&dev->struct_mutex);
- sarea_priv->last_dispatch = (int)hw_status[5];
+ if (sarea_priv)
+ sarea_priv->last_dispatch = (int)hw_status[5];
return ret;
}
@@ -619,7 +651,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
if (cmdbuf->num_cliprects &&
DRM_VERIFYAREA_READ(cmdbuf->cliprects,
@@ -629,24 +661,33 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
return -EFAULT;
}
+ mutex_lock(&dev->struct_mutex);
ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
+ mutex_unlock(&dev->struct_mutex);
if (ret) {
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
return ret;
}
- sarea_priv->last_dispatch = (int)hw_status[5];
+ if (sarea_priv)
+ sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
static int i915_flip_bufs(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
+ int ret;
+
+ DRM_DEBUG("%s\n", __func__);
+
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_dispatch_flip(dev);
+ mutex_unlock(&dev->struct_mutex);
- return i915_dispatch_flip(dev);
+ return ret;
}
static int i915_getparam(struct drm_device *dev, void *data,
@@ -663,7 +704,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
switch (param->param) {
case I915_PARAM_IRQ_ACTIVE:
- value = dev->irq ? 1 : 0;
+ value = dev->pdev->irq ? 1 : 0;
break;
case I915_PARAM_ALLOW_BATCHBUFFER:
value = dev_priv->allow_batchbuffer ? 1 : 0;
@@ -671,6 +712,12 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_LAST_DISPATCH:
value = READ_BREADCRUMB(dev_priv);
break;
+ case I915_PARAM_CHIPSET_ID:
+ value = dev->pci_device;
+ break;
+ case I915_PARAM_HAS_GEM:
+ value = 1;
+ break;
default:
DRM_ERROR("Unknown parameter %d\n", param->param);
return -EINVAL;
@@ -697,8 +744,6 @@ static int i915_setparam(struct drm_device *dev, void *data,
switch (param->param) {
case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
- if (!IS_I965G(dev))
- dev_priv->use_mi_batchbuffer_start = param->value;
break;
case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
dev_priv->tex_lru_log_granularity = param->value;
@@ -749,8 +794,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
dev_priv->hw_status_page = dev_priv->hws_map.handle;
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(0x02080, dev_priv->status_gfx_addr);
- DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+ I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+ DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
dev_priv->status_gfx_addr);
DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
return 0;
@@ -776,14 +821,38 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
memset(dev_priv, 0, sizeof(drm_i915_private_t));
dev->dev_private = (void *)dev_priv;
+ dev_priv->dev = dev;
/* Add register map (needed for suspend/resume) */
base = drm_get_resource_start(dev, mmio_bar);
size = drm_get_resource_len(dev, mmio_bar);
- ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
- _DRM_KERNEL | _DRM_DRIVER,
- &dev_priv->mmio_map);
+ dev_priv->regs = ioremap(base, size);
+
+ i915_gem_load(dev);
+
+ /* Init HWS */
+ if (!I915_NEED_GFX_HWS(dev)) {
+ ret = i915_init_phys_hws(dev);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* On the 945G/GM, the chipset reports the MSI capability on the
+ * integrated graphics even though the support isn't actually there
+ * according to the published specs. It doesn't appear to function
+ * correctly in testing on 945G.
+ * This may be a side effect of MSI having been made available for PEG
+ * and the registers being closely associated.
+ */
+ if (!IS_I945G(dev) && !IS_I945GM(dev))
+ if (pci_enable_msi(dev->pdev))
+ DRM_ERROR("failed to enable MSI\n");
+
+ intel_opregion_init(dev);
+
+ spin_lock_init(&dev_priv->user_irq_lock);
+
return ret;
}
@@ -791,8 +860,15 @@ int i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (dev_priv->mmio_map)
- drm_rmmap(dev, dev_priv->mmio_map);
+ if (dev->pdev->msi_enabled)
+ pci_disable_msi(dev->pdev);
+
+ i915_free_hws(dev);
+
+ if (dev_priv->regs != NULL)
+ iounmap(dev_priv->regs);
+
+ intel_opregion_free(dev);
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
DRM_MEM_DRIVER);
@@ -800,6 +876,25 @@ int i915_driver_unload(struct drm_device *dev)
return 0;
}
+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_i915_file_private *i915_file_priv;
+
+ DRM_DEBUG("\n");
+ i915_file_priv = (struct drm_i915_file_private *)
+ drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+
+ if (!i915_file_priv)
+ return -ENOMEM;
+
+ file_priv->driver_priv = i915_file_priv;
+
+ i915_file_priv->mm.last_gem_seqno = 0;
+ i915_file_priv->mm.last_gem_throttle_seqno = 0;
+
+ return 0;
+}
+
void i915_driver_lastclose(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -807,6 +902,8 @@ void i915_driver_lastclose(struct drm_device * dev)
if (!dev_priv)
return;
+ i915_gem_lastclose(dev);
+
if (dev_priv->agp_heap)
i915_mem_takedown(&(dev_priv->agp_heap));
@@ -819,6 +916,13 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
i915_mem_release(dev, file_priv, dev_priv->agp_heap);
}
+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+
+ drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+}
+
struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
@@ -836,7 +940,23 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ),
DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 93aed1c38bd..a80ead21528 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -38,211 +38,9 @@ static struct pci_device_id pciidlist[] = {
i915_PCI_IDS
};
-enum pipe {
- PIPE_A = 0,
- PIPE_B,
-};
-
-static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (pipe == PIPE_A)
- return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
- else
- return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
-}
-
-static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
- u32 *array;
- int i;
-
- if (!i915_pipe_enabled(dev, pipe))
- return;
-
- if (pipe == PIPE_A)
- array = dev_priv->save_palette_a;
- else
- array = dev_priv->save_palette_b;
-
- for(i = 0; i < 256; i++)
- array[i] = I915_READ(reg + (i << 2));
-}
-
-static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
- u32 *array;
- int i;
-
- if (!i915_pipe_enabled(dev, pipe))
- return;
-
- if (pipe == PIPE_A)
- array = dev_priv->save_palette_a;
- else
- array = dev_priv->save_palette_b;
-
- for(i = 0; i < 256; i++)
- I915_WRITE(reg + (i << 2), array[i]);
-}
-
-static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg)
-{
- outb(reg, index_port);
- return inb(data_port);
-}
-
-static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable)
-{
- inb(st01);
- outb(palette_enable | reg, VGA_AR_INDEX);
- return inb(VGA_AR_DATA_READ);
-}
-
-static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable)
-{
- inb(st01);
- outb(palette_enable | reg, VGA_AR_INDEX);
- outb(val, VGA_AR_DATA_WRITE);
-}
-
-static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val)
-{
- outb(reg, index_port);
- outb(val, data_port);
-}
-
-static void i915_save_vga(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int i;
- u16 cr_index, cr_data, st01;
-
- /* VGA color palette registers */
- dev_priv->saveDACMASK = inb(VGA_DACMASK);
- /* DACCRX automatically increments during read */
- outb(0, VGA_DACRX);
- /* Read 3 bytes of color data from each index */
- for (i = 0; i < 256 * 3; i++)
- dev_priv->saveDACDATA[i] = inb(VGA_DACDATA);
-
- /* MSR bits */
- dev_priv->saveMSR = inb(VGA_MSR_READ);
- if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
- cr_index = VGA_CR_INDEX_CGA;
- cr_data = VGA_CR_DATA_CGA;
- st01 = VGA_ST01_CGA;
- } else {
- cr_index = VGA_CR_INDEX_MDA;
- cr_data = VGA_CR_DATA_MDA;
- st01 = VGA_ST01_MDA;
- }
-
- /* CRT controller regs */
- i915_write_indexed(cr_index, cr_data, 0x11,
- i915_read_indexed(cr_index, cr_data, 0x11) &
- (~0x80));
- for (i = 0; i <= 0x24; i++)
- dev_priv->saveCR[i] =
- i915_read_indexed(cr_index, cr_data, i);
- /* Make sure we don't turn off CR group 0 writes */
- dev_priv->saveCR[0x11] &= ~0x80;
-
- /* Attribute controller registers */
- inb(st01);
- dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
- for (i = 0; i <= 0x14; i++)
- dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
- inb(st01);
- outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
- inb(st01);
-
- /* Graphics controller registers */
- for (i = 0; i < 9; i++)
- dev_priv->saveGR[i] =
- i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i);
-
- dev_priv->saveGR[0x10] =
- i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10);
- dev_priv->saveGR[0x11] =
- i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11);
- dev_priv->saveGR[0x18] =
- i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18);
-
- /* Sequencer registers */
- for (i = 0; i < 8; i++)
- dev_priv->saveSR[i] =
- i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i);
-}
-
-static void i915_restore_vga(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int i;
- u16 cr_index, cr_data, st01;
-
- /* MSR bits */
- outb(dev_priv->saveMSR, VGA_MSR_WRITE);
- if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
- cr_index = VGA_CR_INDEX_CGA;
- cr_data = VGA_CR_DATA_CGA;
- st01 = VGA_ST01_CGA;
- } else {
- cr_index = VGA_CR_INDEX_MDA;
- cr_data = VGA_CR_DATA_MDA;
- st01 = VGA_ST01_MDA;
- }
-
- /* Sequencer registers, don't write SR07 */
- for (i = 0; i < 7; i++)
- i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i,
- dev_priv->saveSR[i]);
-
- /* CRT controller regs */
- /* Enable CR group 0 writes */
- i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
- for (i = 0; i <= 0x24; i++)
- i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
-
- /* Graphics controller regs */
- for (i = 0; i < 9; i++)
- i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i,
- dev_priv->saveGR[i]);
-
- i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10,
- dev_priv->saveGR[0x10]);
- i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11,
- dev_priv->saveGR[0x11]);
- i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18,
- dev_priv->saveGR[0x18]);
-
- /* Attribute controller registers */
- inb(st01);
- for (i = 0; i <= 0x14; i++)
- i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
- inb(st01); /* switch back to index mode */
- outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
- inb(st01);
-
- /* VGA color palette registers */
- outb(dev_priv->saveDACMASK, VGA_DACMASK);
- /* DACCRX automatically increments during read */
- outb(0, VGA_DACWX);
- /* Read 3 bytes of color data from each index */
- for (i = 0; i < 256 * 3; i++)
- outb(dev_priv->saveDACDATA[i], VGA_DACDATA);
-
-}
-
static int i915_suspend(struct drm_device *dev, pm_message_t state)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int i;
if (!dev || !dev_priv) {
printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
@@ -254,122 +52,10 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
return 0;
pci_save_state(dev->pdev);
- pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
-
- /* Display arbitration control */
- dev_priv->saveDSPARB = I915_READ(DSPARB);
-
- /* Pipe & plane A info */
- dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
- dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
- dev_priv->saveFPA0 = I915_READ(FPA0);
- dev_priv->saveFPA1 = I915_READ(FPA1);
- dev_priv->saveDPLL_A = I915_READ(DPLL_A);
- if (IS_I965G(dev))
- dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
- dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
- dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
- dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
- dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
- dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
- dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
- dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
- dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
- dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
- dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
- dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
- dev_priv->saveDSPABASE = I915_READ(DSPABASE);
- if (IS_I965G(dev)) {
- dev_priv->saveDSPASURF = I915_READ(DSPASURF);
- dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
- }
- i915_save_palette(dev, PIPE_A);
- dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
-
- /* Pipe & plane B info */
- dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
- dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
- dev_priv->saveFPB0 = I915_READ(FPB0);
- dev_priv->saveFPB1 = I915_READ(FPB1);
- dev_priv->saveDPLL_B = I915_READ(DPLL_B);
- if (IS_I965G(dev))
- dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
- dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
- dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
- dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
- dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
- dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
- dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
- dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
- dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
- dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
- dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
- dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
- dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
- if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
- dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
- dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
- }
- i915_save_palette(dev, PIPE_B);
- dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
- /* CRT state */
- dev_priv->saveADPA = I915_READ(ADPA);
+ i915_save_state(dev);
- /* LVDS state */
- dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
- dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
- dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
- if (IS_I965G(dev))
- dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
- if (IS_MOBILE(dev) && !IS_I830(dev))
- dev_priv->saveLVDS = I915_READ(LVDS);
- if (!IS_I830(dev) && !IS_845G(dev))
- dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
- dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
- dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
- dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
-
- /* FIXME: save TV & SDVO state */
-
- /* FBC state */
- dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
- dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
- dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
- dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-
- /* Interrupt state */
- dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
- dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
- dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
-
- /* VGA state */
- dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
- dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
- dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
- dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-
- /* Clock gating state */
- dev_priv->saveD_STATE = I915_READ(D_STATE);
- dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
-
- /* Cache mode state */
- dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-
- /* Memory Arbitration state */
- dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
-
- /* Scratch space */
- for (i = 0; i < 16; i++) {
- dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
- dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
- }
- for (i = 0; i < 3; i++)
- dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
-
- i915_save_vga(dev);
+ intel_opregion_free(dev);
if (state.event == PM_EVENT_SUSPEND) {
/* Shut down the device */
@@ -382,155 +68,15 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
static int i915_resume(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int i;
-
pci_set_power_state(dev->pdev, PCI_D0);
pci_restore_state(dev->pdev);
if (pci_enable_device(dev->pdev))
return -1;
pci_set_master(dev->pdev);
- pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
-
- I915_WRITE(DSPARB, dev_priv->saveDSPARB);
-
- /* Pipe & plane A info */
- /* Prime the clock */
- if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
- I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
- ~DPLL_VCO_ENABLE);
- udelay(150);
- }
- I915_WRITE(FPA0, dev_priv->saveFPA0);
- I915_WRITE(FPA1, dev_priv->saveFPA1);
- /* Actually enable it */
- I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
- udelay(150);
- if (IS_I965G(dev))
- I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
- udelay(150);
-
- /* Restore mode */
- I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
- I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
- I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
- I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
- I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
- I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
- I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-
- /* Restore plane info */
- I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
- I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
- I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
- I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
- I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
- if (IS_I965G(dev)) {
- I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
- I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
- }
-
- I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-
- i915_restore_palette(dev, PIPE_A);
- /* Enable the plane */
- I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
- I915_WRITE(DSPABASE, I915_READ(DSPABASE));
-
- /* Pipe & plane B info */
- if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
- I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
- ~DPLL_VCO_ENABLE);
- udelay(150);
- }
- I915_WRITE(FPB0, dev_priv->saveFPB0);
- I915_WRITE(FPB1, dev_priv->saveFPB1);
- /* Actually enable it */
- I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
- udelay(150);
- if (IS_I965G(dev))
- I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
- udelay(150);
-
- /* Restore mode */
- I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
- I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
- I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
- I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
- I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
- I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
- I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-
- /* Restore plane info */
- I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
- I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
- I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
- I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
- I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
- if (IS_I965G(dev)) {
- I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
- I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
- }
-
- I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-
- i915_restore_palette(dev, PIPE_B);
- /* Enable the plane */
- I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
- I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
-
- /* CRT state */
- I915_WRITE(ADPA, dev_priv->saveADPA);
-
- /* LVDS state */
- if (IS_I965G(dev))
- I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
- if (IS_MOBILE(dev) && !IS_I830(dev))
- I915_WRITE(LVDS, dev_priv->saveLVDS);
- if (!IS_I830(dev) && !IS_845G(dev))
- I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
-
- I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
- I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
- I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
- I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
- I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
- I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-
- /* FIXME: restore TV & SDVO state */
-
- /* FBC info */
- I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
- I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
- I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
- I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
-
- /* VGA state */
- I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
- I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
- I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
- I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
- udelay(150);
-
- /* Clock gating state */
- I915_WRITE (D_STATE, dev_priv->saveD_STATE);
- I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
-
- /* Cache mode state */
- I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-
- /* Memory arbitration state */
- I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-
- for (i = 0; i < 16; i++) {
- I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
- I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
- }
- for (i = 0; i < 3; i++)
- I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+ i915_restore_state(dev);
- i915_restore_vga(dev);
+ intel_opregion_init(dev);
return 0;
}
@@ -541,17 +87,19 @@ static struct drm_driver driver = {
*/
.driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
- DRIVER_IRQ_VBL2,
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
.load = i915_driver_load,
.unload = i915_driver_unload,
+ .open = i915_driver_open,
.lastclose = i915_driver_lastclose,
.preclose = i915_driver_preclose,
+ .postclose = i915_driver_postclose,
.suspend = i915_suspend,
.resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp,
- .vblank_wait = i915_driver_vblank_wait,
- .vblank_wait2 = i915_driver_vblank_wait2,
+ .get_vblank_counter = i915_get_vblank_counter,
+ .enable_vblank = i915_enable_vblank,
+ .disable_vblank = i915_disable_vblank,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
@@ -559,6 +107,10 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
+ .proc_init = i915_gem_proc_init,
+ .proc_cleanup = i915_gem_proc_cleanup,
+ .gem_init_object = i915_gem_init_object,
+ .gem_free_object = i915_gem_free_object,
.ioctls = i915_ioctls,
.fops = {
.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d7326d92a23..eae4ed3956e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -30,6 +30,8 @@
#ifndef _I915_DRV_H_
#define _I915_DRV_H_
+#include "i915_reg.h"
+
/* General customization:
*/
@@ -37,7 +39,12 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20060119"
+#define DRIVER_DATE "20080730"
+
+enum pipe {
+ PIPE_A = 0,
+ PIPE_B,
+};
/* Interface history:
*
@@ -53,16 +60,23 @@
#define DRIVER_MINOR 6
#define DRIVER_PATCHLEVEL 0
+#define WATCH_COHERENCY 0
+#define WATCH_BUF 0
+#define WATCH_EXEC 0
+#define WATCH_LRU 0
+#define WATCH_RELOC 0
+#define WATCH_INACTIVE 0
+#define WATCH_PWRITE 0
+
typedef struct _drm_i915_ring_buffer {
int tail_mask;
- unsigned long Start;
- unsigned long End;
unsigned long Size;
u8 *virtual_start;
int head;
int tail;
int space;
drm_local_map_t map;
+ struct drm_gem_object *ring_obj;
} drm_i915_ring_buffer_t;
struct mem_block {
@@ -76,13 +90,28 @@ struct mem_block {
typedef struct _drm_i915_vbl_swap {
struct list_head head;
drm_drawable_t drw_id;
- unsigned int pipe;
+ unsigned int plane;
unsigned int sequence;
} drm_i915_vbl_swap_t;
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct intel_opregion {
+ struct opregion_header *header;
+ struct opregion_acpi *acpi;
+ struct opregion_swsci *swsci;
+ struct opregion_asle *asle;
+ int enabled;
+};
+
typedef struct drm_i915_private {
+ struct drm_device *dev;
+
+ void __iomem *regs;
drm_local_map_t *sarea;
- drm_local_map_t *mmio_map;
drm_i915_sarea_t *sarea_priv;
drm_i915_ring_buffer_t ring;
@@ -90,20 +119,25 @@ typedef struct drm_i915_private {
drm_dma_handle_t *status_page_dmah;
void *hw_status_page;
dma_addr_t dma_status_page;
- unsigned long counter;
+ uint32_t counter;
unsigned int status_gfx_addr;
drm_local_map_t hws_map;
+ struct drm_gem_object *hws_obj;
unsigned int cpp;
int back_offset;
int front_offset;
int current_page;
int page_flipping;
- int use_mi_batchbuffer_start;
wait_queue_head_t irq_queue;
atomic_t irq_received;
- atomic_t irq_emitted;
+ /** Protects user_irq_refcount and irq_mask_reg */
+ spinlock_t user_irq_lock;
+ /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
+ int user_irq_refcount;
+ /** Cached value of IMR to avoid reads in updating the bitfield */
+ u32 irq_mask_reg;
int tex_lru_log_granularity;
int allow_batchbuffer;
@@ -115,6 +149,8 @@ typedef struct drm_i915_private {
drm_i915_vbl_swap_t vbl_swaps;
unsigned int swaps_pending;
+ struct intel_opregion opregion;
+
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;
@@ -139,7 +175,7 @@ typedef struct drm_i915_private {
u32 saveDSPASTRIDE;
u32 saveDSPASIZE;
u32 saveDSPAPOS;
- u32 saveDSPABASE;
+ u32 saveDSPAADDR;
u32 saveDSPASURF;
u32 saveDSPATILEOFF;
u32 savePFIT_PGM_RATIOS;
@@ -160,24 +196,24 @@ typedef struct drm_i915_private {
u32 saveDSPBSTRIDE;
u32 saveDSPBSIZE;
u32 saveDSPBPOS;
- u32 saveDSPBBASE;
+ u32 saveDSPBADDR;
u32 saveDSPBSURF;
u32 saveDSPBTILEOFF;
- u32 saveVCLK_DIVISOR_VGA0;
- u32 saveVCLK_DIVISOR_VGA1;
- u32 saveVCLK_POST_DIV;
+ u32 saveVGA0;
+ u32 saveVGA1;
+ u32 saveVGA_PD;
u32 saveVGACNTRL;
u32 saveADPA;
u32 saveLVDS;
- u32 saveLVDSPP_ON;
- u32 saveLVDSPP_OFF;
+ u32 savePP_ON_DELAYS;
+ u32 savePP_OFF_DELAYS;
u32 saveDVOA;
u32 saveDVOB;
u32 saveDVOC;
u32 savePP_ON;
u32 savePP_OFF;
u32 savePP_CONTROL;
- u32 savePP_CYCLE;
+ u32 savePP_DIVISOR;
u32 savePFIT_CONTROL;
u32 save_palette_a[256];
u32 save_palette_b[256];
@@ -190,7 +226,7 @@ typedef struct drm_i915_private {
u32 saveIMR;
u32 saveCACHE_MODE_0;
u32 saveD_STATE;
- u32 saveDSPCLK_GATE_D;
+ u32 saveCG_2D_DIS;
u32 saveMI_ARB_STATE;
u32 saveSWF0[16];
u32 saveSWF1[16];
@@ -203,8 +239,180 @@ typedef struct drm_i915_private {
u8 saveDACMASK;
u8 saveDACDATA[256*3]; /* 256 3-byte colors */
u8 saveCR[37];
+
+ struct {
+ struct drm_mm gtt_space;
+
+ /**
+ * List of objects currently involved in rendering from the
+ * ringbuffer.
+ *
+ * A reference is held on the buffer while on this list.
+ */
+ struct list_head active_list;
+
+ /**
+ * List of objects which are not in the ringbuffer but which
+ * still have a write_domain which needs to be flushed before
+ * unbinding.
+ *
+ * A reference is held on the buffer while on this list.
+ */
+ struct list_head flushing_list;
+
+ /**
+ * LRU list of objects which are not in the ringbuffer and
+ * are ready to unbind, but are still in the GTT.
+ *
+ * A reference is not held on the buffer while on this list,
+ * as merely being GTT-bound shouldn't prevent its being
+ * freed, and we'll pull it off the list in the free path.
+ */
+ struct list_head inactive_list;
+
+ /**
+ * List of breadcrumbs associated with GPU requests currently
+ * outstanding.
+ */
+ struct list_head request_list;
+
+ /**
+ * We leave the user IRQ off as much as possible,
+ * but this means that requests will finish and never
+ * be retired once the system goes idle. Set a timer to
+ * fire periodically while the ring is running. When it
+ * fires, go retire requests.
+ */
+ struct delayed_work retire_work;
+
+ /** Work task for vblank-related ring access */
+ struct work_struct vblank_work;
+
+ uint32_t next_gem_seqno;
+
+ /**
+ * Waiting sequence number, if any
+ */
+ uint32_t waiting_gem_seqno;
+
+ /**
+ * Last seq seen at irq time
+ */
+ uint32_t irq_gem_seqno;
+
+ /**
+ * Flag if the X Server, and thus DRM, is not currently in
+ * control of the device.
+ *
+ * This is set between LeaveVT and EnterVT. It needs to be
+ * replaced with a semaphore. It also needs to be
+ * transitioned away from for kernel modesetting.
+ */
+ int suspended;
+
+ /**
+ * Flag if the hardware appears to be wedged.
+ *
+ * This is set when attempts to idle the device timeout.
+ * It prevents command submission from occuring and makes
+ * every pending request fail
+ */
+ int wedged;
+
+ /** Bit 6 swizzling required for X tiling */
+ uint32_t bit_6_swizzle_x;
+ /** Bit 6 swizzling required for Y tiling */
+ uint32_t bit_6_swizzle_y;
+ } mm;
} drm_i915_private_t;
+/** driver private structure attached to each drm_gem_object */
+struct drm_i915_gem_object {
+ struct drm_gem_object *obj;
+
+ /** Current space allocated to this object in the GTT, if any. */
+ struct drm_mm_node *gtt_space;
+
+ /** This object's place on the active/flushing/inactive lists */
+ struct list_head list;
+
+ /**
+ * This is set if the object is on the active or flushing lists
+ * (has pending rendering), and is not set if it's on inactive (ready
+ * to be unbound).
+ */
+ int active;
+
+ /**
+ * This is set if the object has been written to since last bound
+ * to the GTT
+ */
+ int dirty;
+
+ /** AGP memory structure for our GTT binding. */
+ DRM_AGP_MEM *agp_mem;
+
+ struct page **page_list;
+
+ /**
+ * Current offset of the object in GTT space.
+ *
+ * This is the same as gtt_space->start
+ */
+ uint32_t gtt_offset;
+
+ /** Boolean whether this object has a valid gtt offset. */
+ int gtt_bound;
+
+ /** How many users have pinned this object in GTT space */
+ int pin_count;
+
+ /** Breadcrumb of last rendering to the buffer. */
+ uint32_t last_rendering_seqno;
+
+ /** Current tiling mode for the object. */
+ uint32_t tiling_mode;
+
+ /** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
+ uint32_t agp_type;
+
+ /**
+ * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
+ * GEM_DOMAIN_CPU is not in the object's read domain.
+ */
+ uint8_t *page_cpu_valid;
+};
+
+/**
+ * Request queue structure.
+ *
+ * The request queue allows us to note sequence numbers that have been emitted
+ * and may be associated with active buffers to be retired.
+ *
+ * By keeping this list, we can avoid having to do questionable
+ * sequence-number comparisons on buffer last_rendering_seqnos, and associate
+ * an emission time with seqnos for tracking how far ahead of the GPU we are.
+ */
+struct drm_i915_gem_request {
+ /** GEM sequence number associated with this request. */
+ uint32_t seqno;
+
+ /** Time at which this request was emitted, in jiffies. */
+ unsigned long emitted_jiffies;
+
+ /** Cache domains that were flushed at the start of the request. */
+ uint32_t flush_domains;
+
+ struct list_head list;
+};
+
+struct drm_i915_file_private {
+ struct {
+ uint32_t last_gem_seqno;
+ uint32_t last_gem_throttle_seqno;
+ } mm;
+};
+
extern struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
@@ -212,31 +420,42 @@ extern int i915_max_ioctl;
extern void i915_kernel_lost_context(struct drm_device * dev);
extern int i915_driver_load(struct drm_device *, unsigned long flags);
extern int i915_driver_unload(struct drm_device *);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
extern void i915_driver_lastclose(struct drm_device * dev);
extern void i915_driver_preclose(struct drm_device *dev,
struct drm_file *file_priv);
+extern void i915_driver_postclose(struct drm_device *dev,
+ struct drm_file *file_priv);
extern int i915_driver_device_is_agp(struct drm_device * dev);
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
+extern int i915_emit_box(struct drm_device *dev,
+ struct drm_clip_rect __user *boxes,
+ int i, int DR1, int DR4);
/* i915_irq.c */
extern int i915_irq_emit(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_irq_wait(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+void i915_user_irq_get(struct drm_device *dev);
+void i915_user_irq_put(struct drm_device *dev);
-extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+extern void i915_gem_vblank_work_handler(struct work_struct *work);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern int i915_driver_irq_postinstall(struct drm_device *dev);
extern void i915_driver_irq_uninstall(struct drm_device * dev);
extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -250,11 +469,99 @@ extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(struct drm_device * dev,
struct drm_file *file_priv, struct mem_block *heap);
+/* i915_gem.c */
+int i915_gem_init_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_execbuffer(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_set_tiling(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int i915_gem_get_tiling(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+void i915_gem_load(struct drm_device *dev);
+int i915_gem_proc_init(struct drm_minor *minor);
+void i915_gem_proc_cleanup(struct drm_minor *minor);
+int i915_gem_init_object(struct drm_gem_object *obj);
+void i915_gem_free_object(struct drm_gem_object *obj);
+int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
+void i915_gem_object_unpin(struct drm_gem_object *obj);
+void i915_gem_lastclose(struct drm_device *dev);
+uint32_t i915_get_gem_seqno(struct drm_device *dev);
+void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_work_handler(struct work_struct *work);
+void i915_gem_clflush_object(struct drm_gem_object *obj);
+
+/* i915_gem_tiling.c */
+void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
+
+/* i915_gem_debug.c */
+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+ const char *where, uint32_t mark);
+#if WATCH_INACTIVE
+void i915_verify_inactive(struct drm_device *dev, char *file, int line);
+#else
+#define i915_verify_inactive(dev, file, line)
+#endif
+void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+ const char *where, uint32_t mark);
+void i915_dump_lru(struct drm_device *dev, const char *where);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
+/* i915_opregion.c */
+extern int intel_opregion_init(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev);
+extern void opregion_asle_intr(struct drm_device *dev);
+extern void opregion_enable_asle(struct drm_device *dev);
+
+/**
+ * Lock test for when it's just for synchronization of ring access.
+ *
+ * In that case, we don't need to do it when GEM is initialized as nobody else
+ * has access to the ring.
+ */
+#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \
+ if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
+ LOCK_TEST_WITH_RETURN(dev, file_priv); \
+} while (0)
-#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
-#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
-#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
-#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+#define I915_READ(reg) readl(dev_priv->regs + (reg))
+#define I915_WRITE(reg, val) writel(val, dev_priv->regs + (reg))
+#define I915_READ16(reg) readw(dev_priv->regs + (reg))
+#define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg))
+#define I915_READ8(reg) readb(dev_priv->regs + (reg))
+#define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg))
#define I915_VERBOSE 0
@@ -284,816 +591,29 @@ extern void i915_mem_release(struct drm_device * dev,
if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
dev_priv->ring.tail = outring; \
dev_priv->ring.space -= outcount * 4; \
- I915_WRITE(LP_RING + RING_TAIL, outring); \
+ I915_WRITE(PRB0_TAIL, outring); \
} while(0)
-extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
-
-/* Extended config space */
-#define LBB 0xf4
-
-/* VGA stuff */
-
-#define VGA_ST01_MDA 0x3ba
-#define VGA_ST01_CGA 0x3da
-
-#define VGA_MSR_WRITE 0x3c2
-#define VGA_MSR_READ 0x3cc
-#define VGA_MSR_MEM_EN (1<<1)
-#define VGA_MSR_CGA_MODE (1<<0)
-
-#define VGA_SR_INDEX 0x3c4
-#define VGA_SR_DATA 0x3c5
-
-#define VGA_AR_INDEX 0x3c0
-#define VGA_AR_VID_EN (1<<5)
-#define VGA_AR_DATA_WRITE 0x3c0
-#define VGA_AR_DATA_READ 0x3c1
-
-#define VGA_GR_INDEX 0x3ce
-#define VGA_GR_DATA 0x3cf
-/* GR05 */
-#define VGA_GR_MEM_READ_MODE_SHIFT 3
-#define VGA_GR_MEM_READ_MODE_PLANE 1
-/* GR06 */
-#define VGA_GR_MEM_MODE_MASK 0xc
-#define VGA_GR_MEM_MODE_SHIFT 2
-#define VGA_GR_MEM_A0000_AFFFF 0
-#define VGA_GR_MEM_A0000_BFFFF 1
-#define VGA_GR_MEM_B0000_B7FFF 2
-#define VGA_GR_MEM_B0000_BFFFF 3
-
-#define VGA_DACMASK 0x3c6
-#define VGA_DACRX 0x3c7
-#define VGA_DACWX 0x3c8
-#define VGA_DACDATA 0x3c9
-
-#define VGA_CR_INDEX_MDA 0x3b4
-#define VGA_CR_DATA_MDA 0x3b5
-#define VGA_CR_INDEX_CGA 0x3d4
-#define VGA_CR_DATA_CGA 0x3d5
-
-#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD (7<<23)
-#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
-
-#define INST_PARSER_CLIENT 0x00000000
-#define INST_OP_FLUSH 0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK (~0x7)
-#define BB1_PROTECTED (1<<0)
-#define BB1_UNPROTECTED (0<<0)
-#define BB2_END_ADDR_MASK (~0x7)
-
-/* Framebuffer compression */
-#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
-#define FBC_LL_BASE 0x03204 /* 4k page aligned */
-#define FBC_CONTROL 0x03208
-#define FBC_CTL_EN (1<<31)
-#define FBC_CTL_PERIODIC (1<<30)
-#define FBC_CTL_INTERVAL_SHIFT (16)
-#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
-#define FBC_CTL_STRIDE_SHIFT (5)
-#define FBC_CTL_FENCENO (1<<0)
-#define FBC_COMMAND 0x0320c
-#define FBC_CMD_COMPRESS (1<<0)
-#define FBC_STATUS 0x03210
-#define FBC_STAT_COMPRESSING (1<<31)
-#define FBC_STAT_COMPRESSED (1<<30)
-#define FBC_STAT_MODIFIED (1<<29)
-#define FBC_STAT_CURRENT_LINE (1<<0)
-#define FBC_CONTROL2 0x03214
-#define FBC_CTL_FENCE_DBL (0<<4)
-#define FBC_CTL_IDLE_IMM (0<<2)
-#define FBC_CTL_IDLE_FULL (1<<2)
-#define FBC_CTL_IDLE_LINE (2<<2)
-#define FBC_CTL_IDLE_DEBUG (3<<2)
-#define FBC_CTL_CPU_FENCE (1<<1)
-#define FBC_CTL_PLANEA (0<<0)
-#define FBC_CTL_PLANEB (1<<0)
-#define FBC_FENCE_OFF 0x0321b
-
-#define FBC_LL_SIZE (1536)
-#define FBC_LL_PAD (32)
-
-/* Interrupt bits:
- */
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG (1<<13) /* binner out of memory */
-
-#define I915REG_HWSTAM 0x02098
-#define I915REG_INT_IDENTITY_R 0x020a4
-#define I915REG_INT_MASK_R 0x020a8
-#define I915REG_INT_ENABLE_R 0x020a0
-
-#define I915REG_PIPEASTAT 0x70024
-#define I915REG_PIPEBSTAT 0x71024
-
-#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
-#define I915_VBLANK_CLEAR (1UL<<1)
-
-#define SRX_INDEX 0x3c4
-#define SRX_DATA 0x3c5
-#define SR01 1
-#define SR01_SCREEN_OFF (1<<5)
-
-#define PPCR 0x61204
-#define PPCR_ON (1<<0)
-
-#define DVOB 0x61140
-#define DVOB_ON (1<<31)
-#define DVOC 0x61160
-#define DVOC_ON (1<<31)
-#define LVDS 0x61180
-#define LVDS_ON (1<<31)
-
-#define ADPA 0x61100
-#define ADPA_DPMS_MASK (~(3<<10))
-#define ADPA_DPMS_ON (0<<10)
-#define ADPA_DPMS_SUSPEND (1<<10)
-#define ADPA_DPMS_STANDBY (2<<10)
-#define ADPA_DPMS_OFF (3<<10)
-
-#define NOPID 0x2094
-#define LP_RING 0x2030
-#define HP_RING 0x2040
-/* The binner has its own ring buffer:
- */
-#define HWB_RING 0x2400
-
-#define RING_TAIL 0x00
-#define TAIL_ADDR 0x001FFFF8
-#define RING_HEAD 0x04
-#define HEAD_WRAP_COUNT 0xFFE00000
-#define HEAD_WRAP_ONE 0x00200000
-#define HEAD_ADDR 0x001FFFFC
-#define RING_START 0x08
-#define START_ADDR 0x0xFFFFF000
-#define RING_LEN 0x0C
-#define RING_NR_PAGES 0x001FF000
-#define RING_REPORT_MASK 0x00000006
-#define RING_REPORT_64K 0x00000002
-#define RING_REPORT_128K 0x00000004
-#define RING_NO_REPORT 0x00000000
-#define RING_VALID_MASK 0x00000001
-#define RING_VALID 0x00000001
-#define RING_INVALID 0x00000000
-
-/* Instruction parser error reg:
- */
-#define IPEIR 0x2088
-
-/* Scratch pad debug 0 reg:
- */
-#define SCPD0 0x209c
-
-/* Error status reg:
- */
-#define ESR 0x20b8
-
-/* Secondary DMA fetch address debug reg:
- */
-#define DMA_FADD_S 0x20d4
-
-/* Memory Interface Arbitration State
- */
-#define MI_ARB_STATE 0x20e4
-
-/* Cache mode 0 reg.
- * - Manipulating render cache behaviour is central
- * to the concept of zone rendering, tuning this reg can help avoid
- * unnecessary render cache reads and even writes (for z/stencil)
- * at beginning and end of scene.
- *
- * - To change a bit, write to this reg with a mask bit set and the
- * bit of interest either set or cleared. EG: (BIT<<16) | BIT to set.
- */
-#define Cache_Mode_0 0x2120
-#define CACHE_MODE_0 0x2120
-#define CM0_MASK_SHIFT 16
-#define CM0_IZ_OPT_DISABLE (1<<6)
-#define CM0_ZR_OPT_DISABLE (1<<5)
-#define CM0_DEPTH_EVICT_DISABLE (1<<4)
-#define CM0_COLOR_EVICT_DISABLE (1<<3)
-#define CM0_DEPTH_WRITE_DISABLE (1<<1)
-#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
-
-
-/* Graphics flush control. A CPU write flushes the GWB of all writes.
- * The data is discarded.
- */
-#define GFX_FLSH_CNTL 0x2170
-
-/* Binner control. Defines the location of the bin pointer list:
- */
-#define BINCTL 0x2420
-#define BC_MASK (1 << 9)
-
-/* Binned scene info.
- */
-#define BINSCENE 0x2428
-#define BS_OP_LOAD (1 << 8)
-#define BS_MASK (1 << 22)
-
-/* Bin command parser debug reg:
- */
-#define BCPD 0x2480
-
-/* Bin memory control debug reg:
- */
-#define BMCD 0x2484
-
-/* Bin data cache debug reg:
- */
-#define BDCD 0x2488
-
-/* Binner pointer cache debug reg:
- */
-#define BPCD 0x248c
-
-/* Binner scratch pad debug reg:
- */
-#define BINSKPD 0x24f0
-
-/* HWB scratch pad debug reg:
- */
-#define HWBSKPD 0x24f4
-
-/* Binner memory pool reg:
- */
-#define BMP_BUFFER 0x2430
-#define BMP_PAGE_SIZE_4K (0 << 10)
-#define BMP_BUFFER_SIZE_SHIFT 1
-#define BMP_ENABLE (1 << 0)
-
-/* Get/put memory from the binner memory pool:
- */
-#define BMP_GET 0x2438
-#define BMP_PUT 0x2440
-#define BMP_OFFSET_SHIFT 5
-
-/* 3D state packets:
- */
-#define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24))
-
-#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR (0x1<<1)
-#define SC_ENABLE_MASK (0x1<<0)
-#define SC_ENABLE (0x1<<0)
-
-#define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-
-#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK (0xffff<<16)
-#define SCI_XMIN_MASK (0xffff<<0)
-#define SCI_YMAX_MASK (0xffff<<16)
-#define SCI_XMAX_MASK (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-
-#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
-
-#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4)
-#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
-#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
-#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
-
-#define MI_BATCH_BUFFER ((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START (0x31<<23)
-#define MI_BATCH_BUFFER_END (0xA<<23)
-#define MI_BATCH_NON_SECURE (1)
-#define MI_BATCH_NON_SECURE_I965 (1<<8)
-
-#define MI_WAIT_FOR_EVENT ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
-#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP (1<<22)
-#define DISPLAY_PLANE_A (0<<20)
-#define DISPLAY_PLANE_B (1<<20)
-
-/* Display regs */
-#define DSPACNTR 0x70180
-#define DSPBCNTR 0x71180
-#define DISPPLANE_SEL_PIPE_MASK (1<<24)
-
-/* Define the region of interest for the binner:
- */
-#define CMD_OP_BIN_CONTROL ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
-
-#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_MI_FLUSH (0x04 << 23)
-#define MI_NO_WRITE_FLUSH (1 << 2)
-#define MI_READ_FLUSH (1 << 0)
-#define MI_EXE_FLUSH (1 << 1)
-#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
-#define MI_SCENE_COUNT (1 << 3) /* just increment scene count */
-
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
-#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
-#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
-
-#define BLC_PWM_CTL 0x61254
-#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
-
-#define BLC_PWM_CTL2 0x61250
-/**
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
-#define BLM_LEGACY_MODE (1 << 16)
-/**
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
-#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
-
-#define I915_GCFGC 0xf0
-#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
-#define I915_DISPLAY_CLOCK_MASK (7 << 4)
-
-#define I855_HPLLCC 0xc0
-#define I855_CLOCK_CONTROL_MASK (3 << 0)
-#define I855_CLOCK_133_200 (0 << 0)
-#define I855_CLOCK_100_200 (1 << 0)
-#define I855_CLOCK_100_133 (2 << 0)
-#define I855_CLOCK_166_250 (3 << 0)
-
-/* p317, 319
- */
-#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */
-#define VCLK2_VCO_N 0x600a
-#define VCLK2_VCO_DIV_SEL 0x6012
-
-#define VCLK_DIVISOR_VGA0 0x6000
-#define VCLK_DIVISOR_VGA1 0x6004
-#define VCLK_POST_DIV 0x6010
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA1_PD_P2_DIV_4 (1 << 15)
-/** Overrides the p2 post divisor field */
-# define VGA1_PD_P1_DIV_2 (1 << 13)
-# define VGA1_PD_P1_SHIFT 8
-/** P1 value is 2 greater than this field */
-# define VGA1_PD_P1_MASK (0x1f << 8)
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA0_PD_P2_DIV_4 (1 << 7)
-/** Overrides the p2 post divisor field */
-# define VGA0_PD_P1_DIV_2 (1 << 5)
-# define VGA0_PD_P1_SHIFT 0
-/** P1 value is 2 greater than this field */
-# define VGA0_PD_P1_MASK (0x1f << 0)
-
-/* PCI D state control register */
-#define D_STATE 0x6104
-#define DSPCLK_GATE_D 0x6200
-
-/* I830 CRTC registers */
-#define HTOTAL_A 0x60000
-#define HBLANK_A 0x60004
-#define HSYNC_A 0x60008
-#define VTOTAL_A 0x6000c
-#define VBLANK_A 0x60010
-#define VSYNC_A 0x60014
-#define PIPEASRC 0x6001c
-#define BCLRPAT_A 0x60020
-#define VSYNCSHIFT_A 0x60028
-
-#define HTOTAL_B 0x61000
-#define HBLANK_B 0x61004
-#define HSYNC_B 0x61008
-#define VTOTAL_B 0x6100c
-#define VBLANK_B 0x61010
-#define VSYNC_B 0x61014
-#define PIPEBSRC 0x6101c
-#define BCLRPAT_B 0x61020
-#define VSYNCSHIFT_B 0x61028
-
-#define PP_STATUS 0x61200
-# define PP_ON (1 << 31)
-/**
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-# define PP_READY (1 << 30)
-# define PP_SEQUENCE_NONE (0 << 28)
-# define PP_SEQUENCE_ON (1 << 28)
-# define PP_SEQUENCE_OFF (2 << 28)
-# define PP_SEQUENCE_MASK 0x30000000
-#define PP_CONTROL 0x61204
-# define POWER_TARGET_ON (1 << 0)
-
-#define LVDSPP_ON 0x61208
-#define LVDSPP_OFF 0x6120c
-#define PP_CYCLE 0x61210
-
-#define PFIT_CONTROL 0x61230
-# define PFIT_ENABLE (1 << 31)
-# define PFIT_PIPE_MASK (3 << 29)
-# define PFIT_PIPE_SHIFT 29
-# define VERT_INTERP_DISABLE (0 << 10)
-# define VERT_INTERP_BILINEAR (1 << 10)
-# define VERT_INTERP_MASK (3 << 10)
-# define VERT_AUTO_SCALE (1 << 9)
-# define HORIZ_INTERP_DISABLE (0 << 6)
-# define HORIZ_INTERP_BILINEAR (1 << 6)
-# define HORIZ_INTERP_MASK (3 << 6)
-# define HORIZ_AUTO_SCALE (1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
-
-#define PFIT_PGM_RATIOS 0x61234
-# define PFIT_VERT_SCALE_MASK 0xfff00000
-# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
-
-#define PFIT_AUTO_RATIOS 0x61238
-
-
-#define DPLL_A 0x06014
-#define DPLL_B 0x06018
-# define DPLL_VCO_ENABLE (1 << 31)
-# define DPLL_DVO_HIGH_SPEED (1 << 30)
-# define DPLL_SYNCLOCK_ENABLE (1 << 29)
-# define DPLL_VGA_MODE_DIS (1 << 28)
-# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
-# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
-# define DPLL_MODE_MASK (3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
-/**
- * The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
-/**
- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
- * this field (only one bit may be set).
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
-# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
-# define PLL_REF_INPUT_DREFCLK (0 << 13)
-# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
-# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
-# define PLL_REF_INPUT_MASK (3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT 9
-/*
- * Parallel to Serial Load Pulse phase selection.
- * Selects the phase for the 10X DPLL clock for the PCIe
- * digital display port. The range is 4 to 13; 10 or more
- * is just a flip delay. The default is 6
- */
-# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
-
-/**
- * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-# define SDVO_MULTIPLIER_MASK 0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES 4
-# define SDVO_MULTIPLIER_SHIFT_VGA 0
-
-/** @defgroup DPLL_MD
- * @{
- */
-/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD 0x0601c
-/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD 0x06020
-/**
- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
- *
- * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
- */
-# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT 24
-/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
-/**
- * SDVO/UDI pixel multiplier.
- *
- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
- * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
- * dummy bytes in the datastream at an increased clock rate, with both sides of
- * the link knowing how many bytes are fill.
- *
- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
- * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
- * through an SDVO command.
- *
- * This register field has values of multiplication factor minus 1, with
- * a maximum multiplier of 5 for SDVO.
- */
-# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
-/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
- * This best be set to the default value (3) or the CRT won't work. No,
- * I don't entirely understand what this does...
- */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
-/** @} */
-
-#define DPLL_TEST 0x606c
-# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
-# define DPLLB_TEST_N_BYPASS (1 << 19)
-# define DPLLB_TEST_M_BYPASS (1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
-# define DPLLA_TEST_N_BYPASS (1 << 3)
-# define DPLLA_TEST_M_BYPASS (1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
-
-#define ADPA 0x61100
-#define ADPA_DAC_ENABLE (1<<31)
-#define ADPA_DAC_DISABLE 0
-#define ADPA_PIPE_SELECT_MASK (1<<30)
-#define ADPA_PIPE_A_SELECT 0
-#define ADPA_PIPE_B_SELECT (1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY 0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE 0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE 0
-#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW 0
-#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW 0
-
-#define FPA0 0x06040
-#define FPA1 0x06044
-#define FPB0 0x06048
-#define FPB1 0x0604c
-# define FP_N_DIV_MASK 0x003f0000
-# define FP_N_DIV_SHIFT 16
-# define FP_M1_DIV_MASK 0x00003f00
-# define FP_M1_DIV_SHIFT 8
-# define FP_M2_DIV_MASK 0x0000003f
-# define FP_M2_DIV_SHIFT 0
-
-
-#define PORT_HOTPLUG_EN 0x61110
-# define SDVOB_HOTPLUG_INT_EN (1 << 26)
-# define SDVOC_HOTPLUG_INT_EN (1 << 25)
-# define TV_HOTPLUG_INT_EN (1 << 18)
-# define CRT_HOTPLUG_INT_EN (1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
-
-#define PORT_HOTPLUG_STAT 0x61114
-# define CRT_HOTPLUG_INT_STATUS (1 << 11)
-# define TV_HOTPLUG_INT_STATUS (1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
-
-#define SDVOB 0x61140
-#define SDVOC 0x61160
-#define SDVO_ENABLE (1 << 31)
-#define SDVO_PIPE_B_SELECT (1 << 30)
-#define SDVO_STALL_SELECT (1 << 29)
-#define SDVO_INTERRUPT_ENABLE (1 << 26)
/**
- * 915G/GM SDVO pixel multiplier.
+ * Reads a dword out of the status page, which is written to from the command
+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
+ * MI_STORE_DATA_IMM.
*
- * Programmed value is multiplier - 1, up to 5x.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT 23
-#define SDVO_PHASE_SELECT_MASK (15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
-#define SDVOC_GANG_MODE (1 << 16)
-#define SDVO_BORDER_ENABLE (1 << 7)
-#define SDVOB_PCIE_CONCURRENCY (1 << 3)
-#define SDVO_DETECTED (1 << 2)
-/* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK (1 << 17)
-
-/** @defgroup LVDS
- * @{
- */
-/**
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
+ * The following dwords have a reserved meaning:
+ * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
+ * 0x04: ring 0 head pointer
+ * 0x05: ring 1 head pointer (915-class)
+ * 0x06: ring 2 head pointer (915-class)
+ * 0x10-0x1b: Context status DWords (GM45)
+ * 0x1f: Last written status offset. (GM45)
*
- * All of the clock/data pairs are force powered down by power sequencing.
- */
-#define LVDS 0x61180
-/**
- * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
- * the DPLL semantics change when the LVDS is assigned to that pipe.
- */
-# define LVDS_PORT_EN (1 << 31)
-/** Selects pipe B for LVDS data. Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT (1 << 30)
-
-/**
- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
- * pixel.
- */
-# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
-/**
- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
- * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
- * on.
- */
-# define LVDS_A3_POWER_MASK (3 << 6)
-# define LVDS_A3_POWER_DOWN (0 << 6)
-# define LVDS_A3_POWER_UP (3 << 6)
-/**
- * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
- * is set.
- */
-# define LVDS_CLKB_POWER_MASK (3 << 4)
-# define LVDS_CLKB_POWER_DOWN (0 << 4)
-# define LVDS_CLKB_POWER_UP (3 << 4)
-
-/**
- * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
- * setting for whether we are in dual-channel mode. The B3 pair will
- * additionally only be powered up when LVDS_A3_POWER_UP is set.
- */
-# define LVDS_B0B3_POWER_MASK (3 << 2)
-# define LVDS_B0B3_POWER_DOWN (0 << 2)
-# define LVDS_B0B3_POWER_UP (3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE (1<<31)
-#define PIPEACONF_DISABLE 0
-#define PIPEACONF_DOUBLE_WIDE (1<<30)
-#define I965_PIPECONF_ACTIVE (1<<30)
-#define PIPEACONF_SINGLE_WIDE 0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_PIPE_LOCKED (1<<25)
-#define PIPEACONF_PALETTE 0
-#define PIPEACONF_GAMMA (1<<24)
-#define PIPECONF_FORCE_BORDER (1<<25)
-#define PIPECONF_PROGRESSIVE (0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
-
-#define DSPARB 0x70030
-#define DSPARB_CSTART_MASK (0x7f << 7)
-#define DSPARB_CSTART_SHIFT 7
-#define DSPARB_BSTART_MASK (0x7f)
-#define DSPARB_BSTART_SHIFT 0
-
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE (1<<31)
-#define PIPEBCONF_DISABLE 0
-#define PIPEBCONF_DOUBLE_WIDE (1<<30)
-#define PIPEBCONF_DISABLE 0
-#define PIPEBCONF_GAMMA (1<<24)
-#define PIPEBCONF_PALETTE 0
-
-#define PIPEBGCMAXRED 0x71010
-#define PIPEBGCMAXGREEN 0x71014
-#define PIPEBGCMAXBLUE 0x71018
-#define PIPEBSTAT 0x71024
-#define PIPEBFRAMEHIGH 0x71040
-#define PIPEBFRAMEPIXEL 0x71044
-
-#define DSPACNTR 0x70180
-#define DSPBCNTR 0x71180
-#define DISPLAY_PLANE_ENABLE (1<<31)
-#define DISPLAY_PLANE_DISABLE 0
-#define DISPPLANE_GAMMA_ENABLE (1<<30)
-#define DISPPLANE_GAMMA_DISABLE 0
-#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
-#define DISPPLANE_8BPP (0x2<<26)
-#define DISPPLANE_15_16BPP (0x4<<26)
-#define DISPPLANE_16BPP (0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
-#define DISPPLANE_32BPP (0x7<<26)
-#define DISPPLANE_STEREO_ENABLE (1<<25)
-#define DISPPLANE_STEREO_DISABLE 0
-#define DISPPLANE_SEL_PIPE_MASK (1<<24)
-#define DISPPLANE_SEL_PIPE_A 0
-#define DISPPLANE_SEL_PIPE_B (1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
-#define DISPPLANE_SRC_KEY_DISABLE 0
-#define DISPPLANE_LINE_DOUBLE (1<<20)
-#define DISPPLANE_NO_LINE_DOUBLE 0
-#define DISPPLANE_STEREO_POLARITY_FIRST 0
-#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE 0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
-
-#define DSPABASE 0x70184
-#define DSPASTRIDE 0x70188
-
-#define DSPBBASE 0x71184
-#define DSPBADDR DSPBBASE
-#define DSPBSTRIDE 0x71188
-
-#define DSPAKEYVAL 0x70194
-#define DSPAKEYMASK 0x70198
-
-#define DSPAPOS 0x7018C /* reserved */
-#define DSPASIZE 0x70190
-#define DSPBPOS 0x7118C
-#define DSPBSIZE 0x71190
-
-#define DSPASURF 0x7019C
-#define DSPATILEOFF 0x701A4
-
-#define DSPBSURF 0x7119C
-#define DSPBTILEOFF 0x711A4
-
-#define VGACNTRL 0x71400
-# define VGA_DISP_DISABLE (1 << 31)
-# define VGA_2X_MODE (1 << 30)
-# define VGA_PIPE_B_SELECT (1 << 29)
-
-/*
- * Some BIOS scratch area registers. The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-
-#define SWF0 0x71410
-
-/*
- * 855 scratch registers.
- */
-#define SWF10 0x70410
-
-#define SWF30 0x72414
-
-/*
- * Overlay registers. These are overlay registers accessed via MMIO.
- * Those loaded via the overlay register page are defined in i830_video.c.
+ * The area from dword 0x20 to 0x3ff is available for driver usage.
*/
-#define OVADD 0x30000
-
-#define DOVSTA 0x30008
-#define OC_BUF (0x3<<20)
+#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
+#define I915_GEM_HWS_INDEX 0x20
-#define OGAMC5 0x30010
-#define OGAMC4 0x30014
-#define OGAMC3 0x30018
-#define OGAMC2 0x3001c
-#define OGAMC1 0x30020
-#define OGAMC0 0x30024
-/*
- * Palette registers
- */
-#define PALETTE_A 0x0a000
-#define PALETTE_B 0x0a800
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
#define IS_845G(dev) ((dev)->pci_device == 0x2562)
@@ -1119,7 +639,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
-#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
+#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \
@@ -1133,9 +653,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
- IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
+ IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev) || IS_G4X(dev))
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
new file mode 100644
index 00000000000..9ac73dd1b42
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -0,0 +1,2558 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include <linux/swap.h>
+
+static int
+i915_gem_object_set_domain(struct drm_gem_object *obj,
+ uint32_t read_domains,
+ uint32_t write_domain);
+static int
+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
+ uint64_t offset,
+ uint64_t size,
+ uint32_t read_domains,
+ uint32_t write_domain);
+static int
+i915_gem_set_domain(struct drm_gem_object *obj,
+ struct drm_file *file_priv,
+ uint32_t read_domains,
+ uint32_t write_domain);
+static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
+static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
+static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
+
+static void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+
+int
+i915_gem_init_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_init *args = data;
+
+ mutex_lock(&dev->struct_mutex);
+
+ if (args->gtt_start >= args->gtt_end ||
+ (args->gtt_start & (PAGE_SIZE - 1)) != 0 ||
+ (args->gtt_end & (PAGE_SIZE - 1)) != 0) {
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+
+ drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start,
+ args->gtt_end - args->gtt_start);
+
+ dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_create *args = data;
+ struct drm_gem_object *obj;
+ int handle, ret;
+
+ args->size = roundup(args->size, PAGE_SIZE);
+
+ /* Allocate the new object */
+ obj = drm_gem_object_alloc(dev, args->size);
+ if (obj == NULL)
+ return -ENOMEM;
+
+ ret = drm_gem_handle_create(file_priv, obj, &handle);
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_handle_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ if (ret)
+ return ret;
+
+ args->handle = handle;
+
+ return 0;
+}
+
+/**
+ * Reads data from the object referenced by handle.
+ *
+ * On error, the contents of *data are undefined.
+ */
+int
+i915_gem_pread_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_pread *args = data;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ ssize_t read;
+ loff_t offset;
+ int ret;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EBADF;
+ obj_priv = obj->driver_private;
+
+ /* Bounds check source.
+ *
+ * XXX: This could use review for overflow issues...
+ */
+ if (args->offset > obj->size || args->size > obj->size ||
+ args->offset + args->size > obj->size) {
+ drm_gem_object_unreference(obj);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->struct_mutex);
+
+ ret = i915_gem_object_set_domain_range(obj, args->offset, args->size,
+ I915_GEM_DOMAIN_CPU, 0);
+ if (ret != 0) {
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+
+ offset = args->offset;
+
+ read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
+ args->size, &offset);
+ if (read != args->size) {
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ if (read < 0)
+ return read;
+ else
+ return -EINVAL;
+ }
+
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+static int
+i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ ssize_t remain;
+ loff_t offset;
+ char __user *user_data;
+ char __iomem *vaddr;
+ char *vaddr_atomic;
+ int i, o, l;
+ int ret = 0;
+ unsigned long pfn;
+ unsigned long unwritten;
+
+ user_data = (char __user *) (uintptr_t) args->data_ptr;
+ remain = args->size;
+ if (!access_ok(VERIFY_READ, user_data, remain))
+ return -EFAULT;
+
+
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_gem_object_pin(obj, 0);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+ ret = i915_gem_set_domain(obj, file_priv,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ if (ret)
+ goto fail;
+
+ obj_priv = obj->driver_private;
+ offset = obj_priv->gtt_offset + args->offset;
+ obj_priv->dirty = 1;
+
+ while (remain > 0) {
+ /* Operation in this page
+ *
+ * i = page number
+ * o = offset within page
+ * l = bytes to copy
+ */
+ i = offset >> PAGE_SHIFT;
+ o = offset & (PAGE_SIZE-1);
+ l = remain;
+ if ((o + l) > PAGE_SIZE)
+ l = PAGE_SIZE - o;
+
+ pfn = (dev->agp->base >> PAGE_SHIFT) + i;
+
+#ifdef CONFIG_HIGHMEM
+ /* This is a workaround for the low performance of iounmap
+ * (approximate 10% cpu cost on normal 3D workloads).
+ * kmap_atomic on HIGHMEM kernels happens to let us map card
+ * memory without taking IPIs. When the vmap rework lands
+ * we should be able to dump this hack.
+ */
+ vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
+#if WATCH_PWRITE
+ DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
+ i, o, l, pfn, vaddr_atomic);
+#endif
+ unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o,
+ user_data, l);
+ kunmap_atomic(vaddr_atomic, KM_USER0);
+
+ if (unwritten)
+#endif /* CONFIG_HIGHMEM */
+ {
+ vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE);
+#if WATCH_PWRITE
+ DRM_INFO("pwrite slow i %d o %d l %d "
+ "pfn %ld vaddr %p\n",
+ i, o, l, pfn, vaddr);
+#endif
+ if (vaddr == NULL) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ unwritten = __copy_from_user(vaddr + o, user_data, l);
+#if WATCH_PWRITE
+ DRM_INFO("unwritten %ld\n", unwritten);
+#endif
+ iounmap(vaddr);
+ if (unwritten) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ }
+
+ remain -= l;
+ user_data += l;
+ offset += l;
+ }
+#if WATCH_PWRITE && 1
+ i915_gem_clflush_object(obj);
+ i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0);
+ i915_gem_clflush_object(obj);
+#endif
+
+fail:
+ i915_gem_object_unpin(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ return ret;
+}
+
+static int
+i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file_priv)
+{
+ int ret;
+ loff_t offset;
+ ssize_t written;
+
+ mutex_lock(&dev->struct_mutex);
+
+ ret = i915_gem_set_domain(obj, file_priv,
+ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+
+ offset = args->offset;
+
+ written = vfs_write(obj->filp,
+ (char __user *)(uintptr_t) args->data_ptr,
+ args->size, &offset);
+ if (written != args->size) {
+ mutex_unlock(&dev->struct_mutex);
+ if (written < 0)
+ return written;
+ else
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+/**
+ * Writes data to the object referenced by handle.
+ *
+ * On error, the contents of the buffer that were to be modified are undefined.
+ */
+int
+i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_pwrite *args = data;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EBADF;
+ obj_priv = obj->driver_private;
+
+ /* Bounds check destination.
+ *
+ * XXX: This could use review for overflow issues...
+ */
+ if (args->offset > obj->size || args->size > obj->size ||
+ args->offset + args->size > obj->size) {
+ drm_gem_object_unreference(obj);
+ return -EINVAL;
+ }
+
+ /* We can only do the GTT pwrite on untiled buffers, as otherwise
+ * it would end up going through the fenced access, and we'll get
+ * different detiling behavior between reading and writing.
+ * pread/pwrite currently are reading and writing from the CPU
+ * perspective, requiring manual detiling by the client.
+ */
+ if (obj_priv->tiling_mode == I915_TILING_NONE &&
+ dev->gtt_total != 0)
+ ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
+ else
+ ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
+
+#if WATCH_PWRITE
+ if (ret)
+ DRM_INFO("pwrite failed %d\n", ret);
+#endif
+
+ drm_gem_object_unreference(obj);
+
+ return ret;
+}
+
+/**
+ * Called when user space prepares to use an object
+ */
+int
+i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_set_domain *args = data;
+ struct drm_gem_object *obj;
+ int ret;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EBADF;
+
+ mutex_lock(&dev->struct_mutex);
+#if WATCH_BUF
+ DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
+ obj, obj->size, args->read_domains, args->write_domain);
+#endif
+ ret = i915_gem_set_domain(obj, file_priv,
+ args->read_domains, args->write_domain);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+/**
+ * Called when user space has done writes to this buffer
+ */
+int
+i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_sw_finish *args = data;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ mutex_lock(&dev->struct_mutex);
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL) {
+ mutex_unlock(&dev->struct_mutex);
+ return -EBADF;
+ }
+
+#if WATCH_BUF
+ DRM_INFO("%s: sw_finish %d (%p %d)\n",
+ __func__, args->handle, obj, obj->size);
+#endif
+ obj_priv = obj->driver_private;
+
+ /* Pinned buffers may be scanout, so flush the cache */
+ if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) {
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+ }
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+/**
+ * Maps the contents of an object, returning the address it is mapped
+ * into.
+ *
+ * While the mapping holds a reference on the contents of the object, it doesn't
+ * imply a ref on the object itself.
+ */
+int
+i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_mmap *args = data;
+ struct drm_gem_object *obj;
+ loff_t offset;
+ unsigned long addr;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EBADF;
+
+ offset = args->offset;
+
+ down_write(&current->mm->mmap_sem);
+ addr = do_mmap(obj->filp, 0, args->size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ args->offset);
+ up_write(&current->mm->mmap_sem);
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ if (IS_ERR((void *)addr))
+ return addr;
+
+ args->addr_ptr = (uint64_t) addr;
+
+ return 0;
+}
+
+static void
+i915_gem_object_free_page_list(struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page_count = obj->size / PAGE_SIZE;
+ int i;
+
+ if (obj_priv->page_list == NULL)
+ return;
+
+
+ for (i = 0; i < page_count; i++)
+ if (obj_priv->page_list[i] != NULL) {
+ if (obj_priv->dirty)
+ set_page_dirty(obj_priv->page_list[i]);
+ mark_page_accessed(obj_priv->page_list[i]);
+ page_cache_release(obj_priv->page_list[i]);
+ }
+ obj_priv->dirty = 0;
+
+ drm_free(obj_priv->page_list,
+ page_count * sizeof(struct page *),
+ DRM_MEM_DRIVER);
+ obj_priv->page_list = NULL;
+}
+
+static void
+i915_gem_object_move_to_active(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ /* Add a reference if we're newly entering the active list. */
+ if (!obj_priv->active) {
+ drm_gem_object_reference(obj);
+ obj_priv->active = 1;
+ }
+ /* Move from whatever list we were on to the tail of execution. */
+ list_move_tail(&obj_priv->list,
+ &dev_priv->mm.active_list);
+}
+
+
+static void
+i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+ if (obj_priv->pin_count != 0)
+ list_del_init(&obj_priv->list);
+ else
+ list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
+
+ if (obj_priv->active) {
+ obj_priv->active = 0;
+ drm_gem_object_unreference(obj);
+ }
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+}
+
+/**
+ * Creates a new sequence number, emitting a write of it to the status page
+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
+ *
+ * Must be called with struct_lock held.
+ *
+ * Returned sequence numbers are nonzero on success.
+ */
+static uint32_t
+i915_add_request(struct drm_device *dev, uint32_t flush_domains)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_request *request;
+ uint32_t seqno;
+ int was_empty;
+ RING_LOCALS;
+
+ request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
+ if (request == NULL)
+ return 0;
+
+ /* Grab the seqno we're going to make this request be, and bump the
+ * next (skipping 0 so it can be the reserved no-seqno value).
+ */
+ seqno = dev_priv->mm.next_gem_seqno;
+ dev_priv->mm.next_gem_seqno++;
+ if (dev_priv->mm.next_gem_seqno == 0)
+ dev_priv->mm.next_gem_seqno++;
+
+ BEGIN_LP_RING(4);
+ OUT_RING(MI_STORE_DWORD_INDEX);
+ OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+ OUT_RING(seqno);
+
+ OUT_RING(MI_USER_INTERRUPT);
+ ADVANCE_LP_RING();
+
+ DRM_DEBUG("%d\n", seqno);
+
+ request->seqno = seqno;
+ request->emitted_jiffies = jiffies;
+ request->flush_domains = flush_domains;
+ was_empty = list_empty(&dev_priv->mm.request_list);
+ list_add_tail(&request->list, &dev_priv->mm.request_list);
+
+ if (was_empty && !dev_priv->mm.suspended)
+ schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+ return seqno;
+}
+
+/**
+ * Command execution barrier
+ *
+ * Ensures that all commands in the ring are finished
+ * before signalling the CPU
+ */
+static uint32_t
+i915_retire_commands(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+ uint32_t flush_domains = 0;
+ RING_LOCALS;
+
+ /* The sampler always gets flushed on i965 (sigh) */
+ if (IS_I965G(dev))
+ flush_domains |= I915_GEM_DOMAIN_SAMPLER;
+ BEGIN_LP_RING(2);
+ OUT_RING(cmd);
+ OUT_RING(0); /* noop */
+ ADVANCE_LP_RING();
+ return flush_domains;
+}
+
+/**
+ * Moves buffers associated only with the given active seqno from the active
+ * to inactive list, potentially freeing them.
+ */
+static void
+i915_gem_retire_request(struct drm_device *dev,
+ struct drm_i915_gem_request *request)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ /* Move any buffers on the active list that are no longer referenced
+ * by the ringbuffer to the flushing/inactive lists as appropriate.
+ */
+ while (!list_empty(&dev_priv->mm.active_list)) {
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ obj_priv = list_first_entry(&dev_priv->mm.active_list,
+ struct drm_i915_gem_object,
+ list);
+ obj = obj_priv->obj;
+
+ /* If the seqno being retired doesn't match the oldest in the
+ * list, then the oldest in the list must still be newer than
+ * this seqno.
+ */
+ if (obj_priv->last_rendering_seqno != request->seqno)
+ return;
+#if WATCH_LRU
+ DRM_INFO("%s: retire %d moves to inactive list %p\n",
+ __func__, request->seqno, obj);
+#endif
+
+ if (obj->write_domain != 0) {
+ list_move_tail(&obj_priv->list,
+ &dev_priv->mm.flushing_list);
+ } else {
+ i915_gem_object_move_to_inactive(obj);
+ }
+ }
+
+ if (request->flush_domains != 0) {
+ struct drm_i915_gem_object *obj_priv, *next;
+
+ /* Clear the write domain and activity from any buffers
+ * that are just waiting for a flush matching the one retired.
+ */
+ list_for_each_entry_safe(obj_priv, next,
+ &dev_priv->mm.flushing_list, list) {
+ struct drm_gem_object *obj = obj_priv->obj;
+
+ if (obj->write_domain & request->flush_domains) {
+ obj->write_domain = 0;
+ i915_gem_object_move_to_inactive(obj);
+ }
+ }
+
+ }
+}
+
+/**
+ * Returns true if seq1 is later than seq2.
+ */
+static int
+i915_seqno_passed(uint32_t seq1, uint32_t seq2)
+{
+ return (int32_t)(seq1 - seq2) >= 0;
+}
+
+uint32_t
+i915_get_gem_seqno(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+}
+
+/**
+ * This function clears the request list as sequence numbers are passed.
+ */
+void
+i915_gem_retire_requests(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t seqno;
+
+ seqno = i915_get_gem_seqno(dev);
+
+ while (!list_empty(&dev_priv->mm.request_list)) {
+ struct drm_i915_gem_request *request;
+ uint32_t retiring_seqno;
+
+ request = list_first_entry(&dev_priv->mm.request_list,
+ struct drm_i915_gem_request,
+ list);
+ retiring_seqno = request->seqno;
+
+ if (i915_seqno_passed(seqno, retiring_seqno) ||
+ dev_priv->mm.wedged) {
+ i915_gem_retire_request(dev, request);
+
+ list_del(&request->list);
+ drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
+ } else
+ break;
+ }
+}
+
+void
+i915_gem_retire_work_handler(struct work_struct *work)
+{
+ drm_i915_private_t *dev_priv;
+ struct drm_device *dev;
+
+ dev_priv = container_of(work, drm_i915_private_t,
+ mm.retire_work.work);
+ dev = dev_priv->dev;
+
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_retire_requests(dev);
+ if (!dev_priv->mm.suspended &&
+ !list_empty(&dev_priv->mm.request_list))
+ schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+ mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+static int
+i915_wait_request(struct drm_device *dev, uint32_t seqno)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret = 0;
+
+ BUG_ON(seqno == 0);
+
+ if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+ dev_priv->mm.waiting_gem_seqno = seqno;
+ i915_user_irq_get(dev);
+ ret = wait_event_interruptible(dev_priv->irq_queue,
+ i915_seqno_passed(i915_get_gem_seqno(dev),
+ seqno) ||
+ dev_priv->mm.wedged);
+ i915_user_irq_put(dev);
+ dev_priv->mm.waiting_gem_seqno = 0;
+ }
+ if (dev_priv->mm.wedged)
+ ret = -EIO;
+
+ if (ret && ret != -ERESTARTSYS)
+ DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
+ __func__, ret, seqno, i915_get_gem_seqno(dev));
+
+ /* Directly dispatch request retiring. While we have the work queue
+ * to handle this, the waiter on a request often wants an associated
+ * buffer to have made it to the inactive list, and we would need
+ * a separate wait queue to handle that.
+ */
+ if (ret == 0)
+ i915_gem_retire_requests(dev);
+
+ return ret;
+}
+
+static void
+i915_gem_flush(struct drm_device *dev,
+ uint32_t invalidate_domains,
+ uint32_t flush_domains)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t cmd;
+ RING_LOCALS;
+
+#if WATCH_EXEC
+ DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
+ invalidate_domains, flush_domains);
+#endif
+
+ if (flush_domains & I915_GEM_DOMAIN_CPU)
+ drm_agp_chipset_flush(dev);
+
+ if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT)) {
+ /*
+ * read/write caches:
+ *
+ * I915_GEM_DOMAIN_RENDER is always invalidated, but is
+ * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is
+ * also flushed at 2d versus 3d pipeline switches.
+ *
+ * read-only caches:
+ *
+ * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
+ * MI_READ_FLUSH is set, and is always flushed on 965.
+ *
+ * I915_GEM_DOMAIN_COMMAND may not exist?
+ *
+ * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
+ * invalidated when MI_EXE_FLUSH is set.
+ *
+ * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
+ * invalidated with every MI_FLUSH.
+ *
+ * TLBs:
+ *
+ * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
+ * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
+ * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
+ * are flushed at any MI_FLUSH.
+ */
+
+ cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+ if ((invalidate_domains|flush_domains) &
+ I915_GEM_DOMAIN_RENDER)
+ cmd &= ~MI_NO_WRITE_FLUSH;
+ if (!IS_I965G(dev)) {
+ /*
+ * On the 965, the sampler cache always gets flushed
+ * and this bit is reserved.
+ */
+ if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+ cmd |= MI_READ_FLUSH;
+ }
+ if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+ cmd |= MI_EXE_FLUSH;
+
+#if WATCH_EXEC
+ DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
+#endif
+ BEGIN_LP_RING(2);
+ OUT_RING(cmd);
+ OUT_RING(0); /* noop */
+ ADVANCE_LP_RING();
+ }
+}
+
+/**
+ * Ensures that all rendering to the object has completed and the object is
+ * safe to unbind from the GTT or access from the CPU.
+ */
+static int
+i915_gem_object_wait_rendering(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int ret;
+
+ /* If there are writes queued to the buffer, flush and
+ * create a new seqno to wait for.
+ */
+ if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) {
+ uint32_t write_domain = obj->write_domain;
+#if WATCH_BUF
+ DRM_INFO("%s: flushing object %p from write domain %08x\n",
+ __func__, obj, write_domain);
+#endif
+ i915_gem_flush(dev, 0, write_domain);
+
+ i915_gem_object_move_to_active(obj);
+ obj_priv->last_rendering_seqno = i915_add_request(dev,
+ write_domain);
+ BUG_ON(obj_priv->last_rendering_seqno == 0);
+#if WATCH_LRU
+ DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj);
+#endif
+ }
+
+ /* If there is rendering queued on the buffer being evicted, wait for
+ * it.
+ */
+ if (obj_priv->active) {
+#if WATCH_BUF
+ DRM_INFO("%s: object %p wait for seqno %08x\n",
+ __func__, obj, obj_priv->last_rendering_seqno);
+#endif
+ ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
+ if (ret != 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * Unbinds an object from the GTT aperture.
+ */
+static int
+i915_gem_object_unbind(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int ret = 0;
+
+#if WATCH_BUF
+ DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj);
+ DRM_INFO("gtt_space %p\n", obj_priv->gtt_space);
+#endif
+ if (obj_priv->gtt_space == NULL)
+ return 0;
+
+ if (obj_priv->pin_count != 0) {
+ DRM_ERROR("Attempting to unbind pinned buffer\n");
+ return -EINVAL;
+ }
+
+ /* Wait for any rendering to complete
+ */
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret) {
+ DRM_ERROR("wait_rendering failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Move the object to the CPU domain to ensure that
+ * any possible CPU writes while it's not in the GTT
+ * are flushed when we go to remap it. This will
+ * also ensure that all pending GPU writes are finished
+ * before we unbind.
+ */
+ ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU,
+ I915_GEM_DOMAIN_CPU);
+ if (ret) {
+ DRM_ERROR("set_domain failed: %d\n", ret);
+ return ret;
+ }
+
+ if (obj_priv->agp_mem != NULL) {
+ drm_unbind_agp(obj_priv->agp_mem);
+ drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
+ obj_priv->agp_mem = NULL;
+ }
+
+ BUG_ON(obj_priv->active);
+
+ i915_gem_object_free_page_list(obj);
+
+ if (obj_priv->gtt_space) {
+ atomic_dec(&dev->gtt_count);
+ atomic_sub(obj->size, &dev->gtt_memory);
+
+ drm_mm_put_block(obj_priv->gtt_space);
+ obj_priv->gtt_space = NULL;
+ }
+
+ /* Remove ourselves from the LRU list if present. */
+ if (!list_empty(&obj_priv->list))
+ list_del_init(&obj_priv->list);
+
+ return 0;
+}
+
+static int
+i915_gem_evict_something(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
+
+ for (;;) {
+ /* If there's an inactive buffer available now, grab it
+ * and be done.
+ */
+ if (!list_empty(&dev_priv->mm.inactive_list)) {
+ obj_priv = list_first_entry(&dev_priv->mm.inactive_list,
+ struct drm_i915_gem_object,
+ list);
+ obj = obj_priv->obj;
+ BUG_ON(obj_priv->pin_count != 0);
+#if WATCH_LRU
+ DRM_INFO("%s: evicting %p\n", __func__, obj);
+#endif
+ BUG_ON(obj_priv->active);
+
+ /* Wait on the rendering and unbind the buffer. */
+ ret = i915_gem_object_unbind(obj);
+ break;
+ }
+
+ /* If we didn't get anything, but the ring is still processing
+ * things, wait for one of those things to finish and hopefully
+ * leave us a buffer to evict.
+ */
+ if (!list_empty(&dev_priv->mm.request_list)) {
+ struct drm_i915_gem_request *request;
+
+ request = list_first_entry(&dev_priv->mm.request_list,
+ struct drm_i915_gem_request,
+ list);
+
+ ret = i915_wait_request(dev, request->seqno);
+ if (ret)
+ break;
+
+ /* if waiting caused an object to become inactive,
+ * then loop around and wait for it. Otherwise, we
+ * assume that waiting freed and unbound something,
+ * so there should now be some space in the GTT
+ */
+ if (!list_empty(&dev_priv->mm.inactive_list))
+ continue;
+ break;
+ }
+
+ /* If we didn't have anything on the request list but there
+ * are buffers awaiting a flush, emit one and try again.
+ * When we wait on it, those buffers waiting for that flush
+ * will get moved to inactive.
+ */
+ if (!list_empty(&dev_priv->mm.flushing_list)) {
+ obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
+ struct drm_i915_gem_object,
+ list);
+ obj = obj_priv->obj;
+
+ i915_gem_flush(dev,
+ obj->write_domain,
+ obj->write_domain);
+ i915_add_request(dev, obj->write_domain);
+
+ obj = NULL;
+ continue;
+ }
+
+ DRM_ERROR("inactive empty %d request empty %d "
+ "flushing empty %d\n",
+ list_empty(&dev_priv->mm.inactive_list),
+ list_empty(&dev_priv->mm.request_list),
+ list_empty(&dev_priv->mm.flushing_list));
+ /* If we didn't do any of the above, there's nothing to be done
+ * and we just can't fit it in.
+ */
+ return -ENOMEM;
+ }
+ return ret;
+}
+
+static int
+i915_gem_object_get_page_list(struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page_count, i;
+ struct address_space *mapping;
+ struct inode *inode;
+ struct page *page;
+ int ret;
+
+ if (obj_priv->page_list)
+ return 0;
+
+ /* Get the list of pages out of our struct file. They'll be pinned
+ * at this point until we release them.
+ */
+ page_count = obj->size / PAGE_SIZE;
+ BUG_ON(obj_priv->page_list != NULL);
+ obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *),
+ DRM_MEM_DRIVER);
+ if (obj_priv->page_list == NULL) {
+ DRM_ERROR("Faled to allocate page list\n");
+ return -ENOMEM;
+ }
+
+ inode = obj->filp->f_path.dentry->d_inode;
+ mapping = inode->i_mapping;
+ for (i = 0; i < page_count; i++) {
+ page = read_mapping_page(mapping, i, NULL);
+ if (IS_ERR(page)) {
+ ret = PTR_ERR(page);
+ DRM_ERROR("read_mapping_page failed: %d\n", ret);
+ i915_gem_object_free_page_list(obj);
+ return ret;
+ }
+ obj_priv->page_list[i] = page;
+ }
+ return 0;
+}
+
+/**
+ * Finds free space in the GTT aperture and binds the object there.
+ */
+static int
+i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ struct drm_mm_node *free_space;
+ int page_count, ret;
+
+ if (alignment == 0)
+ alignment = PAGE_SIZE;
+ if (alignment & (PAGE_SIZE - 1)) {
+ DRM_ERROR("Invalid object alignment requested %u\n", alignment);
+ return -EINVAL;
+ }
+
+ search_free:
+ free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
+ obj->size, alignment, 0);
+ if (free_space != NULL) {
+ obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
+ alignment);
+ if (obj_priv->gtt_space != NULL) {
+ obj_priv->gtt_space->private = obj;
+ obj_priv->gtt_offset = obj_priv->gtt_space->start;
+ }
+ }
+ if (obj_priv->gtt_space == NULL) {
+ /* If the gtt is empty and we're still having trouble
+ * fitting our object in, we're out of memory.
+ */
+#if WATCH_LRU
+ DRM_INFO("%s: GTT full, evicting something\n", __func__);
+#endif
+ if (list_empty(&dev_priv->mm.inactive_list) &&
+ list_empty(&dev_priv->mm.flushing_list) &&
+ list_empty(&dev_priv->mm.active_list)) {
+ DRM_ERROR("GTT full, but LRU list empty\n");
+ return -ENOMEM;
+ }
+
+ ret = i915_gem_evict_something(dev);
+ if (ret != 0) {
+ DRM_ERROR("Failed to evict a buffer %d\n", ret);
+ return ret;
+ }
+ goto search_free;
+ }
+
+#if WATCH_BUF
+ DRM_INFO("Binding object of size %d at 0x%08x\n",
+ obj->size, obj_priv->gtt_offset);
+#endif
+ ret = i915_gem_object_get_page_list(obj);
+ if (ret) {
+ drm_mm_put_block(obj_priv->gtt_space);
+ obj_priv->gtt_space = NULL;
+ return ret;
+ }
+
+ page_count = obj->size / PAGE_SIZE;
+ /* Create an AGP memory structure pointing at our pages, and bind it
+ * into the GTT.
+ */
+ obj_priv->agp_mem = drm_agp_bind_pages(dev,
+ obj_priv->page_list,
+ page_count,
+ obj_priv->gtt_offset,
+ obj_priv->agp_type);
+ if (obj_priv->agp_mem == NULL) {
+ i915_gem_object_free_page_list(obj);
+ drm_mm_put_block(obj_priv->gtt_space);
+ obj_priv->gtt_space = NULL;
+ return -ENOMEM;
+ }
+ atomic_inc(&dev->gtt_count);
+ atomic_add(obj->size, &dev->gtt_memory);
+
+ /* Assert that the object is not currently in any GPU domain. As it
+ * wasn't in the GTT, there shouldn't be any way it could have been in
+ * a GPU cache
+ */
+ BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+ BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+
+ return 0;
+}
+
+void
+i915_gem_clflush_object(struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ /* If we don't have a page list set up, then we're not pinned
+ * to GPU, and we can ignore the cache flush because it'll happen
+ * again at bind time.
+ */
+ if (obj_priv->page_list == NULL)
+ return;
+
+ drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
+}
+
+/*
+ * Set the next domain for the specified object. This
+ * may not actually perform the necessary flushing/invaliding though,
+ * as that may want to be batched with other set_domain operations
+ *
+ * This is (we hope) the only really tricky part of gem. The goal
+ * is fairly simple -- track which caches hold bits of the object
+ * and make sure they remain coherent. A few concrete examples may
+ * help to explain how it works. For shorthand, we use the notation
+ * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
+ * a pair of read and write domain masks.
+ *
+ * Case 1: the batch buffer
+ *
+ * 1. Allocated
+ * 2. Written by CPU
+ * 3. Mapped to GTT
+ * 4. Read by GPU
+ * 5. Unmapped from GTT
+ * 6. Freed
+ *
+ * Let's take these a step at a time
+ *
+ * 1. Allocated
+ * Pages allocated from the kernel may still have
+ * cache contents, so we set them to (CPU, CPU) always.
+ * 2. Written by CPU (using pwrite)
+ * The pwrite function calls set_domain (CPU, CPU) and
+ * this function does nothing (as nothing changes)
+ * 3. Mapped by GTT
+ * This function asserts that the object is not
+ * currently in any GPU-based read or write domains
+ * 4. Read by GPU
+ * i915_gem_execbuffer calls set_domain (COMMAND, 0).
+ * As write_domain is zero, this function adds in the
+ * current read domains (CPU+COMMAND, 0).
+ * flush_domains is set to CPU.
+ * invalidate_domains is set to COMMAND
+ * clflush is run to get data out of the CPU caches
+ * then i915_dev_set_domain calls i915_gem_flush to
+ * emit an MI_FLUSH and drm_agp_chipset_flush
+ * 5. Unmapped from GTT
+ * i915_gem_object_unbind calls set_domain (CPU, CPU)
+ * flush_domains and invalidate_domains end up both zero
+ * so no flushing/invalidating happens
+ * 6. Freed
+ * yay, done
+ *
+ * Case 2: The shared render buffer
+ *
+ * 1. Allocated
+ * 2. Mapped to GTT
+ * 3. Read/written by GPU
+ * 4. set_domain to (CPU,CPU)
+ * 5. Read/written by CPU
+ * 6. Read/written by GPU
+ *
+ * 1. Allocated
+ * Same as last example, (CPU, CPU)
+ * 2. Mapped to GTT
+ * Nothing changes (assertions find that it is not in the GPU)
+ * 3. Read/written by GPU
+ * execbuffer calls set_domain (RENDER, RENDER)
+ * flush_domains gets CPU
+ * invalidate_domains gets GPU
+ * clflush (obj)
+ * MI_FLUSH and drm_agp_chipset_flush
+ * 4. set_domain (CPU, CPU)
+ * flush_domains gets GPU
+ * invalidate_domains gets CPU
+ * wait_rendering (obj) to make sure all drawing is complete.
+ * This will include an MI_FLUSH to get the data from GPU
+ * to memory
+ * clflush (obj) to invalidate the CPU cache
+ * Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
+ * 5. Read/written by CPU
+ * cache lines are loaded and dirtied
+ * 6. Read written by GPU
+ * Same as last GPU access
+ *
+ * Case 3: The constant buffer
+ *
+ * 1. Allocated
+ * 2. Written by CPU
+ * 3. Read by GPU
+ * 4. Updated (written) by CPU again
+ * 5. Read by GPU
+ *
+ * 1. Allocated
+ * (CPU, CPU)
+ * 2. Written by CPU
+ * (CPU, CPU)
+ * 3. Read by GPU
+ * (CPU+RENDER, 0)
+ * flush_domains = CPU
+ * invalidate_domains = RENDER
+ * clflush (obj)
+ * MI_FLUSH
+ * drm_agp_chipset_flush
+ * 4. Updated (written) by CPU again
+ * (CPU, CPU)
+ * flush_domains = 0 (no previous write domain)
+ * invalidate_domains = 0 (no new read domains)
+ * 5. Read by GPU
+ * (CPU+RENDER, 0)
+ * flush_domains = CPU
+ * invalidate_domains = RENDER
+ * clflush (obj)
+ * MI_FLUSH
+ * drm_agp_chipset_flush
+ */
+static int
+i915_gem_object_set_domain(struct drm_gem_object *obj,
+ uint32_t read_domains,
+ uint32_t write_domain)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ uint32_t invalidate_domains = 0;
+ uint32_t flush_domains = 0;
+ int ret;
+
+#if WATCH_BUF
+ DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
+ __func__, obj,
+ obj->read_domains, read_domains,
+ obj->write_domain, write_domain);
+#endif
+ /*
+ * If the object isn't moving to a new write domain,
+ * let the object stay in multiple read domains
+ */
+ if (write_domain == 0)
+ read_domains |= obj->read_domains;
+ else
+ obj_priv->dirty = 1;
+
+ /*
+ * Flush the current write domain if
+ * the new read domains don't match. Invalidate
+ * any read domains which differ from the old
+ * write domain
+ */
+ if (obj->write_domain && obj->write_domain != read_domains) {
+ flush_domains |= obj->write_domain;
+ invalidate_domains |= read_domains & ~obj->write_domain;
+ }
+ /*
+ * Invalidate any read caches which may have
+ * stale data. That is, any new read domains.
+ */
+ invalidate_domains |= read_domains & ~obj->read_domains;
+ if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
+#if WATCH_BUF
+ DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
+ __func__, flush_domains, invalidate_domains);
+#endif
+ /*
+ * If we're invaliding the CPU cache and flushing a GPU cache,
+ * then pause for rendering so that the GPU caches will be
+ * flushed before the cpu cache is invalidated
+ */
+ if ((invalidate_domains & I915_GEM_DOMAIN_CPU) &&
+ (flush_domains & ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT))) {
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret)
+ return ret;
+ }
+ i915_gem_clflush_object(obj);
+ }
+
+ if ((write_domain | flush_domains) != 0)
+ obj->write_domain = write_domain;
+
+ /* If we're invalidating the CPU domain, clear the per-page CPU
+ * domain list as well.
+ */
+ if (obj_priv->page_cpu_valid != NULL &&
+ (write_domain != 0 ||
+ read_domains & I915_GEM_DOMAIN_CPU)) {
+ drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
+ DRM_MEM_DRIVER);
+ obj_priv->page_cpu_valid = NULL;
+ }
+ obj->read_domains = read_domains;
+
+ dev->invalidate_domains |= invalidate_domains;
+ dev->flush_domains |= flush_domains;
+#if WATCH_BUF
+ DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n",
+ __func__,
+ obj->read_domains, obj->write_domain,
+ dev->invalidate_domains, dev->flush_domains);
+#endif
+ return 0;
+}
+
+/**
+ * Set the read/write domain on a range of the object.
+ *
+ * Currently only implemented for CPU reads, otherwise drops to normal
+ * i915_gem_object_set_domain().
+ */
+static int
+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
+ uint64_t offset,
+ uint64_t size,
+ uint32_t read_domains,
+ uint32_t write_domain)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int ret, i;
+
+ if (obj->read_domains & I915_GEM_DOMAIN_CPU)
+ return 0;
+
+ if (read_domains != I915_GEM_DOMAIN_CPU ||
+ write_domain != 0)
+ return i915_gem_object_set_domain(obj,
+ read_domains, write_domain);
+
+ /* Wait on any GPU rendering to the object to be flushed. */
+ if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) {
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret)
+ return ret;
+ }
+
+ if (obj_priv->page_cpu_valid == NULL) {
+ obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
+ DRM_MEM_DRIVER);
+ }
+
+ /* Flush the cache on any pages that are still invalid from the CPU's
+ * perspective.
+ */
+ for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; i++) {
+ if (obj_priv->page_cpu_valid[i])
+ continue;
+
+ drm_clflush_pages(obj_priv->page_list + i, 1);
+
+ obj_priv->page_cpu_valid[i] = 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Once all of the objects have been set in the proper domain,
+ * perform the necessary flush and invalidate operations.
+ *
+ * Returns the write domains flushed, for use in flush tracking.
+ */
+static uint32_t
+i915_gem_dev_set_domain(struct drm_device *dev)
+{
+ uint32_t flush_domains = dev->flush_domains;
+
+ /*
+ * Now that all the buffers are synced to the proper domains,
+ * flush and invalidate the collected domains
+ */
+ if (dev->invalidate_domains | dev->flush_domains) {
+#if WATCH_EXEC
+ DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
+ __func__,
+ dev->invalidate_domains,
+ dev->flush_domains);
+#endif
+ i915_gem_flush(dev,
+ dev->invalidate_domains,
+ dev->flush_domains);
+ dev->invalidate_domains = 0;
+ dev->flush_domains = 0;
+ }
+
+ return flush_domains;
+}
+
+/**
+ * Pin an object to the GTT and evaluate the relocations landing in it.
+ */
+static int
+i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
+ struct drm_file *file_priv,
+ struct drm_i915_gem_exec_object *entry)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_relocation_entry reloc;
+ struct drm_i915_gem_relocation_entry __user *relocs;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int i, ret;
+ uint32_t last_reloc_offset = -1;
+ void __iomem *reloc_page = NULL;
+
+ /* Choose the GTT offset for our buffer and put it there. */
+ ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
+ if (ret)
+ return ret;
+
+ entry->offset = obj_priv->gtt_offset;
+
+ relocs = (struct drm_i915_gem_relocation_entry __user *)
+ (uintptr_t) entry->relocs_ptr;
+ /* Apply the relocations, using the GTT aperture to avoid cache
+ * flushing requirements.
+ */
+ for (i = 0; i < entry->relocation_count; i++) {
+ struct drm_gem_object *target_obj;
+ struct drm_i915_gem_object *target_obj_priv;
+ uint32_t reloc_val, reloc_offset;
+ uint32_t __iomem *reloc_entry;
+
+ ret = copy_from_user(&reloc, relocs + i, sizeof(reloc));
+ if (ret != 0) {
+ i915_gem_object_unpin(obj);
+ return ret;
+ }
+
+ target_obj = drm_gem_object_lookup(obj->dev, file_priv,
+ reloc.target_handle);
+ if (target_obj == NULL) {
+ i915_gem_object_unpin(obj);
+ return -EBADF;
+ }
+ target_obj_priv = target_obj->driver_private;
+
+ /* The target buffer should have appeared before us in the
+ * exec_object list, so it should have a GTT space bound by now.
+ */
+ if (target_obj_priv->gtt_space == NULL) {
+ DRM_ERROR("No GTT space found for object %d\n",
+ reloc.target_handle);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+
+ if (reloc.offset > obj->size - 4) {
+ DRM_ERROR("Relocation beyond object bounds: "
+ "obj %p target %d offset %d size %d.\n",
+ obj, reloc.target_handle,
+ (int) reloc.offset, (int) obj->size);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+ if (reloc.offset & 3) {
+ DRM_ERROR("Relocation not 4-byte aligned: "
+ "obj %p target %d offset %d.\n",
+ obj, reloc.target_handle,
+ (int) reloc.offset);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+
+ if (reloc.write_domain && target_obj->pending_write_domain &&
+ reloc.write_domain != target_obj->pending_write_domain) {
+ DRM_ERROR("Write domain conflict: "
+ "obj %p target %d offset %d "
+ "new %08x old %08x\n",
+ obj, reloc.target_handle,
+ (int) reloc.offset,
+ reloc.write_domain,
+ target_obj->pending_write_domain);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+
+#if WATCH_RELOC
+ DRM_INFO("%s: obj %p offset %08x target %d "
+ "read %08x write %08x gtt %08x "
+ "presumed %08x delta %08x\n",
+ __func__,
+ obj,
+ (int) reloc.offset,
+ (int) reloc.target_handle,
+ (int) reloc.read_domains,
+ (int) reloc.write_domain,
+ (int) target_obj_priv->gtt_offset,
+ (int) reloc.presumed_offset,
+ reloc.delta);
+#endif
+
+ target_obj->pending_read_domains |= reloc.read_domains;
+ target_obj->pending_write_domain |= reloc.write_domain;
+
+ /* If the relocation already has the right value in it, no
+ * more work needs to be done.
+ */
+ if (target_obj_priv->gtt_offset == reloc.presumed_offset) {
+ drm_gem_object_unreference(target_obj);
+ continue;
+ }
+
+ /* Now that we're going to actually write some data in,
+ * make sure that any rendering using this buffer's contents
+ * is completed.
+ */
+ i915_gem_object_wait_rendering(obj);
+
+ /* As we're writing through the gtt, flush
+ * any CPU writes before we write the relocations
+ */
+ if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+ obj->write_domain = 0;
+ }
+
+ /* Map the page containing the relocation we're going to
+ * perform.
+ */
+ reloc_offset = obj_priv->gtt_offset + reloc.offset;
+ if (reloc_page == NULL ||
+ (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
+ (reloc_offset & ~(PAGE_SIZE - 1))) {
+ if (reloc_page != NULL)
+ iounmap(reloc_page);
+
+ reloc_page = ioremap_wc(dev->agp->base +
+ (reloc_offset &
+ ~(PAGE_SIZE - 1)),
+ PAGE_SIZE);
+ last_reloc_offset = reloc_offset;
+ if (reloc_page == NULL) {
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -ENOMEM;
+ }
+ }
+
+ reloc_entry = (uint32_t __iomem *)(reloc_page +
+ (reloc_offset & (PAGE_SIZE - 1)));
+ reloc_val = target_obj_priv->gtt_offset + reloc.delta;
+
+#if WATCH_BUF
+ DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n",
+ obj, (unsigned int) reloc.offset,
+ readl(reloc_entry), reloc_val);
+#endif
+ writel(reloc_val, reloc_entry);
+
+ /* Write the updated presumed offset for this entry back out
+ * to the user.
+ */
+ reloc.presumed_offset = target_obj_priv->gtt_offset;
+ ret = copy_to_user(relocs + i, &reloc, sizeof(reloc));
+ if (ret != 0) {
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return ret;
+ }
+
+ drm_gem_object_unreference(target_obj);
+ }
+
+ if (reloc_page != NULL)
+ iounmap(reloc_page);
+
+#if WATCH_BUF
+ if (0)
+ i915_gem_dump_object(obj, 128, __func__, ~0);
+#endif
+ return 0;
+}
+
+/** Dispatch a batchbuffer to the ring
+ */
+static int
+i915_dispatch_gem_execbuffer(struct drm_device *dev,
+ struct drm_i915_gem_execbuffer *exec,
+ uint64_t exec_offset)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
+ (uintptr_t) exec->cliprects_ptr;
+ int nbox = exec->num_cliprects;
+ int i = 0, count;
+ uint32_t exec_start, exec_len;
+ RING_LOCALS;
+
+ exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+ exec_len = (uint32_t) exec->batch_len;
+
+ if ((exec_start | exec_len) & 0x7) {
+ DRM_ERROR("alignment\n");
+ return -EINVAL;
+ }
+
+ if (!exec_start)
+ return -EINVAL;
+
+ count = nbox ? nbox : 1;
+
+ for (i = 0; i < count; i++) {
+ if (i < nbox) {
+ int ret = i915_emit_box(dev, boxes, i,
+ exec->DR1, exec->DR4);
+ if (ret)
+ return ret;
+ }
+
+ if (IS_I830(dev) || IS_845G(dev)) {
+ BEGIN_LP_RING(4);
+ OUT_RING(MI_BATCH_BUFFER);
+ OUT_RING(exec_start | MI_BATCH_NON_SECURE);
+ OUT_RING(exec_start + exec_len - 4);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ } else {
+ BEGIN_LP_RING(2);
+ if (IS_I965G(dev)) {
+ OUT_RING(MI_BATCH_BUFFER_START |
+ (2 << 6) |
+ MI_BATCH_NON_SECURE_I965);
+ OUT_RING(exec_start);
+ } else {
+ OUT_RING(MI_BATCH_BUFFER_START |
+ (2 << 6));
+ OUT_RING(exec_start | MI_BATCH_NON_SECURE);
+ }
+ ADVANCE_LP_RING();
+ }
+ }
+
+ /* XXX breadcrumb */
+ return 0;
+}
+
+/* Throttle our rendering by waiting until the ring has completed our requests
+ * emitted over 20 msec ago.
+ *
+ * This should get us reasonable parallelism between CPU and GPU but also
+ * relatively low latency when blocking on a particular request to finish.
+ */
+static int
+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+ int ret = 0;
+ uint32_t seqno;
+
+ mutex_lock(&dev->struct_mutex);
+ seqno = i915_file_priv->mm.last_gem_throttle_seqno;
+ i915_file_priv->mm.last_gem_throttle_seqno =
+ i915_file_priv->mm.last_gem_seqno;
+ if (seqno)
+ ret = i915_wait_request(dev, seqno);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+ struct drm_i915_gem_execbuffer *args = data;
+ struct drm_i915_gem_exec_object *exec_list = NULL;
+ struct drm_gem_object **object_list = NULL;
+ struct drm_gem_object *batch_obj;
+ int ret, i, pinned = 0;
+ uint64_t exec_offset;
+ uint32_t seqno, flush_domains;
+
+#if WATCH_EXEC
+ DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+ (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+ if (args->buffer_count < 1) {
+ DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+ return -EINVAL;
+ }
+ /* Copy in the exec list from userland */
+ exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
+ DRM_MEM_DRIVER);
+ object_list = drm_calloc(sizeof(*object_list), args->buffer_count,
+ DRM_MEM_DRIVER);
+ if (exec_list == NULL || object_list == NULL) {
+ DRM_ERROR("Failed to allocate exec or object list "
+ "for %d buffers\n",
+ args->buffer_count);
+ ret = -ENOMEM;
+ goto pre_mutex_err;
+ }
+ ret = copy_from_user(exec_list,
+ (struct drm_i915_relocation_entry __user *)
+ (uintptr_t) args->buffers_ptr,
+ sizeof(*exec_list) * args->buffer_count);
+ if (ret != 0) {
+ DRM_ERROR("copy %d exec entries failed %d\n",
+ args->buffer_count, ret);
+ goto pre_mutex_err;
+ }
+
+ mutex_lock(&dev->struct_mutex);
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ if (dev_priv->mm.wedged) {
+ DRM_ERROR("Execbuf while wedged\n");
+ mutex_unlock(&dev->struct_mutex);
+ return -EIO;
+ }
+
+ if (dev_priv->mm.suspended) {
+ DRM_ERROR("Execbuf while VT-switched.\n");
+ mutex_unlock(&dev->struct_mutex);
+ return -EBUSY;
+ }
+
+ /* Zero the gloabl flush/invalidate flags. These
+ * will be modified as each object is bound to the
+ * gtt
+ */
+ dev->invalidate_domains = 0;
+ dev->flush_domains = 0;
+
+ /* Look up object handles and perform the relocations */
+ for (i = 0; i < args->buffer_count; i++) {
+ object_list[i] = drm_gem_object_lookup(dev, file_priv,
+ exec_list[i].handle);
+ if (object_list[i] == NULL) {
+ DRM_ERROR("Invalid object handle %d at index %d\n",
+ exec_list[i].handle, i);
+ ret = -EBADF;
+ goto err;
+ }
+
+ object_list[i]->pending_read_domains = 0;
+ object_list[i]->pending_write_domain = 0;
+ ret = i915_gem_object_pin_and_relocate(object_list[i],
+ file_priv,
+ &exec_list[i]);
+ if (ret) {
+ DRM_ERROR("object bind and relocate failed %d\n", ret);
+ goto err;
+ }
+ pinned = i + 1;
+ }
+
+ /* Set the pending read domains for the batch buffer to COMMAND */
+ batch_obj = object_list[args->buffer_count-1];
+ batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
+ batch_obj->pending_write_domain = 0;
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ for (i = 0; i < args->buffer_count; i++) {
+ struct drm_gem_object *obj = object_list[i];
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ if (obj_priv->gtt_space == NULL) {
+ /* We evicted the buffer in the process of validating
+ * our set of buffers in. We could try to recover by
+ * kicking them everything out and trying again from
+ * the start.
+ */
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* make sure all previous memory operations have passed */
+ ret = i915_gem_object_set_domain(obj,
+ obj->pending_read_domains,
+ obj->pending_write_domain);
+ if (ret)
+ goto err;
+ }
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ /* Flush/invalidate caches and chipset buffer */
+ flush_domains = i915_gem_dev_set_domain(dev);
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+#if WATCH_COHERENCY
+ for (i = 0; i < args->buffer_count; i++) {
+ i915_gem_object_check_coherency(object_list[i],
+ exec_list[i].handle);
+ }
+#endif
+
+ exec_offset = exec_list[args->buffer_count - 1].offset;
+
+#if WATCH_EXEC
+ i915_gem_dump_object(object_list[args->buffer_count - 1],
+ args->batch_len,
+ __func__,
+ ~0);
+#endif
+
+ (void)i915_add_request(dev, flush_domains);
+
+ /* Exec the batchbuffer */
+ ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
+ if (ret) {
+ DRM_ERROR("dispatch failed %d\n", ret);
+ goto err;
+ }
+
+ /*
+ * Ensure that the commands in the batch buffer are
+ * finished before the interrupt fires
+ */
+ flush_domains = i915_retire_commands(dev);
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ /*
+ * Get a seqno representing the execution of the current buffer,
+ * which we can wait on. We would like to mitigate these interrupts,
+ * likely by only creating seqnos occasionally (so that we have
+ * *some* interrupts representing completion of buffers that we can
+ * wait on when trying to clear up gtt space).
+ */
+ seqno = i915_add_request(dev, flush_domains);
+ BUG_ON(seqno == 0);
+ i915_file_priv->mm.last_gem_seqno = seqno;
+ for (i = 0; i < args->buffer_count; i++) {
+ struct drm_gem_object *obj = object_list[i];
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ i915_gem_object_move_to_active(obj);
+ obj_priv->last_rendering_seqno = seqno;
+#if WATCH_LRU
+ DRM_INFO("%s: move to exec list %p\n", __func__, obj);
+#endif
+ }
+#if WATCH_LRU
+ i915_dump_lru(dev, __func__);
+#endif
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ /* Copy the new buffer offsets back to the user's exec list. */
+ ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+ (uintptr_t) args->buffers_ptr,
+ exec_list,
+ sizeof(*exec_list) * args->buffer_count);
+ if (ret)
+ DRM_ERROR("failed to copy %d exec entries "
+ "back to user (%d)\n",
+ args->buffer_count, ret);
+err:
+ if (object_list != NULL) {
+ for (i = 0; i < pinned; i++)
+ i915_gem_object_unpin(object_list[i]);
+
+ for (i = 0; i < args->buffer_count; i++)
+ drm_gem_object_unreference(object_list[i]);
+ }
+ mutex_unlock(&dev->struct_mutex);
+
+pre_mutex_err:
+ drm_free(object_list, sizeof(*object_list) * args->buffer_count,
+ DRM_MEM_DRIVER);
+ drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
+ DRM_MEM_DRIVER);
+
+ return ret;
+}
+
+int
+i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int ret;
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+ if (obj_priv->gtt_space == NULL) {
+ ret = i915_gem_object_bind_to_gtt(obj, alignment);
+ if (ret != 0) {
+ DRM_ERROR("Failure to bind: %d", ret);
+ return ret;
+ }
+ }
+ obj_priv->pin_count++;
+
+ /* If the object is not active and not pending a flush,
+ * remove it from the inactive list
+ */
+ if (obj_priv->pin_count == 1) {
+ atomic_inc(&dev->pin_count);
+ atomic_add(obj->size, &dev->pin_memory);
+ if (!obj_priv->active &&
+ (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT)) == 0 &&
+ !list_empty(&obj_priv->list))
+ list_del_init(&obj_priv->list);
+ }
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+
+ return 0;
+}
+
+void
+i915_gem_object_unpin(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+ obj_priv->pin_count--;
+ BUG_ON(obj_priv->pin_count < 0);
+ BUG_ON(obj_priv->gtt_space == NULL);
+
+ /* If the object is no longer pinned, and is
+ * neither active nor being flushed, then stick it on
+ * the inactive list
+ */
+ if (obj_priv->pin_count == 0) {
+ if (!obj_priv->active &&
+ (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT)) == 0)
+ list_move_tail(&obj_priv->list,
+ &dev_priv->mm.inactive_list);
+ atomic_dec(&dev->pin_count);
+ atomic_sub(obj->size, &dev->pin_memory);
+ }
+ i915_verify_inactive(dev, __FILE__, __LINE__);
+}
+
+int
+i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_pin *args = data;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL) {
+ DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
+ args->handle);
+ mutex_unlock(&dev->struct_mutex);
+ return -EBADF;
+ }
+ obj_priv = obj->driver_private;
+
+ ret = i915_gem_object_pin(obj, args->alignment);
+ if (ret != 0) {
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+
+ /* XXX - flush the CPU caches for pinned objects
+ * as the X server doesn't manage domains yet
+ */
+ if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+ obj->write_domain = 0;
+ }
+ args->offset = obj_priv->gtt_offset;
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+int
+i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_pin *args = data;
+ struct drm_gem_object *obj;
+
+ mutex_lock(&dev->struct_mutex);
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL) {
+ DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
+ args->handle);
+ mutex_unlock(&dev->struct_mutex);
+ return -EBADF;
+ }
+
+ i915_gem_object_unpin(obj);
+
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return 0;
+}
+
+int
+i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_busy *args = data;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ mutex_lock(&dev->struct_mutex);
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL) {
+ DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
+ args->handle);
+ mutex_unlock(&dev->struct_mutex);
+ return -EBADF;
+ }
+
+ obj_priv = obj->driver_private;
+ args->busy = obj_priv->active;
+
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return 0;
+}
+
+int
+i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return i915_gem_ring_throttle(dev, file_priv);
+}
+
+int i915_gem_init_object(struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv;
+
+ obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
+ if (obj_priv == NULL)
+ return -ENOMEM;
+
+ /*
+ * We've just allocated pages from the kernel,
+ * so they've just been written by the CPU with
+ * zeros. They'll need to be clflushed before we
+ * use them with the GPU.
+ */
+ obj->write_domain = I915_GEM_DOMAIN_CPU;
+ obj->read_domains = I915_GEM_DOMAIN_CPU;
+
+ obj_priv->agp_type = AGP_USER_MEMORY;
+
+ obj->driver_private = obj_priv;
+ obj_priv->obj = obj;
+ INIT_LIST_HEAD(&obj_priv->list);
+ return 0;
+}
+
+void i915_gem_free_object(struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ while (obj_priv->pin_count > 0)
+ i915_gem_object_unpin(obj);
+
+ i915_gem_object_unbind(obj);
+
+ drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
+ drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
+}
+
+static int
+i915_gem_set_domain(struct drm_gem_object *obj,
+ struct drm_file *file_priv,
+ uint32_t read_domains,
+ uint32_t write_domain)
+{
+ struct drm_device *dev = obj->dev;
+ int ret;
+ uint32_t flush_domains;
+
+ BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ ret = i915_gem_object_set_domain(obj, read_domains, write_domain);
+ if (ret)
+ return ret;
+ flush_domains = i915_gem_dev_set_domain(obj->dev);
+
+ if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT))
+ (void) i915_add_request(dev, flush_domains);
+
+ return 0;
+}
+
+/** Unbinds all objects that are on the given buffer list. */
+static int
+i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
+{
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+
+ while (!list_empty(head)) {
+ obj_priv = list_first_entry(head,
+ struct drm_i915_gem_object,
+ list);
+ obj = obj_priv->obj;
+
+ if (obj_priv->pin_count != 0) {
+ DRM_ERROR("Pinned object in unbind list\n");
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+
+ ret = i915_gem_object_unbind(obj);
+ if (ret != 0) {
+ DRM_ERROR("Error unbinding object in LeaveVT: %d\n",
+ ret);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+ }
+
+
+ return 0;
+}
+
+static int
+i915_gem_idle(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t seqno, cur_seqno, last_seqno;
+ int stuck, ret;
+
+ mutex_lock(&dev->struct_mutex);
+
+ if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
+ mutex_unlock(&dev->struct_mutex);
+ return 0;
+ }
+
+ /* Hack! Don't let anybody do execbuf while we don't control the chip.
+ * We need to replace this with a semaphore, or something.
+ */
+ dev_priv->mm.suspended = 1;
+
+ /* Cancel the retire work handler, wait for it to finish if running
+ */
+ mutex_unlock(&dev->struct_mutex);
+ cancel_delayed_work_sync(&dev_priv->mm.retire_work);
+ mutex_lock(&dev->struct_mutex);
+
+ i915_kernel_lost_context(dev);
+
+ /* Flush the GPU along with all non-CPU write domains
+ */
+ i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
+ ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+ seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT));
+
+ if (seqno == 0) {
+ mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+
+ dev_priv->mm.waiting_gem_seqno = seqno;
+ last_seqno = 0;
+ stuck = 0;
+ for (;;) {
+ cur_seqno = i915_get_gem_seqno(dev);
+ if (i915_seqno_passed(cur_seqno, seqno))
+ break;
+ if (last_seqno == cur_seqno) {
+ if (stuck++ > 100) {
+ DRM_ERROR("hardware wedged\n");
+ dev_priv->mm.wedged = 1;
+ DRM_WAKEUP(&dev_priv->irq_queue);
+ break;
+ }
+ }
+ msleep(10);
+ last_seqno = cur_seqno;
+ }
+ dev_priv->mm.waiting_gem_seqno = 0;
+
+ i915_gem_retire_requests(dev);
+
+ /* Active and flushing should now be empty as we've
+ * waited for a sequence higher than any pending execbuffer
+ */
+ BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+
+ /* Request should now be empty as we've also waited
+ * for the last request in the list
+ */
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
+
+ /* Move all buffers out of the GTT. */
+ ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+
+ BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+ BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
+
+ i915_gem_cleanup_ringbuffer(dev);
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+static int
+i915_gem_init_hws(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+
+ /* If we need a physical address for the status page, it's already
+ * initialized at driver load time.
+ */
+ if (!I915_NEED_GFX_HWS(dev))
+ return 0;
+
+ obj = drm_gem_object_alloc(dev, 4096);
+ if (obj == NULL) {
+ DRM_ERROR("Failed to allocate status page\n");
+ return -ENOMEM;
+ }
+ obj_priv = obj->driver_private;
+ obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+ ret = i915_gem_object_pin(obj, 4096);
+ if (ret != 0) {
+ drm_gem_object_unreference(obj);
+ return ret;
+ }
+
+ dev_priv->status_gfx_addr = obj_priv->gtt_offset;
+
+ dev_priv->hw_status_page = kmap(obj_priv->page_list[0]);
+ if (dev_priv->hw_status_page == NULL) {
+ DRM_ERROR("Failed to map status page.\n");
+ memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+ drm_gem_object_unreference(obj);
+ return -EINVAL;
+ }
+ dev_priv->hws_obj = obj;
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+ I915_READ(HWS_PGA); /* posting read */
+ DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
+
+ return 0;
+}
+
+static int
+i915_gem_init_ringbuffer(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ int ret;
+ u32 head;
+
+ ret = i915_gem_init_hws(dev);
+ if (ret != 0)
+ return ret;
+
+ obj = drm_gem_object_alloc(dev, 128 * 1024);
+ if (obj == NULL) {
+ DRM_ERROR("Failed to allocate ringbuffer\n");
+ return -ENOMEM;
+ }
+ obj_priv = obj->driver_private;
+
+ ret = i915_gem_object_pin(obj, 4096);
+ if (ret != 0) {
+ drm_gem_object_unreference(obj);
+ return ret;
+ }
+
+ /* Set up the kernel mapping for the ring. */
+ dev_priv->ring.Size = obj->size;
+ dev_priv->ring.tail_mask = obj->size - 1;
+
+ dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset;
+ dev_priv->ring.map.size = obj->size;
+ dev_priv->ring.map.type = 0;
+ dev_priv->ring.map.flags = 0;
+ dev_priv->ring.map.mtrr = 0;
+
+ drm_core_ioremap_wc(&dev_priv->ring.map, dev);
+ if (dev_priv->ring.map.handle == NULL) {
+ DRM_ERROR("Failed to map ringbuffer.\n");
+ memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+ drm_gem_object_unreference(obj);
+ return -EINVAL;
+ }
+ dev_priv->ring.ring_obj = obj;
+ dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+ /* Stop the ring if it's running. */
+ I915_WRITE(PRB0_CTL, 0);
+ I915_WRITE(PRB0_TAIL, 0);
+ I915_WRITE(PRB0_HEAD, 0);
+
+ /* Initialize the ring. */
+ I915_WRITE(PRB0_START, obj_priv->gtt_offset);
+ head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+
+ /* G45 ring initialization fails to reset head to zero */
+ if (head != 0) {
+ DRM_ERROR("Ring head not reset to zero "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ I915_READ(PRB0_CTL),
+ I915_READ(PRB0_HEAD),
+ I915_READ(PRB0_TAIL),
+ I915_READ(PRB0_START));
+ I915_WRITE(PRB0_HEAD, 0);
+
+ DRM_ERROR("Ring head forced to zero "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ I915_READ(PRB0_CTL),
+ I915_READ(PRB0_HEAD),
+ I915_READ(PRB0_TAIL),
+ I915_READ(PRB0_START));
+ }
+
+ I915_WRITE(PRB0_CTL,
+ ((obj->size - 4096) & RING_NR_PAGES) |
+ RING_NO_REPORT |
+ RING_VALID);
+
+ head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+
+ /* If the head is still not zero, the ring is dead */
+ if (head != 0) {
+ DRM_ERROR("Ring initialization failed "
+ "ctl %08x head %08x tail %08x start %08x\n",
+ I915_READ(PRB0_CTL),
+ I915_READ(PRB0_HEAD),
+ I915_READ(PRB0_TAIL),
+ I915_READ(PRB0_START));
+ return -EIO;
+ }
+
+ /* Update our cache of the ring state */
+ i915_kernel_lost_context(dev);
+
+ return 0;
+}
+
+static void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ if (dev_priv->ring.ring_obj == NULL)
+ return;
+
+ drm_core_ioremapfree(&dev_priv->ring.map, dev);
+
+ i915_gem_object_unpin(dev_priv->ring.ring_obj);
+ drm_gem_object_unreference(dev_priv->ring.ring_obj);
+ dev_priv->ring.ring_obj = NULL;
+ memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+
+ if (dev_priv->hws_obj != NULL) {
+ struct drm_gem_object *obj = dev_priv->hws_obj;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ kunmap(obj_priv->page_list[0]);
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(obj);
+ dev_priv->hws_obj = NULL;
+ memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+ dev_priv->hw_status_page = NULL;
+
+ /* Write high address into HWS_PGA when disabling. */
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+ }
+}
+
+int
+i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ if (dev_priv->mm.wedged) {
+ DRM_ERROR("Reenabling wedged hardware, good luck\n");
+ dev_priv->mm.wedged = 0;
+ }
+
+ ret = i915_gem_init_ringbuffer(dev);
+ if (ret != 0)
+ return ret;
+
+ mutex_lock(&dev->struct_mutex);
+ BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+ BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
+ dev_priv->mm.suspended = 0;
+ mutex_unlock(&dev->struct_mutex);
+
+ drm_irq_install(dev);
+
+ return 0;
+}
+
+int
+i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret;
+
+ ret = i915_gem_idle(dev);
+ drm_irq_uninstall(dev);
+
+ return ret;
+}
+
+void
+i915_gem_lastclose(struct drm_device *dev)
+{
+ int ret;
+
+ ret = i915_gem_idle(dev);
+ if (ret)
+ DRM_ERROR("failed to idle hardware: %d\n", ret);
+}
+
+void
+i915_gem_load(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ INIT_LIST_HEAD(&dev_priv->mm.active_list);
+ INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
+ INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
+ INIT_LIST_HEAD(&dev_priv->mm.request_list);
+ INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
+ i915_gem_retire_work_handler);
+ INIT_WORK(&dev_priv->mm.vblank_work,
+ i915_gem_vblank_work_handler);
+ dev_priv->mm.next_gem_seqno = 1;
+
+ i915_gem_detect_bit_6_swizzle(dev);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
new file mode 100644
index 00000000000..131c088f8c8
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#if WATCH_INACTIVE
+void
+i915_verify_inactive(struct drm_device *dev, char *file, int line)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
+ obj = obj_priv->obj;
+ if (obj_priv->pin_count || obj_priv->active ||
+ (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+ I915_GEM_DOMAIN_GTT)))
+ DRM_ERROR("inactive %p (p %d a %d w %x) %s:%d\n",
+ obj,
+ obj_priv->pin_count, obj_priv->active,
+ obj->write_domain, file, line);
+ }
+}
+#endif /* WATCH_INACTIVE */
+
+
+#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE
+static void
+i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
+ uint32_t bias, uint32_t mark)
+{
+ uint32_t *mem = kmap_atomic(page, KM_USER0);
+ int i;
+ for (i = start; i < end; i += 4)
+ DRM_INFO("%08x: %08x%s\n",
+ (int) (bias + i), mem[i / 4],
+ (bias + i == mark) ? " ********" : "");
+ kunmap_atomic(mem, KM_USER0);
+ /* give syslog time to catch up */
+ msleep(1);
+}
+
+void
+i915_gem_dump_object(struct drm_gem_object *obj, int len,
+ const char *where, uint32_t mark)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page;
+
+ DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
+ for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
+ int page_len, chunk, chunk_len;
+
+ page_len = len - page * PAGE_SIZE;
+ if (page_len > PAGE_SIZE)
+ page_len = PAGE_SIZE;
+
+ for (chunk = 0; chunk < page_len; chunk += 128) {
+ chunk_len = page_len - chunk;
+ if (chunk_len > 128)
+ chunk_len = 128;
+ i915_gem_dump_page(obj_priv->page_list[page],
+ chunk, chunk + chunk_len,
+ obj_priv->gtt_offset +
+ page * PAGE_SIZE,
+ mark);
+ }
+ }
+}
+#endif
+
+#if WATCH_LRU
+void
+i915_dump_lru(struct drm_device *dev, const char *where)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+
+ DRM_INFO("active list %s {\n", where);
+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
+ list)
+ {
+ DRM_INFO(" %p: %08x\n", obj_priv,
+ obj_priv->last_rendering_seqno);
+ }
+ DRM_INFO("}\n");
+ DRM_INFO("flushing list %s {\n", where);
+ list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
+ list)
+ {
+ DRM_INFO(" %p: %08x\n", obj_priv,
+ obj_priv->last_rendering_seqno);
+ }
+ DRM_INFO("}\n");
+ DRM_INFO("inactive %s {\n", where);
+ list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
+ DRM_INFO(" %p: %08x\n", obj_priv,
+ obj_priv->last_rendering_seqno);
+ }
+ DRM_INFO("}\n");
+}
+#endif
+
+
+#if WATCH_COHERENCY
+void
+i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int page;
+ uint32_t *gtt_mapping;
+ uint32_t *backing_map = NULL;
+ int bad_count = 0;
+
+ DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
+ __func__, obj, obj_priv->gtt_offset, handle,
+ obj->size / 1024);
+
+ gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset,
+ obj->size);
+ if (gtt_mapping == NULL) {
+ DRM_ERROR("failed to map GTT space\n");
+ return;
+ }
+
+ for (page = 0; page < obj->size / PAGE_SIZE; page++) {
+ int i;
+
+ backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
+
+ if (backing_map == NULL) {
+ DRM_ERROR("failed to map backing page\n");
+ goto out;
+ }
+
+ for (i = 0; i < PAGE_SIZE / 4; i++) {
+ uint32_t cpuval = backing_map[i];
+ uint32_t gttval = readl(gtt_mapping +
+ page * 1024 + i);
+
+ if (cpuval != gttval) {
+ DRM_INFO("incoherent CPU vs GPU at 0x%08x: "
+ "0x%08x vs 0x%08x\n",
+ (int)(obj_priv->gtt_offset +
+ page * PAGE_SIZE + i * 4),
+ cpuval, gttval);
+ if (bad_count++ >= 8) {
+ DRM_INFO("...\n");
+ goto out;
+ }
+ }
+ }
+ kunmap_atomic(backing_map, KM_USER0);
+ backing_map = NULL;
+ }
+
+ out:
+ if (backing_map != NULL)
+ kunmap_atomic(backing_map, KM_USER0);
+ iounmap(gtt_mapping);
+
+ /* give syslog time to catch up */
+ msleep(1);
+
+ /* Directly flush the object, since we just loaded values with the CPU
+ * from the backing pages and we don't want to disturb the cache
+ * management that we're trying to observe.
+ */
+
+ i915_gem_clflush_object(obj);
+}
+#endif
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
new file mode 100644
index 00000000000..15d4160415b
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static int i915_gem_active_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Active:\n");
+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
+ list)
+ {
+ struct drm_gem_object *obj = obj_priv->obj;
+ if (obj->name) {
+ DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
+ obj, obj->name,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ } else {
+ DRM_PROC_PRINT(" %p: %08x %08x %d\n",
+ obj,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ }
+ }
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Flushing:\n");
+ list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
+ list)
+ {
+ struct drm_gem_object *obj = obj_priv->obj;
+ if (obj->name) {
+ DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
+ obj, obj->name,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ } else {
+ DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ }
+ }
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Inactive:\n");
+ list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
+ list)
+ {
+ struct drm_gem_object *obj = obj_priv->obj;
+ if (obj->name) {
+ DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
+ obj, obj->name,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ } else {
+ DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
+ obj->read_domains, obj->write_domain,
+ obj_priv->last_rendering_seqno);
+ }
+ }
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int i915_gem_request_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_request *gem_request;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Request:\n");
+ list_for_each_entry(gem_request, &dev_priv->mm.request_list,
+ list)
+ {
+ DRM_PROC_PRINT(" %d @ %d %08x\n",
+ gem_request->seqno,
+ (int) (jiffies - gem_request->emitted_jiffies),
+ gem_request->flush_domains);
+ }
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
+ DRM_PROC_PRINT("Waiter sequence: %d\n",
+ dev_priv->mm.waiting_gem_seqno);
+ DRM_PROC_PRINT("IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+
+static int i915_interrupt_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Interrupt enable: %08x\n",
+ I915_READ(IER));
+ DRM_PROC_PRINT("Interrupt identity: %08x\n",
+ I915_READ(IIR));
+ DRM_PROC_PRINT("Interrupt mask: %08x\n",
+ I915_READ(IMR));
+ DRM_PROC_PRINT("Pipe A stat: %08x\n",
+ I915_READ(PIPEASTAT));
+ DRM_PROC_PRINT("Pipe B stat: %08x\n",
+ I915_READ(PIPEBSTAT));
+ DRM_PROC_PRINT("Interrupts received: %d\n",
+ atomic_read(&dev_priv->irq_received));
+ DRM_PROC_PRINT("Current sequence: %d\n",
+ i915_get_gem_seqno(dev));
+ DRM_PROC_PRINT("Waiter sequence: %d\n",
+ dev_priv->mm.waiting_gem_seqno);
+ DRM_PROC_PRINT("IRQ sequence: %d\n",
+ dev_priv->mm.irq_gem_seqno);
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static struct drm_proc_list {
+ /** file name */
+ const char *name;
+ /** proc callback*/
+ int (*f) (char *, char **, off_t, int, int *, void *);
+} i915_gem_proc_list[] = {
+ {"i915_gem_active", i915_gem_active_info},
+ {"i915_gem_flushing", i915_gem_flushing_info},
+ {"i915_gem_inactive", i915_gem_inactive_info},
+ {"i915_gem_request", i915_gem_request_info},
+ {"i915_gem_seqno", i915_gem_seqno_info},
+ {"i915_gem_interrupt", i915_interrupt_info},
+};
+
+#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
+
+int i915_gem_proc_init(struct drm_minor *minor)
+{
+ struct proc_dir_entry *ent;
+ int i, j;
+
+ for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
+ ent = create_proc_entry(i915_gem_proc_list[i].name,
+ S_IFREG | S_IRUGO, minor->dev_root);
+ if (!ent) {
+ DRM_ERROR("Cannot create /proc/dri/.../%s\n",
+ i915_gem_proc_list[i].name);
+ for (j = 0; j < i; j++)
+ remove_proc_entry(i915_gem_proc_list[i].name,
+ minor->dev_root);
+ return -1;
+ }
+ ent->read_proc = i915_gem_proc_list[i].f;
+ ent->data = minor;
+ }
+ return 0;
+}
+
+void i915_gem_proc_cleanup(struct drm_minor *minor)
+{
+ int i;
+
+ if (!minor->dev_root)
+ return;
+
+ for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
+ remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
new file mode 100644
index 00000000000..e8b85ac4ca0
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/** @file i915_gem_tiling.c
+ *
+ * Support for managing tiling state of buffer objects.
+ *
+ * The idea behind tiling is to increase cache hit rates by rearranging
+ * pixel data so that a group of pixel accesses are in the same cacheline.
+ * Performance improvement from doing this on the back/depth buffer are on
+ * the order of 30%.
+ *
+ * Intel architectures make this somewhat more complicated, though, by
+ * adjustments made to addressing of data when the memory is in interleaved
+ * mode (matched pairs of DIMMS) to improve memory bandwidth.
+ * For interleaved memory, the CPU sends every sequential 64 bytes
+ * to an alternate memory channel so it can get the bandwidth from both.
+ *
+ * The GPU also rearranges its accesses for increased bandwidth to interleaved
+ * memory, and it matches what the CPU does for non-tiled. However, when tiled
+ * it does it a little differently, since one walks addresses not just in the
+ * X direction but also Y. So, along with alternating channels when bit
+ * 6 of the address flips, it also alternates when other bits flip -- Bits 9
+ * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
+ * are common to both the 915 and 965-class hardware.
+ *
+ * The CPU also sometimes XORs in higher bits as well, to improve
+ * bandwidth doing strided access like we do so frequently in graphics. This
+ * is called "Channel XOR Randomization" in the MCH documentation. The result
+ * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
+ * decode.
+ *
+ * All of this bit 6 XORing has an effect on our memory management,
+ * as we need to make sure that the 3d driver can correctly address object
+ * contents.
+ *
+ * If we don't have interleaved memory, all tiling is safe and no swizzling is
+ * required.
+ *
+ * When bit 17 is XORed in, we simply refuse to tile at all. Bit
+ * 17 is not just a page offset, so as we page an objet out and back in,
+ * individual pages in it will have different bit 17 addresses, resulting in
+ * each 64 bytes being swapped with its neighbor!
+ *
+ * Otherwise, if interleaved, we have to tell the 3d driver what the address
+ * swizzling it needs to do is, since it's writing with the CPU to the pages
+ * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
+ * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
+ * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
+ * to match what the GPU expects.
+ */
+
+/**
+ * Detects bit 6 swizzling of address lookup between IGD access and CPU
+ * access through main memory.
+ */
+void
+i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+ uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+
+ if (!IS_I9XX(dev)) {
+ /* As far as we know, the 865 doesn't have these bit 6
+ * swizzling issues.
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+ swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+ } else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) ||
+ IS_GM45(dev)) {
+ uint32_t dcc;
+
+ /* On 915-945 and GM965, channel interleave by the CPU is
+ * determined by DCC. The CPU will alternate based on bit 6
+ * in interleaved mode, and the GPU will then also alternate
+ * on bit 6, 9, and 10 for X, but the CPU may also optionally
+ * alternate based on bit 17 (XOR not disabled and XOR
+ * bit == 17).
+ */
+ dcc = I915_READ(DCC);
+ switch (dcc & DCC_ADDRESSING_MODE_MASK) {
+ case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
+ case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
+ swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+ swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+ break;
+ case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
+ if (IS_I915G(dev) || IS_I915GM(dev) ||
+ dcc & DCC_CHANNEL_XOR_DISABLE) {
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ } else if (IS_I965GM(dev) || IS_GM45(dev)) {
+ /* GM965 only does bit 11-based channel
+ * randomization
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
+ swizzle_y = I915_BIT_6_SWIZZLE_9_11;
+ } else {
+ /* Bit 17 or perhaps other swizzling */
+ swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+ swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+ }
+ break;
+ }
+ if (dcc == 0xffffffff) {
+ DRM_ERROR("Couldn't read from MCHBAR. "
+ "Disabling tiling.\n");
+ swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+ swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+ }
+ } else {
+ /* The 965, G33, and newer, have a very flexible memory
+ * configuration. It will enable dual-channel mode
+ * (interleaving) on as much memory as it can, and the GPU
+ * will additionally sometimes enable different bit 6
+ * swizzling for tiled objects from the CPU.
+ *
+ * Here's what I found on the G965:
+ * slot fill memory size swizzling
+ * 0A 0B 1A 1B 1-ch 2-ch
+ * 512 0 0 0 512 0 O
+ * 512 0 512 0 16 1008 X
+ * 512 0 0 512 16 1008 X
+ * 0 512 0 512 16 1008 X
+ * 1024 1024 1024 0 2048 1024 O
+ *
+ * We could probably detect this based on either the DRB
+ * matching, which was the case for the swizzling required in
+ * the table above, or from the 1-ch value being less than
+ * the minimum size of a rank.
+ */
+ if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
+ swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+ swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+ } else {
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ }
+ }
+
+ dev_priv->mm.bit_6_swizzle_x = swizzle_x;
+ dev_priv->mm.bit_6_swizzle_y = swizzle_y;
+}
+
+/**
+ * Sets the tiling mode of an object, returning the required swizzling of
+ * bit 6 of addresses in the object.
+ */
+int
+i915_gem_set_tiling(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_set_tiling *args = data;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EINVAL;
+ obj_priv = obj->driver_private;
+
+ mutex_lock(&dev->struct_mutex);
+
+ if (args->tiling_mode == I915_TILING_NONE) {
+ obj_priv->tiling_mode = I915_TILING_NONE;
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ } else {
+ if (args->tiling_mode == I915_TILING_X)
+ args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
+ else
+ args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+ /* If we can't handle the swizzling, make it untiled. */
+ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
+ args->tiling_mode = I915_TILING_NONE;
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ }
+ }
+ obj_priv->tiling_mode = args->tiling_mode;
+
+ mutex_unlock(&dev->struct_mutex);
+
+ drm_gem_object_unreference(obj);
+
+ return 0;
+}
+
+/**
+ * Returns the current tiling mode and required bit 6 swizzling for the object.
+ */
+int
+i915_gem_get_tiling(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_get_tiling *args = data;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -EINVAL;
+ obj_priv = obj->driver_private;
+
+ mutex_lock(&dev->struct_mutex);
+
+ args->tiling_mode = obj_priv->tiling_mode;
+ switch (obj_priv->tiling_mode) {
+ case I915_TILING_X:
+ args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
+ break;
+ case I915_TILING_Y:
+ args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+ break;
+ case I915_TILING_NONE:
+ args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ break;
+ default:
+ DRM_ERROR("unknown tiling mode\n");
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+
+ drm_gem_object_unreference(obj);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index df036118b8b..baae511c785 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -31,12 +31,92 @@
#include "i915_drm.h"
#include "i915_drv.h"
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-
#define MAX_NOPID ((u32)~0)
+/** These are the interrupts used by the driver */
+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
+ I915_ASLE_INTERRUPT | \
+ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
+void
+i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+ if ((dev_priv->irq_mask_reg & mask) != 0) {
+ dev_priv->irq_mask_reg &= ~mask;
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ (void) I915_READ(IMR);
+ }
+}
+
+static inline void
+i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+ if ((dev_priv->irq_mask_reg & mask) != mask) {
+ dev_priv->irq_mask_reg |= mask;
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ (void) I915_READ(IMR);
+ }
+}
+
+/**
+ * i915_get_pipe - return the the pipe associated with a given plane
+ * @dev: DRM device
+ * @plane: plane to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a pipe number, since they may not always be equal. This routine
+ * maps the given @plane back to a pipe number.
+ */
+static int
+i915_get_pipe(struct drm_device *dev, int plane)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ u32 dspcntr;
+
+ dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
+
+ return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
+ * i915_get_plane - return the the plane associated with a given pipe
+ * @dev: DRM device
+ * @pipe: pipe to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a plane number, since they may not always be equal. This routine
+ * maps the given @pipe back to a plane number.
+ */
+static int
+i915_get_plane(struct drm_device *dev, int pipe)
+{
+ if (i915_get_pipe(dev, 0) == pipe)
+ return 0;
+ return 1;
+}
+
+/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+ *
+ * Reading certain registers when the pipe is disabled can hang the chip.
+ * Use this routine to make sure the PLL is running and the pipe is active
+ * before reading such registers if unsure.
+ */
+static int
+i915_pipe_enabled(struct drm_device *dev, int pipe)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+ if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+ return 1;
+
+ return 0;
+}
+
/**
* Emit blits for scheduled buffer swaps.
*
@@ -48,8 +128,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
unsigned long irqflags;
struct list_head *list, *tmp, hits, *hit;
int nhits, nrects, slice[2], upper[2], lower[2], i;
- unsigned counter[2] = { atomic_read(&dev->vbl_received),
- atomic_read(&dev->vbl_received2) };
+ unsigned counter[2];
struct drm_drawable_info *drw;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
u32 cpp = dev_priv->cpp;
@@ -71,6 +150,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
src_pitch >>= 2;
}
+ counter[0] = drm_vblank_count(dev, 0);
+ counter[1] = drm_vblank_count(dev, 1);
+
DRM_DEBUG("\n");
INIT_LIST_HEAD(&hits);
@@ -83,12 +165,14 @@ static void i915_vblank_tasklet(struct drm_device *dev)
list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
drm_i915_vbl_swap_t *vbl_swap =
list_entry(list, drm_i915_vbl_swap_t, head);
+ int pipe = i915_get_pipe(dev, vbl_swap->plane);
- if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+ if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
continue;
list_del(list);
dev_priv->swaps_pending--;
+ drm_vblank_put(dev, pipe);
spin_unlock(&dev_priv->swaps_lock);
spin_lock(&dev->drw_lock);
@@ -181,7 +265,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
drm_i915_vbl_swap_t *swap_hit =
list_entry(hit, drm_i915_vbl_swap_t, head);
struct drm_clip_rect *rect;
- int num_rects, pipe;
+ int num_rects, plane;
unsigned short top, bottom;
drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -190,9 +274,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
continue;
rect = drw->rects;
- pipe = swap_hit->pipe;
- top = upper[pipe];
- bottom = lower[pipe];
+ plane = swap_hit->plane;
+ top = upper[plane];
+ bottom = lower[plane];
for (num_rects = drw->num_rects; num_rects--; rect++) {
int y1 = max(rect->y1, top);
@@ -229,61 +313,139 @@ static void i915_vblank_tasklet(struct drm_device *dev)
}
}
+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long high_frame;
+ unsigned long low_frame;
+ u32 high1, high2, low, count;
+ int pipe;
+
+ pipe = i915_get_pipe(dev, plane);
+ high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+ low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+
+ if (!i915_pipe_enabled(dev, pipe)) {
+ DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+ return 0;
+ }
+
+ /*
+ * High & low register fields aren't synchronized, so make sure
+ * we get a low value that's stable across two reads of the high
+ * register.
+ */
+ do {
+ high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+ PIPE_FRAME_LOW_SHIFT);
+ high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ } while (high1 != high2);
+
+ count = (high1 << 8) | low;
+
+ return count;
+}
+
+void
+i915_gem_vblank_work_handler(struct work_struct *work)
+{
+ drm_i915_private_t *dev_priv;
+ struct drm_device *dev;
+
+ dev_priv = container_of(work, drm_i915_private_t,
+ mm.vblank_work);
+ dev = dev_priv->dev;
+
+ mutex_lock(&dev->struct_mutex);
+ i915_vblank_tasklet(dev);
+ mutex_unlock(&dev->struct_mutex);
+}
+
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u16 temp;
+ u32 iir;
u32 pipea_stats, pipeb_stats;
+ int vblank = 0;
- pipea_stats = I915_READ(I915REG_PIPEASTAT);
- pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+ atomic_inc(&dev_priv->irq_received);
- temp = I915_READ16(I915REG_INT_IDENTITY_R);
+ if (dev->pdev->msi_enabled)
+ I915_WRITE(IMR, ~0);
+ iir = I915_READ(IIR);
- temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
+ if (iir == 0) {
+ if (dev->pdev->msi_enabled) {
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ (void) I915_READ(IMR);
+ }
+ return IRQ_NONE;
+ }
- DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+ /*
+ * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+ * we may get extra interrupts.
+ */
+ if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+ pipea_stats = I915_READ(PIPEASTAT);
+ if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
+ pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+ PIPE_VBLANK_INTERRUPT_STATUS)) {
+ vblank++;
+ drm_handle_vblank(dev, i915_get_plane(dev, 0));
+ }
- if (temp == 0)
- return IRQ_NONE;
+ I915_WRITE(PIPEASTAT, pipea_stats);
+ }
+ if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+ pipeb_stats = I915_READ(PIPEBSTAT);
+ /* Ack the event */
+ I915_WRITE(PIPEBSTAT, pipeb_stats);
+
+ /* The vblank interrupt gets enabled even if we didn't ask for
+ it, so make sure it's shut down again */
+ if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
+ pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+ PIPE_VBLANK_INTERRUPT_STATUS)) {
+ vblank++;
+ drm_handle_vblank(dev, i915_get_plane(dev, 1));
+ }
- I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
- (void) I915_READ16(I915REG_INT_IDENTITY_R);
- DRM_READMEMORYBARRIER();
+ if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
+ opregion_asle_intr(dev);
+ I915_WRITE(PIPEBSTAT, pipeb_stats);
+ }
+
+ I915_WRITE(IIR, iir);
+ if (dev->pdev->msi_enabled)
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ (void) I915_READ(IIR); /* Flush posted writes */
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
- if (temp & USER_INT_FLAG)
+ if (iir & I915_USER_INTERRUPT) {
+ dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
+ }
- if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
- int vblank_pipe = dev_priv->vblank_pipe;
-
- if ((vblank_pipe &
- (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
- == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
- if (temp & VSYNC_PIPEA_FLAG)
- atomic_inc(&dev->vbl_received);
- if (temp & VSYNC_PIPEB_FLAG)
- atomic_inc(&dev->vbl_received2);
- } else if (((temp & VSYNC_PIPEA_FLAG) &&
- (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
- ((temp & VSYNC_PIPEB_FLAG) &&
- (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
- atomic_inc(&dev->vbl_received);
-
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
-
- if (dev_priv->swaps_pending > 0)
+ if (iir & I915_ASLE_INTERRUPT)
+ opregion_asle_intr(dev);
+
+ if (vblank && dev_priv->swaps_pending > 0) {
+ if (dev_priv->ring.ring_obj == NULL)
drm_locked_tasklet(dev, i915_vblank_tasklet);
- I915_WRITE(I915REG_PIPEASTAT,
- pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
- I915_VBLANK_CLEAR);
- I915_WRITE(I915REG_PIPEBSTAT,
- pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
- I915_VBLANK_CLEAR);
+ else
+ schedule_work(&dev_priv->mm.vblank_work);
}
return IRQ_HANDLED;
@@ -298,23 +460,45 @@ static int i915_emit_irq(struct drm_device * dev)
DRM_DEBUG("\n");
- dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
+ dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+ dev_priv->counter = 1;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
BEGIN_LP_RING(6);
- OUT_RING(CMD_STORE_DWORD_IDX);
- OUT_RING(20);
+ OUT_RING(MI_STORE_DWORD_INDEX);
+ OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
OUT_RING(dev_priv->counter);
OUT_RING(0);
OUT_RING(0);
- OUT_RING(GFX_OP_USER_INTERRUPT);
+ OUT_RING(MI_USER_INTERRUPT);
ADVANCE_LP_RING();
return dev_priv->counter;
}
+void i915_user_irq_get(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+ spin_lock(&dev_priv->user_irq_lock);
+ if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
+ i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+ spin_unlock(&dev_priv->user_irq_lock);
+}
+
+void i915_user_irq_put(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+ spin_lock(&dev_priv->user_irq_lock);
+ BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
+ if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
+ i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+ spin_unlock(&dev_priv->user_irq_lock);
+}
+
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -323,55 +507,34 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv));
- if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+ if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
+ if (dev_priv->sarea_priv) {
+ dev_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
+ }
return 0;
+ }
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ i915_user_irq_get(dev);
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
READ_BREADCRUMB(dev_priv) >= irq_nr);
+ i915_user_irq_put(dev);
if (ret == -EBUSY) {
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
}
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
- return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
- atomic_t *counter)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- unsigned int cur_vblank;
- int ret = 0;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return -EINVAL;
- }
-
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(counter))
- - *sequence) <= (1<<23)));
-
- *sequence = cur_vblank;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
return ret;
}
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
/* Needs the lock as it touches the ring.
*/
int i915_irq_emit(struct drm_device *dev, void *data,
@@ -381,14 +544,15 @@ int i915_irq_emit(struct drm_device *dev, void *data,
drm_i915_irq_emit_t *emit = data;
int result;
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
-
+ mutex_lock(&dev->struct_mutex);
result = i915_emit_irq(dev);
+ mutex_unlock(&dev->struct_mutex);
if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
DRM_ERROR("copy_to_user\n");
@@ -414,18 +578,74 @@ int i915_irq_wait(struct drm_device *dev, void *data,
return i915_wait_irq(dev, irqwait->irq_seq);
}
-static void i915_enable_interrupt (struct drm_device *dev)
+int i915_enable_vblank(struct drm_device *dev, int plane)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u16 flag;
+ int pipe = i915_get_pipe(dev, plane);
+ u32 pipestat_reg = 0;
+ u32 pipestat;
+
+ switch (pipe) {
+ case 0:
+ pipestat_reg = PIPEASTAT;
+ i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+ break;
+ case 1:
+ pipestat_reg = PIPEBSTAT;
+ i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+ pipe);
+ break;
+ }
+
+ if (pipestat_reg) {
+ pipestat = I915_READ(pipestat_reg);
+ if (IS_I965G(dev))
+ pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ else
+ pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
+ /* Clear any stale interrupt status */
+ pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+ PIPE_VBLANK_INTERRUPT_STATUS);
+ I915_WRITE(pipestat_reg, pipestat);
+ }
+
+ return 0;
+}
- flag = 0;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
- flag |= VSYNC_PIPEA_FLAG;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
- flag |= VSYNC_PIPEB_FLAG;
+void i915_disable_vblank(struct drm_device *dev, int plane)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int pipe = i915_get_pipe(dev, plane);
+ u32 pipestat_reg = 0;
+ u32 pipestat;
+
+ switch (pipe) {
+ case 0:
+ pipestat_reg = PIPEASTAT;
+ i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+ break;
+ case 1:
+ pipestat_reg = PIPEBSTAT;
+ i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+ break;
+ default:
+ DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+ pipe);
+ break;
+ }
- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+ if (pipestat_reg) {
+ pipestat = I915_READ(pipestat_reg);
+ pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ /* Clear any stale interrupt status */
+ pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+ PIPE_VBLANK_INTERRUPT_STATUS);
+ I915_WRITE(pipestat_reg, pipestat);
+ }
}
/* Set the vblank monitor pipe
@@ -434,22 +654,12 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_pipe_t *pipe = data;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
- DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
- return -EINVAL;
- }
-
- dev_priv->vblank_pipe = pipe->pipe;
-
- i915_enable_interrupt (dev);
-
return 0;
}
@@ -458,19 +668,13 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_vblank_pipe_t *pipe = data;
- u16 flag;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- flag = I915_READ(I915REG_INT_ENABLE_R);
- pipe->pipe = 0;
- if (flag & VSYNC_PIPEA_FLAG)
- pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
- if (flag & VSYNC_PIPEB_FLAG)
- pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+ pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
return 0;
}
@@ -484,11 +688,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_vblank_swap_t *swap = data;
drm_i915_vbl_swap_t *vbl_swap;
- unsigned int pipe, seqtype, curseq;
+ unsigned int pipe, seqtype, curseq, plane;
unsigned long irqflags;
struct list_head *list;
+ int ret;
- if (!dev_priv) {
+ if (!dev_priv || !dev_priv->sarea_priv) {
DRM_ERROR("%s called with no initialization\n", __func__);
return -EINVAL;
}
@@ -504,7 +709,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
return -EINVAL;
}
- pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+ plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+ pipe = i915_get_pipe(dev, plane);
seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
@@ -523,7 +729,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+ /*
+ * We take the ref here and put it when the swap actually completes
+ * in the tasklet.
+ */
+ ret = drm_vblank_get(dev, pipe);
+ if (ret)
+ return ret;
+ curseq = drm_vblank_count(dev, pipe);
if (seqtype == _DRM_VBLANK_RELATIVE)
swap->sequence += curseq;
@@ -533,6 +746,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
swap->sequence = curseq + 1;
} else {
DRM_DEBUG("Missed target sequence\n");
+ drm_vblank_put(dev, pipe);
return -EINVAL;
}
}
@@ -543,7 +757,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
if (vbl_swap->drw_id == swap->drawable &&
- vbl_swap->pipe == pipe &&
+ vbl_swap->plane == plane &&
vbl_swap->sequence == swap->sequence) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
DRM_DEBUG("Already scheduled\n");
@@ -555,6 +769,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
if (dev_priv->swaps_pending >= 100) {
DRM_DEBUG("Too many swaps queued\n");
+ drm_vblank_put(dev, pipe);
return -EBUSY;
}
@@ -562,13 +777,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
if (!vbl_swap) {
DRM_ERROR("Failed to allocate memory to queue swap\n");
+ drm_vblank_put(dev, pipe);
return -ENOMEM;
}
DRM_DEBUG("\n");
vbl_swap->drw_id = swap->drawable;
- vbl_swap->pipe = pipe;
+ vbl_swap->plane = plane;
vbl_swap->sequence = swap->sequence;
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
@@ -587,37 +803,63 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- I915_WRITE16(I915REG_HWSTAM, 0xfffe);
- I915_WRITE16(I915REG_INT_MASK_R, 0x0);
- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ I915_WRITE(HWSTAM, 0xeffe);
+ I915_WRITE(IMR, 0xffffffff);
+ I915_WRITE(IER, 0x0);
}
-void i915_driver_irq_postinstall(struct drm_device * dev)
+int i915_driver_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int ret, num_pipes = 2;
spin_lock_init(&dev_priv->swaps_lock);
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
dev_priv->swaps_pending = 0;
- if (!dev_priv->vblank_pipe)
- dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
- i915_enable_interrupt(dev);
+ /* Set initial unmasked IRQs to just the selected vblank pipes. */
+ dev_priv->irq_mask_reg = ~0;
+
+ ret = drm_vblank_init(dev, num_pipes);
+ if (ret)
+ return ret;
+
+ dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+ dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
+ dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+
+ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+ dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
+
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+ (void) I915_READ(IER);
+
+ opregion_enable_asle(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+ return 0;
}
void i915_driver_irq_uninstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u16 temp;
+ u32 temp;
if (!dev_priv)
return;
- I915_WRITE16(I915REG_HWSTAM, 0xffff);
- I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ dev_priv->vblank_pipe = 0;
+
+ I915_WRITE(HWSTAM, 0xffffffff);
+ I915_WRITE(IMR, 0xffffffff);
+ I915_WRITE(IER, 0x0);
- temp = I915_READ16(I915REG_INT_IDENTITY_R);
- I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ temp = I915_READ(PIPEASTAT);
+ I915_WRITE(PIPEASTAT, temp);
+ temp = I915_READ(PIPEBSTAT);
+ I915_WRITE(PIPEBSTAT, temp);
+ temp = I915_READ(IIR);
+ I915_WRITE(IIR, temp);
}
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
new file mode 100644
index 00000000000..1787a0c7e3a
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2008 Intel Corporation <hong.liu@intel.com>
+ * Copyright 2008 Red Hat <mjg@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/acpi.h>
+
+#include "drmP.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define PCI_ASLE 0xe4
+#define PCI_LBPC 0xf4
+#define PCI_ASLS 0xfc
+
+#define OPREGION_SZ (8*1024)
+#define OPREGION_HEADER_OFFSET 0
+#define OPREGION_ACPI_OFFSET 0x100
+#define OPREGION_SWSCI_OFFSET 0x200
+#define OPREGION_ASLE_OFFSET 0x300
+#define OPREGION_VBT_OFFSET 0x1000
+
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+#define MBOX_ACPI (1<<0)
+#define MBOX_SWSCI (1<<1)
+#define MBOX_ASLE (1<<2)
+
+struct opregion_header {
+ u8 signature[16];
+ u32 size;
+ u32 opregion_ver;
+ u8 bios_ver[32];
+ u8 vbios_ver[16];
+ u8 driver_ver[16];
+ u32 mboxes;
+ u8 reserved[164];
+} __attribute__((packed));
+
+/* OpRegion mailbox #1: public ACPI methods */
+struct opregion_acpi {
+ u32 drdy; /* driver readiness */
+ u32 csts; /* notification status */
+ u32 cevt; /* current event */
+ u8 rsvd1[20];
+ u32 didl[8]; /* supported display devices ID list */
+ u32 cpdl[8]; /* currently presented display list */
+ u32 cadl[8]; /* currently active display list */
+ u32 nadl[8]; /* next active devices list */
+ u32 aslp; /* ASL sleep time-out */
+ u32 tidx; /* toggle table index */
+ u32 chpd; /* current hotplug enable indicator */
+ u32 clid; /* current lid state*/
+ u32 cdck; /* current docking state */
+ u32 sxsw; /* Sx state resume */
+ u32 evts; /* ASL supported events */
+ u32 cnot; /* current OS notification */
+ u32 nrdy; /* driver status */
+ u8 rsvd2[60];
+} __attribute__((packed));
+
+/* OpRegion mailbox #2: SWSCI */
+struct opregion_swsci {
+ u32 scic; /* SWSCI command|status|data */
+ u32 parm; /* command parameters */
+ u32 dslp; /* driver sleep time-out */
+ u8 rsvd[244];
+} __attribute__((packed));
+
+/* OpRegion mailbox #3: ASLE */
+struct opregion_asle {
+ u32 ardy; /* driver readiness */
+ u32 aslc; /* ASLE interrupt command */
+ u32 tche; /* technology enabled indicator */
+ u32 alsi; /* current ALS illuminance reading */
+ u32 bclp; /* backlight brightness to set */
+ u32 pfit; /* panel fitting state */
+ u32 cblv; /* current brightness level */
+ u16 bclm[20]; /* backlight level duty cycle mapping table */
+ u32 cpfm; /* current panel fitting mode */
+ u32 epfm; /* enabled panel fitting modes */
+ u8 plut[74]; /* panel LUT and identifier */
+ u32 pfmb; /* PWM freq and min brightness */
+ u8 rsvd[102];
+} __attribute__((packed));
+
+/* ASLE irq request bits */
+#define ASLE_SET_ALS_ILLUM (1 << 0)
+#define ASLE_SET_BACKLIGHT (1 << 1)
+#define ASLE_SET_PFIT (1 << 2)
+#define ASLE_SET_PWM_FREQ (1 << 3)
+#define ASLE_REQ_MSK 0xf
+
+/* response bits of ASLE irq request */
+#define ASLE_ALS_ILLUM_FAIL (2<<10)
+#define ASLE_BACKLIGHT_FAIL (2<<12)
+#define ASLE_PFIT_FAIL (2<<14)
+#define ASLE_PWM_FREQ_FAIL (2<<16)
+
+/* ASLE backlight brightness to set */
+#define ASLE_BCLP_VALID (1<<31)
+#define ASLE_BCLP_MSK (~(1<<31))
+
+/* ASLE panel fitting request */
+#define ASLE_PFIT_VALID (1<<31)
+#define ASLE_PFIT_CENTER (1<<0)
+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
+#define ASLE_PFIT_STRETCH_GFX (1<<2)
+
+/* PWM frequency and minimum brightness */
+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
+#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
+#define ASLE_PFMB_PWM_VALID (1<<31)
+
+#define ASLE_CBLV_VALID (1<<31)
+
+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
+ u32 blc_pwm_ctl, blc_pwm_ctl2;
+
+ if (!(bclp & ASLE_BCLP_VALID))
+ return ASLE_BACKLIGHT_FAIL;
+
+ bclp &= ASLE_BCLP_MSK;
+ if (bclp < 0 || bclp > 255)
+ return ASLE_BACKLIGHT_FAIL;
+
+ blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+ blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
+
+ if (blc_pwm_ctl2 & BLM_COMBINATION_MODE)
+ pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
+ else
+ I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | ((bclp * 0x101)-1));
+
+ asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+
+ return 0;
+}
+
+static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
+{
+ /* alsi is the current ALS reading in lux. 0 indicates below sensor
+ range, 0xffff indicates above sensor range. 1-0xfffe are valid */
+ return 0;
+}
+
+static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ if (pfmb & ASLE_PFMB_PWM_VALID) {
+ u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+ u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
+ blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
+ pwm = pwm >> 9;
+ /* FIXME - what do we do with the PWM? */
+ }
+ return 0;
+}
+
+static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
+{
+ /* Panel fitting is currently controlled by the X code, so this is a
+ noop until modesetting support works fully */
+ if (!(pfit & ASLE_PFIT_VALID))
+ return ASLE_PFIT_FAIL;
+ return 0;
+}
+
+void opregion_asle_intr(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
+ u32 asle_stat = 0;
+ u32 asle_req;
+
+ if (!asle)
+ return;
+
+ asle_req = asle->aslc & ASLE_REQ_MSK;
+
+ if (!asle_req) {
+ DRM_DEBUG("non asle set request??\n");
+ return;
+ }
+
+ if (asle_req & ASLE_SET_ALS_ILLUM)
+ asle_stat |= asle_set_als_illum(dev, asle->alsi);
+
+ if (asle_req & ASLE_SET_BACKLIGHT)
+ asle_stat |= asle_set_backlight(dev, asle->bclp);
+
+ if (asle_req & ASLE_SET_PFIT)
+ asle_stat |= asle_set_pfit(dev, asle->pfit);
+
+ if (asle_req & ASLE_SET_PWM_FREQ)
+ asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
+
+ asle->aslc = asle_stat;
+}
+
+#define ASLE_ALS_EN (1<<0)
+#define ASLE_BLC_EN (1<<1)
+#define ASLE_PFIT_EN (1<<2)
+#define ASLE_PFMB_EN (1<<3)
+
+void opregion_enable_asle(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
+
+ if (asle) {
+ u32 pipeb_stats = I915_READ(PIPEBSTAT);
+ if (IS_MOBILE(dev)) {
+ /* Many devices trigger events with a write to the
+ legacy backlight controller, so we need to ensure
+ that it's able to generate interrupts */
+ I915_WRITE(PIPEBSTAT, pipeb_stats |=
+ I915_LEGACY_BLC_EVENT_ENABLE);
+ i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+ } else
+ i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
+
+ asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
+ ASLE_PFMB_EN;
+ asle->ardy = 1;
+ }
+}
+
+#define ACPI_EV_DISPLAY_SWITCH (1<<0)
+#define ACPI_EV_LID (1<<1)
+#define ACPI_EV_DOCK (1<<2)
+
+static struct intel_opregion *system_opregion;
+
+int intel_opregion_video_event(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ /* The only video events relevant to opregion are 0x80. These indicate
+ either a docking event, lid switch or display switch request. In
+ Linux, these are handled by the dock, button and video drivers.
+ We might want to fix the video driver to be opregion-aware in
+ future, but right now we just indicate to the firmware that the
+ request has been handled */
+
+ struct opregion_acpi *acpi;
+
+ if (!system_opregion)
+ return NOTIFY_DONE;
+
+ acpi = system_opregion->acpi;
+ acpi->csts = 0;
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block intel_opregion_notifier = {
+ .notifier_call = intel_opregion_video_event,
+};
+
+int intel_opregion_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_opregion *opregion = &dev_priv->opregion;
+ void *base;
+ u32 asls, mboxes;
+ int err = 0;
+
+ pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
+ DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls);
+ if (asls == 0) {
+ DRM_DEBUG("ACPI OpRegion not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ base = ioremap(asls, OPREGION_SZ);
+ if (!base)
+ return -ENOMEM;
+
+ opregion->header = base;
+ if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
+ DRM_DEBUG("opregion signature mismatch\n");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ mboxes = opregion->header->mboxes;
+ if (mboxes & MBOX_ACPI) {
+ DRM_DEBUG("Public ACPI methods supported\n");
+ opregion->acpi = base + OPREGION_ACPI_OFFSET;
+ } else {
+ DRM_DEBUG("Public ACPI methods not supported\n");
+ err = -ENOTSUPP;
+ goto err_out;
+ }
+ opregion->enabled = 1;
+
+ if (mboxes & MBOX_SWSCI) {
+ DRM_DEBUG("SWSCI supported\n");
+ opregion->swsci = base + OPREGION_SWSCI_OFFSET;
+ }
+ if (mboxes & MBOX_ASLE) {
+ DRM_DEBUG("ASLE supported\n");
+ opregion->asle = base + OPREGION_ASLE_OFFSET;
+ }
+
+ /* Notify BIOS we are ready to handle ACPI video ext notifs.
+ * Right now, all the events are handled by the ACPI video module.
+ * We don't actually need to do anything with them. */
+ opregion->acpi->csts = 0;
+ opregion->acpi->drdy = 1;
+
+ system_opregion = opregion;
+ register_acpi_notifier(&intel_opregion_notifier);
+
+ return 0;
+
+err_out:
+ iounmap(opregion->header);
+ opregion->header = NULL;
+ return err;
+}
+
+void intel_opregion_free(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_opregion *opregion = &dev_priv->opregion;
+
+ if (!opregion->enabled)
+ return;
+
+ opregion->acpi->drdy = 0;
+
+ system_opregion = NULL;
+ unregister_acpi_notifier(&intel_opregion_notifier);
+
+ /* just clear all opregion memory pointers now */
+ iounmap(opregion->header);
+ opregion->header = NULL;
+ opregion->acpi = NULL;
+ opregion->swsci = NULL;
+ opregion->asle = NULL;
+
+ opregion->enabled = 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
new file mode 100644
index 00000000000..5c2d9f206d0
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -0,0 +1,1417 @@
+/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _I915_REG_H_
+#define _I915_REG_H_
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL 0x52
+#define INTEL_GMCH_ENABLED 0x4
+#define INTEL_GMCH_MEM_MASK 0x1
+#define INTEL_GMCH_MEM_64M 0x1
+#define INTEL_GMCH_MEM_128M 0
+
+#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+
+#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+
+/* PCI config space */
+
+#define HPLLCC 0xc0 /* 855 only */
+#define GC_CLOCK_CONTROL_MASK (3 << 0)
+#define GC_CLOCK_133_200 (0 << 0)
+#define GC_CLOCK_100_200 (1 << 0)
+#define GC_CLOCK_100_133 (2 << 0)
+#define GC_CLOCK_166_250 (3 << 0)
+#define GCFGC 0xf0 /* 915+ only */
+#define GC_LOW_FREQUENCY_ENABLE (1 << 7)
+#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
+#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4)
+#define GC_DISPLAY_CLOCK_MASK (7 << 4)
+#define LBB 0xf4
+
+/* VGA stuff */
+
+#define VGA_ST01_MDA 0x3ba
+#define VGA_ST01_CGA 0x3da
+
+#define VGA_MSR_WRITE 0x3c2
+#define VGA_MSR_READ 0x3cc
+#define VGA_MSR_MEM_EN (1<<1)
+#define VGA_MSR_CGA_MODE (1<<0)
+
+#define VGA_SR_INDEX 0x3c4
+#define VGA_SR_DATA 0x3c5
+
+#define VGA_AR_INDEX 0x3c0
+#define VGA_AR_VID_EN (1<<5)
+#define VGA_AR_DATA_WRITE 0x3c0
+#define VGA_AR_DATA_READ 0x3c1
+
+#define VGA_GR_INDEX 0x3ce
+#define VGA_GR_DATA 0x3cf
+/* GR05 */
+#define VGA_GR_MEM_READ_MODE_SHIFT 3
+#define VGA_GR_MEM_READ_MODE_PLANE 1
+/* GR06 */
+#define VGA_GR_MEM_MODE_MASK 0xc
+#define VGA_GR_MEM_MODE_SHIFT 2
+#define VGA_GR_MEM_A0000_AFFFF 0
+#define VGA_GR_MEM_A0000_BFFFF 1
+#define VGA_GR_MEM_B0000_B7FFF 2
+#define VGA_GR_MEM_B0000_BFFFF 3
+
+#define VGA_DACMASK 0x3c6
+#define VGA_DACRX 0x3c7
+#define VGA_DACWX 0x3c8
+#define VGA_DACDATA 0x3c9
+
+#define VGA_CR_INDEX_MDA 0x3b4
+#define VGA_CR_DATA_MDA 0x3b5
+#define VGA_CR_INDEX_CGA 0x3d4
+#define VGA_CR_DATA_CGA 0x3d5
+
+/*
+ * Memory interface instructions used by the kernel
+ */
+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+
+#define MI_NOOP MI_INSTR(0, 0)
+#define MI_USER_INTERRUPT MI_INSTR(0x02, 0)
+#define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0)
+#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
+#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define MI_FLUSH MI_INSTR(0x04, 0)
+#define MI_READ_FLUSH (1 << 0)
+#define MI_EXE_FLUSH (1 << 1)
+#define MI_NO_WRITE_FLUSH (1 << 2)
+#define MI_SCENE_COUNT (1 << 3) /* just increment scene count */
+#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
+#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
+#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
+#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
+#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
+#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
+#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
+#define MI_STORE_DWORD_INDEX_SHIFT 2
+#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1)
+#define MI_BATCH_BUFFER MI_INSTR(0x30, 1)
+#define MI_BATCH_NON_SECURE (1)
+#define MI_BATCH_NON_SECURE_I965 (1<<8)
+#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
+
+/*
+ * 3D instructions used by the kernel
+ */
+#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags))
+
+#define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24))
+#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR (0x1<<1)
+#define SC_ENABLE_MASK (0x1<<0)
+#define SC_ENABLE (0x1<<0)
+#define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16))
+#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK (0xffff<<16)
+#define SCI_XMIN_MASK (0xffff<<0)
+#define SCI_YMAX_MASK (0xffff<<16)
+#define SCI_XMAX_MASK (0xffff<<0)
+#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
+#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4)
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+#define BLT_DEPTH_8 (0<<24)
+#define BLT_DEPTH_16_565 (1<<24)
+#define BLT_DEPTH_16_1555 (2<<24)
+#define BLT_DEPTH_32 (3<<24)
+#define BLT_ROP_GXCOPY (0xcc<<16)
+#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */
+#define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP (1<<22)
+#define DISPLAY_PLANE_A (0<<20)
+#define DISPLAY_PLANE_B (1<<20)
+
+/*
+ * Instruction and interrupt control regs
+ */
+
+#define PRB0_TAIL 0x02030
+#define PRB0_HEAD 0x02034
+#define PRB0_START 0x02038
+#define PRB0_CTL 0x0203c
+#define TAIL_ADDR 0x001FFFF8
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+#define PRB1_TAIL 0x02040 /* 915+ only */
+#define PRB1_HEAD 0x02044 /* 915+ only */
+#define PRB1_START 0x02048 /* 915+ only */
+#define PRB1_CTL 0x0204c /* 915+ only */
+#define ACTHD_I965 0x02074
+#define HWS_PGA 0x02080
+#define HWS_ADDRESS_MASK 0xfffff000
+#define HWS_START_ADDRESS_SHIFT 4
+#define IPEIR 0x02088
+#define NOPID 0x02094
+#define HWSTAM 0x02098
+#define SCPD0 0x0209c /* 915+ only */
+#define IER 0x020a0
+#define IIR 0x020a4
+#define IMR 0x020a8
+#define ISR 0x020ac
+#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
+#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
+#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
+#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
+#define I915_HWB_OOM_INTERRUPT (1<<13)
+#define I915_SYNC_STATUS_INTERRUPT (1<<12)
+#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
+#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
+#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9)
+#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
+#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7)
+#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6)
+#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5)
+#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
+#define I915_DEBUG_INTERRUPT (1<<2)
+#define I915_USER_INTERRUPT (1<<1)
+#define I915_ASLE_INTERRUPT (1<<0)
+#define EIR 0x020b0
+#define EMR 0x020b4
+#define ESR 0x020b8
+#define INSTPM 0x020c0
+#define ACTHD 0x020c8
+#define FW_BLC 0x020d8
+#define FW_BLC_SELF 0x020e0 /* 915+ only */
+#define MI_ARB_STATE 0x020e4 /* 915+ only */
+#define CACHE_MODE_0 0x02120 /* 915+ only */
+#define CM0_MASK_SHIFT 16
+#define CM0_IZ_OPT_DISABLE (1<<6)
+#define CM0_ZR_OPT_DISABLE (1<<5)
+#define CM0_DEPTH_EVICT_DISABLE (1<<4)
+#define CM0_COLOR_EVICT_DISABLE (1<<3)
+#define CM0_DEPTH_WRITE_DISABLE (1<<1)
+#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
+#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
+
+/*
+ * Framebuffer compression (915+ only)
+ */
+
+#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
+#define FBC_LL_BASE 0x03204 /* 4k page aligned */
+#define FBC_CONTROL 0x03208
+#define FBC_CTL_EN (1<<31)
+#define FBC_CTL_PERIODIC (1<<30)
+#define FBC_CTL_INTERVAL_SHIFT (16)
+#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define FBC_CTL_STRIDE_SHIFT (5)
+#define FBC_CTL_FENCENO (1<<0)
+#define FBC_COMMAND 0x0320c
+#define FBC_CMD_COMPRESS (1<<0)
+#define FBC_STATUS 0x03210
+#define FBC_STAT_COMPRESSING (1<<31)
+#define FBC_STAT_COMPRESSED (1<<30)
+#define FBC_STAT_MODIFIED (1<<29)
+#define FBC_STAT_CURRENT_LINE (1<<0)
+#define FBC_CONTROL2 0x03214
+#define FBC_CTL_FENCE_DBL (0<<4)
+#define FBC_CTL_IDLE_IMM (0<<2)
+#define FBC_CTL_IDLE_FULL (1<<2)
+#define FBC_CTL_IDLE_LINE (2<<2)
+#define FBC_CTL_IDLE_DEBUG (3<<2)
+#define FBC_CTL_CPU_FENCE (1<<1)
+#define FBC_CTL_PLANEA (0<<0)
+#define FBC_CTL_PLANEB (1<<0)
+#define FBC_FENCE_OFF 0x0321b
+
+#define FBC_LL_SIZE (1536)
+
+/*
+ * GPIO regs
+ */
+#define GPIOA 0x5010
+#define GPIOB 0x5014
+#define GPIOC 0x5018
+#define GPIOD 0x501c
+#define GPIOE 0x5020
+#define GPIOF 0x5024
+#define GPIOG 0x5028
+#define GPIOH 0x502c
+# define GPIO_CLOCK_DIR_MASK (1 << 0)
+# define GPIO_CLOCK_DIR_IN (0 << 1)
+# define GPIO_CLOCK_DIR_OUT (1 << 1)
+# define GPIO_CLOCK_VAL_MASK (1 << 2)
+# define GPIO_CLOCK_VAL_OUT (1 << 3)
+# define GPIO_CLOCK_VAL_IN (1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
+# define GPIO_DATA_DIR_MASK (1 << 8)
+# define GPIO_DATA_DIR_IN (0 << 9)
+# define GPIO_DATA_DIR_OUT (1 << 9)
+# define GPIO_DATA_VAL_MASK (1 << 10)
+# define GPIO_DATA_VAL_OUT (1 << 11)
+# define GPIO_DATA_VAL_IN (1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
+
+/*
+ * Clock control & power management
+ */
+
+#define VGA0 0x6000
+#define VGA1 0x6004
+#define VGA_PD 0x6010
+#define VGA0_PD_P2_DIV_4 (1 << 7)
+#define VGA0_PD_P1_DIV_2 (1 << 5)
+#define VGA0_PD_P1_SHIFT 0
+#define VGA0_PD_P1_MASK (0x1f << 0)
+#define VGA1_PD_P2_DIV_4 (1 << 15)
+#define VGA1_PD_P1_DIV_2 (1 << 13)
+#define VGA1_PD_P1_SHIFT 8
+#define VGA1_PD_P1_MASK (0x1f << 8)
+#define DPLL_A 0x06014
+#define DPLL_B 0x06018
+#define DPLL_VCO_ENABLE (1 << 31)
+#define DPLL_DVO_HIGH_SPEED (1 << 30)
+#define DPLL_SYNCLOCK_ENABLE (1 << 29)
+#define DPLL_VGA_MODE_DIS (1 << 28)
+#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
+#define DPLLB_MODE_LVDS (2 << 26) /* i915 */
+#define DPLL_MODE_MASK (3 << 26)
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
+#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
+#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
+
+#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
+#define I915_CRC_ERROR_ENABLE (1UL<<29)
+#define I915_CRC_DONE_ENABLE (1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
+#define I915_DPST_EVENT_ENABLE (1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
+#define I915_DPST_EVENT_STATUS (1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
+
+#define SRX_INDEX 0x3c4
+#define SRX_DATA 0x3c5
+#define SR01 1
+#define SR01_SCREEN_OFF (1<<5)
+
+#define PPCR 0x61204
+#define PPCR_ON (1<<0)
+
+#define DVOB 0x61140
+#define DVOB_ON (1<<31)
+#define DVOC 0x61160
+#define DVOC_ON (1<<31)
+#define LVDS 0x61180
+#define LVDS_ON (1<<31)
+
+#define ADPA 0x61100
+#define ADPA_DPMS_MASK (~(3<<10))
+#define ADPA_DPMS_ON (0<<10)
+#define ADPA_DPMS_SUSPEND (1<<10)
+#define ADPA_DPMS_STANDBY (2<<10)
+#define ADPA_DPMS_OFF (3<<10)
+
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x001FFFF8
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define RING_START 0x08
+#define START_ADDR 0xFFFFF000
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+/* Scratch pad debug 0 reg:
+ */
+#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
+/*
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+#define DPLL_FPA01_P1_POST_DIV_SHIFT 16
+/* i830, required in DVO non-gang */
+#define PLL_P2_DIVIDE_BY_4 (1 << 23)
+#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
+#define PLL_REF_INPUT_DREFCLK (0 << 13)
+#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
+#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
+#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+#define PLL_REF_INPUT_MASK (3 << 13)
+#define PLL_LOAD_PULSE_PHASE_SHIFT 9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+#define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
+/*
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ */
+#define SDVO_MULTIPLIER_MASK 0x000000ff
+#define SDVO_MULTIPLIER_SHIFT_HIRES 4
+#define SDVO_MULTIPLIER_SHIFT_VGA 0
+#define DPLL_A_MD 0x0601c /* 965+ only */
+/*
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
+ */
+#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
+#define DPLL_MD_UDI_DIVIDER_SHIFT 24
+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
+#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
+/*
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
+#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
+/*
+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
+#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
+#define DPLL_B_MD 0x06020 /* 965+ only */
+#define FPA0 0x06040
+#define FPA1 0x06044
+#define FPB0 0x06048
+#define FPB1 0x0604c
+#define FP_N_DIV_MASK 0x003f0000
+#define FP_N_DIV_SHIFT 16
+#define FP_M1_DIV_MASK 0x00003f00
+#define FP_M1_DIV_SHIFT 8
+#define FP_M2_DIV_MASK 0x0000003f
+#define FP_M2_DIV_SHIFT 0
+#define DPLL_TEST 0x606c
+#define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
+#define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
+#define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
+#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
+#define DPLLB_TEST_N_BYPASS (1 << 19)
+#define DPLLB_TEST_M_BYPASS (1 << 18)
+#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
+#define DPLLA_TEST_N_BYPASS (1 << 3)
+#define DPLLA_TEST_M_BYPASS (1 << 2)
+#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
+#define D_STATE 0x6104
+#define CG_2D_DIS 0x6200
+#define CG_3D_DIS 0x6204
+
+/*
+ * Palette regs
+ */
+
+#define PALETTE_A 0x0a000
+#define PALETTE_B 0x0a800
+
+/* MCH MMIO space */
+
+/*
+ * MCHBAR mirror.
+ *
+ * This mirrors the MCHBAR MMIO space whose location is determined by
+ * device 0 function 0's pci config register 0x44 or 0x48 and matches it in
+ * every way. It is not accessible from the CP register read instructions.
+ *
+ */
+#define MCHBAR_MIRROR_BASE 0x10000
+
+/** 915-945 and GM965 MCH register controlling DRAM channel access */
+#define DCC 0x10200
+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0)
+#define DCC_ADDRESSING_MODE_MASK (3 << 0)
+#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
+
+/** 965 MCH register controlling DRAM channel configuration */
+#define C0DRB3 0x10206
+#define C1DRB3 0x10606
+
+/*
+ * Overlay regs
+ */
+
+#define OVADD 0x30000
+#define DOVSTA 0x30008
+#define OC_BUF (0x3<<20)
+#define OGAMC5 0x30010
+#define OGAMC4 0x30014
+#define OGAMC3 0x30018
+#define OGAMC2 0x3001c
+#define OGAMC1 0x30020
+#define OGAMC0 0x30024
+
+/*
+ * Display engine regs
+ */
+
+/* Pipe A timing regs */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+
+/* Pipe B timing regs */
+#define HTOTAL_B 0x61000
+#define HBLANK_B 0x61004
+#define HSYNC_B 0x61008
+#define VTOTAL_B 0x6100c
+#define VBLANK_B 0x61010
+#define VSYNC_B 0x61014
+#define PIPEBSRC 0x6101c
+#define BCLRPAT_B 0x61020
+
+/* VGA port control */
+#define ADPA 0x61100
+#define ADPA_DAC_ENABLE (1<<31)
+#define ADPA_DAC_DISABLE 0
+#define ADPA_PIPE_SELECT_MASK (1<<30)
+#define ADPA_PIPE_A_SELECT 0
+#define ADPA_PIPE_B_SELECT (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY 0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW 0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW 0
+#define ADPA_DPMS_MASK (~(3<<10))
+#define ADPA_DPMS_ON (0<<10)
+#define ADPA_DPMS_SUSPEND (1<<10)
+#define ADPA_DPMS_STANDBY (2<<10)
+#define ADPA_DPMS_OFF (3<<10)
+
+/* Hotplug control (945+ only) */
+#define PORT_HOTPLUG_EN 0x61110
+#define SDVOB_HOTPLUG_INT_EN (1 << 26)
+#define SDVOC_HOTPLUG_INT_EN (1 << 25)
+#define TV_HOTPLUG_INT_EN (1 << 18)
+#define CRT_HOTPLUG_INT_EN (1 << 9)
+#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
+
+#define PORT_HOTPLUG_STAT 0x61114
+#define CRT_HOTPLUG_INT_STATUS (1 << 11)
+#define TV_HOTPLUG_INT_STATUS (1 << 10)
+#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
+#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
+#define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
+#define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
+#define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
+#define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
+
+/* SDVO port control */
+#define SDVOB 0x61140
+#define SDVOC 0x61160
+#define SDVO_ENABLE (1 << 31)
+#define SDVO_PIPE_B_SELECT (1 << 30)
+#define SDVO_STALL_SELECT (1 << 29)
+#define SDVO_INTERRUPT_ENABLE (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT 23
+#define SDVO_PHASE_SELECT_MASK (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
+#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVOB_PCIE_CONCURRENCY (1 << 3)
+#define SDVO_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
+#define SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
+
+/* DVO port control */
+#define DVOA 0x61120
+#define DVOB 0x61140
+#define DVOC 0x61160
+#define DVO_ENABLE (1 << 31)
+#define DVO_PIPE_B_SELECT (1 << 30)
+#define DVO_PIPE_STALL_UNUSED (0 << 28)
+#define DVO_PIPE_STALL (1 << 28)
+#define DVO_PIPE_STALL_TV (2 << 28)
+#define DVO_PIPE_STALL_MASK (3 << 28)
+#define DVO_USE_VGA_SYNC (1 << 15)
+#define DVO_DATA_ORDER_I740 (0 << 14)
+#define DVO_DATA_ORDER_FP (1 << 14)
+#define DVO_VSYNC_DISABLE (1 << 11)
+#define DVO_HSYNC_DISABLE (1 << 10)
+#define DVO_VSYNC_TRISTATE (1 << 9)
+#define DVO_HSYNC_TRISTATE (1 << 8)
+#define DVO_BORDER_ENABLE (1 << 7)
+#define DVO_DATA_ORDER_GBRG (1 << 6)
+#define DVO_DATA_ORDER_RGGB (0 << 6)
+#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
+#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
+#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
+#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
+#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
+#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
+#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
+#define DVO_PRESERVE_MASK (0x7<<24)
+#define DVOA_SRCDIM 0x61124
+#define DVOB_SRCDIM 0x61144
+#define DVOC_SRCDIM 0x61164
+#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
+#define DVO_SRCDIM_VERTICAL_SHIFT 0
+
+/* LVDS port control */
+#define LVDS 0x61180
+/*
+ * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+#define LVDS_PORT_EN (1 << 31)
+/* Selects pipe B for LVDS data. Must be set on pre-965. */
+#define LVDS_PIPEB_SELECT (1 << 30)
+/*
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
+#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
+#define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
+/*
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+#define LVDS_A3_POWER_MASK (3 << 6)
+#define LVDS_A3_POWER_DOWN (0 << 6)
+#define LVDS_A3_POWER_UP (3 << 6)
+/*
+ * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+#define LVDS_CLKB_POWER_MASK (3 << 4)
+#define LVDS_CLKB_POWER_DOWN (0 << 4)
+#define LVDS_CLKB_POWER_UP (3 << 4)
+/*
+ * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode. The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+#define LVDS_B0B3_POWER_MASK (3 << 2)
+#define LVDS_B0B3_POWER_DOWN (0 << 2)
+#define LVDS_B0B3_POWER_UP (3 << 2)
+
+/* Panel power sequencing */
+#define PP_STATUS 0x61200
+#define PP_ON (1 << 31)
+/*
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+#define PP_READY (1 << 30)
+#define PP_SEQUENCE_NONE (0 << 28)
+#define PP_SEQUENCE_ON (1 << 28)
+#define PP_SEQUENCE_OFF (2 << 28)
+#define PP_SEQUENCE_MASK 0x30000000
+#define PP_CONTROL 0x61204
+#define POWER_TARGET_ON (1 << 0)
+#define PP_ON_DELAYS 0x61208
+#define PP_OFF_DELAYS 0x6120c
+#define PP_DIVISOR 0x61210
+
+/* Panel fitting */
+#define PFIT_CONTROL 0x61230
+#define PFIT_ENABLE (1 << 31)
+#define PFIT_PIPE_MASK (3 << 29)
+#define PFIT_PIPE_SHIFT 29
+#define VERT_INTERP_DISABLE (0 << 10)
+#define VERT_INTERP_BILINEAR (1 << 10)
+#define VERT_INTERP_MASK (3 << 10)
+#define VERT_AUTO_SCALE (1 << 9)
+#define HORIZ_INTERP_DISABLE (0 << 6)
+#define HORIZ_INTERP_BILINEAR (1 << 6)
+#define HORIZ_INTERP_MASK (3 << 6)
+#define HORIZ_AUTO_SCALE (1 << 5)
+#define PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define PFIT_PGM_RATIOS 0x61234
+#define PFIT_VERT_SCALE_MASK 0xfff00000
+#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+#define PFIT_AUTO_RATIOS 0x61238
+
+/* Backlight control */
+#define BLC_PWM_CTL 0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
+#define BLC_PWM_CTL2 0x61250 /* 965+ only */
+#define BLM_COMBINATION_MODE (1 << 30)
+/*
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
+#define BLM_LEGACY_MODE (1 << 16)
+/*
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+
+/* TV port control */
+#define TV_CTL 0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE (1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT (1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE (0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO (1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT (2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28)
+# define TV_TRILEVEL_SYNC (1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC (1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X (0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X (1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE (2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X (3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE (1 << 17)
+/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */
+# define TV_PAL_BURST (1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK (7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX (1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX (1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE ((3 << 8) | (3 << 6))
+# define TV_FUSE_STATE_MASK (3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED (0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED (2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL (0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1 (1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2 (2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3 (3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4 (4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5 (5 << 0)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
+# define TV_TEST_MODE_MASK (7 << 0)
+
+#define TV_DAC 0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG (1 << 31)
+# define TVDAC_SENSE_MASK (7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE (1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE (1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE (1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN (1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL (1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL (1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL (1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE (1 << 7)
+/** Sets the slew rate. Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST (1 << 6)
+# define DAC_A_1_3_V (0 << 4)
+# define DAC_A_1_1_V (1 << 4)
+# define DAC_A_0_7_V (2 << 4)
+# define DAC_A_OFF (3 << 4)
+# define DAC_B_1_3_V (0 << 2)
+# define DAC_B_1_1_V (1 << 2)
+# define DAC_B_0_7_V (2 << 2)
+# define DAC_B_OFF (3 << 2)
+# define DAC_C_1_3_V (0 << 0)
+# define DAC_C_1_1_V (1 << 0)
+# define DAC_C_0_7_V (2 << 0)
+# define DAC_C_OFF (3 << 0)
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y 0x68010
+# define TV_RY_MASK 0x07ff0000
+# define TV_RY_SHIFT 16
+# define TV_GY_MASK 0x00000fff
+# define TV_GY_SHIFT 0
+
+#define TV_CSC_Y2 0x68014
+# define TV_BY_MASK 0x07ff0000
+# define TV_BY_SHIFT 16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK 0x000003ff
+# define TV_AY_SHIFT 0
+
+#define TV_CSC_U 0x68018
+# define TV_RU_MASK 0x07ff0000
+# define TV_RU_SHIFT 16
+# define TV_GU_MASK 0x000007ff
+# define TV_GU_SHIFT 0
+
+#define TV_CSC_U2 0x6801c
+# define TV_BU_MASK 0x07ff0000
+# define TV_BU_SHIFT 16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK 0x000003ff
+# define TV_AU_SHIFT 0
+
+#define TV_CSC_V 0x68020
+# define TV_RV_MASK 0x0fff0000
+# define TV_RV_SHIFT 16
+# define TV_GV_MASK 0x000007ff
+# define TV_GV_SHIFT 0
+
+#define TV_CSC_V2 0x68024
+# define TV_BV_MASK 0x07ff0000
+# define TV_BV_SHIFT 16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK 0x000007ff
+# define TV_AV_SHIFT 0
+
+#define TV_CLR_KNOBS 0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK 0xff000000
+# define TV_BRIGHTNESS_SHIFT 24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK 0x00ff0000
+# define TV_CONTRAST_SHIFT 16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK 0x0000ff00
+# define TV_SATURATION_SHIFT 8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK 0x000000ff
+# define TV_HUE_SHIFT 0
+
+#define TV_CLR_LEVEL 0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK 0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT 16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK 0x000001ff
+# define TV_BLANK_LEVEL_SHIFT 0
+
+#define TV_H_CTL_1 0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK 0x1fff0000
+# define TV_HSYNC_END_SHIFT 16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK 0x00001fff
+# define TV_HTOTAL_SHIFT 0
+
+#define TV_H_CTL_2 0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA (1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT 16
+# define TV_HBURST_START_MASK 0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT 0
+# define TV_HBURST_LEN_MASK 0x0001fff
+
+#define TV_H_CTL_3 0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT 16
+# define TV_HBLANK_END_MASK 0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT 0
+# define TV_HBLANK_START_MASK 0x0001fff
+
+#define TV_V_CTL_1 0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT 16
+# define TV_NBR_END_MASK 0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT 8
+# define TV_VI_END_F1_MASK 0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT 0
+# define TV_VI_END_F2_MASK 0x0000003f
+
+#define TV_V_CTL_2 0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK 0x07ff0000
+# define TV_VSYNC_LEN_SHIFT 16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK 0x00007f00
+# define TV_VSYNC_START_F1_SHIFT 8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK 0x0000007f
+# define TV_VSYNC_START_F2_SHIFT 0
+
+#define TV_V_CTL_3 0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA (1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK 0x007f0000
+# define TV_VEQ_LEN_SHIFT 16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK 0x0007f00
+# define TV_VEQ_START_F1_SHIFT 8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK 0x000007f
+# define TV_VEQ_START_F2_SHIFT 0
+
+#define TV_V_CTL_4 0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK 0x003f0000
+# define TV_VBURST_START_F1_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK 0x000000ff
+# define TV_VBURST_END_F1_SHIFT 0
+
+#define TV_V_CTL_5 0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK 0x003f0000
+# define TV_VBURST_START_F2_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK 0x000000ff
+# define TV_VBURST_END_F2_SHIFT 0
+
+#define TV_V_CTL_6 0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK 0x003f0000
+# define TV_VBURST_START_F3_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK 0x000000ff
+# define TV_VBURST_END_F3_SHIFT 0
+
+#define TV_V_CTL_7 0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK 0x003f0000
+# define TV_VBURST_START_F4_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK 0x000000ff
+# define TV_VBURST_END_F4_SHIFT 0
+
+#define TV_SC_CTL_1 0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN (1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN (1 << 30)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN (1 << 29)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2 (0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4 (1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8 (2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER (3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK 0x00ff0000
+# define TV_BURST_LEVEL_SHIFT 16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK 0x00000fff
+# define TV_SCDDA1_INC_SHIFT 0
+
+#define TV_SC_CTL_2 0x68064
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK 0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT 16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK 0x00007fff
+# define TV_SCDDA2_INC_SHIFT 0
+
+#define TV_SC_CTL_3 0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK 0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT 16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK 0x00007fff
+# define TV_SCDDA3_INC_SHIFT 0
+
+#define TV_WIN_POS 0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK 0x1fff0000
+# define TV_XPOS_SHIFT 16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK 0x00000fff
+# define TV_YPOS_SHIFT 0
+
+#define TV_WIN_SIZE 0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK 0x1fff0000
+# define TV_XSIZE_SHIFT 16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK 0x00000fff
+# define TV_YSIZE_SHIFT 0
+
+#define TV_FILTER_CTL_1 0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE (1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS (1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT (1 << 28)
+# define TV_VADAPT_MODE_MASK (3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST (0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE (1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST (3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate. TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK 0x00003fff
+# define TV_HSCALE_FRAC_SHIFT 0
+
+#define TV_FILTER_CTL_2 0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK 0x00038000
+# define TV_VSCALE_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK 0x00007fff
+# define TV_VSCALE_FRAC_SHIFT 0
+
+#define TV_FILTER_CTL_3 0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK 0x00038000
+# define TV_VSCALE_IP_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK 0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT 0
+
+#define TV_CC_CONTROL 0x68090
+# define TV_CC_ENABLE (1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK (1 << 27)
+# define TV_CC_FID_SHIFT 27
+/** Sets the horizontal position of the CC data. Usually 135. */
+# define TV_CC_HOFF_MASK 0x03ff0000
+# define TV_CC_HOFF_SHIFT 16
+/** Sets the vertical position of the CC data. Usually 21 */
+# define TV_CC_LINE_MASK 0x0000003f
+# define TV_CC_LINE_SHIFT 0
+
+#define TV_CC_DATA 0x68094
+# define TV_CC_RDY (1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK 0x007f0000
+# define TV_CC_DATA_2_SHIFT 16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK 0x0000007f
+# define TV_CC_DATA_1_SHIFT 0
+
+#define TV_H_LUMA_0 0x68100
+#define TV_H_LUMA_59 0x681ec
+#define TV_H_CHROMA_0 0x68200
+#define TV_H_CHROMA_59 0x682ec
+#define TV_V_LUMA_0 0x68300
+#define TV_V_LUMA_42 0x683a8
+#define TV_V_CHROMA_0 0x68400
+#define TV_V_CHROMA_42 0x684a8
+
+/* Display & cursor control */
+
+/* Pipe A */
+#define PIPEADSL 0x70000
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (1<<30)
+#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPEACONF_SINGLE_WIDE 0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED (1<<25)
+#define PIPEACONF_PALETTE 0
+#define PIPEACONF_GAMMA (1<<24)
+#define PIPECONF_FORCE_BORDER (1<<25)
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+#define PIPEASTAT 0x70024
+#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
+#define PIPE_CRC_ERROR_ENABLE (1UL<<29)
+#define PIPE_CRC_DONE_ENABLE (1UL<<28)
+#define PIPE_GMBUS_EVENT_ENABLE (1UL<<27)
+#define PIPE_HOTPLUG_INTERRUPT_ENABLE (1UL<<26)
+#define PIPE_VSYNC_INTERRUPT_ENABLE (1UL<<25)
+#define PIPE_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
+#define PIPE_DPST_EVENT_ENABLE (1UL<<23)
+#define PIPE_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
+#define PIPE_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
+#define PIPE_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
+#define PIPE_HOTPLUG_TV_INTERRUPT_ENABLE (1UL<<18) /* pre-965 */
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
+#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+#define PIPE_OVERLAY_UPDATED_ENABLE (1UL<<16)
+#define PIPE_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
+#define PIPE_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
+#define PIPE_GMBUS_INTERRUPT_STATUS (1UL<<11)
+#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL<<10)
+#define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9)
+#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
+#define PIPE_DPST_EVENT_STATUS (1UL<<7)
+#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6)
+#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
+#define PIPE_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
+#define PIPE_HOTPLUG_TV_INTERRUPT_STATUS (1UL<<2) /* pre-965 */
+#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
+#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
+#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0)
+
+#define DSPARB 0x70030
+#define DSPARB_CSTART_MASK (0x7f << 7)
+#define DSPARB_CSTART_SHIFT 7
+#define DSPARB_BSTART_MASK (0x7f)
+#define DSPARB_BSTART_SHIFT 0
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ * do {
+ * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ * PIPE_FRAME_HIGH_SHIFT;
+ * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ * PIPE_FRAME_LOW_SHIFT);
+ * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ * PIPE_FRAME_HIGH_SHIFT);
+ * } while (high1 != high2);
+ * frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH 0x70040
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT 0
+#define PIPEAFRAMEPIXEL 0x70044
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_PIXEL_SHIFT 0
+
+/* Cursor A & B regs */
+#define CURACNTR 0x70080
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_64_32B_AX 0x07
+#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_GAMMA_ENABLE (1 << 26)
+#define CURABASE 0x70084
+#define CURAPOS 0x70088
+#define CURSOR_POS_MASK 0x007FF
+#define CURSOR_POS_SIGN 0x8000
+#define CURSOR_X_SHIFT 0
+#define CURSOR_Y_SHIFT 16
+#define CURBCNTR 0x700c0
+#define CURBBASE 0x700c4
+#define CURBPOS 0x700c8
+
+/* Display A control */
+#define DSPACNTR 0x70180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#define DISPPLANE_GAMMA_ENABLE (1<<30)
+#define DISPPLANE_GAMMA_DISABLE 0
+#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#define DISPPLANE_8BPP (0x2<<26)
+#define DISPPLANE_15_16BPP (0x4<<26)
+#define DISPPLANE_16BPP (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
+#define DISPPLANE_32BPP (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE (1<<25)
+#define DISPPLANE_STEREO_DISABLE 0
+#define DISPPLANE_SEL_PIPE_MASK (1<<24)
+#define DISPPLANE_SEL_PIPE_A 0
+#define DISPPLANE_SEL_PIPE_B (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE 0
+#define DISPPLANE_LINE_DOUBLE (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE 0
+#define DISPPLANE_STEREO_POLARITY_FIRST 0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+#define DSPAADDR 0x70184
+#define DSPASTRIDE 0x70188
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPASURF 0x7019C /* 965+ only */
+#define DSPATILEOFF 0x701A4 /* 965+ only */
+
+/* VBIOS flags */
+#define SWF00 0x71410
+#define SWF01 0x71414
+#define SWF02 0x71418
+#define SWF03 0x7141c
+#define SWF04 0x71420
+#define SWF05 0x71424
+#define SWF06 0x71428
+#define SWF10 0x70410
+#define SWF11 0x70414
+#define SWF14 0x71420
+#define SWF30 0x72414
+#define SWF31 0x72418
+#define SWF32 0x7241c
+
+/* Pipe B */
+#define PIPEBDSL 0x71000
+#define PIPEBCONF 0x71008
+#define PIPEBSTAT 0x71024
+#define PIPEBFRAMEHIGH 0x71040
+#define PIPEBFRAMEPIXEL 0x71044
+
+/* Display B control */
+#define DSPBCNTR 0x71180
+#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE 0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAY 0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
+#define DSPBADDR 0x71184
+#define DSPBSTRIDE 0x71188
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+#define DSPBSURF 0x7119C
+#define DSPBTILEOFF 0x711A4
+
+/* VBIOS regs */
+#define VGACNTRL 0x71400
+# define VGA_DISP_DISABLE (1 << 31)
+# define VGA_2X_MODE (1 << 30)
+# define VGA_PIPE_B_SELECT (1 << 29)
+
+#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
new file mode 100644
index 00000000000..603fe742ccd
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -0,0 +1,509 @@
+/*
+ *
+ * Copyright 2008 (c) Intel Corporation
+ * Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (pipe == PIPE_A)
+ return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
+ else
+ return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ u32 *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = dev_priv->save_palette_a;
+ else
+ array = dev_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ array[i] = I915_READ(reg + (i << 2));
+}
+
+static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ u32 *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = dev_priv->save_palette_a;
+ else
+ array = dev_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ I915_WRITE(reg + (i << 2), array[i]);
+}
+
+static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE8(index_port, reg);
+ return I915_READ8(data_port);
+}
+
+static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+ return I915_READ8(VGA_AR_DATA_READ);
+}
+
+static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+ I915_WRITE8(VGA_AR_DATA_WRITE, val);
+}
+
+static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE8(index_port, reg);
+ I915_WRITE8(data_port, val);
+}
+
+static void i915_save_vga(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+ u16 cr_index, cr_data, st01;
+
+ /* VGA color palette registers */
+ dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
+ /* DACCRX automatically increments during read */
+ I915_WRITE8(VGA_DACRX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
+
+ /* MSR bits */
+ dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
+ if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* CRT controller regs */
+ i915_write_indexed(dev, cr_index, cr_data, 0x11,
+ i915_read_indexed(dev, cr_index, cr_data, 0x11) &
+ (~0x80));
+ for (i = 0; i <= 0x24; i++)
+ dev_priv->saveCR[i] =
+ i915_read_indexed(dev, cr_index, cr_data, i);
+ /* Make sure we don't turn off CR group 0 writes */
+ dev_priv->saveCR[0x11] &= ~0x80;
+
+ /* Attribute controller registers */
+ I915_READ8(st01);
+ dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
+ for (i = 0; i <= 0x14; i++)
+ dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
+ I915_READ8(st01);
+
+ /* Graphics controller registers */
+ for (i = 0; i < 9; i++)
+ dev_priv->saveGR[i] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
+
+ dev_priv->saveGR[0x10] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+ dev_priv->saveGR[0x11] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+ dev_priv->saveGR[0x18] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+ /* Sequencer registers */
+ for (i = 0; i < 8; i++)
+ dev_priv->saveSR[i] =
+ i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void i915_restore_vga(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+ u16 cr_index, cr_data, st01;
+
+ /* MSR bits */
+ I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
+ if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* Sequencer registers, don't write SR07 */
+ for (i = 0; i < 7; i++)
+ i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
+ dev_priv->saveSR[i]);
+
+ /* CRT controller regs */
+ /* Enable CR group 0 writes */
+ i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+ for (i = 0; i <= 0x24; i++)
+ i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
+
+ /* Graphics controller regs */
+ for (i = 0; i < 9; i++)
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
+ dev_priv->saveGR[i]);
+
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+ dev_priv->saveGR[0x10]);
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+ dev_priv->saveGR[0x11]);
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+ dev_priv->saveGR[0x18]);
+
+ /* Attribute controller registers */
+ I915_READ8(st01); /* switch back to index mode */
+ for (i = 0; i <= 0x14; i++)
+ i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
+ I915_READ8(st01); /* switch back to index mode */
+ I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
+ I915_READ8(st01);
+
+ /* VGA color palette registers */
+ I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
+ /* DACCRX automatically increments during read */
+ I915_WRITE8(VGA_DACWX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
+
+}
+
+int i915_save_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+
+ /* Display arbitration control */
+ dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+ /* Pipe & plane A info */
+ dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+ dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+ dev_priv->saveFPA0 = I915_READ(FPA0);
+ dev_priv->saveFPA1 = I915_READ(FPA1);
+ dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+ if (IS_I965G(dev))
+ dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+ dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+ dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+ dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+ dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+ dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+ dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+ dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+ dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+ dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+ dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+ dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+ dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+ if (IS_I965G(dev)) {
+ dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+ dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+ }
+ i915_save_palette(dev, PIPE_A);
+ dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+
+ /* Pipe & plane B info */
+ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+ dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+ dev_priv->saveFPB0 = I915_READ(FPB0);
+ dev_priv->saveFPB1 = I915_READ(FPB1);
+ dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+ if (IS_I965G(dev))
+ dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+ dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+ dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+ dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+ dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+ dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+ dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+ dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+ dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+ dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+ dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+ dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+ dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+ if (IS_I965GM(dev) || IS_GM45(dev)) {
+ dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+ dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+ }
+ i915_save_palette(dev, PIPE_B);
+ dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+
+ /* CRT state */
+ dev_priv->saveADPA = I915_READ(ADPA);
+
+ /* LVDS state */
+ dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+ dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+ if (IS_I965G(dev))
+ dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ dev_priv->saveLVDS = I915_READ(LVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+ dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+ dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+ dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+
+ /* FIXME: save TV & SDVO state */
+
+ /* FBC state */
+ dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+ dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+ dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+ dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+
+ /* Interrupt state */
+ dev_priv->saveIIR = I915_READ(IIR);
+ dev_priv->saveIER = I915_READ(IER);
+ dev_priv->saveIMR = I915_READ(IMR);
+
+ /* VGA state */
+ dev_priv->saveVGA0 = I915_READ(VGA0);
+ dev_priv->saveVGA1 = I915_READ(VGA1);
+ dev_priv->saveVGA_PD = I915_READ(VGA_PD);
+ dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+ /* Clock gating state */
+ dev_priv->saveD_STATE = I915_READ(D_STATE);
+ dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
+
+ /* Cache mode state */
+ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+
+ /* Memory Arbitration state */
+ dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+
+ /* Scratch space */
+ for (i = 0; i < 16; i++) {
+ dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
+ dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+
+ i915_save_vga(dev);
+
+ return 0;
+}
+
+int i915_restore_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+
+ I915_WRITE(DSPARB, dev_priv->saveDSPARB);
+
+ /* Pipe & plane A info */
+ /* Prime the clock */
+ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+ I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+ ~DPLL_VCO_ENABLE);
+ DRM_UDELAY(150);
+ }
+ I915_WRITE(FPA0, dev_priv->saveFPA0);
+ I915_WRITE(FPA1, dev_priv->saveFPA1);
+ /* Actually enable it */
+ I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+ DRM_UDELAY(150);
+ if (IS_I965G(dev))
+ I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+ DRM_UDELAY(150);
+
+ /* Restore mode */
+ I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+ I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+ I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+ I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+ I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+ I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+ I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+ /* Restore plane info */
+ I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+ I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+ I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+ I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+ I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+ if (IS_I965G(dev)) {
+ I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+ I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+ }
+
+ I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+ i915_restore_palette(dev, PIPE_A);
+ /* Enable the plane */
+ I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+ I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+ /* Pipe & plane B info */
+ if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+ I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+ ~DPLL_VCO_ENABLE);
+ DRM_UDELAY(150);
+ }
+ I915_WRITE(FPB0, dev_priv->saveFPB0);
+ I915_WRITE(FPB1, dev_priv->saveFPB1);
+ /* Actually enable it */
+ I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+ DRM_UDELAY(150);
+ if (IS_I965G(dev))
+ I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+ DRM_UDELAY(150);
+
+ /* Restore mode */
+ I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+ I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+ I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+ I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+ I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+ I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+ I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+ /* Restore plane info */
+ I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+ I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+ I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+ I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+ I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+ if (IS_I965G(dev)) {
+ I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+ I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+ }
+
+ I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+ i915_restore_palette(dev, PIPE_B);
+ /* Enable the plane */
+ I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+ I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+
+ /* CRT state */
+ I915_WRITE(ADPA, dev_priv->saveADPA);
+
+ /* LVDS state */
+ if (IS_I965G(dev))
+ I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ I915_WRITE(LVDS, dev_priv->saveLVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+ I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+ I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+ I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+ I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+ I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
+ I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+
+ /* FIXME: restore TV & SDVO state */
+
+ /* FBC info */
+ I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+ I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+ I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+ I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+
+ /* VGA state */
+ I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+ I915_WRITE(VGA0, dev_priv->saveVGA0);
+ I915_WRITE(VGA1, dev_priv->saveVGA1);
+ I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
+ DRM_UDELAY(150);
+
+ /* Clock gating state */
+ I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+ I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
+
+ /* Cache mode state */
+ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+ /* Memory arbitration state */
+ I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+
+ for (i = 0; i < 16; i++) {
+ I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
+ I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+
+ i915_restore_vga(dev);
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 5572939fc7d..97ee566ef74 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
- DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL,
+ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_mga_buf_priv_t),
.load = mga_driver_load,
.unload = mga_driver_unload,
.lastclose = mga_driver_lastclose,
.dma_quiescent = mga_driver_dma_quiescent,
.device_is_agp = mga_driver_device_is_agp,
- .vblank_wait = mga_driver_vblank_wait,
+ .get_vblank_counter = mga_get_vblank_counter,
+ .enable_vblank = mga_enable_vblank,
+ .disable_vblank = mga_disable_vblank,
.irq_preinstall = mga_driver_irq_preinstall,
.irq_postinstall = mga_driver_irq_postinstall,
.irq_uninstall = mga_driver_irq_uninstall,
@@ -64,20 +65,20 @@ static struct drm_driver driver = {
.ioctls = mga_ioctls,
.dma_ioctl = mga_dma_buffers,
.fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
#ifdef CONFIG_COMPAT
- .compat_ioctl = mga_compat_ioctl,
+ .compat_ioctl = mga_compat_ioctl,
#endif
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
},
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index f6ebd24bd58..88257c276eb 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -120,6 +120,7 @@ typedef struct drm_mga_private {
u32 clear_cmd;
u32 maccess;
+ atomic_t vbl_received; /**< Number of vblanks received. */
wait_queue_head_t fence_queue;
atomic_t last_fence_retired;
u32 next_fence_to_post;
@@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
extern int mga_warp_init(drm_mga_private_t * dev_priv);
/* mga_irq.c */
+extern int mga_enable_vblank(struct drm_device *dev, int crtc);
+extern void mga_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern int mga_driver_irq_postinstall(struct drm_device *dev);
extern void mga_driver_irq_uninstall(struct drm_device * dev);
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
index 9302cb8f0f8..bab42f41188 100644
--- a/drivers/gpu/drm/mga/mga_irq.c
+++ b/drivers/gpu/drm/mga/mga_irq.c
@@ -1,5 +1,6 @@
/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
+ */
+/*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
@@ -35,6 +36,18 @@
#include "mga_drm.h"
#include "mga_drv.h"
+u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+ const drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ if (crtc != 0)
+ return 0;
+
+ return atomic_read(&dev_priv->vbl_received);
+}
+
+
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
@@ -47,9 +60,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
/* VBLANK interrupt */
if (status & MGA_VLINEPEN) {
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
- atomic_inc(&dev->vbl_received);
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
+ atomic_inc(&dev_priv->vbl_received);
+ drm_handle_vblank(dev, 0);
handled = 1;
}
@@ -58,6 +70,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
const u32 prim_end = MGA_READ(MGA_PRIMEND);
+
MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
/* In addition to clearing the interrupt-pending bit, we
@@ -72,28 +85,39 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
handled = 1;
}
- if (handled) {
+ if (handled)
return IRQ_HANDLED;
- }
return IRQ_NONE;
}
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_enable_vblank(struct drm_device *dev, int crtc)
{
- unsigned int cur_vblank;
- int ret = 0;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- /* Assume that the user has missed the current sequence number
- * by about a day rather than she wants to wait for years
- * using vertical blanks...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
- - *sequence) <= (1 << 23)));
+ if (crtc != 0) {
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ return 0;
+ }
- *sequence = cur_vblank;
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ return 0;
+}
- return ret;
+
+void mga_disable_vblank(struct drm_device *dev, int crtc)
+{
+ if (crtc != 0) {
+ DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+ crtc);
+ }
+
+ /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
+ * a nice hardware counter that tracks the number of refreshes when
+ * the interrupt is disabled, and the kernel doesn't know the refresh
+ * rate to calculate an estimate.
+ */
+ /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
}
int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -125,14 +149,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
MGA_WRITE(MGA_ICLEAR, ~0);
}
-void mga_driver_irq_postinstall(struct drm_device * dev)
+int mga_driver_irq_postinstall(struct drm_device *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ int ret;
+
+ ret = drm_vblank_init(dev, 1);
+ if (ret)
+ return ret;
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
- /* Turn on vertical blank interrupt and soft trap interrupt. */
- MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ /* Turn on soft trap interrupt. Vertical blank interrupts are enabled
+ * in mga_enable_vblank.
+ */
+ MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+ return 0;
}
void mga_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c
index d3f8aade07b..b710fab21cb 100644
--- a/drivers/gpu/drm/mga/mga_state.c
+++ b/drivers/gpu/drm/mga/mga_state.c
@@ -1022,7 +1022,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil
switch (param->param) {
case MGA_PARAM_IRQ_NR:
- value = dev->irq;
+ value = drm_dev_to_irq(dev);
break;
case MGA_PARAM_CARD_TYPE:
value = dev_priv->chipset;
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 6108e7587e1..3265d53ba91 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
- DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL,
+ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
.preclose = r128_driver_preclose,
.lastclose = r128_driver_lastclose,
- .vblank_wait = r128_driver_vblank_wait,
+ .get_vblank_counter = r128_get_vblank_counter,
+ .enable_vblank = r128_enable_vblank,
+ .disable_vblank = r128_disable_vblank,
.irq_preinstall = r128_driver_irq_preinstall,
.irq_postinstall = r128_driver_irq_postinstall,
.irq_uninstall = r128_driver_irq_uninstall,
@@ -59,21 +60,20 @@ static struct drm_driver driver = {
.ioctls = r128_ioctls,
.dma_ioctl = r128_cce_buffers,
.fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
#ifdef CONFIG_COMPAT
- .compat_ioctl = r128_compat_ioctl,
+ .compat_ioctl = r128_compat_ioctl,
#endif
},
-
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
},
.name = DRIVER_NAME,
@@ -87,6 +87,7 @@ static struct drm_driver driver = {
static int __init r128_init(void)
{
driver.num_ioctls = r128_max_ioctl;
+
return drm_init(&driver);
}
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 011105e51ac..5898b274279 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -29,7 +29,7 @@
* Rickard E. (Rik) Faith <faith@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
- * Michel Dänzer <daenzerm@student.ethz.ch>
+ * Michel D�zer <daenzerm@student.ethz.ch>
*/
#ifndef __R128_DRV_H__
@@ -97,6 +97,8 @@ typedef struct drm_r128_private {
u32 crtc_offset;
u32 crtc_offset_cntl;
+ atomic_t vbl_received;
+
u32 color_fmt;
unsigned int front_offset;
unsigned int front_pitch;
@@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
extern int r128_do_cleanup_cce(struct drm_device * dev);
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
+extern int r128_enable_vblank(struct drm_device *dev, int crtc);
+extern void r128_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern int r128_driver_irq_postinstall(struct drm_device *dev);
extern void r128_driver_irq_uninstall(struct drm_device * dev);
extern void r128_driver_lastclose(struct drm_device * dev);
extern void r128_driver_preclose(struct drm_device * dev,
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
index c76fdca7662..d7349012a68 100644
--- a/drivers/gpu/drm/r128/r128_irq.c
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -35,6 +35,16 @@
#include "r128_drm.h"
#include "r128_drv.h"
+u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+ const drm_r128_private_t *dev_priv = dev->dev_private;
+
+ if (crtc != 0)
+ return 0;
+
+ return atomic_read(&dev_priv->vbl_received);
+}
+
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
@@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
/* VBLANK interrupt */
if (status & R128_CRTC_VBLANK_INT) {
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
- atomic_inc(&dev->vbl_received);
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
+ atomic_inc(&dev_priv->vbl_received);
+ drm_handle_vblank(dev, 0);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int r128_enable_vblank(struct drm_device *dev, int crtc)
{
- unsigned int cur_vblank;
- int ret = 0;
+ drm_r128_private_t *dev_priv = dev->dev_private;
- /* Assume that the user has missed the current sequence number
- * by about a day rather than she wants to wait for years
- * using vertical blanks...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
- - *sequence) <= (1 << 23)));
+ if (crtc != 0) {
+ DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
+ return -EINVAL;
+ }
- *sequence = cur_vblank;
+ R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+ return 0;
+}
+
+void r128_disable_vblank(struct drm_device *dev, int crtc)
+{
+ if (crtc != 0)
+ DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
- return ret;
+ /*
+ * FIXME: implement proper interrupt disable by using the vblank
+ * counter register (if available)
+ *
+ * R128_WRITE(R128_GEN_INT_CNTL,
+ * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
+ */
}
void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
}
-void r128_driver_irq_postinstall(struct drm_device * dev)
+int r128_driver_irq_postinstall(struct drm_device *dev)
{
- drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
- /* Turn on VBL interrupt */
- R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+ return drm_vblank_init(dev, 1);
}
void r128_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 51a9afce7b9..f7a5b574076 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1629,7 +1629,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
switch (param->param) {
case R128_PARAM_IRQ_NR:
- value = dev->irq;
+ value = drm_dev_to_irq(dev);
break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 3331f88dcfb..59a2132a8f5 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -71,7 +71,8 @@ static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
{
- if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
return RS690_READ_MCIND(dev_priv, addr);
else
return RS480_READ_MCIND(dev_priv, addr);
@@ -82,7 +83,8 @@ u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
- else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+ else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
@@ -94,7 +96,8 @@ static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
{
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
- else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+ else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
@@ -106,7 +109,8 @@ static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_lo
{
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
- else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+ else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
@@ -122,15 +126,17 @@ static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
- } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+ } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
- } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480) {
+ } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
- RADEON_WRITE(RS480_AGP_BASE_2, 0);
+ RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
} else {
RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
@@ -223,7 +229,7 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
return 0;
DRM_UDELAY(1);
}
- DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
+ DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n",
RADEON_READ(RADEON_RBBM_STATUS),
RADEON_READ(R300_VAP_CNTL_STATUS));
@@ -252,7 +258,7 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
}
DRM_UDELAY(1);
}
- DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
+ DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n",
RADEON_READ(RADEON_RBBM_STATUS),
RADEON_READ(R300_VAP_CNTL_STATUS));
@@ -347,6 +353,7 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
DRM_INFO("Loading R300 Microcode\n");
for (i = 0; i < 256; i++) {
@@ -356,6 +363,7 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
R300_cp_microcode[i][0]);
}
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
DRM_INFO("Loading R400 Microcode\n");
for (i = 0; i < 256; i++) {
@@ -364,8 +372,9 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
R420_cp_microcode[i][0]);
}
- } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
- DRM_INFO("Loading RS690 Microcode\n");
+ } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+ DRM_INFO("Loading RS690/RS740 Microcode\n");
for (i = 0; i < 256; i++) {
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
RS690_cp_microcode[i][1]);
@@ -626,8 +635,6 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->ring.size_l2qw);
#endif
- /* Start with assuming that writeback doesn't work */
- dev_priv->writeback_works = 0;
/* Initialize the scratch register pointer. This will cause
* the scratch register values to be written out to memory
@@ -646,8 +653,18 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
/* Turn on bus mastering */
- tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
- RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+ /* rs400, rs690/rs740 */
+ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS;
+ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+ } else if (!(((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R423))) {
+ /* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
+ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+ } /* PCIE cards appears to not need this */
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
@@ -674,6 +691,9 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
{
u32 tmp;
+ /* Start with assuming that writeback doesn't work */
+ dev_priv->writeback_works = 0;
+
/* Writeback doesn't seem to work everywhere, test it here and possibly
* enable it if it appears to work
*/
@@ -719,7 +739,8 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
dev_priv->gart_size);
temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
- if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
RS690_BLOCK_GFX_D3_EN));
else
@@ -812,6 +833,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
u32 tmp;
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) ||
(dev_priv->flags & RADEON_IS_IGPGART)) {
radeon_set_igpgart(dev_priv, on);
return;
@@ -1286,7 +1308,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
radeon_cp_init_ring_buffer(dev, dev_priv);
radeon_do_engine_reset(dev);
- radeon_enable_interrupt(dev);
+ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
DRM_DEBUG("radeon_do_resume_cp() complete\n");
@@ -1708,6 +1730,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
case CHIP_R300:
case CHIP_R350:
case CHIP_R420:
+ case CHIP_R423:
case CHIP_RV410:
case CHIP_RV515:
case CHIP_R520:
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 637bd7faf13..71af746a4e4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -52,6 +52,28 @@ static int dri_library_name(struct drm_device *dev, char *buf)
"r300"));
}
+static int radeon_suspend(struct drm_device *dev, pm_message_t state)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ /* Disable *all* interrupts */
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+ RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+ return 0;
+}
+
+static int radeon_resume(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ /* Restore interrupt registers */
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+ RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+ return 0;
+}
+
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
@@ -59,8 +81,7 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
- DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+ DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load,
.firstopen = radeon_driver_firstopen,
@@ -69,8 +90,11 @@ static struct drm_driver driver = {
.postclose = radeon_driver_postclose,
.lastclose = radeon_driver_lastclose,
.unload = radeon_driver_unload,
- .vblank_wait = radeon_driver_vblank_wait,
- .vblank_wait2 = radeon_driver_vblank_wait2,
+ .suspend = radeon_suspend,
+ .resume = radeon_resume,
+ .get_vblank_counter = radeon_get_vblank_counter,
+ .enable_vblank = radeon_enable_vblank,
+ .disable_vblank = radeon_disable_vblank,
.dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 09938169317..4dbb813910c 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -122,9 +122,12 @@ enum radeon_family {
CHIP_RV350,
CHIP_RV380,
CHIP_R420,
+ CHIP_R423,
CHIP_RV410,
+ CHIP_RS400,
CHIP_RS480,
CHIP_RS690,
+ CHIP_RS740,
CHIP_RV515,
CHIP_R520,
CHIP_RV530,
@@ -378,17 +381,17 @@ extern void radeon_mem_release(struct drm_file *file_priv,
struct mem_block *heap);
/* radeon_irq.c */
+extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state);
extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
- unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
- unsigned int *sequence);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern int radeon_driver_irq_postinstall(struct drm_device *dev);
extern void radeon_driver_irq_uninstall(struct drm_device * dev);
extern void radeon_enable_interrupt(struct drm_device *dev);
extern int radeon_vblank_crtc_get(struct drm_device *dev);
@@ -397,19 +400,22 @@ extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_unload(struct drm_device *dev);
extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv);
-extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_preclose(struct drm_device *dev,
+ struct drm_file *file_priv);
+extern void radeon_driver_postclose(struct drm_device *dev,
+ struct drm_file *file_priv);
extern void radeon_driver_lastclose(struct drm_device * dev);
-extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
+extern int radeon_driver_open(struct drm_device *dev,
+ struct drm_file *file_priv);
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
/* r300_cmdbuf.c */
extern void r300_init_reg_flags(struct drm_device *dev);
-extern int r300_do_cp_cmdbuf(struct drm_device * dev,
+extern int r300_do_cp_cmdbuf(struct drm_device *dev,
struct drm_file *file_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf);
+ drm_radeon_kcmd_buffer_t *cmdbuf);
/* Flags for stats.boxes
*/
@@ -434,8 +440,31 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
# define RADEON_SCISSOR_1_ENABLE (1 << 29)
# define RADEON_SCISSOR_2_ENABLE (1 << 30)
+/*
+ * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx)
+ * don't have an explicit bus mastering disable bit. It's handled
+ * by the PCI D-states. PMI_BM_DIS disables D-state bus master
+ * handling, not bus mastering itself.
+ */
#define RADEON_BUS_CNTL 0x0030
+/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
# define RADEON_BUS_MASTER_DIS (1 << 6)
+/* rs400, rs690/rs740 */
+# define RS400_BUS_MASTER_DIS (1 << 14)
+# define RS400_MSI_REARM (1 << 20)
+/* see RS480_MSI_REARM in AIC_CNTL for rs480 */
+
+#define RADEON_BUS_CNTL1 0x0034
+# define RADEON_PMI_BM_DIS (1 << 2)
+# define RADEON_PMI_INT_DIS (1 << 3)
+
+#define RV370_BUS_CNTL 0x004c
+# define RV370_PMI_BM_DIS (1 << 5)
+# define RV370_PMI_INT_DIS (1 << 6)
+
+#define RADEON_MSI_REARM_EN 0x0160
+/* rv370/rv380, rv410, r423/r430/r480, r5xx */
+# define RV370_MSI_REARM_EN (1 << 0)
#define RADEON_CLOCK_CNTL_DATA 0x000c
# define RADEON_PLL_WR_EN (1 << 7)
@@ -623,6 +652,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
# define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
# define RADEON_SW_INT_FIRE (1 << 26)
+# define R500_DISPLAY_INT_STATUS (1 << 0)
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
@@ -907,6 +937,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
#define RADEON_AIC_CNTL 0x01d0
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
+# define RS480_MSI_REARM (1 << 3)
#define RADEON_AIC_STAT 0x01d4
#define RADEON_AIC_PT_BASE 0x01d8
#define RADEON_AIC_LO_ADDR 0x01dc
@@ -1116,6 +1147,9 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
#define R200_VAP_PVS_CNTL_1 0x22D0
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
#define R500_D1CRTC_STATUS 0x609c
#define R500_D2CRTC_STATUS 0x689c
#define R500_CRTC_V_BLANK (1<<0)
@@ -1200,7 +1234,8 @@ do { \
#define IGP_WRITE_MCIND(addr, val) \
do { \
- if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) \
+ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || \
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) \
RS690_WRITE_MCIND(addr, val); \
else \
RS480_WRITE_MCIND(addr, val); \
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index ee40d197deb..5079f7054a2 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -27,7 +27,7 @@
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
- * Michel Dänzer <michel@daenzer.net>
+ * Michel D�zer <michel@daenzer.net>
*/
#include "drmP.h"
@@ -35,12 +35,128 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
- u32 mask)
+void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
{
- u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if (state)
+ dev_priv->irq_enable_reg |= mask;
+ else
+ dev_priv->irq_enable_reg &= ~mask;
+
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
+static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if (state)
+ dev_priv->r500_disp_irq_reg |= mask;
+ else
+ dev_priv->r500_disp_irq_reg &= ~mask;
+
+ RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+}
+
+int radeon_enable_vblank(struct drm_device *dev, int crtc)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+ switch (crtc) {
+ case 0:
+ r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
+ break;
+ case 1:
+ r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ return EINVAL;
+ }
+ } else {
+ switch (crtc) {
+ case 0:
+ radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
+ break;
+ case 1:
+ radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ return EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+void radeon_disable_vblank(struct drm_device *dev, int crtc)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+ switch (crtc) {
+ case 0:
+ r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
+ break;
+ case 1:
+ r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ break;
+ }
+ } else {
+ switch (crtc) {
+ case 0:
+ radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
+ break;
+ case 1:
+ radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ break;
+ }
+ }
+}
+
+static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
+{
+ u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
+ u32 irq_mask = RADEON_SW_INT_TEST;
+
+ *r500_disp_int = 0;
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+ /* vbl interrupts in a different place */
+
+ if (irqs & R500_DISPLAY_INT_STATUS) {
+ /* if a display interrupt */
+ u32 disp_irq;
+
+ disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
+
+ *r500_disp_int = disp_irq;
+ if (disp_irq & R500_D1_VBLANK_INTERRUPT)
+ RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+ if (disp_irq & R500_D2_VBLANK_INTERRUPT)
+ RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+ }
+ irq_mask |= R500_DISPLAY_INT_STATUS;
+ } else
+ irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
+
+ irqs &= irq_mask;
+
if (irqs)
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+
return irqs;
}
@@ -68,44 +184,33 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
u32 stat;
+ u32 r500_disp_int;
/* Only consider the bits we're interested in - others could be used
* outside the DRM
*/
- stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT |
- RADEON_CRTC2_VBLANK_STAT));
+ stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
if (!stat)
return IRQ_NONE;
stat &= dev_priv->irq_enable_reg;
/* SW interrupt */
- if (stat & RADEON_SW_INT_TEST) {
+ if (stat & RADEON_SW_INT_TEST)
DRM_WAKEUP(&dev_priv->swi_queue);
- }
/* VBLANK interrupt */
- if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
- int vblank_crtc = dev_priv->vblank_crtc;
-
- if ((vblank_crtc &
- (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
- (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
- if (stat & RADEON_CRTC_VBLANK_STAT)
- atomic_inc(&dev->vbl_received);
- if (stat & RADEON_CRTC2_VBLANK_STAT)
- atomic_inc(&dev->vbl_received2);
- } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
- (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
- ((stat & RADEON_CRTC2_VBLANK_STAT) &&
- (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
- atomic_inc(&dev->vbl_received);
-
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+ if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
+ drm_handle_vblank(dev, 0);
+ if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
+ drm_handle_vblank(dev, 1);
+ } else {
+ if (stat & RADEON_CRTC_VBLANK_STAT)
+ drm_handle_vblank(dev, 0);
+ if (stat & RADEON_CRTC2_VBLANK_STAT)
+ drm_handle_vblank(dev, 1);
}
-
return IRQ_HANDLED;
}
@@ -144,54 +249,31 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
return ret;
}
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
- unsigned int *sequence, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
{
- drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *) dev->dev_private;
- unsigned int cur_vblank;
- int ret = 0;
- int ack = 0;
- atomic_t *counter;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- if (crtc == DRM_RADEON_VBLANK_CRTC1) {
- counter = &dev->vbl_received;
- ack |= RADEON_CRTC_VBLANK_STAT;
- } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
- counter = &dev->vbl_received2;
- ack |= RADEON_CRTC2_VBLANK_STAT;
- } else
+ if (crtc < 0 || crtc > 1) {
+ DRM_ERROR("Invalid crtc %d\n", crtc);
return -EINVAL;
+ }
- radeon_acknowledge_irqs(dev_priv, ack);
-
- dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
- /* Assume that the user has missed the current sequence number
- * by about a day rather than she wants to wait for years
- * using vertical blanks...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(counter))
- - *sequence) <= (1 << 23)));
-
- *sequence = cur_vblank;
-
- return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+ if (crtc == 0)
+ return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
+ else
+ return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
+ } else {
+ if (crtc == 0)
+ return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
+ else
+ return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
+ }
}
/* Needs the lock as it touches the ring.
@@ -234,46 +316,41 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
return radeon_wait_irq(dev, irqwait->irq_seq);
}
-void radeon_enable_interrupt(struct drm_device *dev)
-{
- drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
- dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
- dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
- dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
- dev_priv->irq_enabled = 1;
-}
-
/* drm_dma.h hooks
*/
void radeon_driver_irq_preinstall(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
+ u32 dummy;
/* Disable *all* interrupts */
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+ RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
/* Clear bits if they're already high */
- radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT |
- RADEON_CRTC2_VBLANK_STAT));
+ radeon_acknowledge_irqs(dev_priv, &dummy);
}
-void radeon_driver_irq_postinstall(struct drm_device * dev)
+int radeon_driver_irq_postinstall(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
+ int ret;
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- radeon_enable_interrupt(dev);
+ ret = drm_vblank_init(dev, 2);
+ if (ret)
+ return ret;
+
+ dev->max_vblank_count = 0x001fffff;
+
+ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
+
+ return 0;
}
void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -285,6 +362,8 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
dev_priv->irq_enabled = 0;
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+ RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
/* Disable *all* interrupts */
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
}
@@ -293,18 +372,8 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
int radeon_vblank_crtc_get(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
- u32 flag;
- u32 value;
-
- flag = RADEON_READ(RADEON_GEN_INT_CNTL);
- value = 0;
-
- if (flag & RADEON_CRTC_VBLANK_MASK)
- value |= DRM_RADEON_VBLANK_CRTC1;
- if (flag & RADEON_CRTC2_VBLANK_MASK)
- value |= DRM_RADEON_VBLANK_CRTC2;
- return value;
+ return dev_priv->vblank_crtc;
}
int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
@@ -315,6 +384,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
return -EINVAL;
}
dev_priv->vblank_crtc = (unsigned int)value;
- radeon_enable_interrupt(dev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 11c146b4921..5d7153fcc7b 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -2997,7 +2997,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
value = GET_SCRATCH(2);
break;
case RADEON_PARAM_IRQ_NR:
- value = dev->irq;
+ value = drm_dev_to_irq(dev);
break;
case RADEON_PARAM_GART_BASE:
value = dev_priv->gart_vm_start;
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index b3878770fce..af22111397d 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -41,7 +41,7 @@
#define AGP_TYPE 1
-#if defined(CONFIG_FB_SIS)
+#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
/* fb management via fb device */
#define SIS_MM_ALIGN_SHIFT 0
@@ -57,7 +57,7 @@ static void *sis_sman_mm_allocate(void *private, unsigned long size,
if (req.size == 0)
return NULL;
else
- return (void *)~req.offset;
+ return (void *)(unsigned long)~req.offset;
}
static void sis_sman_mm_free(void *private, void *ref)
@@ -75,12 +75,12 @@ static unsigned long sis_sman_mm_offset(void *private, void *ref)
return ~((unsigned long)ref);
}
-#else /* CONFIG_FB_SIS */
+#else /* CONFIG_FB_SIS[_MODULE] */
#define SIS_MM_ALIGN_SHIFT 4
#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
-#endif /* CONFIG_FB_SIS */
+#endif /* CONFIG_FB_SIS[_MODULE] */
static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
@@ -89,7 +89,7 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file
int ret;
mutex_lock(&dev->struct_mutex);
-#if defined(CONFIG_FB_SIS)
+#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
{
struct drm_sman_mm sman_mm;
sman_mm.private = (void *)0xFFFFFFFF;
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 80c01cdfa37..0993b441fc4 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
- DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ DRIVER_IRQ_SHARED,
.load = via_driver_load,
.unload = via_driver_unload,
.context_dtor = via_final_context,
- .vblank_wait = via_driver_vblank_wait,
+ .get_vblank_counter = via_get_vblank_counter,
+ .enable_vblank = via_enable_vblank,
+ .disable_vblank = via_disable_vblank,
.irq_preinstall = via_driver_irq_preinstall,
.irq_postinstall = via_driver_irq_postinstall,
.irq_uninstall = via_driver_irq_uninstall,
@@ -59,17 +61,17 @@ static struct drm_driver driver = {
.get_reg_ofs = drm_core_get_reg_ofs,
.ioctls = via_ioctls,
.fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- },
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
},
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 2daae81874c..cafcb844a22 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -75,6 +75,7 @@ typedef struct drm_via_private {
struct timeval last_vblank;
int last_vblank_valid;
unsigned usec_per_vblank;
+ atomic_t vbl_received;
drm_via_state_t hc_state;
char pci_buf[VIA_PCI_BUF_SIZE];
const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -130,21 +131,24 @@ extern int via_init_context(struct drm_device * dev, int context);
extern int via_final_context(struct drm_device * dev, int context);
extern int via_do_cleanup_map(struct drm_device * dev);
-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int via_enable_vblank(struct drm_device *dev, int crtc);
+extern void via_disable_vblank(struct drm_device *dev, int crtc);
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
extern void via_driver_irq_preinstall(struct drm_device * dev);
-extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern int via_driver_irq_postinstall(struct drm_device *dev);
extern void via_driver_irq_uninstall(struct drm_device * dev);
extern int via_dma_cleanup(struct drm_device * dev);
extern void via_init_command_verifier(void);
extern int via_driver_dma_quiescent(struct drm_device * dev);
-extern void via_init_futex(drm_via_private_t * dev_priv);
-extern void via_cleanup_futex(drm_via_private_t * dev_priv);
-extern void via_release_futex(drm_via_private_t * dev_priv, int context);
+extern void via_init_futex(drm_via_private_t *dev_priv);
+extern void via_cleanup_futex(drm_via_private_t *dev_priv);
+extern void via_release_futex(drm_via_private_t *dev_priv, int context);
-extern void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv);
+extern void via_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv);
extern void via_lastclose(struct drm_device *dev);
extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index c6bb978a110..665d319b927 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -43,7 +43,7 @@
#define VIA_REG_INTERRUPT 0x200
/* VIA_REG_INTERRUPT */
-#define VIA_IRQ_GLOBAL (1 << 31)
+#define VIA_IRQ_GLOBAL (1 << 31)
#define VIA_IRQ_VBLANK_ENABLE (1 << 19)
#define VIA_IRQ_VBLANK_PENDING (1 << 3)
#define VIA_IRQ_HQV0_ENABLE (1 << 11)
@@ -68,16 +68,15 @@
static maskarray_t via_pro_group_a_irqs[] = {
{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
- 0x00000000},
+ 0x00000000 },
{VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
- 0x00000000},
+ 0x00000000 },
{VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
};
-static int via_num_pro_group_a =
- sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
static maskarray_t via_unichrome_irqs[] = {
@@ -86,14 +85,24 @@ static maskarray_t via_unichrome_irqs[] = {
{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
};
-static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+
static unsigned time_diff(struct timeval *now, struct timeval *then)
{
return (now->tv_usec >= then->tv_usec) ?
- now->tv_usec - then->tv_usec :
- 1000000 - (then->tv_usec - now->tv_usec);
+ now->tv_usec - then->tv_usec :
+ 1000000 - (then->tv_usec - now->tv_usec);
+}
+
+u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+ drm_via_private_t *dev_priv = dev->dev_private;
+ if (crtc != 0)
+ return 0;
+
+ return atomic_read(&dev_priv->vbl_received);
}
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -108,23 +117,22 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
status = VIA_READ(VIA_REG_INTERRUPT);
if (status & VIA_IRQ_VBLANK_PENDING) {
- atomic_inc(&dev->vbl_received);
- if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+ atomic_inc(&dev_priv->vbl_received);
+ if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
do_gettimeofday(&cur_vblank);
if (dev_priv->last_vblank_valid) {
dev_priv->usec_per_vblank =
- time_diff(&cur_vblank,
- &dev_priv->last_vblank) >> 4;
+ time_diff(&cur_vblank,
+ &dev_priv->last_vblank) >> 4;
}
dev_priv->last_vblank = cur_vblank;
dev_priv->last_vblank_valid = 1;
}
- if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+ if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
DRM_DEBUG("US per vblank is: %u\n",
dev_priv->usec_per_vblank);
}
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
+ drm_handle_vblank(dev, 0);
handled = 1;
}
@@ -145,6 +153,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
/* Acknowlege interrupts */
VIA_WRITE(VIA_REG_INTERRUPT, status);
+
if (handled)
return IRQ_HANDLED;
else
@@ -163,31 +172,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
}
}
-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int via_enable_vblank(struct drm_device *dev, int crtc)
{
- drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
- unsigned int cur_vblank;
- int ret = 0;
+ drm_via_private_t *dev_priv = dev->dev_private;
+ u32 status;
- DRM_DEBUG("\n");
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
+ if (crtc != 0) {
+ DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
return -EINVAL;
}
- viadrv_acknowledge_irqs(dev_priv);
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
- /* Assume that the user has missed the current sequence number
- * by about a day rather than she wants to wait for years
- * using vertical blanks...
- */
+ return 0;
+}
+
+void via_disable_vblank(struct drm_device *dev, int crtc)
+{
+ drm_via_private_t *dev_priv = dev->dev_private;
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received)) -
- *sequence) <= (1 << 23)));
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
- *sequence = cur_vblank;
- return ret;
+ if (crtc != 0)
+ DRM_ERROR("%s: bad crtc %d\n", __func__, crtc);
}
static int
@@ -239,6 +251,7 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc
return ret;
}
+
/*
* drm_dma.h hooks
*/
@@ -292,23 +305,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
}
}
-void via_driver_irq_postinstall(struct drm_device * dev)
+int via_driver_irq_postinstall(struct drm_device *dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
- DRM_DEBUG("\n");
- if (dev_priv) {
- status = VIA_READ(VIA_REG_INTERRUPT);
- VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
- | dev_priv->irq_enable_mask);
+ DRM_DEBUG("via_driver_irq_postinstall\n");
+ if (!dev_priv)
+ return -EINVAL;
- /* Some magic, oh for some data sheets ! */
+ drm_vblank_init(dev, 1);
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+ | dev_priv->irq_enable_mask);
- VIA_WRITE8(0x83d4, 0x11);
- VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+ /* Some magic, oh for some data sheets ! */
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
- }
+ return 0;
}
void via_driver_irq_uninstall(struct drm_device * dev)
@@ -339,9 +354,6 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
drm_via_irq_t *cur_irq = dev_priv->via_irqs;
int force_sequence;
- if (!dev->irq)
- return -EINVAL;
-
if (irqwait->request.irq >= dev_priv->num_irqs) {
DRM_ERROR("Trying to wait on unknown irq %d\n",
irqwait->request.irq);
@@ -352,7 +364,8 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
case VIA_IRQ_RELATIVE:
- irqwait->request.sequence += atomic_read(&cur_irq->irq_received);
+ irqwait->request.sequence +=
+ atomic_read(&cur_irq->irq_received);
irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
case VIA_IRQ_ABSOLUTE:
break;
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index e64094916e4..f694cb5eded 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -93,8 +93,7 @@ int via_final_context(struct drm_device *dev, int context)
/* Last context, perform cleanup */
if (dev->ctx_count == 1 && dev->dev_private) {
DRM_DEBUG("Last Context\n");
- if (dev->irq)
- drm_irq_uninstall(dev);
+ drm_irq_uninstall(dev);
via_cleanup_futex(dev_priv);
via_do_cleanup_map(dev);
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index cacf89e65af..f5999a91614 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -67,4 +67,201 @@ config HIDRAW
source "drivers/hid/usbhid/Kconfig"
+menu "Special HID drivers"
+ depends on HID
+
+config HID_COMPAT
+ bool "Load all HID drivers on hid core load"
+ default y
+ ---help---
+ Compatible option for older userspace. If you have system without udev
+ support of module loading through aliases and also old
+ module-init-tools which can't handle hid bus, choose Y here. Otherwise
+ say N. If you say N and your userspace is old enough, the only
+ functionality you lose is modules autoloading.
+
+ If unsure, say Y.
+
+config HID_A4TECH
+ tristate "A4 tech" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for A4 tech X5 and WOP-35 / Trust 450L mice.
+
+config HID_APPLE
+ tristate "Apple" if EMBEDDED
+ depends on (USB_HID || BT_HIDP)
+ default y
+ ---help---
+ Support for some Apple devices which less or more break
+ HID specification.
+
+ Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
+ MacBooks, MacBook Pros and Apple Aluminum.
+
+config HID_BELKIN
+ tristate "Belkin" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Belkin Flip KVM and Wireless keyboard.
+
+config HID_BRIGHT
+ tristate "Bright" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Bright ABNT-2 keyboard.
+
+config HID_CHERRY
+ tristate "Cherry" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Cherry Cymotion keyboard.
+
+config HID_CHICONY
+ tristate "Chicony" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Chicony Tactical pad.
+
+config HID_CYPRESS
+ tristate "Cypress" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for cypress mouse and barcode readers.
+
+config HID_DELL
+ tristate "Dell" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for quirky Dell HID hardware that require
+ special LED handling (W7658 and SK8115 models)
+
+config HID_EZKEY
+ tristate "Ezkey" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Ezkey BTC 8193 keyboard.
+
+config HID_GYRATION
+ tristate "Gyration" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Gyration remote control.
+
+config HID_LOGITECH
+ tristate "Logitech" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Logitech devices that are not fully compliant with HID standard.
+
+config LOGITECH_FF
+ bool "Logitech force feedback"
+ depends on HID_LOGITECH
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you have one of these devices:
+ - Logitech WingMan Cordless RumblePad
+ - Logitech WingMan Cordless RumblePad 2
+ - Logitech WingMan Force 3D
+ - Logitech Formula Force EX
+ - Logitech MOMO Force wheel
+
+ and if you want to enable force feedback for them.
+ Note: if you say N here, this device will still be supported, but without
+ force feedback.
+
+config LOGIRUMBLEPAD2_FF
+ bool "Logitech Rumblepad 2 force feedback"
+ depends on HID_LOGITECH
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you want to enable force feedback support for Logitech
+ Rumblepad 2 devices.
+
+config HID_MICROSOFT
+ tristate "Microsoft" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Microsoft devices that are not fully compliant with HID standard.
+
+config HID_MONTEREY
+ tristate "Monterey" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Monterey Genius KB29E.
+
+config HID_PANTHERLORD
+ tristate "Pantherlord devices support" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for PantherLord/GreenAsia based device support.
+
+config PANTHERLORD_FF
+ bool "Pantherlord force feedback support"
+ depends on HID_PANTHERLORD
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you have a PantherLord/GreenAsia based game controller
+ or adapter and want to enable force feedback support for it.
+
+config HID_PETALYNX
+ tristate "Petalynx" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Petalynx Maxter remote control.
+
+config HID_SAMSUNG
+ tristate "Samsung" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Samsung InfraRed remote control.
+
+config HID_SONY
+ tristate "Sony" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Sony PS3 controller.
+
+config HID_SUNPLUS
+ tristate "Sunplus" if EMBEDDED
+ depends on USB_HID
+ default y
+ ---help---
+ Support for Sunplus wireless desktop.
+
+config THRUSTMASTER_FF
+ tristate "ThrustMaster devices support"
+ default m
+ depends on USB_HID
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
+ a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
+
+config ZEROPLUS_FF
+ tristate "Zeroplus based game controller support"
+ default m
+ depends on USB_HID
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you have a Zeroplus based game controller.
+
+endmenu
+
endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 275dc522c73..b09e43e7413 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -1,13 +1,46 @@
#
# Makefile for the HID driver
#
-hid-objs := hid-core.o hid-input.o hid-input-quirks.o
+hid-objs := hid-core.o hid-input.o
obj-$(CONFIG_HID) += hid.o
hid-$(CONFIG_HID_DEBUG) += hid-debug.o
hid-$(CONFIG_HIDRAW) += hidraw.o
+ifdef CONFIG_HID_COMPAT
+obj-m += hid-dummy.o
+endif
+
+hid-logitech-objs := hid-lg.o
+ifdef CONFIG_LOGITECH_FF
+ hid-logitech-objs += hid-lgff.o
+endif
+ifdef CONFIG_LOGIRUMBLEPAD2_FF
+ hid-logitech-objs += hid-lg2ff.o
+endif
+
+obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
+obj-$(CONFIG_HID_APPLE) += hid-apple.o
+obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
+obj-$(CONFIG_HID_BRIGHT) += hid-bright.o
+obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
+obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
+obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
+obj-$(CONFIG_HID_DELL) += hid-dell.o
+obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
+obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
+obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
+obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
+obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
+obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
+obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
+obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
+obj-$(CONFIG_HID_SONY) += hid-sony.o
+obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
+obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
+obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
+
obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
obj-$(CONFIG_USB_KBD) += usbhid/
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
new file mode 100644
index 00000000000..ebca00e6c10
--- /dev/null
+++ b/drivers/hid/hid-a4tech.c
@@ -0,0 +1,162 @@
+/*
+ * HID driver for some a4tech "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define A4_2WHEEL_MOUSE_HACK_7 0x01
+#define A4_2WHEEL_MOUSE_HACK_B8 0x02
+
+struct a4tech_sc {
+ unsigned long quirks;
+ unsigned int hw_wheel;
+ __s32 delayed_value;
+};
+
+static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+ if (usage->type == EV_REL && usage->code == REL_WHEEL)
+ set_bit(REL_HWHEEL, *bit);
+
+ if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)
+ return -1;
+
+ return 0;
+}
+
+static int a4_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+ struct input_dev *input;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ input = field->hidinput->input;
+
+ if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {
+ if (usage->type == EV_REL && usage->code == REL_WHEEL) {
+ a4->delayed_value = value;
+ return 1;
+ }
+
+ if (usage->hid == 0x000100b8) {
+ input_event(input, EV_REL, value ? REL_HWHEEL :
+ REL_WHEEL, a4->delayed_value);
+ return 1;
+ }
+ }
+
+ if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {
+ a4->hw_wheel = !!value;
+ return 1;
+ }
+
+ if (usage->code == REL_WHEEL && a4->hw_wheel) {
+ input_event(input, usage->type, REL_HWHEEL, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct a4tech_sc *a4;
+ int ret;
+
+ a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
+ if (a4 == NULL) {
+ dev_err(&hdev->dev, "can't alloc device descriptor\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ a4->quirks = id->driver_data;
+
+ hid_set_drvdata(hdev, a4);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ kfree(a4);
+ return ret;
+}
+
+static void a4_remove(struct hid_device *hdev)
+{
+ struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+ hid_hw_stop(hdev);
+ kfree(a4);
+}
+
+static const struct hid_device_id a4_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),
+ .driver_data = A4_2WHEEL_MOUSE_HACK_7 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
+ .driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, a4_devices);
+
+static struct hid_driver a4_driver = {
+ .name = "a4tech",
+ .id_table = a4_devices,
+ .input_mapped = a4_input_mapped,
+ .event = a4_event,
+ .probe = a4_probe,
+ .remove = a4_remove,
+};
+
+static int a4_init(void)
+{
+ return hid_register_driver(&a4_driver);
+}
+
+static void a4_exit(void)
+{
+ hid_unregister_driver(&a4_driver);
+}
+
+module_init(a4_init);
+module_exit(a4_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(a4tech);
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
new file mode 100644
index 00000000000..fd7f896b34f
--- /dev/null
+++ b/drivers/hid/hid-apple.c
@@ -0,0 +1,484 @@
+/*
+ * USB HID quirks support for Linux
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define APPLE_RDESC_JIS 0x0001
+#define APPLE_IGNORE_MOUSE 0x0002
+#define APPLE_HAS_FN 0x0004
+#define APPLE_HIDDEV 0x0008
+#define APPLE_ISO_KEYBOARD 0x0010
+#define APPLE_MIGHTYMOUSE 0x0020
+#define APPLE_INVERT_HWHEEL 0x0040
+#define APPLE_IGNORE_HIDINPUT 0x0080
+#define APPLE_NUMLOCK_EMULATION 0x0100
+
+#define APPLE_FLAG_FKEY 0x01
+
+static unsigned int fnmode = 1;
+module_param(fnmode, uint, 0644);
+MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
+ "[1] = fkeyslast, 2 = fkeysfirst)");
+
+struct apple_sc {
+ unsigned long quirks;
+ unsigned int fn_on;
+ DECLARE_BITMAP(pressed_fn, KEY_CNT);
+ DECLARE_BITMAP(pressed_numlock, KEY_CNT);
+};
+
+struct apple_key_translation {
+ u16 from;
+ u16 to;
+ u8 flags;
+};
+
+static struct apple_key_translation apple_fn_keys[] = {
+ { KEY_BACKSPACE, KEY_DELETE },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
+ { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
+ { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
+ { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
+ { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
+ { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
+ { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
+ { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
+ { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
+ { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
+ { }
+};
+
+static struct apple_key_translation powerbook_fn_keys[] = {
+ { KEY_BACKSPACE, KEY_DELETE },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
+ { KEY_F3, KEY_MUTE, APPLE_FLAG_FKEY },
+ { KEY_F4, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
+ { KEY_F5, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
+ { KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY },
+ { KEY_F7, KEY_SWITCHVIDEOMODE, APPLE_FLAG_FKEY },
+ { KEY_F8, KEY_KBDILLUMTOGGLE, APPLE_FLAG_FKEY },
+ { KEY_F9, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
+ { KEY_F10, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
+ { }
+};
+
+static struct apple_key_translation powerbook_numlock_keys[] = {
+ { KEY_J, KEY_KP1 },
+ { KEY_K, KEY_KP2 },
+ { KEY_L, KEY_KP3 },
+ { KEY_U, KEY_KP4 },
+ { KEY_I, KEY_KP5 },
+ { KEY_O, KEY_KP6 },
+ { KEY_7, KEY_KP7 },
+ { KEY_8, KEY_KP8 },
+ { KEY_9, KEY_KP9 },
+ { KEY_M, KEY_KP0 },
+ { KEY_DOT, KEY_KPDOT },
+ { KEY_SLASH, KEY_KPPLUS },
+ { KEY_SEMICOLON, KEY_KPMINUS },
+ { KEY_P, KEY_KPASTERISK },
+ { KEY_MINUS, KEY_KPEQUAL },
+ { KEY_0, KEY_KPSLASH },
+ { KEY_F6, KEY_NUMLOCK },
+ { KEY_KPENTER, KEY_KPENTER },
+ { KEY_BACKSPACE, KEY_BACKSPACE },
+ { }
+};
+
+static struct apple_key_translation apple_iso_keyboard[] = {
+ { KEY_GRAVE, KEY_102ND },
+ { KEY_102ND, KEY_GRAVE },
+ { }
+};
+
+static struct apple_key_translation *apple_find_translation(
+ struct apple_key_translation *table, u16 from)
+{
+ struct apple_key_translation *trans;
+
+ /* Look for the translation */
+ for (trans = table; trans->from; trans++)
+ if (trans->from == from)
+ return trans;
+
+ return NULL;
+}
+
+static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
+ struct hid_usage *usage, __s32 value)
+{
+ struct apple_sc *asc = hid_get_drvdata(hid);
+ struct apple_key_translation *trans;
+
+ if (usage->code == KEY_FN) {
+ asc->fn_on = !!value;
+ input_event(input, usage->type, usage->code, value);
+ return 1;
+ }
+
+ if (fnmode) {
+ int do_translate;
+
+ trans = apple_find_translation((hid->product < 0x220 ||
+ hid->product >= 0x300) ?
+ powerbook_fn_keys : apple_fn_keys,
+ usage->code);
+ if (trans) {
+ if (test_bit(usage->code, asc->pressed_fn))
+ do_translate = 1;
+ else if (trans->flags & APPLE_FLAG_FKEY)
+ do_translate = (fnmode == 2 && asc->fn_on) ||
+ (fnmode == 1 && !asc->fn_on);
+ else
+ do_translate = asc->fn_on;
+
+ if (do_translate) {
+ if (value)
+ set_bit(usage->code, asc->pressed_fn);
+ else
+ clear_bit(usage->code, asc->pressed_fn);
+
+ input_event(input, usage->type, trans->to,
+ value);
+
+ return 1;
+ }
+ }
+
+ if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
+ (test_bit(usage->code, asc->pressed_numlock) ||
+ test_bit(LED_NUML, input->led))) {
+ trans = apple_find_translation(powerbook_numlock_keys,
+ usage->code);
+
+ if (trans) {
+ if (value)
+ set_bit(usage->code,
+ asc->pressed_numlock);
+ else
+ clear_bit(usage->code,
+ asc->pressed_numlock);
+
+ input_event(input, usage->type, trans->to,
+ value);
+ }
+
+ return 1;
+ }
+ }
+
+ if (asc->quirks & APPLE_ISO_KEYBOARD) {
+ trans = apple_find_translation(apple_iso_keyboard, usage->code);
+ if (trans) {
+ input_event(input, usage->type, trans->to, value);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int apple_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct apple_sc *asc = hid_get_drvdata(hdev);
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
+ usage->code == REL_HWHEEL) {
+ input_event(field->hidinput->input, usage->type, usage->code,
+ -value);
+ return 1;
+ }
+
+ if ((asc->quirks & APPLE_HAS_FN) &&
+ hidinput_apple_event(hdev, field->hidinput->input,
+ usage, value))
+ return 1;
+
+
+ return 0;
+}
+
+/*
+ * MacBook JIS keyboard has wrong logical maximum
+ */
+static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ struct apple_sc *asc = hid_get_drvdata(hdev);
+
+ if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 &&
+ rdesc[53] == 0x65 && rdesc[59] == 0x65) {
+ dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
+ "descriptor\n");
+ rdesc[53] = rdesc[59] = 0xe7;
+ }
+}
+
+static void apple_setup_input(struct input_dev *input)
+{
+ struct apple_key_translation *trans;
+
+ set_bit(KEY_NUMLOCK, input->keybit);
+
+ /* Enable all needed keys */
+ for (trans = apple_fn_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+
+ for (trans = powerbook_fn_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+
+ for (trans = powerbook_numlock_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+
+ for (trans = apple_iso_keyboard; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+}
+
+static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->hid == (HID_UP_CUSTOM | 0x0003)) {
+ /* The fn key on Apple USB keyboards */
+ set_bit(EV_REP, hi->input->evbit);
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+ apple_setup_input(hi->input);
+ return 1;
+ }
+
+ /* we want the hid layer to go through standard path (set and ignore) */
+ return 0;
+}
+
+static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct apple_sc *asc = hid_get_drvdata(hdev);
+
+ if (asc->quirks & APPLE_MIGHTYMOUSE) {
+ if (usage->hid == HID_GD_Z)
+ hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
+ else if (usage->code == BTN_1)
+ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2);
+ else if (usage->code == BTN_2)
+ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1);
+ }
+
+ return 0;
+}
+
+static int apple_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ unsigned long quirks = id->driver_data;
+ struct apple_sc *asc;
+ unsigned int connect_mask = HID_CONNECT_DEFAULT;
+ int ret;
+
+ /* return something else or move to hid layer? device will reside
+ allocated */
+ if (id->bus == BUS_USB && (quirks & APPLE_IGNORE_MOUSE) &&
+ to_usb_interface(hdev->dev.parent)->cur_altsetting->
+ desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
+ return -ENODEV;
+
+ asc = kzalloc(sizeof(*asc), GFP_KERNEL);
+ if (asc == NULL) {
+ dev_err(&hdev->dev, "can't alloc apple descriptor\n");
+ return -ENOMEM;
+ }
+
+ asc->quirks = quirks;
+
+ hid_set_drvdata(hdev, asc);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ if (quirks & APPLE_HIDDEV)
+ connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+ if (quirks & APPLE_IGNORE_HIDINPUT)
+ connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+ ret = hid_hw_start(hdev, connect_mask);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ kfree(asc);
+ return ret;
+}
+
+static void apple_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+}
+
+static const struct hid_device_id apple_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
+ .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
+ .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
+ .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS},
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
+ .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
+ .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_IGNORE_MOUSE },
+
+ /* Apple wireless Mighty Mouse */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
+ .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, apple_devices);
+
+static struct hid_driver apple_driver = {
+ .name = "apple",
+ .id_table = apple_devices,
+ .report_fixup = apple_report_fixup,
+ .probe = apple_probe,
+ .remove = apple_remove,
+ .event = apple_event,
+ .input_mapping = apple_input_mapping,
+ .input_mapped = apple_input_mapped,
+};
+
+static int apple_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&apple_driver);
+ if (ret)
+ printk(KERN_ERR "can't register apple driver\n");
+
+ return ret;
+}
+
+static void apple_exit(void)
+{
+ hid_unregister_driver(&apple_driver);
+}
+
+module_init(apple_init);
+module_exit(apple_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(apple);
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c
new file mode 100644
index 00000000000..12c8a9ba6ed
--- /dev/null
+++ b/drivers/hid/hid-belkin.c
@@ -0,0 +1,105 @@
+/*
+ * HID driver for some belkin "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define BELKIN_HIDDEV 0x01
+#define BELKIN_WKBD 0x02
+
+#define belkin_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int belkin_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER ||
+ !(quirks & BELKIN_WKBD))
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x03a: belkin_map_key_clear(KEY_SOUND); break;
+ case 0x03b: belkin_map_key_clear(KEY_CAMERA); break;
+ case 0x03c: belkin_map_key_clear(KEY_DOCUMENTS); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ unsigned long quirks = id->driver_data;
+ int ret;
+
+ hid_set_drvdata(hdev, (void *)quirks);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
+ ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0));
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id belkin_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM),
+ .driver_data = BELKIN_HIDDEV },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD),
+ .driver_data = BELKIN_WKBD },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, belkin_devices);
+
+static struct hid_driver belkin_driver = {
+ .name = "belkin",
+ .id_table = belkin_devices,
+ .input_mapping = belkin_input_mapping,
+ .probe = belkin_probe,
+};
+
+static int belkin_init(void)
+{
+ return hid_register_driver(&belkin_driver);
+}
+
+static void belkin_exit(void)
+{
+ hid_unregister_driver(&belkin_driver);
+}
+
+module_init(belkin_init);
+module_exit(belkin_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(belkin);
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
new file mode 100644
index 00000000000..38517a117df
--- /dev/null
+++ b/drivers/hid/hid-bright.c
@@ -0,0 +1,71 @@
+/*
+ * HID driver for some bright "special" devices
+ *
+ * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Based on hid-dell driver
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ usbhid_set_leds(hdev);
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id bright_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, bright_devices);
+
+static struct hid_driver bright_driver = {
+ .name = "bright",
+ .id_table = bright_devices,
+ .probe = bright_probe,
+};
+
+static int bright_init(void)
+{
+ return hid_register_driver(&bright_driver);
+}
+
+static void bright_exit(void)
+{
+ hid_unregister_driver(&bright_driver);
+}
+
+module_init(bright_init);
+module_exit(bright_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(bright);
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c
new file mode 100644
index 00000000000..b833b9769ab
--- /dev/null
+++ b/drivers/hid/hid-cherry.c
@@ -0,0 +1,87 @@
+/*
+ * HID driver for some cherry "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
+ "descriptor\n");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
+#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x301: ch_map_key_clear(KEY_PROG1); break;
+ case 0x302: ch_map_key_clear(KEY_PROG2); break;
+ case 0x303: ch_map_key_clear(KEY_PROG3); break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static const struct hid_device_id ch_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ch_devices);
+
+static struct hid_driver ch_driver = {
+ .name = "cherry",
+ .id_table = ch_devices,
+ .report_fixup = ch_report_fixup,
+ .input_mapping = ch_input_mapping,
+};
+
+static int ch_init(void)
+{
+ return hid_register_driver(&ch_driver);
+}
+
+static void ch_exit(void)
+{
+ hid_unregister_driver(&ch_driver);
+}
+
+module_init(ch_init);
+module_exit(ch_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(cherry);
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
new file mode 100644
index 00000000000..a54d4096e0f
--- /dev/null
+++ b/drivers/hid/hid-chicony.c
@@ -0,0 +1,80 @@
+/*
+ * HID driver for some chicony "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+ return 0;
+
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0xff01: ch_map_key_clear(BTN_1); break;
+ case 0xff02: ch_map_key_clear(BTN_2); break;
+ case 0xff03: ch_map_key_clear(BTN_3); break;
+ case 0xff04: ch_map_key_clear(BTN_4); break;
+ case 0xff05: ch_map_key_clear(BTN_5); break;
+ case 0xff06: ch_map_key_clear(BTN_6); break;
+ case 0xff07: ch_map_key_clear(BTN_7); break;
+ case 0xff08: ch_map_key_clear(BTN_8); break;
+ case 0xff09: ch_map_key_clear(BTN_9); break;
+ case 0xff0a: ch_map_key_clear(BTN_A); break;
+ case 0xff0b: ch_map_key_clear(BTN_B); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static const struct hid_device_id ch_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ch_devices);
+
+static struct hid_driver ch_driver = {
+ .name = "chicony",
+ .id_table = ch_devices,
+ .input_mapping = ch_input_mapping,
+};
+
+static int ch_init(void)
+{
+ return hid_register_driver(&ch_driver);
+}
+
+static void ch_exit(void)
+{
+ hid_unregister_driver(&ch_driver);
+}
+
+module_init(ch_init);
+module_exit(ch_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(chicony);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 426ac5add58..721a36d9758 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -33,6 +33,8 @@
#include <linux/hid-debug.h>
#include <linux/hidraw.h>
+#include "hid-ids.h"
+
/*
* Version Information
*/
@@ -268,9 +270,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
static u32 item_udata(struct hid_item *item)
{
switch (item->size) {
- case 1: return item->data.u8;
- case 2: return item->data.u16;
- case 4: return item->data.u32;
+ case 1: return item->data.u8;
+ case 2: return item->data.u16;
+ case 4: return item->data.u32;
}
return 0;
}
@@ -278,9 +280,9 @@ static u32 item_udata(struct hid_item *item)
static s32 item_sdata(struct hid_item *item)
{
switch (item->size) {
- case 1: return item->data.s8;
- case 2: return item->data.s16;
- case 4: return item->data.s32;
+ case 1: return item->data.s8;
+ case 2: return item->data.s16;
+ case 4: return item->data.s32;
}
return 0;
}
@@ -292,87 +294,91 @@ static s32 item_sdata(struct hid_item *item)
static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
{
switch (item->tag) {
+ case HID_GLOBAL_ITEM_TAG_PUSH:
- case HID_GLOBAL_ITEM_TAG_PUSH:
-
- if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg_hid("global enviroment stack overflow\n");
- return -1;
- }
+ if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+ dbg_hid("global enviroment stack overflow\n");
+ return -1;
+ }
- memcpy(parser->global_stack + parser->global_stack_ptr++,
- &parser->global, sizeof(struct hid_global));
- return 0;
+ memcpy(parser->global_stack + parser->global_stack_ptr++,
+ &parser->global, sizeof(struct hid_global));
+ return 0;
- case HID_GLOBAL_ITEM_TAG_POP:
+ case HID_GLOBAL_ITEM_TAG_POP:
- if (!parser->global_stack_ptr) {
- dbg_hid("global enviroment stack underflow\n");
- return -1;
- }
-
- memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
- sizeof(struct hid_global));
- return 0;
+ if (!parser->global_stack_ptr) {
+ dbg_hid("global enviroment stack underflow\n");
+ return -1;
+ }
- case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
- parser->global.usage_page = item_udata(item);
- return 0;
+ memcpy(&parser->global, parser->global_stack +
+ --parser->global_stack_ptr, sizeof(struct hid_global));
+ return 0;
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
- parser->global.logical_minimum = item_sdata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+ parser->global.usage_page = item_udata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
- if (parser->global.logical_minimum < 0)
- parser->global.logical_maximum = item_sdata(item);
- else
- parser->global.logical_maximum = item_udata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+ parser->global.logical_minimum = item_sdata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
- parser->global.physical_minimum = item_sdata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+ if (parser->global.logical_minimum < 0)
+ parser->global.logical_maximum = item_sdata(item);
+ else
+ parser->global.logical_maximum = item_udata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
- if (parser->global.physical_minimum < 0)
- parser->global.physical_maximum = item_sdata(item);
- else
- parser->global.physical_maximum = item_udata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+ parser->global.physical_minimum = item_sdata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
- parser->global.unit_exponent = item_sdata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+ if (parser->global.physical_minimum < 0)
+ parser->global.physical_maximum = item_sdata(item);
+ else
+ parser->global.physical_maximum = item_udata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_UNIT:
- parser->global.unit = item_udata(item);
- return 0;
+ case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+ parser->global.unit_exponent = item_sdata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
- if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg_hid("invalid report_size %d\n", parser->global.report_size);
- return -1;
- }
- return 0;
+ case HID_GLOBAL_ITEM_TAG_UNIT:
+ parser->global.unit = item_udata(item);
+ return 0;
- case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
- if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg_hid("invalid report_count %d\n", parser->global.report_count);
- return -1;
- }
- return 0;
+ case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+ parser->global.report_size = item_udata(item);
+ if (parser->global.report_size > 32) {
+ dbg_hid("invalid report_size %d\n",
+ parser->global.report_size);
+ return -1;
+ }
+ return 0;
- case HID_GLOBAL_ITEM_TAG_REPORT_ID:
- if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg_hid("report_id 0 is invalid\n");
- return -1;
- }
- return 0;
+ case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+ parser->global.report_count = item_udata(item);
+ if (parser->global.report_count > HID_MAX_USAGES) {
+ dbg_hid("invalid report_count %d\n",
+ parser->global.report_count);
+ return -1;
+ }
+ return 0;
- default:
- dbg_hid("unknown global tag 0x%x\n", item->tag);
+ case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+ parser->global.report_id = item_udata(item);
+ if (parser->global.report_id == 0) {
+ dbg_hid("report_id 0 is invalid\n");
return -1;
+ }
+ return 0;
+
+ default:
+ dbg_hid("unknown global tag 0x%x\n", item->tag);
+ return -1;
}
}
@@ -393,77 +399,76 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
data = item_udata(item);
switch (item->tag) {
-
- case HID_LOCAL_ITEM_TAG_DELIMITER:
-
- if (data) {
- /*
- * We treat items before the first delimiter
- * as global to all usage sets (branch 0).
- * In the moment we process only these global
- * items and the first delimiter set.
- */
- if (parser->local.delimiter_depth != 0) {
- dbg_hid("nested delimiters\n");
- return -1;
- }
- parser->local.delimiter_depth++;
- parser->local.delimiter_branch++;
- } else {
- if (parser->local.delimiter_depth < 1) {
- dbg_hid("bogus close delimiter\n");
- return -1;
- }
- parser->local.delimiter_depth--;
+ case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+ if (data) {
+ /*
+ * We treat items before the first delimiter
+ * as global to all usage sets (branch 0).
+ * In the moment we process only these global
+ * items and the first delimiter set.
+ */
+ if (parser->local.delimiter_depth != 0) {
+ dbg_hid("nested delimiters\n");
+ return -1;
}
- return 1;
-
- case HID_LOCAL_ITEM_TAG_USAGE:
-
- if (parser->local.delimiter_branch > 1) {
- dbg_hid("alternative usage ignored\n");
- return 0;
+ parser->local.delimiter_depth++;
+ parser->local.delimiter_branch++;
+ } else {
+ if (parser->local.delimiter_depth < 1) {
+ dbg_hid("bogus close delimiter\n");
+ return -1;
}
+ parser->local.delimiter_depth--;
+ }
+ return 1;
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
+ case HID_LOCAL_ITEM_TAG_USAGE:
- return hid_add_usage(parser, data);
+ if (parser->local.delimiter_branch > 1) {
+ dbg_hid("alternative usage ignored\n");
+ return 0;
+ }
- case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
- if (parser->local.delimiter_branch > 1) {
- dbg_hid("alternative usage ignored\n");
- return 0;
- }
+ return hid_add_usage(parser, data);
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
- parser->local.usage_minimum = data;
+ if (parser->local.delimiter_branch > 1) {
+ dbg_hid("alternative usage ignored\n");
return 0;
+ }
- case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
- if (parser->local.delimiter_branch > 1) {
- dbg_hid("alternative usage ignored\n");
- return 0;
- }
+ parser->local.usage_minimum = data;
+ return 0;
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
- for (n = parser->local.usage_minimum; n <= data; n++)
- if (hid_add_usage(parser, n)) {
- dbg_hid("hid_add_usage failed\n");
- return -1;
- }
+ if (parser->local.delimiter_branch > 1) {
+ dbg_hid("alternative usage ignored\n");
return 0;
+ }
- default:
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
- dbg_hid("unknown local item tag 0x%x\n", item->tag);
- return 0;
+ for (n = parser->local.usage_minimum; n <= data; n++)
+ if (hid_add_usage(parser, n)) {
+ dbg_hid("hid_add_usage failed\n");
+ return -1;
+ }
+ return 0;
+
+ default:
+
+ dbg_hid("unknown local item tag 0x%x\n", item->tag);
+ return 0;
}
return 0;
}
@@ -480,24 +485,24 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
data = item_udata(item);
switch (item->tag) {
- case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
- ret = open_collection(parser, data & 0xff);
- break;
- case HID_MAIN_ITEM_TAG_END_COLLECTION:
- ret = close_collection(parser);
- break;
- case HID_MAIN_ITEM_TAG_INPUT:
- ret = hid_add_field(parser, HID_INPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_OUTPUT:
- ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_FEATURE:
- ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
- break;
- default:
- dbg_hid("unknown main item tag 0x%x\n", item->tag);
- ret = 0;
+ case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+ ret = open_collection(parser, data & 0xff);
+ break;
+ case HID_MAIN_ITEM_TAG_END_COLLECTION:
+ ret = close_collection(parser);
+ break;
+ case HID_MAIN_ITEM_TAG_INPUT:
+ ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_OUTPUT:
+ ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_FEATURE:
+ ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+ break;
+ default:
+ dbg_hid("unknown main item tag 0x%x\n", item->tag);
+ ret = 0;
}
memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
@@ -534,9 +539,10 @@ static void hid_free_report(struct hid_report *report)
* Free a device structure, all reports, and all fields.
*/
-void hid_free_device(struct hid_device *device)
+static void hid_device_release(struct device *dev)
{
- unsigned i,j;
+ struct hid_device *device = container_of(dev, struct hid_device, dev);
+ unsigned i, j;
for (i = 0; i < HID_REPORT_TYPES; i++) {
struct hid_report_enum *report_enum = device->report_enum + i;
@@ -552,7 +558,6 @@ void hid_free_device(struct hid_device *device)
kfree(device->collection);
kfree(device);
}
-EXPORT_SYMBOL_GPL(hid_free_device);
/*
* Fetch a report description item from the data stream. We support long
@@ -593,47 +598,52 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
item->size = b & 3;
switch (item->size) {
+ case 0:
+ return start;
- case 0:
- return start;
-
- case 1:
- if ((end - start) < 1)
- return NULL;
- item->data.u8 = *start++;
- return start;
+ case 1:
+ if ((end - start) < 1)
+ return NULL;
+ item->data.u8 = *start++;
+ return start;
- case 2:
- if ((end - start) < 2)
- return NULL;
- item->data.u16 = get_unaligned_le16(start);
- start = (__u8 *)((__le16 *)start + 1);
- return start;
+ case 2:
+ if ((end - start) < 2)
+ return NULL;
+ item->data.u16 = get_unaligned_le16(start);
+ start = (__u8 *)((__le16 *)start + 1);
+ return start;
- case 3:
- item->size++;
- if ((end - start) < 4)
- return NULL;
- item->data.u32 = get_unaligned_le32(start);
- start = (__u8 *)((__le32 *)start + 1);
- return start;
+ case 3:
+ item->size++;
+ if ((end - start) < 4)
+ return NULL;
+ item->data.u32 = get_unaligned_le32(start);
+ start = (__u8 *)((__le32 *)start + 1);
+ return start;
}
return NULL;
}
-/*
+/**
+ * hid_parse_report - parse device report
+ *
+ * @device: hid device
+ * @start: report start
+ * @size: report size
+ *
* Parse a report description into a hid_device structure. Reports are
* enumerated, fields are attached to these reports.
+ * 0 returned on success, otherwise nonzero error value.
*/
-
-struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+int hid_parse_report(struct hid_device *device, __u8 *start,
+ unsigned size)
{
- struct hid_device *device;
struct hid_parser *parser;
struct hid_item item;
__u8 *end;
- unsigned i;
+ int ret;
static int (*dispatch_type[])(struct hid_parser *parser,
struct hid_item *item) = {
hid_parser_main,
@@ -642,76 +652,57 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
hid_parser_reserved
};
- if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
- return NULL;
+ if (device->driver->report_fixup)
+ device->driver->report_fixup(device, start, size);
- if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
- HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
- kfree(device);
- return NULL;
- }
- device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
- for (i = 0; i < HID_REPORT_TYPES; i++)
- INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
- if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
- kfree(device->collection);
- kfree(device);
- return NULL;
- }
+ device->rdesc = kmalloc(size, GFP_KERNEL);
+ if (device->rdesc == NULL)
+ return -ENOMEM;
memcpy(device->rdesc, start, size);
device->rsize = size;
- if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
- kfree(device->rdesc);
- kfree(device->collection);
- kfree(device);
- return NULL;
+ parser = vmalloc(sizeof(struct hid_parser));
+ if (!parser) {
+ ret = -ENOMEM;
+ goto err;
}
+
memset(parser, 0, sizeof(struct hid_parser));
parser->device = device;
end = start + size;
+ ret = -EINVAL;
while ((start = fetch_item(start, end, &item)) != NULL) {
if (item.format != HID_ITEM_FORMAT_SHORT) {
dbg_hid("unexpected long global item\n");
- hid_free_device(device);
- vfree(parser);
- return NULL;
+ goto err;
}
if (dispatch_type[item.type](parser, &item)) {
dbg_hid("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
- hid_free_device(device);
- vfree(parser);
- return NULL;
+ goto err;
}
if (start == end) {
if (parser->collection_stack_ptr) {
dbg_hid("unbalanced collection at end of report description\n");
- hid_free_device(device);
- vfree(parser);
- return NULL;
+ goto err;
}
if (parser->local.delimiter_depth) {
dbg_hid("unbalanced delimiter at end of report description\n");
- hid_free_device(device);
- vfree(parser);
- return NULL;
+ goto err;
}
vfree(parser);
- return device;
+ return 0;
}
}
dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
- hid_free_device(device);
+err:
vfree(parser);
- return NULL;
+ return ret;
}
EXPORT_SYMBOL_GPL(hid_parse_report);
@@ -724,9 +715,9 @@ EXPORT_SYMBOL_GPL(hid_parse_report);
static s32 snto32(__u32 value, unsigned n)
{
switch (n) {
- case 8: return ((__s8)value);
- case 16: return ((__s16)value);
- case 32: return ((__s32)value);
+ case 8: return ((__s8)value);
+ case 16: return ((__s16)value);
+ case 32: return ((__s32)value);
}
return value & (1 << (n - 1)) ? value | (-1 << n) : value;
}
@@ -815,9 +806,73 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n)
return -1;
}
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
+/**
+ * hid_match_report - check if driver's raw_event should be called
+ *
+ * @hid: hid device
+ * @report_type: type to match against
+ *
+ * compare hid->driver->report_table->report_type to report->type
+ */
+static int hid_match_report(struct hid_device *hid, struct hid_report *report)
+{
+ const struct hid_report_id *id = hid->driver->report_table;
+
+ if (!id) /* NULL means all */
+ return 1;
+
+ for (; id->report_type != HID_TERMINATOR; id++)
+ if (id->report_type == HID_ANY_ID ||
+ id->report_type == report->type)
+ return 1;
+ return 0;
+}
+
+/**
+ * hid_match_usage - check if driver's event should be called
+ *
+ * @hid: hid device
+ * @usage: usage to match against
+ *
+ * compare hid->driver->usage_table->usage_{type,code} to
+ * usage->usage_{type,code}
+ */
+static int hid_match_usage(struct hid_device *hid, struct hid_usage *usage)
{
+ const struct hid_usage_id *id = hid->driver->usage_table;
+
+ if (!id) /* NULL means all */
+ return 1;
+
+ for (; id->usage_type != HID_ANY_ID - 1; id++)
+ if ((id->usage_hid == HID_ANY_ID ||
+ id->usage_hid == usage->hid) &&
+ (id->usage_type == HID_ANY_ID ||
+ id->usage_type == usage->type) &&
+ (id->usage_code == HID_ANY_ID ||
+ id->usage_code == usage->code))
+ return 1;
+ return 0;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field,
+ struct hid_usage *usage, __s32 value, int interrupt)
+{
+ struct hid_driver *hdrv = hid->driver;
+ int ret;
+
hid_dump_input(usage, value);
+
+ if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
+ ret = hdrv->event(hid, field, usage, value);
+ if (ret != 0) {
+ if (ret < 0)
+ dbg_hid("%s's event failed with %d\n",
+ hdrv->name, ret);
+ return;
+ }
+ }
+
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
@@ -946,44 +1001,47 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
}
EXPORT_SYMBOL_GPL(hid_set_field);
-int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
+ const u8 *data)
{
- struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
- int n, rsize, i;
+ unsigned int n = 0; /* Normally report number is 0 */
- if (!hid)
- return -ENODEV;
+ /* Device uses numbered reports, data[0] is report number */
+ if (report_enum->numbered)
+ n = *data;
- if (!size) {
- dbg_hid("empty report\n");
- return -1;
- }
+ report = report_enum->report_id_hash[n];
+ if (report == NULL)
+ dbg_hid("undefined report_id %u received\n", n);
- dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+ return report;
+}
- n = 0; /* Normally report number is 0 */
- if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
- n = *data++;
- size--;
- }
+void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+ int interrupt)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+ unsigned int a;
+ int rsize, csize = size;
+ u8 *cdata = data;
- /* dump the report */
- dbg_hid("report %d (size %u) = ", n, size);
- for (i = 0; i < size; i++)
- dbg_hid_line(" %02x", data[i]);
- dbg_hid_line("\n");
+ report = hid_get_report(report_enum, data);
+ if (!report)
+ return;
- if (!(report = report_enum->report_id_hash[n])) {
- dbg_hid("undefined report_id %d received\n", n);
- return -1;
+ if (report_enum->numbered) {
+ cdata++;
+ csize--;
}
rsize = ((report->size - 1) >> 3) + 1;
- if (size < rsize) {
- dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
- memset(data + size, 0, rsize - size);
+ if (csize < rsize) {
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+ csize, rsize);
+ memset(cdata + csize, 0, rsize - csize);
}
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
@@ -996,24 +1054,663 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
hidraw_report_event(hid, data, size);
}
- for (n = 0; n < report->maxfield; n++)
- hid_input_field(hid, report->field[n], data, interrupt);
+ for (a = 0; a < report->maxfield; a++)
+ hid_input_field(hid, report->field[a], cdata, interrupt);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_report_event(hid, report);
+}
+EXPORT_SYMBOL_GPL(hid_report_raw_event);
+
+/**
+ * hid_input_report - report data from lower layer (usb, bt...)
+ *
+ * @hid: hid device
+ * @type: HID report type (HID_*_REPORT)
+ * @data: report contents
+ * @size: size of data parameter
+ * @interrupt: called from atomic?
+ *
+ * This is data entry for lower layers.
+ */
+int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_driver *hdrv = hid->driver;
+ struct hid_report *report;
+ unsigned int i;
+ int ret;
+
+ if (!hid || !hid->driver)
+ return -ENODEV;
+
+ if (!size) {
+ dbg_hid("empty report\n");
+ return -1;
+ }
+
+ dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+
+ report = hid_get_report(report_enum, data);
+ if (!report)
+ return -1;
+
+ /* dump the report */
+ dbg_hid("report %d (size %u) = ", report->id, size);
+ for (i = 0; i < size; i++)
+ dbg_hid_line(" %02x", data[i]);
+ dbg_hid_line("\n");
+
+ if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
+ ret = hdrv->raw_event(hid, report, data, size);
+ if (ret != 0)
+ return ret < 0 ? ret : 0;
+ }
+
+ hid_report_raw_event(hid, type, data, size, interrupt);
return 0;
}
EXPORT_SYMBOL_GPL(hid_input_report);
+static bool hid_match_one_id(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ return id->bus == hdev->bus &&
+ (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
+ (id->product == HID_ANY_ID || id->product == hdev->product);
+}
+
+static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ for (; id->bus; id++)
+ if (hid_match_one_id(hdev, id))
+ return id;
+
+ return NULL;
+}
+
+static const struct hid_device_id hid_hiddev_list[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) },
+ { }
+};
+
+static bool hid_hiddev(struct hid_device *hdev)
+{
+ return !!hid_match_id(hdev, hid_hiddev_list);
+}
+
+int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
+{
+ static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
+ "Joystick", "Gamepad", "Keyboard", "Keypad",
+ "Multi-Axis Controller"
+ };
+ const char *type, *bus;
+ char buf[64];
+ unsigned int i;
+ int len;
+
+ if (hdev->bus != BUS_USB)
+ connect_mask &= ~HID_CONNECT_HIDDEV;
+ if (hid_hiddev(hdev))
+ connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+
+ if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
+ connect_mask & HID_CONNECT_HIDINPUT_FORCE))
+ hdev->claimed |= HID_CLAIMED_INPUT;
+ if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
+ !hdev->hiddev_connect(hdev,
+ connect_mask & HID_CONNECT_HIDDEV_FORCE))
+ hdev->claimed |= HID_CLAIMED_HIDDEV;
+ if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))
+ hdev->claimed |= HID_CLAIMED_HIDRAW;
+
+ if (!hdev->claimed) {
+ dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
+ "hidraw\n");
+ return -ENODEV;
+ }
+
+ if ((hdev->claimed & HID_CLAIMED_INPUT) &&
+ (connect_mask & HID_CONNECT_FF) && hdev->ff_init)
+ hdev->ff_init(hdev);
+
+ len = 0;
+ if (hdev->claimed & HID_CLAIMED_INPUT)
+ len += sprintf(buf + len, "input");
+ if (hdev->claimed & HID_CLAIMED_HIDDEV)
+ len += sprintf(buf + len, "%shiddev%d", len ? "," : "",
+ hdev->minor);
+ if (hdev->claimed & HID_CLAIMED_HIDRAW)
+ len += sprintf(buf + len, "%shidraw%d", len ? "," : "",
+ ((struct hidraw *)hdev->hidraw)->minor);
+
+ type = "Device";
+ for (i = 0; i < hdev->maxcollection; i++) {
+ struct hid_collection *col = &hdev->collection[i];
+ if (col->type == HID_COLLECTION_APPLICATION &&
+ (col->usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+ (col->usage & 0xffff) < ARRAY_SIZE(types)) {
+ type = types[col->usage & 0xffff];
+ break;
+ }
+ }
+
+ switch (hdev->bus) {
+ case BUS_USB:
+ bus = "USB";
+ break;
+ case BUS_BLUETOOTH:
+ bus = "BLUETOOTH";
+ break;
+ default:
+ bus = "<UNKNOWN>";
+ }
+
+ dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
+ buf, bus, hdev->version >> 8, hdev->version & 0xff,
+ type, hdev->name, hdev->phys);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_connect);
+
+static const struct hid_device_id hid_blacklist[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+ { }
+};
+
+static int hid_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+ if (!hid_match_id(hdev, hdrv->id_table))
+ return 0;
+
+ /* generic wants all non-blacklisted */
+ if (!strncmp(hdrv->name, "generic-", 8))
+ return !hid_match_id(hdev, hid_blacklist);
+
+ return 1;
+}
+
+static int hid_device_probe(struct device *dev)
+{
+ struct hid_driver *hdrv = container_of(dev->driver,
+ struct hid_driver, driver);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ const struct hid_device_id *id;
+ int ret = 0;
+
+ if (!hdev->driver) {
+ id = hid_match_id(hdev, hdrv->id_table);
+ if (id == NULL)
+ return -ENODEV;
+
+ hdev->driver = hdrv;
+ if (hdrv->probe) {
+ ret = hdrv->probe(hdev, id);
+ } else { /* default probe */
+ ret = hid_parse(hdev);
+ if (!ret)
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ }
+ if (ret)
+ hdev->driver = NULL;
+ }
+ return ret;
+}
+
+static int hid_device_remove(struct device *dev)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_driver *hdrv = hdev->driver;
+
+ if (hdrv) {
+ if (hdrv->remove)
+ hdrv->remove(hdev);
+ else /* default remove */
+ hid_hw_stop(hdev);
+ hdev->driver = NULL;
+ }
+
+ return 0;
+}
+
+static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+ if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X",
+ hdev->bus, hdev->vendor, hdev->product))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "HID_NAME=%s", hdev->name))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "HID_PHYS=%s", hdev->phys))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X",
+ hdev->bus, hdev->vendor, hdev->product))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static struct bus_type hid_bus_type = {
+ .name = "hid",
+ .match = hid_bus_match,
+ .probe = hid_device_probe,
+ .remove = hid_device_remove,
+ .uevent = hid_uevent,
+};
+
+static const struct hid_device_id hid_ignore_list[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
+ { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+ { }
+};
+
+static bool hid_ignore(struct hid_device *hdev)
+{
+ switch (hdev->vendor) {
+ case USB_VENDOR_ID_CODEMERCS:
+ /* ignore all Code Mercenaries IOWarrior devices */
+ if (hdev->product >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&
+ hdev->product <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
+ return true;
+ break;
+ case USB_VENDOR_ID_LOGITECH:
+ if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST &&
+ hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST)
+ return true;
+ break;
+ }
+
+ return !!hid_match_id(hdev, hid_ignore_list);
+}
+
+int hid_add_device(struct hid_device *hdev)
+{
+ static atomic_t id = ATOMIC_INIT(0);
+ int ret;
+
+ if (WARN_ON(hdev->status & HID_STAT_ADDED))
+ return -EBUSY;
+
+ /* we need to kill them here, otherwise they will stay allocated to
+ * wait for coming driver */
+ if (hid_ignore(hdev))
+ return -ENODEV;
+
+ /* XXX hack, any other cleaner solution < 20 bus_id bytes? */
+ sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
+ hdev->vendor, hdev->product, atomic_inc_return(&id));
+
+ ret = device_add(&hdev->dev);
+ if (!ret)
+ hdev->status |= HID_STAT_ADDED;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hid_add_device);
+
+/**
+ * hid_allocate_device - allocate new hid device descriptor
+ *
+ * Allocate and initialize hid device, so that hid_destroy_device might be
+ * used to free it.
+ *
+ * New hid_device pointer is returned on success, otherwise ERR_PTR encoded
+ * error value.
+ */
+struct hid_device *hid_allocate_device(void)
+{
+ struct hid_device *hdev;
+ unsigned int i;
+ int ret = -ENOMEM;
+
+ hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
+ if (hdev == NULL)
+ return ERR_PTR(ret);
+
+ device_initialize(&hdev->dev);
+ hdev->dev.release = hid_device_release;
+ hdev->dev.bus = &hid_bus_type;
+
+ hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
+ sizeof(struct hid_collection), GFP_KERNEL);
+ if (hdev->collection == NULL)
+ goto err;
+ hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
+ for (i = 0; i < HID_REPORT_TYPES; i++)
+ INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
+
+ return hdev;
+err:
+ put_device(&hdev->dev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(hid_allocate_device);
+
+static void hid_remove_device(struct hid_device *hdev)
+{
+ if (hdev->status & HID_STAT_ADDED) {
+ device_del(&hdev->dev);
+ hdev->status &= ~HID_STAT_ADDED;
+ }
+}
+
+/**
+ * hid_destroy_device - free previously allocated device
+ *
+ * @hdev: hid device
+ *
+ * If you allocate hid_device through hid_allocate_device, you should ever
+ * free by this function.
+ */
+void hid_destroy_device(struct hid_device *hdev)
+{
+ hid_remove_device(hdev);
+ put_device(&hdev->dev);
+}
+EXPORT_SYMBOL_GPL(hid_destroy_device);
+
+int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
+ const char *mod_name)
+{
+ hdrv->driver.name = hdrv->name;
+ hdrv->driver.bus = &hid_bus_type;
+ hdrv->driver.owner = owner;
+ hdrv->driver.mod_name = mod_name;
+
+ return driver_register(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__hid_register_driver);
+
+void hid_unregister_driver(struct hid_driver *hdrv)
+{
+ driver_unregister(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(hid_unregister_driver);
+
+#ifdef CONFIG_HID_COMPAT
+static void hid_compat_load(struct work_struct *ws)
+{
+ request_module("hid-dummy");
+}
+static DECLARE_WORK(hid_compat_work, hid_compat_load);
+static struct workqueue_struct *hid_compat_wq;
+#endif
+
static int __init hid_init(void)
{
- return hidraw_init();
+ int ret;
+
+ ret = bus_register(&hid_bus_type);
+ if (ret) {
+ printk(KERN_ERR "HID: can't register hid bus\n");
+ goto err;
+ }
+
+ ret = hidraw_init();
+ if (ret)
+ goto err_bus;
+
+#ifdef CONFIG_HID_COMPAT
+ hid_compat_wq = create_workqueue("hid_compat");
+ if (!hid_compat_wq) {
+ hidraw_exit();
+ goto err;
+ }
+ queue_work(hid_compat_wq, &hid_compat_work);
+#endif
+
+ return 0;
+err_bus:
+ bus_unregister(&hid_bus_type);
+err:
+ return ret;
}
static void __exit hid_exit(void)
{
+#ifdef CONFIG_HID_COMPAT
+ destroy_workqueue(hid_compat_wq);
+#endif
hidraw_exit();
+ bus_unregister(&hid_bus_type);
}
module_init(hid_init);
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
new file mode 100644
index 00000000000..5d69d27b935
--- /dev/null
+++ b/drivers/hid/hid-cypress.c
@@ -0,0 +1,158 @@
+/*
+ * HID driver for some cypress "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define CP_RDESC_SWAPPED_MIN_MAX 0x01
+#define CP_2WHEEL_MOUSE_HACK 0x02
+#define CP_2WHEEL_MOUSE_HACK_ON 0x04
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ unsigned int i;
+
+ if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
+ return;
+
+ for (i = 0; i < rsize - 4; i++)
+ if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
+ __u8 tmp;
+
+ rdesc[i] = 0x19;
+ rdesc[i + 2] = 0x29;
+ tmp = rdesc[i + 3];
+ rdesc[i + 3] = rdesc[i + 1];
+ rdesc[i + 1] = tmp;
+ }
+}
+
+static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if (!(quirks & CP_2WHEEL_MOUSE_HACK))
+ return 0;
+
+ if (usage->type == EV_REL && usage->code == REL_WHEEL)
+ set_bit(REL_HWHEEL, *bit);
+ if (usage->hid == 0x00090005)
+ return -1;
+
+ return 0;
+}
+
+static int cp_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK))
+ return 0;
+
+ if (usage->hid == 0x00090005) {
+ if (value)
+ quirks |= CP_2WHEEL_MOUSE_HACK_ON;
+ else
+ quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
+ hid_set_drvdata(hdev, (void *)quirks);
+ return 1;
+ }
+
+ if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
+ struct input_dev *input = field->hidinput->input;
+
+ input_event(input, usage->type, REL_HWHEEL, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ unsigned long quirks = id->driver_data;
+ int ret;
+
+ hid_set_drvdata(hdev, (void *)quirks);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id cp_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1),
+ .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2),
+ .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
+ .driver_data = CP_2WHEEL_MOUSE_HACK },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, cp_devices);
+
+static struct hid_driver cp_driver = {
+ .name = "cypress",
+ .id_table = cp_devices,
+ .report_fixup = cp_report_fixup,
+ .input_mapped = cp_input_mapped,
+ .event = cp_event,
+ .probe = cp_probe,
+};
+
+static int cp_init(void)
+{
+ return hid_register_driver(&cp_driver);
+}
+
+static void cp_exit(void)
+{
+ hid_unregister_driver(&cp_driver);
+}
+
+module_init(cp_init);
+module_exit(cp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(cypress);
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
new file mode 100644
index 00000000000..1a0d0dfc62f
--- /dev/null
+++ b/drivers/hid/hid-dell.c
@@ -0,0 +1,75 @@
+/*
+ * HID driver for some dell "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ usbhid_set_leds(hdev);
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id dell_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, dell_devices);
+
+static struct hid_driver dell_driver = {
+ .name = "dell",
+ .id_table = dell_devices,
+ .probe = dell_probe,
+};
+
+static int dell_init(void)
+{
+ return hid_register_driver(&dell_driver);
+}
+
+static void dell_exit(void)
+{
+ hid_unregister_driver(&dell_driver);
+}
+
+module_init(dell_init);
+module_exit(dell_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(dell);
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
new file mode 100644
index 00000000000..e148f86fb58
--- /dev/null
+++ b/drivers/hid/hid-dummy.c
@@ -0,0 +1,72 @@
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/hid.h>
+
+static int __init hid_dummy_init(void)
+{
+#ifdef CONFIG_HID_A4TECH_MODULE
+ HID_COMPAT_CALL_DRIVER(a4tech);
+#endif
+#ifdef CONFIG_HID_APPLE_MODULE
+ HID_COMPAT_CALL_DRIVER(apple);
+#endif
+#ifdef CONFIG_HID_BELKIN_MODULE
+ HID_COMPAT_CALL_DRIVER(belkin);
+#endif
+#ifdef CONFIG_HID_BRIGHT_MODULE
+ HID_COMPAT_CALL_DRIVER(bright);
+#endif
+#ifdef CONFIG_HID_CHERRY_MODULE
+ HID_COMPAT_CALL_DRIVER(cherry);
+#endif
+#ifdef CONFIG_HID_CHICONY_MODULE
+ HID_COMPAT_CALL_DRIVER(chicony);
+#endif
+#ifdef CONFIG_HID_CYPRESS_MODULE
+ HID_COMPAT_CALL_DRIVER(cypress);
+#endif
+#ifdef CONFIG_HID_DELL_MODULE
+ HID_COMPAT_CALL_DRIVER(dell);
+#endif
+#ifdef CONFIG_HID_EZKEY_MODULE
+ HID_COMPAT_CALL_DRIVER(ezkey);
+#endif
+#ifdef CONFIG_HID_GYRATION_MODULE
+ HID_COMPAT_CALL_DRIVER(gyration);
+#endif
+#ifdef CONFIG_HID_LOGITECH_MODULE
+ HID_COMPAT_CALL_DRIVER(logitech);
+#endif
+#ifdef CONFIG_HID_MICROSOFT_MODULE
+ HID_COMPAT_CALL_DRIVER(microsoft);
+#endif
+#ifdef CONFIG_HID_MONTEREY_MODULE
+ HID_COMPAT_CALL_DRIVER(monterey);
+#endif
+#ifdef CONFIG_HID_PANTHERLORD_MODULE
+ HID_COMPAT_CALL_DRIVER(pantherlord);
+#endif
+#ifdef CONFIG_HID_PETALYNX_MODULE
+ HID_COMPAT_CALL_DRIVER(petalynx);
+#endif
+#ifdef CONFIG_HID_SAMSUNG_MODULE
+ HID_COMPAT_CALL_DRIVER(samsung);
+#endif
+#ifdef CONFIG_HID_SONY_MODULE
+ HID_COMPAT_CALL_DRIVER(sony);
+#endif
+#ifdef CONFIG_HID_SUNPLUS_MODULE
+ HID_COMPAT_CALL_DRIVER(sunplus);
+#endif
+#ifdef CONFIG_THRUSTMASTER_FF_MODULE
+ HID_COMPAT_CALL_DRIVER(thrustmaster);
+#endif
+#ifdef CONFIG_ZEROPLUS_FF_MODULE
+ HID_COMPAT_CALL_DRIVER(zeroplus);
+#endif
+
+ return -EIO;
+}
+module_init(hid_dummy_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c
new file mode 100644
index 00000000000..deb42f931b7
--- /dev/null
+++ b/drivers/hid/hid-ezkey.c
@@ -0,0 +1,95 @@
+/*
+ * HID driver for some ezkey "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ez_map_rel(c) hid_map_usage(hi, usage, bit, max, EV_REL, (c))
+#define ez_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c))
+
+static int ez_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x230: ez_map_key(BTN_MOUSE); break;
+ case 0x231: ez_map_rel(REL_WHEEL); break;
+ /*
+ * this keyboard has a scrollwheel implemented in
+ * totally broken way. We map this usage temporarily
+ * to HWHEEL and handle it in the event quirk handler
+ */
+ case 0x232: ez_map_rel(REL_HWHEEL); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int ez_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ /* handle the temporary quirky mapping to HWHEEL */
+ if (usage->type == EV_REL && usage->code == REL_HWHEEL) {
+ struct input_dev *input = field->hidinput->input;
+ input_event(input, usage->type, REL_WHEEL, -value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id ez_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ez_devices);
+
+static struct hid_driver ez_driver = {
+ .name = "ezkey",
+ .id_table = ez_devices,
+ .input_mapping = ez_input_mapping,
+ .event = ez_event,
+};
+
+static int ez_init(void)
+{
+ return hid_register_driver(&ez_driver);
+}
+
+static void ez_exit(void)
+{
+ hid_unregister_driver(&ez_driver);
+}
+
+module_init(ez_init);
+module_exit(ez_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(ezkey);
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
new file mode 100644
index 00000000000..ac5120f542c
--- /dev/null
+++ b/drivers/hid/hid-gyration.c
@@ -0,0 +1,96 @@
+/*
+ * HID driver for some gyration "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define gy_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+ return 0;
+
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ /* Reported on Gyration MCE Remote */
+ case 0x00d: gy_map_key_clear(KEY_HOME); break;
+ case 0x024: gy_map_key_clear(KEY_DVD); break;
+ case 0x025: gy_map_key_clear(KEY_PVR); break;
+ case 0x046: gy_map_key_clear(KEY_MEDIA); break;
+ case 0x047: gy_map_key_clear(KEY_MP3); break;
+ case 0x049: gy_map_key_clear(KEY_CAMERA); break;
+ case 0x04a: gy_map_key_clear(KEY_VIDEO); break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int gyration_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct input_dev *input = field->hidinput->input;
+
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+ (usage->hid & 0xff) == 0x82) {
+ input_event(input, usage->type, usage->code, 1);
+ input_sync(input);
+ input_event(input, usage->type, usage->code, 0);
+ input_sync(input);
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id gyration_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, gyration_devices);
+
+static struct hid_driver gyration_driver = {
+ .name = "gyration",
+ .id_table = gyration_devices,
+ .input_mapping = gyration_input_mapping,
+ .event = gyration_event,
+};
+
+static int gyration_init(void)
+{
+ return hid_register_driver(&gyration_driver);
+}
+
+static void gyration_exit(void)
+{
+ hid_unregister_driver(&gyration_driver);
+}
+
+module_init(gyration_init);
+module_exit(gyration_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(gyration);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
new file mode 100644
index 00000000000..d9a1ba920c2
--- /dev/null
+++ b/drivers/hid/hid-ids.h
@@ -0,0 +1,406 @@
+/*
+ * USB HID quirks support for Linux
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ */
+
+/*
+ * 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 HID_IDS_H_FILE
+#define HID_IDS_H_FILE
+
+#define USB_VENDOR_ID_A4TECH 0x09da
+#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
+#define USB_DEVICE_ID_A4TECH_X5_005D 0x000a
+
+#define USB_VENDOR_ID_AASHIMA 0x06d6
+#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
+
+#define USB_VENDOR_ID_ACECAD 0x0460
+#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004
+#define USB_DEVICE_ID_ACECAD_302 0x0008
+
+#define USB_VENDOR_ID_ADS_TECH 0x06e1
+#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
+
+#define USB_VENDOR_ID_AFATECH 0x15a4
+#define USB_DEVICE_ID_AFATECH_AF9016 0x9016
+
+#define USB_VENDOR_ID_AIPTEK 0x08ca
+#define USB_DEVICE_ID_AIPTEK_01 0x0001
+#define USB_DEVICE_ID_AIPTEK_10 0x0010
+#define USB_DEVICE_ID_AIPTEK_20 0x0020
+#define USB_DEVICE_ID_AIPTEK_21 0x0021
+#define USB_DEVICE_ID_AIPTEK_22 0x0022
+#define USB_DEVICE_ID_AIPTEK_23 0x0023
+#define USB_DEVICE_ID_AIPTEK_24 0x0024
+
+#define USB_VENDOR_ID_AIRCABLE 0x16CA
+#define USB_DEVICE_ID_AIRCABLE1 0x1502
+
+#define USB_VENDOR_ID_ALCOR 0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720
+
+#define USB_VENDOR_ID_ALPS 0x0433
+#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101
+
+#define USB_VENDOR_ID_APPLE 0x05ac
+#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
+#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220
+#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221
+#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
+#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
+#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
+
+#define USB_VENDOR_ID_ASUS 0x0b05
+#define USB_DEVICE_ID_ASUS_LCM 0x1726
+
+#define USB_VENDOR_ID_ATEN 0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+#define USB_DEVICE_ID_ATEN_CS124U 0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
+
+#define USB_VENDOR_ID_AVERMEDIA 0x07ca
+#define USB_DEVICE_ID_AVER_FM_MR800 0xb800
+
+#define USB_VENDOR_ID_BELKIN 0x050d
+#define USB_DEVICE_ID_FLIP_KVM 0x3201
+
+#define USB_VENDOR_ID_BRIGHT 0x1241
+#define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503
+
+#define USB_VENDOR_ID_BERKSHIRE 0x0c98
+#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
+
+#define USB_VENDOR_ID_CHERRY 0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
+
+#define USB_VENDOR_ID_CHIC 0x05fe
+#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014
+
+#define USB_VENDOR_ID_CHICONY 0x04f2
+#define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
+
+#define USB_VENDOR_ID_CIDC 0x1677
+
+#define USB_VENDOR_ID_CMEDIA 0x0d8c
+#define USB_DEVICE_ID_CM109 0x000e
+
+#define USB_VENDOR_ID_CODEMERCS 0x07c0
+#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff
+
+#define USB_VENDOR_ID_CYGNAL 0x10c4
+#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
+
+#define USB_VENDOR_ID_CYPRESS 0x04b4
+#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
+#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
+#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
+#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
+
+#define USB_VENDOR_ID_DELL 0x413c
+#define USB_DEVICE_ID_DELL_W7658 0x2005
+#define USB_DEVICE_ID_DELL_SK8115 0x2105
+
+#define USB_VENDOR_ID_DELORME 0x1163
+#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
+
+#define USB_VENDOR_ID_DMI 0x0c0b
+#define USB_DEVICE_ID_DMI_ENC 0x5fab
+
+#define USB_VENDOR_ID_ELO 0x04E7
+#define USB_DEVICE_ID_ELO_TS2700 0x0020
+
+#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+
+#define USB_VENDOR_ID_EZKEY 0x0518
+#define USB_DEVICE_ID_BTC_8193 0x0002
+
+#define USB_VENDOR_ID_GAMERON 0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+
+#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
+
+#define USB_VENDOR_ID_GLAB 0x06c2
+#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
+#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
+#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051
+#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058
+
+#define USB_VENDOR_ID_GOTOP 0x08f2
+#define USB_DEVICE_ID_SUPER_Q2 0x007f
+#define USB_DEVICE_ID_GOGOPEN 0x00ce
+#define USB_DEVICE_ID_PENPOWER 0x00f4
+
+#define USB_VENDOR_ID_GREENASIA 0x0e8f
+
+#define USB_VENDOR_ID_GRETAGMACBETH 0x0971
+#define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005
+
+#define USB_VENDOR_ID_GRIFFIN 0x077d
+#define USB_DEVICE_ID_POWERMATE 0x0410
+#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
+
+#define USB_VENDOR_ID_GTCO 0x078c
+#define USB_DEVICE_ID_GTCO_90 0x0090
+#define USB_DEVICE_ID_GTCO_100 0x0100
+#define USB_DEVICE_ID_GTCO_101 0x0101
+#define USB_DEVICE_ID_GTCO_103 0x0103
+#define USB_DEVICE_ID_GTCO_104 0x0104
+#define USB_DEVICE_ID_GTCO_105 0x0105
+#define USB_DEVICE_ID_GTCO_106 0x0106
+#define USB_DEVICE_ID_GTCO_107 0x0107
+#define USB_DEVICE_ID_GTCO_108 0x0108
+#define USB_DEVICE_ID_GTCO_200 0x0200
+#define USB_DEVICE_ID_GTCO_201 0x0201
+#define USB_DEVICE_ID_GTCO_202 0x0202
+#define USB_DEVICE_ID_GTCO_203 0x0203
+#define USB_DEVICE_ID_GTCO_204 0x0204
+#define USB_DEVICE_ID_GTCO_205 0x0205
+#define USB_DEVICE_ID_GTCO_206 0x0206
+#define USB_DEVICE_ID_GTCO_207 0x0207
+#define USB_DEVICE_ID_GTCO_300 0x0300
+#define USB_DEVICE_ID_GTCO_301 0x0301
+#define USB_DEVICE_ID_GTCO_302 0x0302
+#define USB_DEVICE_ID_GTCO_303 0x0303
+#define USB_DEVICE_ID_GTCO_304 0x0304
+#define USB_DEVICE_ID_GTCO_305 0x0305
+#define USB_DEVICE_ID_GTCO_306 0x0306
+#define USB_DEVICE_ID_GTCO_307 0x0307
+#define USB_DEVICE_ID_GTCO_308 0x0308
+#define USB_DEVICE_ID_GTCO_309 0x0309
+#define USB_DEVICE_ID_GTCO_400 0x0400
+#define USB_DEVICE_ID_GTCO_401 0x0401
+#define USB_DEVICE_ID_GTCO_402 0x0402
+#define USB_DEVICE_ID_GTCO_403 0x0403
+#define USB_DEVICE_ID_GTCO_404 0x0404
+#define USB_DEVICE_ID_GTCO_405 0x0405
+#define USB_DEVICE_ID_GTCO_500 0x0500
+#define USB_DEVICE_ID_GTCO_501 0x0501
+#define USB_DEVICE_ID_GTCO_502 0x0502
+#define USB_DEVICE_ID_GTCO_503 0x0503
+#define USB_DEVICE_ID_GTCO_504 0x0504
+#define USB_DEVICE_ID_GTCO_1000 0x1000
+#define USB_DEVICE_ID_GTCO_1001 0x1001
+#define USB_DEVICE_ID_GTCO_1002 0x1002
+#define USB_DEVICE_ID_GTCO_1003 0x1003
+#define USB_DEVICE_ID_GTCO_1004 0x1004
+#define USB_DEVICE_ID_GTCO_1005 0x1005
+#define USB_DEVICE_ID_GTCO_1006 0x1006
+#define USB_DEVICE_ID_GTCO_1007 0x1007
+
+#define USB_VENDOR_ID_GYRATION 0x0c16
+#define USB_DEVICE_ID_GYRATION_REMOTE 0x0002
+
+#define USB_VENDOR_ID_HAPP 0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
+#define USB_DEVICE_ID_UGCI_FLYING 0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
+
+#define USB_VENDOR_ID_IMATION 0x0718
+#define USB_DEVICE_ID_DISC_STAKKA 0xd000
+
+#define USB_VENDOR_ID_KBGEAR 0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
+
+#define USB_VENDOR_ID_LABTEC 0x1020
+#define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
+
+#define USB_VENDOR_ID_LD 0x0f11
+#define USB_DEVICE_ID_LD_CASSY 0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020
+#define USB_DEVICE_ID_LD_JWM 0x1080
+#define USB_DEVICE_ID_LD_DMMP 0x1081
+#define USB_DEVICE_ID_LD_UMIP 0x1090
+#define USB_DEVICE_ID_LD_XRAY1 0x1100
+#define USB_DEVICE_ID_LD_XRAY2 0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200
+#define USB_DEVICE_ID_LD_COM3LAB 0x2000
+#define USB_DEVICE_ID_LD_TELEPORT 0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
+
+#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_LX3 0xc044
+#define USB_DEVICE_ID_LOGITECH_V150 0xc047
+#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
+#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
+#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211
+#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
+#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
+#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
+#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
+#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
+#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
+#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
+#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
+#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
+#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
+#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
+#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
+#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03
+
+#define USB_VENDOR_ID_MCC 0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a
+
+#define USB_VENDOR_ID_MGE 0x0463
+#define USB_DEVICE_ID_MGE_UPS 0xffff
+#define USB_DEVICE_ID_MGE_UPS1 0x0001
+
+#define USB_VENDOR_ID_MICROCHIP 0x04d8
+#define USB_DEVICE_ID_PICKIT1 0x0032
+#define USB_DEVICE_ID_PICKIT2 0x0033
+
+#define USB_VENDOR_ID_MICROSOFT 0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
+#define USB_DEVICE_ID_MS_NE4K 0x00db
+#define USB_DEVICE_ID_MS_LK6K 0x00f9
+#define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701
+#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
+
+
+#define USB_VENDOR_ID_MONTEREY 0x0566
+#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
+
+#define USB_VENDOR_ID_NCR 0x0404
+#define USB_DEVICE_ID_NCR_FIRST 0x0300
+#define USB_DEVICE_ID_NCR_LAST 0x03ff
+
+#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
+#define USB_DEVICE_ID_N_S_HARMONY 0xc359
+
+#define USB_VENDOR_ID_NATSU 0x08b7
+#define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001
+
+#define USB_VENDOR_ID_NEC 0x073e
+#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
+
+#define USB_VENDOR_ID_ONTRAK 0x0a07
+#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
+
+#define USB_VENDOR_ID_PANJIT 0x134c
+
+#define USB_VENDOR_ID_PANTHERLORD 0x0810
+#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
+
+#define USB_VENDOR_ID_PETALYNX 0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+
+#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
+#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
+
+#define USB_VENDOR_ID_SAITEK 0x06a3
+#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
+
+#define USB_VENDOR_ID_SAMSUNG 0x0419
+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
+
+#define USB_VENDOR_ID_SONY 0x054c
+#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
+
+#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2 0x0036
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3 0x0034
+
+#define USB_VENDOR_ID_SUN 0x0430
+#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
+
+#define USB_VENDOR_ID_SUNPLUS 0x04fc
+#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
+
+#define USB_VENDOR_ID_TENX 0x1130
+#define USB_DEVICE_ID_TENX_IBUDDY1 0x0001
+#define USB_DEVICE_ID_TENX_IBUDDY2 0x0002
+
+#define USB_VENDOR_ID_THRUSTMASTER 0x044f
+
+#define USB_VENDOR_ID_TOPMAX 0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+
+#define USB_VENDOR_ID_TURBOX 0x062a
+#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+
+#define USB_VENDOR_ID_VERNIER 0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP 0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
+#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
+
+#define USB_VENDOR_ID_WACOM 0x056a
+
+#define USB_VENDOR_ID_WISEGROUP 0x0925
+#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
+#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201
+#define USB_DEVICE_ID_QUAD_USB_JOYPAD 0x8800
+#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866
+
+#define USB_VENDOR_ID_WISEGROUP_LTD 0x6666
+#define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677
+#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+
+#define USB_VENDOR_ID_YEALINK 0x6993
+#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
+
+#define USB_VENDOR_ID_ZEROPLUS 0x0c12
+
+#define USB_VENDOR_ID_KYE 0x0458
+#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
+
+#endif
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
deleted file mode 100644
index 16feea01449..00000000000
--- a/drivers/hid/hid-input-quirks.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * HID-input usage mapping quirks
- *
- * This is used to handle HID-input mappings for devices violating
- * HUT 1.12 specification.
- *
- * Copyright (c) 2007-2008 Jiri Kosina
- */
-
-/*
- * 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
- */
-
-#include <linux/input.h>
-#include <linux/hid.h>
-
-#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
-#define map_rel(c) do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
-#define map_key(c) do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
-#define map_led(c) do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
-
-#define map_abs_clear(c) do { map_abs(c); clear_bit(c, *bit); } while (0)
-#define map_key_clear(c) do { map_key(c); clear_bit(c, *bit); } while (0)
-
-static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x03a: map_key_clear(KEY_SOUND); break;
- case 0x03b: map_key_clear(KEY_CAMERA); break;
- case 0x03c: map_key_clear(KEY_DOCUMENTS); break;
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x301: map_key_clear(KEY_PROG1); break;
- case 0x302: map_key_clear(KEY_PROG2); break;
- case 0x303: map_key_clear(KEY_PROG3); break;
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
- return 0;
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- /* Reported on Logitech Ultra X Media Remote */
- case 0x004: map_key_clear(KEY_AGAIN); break;
- case 0x00d: map_key_clear(KEY_HOME); break;
- case 0x024: map_key_clear(KEY_SHUFFLE); break;
- case 0x025: map_key_clear(KEY_TV); break;
- case 0x026: map_key_clear(KEY_MENU); break;
- case 0x031: map_key_clear(KEY_AUDIO); break;
- case 0x032: map_key_clear(KEY_TEXT); break;
- case 0x033: map_key_clear(KEY_LAST); break;
- case 0x047: map_key_clear(KEY_MP3); break;
- case 0x048: map_key_clear(KEY_DVD); break;
- case 0x049: map_key_clear(KEY_MEDIA); break;
- case 0x04a: map_key_clear(KEY_VIDEO); break;
- case 0x04b: map_key_clear(KEY_ANGLE); break;
- case 0x04c: map_key_clear(KEY_LANGUAGE); break;
- case 0x04d: map_key_clear(KEY_SUBTITLE); break;
- case 0x051: map_key_clear(KEY_RED); break;
- case 0x052: map_key_clear(KEY_CLOSE); break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
- return 0;
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- /* Reported on Gyration MCE Remote */
- case 0x00d: map_key_clear(KEY_HOME); break;
- case 0x024: map_key_clear(KEY_DVD); break;
- case 0x025: map_key_clear(KEY_PVR); break;
- case 0x046: map_key_clear(KEY_MEDIA); break;
- case 0x047: map_key_clear(KEY_MP3); break;
- case 0x049: map_key_clear(KEY_CAMERA); break;
- case 0x04a: map_key_clear(KEY_VIDEO); break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
- return 0;
-
- set_bit(EV_REP, input->evbit);
- switch (usage->hid & HID_USAGE) {
- case 0xff01: map_key_clear(BTN_1); break;
- case 0xff02: map_key_clear(BTN_2); break;
- case 0xff03: map_key_clear(BTN_3); break;
- case 0xff04: map_key_clear(BTN_4); break;
- case 0xff05: map_key_clear(BTN_5); break;
- case 0xff06: map_key_clear(BTN_6); break;
- case 0xff07: map_key_clear(BTN_7); break;
- case 0xff08: map_key_clear(BTN_8); break;
- case 0xff09: map_key_clear(BTN_9); break;
- case 0xff0a: map_key_clear(BTN_A); break;
- case 0xff0b: map_key_clear(BTN_B); break;
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
- return 0;
-
- switch(usage->hid & HID_USAGE) {
- case 0xfd06: map_key_clear(KEY_CHAT); break;
- case 0xfd07: map_key_clear(KEY_PHONE); break;
- case 0xff05:
- set_bit(EV_REP, input->evbit);
- map_key_clear(KEY_F13);
- set_bit(KEY_F14, input->keybit);
- set_bit(KEY_F15, input->keybit);
- set_bit(KEY_F16, input->keybit);
- set_bit(KEY_F17, input->keybit);
- set_bit(KEY_F18, input->keybit);
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
- return 0;
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- case 0xfd08: map_key_clear(KEY_FORWARD); break;
- case 0xfd09: map_key_clear(KEY_BACK); break;
- case 0xfd0b: map_key_clear(KEY_PLAYPAUSE); break;
- case 0xfd0e: map_key_clear(KEY_CLOSE); break;
- case 0xfd0f: map_key_clear(KEY_PLAY); break;
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
- ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
- return 0;
-
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR)
- switch(usage->hid & HID_USAGE) {
- case 0x05a: map_key_clear(KEY_TEXT); break;
- case 0x05b: map_key_clear(KEY_RED); break;
- case 0x05c: map_key_clear(KEY_GREEN); break;
- case 0x05d: map_key_clear(KEY_YELLOW); break;
- case 0x05e: map_key_clear(KEY_BLUE); break;
- default:
- return 0;
- }
-
- if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
- switch(usage->hid & HID_USAGE) {
- case 0x0f6: map_key_clear(KEY_NEXT); break;
- case 0x0fa: map_key_clear(KEY_BACK); break;
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x1001: map_key_clear(KEY_MESSENGER); break;
- case 0x1003: map_key_clear(KEY_SOUND); break;
- case 0x1004: map_key_clear(KEY_VIDEO); break;
- case 0x1005: map_key_clear(KEY_AUDIO); break;
- case 0x100a: map_key_clear(KEY_DOCUMENTS); break;
- case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break;
- case 0x1012: map_key_clear(KEY_NEXTSONG); break;
- case 0x1013: map_key_clear(KEY_CAMERA); break;
- case 0x1014: map_key_clear(KEY_MESSENGER); break;
- case 0x1015: map_key_clear(KEY_RECORD); break;
- case 0x1016: map_key_clear(KEY_PLAYER); break;
- case 0x1017: map_key_clear(KEY_EJECTCD); break;
- case 0x1018: map_key_clear(KEY_MEDIA); break;
- case 0x1019: map_key_clear(KEY_PROG1); break;
- case 0x101a: map_key_clear(KEY_PROG2); break;
- case 0x101b: map_key_clear(KEY_PROG3); break;
- case 0x101f: map_key_clear(KEY_ZOOMIN); break;
- case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
- case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
- case 0x1023: map_key_clear(KEY_CLOSE); break;
- case 0x1027: map_key_clear(KEY_MENU); break;
- /* this one is marked as 'Rotate' */
- case 0x1028: map_key_clear(KEY_ANGLE); break;
- case 0x1029: map_key_clear(KEY_SHUFFLE); break;
- case 0x102a: map_key_clear(KEY_BACK); break;
- case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break;
- case 0x1041: map_key_clear(KEY_BATTERY); break;
- case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
- case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
- case 0x1044: map_key_clear(KEY_PRESENTATION); break;
- case 0x1045: map_key_clear(KEY_UNDO); break;
- case 0x1046: map_key_clear(KEY_REDO); break;
- case 0x1047: map_key_clear(KEY_PRINT); break;
- case 0x1048: map_key_clear(KEY_SAVE); break;
- case 0x1049: map_key_clear(KEY_PROG1); break;
- case 0x104a: map_key_clear(KEY_PROG2); break;
- case 0x104b: map_key_clear(KEY_PROG3); break;
- case 0x104c: map_key_clear(KEY_PROG4); break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x156: map_key_clear(KEY_WORDPROCESSOR); break;
- case 0x157: map_key_clear(KEY_SPREADSHEET); break;
- case 0x158: map_key_clear(KEY_PRESENTATION); break;
- case 0x15c: map_key_clear(KEY_STOP); break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x230: map_key(BTN_MOUSE); break;
- case 0x231: map_rel(REL_WHEEL); break;
- /*
- * this keyboard has a scrollwheel implemented in
- * totally broken way. We map this usage temporarily
- * to HWHEEL and handle it in the event quirk handler
- */
- case 0x232: map_rel(REL_HWHEEL); break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input,
- unsigned long **bit, int *max)
-{
- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
- return 0;
-
- switch (usage->hid & HID_USAGE) {
- case 0x2003: map_key_clear(KEY_ZOOMIN); break;
- case 0x2103: map_key_clear(KEY_ZOOMOUT); break;
- default:
- return 0;
- }
- return 1;
-}
-
-#define VENDOR_ID_BELKIN 0x1020
-#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006
-
-#define VENDOR_ID_CHERRY 0x046a
-#define DEVICE_ID_CHERRY_CYMOTION 0x0023
-
-#define VENDOR_ID_CHICONY 0x04f2
-#define DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
-
-#define VENDOR_ID_EZKEY 0x0518
-#define DEVICE_ID_BTC_8193 0x0002
-
-#define VENDOR_ID_GYRATION 0x0c16
-#define DEVICE_ID_GYRATION_REMOTE 0x0002
-
-#define VENDOR_ID_LOGITECH 0x046d
-#define DEVICE_ID_LOGITECH_RECEIVER 0xc101
-#define DEVICE_ID_S510_RECEIVER 0xc50c
-#define DEVICE_ID_S510_RECEIVER_2 0xc517
-#define DEVICE_ID_MX3000_RECEIVER 0xc513
-
-#define VENDOR_ID_MICROSOFT 0x045e
-#define DEVICE_ID_MS4K 0x00db
-#define DEVICE_ID_MS6K 0x00f9
-#define DEVICE_IS_MS_PRESENTER_8K_BT 0x0701
-#define DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
-
-#define VENDOR_ID_MONTEREY 0x0566
-#define DEVICE_ID_GENIUS_KB29E 0x3004
-
-#define VENDOR_ID_PETALYNX 0x18b1
-#define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
-
-#define VENDOR_ID_SUNPLUS 0x04fc
-#define DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
-
-static const struct hid_input_blacklist {
- __u16 idVendor;
- __u16 idProduct;
- int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
-} hid_input_blacklist[] = {
- { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
-
- { VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion },
-
- { VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad },
-
- { VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
-
- { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },
-
- { VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
- { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
- { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
- { VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },
-
- { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
- { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
- { VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
- { VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k },
-
- { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
-
- { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
-
- { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
-
- { 0, 0, NULL }
-};
-
-int hidinput_mapping_quirks(struct hid_usage *usage,
- struct input_dev *input,
- unsigned long **bit, int *max)
-{
- struct hid_device *device = input_get_drvdata(input);
- int i = 0;
-
- while (hid_input_blacklist[i].quirk) {
- if (hid_input_blacklist[i].idVendor == device->vendor &&
- hid_input_blacklist[i].idProduct == device->product)
- return hid_input_blacklist[i].quirk(usage, input, bit, max);
- i++;
- }
- return 0;
-}
-
-int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
- struct input_dev *input;
-
- input = field->hidinput->input;
-
- if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
- || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
- if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
- (usage->type == EV_REL) &&
- (usage->code == REL_WHEEL)) {
- hid->delayed_value = value;
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
- (usage->hid == 0x000100b8)) {
- input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
- input_event(input, usage->type, usage->code, -value);
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
- input_event(input, usage->type, REL_HWHEEL, value);
- return 1;
- }
-
- if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
- return 1;
-
- /* Handling MS keyboards special buttons */
- if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS &&
- usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
- int key = 0;
- static int last_key = 0;
- switch (value) {
- case 0x01: key = KEY_F14; break;
- case 0x02: key = KEY_F15; break;
- case 0x04: key = KEY_F16; break;
- case 0x08: key = KEY_F17; break;
- case 0x10: key = KEY_F18; break;
- default: break;
- }
- if (key) {
- input_event(input, usage->type, key, 1);
- last_key = key;
- } else {
- input_event(input, usage->type, last_key, 0);
- }
- }
-
- /* handle the temporary quirky mapping to HWHEEL */
- if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
- usage->type == EV_REL && usage->code == REL_HWHEEL) {
- input_event(input, usage->type, REL_WHEEL, -value);
- return 1;
- }
-
- /* Gyration MCE remote "Sleep" key */
- if (hid->vendor == VENDOR_ID_GYRATION &&
- hid->product == DEVICE_ID_GYRATION_REMOTE &&
- (usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
- (usage->hid & 0xff) == 0x82) {
- input_event(input, usage->type, usage->code, 1);
- input_sync(input);
- input_event(input, usage->type, usage->code, 0);
- input_sync(input);
- return 1;
- }
- return 0;
-}
-
-
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 1b2e8dc3398..7f183b7147e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -32,11 +32,6 @@
#include <linux/hid.h>
#include <linux/hid-debug.h>
-static int hid_apple_fnmode = 1;
-module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
- "Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
#define unk KEY_UNKNOWN
static const unsigned char hid_keyboard[256] = {
@@ -58,227 +53,20 @@ static const unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
-/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
-#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
-static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
- 0,216, 0,213,175,156, 0, 0, 0, 0,
- 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
- 174,167,152,161,112, 0, 0, 0,154, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,183,184,185,186,187,
- 188,189,190,191,192,193,194, 0, 0, 0
-};
-
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}};
-#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
-#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
-#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
-#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
-
-#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
-
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-
-struct hidinput_key_translation {
- u16 from;
- u16 to;
- u8 flags;
-};
-
-#define APPLE_FLAG_FKEY 0x01
-
-static struct hidinput_key_translation apple_fn_keys[] = {
- { KEY_BACKSPACE, KEY_DELETE },
- { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
- { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
- { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
- { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
- { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
- { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
- { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
- { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
- { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
- { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
- { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
- { KEY_UP, KEY_PAGEUP },
- { KEY_DOWN, KEY_PAGEDOWN },
- { KEY_LEFT, KEY_HOME },
- { KEY_RIGHT, KEY_END },
- { }
-};
-
-static struct hidinput_key_translation powerbook_fn_keys[] = {
- { KEY_BACKSPACE, KEY_DELETE },
- { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
- { KEY_F3, KEY_MUTE, APPLE_FLAG_FKEY },
- { KEY_F4, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
- { KEY_F5, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
- { KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY },
- { KEY_F7, KEY_SWITCHVIDEOMODE, APPLE_FLAG_FKEY },
- { KEY_F8, KEY_KBDILLUMTOGGLE, APPLE_FLAG_FKEY },
- { KEY_F9, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
- { KEY_F10, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
- { KEY_UP, KEY_PAGEUP },
- { KEY_DOWN, KEY_PAGEDOWN },
- { KEY_LEFT, KEY_HOME },
- { KEY_RIGHT, KEY_END },
- { }
-};
-
-static struct hidinput_key_translation powerbook_numlock_keys[] = {
- { KEY_J, KEY_KP1 },
- { KEY_K, KEY_KP2 },
- { KEY_L, KEY_KP3 },
- { KEY_U, KEY_KP4 },
- { KEY_I, KEY_KP5 },
- { KEY_O, KEY_KP6 },
- { KEY_7, KEY_KP7 },
- { KEY_8, KEY_KP8 },
- { KEY_9, KEY_KP9 },
- { KEY_M, KEY_KP0 },
- { KEY_DOT, KEY_KPDOT },
- { KEY_SLASH, KEY_KPPLUS },
- { KEY_SEMICOLON, KEY_KPMINUS },
- { KEY_P, KEY_KPASTERISK },
- { KEY_MINUS, KEY_KPEQUAL },
- { KEY_0, KEY_KPSLASH },
- { KEY_F6, KEY_NUMLOCK },
- { KEY_KPENTER, KEY_KPENTER },
- { KEY_BACKSPACE, KEY_BACKSPACE },
- { }
-};
-
-static struct hidinput_key_translation apple_iso_keyboard[] = {
- { KEY_GRAVE, KEY_102ND },
- { KEY_102ND, KEY_GRAVE },
- { }
-};
+#define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))
+#define map_rel(c) hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c))
+#define map_key(c) hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c))
+#define map_led(c) hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c))
-static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
-{
- struct hidinput_key_translation *trans;
-
- /* Look for the translation */
- for (trans = table; trans->from; trans++)
- if (trans->from == from)
- return trans;
-
- return NULL;
-}
-
-int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
-{
- struct hidinput_key_translation *trans;
-
- if (usage->code == KEY_FN) {
- if (value) hid->quirks |= HID_QUIRK_APPLE_FN_ON;
- else hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
-
- input_event(input, usage->type, usage->code, value);
-
- return 1;
- }
-
- if (hid_apple_fnmode) {
- int do_translate;
-
- trans = find_translation((hid->product < 0x220 ||
- hid->product >= 0x300) ?
- powerbook_fn_keys : apple_fn_keys,
- usage->code);
- if (trans) {
- if (test_bit(usage->code, hid->apple_pressed_fn))
- do_translate = 1;
- else if (trans->flags & APPLE_FLAG_FKEY)
- do_translate =
- (hid_apple_fnmode == 2 && (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
- (hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
- else
- do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
-
- if (do_translate) {
- if (value)
- set_bit(usage->code, hid->apple_pressed_fn);
- else
- clear_bit(usage->code, hid->apple_pressed_fn);
-
- input_event(input, usage->type, trans->to, value);
-
- return 1;
- }
- }
-
- if (hid->quirks & HID_QUIRK_APPLE_NUMLOCK_EMULATION && (
- test_bit(usage->code, hid->pb_pressed_numlock) ||
- test_bit(LED_NUML, input->led))) {
- trans = find_translation(powerbook_numlock_keys, usage->code);
-
- if (trans) {
- if (value)
- set_bit(usage->code, hid->pb_pressed_numlock);
- else
- clear_bit(usage->code, hid->pb_pressed_numlock);
-
- input_event(input, usage->type, trans->to, value);
- }
-
- return 1;
- }
- }
-
- if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
- trans = find_translation(apple_iso_keyboard, usage->code);
- if (trans) {
- input_event(input, usage->type, trans->to, value);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void hidinput_apple_setup(struct input_dev *input)
-{
- struct hidinput_key_translation *trans;
-
- set_bit(KEY_NUMLOCK, input->keybit);
-
- /* Enable all needed keys */
- for (trans = apple_fn_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_fn_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_numlock_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = apple_iso_keyboard; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
-}
-#else
-inline int hidinput_apple_event(struct hid_device *hid,
- struct input_dev *input,
- struct hid_usage *usage, __s32 value)
-{
- return 0;
-}
-
-static inline void hidinput_apple_setup(struct input_dev *input)
-{
-}
-#endif
+#define map_abs_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
+ &max, EV_ABS, (c))
+#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
+ &max, EV_KEY, (c))
static inline int match_scancode(int code, int scancode)
{
@@ -366,7 +154,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
{
struct input_dev *input = hidinput->input;
struct hid_device *device = input_get_drvdata(input);
- int max = 0, code, ret;
+ int max = 0, code;
unsigned long *bit = NULL;
field->hidinput = hidinput;
@@ -385,406 +173,345 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
goto ignore;
}
- /* handle input mappings for quirky devices */
- ret = hidinput_mapping_quirks(usage, input, &bit, &max);
- if (ret)
- goto mapped;
+ if (device->driver->input_mapping) {
+ int ret = device->driver->input_mapping(device, hidinput, field,
+ usage, &bit, &max);
+ if (ret > 0)
+ goto mapped;
+ if (ret < 0)
+ goto ignore;
+ }
switch (usage->hid & HID_USAGE_PAGE) {
+ case HID_UP_UNDEFINED:
+ goto ignore;
- case HID_UP_UNDEFINED:
- goto ignore;
-
- case HID_UP_KEYBOARD:
+ case HID_UP_KEYBOARD:
+ set_bit(EV_REP, input->evbit);
- set_bit(EV_REP, input->evbit);
+ if ((usage->hid & HID_USAGE) < 256) {
+ if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
+ map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
+ } else
+ map_key(KEY_UNKNOWN);
- if ((usage->hid & HID_USAGE) < 256) {
- if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
- map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
- } else
- map_key(KEY_UNKNOWN);
+ break;
- break;
+ case HID_UP_BUTTON:
+ code = ((usage->hid - 1) & 0xf);
- case HID_UP_BUTTON:
-
- code = ((usage->hid - 1) & 0xf);
-
- switch (field->application) {
- case HID_GD_MOUSE:
- case HID_GD_POINTER: code += 0x110; break;
- case HID_GD_JOYSTICK: code += 0x120; break;
- case HID_GD_GAMEPAD: code += 0x130; break;
- default:
- switch (field->physical) {
- case HID_GD_MOUSE:
- case HID_GD_POINTER: code += 0x110; break;
- case HID_GD_JOYSTICK: code += 0x120; break;
- case HID_GD_GAMEPAD: code += 0x130; break;
- default: code += 0x100;
- }
- }
-
- /* Special handling for Logitech Cordless Desktop */
- if (field->application != HID_GD_MOUSE) {
- if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
- int hid = usage->hid & HID_USAGE;
- if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
- code = logitech_expanded_keymap[hid];
- }
- } else {
- if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
- int hid = usage->hid & HID_USAGE;
- if (hid == 7 || hid == 8)
- goto ignore;
- }
+ switch (field->application) {
+ case HID_GD_MOUSE:
+ case HID_GD_POINTER: code += 0x110; break;
+ case HID_GD_JOYSTICK: code += 0x120; break;
+ case HID_GD_GAMEPAD: code += 0x130; break;
+ default:
+ switch (field->physical) {
+ case HID_GD_MOUSE:
+ case HID_GD_POINTER: code += 0x110; break;
+ case HID_GD_JOYSTICK: code += 0x120; break;
+ case HID_GD_GAMEPAD: code += 0x130; break;
+ default: code += 0x100;
}
+ }
- map_key(code);
- break;
-
-
- case HID_UP_SIMULATION:
-
- switch (usage->hid & 0xffff) {
- case 0xba: map_abs(ABS_RUDDER); break;
- case 0xbb: map_abs(ABS_THROTTLE); break;
- case 0xc4: map_abs(ABS_GAS); break;
- case 0xc5: map_abs(ABS_BRAKE); break;
- case 0xc8: map_abs(ABS_WHEEL); break;
- default: goto ignore;
+ map_key(code);
+ break;
+
+ case HID_UP_SIMULATION:
+ switch (usage->hid & 0xffff) {
+ case 0xba: map_abs(ABS_RUDDER); break;
+ case 0xbb: map_abs(ABS_THROTTLE); break;
+ case 0xc4: map_abs(ABS_GAS); break;
+ case 0xc5: map_abs(ABS_BRAKE); break;
+ case 0xc8: map_abs(ABS_WHEEL); break;
+ default: goto ignore;
+ }
+ break;
+
+ case HID_UP_GENDESK:
+ if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
+ switch (usage->hid & 0xf) {
+ case 0x1: map_key_clear(KEY_POWER); break;
+ case 0x2: map_key_clear(KEY_SLEEP); break;
+ case 0x3: map_key_clear(KEY_WAKEUP); break;
+ default: goto unknown;
}
break;
+ }
- case HID_UP_GENDESK:
-
- if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
- switch (usage->hid & 0xf) {
- case 0x1: map_key_clear(KEY_POWER); break;
- case 0x2: map_key_clear(KEY_SLEEP); break;
- case 0x3: map_key_clear(KEY_WAKEUP); break;
- default: goto unknown;
- }
- break;
- }
-
- if ((usage->hid & 0xf0) == 0x90) { /* D-pad */
- switch (usage->hid) {
- case HID_GD_UP: usage->hat_dir = 1; break;
- case HID_GD_DOWN: usage->hat_dir = 5; break;
- case HID_GD_RIGHT: usage->hat_dir = 3; break;
- case HID_GD_LEFT: usage->hat_dir = 7; break;
- default: goto unknown;
- }
- if (field->dpad) {
- map_abs(field->dpad);
- goto ignore;
- }
- map_abs(ABS_HAT0X);
- break;
- }
-
+ if ((usage->hid & 0xf0) == 0x90) { /* D-pad */
switch (usage->hid) {
-
- /* These usage IDs map directly to the usage codes. */
- case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
- case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
- case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
- if (field->flags & HID_MAIN_ITEM_RELATIVE)
- map_rel(usage->hid & 0xf);
- else
- map_abs(usage->hid & 0xf);
- break;
-
- case HID_GD_HATSWITCH:
- usage->hat_min = field->logical_minimum;
- usage->hat_max = field->logical_maximum;
- map_abs(ABS_HAT0X);
- break;
-
- case HID_GD_START: map_key_clear(BTN_START); break;
- case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
-
- default: goto unknown;
+ case HID_GD_UP: usage->hat_dir = 1; break;
+ case HID_GD_DOWN: usage->hat_dir = 5; break;
+ case HID_GD_RIGHT: usage->hat_dir = 3; break;
+ case HID_GD_LEFT: usage->hat_dir = 7; break;
+ default: goto unknown;
}
-
- break;
-
- case HID_UP_LED:
-
- switch (usage->hid & 0xffff) { /* HID-Value: */
- case 0x01: map_led (LED_NUML); break; /* "Num Lock" */
- case 0x02: map_led (LED_CAPSL); break; /* "Caps Lock" */
- case 0x03: map_led (LED_SCROLLL); break; /* "Scroll Lock" */
- case 0x04: map_led (LED_COMPOSE); break; /* "Compose" */
- case 0x05: map_led (LED_KANA); break; /* "Kana" */
- case 0x27: map_led (LED_SLEEP); break; /* "Stand-By" */
- case 0x4c: map_led (LED_SUSPEND); break; /* "System Suspend" */
- case 0x09: map_led (LED_MUTE); break; /* "Mute" */
- case 0x4b: map_led (LED_MISC); break; /* "Generic Indicator" */
- case 0x19: map_led (LED_MAIL); break; /* "Message Waiting" */
- case 0x4d: map_led (LED_CHARGING); break; /* "External Power Connected" */
-
- default: goto ignore;
+ if (field->dpad) {
+ map_abs(field->dpad);
+ goto ignore;
}
+ map_abs(ABS_HAT0X);
break;
+ }
- case HID_UP_DIGITIZER:
-
- switch (usage->hid & 0xff) {
-
- case 0x30: /* TipPressure */
- if (!test_bit(BTN_TOUCH, input->keybit)) {
- device->quirks |= HID_QUIRK_NOTOUCH;
- set_bit(EV_KEY, input->evbit);
- set_bit(BTN_TOUCH, input->keybit);
- }
-
- map_abs_clear(ABS_PRESSURE);
- break;
-
- case 0x32: /* InRange */
- switch (field->physical & 0xff) {
- case 0x21: map_key(BTN_TOOL_MOUSE); break;
- case 0x22: map_key(BTN_TOOL_FINGER); break;
- default: map_key(BTN_TOOL_PEN); break;
- }
- break;
+ switch (usage->hid) {
+ /* These usage IDs map directly to the usage codes. */
+ case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
+ case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
+ case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
+ if (field->flags & HID_MAIN_ITEM_RELATIVE)
+ map_rel(usage->hid & 0xf);
+ else
+ map_abs(usage->hid & 0xf);
+ break;
- case 0x3c: /* Invert */
- map_key_clear(BTN_TOOL_RUBBER);
- break;
+ case HID_GD_HATSWITCH:
+ usage->hat_min = field->logical_minimum;
+ usage->hat_max = field->logical_maximum;
+ map_abs(ABS_HAT0X);
+ break;
- case 0x33: /* Touch */
- case 0x42: /* TipSwitch */
- case 0x43: /* TipSwitch2 */
- device->quirks &= ~HID_QUIRK_NOTOUCH;
- map_key_clear(BTN_TOUCH);
- break;
+ case HID_GD_START: map_key_clear(BTN_START); break;
+ case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
- case 0x44: /* BarrelSwitch */
- map_key_clear(BTN_STYLUS);
- break;
+ default: goto unknown;
+ }
- default: goto unknown;
+ break;
+
+ case HID_UP_LED:
+ switch (usage->hid & 0xffff) { /* HID-Value: */
+ case 0x01: map_led (LED_NUML); break; /* "Num Lock" */
+ case 0x02: map_led (LED_CAPSL); break; /* "Caps Lock" */
+ case 0x03: map_led (LED_SCROLLL); break; /* "Scroll Lock" */
+ case 0x04: map_led (LED_COMPOSE); break; /* "Compose" */
+ case 0x05: map_led (LED_KANA); break; /* "Kana" */
+ case 0x27: map_led (LED_SLEEP); break; /* "Stand-By" */
+ case 0x4c: map_led (LED_SUSPEND); break; /* "System Suspend" */
+ case 0x09: map_led (LED_MUTE); break; /* "Mute" */
+ case 0x4b: map_led (LED_MISC); break; /* "Generic Indicator" */
+ case 0x19: map_led (LED_MAIL); break; /* "Message Waiting" */
+ case 0x4d: map_led (LED_CHARGING); break; /* "External Power Connected" */
+
+ default: goto ignore;
+ }
+ break;
+
+ case HID_UP_DIGITIZER:
+ switch (usage->hid & 0xff) {
+ case 0x30: /* TipPressure */
+ if (!test_bit(BTN_TOUCH, input->keybit)) {
+ device->quirks |= HID_QUIRK_NOTOUCH;
+ set_bit(EV_KEY, input->evbit);
+ set_bit(BTN_TOUCH, input->keybit);
}
+ map_abs_clear(ABS_PRESSURE);
break;
- case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
-
- switch (usage->hid & HID_USAGE) {
- case 0x000: goto ignore;
- case 0x034: map_key_clear(KEY_SLEEP); break;
- case 0x036: map_key_clear(BTN_MISC); break;
-
- case 0x040: map_key_clear(KEY_MENU); break;
- case 0x045: map_key_clear(KEY_RADIO); break;
-
- case 0x083: map_key_clear(KEY_LAST); break;
- case 0x088: map_key_clear(KEY_PC); break;
- case 0x089: map_key_clear(KEY_TV); break;
- case 0x08a: map_key_clear(KEY_WWW); break;
- case 0x08b: map_key_clear(KEY_DVD); break;
- case 0x08c: map_key_clear(KEY_PHONE); break;
- case 0x08d: map_key_clear(KEY_PROGRAM); break;
- case 0x08e: map_key_clear(KEY_VIDEOPHONE); break;
- case 0x08f: map_key_clear(KEY_GAMES); break;
- case 0x090: map_key_clear(KEY_MEMO); break;
- case 0x091: map_key_clear(KEY_CD); break;
- case 0x092: map_key_clear(KEY_VCR); break;
- case 0x093: map_key_clear(KEY_TUNER); break;
- case 0x094: map_key_clear(KEY_EXIT); break;
- case 0x095: map_key_clear(KEY_HELP); break;
- case 0x096: map_key_clear(KEY_TAPE); break;
- case 0x097: map_key_clear(KEY_TV2); break;
- case 0x098: map_key_clear(KEY_SAT); break;
- case 0x09a: map_key_clear(KEY_PVR); break;
-
- case 0x09c: map_key_clear(KEY_CHANNELUP); break;
- case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
- case 0x0a0: map_key_clear(KEY_VCR2); break;
-
- case 0x0b0: map_key_clear(KEY_PLAY); break;
- case 0x0b1: map_key_clear(KEY_PAUSE); break;
- case 0x0b2: map_key_clear(KEY_RECORD); break;
- case 0x0b3: map_key_clear(KEY_FASTFORWARD); break;
- case 0x0b4: map_key_clear(KEY_REWIND); break;
- case 0x0b5: map_key_clear(KEY_NEXTSONG); break;
- case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
- case 0x0b7: map_key_clear(KEY_STOPCD); break;
- case 0x0b8: map_key_clear(KEY_EJECTCD); break;
- case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break;
-
- case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
- case 0x0e0: map_abs_clear(ABS_VOLUME); break;
- case 0x0e2: map_key_clear(KEY_MUTE); break;
- case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
- case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
- case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
-
- case 0x182: map_key_clear(KEY_BOOKMARKS); break;
- case 0x183: map_key_clear(KEY_CONFIG); break;
- case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
- case 0x185: map_key_clear(KEY_EDITOR); break;
- case 0x186: map_key_clear(KEY_SPREADSHEET); break;
- case 0x187: map_key_clear(KEY_GRAPHICSEDITOR); break;
- case 0x188: map_key_clear(KEY_PRESENTATION); break;
- case 0x189: map_key_clear(KEY_DATABASE); break;
- case 0x18a: map_key_clear(KEY_MAIL); break;
- case 0x18b: map_key_clear(KEY_NEWS); break;
- case 0x18c: map_key_clear(KEY_VOICEMAIL); break;
- case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break;
- case 0x18e: map_key_clear(KEY_CALENDAR); break;
- case 0x191: map_key_clear(KEY_FINANCE); break;
- case 0x192: map_key_clear(KEY_CALC); break;
- case 0x194: map_key_clear(KEY_FILE); break;
- case 0x196: map_key_clear(KEY_WWW); break;
- case 0x19c: map_key_clear(KEY_LOGOFF); break;
- case 0x19e: map_key_clear(KEY_COFFEE); break;
- case 0x1a6: map_key_clear(KEY_HELP); break;
- case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
- case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
- case 0x1b6: map_key_clear(KEY_MEDIA); break;
- case 0x1b7: map_key_clear(KEY_SOUND); break;
- case 0x1bc: map_key_clear(KEY_MESSENGER); break;
- case 0x1bd: map_key_clear(KEY_INFO); break;
- case 0x201: map_key_clear(KEY_NEW); break;
- case 0x202: map_key_clear(KEY_OPEN); break;
- case 0x203: map_key_clear(KEY_CLOSE); break;
- case 0x204: map_key_clear(KEY_EXIT); break;
- case 0x207: map_key_clear(KEY_SAVE); break;
- case 0x208: map_key_clear(KEY_PRINT); break;
- case 0x209: map_key_clear(KEY_PROPS); break;
- case 0x21a: map_key_clear(KEY_UNDO); break;
- case 0x21b: map_key_clear(KEY_COPY); break;
- case 0x21c: map_key_clear(KEY_CUT); break;
- case 0x21d: map_key_clear(KEY_PASTE); break;
- case 0x21f: map_key_clear(KEY_FIND); break;
- case 0x221: map_key_clear(KEY_SEARCH); break;
- case 0x222: map_key_clear(KEY_GOTO); break;
- case 0x223: map_key_clear(KEY_HOMEPAGE); break;
- case 0x224: map_key_clear(KEY_BACK); break;
- case 0x225: map_key_clear(KEY_FORWARD); break;
- case 0x226: map_key_clear(KEY_STOP); break;
- case 0x227: map_key_clear(KEY_REFRESH); break;
- case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
- case 0x22d: map_key_clear(KEY_ZOOMIN); break;
- case 0x22e: map_key_clear(KEY_ZOOMOUT); break;
- case 0x22f: map_key_clear(KEY_ZOOMRESET); break;
- case 0x233: map_key_clear(KEY_SCROLLUP); break;
- case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
- case 0x238: map_rel(REL_HWHEEL); break;
- case 0x25f: map_key_clear(KEY_CANCEL); break;
- case 0x279: map_key_clear(KEY_REDO); break;
-
- case 0x289: map_key_clear(KEY_REPLY); break;
- case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
- case 0x28c: map_key_clear(KEY_SEND); break;
-
- default: goto ignore;
+ case 0x32: /* InRange */
+ switch (field->physical & 0xff) {
+ case 0x21: map_key(BTN_TOOL_MOUSE); break;
+ case 0x22: map_key(BTN_TOOL_FINGER); break;
+ default: map_key(BTN_TOOL_PEN); break;
}
break;
- case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
-
- set_bit(EV_REP, input->evbit);
- switch (usage->hid & HID_USAGE) {
- case 0x021: map_key_clear(KEY_PRINT); break;
- case 0x070: map_key_clear(KEY_HP); break;
- case 0x071: map_key_clear(KEY_CAMERA); break;
- case 0x072: map_key_clear(KEY_SOUND); break;
- case 0x073: map_key_clear(KEY_QUESTION); break;
- case 0x080: map_key_clear(KEY_EMAIL); break;
- case 0x081: map_key_clear(KEY_CHAT); break;
- case 0x082: map_key_clear(KEY_SEARCH); break;
- case 0x083: map_key_clear(KEY_CONNECT); break;
- case 0x084: map_key_clear(KEY_FINANCE); break;
- case 0x085: map_key_clear(KEY_SPORT); break;
- case 0x086: map_key_clear(KEY_SHOP); break;
- default: goto ignore;
- }
+ case 0x3c: /* Invert */
+ map_key_clear(BTN_TOOL_RUBBER);
break;
- case HID_UP_MSVENDOR:
-
- goto ignore;
-
- case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- case 0x003:
- /* The fn key on Apple USB keyboards */
- map_key_clear(KEY_FN);
- hidinput_apple_setup(input);
- break;
+ case 0x33: /* Touch */
+ case 0x42: /* TipSwitch */
+ case 0x43: /* TipSwitch2 */
+ device->quirks &= ~HID_QUIRK_NOTOUCH;
+ map_key_clear(BTN_TOUCH);
+ break;
- default: goto ignore;
- }
+ case 0x44: /* BarrelSwitch */
+ map_key_clear(BTN_STYLUS);
break;
- case HID_UP_LOGIVENDOR:
+ default: goto unknown;
+ }
+ break;
+
+ case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
+ switch (usage->hid & HID_USAGE) {
+ case 0x000: goto ignore;
+ case 0x034: map_key_clear(KEY_SLEEP); break;
+ case 0x036: map_key_clear(BTN_MISC); break;
+
+ case 0x040: map_key_clear(KEY_MENU); break;
+ case 0x045: map_key_clear(KEY_RADIO); break;
+
+ case 0x083: map_key_clear(KEY_LAST); break;
+ case 0x088: map_key_clear(KEY_PC); break;
+ case 0x089: map_key_clear(KEY_TV); break;
+ case 0x08a: map_key_clear(KEY_WWW); break;
+ case 0x08b: map_key_clear(KEY_DVD); break;
+ case 0x08c: map_key_clear(KEY_PHONE); break;
+ case 0x08d: map_key_clear(KEY_PROGRAM); break;
+ case 0x08e: map_key_clear(KEY_VIDEOPHONE); break;
+ case 0x08f: map_key_clear(KEY_GAMES); break;
+ case 0x090: map_key_clear(KEY_MEMO); break;
+ case 0x091: map_key_clear(KEY_CD); break;
+ case 0x092: map_key_clear(KEY_VCR); break;
+ case 0x093: map_key_clear(KEY_TUNER); break;
+ case 0x094: map_key_clear(KEY_EXIT); break;
+ case 0x095: map_key_clear(KEY_HELP); break;
+ case 0x096: map_key_clear(KEY_TAPE); break;
+ case 0x097: map_key_clear(KEY_TV2); break;
+ case 0x098: map_key_clear(KEY_SAT); break;
+ case 0x09a: map_key_clear(KEY_PVR); break;
+
+ case 0x09c: map_key_clear(KEY_CHANNELUP); break;
+ case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
+ case 0x0a0: map_key_clear(KEY_VCR2); break;
+
+ case 0x0b0: map_key_clear(KEY_PLAY); break;
+ case 0x0b1: map_key_clear(KEY_PAUSE); break;
+ case 0x0b2: map_key_clear(KEY_RECORD); break;
+ case 0x0b3: map_key_clear(KEY_FASTFORWARD); break;
+ case 0x0b4: map_key_clear(KEY_REWIND); break;
+ case 0x0b5: map_key_clear(KEY_NEXTSONG); break;
+ case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
+ case 0x0b7: map_key_clear(KEY_STOPCD); break;
+ case 0x0b8: map_key_clear(KEY_EJECTCD); break;
+ case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break;
+
+ case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
+ case 0x0e0: map_abs_clear(ABS_VOLUME); break;
+ case 0x0e2: map_key_clear(KEY_MUTE); break;
+ case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
+ case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
+ case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
+
+ case 0x182: map_key_clear(KEY_BOOKMARKS); break;
+ case 0x183: map_key_clear(KEY_CONFIG); break;
+ case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
+ case 0x185: map_key_clear(KEY_EDITOR); break;
+ case 0x186: map_key_clear(KEY_SPREADSHEET); break;
+ case 0x187: map_key_clear(KEY_GRAPHICSEDITOR); break;
+ case 0x188: map_key_clear(KEY_PRESENTATION); break;
+ case 0x189: map_key_clear(KEY_DATABASE); break;
+ case 0x18a: map_key_clear(KEY_MAIL); break;
+ case 0x18b: map_key_clear(KEY_NEWS); break;
+ case 0x18c: map_key_clear(KEY_VOICEMAIL); break;
+ case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break;
+ case 0x18e: map_key_clear(KEY_CALENDAR); break;
+ case 0x191: map_key_clear(KEY_FINANCE); break;
+ case 0x192: map_key_clear(KEY_CALC); break;
+ case 0x194: map_key_clear(KEY_FILE); break;
+ case 0x196: map_key_clear(KEY_WWW); break;
+ case 0x19c: map_key_clear(KEY_LOGOFF); break;
+ case 0x19e: map_key_clear(KEY_COFFEE); break;
+ case 0x1a6: map_key_clear(KEY_HELP); break;
+ case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
+ case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
+ case 0x1b6: map_key_clear(KEY_MEDIA); break;
+ case 0x1b7: map_key_clear(KEY_SOUND); break;
+ case 0x1bc: map_key_clear(KEY_MESSENGER); break;
+ case 0x1bd: map_key_clear(KEY_INFO); break;
+ case 0x201: map_key_clear(KEY_NEW); break;
+ case 0x202: map_key_clear(KEY_OPEN); break;
+ case 0x203: map_key_clear(KEY_CLOSE); break;
+ case 0x204: map_key_clear(KEY_EXIT); break;
+ case 0x207: map_key_clear(KEY_SAVE); break;
+ case 0x208: map_key_clear(KEY_PRINT); break;
+ case 0x209: map_key_clear(KEY_PROPS); break;
+ case 0x21a: map_key_clear(KEY_UNDO); break;
+ case 0x21b: map_key_clear(KEY_COPY); break;
+ case 0x21c: map_key_clear(KEY_CUT); break;
+ case 0x21d: map_key_clear(KEY_PASTE); break;
+ case 0x21f: map_key_clear(KEY_FIND); break;
+ case 0x221: map_key_clear(KEY_SEARCH); break;
+ case 0x222: map_key_clear(KEY_GOTO); break;
+ case 0x223: map_key_clear(KEY_HOMEPAGE); break;
+ case 0x224: map_key_clear(KEY_BACK); break;
+ case 0x225: map_key_clear(KEY_FORWARD); break;
+ case 0x226: map_key_clear(KEY_STOP); break;
+ case 0x227: map_key_clear(KEY_REFRESH); break;
+ case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
+ case 0x22d: map_key_clear(KEY_ZOOMIN); break;
+ case 0x22e: map_key_clear(KEY_ZOOMOUT); break;
+ case 0x22f: map_key_clear(KEY_ZOOMRESET); break;
+ case 0x233: map_key_clear(KEY_SCROLLUP); break;
+ case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
+ case 0x238: map_rel(REL_HWHEEL); break;
+ case 0x25f: map_key_clear(KEY_CANCEL); break;
+ case 0x279: map_key_clear(KEY_REDO); break;
+
+ case 0x289: map_key_clear(KEY_REPLY); break;
+ case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
+ case 0x28c: map_key_clear(KEY_SEND); break;
+
+ default: goto ignore;
+ }
+ break;
+
+ case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
+ set_bit(EV_REP, input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x021: map_key_clear(KEY_PRINT); break;
+ case 0x070: map_key_clear(KEY_HP); break;
+ case 0x071: map_key_clear(KEY_CAMERA); break;
+ case 0x072: map_key_clear(KEY_SOUND); break;
+ case 0x073: map_key_clear(KEY_QUESTION); break;
+ case 0x080: map_key_clear(KEY_EMAIL); break;
+ case 0x081: map_key_clear(KEY_CHAT); break;
+ case 0x082: map_key_clear(KEY_SEARCH); break;
+ case 0x083: map_key_clear(KEY_CONNECT); break;
+ case 0x084: map_key_clear(KEY_FINANCE); break;
+ case 0x085: map_key_clear(KEY_SPORT); break;
+ case 0x086: map_key_clear(KEY_SHOP); break;
+ default: goto ignore;
+ }
+ break;
- goto ignore;
-
- case HID_UP_PID:
+ case HID_UP_MSVENDOR:
+ goto ignore;
- switch(usage->hid & HID_USAGE) {
- case 0xa4: map_key_clear(BTN_DEAD); break;
- default: goto ignore;
- }
- break;
+ case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
+ set_bit(EV_REP, input->evbit);
+ goto ignore;
- default:
- unknown:
- if (field->report_size == 1) {
- if (field->report->type == HID_OUTPUT_REPORT) {
- map_led(LED_MISC);
- break;
- }
- map_key(BTN_MISC);
- break;
- }
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- map_rel(REL_MISC);
+ case HID_UP_LOGIVENDOR:
+ goto ignore;
+
+ case HID_UP_PID:
+ switch (usage->hid & HID_USAGE) {
+ case 0xa4: map_key_clear(BTN_DEAD); break;
+ default: goto ignore;
+ }
+ break;
+
+ default:
+ unknown:
+ if (field->report_size == 1) {
+ if (field->report->type == HID_OUTPUT_REPORT) {
+ map_led(LED_MISC);
break;
}
- map_abs(ABS_MISC);
+ map_key(BTN_MISC);
+ break;
+ }
+ if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+ map_rel(REL_MISC);
break;
+ }
+ map_abs(ABS_MISC);
+ break;
}
mapped:
- if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
- if (usage->hid == HID_GD_Z)
- map_rel(REL_HWHEEL);
- else if (usage->code == BTN_1)
- map_key(BTN_2);
- else if (usage->code == BTN_2)
- map_key(BTN_1);
- }
-
- if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
- HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
- (usage->code == REL_WHEEL))
- set_bit(REL_HWHEEL, bit);
-
- if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
- || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
+ if (device->driver->input_mapped && device->driver->input_mapped(device,
+ hidinput, field, usage, &bit, &max) < 0)
goto ignore;
- if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) &&
- usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE))
- field->flags &= ~HID_MAIN_ITEM_RELATIVE;
-
set_bit(usage->type, input->evbit);
- if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
- (usage->type == EV_KEY ||
- usage->type == EV_REL ||
- usage->type == EV_ABS))
- clear_bit(usage->code, bit);
-
while (usage->code <= max && test_and_set_bit(usage->code, bit))
usage->code = find_next_zero_bit(bit, max + 1, usage->code);
@@ -858,10 +585,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
if (!usage->type)
return;
- /* handle input events for quirky devices */
- if (hidinput_event_quirks(hid, field, usage, value))
- return;
-
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
@@ -961,14 +684,14 @@ static int hidinput_open(struct input_dev *dev)
{
struct hid_device *hid = input_get_drvdata(dev);
- return hid->hid_open(hid);
+ return hid->ll_driver->open(hid);
}
static void hidinput_close(struct input_dev *dev)
{
struct hid_device *hid = input_get_drvdata(dev);
- hid->hid_close(hid);
+ hid->ll_driver->close(hid);
}
/*
@@ -977,7 +700,7 @@ static void hidinput_close(struct input_dev *dev)
* Read all reports and initialize the absolute field values.
*/
-int hidinput_connect(struct hid_device *hid)
+int hidinput_connect(struct hid_device *hid, unsigned int force)
{
struct hid_report *report;
struct hid_input *hidinput = NULL;
@@ -985,19 +708,20 @@ int hidinput_connect(struct hid_device *hid)
int i, j, k;
int max_report_type = HID_OUTPUT_REPORT;
- if (hid->quirks & HID_QUIRK_IGNORE_HIDINPUT)
- return -1;
-
INIT_LIST_HEAD(&hid->inputs);
- for (i = 0; i < hid->maxcollection; i++)
- if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
- hid->collection[i].type == HID_COLLECTION_PHYSICAL)
- if (IS_INPUT_APPLICATION(hid->collection[i].usage))
- break;
+ if (!force) {
+ for (i = 0; i < hid->maxcollection; i++) {
+ struct hid_collection *col = &hid->collection[i];
+ if (col->type == HID_COLLECTION_APPLICATION ||
+ col->type == HID_COLLECTION_PHYSICAL)
+ if (IS_INPUT_APPLICATION(col->usage))
+ break;
+ }
- if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
- return -1;
+ if (i == hid->maxcollection)
+ return -1;
+ }
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
max_report_type = HID_INPUT_REPORT;
@@ -1019,7 +743,8 @@ int hidinput_connect(struct hid_device *hid)
}
input_set_drvdata(input_dev, hid);
- input_dev->event = hid->hidinput_input_event;
+ input_dev->event =
+ hid->ll_driver->hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
input_dev->setkeycode = hidinput_setkeycode;
@@ -1032,7 +757,7 @@ int hidinput_connect(struct hid_device *hid)
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
- input_dev->dev.parent = hid->dev;
+ input_dev->dev.parent = hid->dev.parent;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
}
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
new file mode 100644
index 00000000000..406d8c82abf
--- /dev/null
+++ b/drivers/hid/hid-lg.c
@@ -0,0 +1,342 @@
+/*
+ * HID driver for some logitech "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+#include "hid-lg.h"
+
+#define LG_RDESC 0x001
+#define LG_BAD_RELATIVE_KEYS 0x002
+#define LG_DUPLICATE_USAGES 0x004
+#define LG_RESET_LEDS 0x008
+#define LG_EXPANDED_KEYMAP 0x010
+#define LG_IGNORE_DOUBLED_WHEEL 0x020
+#define LG_WIRELESS 0x040
+#define LG_INVERT_HWHEEL 0x080
+#define LG_NOGET 0x100
+#define LG_FF 0x200
+#define LG_FF2 0x400
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 &&
+ rdesc[84] == 0x8c && rdesc[85] == 0x02) {
+ dev_info(&hdev->dev, "fixing up Logitech keyboard report "
+ "descriptor\n");
+ rdesc[84] = rdesc[89] = 0x4d;
+ rdesc[85] = rdesc[90] = 0x10;
+ }
+}
+
+#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+
+static int lg_ultrax_remote_mapping(struct hid_input *hi,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+ return 0;
+
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ /* Reported on Logitech Ultra X Media Remote */
+ case 0x004: lg_map_key_clear(KEY_AGAIN); break;
+ case 0x00d: lg_map_key_clear(KEY_HOME); break;
+ case 0x024: lg_map_key_clear(KEY_SHUFFLE); break;
+ case 0x025: lg_map_key_clear(KEY_TV); break;
+ case 0x026: lg_map_key_clear(KEY_MENU); break;
+ case 0x031: lg_map_key_clear(KEY_AUDIO); break;
+ case 0x032: lg_map_key_clear(KEY_TEXT); break;
+ case 0x033: lg_map_key_clear(KEY_LAST); break;
+ case 0x047: lg_map_key_clear(KEY_MP3); break;
+ case 0x048: lg_map_key_clear(KEY_DVD); break;
+ case 0x049: lg_map_key_clear(KEY_MEDIA); break;
+ case 0x04a: lg_map_key_clear(KEY_VIDEO); break;
+ case 0x04b: lg_map_key_clear(KEY_ANGLE); break;
+ case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break;
+ case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break;
+ case 0x051: lg_map_key_clear(KEY_RED); break;
+ case 0x052: lg_map_key_clear(KEY_CLOSE); break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x1001: lg_map_key_clear(KEY_MESSENGER); break;
+ case 0x1003: lg_map_key_clear(KEY_SOUND); break;
+ case 0x1004: lg_map_key_clear(KEY_VIDEO); break;
+ case 0x1005: lg_map_key_clear(KEY_AUDIO); break;
+ case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break;
+ case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break;
+ case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break;
+ case 0x1013: lg_map_key_clear(KEY_CAMERA); break;
+ case 0x1014: lg_map_key_clear(KEY_MESSENGER); break;
+ case 0x1015: lg_map_key_clear(KEY_RECORD); break;
+ case 0x1016: lg_map_key_clear(KEY_PLAYER); break;
+ case 0x1017: lg_map_key_clear(KEY_EJECTCD); break;
+ case 0x1018: lg_map_key_clear(KEY_MEDIA); break;
+ case 0x1019: lg_map_key_clear(KEY_PROG1); break;
+ case 0x101a: lg_map_key_clear(KEY_PROG2); break;
+ case 0x101b: lg_map_key_clear(KEY_PROG3); break;
+ case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break;
+ case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break;
+ case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break;
+ case 0x1023: lg_map_key_clear(KEY_CLOSE); break;
+ case 0x1027: lg_map_key_clear(KEY_MENU); break;
+ /* this one is marked as 'Rotate' */
+ case 0x1028: lg_map_key_clear(KEY_ANGLE); break;
+ case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break;
+ case 0x102a: lg_map_key_clear(KEY_BACK); break;
+ case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
+ case 0x1041: lg_map_key_clear(KEY_BATTERY); break;
+ case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break;
+ case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break;
+ case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break;
+ case 0x1045: lg_map_key_clear(KEY_UNDO); break;
+ case 0x1046: lg_map_key_clear(KEY_REDO); break;
+ case 0x1047: lg_map_key_clear(KEY_PRINT); break;
+ case 0x1048: lg_map_key_clear(KEY_SAVE); break;
+ case 0x1049: lg_map_key_clear(KEY_PROG1); break;
+ case 0x104a: lg_map_key_clear(KEY_PROG2); break;
+ case 0x104b: lg_map_key_clear(KEY_PROG3); break;
+ case 0x104c: lg_map_key_clear(KEY_PROG4); break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ /* extended mapping for certain Logitech hardware (Logitech cordless
+ desktop LX500) */
+ static const u8 e_keymap[] = {
+ 0,216, 0,213,175,156, 0, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
+ 174,167,152,161,112, 0, 0, 0,154, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,183,184,185,186,187,
+ 188,189,190,191,192,193,194, 0, 0, 0
+ };
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ unsigned int hid = usage->hid;
+
+ if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
+ lg_ultrax_remote_mapping(hi, usage, bit, max))
+ return 1;
+
+ if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
+ return 1;
+
+ if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+ return 0;
+
+ hid &= HID_USAGE;
+
+ /* Special handling for Logitech Cordless Desktop */
+ if (field->application == HID_GD_MOUSE) {
+ if ((quirks & LG_IGNORE_DOUBLED_WHEEL) &&
+ (hid == 7 || hid == 8))
+ return -1;
+ } else {
+ if ((quirks & LG_EXPANDED_KEYMAP) &&
+ hid < ARRAY_SIZE(e_keymap) &&
+ e_keymap[hid] != 0) {
+ hid_map_usage(hi, usage, bit, max, EV_KEY,
+ e_keymap[hid]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
+ (field->flags & HID_MAIN_ITEM_RELATIVE))
+ field->flags &= ~HID_MAIN_ITEM_RELATIVE;
+
+ if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
+ usage->type == EV_REL || usage->type == EV_ABS))
+ clear_bit(usage->code, *bit);
+
+ return 0;
+}
+
+static int lg_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
+ input_event(field->hidinput->input, usage->type, usage->code,
+ -value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ unsigned long quirks = id->driver_data;
+ unsigned int connect_mask = HID_CONNECT_DEFAULT;
+ int ret;
+
+ hid_set_drvdata(hdev, (void *)quirks);
+
+ if (quirks & LG_NOGET)
+ hdev->quirks |= HID_QUIRK_NOGET;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ if (quirks & (LG_FF | LG_FF2))
+ connect_mask &= ~HID_CONNECT_FF;
+
+ ret = hid_hw_start(hdev, connect_mask);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ if (quirks & LG_RESET_LEDS)
+ usbhid_set_leds(hdev);
+
+ if (quirks & LG_FF)
+ lgff_init(hdev);
+ if (quirks & LG_FF2)
+ lg2ff_init(hdev);
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id lg_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
+ .driver_data = LG_RDESC | LG_WIRELESS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
+ .driver_data = LG_RDESC | LG_WIRELESS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
+ .driver_data = LG_RDESC | LG_WIRELESS },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
+ .driver_data = LG_BAD_RELATIVE_KEYS },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
+ .driver_data = LG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
+ .driver_data = LG_DUPLICATE_USAGES },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
+ .driver_data = LG_DUPLICATE_USAGES },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
+ .driver_data = LG_RESET_LEDS },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
+ .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
+ .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3),
+ .driver_data = LG_INVERT_HWHEEL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150),
+ .driver_data = LG_INVERT_HWHEEL },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
+ .driver_data = LG_NOGET },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
+ .driver_data = LG_NOGET | LG_FF },
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
+ .driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
+ .driver_data = LG_FF2 },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, lg_devices);
+
+static struct hid_driver lg_driver = {
+ .name = "logitech",
+ .id_table = lg_devices,
+ .report_fixup = lg_report_fixup,
+ .input_mapping = lg_input_mapping,
+ .input_mapped = lg_input_mapped,
+ .event = lg_event,
+ .probe = lg_probe,
+};
+
+static int lg_init(void)
+{
+ return hid_register_driver(&lg_driver);
+}
+
+static void lg_exit(void)
+{
+ hid_unregister_driver(&lg_driver);
+}
+
+module_init(lg_init);
+module_exit(lg_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(logitech);
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
new file mode 100644
index 00000000000..27ae750ca87
--- /dev/null
+++ b/drivers/hid/hid-lg.h
@@ -0,0 +1,18 @@
+#ifndef __HID_LG_H
+#define __HID_LG_H
+
+#include <linux/autoconf.h>
+
+#ifdef CONFIG_LOGITECH_FF
+int lgff_init(struct hid_device *hdev);
+#else
+static inline int lgff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#ifdef CONFIG_LOGIRUMBLEPAD2_FF
+int lg2ff_init(struct hid_device *hdev);
+#else
+static inline int lg2ff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
index d469bd0061c..4e6dc6e2652 100644
--- a/drivers/hid/usbhid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -24,7 +24,9 @@
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
-#include "usbhid.h"
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
struct lg2ff_device {
struct hid_report *report;
@@ -57,7 +59,7 @@ static int play_effect(struct input_dev *dev, void *data,
return 0;
}
-int hid_lg2ff_init(struct hid_device *hid)
+int lg2ff_init(struct hid_device *hid)
{
struct lg2ff_device *lg2ff;
struct hid_report *report;
@@ -69,18 +71,18 @@ int hid_lg2ff_init(struct hid_device *hid)
int error;
if (list_empty(report_list)) {
- printk(KERN_ERR "hid-lg2ff: no output report found\n");
+ dev_err(&hid->dev, "no output report found\n");
return -ENODEV;
}
report = list_entry(report_list->next, struct hid_report, list);
if (report->maxfield < 1) {
- printk(KERN_ERR "hid-lg2ff: output report is empty\n");
+ dev_err(&hid->dev, "output report is empty\n");
return -ENODEV;
}
if (report->field[0]->report_count < 7) {
- printk(KERN_ERR "hid-lg2ff: not enough values in the field\n");
+ dev_err(&hid->dev, "not enough values in the field\n");
return -ENODEV;
}
@@ -107,7 +109,7 @@ int hid_lg2ff_init(struct hid_device *hid)
usbhid_submit_report(hid, report, USB_DIR_OUT);
- printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
+ dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by "
"Anssi Hannula <anssi.hannula@gmail.com>\n");
return 0;
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/hid-lgff.c
index 4b7ab6a46d9..51aff08e10c 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -30,7 +30,9 @@
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
-#include "usbhid.h"
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
struct dev_type {
u16 idVendor;
@@ -48,6 +50,12 @@ static const signed short ff_joystick[] = {
-1
};
+static const signed short ff_wheel[] = {
+ FF_CONSTANT,
+ FF_AUTOCENTER,
+ -1
+};
+
static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble },
@@ -55,7 +63,7 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc286, ff_joystick },
{ 0x046d, 0xc294, ff_joystick },
{ 0x046d, 0xc295, ff_joystick },
- { 0x046d, 0xca03, ff_joystick },
+ { 0x046d, 0xca03, ff_wheel },
};
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
@@ -100,7 +108,24 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
return 0;
}
-int hid_lgff_init(struct hid_device* hid)
+static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ __s32 *value = report->field[0]->value;
+ magnitude = (magnitude >> 12) & 0xf;
+ *value++ = 0xfe;
+ *value++ = 0x0d;
+ *value++ = magnitude; /* clockwise strength */
+ *value++ = magnitude; /* counter-clockwise strength */
+ *value++ = 0x80;
+ *value++ = 0x00;
+ *value = 0x00;
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+int lgff_init(struct hid_device* hid)
{
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -145,6 +170,9 @@ int hid_lgff_init(struct hid_device* hid)
if (error)
return error;
+ if ( test_bit(FF_AUTOCENTER, dev->ffbit) )
+ dev->ff->set_autocenter = hid_lgff_set_autocenter;
+
printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
return 0;
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
new file mode 100644
index 00000000000..d718b1607d0
--- /dev/null
+++ b/drivers/hid/hid-microsoft.c
@@ -0,0 +1,219 @@
+/*
+ * HID driver for some microsoft "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define MS_HIDINPUT 0x01
+#define MS_ERGONOMY 0x02
+#define MS_PRESENTER 0x04
+#define MS_RDESC 0x08
+#define MS_NOGET 0x10
+
+/*
+ * Microsoft Wireless Desktop Receiver (Model 1028) has several
+ * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+ */
+static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((quirks & MS_RDESC) && rsize == 571 && rdesc[284] == 0x19 &&
+ rdesc[286] == 0x2a && rdesc[304] == 0x19 &&
+ rdesc[306] == 0x29 && rdesc[352] == 0x1a &&
+ rdesc[355] == 0x2a && rdesc[557] == 0x19 &&
+ rdesc[559] == 0x29) {
+ dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
+ "Model 1028 report descriptor\n");
+ rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
+ rdesc[352] = 0x36;
+ rdesc[286] = rdesc[355] = 0x46;
+ rdesc[306] = rdesc[559] = 0x45;
+ }
+}
+
+#define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct input_dev *input = hi->input;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0xfd06: ms_map_key_clear(KEY_CHAT); break;
+ case 0xfd07: ms_map_key_clear(KEY_PHONE); break;
+ case 0xff05:
+ set_bit(EV_REP, input->evbit);
+ ms_map_key_clear(KEY_F13);
+ set_bit(KEY_F14, input->keybit);
+ set_bit(KEY_F15, input->keybit);
+ set_bit(KEY_F16, input->keybit);
+ set_bit(KEY_F17, input->keybit);
+ set_bit(KEY_F18, input->keybit);
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0xfd08: ms_map_key_clear(KEY_FORWARD); break;
+ case 0xfd09: ms_map_key_clear(KEY_BACK); break;
+ case 0xfd0b: ms_map_key_clear(KEY_PLAYPAUSE); break;
+ case 0xfd0e: ms_map_key_clear(KEY_CLOSE); break;
+ case 0xfd0f: ms_map_key_clear(KEY_PLAY); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+ return 0;
+
+ if (quirks & MS_ERGONOMY) {
+ int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
+ if (ret)
+ return ret;
+ }
+
+ if ((quirks & MS_PRESENTER) &&
+ ms_presenter_8k_quirk(hi, usage, bit, max))
+ return 1;
+
+ return 0;
+}
+
+static int ms_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ /* Handling MS keyboards special buttons */
+ if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
+ struct input_dev *input = field->hidinput->input;
+ static unsigned int last_key = 0;
+ unsigned int key = 0;
+ switch (value) {
+ case 0x01: key = KEY_F14; break;
+ case 0x02: key = KEY_F15; break;
+ case 0x04: key = KEY_F16; break;
+ case 0x08: key = KEY_F17; break;
+ case 0x10: key = KEY_F18; break;
+ }
+ if (key) {
+ input_event(input, usage->type, key, 1);
+ last_key = key;
+ } else
+ input_event(input, usage->type, last_key, 0);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ unsigned long quirks = id->driver_data;
+ int ret;
+
+ hid_set_drvdata(hdev, (void *)quirks);
+
+ if (quirks & MS_NOGET)
+ hdev->quirks |= HID_QUIRK_NOGET;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
+ HID_CONNECT_HIDINPUT_FORCE : 0));
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id ms_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
+ .driver_data = MS_HIDINPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
+ .driver_data = MS_ERGONOMY },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K),
+ .driver_data = MS_ERGONOMY | MS_RDESC },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
+ .driver_data = MS_PRESENTER },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
+ .driver_data = MS_NOGET },
+
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
+ .driver_data = MS_PRESENTER },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ms_devices);
+
+static struct hid_driver ms_driver = {
+ .name = "microsoft",
+ .id_table = ms_devices,
+ .report_fixup = ms_report_fixup,
+ .input_mapping = ms_input_mapping,
+ .event = ms_event,
+ .probe = ms_probe,
+};
+
+static int ms_init(void)
+{
+ return hid_register_driver(&ms_driver);
+}
+
+static void ms_exit(void)
+{
+ hid_unregister_driver(&ms_driver);
+}
+
+module_init(ms_init);
+module_exit(ms_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(microsoft);
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c
new file mode 100644
index 00000000000..f3a85a065f1
--- /dev/null
+++ b/drivers/hid/hid-monterey.c
@@ -0,0 +1,82 @@
+/*
+ * HID driver for some monterey "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
+ dev_info(&hdev->dev, "fixing up button/consumer in HID report "
+ "descriptor\n");
+ rdesc[30] = 0x0c;
+ }
+}
+
+#define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int mr_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x156: mr_map_key_clear(KEY_WORDPROCESSOR); break;
+ case 0x157: mr_map_key_clear(KEY_SPREADSHEET); break;
+ case 0x158: mr_map_key_clear(KEY_PRESENTATION); break;
+ case 0x15c: mr_map_key_clear(KEY_STOP); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static const struct hid_device_id mr_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, mr_devices);
+
+static struct hid_driver mr_driver = {
+ .name = "monterey",
+ .id_table = mr_devices,
+ .report_fixup = mr_report_fixup,
+ .input_mapping = mr_input_mapping,
+};
+
+static int mr_init(void)
+{
+ return hid_register_driver(&mr_driver);
+}
+
+static void mr_exit(void)
+{
+ hid_unregister_driver(&mr_driver);
+}
+
+module_init(mr_init);
+module_exit(mr_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(monterey);
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c
new file mode 100644
index 00000000000..10945fe12d5
--- /dev/null
+++ b/drivers/hid/hid-petalynx.c
@@ -0,0 +1,122 @@
+/*
+ * HID driver for some petalynx "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
+ rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
+ rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
+ dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
+ "descriptor\n");
+ rdesc[60] = 0xfa;
+ rdesc[40] = 0xfa;
+ }
+}
+
+#define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int pl_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR) {
+ switch (usage->hid & HID_USAGE) {
+ case 0x05a: pl_map_key_clear(KEY_TEXT); break;
+ case 0x05b: pl_map_key_clear(KEY_RED); break;
+ case 0x05c: pl_map_key_clear(KEY_GREEN); break;
+ case 0x05d: pl_map_key_clear(KEY_YELLOW); break;
+ case 0x05e: pl_map_key_clear(KEY_BLUE); break;
+ default:
+ return 0;
+ }
+ return 1;
+ }
+
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
+ switch (usage->hid & HID_USAGE) {
+ case 0x0f6: pl_map_key_clear(KEY_NEXT); break;
+ case 0x0fa: pl_map_key_clear(KEY_BACK); break;
+ default:
+ return 0;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ hdev->quirks |= HID_QUIRK_NOGET;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id pl_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, pl_devices);
+
+static struct hid_driver pl_driver = {
+ .name = "petalynx",
+ .id_table = pl_devices,
+ .report_fixup = pl_report_fixup,
+ .input_mapping = pl_input_mapping,
+ .probe = pl_probe,
+};
+
+static int pl_init(void)
+{
+ return hid_register_driver(&pl_driver);
+}
+
+static void pl_exit(void)
+{
+ hid_unregister_driver(&pl_driver);
+}
+
+module_init(pl_init);
+module_exit(pl_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(petalynx);
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/hid-pl.c
index 9eb83cf9d22..acd81558618 100644
--- a/drivers/hid/usbhid/hid-plff.c
+++ b/drivers/hid/hid-pl.c
@@ -9,7 +9,7 @@
* - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT)
*
* 0e8f:0003 "GreenAsia Inc. USB Joystick "
- * - tested with Köng Gaming gamepad
+ * - tested with K??ng Gaming gamepad
*
* Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
*/
@@ -38,7 +38,11 @@
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
-#include "usbhid.h"
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_PANTHERLORD_FF
+#include "usbhid/usbhid.h"
struct plff_device {
struct hid_report *report;
@@ -66,7 +70,7 @@ static int hid_plff_play(struct input_dev *dev, void *data,
return 0;
}
-int hid_plff_init(struct hid_device *hid)
+static int plff_init(struct hid_device *hid)
{
struct plff_device *plff;
struct hid_report *report;
@@ -86,7 +90,7 @@ int hid_plff_init(struct hid_device *hid)
currently unknown. */
if (list_empty(report_list)) {
- printk(KERN_ERR "hid-plff: no output reports found\n");
+ dev_err(&hid->dev, "no output reports found\n");
return -ENODEV;
}
@@ -95,18 +99,19 @@ int hid_plff_init(struct hid_device *hid)
report_ptr = report_ptr->next;
if (report_ptr == report_list) {
- printk(KERN_ERR "hid-plff: required output report is missing\n");
+ dev_err(&hid->dev, "required output report is "
+ "missing\n");
return -ENODEV;
}
report = list_entry(report_ptr, struct hid_report, list);
if (report->maxfield < 1) {
- printk(KERN_ERR "hid-plff: no fields in the report\n");
+ dev_err(&hid->dev, "no fields in the report\n");
return -ENODEV;
}
if (report->field[0]->report_count < 4) {
- printk(KERN_ERR "hid-plff: not enough values in the field\n");
+ dev_err(&hid->dev, "not enough values in the field\n");
return -ENODEV;
}
@@ -132,8 +137,70 @@ int hid_plff_init(struct hid_device *hid)
usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
}
- printk(KERN_INFO "hid-plff: Force feedback for PantherLord/GreenAsia "
+ dev_info(&hid->dev, "Force feedback for PantherLord/GreenAsia "
"devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
return 0;
}
+#else
+static inline int plff_init(struct hid_device *hid)
+{
+ return 0;
+}
+#endif
+
+static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ if (id->driver_data)
+ hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ plff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id pl_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR),
+ .driver_data = 1 }, /* Twin USB Joystick */
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */
+ { }
+};
+MODULE_DEVICE_TABLE(hid, pl_devices);
+
+static struct hid_driver pl_driver = {
+ .name = "pantherlord",
+ .id_table = pl_devices,
+ .probe = pl_probe,
+};
+
+static int pl_init(void)
+{
+ return hid_register_driver(&pl_driver);
+}
+
+static void pl_exit(void)
+{
+ hid_unregister_driver(&pl_driver);
+}
+
+module_init(pl_init);
+module_exit(pl_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(pantherlord);
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c
new file mode 100644
index 00000000000..15f3c049245
--- /dev/null
+++ b/drivers/hid/hid-samsung.c
@@ -0,0 +1,100 @@
+/*
+ * HID driver for some samsung "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * Samsung IrDA remote controller (reports as Cypress USB Mouse).
+ *
+ * Vendor specific report #4 has a size of 48 bit,
+ * and therefore is not accepted when inspecting the descriptors.
+ * As a workaround we reinterpret the report as:
+ * Variable type, count 6, size 8 bit, log. maximum 255
+ * The burden to reconstruct the data is moved into user space.
+ */
+static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ if (rsize >= 182 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
+ rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
+ rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
+ rdesc[182] == 0x40) {
+ dev_info(&hdev->dev, "fixing up Samsung IrDA report "
+ "descriptor\n");
+ rdesc[176] = 0xff;
+ rdesc[178] = 0x08;
+ rdesc[180] = 0x06;
+ rdesc[182] = 0x42;
+ }
+}
+
+static int samsung_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, (HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT) |
+ HID_CONNECT_HIDDEV_FORCE);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id samsung_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, samsung_devices);
+
+static struct hid_driver samsung_driver = {
+ .name = "samsung",
+ .id_table = samsung_devices,
+ .report_fixup = samsung_report_fixup,
+ .probe = samsung_probe,
+};
+
+static int samsung_init(void)
+{
+ return hid_register_driver(&samsung_driver);
+}
+
+static void samsung_exit(void)
+{
+ hid_unregister_driver(&samsung_driver);
+}
+
+module_init(samsung_init);
+module_exit(samsung_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(samsung);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
new file mode 100644
index 00000000000..3af8095a7de
--- /dev/null
+++ b/drivers/hid/hid-sony.c
@@ -0,0 +1,110 @@
+/*
+ * HID driver for some sony "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+/*
+ * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
+ * to "operational". Without this, the ps3 controller will not report any
+ * events.
+ */
+static int sony_set_operational(struct hid_device *hdev)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+ int ret;
+ char *buf = kmalloc(18, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_DIR_IN | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE,
+ (3 << 8) | 0xf2, ifnum, buf, 17,
+ USB_CTRL_GET_TIMEOUT);
+ if (ret < 0)
+ dev_err(&hdev->dev, "can't set operational mode\n");
+
+ kfree(buf);
+
+ return ret;
+}
+
+static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
+ HID_CONNECT_HIDDEV_FORCE);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+ ret = sony_set_operational(hdev);
+ if (ret)
+ goto err_stop;
+
+ return 0;
+err_stop:
+ hid_hw_stop(hdev);
+err_free:
+ return ret;
+}
+
+static const struct hid_device_id sony_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, sony_devices);
+
+static struct hid_driver sony_driver = {
+ .name = "sony",
+ .id_table = sony_devices,
+ .probe = sony_probe,
+};
+
+static int sony_init(void)
+{
+ return hid_register_driver(&sony_driver);
+}
+
+static void sony_exit(void)
+{
+ hid_unregister_driver(&sony_driver);
+}
+
+module_init(sony_init);
+module_exit(sony_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(sony);
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c
new file mode 100644
index 00000000000..5ba68f7dbb7
--- /dev/null
+++ b/drivers/hid/hid-sunplus.c
@@ -0,0 +1,82 @@
+/*
+ * HID driver for some sunplus "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int rsize)
+{
+ if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
+ rdesc[106] == 0x03) {
+ dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop "
+ "report descriptor\n");
+ rdesc[105] = rdesc[110] = 0x03;
+ rdesc[106] = rdesc[111] = 0x21;
+ }
+}
+
+#define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int sp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x2003: sp_map_key_clear(KEY_ZOOMIN); break;
+ case 0x2103: sp_map_key_clear(KEY_ZOOMOUT); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static const struct hid_device_id sp_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, sp_devices);
+
+static struct hid_driver sp_driver = {
+ .name = "sunplus",
+ .id_table = sp_devices,
+ .report_fixup = sp_report_fixup,
+ .input_mapping = sp_input_mapping,
+};
+
+static int sp_init(void)
+{
+ return hid_register_driver(&sp_driver);
+}
+
+static void sp_exit(void)
+{
+ hid_unregister_driver(&sp_driver);
+}
+
+module_init(sp_init);
+module_exit(sp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(sunplus);
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/hid-tmff.c
index 144578b1a00..1b7cba0f7e1 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -27,23 +27,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/hid.h>
#include <linux/input.h>
-
-#undef DEBUG
#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
+#include "hid-ids.h"
+
+#include "usbhid/usbhid.h"
/* Usages for thrustmaster devices I know about */
#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
-struct dev_type {
- u16 idVendor;
- u16 idProduct;
- const signed short *ff;
-};
-
static const signed short ff_rumble[] = {
FF_RUMBLE,
-1
@@ -54,21 +48,13 @@ static const signed short ff_joystick[] = {
-1
};
-static const struct dev_type devices[] = {
- { 0x44f, 0xb300, ff_rumble },
- { 0x44f, 0xb304, ff_rumble },
- { 0x44f, 0xb651, ff_rumble }, /* FGT Rumble Force Wheel */
- { 0x44f, 0xb654, ff_joystick }, /* FGT Force Feedback Wheel */
-};
-
struct tmff_device {
struct hid_report *report;
struct hid_field *ff_field;
};
/* Changes values from 0 to 0xffff into values from minimum to maximum */
-static inline int hid_tmff_scale_u16(unsigned int in,
- int minimum, int maximum)
+static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
{
int ret;
@@ -81,8 +67,7 @@ static inline int hid_tmff_scale_u16(unsigned int in,
}
/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
-static inline int hid_tmff_scale_s8(int in,
- int minimum, int maximum)
+static inline int tmff_scale_s8(int in, int minimum, int maximum)
{
int ret;
@@ -94,7 +79,8 @@ static inline int hid_tmff_scale_s8(int in,
return ret;
}
-static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+static int tmff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
{
struct hid_device *hid = input_get_drvdata(dev);
struct tmff_device *tmff = data;
@@ -104,10 +90,10 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
switch (effect->type) {
case FF_CONSTANT:
- x = hid_tmff_scale_s8(effect->u.ramp.start_level,
+ x = tmff_scale_s8(effect->u.ramp.start_level,
ff_field->logical_minimum,
ff_field->logical_maximum);
- y = hid_tmff_scale_s8(effect->u.ramp.end_level,
+ y = tmff_scale_s8(effect->u.ramp.end_level,
ff_field->logical_minimum,
ff_field->logical_maximum);
@@ -118,10 +104,10 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
break;
case FF_RUMBLE:
- left = hid_tmff_scale_u16(effect->u.rumble.weak_magnitude,
+ left = tmff_scale_u16(effect->u.rumble.weak_magnitude,
ff_field->logical_minimum,
ff_field->logical_maximum);
- right = hid_tmff_scale_u16(effect->u.rumble.strong_magnitude,
+ right = tmff_scale_u16(effect->u.rumble.strong_magnitude,
ff_field->logical_minimum,
ff_field->logical_maximum);
@@ -134,14 +120,14 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
return 0;
}
-int hid_tmff_init(struct hid_device *hid)
+static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
{
struct tmff_device *tmff;
struct hid_report *report;
struct list_head *report_list;
- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+ struct hid_input, list);
struct input_dev *input_dev = hidinput->input;
- const signed short *ff_bits = ff_joystick;
int error;
int i;
@@ -163,63 +149,121 @@ int hid_tmff_init(struct hid_device *hid)
switch (field->usage[0].hid) {
case THRUSTMASTER_USAGE_FF:
if (field->report_count < 2) {
- warn("ignoring FF field with report_count < 2");
+ dev_warn(&hid->dev, "ignoring FF field "
+ "with report_count < 2\n");
continue;
}
- if (field->logical_maximum == field->logical_minimum) {
- warn("ignoring FF field with logical_maximum == logical_minimum");
+ if (field->logical_maximum ==
+ field->logical_minimum) {
+ dev_warn(&hid->dev, "ignoring FF field "
+ "with logical_maximum "
+ "== logical_minimum\n");
continue;
}
if (tmff->report && tmff->report != report) {
- warn("ignoring FF field in other report");
+ dev_warn(&hid->dev, "ignoring FF field "
+ "in other report\n");
continue;
}
if (tmff->ff_field && tmff->ff_field != field) {
- warn("ignoring duplicate FF field");
+ dev_warn(&hid->dev, "ignoring "
+ "duplicate FF field\n");
continue;
}
tmff->report = report;
tmff->ff_field = field;
- for (i = 0; i < ARRAY_SIZE(devices); i++) {
- if (input_dev->id.vendor == devices[i].idVendor &&
- input_dev->id.product == devices[i].idProduct) {
- ff_bits = devices[i].ff;
- break;
- }
- }
-
for (i = 0; ff_bits[i] >= 0; i++)
set_bit(ff_bits[i], input_dev->ffbit);
break;
default:
- warn("ignoring unknown output usage %08x", field->usage[0].hid);
+ dev_warn(&hid->dev, "ignoring unknown output "
+ "usage %08x\n",
+ field->usage[0].hid);
continue;
}
}
}
if (!tmff->report) {
- err("cant find FF field in output reports\n");
+ dev_err(&hid->dev, "can't find FF field in output reports\n");
error = -ENODEV;
goto fail;
}
- error = input_ff_create_memless(input_dev, tmff, hid_tmff_play);
+ error = input_ff_create_memless(input_dev, tmff, tmff_play);
if (error)
goto fail;
- info("Force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>");
+ dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx "
+ "Verituse <zinx@epicsol.org>");
return 0;
- fail:
+fail:
kfree(tmff);
return error;
}
+static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ tmff_init(hdev, (void *)id->driver_data);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id tm_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300),
+ .driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),
+ .driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651), /* FGT Rumble Force Wheel */
+ .driver_data = (unsigned long)ff_rumble },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654), /* FGT Force Feedback Wheel */
+ .driver_data = (unsigned long)ff_joystick },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, tm_devices);
+
+static struct hid_driver tm_driver = {
+ .name = "thrustmaster",
+ .id_table = tm_devices,
+ .probe = tm_probe,
+};
+
+static int tm_init(void)
+{
+ return hid_register_driver(&tm_driver);
+}
+
+static void tm_exit(void)
+{
+ hid_unregister_driver(&tm_driver);
+}
+
+module_init(tm_init);
+module_exit(tm_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(thrustmaster);
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/hid-zpff.c
index 5a688274f6a..ea82f3718b2 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/hid-zpff.c
@@ -21,16 +21,19 @@
*/
+#include <linux/hid.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
+
+#include "hid-ids.h"
+
+#include "usbhid/usbhid.h"
struct zpff_device {
struct hid_report *report;
};
-static int hid_zpff_play(struct input_dev *dev, void *data,
+static int zpff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct hid_device *hid = input_get_drvdata(dev);
@@ -58,7 +61,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
return 0;
}
-int hid_zpff_init(struct hid_device *hid)
+static int zpff_init(struct hid_device *hid)
{
struct zpff_device *zpff;
struct hid_report *report;
@@ -70,14 +73,14 @@ int hid_zpff_init(struct hid_device *hid)
int error;
if (list_empty(report_list)) {
- printk(KERN_ERR "hid-zpff: no output report found\n");
+ dev_err(&hid->dev, "no output report found\n");
return -ENODEV;
}
report = list_entry(report_list->next, struct hid_report, list);
if (report->maxfield < 4) {
- printk(KERN_ERR "hid-zpff: not enough fields in report\n");
+ dev_err(&hid->dev, "not enough fields in report\n");
return -ENODEV;
}
@@ -87,7 +90,7 @@ int hid_zpff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, zpff, hid_zpff_play);
+ error = input_ff_create_memless(dev, zpff, zpff_play);
if (error) {
kfree(zpff);
return error;
@@ -100,8 +103,60 @@ int hid_zpff_init(struct hid_device *hid)
zpff->report->field[3]->value[0] = 0x00;
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
- printk(KERN_INFO "Force feedback for Zeroplus based devices by "
+ dev_info(&hid->dev, "force feedback for Zeroplus based devices by "
"Anssi Hannula <anssi.hannula@gmail.com>\n");
return 0;
}
+
+static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ zpff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id zp_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, zp_devices);
+
+static struct hid_driver zp_driver = {
+ .name = "zeroplus",
+ .id_table = zp_devices,
+ .probe = zp_probe,
+};
+
+static int zp_init(void)
+{
+ return hid_register_driver(&zp_driver);
+}
+
+static void zp_exit(void)
+{
+ hid_unregister_driver(&zp_driver);
+}
+
+module_init(zp_init);
+module_exit(zp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(zeroplus);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index c40f0403eda..af3edb98df4 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -113,7 +113,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
if (!dev->hid_output_raw_report)
return -ENODEV;
- if (count > HID_MIN_BUFFER_SIZE) {
+ if (count > HID_MAX_BUFFER_SIZE) {
printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
task_pid_nr(current));
return -EINVAL;
@@ -181,7 +181,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
dev = hidraw_table[minor];
if (!dev->open++)
- dev->hid->hid_open(dev->hid);
+ dev->hid->ll_driver->open(dev->hid);
out_unlock:
spin_unlock(&minors_lock);
@@ -207,7 +207,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
dev = hidraw_table[minor];
if (!dev->open--) {
if (list->hidraw->exist)
- dev->hid->hid_close(dev->hid);
+ dev->hid->ll_driver->close(dev->hid);
else
kfree(list->hidraw);
}
@@ -326,9 +326,8 @@ int hidraw_connect(struct hid_device *hid)
goto out;
}
- dev->dev = device_create_drvdata(hidraw_class, NULL,
- MKDEV(hidraw_major, minor), NULL,
- "%s%d", "hidraw", minor);
+ dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+ NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
spin_lock(&minors_lock);
@@ -367,7 +366,7 @@ void hidraw_disconnect(struct hid_device *hid)
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
if (hidraw->open) {
- hid->hid_close(hid);
+ hid->ll_driver->close(hid);
wake_up_interruptible(&hidraw->wait);
} else {
kfree(hidraw);
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 18f09104765..5d9aa95fc3e 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -24,88 +24,13 @@ config USB_HID
comment "Input core support is needed for USB HID input layer or HIDBP support"
depends on USB_HID && INPUT=n
-config USB_HIDINPUT_POWERBOOK
- bool "Enable support for Apple laptop/aluminum USB special keys"
- default n
- depends on USB_HID
- help
- Say Y here if you want support for the special keys (Fn, Numlock) on
- Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
- keyboards.
-
- If unsure, say N.
-
-config HID_FF
- bool "Force feedback support (EXPERIMENTAL)"
- depends on USB_HID && EXPERIMENTAL
- help
- Say Y here is you want force feedback support for a few HID devices.
- See below for a list of supported devices.
-
- See <file:Documentation/input/ff.txt> for a description of the force
- feedback API.
-
- If unsure, say N.
-
config HID_PID
bool "PID device support"
- depends on HID_FF
help
Say Y here if you have a PID-compliant device and wish to enable force
feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such
devices.
-config LOGITECH_FF
- bool "Logitech devices support"
- depends on HID_FF
- select INPUT_FF_MEMLESS if USB_HID
- help
- Say Y here if you have one of these devices:
- - Logitech WingMan Cordless RumblePad
- - Logitech WingMan Cordless RumblePad 2
- - Logitech WingMan Force 3D
- - Logitech Formula Force EX
- - Logitech MOMO Force wheel
-
- and if you want to enable force feedback for them.
- Note: if you say N here, this device will still be supported, but without
- force feedback.
-
-config LOGIRUMBLEPAD2_FF
- bool "Logitech Rumblepad 2 support"
- depends on HID_FF
- select INPUT_FF_MEMLESS if USB_HID
- help
- Say Y here if you want to enable force feedback support for Logitech
- Rumblepad 2 devices.
-
-config PANTHERLORD_FF
- bool "PantherLord/GreenAsia based device support"
- depends on HID_FF
- select INPUT_FF_MEMLESS if USB_HID
- help
- Say Y here if you have a PantherLord/GreenAsia based game controller
- or adapter and want to enable force feedback support for it.
-
-config THRUSTMASTER_FF
- bool "ThrustMaster devices support"
- depends on HID_FF
- select INPUT_FF_MEMLESS if USB_HID
- help
- Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
- a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel,
- and want to enable force feedback support for it.
- Note: if you say N here, this device will still be supported, but without
- force feedback.
-
-config ZEROPLUS_FF
- bool "Zeroplus based game controller support"
- depends on HID_FF
- select INPUT_FF_MEMLESS if USB_HID
- help
- Say Y here if you have a Zeroplus based game controller and want to
- enable force feedback for it.
-
config USB_HIDDEV
bool "/dev/hiddev raw HID device support"
depends on USB_HID
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile
index 00a7b709019..1329ecb37a1 100644
--- a/drivers/hid/usbhid/Makefile
+++ b/drivers/hid/usbhid/Makefile
@@ -13,24 +13,6 @@ endif
ifeq ($(CONFIG_HID_PID),y)
usbhid-objs += hid-pidff.o
endif
-ifeq ($(CONFIG_LOGITECH_FF),y)
- usbhid-objs += hid-lgff.o
-endif
-ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
- usbhid-objs += hid-lg2ff.o
-endif
-ifeq ($(CONFIG_PANTHERLORD_FF),y)
- usbhid-objs += hid-plff.o
-endif
-ifeq ($(CONFIG_THRUSTMASTER_FF),y)
- usbhid-objs += hid-tmff.o
-endif
-ifeq ($(CONFIG_ZEROPLUS_FF),y)
- usbhid-objs += hid-zpff.o
-endif
-ifeq ($(CONFIG_HID_FF),y)
- usbhid-objs += hid-ff.o
-endif
obj-$(CONFIG_USB_HID) += usbhid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 27fe4d8912c..705a43cdeea 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -44,8 +44,6 @@
#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
- "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
/*
* Module parameters.
*/
@@ -61,12 +59,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex");
-static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
-module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
-MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
- " rdesc_quirks=vendorID:productID:rdesc_quirks"
- " where vendorID, productID, and rdesc_quirks are all in"
- " 0x-prefixed hex");
/*
* Input submission and I/O error handler.
*/
@@ -197,31 +189,32 @@ static void hid_irq_in(struct urb *urb)
int status;
switch (urb->status) {
- case 0: /* success */
- usbhid->retry_delay = 0;
- hid_input_report(urb->context, HID_INPUT_REPORT,
- urb->transfer_buffer,
- urb->actual_length, 1);
- break;
- case -EPIPE: /* stall */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- set_bit(HID_CLEAR_HALT, &usbhid->iofl);
- schedule_work(&usbhid->reset_work);
- return;
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- case -ESHUTDOWN: /* unplug */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- return;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ETIME: /* protocol error or unplug */
- case -ETIMEDOUT: /* Should never happen, but... */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- hid_io_error(hid);
- return;
- default: /* error */
- warn("input irq status %d received", urb->status);
+ case 0: /* success */
+ usbhid->retry_delay = 0;
+ hid_input_report(urb->context, HID_INPUT_REPORT,
+ urb->transfer_buffer,
+ urb->actual_length, 1);
+ break;
+ case -EPIPE: /* stall */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ schedule_work(&usbhid->reset_work);
+ return;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN: /* unplug */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ return;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ETIME: /* protocol error or unplug */
+ case -ETIMEDOUT: /* Should never happen, but... */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ hid_io_error(hid);
+ return;
+ default: /* error */
+ dev_warn(&urb->dev->dev, "input irq status %d "
+ "received\n", urb->status);
}
status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -240,13 +233,16 @@ static void hid_irq_in(struct urb *urb)
static int hid_submit_out(struct hid_device *hid)
{
struct hid_report *report;
+ char *raw_report;
struct usbhid_device *usbhid = hid->driver_data;
- report = usbhid->out[usbhid->outtail];
+ report = usbhid->out[usbhid->outtail].report;
+ raw_report = usbhid->out[usbhid->outtail].raw_report;
- hid_output_report(report, usbhid->outbuf);
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
usbhid->urbout->dev = hid_to_usb_dev(hid);
+ memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length);
+ kfree(raw_report);
dbg_hid("submitting out urb\n");
@@ -262,17 +258,20 @@ static int hid_submit_ctrl(struct hid_device *hid)
{
struct hid_report *report;
unsigned char dir;
+ char *raw_report;
int len;
struct usbhid_device *usbhid = hid->driver_data;
report = usbhid->ctrl[usbhid->ctrltail].report;
+ raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
dir = usbhid->ctrl[usbhid->ctrltail].dir;
len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
if (dir == USB_DIR_OUT) {
- hid_output_report(report, usbhid->ctrlbuf);
usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
usbhid->urbctrl->transfer_buffer_length = len;
+ memcpy(usbhid->ctrlbuf, raw_report, len);
+ kfree(raw_report);
} else {
int maxpacket, padlen;
@@ -319,17 +318,18 @@ static void hid_irq_out(struct urb *urb)
int unplug = 0;
switch (urb->status) {
- case 0: /* success */
- break;
- case -ESHUTDOWN: /* unplug */
- unplug = 1;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- break;
- default: /* error */
- warn("output irq status %d received", urb->status);
+ case 0: /* success */
+ break;
+ case -ESHUTDOWN: /* unplug */
+ unplug = 1;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ break;
+ default: /* error */
+ dev_warn(&urb->dev->dev, "output irq status %d "
+ "received\n", urb->status);
}
spin_lock_irqsave(&usbhid->outlock, flags);
@@ -367,21 +367,23 @@ static void hid_ctrl(struct urb *urb)
spin_lock_irqsave(&usbhid->ctrllock, flags);
switch (urb->status) {
- case 0: /* success */
- if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
- hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
- urb->transfer_buffer, urb->actual_length, 0);
- break;
- case -ESHUTDOWN: /* unplug */
- unplug = 1;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- case -EPIPE: /* report not available */
- break;
- default: /* error */
- warn("ctrl urb status %d received", urb->status);
+ case 0: /* success */
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+ hid_input_report(urb->context,
+ usbhid->ctrl[usbhid->ctrltail].report->type,
+ urb->transfer_buffer, urb->actual_length, 0);
+ break;
+ case -ESHUTDOWN: /* unplug */
+ unplug = 1;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -EPIPE: /* report not available */
+ break;
+ default: /* error */
+ dev_warn(&urb->dev->dev, "ctrl urb status %d "
+ "received\n", urb->status);
}
if (unplug)
@@ -408,6 +410,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
int head;
unsigned long flags;
struct usbhid_device *usbhid = hid->driver_data;
+ int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
return;
@@ -418,11 +421,18 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
spin_unlock_irqrestore(&usbhid->outlock, flags);
- warn("output queue full");
+ dev_warn(&hid->dev, "output queue full\n");
return;
}
- usbhid->out[usbhid->outhead] = report;
+ usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
+ if (!usbhid->out[usbhid->outhead].raw_report) {
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
+ dev_warn(&hid->dev, "output queueing failed\n");
+ return;
+ }
+ hid_output_report(report, usbhid->out[usbhid->outhead].raw_report);
+ usbhid->out[usbhid->outhead].report = report;
usbhid->outhead = head;
if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
@@ -437,10 +447,19 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
spin_unlock_irqrestore(&usbhid->ctrllock, flags);
- warn("control queue full");
+ dev_warn(&hid->dev, "control queue full\n");
return;
}
+ if (dir == USB_DIR_OUT) {
+ usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
+ if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+ dev_warn(&hid->dev, "control queueing failed\n");
+ return;
+ }
+ hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report);
+ }
usbhid->ctrl[usbhid->ctrlhead].report = report;
usbhid->ctrl[usbhid->ctrlhead].dir = dir;
usbhid->ctrlhead = head;
@@ -451,6 +470,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
spin_unlock_irqrestore(&usbhid->ctrllock, flags);
}
+EXPORT_SYMBOL_GPL(usbhid_submit_report);
static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -465,7 +485,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
return -1;
if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
- warn("event field not found");
+ dev_warn(&dev->dev, "event field not found\n");
return -1;
}
@@ -568,7 +588,7 @@ void usbhid_init_reports(struct hid_device *hid)
}
if (err)
- warn("timeout initializing reports");
+ dev_warn(&hid->dev, "timeout initializing reports\n");
}
/*
@@ -598,7 +618,7 @@ static int hid_find_field_early(struct hid_device *hid, unsigned int page,
return -1;
}
-static void usbhid_set_leds(struct hid_device *hid)
+void usbhid_set_leds(struct hid_device *hid)
{
struct hid_field *field;
int offset;
@@ -608,6 +628,7 @@ static void usbhid_set_leds(struct hid_device *hid)
usbhid_submit_report(hid, field->report, USB_DIR_OUT);
}
}
+EXPORT_SYMBOL_GPL(usbhid_set_leds);
/*
* Traverse the supplied list of reports and find the longest
@@ -675,43 +696,16 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
-/*
- * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
- * to "operational". Without this, the ps3 controller will not report any
- * events.
- */
-static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
-{
- int result;
- char *buf = kmalloc(18, GFP_KERNEL);
-
- if (!buf)
- return;
-
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- HID_REQ_GET_REPORT,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- (3 << 8) | 0xf2, ifnum, buf, 17,
- USB_CTRL_GET_TIMEOUT);
-
- if (result < 0)
- err_hid("%s failed: %d\n", __func__, result);
-
- kfree(buf);
-}
-
-static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+static int usbhid_parse(struct hid_device *hid)
{
+ struct usb_interface *intf = to_usb_interface(hid->dev.parent);
struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_device *dev = interface_to_usbdev (intf);
struct hid_descriptor *hdesc;
- struct hid_device *hid;
u32 quirks = 0;
- unsigned int insize = 0, rsize = 0;
+ unsigned int rsize = 0;
char *rdesc;
- int n, len;
- struct usbhid_device *usbhid;
+ int ret, n;
quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
@@ -724,63 +718,75 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
quirks |= HID_QUIRK_NOGET;
}
- if (quirks & HID_QUIRK_IGNORE)
- return NULL;
-
- if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
- (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
- return NULL;
-
-
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
(!interface->desc.bNumEndpoints ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
dbg_hid("class descriptor not present\n");
- return NULL;
+ return -ENODEV;
}
+ hid->version = le16_to_cpu(hdesc->bcdHID);
+ hid->country = hdesc->bCountryCode;
+
for (n = 0; n < hdesc->bNumDescriptors; n++)
if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
dbg_hid("weird size of report descriptor (%u)\n", rsize);
- return NULL;
+ return -EINVAL;
}
if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
dbg_hid("couldn't allocate rdesc memory\n");
- return NULL;
+ return -ENOMEM;
}
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
- if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
+ ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber,
+ HID_DT_REPORT, rdesc, rsize);
+ if (ret < 0) {
dbg_hid("reading report descriptor failed\n");
kfree(rdesc);
- return NULL;
+ goto err;
}
- usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct), rdesc,
- rsize, rdesc_quirks_param);
-
dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
dbg_hid_line("\n");
- if (!(hid = hid_parse_report(rdesc, n))) {
+ ret = hid_parse_report(hid, rdesc, rsize);
+ kfree(rdesc);
+ if (ret) {
dbg_hid("parsing report descriptor failed\n");
- kfree(rdesc);
- return NULL;
+ goto err;
}
- kfree(rdesc);
hid->quirks = quirks;
- if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
- goto fail_no_usbhid;
+ return 0;
+err:
+ return ret;
+}
+
+static int usbhid_start(struct hid_device *hid)
+{
+ struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+ struct usb_host_interface *interface = intf->cur_altsetting;
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usbhid_device *usbhid;
+ unsigned int n, insize = 0;
+ int ret;
+
+ WARN_ON(hid->driver_data);
+
+ usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL);
+ if (usbhid == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
hid->driver_data = usbhid;
usbhid->hid = hid;
@@ -799,28 +805,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
insize = HID_MAX_BUFFER_SIZE;
if (hid_alloc_buffers(dev, hid)) {
- hid_free_buffers(dev, hid);
+ ret = -ENOMEM;
goto fail;
}
- hid->name[0] = 0;
-
- if (dev->manufacturer)
- strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
-
- if (dev->product) {
- if (dev->manufacturer)
- strlcat(hid->name, " ", sizeof(hid->name));
- strlcat(hid->name, dev->product, sizeof(hid->name));
- }
-
- if (!strlen(hid->name))
- snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
-
for (n = 0; n < interface->desc.bNumEndpoints; n++) {
-
struct usb_endpoint_descriptor *endpoint;
int pipe;
int interval;
@@ -832,7 +821,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
interval = endpoint->bInterval;
/* Some vendors give fullspeed interval on highspeed devides */
- if (quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
+ if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
dev->speed == USB_SPEED_HIGH) {
interval = fls(endpoint->bInterval*8);
printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
@@ -843,6 +832,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
interval = hid_mousepoll_interval;
+ ret = -ENOMEM;
if (usb_endpoint_dir_in(endpoint)) {
if (usbhid->urbin)
continue;
@@ -868,6 +858,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (!usbhid->urbin) {
err_hid("couldn't find an input interrupt endpoint");
+ ret = -ENODEV;
goto fail;
}
@@ -879,44 +870,25 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
spin_lock_init(&usbhid->outlock);
spin_lock_init(&usbhid->ctrllock);
- hid->version = le16_to_cpu(hdesc->bcdHID);
- hid->country = hdesc->bCountryCode;
- hid->dev = &intf->dev;
usbhid->intf = intf;
usbhid->ifnum = interface->desc.bInterfaceNumber;
- hid->bus = BUS_USB;
- hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
- hid->product = le16_to_cpu(dev->descriptor.idProduct);
-
- usb_make_path(dev, hid->phys, sizeof(hid->phys));
- strlcat(hid->phys, "/input", sizeof(hid->phys));
- len = strlen(hid->phys);
- if (len < sizeof(hid->phys) - 1)
- snprintf(hid->phys + len, sizeof(hid->phys) - len,
- "%d", intf->altsetting[0].desc.bInterfaceNumber);
-
- if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
- hid->uniq[0] = 0;
-
usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
- if (!usbhid->urbctrl)
+ if (!usbhid->urbctrl) {
+ ret = -ENOMEM;
goto fail;
+ }
usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
usbhid->ctrlbuf, 1, hid_ctrl, hid);
usbhid->urbctrl->setup_dma = usbhid->cr_dma;
usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- hid->hidinput_input_event = usb_hidinput_input_event;
- hid->hid_open = usbhid_open;
- hid->hid_close = usbhid_close;
-#ifdef CONFIG_USB_HIDDEV
- hid->hiddev_hid_event = hiddev_hid_event;
- hid->hiddev_report_event = hiddev_report_event;
-#endif
- hid->hid_output_raw_report = usbhid_output_raw_report;
- return hid;
+
+ usbhid_init_reports(hid);
+ hid_dump_device(hid);
+
+ return 0;
fail:
usb_free_urb(usbhid->urbin);
@@ -924,24 +896,18 @@ fail:
usb_free_urb(usbhid->urbctrl);
hid_free_buffers(dev, hid);
kfree(usbhid);
-fail_no_usbhid:
- hid_free_device(hid);
-
- return NULL;
+err:
+ return ret;
}
-static void hid_disconnect(struct usb_interface *intf)
+static void usbhid_stop(struct hid_device *hid)
{
- struct hid_device *hid = usb_get_intfdata (intf);
- struct usbhid_device *usbhid;
+ struct usbhid_device *usbhid = hid->driver_data;
- if (!hid)
+ if (WARN_ON(!usbhid))
return;
- usbhid = hid->driver_data;
-
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
- usb_set_intfdata(intf, NULL);
set_bit(HID_DISCONNECTED, &usbhid->iofl);
spin_unlock_irq(&usbhid->inlock);
usb_kill_urb(usbhid->urbin);
@@ -958,86 +924,100 @@ static void hid_disconnect(struct usb_interface *intf)
if (hid->claimed & HID_CLAIMED_HIDRAW)
hidraw_disconnect(hid);
+ hid->claimed = 0;
+
usb_free_urb(usbhid->urbin);
usb_free_urb(usbhid->urbctrl);
usb_free_urb(usbhid->urbout);
hid_free_buffers(hid_to_usb_dev(hid), hid);
kfree(usbhid);
- hid_free_device(hid);
+ hid->driver_data = NULL;
}
+static struct hid_ll_driver usb_hid_driver = {
+ .parse = usbhid_parse,
+ .start = usbhid_start,
+ .stop = usbhid_stop,
+ .open = usbhid_open,
+ .close = usbhid_close,
+ .hidinput_input_event = usb_hidinput_input_event,
+};
+
static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
+ struct usb_device *dev = interface_to_usbdev(intf);
struct hid_device *hid;
- char path[64];
- int i;
- char *c;
+ size_t len;
+ int ret;
dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
- if (!(hid = usb_hid_configure(intf)))
- return -ENODEV;
-
- usbhid_init_reports(hid);
- hid_dump_device(hid);
- if (hid->quirks & HID_QUIRK_RESET_LEDS)
- usbhid_set_leds(hid);
-
- if (!hidinput_connect(hid))
- hid->claimed |= HID_CLAIMED_INPUT;
- if (!hiddev_connect(hid))
- hid->claimed |= HID_CLAIMED_HIDDEV;
- if (!hidraw_connect(hid))
- hid->claimed |= HID_CLAIMED_HIDRAW;
+ hid = hid_allocate_device();
+ if (IS_ERR(hid))
+ return PTR_ERR(hid);
usb_set_intfdata(intf, hid);
+ hid->ll_driver = &usb_hid_driver;
+ hid->hid_output_raw_report = usbhid_output_raw_report;
+ hid->ff_init = hid_pidff_init;
+#ifdef CONFIG_USB_HIDDEV
+ hid->hiddev_connect = hiddev_connect;
+ hid->hiddev_hid_event = hiddev_hid_event;
+ hid->hiddev_report_event = hiddev_report_event;
+#endif
+ hid->dev.parent = &intf->dev;
+ hid->bus = BUS_USB;
+ hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+ hid->product = le16_to_cpu(dev->descriptor.idProduct);
+ hid->name[0] = 0;
- if (!hid->claimed) {
- printk ("HID device claimed by neither input, hiddev nor hidraw\n");
- hid_disconnect(intf);
- return -ENODEV;
+ if (dev->manufacturer)
+ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(hid->name, " ", sizeof(hid->name));
+ strlcat(hid->name, dev->product, sizeof(hid->name));
}
- if ((hid->claimed & HID_CLAIMED_INPUT))
- hid_ff_init(hid);
+ if (!strlen(hid->name))
+ snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
- if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
- hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
- intf->cur_altsetting->desc.bInterfaceNumber);
+ usb_make_path(dev, hid->phys, sizeof(hid->phys));
+ strlcat(hid->phys, "/input", sizeof(hid->phys));
+ len = strlen(hid->phys);
+ if (len < sizeof(hid->phys) - 1)
+ snprintf(hid->phys + len, sizeof(hid->phys) - len,
+ "%d", intf->altsetting[0].desc.bInterfaceNumber);
- printk(KERN_INFO);
+ if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
+ hid->uniq[0] = 0;
- if (hid->claimed & HID_CLAIMED_INPUT)
- printk("input");
- if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
- hid->claimed & HID_CLAIMED_HIDRAW))
- printk(",");
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- printk("hiddev%d", hid->minor);
- if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
- (hid->claimed & HID_CLAIMED_HIDRAW))
- printk(",");
- if (hid->claimed & HID_CLAIMED_HIDRAW)
- printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
-
- c = "Device";
- for (i = 0; i < hid->maxcollection; i++) {
- if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
- (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
- (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) {
- c = hid_types[hid->collection[i].usage & 0xffff];
- break;
- }
+ ret = hid_add_device(hid);
+ if (ret) {
+ if (ret != -ENODEV)
+ dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+ goto err;
}
- usb_make_path(interface_to_usbdev(intf), path, 63);
+ return 0;
+err:
+ hid_destroy_device(hid);
+ return ret;
+}
- printk(": USB HID v%x.%02x %s [%s] on %s\n",
- hid->version >> 8, hid->version & 0xff, c, hid->name, path);
+static void hid_disconnect(struct usb_interface *intf)
+{
+ struct hid_device *hid = usb_get_intfdata(intf);
- return 0;
+ if (WARN_ON(!hid))
+ return;
+
+ hid_destroy_device(hid);
}
static int hid_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1107,9 +1087,22 @@ static struct usb_driver hid_driver = {
.supports_autosuspend = 1,
};
+static const struct hid_device_id hid_usb_table[] = {
+ { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
+ { }
+};
+
+static struct hid_driver hid_usb_driver = {
+ .name = "generic-usb",
+ .id_table = hid_usb_table,
+};
+
static int __init hid_init(void)
{
int retval;
+ retval = hid_register_driver(&hid_usb_driver);
+ if (retval)
+ goto hid_register_fail;
retval = usbhid_quirks_init(quirks_param);
if (retval)
goto usbhid_quirks_init_fail;
@@ -1119,7 +1112,8 @@ static int __init hid_init(void)
retval = usb_register(&hid_driver);
if (retval)
goto usb_register_fail;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
usb_register_fail:
@@ -1127,6 +1121,8 @@ usb_register_fail:
hiddev_init_fail:
usbhid_quirks_exit();
usbhid_quirks_init_fail:
+ hid_unregister_driver(&hid_usb_driver);
+hid_register_fail:
return retval;
}
@@ -1135,6 +1131,7 @@ static void __exit hid_exit(void)
usb_deregister(&hid_driver);
hiddev_exit();
usbhid_quirks_exit();
+ hid_unregister_driver(&hid_usb_driver);
}
module_init(hid_init);
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
deleted file mode 100644
index 1d0dac52f16..00000000000
--- a/drivers/hid/usbhid/hid-ff.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Force feedback support for hid devices.
- * Not all hid devices use the same protocol. For example, some use PID,
- * other use their own proprietary procotol.
- *
- * Copyright (c) 2002-2004 Johann Deneux
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <johann.deneux@it.uu.se>
- */
-
-#include <linux/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/*
- * This table contains pointers to initializers. To add support for new
- * devices, you need to add the USB vendor and product ids here.
- */
-struct hid_ff_initializer {
- u16 idVendor;
- u16 idProduct;
- int (*init)(struct hid_device*);
-};
-
-/*
- * We try pidff when no other driver is found because PID is the
- * standards compliant way of implementing force feedback in HID.
- * pidff_init() will quickly abort if the device doesn't appear to
- * be a PID device
- */
-static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_FF
- { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
- { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
- { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
- { 0x46d, 0xc286, hid_lgff_init }, /* Logitech Force 3D Pro Joystick */
- { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
- { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
- { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
-#endif
-#ifdef CONFIG_LOGIRUMBLEPAD2_FF
- { 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
-#endif
-#ifdef CONFIG_PANTHERLORD_FF
- { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
- { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc. USB Joystick " */
-#endif
-#ifdef CONFIG_THRUSTMASTER_FF
- { 0x44f, 0xb300, hid_tmff_init },
- { 0x44f, 0xb304, hid_tmff_init },
- { 0x44f, 0xb651, hid_tmff_init }, /* FGT Rumble Force Wheel */
- { 0x44f, 0xb654, hid_tmff_init }, /* FGT Force Feedback Wheel */
-#endif
-#ifdef CONFIG_ZEROPLUS_FF
- { 0xc12, 0x0005, hid_zpff_init },
- { 0xc12, 0x0030, hid_zpff_init },
-#endif
- { 0, 0, hid_pidff_init} /* Matches anything */
-};
-
-int hid_ff_init(struct hid_device* hid)
-{
- struct hid_ff_initializer *init;
- int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
- int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
-
- for (init = inits; init->idVendor; init++)
- if (init->idVendor == vendor && init->idProduct == product)
- break;
-
- return init->init(hid);
-}
-EXPORT_SYMBOL_GPL(hid_ff_init);
-
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 011326178c0..484e3eec2f8 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -397,7 +397,6 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
effect->u.condition[i].left_saturation);
pidff_set(&pidff->set_condition[PID_DEAD_BAND],
effect->u.condition[i].deadband);
- usbhid_wait_io(pidff->hid);
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
USB_DIR_OUT);
}
@@ -512,7 +511,6 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
}
- usbhid_wait_io(pidff->hid);
usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
USB_DIR_OUT);
}
@@ -548,6 +546,9 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
int pid_id = pidff->pid_id[effect_id];
debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]);
+ /* Wait for the queue to clear. We do not want a full fifo to
+ prevent the effect removal. */
+ usbhid_wait_io(pidff->hid);
pidff_playback_pid(pidff, pid_id, 0);
pidff_erase_pid(pidff, pid_id);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index b15f8824963..47ebe045f9b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -17,412 +17,7 @@
#include <linux/hid.h>
-#define USB_VENDOR_ID_A4TECH 0x09da
-#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
-#define USB_DEVICE_ID_A4TECH_X5_005D 0x000a
-
-#define USB_VENDOR_ID_AASHIMA 0x06d6
-#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
-#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
-
-#define USB_VENDOR_ID_ACECAD 0x0460
-#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004
-#define USB_DEVICE_ID_ACECAD_302 0x0008
-
-#define USB_VENDOR_ID_ADS_TECH 0x06e1
-#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
-
-#define USB_VENDOR_ID_AFATECH 0x15a4
-#define USB_DEVICE_ID_AFATECH_AF9016 0x9016
-
-#define USB_VENDOR_ID_AIPTEK 0x08ca
-#define USB_DEVICE_ID_AIPTEK_01 0x0001
-#define USB_DEVICE_ID_AIPTEK_10 0x0010
-#define USB_DEVICE_ID_AIPTEK_20 0x0020
-#define USB_DEVICE_ID_AIPTEK_21 0x0021
-#define USB_DEVICE_ID_AIPTEK_22 0x0022
-#define USB_DEVICE_ID_AIPTEK_23 0x0023
-#define USB_DEVICE_ID_AIPTEK_24 0x0024
-
-#define USB_VENDOR_ID_AIRCABLE 0x16CA
-#define USB_DEVICE_ID_AIRCABLE1 0x1502
-
-#define USB_VENDOR_ID_ALCOR 0x058f
-#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720
-
-#define USB_VENDOR_ID_ALPS 0x0433
-#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101
-
-#define USB_VENDOR_ID_APPLE 0x05ac
-#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
-#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
-#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
-#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
-#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217
-#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218
-#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219
-#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
-#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
-#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
-#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220
-#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221
-#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
-#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
-#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
-#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
-
-#define USB_VENDOR_ID_ASUS 0x0b05
-#define USB_DEVICE_ID_ASUS_LCM 0x1726
-
-#define USB_VENDOR_ID_ATEN 0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
-#define USB_DEVICE_ID_ATEN_CS124U 0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
-
-#define USB_VENDOR_ID_BELKIN 0x050d
-#define USB_DEVICE_ID_FLIP_KVM 0x3201
-
-#define USB_VENDOR_ID_BERKSHIRE 0x0c98
-#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
-
-#define USB_VENDOR_ID_CHERRY 0x046a
-#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
-
-#define USB_VENDOR_ID_CHIC 0x05fe
-#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014
-
-#define USB_VENDOR_ID_CIDC 0x1677
-
-#define USB_VENDOR_ID_CMEDIA 0x0d8c
-#define USB_DEVICE_ID_CM109 0x000e
-
-#define USB_VENDOR_ID_CODEMERCS 0x07c0
-#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
-#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff
-
-#define USB_VENDOR_ID_CYGNAL 0x10c4
-#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
-
-#define USB_VENDOR_ID_CYPRESS 0x04b4
-#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
-#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
-#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
-#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
-#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
-
-#define USB_VENDOR_ID_DELL 0x413c
-#define USB_DEVICE_ID_DELL_W7658 0x2005
-
-#define USB_VENDOR_ID_DELORME 0x1163
-#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
-#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
-
-#define USB_VENDOR_ID_DMI 0x0c0b
-#define USB_DEVICE_ID_DMI_ENC 0x5fab
-
-#define USB_VENDOR_ID_ELO 0x04E7
-#define USB_DEVICE_ID_ELO_TS2700 0x0020
-
-#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
-
-#define USB_VENDOR_ID_EZKEY 0x0518
-#define USB_DEVICE_ID_BTC_8193 0x0002
-
-#define USB_VENDOR_ID_GAMERON 0x0810
-#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
-
-#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
-
-#define USB_VENDOR_ID_GLAB 0x06c2
-#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
-#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
-#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040
-#define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044
-#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045
-#define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051
-#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053
-#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058
-
-#define USB_VENDOR_ID_GOTOP 0x08f2
-#define USB_DEVICE_ID_SUPER_Q2 0x007f
-#define USB_DEVICE_ID_GOGOPEN 0x00ce
-#define USB_DEVICE_ID_PENPOWER 0x00f4
-
-#define USB_VENDOR_ID_GRETAGMACBETH 0x0971
-#define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005
-
-#define USB_VENDOR_ID_GRIFFIN 0x077d
-#define USB_DEVICE_ID_POWERMATE 0x0410
-#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
-
-#define USB_VENDOR_ID_GTCO 0x078c
-#define USB_DEVICE_ID_GTCO_90 0x0090
-#define USB_DEVICE_ID_GTCO_100 0x0100
-#define USB_DEVICE_ID_GTCO_101 0x0101
-#define USB_DEVICE_ID_GTCO_103 0x0103
-#define USB_DEVICE_ID_GTCO_104 0x0104
-#define USB_DEVICE_ID_GTCO_105 0x0105
-#define USB_DEVICE_ID_GTCO_106 0x0106
-#define USB_DEVICE_ID_GTCO_107 0x0107
-#define USB_DEVICE_ID_GTCO_108 0x0108
-#define USB_DEVICE_ID_GTCO_200 0x0200
-#define USB_DEVICE_ID_GTCO_201 0x0201
-#define USB_DEVICE_ID_GTCO_202 0x0202
-#define USB_DEVICE_ID_GTCO_203 0x0203
-#define USB_DEVICE_ID_GTCO_204 0x0204
-#define USB_DEVICE_ID_GTCO_205 0x0205
-#define USB_DEVICE_ID_GTCO_206 0x0206
-#define USB_DEVICE_ID_GTCO_207 0x0207
-#define USB_DEVICE_ID_GTCO_300 0x0300
-#define USB_DEVICE_ID_GTCO_301 0x0301
-#define USB_DEVICE_ID_GTCO_302 0x0302
-#define USB_DEVICE_ID_GTCO_303 0x0303
-#define USB_DEVICE_ID_GTCO_304 0x0304
-#define USB_DEVICE_ID_GTCO_305 0x0305
-#define USB_DEVICE_ID_GTCO_306 0x0306
-#define USB_DEVICE_ID_GTCO_307 0x0307
-#define USB_DEVICE_ID_GTCO_308 0x0308
-#define USB_DEVICE_ID_GTCO_309 0x0309
-#define USB_DEVICE_ID_GTCO_400 0x0400
-#define USB_DEVICE_ID_GTCO_401 0x0401
-#define USB_DEVICE_ID_GTCO_402 0x0402
-#define USB_DEVICE_ID_GTCO_403 0x0403
-#define USB_DEVICE_ID_GTCO_404 0x0404
-#define USB_DEVICE_ID_GTCO_405 0x0405
-#define USB_DEVICE_ID_GTCO_500 0x0500
-#define USB_DEVICE_ID_GTCO_501 0x0501
-#define USB_DEVICE_ID_GTCO_502 0x0502
-#define USB_DEVICE_ID_GTCO_503 0x0503
-#define USB_DEVICE_ID_GTCO_504 0x0504
-#define USB_DEVICE_ID_GTCO_1000 0x1000
-#define USB_DEVICE_ID_GTCO_1001 0x1001
-#define USB_DEVICE_ID_GTCO_1002 0x1002
-#define USB_DEVICE_ID_GTCO_1003 0x1003
-#define USB_DEVICE_ID_GTCO_1004 0x1004
-#define USB_DEVICE_ID_GTCO_1005 0x1005
-#define USB_DEVICE_ID_GTCO_1006 0x1006
-#define USB_DEVICE_ID_GTCO_1007 0x1007
-#define USB_VENDOR_ID_HAPP 0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
-#define USB_DEVICE_ID_UGCI_FLYING 0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
-
-#define USB_VENDOR_ID_IMATION 0x0718
-#define USB_DEVICE_ID_DISC_STAKKA 0xd000
-
-#define USB_VENDOR_ID_KBGEAR 0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
-
-#define USB_VENDOR_ID_LD 0x0f11
-#define USB_DEVICE_ID_LD_CASSY 0x1000
-#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010
-#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020
-#define USB_DEVICE_ID_LD_JWM 0x1080
-#define USB_DEVICE_ID_LD_DMMP 0x1081
-#define USB_DEVICE_ID_LD_UMIP 0x1090
-#define USB_DEVICE_ID_LD_XRAY1 0x1100
-#define USB_DEVICE_ID_LD_XRAY2 0x1101
-#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200
-#define USB_DEVICE_ID_LD_COM3LAB 0x2000
-#define USB_DEVICE_ID_LD_TELEPORT 0x2010
-#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030
-#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
-
-#define USB_VENDOR_ID_LOGITECH 0x046d
-#define USB_DEVICE_ID_LOGITECH_LX3 0xc044
-#define USB_DEVICE_ID_LOGITECH_V150 0xc047
-#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
-#define USB_DEVICE_ID_LOGITECH_HARMONY 0xc110
-#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
-#define USB_DEVICE_ID_LOGITECH_HARMONY_3 0xc112
-#define USB_DEVICE_ID_LOGITECH_HARMONY_4 0xc113
-#define USB_DEVICE_ID_LOGITECH_HARMONY_5 0xc114
-#define USB_DEVICE_ID_LOGITECH_HARMONY_6 0xc115
-#define USB_DEVICE_ID_LOGITECH_HARMONY_7 0xc116
-#define USB_DEVICE_ID_LOGITECH_HARMONY_8 0xc117
-#define USB_DEVICE_ID_LOGITECH_HARMONY_9 0xc118
-#define USB_DEVICE_ID_LOGITECH_HARMONY_10 0xc119
-#define USB_DEVICE_ID_LOGITECH_HARMONY_11 0xc11a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_12 0xc11b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_13 0xc11c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_14 0xc11d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_15 0xc11e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_16 0xc11f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_17 0xc120
-#define USB_DEVICE_ID_LOGITECH_HARMONY_18 0xc121
-#define USB_DEVICE_ID_LOGITECH_HARMONY_19 0xc122
-#define USB_DEVICE_ID_LOGITECH_HARMONY_20 0xc123
-#define USB_DEVICE_ID_LOGITECH_HARMONY_21 0xc124
-#define USB_DEVICE_ID_LOGITECH_HARMONY_22 0xc125
-#define USB_DEVICE_ID_LOGITECH_HARMONY_23 0xc126
-#define USB_DEVICE_ID_LOGITECH_HARMONY_24 0xc127
-#define USB_DEVICE_ID_LOGITECH_HARMONY_25 0xc128
-#define USB_DEVICE_ID_LOGITECH_HARMONY_26 0xc129
-#define USB_DEVICE_ID_LOGITECH_HARMONY_27 0xc12a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_28 0xc12b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_29 0xc12c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_30 0xc12d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_31 0xc12e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_32 0xc12f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_33 0xc130
-#define USB_DEVICE_ID_LOGITECH_HARMONY_34 0xc131
-#define USB_DEVICE_ID_LOGITECH_HARMONY_35 0xc132
-#define USB_DEVICE_ID_LOGITECH_HARMONY_36 0xc133
-#define USB_DEVICE_ID_LOGITECH_HARMONY_37 0xc134
-#define USB_DEVICE_ID_LOGITECH_HARMONY_38 0xc135
-#define USB_DEVICE_ID_LOGITECH_HARMONY_39 0xc136
-#define USB_DEVICE_ID_LOGITECH_HARMONY_40 0xc137
-#define USB_DEVICE_ID_LOGITECH_HARMONY_41 0xc138
-#define USB_DEVICE_ID_LOGITECH_HARMONY_42 0xc139
-#define USB_DEVICE_ID_LOGITECH_HARMONY_43 0xc13a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_44 0xc13b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_45 0xc13c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_46 0xc13d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_47 0xc13e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_48 0xc13f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_49 0xc140
-#define USB_DEVICE_ID_LOGITECH_HARMONY_50 0xc141
-#define USB_DEVICE_ID_LOGITECH_HARMONY_51 0xc142
-#define USB_DEVICE_ID_LOGITECH_HARMONY_52 0xc143
-#define USB_DEVICE_ID_LOGITECH_HARMONY_53 0xc144
-#define USB_DEVICE_ID_LOGITECH_HARMONY_54 0xc145
-#define USB_DEVICE_ID_LOGITECH_HARMONY_55 0xc146
-#define USB_DEVICE_ID_LOGITECH_HARMONY_56 0xc147
-#define USB_DEVICE_ID_LOGITECH_HARMONY_57 0xc148
-#define USB_DEVICE_ID_LOGITECH_HARMONY_58 0xc149
-#define USB_DEVICE_ID_LOGITECH_HARMONY_59 0xc14a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_60 0xc14b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_61 0xc14c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
-#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
-#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
-#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
-#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
-#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
-#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
-#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
-#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
-#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
-#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
-
-#define USB_VENDOR_ID_MCC 0x09db
-#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
-#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a
-
-#define USB_VENDOR_ID_MGE 0x0463
-#define USB_DEVICE_ID_MGE_UPS 0xffff
-#define USB_DEVICE_ID_MGE_UPS1 0x0001
-
-#define USB_VENDOR_ID_MICROCHIP 0x04d8
-#define USB_DEVICE_ID_PICKIT1 0x0032
-#define USB_DEVICE_ID_PICKIT2 0x0033
-
-#define USB_VENDOR_ID_MICROSOFT 0x045e
-#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
-#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
-#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
-#define USB_DEVICE_ID_MS_NE4K 0x00db
-#define USB_DEVICE_ID_MS_LK6K 0x00f9
-
-#define USB_VENDOR_ID_MONTEREY 0x0566
-#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
-
-#define USB_VENDOR_ID_NCR 0x0404
-#define USB_DEVICE_ID_NCR_FIRST 0x0300
-#define USB_DEVICE_ID_NCR_LAST 0x03ff
-
-#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
-#define USB_DEVICE_ID_N_S_HARMONY 0xc359
-
-#define USB_VENDOR_ID_NATSU 0x08b7
-#define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001
-
-#define USB_VENDOR_ID_NEC 0x073e
-#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
-
-#define USB_VENDOR_ID_ONTRAK 0x0a07
-#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
-
-#define USB_VENDOR_ID_PANJIT 0x134c
-
-#define USB_VENDOR_ID_PANTHERLORD 0x0810
-#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
-
-#define USB_VENDOR_ID_PETALYNX 0x18b1
-#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
-
-#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
-#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
-
-#define USB_VENDOR_ID_SAITEK 0x06a3
-#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
-
-#define USB_VENDOR_ID_SAMSUNG 0x0419
-#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
-
-#define USB_VENDOR_ID_SONY 0x054c
-#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
-
-#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038
-
-#define USB_VENDOR_ID_SUN 0x0430
-#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
-
-#define USB_VENDOR_ID_SUNPLUS 0x04fc
-#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
-
-#define USB_VENDOR_ID_TOPMAX 0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
-
-#define USB_VENDOR_ID_TURBOX 0x062a
-#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
-
-#define USB_VENDOR_ID_VERNIER 0x08f7
-#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
-#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
-#define USB_DEVICE_ID_VERNIER_SKIP 0x0003
-#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
-#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
-
-#define USB_VENDOR_ID_WACOM 0x056a
-
-#define USB_VENDOR_ID_WISEGROUP 0x0925
-#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
-#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
-#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201
-#define USB_DEVICE_ID_QUAD_USB_JOYPAD 0x8800
-#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866
-
-#define USB_VENDOR_ID_WISEGROUP_LTD 0x6677
-#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
-
-#define USB_VENDOR_ID_YEALINK 0x6993
-#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
-
-#define USB_VENDOR_ID_KYE 0x0458
-#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
+#include "../hid-ids.h"
/*
* Alphabetically sorted blacklist by quirk type.
@@ -433,18 +28,10 @@ static const struct hid_blacklist {
__u16 idProduct;
__u32 quirks;
} hid_blacklist[] = {
-
- { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
- { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
-
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
-
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
- { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -453,169 +40,11 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
-
{ USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
- { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
- { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
-
- { USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
-
- { USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
- { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GENERAL_TOUCH, 0x0001, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GENERAL_TOUCH, 0x0002, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GENERAL_TOUCH, 0x0003, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GENERAL_TOUCH, 0x0004, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
-
- { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
-
- { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2, HID_QUIRK_IGNORE },
-
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL },
-
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
-
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
-
{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
- { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
-
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
@@ -623,144 +52,13 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-
- { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_6, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_7, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_8, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_9, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_10, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_11, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_12, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_13, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_14, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_15, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_16, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_17, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_18, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_19, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_20, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_21, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_22, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_23, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_24, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_25, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_26, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_27, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_28, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_29, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_30, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_31, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_32, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_33, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_34, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_35, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_36, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_37, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_38, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_39, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_40, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_41, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_42, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_43, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_44, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_45, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_46, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_47, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_48, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_49, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_50, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_51, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_52, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_53, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_54, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_55, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_56, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_57, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_58, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_59, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_60, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_61, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_62, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
-
- { 0, 0 }
-};
-
-/* Quirks for devices which require report descriptor fixup go here */
-static const struct hid_rdesc_blacklist {
- __u16 idVendor;
- __u16 idProduct;
- __u32 quirks;
-} hid_rdesc_blacklist[] = {
-
- { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
-
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 },
-
- { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
-
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
-
- { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
-
- { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
-
- { USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP, HID_QUIRK_RDESC_SUNPLUS_WDESKTOP },
-
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ 0, 0 }
};
@@ -974,16 +272,6 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
u32 quirks = 0;
const struct hid_blacklist *bl_entry = NULL;
- /* Ignore all Wacom devices */
- if (idVendor == USB_VENDOR_ID_WACOM)
- return HID_QUIRK_IGNORE;
-
- /* ignore all Code Mercenaries IOWarrior devices */
- if (idVendor == USB_VENDOR_ID_CODEMERCS)
- if (idProduct >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&
- idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
- return HID_QUIRK_IGNORE;
-
/* NCR devices must not be queried for reports */
if (idVendor == USB_VENDOR_ID_NCR &&
idProduct >= USB_DEVICE_ID_NCR_FIRST &&
@@ -1002,221 +290,3 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
}
EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
-
-/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
- if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
- printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
- rdesc[11] = rdesc[16] = 0xff;
- rdesc[12] = rdesc[17] = 0x03;
- }
-}
-
-
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 90 && rdesc[83] == 0x26
- && rdesc[84] == 0x8c
- && rdesc[85] == 0x02) {
- printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
- rdesc[84] = rdesc[89] = 0x4d;
- rdesc[85] = rdesc[90] = 0x10;
- }
-}
-
-static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 107 && rdesc[104] == 0x26
- && rdesc[105] == 0x80
- && rdesc[106] == 0x03) {
- printk(KERN_INFO "Fixing up Sunplus Wireless Desktop report descriptor\n");
- rdesc[105] = rdesc[110] = 0x03;
- rdesc[106] = rdesc[111] = 0x21;
- }
-}
-
-/*
- * Samsung IrDA remote controller (reports as Cypress USB Mouse).
- *
- * Vendor specific report #4 has a size of 48 bit,
- * and therefore is not accepted when inspecting the descriptors.
- * As a workaround we reinterpret the report as:
- * Variable type, count 6, size 8 bit, log. maximum 255
- * The burden to reconstruct the data is moved into user space.
- */
-static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc,
- int rsize)
-{
- if (rsize >= 182 && rdesc[175] == 0x25
- && rdesc[176] == 0x40
- && rdesc[177] == 0x75
- && rdesc[178] == 0x30
- && rdesc[179] == 0x95
- && rdesc[180] == 0x01
- && rdesc[182] == 0x40) {
- printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n");
- rdesc[176] = 0xff;
- rdesc[178] = 0x08;
- rdesc[180] = 0x06;
- rdesc[182] = 0x42;
- }
-}
-
-/* Petalynx Maxter Remote has maximum for consumer page set too low */
-static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 60 && rdesc[39] == 0x2a
- && rdesc[40] == 0xf5
- && rdesc[41] == 0x00
- && rdesc[59] == 0x26
- && rdesc[60] == 0xf9
- && rdesc[61] == 0x00) {
- printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
- rdesc[60] = 0xfa;
- rdesc[40] = 0xfa;
- }
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
- short fixed = 0;
- int i;
-
- for (i = 0; i < rsize - 4; i++) {
- if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
- unsigned char tmp;
-
- rdesc[i] = 0x19; rdesc[i+2] = 0x29;
- tmp = rdesc[i+3];
- rdesc[i+3] = rdesc[i+1];
- rdesc[i+1] = tmp;
- }
- }
-
- if (fixed)
- printk(KERN_INFO "Fixing up Cypress report descriptor\n");
-}
-
-/*
- * MacBook JIS keyboard has wrong logical maximum
- */
-static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 60 && rdesc[53] == 0x65
- && rdesc[59] == 0x65) {
- printk(KERN_INFO "Fixing up MacBook JIS keyboard report descriptor\n");
- rdesc[53] = rdesc[59] = 0xe7;
- }
-}
-
-static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 30 && rdesc[29] == 0x05
- && rdesc[30] == 0x09) {
- printk(KERN_INFO "Fixing up button/consumer in HID report descriptor\n");
- rdesc[30] = 0x0c;
- }
-}
-
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has several
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
-static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize == 571 && rdesc[284] == 0x19
- && rdesc[286] == 0x2a
- && rdesc[304] == 0x19
- && rdesc[306] == 0x29
- && rdesc[352] == 0x1a
- && rdesc[355] == 0x2a
- && rdesc[557] == 0x19
- && rdesc[559] == 0x29) {
- printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
- rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
- rdesc[352] = 0x36;
- rdesc[286] = rdesc[355] = 0x46;
- rdesc[306] = rdesc[559] = 0x45;
- }
-}
-
-static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
-{
- if ((quirks & HID_QUIRK_RDESC_CYMOTION))
- usbhid_fixup_cymotion_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_LOGITECH)
- usbhid_fixup_logitech_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
- usbhid_fixup_cypress_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_PETALYNX)
- usbhid_fixup_petalynx_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
- usbhid_fixup_macbook_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
- usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
- usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_MICROSOFT_RECV_1028)
- usbhid_fixup_microsoft_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_RDESC_SUNPLUS_WDESKTOP)
- usbhid_fixup_sunplus_wdesktop(rdesc, rsize);
-}
-
-/**
- * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
- *
- * Description:
- * Walks the hid_rdesc_blacklist[] array and checks whether the device
- * is known to have broken report descriptor that needs to be fixed up
- * prior to entering the HID parser
- *
- * Returns: nothing
- */
-void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
- char *rdesc, unsigned rsize, char **quirks_param)
-{
- int n, m;
- u16 paramVendor, paramProduct;
- u32 quirks;
-
- /* static rdesc quirk entries */
- for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
- if (hid_rdesc_blacklist[n].idVendor == idVendor &&
- hid_rdesc_blacklist[n].idProduct == idProduct)
- __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
- rdesc, rsize);
-
- /* runtime rdesc quirk entries handling */
- for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
- m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
- &paramVendor, &paramProduct, &quirks);
-
- if (m != 3)
- printk(KERN_WARNING
- "Could not parse HID quirk module param %s\n",
- quirks_param[n]);
- else if (paramVendor == idVendor && paramProduct == idProduct)
- __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
- }
-}
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 842e9edb888..babd65dd46a 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -790,21 +790,23 @@ static struct usb_class_driver hiddev_class = {
/*
* This is where hid.c calls us to connect a hid device to the hiddev driver
*/
-int hiddev_connect(struct hid_device *hid)
+int hiddev_connect(struct hid_device *hid, unsigned int force)
{
struct hiddev *hiddev;
struct usbhid_device *usbhid = hid->driver_data;
- int i;
int retval;
- for (i = 0; i < hid->maxcollection; i++)
- if (hid->collection[i].type ==
- HID_COLLECTION_APPLICATION &&
- !IS_INPUT_APPLICATION(hid->collection[i].usage))
- break;
+ if (!force) {
+ unsigned int i;
+ for (i = 0; i < hid->maxcollection; i++)
+ if (hid->collection[i].type ==
+ HID_COLLECTION_APPLICATION &&
+ !IS_INPUT_APPLICATION(hid->collection[i].usage))
+ break;
- if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
- return -1;
+ if (i == hid->maxcollection)
+ return -1;
+ }
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 62d2d7c925b..abedb13c623 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -67,7 +67,7 @@ struct usbhid_device {
spinlock_t ctrllock; /* Control fifo spinlock */
struct urb *urbout; /* Output URB */
- struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
+ struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
unsigned char outhead, outtail; /* Output pipe fifo head & tail */
char *outbuf; /* Output buffer */
dma_addr_t outbuf_dma; /* Output buffer dma */
@@ -82,7 +82,7 @@ struct usbhid_device {
};
#define hid_to_usb_dev(hid_dev) \
- container_of(hid_dev->dev->parent, struct usb_device, dev)
+ container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
#endif
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 0caaafe0184..b342926dd7f 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -105,14 +105,16 @@ static void usb_kbd_irq(struct urb *urb)
if (usb_kbd_keycode[kbd->old[i]])
input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
else
- info("Unknown key (scancode %#x) released.", kbd->old[i]);
+ dev_info(&urb->dev->dev,
+ "Unknown key (scancode %#x) released.\n", kbd->old[i]);
}
if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
if (usb_kbd_keycode[kbd->new[i]])
input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
- info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
+ dev_info(&urb->dev->dev,
+ "Unknown key (scancode %#x) released.\n", kbd->new[i]);
}
}
@@ -159,7 +161,8 @@ static void usb_kbd_led(struct urb *urb)
struct usb_kbd *kbd = urb->context;
if (urb->status)
- warn("led urb status %d received", urb->status);
+ dev_warn(&urb->dev->dev, "led urb status %d received\n",
+ urb->status);
if (*(kbd->leds) == kbd->newleds)
return;
@@ -352,7 +355,8 @@ static int __init usb_kbd_init(void)
{
int result = usb_register(&usb_kbd_driver);
if (result == 0)
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 35689ef172c..72ab4b26809 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -31,6 +31,11 @@
#include <linux/usb/input.h>
#include <linux/hid.h>
+/* for apple IDs */
+#ifdef CONFIG_USB_HID_MODULE
+#include "../hid-ids.h"
+#endif
+
/*
* Version Information
*/
@@ -240,7 +245,8 @@ static int __init usb_mouse_init(void)
{
int retval = usb_register(&usb_mouse_driver);
if (retval == 0)
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d402e8d813c..6de1e0ffd39 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -510,11 +510,9 @@ config SENSORS_LM90
depends on I2C
help
If you say yes here you get support for National Semiconductor LM90,
- LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657,
- MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
-
- The Analog Devices ADT7461 sensor chip is also supported, but only
- if found in ADM1032 compatibility mode.
+ LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
+ MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and
+ MAX6681 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm90.
@@ -540,6 +538,15 @@ config SENSORS_LM93
This driver can also be built as a module. If so, the module
will be called lm93.
+config SENSORS_MAX1111
+ tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
+ depends on SPI_MASTER
+ help
+ Say y here to support Maxim's MAX1111 ADC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called max1111.
+
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on I2C
@@ -791,6 +798,13 @@ config SENSORS_W83627EHF
This driver can also be built as a module. If so, the module
will be called w83627ehf.
+config SENSORS_ULTRA45
+ tristate "Sun Ultra45 PIC16F747"
+ depends on SPARC64
+ help
+ This driver provides support for the Ultra45 workstation environmental
+ sensors.
+
config SENSORS_HDAPS
tristate "IBM Hard Drive Active Protection System (hdaps)"
depends on INPUT && X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 950134ab842..042d5a78622 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
@@ -59,6 +60,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_LM93) += lm93.o
+obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index d568c65c137..d9e7a49d6cb 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "OTES1 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0011, NULL /* Abit AT8 32X, need DMI string */, {
+ { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -303,6 +303,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "SYS Fan", 34, 2, 60, 1, 0 },
{ "AUX1 Fan", 35, 2, 60, 1, 0 },
{ "AUX2 Fan", 36, 2, 60, 1, 0 },
+ { "AUX3 Fan", 37, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
{ 0x0012, NULL /* Abit AN8 32X, need DMI string */, {
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index ce8d94fbfd7..bfda8c80ef2 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -69,7 +69,7 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
-struct ad7414_data *ad7414_update_device(struct device *dev)
+static struct ad7414_data *ad7414_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct ad7414_data *data = i2c_get_clientdata(client);
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 7fe2441fc84..ff7de40b6e3 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -279,7 +279,6 @@ struct adm1026_data {
u8 fan_min[8]; /* Register value */
u8 fan_div[8]; /* Decoded value */
struct pwm_data pwm1; /* Pwm control values */
- int vid; /* Decoded value */
u8 vrm; /* VRM version */
u8 analog_out; /* Register value (DAC) */
long alarms; /* Register encoding, combined */
@@ -455,7 +454,7 @@ static void adm1026_print_gpio(struct i2c_client *client)
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
- dev_dbg(&client->dev, "GPIO config is:");
+ dev_dbg(&client->dev, "GPIO config is:\n");
for (i = 0;i <= 7;++i) {
if (data->config2 & (1 << i)) {
dev_dbg(&client->dev, "\t%sGP%s%d\n",
@@ -697,8 +696,6 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
data->last_config = jiffies;
}; /* last_config */
- dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
- data->vid = (data->gpio >> 11) & 0x1f;
data->valid = 1;
mutex_unlock(&data->update_lock);
return data;
@@ -1215,7 +1212,10 @@ static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
- return sprintf(buf, "%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
+ int vid = (data->gpio >> 11) & 0x1f;
+
+ dev_dbg(dev, "Setting VID from GPIO11-15.\n");
+ return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
@@ -1681,17 +1681,16 @@ static int adm1026_detect(struct i2c_client *client, int kind,
kind = adm1026;
} else if (company == ADM1026_COMPANY_ANALOG_DEV
&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, ": Unrecognized stepping "
+ dev_err(&adapter->dev, "Unrecognized stepping "
"0x%02x. Defaulting to ADM1026.\n", verstep);
kind = adm1026;
} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, ": Found version/stepping "
+ dev_err(&adapter->dev, "Found version/stepping "
"0x%02x. Assuming generic ADM1026.\n",
verstep);
kind = any_chip;
} else {
- dev_dbg(&adapter->dev, ": Autodetection "
- "failed\n");
+ dev_dbg(&adapter->dev, "Autodetection failed\n");
/* Not an ADM1026 ... */
if (kind == 0) { /* User used force=x,y */
dev_err(&adapter->dev, "Generic ADM1026 not "
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index ba84ca5923f..36718150b47 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -179,7 +179,8 @@ show_fan(struct device *dev, struct device_attribute *devattr, char *buf)
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm1029_data *data = adm1029_update_device(dev);
u16 val;
- if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0
+ if (data->fan[attr->index] == 0
+ || (data->fan_div[attr->index] & 0xC0) == 0
|| data->fan[attr->index] == 255) {
return sprintf(buf, "0\n");
}
@@ -194,7 +195,7 @@ show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm1029_data *data = adm1029_update_device(dev);
- if (data->fan_div[attr->index] == 0)
+ if ((data->fan_div[attr->index] & 0xC0) == 0)
return sprintf(buf, "0\n");
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
}
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c
index fbefa82a015..6c9ace1b76f 100644
--- a/drivers/hwmon/ams/ams-core.c
+++ b/drivers/hwmon/ams/ams-core.c
@@ -99,39 +99,31 @@ static struct pmf_irq_client ams_shock_client = {
*/
static void ams_worker(struct work_struct *work)
{
- mutex_lock(&ams_info.lock);
-
- if (ams_info.has_device) {
- unsigned long flags;
+ unsigned long flags;
+ u8 irqs_to_clear;
- spin_lock_irqsave(&ams_info.irq_lock, flags);
+ mutex_lock(&ams_info.lock);
- if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
- if (verbose)
- printk(KERN_INFO "ams: freefall detected!\n");
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ irqs_to_clear = ams_info.worker_irqs;
- ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+ if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
+ if (verbose)
+ printk(KERN_INFO "ams: freefall detected!\n");
- /* we must call this with interrupts enabled */
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- ams_info.clear_irq(AMS_IRQ_FREEFALL);
- spin_lock_irqsave(&ams_info.irq_lock, flags);
- }
+ ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+ }
- if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
- if (verbose)
- printk(KERN_INFO "ams: shock detected!\n");
+ if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
+ if (verbose)
+ printk(KERN_INFO "ams: shock detected!\n");
- ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+ ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+ }
- /* we must call this with interrupts enabled */
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- ams_info.clear_irq(AMS_IRQ_SHOCK);
- spin_lock_irqsave(&ams_info.irq_lock, flags);
- }
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- spin_unlock_irqrestore(&ams_info.irq_lock, flags);
- }
+ ams_info.clear_irq(irqs_to_clear);
mutex_unlock(&ams_info.lock);
}
@@ -223,34 +215,28 @@ int __init ams_init(void)
void ams_exit(void)
{
- mutex_lock(&ams_info.lock);
-
- if (ams_info.has_device) {
- /* Remove input device */
- ams_input_exit();
+ /* Remove input device */
+ ams_input_exit();
- /* Shut down implementation */
- ams_info.exit();
-
- /* Flush interrupt worker
- *
- * We do this after ams_info.exit(), because an interrupt might
- * have arrived before disabling them.
- */
- flush_scheduled_work();
+ /* Remove attributes */
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
- /* Remove attributes */
- device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+ /* Shut down implementation */
+ ams_info.exit();
- /* Remove device */
- of_device_unregister(ams_info.of_dev);
+ /* Flush interrupt worker
+ *
+ * We do this after ams_info.exit(), because an interrupt might
+ * have arrived before disabling them.
+ */
+ flush_scheduled_work();
- /* Remove handler */
- pmf_unregister_irq_client(&ams_shock_client);
- pmf_unregister_irq_client(&ams_freefall_client);
- }
+ /* Remove device */
+ of_device_unregister(ams_info.of_dev);
- mutex_unlock(&ams_info.lock);
+ /* Remove handler */
+ pmf_unregister_irq_client(&ams_shock_client);
+ pmf_unregister_irq_client(&ams_freefall_client);
}
MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c
index 957760536a4..2cbf8a6506c 100644
--- a/drivers/hwmon/ams/ams-i2c.c
+++ b/drivers/hwmon/ams/ams-i2c.c
@@ -60,26 +60,34 @@ enum ams_i2c_cmd {
AMS_CMD_START,
};
-static int ams_i2c_attach(struct i2c_adapter *adapter);
-static int ams_i2c_detach(struct i2c_adapter *adapter);
+static int ams_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int ams_i2c_remove(struct i2c_client *client);
+
+static const struct i2c_device_id ams_id[] = {
+ { "ams", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ams_id);
static struct i2c_driver ams_i2c_driver = {
.driver = {
.name = "ams",
.owner = THIS_MODULE,
},
- .attach_adapter = ams_i2c_attach,
- .detach_adapter = ams_i2c_detach,
+ .probe = ams_i2c_probe,
+ .remove = ams_i2c_remove,
+ .id_table = ams_id,
};
static s32 ams_i2c_read(u8 reg)
{
- return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg);
+ return i2c_smbus_read_byte_data(ams_info.i2c_client, reg);
}
static int ams_i2c_write(u8 reg, u8 value)
{
- return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value);
+ return i2c_smbus_write_byte_data(ams_info.i2c_client, reg, value);
}
static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
@@ -152,9 +160,9 @@ static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
*z = ams_i2c_read(AMS_DATAZ);
}
-static int ams_i2c_attach(struct i2c_adapter *adapter)
+static int ams_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- unsigned long bus;
int vmaj, vmin;
int result;
@@ -162,17 +170,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
if (unlikely(ams_info.has_device))
return -ENODEV;
- if (strncmp(adapter->name, "uni-n", 5))
- return -ENODEV;
-
- bus = simple_strtoul(adapter->name + 6, NULL, 10);
- if (bus != ams_info.i2c_bus)
- return -ENODEV;
-
- ams_info.i2c_client.addr = ams_info.i2c_address;
- ams_info.i2c_client.adapter = adapter;
- ams_info.i2c_client.driver = &ams_i2c_driver;
- strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
+ ams_info.i2c_client = client;
if (ams_i2c_cmd(AMS_CMD_RESET)) {
printk(KERN_INFO "ams: Failed to reset the device\n");
@@ -237,7 +235,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
return 0;
}
-static int ams_i2c_detach(struct i2c_adapter *adapter)
+static int ams_i2c_remove(struct i2c_client *client)
{
if (ams_info.has_device) {
/* Disable interrupts */
@@ -261,11 +259,7 @@ static void ams_i2c_exit(void)
int __init ams_i2c_init(struct device_node *np)
{
- char *tmp_bus;
int result;
- const u32 *prop;
-
- mutex_lock(&ams_info.lock);
/* Set implementation stuff */
ams_info.of_node = np;
@@ -275,25 +269,7 @@ int __init ams_i2c_init(struct device_node *np)
ams_info.clear_irq = ams_i2c_clear_irq;
ams_info.bustype = BUS_I2C;
- /* look for bus either using "reg" or by path */
- prop = of_get_property(ams_info.of_node, "reg", NULL);
- if (!prop) {
- result = -ENODEV;
-
- goto exit;
- }
-
- tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
- if (tmp_bus)
- ams_info.i2c_bus = *(tmp_bus + 9) - '0';
- else
- ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
- ams_info.i2c_address = ((*prop) & 0xff) >> 1;
-
result = i2c_add_driver(&ams_i2c_driver);
-exit:
- mutex_unlock(&ams_info.lock);
-
return result;
}
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index 7b81e0c2c2d..8a712392cd3 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -20,13 +20,15 @@
#include "ams.h"
static unsigned int joystick;
-module_param(joystick, bool, 0644);
+module_param(joystick, bool, S_IRUGO);
MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
static unsigned int invert;
-module_param(invert, bool, 0644);
+module_param(invert, bool, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
+static DEFINE_MUTEX(ams_input_mutex);
+
static void ams_idev_poll(struct input_polled_dev *dev)
{
struct input_dev *idev = dev->input;
@@ -50,13 +52,11 @@ static void ams_idev_poll(struct input_polled_dev *dev)
}
/* Call with ams_info.lock held! */
-static void ams_input_enable(void)
+static int ams_input_enable(void)
{
struct input_dev *input;
s8 x, y, z;
-
- if (ams_info.idev)
- return;
+ int error;
ams_sensors(&x, &y, &z);
ams_info.xcalib = x;
@@ -65,7 +65,7 @@ static void ams_input_enable(void)
ams_info.idev = input_allocate_polled_device();
if (!ams_info.idev)
- return;
+ return -ENOMEM;
ams_info.idev->poll = ams_idev_poll;
ams_info.idev->poll_interval = 25;
@@ -84,14 +84,18 @@ static void ams_input_enable(void)
set_bit(EV_KEY, input->evbit);
set_bit(BTN_TOUCH, input->keybit);
- if (input_register_polled_device(ams_info.idev)) {
+ error = input_register_polled_device(ams_info.idev);
+ if (error) {
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
- return;
+ return error;
}
+
+ joystick = 1;
+
+ return 0;
}
-/* Call with ams_info.lock held! */
static void ams_input_disable(void)
{
if (ams_info.idev) {
@@ -99,6 +103,8 @@ static void ams_input_disable(void)
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
}
+
+ joystick = 0;
}
static ssize_t ams_input_show_joystick(struct device *dev,
@@ -110,39 +116,42 @@ static ssize_t ams_input_show_joystick(struct device *dev,
static ssize_t ams_input_store_joystick(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- if (sscanf(buf, "%d\n", &joystick) != 1)
+ unsigned long enable;
+ int error = 0;
+
+ if (strict_strtoul(buf, 0, &enable) || enable > 1)
return -EINVAL;
- mutex_lock(&ams_info.lock);
+ mutex_lock(&ams_input_mutex);
- if (joystick)
- ams_input_enable();
- else
- ams_input_disable();
+ if (enable != joystick) {
+ if (enable)
+ error = ams_input_enable();
+ else
+ ams_input_disable();
+ }
- mutex_unlock(&ams_info.lock);
+ mutex_unlock(&ams_input_mutex);
- return count;
+ return error ? error : count;
}
static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
ams_input_show_joystick, ams_input_store_joystick);
-/* Call with ams_info.lock held! */
int ams_input_init(void)
{
- int result;
-
- result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
-
- if (!result && joystick)
+ if (joystick)
ams_input_enable();
- return result;
+
+ return device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
}
-/* Call with ams_info.lock held! */
void ams_input_exit(void)
{
- ams_input_disable();
device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+
+ mutex_lock(&ams_input_mutex);
+ ams_input_disable();
+ mutex_unlock(&ams_input_mutex);
}
diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c
index 9463e9768f6..fb18b3d3162 100644
--- a/drivers/hwmon/ams/ams-pmu.c
+++ b/drivers/hwmon/ams/ams-pmu.c
@@ -149,8 +149,6 @@ int __init ams_pmu_init(struct device_node *np)
const u32 *prop;
int result;
- mutex_lock(&ams_info.lock);
-
/* Set implementation stuff */
ams_info.of_node = np;
ams_info.exit = ams_pmu_exit;
@@ -161,10 +159,9 @@ int __init ams_pmu_init(struct device_node *np)
/* Get PMU command, should be 0x4e, but we can never know */
prop = of_get_property(ams_info.of_node, "reg", NULL);
- if (!prop) {
- result = -ENODEV;
- goto exit;
- }
+ if (!prop)
+ return -ENODEV;
+
ams_pmu_cmd = ((*prop) >> 8) & 0xff;
/* Disable interrupts */
@@ -175,7 +172,7 @@ int __init ams_pmu_init(struct device_node *np)
result = ams_sensor_attach();
if (result < 0)
- goto exit;
+ return result;
/* Set default values */
ams_pmu_set_register(AMS_FF_LOW_LIMIT, 0x15);
@@ -198,10 +195,5 @@ int __init ams_pmu_init(struct device_node *np)
printk(KERN_INFO "ams: Found PMU based motion sensor\n");
- result = 0;
-
-exit:
- mutex_unlock(&ams_info.lock);
-
- return result;
+ return 0;
}
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
index a6221e5dd98..5ed387b0bd9 100644
--- a/drivers/hwmon/ams/ams.h
+++ b/drivers/hwmon/ams/ams.h
@@ -4,7 +4,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
enum ams_irq {
AMS_IRQ_FREEFALL = 0x01,
@@ -46,9 +46,7 @@ struct ams {
#ifdef CONFIG_SENSORS_AMS_I2C
/* I2C properties */
- int i2c_bus;
- int i2c_address;
- struct i2c_client i2c_client;
+ struct i2c_client *i2c_client;
#endif
/* Joystick emulation */
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index d191118ba0c..d6b490d3e36 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -31,7 +31,7 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
-MODULE_VERSION("0.6.2");
+MODULE_VERSION("0.6.3");
MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
#define ATXP1_VID 0x00
@@ -289,16 +289,16 @@ static int atxp1_detect(struct i2c_client *new_client, int kind,
if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
(i2c_smbus_read_byte_data(new_client, 0x3f) == 0) &&
(i2c_smbus_read_byte_data(new_client, 0xfe) == 0) &&
- (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) {
+ (i2c_smbus_read_byte_data(new_client, 0xff) == 0)))
+ return -ENODEV;
- /* No vendor ID, now checking if registers 0x10,0x11 (non-existent)
- * showing the same as register 0x00 */
- temp = i2c_smbus_read_byte_data(new_client, 0x00);
+ /* No vendor ID, now checking if registers 0x10,0x11 (non-existent)
+ * showing the same as register 0x00 */
+ temp = i2c_smbus_read_byte_data(new_client, 0x00);
- if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
- (i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
- return -ENODEV;
- }
+ if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
+ (i2c_smbus_read_byte_data(new_client, 0x11) == temp)))
+ return -ENODEV;
/* Get VRM */
temp = vid_which_vrm();
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index cdb8311e4ef..27a5d397f9a 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -175,11 +175,11 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
* Data structures and manipulation thereof
* --------------------------------------------------------------------- */
-/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
- the driver field to differentiate between I2C and ISA chips. */
struct dme1737_data {
- struct i2c_client client;
+ struct i2c_client *client; /* for I2C devices only */
struct device *hwmon_dev;
+ const char *name;
+ unsigned int addr; /* for ISA devices only */
struct mutex update_lock;
int valid; /* !=0 if following fields are valid */
@@ -512,11 +512,12 @@ static inline int PWM_OFF_TO_REG(int val, int ix, int reg)
* before calling dme1737_read or dme1737_write.
* --------------------------------------------------------------------- */
-static u8 dme1737_read(struct i2c_client *client, u8 reg)
+static u8 dme1737_read(const struct dme1737_data *data, u8 reg)
{
+ struct i2c_client *client = data->client;
s32 val;
- if (client->driver) { /* I2C device */
+ if (client) { /* I2C device */
val = i2c_smbus_read_byte_data(client, reg);
if (val < 0) {
@@ -525,18 +526,19 @@ static u8 dme1737_read(struct i2c_client *client, u8 reg)
"maintainer.\n", reg);
}
} else { /* ISA device */
- outb(reg, client->addr);
- val = inb(client->addr + 1);
+ outb(reg, data->addr);
+ val = inb(data->addr + 1);
}
return val;
}
-static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
+static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val)
{
+ struct i2c_client *client = data->client;
s32 res = 0;
- if (client->driver) { /* I2C device */
+ if (client) { /* I2C device */
res = i2c_smbus_write_byte_data(client, reg, val);
if (res < 0) {
@@ -545,8 +547,8 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
"maintainer.\n", reg);
}
} else { /* ISA device */
- outb(reg, client->addr);
- outb(val, client->addr + 1);
+ outb(reg, data->addr);
+ outb(val, data->addr + 1);
}
return res;
@@ -555,7 +557,6 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
static struct dme1737_data *dme1737_update_device(struct device *dev)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
int ix;
u8 lsb[5];
@@ -563,7 +564,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* Enable a Vbat monitoring cycle every 10 mins */
if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) {
- dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client,
+ dme1737_write(data, DME1737_REG_CONFIG, dme1737_read(data,
DME1737_REG_CONFIG) | 0x10);
data->last_vbat = jiffies;
}
@@ -571,7 +572,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* Sample register contents every 1 sec */
if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
if (data->type != sch5027) {
- data->vid = dme1737_read(client, DME1737_REG_VID) &
+ data->vid = dme1737_read(data, DME1737_REG_VID) &
0x3f;
}
@@ -580,11 +581,11 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* Voltage inputs are stored as 16 bit values even
* though they have only 12 bits resolution. This is
* to make it consistent with the temp inputs. */
- data->in[ix] = dme1737_read(client,
+ data->in[ix] = dme1737_read(data,
DME1737_REG_IN(ix)) << 8;
- data->in_min[ix] = dme1737_read(client,
+ data->in_min[ix] = dme1737_read(data,
DME1737_REG_IN_MIN(ix));
- data->in_max[ix] = dme1737_read(client,
+ data->in_max[ix] = dme1737_read(data,
DME1737_REG_IN_MAX(ix));
}
@@ -595,14 +596,14 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
* to take advantage of implicit conversions between
* register values (2's complement) and temp values
* (signed decimal). */
- data->temp[ix] = dme1737_read(client,
+ data->temp[ix] = dme1737_read(data,
DME1737_REG_TEMP(ix)) << 8;
- data->temp_min[ix] = dme1737_read(client,
+ data->temp_min[ix] = dme1737_read(data,
DME1737_REG_TEMP_MIN(ix));
- data->temp_max[ix] = dme1737_read(client,
+ data->temp_max[ix] = dme1737_read(data,
DME1737_REG_TEMP_MAX(ix));
if (data->type != sch5027) {
- data->temp_offset[ix] = dme1737_read(client,
+ data->temp_offset[ix] = dme1737_read(data,
DME1737_REG_TEMP_OFFSET(ix));
}
}
@@ -612,7 +613,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
* which the registers are read (MSB first, then LSB) is
* important! */
for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
- lsb[ix] = dme1737_read(client,
+ lsb[ix] = dme1737_read(data,
DME1737_REG_IN_TEMP_LSB(ix));
}
for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
@@ -631,19 +632,19 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
if (!(data->has_fan & (1 << ix))) {
continue;
}
- data->fan[ix] = dme1737_read(client,
+ data->fan[ix] = dme1737_read(data,
DME1737_REG_FAN(ix));
- data->fan[ix] |= dme1737_read(client,
+ data->fan[ix] |= dme1737_read(data,
DME1737_REG_FAN(ix) + 1) << 8;
- data->fan_min[ix] = dme1737_read(client,
+ data->fan_min[ix] = dme1737_read(data,
DME1737_REG_FAN_MIN(ix));
- data->fan_min[ix] |= dme1737_read(client,
+ data->fan_min[ix] |= dme1737_read(data,
DME1737_REG_FAN_MIN(ix) + 1) << 8;
- data->fan_opt[ix] = dme1737_read(client,
+ data->fan_opt[ix] = dme1737_read(data,
DME1737_REG_FAN_OPT(ix));
/* fan_max exists only for fan[5-6] */
if (ix > 3) {
- data->fan_max[ix - 4] = dme1737_read(client,
+ data->fan_max[ix - 4] = dme1737_read(data,
DME1737_REG_FAN_MAX(ix));
}
}
@@ -655,63 +656,63 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
if (!(data->has_pwm & (1 << ix))) {
continue;
}
- data->pwm[ix] = dme1737_read(client,
+ data->pwm[ix] = dme1737_read(data,
DME1737_REG_PWM(ix));
- data->pwm_freq[ix] = dme1737_read(client,
+ data->pwm_freq[ix] = dme1737_read(data,
DME1737_REG_PWM_FREQ(ix));
/* pwm_config and pwm_min exist only for pwm[1-3] */
if (ix < 3) {
- data->pwm_config[ix] = dme1737_read(client,
+ data->pwm_config[ix] = dme1737_read(data,
DME1737_REG_PWM_CONFIG(ix));
- data->pwm_min[ix] = dme1737_read(client,
+ data->pwm_min[ix] = dme1737_read(data,
DME1737_REG_PWM_MIN(ix));
}
}
for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) {
- data->pwm_rr[ix] = dme1737_read(client,
+ data->pwm_rr[ix] = dme1737_read(data,
DME1737_REG_PWM_RR(ix));
}
/* Thermal zone registers */
for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {
- data->zone_low[ix] = dme1737_read(client,
+ data->zone_low[ix] = dme1737_read(data,
DME1737_REG_ZONE_LOW(ix));
- data->zone_abs[ix] = dme1737_read(client,
+ data->zone_abs[ix] = dme1737_read(data,
DME1737_REG_ZONE_ABS(ix));
}
if (data->type != sch5027) {
for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {
- data->zone_hyst[ix] = dme1737_read(client,
+ data->zone_hyst[ix] = dme1737_read(data,
DME1737_REG_ZONE_HYST(ix));
}
}
/* Alarm registers */
- data->alarms = dme1737_read(client,
+ data->alarms = dme1737_read(data,
DME1737_REG_ALARM1);
/* Bit 7 tells us if the other alarm registers are non-zero and
* therefore also need to be read */
if (data->alarms & 0x80) {
- data->alarms |= dme1737_read(client,
+ data->alarms |= dme1737_read(data,
DME1737_REG_ALARM2) << 8;
- data->alarms |= dme1737_read(client,
+ data->alarms |= dme1737_read(data,
DME1737_REG_ALARM3) << 16;
}
/* The ISA chips require explicit clearing of alarm bits.
* Don't worry, an alarm will come back if the condition
* that causes it still exists */
- if (!client->driver) {
+ if (!data->client) {
if (data->alarms & 0xff0000) {
- dme1737_write(client, DME1737_REG_ALARM3,
+ dme1737_write(data, DME1737_REG_ALARM3,
0xff);
}
if (data->alarms & 0xff00) {
- dme1737_write(client, DME1737_REG_ALARM2,
+ dme1737_write(data, DME1737_REG_ALARM2,
0xff);
}
if (data->alarms & 0xff) {
- dme1737_write(client, DME1737_REG_ALARM1,
+ dme1737_write(data, DME1737_REG_ALARM1,
0xff);
}
}
@@ -770,7 +771,6 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
struct sensor_device_attribute_2
*sensor_attr_2 = to_sensor_dev_attr_2(attr);
int ix = sensor_attr_2->index;
@@ -781,12 +781,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
switch (fn) {
case SYS_IN_MIN:
data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]);
- dme1737_write(client, DME1737_REG_IN_MIN(ix),
+ dme1737_write(data, DME1737_REG_IN_MIN(ix),
data->in_min[ix]);
break;
case SYS_IN_MAX:
data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]);
- dme1737_write(client, DME1737_REG_IN_MAX(ix),
+ dme1737_write(data, DME1737_REG_IN_MAX(ix),
data->in_max[ix]);
break;
default:
@@ -850,7 +850,6 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
struct sensor_device_attribute_2
*sensor_attr_2 = to_sensor_dev_attr_2(attr);
int ix = sensor_attr_2->index;
@@ -861,17 +860,17 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
switch (fn) {
case SYS_TEMP_MIN:
data->temp_min[ix] = TEMP_TO_REG(val);
- dme1737_write(client, DME1737_REG_TEMP_MIN(ix),
+ dme1737_write(data, DME1737_REG_TEMP_MIN(ix),
data->temp_min[ix]);
break;
case SYS_TEMP_MAX:
data->temp_max[ix] = TEMP_TO_REG(val);
- dme1737_write(client, DME1737_REG_TEMP_MAX(ix),
+ dme1737_write(data, DME1737_REG_TEMP_MAX(ix),
data->temp_max[ix]);
break;
case SYS_TEMP_OFFSET:
data->temp_offset[ix] = TEMP_TO_REG(val);
- dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix),
+ dme1737_write(data, DME1737_REG_TEMP_OFFSET(ix),
data->temp_offset[ix]);
break;
default:
@@ -939,7 +938,6 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
struct sensor_device_attribute_2
*sensor_attr_2 = to_sensor_dev_attr_2(attr);
int ix = sensor_attr_2->index;
@@ -950,37 +948,37 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
switch (fn) {
case SYS_ZONE_AUTO_POINT1_TEMP_HYST:
/* Refresh the cache */
- data->zone_low[ix] = dme1737_read(client,
+ data->zone_low[ix] = dme1737_read(data,
DME1737_REG_ZONE_LOW(ix));
/* Modify the temp hyst value */
data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG(
TEMP_FROM_REG(data->zone_low[ix], 8) -
- val, ix, dme1737_read(client,
+ val, ix, dme1737_read(data,
DME1737_REG_ZONE_HYST(ix == 2)));
- dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2),
+ dme1737_write(data, DME1737_REG_ZONE_HYST(ix == 2),
data->zone_hyst[ix == 2]);
break;
case SYS_ZONE_AUTO_POINT1_TEMP:
data->zone_low[ix] = TEMP_TO_REG(val);
- dme1737_write(client, DME1737_REG_ZONE_LOW(ix),
+ dme1737_write(data, DME1737_REG_ZONE_LOW(ix),
data->zone_low[ix]);
break;
case SYS_ZONE_AUTO_POINT2_TEMP:
/* Refresh the cache */
- data->zone_low[ix] = dme1737_read(client,
+ data->zone_low[ix] = dme1737_read(data,
DME1737_REG_ZONE_LOW(ix));
/* Modify the temp range value (which is stored in the upper
* nibble of the pwm_freq register) */
data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val -
TEMP_FROM_REG(data->zone_low[ix], 8),
- dme1737_read(client,
+ dme1737_read(data,
DME1737_REG_PWM_FREQ(ix)));
- dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+ dme1737_write(data, DME1737_REG_PWM_FREQ(ix),
data->pwm_freq[ix]);
break;
case SYS_ZONE_AUTO_POINT3_TEMP:
data->zone_abs[ix] = TEMP_TO_REG(val);
- dme1737_write(client, DME1737_REG_ZONE_ABS(ix),
+ dme1737_write(data, DME1737_REG_ZONE_ABS(ix),
data->zone_abs[ix]);
break;
default:
@@ -1046,7 +1044,6 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
struct sensor_device_attribute_2
*sensor_attr_2 = to_sensor_dev_attr_2(attr);
int ix = sensor_attr_2->index;
@@ -1060,21 +1057,21 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
data->fan_min[ix] = FAN_TO_REG(val, 0);
} else {
/* Refresh the cache */
- data->fan_opt[ix] = dme1737_read(client,
+ data->fan_opt[ix] = dme1737_read(data,
DME1737_REG_FAN_OPT(ix));
/* Modify the fan min value */
data->fan_min[ix] = FAN_TO_REG(val,
FAN_TPC_FROM_REG(data->fan_opt[ix]));
}
- dme1737_write(client, DME1737_REG_FAN_MIN(ix),
+ dme1737_write(data, DME1737_REG_FAN_MIN(ix),
data->fan_min[ix] & 0xff);
- dme1737_write(client, DME1737_REG_FAN_MIN(ix) + 1,
+ dme1737_write(data, DME1737_REG_FAN_MIN(ix) + 1,
data->fan_min[ix] >> 8);
break;
case SYS_FAN_MAX:
/* Only valid for fan[5-6] */
data->fan_max[ix - 4] = FAN_MAX_TO_REG(val);
- dme1737_write(client, DME1737_REG_FAN_MAX(ix),
+ dme1737_write(data, DME1737_REG_FAN_MAX(ix),
data->fan_max[ix - 4]);
break;
case SYS_FAN_TYPE:
@@ -1086,9 +1083,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
val);
goto exit;
}
- data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(client,
+ data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(data,
DME1737_REG_FAN_OPT(ix)));
- dme1737_write(client, DME1737_REG_FAN_OPT(ix),
+ dme1737_write(data, DME1737_REG_FAN_OPT(ix),
data->fan_opt[ix]);
break;
default:
@@ -1185,7 +1182,6 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
struct sensor_device_attribute_2
*sensor_attr_2 = to_sensor_dev_attr_2(attr);
int ix = sensor_attr_2->index;
@@ -1196,12 +1192,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
switch (fn) {
case SYS_PWM:
data->pwm[ix] = SENSORS_LIMIT(val, 0, 255);
- dme1737_write(client, DME1737_REG_PWM(ix), data->pwm[ix]);
+ dme1737_write(data, DME1737_REG_PWM(ix), data->pwm[ix]);
break;
case SYS_PWM_FREQ:
- data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(client,
+ data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(data,
DME1737_REG_PWM_FREQ(ix)));
- dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+ dme1737_write(data, DME1737_REG_PWM_FREQ(ix),
data->pwm_freq[ix]);
break;
case SYS_PWM_ENABLE:
@@ -1214,7 +1210,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
goto exit;
}
/* Refresh the cache */
- data->pwm_config[ix] = dme1737_read(client,
+ data->pwm_config[ix] = dme1737_read(data,
DME1737_REG_PWM_CONFIG(ix));
if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) {
/* Bail out if no change */
@@ -1226,14 +1222,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
data->pwm_acz[ix] = PWM_ACZ_FROM_REG(
data->pwm_config[ix]);
/* Save the current ramp rate state and disable it */
- data->pwm_rr[ix > 0] = dme1737_read(client,
+ data->pwm_rr[ix > 0] = dme1737_read(data,
DME1737_REG_PWM_RR(ix > 0));
data->pwm_rr_en &= ~(1 << ix);
if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) {
data->pwm_rr_en |= (1 << ix);
data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix,
data->pwm_rr[ix > 0]);
- dme1737_write(client,
+ dme1737_write(data,
DME1737_REG_PWM_RR(ix > 0),
data->pwm_rr[ix > 0]);
}
@@ -1247,14 +1243,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
/* Turn fan fully on */
data->pwm_config[ix] = PWM_EN_TO_REG(0,
data->pwm_config[ix]);
- dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+ dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
data->pwm_config[ix]);
break;
case 1:
/* Turn on manual mode */
data->pwm_config[ix] = PWM_EN_TO_REG(1,
data->pwm_config[ix]);
- dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+ dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
data->pwm_config[ix]);
/* Change permissions of pwm[ix] to read-writeable */
dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix],
@@ -1269,14 +1265,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
data->pwm_config[ix] = PWM_ACZ_TO_REG(
data->pwm_acz[ix],
data->pwm_config[ix]);
- dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+ dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
data->pwm_config[ix]);
/* Enable PWM ramp rate if previously enabled */
if (data->pwm_rr_en & (1 << ix)) {
data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix,
- dme1737_read(client,
+ dme1737_read(data,
DME1737_REG_PWM_RR(ix > 0)));
- dme1737_write(client,
+ dme1737_write(data,
DME1737_REG_PWM_RR(ix > 0),
data->pwm_rr[ix > 0]);
}
@@ -1286,9 +1282,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
case SYS_PWM_RAMP_RATE:
/* Only valid for pwm[1-3] */
/* Refresh the cache */
- data->pwm_config[ix] = dme1737_read(client,
+ data->pwm_config[ix] = dme1737_read(data,
DME1737_REG_PWM_CONFIG(ix));
- data->pwm_rr[ix > 0] = dme1737_read(client,
+ data->pwm_rr[ix > 0] = dme1737_read(data,
DME1737_REG_PWM_RR(ix > 0));
/* Set the ramp rate value */
if (val > 0) {
@@ -1301,7 +1297,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix,
data->pwm_rr[ix > 0]);
}
- dme1737_write(client, DME1737_REG_PWM_RR(ix > 0),
+ dme1737_write(data, DME1737_REG_PWM_RR(ix > 0),
data->pwm_rr[ix > 0]);
break;
case SYS_PWM_AUTO_CHANNELS_ZONE:
@@ -1315,14 +1311,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
goto exit;
}
/* Refresh the cache */
- data->pwm_config[ix] = dme1737_read(client,
+ data->pwm_config[ix] = dme1737_read(data,
DME1737_REG_PWM_CONFIG(ix));
if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
/* PWM is already in auto mode so update the temp
* channel assignment */
data->pwm_config[ix] = PWM_ACZ_TO_REG(val,
data->pwm_config[ix]);
- dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+ dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
data->pwm_config[ix]);
} else {
/* PWM is not in auto mode so we save the temp
@@ -1333,7 +1329,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
case SYS_PWM_AUTO_PWM_MIN:
/* Only valid for pwm[1-3] */
/* Refresh the cache */
- data->pwm_min[ix] = dme1737_read(client,
+ data->pwm_min[ix] = dme1737_read(data,
DME1737_REG_PWM_MIN(ix));
/* There are only 2 values supported for the auto_pwm_min
* value: 0 or auto_point1_pwm. So if the temperature drops
@@ -1341,20 +1337,20 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
* off or runs at auto_point1_pwm duty-cycle. */
if (val > ((data->pwm_min[ix] + 1) / 2)) {
data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix,
- dme1737_read(client,
+ dme1737_read(data,
DME1737_REG_PWM_RR(0)));
} else {
data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix,
- dme1737_read(client,
+ dme1737_read(data,
DME1737_REG_PWM_RR(0)));
}
- dme1737_write(client, DME1737_REG_PWM_RR(0),
+ dme1737_write(data, DME1737_REG_PWM_RR(0),
data->pwm_rr[0]);
break;
case SYS_PWM_AUTO_POINT1_PWM:
/* Only valid for pwm[1-3] */
data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255);
- dme1737_write(client, DME1737_REG_PWM_MIN(ix),
+ dme1737_write(data, DME1737_REG_PWM_MIN(ix),
data->pwm_min[ix]);
break;
default:
@@ -1402,7 +1398,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr,
{
struct dme1737_data *data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", data->client.name);
+ return sprintf(buf, "%s\n", data->name);
}
/* ---------------------------------------------------------------------
@@ -1908,7 +1904,7 @@ static void dme1737_remove_files(struct device *dev)
sysfs_remove_group(&dev->kobj, &dme1737_group);
- if (!data->client.driver) {
+ if (!data->client) {
sysfs_remove_file(&dev->kobj, &dev_attr_name.attr);
}
}
@@ -1919,7 +1915,7 @@ static int dme1737_create_files(struct device *dev)
int err, ix;
/* Create a name attribute for ISA devices */
- if (!data->client.driver &&
+ if (!data->client &&
(err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) {
goto exit;
}
@@ -2013,14 +2009,14 @@ exit:
static int dme1737_init_device(struct device *dev)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
+ struct i2c_client *client = data->client;
int ix;
u8 reg;
/* Point to the right nominal voltages array */
data->in_nominal = IN_NOMINAL(data->type);
- data->config = dme1737_read(client, DME1737_REG_CONFIG);
+ data->config = dme1737_read(data, DME1737_REG_CONFIG);
/* Inform if part is not monitoring/started */
if (!(data->config & 0x01)) {
if (!force_start) {
@@ -2032,7 +2028,7 @@ static int dme1737_init_device(struct device *dev)
/* Force monitoring */
data->config |= 0x01;
- dme1737_write(client, DME1737_REG_CONFIG, data->config);
+ dme1737_write(data, DME1737_REG_CONFIG, data->config);
}
/* Inform if part is not ready */
if (!(data->config & 0x04)) {
@@ -2041,8 +2037,8 @@ static int dme1737_init_device(struct device *dev)
}
/* Determine which optional fan and pwm features are enabled/present */
- if (client->driver) { /* I2C chip */
- data->config2 = dme1737_read(client, DME1737_REG_CONFIG2);
+ if (client) { /* I2C chip */
+ data->config2 = dme1737_read(data, DME1737_REG_CONFIG2);
/* Check if optional fan3 input is enabled */
if (data->config2 & 0x04) {
data->has_fan |= (1 << 2);
@@ -2051,7 +2047,7 @@ static int dme1737_init_device(struct device *dev)
/* Fan4 and pwm3 are only available if the client's I2C address
* is the default 0x2e. Otherwise the I/Os associated with
* these functions are used for addr enable/select. */
- if (data->client.addr == 0x2e) {
+ if (client->addr == 0x2e) {
data->has_fan |= (1 << 3);
data->has_pwm |= (1 << 2);
}
@@ -2086,16 +2082,16 @@ static int dme1737_init_device(struct device *dev)
(data->has_fan & (1 << 4)) ? "yes" : "no",
(data->has_fan & (1 << 5)) ? "yes" : "no");
- reg = dme1737_read(client, DME1737_REG_TACH_PWM);
+ reg = dme1737_read(data, DME1737_REG_TACH_PWM);
/* Inform if fan-to-pwm mapping differs from the default */
- if (client->driver && reg != 0xa4) { /* I2C chip */
+ if (client && reg != 0xa4) { /* I2C chip */
dev_warn(dev, "Non-standard fan to pwm mapping: "
"fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "
"fan4->pwm%d. Please report to the driver "
"maintainer.\n",
(reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);
- } else if (!client->driver && reg != 0x24) { /* ISA chip */
+ } else if (!client && reg != 0x24) { /* ISA chip */
dev_warn(dev, "Non-standard fan to pwm mapping: "
"fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. "
"Please report to the driver maintainer.\n",
@@ -2108,7 +2104,7 @@ static int dme1737_init_device(struct device *dev)
* disabled). */
if (!(data->config & 0x02)) {
for (ix = 0; ix < 3; ix++) {
- data->pwm_config[ix] = dme1737_read(client,
+ data->pwm_config[ix] = dme1737_read(data,
DME1737_REG_PWM_CONFIG(ix));
if ((data->has_pwm & (1 << ix)) &&
(PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
@@ -2116,8 +2112,8 @@ static int dme1737_init_device(struct device *dev)
"manual mode.\n", ix + 1);
data->pwm_config[ix] = PWM_EN_TO_REG(1,
data->pwm_config[ix]);
- dme1737_write(client, DME1737_REG_PWM(ix), 0);
- dme1737_write(client,
+ dme1737_write(data, DME1737_REG_PWM(ix), 0);
+ dme1737_write(data,
DME1737_REG_PWM_CONFIG(ix),
data->pwm_config[ix]);
}
@@ -2191,37 +2187,24 @@ exit:
return err;
}
-static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int dme1737_i2c_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
+ struct i2c_adapter *adapter = client->adapter;
+ struct device *dev = &adapter->dev;
u8 company, verstep = 0;
- struct i2c_client *client;
- struct dme1737_data *data;
- struct device *dev;
- int err = 0;
const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- goto exit;
- }
-
- if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
+ return -ENODEV;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &dme1737_i2c_driver;
- dev = &client->dev;
-
/* A negative kind means that the driver was loaded with no force
* parameter (default), so we must identify the chip. */
if (kind < 0) {
- company = dme1737_read(client, DME1737_REG_COMPANY);
- verstep = dme1737_read(client, DME1737_REG_VERSTEP);
+ company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
+ verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
if (company == DME1737_COMPANY_SMSC &&
(verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
@@ -2230,8 +2213,7 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
verstep == SCH5027_VERSTEP) {
kind = sch5027;
} else {
- err = -ENODEV;
- goto exit_kfree;
+ return -ENODEV;
}
}
@@ -2241,32 +2223,44 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
kind = dme1737;
name = "dme1737";
}
- data->type = kind;
-
- /* Fill in the remaining client fields and put it into the global
- * list */
- strlcpy(client->name, name, I2C_NAME_SIZE);
- mutex_init(&data->update_lock);
-
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client))) {
- goto exit_kfree;
- }
dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n",
kind == sch5027 ? "SCH5027" : "DME1737", client->addr,
verstep);
+ strlcpy(info->type, name, I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int dme1737_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct dme1737_data *data;
+ struct device *dev = &client->dev;
+ int err;
+
+ data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->type = id->driver_data;
+ data->client = client;
+ data->name = client->name;
+ mutex_init(&data->update_lock);
/* Initialize the DME1737 chip */
if ((err = dme1737_init_device(dev))) {
dev_err(dev, "Failed to initialize device.\n");
- goto exit_detach;
+ goto exit_kfree;
}
/* Create sysfs files */
if ((err = dme1737_create_files(dev))) {
dev_err(dev, "Failed to create sysfs files.\n");
- goto exit_detach;
+ goto exit_kfree;
}
/* Register device */
@@ -2281,45 +2275,40 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
exit_remove:
dme1737_remove_files(dev);
-exit_detach:
- i2c_detach_client(client);
exit_kfree:
kfree(data);
exit:
return err;
}
-static int dme1737_i2c_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON)) {
- return 0;
- }
-
- return i2c_probe(adapter, &addr_data, dme1737_i2c_detect);
-}
-
-static int dme1737_i2c_detach_client(struct i2c_client *client)
+static int dme1737_i2c_remove(struct i2c_client *client)
{
struct dme1737_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
dme1737_remove_files(&client->dev);
- if ((err = i2c_detach_client(client))) {
- return err;
- }
-
kfree(data);
return 0;
}
+static const struct i2c_device_id dme1737_id[] = {
+ { "dme1737", dme1737 },
+ { "sch5027", sch5027 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, dme1737_id);
+
static struct i2c_driver dme1737_i2c_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "dme1737",
},
- .attach_adapter = dme1737_i2c_attach_adapter,
- .detach_client = dme1737_i2c_detach_client,
+ .probe = dme1737_i2c_probe,
+ .remove = dme1737_i2c_remove,
+ .id_table = dme1737_id,
+ .detect = dme1737_i2c_detect,
+ .address_data = &addr_data,
};
/* ---------------------------------------------------------------------
@@ -2403,7 +2392,6 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
{
u8 company, device;
struct resource *res;
- struct i2c_client *client;
struct dme1737_data *data;
struct device *dev = &pdev->dev;
int err;
@@ -2422,15 +2410,13 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
goto exit_release_region;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = res->start;
+ data->addr = res->start;
platform_set_drvdata(pdev, data);
/* Skip chip detection if module is loaded with force_id parameter */
if (!force_id) {
- company = dme1737_read(client, DME1737_REG_COMPANY);
- device = dme1737_read(client, DME1737_REG_DEVICE);
+ company = dme1737_read(data, DME1737_REG_COMPANY);
+ device = dme1737_read(data, DME1737_REG_DEVICE);
if (!((company == DME1737_COMPANY_SMSC) &&
(device == SCH311X_DEVICE))) {
@@ -2441,10 +2427,10 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
data->type = sch311x;
/* Fill in the remaining client fields and initialize the mutex */
- strlcpy(client->name, "sch311x", I2C_NAME_SIZE);
+ data->name = "sch311x";
mutex_init(&data->update_lock);
- dev_info(dev, "Found a SCH311x chip at 0x%04x\n", client->addr);
+ dev_info(dev, "Found a SCH311x chip at 0x%04x\n", data->addr);
/* Initialize the chip */
if ((err = dme1737_init_device(dev))) {
@@ -2485,7 +2471,7 @@ static int __devexit dme1737_isa_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
dme1737_remove_files(&pdev->dev);
- release_region(data->client.addr, DME1737_EXTENT);
+ release_region(data->addr, DME1737_EXTENT);
platform_set_drvdata(pdev, NULL);
kfree(data);
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 7321a88a511..076a59cdabe 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,8 +55,8 @@ again:
return ERR_PTR(err);
id = id & MAX_ID_MASK;
- hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
- HWMON_ID_FORMAT, id);
+ hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
+ HWMON_ID_FORMAT, id);
if (IS_ERR(hwdev)) {
spin_lock(&idr_lock);
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 0f70dc20410..7b0ed5dea39 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -1118,3 +1118,10 @@ MODULE_LICENSE("GPL");
module_init(aem_init);
module_exit(aem_exit);
+
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBM3850M2/x3950M2-*");
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index 4e9b19c6732..537d9fb2ff8 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -608,3 +608,9 @@ MODULE_LICENSE("GPL");
module_init(ibmpex_init);
module_exit(ibmpex_exit);
+
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 30cdb095677..b74c95735f9 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -46,6 +46,8 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/dmi.h>
#include <asm/io.h>
#define DRVNAME "it87"
@@ -236,6 +238,8 @@ struct it87_sio_data {
/* Values read from Super-I/O config space */
u8 revision;
u8 vid_value;
+ /* Values set based on DMI strings */
+ u8 skip_pwm;
};
/* For each registered chip, we need to keep some data in memory.
@@ -273,10 +277,10 @@ struct it87_data {
static inline int has_16bit_fans(const struct it87_data *data)
{
/* IT8705F Datasheet 0.4.1, 3h == Version G.
- IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I.
+ IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
These are the first revisions with 16bit tachometer support. */
return (data->type == it87 && data->revision >= 0x03)
- || (data->type == it8712 && data->revision >= 0x07)
+ || (data->type == it8712 && data->revision >= 0x08)
|| data->type == it8716
|| data->type == it8718;
}
@@ -473,7 +477,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
if (reg & (1 << nr))
return sprintf(buf, "3\n"); /* thermal diode */
if (reg & (8 << nr))
- return sprintf(buf, "2\n"); /* thermistor */
+ return sprintf(buf, "4\n"); /* thermistor */
return sprintf(buf, "0\n"); /* disabled */
}
static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
@@ -489,10 +493,15 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
data->sensor &= ~(1 << nr);
data->sensor &= ~(8 << nr);
- /* 3 = thermal diode; 2 = thermistor; 0 = disabled */
+ if (val == 2) { /* backwards compatibility */
+ dev_warn(dev, "Sensor type 2 is deprecated, please use 4 "
+ "instead\n");
+ val = 4;
+ }
+ /* 3 = thermal diode; 4 = thermistor; 0 = disabled */
if (val == 3)
data->sensor |= 1 << nr;
- else if (val == 2)
+ else if (val == 4)
data->sensor |= 8 << nr;
else if (val != 0) {
mutex_unlock(&data->update_lock);
@@ -964,6 +973,7 @@ static int __init it87_find(unsigned short *address,
{
int err = -ENODEV;
u16 chip_type;
+ const char *board_vendor, *board_name;
superio_enter();
chip_type = force_id ? force_id : superio_inw(DEVID);
@@ -1022,6 +1032,24 @@ static int __init it87_find(unsigned short *address,
pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
}
+ /* Disable specific features based on DMI strings */
+ board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+ board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ if (board_vendor && board_name) {
+ if (strcmp(board_vendor, "nVIDIA") == 0
+ && strcmp(board_name, "FN68PT") == 0) {
+ /* On the Shuttle SN68PT, FAN_CTL2 is apparently not
+ connected to a fan, but to something else. One user
+ has reported instant system power-off when changing
+ the PWM2 duty cycle, so we disable it.
+ I use the board name string as the trigger in case
+ the same board is ever used in other systems. */
+ pr_info("it87: Disabling pwm2 due to "
+ "hardware constraints\n");
+ sio_data->skip_pwm = (1 << 1);
+ }
+ }
+
exit:
superio_exit();
return err;
@@ -1168,25 +1196,33 @@ static int __devinit it87_probe(struct platform_device *pdev)
}
if (enable_pwm_interface) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_pwm1_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm2_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm3_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm1.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm2.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm3.dev_attr))
- || (err = device_create_file(dev,
- &dev_attr_pwm1_freq))
- || (err = device_create_file(dev,
- &dev_attr_pwm2_freq))
- || (err = device_create_file(dev,
- &dev_attr_pwm3_freq)))
- goto ERROR4;
+ if (!(sio_data->skip_pwm & (1 << 0))) {
+ if ((err = device_create_file(dev,
+ &sensor_dev_attr_pwm1_enable.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_pwm1.dev_attr))
+ || (err = device_create_file(dev,
+ &dev_attr_pwm1_freq)))
+ goto ERROR4;
+ }
+ if (!(sio_data->skip_pwm & (1 << 1))) {
+ if ((err = device_create_file(dev,
+ &sensor_dev_attr_pwm2_enable.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_pwm2.dev_attr))
+ || (err = device_create_file(dev,
+ &dev_attr_pwm2_freq)))
+ goto ERROR4;
+ }
+ if (!(sio_data->skip_pwm & (1 << 2))) {
+ if ((err = device_create_file(dev,
+ &sensor_dev_attr_pwm3_enable.dev_attr))
+ || (err = device_create_file(dev,
+ &sensor_dev_attr_pwm3.dev_attr))
+ || (err = device_create_file(dev,
+ &dev_attr_pwm3_freq)))
+ goto ERROR4;
+ }
}
if (data->type == it8712 || data->type == it8716
@@ -1546,6 +1582,7 @@ static int __init sm_it87_init(void)
unsigned short isa_address=0;
struct it87_sio_data sio_data;
+ memset(&sio_data, 0, sizeof(struct it87_sio_data));
err = it87_find(&isa_address, &sio_data);
if (err)
return err;
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index ed7859f0e16..b5e3b285169 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -114,25 +114,16 @@ static inline int TEMP_FROM_REG(s8 val)
#define DIV_FROM_REG(val) (1 << (val))
-/* There are some complications in a module like this. First off, LM78 chips
- may be both present on the SMBus and the ISA bus, and we have to handle
- those cases separately at some places. Second, there might be several
- LM78 chips available (well, actually, that is probably never done; but
- it is a clean illustration of how to handle a case like that). Finally,
- a specific chip may be attached to *both* ISA and SMBus, and we would
- not like to detect it double. Fortunately, in the case of the LM78 at
- least, a register tells us what SMBus address we are on, so that helps
- a bit - except if there could be more than one SMBus. Groan. No solution
- for this yet. */
-
-/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
- the driver field to differentiate between I2C and ISA chips. */
struct lm78_data {
- struct i2c_client client;
+ struct i2c_client *client;
struct device *hwmon_dev;
struct mutex lock;
enum chips type;
+ /* For ISA device only */
+ const char *name;
+ int isa_addr;
+
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -151,9 +142,11 @@ struct lm78_data {
};
-static int lm78_attach_adapter(struct i2c_adapter *adapter);
-static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
-static int lm78_detach_client(struct i2c_client *client);
+static int lm78_i2c_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int lm78_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm78_i2c_remove(struct i2c_client *client);
static int __devinit lm78_isa_probe(struct platform_device *pdev);
static int __devexit lm78_isa_remove(struct platform_device *pdev);
@@ -164,12 +157,23 @@ static struct lm78_data *lm78_update_device(struct device *dev);
static void lm78_init_device(struct lm78_data *data);
+static const struct i2c_device_id lm78_i2c_id[] = {
+ { "lm78", lm78 },
+ { "lm79", lm79 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
+
static struct i2c_driver lm78_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm78",
},
- .attach_adapter = lm78_attach_adapter,
- .detach_client = lm78_detach_client,
+ .probe = lm78_i2c_probe,
+ .remove = lm78_i2c_remove,
+ .id_table = lm78_i2c_id,
+ .detect = lm78_i2c_detect,
+ .address_data = &addr_data,
};
static struct platform_driver lm78_isa_driver = {
@@ -454,17 +458,6 @@ static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
-/* This function is called when:
- * lm78_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and lm78_driver is still present) */
-static int lm78_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm78_detect);
-}
-
static struct attribute *lm78_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
@@ -527,54 +520,77 @@ static ssize_t show_name(struct device *dev, struct device_attribute
{
struct lm78_data *data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", data->client.name);
+ return sprintf(buf, "%s\n", data->name);
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-/* This function is called by i2c_probe */
-static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
+/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
+static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
{
- int i, err;
- struct i2c_client *new_client;
- struct lm78_data *data;
- const char *client_name = "";
+ struct lm78_data *isa;
+ int i;
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- err = -ENODEV;
- goto ERROR1;
+ if (!pdev) /* No ISA chip */
+ return 0;
+ isa = platform_get_drvdata(pdev);
+
+ if (lm78_read_value(isa, LM78_REG_I2C_ADDR) != client->addr)
+ return 0; /* Address doesn't match */
+ if ((lm78_read_value(isa, LM78_REG_CHIPID) & 0xfe) != (chipid & 0xfe))
+ return 0; /* Chip type doesn't match */
+
+ /* We compare all the limit registers, the config register and the
+ * interrupt mask registers */
+ for (i = 0x2b; i <= 0x3d; i++) {
+ if (lm78_read_value(isa, i) !=
+ i2c_smbus_read_byte_data(client, i))
+ return 0;
}
+ if (lm78_read_value(isa, LM78_REG_CONFIG) !=
+ i2c_smbus_read_byte_data(client, LM78_REG_CONFIG))
+ return 0;
+ for (i = 0x43; i <= 0x46; i++) {
+ if (lm78_read_value(isa, i) !=
+ i2c_smbus_read_byte_data(client, i))
+ return 0;
+ }
+
+ return 1;
+}
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access lm78_{read,write}_value. */
+static int lm78_i2c_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ int i;
+ struct lm78_data *isa = pdev ? platform_get_drvdata(pdev) : NULL;
+ const char *client_name;
+ struct i2c_adapter *adapter = client->adapter;
+ int address = client->addr;
- if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto ERROR1;
- }
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &lm78_driver;
+ /* We block updates of the ISA device to minimize the risk of
+ concurrent access to the same LM78 chip through different
+ interfaces. */
+ if (isa)
+ mutex_lock(&isa->update_lock);
- /* Now, we do the remaining detection. */
if (kind < 0) {
- if (lm78_read_value(data, LM78_REG_CONFIG) & 0x80) {
- err = -ENODEV;
- goto ERROR2;
- }
- if (lm78_read_value(data, LM78_REG_I2C_ADDR) !=
- address) {
- err = -ENODEV;
- goto ERROR2;
- }
+ if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80)
+ || i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR)
+ != address)
+ goto err_nodev;
+
+ /* Explicitly prevent the misdetection of Winbond chips */
+ i = i2c_smbus_read_byte_data(client, 0x4f);
+ if (i == 0xa3 || i == 0x5c)
+ goto err_nodev;
}
/* Determine the chip type. */
if (kind <= 0) {
- i = lm78_read_value(data, LM78_REG_CHIPID);
+ i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID);
if (i == 0x00 || i == 0x20 /* LM78 */
|| i == 0x40) /* LM78-J */
kind = lm78;
@@ -586,33 +602,59 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
"parameter for unknown chip at "
"adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address);
- err = -ENODEV;
- goto ERROR2;
+ goto err_nodev;
+ }
+
+ if (lm78_alias_detect(client, i)) {
+ dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
+ "be the same as ISA device\n", address);
+ goto err_nodev;
}
}
- if (kind == lm78) {
- client_name = "lm78";
- } else if (kind == lm79) {
+ if (isa)
+ mutex_unlock(&isa->update_lock);
+
+ switch (kind) {
+ case lm79:
client_name = "lm79";
+ break;
+ default:
+ client_name = "lm78";
}
+ strlcpy(info->type, client_name, I2C_NAME_SIZE);
+
+ return 0;
+
+ err_nodev:
+ if (isa)
+ mutex_unlock(&isa->update_lock);
+ return -ENODEV;
+}
+
+static int lm78_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm78_data *data;
+ int err;
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
- data->type = kind;
+ data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto ERROR2;
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ data->type = id->driver_data;
/* Initialize the LM78 chip */
lm78_init_device(data);
/* Register sysfs hooks */
- if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group)))
+ err = sysfs_create_group(&client->dev.kobj, &lm78_group);
+ if (err)
goto ERROR3;
- data->hwmon_dev = hwmon_device_register(&new_client->dev);
+ data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto ERROR4;
@@ -621,26 +663,18 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
ERROR4:
- sysfs_remove_group(&new_client->dev.kobj, &lm78_group);
+ sysfs_remove_group(&client->dev.kobj, &lm78_group);
ERROR3:
- i2c_detach_client(new_client);
-ERROR2:
kfree(data);
-ERROR1:
return err;
}
-static int lm78_detach_client(struct i2c_client *client)
+static int lm78_i2c_remove(struct i2c_client *client)
{
struct lm78_data *data = i2c_get_clientdata(client);
- int err;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm78_group);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
kfree(data);
return 0;
@@ -651,11 +685,10 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
int err;
struct lm78_data *data;
struct resource *res;
- const char *name;
/* Reserve the ISA region */
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!request_region(res->start, LM78_EXTENT, "lm78")) {
+ if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) {
err = -EBUSY;
goto exit;
}
@@ -665,18 +698,16 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
goto exit_release_region;
}
mutex_init(&data->lock);
- data->client.addr = res->start;
- i2c_set_clientdata(&data->client, data);
+ data->isa_addr = res->start;
platform_set_drvdata(pdev, data);
if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
data->type = lm79;
- name = "lm79";
+ data->name = "lm79";
} else {
data->type = lm78;
- name = "lm78";
+ data->name = "lm78";
}
- strlcpy(data->client.name, name, I2C_NAME_SIZE);
/* Initialize the LM78 chip */
lm78_init_device(data);
@@ -699,7 +730,7 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_name);
kfree(data);
exit_release_region:
- release_region(res->start, LM78_EXTENT);
+ release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
exit:
return err;
}
@@ -707,13 +738,16 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
static int __devexit lm78_isa_remove(struct platform_device *pdev)
{
struct lm78_data *data = platform_get_drvdata(pdev);
+ struct resource *res;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
device_remove_file(&pdev->dev, &dev_attr_name);
- release_region(data->client.addr, LM78_EXTENT);
kfree(data);
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+
return 0;
}
@@ -724,13 +758,13 @@ static int __devexit lm78_isa_remove(struct platform_device *pdev)
would slow down the LM78 access and should not be necessary. */
static int lm78_read_value(struct lm78_data *data, u8 reg)
{
- struct i2c_client *client = &data->client;
+ struct i2c_client *client = data->client;
- if (!client->driver) { /* ISA device */
+ if (!client) { /* ISA device */
int res;
mutex_lock(&data->lock);
- outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
- res = inb_p(client->addr + LM78_DATA_REG_OFFSET);
+ outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET);
+ res = inb_p(data->isa_addr + LM78_DATA_REG_OFFSET);
mutex_unlock(&data->lock);
return res;
} else
@@ -746,12 +780,12 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
nowhere else be necessary! */
static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
{
- struct i2c_client *client = &data->client;
+ struct i2c_client *client = data->client;
- if (!client->driver) { /* ISA device */
+ if (!client) { /* ISA device */
mutex_lock(&data->lock);
- outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
- outb_p(value, client->addr + LM78_DATA_REG_OFFSET);
+ outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET);
+ outb_p(value, data->isa_addr + LM78_DATA_REG_OFFSET);
mutex_unlock(&data->lock);
return 0;
} else
@@ -837,8 +871,17 @@ static int __init lm78_isa_found(unsigned short address)
{
int val, save, found = 0;
- if (!request_region(address, LM78_EXTENT, "lm78"))
+ /* We have to request the region in two parts because some
+ boards declare base+4 to base+7 as a PNP device */
+ if (!request_region(address, 4, "lm78")) {
+ pr_debug("lm78: Failed to request low part of region\n");
return 0;
+ }
+ if (!request_region(address + 4, 4, "lm78")) {
+ pr_debug("lm78: Failed to request high part of region\n");
+ release_region(address, 4);
+ return 0;
+ }
#define REALLY_SLOW_IO
/* We need the timeouts for at least some LM78-like
@@ -901,7 +944,8 @@ static int __init lm78_isa_found(unsigned short address)
val & 0x80 ? "LM79" : "LM78", (int)address);
release:
- release_region(address, LM78_EXTENT);
+ release_region(address + 4, 4);
+ release_region(address, 4);
return found;
}
@@ -949,14 +993,12 @@ static int __init sm_lm78_init(void)
{
int res;
- res = i2c_add_driver(&lm78_driver);
- if (res)
- goto exit;
-
+ /* We register the ISA device first, so that we can skip the
+ * registration of an I2C interface to the same device. */
if (lm78_isa_found(isa_address)) {
res = platform_driver_register(&lm78_isa_driver);
if (res)
- goto exit_unreg_i2c_driver;
+ goto exit;
/* Sets global pdev as a side effect */
res = lm78_isa_device_add(isa_address);
@@ -964,12 +1006,16 @@ static int __init sm_lm78_init(void)
goto exit_unreg_isa_driver;
}
+ res = i2c_add_driver(&lm78_driver);
+ if (res)
+ goto exit_unreg_isa_device;
+
return 0;
+ exit_unreg_isa_device:
+ platform_device_unregister(pdev);
exit_unreg_isa_driver:
platform_driver_unregister(&lm78_isa_driver);
- exit_unreg_i2c_driver:
- i2c_del_driver(&lm78_driver);
exit:
return res;
}
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 12d446f54f9..3ff0285396f 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -5,6 +5,7 @@
Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
+ Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org>
Chip details at <http://www.national.com/ds/LM/LM85.pdf>
@@ -173,40 +174,39 @@ static int RANGE_TO_REG(int range)
{
int i;
- if (range >= lm85_range_map[15])
- return 15;
-
/* Find the closest match */
- for (i = 14; i >= 0; --i) {
- if (range >= lm85_range_map[i]) {
- if ((lm85_range_map[i + 1] - range) <
- (range - lm85_range_map[i]))
- return i + 1;
- return i;
- }
+ for (i = 0; i < 15; ++i) {
+ if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2)
+ break;
}
- return 0;
+ return i;
}
#define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f]
/* These are the PWM frequency encodings */
-static const int lm85_freq_map[] = { /* .1 Hz */
- 100, 150, 230, 300, 380, 470, 620, 940
+static const int lm85_freq_map[8] = { /* 1 Hz */
+ 10, 15, 23, 30, 38, 47, 61, 94
+};
+static const int adm1027_freq_map[8] = { /* 1 Hz */
+ 11, 15, 22, 29, 35, 44, 59, 88
};
-static int FREQ_TO_REG(int freq)
+static int FREQ_TO_REG(const int *map, int freq)
{
int i;
- if (freq >= lm85_freq_map[7])
- return 7;
+ /* Find the closest match */
for (i = 0; i < 7; ++i)
- if (freq <= lm85_freq_map[i])
+ if (freq <= (map[i] + map[i + 1]) / 2)
break;
return i;
}
-#define FREQ_FROM_REG(val) lm85_freq_map[(val) & 0x07]
+
+static int FREQ_FROM_REG(const int *map, u8 reg)
+{
+ return map[reg & 0x07];
+}
/* Since we can't use strings, I'm abusing these numbers
* to stand in for the following meanings:
@@ -275,7 +275,6 @@ struct lm85_zone {
struct lm85_autofan {
u8 config; /* Register value */
- u8 freq; /* PWM frequency, encoded */
u8 min_pwm; /* Minimum PWM value, encoded */
u8 min_off; /* Min PWM or OFF below "limit", flag */
};
@@ -283,8 +282,8 @@ struct lm85_autofan {
/* For each registered chip, we need to keep some data in memory.
The structure is dynamically allocated. */
struct lm85_data {
- struct i2c_client client;
struct device *hwmon_dev;
+ const int *freq_map;
enum chips type;
struct mutex update_lock;
@@ -301,6 +300,7 @@ struct lm85_data {
u16 fan[4]; /* Register value */
u16 fan_min[4]; /* Register value */
u8 pwm[3]; /* Register value */
+ u8 pwm_freq[3]; /* Register encoding */
u8 temp_ext[3]; /* Decoded values */
u8 in_ext[8]; /* Decoded values */
u8 vid; /* Register value */
@@ -310,22 +310,40 @@ struct lm85_data {
struct lm85_zone zone[3];
};
-static int lm85_attach_adapter(struct i2c_adapter *adapter);
-static int lm85_detect(struct i2c_adapter *adapter, int address,
- int kind);
-static int lm85_detach_client(struct i2c_client *client);
+static int lm85_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int lm85_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int lm85_remove(struct i2c_client *client);
static int lm85_read_value(struct i2c_client *client, u8 reg);
static void lm85_write_value(struct i2c_client *client, u8 reg, int value);
static struct lm85_data *lm85_update_device(struct device *dev);
+static const struct i2c_device_id lm85_id[] = {
+ { "adm1027", adm1027 },
+ { "adt7463", adt7463 },
+ { "lm85", any_chip },
+ { "lm85b", lm85b },
+ { "lm85c", lm85c },
+ { "emc6d100", emc6d100 },
+ { "emc6d101", emc6d100 },
+ { "emc6d102", emc6d102 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm85_id);
+
static struct i2c_driver lm85_driver = {
+ .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm85",
},
- .attach_adapter = lm85_attach_adapter,
- .detach_client = lm85_detach_client,
+ .probe = lm85_probe,
+ .remove = lm85_remove,
+ .id_table = lm85_id,
+ .detect = lm85_detect,
+ .address_data = &addr_data,
};
@@ -528,11 +546,39 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
return count;
}
+static ssize_t show_pwm_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct lm85_data *data = lm85_update_device(dev);
+ return sprintf(buf, "%d\n", FREQ_FROM_REG(data->freq_map,
+ data->pwm_freq[nr]));
+}
+
+static ssize_t set_pwm_freq(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val);
+ lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
+ (data->zone[nr].range << 4)
+ | data->pwm_freq[nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
#define show_pwm_reg(offset) \
static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
show_pwm, set_pwm, offset - 1); \
static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
- show_pwm_enable, set_pwm_enable, offset - 1)
+ show_pwm_enable, set_pwm_enable, offset - 1); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \
+ show_pwm_freq, set_pwm_freq, offset - 1)
show_pwm_reg(1);
show_pwm_reg(2);
@@ -761,31 +807,6 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev,
return count;
}
-static ssize_t show_pwm_auto_pwm_freq(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int nr = to_sensor_dev_attr(attr)->index;
- struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf, "%d\n", FREQ_FROM_REG(data->autofan[nr].freq));
-}
-
-static ssize_t set_pwm_auto_pwm_freq(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
-
- mutex_lock(&data->update_lock);
- data->autofan[nr].freq = FREQ_TO_REG(val);
- lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
- (data->zone[nr].range << 4)
- | data->autofan[nr].freq);
- mutex_unlock(&data->update_lock);
- return count;
-}
-
#define pwm_auto(offset) \
static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels, \
S_IRUGO | S_IWUSR, show_pwm_auto_channels, \
@@ -795,10 +816,7 @@ static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_min, \
set_pwm_auto_pwm_min, offset - 1); \
static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_minctl, \
S_IRUGO | S_IWUSR, show_pwm_auto_pwm_minctl, \
- set_pwm_auto_pwm_minctl, offset - 1); \
-static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_freq, \
- S_IRUGO | S_IWUSR, show_pwm_auto_pwm_freq, \
- set_pwm_auto_pwm_freq, offset - 1);
+ set_pwm_auto_pwm_minctl, offset - 1)
pwm_auto(1);
pwm_auto(2);
@@ -867,7 +885,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
TEMP_FROM_REG(data->zone[nr].limit));
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->autofan[nr].freq & 0x07));
+ | (data->pwm_freq[nr] & 0x07));
/* Update temp_auto_hyst and temp_auto_off */
data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG(
@@ -910,7 +928,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
val - min);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->autofan[nr].freq & 0x07));
+ | (data->pwm_freq[nr] & 0x07));
mutex_unlock(&data->update_lock);
return count;
}
@@ -957,13 +975,6 @@ temp_auto(1);
temp_auto(2);
temp_auto(3);
-static int lm85_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, lm85_detect);
-}
-
static struct attribute *lm85_attributes[] = {
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
@@ -984,6 +995,9 @@ static struct attribute *lm85_attributes[] = {
&sensor_dev_attr_pwm1_enable.dev_attr.attr,
&sensor_dev_attr_pwm2_enable.dev_attr.attr,
&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm1_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm3_freq.dev_attr.attr,
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -1026,9 +1040,6 @@ static struct attribute *lm85_attributes[] = {
&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
- &sensor_dev_attr_pwm1_auto_pwm_freq.dev_attr.attr,
- &sensor_dev_attr_pwm2_auto_pwm_freq.dev_attr.attr,
- &sensor_dev_attr_pwm3_auto_pwm_freq.dev_attr.attr,
&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
@@ -1103,109 +1114,74 @@ static void lm85_init_client(struct i2c_client *client)
dev_warn(&client->dev, "Device is not ready\n");
}
-static int lm85_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lm85_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
- int company, verstep;
- struct i2c_client *client;
- struct lm85_data *data;
- int err = 0;
+ struct i2c_adapter *adapter = client->adapter;
+ int address = client->addr;
const char *type_name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */
- goto ERROR0;
+ return -ENODEV;
}
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access lm85_{read,write}_value. */
+ /* If auto-detecting, determine the chip type */
+ if (kind < 0) {
+ int company = lm85_read_value(client, LM85_REG_COMPANY);
+ int verstep = lm85_read_value(client, LM85_REG_VERSTEP);
- if (!(data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto ERROR0;
- }
+ dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
+ "COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+ address, company, verstep);
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- client->adapter = adapter;
- client->driver = &lm85_driver;
-
- /* Now, we do the remaining detection. */
-
- company = lm85_read_value(client, LM85_REG_COMPANY);
- verstep = lm85_read_value(client, LM85_REG_VERSTEP);
-
- dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
- " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
- i2c_adapter_id(client->adapter), client->addr,
- company, verstep);
-
- /* If auto-detecting, Determine the chip type. */
- if (kind <= 0) {
- dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x ...\n",
- i2c_adapter_id(adapter), address);
- if (company == LM85_COMPANY_NATIONAL
- && verstep == LM85_VERSTEP_LM85C) {
- kind = lm85c;
- } else if (company == LM85_COMPANY_NATIONAL
- && verstep == LM85_VERSTEP_LM85B) {
- kind = lm85b;
- } else if (company == LM85_COMPANY_NATIONAL
- && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, "Unrecognized version/stepping 0x%02x"
- " Defaulting to LM85.\n", verstep);
- kind = any_chip;
- } else if (company == LM85_COMPANY_ANALOG_DEV
- && verstep == LM85_VERSTEP_ADM1027) {
- kind = adm1027;
- } else if (company == LM85_COMPANY_ANALOG_DEV
- && (verstep == LM85_VERSTEP_ADT7463
- || verstep == LM85_VERSTEP_ADT7463C)) {
- kind = adt7463;
- } else if (company == LM85_COMPANY_ANALOG_DEV
- && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, "Unrecognized version/stepping 0x%02x"
- " Defaulting to Generic LM85.\n", verstep);
- kind = any_chip;
- } else if (company == LM85_COMPANY_SMSC
- && (verstep == LM85_VERSTEP_EMC6D100_A0
- || verstep == LM85_VERSTEP_EMC6D100_A1)) {
- /* Unfortunately, we can't tell a '100 from a '101
- * from the registers. Since a '101 is a '100
- * in a package with fewer pins and therefore no
- * 3.3V, 1.5V or 1.8V inputs, perhaps if those
- * inputs read 0, then it's a '101.
- */
- kind = emc6d100;
- } else if (company == LM85_COMPANY_SMSC
- && verstep == LM85_VERSTEP_EMC6D102) {
- kind = emc6d102;
- } else if (company == LM85_COMPANY_SMSC
- && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, "lm85: Detected SMSC chip\n");
- dev_err(&adapter->dev, "lm85: Unrecognized version/stepping 0x%02x"
- " Defaulting to Generic LM85.\n", verstep);
- kind = any_chip;
- } else if (kind == any_chip
- && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
- dev_err(&adapter->dev, "Generic LM85 Version 6 detected\n");
- /* Leave kind as "any_chip" */
- } else {
- dev_dbg(&adapter->dev, "Autodetection failed\n");
- /* Not an LM85... */
- if (kind == any_chip) { /* User used force=x,y */
- dev_err(&adapter->dev, "Generic LM85 Version 6 not"
- " found at %d,0x%02x. Try force_lm85c.\n",
- i2c_adapter_id(adapter), address);
+ /* All supported chips have the version in common */
+ if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC) {
+ dev_dbg(&adapter->dev, "Autodetection failed: "
+ "unsupported version\n");
+ return -ENODEV;
+ }
+ kind = any_chip;
+
+ /* Now, refine the detection */
+ if (company == LM85_COMPANY_NATIONAL) {
+ switch (verstep) {
+ case LM85_VERSTEP_LM85C:
+ kind = lm85c;
+ break;
+ case LM85_VERSTEP_LM85B:
+ kind = lm85b;
+ break;
+ }
+ } else if (company == LM85_COMPANY_ANALOG_DEV) {
+ switch (verstep) {
+ case LM85_VERSTEP_ADM1027:
+ kind = adm1027;
+ break;
+ case LM85_VERSTEP_ADT7463:
+ case LM85_VERSTEP_ADT7463C:
+ kind = adt7463;
+ break;
+ }
+ } else if (company == LM85_COMPANY_SMSC) {
+ switch (verstep) {
+ case LM85_VERSTEP_EMC6D100_A0:
+ case LM85_VERSTEP_EMC6D100_A1:
+ /* Note: we can't tell a '100 from a '101 */
+ kind = emc6d100;
+ break;
+ case LM85_VERSTEP_EMC6D102:
+ kind = emc6d102;
+ break;
}
- err = 0;
- goto ERROR1;
+ } else {
+ dev_dbg(&adapter->dev, "Autodetection failed: "
+ "unknown vendor\n");
+ return -ENODEV;
}
}
- /* Fill in the chip specific driver values */
switch (kind) {
case lm85b:
type_name = "lm85b";
@@ -1228,16 +1204,36 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
default:
type_name = "lm85";
}
- strlcpy(client->name, type_name, I2C_NAME_SIZE);
+ strlcpy(info->type, type_name, I2C_NAME_SIZE);
+
+ return 0;
+}
- /* Fill in the remaining client fields */
- data->type = kind;
+static int lm85_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm85_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->type = id->driver_data;
mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- err = i2c_attach_client(client);
- if (err)
- goto ERROR1;
+ /* Fill in the chip specific driver values */
+ switch (data->type) {
+ case adm1027:
+ case adt7463:
+ case emc6d100:
+ case emc6d102:
+ data->freq_map = adm1027_freq_map;
+ break;
+ default:
+ data->freq_map = lm85_freq_map;
+ }
/* Set the VRM version */
data->vrm = vid_which_vrm();
@@ -1248,45 +1244,42 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &lm85_group);
if (err)
- goto ERROR2;
+ goto err_kfree;
/* The ADT7463 has an optional VRM 10 mode where pin 21 is used
as a sixth digital VID input rather than an analog input. */
data->vid = lm85_read_value(client, LM85_REG_VID);
- if (!(kind == adt7463 && (data->vid & 0x80)))
+ if (!(data->type == adt7463 && (data->vid & 0x80)))
if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in4)))
- goto ERROR3;
+ goto err_remove_files;
/* The EMC6D100 has 3 additional voltage inputs */
- if (kind == emc6d100)
+ if (data->type == emc6d100)
if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in567)))
- goto ERROR3;
+ goto err_remove_files;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
- goto ERROR3;
+ goto err_remove_files;
}
return 0;
/* Error out and cleanup code */
- ERROR3:
+ err_remove_files:
sysfs_remove_group(&client->dev.kobj, &lm85_group);
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
- if (kind == emc6d100)
+ if (data->type == emc6d100)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
- ERROR2:
- i2c_detach_client(client);
- ERROR1:
+ err_kfree:
kfree(data);
- ERROR0:
return err;
}
-static int lm85_detach_client(struct i2c_client *client)
+static int lm85_remove(struct i2c_client *client)
{
struct lm85_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
@@ -1294,7 +1287,6 @@ static int lm85_detach_client(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
if (data->type == emc6d100)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
- i2c_detach_client(client);
kfree(data);
return 0;
}
@@ -1481,7 +1473,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
data->autofan[i].config =
lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
- data->autofan[i].freq = val & 0x07;
+ data->pwm_freq[i] = val & 0x07;
data->zone[i].range = val >> 4;
data->autofan[i].min_pwm =
lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 21970f0d53a..2e4a3cea95f 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -21,11 +21,10 @@
* http://www.national.com/pf/LM/LM87.html
*
* Some functions share pins, so not all functions are available at the same
- * time. Which are depends on the hardware setup. This driver assumes that
- * the BIOS configured the chip correctly. In that respect, it differs from
- * the original driver (from lm_sensors for Linux 2.4), which would force the
- * LM87 to an arbitrary, compile-time chosen mode, regardless of the actual
- * chipset wiring.
+ * time. Which are depends on the hardware setup. This driver normally
+ * assumes that firmware configured the chip correctly. Where this is not
+ * the case, platform code must set the I2C client's platform_data to point
+ * to a u8 value to be written to the channel register.
* For reference, here is the list of exclusive functions:
* - in0+in5 (default) or temp3
* - fan1 (default) or in6
@@ -199,6 +198,7 @@ struct lm87_data {
unsigned long last_updated; /* In jiffies */
u8 channel; /* register value */
+ u8 config; /* original register value */
u8 in[8]; /* register value */
u8 in_max[8]; /* register value */
@@ -832,6 +832,7 @@ exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &lm87_group);
sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt);
exit_free:
+ lm87_write_value(new_client, LM87_REG_CONFIG, data->config);
kfree(data);
exit:
return err;
@@ -840,12 +841,17 @@ exit:
static void lm87_init_client(struct i2c_client *client)
{
struct lm87_data *data = i2c_get_clientdata(client);
- u8 config;
- data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
+ if (client->dev.platform_data) {
+ data->channel = *(u8 *)client->dev.platform_data;
+ lm87_write_value(client,
+ LM87_REG_CHANNEL_MODE, data->channel);
+ } else {
+ data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
+ }
+ data->config = lm87_read_value(client, LM87_REG_CONFIG) & 0x6F;
- config = lm87_read_value(client, LM87_REG_CONFIG);
- if (!(config & 0x01)) {
+ if (!(data->config & 0x01)) {
int i;
/* Limits are left uninitialized after power-up */
@@ -867,11 +873,11 @@ static void lm87_init_client(struct i2c_client *client)
lm87_write_value(client, LM87_REG_IN_MAX(0), 0xFF);
}
}
- if ((config & 0x81) != 0x01) {
- /* Start monitoring */
+
+ /* Make sure Start is set and INT#_Clear is clear */
+ if ((data->config & 0x09) != 0x01)
lm87_write_value(client, LM87_REG_CONFIG,
- (config & 0xF7) | 0x01);
- }
+ (data->config & 0x77) | 0x01);
}
static int lm87_remove(struct i2c_client *client)
@@ -882,6 +888,7 @@ static int lm87_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &lm87_group);
sysfs_remove_group(&client->dev.kobj, &lm87_group_opt);
+ lm87_write_value(client, LM87_REG_CONFIG, data->config);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index c24fe36ac78..3edeebc0b83 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1,14 +1,12 @@
/*
* lm90.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org>
*
* Based on the lm83 driver. The LM90 is a sensor chip made by National
* Semiconductor. It reports up to two temperatures (its own plus up to
* one external one) with a 0.125 deg resolution (1 deg for local
- * temperature) and a 3-4 deg accuracy. Complete datasheet can be
- * obtained from National's website at:
- * http://www.national.com/pf/LM/LM90.html
+ * temperature) and a 3-4 deg accuracy.
*
* This driver also supports the LM89 and LM99, two other sensor chips
* made by National Semiconductor. Both have an increased remote
@@ -16,48 +14,38 @@
* additionally shifts remote temperatures (measured and limits) by 16
* degrees, which allows for higher temperatures measurement. The
* driver doesn't handle it since it can be done easily in user-space.
- * Complete datasheets can be obtained from National's website at:
- * http://www.national.com/pf/LM/LM89.html
- * http://www.national.com/pf/LM/LM99.html
* Note that there is no way to differentiate between both chips.
*
* This driver also supports the LM86, another sensor chip made by
* National Semiconductor. It is exactly similar to the LM90 except it
* has a higher accuracy.
- * Complete datasheet can be obtained from National's website at:
- * http://www.national.com/pf/LM/LM86.html
*
* This driver also supports the ADM1032, a sensor chip made by Analog
* Devices. That chip is similar to the LM90, with a few differences
- * that are not handled by this driver. Complete datasheet can be
- * obtained from Analog's website at:
- * http://www.analog.com/en/prod/0,2877,ADM1032,00.html
- * Among others, it has a higher accuracy than the LM90, much like the
- * LM86 does.
+ * that are not handled by this driver. Among others, it has a higher
+ * accuracy than the LM90, much like the LM86 does.
*
* This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
- * chips made by Maxim. These chips are similar to the LM86. Complete
- * datasheet can be obtained at Maxim's website at:
- * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+ * chips made by Maxim. These chips are similar to the LM86.
* Note that there is no easy way to differentiate between the three
* variants. The extra address and features of the MAX6659 are not
* supported by this driver. These chips lack the remote temperature
* offset feature.
*
+ * This driver also supports the MAX6646, MAX6647 and MAX6649 chips
+ * made by Maxim. These are again similar to the LM86, but they use
+ * unsigned temperature values and can report temperatures from 0 to
+ * 145 degrees.
+ *
* This driver also supports the MAX6680 and MAX6681, two other sensor
* chips made by Maxim. These are quite similar to the other Maxim
- * chips. Complete datasheet can be obtained at:
- * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3370
- * The MAX6680 and MAX6681 only differ in the pinout so they can be
- * treated identically.
+ * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
+ * be treated identically.
*
- * This driver also supports the ADT7461 chip from Analog Devices but
- * only in its "compatability mode". If an ADT7461 chip is found but
- * is configured in non-compatible mode (where its temperature
- * register values are decoded differently) it is ignored by this
- * driver. Complete datasheet can be obtained from Analog's website
- * at:
- * http://www.analog.com/en/prod/0,2877,ADT7461,00.html
+ * This driver also supports the ADT7461 chip from Analog Devices.
+ * It's supported in both compatibility and extended mode. It is mostly
+ * compatible with LM90 except for a data format difference for the
+ * temperature value registers.
*
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
@@ -93,9 +81,10 @@
* Addresses to scan
* Address is fully defined internally and cannot be changed except for
* MAX6659, MAX6680 and MAX6681.
- * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
- * have address 0x4c.
- * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657
+ * and MAX6658 have address 0x4c.
+ * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
+ * MAX6647 has address 0x4e.
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
* MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
* 0x4c, 0x4d or 0x4e.
@@ -108,7 +97,8 @@ static const unsigned short normal_i2c[] = {
* Insmod parameters
*/
-I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
+I2C_CLIENT_INSMOD_8(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680,
+ max6646);
/*
* The LM90 registers
@@ -149,39 +139,14 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
#define LM90_REG_R_TCRIT_HYST 0x21
#define LM90_REG_W_TCRIT_HYST 0x21
-/*
- * Conversions and various macros
- * For local temperatures and limits, critical limits and the hysteresis
- * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
- * For remote temperatures and limits, it uses signed 11-bit values with
- * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
- */
+/* MAX6646/6647/6649/6657/6658/6659 registers */
-#define TEMP1_FROM_REG(val) ((val) * 1000)
-#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \
- (val) >= 127000 ? 127 : \
- (val) < 0 ? ((val) - 500) / 1000 : \
- ((val) + 500) / 1000)
-#define TEMP2_FROM_REG(val) ((val) / 32 * 125)
-#define TEMP2_TO_REG(val) ((val) <= -128000 ? 0x8000 : \
- (val) >= 127875 ? 0x7FE0 : \
- (val) < 0 ? ((val) - 62) / 125 * 32 : \
- ((val) + 62) / 125 * 32)
-#define HYST_TO_REG(val) ((val) <= 0 ? 0 : (val) >= 30500 ? 31 : \
- ((val) + 500) / 1000)
-
-/*
- * ADT7461 is almost identical to LM90 except that attempts to write
- * values that are outside the range 0 < temp < 127 are treated as
- * the boundary value.
- */
+#define MAX6657_REG_R_LOCAL_TEMPL 0x11
-#define TEMP1_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
- (val) >= 127000 ? 127 : \
- ((val) + 500) / 1000)
-#define TEMP2_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
- (val) >= 127750 ? 0x7FC0 : \
- ((val) + 125) / 250 * 64)
+/*
+ * Device flags
+ */
+#define LM90_FLAG_ADT7461_EXT 0x01 /* ADT7461 extended mode */
/*
* Functions declaration
@@ -206,6 +171,9 @@ static const struct i2c_device_id lm90_id[] = {
{ "lm86", lm86 },
{ "lm89", lm99 },
{ "lm99", lm99 }, /* Missing temperature offset */
+ { "max6646", max6646 },
+ { "max6647", max6646 },
+ { "max6649", max6646 },
{ "max6657", max6657 },
{ "max6658", max6657 },
{ "max6659", max6657 },
@@ -237,22 +205,150 @@ struct lm90_data {
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
int kind;
+ int flags;
/* registers values */
- s8 temp8[5]; /* 0: local input
- 1: local low limit
- 2: local high limit
- 3: local critical limit
- 4: remote critical limit */
- s16 temp11[4]; /* 0: remote input
+ s8 temp8[4]; /* 0: local low limit
+ 1: local high limit
+ 2: local critical limit
+ 3: remote critical limit */
+ s16 temp11[5]; /* 0: remote input
1: remote low limit
2: remote high limit
- 3: remote offset (except max6657) */
+ 3: remote offset (except max6646 and max6657)
+ 4: local input */
u8 temp_hyst;
u8 alarms; /* bitvector */
};
/*
+ * Conversions
+ * For local temperatures and limits, critical limits and the hysteresis
+ * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
+ * For remote temperatures and limits, it uses signed 11-bit values with
+ * LSB = 0.125 degree Celsius, left-justified in 16-bit registers. Some
+ * Maxim chips use unsigned values.
+ */
+
+static inline int temp_from_s8(s8 val)
+{
+ return val * 1000;
+}
+
+static inline int temp_from_u8(u8 val)
+{
+ return val * 1000;
+}
+
+static inline int temp_from_s16(s16 val)
+{
+ return val / 32 * 125;
+}
+
+static inline int temp_from_u16(u16 val)
+{
+ return val / 32 * 125;
+}
+
+static s8 temp_to_s8(long val)
+{
+ if (val <= -128000)
+ return -128;
+ if (val >= 127000)
+ return 127;
+ if (val < 0)
+ return (val - 500) / 1000;
+ return (val + 500) / 1000;
+}
+
+static u8 temp_to_u8(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 255000)
+ return 255;
+ return (val + 500) / 1000;
+}
+
+static s16 temp_to_s16(long val)
+{
+ if (val <= -128000)
+ return 0x8000;
+ if (val >= 127875)
+ return 0x7FE0;
+ if (val < 0)
+ return (val - 62) / 125 * 32;
+ return (val + 62) / 125 * 32;
+}
+
+static u8 hyst_to_reg(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 30500)
+ return 31;
+ return (val + 500) / 1000;
+}
+
+/*
+ * ADT7461 in compatibility mode is almost identical to LM90 except that
+ * attempts to write values that are outside the range 0 < temp < 127 are
+ * treated as the boundary value.
+ *
+ * ADT7461 in "extended mode" operation uses unsigned integers offset by
+ * 64 (e.g., 0 -> -64 degC). The range is restricted to -64..191 degC.
+ */
+static inline int temp_from_u8_adt7461(struct lm90_data *data, u8 val)
+{
+ if (data->flags & LM90_FLAG_ADT7461_EXT)
+ return (val - 64) * 1000;
+ else
+ return temp_from_s8(val);
+}
+
+static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val)
+{
+ if (data->flags & LM90_FLAG_ADT7461_EXT)
+ return (val - 0x4000) / 64 * 250;
+ else
+ return temp_from_s16(val);
+}
+
+static u8 temp_to_u8_adt7461(struct lm90_data *data, long val)
+{
+ if (data->flags & LM90_FLAG_ADT7461_EXT) {
+ if (val <= -64000)
+ return 0;
+ if (val >= 191000)
+ return 0xFF;
+ return (val + 500 + 64000) / 1000;
+ } else {
+ if (val <= 0)
+ return 0;
+ if (val >= 127000)
+ return 127;
+ return (val + 500) / 1000;
+ }
+}
+
+static u16 temp_to_u16_adt7461(struct lm90_data *data, long val)
+{
+ if (data->flags & LM90_FLAG_ADT7461_EXT) {
+ if (val <= -64000)
+ return 0;
+ if (val >= 191750)
+ return 0xFFC0;
+ return (val + 64000 + 125) / 250 * 64;
+ } else {
+ if (val <= 0)
+ return 0;
+ if (val >= 127750)
+ return 0x7FC0;
+ return (val + 125) / 250 * 64;
+ }
+}
+
+/*
* Sysfs stuff
*/
@@ -261,7 +357,16 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index]));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
+ else if (data->kind == max6646)
+ temp = temp_from_u8(data->temp8[attr->index]);
+ else
+ temp = temp_from_s8(data->temp8[attr->index]);
+
+ return sprintf(buf, "%d\n", temp);
}
static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
@@ -282,10 +387,12 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
- data->temp8[nr] = TEMP1_TO_REG_ADT7461(val);
+ data->temp8[nr] = temp_to_u8_adt7461(data, val);
+ else if (data->kind == max6646)
+ data->temp8[nr] = temp_to_u8(val);
else
- data->temp8[nr] = TEMP1_TO_REG(val);
- i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]);
+ data->temp8[nr] = temp_to_s8(val);
+ i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
mutex_unlock(&data->update_lock);
return count;
}
@@ -295,7 +402,16 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", TEMP2_FROM_REG(data->temp11[attr->index]));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
+ else if (data->kind == max6646)
+ temp = temp_from_u16(data->temp11[attr->index]);
+ else
+ temp = temp_from_s16(data->temp11[attr->index]);
+
+ return sprintf(buf, "%d\n", temp);
}
static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
@@ -318,13 +434,20 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
mutex_lock(&data->update_lock);
if (data->kind == adt7461)
- data->temp11[nr] = TEMP2_TO_REG_ADT7461(val);
+ data->temp11[nr] = temp_to_u16_adt7461(data, val);
+ else if (data->kind == max6657 || data->kind == max6680)
+ data->temp11[nr] = temp_to_s8(val) << 8;
+ else if (data->kind == max6646)
+ data->temp11[nr] = temp_to_u8(val) << 8;
else
- data->temp11[nr] = TEMP2_TO_REG(val);
+ data->temp11[nr] = temp_to_s16(val);
+
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8);
- i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
- data->temp11[nr] & 0xff);
+ if (data->kind != max6657 && data->kind != max6680
+ && data->kind != max6646)
+ i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+ data->temp11[nr] & 0xff);
mutex_unlock(&data->update_lock);
return count;
}
@@ -334,8 +457,14 @@ static ssize_t show_temphyst(struct device *dev, struct device_attribute *devatt
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm90_data *data = lm90_update_device(dev);
- return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index])
- - TEMP1_FROM_REG(data->temp_hyst));
+ int temp;
+
+ if (data->kind == adt7461)
+ temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
+ else
+ temp = temp_from_s8(data->temp8[attr->index]);
+
+ return sprintf(buf, "%d\n", temp - temp_from_s8(data->temp_hyst));
}
static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
@@ -347,9 +476,9 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
long hyst;
mutex_lock(&data->update_lock);
- hyst = TEMP1_FROM_REG(data->temp8[3]) - val;
+ hyst = temp_from_s8(data->temp8[2]) - val;
i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
- HYST_TO_REG(hyst));
+ hyst_to_reg(hyst));
mutex_unlock(&data->update_lock);
return count;
}
@@ -371,23 +500,23 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp11, NULL, 4);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
- set_temp8, 1);
+ set_temp8, 0);
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 1);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
- set_temp8, 2);
+ set_temp8, 1);
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 2);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8,
- set_temp8, 3);
+ set_temp8, 2);
static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
- set_temp8, 4);
+ set_temp8, 3);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
- set_temphyst, 3);
-static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
+ set_temphyst, 2);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 3);
static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 3);
@@ -568,7 +697,7 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
kind = adm1032;
} else
if (chip_id == 0x51 /* ADT7461 */
- && (reg_config1 & 0x1F) == 0x00 /* check compat mode */
+ && (reg_config1 & 0x1B) == 0x00
&& reg_convrate <= 0x0A) {
kind = adt7461;
}
@@ -599,13 +728,23 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
&& (reg_config1 & 0x03) == 0x00
&& reg_convrate <= 0x07) {
kind = max6680;
+ } else
+ /* The chip_id register of the MAX6646/6647/6649
+ * holds the revision of the chip.
+ * The lowest 6 bits of the config1 register are
+ * unused and should return zero when read.
+ */
+ if (chip_id == 0x59
+ && (reg_config1 & 0x3f) == 0x00
+ && reg_convrate <= 0x07) {
+ kind = max6646;
}
}
if (kind <= 0) { /* identification failed */
- dev_info(&adapter->dev,
- "Unsupported chip (man_id=0x%02X, "
- "chip_id=0x%02X).\n", man_id, chip_id);
+ dev_dbg(&adapter->dev,
+ "Unsupported chip at 0x%02x (man_id=0x%02X, "
+ "chip_id=0x%02X)\n", address, man_id, chip_id);
return -ENODEV;
}
}
@@ -629,6 +768,8 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
name = "max6680";
} else if (kind == adt7461) {
name = "adt7461";
+ } else if (kind == max6646) {
+ name = "max6646";
}
strlcpy(info->type, name, I2C_NAME_SIZE);
@@ -668,7 +809,7 @@ static int lm90_probe(struct i2c_client *new_client,
&dev_attr_pec)))
goto exit_remove_files;
}
- if (data->kind != max6657) {
+ if (data->kind != max6657 && data->kind != max6646) {
if ((err = device_create_file(&new_client->dev,
&sensor_dev_attr_temp2_offset.dev_attr)))
goto exit_remove_files;
@@ -707,6 +848,12 @@ static void lm90_init_client(struct i2c_client *client)
}
config_orig = config;
+ /* Check Temperature Range Select */
+ if (data->kind == adt7461) {
+ if (config & 0x04)
+ data->flags |= LM90_FLAG_ADT7461_EXT;
+ }
+
/*
* Put MAX6680/MAX8881 into extended resolution (bit 0x10,
* 0.125 degree resolution) and range (0x08, extend range
@@ -728,7 +875,7 @@ static int lm90_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm90_group);
device_remove_file(&client->dev, &dev_attr_pec);
- if (data->kind != max6657)
+ if (data->kind != max6657 && data->kind != max6646)
device_remove_file(&client->dev,
&sensor_dev_attr_temp2_offset.dev_attr);
@@ -736,6 +883,38 @@ static int lm90_remove(struct i2c_client *client)
return 0;
}
+static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
+{
+ int err;
+ u8 oldh, newh, l;
+
+ /*
+ * There is a trick here. We have to read two registers to have the
+ * sensor temperature, but we have to beware a conversion could occur
+ * inbetween the readings. The datasheet says we should either use
+ * the one-shot conversion register, which we don't want to do
+ * (disables hardware monitoring) or monitor the busy bit, which is
+ * impossible (we can't read the values and monitor that bit at the
+ * exact same time). So the solution used here is to read the high
+ * byte once, then the low byte, then the high byte again. If the new
+ * high byte matches the old one, then we have a valid reading. Else
+ * we have to read the low byte again, and now we believe we have a
+ * correct reading.
+ */
+ if ((err = lm90_read_reg(client, regh, &oldh))
+ || (err = lm90_read_reg(client, regl, &l))
+ || (err = lm90_read_reg(client, regh, &newh)))
+ return err;
+ if (oldh != newh) {
+ err = lm90_read_reg(client, regl, &l);
+ if (err)
+ return err;
+ }
+ *value = (newh << 8) | l;
+
+ return 0;
+}
+
static struct lm90_data *lm90_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -744,49 +923,50 @@ static struct lm90_data *lm90_update_device(struct device *dev)
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
- u8 oldh, newh, l;
+ u8 h, l;
dev_dbg(&client->dev, "Updating lm90 data.\n");
- lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, &data->temp8[0]);
- lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[1]);
- lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[2]);
- lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[3]);
- lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[4]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]);
+ lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]);
+ lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
- /*
- * There is a trick here. We have to read two registers to
- * have the remote sensor temperature, but we have to beware
- * a conversion could occur inbetween the readings. The
- * datasheet says we should either use the one-shot
- * conversion register, which we don't want to do (disables
- * hardware monitoring) or monitor the busy bit, which is
- * impossible (we can't read the values and monitor that bit
- * at the exact same time). So the solution used here is to
- * read the high byte once, then the low byte, then the high
- * byte again. If the new high byte matches the old one,
- * then we have a valid reading. Else we have to read the low
- * byte again, and now we believe we have a correct reading.
- */
- if (lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &oldh) == 0
- && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0
- && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &newh) == 0
- && (newh == oldh
- || lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0))
- data->temp11[0] = (newh << 8) | l;
-
- if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &newh) == 0
- && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, &l) == 0)
- data->temp11[1] = (newh << 8) | l;
- if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0
- && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0)
- data->temp11[2] = (newh << 8) | l;
- if (data->kind != max6657) {
+ if (data->kind == max6657 || data->kind == max6646) {
+ lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
+ MAX6657_REG_R_LOCAL_TEMPL,
+ &data->temp11[4]);
+ } else {
+ if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
+ &h) == 0)
+ data->temp11[4] = h << 8;
+ }
+ lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
+ LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]);
+
+ if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
+ data->temp11[1] = h << 8;
+ if (data->kind != max6657 && data->kind != max6680
+ && data->kind != max6646
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
+ &l) == 0)
+ data->temp11[1] |= l;
+ }
+ if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
+ data->temp11[2] = h << 8;
+ if (data->kind != max6657 && data->kind != max6680
+ && data->kind != max6646
+ && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
+ &l) == 0)
+ data->temp11[2] |= l;
+ }
+
+ if (data->kind != max6657 && data->kind != max6646) {
if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
- &newh) == 0
+ &h) == 0
&& lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
&l) == 0)
- data->temp11[3] = (newh << 8) | l;
+ data->temp11[3] = (h << 8) | l;
}
lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
new file mode 100644
index 00000000000..bfaa665ccf3
--- /dev/null
+++ b/drivers/hwmon/max1111.c
@@ -0,0 +1,244 @@
+/*
+ * max1111.c - +2.7V, Low-Power, Multichannel, Serial 8-bit ADCs
+ *
+ * Based on arch/arm/mach-pxa/corgi_ssp.c
+ *
+ * Copyright (C) 2004-2005 Richard Purdie
+ *
+ * Copyright (C) 2008 Marvell International Ltd.
+ * Eric Miao <eric.miao@marvell.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/spi/spi.h>
+
+#define MAX1111_TX_BUF_SIZE 1
+#define MAX1111_RX_BUF_SIZE 2
+
+/* MAX1111 Commands */
+#define MAX1111_CTRL_PD0 (1u << 0)
+#define MAX1111_CTRL_PD1 (1u << 1)
+#define MAX1111_CTRL_SGL (1u << 2)
+#define MAX1111_CTRL_UNI (1u << 3)
+#define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */
+#define MAX1111_CTRL_STR (1u << 7)
+
+struct max1111_data {
+ struct spi_device *spi;
+ struct device *hwmon_dev;
+ struct spi_message msg;
+ struct spi_transfer xfer[2];
+ uint8_t *tx_buf;
+ uint8_t *rx_buf;
+};
+
+static int max1111_read(struct device *dev, int channel)
+{
+ struct max1111_data *data = dev_get_drvdata(dev);
+ uint8_t v1, v2;
+ int err;
+
+ data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) |
+ MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 |
+ MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR;
+
+ err = spi_sync(data->spi, &data->msg);
+ if (err < 0) {
+ dev_err(dev, "spi_sync failed with %d\n", err);
+ return err;
+ }
+
+ v1 = data->rx_buf[0];
+ v2 = data->rx_buf[1];
+
+ if ((v1 & 0xc0) || (v2 & 0x3f))
+ return -EINVAL;
+
+ return (v1 << 2) | (v2 >> 6);
+}
+
+#ifdef CONFIG_SHARPSL_PM
+static struct max1111_data *the_max1111;
+
+int max1111_read_channel(int channel)
+{
+ return max1111_read(&the_max1111->spi->dev, channel);
+}
+EXPORT_SYMBOL(max1111_read_channel);
+#endif
+
+/*
+ * NOTE: SPI devices do not have a default 'name' attribute, which is
+ * likely to be used by hwmon applications to distinguish between
+ * different devices, explicitly add a name attribute here.
+ */
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "max1111\n");
+}
+
+static ssize_t show_adc(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int channel = to_sensor_dev_attr(attr)->index;
+ int ret;
+
+ ret = max1111_read(dev, channel);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+#define MAX1111_ADC_ATTR(_id) \
+ SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id)
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static MAX1111_ADC_ATTR(0);
+static MAX1111_ADC_ATTR(1);
+static MAX1111_ADC_ATTR(2);
+static MAX1111_ADC_ATTR(3);
+
+static struct attribute *max1111_attributes[] = {
+ &dev_attr_name.attr,
+ &sensor_dev_attr_adc0_in.dev_attr.attr,
+ &sensor_dev_attr_adc1_in.dev_attr.attr,
+ &sensor_dev_attr_adc2_in.dev_attr.attr,
+ &sensor_dev_attr_adc3_in.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group max1111_attr_group = {
+ .attrs = max1111_attributes,
+};
+
+static int setup_transfer(struct max1111_data *data)
+{
+ struct spi_message *m;
+ struct spi_transfer *x;
+
+ data->tx_buf = kmalloc(MAX1111_TX_BUF_SIZE, GFP_KERNEL);
+ if (!data->tx_buf)
+ return -ENOMEM;
+
+ data->rx_buf = kmalloc(MAX1111_RX_BUF_SIZE, GFP_KERNEL);
+ if (!data->rx_buf) {
+ kfree(data->tx_buf);
+ return -ENOMEM;
+ }
+
+ m = &data->msg;
+ x = &data->xfer[0];
+
+ spi_message_init(m);
+
+ x->tx_buf = &data->tx_buf[0];
+ x->len = 1;
+ spi_message_add_tail(x, m);
+
+ x++;
+ x->rx_buf = &data->rx_buf[0];
+ x->len = 2;
+ spi_message_add_tail(x, m);
+
+ return 0;
+}
+
+static int __devinit max1111_probe(struct spi_device *spi)
+{
+ struct max1111_data *data;
+ int err;
+
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_0;
+ err = spi_setup(spi);
+ if (err < 0)
+ return err;
+
+ data = kzalloc(sizeof(struct max1111_data), GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(&spi->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ err = setup_transfer(data);
+ if (err)
+ goto err_free_data;
+
+ data->spi = spi;
+ spi_set_drvdata(spi, data);
+
+ err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group);
+ if (err) {
+ dev_err(&spi->dev, "failed to create attribute group\n");
+ goto err_free_all;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&spi->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ dev_err(&spi->dev, "failed to create hwmon device\n");
+ err = PTR_ERR(data->hwmon_dev);
+ goto err_remove;
+ }
+
+#ifdef CONFIG_SHARPSL_PM
+ the_max1111 = data;
+#endif
+ return 0;
+
+err_remove:
+ sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
+err_free_all:
+ kfree(data->rx_buf);
+ kfree(data->tx_buf);
+err_free_data:
+ kfree(data);
+ return err;
+}
+
+static int __devexit max1111_remove(struct spi_device *spi)
+{
+ struct max1111_data *data = spi_get_drvdata(spi);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
+ kfree(data->rx_buf);
+ kfree(data->tx_buf);
+ kfree(data);
+ return 0;
+}
+
+static struct spi_driver max1111_driver = {
+ .driver = {
+ .name = "max1111",
+ .owner = THIS_MODULE,
+ },
+ .probe = max1111_probe,
+ .remove = __devexit_p(max1111_remove),
+};
+
+static int __init max1111_init(void)
+{
+ return spi_register_driver(&max1111_driver);
+}
+module_init(max1111_init);
+
+static void __exit max1111_exit(void)
+{
+ spi_unregister_driver(&max1111_driver);
+}
+module_exit(max1111_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("MAX1111 ADC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 1ab1cacad59..7897754f3a5 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -69,11 +69,18 @@ I2C_CLIENT_INSMOD_1(max1619);
#define MAX1619_REG_W_TCRIT_HYST 0x13
/*
- * Conversions and various macros
+ * Conversions
*/
-#define TEMP_FROM_REG(val) ((val & 0x80 ? val-0x100 : val) * 1000)
-#define TEMP_TO_REG(val) ((val < 0 ? val+0x100*1000 : val) / 1000)
+static int temp_from_reg(int val)
+{
+ return (val & 0x80 ? val-0x100 : val) * 1000;
+}
+
+static int temp_to_reg(int val)
+{
+ return (val < 0 ? val+0x100*1000 : val) / 1000;
+}
/*
* Functions declaration
@@ -135,7 +142,7 @@ struct max1619_data {
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct max1619_data *data = max1619_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+ return sprintf(buf, "%d\n", temp_from_reg(data->value)); \
}
show_temp(temp_input1);
show_temp(temp_input2);
@@ -153,7 +160,7 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
long val = simple_strtol(buf, NULL, 10); \
\
mutex_lock(&data->update_lock); \
- data->value = TEMP_TO_REG(val); \
+ data->value = temp_to_reg(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \
mutex_unlock(&data->update_lock); \
return count; \
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
new file mode 100644
index 00000000000..68e90abeba9
--- /dev/null
+++ b/drivers/hwmon/ultra45_env.c
@@ -0,0 +1,320 @@
+/* ultra45_env.c: Driver for Ultra45 PIC16F747 environmental monitor.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#define DRV_MODULE_VERSION "0.1"
+
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Ultra45 environmental monitor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* PIC device registers */
+#define REG_CMD 0x00UL
+#define REG_CMD_RESET 0x80
+#define REG_CMD_ESTAR 0x01
+#define REG_STAT 0x01UL
+#define REG_STAT_FWVER 0xf0
+#define REG_STAT_TGOOD 0x08
+#define REG_STAT_STALE 0x04
+#define REG_STAT_BUSY 0x02
+#define REG_STAT_FAULT 0x01
+#define REG_DATA 0x40UL
+#define REG_ADDR 0x41UL
+#define REG_SIZE 0x42UL
+
+/* Registers accessed indirectly via REG_DATA/REG_ADDR */
+#define IREG_FAN0 0x00
+#define IREG_FAN1 0x01
+#define IREG_FAN2 0x02
+#define IREG_FAN3 0x03
+#define IREG_FAN4 0x04
+#define IREG_FAN5 0x05
+#define IREG_LCL_TEMP 0x06
+#define IREG_RMT1_TEMP 0x07
+#define IREG_RMT2_TEMP 0x08
+#define IREG_RMT3_TEMP 0x09
+#define IREG_LM95221_TEMP 0x0a
+#define IREG_FIRE_TEMP 0x0b
+#define IREG_LSI1064_TEMP 0x0c
+#define IREG_FRONT_TEMP 0x0d
+#define IREG_FAN_STAT 0x0e
+#define IREG_VCORE0 0x0f
+#define IREG_VCORE1 0x10
+#define IREG_VMEM0 0x11
+#define IREG_VMEM1 0x12
+#define IREG_PSU_TEMP 0x13
+
+struct env {
+ void __iomem *regs;
+ spinlock_t lock;
+
+ struct device *hwmon_dev;
+};
+
+static u8 env_read(struct env *p, u8 ireg)
+{
+ u8 ret;
+
+ spin_lock(&p->lock);
+ writeb(ireg, p->regs + REG_ADDR);
+ ret = readb(p->regs + REG_DATA);
+ spin_unlock(&p->lock);
+
+ return ret;
+}
+
+static void env_write(struct env *p, u8 ireg, u8 val)
+{
+ spin_lock(&p->lock);
+ writeb(ireg, p->regs + REG_ADDR);
+ writeb(val, p->regs + REG_DATA);
+ spin_unlock(&p->lock);
+}
+
+/* There seems to be a adr7462 providing these values, thus a lot
+ * of these calculations are borrowed from the adt7470 driver.
+ */
+#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x))
+#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM
+#define FAN_PERIOD_INVALID (0xff << 8)
+#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
+
+static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int fan_nr = to_sensor_dev_attr(attr)->index;
+ struct env *p = dev_get_drvdata(dev);
+ int rpm, period;
+ u8 val;
+
+ val = env_read(p, IREG_FAN0 + fan_nr);
+ period = (int) val << 8;
+ if (FAN_DATA_VALID(period))
+ rpm = FAN_PERIOD_TO_RPM(period);
+ else
+ rpm = 0;
+
+ return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int fan_nr = to_sensor_dev_attr(attr)->index;
+ int rpm = simple_strtol(buf, NULL, 10);
+ struct env *p = dev_get_drvdata(dev);
+ int period;
+ u8 val;
+
+ if (!rpm)
+ return -EINVAL;
+
+ period = FAN_RPM_TO_PERIOD(rpm);
+ val = period >> 8;
+ env_write(p, IREG_FAN0 + fan_nr, val);
+
+ return count;
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int fan_nr = to_sensor_dev_attr(attr)->index;
+ struct env *p = dev_get_drvdata(dev);
+ u8 val = env_read(p, IREG_FAN_STAT);
+ return sprintf(buf, "%d\n", (val & (1 << fan_nr)) ? 1 : 0);
+}
+
+#define fan(index) \
+static SENSOR_DEVICE_ATTR(fan##index##_speed, S_IRUGO | S_IWUSR, \
+ show_fan_speed, set_fan_speed, index); \
+static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, \
+ show_fan_fault, NULL, index)
+
+fan(0);
+fan(1);
+fan(2);
+fan(3);
+fan(4);
+
+static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6);
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int temp_nr = to_sensor_dev_attr(attr)->index;
+ struct env *p = dev_get_drvdata(dev);
+ s8 val;
+
+ val = env_read(p, IREG_LCL_TEMP + temp_nr);
+ return sprintf(buf, "%d\n", ((int) val) - 64);
+}
+
+static SENSOR_DEVICE_ATTR(adt7462_local_temp, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(cpu0_temp, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(cpu1_temp, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(motherboard_temp, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(lm95221_local_temp, S_IRUGO, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(fire_temp, S_IRUGO, show_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13);
+
+static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int index = to_sensor_dev_attr(attr)->index;
+ struct env *p = dev_get_drvdata(dev);
+ u8 val;
+
+ val = readb(p->regs + REG_STAT);
+ return sprintf(buf, "%d\n", (val & (1 << index)) ? 1 : 0);
+}
+
+static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0);
+static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1);
+static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2);
+static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, 3);
+
+static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct env *p = dev_get_drvdata(dev);
+ u8 val;
+
+ val = readb(p->regs + REG_STAT);
+ return sprintf(buf, "%d\n", val >> 4);
+}
+
+static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0);
+
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "ultra45\n");
+}
+
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
+static struct attribute *env_attributes[] = {
+ &sensor_dev_attr_fan0_speed.dev_attr.attr,
+ &sensor_dev_attr_fan0_fault.dev_attr.attr,
+ &sensor_dev_attr_fan1_speed.dev_attr.attr,
+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
+ &sensor_dev_attr_fan2_speed.dev_attr.attr,
+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
+ &sensor_dev_attr_fan3_speed.dev_attr.attr,
+ &sensor_dev_attr_fan3_fault.dev_attr.attr,
+ &sensor_dev_attr_fan4_speed.dev_attr.attr,
+ &sensor_dev_attr_fan4_fault.dev_attr.attr,
+ &sensor_dev_attr_psu_fan_fault.dev_attr.attr,
+ &sensor_dev_attr_adt7462_local_temp.dev_attr.attr,
+ &sensor_dev_attr_cpu0_temp.dev_attr.attr,
+ &sensor_dev_attr_cpu1_temp.dev_attr.attr,
+ &sensor_dev_attr_motherboard_temp.dev_attr.attr,
+ &sensor_dev_attr_lm95221_local_temp.dev_attr.attr,
+ &sensor_dev_attr_fire_temp.dev_attr.attr,
+ &sensor_dev_attr_lsi1064_local_temp.dev_attr.attr,
+ &sensor_dev_attr_front_panel_temp.dev_attr.attr,
+ &sensor_dev_attr_psu_temp.dev_attr.attr,
+ &sensor_dev_attr_fan_failure.dev_attr.attr,
+ &sensor_dev_attr_env_bus_busy.dev_attr.attr,
+ &sensor_dev_attr_env_data_stale.dev_attr.attr,
+ &sensor_dev_attr_tpm_self_test_passed.dev_attr.attr,
+ &sensor_dev_attr_firmware_version.dev_attr.attr,
+ &sensor_dev_attr_name.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group env_group = {
+ .attrs = env_attributes,
+};
+
+static int __devinit env_probe(struct of_device *op,
+ const struct of_device_id *match)
+{
+ struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ int err = -ENOMEM;
+
+ if (!p)
+ goto out;
+
+ spin_lock_init(&p->lock);
+
+ p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747");
+ if (!p->regs)
+ goto out_free;
+
+ err = sysfs_create_group(&op->dev.kobj, &env_group);
+ if (err)
+ goto out_iounmap;
+
+ p->hwmon_dev = hwmon_device_register(&op->dev);
+ if (IS_ERR(p->hwmon_dev)) {
+ err = PTR_ERR(p->hwmon_dev);
+ goto out_sysfs_remove_group;
+ }
+
+ dev_set_drvdata(&op->dev, p);
+ err = 0;
+
+out:
+ return err;
+
+out_sysfs_remove_group:
+ sysfs_remove_group(&op->dev.kobj, &env_group);
+
+out_iounmap:
+ of_iounmap(&op->resource[0], p->regs, REG_SIZE);
+
+out_free:
+ kfree(p);
+ goto out;
+}
+
+static int __devexit env_remove(struct of_device *op)
+{
+ struct env *p = dev_get_drvdata(&op->dev);
+
+ if (p) {
+ sysfs_remove_group(&op->dev.kobj, &env_group);
+ hwmon_device_unregister(p->hwmon_dev);
+ of_iounmap(&op->resource[0], p->regs, REG_SIZE);
+ kfree(p);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id env_match[] = {
+ {
+ .name = "env-monitor",
+ .compatible = "SUNW,ebus-pic16f747-env",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, env_match);
+
+static struct of_platform_driver env_driver = {
+ .name = "ultra45_env",
+ .match_table = env_match,
+ .probe = env_probe,
+ .remove = __devexit_p(env_remove),
+};
+
+static int __init env_init(void)
+{
+ return of_register_driver(&env_driver, &of_bus_type);
+}
+
+static void __exit env_exit(void)
+{
+ of_unregister_driver(&env_driver);
+}
+
+module_init(env_init);
+module_exit(env_exit);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index f942ecdd47c..d4d1b859d4f 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -4,7 +4,7 @@
Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
and Mark Studebaker <mdsxyz123@yahoo.com>
- Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
+ Copyright (c) 2007 - 2008 Jean Delvare <khali@linux-fr.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
@@ -38,25 +38,24 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
#include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h>
#include <linux/sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+
+#ifdef CONFIG_ISA
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
#include <asm/io.h>
-#include "lm75.h"
+#endif
-/* ISA device, if found */
-static struct platform_device *pdev;
+#include "lm75.h"
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned short isa_address = 0x290;
-
/* Insmod parameters */
I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
@@ -178,9 +177,9 @@ FAN_FROM_REG(u8 val, int div)
#define TEMP_FROM_REG(val) ((val) * 1000)
#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \
- (val) ^ 0x7fff : (val))
+ (~(val)) & 0x7fff : (val) & 0xff7fff)
#define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \
- (~(val)) & 0x7fff : (val) & 0xffffff)
+ (~(val)) & 0x7fff : (val) & 0xff7fff)
#define DIV_FROM_REG(val) (1 << (val))
@@ -199,25 +198,16 @@ DIV_TO_REG(long val, enum chips type)
return i;
}
-/* There are some complications in a module like this. First off, W83781D chips
- may be both present on the SMBus and the ISA bus, and we have to handle
- those cases separately at some places. Second, there might be several
- W83781D chips available (well, actually, that is probably never done; but
- it is a clean illustration of how to handle a case like that). Finally,
- a specific chip may be attached to *both* ISA and SMBus, and we would
- not like to detect it double. Fortunately, in the case of the W83781D at
- least, a register tells us what SMBus address we are on, so that helps
- a bit - except if there could be more than one SMBus. Groan. No solution
- for this yet. */
-
-/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
- the driver field to differentiate between I2C and ISA chips. */
struct w83781d_data {
- struct i2c_client client;
+ struct i2c_client *client;
struct device *hwmon_dev;
struct mutex lock;
enum chips type;
+ /* For ISA device only */
+ const char *name;
+ int isa_addr;
+
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -240,7 +230,6 @@ struct w83781d_data {
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
u32 beep_mask; /* Register encoding, combined */
- u8 beep_enable; /* Boolean */
u8 pwm[4]; /* Register value */
u8 pwm2_enable; /* Boolean */
u16 sens[3]; /* 782D/783S only.
@@ -249,36 +238,14 @@ struct w83781d_data {
u8 vrm;
};
-static int w83781d_attach_adapter(struct i2c_adapter *adapter);
-static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
-static int w83781d_detach_client(struct i2c_client *client);
-
-static int __devinit w83781d_isa_probe(struct platform_device *pdev);
-static int __devexit w83781d_isa_remove(struct platform_device *pdev);
+static struct w83781d_data *w83781d_data_if_isa(void);
+static int w83781d_alias_detect(struct i2c_client *client, u8 chipid);
static int w83781d_read_value(struct w83781d_data *data, u16 reg);
static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
static struct w83781d_data *w83781d_update_device(struct device *dev);
static void w83781d_init_device(struct device *dev);
-static struct i2c_driver w83781d_driver = {
- .driver = {
- .name = "w83781d",
- },
- .attach_adapter = w83781d_attach_adapter,
- .detach_client = w83781d_detach_client,
-};
-
-static struct platform_driver w83781d_isa_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "w83781d",
- },
- .probe = w83781d_isa_probe,
- .remove = w83781d_isa_remove,
-};
-
-
/* following are the sysfs callback functions */
#define show_in_reg(reg) \
static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
@@ -513,11 +480,6 @@ static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr
return sprintf(buf, "%ld\n",
(long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
}
-static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83781d_data *data = w83781d_update_device(dev);
- return sprintf(buf, "%ld\n", (long)data->beep_enable);
-}
static ssize_t
store_beep_mask(struct device *dev, struct device_attribute *attr,
@@ -529,12 +491,12 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
- data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
+ data->beep_mask &= 0x8000; /* preserve beep enable */
+ data->beep_mask |= BEEP_MASK_TO_REG(val, data->type);
w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
data->beep_mask & 0xff);
w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
- ((data->beep_mask >> 8) & 0x7f)
- | data->beep_enable << 7);
+ (data->beep_mask >> 8) & 0xff);
if (data->type != w83781d && data->type != as99127f) {
w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
((data->beep_mask) >> 16) & 0xff);
@@ -544,31 +506,8 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t
-store_beep_enable(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct w83781d_data *data = dev_get_drvdata(dev);
- u32 val;
-
- val = simple_strtoul(buf, NULL, 10);
- if (val != 0 && val != 1)
- return -EINVAL;
-
- mutex_lock(&data->update_lock);
- data->beep_enable = val;
- val = w83781d_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
- val |= data->beep_enable << 7;
- w83781d_write_value(data, W83781D_REG_BEEP_INTS2, val);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
show_beep_mask, store_beep_mask);
-static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
- show_beep_enable, store_beep_enable);
static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -663,6 +602,8 @@ static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
show_beep, store_beep, 5);
static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO,
show_temp3_beep, store_beep, 13);
+static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+ show_beep, store_beep, 15);
static ssize_t
show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
@@ -866,45 +807,19 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
show_sensor, store_sensor, 2);
-/* I2C devices get this name attribute automatically, but for ISA devices
- we must create it by ourselves. */
-static ssize_t
-show_name(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- struct w83781d_data *data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", data->client.name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-/* This function is called when:
- * w83781d_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and w83781d_driver is still present) */
-static int
-w83781d_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, w83781d_detect);
-}
-
/* Assumes that adapter is of I2C, not ISA variety.
* OTHERWISE DON'T CALL THIS
*/
static int
-w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
- struct i2c_client *new_client)
+w83781d_detect_subclients(struct i2c_client *new_client)
{
int i, val1 = 0, id;
int err;
- const char *client_name = "";
+ int address = new_client->addr;
+ unsigned short sc_addr[2];
+ struct i2c_adapter *adapter = new_client->adapter;
struct w83781d_data *data = i2c_get_clientdata(new_client);
-
- data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!(data->lm75[0])) {
- err = -ENOMEM;
- goto ERROR_SC_0;
- }
+ enum chips kind = data->type;
id = i2c_adapter_id(adapter);
@@ -922,55 +837,35 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) << 4));
- data->lm75[0]->addr = force_subclients[2];
+ sc_addr[0] = force_subclients[2];
} else {
val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
- data->lm75[0]->addr = 0x48 + (val1 & 0x07);
+ sc_addr[0] = 0x48 + (val1 & 0x07);
}
if (kind != w83783s) {
- data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!(data->lm75[1])) {
- err = -ENOMEM;
- goto ERROR_SC_1;
- }
-
if (force_subclients[0] == id &&
force_subclients[1] == address) {
- data->lm75[1]->addr = force_subclients[3];
+ sc_addr[1] = force_subclients[3];
} else {
- data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
+ sc_addr[1] = 0x48 + ((val1 >> 4) & 0x07);
}
- if (data->lm75[0]->addr == data->lm75[1]->addr) {
+ if (sc_addr[0] == sc_addr[1]) {
dev_err(&new_client->dev,
"Duplicate addresses 0x%x for subclients.\n",
- data->lm75[0]->addr);
+ sc_addr[0]);
err = -EBUSY;
goto ERROR_SC_2;
}
}
- if (kind == w83781d)
- client_name = "w83781d subclient";
- else if (kind == w83782d)
- client_name = "w83782d subclient";
- else if (kind == w83783s)
- client_name = "w83783s subclient";
- else if (kind == as99127f)
- client_name = "as99127f subclient";
-
for (i = 0; i <= 1; i++) {
- /* store all data in w83781d */
- i2c_set_clientdata(data->lm75[i], NULL);
- data->lm75[i]->adapter = adapter;
- data->lm75[i]->driver = &w83781d_driver;
- data->lm75[i]->flags = 0;
- strlcpy(data->lm75[i]->name, client_name,
- I2C_NAME_SIZE);
- if ((err = i2c_attach_client(data->lm75[i]))) {
+ data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]);
+ if (!data->lm75[i]) {
dev_err(&new_client->dev, "Subclient %d "
"registration at address 0x%x "
- "failed.\n", i, data->lm75[i]->addr);
+ "failed.\n", i, sc_addr[i]);
+ err = -ENOMEM;
if (i == 1)
goto ERROR_SC_3;
goto ERROR_SC_2;
@@ -983,12 +878,9 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
/* Undo inits in case of errors */
ERROR_SC_3:
- i2c_detach_client(data->lm75[0]);
+ i2c_unregister_device(data->lm75[0]);
ERROR_SC_2:
- kfree(data->lm75[1]);
ERROR_SC_1:
- kfree(data->lm75[0]);
-ERROR_SC_0:
return err;
}
@@ -1029,7 +921,7 @@ static struct attribute* w83781d_attributes[] = {
&dev_attr_vrm.attr,
&dev_attr_alarms.attr,
&dev_attr_beep_mask.attr,
- &dev_attr_beep_enable.attr,
+ &sensor_dev_attr_beep_enable.dev_attr.attr,
NULL
};
static const struct attribute_group w83781d_group = {
@@ -1151,96 +1043,74 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
}
}
- if (is_isa) {
- err = device_create_file(&pdev->dev, &dev_attr_name);
- if (err)
- return err;
- }
-
return 0;
}
+/* Return 0 if detection is successful, -ENODEV otherwise */
static int
-w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
+w83781d_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
{
int val1 = 0, val2;
- struct i2c_client *client;
- struct device *dev;
- struct w83781d_data *data;
- int err;
+ struct w83781d_data *isa = w83781d_data_if_isa();
+ struct i2c_adapter *adapter = client->adapter;
+ int address = client->addr;
const char *client_name = "";
enum vendor { winbond, asus } vendid;
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- err = -EINVAL;
- goto ERROR1;
- }
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access w83781d_{read,write}_value. */
-
- if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto ERROR1;
- }
-
- client = &data->client;
- i2c_set_clientdata(client, data);
- client->addr = address;
- mutex_init(&data->lock);
- client->adapter = adapter;
- client->driver = &w83781d_driver;
- dev = &client->dev;
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- /* Now, we do the remaining detection. */
+ /* We block updates of the ISA device to minimize the risk of
+ concurrent access to the same W83781D chip through different
+ interfaces. */
+ if (isa)
+ mutex_lock(&isa->update_lock);
/* The w8378?d may be stuck in some other bank than bank 0. This may
make reading other information impossible. Specify a force=... or
force_*=... parameter, and the Winbond will be reset to the right
bank. */
if (kind < 0) {
- if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
+ if (i2c_smbus_read_byte_data
+ (client, W83781D_REG_CONFIG) & 0x80) {
dev_dbg(&adapter->dev, "Detection of w83781d chip "
"failed at step 3\n");
- err = -ENODEV;
- goto ERROR2;
+ goto err_nodev;
}
- val1 = w83781d_read_value(data, W83781D_REG_BANK);
- val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
+ val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK);
+ val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
/* Check for Winbond or Asus ID if in bank 0 */
if ((!(val1 & 0x07)) &&
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
dev_dbg(&adapter->dev, "Detection of w83781d chip "
"failed at step 4\n");
- err = -ENODEV;
- goto ERROR2;
+ goto err_nodev;
}
/* If Winbond SMBus, check address at 0x48.
Asus doesn't support, except for as99127f rev.2 */
if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
((val1 & 0x80) && (val2 == 0x5c))) {
- if (w83781d_read_value
- (data, W83781D_REG_I2C_ADDR) != address) {
+ if (i2c_smbus_read_byte_data
+ (client, W83781D_REG_I2C_ADDR) != address) {
dev_dbg(&adapter->dev, "Detection of w83781d "
"chip failed at step 5\n");
- err = -ENODEV;
- goto ERROR2;
+ goto err_nodev;
}
}
}
/* We have either had a force parameter, or we have already detected the
Winbond. Put it now into bank 0 and Vendor ID High Byte */
- w83781d_write_value(data, W83781D_REG_BANK,
- (w83781d_read_value(data, W83781D_REG_BANK)
- & 0x78) | 0x80);
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+ (i2c_smbus_read_byte_data(client, W83781D_REG_BANK)
+ & 0x78) | 0x80);
/* Determine the chip type. */
if (kind <= 0) {
/* get vendor ID */
- val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
+ val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
if (val2 == 0x5c)
vendid = winbond;
else if (val2 == 0x12)
@@ -1248,11 +1118,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
else {
dev_dbg(&adapter->dev, "w83781d chip vendor is "
"neither Winbond nor Asus\n");
- err = -ENODEV;
- goto ERROR2;
+ goto err_nodev;
}
- val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
+ val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID);
if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
kind = w83781d;
else if (val1 == 0x30 && vendid == winbond)
@@ -1266,11 +1135,20 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
dev_warn(&adapter->dev, "Ignoring 'force' "
"parameter for unknown chip at "
"address 0x%02x\n", address);
- err = -EINVAL;
- goto ERROR2;
+ goto err_nodev;
+ }
+
+ if ((kind == w83781d || kind == w83782d)
+ && w83781d_alias_detect(client, val1)) {
+ dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
+ "be the same as ISA device\n", address);
+ goto err_nodev;
}
}
+ if (isa)
+ mutex_unlock(&isa->update_lock);
+
if (kind == w83781d) {
client_name = "w83781d";
} else if (kind == w83782d) {
@@ -1281,24 +1159,46 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "as99127f";
}
- /* Fill in the remaining client fields and put into the global list */
- strlcpy(client->name, client_name, I2C_NAME_SIZE);
- data->type = kind;
+ strlcpy(info->type, client_name, I2C_NAME_SIZE);
+
+ return 0;
+
+ err_nodev:
+ if (isa)
+ mutex_unlock(&isa->update_lock);
+ return -ENODEV;
+}
+
+static int
+w83781d_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct w83781d_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto ERROR1;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->lock);
+ mutex_init(&data->update_lock);
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto ERROR2;
+ data->type = id->driver_data;
+ data->client = client;
/* attach secondary i2c lm75-like clients */
- if ((err = w83781d_detect_subclients(adapter, address,
- kind, client)))
+ err = w83781d_detect_subclients(client);
+ if (err)
goto ERROR3;
/* Initialize the chip */
w83781d_init_device(dev);
/* Register sysfs hooks */
- err = w83781d_create_files(dev, kind, 0);
+ err = w83781d_create_files(dev, data->type, 0);
if (err)
goto ERROR4;
@@ -1314,264 +1214,113 @@ ERROR4:
sysfs_remove_group(&dev->kobj, &w83781d_group);
sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
- if (data->lm75[1]) {
- i2c_detach_client(data->lm75[1]);
- kfree(data->lm75[1]);
- }
- if (data->lm75[0]) {
- i2c_detach_client(data->lm75[0]);
- kfree(data->lm75[0]);
- }
+ if (data->lm75[0])
+ i2c_unregister_device(data->lm75[0]);
+ if (data->lm75[1])
+ i2c_unregister_device(data->lm75[1]);
ERROR3:
- i2c_detach_client(client);
-ERROR2:
+ i2c_set_clientdata(client, NULL);
kfree(data);
ERROR1:
return err;
}
static int
-w83781d_detach_client(struct i2c_client *client)
+w83781d_remove(struct i2c_client *client)
{
struct w83781d_data *data = i2c_get_clientdata(client);
- int err;
-
- /* main client */
- if (data) {
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &w83781d_group);
- sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
- }
-
- if ((err = i2c_detach_client(client)))
- return err;
+ struct device *dev = &client->dev;
- /* main client */
- if (data)
- kfree(data);
-
- /* subclient */
- else
- kfree(client);
-
- return 0;
-}
-
-static int __devinit
-w83781d_isa_probe(struct platform_device *pdev)
-{
- int err, reg;
- struct w83781d_data *data;
- struct resource *res;
- const char *name;
-
- /* Reserve the ISA region */
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
- "w83781d")) {
- err = -EBUSY;
- goto exit;
- }
-
- if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit_release_region;
- }
- mutex_init(&data->lock);
- data->client.addr = res->start;
- i2c_set_clientdata(&data->client, data);
- platform_set_drvdata(pdev, data);
-
- reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
- switch (reg) {
- case 0x30:
- data->type = w83782d;
- name = "w83782d";
- break;
- default:
- data->type = w83781d;
- name = "w83781d";
- }
- strlcpy(data->client.name, name, I2C_NAME_SIZE);
-
- /* Initialize the W83781D chip */
- w83781d_init_device(&pdev->dev);
-
- /* Register sysfs hooks */
- err = w83781d_create_files(&pdev->dev, data->type, 1);
- if (err)
- goto exit_remove_files;
-
- data->hwmon_dev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
+ hwmon_device_unregister(data->hwmon_dev);
- exit_remove_files:
- sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
- sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
- device_remove_file(&pdev->dev, &dev_attr_name);
- kfree(data);
- exit_release_region:
- release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
- exit:
- return err;
-}
+ sysfs_remove_group(&dev->kobj, &w83781d_group);
+ sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
-static int __devexit
-w83781d_isa_remove(struct platform_device *pdev)
-{
- struct w83781d_data *data = platform_get_drvdata(pdev);
+ if (data->lm75[0])
+ i2c_unregister_device(data->lm75[0]);
+ if (data->lm75[1])
+ i2c_unregister_device(data->lm75[1]);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
- sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
- device_remove_file(&pdev->dev, &dev_attr_name);
- release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2);
+ i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
}
-/* The SMBus locks itself, usually, but nothing may access the Winbond between
- bank switches. ISA access must always be locked explicitly!
- We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
- would slow down the W83781D access and should not be necessary.
- There are some ugly typecasts here, but the good news is - they should
- nowhere else be necessary! */
static int
-w83781d_read_value(struct w83781d_data *data, u16 reg)
+w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
{
- struct i2c_client *client = &data->client;
- int res, word_sized, bank;
+ struct i2c_client *client = data->client;
+ int res, bank;
struct i2c_client *cl;
- mutex_lock(&data->lock);
- if (!client->driver) { /* ISA device */
- word_sized = (((reg & 0xff00) == 0x100)
- || ((reg & 0xff00) == 0x200))
- && (((reg & 0x00ff) == 0x50)
- || ((reg & 0x00ff) == 0x53)
- || ((reg & 0x00ff) == 0x55));
- if (reg & 0xff00) {
- outb_p(W83781D_REG_BANK,
- client->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(reg >> 8,
- client->addr + W83781D_DATA_REG_OFFSET);
- }
- outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
- res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
- if (word_sized) {
- outb_p((reg & 0xff) + 1,
- client->addr + W83781D_ADDR_REG_OFFSET);
- res =
- (res << 8) + inb_p(client->addr +
- W83781D_DATA_REG_OFFSET);
- }
- if (reg & 0xff00) {
- outb_p(W83781D_REG_BANK,
- client->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
- }
+ bank = (reg >> 8) & 0x0f;
+ if (bank > 2)
+ /* switch banks */
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+ bank);
+ if (bank == 0 || bank > 2) {
+ res = i2c_smbus_read_byte_data(client, reg & 0xff);
} else {
- bank = (reg >> 8) & 0x0f;
- if (bank > 2)
- /* switch banks */
- i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
- bank);
- if (bank == 0 || bank > 2) {
- res = i2c_smbus_read_byte_data(client, reg & 0xff);
- } else {
- /* switch to subclient */
- cl = data->lm75[bank - 1];
- /* convert from ISA to LM75 I2C addresses */
- switch (reg & 0xff) {
- case 0x50: /* TEMP */
- res = swab16(i2c_smbus_read_word_data(cl, 0));
- break;
- case 0x52: /* CONFIG */
- res = i2c_smbus_read_byte_data(cl, 1);
- break;
- case 0x53: /* HYST */
- res = swab16(i2c_smbus_read_word_data(cl, 2));
- break;
- case 0x55: /* OVER */
- default:
- res = swab16(i2c_smbus_read_word_data(cl, 3));
- break;
- }
+ /* switch to subclient */
+ cl = data->lm75[bank - 1];
+ /* convert from ISA to LM75 I2C addresses */
+ switch (reg & 0xff) {
+ case 0x50: /* TEMP */
+ res = swab16(i2c_smbus_read_word_data(cl, 0));
+ break;
+ case 0x52: /* CONFIG */
+ res = i2c_smbus_read_byte_data(cl, 1);
+ break;
+ case 0x53: /* HYST */
+ res = swab16(i2c_smbus_read_word_data(cl, 2));
+ break;
+ case 0x55: /* OVER */
+ default:
+ res = swab16(i2c_smbus_read_word_data(cl, 3));
+ break;
}
- if (bank > 2)
- i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
}
- mutex_unlock(&data->lock);
+ if (bank > 2)
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+
return res;
}
static int
-w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
+w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
{
- struct i2c_client *client = &data->client;
- int word_sized, bank;
+ struct i2c_client *client = data->client;
+ int bank;
struct i2c_client *cl;
- mutex_lock(&data->lock);
- if (!client->driver) { /* ISA device */
- word_sized = (((reg & 0xff00) == 0x100)
- || ((reg & 0xff00) == 0x200))
- && (((reg & 0x00ff) == 0x53)
- || ((reg & 0x00ff) == 0x55));
- if (reg & 0xff00) {
- outb_p(W83781D_REG_BANK,
- client->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(reg >> 8,
- client->addr + W83781D_DATA_REG_OFFSET);
- }
- outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
- if (word_sized) {
- outb_p(value >> 8,
- client->addr + W83781D_DATA_REG_OFFSET);
- outb_p((reg & 0xff) + 1,
- client->addr + W83781D_ADDR_REG_OFFSET);
- }
- outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
- if (reg & 0xff00) {
- outb_p(W83781D_REG_BANK,
- client->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
- }
+ bank = (reg >> 8) & 0x0f;
+ if (bank > 2)
+ /* switch banks */
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+ bank);
+ if (bank == 0 || bank > 2) {
+ i2c_smbus_write_byte_data(client, reg & 0xff,
+ value & 0xff);
} else {
- bank = (reg >> 8) & 0x0f;
- if (bank > 2)
- /* switch banks */
- i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
- bank);
- if (bank == 0 || bank > 2) {
- i2c_smbus_write_byte_data(client, reg & 0xff,
- value & 0xff);
- } else {
- /* switch to subclient */
- cl = data->lm75[bank - 1];
- /* convert from ISA to LM75 I2C addresses */
- switch (reg & 0xff) {
- case 0x52: /* CONFIG */
- i2c_smbus_write_byte_data(cl, 1, value & 0xff);
- break;
- case 0x53: /* HYST */
- i2c_smbus_write_word_data(cl, 2, swab16(value));
- break;
- case 0x55: /* OVER */
- i2c_smbus_write_word_data(cl, 3, swab16(value));
- break;
- }
+ /* switch to subclient */
+ cl = data->lm75[bank - 1];
+ /* convert from ISA to LM75 I2C addresses */
+ switch (reg & 0xff) {
+ case 0x52: /* CONFIG */
+ i2c_smbus_write_byte_data(cl, 1, value & 0xff);
+ break;
+ case 0x53: /* HYST */
+ i2c_smbus_write_word_data(cl, 2, swab16(value));
+ break;
+ case 0x55: /* OVER */
+ i2c_smbus_write_word_data(cl, 3, swab16(value));
+ break;
}
- if (bank > 2)
- i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
}
- mutex_unlock(&data->lock);
+ if (bank > 2)
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+
return 0;
}
@@ -1678,7 +1427,7 @@ w83781d_init_device(struct device *dev)
static struct w83781d_data *w83781d_update_device(struct device *dev)
{
struct w83781d_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = &data->client;
+ struct i2c_client *client = data->client;
int i;
mutex_lock(&data->update_lock);
@@ -1775,8 +1524,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
W83781D_REG_ALARM2) << 8);
}
i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
- data->beep_enable = i >> 7;
- data->beep_mask = ((i & 0x7f) << 8) +
+ data->beep_mask = (i << 8) +
w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
if ((data->type != w83781d) && (data->type != as99127f)) {
data->beep_mask |=
@@ -1792,6 +1540,275 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
return data;
}
+static const struct i2c_device_id w83781d_ids[] = {
+ { "w83781d", w83781d, },
+ { "w83782d", w83782d, },
+ { "w83783s", w83783s, },
+ { "as99127f", as99127f },
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, w83781d_ids);
+
+static struct i2c_driver w83781d_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "w83781d",
+ },
+ .probe = w83781d_probe,
+ .remove = w83781d_remove,
+ .id_table = w83781d_ids,
+ .detect = w83781d_detect,
+ .address_data = &addr_data,
+};
+
+/*
+ * ISA related code
+ */
+#ifdef CONFIG_ISA
+
+/* ISA device, if found */
+static struct platform_device *pdev;
+
+static unsigned short isa_address = 0x290;
+
+/* I2C devices get this name attribute automatically, but for ISA devices
+ we must create it by ourselves. */
+static ssize_t
+show_name(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct w83781d_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct w83781d_data *w83781d_data_if_isa(void)
+{
+ return pdev ? platform_get_drvdata(pdev) : NULL;
+}
+
+/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
+static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
+{
+ struct w83781d_data *isa;
+ int i;
+
+ if (!pdev) /* No ISA chip */
+ return 0;
+
+ isa = platform_get_drvdata(pdev);
+
+ if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
+ return 0; /* Address doesn't match */
+ if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
+ return 0; /* Chip type doesn't match */
+
+ /* We compare all the limit registers, the config register and the
+ * interrupt mask registers */
+ for (i = 0x2b; i <= 0x3d; i++) {
+ if (w83781d_read_value(isa, i) !=
+ i2c_smbus_read_byte_data(client, i))
+ return 0;
+ }
+ if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
+ i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG))
+ return 0;
+ for (i = 0x43; i <= 0x46; i++) {
+ if (w83781d_read_value(isa, i) !=
+ i2c_smbus_read_byte_data(client, i))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
+{
+ int word_sized, res;
+
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x50)
+ || ((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(reg >> 8,
+ data->isa_addr + W83781D_DATA_REG_OFFSET);
+ }
+ outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET);
+ if (word_sized) {
+ outb_p((reg & 0xff) + 1,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ res =
+ (res << 8) + inb_p(data->isa_addr +
+ W83781D_DATA_REG_OFFSET);
+ }
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET);
+ }
+ return res;
+}
+
+static void
+w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
+{
+ int word_sized;
+
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(reg >> 8,
+ data->isa_addr + W83781D_DATA_REG_OFFSET);
+ }
+ outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ if (word_sized) {
+ outb_p(value >> 8,
+ data->isa_addr + W83781D_DATA_REG_OFFSET);
+ outb_p((reg & 0xff) + 1,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ }
+ outb_p(value & 0xff, data->isa_addr + W83781D_DATA_REG_OFFSET);
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ data->isa_addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET);
+ }
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+ bank switches. ISA access must always be locked explicitly!
+ We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
+ would slow down the W83781D access and should not be necessary.
+ There are some ugly typecasts here, but the good news is - they should
+ nowhere else be necessary! */
+static int
+w83781d_read_value(struct w83781d_data *data, u16 reg)
+{
+ struct i2c_client *client = data->client;
+ int res;
+
+ mutex_lock(&data->lock);
+ if (client)
+ res = w83781d_read_value_i2c(data, reg);
+ else
+ res = w83781d_read_value_isa(data, reg);
+ mutex_unlock(&data->lock);
+ return res;
+}
+
+static int
+w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
+{
+ struct i2c_client *client = data->client;
+
+ mutex_lock(&data->lock);
+ if (client)
+ w83781d_write_value_i2c(data, reg, value);
+ else
+ w83781d_write_value_isa(data, reg, value);
+ mutex_unlock(&data->lock);
+ return 0;
+}
+
+static int __devinit
+w83781d_isa_probe(struct platform_device *pdev)
+{
+ int err, reg;
+ struct w83781d_data *data;
+ struct resource *res;
+
+ /* Reserve the ISA region */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
+ "w83781d")) {
+ err = -EBUSY;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit_release_region;
+ }
+ mutex_init(&data->lock);
+ data->isa_addr = res->start;
+ platform_set_drvdata(pdev, data);
+
+ reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
+ switch (reg) {
+ case 0x30:
+ data->type = w83782d;
+ data->name = "w83782d";
+ break;
+ default:
+ data->type = w83781d;
+ data->name = "w83781d";
+ }
+
+ /* Initialize the W83781D chip */
+ w83781d_init_device(&pdev->dev);
+
+ /* Register sysfs hooks */
+ err = w83781d_create_files(&pdev->dev, data->type, 1);
+ if (err)
+ goto exit_remove_files;
+
+ err = device_create_file(&pdev->dev, &dev_attr_name);
+ if (err)
+ goto exit_remove_files;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove_files;
+ }
+
+ return 0;
+
+ exit_remove_files:
+ sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
+ sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ kfree(data);
+ exit_release_region:
+ release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
+ exit:
+ return err;
+}
+
+static int __devexit
+w83781d_isa_remove(struct platform_device *pdev)
+{
+ struct w83781d_data *data = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
+ sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2);
+ kfree(data);
+
+ return 0;
+}
+
+static struct platform_driver w83781d_isa_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "w83781d",
+ },
+ .probe = w83781d_isa_probe,
+ .remove = __devexit_p(w83781d_isa_remove),
+};
+
/* return 1 if a supported chip is found, 0 otherwise */
static int __init
w83781d_isa_found(unsigned short address)
@@ -1928,18 +1945,14 @@ w83781d_isa_device_add(unsigned short address)
}
static int __init
-sensors_w83781d_init(void)
+w83781d_isa_register(void)
{
int res;
- res = i2c_add_driver(&w83781d_driver);
- if (res)
- goto exit;
-
if (w83781d_isa_found(isa_address)) {
res = platform_driver_register(&w83781d_isa_driver);
if (res)
- goto exit_unreg_i2c_driver;
+ goto exit;
/* Sets global pdev as a side effect */
res = w83781d_isa_device_add(isa_address);
@@ -1949,21 +1962,94 @@ sensors_w83781d_init(void)
return 0;
- exit_unreg_isa_driver:
+exit_unreg_isa_driver:
platform_driver_unregister(&w83781d_isa_driver);
- exit_unreg_i2c_driver:
- i2c_del_driver(&w83781d_driver);
- exit:
+exit:
return res;
}
static void __exit
-sensors_w83781d_exit(void)
+w83781d_isa_unregister(void)
{
if (pdev) {
platform_device_unregister(pdev);
platform_driver_unregister(&w83781d_isa_driver);
}
+}
+#else /* !CONFIG_ISA */
+
+static struct w83781d_data *w83781d_data_if_isa(void)
+{
+ return NULL;
+}
+
+static int
+w83781d_alias_detect(struct i2c_client *client, u8 chipid)
+{
+ return 0;
+}
+
+static int
+w83781d_read_value(struct w83781d_data *data, u16 reg)
+{
+ int res;
+
+ mutex_lock(&data->lock);
+ res = w83781d_read_value_i2c(data, reg);
+ mutex_unlock(&data->lock);
+
+ return res;
+}
+
+static int
+w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
+{
+ mutex_lock(&data->lock);
+ w83781d_write_value_i2c(data, reg, value);
+ mutex_unlock(&data->lock);
+
+ return 0;
+}
+
+static int __init
+w83781d_isa_register(void)
+{
+ return 0;
+}
+
+static void __exit
+w83781d_isa_unregister(void)
+{
+}
+#endif /* CONFIG_ISA */
+
+static int __init
+sensors_w83781d_init(void)
+{
+ int res;
+
+ /* We register the ISA device first, so that we can skip the
+ * registration of an I2C interface to the same device. */
+ res = w83781d_isa_register();
+ if (res)
+ goto exit;
+
+ res = i2c_add_driver(&w83781d_driver);
+ if (res)
+ goto exit_unreg_isa;
+
+ return 0;
+
+ exit_unreg_isa:
+ w83781d_isa_unregister();
+ exit:
+ return res;
+}
+
+static void __exit
+sensors_w83781d_exit(void)
+{
+ w83781d_isa_unregister();
i2c_del_driver(&w83781d_driver);
}
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index de21142d106..5768def8a4f 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -23,7 +23,7 @@
Supports following chips:
Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
- w83791d 10 5 3 3 0x71 0x5ca3 yes no
+ w83791d 10 5 5 3 0x71 0x5ca3 yes no
The w83791d chip appears to be part way between the 83781d and the
83792d. Thus, this file is derived from both the w83792d.c and
@@ -45,6 +45,7 @@
#define NUMBER_OF_VIN 10
#define NUMBER_OF_FANIN 5
#define NUMBER_OF_TEMPIN 3
+#define NUMBER_OF_PWM 5
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
@@ -116,6 +117,25 @@ static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
0xBD, /* FAN 5 Count Low Limit in DataSheet */
};
+static const u8 W83791D_REG_PWM[NUMBER_OF_PWM] = {
+ 0x81, /* PWM 1 duty cycle register in DataSheet */
+ 0x83, /* PWM 2 duty cycle register in DataSheet */
+ 0x94, /* PWM 3 duty cycle register in DataSheet */
+ 0xA0, /* PWM 4 duty cycle register in DataSheet */
+ 0xA1, /* PWM 5 duty cycle register in DataSheet */
+};
+
+static const u8 W83791D_REG_TEMP_TARGET[3] = {
+ 0x85, /* PWM 1 target temperature for temp 1 */
+ 0x86, /* PWM 2 target temperature for temp 2 */
+ 0x96, /* PWM 3 target temperature for temp 3 */
+};
+
+static const u8 W83791D_REG_TEMP_TOL[2] = {
+ 0x87, /* PWM 1/2 temperature tolerance */
+ 0x97, /* PWM 3 temperature tolerance */
+};
+
static const u8 W83791D_REG_FAN_CFG[2] = {
0x84, /* FAN 1/2 configuration */
0x95, /* FAN 3 configuration */
@@ -160,6 +180,7 @@ static const u8 W83791D_REG_BEEP_CTRL[3] = {
0xA3, /* BEEP Control Register 3 */
};
+#define W83791D_REG_GPIO 0x15
#define W83791D_REG_CONFIG 0x40
#define W83791D_REG_VID_FANDIV 0x47
#define W83791D_REG_DID_VID4 0x49
@@ -224,6 +245,15 @@ static u8 fan_to_reg(long rpm, int div)
(val) < 0 ? ((val) - 250) / 500 * 128 : \
((val) + 250) / 500 * 128)
+/* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */
+#define TARGET_TEMP_TO_REG(val) ((val) < 0 ? 0 : \
+ (val) >= 127000 ? 127 : \
+ ((val) + 500) / 1000)
+
+/* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
+#define TOL_TEMP_TO_REG(val) ((val) < 0 ? 0 : \
+ (val) >= 15000 ? 15 : \
+ ((val) + 500) / 1000)
#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff)
@@ -275,6 +305,14 @@ struct w83791d_data {
two sensors with three values
(cur, over, hyst) */
+ /* PWMs */
+ u8 pwm[5]; /* pwm duty cycle */
+ u8 pwm_enable[3]; /* pwm enable status for fan 1-3
+ (fan 4-5 only support manual mode) */
+
+ u8 temp_target[3]; /* pwm 1-3 target temperature */
+ u8 temp_tolerance[3]; /* pwm 1-3 temperature tolerance */
+
/* Misc */
u32 alarms; /* realtime status register encoding,combined */
u8 beep_enable; /* Global beep enable */
@@ -652,6 +690,217 @@ static struct sensor_device_attribute sda_fan_alarm[] = {
SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),
};
+/* read/write PWMs */
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83791d_data *data = w83791d_update_device(dev);
+ return sprintf(buf, "%u\n", data->pwm[nr]);
+}
+
+static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83791d_data *data = i2c_get_clientdata(client);
+ int nr = sensor_attr->index;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
+ w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static struct sensor_device_attribute sda_pwm[] = {
+ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO,
+ show_pwm, store_pwm, 0),
+ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO,
+ show_pwm, store_pwm, 1),
+ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO,
+ show_pwm, store_pwm, 2),
+ SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO,
+ show_pwm, store_pwm, 3),
+ SENSOR_ATTR(pwm5, S_IWUSR | S_IRUGO,
+ show_pwm, store_pwm, 4),
+};
+
+static ssize_t show_pwmenable(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83791d_data *data = w83791d_update_device(dev);
+ return sprintf(buf, "%u\n", data->pwm_enable[nr] + 1);
+}
+
+static ssize_t store_pwmenable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83791d_data *data = i2c_get_clientdata(client);
+ int nr = sensor_attr->index;
+ unsigned long val;
+ u8 reg_cfg_tmp;
+ u8 reg_idx = 0;
+ u8 val_shift = 0;
+ u8 keep_mask = 0;
+
+ int ret = strict_strtoul(buf, 10, &val);
+
+ if (ret || val < 1 || val > 3)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->pwm_enable[nr] = val - 1;
+ switch (nr) {
+ case 0:
+ reg_idx = 0;
+ val_shift = 2;
+ keep_mask = 0xf3;
+ break;
+ case 1:
+ reg_idx = 0;
+ val_shift = 4;
+ keep_mask = 0xcf;
+ break;
+ case 2:
+ reg_idx = 1;
+ val_shift = 2;
+ keep_mask = 0xf3;
+ break;
+ }
+
+ reg_cfg_tmp = w83791d_read(client, W83791D_REG_FAN_CFG[reg_idx]);
+ reg_cfg_tmp = (reg_cfg_tmp & keep_mask) |
+ data->pwm_enable[nr] << val_shift;
+
+ w83791d_write(client, W83791D_REG_FAN_CFG[reg_idx], reg_cfg_tmp);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+static struct sensor_device_attribute sda_pwmenable[] = {
+ SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+ show_pwmenable, store_pwmenable, 0),
+ SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+ show_pwmenable, store_pwmenable, 1),
+ SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
+ show_pwmenable, store_pwmenable, 2),
+};
+
+/* For Smart Fan I / Thermal Cruise */
+static ssize_t show_temp_target(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct w83791d_data *data = w83791d_update_device(dev);
+ int nr = sensor_attr->index;
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_target[nr]));
+}
+
+static ssize_t store_temp_target(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83791d_data *data = i2c_get_clientdata(client);
+ int nr = sensor_attr->index;
+ unsigned long val;
+ u8 target_mask;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->temp_target[nr] = TARGET_TEMP_TO_REG(val);
+ target_mask = w83791d_read(client,
+ W83791D_REG_TEMP_TARGET[nr]) & 0x80;
+ w83791d_write(client, W83791D_REG_TEMP_TARGET[nr],
+ data->temp_target[nr] | target_mask);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static struct sensor_device_attribute sda_temp_target[] = {
+ SENSOR_ATTR(temp1_target, S_IWUSR | S_IRUGO,
+ show_temp_target, store_temp_target, 0),
+ SENSOR_ATTR(temp2_target, S_IWUSR | S_IRUGO,
+ show_temp_target, store_temp_target, 1),
+ SENSOR_ATTR(temp3_target, S_IWUSR | S_IRUGO,
+ show_temp_target, store_temp_target, 2),
+};
+
+static ssize_t show_temp_tolerance(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct w83791d_data *data = w83791d_update_device(dev);
+ int nr = sensor_attr->index;
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_tolerance[nr]));
+}
+
+static ssize_t store_temp_tolerance(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83791d_data *data = i2c_get_clientdata(client);
+ int nr = sensor_attr->index;
+ unsigned long val;
+ u8 target_mask;
+ u8 reg_idx = 0;
+ u8 val_shift = 0;
+ u8 keep_mask = 0;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ switch (nr) {
+ case 0:
+ reg_idx = 0;
+ val_shift = 0;
+ keep_mask = 0xf0;
+ break;
+ case 1:
+ reg_idx = 0;
+ val_shift = 4;
+ keep_mask = 0x0f;
+ break;
+ case 2:
+ reg_idx = 1;
+ val_shift = 0;
+ keep_mask = 0xf0;
+ break;
+ }
+
+ mutex_lock(&data->update_lock);
+ data->temp_tolerance[nr] = TOL_TEMP_TO_REG(val);
+ target_mask = w83791d_read(client,
+ W83791D_REG_TEMP_TOL[reg_idx]) & keep_mask;
+ w83791d_write(client, W83791D_REG_TEMP_TOL[reg_idx],
+ (data->temp_tolerance[nr] << val_shift) | target_mask);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static struct sensor_device_attribute sda_temp_tolerance[] = {
+ SENSOR_ATTR(temp1_tolerance, S_IWUSR | S_IRUGO,
+ show_temp_tolerance, store_temp_tolerance, 0),
+ SENSOR_ATTR(temp2_tolerance, S_IWUSR | S_IRUGO,
+ show_temp_tolerance, store_temp_tolerance, 1),
+ SENSOR_ATTR(temp3_tolerance, S_IWUSR | S_IRUGO,
+ show_temp_tolerance, store_temp_tolerance, 2),
+};
+
/* read/write the temperature1, includes measured value and limits */
static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
char *buf)
@@ -908,8 +1157,6 @@ static struct attribute *w83791d_attributes[] = {
FAN_UNIT_ATTRS(0),
FAN_UNIT_ATTRS(1),
FAN_UNIT_ATTRS(2),
- FAN_UNIT_ATTRS(3),
- FAN_UNIT_ATTRS(4),
TEMP_UNIT_ATTRS(0),
TEMP_UNIT_ATTRS(1),
TEMP_UNIT_ATTRS(2),
@@ -918,6 +1165,18 @@ static struct attribute *w83791d_attributes[] = {
&sda_beep_ctrl[1].dev_attr.attr,
&dev_attr_cpu0_vid.attr,
&dev_attr_vrm.attr,
+ &sda_pwm[0].dev_attr.attr,
+ &sda_pwm[1].dev_attr.attr,
+ &sda_pwm[2].dev_attr.attr,
+ &sda_pwmenable[0].dev_attr.attr,
+ &sda_pwmenable[1].dev_attr.attr,
+ &sda_pwmenable[2].dev_attr.attr,
+ &sda_temp_target[0].dev_attr.attr,
+ &sda_temp_target[1].dev_attr.attr,
+ &sda_temp_target[2].dev_attr.attr,
+ &sda_temp_tolerance[0].dev_attr.attr,
+ &sda_temp_tolerance[1].dev_attr.attr,
+ &sda_temp_tolerance[2].dev_attr.attr,
NULL
};
@@ -925,6 +1184,20 @@ static const struct attribute_group w83791d_group = {
.attrs = w83791d_attributes,
};
+/* Separate group of attributes for fan/pwm 4-5. Their pins can also be
+ in use for GPIO in which case their sysfs-interface should not be made
+ available */
+static struct attribute *w83791d_attributes_fanpwm45[] = {
+ FAN_UNIT_ATTRS(3),
+ FAN_UNIT_ATTRS(4),
+ &sda_pwm[3].dev_attr.attr,
+ &sda_pwm[4].dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group w83791d_group_fanpwm45 = {
+ .attrs = w83791d_attributes_fanpwm45,
+};
static int w83791d_detect_subclients(struct i2c_client *client)
{
@@ -1056,6 +1329,7 @@ static int w83791d_probe(struct i2c_client *client,
struct w83791d_data *data;
struct device *dev = &client->dev;
int i, err;
+ u8 has_fanpwm45;
#ifdef DEBUG
int val1;
@@ -1090,15 +1364,27 @@ static int w83791d_probe(struct i2c_client *client,
if ((err = sysfs_create_group(&client->dev.kobj, &w83791d_group)))
goto error3;
+ /* Check if pins of fan/pwm 4-5 are in use as GPIO */
+ has_fanpwm45 = w83791d_read(client, W83791D_REG_GPIO) & 0x10;
+ if (has_fanpwm45) {
+ err = sysfs_create_group(&client->dev.kobj,
+ &w83791d_group_fanpwm45);
+ if (err)
+ goto error4;
+ }
+
/* Everything is ready, now register the working device */
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
- goto error4;
+ goto error5;
}
return 0;
+error5:
+ if (has_fanpwm45)
+ sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45);
error4:
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
error3:
@@ -1236,6 +1522,36 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
for (i = 0; i < 3; i++)
data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
+ /* Update PWM duty cycle */
+ for (i = 0; i < NUMBER_OF_PWM; i++) {
+ data->pwm[i] = w83791d_read(client,
+ W83791D_REG_PWM[i]);
+ }
+
+ /* Update PWM enable status */
+ for (i = 0; i < 2; i++) {
+ reg_array_tmp[i] = w83791d_read(client,
+ W83791D_REG_FAN_CFG[i]);
+ }
+ data->pwm_enable[0] = (reg_array_tmp[0] >> 2) & 0x03;
+ data->pwm_enable[1] = (reg_array_tmp[0] >> 4) & 0x03;
+ data->pwm_enable[2] = (reg_array_tmp[1] >> 2) & 0x03;
+
+ /* Update PWM target temperature */
+ for (i = 0; i < 3; i++) {
+ data->temp_target[i] = w83791d_read(client,
+ W83791D_REG_TEMP_TARGET[i]) & 0x7f;
+ }
+
+ /* Update PWM temperature tolerance */
+ for (i = 0; i < 2; i++) {
+ reg_array_tmp[i] = w83791d_read(client,
+ W83791D_REG_TEMP_TOL[i]);
+ }
+ data->temp_tolerance[0] = reg_array_tmp[0] & 0x0f;
+ data->temp_tolerance[1] = (reg_array_tmp[0] >> 4) & 0x0f;
+ data->temp_tolerance[2] = reg_array_tmp[1] & 0x0f;
+
/* Update the first temperature sensor */
for (i = 0; i < 3; i++) {
data->temp1[i] = w83791d_read(client,
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 6ee997b2817..acadbc51fc0 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -55,7 +55,7 @@ config I2C_AMD756
config I2C_AMD756_S4882
tristate "SMBus multiplexing on the Tyan S4882"
- depends on I2C_AMD756 && EXPERIMENTAL
+ depends on I2C_AMD756 && X86 && EXPERIMENTAL
help
Enabling this option will add specific SMBus support for the Tyan
S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed
@@ -148,7 +148,7 @@ config I2C_NFORCE2
config I2C_NFORCE2_S4985
tristate "SMBus multiplexing on the Tyan S4985"
- depends on I2C_NFORCE2 && EXPERIMENTAL
+ depends on I2C_NFORCE2 && X86 && EXPERIMENTAL
help
Enabling this option will add specific SMBus support for the Tyan
S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed
@@ -209,7 +209,7 @@ config I2C_VIA
will be called i2c-via.
config I2C_VIAPRO
- tristate "VIA VT82C596/82C686/82xx and CX700"
+ tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820"
depends on PCI
help
If you say yes to this option, support will be included for the VIA
@@ -223,6 +223,8 @@ config I2C_VIAPRO
VT8237R/A/S
VT8251
CX700
+ VX800
+ VX820
This driver can also be built as a module. If so, the module
will be called i2c-viapro.
@@ -330,6 +332,18 @@ config I2C_GPIO
This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines.
+config I2C_HIGHLANDER
+ tristate "Highlander FPGA SMBus interface"
+ depends on SH_HIGHLANDER
+ help
+ If you say yes to this option, support will be included for
+ the SMBus interface located in the FPGA on various Highlander
+ boards, particularly the R0P7780LC0011RL and R0P7785LC0011RL
+ FPGAs. This is wholly unrelated to the SoC I2C.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-highlander.
+
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
depends on 4xx
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 97dbfa2107f..0c2c4b26cdf 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
+obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
new file mode 100644
index 00000000000..f4d22ae9d29
--- /dev/null
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -0,0 +1,498 @@
+/*
+ * Renesas Solutions Highlander FPGA I2C/SMBus support.
+ *
+ * Supported devices: R0P7780LC0011RL, R0P7785LC0011RL
+ *
+ * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Copyright (C) 2008 Atom Create Engineering Co., Ltd.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License version 2. See the file "COPYING" in the main directory
+ * of this archive for more details.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define SMCR 0x00
+#define SMCR_START (1 << 0)
+#define SMCR_IRIC (1 << 1)
+#define SMCR_BBSY (1 << 2)
+#define SMCR_ACKE (1 << 3)
+#define SMCR_RST (1 << 4)
+#define SMCR_IEIC (1 << 6)
+
+#define SMSMADR 0x02
+
+#define SMMR 0x04
+#define SMMR_MODE0 (1 << 0)
+#define SMMR_MODE1 (1 << 1)
+#define SMMR_CAP (1 << 3)
+#define SMMR_TMMD (1 << 4)
+#define SMMR_SP (1 << 7)
+
+#define SMSADR 0x06
+#define SMTRDR 0x46
+
+struct highlander_i2c_dev {
+ struct device *dev;
+ void __iomem *base;
+ struct i2c_adapter adapter;
+ struct completion cmd_complete;
+ unsigned long last_read_time;
+ int irq;
+ u8 *buf;
+ size_t buf_len;
+};
+
+static int iic_force_poll, iic_force_normal;
+static int iic_timeout = 1000, iic_read_delay;
+
+static inline void highlander_i2c_irq_enable(struct highlander_i2c_dev *dev)
+{
+ iowrite16(ioread16(dev->base + SMCR) | SMCR_IEIC, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_irq_disable(struct highlander_i2c_dev *dev)
+{
+ iowrite16(ioread16(dev->base + SMCR) & ~SMCR_IEIC, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_start(struct highlander_i2c_dev *dev)
+{
+ iowrite16(ioread16(dev->base + SMCR) | SMCR_START, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_done(struct highlander_i2c_dev *dev)
+{
+ iowrite16(ioread16(dev->base + SMCR) | SMCR_IRIC, dev->base + SMCR);
+}
+
+static void highlander_i2c_setup(struct highlander_i2c_dev *dev)
+{
+ u16 smmr;
+
+ smmr = ioread16(dev->base + SMMR);
+ smmr |= SMMR_TMMD;
+
+ if (iic_force_normal)
+ smmr &= ~SMMR_SP;
+ else
+ smmr |= SMMR_SP;
+
+ iowrite16(smmr, dev->base + SMMR);
+}
+
+static void smbus_write_data(u8 *src, u16 *dst, int len)
+{
+ for (; len > 1; len -= 2) {
+ *dst++ = be16_to_cpup((u16 *)src);
+ src += 2;
+ }
+
+ if (len)
+ *dst = *src << 8;
+}
+
+static void smbus_read_data(u16 *src, u8 *dst, int len)
+{
+ for (; len > 1; len -= 2) {
+ *(u16 *)dst = cpu_to_be16p(src++);
+ dst += 2;
+ }
+
+ if (len)
+ *dst = *src >> 8;
+}
+
+static void highlander_i2c_command(struct highlander_i2c_dev *dev,
+ u8 command, int len)
+{
+ unsigned int i;
+ u16 cmd = (command << 8) | command;
+
+ for (i = 0; i < len; i += 2) {
+ if (len - i == 1)
+ cmd = command << 8;
+ iowrite16(cmd, dev->base + SMSADR + i);
+ dev_dbg(dev->dev, "command data[%x] 0x%04x\n", i/2, cmd);
+ }
+}
+
+static int highlander_i2c_wait_for_bbsy(struct highlander_i2c_dev *dev)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(iic_timeout);
+ while (ioread16(dev->base + SMCR) & SMCR_BBSY) {
+ if (time_after(jiffies, timeout)) {
+ dev_warn(dev->dev, "timeout waiting for bus ready\n");
+ return -ETIMEDOUT;
+ }
+
+ msleep(1);
+ }
+
+ return 0;
+}
+
+static int highlander_i2c_reset(struct highlander_i2c_dev *dev)
+{
+ iowrite16(ioread16(dev->base + SMCR) | SMCR_RST, dev->base + SMCR);
+ return highlander_i2c_wait_for_bbsy(dev);
+}
+
+static int highlander_i2c_wait_for_ack(struct highlander_i2c_dev *dev)
+{
+ u16 tmp = ioread16(dev->base + SMCR);
+
+ if ((tmp & (SMCR_IRIC | SMCR_ACKE)) == SMCR_ACKE) {
+ dev_warn(dev->dev, "ack abnormality\n");
+ return highlander_i2c_reset(dev);
+ }
+
+ return 0;
+}
+
+static irqreturn_t highlander_i2c_irq(int irq, void *dev_id)
+{
+ struct highlander_i2c_dev *dev = dev_id;
+
+ highlander_i2c_done(dev);
+ complete(&dev->cmd_complete);
+
+ return IRQ_HANDLED;
+}
+
+static void highlander_i2c_poll(struct highlander_i2c_dev *dev)
+{
+ unsigned long timeout;
+ u16 smcr;
+
+ timeout = jiffies + msecs_to_jiffies(iic_timeout);
+ for (;;) {
+ smcr = ioread16(dev->base + SMCR);
+
+ /*
+ * Don't bother checking ACKE here, this and the reset
+ * are handled in highlander_i2c_wait_xfer_done() when
+ * waiting for the ACK.
+ */
+
+ if (smcr & SMCR_IRIC)
+ return;
+ if (time_after(jiffies, timeout))
+ break;
+
+ cpu_relax();
+ cond_resched();
+ }
+
+ dev_err(dev->dev, "polling timed out\n");
+}
+
+static inline int highlander_i2c_wait_xfer_done(struct highlander_i2c_dev *dev)
+{
+ if (dev->irq)
+ wait_for_completion_timeout(&dev->cmd_complete,
+ msecs_to_jiffies(iic_timeout));
+ else
+ /* busy looping, the IRQ of champions */
+ highlander_i2c_poll(dev);
+
+ return highlander_i2c_wait_for_ack(dev);
+}
+
+static int highlander_i2c_read(struct highlander_i2c_dev *dev)
+{
+ int i, cnt;
+ u16 data[16];
+
+ if (highlander_i2c_wait_for_bbsy(dev))
+ return -EAGAIN;
+
+ highlander_i2c_start(dev);
+
+ if (highlander_i2c_wait_xfer_done(dev)) {
+ dev_err(dev->dev, "Arbitration loss\n");
+ return -EAGAIN;
+ }
+
+ /*
+ * The R0P7780LC0011RL FPGA needs a significant delay between
+ * data read cycles, otherwise the transciever gets confused and
+ * garbage is returned when the read is subsequently aborted.
+ *
+ * It is not sufficient to wait for BBSY.
+ *
+ * While this generally only applies to the older SH7780-based
+ * Highlanders, the same issue can be observed on SH7785 ones,
+ * albeit less frequently. SH7780-based Highlanders may need
+ * this to be as high as 1000 ms.
+ */
+ if (iic_read_delay && time_before(jiffies, dev->last_read_time +
+ msecs_to_jiffies(iic_read_delay)))
+ msleep(jiffies_to_msecs((dev->last_read_time +
+ msecs_to_jiffies(iic_read_delay)) - jiffies));
+
+ cnt = (dev->buf_len + 1) >> 1;
+ for (i = 0; i < cnt; i++) {
+ data[i] = ioread16(dev->base + SMTRDR + (i * sizeof(u16)));
+ dev_dbg(dev->dev, "read data[%x] 0x%04x\n", i, data[i]);
+ }
+
+ smbus_read_data(data, dev->buf, dev->buf_len);
+
+ dev->last_read_time = jiffies;
+
+ return 0;
+}
+
+static int highlander_i2c_write(struct highlander_i2c_dev *dev)
+{
+ int i, cnt;
+ u16 data[16];
+
+ smbus_write_data(dev->buf, data, dev->buf_len);
+
+ cnt = (dev->buf_len + 1) >> 1;
+ for (i = 0; i < cnt; i++) {
+ iowrite16(data[i], dev->base + SMTRDR + (i * sizeof(u16)));
+ dev_dbg(dev->dev, "write data[%x] 0x%04x\n", i, data[i]);
+ }
+
+ if (highlander_i2c_wait_for_bbsy(dev))
+ return -EAGAIN;
+
+ highlander_i2c_start(dev);
+
+ return highlander_i2c_wait_xfer_done(dev);
+}
+
+static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size,
+ union i2c_smbus_data *data)
+{
+ struct highlander_i2c_dev *dev = i2c_get_adapdata(adap);
+ int read = read_write & I2C_SMBUS_READ;
+ u16 tmp;
+
+ init_completion(&dev->cmd_complete);
+
+ dev_dbg(dev->dev, "addr %04x, command %02x, read_write %d, size %d\n",
+ addr, command, read_write, size);
+
+ /*
+ * Set up the buffer and transfer size
+ */
+ switch (size) {
+ case I2C_SMBUS_BYTE_DATA:
+ dev->buf = &data->byte;
+ dev->buf_len = 1;
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ dev->buf = &data->block[1];
+ dev->buf_len = data->block[0];
+ break;
+ default:
+ dev_err(dev->dev, "unsupported command %d\n", size);
+ return -EINVAL;
+ }
+
+ /*
+ * Encode the mode setting
+ */
+ tmp = ioread16(dev->base + SMMR);
+ tmp &= ~(SMMR_MODE0 | SMMR_MODE1);
+
+ switch (dev->buf_len) {
+ case 1:
+ /* default */
+ break;
+ case 8:
+ tmp |= SMMR_MODE0;
+ break;
+ case 16:
+ tmp |= SMMR_MODE1;
+ break;
+ case 32:
+ tmp |= (SMMR_MODE0 | SMMR_MODE1);
+ break;
+ default:
+ dev_err(dev->dev, "unsupported xfer size %d\n", dev->buf_len);
+ return -EINVAL;
+ }
+
+ iowrite16(tmp, dev->base + SMMR);
+
+ /* Ensure we're in a sane state */
+ highlander_i2c_done(dev);
+
+ /* Set slave address */
+ iowrite16((addr << 1) | read, dev->base + SMSMADR);
+
+ highlander_i2c_command(dev, command, dev->buf_len);
+
+ if (read)
+ return highlander_i2c_read(dev);
+ else
+ return highlander_i2c_write(dev);
+}
+
+static u32 highlander_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm highlander_i2c_algo = {
+ .smbus_xfer = highlander_i2c_smbus_xfer,
+ .functionality = highlander_i2c_func,
+};
+
+static int __devinit highlander_i2c_probe(struct platform_device *pdev)
+{
+ struct highlander_i2c_dev *dev;
+ struct i2c_adapter *adap;
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "no mem resource\n");
+ return -ENODEV;
+ }
+
+ dev = kzalloc(sizeof(struct highlander_i2c_dev), GFP_KERNEL);
+ if (unlikely(!dev))
+ return -ENOMEM;
+
+ dev->base = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (unlikely(!dev->base)) {
+ ret = -ENXIO;
+ goto err;
+ }
+
+ dev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, dev);
+
+ dev->irq = platform_get_irq(pdev, 0);
+ if (iic_force_poll)
+ dev->irq = 0;
+
+ if (dev->irq) {
+ ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+ pdev->name, dev);
+ if (unlikely(ret))
+ goto err_unmap;
+
+ highlander_i2c_irq_enable(dev);
+ } else {
+ dev_notice(&pdev->dev, "no IRQ, using polling mode\n");
+ highlander_i2c_irq_disable(dev);
+ }
+
+ dev->last_read_time = jiffies; /* initial read jiffies */
+
+ highlander_i2c_setup(dev);
+
+ adap = &dev->adapter;
+ i2c_set_adapdata(adap, dev);
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON;
+ strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name));
+ adap->algo = &highlander_i2c_algo;
+ adap->dev.parent = &pdev->dev;
+ adap->nr = pdev->id;
+
+ /*
+ * Reset the adapter
+ */
+ ret = highlander_i2c_reset(dev);
+ if (unlikely(ret)) {
+ dev_err(&pdev->dev, "controller didn't come up\n");
+ goto err_free_irq;
+ }
+
+ ret = i2c_add_numbered_adapter(adap);
+ if (unlikely(ret)) {
+ dev_err(&pdev->dev, "failure adding adapter\n");
+ goto err_free_irq;
+ }
+
+ return 0;
+
+err_free_irq:
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+err_unmap:
+ iounmap(dev->base);
+err:
+ kfree(dev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int __devexit highlander_i2c_remove(struct platform_device *pdev)
+{
+ struct highlander_i2c_dev *dev = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&dev->adapter);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ iounmap(dev->base);
+ kfree(dev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver highlander_i2c_driver = {
+ .driver = {
+ .name = "i2c-highlander",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = highlander_i2c_probe,
+ .remove = __devexit_p(highlander_i2c_remove),
+};
+
+static int __init highlander_i2c_init(void)
+{
+ return platform_driver_register(&highlander_i2c_driver);
+}
+
+static void __exit highlander_i2c_exit(void)
+{
+ platform_driver_unregister(&highlander_i2c_driver);
+}
+
+module_init(highlander_i2c_init);
+module_exit(highlander_i2c_exit);
+
+MODULE_AUTHOR("Paul Mundt");
+MODULE_DESCRIPTION("Renesas Highlander FPGA I2C/SMBus adapter");
+MODULE_LICENSE("GPL v2");
+
+module_param(iic_force_poll, bool, 0);
+module_param(iic_force_normal, bool, 0);
+module_param(iic_timeout, int, 0);
+module_param(iic_read_delay, int, 0);
+
+MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
+MODULE_PARM_DESC(iic_force_normal,
+ "Force normal mode (100 kHz), default is fast mode (400 kHz)");
+MODULE_PARM_DESC(iic_timeout, "Set timeout value in msecs (default 1000 ms)");
+MODULE_PARM_DESC(iic_read_delay,
+ "Delay between data read cycles (default 0 ms)");
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 27443f073bc..a9a45fcc854 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -312,7 +312,6 @@ static struct i2c_adapter mpc_ops = {
.name = "MPC adapter",
.id = I2C_HW_MPC107,
.algo = &mpc_algo,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.timeout = 1,
};
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index e7eb7bf9dde..608038d64f8 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -589,11 +589,16 @@ omap_i2c_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->irq = irq->start;
- dev->base = (void __iomem *) IO_ADDRESS(mem->start);
+ dev->base = ioremap(mem->start, mem->end - mem->start + 1);
+ if (!dev->base) {
+ r = -ENOMEM;
+ goto err_free_mem;
+ }
+
platform_set_drvdata(pdev, dev);
if ((r = omap_i2c_get_clocks(dev)) != 0)
- goto err_free_mem;
+ goto err_iounmap;
omap_i2c_unidle(dev);
@@ -640,6 +645,8 @@ err_unuse_clocks:
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_idle(dev);
omap_i2c_put_clocks(dev);
+err_iounmap:
+ iounmap(dev->base);
err_free_mem:
platform_set_drvdata(pdev, NULL);
kfree(dev);
@@ -661,6 +668,7 @@ omap_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_put_clocks(dev);
+ iounmap(dev->base);
kfree(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, (mem->end - mem->start) + 1);
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index c6faf9bdad1..b2b8380f660 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -123,11 +123,6 @@ static struct i2c_adapter parport_adapter = {
static int __devinit i2c_parport_probe(struct platform_device *pdev)
{
int err;
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
- return -EBUSY;
/* Reset hardware to a sane state (SCL and SDA high) */
parport_setsda(NULL, 1);
@@ -138,29 +133,19 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev)
parport_adapter.dev.parent = &pdev->dev;
err = i2c_bit_add_bus(&parport_adapter);
- if (err) {
+ if (err)
dev_err(&pdev->dev, "Unable to register with I2C\n");
- goto exit_region;
- }
- return 0;
-
-exit_region:
- release_region(res->start, res->end - res->start + 1);
return err;
}
static int __devexit i2c_parport_remove(struct platform_device *pdev)
{
- struct resource *res;
-
i2c_del_adapter(&parport_adapter);
/* Un-init if needed (power off...) */
if (adapter_parm[type].init.val)
line_set(0, &adapter_parm[type].init);
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- release_region(res->start, res->end - res->start + 1);
return 0;
}
@@ -175,12 +160,6 @@ static struct platform_driver i2c_parport_driver = {
static int __init i2c_parport_device_add(u16 address)
{
- struct resource res = {
- .start = address,
- .end = address + 2,
- .name = DRVNAME,
- .flags = IORESOURCE_IO,
- };
int err;
pdev = platform_device_alloc(DRVNAME, -1);
@@ -190,13 +169,6 @@ static int __init i2c_parport_device_add(u16 address)
goto exit;
}
- err = platform_device_add_resources(pdev, &res, 1);
- if (err) {
- printk(KERN_ERR DRVNAME ": Device resource addition failed "
- "(%d)\n", err);
- goto exit_device_put;
- }
-
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
@@ -231,13 +203,16 @@ static int __init i2c_parport_init(void)
base = DEFAULT_BASE;
}
+ if (!request_region(base, 3, DRVNAME))
+ return -EBUSY;
+
if (!adapter_parm[type].getscl.val)
parport_algo_data.getscl = NULL;
/* Sets global pdev as a side effect */
err = i2c_parport_device_add(base);
if (err)
- goto exit;
+ goto exit_release;
err = platform_driver_register(&i2c_parport_driver);
if (err)
@@ -247,7 +222,8 @@ static int __init i2c_parport_init(void)
exit_device:
platform_device_unregister(pdev);
-exit:
+exit_release:
+ release_region(base, 3);
return err;
}
@@ -255,6 +231,7 @@ static void __exit i2c_parport_exit(void)
{
platform_driver_unregister(&i2c_parport_driver);
platform_device_unregister(pdev);
+ release_region(base, 3);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index a119784bae1..9eb76268ec7 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -36,8 +36,8 @@
#define DRIVER "i2c-pca-isa"
#define IO_SIZE 4
-static unsigned long base = 0x330;
-static int irq = 10;
+static unsigned long base;
+static int irq = -1;
/* Data sheet recommends 59kHz for 100kHz operation due to variation
* in the actual clock rate */
@@ -107,13 +107,26 @@ static struct i2c_adapter pca_isa_ops = {
.timeout = 100,
};
+static int __devinit pca_isa_match(struct device *dev, unsigned int id)
+{
+ int match = base != 0;
+
+ if (match) {
+ if (irq <= -1)
+ dev_warn(dev, "Using polling mode (specify irq)\n");
+ } else
+ dev_err(dev, "Please specify I/O base\n");
+
+ return match;
+}
+
static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
{
init_waitqueue_head(&pca_wait);
dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
if (check_legacy_ioport(base)) {
dev_err(dev, "I/O address %#08lx is not available\n", base);
goto out;
@@ -153,7 +166,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
{
i2c_del_adapter(&pca_isa_ops);
- if (irq > 0) {
+ if (irq > -1) {
disable_irq(irq);
free_irq(irq, &pca_isa_ops);
}
@@ -163,6 +176,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
}
static struct isa_driver pca_isa_driver = {
+ .match = pca_isa_match,
.probe = pca_isa_probe,
.remove = __devexit_p(pca_isa_remove),
.driver = {
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 22f6d5c00d8..60ca91745e5 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -180,7 +180,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
};
-static int i2c_powermac_remove(struct platform_device *dev)
+static int __devexit i2c_powermac_remove(struct platform_device *dev)
{
struct i2c_adapter *adapter = platform_get_drvdata(dev);
struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter);
@@ -200,7 +200,7 @@ static int i2c_powermac_remove(struct platform_device *dev)
}
-static int __devexit i2c_powermac_probe(struct platform_device *dev)
+static int __devinit i2c_powermac_probe(struct platform_device *dev)
{
struct pmac_i2c_bus *bus = dev->dev.platform_data;
struct device_node *parent = NULL;
@@ -259,6 +259,35 @@ static int __devexit i2c_powermac_probe(struct platform_device *dev)
}
printk(KERN_INFO "PowerMac i2c bus %s registered\n", name);
+
+ if (!strncmp(basename, "uni-n", 5)) {
+ struct device_node *np;
+ const u32 *prop;
+ struct i2c_board_info info;
+
+ /* Instantiate I2C motion sensor if present */
+ np = of_find_node_by_name(NULL, "accelerometer");
+ if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") &&
+ (prop = of_get_property(np, "reg", NULL))) {
+ int i2c_bus;
+ const char *tmp_bus;
+
+ /* look for bus either using "reg" or by path */
+ tmp_bus = strstr(np->full_name, "/i2c-bus@");
+ if (tmp_bus)
+ i2c_bus = *(tmp_bus + 9) - '0';
+ else
+ i2c_bus = ((*prop) >> 8) & 0x0f;
+
+ if (pmac_i2c_get_channel(bus) == i2c_bus) {
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = ((*prop) & 0xff) >> 1;
+ strlcpy(info.type, "ams", I2C_NAME_SIZE);
+ i2c_new_device(adapter, &info);
+ }
+ }
+ }
+
return rc;
}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 44d838410f1..906f9b9d715 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -38,7 +38,44 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/i2c.h>
-#include <mach/pxa-regs.h>
+
+/*
+ * I2C registers and bit definitions
+ */
+#define IBMR (0x00)
+#define IDBR (0x08)
+#define ICR (0x10)
+#define ISR (0x18)
+#define ISAR (0x20)
+
+#define ICR_START (1 << 0) /* start bit */
+#define ICR_STOP (1 << 1) /* stop bit */
+#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */
+#define ICR_TB (1 << 3) /* transfer byte bit */
+#define ICR_MA (1 << 4) /* master abort */
+#define ICR_SCLE (1 << 5) /* master clock enable */
+#define ICR_IUE (1 << 6) /* unit enable */
+#define ICR_GCD (1 << 7) /* general call disable */
+#define ICR_ITEIE (1 << 8) /* enable tx interrupts */
+#define ICR_IRFIE (1 << 9) /* enable rx interrupts */
+#define ICR_BEIE (1 << 10) /* enable bus error ints */
+#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */
+#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */
+#define ICR_SADIE (1 << 13) /* slave address detected int enable */
+#define ICR_UR (1 << 14) /* unit reset */
+#define ICR_FM (1 << 15) /* fast mode */
+
+#define ISR_RWM (1 << 0) /* read/write mode */
+#define ISR_ACKNAK (1 << 1) /* ack/nak status */
+#define ISR_UB (1 << 2) /* unit busy */
+#define ISR_IBB (1 << 3) /* bus busy */
+#define ISR_SSD (1 << 4) /* slave stop detected */
+#define ISR_ALD (1 << 5) /* arbitration loss detected */
+#define ISR_ITE (1 << 6) /* tx buffer empty */
+#define ISR_IRF (1 << 7) /* rx buffer full */
+#define ISR_GCAD (1 << 8) /* general call address detected */
+#define ISR_SAD (1 << 9) /* slave address detected */
+#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
struct pxa_i2c {
spinlock_t lock;
@@ -60,19 +97,21 @@ struct pxa_i2c {
u32 icrlog[32];
void __iomem *reg_base;
+ unsigned int reg_shift;
unsigned long iobase;
unsigned long iosize;
int irq;
- int use_pio;
+ unsigned int use_pio :1;
+ unsigned int fast_mode :1;
};
-#define _IBMR(i2c) ((i2c)->reg_base + 0)
-#define _IDBR(i2c) ((i2c)->reg_base + 8)
-#define _ICR(i2c) ((i2c)->reg_base + 0x10)
-#define _ISR(i2c) ((i2c)->reg_base + 0x18)
-#define _ISAR(i2c) ((i2c)->reg_base + 0x20)
+#define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift))
+#define _IDBR(i2c) ((i2c)->reg_base + (0x4 << (i2c)->reg_shift))
+#define _ICR(i2c) ((i2c)->reg_base + (0x8 << (i2c)->reg_shift))
+#define _ISR(i2c) ((i2c)->reg_base + (0xc << (i2c)->reg_shift))
+#define _ISAR(i2c) ((i2c)->reg_base + (0x10 << (i2c)->reg_shift))
/*
* I2C Slave mode address
@@ -188,14 +227,14 @@ static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
static void i2c_pxa_abort(struct pxa_i2c *i2c)
{
- unsigned long timeout = jiffies + HZ/4;
+ int i = 250;
if (i2c_pxa_is_slavemode(i2c)) {
dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__);
return;
}
- while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) {
+ while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) {
unsigned long icr = readl(_ICR(i2c));
icr &= ~ICR_START;
@@ -205,7 +244,8 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c)
show_state(i2c);
- msleep(1);
+ mdelay(1);
+ i --;
}
writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
@@ -364,7 +404,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
- writel(I2C_ICR_INIT, _ICR(i2c));
+ writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
#ifdef CONFIG_I2C_PXA_SLAVE
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -907,12 +947,6 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
struct pxa_i2c *i2c = adap->algo_data;
int ret, i;
- /* If the I2C controller is disabled we need to reset it (probably due
- to a suspend/resume destroying state). We do this here as we can then
- avoid worrying about resuming the controller before its users. */
- if (!(readl(_ICR(i2c)) & ICR_IUE))
- i2c_pxa_reset(i2c);
-
for (i = adap->retries; i >= 0; i--) {
ret = i2c_pxa_do_xfer(i2c, msgs, num);
if (ret != I2C_RETRY)
@@ -993,6 +1027,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
ret = -EIO;
goto eremap;
}
+ i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1;
i2c->iobase = res->start;
i2c->iosize = res_len(res);
@@ -1013,6 +1048,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
if (plat) {
i2c->adap.class = plat->class;
i2c->use_pio = plat->use_pio;
+ i2c->fast_mode = plat->fast_mode;
}
if (i2c->use_pio) {
@@ -1082,9 +1118,33 @@ static int __exit i2c_pxa_remove(struct platform_device *dev)
return 0;
}
+#ifdef CONFIG_PM
+static int i2c_pxa_suspend_late(struct platform_device *dev, pm_message_t state)
+{
+ struct pxa_i2c *i2c = platform_get_drvdata(dev);
+ clk_disable(i2c->clk);
+ return 0;
+}
+
+static int i2c_pxa_resume_early(struct platform_device *dev)
+{
+ struct pxa_i2c *i2c = platform_get_drvdata(dev);
+
+ clk_enable(i2c->clk);
+ i2c_pxa_reset(i2c);
+
+ return 0;
+}
+#else
+#define i2c_pxa_suspend_late NULL
+#define i2c_pxa_resume_early NULL
+#endif
+
static struct platform_driver i2c_pxa_driver = {
.probe = i2c_pxa_probe,
.remove = __exit_p(i2c_pxa_remove),
+ .suspend_late = i2c_pxa_suspend_late,
+ .resume_early = i2c_pxa_resume_early,
.driver = {
.name = "pxa2xx-i2c",
.owner = THIS_MODULE,
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 840e634fa31..640cbb23732 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -31,13 +31,84 @@
#include <linux/clk.h>
#include <linux/io.h>
+/* Transmit operation: */
+/* */
+/* 0 byte transmit */
+/* BUS: S A8 ACK P */
+/* IRQ: DTE WAIT */
+/* ICIC: */
+/* ICCR: 0x94 0x90 */
+/* ICDR: A8 */
+/* */
+/* 1 byte transmit */
+/* BUS: S A8 ACK D8(1) ACK P */
+/* IRQ: DTE WAIT WAIT */
+/* ICIC: -DTE */
+/* ICCR: 0x94 0x90 */
+/* ICDR: A8 D8(1) */
+/* */
+/* 2 byte transmit */
+/* BUS: S A8 ACK D8(1) ACK D8(2) ACK P */
+/* IRQ: DTE WAIT WAIT WAIT */
+/* ICIC: -DTE */
+/* ICCR: 0x94 0x90 */
+/* ICDR: A8 D8(1) D8(2) */
+/* */
+/* 3 bytes or more, +---------+ gets repeated */
+/* */
+/* */
+/* Receive operation: */
+/* */
+/* 0 byte receive - not supported since slave may hold SDA low */
+/* */
+/* 1 byte receive [TX] | [RX] */
+/* BUS: S A8 ACK | D8(1) ACK P */
+/* IRQ: DTE WAIT | WAIT DTE */
+/* ICIC: -DTE | +DTE */
+/* ICCR: 0x94 0x81 | 0xc0 */
+/* ICDR: A8 | D8(1) */
+/* */
+/* 2 byte receive [TX]| [RX] */
+/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK P */
+/* IRQ: DTE WAIT | WAIT WAIT DTE */
+/* ICIC: -DTE | +DTE */
+/* ICCR: 0x94 0x81 | 0xc0 */
+/* ICDR: A8 | D8(1) D8(2) */
+/* */
+/* 3 byte receive [TX] | [RX] */
+/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK D8(3) ACK P */
+/* IRQ: DTE WAIT | WAIT WAIT WAIT DTE */
+/* ICIC: -DTE | +DTE */
+/* ICCR: 0x94 0x81 | 0xc0 */
+/* ICDR: A8 | D8(1) D8(2) D8(3) */
+/* */
+/* 4 bytes or more, this part is repeated +---------+ */
+/* */
+/* */
+/* Interrupt order and BUSY flag */
+/* ___ _ */
+/* SDA ___\___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAA___/ */
+/* SCL \_/1\_/2\_/3\_/4\_/5\_/6\_/7\_/8\___/9\_____/ */
+/* */
+/* S D7 D6 D5 D4 D3 D2 D1 D0 P */
+/* ___ */
+/* WAIT IRQ ________________________________/ \___________ */
+/* TACK IRQ ____________________________________/ \_______ */
+/* DTE IRQ __________________________________________/ \_ */
+/* AL IRQ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+/* _______________________________________________ */
+/* BUSY __/ \_ */
+/* */
+
enum sh_mobile_i2c_op {
OP_START = 0,
- OP_TX_ONLY,
+ OP_TX_FIRST,
+ OP_TX,
OP_TX_STOP,
OP_TX_TO_RX,
- OP_RX_ONLY,
+ OP_RX,
OP_RX_STOP,
+ OP_RX_STOP_DATA,
};
struct sh_mobile_i2c_data {
@@ -127,25 +198,34 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
spin_lock_irqsave(&pd->lock, flags);
switch (op) {
- case OP_START:
+ case OP_START: /* issue start and trigger DTE interrupt */
iowrite8(0x94, ICCR(pd));
break;
- case OP_TX_ONLY:
+ case OP_TX_FIRST: /* disable DTE interrupt and write data */
+ iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd));
iowrite8(data, ICDR(pd));
break;
- case OP_TX_STOP:
+ case OP_TX: /* write data */
iowrite8(data, ICDR(pd));
- iowrite8(0x90, ICCR(pd));
- iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
break;
- case OP_TX_TO_RX:
+ case OP_TX_STOP: /* write data and issue a stop afterwards */
iowrite8(data, ICDR(pd));
+ iowrite8(0x90, ICCR(pd));
+ break;
+ case OP_TX_TO_RX: /* select read mode */
iowrite8(0x81, ICCR(pd));
break;
- case OP_RX_ONLY:
+ case OP_RX: /* just read data */
ret = ioread8(ICDR(pd));
break;
- case OP_RX_STOP:
+ case OP_RX_STOP: /* enable DTE interrupt, issue stop */
+ iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
+ ICIC(pd));
+ iowrite8(0xc0, ICCR(pd));
+ break;
+ case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
+ iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
+ ICIC(pd));
ret = ioread8(ICDR(pd));
iowrite8(0xc0, ICCR(pd));
break;
@@ -157,58 +237,120 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
return ret;
}
+static int sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd)
+{
+ if (pd->pos == -1)
+ return 1;
+
+ return 0;
+}
+
+static int sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd)
+{
+ if (pd->pos == (pd->msg->len - 1))
+ return 1;
+
+ return 0;
+}
+
+static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd,
+ unsigned char *buf)
+{
+ switch (pd->pos) {
+ case -1:
+ *buf = (pd->msg->addr & 0x7f) << 1;
+ *buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0;
+ break;
+ default:
+ *buf = pd->msg->buf[pd->pos];
+ }
+}
+
+static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd)
+{
+ unsigned char data;
+
+ if (pd->pos == pd->msg->len)
+ return 1;
+
+ sh_mobile_i2c_get_data(pd, &data);
+
+ if (sh_mobile_i2c_is_last_byte(pd))
+ i2c_op(pd, OP_TX_STOP, data);
+ else if (sh_mobile_i2c_is_first_byte(pd))
+ i2c_op(pd, OP_TX_FIRST, data);
+ else
+ i2c_op(pd, OP_TX, data);
+
+ pd->pos++;
+ return 0;
+}
+
+static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
+{
+ unsigned char data;
+ int real_pos;
+
+ do {
+ if (pd->pos <= -1) {
+ sh_mobile_i2c_get_data(pd, &data);
+
+ if (sh_mobile_i2c_is_first_byte(pd))
+ i2c_op(pd, OP_TX_FIRST, data);
+ else
+ i2c_op(pd, OP_TX, data);
+ break;
+ }
+
+ if (pd->pos == 0) {
+ i2c_op(pd, OP_TX_TO_RX, 0);
+ break;
+ }
+
+ real_pos = pd->pos - 2;
+
+ if (pd->pos == pd->msg->len) {
+ if (real_pos < 0) {
+ i2c_op(pd, OP_RX_STOP, 0);
+ break;
+ }
+ data = i2c_op(pd, OP_RX_STOP_DATA, 0);
+ } else
+ data = i2c_op(pd, OP_RX, 0);
+
+ pd->msg->buf[real_pos] = data;
+ } while (0);
+
+ pd->pos++;
+ return pd->pos == (pd->msg->len + 2);
+}
+
static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
{
struct platform_device *dev = dev_id;
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
- struct i2c_msg *msg = pd->msg;
- unsigned char data, sr;
- int wakeup = 0;
+ unsigned char sr;
+ int wakeup;
sr = ioread8(ICSR(pd));
- pd->sr |= sr;
+ pd->sr |= sr; /* remember state */
dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
- (msg->flags & I2C_M_RD) ? "read" : "write",
- pd->pos, msg->len);
+ (pd->msg->flags & I2C_M_RD) ? "read" : "write",
+ pd->pos, pd->msg->len);
if (sr & (ICSR_AL | ICSR_TACK)) {
- iowrite8(0, ICIC(pd)); /* disable interrupts */
- wakeup = 1;
- goto do_wakeup;
- }
+ /* don't interrupt transaction - continue to issue stop */
+ iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd));
+ wakeup = 0;
+ } else if (pd->msg->flags & I2C_M_RD)
+ wakeup = sh_mobile_i2c_isr_rx(pd);
+ else
+ wakeup = sh_mobile_i2c_isr_tx(pd);
- if (pd->pos == msg->len) {
- i2c_op(pd, OP_RX_ONLY, 0);
- wakeup = 1;
- goto do_wakeup;
- }
+ if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */
+ iowrite8(sr & ~ICSR_WAIT, ICSR(pd));
- if (pd->pos == -1) {
- data = (msg->addr & 0x7f) << 1;
- data |= (msg->flags & I2C_M_RD) ? 1 : 0;
- } else
- data = msg->buf[pd->pos];
-
- if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
- if (msg->flags & I2C_M_RD)
- i2c_op(pd, OP_TX_TO_RX, data);
- else if (pd->pos == (msg->len - 1)) {
- i2c_op(pd, OP_TX_STOP, data);
- wakeup = 1;
- } else
- i2c_op(pd, OP_TX_ONLY, data);
- } else {
- if (pd->pos == (msg->len - 1))
- data = i2c_op(pd, OP_RX_STOP, 0);
- else
- data = i2c_op(pd, OP_RX_ONLY, 0);
-
- msg->buf[pd->pos] = data;
- }
- pd->pos++;
-
- do_wakeup:
if (wakeup) {
pd->sr |= SW_DONE;
wake_up(&pd->wait);
@@ -219,6 +361,11 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
{
+ if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
+ dev_err(pd->dev, "Unsupported zero length i2c read\n");
+ return -EIO;
+ }
+
/* Initialize channel registers */
iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
@@ -233,9 +380,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
pd->pos = -1;
pd->sr = 0;
- /* Enable all interrupts except wait */
- iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
- ICIC(pd));
+ /* Enable all interrupts to begin with */
+ iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd));
return 0;
}
@@ -268,25 +414,18 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
if (!k)
dev_err(pd->dev, "Transfer request timed out\n");
- retry_count = 10;
+ retry_count = 1000;
again:
val = ioread8(ICSR(pd));
dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
- if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
- err = -EIO;
- break;
- }
-
/* the interrupt handler may wake us up before the
* transfer is finished, so poll the hardware
* until we're done.
*/
-
- if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
- (val & ICSR_SDAM))) {
- msleep(1);
+ if (val & ICSR_BUSY) {
+ udelay(10);
if (retry_count--)
goto again;
@@ -294,6 +433,12 @@ again:
dev_err(pd->dev, "Polling timed out\n");
break;
}
+
+ /* handle missing acknowledge and arbitration lost */
+ if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
+ err = -EIO;
+ break;
+ }
}
deactivate_ch(pd);
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 862eb352a2d..73dc52e114e 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -36,6 +36,7 @@
VT8237S 0x3372 yes
VT8251 0x3287 yes
CX700 0x8324 yes
+ VX800/VX820 0x8353 yes
Note: we assume there can only be one device, with one SMBus interface.
*/
@@ -82,6 +83,7 @@ static unsigned short SMBHSTCFG = 0xD2;
#define VT596_BYTE 0x04
#define VT596_BYTE_DATA 0x08
#define VT596_WORD_DATA 0x0C
+#define VT596_PROC_CALL 0x10
#define VT596_BLOCK_DATA 0x14
#define VT596_I2C_BLOCK_DATA 0x34
@@ -232,6 +234,12 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
}
size = VT596_WORD_DATA;
break;
+ case I2C_SMBUS_PROC_CALL:
+ outb_p(command, SMBHSTCMD);
+ outb_p(data->word & 0xff, SMBHSTDAT0);
+ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+ size = VT596_PROC_CALL;
+ break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (!(vt596_features & FEATURE_I2CBLOCK))
goto exit_unsupported;
@@ -262,6 +270,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
if (status)
return status;
+ if (size == VT596_PROC_CALL)
+ read_write = I2C_SMBUS_READ;
+
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
return 0;
@@ -271,6 +282,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
data->byte = inb_p(SMBHSTDAT0);
break;
case VT596_WORD_DATA:
+ case VT596_PROC_CALL:
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
break;
case VT596_I2C_BLOCK_DATA:
@@ -295,7 +307,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
{
u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA;
+ I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
if (vt596_features & FEATURE_I2CBLOCK)
func |= I2C_FUNC_SMBUS_I2C_BLOCK;
@@ -396,6 +408,7 @@ found:
switch (pdev->device) {
case PCI_DEVICE_ID_VIA_CX700:
+ case PCI_DEVICE_ID_VIA_VX800:
case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A:
@@ -459,6 +472,8 @@ static struct pci_device_id vt596_ids[] = {
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
.driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800),
+ .driver_data = SMBBA3 },
{ 0, }
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index a95cb9465d6..17356827b93 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -172,4 +172,15 @@ config MENELAUS
and other features that are often used in portable devices like
cell phones and PDAs.
+config MCU_MPC8349EMITX
+ tristate "MPC8349E-mITX MCU driver"
+ depends on I2C && PPC_83xx
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Say Y here to enable soft power-off functionality on the Freescale
+ boards with the MPC8349E-mITX-compatible MCU chips. This driver will
+ also register MCU GPIOs with the generic GPIO API, so you'll able
+ to use MCU pins as GPIOs.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 39e3e69ed12..ca520fa143d 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
+obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 4655b794ebe..28902ebd553 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -49,10 +49,9 @@ MODULE_LICENSE("GPL");
struct isp1301 {
struct otg_transceiver otg;
- struct i2c_client client;
+ struct i2c_client *client;
void (*i2c_release)(struct device *dev);
- int irq;
int irq_type;
u32 last_otg_ctrl;
@@ -138,14 +137,6 @@ static inline void notresponding(struct isp1301 *isp)
/*-------------------------------------------------------------------------*/
-/* only two addresses possible */
-#define ISP_BASE 0x2c
-static unsigned short normal_i2c[] = {
- ISP_BASE, ISP_BASE + 1,
- I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
static struct i2c_driver isp1301_driver;
/* smbus apis are used for portability */
@@ -153,25 +144,25 @@ static struct i2c_driver isp1301_driver;
static inline u8
isp1301_get_u8(struct isp1301 *isp, u8 reg)
{
- return i2c_smbus_read_byte_data(&isp->client, reg + 0);
+ return i2c_smbus_read_byte_data(isp->client, reg + 0);
}
static inline int
isp1301_get_u16(struct isp1301 *isp, u8 reg)
{
- return i2c_smbus_read_word_data(&isp->client, reg);
+ return i2c_smbus_read_word_data(isp->client, reg);
}
static inline int
isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
{
- return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits);
+ return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
}
static inline int
isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
{
- return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits);
+ return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
}
/*-------------------------------------------------------------------------*/
@@ -349,10 +340,10 @@ isp1301_defer_work(struct isp1301 *isp, int work)
int status;
if (isp && !test_and_set_bit(work, &isp->todo)) {
- (void) get_device(&isp->client.dev);
+ (void) get_device(&isp->client->dev);
status = schedule_work(&isp->work);
if (!status && !isp->working)
- dev_vdbg(&isp->client.dev,
+ dev_vdbg(&isp->client->dev,
"work item %d may be lost\n", work);
}
}
@@ -1135,7 +1126,7 @@ isp1301_work(struct work_struct *work)
/* transfer state from otg engine to isp1301 */
if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
otg_update_isp(isp);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
#endif
/* transfer state from isp1301 to otg engine */
@@ -1143,7 +1134,7 @@ isp1301_work(struct work_struct *work)
u8 stat = isp1301_clear_latch(isp);
isp_update_otg(isp, stat);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
@@ -1178,7 +1169,7 @@ isp1301_work(struct work_struct *work)
}
host_resume(isp);
// mdelay(10);
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
@@ -1187,15 +1178,15 @@ isp1301_work(struct work_struct *work)
if (!stop)
mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
#endif
- put_device(&isp->client.dev);
+ put_device(&isp->client->dev);
}
if (isp->todo)
- dev_vdbg(&isp->client.dev,
+ dev_vdbg(&isp->client->dev,
"work done, todo = 0x%lx\n",
isp->todo);
if (stop) {
- dev_dbg(&isp->client.dev, "stop\n");
+ dev_dbg(&isp->client->dev, "stop\n");
break;
}
} while (isp->todo);
@@ -1219,7 +1210,7 @@ static void isp1301_release(struct device *dev)
{
struct isp1301 *isp;
- isp = container_of(dev, struct isp1301, client.dev);
+ isp = dev_get_drvdata(dev);
/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
if (isp->i2c_release)
@@ -1229,15 +1220,15 @@ static void isp1301_release(struct device *dev)
static struct isp1301 *the_transceiver;
-static int isp1301_detach_client(struct i2c_client *i2c)
+static int __exit isp1301_remove(struct i2c_client *i2c)
{
struct isp1301 *isp;
- isp = container_of(i2c, struct isp1301, client);
+ isp = i2c_get_clientdata(i2c);
isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
- free_irq(isp->irq, isp);
+ free_irq(i2c->irq, isp);
#ifdef CONFIG_USB_OTG
otg_unbind(isp);
#endif
@@ -1252,7 +1243,7 @@ static int isp1301_detach_client(struct i2c_client *i2c)
put_device(&i2c->dev);
the_transceiver = 0;
- return i2c_detach_client(i2c);
+ return 0;
}
/*-------------------------------------------------------------------------*/
@@ -1285,7 +1276,7 @@ static int isp1301_otg_enable(struct isp1301 *isp)
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
- dev_info(&isp->client.dev, "ready for dual-role USB ...\n");
+ dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
return 0;
}
@@ -1310,7 +1301,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
#ifdef CONFIG_USB_OTG
isp->otg.host = host;
- dev_dbg(&isp->client.dev, "registered host\n");
+ dev_dbg(&isp->client->dev, "registered host\n");
host_suspend(isp);
if (isp->otg.gadget)
return isp1301_otg_enable(isp);
@@ -1325,7 +1316,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
if (machine_is_omap_h2())
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
- dev_info(&isp->client.dev, "A-Host sessions ok\n");
+ dev_info(&isp->client->dev, "A-Host sessions ok\n");
isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
INTR_ID_GND);
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
@@ -1343,7 +1334,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
return 0;
#else
- dev_dbg(&isp->client.dev, "host sessions not allowed\n");
+ dev_dbg(&isp->client->dev, "host sessions not allowed\n");
return -EINVAL;
#endif
@@ -1370,7 +1361,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
#ifdef CONFIG_USB_OTG
isp->otg.gadget = gadget;
- dev_dbg(&isp->client.dev, "registered gadget\n");
+ dev_dbg(&isp->client->dev, "registered gadget\n");
/* gadget driver may be suspended until vbus_connect () */
if (isp->otg.host)
return isp1301_otg_enable(isp);
@@ -1395,7 +1386,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
INTR_SESS_VLD);
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
INTR_VBUS_VLD);
- dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+ dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
dump_regs(isp, __func__);
/* If this has a Mini-AB connector, this mode is highly
@@ -1408,7 +1399,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
return 0;
#else
- dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
+ dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
return -EINVAL;
#endif
}
@@ -1508,12 +1499,10 @@ isp1301_start_hnp(struct otg_transceiver *dev)
/*-------------------------------------------------------------------------*/
-/* no error returns, they'd just make bus scanning stop */
-static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
+static int __init isp1301_probe(struct i2c_client *i2c)
{
int status;
struct isp1301 *isp;
- struct i2c_client *i2c;
if (the_transceiver)
return 0;
@@ -1527,37 +1516,19 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
isp->timer.function = isp1301_timer;
isp->timer.data = (unsigned long) isp;
- isp->irq = -1;
- isp->client.addr = address;
- i2c_set_clientdata(&isp->client, isp);
- isp->client.adapter = bus;
- isp->client.driver = &isp1301_driver;
- strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
- i2c = &isp->client;
-
- /* if this is a true probe, verify the chip ... */
- if (kind < 0) {
- status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
- if (status != I2C_VENDOR_ID_PHILIPS) {
- dev_dbg(&bus->dev, "addr %d not philips id: %d\n",
- address, status);
- goto fail1;
- }
- status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
- if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
- dev_dbg(&bus->dev, "%d not isp1301, %d\n",
- address, status);
- goto fail1;
- }
- }
+ i2c_set_clientdata(i2c, isp);
+ isp->client = i2c;
- status = i2c_attach_client(i2c);
- if (status < 0) {
- dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
- DRIVER_NAME, address, status);
-fail1:
- kfree(isp);
- return 0;
+ /* verify the chip (shouldn't be necesary) */
+ status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+ if (status != I2C_VENDOR_ID_PHILIPS) {
+ dev_dbg(&i2c->dev, "not philips id: %d\n", status);
+ goto fail;
+ }
+ status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+ if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+ dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
+ goto fail;
}
isp->i2c_release = i2c->dev.release;
i2c->dev.release = isp1301_release;
@@ -1586,7 +1557,7 @@ fail1:
status = otg_bind(isp);
if (status < 0) {
dev_dbg(&i2c->dev, "can't bind OTG\n");
- goto fail2;
+ goto fail;
}
#endif
@@ -1599,26 +1570,21 @@ fail1:
/* IRQ wired at M14 */
omap_cfg_reg(M14_1510_GPIO2);
- isp->irq = OMAP_GPIO_IRQ(2);
if (gpio_request(2, "isp1301") == 0)
gpio_direction_input(2);
isp->irq_type = IRQF_TRIGGER_FALLING;
}
isp->irq_type |= IRQF_SAMPLE_RANDOM;
- status = request_irq(isp->irq, isp1301_irq,
+ status = request_irq(i2c->irq, isp1301_irq,
isp->irq_type, DRIVER_NAME, isp);
if (status < 0) {
dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
- isp->irq, status);
-#ifdef CONFIG_USB_OTG
-fail2:
-#endif
- i2c_detach_client(i2c);
- goto fail1;
+ i2c->irq, status);
+ goto fail;
}
- isp->otg.dev = &isp->client.dev;
+ isp->otg.dev = &i2c->dev;
isp->otg.label = DRIVER_NAME;
isp->otg.set_host = isp1301_set_host,
@@ -1649,22 +1615,25 @@ fail2:
status);
return 0;
-}
-static int isp1301_scan_bus(struct i2c_adapter *bus)
-{
- if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA
- | I2C_FUNC_SMBUS_READ_WORD_DATA))
- return -EINVAL;
- return i2c_probe(bus, &addr_data, isp1301_probe);
+fail:
+ kfree(isp);
+ return -ENODEV;
}
+static const struct i2c_device_id isp1301_id[] = {
+ { "isp1301_omap", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, isp1301_id);
+
static struct i2c_driver isp1301_driver = {
.driver = {
.name = "isp1301_omap",
},
- .attach_adapter = isp1301_scan_bus,
- .detach_client = isp1301_detach_client,
+ .probe = isp1301_probe,
+ .remove = __exit_p(isp1301_remove),
+ .id_table = isp1301_id,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c
new file mode 100644
index 00000000000..82a9bcb858b
--- /dev/null
+++ b/drivers/i2c/chips/mcu_mpc8349emitx.c
@@ -0,0 +1,209 @@
+/*
+ * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
+ *
+ * Copyright (c) 2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+/*
+ * I don't have specifications for the MCU firmware, I found this register
+ * and bits positions by the trial&error method.
+ */
+#define MCU_REG_CTRL 0x20
+#define MCU_CTRL_POFF 0x40
+
+#define MCU_NUM_GPIO 2
+
+struct mcu {
+ struct mutex lock;
+ struct device_node *np;
+ struct i2c_client *client;
+ struct of_gpio_chip of_gc;
+ u8 reg_ctrl;
+};
+
+static struct mcu *glob_mcu;
+
+static void mcu_power_off(void)
+{
+ struct mcu *mcu = glob_mcu;
+
+ pr_info("Sending power-off request to the MCU...\n");
+ mutex_lock(&mcu->lock);
+ i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+ mcu->reg_ctrl | MCU_CTRL_POFF);
+ mutex_unlock(&mcu->lock);
+}
+
+static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
+ struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
+ u8 bit = 1 << (4 + gpio);
+
+ mutex_lock(&mcu->lock);
+ if (val)
+ mcu->reg_ctrl &= ~bit;
+ else
+ mcu->reg_ctrl |= bit;
+
+ i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
+ mutex_unlock(&mcu->lock);
+}
+
+static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ mcu_gpio_set(gc, gpio, val);
+ return 0;
+}
+
+static int mcu_gpiochip_add(struct mcu *mcu)
+{
+ struct device_node *np;
+ struct of_gpio_chip *of_gc = &mcu->of_gc;
+ struct gpio_chip *gc = &of_gc->gc;
+ int ret;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
+ if (!np)
+ return -ENODEV;
+
+ gc->owner = THIS_MODULE;
+ gc->label = np->full_name;
+ gc->can_sleep = 1;
+ gc->ngpio = MCU_NUM_GPIO;
+ gc->base = -1;
+ gc->set = mcu_gpio_set;
+ gc->direction_output = mcu_gpio_dir_out;
+ of_gc->gpio_cells = 2;
+ of_gc->xlate = of_gpio_simple_xlate;
+
+ np->data = of_gc;
+ mcu->np = np;
+
+ /*
+ * We don't want to lose the node, its ->data and ->full_name...
+ * So, if succeeded, we don't put the node here.
+ */
+ ret = gpiochip_add(gc);
+ if (ret)
+ of_node_put(np);
+ return ret;
+}
+
+static int mcu_gpiochip_remove(struct mcu *mcu)
+{
+ int ret;
+
+ ret = gpiochip_remove(&mcu->of_gc.gc);
+ if (ret)
+ return ret;
+ of_node_put(mcu->np);
+
+ return 0;
+}
+
+static int __devinit mcu_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mcu *mcu;
+ int ret;
+
+ mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
+ if (!mcu)
+ return -ENOMEM;
+
+ mutex_init(&mcu->lock);
+ mcu->client = client;
+ i2c_set_clientdata(client, mcu);
+
+ ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+ if (ret < 0)
+ goto err;
+ mcu->reg_ctrl = ret;
+
+ ret = mcu_gpiochip_add(mcu);
+ if (ret)
+ goto err;
+
+ /* XXX: this is potentially racy, but there is no lock for ppc_md */
+ if (!ppc_md.power_off) {
+ glob_mcu = mcu;
+ ppc_md.power_off = mcu_power_off;
+ dev_info(&client->dev, "will provide power-off service\n");
+ }
+
+ return 0;
+err:
+ kfree(mcu);
+ return ret;
+}
+
+static int __devexit mcu_remove(struct i2c_client *client)
+{
+ struct mcu *mcu = i2c_get_clientdata(client);
+ int ret;
+
+ if (glob_mcu == mcu) {
+ ppc_md.power_off = NULL;
+ glob_mcu = NULL;
+ }
+
+ ret = mcu_gpiochip_remove(mcu);
+ if (ret)
+ return ret;
+ i2c_set_clientdata(client, NULL);
+ kfree(mcu);
+ return 0;
+}
+
+static const struct i2c_device_id mcu_ids[] = {
+ { "mcu-mpc8349emitx", },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, mcu_ids);
+
+static struct i2c_driver mcu_driver = {
+ .driver = {
+ .name = "mcu-mpc8349emitx",
+ .owner = THIS_MODULE,
+ },
+ .probe = mcu_probe,
+ .remove = __devexit_p(mcu_remove),
+ .id_table = mcu_ids,
+};
+
+static int __init mcu_init(void)
+{
+ return i2c_add_driver(&mcu_driver);
+}
+module_init(mcu_init);
+
+static void __exit mcu_exit(void)
+{
+ i2c_del_driver(&mcu_driver);
+}
+module_exit(mcu_exit);
+
+MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
+ "MPC8349E-mITX-compatible MCU");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index cf02e8fceb4..acf8b9d5f57 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -456,14 +456,17 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
/* offsets 0..3 == GPIO1..GPIO4
* offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
+ * offset 6 == vibrator motor driver
*/
static void
tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
if (offset < 4)
tps65010_set_gpio_out_value(offset + 1, value);
- else
+ else if (offset < 6)
tps65010_set_led(offset - 3, value ? ON : OFF);
+ else
+ tps65010_set_vib(value);
}
static int
@@ -477,8 +480,10 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
if (!(tps->outmask & (1 << offset)))
return -EINVAL;
tps65010_set_gpio_out_value(offset + 1, value);
- } else
+ } else if (offset < 6)
tps65010_set_led(offset - 3, value ? ON : OFF);
+ else
+ tps65010_set_vib(value);
return 0;
}
@@ -646,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client,
tps->chip.get = tps65010_gpio_get;
tps->chip.base = board->base;
- tps->chip.ngpio = 6;
+ tps->chip.ngpio = 7;
tps->chip.can_sleep = 1;
status = gpiochip_add(&tps->chip);
@@ -675,6 +680,7 @@ static const struct i2c_device_id tps65010_id[] = {
{ "tps65011", TPS65011 },
{ "tps65012", TPS65012 },
{ "tps65013", TPS65013 },
+ { "tps65014", TPS65011 }, /* tps65011 charging at 6.5V max */
{ }
};
MODULE_DEVICE_TABLE(i2c, tps65010_id);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b346a687ab5..42e852d79ff 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -437,6 +437,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
{
int res = 0, dummy;
+ /* Can't register until after driver model init */
+ if (unlikely(WARN_ON(!i2c_bus_type.p)))
+ return -EAGAIN;
+
mutex_init(&adap->bus_lock);
mutex_init(&adap->clist_lock);
INIT_LIST_HEAD(&adap->clients);
@@ -696,6 +700,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
+ /* Can't register until after driver model init */
+ if (unlikely(WARN_ON(!i2c_bus_type.p)))
+ return -EAGAIN;
+
/* new style driver methods can't mix with legacy ones */
if (is_newstyle_driver(driver)) {
if (driver->attach_adapter || driver->detach_adapter
@@ -978,7 +986,10 @@ static void __exit i2c_exit(void)
bus_unregister(&i2c_bus_type);
}
-subsys_initcall(i2c_init);
+/* We must initialize early, because some subsystems register i2c drivers
+ * in subsys_initcall() code, but are linked (and initialized) before i2c.
+ */
+postcore_initcall(i2c_init);
module_exit(i2c_exit);
/* ----------------------------------------------------
@@ -1677,6 +1688,28 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
EXPORT_SYMBOL(i2c_smbus_write_word_data);
/**
+ * i2c_smbus_process_call - SMBus "process call" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: 16-bit "word" being written
+ *
+ * This executes the SMBus "process call" protocol, returning negative errno
+ * else a 16-bit unsigned "word" received from the device.
+ */
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
+{
+ union i2c_smbus_data data;
+ int status;
+ data.word = value;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_PROC_CALL, &data);
+ return (status < 0) ? status : data.word;
+}
+EXPORT_SYMBOL(i2c_smbus_process_call);
+
+/**
* i2c_smbus_read_block_data - SMBus "block read" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index af4491fa7e3..c171988a9f5 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */
- i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
- MKDEV(I2C_MAJOR, adap->nr),
- NULL, "i2c-%d", adap->nr);
+ i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+ MKDEV(I2C_MAJOR, adap->nr), NULL,
+ "i2c-%d", adap->nr);
if (IS_ERR(i2c_dev->dev)) {
res = PTR_ERR(i2c_dev->dev);
goto error;
@@ -583,8 +583,10 @@ static int __init i2c_dev_init(void)
goto out;
i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
- if (IS_ERR(i2c_dev_class))
+ if (IS_ERR(i2c_dev_class)) {
+ res = PTR_ERR(i2c_dev_class);
goto out_unreg_chrdev;
+ }
res = i2c_add_driver(&i2cdev_driver);
if (res)
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index a34758d2951..74a369a6116 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -4,7 +4,7 @@
# Select HAVE_IDE if IDE is supported
config HAVE_IDE
- def_bool n
+ bool
menuconfig IDE
tristate "ATA/ATAPI/MFM/RLL support"
@@ -54,38 +54,6 @@ menuconfig IDE
if IDE
-config BLK_DEV_IDE
- tristate "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
- ---help---
- If you say Y here, you will use the full-featured IDE driver to
- control up to ten ATA/IDE interfaces, each being able to serve a
- "master" and a "slave" device, for a total of up to twenty ATA/IDE
- disk/cdrom/tape/floppy drives.
-
- Useful information about large (>540 MB) IDE disks, multiple
- interfaces, what to do if ATA/IDE devices are not automatically
- detected, sound card ATA/IDE ports, module support, and other
- topics, is contained in <file:Documentation/ide/ide.txt>. For detailed
- information about hard drives, consult the Disk-HOWTO and the
- Multi-Disk-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To fine-tune ATA/IDE drive/interface parameters for improved
- performance, look for the hdparm package at
- <ftp://ibiblio.org/pub/Linux/system/hardware/>.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/ide/ide.txt>. The module will be called ide-mod.
- Do not compile this driver as a module if your root file system (the
- one containing the directory /) is located on an IDE device.
-
- If you have one or more IDE drives, say Y or M here. If your system
- has no IDE drives, or if memory requirements are really tight, you
- could say N here, and select the "Old hard disk driver" below
- instead to save about 13 KB of memory in the kernel.
-
-if BLK_DEV_IDE
-
comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
config IDE_TIMINGS
@@ -131,29 +99,6 @@ config BLK_DEV_IDEDISK
If unsure, say Y.
-config IDEDISK_MULTI_MODE
- bool "Use multiple sector mode for Programmed Input/Output by default"
- help
- This setting is irrelevant for most IDE disks, with direct memory
- access, to which multiple sector mode does not apply. Multiple sector
- mode is a feature of most modern IDE hard drives, permitting the
- transfer of multiple sectors per Programmed Input/Output interrupt,
- rather than the usual one sector per interrupt. When this feature is
- enabled, it can reduce operating system overhead for disk Programmed
- Input/Output. On some systems, it also can increase the data
- throughput of Programmed Input/Output. Some drives, however, seemed
- to run slower with multiple sector mode enabled. Some drives claimed
- to support multiple sector mode, but lost data at some settings.
- Under rare circumstances, such failures could result in massive
- filesystem corruption.
-
- If you get the following error, try to say Y here:
-
- hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
- hda: set_multmode: error=0x04 { DriveStatusError }
-
- If in doubt, say N.
-
config BLK_DEV_IDECS
tristate "PCMCIA IDE support"
depends on PCMCIA
@@ -242,7 +187,7 @@ config BLK_DEV_IDEFLOPPY
module will be called ide-floppy.
config BLK_DEV_IDESCSI
- tristate "SCSI emulation support"
+ tristate "SCSI emulation support (DEPRECATED)"
depends on SCSI
select IDE_ATAPI
---help---
@@ -255,20 +200,6 @@ config BLK_DEV_IDESCSI
and will allow you to use a SCSI device driver instead of a native
ATAPI driver.
- This is useful if you have an ATAPI device for which no native
- driver has been written (for example, an ATAPI PD-CD drive);
- you can then use this emulation together with an appropriate SCSI
- device driver. In order to do this, say Y here and to "SCSI support"
- and "SCSI generic support", below. You must then provide the kernel
- command line "hdx=ide-scsi" (try "man bootparam" or see the
- documentation of your boot loader (lilo or loadlin) about how to
- pass options to the kernel at boot time) for devices if you want the
- native EIDE sub-drivers to skip over the native support, so that
- this SCSI emulation can be used instead.
-
- Note that this option does NOT allow you to attach SCSI devices to a
- box that doesn't have a SCSI host adapter installed.
-
If both this SCSI emulation and native ATAPI support are compiled
into the kernel, the native support will be used.
@@ -306,6 +237,20 @@ config IDE_GENERIC
tristate "generic/default IDE chipset support"
depends on ALPHA || X86 || IA64 || M32R || MIPS
help
+ This is the generic IDE driver. This driver attaches to the
+ fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and
+ so on). Please note that if this driver is built into the
+ kernel or loaded before other ATA (IDE or libata) drivers
+ and the controller is located at legacy ports, this driver
+ may grab those ports and thus can prevent the controller
+ specific driver from attaching.
+
+ Also, currently, IDE generic doesn't allow IRQ sharing
+ meaning that the IRQs it grabs won't be available to other
+ controllers sharing those IRQs which usually makes drivers
+ for those controllers fail. Generally, it's not a good idea
+ to load IDE generic driver on modern systems.
+
If unsure, say N.
config BLK_DEV_PLATFORM
@@ -371,7 +316,7 @@ config BLK_DEV_IDEPCI
config IDEPCI_PCIBUS_ORDER
bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
- depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
+ depends on IDE=y && BLK_DEV_IDEPCI
default y
help
Probe IDE PCI devices in the order in which they appear on the
@@ -752,7 +697,7 @@ endif
config BLK_DEV_IDE_PMAC
tristate "PowerMac on-board IDE support"
- depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
+ depends on PPC_PMAC && IDE=y
select IDE_TIMINGS
help
This driver provides support for the on-board IDE controller on
@@ -780,10 +725,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_SWARM
- tristate "IDE for Sibyte evaluation boards"
- depends on SIBYTE_SB1xxx_SOC
-
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
@@ -990,6 +931,4 @@ config BLK_DEV_IDEDMA
def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-endif
-
endif # IDE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 64e0ecdc4ed..ceaf779054e 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -4,25 +4,26 @@
EXTRA_CFLAGS += -Idrivers/ide
-ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o \
- ide-pio-blacklist.o
+ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
+ ide-taskfile.o ide-park.o ide-pio-blacklist.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
+ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
-obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o
+obj-$(CONFIG_IDE) += ide-core.o
ifeq ($(CONFIG_IDE_ARM), y)
ide-arm-core-y += arm/ide_arm.o
obj-y += ide-arm-core.o
endif
-obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/
+obj-$(CONFIG_IDE) += legacy/ pci/
obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o
@@ -31,17 +32,24 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
obj-y += cmd640-core.o
endif
-obj-$(CONFIG_BLK_DEV_IDE) += ppc/
+obj-$(CONFIG_IDE) += ppc/
obj-$(CONFIG_IDE_H8300) += h8300/
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
+ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o
-obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
+ifeq ($(CONFIG_IDE_PROC_FS), y)
+ ide-disk_mod-y += ide-disk_proc.o
+ ide-floppy_mod-y += ide-floppy_proc.o
+endif
+
+obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o
obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
+obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
-obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
ifeq ($(CONFIG_BLK_DEV_IDECS), y)
ide-cs-core-y += legacy/ide-cs.o
@@ -53,4 +61,4 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
obj-y += ide-platform-core.o
endif
-obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/
+obj-$(CONFIG_IDE) += arm/ mips/
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index df4af408395..76bdc9a27f6 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/errno.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
@@ -265,8 +264,8 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
* If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
* take care to note the values in the ID...
*/
- if (use_dma_info && drive->id->eide_dma_time > cycle_time)
- cycle_time = drive->id->eide_dma_time;
+ if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
+ cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
drive->drive_data = cycle_time;
@@ -373,25 +372,6 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
}
-static void icside_dma_timeout(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
- if (icside_dma_test_irq(drive))
- return;
-
- ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
-
- icside_dma_end(drive);
-}
-
-static void icside_dma_lost_irq(ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
hwif->dmatable_cpu = NULL;
@@ -407,8 +387,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = {
.dma_start = icside_dma_start,
.dma_end = icside_dma_end,
.dma_test_irq = icside_dma_test_irq,
- .dma_timeout = icside_dma_timeout,
- .dma_lost_irq = icside_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
};
#else
#define icside_v6_dma_ops NULL
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
index f788fa5a977..122ed3c072f 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/arm/palm_bk3710.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -180,7 +179,7 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
val32 |= (t2i << (dev ? 8 : 0));
writel(val32, base + BK3710_DATRCVR);
- if (mate && mate->present) {
+ if (mate) {
u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
if (mode2 < mode)
@@ -213,7 +212,8 @@ static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
palm_bk3710_setudmamode(base, is_slave,
xferspeed - XFER_UDMA_0);
} else {
- palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
+ palm_bk3710_setdmamode(base, is_slave,
+ drive->id[ATA_ID_EIDE_DMA_MIN],
xferspeed);
}
}
@@ -229,7 +229,7 @@ static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
* Obtain the drive PIO data for tuning the Palm Chip registers
*/
cycle_time = ide_pio_cycle_time(drive, pio);
- mate = ide_get_paired_drive(drive);
+ mate = ide_get_pair_dev(drive);
palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
}
@@ -343,11 +343,10 @@ static struct ide_port_info __devinitdata palm_bk3710_port_info = {
.mwdma_mask = ATA_MWDMA2,
};
-static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+static int __init palm_bk3710_probe(struct platform_device *pdev)
{
struct clk *clk;
struct resource *mem, *irq;
- struct ide_host *host;
unsigned long base, rate;
int i, rc;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
@@ -390,6 +389,7 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
hw.irq = irq->start;
+ hw.dev = &pdev->dev;
hw.chipset = ide_palm3710;
palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
@@ -413,13 +413,11 @@ static struct platform_driver platform_bk_driver = {
.name = "palm_bk3710",
.owner = THIS_MODULE,
},
- .probe = palm_bk3710_probe,
- .remove = NULL,
};
static int __init palm_bk3710_init(void)
{
- return platform_driver_register(&platform_bk_driver);
+ return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
}
module_init(palm_bk3710_init);
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index bde7a585f19..e2cdd2e9cde 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -80,7 +80,7 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- outb((tf->device & HIHI) | drive->select.all,
+ outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 6f704628c27..244a8a052ce 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -290,7 +290,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
hwif->name, dev->bus_id, port, hwif->channel);
- if (!drive->present) {
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
DEBPRINT("%s drive %d:%d not present\n",
hwif->name, hwif->channel, port);
goto out;
@@ -420,8 +420,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
goto out;
+
if (!gtf_count) /* shouldn't be here */
goto out;
@@ -584,7 +585,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
* This function executes the _STM ACPI method for the target channel.
*
* _STM requires Identify Drive data, which has to passed as an argument.
- * Unfortunately hd_driveid is a mangled version which we can't readily
+ * Unfortunately drive->id is a mangled version which we can't readily
* use; hence we'll get the information afresh.
*/
void ide_acpi_push_timing(ide_hwif_t *hwif)
@@ -614,10 +615,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
in_params[0].buffer.length = sizeof(struct GTM_buffer);
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
in_params[1].type = ACPI_TYPE_BUFFER;
- in_params[1].buffer.length = sizeof(struct hd_driveid);
+ in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[1].buffer.pointer = (u8 *)&master->idbuff;
in_params[2].type = ACPI_TYPE_BUFFER;
- in_params[2].buffer.length = sizeof(struct hd_driveid);
+ in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2);
in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
/* Output buffer: _STM has no output */
@@ -660,7 +661,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
if (!drive->acpidata->obj_handle)
drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
- if (drive->acpidata->obj_handle && drive->present) {
+ if (drive->acpidata->obj_handle &&
+ (drive->dev_flags & IDE_DFLAG_PRESENT)) {
acpi_bus_set_power(drive->acpidata->obj_handle,
on? ACPI_STATE_D0: ACPI_STATE_D3);
}
@@ -720,7 +722,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
memset(drive->acpidata, 0, sizeof(*drive->acpidata));
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
@@ -745,7 +747,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
drive = &hwif->drives[i];
- if (drive->present)
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
/* Execute ACPI startup code */
ide_acpi_exec_tfs(drive);
}
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index adf04f99cde..2e305714c20 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -14,25 +14,268 @@
#define debug_log(fmt, args...) do {} while (0)
#endif
-/* TODO: unify the code thus making some arguments go away */
-ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
- ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
- void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
- void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
- void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
+/*
+ * Check whether we can support a device,
+ * based on the ATAPI IDENTIFY command results.
+ */
+int ide_check_atapi_device(ide_drive_t *drive, const char *s)
+{
+ u16 *id = drive->id;
+ u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
+
+ *((u16 *)&gcw) = id[ATA_ID_CONFIG];
+
+ protocol = (gcw[1] & 0xC0) >> 6;
+ device_type = gcw[1] & 0x1F;
+ removable = (gcw[0] & 0x80) >> 7;
+ drq_type = (gcw[0] & 0x60) >> 5;
+ packet_size = gcw[0] & 0x03;
+
+#ifdef CONFIG_PPC
+ /* kludge for Apple PowerBook internal zip */
+ if (drive->media == ide_floppy && device_type == 5 &&
+ !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
+ strstr((char *)&id[ATA_ID_PROD], "ZIP"))
+ device_type = 0;
+#endif
+
+ if (protocol != 2)
+ printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n",
+ s, drive->name, protocol);
+ else if ((drive->media == ide_floppy && device_type != 0) ||
+ (drive->media == ide_tape && device_type != 1))
+ printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n",
+ s, drive->name, device_type);
+ else if (removable == 0)
+ printk(KERN_ERR "%s: %s: the removable flag is not set\n",
+ s, drive->name);
+ else if (drive->media == ide_floppy && drq_type == 3)
+ printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
+ "supported\n", s, drive->name, drq_type);
+ else if (packet_size != 0)
+ printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
+ "bytes\n", s, drive->name, packet_size);
+ else
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_check_atapi_device);
+
+/* PIO data transfer routine using the scatter gather table. */
+int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount, int write)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
+ struct scatterlist *sg = pc->sg;
+ char *buf;
+ int count, done = 0;
+
+ while (bcount) {
+ count = min(sg->length - pc->b_count, bcount);
+
+ if (PageHighMem(sg_page(sg))) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+ xf(drive, NULL, buf + pc->b_count, count);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = sg_virt(sg);
+ xf(drive, NULL, buf + pc->b_count, count);
+ }
+
+ bcount -= count;
+ pc->b_count += count;
+ done += count;
+
+ if (pc->b_count == sg->length) {
+ if (!--pc->sg_cnt)
+ break;
+ pc->sg = sg = sg_next(sg);
+ pc->b_count = 0;
+ }
+ }
+
+ if (bcount) {
+ printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
+ bcount, write ? "padding with zeros"
+ : "discarding data");
+ ide_pad_transfer(drive, write, bcount);
+ }
+
+ return done;
+}
+EXPORT_SYMBOL_GPL(ide_io_buffers);
+
+void ide_init_pc(struct ide_atapi_pc *pc)
+{
+ memset(pc, 0, sizeof(*pc));
+ pc->buf = pc->pc_buf;
+ pc->buf_size = IDE_PC_BUFFER_SIZE;
+}
+EXPORT_SYMBOL_GPL(ide_init_pc);
+
+/*
+ * Generate a new packet command request in front of the request queue, before
+ * the current request, so that it will be processed immediately, on the next
+ * pass through the driver.
+ */
+static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
+ struct ide_atapi_pc *pc, struct request *rq)
+{
+ blk_rq_init(NULL, rq);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_flags |= REQ_PREEMPT;
+ rq->buffer = (char *)pc;
+ rq->rq_disk = disk;
+ memcpy(rq->cmd, pc->c, 12);
+ if (drive->media == ide_tape)
+ rq->cmd[13] = REQ_IDETAPE_PC1;
+ ide_do_drive_cmd(drive, rq);
+}
+
+/*
+ * Add a special packet command request to the tail of the request queue,
+ * and wait for it to be serviced.
+ */
+int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
+ struct ide_atapi_pc *pc)
+{
+ struct request *rq;
+ int error;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->buffer = (char *)pc;
+ memcpy(rq->cmd, pc->c, 12);
+ if (drive->media == ide_tape)
+ rq->cmd[13] = REQ_IDETAPE_PC1;
+ error = blk_execute_rq(drive->queue, disk, rq, 0);
+ blk_put_request(rq);
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
+
+int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
+{
+ struct ide_atapi_pc pc;
+
+ ide_init_pc(&pc);
+ pc.c[0] = TEST_UNIT_READY;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
+
+int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
+{
+ struct ide_atapi_pc pc;
+
+ ide_init_pc(&pc);
+ pc.c[0] = START_STOP;
+ pc.c[4] = start;
+
+ if (drive->media == ide_tape)
+ pc.flags |= PC_FLAG_WAIT_FOR_DSC;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_do_start_stop);
+
+int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
{
+ struct ide_atapi_pc pc;
+
+ if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
+ return 0;
+
+ ide_init_pc(&pc);
+ pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+ pc.c[4] = on;
+
+ return ide_queue_pc_tail(drive, disk, &pc);
+}
+EXPORT_SYMBOL_GPL(ide_set_media_lock);
+
+void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
+{
+ ide_init_pc(pc);
+ pc->c[0] = REQUEST_SENSE;
+ if (drive->media == ide_floppy) {
+ pc->c[4] = 255;
+ pc->req_xfer = 18;
+ } else {
+ pc->c[4] = 20;
+ pc->req_xfer = 20;
+ }
+}
+EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
+
+/*
+ * Called when an error was detected during the last packet command.
+ * We queue a request sense packet command in the head of the request list.
+ */
+void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+{
+ struct request *rq = &drive->request_sense_rq;
+ struct ide_atapi_pc *pc = &drive->request_sense_pc;
+
+ (void)ide_read_error(drive);
+ ide_create_request_sense_cmd(drive, pc);
+ if (drive->media == ide_tape)
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+ ide_queue_pc_head(drive, disk, pc, rq);
+}
+EXPORT_SYMBOL_GPL(ide_retry_pc);
+
+int ide_scsi_expiry(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
+
+ debug_log("%s called for %lu at %lu\n", __func__,
+ pc->scsi_cmd->serial_number, jiffies);
+
+ pc->flags |= PC_FLAG_TIMEDOUT;
+
+ return 0; /* we do not want the IDE subsystem to retry */
+}
+EXPORT_SYMBOL_GPL(ide_scsi_expiry);
+
+/*
+ * This is the usual interrupt handler which will be called during a packet
+ * command. We will transfer some of the data (as requested by the drive)
+ * and will re-point interrupt handler to us.
+ */
+static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc;
- unsigned int temp;
+ ide_expiry_t *expiry;
+ unsigned int timeout, temp;
u16 bcount;
- u8 stat, ireason, scsi = drive->scsi;
+ u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
debug_log("Enter %s - interrupt handler\n", __func__);
+ if (scsi) {
+ timeout = ide_scsi_get_timeout(pc);
+ expiry = ide_scsi_expiry;
+ } else {
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ expiry = NULL;
+ }
+
if (pc->flags & PC_FLAG_TIMEDOUT) {
- drive->pc_callback(drive);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
@@ -41,7 +284,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) ||
- (drive->media == ide_tape && !scsi && (stat & ERR_STAT))) {
+ (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
if (drive->media == ide_floppy && !scsi)
printk(KERN_ERR "%s: DMA %s error\n",
drive->name, rq_data_dir(pc->rq)
@@ -49,14 +292,14 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
pc->flags |= PC_FLAG_DMA_ERROR;
} else {
pc->xferred = pc->req_xfer;
- if (update_buffers)
- update_buffers(drive, pc);
+ if (drive->pc_update_buffers)
+ drive->pc_update_buffers(drive, pc);
}
debug_log("%s: DMA finished\n", drive->name);
}
/* No more interrupts */
- if ((stat & DRQ_STAT) == 0) {
+ if ((stat & ATA_DRQ) == 0) {
debug_log("Packet command completed, %d bytes transferred\n",
pc->xferred);
@@ -65,10 +308,10 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_enable_in_hardirq();
if (drive->media == ide_tape && !scsi &&
- (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE)
- stat &= ~ERR_STAT;
+ (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
+ stat &= ~ATA_ERR;
- if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+ if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
/* Error detected */
debug_log("%s: I/O error\n", drive->name);
@@ -87,21 +330,19 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
/* Retry operation */
- retry_pc(drive);
+ ide_retry_pc(drive, rq->rq_disk);
/* queued, but not started */
return ide_stopped;
}
cmd_finished:
pc->error = 0;
- if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
- (stat & SEEK_STAT) == 0) {
- dsc_handle(drive);
- return ide_stopped;
- }
+
+ if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
+ dsc = 1;
/* Command finished - Call the callback function */
- drive->pc_callback(drive);
+ drive->pc_callback(drive, dsc);
return ide_stopped;
}
@@ -117,17 +358,18 @@ cmd_finished:
/* Get the number of bytes to transfer on this interrupt. */
ide_read_bcount_and_ireason(drive, &bcount, &ireason);
- if (ireason & CD) {
+ if (ireason & ATAPI_COD) {
printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
return ide_do_reset(drive);
}
- if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
+ if (((ireason & ATAPI_IO) == ATAPI_IO) ==
+ !!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
"to %s!\n", drive->name,
- (ireason & IO) ? "Write" : "Read",
- (ireason & IO) ? "Read" : "Write");
+ (ireason & ATAPI_IO) ? "Write" : "Read",
+ (ireason & ATAPI_IO) ? "Read" : "Write");
return ide_do_reset(drive);
}
@@ -146,7 +388,8 @@ cmd_finished:
temp = 0;
if (temp) {
if (pc->sg)
- io_buffers(drive, pc, temp, 0);
+ drive->pc_io_buffers(drive, pc,
+ temp, 0);
else
tp_ops->input_data(drive, NULL,
pc->cur_pos, temp);
@@ -158,9 +401,7 @@ cmd_finished:
pc->xferred += temp;
pc->cur_pos += temp;
ide_pad_transfer(drive, 0, bcount - temp);
- ide_set_handler(drive, handler, timeout,
- expiry);
- return ide_started;
+ goto next_irq;
}
debug_log("The device wants to send us more data than "
"expected - allowing transfer\n");
@@ -171,9 +412,14 @@ cmd_finished:
if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
(drive->media == ide_tape && !scsi && pc->bh) ||
- (scsi && pc->sg))
- io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING));
- else
+ (scsi && pc->sg)) {
+ int done = drive->pc_io_buffers(drive, pc, bcount,
+ !!(pc->flags & PC_FLAG_WRITING));
+
+ /* FIXME: don't do partial completions */
+ if (drive->media == ide_floppy && !scsi)
+ ide_end_request(drive, 1, done >> 9);
+ } else
xferfunc(drive, NULL, pc->cur_pos, bcount);
/* Update the current position */
@@ -182,12 +428,11 @@ cmd_finished:
debug_log("[cmd %x] transferred %d bytes on that intr.\n",
rq->cmd[0], bcount);
-
+next_irq:
/* And set the interrupt handler again */
- ide_set_handler(drive, handler, timeout, expiry);
+ ide_set_handler(drive, ide_pc_intr, timeout, expiry);
return ide_started;
}
-EXPORT_SYMBOL_GPL(ide_pc_intr);
static u8 ide_read_ireason(ide_drive_t *drive)
{
@@ -205,7 +450,8 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
{
int retries = 100;
- while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+ while (retries-- && ((ireason & ATAPI_COD) == 0 ||
+ (ireason & ATAPI_IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name);
udelay(100);
@@ -214,41 +460,71 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n",
drive->name);
- ireason |= CD;
- ireason &= ~IO;
+ ireason |= ATAPI_COD;
+ ireason &= ~ATAPI_IO;
}
}
return ireason;
}
-ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
- ide_handler_t *handler, unsigned int timeout,
- ide_expiry_t *expiry)
+static int ide_delayed_transfer_pc(ide_drive_t *drive)
{
+ /* Send the actual packet */
+ drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
+
+ /* Timeout for the packet command */
+ return WAIT_FLOPPY_CMD;
+}
+
+static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
+{
+ struct ide_atapi_pc *pc = drive->pc;
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq;
+ ide_expiry_t *expiry;
+ unsigned int timeout;
ide_startstop_t startstop;
u8 ireason;
- if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name);
return startstop;
}
ireason = ide_read_ireason(drive);
- if (drive->media == ide_tape && !drive->scsi)
+ if (drive->media == ide_tape &&
+ (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
ireason = ide_wait_ireason(drive, ireason);
- if ((ireason & CD) == 0 || (ireason & IO)) {
+ if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
"a packet command\n", drive->name);
return ide_do_reset(drive);
}
+ /*
+ * If necessary schedule the packet transfer to occur 'timeout'
+ * miliseconds later in ide_delayed_transfer_pc() after the device
+ * says it's ready for a packet.
+ */
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+ timeout = drive->pc_delay;
+ expiry = &ide_delayed_transfer_pc;
+ } else {
+ if (drive->dev_flags & IDE_DFLAG_SCSI) {
+ timeout = ide_scsi_get_timeout(pc);
+ expiry = ide_scsi_expiry;
+ } else {
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ expiry = NULL;
+ }
+ }
+
/* Set the interrupt routine */
- ide_set_handler(drive, handler, timeout, expiry);
+ ide_set_handler(drive, ide_pc_intr, timeout, expiry);
/* Begin DMA, if necessary */
if (pc->flags & PC_FLAG_DMA_OK) {
@@ -262,22 +538,22 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
return ide_started;
}
-EXPORT_SYMBOL_GPL(ide_transfer_pc);
-ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
- ide_handler_t *handler, unsigned int timeout,
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
ide_expiry_t *expiry)
{
+ struct ide_atapi_pc *pc = drive->pc;
ide_hwif_t *hwif = drive->hwif;
+ u32 tf_flags;
u16 bcount;
- u8 dma = 0;
+ u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
/* We haven't transferred any data yet */
pc->xferred = 0;
pc->cur_pos = pc->buf;
/* Request to transfer the entire buffer at once */
- if (drive->media == ide_tape && !drive->scsi)
+ if (drive->media == ide_tape && scsi == 0)
bcount = pc->req_xfer;
else
bcount = min(pc->req_xfer, 63 * 1024);
@@ -287,28 +563,35 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
ide_dma_off(drive);
}
- if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
- if (drive->scsi)
+ if ((pc->flags & PC_FLAG_DMA_OK) &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
+ if (scsi)
hwif->sg_mapped = 1;
- dma = !hwif->dma_ops->dma_setup(drive);
- if (drive->scsi)
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+ if (scsi)
hwif->sg_mapped = 0;
}
- if (!dma)
+ if (!drive->dma)
pc->flags &= ~PC_FLAG_DMA_OK;
- ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE,
- bcount, dma);
+ if (scsi)
+ tf_flags = 0;
+ else if (drive->media == ide_cdrom || drive->media == ide_optical)
+ tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+ else
+ tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+ ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
/* Issue the packet command */
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
- ide_execute_command(drive, WIN_PACKETCMD, handler,
+ ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
timeout, NULL);
return ide_started;
} else {
ide_execute_pkt_cmd(drive);
- return (*handler)(drive);
+ return ide_transfer_pc(drive);
}
}
EXPORT_SYMBOL_GPL(ide_issue_pc);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 49a8c589e34..3308b1cd3a3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -23,6 +23,9 @@
* Documentation/ide/ChangeLog.ide-cd.1994-2004
*/
+#define DRV_NAME "ide-cd"
+#define PFX DRV_NAME ": "
+
#define IDECD_VERSION "5.00"
#include <linux/module.h>
@@ -50,12 +53,15 @@
#include "ide-cd.h"
-static DEFINE_MUTEX(idecd_ref_mutex);
+#define IDECD_DEBUG_LOG 1
-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+#if IDECD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
-#define ide_cd_g(disk) \
- container_of((disk)->private_data, struct cdrom_info, driver)
+static DEFINE_MUTEX(idecd_ref_mutex);
static void ide_cd_release(struct kref *);
@@ -64,7 +70,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk)
struct cdrom_info *cd = NULL;
mutex_lock(&idecd_ref_mutex);
- cd = ide_cd_g(disk);
+ cd = ide_drv_g(disk, cdrom_info);
if (cd) {
if (ide_device_get(cd->drive))
cd = NULL;
@@ -102,6 +108,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
{
int log = 0;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
+ sense->sense_key);
+
if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
return 0;
@@ -150,6 +159,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
unsigned long bio_sectors;
struct cdrom_info *info = drive->driver_data;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
+ "sense_key: 0x%x\n", __func__, sense->error_code,
+ sense->sense_key);
+
+ if (failed_command)
+ ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
+ __func__, failed_command->cmd[0]);
+
if (!cdrom_log_sense(drive, failed_command, sense))
return;
@@ -200,6 +217,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
struct cdrom_info *info = drive->driver_data;
struct request *rq = &info->request_sense_request;
+ ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);
+
if (sense == NULL)
sense = &info->sense_data;
@@ -219,6 +238,10 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
/* NOTE! Save the failed command in "rq->buffer" */
rq->buffer = (void *) failed_command;
+ if (failed_command)
+ ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
+ failed_command->cmd[0]);
+
ide_do_drive_cmd(drive, rq);
}
@@ -227,6 +250,10 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
struct request *rq = HWGROUP(drive)->rq;
int nsectors = rq->hard_cur_sectors;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
+ "nsectors: %d\n", __func__, rq->cmd[0], uptodate,
+ nsectors);
+
if (blk_sense_request(rq) && uptodate) {
/*
* For REQ_TYPE_SENSE, "rq->buffer" points to the original
@@ -269,6 +296,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
if (!nsectors)
nsectors = 1;
+ ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
+ __func__, uptodate, nsectors);
+
ide_end_request(drive, uptodate, nsectors);
}
@@ -304,11 +334,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense_key = err >> 4;
if (rq == NULL) {
- printk(KERN_ERR "%s: missing rq in %s\n",
+ printk(KERN_ERR PFX "%s: missing rq in %s\n",
drive->name, __func__);
return 1;
}
+ ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
+ "rq->cmd_type: 0x%x, err: 0x%x\n", __func__, stat,
+ good_stat, rq->cmd_type, err);
+
if (blk_sense_request(rq)) {
/*
* We got an error trying to get sense info from the drive
@@ -374,7 +408,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
cdrom_saw_media_change(drive);
/* fail the request */
- printk(KERN_ERR "%s: tray open\n", drive->name);
+ printk(KERN_ERR PFX "%s: tray open\n",
+ drive->name);
do_end_request = 1;
} else {
struct cdrom_info *info = drive->driver_data;
@@ -436,7 +471,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
ide_dump_status_no_sense(drive, "media error (blank)",
stat);
do_end_request = 1;
- } else if ((err & ~ABRT_ERR) != 0) {
+ } else if ((err & ~ATA_ABORTED) != 0) {
/* go to the default handler for other errors */
ide_error(drive, "cdrom_decode_status", stat);
return 1;
@@ -457,10 +492,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
* If we got a CHECK_CONDITION status, queue
* a request sense command.
*/
- if (stat & ERR_STAT)
+ if (stat & ATA_ERR)
cdrom_queue_request_sense(drive, NULL, NULL);
} else {
- blk_dump_rq_flags(rq, "ide-cd: bad rq");
+ blk_dump_rq_flags(rq, PFX "bad rq");
cdrom_end_request(drive, 0);
}
@@ -468,7 +503,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
return 1;
end_request:
- if (stat & ERR_STAT) {
+ if (stat & ATA_ERR) {
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
@@ -488,6 +523,9 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
struct request *rq = HWGROUP(drive)->rq;
unsigned long wait = 0;
+ ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
+ rq->cmd[0]);
+
/*
* Some commands are *slow* and normally take a long time to complete.
* Usually we can use the ATAPI "disconnect" to bypass this, but not all
@@ -504,7 +542,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
break;
default:
if (!(rq->cmd_flags & REQ_QUIET))
- printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n",
+ printk(KERN_INFO PFX "cmd 0x%x timed out\n",
rq->cmd[0]);
wait = 0;
break;
@@ -524,24 +562,25 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
int xferlen,
ide_handler_t *handler)
{
- struct cdrom_info *info = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
+ ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
+
/* FIXME: for Virtual DMA we must check harder */
- if (info->dma)
- info->dma = !hwif->dma_ops->dma_setup(drive);
+ if (drive->dma)
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
/* set up the controller registers */
ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
- xferlen, info->dma);
+ xferlen, drive->dma);
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
- if (info->dma)
+ if (drive->dma)
drive->waiting_for_dma = 0;
/* packet command */
- ide_execute_command(drive, WIN_PACKETCMD, handler,
+ ide_execute_command(drive, ATA_CMD_PACKET, handler,
ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started;
} else {
@@ -564,9 +603,10 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
{
ide_hwif_t *hwif = drive->hwif;
int cmd_len;
- struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
+ ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
+
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/*
* Here we should have been called after receiving an interrupt
@@ -574,16 +614,16 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
*/
/* check for errors */
- if (cdrom_decode_status(drive, DRQ_STAT, NULL))
+ if (cdrom_decode_status(drive, ATA_DRQ, NULL))
return ide_stopped;
/* ok, next interrupt will be DMA interrupt */
- if (info->dma)
+ if (drive->dma)
drive->waiting_for_dma = 1;
} else {
/* otherwise, we must wait for DRQ to get set */
- if (ide_wait_stat(&startstop, drive, DRQ_STAT,
- BUSY_STAT, WAIT_READY))
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ,
+ ATA_BUSY, WAIT_READY))
return startstop;
}
@@ -599,7 +639,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */
- if (info->dma)
+ if (drive->dma)
hwif->dma_ops->dma_start(drive);
return ide_started;
@@ -615,6 +655,9 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
{
ide_hwif_t *hwif = drive->hwif;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
+ __func__, ireason, rw);
+
/*
* ireason == 0: the drive wants to receive data from us
* ireason == 2: the drive is expecting to transfer data to us
@@ -624,7 +667,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
else if (ireason == (rw << 1)) {
/* whoops... */
- printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+ printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
drive->name, __func__);
ide_pad_transfer(drive, rw, len);
@@ -637,7 +680,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
return 0;
} else {
/* drive wants a command packet, or invalid ireason... */
- printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+ printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
drive->name, __func__, ireason);
}
@@ -654,17 +697,19 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
*/
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
+ ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);
+
if ((len % SECTOR_SIZE) == 0)
return 0;
- printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
- drive->name, __func__, len);
+ printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
+ __func__, len);
if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
- printk(KERN_ERR " This drive is not supported by "
- "this version of the driver\n");
+ printk(KERN_ERR PFX "This drive is not supported by this "
+ "version of the driver\n");
else {
- printk(KERN_ERR " Trying to limit transfer sizes\n");
+ printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
}
@@ -676,6 +721,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
struct request *rq)
{
+ ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
+ rq->cmd_flags);
+
if (rq_data_dir(rq) == READ) {
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
@@ -695,7 +743,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
/* sanity check... */
if (rq->current_nr_sectors !=
bio_cur_sectors(rq->bio)) {
- printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+ printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
drive->name, __func__,
rq->current_nr_sectors);
cdrom_end_request(drive, 0);
@@ -704,11 +752,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
rq->current_nr_sectors += nskip;
}
}
-#if 0
- else
- /* the immediate bit */
- rq->cmd[1] = 1 << 3;
-#endif
+
/* set up the command */
rq->timeout = ATAPI_WAIT_PC;
@@ -739,6 +783,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
int stat;
static int retry = 10;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
@@ -746,7 +792,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0)
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
}
return ide_stopped;
}
@@ -755,6 +801,8 @@ static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
{
sector_t frame = rq->sector;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
memset(rq->cmd, 0, BLK_MAX_CDB);
@@ -775,8 +823,11 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
* Fix up a possibly partially-processed request so that we can start it over
* entirely, or even put it back on the request queue.
*/
-static void restore_request(struct request *rq)
+static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
{
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (rq->buffer != bio_data(rq->bio)) {
sector_t n =
(rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
@@ -795,8 +846,11 @@ static void restore_request(struct request *rq)
/*
* All other packet commands.
*/
-static void ide_cd_request_sense_fixup(struct request *rq)
+static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
{
+
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
/*
* Some of the trailing request sense fields are optional,
* and some drives don't send them. Sigh.
@@ -822,6 +876,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
if (!sense)
sense = &local_sense;
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
+ "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
+ timeout, cmd_flags);
+
/* start of retry loop */
do {
struct request *rq;
@@ -895,7 +953,6 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct cdrom_info *info = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
@@ -905,13 +962,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
u16 len;
u8 ireason;
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
+ __func__, rq->cmd[0], write);
+
/* check for errors */
- dma = info->dma;
+ dma = drive->dma;
if (dma) {
- info->dma = 0;
+ drive->dma = 0;
dma_error = hwif->dma_ops->dma_end(drive);
if (dma_error) {
- printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+ printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
write ? "write" : "read");
ide_dma_off(drive);
}
@@ -937,8 +997,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (thislen > len)
thislen = len;
+ ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
+ __func__, stat, thislen);
+
/* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
+ if ((stat & ATA_DRQ) == 0) {
if (blk_fs_request(rq)) {
/*
* If we're not done reading/writing, complain.
@@ -946,7 +1009,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
*/
uptodate = 1;
if (rq->current_nr_sectors > 0) {
- printk(KERN_ERR "%s: %s: data underrun "
+ printk(KERN_ERR PFX "%s: %s: data underrun "
"(%d blocks)\n",
drive->name, __func__,
rq->current_nr_sectors);
@@ -957,7 +1020,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
cdrom_end_request(drive, uptodate);
return ide_stopped;
} else if (!blk_pc_request(rq)) {
- ide_cd_request_sense_fixup(rq);
+ ide_cd_request_sense_fixup(drive, rq);
/* complain if we still have data left to transfer */
uptodate = rq->data_len ? 0 : 1;
}
@@ -1000,6 +1063,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
xferfunc = hwif->tp_ops->input_data;
}
+ ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
+ "ireason: 0x%x\n", __func__, rq->cmd_type, ireason);
+
/* transfer data */
while (thislen > 0) {
u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
@@ -1024,7 +1090,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
*/
ide_pad_transfer(drive, 0, thislen);
else {
- printk(KERN_ERR "%s: confused, missing data\n",
+ printk(KERN_ERR PFX "%s: confused, missing data\n",
drive->name);
blk_dump_rq_flags(rq, rq_data_dir(rq)
? "cdrom_newpc_intr, write"
@@ -1111,9 +1177,12 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ ide_debug_log(IDE_DBG_RQ, "Call %s, write: 0x%x, secs_per_frame: %u\n",
+ __func__, write, sectors_per_frame);
+
if (write) {
/* disk has become write protected */
- if (cd->disk->policy) {
+ if (get_disk_ro(cd->disk)) {
cdrom_end_request(drive, 0);
return ide_stopped;
}
@@ -1122,7 +1191,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
* We may be retrying this request after an error. Fix up any
* weirdness which might be present in the request packet.
*/
- restore_request(rq);
+ ide_cd_restore_request(drive, rq);
}
/* use DMA, if possible / writes *must* be hardware frame aligned */
@@ -1132,9 +1201,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
cdrom_end_request(drive, 0);
return ide_stopped;
}
- cd->dma = 0;
+ drive->dma = 0;
} else
- cd->dma = drive->using_dma;
+ drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
if (write)
cd->devinfo.media_written = 1;
@@ -1151,28 +1220,29 @@ static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
- struct cdrom_info *info = drive->driver_data;
+
+ ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd_type: 0x%x\n", __func__,
+ rq->cmd_type);
if (blk_pc_request(rq))
rq->cmd_flags |= REQ_QUIET;
else
rq->cmd_flags &= ~REQ_FAILED;
- info->dma = 0;
+ drive->dma = 0;
/* sg request */
if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
struct request_queue *q = drive->queue;
unsigned int alignment;
- unsigned long addr;
- unsigned long stack_mask = ~(THREAD_SIZE - 1);
+ char *buf;
if (rq->bio)
- addr = (unsigned long)bio_data(rq->bio);
+ buf = bio_data(rq->bio);
else
- addr = (unsigned long)rq->data;
+ buf = rq->data;
- info->dma = drive->using_dma;
+ drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
/*
* check if dma is safe
@@ -1181,12 +1251,9 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
* separate masks.
*/
alignment = queue_dma_alignment(q) | q->dma_pad_mask;
- if (addr & alignment || rq->data_len & alignment)
- info->dma = 0;
-
- if (!((addr & stack_mask) ^
- ((unsigned long)current->stack & stack_mask)))
- info->dma = 0;
+ if ((unsigned long)buf & alignment || rq->data_len & alignment
+ || object_is_on_stack(buf))
+ drive->dma = 0;
}
}
@@ -1200,19 +1267,22 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
ide_handler_t *fn;
int xferlen;
+ ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd_type: 0x%x, block: %llu\n",
+ __func__, rq->cmd_type, (unsigned long long)block);
+
if (blk_fs_request(rq)) {
if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
ide_hwif_t *hwif = drive->hwif;
unsigned long elapsed = jiffies - info->start_seek;
int stat = hwif->tp_ops->read_status(hwif);
- if ((stat & SEEK_STAT) != SEEK_STAT) {
+ if ((stat & ATA_DSC) != ATA_DSC) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
ide_stall_queue(drive,
IDECD_SEEK_TIMER);
return ide_stopped;
}
- printk(KERN_ERR "%s: DSC timeout\n",
+ printk(KERN_ERR PFX "%s: DSC timeout\n",
drive->name);
}
drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
@@ -1220,11 +1290,11 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
if (rq_data_dir(rq) == READ &&
IDE_LARGE_SEEK(info->last_block, block,
IDECD_SEEK_THRESHOLD) &&
- drive->dsc_overlap) {
+ (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
xferlen = 0;
fn = cdrom_start_seek_continuation;
- info->dma = 0;
+ drive->dma = 0;
info->start_seek = jiffies;
ide_cd_prepare_seek_request(drive, rq);
@@ -1253,7 +1323,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
cdrom_end_request(drive, 1);
return ide_stopped;
} else {
- blk_dump_rq_flags(rq, "ide-cd bad flags");
+ blk_dump_rq_flags(rq, DRV_NAME " bad flags");
cdrom_end_request(drive, 0);
return ide_stopped;
}
@@ -1283,6 +1353,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
struct cdrom_device_info *cdi = &info->devinfo;
unsigned char cmd[BLK_MAX_CDB];
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
memset(cmd, 0, BLK_MAX_CDB);
cmd[0] = GPCMD_TEST_UNIT_READY;
@@ -1309,6 +1381,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
unsigned len = sizeof(capbuf);
u32 blocklen;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
memset(cmd, 0, BLK_MAX_CDB);
cmd[0] = GPCMD_READ_CDVD_CAPACITY;
@@ -1328,10 +1402,10 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
case 4096:
break;
default:
- printk(KERN_ERR "%s: weird block size %u\n",
- drive->name, blocklen);
- printk(KERN_ERR "%s: default to 2kb block size\n",
- drive->name);
+ printk(KERN_ERR PFX "%s: weird block size %u\n",
+ drive->name, blocklen);
+ printk(KERN_ERR PFX "%s: default to 2kb block size\n",
+ drive->name);
blocklen = 2048;
break;
}
@@ -1347,6 +1421,8 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
{
unsigned char cmd[BLK_MAX_CDB];
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
memset(cmd, 0, BLK_MAX_CDB);
cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
@@ -1375,11 +1451,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
long last_written;
unsigned long sectors_per_frame = SECTORS_PER_FRAME;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (toc == NULL) {
/* try to allocate space */
toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
if (toc == NULL) {
- printk(KERN_ERR "%s: No cdrom TOC buffer!\n",
+ printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
drive->name);
return -ENOMEM;
}
@@ -1535,6 +1613,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
struct packet_command cgc;
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
@@ -1553,6 +1633,8 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
struct cdrom_info *cd = drive->driver_data;
u16 curspeed, maxspeed;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
@@ -1593,6 +1675,8 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *devinfo = &info->devinfo;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);
+
devinfo->ops = &ide_cdrom_dops;
devinfo->speed = info->current_speed;
devinfo->capacity = nslots;
@@ -1614,13 +1698,17 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
mechtype_t mechtype;
int nslots = 1;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
+ "drive->atapi_flags: 0x%lx\n", __func__, drive->media,
+ drive->atapi_flags);
+
cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
CDC_MO_DRIVE | CDC_RAM);
if (drive->media == ide_optical) {
cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
- printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
+ printk(KERN_ERR PFX "%s: ATAPI magneto-optical drive\n",
drive->name);
return nslots;
}
@@ -1661,7 +1749,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
- if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
+ if (mechtype == mechtype_caddy ||
+ mechtype == mechtype_popup ||
+ (drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))
cdi->mask |= CDC_CLOSE_TRAY;
if (cdi->sanyo_slot > 0) {
@@ -1676,7 +1766,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
ide_cdrom_update_speed(drive, buf);
- printk(KERN_INFO "%s: ATAPI", drive->name);
+ printk(KERN_INFO PFX "%s: ATAPI", drive->name);
/* don't print speed if the drive reported 0 */
if (cd->max_speed)
@@ -1699,7 +1789,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
else
printk(KERN_CONT " drive");
- printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
+ printk(KERN_CONT ", %dkB Cache\n",
+ be16_to_cpup((__be16 *)&buf[8 + 12]));
return nslots;
}
@@ -1811,13 +1902,12 @@ static ide_proc_entry_t idecd_proc[] = {
{ NULL, 0, NULL, NULL }
};
-static void ide_cdrom_add_settings(ide_drive_t *drive)
-{
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
- &drive->dsc_overlap, NULL);
-}
-#else
-static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
+
+static const struct ide_proc_devset idecd_settings[] = {
+ IDE_PROC_DEVSET(dsc_overlap, 0, 1),
+ { 0 },
+};
#endif
static const struct cd_list_entry ide_cd_quirks_list[] = {
@@ -1859,17 +1949,19 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {
{ "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE },
{ NULL, NULL, 0 }
};
-static unsigned int ide_cd_flags(struct hd_driveid *id)
+static unsigned int ide_cd_flags(u16 *id)
{
const struct cd_list_entry *cle = ide_cd_quirks_list;
while (cle->id_model) {
- if (strcmp(cle->id_model, id->model) == 0 &&
+ if (strcmp(cle->id_model, (char *)&id[ATA_ID_PROD]) == 0 &&
(cle->id_firmware == NULL ||
- strstr(id->fw_rev, cle->id_firmware)))
+ strstr((char *)&id[ATA_ID_FW_REV], cle->id_firmware)))
return cle->cd_flags;
cle++;
}
@@ -1881,9 +1973,12 @@ static int ide_cdrom_setup(ide_drive_t *drive)
{
struct cdrom_info *cd = drive->driver_data;
struct cdrom_device_info *cdi = &cd->devinfo;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
+ char *fw_rev = (char *)&id[ATA_ID_FW_REV];
int nslots;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);
+
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
blk_queue_dma_alignment(drive->queue, 31);
blk_queue_update_dma_pad(drive->queue, 15);
@@ -1891,20 +1986,15 @@ static int ide_cdrom_setup(ide_drive_t *drive)
if (!drive->queue->unplug_delay)
drive->queue->unplug_delay = 1;
- drive->special.all = 0;
-
drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id);
- if ((id->config & 0x0060) == 0x20)
- drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
-
if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
- id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+ fw_rev[4] == '1' && fw_rev[6] <= '2')
drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
IDE_AFLAG_TOCADDR_AS_BCD);
else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
- id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+ fw_rev[4] == '1' && fw_rev[6] <= '2')
drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */
@@ -1915,15 +2005,19 @@ static int ide_cdrom_setup(ide_drive_t *drive)
/* set correct block size */
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
- drive->dsc_overlap = (drive->next != drive);
+ if (drive->next != drive)
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
if (ide_cdrom_register(drive, nslots)) {
- printk(KERN_ERR "%s: %s failed to register device with the"
+ printk(KERN_ERR PFX "%s: %s failed to register device with the"
" cdrom driver.\n", drive->name, __func__);
cd->devinfo.handle = NULL;
return 1;
}
- ide_cdrom_add_settings(drive);
+
+ ide_proc_register_driver(drive, cd->driver);
return 0;
}
@@ -1931,6 +2025,8 @@ static void ide_cd_remove(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
ide_proc_unregister_driver(drive, info->driver);
del_gendisk(info->disk);
@@ -1940,15 +2036,17 @@ static void ide_cd_remove(ide_drive_t *drive)
static void ide_cd_release(struct kref *kref)
{
- struct cdrom_info *info = to_ide_cd(kref);
+ struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
struct cdrom_device_info *devinfo = &info->devinfo;
ide_drive_t *drive = info->drive;
struct gendisk *g = info->disk;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
kfree(info->toc);
if (devinfo->handle == drive)
unregister_cdrom(devinfo);
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
g->private_data = NULL;
@@ -1967,13 +2065,12 @@ static ide_driver_t ide_cdrom_driver = {
.probe = ide_cd_probe,
.remove = ide_cd_remove,
.version = IDECD_VERSION,
- .media = ide_cdrom,
- .supports_dsc_overlap = 1,
.do_request = ide_cd_do_request,
.end_request = ide_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
.proc = idecd_proc,
+ .settings = idecd_settings,
#endif
};
@@ -1998,7 +2095,7 @@ static int idecd_open(struct inode *inode, struct file *file)
static int idecd_release(struct inode *inode, struct file *file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
cdrom_release(&info->devinfo, file);
@@ -2050,7 +2147,7 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
+ struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
int err;
switch (cmd) {
@@ -2071,13 +2168,13 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
static int idecd_media_changed(struct gendisk *disk)
{
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
return cdrom_media_changed(&info->devinfo);
}
static int idecd_revalidate_disk(struct gendisk *disk)
{
- struct cdrom_info *info = ide_cd_g(disk);
+ struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
struct request_sense sense;
ide_cd_read_toc(info->drive, &sense);
@@ -2096,8 +2193,11 @@ static struct block_device_operations idecd_ops = {
/* module options */
static char *ignore;
-
module_param(ignore, charp, 0400);
+
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
+
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
static int ide_cd_probe(ide_drive_t *drive)
@@ -2106,23 +2206,30 @@ static int ide_cd_probe(ide_drive_t *drive)
struct gendisk *g;
struct request_sense sense;
+ ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
+ "drive->media: 0x%x\n", __func__, drive->driver_req,
+ drive->media);
+
if (!strstr("ide-cdrom", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_cdrom && drive->media != ide_optical)
goto failed;
+
/* skip drives that we were told to ignore */
if (ignore != NULL) {
if (strstr(ignore, drive->name)) {
- printk(KERN_INFO "ide-cd: ignoring drive %s\n",
+ printk(KERN_INFO PFX "ignoring drive %s\n",
drive->name);
goto failed;
}
}
+
+ drive->debug_mask = debug_mask;
+
info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
- printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
+ printk(KERN_ERR PFX "%s: Can't allocate a cdrom structure\n",
drive->name);
goto failed;
}
@@ -2133,8 +2240,6 @@ static int ide_cd_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &ide_cdrom_driver);
-
kref_init(&info->kref);
info->drive = drive;
@@ -2149,7 +2254,6 @@ static int ide_cd_probe(ide_drive_t *drive)
g->driverfs_dev = &drive->gendev;
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) {
- ide_proc_unregister_driver(drive, &ide_cdrom_driver);
ide_cd_release(&info->kref);
goto failed;
}
@@ -2173,6 +2277,7 @@ static void __exit ide_cdrom_exit(void)
static int __init ide_cdrom_init(void)
{
+ printk(KERN_INFO DRV_NAME " driver " IDECD_VERSION "\n");
return driver_register(&ide_cdrom_driver.gen_driver);
}
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 61a4599b77d..5882b9a9ea8 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -88,7 +88,6 @@ struct cdrom_info {
struct request_sense sense_data;
struct request request_sense_request;
- int dma;
unsigned long last_block;
unsigned long start_seek;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 68b9cf0138b..3853bde8eed 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -30,10 +30,8 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/leds.h>
-
-#define _IDE_DISK
-
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -41,21 +39,18 @@
#include <asm/io.h>
#include <asm/div64.h>
-struct ide_disk_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-};
+#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
+#define IDE_DISK_MINORS (1 << PARTN_BITS)
+#else
+#define IDE_DISK_MINORS 0
+#endif
+
+#include "ide-disk.h"
static DEFINE_MUTEX(idedisk_ref_mutex);
#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
-#define ide_disk_g(disk) \
- container_of((disk)->private_data, struct ide_disk_obj, driver)
-
static void ide_disk_release(struct kref *);
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
@@ -84,68 +79,19 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
mutex_unlock(&idedisk_ref_mutex);
}
-/*
- * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
- * value for this drive (from its reported identification information).
- *
- * Returns: 1 if lba_capacity looks sensible
- * 0 otherwise
- *
- * It is called only once for each drive.
- */
-static int lba_capacity_is_ok(struct hd_driveid *id)
-{
- unsigned long lba_sects, chs_sects, head, tail;
-
- /* No non-LBA info .. so valid! */
- if (id->cyls == 0)
- return 1;
-
- /*
- * The ATA spec tells large drives to return
- * C/H/S = 16383/16/63 independent of their size.
- * Some drives can be jumpered to use 15 heads instead of 16.
- * Some drives can be jumpered to use 4092 cyls instead of 16383.
- */
- if ((id->cyls == 16383
- || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
- id->sectors == 63 &&
- (id->heads == 15 || id->heads == 16) &&
- (id->lba_capacity >= 16383*63*id->heads))
- return 1;
-
- lba_sects = id->lba_capacity;
- chs_sects = id->cyls * id->heads * id->sectors;
-
- /* perform a rough sanity check on lba_sects: within 10% is OK */
- if ((lba_sects - chs_sects) < chs_sects/10)
- return 1;
-
- /* some drives have the word order reversed */
- head = ((lba_sects >> 16) & 0xffff);
- tail = (lba_sects & 0xffff);
- lba_sects = (head | (tail << 16));
- if ((lba_sects - chs_sects) < chs_sects/10) {
- id->lba_capacity = lba_sects;
- return 1; /* lba_capacity is (now) good */
- }
-
- return 0; /* lba_capacity value may be bad */
-}
-
static const u8 ide_rw_cmds[] = {
- WIN_MULTREAD,
- WIN_MULTWRITE,
- WIN_MULTREAD_EXT,
- WIN_MULTWRITE_EXT,
- WIN_READ,
- WIN_WRITE,
- WIN_READ_EXT,
- WIN_WRITE_EXT,
- WIN_READDMA,
- WIN_WRITEDMA,
- WIN_READDMA_EXT,
- WIN_WRITEDMA_EXT,
+ ATA_CMD_READ_MULTI,
+ ATA_CMD_WRITE_MULTI,
+ ATA_CMD_READ_MULTI_EXT,
+ ATA_CMD_WRITE_MULTI_EXT,
+ ATA_CMD_PIO_READ,
+ ATA_CMD_PIO_WRITE,
+ ATA_CMD_PIO_READ_EXT,
+ ATA_CMD_PIO_WRITE_EXT,
+ ATA_CMD_READ,
+ ATA_CMD_WRITE,
+ ATA_CMD_READ_EXT,
+ ATA_CMD_WRITE_EXT,
};
static const u8 ide_data_phases[] = {
@@ -185,9 +131,9 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
sector_t block)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int dma = drive->using_dma;
u16 nsectors = (u16)rq->nr_sectors;
- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
+ u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
+ u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
ide_task_t task;
struct ide_taskfile *tf = &task.tf;
ide_startstop_t rc;
@@ -207,7 +153,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
memset(&task, 0, sizeof(task));
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- if (drive->select.b.lba) {
+ if (drive->dev_flags & IDE_DFLAG_LBA) {
if (lba48) {
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
@@ -232,6 +178,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
tf->lbah = block >>= 8;
tf->device = (block >> 8) & 0xf;
}
+
+ tf->device |= ATA_LBA;
} else {
unsigned int sect, head, cyl, track;
@@ -282,7 +230,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
{
ide_hwif_t *hwif = HWIF(drive);
- BUG_ON(drive->blocked);
+ BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
if (!blk_fs_request(rq)) {
blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
@@ -316,9 +264,9 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(ide_task_t));
if (lba48)
- tf->command = WIN_READ_NATIVE_MAX_EXT;
+ tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
else
- tf->command = WIN_READ_NATIVE_MAX;
+ tf->command = ATA_CMD_READ_NATIVE_MAX;
tf->device = ATA_LBA;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
if (lba48)
@@ -353,10 +301,10 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
tf->hob_lbal = (addr_req >>= 8) & 0xff;
tf->hob_lbam = (addr_req >>= 8) & 0xff;
tf->hob_lbah = (addr_req >>= 8) & 0xff;
- tf->command = WIN_SET_MAX_EXT;
+ tf->command = ATA_CMD_SET_MAX_EXT;
} else {
tf->device = (addr_req >>= 8) & 0x0f;
- tf->command = WIN_SET_MAX;
+ tf->command = ATA_CMD_SET_MAX;
}
tf->device |= ATA_LBA;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
@@ -379,25 +327,6 @@ static unsigned long long sectors_to_MB(unsigned long long n)
}
/*
- * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
- * so on non-buggy drives we need test only one.
- * However, we should also check whether these fields are valid.
- */
-static inline int idedisk_supports_hpa(const struct hd_driveid *id)
-{
- return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
-}
-
-/*
- * The same here.
- */
-static inline int idedisk_supports_lba48(const struct hd_driveid *id)
-{
- return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)
- && id->lba_capacity_2;
-}
-
-/*
* Some disks report total number of sectors instead of
* maximum sector address. We list them here.
*/
@@ -411,7 +340,7 @@ static const struct drive_list_entry hpa_list[] = {
static void idedisk_check_hpa(ide_drive_t *drive)
{
unsigned long long capacity, set_max;
- int lba48 = idedisk_supports_lba48(drive->id);
+ int lba48 = ata_id_lba48_enabled(drive->id);
capacity = drive->capacity64;
@@ -445,155 +374,42 @@ static void idedisk_check_hpa(ide_drive_t *drive)
}
}
-/*
- * Compute drive->capacity, the full capacity of the drive
- * Called with drive->id != NULL.
- *
- * To compute capacity, this uses either of
- *
- * 1. CHS value set by user (whatever user sets will be trusted)
- * 2. LBA value from target drive (require new ATA feature)
- * 3. LBA value from system BIOS (new one is OK, old one may break)
- * 4. CHS value from system BIOS (traditional style)
- *
- * in above order (i.e., if value of higher priority is available,
- * reset will be ignored).
- */
static void init_idedisk_capacity(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
- /*
- * If this drive supports the Host Protected Area feature set,
- * then we may need to change our opinion about the drive's capacity.
- */
- int hpa = idedisk_supports_hpa(id);
+ u16 *id = drive->id;
+ int lba;
- if (idedisk_supports_lba48(id)) {
+ if (ata_id_lba48_enabled(id)) {
/* drive speaks 48-bit LBA */
- drive->select.b.lba = 1;
- drive->capacity64 = id->lba_capacity_2;
- if (hpa)
- idedisk_check_hpa(drive);
- } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
+ lba = 1;
+ drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
+ } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
/* drive speaks 28-bit LBA */
- drive->select.b.lba = 1;
- drive->capacity64 = id->lba_capacity;
- if (hpa)
- idedisk_check_hpa(drive);
+ lba = 1;
+ drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
} else {
/* drive speaks boring old 28-bit CHS */
+ lba = 0;
drive->capacity64 = drive->cyl * drive->head * drive->sect;
}
-}
-
-static sector_t idedisk_capacity(ide_drive_t *drive)
-{
- return drive->capacity64 - drive->sect0;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-static int smart_enable(ide_drive_t *drive)
-{
- ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
-
- memset(&args, 0, sizeof(ide_task_t));
- tf->feature = SMART_ENABLE;
- tf->lbam = SMART_LCYL_PASS;
- tf->lbah = SMART_HCYL_PASS;
- tf->command = WIN_SMART;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- return ide_no_data_taskfile(drive, &args);
-}
-
-static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
-{
- ide_task_t args;
- struct ide_taskfile *tf = &args.tf;
-
- memset(&args, 0, sizeof(ide_task_t));
- tf->feature = sub_cmd;
- tf->nsect = 0x01;
- tf->lbam = SMART_LCYL_PASS;
- tf->lbah = SMART_HCYL_PASS;
- tf->command = WIN_SMART;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- args.data_phase = TASKFILE_IN;
- (void) smart_enable(drive);
- return ide_raw_taskfile(drive, &args, buf, 1);
-}
-
-static int proc_idedisk_read_cache
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *) data;
- char *out = page;
- int len;
-
- if (drive->id_read)
- len = sprintf(out, "%i\n", drive->id->buf_size / 2);
- else
- len = sprintf(out, "(none)\n");
-
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-static int proc_idedisk_read_capacity
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t*drive = (ide_drive_t *)data;
- int len;
-
- len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
+ if (lba) {
+ drive->dev_flags |= IDE_DFLAG_LBA;
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_read_smart(char *page, char **start, off_t off,
- int count, int *eof, void *data, u8 sub_cmd)
-{
- ide_drive_t *drive = (ide_drive_t *)data;
- int len = 0, i = 0;
-
- if (get_smart_data(drive, page, sub_cmd) == 0) {
- unsigned short *val = (unsigned short *) page;
- char *out = ((char *)val) + (SECTOR_WORDS * 4);
- page = out;
- do {
- out += sprintf(out, "%04x%c", le16_to_cpu(*val),
- (++i & 7) ? ' ' : '\n');
- val += 1;
- } while (i < (SECTOR_WORDS * 2));
- len = out - page;
+ /*
+ * If this device supports the Host Protected Area feature set,
+ * then we may need to change our opinion about its capacity.
+ */
+ if (ata_id_hpa_enabled(id))
+ idedisk_check_hpa(drive);
}
-
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
-static int proc_idedisk_read_sv
- (char *page, char **start, off_t off, int count, int *eof, void *data)
+sector_t ide_disk_capacity(ide_drive_t *drive)
{
- return proc_idedisk_read_smart(page, start, off, count, eof, data,
- SMART_READ_VALUES);
+ return drive->capacity64;
}
-static int proc_idedisk_read_st
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- return proc_idedisk_read_smart(page, start, off, count, eof, data,
- SMART_READ_THRESHOLDS);
-}
-
-static ide_proc_entry_t idedisk_proc[] = {
- { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
- { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
- { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
- { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
- { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
@@ -603,11 +419,11 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
BUG_ON(task == NULL);
memset(task, 0, sizeof(*task));
- if (ide_id_has_flush_cache_ext(drive->id) &&
+ if (ata_id_flush_ext_enabled(drive->id) &&
(drive->capacity64 >= (1UL << 28)))
- task->tf.command = WIN_FLUSH_CACHE_EXT;
+ task->tf.command = ATA_CMD_FLUSH_EXT;
else
- task->tf.command = WIN_FLUSH_CACHE;
+ task->tf.command = ATA_CMD_FLUSH;
task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
IDE_TFLAG_DYN;
task->data_phase = TASKFILE_NO_DATA;
@@ -617,6 +433,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
rq->special = task;
}
+ide_devset_get(multcount, mult_count);
+
/*
* This is tightly woven into the driver->do_special can not touch.
* DON'T do it again until a total personality rewrite is committed.
@@ -626,7 +444,7 @@ static int set_multcount(ide_drive_t *drive, int arg)
struct request *rq;
int error;
- if (arg < 0 || arg > drive->id->max_multsect)
+ if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
return -EINVAL;
if (drive->special.b.set_multmode)
@@ -643,26 +461,43 @@ static int set_multcount(ide_drive_t *drive, int arg)
return (drive->mult_count == arg) ? 0 : -EIO;
}
+ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
+
static int set_nowerr(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->nowerr = arg;
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_NOWERR;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_NOWERR;
+
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irq(&ide_lock);
+
return 0;
}
+static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf.feature = feature;
+ task.tf.nsect = nsect;
+ task.tf.command = ATA_CMD_SET_FEATURES;
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ return ide_no_data_taskfile(drive, &task);
+}
+
static void update_ordered(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
unsigned ordered = QUEUE_ORDERED_NONE;
prepare_flush_fn *prep_fn = NULL;
- if (drive->wcache) {
+ if (drive->dev_flags & IDE_DFLAG_WCACHE) {
unsigned long long capacity;
int barrier;
/*
@@ -673,10 +508,12 @@ static void update_ordered(ide_drive_t *drive)
* 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->noflush &&
- (drive->addressing == 0 || capacity <= (1ULL << 28) ||
- ide_id_has_flush_cache_ext(id));
+ capacity = ide_disk_capacity(drive);
+ barrier = ata_id_flush_enabled(id) &&
+ (drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
+ ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
+ capacity <= (1ULL << 28) ||
+ ata_id_flush_ext_enabled(id));
printk(KERN_INFO "%s: cache flushes %ssupported\n",
drive->name, barrier ? "" : "not ");
@@ -691,23 +528,24 @@ static void update_ordered(ide_drive_t *drive)
blk_queue_ordered(drive->queue, ordered, prep_fn);
}
-static int write_cache(ide_drive_t *drive, int arg)
+ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
+
+static int set_wcache(ide_drive_t *drive, int arg)
{
- ide_task_t args;
int err = 1;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_id_has_flush_cache(drive->id)) {
- memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ?
- SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- args.tf.command = WIN_SETFEATURES;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- err = ide_no_data_taskfile(drive, &args);
- if (err == 0)
- drive->wcache = arg;
+ if (ata_id_flush_enabled(drive->id)) {
+ err = ide_do_setfeature(drive,
+ arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
+ if (err == 0) {
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_WCACHE;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_WCACHE;
+ }
}
update_ordered(drive);
@@ -720,108 +558,88 @@ static int do_idedisk_flushcache(ide_drive_t *drive)
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- if (ide_id_has_flush_cache_ext(drive->id))
- args.tf.command = WIN_FLUSH_CACHE_EXT;
+ if (ata_id_flush_ext_enabled(drive->id))
+ args.tf.command = ATA_CMD_FLUSH_EXT;
else
- args.tf.command = WIN_FLUSH_CACHE;
+ args.tf.command = ATA_CMD_FLUSH;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
return ide_no_data_taskfile(drive, &args);
}
+ide_devset_get(acoustic, acoustic);
+
static int set_acoustic(ide_drive_t *drive, int arg)
{
- ide_task_t args;
-
if (arg < 0 || arg > 254)
return -EINVAL;
- memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
- args.tf.nsect = arg;
- args.tf.command = WIN_SETFEATURES;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- ide_no_data_taskfile(drive, &args);
+ ide_do_setfeature(drive,
+ arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
+
drive->acoustic = arg;
+
return 0;
}
+ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
+
/*
* drive->addressing:
* 0: 28-bit
* 1: 48-bit
* 2: 48-bit capable doing 28-bit
*/
-static int set_lba_addressing(ide_drive_t *drive, int arg)
+static int set_addressing(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 2)
return -EINVAL;
- drive->addressing = 0;
+ if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+ ata_id_lba48_enabled(drive->id) == 0))
+ return -EIO;
- if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
- return 0;
+ if (arg == 2)
+ arg = 0;
+
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_LBA48;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_LBA48;
- if (!idedisk_supports_lba48(drive->id))
- return -EIO;
- drive->addressing = arg;
return 0;
}
-#ifdef CONFIG_IDE_PROC_FS
-static void idedisk_add_settings(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
- &drive->bios_cyl, NULL);
- ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
- &drive->bios_head, NULL);
- ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
- &drive->bios_sect, NULL);
- ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
- &drive->addressing, set_lba_addressing);
- ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
- id->max_multsect, 1, 1, &drive->mult_count,
- set_multcount);
- ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
- &drive->nowerr, set_nowerr);
- ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
- &drive->lun, NULL);
- ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
- &drive->wcache, write_cache);
- ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
- &drive->acoustic, set_acoustic);
- ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
- &drive->failures, NULL);
- ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
- 1, 1, &drive->max_failures, NULL);
-}
-#else
-static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
-#endif
+ide_ext_devset_rw(acoustic, acoustic);
+ide_ext_devset_rw(address, addressing);
+ide_ext_devset_rw(multcount, multcount);
+ide_ext_devset_rw(wcache, wcache);
+
+ide_ext_devset_rw_sync(nowerr, nowerr);
static void idedisk_setup(ide_drive_t *drive)
{
+ struct ide_disk_obj *idkp = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
unsigned long long capacity;
- idedisk_add_settings(drive);
+ ide_proc_register_driver(drive, idkp->driver);
- if (drive->id_read == 0)
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
return;
- if (drive->removable) {
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
/*
* Removable disks (eg. SYQUEST); ignore 'WD' drives
*/
- if (id->model[0] != 'W' || id->model[1] != 'D')
- drive->doorlocking = 1;
+ if (m[0] != 'W' || m[1] != 'D')
+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
}
- (void)set_lba_addressing(drive, 1);
+ (void)set_addressing(drive, 1);
- if (drive->addressing == 1) {
+ if (drive->dev_flags & IDE_DFLAG_LBA48) {
int max_s = 2048;
if (max_s > hwif->rqsize)
@@ -837,7 +655,8 @@ static void idedisk_setup(ide_drive_t *drive)
init_idedisk_capacity(drive);
/* limit drive capacity to 137GB if LBA48 cannot be used */
- if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
+ drive->capacity64 > 1ULL << 28) {
printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
"%llu sectors (%llu MB)\n",
drive->name, (unsigned long long)drive->capacity64,
@@ -845,24 +664,24 @@ static void idedisk_setup(ide_drive_t *drive)
drive->capacity64 = 1ULL << 28;
}
- if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
+ (drive->dev_flags & IDE_DFLAG_LBA48)) {
if (drive->capacity64 > 1ULL << 28) {
printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
" will be used for accessing sectors "
"> %u\n", drive->name, 1 << 28);
} else
- drive->addressing = 0;
+ drive->dev_flags &= ~IDE_DFLAG_LBA48;
}
/*
* if possible, give fdisk access to more of the drive,
* by correcting bios_cyls:
*/
- capacity = idedisk_capacity(drive);
-
- if (!drive->forced_geom) {
+ capacity = ide_disk_capacity(drive);
- if (idedisk_supports_lba48(drive->id)) {
+ if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
+ if (ata_id_lba48_enabled(drive->id)) {
/* compatibility */
drive->bios_sect = 63;
drive->bios_head = 255;
@@ -888,22 +707,23 @@ static void idedisk_setup(ide_drive_t *drive)
drive->name, capacity, sectors_to_MB(capacity));
/* Only print cache size when it was specified */
- if (id->buf_size)
- printk(KERN_CONT " w/%dKiB Cache", id->buf_size / 2);
+ if (id[ATA_ID_BUF_SIZE])
+ printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);
printk(KERN_CONT ", CHS=%d/%d/%d\n",
drive->bios_cyl, drive->bios_head, drive->bios_sect);
/* write cache enabled? */
- if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
- drive->wcache = 1;
+ if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
+ drive->dev_flags |= IDE_DFLAG_WCACHE;
- write_cache(drive, 1);
+ set_wcache(drive, 1);
}
static void ide_cacheflush_p(ide_drive_t *drive)
{
- if (!drive->wcache || !ide_id_has_flush_cache(drive->id))
+ if (ata_id_flush_enabled(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
return;
if (do_idedisk_flushcache(drive))
@@ -945,7 +765,7 @@ static int ide_disk_probe(ide_drive_t *drive);
*/
static void ide_disk_resume(ide_drive_t *drive)
{
- if (idedisk_supports_hpa(drive->id))
+ if (ata_id_hpa_enabled(drive->id))
init_idedisk_capacity(drive);
}
@@ -987,13 +807,12 @@ static ide_driver_t idedisk_driver = {
.resume = ide_disk_resume,
.shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
- .media = ide_disk,
- .supports_dsc_overlap = 0,
.do_request = ide_do_rw_disk,
.end_request = ide_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idedisk_proc,
+ .proc = ide_disk_proc,
+ .settings = ide_disk_settings,
#endif
};
@@ -1002,7 +821,7 @@ static int idedisk_set_doorlock(ide_drive_t *drive, int on)
ide_task_t task;
memset(&task, 0, sizeof(task));
- task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
+ task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
return ide_no_data_taskfile(drive, &task);
@@ -1022,15 +841,16 @@ static int idedisk_open(struct inode *inode, struct file *filp)
idkp->openers++;
- if (drive->removable && idkp->openers == 1) {
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
check_disk_change(inode->i_bdev);
/*
* Ignore the return code from door_lock,
* since the open() has already succeeded,
* and the door_lock is irrelevant at this point.
*/
- if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
- drive->doorlocking = 0;
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+ idedisk_set_doorlock(drive, 1))
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
}
return 0;
}
@@ -1044,9 +864,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
if (idkp->openers == 1)
ide_cacheflush_p(drive);
- if (drive->removable && idkp->openers == 1) {
- if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
- drive->doorlocking = 0;
+ if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
+ if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+ idedisk_set_doorlock(drive, 0))
+ drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
}
idkp->openers--;
@@ -1067,72 +888,25 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int idedisk_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- struct block_device *bdev = inode->i_bdev;
- struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
- ide_drive_t *drive = idkp->drive;
- int err, (*setfunc)(ide_drive_t *, int);
- u8 *val;
-
- switch (cmd) {
- case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val;
- case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val;
- case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val;
- case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val;
- case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val;
- case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
- case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
- case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
- case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val;
- case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
- }
-
- return generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = *val;
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
-}
-
static int idedisk_media_changed(struct gendisk *disk)
{
struct ide_disk_obj *idkp = ide_disk_g(disk);
ide_drive_t *drive = idkp->drive;
/* do not scan partitions twice if this is a removable device */
- if (drive->attach) {
- drive->attach = 0;
+ if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
return 0;
}
+
/* if removable, always assume it was changed */
- return drive->removable;
+ return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
}
static int idedisk_revalidate_disk(struct gendisk *disk)
{
struct ide_disk_obj *idkp = ide_disk_g(disk);
- set_capacity(disk, idedisk_capacity(idkp->drive));
+ set_capacity(disk, ide_disk_capacity(idkp->drive));
return 0;
}
@@ -1140,7 +914,7 @@ static struct block_device_operations idedisk_ops = {
.owner = THIS_MODULE,
.open = idedisk_open,
.release = idedisk_release,
- .ioctl = idedisk_ioctl,
+ .ioctl = ide_disk_ioctl,
.getgeo = idedisk_getgeo,
.media_changed = idedisk_media_changed,
.revalidate_disk = idedisk_revalidate_disk
@@ -1156,8 +930,7 @@ static int ide_disk_probe(ide_drive_t *drive)
/* strstr("foo", "") is non-NULL */
if (!strstr("ide-disk", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_disk)
goto failed;
@@ -1165,15 +938,12 @@ static int ide_disk_probe(ide_drive_t *drive)
if (!idkp)
goto failed;
- g = alloc_disk_node(1 << PARTN_BITS,
- hwif_to_node(drive->hwif));
+ g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
if (!g)
goto out_free_idkp;
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idedisk_driver);
-
kref_init(&idkp->kref);
idkp->drive = drive;
@@ -1185,17 +955,20 @@ static int ide_disk_probe(ide_drive_t *drive)
drive->driver_data = idkp;
idedisk_setup(drive);
- if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
+ (drive->head == 0 || drive->head > 16)) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
drive->name, drive->head);
- drive->attach = 0;
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
} else
- drive->attach = 1;
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
- g->minors = 1 << PARTN_BITS;
+ g->minors = IDE_DISK_MINORS;
g->driverfs_dev = &drive->gendev;
- g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
- set_capacity(g, idedisk_capacity(drive));
+ g->flags |= GENHD_FL_EXT_DEVT;
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
+ set_capacity(g, ide_disk_capacity(drive));
g->fops = &idedisk_ops;
add_disk(g);
return 0;
@@ -1217,6 +990,7 @@ static int __init idedisk_init(void)
}
MODULE_ALIAS("ide:*m-disk*");
+MODULE_ALIAS("ide-disk");
module_init(idedisk_init);
module_exit(idedisk_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.h b/drivers/ide/ide-disk.h
new file mode 100644
index 00000000000..a82fa435566
--- /dev/null
+++ b/drivers/ide/ide-disk.h
@@ -0,0 +1,32 @@
+#ifndef __IDE_DISK_H
+#define __IDE_DISK_H
+
+struct ide_disk_obj {
+ ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
+};
+
+#define ide_disk_g(disk) \
+ container_of((disk)->private_data, struct ide_disk_obj, driver)
+
+/* ide-disk.c */
+sector_t ide_disk_capacity(ide_drive_t *);
+ide_decl_devset(address);
+ide_decl_devset(multcount);
+ide_decl_devset(nowerr);
+ide_decl_devset(wcache);
+ide_decl_devset(acoustic);
+
+/* ide-disk_ioctl.c */
+int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-disk_proc.c */
+extern ide_proc_entry_t ide_disk_proc[];
+extern const struct ide_proc_devset ide_disk_settings[];
+#endif
+
+#endif /* __IDE_DISK_H */
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
new file mode 100644
index 00000000000..a6cf1a03a80
--- /dev/null
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
+{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
+{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
+{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
+{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
+{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
+{ 0 }
+};
+
+int ide_disk_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+ ide_drive_t *drive = idkp->drive;
+ int err;
+
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ return generic_ide_ioctl(drive, file, bdev, cmd, arg);
+}
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
new file mode 100644
index 00000000000..4724976afe7
--- /dev/null
+++ b/drivers/ide/ide-disk_proc.c
@@ -0,0 +1,129 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+static int smart_enable(ide_drive_t *drive)
+{
+ ide_task_t args;
+ struct ide_taskfile *tf = &args.tf;
+
+ memset(&args, 0, sizeof(ide_task_t));
+ tf->feature = ATA_SMART_ENABLE;
+ tf->lbam = ATA_SMART_LBAM_PASS;
+ tf->lbah = ATA_SMART_LBAH_PASS;
+ tf->command = ATA_CMD_SMART;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ return ide_no_data_taskfile(drive, &args);
+}
+
+static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
+{
+ ide_task_t args;
+ struct ide_taskfile *tf = &args.tf;
+
+ memset(&args, 0, sizeof(ide_task_t));
+ tf->feature = sub_cmd;
+ tf->nsect = 0x01;
+ tf->lbam = ATA_SMART_LBAM_PASS;
+ tf->lbah = ATA_SMART_LBAH_PASS;
+ tf->command = ATA_CMD_SMART;
+ args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ args.data_phase = TASKFILE_IN;
+ (void) smart_enable(drive);
+ return ide_raw_taskfile(drive, &args, buf, 1);
+}
+
+static int proc_idedisk_read_cache
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t *drive = (ide_drive_t *) data;
+ char *out = page;
+ int len;
+
+ if (drive->dev_flags & IDE_DFLAG_ID_READ)
+ len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
+ else
+ len = sprintf(out, "(none)\n");
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
+
+ len = sprintf(page, "%llu\n", (long long)ide_disk_capacity(drive));
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_smart(char *page, char **start, off_t off,
+ int count, int *eof, void *data, u8 sub_cmd)
+{
+ ide_drive_t *drive = (ide_drive_t *)data;
+ int len = 0, i = 0;
+
+ if (get_smart_data(drive, page, sub_cmd) == 0) {
+ unsigned short *val = (unsigned short *) page;
+ char *out = (char *)val + SECTOR_SIZE;
+
+ page = out;
+ do {
+ out += sprintf(out, "%04x%c", le16_to_cpu(*val),
+ (++i & 7) ? ' ' : '\n');
+ val += 1;
+ } while (i < SECTOR_SIZE / 2);
+ len = out - page;
+ }
+
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_sv
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ return proc_idedisk_read_smart(page, start, off, count, eof, data,
+ ATA_SMART_READ_VALUES);
+}
+
+static int proc_idedisk_read_st
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ return proc_idedisk_read_smart(page, start, off, count, eof, data,
+ ATA_SMART_READ_THRESHOLDS);
+}
+
+ide_proc_entry_t ide_disk_proc[] = {
+ { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
+ { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+ { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
+ { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(failures, failures);
+ide_devset_rw_field(lun, lun);
+ide_devset_rw_field(max_failures, max_failures);
+
+const struct ide_proc_devset ide_disk_settings[] = {
+ IDE_PROC_DEVSET(acoustic, 0, 254),
+ IDE_PROC_DEVSET(address, 0, 2),
+ IDE_PROC_DEVSET(bios_cyl, 0, 65535),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(failures, 0, 65535),
+ IDE_PROC_DEVSET(lun, 0, 7),
+ IDE_PROC_DEVSET(max_failures, 0, 65535),
+ IDE_PROC_DEVSET(multcount, 0, 16),
+ IDE_PROC_DEVSET(nowerr, 0, 1),
+ IDE_PROC_DEVSET(wcache, 0, 1),
+ { 0 },
+};
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
new file mode 100644
index 00000000000..0903782689e
--- /dev/null
+++ b/drivers/ide/ide-dma-sff.c
@@ -0,0 +1,356 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+/**
+ * config_drive_for_dma - attempt to activate IDE DMA
+ * @drive: the drive to place in DMA mode
+ *
+ * If the drive supports at least mode 2 DMA or UDMA of any kind
+ * then attempt to place it into DMA mode. Drives that are known to
+ * support DMA but predate the DMA properties or that are known
+ * to have DMA handling bugs are also set up appropriately based
+ * on the good/bad drive lists.
+ */
+
+int config_drive_for_dma(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u16 *id = drive->id;
+
+ if (drive->media != ide_disk) {
+ if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
+ return 0;
+ }
+
+ /*
+ * Enable DMA on any drive that has
+ * UltraDMA (mode 0/1/2/3/4/5/6) enabled
+ */
+ if ((id[ATA_ID_FIELD_VALID] & 4) &&
+ ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
+ return 1;
+
+ /*
+ * Enable DMA on any drive that has mode2 DMA
+ * (multi or single) enabled
+ */
+ if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
+ if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
+ (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
+ return 1;
+
+ /* Consult the list of known "good" drives */
+ if (ide_dma_good_drive(drive))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * ide_dma_host_set - Enable/disable DMA on a host
+ * @drive: drive to control
+ *
+ * Enable/disable DMA on an IDE controller following generic
+ * bus-mastering IDE controller behaviour.
+ */
+
+void ide_dma_host_set(ide_drive_t *drive, int on)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 unit = drive->dn & 1;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (on)
+ dma_stat |= (1 << (5 + unit));
+ else
+ dma_stat &= ~(1 << (5 + unit));
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(dma_stat,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_dma_host_set);
+
+/**
+ * ide_build_dmatable - build IDE DMA table
+ *
+ * ide_build_dmatable() prepares a dma request. We map the command
+ * to get the pci bus addresses of the buffers and then build up
+ * the PRD table that the IDE layer wants to be fed.
+ *
+ * Most chipsets correctly interpret a length of 0x0000 as 64KB,
+ * but at least one (e.g. CS5530) misinterprets it as zero (!).
+ * So we break the 64KB entry into two 32KB entries instead.
+ *
+ * Returns the number of built PRD entries if all went okay,
+ * returns 0 otherwise.
+ *
+ * May also be invoked from trm290.c
+ */
+
+int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ __le32 *table = (__le32 *)hwif->dmatable_cpu;
+ unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
+ unsigned int count = 0;
+ int i;
+ struct scatterlist *sg;
+
+ hwif->sg_nents = ide_build_sglist(drive, rq);
+ if (hwif->sg_nents == 0)
+ return 0;
+
+ for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+ u32 cur_addr, cur_len, xcount, bcount;
+
+ cur_addr = sg_dma_address(sg);
+ cur_len = sg_dma_len(sg);
+
+ /*
+ * Fill in the dma table, without crossing any 64kB boundaries.
+ * Most hardware requires 16-bit alignment of all blocks,
+ * but the trm290 requires 32-bit alignment.
+ */
+
+ while (cur_len) {
+ if (count++ >= PRD_ENTRIES)
+ goto use_pio_instead;
+
+ bcount = 0x10000 - (cur_addr & 0xffff);
+ if (bcount > cur_len)
+ bcount = cur_len;
+ *table++ = cpu_to_le32(cur_addr);
+ xcount = bcount & 0xffff;
+ if (is_trm290)
+ xcount = ((xcount >> 2) - 1) << 16;
+ if (xcount == 0x0000) {
+ if (count++ >= PRD_ENTRIES)
+ goto use_pio_instead;
+ *table++ = cpu_to_le32(0x8000);
+ *table++ = cpu_to_le32(cur_addr + 0x8000);
+ xcount = 0x8000;
+ }
+ *table++ = cpu_to_le32(xcount);
+ cur_addr += bcount;
+ cur_len -= bcount;
+ }
+ }
+
+ if (count) {
+ if (!is_trm290)
+ *--table |= cpu_to_le32(0x80000000);
+ return count;
+ }
+
+use_pio_instead:
+ printk(KERN_ERR "%s: %s\n", drive->name,
+ count ? "DMA table too small" : "empty DMA table?");
+
+ ide_destroy_dmatable(drive);
+
+ return 0; /* revert to PIO for this request */
+}
+EXPORT_SYMBOL_GPL(ide_build_dmatable);
+
+/**
+ * ide_dma_setup - begin a DMA phase
+ * @drive: target device
+ *
+ * Build an IDE DMA PRD (IDE speak for scatter gather table)
+ * and then set up the DMA transfer registers for a device
+ * that follows generic IDE PCI DMA behaviour. Controllers can
+ * override this function if they need to
+ *
+ * Returns 0 on success. If a PIO fallback is required then 1
+ * is returned.
+ */
+
+int ide_dma_setup(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ unsigned int reading;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 dma_stat;
+
+ if (rq_data_dir(rq))
+ reading = 0;
+ else
+ reading = 1 << 3;
+
+ /* fall back to pio! */
+ if (!ide_build_dmatable(drive, rq)) {
+ ide_map_sg(drive, rq);
+ return 1;
+ }
+
+ /* PRD table */
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writel(hwif->dmatable_dma,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
+ else
+ outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
+
+ /* specify r/w */
+ if (mmio)
+ writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ else
+ outb(reading, hwif->dma_base + ATA_DMA_CMD);
+
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ /* clear INTR & ERROR flags */
+ if (mmio)
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+ drive->waiting_for_dma = 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_setup);
+
+/**
+ * dma_timer_expiry - handle a DMA timeout
+ * @drive: Drive that timed out
+ *
+ * An IDE DMA transfer timed out. In the event of an error we ask
+ * the driver to resolve the problem, if a DMA transfer is still
+ * in progress we continue to wait (arguably we need to add a
+ * secondary 'I don't care what the drive thinks' timeout here)
+ * Finally if we have an interrupt we let it complete the I/O.
+ * But only one time - we clear expiry and if it's still not
+ * completed after WAIT_CMD, we error and retry in PIO.
+ * This can occur if an interrupt is lost or due to hang or bugs.
+ */
+
+static int dma_timer_expiry(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
+ drive->name, __func__, dma_stat);
+
+ if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
+ return WAIT_CMD;
+
+ hwif->hwgroup->expiry = NULL; /* one free ride for now */
+
+ /* 1 dmaing, 2 error, 4 intr */
+ if (dma_stat & 2) /* ERROR */
+ return -1;
+
+ if (dma_stat & 1) /* DMAing */
+ return WAIT_CMD;
+
+ if (dma_stat & 4) /* Got an Interrupt */
+ return WAIT_CMD;
+
+ return 0; /* Status is unknown -- reset the bus */
+}
+
+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+ /* issue cmd to drive */
+ ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
+ dma_timer_expiry);
+}
+EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+
+void ide_dma_start(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_cmd;
+
+ /* Note that this is done *after* the cmd has
+ * been issued to the drive, as per the BM-IDE spec.
+ * The Promise Ultra33 doesn't work correctly when
+ * we do this part before issuing the drive cmd.
+ */
+ if (hwif->host_flags & IDE_HFLAG_MMIO) {
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* start DMA */
+ writeb(dma_cmd | 1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
+ wmb();
+}
+EXPORT_SYMBOL_GPL(ide_dma_start);
+
+/* returns 1 on error, 0 otherwise */
+int ide_dma_end(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 dma_stat = 0, dma_cmd = 0;
+
+ drive->waiting_for_dma = 0;
+
+ if (mmio) {
+ /* get DMA command mode */
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* stop DMA */
+ writeb(dma_cmd & ~1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
+ /* get DMA status */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (mmio)
+ /* clear the INTR & ERROR bits */
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+ /* purge DMA mappings */
+ ide_destroy_dmatable(drive);
+ /* verify good DMA status */
+ wmb();
+ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_end);
+
+/* returns 1 if dma irq issued, 0 otherwise */
+int ide_dma_test_irq(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ /* return 1 if INTR asserted */
+ if ((dma_stat & 4) == 4)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_test_irq);
+
+const struct ide_dma_ops sff_dma_ops = {
+ .dma_host_set = ide_dma_host_set,
+ .dma_setup = ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = ide_dma_start,
+ .dma_end = ide_dma_end,
+ .dma_test_irq = ide_dma_test_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
+};
+EXPORT_SYMBOL_GPL(sff_dma_ops);
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index adc68275585..fffd11717b2 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -28,24 +28,13 @@
* for supplying a Promise UDMA board & WD UDMA drive for this work!
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
#include <linux/ide.h>
-#include <linux/delay.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-static const struct drive_list_entry drive_whitelist [] = {
-
+static const struct drive_list_entry drive_whitelist[] = {
{ "Micropolis 2112A" , NULL },
{ "CONNER CTMA 4000" , NULL },
{ "CONNER CTT8000-A" , NULL },
@@ -53,8 +42,7 @@ static const struct drive_list_entry drive_whitelist [] = {
{ NULL , NULL }
};
-static const struct drive_list_entry drive_blacklist [] = {
-
+static const struct drive_list_entry drive_blacklist[] = {
{ "WDC AC11000H" , NULL },
{ "WDC AC22100H" , NULL },
{ "WDC AC32500H" , NULL },
@@ -94,11 +82,11 @@ static const struct drive_list_entry drive_blacklist [] = {
* ide_dma_intr - IDE DMA interrupt handler
* @drive: the drive the interrupt is for
*
- * Handle an interrupt completing a read/write DMA transfer on an
+ * Handle an interrupt completing a read/write DMA transfer on an
* IDE device
*/
-
-ide_startstop_t ide_dma_intr (ide_drive_t *drive)
+
+ide_startstop_t ide_dma_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 stat = 0, dma_stat = 0;
@@ -106,22 +94,21 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
dma_stat = hwif->dma_ops->dma_end(drive);
stat = hwif->tp_ops->read_status(hwif);
- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
if (!dma_stat) {
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = hwif->hwgroup->rq;
task_end_request(drive, rq, stat);
return ide_stopped;
}
- printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
- drive->name, dma_stat);
+ printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
+ drive->name, __func__, dma_stat);
}
return ide_error(drive, "dma_intr", stat);
}
-
EXPORT_SYMBOL_GPL(ide_dma_intr);
-static int ide_dma_good_drive(ide_drive_t *drive)
+int ide_dma_good_drive(ide_drive_t *drive)
{
return ide_in_drive_list(drive->id, drive_whitelist);
}
@@ -139,7 +126,7 @@ static int ide_dma_good_drive(ide_drive_t *drive)
int ide_build_sglist(ide_drive_t *drive, struct request *rq)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table;
ide_map_sg(drive, rq);
@@ -152,106 +139,8 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
hwif->sg_dma_direction);
}
-
EXPORT_SYMBOL_GPL(ide_build_sglist);
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- * ide_build_dmatable - build IDE DMA table
- *
- * ide_build_dmatable() prepares a dma request. We map the command
- * to get the pci bus addresses of the buffers and then build up
- * the PRD table that the IDE layer wants to be fed. The code
- * knows about the 64K wrap bug in the CS5530.
- *
- * Returns the number of built PRD entries if all went okay,
- * returns 0 otherwise.
- *
- * May also be invoked from trm290.c
- */
-
-int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = HWIF(drive);
- __le32 *table = (__le32 *)hwif->dmatable_cpu;
- unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
- unsigned int count = 0;
- int i;
- struct scatterlist *sg;
-
- hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
- if (!i)
- return 0;
-
- sg = hwif->sg_table;
- while (i) {
- u32 cur_addr;
- u32 cur_len;
-
- cur_addr = sg_dma_address(sg);
- cur_len = sg_dma_len(sg);
-
- /*
- * Fill in the dma table, without crossing any 64kB boundaries.
- * Most hardware requires 16-bit alignment of all blocks,
- * but the trm290 requires 32-bit alignment.
- */
-
- while (cur_len) {
- if (count++ >= PRD_ENTRIES) {
- printk(KERN_ERR "%s: DMA table too small\n", drive->name);
- goto use_pio_instead;
- } else {
- u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
- if (bcount > cur_len)
- bcount = cur_len;
- *table++ = cpu_to_le32(cur_addr);
- xcount = bcount & 0xffff;
- if (is_trm290)
- xcount = ((xcount >> 2) - 1) << 16;
- if (xcount == 0x0000) {
- /*
- * Most chipsets correctly interpret a length of 0x0000 as 64KB,
- * but at least one (e.g. CS5530) misinterprets it as zero (!).
- * So here we break the 64KB entry into two 32KB entries instead.
- */
- if (count++ >= PRD_ENTRIES) {
- printk(KERN_ERR "%s: DMA table too small\n", drive->name);
- goto use_pio_instead;
- }
- *table++ = cpu_to_le32(0x8000);
- *table++ = cpu_to_le32(cur_addr + 0x8000);
- xcount = 0x8000;
- }
- *table++ = cpu_to_le32(xcount);
- cur_addr += bcount;
- cur_len -= bcount;
- }
- }
-
- sg = sg_next(sg);
- i--;
- }
-
- if (count) {
- if (!is_trm290)
- *--table |= cpu_to_le32(0x80000000);
- return count;
- }
-
- printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
-
-use_pio_instead:
- ide_destroy_dmatable(drive);
-
- return 0; /* revert to PIO for this request */
-}
-
-EXPORT_SYMBOL_GPL(ide_build_dmatable);
-#endif
-
/**
* ide_destroy_dmatable - clean up DMA mapping
* @drive: The drive to unmap
@@ -262,146 +151,30 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
* an oops as only one mapping can be live for each target at a given
* time.
*/
-
-void ide_destroy_dmatable (ide_drive_t *drive)
+
+void ide_destroy_dmatable(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
hwif->sg_dma_direction);
}
-
EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- * config_drive_for_dma - attempt to activate IDE DMA
- * @drive: the drive to place in DMA mode
- *
- * If the drive supports at least mode 2 DMA or UDMA of any kind
- * then attempt to place it into DMA mode. Drives that are known to
- * support DMA but predate the DMA properties or that are known
- * to have DMA handling bugs are also set up appropriately based
- * on the good/bad drive lists.
- */
-
-static int config_drive_for_dma (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
-
- if (drive->media != ide_disk) {
- if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
- return 0;
- }
-
- /*
- * Enable DMA on any drive that has
- * UltraDMA (mode 0/1/2/3/4/5/6) enabled
- */
- if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
- return 1;
-
- /*
- * Enable DMA on any drive that has mode2 DMA
- * (multi or single) enabled
- */
- if (id->field_valid & 2) /* regular DMA */
- if ((id->dma_mword & 0x404) == 0x404 ||
- (id->dma_1word & 0x404) == 0x404)
- return 1;
-
- /* Consult the list of known "good" drives */
- if (ide_dma_good_drive(drive))
- return 1;
-
- return 0;
-}
-
-/**
- * dma_timer_expiry - handle a DMA timeout
- * @drive: Drive that timed out
- *
- * An IDE DMA transfer timed out. In the event of an error we ask
- * the driver to resolve the problem, if a DMA transfer is still
- * in progress we continue to wait (arguably we need to add a
- * secondary 'I don't care what the drive thinks' timeout here)
- * Finally if we have an interrupt we let it complete the I/O.
- * But only one time - we clear expiry and if it's still not
- * completed after WAIT_CMD, we error and retry in PIO.
- * This can occur if an interrupt is lost or due to hang or bugs.
- */
-
-static int dma_timer_expiry (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
- printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
- drive->name, dma_stat);
-
- if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
- return WAIT_CMD;
-
- HWGROUP(drive)->expiry = NULL; /* one free ride for now */
-
- /* 1 dmaing, 2 error, 4 intr */
- if (dma_stat & 2) /* ERROR */
- return -1;
-
- if (dma_stat & 1) /* DMAing */
- return WAIT_CMD;
-
- if (dma_stat & 4) /* Got an Interrupt */
- return WAIT_CMD;
-
- return 0; /* Status is unknown -- reset the bus */
-}
-
-/**
- * ide_dma_host_set - Enable/disable DMA on a host
- * @drive: drive to control
- *
- * Enable/disable DMA on an IDE controller following generic
- * bus-mastering IDE controller behaviour.
- */
-
-void ide_dma_host_set(ide_drive_t *drive, int on)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
- if (on)
- dma_stat |= (1 << (5 + unit));
- else
- dma_stat &= ~(1 << (5 + unit));
-
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- writeb(dma_stat,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_host_set);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
/**
* ide_dma_off_quietly - Generic DMA kill
* @drive: drive to control
*
- * Turn off the current DMA on this IDE controller.
+ * Turn off the current DMA on this IDE controller.
*/
void ide_dma_off_quietly(ide_drive_t *drive)
{
- drive->using_dma = 0;
+ drive->dev_flags &= ~IDE_DFLAG_USING_DMA;
ide_toggle_bounce(drive, 0);
drive->hwif->dma_ops->dma_host_set(drive, 0);
}
-
EXPORT_SYMBOL(ide_dma_off_quietly);
/**
@@ -417,7 +190,6 @@ void ide_dma_off(ide_drive_t *drive)
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
ide_dma_off_quietly(drive);
}
-
EXPORT_SYMBOL(ide_dma_off);
/**
@@ -429,179 +201,24 @@ EXPORT_SYMBOL(ide_dma_off);
void ide_dma_on(ide_drive_t *drive)
{
- drive->using_dma = 1;
+ drive->dev_flags |= IDE_DFLAG_USING_DMA;
ide_toggle_bounce(drive, 1);
drive->hwif->dma_ops->dma_host_set(drive, 1);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- * ide_dma_setup - begin a DMA phase
- * @drive: target device
- *
- * Build an IDE DMA PRD (IDE speak for scatter gather table)
- * and then set up the DMA transfer registers for a device
- * that follows generic IDE PCI DMA behaviour. Controllers can
- * override this function if they need to
- *
- * Returns 0 on success. If a PIO fallback is required then 1
- * is returned.
- */
-
-int ide_dma_setup(ide_drive_t *drive)
+int __ide_dma_bad_drive(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
- unsigned int reading;
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
- u8 dma_stat;
-
- if (rq_data_dir(rq))
- reading = 0;
- else
- reading = 1 << 3;
-
- /* fall back to pio! */
- if (!ide_build_dmatable(drive, rq)) {
- ide_map_sg(drive, rq);
- return 1;
- }
-
- /* PRD table */
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- writel(hwif->dmatable_dma,
- (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
- else
- outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
-
- /* specify r/w */
- if (mmio)
- writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- else
- outb(reading, hwif->dma_base + ATA_DMA_CMD);
-
- /* read DMA status for INTR & ERROR flags */
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
- /* clear INTR & ERROR flags */
- if (mmio)
- writeb(dma_stat | 6,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
- drive->waiting_for_dma = 1;
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_setup);
-
-void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
- /* issue cmd to drive */
- ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-}
-EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
-
-void ide_dma_start(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 dma_cmd;
-
- /* Note that this is done *after* the cmd has
- * been issued to the drive, as per the BM-IDE spec.
- * The Promise Ultra33 doesn't work correctly when
- * we do this part before issuing the drive cmd.
- */
- if (hwif->host_flags & IDE_HFLAG_MMIO) {
- dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- /* start DMA */
- writeb(dma_cmd | 1,
- (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- } else {
- dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
- outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
- }
-
- hwif->dma = 1;
- wmb();
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_start);
-
-/* returns 1 on error, 0 otherwise */
-int __ide_dma_end (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
- u8 dma_stat = 0, dma_cmd = 0;
-
- drive->waiting_for_dma = 0;
-
- if (mmio) {
- /* get DMA command mode */
- dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- /* stop DMA */
- writeb(dma_cmd & ~1,
- (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- } else {
- dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
- outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
- }
-
- /* get DMA status */
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
- if (mmio)
- /* clear the INTR & ERROR bits */
- writeb(dma_stat | 6,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
- /* purge DMA mappings */
- ide_destroy_dmatable(drive);
- /* verify good DMA status */
- hwif->dma = 0;
- wmb();
- return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-
-EXPORT_SYMBOL(__ide_dma_end);
-
-/* returns 1 if dma irq issued, 0 otherwise */
-int ide_dma_test_irq(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
- /* return 1 if INTR asserted */
- if ((dma_stat & 4) == 4)
- return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
- return 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_test_irq);
-#else
-static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
-int __ide_dma_bad_drive (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
int blacklist = ide_in_drive_list(id, drive_blacklist);
if (blacklist) {
printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n",
- drive->name, id->model);
+ drive->name, (char *)&id[ATA_ID_PROD]);
return blacklist;
}
return 0;
}
-
EXPORT_SYMBOL(__ide_dma_bad_drive);
static const u8 xfer_mode_bases[] = {
@@ -612,21 +229,21 @@ static const u8 xfer_mode_bases[] = {
static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
unsigned int mask = 0;
- switch(base) {
+ switch (base) {
case XFER_UDMA_0:
- if ((id->field_valid & 4) == 0)
+ if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
break;
if (port_ops && port_ops->udma_filter)
mask = port_ops->udma_filter(drive);
else
mask = hwif->ultra_mask;
- mask &= id->dma_ultra;
+ mask &= id[ATA_ID_UDMA_MODES];
/*
* avoid false cable warning from eighty_ninty_three()
@@ -637,19 +254,19 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
}
break;
case XFER_MW_DMA_0:
- if ((id->field_valid & 2) == 0)
+ if ((id[ATA_ID_FIELD_VALID] & 2) == 0)
break;
if (port_ops && port_ops->mdma_filter)
mask = port_ops->mdma_filter(drive);
else
mask = hwif->mwdma_mask;
- mask &= id->dma_mword;
+ mask &= id[ATA_ID_MWDMA_MODES];
break;
case XFER_SW_DMA_0:
- if (id->field_valid & 2) {
- mask = id->dma_1word & hwif->swdma_mask;
- } else if (id->tDMA) {
- u8 mode = id->tDMA;
+ if (id[ATA_ID_FIELD_VALID] & 2) {
+ mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask;
+ } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) {
+ u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8;
/*
* if the mode is valid convert it to the mask
@@ -706,7 +323,8 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
/*
* is this correct?
*/
- if (ide_dma_good_drive(drive) && drive->id->eide_dma_time < 150)
+ if (ide_dma_good_drive(drive) &&
+ drive->id[ATA_ID_EIDE_DMA_TIME] < 150)
mode = XFER_MW_DMA_1;
}
@@ -717,7 +335,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
return mode;
}
-
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
static int ide_tune_dma(ide_drive_t *drive)
@@ -725,7 +342,8 @@ static int ide_tune_dma(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
u8 speed;
- if (drive->nodma || (drive->id->capability & 1) == 0)
+ if (ata_id_has_dma(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_NODMA))
return 0;
/* consult the list of known "bad" drives */
@@ -767,13 +385,15 @@ static int ide_dma_check(ide_drive_t *drive)
int ide_id_dma_bug(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
- if (id->field_valid & 4) {
- if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
+ if (id[ATA_ID_FIELD_VALID] & 4) {
+ if ((id[ATA_ID_UDMA_MODES] >> 8) &&
+ (id[ATA_ID_MWDMA_MODES] >> 8))
goto err_out;
- } else if (id->field_valid & 2) {
- if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
+ } else if (id[ATA_ID_FIELD_VALID] & 2) {
+ if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
+ (id[ATA_ID_SWDMA_MODES] >> 8))
goto err_out;
}
return 0;
@@ -823,66 +443,59 @@ void ide_check_dma_crc(ide_drive_t *drive)
ide_dma_on(drive);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-void ide_dma_lost_irq (ide_drive_t *drive)
+void ide_dma_lost_irq(ide_drive_t *drive)
{
- printk("%s: DMA interrupt recovery\n", drive->name);
+ printk(KERN_ERR "%s: DMA interrupt recovery\n", drive->name);
}
+EXPORT_SYMBOL_GPL(ide_dma_lost_irq);
-EXPORT_SYMBOL(ide_dma_lost_irq);
-
-void ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
if (hwif->dma_ops->dma_test_irq(drive))
return;
+ ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
+
hwif->dma_ops->dma_end(drive);
}
-
-EXPORT_SYMBOL(ide_dma_timeout);
+EXPORT_SYMBOL_GPL(ide_dma_timeout);
void ide_release_dma_engine(ide_hwif_t *hwif)
{
if (hwif->dmatable_cpu) {
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ int prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
- pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
+ dma_free_coherent(hwif->dev, prd_size,
+ hwif->dmatable_cpu, hwif->dmatable_dma);
hwif->dmatable_cpu = NULL;
}
}
+EXPORT_SYMBOL_GPL(ide_release_dma_engine);
int ide_allocate_dma_engine(ide_hwif_t *hwif)
{
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ int prd_size;
- hwif->dmatable_cpu = pci_alloc_consistent(pdev,
- PRD_ENTRIES * PRD_BYTES,
- &hwif->dmatable_dma);
+ if (hwif->prd_max_nents == 0)
+ hwif->prd_max_nents = PRD_ENTRIES;
+ if (hwif->prd_ent_size == 0)
+ hwif->prd_ent_size = PRD_BYTES;
- if (hwif->dmatable_cpu)
- return 0;
+ prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
- printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
+ hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, prd_size,
+ &hwif->dmatable_dma,
+ GFP_ATOMIC);
+ if (hwif->dmatable_cpu == NULL) {
+ printk(KERN_ERR "%s: unable to allocate PRD table\n",
hwif->name);
+ return -ENOMEM;
+ }
- return 1;
+ return 0;
}
EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
-
-const struct ide_dma_ops sff_dma_ops = {
- .dma_host_set = ide_dma_host_set,
- .dma_setup = ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
- .dma_test_irq = ide_dma_test_irq,
- .dma_timeout = ide_dma_timeout,
- .dma_lost_irq = ide_dma_lost_irq,
-};
-EXPORT_SYMBOL_GPL(sff_dma_ops);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index e9034c0125f..cf0aa25470e 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -15,6 +15,9 @@
* Documentation/ide/ChangeLog.ide-floppy.1996-2002
*/
+#define DRV_NAME "ide-floppy"
+#define PFX DRV_NAME ": "
+
#define IDEFLOPPY_VERSION "1.00"
#include <linux/module.h>
@@ -31,8 +34,10 @@
#include <linux/slab.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi_ioctl.h>
@@ -42,42 +47,27 @@
#include <linux/io.h>
#include <asm/unaligned.h>
-/* define to see debug info */
-#define IDEFLOPPY_DEBUG_LOG 0
+#include "ide-floppy.h"
-/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
-#define IDEFLOPPY_DEBUG(fmt, args...)
+/* module parameters */
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
+
+/* define to see debug info */
+#define IDEFLOPPY_DEBUG_LOG 0
#if IDEFLOPPY_DEBUG_LOG
-#define debug_log(fmt, args...) \
- printk(KERN_INFO "ide-floppy: " fmt, ## args)
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
#else
-#define debug_log(fmt, args...) do {} while (0)
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
#endif
-
-/* Some drives require a longer irq timeout. */
-#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD)
-
/*
* After each failed packet command we issue a request sense command and retry
* the packet command IDEFLOPPY_MAX_PC_RETRIES times.
*/
#define IDEFLOPPY_MAX_PC_RETRIES 3
-/*
- * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE
- * bytes.
- */
-#define IDEFLOPPY_PC_BUFFER_SIZE 256
-
-/*
- * In various places in the driver, we need to allocate storage for packet
- * commands and requests, which will remain valid while we leave the driver to
- * wait for an interrupt or a timeout event.
- */
-#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)
-
/* format capacities descriptor codes */
#define CAPACITY_INVALID 0x00
#define CAPACITY_UNFORMATTED 0x01
@@ -85,79 +75,16 @@
#define CAPACITY_NO_CARTRIDGE 0x03
/*
- * Most of our global data which we need to save even as we leave the driver
- * due to an interrupt or a timer event is stored in a variable of type
- * idefloppy_floppy_t, defined below.
+ * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
+ * was apparently being deasserted before the unit was ready to receive data.
*/
-typedef struct ide_floppy_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
-
- /* Current packet command */
- struct ide_atapi_pc *pc;
- /* Last failed packet command */
- struct ide_atapi_pc *failed_pc;
- /* Packet command stack */
- struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK];
- /* Next free packet command storage space */
- int pc_stack_index;
- struct request rq_stack[IDEFLOPPY_PC_STACK];
- /* We implement a circular array */
- int rq_stack_index;
-
- /* Last error information */
- u8 sense_key, asc, ascq;
- /* delay this long before sending packet command */
- u8 ticks;
- int progress_indication;
-
- /* Device information */
- /* Current format */
- int blocks, block_size, bs_factor;
- /* Last format capacity descriptor */
- u8 cap_desc[8];
- /* Copy of the flexible disk page */
- u8 flexible_disk_page[32];
- /* Write protect */
- int wp;
- /* Supports format progress report */
- int srfp;
-} idefloppy_floppy_t;
-
-#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-
-/* Defines for the MODE SENSE command */
-#define MODE_SENSE_CURRENT 0x00
-#define MODE_SENSE_CHANGEABLE 0x01
-#define MODE_SENSE_DEFAULT 0x02
-#define MODE_SENSE_SAVED 0x03
-
-/* IOCTLs used in low-level formatting. */
-#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
-#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
-#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
-#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
+#define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */
/* Error code returned in rq->errors to the higher part of the driver. */
#define IDEFLOPPY_ERROR_GENERAL 101
-/*
- * Pages of the SELECT SENSE / MODE SENSE packet commands.
- * See SFF-8070i spec.
- */
-#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
-#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
-
static DEFINE_MUTEX(idefloppy_ref_mutex);
-#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
-
-#define ide_floppy_g(disk) \
- container_of((disk)->private_data, struct ide_floppy_obj, driver)
-
static void idefloppy_cleanup_obj(struct kref *);
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
@@ -165,7 +92,7 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
struct ide_floppy_obj *floppy = NULL;
mutex_lock(&idefloppy_ref_mutex);
- floppy = ide_floppy_g(disk);
+ floppy = ide_drv_g(disk, ide_floppy_obj);
if (floppy) {
if (ide_device_get(floppy->drive))
floppy = NULL;
@@ -196,13 +123,21 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
struct request *rq = HWGROUP(drive)->rq;
int error;
- debug_log("Reached %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
switch (uptodate) {
- case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
- case 1: error = 0; break;
- default: error = uptodate;
+ case 0:
+ error = IDEFLOPPY_ERROR_GENERAL;
+ break;
+
+ case 1:
+ error = 0;
+ break;
+
+ default:
+ error = uptodate;
}
+
if (error)
floppy->failed_pc = NULL;
/* Why does this happen? */
@@ -219,44 +154,6 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
return 0;
}
-static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int direction)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct request *rq = pc->rq;
- struct req_iterator iter;
- struct bio_vec *bvec;
- unsigned long flags;
- int count, done = 0;
- char *data;
-
- rq_for_each_segment(bvec, rq, iter) {
- if (!bcount)
- break;
-
- count = min(bvec->bv_len, bcount);
-
- data = bvec_kmap_irq(bvec, &flags);
- if (direction)
- hwif->tp_ops->output_data(drive, NULL, data, count);
- else
- hwif->tp_ops->input_data(drive, NULL, data, count);
- bvec_kunmap_irq(data, &flags);
-
- bcount -= count;
- pc->b_count += count;
- done += count;
- }
-
- idefloppy_end_request(drive, 1, done >> 9);
-
- if (bcount) {
- printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
- drive->name, __func__, bcount);
- ide_pad_transfer(drive, direction, bcount);
- }
-}
-
static void idefloppy_update_buffers(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
@@ -267,50 +164,13 @@ static void idefloppy_update_buffers(ide_drive_t *drive,
idefloppy_end_request(drive, 1, 0);
}
-/*
- * Generate a new packet command request in front of the request queue, before
- * the current request so that it will be processed immediately, on the next
- * pass through the driver.
- */
-static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
- struct request *rq)
-{
- struct ide_floppy_obj *floppy = drive->driver_data;
-
- blk_rq_init(NULL, rq);
- rq->buffer = (char *) pc;
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_flags |= REQ_PREEMPT;
- rq->rq_disk = floppy->disk;
- memcpy(rq->cmd, pc->c, 12);
- ide_do_drive_cmd(drive, rq);
-}
-
-static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive)
+static void ide_floppy_callback(ide_drive_t *drive, int dsc)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)
- floppy->pc_stack_index = 0;
- return (&floppy->pc_stack[floppy->pc_stack_index++]);
-}
-
-static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK)
- floppy->rq_stack_index = 0;
- return (&floppy->rq_stack[floppy->rq_stack_index++]);
-}
-
-static void ide_floppy_callback(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc *pc = floppy->pc;
+ struct ide_atapi_pc *pc = drive->pc;
int uptodate = pc->error ? 0 : 1;
- debug_log("Reached %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
if (floppy->failed_pc == pc)
floppy->failed_pc = NULL;
@@ -319,7 +179,7 @@ static void ide_floppy_callback(ide_drive_t *drive)
(pc->rq && blk_pc_request(pc->rq)))
uptodate = 1; /* FIXME */
else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
- u8 *buf = floppy->pc->buf;
+ u8 *buf = pc->buf;
if (!pc->error) {
floppy->sense_key = buf[2] & 0x0F;
@@ -329,108 +189,20 @@ static void ide_floppy_callback(ide_drive_t *drive)
(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
if (floppy->failed_pc)
- debug_log("pc = %x, ", floppy->failed_pc->c[0]);
+ ide_debug_log(IDE_DBG_PC, "pc = %x, ",
+ floppy->failed_pc->c[0]);
- debug_log("sense key = %x, asc = %x, ascq = %x\n",
- floppy->sense_key, floppy->asc, floppy->ascq);
+ ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
+ "ascq = %x\n", floppy->sense_key,
+ floppy->asc, floppy->ascq);
} else
- printk(KERN_ERR "Error in REQUEST SENSE itself - "
- "Aborting request!\n");
+ printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
+ "Aborting request!\n");
}
idefloppy_end_request(drive, uptodate, 0);
}
-static void idefloppy_init_pc(struct ide_atapi_pc *pc)
-{
- memset(pc, 0, sizeof(*pc));
- pc->buf = pc->pc_buf;
- pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
-}
-
-static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_REQUEST_SENSE;
- pc->c[4] = 255;
- pc->req_xfer = 18;
-}
-
-/*
- * Called when an error was detected during the last packet command. We queue a
- * request sense packet command in the head of the request list.
- */
-static void idefloppy_retry_pc(ide_drive_t *drive)
-{
- struct ide_atapi_pc *pc;
- struct request *rq;
-
- (void)ide_read_error(drive);
- pc = idefloppy_next_pc_storage(drive);
- rq = idefloppy_next_rq_storage(drive);
- idefloppy_create_request_sense_cmd(pc);
- idefloppy_queue_pc_head(drive, pc, rq);
-}
-
-/* The usual interrupt handler called during a packet command. */
-static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr,
- IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers,
- idefloppy_retry_pc, NULL, ide_floppy_io_buffers);
-}
-
-/*
- * What we have here is a classic case of a top half / bottom half interrupt
- * service routine. In interrupt mode, the device sends an interrupt to signal
- * that it is ready to receive a packet. However, we need to delay about 2-3
- * ticks before issuing the packet or we gets in trouble.
- */
-static int idefloppy_transfer_pc(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- /* Send the actual packet */
- drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
-
- /* Timeout for the packet command */
- return IDEFLOPPY_WAIT_CMD;
-}
-
-
-/*
- * Called as an interrupt (or directly). When the device says it's ready for a
- * packet, we schedule the packet transfer to occur about 2-3 ticks later in
- * transfer_pc.
- */
-static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc *pc = floppy->pc;
- ide_expiry_t *expiry;
- unsigned int timeout;
-
- /*
- * The following delay solves a problem with ATAPI Zip 100 drives
- * where the Busy flag was apparently being deasserted before the
- * unit was ready to receive data. This was happening on a
- * 1200 MHz Athlon system. 10/26/01 25msec is too short,
- * 40 and 50msec work well. idefloppy_pc_intr will not be actually
- * used until after the packet is moved in about 50 msec.
- */
- if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
- timeout = floppy->ticks;
- expiry = &idefloppy_transfer_pc;
- } else {
- timeout = IDEFLOPPY_WAIT_CMD;
- expiry = NULL;
- }
-
- return ide_transfer_pc(drive, pc, idefloppy_pc_intr, timeout, expiry);
-}
-
static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
struct ide_atapi_pc *pc)
{
@@ -440,7 +212,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
floppy->ascq == 0x00)
return;
- printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
+ printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
"asc = %2x, ascq = %2x\n",
floppy->drive->name, pc->c[0], floppy->sense_key,
floppy->asc, floppy->ascq);
@@ -455,8 +227,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
if (floppy->failed_pc == NULL &&
pc->c[0] != GPCMD_REQUEST_SENSE)
floppy->failed_pc = pc;
+
/* Set the current packet command */
- floppy->pc = pc;
+ drive->pc = pc;
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
@@ -465,67 +238,35 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->error = IDEFLOPPY_ERROR_GENERAL;
floppy->failed_pc = NULL;
- drive->pc_callback(drive);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
- debug_log("Retry number - %d\n", pc->retries);
+ ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries);
pc->retries++;
- return ide_issue_pc(drive, pc, idefloppy_start_pc_transfer,
- IDEFLOPPY_WAIT_CMD, NULL);
+ return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
}
-static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
+void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
{
- debug_log("creating prevent removal command, prevent = %d\n", prevent);
-
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- pc->c[4] = prevent;
-}
-
-static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
-{
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
pc->c[7] = 255;
pc->c[8] = 255;
pc->req_xfer = 255;
}
-static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
- int l, int flags)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_FORMAT_UNIT;
- pc->c[1] = 0x17;
-
- memset(pc->buf, 0, 12);
- pc->buf[1] = 0xA2;
- /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
-
- if (flags & 1) /* Verify bit on... */
- pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
- pc->buf[3] = 8;
-
- put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
- put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
- pc->buf_size = 12;
- pc->flags |= PC_FLAG_WRITING;
-}
-
/* A mode sense command is used to "sense" floppy parameters. */
-static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
- u8 page_code, u8 type)
+void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
{
u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = GPCMD_MODE_SENSE_10;
pc->c[1] = 0;
- pc->c[2] = page_code + (type << 6);
+ pc->c[2] = page_code;
switch (page_code) {
case IDEFLOPPY_CAPABILITIES_PAGE:
@@ -535,32 +276,25 @@ static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
length += 32;
break;
default:
- printk(KERN_ERR "ide-floppy: unsupported page code "
- "in create_mode_sense_cmd\n");
+ printk(KERN_ERR PFX "unsupported page code in %s\n", __func__);
}
put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
pc->req_xfer = length;
}
-static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
-{
- idefloppy_init_pc(pc);
- pc->c[0] = GPCMD_START_STOP_UNIT;
- pc->c[4] = start;
-}
-
-static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+static void idefloppy_create_rw_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc, struct request *rq,
unsigned long sector)
{
+ idefloppy_floppy_t *floppy = drive->driver_data;
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
int cmd = rq_data_dir(rq);
- debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
- block, blocks);
+ ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__,
+ block, blocks);
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
@@ -568,7 +302,7 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
memcpy(rq->cmd, pc->c, 12);
pc->rq = rq;
- pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ pc->b_count = 0;
if (rq->cmd_flags & REQ_RW)
pc->flags |= PC_FLAG_WRITING;
pc->buf = NULL;
@@ -579,10 +313,10 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
struct ide_atapi_pc *pc, struct request *rq)
{
- idefloppy_init_pc(pc);
+ ide_init_pc(pc);
memcpy(pc->c, rq->cmd, sizeof(pc->c));
pc->rq = rq;
- pc->b_count = rq->data_len;
+ pc->b_count = 0;
if (rq->data_len && rq_data_dir(rq) == WRITE)
pc->flags |= PC_FLAG_WRITING;
pc->buf = rq->data;
@@ -599,70 +333,59 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
struct request *rq, sector_t block_s)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ ide_hwif_t *hwif = drive->hwif;
struct ide_atapi_pc *pc;
unsigned long block = (unsigned long)block_s;
- debug_log("dev: %s, cmd_type: %x, errors: %d\n",
- rq->rq_disk ? rq->rq_disk->disk_name : "?",
- rq->cmd_type, rq->errors);
- debug_log("sector: %ld, nr_sectors: %ld, "
- "current_nr_sectors: %d\n", (long)rq->sector,
- rq->nr_sectors, rq->current_nr_sectors);
+ ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
+ "errors: %d\n",
+ __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
+ rq->cmd[0], rq->cmd_type, rq->errors);
+
+ ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
+ "current_nr_sectors: %d\n",
+ __func__, (long)rq->sector, rq->nr_sectors,
+ rq->current_nr_sectors);
if (rq->errors >= ERROR_MAX) {
if (floppy->failed_pc)
ide_floppy_report_error(floppy, floppy->failed_pc);
else
- printk(KERN_ERR "ide-floppy: %s: I/O error\n",
- drive->name);
+ printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
+
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
if (blk_fs_request(rq)) {
if (((long)rq->sector % floppy->bs_factor) ||
(rq->nr_sectors % floppy->bs_factor)) {
- printk(KERN_ERR "%s: unsupported r/w request size\n",
- drive->name);
+ printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
+ drive->name);
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
- pc = idefloppy_next_pc_storage(drive);
- idefloppy_create_rw_cmd(floppy, pc, rq, block);
+ pc = &floppy->queued_pc;
+ idefloppy_create_rw_cmd(drive, pc, rq, block);
} else if (blk_special_request(rq)) {
pc = (struct ide_atapi_pc *) rq->buffer;
} else if (blk_pc_request(rq)) {
- pc = idefloppy_next_pc_storage(drive);
+ pc = &floppy->queued_pc;
idefloppy_blockpc_cmd(floppy, pc, rq);
} else {
- blk_dump_rq_flags(rq,
- "ide-floppy: unsupported command in queue");
+ blk_dump_rq_flags(rq, PFX "unsupported command in queue");
idefloppy_end_request(drive, 0, 0);
return ide_stopped;
}
- pc->rq = rq;
+ ide_init_sg_cmd(drive, rq);
+ ide_map_sg(drive, rq);
- return idefloppy_issue_pc(drive, pc);
-}
+ pc->sg = hwif->sg_table;
+ pc->sg_cnt = hwif->sg_nents;
-/*
- * Add a special packet command request to the tail of the request queue,
- * and wait for it to be serviced.
- */
-static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- struct ide_floppy_obj *floppy = drive->driver_data;
- struct request *rq;
- int error;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->buffer = (char *) pc;
- rq->cmd_type = REQ_TYPE_SPECIAL;
- memcpy(rq->cmd, pc->c, 12);
- error = blk_execute_rq(drive->queue, floppy->disk, rq, 0);
- blk_put_request(rq);
+ pc->rq = rq;
- return error;
+ return idefloppy_issue_pc(drive, pc);
}
/*
@@ -672,22 +395,27 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
u8 *page;
int capacity, lba_capacity;
u16 transfer_rate, sector_size, cyls, rpm;
u8 heads, sectors;
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE,
- MODE_SENSE_CURRENT);
+ ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
- " parameters\n");
+ if (ide_queue_pc_tail(drive, disk, &pc)) {
+ printk(KERN_ERR PFX "Can't get flexible disk page params\n");
return 1;
}
- floppy->wp = !!(pc.buf[3] & 0x80);
- set_disk_ro(floppy->disk, floppy->wp);
+
+ if (pc.buf[3] & 0x80)
+ drive->atapi_flags |= IDE_AFLAG_WP;
+ else
+ drive->atapi_flags &= ~IDE_AFLAG_WP;
+
+ set_disk_ro(disk, !!(drive->atapi_flags & IDE_AFLAG_WP));
+
page = &pc.buf[8];
transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
@@ -700,7 +428,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
capacity = cyls * heads * sectors * sector_size;
if (memcmp(page, &floppy->flexible_disk_page, 32))
- printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
+ printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
"%d sector size, %d rpm\n",
drive->name, capacity / 1024, cyls, heads,
sectors, transfer_rate / 8, sector_size, rpm);
@@ -712,7 +440,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
lba_capacity = floppy->blocks * floppy->block_size;
if (capacity < lba_capacity) {
- printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
+ printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
"bytes, but the drive only handles %d\n",
drive->name, lba_capacity, capacity);
floppy->blocks = floppy->block_size ?
@@ -721,23 +449,6 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
return 0;
}
-static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
-
- floppy->srfp = 0;
- idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
- MODE_SENSE_CURRENT);
-
- pc.flags |= PC_FLAG_SUPPRESS_ERROR;
- if (idefloppy_queue_pc_tail(drive, &pc))
- return 1;
-
- floppy->srfp = pc.buf[8 + 2] & 0x40;
- return (0);
-}
-
/*
* Determine if a media is present in the floppy drive, and if so, its LBA
* capacity.
@@ -745,6 +456,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
static int ide_floppy_get_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
struct ide_atapi_pc pc;
u8 *cap_desc;
u8 header_len, desc_cnt;
@@ -756,9 +468,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
floppy->bs_factor = 1;
set_capacity(floppy->disk, 0);
- idefloppy_create_read_capacity_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ ide_floppy_create_read_capacity_cmd(&pc);
+ if (ide_queue_pc_tail(drive, disk, &pc)) {
+ printk(KERN_ERR PFX "Can't get floppy parameters\n");
return 1;
}
header_len = pc.buf[3];
@@ -771,8 +483,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
- debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
- i, blocks * length / 1024, blocks, length);
+ ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
+ "%d sector size\n",
+ i, blocks * length / 1024, blocks, length);
if (i)
continue;
@@ -792,23 +505,24 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
case CAPACITY_CURRENT:
/* Normal Zip/LS-120 disks */
if (memcmp(cap_desc, &floppy->cap_desc, 8))
- printk(KERN_INFO "%s: %dkB, %d blocks, %d "
- "sector size\n", drive->name,
- blocks * length / 1024, blocks, length);
+ printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
+ "sector size\n",
+ drive->name, blocks * length / 1024,
+ blocks, length);
memcpy(&floppy->cap_desc, cap_desc, 8);
if (!length || length % 512) {
- printk(KERN_NOTICE "%s: %d bytes block size "
- "not supported\n", drive->name, length);
+ printk(KERN_NOTICE PFX "%s: %d bytes block size"
+ " not supported\n", drive->name, length);
} else {
floppy->blocks = blocks;
floppy->block_size = length;
floppy->bs_factor = length / 512;
if (floppy->bs_factor != 1)
- printk(KERN_NOTICE "%s: warning: non "
- "512 bytes block size not "
- "fully supported\n",
- drive->name);
+ printk(KERN_NOTICE PFX "%s: Warning: "
+ "non 512 bytes block size not "
+ "fully supported\n",
+ drive->name);
rc = 0;
}
break;
@@ -817,143 +531,28 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
* This is a KERN_ERR so it appears on screen
* for the user to see
*/
- printk(KERN_ERR "%s: No disk in drive\n", drive->name);
+ printk(KERN_ERR PFX "%s: No disk in drive\n",
+ drive->name);
break;
case CAPACITY_INVALID:
- printk(KERN_ERR "%s: Invalid capacity for disk "
+ printk(KERN_ERR PFX "%s: Invalid capacity for disk "
"in drive\n", drive->name);
break;
}
- debug_log("Descriptor 0 Code: %d\n",
- pc.buf[desc_start + 4] & 0x03);
+ ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n",
+ pc.buf[desc_start + 4] & 0x03);
}
/* Clik! disk does not support get_flexible_disk_page */
if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
(void) ide_floppy_get_flexible_disk_page(drive);
- set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
- return rc;
-}
+ set_capacity(disk, floppy->blocks * floppy->bs_factor);
-/*
- * Obtain the list of formattable capacities.
- * Very similar to ide_floppy_get_capacity, except that we push the capacity
- * descriptors to userland, instead of our own structures.
- *
- * Userland gives us the following structure:
- *
- * struct idefloppy_format_capacities {
- * int nformats;
- * struct {
- * int nblocks;
- * int blocksize;
- * } formats[];
- * };
- *
- * userland initializes nformats to the number of allocated formats[] records.
- * On exit we set nformats to the number of records we've actually initialized.
- */
-
-static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
-{
- struct ide_atapi_pc pc;
- u8 header_len, desc_cnt;
- int i, blocks, length, u_array_size, u_index;
- int __user *argp;
-
- if (get_user(u_array_size, arg))
- return (-EFAULT);
-
- if (u_array_size <= 0)
- return (-EINVAL);
-
- idefloppy_create_read_capacity_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
- return (-EIO);
- }
- header_len = pc.buf[3];
- desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
-
- u_index = 0;
- argp = arg + 1;
-
- /*
- * We always skip the first capacity descriptor. That's the current
- * capacity. We are interested in the remaining descriptors, the
- * formattable capacities.
- */
- for (i = 1; i < desc_cnt; i++) {
- unsigned int desc_start = 4 + i*8;
-
- if (u_index >= u_array_size)
- break; /* User-supplied buffer too small */
-
- blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
- length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
-
- if (put_user(blocks, argp))
- return(-EFAULT);
- ++argp;
-
- if (put_user(length, argp))
- return (-EFAULT);
- ++argp;
-
- ++u_index;
- }
-
- if (put_user(u_index, arg))
- return (-EFAULT);
- return (0);
-}
-
-/*
- * Get ATAPI_FORMAT_UNIT progress indication.
- *
- * Userland gives a pointer to an int. The int is set to a progress
- * indicator 0-65536, with 65536=100%.
- *
- * If the drive does not support format progress indication, we just check
- * the dsc bit, and return either 0 or 65536.
- */
-
-static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
- int progress_indication = 0x10000;
-
- if (floppy->srfp) {
- idefloppy_create_request_sense_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc))
- return (-EIO);
-
- if (floppy->sense_key == 2 &&
- floppy->asc == 4 &&
- floppy->ascq == 4)
- progress_indication = floppy->progress_indication;
-
- /* Else assume format_unit has finished, and we're at 0x10000 */
- } else {
- ide_hwif_t *hwif = drive->hwif;
- unsigned long flags;
- u8 stat;
-
- local_irq_save(flags);
- stat = hwif->tp_ops->read_status(hwif);
- local_irq_restore(flags);
-
- progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
- }
- if (put_user(progress_indication, arg))
- return (-EFAULT);
-
- return (0);
+ return rc;
}
-static sector_t idefloppy_capacity(ide_drive_t *drive)
+sector_t ide_floppy_capacity(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
unsigned long capacity = floppy->blocks * floppy->bs_factor;
@@ -961,77 +560,14 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
return capacity;
}
-/*
- * Check whether we can support a drive, based on the ATAPI IDENTIFY command
- * results.
- */
-static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
-{
- u8 gcw[2];
- u8 device_type, protocol, removable, drq_type, packet_size;
-
- *((u16 *) &gcw) = id->config;
-
- device_type = gcw[1] & 0x1F;
- removable = (gcw[0] & 0x80) >> 7;
- protocol = (gcw[1] & 0xC0) >> 6;
- drq_type = (gcw[0] & 0x60) >> 5;
- packet_size = gcw[0] & 0x03;
-
-#ifdef CONFIG_PPC
- /* kludge for Apple PowerBook internal zip */
- if (device_type == 5 &&
- !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP"))
- device_type = 0;
-#endif
-
- if (protocol != 2)
- printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
- protocol);
- else if (device_type != 0)
- printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
- "to floppy\n", device_type);
- else if (!removable)
- printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
- else if (drq_type == 3)
- printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
- "supported\n", drq_type);
- else if (packet_size != 0)
- printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
- "bytes\n", packet_size);
- else
- return 1;
- return 0;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-static void idefloppy_add_settings(ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1,
- &drive->bios_cyl, NULL);
- ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
- &drive->bios_head, NULL);
- ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
- &drive->bios_sect, NULL);
- ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
- &floppy->ticks, NULL);
-}
-#else
-static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
-#endif
-
static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
{
- u8 gcw[2];
+ u16 *id = drive->id;
- *((u16 *) &gcw) = drive->id->config;
- floppy->pc = floppy->pc_stack;
- drive->pc_callback = ide_floppy_callback;
+ drive->pc_callback = ide_floppy_callback;
+ drive->pc_update_buffers = idefloppy_update_buffers;
+ drive->pc_io_buffers = ide_io_buffers;
- if (((gcw[0] & 0x60) >> 5) == 1)
- drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
/*
* We used to check revisions here. At this point however I'm giving up.
* Just assume they are all broken, its easier.
@@ -1041,10 +577,10 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* it. It should be fixed as of version 1.9, but to be on the safe side
* we'll leave the limitation below for the 2.2.x tree.
*/
- if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
+ if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
/* This value will be visible in the /proc/ide/hdx/settings */
- floppy->ticks = IDEFLOPPY_TICKS_DELAY;
+ drive->pc_delay = IDEFLOPPY_PC_DELAY;
blk_queue_max_sectors(drive->queue, 64);
}
@@ -1052,13 +588,16 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
* nasty clicking noises without it, so please don't remove this.
*/
- if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
+ if (strncmp((char *)&id[ATA_ID_PROD], "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(drive->queue, 64);
drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
}
(void) ide_floppy_get_capacity(drive);
- idefloppy_add_settings(drive);
+
+ ide_proc_register_driver(drive, floppy->driver);
}
static void ide_floppy_remove(ide_drive_t *drive)
@@ -1075,7 +614,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
static void idefloppy_cleanup_obj(struct kref *kref)
{
- struct ide_floppy_obj *floppy = to_ide_floppy(kref);
+ struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
struct gendisk *g = floppy->disk;
@@ -1085,24 +624,6 @@ static void idefloppy_cleanup_obj(struct kref *kref)
kfree(floppy);
}
-#ifdef CONFIG_IDE_PROC_FS
-static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- ide_drive_t*drive = (ide_drive_t *)data;
- int len;
-
- len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive));
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static ide_proc_entry_t idefloppy_proc[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
- { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
static int ide_floppy_probe(ide_drive_t *);
static ide_driver_t idefloppy_driver = {
@@ -1114,13 +635,12 @@ static ide_driver_t idefloppy_driver = {
.probe = ide_floppy_probe,
.remove = ide_floppy_remove,
.version = IDEFLOPPY_VERSION,
- .media = ide_floppy,
- .supports_dsc_overlap = 0,
.do_request = idefloppy_do_request,
.end_request = idefloppy_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
- .proc = idefloppy_proc,
+ .proc = ide_floppy_proc,
+ .settings = ide_floppy_settings,
#endif
};
@@ -1129,30 +649,24 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_floppy_obj *floppy;
ide_drive_t *drive;
- struct ide_atapi_pc pc;
int ret = 0;
- debug_log("Reached %s\n", __func__);
-
floppy = ide_floppy_get(disk);
if (!floppy)
return -ENXIO;
drive = floppy->drive;
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
floppy->openers++;
if (floppy->openers == 1) {
drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
/* Just in case */
- idefloppy_init_pc(&pc);
- pc.c[0] = GPCMD_TEST_UNIT_READY;
-
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- idefloppy_create_start_stop_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
+ if (ide_do_test_unit_ready(drive, disk))
+ ide_do_start_stop(drive, disk, 1);
if (ide_floppy_get_capacity(drive)
&& (filp->f_flags & O_NDELAY) == 0
@@ -1166,16 +680,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
goto out_put_floppy;
}
- if (floppy->wp && (filp->f_mode & 2)) {
+ if ((drive->atapi_flags & IDE_AFLAG_WP) && (filp->f_mode & 2)) {
ret = -EROFS;
goto out_put_floppy;
}
+
drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
+ ide_set_media_lock(drive, disk, 1);
check_disk_change(inode->i_bdev);
} else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
@@ -1192,19 +703,13 @@ out_put_floppy:
static int idefloppy_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
- struct ide_atapi_pc pc;
- debug_log("Reached %s\n", __func__);
+ ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
if (floppy->openers == 1) {
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- idefloppy_create_prevent_cmd(&pc, 0);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
-
+ ide_set_media_lock(drive, disk, 0);
drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
}
@@ -1217,7 +722,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
+ ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
geo->heads = drive->bios_head;
@@ -1226,137 +732,15 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned long arg, unsigned int cmd)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (floppy->openers > 1)
- return -EBUSY;
-
- /* The IOMEGA Clik! Drive doesn't support this command -
- * no room for an eject mechanism */
- if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
- int prevent = arg ? 1 : 0;
-
- if (cmd == CDROMEJECT)
- prevent = 0;
-
- idefloppy_create_prevent_cmd(pc, prevent);
- (void) idefloppy_queue_pc_tail(floppy->drive, pc);
- }
-
- if (cmd == CDROMEJECT) {
- idefloppy_create_start_stop_cmd(pc, 2);
- (void) idefloppy_queue_pc_tail(floppy->drive, pc);
- }
-
- return 0;
-}
-
-static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
- int __user *arg)
-{
- struct ide_atapi_pc pc;
- ide_drive_t *drive = floppy->drive;
- int blocks, length, flags, err = 0;
-
- if (floppy->openers > 1) {
- /* Don't format if someone is using the disk */
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
- return -EBUSY;
- }
-
- drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
-
- /*
- * Send ATAPI_FORMAT_UNIT to the drive.
- *
- * Userland gives us the following structure:
- *
- * struct idefloppy_format_command {
- * int nblocks;
- * int blocksize;
- * int flags;
- * } ;
- *
- * flags is a bitmask, currently, the only defined flag is:
- *
- * 0x01 - verify media after format.
- */
- if (get_user(blocks, arg) ||
- get_user(length, arg+1) ||
- get_user(flags, arg+2)) {
- err = -EFAULT;
- goto out;
- }
-
- (void) idefloppy_get_sfrp_bit(drive);
- idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
-
- if (idefloppy_queue_pc_tail(drive, &pc))
- err = -EIO;
-
-out:
- if (err)
- drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
- return err;
-}
-
-
-static int idefloppy_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct block_device *bdev = inode->i_bdev;
- struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
- ide_drive_t *drive = floppy->drive;
- struct ide_atapi_pc pc;
- void __user *argp = (void __user *)arg;
- int err;
-
- switch (cmd) {
- case CDROMEJECT:
- /* fall through */
- case CDROM_LOCKDOOR:
- return ide_floppy_lockdoor(drive, &pc, arg, cmd);
- case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
- return 0;
- case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return ide_floppy_get_format_capacities(drive, argp);
- case IDEFLOPPY_IOCTL_FORMAT_START:
- if (!(file->f_mode & 2))
- return -EPERM;
-
- return ide_floppy_format_unit(floppy, (int __user *)arg);
- case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- return idefloppy_get_format_progress(drive, argp);
- }
-
- /*
- * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
- * and CDROM_SEND_PACKET (legacy) ioctls
- */
- if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
- err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
- bdev->bd_disk, cmd, argp);
- else
- err = -ENOTTY;
-
- if (err == -ENOTTY)
- err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
- return err;
-}
-
static int idefloppy_media_changed(struct gendisk *disk)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
ide_drive_t *drive = floppy->drive;
int ret;
/* do not scan partitions twice if this is a removable device */
- if (drive->attach) {
- drive->attach = 0;
+ if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+ drive->dev_flags &= ~IDE_DFLAG_ATTACH;
return 0;
}
ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
@@ -1366,8 +750,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
static int idefloppy_revalidate_disk(struct gendisk *disk)
{
- struct ide_floppy_obj *floppy = ide_floppy_g(disk);
- set_capacity(disk, idefloppy_capacity(floppy->drive));
+ struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
+ set_capacity(disk, ide_floppy_capacity(floppy->drive));
return 0;
}
@@ -1375,7 +759,7 @@ static struct block_device_operations idefloppy_ops = {
.owner = THIS_MODULE,
.open = idefloppy_open,
.release = idefloppy_release,
- .ioctl = idefloppy_ioctl,
+ .ioctl = ide_floppy_ioctl,
.getgeo = idefloppy_getgeo,
.media_changed = idefloppy_media_changed,
.revalidate_disk = idefloppy_revalidate_disk
@@ -1388,19 +772,19 @@ static int ide_floppy_probe(ide_drive_t *drive)
if (!strstr("ide-floppy", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_floppy)
goto failed;
- if (!idefloppy_identify_device(drive, drive->id)) {
- printk(KERN_ERR "ide-floppy: %s: not supported by this version"
- " of ide-floppy\n", drive->name);
+
+ if (!ide_check_atapi_device(drive, DRV_NAME)) {
+ printk(KERN_ERR PFX "%s: not supported by this version of "
+ DRV_NAME "\n", drive->name);
goto failed;
}
floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
if (!floppy) {
- printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
- " structure\n", drive->name);
+ printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
+ drive->name);
goto failed;
}
@@ -1410,8 +794,6 @@ static int ide_floppy_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idefloppy_driver);
-
kref_init(&floppy->kref);
floppy->drive = drive;
@@ -1422,13 +804,16 @@ static int ide_floppy_probe(ide_drive_t *drive)
drive->driver_data = floppy;
+ drive->debug_mask = debug_mask;
+
idefloppy_setup(drive, floppy);
+ drive->dev_flags |= IDE_DFLAG_ATTACH;
g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev;
- g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
g->fops = &idefloppy_ops;
- drive->attach = 1;
add_disk(g);
return 0;
@@ -1445,11 +830,12 @@ static void __exit idefloppy_exit(void)
static int __init idefloppy_init(void)
{
- printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
+ printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
return driver_register(&idefloppy_driver.gen_driver);
}
MODULE_ALIAS("ide:*m-floppy*");
+MODULE_ALIAS("ide-floppy");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h
new file mode 100644
index 00000000000..17cf865e583
--- /dev/null
+++ b/drivers/ide/ide-floppy.h
@@ -0,0 +1,62 @@
+#ifndef __IDE_FLOPPY_H
+#define __IDE_FLOPPY_H
+
+/*
+ * Most of our global data which we need to save even as we leave the driver
+ * due to an interrupt or a timer event is stored in a variable of type
+ * idefloppy_floppy_t, defined below.
+ */
+typedef struct ide_floppy_obj {
+ ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
+
+ /* Last failed packet command */
+ struct ide_atapi_pc *failed_pc;
+ /* used for blk_{fs,pc}_request() requests */
+ struct ide_atapi_pc queued_pc;
+
+ /* Last error information */
+ u8 sense_key, asc, ascq;
+
+ int progress_indication;
+
+ /* Device information */
+ /* Current format */
+ int blocks, block_size, bs_factor;
+ /* Last format capacity descriptor */
+ u8 cap_desc[8];
+ /* Copy of the flexible disk page */
+ u8 flexible_disk_page[32];
+} idefloppy_floppy_t;
+
+/*
+ * Pages of the SELECT SENSE / MODE SENSE packet commands.
+ * See SFF-8070i spec.
+ */
+#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
+#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
+
+/* IOCTLs used in low-level formatting. */
+#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
+#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
+#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
+#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
+
+/* ide-floppy.c */
+void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
+void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
+sector_t ide_floppy_capacity(ide_drive_t *);
+
+/* ide-floppy_ioctl.c */
+int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-floppy_proc.c */
+extern ide_proc_entry_t ide_floppy_proc[];
+extern const struct ide_proc_devset ide_floppy_settings[];
+#endif
+
+#endif /*__IDE_FLOPPY_H */
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
new file mode 100644
index 00000000000..a3a7a0809e2
--- /dev/null
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -0,0 +1,293 @@
+/*
+ * ide-floppy IOCTLs handling.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/cdrom.h>
+
+#include <asm/unaligned.h>
+
+#include <scsi/scsi_ioctl.h>
+
+#include "ide-floppy.h"
+
+/*
+ * Obtain the list of formattable capacities.
+ * Very similar to ide_floppy_get_capacity, except that we push the capacity
+ * descriptors to userland, instead of our own structures.
+ *
+ * Userland gives us the following structure:
+ *
+ * struct idefloppy_format_capacities {
+ * int nformats;
+ * struct {
+ * int nblocks;
+ * int blocksize;
+ * } formats[];
+ * };
+ *
+ * userland initializes nformats to the number of allocated formats[] records.
+ * On exit we set nformats to the number of records we've actually initialized.
+ */
+
+static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+{
+ struct ide_floppy_obj *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+ u8 header_len, desc_cnt;
+ int i, blocks, length, u_array_size, u_index;
+ int __user *argp;
+
+ if (get_user(u_array_size, arg))
+ return -EFAULT;
+
+ if (u_array_size <= 0)
+ return -EINVAL;
+
+ ide_floppy_create_read_capacity_cmd(&pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
+ printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ return -EIO;
+ }
+
+ header_len = pc.buf[3];
+ desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+
+ u_index = 0;
+ argp = arg + 1;
+
+ /*
+ * We always skip the first capacity descriptor. That's the current
+ * capacity. We are interested in the remaining descriptors, the
+ * formattable capacities.
+ */
+ for (i = 1; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
+
+ if (u_index >= u_array_size)
+ break; /* User-supplied buffer too small */
+
+ blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
+ length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
+
+ if (put_user(blocks, argp))
+ return -EFAULT;
+
+ ++argp;
+
+ if (put_user(length, argp))
+ return -EFAULT;
+
+ ++argp;
+
+ ++u_index;
+ }
+
+ if (put_user(u_index, arg))
+ return -EFAULT;
+
+ return 0;
+}
+
+static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
+ int l, int flags)
+{
+ ide_init_pc(pc);
+ pc->c[0] = GPCMD_FORMAT_UNIT;
+ pc->c[1] = 0x17;
+
+ memset(pc->buf, 0, 12);
+ pc->buf[1] = 0xA2;
+ /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
+
+ if (flags & 1) /* Verify bit on... */
+ pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
+ pc->buf[3] = 8;
+
+ put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
+ put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
+ pc->buf_size = 12;
+ pc->flags |= PC_FLAG_WRITING;
+}
+
+static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+
+ drive->atapi_flags &= ~IDE_AFLAG_SRFP;
+
+ ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
+ pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ return 1;
+
+ if (pc.buf[8 + 2] & 0x40)
+ drive->atapi_flags |= IDE_AFLAG_SRFP;
+
+ return 0;
+}
+
+static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+ int blocks, length, flags, err = 0;
+
+ if (floppy->openers > 1) {
+ /* Don't format if someone is using the disk */
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ return -EBUSY;
+ }
+
+ drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
+
+ /*
+ * Send ATAPI_FORMAT_UNIT to the drive.
+ *
+ * Userland gives us the following structure:
+ *
+ * struct idefloppy_format_command {
+ * int nblocks;
+ * int blocksize;
+ * int flags;
+ * } ;
+ *
+ * flags is a bitmask, currently, the only defined flag is:
+ *
+ * 0x01 - verify media after format.
+ */
+ if (get_user(blocks, arg) ||
+ get_user(length, arg+1) ||
+ get_user(flags, arg+2)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ (void)ide_floppy_get_sfrp_bit(drive);
+ ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);
+
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ err = -EIO;
+
+out:
+ if (err)
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
+ return err;
+}
+
+/*
+ * Get ATAPI_FORMAT_UNIT progress indication.
+ *
+ * Userland gives a pointer to an int. The int is set to a progress
+ * indicator 0-65536, with 65536=100%.
+ *
+ * If the drive does not support format progress indication, we just check
+ * the dsc bit, and return either 0 or 65536.
+ */
+
+static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_atapi_pc pc;
+ int progress_indication = 0x10000;
+
+ if (drive->atapi_flags & IDE_AFLAG_SRFP) {
+ ide_create_request_sense_cmd(drive, &pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ return -EIO;
+
+ if (floppy->sense_key == 2 &&
+ floppy->asc == 4 &&
+ floppy->ascq == 4)
+ progress_indication = floppy->progress_indication;
+
+ /* Else assume format_unit has finished, and we're at 0x10000 */
+ } else {
+ ide_hwif_t *hwif = drive->hwif;
+ unsigned long flags;
+ u8 stat;
+
+ local_irq_save(flags);
+ stat = hwif->tp_ops->read_status(hwif);
+ local_irq_restore(flags);
+
+ progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000;
+ }
+
+ if (put_user(progress_indication, arg))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned long arg, unsigned int cmd)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = floppy->disk;
+ int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
+
+ if (floppy->openers > 1)
+ return -EBUSY;
+
+ ide_set_media_lock(drive, disk, prevent);
+
+ if (cmd == CDROMEJECT)
+ ide_do_start_stop(drive, disk, 2);
+
+ return 0;
+}
+
+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
+ unsigned int cmd, void __user *argp)
+{
+ switch (cmd) {
+ case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+ return 0;
+ case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+ return ide_floppy_get_format_capacities(drive, argp);
+ case IDEFLOPPY_IOCTL_FORMAT_START:
+ if (!(file->f_mode & 2))
+ return -EPERM;
+ return ide_floppy_format_unit(drive, (int __user *)argp);
+ case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+ return ide_floppy_get_format_progress(drive, argp);
+ default:
+ return -ENOTTY;
+ }
+}
+
+int ide_floppy_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
+ ide_floppy_obj);
+ ide_drive_t *drive = floppy->drive;
+ struct ide_atapi_pc pc;
+ void __user *argp = (void __user *)arg;
+ int err;
+
+ if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
+ return ide_floppy_lockdoor(drive, &pc, arg, cmd);
+
+ err = ide_floppy_format_ioctl(drive, file, cmd, argp);
+ if (err != -ENOTTY)
+ return err;
+
+ /*
+ * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
+ * and CDROM_SEND_PACKET (legacy) ioctls
+ */
+ if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
+ err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
+ bdev->bd_disk, cmd, argp);
+
+ if (err == -ENOTTY)
+ err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+
+ return err;
+}
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
new file mode 100644
index 00000000000..76f0c6c4eca
--- /dev/null
+++ b/drivers/ide/ide-floppy_proc.c
@@ -0,0 +1,33 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+#include "ide-floppy.h"
+
+static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
+
+ len = sprintf(page, "%llu\n", (long long)ide_floppy_capacity(drive));
+ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+ide_proc_entry_t ide_floppy_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
+ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(ticks, pc_delay);
+
+const struct ide_proc_devset ide_floppy_settings[] = {
+ IDE_PROC_DEVSET(bios_cyl, 0, 1023),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(ticks, 0, 255),
+ { 0 },
+};
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 8fe8b5b9cf7..81a5282ce1e 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ide.h>
+#include <linux/pci_ids.h>
/* FIXME: convert m32r to use ide_platform host driver */
#ifdef CONFIG_M32R
@@ -27,7 +28,7 @@
#define DRV_NAME "ide_generic"
-static int probe_mask = 0x03;
+static int probe_mask;
module_param(probe_mask, int, 0);
MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
@@ -100,27 +101,64 @@ static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 };
#endif
+static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary)
+{
+ struct pci_dev *p = NULL;
+ u16 val;
+
+ for_each_pci_dev(p) {
+
+ if (pci_resource_start(p, 0) == 0x1f0)
+ *primary = 1;
+ if (pci_resource_start(p, 2) == 0x170)
+ *secondary = 1;
+
+ /* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */
+ if (p->vendor == PCI_VENDOR_ID_CYRIX &&
+ (p->device == PCI_DEVICE_ID_CYRIX_5510 ||
+ p->device == PCI_DEVICE_ID_CYRIX_5520))
+ *primary = *secondary = 1;
+
+ /* Intel MPIIX - PIO ATA on non PCI side of bridge */
+ if (p->vendor == PCI_VENDOR_ID_INTEL &&
+ p->device == PCI_DEVICE_ID_INTEL_82371MX) {
+
+ pci_read_config_word(p, 0x6C, &val);
+ if (val & 0x8000) {
+ /* ATA port enabled */
+ if (val & 0x4000)
+ *secondary = 1;
+ else
+ *primary = 1;
+ }
+ }
+ }
+}
+
static int __init ide_generic_init(void)
{
- hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
- struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
unsigned long io_addr;
- int i, rc;
+ int i, rc = 0, primary = 0, secondary = 0;
-#ifdef CONFIG_MIPS
- if (!ide_probe_legacy())
- return -ENODEV;
-#endif
- printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
- "parameter for probing all legacy ISA IDE ports\n");
+ ide_generic_check_pci_legacy_iobases(&primary, &secondary);
+
+ if (!probe_mask) {
+ printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" "
+ "module parameter for probing all legacy ISA IDE ports\n");
+
+ if (primary == 0)
+ probe_mask |= 0x1;
- memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
+ if (secondary == 0)
+ probe_mask |= 0x2;
+ } else
+ printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports "
+ "upon user request\n");
for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
io_addr = legacy_bases[i];
- hws[i] = NULL;
-
if ((probe_mask & (1 << i)) && io_addr) {
if (!request_region(io_addr, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX "
@@ -137,45 +175,27 @@ static int __init ide_generic_init(void)
continue;
}
- memset(&hw[i], 0, sizeof(hw[i]));
- ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
+ memset(&hw, 0, sizeof(hw));
+ ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
#ifdef CONFIG_IA64
- hw[i].irq = isa_irq_to_vector(legacy_irqs[i]);
+ hw.irq = isa_irq_to_vector(legacy_irqs[i]);
#else
- hw[i].irq = legacy_irqs[i];
+ hw.irq = legacy_irqs[i];
#endif
- hw[i].chipset = ide_generic;
+ hw.chipset = ide_generic;
- hws[i] = &hw[i];
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc) {
+ release_region(io_addr + 0x206, 1);
+ release_region(io_addr, 8);
+ }
}
}
- host = ide_host_alloc_all(NULL, hws);
- if (host == NULL) {
- rc = -ENOMEM;
- goto err;
- }
-
- rc = ide_host_register(host, NULL, hws);
- if (rc)
- goto err_free;
-
if (ide_generic_sysfs_init())
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
"class\n");
- return 0;
-err_free:
- ide_host_free(host);
-err:
- for (i = 0; i < MAX_HWIFS; i++) {
- if (hws[i] == NULL)
- continue;
-
- io_addr = hws[i]->io_ports.data_addr;
- release_region(io_addr + 0x206, 1);
- release_region(io_addr, 8);
- }
return rc;
}
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a896a283f27..7162d67562a 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -40,6 +40,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/completion.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
@@ -77,8 +78,9 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
* decide whether to reenable DMA -- 3 is a random magic for now,
* if we DMA timeout more than 3 times, just stay in PIO
*/
- if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
- drive->state = 0;
+ if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
+ drive->retry_pio <= 3) {
+ drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
ide_dma_on(drive);
}
@@ -130,21 +132,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
}
EXPORT_SYMBOL(ide_end_request);
-/*
- * Power Management state machine. This one is rather trivial for now,
- * we should probably add more, like switching back to PIO on suspend
- * to help some BIOSes, re-do the door locking on resume, etc...
- */
-
-enum {
- ide_pm_flush_cache = ide_pm_state_start_suspend,
- idedisk_pm_standby,
-
- idedisk_pm_restore_pio = ide_pm_state_start_resume,
- idedisk_pm_idle,
- ide_pm_restore_dma,
-};
-
static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
{
struct request_pm_state *pm = rq->data;
@@ -153,20 +140,20 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
return;
switch (pm->pm_step) {
- case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
if (pm->pm_state == PM_EVENT_FREEZE)
- pm->pm_step = ide_pm_state_completed;
+ pm->pm_step = IDE_PM_COMPLETED;
else
- pm->pm_step = idedisk_pm_standby;
+ pm->pm_step = IDE_PM_STANDBY;
break;
- case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
- pm->pm_step = ide_pm_state_completed;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ pm->pm_step = IDE_PM_COMPLETED;
break;
- case idedisk_pm_restore_pio: /* Resume step 1 complete */
- pm->pm_step = idedisk_pm_idle;
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
+ pm->pm_step = IDE_PM_IDLE;
break;
- case idedisk_pm_idle: /* Resume step 2 (idle) complete */
- pm->pm_step = ide_pm_restore_dma;
+ case IDE_PM_IDLE: /* Resume step 2 (idle)*/
+ pm->pm_step = IDE_PM_RESTORE_DMA;
break;
}
}
@@ -179,40 +166,37 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
memset(args, 0, sizeof(*args));
switch (pm->pm_step) {
- case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
if (drive->media != ide_disk)
break;
/* Not supported? Switch to next step now. */
- if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
+ if (ata_id_flush_enabled(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
ide_complete_power_step(drive, rq, 0, 0);
return ide_stopped;
}
- if (ide_id_has_flush_cache_ext(drive->id))
- args->tf.command = WIN_FLUSH_CACHE_EXT;
+ if (ata_id_flush_ext_enabled(drive->id))
+ args->tf.command = ATA_CMD_FLUSH_EXT;
else
- args->tf.command = WIN_FLUSH_CACHE;
+ args->tf.command = ATA_CMD_FLUSH;
goto out_do_tf;
-
- case idedisk_pm_standby: /* Suspend step 2 (standby) */
- args->tf.command = WIN_STANDBYNOW1;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ args->tf.command = ATA_CMD_STANDBYNOW1;
goto out_do_tf;
-
- case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
/*
- * skip idedisk_pm_idle for ATAPI devices
+ * skip IDE_PM_IDLE for ATAPI devices
*/
if (drive->media != ide_disk)
- pm->pm_step = ide_pm_restore_dma;
+ pm->pm_step = IDE_PM_RESTORE_DMA;
else
ide_complete_power_step(drive, rq, 0, 0);
return ide_stopped;
-
- case idedisk_pm_idle: /* Resume step 2 (idle) */
- args->tf.command = WIN_IDLEIMMEDIATE;
+ case IDE_PM_IDLE: /* Resume step 2 (idle) */
+ args->tf.command = ATA_CMD_IDLEIMMEDIATE;
goto out_do_tf;
-
- case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */
+ case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
/*
* Right now, all we do is call ide_set_dma(drive),
* we could be smarter and check for current xfer_speed
@@ -221,12 +205,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
if (drive->hwif->dma_ops == NULL)
break;
/*
- * TODO: respect ->using_dma setting
+ * TODO: respect IDE_DFLAG_USING_DMA
*/
ide_set_dma(drive);
break;
}
- pm->pm_step = ide_pm_state_completed;
+
+ pm->pm_step = IDE_PM_COMPLETED;
return ide_stopped;
out_do_tf:
@@ -286,7 +271,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
if (blk_pm_suspend_request(rq)) {
blk_stop_queue(drive->queue);
} else {
- drive->blocked = 0;
+ drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
blk_start_queue(drive->queue);
}
HWGROUP(drive)->rq = NULL;
@@ -322,7 +307,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
ide_task_t *task = (ide_task_t *)rq->special;
if (rq->errors == 0)
- rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
+ rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
if (task) {
struct ide_taskfile *tf = &task->tf;
@@ -342,7 +327,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
drive->name, rq->pm->pm_step, stat, err);
#endif
ide_complete_power_step(drive, rq, stat, err);
- if (pm->pm_step == ide_pm_state_completed)
+ if (pm->pm_step == IDE_PM_COMPLETED)
ide_complete_pm_request(drive, rq);
return;
}
@@ -373,29 +358,30 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
{
ide_hwif_t *hwif = drive->hwif;
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
- } else if (stat & ERR_STAT) {
+ } else if (stat & ATA_ERR) {
/* err has different meaning on cdrom and tape */
- if (err == ABRT_ERR) {
- if (drive->select.b.lba &&
- /* some newer drives don't support WIN_SPECIFY */
- hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
+ if (err == ATA_ABORTED) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA) &&
+ /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
+ hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
- } else if (err & (BBD_ERR | ECC_ERR)) {
+ } else if (err & (ATA_BBK | ATA_UNC)) {
/* retries won't help these */
rq->errors = ERROR_MAX;
- } else if (err & TRK0_ERR) {
+ } else if (err & ATA_TRK0NF) {
/* help it find track zero */
rq->errors |= ERROR_RECAL;
}
}
- if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ &&
+ if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
(hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
int nsect = drive->mult_count ? drive->mult_count : 1;
@@ -407,7 +393,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
return ide_stopped;
}
- if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -427,16 +413,17 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
{
ide_hwif_t *hwif = drive->hwif;
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
- if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
/* force an abort */
- hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq);
@@ -508,20 +495,20 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
tf->lbal = drive->sect;
tf->lbam = drive->cyl;
tf->lbah = drive->cyl >> 8;
- tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
- tf->command = WIN_SPECIFY;
+ tf->device = (drive->head - 1) | drive->select;
+ tf->command = ATA_CMD_INIT_DEV_PARAMS;
}
static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->sect;
- tf->command = WIN_RESTORE;
+ tf->command = ATA_CMD_RESTORE;
}
static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->mult_req;
- tf->command = WIN_SETMULT;
+ tf->command = ATA_CMD_SET_MULTI;
}
static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -540,8 +527,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
ide_tf_set_restore_cmd(drive, &args.tf);
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
- if (drive->mult_req > drive->id->max_multsect)
- drive->mult_req = drive->id->max_multsect;
ide_tf_set_setmult_cmd(drive, &args.tf);
} else if (s->all) {
int special = s->all;
@@ -558,37 +543,14 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
return ide_started;
}
-/*
- * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
- */
-static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
-{
- switch (req_pio) {
- case 202:
- case 201:
- case 200:
- case 102:
- case 101:
- case 100:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
- case 9:
- case 8:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
- case 7:
- case 6:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
- default:
- return 0;
- }
-}
-
/**
* do_special - issue some special commands
* @drive: drive the command is for
*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- * commands to a drive. It used to do much more, but has been scaled
- * back.
+ * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
+ * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
+ *
+ * It used to do much more, but has been scaled back.
*/
static ide_startstop_t do_special (ide_drive_t *drive)
@@ -598,45 +560,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
#ifdef DEBUG
printk("%s: do_special: 0x%02x\n", drive->name, s->all);
#endif
- if (s->b.set_tune) {
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
- u8 req_pio = drive->tune_req;
-
- s->b.set_tune = 0;
-
- if (set_pio_mode_abuse(drive->hwif, req_pio)) {
- /*
- * take ide_lock for drive->[no_]unmask/[no_]io_32bit
- */
- if (req_pio == 8 || req_pio == 9) {
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
- port_ops->set_pio_mode(drive, req_pio);
- spin_unlock_irqrestore(&ide_lock, flags);
- } else
- port_ops->set_pio_mode(drive, req_pio);
- } else {
- int keep_dma = drive->using_dma;
-
- ide_set_pio(drive, req_pio);
-
- if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
- if (keep_dma)
- ide_dma_on(drive);
- }
- }
-
- return ide_stopped;
- } else {
- if (drive->media == ide_disk)
- return ide_disk_special(drive);
+ if (drive->media == ide_disk)
+ return ide_disk_special(drive);
- s->all = 0;
- drive->mult_req = 0;
- return ide_stopped;
- }
+ s->all = 0;
+ drive->mult_req = 0;
+ return ide_stopped;
}
void ide_map_sg(ide_drive_t *drive, struct request *rq)
@@ -716,9 +645,71 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return ide_stopped;
}
+int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
+ int arg)
+{
+ struct request_queue *q = drive->queue;
+ struct request *rq;
+ int ret = 0;
+
+ if (!(setting->flags & DS_SYNC))
+ return setting->set(drive, arg);
+
+ rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_len = 5;
+ rq->cmd[0] = REQ_DEVSET_EXEC;
+ *(int *)&rq->cmd[1] = arg;
+ rq->special = setting->set;
+
+ if (blk_execute_rq(q, NULL, rq, 0))
+ ret = rq->errors;
+ blk_put_request(rq);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ide_devset_execute);
+
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
{
- switch (rq->cmd[0]) {
+ u8 cmd = rq->cmd[0];
+
+ if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
+ ide_task_t task;
+ struct ide_taskfile *tf = &task.tf;
+
+ memset(&task, 0, sizeof(task));
+ if (cmd == REQ_PARK_HEADS) {
+ drive->sleep = *(unsigned long *)rq->special;
+ drive->dev_flags |= IDE_DFLAG_SLEEPING;
+ tf->command = ATA_CMD_IDLEIMMEDIATE;
+ tf->feature = 0x44;
+ tf->lbal = 0x4c;
+ tf->lbam = 0x4e;
+ tf->lbah = 0x55;
+ task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+ } else /* cmd == REQ_UNPARK_HEADS */
+ tf->command = ATA_CMD_CHK_POWER;
+
+ task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ task.rq = rq;
+ drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
+ return do_rw_taskfile(drive, &task);
+ }
+
+ switch (cmd) {
+ case REQ_DEVSET_EXEC:
+ {
+ int err, (*setfunc)(ide_drive_t *, int) = rq->special;
+
+ err = setfunc(drive, *(int *)&rq->cmd[1]);
+ if (err)
+ rq->errors = err;
+ else
+ err = 1;
+ ide_end_request(drive, err, 0);
+ return ide_stopped;
+ }
case REQ_DRIVE_RESET:
return ide_do_reset(drive);
default:
@@ -733,11 +724,11 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
struct request_pm_state *pm = rq->data;
if (blk_pm_suspend_request(rq) &&
- pm->pm_step == ide_pm_state_start_suspend)
+ pm->pm_step == IDE_PM_START_SUSPEND)
/* Mark drive blocked when starting the suspend sequence. */
- drive->blocked = 1;
+ drive->dev_flags |= IDE_DFLAG_BLOCKED;
else if (blk_pm_resume_request(rq) &&
- pm->pm_step == ide_pm_state_start_resume) {
+ pm->pm_step == IDE_PM_START_RESUME) {
/*
* The first thing we do on wakeup is to wait for BSY bit to
* go away (with a looong timeout) as a drive on this hwif may
@@ -766,9 +757,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* start_request - start of I/O and command issuing for IDE
*
* start_request() initiates handling of a new I/O request. It
- * accepts commands and I/O (read/write) requests. It also does
- * the final remapping for weird stuff like EZDrive. Once
- * device mapper can work sector level the EZDrive stuff can go away
+ * accepts commands and I/O (read/write) requests.
*
* FIXME: this function needs a rename
*/
@@ -776,7 +765,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
- sector_t block;
BUG_ON(!blk_rq_started(rq));
@@ -791,21 +779,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
goto kill_rq;
}
- block = rq->sector;
- if (blk_fs_request(rq) &&
- (drive->media == ide_disk || drive->media == ide_floppy)) {
- block += drive->sect0;
- }
- /* Yecch - this will shift the entire interval,
- possibly killing some innocent following sector */
- if (block == 0 && drive->remap_0_to_1 == 1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
-
if (blk_pm_request(rq))
ide_check_pm_state(drive, rq);
SELECT_DRIVE(drive);
- if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+ if (ide_wait_stat(&startstop, drive, drive->ready_stat,
+ ATA_BUSY | ATA_DRQ, WAIT_READY)) {
printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
return startstop;
}
@@ -829,7 +808,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
#endif
startstop = ide_start_power_step(drive, rq);
if (startstop == ide_stopped &&
- pm->pm_step == ide_pm_state_completed)
+ pm->pm_step == IDE_PM_COMPLETED)
ide_complete_pm_request(drive, rq);
return startstop;
} else if (!rq->rq_disk && blk_special_request(rq))
@@ -844,7 +823,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
return ide_special_rq(drive, rq);
drv = *(ide_driver_t **)rq->rq_disk->private_data;
- return drv->do_request(drive, rq, block);
+
+ return drv->do_request(drive, rq, rq->sector);
}
return do_special(drive);
kill_rq:
@@ -866,7 +846,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
if (timeout > WAIT_WORSTCASE)
timeout = WAIT_WORSTCASE;
drive->sleep = timeout + jiffies;
- drive->sleeping = 1;
+ drive->dev_flags |= IDE_DFLAG_SLEEPING;
}
EXPORT_SYMBOL(ide_stall_queue);
@@ -906,18 +886,23 @@ repeat:
}
do {
- if ((!drive->sleeping || time_after_eq(jiffies, drive->sleep))
- && !elv_queue_empty(drive->queue)) {
- if (!best
- || (drive->sleeping && (!best->sleeping || time_before(drive->sleep, best->sleep)))
- || (!best->sleeping && time_before(WAKEUP(drive), WAKEUP(best))))
- {
+ u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
+ u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
+
+ if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
+ !elv_queue_empty(drive->queue)) {
+ if (best == NULL ||
+ (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
+ (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
if (!blk_queue_plugged(drive->queue))
best = drive;
}
}
} while ((drive = drive->next) != hwgroup->drive);
- if (best && best->nice1 && !best->sleeping && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+
+ if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
+ (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
+ best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
long t = (signed long)(WAKEUP(best) - jiffies);
if (t >= WAIT_MIN_SLEEP) {
/*
@@ -926,7 +911,7 @@ repeat:
*/
drive = best->next;
do {
- if (!drive->sleeping
+ if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
&& time_before(jiffies - best->service_time, WAKEUP(drive))
&& time_before(WAKEUP(drive), jiffies + t))
{
@@ -997,7 +982,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
hwgroup->rq = NULL;
drive = hwgroup->drive;
do {
- if (drive->sleeping && (!sleeping || time_before(drive->sleep, sleep))) {
+ if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
+ (sleeping == 0 ||
+ time_before(drive->sleep, sleep))) {
sleeping = 1;
sleep = drive->sleep;
}
@@ -1046,7 +1033,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
- drive->sleeping = 0;
+ drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
drive->service_start = jiffies;
if (blk_queue_plugged(drive->queue)) {
@@ -1080,7 +1067,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* We count how many times we loop here to make sure we service
* all drives in the hwgroup without looping for ever
*/
- if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
+ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
+ blk_pm_request(rq) == 0 &&
+ (rq->cmd_flags & REQ_PREEMPT) == 0) {
drive = drive->next ? drive->next : hwgroup->drive;
if (loops++ < 4 && !blk_queue_plugged(drive->queue))
goto again;
@@ -1153,8 +1142,8 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
* a timeout -- we'll reenable after we finish this next request
* (or rather the first chunk of it) in pio.
*/
+ drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
drive->retry_pio++;
- drive->state = DMA_PIO_RETRY;
ide_dma_off_quietly(drive);
/*
@@ -1325,7 +1314,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
if (hwif->irq == irq) {
stat = hwif->tp_ops->read_status(hwif);
- if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+ if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime, count;
++count;
@@ -1451,23 +1440,16 @@ irqreturn_t ide_intr (int irq, void *dev_id)
del_timer(&hwgroup->timer);
spin_unlock(&ide_lock);
- /* Some controllers might set DMA INTR no matter DMA or PIO;
- * bmdma status might need to be cleared even for
- * PIO interrupts to prevent spurious/lost irq.
- */
- if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
- /* ide_dma_end() needs bmdma status for error checking.
- * So, skip clearing bmdma status here and leave it
- * to ide_dma_end() if this is dma interrupt.
- */
- hwif->ide_dma_clear_irq(drive);
+ if (hwif->port_ops && hwif->port_ops->clear_irq)
+ hwif->port_ops->clear_irq(drive);
- if (drive->unmask)
+ if (drive->dev_flags & IDE_DFLAG_UNMASK)
local_irq_enable_in_hardirq();
+
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&ide_lock);
/*
* Note that handler() may have set things up for another
* interrupt to occur soon, but it cannot happen until
@@ -1511,8 +1493,8 @@ void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
spin_lock_irqsave(&ide_lock, flags);
hwgroup->rq = NULL;
- __elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 1);
- __generic_unplug_device(drive->queue);
+ __elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
+ blk_start_queueing(drive->queue);
spin_unlock_irqrestore(&ide_lock, flags);
}
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
new file mode 100644
index 00000000000..a90945f4979
--- /dev/null
+++ b/drivers/ide/ide-ioctls.c
@@ -0,0 +1,299 @@
+/*
+ * IDE ioctls handling.
+ */
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+static const struct ide_ioctl_devset ide_ioctl_settings[] = {
+{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit },
+{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings },
+{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq },
+{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma },
+{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode },
+{ 0 }
+};
+
+int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
+ unsigned int cmd, unsigned long arg,
+ const struct ide_ioctl_devset *s)
+{
+ const struct ide_devset *ds;
+ unsigned long flags;
+ int err = -EOPNOTSUPP;
+
+ for (; (ds = s->setting); s++) {
+ if (ds->get && s->get_ioctl == cmd)
+ goto read_val;
+ else if (ds->set && s->set_ioctl == cmd)
+ goto set_val;
+ }
+
+ return err;
+
+read_val:
+ mutex_lock(&ide_setting_mtx);
+ spin_lock_irqsave(&ide_lock, flags);
+ err = ds->get(drive);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ mutex_unlock(&ide_setting_mtx);
+ return err >= 0 ? put_user(err, (long __user *)arg) : err;
+
+set_val:
+ if (bdev != bdev->bd_contains)
+ err = -EINVAL;
+ else {
+ if (!capable(CAP_SYS_ADMIN))
+ err = -EACCES;
+ else {
+ mutex_lock(&ide_setting_mtx);
+ err = ide_devset_execute(drive, ds, arg);
+ mutex_unlock(&ide_setting_mtx);
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(ide_setting_ioctl);
+
+static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
+ unsigned long arg)
+{
+ u16 *id = NULL;
+ int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
+ int rc = 0;
+
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
+ rc = -ENOMSG;
+ goto out;
+ }
+
+ id = kmalloc(size, GFP_KERNEL);
+ if (id == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(id, drive->id, size);
+ ata_id_to_hd_driveid(id);
+
+ if (copy_to_user((void __user *)arg, id, size))
+ rc = -EFAULT;
+
+ kfree(id);
+out:
+ return rc;
+}
+
+static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
+ << IDE_NICE_DSC_OVERLAP) |
+ (!!(drive->dev_flags & IDE_DFLAG_NICE1)
+ << IDE_NICE_1), (long __user *)arg);
+}
+
+static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+ return -EPERM;
+
+ if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
+ (drive->media == ide_disk || drive->media == ide_floppy ||
+ (drive->dev_flags & IDE_DFLAG_SCSI)))
+ return -EPERM;
+
+ if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
+ if ((arg >> IDE_NICE_1) & 1)
+ drive->dev_flags |= IDE_DFLAG_NICE1;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_NICE1;
+
+ return 0;
+}
+
+static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+{
+ u8 *buf = NULL;
+ int bufsize = 0, err = 0;
+ u8 args[4], xfer_rate = 0;
+ ide_task_t tfargs;
+ struct ide_taskfile *tf = &tfargs.tf;
+ u16 *id = drive->id;
+
+ if (NULL == (void *) arg) {
+ struct request *rq;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ err = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
+
+ return err;
+ }
+
+ if (copy_from_user(args, (void __user *)arg, 4))
+ return -EFAULT;
+
+ memset(&tfargs, 0, sizeof(ide_task_t));
+ tf->feature = args[2];
+ if (args[0] == ATA_CMD_SMART) {
+ tf->nsect = args[3];
+ tf->lbal = args[1];
+ tf->lbam = 0x4f;
+ tf->lbah = 0xc2;
+ tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
+ } else {
+ tf->nsect = args[1];
+ tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
+ IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
+ }
+ tf->command = args[0];
+ tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
+
+ if (args[3]) {
+ tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+ bufsize = SECTOR_SIZE * args[3];
+ buf = kzalloc(bufsize, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ }
+
+ if (tf->command == ATA_CMD_SET_FEATURES &&
+ tf->feature == SETFEATURES_XFER &&
+ tf->nsect >= XFER_SW_DMA_0 &&
+ (id[ATA_ID_UDMA_MODES] ||
+ id[ATA_ID_MWDMA_MODES] ||
+ id[ATA_ID_SWDMA_MODES])) {
+ xfer_rate = args[1];
+ if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
+ printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
+ "be set\n", drive->name);
+ goto abort;
+ }
+ }
+
+ err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
+
+ args[0] = tf->status;
+ args[1] = tf->error;
+ args[2] = tf->nsect;
+
+ if (!err && xfer_rate) {
+ /* active-retuning-calls future */
+ ide_set_xfer_rate(drive, xfer_rate);
+ ide_driveid_update(drive);
+ }
+abort:
+ if (copy_to_user((void __user *)arg, &args, 4))
+ err = -EFAULT;
+ if (buf) {
+ if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
+ err = -EFAULT;
+ kfree(buf);
+ }
+ return err;
+}
+
+static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+{
+ void __user *p = (void __user *)arg;
+ int err = 0;
+ u8 args[7];
+ ide_task_t task;
+
+ if (copy_from_user(args, p, 7))
+ return -EFAULT;
+
+ memset(&task, 0, sizeof(task));
+ memcpy(&task.tf_array[7], &args[1], 6);
+ task.tf.command = args[0];
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ err = ide_no_data_taskfile(drive, &task);
+
+ args[0] = task.tf.command;
+ memcpy(&args[1], &task.tf_array[7], 6);
+
+ if (copy_to_user(p, args, 7))
+ err = -EFAULT;
+
+ return err;
+}
+
+static int generic_drive_reset(ide_drive_t *drive)
+{
+ struct request *rq;
+ int ret = 0;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_len = 1;
+ rq->cmd[0] = REQ_DRIVE_RESET;
+ rq->cmd_flags |= REQ_SOFTBARRIER;
+ if (blk_execute_rq(drive->queue, NULL, rq, 1))
+ ret = rq->errors;
+ blk_put_request(rq);
+ return ret;
+}
+
+int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
+ struct block_device *bdev,
+ unsigned int cmd, unsigned long arg)
+{
+ int err;
+
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ switch (cmd) {
+ case HDIO_OBSOLETE_IDENTITY:
+ case HDIO_GET_IDENTITY:
+ if (bdev != bdev->bd_contains)
+ return -EINVAL;
+ return ide_get_identity_ioctl(drive, cmd, arg);
+ case HDIO_GET_NICE:
+ return ide_get_nice_ioctl(drive, arg);
+ case HDIO_SET_NICE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return ide_set_nice_ioctl(drive, arg);
+#ifdef CONFIG_IDE_TASK_IOCTL
+ case HDIO_DRIVE_TASKFILE:
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ if (drive->media == ide_disk)
+ return ide_taskfile_ioctl(drive, cmd, arg);
+ return -ENOMSG;
+#endif
+ case HDIO_DRIVE_CMD:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_cmd_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_TASK:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_task_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_RESET:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return generic_drive_reset(drive);
+ case HDIO_GET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (put_user(BUSSTATE_ON, (long __user *)arg))
+ return -EFAULT;
+ return 0;
+ case HDIO_SET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL(generic_ide_ioctl);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 2cbadffe922..b762deb2dac 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
#include <linux/nmi.h>
@@ -182,7 +181,7 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
tf_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- tf_outb((tf->device & HIHI) | drive->select.all,
+ tf_outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
EXPORT_SYMBOL_GPL(ide_tf_load);
@@ -400,97 +399,14 @@ const struct ide_tp_ops default_tp_ops = {
.output_data = ide_output_data,
};
-void ide_fix_driveid (struct hd_driveid *id)
+void ide_fix_driveid(u16 *id)
{
#ifndef __LITTLE_ENDIAN
# ifdef __BIG_ENDIAN
int i;
- u16 *stringcast;
-
- id->config = __le16_to_cpu(id->config);
- id->cyls = __le16_to_cpu(id->cyls);
- id->reserved2 = __le16_to_cpu(id->reserved2);
- id->heads = __le16_to_cpu(id->heads);
- id->track_bytes = __le16_to_cpu(id->track_bytes);
- id->sector_bytes = __le16_to_cpu(id->sector_bytes);
- id->sectors = __le16_to_cpu(id->sectors);
- id->vendor0 = __le16_to_cpu(id->vendor0);
- id->vendor1 = __le16_to_cpu(id->vendor1);
- id->vendor2 = __le16_to_cpu(id->vendor2);
- stringcast = (u16 *)&id->serial_no[0];
- for (i = 0; i < (20/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->buf_type = __le16_to_cpu(id->buf_type);
- id->buf_size = __le16_to_cpu(id->buf_size);
- id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
- stringcast = (u16 *)&id->fw_rev[0];
- for (i = 0; i < (8/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- stringcast = (u16 *)&id->model[0];
- for (i = 0; i < (40/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->dword_io = __le16_to_cpu(id->dword_io);
- id->reserved50 = __le16_to_cpu(id->reserved50);
- id->field_valid = __le16_to_cpu(id->field_valid);
- id->cur_cyls = __le16_to_cpu(id->cur_cyls);
- id->cur_heads = __le16_to_cpu(id->cur_heads);
- id->cur_sectors = __le16_to_cpu(id->cur_sectors);
- id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
- id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
- id->lba_capacity = __le32_to_cpu(id->lba_capacity);
- id->dma_1word = __le16_to_cpu(id->dma_1word);
- id->dma_mword = __le16_to_cpu(id->dma_mword);
- id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
- id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
- id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
- id->eide_pio = __le16_to_cpu(id->eide_pio);
- id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- for (i = 0; i < 2; ++i)
- id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
- for (i = 0; i < 4; ++i)
- id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
- id->queue_depth = __le16_to_cpu(id->queue_depth);
- for (i = 0; i < 4; ++i)
- id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
- id->major_rev_num = __le16_to_cpu(id->major_rev_num);
- id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
- id->command_set_1 = __le16_to_cpu(id->command_set_1);
- id->command_set_2 = __le16_to_cpu(id->command_set_2);
- id->cfsse = __le16_to_cpu(id->cfsse);
- id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
- id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
- id->csf_default = __le16_to_cpu(id->csf_default);
- id->dma_ultra = __le16_to_cpu(id->dma_ultra);
- id->trseuc = __le16_to_cpu(id->trseuc);
- id->trsEuc = __le16_to_cpu(id->trsEuc);
- id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
- id->mprc = __le16_to_cpu(id->mprc);
- id->hw_config = __le16_to_cpu(id->hw_config);
- id->acoustic = __le16_to_cpu(id->acoustic);
- id->msrqs = __le16_to_cpu(id->msrqs);
- id->sxfert = __le16_to_cpu(id->sxfert);
- id->sal = __le16_to_cpu(id->sal);
- id->spg = __le32_to_cpu(id->spg);
- id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
- for (i = 0; i < 22; i++)
- id->words104_125[i] = __le16_to_cpu(id->words104_125[i]);
- id->last_lun = __le16_to_cpu(id->last_lun);
- id->word127 = __le16_to_cpu(id->word127);
- id->dlf = __le16_to_cpu(id->dlf);
- id->csfo = __le16_to_cpu(id->csfo);
- for (i = 0; i < 26; i++)
- id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
- id->word156 = __le16_to_cpu(id->word156);
- for (i = 0; i < 3; i++)
- id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
- id->cfa_power = __le16_to_cpu(id->cfa_power);
- for (i = 0; i < 15; i++)
- id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
- for (i = 0; i < 30; i++)
- id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
- for (i = 0; i < 49; i++)
- id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
- id->integrity_word = __le16_to_cpu(id->integrity_word);
+
+ for (i = 0; i < 256; i++)
+ id[i] = __le16_to_cpu(id[i]);
# else
# error "Please fix <asm/byteorder.h>"
# endif
@@ -501,19 +417,21 @@ void ide_fix_driveid (struct hd_driveid *id)
* ide_fixstring() cleans up and (optionally) byte-swaps a text string,
* removing leading/trailing blanks and compressing internal blanks.
* It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
+ * returned by the ATA_CMD_ID_ATA[PI] commands.
*/
void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
{
- u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+ u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
if (byteswap) {
/* convert from big-endian to host byte order */
- for (p = end ; p != s;)
- be16_to_cpus((u16 *)(p -= 2));
+ for (p = s ; p != end ; p += 2)
+ be16_to_cpus((u16 *) p);
}
+
/* strip leading blanks */
+ p = s;
while (s != end && *s == ' ')
++s;
/* compress internal blanks and strip trailing blanks */
@@ -556,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive)
/* Note: this may clear a pending IRQ!! */
stat = hwif->tp_ops->read_status(hwif);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
/* drive busy: definitely not interrupting */
return 0;
@@ -588,10 +506,10 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
stat = tp_ops->read_status(hwif);
- if (stat & BUSY_STAT) {
+ if (stat & ATA_BUSY) {
local_irq_set(flags);
timeout += jiffies;
- while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
+ while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
if (time_after(jiffies, timeout)) {
/*
* One last read after the timeout in case
@@ -599,7 +517,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
* progress during the timeout..
*/
stat = tp_ops->read_status(hwif);
- if (!(stat & BUSY_STAT))
+ if ((stat & ATA_BUSY) == 0)
break;
local_irq_restore(flags);
@@ -660,18 +578,18 @@ EXPORT_SYMBOL(ide_wait_stat);
/**
* ide_in_drive_list - look for drive in black/white list
* @id: drive identifier
- * @drive_table: list to inspect
+ * @table: list to inspect
*
* Look for a drive in the blacklist and the whitelist tables
* Returns 1 if the drive is found in the table.
*/
-int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
+int ide_in_drive_list(u16 *id, const struct drive_list_entry *table)
{
- for ( ; drive_table->id_model; drive_table++)
- if ((!strcmp(drive_table->id_model, id->model)) &&
- (!drive_table->id_firmware ||
- strstr(id->fw_rev, drive_table->id_firmware)))
+ for ( ; table->id_model; table++)
+ if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) &&
+ (!table->id_firmware ||
+ strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware)))
return 1;
return 0;
}
@@ -702,7 +620,7 @@ static const struct drive_list_entry ivb_list[] = {
u8 eighty_ninty_three (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
int ivb = ide_in_drive_list(id, ivb_list);
if (hwif->cbl == ATA_CBL_PATA40_SHORT)
@@ -712,7 +630,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
printk(KERN_DEBUG "%s: skipping word 93 validity check\n",
drive->name);
- if (ide_dev_is_sata(id) && !ivb)
+ if (ata_id_is_sata(id) && !ivb)
return 1;
if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
@@ -724,11 +642,12 @@ u8 eighty_ninty_three (ide_drive_t *drive)
* - force bit13 (80c cable present) check also for !ivb devices
* (unless the slave device is pre-ATA3)
*/
- if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000)))
+ if ((id[ATA_ID_HW_CONFIG] & 0x4000) ||
+ (ivb && (id[ATA_ID_HW_CONFIG] & 0x2000)))
return 1;
no_80w:
- if (drive->udma33_warned == 1)
+ if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
return 0;
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
@@ -736,7 +655,7 @@ no_80w:
drive->name,
hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
- drive->udma33_warned = 1;
+ drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
return 0;
}
@@ -745,8 +664,8 @@ int ide_driveid_update(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- struct hd_driveid *id;
- unsigned long timeout, flags;
+ u16 *id;
+ unsigned long flags;
u8 stat;
/*
@@ -757,29 +676,24 @@ int ide_driveid_update(ide_drive_t *drive)
SELECT_MASK(drive, 1);
tp_ops->set_irq(hwif, 0);
msleep(50);
- tp_ops->exec_command(hwif, WIN_IDENTIFY);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (time_after(jiffies, timeout)) {
- SELECT_MASK(drive, 0);
- return 0; /* drive timed-out */
- }
+ tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
- msleep(50); /* give drive a breather */
- stat = tp_ops->read_altstatus(hwif);
- } while (stat & BUSY_STAT);
+ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
+ SELECT_MASK(drive, 0);
+ return 0;
+ }
- msleep(50); /* wait for IRQ and DRQ_STAT */
+ msleep(50); /* wait for IRQ and ATA_DRQ */
stat = tp_ops->read_status(hwif);
- if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+ if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) {
SELECT_MASK(drive, 0);
printk("%s: CHECK for good STATUS\n", drive->name);
return 0;
}
local_irq_save(flags);
SELECT_MASK(drive, 0);
- id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+ id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
if (!id) {
local_irq_restore(flags);
return 0;
@@ -789,16 +703,16 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_enable();
local_irq_restore(flags);
ide_fix_driveid(id);
- if (id) {
- drive->id->dma_ultra = id->dma_ultra;
- drive->id->dma_mword = id->dma_mword;
- drive->id->dma_1word = id->dma_1word;
- /* anything more ? */
- kfree(id);
-
- if (drive->using_dma && ide_id_dma_bug(drive))
- ide_dma_off(drive);
- }
+
+ drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
+ drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
+ drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
+ /* anything more ? */
+
+ kfree(id);
+
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
+ ide_dma_off(drive);
return 1;
}
@@ -807,6 +721,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ u16 *id = drive->id, i;
int error = 0;
u8 stat;
ide_task_t task;
@@ -817,7 +732,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
#endif
/* Skip setting PIO flow-control modes on pre-EIDE drives */
- if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08))
+ if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0)
goto skip;
/*
@@ -851,13 +766,13 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
tp_ops->tf_load(drive, &task);
- tp_ops->exec_command(hwif, WIN_SETFEATURES);
+ tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
if (drive->quirk_list == 2)
tp_ops->set_irq(hwif, 1);
error = __ide_wait_stat(drive, drive->ready_stat,
- BUSY_STAT|DRQ_STAT|ERR_STAT,
+ ATA_BUSY | ATA_DRQ | ATA_ERR,
WAIT_CMD, &stat);
SELECT_MASK(drive, 0);
@@ -869,35 +784,29 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
return error;
}
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
+ id[ATA_ID_UDMA_MODES] &= ~0xFF00;
+ id[ATA_ID_MWDMA_MODES] &= ~0x0F00;
+ id[ATA_ID_SWDMA_MODES] &= ~0x0F00;
skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (speed >= XFER_SW_DMA_0 && drive->using_dma)
+ if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
hwif->dma_ops->dma_host_set(drive, 1);
else if (hwif->dma_ops) /* check if host supports DMA */
ide_dma_off_quietly(drive);
#endif
- switch(speed) {
- case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break;
- case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break;
- case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break;
- case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
- case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
- case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
- case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
- case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
- case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
- case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
- case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
- case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
- case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
- case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
- default: break;
+ if (speed >= XFER_UDMA_0) {
+ i = 1 << (speed - XFER_UDMA_0);
+ id[ATA_ID_UDMA_MODES] |= (i << 8 | i);
+ } else if (speed >= XFER_MW_DMA_0) {
+ i = 1 << (speed - XFER_MW_DMA_0);
+ id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
+ } else if (speed >= XFER_SW_DMA_0) {
+ i = 1 << (speed - XFER_SW_DMA_0);
+ id[ATA_ID_SWDMA_MODES] |= (i << 8 | i);
}
+
if (!drive->init_speed)
drive->init_speed = speed;
drive->current_speed = speed;
@@ -977,7 +886,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
- hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -1010,7 +919,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
udelay (10);
stat = hwif->tp_ops->read_status(hwif);
- if (OK_STAT(stat, 0, BUSY_STAT))
+ if (OK_STAT(stat, 0, ATA_BUSY))
printk("%s: ATAPI reset complete\n", drive->name);
else {
if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -1031,6 +940,25 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
return ide_stopped;
}
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+ static const char *err_master_vals[] =
+ { NULL, "passed", "formatter device error",
+ "sector buffer error", "ECC circuitry error",
+ "controlling MPU error" };
+
+ u8 err_master = err & 0x7f;
+
+ printk(KERN_ERR "%s: reset: master: ", hwif->name);
+ if (err_master && err_master < 6)
+ printk(KERN_CONT "%s", err_master_vals[err_master]);
+ else
+ printk(KERN_CONT "error (0x%02x?)", err);
+ if (err & 0x80)
+ printk(KERN_CONT "; slave: failed");
+ printk(KERN_CONT "\n");
+}
+
/*
* reset_pollfunc() gets invoked to poll the interface for completion every 50ms
* during an ide reset operation. If the drives have not yet responded,
@@ -1056,7 +984,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
tmp = hwif->tp_ops->read_status(hwif);
- if (!OK_STAT(tmp, 0, BUSY_STAT)) {
+ if (!OK_STAT(tmp, 0, ATA_BUSY)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/* continue polling */
@@ -1066,31 +994,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
drive->failures++;
err = -EIO;
} else {
- printk("%s: reset: ", hwif->name);
tmp = ide_read_error(drive);
if (tmp == 1) {
- printk("success\n");
+ printk(KERN_INFO "%s: reset: success\n", hwif->name);
drive->failures = 0;
} else {
+ ide_reset_report_error(hwif, tmp);
drive->failures++;
- printk("master: ");
- switch (tmp & 0x7f) {
- case 1: printk("passed");
- break;
- case 2: printk("formatter device error");
- break;
- case 3: printk("sector buffer error");
- break;
- case 4: printk("ECC circuitry error");
- break;
- case 5: printk("controlling MPU error");
- break;
- default:printk("error (0x%02x?)", tmp);
- }
- if (tmp & 0x80)
- printk("; slave: failed");
- printk("\n");
err = -EIO;
}
}
@@ -1102,14 +1013,19 @@ out:
static void ide_disk_pre_reset(ide_drive_t *drive)
{
- int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
+ int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
drive->special.all = 0;
drive->special.b.set_geometry = legacy;
drive->special.b.recalibrate = legacy;
+
drive->mult_count = 0;
- if (!drive->keep_settings && !drive->using_dma)
+ drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
drive->mult_req = 0;
+
if (drive->mult_req != drive->mult_count)
drive->special.b.set_multmode = 1;
}
@@ -1121,18 +1037,18 @@ static void pre_reset(ide_drive_t *drive)
if (drive->media == ide_disk)
ide_disk_pre_reset(drive);
else
- drive->post_reset = 1;
+ drive->dev_flags |= IDE_DFLAG_POST_RESET;
- if (drive->using_dma) {
+ if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
if (drive->crc_count)
ide_check_dma_crc(drive);
else
ide_dma_off(drive);
}
- if (!drive->keep_settings) {
- if (!drive->using_dma) {
- drive->unmask = 0;
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
drive->io_32bit = 0;
}
return;
@@ -1164,12 +1080,13 @@ static void pre_reset(ide_drive_t *drive)
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
unsigned int unit;
- unsigned long flags;
+ unsigned long flags, timeout;
ide_hwif_t *hwif;
ide_hwgroup_t *hwgroup;
struct ide_io_ports *io_ports;
const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
+ DEFINE_WAIT(wait);
spin_lock_irqsave(&ide_lock, flags);
hwif = HWIF(drive);
@@ -1187,7 +1104,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- tp_ops->exec_command(hwif, WIN_SRST);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
@@ -1196,6 +1113,31 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
return ide_started;
}
+ /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+ do {
+ unsigned long now;
+
+ prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+ timeout = jiffies;
+ for (unit = 0; unit < MAX_DRIVES; unit++) {
+ ide_drive_t *tdrive = &hwif->drives[unit];
+
+ if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
+ tdrive->dev_flags & IDE_DFLAG_PARKED &&
+ time_after(tdrive->sleep, timeout))
+ timeout = tdrive->sleep;
+ }
+
+ now = jiffies;
+ if (time_before_eq(timeout, now))
+ break;
+
+ spin_unlock_irqrestore(&ide_lock, flags);
+ timeout = schedule_timeout_uninterruptible(timeout - now);
+ spin_lock_irqsave(&ide_lock, flags);
+ } while (timeout);
+ finish_wait(&ide_park_wq, &wait);
+
/*
* First, reset any device state data we were maintaining
* for any of the drives on this interface.
@@ -1270,7 +1212,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
*/
mdelay(1);
stat = hwif->tp_ops->read_status(hwif);
- if ((stat & BUSY_STAT) == 0)
+ if ((stat & ATA_BUSY) == 0)
return 0;
/*
* Assume a value of 0xff means nothing is connected to
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 97fefabea8b..9fc4cfb2a27 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -2,7 +2,6 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
@@ -90,29 +89,31 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
{
- int pio_mode;
- struct hd_driveid* id = drive->id;
- int overridden = 0;
+ u16 *id = drive->id;
+ int pio_mode = -1, overridden = 0;
if (mode_wanted != 255)
return min_t(u8, mode_wanted, max_mode);
- if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 &&
- (pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
+ if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
+ pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
+
+ if (pio_mode != -1) {
printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
} else {
- pio_mode = id->tPIO;
+ pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
pio_mode = 2;
overridden = 1;
}
- if (id->field_valid & 2) { /* drive implements ATA2? */
- if (id->capability & 8) { /* IORDY supported? */
- if (id->eide_pio_modes & 7) {
+
+ if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
+ if (ata_id_has_iordy(id)) {
+ if (id[ATA_ID_PIO_MODES] & 7) {
overridden = 0;
- if (id->eide_pio_modes & 4)
+ if (id[ATA_ID_PIO_MODES] & 4)
pio_mode = 5;
- else if (id->eide_pio_modes & 2)
+ else if (id[ATA_ID_PIO_MODES] & 2)
pio_mode = 4;
else
pio_mode = 3;
@@ -316,7 +317,7 @@ static void ide_dump_sector(ide_drive_t *drive)
{
ide_task_t task;
struct ide_taskfile *tf = &task.tf;
- int lba48 = (drive->addressing == 1) ? 1 : 0;
+ u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
memset(&task, 0, sizeof(task));
if (lba48)
@@ -338,16 +339,16 @@ static void ide_dump_sector(ide_drive_t *drive)
static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
{
printk("{ ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR)
- printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
+ if (err & ATA_ABORTED) printk("DriveStatusError ");
+ if (err & ATA_ICRC)
+ printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
+ if (err & ATA_UNC) printk("UncorrectableError ");
+ if (err & ATA_IDNF) printk("SectorIdNotFound ");
+ if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
+ if (err & ATA_AMNF) printk("AddrMarkNotFound ");
printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
- (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+ if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
+ (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
ide_dump_sector(drive);
if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu",
@@ -359,12 +360,12 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
{
printk("{ ");
- if (err & ILI_ERR) printk("IllegalLengthIndication ");
- if (err & EOM_ERR) printk("EndOfMedia ");
- if (err & ABRT_ERR) printk("AbortedCommand ");
- if (err & MCR_ERR) printk("MediaChangeRequested ");
- if (err & LFS_ERR) printk("LastFailedSense=0x%02x ",
- (err & LFS_ERR) >> 4);
+ if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
+ if (err & ATAPI_EOM) printk("EndOfMedia ");
+ if (err & ATA_ABORTED) printk("AbortedCommand ");
+ if (err & ATA_MCR) printk("MediaChangeRequested ");
+ if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
+ (err & ATAPI_LFS) >> 4);
printk("}\n");
}
@@ -386,19 +387,19 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
printk("Busy ");
else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
+ if (stat & ATA_DRDY) printk("DriveReady ");
+ if (stat & ATA_DF) printk("DeviceFault ");
+ if (stat & ATA_DSC) printk("SeekComplete ");
+ if (stat & ATA_DRQ) printk("DataRequest ");
+ if (stat & ATA_CORR) printk("CorrectedError ");
+ if (stat & ATA_IDX) printk("Index ");
+ if (stat & ATA_ERR) printk("Error ");
}
printk("}\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+ if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
err = ide_read_error(drive);
printk("%s: %s: error=0x%02x ", drive->name, msg, err);
if (drive->media == ide_disk)
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
new file mode 100644
index 00000000000..03b00e57e93
--- /dev/null
+++ b/drivers/ide/ide-park.c
@@ -0,0 +1,121 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/jiffies.h>
+#include <linux/blkdev.h>
+
+DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
+
+static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
+{
+ struct request_queue *q = drive->queue;
+ struct request *rq;
+ int rc;
+
+ timeout += jiffies;
+ spin_lock_irq(&ide_lock);
+ if (drive->dev_flags & IDE_DFLAG_PARKED) {
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ int reset_timer;
+
+ reset_timer = time_before(timeout, drive->sleep);
+ drive->sleep = timeout;
+ wake_up_all(&ide_park_wq);
+ if (reset_timer && hwgroup->sleeping &&
+ del_timer(&hwgroup->timer)) {
+ hwgroup->sleeping = 0;
+ hwgroup->busy = 0;
+ blk_start_queueing(q);
+ }
+ spin_unlock_irq(&ide_lock);
+ return;
+ }
+ spin_unlock_irq(&ide_lock);
+
+ rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq->cmd[0] = REQ_PARK_HEADS;
+ rq->cmd_len = 1;
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->special = &timeout;
+ rc = blk_execute_rq(q, NULL, rq, 1);
+ blk_put_request(rq);
+ if (rc)
+ goto out;
+
+ /*
+ * Make sure that *some* command is sent to the drive after the
+ * timeout has expired, so power management will be reenabled.
+ */
+ rq = blk_get_request(q, READ, GFP_NOWAIT);
+ if (unlikely(!rq))
+ goto out;
+
+ rq->cmd[0] = REQ_UNPARK_HEADS;
+ rq->cmd_len = 1;
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+
+out:
+ return;
+}
+
+ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ unsigned long now;
+ unsigned int msecs;
+
+ if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+ return -EOPNOTSUPP;
+
+ spin_lock_irq(&ide_lock);
+ now = jiffies;
+ if (drive->dev_flags & IDE_DFLAG_PARKED &&
+ time_after(drive->sleep, now))
+ msecs = jiffies_to_msecs(drive->sleep - now);
+ else
+ msecs = 0;
+ spin_unlock_irq(&ide_lock);
+
+ return snprintf(buf, 20, "%u\n", msecs);
+}
+
+ssize_t ide_park_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+#define MAX_PARK_TIMEOUT 30000
+ ide_drive_t *drive = to_ide_device(dev);
+ long int input;
+ int rc;
+
+ rc = strict_strtol(buf, 10, &input);
+ if (rc || input < -2)
+ return -EINVAL;
+ if (input > MAX_PARK_TIMEOUT) {
+ input = MAX_PARK_TIMEOUT;
+ rc = -EOVERFLOW;
+ }
+
+ mutex_lock(&ide_setting_mtx);
+ if (input >= 0) {
+ if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+ rc = -EOPNOTSUPP;
+ else if (input || drive->dev_flags & IDE_DFLAG_PARKED)
+ issue_park_cmd(drive, msecs_to_jiffies(input));
+ } else {
+ if (drive->media == ide_disk)
+ switch (input) {
+ case -1:
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD;
+ break;
+ case -2:
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+ break;
+ }
+ else
+ rc = -EOPNOTSUPP;
+ }
+ mutex_unlock(&ide_setting_mtx);
+
+ return rc ? rc : len;
+}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 994e41099b4..19f8c7770a2 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -50,59 +50,54 @@
static void generic_id(ide_drive_t *drive)
{
- drive->id->cyls = drive->cyl;
- drive->id->heads = drive->head;
- drive->id->sectors = drive->sect;
- drive->id->cur_cyls = drive->cyl;
- drive->id->cur_heads = drive->head;
- drive->id->cur_sectors = drive->sect;
+ u16 *id = drive->id;
+
+ id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl;
+ id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head;
+ id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect;
}
static void ide_disk_init_chs(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
/* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) {
- drive->cyl = drive->bios_cyl = id->cyls;
- drive->head = drive->bios_head = id->heads;
- drive->sect = drive->bios_sect = id->sectors;
+ drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS];
+ drive->head = drive->bios_head = id[ATA_ID_HEADS];
+ drive->sect = drive->bios_sect = id[ATA_ID_SECTORS];
}
/* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls &&
- id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
+ if (ata_id_current_chs_valid(id)) {
+ drive->cyl = id[ATA_ID_CUR_CYLS];
+ drive->head = id[ATA_ID_CUR_HEADS];
+ drive->sect = id[ATA_ID_CUR_SECTORS];
}
/* Use physical geometry if what we have still makes no sense */
- if (drive->head > 16 && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
+ if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) {
+ drive->cyl = id[ATA_ID_CYLS];
+ drive->head = id[ATA_ID_HEADS];
+ drive->sect = id[ATA_ID_SECTORS];
}
}
static void ide_disk_init_mult_count(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
-
- drive->mult_count = 0;
- if (id->max_multsect) {
-#ifdef CONFIG_IDEDISK_MULTI_MODE
- id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
- id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
- drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = 0;
- if (drive->mult_req > id->max_multsect)
- drive->mult_req = id->max_multsect;
- if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+ u16 *id = drive->id;
+ u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff;
+
+ if (max_multsect) {
+ if ((max_multsect / 2) > 1)
+ id[ATA_ID_MULTSECT] = max_multsect | 0x100;
+ else
+ id[ATA_ID_MULTSECT] &= ~0x1ff;
+
+ drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
+
+ if (drive->mult_req)
drive->special.b.set_multmode = 1;
-#endif
}
}
@@ -119,14 +114,15 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
static inline void do_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- int bswap = 1;
- struct hd_driveid *id;
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ int bswap = 1, is_cfa;
- id = drive->id;
/* read 512 bytes of id info */
hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
- drive->id_read = 1;
+ drive->dev_flags |= IDE_DFLAG_ID_READ;
+
local_irq_enable();
#ifdef DEBUG
printk(KERN_INFO "%s: dumping identify data\n", drive->name);
@@ -135,59 +131,59 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
ide_fix_driveid(id);
/*
- * WIN_IDENTIFY returns little-endian info,
- * WIN_PIDENTIFY *usually* returns little-endian info.
+ * ATA_CMD_ID_ATA returns little-endian info,
+ * ATA_CMD_ID_ATAPI *usually* returns little-endian info.
*/
- if (cmd == WIN_PIDENTIFY) {
- if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
- || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
- || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ if ((m[0] == 'N' && m[1] == 'E') || /* NEC */
+ (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */
+ (m[0] == 'P' && m[1] == 'i')) /* Pioneer */
/* Vertos drives may still be weird */
- bswap ^= 1;
+ bswap ^= 1;
}
- ide_fixstring(id->model, sizeof(id->model), bswap);
- ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
- ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
+
+ ide_fixstring(m, ATA_ID_PROD_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap);
/* we depend on this a lot! */
- id->model[sizeof(id->model)-1] = '\0';
+ m[ATA_ID_PROD_LEN - 1] = '\0';
- if (strstr(id->model, "E X A B Y T E N E S T"))
+ if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc;
- printk(KERN_INFO "%s: %s, ", drive->name, id->model);
+ printk(KERN_INFO "%s: %s, ", drive->name, m);
- drive->present = 1;
- drive->dead = 0;
+ drive->dev_flags |= IDE_DFLAG_PRESENT;
+ drive->dev_flags &= ~IDE_DFLAG_DEAD;
/*
* Check for an ATAPI device
*/
- if (cmd == WIN_PIDENTIFY) {
- u8 type = (id->config >> 8) & 0x1f;
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
printk(KERN_CONT "ATAPI ");
switch (type) {
case ide_floppy:
- if (!strstr(id->model, "CD-ROM")) {
- if (!strstr(id->model, "oppy") &&
- !strstr(id->model, "poyp") &&
- !strstr(id->model, "ZIP"))
+ if (!strstr(m, "CD-ROM")) {
+ if (!strstr(m, "oppy") &&
+ !strstr(m, "poyp") &&
+ !strstr(m, "ZIP"))
printk(KERN_CONT "cdrom or floppy?, assuming ");
if (drive->media != ide_cdrom) {
printk(KERN_CONT "FLOPPY");
- drive->removable = 1;
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
break;
}
}
/* Early cdrom models used zero */
type = ide_cdrom;
case ide_cdrom:
- drive->removable = 1;
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
#ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */
- if (!strstr(id->model, "CD-ROM") &&
- strstr(id->model, "ZIP")) {
+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
printk(KERN_CONT "FLOPPY");
type = ide_floppy;
break;
@@ -200,7 +196,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
break;
case ide_optical:
printk(KERN_CONT "OPTICAL");
- drive->removable = 1;
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
break;
default:
printk(KERN_CONT "UNKNOWN (type %d)", type);
@@ -210,6 +206,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->media = type;
/* an ATAPI device ignores DRDY */
drive->ready_stat = 0;
+ if (ata_id_cdb_intr(id))
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+ /* we don't do head unloading on ATAPI devices */
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
return;
}
@@ -217,24 +217,24 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
* Not an ATAPI device: looks like a "regular" hard disk
*/
- /*
- * 0x848a = CompactFlash device
- * These are *not* removable in Linux definition of the term
- */
+ is_cfa = ata_id_is_cfa(id);
- if ((id->config != 0x848a) && (id->config & (1<<7)))
- drive->removable = 1;
+ /* CF devices are *not* removable in Linux definition of the term */
+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
drive->media = ide_disk;
- printk(KERN_CONT "%s DISK drive\n",
- (id->config == 0x848a) ? "CFA" : "ATA");
+ if (!ata_id_has_unload(drive->id))
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+
+ printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
return;
err_misc:
kfree(id);
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
return;
}
@@ -268,7 +268,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
if (io_ports->ctl_addr) {
a = tp_ops->read_altstatus(hwif);
s = tp_ops->read_status(hwif);
- if ((a ^ s) & ~INDEX_STAT)
+ if ((a ^ s) & ~ATA_IDX)
/* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
"instead of ALTSTATUS(0x%02x)\n",
@@ -281,7 +281,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi
* identify command to be sure of reply
*/
- if (cmd == WIN_PIDENTIFY) {
+ if (cmd == ATA_CMD_ID_ATAPI) {
ide_task_t task;
memset(&task, 0, sizeof(task));
@@ -294,24 +294,16 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* ask drive for ID */
tp_ops->exec_command(hwif, cmd);
- timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- timeout += jiffies;
- do {
- if (time_after(jiffies, timeout)) {
- /* drive timed-out */
- return 1;
- }
- /* give drive a breather */
- msleep(50);
- s = use_altstatus ? tp_ops->read_altstatus(hwif)
- : tp_ops->read_status(hwif);
- } while (s & BUSY_STAT);
+ timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- /* wait for IRQ and DRQ_STAT */
+ if (ide_busy_sleep(hwif, timeout, use_altstatus))
+ return 1;
+
+ /* wait for IRQ and ATA_DRQ */
msleep(50);
s = tp_ops->read_status(hwif);
- if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
+ if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
unsigned long flags;
/* local CPU only; some systems need this */
@@ -387,19 +379,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
return retval;
}
-static int ide_busy_sleep(ide_hwif_t *hwif)
+int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
{
- unsigned long timeout = jiffies + WAIT_WORSTCASE;
u8 stat;
+ timeout += jiffies;
+
do {
- msleep(50);
- stat = hwif->tp_ops->read_status(hwif);
- if ((stat & BUSY_STAT) == 0)
+ msleep(50); /* give drive a breather */
+ stat = altstatus ? hwif->tp_ops->read_altstatus(hwif)
+ : hwif->tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0)
return 0;
} while (time_before(jiffies, timeout));
- return 1;
+ return 1; /* drive timed-out */
}
static u8 ide_read_device(ide_drive_t *drive)
@@ -440,17 +434,16 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
ide_hwif_t *hwif = HWIF(drive);
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int rc;
- u8 stat;
+ u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
+
+ /* avoid waiting for inappropriate probes */
+ if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
+ return 4;
- if (drive->present) {
- /* avoid waiting for inappropriate probes */
- if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
- return 4;
- }
#ifdef DEBUG
printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
- drive->name, drive->present, drive->media,
- (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
+ drive->name, present, drive->media,
+ (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
#endif
/* needed for some systems
@@ -460,11 +453,11 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
SELECT_DRIVE(drive);
msleep(50);
- if (ide_read_device(drive) != drive->select.all && !drive->present) {
- if (drive->select.b.unit != 0) {
+ if (ide_read_device(drive) != drive->select && present == 0) {
+ if (drive->dn & 1) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
- /* allow BUSY_STAT to assert & clear */
+ /* allow ATA_BUSY to assert & clear */
msleep(50);
}
/* no i/f present: mmm.. this should be a 4 -ml */
@@ -473,8 +466,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif);
- if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
- drive->present || cmd == WIN_PIDENTIFY) {
+ if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
+ present || cmd == ATA_CMD_ID_ATAPI) {
/* send cmd and wait */
if ((rc = try_to_identify(drive, cmd))) {
/* failed: try again */
@@ -483,17 +476,17 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif);
- if (stat == (BUSY_STAT | READY_STAT))
+ if (stat == (ATA_BUSY | ATA_DRDY))
return 4;
- if (rc == 1 && cmd == WIN_PIDENTIFY) {
+ if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
printk(KERN_ERR "%s: no response (status = 0x%02x), "
"resetting drive\n", drive->name, stat);
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- tp_ops->exec_command(hwif, WIN_SRST);
- (void)ide_busy_sleep(hwif);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+ (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
rc = try_to_identify(drive, cmd);
}
@@ -507,7 +500,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
/* not present or maybe ATAPI */
rc = 3;
}
- if (drive->select.b.unit != 0) {
+ if (drive->dn & 1) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
msleep(50);
@@ -526,13 +519,14 @@ static void enable_nest (ide_drive_t *drive)
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
- printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model);
+ printk(KERN_INFO "%s: enabling %s -- ",
+ hwif->name, (char *)&drive->id[ATA_ID_PROD]);
SELECT_DRIVE(drive);
msleep(50);
- tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
+ tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
- if (ide_busy_sleep(hwif)) {
+ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
printk(KERN_CONT "failed (timeout)\n");
return;
}
@@ -545,12 +539,6 @@ static void enable_nest (ide_drive_t *drive)
printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
else
printk(KERN_CONT "success\n");
-
- /* if !(success||timed-out) */
- if (do_probe(drive, WIN_IDENTIFY) >= 2) {
- /* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
}
/**
@@ -561,12 +549,14 @@ static void enable_nest (ide_drive_t *drive)
* and presents things to the user as needed.
*
* Returns: 0 no device was found
- * 1 device was found (note: drive->present might
- * still be 0)
+ * 1 device was found
+ * (note: IDE_DFLAG_PRESENT might still be not set)
*/
static inline u8 probe_for_drive (ide_drive_t *drive)
{
+ char *m;
+
/*
* In order to keep things simple we have an id
* block for all drives at all times. If the device
@@ -576,31 +566,36 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
* Also note that 0 everywhere means "can't do X"
*/
- drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL);
- drive->id_read = 0;
- if(drive->id == NULL)
- {
+ drive->dev_flags &= ~IDE_DFLAG_ID_READ;
+
+ drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
+ if (drive->id == NULL) {
printk(KERN_ERR "ide: out of memory for id data.\n");
return 0;
}
- strcpy(drive->id->model, "UNKNOWN");
-
+
+ m = (char *)&drive->id[ATA_ID_PROD];
+ strcpy(m, "UNKNOWN");
+
/* skip probing? */
- if (!drive->noprobe)
- {
+ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
+retry:
/* if !(success||timed-out) */
- if (do_probe(drive, WIN_IDENTIFY) >= 2) {
+ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
/* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
- if (!drive->present)
+ (void)do_probe(drive, ATA_CMD_ID_ATAPI);
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
/* drive not found */
return 0;
- if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+
+ if (strstr(m, "E X A B Y T E N E S T")) {
enable_nest(drive);
-
+ goto retry;
+ }
+
/* identification failed? */
- if (!drive->id_read) {
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
if (drive->media == ide_disk) {
printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
drive->name, drive->cyl,
@@ -610,15 +605,17 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
} else {
/* nuke it */
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
}
}
/* drive was found */
}
- if(!drive->present)
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
return 0;
+
/* The drive wasn't being helpful. Add generic info only */
- if (drive->id_read == 0) {
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
generic_id(drive);
return 1;
}
@@ -628,7 +625,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
ide_disk_init_mult_count(drive);
}
- return drive->present;
+ return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
}
static void hwif_release_dev(struct device *dev)
@@ -660,8 +657,8 @@ static int ide_register_port(ide_hwif_t *hwif)
goto out;
}
- hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
- MKDEV(0, 0), hwif, hwif->name);
+ hwif->portdev = device_create(ide_port_class, &hwif->gendev,
+ MKDEV(0, 0), hwif, hwif->name);
if (IS_ERR(hwif->portdev)) {
ret = PTR_ERR(hwif->portdev);
device_unregister(&hwif->gendev);
@@ -719,7 +716,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[unit];
/* Ignore disks that we will not probe for later. */
- if (!drive->noprobe || drive->present) {
+ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_PRESENT)) {
SELECT_DRIVE(drive);
hwif->tp_ops->set_irq(hwif, 1);
mdelay(2);
@@ -740,36 +738,38 @@ out:
/**
* ide_undecoded_slave - look for bad CF adapters
- * @drive1: drive
+ * @dev1: slave device
*
* Analyse the drives on the interface and attempt to decide if we
* have the same drive viewed twice. This occurs with crap CF adapters
* and PCMCIA sometimes.
*/
-void ide_undecoded_slave(ide_drive_t *drive1)
+void ide_undecoded_slave(ide_drive_t *dev1)
{
- ide_drive_t *drive0 = &drive1->hwif->drives[0];
+ ide_drive_t *dev0 = &dev1->hwif->drives[0];
- if ((drive1->dn & 1) == 0 || drive0->present == 0)
+ if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0)
return;
/* If the models don't match they are not the same product */
- if (strcmp(drive0->id->model, drive1->id->model))
+ if (strcmp((char *)&dev0->id[ATA_ID_PROD],
+ (char *)&dev1->id[ATA_ID_PROD]))
return;
/* Serial numbers do not match */
- if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20))
+ if (strncmp((char *)&dev0->id[ATA_ID_SERNO],
+ (char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN))
return;
/* No serial number, thankfully very rare for CF */
- if (drive0->id->serial_no[0] == 0)
+ if (*(char *)&dev0->id[ATA_ID_SERNO] == 0)
return;
/* Appears to be an IDE flash adapter with decode bugs */
printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
- drive1->present = 0;
+ dev1->dev_flags &= ~IDE_DFLAG_PRESENT;
}
EXPORT_SYMBOL_GPL(ide_undecoded_slave);
@@ -782,7 +782,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
BUG_ON(hwif->present);
- if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
+ if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) &&
+ (hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE))
return -EACCES;
/*
@@ -804,9 +805,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
*/
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- drive->dn = (hwif->channel ? 2 : 0) + unit;
+
(void) probe_for_drive(drive);
- if (drive->present)
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
rc = 0;
}
@@ -830,17 +831,19 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
for (unit = 0; unit < MAX_DRIVES; unit++) {
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present && port_ops && port_ops->quirkproc)
- port_ops->quirkproc(drive);
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
+ if (port_ops && port_ops->quirkproc)
+ port_ops->quirkproc(drive);
+ }
}
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
ide_set_max_pio(drive);
- drive->nice1 = 1;
+ drive->dev_flags |= IDE_DFLAG_NICE1;
if (hwif->dma_ops)
ide_set_dma(drive);
@@ -850,14 +853,14 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
- drive->no_io_32bit = 1;
+ if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) ||
+ drive->id[ATA_ID_DWORD_IO])
+ drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
else
- drive->no_io_32bit = drive->id->dword_io ? 1 : 0;
+ drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
}
}
-#if MAX_HWIFS > 1
/*
* save_match() is used to simplify logic in init_irq() below.
*
@@ -882,7 +885,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
*match = new;
}
-#endif /* MAX_HWIFS > 1 */
/*
* init request queue
@@ -961,26 +963,33 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
* - allocate the block device queue
* - link drive into the hwgroup
*/
-static void ide_port_setup_devices(ide_hwif_t *hwif)
+static int ide_port_setup_devices(ide_hwif_t *hwif)
{
- int i;
+ int i, j = 0;
mutex_lock(&ide_cfg_mtx);
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
if (ide_init_queue(drive)) {
printk(KERN_ERR "ide: failed to init %s\n",
drive->name);
+ kfree(drive->id);
+ drive->id = NULL;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
continue;
}
+ j++;
+
ide_add_drive_to_hwgroup(drive);
}
mutex_unlock(&ide_cfg_mtx);
+
+ return j;
}
static ide_hwif_t *ide_ports[MAX_HWIFS];
@@ -1037,14 +1046,9 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
-
- BUG_ON(in_interrupt());
- BUG_ON(irqs_disabled());
- BUG_ON(hwif == NULL);
-
mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
-#if MAX_HWIFS > 1
+
/*
* Group up with any other hwifs that share our irq(s).
*/
@@ -1069,7 +1073,7 @@ static int init_irq (ide_hwif_t *hwif)
}
}
}
-#endif /* MAX_HWIFS > 1 */
+
/*
* If we are still without a hwgroup, then form a new one
*/
@@ -1116,7 +1120,8 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
#endif /* __mc68000__ */
- if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
+ hwif->chipset == ide_ali14xx)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
@@ -1167,12 +1172,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
ide_hwif_t *hwif = data;
int unit = *part >> PARTN_BITS;
ide_drive_t *drive = &hwif->drives[unit];
- if (!drive->present)
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
return NULL;
if (drive->media == ide_disk)
request_module("ide-disk");
- if (drive->scsi)
+ if (drive->dev_flags & IDE_DFLAG_SCSI)
request_module("ide-scsi");
if (drive->media == ide_cdrom || drive->media == ide_optical)
request_module("ide-cd");
@@ -1188,7 +1194,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
{
struct gendisk *p = data;
*part &= (1 << PARTN_BITS) - 1;
- return &p->dev.kobj;
+ return &disk_to_dev(p)->kobj;
}
static int exact_lock(dev_t dev, void *data)
@@ -1219,7 +1225,7 @@ EXPORT_SYMBOL_GPL(ide_unregister_region);
void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- unsigned int unit = (drive->select.all >> 4) & 1;
+ unsigned int unit = drive->dn & 1;
disk->major = hwif->major;
disk->first_minor = unit << PARTN_BITS;
@@ -1262,7 +1268,7 @@ static void drive_release_dev (struct device *dev)
ide_remove_drive_from_hwgroup(drive);
kfree(drive->id);
drive->id = NULL;
- drive->present = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PRESENT;
/* Messed up locking ... */
spin_unlock_irq(&ide_lock);
blk_cleanup_queue(drive->queue);
@@ -1341,11 +1347,9 @@ static void hwif_register_devices(ide_hwif_t *hwif)
struct device *dev = &drive->gendev;
int ret;
- if (!drive->present)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
- ide_add_generic_settings(drive);
-
snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type;
@@ -1367,12 +1371,14 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
+ drive->dn = i + hwif->channel * 2;
+
if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
drive->io_32bit = 1;
if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
- drive->unmask = 1;
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
- drive->no_unmask = 1;
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
if (port_ops && port_ops->init_dev)
port_ops->init_dev(drive);
@@ -1492,7 +1498,7 @@ static struct device_attribute *ide_port_attrs[] = {
static int ide_sysfs_register_port(ide_hwif_t *hwif)
{
- int i, rc;
+ int i, uninitialized_var(rc);
for (i = 0; ide_port_attrs[i]; i++) {
rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
@@ -1529,19 +1535,14 @@ static int ide_find_port_slot(const struct ide_port_info *d)
* ports 0x1f0/0x170 (the ide0/ide1 defaults).
*/
mutex_lock(&ide_cfg_mtx);
- if (MAX_HWIFS == 1) {
- if (ide_indexes == 0 && i == 0)
- idx = 1;
+ if (bootable) {
+ if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | i);
} else {
- if (bootable) {
- if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
- idx = ffz(ide_indexes | i);
- } else {
- if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
- idx = ffz(ide_indexes | 3);
- else if ((ide_indexes & 3) != 3)
- idx = ffz(ide_indexes);
- }
+ if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | 3);
+ else if ((ide_indexes & 3) != 3)
+ idx = ffz(ide_indexes);
}
if (idx >= 0)
ide_indexes |= (1 << idx);
@@ -1557,8 +1558,7 @@ static void ide_free_port_slot(int idx)
mutex_unlock(&ide_cfg_mtx);
}
-struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
- hw_regs_t **hws)
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
{
struct ide_host *host;
int i;
@@ -1567,7 +1567,7 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
if (host == NULL)
return NULL;
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
ide_hwif_t *hwif;
int idx;
@@ -1602,23 +1602,13 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
if (hws[0])
host->dev[0] = hws[0]->dev;
- if (d)
+ if (d) {
+ host->init_chipset = d->init_chipset;
host->host_flags = d->host_flags;
+ }
return host;
}
-EXPORT_SYMBOL_GPL(ide_host_alloc_all);
-
-struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
-{
- hw_regs_t *hws_all[MAX_HWIFS];
- int i;
-
- for (i = 0; i < MAX_HWIFS; i++)
- hws_all[i] = (i < 4) ? hws[i] : NULL;
-
- return ide_host_alloc_all(d, hws_all);
-}
EXPORT_SYMBOL_GPL(ide_host_alloc);
int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
@@ -1627,7 +1617,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_hwif_t *hwif, *mate = NULL;
int i, j = 0;
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL) {
@@ -1640,22 +1630,22 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
if (d == NULL) {
mate = NULL;
- continue;
- }
+ } else {
+ if ((i & 1) && mate) {
+ hwif->mate = mate;
+ mate->mate = hwif;
+ }
- if ((i & 1) && mate) {
- hwif->mate = mate;
- mate->mate = hwif;
- }
+ mate = (i & 1) ? NULL : hwif;
- mate = (i & 1) ? NULL : hwif;
+ ide_init_port(hwif, i & 1, d);
+ ide_port_cable_detect(hwif);
+ }
- ide_init_port(hwif, i & 1, d);
- ide_port_cable_detect(hwif);
ide_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL)
@@ -1672,7 +1662,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_port_tune_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL)
@@ -1685,10 +1675,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
continue;
}
- j++;
-
if (hwif->present)
- ide_port_setup_devices(hwif);
+ if (ide_port_setup_devices(hwif) == 0) {
+ hwif->present = 0;
+ continue;
+ }
+
+ j++;
ide_acpi_init(hwif);
@@ -1696,7 +1689,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_acpi_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL)
@@ -1709,7 +1702,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
hwif_register_devices(hwif);
}
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL)
@@ -1754,7 +1747,7 @@ void ide_host_free(struct ide_host *host)
ide_hwif_t *hwif;
int i;
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
hwif = host->ports[i];
if (hwif == NULL)
@@ -1772,7 +1765,7 @@ void ide_host_remove(struct ide_host *host)
{
int i;
- for (i = 0; i < MAX_HWIFS; i++) {
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
if (host->ports[i])
ide_unregister(host->ports[i]);
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index f66c9c3f6fc..b26926487cc 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -12,14 +12,6 @@
* "settings" files. e.g. "cat /proc/ide0/hda/settings"
* To write a new value "val" into a specific setting "name", use:
* echo "name:val" >/proc/ide/ide0/hda/settings
- *
- * Also useful, "cat /proc/ide0/hda/[identify, smart_values,
- * smart_thresholds, capabilities]" will issue an IDENTIFY /
- * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS /
- * SENSE CAPABILITIES command to /dev/hda, and then dump out the
- * returned data as 256 16-bit words. The "hdparm" utility will
- * be updated someday soon to use this mechanism.
- *
*/
#include <linux/module.h>
@@ -31,7 +23,6 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/ctype.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/seq_file.h>
@@ -109,13 +100,14 @@ static int proc_ide_read_identify
err = taskfile_lib_get_identify(drive, page);
if (!err) {
- char *out = ((char *)page) + (SECTOR_WORDS * 4);
+ char *out = (char *)page + SECTOR_SIZE;
+
page = out;
do {
out += sprintf(out, "%04x%c",
le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
val += 1;
- } while (i < (SECTOR_WORDS * 2));
+ } while (i < SECTOR_SIZE / 2);
len = out - page;
}
}
@@ -123,140 +115,25 @@ static int proc_ide_read_identify
}
/**
- * __ide_add_setting - add an ide setting option
- * @drive: drive to use
- * @name: setting name
- * @rw: true if the function is read write
- * @data_type: type of data
- * @min: range minimum
- * @max: range maximum
- * @mul_factor: multiplication scale
- * @div_factor: divison scale
- * @data: private data field
- * @set: setting
- * @auto_remove: setting auto removal flag
- *
- * Removes the setting named from the device if it is present.
- * The function takes the settings_lock to protect against
- * parallel changes. This function must not be called from IRQ
- * context. Returns 0 on success or -1 on failure.
- *
- * BUGS: This code is seriously over-engineered. There is also
- * magic about how the driver specific features are setup. If
- * a driver is attached we assume the driver settings are auto
- * remove.
- */
-
-static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
-{
- ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
-
- mutex_lock(&ide_setting_mtx);
- while ((*p) && strcmp((*p)->name, name) < 0)
- p = &((*p)->next);
- if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
- goto abort;
- if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
- goto abort;
- strcpy(setting->name, name);
- setting->rw = rw;
- setting->data_type = data_type;
- setting->min = min;
- setting->max = max;
- setting->mul_factor = mul_factor;
- setting->div_factor = div_factor;
- setting->data = data;
- setting->set = set;
-
- setting->next = *p;
- if (auto_remove)
- setting->auto_remove = 1;
- *p = setting;
- mutex_unlock(&ide_setting_mtx);
- return 0;
-abort:
- mutex_unlock(&ide_setting_mtx);
- kfree(setting);
- return -1;
-}
-
-int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
-{
- return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
-}
-
-EXPORT_SYMBOL(ide_add_setting);
-
-/**
- * __ide_remove_setting - remove an ide setting option
- * @drive: drive to use
- * @name: setting name
- *
- * Removes the setting named from the device if it is present.
- * The caller must hold the setting semaphore.
- */
-
-static void __ide_remove_setting(ide_drive_t *drive, char *name)
-{
- ide_settings_t **p, *setting;
-
- p = (ide_settings_t **) &drive->settings;
-
- while ((*p) && strcmp((*p)->name, name))
- p = &((*p)->next);
- setting = (*p);
- if (setting == NULL)
- return;
-
- (*p) = setting->next;
-
- kfree(setting->name);
- kfree(setting);
-}
-
-/**
- * auto_remove_settings - remove driver specific settings
- * @drive: drive
- *
- * Automatically remove all the driver specific settings for this
- * drive. This function may not be called from IRQ context. The
- * caller must hold ide_setting_mtx.
- */
-
-static void auto_remove_settings(ide_drive_t *drive)
-{
- ide_settings_t *setting;
-repeat:
- setting = drive->settings;
- while (setting) {
- if (setting->auto_remove) {
- __ide_remove_setting(drive, setting->name);
- goto repeat;
- }
- setting = setting->next;
- }
-}
-
-/**
- * ide_find_setting_by_name - find a drive specific setting
- * @drive: drive to scan
+ * ide_find_setting - find a specific setting
+ * @st: setting table pointer
* @name: setting name
*
- * Scan's the device setting table for a matching entry and returns
+ * Scan's the setting table for a matching entry and returns
* this or NULL if no entry is found. The caller must hold the
* setting semaphore
*/
-static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
+static
+const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st,
+ char *name)
{
- ide_settings_t *setting = drive->settings;
-
- while (setting) {
- if (strcmp(setting->name, name) == 0)
+ while (st->name) {
+ if (strcmp(st->name, name) == 0)
break;
- setting = setting->next;
+ st++;
}
- return setting;
+ return st->name ? st : NULL;
}
/**
@@ -272,26 +149,20 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* be told apart
*/
-static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+static int ide_read_setting(ide_drive_t *drive,
+ const struct ide_proc_devset *setting)
{
- int val = -EINVAL;
- unsigned long flags;
+ const struct ide_devset *ds = setting->setting;
+ int val = -EINVAL;
+
+ if (ds->get) {
+ unsigned long flags;
- if ((setting->rw & SETTING_READ)) {
spin_lock_irqsave(&ide_lock, flags);
- switch (setting->data_type) {
- case TYPE_BYTE:
- val = *((u8 *) setting->data);
- break;
- case TYPE_SHORT:
- val = *((u16 *) setting->data);
- break;
- case TYPE_INT:
- val = *((u32 *) setting->data);
- break;
- }
+ val = ds->get(drive);
spin_unlock_irqrestore(&ide_lock, flags);
}
+
return val;
}
@@ -313,33 +184,23 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* The current scheme of polling is kludgy, though safe enough.
*/
-static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
+static int ide_write_setting(ide_drive_t *drive,
+ const struct ide_proc_devset *setting, int val)
{
+ const struct ide_devset *ds = setting->setting;
+
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (setting->set)
- return setting->set(drive, val);
- if (!(setting->rw & SETTING_WRITE))
+ if (!ds->set)
return -EPERM;
- if (val < setting->min || val > setting->max)
+ if ((ds->flags & DS_SYNC)
+ && (val < setting->min || val > setting->max))
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- switch (setting->data_type) {
- case TYPE_BYTE:
- *((u8 *) setting->data) = val;
- break;
- case TYPE_SHORT:
- *((u16 *) setting->data) = val;
- break;
- case TYPE_INT:
- *((u32 *) setting->data) = val;
- break;
- }
- spin_unlock_irq(&ide_lock);
- return 0;
+ return ide_devset_execute(drive, ds, val);
}
+ide_devset_get(xfer_rate, current_speed);
+
static int set_xfer_rate (ide_drive_t *drive, int arg)
{
ide_task_t task;
@@ -349,7 +210,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
return -EINVAL;
memset(&task, 0, sizeof(task));
- task.tf.command = WIN_SETFEATURES;
+ task.tf.command = ATA_CMD_SET_FEATURES;
task.tf.feature = SETFEATURES_XFER;
task.tf.nsect = (u8)arg;
task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
@@ -364,29 +225,23 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
return err;
}
-/**
- * ide_add_generic_settings - generic ide settings
- * @drive: drive being configured
- *
- * Add the generic parts of the system settings to the /proc files.
- * The caller must not be holding the ide_setting_mtx.
- */
-
-void ide_add_generic_settings (ide_drive_t *drive)
-{
-/*
- * drive setting name read/write access data type min max mul_factor div_factor data pointer set function
- */
- __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0);
- __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0);
- __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0);
- __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0);
- __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0);
- __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0);
- __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0);
- __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0);
- __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0);
-}
+ide_devset_rw(current_speed, xfer_rate);
+ide_devset_rw_field(init_speed, init_speed);
+ide_devset_rw_flag(nice1, IDE_DFLAG_NICE1);
+ide_devset_rw_field(number, dn);
+
+static const struct ide_proc_devset ide_generic_settings[] = {
+ IDE_PROC_DEVSET(current_speed, 0, 70),
+ IDE_PROC_DEVSET(init_speed, 0, 70),
+ IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)),
+ IDE_PROC_DEVSET(keepsettings, 0, 1),
+ IDE_PROC_DEVSET(nice1, 0, 1),
+ IDE_PROC_DEVSET(number, 0, 3),
+ IDE_PROC_DEVSET(pio_mode, 0, 255),
+ IDE_PROC_DEVSET(unmaskirq, 0, 1),
+ IDE_PROC_DEVSET(using_dma, 0, 1),
+ { 0 },
+};
static void proc_ide_settings_warn(void)
{
@@ -403,19 +258,32 @@ static void proc_ide_settings_warn(void)
static int proc_ide_read_settings
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
+ const struct ide_proc_devset *setting, *g, *d;
+ const struct ide_devset *ds;
ide_drive_t *drive = (ide_drive_t *) data;
- ide_settings_t *setting = (ide_settings_t *) drive->settings;
char *out = page;
int len, rc, mul_factor, div_factor;
proc_ide_settings_warn();
mutex_lock(&ide_setting_mtx);
+ g = ide_generic_settings;
+ d = drive->settings;
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
- while (setting) {
- mul_factor = setting->mul_factor;
- div_factor = setting->div_factor;
+ while (g->name || (d && d->name)) {
+ /* read settings in the alphabetical order */
+ if (g->name && d && d->name) {
+ if (strcmp(d->name, g->name) < 0)
+ setting = d++;
+ else
+ setting = g++;
+ } else if (d && d->name) {
+ setting = d++;
+ } else
+ setting = g++;
+ mul_factor = setting->mulf ? setting->mulf(drive) : 1;
+ div_factor = setting->divf ? setting->divf(drive) : 1;
out += sprintf(out, "%-24s", setting->name);
rc = ide_read_setting(drive, setting);
if (rc >= 0)
@@ -423,12 +291,12 @@ static int proc_ide_read_settings
else
out += sprintf(out, "%-16s", "write-only");
out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
- if (setting->rw & SETTING_READ)
+ ds = setting->setting;
+ if (ds->get)
out += sprintf(out, "r");
- if (setting->rw & SETTING_WRITE)
+ if (ds->set)
out += sprintf(out, "w");
out += sprintf(out, "\n");
- setting = setting->next;
}
len = out - page;
mutex_unlock(&ide_setting_mtx);
@@ -442,9 +310,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
{
ide_drive_t *drive = (ide_drive_t *) data;
char name[MAX_LEN + 1];
- int for_real = 0;
+ int for_real = 0, mul_factor, div_factor;
unsigned long n;
- ide_settings_t *setting;
+
+ const struct ide_proc_devset *setting;
char *buf, *s;
if (!capable(CAP_SYS_ADMIN))
@@ -512,13 +381,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
}
mutex_lock(&ide_setting_mtx);
- setting = ide_find_setting_by_name(drive, name);
+ /* generic settings first, then driver specific ones */
+ setting = ide_find_setting(ide_generic_settings, name);
if (!setting) {
- mutex_unlock(&ide_setting_mtx);
- goto parse_error;
+ if (drive->settings)
+ setting = ide_find_setting(drive->settings, name);
+ if (!setting) {
+ mutex_unlock(&ide_setting_mtx);
+ goto parse_error;
+ }
+ }
+ if (for_real) {
+ mul_factor = setting->mulf ? setting->mulf(drive) : 1;
+ div_factor = setting->divf ? setting->divf(drive) : 1;
+ ide_write_setting(drive, setting, val * div_factor / mul_factor);
}
- if (for_real)
- ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
mutex_unlock(&ide_setting_mtx);
}
} while (!for_real++);
@@ -561,11 +438,10 @@ static int proc_ide_read_dmodel
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
ide_drive_t *drive = (ide_drive_t *) data;
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
int len;
- len = sprintf(page, "%.40s\n",
- (id && id->model[0]) ? (char *)id->model : "(none)");
+ len = sprintf(page, "%.40s\n", m[0] ? m : "(none)");
PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}
@@ -690,6 +566,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
{
+ mutex_lock(&ide_setting_mtx);
+ drive->settings = driver->settings;
+ mutex_unlock(&ide_setting_mtx);
+
ide_add_proc_entries(drive->proc, driver->proc, drive);
}
@@ -726,7 +606,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* OTOH both ide_{read,write}_setting are only ever used under
* ide_setting_mtx.
*/
- auto_remove_settings(drive);
+ drive->settings = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
}
@@ -742,9 +622,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
for (d = 0; d < MAX_DRIVES; d++) {
ide_drive_t *drive = &hwif->drives[d];
- if (!drive->present)
- continue;
- if (drive->proc)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
continue;
drive->proc = proc_mkdir(drive->name, parent);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 1bce84b5663..d879c7797cd 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -15,6 +15,8 @@
* Documentation/ide/ChangeLog.ide-tape.1995-2002
*/
+#define DRV_NAME "ide-tape"
+
#define IDETAPE_VERSION "1.20"
#include <linux/module.h>
@@ -54,8 +56,6 @@ enum {
DBG_CHRDEV = (1 << 2),
/* all remaining procedures */
DBG_PROCS = (1 << 3),
- /* buffer alloc info (pc_stack & rq_stack) */
- DBG_PCRQ_STACK = (1 << 4),
};
/* define to see debug info */
@@ -81,26 +81,6 @@ enum {
#define IDETAPE_MAX_PC_RETRIES 3
/*
- * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE
- * bytes. This is used for several packet commands (Not for READ/WRITE commands)
- */
-#define IDETAPE_PC_BUFFER_SIZE 256
-
-/*
- * In various places in the driver, we need to allocate storage
- * for packet commands and requests, which will remain valid while
- * we leave the driver to wait for an interrupt or a timeout event.
- */
-#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES)
-
-/*
- * Some drives (for example, Seagate STT3401A Travan) require a very long
- * timeout, because they don't return an interrupt or clear their busy bit
- * until after the command completes (even retension commands).
- */
-#define IDETAPE_WAIT_CMD (900*HZ)
-
-/*
* The following parameter is used to select the point in the internal tape fifo
* in which we will start to refill the buffer. Decreasing the following
* parameter will improve the system's latency and interactive response, while
@@ -172,20 +152,6 @@ struct idetape_bh {
#define IDETAPE_LU_RETENSION_MASK 2
#define IDETAPE_LU_EOT_MASK 4
-/*
- * Special requests for our block device strategy routine.
- *
- * In order to service a character device command, we add special requests to
- * the tail of our block device request queue and wait for their completion.
- */
-
-enum {
- REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */
- REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */
- REQ_IDETAPE_READ = (1 << 2),
- REQ_IDETAPE_WRITE = (1 << 3),
-};
-
/* Error codes returned in rq->errors to the higher part of the driver. */
#define IDETAPE_ERROR_GENERAL 101
#define IDETAPE_ERROR_FILEMARK 102
@@ -206,31 +172,15 @@ typedef struct ide_tape_obj {
struct kref kref;
/*
- * Since a typical character device operation requires more
- * than one packet command, we provide here enough memory
- * for the maximum of interconnected packet commands.
- * The packet commands are stored in the circular array pc_stack.
- * pc_stack_index points to the last used entry, and warps around
- * to the start when we get to the last array entry.
- *
- * pc points to the current processed packet command.
- *
* failed_pc points to the last failed packet command, or contains
* NULL if we do not need to retry any packet command. This is
* required since an additional packet command is needed before the
* retry, to get detailed information on what went wrong.
*/
- /* Current packet command */
- struct ide_atapi_pc *pc;
/* Last failed packet command */
struct ide_atapi_pc *failed_pc;
- /* Packet command stack */
- struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK];
- /* Next free packet command storage space */
- int pc_stack_index;
- struct request rq_stack[IDETAPE_PC_STACK];
- /* We implement a circular array */
- int rq_stack_index;
+ /* used by REQ_IDETAPE_{READ,WRITE} requests */
+ struct ide_atapi_pc queued_pc;
/*
* DSC polling variables.
@@ -317,11 +267,6 @@ static DEFINE_MUTEX(idetape_ref_mutex);
static struct class *idetape_sysfs_class;
-#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
-
-#define ide_tape_g(disk) \
- container_of((disk)->private_data, struct ide_tape_obj, driver)
-
static void ide_tape_release(struct kref *);
static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
@@ -329,7 +274,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
struct ide_tape_obj *tape = NULL;
mutex_lock(&idetape_ref_mutex);
- tape = ide_tape_g(disk);
+ tape = ide_drv_g(disk, ide_tape_obj);
if (tape) {
if (ide_device_get(tape->drive))
tape = NULL;
@@ -356,8 +301,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
*/
static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
-#define ide_tape_f(file) ((file)->private_data)
-
static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
{
struct ide_tape_obj *tape = NULL;
@@ -451,47 +394,6 @@ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
}
/*
- * idetape_next_pc_storage returns a pointer to a place in which we can
- * safely store a packet command, even though we intend to leave the
- * driver. A storage space for a maximum of IDETAPE_PC_STACK packet
- * commands is allocated at initialization time.
- */
-static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index);
-
- if (tape->pc_stack_index == IDETAPE_PC_STACK)
- tape->pc_stack_index = 0;
- return (&tape->pc_stack[tape->pc_stack_index++]);
-}
-
-/*
- * idetape_next_rq_storage is used along with idetape_next_pc_storage.
- * Since we queue packet commands in the request queue, we need to
- * allocate a request, along with the allocation of a packet command.
- */
-
-/**************************************************************
- * *
- * This should get fixed to use kmalloc(.., GFP_ATOMIC) *
- * followed later on by kfree(). -ml *
- * *
- **************************************************************/
-
-static struct request *idetape_next_rq_storage(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index);
-
- if (tape->rq_stack_index == IDETAPE_PC_STACK)
- tape->rq_stack_index = 0;
- return (&tape->rq_stack[tape->rq_stack_index++]);
-}
-
-/*
* called on each failed packet command retry to analyze the request sense. We
* currently do not utilize this information.
*/
@@ -606,14 +508,19 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
return 0;
}
-static void ide_tape_callback(ide_drive_t *drive)
+static void ide_tape_handle_dsc(ide_drive_t *);
+
+static void ide_tape_callback(ide_drive_t *drive, int dsc)
{
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc = tape->pc;
+ struct ide_atapi_pc *pc = drive->pc;
int uptodate = pc->error ? 0 : 1;
debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ if (dsc)
+ ide_tape_handle_dsc(drive);
+
if (tape->failed_pc == pc)
tape->failed_pc = NULL;
@@ -642,7 +549,7 @@ static void ide_tape_callback(ide_drive_t *drive)
if (pc->error)
uptodate = pc->error;
} else if (pc->c[0] == READ_POSITION && uptodate) {
- u8 *readpos = tape->pc->buf;
+ u8 *readpos = pc->buf;
debug_log(DBG_SENSE, "BOP - %s\n",
(readpos[0] & 0x80) ? "Yes" : "No");
@@ -667,79 +574,6 @@ static void ide_tape_callback(ide_drive_t *drive)
idetape_end_request(drive, uptodate, 0);
}
-static void idetape_init_pc(struct ide_atapi_pc *pc)
-{
- memset(pc->c, 0, 12);
- pc->retries = 0;
- pc->flags = 0;
- pc->req_xfer = 0;
- pc->buf = pc->pc_buf;
- pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
- pc->bh = NULL;
- pc->b_data = NULL;
-}
-
-static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
- idetape_init_pc(pc);
- pc->c[0] = REQUEST_SENSE;
- pc->c[4] = 20;
- pc->req_xfer = 20;
-}
-
-static void idetape_init_rq(struct request *rq, u8 cmd)
-{
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[13] = cmd;
-}
-
-/*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver. The function below is called from the request
- * handling part of the driver (the "bottom" part). Safe storage for the request
- * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that.
- *
- * Memory for those requests is pre-allocated at initialization time, and is
- * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for
- * the maximum possible number of inter-dependent packet commands.
- *
- * The higher level of the driver - The ioctl handler and the character device
- * handling functions should queue request to the lower level part and wait for
- * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
- */
-static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
- struct request *rq)
-{
- struct ide_tape_obj *tape = drive->driver_data;
-
- idetape_init_rq(rq, REQ_IDETAPE_PC1);
- rq->cmd_flags |= REQ_PREEMPT;
- rq->buffer = (char *) pc;
- rq->rq_disk = tape->disk;
- memcpy(rq->cmd, pc->c, 12);
- ide_do_drive_cmd(drive, rq);
-}
-
-/*
- * idetape_retry_pc is called when an error was detected during the
- * last packet command. We queue a request sense packet command in
- * the head of the request list.
- */
-static void idetape_retry_pc(ide_drive_t *drive)
-{
- struct ide_atapi_pc *pc;
- struct request *rq;
-
- (void)ide_read_error(drive);
- pc = idetape_next_pc_storage(drive);
- rq = idetape_next_rq_storage(drive);
- idetape_create_request_sense_cmd(pc);
- set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- idetape_queue_pc_head(drive, pc, rq);
-}
-
/*
* Postpone the current request so that ide.c will be able to service requests
* from another device on the same hwgroup while we are polling for DSC.
@@ -766,44 +600,30 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
idetape_postpone_request(drive);
}
-static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write)
{
if (write)
idetape_output_buffers(drive, pc, bcount);
else
idetape_input_buffers(drive, pc, bcount);
-}
-
-/*
- * This is the usual interrupt handler which will be called during a packet
- * command. We will transfer some of the data (as requested by the drive) and
- * will re-point interrupt handler to us. When data transfer is finished, we
- * will act according to the algorithm described before
- * idetape_issue_pc.
- */
-static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD,
- NULL, idetape_update_buffers, idetape_retry_pc,
- ide_tape_handle_dsc, ide_tape_io_buffers);
+ return bcount;
}
/*
* Packet Command Interface
*
- * The current Packet Command is available in tape->pc, and will not change
+ * The current Packet Command is available in drive->pc, and will not change
* until we finish handling it. Each packet command is associated with a
* callback function that will be called when the command is finished.
*
* The handling will be done in three stages:
*
* 1. idetape_issue_pc will send the packet command to the drive, and will set
- * the interrupt handler to idetape_pc_intr.
+ * the interrupt handler to ide_pc_intr.
*
- * 2. On each interrupt, idetape_pc_intr will be called. This step will be
+ * 2. On each interrupt, ide_pc_intr will be called. This step will be
* repeated until the device signals us that no more interrupts will be issued.
*
* 3. ATAPI Tape media access commands have immediate status with a delayed
@@ -827,20 +647,13 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
* again, the callback function will be called and then we will handle the next
* request.
*/
-static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
- IDETAPE_WAIT_CMD, NULL);
-}
static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
idetape_tape_t *tape = drive->driver_data;
- if (tape->pc->c[0] == REQUEST_SENSE &&
+ if (drive->pc->c[0] == REQUEST_SENSE &&
pc->c[0] == REQUEST_SENSE) {
printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
"Two request sense in serial were issued\n");
@@ -848,8 +661,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
tape->failed_pc = pc;
+
/* Set the current packet command */
- tape->pc = pc;
+ drive->pc = pc;
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
(pc->flags & PC_FLAG_ABORT)) {
@@ -873,21 +687,20 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->error = IDETAPE_ERROR_GENERAL;
}
tape->failed_pc = NULL;
- drive->pc_callback(drive);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
pc->retries++;
- return ide_issue_pc(drive, pc, idetape_transfer_pc,
- IDETAPE_WAIT_CMD, NULL);
+ return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
}
/* A mode sense command is used to "sense" tape parameters. */
static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = MODE_SENSE;
if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
/* DBD = 1 - Don't return block descriptors */
@@ -915,19 +728,19 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc *pc = tape->pc;
+ struct ide_atapi_pc *pc = drive->pc;
u8 stat;
stat = hwif->tp_ops->read_status(hwif);
- if (stat & SEEK_STAT) {
- if (stat & ERR_STAT) {
+ if (stat & ATA_DSC) {
+ if (stat & ATA_ERR) {
/* Error detected */
if (pc->c[0] != TEST_UNIT_READY)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
tape->name);
/* Retry operation */
- idetape_retry_pc(drive);
+ ide_retry_pc(drive, tape->disk);
return ide_stopped;
}
pc->error = 0;
@@ -935,7 +748,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
pc->error = IDETAPE_ERROR_GENERAL;
tape->failed_pc = NULL;
}
- drive->pc_callback(drive);
+ drive->pc_callback(drive, 0);
return ide_stopped;
}
@@ -946,7 +759,7 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
struct idetape_bh *bh = (struct idetape_bh *)rq->special;
unsigned int length = rq->current_nr_sectors;
- idetape_init_pc(pc);
+ ide_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
pc->bh = bh;
@@ -978,9 +791,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *postponed_rq = tape->postponed_rq;
u8 stat;
- debug_log(DBG_SENSE, "sector: %ld, nr_sectors: %ld,"
- " current_nr_sectors: %d\n",
- rq->sector, rq->nr_sectors, rq->current_nr_sectors);
+ debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
+ " current_nr_sectors: %u\n",
+ (unsigned long long)rq->sector, rq->nr_sectors,
+ rq->current_nr_sectors);
if (!blk_special_request(rq)) {
/* We do not support buffer cache originated requests. */
@@ -991,7 +805,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
/* Retry a failed packet command */
- if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) {
+ if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
pc = tape->failed_pc;
goto out;
}
@@ -1012,16 +826,17 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
*/
stat = hwif->tp_ops->read_status(hwif);
- if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+ if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
+ (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- if (drive->post_reset == 1) {
+ if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- drive->post_reset = 0;
+ drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
}
if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
- (stat & SEEK_STAT) == 0) {
+ (stat & ATA_DSC) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
tape->dsc_poll_freq = tape->best_dsc_rw_freq;
@@ -1043,12 +858,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
return ide_stopped;
}
if (rq->cmd[13] & REQ_IDETAPE_READ) {
- pc = idetape_next_pc_storage(drive);
+ pc = &tape->queued_pc;
ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
goto out;
}
if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
- pc = idetape_next_pc_storage(drive);
+ pc = &tape->queued_pc;
ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
goto out;
}
@@ -1235,77 +1050,30 @@ static void idetape_init_merge_buffer(idetape_tape_t *tape)
static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc, int write_filemark)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = WRITE_FILEMARKS;
pc->c[4] = write_filemark;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
}
-static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
-{
- idetape_init_pc(pc);
- pc->c[0] = TEST_UNIT_READY;
-}
-
-/*
- * We add a special packet command request to the tail of the request queue, and
- * wait for it to be serviced. This is not to be called from within the request
- * handling part of the driver! We allocate here data on the stack and it is
- * valid until the request is finished. This is not the case for the bottom part
- * of the driver, where we are always leaving the functions to wait for an
- * interrupt or a timer event.
- *
- * From the bottom part of the driver, we should allocate safe memory using
- * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request
- * to the request list without waiting for it to be serviced! In that case, we
- * usually use idetape_queue_pc_head().
- */
-static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- struct ide_tape_obj *tape = drive->driver_data;
- struct request *rq;
- int error;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[13] = REQ_IDETAPE_PC1;
- rq->buffer = (char *)pc;
- memcpy(rq->cmd, pc->c, 12);
- error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
- blk_put_request(rq);
- return error;
-}
-
-static void idetape_create_load_unload_cmd(ide_drive_t *drive,
- struct ide_atapi_pc *pc, int cmd)
-{
- idetape_init_pc(pc);
- pc->c[0] = START_STOP;
- pc->c[4] = cmd;
- pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-}
-
static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
{
idetape_tape_t *tape = drive->driver_data;
- struct ide_atapi_pc pc;
+ struct gendisk *disk = tape->disk;
int load_attempted = 0;
/* Wait for the tape to become ready */
set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
timeout += jiffies;
while (time_before(jiffies, timeout)) {
- idetape_create_test_unit_ready_cmd(&pc);
- if (!idetape_queue_pc_tail(drive, &pc))
+ if (ide_do_test_unit_ready(drive, disk) == 0)
return 0;
if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
|| (tape->asc == 0x3A)) {
/* no media */
if (load_attempted)
return -ENOMEDIUM;
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
- idetape_queue_pc_tail(drive, &pc);
+ ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
load_attempted = 1;
/* not about to be ready */
} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
@@ -1318,11 +1086,12 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
static int idetape_flush_tape_buffers(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
struct ide_atapi_pc pc;
int rc;
idetape_create_write_filemark_cmd(drive, &pc, 0);
- rc = idetape_queue_pc_tail(drive, &pc);
+ rc = ide_queue_pc_tail(drive, tape->disk, &pc);
if (rc)
return rc;
idetape_wait_ready(drive, 60 * 5 * HZ);
@@ -1331,7 +1100,7 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = READ_POSITION;
pc->req_xfer = 20;
}
@@ -1345,7 +1114,7 @@ static int idetape_read_position(ide_drive_t *drive)
debug_log(DBG_PROCS, "Enter %s\n", __func__);
idetape_create_read_position_cmd(&pc);
- if (idetape_queue_pc_tail(drive, &pc))
+ if (ide_queue_pc_tail(drive, tape->disk, &pc))
return -1;
position = tape->first_frame;
return position;
@@ -1355,7 +1124,7 @@ static void idetape_create_locate_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc,
unsigned int block, u8 partition, int skip)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = POSITION_TO_ELEMENT;
pc->c[1] = 2;
put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
@@ -1363,21 +1132,6 @@ static void idetape_create_locate_cmd(ide_drive_t *drive,
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
}
-static int idetape_create_prevent_cmd(ide_drive_t *drive,
- struct ide_atapi_pc *pc, int prevent)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- /* device supports locking according to capabilities page */
- if (!(tape->caps[6] & 0x01))
- return 0;
-
- idetape_init_pc(pc);
- pc->c[0] = ALLOW_MEDIUM_REMOVAL;
- pc->c[4] = prevent;
- return 1;
-}
-
static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
@@ -1405,6 +1159,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
u8 partition, int skip)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
int retval;
struct ide_atapi_pc pc;
@@ -1412,12 +1167,12 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
__ide_tape_discard_merge_buffer(drive);
idetape_wait_ready(drive, 60 * 5 * HZ);
idetape_create_locate_cmd(drive, &pc, block, partition, skip);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return (retval);
idetape_create_read_position_cmd(&pc);
- return (idetape_queue_pc_tail(drive, &pc));
+ return ide_queue_pc_tail(drive, disk, &pc);
}
static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
@@ -1477,7 +1232,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = INQUIRY;
pc->c[4] = 254;
pc->req_xfer = 254;
@@ -1486,14 +1241,14 @@ static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
static void idetape_create_rewind_cmd(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = REZERO_UNIT;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
}
static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = ERASE;
pc->c[1] = 1;
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
@@ -1501,7 +1256,7 @@ static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
{
- idetape_init_pc(pc);
+ ide_init_pc(pc);
pc->c[0] = SPACE;
put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
pc->c[1] = cmd;
@@ -1600,7 +1355,7 @@ static int idetape_init_read(ide_drive_t *drive)
* No point in issuing this if DSC overlap isn't supported, some
* drives (Seagate STT3401A) will return an error.
*/
- if (drive->dsc_overlap) {
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
bytes_read = idetape_queue_rw_tail(drive,
REQ_IDETAPE_READ, 0,
tape->merge_bh);
@@ -1664,20 +1419,20 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
*/
static int idetape_rewind_tape(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
int retval;
struct ide_atapi_pc pc;
- idetape_tape_t *tape;
- tape = drive->driver_data;
debug_log(DBG_SENSE, "Enter %s\n", __func__);
idetape_create_rewind_cmd(drive, &pc);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return retval;
idetape_create_read_position_cmd(&pc);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_queue_pc_tail(drive, disk, &pc);
if (retval)
return retval;
return 0;
@@ -1720,6 +1475,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
struct ide_atapi_pc pc;
int retval, count = 0;
int sprev = !!(tape->caps[4] & 0x20);
@@ -1744,7 +1500,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
case MTBSF:
idetape_create_space_cmd(&pc, mt_count - count,
IDETAPE_SPACE_OVER_FILEMARK);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTFSFM:
case MTBSFM:
if (!sprev)
@@ -1780,7 +1536,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct ide_tape_obj *tape = ide_tape_f(file);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
ssize_t bytes_read, temp, actually_read = 0, rc;
ssize_t ret = 0;
@@ -1842,7 +1598,7 @@ finish:
static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct ide_tape_obj *tape = ide_tape_f(file);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
ssize_t actually_written = 0;
ssize_t ret = 0;
@@ -1875,7 +1631,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
* point in issuing this if DSC overlap isn't supported, some
* drives (Seagate STT3401A) will return an error.
*/
- if (drive->dsc_overlap) {
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
ssize_t retval = idetape_queue_rw_tail(drive,
REQ_IDETAPE_WRITE, 0,
tape->merge_bh);
@@ -1933,11 +1689,12 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
static int idetape_write_filemark(ide_drive_t *drive)
{
+ struct ide_tape_obj *tape = drive->driver_data;
struct ide_atapi_pc pc;
/* Write a filemark */
idetape_create_write_filemark_cmd(drive, &pc, 1);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
return -EIO;
}
@@ -1960,6 +1717,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
+ struct gendisk *disk = tape->disk;
struct ide_atapi_pc pc;
int i, retval;
@@ -1996,9 +1754,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
return 0;
case MTLOAD:
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
case MTUNLOAD:
case MTOFFL:
/*
@@ -2006,14 +1762,11 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
* attempting to eject.
*/
if (tape->door_locked) {
- if (idetape_create_prevent_cmd(drive, &pc, 0))
- if (!idetape_queue_pc_tail(drive, &pc))
- tape->door_locked = DOOR_UNLOCKED;
+ if (!ide_set_media_lock(drive, disk, 0))
+ tape->door_locked = DOOR_UNLOCKED;
}
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- !IDETAPE_LU_LOAD_MASK);
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK);
if (!retval)
clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
return retval;
@@ -2022,16 +1775,15 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
return idetape_flush_tape_buffers(drive);
case MTRETEN:
ide_tape_discard_merge_buffer(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
+ return ide_do_start_stop(drive, disk,
IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
case MTEOM:
idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTERASE:
(void)idetape_rewind_tape(drive);
idetape_create_erase_cmd(&pc);
- return idetape_queue_pc_tail(drive, &pc);
+ return ide_queue_pc_tail(drive, disk, &pc);
case MTSETBLK:
if (mt_count) {
if (mt_count < tape->blk_size ||
@@ -2052,17 +1804,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
case MTFSR:
case MTBSR:
case MTLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 1))
- return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_set_media_lock(drive, disk, 1);
if (retval)
return retval;
tape->door_locked = DOOR_EXPLICITLY_LOCKED;
return 0;
case MTUNLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 0))
- return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
+ retval = ide_set_media_lock(drive, disk, 0);
if (retval)
return retval;
tape->door_locked = DOOR_UNLOCKED;
@@ -2082,7 +1830,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct ide_tape_obj *tape = ide_tape_f(file);
+ struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
struct mtop mtop;
struct mtget mtget;
@@ -2144,7 +1892,7 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
struct ide_atapi_pc pc;
idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
if (tape->blk_size == 0) {
printk(KERN_WARNING "ide-tape: Cannot deal with zero "
@@ -2164,7 +1912,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
unsigned int minor = iminor(inode), i = minor & ~0xc0;
ide_drive_t *drive;
idetape_tape_t *tape;
- struct ide_atapi_pc pc;
int retval;
if (i >= MAX_HWIFS * MAX_DRIVES)
@@ -2227,11 +1974,9 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
/* Lock the tape drive door so user can't eject. */
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
- if (idetape_create_prevent_cmd(drive, &pc, 1)) {
- if (!idetape_queue_pc_tail(drive, &pc)) {
- if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
- tape->door_locked = DOOR_LOCKED;
- }
+ if (!ide_set_media_lock(drive, tape->disk, 1)) {
+ if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
+ tape->door_locked = DOOR_LOCKED;
}
}
unlock_kernel();
@@ -2262,9 +2007,8 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
static int idetape_chrdev_release(struct inode *inode, struct file *filp)
{
- struct ide_tape_obj *tape = ide_tape_f(filp);
+ struct ide_tape_obj *tape = filp->private_data;
ide_drive_t *drive = tape->drive;
- struct ide_atapi_pc pc;
unsigned int minor = iminor(inode);
lock_kernel();
@@ -2283,10 +2027,8 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
(void) idetape_rewind_tape(drive);
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
if (tape->door_locked == DOOR_LOCKED) {
- if (idetape_create_prevent_cmd(drive, &pc, 0)) {
- if (!idetape_queue_pc_tail(drive, &pc))
- tape->door_locked = DOOR_UNLOCKED;
- }
+ if (!ide_set_media_lock(drive, tape->disk, 0))
+ tape->door_locked = DOOR_UNLOCKED;
}
}
clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
@@ -2295,53 +2037,14 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
return 0;
}
-/*
- * check the contents of the ATAPI IDENTIFY command results. We return:
- *
- * 1 - If the tape can be supported by us, based on the information we have so
- * far.
- *
- * 0 - If this tape driver is not currently supported by us.
- */
-static int idetape_identify_device(ide_drive_t *drive)
-{
- u8 gcw[2], protocol, device_type, removable, packet_size;
-
- if (drive->id_read == 0)
- return 1;
-
- *((unsigned short *) &gcw) = drive->id->config;
-
- protocol = (gcw[1] & 0xC0) >> 6;
- device_type = gcw[1] & 0x1F;
- removable = !!(gcw[0] & 0x80);
- packet_size = gcw[0] & 0x3;
-
- /* Check that we can support this device */
- if (protocol != 2)
- printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
- protocol);
- else if (device_type != 1)
- printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
- "to tape\n", device_type);
- else if (!removable)
- printk(KERN_ERR "ide-tape: The removable flag is not set\n");
- else if (packet_size != 0) {
- printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12"
- " bytes\n", packet_size);
- } else
- return 1;
- return 0;
-}
-
static void idetape_get_inquiry_results(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc pc;
- char fw_rev[6], vendor_id[10], product_id[18];
+ char fw_rev[4], vendor_id[8], product_id[16];
idetape_create_inquiry_cmd(&pc);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
tape->name);
return;
@@ -2350,11 +2053,11 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
memcpy(product_id, &pc.buf[16], 16);
memcpy(fw_rev, &pc.buf[32], 4);
- ide_fixstring(vendor_id, 10, 0);
- ide_fixstring(product_id, 18, 0);
- ide_fixstring(fw_rev, 6, 0);
+ ide_fixstring(vendor_id, 8, 0);
+ ide_fixstring(product_id, 16, 0);
+ ide_fixstring(fw_rev, 4, 0);
- printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
+ printk(KERN_INFO "ide-tape: %s <-> %s: %.8s %.16s rev %.4s\n",
drive->name, tape->name, vendor_id, product_id, fw_rev);
}
@@ -2370,7 +2073,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
u8 speed, max_speed;
idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
- if (idetape_queue_pc_tail(drive, &pc)) {
+ if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
" some default values\n");
tape->blk_size = 512;
@@ -2402,6 +2105,11 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
}
memcpy(&tape->caps, caps, 20);
+
+ /* device lacks locking support according to capabilities page */
+ if ((caps[6] & 1) == 0)
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+
if (caps[7] & 0x02)
tape->blk_size = 512;
else if (caps[7] & 0x04)
@@ -2409,28 +2117,56 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
}
#ifdef CONFIG_IDE_PROC_FS
-static void idetape_add_settings(ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
- 1, 2, (u16 *)&tape->caps[16], NULL);
- ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
- 1, 1, (u16 *)&tape->caps[14], NULL);
- ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
- 1, 1024, &tape->buffer_size, NULL);
- ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
- IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
- NULL);
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
- 1, &drive->dsc_overlap, NULL);
- ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
- 1, 1, &tape->avg_speed, NULL);
- ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
- 1, &tape->debug_mask, NULL);
-}
-#else
-static inline void idetape_add_settings(ide_drive_t *drive) { ; }
+#define ide_tape_devset_get(name, field) \
+static int get_##name(ide_drive_t *drive) \
+{ \
+ idetape_tape_t *tape = drive->driver_data; \
+ return tape->field; \
+}
+
+#define ide_tape_devset_set(name, field) \
+static int set_##name(ide_drive_t *drive, int arg) \
+{ \
+ idetape_tape_t *tape = drive->driver_data; \
+ tape->field = arg; \
+ return 0; \
+}
+
+#define ide_tape_devset_rw_field(_name, _field) \
+ide_tape_devset_get(_name, _field) \
+ide_tape_devset_set(_name, _field) \
+IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
+
+#define ide_tape_devset_r_field(_name, _field) \
+ide_tape_devset_get(_name, _field) \
+IDE_DEVSET(_name, 0, get_##_name, NULL)
+
+static int mulf_tdsc(ide_drive_t *drive) { return 1000; }
+static int divf_tdsc(ide_drive_t *drive) { return HZ; }
+static int divf_buffer(ide_drive_t *drive) { return 2; }
+static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
+
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
+
+ide_tape_devset_rw_field(debug_mask, debug_mask);
+ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
+
+ide_tape_devset_r_field(avg_speed, avg_speed);
+ide_tape_devset_r_field(speed, caps[14]);
+ide_tape_devset_r_field(buffer, caps[16]);
+ide_tape_devset_r_field(buffer_size, buffer_size);
+
+static const struct ide_proc_devset idetape_settings[] = {
+ __IDE_PROC_DEVSET(avg_speed, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(buffer, 0, 0xffff, NULL, divf_buffer),
+ __IDE_PROC_DEVSET(buffer_size, 0, 0xffff, NULL, divf_buffer_size),
+ __IDE_PROC_DEVSET(debug_mask, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(dsc_overlap, 0, 1, NULL, NULL),
+ __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL),
+ __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
+ mulf_tdsc, divf_tdsc),
+ { 0 },
+};
#endif
/*
@@ -2449,32 +2185,31 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
unsigned long t;
int speed;
int buffer_size;
- u8 gcw[2];
u16 *ctl = (u16 *)&tape->caps[12];
- drive->pc_callback = ide_tape_callback;
+ drive->pc_callback = ide_tape_callback;
+ drive->pc_update_buffers = idetape_update_buffers;
+ drive->pc_io_buffers = ide_tape_io_buffers;
spin_lock_init(&tape->lock);
- drive->dsc_overlap = 1;
+
+ drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+
if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
tape->name);
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
}
+
/* Seagate Travan drives do not support DSC overlap. */
- if (strstr(drive->id->model, "Seagate STT3401"))
- drive->dsc_overlap = 0;
+ if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
tape->minor = minor;
tape->name[0] = 'h';
tape->name[1] = 't';
tape->name[2] = '0' + minor;
tape->chrdev_dir = IDETAPE_DIR_NONE;
- tape->pc = tape->pc_stack;
- *((unsigned short *) &gcw) = drive->id->config;
-
- /* Command packet DRQ type */
- if (((gcw[0] & 0x60) >> 5) == 1)
- set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
@@ -2510,9 +2245,9 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
(*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
tape->buffer_size / 1024,
tape->best_dsc_rw_freq * 1000 / HZ,
- drive->using_dma ? ", DMA":"");
+ (drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
- idetape_add_settings(drive);
+ ide_proc_register_driver(drive, tape->driver);
}
static void ide_tape_remove(ide_drive_t *drive)
@@ -2528,13 +2263,13 @@ static void ide_tape_remove(ide_drive_t *drive)
static void ide_tape_release(struct kref *kref)
{
- struct ide_tape_obj *tape = to_ide_tape(kref);
+ struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk;
BUG_ON(tape->merge_bh_size);
- drive->dsc_overlap = 0;
+ drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
device_destroy(idetape_sysfs_class,
@@ -2576,13 +2311,12 @@ static ide_driver_t idetape_driver = {
.probe = ide_tape_probe,
.remove = ide_tape_remove,
.version = IDETAPE_VERSION,
- .media = ide_tape,
- .supports_dsc_overlap = 1,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
.error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
.proc = idetape_proc,
+ .settings = idetape_settings,
#endif
};
@@ -2611,7 +2345,7 @@ static int idetape_open(struct inode *inode, struct file *filp)
static int idetape_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ide_tape_obj *tape = ide_tape_g(disk);
+ struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
ide_tape_put(tape);
@@ -2622,7 +2356,7 @@ static int idetape_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
+ struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
ide_drive_t *drive = tape->drive;
int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
if (err == -EINVAL)
@@ -2645,11 +2379,12 @@ static int ide_tape_probe(ide_drive_t *drive)
if (!strstr("ide-tape", drive->driver_req))
goto failed;
- if (!drive->present)
- goto failed;
+
if (drive->media != ide_tape)
goto failed;
- if (!idetape_identify_device(drive)) {
+
+ if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
+ ide_check_atapi_device(drive, DRV_NAME) == 0) {
printk(KERN_ERR "ide-tape: %s: not supported by this version of"
" the driver\n", drive->name);
goto failed;
@@ -2667,8 +2402,6 @@ static int ide_tape_probe(ide_drive_t *drive)
ide_init_disk(g, drive);
- ide_proc_register_driver(drive, &idetape_driver);
-
kref_init(&tape->kref);
tape->drive = drive;
@@ -2687,12 +2420,11 @@ static int ide_tape_probe(ide_drive_t *drive)
idetape_setup(drive, tape, minor);
- device_create_drvdata(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor), NULL,
- "%s", tape->name);
- device_create_drvdata(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
- "n%s", tape->name);
+ device_create(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor), NULL, "%s", tape->name);
+ device_create(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+ "n%s", tape->name);
g->fops = &idetape_block_ops;
ide_register_region(g);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 7fb6f1c8627..bf4fb9d8d17 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -44,18 +44,15 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
memset(&args, 0, sizeof(ide_task_t));
args.tf.nsect = 0x01;
if (drive->media == ide_disk)
- args.tf.command = WIN_IDENTIFY;
+ args.tf.command = ATA_CMD_ID_ATA;
else
- args.tf.command = WIN_PIDENTIFY;
+ args.tf.command = ATA_CMD_ID_ATAPI;
args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
args.data_phase = TASKFILE_IN;
return ide_raw_taskfile(drive, &args, buf, 1);
}
static ide_startstop_t task_no_data_intr(ide_drive_t *);
-static ide_startstop_t set_geometry_intr(ide_drive_t *);
-static ide_startstop_t recal_intr(ide_drive_t *);
-static ide_startstop_t set_multmode_intr(ide_drive_t *);
static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
static ide_startstop_t task_in_intr(ide_drive_t *);
@@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
+ memcpy(&hwif->task, task, sizeof(*task));
+
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_dump(drive->name, tf);
tp_ops->set_irq(hwif, 1);
@@ -99,19 +98,12 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
case TASKFILE_NO_DATA:
if (handler == NULL)
handler = task_no_data_intr;
- /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
- if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
- switch (tf->command) {
- case WIN_SPECIFY: handler = set_geometry_intr; break;
- case WIN_RESTORE: handler = recal_intr; break;
- case WIN_SETMULT: handler = set_multmode_intr; break;
- }
- }
ide_execute_command(drive, tf->command, handler,
WAIT_WORSTCASE, NULL);
return ide_started;
default:
- if (drive->using_dma == 0 || dma_ops->dma_setup(drive))
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
+ dma_ops->dma_setup(drive))
return ide_stopped;
dma_ops->dma_exec_cmd(drive, tf->command);
dma_ops->dma_start(drive);
@@ -121,88 +113,56 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
EXPORT_SYMBOL_GPL(do_rw_taskfile);
/*
- * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
- */
-static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 stat;
-
- local_irq_enable_in_hardirq();
- stat = hwif->tp_ops->read_status(hwif);
-
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
- drive->mult_count = drive->mult_req;
- else {
- drive->mult_req = drive->mult_count = 0;
- drive->special.b.recalibrate = 1;
- (void) ide_dump_status(drive, "set_multmode", stat);
- }
- return ide_stopped;
-}
-
-/*
- * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
+ * Handler for commands without a data phase
*/
-static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
+static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int retries = 5;
+ ide_task_t *task = &hwif->task;
+ struct ide_taskfile *tf = &task->tf;
+ int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
+ int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
u8 stat;
local_irq_enable_in_hardirq();
while (1) {
stat = hwif->tp_ops->read_status(hwif);
- if ((stat & BUSY_STAT) == 0 || retries-- == 0)
+ if ((stat & ATA_BUSY) == 0 || retries-- == 0)
break;
udelay(10);
};
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_stopped;
-
- if (stat & (ERR_STAT|DRQ_STAT))
- return ide_error(drive, "set_geometry_intr", stat);
-
- ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
- return ide_started;
-}
-
-/*
- * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
- */
-static ide_startstop_t recal_intr(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 stat;
-
- local_irq_enable_in_hardirq();
- stat = hwif->tp_ops->read_status(hwif);
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "recal_intr", stat);
- return ide_stopped;
-}
-
-/*
- * Handler for commands without a data phase
- */
-static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- ide_task_t *args = hwif->hwgroup->rq->special;
- u8 stat;
-
- local_irq_enable_in_hardirq();
- stat = hwif->tp_ops->read_status(hwif);
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
+ if (custom && tf->command == ATA_CMD_SET_MULTI) {
+ drive->mult_req = drive->mult_count = 0;
+ drive->special.b.recalibrate = 1;
+ (void)ide_dump_status(drive, __func__, stat);
+ return ide_stopped;
+ } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
+ if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
+ ide_set_handler(drive, &task_no_data_intr,
+ WAIT_WORSTCASE, NULL);
+ return ide_started;
+ }
+ }
return ide_error(drive, "task_no_data_intr", stat);
/* calls ide_end_drive_cmd */
+ }
- if (args)
+ if (!custom)
ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+ else if (tf->command == ATA_CMD_IDLEIMMEDIATE) {
+ hwif->tp_ops->tf_read(drive, task);
+ if (tf->lbal != 0xc4) {
+ printk(KERN_ERR "%s: head unload failed!\n",
+ drive->name);
+ ide_tf_dump(drive->name, tf);
+ } else
+ drive->dev_flags |= IDE_DFLAG_PARKED;
+ ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+ } else if (tf->command == ATA_CMD_SET_MULTI)
+ drive->mult_count = drive->mult_req;
return ide_stopped;
}
@@ -220,13 +180,13 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
for (retries = 0; retries < 1000; retries++) {
stat = hwif->tp_ops->read_status(hwif);
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
udelay(10);
else
break;
}
- if (stat & BUSY_STAT)
+ if (stat & ATA_BUSY)
printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
return stat;
@@ -385,7 +345,7 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat)
{
/* Command all done? */
- if (OK_STAT(stat, READY_STAT, BUSY_STAT)) {
+ if (OK_STAT(stat, ATA_DRDY, ATA_BUSY)) {
task_end_request(drive, rq, stat);
return ide_stopped;
}
@@ -405,11 +365,11 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
u8 stat = hwif->tp_ops->read_status(hwif);
/* Error? */
- if (stat & ERR_STAT)
+ if (stat & ATA_ERR)
return task_error(drive, rq, __func__, stat);
/* Didn't want any data? Odd. */
- if (!(stat & DRQ_STAT))
+ if ((stat & ATA_DRQ) == 0)
return task_in_unexpected(drive, rq, stat);
ide_pio_datablock(drive, rq, 0);
@@ -442,7 +402,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
return task_error(drive, rq, __func__, stat);
/* Deal with unexpected ATA data phase. */
- if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft)
+ if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft)
return task_error(drive, rq, __func__, stat);
if (!hwif->nleft) {
@@ -461,16 +421,15 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
- if (ide_wait_stat(&startstop, drive, DRQ_STAT,
+ if (ide_wait_stat(&startstop, drive, ATA_DRQ,
drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
- drive->name,
- drive->hwif->data_phase ? "MULT" : "",
- drive->addressing ? "_EXT" : "");
+ drive->name, drive->hwif->data_phase ? "MULT" : "",
+ (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
return startstop;
}
- if (!drive->unmask)
+ if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
local_irq_disable();
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
@@ -586,7 +545,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
IDE_TFLAG_IN_TF;
- if (drive->addressing == 1)
+ if (drive->dev_flags & IDE_DFLAG_LBA48)
args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
if (req_task->out_flags.all) {
@@ -689,7 +648,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
req_task->in_flags.all == 0) {
req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if (drive->addressing == 1)
+ if (drive->dev_flags & IDE_DFLAG_LBA48)
req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
}
@@ -721,110 +680,3 @@ abort:
return err;
}
#endif
-
-int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
-{
- u8 *buf = NULL;
- int bufsize = 0, err = 0;
- u8 args[4], xfer_rate = 0;
- ide_task_t tfargs;
- struct ide_taskfile *tf = &tfargs.tf;
- struct hd_driveid *id = drive->id;
-
- if (NULL == (void *) arg) {
- struct request *rq;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- err = blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
-
- return err;
- }
-
- if (copy_from_user(args, (void __user *)arg, 4))
- return -EFAULT;
-
- memset(&tfargs, 0, sizeof(ide_task_t));
- tf->feature = args[2];
- if (args[0] == WIN_SMART) {
- tf->nsect = args[3];
- tf->lbal = args[1];
- tf->lbam = 0x4f;
- tf->lbah = 0xc2;
- tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
- } else {
- tf->nsect = args[1];
- tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
- IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
- }
- tf->command = args[0];
- tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
-
- if (args[3]) {
- tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
- bufsize = SECTOR_WORDS * 4 * args[3];
- buf = kzalloc(bufsize, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
- }
-
- if (tf->command == WIN_SETFEATURES &&
- tf->feature == SETFEATURES_XFER &&
- tf->nsect >= XFER_SW_DMA_0 &&
- (id->dma_ultra || id->dma_mword || id->dma_1word)) {
- xfer_rate = args[1];
- if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
- printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
- "be set\n", drive->name);
- goto abort;
- }
- }
-
- err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
-
- args[0] = tf->status;
- args[1] = tf->error;
- args[2] = tf->nsect;
-
- if (!err && xfer_rate) {
- /* active-retuning-calls future */
- ide_set_xfer_rate(drive, xfer_rate);
- ide_driveid_update(drive);
- }
-abort:
- if (copy_to_user((void __user *)arg, &args, 4))
- err = -EFAULT;
- if (buf) {
- if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
- err = -EFAULT;
- kfree(buf);
- }
- return err;
-}
-
-int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
-{
- void __user *p = (void __user *)arg;
- int err = 0;
- u8 args[7];
- ide_task_t task;
-
- if (copy_from_user(args, p, 7))
- return -EFAULT;
-
- memset(&task, 0, sizeof(task));
- memcpy(&task.tf_array[7], &args[1], 6);
- task.tf.command = args[0];
- task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-
- err = ide_no_data_taskfile(drive, &task);
-
- args[0] = task.tf.command;
- memcpy(&args[1], &task.tf_array[7], 6);
-
- if (copy_to_user(p, args, 7))
- err = -EFAULT;
-
- return err;
-}
diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c
index 8c2f8327f48..81f527af8fa 100644
--- a/drivers/ide/ide-timings.c
+++ b/drivers/ide/ide-timings.c
@@ -22,7 +22,6 @@
*/
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/module.h>
@@ -78,15 +77,15 @@ EXPORT_SYMBOL_GPL(ide_timing_find_mode);
u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
u16 cycle = 0;
- if (id->field_valid & 2) {
- if (id->capability & 8)
- cycle = id->eide_pio_iordy;
+ if (id[ATA_ID_FIELD_VALID] & 2) {
+ if (ata_id_has_iordy(drive->id))
+ cycle = id[ATA_ID_EIDE_PIO_IORDY];
else
- cycle = id->eide_pio;
+ cycle = id[ATA_ID_EIDE_PIO];
/* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3 && cycle < t->cycle)
@@ -138,7 +137,7 @@ EXPORT_SYMBOL_GPL(ide_timing_merge);
int ide_timing_compute(ide_drive_t *drive, u8 speed,
struct ide_timing *t, int T, int UT)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
struct ide_timing *s, p;
/*
@@ -157,16 +156,15 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed,
* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing.
*/
- if (id && id->field_valid & 2) { /* EIDE drive */
-
+ if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
if (speed <= XFER_PIO_2)
- p.cycle = p.cyc8b = id->eide_pio;
+ p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
else if (speed <= XFER_PIO_5)
- p.cycle = p.cyc8b = id->eide_pio_iordy;
+ p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
- p.cycle = id->eide_dma_min;
+ p.cycle = id[ATA_ID_EIDE_DMA_MIN];
ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 772451600e4..04f8f13cb9d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -44,8 +44,6 @@
* inspiration from lots of linux users, esp. hamish@zot.apana.org.au
*/
-#define _IDE_C /* Tell ide.h it's really us */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
@@ -58,6 +56,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/completion.h>
#include <linux/device.h>
@@ -97,8 +96,6 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
hwif->name[2] = 'e';
hwif->name[3] = '0' + index;
- hwif->bus_state = BUSSTATE_ON;
-
init_completion(&hwif->gendev_rel_comp);
hwif->tp_ops = &default_tp_ops;
@@ -117,9 +114,9 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
memset(drive, 0, sizeof(*drive));
drive->media = ide_disk;
- drive->select.all = (unit<<4)|0xa0;
+ drive->select = (unit << 4) | ATA_DEVICE_OBS;
drive->hwif = hwif;
- drive->ready_stat = READY_STAT;
+ drive->ready_stat = ATA_DRDY;
drive->bad_wstat = BAD_W_STAT;
drive->special.b.recalibrate = 1;
drive->special.b.set_geometry = 1;
@@ -141,7 +138,7 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
for (i = 0; i < MAX_DRIVES; i++) {
ide_drive_t *drive = &hwif->drives[i];
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
spin_unlock_irq(&ide_lock);
device_unregister(&drive->gendev);
wait_for_completion(&drive->gendev_rel_comp);
@@ -230,8 +227,7 @@ void ide_unregister(ide_hwif_t *hwif)
kfree(hwif->sg_table);
unregister_blkdev(hwif->major, hwif->name);
- if (hwif->dma_base)
- ide_release_dma_engine(hwif);
+ ide_release_dma_engine(hwif);
mutex_unlock(&ide_cfg_mtx);
}
@@ -253,96 +249,52 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_mtx);
-
-/**
- * ide_spin_wait_hwgroup - wait for group
- * @drive: drive in the group
- *
- * Wait for an IDE device group to go non busy and then return
- * holding the ide_lock which guards the hwgroup->busy status
- * and right to use it.
- */
-
-int ide_spin_wait_hwgroup (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- unsigned long timeout = jiffies + (3 * HZ);
-
- spin_lock_irq(&ide_lock);
+ide_devset_get(io_32bit, io_32bit);
- while (hwgroup->busy) {
- unsigned long lflags;
- spin_unlock_irq(&ide_lock);
- local_irq_set(lflags);
- if (time_after(jiffies, timeout)) {
- local_irq_restore(lflags);
- printk(KERN_ERR "%s: channel busy\n", drive->name);
- return -EBUSY;
- }
- local_irq_restore(lflags);
- spin_lock_irq(&ide_lock);
- }
- return 0;
-}
-
-EXPORT_SYMBOL(ide_spin_wait_hwgroup);
-
-int set_io_32bit(ide_drive_t *drive, int arg)
+static int set_io_32bit(ide_drive_t *drive, int arg)
{
- if (drive->no_io_32bit)
+ if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
return -EPERM;
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
drive->io_32bit = arg;
- spin_unlock_irq(&ide_lock);
-
return 0;
}
+ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
+
static int set_ksettings(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->keep_settings = arg;
- spin_unlock_irq(&ide_lock);
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
return 0;
}
-int set_using_dma(ide_drive_t *drive, int arg)
+ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
+
+static int set_using_dma(ide_drive_t *drive, int arg)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
- ide_hwif_t *hwif = drive->hwif;
int err = -EPERM;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (!drive->id || !(drive->id->capability & 1))
+ if (ata_id_has_dma(drive->id) == 0)
goto out;
- if (hwif->dma_ops == NULL)
+ if (drive->hwif->dma_ops == NULL)
goto out;
- err = -EBUSY;
- if (ide_spin_wait_hwgroup(drive))
- goto out;
- /*
- * set ->busy flag, unlock and let it ride
- */
- hwif->hwgroup->busy = 1;
- spin_unlock_irq(&ide_lock);
-
err = 0;
if (arg) {
@@ -351,12 +303,6 @@ int set_using_dma(ide_drive_t *drive, int arg)
} else
ide_dma_off(drive);
- /*
- * lock, clear ->busy flag and unlock before leaving
- */
- spin_lock_irq(&ide_lock);
- hwif->hwgroup->busy = 0;
- spin_unlock_irq(&ide_lock);
out:
return err;
#else
@@ -367,9 +313,32 @@ out:
#endif
}
-int set_pio_mode(ide_drive_t *drive, int arg)
+/*
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
+ */
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
+{
+ switch (req_pio) {
+ case 202:
+ case 201:
+ case 200:
+ case 102:
+ case 101:
+ case 100:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
+ case 9:
+ case 8:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
+ case 7:
+ case 6:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+static int set_pio_mode(ide_drive_t *drive, int arg)
{
- struct request *rq;
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
@@ -380,48 +349,65 @@ int set_pio_mode(ide_drive_t *drive, int arg)
(hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
return -ENOSYS;
- if (drive->special.b.set_tune)
- return -EBUSY;
+ if (set_pio_mode_abuse(drive->hwif, arg)) {
+ if (arg == 8 || arg == 9) {
+ unsigned long flags;
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
+ spin_lock_irqsave(&ide_lock, flags);
+ port_ops->set_pio_mode(drive, arg);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else
+ port_ops->set_pio_mode(drive, arg);
+ } else {
+ int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
- drive->tune_req = (u8) arg;
- drive->special.b.set_tune = 1;
+ ide_set_pio(drive, arg);
- blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
+ if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+ if (keep_dma)
+ ide_dma_on(drive);
+ }
+ }
return 0;
}
+ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
+
static int set_unmaskirq(ide_drive_t *drive, int arg)
{
- if (drive->no_unmask)
+ if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
return -EPERM;
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->unmask = arg;
- spin_unlock_irq(&ide_lock);
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
return 0;
}
+ide_ext_devset_rw_sync(io_32bit, io_32bit);
+ide_ext_devset_rw_sync(keepsettings, ksettings);
+ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
+ide_ext_devset_rw_sync(using_dma, using_dma);
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
+
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
{
- ide_drive_t *drive = dev->driver_data;
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = HWIF(drive);
struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
int ret;
- /* Call ACPI _GTM only once */
- if (!(drive->dn % 2))
+ /* call ACPI _GTM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL)
ide_acpi_get_timing(hwif);
memset(&rqpm, 0, sizeof(rqpm));
@@ -430,33 +416,32 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
rq->special = &args;
rq->data = &rqpm;
- rqpm.pm_step = ide_pm_state_start_suspend;
+ rqpm.pm_step = IDE_PM_START_SUSPEND;
if (mesg.event == PM_EVENT_PRETHAW)
mesg.event = PM_EVENT_FREEZE;
rqpm.pm_state = mesg.event;
ret = blk_execute_rq(drive->queue, NULL, rq, 0);
blk_put_request(rq);
- /* only call ACPI _PS3 after both drivers are suspended */
- if (!ret && (((drive->dn % 2) && hwif->drives[0].present
- && hwif->drives[1].present)
- || !hwif->drives[0].present
- || !hwif->drives[1].present))
+
+ /* call ACPI _PS3 only after both devices are suspended */
+ if (ret == 0 && ((drive->dn & 1) || pair == NULL))
ide_acpi_set_state(hwif, 0);
+
return ret;
}
static int generic_ide_resume(struct device *dev)
{
- ide_drive_t *drive = dev->driver_data;
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
ide_hwif_t *hwif = HWIF(drive);
struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
int err;
- /* Call ACPI _STM only once */
- if (!(drive->dn % 2)) {
+ /* call ACPI _PS0 / _STM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL) {
ide_acpi_set_state(hwif, 1);
ide_acpi_push_timing(hwif);
}
@@ -470,7 +455,7 @@ static int generic_ide_resume(struct device *dev)
rq->cmd_flags |= REQ_PREEMPT;
rq->special = &args;
rq->data = &rqpm;
- rqpm.pm_step = ide_pm_state_start_resume;
+ rqpm.pm_step = IDE_PM_START_RESUME;
rqpm.pm_state = PM_EVENT_ON;
err = blk_execute_rq(drive->queue, NULL, rq, 1);
@@ -486,138 +471,6 @@ static int generic_ide_resume(struct device *dev)
return err;
}
-static int generic_drive_reset(ide_drive_t *drive)
-{
- struct request *rq;
- int ret = 0;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_len = 1;
- rq->cmd[0] = REQ_DRIVE_RESET;
- rq->cmd_flags |= REQ_SOFTBARRIER;
- if (blk_execute_rq(drive->queue, NULL, rq, 1))
- ret = rq->errors;
- blk_put_request(rq);
- return ret;
-}
-
-int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
- unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- ide_driver_t *drv;
- void __user *p = (void __user *)arg;
- int err = 0, (*setfunc)(ide_drive_t *, int);
- u8 *val;
-
- switch (cmd) {
- case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
- case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
- case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val;
- case HDIO_GET_DMA: val = &drive->using_dma; goto read_val;
- case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
- case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
- case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
- case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val;
- case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val;
- }
-
- switch (cmd) {
- case HDIO_OBSOLETE_IDENTITY:
- case HDIO_GET_IDENTITY:
- if (bdev != bdev->bd_contains)
- return -EINVAL;
- if (drive->id_read == 0)
- return -ENOMSG;
- if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
- return -EFAULT;
- return 0;
-
- case HDIO_GET_NICE:
- return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
- drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP |
- drive->nice1 << IDE_NICE_1,
- (long __user *) arg);
-#ifdef CONFIG_IDE_TASK_IOCTL
- case HDIO_DRIVE_TASKFILE:
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- switch(drive->media) {
- case ide_disk:
- return ide_taskfile_ioctl(drive, cmd, arg);
- default:
- return -ENOMSG;
- }
-#endif /* CONFIG_IDE_TASK_IOCTL */
-
- case HDIO_DRIVE_CMD:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_cmd_ioctl(drive, cmd, arg);
-
- case HDIO_DRIVE_TASK:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_task_ioctl(drive, cmd, arg);
- case HDIO_SET_NICE:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
- return -EPERM;
- drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
- drv = *(ide_driver_t **)bdev->bd_disk->private_data;
- if (drive->dsc_overlap && !drv->supports_dsc_overlap) {
- drive->dsc_overlap = 0;
- return -EPERM;
- }
- drive->nice1 = (arg >> IDE_NICE_1) & 1;
- return 0;
- case HDIO_DRIVE_RESET:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- return generic_drive_reset(drive);
-
- case HDIO_GET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (put_user(HWIF(drive)->bus_state, (long __user *)arg))
- return -EFAULT;
- return 0;
-
- case HDIO_SET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return -EOPNOTSUPP;
- default:
- return -EINVAL;
- }
-
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = *val;
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
-}
-
-EXPORT_SYMBOL(generic_ide_ioctl);
-
/**
* ide_device_get - get an additional reference to a ide_drive_t
* @drive: device to get a reference to
@@ -710,21 +563,21 @@ static ssize_t model_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", drive->id->model);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
}
static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", drive->id->fw_rev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
}
static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", drive->id->serial_no);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
}
static struct device_attribute ide_dev_attrs[] = {
@@ -734,6 +587,7 @@ static struct device_attribute ide_dev_attrs[] = {
__ATTR_RO(model),
__ATTR_RO(firmware),
__ATTR(serial, 0400, serial_show, NULL),
+ __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
__ATTR_NULL
};
@@ -841,7 +695,7 @@ MODULE_PARM_DESC(noprobe, "skip probing for a device");
static unsigned int ide_nowerr;
module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0);
-MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device");
+MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device");
static unsigned int ide_cdroms;
@@ -888,31 +742,31 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
-static void ide_dev_apply_params(ide_drive_t *drive)
+static void ide_dev_apply_params(ide_drive_t *drive, u8 unit)
{
- int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
+ int i = drive->hwif->index * MAX_DRIVES + unit;
if (ide_nodma & (1 << i)) {
printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
- drive->nodma = 1;
+ drive->dev_flags |= IDE_DFLAG_NODMA;
}
if (ide_noflush & (1 << i)) {
printk(KERN_INFO "ide: disabling flush requests for %s\n",
drive->name);
- drive->noflush = 1;
+ drive->dev_flags |= IDE_DFLAG_NOFLUSH;
}
if (ide_noprobe & (1 << i)) {
printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
- drive->noprobe = 1;
+ drive->dev_flags |= IDE_DFLAG_NOPROBE;
}
if (ide_nowerr & (1 << i)) {
- printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n",
+ printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n",
drive->name);
drive->bad_wstat = BAD_R_STAT;
}
if (ide_cdroms & (1 << i)) {
printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
- drive->present = 1;
+ drive->dev_flags |= IDE_DFLAG_PRESENT;
drive->media = ide_cdrom;
/* an ATAPI device ignores DRDY */
drive->ready_stat = 0;
@@ -921,13 +775,14 @@ static void ide_dev_apply_params(ide_drive_t *drive)
drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl;
drive->head = drive->bios_head = ide_disks_chs[i].head;
drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
- drive->forced_geom = 1;
+
printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
drive->name,
drive->cyl, drive->head, drive->sect);
- drive->present = 1;
+
+ drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT;
drive->media = ide_disk;
- drive->ready_stat = READY_STAT;
+ drive->ready_stat = ATA_DRDY;
}
}
@@ -965,7 +820,7 @@ void ide_port_apply_params(ide_hwif_t *hwif)
}
for (i = 0; i < MAX_DRIVES; i++)
- ide_dev_apply_params(&hwif->drives[i]);
+ ide_dev_apply_params(&hwif->drives[i], i);
}
/*
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 4ec19737f3c..90da1f953ed 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -43,7 +43,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -132,7 +131,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->name, pio, time1, time2, param1, param2, param3, param4);
/* stuff timing parameters into controller registers */
- driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+ driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
spin_lock_irqsave(&ali14xx_lock, flags);
outb_p(regOn, basePort);
outReg(param1, regTab[driveNum].reg1);
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 7c2afa97f41..c5a3c9ef6a5 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -20,7 +20,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/zorro.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
index af791a02a12..689b2e49341 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/legacy/dtc2278.c
@@ -10,7 +10,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 724f95073d8..39d500d84b0 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -13,7 +13,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 51ba085d7aa..69150688656 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -12,7 +12,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/zorro.h>
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 98f7c95e39e..c7e5c2246b7 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -24,7 +24,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -121,7 +120,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
* Need to enforce prefetch sometimes because otherwise
* it'll hang (hard).
*/
- if (drive->media != ide_disk || !drive->present)
+ if (drive->media != ide_disk ||
+ (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
select |= HT_PREFETCH_MODE;
if (select != current_select || timing != current_timing) {
@@ -250,11 +250,11 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
*/
if (state) {
drive->drive_data |= t; /* enable prefetch mode */
- drive->no_unmask = 1;
- drive->unmask = 0;
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
} else {
drive->drive_data &= ~t; /* disable prefetch mode */
- drive->no_unmask = 0;
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
}
spin_unlock_irqrestore(&ht6560b_lock, flags);
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
index c76d55de699..9e85b1ec960 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/legacy/ide-4drives.c
@@ -14,7 +14,7 @@ MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
static void ide_4drives_init_dev(ide_drive_t *drive)
{
if (drive->hwif->channel)
- drive->select.all ^= 0x20;
+ drive->select ^= 0x20;
}
static const struct ide_port_ops ide_4drives_port_ops = {
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 21bfac13784..cb199c815b5 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -38,7 +38,6 @@
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/ide.h>
-#include <linux/hdreg.h>
#include <linux/major.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -220,103 +219,91 @@ out_release:
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+struct pcmcia_config_check {
+ unsigned long ctl_base;
+ int skip_vcc;
+ int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ struct pcmcia_config_check *stk = priv_data;
+
+ /* Check for matching Vcc, unless we're desperate */
+ if (!stk->skip_vcc) {
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ pdev->conf.ConfigIndex = cfg->index;
+ pdev->io.BasePort1 = io->win[0].base;
+ pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ if (io->nwin == 2) {
+ pdev->io.NumPorts1 = 8;
+ pdev->io.BasePort2 = io->win[1].base;
+ pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort2;
+ } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+ pdev->io.NumPorts1 = io->win[0].len;
+ pdev->io.NumPorts2 = 0;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+ } else
+ return -ENODEV;
+ /* If we've got this far, we're done */
+ return 0;
+ }
+ return -ENODEV;
+}
+
static int ide_config(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- tuple_t tuple;
- struct {
- u_short buf[128];
- cisparse_t parse;
- config_info_t conf;
- cistpl_cftable_entry_t dflt;
- } *stk = NULL;
- cistpl_cftable_entry_t *cfg;
- int pass, last_ret = 0, last_fn = 0, is_kme = 0;
+ struct pcmcia_config_check *stk = NULL;
+ int last_ret = 0, last_fn = 0, is_kme = 0;
unsigned long io_base, ctl_base;
struct ide_host *host;
DEBUG(0, "ide_config(0x%p)\n", link);
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk) goto err_mem;
- cfg = &stk->parse.cftable_entry;
-
- tuple.TupleData = (cisdata_t *)&stk->buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
-
is_kme = ((link->manf_id == MANFID_KME) &&
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
-
- pass = io_base = ctl_base = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
- if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
-
- /* Check for matching Vcc, unless we're desperate */
- if (!pass) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
- link->conf.ConfigIndex = cfg->index;
- link->io.BasePort1 = io->win[0].base;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- if (io->nwin == 2) {
- link->io.NumPorts1 = 8;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort2;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- link->io.NumPorts1 = io->win[0].len;
- link->io.NumPorts2 = 0;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort1 + 0x0e;
- } else goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
-
- next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
- if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- memset(&stk->dflt, 0, sizeof(stk->dflt));
- pass++;
- }
+ stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+ if (!stk)
+ goto err_mem;
+ stk->is_kme = is_kme;
+ stk->skip_vcc = io_base = ctl_base = 0;
+
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+ stk->skip_vcc = 1;
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+ goto failed; /* No suitable config found */
}
+ io_base = link->io.BasePort1;
+ ctl_base = stk->ctl_base;
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@@ -404,8 +391,10 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
+ PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index a0bb167980e..43f97cc1d30 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -15,7 +15,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/ide.h>
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 4abd8fc7819..4af4a8ce4cd 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -14,8 +14,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
#include <linux/ide.h>
/*
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index 2338f344ea2..bc27c7aba93 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -27,7 +27,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/system.h>
@@ -151,12 +150,14 @@ static int qd_find_disk_type (ide_drive_t *drive,
int *active_time, int *recovery_time)
{
struct qd65xx_timing_s *p;
- char model[40];
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+ char model[ATA_ID_PROD_LEN];
- if (!*drive->id->model) return 0;
+ if (*m == 0)
+ return 0;
- strncpy(model,drive->id->model,40);
- ide_fixstring(model,40,1); /* byte-swap */
+ strncpy(model, m, ATA_ID_PROD_LEN);
+ ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */
for (p = qd65xx_timing ; p->offset != -1 ; p++) {
if (!strncmp(p->model, model+p->offset, 4)) {
@@ -185,20 +186,20 @@ static void qd_set_timing (ide_drive_t *drive, u8 timing)
static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
+ u16 *id = drive->id;
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
/*
* FIXME: use "pio" value
*/
- if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)
- && drive->id->tPIO && (drive->id->field_valid & 0x02)
- && drive->id->eide_pio >= 240) {
-
+ if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
+ (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
+ id[ATA_ID_EIDE_PIO] >= 240) {
printk(KERN_INFO "%s: PIO mode%d\n", drive->name,
- drive->id->tPIO);
+ id[ATA_ID_OLD_PIO_MODES] & 0xff);
active_time = 110;
- recovery_time = drive->id->eide_pio - 120;
+ recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
}
qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
@@ -304,7 +305,7 @@ static void __init qd6580_init_dev(ide_drive_t *drive)
} else
t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
- drive->drive_data = drive->select.b.unit ? t2 : t1;
+ drive->drive_data = (drive->dn & 1) ? t2 : t1;
}
static const struct ide_port_ops qd6500_port_ops = {
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
index b54a14a5775..1da076e0c91 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/legacy/umc8672.c
@@ -45,7 +45,6 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
index 677c7b2bac9..5873fa0b876 100644
--- a/drivers/ide/mips/Makefile
+++ b/drivers/ide/mips/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o
obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 11b7f61aae4..0ec8fd1e4dc 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -322,11 +322,7 @@ static int auide_dma_setup(ide_drive_t *drive)
}
static int auide_dma_test_irq(ide_drive_t *drive)
-{
- if (drive->waiting_for_dma == 0)
- printk(KERN_WARNING "%s: ide_dma_test_irq \
- called while not waiting\n", drive->name);
-
+{
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set
*/
@@ -344,11 +340,6 @@ static void auide_dma_host_set(ide_drive_t *drive, int on)
{
}
-static void auide_dma_lost_irq(ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
static void auide_ddma_tx_callback(int irq, void *param)
{
_auide_hwif *ahwif = (_auide_hwif*)param;
@@ -375,18 +366,6 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
}
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static void auide_dma_timeout(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
-
- printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
- if (auide_dma_test_irq(drive))
- return;
-
- auide_dma_end(drive);
-}
-
static const struct ide_dma_ops au1xxx_dma_ops = {
.dma_host_set = auide_dma_host_set,
.dma_setup = auide_dma_setup,
@@ -394,8 +373,8 @@ static const struct ide_dma_ops au1xxx_dma_ops = {
.dma_start = auide_dma_start,
.dma_end = auide_dma_end,
.dma_test_irq = auide_dma_test_irq,
- .dma_lost_irq = auide_dma_lost_irq,
- .dma_timeout = auide_dma_timeout,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
};
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
@@ -448,10 +427,9 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
NUM_DESCRIPTORS);
auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
NUM_DESCRIPTORS);
-
- hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
- PRD_ENTRIES * PRD_BYTES, /* 1 Page */
- &hwif->dmatable_dma, GFP_KERNEL);
+
+ /* FIXME: check return value */
+ (void)ide_allocate_dma_engine(hwif);
au1xxx_dbdma_start( auide->tx_chan );
au1xxx_dbdma_start( auide->rx_chan );
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
deleted file mode 100644
index badf79fc9e3..00000000000
--- a/drivers/ide/mips/swarm.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
- * Author: Maciej W. Rozycki <macro@mips.com>
- * Copyright (c) 2006, 2008 Maciej W. Rozycki
- *
- * 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.
- */
-
-/*
- * Derived loosely from ide-pmac.c, so:
- * Copyright (C) 1998 Paul Mackerras.
- * Copyright (C) 1995-1998 Mark Lord
- */
-
-/*
- * Boards with SiByte processors so far have supported IDE devices via
- * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all
- * cases, byte-swapping must be avoided for these devices (whereas
- * other PCI devices, for example, will require swapping). Any
- * SiByte-targetted kernel including IDE support will include this
- * file. Probing of a Generic Bus for an IDE device is controlled by
- * the definition of "SIBYTE_HAVE_IDE", which is provided by
- * <asm/sibyte/board.h> for Broadcom boards.
- */
-
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-
-#include <asm/io.h>
-
-#include <asm/sibyte/board.h>
-#include <asm/sibyte/sb1250_genbus.h>
-#include <asm/sibyte/sb1250_regs.h>
-
-#define DRV_NAME "ide-swarm"
-
-static char swarm_ide_string[] = DRV_NAME;
-
-static struct resource swarm_ide_resource = {
- .name = "SWARM GenBus IDE",
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device *swarm_ide_dev;
-
-static const struct ide_port_info swarm_port_info = {
- .name = DRV_NAME,
- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
-};
-
-/*
- * swarm_ide_probe - if the board header indicates the existence of
- * Generic Bus IDE, allocate a HWIF for it.
- */
-static int __devinit swarm_ide_probe(struct device *dev)
-{
- u8 __iomem *base;
- struct ide_host *host;
- phys_t offset, size;
- int i, rc;
- hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
- if (!SIBYTE_HAVE_IDE)
- return -ENODEV;
-
- base = ioremap(A_IO_EXT_BASE, 0x800);
- offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
- size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
- iounmap(base);
-
- offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
- size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
- if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
- printk(KERN_INFO DRV_NAME
- ": IDE interface at GenBus disabled\n");
- return -EBUSY;
- }
-
- printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n",
- IDE_CS);
-
- swarm_ide_resource.start = offset;
- swarm_ide_resource.end = offset + size - 1;
- if (request_resource(&iomem_resource, &swarm_ide_resource)) {
- printk(KERN_ERR DRV_NAME
- ": can't request I/O memory resource\n");
- return -EBUSY;
- }
-
- base = ioremap(offset, size);
-
- for (i = 0; i <= 7; i++)
- hw.io_ports_array[i] =
- (unsigned long)(base + ((0x1f0 + i) << 5));
- hw.io_ports.ctl_addr =
- (unsigned long)(base + (0x3f6 << 5));
- hw.irq = K_INT_GB_IDE;
- hw.chipset = ide_generic;
-
- rc = ide_host_add(&swarm_port_info, hws, &host);
- if (rc)
- goto err;
-
- dev_set_drvdata(dev, host);
-
- return 0;
-err:
- release_resource(&swarm_ide_resource);
- iounmap(base);
- return rc;
-}
-
-static struct device_driver swarm_ide_driver = {
- .name = swarm_ide_string,
- .bus = &platform_bus_type,
- .probe = swarm_ide_probe,
-};
-
-static void swarm_ide_platform_release(struct device *device)
-{
- struct platform_device *pldev;
-
- /* free device */
- pldev = to_platform_device(device);
- kfree(pldev);
-}
-
-static int __devinit swarm_ide_init_module(void)
-{
- struct platform_device *pldev;
- int err;
-
- printk(KERN_INFO "SWARM IDE driver\n");
-
- if (driver_register(&swarm_ide_driver)) {
- printk(KERN_ERR "Driver registration failed\n");
- err = -ENODEV;
- goto out;
- }
-
- if (!(pldev = kzalloc(sizeof (*pldev), GFP_KERNEL))) {
- err = -ENOMEM;
- goto out_unregister_driver;
- }
-
- pldev->name = swarm_ide_string;
- pldev->id = 0;
- pldev->dev.release = swarm_ide_platform_release;
-
- if (platform_device_register(pldev)) {
- err = -ENODEV;
- goto out_free_pldev;
- }
-
- if (!pldev->dev.driver) {
- /*
- * The driver was not bound to this device, there was
- * no hardware at this address. Unregister it, as the
- * release fuction will take care of freeing the
- * allocated structure
- */
- platform_device_unregister (pldev);
- }
-
- swarm_ide_dev = pldev;
-
- return 0;
-
-out_free_pldev:
- kfree(pldev);
-
-out_unregister_driver:
- driver_unregister(&swarm_ide_driver);
-out:
- return err;
-}
-
-module_init(swarm_ide_init_module);
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 3187215e8f8..4142c698e0d 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -7,7 +7,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -116,7 +115,7 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
- u8 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 tmp1 = 0, tmp2 = 0;
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
unsigned long flags;
@@ -140,7 +139,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
}
-static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev)
+static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
{
/* These are necessary to get AEC6280 Macintosh cards to work */
if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
@@ -303,21 +302,23 @@ static const struct pci_device_id aec62xx_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver aec62xx_pci_driver = {
.name = "AEC62xx_IDE",
.id_table = aec62xx_pci_tbl,
.probe = aec62xx_init_one,
.remove = __devexit_p(aec62xx_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init aec62xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&aec62xx_pci_driver);
}
static void __exit aec62xx_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&aec62xx_pci_driver);
}
module_init(aec62xx_ide_init);
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index d647526af55..daf9dce39e5 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -31,7 +31,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/dmi.h>
@@ -78,8 +77,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
int port = hwif->channel ? 0x5c : 0x58;
int portFIFO = hwif->channel ? 0x55 : 0x54;
- u8 cd_dma_fifo = 0;
- int unit = drive->select.b.unit & 1;
+ u8 cd_dma_fifo = 0, unit = drive->dn & 1;
if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
s_clc = 0;
@@ -113,7 +111,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
pci_write_config_byte(dev, port, s_clc);
- pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
+ pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
local_irq_restore(flags);
}
@@ -134,8 +132,8 @@ static u8 ali_udma_filter(ide_drive_t *drive)
if (m5229_revision > 0x20 && m5229_revision < 0xC2) {
if (drive->media != ide_disk)
return 0;
- if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") &&
- wdc_udma == 0)
+ if (wdc_udma == 0 && chip_is_1543c_e &&
+ strstr((char *)&drive->id[ATA_ID_PROD], "WDC "))
return 0;
}
@@ -155,7 +153,7 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 speed1 = speed;
- u8 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 tmpbyte = 0x00;
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
@@ -214,7 +212,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive)
* appropriate also sets up the 1533 southbridge.
*/
-static unsigned int __devinit init_chipset_ali15x3(struct pci_dev *dev)
+static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
{
unsigned long flags;
u8 tmpbyte;
@@ -509,7 +507,7 @@ static const struct ide_dma_ops ali_dma_ops = {
.dma_setup = ali15x3_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
@@ -577,21 +575,23 @@ static const struct pci_device_id alim15x3_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver alim15x3_pci_driver = {
.name = "ALI15x3_IDE",
.id_table = alim15x3_pci_tbl,
.probe = alim15x3_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init ali15x3_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&alim15x3_pci_driver);
}
static void __exit ali15x3_ide_exit(void)
{
- return pci_unregister_driver(&driver);
+ return pci_unregister_driver(&alim15x3_pci_driver);
}
module_init(ali15x3_ide_init);
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 1e66a960a96..81ec73134ed 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_compute(drive, speed, &t, T, UT);
- if (peer->present) {
+ if (peer->dev_flags & IDE_DFLAG_PRESENT) {
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
@@ -112,13 +112,13 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
-static void __devinit amd7409_cable_detect(struct pci_dev *dev)
+static void amd7409_cable_detect(struct pci_dev *dev)
{
/* no host side cable detection */
amd_80w = 0x03;
}
-static void __devinit amd7411_cable_detect(struct pci_dev *dev)
+static void amd7411_cable_detect(struct pci_dev *dev)
{
int i;
u32 u = 0;
@@ -140,7 +140,7 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev)
* The initialization callback. Initialize drive independent registers.
*/
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev)
+static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
{
u8 t = 0, offset = amd_offset(dev);
@@ -319,21 +319,23 @@ static const struct pci_device_id amd74xx_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver amd74xx_pci_driver = {
.name = "AMD_IDE",
.id_table = amd74xx_pci_tbl,
.probe = amd74xx_probe,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init amd74xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&amd74xx_pci_driver);
}
static void __exit amd74xx_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&amd74xx_pci_driver);
}
module_init(amd74xx_ide_init);
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 41f6cb6c163..b2735d28f5c 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -7,7 +7,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -183,21 +182,23 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver atiixp_pci_driver = {
.name = "ATIIXP_IDE",
.id_table = atiixp_pci_tbl,
.probe = atiixp_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init atiixp_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&atiixp_pci_driver);
}
static void __exit atiixp_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&atiixp_pci_driver);
}
module_init(atiixp_ide_init);
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index e6c62006ca1..e4306647d00 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -103,7 +103,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -375,6 +374,21 @@ static void cmd640_dump_regs(void)
}
#endif
+static void __set_prefetch_mode(ide_drive_t *drive, int mode)
+{
+ if (mode) { /* want prefetch on? */
+#if CMD640_PREFETCH_MASKS
+ drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+#endif
+ drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
+ } else {
+ drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
+ drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
+ drive->io_32bit = 0;
+ }
+}
+
#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
/*
* Check whether prefetch is on for a drive,
@@ -384,19 +398,10 @@ static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
{
u8 b = get_cmd640_reg(prefetch_regs[index]);
- if (b & prefetch_masks[index]) { /* is prefetch off? */
- drive->no_unmask = 0;
- drive->no_io_32bit = 1;
- drive->io_32bit = 0;
- } else {
-#if CMD640_PREFETCH_MASKS
- drive->no_unmask = 1;
- drive->unmask = 0;
-#endif
- drive->no_io_32bit = 0;
- }
+ __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1);
}
#else
+
/*
* Sets prefetch mode for a drive.
*/
@@ -408,19 +413,11 @@ static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
spin_lock_irqsave(&cmd640_lock, flags);
b = __get_cmd640_reg(reg);
- if (mode) { /* want prefetch on? */
-#if CMD640_PREFETCH_MASKS
- drive->no_unmask = 1;
- drive->unmask = 0;
-#endif
- drive->no_io_32bit = 0;
+ __set_prefetch_mode(drive, mode);
+ if (mode)
b &= ~prefetch_masks[index]; /* enable prefetch */
- } else {
- drive->no_unmask = 0;
- drive->no_io_32bit = 1;
- drive->io_32bit = 0;
+ else
b |= prefetch_masks[index]; /* disable prefetch */
- }
__put_cmd640_reg(reg, b);
spin_unlock_irqrestore(&cmd640_lock, flags);
}
@@ -471,10 +468,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
*/
if (index > 1) {
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
+ ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
unsigned int mate = index ^ 1;
- if (peer->present) {
+ if (peer->dev_flags & IDE_DFLAG_PRESENT) {
if (setup_count < setup_counts[mate])
setup_count = setup_counts[mate];
if (active_count < active_counts[mate])
@@ -610,7 +607,7 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void cmd640_init_dev(ide_drive_t *drive)
{
- unsigned int i = drive->hwif->channel * 2 + drive->select.b.unit;
+ unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
/*
@@ -629,7 +626,7 @@ static void cmd640_init_dev(ide_drive_t *drive)
*/
check_prefetch(drive, i);
printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
- i, drive->no_io_32bit ? "off" : "on");
+ i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
}
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index e064398e03b..935385c77e0 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -229,7 +228,7 @@ static int cmd648_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long base = hwif->dma_base - (hwif->channel * 8);
- int err = __ide_dma_end(drive);
+ int err = ide_dma_end(drive);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
u8 mrdmode = inb(base + 1);
@@ -249,7 +248,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
u8 irq_stat = 0;
- int err = __ide_dma_end(drive);
+ int err = ide_dma_end(drive);
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
/* clear the interrupt bit */
@@ -332,7 +331,7 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
return (dma_stat & 7) != 4;
}
-static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev)
+static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
{
u8 mrdmode = 0;
@@ -506,21 +505,23 @@ static const struct pci_device_id cmd64x_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cmd64x_pci_driver = {
.name = "CMD64x_IDE",
.id_table = cmd64x_pci_tbl,
.probe = cmd64x_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cmd64x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cmd64x_pci_driver);
}
static void __exit cmd64x_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&cmd64x_pci_driver);
}
module_init(cmd64x_ide_init);
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 151844fcbb0..5efb467f8fa 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -35,7 +35,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
@@ -146,15 +145,17 @@ static const struct pci_device_id cs5520_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cs5520_pci_driver = {
.name = "Cyrix_IDE",
.id_table = cs5520_pci_tbl,
.probe = cs5520_init_one,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5520_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5520_pci_driver);
}
module_init(cs5520_ide_init);
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index f235db8c678..53f079cc00a 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -81,17 +80,19 @@ static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
static u8 cs5530_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
- struct hd_driveid *mateid = mate->id;
+ ide_drive_t *mate = ide_get_pair_dev(drive);
+ u16 *mateid = mate->id;
u8 mask = hwif->ultra_mask;
- if (mate->present == 0)
+ if (mate == NULL)
goto out;
- if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
- if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+ (mateid[ATA_ID_UDMA_MODES] & 7))
goto out;
- if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+ (mateid[ATA_ID_MWDMA_MODES] & 7))
mask = 0;
}
out:
@@ -133,7 +134,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
-static unsigned int __devinit init_chipset_cs5530(struct pci_dev *dev)
+static unsigned int init_chipset_cs5530(struct pci_dev *dev)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
@@ -266,21 +267,23 @@ static const struct pci_device_id cs5530_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cs5530_pci_driver = {
.name = "CS5530 IDE",
.id_table = cs5530_pci_tbl,
.probe = cs5530_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5530_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5530_pci_driver);
}
static void __exit cs5530_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&cs5530_pci_driver);
}
module_init(cs5530_ide_init);
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index dd3dc23af99..983d957a018 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -76,16 +76,16 @@ static unsigned int cs5535_udma_timings[5] =
static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
{
u32 reg = 0, dummy;
- int unit = drive->select.b.unit;
+ u8 unit = drive->dn & 1;
/* Set the PIO timings */
if (speed < XFER_SW_DMA_0) {
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
u8 cmd, pioa;
cmd = pioa = speed - XFER_PIO_0;
- if (pair->present) {
+ if (pair) {
u8 piob = ide_get_best_pio_mode(pair, 255, 4);
if (piob < cmd)
@@ -192,21 +192,23 @@ static const struct pci_device_id cs5535_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
-static struct pci_driver driver = {
- .name = "CS5535_IDE",
- .id_table = cs5535_pci_tbl,
- .probe = cs5535_init_one,
- .remove = ide_pci_remove,
+static struct pci_driver cs5535_pci_driver = {
+ .name = "CS5535_IDE",
+ .id_table = cs5535_pci_tbl,
+ .probe = cs5535_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cs5535_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cs5535_pci_driver);
}
static void __exit cs5535_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&cs5535_pci_driver);
}
module_init(cs5535_ide_init);
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index e6d8ee88d56..5297f07d293 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -50,18 +50,11 @@
#define DRV_NAME "cy82c693"
-/* the current version */
-#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
-
/*
* The following are used to debug the driver.
*/
-#define CY82C693_DEBUG_LOGS 0
#define CY82C693_DEBUG_INFO 0
-/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
-#undef CY82C693_SETDMA_CLOCK
-
/*
* NOTE: the value for busmaster timeout is tricky and I got it by
* trial and error! By using a to low value will cause DMA timeouts
@@ -89,7 +82,6 @@
#define CY82_INDEX_PORT 0x22
#define CY82_DATA_PORT 0x23
-#define CY82_INDEX_CTRLREG1 0x01
#define CY82_INDEX_CHANNEL0 0x30
#define CY82_INDEX_CHANNEL1 0x31
#define CY82_INDEX_TIMEOUT 0x32
@@ -179,17 +171,6 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
-#if CY82C693_DEBUG_LOGS
- /* for debug let's show the previous values */
-
- outb(index, CY82_INDEX_PORT);
- data = inb(CY82_DATA_PORT);
-
- printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
- drive->name, HWIF(drive)->channel, drive->select.b.unit,
- (data&0x3), ((data>>2)&1));
-#endif /* CY82C693_DEBUG_LOGS */
-
data = (mode & 3) | (single << 2);
outb(index, CY82_INDEX_PORT);
@@ -197,8 +178,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
#if CY82C693_DEBUG_INFO
printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
- drive->name, HWIF(drive)->channel, drive->select.b.unit,
- mode & 3, single);
+ drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
#endif /* CY82C693_DEBUG_INFO */
/*
@@ -239,50 +219,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
}
-#if CY82C693_DEBUG_LOGS
- /* for debug let's show the register values */
-
- if (drive->select.b.unit == 0) {
- /*
- * get master drive registers
- * address setup control register
- * is 32 bit !!!
- */
- pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
- addrCtrl &= 0x0F;
-
- /* now let's get the remaining registers */
- pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
- pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
- pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
- } else {
- /*
- * set slave drive registers
- * address setup control register
- * is 32 bit !!!
- */
- pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-
- addrCtrl &= 0xF0;
- addrCtrl >>= 4;
-
- /* now let's get the remaining registers */
- pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
- pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
- pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
- }
-
- printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is "
- "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
- drive->name, hwif->channel, drive->select.b.unit,
- addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
-#endif /* CY82C693_DEBUG_LOGS */
-
/* let's calc the values for this PIO mode */
compute_clocks(pio, &pclk);
/* now let's write the clocks registers */
- if (drive->select.b.unit == 0) {
+ if ((drive->dn & 1) == 0) {
/*
* set master drive
* address setup control register
@@ -324,63 +265,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
#if CY82C693_DEBUG_INFO
printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
"(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
- drive->name, hwif->channel, drive->select.b.unit,
+ drive->name, hwif->channel, drive->dn & 1,
addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
#endif /* CY82C693_DEBUG_INFO */
}
-/*
- * this function is called during init and is used to setup the cy82c693 chip
- */
-static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev)
-{
- if (PCI_FUNC(dev->devfn) != 1)
- return 0;
-
-#ifdef CY82C693_SETDMA_CLOCK
- u8 data = 0;
-#endif /* CY82C693_SETDMA_CLOCK */
-
- /* write info about this verion of the driver */
- printk(KERN_INFO CY82_VERSION "\n");
-
-#ifdef CY82C693_SETDMA_CLOCK
- /* okay let's set the DMA clock speed */
-
- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
- data = inb(CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
- printk(KERN_INFO DRV_NAME ": Peripheral Configuration Register: 0x%X\n",
- data);
-#endif /* CY82C693_DEBUG_INFO */
-
- /*
- * for some reason sometimes the DMA controller
- * speed is set to ATCLK/2 ???? - we fix this here
- *
- * note: i don't know what causes this strange behaviour,
- * but even changing the dma speed doesn't solve it :-(
- * the ide performance is still only half the normal speed
- *
- * if anybody knows what goes wrong with my machine, please
- * let me know - ASK
- */
-
- data |= 0x03;
-
- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
- outb(data, CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
- printk(KERN_INFO ": New Peripheral Configuration Register: 0x%X\n",
- data);
-#endif /* CY82C693_DEBUG_INFO */
-
-#endif /* CY82C693_SETDMA_CLOCK */
- return 0;
-}
-
static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
{
static ide_hwif_t *primary;
@@ -401,7 +290,6 @@ static const struct ide_port_ops cy82c693_port_ops = {
static const struct ide_port_info cy82c693_chipset __devinitdata = {
.name = DRV_NAME,
- .init_chipset = init_chipset_cy82c693,
.init_iops = init_iops_cy82c693,
.port_ops = &cy82c693_port_ops,
.chipset = ide_cy82c693,
@@ -443,21 +331,23 @@ static const struct pci_device_id cy82c693_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver cy82c693_pci_driver = {
.name = "Cypress_IDE",
.id_table = cy82c693_pci_tbl,
.probe = cy82c693_init_one,
.remove = __devexit_p(cy82c693_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init cy82c693_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&cy82c693_pci_driver);
}
static void __exit cy82c693_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&cy82c693_pci_driver);
}
module_init(cy82c693_ide_init);
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index f84bfb4f600..8689a706f53 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <linux/module.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -118,7 +117,7 @@ static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver delkin_cb_pci_driver = {
.name = "Delkin-ASKA-Workbit Cardbus IDE",
.id_table = delkin_cb_pci_tbl,
.probe = delkin_cb_probe,
@@ -127,12 +126,12 @@ static struct pci_driver driver = {
static int __init delkin_cb_init(void)
{
- return pci_register_driver(&driver);
+ return pci_register_driver(&delkin_cb_pci_driver);
}
static void __exit delkin_cb_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&delkin_cb_pci_driver);
}
module_init(delkin_cb_init);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index b07d4f4273b..474f96a7c07 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -22,7 +22,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -167,21 +166,23 @@ static const struct pci_device_id generic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver generic_pci_driver = {
.name = "PCI_IDE",
.id_table = generic_pci_tbl,
.probe = generic_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init generic_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&generic_pci_driver);
}
static void __exit generic_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&generic_pci_driver);
}
module_init(generic_ide_init);
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 6009b0b9655..fb1a3aa57f0 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -27,7 +27,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -79,7 +78,7 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
*/
#define HPT34X_PCI_INIT_REG 0x80
-static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev)
+static unsigned int init_chipset_hpt34x(struct pci_dev *dev)
{
int i = 0;
unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
@@ -167,21 +166,23 @@ static const struct pci_device_id hpt34x_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver hpt34x_pci_driver = {
.name = "HPT34x_IDE",
.id_table = hpt34x_pci_tbl,
.probe = hpt34x_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init hpt34x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&hpt34x_pci_driver);
}
static void __exit hpt34x_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&hpt34x_pci_driver);
}
module_init(hpt34x_ide_init);
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index eb107eef0db..9cf171cb937 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -122,7 +122,6 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -605,14 +604,22 @@ static const struct hpt_info hpt371n __devinitdata = {
static int check_in_drive_list(ide_drive_t *drive, const char **list)
{
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
while (*list)
- if (!strcmp(*list++,id->model))
+ if (!strcmp(*list++, m))
return 1;
return 0;
}
+static struct hpt_info *hpt3xx_get_info(struct device *dev)
+{
+ struct ide_host *host = dev_get_drvdata(dev);
+ struct hpt_info *info = (struct hpt_info *)host->host_priv;
+
+ return dev == host->dev[1] ? info + 1 : info;
+}
+
/*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
@@ -621,9 +628,7 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
u8 mask = hwif->ultra_mask;
switch (info->chip_type) {
@@ -649,7 +654,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
case HPT372A:
case HPT372N:
case HPT374 :
- if (ide_dev_is_sata(drive->id))
+ if (ata_id_is_sata(drive->id))
mask &= ~0x0e;
/* Fall thru */
default:
@@ -662,16 +667,14 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
switch (info->chip_type) {
case HPT372 :
case HPT372A:
case HPT372N:
case HPT374 :
- if (ide_dev_is_sata(drive->id))
+ if (ata_id_is_sata(drive->id))
return 0x00;
/* Fall thru */
default:
@@ -700,8 +703,7 @@ static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
struct hpt_timings *t = info->timings;
u8 itr_addr = 0x40 + (drive->dn * 4);
u32 old_itr = 0;
@@ -728,11 +730,11 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void hpt3xx_quirkproc(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
const char **list = quirk_drives;
while (*list)
- if (strstr(id->model, *list++)) {
+ if (strstr(m, *list++)) {
drive->quirk_list = 1;
return;
}
@@ -744,8 +746,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
if (drive->quirk_list) {
if (info->chip_type >= HPT370) {
@@ -834,7 +835,7 @@ static int hpt370_dma_end(ide_drive_t *drive)
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
}
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
static void hpt370_dma_timeout(ide_drive_t *drive)
@@ -862,9 +863,6 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
if (dma_stat & 4)
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
return 0;
}
@@ -879,7 +877,7 @@ static int hpt374_dma_end(ide_drive_t *drive)
pci_read_config_byte(dev, mcr_addr, &mcr);
if (bwsr & mask)
pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
/**
@@ -942,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
* Perform a calibration cycle on the DPLL.
* Returns 1 if this succeeds
*/
-static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
+static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
{
u32 dpll = (f_high << 16) | f_low | 0x100;
u8 scr2;
@@ -970,11 +968,40 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f
return 1;
}
-static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev)
+static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
{
- unsigned long io_base = pci_resource_start(dev, 4);
struct ide_host *host = pci_get_drvdata(dev);
struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]);
+ u8 chip_type = info->chip_type;
+ u8 new_mcr, old_mcr = 0;
+
+ /*
+ * Disable the "fast interrupt" prediction. Don't hold off
+ * on interrupts. (== 0x01 despite what the docs say)
+ */
+ pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
+
+ if (chip_type >= HPT374)
+ new_mcr = old_mcr & ~0x07;
+ else if (chip_type >= HPT370) {
+ new_mcr = old_mcr;
+ new_mcr &= ~0x02;
+#ifdef HPT_DELAY_INTERRUPT
+ new_mcr &= ~0x01;
+#else
+ new_mcr |= 0x01;
+#endif
+ } else /* HPT366 and HPT368 */
+ new_mcr = old_mcr & ~0x80;
+
+ if (new_mcr != old_mcr)
+ pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
+}
+
+static unsigned int init_chipset_hpt366(struct pci_dev *dev)
+{
+ unsigned long io_base = pci_resource_start(dev, 4);
+ struct hpt_info *info = hpt3xx_get_info(&dev->dev);
const char *name = DRV_NAME;
u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */
u8 chip_type;
@@ -1208,17 +1235,18 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev)
* NOTE: This register is only writeable via I/O space.
*/
if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
-
outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
+ hpt3xx_disable_fast_irq(dev, 0x50);
+ hpt3xx_disable_fast_irq(dev, 0x54);
+
return dev->irq;
}
static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
u8 chip_type = info->chip_type;
u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
@@ -1262,11 +1290,9 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct ide_host *host = pci_get_drvdata(dev);
- struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
+ struct hpt_info *info = hpt3xx_get_info(hwif->dev);
int serialize = HPT_SERIALIZE_IO;
u8 chip_type = info->chip_type;
- u8 new_mcr, old_mcr = 0;
/* Cache the channel's MISC. control registers' offset */
hwif->select_data = hwif->channel ? 0x54 : 0x50;
@@ -1289,29 +1315,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
/* Serialize access to this device if needed */
if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
-
- /*
- * Disable the "fast interrupt" prediction. Don't hold off
- * on interrupts. (== 0x01 despite what the docs say)
- */
- pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr);
-
- if (info->chip_type >= HPT374)
- new_mcr = old_mcr & ~0x07;
- else if (info->chip_type >= HPT370) {
- new_mcr = old_mcr;
- new_mcr &= ~0x02;
-
-#ifdef HPT_DELAY_INTERRUPT
- new_mcr &= ~0x01;
-#else
- new_mcr |= 0x01;
-#endif
- } else /* HPT366 and HPT368 */
- new_mcr = old_mcr & ~0x80;
-
- if (new_mcr != old_mcr)
- pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
}
static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
@@ -1450,7 +1453,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = hpt366_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
@@ -1616,21 +1619,23 @@ static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
};
MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver hpt366_pci_driver = {
.name = "HPT366_IDE",
.id_table = hpt366_pci_tbl,
.probe = hpt366_init_one,
.remove = __devexit_p(hpt366_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init hpt366_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&hpt366_pci_driver);
}
static void __exit hpt366_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&hpt366_pci_driver);
}
module_init(hpt366_ide_init);
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 652e47dd7e8..7c2feeb3c5e 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -10,7 +10,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -190,21 +189,23 @@ static const struct pci_device_id it8213_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver it8213_pci_driver = {
.name = "ITE8213_IDE",
.id_table = it8213_pci_tbl,
.probe = it8213_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init it8213_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&it8213_pci_driver);
}
static void __exit it8213_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&it8213_pci_driver);
}
module_init(it8213_ide_init);
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 4a1508a707c..995e18bb313 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -63,7 +63,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -139,8 +138,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int channel = hwif->channel;
- int unit = drive->select.b.unit;
- u8 conf;
+ u8 unit = drive->dn & 1, conf;
/* Program UDMA timing bits */
if(itdev->clock_mode == ATA_66)
@@ -169,13 +167,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+ ide_drive_t *pair;
+ int clock, altclock, sel = 0;
+ u8 unit = drive->dn & 1, v;
- u8 unit = drive->select.b.unit;
- ide_drive_t *pair = &hwif->drives[1-unit];
-
- int clock, altclock;
- u8 v;
- int sel = 0;
+ pair = &hwif->drives[1 - unit];
if(itdev->want[0][0] > itdev->want[1][0]) {
clock = itdev->want[0][1];
@@ -241,16 +237,17 @@ static void it821x_clock_strategy(ide_drive_t *drive)
static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- ide_drive_t *pair = &hwif->drives[1 - unit];
- u8 set_pio = pio;
+ ide_drive_t *pair;
+ u8 unit = drive->dn & 1, set_pio = pio;
/* Spec says 89 ref driver uses 88 */
static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
+ pair = &hwif->drives[1 - unit];
+
/*
* Compute the best PIO mode we can for a given device. We must
* pick a speed that does not cause problems with the other device
@@ -287,9 +284,7 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- int channel = hwif->channel;
- u8 conf;
+ u8 unit = drive->dn & 1, channel = hwif->channel, conf;
static u16 dma[] = { 0x8866, 0x3222, 0x3121 };
static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY };
@@ -326,9 +321,7 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- int channel = hwif->channel;
- u8 conf;
+ u8 unit = drive->dn & 1, channel = hwif->channel, conf;
static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
@@ -370,7 +363,8 @@ static void it821x_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
+ u8 unit = drive->dn & 1;
+
if(itdev->mwdma[unit] != MWDMA_OFF)
it821x_program(drive, itdev->mwdma[unit]);
else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
@@ -390,9 +384,10 @@ static void it821x_dma_start(ide_drive_t *drive)
static int it821x_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int unit = drive->select.b.unit;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int ret = __ide_dma_end(drive);
+ int ret = ide_dma_end(drive);
+ u8 unit = drive->dn & 1;
+
if(itdev->mwdma[unit] != MWDMA_OFF)
it821x_program(drive, itdev->pio[unit]);
return ret;
@@ -446,8 +441,7 @@ static u8 it821x_cable_detect(ide_hwif_t *hwif)
static void it821x_quirkproc(ide_drive_t *drive)
{
struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
- struct hd_driveid *id = drive->id;
- u16 *idbits = (u16 *)drive->id;
+ u16 *id = drive->id;
if (!itdev->smart) {
/*
@@ -456,7 +450,7 @@ static void it821x_quirkproc(ide_drive_t *drive)
* IRQ mask as we may well be in PIO (eg rev 0x10)
* for now and we know unmasking is safe on this chipset.
*/
- drive->unmask = 1;
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
} else {
/*
* Perform fixups on smart mode. We need to "lose" some
@@ -466,36 +460,36 @@ static void it821x_quirkproc(ide_drive_t *drive)
*/
/* Check for RAID v native */
- if(strstr(id->model, "Integrated Technology Express")) {
+ if (strstr((char *)&id[ATA_ID_PROD],
+ "Integrated Technology Express")) {
/* In raid mode the ident block is slightly buggy
We need to set the bits so that the IDE layer knows
LBA28. LBA48 and DMA ar valid */
- id->capability |= 3; /* LBA28, DMA */
- id->command_set_2 |= 0x0400; /* LBA48 valid */
- id->cfs_enable_2 |= 0x0400; /* LBA48 on */
+ id[ATA_ID_CAPABILITY] |= (3 << 8); /* LBA28, DMA */
+ id[ATA_ID_COMMAND_SET_2] |= 0x0400; /* LBA48 valid */
+ id[ATA_ID_CFS_ENABLE_2] |= 0x0400; /* LBA48 on */
/* Reporting logic */
printk(KERN_INFO "%s: IT8212 %sRAID %d volume",
- drive->name,
- idbits[147] ? "Bootable ":"",
- idbits[129]);
- if(idbits[129] != 1)
- printk("(%dK stripe)", idbits[146]);
- printk(".\n");
+ drive->name, id[147] ? "Bootable " : "",
+ id[ATA_ID_CSFO]);
+ if (id[ATA_ID_CSFO] != 1)
+ printk(KERN_CONT "(%dK stripe)", id[146]);
+ printk(KERN_CONT ".\n");
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
- id->field_valid &= 3;
- id->queue_depth = 0;
- id->command_set_1 = 0;
- id->command_set_2 &= 0xC400;
- id->cfsse &= 0xC000;
- id->cfs_enable_1 = 0;
- id->cfs_enable_2 &= 0xC400;
- id->csf_default &= 0xC000;
- id->word127 = 0;
- id->dlf = 0;
- id->csfo = 0;
- id->cfa_power = 0;
+ id[ATA_ID_FIELD_VALID] &= 3;
+ id[ATA_ID_QUEUE_DEPTH] = 0;
+ id[ATA_ID_COMMAND_SET_1] = 0;
+ id[ATA_ID_COMMAND_SET_2] &= 0xC400;
+ id[ATA_ID_CFSSE] &= 0xC000;
+ id[ATA_ID_CFS_ENABLE_1] = 0;
+ id[ATA_ID_CFS_ENABLE_2] &= 0xC400;
+ id[ATA_ID_CSF_DEFAULT] &= 0xC000;
+ id[127] = 0;
+ id[ATA_ID_DLF] = 0;
+ id[ATA_ID_CSFO] = 0;
+ id[ATA_ID_CFA_POWER] = 0;
printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name);
}
@@ -505,8 +499,8 @@ static void it821x_quirkproc(ide_drive_t *drive)
* IDE core that DMA is supported (it821x hardware
* takes care of DMA mode programming).
*/
- if (id->capability & 1) {
- id->dma_mword |= 0x0101;
+ if (ata_id_has_dma(id)) {
+ id[ATA_ID_MWDMA_MODES] |= 0x0101;
drive->current_speed = XFER_MW_DMA_0;
}
}
@@ -588,7 +582,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->mwdma_mask = ATA_MWDMA2;
}
-static void __devinit it8212_disable_raid(struct pci_dev *dev)
+static void it8212_disable_raid(struct pci_dev *dev)
{
/* Reset local CPU, and set BIOS not ready */
pci_write_config_byte(dev, 0x5E, 0x01);
@@ -605,7 +599,7 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
-static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev)
+static unsigned int init_chipset_it821x(struct pci_dev *dev)
{
u8 conf;
static char *mode[2] = { "pass through", "smart" };
@@ -682,21 +676,23 @@ static const struct pci_device_id it821x_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver it821x_pci_driver = {
.name = "ITE821x IDE",
.id_table = it821x_pci_tbl,
.probe = it821x_init_one,
.remove = __devexit_p(it821x_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init it821x_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&it821x_pci_driver);
}
static void __exit it821x_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&it821x_pci_driver);
}
module_init(it821x_ide_init);
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index bb9d09d8f19..9a68433cf46 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -8,7 +8,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -150,21 +149,23 @@ static struct pci_device_id jmicron_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver jmicron_pci_driver = {
.name = "JMicron IDE",
.id_table = jmicron_pci_tbl,
.probe = jmicron_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init jmicron_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&jmicron_pci_driver);
}
static void __exit jmicron_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&jmicron_pci_driver);
}
module_init(jmicron_ide_init);
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index ffefcd15196..13789060f40 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -11,7 +11,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
@@ -138,7 +137,7 @@ static void __devinit superio_init_iops(struct hwif_s *hwif)
static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
/*
- * This routine either enables/disables (according to drive->present)
+ * This routine either enables/disables (according to IDE_DFLAG_PRESENT)
* the IRQ associated with the port (HWIF(drive)),
* and selects either PIO or DMA handshaking for the next I/O operation.
*/
@@ -154,11 +153,15 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
/* Adjust IRQ enable bit */
bit = 1 << (8 + hwif->channel);
- new = drive->present ? (new & ~bit) : (new | bit);
+
+ if (drive->dev_flags & IDE_DFLAG_PRESENT)
+ new &= ~bit;
+ else
+ new |= bit;
/* Select PIO or DMA, DMA may only be selected for one drive/channel. */
- bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
- other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+ bit = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
+ other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
if (new != *old) {
@@ -188,7 +191,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
static void ns87415_selectproc (ide_drive_t *drive)
{
- ns87415_prepare_drive (drive, drive->using_dma);
+ ns87415_prepare_drive(drive,
+ !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
}
static int ns87415_dma_end(ide_drive_t *drive)
@@ -274,9 +278,9 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
do {
udelay(50);
stat = hwif->tp_ops->read_status(hwif);
- if (stat == 0xff)
- break;
- } while ((stat & BUSY_STAT) && --timeout);
+ if (stat == 0xff)
+ break;
+ } while ((stat & ATA_BUSY) && --timeout);
#endif
}
@@ -335,21 +339,23 @@ static const struct pci_device_id ns87415_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver ns87415_pci_driver = {
.name = "NS87415_IDE",
.id_table = ns87415_pci_tbl,
.probe = ns87415_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init ns87415_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&ns87415_pci_driver);
}
static void __exit ns87415_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&ns87415_pci_driver);
}
module_init(ns87415_ide_init);
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index e28e672ddaf..6048eda3cd6 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -85,7 +85,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
@@ -137,7 +136,7 @@ static u8 read_reg(int reg)
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
unsigned long flags;
u8 tim, misc, addr_pio = pio, clk;
@@ -153,7 +152,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->drive_data = XFER_PIO_0 + pio;
- if (pair->present) {
+ if (pair) {
if (pair->drive_data && pair->drive_data < drive->drive_data)
addr_pio = pair->drive_data - XFER_PIO_0;
}
@@ -180,7 +179,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
misc = addr_timings[clk][addr_pio];
/* select Index-0/1 for Register-A/B */
- write_reg(drive->select.b.unit, MISC_REG);
+ write_reg(drive->dn & 1, MISC_REG);
/* set read cycle timings */
write_reg(tim, READ_REG);
/* set write cycle timings */
@@ -221,21 +220,23 @@ static const struct pci_device_id opti621_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver opti621_pci_driver = {
.name = "Opti621_IDE",
.id_table = opti621_pci_tbl,
.probe = opti621_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init opti621_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&opti621_pci_driver);
}
static void __exit opti621_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&opti621_pci_driver);
}
module_init(opti621_ide_init);
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index d477da6b585..211ae46e3e0 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -203,10 +202,10 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
static void pdcnew_quirkproc(ide_drive_t *drive)
{
- const char **list, *model = drive->id->model;
+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL) {
+ if (strstr(m, *list) != NULL) {
drive->quirk_list = 2;
return;
}
@@ -227,7 +226,7 @@ static void pdcnew_reset(ide_drive_t *drive)
* read_counter - Read the byte count registers
* @dma_base: for the port address
*/
-static long __devinit read_counter(u32 dma_base)
+static long read_counter(u32 dma_base)
{
u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
u8 cnt0, cnt1, cnt2, cnt3;
@@ -267,7 +266,7 @@ static long __devinit read_counter(u32 dma_base)
* @dma_base: for the port address
* E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
*/
-static long __devinit detect_pll_input_clock(unsigned long dma_base)
+static long detect_pll_input_clock(unsigned long dma_base)
{
struct timeval start_time, end_time;
long start_count, end_count;
@@ -310,7 +309,7 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
}
#ifdef CONFIG_PPC_PMAC
-static void __devinit apple_kiwi_init(struct pci_dev *pdev)
+static void apple_kiwi_init(struct pci_dev *pdev)
{
struct device_node *np = pci_device_to_OF_node(pdev);
u8 conf;
@@ -326,7 +325,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
}
#endif /* CONFIG_PPC_PMAC */
-static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev)
+static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
{
const char *name = DRV_NAME;
unsigned long dma_base = pci_resource_start(dev, 4);
@@ -562,21 +561,23 @@ static const struct pci_device_id pdc202new_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver pdc202new_pci_driver = {
.name = "Promise_IDE",
.id_table = pdc202new_pci_tbl,
.probe = pdc202new_init_one,
.remove = __devexit_p(pdc202new_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init pdc202new_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&pdc202new_pci_driver);
}
static void __exit pdc202new_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&pdc202new_pci_driver);
}
module_init(pdc202new_ide_init);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index de9a2740046..799557c25ee 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -86,7 +85,7 @@ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
* Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
*/
AP &= ~0x3f;
- if (drive->id->capability & 4)
+ if (ata_id_iordy_disable(drive->id))
AP |= 0x20; /* set IORDY_EN bit */
if (drive->media == ide_disk)
AP |= 0x10; /* set Prefetch_EN bit */
@@ -154,10 +153,10 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
static void pdc202xx_quirkproc(ide_drive_t *drive)
{
- const char **list, *model = drive->id->model;
+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
for (list = pdc_quirk_drives; *list != NULL; list++)
- if (strstr(model, *list) != NULL) {
+ if (strstr(m, *list) != NULL) {
drive->quirk_list = 2;
return;
}
@@ -169,7 +168,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
{
if (drive->current_speed > XFER_UDMA_2)
pdc_old_enable_66MHz_clock(drive->hwif);
- if (drive->media != ide_disk || drive->addressing == 1) {
+ if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
@@ -189,7 +188,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
static int pdc202xx_dma_end(ide_drive_t *drive)
{
- if (drive->media != ide_disk || drive->addressing == 1) {
+ if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
@@ -201,7 +200,7 @@ static int pdc202xx_dma_end(ide_drive_t *drive)
}
if (drive->current_speed > XFER_UDMA_2)
pdc_old_disable_66MHz_clock(drive->hwif);
- return __ide_dma_end(drive);
+ return ide_dma_end(drive);
}
static int pdc202xx_dma_test_irq(ide_drive_t *drive)
@@ -265,7 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
ide_dma_timeout(drive);
}
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev)
+static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
{
unsigned long dmabase = pci_resource_start(dev, 4);
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -334,7 +333,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = pdc202xx_dma_test_irq,
.dma_lost_irq = pdc202xx_dma_lost_irq,
.dma_timeout = pdc202xx_dma_timeout,
@@ -427,21 +426,23 @@ static const struct pci_device_id pdc202xx_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver pdc202xx_pci_driver = {
.name = "Promise_Old_IDE",
.id_table = pdc202xx_pci_tbl,
.probe = pdc202xx_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init pdc202xx_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&pdc202xx_pci_driver);
}
static void __exit pdc202xx_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&pdc202xx_pci_driver);
}
module_init(pdc202xx_ide_init);
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 30cfc815fe3..d63f9fdca76 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -48,7 +48,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -205,7 +204,7 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
* out to be nice and simple.
*/
-static unsigned int __devinit init_chipset_ich(struct pci_dev *dev)
+static unsigned int init_chipset_ich(struct pci_dev *dev)
{
u32 extra = 0;
@@ -216,17 +215,26 @@ static unsigned int __devinit init_chipset_ich(struct pci_dev *dev)
}
/**
- * piix_dma_clear_irq - clear BMDMA status
- * @drive: IDE drive to clear
+ * ich_clear_irq - clear BMDMA status
+ * @drive: IDE drive
*
- * Called from ide_intr() for PIO interrupts
- * to clear BMDMA status as needed by ICHx
+ * ICHx contollers set DMA INTR no matter DMA or PIO.
+ * BMDMA status might need to be cleared even for
+ * PIO interrupts to prevent spurious/lost IRQ.
*/
-static void piix_dma_clear_irq(ide_drive_t *drive)
+static void ich_clear_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat;
+ /*
+ * ide_dma_end() needs BMDMA status for error checking.
+ * So, skip clearing BMDMA status here and leave it
+ * to ide_dma_end() if this is DMA interrupt.
+ */
+ if (drive->waiting_for_dma || hwif->dma_base == 0)
+ return;
+
/* clear the INTR & ERROR bits */
dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Should we force the bit as well ? */
@@ -250,6 +258,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
+ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */
@@ -294,21 +303,19 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
}
-static void __devinit init_hwif_ich(ide_hwif_t *hwif)
-{
- init_hwif_piix(hwif);
-
- /* ICHx need to clear the BMDMA status for all interrupts */
- if (hwif->dma_base)
- hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
-}
-
static const struct ide_port_ops piix_port_ops = {
.set_pio_mode = piix_set_pio_mode,
.set_dma_mode = piix_set_dma_mode,
.cable_detect = piix_cable_detect,
};
+static const struct ide_port_ops ich_port_ops = {
+ .set_pio_mode = piix_set_pio_mode,
+ .set_dma_mode = piix_set_dma_mode,
+ .clear_irq = ich_clear_irq,
+ .cable_detect = piix_cable_detect,
+};
+
#ifndef CONFIG_IA64
#define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
#else
@@ -332,9 +339,9 @@ static const struct ide_port_ops piix_port_ops = {
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_ich, \
- .init_hwif = init_hwif_ich, \
+ .init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
- .port_ops = &piix_port_ops, \
+ .port_ops = &ich_port_ops, \
.host_flags = IDE_HFLAGS_PIIX, \
.pio_mask = ATA_PIO4, \
.swdma_mask = ATA_SWDMA2_ONLY, \
@@ -445,22 +452,24 @@ static const struct pci_device_id piix_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver piix_pci_driver = {
.name = "PIIX_IDE",
.id_table = piix_pci_tbl,
.probe = piix_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init piix_ide_init(void)
{
piix_check_450nx();
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&piix_pci_driver);
}
static void __exit piix_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&piix_pci_driver);
}
module_init(piix_ide_init);
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 8d11ee838a2..7daf0135cba 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -16,7 +16,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -60,7 +59,7 @@ static const struct pci_device_id rz1000_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver rz1000_pci_driver = {
.name = "RZ1000_IDE",
.id_table = rz1000_pci_tbl,
.probe = rz1000_init_one,
@@ -69,12 +68,12 @@ static struct pci_driver driver = {
static int __init rz1000_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&rz1000_pci_driver);
}
static void __exit rz1000_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&rz1000_pci_driver);
}
module_init(rz1000_ide_init);
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 8efaed16fea..f1a8758e3a9 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -104,17 +103,19 @@ static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
static u8 sc1200_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
- struct hd_driveid *mateid = mate->id;
+ ide_drive_t *mate = ide_get_pair_dev(drive);
+ u16 *mateid = mate->id;
u8 mask = hwif->ultra_mask;
- if (mate->present == 0)
+ if (mate == NULL)
goto out;
- if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
- if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+ (mateid[ATA_ID_UDMA_MODES] & 7))
goto out;
- if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+ (mateid[ATA_ID_MWDMA_MODES] & 7))
mask = 0;
}
out:
@@ -125,7 +126,6 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- int unit = drive->select.b.unit;
unsigned int reg, timings;
unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
@@ -154,7 +154,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
else
timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
- if (unit == 0) { /* are we configuring drive0? */
+ if ((drive->dn & 1) == 0) {
pci_read_config_dword(dev, basereg + 4, &reg);
timings |= reg & 0x80000000; /* preserve PIO format bit */
pci_write_config_dword(dev, basereg + 4, timings);
@@ -215,7 +215,8 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
if (mode != -1) {
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
ide_dma_off_quietly(drive);
- if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
+ if (ide_set_dma_mode(drive, mode) == 0 &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA))
hwif->dma_ops->dma_host_set(drive, 1);
return;
}
@@ -327,7 +328,7 @@ static const struct pci_device_id sc1200_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sc1200_pci_driver = {
.name = "SC1200_IDE",
.id_table = sc1200_pci_tbl,
.probe = sc1200_init_one,
@@ -340,12 +341,12 @@ static struct pci_driver driver = {
static int __init sc1200_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sc1200_pci_driver);
}
static void __exit sc1200_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&sc1200_pci_driver);
}
module_init(sc1200_ide_init);
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 44cccd1e086..9ce1d805992 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -26,7 +26,6 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -292,7 +291,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
- u8 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
if (on)
@@ -354,7 +353,6 @@ static void scc_dma_start(ide_drive_t *drive)
/* start DMA */
scc_ide_outb(dma_cmd | 1, hwif->dma_base);
- hwif->dma = 1;
wmb();
}
@@ -375,7 +373,6 @@ static int __scc_dma_end(ide_drive_t *drive)
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
- hwif->dma = 0;
wmb();
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
}
@@ -400,7 +397,7 @@ static int scc_dma_end(ide_drive_t *drive)
/* errata A308 workaround: Step5 (check data loss) */
/* We don't check non ide_disk because it is limited to UDMA4 */
if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ERR_STAT) &&
+ & ATA_ERR) &&
drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
reg = in_be32((void __iomem *)intsts_port);
if (!(reg & INTSTS_ACTEINT)) {
@@ -504,7 +501,7 @@ static int scc_dma_test_irq(ide_drive_t *drive)
/* SCC errata A252,A308 workaround: Step4 */
if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ERR_STAT) &&
+ & ATA_ERR) &&
(int_stat & INTSTS_INTRQ))
return 1;
@@ -512,9 +509,6 @@ static int scc_dma_test_irq(ide_drive_t *drive)
if (int_stat & INTSTS_IOIRQS)
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "%s: (%s) called while not waiting\n",
- drive->name, __func__);
return 0;
}
@@ -711,7 +705,7 @@ static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
scc_ide_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- scc_ide_outb((tf->device & HIHI) | drive->select.all,
+ scc_ide_outb((tf->device & HIHI) | drive->select,
io_ports->device_addr);
}
@@ -827,6 +821,12 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
init_mmio_iops_scc(hwif);
}
+static int __devinit scc_init_dma(ide_hwif_t *hwif,
+ const struct ide_port_info *d)
+{
+ return ide_allocate_dma_engine(hwif);
+}
+
static u8 scc_cable_detect(ide_hwif_t *hwif)
{
return ATA_CBL_PATA80;
@@ -891,6 +891,7 @@ static const struct ide_dma_ops scc_dma_ops = {
{ \
.name = name_str, \
.init_iops = init_iops_scc, \
+ .init_dma = scc_init_dma, \
.init_hwif = init_hwif_scc, \
.tp_ops = &scc_tp_ops, \
.port_ops = &scc_port_ops, \
@@ -928,13 +929,6 @@ static void __devexit scc_remove(struct pci_dev *dev)
{
struct scc_ports *ports = pci_get_drvdata(dev);
struct ide_host *host = ports->host;
- ide_hwif_t *hwif = host->ports[0];
-
- if (hwif->dmatable_cpu) {
- pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
- hwif->dmatable_cpu = NULL;
- }
ide_host_remove(host);
@@ -950,7 +944,7 @@ static const struct pci_device_id scc_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver scc_pci_driver = {
.name = "SCC IDE",
.id_table = scc_pci_tbl,
.probe = scc_init_one,
@@ -959,14 +953,14 @@ static struct pci_driver driver = {
static int scc_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&scc_pci_driver);
}
module_init(scc_ide_init);
/* -- No exit code?
static void scc_ide_exit(void)
{
- ide_pci_unregister_driver(&driver);
+ ide_pci_unregister_driver(&scc_pci_driver);
}
module_exit(scc_ide_exit);
*/
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index c3bdc6e51a4..437bc919daf 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -32,7 +32,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -57,8 +56,10 @@ static struct pci_dev *isa_dev;
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+
while (*list)
- if (!strcmp(*list++, drive->id->model))
+ if (!strcmp(*list++, m))
return 1;
return 0;
}
@@ -152,7 +153,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- u8 unit = (drive->select.b.unit & 0x01);
+ u8 unit = drive->dn & 1;
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
@@ -174,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, ultra_enable);
}
-static unsigned int __devinit init_chipset_svwks(struct pci_dev *dev)
+static unsigned int init_chipset_svwks(struct pci_dev *dev)
{
unsigned int reg;
u8 btr;
@@ -442,21 +443,23 @@ static const struct pci_device_id svwks_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver svwks_pci_driver = {
.name = "Serverworks_IDE",
.id_table = svwks_pci_tbl,
.probe = svwks_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init svwks_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&svwks_pci_driver);
}
static void __exit svwks_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&svwks_pci_driver);
}
module_init(svwks_ide_init);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 681306c9d79..dd634541ce3 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -22,7 +23,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
@@ -151,7 +151,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
int count = 0;
stat = sgiioc4_read_status(hwif);
- while ((stat & 0x80) && (count++ < 100)) {
+ while ((stat & ATA_BUSY) && (count++ < 100)) {
udelay(1);
stat = sgiioc4_read_status(hwif);
}
@@ -311,7 +311,7 @@ static u8 sgiioc4_read_status(ide_hwif_t *hwif)
u8 reg = (u8) readb((void __iomem *) port);
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
- if (reg & 0x51) { /* Not busy...check for interrupt */
+ if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
unsigned long other_ir = port - 0x110;
unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
@@ -339,35 +339,31 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
if (dma_base == 0)
return -1;
- printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
- dma_base, dma_base + num_ports - 1);
+ printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
- if (!request_mem_region(dma_base, num_ports, hwif->name)) {
- printk(KERN_ERR
- "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
- "ALREADY in use\n",
- __func__, hwif->name, (void *) dma_base,
- (void *) dma_base + num_ports - 1);
+ if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
+ printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
+ "already in use\n", __func__, hwif->name,
+ dma_base, dma_base + num_ports - 1);
return -1;
}
virt_dma_base = ioremap(dma_base, num_ports);
if (virt_dma_base == NULL) {
- printk(KERN_ERR
- "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
- __func__, hwif->name, dma_base, dma_base + num_ports - 1);
+ printk(KERN_ERR "%s(%s) -- ERROR: unable to map addresses "
+ "0x%lx to 0x%lx\n", __func__, hwif->name,
+ dma_base, dma_base + num_ports - 1);
goto dma_remap_failure;
}
hwif->dma_base = (unsigned long) virt_dma_base;
- hwif->dmatable_cpu = pci_alloc_consistent(dev,
- IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
- &hwif->dmatable_dma);
+ hwif->sg_max_nents = IOC4_PRD_ENTRIES;
- if (!hwif->dmatable_cpu)
- goto dma_pci_alloc_failure;
+ hwif->prd_max_nents = IOC4_PRD_ENTRIES;
+ hwif->prd_ent_size = IOC4_PRD_BYTES;
- hwif->sg_max_nents = IOC4_PRD_ENTRIES;
+ if (ide_allocate_dma_engine(hwif))
+ goto dma_pci_alloc_failure;
pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
(dma_addr_t *)&hwif->extra_base);
@@ -376,13 +372,11 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
return 0;
}
- pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
- printk(KERN_INFO
- "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
+ ide_release_dma_engine(hwif);
+
+ printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
__func__, hwif->name);
- printk(KERN_INFO
- "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+ printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
dma_pci_alloc_failure:
iounmap(virt_dma_base);
@@ -618,14 +612,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
- if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
- DRV_NAME)) {
- printk(KERN_ERR
- "%s %s: -- ERROR, Addresses "
- "0x%p to 0x%p ALREADY in use\n",
- DRV_NAME, pci_name(dev), (void *)cmd_phys_base,
- (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
- return -ENOMEM;
+ if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+ DRV_NAME) == NULL) {
+ printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
+ "already in use\n", DRV_NAME, pci_name(dev),
+ cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
+ return -EBUSY;
}
/* Initialize the IO registers */
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index db2b88a369a..eb4faf92c57 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -39,7 +39,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -117,13 +116,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long base = (unsigned long)hwif->hwif_data;
+ u8 unit = drive->dn & 1;
base += 0xA0 + r;
if (hwif->host_flags & IDE_HFLAG_MMIO)
base += hwif->channel << 6;
else
base += hwif->channel << 4;
- base |= drive->select.b.unit << drive->select.b.unit;
+ base |= unit << unit;
return base;
}
@@ -223,7 +223,9 @@ static u8 sil_pata_udma_filter(ide_drive_t *drive)
static u8 sil_sata_udma_filter(ide_drive_t *drive)
{
- return strstr(drive->id->model, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
+ char *m = (char *)&drive->id[ATA_ID_PROD];
+
+ return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
}
/**
@@ -243,7 +245,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- ide_drive_t *pair = ide_get_paired_drive(drive);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
u32 speedt = 0;
u16 speedp = 0;
unsigned long addr = siimage_seldev(drive, 0x04);
@@ -254,10 +256,10 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
u8 addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
: (mmio ? 0xB4 : 0x80);
u8 mode = 0;
- u8 unit = drive->select.b.unit;
+ u8 unit = drive->dn & 1;
/* trim *taskfile* PIO to the slowest of the master/slave */
- if (pair->present) {
+ if (pair) {
u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
if (pair_pio < tf_pio)
@@ -300,9 +302,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- u16 ultra = 0, multi = 0;
- u8 mode = 0, unit = drive->select.b.unit;
unsigned long base = (unsigned long)hwif->hwif_data;
+ u16 ultra = 0, multi = 0;
+ u8 mode = 0, unit = drive->dn & 1;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 scsc = 0, addr_mask = hwif->channel ? (mmio ? 0xF4 : 0x84)
: (mmio ? 0xB4 : 0x80);
@@ -462,7 +464,7 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
* to 133 MHz clocking if the system isn't already set up to do it.
*/
-static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev)
+static unsigned int init_chipset_siimage(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
void __iomem *ioaddr = host->host_priv;
@@ -616,8 +618,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
static int is_dev_seagate_sata(ide_drive_t *drive)
{
- const char *s = &drive->id->model[0];
- unsigned len = strnlen(s, sizeof(drive->id->model));
+ const char *s = (const char *)&drive->id[ATA_ID_PROD];
+ unsigned len = strnlen(s, ATA_ID_PROD_LEN);
if ((len > 4) && (!memcmp(s, "ST", 2)))
if ((!memcmp(s + len - 2, "AS", 2)) ||
@@ -711,7 +713,7 @@ static const struct ide_dma_ops sil_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = siimage_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
@@ -828,21 +830,23 @@ static const struct pci_device_id siimage_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver siimage_pci_driver = {
.name = "SiI_IDE",
.id_table = siimage_pci_tbl,
.probe = siimage_init_one,
.remove = __devexit_p(siimage_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init siimage_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&siimage_pci_driver);
}
static void __exit siimage_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&siimage_pci_driver);
}
module_init(siimage_ide_init);
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 5efe21d6ef9..ad32e18c5ba 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -47,7 +47,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
@@ -448,7 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev)
return chipset_family;
}
-static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev)
+static unsigned int init_chipset_sis5513(struct pci_dev *dev)
{
/* Make general config ops here
1/ tell IDE channels to operate in Compatibility mode only
@@ -606,21 +605,23 @@ static const struct pci_device_id sis5513_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sis5513_pci_driver = {
.name = "SIS_IDE",
.id_table = sis5513_pci_tbl,
.probe = sis5513_init_one,
.remove = __devexit_p(sis5513_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init sis5513_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sis5513_pci_driver);
}
static void __exit sis5513_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&sis5513_pci_driver);
}
module_init(sis5513_ide_init);
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 73905bcc08f..84dc33602ff 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -17,7 +17,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
@@ -62,7 +61,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
if (cmd_off == 0)
cmd_off = 1;
- if (pio > 2 || ide_dev_has_iordy(drive->id))
+ if (pio > 2 || ata_id_has_iordy(drive->id))
iordy = 0x40;
return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
@@ -208,7 +207,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
DBG(("%s(drive:%s)\n", __func__, drive->name));
- ret = __ide_dma_end(drive);
+ ret = ide_dma_end(drive);
pci_write_config_word(dev, reg, drive->drive_data);
@@ -272,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev)
* channel 0 here at least, but channel 1 has to be enabled by
* firmware or arch code. We still set both to 16 bits mode.
*/
-static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev)
+static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
{
u32 val;
@@ -346,21 +345,23 @@ static const struct pci_device_id sl82c105_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver sl82c105_pci_driver = {
.name = "W82C105_IDE",
.id_table = sl82c105_pci_tbl,
.probe = sl82c105_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init sl82c105_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&sl82c105_pci_driver);
}
static void __exit sl82c105_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&sl82c105_pci_driver);
}
module_init(sl82c105_ide_init);
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 866d6c65e3a..0f759e4ed77 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -155,21 +154,23 @@ static const struct pci_device_id slc90e66_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver slc90e66_pci_driver = {
.name = "SLC90e66_IDE",
.id_table = slc90e66_pci_tbl,
.probe = slc90e66_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init slc90e66_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&slc90e66_pci_driver);
}
static void __exit slc90e66_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&slc90e66_pci_driver);
}
module_init(slc90e66_ide_init);
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 927277c54ec..93e2cce4b29 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -186,7 +186,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = tc86c001_dma_start,
- .dma_end = __ide_dma_end,
+ .dma_end = ide_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
@@ -245,7 +245,7 @@ static const struct pci_device_id tc86c001_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver tc86c001_pci_driver = {
.name = "TC86C001",
.id_table = tc86c001_pci_tbl,
.probe = tc86c001_init_one,
@@ -254,12 +254,12 @@ static struct pci_driver driver = {
static int __init tc86c001_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&tc86c001_pci_driver);
}
static void __exit tc86c001_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&tc86c001_pci_driver);
}
module_init(tc86c001_ide_init);
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index b77ec35151b..b6ff40336aa 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -28,7 +28,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
@@ -39,13 +38,12 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- u8 channel_offset = hwif->channel ? 0x74 : 0x70;
- u16 timing = 0;
u32 triflex_timings = 0;
- u8 unit = (drive->select.b.unit & 0x01);
-
+ u16 timing = 0;
+ u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
+
pci_read_config_dword(dev, channel_offset, &triflex_timings);
-
+
switch(speed) {
case XFER_MW_DMA_2:
timing = 0x0103;
@@ -115,21 +113,23 @@ static const struct pci_device_id triflex_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver triflex_pci_driver = {
.name = "TRIFLEX_IDE",
.id_table = triflex_pci_tbl,
.probe = triflex_init_one,
.remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init triflex_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&triflex_pci_driver);
}
static void __exit triflex_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&triflex_pci_driver);
}
module_init(triflex_ide_init);
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index fd28b49977f..75ea6152656 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -135,7 +135,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/init.h>
-#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
@@ -162,7 +161,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
}
/* enable IRQ if not probing */
- if (drive->present) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
reg = inw(hwif->config_data + 3);
reg &= 0x13;
reg &= ~(1 << hwif->channel);
@@ -174,7 +173,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
static void trm290_selectproc (ide_drive_t *drive)
{
- trm290_prepare_drive(drive, drive->using_dma);
+ trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
}
static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
@@ -351,7 +350,7 @@ static const struct pci_device_id trm290_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver trm290_pci_driver = {
.name = "TRM290_IDE",
.id_table = trm290_pci_tbl,
.probe = trm290_init_one,
@@ -360,12 +359,12 @@ static struct pci_driver driver = {
static int __init trm290_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&trm290_pci_driver);
}
static void __exit trm290_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&trm290_pci_driver);
}
module_init(trm290_ide_init);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 94fb9ab3223..2a812d3207e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -154,7 +154,7 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
static void via_set_drive(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+ ide_drive_t *peer = ide_get_pair_dev(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct via82cxxx_dev *vdev = host->host_priv;
@@ -173,7 +173,7 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_compute(drive, speed, &t, T, UT);
- if (peer->present) {
+ if (peer) {
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
@@ -215,7 +215,7 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
/*
* Check and handle 80-wire cable presence
*/
-static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
+static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
{
int i;
@@ -267,7 +267,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
* and initialize its drive independent registers.
*/
-static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev)
+static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
struct via82cxxx_dev *vdev = host->host_priv;
@@ -487,21 +487,23 @@ static const struct pci_device_id via_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, via_pci_tbl);
-static struct pci_driver driver = {
+static struct pci_driver via_pci_driver = {
.name = "VIA_IDE",
.id_table = via_pci_tbl,
.probe = via_init_one,
.remove = __devexit_p(via_remove),
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
};
static int __init via_ide_init(void)
{
- return ide_pci_register_driver(&driver);
+ return ide_pci_register_driver(&via_pci_driver);
}
static void __exit via_ide_exit(void)
{
- pci_unregister_driver(&driver);
+ pci_unregister_driver(&via_pci_driver);
}
module_init(via_ide_init);
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index fa2be26272d..2e19d629853 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -430,10 +430,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (pmif == NULL)
- return;
-
- if (drive->select.b.unit & 0x01)
+ if (drive->dn & 1)
writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
else
writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
@@ -452,10 +449,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (pmif == NULL)
- return;
-
- if (drive->select.b.unit & 0x01) {
+ if (drive->dn & 1) {
writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
} else {
@@ -475,9 +469,6 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (pmif == NULL)
- return;
-
if (pmif->kind == controller_sh_ata6 ||
pmif->kind == controller_un_ata6 ||
pmif->kind == controller_k2_ata6)
@@ -524,11 +515,8 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
unsigned accessTime, recTime;
unsigned int cycle_time;
- if (pmif == NULL)
- return;
-
/* which drive is it ? */
- timings = &pmif->timings[drive->select.b.unit & 0x01];
+ timings = &pmif->timings[drive->dn & 1];
t = *timings;
cycle_time = ide_pio_cycle_time(drive, pio);
@@ -669,9 +657,9 @@ static void
set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
u8 speed)
{
+ u16 *id = drive->id;
int cycleTime, accessTime = 0, recTime = 0;
unsigned accessTicks, recTicks;
- struct hd_driveid *id = drive->id;
struct mdma_timings_t* tm = NULL;
int i;
@@ -686,8 +674,8 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
}
/* Check if drive provides explicit DMA cycle time */
- if ((id->field_valid & 2) && id->eide_dma_time)
- cycleTime = max_t(int, id->eide_dma_time, cycleTime);
+ if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME])
+ cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime);
/* OHare limits according to some old Apple sources */
if ((intf_type == controller_ohare) && (cycleTime < 150))
@@ -805,9 +793,9 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
ide_hwif_t *hwif = drive->hwif;
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- int unit = (drive->select.b.unit & 0x01);
int ret = 0;
u32 *timings, *timings2, tl[2];
+ u8 unit = drive->dn & 1;
timings = &pmif->timings[unit];
timings2 = &pmif->timings[unit+2];
@@ -966,11 +954,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
if (pmif->mediabay) {
#ifdef CONFIG_PMAC_MEDIABAY
if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
- drive->noprobe = 0;
+ drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
return;
}
#endif
- drive->noprobe = 1;
+ drive->dev_flags |= IDE_DFLAG_NOPROBE;
}
}
@@ -1535,18 +1523,6 @@ use_pio_instead:
return 0; /* revert to PIO for this request */
}
-/* Teardown mappings after DMA has completed. */
-static void
-pmac_ide_destroy_dmatable (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if (hwif->sg_nents) {
- ide_destroy_dmatable(drive);
- hwif->sg_nents = 0;
- }
-}
-
/*
* Prepare a DMA transfer. We build the DMA table, adjust the timings for
* a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
@@ -1558,12 +1534,7 @@ pmac_ide_dma_setup(ide_drive_t *drive)
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct request *rq = HWGROUP(drive)->rq;
- u8 unit = (drive->select.b.unit & 0x01);
- u8 ata4;
-
- if (pmif == NULL)
- return 1;
- ata4 = (pmif->kind == controller_kl_ata4);
+ u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
if (!pmac_ide_build_dmatable(drive, rq)) {
ide_map_sg(drive, rq);
@@ -1617,17 +1588,15 @@ pmac_ide_dma_end (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- volatile struct dbdma_regs __iomem *dma;
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
u32 dstat;
-
- if (pmif == NULL)
- return 0;
- dma = pmif->dma_regs;
drive->waiting_for_dma = 0;
dstat = readl(&dma->status);
writel(((RUN|WAKE|DEAD) << 16), &dma->control);
- pmac_ide_destroy_dmatable(drive);
+
+ ide_destroy_dmatable(drive);
+
/* verify good dma status. we don't check for ACTIVE beeing 0. We should...
* in theory, but with ATAPI decices doing buffer underruns, that would
* cause us to disable DMA, which isn't what we want
@@ -1647,13 +1616,9 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- volatile struct dbdma_regs __iomem *dma;
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
unsigned long status, timeout;
- if (pmif == NULL)
- return 0;
- dma = pmif->dma_regs;
-
/* We have to things to deal with here:
*
* - The dbdma won't stop if the command was started
@@ -1672,9 +1637,6 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
status = readl(&dma->status);
if (!(status & ACTIVE))
return 1;
- if (!drive->waiting_for_dma)
- printk(KERN_WARNING "ide%d, ide_dma_test_irq \
- called while not waiting\n", HWIF(drive)->index);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set. We consider that we aren't
@@ -1709,14 +1671,9 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- volatile struct dbdma_regs __iomem *dma;
- unsigned long status;
-
- if (pmif == NULL)
- return;
- dma = pmif->dma_regs;
+ volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+ unsigned long status = readl(&dma->status);
- status = readl(&dma->status);
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
}
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index a8e9e8a69a5..9f1f9163a13 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -659,3 +659,36 @@ void ide_pci_remove(struct pci_dev *dev)
pci_disable_device(dev);
}
EXPORT_SYMBOL_GPL(ide_pci_remove);
+
+#ifdef CONFIG_PM
+int ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_pci_suspend);
+
+int ide_pci_resume(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ int rc;
+
+ pci_set_power_state(dev, PCI_D0);
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_restore_state(dev);
+ pci_set_master(dev);
+
+ if (host->init_chipset)
+ host->init_chipset(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_pci_resume);
+#endif
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 9f95337139e..5e38a68b8af 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = {
#define quads_to_bytes(_q) ((_q) * sizeof(u32))
-#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32))
+#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32))
static void free_keyval(struct csr1212_keyval *kv)
{
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index b6eb2cf2591..2f83543a9df 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
/* default SYT offset is 3 cycles */
init->syt_offset = 3;
- if ( (init->channel > 63) || (init->channel < 0) )
+ if (init->channel > 63)
init->channel = 63;
chan_mask = (u64)1 << init->channel;
@@ -2296,10 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- device_create_drvdata(hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
- "dv1394-%d", id);
+ device_create(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ NULL, "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index b166b3575fa..20128692b33 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
hdr->ff.dgl = dgl;
adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
}
- return (dg_size + adj_max_payload - 1) / adj_max_payload;
+ return DIV_ROUND_UP(dg_size, adj_max_payload);
}
static unsigned int ether1394_encapsulate(struct sk_buff *skb,
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 16240a78965..2376b729e87 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -154,9 +154,6 @@ struct host_info {
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
-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);
struct bus_type ieee1394_bus_type = {
.name = "ieee1394",
@@ -385,27 +382,6 @@ static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute
static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
-static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count)
-{
- struct node_entry *ne;
- u64 guid = (u64)simple_strtoull(buf, NULL, 16);
-
- ne = find_entry_by_guid(guid);
-
- if (ne == NULL || !ne->in_limbo)
- return -EINVAL;
-
- nodemgr_remove_ne(ne);
-
- return count;
-}
-static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
-{
- return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n");
-}
-static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
-
-
static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
size_t count)
{
@@ -442,7 +418,6 @@ static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set
struct bus_attribute *const fw_bus_attrs[] = {
- &bus_attr_destroy_node,
&bus_attr_rescan,
&bus_attr_ignore_drivers,
NULL
@@ -734,10 +709,10 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
-static int __match_ne(struct device *dev, void *data)
+static int match_ne(struct device *dev, void *data)
{
struct unit_directory *ud;
- struct node_entry *ne = (struct node_entry *)data;
+ struct node_entry *ne = data;
ud = container_of(dev, struct unit_directory, unit_dev);
return ud->ne == ne;
@@ -754,8 +729,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
*/
mutex_lock(&nodemgr_serialize_remove_uds);
for (;;) {
- dev = class_find_device(&nodemgr_ud_class, NULL, ne,
- __match_ne);
+ dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne);
if (!dev)
break;
ud = container_of(dev, struct unit_directory, unit_dev);
@@ -785,7 +759,7 @@ static void nodemgr_remove_ne(struct node_entry *ne)
put_device(dev);
}
-static int __nodemgr_remove_host_dev(struct device *dev, void *data)
+static int remove_host_dev(struct device *dev, void *data)
{
if (dev->bus == &ieee1394_bus_type)
nodemgr_remove_ne(container_of(dev, struct node_entry,
@@ -795,7 +769,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data)
static void nodemgr_remove_host_dev(struct device *dev)
{
- WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev));
+ device_for_each_child(dev, NULL, remove_host_dev);
sysfs_remove_link(&dev->kobj, "irm_id");
sysfs_remove_link(&dev->kobj, "busmgr_id");
sysfs_remove_link(&dev->kobj, "host_id");
@@ -830,11 +804,10 @@ static void nodemgr_update_bus_options(struct node_entry *ne)
}
-static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr,
- struct host_info *hi, nodeid_t nodeid,
- unsigned int generation)
+static struct node_entry *nodemgr_create_node(octlet_t guid,
+ struct csr1212_csr *csr, struct hpsb_host *host,
+ nodeid_t nodeid, unsigned int generation)
{
- struct hpsb_host *host = hi->host;
struct node_entry *ne;
ne = kzalloc(sizeof(*ne), GFP_KERNEL);
@@ -888,10 +861,10 @@ fail_alloc:
return NULL;
}
-static int __match_ne_guid(struct device *dev, void *data)
+static int match_ne_guid(struct device *dev, void *data)
{
struct node_entry *ne;
- u64 *guid = (u64 *)data;
+ u64 *guid = data;
ne = container_of(dev, struct node_entry, node_dev);
return ne->guid == *guid;
@@ -902,8 +875,7 @@ static struct node_entry *find_entry_by_guid(u64 guid)
struct device *dev;
struct node_entry *ne;
- dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
- __match_ne_guid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -912,21 +884,21 @@ static struct node_entry *find_entry_by_guid(u64 guid)
return ne;
}
-struct match_nodeid_param {
+struct match_nodeid_parameter {
struct hpsb_host *host;
nodeid_t nodeid;
};
-static int __match_ne_nodeid(struct device *dev, void *data)
+static int match_ne_nodeid(struct device *dev, void *data)
{
int found = 0;
struct node_entry *ne;
- struct match_nodeid_param *param = (struct match_nodeid_param *)data;
+ struct match_nodeid_parameter *p = data;
if (!dev)
goto ret;
ne = container_of(dev, struct node_entry, node_dev);
- if (ne->host == param->host && ne->nodeid == param->nodeid)
+ if (ne->host == p->host && ne->nodeid == p->nodeid)
found = 1;
ret:
return found;
@@ -937,13 +909,12 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
{
struct device *dev;
struct node_entry *ne;
- struct match_nodeid_param param;
+ struct match_nodeid_parameter p;
- param.host = host;
- param.nodeid = nodeid;
+ p.host = host;
+ p.nodeid = nodeid;
- dev = class_find_device(&nodemgr_ne_class, NULL, &param,
- __match_ne_nodeid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -990,7 +961,7 @@ fail_devreg:
* immediate unit directories looking for software_id and
* software_version entries, in order to get driver autoloading working. */
static struct unit_directory *nodemgr_process_unit_directory
- (struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv,
+ (struct node_entry *ne, struct csr1212_keyval *ud_kv,
unsigned int *id, struct unit_directory *parent)
{
struct unit_directory *ud;
@@ -1083,7 +1054,7 @@ static struct unit_directory *nodemgr_process_unit_directory
nodemgr_register_device(ne, ud, &ne->device);
/* process the child unit */
- ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);
+ ud_child = nodemgr_process_unit_directory(ne, kv, id, ud);
if (ud_child == NULL)
break;
@@ -1137,7 +1108,7 @@ unit_directory_error:
}
-static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne)
+static void nodemgr_process_root_directory(struct node_entry *ne)
{
unsigned int ud_id = 0;
struct csr1212_dentry *dentry;
@@ -1157,7 +1128,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
break;
case CSR1212_KV_ID_UNIT:
- nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL);
+ nodemgr_process_unit_directory(ne, kv, &ud_id, NULL);
break;
case CSR1212_KV_ID_DESCRIPTOR:
@@ -1273,8 +1244,7 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
* the to take whatever actions required.
*/
static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
- struct host_info *hi, nodeid_t nodeid,
- unsigned int generation)
+ nodeid_t nodeid, unsigned int generation)
{
if (ne->nodeid != nodeid) {
HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
@@ -1305,19 +1275,23 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
csr1212_destroy_csr(csr);
}
- if (ne->in_limbo)
- nodemgr_resume_ne(ne);
-
/* Mark the node current */
ne->generation = generation;
-}
+ if (ne->in_limbo) {
+ device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
+ ne->in_limbo = false;
+ HPSB_DEBUG("Node reactivated: "
+ "ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
+ NODE_BUS_ARGS(ne->host, ne->nodeid),
+ (unsigned long long)ne->guid);
+ }
+}
-static void nodemgr_node_scan_one(struct host_info *hi,
+static void nodemgr_node_scan_one(struct hpsb_host *host,
nodeid_t nodeid, int generation)
{
- struct hpsb_host *host = hi->host;
struct node_entry *ne;
octlet_t guid;
struct csr1212_csr *csr;
@@ -1373,16 +1347,15 @@ static void nodemgr_node_scan_one(struct host_info *hi,
}
if (!ne)
- nodemgr_create_node(guid, csr, hi, nodeid, generation);
+ nodemgr_create_node(guid, csr, host, nodeid, generation);
else
- nodemgr_update_node(ne, csr, hi, nodeid, generation);
+ nodemgr_update_node(ne, csr, nodeid, generation);
}
-static void nodemgr_node_scan(struct host_info *hi, int generation)
+static void nodemgr_node_scan(struct hpsb_host *host, int generation)
{
int count;
- struct hpsb_host *host = hi->host;
struct selfid *sid = (struct selfid *)host->topology_map;
nodeid_t nodeid = LOCAL_BUS;
@@ -1395,89 +1368,26 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
nodeid++;
continue;
}
- nodemgr_node_scan_one(hi, nodeid++, generation);
- }
-}
-
-static int __nodemgr_driver_suspend(struct device *dev, void *data)
-{
- struct unit_directory *ud;
- struct device_driver *drv;
- struct node_entry *ne = (struct node_entry *)data;
- int error;
-
- ud = container_of(dev, struct unit_directory, unit_dev);
- if (ud->ne == ne) {
- drv = get_driver(ud->device.driver);
- if (drv) {
- error = 1; /* release if suspend is not implemented */
- if (drv->suspend) {
- down(&ud->device.sem);
- error = drv->suspend(&ud->device, PMSG_SUSPEND);
- up(&ud->device.sem);
- }
- if (error)
- device_release_driver(&ud->device);
- put_driver(drv);
- }
- }
-
- return 0;
-}
-
-static int __nodemgr_driver_resume(struct device *dev, void *data)
-{
- struct unit_directory *ud;
- struct device_driver *drv;
- struct node_entry *ne = (struct node_entry *)data;
-
- ud = container_of(dev, struct unit_directory, unit_dev);
- if (ud->ne == ne) {
- drv = get_driver(ud->device.driver);
- if (drv) {
- if (drv->resume) {
- down(&ud->device.sem);
- drv->resume(&ud->device);
- up(&ud->device.sem);
- }
- put_driver(drv);
- }
+ nodemgr_node_scan_one(host, nodeid++, generation);
}
-
- return 0;
}
-static void nodemgr_suspend_ne(struct node_entry *ne)
+static void nodemgr_pause_ne(struct node_entry *ne)
{
- HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
+ HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid),
(unsigned long long)ne->guid);
- ne->in_limbo = 1;
+ ne->in_limbo = true;
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
-
- class_for_each_device(&nodemgr_ud_class, NULL, ne,
- __nodemgr_driver_suspend);
-}
-
-
-static void nodemgr_resume_ne(struct node_entry *ne)
-{
- ne->in_limbo = 0;
- device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-
- class_for_each_device(&nodemgr_ud_class, NULL, ne,
- __nodemgr_driver_resume);
- HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
- NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
}
-static int __nodemgr_update_pdrv(struct device *dev, void *data)
+static int update_pdrv(struct device *dev, void *data)
{
struct unit_directory *ud;
struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
- struct node_entry *ne = (struct node_entry *)data;
+ struct node_entry *ne = data;
int error;
ud = container_of(dev, struct unit_directory, unit_dev);
@@ -1503,11 +1413,9 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
- class_for_each_device(&nodemgr_ud_class, NULL, ne,
- __nodemgr_update_pdrv);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
}
-
/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This
* seems like an optional service but in the end it is practically mandatory
* as a consequence of these clauses.
@@ -1535,11 +1443,12 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
}
-static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
+static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne,
+ int generation)
{
struct device *dev;
- if (ne->host != hi->host || ne->in_limbo)
+ if (ne->host != host || ne->in_limbo)
return;
dev = get_device(&ne->device);
@@ -1554,40 +1463,40 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
* down to the drivers. Otherwise, this is a dead node and we
* suspend it. */
if (ne->needs_probe)
- nodemgr_process_root_directory(hi, ne);
+ nodemgr_process_root_directory(ne);
else if (ne->generation == generation)
nodemgr_update_pdrv(ne);
else
- nodemgr_suspend_ne(ne);
+ nodemgr_pause_ne(ne);
put_device(dev);
}
-struct probe_param {
- struct host_info *hi;
+struct node_probe_parameter {
+ struct hpsb_host *host;
int generation;
bool probe_now;
};
static int node_probe(struct device *dev, void *data)
{
- struct probe_param *p = data;
+ struct node_probe_parameter *p = data;
struct node_entry *ne;
- if (p->generation != get_hpsb_generation(p->hi->host))
+ if (p->generation != get_hpsb_generation(p->host))
return -EAGAIN;
ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe == p->probe_now)
- nodemgr_probe_ne(p->hi, ne, p->generation);
+ nodemgr_probe_ne(p->host, ne, p->generation);
return 0;
}
-static void nodemgr_node_probe(struct host_info *hi, int generation)
+static int nodemgr_node_probe(struct hpsb_host *host, int generation)
{
- struct probe_param p;
+ struct node_probe_parameter p;
- p.hi = hi;
+ p.host = host;
p.generation = generation;
/*
* Do some processing of the nodes we've probed. This pulls them
@@ -1604,11 +1513,11 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
*/
p.probe_now = false;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
- return;
+ return 0;
p.probe_now = true;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
- return;
+ return 0;
/*
* Now let's tell the bus to rescan our devices. This may seem
* like overhead, but the driver-model core will only scan a
@@ -1620,6 +1529,27 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
*/
if (bus_rescan_devices(&ieee1394_bus_type) != 0)
HPSB_DEBUG("bus_rescan_devices had an error");
+
+ return 1;
+}
+
+static int remove_nodes_in_limbo(struct device *dev, void *data)
+{
+ struct node_entry *ne;
+
+ if (dev->bus != &ieee1394_bus_type)
+ return 0;
+
+ ne = container_of(dev, struct node_entry, device);
+ if (ne->in_limbo)
+ nodemgr_remove_ne(ne);
+
+ return 0;
+}
+
+static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
+{
+ device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
}
static int nodemgr_send_resume_packet(struct hpsb_host *host)
@@ -1730,10 +1660,9 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
return 1;
}
-static int nodemgr_host_thread(void *__hi)
+static int nodemgr_host_thread(void *data)
{
- struct host_info *hi = (struct host_info *)__hi;
- struct hpsb_host *host = hi->host;
+ struct hpsb_host *host = data;
unsigned int g, generation = 0;
int i, reset_cycles = 0;
@@ -1787,36 +1716,48 @@ static int nodemgr_host_thread(void *__hi)
* entries. This does not do the sysfs stuff, since that
* would trigger uevents and such, which is a bad idea at
* this point. */
- nodemgr_node_scan(hi, generation);
+ nodemgr_node_scan(host, generation);
/* This actually does the full probe, with sysfs
* registration. */
- nodemgr_node_probe(hi, generation);
+ if (!nodemgr_node_probe(host, generation))
+ continue;
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
+
+ /* Sleep 3 seconds */
+ for (i = 3000/200; i; i--) {
+ msleep_interruptible(200);
+ if (kthread_should_stop())
+ goto exit;
+
+ if (generation != get_hpsb_generation(host))
+ break;
+ }
+ /* Remove nodes which are gone, unless a bus reset happened */
+ if (!i)
+ nodemgr_remove_nodes_in_limbo(host);
}
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
}
-struct host_iter_param {
+struct per_host_parameter {
void *data;
int (*cb)(struct hpsb_host *, void *);
};
-static int __nodemgr_for_each_host(struct device *dev, void *data)
+static int per_host(struct device *dev, void *data)
{
struct hpsb_host *host;
- struct host_iter_param *hip = (struct host_iter_param *)data;
- int error = 0;
+ struct per_host_parameter *p = data;
host = container_of(dev, struct hpsb_host, host_dev);
- error = hip->cb(host, hip->data);
-
- return error;
+ return p->cb(host, p->data);
}
+
/**
* nodemgr_for_each_host - call a function for each IEEE 1394 host
* @data: an address to supply to the callback
@@ -1831,15 +1772,11 @@ static int __nodemgr_for_each_host(struct device *dev, void *data)
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
- struct host_iter_param hip;
- int error;
-
- hip.cb = cb;
- hip.data = data;
- error = class_for_each_device(&hpsb_host_class, NULL, &hip,
- __nodemgr_for_each_host);
+ struct per_host_parameter p;
- return error;
+ p.cb = cb;
+ p.data = data;
+ return class_for_each_device(&hpsb_host_class, NULL, &p, per_host);
}
/* The following two convenience functions use a struct node_entry
@@ -1893,7 +1830,7 @@ static void nodemgr_add_host(struct hpsb_host *host)
return;
}
hi->host = host;
- hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d",
+ hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d",
host->id);
if (IS_ERR(hi->thread)) {
HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 6eb26465a84..4f287a3561b 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -110,7 +110,7 @@ struct node_entry {
struct device node_dev;
/* Means this node is not attached anymore */
- int in_limbo;
+ bool in_limbo;
struct csr1212_csr *csr;
};
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index a06aaad5b44..7a225a40598 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
struct file_info {
struct list_head list;
+ struct mutex state_mutex;
enum { opened, initialized, connected } state;
unsigned int protocol_version;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 6fa9e4a2184..9f19ac49210 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -34,6 +34,7 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
return -EFAULT;
}
+ mutex_lock(&fi->state_mutex);
+
switch (fi->state) {
case opened:
retval = state_opened(fi, req);
@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
break;
}
+ mutex_unlock(&fi->state_mutex);
+
if (retval < 0) {
free_pending_request(req);
} else {
@@ -2541,109 +2546,120 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
{
struct file_info *fi = file->private_data;
+ int ret;
+
+ mutex_lock(&fi->state_mutex);
if (fi->iso_state == RAW1394_ISO_INACTIVE)
- return -EINVAL;
+ ret = -EINVAL;
+ else
+ ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
+
+ mutex_unlock(&fi->state_mutex);
- return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
+ return ret;
}
-/* ioctl is only used for rawiso operations */
-static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
+static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
+ void __user *argp)
+{
+ switch (cmd) {
+ case RAW1394_IOC_ISO_XMIT_INIT:
+ return raw1394_iso_xmit_init(fi, argp);
+ case RAW1394_IOC_ISO_RECV_INIT:
+ return raw1394_iso_recv_init(fi, argp);
+ default:
+ return -EINVAL;
+ }
+}
+
+static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
+ unsigned long arg)
{
- struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg;
- switch (fi->iso_state) {
- case RAW1394_ISO_INACTIVE:
- switch (cmd) {
- case RAW1394_IOC_ISO_XMIT_INIT:
- return raw1394_iso_xmit_init(fi, argp);
- case RAW1394_IOC_ISO_RECV_INIT:
- return raw1394_iso_recv_init(fi, argp);
- default:
- break;
+ switch (cmd) {
+ case RAW1394_IOC_ISO_RECV_START:{
+ int args[3];
+
+ if (copy_from_user(&args[0], argp, sizeof(args)))
+ return -EFAULT;
+ return hpsb_iso_recv_start(fi->iso_handle,
+ args[0], args[1], args[2]);
}
- break;
- case RAW1394_ISO_RECV:
- switch (cmd) {
- case RAW1394_IOC_ISO_RECV_START:{
- /* copy args from user-space */
- int args[3];
- if (copy_from_user
- (&args[0], argp, sizeof(args)))
- return -EFAULT;
- return hpsb_iso_recv_start(fi->iso_handle,
- args[0], args[1],
- args[2]);
- }
- case RAW1394_IOC_ISO_XMIT_RECV_STOP:
- hpsb_iso_stop(fi->iso_handle);
- return 0;
- case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
- return hpsb_iso_recv_listen_channel(fi->iso_handle,
- arg);
- case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
- return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
- arg);
- case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
- /* copy the u64 from user-space */
- u64 mask;
- if (copy_from_user(&mask, argp, sizeof(mask)))
- return -EFAULT;
- return hpsb_iso_recv_set_channel_mask(fi->
- iso_handle,
- mask);
- }
- case RAW1394_IOC_ISO_GET_STATUS:
- return raw1394_iso_get_status(fi, argp);
- case RAW1394_IOC_ISO_RECV_PACKETS:
- return raw1394_iso_recv_packets(fi, argp);
- case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
- return hpsb_iso_recv_release_packets(fi->iso_handle,
- arg);
- case RAW1394_IOC_ISO_RECV_FLUSH:
- return hpsb_iso_recv_flush(fi->iso_handle);
- case RAW1394_IOC_ISO_SHUTDOWN:
- raw1394_iso_shutdown(fi);
- return 0;
- case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
- queue_rawiso_event(fi);
- return 0;
+ case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+ hpsb_iso_stop(fi->iso_handle);
+ return 0;
+ case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+ return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
+ case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+ return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
+ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
+ u64 mask;
+
+ if (copy_from_user(&mask, argp, sizeof(mask)))
+ return -EFAULT;
+ return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
+ mask);
}
- break;
- case RAW1394_ISO_XMIT:
- switch (cmd) {
- case RAW1394_IOC_ISO_XMIT_START:{
- /* copy two ints from user-space */
- int args[2];
- if (copy_from_user
- (&args[0], argp, sizeof(args)))
- return -EFAULT;
- return hpsb_iso_xmit_start(fi->iso_handle,
- args[0], args[1]);
- }
- case RAW1394_IOC_ISO_XMIT_SYNC:
- return hpsb_iso_xmit_sync(fi->iso_handle);
- case RAW1394_IOC_ISO_XMIT_RECV_STOP:
- hpsb_iso_stop(fi->iso_handle);
- return 0;
- case RAW1394_IOC_ISO_GET_STATUS:
- return raw1394_iso_get_status(fi, argp);
- case RAW1394_IOC_ISO_XMIT_PACKETS:
- return raw1394_iso_send_packets(fi, argp);
- case RAW1394_IOC_ISO_SHUTDOWN:
- raw1394_iso_shutdown(fi);
- return 0;
- case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
- queue_rawiso_event(fi);
- return 0;
+ case RAW1394_IOC_ISO_GET_STATUS:
+ return raw1394_iso_get_status(fi, argp);
+ case RAW1394_IOC_ISO_RECV_PACKETS:
+ return raw1394_iso_recv_packets(fi, argp);
+ case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+ return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
+ case RAW1394_IOC_ISO_RECV_FLUSH:
+ return hpsb_iso_recv_flush(fi->iso_handle);
+ case RAW1394_IOC_ISO_SHUTDOWN:
+ raw1394_iso_shutdown(fi);
+ return 0;
+ case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+ queue_rawiso_event(fi);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
+ void __user *argp)
+{
+ switch (cmd) {
+ case RAW1394_IOC_ISO_XMIT_START:{
+ int args[2];
+
+ if (copy_from_user(&args[0], argp, sizeof(args)))
+ return -EFAULT;
+ return hpsb_iso_xmit_start(fi->iso_handle,
+ args[0], args[1]);
}
- break;
+ case RAW1394_IOC_ISO_XMIT_SYNC:
+ return hpsb_iso_xmit_sync(fi->iso_handle);
+ case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+ hpsb_iso_stop(fi->iso_handle);
+ return 0;
+ case RAW1394_IOC_ISO_GET_STATUS:
+ return raw1394_iso_get_status(fi, argp);
+ case RAW1394_IOC_ISO_XMIT_PACKETS:
+ return raw1394_iso_send_packets(fi, argp);
+ case RAW1394_IOC_ISO_SHUTDOWN:
+ raw1394_iso_shutdown(fi);
+ return 0;
+ case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+ queue_rawiso_event(fi);
+ return 0;
default:
- break;
+ return -EINVAL;
}
+}
+
+/* ioctl is only used for rawiso operations */
+static long raw1394_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct file_info *fi = file->private_data;
+ void __user *argp = (void __user *)arg;
+ long ret;
/* state-independent commands */
switch(cmd) {
@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
break;
}
- return -EINVAL;
-}
+ mutex_lock(&fi->state_mutex);
+
+ switch (fi->iso_state) {
+ case RAW1394_ISO_INACTIVE:
+ ret = raw1394_ioctl_inactive(fi, cmd, argp);
+ break;
+ case RAW1394_ISO_RECV:
+ ret = raw1394_ioctl_recv(fi, cmd, arg);
+ break;
+ case RAW1394_ISO_XMIT:
+ ret = raw1394_ioctl_xmit(fi, cmd, argp);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&fi->state_mutex);
-static long raw1394_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- long ret;
- lock_kernel();
- ret = do_raw1394_ioctl(file, cmd, arg);
- unlock_kernel();
return ret;
}
@@ -2700,7 +2725,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
!copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
infos = compat_ptr(infos32);
if (!copy_to_user(&dst->infos, &infos, sizeof infos))
- err = do_raw1394_ioctl(file, cmd, (unsigned long)dst);
+ err = raw1394_ioctl(file, cmd, (unsigned long)dst);
}
return err;
}
@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file,
void __user *argp = (void __user *)arg;
long err;
- lock_kernel();
switch (cmd) {
/* These requests have same format as long as 'int' has same size. */
case RAW1394_IOC_ISO_RECV_INIT:
@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file,
case RAW1394_IOC_ISO_GET_STATUS:
case RAW1394_IOC_ISO_SHUTDOWN:
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
- err = do_raw1394_ioctl(file, cmd, arg);
+ err = raw1394_ioctl(file, cmd, arg);
break;
/* These request have different format. */
case RAW1394_IOC_ISO_RECV_PACKETS32:
@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file,
err = -EINVAL;
break;
}
- unlock_kernel();
return err;
}
@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
INIT_LIST_HEAD(&fi->list);
+ mutex_init(&fi->state_mutex);
fi->state = opened;
INIT_LIST_HEAD(&fi->req_pending);
INIT_LIST_HEAD(&fi->req_complete);
@@ -3010,10 +3034,10 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (device_create_drvdata(
- hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- NULL, RAW1394_DEVICE_NAME))) {
+ (device_create(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+ NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 1d6ad343553..c52f6e6e8af 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work)
static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
{
- struct sbp2_fwhost_info *hi = lu->hi;
struct sbp2_command_info *cmd;
+ struct device *dmadev = lu->hi->host->device.parent;
int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
for (i = 0; i < orbs; i++) {
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
- return -ENOMEM;
- cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
- &cmd->command_orb,
- sizeof(struct sbp2_command_orb),
- DMA_TO_DEVICE);
- cmd->sge_dma = dma_map_single(hi->host->device.parent,
- &cmd->scatter_gather_element,
- sizeof(cmd->scatter_gather_element),
- DMA_TO_DEVICE);
+ goto failed_alloc;
+
+ cmd->command_orb_dma =
+ dma_map_single(dmadev, &cmd->command_orb,
+ sizeof(struct sbp2_command_orb),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dmadev, cmd->command_orb_dma))
+ goto failed_orb;
+
+ cmd->sge_dma =
+ dma_map_single(dmadev, &cmd->scatter_gather_element,
+ sizeof(cmd->scatter_gather_element),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dmadev, cmd->sge_dma))
+ goto failed_sge;
+
INIT_LIST_HEAD(&cmd->list);
list_add_tail(&cmd->list, &lu->cmd_orb_completed);
}
return 0;
+
+failed_sge:
+ dma_unmap_single(dmadev, cmd->command_orb_dma,
+ sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
+failed_orb:
+ kfree(cmd);
+failed_alloc:
+ return -ENOMEM;
}
static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
@@ -641,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
struct sbp2_command_info *cmd)
{
- struct hpsb_host *host = lu->ud->ne->host;
-
- if (cmd->cmd_dma) {
- if (cmd->dma_type == CMD_DMA_SINGLE)
- dma_unmap_single(host->device.parent, cmd->cmd_dma,
- cmd->dma_size, cmd->dma_dir);
- else if (cmd->dma_type == CMD_DMA_PAGE)
- dma_unmap_page(host->device.parent, cmd->cmd_dma,
- cmd->dma_size, cmd->dma_dir);
- /* XXX: Check for CMD_DMA_NONE bug */
- cmd->dma_type = CMD_DMA_NONE;
- cmd->cmd_dma = 0;
- }
- if (cmd->sge_buffer) {
- dma_unmap_sg(host->device.parent, cmd->sge_buffer,
- cmd->dma_size, cmd->dma_dir);
- cmd->sge_buffer = NULL;
- }
+ if (scsi_sg_count(cmd->Current_SCpnt))
+ dma_unmap_sg(lu->ud->ne->host->device.parent,
+ scsi_sglist(cmd->Current_SCpnt),
+ scsi_sg_count(cmd->Current_SCpnt),
+ cmd->Current_SCpnt->sc_data_direction);
list_move_tail(&cmd->list, &lu->cmd_orb_completed);
}
@@ -823,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
#endif
}
+ if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
+ BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
+ SBP2_MAX_SEG_SIZE));
+
/* Prevent unloading of the 1394 host */
if (!try_module_get(hi->host->driver->owner)) {
SBP2_ERR("failed to get a reference on 1394 host driver");
@@ -1494,84 +1500,65 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
return 0;
}
-static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
- struct sbp2_fwhost_info *hi,
- struct sbp2_command_info *cmd,
- unsigned int scsi_use_sg,
- struct scatterlist *sg,
- u32 orb_direction,
- enum dma_data_direction dma_dir)
+static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ struct sbp2_fwhost_info *hi,
+ struct sbp2_command_info *cmd,
+ unsigned int sg_count,
+ struct scatterlist *sg,
+ u32 orb_direction,
+ enum dma_data_direction dma_dir)
{
- cmd->dma_dir = dma_dir;
+ struct device *dmadev = hi->host->device.parent;
+ struct sbp2_unrestricted_page_table *pt;
+ int i, n;
+
+ n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
+ if (n == 0)
+ return -ENOMEM;
+
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 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
- cmd->dma_size = sg->length;
- cmd->dma_type = CMD_DMA_PAGE;
- cmd->cmd_dma = dma_map_page(hi->host->device.parent,
- sg_page(sg), sg->offset,
- cmd->dma_size, cmd->dma_dir);
-
- orb->data_descriptor_lo = cmd->cmd_dma;
- orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
-
+ if (n == 1) {
+ orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
+ orb->data_descriptor_lo = sg_dma_address(sg);
} else {
- struct sbp2_unrestricted_page_table *sg_element =
- &cmd->scatter_gather_element[0];
- u32 sg_count, sg_len;
- dma_addr_t sg_addr;
- int i, count = dma_map_sg(hi->host->device.parent, sg,
- scsi_use_sg, dma_dir);
-
- cmd->dma_size = scsi_use_sg;
- cmd->sge_buffer = sg;
-
- /* use page tables (s/g) */
- orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
- orb->data_descriptor_lo = cmd->sge_dma;
+ pt = &cmd->scatter_gather_element[0];
- /* 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++, sg = sg_next(sg)) {
- sg_len = sg_dma_len(sg);
- sg_addr = sg_dma_address(sg);
- 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++;
- }
+ dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
+ sizeof(cmd->scatter_gather_element),
+ DMA_TO_DEVICE);
+
+ for_each_sg(sg, sg, n, i) {
+ pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
+ pt[i].low = cpu_to_be32(sg_dma_address(sg));
}
- orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
+ ORB_SET_DATA_SIZE(n);
+ orb->data_descriptor_lo = cmd->sge_dma;
- sbp2util_cpu_to_be32_buffer(sg_element,
- (sizeof(struct sbp2_unrestricted_page_table)) *
- sg_count);
+ dma_sync_single_for_device(dmadev, cmd->sge_dma,
+ sizeof(cmd->scatter_gather_element),
+ DMA_TO_DEVICE);
}
+ return 0;
}
-static void sbp2_create_command_orb(struct sbp2_lu *lu,
- struct sbp2_command_info *cmd,
- struct scsi_cmnd *SCpnt)
+static int sbp2_create_command_orb(struct sbp2_lu *lu,
+ struct sbp2_command_info *cmd,
+ struct scsi_cmnd *SCpnt)
{
- struct sbp2_fwhost_info *hi = lu->hi;
+ struct device *dmadev = lu->hi->host->device.parent;
struct sbp2_command_orb *orb = &cmd->command_orb;
- u32 orb_direction;
unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
+ u32 orb_direction;
+ int ret;
+ dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
+ sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
/*
* Set-up our command ORB.
*
@@ -1602,15 +1589,21 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
orb->data_descriptor_hi = 0x0;
orb->data_descriptor_lo = 0x0;
orb->misc |= ORB_SET_DIRECTION(1);
- } else
- sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt),
- scsi_sglist(SCpnt),
- orb_direction, dma_dir);
-
+ ret = 0;
+ } else {
+ ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
+ scsi_sg_count(SCpnt),
+ scsi_sglist(SCpnt),
+ orb_direction, dma_dir);
+ }
sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
memset(orb->cdb, 0, sizeof(orb->cdb));
memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+ dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
+ sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
+ return ret;
}
static void sbp2_link_orb_command(struct sbp2_lu *lu,
@@ -1624,14 +1617,6 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
size_t length;
unsigned long flags;
- dma_sync_single_for_device(hi->host->device.parent,
- cmd->command_orb_dma,
- sizeof(struct sbp2_command_orb),
- DMA_TO_DEVICE);
- dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
- sizeof(cmd->scatter_gather_element),
- DMA_TO_DEVICE);
-
/* check to see if there are any previous orbs to use */
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
last_orb = lu->last_orb;
@@ -1699,9 +1684,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
if (!cmd)
return -EIO;
- sbp2_create_command_orb(lu, cmd, SCpnt);
- sbp2_link_orb_command(lu, cmd);
+ if (sbp2_create_command_orb(lu, cmd, SCpnt))
+ return -ENOMEM;
+ sbp2_link_orb_command(lu, cmd);
return 0;
}
@@ -1789,13 +1775,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
else
cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
if (cmd) {
- dma_sync_single_for_cpu(hi->host->device.parent,
- cmd->command_orb_dma,
- sizeof(struct sbp2_command_orb),
- DMA_TO_DEVICE);
- dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
- sizeof(cmd->scatter_gather_element),
- DMA_TO_DEVICE);
/* Grab SCSI command pointers and check status. */
/*
* FIXME: If the src field in the status is 1, the ORB DMA must
@@ -1912,7 +1891,6 @@ done:
static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
{
- struct sbp2_fwhost_info *hi = lu->hi;
struct list_head *lh;
struct sbp2_command_info *cmd;
unsigned long flags;
@@ -1921,13 +1899,6 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
while (!list_empty(&lu->cmd_orb_inuse)) {
lh = lu->cmd_orb_inuse.next;
cmd = list_entry(lh, struct sbp2_command_info, list);
- dma_sync_single_for_cpu(hi->host->device.parent,
- cmd->command_orb_dma,
- sizeof(struct sbp2_command_orb),
- DMA_TO_DEVICE);
- dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
- sizeof(cmd->scatter_gather_element),
- DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = status << 16;
@@ -2033,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
sdev->start_stop_pwr_cond = 1;
if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+
+ blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
return 0;
}
@@ -2049,7 +2022,6 @@ static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
{
struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
- struct sbp2_fwhost_info *hi = lu->hi;
struct sbp2_command_info *cmd;
unsigned long flags;
@@ -2063,14 +2035,6 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
if (cmd) {
- dma_sync_single_for_cpu(hi->host->device.parent,
- cmd->command_orb_dma,
- sizeof(struct sbp2_command_orb),
- DMA_TO_DEVICE);
- dma_sync_single_for_cpu(hi->host->device.parent,
- cmd->sge_dma,
- sizeof(cmd->scatter_gather_element),
- DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = DID_ABORT << 16;
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 875428bc8d2..c5036f1cc5b 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -139,13 +139,10 @@ struct sbp2_logout_orb {
u32 status_fifo_lo;
} __attribute__((packed));
-#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff)
-#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16)
-
struct sbp2_unrestricted_page_table {
- u32 length_segment_base_hi;
- u32 segment_base_lo;
-} __attribute__((packed));
+ __be32 high;
+ __be32 low;
+};
#define RESP_STATUS_REQUEST_COMPLETE 0x0
#define RESP_STATUS_TRANSPORT_FAILURE 0x1
@@ -216,15 +213,18 @@ struct sbp2_status_block {
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
#define SBP2_SW_VERSION_ENTRY 0x00010483
-
/*
- * SCSI specific definitions
+ * The default maximum s/g segment size of a FireWire controller is
+ * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
+ * be quadlet-aligned, we set the length limit to 0xffff & ~3.
*/
+#define SBP2_MAX_SEG_SIZE 0xfffc
-#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
-/* There is no real limitation of the queue depth (i.e. length of the linked
+/*
+ * There is no real limitation of the queue depth (i.e. length of the linked
* list of command ORBs) at the target. The chosen depth is merely an
- * implementation detail of the sbp2 driver. */
+ * implementation detail of the sbp2 driver.
+ */
#define SBP2_MAX_CMDS 8
#define SBP2_SCSI_STATUS_GOOD 0x0
@@ -240,12 +240,6 @@ struct sbp2_status_block {
* Representations of commands and devices
*/
-enum sbp2_dma_types {
- CMD_DMA_NONE,
- CMD_DMA_PAGE,
- CMD_DMA_SINGLE
-};
-
/* Per SCSI command */
struct sbp2_command_info {
struct list_head list;
@@ -258,11 +252,6 @@ struct sbp2_command_info {
struct sbp2_unrestricted_page_table
scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
dma_addr_t sge_dma;
- void *sge_buffer;
- dma_addr_t cmd_dma;
- enum sbp2_dma_types dma_type;
- unsigned long dma_size;
- enum dma_data_direction dma_dir;
};
/* Per FireWire host */
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 25db6e67fa4..679a918a5cc 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL))
return -EFAULT;
- if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) {
+ if (unlikely(v.buffer >= d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL))
return -EFAULT;
- if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) {
+ if (unlikely(v.buffer > d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
+ if (v.buffer >= d->num_desc - 1) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
+ if (v.buffer >= d->num_desc - 1) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1341,9 +1341,8 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- device_create_drvdata(hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, minor), NULL,
- "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor),
+ NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 922d35f4fc0..a78d35aecee 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3691,9 +3691,9 @@ static void cm_add_one(struct ib_device *ib_device)
cm_dev->ib_device = ib_device;
cm_get_ack_delay(cm_dev);
- cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
- MKDEV(0, 0), NULL,
- "%s", ib_device->name);
+ cm_dev->device = device_create(&cm_class, &ib_device->dev,
+ MKDEV(0, 0), NULL,
+ "%s", ib_device->name);
if (!cm_dev->device) {
kfree(cm_dev);
return;
@@ -3748,6 +3748,7 @@ error1:
cm_remove_port_fs(port);
}
device_unregister(cm_dev->device);
+ kfree(cm_dev);
}
static void cm_remove_one(struct ib_device *ib_device)
@@ -3776,6 +3777,7 @@ static void cm_remove_one(struct ib_device *ib_device)
cm_remove_port_fs(port);
}
device_unregister(cm_dev->device);
+ kfree(cm_dev);
}
static int __init ib_cm_init(void)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 1adf2efd3cb..49c45feccd5 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1697,9 +1697,8 @@ static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
u8 port_num = mad_agent_priv->agent.port_num;
u8 lmc;
- send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
- mad_hdr.method & IB_MGMT_METHOD_RESP;
- rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
+ send_resp = ib_response_mad((struct ib_mad *)wr->send_buf.mad);
+ rcv_resp = ib_response_mad(rwc->recv_buf.mad);
if (send_resp == rcv_resp)
/* both requests, or both responses. GIDs different */
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 268a2d23b7c..8c46f225709 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1016,9 +1016,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
goto err_cdev;
- port->dev = device_create_drvdata(umad_class, device->dma_device,
- port->cdev->dev, port,
- "umad%d", port->dev_num);
+ port->dev = device_create(umad_class, device->dma_device,
+ port->cdev->dev, port,
+ "umad%d", port->dev_num);
if (IS_ERR(port->dev))
goto err_cdev;
@@ -1036,9 +1036,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
goto err_sm_cdev;
- port->sm_dev = device_create_drvdata(umad_class, device->dma_device,
- port->sm_cdev->dev, port,
- "issm%d", port->dev_num);
+ port->sm_dev = device_create(umad_class, device->dma_device,
+ port->sm_cdev->dev, port,
+ "issm%d", port->dev_num);
if (IS_ERR(port->sm_dev))
goto err_sm_cdev;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index aeee856c406..d85af1b6702 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -764,12 +764,9 @@ static void ib_uverbs_add_one(struct ib_device *device)
if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
goto err_cdev;
- uverbs_dev->dev = device_create_drvdata(uverbs_class,
- device->dma_device,
- uverbs_dev->cdev->dev,
- uverbs_dev,
- "uverbs%d",
- uverbs_dev->devnum);
+ uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
+ uverbs_dev->cdev->dev, uverbs_dev,
+ "uverbs%d", uverbs_dev->devnum);
if (IS_ERR(uverbs_dev->dev))
goto err_cdev;
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index 2acf9b62cf9..69580e282af 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -272,7 +272,6 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd,
pr_debug("%s: Invalid QP type: %d\n", __func__,
init_attr->qp_type);
return ERR_PTR(-EINVAL);
- break;
}
if (err) {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index eb778bfd6f6..ecff9804358 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1155,13 +1155,11 @@ static int iwch_query_port(struct ib_device *ibdev,
u8 port, struct ib_port_attr *props)
{
PDBG("%s ibdev %p\n", __func__, ibdev);
+
+ memset(props, 0, sizeof(struct ib_port_attr));
props->max_mtu = IB_MTU_4096;
- props->lid = 0;
- props->lmc = 0;
- props->sm_lid = 0;
- props->sm_sl = 0;
+ props->active_mtu = IB_MTU_2048;
props->state = IB_PORT_ACTIVE;
- props->phys_state = 0;
props->port_cap_flags =
IB_PORT_CM_SUP |
IB_PORT_SNMP_TUNNEL_SUP |
@@ -1170,7 +1168,6 @@ static int iwch_query_port(struct ib_device *ibdev,
IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
props->gid_tbl_len = 1;
props->pkey_tbl_len = 1;
- props->qkey_viol_cntr = 0;
props->active_width = 2;
props->active_speed = 2;
props->max_msg_sz = -1;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1ab919f836a..5d7b7855afb 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -164,6 +164,13 @@ struct ehca_qmap_entry {
u16 reported;
};
+struct ehca_queue_map {
+ struct ehca_qmap_entry *map;
+ unsigned int entries;
+ unsigned int tail;
+ unsigned int left_to_poll;
+};
+
struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -173,8 +180,9 @@ struct ehca_qp {
enum ehca_ext_qp_type ext_type;
enum ib_qp_state state;
struct ipz_queue ipz_squeue;
- struct ehca_qmap_entry *sq_map;
+ struct ehca_queue_map sq_map;
struct ipz_queue ipz_rqueue;
+ struct ehca_queue_map rq_map;
struct h_galpas galpas;
u32 qkey;
u32 real_qp_num;
@@ -204,6 +212,8 @@ struct ehca_qp {
atomic_t nr_events; /* events seen */
wait_queue_head_t wait_completion;
int mig_armed;
+ struct list_head sq_err_node;
+ struct list_head rq_err_node;
};
#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
@@ -233,6 +243,8 @@ struct ehca_cq {
/* mmap counter for resources mapped into user space */
u32 mm_count_queue;
u32 mm_count_galpa;
+ struct list_head sqp_err_list;
+ struct list_head rqp_err_list;
};
enum ehca_mr_flag {
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 5540b276a33..33647a95eb9 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -276,6 +276,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
for (i = 0; i < QP_HASHTAB_LEN; i++)
INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]);
+ INIT_LIST_HEAD(&my_cq->sqp_err_list);
+ INIT_LIST_HEAD(&my_cq->rqp_err_list);
+
if (context) {
struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
struct ehca_create_cq_resp resp;
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index a8a2ea585d2..8f7f282ead6 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -197,6 +197,8 @@ void ehca_poll_eqs(unsigned long data);
int ehca_calc_ipd(struct ehca_shca *shca, int port,
enum ib_rate path_rate, u32 *ipd);
+void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq);
+
#ifdef CONFIG_PPC_64K_PAGES
void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr);
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index b6bcee03673..4dbe2870e01 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -396,6 +396,50 @@ static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue,
queue->is_small = (queue->page_size != 0);
}
+/* needs to be called with cq->spinlock held */
+void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq)
+{
+ struct list_head *list, *node;
+
+ /* TODO: support low latency QPs */
+ if (qp->ext_type == EQPT_LLQP)
+ return;
+
+ if (on_sq) {
+ list = &qp->send_cq->sqp_err_list;
+ node = &qp->sq_err_node;
+ } else {
+ list = &qp->recv_cq->rqp_err_list;
+ node = &qp->rq_err_node;
+ }
+
+ if (list_empty(node))
+ list_add_tail(node, list);
+
+ return;
+}
+
+static void del_from_err_list(struct ehca_cq *cq, struct list_head *node)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->spinlock, flags);
+
+ if (!list_empty(node))
+ list_del_init(node);
+
+ spin_unlock_irqrestore(&cq->spinlock, flags);
+}
+
+static void reset_queue_map(struct ehca_queue_map *qmap)
+{
+ int i;
+
+ qmap->tail = 0;
+ for (i = 0; i < qmap->entries; i++)
+ qmap->map[i].reported = 1;
+}
+
/*
* Create an ib_qp struct that is either a QP or an SRQ, depending on
* the value of the is_srq parameter. If init_attr and srq_init_attr share
@@ -407,12 +451,11 @@ static struct ehca_qp *internal_create_qp(
struct ib_srq_init_attr *srq_init_attr,
struct ib_udata *udata, int is_srq)
{
- struct ehca_qp *my_qp;
+ struct ehca_qp *my_qp, *my_srq = NULL;
struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
ib_device);
struct ib_ucontext *context = NULL;
- u32 nr_qes;
u64 h_ret;
int is_llqp = 0, has_srq = 0;
int qp_type, max_send_sge, max_recv_sge, ret;
@@ -457,8 +500,7 @@ static struct ehca_qp *internal_create_qp(
/* handle SRQ base QPs */
if (init_attr->srq) {
- struct ehca_qp *my_srq =
- container_of(init_attr->srq, struct ehca_qp, ib_srq);
+ my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq);
has_srq = 1;
parms.ext_type = EQPT_SRQBASE;
@@ -716,15 +758,19 @@ static struct ehca_qp *internal_create_qp(
"and pages ret=%i", ret);
goto create_qp_exit2;
}
- nr_qes = my_qp->ipz_squeue.queue_length /
+
+ my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
my_qp->ipz_squeue.qe_size;
- my_qp->sq_map = vmalloc(nr_qes *
+ my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
sizeof(struct ehca_qmap_entry));
- if (!my_qp->sq_map) {
+ if (!my_qp->sq_map.map) {
ehca_err(pd->device, "Couldn't allocate squeue "
"map ret=%i", ret);
goto create_qp_exit3;
}
+ INIT_LIST_HEAD(&my_qp->sq_err_node);
+ /* to avoid the generation of bogus flush CQEs */
+ reset_queue_map(&my_qp->sq_map);
}
if (HAS_RQ(my_qp)) {
@@ -736,6 +782,25 @@ static struct ehca_qp *internal_create_qp(
"and pages ret=%i", ret);
goto create_qp_exit4;
}
+
+ my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
+ my_qp->ipz_rqueue.qe_size;
+ my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
+ sizeof(struct ehca_qmap_entry));
+ if (!my_qp->rq_map.map) {
+ ehca_err(pd->device, "Couldn't allocate squeue "
+ "map ret=%i", ret);
+ goto create_qp_exit5;
+ }
+ INIT_LIST_HEAD(&my_qp->rq_err_node);
+ /* to avoid the generation of bogus flush CQEs */
+ reset_queue_map(&my_qp->rq_map);
+ } else if (init_attr->srq) {
+ /* this is a base QP, use the queue map of the SRQ */
+ my_qp->rq_map = my_srq->rq_map;
+ INIT_LIST_HEAD(&my_qp->rq_err_node);
+
+ my_qp->ipz_rqueue = my_srq->ipz_rqueue;
}
if (is_srq) {
@@ -799,7 +864,7 @@ static struct ehca_qp *internal_create_qp(
if (ret) {
ehca_err(pd->device,
"Couldn't assign qp to send_cq ret=%i", ret);
- goto create_qp_exit6;
+ goto create_qp_exit7;
}
}
@@ -825,25 +890,29 @@ static struct ehca_qp *internal_create_qp(
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
- goto create_qp_exit7;
+ goto create_qp_exit8;
}
}
return my_qp;
-create_qp_exit7:
+create_qp_exit8:
ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
-create_qp_exit6:
+create_qp_exit7:
kfree(my_qp->mod_qp_parm);
+create_qp_exit6:
+ if (HAS_RQ(my_qp))
+ vfree(my_qp->rq_map.map);
+
create_qp_exit5:
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
create_qp_exit4:
if (HAS_SQ(my_qp))
- vfree(my_qp->sq_map);
+ vfree(my_qp->sq_map.map);
create_qp_exit3:
if (HAS_SQ(my_qp))
@@ -1035,6 +1104,101 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
return 0;
}
+static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
+ struct ehca_queue_map *qmap)
+{
+ void *wqe_v;
+ u64 q_ofs;
+ u32 wqe_idx;
+
+ /* convert real to abs address */
+ wqe_p = wqe_p & (~(1UL << 63));
+
+ wqe_v = abs_to_virt(wqe_p);
+
+ if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
+ ehca_gen_err("Invalid offset for calculating left cqes "
+ "wqe_p=%#lx wqe_v=%p\n", wqe_p, wqe_v);
+ return -EFAULT;
+ }
+
+ wqe_idx = q_ofs / ipz_queue->qe_size;
+ if (wqe_idx < qmap->tail)
+ qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx;
+ else
+ qmap->left_to_poll = wqe_idx - qmap->tail;
+
+ return 0;
+}
+
+static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca)
+{
+ u64 h_ret;
+ void *send_wqe_p, *recv_wqe_p;
+ int ret;
+ unsigned long flags;
+ int qp_num = my_qp->ib_qp.qp_num;
+
+ /* this hcall is not supported on base QPs */
+ if (my_qp->ext_type != EQPT_SRQBASE) {
+ /* get send and receive wqe pointer */
+ h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,
+ my_qp->ipz_qp_handle, &my_qp->pf,
+ &send_wqe_p, &recv_wqe_p, 4);
+ if (h_ret != H_SUCCESS) {
+ ehca_err(&shca->ib_device, "disable_and_get_wqe() "
+ "failed ehca_qp=%p qp_num=%x h_ret=%li",
+ my_qp, qp_num, h_ret);
+ return ehca2ib_return_code(h_ret);
+ }
+
+ /*
+ * acquire lock to ensure that nobody is polling the cq which
+ * could mean that the qmap->tail pointer is in an
+ * inconsistent state.
+ */
+ spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+ ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue,
+ &my_qp->sq_map);
+ spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+ if (ret)
+ return ret;
+
+
+ spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+ ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue,
+ &my_qp->rq_map);
+ spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
+ if (ret)
+ return ret;
+ } else {
+ spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+ my_qp->sq_map.left_to_poll = 0;
+ spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+
+ spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+ my_qp->rq_map.left_to_poll = 0;
+ spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
+ }
+
+ /* this assures flush cqes being generated only for pending wqes */
+ if ((my_qp->sq_map.left_to_poll == 0) &&
+ (my_qp->rq_map.left_to_poll == 0)) {
+ spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+ ehca_add_to_err_list(my_qp, 1);
+ spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+
+ if (HAS_RQ(my_qp)) {
+ spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+ ehca_add_to_err_list(my_qp, 0);
+ spin_unlock_irqrestore(&my_qp->recv_cq->spinlock,
+ flags);
+ }
+ }
+
+ return 0;
+}
+
/*
* internal_modify_qp with circumvention to handle aqp0 properly
* smi_reset2init indicates if this is an internal reset-to-init-call for
@@ -1539,10 +1703,27 @@ static int internal_modify_qp(struct ib_qp *ibqp,
goto modify_qp_exit2;
}
}
+ if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) {
+ ret = check_for_left_cqes(my_qp, shca);
+ if (ret)
+ goto modify_qp_exit2;
+ }
if (statetrans == IB_QPST_ANY2RESET) {
ipz_qeit_reset(&my_qp->ipz_rqueue);
ipz_qeit_reset(&my_qp->ipz_squeue);
+
+ if (qp_cur_state == IB_QPS_ERR) {
+ del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
+
+ if (HAS_RQ(my_qp))
+ del_from_err_list(my_qp->recv_cq,
+ &my_qp->rq_err_node);
+ }
+ reset_queue_map(&my_qp->sq_map);
+
+ if (HAS_RQ(my_qp))
+ reset_queue_map(&my_qp->rq_map);
}
if (attr_mask & IB_QP_QKEY)
@@ -1958,6 +2139,16 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
idr_remove(&ehca_qp_idr, my_qp->token);
write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ /*
+ * SRQs will never get into an error list and do not have a recv_cq,
+ * so we need to skip them here.
+ */
+ if (HAS_RQ(my_qp) && !IS_SRQ(my_qp))
+ del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
+
+ if (HAS_SQ(my_qp))
+ del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
+
/* now wait until all pending events have completed */
wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events));
@@ -1983,7 +2174,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
if (qp_type == IB_QPT_GSI) {
struct ib_event event;
ehca_info(dev, "device %s: port %x is inactive.",
- shca->ib_device.name, port_num);
+ shca->ib_device.name, port_num);
event.device = &shca->ib_device;
event.event = IB_EVENT_PORT_ERR;
event.element.port_num = port_num;
@@ -1991,11 +2182,15 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
ib_dispatch_event(&event);
}
- if (HAS_RQ(my_qp))
+ if (HAS_RQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+
+ vfree(my_qp->rq_map.map);
+ }
if (HAS_SQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
- vfree(my_qp->sq_map);
+
+ vfree(my_qp->sq_map.map);
}
kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 4426d82fe79..64928079eaf 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -53,9 +53,25 @@
/* in RC traffic, insert an empty RDMA READ every this many packets */
#define ACK_CIRC_THRESHOLD 2000000
+static u64 replace_wr_id(u64 wr_id, u16 idx)
+{
+ u64 ret;
+
+ ret = wr_id & ~QMAP_IDX_MASK;
+ ret |= idx & QMAP_IDX_MASK;
+
+ return ret;
+}
+
+static u16 get_app_wr_id(u64 wr_id)
+{
+ return wr_id & QMAP_IDX_MASK;
+}
+
static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
struct ehca_wqe *wqe_p,
- struct ib_recv_wr *recv_wr)
+ struct ib_recv_wr *recv_wr,
+ u32 rq_map_idx)
{
u8 cnt_ds;
if (unlikely((recv_wr->num_sge < 0) ||
@@ -69,7 +85,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
/* clear wqe header until sglist */
memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
- wqe_p->work_request_id = recv_wr->wr_id;
+ wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx);
wqe_p->nr_of_data_seg = recv_wr->num_sge;
for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) {
@@ -146,6 +162,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
u64 dma_length;
struct ehca_av *my_av;
u32 remote_qkey = send_wr->wr.ud.remote_qkey;
+ struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx];
if (unlikely((send_wr->num_sge < 0) ||
(send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) {
@@ -158,11 +175,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
/* clear wqe header until sglist */
memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
- wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK;
- wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK;
+ wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx);
- qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK;
- qp->sq_map[sq_map_idx].reported = 0;
+ qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id);
+ qmap_entry->reported = 0;
switch (send_wr->opcode) {
case IB_WR_SEND:
@@ -496,7 +512,9 @@ static int internal_post_recv(struct ehca_qp *my_qp,
struct ehca_wqe *wqe_p;
int wqe_cnt = 0;
int ret = 0;
+ u32 rq_map_idx;
unsigned long flags;
+ struct ehca_qmap_entry *qmap_entry;
if (unlikely(!HAS_RQ(my_qp))) {
ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d",
@@ -524,8 +542,15 @@ static int internal_post_recv(struct ehca_qp *my_qp,
}
goto post_recv_exit0;
}
+ /*
+ * Get the index of the WQE in the recv queue. The same index
+ * is used for writing into the rq_map.
+ */
+ rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size;
+
/* write a RECV WQE into the QUEUE */
- ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr);
+ ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr,
+ rq_map_idx);
/*
* if something failed,
* reset the free entry pointer to the start value
@@ -540,6 +565,11 @@ static int internal_post_recv(struct ehca_qp *my_qp,
}
goto post_recv_exit0;
}
+
+ qmap_entry = &my_qp->rq_map.map[rq_map_idx];
+ qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id);
+ qmap_entry->reported = 0;
+
wqe_cnt++;
} /* eof for cur_recv_wr */
@@ -596,10 +626,12 @@ static const u8 ib_wc_opcode[255] = {
/* internal function to poll one entry of cq */
static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
{
- int ret = 0;
+ int ret = 0, qmap_tail_idx;
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
struct ehca_cqe *cqe;
struct ehca_qp *my_qp;
+ struct ehca_qmap_entry *qmap_entry;
+ struct ehca_queue_map *qmap;
int cqe_count = 0, is_error;
repoll:
@@ -674,27 +706,52 @@ repoll:
goto repoll;
wc->qp = &my_qp->ib_qp;
- if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) {
- struct ehca_qmap_entry *qmap_entry;
+ if (is_error) {
/*
- * We got a send completion and need to restore the original
- * wr_id.
+ * set left_to_poll to 0 because in error state, we will not
+ * get any additional CQEs
*/
- qmap_entry = &my_qp->sq_map[cqe->work_request_id &
- QMAP_IDX_MASK];
+ ehca_add_to_err_list(my_qp, 1);
+ my_qp->sq_map.left_to_poll = 0;
- if (qmap_entry->reported) {
- ehca_warn(cq->device, "Double cqe on qp_num=%#x",
- my_qp->real_qp_num);
- /* found a double cqe, discard it and read next one */
- goto repoll;
- }
- wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK;
- wc->wr_id |= qmap_entry->app_wr_id;
- qmap_entry->reported = 1;
- } else
+ if (HAS_RQ(my_qp))
+ ehca_add_to_err_list(my_qp, 0);
+ my_qp->rq_map.left_to_poll = 0;
+ }
+
+ qmap_tail_idx = get_app_wr_id(cqe->work_request_id);
+ if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT))
+ /* We got a send completion. */
+ qmap = &my_qp->sq_map;
+ else
/* We got a receive completion. */
- wc->wr_id = cqe->work_request_id;
+ qmap = &my_qp->rq_map;
+
+ qmap_entry = &qmap->map[qmap_tail_idx];
+ if (qmap_entry->reported) {
+ ehca_warn(cq->device, "Double cqe on qp_num=%#x",
+ my_qp->real_qp_num);
+ /* found a double cqe, discard it and read next one */
+ goto repoll;
+ }
+
+ wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id);
+ qmap_entry->reported = 1;
+
+ /* this is a proper completion, we need to advance the tail pointer */
+ if (++qmap->tail == qmap->entries)
+ qmap->tail = 0;
+
+ /* if left_to_poll is decremented to 0, add the QP to the error list */
+ if (qmap->left_to_poll > 0) {
+ qmap->left_to_poll--;
+ if ((my_qp->sq_map.left_to_poll == 0) &&
+ (my_qp->rq_map.left_to_poll == 0)) {
+ ehca_add_to_err_list(my_qp, 1);
+ if (HAS_RQ(my_qp))
+ ehca_add_to_err_list(my_qp, 0);
+ }
+ }
/* eval ib_wc_opcode */
wc->opcode = ib_wc_opcode[cqe->optype]-1;
@@ -733,13 +790,88 @@ poll_cq_one_exit0:
return ret;
}
+static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
+ struct ib_wc *wc, int num_entries,
+ struct ipz_queue *ipz_queue, int on_sq)
+{
+ int nr = 0;
+ struct ehca_wqe *wqe;
+ u64 offset;
+ struct ehca_queue_map *qmap;
+ struct ehca_qmap_entry *qmap_entry;
+
+ if (on_sq)
+ qmap = &my_qp->sq_map;
+ else
+ qmap = &my_qp->rq_map;
+
+ qmap_entry = &qmap->map[qmap->tail];
+
+ while ((nr < num_entries) && (qmap_entry->reported == 0)) {
+ /* generate flush CQE */
+ memset(wc, 0, sizeof(*wc));
+
+ offset = qmap->tail * ipz_queue->qe_size;
+ wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset);
+ if (!wqe) {
+ ehca_err(cq->device, "Invalid wqe offset=%#lx on "
+ "qp_num=%#x", offset, my_qp->real_qp_num);
+ return nr;
+ }
+
+ wc->wr_id = replace_wr_id(wqe->work_request_id,
+ qmap_entry->app_wr_id);
+
+ if (on_sq) {
+ switch (wqe->optype) {
+ case WQE_OPTYPE_SEND:
+ wc->opcode = IB_WC_SEND;
+ break;
+ case WQE_OPTYPE_RDMAWRITE:
+ wc->opcode = IB_WC_RDMA_WRITE;
+ break;
+ case WQE_OPTYPE_RDMAREAD:
+ wc->opcode = IB_WC_RDMA_READ;
+ break;
+ default:
+ ehca_err(cq->device, "Invalid optype=%x",
+ wqe->optype);
+ return nr;
+ }
+ } else
+ wc->opcode = IB_WC_RECV;
+
+ if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) {
+ wc->ex.imm_data = wqe->immediate_data;
+ wc->wc_flags |= IB_WC_WITH_IMM;
+ }
+
+ wc->status = IB_WC_WR_FLUSH_ERR;
+
+ wc->qp = &my_qp->ib_qp;
+
+ /* mark as reported and advance tail pointer */
+ qmap_entry->reported = 1;
+ if (++qmap->tail == qmap->entries)
+ qmap->tail = 0;
+ qmap_entry = &qmap->map[qmap->tail];
+
+ wc++; nr++;
+ }
+
+ return nr;
+
+}
+
int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
{
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
int nr;
+ struct ehca_qp *err_qp;
struct ib_wc *current_wc = wc;
int ret = 0;
unsigned long flags;
+ int entries_left = num_entries;
if (num_entries < 1) {
ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
@@ -749,15 +881,40 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
}
spin_lock_irqsave(&my_cq->spinlock, flags);
- for (nr = 0; nr < num_entries; nr++) {
+
+ /* generate flush cqes for send queues */
+ list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) {
+ nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
+ &err_qp->ipz_squeue, 1);
+ entries_left -= nr;
+ current_wc += nr;
+
+ if (entries_left == 0)
+ break;
+ }
+
+ /* generate flush cqes for receive queues */
+ list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) {
+ nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
+ &err_qp->ipz_rqueue, 0);
+ entries_left -= nr;
+ current_wc += nr;
+
+ if (entries_left == 0)
+ break;
+ }
+
+ for (nr = 0; nr < entries_left; nr++) {
ret = ehca_poll_cq_one(cq, current_wc);
if (ret)
break;
current_wc++;
} /* eof for nr */
+ entries_left -= nr;
+
spin_unlock_irqrestore(&my_cq->spinlock, flags);
if (ret == -EAGAIN || !ret)
- ret = nr;
+ ret = num_entries - entries_left;
poll_cq_exit0:
return ret;
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 56c0eda3c07..1af1f3a907c 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
goto err_cdev;
}
- device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
+ device = device_create(ipath_class, NULL, dev, NULL, name);
if (IS_ERR(device)) {
ret = PTR_ERR(device);
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 97710522624..7b93cda1a4b 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -675,7 +675,8 @@ static void send_rc_ack(struct ipath_qp *qp)
hdr.lrh[0] = cpu_to_be16(lrh0);
hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC);
- hdr.lrh[3] = cpu_to_be16(dd->ipath_lid);
+ hdr.lrh[3] = cpu_to_be16(dd->ipath_lid |
+ qp->remote_ah_attr.src_path_bits);
ohdr->bth[0] = cpu_to_be32(bth0);
ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK);
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index af051f75766..fc0f6d9e603 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -618,7 +618,8 @@ void ipath_make_ruc_header(struct ipath_ibdev *dev, struct ipath_qp *qp,
qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
- qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid);
+ qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid |
+ qp->remote_ah_attr.src_path_bits);
bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index);
bth0 |= extra_bytes << 20;
ohdr->bth[0] = cpu_to_be32(bth0 | (1 << 22));
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index b766e40e9eb..eabc4247860 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -340,9 +340,16 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr)
int acc;
int ret;
unsigned long flags;
+ struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
spin_lock_irqsave(&qp->s_lock, flags);
+ if (qp->ibqp.qp_type != IB_QPT_SMI &&
+ !(dd->ipath_flags & IPATH_LINKACTIVE)) {
+ ret = -ENETDOWN;
+ goto bail;
+ }
+
/* Check that state is OK to post send. */
if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK)))
goto bail_inval;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index f29dbb767e8..baa01deb243 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1058,6 +1058,9 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
else
sqd_event = 0;
+ if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ context->rlkey |= (1 << 4);
+
/*
* Before passing a kernel QP to the HW, make sure that the
* ownership bits of the send queue are set and the SQ
@@ -1342,6 +1345,12 @@ static __be32 convert_access(int acc)
static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
{
struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
+ int i;
+
+ for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i)
+ wr->wr.fast_reg.page_list->page_list[i] =
+ cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] |
+ MLX4_MTT_FLAG_PRESENT);
fseg->flags = convert_access(wr->wr.fast_reg.access_flags);
fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey);
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
index cc440f90000..65ad359fdf1 100644
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -149,18 +149,10 @@ void mthca_start_catas_poll(struct mthca_dev *dev)
((pci_resource_len(dev->pdev, 0) - 1) &
dev->catas_err.addr);
- if (!request_mem_region(addr, dev->catas_err.size * 4,
- DRV_NAME)) {
- mthca_warn(dev, "couldn't request catastrophic error region "
- "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
- return;
- }
-
dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4);
if (!dev->catas_err.map) {
mthca_warn(dev, "couldn't map catastrophic error region "
"at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
- release_mem_region(addr, dev->catas_err.size * 4);
return;
}
@@ -175,13 +167,8 @@ void mthca_stop_catas_poll(struct mthca_dev *dev)
{
del_timer_sync(&dev->catas_err.timer);
- if (dev->catas_err.map) {
+ if (dev->catas_err.map)
iounmap(dev->catas_err.map);
- release_mem_region(pci_resource_start(dev->pdev, 0) +
- ((pci_resource_len(dev->pdev, 0) - 1) &
- dev->catas_err.addr),
- dev->catas_err.size * 4);
- }
spin_lock_irq(&catas_lock);
list_del(&dev->catas_err.list);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index cc6858f0b65..28f0e0c40d7 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -652,27 +652,13 @@ static int mthca_map_reg(struct mthca_dev *dev,
{
unsigned long base = pci_resource_start(dev->pdev, 0);
- if (!request_mem_region(base + offset, size, DRV_NAME))
- return -EBUSY;
-
*map = ioremap(base + offset, size);
- if (!*map) {
- release_mem_region(base + offset, size);
+ if (!*map)
return -ENOMEM;
- }
return 0;
}
-static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset,
- unsigned long size, void __iomem *map)
-{
- unsigned long base = pci_resource_start(dev->pdev, 0);
-
- release_mem_region(base + offset, size);
- iounmap(map);
-}
-
static int mthca_map_eq_regs(struct mthca_dev *dev)
{
if (mthca_is_memfree(dev)) {
@@ -699,9 +685,7 @@ static int mthca_map_eq_regs(struct mthca_dev *dev)
dev->fw.arbel.eq_arm_base) + 4, 4,
&dev->eq_regs.arbel.eq_arm)) {
mthca_err(dev, "Couldn't map EQ arm register, aborting.\n");
- mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
- dev->clr_base);
+ iounmap(dev->clr_base);
return -ENOMEM;
}
@@ -710,12 +694,8 @@ static int mthca_map_eq_regs(struct mthca_dev *dev)
MTHCA_EQ_SET_CI_SIZE,
&dev->eq_regs.arbel.eq_set_ci_base)) {
mthca_err(dev, "Couldn't map EQ CI register, aborting.\n");
- mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.eq_arm_base) + 4, 4,
- dev->eq_regs.arbel.eq_arm);
- mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
- dev->clr_base);
+ iounmap(dev->eq_regs.arbel.eq_arm);
+ iounmap(dev->clr_base);
return -ENOMEM;
}
} else {
@@ -731,8 +711,7 @@ static int mthca_map_eq_regs(struct mthca_dev *dev)
&dev->eq_regs.tavor.ecr_base)) {
mthca_err(dev, "Couldn't map ecr register, "
"aborting.\n");
- mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
- dev->clr_base);
+ iounmap(dev->clr_base);
return -ENOMEM;
}
}
@@ -744,22 +723,12 @@ static int mthca_map_eq_regs(struct mthca_dev *dev)
static void mthca_unmap_eq_regs(struct mthca_dev *dev)
{
if (mthca_is_memfree(dev)) {
- mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.eq_set_ci_base,
- MTHCA_EQ_SET_CI_SIZE,
- dev->eq_regs.arbel.eq_set_ci_base);
- mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.eq_arm_base) + 4, 4,
- dev->eq_regs.arbel.eq_arm);
- mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
- dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
- dev->clr_base);
+ iounmap(dev->eq_regs.arbel.eq_set_ci_base);
+ iounmap(dev->eq_regs.arbel.eq_arm);
+ iounmap(dev->clr_base);
} else {
- mthca_unmap_reg(dev, MTHCA_ECR_BASE,
- MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
- dev->eq_regs.tavor.ecr_base);
- mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
- dev->clr_base);
+ iounmap(dev->eq_regs.tavor.ecr_base);
+ iounmap(dev->clr_base);
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index fb9f91b60f3..52f60f4eea0 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -921,58 +921,6 @@ err_uar_table_free:
return err;
}
-static int mthca_request_regions(struct pci_dev *pdev, int ddr_hidden)
-{
- int err;
-
- /*
- * We can't just use pci_request_regions() because the MSI-X
- * table is right in the middle of the first BAR. If we did
- * pci_request_region and grab all of the first BAR, then
- * setting up MSI-X would fail, since the PCI core wants to do
- * request_mem_region on the MSI-X vector table.
- *
- * So just request what we need right now, and request any
- * other regions we need when setting up EQs.
- */
- if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
- MTHCA_HCR_SIZE, DRV_NAME))
- return -EBUSY;
-
- err = pci_request_region(pdev, 2, DRV_NAME);
- if (err)
- goto err_bar2_failed;
-
- if (!ddr_hidden) {
- err = pci_request_region(pdev, 4, DRV_NAME);
- if (err)
- goto err_bar4_failed;
- }
-
- return 0;
-
-err_bar4_failed:
- pci_release_region(pdev, 2);
-
-err_bar2_failed:
- release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
- MTHCA_HCR_SIZE);
-
- return err;
-}
-
-static void mthca_release_regions(struct pci_dev *pdev,
- int ddr_hidden)
-{
- if (!ddr_hidden)
- pci_release_region(pdev, 4);
-
- pci_release_region(pdev, 2);
-
- release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
- MTHCA_HCR_SIZE);
-}
-
static int mthca_enable_msi_x(struct mthca_dev *mdev)
{
struct msix_entry entries[3];
@@ -1059,7 +1007,7 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM))
ddr_hidden = 1;
- err = mthca_request_regions(pdev, ddr_hidden);
+ err = pci_request_regions(pdev, DRV_NAME);
if (err) {
dev_err(&pdev->dev, "Cannot obtain PCI resources, "
"aborting.\n");
@@ -1196,7 +1144,7 @@ err_free_dev:
ib_dealloc_device(&mdev->ib_dev);
err_free_res:
- mthca_release_regions(pdev, ddr_hidden);
+ pci_release_regions(pdev);
err_disable_pdev:
pci_disable_device(pdev);
@@ -1240,8 +1188,7 @@ static void __mthca_remove_one(struct pci_dev *pdev)
pci_disable_msix(pdev);
ib_dealloc_device(&mdev->ib_dev);
- mthca_release_regions(pdev, mdev->mthca_flags &
- MTHCA_FLAG_DDR_HIDDEN);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index b0cab64e5e3..a2b04d62b1a 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -70,27 +70,31 @@ int interrupt_mod_interval = 0;
/* Interoperability */
int mpa_version = 1;
-module_param(mpa_version, int, 0);
+module_param(mpa_version, int, 0644);
MODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)");
/* Interoperability */
int disable_mpa_crc = 0;
-module_param(disable_mpa_crc, int, 0);
+module_param(disable_mpa_crc, int, 0644);
MODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC");
unsigned int send_first = 0;
-module_param(send_first, int, 0);
+module_param(send_first, int, 0644);
MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
unsigned int nes_drv_opt = 0;
-module_param(nes_drv_opt, int, 0);
+module_param(nes_drv_opt, int, 0644);
MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
unsigned int nes_debug_level = 0;
module_param_named(debug_level, nes_debug_level, uint, 0644);
MODULE_PARM_DESC(debug_level, "Enable debug output level");
+unsigned int wqm_quanta = 0x10000;
+module_param(wqm_quanta, int, 0644);
+MODULE_PARM_DESC(wqm_quanta, "WQM quanta");
+
LIST_HEAD(nes_adapter_list);
static LIST_HEAD(nes_dev_list);
@@ -557,12 +561,32 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i
goto bail5;
}
nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;
+ nesdev->nesadapter->wqm_quanta = wqm_quanta;
/* nesdev->base_doorbell_index =
nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */
nesdev->base_doorbell_index = 1;
nesdev->doorbell_start = nesdev->nesadapter->doorbell_start;
- nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % nesdev->nesadapter->port_count;
+ if (nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+ switch (PCI_FUNC(nesdev->pcidev->devfn) %
+ nesdev->nesadapter->port_count) {
+ case 1:
+ nesdev->mac_index = 2;
+ break;
+ case 2:
+ nesdev->mac_index = 1;
+ break;
+ case 3:
+ nesdev->mac_index = 3;
+ break;
+ case 0:
+ default:
+ nesdev->mac_index = 0;
+ }
+ } else {
+ nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) %
+ nesdev->nesadapter->port_count;
+ }
tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev);
@@ -581,7 +605,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i
nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) |
(1 << (PCI_FUNC(nesdev->pcidev->devfn)+16));
if (PCI_FUNC(nesdev->pcidev->devfn) < 4) {
- nesdev->int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+24));
+ nesdev->int_req |= (1 << (PCI_FUNC(nesdev->mac_index)+24));
}
/* TODO: This really should be the first driver to load, not function 0 */
@@ -772,14 +796,14 @@ static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf)
list_for_each_entry(nesdev, &nes_dev_list, list) {
if (i == ee_flsh_adapter) {
- devfn = nesdev->nesadapter->devfn;
- bus_number = nesdev->nesadapter->bus_number;
+ devfn = nesdev->pcidev->devfn;
+ bus_number = nesdev->pcidev->bus->number;
break;
}
i++;
}
- return snprintf(buf, PAGE_SIZE, "%x:%x", bus_number, devfn);
+ return snprintf(buf, PAGE_SIZE, "%x:%x\n", bus_number, devfn);
}
static ssize_t nes_store_adapter(struct device_driver *ddp,
@@ -1050,6 +1074,55 @@ static ssize_t nes_store_idx_data(struct device_driver *ddp,
return strnlen(buf, count);
}
+
+/**
+ * nes_show_wqm_quanta
+ */
+static ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf)
+{
+ u32 wqm_quanta_value = 0xdead;
+ u32 i = 0;
+ struct nes_device *nesdev;
+
+ list_for_each_entry(nesdev, &nes_dev_list, list) {
+ if (i == ee_flsh_adapter) {
+ wqm_quanta_value = nesdev->nesadapter->wqm_quanta;
+ break;
+ }
+ i++;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", wqm_quanta);
+}
+
+
+/**
+ * nes_store_wqm_quanta
+ */
+static ssize_t nes_store_wqm_quanta(struct device_driver *ddp,
+ const char *buf, size_t count)
+{
+ unsigned long wqm_quanta_value;
+ u32 wqm_config1;
+ u32 i = 0;
+ struct nes_device *nesdev;
+
+ strict_strtoul(buf, 0, &wqm_quanta_value);
+ list_for_each_entry(nesdev, &nes_dev_list, list) {
+ if (i == ee_flsh_adapter) {
+ nesdev->nesadapter->wqm_quanta = wqm_quanta_value;
+ wqm_config1 = nes_read_indexed(nesdev,
+ NES_IDX_WQM_CONFIG1);
+ nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1,
+ ((wqm_quanta_value << 1) |
+ (wqm_config1 & 0x00000001)));
+ break;
+ }
+ i++;
+ }
+ return strnlen(buf, count);
+}
+
static DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR,
nes_show_adapter, nes_store_adapter);
static DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR,
@@ -1068,6 +1141,8 @@ static DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR,
nes_show_idx_addr, nes_store_idx_addr);
static DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR,
nes_show_idx_data, nes_store_idx_data);
+static DRIVER_ATTR(wqm_quanta, S_IRUSR | S_IWUSR,
+ nes_show_wqm_quanta, nes_store_wqm_quanta);
static int nes_create_driver_sysfs(struct pci_driver *drv)
{
@@ -1081,6 +1156,7 @@ static int nes_create_driver_sysfs(struct pci_driver *drv)
error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data);
error |= driver_create_file(&drv->driver, &driver_attr_idx_addr);
error |= driver_create_file(&drv->driver, &driver_attr_idx_data);
+ error |= driver_create_file(&drv->driver, &driver_attr_wqm_quanta);
return error;
}
@@ -1095,6 +1171,7 @@ static void nes_remove_driver_sysfs(struct pci_driver *drv)
driver_remove_file(&drv->driver, &driver_attr_nonidx_data);
driver_remove_file(&drv->driver, &driver_attr_idx_addr);
driver_remove_file(&drv->driver, &driver_attr_idx_data);
+ driver_remove_file(&drv->driver, &driver_attr_wqm_quanta);
}
/**
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 8eb7ae96974..1595dc7bba9 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -169,7 +169,7 @@ extern int disable_mpa_crc;
extern unsigned int send_first;
extern unsigned int nes_drv_opt;
extern unsigned int nes_debug_level;
-
+extern unsigned int wqm_quanta;
extern struct list_head nes_adapter_list;
extern atomic_t cm_connects;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 9f0b964b2c9..2caf9da81ad 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -52,7 +52,7 @@
#include <linux/random.h>
#include <linux/list.h>
#include <linux/threads.h>
-
+#include <net/arp.h>
#include <net/neighbour.h>
#include <net/route.h>
#include <net/ip_fib.h>
@@ -1019,23 +1019,43 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
/**
- * nes_addr_send_arp
+ * nes_addr_resolve_neigh
*/
-static void nes_addr_send_arp(u32 dst_ip)
+static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
{
struct rtable *rt;
struct flowi fl;
+ struct neighbour *neigh;
+ int rc = -1;
+ DECLARE_MAC_BUF(mac);
memset(&fl, 0, sizeof fl);
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
if (ip_route_output_key(&init_net, &rt, &fl)) {
printk("%s: ip_route_output_key failed for 0x%08X\n",
__func__, dst_ip);
- return;
+ return rc;
+ }
+
+ neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev);
+ if (neigh) {
+ if (neigh->nud_state & NUD_VALID) {
+ nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
+ " is %s, Gateway is 0x%08X \n", dst_ip,
+ print_mac(mac, neigh->ha), ntohl(rt->rt_gateway));
+ nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
+ dst_ip, NES_ARP_ADD);
+ rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
+ NES_ARP_RESOLVE);
+ }
+ neigh_release(neigh);
}
- neigh_event_send(rt->u.dst.neighbour, NULL);
+ if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+ neigh_event_send(rt->u.dst.neighbour, NULL);
+
ip_rt_put(rt);
+ return rc;
}
@@ -1108,9 +1128,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
/* get the mac addr for the remote node */
arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
if (arpindex < 0) {
- kfree(cm_node);
- nes_addr_send_arp(cm_info->rem_addr);
- return NULL;
+ arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr);
+ if (arpindex < 0) {
+ kfree(cm_node);
+ return NULL;
+ }
}
/* copy the mac addr to node context */
@@ -1826,7 +1848,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
/**
* mini_cm_connect - make a connection node with params
*/
-struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
struct nes_vnic *nesvnic, u16 private_data_len,
void *private_data, struct nes_cm_info *cm_info)
{
@@ -1956,13 +1978,6 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
return ret;
cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
- ret = send_fin(cm_node, NULL);
-
- if (cm_node->accept_pend) {
- BUG_ON(!cm_node->listener);
- atomic_dec(&cm_node->listener->pend_accepts_cnt);
- BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
- }
ret = send_reset(cm_node, NULL);
return ret;
@@ -2014,7 +2029,6 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
ret = rem_ref_cm_node(cm_core, cm_node);
break;
}
- cm_node->cm_id = NULL;
return ret;
}
@@ -2383,6 +2397,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
atomic_inc(&cm_disconnects);
cm_event.event = IW_CM_EVENT_DISCONNECT;
if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) {
+ issued_disconnect_reset = 1;
cm_event.status = IW_CM_EVENT_STATUS_RESET;
nes_debug(NES_DBG_CM, "Generating a CM "
"Disconnect Event (status reset) for "
@@ -2508,7 +2523,6 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
nes_debug(NES_DBG_CM, "Call close API\n");
g_cm_core->api->close(g_cm_core, nesqp->cm_node);
- nesqp->cm_node = NULL;
}
return ret;
@@ -2837,6 +2851,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cm_node->apbvt_set = 1;
nesqp->cm_node = cm_node;
cm_node->nesqp = nesqp;
+ nes_add_ref(&nesqp->ibqp);
return 0;
}
@@ -3167,7 +3182,6 @@ static void cm_event_connect_error(struct nes_cm_event *event)
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
"ret=%d\n", __func__, __LINE__, ret);
- nes_rem_ref(&nesqp->ibqp);
cm_id->rem_ref(cm_id);
rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 1513d4066f1..7c49cc882d7 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -55,18 +55,19 @@ u32 int_mod_cq_depth_24;
u32 int_mod_cq_depth_16;
u32 int_mod_cq_depth_4;
u32 int_mod_cq_depth_1;
-
+static const u8 nes_max_critical_error_count = 100;
#include "nes_cm.h"
static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);
static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);
static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
- u8 OneG_Mode);
+ struct nes_adapter *nesadapter, u8 OneG_Mode);
static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);
static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);
static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
struct nes_hw_aeqe *aeqe);
+static void process_critical_error(struct nes_device *nesdev);
static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
@@ -222,11 +223,10 @@ static void nes_nic_tune_timer(struct nes_device *nesdev)
}
/* boundary checking */
- if (shared_timer->timer_in_use > NES_NIC_FAST_TIMER_HIGH)
- shared_timer->timer_in_use = NES_NIC_FAST_TIMER_HIGH;
- else if (shared_timer->timer_in_use < NES_NIC_FAST_TIMER_LOW) {
- shared_timer->timer_in_use = NES_NIC_FAST_TIMER_LOW;
- }
+ if (shared_timer->timer_in_use > shared_timer->threshold_high)
+ shared_timer->timer_in_use = shared_timer->threshold_high;
+ else if (shared_timer->timer_in_use < shared_timer->threshold_low)
+ shared_timer->timer_in_use = shared_timer->threshold_low;
nesdev->currcq_count = 0;
@@ -292,9 +292,6 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)
return NULL;
- if (nes_init_serdes(nesdev, hw_rev, port_count, OneG_Mode))
- return NULL;
- nes_init_csr_ne020(nesdev, hw_rev, port_count);
max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);
nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);
@@ -353,6 +350,22 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
+ if (nes_read_eeprom_values(nesdev, nesadapter)) {
+ printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
+ kfree(nesadapter);
+ return NULL;
+ }
+
+ if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter,
+ OneG_Mode)) {
+ kfree(nesadapter);
+ return NULL;
+ }
+ nes_init_csr_ne020(nesdev, hw_rev, port_count);
+
+ memset(nesadapter->pft_mcast_map, 255,
+ sizeof nesadapter->pft_mcast_map);
+
/* populate the new nesadapter */
nesadapter->devfn = nesdev->pcidev->devfn;
nesadapter->bus_number = nesdev->pcidev->bus->number;
@@ -468,20 +481,25 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
/* setup port configuration */
if (nesadapter->port_count == 1) {
- u32temp = 0x00000000;
+ nesadapter->log_port = 0x00000000;
if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)
nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);
else
nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
} else {
- if (nesadapter->port_count == 2)
- u32temp = 0x00000044;
- else
- u32temp = 0x000000e4;
+ if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+ nesadapter->log_port = 0x000000D8;
+ } else {
+ if (nesadapter->port_count == 2)
+ nesadapter->log_port = 0x00000044;
+ else
+ nesadapter->log_port = 0x000000e4;
+ }
nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
}
- nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, u32temp);
+ nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT,
+ nesadapter->log_port);
nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",
nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));
@@ -706,23 +724,43 @@ static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_
* nes_init_serdes
*/
static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
- u8 OneG_Mode)
+ struct nes_adapter *nesadapter, u8 OneG_Mode)
{
int i;
u32 u32temp;
+ u32 serdes_common_control;
if (hw_rev != NE020_REV) {
/* init serdes 0 */
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
- if (!OneG_Mode)
+ if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+ serdes_common_control = nes_read_indexed(nesdev,
+ NES_IDX_ETH_SERDES_COMMON_CONTROL0);
+ serdes_common_control |= 0x000000100;
+ nes_write_indexed(nesdev,
+ NES_IDX_ETH_SERDES_COMMON_CONTROL0,
+ serdes_common_control);
+ } else if (!OneG_Mode) {
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
- if (port_count > 1) {
+ }
+ if (((port_count > 1) &&
+ (nesadapter->phy_type[0] != NES_PHY_TYPE_PUMA_1G)) ||
+ ((port_count > 2) &&
+ (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G))) {
/* init serdes 1 */
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
- if (!OneG_Mode)
+ if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+ serdes_common_control = nes_read_indexed(nesdev,
+ NES_IDX_ETH_SERDES_COMMON_CONTROL1);
+ serdes_common_control |= 0x000000100;
+ nes_write_indexed(nesdev,
+ NES_IDX_ETH_SERDES_COMMON_CONTROL1,
+ serdes_common_control);
+ } else if (!OneG_Mode) {
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
}
+ }
} else {
/* init serdes 0 */
nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
@@ -826,7 +864,8 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou
nes_write_indexed(nesdev, 0x00005000, 0x00018000);
/* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
- nes_write_indexed(nesdev, 0x00005004, 0x00020001);
+ nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |
+ 0x00000001);
nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
@@ -1226,6 +1265,7 @@ int nes_init_phy(struct nes_device *nesdev)
if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
printk(PFX "%s: Programming mdc config for 1G\n", __func__);
tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+ tx_config &= 0xFFFFFFE3;
tx_config |= 0x04;
nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
}
@@ -1291,7 +1331,8 @@ int nes_init_phy(struct nes_device *nesdev)
(nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
/* setup 10G MDIO operation */
tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
- tx_config |= 0x14;
+ tx_config &= 0xFFFFFFE3;
+ tx_config |= 0x15;
nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
}
if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
@@ -1315,7 +1356,7 @@ int nes_init_phy(struct nes_device *nesdev)
nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008);
nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098);
nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00);
- nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0000);
+ nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0001);
nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528);
/*
@@ -1759,9 +1800,14 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
*/
void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
{
+ u64 u64temp;
+ dma_addr_t bus_address;
struct nes_device *nesdev = nesvnic->nesdev;
struct nes_hw_cqp_wqe *cqp_wqe;
+ struct nes_hw_nic_sq_wqe *nic_sqe;
struct nes_hw_nic_rq_wqe *nic_rqe;
+ __le16 *wqe_fragment_length;
+ u16 wqe_fragment_index;
u64 wqe_frag;
u32 cqp_head;
unsigned long flags;
@@ -1770,14 +1816,69 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
/* Free remaining NIC receive buffers */
while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
- wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
- wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
+ wqe_frag = (u64)le32_to_cpu(
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
+ wqe_frag |= ((u64)le32_to_cpu(
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
}
+ /* Free remaining NIC transmit buffers */
+ while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {
+ nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];
+ wqe_fragment_index = 1;
+ wqe_fragment_length = (__le16 *)
+ &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
+ /* bump past the vlan tag */
+ wqe_fragment_length++;
+ if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
+ u64temp = (u64)le32_to_cpu(
+ nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
+ wqe_fragment_index*2]);
+ u64temp += ((u64)le32_to_cpu(
+ nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
+ + wqe_fragment_index*2]))<<32;
+ bus_address = (dma_addr_t)u64temp;
+ if (test_and_clear_bit(nesvnic->nic.sq_tail,
+ nesvnic->nic.first_frag_overflow)) {
+ pci_unmap_single(nesdev->pcidev,
+ bus_address,
+ le16_to_cpu(wqe_fragment_length[
+ wqe_fragment_index++]),
+ PCI_DMA_TODEVICE);
+ }
+ for (; wqe_fragment_index < 5; wqe_fragment_index++) {
+ if (wqe_fragment_length[wqe_fragment_index]) {
+ u64temp = le32_to_cpu(
+ nic_sqe->wqe_words[
+ NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
+ wqe_fragment_index*2]);
+ u64temp += ((u64)le32_to_cpu(
+ nic_sqe->wqe_words[
+ NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+
+ wqe_fragment_index*2]))<<32;
+ bus_address = (dma_addr_t)u64temp;
+ pci_unmap_page(nesdev->pcidev,
+ bus_address,
+ le16_to_cpu(
+ wqe_fragment_length[
+ wqe_fragment_index]),
+ PCI_DMA_TODEVICE);
+ } else
+ break;
+ }
+ }
+ if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])
+ dev_kfree_skb(
+ nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);
+
+ nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail)
+ & (nesvnic->nic.sq_size - 1);
+ }
+
spin_lock_irqsave(&nesdev->cqp.lock, flags);
/* Destroy NIC QP */
@@ -1894,7 +1995,30 @@ int nes_napi_isr(struct nes_device *nesdev)
}
}
-
+static void process_critical_error(struct nes_device *nesdev)
+{
+ u32 debug_error;
+ u32 nes_idx_debug_error_masks0 = 0;
+ u16 error_module = 0;
+
+ debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
+ printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
+ (u16)debug_error);
+ nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
+ 0x01010000 | (debug_error & 0x0000ffff));
+ if (crit_err_count++ > 10)
+ nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
+ error_module = (u16) (debug_error & 0x1F00) >> 8;
+ if (++nesdev->nesadapter->crit_error_count[error_module-1] >=
+ nes_max_critical_error_count) {
+ printk(KERN_ERR PFX "Masking off critical error for module "
+ "0x%02X\n", (u16)error_module);
+ nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,
+ NES_IDX_DEBUG_ERROR_MASKS0);
+ nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,
+ nes_idx_debug_error_masks0 | (1 << error_module));
+ }
+}
/**
* nes_dpc
*/
@@ -1909,7 +2033,6 @@ void nes_dpc(unsigned long param)
u32 timer_stat;
u32 temp_int_stat;
u32 intf_int_stat;
- u32 debug_error;
u32 processed_intf_int = 0;
u16 processed_timer_int = 0;
u16 completion_ints = 0;
@@ -1987,14 +2110,7 @@ void nes_dpc(unsigned long param)
intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
intf_int_stat &= nesdev->intf_int_req;
if (NES_INTF_INT_CRITERR & intf_int_stat) {
- debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
- printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
- (u16)debug_error);
- nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
- 0x01010000 | (debug_error & 0x0000ffff));
- /* BUG(); */
- if (crit_err_count++ > 10)
- nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
+ process_critical_error(nesdev);
}
if (NES_INTF_INT_PCIERR & intf_int_stat) {
printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
@@ -2258,7 +2374,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
}
/* read the PHY interrupt status register */
- if (nesadapter->OneG_Mode) {
+ if ((nesadapter->OneG_Mode) &&
+ (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
do {
nes_read_1G_phy_reg(nesdev, 0x1a,
nesadapter->phy_index[mac_index], &phy_data);
@@ -3077,6 +3194,22 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
nes_cm_disconn(nesqp);
break;
/* TODO: additional AEs need to be here */
+ case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
+ nesqp = *((struct nes_qp **)&context);
+ spin_lock_irqsave(&nesqp->lock, flags);
+ nesqp->hw_iwarp_state = iwarp_state;
+ nesqp->hw_tcp_state = tcp_state;
+ nesqp->last_aeq = async_event_id;
+ spin_unlock_irqrestore(&nesqp->lock, flags);
+ if (nesqp->ibqp.event_handler) {
+ ibevent.device = nesqp->ibqp.device;
+ ibevent.element.qp = &nesqp->ibqp;
+ ibevent.event = IB_EVENT_QP_ACCESS_ERR;
+ nesqp->ibqp.event_handler(&ibevent,
+ nesqp->ibqp.qp_context);
+ }
+ nes_cm_disconn(nesqp);
+ break;
default:
nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
async_event_id);
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 7b81e0ae007..610b9d85959 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -156,6 +156,7 @@ enum indexed_regs {
NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004,
NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008,
NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c,
+ NES_IDX_WQM_CONFIG1 = 0x5004,
NES_IDX_CM_CONFIG = 0x5100,
NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000,
NES_IDX_NIC_PHYPORT_TO_USW = 0x6008,
@@ -967,6 +968,7 @@ struct nes_arp_entry {
#define DEFAULT_JUMBO_NES_QL_TARGET 40
#define DEFAULT_JUMBO_NES_QL_HIGH 128
#define NES_NIC_CQ_DOWNWARD_TREND 16
+#define NES_PFT_SIZE 48
struct nes_hw_tune_timer {
/* u16 cq_count; */
@@ -1079,6 +1081,7 @@ struct nes_adapter {
u32 et_rx_max_coalesced_frames_high;
u32 et_rate_sample_interval;
u32 timer_int_limit;
+ u32 wqm_quanta;
/* Adapter base MAC address */
u32 mac_addr_low;
@@ -1094,12 +1097,14 @@ struct nes_adapter {
u16 pd_config_base[4];
u16 link_interrupt_count[4];
+ u8 crit_error_count[32];
/* the phy index for each port */
u8 phy_index[4];
u8 mac_sw_state[4];
u8 mac_link_down[4];
u8 phy_type[4];
+ u8 log_port;
/* PCI information */
unsigned int devfn;
@@ -1113,6 +1118,7 @@ struct nes_adapter {
u8 virtwq;
u8 et_use_adaptive_rx_coalesce;
u8 adapter_fcn_count;
+ u8 pft_mcast_map[NES_PFT_SIZE];
};
struct nes_pbl {
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 1b0938c8777..730358637bb 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -91,6 +91,7 @@ static struct nic_qp_map *nic_qp_mapping_per_function[] = {
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
static int debug = -1;
+static int nics_per_function = 1;
/**
* nes_netdev_poll
@@ -201,7 +202,8 @@ static int nes_netdev_open(struct net_device *netdev)
nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW"
" (Addr:%08X) = %08X, HIGH = %08X.\n",
i, nesvnic->qp_nic_index[i],
- NES_IDX_PERFECT_FILTER_LOW+((nesvnic->perfect_filter_index + i) * 8),
+ NES_IDX_PERFECT_FILTER_LOW+
+ (nesvnic->qp_nic_index[i] * 8),
macaddr_low,
(u32)macaddr_high | NES_MAC_ADDR_VALID |
((((u32)nesvnic->nic_index) << 16)));
@@ -272,14 +274,18 @@ static int nes_netdev_stop(struct net_device *netdev)
break;
}
- if (first_nesvnic->netdev_open == 0)
+ if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic) &&
+ (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) !=
+ PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) {
+ nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+
+ (0x200*nesdev->mac_index), 0xffffffff);
+ nes_write_indexed(first_nesvnic->nesdev,
+ NES_IDX_MAC_INT_MASK+
+ (0x200*first_nesvnic->nesdev->mac_index),
+ ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
+ NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
+ } else {
nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
- else if ((first_nesvnic != nesvnic) &&
- (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) {
- nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff);
- nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index),
- ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
- NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
}
nic_active_mask = ~((u32)(1 << nesvnic->nic_index));
@@ -437,7 +443,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
struct nes_hw_nic_sq_wqe *nic_sqe;
struct tcphdr *tcph;
/* struct udphdr *udph; */
-#define NES_MAX_TSO_FRAGS 18
+#define NES_MAX_TSO_FRAGS MAX_SKB_FRAGS
/* 64K segment plus overflow on each side */
dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS];
dma_addr_t bus_address;
@@ -605,6 +611,8 @@ tso_sq_no_longer_full:
wqe_fragment_length[wqe_fragment_index] = 0;
set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
bus_address);
+ tso_wqe_length += skb_headlen(skb) -
+ original_first_length;
}
while (wqe_fragment_index < 5) {
wqe_fragment_length[wqe_fragment_index] =
@@ -827,6 +835,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
{
struct nes_vnic *nesvnic = netdev_priv(netdev);
struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
struct dev_mc_list *multicast_addr;
u32 nic_active_bit;
u32 nic_active;
@@ -836,7 +845,12 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
u8 mc_all_on = 0;
u8 mc_index;
int mc_nic_index = -1;
+ u8 pft_entries_preallocated = max(nesadapter->adapter_fcn_count *
+ nics_per_function, 4);
+ u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated;
+ unsigned long flags;
+ spin_lock_irqsave(&nesadapter->resource_lock, flags);
nic_active_bit = 1 << nesvnic->nic_index;
if (netdev->flags & IFF_PROMISC) {
@@ -847,7 +861,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
mc_all_on = 1;
- } else if ((netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > NES_MULTICAST_PF_MAX) ||
+ } else if ((netdev->flags & IFF_ALLMULTI) ||
(nesvnic->nic_index > 3)) {
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
nic_active |= nic_active_bit;
@@ -866,17 +880,34 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
}
nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
- netdev->mc_count, (netdev->flags & IFF_PROMISC)?1:0,
- (netdev->flags & IFF_ALLMULTI)?1:0);
+ netdev->mc_count, !!(netdev->flags & IFF_PROMISC),
+ !!(netdev->flags & IFF_ALLMULTI));
if (!mc_all_on) {
multicast_addr = netdev->mc_list;
- perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + 0x80;
- perfect_filter_register_address += nesvnic->nic_index*0x40;
- for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) {
- while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0))
+ perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +
+ pft_entries_preallocated * 0x8;
+ for (mc_index = 0; mc_index < max_pft_entries_avaiable;
+ mc_index++) {
+ while (multicast_addr && nesvnic->mcrq_mcast_filter &&
+ ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic,
+ multicast_addr->dmi_addr)) == 0)) {
multicast_addr = multicast_addr->next;
+ }
if (mc_nic_index < 0)
mc_nic_index = nesvnic->nic_index;
+ while (nesadapter->pft_mcast_map[mc_index] < 16 &&
+ nesadapter->pft_mcast_map[mc_index] !=
+ nesvnic->nic_index &&
+ mc_index < max_pft_entries_avaiable) {
+ nes_debug(NES_DBG_NIC_RX,
+ "mc_index=%d skipping nic_index=%d,\
+ used for=%d \n", mc_index,
+ nesvnic->nic_index,
+ nesadapter->pft_mcast_map[mc_index]);
+ mc_index++;
+ }
+ if (mc_index >= max_pft_entries_avaiable)
+ break;
if (multicast_addr) {
DECLARE_MAC_BUF(mac);
nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %s to register 0x%04X nic_idx=%d\n",
@@ -897,15 +928,33 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
(u32)macaddr_high | NES_MAC_ADDR_VALID |
((((u32)(1<<mc_nic_index)) << 16)));
multicast_addr = multicast_addr->next;
+ nesadapter->pft_mcast_map[mc_index] =
+ nesvnic->nic_index;
} else {
nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n",
perfect_filter_register_address+(mc_index * 8));
nes_write_indexed(nesdev,
perfect_filter_register_address+4+(mc_index * 8),
0);
+ nesadapter->pft_mcast_map[mc_index] = 255;
}
}
+ /* PFT is not large enough */
+ if (multicast_addr && multicast_addr->next) {
+ nic_active = nes_read_indexed(nesdev,
+ NES_IDX_NIC_MULTICAST_ALL);
+ nic_active |= nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,
+ nic_active);
+ nic_active = nes_read_indexed(nesdev,
+ NES_IDX_NIC_UNICAST_ALL);
+ nic_active &= ~nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL,
+ nic_active);
+ }
}
+
+ spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
}
@@ -918,6 +967,10 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
struct nes_device *nesdev = nesvnic->nesdev;
int ret = 0;
u8 jumbomode = 0;
+ u32 nic_active;
+ u32 nic_active_bit;
+ u32 uc_all_active;
+ u32 mc_all_active;
if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
return -EINVAL;
@@ -931,8 +984,24 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
nes_nic_init_timer_defaults(nesdev, jumbomode);
if (netif_running(netdev)) {
+ nic_active_bit = 1 << nesvnic->nic_index;
+ mc_all_active = nes_read_indexed(nesdev,
+ NES_IDX_NIC_MULTICAST_ALL) & nic_active_bit;
+ uc_all_active = nes_read_indexed(nesdev,
+ NES_IDX_NIC_UNICAST_ALL) & nic_active_bit;
+
nes_netdev_stop(netdev);
nes_netdev_open(netdev);
+
+ nic_active = nes_read_indexed(nesdev,
+ NES_IDX_NIC_MULTICAST_ALL);
+ nic_active |= mc_all_active;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,
+ nic_active);
+
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
+ nic_active |= uc_all_active;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
}
return ret;
@@ -1208,10 +1277,12 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
strcpy(drvinfo->driver, DRV_NAME);
strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev));
- strcpy(drvinfo->fw_version, "TBD");
+ sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,
+ nesadapter->firmware_version & 0x000000ff);
strcpy(drvinfo->version, DRV_VERSION);
drvinfo->n_stats = nes_netdev_get_stats_count(netdev);
drvinfo->testinfo_len = 0;
@@ -1587,7 +1658,9 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id,
nesvnic->nic_index, nesvnic->logical_port, nesdev->mac_index);
- if (nesvnic->nesdev->nesadapter->port_count == 1) {
+ if (nesvnic->nesdev->nesadapter->port_count == 1 &&
+ nesvnic->nesdev->nesadapter->adapter_fcn_count == 1) {
+
nesvnic->qp_nic_index[0] = nesvnic->nic_index;
nesvnic->qp_nic_index[1] = nesvnic->nic_index + 1;
if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) {
@@ -1598,11 +1671,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
nesvnic->qp_nic_index[3] = nesvnic->nic_index + 3;
}
} else {
- if (nesvnic->nesdev->nesadapter->port_count == 2) {
- nesvnic->qp_nic_index[0] = nesvnic->nic_index;
- nesvnic->qp_nic_index[1] = nesvnic->nic_index + 2;
- nesvnic->qp_nic_index[2] = 0xf;
- nesvnic->qp_nic_index[3] = 0xf;
+ if (nesvnic->nesdev->nesadapter->port_count == 2 ||
+ (nesvnic->nesdev->nesadapter->port_count == 1 &&
+ nesvnic->nesdev->nesadapter->adapter_fcn_count == 2)) {
+ nesvnic->qp_nic_index[0] = nesvnic->nic_index;
+ nesvnic->qp_nic_index[1] = nesvnic->nic_index
+ + 2;
+ nesvnic->qp_nic_index[2] = 0xf;
+ nesvnic->qp_nic_index[3] = 0xf;
} else {
nesvnic->qp_nic_index[0] = nesvnic->nic_index;
nesvnic->qp_nic_index[1] = 0xf;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index d79942e8497..932e56fcf77 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1467,7 +1467,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
default:
nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type);
return ERR_PTR(-EINVAL);
- break;
}
/* update the QP table */
@@ -2498,7 +2497,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr);
return ibmr;
- break;
case IWNES_MEMREG_TYPE_QP:
case IWNES_MEMREG_TYPE_CQ:
nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);
@@ -2572,7 +2570,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
nesmr->ibmr.lkey = -1;
nesmr->mode = req.reg_type;
return &nesmr->ibmr;
- break;
}
return ERR_PTR(-ENOSYS);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index b0ffc9abe8c..68ba5c3482e 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -268,10 +268,9 @@ struct ipoib_lro {
};
/*
- * Device private locking: tx_lock protects members used in TX fast
- * path (and we use LLTX so upper layers don't do extra locking).
- * lock protects everything else. lock nests inside of tx_lock (ie
- * tx_lock must be acquired first if needed).
+ * Device private locking: network stack tx_lock protects members used
+ * in TX fast path, lock protects everything else. lock nests inside
+ * of tx_lock (ie tx_lock must be acquired first if needed).
*/
struct ipoib_dev_priv {
spinlock_t lock;
@@ -293,6 +292,7 @@ struct ipoib_dev_priv {
struct delayed_work pkey_poll_task;
struct delayed_work mcast_task;
+ struct work_struct carrier_on_task;
struct work_struct flush_light;
struct work_struct flush_normal;
struct work_struct flush_heavy;
@@ -319,7 +319,6 @@ struct ipoib_dev_priv {
struct ipoib_rx_buf *rx_ring;
- spinlock_t tx_lock;
struct ipoib_tx_buf *tx_ring;
unsigned tx_head;
unsigned tx_tail;
@@ -464,6 +463,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
void ipoib_dev_cleanup(struct net_device *dev);
void ipoib_mcast_join_task(struct work_struct *work);
+void ipoib_mcast_carrier_on_task(struct work_struct *work);
void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb);
void ipoib_mcast_restart_task(struct work_struct *work);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 341ffedafed..7b14c2c3950 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -786,7 +786,8 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
dev_kfree_skb_any(tx_req->skb);
- spin_lock_irqsave(&priv->tx_lock, flags);
+ netif_tx_lock(dev);
+
++tx->tx_tail;
if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
netif_queue_stopped(dev) &&
@@ -801,7 +802,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
"(status=%d, wrid=%d vend_err %x)\n",
wc->status, wr_id, wc->vendor_err);
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
neigh = tx->neigh;
if (neigh) {
@@ -821,10 +822,10 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+ netif_tx_unlock(dev);
}
int ipoib_cm_dev_open(struct net_device *dev)
@@ -1149,7 +1150,6 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
{
struct ipoib_dev_priv *priv = netdev_priv(p->dev);
struct ipoib_cm_tx_buf *tx_req;
- unsigned long flags;
unsigned long begin;
ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n",
@@ -1180,12 +1180,12 @@ timeout:
DMA_TO_DEVICE);
dev_kfree_skb_any(tx_req->skb);
++p->tx_tail;
- spin_lock_irqsave(&priv->tx_lock, flags);
+ netif_tx_lock_bh(p->dev);
if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
netif_queue_stopped(p->dev) &&
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
netif_wake_queue(p->dev);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+ netif_tx_unlock_bh(p->dev);
}
if (p->qp)
@@ -1202,6 +1202,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
struct ipoib_dev_priv *priv = netdev_priv(tx->dev);
struct net_device *dev = priv->dev;
struct ipoib_neigh *neigh;
+ unsigned long flags;
int ret;
switch (event->event) {
@@ -1220,8 +1221,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
case IB_CM_REJ_RECEIVED:
case IB_CM_TIMEWAIT_EXIT:
ipoib_dbg(priv, "CM error %d.\n", event->event);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
neigh = tx->neigh;
if (neigh) {
@@ -1239,8 +1240,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
queue_work(ipoib_workqueue, &priv->cm.reap_task);
}
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
break;
default:
break;
@@ -1294,19 +1295,24 @@ static void ipoib_cm_tx_start(struct work_struct *work)
struct ib_sa_path_rec pathrec;
u32 qpn;
- spin_lock_irqsave(&priv->tx_lock, flags);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
+
while (!list_empty(&priv->cm.start_list)) {
p = list_entry(priv->cm.start_list.next, typeof(*p), list);
list_del_init(&p->list);
neigh = p->neigh;
qpn = IPOIB_QPN(neigh->neighbour->ha);
memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
- spin_unlock(&priv->lock);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
+
ret = ipoib_cm_tx_init(p, qpn, &pathrec);
- spin_lock_irqsave(&priv->tx_lock, flags);
- spin_lock(&priv->lock);
+
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
+
if (ret) {
neigh = p->neigh;
if (neigh) {
@@ -1320,44 +1326,52 @@ static void ipoib_cm_tx_start(struct work_struct *work)
kfree(p);
}
}
- spin_unlock(&priv->lock);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
}
static void ipoib_cm_tx_reap(struct work_struct *work)
{
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
cm.reap_task);
+ struct net_device *dev = priv->dev;
struct ipoib_cm_tx *p;
+ unsigned long flags;
+
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
while (!list_empty(&priv->cm.reap_list)) {
p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
list_del(&p->list);
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
ipoib_cm_tx_destroy(p);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
}
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
}
static void ipoib_cm_skb_reap(struct work_struct *work)
{
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
cm.skb_task);
+ struct net_device *dev = priv->dev;
struct sk_buff *skb;
-
+ unsigned long flags;
unsigned mtu = priv->mcast_mtu;
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
+
while ((skb = skb_dequeue(&priv->cm.skb_queue))) {
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
+
if (skb->protocol == htons(ETH_P_IP))
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -1365,11 +1379,13 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev);
#endif
dev_kfree_skb_any(skb);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
}
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
}
void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 66cafa20c24..0e748aeeae9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -468,21 +468,22 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
static void drain_tx_cq(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
- spin_lock_irqsave(&priv->tx_lock, flags);
+ netif_tx_lock(dev);
while (poll_tx(priv))
; /* nothing */
if (netif_queue_stopped(dev))
mod_timer(&priv->poll_timer, jiffies + 1);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+ netif_tx_unlock(dev);
}
void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr)
{
- drain_tx_cq((struct net_device *)dev_ptr);
+ struct ipoib_dev_priv *priv = netdev_priv(dev_ptr);
+
+ mod_timer(&priv->poll_timer, jiffies);
}
static inline int post_send(struct ipoib_dev_priv *priv,
@@ -614,17 +615,20 @@ static void __ipoib_reap_ah(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_ah *ah, *tah;
LIST_HEAD(remove_list);
+ unsigned long flags;
+
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
list_del(&ah->list);
ib_destroy_ah(ah->ah);
kfree(ah);
}
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
}
void ipoib_reap_ah(struct work_struct *work)
@@ -761,6 +765,14 @@ void ipoib_drain_cq(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
int i, n;
+
+ /*
+ * We call completion handling routines that expect to be
+ * called from the BH-disabled NAPI poll context, so disable
+ * BHs here too.
+ */
+ local_bh_disable();
+
do {
n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc);
for (i = 0; i < n; ++i) {
@@ -784,6 +796,8 @@ void ipoib_drain_cq(struct net_device *dev)
while (poll_tx(priv))
; /* nothing */
+
+ local_bh_enable();
}
int ipoib_ib_dev_stop(struct net_device *dev, int flush)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 7e9e218738f..c0ee514396d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -373,9 +373,10 @@ void ipoib_flush_paths(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path, *tp;
LIST_HEAD(remove_list);
+ unsigned long flags;
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
list_splice_init(&priv->path_list, &remove_list);
@@ -385,15 +386,16 @@ void ipoib_flush_paths(struct net_device *dev)
list_for_each_entry_safe(path, tp, &remove_list, list) {
if (path->query)
ib_sa_cancel_query(path->query_id, path->query);
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
wait_for_completion(&path->done);
path_free(dev, path);
- spin_lock_irq(&priv->tx_lock);
- spin_lock(&priv->lock);
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
}
- spin_unlock(&priv->lock);
- spin_unlock_irq(&priv->tx_lock);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
}
static void path_rec_completion(int status,
@@ -404,7 +406,7 @@ static void path_rec_completion(int status,
struct net_device *dev = path->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_ah *ah = NULL;
- struct ipoib_ah *old_ah;
+ struct ipoib_ah *old_ah = NULL;
struct ipoib_neigh *neigh, *tn;
struct sk_buff_head skqueue;
struct sk_buff *skb;
@@ -428,12 +430,12 @@ static void path_rec_completion(int status,
spin_lock_irqsave(&priv->lock, flags);
- old_ah = path->ah;
- path->ah = ah;
-
if (ah) {
path->pathrec = *pathrec;
+ old_ah = path->ah;
+ path->ah = ah;
+
ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n",
ah, be16_to_cpu(pathrec->dlid), pathrec->sl);
@@ -555,6 +557,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
struct ipoib_neigh *neigh;
+ unsigned long flags;
neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
if (!neigh) {
@@ -563,11 +566,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
return;
}
- /*
- * We can only be called from ipoib_start_xmit, so we're
- * inside tx_lock -- no need to save/restore flags.
- */
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
path = __path_find(dev, skb->dst->neighbour->ha + 4);
if (!path) {
@@ -614,7 +613,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
__skb_queue_tail(&neigh->queue, skb);
}
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
return;
err_list:
@@ -626,7 +625,7 @@ err_drop:
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
@@ -650,12 +649,9 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
+ unsigned long flags;
- /*
- * We can only be called from ipoib_start_xmit, so we're
- * inside tx_lock -- no need to save/restore flags.
- */
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
path = __path_find(dev, phdr->hwaddr + 4);
if (!path || !path->valid) {
@@ -667,7 +663,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
__skb_queue_tail(&path->queue, skb);
if (path_rec_start(dev, path)) {
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
path_free(dev, path);
return;
} else
@@ -677,7 +673,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
dev_kfree_skb_any(skb);
}
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
return;
}
@@ -696,7 +692,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
dev_kfree_skb_any(skb);
}
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -705,13 +701,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct ipoib_neigh *neigh;
unsigned long flags;
- if (unlikely(!spin_trylock_irqsave(&priv->tx_lock, flags)))
- return NETDEV_TX_LOCKED;
-
if (likely(skb->dst && skb->dst->neighbour)) {
if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
ipoib_path_lookup(skb, dev);
- goto out;
+ return NETDEV_TX_OK;
}
neigh = *to_ipoib_neigh(skb->dst->neighbour);
@@ -721,7 +714,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->dst->neighbour->ha + 4,
sizeof(union ib_gid))) ||
(neigh->dev != dev))) {
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
@@ -732,25 +725,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, dev);
- goto out;
+ return NETDEV_TX_OK;
}
if (ipoib_cm_get(neigh)) {
if (ipoib_cm_up(neigh)) {
ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
- goto out;
+ return NETDEV_TX_OK;
}
} else if (neigh->ah) {
ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
- goto out;
+ return NETDEV_TX_OK;
}
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
__skb_queue_tail(&neigh->queue, skb);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
} else {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -779,16 +772,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
dev_kfree_skb_any(skb);
++dev->stats.tx_dropped;
- goto out;
+ return NETDEV_TX_OK;
}
unicast_arp_send(skb, dev, phdr);
}
}
-out:
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-
return NETDEV_TX_OK;
}
@@ -1052,7 +1042,6 @@ static void ipoib_setup(struct net_device *dev)
dev->type = ARPHRD_INFINIBAND;
dev->tx_queue_len = ipoib_sendq_size * 2;
dev->features = (NETIF_F_VLAN_CHALLENGED |
- NETIF_F_LLTX |
NETIF_F_HIGHDMA);
memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
@@ -1064,7 +1053,6 @@ static void ipoib_setup(struct net_device *dev)
ipoib_lro_setup(priv);
spin_lock_init(&priv->lock);
- spin_lock_init(&priv->tx_lock);
mutex_init(&priv->vlan_mutex);
@@ -1075,6 +1063,7 @@ static void ipoib_setup(struct net_device *dev)
INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
+ INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task);
INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light);
INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal);
INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ac33c8f3ea8..d9d1223c3fd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -69,14 +69,13 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct net_device *dev = mcast->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
- unsigned long flags;
int tx_dropped = 0;
ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
IPOIB_GID_ARG(mcast->mcmember.mgid));
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
/*
@@ -90,7 +89,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
ipoib_neigh_free(dev, neigh);
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irq(&priv->lock);
if (mcast->ah)
ipoib_put_ah(mcast->ah);
@@ -100,9 +99,9 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
}
- spin_lock_irqsave(&priv->tx_lock, flags);
+ netif_tx_lock_bh(dev);
dev->stats.tx_dropped += tx_dropped;
- spin_unlock_irqrestore(&priv->tx_lock, flags);
+ netif_tx_unlock_bh(dev);
kfree(mcast);
}
@@ -259,10 +258,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
}
/* actually send any queued packets */
- spin_lock_irq(&priv->tx_lock);
+ netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
- spin_unlock_irq(&priv->tx_lock);
+ netif_tx_unlock_bh(dev);
skb->dev = dev;
@@ -273,9 +272,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
if (dev_queue_xmit(skb))
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
- spin_lock_irq(&priv->tx_lock);
+ netif_tx_lock_bh(dev);
}
- spin_unlock_irq(&priv->tx_lock);
+ netif_tx_unlock_bh(dev);
return 0;
}
@@ -286,7 +285,6 @@ ipoib_mcast_sendonly_join_complete(int status,
{
struct ipoib_mcast *mcast = multicast->context;
struct net_device *dev = mcast->dev;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
/* We trap for port events ourselves. */
if (status == -ENETRESET)
@@ -302,12 +300,12 @@ ipoib_mcast_sendonly_join_complete(int status,
IPOIB_GID_ARG(mcast->mcmember.mgid), status);
/* Flush out any queued packets */
- spin_lock_irq(&priv->tx_lock);
+ netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
}
- spin_unlock_irq(&priv->tx_lock);
+ netif_tx_unlock_bh(dev);
/* Clear the busy flag so we try again */
status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
@@ -366,6 +364,21 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
return ret;
}
+void ipoib_mcast_carrier_on_task(struct work_struct *work)
+{
+ struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+ carrier_on_task);
+
+ /*
+ * Take rtnl_lock to avoid racing with ipoib_stop() and
+ * turning the carrier back on while a device is being
+ * removed.
+ */
+ rtnl_lock();
+ netif_carrier_on(priv->dev);
+ rtnl_unlock();
+}
+
static int ipoib_mcast_join_complete(int status,
struct ib_sa_multicast *multicast)
{
@@ -392,16 +405,12 @@ static int ipoib_mcast_join_complete(int status,
&priv->mcast_task, 0);
mutex_unlock(&mcast_mutex);
- if (mcast == priv->broadcast) {
- /*
- * Take RTNL lock here to avoid racing with
- * ipoib_stop() and turning the carrier back
- * on while a device is being removed.
- */
- rtnl_lock();
- netif_carrier_on(dev);
- rtnl_unlock();
- }
+ /*
+ * Defer carrier on work to ipoib_workqueue to avoid a
+ * deadlock on rtnl_lock here.
+ */
+ if (mcast == priv->broadcast)
+ queue_work(ipoib_workqueue, &priv->carrier_on_task);
return 0;
}
@@ -651,12 +660,9 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_mcast *mcast;
+ unsigned long flags;
- /*
- * We can only be called from ipoib_start_xmit, so we're
- * inside tx_lock -- no need to save/restore flags.
- */
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) ||
!priv->broadcast ||
@@ -727,7 +733,7 @@ out:
}
unlock:
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
void ipoib_mcast_dev_flush(struct net_device *dev)
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 5a1cf2580e1..1e5b6446231 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -378,6 +378,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
{
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ iscsi_session_teardown(cls_session);
iscsi_host_remove(shost);
iscsi_host_free(shost);
}
@@ -597,7 +598,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.cmd_per_lun = ISCSI_MAX_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
- .eh_host_reset_handler = iscsi_eh_host_reset,
+ .eh_target_reset_handler= iscsi_eh_target_reset,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_iser",
.this_id = -1,
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ed7c5f72cb8..5b8b533f290 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1683,7 +1683,7 @@ enum {
SRP_OPT_SERVICE_ID),
};
-static match_table_t srp_opt_tokens = {
+static const match_table_t srp_opt_tokens = {
{ SRP_OPT_ID_EXT, "id_ext=%s" },
{ SRP_OPT_IOC_GUID, "ioc_guid=%s" },
{ SRP_OPT_DGID, "dgid=%s" },
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 078e4eed089..2880eaae157 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport)
enum gameport_event_type {
GAMEPORT_REGISTER_PORT,
GAMEPORT_REGISTER_DRIVER,
+ GAMEPORT_ATTACH_DRIVER,
};
struct gameport_event {
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list);
static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
static struct task_struct *gameport_task;
-static void gameport_queue_event(void *object, struct module *owner,
- enum gameport_event_type event_type)
+static int gameport_queue_event(void *object, struct module *owner,
+ enum gameport_event_type event_type)
{
unsigned long flags;
struct gameport_event *event;
+ int retval = 0;
spin_lock_irqsave(&gameport_event_lock, flags);
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner,
}
}
- if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
- if (!try_module_get(owner)) {
- printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
- kfree(event);
- goto out;
- }
-
- event->type = event_type;
- event->object = object;
- event->owner = owner;
+ event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
+ if (!event) {
+ printk(KERN_ERR
+ "gameport: Not enough memory to queue event %d\n",
+ event_type);
+ retval = -ENOMEM;
+ goto out;
+ }
- list_add_tail(&event->node, &gameport_event_list);
- wake_up(&gameport_wait);
- } else {
- printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING
+ "gameport: Can't get module reference, dropping event %d\n",
+ event_type);
+ kfree(event);
+ retval = -EINVAL;
+ goto out;
}
+
+ event->type = event_type;
+ event->object = object;
+ event->owner = owner;
+
+ list_add_tail(&event->node, &gameport_event_list);
+ wake_up(&gameport_wait);
+
out:
spin_unlock_irqrestore(&gameport_event_lock, flags);
+ return retval;
}
static void gameport_free_event(struct gameport_event *event)
@@ -378,9 +390,10 @@ static void gameport_handle_event(void)
}
/*
- * Remove all events that have been submitted for a given gameport port.
+ * Remove all events that have been submitted for a given object,
+ * be it a gameport port or a driver.
*/
-static void gameport_remove_pending_events(struct gameport *gameport)
+static void gameport_remove_pending_events(void *object)
{
struct list_head *node, *next;
struct gameport_event *event;
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport)
list_for_each_safe(node, next, &gameport_event_list) {
event = list_entry(node, struct gameport_event, node);
- if (event->object == gameport) {
+ if (event->object == object) {
list_del_init(node);
gameport_free_event(event);
}
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv)
drv->driver.name, error);
}
-void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
+int __gameport_register_driver(struct gameport_driver *drv, struct module *owner,
+ const char *mod_name)
{
+ int error;
+
drv->driver.bus = &gameport_bus;
- gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
+ drv->driver.owner = owner;
+ drv->driver.mod_name = mod_name;
+
+ /*
+ * Temporarily disable automatic binding because probing
+ * takes long time and we are better off doing it in kgameportd
+ */
+ drv->ignore = 1;
+
+ error = driver_register(&drv->driver);
+ if (error) {
+ printk(KERN_ERR
+ "gameport: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+ return error;
+ }
+
+ /*
+ * Reset ignore flag and let kgameportd bind the driver to free ports
+ */
+ drv->ignore = 0;
+ error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
+ if (error) {
+ driver_unregister(&drv->driver);
+ return error;
+ }
+
+ return 0;
}
void gameport_unregister_driver(struct gameport_driver *drv)
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv)
struct gameport *gameport;
mutex_lock(&gameport_mutex);
+
drv->ignore = 1; /* so gameport_find_driver ignores it */
+ gameport_remove_pending_events(drv);
start_over:
list_for_each_entry(gameport, &gameport_list, node) {
@@ -729,6 +774,7 @@ start_over:
}
driver_unregister(&drv->driver);
+
mutex_unlock(&gameport_mutex);
}
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 92498d470b1..6489f4010c4 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = {
static int __init a3d_init(void)
{
- gameport_register_driver(&a3d_drv);
- return 0;
+ return gameport_register_driver(&a3d_drv);
}
static void __exit a3d_exit(void)
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index d1ca8a14950..89c4c084d4a 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = {
static int __init adi_init(void)
{
- gameport_register_driver(&adi_drv);
- return 0;
+ return gameport_register_driver(&adi_drv);
}
static void __exit adi_exit(void)
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 708c5ae13b2..356b3a25efa 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = {
static int __init analog_init(void)
{
analog_parse_options();
- gameport_register_driver(&analog_drv);
-
- return 0;
+ return gameport_register_driver(&analog_drv);
}
static void __exit analog_exit(void)
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 639b975a8ed..3497b87c3d0 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = {
static int __init cobra_init(void)
{
- gameport_register_driver(&cobra_drv);
- return 0;
+ return gameport_register_driver(&cobra_drv);
}
static void __exit cobra_exit(void)
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index cb6eef1f2d9..67c207f5b1a 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = {
static int __init gf2k_init(void)
{
- gameport_register_driver(&gf2k_drv);
- return 0;
+ return gameport_register_driver(&gf2k_drv);
}
static void __exit gf2k_exit(void)
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 684e07cfccc..fc55899ba6c 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = {
static int __init grip_init(void)
{
- gameport_register_driver(&grip_drv);
- return 0;
+ return gameport_register_driver(&grip_drv);
}
static void __exit grip_exit(void)
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 8279481b16e..2d47baf4776 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = {
static int __init grip_init(void)
{
- gameport_register_driver(&grip_drv);
- return 0;
+ return gameport_register_driver(&grip_drv);
}
static void __exit grip_exit(void)
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 25ec3fad9f2..4058d4b272f 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = {
static int __init guillemot_init(void)
{
- gameport_register_driver(&guillemot_drv);
- return 0;
+ return gameport_register_driver(&guillemot_drv);
}
static void __exit guillemot_exit(void)
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 7839b7b6fa9..0de9a0943a9 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -197,13 +197,16 @@ static unsigned char find_button(struct iforce *iforce, signed short button)
* Analyse the changes in an effect, and tell if we need to send an condition
* parameter packet
*/
-static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new)
+static int need_condition_modifier(struct iforce *iforce,
+ struct ff_effect *old,
+ struct ff_effect *new)
{
int ret = 0;
int i;
if (new->type != FF_SPRING && new->type != FF_FRICTION) {
- warn("bad effect type in need_condition_modifier");
+ dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
+ __func__);
return 0;
}
@@ -222,10 +225,13 @@ static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new)
* Analyse the changes in an effect, and tell if we need to send a magnitude
* parameter packet
*/
-static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect)
+static int need_magnitude_modifier(struct iforce *iforce,
+ struct ff_effect *old,
+ struct ff_effect *effect)
{
if (effect->type != FF_CONSTANT) {
- warn("bad effect type in need_envelope_modifier");
+ dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
+ __func__);
return 0;
}
@@ -236,7 +242,8 @@ static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effe
* Analyse the changes in an effect, and tell if we need to send an envelope
* parameter packet
*/
-static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effect)
+static int need_envelope_modifier(struct iforce *iforce, struct ff_effect *old,
+ struct ff_effect *effect)
{
switch (effect->type) {
case FF_CONSTANT:
@@ -256,7 +263,8 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec
break;
default:
- warn("bad effect type in need_envelope_modifier");
+ dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
+ __func__);
}
return 0;
@@ -266,10 +274,12 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec
* Analyse the changes in an effect, and tell if we need to send a periodic
* parameter effect
*/
-static int need_period_modifier(struct ff_effect *old, struct ff_effect *new)
+static int need_period_modifier(struct iforce *iforce, struct ff_effect *old,
+ struct ff_effect *new)
{
if (new->type != FF_PERIODIC) {
- warn("bad effect type in need_period_modifier");
+ dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
+ __func__);
return 0;
}
return (old->u.periodic.period != new->u.periodic.period
@@ -355,7 +365,7 @@ int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, stru
int param2_err = 1;
int core_err = 0;
- if (!old || need_period_modifier(old, effect)) {
+ if (!old || need_period_modifier(iforce, old, effect)) {
param1_err = make_period_modifier(iforce, mod1_chunk,
old != NULL,
effect->u.periodic.magnitude, effect->u.periodic.offset,
@@ -365,7 +375,7 @@ int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, stru
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
- if (!old || need_envelope_modifier(old, effect)) {
+ if (!old || need_envelope_modifier(iforce, old, effect)) {
param2_err = make_envelope_modifier(iforce, mod2_chunk,
old !=NULL,
effect->u.periodic.envelope.attack_length,
@@ -425,7 +435,7 @@ int iforce_upload_constant(struct iforce *iforce, struct ff_effect *effect, stru
int param2_err = 1;
int core_err = 0;
- if (!old || need_magnitude_modifier(old, effect)) {
+ if (!old || need_magnitude_modifier(iforce, old, effect)) {
param1_err = make_magnitude_modifier(iforce, mod1_chunk,
old != NULL,
effect->u.constant.level);
@@ -434,7 +444,7 @@ int iforce_upload_constant(struct iforce *iforce, struct ff_effect *effect, stru
set_bit(FF_MOD1_IS_USED, core_effect->flags);
}
- if (!old || need_envelope_modifier(old, effect)) {
+ if (!old || need_envelope_modifier(iforce, old, effect)) {
param2_err = make_envelope_modifier(iforce, mod2_chunk,
old != NULL,
effect->u.constant.envelope.attack_length,
@@ -487,7 +497,7 @@ int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, str
default: return -1;
}
- if (!old || need_condition_modifier(old, effect)) {
+ if (!old || need_condition_modifier(iforce, old, effect)) {
param_err = make_condition_modifier(iforce, mod1_chunk,
old != NULL,
effect->u.condition[0].right_saturation,
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 61ee6e38739..baabf830264 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -218,7 +218,9 @@ static void iforce_release(struct input_dev *dev)
/* Check: no effects should be present in memory */
for (i = 0; i < dev->ff->max_effects; i++) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) {
- warn("iforce_release: Device still owns effects");
+ dev_warn(&dev->dev,
+ "%s: Device still owns effects\n",
+ __func__);
break;
}
}
@@ -335,26 +337,26 @@ int iforce_init_device(struct iforce *iforce)
if (!iforce_get_id_packet(iforce, "M"))
input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
else
- warn("Device does not respond to id packet M");
+ dev_warn(&iforce->dev->dev, "Device does not respond to id packet M\n");
if (!iforce_get_id_packet(iforce, "P"))
input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
else
- warn("Device does not respond to id packet P");
+ dev_warn(&iforce->dev->dev, "Device does not respond to id packet P\n");
if (!iforce_get_id_packet(iforce, "B"))
iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
else
- warn("Device does not respond to id packet B");
+ dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n");
if (!iforce_get_id_packet(iforce, "N"))
ff_effects = iforce->edata[1];
else
- warn("Device does not respond to id packet N");
+ dev_warn(&iforce->dev->dev, "Device does not respond to id packet N\n");
/* Check if the device can store more effects than the driver can really handle */
if (ff_effects > IFORCE_EFFECTS_MAX) {
- warn("Limiting number of effects to %d (device reports %d)",
+ dev_warn(&iforce->dev->dev, "Limiting number of effects to %d (device reports %d)\n",
IFORCE_EFFECTS_MAX, ff_effects);
ff_effects = IFORCE_EFFECTS_MAX;
}
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 015b50aa76f..a17b5001600 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -65,7 +65,8 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
- warn("not enough space in xmit buffer to send new packet");
+ dev_warn(&iforce->dev->dev,
+ "not enough space in xmit buffer to send new packet\n");
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
return -1;
}
@@ -148,7 +149,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
return 0;
}
}
- warn("unused effect %04x updated !!!", addr);
+ dev_warn(&iforce->dev->dev, "unused effect %04x updated !!!\n", addr);
return -1;
}
@@ -159,7 +160,8 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
static int being_used = 0;
if (being_used)
- warn("re-entrant call to iforce_process %d", being_used);
+ dev_warn(&iforce->dev->dev,
+ "re-entrant call to iforce_process %d\n", being_used);
being_used++;
#ifdef CONFIG_JOYSTICK_IFORCE_232
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 851cc4087c2..f83185aeb51 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -64,7 +64,7 @@ void iforce_usb_xmit(struct iforce *iforce)
if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
- warn("usb_submit_urb failed %d\n", n);
+ dev_warn(&iforce->dev->dev, "usb_submit_urb failed %d\n", n);
}
/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index 8c3290b6820..2478289aeee 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = {
static int __init interact_init(void)
{
- gameport_register_driver(&interact_drv);
- return 0;
+ return gameport_register_driver(&interact_drv);
}
static void __exit interact_exit(void)
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 2a1b82c8b31..cd894a0564a 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = {
static int __init joydump_init(void)
{
- gameport_register_driver(&joydump_drv);
- return 0;
+ return gameport_register_driver(&joydump_drv);
}
static void __exit joydump_exit(void)
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 7b4865fdee5..ca13a6bec33 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = {
static int __init sw_init(void)
{
- gameport_register_driver(&sw_drv);
- return 0;
+ return gameport_register_driver(&sw_drv);
}
static void __exit sw_exit(void)
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 60c37bcb938..d6c60980711 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = {
static int __init tmdc_init(void)
{
- gameport_register_driver(&tmdc_drv);
- return 0;
+ return gameport_register_driver(&tmdc_drv);
}
static void __exit tmdc_exit(void)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 6791be81eb2..b868b8d5fbb 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -455,10 +455,10 @@ static void xpad_bulk_out(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
break;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
}
}
@@ -911,7 +911,7 @@ static int __init usb_xpad_init(void)
{
int result = usb_register(&xpad_driver);
if (result == 0)
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index b1ce10f50bc..22016ca1535 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio)
}
/*
- * Most special keys (Fn+F?) on Dell Latitudes do not generate release
+ * Most special keys (Fn+F?) on Dell laptops do not generate release
* events so we have to do it ourselves.
*/
-static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
+static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd)
{
const unsigned int forced_release_keys[] = {
0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93,
@@ -1207,15 +1207,13 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
{
struct input_dev *old_dev, *new_dev;
unsigned long value;
- char *rest;
int err;
unsigned char old_extra, old_set;
if (!atkbd->write)
return -EIO;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
if (atkbd->extra != value) {
@@ -1264,12 +1262,10 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
{
struct input_dev *old_dev, *new_dev;
unsigned long value;
- char *rest;
int err;
unsigned char old_scroll;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
if (atkbd->scroll != value) {
@@ -1310,15 +1306,13 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *old_dev, *new_dev;
unsigned long value;
- char *rest;
int err;
unsigned char old_set, old_extra;
if (!atkbd->write)
return -EIO;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || (value != 2 && value != 3))
+ if (strict_strtoul(buf, 10, &value) || (value != 2 && value != 3))
return -EINVAL;
if (atkbd->set != value) {
@@ -1361,15 +1355,13 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
{
struct input_dev *old_dev, *new_dev;
unsigned long value;
- char *rest;
int err;
unsigned char old_softrepeat, old_softraw;
if (!atkbd->write)
return -EIO;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
if (atkbd->softrepeat != value) {
@@ -1413,12 +1405,10 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
{
struct input_dev *old_dev, *new_dev;
unsigned long value;
- char *rest;
int err;
unsigned char old_softraw;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
if (atkbd->softraw != value) {
@@ -1461,13 +1451,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id)
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
{
- .ident = "Dell Latitude series",
+ .ident = "Dell Laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
},
.callback = atkbd_setup_fixup,
- .driver_data = atkbd_latitude_keymap_fixup,
+ .driver_data = atkbd_dell_laptop_keymap_fixup,
},
{
.ident = "HP 2133",
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
index e348cfccc17..19284016e0f 100644
--- a/drivers/input/keyboard/bf54x-keys.c
+++ b/drivers/input/keyboard/bf54x-keys.c
@@ -8,7 +8,7 @@
*
*
* Modified:
- * Copyright 2007 Analog Devices Inc.
+ * Copyright 2007-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -81,6 +81,9 @@ struct bf54x_kpad {
unsigned short *keycode;
struct timer_list timer;
unsigned int keyup_test_jiffies;
+ unsigned short kpad_msel;
+ unsigned short kpad_prescale;
+ unsigned short kpad_ctl;
};
static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad,
@@ -360,6 +363,10 @@ static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
{
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+ bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL();
+ bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE();
+ bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL();
+
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(bf54x_kpad->irq);
@@ -370,6 +377,10 @@ static int bfin_kpad_resume(struct platform_device *pdev)
{
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+ bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel);
+ bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale);
+ bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl);
+
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(bf54x_kpad->irq);
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 134e67bf6a9..c8ed065ea0c 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -80,9 +80,9 @@ struct corgikbd {
#define KB_ACTIVATE_DELAY 10
/* Helper functions for reading the keyboard matrix
- * Note: We should really be using pxa_gpio_mode to alter GPDR but it
- * requires a function call per GPIO bit which is excessive
- * when we need to access 12 bits at once multiple times.
+ * Note: We should really be using the generic gpio functions to alter
+ * GPDR but it requires a function call per GPIO bit which is
+ * excessive when we need to access 12 bits at once, multiple times.
* These functions must be called within local_irq_save()/local_irq_restore()
* or similar.
*/
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ec96b369dd7..05f3f43582c 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -36,9 +36,10 @@ struct gpio_keys_drvdata {
struct gpio_button_data data[0];
};
-static void gpio_keys_report_event(struct gpio_keys_button *button,
- struct input_dev *input)
+static void gpio_keys_report_event(struct gpio_button_data *bdata)
{
+ struct gpio_keys_button *button = bdata->button;
+ struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
@@ -50,34 +51,23 @@ static void gpio_check_button(unsigned long _data)
{
struct gpio_button_data *data = (struct gpio_button_data *)_data;
- gpio_keys_report_event(data->button, data->input);
+ gpio_keys_report_event(data);
}
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
- struct platform_device *pdev = dev_id;
- struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
- struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
- int i;
+ struct gpio_button_data *bdata = dev_id;
+ struct gpio_keys_button *button = bdata->button;
- for (i = 0; i < pdata->nbuttons; i++) {
- struct gpio_keys_button *button = &pdata->buttons[i];
+ BUG_ON(irq != gpio_to_irq(button->gpio));
- if (irq == gpio_to_irq(button->gpio)) {
- struct gpio_button_data *bdata = &ddata->data[i];
-
- if (button->debounce_interval)
- mod_timer(&bdata->timer,
- jiffies +
- msecs_to_jiffies(button->debounce_interval));
- else
- gpio_keys_report_event(button, bdata->input);
-
- return IRQ_HANDLED;
- }
- }
+ if (button->debounce_interval)
+ mod_timer(&bdata->timer,
+ jiffies + msecs_to_jiffies(button->debounce_interval));
+ else
+ gpio_keys_report_event(bdata);
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static int __devinit gpio_keys_probe(struct platform_device *pdev)
@@ -151,7 +141,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
- pdev);
+ bdata);
if (error) {
pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
@@ -178,7 +168,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail2:
while (--i >= 0) {
- free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+ free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio);
@@ -203,7 +193,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
- free_irq(irq, pdev);
+ free_irq(irq, &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio);
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index dcea87a0bc5..69e674ecf19 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -62,7 +62,7 @@ struct omap_kp {
unsigned int debounce;
};
-DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
static int *keymap;
static unsigned int *row_gpios;
@@ -72,12 +72,9 @@ static unsigned int *col_gpios;
static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value)
{
int col;
- for (col = 0; col < omap_kp->cols; col++) {
- if (value & (1 << col))
- omap_set_gpio_dataout(col_gpios[col], 1);
- else
- omap_set_gpio_dataout(col_gpios[col], 0);
- }
+
+ for (col = 0; col < omap_kp->cols; col++)
+ gpio_set_value(col_gpios[col], value & (1 << col));
}
static u8 get_row_gpio_val(struct omap_kp *omap_kp)
@@ -86,7 +83,7 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp)
u8 value = 0;
for (row = 0; row < omap_kp->rows; row++) {
- if (omap_get_gpio_datain(row_gpios[row]))
+ if (gpio_get_value(row_gpios[row]))
value |= (1 << row);
}
return value;
@@ -333,23 +330,23 @@ static int __init omap_kp_probe(struct platform_device *pdev)
if (cpu_is_omap24xx()) {
/* Cols: outputs */
for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
- if (omap_request_gpio(col_gpios[col_idx]) < 0) {
+ if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) {
printk(KERN_ERR "Failed to request"
"GPIO%d for keypad\n",
col_gpios[col_idx]);
goto err1;
}
- omap_set_gpio_direction(col_gpios[col_idx], 0);
+ gpio_direction_output(col_gpios[col_idx], 0);
}
/* Rows: inputs */
for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
- if (omap_request_gpio(row_gpios[row_idx]) < 0) {
+ if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) {
printk(KERN_ERR "Failed to request"
"GPIO%d for keypad\n",
row_gpios[row_idx]);
goto err2;
}
- omap_set_gpio_direction(row_gpios[row_idx], 1);
+ gpio_direction_input(row_gpios[row_idx]);
}
} else {
col_idx = 0;
@@ -418,10 +415,10 @@ err3:
device_remove_file(&pdev->dev, &dev_attr_enable);
err2:
for (i = row_idx - 1; i >=0; i--)
- omap_free_gpio(row_gpios[i]);
+ gpio_free(row_gpios[i]);
err1:
for (i = col_idx - 1; i >=0; i--)
- omap_free_gpio(col_gpios[i]);
+ gpio_free(col_gpios[i]);
kfree(omap_kp);
input_free_device(input_dev);
@@ -438,9 +435,9 @@ static int omap_kp_remove(struct platform_device *pdev)
if (cpu_is_omap24xx()) {
int i;
for (i = 0; i < omap_kp->cols; i++)
- omap_free_gpio(col_gpios[i]);
+ gpio_free(col_gpios[i]);
for (i = 0; i < omap_kp->rows; i++) {
- omap_free_gpio(row_gpios[i]);
+ gpio_free(row_gpios[i]);
free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
}
} else {
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index de67b8e0a79..c48b76a46a5 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -101,9 +101,9 @@ struct spitzkbd {
#define KB_ACTIVATE_DELAY 10
/* Helper functions for reading the keyboard matrix
- * Note: We should really be using pxa_gpio_mode to alter GPDR but it
- * requires a function call per GPIO bit which is excessive
- * when we need to access 11 bits at once, multiple times.
+ * Note: We should really be using the generic gpio functions to alter
+ * GPDR but it requires a function call per GPIO bit which is
+ * excessive when we need to access 11 bits at once, multiple times.
* These functions must be called within local_irq_save()/local_irq_restore()
* or similar.
*/
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
index 44cb50af3ce..677276b1202 100644
--- a/drivers/input/keyboard/tosakbd.c
+++ b/drivers/input/keyboard/tosakbd.c
@@ -59,9 +59,9 @@ struct tosakbd {
/* Helper functions for reading the keyboard matrix
- * Note: We should really be using pxa_gpio_mode to alter GPDR but it
- * requires a function call per GPIO bit which is excessive
- * when we need to access 12 bits at once, multiple times.
+ * Note: We should really be using the generic gpio functions to alter
+ * GPDR but it requires a function call per GPIO bit which is
+ * excessive when we need to access 12 bits at once, multiple times.
* These functions must be called within local_irq_save()/local_irq_restore()
* or similar.
*/
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index e99b7882f38..199055db508 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -180,6 +180,19 @@ config INPUT_YEALINK
To compile this driver as a module, choose M here: the module will be
called yealink.
+config INPUT_CM109
+ tristate "C-Media CM109 USB I/O Controller"
+ depends on EXPERIMENTAL
+ depends on USB_ARCH_HAS_HCD
+ select USB
+ help
+ Say Y here if you want to enable keyboard and buzzer functions of the
+ C-Media CM109 usb phones. The audio part is enabled by the generic
+ usb sound driver, so you might want to enable that as well.
+
+ To compile this driver as a module, choose M here: the module will be
+ called cm109.
+
config INPUT_UINPUT
tristate "User level driver support"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f48009b5222..d7db2aeb8a9 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
+obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c
index debfc1af9d9..e290fde35e7 100644
--- a/drivers/input/misc/ati_remote.c
+++ b/drivers/input/misc/ati_remote.c
@@ -285,7 +285,6 @@ static const struct {
};
/* Local function prototypes */
-static void ati_remote_dump (unsigned char *data, unsigned int actual_length);
static int ati_remote_open (struct input_dev *inputdev);
static void ati_remote_close (struct input_dev *inputdev);
static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
@@ -307,15 +306,16 @@ static struct usb_driver ati_remote_driver = {
/*
* ati_remote_dump_input
*/
-static void ati_remote_dump(unsigned char *data, unsigned int len)
+static void ati_remote_dump(struct device *dev, unsigned char *data,
+ unsigned int len)
{
if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00))
- warn("Weird byte 0x%02x", data[0]);
+ dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
else if (len == 4)
- warn("Weird key %02x %02x %02x %02x",
+ dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
data[0], data[1], data[2], data[3]);
else
- warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...",
+ dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
len, data[0], data[1], data[2], data[3], data[4], data[5]);
}
@@ -470,7 +470,7 @@ static void ati_remote_input_report(struct urb *urb)
/* Deal with strange looking inputs */
if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
((data[3] & 0x0f) != 0x00) ) {
- ati_remote_dump(data, urb->actual_length);
+ ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
return;
}
@@ -814,7 +814,7 @@ static void ati_remote_disconnect(struct usb_interface *interface)
ati_remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!ati_remote) {
- warn("%s - null device?\n", __func__);
+ dev_warn(&interface->dev, "%s - null device?\n", __func__);
return;
}
@@ -834,9 +834,11 @@ static int __init ati_remote_init(void)
result = usb_register(&ati_remote_driver);
if (result)
- err("usb_register error #%d\n", result);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": usb_register error #%d\n", result);
else
- info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index a7fabafbd94..3c9988dc0e9 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -1,8 +1,8 @@
/*
* ati_remote2 - ATI/Philips USB RF remote driver
*
- * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
- * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk>
+ * Copyright (C) 2005-2008 Ville Syrjala <syrjala@sci.fi>
+ * Copyright (C) 2007-2008 Peter Stokes <linux@dadeos.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -12,7 +12,7 @@
#include <linux/usb/input.h>
#define DRIVER_DESC "ATI/Philips USB RF remote driver"
-#define DRIVER_VERSION "0.2"
+#define DRIVER_VERSION "0.3"
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
@@ -27,7 +27,7 @@ MODULE_LICENSE("GPL");
* A remote's "channel" may be altered by pressing and holding the "PC" button for
* approximately 3 seconds, after which the button will slowly flash the count of the
* currently configured "channel", using the numeric keypad enter a number between 1 and
- * 16 and then the "PC" button again, the button will slowly flash the count of the
+ * 16 and then press the "PC" button again, the button will slowly flash the count of the
* newly configured "channel".
*/
@@ -45,9 +45,25 @@ static struct usb_device_id ati_remote2_id_table[] = {
};
MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
-static struct {
- int hw_code;
- int key_code;
+static DEFINE_MUTEX(ati_remote2_mutex);
+
+enum {
+ ATI_REMOTE2_OPENED = 0x1,
+ ATI_REMOTE2_SUSPENDED = 0x2,
+};
+
+enum {
+ ATI_REMOTE2_AUX1,
+ ATI_REMOTE2_AUX2,
+ ATI_REMOTE2_AUX3,
+ ATI_REMOTE2_AUX4,
+ ATI_REMOTE2_PC,
+ ATI_REMOTE2_MODES,
+};
+
+static const struct {
+ u8 hw_code;
+ u16 keycode;
} ati_remote2_key_table[] = {
{ 0x00, KEY_0 },
{ 0x01, KEY_1 },
@@ -73,6 +89,7 @@ static struct {
{ 0x37, KEY_RECORD },
{ 0x38, KEY_DVD },
{ 0x39, KEY_TV },
+ { 0x3f, KEY_PROG1 }, /* AUX1-AUX4 and PC */
{ 0x54, KEY_MENU },
{ 0x58, KEY_UP },
{ 0x59, KEY_DOWN },
@@ -91,15 +108,9 @@ static struct {
{ 0xa9, BTN_LEFT },
{ 0xaa, BTN_RIGHT },
{ 0xbe, KEY_QUESTION },
- { 0xd5, KEY_FRONT },
{ 0xd0, KEY_EDIT },
+ { 0xd5, KEY_FRONT },
{ 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 {
@@ -117,46 +128,106 @@ struct ati_remote2 {
char name[64];
char phys[64];
+
+ /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */
+ u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)];
+
+ unsigned int flags;
};
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 int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message);
+static int ati_remote2_resume(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,
+ .suspend = ati_remote2_suspend,
+ .resume = ati_remote2_resume,
+ .supports_autosuspend = 1,
};
-static int ati_remote2_open(struct input_dev *idev)
+static int ati_remote2_submit_urbs(struct ati_remote2 *ar2)
{
- struct ati_remote2 *ar2 = input_get_drvdata(idev);
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", __func__, r);
+ "%s(): usb_submit_urb() = %d\n", __func__, 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", __func__, r);
+ "%s(): usb_submit_urb() = %d\n", __func__, r);
return r;
}
return 0;
}
+static void ati_remote2_kill_urbs(struct ati_remote2 *ar2)
+{
+ usb_kill_urb(ar2->urb[1]);
+ usb_kill_urb(ar2->urb[0]);
+}
+
+static int ati_remote2_open(struct input_dev *idev)
+{
+ struct ati_remote2 *ar2 = input_get_drvdata(idev);
+ int r;
+
+ dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+ r = usb_autopm_get_interface(ar2->intf[0]);
+ if (r) {
+ dev_err(&ar2->intf[0]->dev,
+ "%s(): usb_autopm_get_interface() = %d\n", __func__, r);
+ goto fail1;
+ }
+
+ mutex_lock(&ati_remote2_mutex);
+
+ if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) {
+ r = ati_remote2_submit_urbs(ar2);
+ if (r)
+ goto fail2;
+ }
+
+ ar2->flags |= ATI_REMOTE2_OPENED;
+
+ mutex_unlock(&ati_remote2_mutex);
+
+ usb_autopm_put_interface(ar2->intf[0]);
+
+ return 0;
+
+ fail2:
+ mutex_unlock(&ati_remote2_mutex);
+ usb_autopm_put_interface(ar2->intf[0]);
+ fail1:
+ return r;
+}
+
static void ati_remote2_close(struct input_dev *idev)
{
struct ati_remote2 *ar2 = input_get_drvdata(idev);
- usb_kill_urb(ar2->urb[0]);
- usb_kill_urb(ar2->urb[1]);
+ dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+ mutex_lock(&ati_remote2_mutex);
+
+ if (!(ar2->flags & ATI_REMOTE2_SUSPENDED))
+ ati_remote2_kill_urbs(ar2);
+
+ ar2->flags &= ~ATI_REMOTE2_OPENED;
+
+ mutex_unlock(&ati_remote2_mutex);
}
static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
@@ -172,7 +243,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
mode = data[0] & 0x0F;
- if (mode > 4) {
+ if (mode > ATI_REMOTE2_PC) {
dev_err(&ar2->intf[0]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
@@ -191,7 +262,7 @@ static int ati_remote2_lookup(unsigned int hw_code)
{
int i;
- for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+ for (i = 0; i < ARRAY_SIZE(ati_remote2_key_table); i++)
if (ati_remote2_key_table[i].hw_code == hw_code)
return i;
@@ -211,7 +282,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
mode = data[0] & 0x0F;
- if (mode > 4) {
+ if (mode > ATI_REMOTE2_PC) {
dev_err(&ar2->intf[1]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
@@ -219,10 +290,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
}
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
@@ -236,8 +303,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
if (data[1] == 0)
ar2->mode = mode;
-
- hw_code |= mode << 8;
}
if (!((1 << mode) & mode_mask))
@@ -260,8 +325,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
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)
+ if (ar2->keycode[mode][index] == BTN_LEFT ||
+ ar2->keycode[mode][index] == BTN_RIGHT)
return;
if (!time_after_eq(jiffies, ar2->jiffies))
@@ -276,7 +341,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
return;
}
- input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
+ input_event(idev, EV_KEY, ar2->keycode[mode][index], data[1]);
input_sync(idev);
}
@@ -287,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
switch (urb->status) {
case 0:
+ usb_mark_last_busy(ar2->udev);
ati_remote2_input_mouse(ar2);
break;
case -ENOENT:
@@ -297,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
"%s(): urb status = %d\n", __func__, urb->status);
return;
default:
+ usb_mark_last_busy(ar2->udev);
dev_err(&ar2->intf[0]->dev,
"%s(): urb status = %d\n", __func__, urb->status);
}
@@ -314,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb)
switch (urb->status) {
case 0:
+ usb_mark_last_busy(ar2->udev);
ati_remote2_input_key(ar2);
break;
case -ENOENT:
@@ -324,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb)
"%s(): urb status = %d\n", __func__, urb->status);
return;
default:
+ usb_mark_last_busy(ar2->udev);
dev_err(&ar2->intf[1]->dev,
"%s(): urb status = %d\n", __func__, urb->status);
}
@@ -334,10 +403,60 @@ static void ati_remote2_complete_key(struct urb *urb)
"%s(): usb_submit_urb() = %d\n", __func__, r);
}
+static int ati_remote2_getkeycode(struct input_dev *idev,
+ int scancode, int *keycode)
+{
+ struct ati_remote2 *ar2 = input_get_drvdata(idev);
+ int index, mode;
+
+ mode = scancode >> 8;
+ if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
+ return -EINVAL;
+
+ index = ati_remote2_lookup(scancode & 0xFF);
+ if (index < 0)
+ return -EINVAL;
+
+ *keycode = ar2->keycode[mode][index];
+ return 0;
+}
+
+static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode)
+{
+ struct ati_remote2 *ar2 = input_get_drvdata(idev);
+ int index, mode, old_keycode;
+
+ mode = scancode >> 8;
+ if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
+ return -EINVAL;
+
+ index = ati_remote2_lookup(scancode & 0xFF);
+ if (index < 0)
+ return -EINVAL;
+
+ if (keycode < KEY_RESERVED || keycode > KEY_MAX)
+ return -EINVAL;
+
+ old_keycode = ar2->keycode[mode][index];
+ ar2->keycode[mode][index] = keycode;
+ set_bit(keycode, idev->keybit);
+
+ for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
+ for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
+ if (ar2->keycode[mode][index] == old_keycode)
+ return 0;
+ }
+ }
+
+ clear_bit(old_keycode, idev->keybit);
+
+ return 0;
+}
+
static int ati_remote2_input_init(struct ati_remote2 *ar2)
{
struct input_dev *idev;
- int i, retval;
+ int index, mode, retval;
idev = input_allocate_device();
if (!idev)
@@ -350,8 +469,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT);
idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(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);
+
+ for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
+ for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
+ ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode;
+ set_bit(ar2->keycode[mode][index], idev->keybit);
+ }
+ }
+
+ /* AUX1-AUX4 and PC generate the same scancode. */
+ index = ati_remote2_lookup(0x3f);
+ ar2->keycode[ATI_REMOTE2_AUX1][index] = KEY_PROG1;
+ ar2->keycode[ATI_REMOTE2_AUX2][index] = KEY_PROG2;
+ ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3;
+ ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4;
+ ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC;
+ set_bit(KEY_PROG1, idev->keybit);
+ set_bit(KEY_PROG2, idev->keybit);
+ set_bit(KEY_PROG3, idev->keybit);
+ set_bit(KEY_PROG4, idev->keybit);
+ set_bit(KEY_PC, idev->keybit);
idev->rep[REP_DELAY] = 250;
idev->rep[REP_PERIOD] = 33;
@@ -359,6 +496,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
idev->open = ati_remote2_open;
idev->close = ati_remote2_close;
+ idev->getkeycode = ati_remote2_getkeycode;
+ idev->setkeycode = ati_remote2_setkeycode;
+
idev->name = ar2->name;
idev->phys = ar2->phys;
@@ -490,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
usb_set_intfdata(interface, ar2);
+ interface->needs_remote_wakeup = 1;
+
return 0;
fail2:
@@ -522,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface)
kfree(ar2);
}
+static int ati_remote2_suspend(struct usb_interface *interface,
+ pm_message_t message)
+{
+ struct ati_remote2 *ar2;
+ struct usb_host_interface *alt = interface->cur_altsetting;
+
+ if (alt->desc.bInterfaceNumber)
+ return 0;
+
+ ar2 = usb_get_intfdata(interface);
+
+ dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+ mutex_lock(&ati_remote2_mutex);
+
+ if (ar2->flags & ATI_REMOTE2_OPENED)
+ ati_remote2_kill_urbs(ar2);
+
+ ar2->flags |= ATI_REMOTE2_SUSPENDED;
+
+ mutex_unlock(&ati_remote2_mutex);
+
+ return 0;
+}
+
+static int ati_remote2_resume(struct usb_interface *interface)
+{
+ struct ati_remote2 *ar2;
+ struct usb_host_interface *alt = interface->cur_altsetting;
+ int r = 0;
+
+ if (alt->desc.bInterfaceNumber)
+ return 0;
+
+ ar2 = usb_get_intfdata(interface);
+
+ dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+ mutex_lock(&ati_remote2_mutex);
+
+ if (ar2->flags & ATI_REMOTE2_OPENED)
+ r = ati_remote2_submit_urbs(ar2);
+
+ if (!r)
+ ar2->flags &= ~ATI_REMOTE2_SUSPENDED;
+
+ mutex_unlock(&ati_remote2_mutex);
+
+ return r;
+}
+
static int __init ati_remote2_init(void)
{
int r;
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
new file mode 100644
index 00000000000..bce160f4349
--- /dev/null
+++ b/drivers/input/misc/cm109.c
@@ -0,0 +1,882 @@
+/*
+ * Driver for the VoIP USB phones with CM109 chipsets.
+ *
+ * Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.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, version 2.
+ */
+
+/*
+ * Tested devices:
+ * - Komunikate KIP1000
+ * - Genius G-talk
+ * - Allied-Telesis Corega USBPH01
+ * - ...
+ *
+ * This driver is based on the yealink.c driver
+ *
+ * Thanks to:
+ * - Authors of yealink.c
+ * - Thomas Reitmayr
+ * - Oliver Neukum for good review comments and code
+ * - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap
+ * - Dmitry Torokhov for valuable input and review
+ *
+ * Todo:
+ * - Read/write EEPROM
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/rwsem.h>
+#include <linux/usb/input.h>
+
+#define DRIVER_VERSION "20080805"
+#define DRIVER_AUTHOR "Alfred E. Heggestad"
+#define DRIVER_DESC "CM109 phone driver"
+
+static char *phone = "kip1000";
+module_param(phone, charp, S_IRUSR);
+MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}");
+
+enum {
+ /* HID Registers */
+ HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down */
+ HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0 */
+ HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1 */
+ HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL */
+ HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */
+ HID_OR1 = 0x01, /* GPO - General Purpose Output */
+ HID_OR2 = 0x02, /* Set GPIO to input/output mode */
+ HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL */
+
+ /* HID_IR0 */
+ RECORD_MUTE = 1 << 3,
+ PLAYBACK_MUTE = 1 << 2,
+ VOLUME_DOWN = 1 << 1,
+ VOLUME_UP = 1 << 0,
+
+ /* HID_OR0 */
+ /* bits 7-6
+ 0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer
+ and SPDIF
+ 1: HID_OR0-3 are used as generic HID registers
+ 2: Values written to HID_OR0-3 are also mapped to MCU_CTRL,
+ EEPROM_DATA0-1, EEPROM_CTRL (see Note)
+ 3: Reserved
+ */
+ HID_OR_GPO_BUZ_SPDIF = 0 << 6,
+ HID_OR_GENERIC_HID_REG = 1 << 6,
+ HID_OR_MAP_MCU_EEPROM = 2 << 6,
+
+ BUZZER_ON = 1 << 5,
+
+ /* up to 256 normal keys, up to 16 special keys */
+ KEYMAP_SIZE = 256 + 16,
+};
+
+/* CM109 protocol packet */
+struct cm109_ctl_packet {
+ u8 byte[4];
+} __attribute__ ((packed));
+
+enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) };
+
+/* CM109 device structure */
+struct cm109_dev {
+ struct input_dev *idev; /* input device */
+ struct usb_device *udev; /* usb device */
+ struct usb_interface *intf;
+
+ /* irq input channel */
+ struct cm109_ctl_packet *irq_data;
+ dma_addr_t irq_dma;
+ struct urb *urb_irq;
+
+ /* control output channel */
+ struct cm109_ctl_packet *ctl_data;
+ dma_addr_t ctl_dma;
+ struct usb_ctrlrequest *ctl_req;
+ dma_addr_t ctl_req_dma;
+ struct urb *urb_ctl;
+ /*
+ * The 3 bitfields below are protected by ctl_submit_lock.
+ * They have to be separate since they are accessed from IRQ
+ * context.
+ */
+ unsigned irq_urb_pending:1; /* irq_urb is in flight */
+ unsigned ctl_urb_pending:1; /* ctl_urb is in flight */
+ unsigned buzzer_pending:1; /* need to issue buzz command */
+ spinlock_t ctl_submit_lock;
+
+ unsigned char buzzer_state; /* on/off */
+
+ /* flags */
+ unsigned open:1;
+ unsigned resetting:1;
+ unsigned shutdown:1;
+
+ /* This mutex protects writes to the above flags */
+ struct mutex pm_mutex;
+
+ unsigned short keymap[KEYMAP_SIZE];
+
+ char phys[64]; /* physical device path */
+ int key_code; /* last reported key */
+ int keybit; /* 0=new scan 1,2,4,8=scan columns */
+ u8 gpi; /* Cached value of GPI (high nibble) */
+};
+
+/******************************************************************************
+ * CM109 key interface
+ *****************************************************************************/
+
+static unsigned short special_keymap(int code)
+{
+ if (code > 0xff) {
+ switch (code - 0xff) {
+ case RECORD_MUTE: return KEY_MUTE;
+ case PLAYBACK_MUTE: return KEY_MUTE;
+ case VOLUME_DOWN: return KEY_VOLUMEDOWN;
+ case VOLUME_UP: return KEY_VOLUMEUP;
+ }
+ }
+ return KEY_RESERVED;
+}
+
+/* Map device buttons to internal key events.
+ *
+ * The "up" and "down" keys, are symbolised by arrows on the button.
+ * The "pickup" and "hangup" keys are symbolised by a green and red phone
+ * on the button.
+
+ Komunikate KIP1000 Keyboard Matrix
+
+ -> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10)
+ | | | |
+ <- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20)
+ | | | |
+ END - 7 -- 8 -- 9 --> GPI pin 6 (0x40)
+ | | | |
+ OK -- * -- 0 -- # --> GPI pin 7 (0x80)
+ | | | |
+
+ /|\ /|\ /|\ /|\
+ | | | |
+GPO
+pin: 3 2 1 0
+ 0x8 0x4 0x2 0x1
+
+ */
+static unsigned short keymap_kip1000(int scancode)
+{
+ switch (scancode) { /* phone key: */
+ case 0x82: return KEY_NUMERIC_0; /* 0 */
+ case 0x14: return KEY_NUMERIC_1; /* 1 */
+ case 0x12: return KEY_NUMERIC_2; /* 2 */
+ case 0x11: return KEY_NUMERIC_3; /* 3 */
+ case 0x24: return KEY_NUMERIC_4; /* 4 */
+ case 0x22: return KEY_NUMERIC_5; /* 5 */
+ case 0x21: return KEY_NUMERIC_6; /* 6 */
+ case 0x44: return KEY_NUMERIC_7; /* 7 */
+ case 0x42: return KEY_NUMERIC_8; /* 8 */
+ case 0x41: return KEY_NUMERIC_9; /* 9 */
+ case 0x81: return KEY_NUMERIC_POUND; /* # */
+ case 0x84: return KEY_NUMERIC_STAR; /* * */
+ case 0x88: return KEY_ENTER; /* pickup */
+ case 0x48: return KEY_ESC; /* hangup */
+ case 0x28: return KEY_LEFT; /* IN */
+ case 0x18: return KEY_RIGHT; /* OUT */
+ default: return special_keymap(scancode);
+ }
+}
+
+/*
+ Contributed by Shaun Jackman <sjackman@gmail.com>
+
+ Genius G-Talk keyboard matrix
+ 0 1 2 3
+ 4: 0 4 8 Talk
+ 5: 1 5 9 End
+ 6: 2 6 # Up
+ 7: 3 7 * Down
+*/
+static unsigned short keymap_gtalk(int scancode)
+{
+ switch (scancode) {
+ case 0x11: return KEY_NUMERIC_0;
+ case 0x21: return KEY_NUMERIC_1;
+ case 0x41: return KEY_NUMERIC_2;
+ case 0x81: return KEY_NUMERIC_3;
+ case 0x12: return KEY_NUMERIC_4;
+ case 0x22: return KEY_NUMERIC_5;
+ case 0x42: return KEY_NUMERIC_6;
+ case 0x82: return KEY_NUMERIC_7;
+ case 0x14: return KEY_NUMERIC_8;
+ case 0x24: return KEY_NUMERIC_9;
+ case 0x44: return KEY_NUMERIC_POUND; /* # */
+ case 0x84: return KEY_NUMERIC_STAR; /* * */
+ case 0x18: return KEY_ENTER; /* Talk (green handset) */
+ case 0x28: return KEY_ESC; /* End (red handset) */
+ case 0x48: return KEY_UP; /* Menu up (rocker switch) */
+ case 0x88: return KEY_DOWN; /* Menu down (rocker switch) */
+ default: return special_keymap(scancode);
+ }
+}
+
+/*
+ * Keymap for Allied-Telesis Corega USBPH01
+ * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html
+ *
+ * Contributed by july@nat.bg
+ */
+static unsigned short keymap_usbph01(int scancode)
+{
+ switch (scancode) {
+ case 0x11: return KEY_NUMERIC_0; /* 0 */
+ case 0x21: return KEY_NUMERIC_1; /* 1 */
+ case 0x41: return KEY_NUMERIC_2; /* 2 */
+ case 0x81: return KEY_NUMERIC_3; /* 3 */
+ case 0x12: return KEY_NUMERIC_4; /* 4 */
+ case 0x22: return KEY_NUMERIC_5; /* 5 */
+ case 0x42: return KEY_NUMERIC_6; /* 6 */
+ case 0x82: return KEY_NUMERIC_7; /* 7 */
+ case 0x14: return KEY_NUMERIC_8; /* 8 */
+ case 0x24: return KEY_NUMERIC_9; /* 9 */
+ case 0x44: return KEY_NUMERIC_POUND; /* # */
+ case 0x84: return KEY_NUMERIC_STAR; /* * */
+ case 0x18: return KEY_ENTER; /* pickup */
+ case 0x28: return KEY_ESC; /* hangup */
+ case 0x48: return KEY_LEFT; /* IN */
+ case 0x88: return KEY_RIGHT; /* OUT */
+ default: return special_keymap(scancode);
+ }
+}
+
+static unsigned short (*keymap)(int) = keymap_kip1000;
+
+/*
+ * Completes a request by converting the data into events for the
+ * input subsystem.
+ */
+static void report_key(struct cm109_dev *dev, int key)
+{
+ struct input_dev *idev = dev->idev;
+
+ if (dev->key_code >= 0) {
+ /* old key up */
+ input_report_key(idev, dev->key_code, 0);
+ }
+
+ dev->key_code = key;
+ if (key >= 0) {
+ /* new valid key */
+ input_report_key(idev, key, 1);
+ }
+
+ input_sync(idev);
+}
+
+/******************************************************************************
+ * CM109 usb communication interface
+ *****************************************************************************/
+
+static void cm109_submit_buzz_toggle(struct cm109_dev *dev)
+{
+ int error;
+
+ if (dev->buzzer_state)
+ dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+ else
+ dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+ error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
+ if (error)
+ err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+}
+
+/*
+ * IRQ handler
+ */
+static void cm109_urb_irq_callback(struct urb *urb)
+{
+ struct cm109_dev *dev = urb->context;
+ const int status = urb->status;
+ int error;
+
+ dev_dbg(&urb->dev->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n",
+ dev->irq_data->byte[0],
+ dev->irq_data->byte[1],
+ dev->irq_data->byte[2],
+ dev->irq_data->byte[3],
+ dev->keybit);
+
+ if (status) {
+ if (status == -ESHUTDOWN)
+ return;
+ err("%s: urb status %d", __func__, status);
+ }
+
+ /* Special keys */
+ if (dev->irq_data->byte[HID_IR0] & 0x0f) {
+ const int code = (dev->irq_data->byte[HID_IR0] & 0x0f);
+ report_key(dev, dev->keymap[0xff + code]);
+ }
+
+ /* Scan key column */
+ if (dev->keybit == 0xf) {
+
+ /* Any changes ? */
+ if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0))
+ goto out;
+
+ dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0;
+ dev->keybit = 0x1;
+ } else {
+ report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]);
+
+ dev->keybit <<= 1;
+ if (dev->keybit > 0x8)
+ dev->keybit = 0xf;
+ }
+
+ out:
+
+ spin_lock(&dev->ctl_submit_lock);
+
+ dev->irq_urb_pending = 0;
+
+ if (likely(!dev->shutdown)) {
+
+ if (dev->buzzer_state)
+ dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+ else
+ dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+ dev->ctl_data->byte[HID_OR1] = dev->keybit;
+ dev->ctl_data->byte[HID_OR2] = dev->keybit;
+
+ dev->buzzer_pending = 0;
+ dev->ctl_urb_pending = 1;
+
+ error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
+ if (error)
+ err("%s: usb_submit_urb (urb_ctl) failed %d",
+ __func__, error);
+ }
+
+ spin_unlock(&dev->ctl_submit_lock);
+}
+
+static void cm109_urb_ctl_callback(struct urb *urb)
+{
+ struct cm109_dev *dev = urb->context;
+ const int status = urb->status;
+ int error;
+
+ dev_dbg(&urb->dev->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
+ dev->ctl_data->byte[0],
+ dev->ctl_data->byte[1],
+ dev->ctl_data->byte[2],
+ dev->ctl_data->byte[3]);
+
+ if (status)
+ err("%s: urb status %d", __func__, status);
+
+ spin_lock(&dev->ctl_submit_lock);
+
+ dev->ctl_urb_pending = 0;
+
+ if (likely(!dev->shutdown)) {
+
+ if (dev->buzzer_pending) {
+ dev->buzzer_pending = 0;
+ dev->ctl_urb_pending = 1;
+ cm109_submit_buzz_toggle(dev);
+ } else if (likely(!dev->irq_urb_pending)) {
+ /* ask for key data */
+ dev->irq_urb_pending = 1;
+ error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC);
+ if (error)
+ err("%s: usb_submit_urb (urb_irq) failed %d",
+ __func__, error);
+ }
+ }
+
+ spin_unlock(&dev->ctl_submit_lock);
+}
+
+static void cm109_toggle_buzzer_async(struct cm109_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->ctl_submit_lock, flags);
+
+ if (dev->ctl_urb_pending) {
+ /* URB completion will resubmit */
+ dev->buzzer_pending = 1;
+ } else {
+ dev->ctl_urb_pending = 1;
+ cm109_submit_buzz_toggle(dev);
+ }
+
+ spin_unlock_irqrestore(&dev->ctl_submit_lock, flags);
+}
+
+static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on)
+{
+ int error;
+
+ if (on)
+ dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+ else
+ dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+ error = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ dev->ctl_req->bRequest,
+ dev->ctl_req->bRequestType,
+ le16_to_cpu(dev->ctl_req->wValue),
+ le16_to_cpu(dev->ctl_req->wIndex),
+ dev->ctl_data,
+ USB_PKT_LEN, USB_CTRL_SET_TIMEOUT);
+ if (error && error != EINTR)
+ err("%s: usb_control_msg() failed %d", __func__, error);
+}
+
+static void cm109_stop_traffic(struct cm109_dev *dev)
+{
+ dev->shutdown = 1;
+ /*
+ * Make sure other CPUs see this
+ */
+ smp_wmb();
+
+ usb_kill_urb(dev->urb_ctl);
+ usb_kill_urb(dev->urb_irq);
+
+ cm109_toggle_buzzer_sync(dev, 0);
+
+ dev->shutdown = 0;
+ smp_wmb();
+}
+
+static void cm109_restore_state(struct cm109_dev *dev)
+{
+ if (dev->open) {
+ /*
+ * Restore buzzer state.
+ * This will also kick regular URB submission
+ */
+ cm109_toggle_buzzer_async(dev);
+ }
+}
+
+/******************************************************************************
+ * input event interface
+ *****************************************************************************/
+
+static int cm109_input_open(struct input_dev *idev)
+{
+ struct cm109_dev *dev = input_get_drvdata(idev);
+ int error;
+
+ error = usb_autopm_get_interface(dev->intf);
+ if (error < 0) {
+ err("%s - cannot autoresume, result %d",
+ __func__, error);
+ return error;
+ }
+
+ mutex_lock(&dev->pm_mutex);
+
+ dev->buzzer_state = 0;
+ dev->key_code = -1; /* no keys pressed */
+ dev->keybit = 0xf;
+
+ /* issue INIT */
+ dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF;
+ dev->ctl_data->byte[HID_OR1] = dev->keybit;
+ dev->ctl_data->byte[HID_OR2] = dev->keybit;
+ dev->ctl_data->byte[HID_OR3] = 0x00;
+
+ error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
+ if (error)
+ err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+ else
+ dev->open = 1;
+
+ mutex_unlock(&dev->pm_mutex);
+
+ if (error)
+ usb_autopm_put_interface(dev->intf);
+
+ return error;
+}
+
+static void cm109_input_close(struct input_dev *idev)
+{
+ struct cm109_dev *dev = input_get_drvdata(idev);
+
+ mutex_lock(&dev->pm_mutex);
+
+ /*
+ * Once we are here event delivery is stopped so we
+ * don't need to worry about someone starting buzzer
+ * again
+ */
+ cm109_stop_traffic(dev);
+ dev->open = 0;
+
+ mutex_unlock(&dev->pm_mutex);
+
+ usb_autopm_put_interface(dev->intf);
+}
+
+static int cm109_input_ev(struct input_dev *idev, unsigned int type,
+ unsigned int code, int value)
+{
+ struct cm109_dev *dev = input_get_drvdata(idev);
+
+ dev_dbg(&dev->udev->dev,
+ "input_ev: type=%u code=%u value=%d\n", type, code, value);
+
+ if (type != EV_SND)
+ return -EINVAL;
+
+ switch (code) {
+ case SND_TONE:
+ case SND_BELL:
+ dev->buzzer_state = !!value;
+ if (!dev->resetting)
+ cm109_toggle_buzzer_async(dev);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+
+/******************************************************************************
+ * Linux interface and usb initialisation
+ *****************************************************************************/
+
+struct driver_info {
+ char *name;
+};
+
+static const struct driver_info info_cm109 = {
+ .name = "CM109 USB driver",
+};
+
+enum {
+ VENDOR_ID = 0x0d8c, /* C-Media Electronics */
+ PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */
+};
+
+/* table of devices that work with this driver */
+static const struct usb_device_id cm109_usb_table[] = {
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = VENDOR_ID,
+ .idProduct = PRODUCT_ID_CM109,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .driver_info = (kernel_ulong_t) &info_cm109
+ },
+ /* you can add more devices here with product ID 0x0008 - 0x000f */
+ { }
+};
+
+static void cm109_usb_cleanup(struct cm109_dev *dev)
+{
+ if (dev->ctl_req)
+ usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)),
+ dev->ctl_req, dev->ctl_req_dma);
+ if (dev->ctl_data)
+ usb_buffer_free(dev->udev, USB_PKT_LEN,
+ dev->ctl_data, dev->ctl_dma);
+ if (dev->irq_data)
+ usb_buffer_free(dev->udev, USB_PKT_LEN,
+ dev->irq_data, dev->irq_dma);
+
+ usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */
+ usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */
+ kfree(dev);
+}
+
+static void cm109_usb_disconnect(struct usb_interface *interface)
+{
+ struct cm109_dev *dev = usb_get_intfdata(interface);
+
+ usb_set_intfdata(interface, NULL);
+ input_unregister_device(dev->idev);
+ cm109_usb_cleanup(dev);
+}
+
+static int cm109_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct driver_info *nfo = (struct driver_info *)id->driver_info;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct cm109_dev *dev;
+ struct input_dev *input_dev = NULL;
+ int ret, pipe, i;
+ int error = -ENOMEM;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+
+ if (!usb_endpoint_is_int_in(endpoint))
+ return -ENODEV;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ spin_lock_init(&dev->ctl_submit_lock);
+ mutex_init(&dev->pm_mutex);
+
+ dev->udev = udev;
+ dev->intf = intf;
+
+ dev->idev = input_dev = input_allocate_device();
+ if (!input_dev)
+ goto err_out;
+
+ /* allocate usb buffers */
+ dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ GFP_KERNEL, &dev->irq_dma);
+ if (!dev->irq_data)
+ goto err_out;
+
+ dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ GFP_KERNEL, &dev->ctl_dma);
+ if (!dev->ctl_data)
+ goto err_out;
+
+ dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)),
+ GFP_KERNEL, &dev->ctl_req_dma);
+ if (!dev->ctl_req)
+ goto err_out;
+
+ /* allocate urb structures */
+ dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb_irq)
+ goto err_out;
+
+ dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb_ctl)
+ goto err_out;
+
+ /* get a handle to the interrupt data pipe */
+ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+ ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ if (ret != USB_PKT_LEN)
+ err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+
+ /* initialise irq urb */
+ usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data,
+ USB_PKT_LEN,
+ cm109_urb_irq_callback, dev, endpoint->bInterval);
+ dev->urb_irq->transfer_dma = dev->irq_dma;
+ dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ dev->urb_irq->dev = udev;
+
+ /* initialise ctl urb */
+ dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
+ USB_DIR_OUT;
+ dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION;
+ dev->ctl_req->wValue = cpu_to_le16(0x200);
+ dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
+ dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN);
+
+ usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+ (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN,
+ cm109_urb_ctl_callback, dev);
+ dev->urb_ctl->setup_dma = dev->ctl_req_dma;
+ dev->urb_ctl->transfer_dma = dev->ctl_dma;
+ dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
+ URB_NO_TRANSFER_DMA_MAP;
+ dev->urb_ctl->dev = udev;
+
+ /* find out the physical bus location */
+ usb_make_path(udev, dev->phys, sizeof(dev->phys));
+ strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+ /* register settings for the input device */
+ input_dev->name = nfo->name;
+ input_dev->phys = dev->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+
+ input_set_drvdata(input_dev, dev);
+ input_dev->open = cm109_input_open;
+ input_dev->close = cm109_input_close;
+ input_dev->event = cm109_input_ev;
+
+ input_dev->keycode = dev->keymap;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(dev->keymap);
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND);
+ input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+
+ /* register available key events */
+ for (i = 0; i < KEYMAP_SIZE; i++) {
+ unsigned short k = keymap(i);
+ dev->keymap[i] = k;
+ __set_bit(k, input_dev->keybit);
+ }
+ __clear_bit(KEY_RESERVED, input_dev->keybit);
+
+ error = input_register_device(dev->idev);
+ if (error)
+ goto err_out;
+
+ usb_set_intfdata(intf, dev);
+
+ return 0;
+
+ err_out:
+ input_free_device(input_dev);
+ cm109_usb_cleanup(dev);
+ return error;
+}
+
+static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct cm109_dev *dev = usb_get_intfdata(intf);
+
+ dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event);
+
+ mutex_lock(&dev->pm_mutex);
+ cm109_stop_traffic(dev);
+ mutex_unlock(&dev->pm_mutex);
+
+ return 0;
+}
+
+static int cm109_usb_resume(struct usb_interface *intf)
+{
+ struct cm109_dev *dev = usb_get_intfdata(intf);
+
+ dev_info(&intf->dev, "cm109: usb_resume\n");
+
+ mutex_lock(&dev->pm_mutex);
+ cm109_restore_state(dev);
+ mutex_unlock(&dev->pm_mutex);
+
+ return 0;
+}
+
+static int cm109_usb_pre_reset(struct usb_interface *intf)
+{
+ struct cm109_dev *dev = usb_get_intfdata(intf);
+
+ mutex_lock(&dev->pm_mutex);
+
+ /*
+ * Make sure input events don't try to toggle buzzer
+ * while we are resetting
+ */
+ dev->resetting = 1;
+ smp_wmb();
+
+ cm109_stop_traffic(dev);
+
+ return 0;
+}
+
+static int cm109_usb_post_reset(struct usb_interface *intf)
+{
+ struct cm109_dev *dev = usb_get_intfdata(intf);
+
+ dev->resetting = 0;
+ smp_wmb();
+
+ cm109_restore_state(dev);
+
+ mutex_unlock(&dev->pm_mutex);
+
+ return 0;
+}
+
+static struct usb_driver cm109_driver = {
+ .name = "cm109",
+ .probe = cm109_usb_probe,
+ .disconnect = cm109_usb_disconnect,
+ .suspend = cm109_usb_suspend,
+ .resume = cm109_usb_resume,
+ .reset_resume = cm109_usb_resume,
+ .pre_reset = cm109_usb_pre_reset,
+ .post_reset = cm109_usb_post_reset,
+ .id_table = cm109_usb_table,
+ .supports_autosuspend = 1,
+};
+
+static int __init cm109_select_keymap(void)
+{
+ /* Load the phone keymap */
+ if (!strcasecmp(phone, "kip1000")) {
+ keymap = keymap_kip1000;
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ "Keymap for Komunikate KIP1000 phone loaded\n");
+ } else if (!strcasecmp(phone, "gtalk")) {
+ keymap = keymap_gtalk;
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ "Keymap for Genius G-talk phone loaded\n");
+ } else if (!strcasecmp(phone, "usbph01")) {
+ keymap = keymap_usbph01;
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ "Keymap for Allied-Telesis Corega USBPH01 phone loaded\n");
+ } else {
+ printk(KERN_ERR KBUILD_MODNAME ": "
+ "Unsupported phone: %s\n", phone);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init cm109_init(void)
+{
+ int err;
+
+ err = cm109_select_keymap();
+ if (err)
+ return err;
+
+ err = usb_register(&cm109_driver);
+ if (err)
+ return err;
+
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR "\n");
+
+ return 0;
+}
+
+static void __exit cm109_exit(void)
+{
+ usb_deregister(&cm109_driver);
+}
+
+module_init(cm109_init);
+module_exit(cm109_exit);
+
+MODULE_DEVICE_TABLE(usb, cm109_usb_table);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index daa9d422033..82ec6b1b646 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -458,35 +458,35 @@ static int hp_sdc_rtc_proc_output (char *buf)
p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
} else {
p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n",
- tv.tv_sec, tv.tv_usec/1000);
+ tv.tv_sec, (int)tv.tv_usec/1000);
}
if (hp_sdc_rtc_read_fhs(&tv)) {
p += sprintf(p, "handshake\t: READ FAILED!\n");
} else {
p += sprintf(p, "handshake\t: %ld.%02d seconds\n",
- tv.tv_sec, tv.tv_usec/1000);
+ tv.tv_sec, (int)tv.tv_usec/1000);
}
if (hp_sdc_rtc_read_mt(&tv)) {
p += sprintf(p, "alarm\t\t: READ FAILED!\n");
} else {
p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n",
- tv.tv_sec, tv.tv_usec/1000);
+ tv.tv_sec, (int)tv.tv_usec/1000);
}
if (hp_sdc_rtc_read_dt(&tv)) {
p += sprintf(p, "delay\t\t: READ FAILED!\n");
} else {
p += sprintf(p, "delay\t\t: %ld.%02d seconds\n",
- tv.tv_sec, tv.tv_usec/1000);
+ tv.tv_sec, (int)tv.tv_usec/1000);
}
if (hp_sdc_rtc_read_ct(&tv)) {
p += sprintf(p, "periodic\t: READ FAILED!\n");
} else {
p += sprintf(p, "periodic\t: %ld.%02d seconds\n",
- tv.tv_sec, tv.tv_usec/1000);
+ tv.tv_sec, (int)tv.tv_usec/1000);
}
p += sprintf(p,
diff --git a/drivers/input/misc/map_to_7segment.h b/drivers/input/misc/map_to_7segment.h
deleted file mode 100644
index a424094d9fe..00000000000
--- a/drivers/input/misc/map_to_7segment.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * drivers/usb/input/map_to_7segment.h
- *
- * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef MAP_TO_7SEGMENT_H
-#define MAP_TO_7SEGMENT_H
-
-/* This file provides translation primitives and tables for the conversion
- * of (ASCII) characters to a 7-segments notation.
- *
- * The 7 segment's wikipedia notation below is used as standard.
- * See: http://en.wikipedia.org/wiki/Seven_segment_display
- *
- * Notation: +-a-+
- * f b
- * +-g-+
- * e c
- * +-d-+
- *
- * Usage:
- *
- * Register a map variable, and fill it with a character set:
- * static SEG7_DEFAULT_MAP(map_seg7);
- *
- *
- * Then use for conversion:
- * seg7 = map_to_seg7(&map_seg7, some_char);
- * ...
- *
- * In device drivers it is recommended, if required, to make the char map
- * accessible via the sysfs interface using the following scheme:
- *
- * static ssize_t show_map(struct device *dev, char *buf) {
- * memcpy(buf, &map_seg7, sizeof(map_seg7));
- * return sizeof(map_seg7);
- * }
- * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) {
- * if(cnt != sizeof(map_seg7))
- * return -EINVAL;
- * memcpy(&map_seg7, buf, cnt);
- * return cnt;
- * }
- * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map);
- *
- * History:
- * 2005-05-31 RFC linux-kernel@vger.kernel.org
- */
-#include <linux/errno.h>
-
-
-#define BIT_SEG7_A 0
-#define BIT_SEG7_B 1
-#define BIT_SEG7_C 2
-#define BIT_SEG7_D 3
-#define BIT_SEG7_E 4
-#define BIT_SEG7_F 5
-#define BIT_SEG7_G 6
-#define BIT_SEG7_RESERVED 7
-
-struct seg7_conversion_map {
- unsigned char table[128];
-};
-
-static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
-{
- return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL;
-}
-
-#define SEG7_CONVERSION_MAP(_name, _map) \
- struct seg7_conversion_map _name = { .table = { _map } }
-
-/*
- * It is recommended to use a facility that allows user space to redefine
- * custom character sets for LCD devices. Please use a sysfs interface
- * as described above.
- */
-#define MAP_TO_SEG7_SYSFS_FILE "map_seg7"
-
-/*******************************************************************************
- * ASCII conversion table
- ******************************************************************************/
-
-#define _SEG7(l,a,b,c,d,e,f,g) \
- ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \
- e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G )
-
-#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-
-#define _MAP_33_47_ASCII_SEG7_SYMBOL \
- _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\
- _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\
- _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\
- _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\
- _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1),
-
-#define _MAP_48_57_ASCII_SEG7_NUMERIC \
- _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\
- _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\
- _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\
- _SEG7('9',1,1,1,1,0,1,1),
-
-#define _MAP_58_64_ASCII_SEG7_SYMBOL \
- _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\
- _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\
- _SEG7('@',1,1,0,1,1,1,1),
-
-#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \
- _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\
- _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
- _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\
- _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
- _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\
- _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\
- _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\
- _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
- _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
-
-#define _MAP_91_96_ASCII_SEG7_SYMBOL \
- _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\
- _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0),
-
-#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
- _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\
- _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
- _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\
- _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
- _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\
- _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\
- _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\
- _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
- _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
-
-#define _MAP_123_126_ASCII_SEG7_SYMBOL \
- _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\
- _SEG7('~',1,0,0,0,0,0,0),
-
-/* Maps */
-
-/* This set tries to map as close as possible to the visible characteristics
- * of the ASCII symbol, lowercase and uppercase letters may differ in
- * presentation on the display.
- */
-#define MAP_ASCII7SEG_ALPHANUM \
- _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
- _MAP_33_47_ASCII_SEG7_SYMBOL \
- _MAP_48_57_ASCII_SEG7_NUMERIC \
- _MAP_58_64_ASCII_SEG7_SYMBOL \
- _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \
- _MAP_91_96_ASCII_SEG7_SYMBOL \
- _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
- _MAP_123_126_ASCII_SEG7_SYMBOL
-
-/* This set tries to map as close as possible to the symbolic characteristics
- * of the ASCII character for maximum discrimination.
- * For now this means all alpha chars are in lower case representations.
- * (This for example facilitates the use of hex numbers with uppercase input.)
- */
-#define MAP_ASCII7SEG_ALPHANUM_LC \
- _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
- _MAP_33_47_ASCII_SEG7_SYMBOL \
- _MAP_48_57_ASCII_SEG7_NUMERIC \
- _MAP_58_64_ASCII_SEG7_SYMBOL \
- _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
- _MAP_91_96_ASCII_SEG7_SYMBOL \
- _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
- _MAP_123_126_ASCII_SEG7_SYMBOL
-
-#define SEG7_DEFAULT_MAP(_name) \
- SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM)
-
-#endif /* MAP_TO_7SEGMENT_H */
-
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index d8765cc93d2..c4f42311fde 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -249,7 +249,7 @@ static int bbc_remove(struct of_device *op)
return 0;
}
-static struct of_device_id bbc_beep_match[] = {
+static const struct of_device_id bbc_beep_match[] = {
{
.name = "beep",
.compatible = "SUNW,bbc-beep",
@@ -328,7 +328,7 @@ static int grover_remove(struct of_device *op)
return 0;
}
-static struct of_device_id grover_beep_match[] = {
+static const struct of_device_id grover_beep_match[] = {
{
.name = "beep",
.compatible = "SUNW,smbus-beep",
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index fe268be3293..7c8957dd22c 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
{ KE_END, 0 }
};
+static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
+ { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */
+ { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
+ { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */
+ { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */
+ { KE_KEY, 0x36, {KEY_WWW} }, /* www button */
+ { KE_WIFI, 0x78 }, /* satelite dish button */
+ { KE_END, 0 }
+};
+
static struct key_entry keymap_fujitsu_n3510[] __initdata = {
{ KE_KEY, 0x11, {KEY_PROG1} },
{ KE_KEY, 0x12, {KEY_PROG2} },
@@ -618,6 +628,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
},
{
.callback = dmi_matched,
+ .ident = "Fujitsu-Siemens Amilo Pro Edition V3505",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
+ },
+ .driver_data = keymap_fs_amilo_pro_v3505
+ },
+ {
+ .callback = dmi_matched,
.ident = "Fujitsu-Siemens Amilo M7400",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index facefd3dba2..93a22ac0f88 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -52,8 +52,8 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/usb/input.h>
+#include <linux/map_to_7segment.h>
-#include "map_to_7segment.h"
#include "yealink.h"
#define DRIVER_VERSION "yld-20051230"
@@ -999,7 +999,8 @@ static int __init yealink_dev_init(void)
{
int ret = usb_register(&yealink_driver);
if (ret == 0)
- info(DRIVER_DESC ":" DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return ret;
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index f996546fc44..f488b6852ba 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
If unsure, say N.
+config MOUSE_PS2_OLPC
+ bool "OLPC PS/2 mouse protocol extension"
+ depends on MOUSE_PS2 && OLPC
+ help
+ Say Y here if you have an OLPC XO-1 laptop (with built-in
+ PS/2 touchpad/tablet device). The manufacturer calls the
+ touchpad an HGPK.
+
+ If unsure, say N.
+
config MOUSE_SERIAL
tristate "Serial mouse"
select SERIO
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index d4d20251609..8e6e6909780 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs := psmouse-base.o synaptics.o
psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o
+psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o
psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 385e32bcf6a..cbedf957cc5 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -54,6 +54,7 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
+ { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
};
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 1f41ae94f26..079816e6b23 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table);
#define ATP_GEYSER_MODE_REQUEST_INDEX 0
#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04
+/**
+ * enum atp_status_bits - status bit meanings
+ *
+ * These constants represent the meaning of the status bits.
+ * (only Geyser 3/4)
+ *
+ * @ATP_STATUS_BUTTON: The button was pressed
+ * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad)
+ * @ATP_STATUS_FROM_RESET: Reset previously performed
+ */
+enum atp_status_bits {
+ ATP_STATUS_BUTTON = BIT(0),
+ ATP_STATUS_BASE_UPDATE = BIT(2),
+ ATP_STATUS_FROM_RESET = BIT(4),
+};
+
/* Structure to hold all of our device specific stuff */
struct atp {
char phys[64];
struct usb_device *udev; /* usb device */
struct urb *urb; /* usb request block */
- signed char *data; /* transferred data */
+ u8 *data; /* transferred data */
struct input_dev *input; /* input dev */
enum atp_touchpad_type type; /* type of touchpad */
bool open;
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work)
int retval;
dprintk("appletouch: putting appletouch to sleep (reinit)\n");
- dev->idlecount = 0;
-
atp_geyser_init(udev);
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
}
-static void atp_complete(struct urb *urb)
+/* Check URB status and for correct length of data package */
+
+#define ATP_URB_STATUS_SUCCESS 0
+#define ATP_URB_STATUS_ERROR 1
+#define ATP_URB_STATUS_ERROR_FATAL 2
+
+static int atp_status_check(struct urb *urb)
{
- int x, y, x_z, y_z, x_f, y_f;
- int retval, i, j;
- int key;
struct atp *dev = urb->context;
switch (urb->status) {
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb)
/* This urb is terminated, clean up */
dbg("atp_complete: urb shutting down with status: %d",
urb->status);
- return;
+ return ATP_URB_STATUS_ERROR_FATAL;
+
default:
dbg("atp_complete: nonzero urb status received: %d",
urb->status);
- goto exit;
+ return ATP_URB_STATUS_ERROR;
}
/* drop incomplete datasets */
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb)
dprintk("appletouch: incomplete data package"
" (first byte: %d, length: %d).\n",
dev->data[0], dev->urb->actual_length);
- goto exit;
+ return ATP_URB_STATUS_ERROR;
}
- /* reorder the sensors values */
- if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
- memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+ return ATP_URB_STATUS_SUCCESS;
+}
- /*
- * The values are laid out like this:
- * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
- * '-' is an unused value.
- */
+/*
+ * USB interrupt callback functions
+ */
- /* read X values */
- for (i = 0, j = 19; i < 20; i += 2, j += 3) {
- dev->xy_cur[i] = dev->data[j + 1];
- dev->xy_cur[i + 1] = dev->data[j + 2];
- }
- /* read Y values */
- for (i = 0, j = 1; i < 9; i += 2, j += 3) {
- dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
- dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
- }
- } else if (dev->type == ATP_GEYSER2) {
+/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */
+
+static void atp_complete_geyser_1_2(struct urb *urb)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i, j;
+ int key;
+ struct atp *dev = urb->context;
+ int status = atp_status_check(urb);
+
+ if (status == ATP_URB_STATUS_ERROR_FATAL)
+ return;
+ else if (status == ATP_URB_STATUS_ERROR)
+ goto exit;
+
+ /* reorder the sensors values */
+ if (dev->type == ATP_GEYSER2) {
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
/*
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb)
/* first sample */
dev->valid = true;
dev->x_old = dev->y_old = -1;
+
+ /* Store first sample */
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
- if (dev->size_detect_done ||
- dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */
- goto exit;
+ /* Perform size detection, if not done already */
+ if (!dev->size_detect_done) {
+
+ /* 17" Powerbooks have extra X sensors */
+ for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
+ i < ATP_XSENSORS; i++) {
+ if (!dev->xy_cur[i])
+ continue;
+
+ printk(KERN_INFO
+ "appletouch: 17\" model detected.\n");
+
+ if (dev->type == ATP_GEYSER2)
+ input_set_abs_params(dev->input, ABS_X,
+ 0,
+ (20 - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ else
+ input_set_abs_params(dev->input, ABS_X,
+ 0,
+ (26 - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ break;
+ }
- /* 17" Powerbooks have extra X sensors */
- for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
- i < ATP_XSENSORS; i++) {
- if (!dev->xy_cur[i])
- continue;
-
- printk(KERN_INFO "appletouch: 17\" model detected.\n");
- if (dev->type == ATP_GEYSER2)
- input_set_abs_params(dev->input, ABS_X, 0,
- (20 - 1) *
- ATP_XFACT - 1,
- ATP_FUZZ, 0);
- else
- input_set_abs_params(dev->input, ABS_X, 0,
- (ATP_XSENSORS - 1) *
- ATP_XFACT - 1,
- ATP_FUZZ, 0);
- break;
+ dev->size_detect_done = 1;
+ goto exit;
}
-
- dev->size_detect_done = 1;
- goto exit;
}
for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb)
ATP_XFACT, &x_z, &x_f);
y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
ATP_YFACT, &y_z, &y_f);
- key = dev->data[dev->datalen - 1] & 1;
+ key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+
+ if (x && y) {
+ if (dev->x_old != -1) {
+ x = (dev->x_old * 3 + x) >> 2;
+ y = (dev->y_old * 3 + y) >> 2;
+ dev->x_old = x;
+ dev->y_old = y;
+
+ if (debug > 1)
+ printk(KERN_DEBUG "appletouch: "
+ "X: %3d Y: %3d Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+
+ input_report_key(dev->input, BTN_TOUCH, 1);
+ input_report_abs(dev->input, ABS_X, x);
+ input_report_abs(dev->input, ABS_Y, y);
+ input_report_abs(dev->input, ABS_PRESSURE,
+ min(ATP_PRESSURE, x_z + y_z));
+ atp_report_fingers(dev->input, max(x_f, y_f));
+ }
+ dev->x_old = x;
+ dev->y_old = y;
+
+ } else if (!x && !y) {
+
+ dev->x_old = dev->y_old = -1;
+ input_report_key(dev->input, BTN_TOUCH, 0);
+ input_report_abs(dev->input, ABS_PRESSURE, 0);
+ atp_report_fingers(dev->input, 0);
+
+ /* reset the accumulator on release */
+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+ }
+
+ input_report_key(dev->input, BTN_LEFT, key);
+ input_sync(dev->input);
+
+ exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval)
+ err("atp_complete: usb_submit_urb failed with result %d",
+ retval);
+}
+
+/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */
+
+static void atp_complete_geyser_3_4(struct urb *urb)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i, j;
+ int key;
+ struct atp *dev = urb->context;
+ int status = atp_status_check(urb);
+
+ if (status == ATP_URB_STATUS_ERROR_FATAL)
+ return;
+ else if (status == ATP_URB_STATUS_ERROR)
+ goto exit;
+
+ /* Reorder the sensors values:
+ *
+ * The values are laid out like this:
+ * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
+ * '-' is an unused value.
+ */
+
+ /* read X values */
+ for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+ dev->xy_cur[i] = dev->data[j + 1];
+ dev->xy_cur[i + 1] = dev->data[j + 2];
+ }
+ /* read Y values */
+ for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+ dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
+ dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ /* Just update the base values (i.e. touchpad in untouched state) */
+ if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
+
+ dprintk(KERN_DEBUG "appletouch: updated base values\n");
+
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+ /* calculate the change */
+ dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i];
+
+ /* this is a round-robin value, so couple with that */
+ if (dev->xy_acc[i] > 127)
+ dev->xy_acc[i] -= 256;
+
+ if (dev->xy_acc[i] < -127)
+ dev->xy_acc[i] += 256;
+
+ /* prevent down drifting */
+ if (dev->xy_acc[i] < 0)
+ dev->xy_acc[i] = 0;
+ }
+
+ dbg_dump("accumulator", dev->xy_acc);
+
+ x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+ ATP_XFACT, &x_z, &x_f);
+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+ ATP_YFACT, &y_z, &y_f);
+ key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
if (x && y) {
if (dev->x_old != -1) {
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb)
input_sync(dev->input);
/*
- * Many Geysers will continue to send packets continually after
+ * Geysers 3/4 will continue to send packets continually after
* the first touch unless reinitialised. Do so if it's been
* idle for a while in order to avoid waking the kernel up
- * several hundred times a second. Re-initialization does not
- * work on Fountain touchpads.
+ * several hundred times a second.
*/
- if (dev->type != ATP_FOUNTAIN) {
- /*
- * Button must not be pressed when entering suspend,
- * otherwise we will never release the button.
- */
- if (!x && !y && !key) {
- dev->idlecount++;
- if (dev->idlecount == 10) {
- dev->valid = false;
- schedule_work(&dev->work);
- /* Don't resubmit urb here, wait for reinit */
- return;
- }
- } else
+
+ /*
+ * Button must not be pressed when entering suspend,
+ * otherwise we will never release the button.
+ */
+ if (!x && !y && !key) {
+ dev->idlecount++;
+ if (dev->idlecount == 10) {
+ dev->x_old = dev->y_old = -1;
dev->idlecount = 0;
- }
+ schedule_work(&dev->work);
+ /* Don't resubmit urb here, wait for reinit */
+ return;
+ }
+ } else
+ dev->idlecount = 0;
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface,
if (!dev->data)
goto err_free_urb;
- usb_fill_int_urb(dev->urb, udev,
- usb_rcvintpipe(udev, int_in_endpointAddr),
- dev->data, dev->datalen, atp_complete, dev, 1);
+ /* Select the USB complete (callback) function */
+ if (dev->type == ATP_FOUNTAIN ||
+ dev->type == ATP_GEYSER1 ||
+ dev->type == ATP_GEYSER2)
+ usb_fill_int_urb(dev->urb, udev,
+ usb_rcvintpipe(udev, int_in_endpointAddr),
+ dev->data, dev->datalen,
+ atp_complete_geyser_1_2, dev, 1);
+ else
+ usb_fill_int_urb(dev->urb, udev,
+ usb_rcvintpipe(udev, int_in_endpointAddr),
+ dev->data, dev->datalen,
+ atp_complete_geyser_3_4, dev, 1);
error = atp_handle_geyser(dev);
if (error)
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message)
struct atp *dev = usb_get_intfdata(iface);
usb_kill_urb(dev->urb);
- dev->valid = false;
-
return 0;
}
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 2ec921bf3c6..2998a6ac9ae 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -63,7 +63,7 @@
}
/* table of devices that work with this driver */
-static const struct usb_device_id bcm5974_table [] = {
+static const struct usb_device_id bcm5974_table[] = {
/* MacbookAir1.1 */
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
@@ -105,7 +105,7 @@ struct tp_header {
/* trackpad finger structure */
struct tp_finger {
- __le16 origin; /* left/right origin? */
+ __le16 origin; /* zero when switching track finger */
__le16 abs_x; /* absolute x coodinate */
__le16 abs_y; /* absolute y coodinate */
__le16 rel_x; /* relative x coodinate */
@@ -159,6 +159,7 @@ struct bcm5974 {
struct bt_data *bt_data; /* button transferred data */
struct urb *tp_urb; /* trackpad usb request block */
struct tp_data *tp_data; /* trackpad transferred data */
+ int fingers; /* number of fingers on trackpad */
};
/* logical dimensions */
@@ -172,6 +173,10 @@ struct bcm5974 {
#define SN_WIDTH 100 /* width signal-to-noise ratio */
#define SN_COORD 250 /* coordinate signal-to-noise ratio */
+/* pressure thresholds */
+#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE)
+#define PRESSURE_HIGH (3 * PRESSURE_LOW)
+
/* device constants */
static const struct bcm5974_config bcm5974_config_table[] = {
{
@@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
0, cfg->y.dim, cfg->y.fuzz, 0);
__set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
@@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size)
const struct tp_finger *f = dev->tp_data->finger;
struct input_dev *input = dev->input;
const int fingers = (size - 26) / 28;
- int p = 0, w, x, y, n = 0;
+ int raw_p, raw_w, raw_x, raw_y;
+ int ptest = 0, origin = 0, nmin = 0, nmax = 0;
+ int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
if (size < 26 || (size - 26) % 28 != 0)
return -EIO;
+ /* always track the first finger; when detached, start over */
if (fingers) {
- p = raw2int(f->force_major);
- w = raw2int(f->size_major);
- x = raw2int(f->abs_x);
- y = raw2int(f->abs_y);
- n = p > 0 ? fingers : 0;
+ raw_p = raw2int(f->force_major);
+ raw_w = raw2int(f->size_major);
+ raw_x = raw2int(f->abs_x);
+ raw_y = raw2int(f->abs_y);
dprintk(9,
- "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
- p, w, x, y, n);
+ "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
+ raw_p, raw_w, raw_x, raw_y);
+
+ ptest = int2bound(&c->p, raw_p);
+ origin = raw2int(f->origin);
+ }
- input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
- input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
- input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
+ /* while tracking finger still valid, count all fingers */
+ if (ptest > PRESSURE_LOW && origin) {
+ abs_p = ptest;
+ abs_w = int2bound(&c->w, raw_w);
+ abs_x = int2bound(&c->x, raw_x - c->x.devmin);
+ abs_y = int2bound(&c->y, c->y.devmax - raw_y);
+ for (; f != dev->tp_data->finger + fingers; f++) {
+ ptest = int2bound(&c->p, raw2int(f->force_major));
+ if (ptest > PRESSURE_LOW)
+ nmax++;
+ if (ptest > PRESSURE_HIGH)
+ nmin++;
+ }
}
- input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
+ if (dev->fingers < nmin)
+ dev->fingers = nmin;
+ if (dev->fingers > nmax)
+ dev->fingers = nmax;
+
+ input_report_key(input, BTN_TOUCH, dev->fingers > 0);
+ input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
- input_report_key(input, BTN_TOOL_FINGER, n == 1);
- input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
- input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
+ input_report_abs(input, ABS_PRESSURE, abs_p);
+ input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
+
+ if (abs_p) {
+ input_report_abs(input, ABS_X, abs_x);
+ input_report_abs(input, ABS_Y, abs_y);
+
+ dprintk(8,
+ "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
+ "nmin: %d nmax: %d n: %d\n",
+ abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
+
+ }
input_sync(input);
@@ -311,8 +351,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
+#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08
-static int bcm5974_wellspring_mode(struct bcm5974 *dev)
+static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
{
char *data = kmalloc(8, GFP_KERNEL);
int retval = 0, size;
@@ -337,7 +378,9 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev)
}
/* apply the mode switch */
- data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE;
+ data[0] = on ?
+ BCM5974_WELLSPRING_MODE_VENDOR_VALUE :
+ BCM5974_WELLSPRING_MODE_NORMAL_VALUE;
/* write configuration */
size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
@@ -352,7 +395,8 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev)
goto out;
}
- dprintk(2, "bcm5974: switched to wellspring mode.\n");
+ dprintk(2, "bcm5974: switched to %s mode.\n",
+ on ? "wellspring" : "normal");
out:
kfree(data);
@@ -441,7 +485,7 @@ exit:
*/
static int bcm5974_start_traffic(struct bcm5974 *dev)
{
- if (bcm5974_wellspring_mode(dev)) {
+ if (bcm5974_wellspring_mode(dev, true)) {
dprintk(1, "bcm5974: mode switch failed\n");
goto error;
}
@@ -464,6 +508,7 @@ static void bcm5974_pause_traffic(struct bcm5974 *dev)
{
usb_kill_urb(dev->tp_urb);
usb_kill_urb(dev->bt_urb);
+ bcm5974_wellspring_mode(dev, false);
}
/*
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
new file mode 100644
index 00000000000..e82d34201e9
--- /dev/null
+++ b/drivers/input/mouse/hgpk.c
@@ -0,0 +1,477 @@
+/*
+ * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
+ *
+ * Copyright (c) 2006-2008 One Laptop Per Child
+ * Authors:
+ * Zephaniah E. Hull
+ * Andres Salomon <dilinger@debian.org>
+ *
+ * This driver is partly based on the ALPS driver, which is:
+ *
+ * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
+ * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ *
+ * 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.
+ */
+
+/*
+ * The spec from ALPS is available from
+ * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this
+ * device as HGPK (Hybrid GS, PT, and Keymatrix).
+ *
+ * The earliest versions of the device had simultaneous reporting; that
+ * was removed. After that, the device used the Advanced Mode GS/PT streaming
+ * stuff. That turned out to be too buggy to support, so we've finally
+ * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
+ */
+
+#define DEBUG
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+#include <linux/delay.h>
+#include <asm/olpc.h>
+
+#include "psmouse.h"
+#include "hgpk.h"
+
+static int tpdebug;
+module_param(tpdebug, int, 0644);
+MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
+
+static int recalib_delta = 100;
+module_param(recalib_delta, int, 0644);
+MODULE_PARM_DESC(recalib_delta,
+ "packets containing a delta this large will cause a recalibration.");
+
+/*
+ * When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
+ * above the pad and still have it send packets. This causes a jump cursor
+ * when one places their finger on the pad. We can probably detect the
+ * jump as we see a large deltas (>= 100px). In mouse mode, I've been
+ * unable to even come close to 100px deltas during normal usage, so I think
+ * this threshold is safe. If a large delta occurs, trigger a recalibration.
+ */
+static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
+{
+ struct hgpk_data *priv = psmouse->private;
+
+ if (abs(x) > recalib_delta || abs(y) > recalib_delta) {
+ hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n",
+ recalib_delta, x, y);
+ /* My car gets forty rods to the hogshead and that's the
+ * way I likes it! */
+ psmouse_queue_work(psmouse, &priv->recalib_wq,
+ msecs_to_jiffies(1000));
+ }
+}
+
+/*
+ * We have no idea why this particular hardware bug occurs. The touchpad
+ * will randomly start spewing packets without anything touching the
+ * pad. This wouldn't necessarily be bad, but it's indicative of a
+ * severely miscalibrated pad; attempting to use the touchpad while it's
+ * spewing means the cursor will jump all over the place, and act "drunk".
+ *
+ * The packets that are spewed tend to all have deltas between -2 and 2, and
+ * the cursor will move around without really going very far. It will
+ * tend to end up in the same location; if we tally up the changes over
+ * 100 packets, we end up w/ a final delta of close to 0. This happens
+ * pretty regularly when the touchpad is spewing, and is pretty hard to
+ * manually trigger (at least for *my* fingers). So, it makes a perfect
+ * scheme for detecting spews.
+ */
+static void hgpk_spewing_hack(struct psmouse *psmouse,
+ int l, int r, int x, int y)
+{
+ struct hgpk_data *priv = psmouse->private;
+
+ /* ignore button press packets; many in a row could trigger
+ * a false-positive! */
+ if (l || r)
+ return;
+
+ priv->x_tally += x;
+ priv->y_tally += y;
+
+ if (++priv->count > 100) {
+ if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
+ hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n",
+ priv->x_tally, priv->y_tally);
+ psmouse_queue_work(psmouse, &priv->recalib_wq,
+ msecs_to_jiffies(1000));
+ }
+ /* reset every 100 packets */
+ priv->count = 0;
+ priv->x_tally = 0;
+ priv->y_tally = 0;
+ }
+}
+
+/*
+ * HGPK Mouse Mode format (standard mouse format, sans middle button)
+ *
+ * byte 0: y-over x-over y-neg x-neg 1 0 swr swl
+ * byte 1: x7 x6 x5 x4 x3 x2 x1 x0
+ * byte 2: y7 y6 y5 y4 y3 y2 y1 y0
+ *
+ * swr/swl are the left/right buttons.
+ * x-neg/y-neg are the x and y delta negative bits
+ * x-over/y-over are the x and y overflow bits
+ */
+static int hgpk_validate_byte(unsigned char *packet)
+{
+ return (packet[0] & 0x0C) == 0x08;
+}
+
+static void hgpk_process_packet(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ unsigned char *packet = psmouse->packet;
+ int x, y, left, right;
+
+ left = packet[0] & 1;
+ right = (packet[0] >> 1) & 1;
+
+ x = packet[1] - ((packet[0] << 4) & 0x100);
+ y = ((packet[0] << 3) & 0x100) - packet[2];
+
+ hgpk_jumpy_hack(psmouse, x, y);
+ hgpk_spewing_hack(psmouse, left, right, x, y);
+
+ if (tpdebug)
+ hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+
+ input_report_key(dev, BTN_LEFT, left);
+ input_report_key(dev, BTN_RIGHT, right);
+
+ input_report_rel(dev, REL_X, x);
+ input_report_rel(dev, REL_Y, y);
+
+ input_sync(dev);
+}
+
+static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
+{
+ struct hgpk_data *priv = psmouse->private;
+
+ if (hgpk_validate_byte(psmouse->packet)) {
+ hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n",
+ __func__, psmouse->pktcnt, psmouse->packet[0],
+ psmouse->packet[1], psmouse->packet[2]);
+ return PSMOUSE_BAD_DATA;
+ }
+
+ if (psmouse->pktcnt >= psmouse->pktsize) {
+ hgpk_process_packet(psmouse);
+ return PSMOUSE_FULL_PACKET;
+ }
+
+ if (priv->recalib_window) {
+ if (time_before(jiffies, priv->recalib_window)) {
+ /*
+ * ugh, got a packet inside our recalibration
+ * window, schedule another recalibration.
+ */
+ hgpk_dbg(psmouse,
+ "packet inside calibration window, "
+ "queueing another recalibration\n");
+ psmouse_queue_work(psmouse, &priv->recalib_wq,
+ msecs_to_jiffies(1000));
+ }
+ priv->recalib_window = 0;
+ }
+
+ return PSMOUSE_GOOD_DATA;
+}
+
+static int hgpk_force_recalibrate(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ struct hgpk_data *priv = psmouse->private;
+
+ /* C-series touchpads added the recalibrate command */
+ if (psmouse->model < HGPK_MODEL_C)
+ return 0;
+
+ /* we don't want to race with the irq handler, nor with resyncs */
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+ /* start by resetting the device */
+ psmouse_reset(psmouse);
+
+ /* send the recalibrate request */
+ if (ps2_command(ps2dev, NULL, 0xf5) ||
+ ps2_command(ps2dev, NULL, 0xf5) ||
+ ps2_command(ps2dev, NULL, 0xe6) ||
+ ps2_command(ps2dev, NULL, 0xf5)) {
+ return -1;
+ }
+
+ /* according to ALPS, 150mS is required for recalibration */
+ msleep(150);
+
+ /* XXX: If a finger is down during this delay, recalibration will
+ * detect capacitance incorrectly. This is a hardware bug, and
+ * we don't have a good way to deal with it. The 2s window stuff
+ * (below) is our best option for now.
+ */
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+ return -1;
+
+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+ /* After we recalibrate, we shouldn't get any packets for 2s. If
+ * we do, it's likely that someone's finger was on the touchpad.
+ * If someone's finger *was* on the touchpad, it's probably
+ * miscalibrated. So, we should schedule another recalibration
+ */
+ priv->recalib_window = jiffies + msecs_to_jiffies(2000);
+
+ return 0;
+}
+
+/*
+ * This kills power to the touchpad; according to ALPS, current consumption
+ * goes down to 50uA after running this. To turn power back on, we drive
+ * MS-DAT low.
+ */
+static int hgpk_toggle_power(struct psmouse *psmouse, int enable)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ int timeo;
+
+ /* Added on D-series touchpads */
+ if (psmouse->model < HGPK_MODEL_D)
+ return 0;
+
+ if (enable) {
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+ /*
+ * Sending a byte will drive MS-DAT low; this will wake up
+ * the controller. Once we get an ACK back from it, it
+ * means we can continue with the touchpad re-init. ALPS
+ * tells us that 1s should be long enough, so set that as
+ * the upper bound.
+ */
+ for (timeo = 20; timeo > 0; timeo--) {
+ if (!ps2_sendbyte(&psmouse->ps2dev,
+ PSMOUSE_CMD_DISABLE, 20))
+ break;
+ msleep(50);
+ }
+
+ psmouse_reset(psmouse);
+
+ /* should be all set, enable the touchpad */
+ ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+ } else {
+ hgpk_dbg(psmouse, "Powering off touchpad.\n");
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+
+ if (ps2_command(ps2dev, NULL, 0xec) ||
+ ps2_command(ps2dev, NULL, 0xec) ||
+ ps2_command(ps2dev, NULL, 0xea)) {
+ return -1;
+ }
+
+ /* probably won't see an ACK, the touchpad will be off */
+ ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
+ }
+
+ return 0;
+}
+
+static int hgpk_poll(struct psmouse *psmouse)
+{
+ /* We can't poll, so always return failure. */
+ return -1;
+}
+
+static int hgpk_reconnect(struct psmouse *psmouse)
+{
+ /* During suspend/resume the ps2 rails remain powered. We don't want
+ * to do a reset because it's flush data out of buffers; however,
+ * earlier prototypes (B1) had some brokenness that required a reset. */
+ if (olpc_board_at_least(olpc_board(0xb2)))
+ if (psmouse->ps2dev.serio->dev.power.power_state.event !=
+ PM_EVENT_ON)
+ return 0;
+
+ psmouse_reset(psmouse);
+
+ return 0;
+}
+
+static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
+{
+ struct hgpk_data *priv = psmouse->private;
+
+ return sprintf(buf, "%d\n", priv->powered);
+}
+
+static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
+{
+ struct hgpk_data *priv = psmouse->private;
+ unsigned long value;
+ int err;
+
+ err = strict_strtoul(buf, 10, &value);
+ if (err || value > 1)
+ return -EINVAL;
+
+ if (value != priv->powered) {
+ /*
+ * hgpk_toggle_power will deal w/ state so
+ * we're not racing w/ irq
+ */
+ err = hgpk_toggle_power(psmouse, value);
+ if (!err)
+ priv->powered = value;
+ }
+
+ return err ? err : count;
+}
+
+__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
+ hgpk_show_powered, hgpk_set_powered, 0);
+
+static void hgpk_disconnect(struct psmouse *psmouse)
+{
+ struct hgpk_data *priv = psmouse->private;
+
+ device_remove_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_powered.dattr);
+ psmouse_reset(psmouse);
+ kfree(priv);
+}
+
+static void hgpk_recalib_work(struct work_struct *work)
+{
+ struct delayed_work *w = container_of(work, struct delayed_work, work);
+ struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
+ struct psmouse *psmouse = priv->psmouse;
+
+ hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+
+ if (hgpk_force_recalibrate(psmouse))
+ hgpk_err(psmouse, "recalibration failed!\n");
+}
+
+static int hgpk_register(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ int err;
+
+ /* unset the things that psmouse-base sets which we don't have */
+ __clear_bit(BTN_MIDDLE, dev->keybit);
+
+ /* set the things we do have */
+ __set_bit(EV_KEY, dev->evbit);
+ __set_bit(EV_REL, dev->evbit);
+
+ __set_bit(REL_X, dev->relbit);
+ __set_bit(REL_Y, dev->relbit);
+
+ __set_bit(BTN_LEFT, dev->keybit);
+ __set_bit(BTN_RIGHT, dev->keybit);
+
+ /* register handlers */
+ psmouse->protocol_handler = hgpk_process_byte;
+ psmouse->poll = hgpk_poll;
+ psmouse->disconnect = hgpk_disconnect;
+ psmouse->reconnect = hgpk_reconnect;
+ psmouse->pktsize = 3;
+
+ /* Disable the idle resync. */
+ psmouse->resync_time = 0;
+ /* Reset after a lot of bad bytes. */
+ psmouse->resetafter = 1024;
+
+ err = device_create_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_powered.dattr);
+ if (err)
+ hgpk_err(psmouse, "Failed to create sysfs attribute\n");
+
+ return err;
+}
+
+int hgpk_init(struct psmouse *psmouse)
+{
+ struct hgpk_data *priv;
+ int err = -ENOMEM;
+
+ priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
+ if (!priv)
+ goto alloc_fail;
+
+ psmouse->private = priv;
+ priv->psmouse = psmouse;
+ priv->powered = 1;
+ INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
+
+ err = psmouse_reset(psmouse);
+ if (err)
+ goto init_fail;
+
+ err = hgpk_register(psmouse);
+ if (err)
+ goto init_fail;
+
+ return 0;
+
+init_fail:
+ kfree(priv);
+alloc_fail:
+ return err;
+}
+
+static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param[3];
+
+ /* E7, E7, E7, E9 gets us a 3 byte identifier */
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
+ return -EIO;
+ }
+
+ hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]);
+
+ /* HGPK signature: 0x67, 0x00, 0x<model> */
+ if (param[0] != 0x67 || param[1] != 0x00)
+ return -ENODEV;
+
+ hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+
+ return param[2];
+}
+
+int hgpk_detect(struct psmouse *psmouse, int set_properties)
+{
+ int version;
+
+ version = hgpk_get_model(psmouse);
+ if (version < 0)
+ return version;
+
+ if (set_properties) {
+ psmouse->vendor = "ALPS";
+ psmouse->name = "HGPK";
+ psmouse->model = version;
+ }
+
+ return 0;
+}
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
new file mode 100644
index 00000000000..a4b2a96f5f5
--- /dev/null
+++ b/drivers/input/mouse/hgpk.h
@@ -0,0 +1,49 @@
+/*
+ * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
+ */
+
+#ifndef _HGPK_H
+#define _HGPK_H
+
+enum hgpk_model_t {
+ HGPK_MODEL_PREA = 0x0a, /* pre-B1s */
+ HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */
+ HGPK_MODEL_B = 0x28, /* B2s, has capacitance issues */
+ HGPK_MODEL_C = 0x3c,
+ HGPK_MODEL_D = 0x50, /* C1, mass production */
+};
+
+struct hgpk_data {
+ struct psmouse *psmouse;
+ int powered;
+ int count, x_tally, y_tally; /* hardware workaround stuff */
+ unsigned long recalib_window;
+ struct delayed_work recalib_wq;
+};
+
+#define hgpk_dbg(psmouse, format, arg...) \
+ dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_err(psmouse, format, arg...) \
+ dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_info(psmouse, format, arg...) \
+ dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_warn(psmouse, format, arg...) \
+ dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_notice(psmouse, format, arg...) \
+ dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+
+#ifdef CONFIG_MOUSE_PS2_OLPC
+int hgpk_detect(struct psmouse *psmouse, int set_properties);
+int hgpk_init(struct psmouse *psmouse);
+#else
+static inline int hgpk_detect(struct psmouse *psmouse, int set_properties)
+{
+ return -ENODEV;
+}
+static inline int hgpk_init(struct psmouse *psmouse)
+{
+ return -ENODEV;
+}
+#endif
+
+#endif
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 0c5660d28ca..390f1dbb98a 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -157,10 +157,8 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data,
static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
ps2pp_set_smartscroll(psmouse, value);
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f5a6be1d3c4..126e977e199 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -25,6 +25,7 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
+#include "hgpk.h"
#include "lifebook.h"
#include "trackpoint.h"
#include "touchkit_ps2.h"
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
return PSMOUSE_FULL_PACKET;
}
+void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
+ unsigned long delay)
+{
+ queue_delayed_work(kpsmoused_wq, work, delay);
+}
+
/*
* __psmouse_set_state() sets new psmouse state and resets all flags.
*/
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
* is not a concern.
*/
-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
serio_pause_rx(psmouse->ps2dev.serio);
__psmouse_set_state(psmouse, new_state);
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- queue_work(kpsmoused_wq, &psmouse->resync_work);
+ psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
goto out;
}
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- queue_work(kpsmoused_wq, &psmouse->resync_work);
+ psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
goto out;
}
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
}
}
- if (max_proto > PSMOUSE_IMEX) {
+/*
+ * Try OLPC HGPK touchpad.
+ */
+ if (max_proto > PSMOUSE_IMEX &&
+ hgpk_detect(psmouse, set_properties) == 0) {
+ if (!set_properties || hgpk_init(psmouse) == 0)
+ return PSMOUSE_HGPK;
+/*
+ * Init failed, try basic relative protocols
+ */
+ max_proto = PSMOUSE_IMEX;
+ }
+ if (max_proto > PSMOUSE_IMEX) {
if (genius_detect(psmouse, set_properties) == 0)
return PSMOUSE_GENPS;
@@ -762,6 +781,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.detect = touchkit_ps2_detect,
},
#endif
+#ifdef CONFIG_MOUSE_PS2_OLPC
+ {
+ .type = PSMOUSE_HGPK,
+ .name = "OLPC HGPK",
+ .alias = "hgpk",
+ .detect = hgpk_detect,
+ },
+#endif
{
.type = PSMOUSE_CORTRON,
.name = "CortronPS/2",
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse)
static void psmouse_resync(struct work_struct *work)
{
struct psmouse *parent = NULL, *psmouse =
- container_of(work, struct psmouse, resync_work);
+ container_of(work, struct psmouse, resync_work.work);
struct serio *serio = psmouse->ps2dev.serio;
psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
int failed = 0, enabled = 0;
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto err_free;
ps2_init(&psmouse->ps2dev, serio);
- INIT_WORK(&psmouse->resync_work, psmouse_resync);
+ INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
psmouse->dev = input_dev;
snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
psmouse = serio_get_drvdata(serio);
- if (psmouse->state == PSMOUSE_IGNORE) {
- retval = -ENODEV;
- goto out_unlock;
- }
+ if (attr->protect) {
+ if (psmouse->state == PSMOUSE_IGNORE) {
+ retval = -ENODEV;
+ goto out_unlock;
+ }
- if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
- psmouse_deactivate(parent);
- }
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
+ psmouse_deactivate(parent);
+ }
- psmouse_deactivate(psmouse);
+ psmouse_deactivate(psmouse);
+ }
retval = attr->set(psmouse, attr->data, buf, count);
- if (retval != -ENODEV)
- psmouse_activate(psmouse);
+ if (attr->protect) {
+ if (retval != -ENODEV)
+ psmouse_activate(psmouse);
- if (parent)
- psmouse_activate(parent);
+ if (parent)
+ psmouse_activate(parent);
+ }
out_unlock:
mutex_unlock(&psmouse_mutex);
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
{
unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest)
+ if (strict_strtoul(buf, 10, &value))
return -EINVAL;
if ((unsigned int)value != value)
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest)
+ if (strict_strtoul(buf, 10, &value))
return -EINVAL;
psmouse->set_rate(psmouse, value);
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const
static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest)
+ if (strict_strtoul(buf, 10, &value))
return -EINVAL;
psmouse->set_resolution(psmouse, value);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 1317bdd8cc7..8b608a1cdd1 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -39,7 +39,7 @@ struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
- struct work_struct resync_work;
+ struct delayed_work resync_work;
char *vendor;
char *name;
unsigned char packet[8];
@@ -89,20 +89,24 @@ enum psmouse_type {
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
PSMOUSE_CORTRON,
+ PSMOUSE_HGPK,
PSMOUSE_AUTO /* This one should always be last */
};
+void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
+ unsigned long delay);
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse);
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
-
struct psmouse_attribute {
struct device_attribute dattr;
void *data;
ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
ssize_t (*set)(struct psmouse *psmouse, void *data,
const char *buf, size_t count);
+ int protect;
};
#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
@@ -111,7 +115,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at
ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
+#define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \
static ssize_t _show(struct psmouse *, void *data, char *); \
static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \
static struct psmouse_attribute psmouse_attr_##_name = { \
@@ -126,6 +130,10 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
.data = _data, \
.show = _show, \
.set = _set, \
+ .protect = _protect, \
}
+#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
+ __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1)
+
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 26b845fc186..e68c814c436 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -89,10 +89,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
struct trackpoint_attr_data *attr = data;
unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 255)
+ if (strict_strtoul(buf, 10, &value) || value > 255)
return -EINVAL;
*field = value;
@@ -117,10 +115,8 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
struct trackpoint_attr_data *attr = data;
unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
unsigned long value;
- char *rest;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (strict_strtoul(buf, 10, &value) || value > 1)
return -EINVAL;
if (attr->inverted)
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 0d395979b2d..bfe49243f38 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -323,7 +323,7 @@ static void hp_sdc_tasklet(unsigned long foo)
* it back to the application. and be less verbose.
*/
printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
- tv.tv_usec - hp_sdc.rtv.tv_usec);
+ (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
curr->idx += hp_sdc.rqty;
hp_sdc.rqty = 0;
tmp = curr->seq[curr->actidx];
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index f451c7351a9..847f4aad7ed 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -67,7 +67,7 @@ static inline int i8042_platform_init(void)
* On some platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on such boxes.
*/
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
if (check_legacy_ioport(I8042_DATA_REG))
return -ENODEV;
#endif
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index 692a79ec2a2..5071af2c060 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -87,7 +87,7 @@ static int __devexit sparc_i8042_remove(struct of_device *op)
return 0;
}
-static struct of_device_id sparc_i8042_match[] = {
+static const struct of_device_id sparc_i8042_match[] = {
{
.name = "8042",
},
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 3282b741e24..a321aea2c7b 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
.ident = "Lenovo 3000 n100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
},
},
{
@@ -322,6 +322,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
},
},
+ {
+ .ident = "IBM 2656",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index c9397c8ee97..470770c0926 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -373,6 +373,12 @@ static struct serio_device_id serio_raw_serio_ids[] = {
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
+ {
+ .type = SERIO_8042_XL,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
{ 0 }
};
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index 570e0e83ac4..670c61c5a51 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -280,7 +280,8 @@ static int __init usb_acecad_init(void)
{
int result = usb_register(&usb_acecad_driver);
if (result == 0)
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 8f037a1d44a..7d005a3616d 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1202,16 +1202,22 @@ static ssize_t
store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- int x;
+ long x;
+
+ if (strict_strtol(buf, 10, &x)) {
+ size_t len = buf[count - 1] == '\n' ? count - 1 : count;
+
+ if (strncmp(buf, "disable", len))
+ return -EINVAL;
- if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
} else {
- x = (int)simple_strtol(buf, NULL, 10);
- if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) {
- aiptek->newSetting.xTilt = x;
- }
+ if (x < AIPTEK_TILT_MIN || x > AIPTEK_TILT_MAX)
+ return -EINVAL;
+
+ aiptek->newSetting.xTilt = x;
}
+
return count;
}
@@ -1238,16 +1244,22 @@ static ssize_t
store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- int y;
+ long y;
+
+ if (strict_strtol(buf, 10, &y)) {
+ size_t len = buf[count - 1] == '\n' ? count - 1 : count;
+
+ if (strncmp(buf, "disable", len))
+ return -EINVAL;
- if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
} else {
- y = (int)simple_strtol(buf, NULL, 10);
- if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) {
- aiptek->newSetting.yTilt = y;
- }
+ if (y < AIPTEK_TILT_MIN || y > AIPTEK_TILT_MAX)
+ return -EINVAL;
+
+ aiptek->newSetting.yTilt = y;
}
+
return count;
}
@@ -1269,8 +1281,12 @@ static ssize_t
store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ long j;
+
+ if (strict_strtol(buf, 10, &j))
+ return -EINVAL;
- aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
+ aiptek->newSetting.jitterDelay = (int)j;
return count;
}
@@ -1294,8 +1310,12 @@ static ssize_t
store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ long d;
- aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
+ if (strict_strtol(buf, 10, &d))
+ return -EINVAL;
+
+ aiptek->newSetting.programmableDelay = (int)d;
return count;
}
@@ -1541,8 +1561,11 @@ static ssize_t
store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ long w;
+
+ if (strict_strtol(buf, 10, &w)) return -EINVAL;
- aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
+ aiptek->newSetting.wheel = (int)w;
return count;
}
@@ -1683,20 +1706,21 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
inputdev = input_allocate_device();
if (!aiptek || !inputdev) {
- warn("aiptek: cannot allocate memory or input device");
+ dev_warn(&intf->dev,
+ "cannot allocate memory or input device\n");
goto fail1;
}
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
if (!aiptek->data) {
- warn("aiptek: cannot allocate usb buffer");
+ dev_warn(&intf->dev, "cannot allocate usb buffer\n");
goto fail1;
}
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!aiptek->urb) {
- warn("aiptek: cannot allocate urb");
+ dev_warn(&intf->dev, "cannot allocate urb\n");
goto fail2;
}
@@ -1820,8 +1844,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->curSetting.programmableDelay = speeds[i];
(void)aiptek_program_tablet(aiptek);
if (aiptek->inputdev->absmax[ABS_X] > 0) {
- info("input: Aiptek using %d ms programming speed\n",
- aiptek->curSetting.programmableDelay);
+ dev_info(&intf->dev,
+ "Aiptek using %d ms programming speed\n",
+ aiptek->curSetting.programmableDelay);
break;
}
}
@@ -1829,7 +1854,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Murphy says that some day someone will have a tablet that fails the
above test. That's you, Frederic Rodrigo */
if (i == ARRAY_SIZE(speeds)) {
- info("input: Aiptek tried all speeds, no sane response");
+ dev_info(&intf->dev,
+ "Aiptek tried all speeds, no sane response\n");
goto fail2;
}
@@ -1841,7 +1867,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
*/
err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
if (err) {
- warn("aiptek: cannot create sysfs group err: %d", err);
+ dev_warn(&intf->dev, "cannot create sysfs group err: %d\n",
+ err);
goto fail3;
}
@@ -1849,7 +1876,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
*/
err = input_register_device(aiptek->inputdev);
if (err) {
- warn("aiptek: input_register_device returned err: %d", err);
+ dev_warn(&intf->dev,
+ "input_register_device returned err: %d\n", err);
goto fail4;
}
return 0;
@@ -1899,8 +1927,9 @@ static int __init aiptek_init(void)
{
int result = usb_register(&aiptek_driver);
if (result == 0) {
- info(DRIVER_VERSION ": " DRIVER_AUTHOR);
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_AUTHOR "\n");
}
return result;
}
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 7df0228e836..5524e01dbb1 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -2,7 +2,7 @@
GTCO digitizer USB driver
-Use the err(), dbg() and info() macros from usb.h for system logging
+Use the err() and dbg() macros from usb.h for system logging
TO CHECK: Is pressure done right on report 5?
@@ -1010,7 +1010,7 @@ static void gtco_disconnect(struct usb_interface *interface)
kfree(gtco);
}
- info("gtco driver disconnected");
+ dev_info(&interface->dev, "gtco driver disconnected\n");
}
/* STANDARD MODULE LOAD ROUTINES */
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index d89112fa6e6..6682b17bf84 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -215,7 +215,8 @@ static int __init kbtab_init(void)
retval = usb_register(&kbtab_driver);
if (retval)
goto out;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
out:
return retval;
}
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 5fbc463baf5..09e227aa0d4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -385,7 +385,8 @@ static int __init wacom_init(void)
wacom_driver.id_table = get_device_table();
result = usb_register(&wacom_driver);
if (result == 0)
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 25287e80e23..6e1e8c624f9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -220,6 +220,7 @@ config TOUCHSCREEN_ATMEL_TSADCC
config TOUCHSCREEN_UCB1400
tristate "Philips UCB1400 touchscreen"
select AC97_BUS
+ depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 touchscreen interface.
The UCB1400 is an AC97 audio codec. The touchscreen interface
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index ce6f48c695f..b9b7fc6ff1e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -24,6 +24,7 @@
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <asm/irq.h>
@@ -68,6 +69,17 @@ struct ts_event {
int ignore;
};
+/*
+ * We allocate this separately to avoid cache line sharing issues when
+ * driver is used with DMA-based SPI controllers (like atmel_spi) on
+ * systems where main memory is not DMA-coherent (most non-x86 boards).
+ */
+struct ads7846_packet {
+ u8 read_x, read_y, read_z1, read_z2, pwrdown;
+ u16 dummy; /* for the pwrdown read */
+ struct ts_event tc;
+};
+
struct ads7846 {
struct input_dev *input;
char phys[32];
@@ -85,9 +97,7 @@ struct ads7846 {
u16 x_plate_ohms;
u16 pressure_max;
- u8 read_x, read_y, read_z1, read_z2, pwrdown;
- u16 dummy; /* for the pwrdown read */
- struct ts_event tc;
+ struct ads7846_packet *packet;
struct spi_transfer xfer[18];
struct spi_message msg[5];
@@ -116,6 +126,7 @@ struct ads7846 {
void *filter_data;
void (*filter_cleanup)(void *data);
int (*get_pendown_state)(void);
+ int gpio_pendown;
};
/* leave chip selected when we're done, for quicker re-select? */
@@ -461,10 +472,11 @@ static ssize_t ads7846_disable_store(struct device *dev,
const char *buf, size_t count)
{
struct ads7846 *ts = dev_get_drvdata(dev);
- char *endp;
- int i;
+ long i;
+
+ if (strict_strtoul(buf, 10, &i))
+ return -EINVAL;
- i = simple_strtoul(buf, &endp, 10);
spin_lock_irq(&ts->lock);
if (i)
@@ -491,6 +503,14 @@ static struct attribute_group ads784x_attr_group = {
/*--------------------------------------------------------------------------*/
+static int get_pendown_state(struct ads7846 *ts)
+{
+ if (ts->get_pendown_state)
+ return ts->get_pendown_state();
+
+ return !gpio_get_value(ts->gpio_pendown);
+}
+
/*
* PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
* to retrieve touchscreen status.
@@ -502,16 +522,17 @@ static struct attribute_group ads784x_attr_group = {
static void ads7846_rx(void *ads)
{
struct ads7846 *ts = ads;
+ struct ads7846_packet *packet = ts->packet;
unsigned Rt;
u16 x, y, z1, z2;
/* ads7846_rx_val() did in-place conversion (including byteswap) from
* on-the-wire format as part of debouncing to get stable readings.
*/
- x = ts->tc.x;
- y = ts->tc.y;
- z1 = ts->tc.z1;
- z2 = ts->tc.z2;
+ x = packet->tc.x;
+ y = packet->tc.y;
+ z1 = packet->tc.z1;
+ z2 = packet->tc.z2;
/* range filtering */
if (x == MAX_12BIT)
@@ -535,10 +556,10 @@ static void ads7846_rx(void *ads)
* the maximum. Don't report it to user space, repeat at least
* once more the measurement
*/
- if (ts->tc.ignore || Rt > ts->pressure_max) {
+ if (packet->tc.ignore || Rt > ts->pressure_max) {
#ifdef VERBOSE
pr_debug("%s: ignored %d pressure %d\n",
- ts->spi->dev.bus_id, ts->tc.ignore, Rt);
+ ts->spi->dev.bus_id, packet->tc.ignore, Rt);
#endif
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
HRTIMER_MODE_REL);
@@ -550,7 +571,7 @@ static void ads7846_rx(void *ads)
*/
if (ts->penirq_recheck_delay_usecs) {
udelay(ts->penirq_recheck_delay_usecs);
- if (!ts->get_pendown_state())
+ if (!get_pendown_state(ts))
Rt = 0;
}
@@ -631,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)
static void ads7846_rx_val(void *ads)
{
struct ads7846 *ts = ads;
+ struct ads7846_packet *packet = ts->packet;
struct spi_message *m;
struct spi_transfer *t;
int val;
@@ -650,7 +672,7 @@ static void ads7846_rx_val(void *ads)
case ADS7846_FILTER_REPEAT:
break;
case ADS7846_FILTER_IGNORE:
- ts->tc.ignore = 1;
+ packet->tc.ignore = 1;
/* Last message will contain ads7846_rx() as the
* completion function.
*/
@@ -658,7 +680,7 @@ static void ads7846_rx_val(void *ads)
break;
case ADS7846_FILTER_OK:
*(u16 *)t->rx_buf = val;
- ts->tc.ignore = 0;
+ packet->tc.ignore = 0;
m = &ts->msg[++ts->msg_idx];
break;
default:
@@ -677,7 +699,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
spin_lock_irq(&ts->lock);
- if (unlikely(!ts->get_pendown_state() ||
+ if (unlikely(!get_pendown_state(ts) ||
device_suspended(&ts->spi->dev))) {
if (ts->pendown) {
struct input_dev *input = ts->input;
@@ -716,7 +738,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
- if (likely(ts->get_pendown_state())) {
+ if (likely(get_pendown_state(ts))) {
if (!ts->irq_disabled) {
/* The ARM do_simple_IRQ() dispatcher doesn't act
* like the other dispatchers: it will report IRQs
@@ -763,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts)
/* we know the chip's in lowpower mode since we always
* leave it that way after every request
*/
-
}
/* Must be called with ts->lock held */
@@ -806,9 +827,40 @@ static int ads7846_resume(struct spi_device *spi)
return 0;
}
+static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+{
+ struct ads7846_platform_data *pdata = spi->dev.platform_data;
+ int err;
+
+ /* REVISIT when the irq can be triggered active-low, or if for some
+ * reason the touchscreen isn't hooked up, we don't need to access
+ * the pendown state.
+ */
+ if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) {
+ dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
+ return -EINVAL;
+ }
+
+ if (pdata->get_pendown_state) {
+ ts->get_pendown_state = pdata->get_pendown_state;
+ return 0;
+ }
+
+ err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+ if (err) {
+ dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
+ pdata->gpio_pendown);
+ return err;
+ }
+
+ ts->gpio_pendown = pdata->gpio_pendown;
+ return 0;
+}
+
static int __devinit ads7846_probe(struct spi_device *spi)
{
struct ads7846 *ts;
+ struct ads7846_packet *packet;
struct input_dev *input_dev;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
struct spi_message *m;
@@ -833,15 +885,6 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return -EINVAL;
}
- /* REVISIT when the irq can be triggered active-low, or if for some
- * reason the touchscreen isn't hooked up, we don't need to access
- * the pendown state.
- */
- if (pdata->get_pendown_state == NULL) {
- dev_dbg(&spi->dev, "no get_pendown_state function?\n");
- return -EINVAL;
- }
-
/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
* that even if the hardware can do that, the SPI controller driver
* may not. So we stick to very-portable 8 bit words, both RX and TX.
@@ -853,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return err;
ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+ packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
input_dev = input_allocate_device();
- if (!ts || !input_dev) {
+ if (!ts || !packet || !input_dev) {
err = -ENOMEM;
goto err_free_mem;
}
dev_set_drvdata(&spi->dev, ts);
+ ts->packet = packet;
ts->spi = spi;
ts->input = input_dev;
ts->vref_mv = pdata->vref_mv;
@@ -893,7 +938,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->filter_data = ts;
} else
ts->filter = ads7846_no_filter;
- ts->get_pendown_state = pdata->get_pendown_state;
+
+ err = setup_pendown(spi, ts);
+ if (err)
+ goto err_cleanup_filter;
if (pdata->penirq_recheck_delay_usecs)
ts->penirq_recheck_delay_usecs =
@@ -929,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init(m);
/* y- still on; turn on only y+ (and ADC) */
- ts->read_y = READ_Y(vref);
- x->tx_buf = &ts->read_y;
+ packet->read_y = READ_Y(vref);
+ x->tx_buf = &packet->read_y;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.y;
+ x->rx_buf = &packet->tc.y;
x->len = 2;
spi_message_add_tail(x, m);
@@ -947,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x->delay_usecs = pdata->settle_delay_usecs;
x++;
- x->tx_buf = &ts->read_y;
+ x->tx_buf = &packet->read_y;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.y;
+ x->rx_buf = &packet->tc.y;
x->len = 2;
spi_message_add_tail(x, m);
}
@@ -965,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
/* turn y- off, x+ on, then leave in lowpower */
x++;
- ts->read_x = READ_X(vref);
- x->tx_buf = &ts->read_x;
+ packet->read_x = READ_X(vref);
+ x->tx_buf = &packet->read_x;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.x;
+ x->rx_buf = &packet->tc.x;
x->len = 2;
spi_message_add_tail(x, m);
@@ -980,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x->delay_usecs = pdata->settle_delay_usecs;
x++;
- x->tx_buf = &ts->read_x;
+ x->tx_buf = &packet->read_x;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.x;
+ x->rx_buf = &packet->tc.x;
x->len = 2;
spi_message_add_tail(x, m);
}
@@ -999,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init(m);
x++;
- ts->read_z1 = READ_Z1(vref);
- x->tx_buf = &ts->read_z1;
+ packet->read_z1 = READ_Z1(vref);
+ x->tx_buf = &packet->read_z1;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.z1;
+ x->rx_buf = &packet->tc.z1;
x->len = 2;
spi_message_add_tail(x, m);
@@ -1014,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x->delay_usecs = pdata->settle_delay_usecs;
x++;
- x->tx_buf = &ts->read_z1;
+ x->tx_buf = &packet->read_z1;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.z1;
+ x->rx_buf = &packet->tc.z1;
x->len = 2;
spi_message_add_tail(x, m);
}
@@ -1031,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init(m);
x++;
- ts->read_z2 = READ_Z2(vref);
- x->tx_buf = &ts->read_z2;
+ packet->read_z2 = READ_Z2(vref);
+ x->tx_buf = &packet->read_z2;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.z2;
+ x->rx_buf = &packet->tc.z2;
x->len = 2;
spi_message_add_tail(x, m);
@@ -1046,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x->delay_usecs = pdata->settle_delay_usecs;
x++;
- x->tx_buf = &ts->read_z2;
+ x->tx_buf = &packet->read_z2;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.z2;
+ x->rx_buf = &packet->tc.z2;
x->len = 2;
spi_message_add_tail(x, m);
}
@@ -1065,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init(m);
x++;
- ts->pwrdown = PWRDOWN;
- x->tx_buf = &ts->pwrdown;
+ packet->pwrdown = PWRDOWN;
+ x->tx_buf = &packet->pwrdown;
x->len = 1;
spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->dummy;
+ x->rx_buf = &packet->dummy;
x->len = 2;
CS_CHANGE(*x);
spi_message_add_tail(x, m);
@@ -1085,7 +1133,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi->dev.driver->name, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
err = -EBUSY;
- goto err_cleanup_filter;
+ goto err_free_gpio;
}
err = ads784x_hwmon_register(spi, ts);
@@ -1116,11 +1164,15 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ads784x_hwmon_unregister(spi, ts);
err_free_irq:
free_irq(spi->irq, ts);
+ err_free_gpio:
+ if (ts->gpio_pendown != -1)
+ gpio_free(ts->gpio_pendown);
err_cleanup_filter:
if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);
err_free_mem:
input_free_device(input_dev);
+ kfree(packet);
kfree(ts);
return err;
}
@@ -1140,9 +1192,13 @@ static int __devexit ads7846_remove(struct spi_device *spi)
/* suspend left the IRQ disabled */
enable_irq(ts->spi->irq);
+ if (ts->gpio_pendown != -1)
+ gpio_free(ts->gpio_pendown);
+
if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);
+ kfree(ts->packet);
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
index eee126b19e8..a89a6a8f05e 100644
--- a/drivers/input/touchscreen/atmel_tsadcc.c
+++ b/drivers/input/touchscreen/atmel_tsadcc.c
@@ -91,6 +91,9 @@ struct atmel_tsadcc {
char phys[32];
struct clk *clk;
int irq;
+ unsigned int prev_absx;
+ unsigned int prev_absy;
+ unsigned char bufferedmeasure;
};
static void __iomem *tsc_base;
@@ -100,10 +103,9 @@ static void __iomem *tsc_base;
static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
{
- struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input;
+ struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev;
+ struct input_dev *input_dev = ts_dev->input;
- unsigned int absx;
- unsigned int absy;
unsigned int status;
unsigned int reg;
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
input_report_key(input_dev, BTN_TOUCH, 0);
+ ts_dev->bufferedmeasure = 0;
input_sync(input_dev);
} else if (status & ATMEL_TSADCC_PENCNT) {
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
} else if (status & ATMEL_TSADCC_EOC(3)) {
/* Conversion finished */
- absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
- absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
-
- absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
- absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
-
- input_report_abs(input_dev, ABS_X, absx);
- input_report_abs(input_dev, ABS_Y, absy);
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_sync(input_dev);
+ if (ts_dev->bufferedmeasure) {
+ /* Last measurement is always discarded, since it can
+ * be erroneous.
+ * Always report previous measurement */
+ input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
+ input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
+ input_report_key(input_dev, BTN_TOUCH, 1);
+ input_sync(input_dev);
+ } else
+ ts_dev->bufferedmeasure = 1;
+
+ /* Now make new measurement */
+ ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
+ ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
+
+ ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
+ ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
}
return IRQ_HANDLED;
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
}
ts_dev->input = input_dev;
+ ts_dev->bufferedmeasure = 0;
snprintf(ts_dev->phys, sizeof(ts_dev->phys),
"%s/input0", pdev->dev.bus_id);
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
index bf44f9d6834..c8b7e8a45c4 100644
--- a/drivers/input/touchscreen/jornada720_ts.c
+++ b/drivers/input/touchscreen/jornada720_ts.c
@@ -119,8 +119,8 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev)
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0);
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
index 37a555f3730..ba648750a8d 100644
--- a/drivers/input/touchscreen/mainstone-wm97xx.c
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -3,8 +3,7 @@
* Wolfson WM97xx AC97 Codecs.
*
* Copyright 2004, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
*
@@ -296,6 +295,6 @@ module_init(mainstone_wm97xx_init);
module_exit(mainstone_wm97xx_exit);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index bce018e45bc..54986627def 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -5,6 +5,10 @@
* Created: September 25, 2006
* Copyright: MontaVista Software, Inc.
*
+ * Spliting done by: Marek Vasut <marek.vasut@gmail.com>
+ * If something doesnt work and it worked before spliting, e-mail me,
+ * dont bother Nicolas please ;-)
+ *
* 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.
@@ -25,124 +29,16 @@
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
-
-#include <sound/core.h>
-#include <sound/ac97_codec.h>
-
-
-/*
- * Interesting UCB1400 AC-link registers
- */
-
-#define UCB_IE_RIS 0x5e
-#define UCB_IE_FAL 0x60
-#define UCB_IE_STATUS 0x62
-#define UCB_IE_CLEAR 0x62
-#define UCB_IE_ADC (1 << 11)
-#define UCB_IE_TSPX (1 << 12)
-
-#define UCB_TS_CR 0x64
-#define UCB_TS_CR_TSMX_POW (1 << 0)
-#define UCB_TS_CR_TSPX_POW (1 << 1)
-#define UCB_TS_CR_TSMY_POW (1 << 2)
-#define UCB_TS_CR_TSPY_POW (1 << 3)
-#define UCB_TS_CR_TSMX_GND (1 << 4)
-#define UCB_TS_CR_TSPX_GND (1 << 5)
-#define UCB_TS_CR_TSMY_GND (1 << 6)
-#define UCB_TS_CR_TSPY_GND (1 << 7)
-#define UCB_TS_CR_MODE_INT (0 << 8)
-#define UCB_TS_CR_MODE_PRES (1 << 8)
-#define UCB_TS_CR_MODE_POS (2 << 8)
-#define UCB_TS_CR_BIAS_ENA (1 << 11)
-#define UCB_TS_CR_TSPX_LOW (1 << 12)
-#define UCB_TS_CR_TSMX_LOW (1 << 13)
-
-#define UCB_ADC_CR 0x66
-#define UCB_ADC_SYNC_ENA (1 << 0)
-#define UCB_ADC_VREFBYP_CON (1 << 1)
-#define UCB_ADC_INP_TSPX (0 << 2)
-#define UCB_ADC_INP_TSMX (1 << 2)
-#define UCB_ADC_INP_TSPY (2 << 2)
-#define UCB_ADC_INP_TSMY (3 << 2)
-#define UCB_ADC_INP_AD0 (4 << 2)
-#define UCB_ADC_INP_AD1 (5 << 2)
-#define UCB_ADC_INP_AD2 (6 << 2)
-#define UCB_ADC_INP_AD3 (7 << 2)
-#define UCB_ADC_EXT_REF (1 << 5)
-#define UCB_ADC_START (1 << 7)
-#define UCB_ADC_ENA (1 << 15)
-
-#define UCB_ADC_DATA 0x68
-#define UCB_ADC_DAT_VALID (1 << 15)
-#define UCB_ADC_DAT_VALUE(x) ((x) & 0x3ff)
-
-#define UCB_ID 0x7e
-#define UCB_ID_1400 0x4304
-
-
-struct ucb1400 {
- struct snd_ac97 *ac97;
- struct input_dev *ts_idev;
-
- int irq;
-
- wait_queue_head_t ts_wait;
- struct task_struct *ts_task;
-
- unsigned int irq_pending; /* not bit field shared */
- unsigned int ts_restart:1;
- unsigned int adcsync:1;
-};
+#include <linux/ucb1400.h>
static int adcsync;
static int ts_delay = 55; /* us */
static int ts_delay_pressure; /* us */
-static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
-{
- return ucb->ac97->bus->ops->read(ucb->ac97, reg);
-}
-
-static inline void ucb1400_reg_write(struct ucb1400 *ucb, u16 reg, u16 val)
-{
- ucb->ac97->bus->ops->write(ucb->ac97, reg, val);
-}
-
-static inline void ucb1400_adc_enable(struct ucb1400 *ucb)
-{
- ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
-}
-
-static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
-{
- unsigned int val;
-
- if (ucb->adcsync)
- adc_channel |= UCB_ADC_SYNC_ENA;
-
- ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
- ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel | UCB_ADC_START);
-
- for (;;) {
- val = ucb1400_reg_read(ucb, UCB_ADC_DATA);
- if (val & UCB_ADC_DAT_VALID)
- break;
- /* yield to other processes */
- schedule_timeout_uninterruptible(1);
- }
-
- return UCB_ADC_DAT_VALUE(val);
-}
-
-static inline void ucb1400_adc_disable(struct ucb1400 *ucb)
-{
- ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
-}
-
/* Switch to interrupt mode. */
-static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb)
+static inline void ucb1400_ts_mode_int(struct snd_ac97 *ac97)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
UCB_TS_CR_MODE_INT);
@@ -152,14 +48,14 @@ static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb)
* Switch to pressure mode, and read pressure. We don't need to wait
* here, since both plates are being driven.
*/
-static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
+static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400_ts *ucb)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
udelay(ts_delay_pressure);
- return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+ return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync);
}
/*
@@ -168,21 +64,21 @@ static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
* gives a faster response time. Even so, we need to wait about 55us
* for things to stabilise.
*/
-static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
+static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400_ts *ucb)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
udelay(ts_delay);
- return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+ return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync);
}
/*
@@ -191,63 +87,63 @@ static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
* gives a faster response time. Even so, we need to wait about 55us
* for things to stabilise.
*/
-static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb)
+static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400_ts *ucb)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
udelay(ts_delay);
- return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
+ return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPX, adcsync);
}
/*
* Switch to X plate resistance mode. Set MX to ground, PX to
* supply. Measure current.
*/
-static inline unsigned int ucb1400_ts_read_xres(struct ucb1400 *ucb)
+static inline unsigned int ucb1400_ts_read_xres(struct ucb1400_ts *ucb)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- return ucb1400_adc_read(ucb, 0);
+ return ucb1400_adc_read(ucb->ac97, 0, adcsync);
}
/*
* Switch to Y plate resistance mode. Set MY to ground, PY to
* supply. Measure current.
*/
-static inline unsigned int ucb1400_ts_read_yres(struct ucb1400 *ucb)
+static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb)
{
- ucb1400_reg_write(ucb, UCB_TS_CR,
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR,
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
- return ucb1400_adc_read(ucb, 0);
+ return ucb1400_adc_read(ucb->ac97, 0, adcsync);
}
-static inline int ucb1400_ts_pen_down(struct ucb1400 *ucb)
+static inline int ucb1400_ts_pen_down(struct snd_ac97 *ac97)
{
- unsigned short val = ucb1400_reg_read(ucb, UCB_TS_CR);
- return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
+ unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR);
+ return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW);
}
-static inline void ucb1400_ts_irq_enable(struct ucb1400 *ucb)
+static inline void ucb1400_ts_irq_enable(struct snd_ac97 *ac97)
{
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, UCB_IE_TSPX);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
- ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_TSPX);
+ ucb1400_reg_write(ac97, UCB_IE_CLEAR, UCB_IE_TSPX);
+ ucb1400_reg_write(ac97, UCB_IE_CLEAR, 0);
+ ucb1400_reg_write(ac97, UCB_IE_FAL, UCB_IE_TSPX);
}
-static inline void ucb1400_ts_irq_disable(struct ucb1400 *ucb)
+static inline void ucb1400_ts_irq_disable(struct snd_ac97 *ac97)
{
- ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
+ ucb1400_reg_write(ac97, UCB_IE_FAL, 0);
}
static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y)
@@ -264,25 +160,24 @@ static void ucb1400_ts_event_release(struct input_dev *idev)
input_sync(idev);
}
-static void ucb1400_handle_pending_irq(struct ucb1400 *ucb)
+static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb)
{
unsigned int isr;
- isr = ucb1400_reg_read(ucb, UCB_IE_STATUS);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, isr);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+ isr = ucb1400_reg_read(ucb->ac97, UCB_IE_STATUS);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
- if (isr & UCB_IE_TSPX)
- ucb1400_ts_irq_disable(ucb);
- else
+ if (isr & UCB_IE_TSPX) {
+ ucb1400_ts_irq_disable(ucb->ac97);
+ enable_irq(ucb->irq);
+ } else
printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
-
- enable_irq(ucb->irq);
}
static int ucb1400_ts_thread(void *_ucb)
{
- struct ucb1400 *ucb = _ucb;
+ struct ucb1400_ts *ucb = _ucb;
struct task_struct *tsk = current;
int valid = 0;
struct sched_param param = { .sched_priority = 1 };
@@ -301,19 +196,19 @@ static int ucb1400_ts_thread(void *_ucb)
ucb1400_handle_pending_irq(ucb);
}
- ucb1400_adc_enable(ucb);
+ ucb1400_adc_enable(ucb->ac97);
x = ucb1400_ts_read_xpos(ucb);
y = ucb1400_ts_read_ypos(ucb);
p = ucb1400_ts_read_pressure(ucb);
- ucb1400_adc_disable(ucb);
+ ucb1400_adc_disable(ucb->ac97);
/* Switch back to interrupt mode. */
- ucb1400_ts_mode_int(ucb);
+ ucb1400_ts_mode_int(ucb->ac97);
msleep(10);
- if (ucb1400_ts_pen_down(ucb)) {
- ucb1400_ts_irq_enable(ucb);
+ if (ucb1400_ts_pen_down(ucb->ac97)) {
+ ucb1400_ts_irq_enable(ucb->ac97);
/*
* If we spat out a valid sample set last time,
@@ -332,8 +227,8 @@ static int ucb1400_ts_thread(void *_ucb)
}
wait_event_freezable_timeout(ucb->ts_wait,
- ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
- timeout);
+ ucb->irq_pending || ucb->ts_restart ||
+ kthread_should_stop(), timeout);
}
/* Send the "pen off" if we are stopping with the pen still active */
@@ -356,7 +251,7 @@ static int ucb1400_ts_thread(void *_ucb)
*/
static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
{
- struct ucb1400 *ucb = devid;
+ struct ucb1400_ts *ucb = devid;
if (irqnr == ucb->irq) {
disable_irq(ucb->irq);
@@ -369,7 +264,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
static int ucb1400_ts_open(struct input_dev *idev)
{
- struct ucb1400 *ucb = input_get_drvdata(idev);
+ struct ucb1400_ts *ucb = input_get_drvdata(idev);
int ret = 0;
BUG_ON(ucb->ts_task);
@@ -385,34 +280,14 @@ static int ucb1400_ts_open(struct input_dev *idev)
static void ucb1400_ts_close(struct input_dev *idev)
{
- struct ucb1400 *ucb = input_get_drvdata(idev);
+ struct ucb1400_ts *ucb = input_get_drvdata(idev);
if (ucb->ts_task)
kthread_stop(ucb->ts_task);
- ucb1400_ts_irq_disable(ucb);
- ucb1400_reg_write(ucb, UCB_TS_CR, 0);
-}
-
-#ifdef CONFIG_PM
-static int ucb1400_ts_resume(struct device *dev)
-{
- struct ucb1400 *ucb = dev_get_drvdata(dev);
-
- if (ucb->ts_task) {
- /*
- * Restart the TS thread to ensure the
- * TS interrupt mode is set up again
- * after sleep.
- */
- ucb->ts_restart = 1;
- wake_up(&ucb->ts_wait);
- }
- return 0;
+ ucb1400_ts_irq_disable(ucb->ac97);
+ ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0);
}
-#else
-#define ucb1400_ts_resume NULL
-#endif
#ifndef NO_IRQ
#define NO_IRQ 0
@@ -422,25 +297,26 @@ static int ucb1400_ts_resume(struct device *dev)
* Try to probe our interrupt, rather than relying on lots of
* hard-coded machine dependencies.
*/
-static int ucb1400_detect_irq(struct ucb1400 *ucb)
+static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb)
{
unsigned long mask, timeout;
mask = probe_irq_on();
/* Enable the ADC interrupt. */
- ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
- ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_RIS, UCB_IE_ADC);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, UCB_IE_ADC);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0xffff);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
/* Cause an ADC interrupt. */
- ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
- ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+ ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, UCB_ADC_ENA);
+ ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
/* Wait for the conversion to complete. */
timeout = jiffies + HZ/2;
- while (!(ucb1400_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VALID)) {
+ while (!(ucb1400_reg_read(ucb->ac97, UCB_ADC_DATA) &
+ UCB_ADC_DAT_VALID)) {
cpu_relax();
if (time_after(jiffies, timeout)) {
printk(KERN_ERR "ucb1400: timed out in IRQ probe\n");
@@ -448,13 +324,13 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
return -ENODEV;
}
}
- ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
+ ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, 0);
/* Disable and clear interrupt. */
- ucb1400_reg_write(ucb, UCB_IE_RIS, 0);
- ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
- ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_RIS, 0);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, 0);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0xffff);
+ ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
/* Read triggered interrupt. */
ucb->irq = probe_irq_off(mask);
@@ -464,36 +340,25 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
return 0;
}
-static int ucb1400_ts_probe(struct device *dev)
+static int ucb1400_ts_probe(struct platform_device *dev)
{
- struct ucb1400 *ucb;
- struct input_dev *idev;
- int error, id, x_res, y_res;
+ int error, x_res, y_res;
+ struct ucb1400_ts *ucb = dev->dev.platform_data;
- ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL);
- idev = input_allocate_device();
- if (!ucb || !idev) {
+ ucb->ts_idev = input_allocate_device();
+ if (!ucb->ts_idev) {
error = -ENOMEM;
- goto err_free_devs;
+ goto err;
}
- ucb->ts_idev = idev;
- ucb->adcsync = adcsync;
- ucb->ac97 = to_ac97_t(dev);
- init_waitqueue_head(&ucb->ts_wait);
-
- id = ucb1400_reg_read(ucb, UCB_ID);
- if (id != UCB_ID_1400) {
- error = -ENODEV;
- goto err_free_devs;
- }
-
- error = ucb1400_detect_irq(ucb);
+ error = ucb1400_ts_detect_irq(ucb);
if (error) {
printk(KERN_ERR "UCB1400: IRQ probe failed\n");
goto err_free_devs;
}
+ init_waitqueue_head(&ucb->ts_wait);
+
error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING,
"UCB1400", ucb);
if (error) {
@@ -503,80 +368,101 @@ static int ucb1400_ts_probe(struct device *dev)
}
printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
- input_set_drvdata(idev, ucb);
+ input_set_drvdata(ucb->ts_idev, ucb);
- idev->dev.parent = dev;
- idev->name = "UCB1400 touchscreen interface";
- idev->id.vendor = ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
- idev->id.product = id;
- idev->open = ucb1400_ts_open;
- idev->close = ucb1400_ts_close;
- idev->evbit[0] = BIT_MASK(EV_ABS);
+ ucb->ts_idev->dev.parent = &dev->dev;
+ ucb->ts_idev->name = "UCB1400 touchscreen interface";
+ ucb->ts_idev->id.vendor = ucb1400_reg_read(ucb->ac97,
+ AC97_VENDOR_ID1);
+ ucb->ts_idev->id.product = ucb->id;
+ ucb->ts_idev->open = ucb1400_ts_open;
+ ucb->ts_idev->close = ucb1400_ts_close;
+ ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS);
- ucb1400_adc_enable(ucb);
+ ucb1400_adc_enable(ucb->ac97);
x_res = ucb1400_ts_read_xres(ucb);
y_res = ucb1400_ts_read_yres(ucb);
- ucb1400_adc_disable(ucb);
+ ucb1400_adc_disable(ucb->ac97);
printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res);
- input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0);
- input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0);
- input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
+ input_set_abs_params(ucb->ts_idev, ABS_X, 0, x_res, 0, 0);
+ input_set_abs_params(ucb->ts_idev, ABS_Y, 0, y_res, 0, 0);
+ input_set_abs_params(ucb->ts_idev, ABS_PRESSURE, 0, 0, 0, 0);
- error = input_register_device(idev);
+ error = input_register_device(ucb->ts_idev);
if (error)
goto err_free_irq;
- dev_set_drvdata(dev, ucb);
return 0;
- err_free_irq:
+err_free_irq:
free_irq(ucb->irq, ucb);
- err_free_devs:
- input_free_device(idev);
- kfree(ucb);
+err_free_devs:
+ input_free_device(ucb->ts_idev);
+err:
return error;
+
}
-static int ucb1400_ts_remove(struct device *dev)
+static int ucb1400_ts_remove(struct platform_device *dev)
{
- struct ucb1400 *ucb = dev_get_drvdata(dev);
+ struct ucb1400_ts *ucb = dev->dev.platform_data;
free_irq(ucb->irq, ucb);
input_unregister_device(ucb->ts_idev);
- dev_set_drvdata(dev, NULL);
- kfree(ucb);
return 0;
}
-static struct device_driver ucb1400_ts_driver = {
- .name = "ucb1400_ts",
- .owner = THIS_MODULE,
- .bus = &ac97_bus_type,
- .probe = ucb1400_ts_probe,
- .remove = ucb1400_ts_remove,
- .resume = ucb1400_ts_resume,
+#ifdef CONFIG_PM
+static int ucb1400_ts_resume(struct platform_device *dev)
+{
+ struct ucb1400_ts *ucb = platform_get_drvdata(dev);
+
+ if (ucb->ts_task) {
+ /*
+ * Restart the TS thread to ensure the
+ * TS interrupt mode is set up again
+ * after sleep.
+ */
+ ucb->ts_restart = 1;
+ wake_up(&ucb->ts_wait);
+ }
+ return 0;
+}
+#else
+#define ucb1400_ts_resume NULL
+#endif
+
+static struct platform_driver ucb1400_ts_driver = {
+ .probe = ucb1400_ts_probe,
+ .remove = ucb1400_ts_remove,
+ .resume = ucb1400_ts_resume,
+ .driver = {
+ .name = "ucb1400_ts",
+ },
};
static int __init ucb1400_ts_init(void)
{
- return driver_register(&ucb1400_ts_driver);
+ return platform_driver_register(&ucb1400_ts_driver);
}
static void __exit ucb1400_ts_exit(void)
{
- driver_unregister(&ucb1400_ts_driver);
+ platform_driver_unregister(&ucb1400_ts_driver);
}
module_param(adcsync, bool, 0444);
MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
module_param(ts_delay, int, 0444);
-MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us.");
+MODULE_PARM_DESC(ts_delay, "Delay between panel setup and"
+ " position read. Default = 55us.");
module_param(ts_delay_pressure, int, 0444);
MODULE_PARM_DESC(ts_delay_pressure,
- "delay between panel setup and pressure read. Default = 0us.");
+ "delay between panel setup and pressure read."
+ " Default = 0us.");
module_init(ucb1400_ts_init);
module_exit(ucb1400_ts_exit);
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
index 372efbc694f..6b5be742c27 100644
--- a/drivers/input/touchscreen/wm9705.c
+++ b/drivers/input/touchscreen/wm9705.c
@@ -2,8 +2,7 @@
* wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
*
* Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
@@ -347,6 +346,6 @@ struct wm97xx_codec_drv wm9705_codec = {
EXPORT_SYMBOL_GPL(wm9705_codec);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index c8bb1e7335f..7490b05c356 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -2,8 +2,7 @@
* wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
*
* Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
@@ -462,6 +461,6 @@ struct wm97xx_codec_drv wm9712_codec = {
EXPORT_SYMBOL_GPL(wm9712_codec);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index 781ee83547e..238b5132712 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -2,8 +2,7 @@
* wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
@@ -476,6 +475,6 @@ struct wm97xx_codec_drv wm9713_codec = {
EXPORT_SYMBOL_GPL(wm9713_codec);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index d589ab0e3ad..d15aa11d705 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -3,8 +3,7 @@
* and WM9713 AC97 Codecs.
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
@@ -824,6 +823,6 @@ module_init(wm97xx_init);
module_exit(wm97xx_exit);
/* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
index 9ce3b3baf3a..3ab6362f043 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -335,11 +335,11 @@ static struct xenbus_driver xenkbd = {
static int __init xenkbd_init(void)
{
- if (!is_running_on_xen())
+ if (!xen_domain())
return -ENODEV;
/* Nothing to do if running in dom0. */
- if (is_initial_xendomain())
+ if (xen_initial_domain())
return -ENODEV;
return xenbus_register_frontend(&xenkbd);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 871b0cbca5e..1b5bf87c4cf 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1231,7 +1231,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
int error = 0;
switch (cmd) {
default:
- error = n_tty_ioctl (tty, file, cmd, arg);
+ error = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
}
return error;
@@ -1553,8 +1553,7 @@ static int __init capi_init(void)
return PTR_ERR(capi_class);
}
- device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
- "capi");
+ device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 75726ea0fbb..5360c4fd473 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -828,15 +828,18 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
return -ESRCH;
if (card->load_firmware == NULL) {
printk(KERN_DEBUG "kcapi: load: no load function\n");
+ capi_ctr_put(card);
return -ESRCH;
}
if (ldef.t4file.len <= 0) {
printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
+ capi_ctr_put(card);
return -EINVAL;
}
if (ldef.t4file.data == NULL) {
printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
+ capi_ctr_put(card);
return -EINVAL;
}
@@ -849,6 +852,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
if (card->cardstate != CARD_DETECTED) {
printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
+ capi_ctr_put(card);
return -EBUSY;
}
card->cardstate = CARD_LOADING;
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 5e89fa17781..07052ed2a0c 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -571,6 +571,7 @@ gigaset_tty_close(struct tty_struct *tty)
}
/* prevent other callers from entering ldisc methods */
+ /* FIXME: should use the tty state flags */
tty->disc_data = NULL;
if (!cs->hw.ser)
@@ -642,10 +643,11 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
return -ENXIO;
switch (cmd) {
- case TCGETS:
- case TCGETA:
- /* pass through to underlying serial device */
- rc = n_tty_ioctl(tty, file, cmd, arg);
+
+ case FIONREAD:
+ /* unused, always return zero */
+ val = 0;
+ rc = put_user(val, p);
break;
case TCFLSH:
@@ -659,20 +661,13 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
flush_send_queue(cs);
break;
}
- /* flush the serial port's buffer */
- rc = n_tty_ioctl(tty, file, cmd, arg);
- break;
-
- case FIONREAD:
- /* unused, always return zero */
- val = 0;
- rc = put_user(val, p);
- break;
+ /* Pass through */
default:
- rc = -ENOIOCTLCMD;
+ /* pass through to underlying serial device */
+ rc = n_tty_ioctl_helper(tty, file, cmd, arg);
+ break;
}
-
cs_put(cs);
return rc;
}
@@ -680,6 +675,8 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
/*
* Poll on the tty.
* Unused, always return zero.
+ *
+ * FIXME: should probably return an exception - especially on hangup
*/
static unsigned int
gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index a5b941c327f..c72565520e4 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -154,83 +154,50 @@ static void avmcs_detach(struct pcmcia_device *link)
======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
+static int avmcs_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_first_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_next_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
+ if (cf->io.nwin <= 0)
+ return -ENODEV;
+
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.NumPorts1 = cf->io.win[0].len;
+ p_dev->io.NumPorts2 = 0;
+ printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
+ p_dev->io.BasePort1,
+ p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+ return pcmcia_request_io(p_dev, &p_dev->io);
}
static int avmcs_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
local_info_t *dev;
int i;
- u_char buf[64];
char devname[128];
int cardtype;
int (*addcard)(unsigned int port, unsigned irq);
dev = link->priv;
- do {
- devname[0] = 0;
- if (link->prod_id[1])
- strlcpy(devname, link->prod_id[1], sizeof(devname));
+ devname[0] = 0;
+ if (link->prod_id[1])
+ strlcpy(devname, link->prod_id[1], sizeof(devname));
- /*
- * find IO port
- */
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link, &tuple, &parse);
- while (i == CS_SUCCESS) {
- if (cf->io.nwin > 0) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.NumPorts1 = cf->io.win[0].len;
- link->io.NumPorts2 = 0;
- printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
- link->io.BasePort1,
- link->io.BasePort1+link->io.NumPorts1-1);
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) goto found_port;
- }
- i = next_tuple(link, &tuple, &parse);
- }
-
-found_port:
- if (i != CS_SUCCESS) {
- cs_error(link, RequestIO, i);
- break;
- }
+ /*
+ * find IO port
+ */
+ if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
+ return -ENODEV;
+ do {
/*
* allocate an interrupt line
*/
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
/* undo */
pcmcia_disable_device(link);
@@ -241,7 +208,7 @@ found_port:
* configure the PCMCIA socket
*/
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
pcmcia_disable_device(link);
break;
diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h
index fd2c9be6d84..5783d22a18f 100644
--- a/drivers/isdn/hardware/mISDN/hfc_pci.h
+++ b/drivers/isdn/hardware/mISDN/hfc_pci.h
@@ -183,8 +183,8 @@
#define D_FREG_MASK 0xF
struct zt {
- unsigned short z1; /* Z1 pointer 16 Bit */
- unsigned short z2; /* Z2 pointer 16 Bit */
+ __le16 z1; /* Z1 pointer 16 Bit */
+ __le16 z2; /* Z2 pointer 16 Bit */
};
struct dfifo {
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 9cf5edbb1a9..cd8302af40e 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
module_param(debug, uint, 0);
static LIST_HEAD(HFClist);
-DEFINE_RWLOCK(HFClock);
+static DEFINE_RWLOCK(HFClock);
enum {
HFC_CCD_2BD0,
@@ -88,7 +88,7 @@ struct hfcPCI_hw {
unsigned char bswapped;
unsigned char protocol;
int nt_timer;
- unsigned char *pci_io; /* start of PCI IO memory */
+ unsigned char __iomem *pci_io; /* start of PCI IO memory */
dma_addr_t dmahandle;
void *fifos; /* FIFO memory */
int last_bfifo_cnt[2];
@@ -153,7 +153,7 @@ release_io_hfcpci(struct hfc_pci *hc)
pci_write_config_word(hc->pdev, PCI_COMMAND, 0);
del_timer(&hc->hw.timer);
pci_free_consistent(hc->pdev, 0x8000, hc->hw.fifos, hc->hw.dmahandle);
- iounmap((void *)hc->hw.pci_io);
+ iounmap(hc->hw.pci_io);
}
/*
@@ -366,8 +366,7 @@ static void hfcpci_clear_fifo_tx(struct hfc_pci *hc, int fifo)
bzt->f2 = MAX_B_FRAMES;
bzt->f1 = bzt->f2; /* init F pointers to remain constant */
bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1);
- bzt->za[MAX_B_FRAMES].z2 = cpu_to_le16(
- le16_to_cpu(bzt->za[MAX_B_FRAMES].z1 - 1));
+ bzt->za[MAX_B_FRAMES].z2 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 2);
if (fifo_state)
hc->hw.fifo_en |= fifo_state;
Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
@@ -482,7 +481,7 @@ receive_dmsg(struct hfc_pci *hc)
df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) |
(MAX_D_FRAMES + 1); /* next buffer */
df->za[df->f2 & D_FREG_MASK].z2 =
- cpu_to_le16((zp->z2 + rcnt) & (D_FIFO_SIZE - 1));
+ cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1));
} else {
dch->rx_skb = mI_alloc_skb(rcnt - 3, GFP_ATOMIC);
if (!dch->rx_skb) {
@@ -523,10 +522,10 @@ receive_dmsg(struct hfc_pci *hc)
/*
* check for transparent receive data and read max one threshold size if avail
*/
-int
+static int
hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
{
- unsigned short *z1r, *z2r;
+ __le16 *z1r, *z2r;
int new_z2, fcnt, maxlen;
u_char *ptr, *ptr1;
@@ -576,7 +575,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
/*
* B-channel main receive routine
*/
-void
+static void
main_rec_hfcpci(struct bchannel *bch)
{
struct hfc_pci *hc = bch->hw;
@@ -724,7 +723,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
struct bzfifo *bz;
u_char *bdata;
u_char new_f1, *src, *dst;
- unsigned short *z1t, *z2t;
+ __le16 *z1t, *z2t;
if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
printk(KERN_DEBUG "%s\n", __func__);
@@ -1679,7 +1678,7 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
* called for card init message
*/
-void
+static void
inithfcpci(struct hfc_pci *hc)
{
printk(KERN_DEBUG "inithfcpci: entered\n");
@@ -1966,7 +1965,7 @@ setup_hw(struct hfc_pci *hc)
printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
return 1;
}
- hc->hw.pci_io = (char *)(ulong)hc->pdev->resource[1].start;
+ hc->hw.pci_io = (char __iomem *)(unsigned long)hc->pdev->resource[1].start;
if (!hc->hw.pci_io) {
printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index fc6cc2c065b..23560c897ec 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -174,38 +174,29 @@ static void avma1cs_detach(struct pcmcia_device *link)
======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
+ if (cf->io.nwin <= 0)
+ return -ENODEV;
+
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.NumPorts1 = cf->io.win[0].len;
+ p_dev->io.NumPorts2 = 0;
+ printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
+ p_dev->io.BasePort1,
+ p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+ return pcmcia_request_io(p_dev, &p_dev->io);
}
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_first_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_next_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
-}
static int avma1cs_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
local_info_t *dev;
int i;
- u_char buf[64];
char devname[128];
IsdnCard_t icard;
int busy = 0;
@@ -214,45 +205,19 @@ static int avma1cs_config(struct pcmcia_device *link)
DEBUG(0, "avma1cs_config(0x%p)\n", link);
- do {
- devname[0] = 0;
- if (link->prod_id[1])
- strlcpy(devname, link->prod_id[1], sizeof(devname));
+ devname[0] = 0;
+ if (link->prod_id[1])
+ strlcpy(devname, link->prod_id[1], sizeof(devname));
- /*
- * find IO port
- */
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link, &tuple, &parse);
- while (i == CS_SUCCESS) {
- if (cf->io.nwin > 0) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.NumPorts1 = cf->io.win[0].len;
- link->io.NumPorts2 = 0;
- printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
- link->io.BasePort1,
- link->io.BasePort1+link->io.NumPorts1 - 1);
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) goto found_port;
- }
- i = next_tuple(link, &tuple, &parse);
- }
+ if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
+ return -ENODEV;
-found_port:
- if (i != CS_SUCCESS) {
- cs_error(link, RequestIO, i);
- break;
- }
-
+ do {
/*
* allocate an interrupt line
*/
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
/* undo */
pcmcia_disable_device(link);
@@ -263,7 +228,7 @@ found_port:
* configure the PCMCIA socket
*/
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
pcmcia_disable_device(link);
break;
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index db7e64424af..f4d0fe29bcf 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -203,82 +203,55 @@ static void elsa_cs_detach(struct pcmcia_device *link)
device available to the system.
======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_first_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
-}
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i = pcmcia_get_next_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
+ int j;
+
+ if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+ printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ } else {
+ printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
+ for (j = 0x2f0; j > 0x100; j -= 0x10) {
+ p_dev->io.BasePort1 = j;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
}
static int elsa_cs_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
- int i, j, last_fn;
- u_short buf[128];
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+ int i, last_fn;
IsdnCard_t icard;
DEBUG(0, "elsa_config(0x%p)\n", link);
dev = link->priv;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link, &tuple, &parse);
- while (i == CS_SUCCESS) {
- if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
- printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- } else {
- printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
- link->conf.ConfigIndex = cf->index;
- for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
- link->io.BasePort1 = j;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- break;
- }
- i = next_tuple(link, &tuple, &parse);
- }
-
- if (i != CS_SUCCESS) {
+ i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
+ if (i != 0) {
last_fn = RequestIO;
goto cs_failed;
}
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
last_fn = RequestConfiguration;
goto cs_failed;
}
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 439cb530def..9a3c9f5e4fe 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -217,101 +217,61 @@ static void sedlbauer_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int sedlbauer_config(struct pcmcia_device *link)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- local_info_t *dev = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int last_fn, last_ret;
- u8 buf[64];
- config_info_t conf;
- win_req_t req;
- memreq_t map;
- IsdnCard_t icard;
-
- DEBUG(0, "sedlbauer_config(0x%p)\n", link);
-
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
+ win_req_t *req = priv_data;
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
+ if (cfg->index == 0)
+ return -ENODEV;
- /*
- In this loop, we scan the CIS for configuration table entries,
- each of which describes a valid card configuration, including
- voltage, IO window, memory window, and interrupt settings.
-
- We make no assumptions about the card to be configured: we use
- just the information available in the CIS. In an ideal world,
- this would work for any PCMCIA card, but it requires a complete
- and accurate CIS. In practice, a driver usually "knows" most of
- these things without consulting the CIS, and most client drivers
- will only use the CIS to fill in implementation-defined details.
- */
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t dflt = { 0 };
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- if (cfg->index == 0) goto next_entry;
- link->conf.ConfigIndex = cfg->index;
-
/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
}
-
+
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
- goto next_entry;
- } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
- goto next_entry;
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
}
-
+
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
+ p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
/* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
/* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-/* new in dummy.cs 2001/01/28 MN
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-*/
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+ return -ENODEV;
}
/*
@@ -325,30 +285,54 @@ static int sedlbauer_config(struct pcmcia_device *link)
needs to be mapped to virtual space with ioremap() before it
is used.
*/
- if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
- cistpl_mem_t *mem =
- (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- req.Attributes |= WIN_ENABLE;
- req.Base = mem->win[0].host_addr;
- req.Size = mem->win[0].len;
-/* new in dummy.cs 2001/01/28 MN
- if (req.Size < 0x1000)
- req.Size = 0x1000;
-*/
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link, &req, &link->win) != 0)
- goto next_entry;
- map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
- goto next_entry;
+ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+ cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+ memreq_t map;
+ req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+ req->Attributes |= WIN_ENABLE;
+ req->Base = mem->win[0].host_addr;
+ req->Size = mem->win[0].len;
+ req->AccessSpeed = 0;
+ if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0)
+ return -ENODEV;
+ map.Page = 0;
+ map.CardOffset = mem->win[0].card_addr;
+ if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+ return -ENODEV;
}
- /* If we got this far, we're cool! */
- break;
+ return 0;
+}
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
+
+
+static int sedlbauer_config(struct pcmcia_device *link)
+{
+ local_info_t *dev = link->priv;
+ win_req_t *req;
+ int last_fn, last_ret;
+ IsdnCard_t icard;
+
+ DEBUG(0, "sedlbauer_config(0x%p)\n", link);
+
+ req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ /*
+ In this loop, we scan the CIS for configuration table entries,
+ each of which describes a valid card configuration, including
+ voltage, IO window, memory window, and interrupt settings.
+
+ We make no assumptions about the card to be configured: we use
+ just the information available in the CIS. In an ideal world,
+ this would work for any PCMCIA card, but it requires a complete
+ and accurate CIS. In practice, a driver usually "knows" most of
+ these things without consulting the CIS, and most client drivers
+ will only use the CIS to fill in implementation-defined details.
+ */
+ last_ret = pcmcia_loop_config(link, sedlbauer_config_check, req);
+ if (last_ret)
+ goto failed;
/*
Allocate an interrupt line. Note that this does not assign a
@@ -387,8 +371,8 @@ static int sedlbauer_config(struct pcmcia_device *link)
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
if (link->win)
- printk(", mem 0x%06lx-0x%06lx", req.Base,
- req.Base+req.Size-1);
+ printk(", mem 0x%06lx-0x%06lx", req->Base,
+ req->Base+req->Size-1);
printk("\n");
icard.para[0] = link->irq.AssignedIRQ;
@@ -409,6 +393,7 @@ static int sedlbauer_config(struct pcmcia_device *link)
cs_failed:
cs_error(link, last_fn, last_ret);
+failed:
sedlbauer_release(link);
return -ENODEV;
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index ab4bd455450..623d111544d 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -193,82 +193,55 @@ static void teles_detach(struct pcmcia_device *link)
device available to the system.
======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
-{
- int i = pcmcia_get_first_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
-}
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
- cisparse_t *parse)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i = pcmcia_get_next_tuple(handle, tuple);
- if (i != CS_SUCCESS) return i;
- return get_tuple(handle, tuple, parse);
+ int j;
+
+ if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+ printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ } else {
+ printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
+ for (j = 0x2f0; j > 0x100; j -= 0x10) {
+ p_dev->io.BasePort1 = j;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
}
static int teles_cs_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
- int i, j, last_fn;
- u_short buf[128];
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+ int i, last_fn;
IsdnCard_t icard;
DEBUG(0, "teles_config(0x%p)\n", link);
dev = link->priv;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link, &tuple, &parse);
- while (i == CS_SUCCESS) {
- if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
- printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- } else {
- printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
- link->conf.ConfigIndex = cf->index;
- for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
- link->io.BasePort1 = j;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- break;
- }
- i = next_tuple(link, &tuple, &parse);
- }
-
- if (i != CS_SUCCESS) {
+ i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
+ if (i != 0) {
last_fn = RequestIO;
goto cs_failed;
}
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
last_fn = RequestConfiguration;
goto cs_failed;
}
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 127cfdad68e..77c280ef2eb 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1533,8 +1533,10 @@ static int isdn_ppp_mp_bundle_array_init(void)
int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
return -ENOMEM;
- for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
+ skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags);
+ }
return 0;
}
@@ -1567,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
return -ENOMEM;
lp->next = lp->last = lp; /* nobody else in a queue */
- lp->netdev->pb->frags = NULL;
+ skb_queue_head_init(&lp->netdev->pb->frags);
lp->netdev->pb->frames = 0;
lp->netdev->pb->seq = UINT_MAX;
}
@@ -1579,28 +1581,29 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
static u32 isdn_ppp_mp_get_seq( int short_seq,
struct sk_buff * skb, u32 last_seq );
-static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
- struct sk_buff * from, struct sk_buff * to );
-static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff * from, struct sk_buff * to );
-static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
+static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
+ struct sk_buff *to);
+static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
+ struct sk_buff *from, struct sk_buff *to,
+ u32 lastseq);
+static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
- struct ippp_struct *is;
- isdn_net_local * lpq;
- ippp_bundle * mp;
- isdn_mppp_stats * stats;
- struct sk_buff * newfrag, * frag, * start, *nextf;
+ struct sk_buff *newfrag, *frag, *start, *nextf;
u32 newseq, minseq, thisseq;
+ isdn_mppp_stats *stats;
+ struct ippp_struct *is;
unsigned long flags;
+ isdn_net_local *lpq;
+ ippp_bundle *mp;
int slot;
spin_lock_irqsave(&net_dev->pb->lock, flags);
- mp = net_dev->pb;
- stats = &mp->stats;
+ mp = net_dev->pb;
+ stats = &mp->stats;
slot = lp->ppp_slot;
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
@@ -1611,20 +1614,19 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
return;
}
is = ippp_table[slot];
- if( ++mp->frames > stats->max_queue_len )
+ if (++mp->frames > stats->max_queue_len)
stats->max_queue_len = mp->frames;
-
+
if (is->debug & 0x8)
isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
- newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
- skb, is->last_link_seqno);
-
+ newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
+ skb, is->last_link_seqno);
/* if this packet seq # is less than last already processed one,
* toss it right away, but check for sequence start case first
*/
- if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
+ if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
mp->seq = newseq; /* the first packet: required for
* rfc1990 non-compliant clients --
* prevents constant packet toss */
@@ -1634,7 +1636,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
spin_unlock_irqrestore(&mp->lock, flags);
return;
}
-
+
/* find the minimum received sequence number over all links */
is->last_link_seqno = minseq = newseq;
for (lpq = net_dev->queue;;) {
@@ -1655,22 +1657,31 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* packets */
newfrag = skb;
- /* if this new fragment is before the first one, then enqueue it now. */
- if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
- newfrag->next = frag;
- mp->frags = frag = newfrag;
- newfrag = NULL;
- }
+ /* Insert new fragment into the proper sequence slot. */
+ skb_queue_walk(&mp->frags, frag) {
+ if (MP_SEQ(frag) == newseq) {
+ isdn_ppp_mp_free_skb(mp, newfrag);
+ newfrag = NULL;
+ break;
+ }
+ if (MP_LT(newseq, MP_SEQ(frag))) {
+ __skb_queue_before(&mp->frags, frag, newfrag);
+ newfrag = NULL;
+ break;
+ }
+ }
+ if (newfrag)
+ __skb_queue_tail(&mp->frags, newfrag);
- start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
- MP_SEQ(frag) == mp->seq ? frag : NULL;
+ frag = skb_peek(&mp->frags);
+ start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) &&
+ (MP_SEQ(frag) == mp->seq)) ? frag : NULL;
+ if (!start)
+ goto check_overflow;
- /*
- * main fragment traversing loop
+ /* main fragment traversing loop
*
* try to accomplish several tasks:
- * - insert new fragment into the proper sequence slot (once that's done
- * newfrag will be set to NULL)
* - reassemble any complete fragment sequence (non-null 'start'
* indicates there is a continguous sequence present)
* - discard any incomplete sequences that are below minseq -- due
@@ -1679,71 +1690,46 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* come to complete such sequence and it should be discarded
*
* loop completes when we accomplished the following tasks:
- * - new fragment is inserted in the proper sequence ('newfrag' is
- * set to NULL)
* - we hit a gap in the sequence, so no reassembly/processing is
* possible ('start' would be set to NULL)
*
* algorithm for this code is derived from code in the book
* 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
*/
- while (start != NULL || newfrag != NULL) {
-
- thisseq = MP_SEQ(frag);
- nextf = frag->next;
-
- /* drop any duplicate fragments */
- if (newfrag != NULL && thisseq == newseq) {
- isdn_ppp_mp_free_skb(mp, newfrag);
- newfrag = NULL;
- }
-
- /* insert new fragment before next element if possible. */
- if (newfrag != NULL && (nextf == NULL ||
- MP_LT(newseq, MP_SEQ(nextf)))) {
- newfrag->next = nextf;
- frag->next = nextf = newfrag;
- newfrag = NULL;
- }
-
- if (start != NULL) {
- /* check for misplaced start */
- if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
- printk(KERN_WARNING"isdn_mppp(seq %d): new "
- "BEGIN flag with no prior END", thisseq);
- stats->seqerrs++;
- stats->frame_drops++;
- start = isdn_ppp_mp_discard(mp, start,frag);
- nextf = frag->next;
- }
- } else if (MP_LE(thisseq, minseq)) {
- if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
+ skb_queue_walk_safe(&mp->frags, frag, nextf) {
+ thisseq = MP_SEQ(frag);
+
+ /* check for misplaced start */
+ if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
+ printk(KERN_WARNING"isdn_mppp(seq %d): new "
+ "BEGIN flag with no prior END", thisseq);
+ stats->seqerrs++;
+ stats->frame_drops++;
+ isdn_ppp_mp_discard(mp, start, frag);
+ start = frag;
+ } else if (MP_LE(thisseq, minseq)) {
+ if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
start = frag;
- else {
+ else {
if (MP_FLAGS(frag) & MP_END_FRAG)
- stats->frame_drops++;
- if( mp->frags == frag )
- mp->frags = nextf;
+ stats->frame_drops++;
+ __skb_unlink(skb, &mp->frags);
isdn_ppp_mp_free_skb(mp, frag);
- frag = nextf;
continue;
- }
+ }
}
-
- /* if start is non-null and we have end fragment, then
- * we have full reassembly sequence -- reassemble
- * and process packet now
+
+ /* if we have end fragment, then we have full reassembly
+ * sequence -- reassemble and process packet now
*/
- if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
- minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
- /* Reassemble the packet then dispatch it */
- isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
-
- start = NULL;
- frag = NULL;
+ if (MP_FLAGS(frag) & MP_END_FRAG) {
+ minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
+ /* Reassemble the packet then dispatch it */
+ isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq);
- mp->frags = nextf;
- }
+ start = NULL;
+ frag = NULL;
+ }
/* check if need to update start pointer: if we just
* reassembled the packet and sequence is contiguous
@@ -1754,26 +1740,25 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* below low watermark and set start to the next frag or
* clear start ptr.
*/
- if (nextf != NULL &&
+ if (nextf != (struct sk_buff *)&mp->frags &&
((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
- /* if we just reassembled and the next one is here,
- * then start another reassembly. */
-
- if (frag == NULL) {
+ /* if we just reassembled and the next one is here,
+ * then start another reassembly.
+ */
+ if (frag == NULL) {
if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
- start = nextf;
- else
- {
- printk(KERN_WARNING"isdn_mppp(seq %d):"
- " END flag with no following "
- "BEGIN", thisseq);
+ start = nextf;
+ else {
+ printk(KERN_WARNING"isdn_mppp(seq %d):"
+ " END flag with no following "
+ "BEGIN", thisseq);
stats->seqerrs++;
}
}
-
- } else {
- if ( nextf != NULL && frag != NULL &&
- MP_LT(thisseq, minseq)) {
+ } else {
+ if (nextf != (struct sk_buff *)&mp->frags &&
+ frag != NULL &&
+ MP_LT(thisseq, minseq)) {
/* we've got a break in the sequence
* and we not at the end yet
* and we did not just reassembled
@@ -1782,41 +1767,39 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* discard all the frames below low watermark
* and start over */
stats->frame_drops++;
- mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
+ isdn_ppp_mp_discard(mp, start, nextf);
}
/* break in the sequence, no reassembly */
- start = NULL;
- }
-
- frag = nextf;
- } /* while -- main loop */
-
- if (mp->frags == NULL)
- mp->frags = frag;
-
+ start = NULL;
+ }
+ if (!start)
+ break;
+ }
+
+check_overflow:
/* rather straighforward way to deal with (not very) possible
- * queue overflow */
+ * queue overflow
+ */
if (mp->frames > MP_MAX_QUEUE_LEN) {
stats->overflows++;
- while (mp->frames > MP_MAX_QUEUE_LEN) {
- frag = mp->frags->next;
- isdn_ppp_mp_free_skb(mp, mp->frags);
- mp->frags = frag;
+ skb_queue_walk_safe(&mp->frags, frag, nextf) {
+ if (mp->frames <= MP_MAX_QUEUE_LEN)
+ break;
+ __skb_unlink(frag, &mp->frags);
+ isdn_ppp_mp_free_skb(mp, frag);
}
}
spin_unlock_irqrestore(&mp->lock, flags);
}
-static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
+static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
{
- struct sk_buff * frag = lp->netdev->pb->frags;
- struct sk_buff * nextfrag;
- while( frag ) {
- nextfrag = frag->next;
- isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
- frag = nextfrag;
- }
- lp->netdev->pb->frags = NULL;
+ struct sk_buff *skb, *tmp;
+
+ skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) {
+ __skb_unlink(skb, &lp->netdev->pb->frags);
+ isdn_ppp_mp_free_skb(lp->netdev->pb, skb);
+ }
}
static u32 isdn_ppp_mp_get_seq( int short_seq,
@@ -1853,72 +1836,115 @@ static u32 isdn_ppp_mp_get_seq( int short_seq,
return seq;
}
-struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
- struct sk_buff * from, struct sk_buff * to )
+static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
+ struct sk_buff *to)
{
- if( from )
- while (from != to) {
- struct sk_buff * next = from->next;
- isdn_ppp_mp_free_skb(mp, from);
- from = next;
+ if (from) {
+ struct sk_buff *skb, *tmp;
+ int freeing = 0;
+
+ skb_queue_walk_safe(&mp->frags, skb, tmp) {
+ if (skb == to)
+ break;
+ if (skb == from)
+ freeing = 1;
+ if (!freeing)
+ continue;
+ __skb_unlink(skb, &mp->frags);
+ isdn_ppp_mp_free_skb(mp, skb);
}
- return from;
+ }
}
-void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff * from, struct sk_buff * to )
+static unsigned int calc_tot_len(struct sk_buff_head *queue,
+ struct sk_buff *from, struct sk_buff *to)
{
- ippp_bundle * mp = net_dev->pb;
- int proto;
- struct sk_buff * skb;
+ unsigned int tot_len = 0;
+ struct sk_buff *skb;
+ int found_start = 0;
+
+ skb_queue_walk(queue, skb) {
+ if (skb == from)
+ found_start = 1;
+ if (!found_start)
+ continue;
+ tot_len += skb->len - MP_HEADER_LEN;
+ if (skb == to)
+ break;
+ }
+ return tot_len;
+}
+
+/* Reassemble packet using fragments in the reassembly queue from
+ * 'from' until 'to', inclusive.
+ */
+static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
+ struct sk_buff *from, struct sk_buff *to,
+ u32 lastseq)
+{
+ ippp_bundle *mp = net_dev->pb;
unsigned int tot_len;
+ struct sk_buff *skb;
+ int proto;
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__func__, lp->ppp_slot);
return;
}
- if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
- if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+
+ tot_len = calc_tot_len(&mp->frags, from, to);
+
+ if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
+ if (ippp_table[lp->ppp_slot]->debug & 0x40)
printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
- "len %d\n", MP_SEQ(from), from->len );
+ "len %d\n", MP_SEQ(from), from->len);
skb = from;
skb_pull(skb, MP_HEADER_LEN);
+ __skb_unlink(skb, &mp->frags);
mp->frames--;
} else {
- struct sk_buff * frag;
- int n;
+ struct sk_buff *walk, *tmp;
+ int found_start = 0;
- for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
- tot_len += frag->len - MP_HEADER_LEN;
-
- if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+ if (ippp_table[lp->ppp_slot]->debug & 0x40)
printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
- "to %d, len %d\n", MP_SEQ(from),
- (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
- if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
+ "to %d, len %d\n", MP_SEQ(from), lastseq,
+ tot_len);
+
+ skb = dev_alloc_skb(tot_len);
+ if (!skb)
printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
- "of size %d\n", tot_len);
- isdn_ppp_mp_discard(mp, from, to);
- return;
- }
+ "of size %d\n", tot_len);
+
+ found_start = 0;
+ skb_queue_walk_safe(&mp->frags, walk, tmp) {
+ if (walk == from)
+ found_start = 1;
+ if (!found_start)
+ continue;
- while( from != to ) {
- unsigned int len = from->len - MP_HEADER_LEN;
+ if (skb) {
+ unsigned int len = walk->len - MP_HEADER_LEN;
+ skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN,
+ skb_put(skb, len),
+ len);
+ }
+ __skb_unlink(walk, &mp->frags);
+ isdn_ppp_mp_free_skb(mp, walk);
- skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
- skb_put(skb,len),
- len);
- frag = from->next;
- isdn_ppp_mp_free_skb(mp, from);
- from = frag;
+ if (walk == to)
+ break;
}
}
+ if (!skb)
+ return;
+
proto = isdn_ppp_strip_proto(skb);
isdn_ppp_push_higher(net_dev, lp, skb, proto);
}
-static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
+static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
{
dev_kfree_skb(skb);
mp->frames--;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index e92b1ba4b45..c2f51cc5076 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -452,10 +452,10 @@ one_member:
if (finddsp->features.pcm_id == dsp->features.pcm_id) {
if (finddsp->pcm_slot_rx >= 0 &&
finddsp->pcm_slot_rx < sizeof(freeslots))
- freeslots[finddsp->pcm_slot_tx] = 0;
+ freeslots[finddsp->pcm_slot_rx] = 0;
if (finddsp->pcm_slot_tx >= 0 &&
finddsp->pcm_slot_tx < sizeof(freeslots))
- freeslots[finddsp->pcm_slot_rx] = 0;
+ freeslots[finddsp->pcm_slot_tx] = 0;
}
}
i = 0;
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index b5fabc7019d..875fabe16e3 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -61,7 +61,7 @@ mISDN_open(struct inode *ino, struct file *filep)
init_waitqueue_head(&dev->wait);
filep->private_data = dev;
__module_get(THIS_MODULE);
- return 0;
+ return nonseekable_open(ino, filep);
}
static int
@@ -124,18 +124,6 @@ mISDN_read(struct file *filep, char *buf, size_t count, loff_t *off)
return ret;
}
-static loff_t
-mISDN_llseek(struct file *filep, loff_t offset, int orig)
-{
- return -ESPIPE;
-}
-
-static ssize_t
-mISDN_write(struct file *filep, const char *buf, size_t count, loff_t *off)
-{
- return -EOPNOTSUPP;
-}
-
static unsigned int
mISDN_poll(struct file *filep, poll_table *wait)
{
@@ -157,8 +145,9 @@ mISDN_poll(struct file *filep, poll_table *wait)
}
static void
-dev_expire_timer(struct mISDNtimer *timer)
+dev_expire_timer(unsigned long data)
{
+ struct mISDNtimer *timer = (void *)data;
u_long flags;
spin_lock_irqsave(&timer->dev->lock, flags);
@@ -191,7 +180,7 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
spin_unlock_irqrestore(&dev->lock, flags);
timer->dev = dev;
timer->tl.data = (long)timer;
- timer->tl.function = (void *) dev_expire_timer;
+ timer->tl.function = dev_expire_timer;
init_timer(&timer->tl);
timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000);
add_timer(&timer->tl);
@@ -211,6 +200,9 @@ misdn_del_timer(struct mISDNtimerdev *dev, int id)
list_for_each_entry(timer, &dev->pending, list) {
if (timer->id == id) {
list_del_init(&timer->list);
+ /* RED-PEN AK: race -- timer can be still running on
+ * other CPU. Needs reference count I think
+ */
del_timer(&timer->tl);
ret = timer->id;
kfree(timer);
@@ -268,9 +260,7 @@ mISDN_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
}
static struct file_operations mISDN_fops = {
- .llseek = mISDN_llseek,
.read = mISDN_read,
- .write = mISDN_write,
.poll = mISDN_poll,
.ioctl = mISDN_ioctl,
.open = mISDN_open,
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 9556262dda5..e3e40427e00 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -24,13 +24,6 @@ config LEDS_ATMEL_PWM
This option enables support for LEDs driven using outputs
of the dedicated PWM controller found on newer Atmel SOCs.
-config LEDS_CORGI
- tristate "LED Support for the Sharp SL-C7x0 series"
- depends on LEDS_CLASS && PXA_SHARP_C7xx
- help
- This option enables support for the LEDs on Sharp Zaurus
- SL-C7x0 series (C700, C750, C760, C860).
-
config LEDS_LOCOMO
tristate "LED Support for Locomo device"
depends on LEDS_CLASS && SHARP_LOCOMO
@@ -38,13 +31,6 @@ config LEDS_LOCOMO
This option enables support for the LEDs on Sharp Locomo.
Zaurus models SL-5500 and SL-5600.
-config LEDS_SPITZ
- tristate "LED Support for the Sharp SL-Cxx00 series"
- depends on LEDS_CLASS && PXA_SHARP_Cxx00
- help
- This option enables support for the LEDs on Sharp Zaurus
- SL-Cxx00 series (C1000, C3000, C3100).
-
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
depends on LEDS_CLASS && ARCH_S3C2410
@@ -96,6 +82,14 @@ config LEDS_COBALT_RAQ
help
This option enables support for the Cobalt Raq series LEDs.
+config LEDS_SUNFIRE
+ tristate "LED support for SunFire servers."
+ depends on LEDS_CLASS && SPARC64
+ select LEDS_TRIGGERS
+ help
+ This option enables support for the Left, Middle, and Right
+ LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
+
config LEDS_HP6XX
tristate "LED Support for the HP Jornada 6xx"
depends on LEDS_CLASS && SH_HP6XX
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index ff7982b4456..eb186c351a1 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -6,9 +6,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
# LED Platform Drivers
obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
-obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
-obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
@@ -16,6 +14,7 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
+obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 559a40861c3..ee74ee7b2ac 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -103,8 +103,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
int rc;
- led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,
- "%s", led_cdev->name);
+ led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
+ "%s", led_cdev->name);
if (IS_ERR(led_cdev->dev))
return PTR_ERR(led_cdev->dev);
diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
deleted file mode 100644
index bc2dcd89f63..00000000000
--- a/drivers/leds/leds-corgi.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * LED Triggers Core
- *
- * Copyright 2005-2006 Openedhand Ltd.
- *
- * Author: Richard Purdie <rpurdie@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <mach/corgi.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <asm/hardware/scoop.h>
-
-static void corgiled_amber_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
- else
- GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
-}
-
-static void corgiled_green_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
- else
- reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
-}
-
-static struct led_classdev corgi_amber_led = {
- .name = "corgi:amber:charge",
- .default_trigger = "sharpsl-charge",
- .brightness_set = corgiled_amber_set,
-};
-
-static struct led_classdev corgi_green_led = {
- .name = "corgi:green:mail",
- .default_trigger = "nand-disk",
- .brightness_set = corgiled_green_set,
-};
-
-#ifdef CONFIG_PM
-static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
-{
-#ifdef CONFIG_LEDS_TRIGGERS
- if (corgi_amber_led.trigger &&
- strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
-#endif
- led_classdev_suspend(&corgi_amber_led);
- led_classdev_suspend(&corgi_green_led);
- return 0;
-}
-
-static int corgiled_resume(struct platform_device *dev)
-{
- led_classdev_resume(&corgi_amber_led);
- led_classdev_resume(&corgi_green_led);
- return 0;
-}
-#endif
-
-static int corgiled_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = led_classdev_register(&pdev->dev, &corgi_amber_led);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &corgi_green_led);
- if (ret < 0)
- led_classdev_unregister(&corgi_amber_led);
-
- return ret;
-}
-
-static int corgiled_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&corgi_amber_led);
- led_classdev_unregister(&corgi_green_led);
- return 0;
-}
-
-static struct platform_driver corgiled_driver = {
- .probe = corgiled_probe,
- .remove = corgiled_remove,
-#ifdef CONFIG_PM
- .suspend = corgiled_suspend,
- .resume = corgiled_resume,
-#endif
- .driver = {
- .name = "corgi-led",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init corgiled_init(void)
-{
- return platform_driver_register(&corgiled_driver);
-}
-
-static void __exit corgiled_exit(void)
-{
- platform_driver_unregister(&corgiled_driver);
-}
-
-module_init(corgiled_init);
-module_exit(corgiled_exit);
-
-MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
-MODULE_DESCRIPTION("Corgi LED driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:corgi-led");
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index be0e12144b8..34935155c1c 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -161,6 +161,16 @@ static int fsg_led_probe(struct platform_device *pdev)
{
int ret;
+ /* Map the LED chip select address space */
+ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
+ if (!latch_address) {
+ ret = -ENOMEM;
+ goto failremap;
+ }
+
+ latch_value = 0xffff;
+ *latch_address = latch_value;
+
ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
if (ret < 0)
goto failwlan;
@@ -185,20 +195,8 @@ static int fsg_led_probe(struct platform_device *pdev)
if (ret < 0)
goto failring;
- /* Map the LED chip select address space */
- latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
- if (!latch_address) {
- ret = -ENOMEM;
- goto failremap;
- }
-
- latch_value = 0xffff;
- *latch_address = latch_value;
-
return ret;
- failremap:
- led_classdev_unregister(&fsg_ring_led);
failring:
led_classdev_unregister(&fsg_sync_led);
failsync:
@@ -210,14 +208,14 @@ static int fsg_led_probe(struct platform_device *pdev)
failwan:
led_classdev_unregister(&fsg_wlan_led);
failwlan:
+ iounmap(latch_address);
+ failremap:
return ret;
}
static int fsg_led_remove(struct platform_device *pdev)
{
- iounmap(latch_address);
-
led_classdev_unregister(&fsg_wlan_led);
led_classdev_unregister(&fsg_wan_led);
led_classdev_unregister(&fsg_sata_led);
@@ -225,6 +223,8 @@ static int fsg_led_remove(struct platform_device *pdev)
led_classdev_unregister(&fsg_sync_led);
led_classdev_unregister(&fsg_ring_led);
+ iounmap(latch_address);
+
return 0;
}
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 146c0697286..f508729123b 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -248,11 +248,10 @@ static int __devinit pca955x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca955x_led *pca955x;
- int i;
- int err = -ENODEV;
struct pca955x_chipdef *chip;
struct i2c_adapter *adapter;
struct led_platform_data *pdata;
+ int i, err;
chip = &pca955x_chipdefs[id->driver_data];
adapter = to_i2c_adapter(client->dev.parent);
@@ -282,43 +281,41 @@ static int __devinit pca955x_probe(struct i2c_client *client,
}
}
+ pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL);
+ if (!pca955x)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, pca955x);
+
for (i = 0; i < chip->bits; i++) {
- pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
- if (!pca955x) {
- err = -ENOMEM;
- goto exit;
- }
+ pca955x[i].chipdef = chip;
+ pca955x[i].client = client;
+ pca955x[i].led_num = i;
- pca955x->chipdef = chip;
- pca955x->client = client;
- pca955x->led_num = i;
/* Platform data can specify LED names and default triggers */
if (pdata) {
if (pdata->leds[i].name)
- snprintf(pca955x->name, 32, "pca955x:%s",
- pdata->leds[i].name);
+ snprintf(pca955x[i].name,
+ sizeof(pca955x[i].name), "pca955x:%s",
+ pdata->leds[i].name);
if (pdata->leds[i].default_trigger)
- pca955x->led_cdev.default_trigger =
+ pca955x[i].led_cdev.default_trigger =
pdata->leds[i].default_trigger;
} else {
- snprintf(pca955x->name, 32, "pca955x:%d", i);
+ snprintf(pca955x[i].name, sizeof(pca955x[i].name),
+ "pca955x:%d", i);
}
- spin_lock_init(&pca955x->lock);
- pca955x->led_cdev.name = pca955x->name;
- pca955x->led_cdev.brightness_set =
- pca955x_led_set;
+ spin_lock_init(&pca955x[i].lock);
- /*
- * Client data is a pointer to the _first_ pca955x_led
- * struct
- */
- if (i == 0)
- i2c_set_clientdata(client, pca955x);
+ pca955x[i].led_cdev.name = pca955x[i].name;
+ pca955x[i].led_cdev.brightness_set = pca955x_led_set;
- INIT_WORK(&(pca955x->work), pca955x_led_work);
+ INIT_WORK(&pca955x[i].work, pca955x_led_work);
- led_classdev_register(&client->dev, &(pca955x->led_cdev));
+ err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
+ if (err < 0)
+ goto exit;
}
/* Turn off LEDs */
@@ -336,23 +333,32 @@ static int __devinit pca955x_probe(struct i2c_client *client,
pca955x_write_psc(client, 1, 0);
return 0;
+
exit:
+ while (i--) {
+ led_classdev_unregister(&pca955x[i].led_cdev);
+ cancel_work_sync(&pca955x[i].work);
+ }
+
+ kfree(pca955x);
+ i2c_set_clientdata(client, NULL);
+
return err;
}
static int __devexit pca955x_remove(struct i2c_client *client)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
- int leds = pca955x->chipdef->bits;
int i;
- for (i = 0; i < leds; i++) {
- led_classdev_unregister(&(pca955x->led_cdev));
- cancel_work_sync(&(pca955x->work));
- kfree(pca955x);
- pca955x = pca955x + 1;
+ for (i = 0; i < pca955x->chipdef->bits; i++) {
+ led_classdev_unregister(&pca955x[i].led_cdev);
+ cancel_work_sync(&pca955x[i].work);
}
+ kfree(pca955x);
+ i2c_set_clientdata(client, NULL);
+
return 0;
}
diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
deleted file mode 100644
index 178831c64bf..00000000000
--- a/drivers/leds/leds-spitz.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * LED Triggers Core
- *
- * Copyright 2005-2006 Openedhand Ltd.
- *
- * Author: Richard Purdie <rpurdie@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <asm/hardware/scoop.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/spitz.h>
-
-static void spitzled_amber_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
- else
- reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
-}
-
-static void spitzled_green_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
- else
- reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
-}
-
-static struct led_classdev spitz_amber_led = {
- .name = "spitz:amber:charge",
- .default_trigger = "sharpsl-charge",
- .brightness_set = spitzled_amber_set,
-};
-
-static struct led_classdev spitz_green_led = {
- .name = "spitz:green:hddactivity",
- .default_trigger = "ide-disk",
- .brightness_set = spitzled_green_set,
-};
-
-#ifdef CONFIG_PM
-static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
-{
-#ifdef CONFIG_LEDS_TRIGGERS
- if (spitz_amber_led.trigger &&
- strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
-#endif
- led_classdev_suspend(&spitz_amber_led);
- led_classdev_suspend(&spitz_green_led);
- return 0;
-}
-
-static int spitzled_resume(struct platform_device *dev)
-{
- led_classdev_resume(&spitz_amber_led);
- led_classdev_resume(&spitz_green_led);
- return 0;
-}
-#endif
-
-static int spitzled_probe(struct platform_device *pdev)
-{
- int ret;
-
- if (machine_is_akita()) {
- spitz_green_led.name = "spitz:green:mail";
- spitz_green_led.default_trigger = "nand-disk";
- }
-
- ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &spitz_green_led);
- if (ret < 0)
- led_classdev_unregister(&spitz_amber_led);
-
- return ret;
-}
-
-static int spitzled_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&spitz_amber_led);
- led_classdev_unregister(&spitz_green_led);
-
- return 0;
-}
-
-static struct platform_driver spitzled_driver = {
- .probe = spitzled_probe,
- .remove = spitzled_remove,
-#ifdef CONFIG_PM
- .suspend = spitzled_suspend,
- .resume = spitzled_resume,
-#endif
- .driver = {
- .name = "spitz-led",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init spitzled_init(void)
-{
- return platform_driver_register(&spitzled_driver);
-}
-
-static void __exit spitzled_exit(void)
-{
- platform_driver_unregister(&spitzled_driver);
-}
-
-module_init(spitzled_init);
-module_exit(spitzled_exit);
-
-MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
-MODULE_DESCRIPTION("Spitz LED driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:spitz-led");
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
new file mode 100644
index 00000000000..6b008f0c3f6
--- /dev/null
+++ b/drivers/leds/leds-sunfire.c
@@ -0,0 +1,273 @@
+/* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <asm/fhc.h>
+#include <asm/upa.h>
+
+#define DRIVER_NAME "leds-sunfire"
+#define PFX DRIVER_NAME ": "
+
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun Fire LED driver");
+MODULE_LICENSE("GPL");
+
+struct sunfire_led {
+ struct led_classdev led_cdev;
+ void __iomem *reg;
+};
+#define to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev)
+
+static void __clockboard_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val, u8 bit)
+{
+ struct sunfire_led *p = to_sunfire_led(led_cdev);
+ u8 reg = upa_readb(p->reg);
+
+ switch (bit) {
+ case CLOCK_CTRL_LLED:
+ if (led_val)
+ reg &= ~bit;
+ else
+ reg |= bit;
+ break;
+
+ default:
+ if (led_val)
+ reg |= bit;
+ else
+ reg &= ~bit;
+ break;
+ }
+ upa_writeb(reg, p->reg);
+}
+
+static void clockboard_left_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED);
+}
+
+static void clockboard_middle_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED);
+}
+
+static void clockboard_right_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED);
+}
+
+static void __fhc_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val, u32 bit)
+{
+ struct sunfire_led *p = to_sunfire_led(led_cdev);
+ u32 reg = upa_readl(p->reg);
+
+ switch (bit) {
+ case FHC_CONTROL_LLED:
+ if (led_val)
+ reg &= ~bit;
+ else
+ reg |= bit;
+ break;
+
+ default:
+ if (led_val)
+ reg |= bit;
+ else
+ reg &= ~bit;
+ break;
+ }
+ upa_writel(reg, p->reg);
+}
+
+static void fhc_left_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __fhc_set(led_cdev, led_val, FHC_CONTROL_LLED);
+}
+
+static void fhc_middle_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __fhc_set(led_cdev, led_val, FHC_CONTROL_MLED);
+}
+
+static void fhc_right_set(struct led_classdev *led_cdev,
+ enum led_brightness led_val)
+{
+ __fhc_set(led_cdev, led_val, FHC_CONTROL_RLED);
+}
+
+typedef void (*set_handler)(struct led_classdev *, enum led_brightness);
+struct led_type {
+ const char *name;
+ set_handler handler;
+ const char *default_trigger;
+};
+
+#define NUM_LEDS_PER_BOARD 3
+struct sunfire_drvdata {
+ struct sunfire_led leds[NUM_LEDS_PER_BOARD];
+};
+
+static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
+ struct led_type *types)
+{
+ struct sunfire_drvdata *p;
+ int i, err = -EINVAL;
+
+ if (pdev->num_resources != 1) {
+ printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n",
+ pdev->num_resources);
+ goto out;
+ }
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n");
+ goto out;
+ }
+
+ for (i = 0; i < NUM_LEDS_PER_BOARD; i++) {
+ struct led_classdev *lp = &p->leds[i].led_cdev;
+
+ p->leds[i].reg = (void __iomem *) pdev->resource[0].start;
+ lp->name = types[i].name;
+ lp->brightness = LED_FULL;
+ lp->brightness_set = types[i].handler;
+ lp->default_trigger = types[i].default_trigger;
+
+ err = led_classdev_register(&pdev->dev, lp);
+ if (err) {
+ printk(KERN_ERR PFX "Could not register %s LED\n",
+ lp->name);
+ goto out_unregister_led_cdevs;
+ }
+ }
+
+ dev_set_drvdata(&pdev->dev, p);
+
+ err = 0;
+out:
+ return err;
+
+out_unregister_led_cdevs:
+ for (i--; i >= 0; i--)
+ led_classdev_unregister(&p->leds[i].led_cdev);
+ goto out;
+}
+
+static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
+{
+ struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev);
+ int i;
+
+ for (i = 0; i < NUM_LEDS_PER_BOARD; i++)
+ led_classdev_unregister(&p->leds[i].led_cdev);
+
+ kfree(p);
+
+ return 0;
+}
+
+static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
+ {
+ .name = "clockboard-left",
+ .handler = clockboard_left_set,
+ },
+ {
+ .name = "clockboard-middle",
+ .handler = clockboard_middle_set,
+ },
+ {
+ .name = "clockboard-right",
+ .handler = clockboard_right_set,
+ .default_trigger= "heartbeat",
+ },
+};
+
+static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev)
+{
+ return sunfire_led_generic_probe(pdev, clockboard_led_types);
+}
+
+static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = {
+ {
+ .name = "fhc-left",
+ .handler = fhc_left_set,
+ },
+ {
+ .name = "fhc-middle",
+ .handler = fhc_middle_set,
+ },
+ {
+ .name = "fhc-right",
+ .handler = fhc_right_set,
+ .default_trigger= "heartbeat",
+ },
+};
+
+static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev)
+{
+ return sunfire_led_generic_probe(pdev, fhc_led_types);
+}
+
+MODULE_ALIAS("platform:sunfire-clockboard-leds");
+MODULE_ALIAS("platform:sunfire-fhc-leds");
+
+static struct platform_driver sunfire_clockboard_led_driver = {
+ .probe = sunfire_clockboard_led_probe,
+ .remove = __devexit_p(sunfire_led_generic_remove),
+ .driver = {
+ .name = "sunfire-clockboard-leds",
+ .owner = THIS_MODULE,
+ },
+};
+
+static struct platform_driver sunfire_fhc_led_driver = {
+ .probe = sunfire_fhc_led_probe,
+ .remove = __devexit_p(sunfire_led_generic_remove),
+ .driver = {
+ .name = "sunfire-fhc-leds",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sunfire_leds_init(void)
+{
+ int err = platform_driver_register(&sunfire_clockboard_led_driver);
+
+ if (err) {
+ printk(KERN_ERR PFX "Could not register clock board LED driver\n");
+ return err;
+ }
+
+ err = platform_driver_register(&sunfire_fhc_led_driver);
+ if (err) {
+ printk(KERN_ERR PFX "Could not register FHC LED driver\n");
+ platform_driver_unregister(&sunfire_clockboard_led_driver);
+ }
+
+ return err;
+}
+
+static void __exit sunfire_leds_exit(void)
+{
+ platform_driver_unregister(&sunfire_clockboard_led_driver);
+ platform_driver_unregister(&sunfire_fhc_led_driver);
+}
+
+module_init(sunfire_leds_init);
+module_exit(sunfire_leds_exit);
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index cae52485208..23741cec45e 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -862,8 +862,7 @@ adbdev_init(void)
adb_dev_class = class_create(THIS_MODULE, "adb");
if (IS_ERR(adb_dev_class))
return;
- device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
- "adb");
+ device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
platform_device_register(&adb_pfdev);
platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 07d92c11b5d..2281b5098e9 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -30,6 +30,20 @@ config BLK_DEV_MD
If unsure, say N.
+config MD_AUTODETECT
+ bool "Autodetect RAID arrays during kernel boot"
+ depends on BLK_DEV_MD=y
+ default y
+ ---help---
+ If you say Y here, then the kernel will try to autodetect raid
+ arrays as part of its boot process.
+
+ If you don't use raid and say Y, this autodetection can cause
+ a several-second delay in the boot time due to various
+ synchronisation steps that are part of this step.
+
+ If unsure, say Y.
+
config MD_LINEAR
tristate "Linear (append) mode"
depends on BLK_DEV_MD
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 7e65bad522c..ac89a5deaca 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -238,15 +238,47 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
}
+static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+{
+ /* Iterate the disks of an mddev, using rcu to protect access to the
+ * linked list, and raising the refcount of devices we return to ensure
+ * they don't disappear while in use.
+ * As devices are only added or removed when raid_disk is < 0 and
+ * nr_pending is 0 and In_sync is clear, the entries we return will
+ * still be in the same position on the list when we re-enter
+ * list_for_each_continue_rcu.
+ */
+ struct list_head *pos;
+ rcu_read_lock();
+ if (rdev == NULL)
+ /* start at the beginning */
+ pos = &mddev->disks;
+ else {
+ /* release the previous rdev and start from there. */
+ rdev_dec_pending(rdev, mddev);
+ pos = &rdev->same_set;
+ }
+ list_for_each_continue_rcu(pos, &mddev->disks) {
+ rdev = list_entry(pos, mdk_rdev_t, same_set);
+ if (rdev->raid_disk >= 0 &&
+ test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags)) {
+ /* this is a usable devices */
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ return rdev;
+ }
+ }
+ rcu_read_unlock();
+ return NULL;
+}
+
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
{
- mdk_rdev_t *rdev;
+ mdk_rdev_t *rdev = NULL;
mddev_t *mddev = bitmap->mddev;
- rcu_read_lock();
- rdev_for_each_rcu(rdev, mddev)
- if (test_bit(In_sync, &rdev->flags)
- && !test_bit(Faulty, &rdev->flags)) {
+ while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
int size = PAGE_SIZE;
if (page->index == bitmap->file_pages-1)
size = roundup(bitmap->last_page_size,
@@ -281,8 +313,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
+ page->index * (PAGE_SIZE/512),
size,
page);
- }
- rcu_read_unlock();
+ }
if (wait)
md_super_wait(mddev);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 13956437bc8..682ef9e6acd 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -333,7 +333,6 @@ static void crypt_convert_init(struct crypt_config *cc,
ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
ctx->sector = sector + cc->iv_offset;
init_completion(&ctx->restart);
- atomic_set(&ctx->pending, 1);
}
static int crypt_convert_block(struct crypt_config *cc,
@@ -408,6 +407,8 @@ static int crypt_convert(struct crypt_config *cc,
{
int r;
+ atomic_set(&ctx->pending, 1);
+
while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
ctx->idx_out < ctx->bio_out->bi_vcnt) {
@@ -456,9 +457,11 @@ static void dm_crypt_bio_destructor(struct bio *bio)
/*
* Generate a new unfragmented bio with the given size
* This should never violate the device limitations
- * May return a smaller bio when running out of pages
+ * May return a smaller bio when running out of pages, indicated by
+ * *out_of_pages set to 1.
*/
-static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
+ unsigned *out_of_pages)
{
struct crypt_config *cc = io->target->private;
struct bio *clone;
@@ -472,11 +475,14 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
return NULL;
clone_init(io, clone);
+ *out_of_pages = 0;
for (i = 0; i < nr_iovecs; i++) {
page = mempool_alloc(cc->page_pool, gfp_mask);
- if (!page)
+ if (!page) {
+ *out_of_pages = 1;
break;
+ }
/*
* if additional pages cannot be allocated without waiting,
@@ -517,6 +523,27 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
}
}
+static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti,
+ struct bio *bio, sector_t sector)
+{
+ struct crypt_config *cc = ti->private;
+ struct dm_crypt_io *io;
+
+ io = mempool_alloc(cc->io_pool, GFP_NOIO);
+ io->target = ti;
+ io->base_bio = bio;
+ io->sector = sector;
+ io->error = 0;
+ atomic_set(&io->pending, 0);
+
+ return io;
+}
+
+static void crypt_inc_pending(struct dm_crypt_io *io)
+{
+ atomic_inc(&io->pending);
+}
+
/*
* One of the bios was finished. Check for completion of
* the whole request and correctly clean up the buffer.
@@ -591,7 +618,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io)
struct bio *base_bio = io->base_bio;
struct bio *clone;
- atomic_inc(&io->pending);
+ crypt_inc_pending(io);
/*
* The block layer might modify the bvec array, so always
@@ -653,6 +680,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
io->error = -EIO;
+ crypt_dec_pending(io);
return;
}
@@ -664,28 +692,34 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
if (async)
kcryptd_queue_io(io);
- else {
- atomic_inc(&io->pending);
+ else
generic_make_request(clone);
- }
}
-static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io)
+static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->target->private;
struct bio *clone;
+ int crypt_finished;
+ unsigned out_of_pages = 0;
unsigned remaining = io->base_bio->bi_size;
int r;
/*
+ * Prevent io from disappearing until this function completes.
+ */
+ crypt_inc_pending(io);
+ crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector);
+
+ /*
* The allocated buffers can be smaller than the whole bio,
* so repeat the whole process until all the data can be handled.
*/
while (remaining) {
- clone = crypt_alloc_buffer(io, remaining);
+ clone = crypt_alloc_buffer(io, remaining, &out_of_pages);
if (unlikely(!clone)) {
io->error = -ENOMEM;
- return;
+ break;
}
io->ctx.bio_out = clone;
@@ -693,37 +727,32 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io)
remaining -= clone->bi_size;
+ crypt_inc_pending(io);
r = crypt_convert(cc, &io->ctx);
+ crypt_finished = atomic_dec_and_test(&io->ctx.pending);
- if (atomic_dec_and_test(&io->ctx.pending)) {
- /* processed, no running async crypto */
+ /* Encryption was already finished, submit io now */
+ if (crypt_finished) {
kcryptd_crypt_write_io_submit(io, r, 0);
- if (unlikely(r < 0))
- return;
- } else
- atomic_inc(&io->pending);
- /* out of memory -> run queues */
- if (unlikely(remaining)) {
- /* wait for async crypto then reinitialize pending */
- wait_event(cc->writeq, !atomic_read(&io->ctx.pending));
- atomic_set(&io->ctx.pending, 1);
- congestion_wait(WRITE, HZ/100);
+ /*
+ * If there was an error, do not try next fragments.
+ * For async, error is processed in async handler.
+ */
+ if (unlikely(r < 0))
+ break;
}
- }
-}
-static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
-{
- struct crypt_config *cc = io->target->private;
-
- /*
- * Prevent io from disappearing until this function completes.
- */
- atomic_inc(&io->pending);
+ /*
+ * Out of memory -> run queues
+ * But don't wait if split was due to the io size restriction
+ */
+ if (unlikely(out_of_pages))
+ congestion_wait(WRITE, HZ/100);
- crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector);
- kcryptd_crypt_write_convert_loop(io);
+ if (unlikely(remaining))
+ wait_event(cc->writeq, !atomic_read(&io->ctx.pending));
+ }
crypt_dec_pending(io);
}
@@ -741,7 +770,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
struct crypt_config *cc = io->target->private;
int r = 0;
- atomic_inc(&io->pending);
+ crypt_inc_pending(io);
crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio,
io->sector);
@@ -1108,15 +1137,9 @@ static void crypt_dtr(struct dm_target *ti)
static int crypt_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
- struct crypt_config *cc = ti->private;
struct dm_crypt_io *io;
- io = mempool_alloc(cc->io_pool, GFP_NOIO);
- io->target = ti;
- io->base_bio = bio;
- io->sector = bio->bi_sector - ti->begin;
- io->error = 0;
- atomic_set(&io->pending, 0);
+ io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin);
if (bio_data_dir(io->base_bio) == READ)
kcryptd_queue_io(io);
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 41f408068a7..769ab677f8e 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -108,12 +108,12 @@ struct pstore {
* Used to keep track of which metadata area the data in
* 'chunk' refers to.
*/
- uint32_t current_area;
+ chunk_t current_area;
/*
* The next free chunk for an exception.
*/
- uint32_t next_free;
+ chunk_t next_free;
/*
* The index of next free exception in the current
@@ -175,7 +175,7 @@ static void do_metadata(struct work_struct *work)
/*
* Read or write a chunk aligned and sized block of data from a device.
*/
-static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
+static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
{
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
@@ -209,16 +209,23 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
}
/*
+ * Convert a metadata area index to a chunk index.
+ */
+static chunk_t area_location(struct pstore *ps, chunk_t area)
+{
+ return 1 + ((ps->exceptions_per_area + 1) * area);
+}
+
+/*
* Read or write a metadata area. Remembering to skip the first
* chunk which holds the header.
*/
-static int area_io(struct pstore *ps, uint32_t area, int rw)
+static int area_io(struct pstore *ps, chunk_t area, int rw)
{
int r;
- uint32_t chunk;
+ chunk_t chunk;
- /* convert a metadata area index to a chunk index */
- chunk = 1 + ((ps->exceptions_per_area + 1) * area);
+ chunk = area_location(ps, area);
r = chunk_io(ps, chunk, rw, 0);
if (r)
@@ -228,7 +235,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw)
return 0;
}
-static int zero_area(struct pstore *ps, uint32_t area)
+static int zero_area(struct pstore *ps, chunk_t area)
{
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
return area_io(ps, area, WRITE);
@@ -404,7 +411,7 @@ static int insert_exceptions(struct pstore *ps, int *full)
static int read_exceptions(struct pstore *ps)
{
- uint32_t area;
+ chunk_t area;
int r, full = 1;
/*
@@ -517,6 +524,7 @@ static int persistent_prepare(struct exception_store *store,
{
struct pstore *ps = get_info(store);
uint32_t stride;
+ chunk_t next_free;
sector_t size = get_dev_size(store->snap->cow->bdev);
/* Is there enough room ? */
@@ -530,7 +538,8 @@ static int persistent_prepare(struct exception_store *store,
* into account the location of the metadata chunks.
*/
stride = (ps->exceptions_per_area + 1);
- if ((++ps->next_free % stride) == 1)
+ next_free = ++ps->next_free;
+ if (sector_div(next_free, stride) == 1)
ps->next_free++;
atomic_inc(&ps->pending_count);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index b262c0042de..dca401dc70a 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -426,7 +426,7 @@ static int list_devices(struct dm_ioctl *param, size_t param_size)
old_nl->next = (uint32_t) ((void *) nl -
(void *) old_nl);
disk = dm_disk(hc->md);
- nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
+ nl->dev = huge_encode_dev(disk_devt(disk));
nl->next = 0;
strcpy(nl->name, hc->name);
@@ -539,7 +539,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
if (dm_suspended(md))
param->flags |= DM_SUSPEND_FLAG;
- param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
+ param->dev = huge_encode_dev(disk_devt(disk));
/*
* Yes, this will be out of date by the time it gets back
@@ -548,7 +548,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
*/
param->open_count = dm_open_count(md);
- if (disk->policy)
+ if (get_disk_ro(disk))
param->flags |= DM_READONLY_FLAG;
param->event_nr = dm_get_event_nr(md);
@@ -1131,7 +1131,7 @@ static void retrieve_deps(struct dm_table *table,
unsigned int count = 0;
struct list_head *tmp;
size_t len, needed;
- struct dm_dev *dd;
+ struct dm_dev_internal *dd;
struct dm_target_deps *deps;
deps = get_result_buffer(param, param_size, &len);
@@ -1157,7 +1157,7 @@ static void retrieve_deps(struct dm_table *table,
deps->count = count;
count = 0;
list_for_each_entry (dd, dm_table_get_devices(table), list)
- deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev);
+ deps->dev[count++] = huge_encode_dev(dd->dm_dev.bdev->bd_dev);
param->data_size = param->data_start + needed;
}
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 71dd65aa31b..9bf3460c554 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -30,9 +30,11 @@ struct pgpath {
struct list_head list;
struct priority_group *pg; /* Owning PG */
+ unsigned is_active; /* Path status */
unsigned fail_count; /* Cumulative failure count */
struct dm_path path;
+ struct work_struct deactivate_path;
};
#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -63,6 +65,7 @@ struct multipath {
const char *hw_handler_name;
struct work_struct activate_path;
+ struct pgpath *pgpath_to_activate;
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
@@ -111,6 +114,7 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
static void process_queued_ios(struct work_struct *work);
static void trigger_event(struct work_struct *work);
static void activate_path(struct work_struct *work);
+static void deactivate_path(struct work_struct *work);
/*-----------------------------------------------
@@ -121,8 +125,10 @@ static struct pgpath *alloc_pgpath(void)
{
struct pgpath *pgpath = kzalloc(sizeof(*pgpath), GFP_KERNEL);
- if (pgpath)
- pgpath->path.is_active = 1;
+ if (pgpath) {
+ pgpath->is_active = 1;
+ INIT_WORK(&pgpath->deactivate_path, deactivate_path);
+ }
return pgpath;
}
@@ -132,6 +138,14 @@ static void free_pgpath(struct pgpath *pgpath)
kfree(pgpath);
}
+static void deactivate_path(struct work_struct *work)
+{
+ struct pgpath *pgpath =
+ container_of(work, struct pgpath, deactivate_path);
+
+ blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue);
+}
+
static struct priority_group *alloc_priority_group(void)
{
struct priority_group *pg;
@@ -146,6 +160,7 @@ static struct priority_group *alloc_priority_group(void)
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
{
+ unsigned long flags;
struct pgpath *pgpath, *tmp;
struct multipath *m = ti->private;
@@ -154,6 +169,10 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
if (m->hw_handler_name)
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
+ spin_lock_irqsave(&m->lock, flags);
+ if (m->pgpath_to_activate == pgpath)
+ m->pgpath_to_activate = NULL;
+ spin_unlock_irqrestore(&m->lock, flags);
free_pgpath(pgpath);
}
}
@@ -421,6 +440,7 @@ static void process_queued_ios(struct work_struct *work)
__choose_pgpath(m);
pgpath = m->current_pgpath;
+ m->pgpath_to_activate = m->current_pgpath;
if ((pgpath && !m->queue_io) ||
(!pgpath && !m->queue_if_no_path))
@@ -556,12 +576,12 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
/* we need at least a path arg */
if (as->argc < 1) {
ti->error = "no device given";
- return NULL;
+ return ERR_PTR(-EINVAL);
}
p = alloc_pgpath();
if (!p)
- return NULL;
+ return ERR_PTR(-ENOMEM);
r = dm_get_device(ti, shift(as), ti->begin, ti->len,
dm_table_get_mode(ti->table), &p->path.dev);
@@ -589,7 +609,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
bad:
free_pgpath(p);
- return NULL;
+ return ERR_PTR(r);
}
static struct priority_group *parse_priority_group(struct arg_set *as,
@@ -607,14 +627,14 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
if (as->argc < 2) {
as->argc = 0;
- ti->error = "not enough priority group aruments";
- return NULL;
+ ti->error = "not enough priority group arguments";
+ return ERR_PTR(-EINVAL);
}
pg = alloc_priority_group();
if (!pg) {
ti->error = "couldn't allocate priority group";
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
pg->m = m;
@@ -647,8 +667,10 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
path_args.argv = as->argv;
pgpath = parse_path(&path_args, &pg->ps, ti);
- if (!pgpath)
+ if (IS_ERR(pgpath)) {
+ r = PTR_ERR(pgpath);
goto bad;
+ }
pgpath->pg = pg;
list_add_tail(&pgpath->list, &pg->pgpaths);
@@ -659,7 +681,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
bad:
free_priority_group(pg, ti);
- return NULL;
+ return ERR_PTR(r);
}
static int parse_hw_handler(struct arg_set *as, struct multipath *m)
@@ -778,8 +800,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
struct priority_group *pg;
pg = parse_priority_group(&as, m);
- if (!pg) {
- r = -EINVAL;
+ if (IS_ERR(pg)) {
+ r = PTR_ERR(pg);
goto bad;
}
@@ -827,7 +849,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
dm_bio_record(&mpio->details, bio);
map_context->ptr = mpio;
- bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+ bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
r = map_io(m, bio, mpio, 0);
if (r < 0 || r == DM_MAPIO_REQUEUE)
mempool_free(mpio, m->mpio_pool);
@@ -845,13 +867,13 @@ static int fail_path(struct pgpath *pgpath)
spin_lock_irqsave(&m->lock, flags);
- if (!pgpath->path.is_active)
+ if (!pgpath->is_active)
goto out;
DMWARN("Failing path %s.", pgpath->path.dev->name);
pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);
- pgpath->path.is_active = 0;
+ pgpath->is_active = 0;
pgpath->fail_count++;
m->nr_valid_paths--;
@@ -863,6 +885,7 @@ static int fail_path(struct pgpath *pgpath)
pgpath->path.dev->name, m->nr_valid_paths);
queue_work(kmultipathd, &m->trigger_event);
+ queue_work(kmultipathd, &pgpath->deactivate_path);
out:
spin_unlock_irqrestore(&m->lock, flags);
@@ -881,7 +904,7 @@ static int reinstate_path(struct pgpath *pgpath)
spin_lock_irqsave(&m->lock, flags);
- if (pgpath->path.is_active)
+ if (pgpath->is_active)
goto out;
if (!pgpath->pg->ps.type->reinstate_path) {
@@ -895,7 +918,7 @@ static int reinstate_path(struct pgpath *pgpath)
if (r)
goto out;
- pgpath->path.is_active = 1;
+ pgpath->is_active = 1;
m->current_pgpath = NULL;
if (!m->nr_valid_paths++ && m->queue_size)
@@ -1093,8 +1116,15 @@ static void activate_path(struct work_struct *work)
int ret;
struct multipath *m =
container_of(work, struct multipath, activate_path);
- struct dm_path *path = &m->current_pgpath->path;
+ struct dm_path *path;
+ unsigned long flags;
+ spin_lock_irqsave(&m->lock, flags);
+ path = &m->pgpath_to_activate->path;
+ m->pgpath_to_activate = NULL;
+ spin_unlock_irqrestore(&m->lock, flags);
+ if (!path)
+ return;
ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
pg_init_done(path, ret);
}
@@ -1276,7 +1306,7 @@ static int multipath_status(struct dm_target *ti, status_type_t type,
list_for_each_entry(p, &pg->pgpaths, list) {
DMEMIT("%s %s %u ", p->path.dev->name,
- p->path.is_active ? "A" : "F",
+ p->is_active ? "A" : "F",
p->fail_count);
if (pg->ps.type->status)
sz += pg->ps.type->status(&pg->ps,
diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
index c198b856a45..e230f719625 100644
--- a/drivers/md/dm-mpath.h
+++ b/drivers/md/dm-mpath.h
@@ -13,8 +13,6 @@ struct dm_dev;
struct dm_path {
struct dm_dev *dev; /* Read-only */
- unsigned is_active; /* Read-only */
-
void *pscontext; /* For path-selector use */
};
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ff05fe89308..29913e42c4a 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -842,7 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
}
/* hand to kcopyd */
- set_bit(DM_KCOPYD_IGNORE_ERROR, &flags);
+ if (!errors_handled(ms))
+ set_bit(DM_KCOPYD_IGNORE_ERROR, &flags);
+
r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to,
flags, recovery_complete, reg);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 4de90ab3968..b745d8ac625 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -284,8 +284,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio,
memset(major_minor, 0, sizeof(major_minor));
sprintf(major_minor, "%d:%d",
- bio->bi_bdev->bd_disk->major,
- bio->bi_bdev->bd_disk->first_minor);
+ MAJOR(disk_devt(bio->bi_bdev->bd_disk)),
+ MINOR(disk_devt(bio->bi_bdev->bd_disk)));
/*
* Test to see which stripe drive triggered the event
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 61f44140923..a740a6950f5 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -250,7 +250,8 @@ static void free_devices(struct list_head *devices)
struct list_head *tmp, *next;
list_for_each_safe(tmp, next, devices) {
- struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
+ struct dm_dev_internal *dd =
+ list_entry(tmp, struct dm_dev_internal, list);
kfree(dd);
}
}
@@ -327,12 +328,12 @@ static int lookup_device(const char *path, dev_t *dev)
/*
* See if we've already got a device in the list.
*/
-static struct dm_dev *find_device(struct list_head *l, dev_t dev)
+static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev)
{
- struct dm_dev *dd;
+ struct dm_dev_internal *dd;
list_for_each_entry (dd, l, list)
- if (dd->bdev->bd_dev == dev)
+ if (dd->dm_dev.bdev->bd_dev == dev)
return dd;
return NULL;
@@ -341,45 +342,47 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev)
/*
* Open a device so we can use it as a map destination.
*/
-static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md)
+static int open_dev(struct dm_dev_internal *d, dev_t dev,
+ struct mapped_device *md)
{
static char *_claim_ptr = "I belong to device-mapper";
struct block_device *bdev;
int r;
- BUG_ON(d->bdev);
+ BUG_ON(d->dm_dev.bdev);
- bdev = open_by_devnum(dev, d->mode);
+ bdev = open_by_devnum(dev, d->dm_dev.mode);
if (IS_ERR(bdev))
return PTR_ERR(bdev);
r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
if (r)
blkdev_put(bdev);
else
- d->bdev = bdev;
+ d->dm_dev.bdev = bdev;
return r;
}
/*
* Close a device that we've been using.
*/
-static void close_dev(struct dm_dev *d, struct mapped_device *md)
+static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
{
- if (!d->bdev)
+ if (!d->dm_dev.bdev)
return;
- bd_release_from_disk(d->bdev, dm_disk(md));
- blkdev_put(d->bdev);
- d->bdev = NULL;
+ bd_release_from_disk(d->dm_dev.bdev, dm_disk(md));
+ blkdev_put(d->dm_dev.bdev);
+ d->dm_dev.bdev = NULL;
}
/*
* If possible, this checks an area of a destination device is valid.
*/
-static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len)
+static int check_device_area(struct dm_dev_internal *dd, sector_t start,
+ sector_t len)
{
- sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT;
+ sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT;
if (!dev_size)
return 1;
@@ -392,16 +395,17 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len)
* careful to leave things as they were if we fail to reopen the
* device.
*/
-static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md)
+static int upgrade_mode(struct dm_dev_internal *dd, int new_mode,
+ struct mapped_device *md)
{
int r;
- struct dm_dev dd_copy;
- dev_t dev = dd->bdev->bd_dev;
+ struct dm_dev_internal dd_copy;
+ dev_t dev = dd->dm_dev.bdev->bd_dev;
dd_copy = *dd;
- dd->mode |= new_mode;
- dd->bdev = NULL;
+ dd->dm_dev.mode |= new_mode;
+ dd->dm_dev.bdev = NULL;
r = open_dev(dd, dev, md);
if (!r)
close_dev(&dd_copy, md);
@@ -421,7 +425,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
{
int r;
dev_t uninitialized_var(dev);
- struct dm_dev *dd;
+ struct dm_dev_internal *dd;
unsigned int major, minor;
BUG_ON(!t);
@@ -443,20 +447,20 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
if (!dd)
return -ENOMEM;
- dd->mode = mode;
- dd->bdev = NULL;
+ dd->dm_dev.mode = mode;
+ dd->dm_dev.bdev = NULL;
if ((r = open_dev(dd, dev, t->md))) {
kfree(dd);
return r;
}
- format_dev_t(dd->name, dev);
+ format_dev_t(dd->dm_dev.name, dev);
atomic_set(&dd->count, 0);
list_add(&dd->list, &t->devices);
- } else if (dd->mode != (mode | dd->mode)) {
+ } else if (dd->dm_dev.mode != (mode | dd->dm_dev.mode)) {
r = upgrade_mode(dd, mode, t->md);
if (r)
return r;
@@ -465,11 +469,11 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
if (!check_device_area(dd, start, len)) {
DMWARN("device %s too small for target", path);
- dm_put_device(ti, dd);
+ dm_put_device(ti, &dd->dm_dev);
return -EINVAL;
}
- *result = dd;
+ *result = &dd->dm_dev;
return 0;
}
@@ -478,6 +482,13 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
struct io_restrictions *rs = &ti->limits;
+ char b[BDEVNAME_SIZE];
+
+ if (unlikely(!q)) {
+ DMWARN("%s: Cannot set limits for nonexistent device %s",
+ dm_device_name(ti->table->md), bdevname(bdev, b));
+ return;
+ }
/*
* Combine the device limits low.
@@ -540,8 +551,11 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
/*
* Decrement a devices use count and remove it if necessary.
*/
-void dm_put_device(struct dm_target *ti, struct dm_dev *dd)
+void dm_put_device(struct dm_target *ti, struct dm_dev *d)
{
+ struct dm_dev_internal *dd = container_of(d, struct dm_dev_internal,
+ dm_dev);
+
if (atomic_dec_and_test(&dd->count)) {
close_dev(dd, ti->table->md);
list_del(&dd->list);
@@ -937,13 +951,20 @@ int dm_table_resume_targets(struct dm_table *t)
int dm_table_any_congested(struct dm_table *t, int bdi_bits)
{
- struct dm_dev *dd;
+ struct dm_dev_internal *dd;
struct list_head *devices = dm_table_get_devices(t);
int r = 0;
list_for_each_entry(dd, devices, list) {
- struct request_queue *q = bdev_get_queue(dd->bdev);
- r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+ struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
+ char b[BDEVNAME_SIZE];
+
+ if (likely(q))
+ r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+ else
+ DMWARN_LIMIT("%s: any_congested: nonexistent device %s",
+ dm_device_name(t->md),
+ bdevname(dd->dm_dev.bdev, b));
}
return r;
@@ -951,13 +972,19 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits)
void dm_table_unplug_all(struct dm_table *t)
{
- struct dm_dev *dd;
+ struct dm_dev_internal *dd;
struct list_head *devices = dm_table_get_devices(t);
list_for_each_entry(dd, devices, list) {
- struct request_queue *q = bdev_get_queue(dd->bdev);
-
- blk_unplug(q);
+ struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
+ char b[BDEVNAME_SIZE];
+
+ if (likely(q))
+ blk_unplug(q);
+ else
+ DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s",
+ dm_device_name(t->md),
+ bdevname(dd->dm_dev.bdev, b));
}
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index bca448e1187..327de03a5bd 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -377,13 +377,14 @@ static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
static void start_io_acct(struct dm_io *io)
{
struct mapped_device *md = io->md;
+ int cpu;
io->start_time = jiffies;
- preempt_disable();
- disk_round_stats(dm_disk(md));
- preempt_enable();
- dm_disk(md)->in_flight = atomic_inc_return(&md->pending);
+ cpu = part_stat_lock();
+ part_round_stats(cpu, &dm_disk(md)->part0);
+ part_stat_unlock();
+ dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending);
}
static int end_io_acct(struct dm_io *io)
@@ -391,15 +392,16 @@ static int end_io_acct(struct dm_io *io)
struct mapped_device *md = io->md;
struct bio *bio = io->bio;
unsigned long duration = jiffies - io->start_time;
- int pending;
+ int pending, cpu;
int rw = bio_data_dir(bio);
- preempt_disable();
- disk_round_stats(dm_disk(md));
- preempt_enable();
- dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending);
+ cpu = part_stat_lock();
+ part_round_stats(cpu, &dm_disk(md)->part0);
+ part_stat_add(cpu, &dm_disk(md)->part0, ticks[rw], duration);
+ part_stat_unlock();
- disk_stat_add(dm_disk(md), ticks[rw], duration);
+ dm_disk(md)->part0.in_flight = pending =
+ atomic_dec_return(&md->pending);
return !pending;
}
@@ -837,12 +839,14 @@ static int dm_merge_bvec(struct request_queue *q,
struct dm_table *map = dm_get_table(md);
struct dm_target *ti;
sector_t max_sectors;
- int max_size;
+ int max_size = 0;
if (unlikely(!map))
- return 0;
+ goto out;
ti = dm_table_find_target(map, bvm->bi_sector);
+ if (!dm_target_is_valid(ti))
+ goto out_table;
/*
* Find maximum amount of I/O that won't need splitting
@@ -861,14 +865,16 @@ static int dm_merge_bvec(struct request_queue *q,
if (max_size && ti->type->merge)
max_size = ti->type->merge(ti, bvm, biovec, max_size);
+out_table:
+ dm_table_put(map);
+
+out:
/*
* Always allow an entire first page
*/
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
max_size = biovec->bv_len;
- dm_table_put(map);
-
return max_size;
}
@@ -881,6 +887,7 @@ static int dm_request(struct request_queue *q, struct bio *bio)
int r = -EIO;
int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
+ int cpu;
/*
* There is no use in forwarding any barrier request since we can't
@@ -893,8 +900,10 @@ static int dm_request(struct request_queue *q, struct bio *bio)
down_read(&md->io_lock);
- disk_stat_inc(dm_disk(md), ios[rw]);
- disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &dm_disk(md)->part0, ios[rw]);
+ part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio));
+ part_stat_unlock();
/*
* If we're suspended we have to queue
@@ -1142,7 +1151,7 @@ static void unlock_fs(struct mapped_device *md);
static void free_dev(struct mapped_device *md)
{
- int minor = md->disk->first_minor;
+ int minor = MINOR(disk_devt(md->disk));
if (md->suspended_bdev) {
unlock_fs(md);
@@ -1178,7 +1187,7 @@ static void event_callback(void *context)
list_splice_init(&md->uevent_list, &uevents);
spin_unlock_irqrestore(&md->uevent_lock, flags);
- dm_send_uevents(&uevents, &md->disk->dev.kobj);
+ dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj);
atomic_inc(&md->event_nr);
wake_up(&md->eventq);
@@ -1263,7 +1272,7 @@ static struct mapped_device *dm_find_md(dev_t dev)
md = idr_find(&_minor_idr, minor);
if (md && (md == MINOR_ALLOCED ||
- (dm_disk(md)->first_minor != minor) ||
+ (MINOR(disk_devt(dm_disk(md))) != minor) ||
test_bit(DMF_FREEING, &md->flags))) {
md = NULL;
goto out;
@@ -1314,7 +1323,8 @@ void dm_put(struct mapped_device *md)
if (atomic_dec_and_lock(&md->holders, &_minor_lock)) {
map = dm_get_table(md);
- idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor);
+ idr_replace(&_minor_idr, MINOR_ALLOCED,
+ MINOR(disk_devt(dm_disk(md))));
set_bit(DMF_FREEING, &md->flags);
spin_unlock(&_minor_lock);
if (!dm_suspended(md)) {
@@ -1634,7 +1644,7 @@ out:
*---------------------------------------------------------------*/
void dm_kobject_uevent(struct mapped_device *md)
{
- kobject_uevent(&md->disk->dev.kobj, KOBJ_CHANGE);
+ kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE);
}
uint32_t dm_next_uevent_seq(struct mapped_device *md)
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 1e59a0b0a78..cd189da2b2f 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -25,13 +25,10 @@
/*
* List of devices that a metadevice uses and should open/close.
*/
-struct dm_dev {
+struct dm_dev_internal {
struct list_head list;
-
atomic_t count;
- int mode;
- struct block_device *bdev;
- char name[16];
+ struct dm_dev dm_dev;
};
struct dm_table;
@@ -49,7 +46,6 @@ void dm_table_presuspend_targets(struct dm_table *t);
void dm_table_postsuspend_targets(struct dm_table *t);
int dm_table_resume_targets(struct dm_table *t);
int dm_table_any_congested(struct dm_table *t, int bdi_bits);
-void dm_table_unplug_all(struct dm_table *t);
/*
* To check the return value from dm_table_find_target().
@@ -93,8 +89,6 @@ void dm_linear_exit(void);
int dm_stripe_init(void);
void dm_stripe_exit(void);
-void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
-union map_info *dm_get_mapinfo(struct bio *bio);
int dm_open_count(struct mapped_device *md);
int dm_lock_for_deletion(struct mapped_device *md);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 268547dbfbd..f26c1f9a475 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -287,6 +287,8 @@ static int run(mddev_t *mddev)
int i;
conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
+ if (!conf)
+ return -ENOMEM;
for (i=0; i<Modes; i++) {
atomic_set(&conf->counters[i], 0);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b1eebf88c20..190147c79e7 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -16,16 +16,8 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
-
-#include <linux/raid/md.h>
-#include <linux/slab.h>
#include <linux/raid/linear.h>
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
/*
* find which device holds a particular offset
*/
@@ -33,16 +25,15 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
{
dev_info_t *hash;
linear_conf_t *conf = mddev_to_conf(mddev);
- sector_t block = sector >> 1;
/*
* sector_div(a,b) returns the remainer and sets a to a/b
*/
- block >>= conf->preshift;
- (void)sector_div(block, conf->hash_spacing);
- hash = conf->hash_table[block];
+ sector >>= conf->sector_shift;
+ (void)sector_div(sector, conf->spacing);
+ hash = conf->hash_table[sector];
- while ((sector>>1) >= (hash->size + hash->offset))
+ while (sector >= hash->num_sectors + hash->start_sector)
hash++;
return hash;
}
@@ -65,7 +56,7 @@ static int linear_mergeable_bvec(struct request_queue *q,
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
dev0 = which_dev(mddev, sector);
- maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1));
+ maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
if (maxsectors < bio_sectors)
maxsectors = 0;
@@ -112,8 +103,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
dev_info_t **table;
mdk_rdev_t *rdev;
int i, nb_zone, cnt;
- sector_t min_spacing;
- sector_t curr_offset;
+ sector_t min_sectors;
+ sector_t curr_sector;
struct list_head *tmp;
conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
@@ -145,7 +136,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
mddev->queue->max_sectors > (PAGE_SIZE>>9))
blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
- disk->size = rdev->size;
+ disk->num_sectors = rdev->size * 2;
conf->array_sectors += rdev->size * 2;
cnt++;
@@ -155,34 +146,34 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
goto out;
}
- min_spacing = conf->array_sectors / 2;
- sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+ min_sectors = conf->array_sectors;
+ sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
- /* min_spacing is the minimum spacing that will fit the hash
+ /* min_sectors is the minimum spacing that will fit the hash
* table in one PAGE. This may be much smaller than needed.
* We find the smallest non-terminal set of consecutive devices
- * that is larger than min_spacing as use the size of that as
+ * that is larger than min_sectors and use the size of that as
* the actual spacing
*/
- conf->hash_spacing = conf->array_sectors / 2;
+ conf->spacing = conf->array_sectors;
for (i=0; i < cnt-1 ; i++) {
- sector_t sz = 0;
+ sector_t tmp = 0;
int j;
- for (j = i; j < cnt - 1 && sz < min_spacing; j++)
- sz += conf->disks[j].size;
- if (sz >= min_spacing && sz < conf->hash_spacing)
- conf->hash_spacing = sz;
+ for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
+ tmp += conf->disks[j].num_sectors;
+ if (tmp >= min_sectors && tmp < conf->spacing)
+ conf->spacing = tmp;
}
- /* hash_spacing may be too large for sector_div to work with,
+ /* spacing may be too large for sector_div to work with,
* so we might need to pre-shift
*/
- conf->preshift = 0;
+ conf->sector_shift = 0;
if (sizeof(sector_t) > sizeof(u32)) {
- sector_t space = conf->hash_spacing;
+ sector_t space = conf->spacing;
while (space > (sector_t)(~(u32)0)) {
space >>= 1;
- conf->preshift++;
+ conf->sector_shift++;
}
}
/*
@@ -194,9 +185,9 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
unsigned round;
unsigned long base;
- sz = conf->array_sectors >> (conf->preshift + 1);
+ sz = conf->array_sectors >> conf->sector_shift;
sz += 1; /* force round-up */
- base = conf->hash_spacing >> conf->preshift;
+ base = conf->spacing >> conf->sector_shift;
round = sector_div(sz, base);
nb_zone = sz + (round ? 1 : 0);
}
@@ -211,32 +202,31 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
* Here we generate the linear hash table
* First calculate the device offsets.
*/
- conf->disks[0].offset = 0;
+ conf->disks[0].start_sector = 0;
for (i = 1; i < raid_disks; i++)
- conf->disks[i].offset =
- conf->disks[i-1].offset +
- conf->disks[i-1].size;
+ conf->disks[i].start_sector =
+ conf->disks[i-1].start_sector +
+ conf->disks[i-1].num_sectors;
table = conf->hash_table;
- curr_offset = 0;
i = 0;
- for (curr_offset = 0;
- curr_offset < conf->array_sectors / 2;
- curr_offset += conf->hash_spacing) {
+ for (curr_sector = 0;
+ curr_sector < conf->array_sectors;
+ curr_sector += conf->spacing) {
while (i < raid_disks-1 &&
- curr_offset >= conf->disks[i+1].offset)
+ curr_sector >= conf->disks[i+1].start_sector)
i++;
*table ++ = conf->disks + i;
}
- if (conf->preshift) {
- conf->hash_spacing >>= conf->preshift;
- /* round hash_spacing up so that when we divide by it,
+ if (conf->sector_shift) {
+ conf->spacing >>= conf->sector_shift;
+ /* round spacing up so that when we divide by it,
* we err on the side of "too-low", which is safest.
*/
- conf->hash_spacing++;
+ conf->spacing++;
}
BUG_ON(table - conf->hash_table > nb_zone);
@@ -317,40 +307,47 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
const int rw = bio_data_dir(bio);
mddev_t *mddev = q->queuedata;
dev_info_t *tmp_dev;
- sector_t block;
+ int cpu;
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, -EOPNOTSUPP);
return 0;
}
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bio));
+ part_stat_unlock();
tmp_dev = which_dev(mddev, bio->bi_sector);
- block = bio->bi_sector >> 1;
- if (unlikely(block >= (tmp_dev->size + tmp_dev->offset)
- || block < tmp_dev->offset)) {
+ if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
+ tmp_dev->start_sector)
+ || (bio->bi_sector <
+ tmp_dev->start_sector))) {
char b[BDEVNAME_SIZE];
- printk("linear_make_request: Block %llu out of bounds on "
- "dev %s size %llu offset %llu\n",
- (unsigned long long)block,
+ printk("linear_make_request: Sector %llu out of bounds on "
+ "dev %s: %llu sectors, offset %llu\n",
+ (unsigned long long)bio->bi_sector,
bdevname(tmp_dev->rdev->bdev, b),
- (unsigned long long)tmp_dev->size,
- (unsigned long long)tmp_dev->offset);
+ (unsigned long long)tmp_dev->num_sectors,
+ (unsigned long long)tmp_dev->start_sector);
bio_io_error(bio);
return 0;
}
if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
- (tmp_dev->offset + tmp_dev->size)<<1)) {
+ tmp_dev->start_sector + tmp_dev->num_sectors)) {
/* This bio crosses a device boundary, so we have to
* split it.
*/
struct bio_pair *bp;
- bp = bio_split(bio, bio_split_pool,
- ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector);
+
+ bp = bio_split(bio,
+ tmp_dev->start_sector + tmp_dev->num_sectors
+ - bio->bi_sector);
+
if (linear_make_request(q, &bp->bio1))
generic_make_request(&bp->bio1);
if (linear_make_request(q, &bp->bio2))
@@ -360,7 +357,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
}
bio->bi_bdev = tmp_dev->rdev->bdev;
- bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset;
+ bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
+ + tmp_dev->rdev->data_offset;
return 1;
}
@@ -368,29 +366,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
static void linear_status (struct seq_file *seq, mddev_t *mddev)
{
-#undef MD_DEBUG
-#ifdef MD_DEBUG
- int j;
- linear_conf_t *conf = mddev_to_conf(mddev);
- sector_t s = 0;
-
- seq_printf(seq, " ");
- for (j = 0; j < mddev->raid_disks; j++)
- {
- char b[BDEVNAME_SIZE];
- s += conf->smallest_size;
- seq_printf(seq, "[%s",
- bdevname(conf->hash_table[j][0].rdev->bdev,b));
-
- while (s > conf->hash_table[j][0].offset +
- conf->hash_table[j][0].size)
- seq_printf(seq, "/%s] ",
- bdevname(conf->hash_table[j][1].rdev->bdev,b));
- else
- seq_printf(seq, "] ");
- }
- seq_printf(seq, "\n");
-#endif
seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8cfadc5bd2b..aaa3d465de4 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -32,31 +32,21 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
#include <linux/kthread.h>
-#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/raid/bitmap.h>
#include <linux/sysctl.h>
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/poll.h>
-#include <linux/mutex.h>
#include <linux/ctype.h>
-#include <linux/freezer.h>
-
-#include <linux/init.h>
-
+#include <linux/hdreg.h>
+#include <linux/proc_fs.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
#include <linux/file.h>
-
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/unaligned.h>
+#include <linux/delay.h>
#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
/* 63 partitions with the alternate major number (mdp) */
#define MdpMinorShift 6
@@ -66,7 +56,7 @@
#ifndef MODULE
-static void autostart_arrays (int part);
+static void autostart_arrays(int part);
#endif
static LIST_HEAD(pers_list);
@@ -212,7 +202,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
)
-static int md_fail_request (struct request_queue *q, struct bio *bio)
+static int md_fail_request(struct request_queue *q, struct bio *bio)
{
bio_io_error(bio);
return 0;
@@ -1464,10 +1454,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b)))
goto fail;
- if (rdev->bdev->bd_part)
- ko = &rdev->bdev->bd_part->dev.kobj;
- else
- ko = &rdev->bdev->bd_disk->dev.kobj;
+ ko = &part_to_dev(rdev->bdev->bd_part)->kobj;
if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) {
kobject_del(&rdev->kobj);
goto fail;
@@ -2109,8 +2096,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
if (strict_strtoull(buf, 10, &size) < 0)
return -EINVAL;
- if (size < my_mddev->size)
- return -EINVAL;
if (my_mddev->pers && rdev->raid_disk >= 0) {
if (my_mddev->persistent) {
size = super_types[my_mddev->major_version].
@@ -2121,9 +2106,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
size = (rdev->bdev->bd_inode->i_size >> 10);
size -= rdev->data_offset/2;
}
- if (size < my_mddev->size)
- return -EINVAL; /* component must fit device */
}
+ if (size < my_mddev->size)
+ return -EINVAL; /* component must fit device */
rdev->size = size;
if (size > oldsize && my_mddev->external) {
@@ -2409,12 +2394,11 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
int i;
unsigned long msec;
char buf[30];
- char *e;
+
/* remove a period, and count digits after it */
if (len >= sizeof(buf))
return -EINVAL;
- strlcpy(buf, cbuf, len);
- buf[len] = 0;
+ strlcpy(buf, cbuf, sizeof(buf));
for (i=0; i<len; i++) {
if (dot) {
if (isdigit(buf[i])) {
@@ -2427,8 +2411,7 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
buf[i] = 0;
}
}
- msec = simple_strtoul(buf, &e, 10);
- if (e == buf || (*e && *e != '\n'))
+ if (strict_strtoul(buf, 10, &msec) < 0)
return -EINVAL;
msec = (msec * 1000) / scale;
if (msec == 0)
@@ -2730,9 +2713,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break;
case read_auto:
if (mddev->pers) {
- if (mddev->ro != 1)
+ if (mddev->ro == 0)
err = do_md_stop(mddev, 1, 0);
- else
+ else if (mddev->ro == 1)
err = restart_array(mddev);
if (err == 0) {
mddev->ro = 2;
@@ -2948,7 +2931,13 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
{
int major, minor;
char *e;
- if (!list_empty(&mddev->disks))
+ /* Changing the details of 'external' metadata is
+ * always permitted. Otherwise there must be
+ * no devices attached to the array.
+ */
+ if (mddev->external && strncmp(buf, "external:", 9) == 0)
+ ;
+ else if (!list_empty(&mddev->disks))
return -EBUSY;
if (cmd_match(buf, "none")) {
@@ -3470,8 +3459,8 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
disk->queue = mddev->queue;
add_disk(disk);
mddev->gendisk = disk;
- error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj,
- "%s", "md");
+ error = kobject_init_and_add(&mddev->kobj, &md_ktype,
+ &disk_to_dev(disk)->kobj, "%s", "md");
mutex_unlock(&disks_mutex);
if (error)
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
@@ -3530,17 +3519,12 @@ static int do_md_run(mddev_t * mddev)
return -EINVAL;
}
/*
- * chunk-size has to be a power of 2 and multiples of PAGE_SIZE
+ * chunk-size has to be a power of 2
*/
if ( (1 << ffz(~chunk_size)) != chunk_size) {
printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
return -EINVAL;
}
- if (chunk_size < PAGE_SIZE) {
- printk(KERN_ERR "too small chunk_size: %d < %ld\n",
- chunk_size, PAGE_SIZE);
- return -EINVAL;
- }
/* devices must have minimum size of one chunk */
rdev_for_each(rdev, tmp, mddev) {
@@ -3558,12 +3542,10 @@ static int do_md_run(mddev_t * mddev)
}
}
-#ifdef CONFIG_KMOD
if (mddev->level != LEVEL_NONE)
request_module("md-level-%d", mddev->level);
else if (mddev->clevel[0])
request_module("md-%s", mddev->clevel);
-#endif
/*
* Drop all container device buffers, from now on
@@ -3761,7 +3743,7 @@ static int do_md_run(mddev_t * mddev)
sysfs_notify(&mddev->kobj, NULL, "array_state");
sysfs_notify(&mddev->kobj, NULL, "sync_action");
sysfs_notify(&mddev->kobj, NULL, "degraded");
- kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
+ kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
return 0;
}
@@ -3841,8 +3823,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
del_timer_sync(&mddev->safemode_timer);
- invalidate_partition(disk, 0);
-
switch(mode) {
case 1: /* readonly */
err = -ENXIO;
@@ -3976,10 +3956,10 @@ static void autorun_array(mddev_t *mddev)
}
printk("\n");
- err = do_md_run (mddev);
+ err = do_md_run(mddev);
if (err) {
printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
- do_md_stop (mddev, 0, 0);
+ do_md_stop(mddev, 0, 0);
}
}
@@ -4338,7 +4318,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (!(info->state & (1<<MD_DISK_FAULTY))) {
int err;
- rdev = md_import_device (dev, -1, 0);
+ rdev = md_import_device(dev, -1, 0);
if (IS_ERR(rdev)) {
printk(KERN_WARNING
"md: error, md_import_device() returned %ld\n",
@@ -4420,7 +4400,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
return -EINVAL;
}
- rdev = md_import_device (dev, -1, 0);
+ rdev = md_import_device(dev, -1, 0);
if (IS_ERR(rdev)) {
printk(KERN_WARNING
"md: error, md_import_device() returned %ld\n",
@@ -4939,11 +4919,11 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case STOP_ARRAY:
- err = do_md_stop (mddev, 0, 1);
+ err = do_md_stop(mddev, 0, 1);
goto done_unlock;
case STOP_ARRAY_RO:
- err = do_md_stop (mddev, 1, 1);
+ err = do_md_stop(mddev, 1, 1);
goto done_unlock;
}
@@ -4992,7 +4972,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case RUN_ARRAY:
- err = do_md_run (mddev);
+ err = do_md_run(mddev);
goto done_unlock;
case SET_BITMAP_FILE:
@@ -5430,11 +5410,11 @@ static int md_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, " super non-persistent");
if (mddev->pers) {
- mddev->pers->status (seq, mddev);
+ mddev->pers->status(seq, mddev);
seq_printf(seq, "\n ");
if (mddev->pers->sync_request) {
if (mddev->curr_resync > 2) {
- status_resync (seq, mddev);
+ status_resync(seq, mddev);
seq_printf(seq, "\n ");
} else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
seq_printf(seq, "\tresync=DELAYED\n ");
@@ -5551,8 +5531,8 @@ static int is_mddev_idle(mddev_t *mddev)
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev) {
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
- curr_events = disk_stat_read(disk, sectors[0]) +
- disk_stat_read(disk, sectors[1]) -
+ curr_events = part_stat_read(&disk->part0, sectors[0]) +
+ part_stat_read(&disk->part0, sectors[1]) -
atomic_read(&disk->sync_io);
/* sync IO will cause sync_io to increase before the disk_stats
* as sync_io is counted when a request starts, and
@@ -5763,7 +5743,11 @@ void md_do_sync(mddev_t *mddev)
* time 'round when curr_resync == 2
*/
continue;
- prepare_to_wait(&resync_wait, &wq, TASK_UNINTERRUPTIBLE);
+ /* We need to wait 'interruptible' so as not to
+ * contribute to the load average, and not to
+ * be caught by 'softlockup'
+ */
+ prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE);
if (!kthread_should_stop() &&
mddev2->curr_resync >= mddev->curr_resync) {
printk(KERN_INFO "md: delaying %s of %s"
@@ -5771,6 +5755,8 @@ void md_do_sync(mddev_t *mddev)
" share one or more physical units)\n",
desc, mdname(mddev), mdname(mddev2));
mddev_put(mddev2);
+ if (signal_pending(current))
+ flush_signals(current);
schedule();
finish_wait(&resync_wait, &wq);
goto try_again;
@@ -6259,7 +6245,7 @@ static int md_notify_reboot(struct notifier_block *this,
* appears to still be in use. Hence
* the '100'.
*/
- do_md_stop (mddev, 1, 100);
+ do_md_stop(mddev, 1, 100);
mddev_unlock(mddev);
}
/*
@@ -6303,7 +6289,7 @@ static int __init md_init(void)
raid_table_header = register_sysctl_table(raid_root_table);
md_geninit();
- return (0);
+ return 0;
}
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index c4779ccba1c..d4ac47d1127 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -19,16 +19,7 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
#include <linux/raid/multipath.h>
-#include <linux/buffer_head.h>
-#include <asm/atomic.h>
-
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
#define MAX_WORK_PER_DISK 128
@@ -147,6 +138,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
const int rw = bio_data_dir(bio);
+ int cpu;
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, -EOPNOTSUPP);
@@ -158,8 +150,11 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
mp_bh->master_bio = bio;
mp_bh->mddev = mddev;
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bio));
+ part_stat_unlock();
mp_bh->path = multipath_map(conf);
if (mp_bh->path < 0) {
@@ -172,7 +167,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
mp_bh->bio = *bio;
mp_bh->bio.bi_sector += multipath->rdev->data_offset;
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
- mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST);
+ mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
mp_bh->bio.bi_end_io = multipath_end_request;
mp_bh->bio.bi_private = mp_bh;
generic_make_request(&mp_bh->bio);
@@ -398,7 +393,7 @@ static void multipathd (mddev_t *mddev)
*bio = *(mp_bh->master_bio);
bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
- bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+ bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
bio->bi_end_io = multipath_end_request;
bio->bi_private = mp_bh;
generic_make_request(bio);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 18361063566..8ac6488ad0d 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -18,13 +18,8 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
#include <linux/raid/raid0.h>
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
static void raid0_unplug(struct request_queue *q)
{
mddev_t *mddev = q->queuedata;
@@ -399,14 +394,18 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
sector_t chunk;
sector_t block, rsect;
const int rw = bio_data_dir(bio);
+ int cpu;
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, -EOPNOTSUPP);
return 0;
}
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bio));
+ part_stat_unlock();
chunk_size = mddev->chunk_size >> 10;
chunk_sects = mddev->chunk_size >> 9;
@@ -423,7 +422,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
/* This is a one page bio that upper layers
* refuse to split for us, so we need to split it.
*/
- bp = bio_split(bio, bio_split_pool, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
+ bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1)));
if (raid0_make_request(q, &bp->bio1))
generic_make_request(&bp->bio1);
if (raid0_make_request(q, &bp->bio2))
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 03a5ab705c2..9c788e2489b 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -32,6 +32,7 @@
*/
#include "dm-bio-list.h"
+#include <linux/delay.h>
#include <linux/raid/raid1.h>
#include <linux/raid/bitmap.h>
@@ -779,7 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
struct page **behind_pages = NULL;
const int rw = bio_data_dir(bio);
const int do_sync = bio_sync(bio);
- int do_barriers;
+ int cpu, do_barriers;
mdk_rdev_t *blocked_rdev;
/*
@@ -804,8 +805,11 @@ static int make_request(struct request_queue *q, struct bio * bio)
bitmap = mddev->bitmap;
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bio));
+ part_stat_unlock();
/*
* make_request() can abort the operation when READA is being
@@ -1302,9 +1306,6 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
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;
@@ -1790,7 +1791,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
bio->bi_vcnt = 0;
bio->bi_idx = 0;
bio->bi_phys_segments = 0;
- bio->bi_hw_segments = 0;
bio->bi_size = 0;
bio->bi_end_io = NULL;
bio->bi_private = NULL;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e34cd0e6247..da5129a24b1 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -19,6 +19,7 @@
*/
#include "dm-bio-list.h"
+#include <linux/delay.h>
#include <linux/raid/raid10.h>
#include <linux/raid/bitmap.h>
@@ -789,6 +790,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
mirror_info_t *mirror;
r10bio_t *r10_bio;
struct bio *read_bio;
+ int cpu;
int i;
int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio);
@@ -816,7 +818,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
/* This is a one page bio that upper layers
* refuse to split for us, so we need to split it.
*/
- bp = bio_split(bio, bio_split_pool,
+ bp = bio_split(bio,
chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
if (make_request(q, &bp->bio1))
generic_make_request(&bp->bio1);
@@ -843,8 +845,11 @@ static int make_request(struct request_queue *q, struct bio * bio)
*/
wait_barrier(conf);
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bio));
+ part_stat_unlock();
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
@@ -1345,9 +1350,6 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
tbio->bi_size = r10_bio->sectors << 9;
tbio->bi_idx = 0;
tbio->bi_phys_segments = 0;
- tbio->bi_hw_segments = 0;
- tbio->bi_hw_front_size = 0;
- tbio->bi_hw_back_size = 0;
tbio->bi_flags &= ~(BIO_POOL_MASK - 1);
tbio->bi_flags |= 1 << BIO_UPTODATE;
tbio->bi_next = NULL;
@@ -1947,7 +1949,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
bio->bi_vcnt = 0;
bio->bi_idx = 0;
bio->bi_phys_segments = 0;
- bio->bi_hw_segments = 0;
bio->bi_size = 0;
}
@@ -2028,8 +2029,9 @@ static int run(mddev_t *mddev)
int nc, fc, fo;
sector_t stride, size;
- if (mddev->chunk_size == 0) {
- printk(KERN_ERR "md/raid10: non-zero chunk size required.\n");
+ if (mddev->chunk_size < PAGE_SIZE) {
+ printk(KERN_ERR "md/raid10: chunk size must be "
+ "at least PAGE_SIZE(%ld).\n", PAGE_SIZE);
return -EINVAL;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 224de022e7c..a36a7435edf 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -43,12 +43,7 @@
* miss any bits.
*/
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/bitops.h>
#include <linux/kthread.h>
-#include <asm/atomic.h>
#include "raid6.h"
#include <linux/raid/bitmap.h>
@@ -101,6 +96,40 @@
const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));
#endif
+/*
+ * We maintain a biased count of active stripes in the bottom 16 bits of
+ * bi_phys_segments, and a count of processed stripes in the upper 16 bits
+ */
+static inline int raid5_bi_phys_segments(struct bio *bio)
+{
+ return bio->bi_phys_segments & 0xffff;
+}
+
+static inline int raid5_bi_hw_segments(struct bio *bio)
+{
+ return (bio->bi_phys_segments >> 16) & 0xffff;
+}
+
+static inline int raid5_dec_bi_phys_segments(struct bio *bio)
+{
+ --bio->bi_phys_segments;
+ return raid5_bi_phys_segments(bio);
+}
+
+static inline int raid5_dec_bi_hw_segments(struct bio *bio)
+{
+ unsigned short val = raid5_bi_hw_segments(bio);
+
+ --val;
+ bio->bi_phys_segments = (val << 16) | raid5_bi_phys_segments(bio);
+ return val;
+}
+
+static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt)
+{
+ bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16);
+}
+
static inline int raid6_next_disk(int disk, int raid_disks)
{
disk++;
@@ -241,7 +270,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
return 0;
}
-static void raid5_build_block (struct stripe_head *sh, int i);
+static void raid5_build_block(struct stripe_head *sh, int i);
static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks)
{
@@ -507,7 +536,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
while (rbi && rbi->bi_sector <
dev->sector + STRIPE_SECTORS) {
rbi2 = r5_next_bio(rbi, dev->sector);
- if (--rbi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(rbi)) {
rbi->bi_next = return_bi;
return_bi = rbi;
}
@@ -1117,7 +1146,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
release_stripe(sh);
}
-static void raid5_end_write_request (struct bio *bi, int error)
+static void raid5_end_write_request(struct bio *bi, int error)
{
struct stripe_head *sh = bi->bi_private;
raid5_conf_t *conf = sh->raid_conf;
@@ -1149,7 +1178,7 @@ static void raid5_end_write_request (struct bio *bi, int error)
static sector_t compute_blocknr(struct stripe_head *sh, int i);
-static void raid5_build_block (struct stripe_head *sh, int i)
+static void raid5_build_block(struct stripe_head *sh, int i)
{
struct r5dev *dev = &sh->dev[i];
@@ -1187,10 +1216,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
}
set_bit(Faulty, &rdev->flags);
- printk (KERN_ALERT
- "raid5: Disk failure on %s, disabling device.\n"
- "raid5: Operation continuing on %d devices.\n",
- bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+ printk(KERN_ALERT
+ "raid5: Disk failure on %s, disabling device.\n"
+ "raid5: Operation continuing on %d devices.\n",
+ bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
}
}
@@ -1286,8 +1315,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
*dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
break;
default:
- printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
- conf->algorithm);
+ printk(KERN_CRIT "raid6: unsupported algorithm %d\n",
+ conf->algorithm);
}
break;
}
@@ -1362,8 +1391,8 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
}
break;
default:
- printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
- conf->algorithm);
+ printk(KERN_CRIT "raid6: unsupported algorithm %d\n",
+ conf->algorithm);
}
break;
}
@@ -1371,7 +1400,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
chunk_number = stripe * data_disks + i;
r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
- check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
+ 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(KERN_ERR "compute_blocknr: map not correct\n");
return 0;
@@ -1725,7 +1754,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
if (*bip)
bi->bi_next = *bip;
*bip = bi;
- bi->bi_phys_segments ++;
+ bi->bi_phys_segments++;
spin_unlock_irq(&conf->device_lock);
spin_unlock(&sh->lock);
@@ -1819,7 +1848,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(bi)) {
md_write_end(conf->mddev);
bi->bi_next = *return_bi;
*return_bi = bi;
@@ -1834,7 +1863,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(bi)) {
md_write_end(conf->mddev);
bi->bi_next = *return_bi;
*return_bi = bi;
@@ -1858,7 +1887,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
struct bio *nextbi =
r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(bi)) {
bi->bi_next = *return_bi;
*return_bi = bi;
}
@@ -2033,7 +2062,7 @@ static void handle_stripe_clean_event(raid5_conf_t *conf,
while (wbi && wbi->bi_sector <
dev->sector + STRIPE_SECTORS) {
wbi2 = r5_next_bio(wbi, dev->sector);
- if (--wbi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(wbi)) {
md_write_end(conf->mddev);
wbi->bi_next = *return_bi;
*return_bi = wbi;
@@ -2814,7 +2843,7 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
copy_data(0, rbi, dev->page, dev->sector);
rbi2 = r5_next_bio(rbi, dev->sector);
spin_lock_irq(&conf->device_lock);
- if (--rbi->bi_phys_segments == 0) {
+ if (!raid5_dec_bi_phys_segments(rbi)) {
rbi->bi_next = return_bi;
return_bi = rbi;
}
@@ -3155,8 +3184,11 @@ static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
if(bi) {
conf->retry_read_aligned_list = bi->bi_next;
bi->bi_next = NULL;
+ /*
+ * this sets the active strip count to 1 and the processed
+ * strip count to zero (upper 8 bits)
+ */
bi->bi_phys_segments = 1; /* biased count of active stripes */
- bi->bi_hw_segments = 0; /* count of processed stripes */
}
return bi;
@@ -3206,8 +3238,7 @@ static int bio_fits_rdev(struct bio *bi)
if ((bi->bi_size>>9) > q->max_sectors)
return 0;
blk_recount_segments(q, bi);
- if (bi->bi_phys_segments > q->max_phys_segments ||
- bi->bi_hw_segments > q->max_hw_segments)
+ if (bi->bi_phys_segments > q->max_phys_segments)
return 0;
if (q->merge_bvec_fn)
@@ -3351,7 +3382,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
sector_t logical_sector, last_sector;
struct stripe_head *sh;
const int rw = bio_data_dir(bi);
- int remaining;
+ int cpu, remaining;
if (unlikely(bio_barrier(bi))) {
bio_endio(bi, -EOPNOTSUPP);
@@ -3360,8 +3391,11 @@ static int make_request(struct request_queue *q, struct bio * bi)
md_write_start(mddev, bi);
- disk_stat_inc(mddev->gendisk, ios[rw]);
- disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
+ cpu = part_stat_lock();
+ part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+ part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+ bio_sectors(bi));
+ part_stat_unlock();
if (rw == READ &&
mddev->reshape_position == MaxSector &&
@@ -3468,7 +3502,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
}
spin_lock_irq(&conf->device_lock);
- remaining = --bi->bi_phys_segments;
+ remaining = raid5_dec_bi_phys_segments(bi);
spin_unlock_irq(&conf->device_lock);
if (remaining == 0) {
@@ -3752,7 +3786,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
sector += STRIPE_SECTORS,
scnt++) {
- if (scnt < raid_bio->bi_hw_segments)
+ if (scnt < raid5_bi_hw_segments(raid_bio))
/* already done this stripe */
continue;
@@ -3760,7 +3794,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
if (!sh) {
/* failed to get a stripe - must wait */
- raid_bio->bi_hw_segments = scnt;
+ raid5_set_bi_hw_segments(raid_bio, scnt);
conf->retry_read_aligned = raid_bio;
return handled;
}
@@ -3768,7 +3802,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
set_bit(R5_ReadError, &sh->dev[dd_idx].flags);
if (!add_stripe_bio(sh, raid_bio, dd_idx, 0)) {
release_stripe(sh);
- raid_bio->bi_hw_segments = scnt;
+ raid5_set_bi_hw_segments(raid_bio, scnt);
conf->retry_read_aligned = raid_bio;
return handled;
}
@@ -3778,7 +3812,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
handled++;
}
spin_lock_irq(&conf->device_lock);
- remaining = --raid_bio->bi_phys_segments;
+ remaining = raid5_dec_bi_phys_segments(raid_bio);
spin_unlock_irq(&conf->device_lock);
if (remaining == 0)
bio_endio(raid_bio, 0);
@@ -3973,6 +4007,13 @@ static int run(mddev_t *mddev)
return -EIO;
}
+ if (mddev->chunk_size < PAGE_SIZE) {
+ printk(KERN_ERR "md/raid5: chunk_size must be at least "
+ "PAGE_SIZE but %d < %ld\n",
+ mddev->chunk_size, PAGE_SIZE);
+ return -EINVAL;
+ }
+
if (mddev->reshape_position != MaxSector) {
/* Check that we can continue the reshape.
* Currently only disks can change, it must
@@ -4250,7 +4291,7 @@ static int stop(mddev_t *mddev)
}
#ifdef DEBUG
-static void print_sh (struct seq_file *seq, struct stripe_head *sh)
+static void print_sh(struct seq_file *seq, struct stripe_head *sh)
{
int i;
@@ -4266,7 +4307,7 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
seq_printf(seq, "\n");
}
-static void printall (struct seq_file *seq, raid5_conf_t *conf)
+static void printall(struct seq_file *seq, raid5_conf_t *conf)
{
struct stripe_head *sh;
struct hlist_node *hn;
@@ -4284,7 +4325,7 @@ static void printall (struct seq_file *seq, raid5_conf_t *conf)
}
#endif
-static void status (struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, mddev_t *mddev)
{
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
int i;
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h
index 31cbee71365..98dcde88470 100644
--- a/drivers/md/raid6.h
+++ b/drivers/md/raid6.h
@@ -18,15 +18,6 @@
/* Set to 1 to use kernel-wide empty_zero_page */
#define RAID6_USE_EMPTY_ZERO_PAGE 0
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mempool.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
#include <linux/raid/md.h>
#include <linux/raid/raid5.h>
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index 8fa91f846d5..4952aeb5dd8 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -103,6 +103,56 @@ IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt);
+/* Mauro Carvalho Chehab <mchehab@infradead.org> */
+IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = {
+ [0x00] = KEY_POWER2,
+ [0x2e] = KEY_DOT, /* '.' */
+ [0x01] = KEY_MODE, /* TV/FM */
+
+ [0x05] = KEY_1,
+ [0x06] = KEY_2,
+ [0x07] = KEY_3,
+ [0x09] = KEY_4,
+ [0x0a] = KEY_5,
+ [0x0b] = KEY_6,
+ [0x0d] = KEY_7,
+ [0x0e] = KEY_8,
+ [0x0f] = KEY_9,
+ [0x11] = KEY_0,
+
+ [0x13] = KEY_RIGHT, /* -> */
+ [0x12] = KEY_LEFT, /* <- */
+
+ [0x17] = KEY_SLEEP, /* Capturar Imagem */
+ [0x10] = KEY_SHUFFLE, /* Amostra */
+
+ /* FIXME: The keys bellow aren't ok */
+
+ [0x43] = KEY_CHANNELUP,
+ [0x42] = KEY_CHANNELDOWN,
+ [0x1f] = KEY_VOLUMEUP,
+ [0x1e] = KEY_VOLUMEDOWN,
+ [0x0c] = KEY_ENTER,
+
+ [0x14] = KEY_MUTE,
+ [0x08] = KEY_AUDIO,
+
+ [0x03] = KEY_TEXT,
+ [0x04] = KEY_EPG,
+ [0x2b] = KEY_TV2, /* TV2 */
+
+ [0x1d] = KEY_RED,
+ [0x1c] = KEY_YELLOW,
+ [0x41] = KEY_GREEN,
+ [0x40] = KEY_BLUE,
+
+ [0x1a] = KEY_PLAYPAUSE,
+ [0x19] = KEY_RECORD,
+ [0x18] = KEY_PLAY,
+ [0x1b] = KEY_STOP,
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a);
+
/* Attila Kondoros <attila.kondoros@chello.hu> */
IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
@@ -467,7 +517,8 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci);
/* ---------------------------------------------------------------------- */
-/* MSI TV@nywhere remote */
+/* MSI TV@nywhere MASTER remote */
+
IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
/* Keys 0 to 9 */
[ 0x00 ] = KEY_0,
@@ -501,6 +552,95 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere);
/* ---------------------------------------------------------------------- */
+/*
+ Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
+ is marked "KS003". The controller is I2C at address 0x30, but does not seem
+ to respond to probes until a read is performed from a valid device.
+ I don't know why...
+
+ Note: This remote may be of similar or identical design to the
+ Pixelview remote (?). The raw codes and duplicate button codes
+ appear to be the same.
+
+ Henry Wong <henry@stuffedcow.net>
+ Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com>
+
+*/
+
+IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = {
+
+/* ---- Remote Button Layout ----
+
+ POWER SOURCE SCAN MUTE
+ TV/FM 1 2 3
+ |> 4 5 6
+ <| 7 8 9
+ ^^UP 0 + RECALL
+ vvDN RECORD STOP PLAY
+
+ MINIMIZE ZOOM
+
+ CH+
+ VOL- VOL+
+ CH-
+
+ SNAPSHOT MTS
+
+ << FUNC >> RESET
+*/
+
+ [0x01] = KEY_KP1, /* 1 */
+ [0x0b] = KEY_KP2, /* 2 */
+ [0x1b] = KEY_KP3, /* 3 */
+ [0x05] = KEY_KP4, /* 4 */
+ [0x09] = KEY_KP5, /* 5 */
+ [0x15] = KEY_KP6, /* 6 */
+ [0x06] = KEY_KP7, /* 7 */
+ [0x0a] = KEY_KP8, /* 8 */
+ [0x12] = KEY_KP9, /* 9 */
+ [0x02] = KEY_KP0, /* 0 */
+ [0x10] = KEY_KPPLUS, /* + */
+ [0x13] = KEY_AGAIN, /* Recall */
+
+ [0x1e] = KEY_POWER, /* Power */
+ [0x07] = KEY_TUNER, /* Source */
+ [0x1c] = KEY_SEARCH, /* Scan */
+ [0x18] = KEY_MUTE, /* Mute */
+
+ [0x03] = KEY_RADIO, /* TV/FM */
+ /* The next four keys are duplicates that appear to send the
+ same IR code as Ch+, Ch-, >>, and << . The raw code assigned
+ to them is the actual code + 0x20 - they will never be
+ detected as such unless some way is discovered to distinguish
+ these buttons from those that have the same code. */
+ [0x3f] = KEY_RIGHT, /* |> and Ch+ */
+ [0x37] = KEY_LEFT, /* <| and Ch- */
+ [0x2c] = KEY_UP, /* ^^Up and >> */
+ [0x24] = KEY_DOWN, /* vvDn and << */
+
+ [0x00] = KEY_RECORD, /* Record */
+ [0x08] = KEY_STOP, /* Stop */
+ [0x11] = KEY_PLAY, /* Play */
+
+ [0x0f] = KEY_CLOSE, /* Minimize */
+ [0x19] = KEY_ZOOM, /* Zoom */
+ [0x1a] = KEY_SHUFFLE, /* Snapshot */
+ [0x0d] = KEY_LANGUAGE, /* MTS */
+
+ [0x14] = KEY_VOLUMEDOWN, /* Vol- */
+ [0x16] = KEY_VOLUMEUP, /* Vol+ */
+ [0x17] = KEY_CHANNELDOWN, /* Ch- */
+ [0x1f] = KEY_CHANNELUP, /* Ch+ */
+
+ [0x04] = KEY_REWIND, /* << */
+ [0x0e] = KEY_MENU, /* Function */
+ [0x0c] = KEY_FASTFORWARD, /* >> */
+ [0x1d] = KEY_RESTART, /* Reset */
+};
+EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus);
+
+/* ---------------------------------------------------------------------- */
+
/* Cinergy 1400 DVB-T */
IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
[ 0x01 ] = KEY_POWER,
@@ -1792,12 +1932,61 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = {
[ 0x41 ] = KEY_GREEN, /* AP2 */
[ 0x47 ] = KEY_YELLOW, /* AP3 */
[ 0x57 ] = KEY_BLUE, /* AP4 */
-
-
};
-
EXPORT_SYMBOL_GPL(ir_codes_encore_enltv);
+/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton
+ Mauro Carvalho Chehab <mchehab@infradead.org> */
+IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = {
+ [0x4c] = KEY_POWER2,
+ [0x4a] = KEY_TUNER,
+ [0x40] = KEY_1,
+ [0x60] = KEY_2,
+ [0x50] = KEY_3,
+ [0x70] = KEY_4,
+ [0x48] = KEY_5,
+ [0x68] = KEY_6,
+ [0x58] = KEY_7,
+ [0x78] = KEY_8,
+ [0x44] = KEY_9,
+ [0x54] = KEY_0,
+
+ [0x64] = KEY_LAST, /* +100 */
+ [0x4e] = KEY_AGAIN, /* Recall */
+
+ [0x6c] = KEY_SWITCHVIDEOMODE, /* Video Source */
+ [0x5e] = KEY_MENU,
+ [0x56] = KEY_SCREEN,
+ [0x7a] = KEY_SETUP,
+
+ [0x46] = KEY_MUTE,
+ [0x5c] = KEY_MODE, /* Stereo */
+ [0x74] = KEY_INFO,
+ [0x7c] = KEY_CLEAR,
+
+ [0x55] = KEY_UP,
+ [0x49] = KEY_DOWN,
+ [0x7e] = KEY_LEFT,
+ [0x59] = KEY_RIGHT,
+ [0x6a] = KEY_ENTER,
+
+ [0x42] = KEY_VOLUMEUP,
+ [0x62] = KEY_VOLUMEDOWN,
+ [0x52] = KEY_CHANNELUP,
+ [0x72] = KEY_CHANNELDOWN,
+
+ [0x41] = KEY_RECORD,
+ [0x51] = KEY_SHUFFLE, /* Snapshot */
+ [0x75] = KEY_TIME, /* Timeshift */
+ [0x71] = KEY_TV2, /* PIP */
+
+ [0x45] = KEY_REWIND,
+ [0x6f] = KEY_PAUSE,
+ [0x7d] = KEY_FORWARD,
+ [0x79] = KEY_STOP,
+};
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2);
+
/* for the Technotrend 1500 bundled remotes (grey and black): */
IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
[ 0x01 ] = KEY_POWER,
@@ -2239,3 +2428,86 @@ IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
[0x2a] = KEY_MENU,
};
EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d);
+
+/* Encore ENLTV-FM v5.3
+ Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = {
+ [0x10] = KEY_POWER2,
+ [0x06] = KEY_MUTE,
+
+ [0x09] = KEY_1,
+ [0x1d] = KEY_2,
+ [0x1f] = KEY_3,
+ [0x19] = KEY_4,
+ [0x1b] = KEY_5,
+ [0x11] = KEY_6,
+ [0x17] = KEY_7,
+ [0x12] = KEY_8,
+ [0x16] = KEY_9,
+ [0x48] = KEY_0,
+
+ [0x04] = KEY_LIST, /* -/-- */
+ [0x40] = KEY_LAST, /* recall */
+
+ [0x02] = KEY_MODE, /* TV/AV */
+ [0x05] = KEY_SHUFFLE, /* SNAPSHOT */
+
+ [0x4c] = KEY_CHANNELUP, /* UP */
+ [0x00] = KEY_CHANNELDOWN, /* DOWN */
+ [0x0d] = KEY_VOLUMEUP, /* RIGHT */
+ [0x15] = KEY_VOLUMEDOWN, /* LEFT */
+ [0x49] = KEY_ENTER, /* OK */
+
+ [0x54] = KEY_RECORD,
+ [0x4d] = KEY_PLAY, /* pause */
+
+ [0x1e] = KEY_UP, /* video setting */
+ [0x0e] = KEY_RIGHT, /* <- */
+ [0x1a] = KEY_LEFT, /* -> */
+
+ [0x0a] = KEY_DOWN, /* video default */
+ [0x0c] = KEY_ZOOM, /* hide pannel */
+ [0x47] = KEY_SLEEP, /* shutdown */
+};
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53);
+
+/* Zogis Real Audio 220 - 32 keys IR */
+IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = {
+ [0x1c] = KEY_RADIO,
+ [0x12] = KEY_POWER2,
+
+ [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,
+ [0x00] = KEY_0,
+
+ [0x0c] = KEY_VOLUMEUP,
+ [0x18] = KEY_VOLUMEDOWN,
+ [0x0b] = KEY_CHANNELUP,
+ [0x15] = KEY_CHANNELDOWN,
+ [0x16] = KEY_ENTER,
+
+ [0x11] = KEY_LIST, /* Source */
+ [0x0d] = KEY_AUDIO, /* stereo */
+
+ [0x0f] = KEY_PREVIOUS, /* Prev */
+ [0x1b] = KEY_PAUSE, /* Timeshift */
+ [0x1a] = KEY_NEXT, /* Next */
+
+ [0x0e] = KEY_STOP,
+ [0x1f] = KEY_PLAY,
+ [0x1e] = KEY_PLAYPAUSE, /* Pause */
+
+ [0x1d] = KEY_RECORD,
+ [0x13] = KEY_MUTE,
+ [0x19] = KEY_SHUFFLE, /* Snapshot */
+
+};
+EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index d01965e9692..d599d360da3 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -234,7 +234,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
{
__le32 *cpu;
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr = 0;
cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
if (NULL == cpu) {
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cf6a817d505..5b34c134aa2 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -533,7 +533,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
memcpy(vfd, &device_template, sizeof(struct video_device));
strlcpy(vfd->name, name, sizeof(vfd->name));
vfd->release = video_device_release;
- vfd->priv = dev;
+ video_set_drvdata(vfd, dev);
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
if (video_register_device(vfd, type, -1) < 0) {
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index e8bc7abf240..99be9e5c85f 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1068,7 +1068,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
{
v4l2_std_id *id = arg;
int found = 0;
- int i, err;
+ int i;
DEB_EE(("VIDIOC_S_STD\n"));
@@ -1116,7 +1116,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOC_OVERLAY:
{
int on = *(int *)arg;
- int err = 0;
DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
if (on != 0) {
@@ -1192,7 +1191,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
- struct videobuf_queue *q;
int i;
/* fixme: number of capture buffers and sizes for v4l apps */
diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c
index 1305b0e63ce..12206d75dd4 100644
--- a/drivers/media/common/tuners/mt2060.c
+++ b/drivers/media/common/tuners/mt2060.c
@@ -170,6 +170,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
b[0] = REG_LO1B1;
b[1] = 0xFF;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
mt2060_writeregs(priv,b,2);
freq = params->frequency / 1000; // Hz -> kHz
@@ -233,6 +236,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
i++;
} while (i<10);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
return ret;
}
@@ -296,13 +302,35 @@ static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
static int mt2060_init(struct dvb_frontend *fe)
{
struct mt2060_priv *priv = fe->tuner_priv;
- return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33);
+ int ret;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+ ret = mt2060_writereg(priv, REG_VGAG,
+ (priv->cfg->clock_out << 6) | 0x33);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+ return ret;
}
static int mt2060_sleep(struct dvb_frontend *fe)
{
struct mt2060_priv *priv = fe->tuner_priv;
- return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
+ int ret;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+ ret = mt2060_writereg(priv, REG_VGAG,
+ (priv->cfg->clock_out << 6) | 0x30);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+ return ret;
}
static int mt2060_release(struct dvb_frontend *fe)
@@ -344,6 +372,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter
priv->i2c = i2c;
priv->if1_freq = if1;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
kfree(priv);
return NULL;
@@ -360,6 +391,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter
mt2060_calibrate(priv);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
return fe;
}
EXPORT_SYMBOL(mt2060_attach);
diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/common/tuners/mt2131.c
index e254bcfc2ef..e8d3c48f860 100644
--- a/drivers/media/common/tuners/mt2131.c
+++ b/drivers/media/common/tuners/mt2131.c
@@ -1,7 +1,7 @@
/*
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/common/tuners/mt2131.h b/drivers/media/common/tuners/mt2131.h
index cd8376f6f7b..6632de640df 100644
--- a/drivers/media/common/tuners/mt2131.h
+++ b/drivers/media/common/tuners/mt2131.h
@@ -1,7 +1,7 @@
/*
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/common/tuners/mt2131_priv.h
index e930759c2c0..4e05a67e88c 100644
--- a/drivers/media/common/tuners/mt2131_priv.h
+++ b/drivers/media/common/tuners/mt2131_priv.h
@@ -1,7 +1,7 @@
/*
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 0dc2bef9f6a..a8878244bb3 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -2,7 +2,7 @@
MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
Copyright (C) 2008 MaxLinear
- Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
Functions:
mxl5005s_reset()
mxl5005s_writereg()
@@ -3481,7 +3481,9 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
}
ctrlVal = 0;
for (k = 0; k < state->MXL_Ctrl[i].size; k++)
- ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k);
+ ctrlVal += state->
+ MXL_Ctrl[i].val[k] *
+ (1 << k);
} else
return -1;
}
@@ -3581,7 +3583,7 @@ static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
static u32 MXL_Ceiling(u32 value, u32 resolution)
{
- return (value/resolution + (value % resolution > 0 ? 1 : 0));
+ return value / resolution + (value % resolution > 0 ? 1 : 0);
}
/* Retrieve the Initialzation Registers */
@@ -3837,7 +3839,7 @@ static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
/* ----------------------------------------------------------------
* Begin: Everything after here is new code to adapt the
* proprietary Realtek driver into a Linux API tuner.
- * Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
*/
static int mxl5005s_reset(struct dvb_frontend *fe)
{
@@ -3910,7 +3912,10 @@ static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
static int mxl5005s_init(struct dvb_frontend *fe)
{
+ struct mxl5005s_state *state = fe->tuner_priv;
+
dprintk(1, "%s()\n", __func__);
+ state->current_mode = MXL_QAM;
return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
}
@@ -4092,7 +4097,6 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
state->frontend = fe;
state->config = config;
state->i2c = i2c;
- state->current_mode = MXL_QAM;
printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n",
config->i2c_address);
diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h
index 396db150bf0..7ac6815b30a 100644
--- a/drivers/media/common/tuners/mxl5005s.h
+++ b/drivers/media/common/tuners/mxl5005s.h
@@ -2,7 +2,7 @@
MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
Copyright (C) 2008 MaxLinear
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index cb25e43502f..64379f2bf23 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -979,7 +979,6 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
switch (instance) {
case 0:
goto fail;
- break;
case 1:
/* new tuner instance */
state->config = cfg;
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 93063c6fbbf..1b48b5d0bf1 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -1155,7 +1155,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
switch (instance) {
case 0:
goto fail;
- break;
case 1:
/* new tuner instance */
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index 8555d9cf905..4a74f65e759 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -447,17 +447,19 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
else
arg = 0;
}
- if (priv->cfg->tuner_callback)
- priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
- gp_func, arg);
+ if (fe->callback)
+ fe->callback(priv->i2c_adap->algo_data,
+ DVB_FRONTEND_COMPONENT_TUNER,
+ gp_func, arg);
buf[1] = high ? 0 : 1;
if (priv->cfg->config == 2)
buf[1] = high ? 1 : 0;
i2c_transfer(priv->i2c_adap, &msg, 1);
break;
case 3: /* switch with GPIO of saa713x */
- if (priv->cfg->tuner_callback)
- priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
+ if (fe->callback)
+ fe->callback(priv->i2c_adap->algo_data,
+ DVB_FRONTEND_COMPONENT_TUNER, 0, high);
break;
}
}
diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h
index 7850a9a1dc8..7d72ce0a0c2 100644
--- a/drivers/media/common/tuners/tda827x.h
+++ b/drivers/media/common/tuners/tda827x.h
@@ -36,7 +36,6 @@ struct tda827x_config
/* interface to tda829x driver */
unsigned int config;
int switch_addr;
- int (*tuner_callback) (void *dev, int command, int arg);
void (*agcf)(struct dvb_frontend *fe);
};
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
index 91204d3f282..c112bdd4e0f 100644
--- a/drivers/media/common/tuners/tda8290.c
+++ b/drivers/media/common/tuners/tda8290.c
@@ -672,10 +672,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
priv->i2c_props.addr = i2c_addr;
priv->i2c_props.adap = i2c_adap;
priv->i2c_props.name = "tda829x";
- if (cfg) {
+ if (cfg)
priv->cfg.config = cfg->lna_cfg;
- priv->cfg.tuner_callback = cfg->tuner_callback;
- }
if (tda8290_probe(&priv->i2c_props) == 0) {
priv->ver = TDA8290;
diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h
index aa074f3f0c0..7e288b26fcc 100644
--- a/drivers/media/common/tuners/tda8290.h
+++ b/drivers/media/common/tuners/tda8290.h
@@ -22,7 +22,6 @@
struct tda829x_config {
unsigned int lna_cfg;
- int (*tuner_callback) (void *dev, int command, int arg);
unsigned int probe_tuner:1;
#define TDA829X_PROBE_TUNER 0
diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c
index 72abf0b7348..ff1788cc5d4 100644
--- a/drivers/media/common/tuners/tda9887.c
+++ b/drivers/media/common/tuners/tda9887.c
@@ -686,7 +686,6 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
case 0:
mutex_unlock(&tda9887_list_mutex);
return NULL;
- break;
case 1:
fe->analog_demod_priv = priv;
priv->mode = T_STANDBY;
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index 597e47f5d69..fb3f3b3adab 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -142,6 +142,7 @@ static inline int tuner_stereo(const int type, const int status)
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FM1256_IH3:
case TUNER_LG_NTSC_TAPE:
+ case TUNER_TCL_MF02GIP_5N:
return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
default:
return status & TUNER_STEREO;
@@ -253,7 +254,7 @@ static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
static int simple_config_lookup(struct dvb_frontend *fe,
struct tuner_params *t_params,
- int *frequency, u8 *config, u8 *cb)
+ unsigned *frequency, u8 *config, u8 *cb)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
int i;
@@ -492,8 +493,10 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_PHILIPS_FMD1216MEX_MK3:
case TUNER_LG_NTSC_TAPE:
case TUNER_PHILIPS_FM1256_IH3:
+ case TUNER_TCL_MF02GIP_5N:
buffer[3] = 0x19;
break;
case TUNER_TNF_5335MF:
@@ -587,45 +590,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
priv->last_div = div;
if (t_params->has_tda9887) {
struct v4l2_priv_tun_config tda9887_cfg;
- int config = 0;
+ int tda_config = 0;
int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
V4L2_STD_SECAM_LC)) &&
!(params->std & ~(V4L2_STD_SECAM_L |
V4L2_STD_SECAM_LC));
tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &config;
+ tda9887_cfg.priv = &tda_config;
if (params->std == V4L2_STD_SECAM_LC) {
if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
- config |= TDA9887_PORT1_ACTIVE;
+ tda_config |= TDA9887_PORT1_ACTIVE;
if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
- config |= TDA9887_PORT2_ACTIVE;
+ tda_config |= TDA9887_PORT2_ACTIVE;
} else {
if (t_params->port1_active)
- config |= TDA9887_PORT1_ACTIVE;
+ tda_config |= TDA9887_PORT1_ACTIVE;
if (t_params->port2_active)
- config |= TDA9887_PORT2_ACTIVE;
+ tda_config |= TDA9887_PORT2_ACTIVE;
}
if (t_params->intercarrier_mode)
- config |= TDA9887_INTERCARRIER;
+ tda_config |= TDA9887_INTERCARRIER;
if (is_secam_l) {
if (i == 0 && t_params->default_top_secam_low)
- config |= TDA9887_TOP(t_params->default_top_secam_low);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_low);
else if (i == 1 && t_params->default_top_secam_mid)
- config |= TDA9887_TOP(t_params->default_top_secam_mid);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);
else if (t_params->default_top_secam_high)
- config |= TDA9887_TOP(t_params->default_top_secam_high);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_high);
} else {
if (i == 0 && t_params->default_top_low)
- config |= TDA9887_TOP(t_params->default_top_low);
+ tda_config |= TDA9887_TOP(t_params->default_top_low);
else if (i == 1 && t_params->default_top_mid)
- config |= TDA9887_TOP(t_params->default_top_mid);
+ tda_config |= TDA9887_TOP(t_params->default_top_mid);
else if (t_params->default_top_high)
- config |= TDA9887_TOP(t_params->default_top_high);
+ tda_config |= TDA9887_TOP(t_params->default_top_high);
}
if (t_params->default_pll_gating_18)
- config |= TDA9887_GATING_18;
+ tda_config |= TDA9887_GATING_18;
i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
&tda9887_cfg);
}
@@ -765,6 +768,7 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
switch (priv->type) {
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_PHILIPS_FMD1216MEX_MK3:
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
params->frequency >= 158870000)
buf[3] |= 0x08;
@@ -813,7 +817,8 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
static struct tuner_params *t_params;
u8 config, cb;
u32 div;
- int ret, frequency = params->frequency / 62500;
+ int ret;
+ unsigned frequency = params->frequency / 62500;
t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
@@ -1037,7 +1042,6 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
case 0:
mutex_unlock(&tuner_simple_list_mutex);
return NULL;
- break;
case 1:
fe->tuner_priv = priv;
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
index 10dddca8b5d..7c0bc064c00 100644
--- a/drivers/media/common/tuners/tuner-types.c
+++ b/drivers/media/common/tuners/tuner-types.c
@@ -946,7 +946,7 @@ static struct tuner_params tuner_tena_9533_di_params[] = {
},
};
-/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+/* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
{ 16 * 160.00 /*MHz*/, 0x86, 0x51, },
@@ -984,6 +984,27 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
},
};
+static struct tuner_params tuner_philips_fmd1216mex_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+ .has_tda9887 = 1,
+ .port1_active = 1,
+ .port2_active = 1,
+ .port2_fm_high_sensitivity = 1,
+ .port2_invert_for_secam_lc = 1,
+ .port1_set_for_fm_mono = 1,
+ .radio_if = 1,
+ .fm_gain_normal = 1,
+ },
+ {
+ .type = TUNER_PARAM_TYPE_DIGITAL,
+ .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
+ .iffreq = 16 * 36.125, /*MHz*/
+ },
+};
/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
@@ -1216,6 +1237,23 @@ static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
},
};
+/* ------------ TUNER_TCL_MF02GIP-5N-E - TCL MF02GIP-5N ------------ */
+
+static struct tuner_range tuner_tcl_mf02gip_5n_ntsc_ranges[] = {
+ { 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
+ { 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
+ { 16 * 999.99 , 0x8e, 0x04, },
+};
+
+static struct tuner_params tuner_tcl_mf02gip_5n_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tcl_mf02gip_5n_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_ntsc_ranges),
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
/* --------------------------------------------------------------------- */
struct tunertype tuners[] = {
@@ -1641,6 +1679,21 @@ struct tunertype tuners[] = {
.name = "Xceive 5000 tuner",
/* see xc5000.c for details */
},
+ [TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
+ .name = "TCL tuner MF02GIP-5N-E",
+ .params = tuner_tcl_mf02gip_5n_params,
+ .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
+ },
+ [TUNER_PHILIPS_FMD1216MEX_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216MEX MK3 Hybrid Tuner",
+ .params = tuner_philips_fmd1216mex_mk3_params,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216mex_mk3_params),
+ .min = 16 * 50.87,
+ .max = 16 * 858.00,
+ .stepsize = 166667,
+ .initdata = tua603x_agc112,
+ .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+ },
};
EXPORT_SYMBOL(tuners);
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 4dd1d2421cc..b65e6803e6c 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -71,9 +71,6 @@ struct firmware_properties {
struct xc2028_data {
struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props;
- int (*tuner_callback) (void *dev,
- int command, int arg);
- void *video_dev;
__u32 frequency;
struct firmware_description *firm;
@@ -492,6 +489,23 @@ ret:
return i;
}
+static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg)
+{
+ struct xc2028_data *priv = fe->tuner_priv;
+
+ /* analog side (tuner-core) uses i2c_adap->algo_data.
+ * digital side is not guaranteed to have algo_data defined.
+ *
+ * digital side will always have fe->dvb defined.
+ * analog side (tuner-core) doesn't (yet) define fe->dvb.
+ */
+
+ return (!fe->callback) ? -EINVAL :
+ fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+ fe->dvb->priv : priv->i2c_props.adap->algo_data,
+ DVB_FRONTEND_COMPONENT_TUNER, cmd, arg);
+}
+
static int load_firmware(struct dvb_frontend *fe, unsigned int type,
v4l2_std_id *id)
{
@@ -530,8 +544,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
if (!size) {
/* Special callback command received */
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_TUNER_RESET, 0);
+ rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
if (rc < 0) {
tuner_err("Error at RESET code %d\n",
(*p) & 0x7f);
@@ -542,8 +555,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
if (size >= 0xff00) {
switch (size) {
case 0xff00:
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_RESET_CLK, 0);
+ rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0);
if (rc < 0) {
tuner_err("Error at RESET code %d\n",
(*p) & 0x7f);
@@ -715,8 +727,7 @@ retry:
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
/* Reset is needed before loading firmware */
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_TUNER_RESET, 0);
+ rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
if (rc < 0)
goto fail;
@@ -933,7 +944,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
The reset CLK is needed only with tm6000.
Driver should work fine even if this fails.
*/
- priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+ do_tuner_callback(fe, XC2028_RESET_CLK, 1);
msleep(10);
@@ -1002,11 +1013,6 @@ static int xc2028_set_params(struct dvb_frontend *fe,
tuner_dbg("%s called\n", __func__);
- if (priv->ctrl.d2633)
- type |= D2633;
- else
- type |= D2620;
-
switch(fe->ops.info.type) {
case FE_OFDM:
bw = p->u.ofdm.bandwidth;
@@ -1021,10 +1027,8 @@ static int xc2028_set_params(struct dvb_frontend *fe,
break;
case FE_ATSC:
bw = BANDWIDTH_6_MHZ;
- /* The only ATSC firmware (at least on v2.7) is D2633,
- so overrides ctrl->d2633 */
- type |= ATSC| D2633;
- type &= ~D2620;
+ /* The only ATSC firmware (at least on v2.7) is D2633 */
+ type |= ATSC | D2633;
break;
/* DVB-S is not supported */
default:
@@ -1057,6 +1061,28 @@ static int xc2028_set_params(struct dvb_frontend *fe,
tuner_err("error: bandwidth not supported.\n");
};
+ /*
+ Selects between D2633 or D2620 firmware.
+ It doesn't make sense for ATSC, since it should be D2633 on all cases
+ */
+ if (fe->ops.info.type != FE_ATSC) {
+ switch (priv->ctrl.type) {
+ case XC2028_D2633:
+ type |= D2633;
+ break;
+ case XC2028_D2620:
+ type |= D2620;
+ break;
+ case XC2028_AUTO:
+ default:
+ /* Zarlink seems to need D2633 */
+ if (priv->ctrl.demod == XC3028_FE_ZARLINK456)
+ type |= D2633;
+ else
+ type |= D2620;
+ }
+ }
+
/* All S-code tables need a 200kHz shift */
if (priv->ctrl.demod)
demod = priv->ctrl.demod + 200;
@@ -1177,20 +1203,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
break;
case 1:
/* new tuner instance */
- priv->tuner_callback = cfg->callback;
priv->ctrl.max_len = 13;
mutex_init(&priv->lock);
- /* analog side (tuner-core) uses i2c_adap->algo_data.
- * digital side is not guaranteed to have algo_data defined.
- *
- * digital side will always have fe->dvb defined.
- * analog side (tuner-core) doesn't (yet) define fe->dvb.
- */
- priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
- fe->dvb->priv : cfg->i2c_adap->algo_data;
-
fe->tuner_priv = priv;
break;
case 2:
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
index 216025cf5d4..19de7928a74 100644
--- a/drivers/media/common/tuners/tuner-xc2028.h
+++ b/drivers/media/common/tuners/tuner-xc2028.h
@@ -10,6 +10,7 @@
#include "dvb_frontend.h"
#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
+#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"
/* Dmoduler IF (kHz) */
#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
@@ -23,24 +24,28 @@
#define XC3028_FE_ZARLINK456 4560
#define XC3028_FE_CHINA 5200
+enum firmware_type {
+ XC2028_AUTO = 0, /* By default, auto-detects */
+ XC2028_D2633,
+ XC2028_D2620,
+};
+
struct xc2028_ctrl {
char *fname;
int max_len;
unsigned int scode_table;
unsigned int mts :1;
- unsigned int d2633 :1;
unsigned int input1:1;
unsigned int vhfbw7:1;
unsigned int uhfbw8:1;
unsigned int demod;
+ enum firmware_type type:2;
};
struct xc2028_config {
struct i2c_adapter *i2c_adap;
u8 i2c_addr;
- void *video_dev;
struct xc2028_ctrl *ctrl;
- int (*callback) (void *dev, int command, int arg);
};
/* xc2028 commands for callback */
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 5f99de0ad61..e12d13e0cbe 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -2,7 +2,7 @@
* Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
*
* Copyright (c) 2007 Xceive Corporation
- * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2007 Steven Toth <stoth@linuxtv.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
@@ -30,7 +30,7 @@
#include "dvb_frontend.h"
#include "xc5000.h"
-#include "xc5000_priv.h"
+#include "tuner-i2c.h"
static int debug;
module_param(debug, int, 0644);
@@ -40,12 +40,26 @@ static int xc5000_load_fw_on_attach;
module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
-#define dprintk(level,fmt, arg...) if (debug >= level) \
+static DEFINE_MUTEX(xc5000_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
+#define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
+struct xc5000_priv {
+ struct tuner_i2c_props i2c_props;
+ struct list_head hybrid_tuner_instance_list;
+
+ u32 if_khz;
+ u32 freq_hz;
+ u32 bandwidth;
+ u8 video_standard;
+ u8 rf_mode;
+};
+
/* Misc Defines */
#define MAX_TV_STANDARD 23
#define XC_MAX_I2C_WRITE_LENGTH 64
@@ -124,11 +138,11 @@ MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
immediately the length of the following transaction.
*/
-typedef struct {
+struct XC_TV_STANDARD {
char *Name;
u16 AudioMode;
u16 VideoMode;
-} XC_TV_STANDARD;
+};
/* Tuner standards */
#define MN_NTSC_PAL_BTSC 0
@@ -155,7 +169,7 @@ typedef struct {
#define FM_Radio_INPUT2 21
#define FM_Radio_INPUT1 22
-static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
{"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
@@ -169,7 +183,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"D/K-PAL-NICAM", 0x0E80, 0x8009},
{"D/K-PAL-MONO", 0x1478, 0x8009},
{"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
- {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
+ {"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
{"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
{"L-SECAM-NICAM", 0x8E82, 0x0009},
{"L'-SECAM-NICAM", 0x8E82, 0x4009},
@@ -216,9 +230,12 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
dprintk(1, "%s()\n", __func__);
- if (priv->cfg->tuner_callback) {
- ret = priv->cfg->tuner_callback(priv->devptr,
- XC5000_TUNER_RESET, 0);
+ if (fe->callback) {
+ ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+ fe->dvb->priv :
+ priv->i2c_props.adap->algo_data,
+ DVB_FRONTEND_COMPONENT_TUNER,
+ XC5000_TUNER_RESET, 0);
if (ret)
printk(KERN_ERR "xc5000: reset failed\n");
} else
@@ -290,9 +307,10 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
unsigned int len, pos, index;
u8 buf[XC_MAX_I2C_WRITE_LENGTH];
- index=0;
- while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
- len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
+ index = 0;
+ while ((i2c_sequence[index] != 0xFF) ||
+ (i2c_sequence[index + 1] != 0xFF)) {
+ len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
if (len == 0x0000) {
/* RESET command */
result = xc_reset(fe);
@@ -312,15 +330,17 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
buf[1] = i2c_sequence[index + 1];
pos = 2;
while (pos < len) {
- if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
- nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
- } else {
+ if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
+ nbytes_to_send =
+ XC_MAX_I2C_WRITE_LENGTH;
+ else
nbytes_to_send = (len - pos + 2);
+ for (i = 2; i < nbytes_to_send; i++) {
+ buf[i] = i2c_sequence[index + pos +
+ i - 2];
}
- for (i=2; i<nbytes_to_send; i++) {
- buf[i] = i2c_sequence[index + pos + i - 2];
- }
- result = xc_send_i2c_data(priv, buf, nbytes_to_send);
+ result = xc_send_i2c_data(priv, buf,
+ nbytes_to_send);
if (result != XC_RESULT_SUCCESS)
return result;
@@ -369,8 +389,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
- if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
- {
+ if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
rf_mode = XC_RF_MODE_CABLE;
printk(KERN_ERR
"%s(), Invalid mode, defaulting to CABLE",
@@ -509,13 +528,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
u8 buf[2] = { reg >> 8, reg & 0xff };
u8 bval[2] = { 0, 0 };
struct i2c_msg msg[2] = {
- { .addr = priv->cfg->i2c_address,
+ { .addr = priv->i2c_props.addr,
.flags = 0, .buf = &buf[0], .len = 2 },
- { .addr = priv->cfg->i2c_address,
+ { .addr = priv->i2c_props.addr,
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
};
- if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+ if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
printk(KERN_WARNING "xc5000: I2C read failed\n");
return -EREMOTEIO;
}
@@ -526,10 +545,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+ struct i2c_msg msg = { .addr = priv->i2c_props.addr,
.flags = 0, .buf = buf, .len = len };
- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
(int)len);
return -EREMOTEIO;
@@ -539,17 +558,17 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
- struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+ struct i2c_msg msg = { .addr = priv->i2c_props.addr,
.flags = I2C_M_RD, .buf = buf, .len = len };
- if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
- printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
+ if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
+ printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len);
return -EREMOTEIO;
}
return 0;
}
-static int xc5000_fwupload(struct dvb_frontend* fe)
+static int xc5000_fwupload(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
const struct firmware *fw;
@@ -559,7 +578,8 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
XC5000_DEFAULT_FIRMWARE);
- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
+ ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
+ &priv->i2c_props.adap->dev);
if (ret) {
printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
ret = XC_RESULT_RESET_FAILURE;
@@ -575,7 +595,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
ret = XC_RESULT_RESET_FAILURE;
} else {
printk(KERN_INFO "xc5000: firmware upload\n");
- ret = xc_load_i2c_sequence(fe, fw->data );
+ ret = xc_load_i2c_sequence(fe, fw->data);
}
out:
@@ -634,7 +654,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
- switch(params->u.vsb.modulation) {
+ switch (params->u.vsb.modulation) {
case VSB_8:
case VSB_16:
dprintk(1, "%s() VSB modulation\n", __func__);
@@ -675,10 +695,10 @@ static int xc5000_set_params(struct dvb_frontend *fe,
return -EREMOTEIO;
}
- ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
+ ret = xc_set_IF_frequency(priv, priv->if_khz);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
- priv->cfg->if_khz);
+ priv->if_khz);
return -EIO;
}
@@ -731,42 +751,42 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
/* FIX ME: Some video standards may have several possible audio
standards. We simply default to one of them here.
*/
- if(params->std & V4L2_STD_MN) {
+ if (params->std & V4L2_STD_MN) {
/* default to BTSC audio standard */
priv->video_standard = MN_NTSC_PAL_BTSC;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_BG) {
+ if (params->std & V4L2_STD_PAL_BG) {
/* default to NICAM audio standard */
priv->video_standard = BG_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_I) {
+ if (params->std & V4L2_STD_PAL_I) {
/* default to NICAM audio standard */
priv->video_standard = I_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_DK) {
+ if (params->std & V4L2_STD_PAL_DK) {
/* default to NICAM audio standard */
priv->video_standard = DK_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_DK) {
+ if (params->std & V4L2_STD_SECAM_DK) {
/* default to A2 DK1 audio standard */
priv->video_standard = DK_SECAM_A2DK1;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_L) {
+ if (params->std & V4L2_STD_SECAM_L) {
priv->video_standard = L_SECAM_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_LC) {
+ if (params->std & V4L2_STD_SECAM_LC) {
priv->video_standard = LC_SECAM_NICAM;
goto tune_channel;
}
@@ -774,7 +794,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
tune_channel:
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR
+ printk(KERN_ERR
"xc5000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode);
return -EREMOTEIO;
@@ -846,7 +866,7 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
* I2C transactions until calibration is complete. This way we
* don't have to rely on clock stretching working.
*/
- xc_wait( 100 );
+ xc_wait(100);
/* Default to "CABLE" mode */
ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
@@ -868,15 +888,13 @@ static int xc5000_sleep(struct dvb_frontend *fe)
*/
ret = xc_shutdown(priv);
- if(ret != XC_RESULT_SUCCESS) {
+ if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: %s() unable to shutdown tuner\n",
__func__);
return -EREMOTEIO;
- }
- else {
+ } else
return XC_RESULT_SUCCESS;
- }
}
static int xc5000_init(struct dvb_frontend *fe)
@@ -897,9 +915,19 @@ static int xc5000_init(struct dvb_frontend *fe)
static int xc5000_release(struct dvb_frontend *fe)
{
+ struct xc5000_priv *priv = fe->tuner_priv;
+
dprintk(1, "%s()\n", __func__);
- kfree(fe->tuner_priv);
+
+ mutex_lock(&xc5000_list_mutex);
+
+ if (priv)
+ hybrid_tuner_release_state(priv);
+
+ mutex_unlock(&xc5000_list_mutex);
+
fe->tuner_priv = NULL;
+
return 0;
}
@@ -924,31 +952,45 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
- struct xc5000_config *cfg, void *devptr)
+ struct xc5000_config *cfg)
{
struct xc5000_priv *priv = NULL;
+ int instance;
u16 id = 0;
- dprintk(1, "%s()\n", __func__);
+ dprintk(1, "%s(%d-%04x)\n", __func__,
+ i2c ? i2c_adapter_id(i2c) : -1,
+ cfg ? cfg->i2c_address : -1);
- priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
+ mutex_lock(&xc5000_list_mutex);
- priv->cfg = cfg;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->i2c = i2c;
- priv->devptr = devptr;
+ instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
+ hybrid_tuner_instance_list,
+ i2c, cfg->i2c_address, "xc5000");
+ switch (instance) {
+ case 0:
+ goto fail;
+ break;
+ case 1:
+ /* new tuner instance */
+ priv->bandwidth = BANDWIDTH_6_MHZ;
+ priv->if_khz = cfg->if_khz;
+
+ fe->tuner_priv = priv;
+ break;
+ default:
+ /* existing tuner instance */
+ fe->tuner_priv = priv;
+ break;
+ }
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware.
*/
- if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
- kfree(priv);
- return NULL;
- }
+ if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
+ goto fail;
- switch(id) {
+ switch (id) {
case XC_PRODUCT_ID_FW_LOADED:
printk(KERN_INFO
"xc5000: Successfully identified at address 0x%02x\n",
@@ -967,19 +1009,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
printk(KERN_ERR
"xc5000: Device not found at addr 0x%02x (0x%x)\n",
cfg->i2c_address, id);
- kfree(priv);
- return NULL;
+ goto fail;
}
+ mutex_unlock(&xc5000_list_mutex);
+
memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
sizeof(struct dvb_tuner_ops));
- fe->tuner_priv = priv;
-
if (xc5000_load_fw_on_attach)
xc5000_init(fe);
return fe;
+fail:
+ mutex_unlock(&xc5000_list_mutex);
+
+ xc5000_release(fe);
+ return NULL;
}
EXPORT_SYMBOL(xc5000_attach);
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h
index c910715addc..f4c146698a0 100644
--- a/drivers/media/common/tuners/xc5000.h
+++ b/drivers/media/common/tuners/xc5000.h
@@ -1,7 +1,7 @@
/*
* Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
*
- * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2007 Steven Toth <stoth@linuxtv.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
@@ -30,8 +30,6 @@ struct i2c_adapter;
struct xc5000_config {
u8 i2c_address;
u32 if_khz;
-
- int (*tuner_callback) (void *priv, int command, int arg);
};
/* xc5000 callback command */
@@ -47,19 +45,17 @@ struct xc5000_config {
#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
(defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
-extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
- struct xc5000_config *cfg,
- void *devptr);
+ struct xc5000_config *cfg);
#else
-static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
- struct xc5000_config *cfg,
- void *devptr)
+ struct xc5000_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_MEDIA_TUNER_XC5000
+#endif
-#endif // __XC5000_H__
+#endif
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h
deleted file mode 100644
index a72a9887fe7..00000000000
--- a/drivers/media/common/tuners/xc5000_priv.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef XC5000_PRIV_H
-#define XC5000_PRIV_H
-
-struct xc5000_priv {
- struct xc5000_config *cfg;
- struct i2c_adapter *i2c;
-
- u32 freq_hz;
- u32 bandwidth;
- u8 video_standard;
- u8 rf_mode;
-
- void *devptr;
-};
-
-#endif
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 8bc1445bd33..0bcd852576d 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -20,7 +20,6 @@ comment "Supported USB Adapters"
source "drivers/media/dvb/dvb-usb/Kconfig"
source "drivers/media/dvb/ttusb-budget/Kconfig"
source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/cinergyT2/Kconfig"
source "drivers/media/dvb/siano/Kconfig"
comment "Supported FlexCopII (B2C2) Adapters"
@@ -35,6 +34,10 @@ comment "Supported Pluto2 Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/pluto2/Kconfig"
+comment "Supported SDMC DM1105 Adapters"
+ depends on DVB_CORE && PCI && I2C
+source "drivers/media/dvb/dm1105/Kconfig"
+
comment "Supported DVB Frontends"
depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index d6ba4d19520..f91e9eb15e5 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
+obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index a91ed28f03a..26f0011a507 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -10,7 +10,7 @@
int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
{
u8 *tcpu;
- dma_addr_t tdma;
+ dma_addr_t tdma = 0;
if (size % 2) {
err("dma buffersize has to be even.");
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index f9d087669d5..a127a4175c4 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -137,7 +137,8 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un
flexcop_diseqc_send_byte(fe, 0xff);
else {
flexcop_set_tone(fe, SEC_TONE_ON);
- udelay(12500);
+ mdelay(12);
+ udelay(500);
flexcop_set_tone(fe, SEC_TONE_OFF);
}
msleep(20);
@@ -490,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
.demod_address = 0x53,
.invert = 1,
.repeated_start_workaround = 1,
+ .serial_mpeg = 1,
};
static struct itd1000_config skystar2_rev2_7_itd1000_config = {
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index 55973eaf371..43a112ec6d4 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -221,12 +221,12 @@ int flexcop_i2c_init(struct flexcop_device *fc)
fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
- strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
- "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
- strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
- "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
- strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
- "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
+ strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
+ sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
+ strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
+ sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
+ strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
+ sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index a7637562e74..aa3db57d32d 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1244,7 +1244,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len)
goto error;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
- udelay(3000);
+ mdelay(3);
if (read_dst(state, &reply, GET_ACK)) {
dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
@@ -1260,7 +1260,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len)
if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
goto error;
if (state->type_flags & DST_TYPE_HAS_FW_1)
- udelay(3000);
+ mdelay(3);
else
udelay(2000);
if (!dst_wait_dst_ready(state, NO_DELAY))
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 6afbfbbef0c..48762a2b9e4 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -702,7 +702,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
}
if (card->fe == NULL)
- printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+ printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
card->bt->dev->vendor,
card->bt->dev->device,
card->bt->dev->subsystem_vendor,
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
deleted file mode 100644
index c03513b2cca..00000000000
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ /dev/null
@@ -1,85 +0,0 @@
-config DVB_CINERGYT2
- tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver"
- depends on DVB_CORE && USB && INPUT
- help
- Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
-
- Say Y if you own such a device and want to use it.
-
-
-config DVB_CINERGYT2_TUNING
- bool "sophisticated fine-tuning for CinergyT2 cards"
- depends on DVB_CINERGYT2
- help
- Here you can fine-tune some parameters of the CinergyT2 driver.
-
- Normally you don't need to touch this, but in exotic setups you
- may fine-tune your setup and adjust e.g. DMA buffer sizes for
- a particular application.
-
-
-config DVB_CINERGYT2_STREAM_URB_COUNT
- int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
- depends on DVB_CINERGYT2_TUNING
- default "32"
- help
- USB Request Blocks for Highspeed Stream transfers are scheduled in
- a queue for the Host Controller.
-
- Usually the default value is a safe choice.
-
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
- sharing the same USB bus.
-
-
-config DVB_CINERGYT2_STREAM_BUF_SIZE
- int "Size of URB Stream Buffers for Highspeed Transfers"
- depends on DVB_CINERGYT2_TUNING
- default "512"
- help
- Should be a multiple of native buffer size of 512 bytes.
- Default value is a safe choice.
-
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
- sharing the same USB bus.
-
-
-config DVB_CINERGYT2_QUERY_INTERVAL
- int "Status update interval [milliseconds]"
- depends on DVB_CINERGYT2_TUNING
- default "250"
- help
- This is the interval for status readouts from the demodulator.
- You may try lower values if you need more responsive signal quality
- measurements.
-
- Please keep in mind that these updates cause traffic on the tuner
- control bus and thus may or may not affect reception sensitivity.
-
- The default value should be a safe choice for common applications.
-
-
-config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
- bool "Register the onboard IR Remote Control Receiver as Input Device"
- depends on DVB_CINERGYT2_TUNING
- default y
- help
- Enable this option if you want to use the onboard Infrared Remote
- Control Receiver as Linux-Input device.
-
- Right now only the keycode table for the default Remote Control
- delivered with the device is supported, please see the driver
- source code to find out how to add support for other controls.
-
-
-config DVB_CINERGYT2_RC_QUERY_INTERVAL
- int "Infrared Remote Controller update interval [milliseconds]"
- depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
- default "50"
- help
- If you have a very fast-repeating remote control you can try lower
- values, for normal consumer receivers the default value should be
- a safe choice.
-
diff --git a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile
deleted file mode 100644
index d762d8cb0cf..00000000000
--- a/drivers/media/dvb/cinergyT2/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o
-
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
deleted file mode 100644
index a824f3719f8..00000000000
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- * TerraTec Cinergy T²/qanu USB2 DVB-T adapter.
- *
- * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
- * Holger Waechtler <holger@qanu.de>
- *
- * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/dvb/frontend.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-
-#ifdef CONFIG_DVB_CINERGYT2_TUNING
- #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
- #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
- #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL)
- #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
- #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL)
- #define ENABLE_RC (1)
- #endif
-#else
- #define STREAM_URB_COUNT (32)
- #define STREAM_BUF_SIZE (512) /* bytes */
- #define ENABLE_RC (1)
- #define RC_QUERY_INTERVAL (50) /* milliseconds */
- #define QUERY_INTERVAL (333) /* milliseconds */
-#endif
-
-#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
-
-static int debug;
-module_param_named(debug, debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk(level, args...) \
-do { \
- if ((debug & level)) { \
- printk("%s: %s(): ", KBUILD_MODNAME, \
- __func__); \
- printk(args); } \
-} while (0)
-
-enum cinergyt2_ep1_cmd {
- CINERGYT2_EP1_PID_TABLE_RESET = 0x01,
- CINERGYT2_EP1_PID_SETUP = 0x02,
- CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03,
- CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04,
- CINERGYT2_EP1_GET_TUNER_STATUS = 0x05,
- CINERGYT2_EP1_START_SCAN = 0x06,
- CINERGYT2_EP1_CONTINUE_SCAN = 0x07,
- CINERGYT2_EP1_GET_RC_EVENTS = 0x08,
- CINERGYT2_EP1_SLEEP_MODE = 0x09
-};
-
-struct dvbt_set_parameters_msg {
- uint8_t cmd;
- __le32 freq;
- uint8_t bandwidth;
- __le16 tps;
- uint8_t flags;
-} __attribute__((packed));
-
-struct dvbt_get_status_msg {
- __le32 freq;
- uint8_t bandwidth;
- __le16 tps;
- uint8_t flags;
- __le16 gain;
- uint8_t snr;
- __le32 viterbi_error_rate;
- __le32 rs_error_rate;
- __le32 uncorrected_block_count;
- uint8_t lock_bits;
- uint8_t prev_lock_bits;
-} __attribute__((packed));
-
-static struct dvb_frontend_info cinergyt2_fe_info = {
- .name = DRIVER_NAME,
- .type = FE_OFDM,
- .frequency_min = 174000000,
- .frequency_max = 862000000,
- .frequency_stepsize = 166667,
- .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
- FE_CAN_FEC_AUTO |
- FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS
-};
-
-struct cinergyt2 {
- struct dvb_demux demux;
- struct usb_device *udev;
- struct mutex sem;
- struct mutex wq_sem;
- struct dvb_adapter adapter;
- struct dvb_device *fedev;
- struct dmxdev dmxdev;
- struct dvb_net dvbnet;
-
- int streaming;
- int sleeping;
-
- struct dvbt_set_parameters_msg param;
- struct dvbt_get_status_msg status;
- struct delayed_work query_work;
-
- wait_queue_head_t poll_wq;
- int pending_fe_events;
- int disconnect_pending;
- unsigned int uncorrected_block_count;
- atomic_t inuse;
-
- void *streambuf;
- dma_addr_t streambuf_dmahandle;
- struct urb *stream_urb [STREAM_URB_COUNT];
-
-#ifdef ENABLE_RC
- struct input_dev *rc_input_dev;
- char phys[64];
- struct delayed_work rc_query_work;
- int rc_input_event;
- __le32 rc_last_code;
- unsigned long last_event_jiffies;
-#endif
-};
-
-enum {
- CINERGYT2_RC_EVENT_TYPE_NONE = 0x00,
- CINERGYT2_RC_EVENT_TYPE_NEC = 0x01,
- CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02
-};
-
-struct cinergyt2_rc_event {
- char type;
- __le32 value;
-} __attribute__((packed));
-
-static const uint32_t rc_keys[] = {
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT
-};
-
-static int cinergyt2_command (struct cinergyt2 *cinergyt2,
- char *send_buf, int send_buf_len,
- char *recv_buf, int recv_buf_len)
-{
- int actual_len;
- char dummy;
- int ret;
-
- ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1),
- send_buf, send_buf_len, &actual_len, 1000);
-
- if (ret)
- dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret);
-
- if (!recv_buf)
- recv_buf = &dummy;
-
- ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1),
- recv_buf, recv_buf_len, &actual_len, 1000);
-
- if (ret)
- dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret);
-
- return ret ? ret : actual_len;
-}
-
-static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable)
-{
- char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
- cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
-}
-
-static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep)
-{
- char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 };
- cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
- cinergyt2->sleeping = sleep;
-}
-
-static void cinergyt2_stream_irq (struct urb *urb);
-
-static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb)
-{
- int err;
-
- usb_fill_bulk_urb(urb,
- cinergyt2->udev,
- usb_rcvbulkpipe(cinergyt2->udev, 0x2),
- urb->transfer_buffer,
- STREAM_BUF_SIZE,
- cinergyt2_stream_irq,
- cinergyt2);
-
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)))
- dprintk(1, "urb submission failed (err = %i)!\n", err);
-
- return err;
-}
-
-static void cinergyt2_stream_irq (struct urb *urb)
-{
- struct cinergyt2 *cinergyt2 = urb->context;
-
- if (urb->actual_length > 0)
- dvb_dmx_swfilter(&cinergyt2->demux,
- urb->transfer_buffer, urb->actual_length);
-
- if (cinergyt2->streaming)
- cinergyt2_submit_stream_urb(cinergyt2, urb);
-}
-
-static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
-{
- int i;
-
- for (i=0; i<STREAM_URB_COUNT; i++)
- usb_free_urb(cinergyt2->stream_urb[i]);
-
- usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
- cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
-}
-
-static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
-{
- int i;
-
- cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
- GFP_KERNEL, &cinergyt2->streambuf_dmahandle);
- if (!cinergyt2->streambuf) {
- dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n");
- return -ENOMEM;
- }
-
- memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE);
-
- for (i=0; i<STREAM_URB_COUNT; i++) {
- struct urb *urb;
-
- if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) {
- dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n");
- cinergyt2_free_stream_urbs(cinergyt2);
- return -ENOMEM;
- }
-
- urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE;
- urb->transfer_buffer_length = STREAM_BUF_SIZE;
-
- cinergyt2->stream_urb[i] = urb;
- }
-
- return 0;
-}
-
-static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
-{
- int i;
-
- cinergyt2_control_stream_transfer(cinergyt2, 0);
-
- for (i=0; i<STREAM_URB_COUNT; i++)
- usb_kill_urb(cinergyt2->stream_urb[i]);
-}
-
-static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2)
-{
- int i, err;
-
- for (i=0; i<STREAM_URB_COUNT; i++) {
- if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) {
- cinergyt2_stop_stream_xfer(cinergyt2);
- dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err);
- return err;
- }
- }
-
- cinergyt2_control_stream_transfer(cinergyt2, 1);
- return 0;
-}
-
-static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- struct dvb_demux *demux = dvbdmxfeed->demux;
- struct cinergyt2 *cinergyt2 = demux->priv;
-
- if (cinergyt2->disconnect_pending)
- return -EAGAIN;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
-
- if (cinergyt2->streaming == 0)
- cinergyt2_start_stream_xfer(cinergyt2);
-
- cinergyt2->streaming++;
- mutex_unlock(&cinergyt2->sem);
- return 0;
-}
-
-static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- struct dvb_demux *demux = dvbdmxfeed->demux;
- struct cinergyt2 *cinergyt2 = demux->priv;
-
- if (cinergyt2->disconnect_pending)
- return -EAGAIN;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
-
- if (--cinergyt2->streaming == 0)
- cinergyt2_stop_stream_xfer(cinergyt2);
-
- mutex_unlock(&cinergyt2->sem);
- return 0;
-}
-
-/**
- * convert linux-dvb frontend parameter set into TPS.
- * See ETSI ETS-300744, section 4.6.2, table 9 for details.
- *
- * This function is probably reusable and may better get placed in a support
- * library.
- *
- * We replace errornous fields by default TPS fields (the ones with value 0).
- */
-static uint16_t compute_tps (struct dvb_frontend_parameters *p)
-{
- struct dvb_ofdm_parameters *op = &p->u.ofdm;
- uint16_t tps = 0;
-
- switch (op->code_rate_HP) {
- case FEC_2_3:
- tps |= (1 << 7);
- break;
- case FEC_3_4:
- tps |= (2 << 7);
- break;
- case FEC_5_6:
- tps |= (3 << 7);
- break;
- case FEC_7_8:
- tps |= (4 << 7);
- break;
- case FEC_1_2:
- case FEC_AUTO:
- default:
- /* tps |= (0 << 7) */;
- }
-
- switch (op->code_rate_LP) {
- case FEC_2_3:
- tps |= (1 << 4);
- break;
- case FEC_3_4:
- tps |= (2 << 4);
- break;
- case FEC_5_6:
- tps |= (3 << 4);
- break;
- case FEC_7_8:
- tps |= (4 << 4);
- break;
- case FEC_1_2:
- case FEC_AUTO:
- default:
- /* tps |= (0 << 4) */;
- }
-
- switch (op->constellation) {
- case QAM_16:
- tps |= (1 << 13);
- break;
- case QAM_64:
- tps |= (2 << 13);
- break;
- case QPSK:
- default:
- /* tps |= (0 << 13) */;
- }
-
- switch (op->transmission_mode) {
- case TRANSMISSION_MODE_8K:
- tps |= (1 << 0);
- break;
- case TRANSMISSION_MODE_2K:
- default:
- /* tps |= (0 << 0) */;
- }
-
- switch (op->guard_interval) {
- case GUARD_INTERVAL_1_16:
- tps |= (1 << 2);
- break;
- case GUARD_INTERVAL_1_8:
- tps |= (2 << 2);
- break;
- case GUARD_INTERVAL_1_4:
- tps |= (3 << 2);
- break;
- case GUARD_INTERVAL_1_32:
- default:
- /* tps |= (0 << 2) */;
- }
-
- switch (op->hierarchy_information) {
- case HIERARCHY_1:
- tps |= (1 << 10);
- break;
- case HIERARCHY_2:
- tps |= (2 << 10);
- break;
- case HIERARCHY_4:
- tps |= (3 << 10);
- break;
- case HIERARCHY_NONE:
- default:
- /* tps |= (0 << 10) */;
- }
-
- return tps;
-}
-
-static int cinergyt2_open (struct inode *inode, struct file *file)
-{
- struct dvb_device *dvbdev = file->private_data;
- struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int err = -EAGAIN;
-
- if (cinergyt2->disconnect_pending)
- goto out;
- err = mutex_lock_interruptible(&cinergyt2->wq_sem);
- if (err)
- goto out;
-
- err = mutex_lock_interruptible(&cinergyt2->sem);
- if (err)
- goto out_unlock1;
-
- if ((err = dvb_generic_open(inode, file)))
- goto out_unlock2;
-
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
- cinergyt2_sleep(cinergyt2, 0);
- schedule_delayed_work(&cinergyt2->query_work, HZ/2);
- }
-
- atomic_inc(&cinergyt2->inuse);
-
-out_unlock2:
- mutex_unlock(&cinergyt2->sem);
-out_unlock1:
- mutex_unlock(&cinergyt2->wq_sem);
-out:
- return err;
-}
-
-static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
-{
- dvb_net_release(&cinergyt2->dvbnet);
- dvb_dmxdev_release(&cinergyt2->dmxdev);
- dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_device(cinergyt2->fedev);
- dvb_unregister_adapter(&cinergyt2->adapter);
-
- cinergyt2_free_stream_urbs(cinergyt2);
- kfree(cinergyt2);
-}
-
-static int cinergyt2_release (struct inode *inode, struct file *file)
-{
- struct dvb_device *dvbdev = file->private_data;
- struct cinergyt2 *cinergyt2 = dvbdev->priv;
-
- mutex_lock(&cinergyt2->wq_sem);
-
- if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
- cancel_rearming_delayed_work(&cinergyt2->query_work);
-
- mutex_lock(&cinergyt2->sem);
- cinergyt2_sleep(cinergyt2, 1);
- mutex_unlock(&cinergyt2->sem);
- }
-
- mutex_unlock(&cinergyt2->wq_sem);
-
- if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
- warn("delayed unregister in release");
- cinergyt2_unregister(cinergyt2);
- }
-
- return dvb_generic_release(inode, file);
-}
-
-static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait)
-{
- struct dvb_device *dvbdev = file->private_data;
- struct cinergyt2 *cinergyt2 = dvbdev->priv;
- unsigned int mask = 0;
-
- if (cinergyt2->disconnect_pending)
- return -EAGAIN;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
-
- poll_wait(file, &cinergyt2->poll_wq, wait);
-
- if (cinergyt2->pending_fe_events != 0)
- mask |= (POLLIN | POLLRDNORM | POLLPRI);
-
- mutex_unlock(&cinergyt2->sem);
-
- return mask;
-}
-
-
-static int cinergyt2_ioctl (struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct dvb_device *dvbdev = file->private_data;
- struct cinergyt2 *cinergyt2 = dvbdev->priv;
- struct dvbt_get_status_msg *stat = &cinergyt2->status;
- fe_status_t status = 0;
-
- switch (cmd) {
- case FE_GET_INFO:
- return copy_to_user((void __user*) arg, &cinergyt2_fe_info,
- sizeof(struct dvb_frontend_info));
-
- case FE_READ_STATUS:
- if (0xffff - le16_to_cpu(stat->gain) > 30)
- status |= FE_HAS_SIGNAL;
- if (stat->lock_bits & (1 << 6))
- status |= FE_HAS_LOCK;
- if (stat->lock_bits & (1 << 5))
- status |= FE_HAS_SYNC;
- if (stat->lock_bits & (1 << 4))
- status |= FE_HAS_CARRIER;
- if (stat->lock_bits & (1 << 1))
- status |= FE_HAS_VITERBI;
-
- return copy_to_user((void __user*) arg, &status, sizeof(status));
-
- case FE_READ_BER:
- return put_user(le32_to_cpu(stat->viterbi_error_rate),
- (__u32 __user *) arg);
-
- case FE_READ_SIGNAL_STRENGTH:
- return put_user(0xffff - le16_to_cpu(stat->gain),
- (__u16 __user *) arg);
-
- case FE_READ_SNR:
- return put_user((stat->snr << 8) | stat->snr,
- (__u16 __user *) arg);
-
- case FE_READ_UNCORRECTED_BLOCKS:
- {
- uint32_t unc_count;
-
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
- unc_count = cinergyt2->uncorrected_block_count;
- cinergyt2->uncorrected_block_count = 0;
- mutex_unlock(&cinergyt2->sem);
-
- /* UNC are already converted to host byte order... */
- return put_user(unc_count,(__u32 __user *) arg);
- }
- case FE_SET_FRONTEND:
- {
- struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- struct dvb_frontend_parameters p;
- int err;
-
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- return -EPERM;
-
- if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
- return -EFAULT;
-
- if (cinergyt2->disconnect_pending)
- return -EAGAIN;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
-
- param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
- param->tps = cpu_to_le16(compute_tps(&p));
- param->freq = cpu_to_le32(p.frequency / 1000);
- param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
-
- stat->lock_bits = 0;
- cinergyt2->pending_fe_events++;
- wake_up_interruptible(&cinergyt2->poll_wq);
-
- err = cinergyt2_command(cinergyt2,
- (char *) param, sizeof(*param),
- NULL, 0);
-
- mutex_unlock(&cinergyt2->sem);
-
- return (err < 0) ? err : 0;
- }
-
- case FE_GET_FRONTEND:
- /**
- * trivial to implement (see struct dvbt_get_status_msg).
- * equivalent to FE_READ ioctls, but needs
- * TPS -> linux-dvb parameter set conversion. Feel free
- * to implement this and send us a patch if you need this
- * functionality.
- */
- break;
-
- case FE_GET_EVENT:
- {
- /**
- * for now we only fill the status field. the parameters
- * are trivial to fill as soon FE_GET_FRONTEND is done.
- */
- struct dvb_frontend_event __user *e = (void __user *) arg;
- if (cinergyt2->pending_fe_events == 0) {
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
- wait_event_interruptible(cinergyt2->poll_wq,
- cinergyt2->pending_fe_events > 0);
- }
- cinergyt2->pending_fe_events = 0;
- return cinergyt2_ioctl(inode, file, FE_READ_STATUS,
- (unsigned long) &e->status);
- }
-
- default:
- ;
- }
-
- return -EINVAL;
-}
-
-static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct dvb_device *dvbdev = file->private_data;
- struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int ret = 0;
-
- lock_kernel();
-
- if (vma->vm_flags & (VM_WRITE | VM_EXEC)) {
- ret = -EPERM;
- goto bailout;
- }
-
- if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) {
- ret = -EINVAL;
- goto bailout;
- }
-
- vma->vm_flags |= (VM_IO | VM_DONTCOPY);
- vma->vm_file = file;
-
- ret = remap_pfn_range(vma, vma->vm_start,
- virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot) ? -EAGAIN : 0;
-bailout:
- unlock_kernel();
- return ret;
-}
-
-static struct file_operations cinergyt2_fops = {
- .owner = THIS_MODULE,
- .ioctl = cinergyt2_ioctl,
- .poll = cinergyt2_poll,
- .open = cinergyt2_open,
- .release = cinergyt2_release,
- .mmap = cinergyt2_mmap
-};
-
-static struct dvb_device cinergyt2_fe_template = {
- .users = ~0,
- .writers = 1,
- .readers = (~0)-1,
- .fops = &cinergyt2_fops
-};
-
-#ifdef ENABLE_RC
-
-static void cinergyt2_query_rc (struct work_struct *work)
-{
- struct cinergyt2 *cinergyt2 =
- container_of(work, struct cinergyt2, rc_query_work.work);
- char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
- struct cinergyt2_rc_event rc_events[12];
- int n, len, i;
-
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
- return;
-
- len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
- (char *) rc_events, sizeof(rc_events));
- if (len < 0)
- goto out;
- if (len == 0) {
- if (time_after(jiffies, cinergyt2->last_event_jiffies +
- msecs_to_jiffies(150))) {
- /* stop key repeat */
- if (cinergyt2->rc_input_event != KEY_MAX) {
- dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
- input_report_key(cinergyt2->rc_input_dev,
- cinergyt2->rc_input_event, 0);
- input_sync(cinergyt2->rc_input_dev);
- cinergyt2->rc_input_event = KEY_MAX;
- }
- cinergyt2->rc_last_code = cpu_to_le32(~0);
- }
- goto out;
- }
- cinergyt2->last_event_jiffies = jiffies;
-
- for (n = 0; n < (len / sizeof(rc_events[0])); n++) {
- dprintk(1, "rc_events[%d].value = %x, type=%x\n",
- n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
-
- if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
- rc_events[n].value == cpu_to_le32(~0)) {
- /* keyrepeat bit -> just repeat last rc_input_event */
- } else {
- cinergyt2->rc_input_event = KEY_MAX;
- for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) {
- if (rc_keys[i + 0] == rc_events[n].type &&
- rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
- cinergyt2->rc_input_event = rc_keys[i + 2];
- break;
- }
- }
- }
-
- if (cinergyt2->rc_input_event != KEY_MAX) {
- if (rc_events[n].value == cinergyt2->rc_last_code &&
- cinergyt2->rc_last_code != cpu_to_le32(~0)) {
- /* emit a key-up so the double event is recognized */
- dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
- input_report_key(cinergyt2->rc_input_dev,
- cinergyt2->rc_input_event, 0);
- }
- dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
- input_report_key(cinergyt2->rc_input_dev,
- cinergyt2->rc_input_event, 1);
- input_sync(cinergyt2->rc_input_dev);
- cinergyt2->rc_last_code = rc_events[n].value;
- }
- }
-
-out:
- schedule_delayed_work(&cinergyt2->rc_query_work,
- msecs_to_jiffies(RC_QUERY_INTERVAL));
-
- mutex_unlock(&cinergyt2->sem);
-}
-
-static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
-{
- struct input_dev *input_dev;
- int i;
- int err;
-
- input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
-
- usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
- strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
- cinergyt2->rc_input_event = KEY_MAX;
- cinergyt2->rc_last_code = cpu_to_le32(~0);
- INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc);
-
- input_dev->name = DRIVER_NAME " remote control";
- input_dev->phys = cinergyt2->phys;
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
- for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3)
- set_bit(rc_keys[i + 2], input_dev->keybit);
- input_dev->keycodesize = 0;
- input_dev->keycodemax = 0;
- input_dev->id.bustype = BUS_USB;
- input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor);
- input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct);
- input_dev->id.version = 1;
- input_dev->dev.parent = &cinergyt2->udev->dev;
-
- err = input_register_device(input_dev);
- if (err) {
- input_free_device(input_dev);
- return err;
- }
-
- cinergyt2->rc_input_dev = input_dev;
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-
- return 0;
-}
-
-static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
-{
- cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
- input_unregister_device(cinergyt2->rc_input_dev);
-}
-
-static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
-{
- cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
-}
-
-static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
-{
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-}
-
-#else
-
-static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; }
-static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { }
-static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { }
-static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { }
-
-#endif /* ENABLE_RC */
-
-static void cinergyt2_query (struct work_struct *work)
-{
- struct cinergyt2 *cinergyt2 =
- container_of(work, struct cinergyt2, query_work.work);
- char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
- struct dvbt_get_status_msg *s = &cinergyt2->status;
- uint8_t lock_bits;
-
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
- return;
-
- lock_bits = s->lock_bits;
-
- cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s));
-
- cinergyt2->uncorrected_block_count +=
- le32_to_cpu(s->uncorrected_block_count);
-
- if (lock_bits != s->lock_bits) {
- wake_up_interruptible(&cinergyt2->poll_wq);
- cinergyt2->pending_fe_events++;
- }
-
- schedule_delayed_work(&cinergyt2->query_work,
- msecs_to_jiffies(QUERY_INTERVAL));
-
- mutex_unlock(&cinergyt2->sem);
-}
-
-static int cinergyt2_probe (struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct cinergyt2 *cinergyt2;
- int err;
-
- if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
- dprintk(1, "out of memory?!?\n");
- return -ENOMEM;
- }
-
- usb_set_intfdata (intf, (void *) cinergyt2);
-
- mutex_init(&cinergyt2->sem);
- mutex_init(&cinergyt2->wq_sem);
- init_waitqueue_head (&cinergyt2->poll_wq);
- INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query);
-
- cinergyt2->udev = interface_to_usbdev(intf);
- cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-
- if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) {
- dprintk(1, "unable to allocate stream urbs\n");
- kfree(cinergyt2);
- return -ENOMEM;
- }
-
- err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
- THIS_MODULE, &cinergyt2->udev->dev,
- adapter_nr);
- if (err < 0) {
- kfree(cinergyt2);
- return err;
- }
-
- cinergyt2->demux.priv = cinergyt2;
- cinergyt2->demux.filternum = 256;
- cinergyt2->demux.feednum = 256;
- cinergyt2->demux.start_feed = cinergyt2_start_feed;
- cinergyt2->demux.stop_feed = cinergyt2_stop_feed;
- cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING |
- DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING;
-
- if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) {
- dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err);
- goto bailout;
- }
-
- cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum;
- cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx;
- cinergyt2->dmxdev.capabilities = 0;
-
- if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) {
- dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err);
- goto bailout;
- }
-
- if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx))
- dprintk(1, "dvb_net_init() failed!\n");
-
- dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev,
- &cinergyt2_fe_template, cinergyt2,
- DVB_DEVICE_FRONTEND);
-
- err = cinergyt2_register_rc(cinergyt2);
- if (err)
- goto bailout;
-
- return 0;
-
-bailout:
- dvb_net_release(&cinergyt2->dvbnet);
- dvb_dmxdev_release(&cinergyt2->dmxdev);
- dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_adapter(&cinergyt2->adapter);
- cinergyt2_free_stream_urbs(cinergyt2);
- kfree(cinergyt2);
- return -ENOMEM;
-}
-
-static void cinergyt2_disconnect (struct usb_interface *intf)
-{
- struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
- cinergyt2_unregister_rc(cinergyt2);
- cancel_rearming_delayed_work(&cinergyt2->query_work);
- wake_up_interruptible(&cinergyt2->poll_wq);
-
- cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
- cinergyt2->disconnect_pending = 1;
-
- if (!atomic_read(&cinergyt2->inuse))
- cinergyt2_unregister(cinergyt2);
-}
-
-static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
-{
- struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
- if (cinergyt2->disconnect_pending)
- return -EAGAIN;
- if (mutex_lock_interruptible(&cinergyt2->wq_sem))
- return -ERESTARTSYS;
-
- cinergyt2_suspend_rc(cinergyt2);
- cancel_rearming_delayed_work(&cinergyt2->query_work);
-
- mutex_lock(&cinergyt2->sem);
- if (cinergyt2->streaming)
- cinergyt2_stop_stream_xfer(cinergyt2);
- cinergyt2_sleep(cinergyt2, 1);
- mutex_unlock(&cinergyt2->sem);
-
- mutex_unlock(&cinergyt2->wq_sem);
-
- return 0;
-}
-
-static int cinergyt2_resume (struct usb_interface *intf)
-{
- struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- int err = -EAGAIN;
-
- if (cinergyt2->disconnect_pending)
- goto out;
- err = mutex_lock_interruptible(&cinergyt2->wq_sem);
- if (err)
- goto out;
-
- err = mutex_lock_interruptible(&cinergyt2->sem);
- if (err)
- goto out_unlock1;
-
- if (!cinergyt2->sleeping) {
- cinergyt2_sleep(cinergyt2, 0);
- cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0);
- if (cinergyt2->streaming)
- cinergyt2_start_stream_xfer(cinergyt2);
- schedule_delayed_work(&cinergyt2->query_work, HZ/2);
- }
-
- cinergyt2_resume_rc(cinergyt2);
-
- mutex_unlock(&cinergyt2->sem);
-out_unlock1:
- mutex_unlock(&cinergyt2->wq_sem);
-out:
- return err;
-}
-
-static const struct usb_device_id cinergyt2_table [] __devinitdata = {
- { USB_DEVICE(0x0ccd, 0x0038) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(usb, cinergyt2_table);
-
-static struct usb_driver cinergyt2_driver = {
- .name = "cinergyT2",
- .probe = cinergyt2_probe,
- .disconnect = cinergyt2_disconnect,
- .suspend = cinergyt2_suspend,
- .resume = cinergyt2_resume,
- .id_table = cinergyt2_table
-};
-
-static int __init cinergyt2_init (void)
-{
- int err;
-
- if ((err = usb_register(&cinergyt2_driver)) < 0)
- dprintk(1, "usb_register() failed! (err %i)\n", err);
-
- return err;
-}
-
-static void __exit cinergyt2_exit (void)
-{
- usb_deregister(&cinergyt2_driver);
-}
-
-module_init (cinergyt2_init);
-module_exit (cinergyt2_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
new file mode 100644
index 00000000000..1332301ef3a
--- /dev/null
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -0,0 +1,18 @@
+config DVB_DM1105
+ tristate "SDMC DM1105 based PCI cards"
+ depends on DVB_CORE && PCI && I2C
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_STV0299 if !DVB_FE_CUSTOMISE
+ select DVB_STV0288 if !DVB_FE_CUSTOMISE
+ select DVB_STB6000 if !DVB_FE_CUSTOMISE
+ select DVB_CX24116 if !DVB_FE_CUSTOMISE
+ select DVB_SI21XX if !DVB_FE_CUSTOMISE
+ help
+ Support for cards based on the SDMC DM1105 PCI chip like
+ DvbWorld 2002
+
+ Since these cards have no MPEG decoder onboard, they transmit
+ only compressed MPEG data over the PCI bus, so you need
+ an external software decoder to watch TV on your computer.
+
+ Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
new file mode 100644
index 00000000000..8ac28b0546a
--- /dev/null
+++ b/drivers/media/dvb/dm1105/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_DM1105) += dm1105.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
new file mode 100644
index 00000000000..14e627ef646
--- /dev/null
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -0,0 +1,923 @@
+/*
+ * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip
+ *
+ * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/input.h>
+#include <media/ir-common.h>
+
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+#include "dvb-pll.h"
+
+#include "stv0299.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "si21xx.h"
+#include "cx24116.h"
+#include "z0194a.h"
+
+/* ----------------------------------------------- */
+/*
+ * PCI ID's
+ */
+#ifndef PCI_VENDOR_ID_TRIGEM
+#define PCI_VENDOR_ID_TRIGEM 0x109f
+#endif
+#ifndef PCI_DEVICE_ID_DM1105
+#define PCI_DEVICE_ID_DM1105 0x036f
+#endif
+#ifndef PCI_DEVICE_ID_DW2002
+#define PCI_DEVICE_ID_DW2002 0x2002
+#endif
+#ifndef PCI_DEVICE_ID_DW2004
+#define PCI_DEVICE_ID_DW2004 0x2004
+#endif
+/* ----------------------------------------------- */
+/* sdmc dm1105 registers */
+
+/* TS Control */
+#define DM1105_TSCTR 0x00
+#define DM1105_DTALENTH 0x04
+
+/* GPIO Interface */
+#define DM1105_GPIOVAL 0x08
+#define DM1105_GPIOCTR 0x0c
+
+/* PID serial number */
+#define DM1105_PIDN 0x10
+
+/* Odd-even secret key select */
+#define DM1105_CWSEL 0x14
+
+/* Host Command Interface */
+#define DM1105_HOST_CTR 0x18
+#define DM1105_HOST_AD 0x1c
+
+/* PCI Interface */
+#define DM1105_CR 0x30
+#define DM1105_RST 0x34
+#define DM1105_STADR 0x38
+#define DM1105_RLEN 0x3c
+#define DM1105_WRP 0x40
+#define DM1105_INTCNT 0x44
+#define DM1105_INTMAK 0x48
+#define DM1105_INTSTS 0x4c
+
+/* CW Value */
+#define DM1105_ODD 0x50
+#define DM1105_EVEN 0x58
+
+/* PID Value */
+#define DM1105_PID 0x60
+
+/* IR Control */
+#define DM1105_IRCTR 0x64
+#define DM1105_IRMODE 0x68
+#define DM1105_SYSTEMCODE 0x6c
+#define DM1105_IRCODE 0x70
+
+/* Unknown Values */
+#define DM1105_ENCRYPT 0x74
+#define DM1105_VER 0x7c
+
+/* I2C Interface */
+#define DM1105_I2CCTR 0x80
+#define DM1105_I2CSTS 0x81
+#define DM1105_I2CDAT 0x82
+#define DM1105_I2C_RA 0x83
+/* ----------------------------------------------- */
+/* Interrupt Mask Bits */
+
+#define INTMAK_TSIRQM 0x01
+#define INTMAK_HIRQM 0x04
+#define INTMAK_IRM 0x08
+#define INTMAK_ALLMASK (INTMAK_TSIRQM | \
+ INTMAK_HIRQM | \
+ INTMAK_IRM)
+#define INTMAK_NONEMASK 0x00
+
+/* Interrupt Status Bits */
+#define INTSTS_TSIRQ 0x01
+#define INTSTS_HIRQ 0x04
+#define INTSTS_IR 0x08
+
+/* IR Control Bits */
+#define DM1105_IR_EN 0x01
+#define DM1105_SYS_CHK 0x02
+#define DM1105_REP_FLG 0x08
+
+/* EEPROM addr */
+#define IIC_24C01_addr 0xa0
+/* Max board count */
+#define DM1105_MAX 0x04
+
+#define DRIVER_NAME "dm1105"
+
+#define DM1105_DMA_PACKETS 47
+#define DM1105_DMA_PACKET_LENGTH (128*4)
+#define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS)
+
+/* GPIO's for LNB power control */
+#define DM1105_LNB_MASK 0x00000000
+#define DM1105_LNB_13V 0x00010100
+#define DM1105_LNB_18V 0x00000100
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static u16 ir_codes_dm1105_nec[128] = {
+ [0x0a] = KEY_Q, /*power*/
+ [0x0c] = KEY_M, /*mute*/
+ [0x11] = KEY_1,
+ [0x12] = KEY_2,
+ [0x13] = KEY_3,
+ [0x14] = KEY_4,
+ [0x15] = KEY_5,
+ [0x16] = KEY_6,
+ [0x17] = KEY_7,
+ [0x18] = KEY_8,
+ [0x19] = KEY_9,
+ [0x10] = KEY_0,
+ [0x1c] = KEY_PAGEUP, /*ch+*/
+ [0x0f] = KEY_PAGEDOWN, /*ch-*/
+ [0x1a] = KEY_O, /*vol+*/
+ [0x0e] = KEY_Z, /*vol-*/
+ [0x04] = KEY_R, /*rec*/
+ [0x09] = KEY_D, /*fav*/
+ [0x08] = KEY_BACKSPACE, /*rewind*/
+ [0x07] = KEY_A, /*fast*/
+ [0x0b] = KEY_P, /*pause*/
+ [0x02] = KEY_ESC, /*cancel*/
+ [0x03] = KEY_G, /*tab*/
+ [0x00] = KEY_UP, /*up*/
+ [0x1f] = KEY_ENTER, /*ok*/
+ [0x01] = KEY_DOWN, /*down*/
+ [0x05] = KEY_C, /*cap*/
+ [0x06] = KEY_S, /*stop*/
+ [0x40] = KEY_F, /*full*/
+ [0x1e] = KEY_W, /*tvmode*/
+ [0x1b] = KEY_B, /*recall*/
+};
+
+/* infrared remote control */
+struct infrared {
+ u16 key_map[128];
+ struct input_dev *input_dev;
+ char input_phys[32];
+ struct tasklet_struct ir_tasklet;
+ u32 ir_command;
+};
+
+struct dm1105dvb {
+ /* pci */
+ struct pci_dev *pdev;
+ u8 __iomem *io_mem;
+
+ /* ir */
+ struct infrared ir;
+
+ /* dvb */
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+ struct dmxdev dmxdev;
+ struct dvb_adapter dvb_adapter;
+ struct dvb_demux demux;
+ struct dvb_frontend *fe;
+ struct dvb_net dvbnet;
+ unsigned int full_ts_users;
+
+ /* i2c */
+ struct i2c_adapter i2c_adap;
+
+ /* dma */
+ dma_addr_t dma_addr;
+ unsigned char *ts_buf;
+ u32 wrp;
+ u32 buffer_size;
+ unsigned int PacketErrorCount;
+ unsigned int dmarst;
+ spinlock_t lock;
+
+};
+
+#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
+
+static struct dm1105dvb *dm1105dvb_local;
+
+static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct dm1105dvb *dm1105dvb ;
+
+ int addr, rc, i, j, k, len, byte, data;
+ u8 status;
+
+ dm1105dvb = i2c_adap->algo_data;
+ for (i = 0; i < num; i++) {
+ outb(0x00, dm_io_mem(DM1105_I2CCTR));
+ if (msgs[i].flags & I2C_M_RD) {
+ /* read bytes */
+ addr = msgs[i].addr << 1;
+ addr |= 1;
+ outb(addr, dm_io_mem(DM1105_I2CDAT));
+ for (byte = 0; byte < msgs[i].len; byte++)
+ outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1));
+
+ outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+ for (j = 0; j < 55; j++) {
+ mdelay(10);
+ status = inb(dm_io_mem(DM1105_I2CSTS));
+ if ((status & 0xc0) == 0x40)
+ break;
+ }
+ if (j >= 55)
+ return -1;
+
+ for (byte = 0; byte < msgs[i].len; byte++) {
+ rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1));
+ if (rc < 0)
+ goto err;
+ msgs[i].buf[byte] = rc;
+ }
+ } else {
+ if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
+ /* prepaired for cx24116 firmware */
+ /* Write in small blocks */
+ len = msgs[i].len - 1;
+ k = 1;
+ do {
+ outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT));
+ outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1));
+ for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
+ data = msgs[i].buf[k+byte];
+ outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2));
+ }
+ outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR));
+ for (j = 0; j < 25; j++) {
+ mdelay(10);
+ status = inb(dm_io_mem(DM1105_I2CSTS));
+ if ((status & 0xc0) == 0x40)
+ break;
+ }
+
+ if (j >= 25)
+ return -1;
+
+ k += 48;
+ len -= 48;
+ } while (len > 0);
+ } else {
+ /* write bytes */
+ outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT));
+ for (byte = 0; byte < msgs[i].len; byte++) {
+ data = msgs[i].buf[byte];
+ outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1));
+ }
+ outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+ for (j = 0; j < 25; j++) {
+ mdelay(10);
+ status = inb(dm_io_mem(DM1105_I2CSTS));
+ if ((status & 0xc0) == 0x40)
+ break;
+ }
+
+ if (j >= 25)
+ return -1;
+ }
+ }
+ }
+ return num;
+ err:
+ return rc;
+}
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dm1105_algo = {
+ .master_xfer = dm1105_i2c_xfer,
+ .functionality = functionality,
+};
+
+static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed)
+{
+ return container_of(feed->demux, struct dm1105dvb, demux);
+}
+
+static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
+{
+ return container_of(fe->dvb, struct dm1105dvb, dvb_adapter);
+}
+
+static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+
+ if (voltage == SEC_VOLTAGE_18) {
+ outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
+ outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
+ } else {
+ /*LNB ON-13V by default!*/
+ outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
+ outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
+ }
+
+ return 0;
+}
+
+static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb)
+{
+ outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR));
+}
+
+static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
+{
+ dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
+
+ return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr);
+}
+
+static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
+{
+ pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
+}
+
+static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
+{
+ outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
+ outb(1, dm_io_mem(DM1105_CR));
+}
+
+static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb)
+{
+ outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK));
+ outb(0, dm_io_mem(DM1105_CR));
+}
+
+static int dm1105dvb_start_feed(struct dvb_demux_feed *f)
+{
+ struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+
+ if (dm1105dvb->full_ts_users++ == 0)
+ dm1105dvb_enable_irqs(dm1105dvb);
+
+ return 0;
+}
+
+static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
+{
+ struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+
+ if (--dm1105dvb->full_ts_users == 0)
+ dm1105dvb_disable_irqs(dm1105dvb);
+
+ return 0;
+}
+
+/* ir tasklet */
+static void dm1105_emit_key(unsigned long parm)
+{
+ struct infrared *ir = (struct infrared *) parm;
+ u32 ircom = ir->ir_command;
+ u8 data;
+ u16 keycode;
+
+ data = (ircom >> 8) & 0x7f;
+
+ input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
+ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
+ keycode = ir->key_map[data];
+
+ if (!keycode)
+ return;
+
+ input_event(ir->input_dev, EV_KEY, keycode, 1);
+ input_sync(ir->input_dev);
+ input_event(ir->input_dev, EV_KEY, keycode, 0);
+ input_sync(ir->input_dev);
+
+}
+
+static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
+{
+ struct dm1105dvb *dm1105dvb = dev_id;
+ unsigned int piece;
+ unsigned int nbpackets;
+ u32 command;
+ u32 nextwrp;
+ u32 oldwrp;
+
+ /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
+ unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
+ outb(intsts, dm_io_mem(DM1105_INTSTS));
+
+ switch (intsts) {
+ case INTSTS_TSIRQ:
+ case (INTSTS_TSIRQ | INTSTS_IR):
+ nextwrp = inl(dm_io_mem(DM1105_WRP)) -
+ inl(dm_io_mem(DM1105_STADR)) ;
+ oldwrp = dm1105dvb->wrp;
+ spin_lock(&dm1105dvb->lock);
+ if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
+ (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
+ (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+ dm1105dvb->PacketErrorCount++;
+ /* bad packet found */
+ if ((dm1105dvb->PacketErrorCount >= 2) &&
+ (dm1105dvb->dmarst == 0)) {
+ outb(1, dm_io_mem(DM1105_RST));
+ dm1105dvb->wrp = 0;
+ dm1105dvb->PacketErrorCount = 0;
+ dm1105dvb->dmarst = 0;
+ spin_unlock(&dm1105dvb->lock);
+ return IRQ_HANDLED;
+ }
+ }
+ if (nextwrp < oldwrp) {
+ piece = dm1105dvb->buffer_size - oldwrp;
+ memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
+ nbpackets = (piece + nextwrp)/188;
+ } else {
+ nbpackets = (nextwrp - oldwrp)/188;
+ }
+ dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
+ dm1105dvb->wrp = nextwrp;
+ spin_unlock(&dm1105dvb->lock);
+ break;
+ case INTSTS_IR:
+ command = inl(dm_io_mem(DM1105_IRCODE));
+ if (ir_debug)
+ printk("dm1105: received byte 0x%04x\n", command);
+
+ dm1105dvb->ir.ir_command = command;
+ tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
+ break;
+ }
+ return IRQ_HANDLED;
+
+
+}
+
+/* register with input layer */
+static void input_register_keys(struct infrared *ir)
+{
+ int i;
+
+ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
+
+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++)
+ set_bit(ir->key_map[i], ir->input_dev->keybit);
+
+ ir->input_dev->keycode = ir->key_map;
+ ir->input_dev->keycodesize = sizeof(ir->key_map[0]);
+ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
+}
+
+int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ dm1105dvb_local = dm1105;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ dm1105->ir.input_dev = input_dev;
+ snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
+ "pci-%s/ir0", pci_name(dm1105->pdev));
+
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->name = "DVB on-card IR receiver";
+
+ input_dev->phys = dm1105->ir.input_phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 2;
+ if (dm1105->pdev->subsystem_vendor) {
+ input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
+ input_dev->id.product = dm1105->pdev->subsystem_device;
+ } else {
+ input_dev->id.vendor = dm1105->pdev->vendor;
+ input_dev->id.product = dm1105->pdev->device;
+ }
+ input_dev->dev.parent = &dm1105->pdev->dev;
+ /* initial keymap */
+ memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map);
+ input_register_keys(&dm1105->ir);
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+
+ tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
+
+ return 0;
+}
+
+
+void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
+{
+ tasklet_kill(&dm1105->ir.ir_tasklet);
+ input_unregister_device(dm1105->ir.input_dev);
+
+}
+
+static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
+{
+ dm1105dvb_disable_irqs(dm1105dvb);
+
+ outb(0, dm_io_mem(DM1105_HOST_CTR));
+
+ /*DATALEN 188,*/
+ outb(188, dm_io_mem(DM1105_DTALENTH));
+ /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
+ outw(0xc10a, dm_io_mem(DM1105_TSCTR));
+
+ /* map DMA and set address */
+ dm1105dvb_dma_map(dm1105dvb);
+ dm1105dvb_set_dma_addr(dm1105dvb);
+ /* big buffer */
+ outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN));
+ outb(47, dm_io_mem(DM1105_INTCNT));
+
+ /* IR NEC mode enable */
+ outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR));
+ outb(0, dm_io_mem(DM1105_IRMODE));
+ outw(0, dm_io_mem(DM1105_SYSTEMCODE));
+
+ return 0;
+}
+
+static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
+{
+ dm1105dvb_disable_irqs(dm1105dvb);
+
+ /* IR disable */
+ outb(0, dm_io_mem(DM1105_IRCTR));
+ outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK));
+
+ dm1105dvb_dma_unmap(dm1105dvb);
+}
+
+static struct stv0299_config sharp_z0194a_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
+static struct stv0288_config earda_config = {
+ .demod_address = 0x68,
+ .min_delay_ms = 100,
+};
+
+static struct si21xx_config serit_config = {
+ .demod_address = 0x68,
+ .min_delay_ms = 100,
+
+};
+
+static struct cx24116_config serit_sp2633_config = {
+ .demod_address = 0x55,
+};
+
+static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
+{
+ int ret;
+
+ switch (dm1105dvb->pdev->subsystem_device) {
+ case PCI_DEVICE_ID_DW2002:
+ dm1105dvb->fe = dvb_attach(
+ stv0299_attach, &sharp_z0194a_config,
+ &dm1105dvb->i2c_adap);
+
+ if (dm1105dvb->fe) {
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+ dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
+ &dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+ }
+
+ if (!dm1105dvb->fe) {
+ dm1105dvb->fe = dvb_attach(
+ stv0288_attach, &earda_config,
+ &dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe) {
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+ dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
+ &dm1105dvb->i2c_adap);
+ }
+ }
+
+ if (!dm1105dvb->fe) {
+ dm1105dvb->fe = dvb_attach(
+ si21xx_attach, &serit_config,
+ &dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe)
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+ }
+ break;
+ case PCI_DEVICE_ID_DW2004:
+ dm1105dvb->fe = dvb_attach(
+ cx24116_attach, &serit_sp2633_config,
+ &dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe)
+ dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
+ break;
+ }
+
+ if (!dm1105dvb->fe) {
+ dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n");
+ return -ENODEV;
+ }
+
+ ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe);
+ if (ret < 0) {
+ if (dm1105dvb->fe->ops.release)
+ dm1105dvb->fe->ops.release(dm1105dvb->fe);
+ dm1105dvb->fe = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
+{
+ static u8 command[1] = { 0x28 };
+
+ struct i2c_msg msg[] = {
+ { .addr = IIC_24C01_addr >> 1, .flags = 0,
+ .buf = command, .len = 1 },
+ { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
+ .buf = mac, .len = 6 },
+ };
+
+ dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
+ dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static int __devinit dm1105_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct dm1105dvb *dm1105dvb;
+ struct dvb_adapter *dvb_adapter;
+ struct dvb_demux *dvbdemux;
+ struct dmx_demux *dmx;
+ int ret = -ENOMEM;
+
+ dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
+ if (!dm1105dvb)
+ goto out;
+
+ dm1105dvb->pdev = pdev;
+ dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
+ dm1105dvb->PacketErrorCount = 0;
+ dm1105dvb->dmarst = 0;
+
+ ret = pci_enable_device(pdev);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (ret < 0)
+ goto err_pci_disable_device;
+
+ pci_set_master(pdev);
+
+ ret = pci_request_regions(pdev, DRIVER_NAME);
+ if (ret < 0)
+ goto err_pci_disable_device;
+
+ dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ if (!dm1105dvb->io_mem) {
+ ret = -EIO;
+ goto err_pci_release_regions;
+ }
+
+ spin_lock_init(&dm1105dvb->lock);
+ pci_set_drvdata(pdev, dm1105dvb);
+
+ ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
+ if (ret < 0)
+ goto err_pci_iounmap;
+
+ ret = dm1105dvb_hw_init(dm1105dvb);
+ if (ret < 0)
+ goto err_free_irq;
+
+ /* i2c */
+ i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
+ strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME);
+ dm1105dvb->i2c_adap.owner = THIS_MODULE;
+ dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+ dm1105dvb->i2c_adap.dev.parent = &pdev->dev;
+ dm1105dvb->i2c_adap.algo = &dm1105_algo;
+ dm1105dvb->i2c_adap.algo_data = dm1105dvb;
+ ret = i2c_add_adapter(&dm1105dvb->i2c_adap);
+
+ if (ret < 0)
+ goto err_dm1105dvb_hw_exit;
+
+ /* dvb */
+ ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME,
+ THIS_MODULE, &pdev->dev, adapter_nr);
+ if (ret < 0)
+ goto err_i2c_del_adapter;
+
+ dvb_adapter = &dm1105dvb->dvb_adapter;
+
+ dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac);
+
+ dvbdemux = &dm1105dvb->demux;
+ dvbdemux->filternum = 256;
+ dvbdemux->feednum = 256;
+ dvbdemux->start_feed = dm1105dvb_start_feed;
+ dvbdemux->stop_feed = dm1105dvb_stop_feed;
+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+ DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+ ret = dvb_dmx_init(dvbdemux);
+ if (ret < 0)
+ goto err_dvb_unregister_adapter;
+
+ dmx = &dvbdemux->dmx;
+ dm1105dvb->dmxdev.filternum = 256;
+ dm1105dvb->dmxdev.demux = dmx;
+ dm1105dvb->dmxdev.capabilities = 0;
+
+ ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter);
+ if (ret < 0)
+ goto err_dvb_dmx_release;
+
+ dm1105dvb->hw_frontend.source = DMX_FRONTEND_0;
+
+ ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend);
+ if (ret < 0)
+ goto err_dvb_dmxdev_release;
+
+ dm1105dvb->mem_frontend.source = DMX_MEMORY_FE;
+
+ ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend);
+ if (ret < 0)
+ goto err_remove_hw_frontend;
+
+ ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend);
+ if (ret < 0)
+ goto err_remove_mem_frontend;
+
+ ret = frontend_init(dm1105dvb);
+ if (ret < 0)
+ goto err_disconnect_frontend;
+
+ dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
+ dm1105_ir_init(dm1105dvb);
+out:
+ return ret;
+
+err_disconnect_frontend:
+ dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+ dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
+err_remove_hw_frontend:
+ dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
+err_dvb_dmxdev_release:
+ dvb_dmxdev_release(&dm1105dvb->dmxdev);
+err_dvb_dmx_release:
+ dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+ dvb_unregister_adapter(dvb_adapter);
+err_i2c_del_adapter:
+ i2c_del_adapter(&dm1105dvb->i2c_adap);
+err_dm1105dvb_hw_exit:
+ dm1105dvb_hw_exit(dm1105dvb);
+err_free_irq:
+ free_irq(pdev->irq, dm1105dvb);
+err_pci_iounmap:
+ pci_iounmap(pdev, dm1105dvb->io_mem);
+err_pci_release_regions:
+ pci_release_regions(pdev);
+err_pci_disable_device:
+ pci_disable_device(pdev);
+err_kfree:
+ pci_set_drvdata(pdev, NULL);
+ kfree(dm1105dvb);
+ goto out;
+}
+
+static void __devexit dm1105_remove(struct pci_dev *pdev)
+{
+ struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev);
+ struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter;
+ struct dvb_demux *dvbdemux = &dm1105dvb->demux;
+ struct dmx_demux *dmx = &dvbdemux->dmx;
+
+ dm1105_ir_exit(dm1105dvb);
+ dmx->close(dmx);
+ dvb_net_release(&dm1105dvb->dvbnet);
+ if (dm1105dvb->fe)
+ dvb_unregister_frontend(dm1105dvb->fe);
+
+ dmx->disconnect_frontend(dmx);
+ dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
+ dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
+ dvb_dmxdev_release(&dm1105dvb->dmxdev);
+ dvb_dmx_release(dvbdemux);
+ dvb_unregister_adapter(dvb_adapter);
+ if (&dm1105dvb->i2c_adap)
+ i2c_del_adapter(&dm1105dvb->i2c_adap);
+
+ dm1105dvb_hw_exit(dm1105dvb);
+ synchronize_irq(pdev->irq);
+ free_irq(pdev->irq, dm1105dvb);
+ pci_iounmap(pdev, dm1105dvb->io_mem);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ kfree(dm1105dvb);
+}
+
+static struct pci_device_id dm1105_id_table[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_TRIGEM,
+ .device = PCI_DEVICE_ID_DM1105,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_DEVICE_ID_DW2002,
+ }, {
+ .vendor = PCI_VENDOR_ID_TRIGEM,
+ .device = PCI_DEVICE_ID_DM1105,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_DEVICE_ID_DW2004,
+ }, {
+ /* empty */
+ },
+};
+
+MODULE_DEVICE_TABLE(pci, dm1105_id_table);
+
+static struct pci_driver dm1105_driver = {
+ .name = DRIVER_NAME,
+ .id_table = dm1105_id_table,
+ .probe = dm1105_probe,
+ .remove = __devexit_p(dm1105_remove),
+};
+
+static int __init dm1105_init(void)
+{
+ return pci_register_driver(&dm1105_driver);
+}
+
+static void __exit dm1105_exit(void)
+{
+ pci_unregister_driver(&dm1105_driver);
+}
+
+module_init(dm1105_init);
+module_exit(dm1105_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_DESCRIPTION("SDMC DM1105 DVB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 1cf9fcb6f51..0c733c66a44 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
enum dmx_success success)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
+ unsigned long flags;
int ret;
if (dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
- spin_lock(&dmxdevfilter->dev->lock);
+ spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
return 0;
}
del_timer(&dmxdevfilter->timer);
@@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
}
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE;
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
@@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
+ unsigned long flags;
int ret;
- spin_lock(&dmxdevfilter->dev->lock);
+ spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
return 0;
}
@@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
else
buffer = &dmxdevfilter->dev->dvr_buffer;
if (buffer->error) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&buffer->queue);
return 0;
}
@@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
dvb_ringbuffer_flush(buffer);
buffer->error = ret;
}
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&buffer->queue);
return 0;
}
@@ -641,7 +643,6 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
struct timespec timeout = { 0 };
struct dmx_pes_filter_params *para = &filter->params.pes;
dmx_output_t otype;
- int ret;
int ts_type;
enum dmx_ts_pes ts_pes;
struct dmx_ts_feed **tsfeed = &filter->feed.ts;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 8e5dd7b1f03..98ee16773ff 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1032,7 +1032,7 @@ static int dvb_ca_en50221_thread(void *data)
/* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
- int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
@@ -1089,7 +1089,7 @@ static int dvb_ca_en50221_thread(void *data)
/* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
- int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index e2eca0b1fe7..a2c1fd5d2f6 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -399,7 +399,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
- spin_lock(&demux->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&demux->lock, flags);
while (count--) {
if (buf[0] == 0x47)
@@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
buf += 188;
}
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
+ unsigned long flags;
int p = 0, i, j;
- spin_lock(&demux->lock);
+ spin_lock_irqsave(&demux->lock, flags);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
+ unsigned long flags;
int p = 0, i, j;
u8 tmppack[188];
- spin_lock(&demux->lock);
+ spin_lock_irqsave(&demux->lock, flags);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -500,7 +504,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8cbdb218952..5689d1f1d44 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -40,12 +40,14 @@
#include "dvb_frontend.h"
#include "dvbdev.h"
+#include <linux/dvb/version.h>
static int dvb_frontend_debug;
static int dvb_shutdown_timeout;
static int dvb_force_auto_inversion;
static int dvb_override_tune_delay;
static int dvb_powerdown_on_sleep = 1;
+static int dvb_mfe_wait_time = 5;
module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
@@ -57,6 +59,8 @@ module_param(dvb_override_tune_delay, int, 0644);
MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
module_param(dvb_powerdown_on_sleep, int, 0644);
MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
+module_param(dvb_mfe_wait_time, int, 0644);
+MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
#define dprintk if (dvb_frontend_debug) printk
@@ -211,8 +215,9 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
static void dvb_frontend_init(struct dvb_frontend *fe)
{
- dprintk ("DVB: initialising frontend %i (%s)...\n",
+ dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
fe->dvb->num,
+ fe->id,
fe->ops.info.name);
if (fe->ops.init)
@@ -685,7 +690,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
mb();
fe_thread = kthread_run(dvb_frontend_thread, fe,
- "kdvb-fe-%i", fe->dvb->num);
+ "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
if (IS_ERR(fe_thread)) {
ret = PTR_ERR(fe_thread);
printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
@@ -709,8 +714,8 @@ static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
if (*freq_min == 0 || *freq_max == 0)
- printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n",
- fe->dvb->num);
+ printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
+ fe->dvb->num,fe->id);
}
static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
@@ -723,8 +728,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
if ((freq_min && parms->frequency < freq_min) ||
(freq_max && parms->frequency > freq_max)) {
- printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n",
- fe->dvb->num, parms->frequency, freq_min, freq_max);
+ printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
+ fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max);
return -EINVAL;
}
@@ -734,8 +739,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
(fe->ops.info.symbol_rate_max &&
parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) {
- printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
- fe->dvb->num, parms->u.qpsk.symbol_rate,
+ printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+ fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate,
fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
return -EINVAL;
}
@@ -745,8 +750,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
(fe->ops.info.symbol_rate_max &&
parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) {
- printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
- fe->dvb->num, parms->u.qam.symbol_rate,
+ printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+ fe->dvb->num, fe->id, parms->u.qam.symbol_rate,
fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
return -EINVAL;
}
@@ -755,6 +760,529 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
return 0;
}
+struct dtv_cmds_h dtv_cmds[] = {
+ [DTV_TUNE] = {
+ .name = "DTV_TUNE",
+ .cmd = DTV_TUNE,
+ .set = 1,
+ },
+ [DTV_CLEAR] = {
+ .name = "DTV_CLEAR",
+ .cmd = DTV_CLEAR,
+ .set = 1,
+ },
+
+ /* Set */
+ [DTV_FREQUENCY] = {
+ .name = "DTV_FREQUENCY",
+ .cmd = DTV_FREQUENCY,
+ .set = 1,
+ },
+ [DTV_BANDWIDTH_HZ] = {
+ .name = "DTV_BANDWIDTH_HZ",
+ .cmd = DTV_BANDWIDTH_HZ,
+ .set = 1,
+ },
+ [DTV_MODULATION] = {
+ .name = "DTV_MODULATION",
+ .cmd = DTV_MODULATION,
+ .set = 1,
+ },
+ [DTV_INVERSION] = {
+ .name = "DTV_INVERSION",
+ .cmd = DTV_INVERSION,
+ .set = 1,
+ },
+ [DTV_DISEQC_MASTER] = {
+ .name = "DTV_DISEQC_MASTER",
+ .cmd = DTV_DISEQC_MASTER,
+ .set = 1,
+ .buffer = 1,
+ },
+ [DTV_SYMBOL_RATE] = {
+ .name = "DTV_SYMBOL_RATE",
+ .cmd = DTV_SYMBOL_RATE,
+ .set = 1,
+ },
+ [DTV_INNER_FEC] = {
+ .name = "DTV_INNER_FEC",
+ .cmd = DTV_INNER_FEC,
+ .set = 1,
+ },
+ [DTV_VOLTAGE] = {
+ .name = "DTV_VOLTAGE",
+ .cmd = DTV_VOLTAGE,
+ .set = 1,
+ },
+ [DTV_TONE] = {
+ .name = "DTV_TONE",
+ .cmd = DTV_TONE,
+ .set = 1,
+ },
+ [DTV_PILOT] = {
+ .name = "DTV_PILOT",
+ .cmd = DTV_PILOT,
+ .set = 1,
+ },
+ [DTV_ROLLOFF] = {
+ .name = "DTV_ROLLOFF",
+ .cmd = DTV_ROLLOFF,
+ .set = 1,
+ },
+ [DTV_DELIVERY_SYSTEM] = {
+ .name = "DTV_DELIVERY_SYSTEM",
+ .cmd = DTV_DELIVERY_SYSTEM,
+ .set = 1,
+ },
+ [DTV_HIERARCHY] = {
+ .name = "DTV_HIERARCHY",
+ .cmd = DTV_HIERARCHY,
+ .set = 1,
+ },
+ [DTV_CODE_RATE_HP] = {
+ .name = "DTV_CODE_RATE_HP",
+ .cmd = DTV_CODE_RATE_HP,
+ .set = 1,
+ },
+ [DTV_CODE_RATE_LP] = {
+ .name = "DTV_CODE_RATE_LP",
+ .cmd = DTV_CODE_RATE_LP,
+ .set = 1,
+ },
+ [DTV_GUARD_INTERVAL] = {
+ .name = "DTV_GUARD_INTERVAL",
+ .cmd = DTV_GUARD_INTERVAL,
+ .set = 1,
+ },
+ [DTV_TRANSMISSION_MODE] = {
+ .name = "DTV_TRANSMISSION_MODE",
+ .cmd = DTV_TRANSMISSION_MODE,
+ .set = 1,
+ },
+ /* Get */
+ [DTV_DISEQC_SLAVE_REPLY] = {
+ .name = "DTV_DISEQC_SLAVE_REPLY",
+ .cmd = DTV_DISEQC_SLAVE_REPLY,
+ .set = 0,
+ .buffer = 1,
+ },
+ [DTV_API_VERSION] = {
+ .name = "DTV_API_VERSION",
+ .cmd = DTV_API_VERSION,
+ .set = 0,
+ },
+ [DTV_CODE_RATE_HP] = {
+ .name = "DTV_CODE_RATE_HP",
+ .cmd = DTV_CODE_RATE_HP,
+ .set = 0,
+ },
+ [DTV_CODE_RATE_LP] = {
+ .name = "DTV_CODE_RATE_LP",
+ .cmd = DTV_CODE_RATE_LP,
+ .set = 0,
+ },
+ [DTV_GUARD_INTERVAL] = {
+ .name = "DTV_GUARD_INTERVAL",
+ .cmd = DTV_GUARD_INTERVAL,
+ .set = 0,
+ },
+ [DTV_TRANSMISSION_MODE] = {
+ .name = "DTV_TRANSMISSION_MODE",
+ .cmd = DTV_TRANSMISSION_MODE,
+ .set = 0,
+ },
+ [DTV_HIERARCHY] = {
+ .name = "DTV_HIERARCHY",
+ .cmd = DTV_HIERARCHY,
+ .set = 0,
+ },
+};
+
+void dtv_property_dump(struct dtv_property *tvp)
+{
+ int i;
+
+ if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
+ printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n",
+ __func__, tvp->cmd);
+ return;
+ }
+
+ dprintk("%s() tvp.cmd = 0x%08x (%s)\n"
+ ,__func__
+ ,tvp->cmd
+ ,dtv_cmds[ tvp->cmd ].name);
+
+ if(dtv_cmds[ tvp->cmd ].buffer) {
+
+ dprintk("%s() tvp.u.buffer.len = 0x%02x\n"
+ ,__func__
+ ,tvp->u.buffer.len);
+
+ for(i = 0; i < tvp->u.buffer.len; i++)
+ dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
+ ,__func__
+ ,i
+ ,tvp->u.buffer.data[i]);
+
+ } else
+ dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
+}
+
+int is_legacy_delivery_system(fe_delivery_system_t s)
+{
+ if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
+ (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS))
+ return 1;
+
+ return 0;
+}
+
+/* Synchronise the legacy tuning parameters into the cache, so that demodulator
+ * drivers can use a single set_frontend tuning function, regardless of whether
+ * it's being used for the legacy or new API, reducing code and complexity.
+ */
+void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ c->frequency = p->frequency;
+ c->inversion = p->inversion;
+
+ switch (fe->ops.info.type) {
+ case FE_QPSK:
+ c->modulation = QPSK; /* implied for DVB-S in legacy API */
+ c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+ c->symbol_rate = p->u.qpsk.symbol_rate;
+ c->fec_inner = p->u.qpsk.fec_inner;
+ c->delivery_system = SYS_DVBS;
+ break;
+ case FE_QAM:
+ c->symbol_rate = p->u.qam.symbol_rate;
+ c->fec_inner = p->u.qam.fec_inner;
+ c->modulation = p->u.qam.modulation;
+ c->delivery_system = SYS_DVBC_ANNEX_AC;
+ break;
+ case FE_OFDM:
+ if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+ c->bandwidth_hz = 6000000;
+ else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+ c->bandwidth_hz = 7000000;
+ else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ c->bandwidth_hz = 8000000;
+ else
+ /* Including BANDWIDTH_AUTO */
+ c->bandwidth_hz = 0;
+ c->code_rate_HP = p->u.ofdm.code_rate_HP;
+ c->code_rate_LP = p->u.ofdm.code_rate_LP;
+ c->modulation = p->u.ofdm.constellation;
+ c->transmission_mode = p->u.ofdm.transmission_mode;
+ c->guard_interval = p->u.ofdm.guard_interval;
+ c->hierarchy = p->u.ofdm.hierarchy_information;
+ c->delivery_system = SYS_DVBT;
+ break;
+ case FE_ATSC:
+ c->modulation = p->u.vsb.modulation;
+ if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
+ c->delivery_system = SYS_ATSC;
+ else
+ c->delivery_system = SYS_DVBC_ANNEX_B;
+ break;
+ }
+}
+
+/* Ensure the cached values are set correctly in the frontend
+ * legacy tuning structures, for the advanced tuning API.
+ */
+void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_frontend_parameters *p = &fepriv->parameters;
+
+ p->frequency = c->frequency;
+ p->inversion = c->inversion;
+
+ switch (fe->ops.info.type) {
+ case FE_QPSK:
+ dprintk("%s() Preparing QPSK req\n", __func__);
+ p->u.qpsk.symbol_rate = c->symbol_rate;
+ p->u.qpsk.fec_inner = c->fec_inner;
+ c->delivery_system = SYS_DVBS;
+ break;
+ case FE_QAM:
+ dprintk("%s() Preparing QAM req\n", __func__);
+ p->u.qam.symbol_rate = c->symbol_rate;
+ p->u.qam.fec_inner = c->fec_inner;
+ p->u.qam.modulation = c->modulation;
+ c->delivery_system = SYS_DVBC_ANNEX_AC;
+ break;
+ case FE_OFDM:
+ dprintk("%s() Preparing OFDM req\n", __func__);
+ if (c->bandwidth_hz == 6000000)
+ p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ else if (c->bandwidth_hz == 7000000)
+ p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ else if (c->bandwidth_hz == 8000000)
+ p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ else
+ p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+ p->u.ofdm.code_rate_HP = c->code_rate_HP;
+ p->u.ofdm.code_rate_LP = c->code_rate_LP;
+ p->u.ofdm.constellation = c->modulation;
+ p->u.ofdm.transmission_mode = c->transmission_mode;
+ p->u.ofdm.guard_interval = c->guard_interval;
+ p->u.ofdm.hierarchy_information = c->hierarchy;
+ c->delivery_system = SYS_DVBT;
+ break;
+ case FE_ATSC:
+ dprintk("%s() Preparing VSB req\n", __func__);
+ p->u.vsb.modulation = c->modulation;
+ if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
+ c->delivery_system = SYS_ATSC;
+ else
+ c->delivery_system = SYS_DVBC_ANNEX_B;
+ break;
+ }
+}
+
+/* Ensure the cached values are set correctly in the frontend
+ * legacy tuning structures, for the legacy tuning API.
+ */
+void dtv_property_adv_params_sync(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_frontend_parameters *p = &fepriv->parameters;
+
+ p->frequency = c->frequency;
+ p->inversion = c->inversion;
+
+ switch(c->modulation) {
+ case PSK_8:
+ case APSK_16:
+ case APSK_32:
+ case QPSK:
+ p->u.qpsk.symbol_rate = c->symbol_rate;
+ p->u.qpsk.fec_inner = c->fec_inner;
+ break;
+ default:
+ break;
+ }
+
+ if(c->delivery_system == SYS_ISDBT) {
+ /* Fake out a generic DVB-T request so we pass validation in the ioctl */
+ p->frequency = c->frequency;
+ p->inversion = INVERSION_AUTO;
+ p->u.ofdm.constellation = QAM_AUTO;
+ p->u.ofdm.code_rate_HP = FEC_AUTO;
+ p->u.ofdm.code_rate_LP = FEC_AUTO;
+ p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+ p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+ p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+ p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
+ }
+}
+
+void dtv_property_cache_submit(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ /* For legacy delivery systems we don't need the delivery_system to
+ * be specified, but we populate the older structures from the cache
+ * so we can call set_frontend on older drivers.
+ */
+ if(is_legacy_delivery_system(c->delivery_system)) {
+
+ dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation);
+ dtv_property_legacy_params_sync(fe);
+
+ } else {
+ dprintk("%s() adv, modulation = %d\n", __func__, c->modulation);
+
+ /* For advanced delivery systems / modulation types ...
+ * we seed the lecacy dvb_frontend_parameters structure
+ * so that the sanity checking code later in the IOCTL processing
+ * can validate our basic frequency ranges, symbolrates, modulation
+ * etc.
+ */
+ dtv_property_adv_params_sync(fe);
+ }
+}
+
+static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+ unsigned int cmd, void *parg);
+static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+ unsigned int cmd, void *parg);
+
+int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp,
+ struct inode *inode, struct file *file)
+{
+ int r = 0;
+
+ dtv_property_dump(tvp);
+
+ /* Allow the frontend to validate incoming properties */
+ if (fe->ops.get_property)
+ r = fe->ops.get_property(fe, tvp);
+
+ if (r < 0)
+ return r;
+
+ switch(tvp->cmd) {
+ case DTV_FREQUENCY:
+ tvp->u.data = fe->dtv_property_cache.frequency;
+ break;
+ case DTV_MODULATION:
+ tvp->u.data = fe->dtv_property_cache.modulation;
+ break;
+ case DTV_BANDWIDTH_HZ:
+ tvp->u.data = fe->dtv_property_cache.bandwidth_hz;
+ break;
+ case DTV_INVERSION:
+ tvp->u.data = fe->dtv_property_cache.inversion;
+ break;
+ case DTV_SYMBOL_RATE:
+ tvp->u.data = fe->dtv_property_cache.symbol_rate;
+ break;
+ case DTV_INNER_FEC:
+ tvp->u.data = fe->dtv_property_cache.fec_inner;
+ break;
+ case DTV_PILOT:
+ tvp->u.data = fe->dtv_property_cache.pilot;
+ break;
+ case DTV_ROLLOFF:
+ tvp->u.data = fe->dtv_property_cache.rolloff;
+ break;
+ case DTV_DELIVERY_SYSTEM:
+ tvp->u.data = fe->dtv_property_cache.delivery_system;
+ break;
+ case DTV_VOLTAGE:
+ tvp->u.data = fe->dtv_property_cache.voltage;
+ break;
+ case DTV_TONE:
+ tvp->u.data = fe->dtv_property_cache.sectone;
+ break;
+ case DTV_API_VERSION:
+ tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
+ break;
+ case DTV_CODE_RATE_HP:
+ tvp->u.data = fe->dtv_property_cache.code_rate_HP;
+ break;
+ case DTV_CODE_RATE_LP:
+ tvp->u.data = fe->dtv_property_cache.code_rate_LP;
+ break;
+ case DTV_GUARD_INTERVAL:
+ tvp->u.data = fe->dtv_property_cache.guard_interval;
+ break;
+ case DTV_TRANSMISSION_MODE:
+ tvp->u.data = fe->dtv_property_cache.transmission_mode;
+ break;
+ case DTV_HIERARCHY:
+ tvp->u.data = fe->dtv_property_cache.hierarchy;
+ break;
+ default:
+ r = -1;
+ }
+
+ return r;
+}
+
+int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
+ struct inode *inode, struct file *file)
+{
+ int r = 0;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ dtv_property_dump(tvp);
+
+ /* Allow the frontend to validate incoming properties */
+ if (fe->ops.set_property)
+ r = fe->ops.set_property(fe, tvp);
+
+ if (r < 0)
+ return r;
+
+ switch(tvp->cmd) {
+ case DTV_CLEAR:
+ /* Reset a cache of data specific to the frontend here. This does
+ * not effect hardware.
+ */
+ dprintk("%s() Flushing property cache\n", __func__);
+ memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties));
+ fe->dtv_property_cache.state = tvp->cmd;
+ fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
+ break;
+ case DTV_TUNE:
+ /* interpret the cache of data, build either a traditional frontend
+ * tunerequest so we can pass validation in the FE_SET_FRONTEND
+ * ioctl.
+ */
+ fe->dtv_property_cache.state = tvp->cmd;
+ dprintk("%s() Finalised property cache\n", __func__);
+ dtv_property_cache_submit(fe);
+
+ r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
+ &fepriv->parameters);
+ break;
+ case DTV_FREQUENCY:
+ fe->dtv_property_cache.frequency = tvp->u.data;
+ break;
+ case DTV_MODULATION:
+ fe->dtv_property_cache.modulation = tvp->u.data;
+ break;
+ case DTV_BANDWIDTH_HZ:
+ fe->dtv_property_cache.bandwidth_hz = tvp->u.data;
+ break;
+ case DTV_INVERSION:
+ fe->dtv_property_cache.inversion = tvp->u.data;
+ break;
+ case DTV_SYMBOL_RATE:
+ fe->dtv_property_cache.symbol_rate = tvp->u.data;
+ break;
+ case DTV_INNER_FEC:
+ fe->dtv_property_cache.fec_inner = tvp->u.data;
+ break;
+ case DTV_PILOT:
+ fe->dtv_property_cache.pilot = tvp->u.data;
+ break;
+ case DTV_ROLLOFF:
+ fe->dtv_property_cache.rolloff = tvp->u.data;
+ break;
+ case DTV_DELIVERY_SYSTEM:
+ fe->dtv_property_cache.delivery_system = tvp->u.data;
+ break;
+ case DTV_VOLTAGE:
+ fe->dtv_property_cache.voltage = tvp->u.data;
+ r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE,
+ (void *)fe->dtv_property_cache.voltage);
+ break;
+ case DTV_TONE:
+ fe->dtv_property_cache.sectone = tvp->u.data;
+ r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE,
+ (void *)fe->dtv_property_cache.sectone);
+ break;
+ case DTV_CODE_RATE_HP:
+ fe->dtv_property_cache.code_rate_HP = tvp->u.data;
+ break;
+ case DTV_CODE_RATE_LP:
+ fe->dtv_property_cache.code_rate_LP = tvp->u.data;
+ break;
+ case DTV_GUARD_INTERVAL:
+ fe->dtv_property_cache.guard_interval = tvp->u.data;
+ break;
+ case DTV_TRANSMISSION_MODE:
+ fe->dtv_property_cache.transmission_mode = tvp->u.data;
+ break;
+ case DTV_HIERARCHY:
+ fe->dtv_property_cache.hierarchy = tvp->u.data;
+ break;
+ default:
+ r = -1;
+ }
+
+ return r;
+}
+
static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
@@ -776,6 +1304,112 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
if (down_interruptible (&fepriv->sem))
return -ERESTARTSYS;
+ if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
+ err = dvb_frontend_ioctl_properties(inode, file, cmd, parg);
+ else {
+ fe->dtv_property_cache.state = DTV_UNDEFINED;
+ err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg);
+ }
+
+ up(&fepriv->sem);
+ return err;
+}
+
+static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+ unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_frontend *fe = dvbdev->priv;
+ int err = 0;
+
+ struct dtv_properties *tvps = NULL;
+ struct dtv_property *tvp = NULL;
+ int i;
+
+ dprintk("%s\n", __func__);
+
+ if(cmd == FE_SET_PROPERTY) {
+ tvps = (struct dtv_properties __user *)parg;
+
+ dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+ dprintk("%s() properties.props = %p\n", __func__, tvps->props);
+
+ /* Put an arbitrary limit on the number of messages that can
+ * be sent at once */
+ if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+ return -EINVAL;
+
+ tvp = (struct dtv_property *) kmalloc(tvps->num *
+ sizeof(struct dtv_property), GFP_KERNEL);
+ if (!tvp) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ for (i = 0; i < tvps->num; i++) {
+ (tvp + i)->result = dtv_property_process_set(fe, tvp + i, inode, file);
+ err |= (tvp + i)->result;
+ }
+
+ if(fe->dtv_property_cache.state == DTV_TUNE)
+ dprintk("%s() Property cache is full, tuning\n", __func__);
+
+ } else
+ if(cmd == FE_GET_PROPERTY) {
+
+ tvps = (struct dtv_properties __user *)parg;
+
+ dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+ dprintk("%s() properties.props = %p\n", __func__, tvps->props);
+
+ /* Put an arbitrary limit on the number of messages that can
+ * be sent at once */
+ if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+ return -EINVAL;
+
+ tvp = (struct dtv_property *) kmalloc(tvps->num *
+ sizeof(struct dtv_property), GFP_KERNEL);
+ if (!tvp) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ for (i = 0; i < tvps->num; i++) {
+ (tvp + i)->result = dtv_property_process_get(fe, tvp + i, inode, file);
+ err |= (tvp + i)->result;
+ }
+
+ if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ } else
+ err = -EOPNOTSUPP;
+
+out:
+ kfree(tvp);
+ return err;
+}
+
+static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+ unsigned int cmd, void *parg)
+{
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_frontend *fe = dvbdev->priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ int err = -EOPNOTSUPP;
+
switch (cmd) {
case FE_GET_INFO: {
struct dvb_frontend_info* info = parg;
@@ -889,13 +1523,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
- unsigned long cmd = ((unsigned long) parg) << 1;
+ unsigned long swcmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04lx\n", __func__, cmd);
+ printk("%s switch command: 0x%04lx\n", __func__, swcmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -908,12 +1542,12 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
do_gettimeofday(&tv[i + 1]);
- if ((cmd & 0x01) != last) {
+ if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
last = (last) ? 0 : 1;
}
- cmd = cmd >> 1;
+ swcmd = swcmd >> 1;
if (i != 8)
dvb_frontend_sleep_until(&nexttime, 8000);
}
@@ -942,13 +1576,21 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_SET_FRONTEND: {
struct dvb_frontend_tune_settings fetunesettings;
- if (dvb_frontend_check_parameters(fe, parg) < 0) {
- err = -EINVAL;
- break;
- }
+ if(fe->dtv_property_cache.state == DTV_TUNE) {
+ if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
+ err = -EINVAL;
+ break;
+ }
+ } else {
+ if (dvb_frontend_check_parameters(fe, parg) < 0) {
+ err = -EINVAL;
+ break;
+ }
- memcpy (&fepriv->parameters, parg,
- sizeof (struct dvb_frontend_parameters));
+ memcpy (&fepriv->parameters, parg,
+ sizeof (struct dvb_frontend_parameters));
+ dtv_property_cache_sync(fe, &fepriv->parameters);
+ }
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
memcpy(&fetunesettings.parameters, parg,
@@ -1027,10 +1669,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
};
- up (&fepriv->sem);
return err;
}
+
static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{
struct dvb_device *dvbdev = file->private_data;
@@ -1052,13 +1694,53 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_adapter *adapter = fe->dvb;
int ret;
dprintk ("%s\n", __func__);
+ if (adapter->mfe_shared) {
+ mutex_lock (&adapter->mfe_lock);
+
+ if (adapter->mfe_dvbdev == NULL)
+ adapter->mfe_dvbdev = dvbdev;
+
+ else if (adapter->mfe_dvbdev != dvbdev) {
+ struct dvb_device
+ *mfedev = adapter->mfe_dvbdev;
+ struct dvb_frontend
+ *mfe = mfedev->priv;
+ struct dvb_frontend_private
+ *mfepriv = mfe->frontend_priv;
+ int mferetry = (dvb_mfe_wait_time << 1);
+
+ mutex_unlock (&adapter->mfe_lock);
+ while (mferetry-- && (mfedev->users != -1 ||
+ mfepriv->thread != NULL)) {
+ if(msleep_interruptible(500)) {
+ if(signal_pending(current))
+ return -EINTR;
+ }
+ }
+
+ mutex_lock (&adapter->mfe_lock);
+ if(adapter->mfe_dvbdev != dvbdev) {
+ mfedev = adapter->mfe_dvbdev;
+ mfe = mfedev->priv;
+ mfepriv = mfe->frontend_priv;
+ if (mfedev->users != -1 ||
+ mfepriv->thread != NULL) {
+ mutex_unlock (&adapter->mfe_lock);
+ return -EBUSY;
+ }
+ adapter->mfe_dvbdev = dvbdev;
+ }
+ }
+ }
+
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
- return ret;
+ goto err0;
}
if ((ret = dvb_generic_open (inode, file)) < 0)
@@ -1078,6 +1760,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
fepriv->events.eventr = fepriv->events.eventw = 0;
}
+ if (adapter->mfe_shared)
+ mutex_unlock (&adapter->mfe_lock);
return ret;
err2:
@@ -1085,6 +1769,9 @@ err2:
err1:
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
fe->ops.ts_bus_ctrl(fe, 0);
+err0:
+ if (adapter->mfe_shared)
+ mutex_unlock (&adapter->mfe_lock);
return ret;
}
@@ -1154,8 +1841,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
- printk ("DVB: registering frontend %i (%s)...\n",
+ printk ("DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num,
+ fe->id,
fe->ops.info.name);
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index aa4133f0bd1..db4a63b0a32 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -169,6 +169,9 @@ struct dvb_frontend_ops {
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
+
+ int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+ int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
};
#define MAX_EVENT 8
@@ -182,6 +185,32 @@ struct dvb_fe_events {
struct mutex mtx;
};
+struct dtv_frontend_properties {
+
+ /* Cache State */
+ u32 state;
+
+ u32 frequency;
+ fe_modulation_t modulation;
+
+ fe_sec_voltage_t voltage;
+ fe_sec_tone_mode_t sectone;
+ fe_spectral_inversion_t inversion;
+ fe_code_rate_t fec_inner;
+ fe_transmit_mode_t transmission_mode;
+ u32 bandwidth_hz; /* 0 = AUTO */
+ fe_guard_interval_t guard_interval;
+ fe_hierarchy_t hierarchy;
+ u32 symbol_rate;
+ fe_code_rate_t code_rate_HP;
+ fe_code_rate_t code_rate_LP;
+
+ fe_pilot_t pilot;
+ fe_rolloff_t rolloff;
+
+ fe_delivery_system_t delivery_system;
+};
+
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
@@ -190,6 +219,10 @@ struct dvb_frontend {
void *frontend_priv;
void *sec_priv;
void *analog_demod_priv;
+ struct dtv_frontend_properties dtv_property_cache;
+#define DVB_FRONTEND_COMPONENT_TUNER 0
+ int (*callback)(void *adapter_priv, int component, int cmd, int arg);
+ int id;
};
extern int dvb_register_frontend(struct dvb_adapter *dvb,
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e7132770a3b..a113744a56c 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -233,7 +233,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- clsdev = device_create_drvdata(dvb_class, adap->device,
+ clsdev = device_create(dvb_class, adap->device,
MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
@@ -326,6 +326,9 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
adap->name = name;
adap->module = module;
adap->device = device;
+ adap->mfe_shared = 0;
+ adap->mfe_dvbdev = NULL;
+ mutex_init (&adap->mfe_lock);
list_add_tail (&adap->list_head, &dvb_adapter_list);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 89d12dc477a..574e336bac3 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -62,6 +62,10 @@ struct dvb_adapter {
struct device *device;
struct module *module;
+
+ int mfe_shared; /* indicates mutually exclusive frontends */
+ struct dvb_device *mfe_dvbdev; /* frontend device in use */
+ struct mutex mfe_lock; /* access lock for thread creation */
};
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e84152b7576..3c13bcfa638 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -72,9 +72,11 @@ config DVB_USB_DIB0700
select DVB_DIB7000P
select DVB_DIB7000M
select DVB_DIB3000MC
+ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
select DVB_TUNER_DIB0070
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -108,6 +110,8 @@ config DVB_USB_CXUSB
select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+ select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -245,12 +249,25 @@ config DVB_USB_AF9005_REMOTE
Afatech AF9005 based receiver.
config DVB_USB_DW2102
- tristate "DvbWorld 2102 DVB-S USB2.0 receiver"
+ tristate "DvbWorld DVB-S/S2 USB2.0 support"
depends on DVB_USB
- select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_STV0299 if !DVB_FE_CUSTOMISE
+ select DVB_STV0288 if !DVB_FE_CUSTOMISE
+ select DVB_STB6000 if !DVB_FE_CUSTOMISE
+ select DVB_CX24116 if !DVB_FE_CUSTOMISE
+ select DVB_SI21XX if !DVB_FE_CUSTOMISE
help
- Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver.
+ Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
+ and the TeVii S650.
+
+config DVB_USB_CINERGY_T2
+ tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
+ depends on DVB_USB
+ help
+ Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
+
+ Say Y if you own such a device and want to use it.
config DVB_USB_ANYSEE
tristate "Anysee DVB-T/C USB2.0 support"
@@ -262,3 +279,22 @@ config DVB_USB_ANYSEE
help
Say Y here to support the Anysee E30, Anysee E30 Plus or
Anysee E30 C Plus DVB USB2.0 receiver.
+
+config DVB_USB_DTV5100
+ tristate "AME DTV-5100 USB2.0 DVB-T support"
+ depends on DVB_USB
+ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
+
+config DVB_USB_AF9015
+ tristate "Afatech AF9015 DVB-T USB2.0 support"
+ depends on DVB_USB && EXPERIMENTAL
+ select DVB_AF9013
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index e206f1ea002..3122b7cc2c2 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -67,6 +67,16 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
dvb-usb-dw2102-objs = dw2102.o
obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
+dvb-usb-dtv5100-objs = dtv5100.o
+obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
+
+dvb-usb-af9015-objs = af9015.o
+obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
+
+dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
+obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
+
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
index ff00c0e8f4a..7c596f92676 100644
--- a/drivers/media/dvb/dvb-usb/af9005-remote.c
+++ b/drivers/media/dvb/dvb-usb/af9005-remote.c
@@ -25,7 +25,7 @@
*/
#include "af9005.h"
/* debug */
-int dvb_usb_af9005_remote_debug;
+static int dvb_usb_af9005_remote_debug;
module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644);
MODULE_PARM_DESC(debug,
"enable (1) or disable (0) debug messages."
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h
index 6eeaae51b1c..4d69045426d 100644
--- a/drivers/media/dvb/dvb-usb/af9005-script.h
+++ b/drivers/media/dvb/dvb-usb/af9005-script.h
@@ -14,7 +14,7 @@ typedef struct {
u8 val;
} RegDesc;
-RegDesc script[] = {
+static RegDesc script[] = {
{0xa180, 0x0, 0x8, 0xa},
{0xa181, 0x0, 0x8, 0xd7},
{0xa182, 0x0, 0x8, 0xa3},
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
index cfe71feefca..ca5a0a4d2a4 100644
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -35,17 +35,17 @@ module_param_named(led, dvb_usb_af9005_led, bool, 0644);
MODULE_PARM_DESC(led, "enable led (default: 1).");
/* eeprom dump */
-int dvb_usb_af9005_dump_eeprom = 0;
+static int dvb_usb_af9005_dump_eeprom;
module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* remote control decoder */
-int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
- int *state);
-void *rc_keys;
-int *rc_keys_size;
+static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len,
+ u32 *event, int *state);
+static void *rc_keys;
+static int *rc_keys_size;
u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
@@ -54,8 +54,8 @@ struct af9005_device_state {
int led_state;
};
-int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen,
- u8 * rbuf, u16 rlen, int delay_ms)
+static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen,
+ u8 *rbuf, u16 rlen, int delay_ms)
{
int actlen, ret = -ENOMEM;
@@ -98,12 +98,7 @@ int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen,
return ret;
}
-int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len)
-{
- return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0);
-}
-
-int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
+static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
int readwrite, int type, u8 * values, int len)
{
struct af9005_device_state *st = d->priv;
@@ -765,7 +760,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
return 0;
}
-int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
+static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
{
int i, packets, ret, act_len;
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
new file mode 100644
index 00000000000..cb0829c038c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -0,0 +1,1474 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 "af9015.h"
+#include "af9013.h"
+#include "mt2060.h"
+#include "qt1010.h"
+#include "tda18271.h"
+#include "mxl5005s.h"
+#if 0
+#include "mc44s80x.h"
+#endif
+
+int dvb_usb_af9015_debug;
+module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+int dvb_usb_af9015_remote;
+module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
+MODULE_PARM_DESC(remote, "select remote");
+int dvb_usb_af9015_dual_mode;
+module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);
+MODULE_PARM_DESC(dual_mode, "enable dual mode");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static DEFINE_MUTEX(af9015_usb_mutex);
+
+static struct af9015_config af9015_config;
+static struct dvb_usb_device_properties af9015_properties[2];
+int af9015_properties_count = ARRAY_SIZE(af9015_properties);
+
+static struct af9013_config af9015_af9013_config[] = {
+ {
+ .demod_address = AF9015_I2C_DEMOD,
+ .output_mode = AF9013_OUTPUT_MODE_USB,
+ .api_version = { 0, 1, 9, 0 },
+ .gpio[0] = AF9013_GPIO_HI,
+ .gpio[3] = AF9013_GPIO_TUNER_ON,
+
+ }, {
+ .output_mode = AF9013_OUTPUT_MODE_SERIAL,
+ .api_version = { 0, 1, 9, 0 },
+ .gpio[0] = AF9013_GPIO_TUNER_ON,
+ .gpio[1] = AF9013_GPIO_LO,
+ }
+};
+
+static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
+{
+ int act_len, ret;
+ u8 buf[64];
+ u8 write = 1;
+ u8 msg_len = 8;
+ static u8 seq; /* packet sequence number */
+
+ if (mutex_lock_interruptible(&af9015_usb_mutex) < 0)
+ return -EAGAIN;
+
+ buf[0] = req->cmd;
+ buf[1] = seq++;
+ buf[2] = req->i2c_addr;
+ buf[3] = req->addr >> 8;
+ buf[4] = req->addr & 0xff;
+ buf[5] = req->mbox;
+ buf[6] = req->addr_len;
+ buf[7] = req->data_len;
+
+ switch (req->cmd) {
+ case GET_CONFIG:
+ case BOOT:
+ case READ_MEMORY:
+ case RECONNECT_USB:
+ case GET_IR_CODE:
+ write = 0;
+ break;
+ case READ_I2C:
+ write = 0;
+ buf[2] |= 0x01; /* set I2C direction */
+ case WRITE_I2C:
+ buf[0] = READ_WRITE_I2C;
+ break;
+ case WRITE_MEMORY:
+ if (((req->addr & 0xff00) == 0xff00) ||
+ ((req->addr & 0xae00) == 0xae00))
+ buf[0] = WRITE_VIRTUAL_MEMORY;
+ case WRITE_VIRTUAL_MEMORY:
+ case COPY_FIRMWARE:
+ case DOWNLOAD_FIRMWARE:
+ break;
+ default:
+ err("unknown command:%d", req->cmd);
+ ret = -1;
+ goto error_unlock;
+ }
+
+ /* write requested */
+ if (write) {
+ memcpy(&buf[8], req->data, req->data_len);
+ msg_len += req->data_len;
+ }
+ deb_xfer(">>> ");
+ debug_dump(buf, msg_len, deb_xfer);
+
+ /* send req */
+ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
+ &act_len, AF9015_USB_TIMEOUT);
+ if (ret)
+ err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len);
+ else
+ if (act_len != msg_len)
+ ret = -1; /* all data is not send */
+ if (ret)
+ goto error_unlock;
+
+ /* no ack for those packets */
+ if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
+ goto exit_unlock;
+
+ /* receive ack and data if read req */
+ msg_len = 1 + 1 + req->data_len; /* seq + status + data len */
+ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
+ &act_len, AF9015_USB_TIMEOUT);
+ if (ret) {
+ err("recv bulk message failed:%d", ret);
+ ret = -1;
+ goto error_unlock;
+ }
+
+ deb_xfer("<<< ");
+ debug_dump(buf, act_len, deb_xfer);
+
+ /* remote controller query status is 1 if remote code is not received */
+ if (req->cmd == GET_IR_CODE && buf[1] == 1) {
+ buf[1] = 0; /* clear command "error" status */
+ memset(&buf[2], 0, req->data_len);
+ buf[3] = 1; /* no remote code received mark */
+ }
+
+ /* check status */
+ if (buf[1]) {
+ err("command failed:%d", buf[1]);
+ ret = -1;
+ goto error_unlock;
+ }
+
+ /* read request, copy returned data to return buf */
+ if (!write)
+ memcpy(req->data, &buf[2], req->data_len);
+
+error_unlock:
+exit_unlock:
+ mutex_unlock(&af9015_usb_mutex);
+
+ return ret;
+}
+
+static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
+{
+ return af9015_rw_udev(d->udev, req);
+}
+
+static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
+ u8 len)
+{
+ struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
+ val};
+ return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
+{
+ return af9015_write_regs(d, addr, &val, 1);
+}
+
+static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
+{
+ struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val};
+ return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+ u8 val)
+{
+ struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
+
+ if (addr == af9015_af9013_config[0].demod_address ||
+ addr == af9015_af9013_config[1].demod_address)
+ req.addr_len = 3;
+
+ return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+ u8 *val)
+{
+ struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
+
+ if (addr == af9015_af9013_config[0].demod_address ||
+ addr == af9015_af9013_config[1].demod_address)
+ req.addr_len = 3;
+
+ return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0, i = 0;
+ u16 addr;
+ u8 mbox, addr_len;
+ struct req_t req;
+
+/* TODO: implement bus lock
+
+The bus lock is needed because there is two tuners both using same I2C-address.
+Due to that the only way to select correct tuner is use demodulator I2C-gate.
+
+................................................
+. AF9015 includes integrated AF9013 demodulator.
+. ____________ ____________ . ____________
+.| uC | | demod | . | tuner |
+.|------------| |------------| . |------------|
+.| AF9015 | | AF9013/5 | . | MXL5003 |
+.| |--+----I2C-------|-----/ -----|-.-----I2C-------| |
+.| | | | addr 0x38 | . | addr 0xc6 |
+.|____________| | |____________| . |____________|
+.................|..............................
+ | ____________ ____________
+ | | demod | | tuner |
+ | |------------| |------------|
+ | | AF9013 | | MXL5003 |
+ +----I2C-------|-----/ -----|-------I2C-------| |
+ | addr 0x3a | | addr 0xc6 |
+ |____________| |____________|
+*/
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ while (i < num) {
+ if (msg[i].addr == af9015_af9013_config[0].demod_address ||
+ msg[i].addr == af9015_af9013_config[1].demod_address) {
+ addr = msg[i].buf[0] << 8;
+ addr += msg[i].buf[1];
+ mbox = msg[i].buf[2];
+ addr_len = 3;
+ } else {
+ addr = msg[i].buf[0];
+ addr_len = 1;
+ mbox = 0;
+ }
+
+ if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+ if (msg[i].addr ==
+ af9015_af9013_config[0].demod_address)
+ req.cmd = READ_MEMORY;
+ else
+ req.cmd = READ_I2C;
+ req.i2c_addr = msg[i].addr;
+ req.addr = addr;
+ req.mbox = mbox;
+ req.addr_len = addr_len;
+ req.data_len = msg[i+1].len;
+ req.data = &msg[i+1].buf[0];
+ ret = af9015_ctrl_msg(d, &req);
+ i += 2;
+ } else {
+ if (msg[i].addr ==
+ af9015_af9013_config[0].demod_address)
+ req.cmd = WRITE_MEMORY;
+ else
+ req.cmd = WRITE_I2C;
+ req.i2c_addr = msg[i].addr;
+ req.addr = addr;
+ req.mbox = mbox;
+ req.addr_len = addr_len;
+ req.data_len = msg[i].len-addr_len;
+ req.data = &msg[i].buf[addr_len];
+ ret = af9015_ctrl_msg(d, &req);
+ i += 1;
+ }
+ if (ret)
+ goto error;
+
+ }
+ ret = i;
+
+error:
+ mutex_unlock(&d->i2c_mutex);
+
+ return ret;
+}
+
+static u32 af9015_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm af9015_i2c_algo = {
+ .master_xfer = af9015_i2c_xfer,
+ .functionality = af9015_i2c_func,
+};
+
+static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
+{
+ int ret;
+ u8 val, mask = 0x01;
+
+ ret = af9015_read_reg(d, addr, &val);
+ if (ret)
+ return ret;
+
+ mask <<= bit;
+ if (op) {
+ /* set bit */
+ val |= mask;
+ } else {
+ /* clear bit */
+ mask ^= 0xff;
+ val &= mask;
+ }
+
+ return af9015_write_reg(d, addr, val);
+}
+
+static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+ return af9015_do_reg_bit(d, addr, bit, 1);
+}
+
+static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+ return af9015_do_reg_bit(d, addr, bit, 0);
+}
+
+static int af9015_init_endpoint(struct dvb_usb_device *d)
+{
+ int ret;
+ u16 frame_size;
+ u8 packet_size;
+ deb_info("%s: USB speed:%d\n", __func__, d->udev->speed);
+
+#define TS_PACKET_SIZE 188
+
+#define TS_USB20_PACKET_COUNT 348
+#define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)
+
+#define TS_USB11_PACKET_COUNT 21
+#define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)
+
+#define TS_USB20_MAX_PACKET_SIZE 512
+#define TS_USB11_MAX_PACKET_SIZE 64
+
+ if (d->udev->speed == USB_SPEED_FULL) {
+ frame_size = TS_USB11_FRAME_SIZE/4;
+ packet_size = TS_USB11_MAX_PACKET_SIZE/4;
+ } else {
+ frame_size = TS_USB20_FRAME_SIZE/4;
+ packet_size = TS_USB20_MAX_PACKET_SIZE/4;
+ }
+
+ ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */
+ if (ret)
+ goto error;
+ ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */
+ if (ret)
+ goto error;
+ ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */
+ if (ret)
+ goto error;
+ ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */
+ if (ret)
+ goto error;
+ ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */
+ if (ret)
+ goto error;
+ if (af9015_config.dual_mode) {
+ ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */
+ if (ret)
+ goto error;
+ }
+ ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */
+ if (ret)
+ goto error;
+ if (af9015_config.dual_mode) {
+ ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */
+ if (ret)
+ goto error;
+ }
+ /* EP4 xfer length */
+ ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);
+ if (ret)
+ goto error;
+ ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);
+ if (ret)
+ goto error;
+ /* EP5 xfer length */
+ ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);
+ if (ret)
+ goto error;
+ ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);
+ if (ret)
+ goto error;
+ ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */
+ if (ret)
+ goto error;
+ ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */
+ if (ret)
+ goto error;
+ ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */
+ if (ret)
+ goto error;
+ if (af9015_config.dual_mode) {
+ ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */
+ if (ret)
+ goto error;
+ }
+
+ /* enable / disable mp2if2 */
+ if (af9015_config.dual_mode)
+ ret = af9015_set_reg_bit(d, 0xd50b, 0);
+ else
+ ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+error:
+ if (ret)
+ err("endpoint init failed:%d", ret);
+ return ret;
+}
+
+static int af9015_copy_firmware(struct dvb_usb_device *d)
+{
+ int ret;
+ u8 fw_params[4];
+ u8 val, i;
+ struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
+ fw_params };
+ deb_info("%s:\n", __func__);
+
+ fw_params[0] = af9015_config.firmware_size >> 8;
+ fw_params[1] = af9015_config.firmware_size & 0xff;
+ fw_params[2] = af9015_config.firmware_checksum >> 8;
+ fw_params[3] = af9015_config.firmware_checksum & 0xff;
+
+ /* wait 2nd demodulator ready */
+ msleep(100);
+
+ ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val);
+ if (ret)
+ goto error;
+ else
+ deb_info("%s: firmware status:%02x\n", __func__, val);
+
+ if (val == 0x0c) /* fw is running, no need for download */
+ goto exit;
+
+ /* set I2C master clock to fast (to speed up firmware copy) */
+ ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
+ if (ret)
+ goto error;
+
+ msleep(50);
+
+ /* copy firmware */
+ ret = af9015_ctrl_msg(d, &req);
+ if (ret)
+ err("firmware copy cmd failed:%d", ret);
+ deb_info("%s: firmware copy done\n", __func__);
+
+ /* set I2C master clock back to normal */
+ ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
+ if (ret)
+ goto error;
+
+ /* request boot firmware */
+ ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address,
+ 0xe205, 1);
+ deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
+ if (ret)
+ goto error;
+
+ for (i = 0; i < 15; i++) {
+ msleep(100);
+
+ /* check firmware status */
+ ret = af9015_read_reg_i2c(d,
+ af9015_af9013_config[1].demod_address, 0x98be, &val);
+ deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
+ __func__, ret, val);
+ if (ret)
+ goto error;
+
+ if (val == 0x0c || val == 0x04) /* success or fail */
+ break;
+ }
+
+ if (val == 0x04) {
+ err("firmware did not run");
+ ret = -1;
+ } else if (val != 0x0c) {
+ err("firmware boot timeout");
+ ret = -1;
+ }
+
+error:
+exit:
+ return ret;
+}
+
+/* dump eeprom */
+static int af9015_eeprom_dump(struct dvb_usb_device *d)
+{
+ char buf[52], buf2[4];
+ u8 reg, val;
+
+ for (reg = 0; ; reg++) {
+ if (reg % 16 == 0) {
+ if (reg)
+ deb_info("%s\n", buf);
+ sprintf(buf, "%02x: ", reg);
+ }
+ if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0)
+ sprintf(buf2, "%02x ", val);
+ else
+ strcpy(buf2, "-- ");
+ strcat(buf, buf2);
+ if (reg == 0xff)
+ break;
+ }
+ deb_info("%s\n", buf);
+ return 0;
+}
+
+int af9015_download_ir_table(struct dvb_usb_device *d)
+{
+ int i, packets = 0, ret;
+ u16 addr = 0x9a56; /* ir-table start address */
+ struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL};
+ u8 *data = NULL;
+ deb_info("%s:\n", __func__);
+
+ data = af9015_config.ir_table;
+ packets = af9015_config.ir_table_size;
+
+ /* no remote */
+ if (!packets)
+ goto exit;
+
+ /* load remote ir-table */
+ for (i = 0; i < packets; i++) {
+ req.addr = addr + i;
+ req.data = &data[i];
+ ret = af9015_ctrl_msg(d, &req);
+ if (ret) {
+ err("ir-table download failed at packet %d with " \
+ "code %d", i, ret);
+ return ret;
+ }
+ }
+
+exit:
+ return 0;
+}
+
+static int af9015_init(struct dvb_usb_device *d)
+{
+ int ret;
+ deb_info("%s:\n", __func__);
+
+ ret = af9015_init_endpoint(d);
+ if (ret)
+ goto error;
+
+ ret = af9015_download_ir_table(d);
+ if (ret)
+ goto error;
+
+error:
+ return ret;
+}
+
+static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret;
+ deb_info("%s: onoff:%d\n", __func__, onoff);
+
+ if (onoff)
+ ret = af9015_set_reg_bit(adap->dev, 0xd503, 0);
+ else
+ ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0);
+
+ return ret;
+}
+
+static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+ int onoff)
+{
+ int ret;
+ u8 idx;
+
+ deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n",
+ __func__, index, pid, onoff);
+
+ ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff));
+ if (ret)
+ goto error;
+
+ ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8));
+ if (ret)
+ goto error;
+
+ idx = ((index & 0x1f) | (1 << 5));
+ ret = af9015_write_reg(adap->dev, 0xd504, idx);
+
+error:
+ return ret;
+}
+
+static int af9015_download_firmware(struct usb_device *udev,
+ const struct firmware *fw)
+{
+ int i, len, packets, remainder, ret;
+ struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
+ u16 addr = 0x5100; /* firmware start address */
+ u16 checksum = 0;
+
+ deb_info("%s:\n", __func__);
+
+ /* calc checksum */
+ for (i = 0; i < fw->size; i++)
+ checksum += fw->data[i];
+
+ af9015_config.firmware_size = fw->size;
+ af9015_config.firmware_checksum = checksum;
+
+ #define FW_PACKET_MAX_DATA 55
+
+ packets = fw->size / FW_PACKET_MAX_DATA;
+ remainder = fw->size % FW_PACKET_MAX_DATA;
+ len = FW_PACKET_MAX_DATA;
+ for (i = 0; i <= packets; i++) {
+ if (i == packets) /* set size of the last packet */
+ len = remainder;
+
+ req.data_len = len;
+ req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
+ req.addr = addr;
+ addr += FW_PACKET_MAX_DATA;
+
+ ret = af9015_rw_udev(udev, &req);
+ if (ret) {
+ err("firmware download failed at packet %d with " \
+ "code %d", i, ret);
+ goto error;
+ }
+ }
+
+ /* firmware loaded, request boot */
+ req.cmd = BOOT;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret) {
+ err("firmware boot failed:%d", ret);
+ goto error;
+ }
+
+ /* firmware is running, reconnect device in the usb bus */
+ req.cmd = RECONNECT_USB;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ err("reconnect failed: %d", ret);
+
+error:
+ return ret;
+}
+
+static int af9015_read_config(struct usb_device *udev)
+{
+ int ret;
+ u8 val, i, offset = 0;
+ struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
+ char manufacturer[10];
+
+ /* IR remote controller */
+ req.addr = AF9015_EEPROM_IR_MODE;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ deb_info("%s: IR mode:%d\n", __func__, val);
+ for (i = 0; i < af9015_properties_count; i++) {
+ if (val == AF9015_IR_MODE_DISABLED || val == 0x04) {
+ af9015_properties[i].rc_key_map = NULL;
+ af9015_properties[i].rc_key_map_size = 0;
+ } else if (dvb_usb_af9015_remote) {
+ /* load remote defined as module param */
+ switch (dvb_usb_af9015_remote) {
+ case AF9015_REMOTE_A_LINK_DTU_M:
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_a_link;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_a_link);
+ af9015_config.ir_table = af9015_ir_table_a_link;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_a_link);
+ break;
+ case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_msi;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_msi);
+ af9015_config.ir_table = af9015_ir_table_msi;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_msi);
+ break;
+ case AF9015_REMOTE_MYGICTV_U718:
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_mygictv;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_mygictv);
+ af9015_config.ir_table =
+ af9015_ir_table_mygictv;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_mygictv);
+ break;
+ }
+ } else {
+ switch (udev->descriptor.idVendor) {
+ case USB_VID_LEADTEK:
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_leadtek;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_leadtek);
+ af9015_config.ir_table =
+ af9015_ir_table_leadtek;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_leadtek);
+ break;
+ case USB_VID_VISIONPLUS:
+ if (udev->descriptor.idProduct ==
+ USB_PID_AZUREWAVE_AD_TU700) {
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_twinhan;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_twinhan);
+ af9015_config.ir_table =
+ af9015_ir_table_twinhan;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_twinhan);
+ }
+ break;
+ case USB_VID_KWORLD_2:
+ /* TODO: use correct rc keys */
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_twinhan;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_twinhan);
+ af9015_config.ir_table = af9015_ir_table_kworld;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_kworld);
+ break;
+ /* Check USB manufacturer and product strings and try
+ to determine correct remote in case of chip vendor
+ reference IDs are used. */
+ case USB_VID_AFATECH:
+ memset(manufacturer, 0, sizeof(manufacturer));
+ usb_string(udev, udev->descriptor.iManufacturer,
+ manufacturer, sizeof(manufacturer));
+ if (!strcmp("Geniatech", manufacturer)) {
+ /* iManufacturer 1 Geniatech
+ iProduct 2 AF9015 */
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_mygictv;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_mygictv);
+ af9015_config.ir_table =
+ af9015_ir_table_mygictv;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_mygictv);
+ } else if (!strcmp("MSI", manufacturer)) {
+ /* iManufacturer 1 MSI
+ iProduct 2 MSI K-VOX */
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_msi;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_msi);
+ af9015_config.ir_table =
+ af9015_ir_table_msi;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_msi);
+ }
+ break;
+ }
+ }
+ }
+
+ /* TS mode - one or two receivers */
+ req.addr = AF9015_EEPROM_TS_MODE;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_config.dual_mode = val;
+ deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
+ /* disable dual mode by default because it is buggy */
+ if (!dvb_usb_af9015_dual_mode)
+ af9015_config.dual_mode = 0;
+
+ /* set buffer size according to USB port speed */
+ for (i = 0; i < af9015_properties_count; i++) {
+ /* USB1.1 set smaller buffersize and disable 2nd adapter */
+ if (udev->speed == USB_SPEED_FULL) {
+ af9015_properties[i].adapter->stream.u.bulk.buffersize =
+ TS_USB11_MAX_PACKET_SIZE;
+ /* disable 2nd adapter because we don't have
+ PID-filters */
+ af9015_config.dual_mode = 0;
+ } else {
+ af9015_properties[i].adapter->stream.u.bulk.buffersize =
+ TS_USB20_MAX_PACKET_SIZE;
+ }
+ }
+
+ if (af9015_config.dual_mode) {
+ /* read 2nd demodulator I2C address */
+ req.addr = AF9015_EEPROM_DEMOD2_I2C;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_af9013_config[1].demod_address = val;
+
+ /* enable 2nd adapter */
+ for (i = 0; i < af9015_properties_count; i++)
+ af9015_properties[i].num_adapters = 2;
+
+ } else {
+ /* disable 2nd adapter */
+ for (i = 0; i < af9015_properties_count; i++)
+ af9015_properties[i].num_adapters = 1;
+ }
+
+ for (i = 0; i < af9015_properties[0].num_adapters; i++) {
+ if (i == 1)
+ offset = AF9015_EEPROM_OFFSET;
+ /* xtal */
+ req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ switch (val) {
+ case 0:
+ af9015_af9013_config[i].adc_clock = 28800;
+ break;
+ case 1:
+ af9015_af9013_config[i].adc_clock = 20480;
+ break;
+ case 2:
+ af9015_af9013_config[i].adc_clock = 28000;
+ break;
+ case 3:
+ af9015_af9013_config[i].adc_clock = 25000;
+ break;
+ };
+ deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i,
+ val, af9015_af9013_config[i].adc_clock);
+
+ /* tuner IF */
+ req.addr = AF9015_EEPROM_IF1H + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_af9013_config[i].tuner_if = val << 8;
+ req.addr = AF9015_EEPROM_IF1L + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_af9013_config[i].tuner_if += val;
+ deb_info("%s: [%d] IF1:%d\n", __func__, i,
+ af9015_af9013_config[0].tuner_if);
+
+ /* MT2060 IF1 */
+ req.addr = AF9015_EEPROM_MT2060_IF1H + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_config.mt2060_if1[i] = val << 8;
+ req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ af9015_config.mt2060_if1[i] += val;
+ deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i,
+ af9015_config.mt2060_if1[i]);
+
+ /* tuner */
+ req.addr = AF9015_EEPROM_TUNER_ID1 + offset;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto error;
+ switch (val) {
+ case AF9013_TUNER_ENV77H11D5:
+ case AF9013_TUNER_MT2060:
+ case AF9013_TUNER_MC44S803:
+ case AF9013_TUNER_QT1010:
+ case AF9013_TUNER_UNKNOWN:
+ case AF9013_TUNER_MT2060_2:
+ case AF9013_TUNER_TDA18271:
+ case AF9013_TUNER_QT1010A:
+ af9015_af9013_config[i].rf_spec_inv = 1;
+ break;
+ case AF9013_TUNER_MXL5003D:
+ case AF9013_TUNER_MXL5005D:
+ case AF9013_TUNER_MXL5005R:
+ af9015_af9013_config[i].rf_spec_inv = 0;
+ break;
+ default:
+ warn("tuner id:%d not supported, please report!", val);
+ return -ENODEV;
+ };
+
+ af9015_af9013_config[i].tuner = val;
+ deb_info("%s: [%d] tuner id:%d\n", __func__, i, val);
+ }
+
+error:
+ if (ret)
+ err("eeprom read failed:%d", ret);
+
+ return ret;
+}
+
+static int af9015_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ int ret;
+ u8 reply;
+ struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};
+
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ return ret;
+
+ deb_info("%s: reply:%02x\n", __func__, reply);
+ if (reply == 0x02)
+ *cold = 0;
+ else
+ *cold = 1;
+
+ return ret;
+}
+
+static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 buf[8];
+ struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf};
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ int i, ret;
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = af9015_ctrl_msg(d, &req);
+ if (ret)
+ return ret;
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (!buf[1] && keymap[i].custom == buf[0] &&
+ keymap[i].data == buf[2]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ break;
+ }
+ }
+ if (!buf[1])
+ deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ __func__, buf[0], buf[1], buf[2], buf[3], buf[4],
+ buf[5], buf[6], buf[7]);
+
+ return 0;
+}
+
+/* init 2nd I2C adapter */
+int af9015_i2c_init(struct dvb_usb_device *d)
+{
+ int ret;
+ struct af9015_state *state = d->priv;
+ deb_info("%s:\n", __func__);
+
+ strncpy(state->i2c_adap.name, d->desc->name,
+ sizeof(state->i2c_adap.name));
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+ state->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
+#else
+ state->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
+#endif
+ state->i2c_adap.algo = d->props.i2c_algo;
+ state->i2c_adap.algo_data = NULL;
+ state->i2c_adap.dev.parent = &d->udev->dev;
+
+ i2c_set_adapdata(&state->i2c_adap, d);
+
+ ret = i2c_add_adapter(&state->i2c_adap);
+ if (ret < 0)
+ err("could not add i2c adapter");
+
+ return ret;
+}
+
+static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ int ret;
+ struct af9015_state *state = adap->dev->priv;
+ struct i2c_adapter *i2c_adap;
+
+ if (adap->id == 0) {
+ /* select I2C adapter */
+ i2c_adap = &adap->dev->i2c_adap;
+
+ deb_info("%s: init I2C\n", __func__);
+ ret = af9015_i2c_init(adap->dev);
+
+ /* dump eeprom (debug) */
+ ret = af9015_eeprom_dump(adap->dev);
+ if (ret)
+ return ret;
+ } else {
+ /* select I2C adapter */
+ i2c_adap = &state->i2c_adap;
+
+ /* copy firmware to 2nd demodulator */
+ if (af9015_config.dual_mode) {
+ ret = af9015_copy_firmware(adap->dev);
+ if (ret) {
+ err("firmware copy to 2nd frontend " \
+ "failed, will disable it");
+ af9015_config.dual_mode = 0;
+ return -ENODEV;
+ }
+ } else {
+ return -ENODEV;
+ }
+ }
+
+ /* attach demodulator */
+ adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+ i2c_adap);
+
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static struct mt2060_config af9015_mt2060_config = {
+ .i2c_address = 0xc0,
+ .clock_out = 0,
+};
+
+static struct qt1010_config af9015_qt1010_config = {
+ .i2c_address = 0xc4,
+};
+
+static struct tda18271_config af9015_tda18271_config = {
+ .gate = TDA18271_GATE_DIGITAL,
+ .small_i2c = 1,
+};
+
+static struct mxl5005s_config af9015_mxl5003_config = {
+ .i2c_address = 0xc6,
+ .if_freq = IF_FREQ_4570000HZ,
+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,
+ .agc_mode = MXL_SINGLE_AGC,
+ .tracking_filter = MXL_TF_DEFAULT,
+ .rssi_enable = MXL_RSSI_ENABLE,
+ .cap_select = MXL_CAP_SEL_ENABLE,
+ .div_out = MXL_DIV_OUT_4,
+ .clock_out = MXL_CLOCK_OUT_DISABLE,
+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+ .top = MXL5005S_TOP_25P2,
+ .mod_mode = MXL_DIGITAL_MODE,
+ .if_mode = MXL_ZERO_IF,
+ .AgcMasterByte = 0x00,
+};
+
+static struct mxl5005s_config af9015_mxl5005_config = {
+ .i2c_address = 0xc6,
+ .if_freq = IF_FREQ_4570000HZ,
+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,
+ .agc_mode = MXL_SINGLE_AGC,
+ .tracking_filter = MXL_TF_OFF,
+ .rssi_enable = MXL_RSSI_ENABLE,
+ .cap_select = MXL_CAP_SEL_ENABLE,
+ .div_out = MXL_DIV_OUT_4,
+ .clock_out = MXL_CLOCK_OUT_DISABLE,
+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+ .top = MXL5005S_TOP_25P2,
+ .mod_mode = MXL_DIGITAL_MODE,
+ .if_mode = MXL_ZERO_IF,
+ .AgcMasterByte = 0x00,
+};
+
+static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct af9015_state *state = adap->dev->priv;
+ struct i2c_adapter *i2c_adap;
+ int ret;
+ deb_info("%s: \n", __func__);
+
+ /* select I2C adapter */
+ if (adap->id == 0)
+ i2c_adap = &adap->dev->i2c_adap;
+ else
+ i2c_adap = &state->i2c_adap;
+
+ switch (af9015_af9013_config[adap->id].tuner) {
+ case AF9013_TUNER_MT2060:
+ case AF9013_TUNER_MT2060_2:
+ ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap,
+ &af9015_mt2060_config,
+ af9015_config.mt2060_if1[adap->id])
+ == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_QT1010:
+ case AF9013_TUNER_QT1010A:
+ ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap,
+ &af9015_qt1010_config) == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_TDA18271:
+ ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap,
+ &af9015_tda18271_config) == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_MXL5003D:
+ ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+ &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_MXL5005D:
+ case AF9013_TUNER_MXL5005R:
+ ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+ &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_ENV77H11D5:
+ ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap,
+ DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
+ break;
+ case AF9013_TUNER_MC44S803:
+#if 0
+ ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap)
+ == NULL ? -ENODEV : 0;
+#else
+ ret = -ENODEV;
+ info("Freescale MC44S803 tuner found but no driver for that" \
+ "tuner. Look at the Linuxtv.org for tuner driver" \
+ "status.");
+#endif
+ break;
+ case AF9013_TUNER_UNKNOWN:
+ default:
+ ret = -ENODEV;
+ err("Unknown tuner id:%d",
+ af9015_af9013_config[adap->id].tuner);
+ }
+ return ret;
+}
+
+static struct usb_device_id af9015_usb_table[] = {
+/* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
+ {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
+ {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
+ {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
+/* 5 */{USB_DEVICE(USB_VID_VISIONPLUS,
+ USB_PID_TINYTWIN)},
+ {USB_DEVICE(USB_VID_VISIONPLUS,
+ USB_PID_AZUREWAVE_AD_TU700)},
+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
+ {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
+/* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
+ {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
+ {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
+ {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)},
+ {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
+/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
+ {0},
+};
+MODULE_DEVICE_TABLE(usb, af9015_usb_table);
+
+static struct dvb_usb_device_properties af9015_properties[] = {
+ {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9015_download_firmware,
+ .firmware = "dvb-usb-af9015.fw",
+
+ .size_of_priv = sizeof(struct af9015_state), \
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ },
+ {
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ },
+ }
+ },
+
+ .identify_state = af9015_identify_state,
+
+ .rc_query = af9015_rc_query,
+ .rc_interval = 150,
+
+ .i2c_algo = &af9015_i2c_algo,
+
+ .num_device_descs = 9,
+ .devices = {
+ {
+ .name = "Afatech AF9015 DVB-T USB2.0 stick",
+ .cold_ids = {&af9015_usb_table[0],
+ &af9015_usb_table[1], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Leadtek WinFast DTV Dongle Gold",
+ .cold_ids = {&af9015_usb_table[2], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Pinnacle PCTV 71e",
+ .cold_ids = {&af9015_usb_table[3], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "KWorld PlusTV Dual DVB-T Stick " \
+ "(DVB-T 399U)",
+ .cold_ids = {&af9015_usb_table[4], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "DigitalNow TinyTwin DVB-T Receiver",
+ .cold_ids = {&af9015_usb_table[5], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "TwinHan AzureWave AD-TU700(704J)",
+ .cold_ids = {&af9015_usb_table[6], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "TerraTec Cinergy T USB XE",
+ .cold_ids = {&af9015_usb_table[7], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "KWorld PlusTV Dual DVB-T PCI " \
+ "(DVB-T PC160-2T)",
+ .cold_ids = {&af9015_usb_table[8], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "AVerMedia AVerTV DVB-T Volar X",
+ .cold_ids = {&af9015_usb_table[9], NULL},
+ .warm_ids = {NULL},
+ },
+ }
+ }, {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9015_download_firmware,
+ .firmware = "dvb-usb-af9015.fw",
+
+ .size_of_priv = sizeof(struct af9015_state), \
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ },
+ {
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ },
+ }
+ },
+
+ .identify_state = af9015_identify_state,
+
+ .rc_query = af9015_rc_query,
+ .rc_interval = 150,
+
+ .i2c_algo = &af9015_i2c_algo,
+
+ .num_device_descs = 6,
+ .devices = {
+ {
+ .name = "Xtensions XD-380",
+ .cold_ids = {&af9015_usb_table[10], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "MSI DIGIVOX Duo",
+ .cold_ids = {&af9015_usb_table[11], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
+ .cold_ids = {&af9015_usb_table[12], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Telestar Starstick 2",
+ .cold_ids = {&af9015_usb_table[13], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "AVerMedia A309",
+ .cold_ids = {&af9015_usb_table[14], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "MSI Digi VOX mini III",
+ .cold_ids = {&af9015_usb_table[15], NULL},
+ .warm_ids = {NULL},
+ },
+ }
+ }
+};
+
+static int af9015_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int ret = 0;
+ struct dvb_usb_device *d = NULL;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ u8 i;
+
+ deb_info("%s: interface:%d\n", __func__,
+ intf->cur_altsetting->desc.bInterfaceNumber);
+
+ /* interface 0 is used by DVB-T receiver and
+ interface 1 is for remote controller (HID) */
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+ ret = af9015_read_config(udev);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < af9015_properties_count; i++) {
+ ret = dvb_usb_device_init(intf, &af9015_properties[i],
+ THIS_MODULE, &d, adapter_nr);
+ if (!ret)
+ break;
+ if (ret != -ENODEV)
+ return ret;
+ }
+ if (ret)
+ return ret;
+
+ if (d)
+ ret = af9015_init(d);
+ }
+
+ return ret;
+}
+
+void af9015_i2c_exit(struct dvb_usb_device *d)
+{
+ struct af9015_state *state = d->priv;
+ deb_info("%s: \n", __func__);
+
+ /* remove 2nd I2C adapter */
+ if (d->state & DVB_USB_STATE_I2C)
+ i2c_del_adapter(&state->i2c_adap);
+}
+
+static void af9015_usb_device_exit(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+ deb_info("%s: \n", __func__);
+
+ /* remove 2nd I2C adapter */
+ if (d != NULL && d->desc != NULL)
+ af9015_i2c_exit(d);
+
+ dvb_usb_device_exit(intf);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver af9015_usb_driver = {
+ .name = "dvb_usb_af9015",
+ .probe = af9015_usb_probe,
+ .disconnect = af9015_usb_device_exit,
+ .id_table = af9015_usb_table,
+};
+
+/* module stuff */
+static int __init af9015_usb_module_init(void)
+{
+ int ret;
+ ret = usb_register(&af9015_usb_driver);
+ if (ret)
+ err("module init failed:%d", ret);
+
+ return ret;
+}
+
+static void __exit af9015_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&af9015_usb_driver);
+}
+
+module_init(af9015_usb_module_init);
+module_exit(af9015_usb_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
new file mode 100644
index 00000000000..882e8a4b368
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -0,0 +1,524 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _DVB_USB_AF9015_H_
+#define _DVB_USB_AF9015_H_
+
+#define DVB_USB_LOG_PREFIX "af9015"
+#include "dvb-usb.h"
+
+extern int dvb_usb_af9015_debug;
+#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args)
+#define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args)
+#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args)
+#define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args)
+#define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args)
+#define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args)
+
+#define AF9015_I2C_EEPROM 0xa0
+#define AF9015_I2C_DEMOD 0x38
+#define AF9015_USB_TIMEOUT 2000
+
+/* EEPROM locations */
+#define AF9015_EEPROM_IR_MODE 0x18
+#define AF9015_EEPROM_IR_REMOTE_TYPE 0x34
+#define AF9015_EEPROM_TS_MODE 0x31
+#define AF9015_EEPROM_DEMOD2_I2C 0x32
+
+#define AF9015_EEPROM_SAW_BW1 0x35
+#define AF9015_EEPROM_XTAL_TYPE1 0x36
+#define AF9015_EEPROM_SPEC_INV1 0x37
+#define AF9015_EEPROM_IF1L 0x38
+#define AF9015_EEPROM_IF1H 0x39
+#define AF9015_EEPROM_MT2060_IF1L 0x3a
+#define AF9015_EEPROM_MT2060_IF1H 0x3b
+#define AF9015_EEPROM_TUNER_ID1 0x3c
+
+#define AF9015_EEPROM_SAW_BW2 0x45
+#define AF9015_EEPROM_XTAL_TYPE2 0x46
+#define AF9015_EEPROM_SPEC_INV2 0x47
+#define AF9015_EEPROM_IF2L 0x48
+#define AF9015_EEPROM_IF2H 0x49
+#define AF9015_EEPROM_MT2060_IF2L 0x4a
+#define AF9015_EEPROM_MT2060_IF2H 0x4b
+#define AF9015_EEPROM_TUNER_ID2 0x4c
+
+#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1)
+
+#define AF9015_GPIO_ON (1 << 0)
+#define AF9015_GPIO_EN (1 << 1)
+#define AF9015_GPIO_O (1 << 2)
+#define AF9015_GPIO_I (1 << 3)
+
+#define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN)
+#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O)
+
+struct req_t {
+ u8 cmd; /* [0] */
+ /* seq */ /* [1] */
+ u8 i2c_addr; /* [2] */
+ u16 addr; /* [3|4] */
+ u8 mbox; /* [5] */
+ u8 addr_len; /* [6] */
+ u8 data_len; /* [7] */
+ u8 *data;
+};
+
+enum af9015_cmd {
+ GET_CONFIG = 0x10,
+ DOWNLOAD_FIRMWARE = 0x11,
+ BOOT = 0x13,
+ READ_MEMORY = 0x20,
+ WRITE_MEMORY = 0x21,
+ READ_WRITE_I2C = 0x22,
+ COPY_FIRMWARE = 0x23,
+ RECONNECT_USB = 0x5a,
+ WRITE_VIRTUAL_MEMORY = 0x26,
+ GET_IR_CODE = 0x27,
+ READ_I2C,
+ WRITE_I2C,
+};
+
+enum af9015_ir_mode {
+ AF9015_IR_MODE_DISABLED = 0,
+ AF9015_IR_MODE_HID,
+ AF9015_IR_MODE_RLC,
+ AF9015_IR_MODE_RC6,
+};
+
+struct af9015_state {
+ struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
+};
+
+struct af9015_config {
+ u8 dual_mode:1;
+ u16 mt2060_if1[2];
+ u16 firmware_size;
+ u16 firmware_checksum;
+ u8 *ir_table;
+ u16 ir_table_size;
+};
+
+enum af9015_remote {
+ AF9015_REMOTE_NONE = 0,
+ AF9015_REMOTE_A_LINK_DTU_M,
+ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
+ AF9015_REMOTE_MYGICTV_U718,
+};
+
+/* Leadtek WinFast DTV Dongle Gold */
+static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = {
+ { 0x00, 0x1e, KEY_1 },
+ { 0x00, 0x1f, KEY_2 },
+ { 0x00, 0x20, KEY_3 },
+ { 0x00, 0x21, KEY_4 },
+ { 0x00, 0x22, KEY_5 },
+ { 0x00, 0x23, KEY_6 },
+ { 0x00, 0x24, KEY_7 },
+ { 0x00, 0x25, KEY_8 },
+ { 0x00, 0x26, KEY_9 },
+ { 0x00, 0x27, KEY_0 },
+ { 0x00, 0x28, KEY_ENTER },
+ { 0x00, 0x4f, KEY_VOLUMEUP },
+ { 0x00, 0x50, KEY_VOLUMEDOWN },
+ { 0x00, 0x51, KEY_CHANNELDOWN },
+ { 0x00, 0x52, KEY_CHANNELUP },
+};
+
+static u8 af9015_ir_table_leadtek[] = {
+ 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00,
+ 0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00,
+ 0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00,
+ 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00,
+ 0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00,
+ 0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00,
+ 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00,
+ 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00,
+ 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00,
+ 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00,
+ 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00,
+ 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00,
+ 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00,
+ 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00,
+ 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00,
+ 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00,
+ 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00,
+ 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00,
+ 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00,
+ 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00,
+ 0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00,
+ 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00,
+ 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00,
+ 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00,
+ 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00,
+ 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00,
+ 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00,
+ 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00,
+ 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00,
+ 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00,
+ 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00,
+ 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00,
+ 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00,
+ 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00,
+ 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00,
+ 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00,
+ 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00,
+ 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00,
+ 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00,
+ 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00,
+ 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00,
+ 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00,
+ 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00,
+ 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00,
+ 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00,
+ 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00,
+ 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00,
+ 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00,
+ 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00,
+ 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00,
+};
+
+/* TwinHan AzureWave AD-TU700(704J) */
+static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = {
+ { 0x05, 0x3f, KEY_POWER },
+ { 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */
+ { 0x00, 0x04, KEY_TEXT }, /* Teletext */
+ { 0x00, 0x0e, KEY_POWER },
+ { 0x00, 0x0e, KEY_INFO }, /* Preview */
+ { 0x00, 0x08, KEY_EPG }, /* Info/EPG */
+ { 0x00, 0x0f, KEY_LIST }, /* Record List */
+ { 0x00, 0x1e, KEY_1 },
+ { 0x00, 0x1f, KEY_2 },
+ { 0x00, 0x20, KEY_3 },
+ { 0x00, 0x21, KEY_4 },
+ { 0x00, 0x22, KEY_5 },
+ { 0x00, 0x23, KEY_6 },
+ { 0x00, 0x24, KEY_7 },
+ { 0x00, 0x25, KEY_8 },
+ { 0x00, 0x26, KEY_9 },
+ { 0x00, 0x27, KEY_0 },
+ { 0x00, 0x29, KEY_CANCEL }, /* Cancel */
+ { 0x00, 0x4c, KEY_CLEAR }, /* Clear */
+ { 0x00, 0x2a, KEY_BACK }, /* Back */
+ { 0x00, 0x2b, KEY_TAB }, /* Tab */
+ { 0x00, 0x52, KEY_UP }, /* up arrow */
+ { 0x00, 0x51, KEY_DOWN }, /* down arrow */
+ { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */
+ { 0x00, 0x50, KEY_LEFT }, /* left arrow */
+ { 0x00, 0x28, KEY_ENTER }, /* Enter / ok */
+ { 0x02, 0x52, KEY_VOLUMEUP },
+ { 0x02, 0x51, KEY_VOLUMEDOWN },
+ { 0x00, 0x4e, KEY_CHANNELDOWN },
+ { 0x00, 0x4b, KEY_CHANNELUP },
+ { 0x00, 0x4a, KEY_RECORD },
+ { 0x01, 0x11, KEY_PLAY },
+ { 0x00, 0x17, KEY_PAUSE },
+ { 0x00, 0x0c, KEY_REWIND }, /* FR << */
+ { 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */
+ { 0x01, 0x15, KEY_PREVIOUS }, /* Replay */
+ { 0x01, 0x0e, KEY_NEXT }, /* Skip */
+ { 0x00, 0x13, KEY_CAMERA }, /* Capture */
+ { 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */
+ { 0x01, 0x13, KEY_TV2 }, /* PIP */
+ { 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */
+ { 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */
+ { 0x00, 0x10, KEY_MUTE },
+ { 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */
+ { 0x01, 0x16, KEY_SLEEP }, /* Hibernate */
+ { 0x01, 0x16, KEY_SWITCHVIDEOMODE },
+ /* A/V */ /* TODO does not work */
+ { 0x00, 0x06, KEY_AGAIN }, /* Recall */
+ { 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */
+ { 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */
+ { 0x02, 0x15, KEY_RED },
+ { 0x02, 0x0a, KEY_GREEN },
+ { 0x02, 0x1c, KEY_YELLOW },
+ { 0x02, 0x05, KEY_BLUE },
+};
+
+static u8 af9015_ir_table_twinhan[] = {
+ 0x00, 0xff, 0x16, 0xe9, 0x3f, 0x05, 0x00,
+ 0x00, 0xff, 0x07, 0xf8, 0x16, 0x01, 0x00,
+ 0x00, 0xff, 0x14, 0xeb, 0x11, 0x01, 0x00,
+ 0x00, 0xff, 0x1a, 0xe5, 0x4d, 0x00, 0x00,
+ 0x00, 0xff, 0x4c, 0xb3, 0x17, 0x00, 0x00,
+ 0x00, 0xff, 0x12, 0xed, 0x11, 0x00, 0x00,
+ 0x00, 0xff, 0x40, 0xbf, 0x0c, 0x00, 0x00,
+ 0x00, 0xff, 0x11, 0xee, 0x4a, 0x00, 0x00,
+ 0x00, 0xff, 0x54, 0xab, 0x13, 0x00, 0x00,
+ 0x00, 0xff, 0x41, 0xbe, 0x15, 0x01, 0x00,
+ 0x00, 0xff, 0x42, 0xbd, 0x0e, 0x01, 0x00,
+ 0x00, 0xff, 0x43, 0xbc, 0x17, 0x01, 0x00,
+ 0x00, 0xff, 0x50, 0xaf, 0x0f, 0x01, 0x00,
+ 0x00, 0xff, 0x4d, 0xb2, 0x1d, 0x00, 0x00,
+ 0x00, 0xff, 0x47, 0xb8, 0x13, 0x01, 0x00,
+ 0x00, 0xff, 0x05, 0xfa, 0x4b, 0x00, 0x00,
+ 0x00, 0xff, 0x02, 0xfd, 0x4e, 0x00, 0x00,
+ 0x00, 0xff, 0x0e, 0xf1, 0x06, 0x00, 0x00,
+ 0x00, 0xff, 0x1e, 0xe1, 0x52, 0x02, 0x00,
+ 0x00, 0xff, 0x0a, 0xf5, 0x51, 0x02, 0x00,
+ 0x00, 0xff, 0x10, 0xef, 0x10, 0x00, 0x00,
+ 0x00, 0xff, 0x49, 0xb6, 0x19, 0x01, 0x00,
+ 0x00, 0xff, 0x15, 0xea, 0x27, 0x00, 0x00,
+ 0x00, 0xff, 0x03, 0xfc, 0x1e, 0x00, 0x00,
+ 0x00, 0xff, 0x01, 0xfe, 0x1f, 0x00, 0x00,
+ 0x00, 0xff, 0x06, 0xf9, 0x20, 0x00, 0x00,
+ 0x00, 0xff, 0x09, 0xf6, 0x21, 0x00, 0x00,
+ 0x00, 0xff, 0x1d, 0xe2, 0x22, 0x00, 0x00,
+ 0x00, 0xff, 0x1f, 0xe0, 0x23, 0x00, 0x00,
+ 0x00, 0xff, 0x0d, 0xf2, 0x24, 0x00, 0x00,
+ 0x00, 0xff, 0x19, 0xe6, 0x25, 0x00, 0x00,
+ 0x00, 0xff, 0x1b, 0xe4, 0x26, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0x2b, 0x00, 0x00,
+ 0x00, 0xff, 0x4a, 0xb5, 0x4c, 0x00, 0x00,
+ 0x00, 0xff, 0x4b, 0xb4, 0x52, 0x00, 0x00,
+ 0x00, 0xff, 0x51, 0xae, 0x51, 0x00, 0x00,
+ 0x00, 0xff, 0x52, 0xad, 0x4f, 0x00, 0x00,
+ 0x00, 0xff, 0x4e, 0xb1, 0x50, 0x00, 0x00,
+ 0x00, 0xff, 0x0c, 0xf3, 0x29, 0x00, 0x00,
+ 0x00, 0xff, 0x4f, 0xb0, 0x28, 0x00, 0x00,
+ 0x00, 0xff, 0x13, 0xec, 0x2a, 0x00, 0x00,
+ 0x00, 0xff, 0x17, 0xe8, 0x19, 0x00, 0x00,
+ 0x00, 0xff, 0x04, 0xfb, 0x0f, 0x00, 0x00,
+ 0x00, 0xff, 0x48, 0xb7, 0x0e, 0x00, 0x00,
+ 0x00, 0xff, 0x0f, 0xf0, 0x04, 0x00, 0x00,
+ 0x00, 0xff, 0x1c, 0xe3, 0x08, 0x00, 0x00,
+ 0x00, 0xff, 0x18, 0xe7, 0x15, 0x02, 0x00,
+ 0x00, 0xff, 0x53, 0xac, 0x0a, 0x02, 0x00,
+ 0x00, 0xff, 0x5e, 0xa1, 0x1c, 0x02, 0x00,
+ 0x00, 0xff, 0x5f, 0xa0, 0x05, 0x02, 0x00,
+};
+
+/* A-Link DTU(m) */
+static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = {
+ { 0x00, 0x1e, KEY_1 },
+ { 0x00, 0x1f, KEY_2 },
+ { 0x00, 0x20, KEY_3 },
+ { 0x00, 0x21, KEY_4 },
+ { 0x00, 0x22, KEY_5 },
+ { 0x00, 0x23, KEY_6 },
+ { 0x00, 0x24, KEY_7 },
+ { 0x00, 0x25, KEY_8 },
+ { 0x00, 0x26, KEY_9 },
+ { 0x00, 0x27, KEY_0 },
+ { 0x00, 0x2e, KEY_CHANNELUP },
+ { 0x00, 0x2d, KEY_CHANNELDOWN },
+ { 0x04, 0x28, KEY_ZOOM },
+ { 0x00, 0x41, KEY_MUTE },
+ { 0x00, 0x42, KEY_VOLUMEDOWN },
+ { 0x00, 0x43, KEY_VOLUMEUP },
+ { 0x00, 0x44, KEY_GOTO }, /* jump */
+ { 0x05, 0x45, KEY_POWER },
+};
+
+static u8 af9015_ir_table_a_link[] = {
+ 0x08, 0xf7, 0x12, 0xed, 0x45, 0x05, 0x00, /* power */
+ 0x08, 0xf7, 0x1a, 0xe5, 0x41, 0x00, 0x00, /* mute */
+ 0x08, 0xf7, 0x01, 0xfe, 0x1e, 0x00, 0x00, /* 1 */
+ 0x08, 0xf7, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */
+ 0x08, 0xf7, 0x03, 0xfc, 0x24, 0x00, 0x00, /* 7 */
+ 0x08, 0xf7, 0x05, 0xfa, 0x28, 0x04, 0x00, /* zoom */
+ 0x08, 0xf7, 0x00, 0xff, 0x43, 0x00, 0x00, /* volume up */
+ 0x08, 0xf7, 0x16, 0xe9, 0x42, 0x00, 0x00, /* volume down */
+ 0x08, 0xf7, 0x0f, 0xf0, 0x1f, 0x00, 0x00, /* 2 */
+ 0x08, 0xf7, 0x0d, 0xf2, 0x22, 0x00, 0x00, /* 5 */
+ 0x08, 0xf7, 0x1b, 0xe4, 0x25, 0x00, 0x00, /* 8 */
+ 0x08, 0xf7, 0x06, 0xf9, 0x27, 0x00, 0x00, /* 0 */
+ 0x08, 0xf7, 0x14, 0xeb, 0x2e, 0x00, 0x00, /* channel up */
+ 0x08, 0xf7, 0x1d, 0xe2, 0x2d, 0x00, 0x00, /* channel down */
+ 0x08, 0xf7, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */
+ 0x08, 0xf7, 0x18, 0xe7, 0x23, 0x00, 0x00, /* 6 */
+ 0x08, 0xf7, 0x04, 0xfb, 0x26, 0x00, 0x00, /* 9 */
+ 0x08, 0xf7, 0x07, 0xf8, 0x44, 0x00, 0x00, /* jump */
+};
+
+/* MSI DIGIVOX mini II V3.0 */
+static struct dvb_usb_rc_key af9015_rc_keys_msi[] = {
+ { 0x00, 0x1e, KEY_1 },
+ { 0x00, 0x1f, KEY_2 },
+ { 0x00, 0x20, KEY_3 },
+ { 0x00, 0x21, KEY_4 },
+ { 0x00, 0x22, KEY_5 },
+ { 0x00, 0x23, KEY_6 },
+ { 0x00, 0x24, KEY_7 },
+ { 0x00, 0x25, KEY_8 },
+ { 0x00, 0x26, KEY_9 },
+ { 0x00, 0x27, KEY_0 },
+ { 0x03, 0x0f, KEY_CHANNELUP },
+ { 0x03, 0x0e, KEY_CHANNELDOWN },
+ { 0x00, 0x42, KEY_VOLUMEDOWN },
+ { 0x00, 0x43, KEY_VOLUMEUP },
+ { 0x05, 0x45, KEY_POWER },
+ { 0x00, 0x52, KEY_UP }, /* up */
+ { 0x00, 0x51, KEY_DOWN }, /* down */
+ { 0x00, 0x28, KEY_ENTER },
+};
+
+static u8 af9015_ir_table_msi[] = {
+ 0x03, 0xfc, 0x17, 0xe8, 0x45, 0x05, 0x00, /* power */
+ 0x03, 0xfc, 0x0d, 0xf2, 0x51, 0x00, 0x00, /* down */
+ 0x03, 0xfc, 0x03, 0xfc, 0x52, 0x00, 0x00, /* up */
+ 0x03, 0xfc, 0x1a, 0xe5, 0x1e, 0x00, 0x00, /* 1 */
+ 0x03, 0xfc, 0x02, 0xfd, 0x1f, 0x00, 0x00, /* 2 */
+ 0x03, 0xfc, 0x04, 0xfb, 0x20, 0x00, 0x00, /* 3 */
+ 0x03, 0xfc, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */
+ 0x03, 0xfc, 0x08, 0xf7, 0x22, 0x00, 0x00, /* 5 */
+ 0x03, 0xfc, 0x1d, 0xe2, 0x23, 0x00, 0x00, /* 6 */
+ 0x03, 0xfc, 0x11, 0xee, 0x24, 0x00, 0x00, /* 7 */
+ 0x03, 0xfc, 0x0b, 0xf4, 0x25, 0x00, 0x00, /* 8 */
+ 0x03, 0xfc, 0x10, 0xef, 0x26, 0x00, 0x00, /* 9 */
+ 0x03, 0xfc, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */
+ 0x03, 0xfc, 0x14, 0xeb, 0x43, 0x00, 0x00, /* volume up */
+ 0x03, 0xfc, 0x1f, 0xe0, 0x42, 0x00, 0x00, /* volume down */
+ 0x03, 0xfc, 0x15, 0xea, 0x0f, 0x03, 0x00, /* channel up */
+ 0x03, 0xfc, 0x05, 0xfa, 0x0e, 0x03, 0x00, /* channel down */
+ 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* enter */
+};
+
+/* MYGICTV U718 */
+static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = {
+ { 0x00, 0x3d, KEY_SWITCHVIDEOMODE },
+ /* TV / AV */
+ { 0x05, 0x45, KEY_POWER },
+ { 0x00, 0x1e, KEY_1 },
+ { 0x00, 0x1f, KEY_2 },
+ { 0x00, 0x20, KEY_3 },
+ { 0x00, 0x21, KEY_4 },
+ { 0x00, 0x22, KEY_5 },
+ { 0x00, 0x23, KEY_6 },
+ { 0x00, 0x24, KEY_7 },
+ { 0x00, 0x25, KEY_8 },
+ { 0x00, 0x26, KEY_9 },
+ { 0x00, 0x27, KEY_0 },
+ { 0x00, 0x41, KEY_MUTE },
+ { 0x00, 0x2a, KEY_ESC }, /* Esc */
+ { 0x00, 0x2e, KEY_CHANNELUP },
+ { 0x00, 0x2d, KEY_CHANNELDOWN },
+ { 0x00, 0x42, KEY_VOLUMEDOWN },
+ { 0x00, 0x43, KEY_VOLUMEUP },
+ { 0x00, 0x52, KEY_UP }, /* up arrow */
+ { 0x00, 0x51, KEY_DOWN }, /* down arrow */
+ { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */
+ { 0x00, 0x50, KEY_LEFT }, /* left arrow */
+ { 0x00, 0x28, KEY_ENTER }, /* ok */
+ { 0x01, 0x15, KEY_RECORD },
+ { 0x03, 0x13, KEY_PLAY },
+ { 0x01, 0x13, KEY_PAUSE },
+ { 0x01, 0x16, KEY_STOP },
+ { 0x03, 0x07, KEY_REWIND }, /* FR << */
+ { 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */
+ { 0x00, 0x3b, KEY_TIME }, /* TimeShift */
+ { 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */
+ { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */
+ { 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */
+ { 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */
+ { 0x03, 0x45, KEY_POWER },
+};
+
+static u8 af9015_ir_table_mygictv[] = {
+ 0x02, 0xbd, 0x0c, 0xf3, 0x3d, 0x00, 0x00, /* TV / AV */
+ 0x02, 0xbd, 0x14, 0xeb, 0x45, 0x05, 0x00, /* power */
+ 0x02, 0xbd, 0x00, 0xff, 0x1e, 0x00, 0x00, /* 1 */
+ 0x02, 0xbd, 0x01, 0xfe, 0x1f, 0x00, 0x00, /* 2 */
+ 0x02, 0xbd, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */
+ 0x02, 0xbd, 0x03, 0xfc, 0x21, 0x00, 0x00, /* 4 */
+ 0x02, 0xbd, 0x04, 0xfb, 0x22, 0x00, 0x00, /* 5 */
+ 0x02, 0xbd, 0x05, 0xfa, 0x23, 0x00, 0x00, /* 6 */
+ 0x02, 0xbd, 0x06, 0xf9, 0x24, 0x00, 0x00, /* 7 */
+ 0x02, 0xbd, 0x07, 0xf8, 0x25, 0x00, 0x00, /* 8 */
+ 0x02, 0xbd, 0x08, 0xf7, 0x26, 0x00, 0x00, /* 9 */
+ 0x02, 0xbd, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */
+ 0x02, 0xbd, 0x0a, 0xf5, 0x41, 0x00, 0x00, /* mute */
+ 0x02, 0xbd, 0x1c, 0xe3, 0x2a, 0x00, 0x00, /* esc */
+ 0x02, 0xbd, 0x1f, 0xe0, 0x43, 0x00, 0x00, /* volume up */
+ 0x02, 0xbd, 0x12, 0xed, 0x52, 0x00, 0x00, /* up arrow */
+ 0x02, 0xbd, 0x11, 0xee, 0x50, 0x00, 0x00, /* left arrow */
+ 0x02, 0xbd, 0x15, 0xea, 0x28, 0x00, 0x00, /* ok */
+ 0x02, 0xbd, 0x10, 0xef, 0x4f, 0x00, 0x00, /* right arrow */
+ 0x02, 0xbd, 0x13, 0xec, 0x51, 0x00, 0x00, /* down arrow */
+ 0x02, 0xbd, 0x0e, 0xf1, 0x42, 0x00, 0x00, /* volume down */
+ 0x02, 0xbd, 0x19, 0xe6, 0x15, 0x01, 0x00, /* record */
+ 0x02, 0xbd, 0x1e, 0xe1, 0x13, 0x03, 0x00, /* play */
+ 0x02, 0xbd, 0x16, 0xe9, 0x16, 0x01, 0x00, /* stop */
+ 0x02, 0xbd, 0x0b, 0xf4, 0x28, 0x04, 0x00, /* yellow, min / max */
+ 0x02, 0xbd, 0x0f, 0xf0, 0x3b, 0x00, 0x00, /* time shift */
+ 0x02, 0xbd, 0x18, 0xe7, 0x2e, 0x00, 0x00, /* channel up */
+ 0x02, 0xbd, 0x1a, 0xe5, 0x2d, 0x00, 0x00, /* channel down */
+ 0x02, 0xbd, 0x17, 0xe8, 0x3e, 0x00, 0x00, /* snapshot */
+ 0x02, 0xbd, 0x40, 0xbf, 0x13, 0x01, 0x00, /* pause */
+ 0x02, 0xbd, 0x41, 0xbe, 0x09, 0x03, 0x00, /* FF >> */
+ 0x02, 0xbd, 0x42, 0xbd, 0x07, 0x03, 0x00, /* FR << */
+ 0x02, 0xbd, 0x43, 0xbc, 0x00, 0x00, 0x00, /* 'select' (?) */
+ 0x02, 0xbd, 0x44, 0xbb, 0x16, 0x03, 0x00, /* shuffle */
+ 0x02, 0xbd, 0x45, 0xba, 0x45, 0x03, 0x00, /* power */
+};
+
+/* KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) */
+static u8 af9015_ir_table_kworld[] = {
+ 0x86, 0x6b, 0x0c, 0xf3, 0x2e, 0x07, 0x00,
+ 0x86, 0x6b, 0x16, 0xe9, 0x2d, 0x07, 0x00,
+ 0x86, 0x6b, 0x1d, 0xe2, 0x37, 0x07, 0x00,
+ 0x86, 0x6b, 0x00, 0xff, 0x1e, 0x07, 0x00,
+ 0x86, 0x6b, 0x01, 0xfe, 0x1f, 0x07, 0x00,
+ 0x86, 0x6b, 0x02, 0xfd, 0x20, 0x07, 0x00,
+ 0x86, 0x6b, 0x03, 0xfc, 0x21, 0x07, 0x00,
+ 0x86, 0x6b, 0x04, 0xfb, 0x22, 0x07, 0x00,
+ 0x86, 0x6b, 0x05, 0xfa, 0x23, 0x07, 0x00,
+ 0x86, 0x6b, 0x06, 0xf9, 0x24, 0x07, 0x00,
+ 0x86, 0x6b, 0x07, 0xf8, 0x25, 0x07, 0x00,
+ 0x86, 0x6b, 0x08, 0xf7, 0x26, 0x07, 0x00,
+ 0x86, 0x6b, 0x09, 0xf6, 0x4d, 0x07, 0x00,
+ 0x86, 0x6b, 0x0a, 0xf5, 0x4e, 0x07, 0x00,
+ 0x86, 0x6b, 0x14, 0xeb, 0x4f, 0x07, 0x00,
+ 0x86, 0x6b, 0x1e, 0xe1, 0x50, 0x07, 0x00,
+ 0x86, 0x6b, 0x17, 0xe8, 0x52, 0x07, 0x00,
+ 0x86, 0x6b, 0x1f, 0xe0, 0x51, 0x07, 0x00,
+ 0x86, 0x6b, 0x0e, 0xf1, 0x0b, 0x07, 0x00,
+ 0x86, 0x6b, 0x20, 0xdf, 0x0c, 0x07, 0x00,
+ 0x86, 0x6b, 0x42, 0xbd, 0x0d, 0x07, 0x00,
+ 0x86, 0x6b, 0x0b, 0xf4, 0x0e, 0x07, 0x00,
+ 0x86, 0x6b, 0x43, 0xbc, 0x0f, 0x07, 0x00,
+ 0x86, 0x6b, 0x10, 0xef, 0x10, 0x07, 0x00,
+ 0x86, 0x6b, 0x21, 0xde, 0x11, 0x07, 0x00,
+ 0x86, 0x6b, 0x13, 0xec, 0x12, 0x07, 0x00,
+ 0x86, 0x6b, 0x11, 0xee, 0x13, 0x07, 0x00,
+ 0x86, 0x6b, 0x12, 0xed, 0x14, 0x07, 0x00,
+ 0x86, 0x6b, 0x19, 0xe6, 0x15, 0x07, 0x00,
+ 0x86, 0x6b, 0x1a, 0xe5, 0x16, 0x07, 0x00,
+ 0x86, 0x6b, 0x1b, 0xe4, 0x17, 0x07, 0x00,
+ 0x86, 0x6b, 0x4b, 0xb4, 0x18, 0x07, 0x00,
+ 0x86, 0x6b, 0x40, 0xbf, 0x19, 0x07, 0x00,
+ 0x86, 0x6b, 0x44, 0xbb, 0x1a, 0x07, 0x00,
+ 0x86, 0x6b, 0x41, 0xbe, 0x1b, 0x07, 0x00,
+ 0x86, 0x6b, 0x22, 0xdd, 0x1c, 0x07, 0x00,
+ 0x86, 0x6b, 0x15, 0xea, 0x1d, 0x07, 0x00,
+ 0x86, 0x6b, 0x0f, 0xf0, 0x3f, 0x07, 0x00,
+ 0x86, 0x6b, 0x1c, 0xe3, 0x40, 0x07, 0x00,
+ 0x86, 0x6b, 0x4a, 0xb5, 0x41, 0x07, 0x00,
+ 0x86, 0x6b, 0x48, 0xb7, 0x42, 0x07, 0x00,
+ 0x86, 0x6b, 0x49, 0xb6, 0x43, 0x07, 0x00,
+ 0x86, 0x6b, 0x18, 0xe7, 0x44, 0x07, 0x00,
+ 0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00,
+};
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 2f408d2e1ef..c786359fba0 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -41,6 +41,9 @@
static int dvb_usb_anysee_debug;
module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+int dvb_usb_anysee_delsys;
+module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
+MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static struct mutex anysee_usb_mutex;
@@ -178,14 +181,14 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
inc = 1;
}
if (ret)
- return ret;
+ break;
i += inc;
}
mutex_unlock(&d->i2c_mutex);
- return i;
+ return ret ? ret : i;
}
static u32 anysee_i2c_func(struct i2c_adapter *adapter)
@@ -272,9 +275,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
model demod hw firmware
1. E30 MT352 02 0.2.1
2. E30 ZL10353 02 0.2.1
- 3. E30 Plus ZL10353 06 0.1.0
- 4. E30C Plus TDA10023 0a 0.1.0 rev 0.2
- 4. E30C Plus TDA10023 0f 0.1.2 rev 0.4
+ 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo
+ 4. E30 Plus ZL10353 06 0.1.0
+ 5. E30C Plus TDA10023 0a 0.1.0 rev 0.2
+ E30C Plus TDA10023 0f 0.1.2 rev 0.4
+ E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo
*/
/* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
@@ -293,6 +298,21 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
return 0;
}
+ /* for E30 Combo Plus DVB-T demodulator */
+ if (dvb_usb_anysee_delsys) {
+ ret = anysee_write_reg(adap->dev, 0xb0, 0x01);
+ if (ret)
+ return ret;
+
+ /* Zarlink ZL10353 DVB-T demod */
+ adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
+ return 0;
+ }
+ }
+
/* connect demod on IO port D for TDA10023 & ZL10353 */
ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
if (ret)
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
new file mode 100644
index 00000000000..3ac9f74e9fb
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
@@ -0,0 +1,268 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ * Holger Waechtler <holger@qanu.de>
+ *
+ * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * 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.
+ *
+ */
+
+#include "cinergyT2.h"
+
+
+/* debug */
+int dvb_usb_cinergyt2_debug;
+int disable_remote;
+
+module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
+ "(or-able)).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct cinergyt2_state {
+ u8 rc_counter;
+};
+
+/* We are missing a release hook with usb_device data */
+struct dvb_usb_device *cinergyt2_usb_device;
+
+static struct dvb_usb_device_properties cinergyt2_properties;
+
+static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
+{
+ char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
+ char result[64];
+ return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
+ sizeof(result), 0);
+}
+
+static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
+{
+ char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
+ char state[3];
+ return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
+}
+
+static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
+ char state[3];
+ int ret;
+
+ adap->fe = cinergyt2_fe_attach(adap->dev);
+
+ ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
+ sizeof(state), 0);
+ if (ret < 0) {
+ deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
+ "state info\n");
+ }
+
+ /* Copy this pointer as we are gonna need it in the release phase */
+ cinergyt2_usb_device = adap->dev;
+
+ return 0;
+}
+
+static struct dvb_usb_rc_key cinergyt2_rc_keys[] = {
+ { 0x04, 0x01, KEY_POWER },
+ { 0x04, 0x02, KEY_1 },
+ { 0x04, 0x03, KEY_2 },
+ { 0x04, 0x04, KEY_3 },
+ { 0x04, 0x05, KEY_4 },
+ { 0x04, 0x06, KEY_5 },
+ { 0x04, 0x07, KEY_6 },
+ { 0x04, 0x08, KEY_7 },
+ { 0x04, 0x09, KEY_8 },
+ { 0x04, 0x0a, KEY_9 },
+ { 0x04, 0x0c, KEY_0 },
+ { 0x04, 0x0b, KEY_VIDEO },
+ { 0x04, 0x0d, KEY_REFRESH },
+ { 0x04, 0x0e, KEY_SELECT },
+ { 0x04, 0x0f, KEY_EPG },
+ { 0x04, 0x10, KEY_UP },
+ { 0x04, 0x14, KEY_DOWN },
+ { 0x04, 0x11, KEY_LEFT },
+ { 0x04, 0x13, KEY_RIGHT },
+ { 0x04, 0x12, KEY_OK },
+ { 0x04, 0x15, KEY_TEXT },
+ { 0x04, 0x16, KEY_INFO },
+ { 0x04, 0x17, KEY_RED },
+ { 0x04, 0x18, KEY_GREEN },
+ { 0x04, 0x19, KEY_YELLOW },
+ { 0x04, 0x1a, KEY_BLUE },
+ { 0x04, 0x1c, KEY_VOLUMEUP },
+ { 0x04, 0x1e, KEY_VOLUMEDOWN },
+ { 0x04, 0x1d, KEY_MUTE },
+ { 0x04, 0x1b, KEY_CHANNELUP },
+ { 0x04, 0x1f, KEY_CHANNELDOWN },
+ { 0x04, 0x40, KEY_PAUSE },
+ { 0x04, 0x4c, KEY_PLAY },
+ { 0x04, 0x58, KEY_RECORD },
+ { 0x04, 0x54, KEY_PREVIOUS },
+ { 0x04, 0x48, KEY_STOP },
+ { 0x04, 0x5c, KEY_NEXT }
+};
+
+/* Number of keypresses to ignore before detect repeating */
+#define RC_REPEAT_DELAY 3
+
+static int repeatable_keys[] = {
+ KEY_UP,
+ KEY_DOWN,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_VOLUMEUP,
+ KEY_VOLUMEDOWN,
+ KEY_CHANNELUP,
+ KEY_CHANNELDOWN
+};
+
+static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct cinergyt2_state *st = d->priv;
+ u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
+ int i;
+
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
+ if (key[4] == 0xff) {
+ /* key repeat */
+ st->rc_counter++;
+ if (st->rc_counter > RC_REPEAT_DELAY) {
+ for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
+ if (d->last_event == repeatable_keys[i]) {
+ *state = REMOTE_KEY_REPEAT;
+ *event = d->last_event;
+ deb_rc("repeat key, event %x\n",
+ *event);
+ return 0;
+ }
+ }
+ deb_rc("repeated key (non repeatable)\n");
+ }
+ return 0;
+ }
+
+ /* hack to pass checksum on the custom field */
+ key[2] = ~key[1];
+ dvb_usb_nec_rc_key_to_event(d, key, event, state);
+ if (key[0] != 0) {
+ if (*event != d->last_event)
+ st->rc_counter = 0;
+
+ deb_rc("key: %x %x %x %x %x\n",
+ key[0], key[1], key[2], key[3], key[4]);
+ }
+ return 0;
+}
+
+static int cinergyt2_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf, &cinergyt2_properties,
+ THIS_MODULE, NULL, adapter_nr);
+}
+
+
+static struct usb_device_id cinergyt2_usb_table[] = {
+ { USB_DEVICE(USB_VID_TERRATEC, 0x0038) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table);
+
+static struct dvb_usb_device_properties cinergyt2_properties = {
+ .size_of_priv = sizeof(struct cinergyt2_state),
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = cinergyt2_streaming_ctrl,
+ .frontend_attach = cinergyt2_frontend_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 512,
+ }
+ }
+ },
+ }
+ },
+
+ .power_ctrl = cinergyt2_power_ctrl,
+
+ .rc_interval = 50,
+ .rc_key_map = cinergyt2_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys),
+ .rc_query = cinergyt2_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 1,
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver",
+ .cold_ids = {NULL},
+ .warm_ids = { &cinergyt2_usb_table[0], NULL },
+ },
+ { NULL },
+ }
+};
+
+
+static struct usb_driver cinergyt2_driver = {
+ .name = "cinergyT2",
+ .probe = cinergyt2_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = cinergyt2_usb_table
+};
+
+static int __init cinergyt2_usb_init(void)
+{
+ int err;
+
+ err = usb_register(&cinergyt2_driver);
+ if (err) {
+ err("usb_register() failed! (err %i)\n", err);
+ return err;
+ }
+ return 0;
+}
+
+static void __exit cinergyt2_usb_exit(void)
+{
+ usb_deregister(&cinergyt2_driver);
+}
+
+module_init(cinergyt2_usb_init);
+module_exit(cinergyt2_usb_exit);
+
+MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomi Orava");
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
new file mode 100644
index 00000000000..649f25cca49
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
@@ -0,0 +1,351 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ * Holger Waechtler <holger@qanu.de>
+ *
+ * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * 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.
+ *
+ */
+
+#include "cinergyT2.h"
+
+
+/**
+ * convert linux-dvb frontend parameter set into TPS.
+ * See ETSI ETS-300744, section 4.6.2, table 9 for details.
+ *
+ * This function is probably reusable and may better get placed in a support
+ * library.
+ *
+ * We replace errornous fields by default TPS fields (the ones with value 0).
+ */
+
+static uint16_t compute_tps(struct dvb_frontend_parameters *p)
+{
+ struct dvb_ofdm_parameters *op = &p->u.ofdm;
+ uint16_t tps = 0;
+
+ switch (op->code_rate_HP) {
+ case FEC_2_3:
+ tps |= (1 << 7);
+ break;
+ case FEC_3_4:
+ tps |= (2 << 7);
+ break;
+ case FEC_5_6:
+ tps |= (3 << 7);
+ break;
+ case FEC_7_8:
+ tps |= (4 << 7);
+ break;
+ case FEC_1_2:
+ case FEC_AUTO:
+ default:
+ /* tps |= (0 << 7) */;
+ }
+
+ switch (op->code_rate_LP) {
+ case FEC_2_3:
+ tps |= (1 << 4);
+ break;
+ case FEC_3_4:
+ tps |= (2 << 4);
+ break;
+ case FEC_5_6:
+ tps |= (3 << 4);
+ break;
+ case FEC_7_8:
+ tps |= (4 << 4);
+ break;
+ case FEC_1_2:
+ case FEC_AUTO:
+ default:
+ /* tps |= (0 << 4) */;
+ }
+
+ switch (op->constellation) {
+ case QAM_16:
+ tps |= (1 << 13);
+ break;
+ case QAM_64:
+ tps |= (2 << 13);
+ break;
+ case QPSK:
+ default:
+ /* tps |= (0 << 13) */;
+ }
+
+ switch (op->transmission_mode) {
+ case TRANSMISSION_MODE_8K:
+ tps |= (1 << 0);
+ break;
+ case TRANSMISSION_MODE_2K:
+ default:
+ /* tps |= (0 << 0) */;
+ }
+
+ switch (op->guard_interval) {
+ case GUARD_INTERVAL_1_16:
+ tps |= (1 << 2);
+ break;
+ case GUARD_INTERVAL_1_8:
+ tps |= (2 << 2);
+ break;
+ case GUARD_INTERVAL_1_4:
+ tps |= (3 << 2);
+ break;
+ case GUARD_INTERVAL_1_32:
+ default:
+ /* tps |= (0 << 2) */;
+ }
+
+ switch (op->hierarchy_information) {
+ case HIERARCHY_1:
+ tps |= (1 << 10);
+ break;
+ case HIERARCHY_2:
+ tps |= (2 << 10);
+ break;
+ case HIERARCHY_4:
+ tps |= (3 << 10);
+ break;
+ case HIERARCHY_NONE:
+ default:
+ /* tps |= (0 << 10) */;
+ }
+
+ return tps;
+}
+
+struct cinergyt2_fe_state {
+ struct dvb_frontend fe;
+ struct dvb_usb_device *d;
+};
+
+static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
+ fe_status_t *status)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_get_status_msg result;
+ u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+ int ret;
+
+ ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
+ sizeof(result), 0);
+ if (ret < 0)
+ return ret;
+
+ *status = 0;
+
+ if (0xffff - le16_to_cpu(result.gain) > 30)
+ *status |= FE_HAS_SIGNAL;
+ if (result.lock_bits & (1 << 6))
+ *status |= FE_HAS_LOCK;
+ if (result.lock_bits & (1 << 5))
+ *status |= FE_HAS_SYNC;
+ if (result.lock_bits & (1 << 4))
+ *status |= FE_HAS_CARRIER;
+ if (result.lock_bits & (1 << 1))
+ *status |= FE_HAS_VITERBI;
+
+ if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+ (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+ *status &= ~FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_get_status_msg status;
+ char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+ int ret;
+
+ ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+ sizeof(status), 0);
+ if (ret < 0)
+ return ret;
+
+ *ber = le32_to_cpu(status.viterbi_error_rate);
+ return 0;
+}
+
+static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_get_status_msg status;
+ u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+ int ret;
+
+ ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status,
+ sizeof(status), 0);
+ if (ret < 0) {
+ err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
+ ret);
+ return ret;
+ }
+ *unc = le32_to_cpu(status.uncorrected_block_count);
+ return 0;
+}
+
+static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
+ u16 *strength)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_get_status_msg status;
+ char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+ int ret;
+
+ ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+ sizeof(status), 0);
+ if (ret < 0) {
+ err("cinergyt2_fe_read_signal_strength() Failed!"
+ " (Error=%d)\n", ret);
+ return ret;
+ }
+ *strength = (0xffff - le16_to_cpu(status.gain));
+ return 0;
+}
+
+static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_get_status_msg status;
+ char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+ int ret;
+
+ ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+ sizeof(status), 0);
+ if (ret < 0) {
+ err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
+ return ret;
+ }
+ *snr = (status.snr << 8) | status.snr;
+ return 0;
+}
+
+static int cinergyt2_fe_init(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+static int cinergyt2_fe_sleep(struct dvb_frontend *fe)
+{
+ deb_info("cinergyt2_fe_sleep() Called\n");
+ return 0;
+}
+
+static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 800;
+ return 0;
+}
+
+static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ struct dvbt_set_parameters_msg param;
+ char result[2];
+ int err;
+
+ param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
+ param.tps = cpu_to_le16(compute_tps(fep));
+ param.freq = cpu_to_le32(fep->frequency / 1000);
+ param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
+
+ err = dvb_usb_generic_rw(state->d,
+ (char *)&param, sizeof(param),
+ result, sizeof(result), 0);
+ if (err < 0)
+ err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
+
+ return (err < 0) ? err : 0;
+}
+
+static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ return 0;
+}
+
+static void cinergyt2_fe_release(struct dvb_frontend *fe)
+{
+ struct cinergyt2_fe_state *state = fe->demodulator_priv;
+ if (state != NULL)
+ kfree(state);
+}
+
+static struct dvb_frontend_ops cinergyt2_fe_ops;
+
+struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
+{
+ struct cinergyt2_fe_state *s = kzalloc(sizeof(
+ struct cinergyt2_fe_state), GFP_KERNEL);
+ if (s == NULL)
+ return NULL;
+
+ s->d = d;
+ memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
+ s->fe.demodulator_priv = s;
+ return &s->fe;
+}
+
+
+static struct dvb_frontend_ops cinergyt2_fe_ops = {
+ .info = {
+ .name = DRIVER_NAME,
+ .type = FE_OFDM,
+ .frequency_min = 174000000,
+ .frequency_max = 862000000,
+ .frequency_stepsize = 166667,
+ .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2
+ | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
+ | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8
+ | FE_CAN_FEC_AUTO | FE_CAN_QPSK
+ | FE_CAN_QAM_16 | FE_CAN_QAM_64
+ | FE_CAN_QAM_AUTO
+ | FE_CAN_TRANSMISSION_MODE_AUTO
+ | FE_CAN_GUARD_INTERVAL_AUTO
+ | FE_CAN_HIERARCHY_AUTO
+ | FE_CAN_RECOVER
+ | FE_CAN_MUTE_TS
+ },
+
+ .release = cinergyt2_fe_release,
+
+ .init = cinergyt2_fe_init,
+ .sleep = cinergyt2_fe_sleep,
+
+ .set_frontend = cinergyt2_fe_set_frontend,
+ .get_frontend = cinergyt2_fe_get_frontend,
+ .get_tune_settings = cinergyt2_fe_get_tune_settings,
+
+ .read_status = cinergyt2_fe_read_status,
+ .read_ber = cinergyt2_fe_read_ber,
+ .read_signal_strength = cinergyt2_fe_read_signal_strength,
+ .read_snr = cinergyt2_fe_read_snr,
+ .read_ucblocks = cinergyt2_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h
new file mode 100644
index 00000000000..11d79eb384c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/cinergyT2.h
@@ -0,0 +1,95 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ * Holger Waechtler <holger@qanu.de>
+ *
+ * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _DVB_USB_CINERGYT2_H_
+#define _DVB_USB_CINERGYT2_H_
+
+#include <linux/usb/input.h>
+
+#define DVB_USB_LOG_PREFIX "cinergyT2"
+#include "dvb-usb.h"
+
+#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
+
+extern int dvb_usb_cinergyt2_debug;
+
+#define deb_info(args...) dprintk(dvb_usb_cinergyt2_debug, 0x001, args)
+#define deb_xfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x002, args)
+#define deb_pll(args...) dprintk(dvb_usb_cinergyt2_debug, 0x004, args)
+#define deb_ts(args...) dprintk(dvb_usb_cinergyt2_debug, 0x008, args)
+#define deb_err(args...) dprintk(dvb_usb_cinergyt2_debug, 0x010, args)
+#define deb_rc(args...) dprintk(dvb_usb_cinergyt2_debug, 0x020, args)
+#define deb_fw(args...) dprintk(dvb_usb_cinergyt2_debug, 0x040, args)
+#define deb_mem(args...) dprintk(dvb_usb_cinergyt2_debug, 0x080, args)
+#define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x100, args)
+
+
+
+enum cinergyt2_ep1_cmd {
+ CINERGYT2_EP1_PID_TABLE_RESET = 0x01,
+ CINERGYT2_EP1_PID_SETUP = 0x02,
+ CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03,
+ CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04,
+ CINERGYT2_EP1_GET_TUNER_STATUS = 0x05,
+ CINERGYT2_EP1_START_SCAN = 0x06,
+ CINERGYT2_EP1_CONTINUE_SCAN = 0x07,
+ CINERGYT2_EP1_GET_RC_EVENTS = 0x08,
+ CINERGYT2_EP1_SLEEP_MODE = 0x09,
+ CINERGYT2_EP1_GET_FIRMWARE_VERSION = 0x0A
+};
+
+
+struct dvbt_get_status_msg {
+ uint32_t freq;
+ uint8_t bandwidth;
+ uint16_t tps;
+ uint8_t flags;
+ uint16_t gain;
+ uint8_t snr;
+ uint32_t viterbi_error_rate;
+ uint32_t rs_error_rate;
+ uint32_t uncorrected_block_count;
+ uint8_t lock_bits;
+ uint8_t prev_lock_bits;
+} __attribute__((packed));
+
+
+struct dvbt_set_parameters_msg {
+ uint8_t cmd;
+ uint32_t freq;
+ uint8_t bandwidth;
+ uint16_t tps;
+ uint8_t flags;
+} __attribute__((packed));
+
+
+extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d);
+
+#endif /* _DVB_USB_CINERGYT2_H_ */
+
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index aaa0b6f0b52..406d7fba369 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -36,6 +36,9 @@
#include "tuner-xc2028.h"
#include "tuner-simple.h"
#include "mxl5005s.h"
+#include "dib7000p.h"
+#include "dib0070.h"
+#include "lgs8gl5.h"
/* debug */
static int dvb_usb_cxusb_debug;
@@ -109,6 +112,25 @@ static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
}
+static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
+ u8 addr, int onoff)
+{
+ u8 o[2] = {addr, onoff};
+ u8 i;
+ int rc;
+
+ rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+ if (rc < 0)
+ return rc;
+ if (i == 0x01)
+ return 0;
+ else {
+ deb_info("gpio_write failed.\n");
+ return -EIO;
+ }
+}
+
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@@ -210,7 +232,7 @@ static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
if (d->state == DVB_USB_STATE_INIT &&
usb_set_interface(d->udev, 0, 0) < 0)
err("set interface failed");
- do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
+ do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
!(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
!(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
if (!ret) {
@@ -262,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
return rc;
}
+static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ int ret;
+ u8 b;
+ ret = cxusb_power_ctrl(d, onoff);
+ if (!onoff)
+ return ret;
+
+ msleep(128);
+ cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1);
+ msleep(100);
+ return ret;
+}
+
static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
@@ -283,6 +319,67 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return 0;
}
+static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
+{
+ int ep = d->props.generic_bulk_ctrl_endpoint;
+ const int timeout = 100;
+ const int junk_len = 32;
+ u8 *junk;
+ int rd_count;
+
+ /* Discard remaining data in video pipe */
+ junk = kmalloc(junk_len, GFP_KERNEL);
+ if (!junk)
+ return;
+ while (1) {
+ if (usb_bulk_msg(d->udev,
+ usb_rcvbulkpipe(d->udev, ep),
+ junk, junk_len, &rd_count, timeout) < 0)
+ break;
+ if (!rd_count)
+ break;
+ }
+ kfree(junk);
+}
+
+static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
+{
+ struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+ const int timeout = 100;
+ const int junk_len = p->u.bulk.buffersize;
+ u8 *junk;
+ int rd_count;
+
+ /* Discard remaining data in video pipe */
+ junk = kmalloc(junk_len, GFP_KERNEL);
+ if (!junk)
+ return;
+ while (1) {
+ if (usb_bulk_msg(d->udev,
+ usb_rcvbulkpipe(d->udev, p->endpoint),
+ junk, junk_len, &rd_count, timeout) < 0)
+ break;
+ if (!rd_count)
+ break;
+ }
+ kfree(junk);
+}
+
+static int cxusb_d680_dmb_streaming_ctrl(
+ struct dvb_usb_adapter *adap, int onoff)
+{
+ if (onoff) {
+ u8 buf[2] = { 0x03, 0x00 };
+ cxusb_d680_dmb_drain_video(adap->dev);
+ return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON,
+ buf, sizeof(buf), NULL, 0);
+ } else {
+ int ret = cxusb_ctrl_msg(adap->dev,
+ CMD_STREAMING_OFF, NULL, 0, NULL, 0);
+ return ret;
+ }
+}
+
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
@@ -335,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
return 0;
}
+static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
+ int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[2];
+ int i;
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
+ return 0;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[0] &&
+ keymap[i].data == ircode[1]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
@@ -422,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
{ 0xfc, 0x00, KEY_UNKNOWN }, /* HD */
};
+static struct dvb_usb_rc_key d680_dmb_rc_keys[] = {
+ { 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */
+ { 0x08, 0x0c, KEY_ZOOM },
+ { 0x08, 0x00, KEY_0 },
+ { 0x00, 0x01, KEY_1 },
+ { 0x08, 0x02, KEY_2 },
+ { 0x00, 0x03, KEY_3 },
+ { 0x08, 0x04, KEY_4 },
+ { 0x00, 0x05, KEY_5 },
+ { 0x08, 0x06, KEY_6 },
+ { 0x00, 0x07, KEY_7 },
+ { 0x08, 0x08, KEY_8 },
+ { 0x00, 0x09, KEY_9 },
+ { 0x00, 0x0a, KEY_MUTE },
+ { 0x08, 0x29, KEY_BACK },
+ { 0x00, 0x12, KEY_CHANNELUP },
+ { 0x08, 0x13, KEY_CHANNELDOWN },
+ { 0x00, 0x2b, KEY_VOLUMEUP },
+ { 0x08, 0x2c, KEY_VOLUMEDOWN },
+ { 0x00, 0x20, KEY_UP },
+ { 0x08, 0x21, KEY_DOWN },
+ { 0x00, 0x11, KEY_LEFT },
+ { 0x08, 0x10, KEY_RIGHT },
+ { 0x00, 0x0d, KEY_OK },
+ { 0x08, 0x1f, KEY_RECORD },
+ { 0x00, 0x17, KEY_PLAYPAUSE },
+ { 0x08, 0x16, KEY_PLAYPAUSE },
+ { 0x00, 0x0b, KEY_STOP },
+ { 0x08, 0x27, KEY_FASTFORWARD },
+ { 0x00, 0x26, KEY_REWIND },
+ { 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */
+ { 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */
+ { 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */
+ { 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */
+ { 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */
+ { 0x00, 0x25, KEY_POWER },
+};
+
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
@@ -527,6 +688,24 @@ static struct mxl5005s_config aver_a868r_tuner = {
.AgcMasterByte = 0x00,
};
+/* FIXME: needs tweaking */
+static struct mxl5005s_config d680_dmb_tuner = {
+ .i2c_address = 0x63,
+ .if_freq = 36125000UL,
+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,
+ .agc_mode = MXL_SINGLE_AGC,
+ .tracking_filter = MXL_TF_C,
+ .rssi_enable = MXL_RSSI_ENABLE,
+ .cap_select = MXL_CAP_SEL_ENABLE,
+ .div_out = MXL_DIV_OUT_4,
+ .clock_out = MXL_CLOCK_OUT_DISABLE,
+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+ .top = MXL5005S_TOP_25P2,
+ .mod_mode = MXL_DIGITAL_MODE,
+ .if_mode = MXL_ZERO_IF,
+ .AgcMasterByte = 0x00,
+};
+
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
@@ -563,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
-static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
+static int dvico_bluebird_xc2028_callback(void *ptr, int component,
+ int command, int arg)
{
struct dvb_usb_adapter *adap = ptr;
struct dvb_usb_device *d = adap->dev;
@@ -591,14 +771,16 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
struct xc2028_config cfg = {
.i2c_adap = &adap->dev->i2c_adap,
.i2c_addr = 0x61,
- .callback = dvico_bluebird_xc2028_callback,
};
static struct xc2028_ctrl ctl = {
- .fname = "xc3028-v27.fw",
+ .fname = XC2028_DEFAULT_FIRMWARE,
.max_len = 64,
.demod = XC3028_FE_ZARLINK456,
};
+ /* FIXME: generalize & move to common area */
+ adap->fe->callback = dvico_bluebird_xc2028_callback;
+
fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
return -EIO;
@@ -615,6 +797,14 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_frontend *fe;
+ fe = dvb_attach(mxl5005s_attach, adap->fe,
+ &adap->dev->i2c_adap, &d680_dmb_tuner);
+ return (fe == NULL) ? -EIO : 0;
+}
+
static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
{
u8 b;
@@ -726,6 +916,159 @@ no_IR:
return 0;
}
+static struct dibx000_agc_config dib7070_agc_config = {
+ .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+
+ /*
+ * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
+ * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+ * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
+ */
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
+ (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+ .inv_gain = 600,
+ .time_stabiliz = 10,
+ .alpha_level = 0,
+ .thlock = 118,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
+ .agc1_max = 65535,
+ .agc1_min = 0,
+ .agc2_max = 65535,
+ .agc2_min = 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 40,
+ .agc1_pt3 = 183,
+ .agc1_slope1 = 206,
+ .agc1_slope2 = 255,
+ .agc2_pt1 = 72,
+ .agc2_pt2 = 152,
+ .agc2_slope1 = 88,
+ .agc2_slope2 = 90,
+ .alpha_mant = 17,
+ .alpha_exp = 27,
+ .beta_mant = 23,
+ .beta_exp = 51,
+ .perform_agc_softsplit = 0,
+};
+
+static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
+ .internal = 60000,
+ .sampling = 15000,
+ .pll_prediv = 1,
+ .pll_ratio = 20,
+ .pll_range = 3,
+ .pll_reset = 1,
+ .pll_bypass = 0,
+ .enable_refdiv = 0,
+ .bypclk_div = 0,
+ .IO_CLK_en_core = 1,
+ .ADClkSrc = 1,
+ .modulo = 2,
+ /* refsel, sel, freq_15k */
+ .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
+ .ifreq = (0 << 25) | 0,
+ .timf = 20452225,
+ .xtal_hz = 12000000,
+};
+
+static struct dib7000p_config cxusb_dualdig4_rev2_config = {
+ .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+ .tuner_is_baseband = 1,
+ .spur_protect = 1,
+
+ .gpio_dir = 0xfcef,
+ .gpio_val = 0x0110,
+
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+};
+
+static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
+
+ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ &cxusb_dualdig4_rev2_config);
+
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ &cxusb_dualdig4_rev2_config);
+ if (adap->fe == NULL)
+ return -EIO;
+
+ return 0;
+}
+
+static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+ return dib7000p_set_gpio(fe, 8, 0, !onoff);
+}
+
+static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+ return 0;
+}
+
+static struct dib0070_config dib7070p_dib0070_config = {
+ .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+ .reset = dib7070_tuner_reset,
+ .sleep = dib7070_tuner_sleep,
+ .clock_khz = 12000,
+};
+
+struct dib0700_adapter_state {
+ int (*set_param_save) (struct dvb_frontend *,
+ struct dvb_frontend_parameters *);
+};
+
+static int dib7070_set_param_override(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ u16 offset;
+ u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ switch (band) {
+ case BAND_VHF: offset = 950; break;
+ default:
+ case BAND_UHF: offset = 550; break;
+ }
+
+ dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+
+ return state->set_param_save(fe, fep);
+}
+
+static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c =
+ dib7000p_get_i2c_master(adap->fe,
+ DIBX000_I2C_INTERFACE_TUNER, 1);
+
+ if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ &dib7070p_dib0070_config) == NULL)
+ return -ENODEV;
+
+ st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+ adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ return 0;
+}
+
static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
@@ -751,6 +1094,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
return -EIO;
}
+static struct lgs8gl5_config lgs8gl5_cfg = {
+ .demod_address = 0x19,
+};
+
+static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ int n;
+
+ /* Select required USB configuration */
+ if (usb_set_interface(d->udev, 0, 0) < 0)
+ err("set interface failed");
+
+ /* Unblock all USB pipes */
+ usb_clear_halt(d->udev,
+ usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+ usb_clear_halt(d->udev,
+ usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+ usb_clear_halt(d->udev,
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+
+ /* Drain USB pipes to avoid hang after reboot */
+ for (n = 0; n < 5; n++) {
+ cxusb_d680_dmb_drain_message(d);
+ cxusb_d680_dmb_drain_video(d);
+ msleep(200);
+ }
+
+ /* Reset the tuner */
+ if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
+ err("clear tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+ if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
+ err("set tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+
+ /* Attach frontend */
+ adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap);
+ if (adap->fe == NULL)
+ return -EIO;
+
+ return 0;
+}
+
/*
* DViCO has shipped two devices with the same USB ID, but only one of them
* needs a firmware download. Check the device class details to see if they
@@ -826,9 +1217,11 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
+static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -852,6 +1245,11 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &cxusb_bluebird_dualdig4_rev2_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
0)
return 0;
@@ -876,6 +1274,8 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
+ { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1321,6 +1721,104 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
}
};
+static
+struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
+ .tuner_attach = cxusb_dualdig4_rev2_tuner_attach,
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ },
+ },
+
+ .power_ctrl = cxusb_bluebird_power_ctrl,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .rc_interval = 100,
+ .rc_key_map = dvico_mce_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
+ .rc_query = cxusb_rc_query,
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
+ { NULL },
+ { &cxusb_table[17], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
+ .frontend_attach = cxusb_d680_dmb_frontend_attach,
+ .tuner_attach = cxusb_d680_dmb_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+ },
+ },
+
+ .power_ctrl = cxusb_d680_dmb_power_ctrl,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .rc_interval = 100,
+ .rc_key_map = d680_dmb_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys),
+ .rc_query = cxusb_d680_dmb_rc_query,
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ "Conexant DMB-TH Stick",
+ { NULL },
+ { &cxusb_table[18], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 66d4dc6ba46..739193943c1 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug;
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
#define REQUEST_SET_RC 0x11
+#define REQUEST_NEW_I2C_READ 0x12
+#define REQUEST_NEW_I2C_WRITE 0x13
#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
@@ -39,6 +41,8 @@ struct dib0700_state {
u8 rc_toggle;
u8 rc_counter;
u8 is_dib7000pc;
+ u8 fw_use_new_i2c_api;
+ u8 disable_streaming_master_mode;
};
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 595a04696c8..dd53cee3896 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
}
/*
- * I2C master xfer function
+ * I2C master xfer function (supported in 1.20 firmware)
*/
-static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
+static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ /* The new i2c firmware messages are more reliable and in particular
+ properly support i2c read calls not preceded by a write */
+
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */
+ uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
+ uint8_t en_start = 0;
+ uint8_t en_stop = 0;
+ uint8_t buf[255]; /* TBV: malloc ? */
+ int result, i;
+
+ /* Ensure nobody else hits the i2c bus while we're sending our
+ sequence of messages, (such as the remote control thread) */
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ for (i = 0; i < num; i++) {
+ if (i == 0) {
+ /* First message in the transaction */
+ en_start = 1;
+ } else if (!(msg[i].flags & I2C_M_NOSTART)) {
+ /* Device supports repeated-start */
+ en_start = 1;
+ } else {
+ /* Not the first packet and device doesn't support
+ repeated start */
+ en_start = 0;
+ }
+ if (i == (num - 1)) {
+ /* Last message in the transaction */
+ en_stop = 1;
+ }
+
+ if (msg[i].flags & I2C_M_RD) {
+ /* Read request */
+ u16 index, value;
+ uint8_t i2c_dest;
+
+ i2c_dest = (msg[i].addr << 1);
+ value = ((en_start << 7) | (en_stop << 6) |
+ (msg[i].len & 0x3F)) << 8 | i2c_dest;
+ /* I2C ctrl + FE bus; */
+ index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+
+ result = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev, 0),
+ REQUEST_NEW_I2C_READ,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value, index, msg[i].buf,
+ msg[i].len,
+ USB_CTRL_GET_TIMEOUT);
+ if (result < 0) {
+ err("i2c read error (status = %d)\n", result);
+ break;
+ }
+ } else {
+ /* Write request */
+ buf[0] = REQUEST_NEW_I2C_WRITE;
+ buf[1] = (msg[i].addr << 1);
+ buf[2] = (en_start << 7) | (en_stop << 6) |
+ (msg[i].len & 0x3F);
+ /* I2C ctrl + FE bus; */
+ buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+ /* The Actual i2c payload */
+ memcpy(&buf[4], msg[i].buf, msg[i].len);
+
+ result = usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev, 0),
+ REQUEST_NEW_I2C_WRITE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ 0, 0, buf, msg[i].len + 4,
+ USB_CTRL_GET_TIMEOUT);
+ if (result < 0) {
+ err("i2c write error (status = %d)\n", result);
+ break;
+ }
+ }
+ }
+ mutex_unlock(&d->i2c_mutex);
+ return i;
+}
+
+/*
+ * I2C master xfer function (pre-1.20 firmware)
+ */
+static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+ struct i2c_msg *msg, int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i,len;
@@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num
return i;
}
+static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct dib0700_state *st = d->priv;
+
+ if (st->fw_use_new_i2c_api == 1) {
+ /* User running at least fw 1.20 */
+ return dib0700_i2c_xfer_new(adap, msg, num);
+ } else {
+ /* Use legacy calls */
+ return dib0700_i2c_xfer_legacy(adap, msg, num);
+ }
+}
+
static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
@@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
b[0] = REQUEST_ENABLE_VIDEO;
b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
- b[2] = (0x01 << 4); /* Master mode */
+
+ if (st->disable_streaming_master_mode == 1)
+ b[2] = 0x00;
+ else
+ b[2] = (0x01 << 4); /* Master mode */
+
b[3] = 0x00;
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 3dd20bfbed3..0cfccc24b19 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -14,6 +14,8 @@
#include "mt2060.h"
#include "mt2266.h"
#include "tuner-xc2028.h"
+#include "xc5000.h"
+#include "s5h1411.h"
#include "dib0070.h"
static int force_lna_activation;
@@ -366,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
};
-static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
+static int stk7700ph_xc3028_callback(void *ptr, int component,
+ int command, int arg)
{
struct dvb_usb_adapter *adap = ptr;
@@ -394,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
static struct xc2028_config stk7700ph_xc3028_config = {
.i2c_addr = 0x61,
- .callback = stk7700ph_xc3028_callback,
.ctrl = &stk7700ph_xc3028_ctrl,
};
@@ -435,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
DIBX000_I2C_INTERFACE_TUNER, 1);
stk7700ph_xc3028_config.i2c_adap = tun_i2c;
- stk7700ph_xc3028_config.video_dev = adap;
+
+ /* FIXME: generalize & move to common area */
+ adap->fe->callback = stk7700ph_xc3028_callback;
return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
== NULL ? -ENODEV : 0;
@@ -677,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
{ 0x01, 0x7d, KEY_VOLUMEDOWN },
{ 0x02, 0x42, KEY_CHANNELUP },
{ 0x00, 0x7d, KEY_CHANNELDOWN },
+
+ /* Key codes for Nova-TD "credit card" remote control. */
+ { 0x1d, 0x00, KEY_0 },
+ { 0x1d, 0x01, KEY_1 },
+ { 0x1d, 0x02, KEY_2 },
+ { 0x1d, 0x03, KEY_3 },
+ { 0x1d, 0x04, KEY_4 },
+ { 0x1d, 0x05, KEY_5 },
+ { 0x1d, 0x06, KEY_6 },
+ { 0x1d, 0x07, KEY_7 },
+ { 0x1d, 0x08, KEY_8 },
+ { 0x1d, 0x09, KEY_9 },
+ { 0x1d, 0x0a, KEY_TEXT },
+ { 0x1d, 0x0d, KEY_MENU },
+ { 0x1d, 0x0f, KEY_MUTE },
+ { 0x1d, 0x10, KEY_VOLUMEUP },
+ { 0x1d, 0x11, KEY_VOLUMEDOWN },
+ { 0x1d, 0x12, KEY_CHANNEL },
+ { 0x1d, 0x14, KEY_UP },
+ { 0x1d, 0x15, KEY_DOWN },
+ { 0x1d, 0x16, KEY_LEFT },
+ { 0x1d, 0x17, KEY_RIGHT },
+ { 0x1d, 0x1c, KEY_TV },
+ { 0x1d, 0x1e, KEY_NEXT },
+ { 0x1d, 0x1f, KEY_BACK },
+ { 0x1d, 0x20, KEY_CHANNELUP },
+ { 0x1d, 0x21, KEY_CHANNELDOWN },
+ { 0x1d, 0x24, KEY_LAST },
+ { 0x1d, 0x25, KEY_OK },
+ { 0x1d, 0x30, KEY_PAUSE },
+ { 0x1d, 0x32, KEY_REWIND },
+ { 0x1d, 0x34, KEY_FASTFORWARD },
+ { 0x1d, 0x35, KEY_PLAY },
+ { 0x1d, 0x36, KEY_STOP },
+ { 0x1d, 0x37, KEY_RECORD },
+ { 0x1d, 0x3b, KEY_GOTO },
+ { 0x1d, 0x3d, KEY_POWER },
};
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@@ -1078,6 +1119,97 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe == NULL ? -ENODEV : 0;
}
+/* S5H1411 */
+static struct s5h1411_config pinnacle_801e_config = {
+ .output_mode = S5H1411_PARALLEL_OUTPUT,
+ .gpio = S5H1411_GPIO_OFF,
+ .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+ .qam_if = S5H1411_IF_44000,
+ .vsb_if = S5H1411_IF_44000,
+ .inversion = S5H1411_INVERSION_OFF,
+ .status_mode = S5H1411_DEMODLOCKING
+};
+
+/* Pinnacle PCTV HD Pro 801e GPIOs map:
+ GPIO0 - currently unknown
+ GPIO1 - xc5000 tuner reset
+ GPIO2 - CX25843 sleep
+ GPIO3 - currently unknown
+ GPIO4 - currently unknown
+ GPIO6 - currently unknown
+ GPIO7 - currently unknown
+ GPIO9 - currently unknown
+ GPIO10 - CX25843 reset
+ */
+static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_state *st = adap->dev->priv;
+
+ /* Make use of the new i2c functions from FW 1.20 */
+ st->fw_use_new_i2c_api = 1;
+
+ /* The s5h1411 requires the dib0700 to not be in master mode */
+ st->disable_streaming_master_mode = 1;
+
+ /* All msleep values taken from Windows USB trace */
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(400);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ msleep(60);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(30);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0);
+ msleep(30);
+
+ /* Put the CX25843 to sleep for now since we're in digital mode */
+ dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
+
+ /* GPIOs are initialized, do the attach */
+ adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+ &adap->dev->i2c_adap);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int dib0700_xc5000_tuner_callback(void *priv, int component,
+ int command, int arg)
+{
+ struct dvb_usb_adapter *adap = priv;
+
+ if (command == XC5000_TUNER_RESET) {
+ /* Reset the tuner */
+ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
+ msleep(330); /* from Windows USB trace */
+ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
+ msleep(330); /* from Windows USB trace */
+ } else {
+ err("xc5000: unknown tuner callback command: %d\n", command);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct xc5000_config s5h1411_xc5000_tunerconfig = {
+ .i2c_address = 0x64,
+ .if_khz = 5380,
+};
+
+static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ /* FIXME: generalize & move to common area */
+ adap->fe->callback = dib0700_xc5000_tuner_callback;
+
+ return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+ &s5h1411_xc5000_tunerconfig)
+ == NULL ? -ENODEV : 0;
+}
+
/* DVB-USB and USB stuff follows */
struct usb_device_id dib0700_usb_id_table[] = {
/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
@@ -1117,7 +1249,13 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) },
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
+/* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
+ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) },
+ { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) },
+ { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) },
+ { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) },
+/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1125,7 +1263,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
.usb_ctrl = DEVICE_SPECIFIC, \
- .firmware = "dvb-usb-dib0700-1.10.fw", \
+ .firmware = "dvb-usb-dib0700-1.20.fw", \
.download_firmware = dib0700_download_firmware, \
.no_reconnect = 1, \
.size_of_priv = sizeof(struct dib0700_state), \
@@ -1292,7 +1430,12 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[31], NULL },
{ NULL },
}
- }
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
@@ -1373,7 +1516,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}
},
- .num_device_descs = 3,
+ .num_device_descs = 4,
.devices = {
{ "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL },
@@ -1386,6 +1529,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Hauppauge Nova-TD Stick (52009)",
{ &dib0700_usb_id_table[35], NULL },
{ NULL },
+ },
+ { "Hauppauge Nova-TD-500 (84xxx)",
+ { &dib0700_usb_id_table[36], NULL },
+ { NULL },
}
}
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -1403,7 +1550,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 3,
+ .num_device_descs = 5,
.devices = {
{ "Terratec Cinergy HT USB XE",
{ &dib0700_usb_id_table[27], NULL },
@@ -1417,6 +1564,47 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[32], NULL },
{ NULL },
},
+ { "Gigabyte U8000-RH",
+ { &dib0700_usb_id_table[37], NULL },
+ { NULL },
+ },
+ { "YUAN High-Tech STK7700PH",
+ { &dib0700_usb_id_table[38], NULL },
+ { NULL },
+ },
+ { "Asus My Cinema-U3000Hybrid",
+ { &dib0700_usb_id_table[39], NULL },
+ { NULL },
+ },
+ },
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .frontend_attach = s5h1411_frontend_attach,
+ .tuner_attach = xc5000_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+ .size_of_priv = sizeof(struct
+ dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "Pinnacle PCTV HD Pro USB Stick",
+ { &dib0700_usb_id_table[40], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV HD USB Stick",
+ { &dib0700_usb_id_table[41], NULL },
+ { NULL },
+ },
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c
new file mode 100644
index 00000000000..078ce92ca43
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtv5100.c
@@ -0,0 +1,240 @@
+/*
+ * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
+ *
+ * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com>
+ * http://royale.zerezo.com/dtv5100/
+ *
+ * Inspired by gl861.c and au6610.c drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "dtv5100.h"
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_dtv5100_debug;
+module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
+ u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+ u8 request;
+ u8 type;
+ u16 value;
+ u16 index;
+
+ switch (wlen) {
+ case 1:
+ /* write { reg }, read { value } */
+ request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
+ DTV5100_TUNER_READ);
+ type = USB_TYPE_VENDOR | USB_DIR_IN;
+ value = 0;
+ break;
+ case 2:
+ /* write { reg, value } */
+ request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
+ DTV5100_TUNER_WRITE);
+ type = USB_TYPE_VENDOR | USB_DIR_OUT;
+ value = wbuf[1];
+ break;
+ default:
+ warn("wlen = %x, aborting.", wlen);
+ return -EINVAL;
+ }
+ index = (addr << 8) + wbuf[0];
+
+ msleep(1); /* avoid I2C errors */
+ return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
+ type, value, index, rbuf, rlen,
+ DTV5100_USB_TIMEOUT);
+}
+
+/* I2C */
+static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i;
+
+ if (num > 2)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ for (i = 0; i < num; i++) {
+ /* write/read request */
+ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+ if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
+ msg[i].len, msg[i+1].buf,
+ msg[i+1].len) < 0)
+ break;
+ i++;
+ } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
+ msg[i].len, NULL, 0) < 0)
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return i;
+}
+
+static u32 dtv5100_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dtv5100_i2c_algo = {
+ .master_xfer = dtv5100_i2c_xfer,
+ .functionality = dtv5100_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static struct zl10353_config dtv5100_zl10353_config = {
+ .demod_address = DTV5100_DEMOD_ADDR,
+ .no_tuner = 1,
+ .parallel_ts = 1,
+};
+
+static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe == NULL)
+ return -EIO;
+
+ /* disable i2c gate, or it won't work... is this safe? */
+ adap->fe->ops.i2c_gate_ctrl = NULL;
+
+ return 0;
+}
+
+static struct qt1010_config dtv5100_qt1010_config = {
+ .i2c_address = DTV5100_TUNER_ADDR
+};
+
+static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ return dvb_attach(qt1010_attach,
+ adap->fe, &adap->dev->i2c_adap,
+ &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties dtv5100_properties;
+
+static int dtv5100_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int i, ret;
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ /* initialize non qt1010/zl10353 part? */
+ for (i = 0; dtv5100_init[i].request; i++) {
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ dtv5100_init[i].request,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ dtv5100_init[i].value,
+ dtv5100_init[i].index, NULL, 0,
+ DTV5100_USB_TIMEOUT);
+ if (ret)
+ return ret;
+ }
+
+ ret = dvb_usb_device_init(intf, &dtv5100_properties,
+ THIS_MODULE, NULL, adapter_nr);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct usb_device_id dtv5100_table[] = {
+ { USB_DEVICE(0x06be, 0xa232) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, dtv5100_table);
+
+static struct dvb_usb_device_properties dtv5100_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+
+ .size_of_priv = 0,
+
+ .num_adapters = 1,
+ .adapter = {{
+ .frontend_attach = dtv5100_frontend_attach,
+ .tuner_attach = dtv5100_tuner_attach,
+
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ } },
+
+ .i2c_algo = &dtv5100_i2c_algo,
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ .name = "AME DTV-5100 USB2.0 DVB-T",
+ .cold_ids = { NULL },
+ .warm_ids = { &dtv5100_table[0], NULL },
+ },
+ }
+};
+
+static struct usb_driver dtv5100_driver = {
+ .name = "dvb_usb_dtv5100",
+ .probe = dtv5100_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = dtv5100_table,
+};
+
+/* module stuff */
+static int __init dtv5100_module_init(void)
+{
+ int ret;
+
+ ret = usb_register(&dtv5100_driver);
+ if (ret)
+ err("usb_register failed. Error number %d", ret);
+
+ return ret;
+}
+
+static void __exit dtv5100_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&dtv5100_driver);
+}
+
+module_init(dtv5100_module_init);
+module_exit(dtv5100_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h
new file mode 100644
index 00000000000..93e96e04a82
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtv5100.h
@@ -0,0 +1,51 @@
+/*
+ * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
+ *
+ * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com>
+ * http://royale.zerezo.com/dtv5100/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _DVB_USB_DTV5100_H_
+#define _DVB_USB_DTV5100_H_
+
+#define DVB_USB_LOG_PREFIX "dtv5100"
+#include "dvb-usb.h"
+
+#define DTV5100_USB_TIMEOUT 500
+
+#define DTV5100_DEMOD_ADDR 0x00
+#define DTV5100_DEMOD_WRITE 0xc0
+#define DTV5100_DEMOD_READ 0xc1
+
+#define DTV5100_TUNER_ADDR 0xc4
+#define DTV5100_TUNER_WRITE 0xc7
+#define DTV5100_TUNER_READ 0xc8
+
+#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
+#define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T"
+
+static struct {
+ u8 request;
+ u8 value;
+ u16 index;
+} dtv5100_init[] = {
+ { 0x000000c5, 0x00000000, 0x00000001 },
+ { 0x000000c5, 0x00000001, 0x00000001 },
+ { } /* Terminating entry */
+};
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 029b437caf9..7380b94b3b3 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -22,6 +22,7 @@
#define USB_VID_AVERMEDIA 0x07ca
#define USB_VID_COMPRO 0x185b
#define USB_VID_COMPRO_UNK 0x145f
+#define USB_VID_CONEXANT 0x0572
#define USB_VID_CYPRESS 0x04b4
#define USB_VID_DIBCOM 0x10b8
#define USB_VID_DPOSH 0x1498
@@ -33,16 +34,19 @@
#define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_KWORLD 0xeb2a
+#define USB_VID_KWORLD_2 0x1b80
#define USB_VID_KYE 0x0458
#define USB_VID_LEADTEK 0x0413
#define USB_VID_LITEON 0x04ca
#define USB_VID_MEDION 0x1660
#define USB_VID_MIGLIA 0x18f3
#define USB_VID_MSI 0x0db0
+#define USB_VID_MSI_2 0x1462
#define USB_VID_OPERA1 0x695c
#define USB_VID_PINNACLE 0x2304
#define USB_VID_TECHNOTREND 0x0b48
#define USB_VID_TERRATEC 0x0ccd
+#define USB_VID_TELESTAR 0x10b9
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
@@ -50,15 +54,18 @@
#define USB_VID_WIDEVIEW 0x14aa
#define USB_VID_GIGABYTE 0x1044
#define USB_VID_YUAN 0x1164
-
+#define USB_VID_XTENSIONS 0x1ae7
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
#define USB_PID_ADSTECH_USB2_WARM 0xa334
#define USB_PID_AFATECH_AF9005 0x9020
+#define USB_PID_AFATECH_AF9015_9015 0x9015
+#define USB_PID_AFATECH_AF9015_9016 0x9016
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
#define USB_PID_ANYSEE 0x861f
+#define USB_PID_AZUREWAVE_AD_TU700 0x3237
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -69,6 +76,7 @@
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
+#define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
@@ -87,9 +95,12 @@
#define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
+#define USB_PID_KWORLD_399U 0xe399
+#define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
+#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
@@ -98,6 +109,7 @@
#define USB_PID_TWINHAN_VP7045_WARM 0x3206
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
+#define USB_PID_TINYTWIN 0x3226
#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
@@ -129,6 +141,7 @@
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
+#define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
@@ -143,6 +156,9 @@
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039
#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039
+#define USB_PID_AVERMEDIA_VOLAR_X 0xa815
+#define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150
+#define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
@@ -152,8 +168,11 @@
#define USB_PID_PINNACLE_PCTV2000E 0x022c
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
+#define USB_PID_PINNACLE_PCTV71E 0x022b
#define USB_PID_PINNACLE_PCTV72E 0x0236
#define USB_PID_PINNACLE_PCTV73E 0x0237
+#define USB_PID_PINNACLE_PCTV801E 0x023a
+#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
@@ -170,6 +189,7 @@
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
+#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
@@ -189,6 +209,7 @@
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01
+#define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029
#define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
#define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201
#define USB_PID_GENPIX_8PSK_REV_2 0x0202
@@ -196,14 +217,21 @@
#define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204
#define USB_PID_SIGMATEK_DVB_110 0x6610
#define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513
+#define USB_PID_MSI_DIGIVOX_DUO 0x8801
#define USB_PID_OPERA1_COLD 0x2830
#define USB_PID_OPERA1_WARM 0x3829
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
#define USB_PID_GIGABYTE_U7000 0x7001
+#define USB_PID_GIGABYTE_U8000 0x7002
#define USB_PID_ASUS_U3000 0x171f
+#define USB_PID_ASUS_U3000H 0x1736
#define USB_PID_ASUS_U3100 0x173f
#define USB_PID_YUAN_EC372S 0x1edc
+#define USB_PID_YUAN_STK7700PH 0x1f08
#define USB_PID_DW2102 0x2102
+#define USB_PID_XTENSIONS_XD_380 0x0381
+#define USB_PID_TELESTAR_STARSTICK_2 0x8000
+#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#endif
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index a4d898b44e5..6286fbbe7fb 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,4 +1,5 @@
-/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card
+/* DVB USB framework compliant Linux driver for the
+* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
*
* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
*
@@ -10,62 +11,74 @@
*/
#include <linux/version.h>
#include "dw2102.h"
+#include "si21xx.h"
#include "stv0299.h"
#include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "eds1547.h"
+#include "cx24116.h"
#ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102
#endif
-#define DW2102_READ_MSG 0
-#define DW2102_WRITE_MSG 1
+#ifndef USB_PID_DW2104
+#define USB_PID_DW2104 0x2104
+#endif
+
+#define DW210X_READ_MSG 0
+#define DW210X_WRITE_MSG 1
#define REG_1F_SYMBOLRATE_BYTE0 0x1f
#define REG_20_SYMBOLRATE_BYTE1 0x20
#define REG_21_SYMBOLRATE_BYTE2 0x21
-
+/* on my own*/
#define DW2102_VOLTAGE_CTRL (0x1800)
#define DW2102_RC_QUERY (0x1a00)
-struct dw2102_state {
+struct dw210x_state {
u32 last_key_pressed;
};
-struct dw2102_rc_keys {
+struct dw210x_rc_keys {
u32 keycode;
u32 event;
};
+/* debug */
+static int dvb_usb_dw2102_debug;
+module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
+
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value,
- u8 *data, u16 len, int flags)
+static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
+ u16 index, u8 * data, u16 len, int flags)
{
int ret;
u8 u8buf[len];
- unsigned int pipe = (flags == DW2102_READ_MSG) ?
- usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
- u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+ unsigned int pipe = (flags == DW210X_READ_MSG) ?
+ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
+ u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
- if (flags == DW2102_WRITE_MSG)
+ if (flags == DW210X_WRITE_MSG)
memcpy(u8buf, data, len);
- ret = usb_control_msg(dev, pipe, request,
- request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000);
+ ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
+ value, index , u8buf, len, 2000);
- if (flags == DW2102_READ_MSG)
+ if (flags == DW210X_READ_MSG)
memcpy(data, u8buf, len);
return ret;
}
/* I2C */
-
static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, ret = 0;
u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
- u8 request;
u16 value;
if (!d)
@@ -76,14 +89,12 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
switch (num) {
case 2:
/* read stv0299 register */
- request = 0xb5;
value = msg[0].buf[0];/* register */
for (i = 0; i < msg[1].len; i++) {
value = value + i;
- ret = dw2102_op_rw(d->udev, 0xb5,
- value, buf6, 2, DW2102_READ_MSG);
+ ret = dw210x_op_rw(d->udev, 0xb5, value, 0,
+ buf6, 2, DW210X_READ_MSG);
msg[1].buf[i] = buf6[0];
-
}
break;
case 1:
@@ -93,8 +104,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
buf6[0] = 0x2a;
buf6[1] = msg[0].buf[0];
buf6[2] = msg[0].buf[1];
- ret = dw2102_op_rw(d->udev, 0xb2,
- 0, buf6, 3, DW2102_WRITE_MSG);
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ buf6, 3, DW210X_WRITE_MSG);
break;
case 0x60:
if (msg[0].flags == 0) {
@@ -106,28 +117,156 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
buf6[4] = msg[0].buf[1];
buf6[5] = msg[0].buf[2];
buf6[6] = msg[0].buf[3];
- ret = dw2102_op_rw(d->udev, 0xb2,
- 0, buf6, 7, DW2102_WRITE_MSG);
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ buf6, 7, DW210X_WRITE_MSG);
} else {
- /* write to tuner pll */
- ret = dw2102_op_rw(d->udev, 0xb5,
- 0, buf6, 1, DW2102_READ_MSG);
+ /* read from tuner */
+ ret = dw210x_op_rw(d->udev, 0xb5, 0, 0,
+ buf6, 1, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
}
break;
case (DW2102_RC_QUERY):
- ret = dw2102_op_rw(d->udev, 0xb8,
- 0, buf6, 2, DW2102_READ_MSG);
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ buf6, 2, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
msg[0].buf[1] = buf6[1];
break;
case (DW2102_VOLTAGE_CTRL):
buf6[0] = 0x30;
buf6[1] = msg[0].buf[0];
- ret = dw2102_op_rw(d->udev, 0xb2,
- 0, buf6, 2, DW2102_WRITE_MSG);
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ buf6, 2, DW210X_WRITE_MSG);
+ break;
+ }
+
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+
+static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0;
+ u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2:
+ /* read si2109 register by number */
+ buf6[0] = 0xd0;
+ buf6[1] = msg[0].len;
+ buf6[2] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ buf6, msg[0].len + 2, DW210X_WRITE_MSG);
+ /* read si2109 register */
+ ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
+ buf6, msg[1].len + 2, DW210X_READ_MSG);
+ memcpy(msg[1].buf, buf6 + 2, msg[1].len);
+
+ break;
+ case 1:
+ switch (msg[0].addr) {
+ case 0x68:
+ /* write to si2109 register */
+ buf6[0] = 0xd0;
+ buf6[1] = msg[0].len;
+ memcpy(buf6 + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
+ msg[0].len + 2, DW210X_WRITE_MSG);
+ break;
+ case(DW2102_RC_QUERY):
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ buf6, 2, DW210X_READ_MSG);
+ msg[0].buf[0] = buf6[0];
+ msg[0].buf[1] = buf6[1];
+ break;
+ case(DW2102_VOLTAGE_CTRL):
+ buf6[0] = 0x30;
+ buf6[1] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ buf6, 2, DW210X_WRITE_MSG);
+ break;
+ }
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0;
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2: {
+ /* read */
+ /* first write first register number */
+ u8 ibuf [msg[1].len + 2], obuf[3];
+ obuf[0] = 0xd0;
+ obuf[1] = msg[0].len;
+ obuf[2] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ /* second read registers */
+ ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
+ ibuf, msg[1].len + 2, DW210X_READ_MSG);
+ memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+ break;
+ }
+ case 1:
+ switch (msg[0].addr) {
+ case 0x68: {
+ /* write to register */
+ u8 obuf[msg[0].len + 2];
+ obuf[0] = 0xd0;
+ obuf[1] = msg[0].len;
+ memcpy(obuf + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ break;
+ }
+ case 0x61: {
+ /* write to tuner */
+ u8 obuf[msg[0].len + 2];
+ obuf[0] = 0xc2;
+ obuf[1] = msg[0].len;
+ memcpy(obuf + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
+ case(DW2102_RC_QUERY): {
+ u8 ibuf[2];
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ ibuf, 2, DW210X_READ_MSG);
+ memcpy(msg[0].buf, ibuf , 2);
+ break;
+ }
+ case(DW2102_VOLTAGE_CTRL): {
+ u8 obuf[2];
+ obuf[0] = 0x30;
+ obuf[1] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ obuf, 2, DW210X_WRITE_MSG);
+ break;
+ }
+ }
break;
}
@@ -136,17 +275,137 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
return num;
}
-static u32 dw2102_i2c_func(struct i2c_adapter *adapter)
+static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0;
+ int len, i;
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2: {
+ /* read */
+ /* first write first register number */
+ u8 ibuf [msg[1].len + 2], obuf[3];
+ obuf[0] = 0xaa;
+ obuf[1] = msg[0].len;
+ obuf[2] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ /* second read registers */
+ ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0,
+ ibuf, msg[1].len + 2, DW210X_READ_MSG);
+ memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+ break;
+ }
+ case 1:
+ switch (msg[0].addr) {
+ case 0x55: {
+ if (msg[0].buf[0] == 0xf7) {
+ /* firmware */
+ /* Write in small blocks */
+ u8 obuf[19];
+ obuf[0] = 0xaa;
+ obuf[1] = 0x11;
+ obuf[2] = 0xf7;
+ len = msg[0].len - 1;
+ i = 1;
+ do {
+ memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG);
+ i += 16;
+ len -= 16;
+ } while (len > 0);
+ } else {
+ /* write to register */
+ u8 obuf[msg[0].len + 2];
+ obuf[0] = 0xaa;
+ obuf[1] = msg[0].len;
+ memcpy(obuf + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ }
+ break;
+ }
+ case(DW2102_RC_QUERY): {
+ u8 ibuf[2];
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ ibuf, 2, DW210X_READ_MSG);
+ memcpy(msg[0].buf, ibuf , 2);
+ break;
+ }
+ case(DW2102_VOLTAGE_CTRL): {
+ u8 obuf[2];
+ obuf[0] = 0x30;
+ obuf[1] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ obuf, 2, DW210X_WRITE_MSG);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+
+static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm dw2102_i2c_algo = {
.master_xfer = dw2102_i2c_transfer,
- .functionality = dw2102_i2c_func,
+ .functionality = dw210x_i2c_func,
+};
+
+static struct i2c_algorithm dw2102_serit_i2c_algo = {
+ .master_xfer = dw2102_serit_i2c_transfer,
+ .functionality = dw210x_i2c_func,
+};
+
+static struct i2c_algorithm dw2102_earda_i2c_algo = {
+ .master_xfer = dw2102_earda_i2c_transfer,
+ .functionality = dw210x_i2c_func,
};
-static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static struct i2c_algorithm dw2104_i2c_algo = {
+ .master_xfer = dw2104_i2c_transfer,
+ .functionality = dw210x_i2c_func,
+};
+
+static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+ int i;
+ u8 ibuf[] = {0, 0};
+ u8 eeprom[256], eepromline[16];
+
+ for (i = 0; i < 256; i++) {
+ if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
+ err("read eeprom failed.");
+ return -1;
+ } else {
+ eepromline[i%16] = ibuf[0];
+ eeprom[i] = ibuf[0];
+ }
+ if ((i % 16) == 15) {
+ deb_xfer("%02x: ", i - 15);
+ debug_dump(eepromline, 16, deb_xfer);
+ }
+ }
+ memcpy(mac, eeprom + 8, 6);
+ return 0;
+};
+
+static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
static u8 command_13v[1] = {0x00};
static u8 command_18v[1] = {0x01};
@@ -163,18 +422,78 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
return 0;
}
-static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+static struct stv0299_config sharp_z0194a_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
+static struct cx24116_config dw2104_config = {
+ .demod_address = 0x55,
+ .mpg_clk_pos_pol = 0x01,
+};
+
+static struct si21xx_config serit_sp1511lhb_config = {
+ .demod_address = 0x68,
+ .min_delay_ms = 100,
+
+};
+
+static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{
- d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
- &d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw2102_set_voltage;
- info("Attached stv0299!\n");
+ if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+ &d->dev->i2c_adap)) != NULL) {
+ d->fe->ops.set_voltage = dw210x_set_voltage;
+ info("Attached cx24116!\n");
return 0;
}
return -EIO;
}
+static struct dvb_usb_device_properties dw2102_properties;
+
+static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+{
+ if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
+ /*dw2102_properties.adapter->tuner_attach = NULL;*/
+ d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+ &d->dev->i2c_adap);
+ if (d->fe != NULL) {
+ d->fe->ops.set_voltage = dw210x_set_voltage;
+ info("Attached si21xx!\n");
+ return 0;
+ }
+ }
+ if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
+ /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
+ d->fe = dvb_attach(stv0288_attach, &earda_config,
+ &d->dev->i2c_adap);
+ if (d->fe != NULL) {
+ d->fe->ops.set_voltage = dw210x_set_voltage;
+ info("Attached stv0288!\n");
+ return 0;
+ }
+ }
+
+ if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
+ /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
+ d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+ &d->dev->i2c_adap);
+ if (d->fe != NULL) {
+ d->fe->ops.set_voltage = dw210x_set_voltage;
+ info("Attached stv0299!\n");
+ return 0;
+ }
+ }
+ return -EIO;
+}
+
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -182,7 +501,15 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
-static struct dvb_usb_rc_key dw2102_rc_keys[] = {
+static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(stb6000_attach, adap->fe, 0x61,
+ &adap->dev->i2c_adap);
+
+ return 0;
+}
+
+static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x0a, KEY_Q }, /*power*/
{ 0xf8, 0x0c, KEY_M }, /*mute*/
{ 0xf8, 0x11, KEY_1 },
@@ -221,7 +548,7 @@ static struct dvb_usb_rc_key dw2102_rc_keys[] = {
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
- struct dw2102_state *st = d->priv;
+ struct dw210x_state *st = d->priv;
u8 key[2];
struct i2c_msg msg[] = {
{.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
@@ -231,12 +558,12 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
*state = REMOTE_NO_KEY_PRESSED;
if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
- for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) {
- if (dw2102_rc_keys[i].data == msg[0].buf[0]) {
+ for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
+ if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
*state = REMOTE_KEY_PRESSED;
- *event = dw2102_rc_keys[i].event;
+ *event = dw210x_rc_keys[i].event;
st->last_key_pressed =
- dw2102_rc_keys[i].event;
+ dw210x_rc_keys[i].event;
break;
}
st->last_key_pressed = 0;
@@ -249,6 +576,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+ {USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
+ {USB_DEVICE(0x9022, 0xd650)},
{ }
};
@@ -260,7 +589,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
u8 *b, *p;
int ret = 0, i;
u8 reset;
- u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0};
+ u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
const struct firmware *fw;
const char *filename = "dvb-usb-dw2101.fw";
switch (dev->descriptor.idProduct) {
@@ -273,25 +602,23 @@ static int dw2102_load_firmware(struct usb_device *dev,
return ret;
}
break;
- case USB_PID_DW2102:
+ default:
fw = frmwr;
break;
}
- info("start downloading DW2102 firmware");
+ info("start downloading DW210X firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
- dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG);
- dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG);
+ dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
+ dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
- if (dw2102_op_rw
- (dev, 0xa0, i, b , 0x40,
- DW2102_WRITE_MSG) != 0x40
- ) {
+ if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
+ DW210X_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
@@ -299,43 +626,66 @@ static int dw2102_load_firmware(struct usb_device *dev,
}
/* restart the CPU */
reset = 0;
- if (ret || dw2102_op_rw
- (dev, 0xa0, 0x7f92, &reset, 1,
- DW2102_WRITE_MSG) != 1) {
+ if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
+ DW210X_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
- if (ret || dw2102_op_rw
- (dev, 0xa0, 0xe600, &reset, 1,
- DW2102_WRITE_MSG) != 1) {
+ if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
+ DW210X_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
/* init registers */
switch (dev->descriptor.idProduct) {
- case USB_PID_DW2102:
- dw2102_op_rw
- (dev, 0xbf, 0x0040, &reset, 0,
- DW2102_WRITE_MSG);
- dw2102_op_rw
- (dev, 0xb9, 0x0000, &reset16[0], 2,
- DW2102_READ_MSG);
+ case USB_PID_DW2104:
+ case 0xd650:
+ reset = 1;
+ dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
+ DW210X_WRITE_MSG);
+ reset = 0;
+ dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
+ DW210X_WRITE_MSG);
break;
+ case USB_PID_DW2102:
+ dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
+ DW210X_WRITE_MSG);
+ dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
+ DW210X_READ_MSG);
+ /* check STV0299 frontend */
+ dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
+ DW210X_READ_MSG);
+ if (reset16[0] == 0xa1) {
+ dw2102_properties.i2c_algo = &dw2102_i2c_algo;
+ dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+ break;
+ } else {
+ /* check STV0288 frontend */
+ reset16[0] = 0xd0;
+ reset16[1] = 1;
+ reset16[2] = 0;
+ dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
+ DW210X_WRITE_MSG);
+ dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
+ DW210X_READ_MSG);
+ if (reset16[2] == 0x11) {
+ dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
+ dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;
+ break;
+ }
+ }
case 0x2101:
- dw2102_op_rw
- (dev, 0xbc, 0x0030, &reset16[0], 2,
- DW2102_READ_MSG);
- dw2102_op_rw
- (dev, 0xba, 0x0000, &reset16[0], 7,
- DW2102_READ_MSG);
- dw2102_op_rw
- (dev, 0xba, 0x0000, &reset16[0], 7,
- DW2102_READ_MSG);
- dw2102_op_rw
- (dev, 0xb9, 0x0000, &reset16[0], 2,
- DW2102_READ_MSG);
+ dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
+ DW210X_READ_MSG);
+ dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
+ DW210X_READ_MSG);
+ dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
+ DW210X_READ_MSG);
+ dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
+ DW210X_READ_MSG);
break;
}
+ msleep(100);
kfree(p);
}
return ret;
@@ -345,12 +695,12 @@ static struct dvb_usb_device_properties dw2102_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2102.fw",
- .size_of_priv = sizeof(struct dw2102_state),
+ .size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1,
- .i2c_algo = &dw2102_i2c_algo,
- .rc_key_map = dw2102_rc_keys,
- .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys),
+ .i2c_algo = &dw2102_serit_i2c_algo,
+ .rc_key_map = dw210x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
.rc_interval = 150,
.rc_query = dw2102_rc_query,
@@ -358,11 +708,12 @@ static struct dvb_usb_device_properties dw2102_properties = {
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
- .adapter = {
+ .read_mac_address = dw210x_read_mac_address,
+ .adapter = {
{
.frontend_attach = dw2102_frontend_attach,
.streaming_ctrl = NULL,
- .tuner_attach = dw2102_tuner_attach,
+ .tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
@@ -388,11 +739,64 @@ static struct dvb_usb_device_properties dw2102_properties = {
}
};
+static struct dvb_usb_device_properties dw2104_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-dw2104.fw",
+ .size_of_priv = sizeof(struct dw210x_state),
+ .no_reconnect = 1,
+
+ .i2c_algo = &dw2104_i2c_algo,
+ .rc_key_map = dw210x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
+ .rc_interval = 150,
+ .rc_query = dw2102_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x81,
+ /* parameter for the MPEG2-data transfer */
+ .num_adapters = 1,
+ .download_firmware = dw2102_load_firmware,
+ .read_mac_address = dw210x_read_mac_address,
+ .adapter = {
+ {
+ .frontend_attach = dw2104_frontend_attach,
+ .streaming_ctrl = NULL,
+ /*.tuner_attach = dw2104_tuner_attach,*/
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "DVBWorld DW2104 USB2.0",
+ {&dw2102_table[2], NULL},
+ {NULL},
+ },
+ { "TeVii S650 USB2.0",
+ {&dw2102_table[3], NULL},
+ {NULL},
+ },
+ }
+};
+
static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf, &dw2102_properties,
- THIS_MODULE, NULL, adapter_nr);
+ if (0 == dvb_usb_device_init(intf, &dw2102_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &dw2104_properties,
+ THIS_MODULE, NULL, adapter_nr)) {
+ return 0;
+ }
+ return -ENODEV;
}
static struct usb_driver dw2102_driver = {
@@ -420,6 +824,6 @@ module_init(dw2102_module_init);
module_exit(dw2102_module_exit);
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
index 7a310f90683..e3370734e95 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.h
+++ b/drivers/media/dvb/dvb-usb/dw2102.h
@@ -4,6 +4,5 @@
#define DVB_USB_LOG_PREFIX "dw2102"
#include "dvb-usb.h"
-extern int dvb_usb_dw2102_debug;
#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
#endif
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 7dbb4a223c9..96b93e21a84 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -43,6 +43,20 @@ config DVB_S5H1420
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_STV0288
+ tristate "ST STV0288 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STB6000
+ tristate "ST STB6000 silicon tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
config DVB_STV0299
tristate "ST STV0299 based"
depends on DVB_CORE && I2C
@@ -92,6 +106,20 @@ config DVB_TUA6100
help
A DVB-S PLL chip.
+config DVB_CX24116
+ tristate "Conexant CX24116 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+
+config DVB_SI21XX
+ tristate "Silicon Labs SI21XX based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
@@ -385,4 +413,23 @@ config DVB_ISL6421
help
An SEC control chip.
+config DVB_LGS8GL5
+ tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DMB-TH tuner module. Say Y when you want to support this frontend.
+
+comment "Tools to develop new frontends"
+
+config DVB_DUMMY_FE
+ tristate "Dummy frontend driver"
+ default n
+
+config DVB_AF9013
+ tristate "Afatech AF9013 demodulator"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ Say Y when you want to support this frontend.
endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 028da55611c..aba79f4a63a 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -48,3 +48,10 @@ obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
obj-$(CONFIG_DVB_AU8522) += au8522.o
obj-$(CONFIG_DVB_TDA10048) += tda10048.o
obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
+obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
+obj-$(CONFIG_DVB_AF9013) += af9013.o
+obj-$(CONFIG_DVB_CX24116) += cx24116.o
+obj-$(CONFIG_DVB_SI21XX) += si21xx.o
+obj-$(CONFIG_DVB_STV0288) += stv0288.o
+obj-$(CONFIG_DVB_STB6000) += stb6000.o
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
new file mode 100644
index 00000000000..21c1060cf10
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9013.c
@@ -0,0 +1,1685 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "af9013_priv.h"
+#include "af9013.h"
+
+int af9013_debug;
+
+struct af9013_state {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend frontend;
+
+ struct af9013_config config;
+
+ u16 signal_strength;
+ u32 ber;
+ u32 ucblocks;
+ u16 snr;
+ u32 frequency;
+ unsigned long next_statistics_check;
+};
+
+static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+
+static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg,
+ u8 *val, u8 len)
+{
+ u8 buf[3+len];
+ struct i2c_msg msg = {
+ .addr = state->config.demod_address,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf };
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xff;
+ buf[2] = mbox;
+ memcpy(&buf[3], val, len);
+
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ warn("I2C write failed reg:%04x len:%d", reg, len);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val,
+ u8 len)
+{
+ u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7);
+ return af9013_write_regs(state, mbox, reg, val, len);
+}
+
+static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
+ u8 len)
+{
+ u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7);
+ return af9013_write_regs(state, mbox, reg, val, len);
+}
+
+/* write single register */
+static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val)
+{
+ return af9013_write_ofdm_regs(state, reg, &val, 1);
+}
+
+/* read single register */
+static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val)
+{
+ u8 obuf[3] = { reg >> 8, reg & 0xff, 0 };
+ u8 ibuf[1];
+ struct i2c_msg msg[2] = {
+ {
+ .addr = state->config.demod_address,
+ .flags = 0,
+ .len = sizeof(obuf),
+ .buf = obuf
+ }, {
+ .addr = state->config.demod_address,
+ .flags = I2C_M_RD,
+ .len = sizeof(ibuf),
+ .buf = ibuf
+ }
+ };
+
+ if (i2c_transfer(state->i2c, msg, 2) != 2) {
+ warn("I2C read failed reg:%04x", reg);
+ return -EREMOTEIO;
+ }
+ *val = ibuf[0];
+ return 0;
+}
+
+static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
+ u8 len, u8 val)
+{
+ int ret;
+ u8 tmp, mask;
+
+ ret = af9013_read_reg(state, reg, &tmp);
+ if (ret)
+ return ret;
+
+ mask = regmask[len - 1] << pos;
+ tmp = (tmp & ~mask) | ((val << pos) & mask);
+
+ return af9013_write_reg(state, reg, tmp);
+}
+
+static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
+ u8 len, u8 *val)
+{
+ int ret;
+ u8 tmp;
+
+ ret = af9013_read_reg(state, reg, &tmp);
+ if (ret)
+ return ret;
+ *val = (tmp >> pos) & regmask[len - 1];
+ return 0;
+}
+
+static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
+{
+ int ret;
+ u8 pos;
+ u16 addr;
+ deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval);
+
+/* GPIO0 & GPIO1 0xd735
+ GPIO2 & GPIO3 0xd736 */
+
+ switch (gpio) {
+ case 0:
+ case 1:
+ addr = 0xd735;
+ break;
+ case 2:
+ case 3:
+ addr = 0xd736;
+ break;
+
+ default:
+ err("invalid gpio:%d\n", gpio);
+ ret = -EINVAL;
+ goto error;
+ };
+
+ switch (gpio) {
+ case 0:
+ case 2:
+ pos = 0;
+ break;
+ case 1:
+ case 3:
+ default:
+ pos = 4;
+ break;
+ };
+
+ ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval);
+
+error:
+ return ret;
+}
+
+static u32 af913_div(u32 a, u32 b, u32 x)
+{
+ u32 r = 0, c = 0, i;
+ deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x);
+
+ if (a > b) {
+ c = a / b;
+ a = a - c * b;
+ }
+
+ for (i = 0; i < x; i++) {
+ if (a >= b) {
+ r += 1;
+ a -= b;
+ }
+ a <<= 1;
+ r <<= 1;
+ }
+ r = (c << (u32)x) + r;
+
+ deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r);
+ return r;
+}
+
+static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw)
+{
+ int ret = 0;
+ u8 i = 0;
+ u8 buf[24];
+ u32 ns_coeff1_2048nu;
+ u32 ns_coeff1_8191nu;
+ u32 ns_coeff1_8192nu;
+ u32 ns_coeff1_8193nu;
+ u32 ns_coeff2_2k;
+ u32 ns_coeff2_8k;
+
+ deb_info("%s: adc_clock:%d bw:%d\n", __func__,
+ state->config.adc_clock, bw);
+
+ switch (state->config.adc_clock) {
+ case 28800: /* 28.800 MHz */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ ns_coeff1_2048nu = 0x01e79e7a;
+ ns_coeff1_8191nu = 0x0079eb6e;
+ ns_coeff1_8192nu = 0x0079e79e;
+ ns_coeff1_8193nu = 0x0079e3cf;
+ ns_coeff2_2k = 0x00f3cf3d;
+ ns_coeff2_8k = 0x003cf3cf;
+ break;
+ case BANDWIDTH_7_MHZ:
+ ns_coeff1_2048nu = 0x0238e38e;
+ ns_coeff1_8191nu = 0x008e3d55;
+ ns_coeff1_8192nu = 0x008e38e4;
+ ns_coeff1_8193nu = 0x008e3472;
+ ns_coeff2_2k = 0x011c71c7;
+ ns_coeff2_8k = 0x00471c72;
+ break;
+ case BANDWIDTH_8_MHZ:
+ ns_coeff1_2048nu = 0x028a28a3;
+ ns_coeff1_8191nu = 0x00a28f3d;
+ ns_coeff1_8192nu = 0x00a28a29;
+ ns_coeff1_8193nu = 0x00a28514;
+ ns_coeff2_2k = 0x01451451;
+ ns_coeff2_8k = 0x00514514;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ case 20480: /* 20.480 MHz */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ ns_coeff1_2048nu = 0x02adb6dc;
+ ns_coeff1_8191nu = 0x00ab7313;
+ ns_coeff1_8192nu = 0x00ab6db7;
+ ns_coeff1_8193nu = 0x00ab685c;
+ ns_coeff2_2k = 0x0156db6e;
+ ns_coeff2_8k = 0x0055b6dc;
+ break;
+ case BANDWIDTH_7_MHZ:
+ ns_coeff1_2048nu = 0x03200001;
+ ns_coeff1_8191nu = 0x00c80640;
+ ns_coeff1_8192nu = 0x00c80000;
+ ns_coeff1_8193nu = 0x00c7f9c0;
+ ns_coeff2_2k = 0x01900000;
+ ns_coeff2_8k = 0x00640000;
+ break;
+ case BANDWIDTH_8_MHZ:
+ ns_coeff1_2048nu = 0x03924926;
+ ns_coeff1_8191nu = 0x00e4996e;
+ ns_coeff1_8192nu = 0x00e49249;
+ ns_coeff1_8193nu = 0x00e48b25;
+ ns_coeff2_2k = 0x01c92493;
+ ns_coeff2_8k = 0x00724925;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ case 28000: /* 28.000 MHz */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ ns_coeff1_2048nu = 0x01f58d10;
+ ns_coeff1_8191nu = 0x007d672f;
+ ns_coeff1_8192nu = 0x007d6344;
+ ns_coeff1_8193nu = 0x007d5f59;
+ ns_coeff2_2k = 0x00fac688;
+ ns_coeff2_8k = 0x003eb1a2;
+ break;
+ case BANDWIDTH_7_MHZ:
+ ns_coeff1_2048nu = 0x02492492;
+ ns_coeff1_8191nu = 0x00924db7;
+ ns_coeff1_8192nu = 0x00924925;
+ ns_coeff1_8193nu = 0x00924492;
+ ns_coeff2_2k = 0x01249249;
+ ns_coeff2_8k = 0x00492492;
+ break;
+ case BANDWIDTH_8_MHZ:
+ ns_coeff1_2048nu = 0x029cbc15;
+ ns_coeff1_8191nu = 0x00a7343f;
+ ns_coeff1_8192nu = 0x00a72f05;
+ ns_coeff1_8193nu = 0x00a729cc;
+ ns_coeff2_2k = 0x014e5e0a;
+ ns_coeff2_8k = 0x00539783;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ case 25000: /* 25.000 MHz */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ ns_coeff1_2048nu = 0x0231bcb5;
+ ns_coeff1_8191nu = 0x008c7391;
+ ns_coeff1_8192nu = 0x008c6f2d;
+ ns_coeff1_8193nu = 0x008c6aca;
+ ns_coeff2_2k = 0x0118de5b;
+ ns_coeff2_8k = 0x00463797;
+ break;
+ case BANDWIDTH_7_MHZ:
+ ns_coeff1_2048nu = 0x028f5c29;
+ ns_coeff1_8191nu = 0x00a3dc29;
+ ns_coeff1_8192nu = 0x00a3d70a;
+ ns_coeff1_8193nu = 0x00a3d1ec;
+ ns_coeff2_2k = 0x0147ae14;
+ ns_coeff2_8k = 0x0051eb85;
+ break;
+ case BANDWIDTH_8_MHZ:
+ ns_coeff1_2048nu = 0x02ecfb9d;
+ ns_coeff1_8191nu = 0x00bb44c1;
+ ns_coeff1_8192nu = 0x00bb3ee7;
+ ns_coeff1_8193nu = 0x00bb390d;
+ ns_coeff2_2k = 0x01767dce;
+ ns_coeff2_8k = 0x005d9f74;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ err("invalid xtal");
+ return -EINVAL;
+ }
+ if (ret) {
+ err("invalid bandwidth");
+ return ret;
+ }
+
+ buf[i++] = (u8) ((ns_coeff1_2048nu & 0x03000000) >> 24);
+ buf[i++] = (u8) ((ns_coeff1_2048nu & 0x00ff0000) >> 16);
+ buf[i++] = (u8) ((ns_coeff1_2048nu & 0x0000ff00) >> 8);
+ buf[i++] = (u8) ((ns_coeff1_2048nu & 0x000000ff));
+ buf[i++] = (u8) ((ns_coeff2_2k & 0x01c00000) >> 22);
+ buf[i++] = (u8) ((ns_coeff2_2k & 0x003fc000) >> 14);
+ buf[i++] = (u8) ((ns_coeff2_2k & 0x00003fc0) >> 6);
+ buf[i++] = (u8) ((ns_coeff2_2k & 0x0000003f));
+ buf[i++] = (u8) ((ns_coeff1_8191nu & 0x03000000) >> 24);
+ buf[i++] = (u8) ((ns_coeff1_8191nu & 0x00ffc000) >> 16);
+ buf[i++] = (u8) ((ns_coeff1_8191nu & 0x0000ff00) >> 8);
+ buf[i++] = (u8) ((ns_coeff1_8191nu & 0x000000ff));
+ buf[i++] = (u8) ((ns_coeff1_8192nu & 0x03000000) >> 24);
+ buf[i++] = (u8) ((ns_coeff1_8192nu & 0x00ffc000) >> 16);
+ buf[i++] = (u8) ((ns_coeff1_8192nu & 0x0000ff00) >> 8);
+ buf[i++] = (u8) ((ns_coeff1_8192nu & 0x000000ff));
+ buf[i++] = (u8) ((ns_coeff1_8193nu & 0x03000000) >> 24);
+ buf[i++] = (u8) ((ns_coeff1_8193nu & 0x00ffc000) >> 16);
+ buf[i++] = (u8) ((ns_coeff1_8193nu & 0x0000ff00) >> 8);
+ buf[i++] = (u8) ((ns_coeff1_8193nu & 0x000000ff));
+ buf[i++] = (u8) ((ns_coeff2_8k & 0x01c00000) >> 22);
+ buf[i++] = (u8) ((ns_coeff2_8k & 0x003fc000) >> 14);
+ buf[i++] = (u8) ((ns_coeff2_8k & 0x00003fc0) >> 6);
+ buf[i++] = (u8) ((ns_coeff2_8k & 0x0000003f));
+
+ deb_info("%s: coeff:", __func__);
+ debug_dump(buf, sizeof(buf), deb_info);
+
+ /* program */
+ for (i = 0; i < sizeof(buf); i++) {
+ ret = af9013_write_reg(state, 0xae00 + i, buf[i]);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int af9013_set_adc_ctrl(struct af9013_state *state)
+{
+ int ret;
+ u8 buf[3], tmp, i;
+ u32 adc_cw;
+
+ deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock);
+
+ /* adc frequency type */
+ switch (state->config.adc_clock) {
+ case 28800: /* 28.800 MHz */
+ tmp = 0;
+ break;
+ case 20480: /* 20.480 MHz */
+ tmp = 1;
+ break;
+ case 28000: /* 28.000 MHz */
+ tmp = 2;
+ break;
+ case 25000: /* 25.000 MHz */
+ tmp = 3;
+ break;
+ default:
+ err("invalid xtal");
+ return -EINVAL;
+ }
+
+ adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul);
+
+ buf[0] = (u8) ((adc_cw & 0x000000ff));
+ buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8);
+ buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16);
+
+ deb_info("%s: adc_cw:", __func__);
+ debug_dump(buf, sizeof(buf), deb_info);
+
+ /* program */
+ for (i = 0; i < sizeof(buf); i++) {
+ ret = af9013_write_reg(state, 0xd180 + i, buf[i]);
+ if (ret)
+ goto error;
+ }
+ ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp);
+error:
+ return ret;
+}
+
+static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw)
+{
+ int ret;
+ u16 addr;
+ u8 buf[3], i, j;
+ u32 adc_freq, freq_cw;
+ s8 bfs_spec_inv;
+ int if_sample_freq;
+
+ for (j = 0; j < 3; j++) {
+ if (j == 0) {
+ addr = 0xd140; /* fcw normal */
+ bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
+ } else if (j == 1) {
+ addr = 0x9be7; /* fcw dummy ram */
+ bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
+ } else {
+ addr = 0x9bea; /* fcw inverted */
+ bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1;
+ }
+
+ adc_freq = state->config.adc_clock * 1000;
+ if_sample_freq = state->config.tuner_if * 1000;
+
+ /* TDA18271 uses different sampling freq for every bw */
+ if (state->config.tuner == AF9013_TUNER_TDA18271) {
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ if_sample_freq = 3300000; /* 3.3 MHz */
+ break;
+ case BANDWIDTH_7_MHZ:
+ if_sample_freq = 3800000; /* 3.8 MHz */
+ break;
+ case BANDWIDTH_8_MHZ:
+ default:
+ if_sample_freq = 4300000; /* 4.3 MHz */
+ break;
+ }
+ }
+
+ while (if_sample_freq > (adc_freq / 2))
+ if_sample_freq = if_sample_freq - adc_freq;
+
+ if (if_sample_freq >= 0)
+ bfs_spec_inv = bfs_spec_inv * (-1);
+ else
+ if_sample_freq = if_sample_freq * (-1);
+
+ freq_cw = af913_div(if_sample_freq, adc_freq, 23ul);
+
+ if (bfs_spec_inv == -1)
+ freq_cw = 0x00800000 - freq_cw;
+
+ buf[0] = (u8) ((freq_cw & 0x000000ff));
+ buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8);
+ buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16);
+
+
+ deb_info("%s: freq_cw:", __func__);
+ debug_dump(buf, sizeof(buf), deb_info);
+
+ /* program */
+ for (i = 0; i < sizeof(buf); i++) {
+ ret = af9013_write_reg(state, addr++, buf[i]);
+ if (ret)
+ goto error;
+ }
+ }
+error:
+ return ret;
+}
+
+static int af9013_set_ofdm_params(struct af9013_state *state,
+ struct dvb_ofdm_parameters *params, u8 *auto_mode)
+{
+ int ret;
+ u8 i, buf[3] = {0, 0, 0};
+ *auto_mode = 0; /* set if parameters are requested to auto set */
+
+ switch (params->transmission_mode) {
+ case TRANSMISSION_MODE_AUTO:
+ *auto_mode = 1;
+ case TRANSMISSION_MODE_2K:
+ break;
+ case TRANSMISSION_MODE_8K:
+ buf[0] |= (1 << 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->guard_interval) {
+ case GUARD_INTERVAL_AUTO:
+ *auto_mode = 1;
+ case GUARD_INTERVAL_1_32:
+ break;
+ case GUARD_INTERVAL_1_16:
+ buf[0] |= (1 << 2);
+ break;
+ case GUARD_INTERVAL_1_8:
+ buf[0] |= (2 << 2);
+ break;
+ case GUARD_INTERVAL_1_4:
+ buf[0] |= (3 << 2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->hierarchy_information) {
+ case HIERARCHY_AUTO:
+ *auto_mode = 1;
+ case HIERARCHY_NONE:
+ break;
+ case HIERARCHY_1:
+ buf[0] |= (1 << 4);
+ break;
+ case HIERARCHY_2:
+ buf[0] |= (2 << 4);
+ break;
+ case HIERARCHY_4:
+ buf[0] |= (3 << 4);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ switch (params->constellation) {
+ case QAM_AUTO:
+ *auto_mode = 1;
+ case QPSK:
+ break;
+ case QAM_16:
+ buf[1] |= (1 << 6);
+ break;
+ case QAM_64:
+ buf[1] |= (2 << 6);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Use HP. How and which case we can switch to LP? */
+ buf[1] |= (1 << 4);
+
+ switch (params->code_rate_HP) {
+ case FEC_AUTO:
+ *auto_mode = 1;
+ case FEC_1_2:
+ break;
+ case FEC_2_3:
+ buf[2] |= (1 << 0);
+ break;
+ case FEC_3_4:
+ buf[2] |= (2 << 0);
+ break;
+ case FEC_5_6:
+ buf[2] |= (3 << 0);
+ break;
+ case FEC_7_8:
+ buf[2] |= (4 << 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->code_rate_LP) {
+ case FEC_AUTO:
+ /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO
+ by dvb_frontend.c for compatibility */
+ if (params->hierarchy_information != HIERARCHY_NONE)
+ *auto_mode = 1;
+ case FEC_1_2:
+ break;
+ case FEC_2_3:
+ buf[2] |= (1 << 3);
+ break;
+ case FEC_3_4:
+ buf[2] |= (2 << 3);
+ break;
+ case FEC_5_6:
+ buf[2] |= (3 << 3);
+ break;
+ case FEC_7_8:
+ buf[2] |= (4 << 3);
+ break;
+ case FEC_NONE:
+ if (params->hierarchy_information == HIERARCHY_AUTO)
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ break;
+ case BANDWIDTH_7_MHZ:
+ buf[1] |= (1 << 2);
+ break;
+ case BANDWIDTH_8_MHZ:
+ buf[1] |= (2 << 2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* program */
+ for (i = 0; i < sizeof(buf); i++) {
+ ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int af9013_reset(struct af9013_state *state, u8 sleep)
+{
+ int ret;
+ u8 tmp, i;
+ deb_info("%s\n", __func__);
+
+ /* enable OFDM reset */
+ ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1);
+ if (ret)
+ goto error;
+
+ /* start reset mechanism */
+ ret = af9013_write_reg(state, 0xaeff, 1);
+ if (ret)
+ goto error;
+
+ /* reset is done when bit 1 is set */
+ for (i = 0; i < 150; i++) {
+ ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ break; /* reset done */
+ msleep(10);
+ }
+ if (!tmp)
+ return -ETIMEDOUT;
+
+ /* don't clear reset when going to sleep */
+ if (!sleep) {
+ /* clear OFDM reset */
+ ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+ if (ret)
+ goto error;
+
+ /* disable OFDM reset */
+ ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+ }
+error:
+ return ret;
+}
+
+static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
+{
+ int ret;
+ deb_info("%s: onoff:%d\n", __func__, onoff);
+
+ if (onoff) {
+ /* power on */
+ ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0);
+ if (ret)
+ goto error;
+ ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+ if (ret)
+ goto error;
+ ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+ } else {
+ /* power off */
+ ret = af9013_reset(state, 1);
+ if (ret)
+ goto error;
+ ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1);
+ }
+error:
+ return ret;
+}
+
+static int af9013_lock_led(struct af9013_state *state, u8 onoff)
+{
+ deb_info("%s: onoff:%d\n", __func__, onoff);
+
+ return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff);
+}
+
+static int af9013_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ u8 auto_mode; /* auto set TPS */
+
+ deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
+ params->u.ofdm.bandwidth);
+
+ state->frequency = params->frequency;
+
+ /* program CFOE coefficients */
+ ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
+ if (ret)
+ goto error;
+
+ /* program frequency control */
+ ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth);
+ if (ret)
+ goto error;
+
+ /* clear TPS lock flag (inverted flag) */
+ ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1);
+ if (ret)
+ goto error;
+
+ /* clear MPEG2 lock flag */
+ ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0);
+ if (ret)
+ goto error;
+
+ /* empty channel function */
+ ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0);
+ if (ret)
+ goto error;
+
+ /* empty DVB-T channel function */
+ ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0);
+ if (ret)
+ goto error;
+
+ /* program tuner */
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe, params);
+
+ /* program TPS and bandwidth, check if auto mode needed */
+ ret = af9013_set_ofdm_params(state, &params->u.ofdm, &auto_mode);
+ if (ret)
+ goto error;
+
+ if (auto_mode) {
+ /* clear easy mode flag */
+ ret = af9013_write_reg(state, 0xaefd, 0);
+ deb_info("%s: auto TPS\n", __func__);
+ } else {
+ /* set easy mode flag */
+ ret = af9013_write_reg(state, 0xaefd, 1);
+ if (ret)
+ goto error;
+ ret = af9013_write_reg(state, 0xaefe, 0);
+ deb_info("%s: manual TPS\n", __func__);
+ }
+ if (ret)
+ goto error;
+
+ /* everything is set, lets try to receive channel - OFSM GO! */
+ ret = af9013_write_reg(state, 0xffff, 0);
+ if (ret)
+ goto error;
+
+error:
+ return ret;
+}
+
+static int af9013_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ u8 i, buf[3];
+ deb_info("%s\n", __func__);
+
+ /* read TPS registers */
+ for (i = 0; i < 3; i++) {
+ ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+
+ switch ((buf[1] >> 6) & 3) {
+ case 0:
+ p->u.ofdm.constellation = QPSK;
+ break;
+ case 1:
+ p->u.ofdm.constellation = QAM_16;
+ break;
+ case 2:
+ p->u.ofdm.constellation = QAM_64;
+ break;
+ }
+
+ switch ((buf[0] >> 0) & 3) {
+ case 0:
+ p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ }
+
+ switch ((buf[0] >> 2) & 3) {
+ case 0:
+ p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ break;
+ }
+
+ switch ((buf[0] >> 4) & 7) {
+ case 0:
+ p->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ p->u.ofdm.hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ p->u.ofdm.hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ p->u.ofdm.hierarchy_information = HIERARCHY_4;
+ break;
+ }
+
+ switch ((buf[2] >> 0) & 7) {
+ case 0:
+ p->u.ofdm.code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ p->u.ofdm.code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ p->u.ofdm.code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ p->u.ofdm.code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ p->u.ofdm.code_rate_HP = FEC_7_8;
+ break;
+ }
+
+ switch ((buf[2] >> 3) & 7) {
+ case 0:
+ p->u.ofdm.code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ p->u.ofdm.code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ p->u.ofdm.code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ p->u.ofdm.code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ p->u.ofdm.code_rate_LP = FEC_7_8;
+ break;
+ }
+
+ switch ((buf[1] >> 2) & 3) {
+ case 0:
+ p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ break;
+ case 1:
+ p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ break;
+ case 2:
+ p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ break;
+ }
+
+ p->inversion = INVERSION_AUTO;
+ p->frequency = state->frequency;
+
+error:
+ return ret;
+}
+
+static int af9013_update_ber_unc(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ u8 buf[3], i;
+ u32 error_bit_count = 0;
+ u32 total_bit_count = 0;
+ u32 abort_packet_count = 0;
+
+ state->ber = 0;
+
+ /* check if error bit count is ready */
+ ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]);
+ if (ret)
+ goto error;
+ if (!buf[0])
+ goto exit;
+
+ /* get RSD packet abort count */
+ for (i = 0; i < 2; i++) {
+ ret = af9013_read_reg(state, 0xd38a + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ abort_packet_count = (buf[1] << 8) + buf[0];
+
+ /* get error bit count */
+ for (i = 0; i < 3; i++) {
+ ret = af9013_read_reg(state, 0xd387 + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+ error_bit_count = error_bit_count - abort_packet_count * 8 * 8;
+
+ /* get used RSD counting period (10000 RSD packets used) */
+ for (i = 0; i < 2; i++) {
+ ret = af9013_read_reg(state, 0xd385 + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ total_bit_count = (buf[1] << 8) + buf[0];
+ total_bit_count = total_bit_count - abort_packet_count;
+ total_bit_count = total_bit_count * 204 * 8;
+
+ if (total_bit_count)
+ state->ber = error_bit_count * 1000000000 / total_bit_count;
+
+ state->ucblocks += abort_packet_count;
+
+ deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__,
+ error_bit_count, total_bit_count, abort_packet_count);
+
+ /* set BER counting range */
+ ret = af9013_write_reg(state, 0xd385, 10000 & 0xff);
+ if (ret)
+ goto error;
+ ret = af9013_write_reg(state, 0xd386, 10000 >> 8);
+ if (ret)
+ goto error;
+ /* reset and start BER counter */
+ ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1);
+ if (ret)
+ goto error;
+
+exit:
+error:
+ return ret;
+}
+
+static int af9013_update_snr(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ u8 buf[3], i, len;
+ u32 quant = 0;
+ struct snr_table *snr_table;
+
+ /* check if quantizer ready (for snr) */
+ ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]);
+ if (ret)
+ goto error;
+ if (buf[0]) {
+ /* quantizer ready - read it */
+ for (i = 0; i < 3; i++) {
+ ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ quant = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+ /* read current constellation */
+ ret = af9013_read_reg(state, 0xd3c1, &buf[0]);
+ if (ret)
+ goto error;
+
+ switch ((buf[0] >> 6) & 3) {
+ case 0:
+ len = ARRAY_SIZE(qpsk_snr_table);
+ snr_table = qpsk_snr_table;
+ break;
+ case 1:
+ len = ARRAY_SIZE(qam16_snr_table);
+ snr_table = qam16_snr_table;
+ break;
+ case 2:
+ len = ARRAY_SIZE(qam64_snr_table);
+ snr_table = qam64_snr_table;
+ break;
+ default:
+ len = 0;
+ break;
+ }
+
+ if (len) {
+ for (i = 0; i < len; i++) {
+ if (quant < snr_table[i].val) {
+ state->snr = snr_table[i].snr * 10;
+ break;
+ }
+ }
+ }
+
+ /* set quantizer super frame count */
+ ret = af9013_write_reg(state, 0xd2e2, 1);
+ if (ret)
+ goto error;
+
+ /* check quantizer availability */
+ for (i = 0; i < 10; i++) {
+ msleep(10);
+ ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1,
+ &buf[0]);
+ if (ret)
+ goto error;
+ if (!buf[0])
+ break;
+ }
+
+ /* reset quantizer */
+ ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1);
+ if (ret)
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+static int af9013_update_signal_strength(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ u8 tmp0;
+ u8 rf_gain, rf_50, rf_80, if_gain, if_50, if_80;
+ int signal_strength;
+
+ deb_info("%s\n", __func__);
+
+ state->signal_strength = 0;
+
+ ret = af9013_read_reg_bits(state, 0x9bee, 0, 1, &tmp0);
+ if (ret)
+ goto error;
+ if (tmp0) {
+ ret = af9013_read_reg(state, 0x9bbd, &rf_50);
+ if (ret)
+ goto error;
+ ret = af9013_read_reg(state, 0x9bd0, &rf_80);
+ if (ret)
+ goto error;
+ ret = af9013_read_reg(state, 0x9be2, &if_50);
+ if (ret)
+ goto error;
+ ret = af9013_read_reg(state, 0x9be4, &if_80);
+ if (ret)
+ goto error;
+ ret = af9013_read_reg(state, 0xd07c, &rf_gain);
+ if (ret)
+ goto error;
+ ret = af9013_read_reg(state, 0xd07d, &if_gain);
+ if (ret)
+ goto error;
+ signal_strength = (0xffff / (9 * (rf_50 + if_50) - \
+ 11 * (rf_80 + if_80))) * (10 * (rf_gain + if_gain) - \
+ 11 * (rf_80 + if_80));
+ if (signal_strength < 0)
+ signal_strength = 0;
+ else if (signal_strength > 0xffff)
+ signal_strength = 0xffff;
+
+ state->signal_strength = signal_strength;
+ }
+
+error:
+ return ret;
+}
+
+static int af9013_update_statistics(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+
+ if (time_before(jiffies, state->next_statistics_check))
+ return 0;
+
+ /* set minimum statistic update interval */
+ state->next_statistics_check = jiffies + msecs_to_jiffies(1200);
+
+ ret = af9013_update_signal_strength(fe);
+ if (ret)
+ goto error;
+ ret = af9013_update_snr(fe);
+ if (ret)
+ goto error;
+ ret = af9013_update_ber_unc(fe);
+ if (ret)
+ goto error;
+
+error:
+ return ret;
+}
+
+static int af9013_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *fesettings)
+{
+ fesettings->min_delay_ms = 800;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+
+ return 0;
+}
+
+static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret = 0;
+ u8 tmp;
+ *status = 0;
+
+ /* TPS lock */
+ ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+ /* MPEG2 lock */
+ ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ if (!*status & FE_HAS_SIGNAL) {
+ /* AGC lock */
+ ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ *status |= FE_HAS_SIGNAL;
+ }
+
+ if (!*status & FE_HAS_CARRIER) {
+ /* CFO lock */
+ ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ *status |= FE_HAS_CARRIER;
+ }
+
+ if (!*status & FE_HAS_CARRIER) {
+ /* SFOE lock */
+ ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
+ if (ret)
+ goto error;
+ if (tmp)
+ *status |= FE_HAS_CARRIER;
+ }
+
+ ret = af9013_update_statistics(fe);
+
+error:
+ return ret;
+}
+
+
+static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ ret = af9013_update_statistics(fe);
+ *ber = state->ber;
+ return ret;
+}
+
+static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ ret = af9013_update_statistics(fe);
+ *strength = state->signal_strength;
+ return ret;
+}
+
+static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ ret = af9013_update_statistics(fe);
+ *snr = state->snr;
+ return ret;
+}
+
+static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ ret = af9013_update_statistics(fe);
+ *ucblocks = state->ucblocks;
+ return ret;
+}
+
+static int af9013_sleep(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+ deb_info("%s\n", __func__);
+
+ ret = af9013_lock_led(state, 0);
+ if (ret)
+ goto error;
+
+ ret = af9013_power_ctrl(state, 0);
+error:
+ return ret;
+}
+
+static int af9013_init(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret, i, len;
+ u8 tmp0, tmp1;
+ struct regdesc *init;
+ deb_info("%s\n", __func__);
+
+ /* reset OFDM */
+ ret = af9013_reset(state, 0);
+ if (ret)
+ goto error;
+
+ /* power on */
+ ret = af9013_power_ctrl(state, 1);
+ if (ret)
+ goto error;
+
+ /* enable ADC */
+ ret = af9013_write_reg(state, 0xd73a, 0xa4);
+ if (ret)
+ goto error;
+
+ /* write API version to firmware */
+ for (i = 0; i < sizeof(state->config.api_version); i++) {
+ ret = af9013_write_reg(state, 0x9bf2 + i,
+ state->config.api_version[i]);
+ if (ret)
+ goto error;
+ }
+
+ /* program ADC control */
+ ret = af9013_set_adc_ctrl(state);
+ if (ret)
+ goto error;
+
+ /* set I2C master clock */
+ ret = af9013_write_reg(state, 0xd416, 0x14);
+ if (ret)
+ goto error;
+
+ /* set 16 embx */
+ ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1);
+ if (ret)
+ goto error;
+
+ /* set no trigger */
+ ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0);
+ if (ret)
+ goto error;
+
+ /* set read-update bit for constellation */
+ ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1);
+ if (ret)
+ goto error;
+
+ /* enable FEC monitor */
+ ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1);
+ if (ret)
+ goto error;
+
+ /* load OFSM settings */
+ deb_info("%s: load ofsm settings\n", __func__);
+ len = ARRAY_SIZE(ofsm_init);
+ init = ofsm_init;
+ for (i = 0; i < len; i++) {
+ ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+ init[i].len, init[i].val);
+ if (ret)
+ goto error;
+ }
+
+ /* load tuner specific settings */
+ deb_info("%s: load tuner specific settings\n", __func__);
+ switch (state->config.tuner) {
+ case AF9013_TUNER_MXL5003D:
+ len = ARRAY_SIZE(tuner_init_mxl5003d);
+ init = tuner_init_mxl5003d;
+ break;
+ case AF9013_TUNER_MXL5005D:
+ case AF9013_TUNER_MXL5005R:
+ len = ARRAY_SIZE(tuner_init_mxl5005);
+ init = tuner_init_mxl5005;
+ break;
+ case AF9013_TUNER_ENV77H11D5:
+ len = ARRAY_SIZE(tuner_init_env77h11d5);
+ init = tuner_init_env77h11d5;
+ break;
+ case AF9013_TUNER_MT2060:
+ len = ARRAY_SIZE(tuner_init_mt2060);
+ init = tuner_init_mt2060;
+ break;
+ case AF9013_TUNER_MC44S803:
+ len = ARRAY_SIZE(tuner_init_mc44s803);
+ init = tuner_init_mc44s803;
+ break;
+ case AF9013_TUNER_QT1010:
+ case AF9013_TUNER_QT1010A:
+ len = ARRAY_SIZE(tuner_init_qt1010);
+ init = tuner_init_qt1010;
+ break;
+ case AF9013_TUNER_MT2060_2:
+ len = ARRAY_SIZE(tuner_init_mt2060_2);
+ init = tuner_init_mt2060_2;
+ break;
+ case AF9013_TUNER_TDA18271:
+ len = ARRAY_SIZE(tuner_init_tda18271);
+ init = tuner_init_tda18271;
+ break;
+ case AF9013_TUNER_UNKNOWN:
+ default:
+ len = ARRAY_SIZE(tuner_init_unknown);
+ init = tuner_init_unknown;
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+ init[i].len, init[i].val);
+ if (ret)
+ goto error;
+ }
+
+ /* set TS mode */
+ deb_info("%s: setting ts mode\n", __func__);
+ tmp0 = 0; /* parallel mode */
+ tmp1 = 0; /* serial mode */
+ switch (state->config.output_mode) {
+ case AF9013_OUTPUT_MODE_PARALLEL:
+ tmp0 = 1;
+ break;
+ case AF9013_OUTPUT_MODE_SERIAL:
+ tmp1 = 1;
+ break;
+ case AF9013_OUTPUT_MODE_USB:
+ /* usb mode for AF9015 */
+ default:
+ break;
+ }
+ ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */
+ if (ret)
+ goto error;
+ ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */
+ if (ret)
+ goto error;
+
+ /* enable lock led */
+ ret = af9013_lock_led(state, 1);
+ if (ret)
+ goto error;
+
+error:
+ return ret;
+}
+
+static struct dvb_frontend_ops af9013_ops;
+
+static int af9013_download_firmware(struct af9013_state *state)
+{
+ int i, len, packets, remainder, ret;
+ const struct firmware *fw;
+ u16 addr = 0x5100; /* firmware start address */
+ u16 checksum = 0;
+ u8 val;
+ u8 fw_params[4];
+ u8 *data;
+ u8 *fw_file = AF9013_DEFAULT_FIRMWARE;
+
+ msleep(100);
+ /* check whether firmware is already running */
+ ret = af9013_read_reg(state, 0x98be, &val);
+ if (ret)
+ goto error;
+ else
+ deb_info("%s: firmware status:%02x\n", __func__, val);
+
+ if (val == 0x0c) /* fw is running, no need for download */
+ goto exit;
+
+ info("found a '%s' in cold state, will try to load a firmware",
+ af9013_ops.info.name);
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, &state->i2c->dev);
+ if (ret) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details" \
+ " on firmware-problems. (%d)",
+ fw_file, ret);
+ goto error;
+ }
+
+ info("downloading firmware from file '%s'", fw_file);
+
+ /* calc checksum */
+ for (i = 0; i < fw->size; i++)
+ checksum += fw->data[i];
+
+ fw_params[0] = checksum >> 8;
+ fw_params[1] = checksum & 0xff;
+ fw_params[2] = fw->size >> 8;
+ fw_params[3] = fw->size & 0xff;
+
+ /* write fw checksum & size */
+ ret = af9013_write_ofsm_regs(state, 0x50fc,
+ fw_params, sizeof(fw_params));
+ if (ret)
+ goto error_release;
+
+ #define FW_PACKET_MAX_DATA 16
+
+ packets = fw->size / FW_PACKET_MAX_DATA;
+ remainder = fw->size % FW_PACKET_MAX_DATA;
+ len = FW_PACKET_MAX_DATA;
+ for (i = 0; i <= packets; i++) {
+ if (i == packets) /* set size of the last packet */
+ len = remainder;
+
+ data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
+ ret = af9013_write_ofsm_regs(state, addr, data, len);
+ addr += FW_PACKET_MAX_DATA;
+
+ if (ret) {
+ err("firmware download failed at %d with %d", i, ret);
+ goto error_release;
+ }
+ }
+
+ /* request boot firmware */
+ ret = af9013_write_reg(state, 0xe205, 1);
+ if (ret)
+ goto error_release;
+
+ for (i = 0; i < 15; i++) {
+ msleep(100);
+
+ /* check firmware status */
+ ret = af9013_read_reg(state, 0x98be, &val);
+ if (ret)
+ goto error_release;
+
+ deb_info("%s: firmware status:%02x\n", __func__, val);
+
+ if (val == 0x0c || val == 0x04) /* success or fail */
+ break;
+ }
+
+ if (val == 0x04) {
+ err("firmware did not run");
+ ret = -1;
+ } else if (val != 0x0c) {
+ err("firmware boot timeout");
+ ret = -1;
+ }
+
+error_release:
+ release_firmware(fw);
+error:
+exit:
+ if (!ret)
+ info("found a '%s' in warm state.", af9013_ops.info.name);
+ return ret;
+}
+
+static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ int ret;
+ struct af9013_state *state = fe->demodulator_priv;
+ deb_info("%s: enable:%d\n", __func__, enable);
+
+ if (state->config.output_mode == AF9013_OUTPUT_MODE_USB)
+ ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable);
+ else
+ ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable);
+
+ return ret;
+}
+
+static void af9013_release(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops af9013_ops;
+
+struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+ struct i2c_adapter *i2c)
+{
+ int ret;
+ struct af9013_state *state = NULL;
+ u8 buf[3], i;
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->i2c = i2c;
+ memcpy(&state->config, config, sizeof(struct af9013_config));
+
+ /* chip version */
+ ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
+ if (ret)
+ goto error;
+
+ /* ROM version */
+ for (i = 0; i < 2; i++) {
+ ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
+ buf[2], buf[0], buf[1]);
+
+ /* download firmware */
+ if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
+ ret = af9013_download_firmware(state);
+ if (ret)
+ goto error;
+ }
+
+ /* firmware version */
+ for (i = 0; i < 3; i++) {
+ ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
+ if (ret)
+ goto error;
+ }
+ info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]);
+
+ /* settings for mp2if */
+ if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
+ /* AF9015 split PSB to 1.5k + 0.5k */
+ ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1);
+ } else {
+ /* AF9013 change the output bit to data7 */
+ ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1);
+ if (ret)
+ goto error;
+ /* AF9013 set mpeg to full speed */
+ ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1);
+ }
+ if (ret)
+ goto error;
+ ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1);
+ if (ret)
+ goto error;
+
+ /* set GPIOs */
+ for (i = 0; i < sizeof(state->config.gpio); i++) {
+ ret = af9013_set_gpio(state, i, state->config.gpio[i]);
+ if (ret)
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &af9013_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ return &state->frontend;
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(af9013_attach);
+
+static struct dvb_frontend_ops af9013_ops = {
+ .info = {
+ .name = "Afatech AF9013 DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 174000000,
+ .frequency_max = 862000000,
+ .frequency_stepsize = 250000,
+ .frequency_tolerance = 0,
+ .caps =
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_MUTE_TS
+ },
+
+ .release = af9013_release,
+ .init = af9013_init,
+ .sleep = af9013_sleep,
+ .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+
+ .set_frontend = af9013_set_frontend,
+ .get_frontend = af9013_get_frontend,
+
+ .get_tune_settings = af9013_get_tune_settings,
+
+ .read_status = af9013_read_status,
+ .read_ber = af9013_read_ber,
+ .read_signal_strength = af9013_read_signal_strength,
+ .read_snr = af9013_read_snr,
+ .read_ucblocks = af9013_read_ucblocks,
+};
+
+module_param_named(debug, af9013_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h
new file mode 100644
index 00000000000..28b90c91c76
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9013.h
@@ -0,0 +1,107 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _AF9013_H_
+#define _AF9013_H_
+
+#include <linux/dvb/frontend.h>
+
+enum af9013_ts_mode {
+ AF9013_OUTPUT_MODE_PARALLEL,
+ AF9013_OUTPUT_MODE_SERIAL,
+ AF9013_OUTPUT_MODE_USB, /* only for AF9015 */
+};
+
+enum af9013_tuner {
+ AF9013_TUNER_MXL5003D = 3, /* MaxLinear */
+ AF9013_TUNER_MXL5005D = 13, /* MaxLinear */
+ AF9013_TUNER_MXL5005R = 30, /* MaxLinear */
+ AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */
+ AF9013_TUNER_MT2060 = 130, /* Microtune */
+ AF9013_TUNER_MC44S803 = 133, /* Freescale */
+ AF9013_TUNER_QT1010 = 134, /* Quantek */
+ AF9013_TUNER_UNKNOWN = 140, /* for can tuners ? */
+ AF9013_TUNER_MT2060_2 = 147, /* Microtune */
+ AF9013_TUNER_TDA18271 = 156, /* NXP */
+ AF9013_TUNER_QT1010A = 162, /* Quantek */
+};
+
+/* AF9013/5 GPIOs (mostly guessed)
+ demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
+ demod#1-gpio#1 - xtal setting (?)
+ demod#1-gpio#3 - tuner#1
+ demod#2-gpio#0 - tuner#2
+ demod#2-gpio#1 - xtal setting (?)
+*/
+#define AF9013_GPIO_ON (1 << 0)
+#define AF9013_GPIO_EN (1 << 1)
+#define AF9013_GPIO_O (1 << 2)
+#define AF9013_GPIO_I (1 << 3)
+
+#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+
+#define AF9013_GPIO_TUNER_ON (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+
+struct af9013_config {
+ /* demodulator's I2C address */
+ u8 demod_address;
+
+ /* frequencies in kHz */
+ u32 adc_clock;
+
+ /* tuner ID */
+ u8 tuner;
+
+ /* tuner IF */
+ u16 tuner_if;
+
+ /* TS data output mode */
+ u8 output_mode:2;
+
+ /* RF spectrum inversion */
+ u8 rf_spec_inv:1;
+
+ /* API version */
+ u8 api_version[4];
+
+ /* GPIOs */
+ u8 gpio[4];
+};
+
+
+#if defined(CONFIG_DVB_AF9013) || \
+ (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
+extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *af9013_attach(
+const struct af9013_config *config, struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_AF9013 */
+
+#endif /* _AF9013_H_ */
diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h
new file mode 100644
index 00000000000..163e251d0b7
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9013_priv.h
@@ -0,0 +1,869 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _AF9013_PRIV_
+#define _AF9013_PRIV_
+
+#define LOG_PREFIX "af9013"
+extern int af9013_debug;
+
+#define dprintk(var, level, args...) \
+ do { if ((var & level)) printk(args); } while (0)
+
+#define debug_dump(b, l, func) {\
+ int loop_; \
+ for (loop_ = 0; loop_ < l; loop_++) \
+ func("%02x ", b[loop_]); \
+ func("\n");\
+}
+
+#define deb_info(args...) dprintk(af9013_debug, 0x01, args)
+
+#undef err
+#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+#define AF9013_DEFAULT_FIRMWARE "dvb-fe-af9013.fw"
+
+struct regdesc {
+ u16 addr;
+ u8 pos:4;
+ u8 len:4;
+ u8 val;
+};
+
+struct snr_table {
+ u32 val;
+ u8 snr;
+};
+
+/* QPSK SNR lookup table */
+static struct snr_table qpsk_snr_table[] = {
+ { 0x0b4771, 0 },
+ { 0x0c1aed, 1 },
+ { 0x0d0d27, 2 },
+ { 0x0e4d19, 3 },
+ { 0x0e5da8, 4 },
+ { 0x107097, 5 },
+ { 0x116975, 6 },
+ { 0x1252d9, 7 },
+ { 0x131fa4, 8 },
+ { 0x13d5e1, 9 },
+ { 0x148e53, 10 },
+ { 0x15358b, 11 },
+ { 0x15dd29, 12 },
+ { 0x168112, 13 },
+ { 0x170b61, 14 },
+ { 0xffffff, 15 },
+};
+
+/* QAM16 SNR lookup table */
+static struct snr_table qam16_snr_table[] = {
+ { 0x05eb62, 5 },
+ { 0x05fecf, 6 },
+ { 0x060b80, 7 },
+ { 0x062501, 8 },
+ { 0x064865, 9 },
+ { 0x069604, 10 },
+ { 0x06f356, 11 },
+ { 0x07706a, 12 },
+ { 0x0804d3, 13 },
+ { 0x089d1a, 14 },
+ { 0x093e3d, 15 },
+ { 0x09e35d, 16 },
+ { 0x0a7c3c, 17 },
+ { 0x0afaf8, 18 },
+ { 0x0b719d, 19 },
+ { 0xffffff, 20 },
+};
+
+/* QAM64 SNR lookup table */
+static struct snr_table qam64_snr_table[] = {
+ { 0x03109b, 12 },
+ { 0x0310d4, 13 },
+ { 0x031920, 14 },
+ { 0x0322d0, 15 },
+ { 0x0339fc, 16 },
+ { 0x0364a1, 17 },
+ { 0x038bcc, 18 },
+ { 0x03c7d3, 19 },
+ { 0x0408cc, 20 },
+ { 0x043bed, 21 },
+ { 0x048061, 22 },
+ { 0x04be95, 23 },
+ { 0x04fa7d, 24 },
+ { 0x052405, 25 },
+ { 0x05570d, 26 },
+ { 0xffffff, 27 },
+};
+
+static struct regdesc ofsm_init[] = {
+ { 0xd73a, 0, 8, 0xa1 },
+ { 0xd73b, 0, 8, 0x1f },
+ { 0xd73c, 4, 4, 0x0a },
+ { 0xd732, 3, 1, 0x00 },
+ { 0xd731, 4, 2, 0x03 },
+ { 0xd73d, 7, 1, 0x01 },
+ { 0xd740, 0, 1, 0x00 },
+ { 0xd740, 1, 1, 0x00 },
+ { 0xd740, 2, 1, 0x00 },
+ { 0xd740, 3, 1, 0x01 },
+ { 0xd3c1, 4, 1, 0x01 },
+ { 0xd3a2, 0, 8, 0x00 },
+ { 0xd3a3, 0, 8, 0x04 },
+ { 0xd305, 0, 8, 0x32 },
+ { 0xd306, 0, 8, 0x10 },
+ { 0xd304, 0, 8, 0x04 },
+ { 0x9112, 0, 1, 0x01 },
+ { 0x911d, 0, 1, 0x01 },
+ { 0x911a, 0, 1, 0x01 },
+ { 0x911b, 0, 1, 0x01 },
+ { 0x9bce, 0, 4, 0x02 },
+ { 0x9116, 0, 1, 0x01 },
+ { 0x9bd1, 0, 1, 0x01 },
+ { 0xd2e0, 0, 8, 0xd0 },
+ { 0xd2e9, 0, 4, 0x0d },
+ { 0xd38c, 0, 8, 0xfc },
+ { 0xd38d, 0, 8, 0x00 },
+ { 0xd38e, 0, 8, 0x7e },
+ { 0xd38f, 0, 8, 0x00 },
+ { 0xd390, 0, 8, 0x2f },
+ { 0xd145, 4, 1, 0x01 },
+ { 0xd1a9, 4, 1, 0x01 },
+ { 0xd158, 5, 3, 0x01 },
+ { 0xd159, 0, 6, 0x06 },
+ { 0xd167, 0, 8, 0x00 },
+ { 0xd168, 0, 4, 0x07 },
+ { 0xd1c3, 5, 3, 0x00 },
+ { 0xd1c4, 0, 6, 0x00 },
+ { 0xd1c5, 0, 7, 0x10 },
+ { 0xd1c6, 0, 3, 0x02 },
+ { 0xd080, 2, 5, 0x03 },
+ { 0xd081, 4, 4, 0x09 },
+ { 0xd098, 4, 4, 0x0f },
+ { 0xd098, 0, 4, 0x03 },
+ { 0xdbc0, 3, 1, 0x01 },
+ { 0xdbc0, 4, 1, 0x01 },
+ { 0xdbc7, 0, 8, 0x08 },
+ { 0xdbc8, 4, 4, 0x00 },
+ { 0xdbc9, 0, 5, 0x01 },
+ { 0xd280, 0, 8, 0xe0 },
+ { 0xd281, 0, 8, 0xff },
+ { 0xd282, 0, 8, 0xff },
+ { 0xd283, 0, 8, 0xc3 },
+ { 0xd284, 0, 8, 0xff },
+ { 0xd285, 0, 4, 0x01 },
+ { 0xd0f0, 0, 7, 0x1a },
+ { 0xd0f1, 4, 1, 0x01 },
+ { 0xd0f2, 0, 8, 0x0c },
+ { 0xd103, 0, 4, 0x08 },
+ { 0xd0f8, 0, 7, 0x20 },
+ { 0xd111, 5, 1, 0x00 },
+ { 0xd111, 6, 1, 0x00 },
+ { 0x910b, 0, 8, 0x0a },
+ { 0x9115, 0, 8, 0x02 },
+ { 0x910c, 0, 8, 0x02 },
+ { 0x910d, 0, 8, 0x08 },
+ { 0x910e, 0, 8, 0x0a },
+ { 0x9bf6, 0, 8, 0x06 },
+ { 0x9bf8, 0, 8, 0x02 },
+ { 0x9bf7, 0, 8, 0x05 },
+ { 0x9bf9, 0, 8, 0x0f },
+ { 0x9bfc, 0, 8, 0x13 },
+ { 0x9bd3, 0, 8, 0xff },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+};
+
+/* Panasonic ENV77H11D5 tuner init
+ AF9013_TUNER_ENV77H11D5 = 129 */
+static struct regdesc tuner_init_env77h11d5[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x03 },
+ { 0x9bbe, 0, 8, 0x01 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x00 },
+ { 0x9be3, 0, 8, 0x00 },
+ { 0xd015, 0, 8, 0x50 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0xdf },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x44 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0xeb },
+ { 0xd00d, 0, 2, 0x02 },
+ { 0xd00a, 0, 8, 0xf4 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bba, 0, 8, 0xf9 },
+ { 0x9bc3, 0, 8, 0xdf },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0xeb },
+ { 0x9bc6, 0, 8, 0x02 },
+ { 0x9bc9, 0, 8, 0x52 },
+ { 0xd011, 0, 8, 0x3c },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0xf7 },
+ { 0xd014, 0, 2, 0x02 },
+ { 0xd040, 0, 8, 0x0b },
+ { 0xd041, 0, 2, 0x02 },
+ { 0xd042, 0, 8, 0x4d },
+ { 0xd043, 0, 2, 0x00 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* Microtune MT2060 tuner init
+ AF9013_TUNER_MT2060 = 130 */
+static struct regdesc tuner_init_mt2060[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x07 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x00 },
+ { 0x9be3, 0, 8, 0x00 },
+ { 0x9bbe, 0, 1, 0x00 },
+ { 0x9bcc, 0, 1, 0x00 },
+ { 0x9bb9, 0, 8, 0x75 },
+ { 0x9bcd, 0, 8, 0x24 },
+ { 0x9bff, 0, 8, 0x30 },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0x0f },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x32 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0x36 },
+ { 0xd00d, 0, 2, 0x03 },
+ { 0xd00a, 0, 8, 0x35 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x07 },
+ { 0x9bc8, 0, 8, 0x90 },
+ { 0x9bc3, 0, 8, 0x0f },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x36 },
+ { 0x9bc6, 0, 8, 0x03 },
+ { 0x9bba, 0, 8, 0xc9 },
+ { 0x9bc9, 0, 8, 0x79 },
+ { 0xd011, 0, 8, 0x10 },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0x45 },
+ { 0xd014, 0, 2, 0x03 },
+ { 0xd040, 0, 8, 0x98 },
+ { 0xd041, 0, 2, 0x00 },
+ { 0xd042, 0, 8, 0xcf },
+ { 0xd043, 0, 2, 0x03 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+ { 0x9bd0, 0, 8, 0xcc },
+ { 0x9be4, 0, 8, 0xa0 },
+ { 0x9bbd, 0, 8, 0x8e },
+ { 0x9be2, 0, 8, 0x4d },
+ { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Microtune MT2060 tuner init
+ AF9013_TUNER_MT2060_2 = 147 */
+static struct regdesc tuner_init_mt2060_2[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x06 },
+ { 0x9bbe, 0, 8, 0x01 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0x0f },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x32 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0x36 },
+ { 0xd00d, 0, 2, 0x03 },
+ { 0xd00a, 0, 8, 0x35 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x07 },
+ { 0x9bc8, 0, 8, 0x90 },
+ { 0x9bc3, 0, 8, 0x0f },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x36 },
+ { 0x9bc6, 0, 8, 0x03 },
+ { 0x9bba, 0, 8, 0xc9 },
+ { 0x9bc9, 0, 8, 0x79 },
+ { 0xd011, 0, 8, 0x10 },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0x45 },
+ { 0xd014, 0, 2, 0x03 },
+ { 0xd040, 0, 8, 0x98 },
+ { 0xd041, 0, 2, 0x00 },
+ { 0xd042, 0, 8, 0xcf },
+ { 0xd043, 0, 2, 0x03 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 8, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x96 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0xd045, 7, 1, 0x00 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5003 tuner init
+ AF9013_TUNER_MXL5003D = 3 */
+static struct regdesc tuner_init_mxl5003d[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x09 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x00 },
+ { 0x9be3, 0, 8, 0x00 },
+ { 0x9bfc, 0, 8, 0x0f },
+ { 0x9bf6, 0, 8, 0x01 },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0xd015, 0, 8, 0x33 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x40 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0x0f },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x6c },
+ { 0xd007, 0, 2, 0x00 },
+ { 0xd00c, 0, 8, 0x3d },
+ { 0xd00d, 0, 2, 0x00 },
+ { 0xd00a, 0, 8, 0x45 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x07 },
+ { 0x9bc8, 0, 8, 0x52 },
+ { 0x9bc3, 0, 8, 0x0f },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x3d },
+ { 0x9bc6, 0, 8, 0x00 },
+ { 0x9bba, 0, 8, 0xa2 },
+ { 0x9bc9, 0, 8, 0xa0 },
+ { 0xd011, 0, 8, 0x56 },
+ { 0xd012, 0, 2, 0x00 },
+ { 0xd013, 0, 8, 0x50 },
+ { 0xd014, 0, 2, 0x00 },
+ { 0xd040, 0, 8, 0x56 },
+ { 0xd041, 0, 2, 0x00 },
+ { 0xd042, 0, 8, 0x50 },
+ { 0xd043, 0, 2, 0x00 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 8, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5005 tuner init
+ AF9013_TUNER_MXL5005D = 13
+ AF9013_TUNER_MXL5005R = 30 */
+static struct regdesc tuner_init_mxl5005[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x07 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x01 },
+ { 0x9be3, 0, 8, 0x01 },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+ { 0x9bb9, 0, 8, 0x00 },
+ { 0x9bcd, 0, 8, 0x28 },
+ { 0x9bff, 0, 8, 0x24 },
+ { 0xd015, 0, 8, 0x40 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x40 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0x0f },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x73 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0xfa },
+ { 0xd00d, 0, 2, 0x01 },
+ { 0xd00a, 0, 8, 0xff },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x23 },
+ { 0x9bc8, 0, 8, 0x55 },
+ { 0x9bc3, 0, 8, 0x01 },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0xfa },
+ { 0x9bc6, 0, 8, 0x01 },
+ { 0x9bba, 0, 8, 0xff },
+ { 0x9bc9, 0, 8, 0xff },
+ { 0x9bd3, 0, 8, 0x95 },
+ { 0xd011, 0, 8, 0x70 },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0xfb },
+ { 0xd014, 0, 2, 0x01 },
+ { 0xd040, 0, 8, 0x70 },
+ { 0xd041, 0, 2, 0x01 },
+ { 0xd042, 0, 8, 0xfb },
+ { 0xd043, 0, 2, 0x01 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+ { 0x9bd0, 0, 8, 0x93 },
+ { 0x9be4, 0, 8, 0xfe },
+ { 0x9bbd, 0, 8, 0x63 },
+ { 0x9be2, 0, 8, 0xfe },
+ { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Quantek QT1010 tuner init
+ AF9013_TUNER_QT1010 = 134
+ AF9013_TUNER_QT1010A = 162 */
+static struct regdesc tuner_init_qt1010[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x09 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x01 },
+ { 0x9be3, 0, 8, 0x01 },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+ { 0x9bb9, 0, 8, 0x00 },
+ { 0x9bcd, 0, 8, 0x28 },
+ { 0x9bff, 0, 8, 0x20 },
+ { 0xd008, 0, 8, 0x0f },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x99 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0x0f },
+ { 0xd00d, 0, 2, 0x02 },
+ { 0xd00a, 0, 8, 0x50 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x00 },
+ { 0x9bc8, 0, 8, 0x00 },
+ { 0x9bc3, 0, 8, 0x0f },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x0f },
+ { 0x9bc6, 0, 8, 0x02 },
+ { 0x9bba, 0, 8, 0xc5 },
+ { 0x9bc9, 0, 8, 0xff },
+ { 0xd011, 0, 8, 0x58 },
+ { 0xd012, 0, 2, 0x02 },
+ { 0xd013, 0, 8, 0x89 },
+ { 0xd014, 0, 2, 0x01 },
+ { 0xd040, 0, 8, 0x58 },
+ { 0xd041, 0, 2, 0x02 },
+ { 0xd042, 0, 8, 0x89 },
+ { 0xd043, 0, 2, 0x01 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+ { 0x9bd0, 0, 8, 0xcd },
+ { 0x9be4, 0, 8, 0xbb },
+ { 0x9bbd, 0, 8, 0x93 },
+ { 0x9be2, 0, 8, 0x80 },
+ { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Freescale MC44S803 tuner init
+ AF9013_TUNER_MC44S803 = 133 */
+static struct regdesc tuner_init_mc44s803[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x06 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x00 },
+ { 0x9be3, 0, 8, 0x00 },
+ { 0x9bf6, 0, 8, 0x01 },
+ { 0x9bf8, 0, 8, 0x02 },
+ { 0x9bf9, 0, 8, 0x02 },
+ { 0x9bfc, 0, 8, 0x1f },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+ { 0x9bb9, 0, 8, 0x00 },
+ { 0x9bcd, 0, 8, 0x24 },
+ { 0x9bff, 0, 8, 0x24 },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0x01 },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x7b },
+ { 0xd007, 0, 2, 0x00 },
+ { 0xd00c, 0, 8, 0x7c },
+ { 0xd00d, 0, 2, 0x02 },
+ { 0xd00a, 0, 8, 0xfe },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bc7, 0, 8, 0x08 },
+ { 0x9bc8, 0, 8, 0x9a },
+ { 0x9bc3, 0, 8, 0x01 },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x7c },
+ { 0x9bc6, 0, 8, 0x02 },
+ { 0x9bba, 0, 8, 0xfc },
+ { 0x9bc9, 0, 8, 0xaa },
+ { 0xd011, 0, 8, 0x6b },
+ { 0xd012, 0, 2, 0x00 },
+ { 0xd013, 0, 8, 0x88 },
+ { 0xd014, 0, 2, 0x02 },
+ { 0xd040, 0, 8, 0x6b },
+ { 0xd041, 0, 2, 0x00 },
+ { 0xd042, 0, 8, 0x7c },
+ { 0xd043, 0, 2, 0x02 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+ { 0x9bd0, 0, 8, 0x9e },
+ { 0x9be4, 0, 8, 0xff },
+ { 0x9bbd, 0, 8, 0x9e },
+ { 0x9be2, 0, 8, 0x25 },
+ { 0x9bee, 0, 1, 0x01 },
+ { 0xd73b, 3, 1, 0x00 },
+};
+
+/* unknown, probably for tin can tuner, tuner init
+ AF9013_TUNER_UNKNOWN = 140 */
+static struct regdesc tuner_init_unknown[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x02 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x01 },
+ { 0x9be3, 0, 8, 0x01 },
+ { 0xd1a0, 1, 1, 0x00 },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+ { 0x9bb9, 0, 8, 0x00 },
+ { 0x9bcd, 0, 8, 0x18 },
+ { 0x9bff, 0, 8, 0x2c },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0xdf },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x44 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0x00 },
+ { 0xd00d, 0, 2, 0x02 },
+ { 0xd00a, 0, 8, 0xf6 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bba, 0, 8, 0xf9 },
+ { 0x9bc8, 0, 8, 0xaa },
+ { 0x9bc3, 0, 8, 0xdf },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x00 },
+ { 0x9bc6, 0, 8, 0x02 },
+ { 0x9bc9, 0, 8, 0xf0 },
+ { 0xd011, 0, 8, 0x3c },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0xf7 },
+ { 0xd014, 0, 2, 0x02 },
+ { 0xd040, 0, 8, 0x0b },
+ { 0xd041, 0, 2, 0x02 },
+ { 0xd042, 0, 8, 0x4d },
+ { 0xd043, 0, 2, 0x00 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* NXP TDA18271 tuner init
+ AF9013_TUNER_TDA18271 = 156 */
+static struct regdesc tuner_init_tda18271[] = {
+ { 0x9bd5, 0, 8, 0x01 },
+ { 0x9bd6, 0, 8, 0x04 },
+ { 0xd1a0, 1, 1, 0x01 },
+ { 0xd000, 0, 1, 0x01 },
+ { 0xd000, 1, 1, 0x00 },
+ { 0xd001, 1, 1, 0x01 },
+ { 0xd001, 0, 1, 0x00 },
+ { 0xd001, 5, 1, 0x00 },
+ { 0xd002, 0, 5, 0x19 },
+ { 0xd003, 0, 5, 0x1a },
+ { 0xd004, 0, 5, 0x19 },
+ { 0xd005, 0, 5, 0x1a },
+ { 0xd00e, 0, 5, 0x10 },
+ { 0xd00f, 0, 3, 0x04 },
+ { 0xd00f, 3, 3, 0x05 },
+ { 0xd010, 0, 3, 0x04 },
+ { 0xd010, 3, 3, 0x05 },
+ { 0xd016, 4, 4, 0x03 },
+ { 0xd01f, 0, 6, 0x0a },
+ { 0xd020, 0, 6, 0x0a },
+ { 0x9bda, 0, 8, 0x01 },
+ { 0x9be3, 0, 8, 0x01 },
+ { 0xd1a0, 1, 1, 0x00 },
+ { 0x9bbe, 0, 1, 0x01 },
+ { 0x9bcc, 0, 1, 0x01 },
+ { 0x9bb9, 0, 8, 0x00 },
+ { 0x9bcd, 0, 8, 0x18 },
+ { 0x9bff, 0, 8, 0x2c },
+ { 0xd015, 0, 8, 0x46 },
+ { 0xd016, 0, 1, 0x00 },
+ { 0xd044, 0, 8, 0x46 },
+ { 0xd045, 0, 1, 0x00 },
+ { 0xd008, 0, 8, 0xdf },
+ { 0xd009, 0, 2, 0x02 },
+ { 0xd006, 0, 8, 0x44 },
+ { 0xd007, 0, 2, 0x01 },
+ { 0xd00c, 0, 8, 0x00 },
+ { 0xd00d, 0, 2, 0x02 },
+ { 0xd00a, 0, 8, 0xf6 },
+ { 0xd00b, 0, 2, 0x01 },
+ { 0x9bba, 0, 8, 0xf9 },
+ { 0x9bc8, 0, 8, 0xaa },
+ { 0x9bc3, 0, 8, 0xdf },
+ { 0x9bc4, 0, 8, 0x02 },
+ { 0x9bc5, 0, 8, 0x00 },
+ { 0x9bc6, 0, 8, 0x02 },
+ { 0x9bc9, 0, 8, 0xf0 },
+ { 0xd011, 0, 8, 0x3c },
+ { 0xd012, 0, 2, 0x01 },
+ { 0xd013, 0, 8, 0xf7 },
+ { 0xd014, 0, 2, 0x02 },
+ { 0xd040, 0, 8, 0x0b },
+ { 0xd041, 0, 2, 0x02 },
+ { 0xd042, 0, 8, 0x4d },
+ { 0xd043, 0, 2, 0x00 },
+ { 0xd045, 1, 1, 0x00 },
+ { 0x9bcf, 0, 1, 0x01 },
+ { 0xd045, 2, 1, 0x01 },
+ { 0xd04f, 0, 8, 0x9a },
+ { 0xd050, 0, 1, 0x01 },
+ { 0xd051, 0, 8, 0x5a },
+ { 0xd052, 0, 1, 0x01 },
+ { 0xd053, 0, 8, 0x50 },
+ { 0xd054, 0, 8, 0x46 },
+ { 0x9bd7, 0, 8, 0x0a },
+ { 0x9bd8, 0, 8, 0x14 },
+ { 0x9bd9, 0, 8, 0x08 },
+ { 0x9bd0, 0, 8, 0xa8 },
+ { 0x9be4, 0, 8, 0x7f },
+ { 0x9bbd, 0, 8, 0xa8 },
+ { 0x9be2, 0, 8, 0x20 },
+ { 0x9bee, 0, 1, 0x01 },
+};
+
+#endif /* _AF9013_PRIV_ */
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
index f7b71657f0f..eabf9a68e7e 100644
--- a/drivers/media/dvb/frontends/au8522.c
+++ b/drivers/media/dvb/frontends/au8522.c
@@ -1,7 +1,7 @@
/*
Auvitek AU8522 QAM/8VSB demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
@@ -40,6 +40,8 @@ struct au8522_state {
u32 current_frequency;
fe_modulation_t current_modulation;
+ u32 fe_status;
+ unsigned int led_state;
};
static int debug;
@@ -304,6 +306,43 @@ static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
return ret;
}
+static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ u8 r0b5, r0b6, r0b7;
+ char *ifmhz;
+
+ switch (if_freq) {
+ case AU8522_IF_3_25MHZ:
+ ifmhz = "3.25";
+ r0b5 = 0x00;
+ r0b6 = 0x3d;
+ r0b7 = 0xa0;
+ break;
+ case AU8522_IF_4MHZ:
+ ifmhz = "4.00";
+ r0b5 = 0x00;
+ r0b6 = 0x4b;
+ r0b7 = 0xd9;
+ break;
+ case AU8522_IF_6MHZ:
+ ifmhz = "6.00";
+ r0b5 = 0xfb;
+ r0b6 = 0x8e;
+ r0b7 = 0x39;
+ break;
+ default:
+ dprintk("%s() IF Frequency not supported\n", __func__);
+ return -EINVAL;
+ }
+ dprintk("%s() %s MHz\n", __func__, ifmhz);
+ au8522_writereg(state, 0x80b5, r0b5);
+ au8522_writereg(state, 0x80b6, r0b6);
+ au8522_writereg(state, 0x80b7, r0b7);
+
+ return 0;
+}
+
/* VSB Modulation table */
static struct {
u16 reg;
@@ -334,9 +373,6 @@ static struct {
{ 0x80af, 0x66 },
{ 0x821b, 0xcc },
{ 0x821d, 0x80 },
- { 0x80b5, 0xfb },
- { 0x80b6, 0x8e },
- { 0x80b7, 0x39 },
{ 0x80a4, 0xe8 },
{ 0x8231, 0x13 },
};
@@ -350,9 +386,6 @@ static struct {
{ 0x80a4, 0x00 },
{ 0x8081, 0xc4 },
{ 0x80a5, 0x40 },
- { 0x80b5, 0xfb },
- { 0x80b6, 0x8e },
- { 0x80b7, 0x39 },
{ 0x80aa, 0x77 },
{ 0x80ad, 0x77 },
{ 0x80a6, 0x67 },
@@ -438,6 +471,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
au8522_writereg(state,
VSB_mod_tab[i].reg,
VSB_mod_tab[i].data);
+ au8522_set_if(fe, state->config->vsb_if);
break;
case QAM_64:
case QAM_256:
@@ -446,6 +480,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
au8522_writereg(state,
QAM_mod_tab[i].reg,
QAM_mod_tab[i].data);
+ au8522_set_if(fe, state->config->qam_if);
break;
default:
dprintk("%s() Invalid modulation\n", __func__);
@@ -505,11 +540,98 @@ static int au8522_init(struct dvb_frontend *fe)
return 0;
}
+static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
+{
+ struct au8522_led_config *led_config = state->config->led_cfg;
+ u8 val;
+
+ /* bail out if we cant control an LED */
+ if (!led_config || !led_config->gpio_output ||
+ !led_config->gpio_output_enable || !led_config->gpio_output_disable)
+ return 0;
+
+ val = au8522_readreg(state, 0x4000 |
+ (led_config->gpio_output & ~0xc000));
+ if (onoff) {
+ /* enable GPIO output */
+ val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
+ val |= (led_config->gpio_output_enable & 0xff);
+ } else {
+ /* disable GPIO output */
+ val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
+ val |= (led_config->gpio_output_disable & 0xff);
+ }
+ return au8522_writereg(state, 0x8000 |
+ (led_config->gpio_output & ~0xc000), val);
+}
+
+/* led = 0 | off
+ * led = 1 | signal ok
+ * led = 2 | signal strong
+ * led < 0 | only light led if leds are currently off
+ */
+static int au8522_led_ctrl(struct au8522_state *state, int led)
+{
+ struct au8522_led_config *led_config = state->config->led_cfg;
+ int i, ret = 0;
+
+ /* bail out if we cant control an LED */
+ if (!led_config || !led_config->gpio_leds ||
+ !led_config->num_led_states || !led_config->led_states)
+ return 0;
+
+ if (led < 0) {
+ /* if LED is already lit, then leave it as-is */
+ if (state->led_state)
+ return 0;
+ else
+ led *= -1;
+ }
+
+ /* toggle LED if changing state */
+ if (state->led_state != led) {
+ u8 val;
+
+ dprintk("%s: %d\n", __func__, led);
+
+ au8522_led_gpio_enable(state, 1);
+
+ val = au8522_readreg(state, 0x4000 |
+ (led_config->gpio_leds & ~0xc000));
+
+ /* start with all leds off */
+ for (i = 0; i < led_config->num_led_states; i++)
+ val &= ~led_config->led_states[i];
+
+ /* set selected LED state */
+ if (led < led_config->num_led_states)
+ val |= led_config->led_states[led];
+ else if (led_config->num_led_states)
+ val |=
+ led_config->led_states[led_config->num_led_states - 1];
+
+ ret = au8522_writereg(state, 0x8000 |
+ (led_config->gpio_leds & ~0xc000), val);
+ if (ret < 0)
+ return ret;
+
+ state->led_state = led;
+
+ if (led == 0)
+ au8522_led_gpio_enable(state, 0);
+ }
+
+ return 0;
+}
+
static int au8522_sleep(struct dvb_frontend *fe)
{
struct au8522_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
+ /* turn off led */
+ au8522_led_ctrl(state, 0);
+
state->current_frequency = 0;
return 0;
@@ -559,12 +681,53 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
break;
}
+ state->fe_status = *status;
+
+ if (*status & FE_HAS_LOCK)
+ /* turn on LED, if it isn't on already */
+ au8522_led_ctrl(state, -1);
+ else
+ /* turn off LED */
+ au8522_led_ctrl(state, 0);
dprintk("%s() status 0x%08x\n", __func__, *status);
return 0;
}
+static int au8522_led_status(struct au8522_state *state, const u16 *snr)
+{
+ struct au8522_led_config *led_config = state->config->led_cfg;
+ int led;
+ u16 strong;
+
+ /* bail out if we cant control an LED */
+ if (!led_config)
+ return 0;
+
+ if (0 == (state->fe_status & FE_HAS_LOCK))
+ return au8522_led_ctrl(state, 0);
+ else if (state->current_modulation == QAM_256)
+ strong = led_config->qam256_strong;
+ else if (state->current_modulation == QAM_64)
+ strong = led_config->qam64_strong;
+ else /* (state->current_modulation == VSB_8) */
+ strong = led_config->vsb8_strong;
+
+ if (*snr >= strong)
+ led = 2;
+ else
+ led = 1;
+
+ if ((state->led_state) &&
+ (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10))
+ /* snr didn't change enough to bother
+ * changing the color of the led */
+ return 0;
+
+ return au8522_led_ctrl(state, led);
+}
+
static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct au8522_state *state = fe->demodulator_priv;
@@ -588,6 +751,9 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
au8522_readreg(state, 0x4311),
snr);
+ if (state->config->led_cfg)
+ au8522_led_status(state, snr);
+
return ret;
}
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
index d7affa3cdb2..7b94f554a09 100644
--- a/drivers/media/dvb/frontends/au8522.h
+++ b/drivers/media/dvb/frontends/au8522.h
@@ -1,7 +1,7 @@
/*
Auvitek AU8522 QAM/8VSB demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
@@ -24,6 +24,27 @@
#include <linux/dvb/frontend.h>
+enum au8522_if_freq {
+ AU8522_IF_6MHZ = 0,
+ AU8522_IF_4MHZ,
+ AU8522_IF_3_25MHZ,
+};
+
+struct au8522_led_config {
+ u16 vsb8_strong;
+ u16 qam64_strong;
+ u16 qam256_strong;
+
+ u16 gpio_output;
+ /* unset hi bits, set low bits */
+ u16 gpio_output_enable;
+ u16 gpio_output_disable;
+
+ u16 gpio_leds;
+ u8 *led_states;
+ unsigned int num_led_states;
+};
+
struct au8522_config {
/* the demodulator's i2c address */
u8 demod_address;
@@ -32,6 +53,11 @@ struct au8522_config {
#define AU8522_TUNERLOCKING 0
#define AU8522_DEMODLOCKING 1
u8 status_mode;
+
+ struct au8522_led_config *led_cfg;
+
+ enum au8522_if_freq vsb_if;
+ enum au8522_if_freq qam_if;
};
#if defined(CONFIG_DVB_AU8522) || \
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index cc1db4e371c..5d1abe34bdd 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -7,7 +7,7 @@
Copyright (C) 2001-2002 Convergence Integrated Media GmbH
Holger Waechtler <holger@convergence.de>
- Copyright (C) 2004 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2004 Steven Toth <stoth@linuxtv.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
@@ -34,13 +34,12 @@
#include "dvb_frontend.h"
#include "cx22702.h"
-
struct cx22702_state {
- struct i2c_adapter* i2c;
+ struct i2c_adapter *i2c;
/* configuration settings */
- const struct cx22702_config* config;
+ const struct cx22702_config *config;
struct dvb_frontend frontend;
@@ -49,10 +48,13 @@ struct cx22702_state {
};
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
#define dprintk if (debug) printk
/* Register values to initialise the demod */
-static u8 init_tab [] = {
+static u8 init_tab[] = {
0x00, 0x00, /* Stop aquisition */
0x0B, 0x06,
0x09, 0x01,
@@ -80,65 +82,67 @@ static u8 init_tab [] = {
0xfd, 0x00,
};
-static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
{
int ret;
- u8 buf [] = { reg, data };
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address, .flags = 0,
+ .buf = buf, .len = 2 };
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+ printk(KERN_ERR
+ "%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
__func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
-static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
- struct i2c_msg msg [] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 } };
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
return b1[0];
}
-static int cx22702_set_inversion (struct cx22702_state *state, int inversion)
+static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
{
u8 val;
switch (inversion) {
-
- case INVERSION_AUTO:
- return -EOPNOTSUPP;
-
- case INVERSION_ON:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val | 0x01);
-
- case INVERSION_OFF:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val & 0xfe);
-
- default:
- return -EINVAL;
-
+ case INVERSION_AUTO:
+ return -EOPNOTSUPP;
+ case INVERSION_ON:
+ val = cx22702_readreg(state, 0x0C);
+ return cx22702_writereg(state, 0x0C, val | 0x01);
+ case INVERSION_OFF:
+ val = cx22702_readreg(state, 0x0C);
+ return cx22702_writereg(state, 0x0C, val & 0xfe);
+ default:
+ return -EINVAL;
}
}
/* Retrieve the demod settings */
-static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p)
+static int cx22702_get_tps(struct cx22702_state *state,
+ struct dvb_ofdm_parameters *p)
{
u8 val;
@@ -146,180 +150,281 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
if (!(cx22702_readreg(state, 0x0A) & 0x20))
return -EAGAIN;
- val = cx22702_readreg (state, 0x01);
- switch( (val&0x18)>>3) {
- case 0: p->constellation = QPSK; break;
- case 1: p->constellation = QAM_16; break;
- case 2: p->constellation = QAM_64; break;
+ val = cx22702_readreg(state, 0x01);
+ switch ((val & 0x18) >> 3) {
+ case 0:
+ p->constellation = QPSK;
+ break;
+ case 1:
+ p->constellation = QAM_16;
+ break;
+ case 2:
+ p->constellation = QAM_64;
+ break;
}
- switch( val&0x07 ) {
- case 0: p->hierarchy_information = HIERARCHY_NONE; break;
- case 1: p->hierarchy_information = HIERARCHY_1; break;
- case 2: p->hierarchy_information = HIERARCHY_2; break;
- case 3: p->hierarchy_information = HIERARCHY_4; break;
+ switch (val & 0x07) {
+ case 0:
+ p->hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ p->hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ p->hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ p->hierarchy_information = HIERARCHY_4;
+ break;
}
- val = cx22702_readreg (state, 0x02);
- switch( (val&0x38)>>3 ) {
- case 0: p->code_rate_HP = FEC_1_2; break;
- case 1: p->code_rate_HP = FEC_2_3; break;
- case 2: p->code_rate_HP = FEC_3_4; break;
- case 3: p->code_rate_HP = FEC_5_6; break;
- case 4: p->code_rate_HP = FEC_7_8; break;
+ val = cx22702_readreg(state, 0x02);
+ switch ((val & 0x38) >> 3) {
+ case 0:
+ p->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_HP = FEC_7_8;
+ break;
}
- switch( val&0x07 ) {
- case 0: p->code_rate_LP = FEC_1_2; break;
- case 1: p->code_rate_LP = FEC_2_3; break;
- case 2: p->code_rate_LP = FEC_3_4; break;
- case 3: p->code_rate_LP = FEC_5_6; break;
- case 4: p->code_rate_LP = FEC_7_8; break;
+ switch (val & 0x07) {
+ case 0:
+ p->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_LP = FEC_7_8;
+ break;
}
-
- val = cx22702_readreg (state, 0x03);
- switch( (val&0x0c)>>2 ) {
- case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
+ val = cx22702_readreg(state, 0x03);
+ switch ((val & 0x0c) >> 2) {
+ case 0:
+ p->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ p->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ p->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ p->guard_interval = GUARD_INTERVAL_1_4;
+ break;
}
- switch( val&0x03 ) {
- case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+ switch (val & 0x03) {
+ case 0:
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
}
return 0;
}
-static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
- struct cx22702_state* state = fe->demodulator_priv;
- dprintk ("%s(%d)\n", __func__, enable);
+ struct cx22702_state *state = fe->demodulator_priv;
+ dprintk("%s(%d)\n", __func__, enable);
if (enable)
- return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ return cx22702_writereg(state, 0x0D,
+ cx22702_readreg(state, 0x0D) & 0xfe);
else
- return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+ return cx22702_writereg(state, 0x0D,
+ cx22702_readreg(state, 0x0D) | 1);
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
u8 val;
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
}
/* set inversion */
- cx22702_set_inversion (state, p->inversion);
+ cx22702_set_inversion(state, p->inversion);
/* set bandwidth */
- switch(p->u.ofdm.bandwidth) {
+ switch (p->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 );
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20);
break;
case BANDWIDTH_7_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 );
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10);
break;
case BANDWIDTH_8_MHZ:
- cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+ cx22702_writereg(state, 0x0C,
+ cx22702_readreg(state, 0x0C) & 0xcf);
break;
default:
- dprintk ("%s: invalid bandwidth\n",__func__);
+ dprintk("%s: invalid bandwidth\n", __func__);
return -EINVAL;
}
-
- p->u.ofdm.code_rate_LP = FEC_AUTO; //temp hack as manual not working
+ p->u.ofdm.code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
/* use auto configuration? */
- if((p->u.ofdm.hierarchy_information==HIERARCHY_AUTO) ||
- (p->u.ofdm.constellation==QAM_AUTO) ||
- (p->u.ofdm.code_rate_HP==FEC_AUTO) ||
- (p->u.ofdm.code_rate_LP==FEC_AUTO) ||
- (p->u.ofdm.guard_interval==GUARD_INTERVAL_AUTO) ||
- (p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) {
+ if ((p->u.ofdm.hierarchy_information == HIERARCHY_AUTO) ||
+ (p->u.ofdm.constellation == QAM_AUTO) ||
+ (p->u.ofdm.code_rate_HP == FEC_AUTO) ||
+ (p->u.ofdm.code_rate_LP == FEC_AUTO) ||
+ (p->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO) ||
+ (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO)) {
/* TPS Source - use hardware driven values */
cx22702_writereg(state, 0x06, 0x10);
cx22702_writereg(state, 0x07, 0x9);
cx22702_writereg(state, 0x08, 0xC1);
- cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
+ & 0xfc);
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
- dprintk("%s: Autodetecting\n",__func__);
+ dprintk("%s: Autodetecting\n", __func__);
return 0;
}
/* manually programmed values */
- val=0;
- switch(p->u.ofdm.constellation) {
- case QPSK: val = (val&0xe7); break;
- case QAM_16: val = (val&0xe7)|0x08; break;
- case QAM_64: val = (val&0xe7)|0x10; break;
- default:
- dprintk ("%s: invalid constellation\n",__func__);
- return -EINVAL;
+ val = 0;
+ switch (p->u.ofdm.constellation) {
+ case QPSK:
+ val = (val & 0xe7);
+ break;
+ case QAM_16:
+ val = (val & 0xe7) | 0x08;
+ break;
+ case QAM_64:
+ val = (val & 0xe7) | 0x10;
+ break;
+ default:
+ dprintk("%s: invalid constellation\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.hierarchy_information) {
- case HIERARCHY_NONE: val = (val&0xf8); break;
- case HIERARCHY_1: val = (val&0xf8)|1; break;
- case HIERARCHY_2: val = (val&0xf8)|2; break;
- case HIERARCHY_4: val = (val&0xf8)|3; break;
- default:
- dprintk ("%s: invalid hierarchy\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.hierarchy_information) {
+ case HIERARCHY_NONE:
+ val = (val & 0xf8);
+ break;
+ case HIERARCHY_1:
+ val = (val & 0xf8) | 1;
+ break;
+ case HIERARCHY_2:
+ val = (val & 0xf8) | 2;
+ break;
+ case HIERARCHY_4:
+ val = (val & 0xf8) | 3;
+ break;
+ default:
+ dprintk("%s: invalid hierarchy\n", __func__);
+ return -EINVAL;
}
- cx22702_writereg (state, 0x06, val);
-
- val=0;
- switch(p->u.ofdm.code_rate_HP) {
- case FEC_NONE:
- case FEC_1_2: val = (val&0xc7); break;
- case FEC_2_3: val = (val&0xc7)|0x08; break;
- case FEC_3_4: val = (val&0xc7)|0x10; break;
- case FEC_5_6: val = (val&0xc7)|0x18; break;
- case FEC_7_8: val = (val&0xc7)|0x20; break;
- default:
- dprintk ("%s: invalid code_rate_HP\n",__func__);
- return -EINVAL;
+ cx22702_writereg(state, 0x06, val);
+
+ val = 0;
+ switch (p->u.ofdm.code_rate_HP) {
+ case FEC_NONE:
+ case FEC_1_2:
+ val = (val & 0xc7);
+ break;
+ case FEC_2_3:
+ val = (val & 0xc7) | 0x08;
+ break;
+ case FEC_3_4:
+ val = (val & 0xc7) | 0x10;
+ break;
+ case FEC_5_6:
+ val = (val & 0xc7) | 0x18;
+ break;
+ case FEC_7_8:
+ val = (val & 0xc7) | 0x20;
+ break;
+ default:
+ dprintk("%s: invalid code_rate_HP\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.code_rate_LP) {
- case FEC_NONE:
- case FEC_1_2: val = (val&0xf8); break;
- case FEC_2_3: val = (val&0xf8)|1; break;
- case FEC_3_4: val = (val&0xf8)|2; break;
- case FEC_5_6: val = (val&0xf8)|3; break;
- case FEC_7_8: val = (val&0xf8)|4; break;
- default:
- dprintk ("%s: invalid code_rate_LP\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.code_rate_LP) {
+ case FEC_NONE:
+ case FEC_1_2:
+ val = (val & 0xf8);
+ break;
+ case FEC_2_3:
+ val = (val & 0xf8) | 1;
+ break;
+ case FEC_3_4:
+ val = (val & 0xf8) | 2;
+ break;
+ case FEC_5_6:
+ val = (val & 0xf8) | 3;
+ break;
+ case FEC_7_8:
+ val = (val & 0xf8) | 4;
+ break;
+ default:
+ dprintk("%s: invalid code_rate_LP\n", __func__);
+ return -EINVAL;
}
- cx22702_writereg (state, 0x07, val);
-
- val=0;
- switch(p->u.ofdm.guard_interval) {
- case GUARD_INTERVAL_1_32: val = (val&0xf3); break;
- case GUARD_INTERVAL_1_16: val = (val&0xf3)|0x04; break;
- case GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
- case GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
- default:
- dprintk ("%s: invalid guard_interval\n",__func__);
- return -EINVAL;
+ cx22702_writereg(state, 0x07, val);
+
+ val = 0;
+ switch (p->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_32:
+ val = (val & 0xf3);
+ break;
+ case GUARD_INTERVAL_1_16:
+ val = (val & 0xf3) | 0x04;
+ break;
+ case GUARD_INTERVAL_1_8:
+ val = (val & 0xf3) | 0x08;
+ break;
+ case GUARD_INTERVAL_1_4:
+ val = (val & 0xf3) | 0x0c;
+ break;
+ default:
+ dprintk("%s: invalid guard_interval\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.transmission_mode) {
- case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
- case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
- default:
- dprintk ("%s: invalid transmission_mode\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K:
+ val = (val & 0xfc);
+ break;
+ case TRANSMISSION_MODE_8K:
+ val = (val & 0xfc) | 1;
+ break;
+ default:
+ dprintk("%s: invalid transmission_mode\n", __func__);
+ return -EINVAL;
}
cx22702_writereg(state, 0x08, val);
- cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ cx22702_writereg(state, 0x0B,
+ (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
/* Begin channel aquisition */
cx22702_writereg(state, 0x00, 0x01);
@@ -329,109 +434,111 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
-static int cx22702_init (struct dvb_frontend* fe)
+static int cx22702_init(struct dvb_frontend *fe)
{
int i;
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- cx22702_writereg (state, 0x00, 0x02);
+ cx22702_writereg(state, 0x00, 0x02);
msleep(10);
- for (i=0; i<sizeof(init_tab); i+=2)
- cx22702_writereg (state, init_tab[i], init_tab[i+1]);
+ for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
+ cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
- cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
+ cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
+ & 0x02);
cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
-static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u8 reg0A;
u8 reg23;
*status = 0;
- reg0A = cx22702_readreg (state, 0x0A);
- reg23 = cx22702_readreg (state, 0x23);
+ reg0A = cx22702_readreg(state, 0x0A);
+ reg23 = cx22702_readreg(state, 0x23);
- dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
- ,__func__,reg0A,reg23);
+ dprintk("%s: status demod=0x%02x agc=0x%02x\n"
+ , __func__, reg0A, reg23);
- if(reg0A & 0x10) {
+ if (reg0A & 0x10) {
*status |= FE_HAS_LOCK;
*status |= FE_HAS_VITERBI;
*status |= FE_HAS_SYNC;
}
- if(reg0A & 0x20)
+ if (reg0A & 0x20)
*status |= FE_HAS_CARRIER;
- if(reg23 < 0xf0)
+ if (reg23 < 0xf0)
*status |= FE_HAS_SIGNAL;
return 0;
}
-static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- if(cx22702_readreg (state, 0xE4) & 0x02) {
+ if (cx22702_readreg(state, 0xE4) & 0x02) {
/* Realtime statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)&0x7F);
+ *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | (cx22702_readreg(state, 0xDF) & 0x7F);
} else {
/* Averagtine statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | cx22702_readreg (state, 0xDF);
+ *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | cx22702_readreg(state, 0xDF);
}
return 0;
}
-static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx22702_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u16 rs_ber = 0;
- rs_ber = cx22702_readreg (state, 0x23);
+ rs_ber = cx22702_readreg(state, 0x23);
*signal_strength = (rs_ber << 8) | rs_ber;
return 0;
}
-static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- u16 rs_ber=0;
- if(cx22702_readreg (state, 0xE4) & 0x02) {
+ u16 rs_ber = 0;
+ if (cx22702_readreg(state, 0xE4) & 0x02) {
/* Realtime statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)& 0x7F);
+ rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | (cx22702_readreg(state, 0xDF) & 0x7F);
} else {
/* Averagine statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8
- | cx22702_readreg (state, 0xDF);
+ rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
+ | cx22702_readreg(state, 0xDF);
}
*snr = ~rs_ber;
return 0;
}
-static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u8 _ucblocks;
/* RS Uncorrectable Packet Count then reset */
- _ucblocks = cx22702_readreg (state, 0xE3);
+ _ucblocks = cx22702_readreg(state, 0xE3);
if (state->prevUCBlocks < _ucblocks)
*ucblocks = (_ucblocks - state->prevUCBlocks);
else
@@ -441,34 +548,36 @@ static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- u8 reg0C = cx22702_readreg (state, 0x0C);
+ u8 reg0C = cx22702_readreg(state, 0x0C);
p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
- return cx22702_get_tps (state, &p->u.ofdm);
+ return cx22702_get_tps(state, &p->u.ofdm);
}
-static int cx22702_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int cx22702_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
return 0;
}
-static void cx22702_release(struct dvb_frontend* fe)
+static void cx22702_release(struct dvb_frontend *fe)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops cx22702_ops;
-struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
+ struct i2c_adapter *i2c)
{
- struct cx22702_state* state = NULL;
+ struct cx22702_state *state = NULL;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
@@ -485,7 +594,8 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
goto error;
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &cx22702_ops,
+ sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -493,6 +603,7 @@ error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(cx22702_attach);
static struct dvb_frontend_ops cx22702_ops = {
@@ -525,11 +636,6 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_ucblocks = cx22702_read_ucblocks,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cx22702_attach);
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
index 8af766a3155..f154e1f428e 100644
--- a/drivers/media/dvb/frontends/cx22702.h
+++ b/drivers/media/dvb/frontends/cx22702.h
@@ -7,7 +7,7 @@
Copyright (C) 2001-2002 Convergence Integrated Media GmbH
Holger Waechtler <holger@convergence.de>
- Copyright (C) 2004 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2004 Steven Toth <stoth@linuxtv.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
@@ -30,8 +30,7 @@
#include <linux/dvb/frontend.h>
-struct cx22702_config
-{
+struct cx22702_config {
/* the demodulator's i2c address */
u8 demod_address;
@@ -41,16 +40,19 @@ struct cx22702_config
u8 output_mode;
};
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
+ && defined(MODULE))
+extern struct dvb_frontend *cx22702_attach(
+ const struct cx22702_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx22702_attach(
+ const struct cx22702_config *config,
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_CX22702
+#endif
-#endif // CX22702_H
+#endif
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
index 1792adb23c4..fdcceee91f3 100644
--- a/drivers/media/dvb/frontends/cx24110.h
+++ b/drivers/media/dvb/frontends/cx24110.h
@@ -33,12 +33,17 @@ struct cx24110_config
u8 demod_address;
};
-static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
- int r = 0;
- u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
+{
+ u8 buf[] = {
+ (u8)((val >> 24) & 0xff),
+ (u8)((val >> 16) & 0xff),
+ (u8)((val >> 8) & 0xff)
+ };
+
if (fe->ops.write)
- r = fe->ops.write(fe, buf, 3);
- return r;
+ return fe->ops.write(fe, buf, 3);
+ return 0;
}
#if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
new file mode 100644
index 00000000000..b144b308a4d
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -0,0 +1,1470 @@
+/*
+ Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+ Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2006-2007 Georg Acher
+ Copyright (C) 2007-2008 Darron Broad
+ March 2007
+ Fixed some bugs.
+ Added diseqc support.
+ Added corrected signal strength support.
+ August 2007
+ Sync with legacy version.
+ Some clean ups.
+ Copyright (C) 2008 Igor Liplianin
+ September, 9th 2008
+ Fixed locking on high symbol rates (>30000).
+ Implement MPEG initialization parameter.
+
+ 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.
+*/
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "cx24116.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define dprintk(args...) \
+ do { \
+ if (debug) \
+ printk(KERN_INFO "cx24116: " args); \
+ } while (0)
+
+#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
+#define CX24116_SEARCH_RANGE_KHZ 5000
+
+/* known registers */
+#define CX24116_REG_COMMAND (0x00) /* command args 0x00..0x1e */
+#define CX24116_REG_EXECUTE (0x1f) /* execute command */
+#define CX24116_REG_MAILBOX (0x96) /* FW or multipurpose mailbox? */
+#define CX24116_REG_RESET (0x20) /* reset status > 0 */
+#define CX24116_REG_SIGNAL (0x9e) /* signal low */
+#define CX24116_REG_SSTATUS (0x9d) /* signal high / status */
+#define CX24116_REG_QUALITY8 (0xa3)
+#define CX24116_REG_QSTATUS (0xbc)
+#define CX24116_REG_QUALITY0 (0xd5)
+#define CX24116_REG_BER0 (0xc9)
+#define CX24116_REG_BER8 (0xc8)
+#define CX24116_REG_BER16 (0xc7)
+#define CX24116_REG_BER24 (0xc6)
+#define CX24116_REG_UCB0 (0xcb)
+#define CX24116_REG_UCB8 (0xca)
+#define CX24116_REG_CLKDIV (0xf3)
+#define CX24116_REG_RATEDIV (0xf9)
+
+/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+#define CX24116_REG_FECSTATUS (0x9c)
+
+/* FECSTATUS bits */
+/* mask to determine configured fec (not tuned) or actual fec (tuned) */
+#define CX24116_FEC_FECMASK (0x1f)
+
+/* Select DVB-S demodulator, else DVB-S2 */
+#define CX24116_FEC_DVBS (0x20)
+#define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */
+
+/* Pilot mode requested when tuning else always reset when tuned */
+#define CX24116_FEC_PILOT (0x80)
+
+/* arg buffer size */
+#define CX24116_ARGLEN (0x1e)
+
+/* rolloff */
+#define CX24116_ROLLOFF_020 (0x00)
+#define CX24116_ROLLOFF_025 (0x01)
+#define CX24116_ROLLOFF_035 (0x02)
+
+/* pilot bit */
+#define CX24116_PILOT_OFF (0x00)
+#define CX24116_PILOT_ON (0x40)
+
+/* signal status */
+#define CX24116_HAS_SIGNAL (0x01)
+#define CX24116_HAS_CARRIER (0x02)
+#define CX24116_HAS_VITERBI (0x04)
+#define CX24116_HAS_SYNCLOCK (0x08)
+#define CX24116_HAS_UNKNOWN1 (0x10)
+#define CX24116_HAS_UNKNOWN2 (0x20)
+#define CX24116_STATUS_MASK (0x3f)
+#define CX24116_SIGNAL_MASK (0xc0)
+
+#define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */
+#define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */
+#define CX24116_DISEQC_MESGCACHE (2) /* message cached */
+
+/* arg offset for DiSEqC */
+#define CX24116_DISEQC_BURST (1)
+#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
+#define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */
+#define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */
+#define CX24116_DISEQC_MSGLEN (5)
+#define CX24116_DISEQC_MSGOFS (6)
+
+/* DiSEqC burst */
+#define CX24116_DISEQC_MINI_A (0)
+#define CX24116_DISEQC_MINI_B (1)
+
+/* DiSEqC tone burst */
+static int toneburst = 1;
+module_param(toneburst, int, 0644);
+MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
+ "2=MESSAGE CACHE (default:1)");
+
+/* SNR measurements */
+static int esno_snr;
+module_param(esno_snr, int, 0644);
+MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
+ "1=ESNO(db * 10) (default:0)");
+
+enum cmds {
+ CMD_SET_VCO = 0x10,
+ CMD_TUNEREQUEST = 0x11,
+ CMD_MPEGCONFIG = 0x13,
+ CMD_TUNERINIT = 0x14,
+ CMD_BANDWIDTH = 0x15,
+ CMD_GETAGC = 0x19,
+ CMD_LNBCONFIG = 0x20,
+ CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
+ CMD_SET_TONEPRE = 0x22,
+ CMD_SET_TONE = 0x23,
+ CMD_UPDFWVERS = 0x35,
+ CMD_TUNERSLEEP = 0x36,
+ CMD_AGCCONTROL = 0x3b, /* Unknown */
+};
+
+/* The Demod/Tuner can't easily provide these, we cache them */
+struct cx24116_tuning {
+ u32 frequency;
+ u32 symbol_rate;
+ fe_spectral_inversion_t inversion;
+ fe_code_rate_t fec;
+
+ fe_modulation_t modulation;
+ fe_pilot_t pilot;
+ fe_rolloff_t rolloff;
+
+ /* Demod values */
+ u8 fec_val;
+ u8 fec_mask;
+ u8 inversion_val;
+ u8 pilot_val;
+ u8 rolloff_val;
+};
+
+/* Basic commands that are sent to the firmware */
+struct cx24116_cmd {
+ u8 len;
+ u8 args[CX24116_ARGLEN];
+};
+
+struct cx24116_state {
+ struct i2c_adapter *i2c;
+ const struct cx24116_config *config;
+
+ struct dvb_frontend frontend;
+
+ struct cx24116_tuning dcur;
+ struct cx24116_tuning dnxt;
+
+ u8 skip_fw_load;
+ u8 burst;
+ struct cx24116_cmd dsec_cmd;
+};
+
+static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address,
+ .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if (debug > 1)
+ printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
+ __func__, reg, data);
+
+ err = i2c_transfer(state->i2c, &msg, 1);
+ if (err != 1) {
+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
+ " value == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+/* Bulk byte writes to a single I2C address, for 32k firmware load */
+static int cx24116_writeregN(struct cx24116_state *state, int reg,
+ const u8 *data, u16 len)
+{
+ int ret = -EREMOTEIO;
+ struct i2c_msg msg;
+ u8 *buf;
+
+ buf = kmalloc(len + 1, GFP_KERNEL);
+ if (buf == NULL) {
+ printk("Unable to kmalloc\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ *(buf) = reg;
+ memcpy(buf + 1, data, len);
+
+ msg.addr = state->config->demod_address;
+ msg.flags = 0;
+ msg.buf = buf;
+ msg.len = len + 1;
+
+ if (debug > 1)
+ printk(KERN_INFO "cx24116: %s: write regN 0x%02x, len = %d\n",
+ __func__, reg, len);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1) {
+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
+ __func__, ret, reg);
+ ret = -EREMOTEIO;
+ }
+
+error:
+ kfree(buf);
+
+ return ret;
+}
+
+static int cx24116_readreg(struct cx24116_state *state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
+ __func__, reg, ret);
+ return ret;
+ }
+
+ if (debug > 1)
+ printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
+ reg, b1[0]);
+
+ return b1[0];
+}
+
+static int cx24116_set_inversion(struct cx24116_state *state,
+ fe_spectral_inversion_t inversion)
+{
+ dprintk("%s(%d)\n", __func__, inversion);
+
+ switch (inversion) {
+ case INVERSION_OFF:
+ state->dnxt.inversion_val = 0x00;
+ break;
+ case INVERSION_ON:
+ state->dnxt.inversion_val = 0x04;
+ break;
+ case INVERSION_AUTO:
+ state->dnxt.inversion_val = 0x0C;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ state->dnxt.inversion = inversion;
+
+ return 0;
+}
+
+/*
+ * modfec (modulation and FEC)
+ * ===========================
+ *
+ * MOD FEC mask/val standard
+ * ---- -------- ----------- --------
+ * QPSK FEC_1_2 0x02 0x02+X DVB-S
+ * QPSK FEC_2_3 0x04 0x02+X DVB-S
+ * QPSK FEC_3_4 0x08 0x02+X DVB-S
+ * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
+ * QPSK FEC_5_6 0x20 0x02+X DVB-S
+ * QPSK FEC_6_7 0x40 0x02+X DVB-S
+ * QPSK FEC_7_8 0x80 0x02+X DVB-S
+ * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
+ * QPSK AUTO 0xff 0x02+X DVB-S
+ *
+ * For DVB-S high byte probably represents FEC
+ * and low byte selects the modulator. The high
+ * byte is search range mask. Bit 5 may turn
+ * on DVB-S and remaining bits represent some
+ * kind of calibration (how/what i do not know).
+ *
+ * Eg.(2/3) szap "Zone Horror"
+ *
+ * mask/val = 0x04, 0x20
+ * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
+ *
+ * mask/val = 0x04, 0x30
+ * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
+ *
+ * After tuning FECSTATUS contains actual FEC
+ * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
+ *
+ * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
+ *
+ * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
+ * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
+ * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
+ * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
+ * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
+ * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
+ * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
+ * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
+ *
+ * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
+ * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
+ * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
+ * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
+ * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
+ * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
+ *
+ * For DVB-S2 low bytes selects both modulator
+ * and FEC. High byte is meaningless here. To
+ * set pilot, bit 6 (0x40) is set. When inspecting
+ * FECSTATUS bit 7 (0x80) represents the pilot
+ * selection whilst not tuned. When tuned, actual FEC
+ * in use is found in FECSTATUS as per above. Pilot
+ * value is reset.
+ */
+
+/* A table of modulation, fec and configuration bytes for the demod.
+ * Not all S2 mmodulation schemes are support and not all rates with
+ * a scheme are support. Especially, no auto detect when in S2 mode.
+ */
+struct cx24116_modfec {
+ fe_delivery_system_t delivery_system;
+ fe_modulation_t modulation;
+ fe_code_rate_t fec;
+ u8 mask; /* In DVBS mode this is used to autodetect */
+ u8 val; /* Passed to the firmware to indicate mode selection */
+} CX24116_MODFEC_MODES[] = {
+ /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
+
+ /*mod fec mask val */
+ { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
+ { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
+ { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
+ { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
+ { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
+ { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
+ { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
+ { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
+ { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
+ { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
+ /* NBC-QPSK */
+ { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
+ /* 8PSK */
+ { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
+ /*
+ * `val' can be found in the FECSTATUS register when tuning.
+ * FECSTATUS will give the actual FEC in use if tuning was successful.
+ */
+};
+
+static int cx24116_lookup_fecmod(struct cx24116_state *state,
+ fe_modulation_t m, fe_code_rate_t f)
+{
+ int i, ret = -EOPNOTSUPP;
+
+ dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
+
+ for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
+ if ((m == CX24116_MODFEC_MODES[i].modulation) &&
+ (f == CX24116_MODFEC_MODES[i].fec)) {
+ ret = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int cx24116_set_fec(struct cx24116_state *state,
+ fe_modulation_t mod, fe_code_rate_t fec)
+{
+ int ret = 0;
+
+ dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
+
+ ret = cx24116_lookup_fecmod(state, mod, fec);
+
+ if (ret < 0)
+ return ret;
+
+ state->dnxt.fec = fec;
+ state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
+ state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
+ dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
+ state->dnxt.fec_mask, state->dnxt.fec_val);
+
+ return 0;
+}
+
+static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
+{
+ dprintk("%s(%d)\n", __func__, rate);
+
+ /* check if symbol rate is within limits */
+ if ((rate > state->frontend.ops.info.symbol_rate_max) ||
+ (rate < state->frontend.ops.info.symbol_rate_min)) {
+ dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
+ return -EOPNOTSUPP;
+ }
+
+ state->dnxt.symbol_rate = rate;
+ dprintk("%s() symbol_rate = %d\n", __func__, rate);
+
+ return 0;
+}
+
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+ const struct firmware *fw);
+
+static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ const struct firmware *fw;
+ int ret = 0;
+
+ dprintk("%s()\n", __func__);
+
+ if (cx24116_readreg(state, 0x20) > 0) {
+
+ if (state->skip_fw_load)
+ return 0;
+
+ /* Load firmware */
+ /* request the firmware, this will block until loaded */
+ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
+ __func__, CX24116_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
+ &state->i2c->dev);
+ printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
+ __func__);
+ if (ret) {
+ printk(KERN_ERR "%s: No firmware uploaded "
+ "(timeout or file not found?)\n", __func__);
+ return ret;
+ }
+
+ /* Make sure we don't recurse back through here
+ * during loading */
+ state->skip_fw_load = 1;
+
+ ret = cx24116_load_firmware(fe, fw);
+ if (ret)
+ printk(KERN_ERR "%s: Writing firmware to device failed\n",
+ __func__);
+
+ release_firmware(fw);
+
+ printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
+ ret == 0 ? "complete" : "failed");
+
+ /* Ensure firmware is always loaded if required */
+ state->skip_fw_load = 0;
+ }
+
+ return ret;
+}
+
+/* Take a basic firmware command structure, format it
+ * and forward it for processing
+ */
+static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ int i, ret;
+
+ dprintk("%s()\n", __func__);
+
+ /* Load the firmware if required */
+ ret = cx24116_firmware_ondemand(fe);
+ if (ret != 0) {
+ printk(KERN_ERR "%s(): Unable initialise the firmware\n",
+ __func__);
+ return ret;
+ }
+
+ /* Write the command */
+ for (i = 0; i < cmd->len ; i++) {
+ dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
+ cx24116_writereg(state, i, cmd->args[i]);
+ }
+
+ /* Start execution and wait for cmd to terminate */
+ cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
+ while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
+ msleep(10);
+ if (i++ > 64) {
+ /* Avoid looping forever if the firmware does
+ not respond */
+ printk(KERN_WARNING "%s() Firmware not responding\n",
+ __func__);
+ return -EREMOTEIO;
+ }
+ }
+ return 0;
+}
+
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+ const struct firmware *fw)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct cx24116_cmd cmd;
+ int i, ret;
+ unsigned char vers[4];
+
+ dprintk("%s\n", __func__);
+ dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
+ fw->size,
+ fw->data[0],
+ fw->data[1],
+ fw->data[fw->size-2],
+ fw->data[fw->size-1]);
+
+ /* Toggle 88x SRST pin to reset demod */
+ if (state->config->reset_device)
+ state->config->reset_device(fe);
+
+ /* Begin the firmware load process */
+ /* Prepare the demod, load the firmware, cleanup after load */
+
+ /* Init PLL */
+ cx24116_writereg(state, 0xE5, 0x00);
+ cx24116_writereg(state, 0xF1, 0x08);
+ cx24116_writereg(state, 0xF2, 0x13);
+
+ /* Start PLL */
+ cx24116_writereg(state, 0xe0, 0x03);
+ cx24116_writereg(state, 0xe0, 0x00);
+
+ /* Unknown */
+ cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+ cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+
+ /* Unknown */
+ cx24116_writereg(state, 0xF0, 0x03);
+ cx24116_writereg(state, 0xF4, 0x81);
+ cx24116_writereg(state, 0xF5, 0x00);
+ cx24116_writereg(state, 0xF6, 0x00);
+
+ /* write the entire firmware as one transaction */
+ cx24116_writeregN(state, 0xF7, fw->data, fw->size);
+
+ cx24116_writereg(state, 0xF4, 0x10);
+ cx24116_writereg(state, 0xF0, 0x00);
+ cx24116_writereg(state, 0xF8, 0x06);
+
+ /* Firmware CMD 10: VCO config */
+ cmd.args[0x00] = CMD_SET_VCO;
+ cmd.args[0x01] = 0x05;
+ cmd.args[0x02] = 0xdc;
+ cmd.args[0x03] = 0xda;
+ cmd.args[0x04] = 0xae;
+ cmd.args[0x05] = 0xaa;
+ cmd.args[0x06] = 0x04;
+ cmd.args[0x07] = 0x9d;
+ cmd.args[0x08] = 0xfc;
+ cmd.args[0x09] = 0x06;
+ cmd.len = 0x0a;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
+
+ /* Firmware CMD 14: Tuner config */
+ cmd.args[0x00] = CMD_TUNERINIT;
+ cmd.args[0x01] = 0x00;
+ cmd.args[0x02] = 0x00;
+ cmd.len = 0x03;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ cx24116_writereg(state, 0xe5, 0x00);
+
+ /* Firmware CMD 13: MPEG config */
+ cmd.args[0x00] = CMD_MPEGCONFIG;
+ cmd.args[0x01] = 0x01;
+ cmd.args[0x02] = 0x75;
+ cmd.args[0x03] = 0x00;
+ if (state->config->mpg_clk_pos_pol)
+ cmd.args[0x04] = state->config->mpg_clk_pos_pol;
+ else
+ cmd.args[0x04] = 0x02;
+ cmd.args[0x05] = 0x00;
+ cmd.len = 0x06;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Firmware CMD 35: Get firmware version */
+ cmd.args[0x00] = CMD_UPDFWVERS;
+ cmd.len = 0x02;
+ for (i = 0; i < 4; i++) {
+ cmd.args[0x01] = i;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+ vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
+ }
+ printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
+ vers[0], vers[1], vers[2], vers[3]);
+
+ return 0;
+}
+
+static int cx24116_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t voltage)
+{
+ /* The isl6421 module will override this function in the fops. */
+ dprintk("%s() This should never appear if the isl6421 module "
+ "is loaded correctly\n", __func__);
+
+ return -EOPNOTSUPP;
+}
+
+static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+
+ int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
+
+ dprintk("%s: status = 0x%02x\n", __func__, lock);
+
+ *status = 0;
+
+ if (lock & CX24116_HAS_SIGNAL)
+ *status |= FE_HAS_SIGNAL;
+ if (lock & CX24116_HAS_CARRIER)
+ *status |= FE_HAS_CARRIER;
+ if (lock & CX24116_HAS_VITERBI)
+ *status |= FE_HAS_VITERBI;
+ if (lock & CX24116_HAS_SYNCLOCK)
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __func__);
+
+ *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
+ (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
+ (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
+ cx24116_readreg(state, CX24116_REG_BER0);
+
+ return 0;
+}
+
+/* TODO Determine function and scale appropriately */
+static int cx24116_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct cx24116_cmd cmd;
+ int ret;
+ u16 sig_reading;
+
+ dprintk("%s()\n", __func__);
+
+ /* Firmware CMD 19: Get AGC */
+ cmd.args[0x00] = CMD_GETAGC;
+ cmd.len = 0x01;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ sig_reading =
+ (cx24116_readreg(state,
+ CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
+ (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
+ *signal_strength = 0 - sig_reading;
+
+ dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
+ __func__, sig_reading, *signal_strength);
+
+ return 0;
+}
+
+/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
+static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ u8 snr_reading;
+ static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
+ 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
+ 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
+ 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
+ 0x18000 };
+
+ dprintk("%s()\n", __func__);
+
+ snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+ if (snr_reading >= 0xa0 /* 100% */)
+ *snr = 0xffff;
+ else
+ *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
+ (snr_tab[(snr_reading & 0x0f)] >> 4);
+
+ dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
+ snr_reading, *snr);
+
+ return 0;
+}
+
+/* The reelbox patches show the value in the registers represents
+ * ESNO, from 0->30db (values 0->300). We provide this value by
+ * default.
+ */
+static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __func__);
+
+ *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
+ cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+ dprintk("%s: raw 0x%04x\n", __func__, *snr);
+
+ return 0;
+}
+
+static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ if (esno_snr == 1)
+ return cx24116_read_snr_esno(fe, snr);
+ else
+ return cx24116_read_snr_pct(fe, snr);
+}
+
+static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __func__);
+
+ *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
+ cx24116_readreg(state, CX24116_REG_UCB0);
+
+ return 0;
+}
+
+/* Overwrite the current tuning params, we are about to tune */
+static void cx24116_clone_params(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
+}
+
+/* Wait for LNB */
+static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ int i;
+
+ dprintk("%s() qstatus = 0x%02x\n", __func__,
+ cx24116_readreg(state, CX24116_REG_QSTATUS));
+
+ /* Wait for up to 300 ms */
+ for (i = 0; i < 30 ; i++) {
+ if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
+ return 0;
+ msleep(10);
+ }
+
+ dprintk("%s(): LNB not ready\n", __func__);
+
+ return -ETIMEDOUT; /* -EBUSY ? */
+}
+
+static int cx24116_set_tone(struct dvb_frontend *fe,
+ fe_sec_tone_mode_t tone)
+{
+ struct cx24116_cmd cmd;
+ int ret;
+
+ dprintk("%s(%d)\n", __func__, tone);
+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+ printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
+ return -EINVAL;
+ }
+
+ /* Wait for LNB ready */
+ ret = cx24116_wait_for_lnb(fe);
+ if (ret != 0)
+ return ret;
+
+ /* Min delay time after DiSEqC send */
+ msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+ /* This is always done before the tone is set */
+ cmd.args[0x00] = CMD_SET_TONEPRE;
+ cmd.args[0x01] = 0x00;
+ cmd.len = 0x02;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Now we set the tone */
+ cmd.args[0x00] = CMD_SET_TONE;
+ cmd.args[0x01] = 0x00;
+ cmd.args[0x02] = 0x00;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __func__);
+ cmd.args[0x03] = 0x01;
+ break;
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n", __func__);
+ cmd.args[0x03] = 0x00;
+ break;
+ }
+ cmd.len = 0x04;
+
+ /* Min delay time before DiSEqC send */
+ msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+ return cx24116_cmd_execute(fe, &cmd);
+}
+
+/* Initialise DiSEqC */
+static int cx24116_diseqc_init(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct cx24116_cmd cmd;
+ int ret;
+
+ /* Firmware CMD 20: LNB/DiSEqC config */
+ cmd.args[0x00] = CMD_LNBCONFIG;
+ cmd.args[0x01] = 0x00;
+ cmd.args[0x02] = 0x10;
+ cmd.args[0x03] = 0x00;
+ cmd.args[0x04] = 0x8f;
+ cmd.args[0x05] = 0x28;
+ cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
+ cmd.args[0x07] = 0x01;
+ cmd.len = 0x08;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Prepare a DiSEqC command */
+ state->dsec_cmd.args[0x00] = CMD_LNBSEND;
+
+ /* DiSEqC burst */
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
+
+ /* Unknown */
+ state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
+ state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
+ /* Continuation flag? */
+ state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
+
+ /* DiSEqC message length */
+ state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
+
+ /* Command length */
+ state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
+
+ return 0;
+}
+
+/* Send DiSEqC message with derived burst (hack) || previous burst */
+static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *d)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ int i, ret;
+
+ /* Dump DiSEqC message */
+ if (debug) {
+ printk(KERN_INFO "cx24116: %s(", __func__);
+ for (i = 0 ; i < d->msg_len ;) {
+ printk(KERN_INFO "0x%02x", d->msg[i]);
+ if (++i < d->msg_len)
+ printk(KERN_INFO ", ");
+ }
+ printk(") toneburst=%d\n", toneburst);
+ }
+
+ /* Validate length */
+ if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
+ return -EINVAL;
+
+ /* DiSEqC message */
+ for (i = 0; i < d->msg_len; i++)
+ state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
+
+ /* DiSEqC message length */
+ state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
+
+ /* Command length */
+ state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
+ state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
+
+ /* DiSEqC toneburst */
+ if (toneburst == CX24116_DISEQC_MESGCACHE)
+ /* Message is cached */
+ return 0;
+
+ else if (toneburst == CX24116_DISEQC_TONEOFF)
+ /* Message is sent without burst */
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
+
+ else if (toneburst == CX24116_DISEQC_TONECACHE) {
+ /*
+ * Message is sent with derived else cached burst
+ *
+ * WRITE PORT GROUP COMMAND 38
+ *
+ * 0/A/A: E0 10 38 F0..F3
+ * 1/B/B: E0 10 38 F4..F7
+ * 2/C/A: E0 10 38 F8..FB
+ * 3/D/B: E0 10 38 FC..FF
+ *
+ * databyte[3]= 8421:8421
+ * ABCD:WXYZ
+ * CLR :SET
+ *
+ * WX= PORT SELECT 0..3 (X=TONEBURST)
+ * Y = VOLTAGE (0=13V, 1=18V)
+ * Z = BAND (0=LOW, 1=HIGH(22K))
+ */
+ if (d->msg_len >= 4 && d->msg[2] == 0x38)
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ ((d->msg[3] & 4) >> 2);
+ if (debug)
+ dprintk("%s burst=%d\n", __func__,
+ state->dsec_cmd.args[CX24116_DISEQC_BURST]);
+ }
+
+ /* Wait for LNB ready */
+ ret = cx24116_wait_for_lnb(fe);
+ if (ret != 0)
+ return ret;
+
+ /* Wait for voltage/min repeat delay */
+ msleep(100);
+
+ /* Command */
+ ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+ if (ret != 0)
+ return ret;
+ /*
+ * Wait for send
+ *
+ * Eutelsat spec:
+ * >15ms delay + (XXX determine if FW does this, see set_tone)
+ * 13.5ms per byte +
+ * >15ms delay +
+ * 12.5ms burst +
+ * >15ms delay (XXX determine if FW does this, see set_tone)
+ */
+ msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
+ ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
+
+ return 0;
+}
+
+/* Send DiSEqC burst */
+static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ int ret;
+
+ dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
+
+ /* DiSEqC burst */
+ if (burst == SEC_MINI_A)
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ CX24116_DISEQC_MINI_A;
+ else if (burst == SEC_MINI_B)
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ CX24116_DISEQC_MINI_B;
+ else
+ return -EINVAL;
+
+ /* DiSEqC toneburst */
+ if (toneburst != CX24116_DISEQC_MESGCACHE)
+ /* Burst is cached */
+ return 0;
+
+ /* Burst is to be sent with cached message */
+
+ /* Wait for LNB ready */
+ ret = cx24116_wait_for_lnb(fe);
+ if (ret != 0)
+ return ret;
+
+ /* Wait for voltage/min repeat delay */
+ msleep(100);
+
+ /* Command */
+ ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+ if (ret != 0)
+ return ret;
+
+ /*
+ * Wait for send
+ *
+ * Eutelsat spec:
+ * >15ms delay + (XXX determine if FW does this, see set_tone)
+ * 13.5ms per byte +
+ * >15ms delay +
+ * 12.5ms burst +
+ * >15ms delay (XXX determine if FW does this, see set_tone)
+ */
+ msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
+
+ return 0;
+}
+
+static void cx24116_release(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ dprintk("%s\n", __func__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops cx24116_ops;
+
+struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct cx24116_state *state = NULL;
+ int ret;
+
+ dprintk("%s\n", __func__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error1;
+
+ /* setup the state */
+ memset(state, 0, sizeof(struct cx24116_state));
+
+ state->config = config;
+ state->i2c = i2c;
+
+ /* check if the demod is present */
+ ret = (cx24116_readreg(state, 0xFF) << 8) |
+ cx24116_readreg(state, 0xFE);
+ if (ret != 0x0501) {
+ printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
+ goto error2;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &cx24116_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error2: kfree(state);
+error1: return NULL;
+}
+EXPORT_SYMBOL(cx24116_attach);
+
+/*
+ * Initialise or wake up device
+ *
+ * Power config will reset and load initial firmware if required
+ */
+static int cx24116_initfe(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct cx24116_cmd cmd;
+ int ret;
+
+ dprintk("%s()\n", __func__);
+
+ /* Power on */
+ cx24116_writereg(state, 0xe0, 0);
+ cx24116_writereg(state, 0xe1, 0);
+ cx24116_writereg(state, 0xea, 0);
+
+ /* Firmware CMD 36: Power config */
+ cmd.args[0x00] = CMD_TUNERSLEEP;
+ cmd.args[0x01] = 0;
+ cmd.len = 0x02;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ return cx24116_diseqc_init(fe);
+}
+
+/*
+ * Put device to sleep
+ */
+static int cx24116_sleep(struct dvb_frontend *fe)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct cx24116_cmd cmd;
+ int ret;
+
+ dprintk("%s()\n", __func__);
+
+ /* Firmware CMD 36: Power config */
+ cmd.args[0x00] = CMD_TUNERSLEEP;
+ cmd.args[0x01] = 1;
+ cmd.len = 0x02;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Power off (Shutdown clocks) */
+ cx24116_writereg(state, 0xea, 0xff);
+ cx24116_writereg(state, 0xe1, 1);
+ cx24116_writereg(state, 0xe0, 1);
+
+ return 0;
+}
+
+static int cx24116_set_property(struct dvb_frontend *fe,
+ struct dtv_property *tvp)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+static int cx24116_get_property(struct dvb_frontend *fe,
+ struct dtv_property *tvp)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+/* dvb-core told us to tune, the tv property cache will be complete,
+ * it's safe for is to pull values and use them for tuning purposes.
+ */
+static int cx24116_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct cx24116_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct cx24116_cmd cmd;
+ fe_status_t tunerstat;
+ int i, status, ret, retune;
+
+ dprintk("%s()\n", __func__);
+
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ dprintk("%s: DVB-S delivery system selected\n", __func__);
+
+ /* Only QPSK is supported for DVB-S */
+ if (c->modulation != QPSK) {
+ dprintk("%s: unsupported modulation selected (%d)\n",
+ __func__, c->modulation);
+ return -EOPNOTSUPP;
+ }
+
+ /* Pilot doesn't exist in DVB-S, turn bit off */
+ state->dnxt.pilot_val = CX24116_PILOT_OFF;
+ retune = 1;
+
+ /* DVB-S only supports 0.35 */
+ if (c->rolloff != ROLLOFF_35) {
+ dprintk("%s: unsupported rolloff selected (%d)\n",
+ __func__, c->rolloff);
+ return -EOPNOTSUPP;
+ }
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+ break;
+
+ case SYS_DVBS2:
+ dprintk("%s: DVB-S2 delivery system selected\n", __func__);
+
+ /*
+ * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
+ * but not hardware auto detection
+ */
+ if (c->modulation != PSK_8 && c->modulation != QPSK) {
+ dprintk("%s: unsupported modulation selected (%d)\n",
+ __func__, c->modulation);
+ return -EOPNOTSUPP;
+ }
+
+ switch (c->pilot) {
+ case PILOT_AUTO: /* Not supported but emulated */
+ state->dnxt.pilot_val = (c->modulation == QPSK)
+ ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
+ retune = 2;
+ break;
+ case PILOT_OFF:
+ state->dnxt.pilot_val = CX24116_PILOT_OFF;
+ break;
+ case PILOT_ON:
+ state->dnxt.pilot_val = CX24116_PILOT_ON;
+ break;
+ default:
+ dprintk("%s: unsupported pilot mode selected (%d)\n",
+ __func__, c->pilot);
+ return -EOPNOTSUPP;
+ }
+
+ switch (c->rolloff) {
+ case ROLLOFF_20:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
+ break;
+ case ROLLOFF_25:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
+ break;
+ case ROLLOFF_35:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+ break;
+ case ROLLOFF_AUTO: /* Rolloff must be explicit */
+ default:
+ dprintk("%s: unsupported rolloff selected (%d)\n",
+ __func__, c->rolloff);
+ return -EOPNOTSUPP;
+ }
+ break;
+
+ default:
+ dprintk("%s: unsupported delivery system selected (%d)\n",
+ __func__, c->delivery_system);
+ return -EOPNOTSUPP;
+ }
+ state->dnxt.modulation = c->modulation;
+ state->dnxt.frequency = c->frequency;
+ state->dnxt.pilot = c->pilot;
+ state->dnxt.rolloff = c->rolloff;
+
+ ret = cx24116_set_inversion(state, c->inversion);
+ if (ret != 0)
+ return ret;
+
+ /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
+ ret = cx24116_set_fec(state, c->modulation, c->fec_inner);
+ if (ret != 0)
+ return ret;
+
+ ret = cx24116_set_symbolrate(state, c->symbol_rate);
+ if (ret != 0)
+ return ret;
+
+ /* discard the 'current' tuning parameters and prepare to tune */
+ cx24116_clone_params(fe);
+
+ dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
+ dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
+ dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
+ state->dcur.pilot, state->dcur.pilot_val);
+ dprintk("%s: retune = %d\n", __func__, retune);
+ dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
+ state->dcur.rolloff, state->dcur.rolloff_val);
+ dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
+ dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
+ state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
+ dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
+ state->dcur.inversion, state->dcur.inversion_val);
+
+ /* This is also done in advise/acquire on HVR4000 but not on LITE */
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ /* Set/Reset B/W */
+ cmd.args[0x00] = CMD_BANDWIDTH;
+ cmd.args[0x01] = 0x01;
+ cmd.len = 0x02;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* Prepare a tune request */
+ cmd.args[0x00] = CMD_TUNEREQUEST;
+
+ /* Frequency */
+ cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
+ cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
+ cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
+
+ /* Symbol Rate */
+ cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
+ cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
+
+ /* Automatic Inversion */
+ cmd.args[0x06] = state->dcur.inversion_val;
+
+ /* Modulation / FEC / Pilot */
+ cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
+
+ cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
+ cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
+ cmd.args[0x0a] = 0x00;
+ cmd.args[0x0b] = 0x00;
+ cmd.args[0x0c] = state->dcur.rolloff_val;
+ cmd.args[0x0d] = state->dcur.fec_mask;
+
+ if (state->dcur.symbol_rate > 30000000) {
+ cmd.args[0x0e] = 0x04;
+ cmd.args[0x0f] = 0x00;
+ cmd.args[0x10] = 0x01;
+ cmd.args[0x11] = 0x77;
+ cmd.args[0x12] = 0x36;
+ cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
+ cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
+ } else {
+ cmd.args[0x0e] = 0x06;
+ cmd.args[0x0f] = 0x00;
+ cmd.args[0x10] = 0x00;
+ cmd.args[0x11] = 0xFA;
+ cmd.args[0x12] = 0x24;
+ cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+ cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+ }
+
+ cmd.len = 0x13;
+
+ /* We need to support pilot and non-pilot tuning in the
+ * driver automatically. This is a workaround for because
+ * the demod does not support autodetect.
+ */
+ do {
+ /* Reset status register */
+ status = cx24116_readreg(state, CX24116_REG_SSTATUS)
+ & CX24116_SIGNAL_MASK;
+ cx24116_writereg(state, CX24116_REG_SSTATUS, status);
+
+ /* Tune */
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ break;
+
+ /*
+ * Wait for up to 500 ms before retrying
+ *
+ * If we are able to tune then generally it occurs within 100ms.
+ * If it takes longer, try a different toneburst setting.
+ */
+ for (i = 0; i < 50 ; i++) {
+ cx24116_read_status(fe, &tunerstat);
+ status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
+ if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
+ dprintk("%s: Tuned\n", __func__);
+ goto tuned;
+ }
+ msleep(10);
+ }
+
+ dprintk("%s: Not tuned\n", __func__);
+
+ /* Toggle pilot bit when in auto-pilot */
+ if (state->dcur.pilot == PILOT_AUTO)
+ cmd.args[0x07] ^= CX24116_PILOT_ON;
+ } while (--retune);
+
+tuned: /* Set/Reset B/W */
+ cmd.args[0x00] = CMD_BANDWIDTH;
+ cmd.args[0x01] = 0x00;
+ cmd.len = 0x02;
+ ret = cx24116_cmd_execute(fe, &cmd);
+ if (ret != 0)
+ return ret;
+
+ return ret;
+}
+
+static struct dvb_frontend_ops cx24116_ops = {
+
+ .info = {
+ .name = "Conexant CX24116/CX24118",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+ .frequency_tolerance = 5000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_RECOVER
+ },
+
+ .release = cx24116_release,
+
+ .init = cx24116_initfe,
+ .sleep = cx24116_sleep,
+ .read_status = cx24116_read_status,
+ .read_ber = cx24116_read_ber,
+ .read_signal_strength = cx24116_read_signal_strength,
+ .read_snr = cx24116_read_snr,
+ .read_ucblocks = cx24116_read_ucblocks,
+ .set_tone = cx24116_set_tone,
+ .set_voltage = cx24116_set_voltage,
+ .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
+ .diseqc_send_burst = cx24116_diseqc_send_burst,
+
+ .set_property = cx24116_set_property,
+ .get_property = cx24116_get_property,
+ .set_frontend = cx24116_set_frontend,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h
new file mode 100644
index 00000000000..4cb3ddd6c62
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24116.h
@@ -0,0 +1,54 @@
+/*
+ Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+ Copyright (C) 2006 Steven Toth <stoth@linuxtv.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef CX24116_H
+#define CX24116_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24116_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* Need to set device param for start_dma */
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+
+ /* Need to reset device during firmware loading */
+ int (*reset_device)(struct dvb_frontend *fe);
+
+ /* Need to set MPEG parameters */
+ u8 mpg_clk_pos_pol:0x02;
+};
+
+#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
+extern struct dvb_frontend *cx24116_attach(
+ const struct cx24116_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *cx24116_attach(
+ const struct cx24116_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* CX24116_H */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 7f68d78c655..1a8c36f7606 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -1,7 +1,7 @@
/*
* Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
*
- * Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+ * Copyright (C) 2005 Steven Toth <stoth@linuxtv.org>
*
* Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
*
@@ -33,7 +33,13 @@
#define XTAL 10111000
static int force_band;
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select "\
+ "(1-9, default:off).");
+
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
#define err(args...) do { printk(KERN_ERR "CX24123: " args); } while (0)
@@ -46,10 +52,9 @@ static int debug;
} \
} while (0)
-struct cx24123_state
-{
- struct i2c_adapter* i2c;
- const struct cx24123_config* config;
+struct cx24123_state {
+ struct i2c_adapter *i2c;
+ const struct cx24123_config *config;
struct dvb_frontend frontend;
@@ -70,8 +75,7 @@ struct cx24123_state
};
/* Various tuner defaults need to be established for a given symbol rate Sps */
-static struct
-{
+static struct cx24123_AGC_val {
u32 symbolrate_low;
u32 symbolrate_high;
u32 VCAprogdata;
@@ -109,8 +113,7 @@ static struct
* fixme: The bounds on the bands do not match the doc in real life.
* fixme: Some of them have been moved, other might need adjustment.
*/
-static struct
-{
+static struct cx24123_bandselect_val {
u32 freq_low;
u32 freq_high;
u32 VCOdivider;
@@ -249,7 +252,8 @@ static int cx24123_i2c_writereg(struct cx24123_state *state,
/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ err = i2c_transfer(state->i2c, &msg, 1);
+ if (err != 1) {
printk("%s: writereg error(err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __func__, err, reg, data);
return err;
@@ -284,7 +288,8 @@ static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
#define cx24123_writereg(state, reg, val) \
cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
-static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+static int cx24123_set_inversion(struct cx24123_state *state,
+ fe_spectral_inversion_t inversion)
{
u8 nom_reg = cx24123_readreg(state, 0x0e);
u8 auto_reg = cx24123_readreg(state, 0x10);
@@ -311,7 +316,8 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
return 0;
}
-static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+static int cx24123_get_inversion(struct cx24123_state *state,
+ fe_spectral_inversion_t *inversion)
{
u8 val;
@@ -328,18 +334,20 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
return 0;
}
-static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
{
u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
- if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+ if ((fec < FEC_NONE) || (fec > FEC_AUTO))
fec = FEC_AUTO;
/* Set the soft decision threshold */
- if(fec == FEC_1_2)
- cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+ if (fec == FEC_1_2)
+ cx24123_writereg(state, 0x43,
+ cx24123_readreg(state, 0x43) | 0x01);
else
- cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
+ cx24123_writereg(state, 0x43,
+ cx24123_readreg(state, 0x43) & ~0x01);
switch (fec) {
case FEC_1_2:
@@ -388,11 +396,11 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
return 0;
}
-static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
{
int ret;
- ret = cx24123_readreg (state, 0x1b);
+ ret = cx24123_readreg(state, 0x1b);
if (ret < 0)
return ret;
ret = ret & 0x07;
@@ -433,16 +441,16 @@ static u32 cx24123_int_log2(u32 a, u32 b)
{
u32 exp, nearest = 0;
u32 div = a / b;
- if(a % b >= b / 2) ++div;
- if(div < (1 << 31))
- {
- for(exp = 1; div > exp; nearest++)
+ if (a % b >= b / 2)
+ ++div;
+ if (div < (1 << 31)) {
+ for (exp = 1; div > exp; nearest++)
exp += exp;
}
return nearest;
}
-static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
{
u32 tmp, sample_rate, ratio, sample_gain;
u8 pll_mult;
@@ -498,9 +506,9 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
cx24123_writereg(state, 0x01, pll_mult * 6);
- cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f );
- cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff );
- cx24123_writereg(state, 0x0a, (ratio ) & 0xff );
+ cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f);
+ cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff);
+ cx24123_writereg(state, 0x0a, ratio & 0xff);
/* also set the demodulator sample gain */
sample_gain = cx24123_int_log2(sample_rate, srate);
@@ -514,10 +522,12 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
}
/*
- * Based on the required frequency and symbolrate, the tuner AGC has to be configured
- * and the correct band selected. Calculate those values
+ * Based on the required frequency and symbolrate, the tuner AGC has
+ * to be configured and the correct band selected.
+ * Calculate those values.
*/
-static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
u32 ndiv = 0, adiv = 0, vco_div = 0;
@@ -525,6 +535,8 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
int pump = 2;
int band = 0;
int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
+ struct cx24123_bandselect_val *bsv = NULL;
+ struct cx24123_AGC_val *agcv = NULL;
/* Defaults for low freq, low rate */
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -532,58 +544,65 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
state->bandselectarg = cx24123_bandselect_vals[0].progdata;
vco_div = cx24123_bandselect_vals[0].VCOdivider;
- /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
- for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++)
- {
- if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
- (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
- state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
- state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
- state->FILTune = cx24123_AGC_vals[i].FILTune;
+ /* For the given symbol rate, determine the VCA, VGA and
+ * FILTUNE programming bits */
+ for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
+ agcv = &cx24123_AGC_vals[i];
+ if ((agcv->symbolrate_low <= p->u.qpsk.symbol_rate) &&
+ (agcv->symbolrate_high >= p->u.qpsk.symbol_rate)) {
+ state->VCAarg = agcv->VCAprogdata;
+ state->VGAarg = agcv->VGAprogdata;
+ state->FILTune = agcv->FILTune;
}
}
/* determine the band to use */
- if(force_band < 1 || force_band > num_bands)
- {
- for (i = 0; i < num_bands; i++)
- {
- if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
- (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+ if (force_band < 1 || force_band > num_bands) {
+ for (i = 0; i < num_bands; i++) {
+ bsv = &cx24123_bandselect_vals[i];
+ if ((bsv->freq_low <= p->frequency) &&
+ (bsv->freq_high >= p->frequency))
band = i;
}
- }
- else
+ } else
band = force_band - 1;
state->bandselectarg = cx24123_bandselect_vals[band].progdata;
vco_div = cx24123_bandselect_vals[band].VCOdivider;
/* determine the charge pump current */
- if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+ if (p->frequency < (cx24123_bandselect_vals[band].freq_low +
+ cx24123_bandselect_vals[band].freq_high) / 2)
pump = 0x01;
else
pump = 0x02;
/* Determine the N/A dividers for the requested lband freq (in kHz). */
- /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
- ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
- adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
+ /* Note: the reference divider R=10, frequency is in KHz,
+ * XTAL is in Hz */
+ ndiv = (((p->frequency * vco_div * 10) /
+ (2 * XTAL / 1000)) / 32) & 0x1ff;
+ adiv = (((p->frequency * vco_div * 10) /
+ (2 * XTAL / 1000)) % 32) & 0x1f;
if (adiv == 0 && ndiv > 0)
ndiv--;
- /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
- state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
+ /* control bits 11, refdiv 11, charge pump polarity 1,
+ * charge pump current, ndiv, adiv */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) |
+ (pump << 14) | (ndiv << 5) | adiv;
return 0;
}
/*
* Tuner data is 21 bits long, must be left-aligned in data.
- * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ * Tuner cx24109 is written through a dedicated 3wire interface
+ * on the demod chip.
*/
-static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p, u32 data)
{
struct cx24123_state *state = fe->demodulator_priv;
unsigned long timeout;
@@ -610,7 +629,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
/* send another 8 bytes, wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
- cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ cx24123_writereg(state, 0x22, (data >> 8) & 0xff);
while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
if (time_after(jiffies, timeout)) {
err("%s: demodulator is not responding, "\
@@ -620,9 +639,10 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
msleep(10);
}
- /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+ /* send the lower 5 bits of this byte, padded with 3 LBB,
+ * wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
- cx24123_writereg(state, 0x22, (data) & 0xff );
+ cx24123_writereg(state, 0x22, (data) & 0xff);
while ((cx24123_readreg(state, 0x20) & 0x80)) {
if (time_after(jiffies, timeout)) {
err("%s: demodulator is not responding," \
@@ -639,7 +659,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -690,7 +711,7 @@ static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
return cx24123_writereg(state, 0x23, r);
}
-static int cx24123_initfe(struct dvb_frontend* fe)
+static int cx24123_initfe(struct dvb_frontend *fe)
{
struct cx24123_state *state = fe->demodulator_priv;
int i;
@@ -699,19 +720,22 @@ static int cx24123_initfe(struct dvb_frontend* fe)
/* Configure the demod to a good set of defaults */
for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
- cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+ cx24123_writereg(state, cx24123_regdata[i].reg,
+ cx24123_regdata[i].data);
/* Set the LNB polarity */
- if(state->config->lnb_polarity)
- cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+ if (state->config->lnb_polarity)
+ cx24123_writereg(state, 0x32,
+ cx24123_readreg(state, 0x32) | 0x02);
if (state->config->dont_use_pll)
- cx24123_repeater_mode(state, 1, 0);
+ cx24123_repeater_mode(state, 1, 0);
return 0;
}
-static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24123_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t voltage)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -740,7 +764,7 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
{
unsigned long timeout = jiffies + msecs_to_jiffies(200);
while (!(cx24123_readreg(state, 0x29) & 0x40)) {
- if(time_after(jiffies, timeout)) {
+ if (time_after(jiffies, timeout)) {
err("%s: diseqc queue not ready, " \
"command may be lost.\n", __func__);
break;
@@ -749,7 +773,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
}
}
-static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
+static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *cmd)
{
struct cx24123_state *state = fe->demodulator_priv;
int i, val, tone;
@@ -771,20 +796,21 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
val = cx24123_readreg(state, 0x29);
- cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
+ cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) |
+ ((cmd->msg_len-3) & 3));
/* wait for diseqc message to finish sending */
cx24123_wait_for_diseqc(state);
/* restart continuous tone if enabled */
- if (tone & 0x10) {
+ if (tone & 0x10)
cx24123_writereg(state, 0x29, tone & ~0x40);
- }
return 0;
}
-static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
{
struct cx24123_state *state = fe->demodulator_priv;
int val, tone;
@@ -814,13 +840,13 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
/* restart continuous tone if enabled */
- if (tone & 0x10) {
+ if (tone & 0x10)
cx24123_writereg(state, 0x29, tone & ~0x40);
- }
+
return 0;
}
-static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct cx24123_state *state = fe->demodulator_priv;
int sync = cx24123_readreg(state, 0x14);
@@ -853,8 +879,9 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
/*
- * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
- * is available, so this value doubles up to satisfy both measurements
+ * Configured to return the measurement of errors in blocks,
+ * because no UCBLOCKS value is available, so this value doubles up
+ * to satisfy both measurements.
*/
static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
{
@@ -876,7 +903,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend *fe,
{
struct cx24123_state *state = fe->demodulator_priv;
- *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+ /* larger = better */
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8;
dprintk("Signal strength = %d\n", *signal_strength);
@@ -907,7 +935,7 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
- state->currentfreq=p->frequency;
+ state->currentfreq = p->frequency;
state->currentsymbolrate = p->u.qpsk.symbol_rate;
cx24123_set_inversion(state, p->inversion);
@@ -932,7 +960,8 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
@@ -952,7 +981,7 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -977,8 +1006,8 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
return 0;
}
-static int cx24123_tune(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
+static int cx24123_tune(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
@@ -997,12 +1026,12 @@ static int cx24123_tune(struct dvb_frontend* fe,
static int cx24123_get_algo(struct dvb_frontend *fe)
{
- return 1; //FE_ALGO_HW
+ return 1; /* FE_ALGO_HW */
}
-static void cx24123_release(struct dvb_frontend* fe)
+static void cx24123_release(struct dvb_frontend *fe)
{
- struct cx24123_state* state = fe->demodulator_priv;
+ struct cx24123_state *state = fe->demodulator_priv;
dprintk("\n");
i2c_del_adapter(&state->tuner_i2c_adapter);
kfree(state);
@@ -1013,7 +1042,7 @@ static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
{
struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
/* this repeater closes after the first stop */
- cx24123_repeater_mode(state, 1, 1);
+ cx24123_repeater_mode(state, 1, 1);
return i2c_transfer(state->i2c, msg, num);
}
@@ -1037,8 +1066,8 @@ EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
static struct dvb_frontend_ops cx24123_ops;
-struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+ struct i2c_adapter *i2c)
{
struct cx24123_state *state =
kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
@@ -1057,29 +1086,34 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
/* check if the demod is there */
state->demod_rev = cx24123_readreg(state, 0x00);
switch (state->demod_rev) {
- case 0xe1: info("detected CX24123C\n"); break;
- case 0xd1: info("detected CX24123\n"); break;
+ case 0xe1:
+ info("detected CX24123C\n");
+ break;
+ case 0xd1:
+ info("detected CX24123\n");
+ break;
default:
err("wrong demod revision: %x\n", state->demod_rev);
goto error;
}
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &cx24123_ops,
+ sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
- /* create tuner i2c adapter */
- if (config->dont_use_pll)
- cx24123_repeater_mode(state, 1, 0);
+ /* create tuner i2c adapter */
+ if (config->dont_use_pll)
+ cx24123_repeater_mode(state, 1, 0);
- strncpy(state->tuner_i2c_adapter.name,
- "CX24123 tuner I2C bus", I2C_NAME_SIZE);
+ strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
+ sizeof(state->tuner_i2c_adapter.name));
state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL,
state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo;
state->tuner_i2c_adapter.algo_data = NULL;
i2c_set_adapdata(&state->tuner_i2c_adapter, state);
if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
- err("tuner i2c bus could not be initialized\n");
+ err("tuner i2c bus could not be initialized\n");
goto error;
}
@@ -1090,6 +1124,7 @@ error:
return NULL;
}
+EXPORT_SYMBOL(cx24123_attach);
static struct dvb_frontend_ops cx24123_ops = {
@@ -1126,15 +1161,8 @@ static struct dvb_frontend_ops cx24123_ops = {
.get_frontend_algo = cx24123_get_algo,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-module_param(force_band, int, 0644);
-MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
-
MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
"CX24123/CX24109/CX24113 hardware");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(cx24123_attach);
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
index 81ebc3d2f19..51ae866e9fe 100644
--- a/drivers/media/dvb/frontends/cx24123.h
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -1,7 +1,7 @@
/*
Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
- Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2005 Steven Toth <stoth@linuxtv.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
@@ -23,13 +23,12 @@
#include <linux/dvb/frontend.h>
-struct cx24123_config
-{
+struct cx24123_config {
/* the demodulator's i2c address */
u8 demod_address;
/* Need to set device param for start_dma */
- int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
int lnb_polarity;
@@ -39,7 +38,8 @@ struct cx24123_config
void (*agc_callback) (struct dvb_frontend *);
};
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
+#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
+ && defined(MODULE))
extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
struct i2c_adapter *i2c);
extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
@@ -56,6 +56,6 @@ static struct i2c_adapter *
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_CX24123
+#endif
#endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index 3eedfdf505b..21f2c5161af 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -41,6 +41,7 @@ struct dib0070_config {
extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct dib0070_config *cfg);
+extern u16 dib0070_wbd_offset(struct dvb_frontend *);
#else
static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
@@ -49,9 +50,14 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
+
+static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
#endif
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
-extern u16 dib0070_wbd_offset(struct dvb_frontend *);
#endif
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index 5f1375e30df..0109720353b 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -1284,7 +1284,10 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di
}
EXPORT_SYMBOL(dib7000m_get_i2c_master);
-int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[])
+#if 0
+/* used with some prototype boards */
+int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
+ u8 default_addr, struct dib7000m_config cfg[])
{
struct dib7000m_state st = { .i2c_adap = i2c };
int k = 0;
@@ -1329,6 +1332,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
return 0;
}
EXPORT_SYMBOL(dib7000m_i2c_enumeration);
+#endif
static struct dvb_frontend_ops dib7000m_ops;
struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 1a0142e0d74..8217e5b38f4 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -1333,7 +1333,8 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
/* Ensure the output mode remains at the previous default if it's
* not specifically set by the caller.
*/
- if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
+ if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
+ (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
demod = &st->demod;
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 07c4d12ed5b..3e812685712 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -41,6 +41,14 @@ struct dib7000p_config {
extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
struct dib7000p_config *cfg);
+extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *,
+ enum dibx000_i2c_interface,
+ int);
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+ int no_of_demods, u8 default_addr,
+ struct dib7000p_config cfg[]);
+extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
+extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
#else
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
@@ -49,13 +57,36 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+static inline
+struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
+ enum dibx000_i2c_interface i, int x)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+ int no_of_demods, u8 default_addr,
+ struct dib7000p_config cfg[])
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+
+extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+
+extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+#endif
-extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
#endif
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
index 3cbed874a6f..b9ca5c8d2dd 100644
--- a/drivers/media/dvb/frontends/drx397xD.c
+++ b/drivers/media/dvb/frontends/drx397xD.c
@@ -38,35 +38,32 @@ static const char mod_name[] = "drx397xD";
#define F_SET_0D0h 1
#define F_SET_0D4h 2
-typedef enum fw_ix {
+enum fw_ix {
#define _FW_ENTRY(a, b) b
#include "drx397xD_fw.h"
-} fw_ix_t;
+};
/* chip specifics */
struct drx397xD_state {
struct i2c_adapter *i2c;
struct dvb_frontend frontend;
struct drx397xD_config config;
- fw_ix_t chip_rev;
+ enum fw_ix chip_rev;
int flags;
u32 bandwidth_parm; /* internal bandwidth conversions */
u32 f_osc; /* w90: actual osc frequency [Hz] */
};
-/*******************************************************************************
- * Firmware
- ******************************************************************************/
-
+/* Firmware */
static const char *blob_name[] = {
#define _BLOB_ENTRY(a, b) a
#include "drx397xD_fw.h"
};
-typedef enum blob_ix {
+enum blob_ix {
#define _BLOB_ENTRY(a, b) b
#include "drx397xD_fw.h"
-} blob_ix_t;
+};
static struct {
const char *name;
@@ -85,7 +82,7 @@ static struct {
};
/* use only with writer lock aquired */
-static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix)
{
memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
if (fw[ix].file)
@@ -94,9 +91,9 @@ static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
static void drx_release_fw(struct drx397xD_state *s)
{
- fw_ix_t ix = s->chip_rev;
+ enum fw_ix ix = s->chip_rev;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
write_lock(&fw[ix].lock);
if (fw[ix].refcnt) {
@@ -107,13 +104,13 @@ static void drx_release_fw(struct drx397xD_state *s)
write_unlock(&fw[ix].lock);
}
-static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix)
{
const u8 *data;
size_t size, len;
int i = 0, j, rc = -EINVAL;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
if (ix < 0 || ix >= ARRAY_SIZE(fw))
return -EINVAL;
@@ -175,32 +172,34 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
goto exit_corrupt;
}
} while (i < size);
- exit_corrupt:
+
+exit_corrupt:
printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
- exit_err:
+exit_err:
_drx_release_fw(s, ix);
fw[ix].refcnt--;
- exit_ok:
+exit_ok:
fw[ix].refcnt++;
write_unlock(&fw[ix].lock);
+
return rc;
}
-/*******************************************************************************
- * i2c bus IO
- ******************************************************************************/
-
-static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+/* i2c bus IO */
+static int write_fw(struct drx397xD_state *s, enum blob_ix ix)
{
- struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
const u8 *data;
int len, rc = 0, i = 0;
+ struct i2c_msg msg = {
+ .addr = s->config.demod_address,
+ .flags = 0
+ };
if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
- pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+ pr_debug("%s drx_fw_ix_t out of range\n", __func__);
return -EINVAL;
}
- pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+ pr_debug("%s %s\n", __func__, blob_name[ix]);
read_lock(&fw[s->chip_rev].lock);
data = fw[s->chip_rev].data[ix];
@@ -229,33 +228,33 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
goto exit_rc;
}
}
- exit_rc:
+exit_rc:
read_unlock(&fw[s->chip_rev].lock);
+
return 0;
}
/* Function is not endian safe, use the RD16 wrapper below */
-static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+static int _read16(struct drx397xD_state *s, __le32 i2c_adr)
{
int rc;
u8 a[4];
- u16 v;
+ __le16 v;
struct i2c_msg msg[2] = {
{
- .addr = s->config.demod_address,
- .flags = 0,
- .buf = a,
- .len = sizeof(a)
- }
- , {
- .addr = s->config.demod_address,
- .flags = I2C_M_RD,
- .buf = (u8 *) & v,
- .len = sizeof(v)
- }
+ .addr = s->config.demod_address,
+ .flags = 0,
+ .buf = a,
+ .len = sizeof(a)
+ }, {
+ .addr = s->config.demod_address,
+ .flags = I2C_M_RD,
+ .buf = (u8 *)&v,
+ .len = sizeof(v)
+ }
};
- *(u32 *) a = i2c_adr;
+ *(__le32 *) a = i2c_adr;
rc = i2c_transfer(s->i2c, msg, 2);
if (rc != 2)
@@ -265,7 +264,7 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr)
}
/* Function is not endian safe, use the WR16.. wrappers below */
-static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val)
{
u8 a[6];
int rc;
@@ -276,28 +275,28 @@ static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
.len = sizeof(a)
};
- *(u32 *) a = i2c_adr;
- *(u16 *) & a[4] = val;
+ *(__le32 *)a = i2c_adr;
+ *(__le16 *)&a[4] = val;
rc = i2c_transfer(s->i2c, &msg, 1);
if (rc != 1)
return -EIO;
+
return 0;
}
-#define WR16(ss,adr, val) \
+#define WR16(ss, adr, val) \
_write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
-#define WR16_E0(ss,adr, val) \
+#define WR16_E0(ss, adr, val) \
_write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
-#define RD16(ss,adr) \
+#define RD16(ss, adr) \
_read16(ss, I2C_ADR_C0(adr))
-#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
-
-/*******************************************************************************
- * Tuner callback
- ******************************************************************************/
+#define EXIT_RC(cmd) \
+ if ((rc = (cmd)) < 0) \
+ goto exit_rc
+/* Tuner callback */
static int PLL_Set(struct drx397xD_state *s,
struct dvb_frontend_parameters *fep, int *df_tuner)
{
@@ -305,7 +304,7 @@ static int PLL_Set(struct drx397xD_state *s,
u32 f_tuner, f = fep->frequency;
int rc;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
(f < s->frontend.ops.tuner_ops.info.frequency_min))
@@ -325,28 +324,26 @@ static int PLL_Set(struct drx397xD_state *s,
return rc;
*df_tuner = f_tuner - f;
- pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+ pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f,
f_tuner);
return 0;
}
-/*******************************************************************************
- * Demodulator helper functions
- ******************************************************************************/
-
+/* Demodulator helper functions */
static int SC_WaitForReady(struct drx397xD_state *s)
{
int cnt = 1000;
int rc;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
while (cnt--) {
rc = RD16(s, 0x820043);
if (rc == 0)
return 0;
}
+
return -1;
}
@@ -354,13 +351,14 @@ static int SC_SendCommand(struct drx397xD_state *s, int cmd)
{
int rc;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
WR16(s, 0x820043, cmd);
SC_WaitForReady(s);
rc = RD16(s, 0x820042);
if ((rc & 0xffff) == 0xffff)
return -1;
+
return 0;
}
@@ -368,7 +366,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd)
{
int rc, cnt = 1000;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
rc = WR16(s, 0x420032, cmd);
if (rc < 0)
@@ -383,22 +381,24 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd)
if (rc < 0)
return rc;
} while (--cnt);
+
return rc;
}
static int HI_CfgCommand(struct drx397xD_state *s)
{
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
WR16(s, 0x420033, 0x3973);
- WR16(s, 0x420034, s->config.w50); // code 4, log 4
- WR16(s, 0x420035, s->config.w52); // code 15, log 9
+ WR16(s, 0x420034, s->config.w50); /* code 4, log 4 */
+ WR16(s, 0x420035, s->config.w52); /* code 15, log 9 */
WR16(s, 0x420036, s->config.demod_address << 1);
- WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1
-// WR16(s, 0x420033, 0x3973);
+ WR16(s, 0x420037, s->config.w56); /* code (set_i2c ?? initX 1 ), log 1 */
+ /* WR16(s, 0x420033, 0x3973); */
if ((s->config.w56 & 8) == 0)
return HI_Command(s, 3);
+
return WR16(s, 0x420032, 0x3);
}
@@ -419,7 +419,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
u16 w0C = agc->w0C;
int quot, rem, i, rc = -EINVAL;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
if (agc->w04 > 0x3ff)
goto exit_rc;
@@ -468,7 +468,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
i = slowIncrDecLUT_15272[rem / 28];
EXIT_RC(WR16(s, 0x0c2002b, i));
rc = WR16(s, 0x0c2002c, i);
- exit_rc:
+exit_rc:
return rc;
}
@@ -478,7 +478,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
u16 w06 = agc->w06;
int rc = -1;
- pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+ pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06);
if (w04 > 0x3ff)
goto exit_rc;
@@ -498,7 +498,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
rc &= ~2;
break;
case 0:
- // loc_8000659
+ /* loc_8000659 */
s->config.w9C &= ~2;
EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
EXIT_RC(RD16(s, 0x0c20010));
@@ -522,7 +522,8 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
rc |= 2;
}
rc = WR16(s, 0x0c20013, rc);
- exit_rc:
+
+exit_rc:
return rc;
}
@@ -554,7 +555,7 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s)
int lockstat;
u32 clk, clk_limit;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
if (s->config.d5C == 0) {
EXIT_RC(WR16(s, 0x08200e8, 0x010));
@@ -598,11 +599,12 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s)
if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
s->f_osc = clk;
- pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+ pr_debug("%s: osc %d %d [Hz]\n", __func__,
s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
}
rc = WR16(s, 0x08200e8, 0);
- exit_rc:
+
+exit_rc:
return rc;
}
@@ -610,7 +612,7 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
{
int rc, si, bp;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
si = s->config.wA0;
if (s->config.w98 == 0) {
@@ -620,17 +622,17 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
si &= ~1;
bp = 0x200;
}
- if (s->config.w9A == 0) {
+ if (s->config.w9A == 0)
si |= 0x80;
- } else {
+ else
si &= ~0x80;
- }
EXIT_RC(WR16(s, 0x2150045, 0));
EXIT_RC(WR16(s, 0x2150010, si));
EXIT_RC(WR16(s, 0x2150011, bp));
rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
- exit_rc:
+
+exit_rc:
return rc;
}
@@ -646,7 +648,7 @@ static int drx_tune(struct drx397xD_state *s,
int rc, df_tuner;
int a, b, c, d;
- pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+ pr_debug("%s %d\n", __func__, s->config.d60);
if (s->config.d60 != 2)
goto set_tuner;
@@ -658,7 +660,7 @@ static int drx_tune(struct drx397xD_state *s,
rc = ConfigureMPEGOutput(s, 0);
if (rc < 0)
goto set_tuner;
- set_tuner:
+set_tuner:
rc = PLL_Set(s, fep, &df_tuner);
if (rc < 0) {
@@ -835,16 +837,16 @@ static int drx_tune(struct drx397xD_state *s,
rc = WR16(s, 0x2010012, 0);
if (rc < 0)
goto exit_rc;
- // QPSK QAM16 QAM64
- ebx = 0x19f; // 62
- ebp = 0x1fb; // 15
- v20 = 0x16a; // 62
- v1E = 0x195; // 62
- v16 = 0x1bb; // 15
- v14 = 0x1ef; // 15
- v12 = 5; // 16
- v10 = 5; // 16
- v0E = 5; // 16
+ /* QPSK QAM16 QAM64 */
+ ebx = 0x19f; /* 62 */
+ ebp = 0x1fb; /* 15 */
+ v20 = 0x16a; /* 62 */
+ v1E = 0x195; /* 62 */
+ v16 = 0x1bb; /* 15 */
+ v14 = 0x1ef; /* 15 */
+ v12 = 5; /* 16 */
+ v10 = 5; /* 16 */
+ v0E = 5; /* 16 */
}
switch (fep->u.ofdm.constellation) {
@@ -997,17 +999,17 @@ static int drx_tune(struct drx397xD_state *s,
case BANDWIDTH_8_MHZ: /* 0 */
case BANDWIDTH_AUTO:
rc = WR16(s, 0x0c2003f, 0x32);
- s->bandwidth_parm = ebx = 0x8b8249; // 9142857
+ s->bandwidth_parm = ebx = 0x8b8249;
edx = 0;
break;
case BANDWIDTH_7_MHZ:
rc = WR16(s, 0x0c2003f, 0x3b);
- s->bandwidth_parm = ebx = 0x7a1200; // 8000000
+ s->bandwidth_parm = ebx = 0x7a1200;
edx = 0x4807;
break;
case BANDWIDTH_6_MHZ:
rc = WR16(s, 0x0c2003f, 0x47);
- s->bandwidth_parm = ebx = 0x68a1b6; // 6857142
+ s->bandwidth_parm = ebx = 0x68a1b6;
edx = 0x0f07;
break;
};
@@ -1060,8 +1062,6 @@ static int drx_tune(struct drx397xD_state *s,
WR16(s, 0x0820040, 1);
SC_SendCommand(s, 1);
-// rc = WR16(s, 0x2150000, 1);
-// if (rc < 0) goto exit_rc;
rc = WR16(s, 0x2150000, 2);
rc = WR16(s, 0x2150016, a);
@@ -1069,7 +1069,8 @@ static int drx_tune(struct drx397xD_state *s,
rc = WR16(s, 0x2150036, 0);
rc = WR16(s, 0x2150000, 1);
s->config.d60 = 2;
- exit_rc:
+
+exit_rc:
return rc;
}
@@ -1082,7 +1083,7 @@ static int drx397x_init(struct dvb_frontend *fe)
struct drx397xD_state *s = fe->demodulator_priv;
int rc;
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __func__);
s->config.rfagc.d00 = 2; /* 0x7c */
s->config.rfagc.w04 = 0;
@@ -1102,18 +1103,18 @@ static int drx397x_init(struct dvb_frontend *fe)
/* HI_CfgCommand */
s->config.w50 = 4;
- s->config.w52 = 9; // 0xf;
+ s->config.w52 = 9;
- s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */
- s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */
- s->config.w92 = 12000; // 20000;
+ s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */
+ s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */
+ s->config.w92 = 12000;
s->config.w9C = 0x000e;
s->config.w9E = 0x0000;
/* ConfigureMPEGOutput params */
s->config.wA0 = 4;
- s->config.w98 = 1; // 0;
+ s->config.w98 = 1;
s->config.w9A = 1;
/* get chip revision */
@@ -1248,7 +1249,7 @@ static int drx397x_init(struct dvb_frontend *fe)
rc = WR16(s, 0x0c20012, 1);
}
- write_DRXD_InitFE_1:
+write_DRXD_InitFE_1:
rc = write_fw(s, DRXD_InitFE_1);
if (rc < 0)
@@ -1311,7 +1312,8 @@ static int drx397x_init(struct dvb_frontend *fe)
s->config.d5C = 0;
s->config.d60 = 1;
s->config.d48 = 1;
- error:
+
+error:
return rc;
}
@@ -1326,7 +1328,8 @@ static int drx397x_set_frontend(struct dvb_frontend *fe,
{
struct drx397xD_state *s = fe->demodulator_priv;
- s->config.s20d24 = 1; // 0;
+ s->config.s20d24 = 1;
+
return drx_tune(s, params);
}
@@ -1337,18 +1340,16 @@ static int drx397x_get_tune_settings(struct dvb_frontend *fe,
fe_tune_settings->min_delay_ms = 10000;
fe_tune_settings->step_size = 0;
fe_tune_settings->max_drift = 0;
+
return 0;
}
-static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct drx397xD_state *s = fe->demodulator_priv;
int lockstat;
GetLockStatus(s, &lockstat);
- /* TODO */
-// if (lockstat & 1)
-// CorrectSysClockDeviation(s);
*status = 0;
if (lockstat & 2) {
@@ -1356,9 +1357,8 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
ConfigureMPEGOutput(s, 1);
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
}
- if (lockstat & 4) {
+ if (lockstat & 4)
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
- }
return 0;
}
@@ -1366,16 +1366,18 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
{
*ber = 0;
+
return 0;
}
-static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr)
{
*snr = 0;
+
return 0;
}
-static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct drx397xD_state *s = fe->demodulator_priv;
int rc;
@@ -1401,6 +1403,7 @@ static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
* The following does the same but with less rounding errors:
*/
*strength = ~(7720 + (rc * 30744 >> 10));
+
return 0;
}
@@ -1408,6 +1411,7 @@ static int drx397x_read_ucblocks(struct dvb_frontend *fe,
unsigned int *ucblocks)
{
*ucblocks = 0;
+
return 0;
}
@@ -1436,22 +1440,22 @@ static struct dvb_frontend_ops drx397x_ops = {
.frequency_max = 855250000,
.frequency_stepsize = 166667,
.frequency_tolerance = 0,
- .caps = /* 0x0C01B2EAE */
- FE_CAN_FEC_1_2 | // = 0x2,
- FE_CAN_FEC_2_3 | // = 0x4,
- FE_CAN_FEC_3_4 | // = 0x8,
- FE_CAN_FEC_5_6 | // = 0x20,
- FE_CAN_FEC_7_8 | // = 0x80,
- FE_CAN_FEC_AUTO | // = 0x200,
- FE_CAN_QPSK | // = 0x400,
- FE_CAN_QAM_16 | // = 0x800,
- FE_CAN_QAM_64 | // = 0x2000,
- FE_CAN_QAM_AUTO | // = 0x10000,
- FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000,
- FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000,
- FE_CAN_HIERARCHY_AUTO | // = 0x100000,
- FE_CAN_RECOVER | // = 0x40000000,
- FE_CAN_MUTE_TS // = 0x80000000
+ .caps = /* 0x0C01B2EAE */
+ FE_CAN_FEC_1_2 | /* = 0x2, */
+ FE_CAN_FEC_2_3 | /* = 0x4, */
+ FE_CAN_FEC_3_4 | /* = 0x8, */
+ FE_CAN_FEC_5_6 | /* = 0x20, */
+ FE_CAN_FEC_7_8 | /* = 0x80, */
+ FE_CAN_FEC_AUTO | /* = 0x200, */
+ FE_CAN_QPSK | /* = 0x400, */
+ FE_CAN_QAM_16 | /* = 0x800, */
+ FE_CAN_QAM_64 | /* = 0x2000, */
+ FE_CAN_QAM_AUTO | /* = 0x10000, */
+ FE_CAN_TRANSMISSION_MODE_AUTO | /* = 0x20000, */
+ FE_CAN_GUARD_INTERVAL_AUTO | /* = 0x80000, */
+ FE_CAN_HIERARCHY_AUTO | /* = 0x100000, */
+ FE_CAN_RECOVER | /* = 0x40000000, */
+ FE_CAN_MUTE_TS /* = 0x80000000 */
},
.release = drx397x_release,
@@ -1472,33 +1476,35 @@ static struct dvb_frontend_ops drx397x_ops = {
struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
struct i2c_adapter *i2c)
{
- struct drx397xD_state *s = NULL;
+ struct drx397xD_state *state;
/* allocate memory for the internal state */
- s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
- if (s == NULL)
+ state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+ if (!state)
goto error;
/* setup the state */
- s->i2c = i2c;
- memcpy(&s->config, config, sizeof(struct drx397xD_config));
+ state->i2c = i2c;
+ memcpy(&state->config, config, sizeof(struct drx397xD_config));
/* check if the demod is there */
- if (RD16(s, 0x2410019) < 0)
+ if (RD16(state, 0x2410019) < 0)
goto error;
/* create dvb_frontend */
- memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
- s->frontend.demodulator_priv = s;
+ memcpy(&state->frontend.ops, &drx397x_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ return &state->frontend;
+error:
+ kfree(state);
- return &s->frontend;
- error:
- kfree(s);
return NULL;
}
+EXPORT_SYMBOL(drx397xD_attach);
MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
MODULE_AUTHOR("Henk Vergonet");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(drx397xD_attach);
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h
index ddc7a07971b..ba05d17290c 100644
--- a/drivers/media/dvb/frontends/drx397xD.h
+++ b/drivers/media/dvb/frontends/drx397xD.h
@@ -28,7 +28,7 @@
#define DRX_F_OFFSET 36000000
#define I2C_ADR_C0(x) \
-( (u32)cpu_to_le32( \
+( cpu_to_le32( \
(u32)( \
(((u32)(x) & (u32)0x000000ffUL) ) | \
(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
@@ -38,7 +38,7 @@
)
#define I2C_ADR_E0(x) \
-( (u32)cpu_to_le32( \
+( cpu_to_le32( \
(u32)( \
(((u32)(x) & (u32)0x000000ffUL) ) | \
(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
@@ -122,7 +122,7 @@ extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config
static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
struct i2c_adapter *i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_DRX397XD */
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index fed09dfb2b7..db8a937cc63 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -75,9 +75,10 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- if (fe->ops->tuner_ops->set_params) {
- fe->ops->tuner_ops->set_params(fe, p);
- if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
}
return 0;
@@ -131,7 +132,7 @@ error:
static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
-struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
+struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
{
struct dvb_dummy_fe_state* state = NULL;
@@ -151,7 +152,7 @@ error:
static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
-struct dvb_frontend* dvb_dummy_fe_qam_attach()
+struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
{
struct dvb_dummy_fe_state* state = NULL;
diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb/frontends/eds1547.h
new file mode 100644
index 00000000000..fa79b7c83dd
--- /dev/null
+++ b/drivers/media/dvb/frontends/eds1547.h
@@ -0,0 +1,133 @@
+/* eds1547.h Earda EDS-1547 tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+* 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, version 2.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef EDS1547
+#define EDS1547
+
+static u8 stv0288_earda_inittab[] = {
+ 0x01, 0x57,
+ 0x02, 0x20,
+ 0x03, 0x8e,
+ 0x04, 0x8e,
+ 0x05, 0x12,
+ 0x06, 0x00,
+ 0x07, 0x00,
+ 0x09, 0x00,
+ 0x0a, 0x04,
+ 0x0b, 0x00,
+ 0x0c, 0x00,
+ 0x0d, 0x00,
+ 0x0e, 0xd4,
+ 0x0f, 0x30,
+ 0x11, 0x44,
+ 0x12, 0x03,
+ 0x13, 0x48,
+ 0x14, 0x84,
+ 0x15, 0x45,
+ 0x16, 0xb7,
+ 0x17, 0x9c,
+ 0x18, 0x00,
+ 0x19, 0xa6,
+ 0x1a, 0x88,
+ 0x1b, 0x8f,
+ 0x1c, 0xf0,
+ 0x20, 0x0b,
+ 0x21, 0x54,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x2b, 0xff,
+ 0x2c, 0xf7,
+ 0x30, 0x00,
+ 0x31, 0x1e,
+ 0x32, 0x14,
+ 0x33, 0x0f,
+ 0x34, 0x09,
+ 0x35, 0x0c,
+ 0x36, 0x05,
+ 0x37, 0x2f,
+ 0x38, 0x16,
+ 0x39, 0xbd,
+ 0x3a, 0x00,
+ 0x3b, 0x13,
+ 0x3c, 0x11,
+ 0x3d, 0x30,
+ 0x40, 0x63,
+ 0x41, 0x04,
+ 0x42, 0x60,
+ 0x43, 0x00,
+ 0x44, 0x00,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x47, 0x00,
+ 0x4a, 0x00,
+ 0x50, 0x10,
+ 0x51, 0x36,
+ 0x52, 0x09,
+ 0x53, 0x94,
+ 0x54, 0x62,
+ 0x55, 0x29,
+ 0x56, 0x64,
+ 0x57, 0x2b,
+ 0x58, 0x54,
+ 0x59, 0x86,
+ 0x5a, 0x00,
+ 0x5b, 0x9b,
+ 0x5c, 0x08,
+ 0x5d, 0x7f,
+ 0x5e, 0x00,
+ 0x5f, 0xff,
+ 0x70, 0x00,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x74, 0x00,
+ 0x75, 0x00,
+ 0x76, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x3f,
+ 0x83, 0x3f,
+ 0x84, 0x00,
+ 0x85, 0x00,
+ 0x88, 0x00,
+ 0x89, 0x00,
+ 0x8a, 0x00,
+ 0x8b, 0x00,
+ 0x8c, 0x00,
+ 0x90, 0x00,
+ 0x91, 0x00,
+ 0x92, 0x00,
+ 0x93, 0x00,
+ 0x94, 0x1c,
+ 0x97, 0x00,
+ 0xa0, 0x48,
+ 0xa1, 0x00,
+ 0xb0, 0xb8,
+ 0xb1, 0x3a,
+ 0xb2, 0x10,
+ 0xb3, 0x82,
+ 0xb4, 0x80,
+ 0xb5, 0x82,
+ 0xb6, 0x82,
+ 0xb7, 0x82,
+ 0xb8, 0x20,
+ 0xb9, 0x00,
+ 0xf0, 0x00,
+ 0xf1, 0x00,
+ 0xf2, 0xc0,
+ 0xff,0xff,
+};
+
+static struct stv0288_config earda_config = {
+ .demod_address = 0x68,
+ .min_delay_ms = 100,
+ .inittab = stv0288_earda_inittab,
+};
+
+#endif
diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c
new file mode 100644
index 00000000000..855852fddf2
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgs8gl5.c
@@ -0,0 +1,454 @@
+/*
+ Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+ Copyright (C) 2008 Sirius International (Hong Kong) Limited
+ Timothy Lee <timothy.lee@siriushk.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "dvb_frontend.h"
+#include "lgs8gl5.h"
+
+
+#define REG_RESET 0x02
+#define REG_RESET_OFF 0x01
+#define REG_03 0x03
+#define REG_04 0x04
+#define REG_07 0x07
+#define REG_09 0x09
+#define REG_0A 0x0a
+#define REG_0B 0x0b
+#define REG_0C 0x0c
+#define REG_37 0x37
+#define REG_STRENGTH 0x4b
+#define REG_STRENGTH_MASK 0x7f
+#define REG_STRENGTH_CARRIER 0x80
+#define REG_INVERSION 0x7c
+#define REG_INVERSION_ON 0x80
+#define REG_7D 0x7d
+#define REG_7E 0x7e
+#define REG_A2 0xa2
+#define REG_STATUS 0xa4
+#define REG_STATUS_SYNC 0x04
+#define REG_STATUS_LOCK 0x01
+
+
+struct lgs8gl5_state {
+ struct i2c_adapter *i2c;
+ const struct lgs8gl5_config *config;
+ struct dvb_frontend frontend;
+};
+
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "lgs8gl5: " args); \
+ } while (0)
+
+
+/* Writes into demod's register */
+static int
+lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+ int ret;
+ u8 buf[] = {reg, data};
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2
+ };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1)
+ dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n",
+ __func__, reg, data, ret);
+ return (ret != 1) ? -1 : 0;
+}
+
+
+/* Reads from demod's register */
+static int
+lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg)
+{
+ int ret;
+ u8 b0[] = {reg};
+ u8 b1[] = {0};
+ struct i2c_msg msg[2] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 1
+ },
+ {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = b1,
+ .len = 1
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2)
+ return -EIO;
+
+ return b1[0];
+}
+
+
+static int
+lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+ lgs8gl5_read_reg(state, reg);
+ lgs8gl5_write_reg(state, reg, data);
+ return 0;
+}
+
+
+/* Writes into alternate device's register */
+/* TODO: Find out what that device is for! */
+static int
+lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+ int ret;
+ u8 b0[] = {reg};
+ u8 b1[] = {0};
+ u8 b2[] = {reg, data};
+ struct i2c_msg msg[3] = {
+ {
+ .addr = state->config->demod_address + 2,
+ .flags = 0,
+ .buf = b0,
+ .len = 1
+ },
+ {
+ .addr = state->config->demod_address + 2,
+ .flags = I2C_M_RD,
+ .buf = b1,
+ .len = 1
+ },
+ {
+ .addr = state->config->demod_address + 2,
+ .flags = 0,
+ .buf = b2,
+ .len = 2
+ },
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 3);
+ return (ret != 3) ? -1 : 0;
+}
+
+
+static void
+lgs8gl5_soft_reset(struct lgs8gl5_state *state)
+{
+ u8 val;
+
+ dprintk("%s\n", __func__);
+
+ val = lgs8gl5_read_reg(state, REG_RESET);
+ lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF);
+ lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF);
+ msleep(5);
+}
+
+
+/* Starts demodulation */
+static void
+lgs8gl5_start_demod(struct lgs8gl5_state *state)
+{
+ u8 val;
+ int n;
+
+ dprintk("%s\n", __func__);
+
+ lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+ lgs8gl5_soft_reset(state);
+ lgs8gl5_update_reg(state, REG_07, 0x10);
+ lgs8gl5_update_reg(state, REG_07, 0x10);
+ lgs8gl5_write_reg(state, REG_09, 0x0e);
+ lgs8gl5_write_reg(state, REG_0A, 0xe5);
+ lgs8gl5_write_reg(state, REG_0B, 0x35);
+ lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+ lgs8gl5_update_reg(state, REG_03, 0x00);
+ lgs8gl5_update_reg(state, REG_7E, 0x01);
+ lgs8gl5_update_alt_reg(state, 0xc5, 0x00);
+ lgs8gl5_update_reg(state, REG_04, 0x02);
+ lgs8gl5_update_reg(state, REG_37, 0x01);
+ lgs8gl5_soft_reset(state);
+
+ /* Wait for carrier */
+ for (n = 0; n < 10; n++) {
+ val = lgs8gl5_read_reg(state, REG_STRENGTH);
+ dprintk("Wait for carrier[%d] 0x%02X\n", n, val);
+ if (val & REG_STRENGTH_CARRIER)
+ break;
+ msleep(4);
+ }
+ if (!(val & REG_STRENGTH_CARRIER))
+ return;
+
+ /* Wait for lock */
+ for (n = 0; n < 20; n++) {
+ val = lgs8gl5_read_reg(state, REG_STATUS);
+ dprintk("Wait for lock[%d] 0x%02X\n", n, val);
+ if (val & REG_STATUS_LOCK)
+ break;
+ msleep(12);
+ }
+ if (!(val & REG_STATUS_LOCK))
+ return;
+
+ lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2));
+ lgs8gl5_soft_reset(state);
+}
+
+
+static int
+lgs8gl5_init(struct dvb_frontend *fe)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+ lgs8gl5_soft_reset(state);
+ lgs8gl5_update_reg(state, REG_07, 0x10);
+ lgs8gl5_update_reg(state, REG_07, 0x10);
+ lgs8gl5_write_reg(state, REG_09, 0x0e);
+ lgs8gl5_write_reg(state, REG_0A, 0xe5);
+ lgs8gl5_write_reg(state, REG_0B, 0x35);
+ lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+ u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+ u8 flags = lgs8gl5_read_reg(state, REG_STATUS);
+
+ *status = 0;
+
+ if ((level & REG_STRENGTH_MASK) > 0)
+ *status |= FE_HAS_SIGNAL;
+ if (level & REG_STRENGTH_CARRIER)
+ *status |= FE_HAS_CARRIER;
+ if (flags & REG_STATUS_SYNC)
+ *status |= FE_HAS_SYNC;
+ if (flags & REG_STATUS_LOCK)
+ *status |= FE_HAS_LOCK;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ *ber = 0;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+ u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+ *signal_strength = (level & REG_STRENGTH_MASK) << 8;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+ u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+ *snr = (level & REG_STRENGTH_MASK) << 8;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ *ucblocks = 0;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ)
+ return -EINVAL;
+
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ /* lgs8gl5_set_inversion(state, p->inversion); */
+
+ lgs8gl5_start_demod(state);
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+ u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
+ struct dvb_ofdm_parameters *o = &p->u.ofdm;
+
+ p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
+
+ o->code_rate_HP = FEC_1_2;
+ o->code_rate_LP = FEC_7_8;
+ o->guard_interval = GUARD_INTERVAL_1_32;
+ o->transmission_mode = TRANSMISSION_MODE_2K;
+ o->constellation = QAM_64;
+ o->hierarchy_information = HIERARCHY_NONE;
+ o->bandwidth = BANDWIDTH_8_MHZ;
+
+ return 0;
+}
+
+
+static int
+lgs8gl5_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *fesettings)
+{
+ fesettings->min_delay_ms = 240;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
+
+static void
+lgs8gl5_release(struct dvb_frontend *fe)
+{
+ struct lgs8gl5_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+
+static struct dvb_frontend_ops lgs8gl5_ops;
+
+
+struct dvb_frontend*
+lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c)
+{
+ struct lgs8gl5_state *state = NULL;
+
+ dprintk("%s\n", __func__);
+
+ /* Allocate memory for the internal state */
+ state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* Setup the state */
+ state->config = config;
+ state->i2c = i2c;
+
+ /* Check if the demod is there */
+ if (lgs8gl5_read_reg(state, REG_RESET) < 0)
+ goto error;
+
+ /* Create dvb_frontend */
+ memcpy(&state->frontend.ops, &lgs8gl5_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(lgs8gl5_attach);
+
+
+static struct dvb_frontend_ops lgs8gl5_ops = {
+ .info = {
+ .name = "Legend Silicon LGS-8GL5 DMB-TH",
+ .type = FE_OFDM,
+ .frequency_min = 474000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 10000,
+ .frequency_tolerance = 0,
+ .caps = FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
+ FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_BANDWIDTH_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_RECOVER
+ },
+
+ .release = lgs8gl5_release,
+
+ .init = lgs8gl5_init,
+
+ .set_frontend = lgs8gl5_set_frontend,
+ .get_frontend = lgs8gl5_get_frontend,
+ .get_tune_settings = lgs8gl5_get_tune_settings,
+
+ .read_status = lgs8gl5_read_status,
+ .read_ber = lgs8gl5_read_ber,
+ .read_signal_strength = lgs8gl5_read_signal_strength,
+ .read_snr = lgs8gl5_read_snr,
+ .read_ucblocks = lgs8gl5_read_ucblocks,
+};
+
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver");
+MODULE_AUTHOR("Timothy Lee");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb/frontends/lgs8gl5.h
new file mode 100644
index 00000000000..d14176787a7
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgs8gl5.h
@@ -0,0 +1,45 @@
+/*
+ Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+ Copyright (C) 2008 Sirius International (Hong Kong) Limited
+ Timothy Lee <timothy.lee@siriushk.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LGS8GL5_H
+#define LGS8GL5_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgs8gl5_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_LGS8GL5) || \
+ (defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
+extern struct dvb_frontend *lgs8gl5_attach(
+ const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lgs8gl5_attach(
+ const struct lgs8gl5_config *config, struct i2c_adapter *i2c) {
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_LGS8GL5 */
+
+#endif /* LGS8GL5_H */
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index af298358e82..a8429ebfa8a 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -80,7 +80,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
return 0;
}
-static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
+static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
{
int err;
struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
@@ -111,7 +111,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
return 0;
}
-static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len)
+static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)
{
u8 reg2 [] = { reg };
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 6afe12aaca4..16cf2fdd5d7 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -88,7 +88,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
return 0;
}
-static u8 i2c_readbytes (struct or51211_state* state, u8 reg, u8* buf, int len)
+static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
{
int err;
struct i2c_msg msg;
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 5ddb2dca305..cf4d8936bb8 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -1,7 +1,7 @@
/*
Samsung S5H1409 VSB/QAM demodulator driver
- Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2006 Steven Toth <stoth@linuxtv.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
@@ -30,10 +30,10 @@
struct s5h1409_state {
- struct i2c_adapter* i2c;
+ struct i2c_adapter *i2c;
/* configuration settings */
- const struct s5h1409_config* config;
+ const struct s5h1409_config *config;
struct dvb_frontend frontend;
@@ -48,6 +48,9 @@ struct s5h1409_state {
};
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
#define dprintk if (debug) printk
/* Register values to initialise the demod, this will set VSB by default */
@@ -299,10 +302,10 @@ static struct qam256_snr_tab {
};
/* 8 bit registers, 16 bit values */
-static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+static int s5h1409_writereg(struct s5h1409_state *state, u8 reg, u16 data)
{
int ret;
- u8 buf [] = { reg, data >> 8, data & 0xff };
+ u8 buf[] = { reg, data >> 8, data & 0xff };
struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 3 };
@@ -310,19 +313,19 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+ printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
"ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
-static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+static u16 s5h1409_readreg(struct s5h1409_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0, 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0, 0 };
- struct i2c_msg msg [] = {
+ struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0,
.buf = b0, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
@@ -335,9 +338,9 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
return (b1[0] << 8) | b1[1];
}
-static int s5h1409_softreset(struct dvb_frontend* fe)
+static int s5h1409_softreset(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
@@ -349,11 +352,11 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
}
#define S5H1409_VSB_IF_FREQ 5380
-#define S5H1409_QAM_IF_FREQ state->config->qam_if
+#define S5H1409_QAM_IF_FREQ (state->config->qam_if)
-static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+static int s5h1409_set_if_freq(struct dvb_frontend *fe, int KHz)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d KHz)\n", __func__, KHz);
@@ -376,26 +379,26 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
return 0;
}
-static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, inverted);
- if(inverted == 1)
+ if (inverted == 1)
return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
else
return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
}
-static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+static int s5h1409_enable_modulation(struct dvb_frontend *fe,
fe_modulation_t m)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(0x%08x)\n", __func__, m);
- switch(m) {
+ switch (m) {
case VSB_8:
dprintk("%s() VSB_8\n", __func__);
if (state->if_freq != S5H1409_VSB_IF_FREQ)
@@ -404,6 +407,7 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
break;
case QAM_64:
case QAM_256:
+ case QAM_AUTO:
dprintk("%s() QAM_AUTO (64/256)\n", __func__);
if (state->if_freq != S5H1409_QAM_IF_FREQ)
s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
@@ -421,9 +425,9 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
return 0;
}
-static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int s5h1409_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
@@ -433,9 +437,9 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
return s5h1409_writereg(state, 0xf3, 0);
}
-static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+static int s5h1409_set_gpio(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
@@ -447,18 +451,18 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
s5h1409_readreg(state, 0xe3) & 0xfeff);
}
-static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+static int s5h1409_sleep(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
return s5h1409_writereg(state, 0xf2, enable);
}
-static int s5h1409_register_reset(struct dvb_frontend* fe)
+static int s5h1409_register_reset(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
@@ -482,7 +486,7 @@ static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
reg &= 0xff;
s5h1409_writereg(state, 0x96, 0x00c);
- if ((reg < 0x38) || (reg > 0x68) ) {
+ if ((reg < 0x38) || (reg > 0x68)) {
s5h1409_writereg(state, 0x93, 0x3332);
s5h1409_writereg(state, 0x9e, 0x2c37);
} else {
@@ -513,7 +517,7 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
s5h1409_writereg(state, 0x96, 0x20);
s5h1409_writereg(state, 0xad,
- ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
+ (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) & 0xeffe);
}
@@ -528,10 +532,10 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend (struct dvb_frontend* fe,
+static int s5h1409_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -545,9 +549,11 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
msleep(100);
if (fe->ops.tuner_ops.set_params) {
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
}
/* Optimize the demod for QAM */
@@ -591,17 +597,17 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
-static int s5h1409_init (struct dvb_frontend* fe)
+static int s5h1409_init(struct dvb_frontend *fe)
{
int i;
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
s5h1409_sleep(fe, 0);
s5h1409_register_reset(fe);
- for (i=0; i < ARRAY_SIZE(init_tab); i++)
+ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
/* The datasheet says that after initialisation, VSB is default */
@@ -626,9 +632,9 @@ static int s5h1409_init (struct dvb_frontend* fe)
return 0;
}
-static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
u16 reg;
u32 tuner_status = 0;
@@ -636,12 +642,12 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Get the demodulator status */
reg = s5h1409_readreg(state, 0xf1);
- if(reg & 0x1000)
+ if (reg & 0x1000)
*status |= FE_HAS_VITERBI;
- if(reg & 0x8000)
+ if (reg & 0x8000)
*status |= FE_HAS_LOCK | FE_HAS_SYNC;
- switch(state->config->status_mode) {
+ switch (state->config->status_mode) {
case S5H1409_DEMODLOCKING:
if (*status & FE_HAS_VITERBI)
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
@@ -667,12 +673,12 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
if (v < qam256_snr_tab[i].val) {
*snr = qam256_snr_tab[i].data;
ret = 0;
@@ -682,12 +688,12 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
if (v < qam64_snr_tab[i].val) {
*snr = qam64_snr_tab[i].data;
ret = 0;
@@ -697,12 +703,12 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
if (v > vsb_snr_tab[i].val) {
*snr = vsb_snr_tab[i].data;
ret = 0;
@@ -713,13 +719,13 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
u16 reg;
dprintk("%s()\n", __func__);
- switch(state->current_modulation) {
+ switch (state->current_modulation) {
case QAM_64:
reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam64_lookup_snr(fe, snr, reg);
@@ -736,30 +742,30 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
return -EINVAL;
}
-static int s5h1409_read_signal_strength(struct dvb_frontend* fe,
- u16* signal_strength)
+static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
{
return s5h1409_read_snr(fe, signal_strength);
}
-static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
*ucblocks = s5h1409_readreg(state, 0xb5);
return 0;
}
-static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber)
+static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
{
return s5h1409_read_ucblocks(fe, ber);
}
-static int s5h1409_get_frontend(struct dvb_frontend* fe,
+static int s5h1409_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
p->frequency = state->current_frequency;
p->u.vsb.modulation = state->current_modulation;
@@ -767,25 +773,25 @@ static int s5h1409_get_frontend(struct dvb_frontend* fe,
return 0;
}
-static int s5h1409_get_tune_settings(struct dvb_frontend* fe,
+static int s5h1409_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
return 0;
}
-static void s5h1409_release(struct dvb_frontend* fe)
+static void s5h1409_release(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops s5h1409_ops;
-struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+ struct i2c_adapter *i2c)
{
- struct s5h1409_state* state = NULL;
+ struct s5h1409_state *state = NULL;
u16 reg;
/* allocate memory for the internal state */
@@ -824,6 +830,7 @@ error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(s5h1409_attach);
static struct dvb_frontend_ops s5h1409_ops = {
@@ -849,14 +856,10 @@ static struct dvb_frontend_ops s5h1409_ops = {
.release = s5h1409_release,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(s5h1409_attach);
/*
* Local variables:
diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
index 59f4335964c..070d9743e33 100644
--- a/drivers/media/dvb/frontends/s5h1409.h
+++ b/drivers/media/dvb/frontends/s5h1409.h
@@ -1,7 +1,7 @@
/*
Samsung S5H1409 VSB/QAM demodulator driver
- Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2006 Steven Toth <stoth@linuxtv.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
@@ -24,8 +24,7 @@
#include <linux/dvb/frontend.h>
-struct s5h1409_config
-{
+struct s5h1409_config {
/* the demodulator's i2c address */
u8 demod_address;
@@ -60,12 +59,14 @@ struct s5h1409_config
u16 mpeg_timing;
};
-#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
+ && defined(MODULE))
+extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1409_attach(
+ const struct s5h1409_config *config,
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index cff360ce1ba..2febfb5a846 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -1,7 +1,7 @@
/*
Samsung S5H1411 VSB/QAM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
@@ -343,7 +343,7 @@ static int s5h1411_writereg(struct s5h1411_state *state,
u8 addr, u8 reg, u16 data)
{
int ret;
- u8 buf [] = { reg, data >> 8, data & 0xff };
+ u8 buf[] = { reg, data >> 8, data & 0xff };
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
@@ -359,10 +359,10 @@ static int s5h1411_writereg(struct s5h1411_state *state,
static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0, 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0, 0 };
- struct i2c_msg msg [] = {
+ struct i2c_msg msg[] = {
{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
@@ -488,6 +488,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
break;
case QAM_64:
case QAM_256:
+ case QAM_AUTO:
dprintk("%s() QAM_AUTO (64/256)\n", __func__);
s5h1411_set_if_freq(fe, state->config->qam_if);
s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
index 1855f64ed4d..7d542bc00c4 100644
--- a/drivers/media/dvb/frontends/s5h1411.h
+++ b/drivers/media/dvb/frontends/s5h1411.h
@@ -1,7 +1,7 @@
/*
Samsung S5H1411 VSB/QAM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 720ed9ff7c5..2e9fd2893ed 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -59,7 +59,7 @@ struct s5h1420_state {
* it does not support repeated-start, workaround: write addr-1
* and then read
*/
- u8 shadow[255];
+ u8 shadow[256];
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
@@ -94,8 +94,11 @@ static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
if (ret != 3)
return ret;
} else {
- ret = i2c_transfer(state->i2c, &msg[1], 2);
- if (ret != 2)
+ ret = i2c_transfer(state->i2c, &msg[1], 1);
+ if (ret != 1)
+ return ret;
+ ret = i2c_transfer(state->i2c, &msg[2], 1);
+ if (ret != 1)
return ret;
}
@@ -823,7 +826,7 @@ static int s5h1420_init (struct dvb_frontend* fe)
struct s5h1420_state* state = fe->demodulator_priv;
/* disable power down and do reset */
- state->CON_1_val = 0x10;
+ state->CON_1_val = state->config->serial_mpeg << 4;
s5h1420_writereg(state, 0x02, state->CON_1_val);
msleep(10);
s5h1420_reset(state);
@@ -915,7 +918,8 @@ struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
state->frontend.demodulator_priv = state;
/* create tuner i2c adapter */
- strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
+ strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
+ sizeof(state->tuner_i2c_adapter.name));
state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL,
state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo;
state->tuner_i2c_adapter.algo_data = NULL;
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index 4c913f142bc..ff308136d86 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -32,10 +32,12 @@ struct s5h1420_config
u8 demod_address;
/* does the inversion require inversion? */
- u8 invert : 1;
+ u8 invert:1;
- u8 repeated_start_workaround : 1;
- u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
+ u8 repeated_start_workaround:1;
+ u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */
+
+ u8 serial_mpeg:1;
};
#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c
new file mode 100644
index 00000000000..3ddbe69c45c
--- /dev/null
+++ b/drivers/media/dvb/frontends/si21xx.c
@@ -0,0 +1,974 @@
+/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+*/
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "si21xx.h"
+
+#define REVISION_REG 0x00
+#define SYSTEM_MODE_REG 0x01
+#define TS_CTRL_REG_1 0x02
+#define TS_CTRL_REG_2 0x03
+#define PIN_CTRL_REG_1 0x04
+#define PIN_CTRL_REG_2 0x05
+#define LOCK_STATUS_REG_1 0x0f
+#define LOCK_STATUS_REG_2 0x10
+#define ACQ_STATUS_REG 0x11
+#define ACQ_CTRL_REG_1 0x13
+#define ACQ_CTRL_REG_2 0x14
+#define PLL_DIVISOR_REG 0x15
+#define COARSE_TUNE_REG 0x16
+#define FINE_TUNE_REG_L 0x17
+#define FINE_TUNE_REG_H 0x18
+
+#define ANALOG_AGC_POWER_LEVEL_REG 0x28
+#define CFO_ESTIMATOR_CTRL_REG_1 0x29
+#define CFO_ESTIMATOR_CTRL_REG_2 0x2a
+#define CFO_ESTIMATOR_CTRL_REG_3 0x2b
+
+#define SYM_RATE_ESTIMATE_REG_L 0x31
+#define SYM_RATE_ESTIMATE_REG_M 0x32
+#define SYM_RATE_ESTIMATE_REG_H 0x33
+
+#define CFO_ESTIMATOR_OFFSET_REG_L 0x36
+#define CFO_ESTIMATOR_OFFSET_REG_H 0x37
+#define CFO_ERROR_REG_L 0x38
+#define CFO_ERROR_REG_H 0x39
+#define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a
+
+#define SYM_RATE_REG_L 0x3f
+#define SYM_RATE_REG_M 0x40
+#define SYM_RATE_REG_H 0x41
+#define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42
+#define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43
+
+#define C_N_ESTIMATOR_CTRL_REG 0x7c
+#define C_N_ESTIMATOR_THRSHLD_REG 0x7d
+#define C_N_ESTIMATOR_LEVEL_REG_L 0x7e
+#define C_N_ESTIMATOR_LEVEL_REG_H 0x7f
+
+#define BLIND_SCAN_CTRL_REG 0x80
+
+#define LSA_CTRL_REG_1 0x8D
+#define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f
+#define ONE_DB_BNDWDTH_THRSHLD_REG 0x90
+#define TWO_DB_BNDWDTH_THRSHLD_REG 0x91
+#define THREE_DB_BNDWDTH_THRSHLD_REG 0x92
+#define INBAND_POWER_THRSHLD_REG 0x93
+#define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94
+
+#define VIT_SRCH_CTRL_REG_1 0xa0
+#define VIT_SRCH_CTRL_REG_2 0xa1
+#define VIT_SRCH_CTRL_REG_3 0xa2
+#define VIT_SRCH_STATUS_REG 0xa3
+#define VITERBI_BER_COUNT_REG_L 0xab
+#define REED_SOLOMON_CTRL_REG 0xb0
+#define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1
+#define PRBS_CTRL_REG 0xb5
+
+#define LNB_CTRL_REG_1 0xc0
+#define LNB_CTRL_REG_2 0xc1
+#define LNB_CTRL_REG_3 0xc2
+#define LNB_CTRL_REG_4 0xc3
+#define LNB_CTRL_STATUS_REG 0xc4
+#define LNB_FIFO_REGS_0 0xc5
+#define LNB_FIFO_REGS_1 0xc6
+#define LNB_FIFO_REGS_2 0xc7
+#define LNB_FIFO_REGS_3 0xc8
+#define LNB_FIFO_REGS_4 0xc9
+#define LNB_FIFO_REGS_5 0xca
+#define LNB_SUPPLY_CTRL_REG_1 0xcb
+#define LNB_SUPPLY_CTRL_REG_2 0xcc
+#define LNB_SUPPLY_CTRL_REG_3 0xcd
+#define LNB_SUPPLY_CTRL_REG_4 0xce
+#define LNB_SUPPLY_STATUS_REG 0xcf
+
+#define FALSE 0
+#define TRUE 1
+#define FAIL -1
+#define PASS 0
+
+#define ALLOWABLE_FS_COUNT 10
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "si21xx: " args); \
+ } while (0)
+
+enum {
+ ACTIVE_HIGH,
+ ACTIVE_LOW
+};
+enum {
+ BYTE_WIDE,
+ BIT_WIDE
+};
+enum {
+ CLK_GAPPED_MODE,
+ CLK_CONTINUOUS_MODE
+};
+enum {
+ RISING_EDGE,
+ FALLING_EDGE
+};
+enum {
+ MSB_FIRST,
+ LSB_FIRST
+};
+enum {
+ SERIAL,
+ PARALLEL
+};
+
+struct si21xx_state {
+ struct i2c_adapter *i2c;
+ const struct si21xx_config *config;
+ struct dvb_frontend frontend;
+ u8 initialised:1;
+ int errmode;
+ int fs; /*Sampling rate of the ADC in MHz*/
+};
+
+/* register default initialization */
+static u8 serit_sp1511lhb_inittab[] = {
+ 0x01, 0x28, /* set i2c_inc_disable */
+ 0x20, 0x03,
+ 0x27, 0x20,
+ 0xe0, 0x45,
+ 0xe1, 0x08,
+ 0xfe, 0x01,
+ 0x01, 0x28,
+ 0x89, 0x09,
+ 0x04, 0x80,
+ 0x05, 0x01,
+ 0x06, 0x00,
+ 0x20, 0x03,
+ 0x24, 0x88,
+ 0x29, 0x09,
+ 0x2a, 0x0f,
+ 0x2c, 0x10,
+ 0x2d, 0x19,
+ 0x2e, 0x08,
+ 0x2f, 0x10,
+ 0x30, 0x19,
+ 0x34, 0x20,
+ 0x35, 0x03,
+ 0x45, 0x02,
+ 0x46, 0x45,
+ 0x47, 0xd0,
+ 0x48, 0x00,
+ 0x49, 0x40,
+ 0x4a, 0x03,
+ 0x4c, 0xfd,
+ 0x4f, 0x2e,
+ 0x50, 0x2e,
+ 0x51, 0x10,
+ 0x52, 0x10,
+ 0x56, 0x92,
+ 0x59, 0x00,
+ 0x5a, 0x2d,
+ 0x5b, 0x33,
+ 0x5c, 0x1f,
+ 0x5f, 0x76,
+ 0x62, 0xc0,
+ 0x63, 0xc0,
+ 0x64, 0xf3,
+ 0x65, 0xf3,
+ 0x79, 0x40,
+ 0x6a, 0x40,
+ 0x6b, 0x0a,
+ 0x6c, 0x80,
+ 0x6d, 0x27,
+ 0x71, 0x06,
+ 0x75, 0x60,
+ 0x78, 0x00,
+ 0x79, 0xb5,
+ 0x7c, 0x05,
+ 0x7d, 0x1a,
+ 0x87, 0x55,
+ 0x88, 0x72,
+ 0x8f, 0x08,
+ 0x90, 0xe0,
+ 0x94, 0x40,
+ 0xa0, 0x3f,
+ 0xa1, 0xc0,
+ 0xa4, 0xcc,
+ 0xa5, 0x66,
+ 0xa6, 0x66,
+ 0xa7, 0x7b,
+ 0xa8, 0x7b,
+ 0xa9, 0x7b,
+ 0xaa, 0x9a,
+ 0xed, 0x04,
+ 0xad, 0x00,
+ 0xae, 0x03,
+ 0xcc, 0xab,
+ 0x01, 0x08,
+ 0xff, 0xff
+};
+
+/* low level read/writes */
+static int si21_writeregs(struct si21xx_state *state, u8 reg1,
+ u8 *data, int len)
+{
+ int ret;
+ u8 buf[60];/* = { reg1, data };*/
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = len + 1
+ };
+
+ msg.buf[0] = reg1;
+ memcpy(msg.buf + 1, data, len);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
+ "ret == %i)\n", __func__, reg1, data[0], ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
+{
+ int ret;
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2
+ };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
+ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_write(struct dvb_frontend *fe, u8 *buf, int len)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ if (len != 2)
+ return -EINVAL;
+
+ return si21_writereg(state, buf[0], buf[1]);
+}
+
+static u8 si21_readreg(struct si21xx_state *state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 1
+ }, {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = b1,
+ .len = 1
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+ __func__, reg, ret);
+
+ return b1[0];
+}
+
+static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
+{
+ int ret;
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = &reg1,
+ .len = 1
+ }, {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = b,
+ .len = len
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+ return ret == 2 ? 0 : -1;
+}
+
+static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
+{
+ unsigned long start = jiffies;
+
+ dprintk("%s\n", __func__);
+
+ while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
+ if (jiffies - start > timeout) {
+ dprintk("%s: timeout!!\n", __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(10);
+ };
+
+ return 0;
+}
+
+static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u32 sym_rate, data_rate;
+ int i;
+ u8 sym_rate_bytes[3];
+
+ dprintk("%s : srate = %i\n", __func__ , srate);
+
+ if ((srate < 1000000) || (srate > 45000000))
+ return -EINVAL;
+
+ data_rate = srate;
+ sym_rate = 0;
+
+ for (i = 0; i < 4; ++i) {
+ sym_rate /= 100;
+ sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
+ state->fs;
+ data_rate /= 100;
+ }
+ for (i = 0; i < 3; ++i)
+ sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
+
+ si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
+
+ return 0;
+}
+
+static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *m)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 lnb_status;
+ u8 LNB_CTRL_1;
+ int status;
+
+ dprintk("%s\n", __func__);
+
+ status = PASS;
+ LNB_CTRL_1 = 0;
+
+ status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
+ status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
+
+ /*fill the FIFO*/
+ status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
+
+ LNB_CTRL_1 = (lnb_status & 0x70);
+ LNB_CTRL_1 |= m->msg_len;
+
+ LNB_CTRL_1 |= 0x80; /* begin LNB signaling */
+
+ status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
+
+ return status;
+}
+
+static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 val;
+
+ dprintk("%s\n", __func__);
+
+ if (si21xx_wait_diseqc_idle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ val = (0x80 | si21_readreg(state, 0xc1));
+ if (si21_writereg(state, LNB_CTRL_REG_1,
+ burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
+ return -EREMOTEIO;
+
+ if (si21xx_wait_diseqc_idle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ if (si21_writereg(state, LNB_CTRL_REG_1, val))
+ return -EREMOTEIO;
+
+ return 0;
+}
+/* 30.06.2008 */
+static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 val;
+
+ dprintk("%s\n", __func__);
+ val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
+
+ case SEC_TONE_OFF:
+ return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ u8 val;
+ dprintk("%s: %s\n", __func__,
+ volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+
+ val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+ switch (volt) {
+ case SEC_VOLTAGE_18:
+ return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
+ break;
+ case SEC_VOLTAGE_13:
+ return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
+ break;
+ default:
+ return -EINVAL;
+ };
+}
+
+static int si21xx_init(struct dvb_frontend *fe)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ int i;
+ int status = 0;
+ u8 reg1;
+ u8 val;
+ u8 reg2[2];
+
+ dprintk("%s\n", __func__);
+
+ for (i = 0; ; i += 2) {
+ reg1 = serit_sp1511lhb_inittab[i];
+ val = serit_sp1511lhb_inittab[i+1];
+ if (reg1 == 0xff && val == 0xff)
+ break;
+ si21_writeregs(state, reg1, &val, 1);
+ }
+
+ /*DVB QPSK SYSTEM MODE REG*/
+ reg1 = 0x08;
+ si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
+
+ /*transport stream config*/
+ /*
+ mode = PARALLEL;
+ sdata_form = LSB_FIRST;
+ clk_edge = FALLING_EDGE;
+ clk_mode = CLK_GAPPED_MODE;
+ strt_len = BYTE_WIDE;
+ sync_pol = ACTIVE_HIGH;
+ val_pol = ACTIVE_HIGH;
+ err_pol = ACTIVE_HIGH;
+ sclk_rate = 0x00;
+ parity = 0x00 ;
+ data_delay = 0x00;
+ clk_delay = 0x00;
+ pclk_smooth = 0x00;
+ */
+ reg2[0] =
+ PARALLEL + (LSB_FIRST << 1)
+ + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
+ + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
+ + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
+
+ reg2[1] = 0;
+ /* sclk_rate + (parity << 2)
+ + (data_delay << 3) + (clk_delay << 4)
+ + (pclk_smooth << 5);
+ */
+ status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
+ if (status != 0)
+ dprintk(" %s : TS Set Error\n", __func__);
+
+ return 0;
+
+}
+
+static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 regs_read[2];
+ u8 reg_read;
+ u8 i;
+ u8 lock;
+ u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
+
+ si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
+ reg_read = 0;
+
+ for (i = 0; i < 7; ++i)
+ reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
+
+ lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
+
+ dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
+ *status = 0;
+
+ if (signal > 10)
+ *status |= FE_HAS_SIGNAL;
+
+ if (lock & 0x2)
+ *status |= FE_HAS_CARRIER;
+
+ if (lock & 0x20)
+ *status |= FE_HAS_VITERBI;
+
+ if (lock & 0x40)
+ *status |= FE_HAS_SYNC;
+
+ if ((lock & 0x7b) == 0x7b)
+ *status |= FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
+ (u8*)agclevel, 0x01);*/
+
+ u16 signal = (3 * si21_readreg(state, 0x27) *
+ si21_readreg(state, 0x28));
+
+ dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
+ si21_readreg(state, 0x27),
+ si21_readreg(state, 0x28), (int) signal);
+
+ signal <<= 4;
+ *strength = signal;
+
+ return 0;
+}
+
+static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ if (state->errmode != STATUS_BER)
+ return 0;
+
+ *ber = (si21_readreg(state, 0x1d) << 8) |
+ si21_readreg(state, 0x1e);
+
+ return 0;
+}
+
+static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
+ si21_readreg(state, 0x25));
+ xsnr = 3 * (xsnr - 0xa100);
+ *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+
+ dprintk("%s\n", __func__);
+
+ return 0;
+}
+
+static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ if (state->errmode != STATUS_UCBLOCKS)
+ *ucblocks = 0;
+ else
+ *ucblocks = (si21_readreg(state, 0x1d) << 8) |
+ si21_readreg(state, 0x1e);
+
+ return 0;
+}
+
+/* initiates a channel acquisition sequence
+ using the specified symbol rate and code rate */
+static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
+ fe_code_rate_t crate)
+{
+
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 coderates[] = {
+ 0x0, 0x01, 0x02, 0x04, 0x00,
+ 0x8, 0x10, 0x20, 0x00, 0x3f
+ };
+
+ u8 coderate_ptr;
+ int status;
+ u8 start_acq = 0x80;
+ u8 reg, regs[3];
+
+ dprintk("%s\n", __func__);
+
+ status = PASS;
+ coderate_ptr = coderates[crate];
+
+ si21xx_set_symbolrate(fe, symbrate);
+
+ /* write code rates to use in the Viterbi search */
+ status |= si21_writeregs(state,
+ VIT_SRCH_CTRL_REG_1,
+ &coderate_ptr, 0x01);
+
+ /* clear acq_start bit */
+ status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+ reg &= ~start_acq;
+ status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+
+ /* use new Carrier Frequency Offset Estimator (QuickLock) */
+ regs[0] = 0xCB;
+ regs[1] = 0x40;
+ regs[2] = 0xCB;
+
+ status |= si21_writeregs(state,
+ TWO_DB_BNDWDTH_THRSHLD_REG,
+ &regs[0], 0x03);
+ reg = 0x56;
+ status |= si21_writeregs(state,
+ LSA_CTRL_REG_1, &reg, 1);
+ reg = 0x05;
+ status |= si21_writeregs(state,
+ BLIND_SCAN_CTRL_REG, &reg, 1);
+ /* start automatic acq */
+ status |= si21_writeregs(state,
+ ACQ_CTRL_REG_2, &start_acq, 0x01);
+
+ return status;
+}
+
+static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+static int si21xx_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *dfp)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
+ datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
+
+ /* in MHz */
+ unsigned char coarse_tune_freq;
+ int fine_tune_freq;
+ unsigned char sample_rate = 0;
+ /* boolean */
+ unsigned int inband_interferer_ind;
+
+ /* INTERMEDIATE VALUES */
+ int icoarse_tune_freq; /* MHz */
+ int ifine_tune_freq; /* MHz */
+ unsigned int band_high;
+ unsigned int band_low;
+ unsigned int x1;
+ unsigned int x2;
+ int i;
+ unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = {
+ FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE
+ };
+ unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = {
+ FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE
+ };
+
+ int status;
+
+ /* allowable sample rates for ADC in MHz */
+ int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
+ 196, 204, 205, 206, 207
+ };
+ /* in MHz */
+ int if_limit_high;
+ int if_limit_low;
+ int lnb_lo;
+ int lnb_uncertanity;
+
+ int rf_freq;
+ int data_rate;
+ unsigned char regs[4];
+
+ dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+ if (c->delivery_system != SYS_DVBS) {
+ dprintk("%s: unsupported delivery system selected (%d)\n",
+ __func__, c->delivery_system);
+ return -EOPNOTSUPP;
+ }
+
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
+ inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE;
+
+ if_limit_high = -700000;
+ if_limit_low = -100000;
+ /* in MHz */
+ lnb_lo = 0;
+ lnb_uncertanity = 0;
+
+ rf_freq = 10 * c->frequency ;
+ data_rate = c->symbol_rate / 100;
+
+ status = PASS;
+
+ band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
+ + (data_rate * 135)) / 200;
+
+ band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
+ + (data_rate * 135)) / 200;
+
+
+ icoarse_tune_freq = 100000 *
+ (((rf_freq - lnb_lo) -
+ (if_limit_low + if_limit_high) / 2)
+ / 100000);
+
+ ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
+
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+ x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+ (afs[i] * 2500) + afs[i] * 2500;
+
+ x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+ (afs[i] * 2500);
+
+ if (((band_low < x1) && (x1 < band_high)) ||
+ ((band_low < x2) && (x2 < band_high)))
+ inband_interferer_div4[i] = TRUE;
+
+ }
+
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+ x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+ (afs[i] * 5000) + afs[i] * 5000;
+
+ x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+ (afs[i] * 5000);
+
+ if (((band_low < x1) && (x1 < band_high)) ||
+ ((band_low < x2) && (x2 < band_high)))
+ inband_interferer_div2[i] = TRUE;
+ }
+
+ inband_interferer_ind = TRUE;
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
+ inband_interferer_ind &= inband_interferer_div2[i] |
+ inband_interferer_div4[i];
+
+ if (inband_interferer_ind) {
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+ if (inband_interferer_div2[i] == FALSE) {
+ sample_rate = (u8) afs[i];
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+ if ((inband_interferer_div2[i] |
+ inband_interferer_div4[i]) == FALSE) {
+ sample_rate = (u8) afs[i];
+ break;
+ }
+ }
+
+ }
+
+ if (sample_rate > 207 || sample_rate < 192)
+ sample_rate = 200;
+
+ fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
+ ((sample_rate) * 1000));
+
+ coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
+
+ regs[0] = sample_rate;
+ regs[1] = coarse_tune_freq;
+ regs[2] = fine_tune_freq & 0xFF;
+ regs[3] = fine_tune_freq >> 8 & 0xFF;
+
+ status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
+
+ state->fs = sample_rate;/*ADC MHz*/
+ si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
+
+ return 0;
+}
+
+static int si21xx_sleep(struct dvb_frontend *fe)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+ u8 regdata;
+
+ dprintk("%s\n", __func__);
+
+ si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+ regdata |= 1 << 6;
+ si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+ state->initialised = 0;
+
+ return 0;
+}
+
+static void si21xx_release(struct dvb_frontend *fe)
+{
+ struct si21xx_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ kfree(state);
+}
+
+static struct dvb_frontend_ops si21xx_ops = {
+
+ .info = {
+ .name = "SL SI21XX DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 125, /* kHz for QPSK frontends */
+ .frequency_tolerance = 0,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .symbol_rate_tolerance = 500, /* ppm */
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+ FE_CAN_QPSK |
+ FE_CAN_FEC_AUTO
+ },
+
+ .release = si21xx_release,
+ .init = si21xx_init,
+ .sleep = si21xx_sleep,
+ .write = si21_write,
+ .read_status = si21_read_status,
+ .read_ber = si21_read_ber,
+ .read_signal_strength = si21_read_signal_strength,
+ .read_snr = si21_read_snr,
+ .read_ucblocks = si21_read_ucblocks,
+ .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
+ .diseqc_send_burst = si21xx_send_diseqc_burst,
+ .set_tone = si21xx_set_tone,
+ .set_voltage = si21xx_set_voltage,
+
+ .set_property = si21xx_set_property,
+ .get_property = si21xx_get_property,
+ .set_frontend = si21xx_set_frontend,
+};
+
+struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct si21xx_state *state = NULL;
+ int id;
+
+ dprintk("%s\n", __func__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->initialised = 0;
+ state->errmode = STATUS_BER;
+
+ /* check if the demod is there */
+ id = si21_readreg(state, SYSTEM_MODE_REG);
+ si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
+ msleep(200);
+ id = si21_readreg(state, 0x00);
+
+ /* register 0x00 contains:
+ 0x34 for SI2107
+ 0x24 for SI2108
+ 0x14 for SI2109
+ 0x04 for SI2110
+ */
+ if (id != 0x04 && id != 0x14)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &si21xx_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(si21xx_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb/frontends/si21xx.h
new file mode 100644
index 00000000000..141b5b8a5f6
--- /dev/null
+++ b/drivers/media/dvb/frontends/si21xx.h
@@ -0,0 +1,37 @@
+#ifndef SI21XX_H
+#define SI21XX_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct si21xx_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* minimum delay before retuning */
+ int min_delay_ms;
+};
+
+#if defined(CONFIG_DVB_SI21XX) || \
+ (defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
+extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *si21xx_attach(
+ const struct si21xx_config *config, struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+ int r = 0;
+ u8 buf[] = {reg, val};
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 2);
+ return r;
+}
+
+#endif
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 4543609e181..559509ab4da 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -337,7 +337,8 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct sp887x_state* state = fe->demodulator_priv;
- int actual_freq, err;
+ unsigned actual_freq;
+ int err;
u16 val, reg0xc05;
if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ &&
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c
new file mode 100644
index 00000000000..0e2cb0df144
--- /dev/null
+++ b/drivers/media/dvb/frontends/stb6000.c
@@ -0,0 +1,255 @@
+ /*
+ Driver for ST STB6000 DVBS Silicon tuner
+
+ Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+ 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.
+
+ */
+
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "stb6000.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "stb6000: " args); \
+ } while (0)
+
+struct stb6000_priv {
+ /* i2c details */
+ int i2c_address;
+ struct i2c_adapter *i2c;
+ u32 frequency;
+};
+
+static int stb6000_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static int stb6000_sleep(struct dvb_frontend *fe)
+{
+ struct stb6000_priv *priv = fe->tuner_priv;
+ int ret;
+ u8 buf[] = { 10, 0 };
+ struct i2c_msg msg = {
+ .addr = priv->i2c_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2
+ };
+
+ dprintk("%s:\n", __func__);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = i2c_transfer(priv->i2c, &msg, 1);
+ if (ret != 1)
+ dprintk("%s: i2c error\n", __func__);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return (ret == 1) ? 0 : ret;
+}
+
+static int stb6000_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct stb6000_priv *priv = fe->tuner_priv;
+ unsigned int n, m;
+ int ret;
+ u32 freq_mhz;
+ int bandwidth;
+ u8 buf[12];
+ struct i2c_msg msg = {
+ .addr = priv->i2c_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 12
+ };
+
+ dprintk("%s:\n", __func__);
+
+ freq_mhz = params->frequency / 1000;
+ bandwidth = params->u.qpsk.symbol_rate / 1000000;
+
+ if (bandwidth > 31)
+ bandwidth = 31;
+
+ if ((freq_mhz > 949) && (freq_mhz < 2151)) {
+ buf[0] = 0x01;
+ buf[1] = 0xac;
+ if (freq_mhz < 1950)
+ buf[1] = 0xaa;
+ if (freq_mhz < 1800)
+ buf[1] = 0xa8;
+ if (freq_mhz < 1650)
+ buf[1] = 0xa6;
+ if (freq_mhz < 1530)
+ buf[1] = 0xa5;
+ if (freq_mhz < 1470)
+ buf[1] = 0xa4;
+ if (freq_mhz < 1370)
+ buf[1] = 0xa2;
+ if (freq_mhz < 1300)
+ buf[1] = 0xa1;
+ if (freq_mhz < 1200)
+ buf[1] = 0xa0;
+ if (freq_mhz < 1075)
+ buf[1] = 0xbc;
+ if (freq_mhz < 1000)
+ buf[1] = 0xba;
+ if (freq_mhz < 1075) {
+ n = freq_mhz / 8; /* vco=lo*4 */
+ m = 2;
+ } else {
+ n = freq_mhz / 16; /* vco=lo*2 */
+ m = 1;
+ }
+ buf[2] = n >> 1;
+ buf[3] = (unsigned char)(((n & 1) << 7) |
+ (m * freq_mhz - n * 16) | 0x60);
+ buf[4] = 0x04;
+ buf[5] = 0x0e;
+
+ buf[6] = (unsigned char)(bandwidth);
+
+ buf[7] = 0xd8;
+ buf[8] = 0xd0;
+ buf[9] = 0x50;
+ buf[10] = 0xeb;
+ buf[11] = 0x4f;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = i2c_transfer(priv->i2c, &msg, 1);
+ if (ret != 1)
+ dprintk("%s: i2c error\n", __func__);
+
+ udelay(10);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ buf[0] = 0x07;
+ buf[1] = 0xdf;
+ buf[2] = 0xd0;
+ buf[3] = 0x50;
+ buf[4] = 0xfb;
+ msg.len = 5;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = i2c_transfer(priv->i2c, &msg, 1);
+ if (ret != 1)
+ dprintk("%s: i2c error\n", __func__);
+
+ udelay(10);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ priv->frequency = freq_mhz * 1000;
+
+ return (ret == 1) ? 0 : ret;
+ }
+ return -1;
+}
+
+static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct stb6000_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static struct dvb_tuner_ops stb6000_tuner_ops = {
+ .info = {
+ .name = "ST STB6000",
+ .frequency_min = 950000,
+ .frequency_max = 2150000
+ },
+ .release = stb6000_release,
+ .sleep = stb6000_sleep,
+ .set_params = stb6000_set_params,
+ .get_frequency = stb6000_get_frequency,
+};
+
+struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+ struct i2c_adapter *i2c)
+{
+ struct stb6000_priv *priv = NULL;
+ u8 b0[] = { 0 };
+ u8 b1[] = { 0, 0 };
+ struct i2c_msg msg[2] = {
+ {
+ .addr = addr,
+ .flags = 0,
+ .buf = b0,
+ .len = 0
+ }, {
+ .addr = addr,
+ .flags = I2C_M_RD,
+ .buf = b1,
+ .len = 2
+ }
+ };
+ int ret;
+
+ dprintk("%s:\n", __func__);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ /* is some i2c device here ? */
+ ret = i2c_transfer(i2c, msg, 2);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ if (ret != 2)
+ return NULL;
+
+ priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+
+ priv->i2c_address = addr;
+ priv->i2c = i2c;
+
+ memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = priv;
+
+ return fe;
+}
+EXPORT_SYMBOL(stb6000_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB STB6000 driver");
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h
new file mode 100644
index 00000000000..7be479c22d5
--- /dev/null
+++ b/drivers/media/dvb/frontends/stb6000.h
@@ -0,0 +1,51 @@
+ /*
+ Driver for ST stb6000 DVBS Silicon tuner
+
+ Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+#ifndef __DVB_STB6000_H__
+#define __DVB_STB6000_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a stb6000 tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param addr i2c address of the tuner.
+ * @param i2c i2c adapter to use.
+ * @return FE pointer on success, NULL on failure.
+ */
+#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
+ && defined(MODULE))
+extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe,
+ int addr,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_STB6000 */
+
+#endif /* __DVB_STB6000_H__ */
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
new file mode 100644
index 00000000000..ff1194de34c
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0288.c
@@ -0,0 +1,618 @@
+/*
+ Driver for ST STV0288 demodulator
+ Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+ for Reel Multimedia
+ Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
+ Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+ Removed stb6000 specific tuner code and revised some
+ procedures.
+
+ 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.
+
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0288.h"
+
+struct stv0288_state {
+ struct i2c_adapter *i2c;
+ const struct stv0288_config *config;
+ struct dvb_frontend frontend;
+
+ u8 initialised:1;
+ u32 tuner_frequency;
+ u32 symbol_rate;
+ fe_code_rate_t fec_inner;
+ int errmode;
+};
+
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
+static int debug;
+static int debug_legacy_dish_switch;
+#define dprintk(args...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "stv0288: " args); \
+ } while (0)
+
+
+static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
+{
+ int ret;
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2
+ };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0288_write(struct dvb_frontend *fe, u8 *buf, int len)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ if (len != 2)
+ return -EINVAL;
+
+ return stv0288_writeregI(state, buf[0], buf[1]);
+}
+
+static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 1
+ }, {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = b1,
+ .len = 1
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+ __func__, reg, ret);
+
+ return b1[0];
+}
+
+static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+ unsigned int temp;
+ unsigned char b[3];
+
+ if ((srate < 1000000) || (srate > 45000000))
+ return -EINVAL;
+
+ temp = (unsigned int)srate / 1000;
+
+ temp = temp * 32768;
+ temp = temp / 25;
+ temp = temp / 125;
+ b[0] = (unsigned char)((temp >> 12) & 0xff);
+ b[1] = (unsigned char)((temp >> 4) & 0xff);
+ b[2] = (unsigned char)((temp << 4) & 0xf0);
+ stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
+ stv0288_writeregI(state, 0x29, 0); /* SFRM */
+ stv0288_writeregI(state, 0x2a, 0); /* SFRL */
+
+ stv0288_writeregI(state, 0x28, b[0]);
+ stv0288_writeregI(state, 0x29, b[1]);
+ stv0288_writeregI(state, 0x2a, b[2]);
+ dprintk("stv0288: stv0288_set_symbolrate\n");
+
+ return 0;
+}
+
+static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *m)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ int i;
+
+ dprintk("%s\n", __func__);
+
+ stv0288_writeregI(state, 0x09, 0);
+ msleep(30);
+ stv0288_writeregI(state, 0x05, 0x16);
+
+ for (i = 0; i < m->msg_len; i++) {
+ if (stv0288_writeregI(state, 0x06, m->msg[i]))
+ return -EREMOTEIO;
+ msleep(12);
+ }
+
+ return 0;
+}
+
+static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ dprintk("%s\n", __func__);
+
+ if (stv0288_writeregI(state, 0x05, 0x16))/* burst mode */
+ return -EREMOTEIO;
+
+ if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
+ return -EREMOTEIO;
+
+ if (stv0288_writeregI(state, 0x06, 0x12))
+ return -EREMOTEIO;
+
+ return 0;
+}
+
+static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ if (stv0288_writeregI(state, 0x05, 0x10))/* burst mode */
+ return -EREMOTEIO;
+ return stv0288_writeregI(state, 0x06, 0xff);
+
+ case SEC_TONE_OFF:
+ if (stv0288_writeregI(state, 0x05, 0x13))/* burst mode */
+ return -EREMOTEIO;
+ return stv0288_writeregI(state, 0x06, 0x00);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static u8 stv0288_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x20,
+ 0x09, 0x0,
+ 0x0a, 0x4,
+ 0x0b, 0x0,
+ 0x0c, 0x0,
+ 0x0d, 0x0,
+ 0x0e, 0xd4,
+ 0x0f, 0x30,
+ 0x11, 0x80,
+ 0x12, 0x03,
+ 0x13, 0x48,
+ 0x14, 0x84,
+ 0x15, 0x45,
+ 0x16, 0xb7,
+ 0x17, 0x9c,
+ 0x18, 0x0,
+ 0x19, 0xa6,
+ 0x1a, 0x88,
+ 0x1b, 0x8f,
+ 0x1c, 0xf0,
+ 0x20, 0x0b,
+ 0x21, 0x54,
+ 0x22, 0x0,
+ 0x23, 0x0,
+ 0x2b, 0xff,
+ 0x2c, 0xf7,
+ 0x30, 0x0,
+ 0x31, 0x1e,
+ 0x32, 0x14,
+ 0x33, 0x0f,
+ 0x34, 0x09,
+ 0x35, 0x0c,
+ 0x36, 0x05,
+ 0x37, 0x2f,
+ 0x38, 0x16,
+ 0x39, 0xbe,
+ 0x3a, 0x0,
+ 0x3b, 0x13,
+ 0x3c, 0x11,
+ 0x3d, 0x30,
+ 0x40, 0x63,
+ 0x41, 0x04,
+ 0x42, 0x60,
+ 0x43, 0x00,
+ 0x44, 0x00,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x47, 0x00,
+ 0x4a, 0x00,
+ 0x50, 0x10,
+ 0x51, 0x38,
+ 0x52, 0x21,
+ 0x58, 0x54,
+ 0x59, 0x86,
+ 0x5a, 0x0,
+ 0x5b, 0x9b,
+ 0x5c, 0x08,
+ 0x5d, 0x7f,
+ 0x5e, 0x0,
+ 0x5f, 0xff,
+ 0x70, 0x0,
+ 0x71, 0x0,
+ 0x72, 0x0,
+ 0x74, 0x0,
+ 0x75, 0x0,
+ 0x76, 0x0,
+ 0x81, 0x0,
+ 0x82, 0x3f,
+ 0x83, 0x3f,
+ 0x84, 0x0,
+ 0x85, 0x0,
+ 0x88, 0x0,
+ 0x89, 0x0,
+ 0x8a, 0x0,
+ 0x8b, 0x0,
+ 0x8c, 0x0,
+ 0x90, 0x0,
+ 0x91, 0x0,
+ 0x92, 0x0,
+ 0x93, 0x0,
+ 0x94, 0x1c,
+ 0x97, 0x0,
+ 0xa0, 0x48,
+ 0xa1, 0x0,
+ 0xb0, 0xb8,
+ 0xb1, 0x3a,
+ 0xb2, 0x10,
+ 0xb3, 0x82,
+ 0xb4, 0x80,
+ 0xb5, 0x82,
+ 0xb6, 0x82,
+ 0xb7, 0x82,
+ 0xb8, 0x20,
+ 0xb9, 0x0,
+ 0xf0, 0x0,
+ 0xf1, 0x0,
+ 0xf2, 0xc0,
+ 0x51, 0x36,
+ 0x52, 0x09,
+ 0x53, 0x94,
+ 0x54, 0x62,
+ 0x55, 0x29,
+ 0x56, 0x64,
+ 0x57, 0x2b,
+ 0xff, 0xff,
+};
+
+static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+ dprintk("%s: %s\n", __func__,
+ volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+ return 0;
+}
+
+static int stv0288_init(struct dvb_frontend *fe)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+ int i;
+ u8 reg;
+ u8 val;
+
+ dprintk("stv0288: init chip\n");
+ stv0288_writeregI(state, 0x41, 0x04);
+ msleep(50);
+
+ /* we have default inittab */
+ if (state->config->inittab == NULL) {
+ for (i = 0; !(stv0288_inittab[i] == 0xff &&
+ stv0288_inittab[i + 1] == 0xff); i += 2)
+ stv0288_writeregI(state, stv0288_inittab[i],
+ stv0288_inittab[i + 1]);
+ } else {
+ for (i = 0; ; i += 2) {
+ reg = state->config->inittab[i];
+ val = state->config->inittab[i+1];
+ if (reg == 0xff && val == 0xff)
+ break;
+ stv0288_writeregI(state, reg, val);
+ }
+ }
+ return 0;
+}
+
+static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ u8 sync = stv0288_readreg(state, 0x24);
+ if (sync == 255)
+ sync = 0;
+
+ dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+
+ *status = 0;
+
+ if ((sync & 0x08) == 0x08) {
+ *status |= FE_HAS_LOCK;
+ dprintk("stv0288 has locked\n");
+ }
+
+ return 0;
+}
+
+static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ if (state->errmode != STATUS_BER)
+ return 0;
+ *ber = (stv0288_readreg(state, 0x26) << 8) |
+ stv0288_readreg(state, 0x27);
+ dprintk("stv0288_read_ber %d\n", *ber);
+
+ return 0;
+}
+
+
+static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ s32 signal = 0xffff - ((stv0288_readreg(state, 0x10) << 8));
+
+
+ signal = signal * 5 / 4;
+ *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
+ dprintk("stv0288_read_signal_strength %d\n", *strength);
+
+ return 0;
+}
+static int stv0288_sleep(struct dvb_frontend *fe)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ stv0288_writeregI(state, 0x41, 0x84);
+ state->initialised = 0;
+
+ return 0;
+}
+static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
+ | stv0288_readreg(state, 0x2e));
+ xsnr = 3 * (xsnr - 0xa100);
+ *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+ dprintk("stv0288_read_snr %d\n", *snr);
+
+ return 0;
+}
+
+static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ if (state->errmode != STATUS_BER)
+ return 0;
+ *ucblocks = (stv0288_readreg(state, 0x26) << 8) |
+ stv0288_readreg(state, 0x27);
+ dprintk("stv0288_read_ber %d\n", *ucblocks);
+
+ return 0;
+}
+
+static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+ dprintk("%s(..)\n", __func__);
+ return 0;
+}
+
+static int stv0288_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *dfp)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ char tm;
+ unsigned char tda[3];
+
+ dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+ if (c->delivery_system != SYS_DVBS) {
+ dprintk("%s: unsupported delivery "
+ "system selected (%d)\n",
+ __func__, c->delivery_system);
+ return -EOPNOTSUPP;
+ }
+
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ /* only frequency & symbol_rate are used for tuner*/
+ dfp->frequency = c->frequency;
+ dfp->u.qpsk.symbol_rate = c->symbol_rate;
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, dfp);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ udelay(10);
+ stv0288_set_symbolrate(fe, c->symbol_rate);
+ /* Carrier lock control register */
+ stv0288_writeregI(state, 0x15, 0xc5);
+
+ tda[0] = 0x2b; /* CFRM */
+ tda[2] = 0x0; /* CFRL */
+ for (tm = -6; tm < 7;) {
+ /* Viterbi status */
+ if (stv0288_readreg(state, 0x24) & 0x80)
+ break;
+
+ tda[2] += 40;
+ if (tda[2] < 40)
+ tm++;
+ tda[1] = (unsigned char)tm;
+ stv0288_writeregI(state, 0x2b, tda[1]);
+ stv0288_writeregI(state, 0x2c, tda[2]);
+ udelay(30);
+ }
+
+ state->tuner_frequency = c->frequency;
+ state->fec_inner = FEC_AUTO;
+ state->symbol_rate = c->symbol_rate;
+
+ return 0;
+}
+
+static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+
+ if (enable)
+ stv0288_writeregI(state, 0x01, 0xb5);
+ else
+ stv0288_writeregI(state, 0x01, 0x35);
+
+ udelay(1);
+
+ return 0;
+}
+
+static void stv0288_release(struct dvb_frontend *fe)
+{
+ struct stv0288_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops stv0288_ops = {
+
+ .info = {
+ .name = "ST STV0288 DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1000, /* kHz for QPSK frontends */
+ .frequency_tolerance = 0,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .symbol_rate_tolerance = 500, /* ppm */
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+ FE_CAN_QPSK |
+ FE_CAN_FEC_AUTO
+ },
+
+ .release = stv0288_release,
+ .init = stv0288_init,
+ .sleep = stv0288_sleep,
+ .write = stv0288_write,
+ .i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
+ .read_status = stv0288_read_status,
+ .read_ber = stv0288_read_ber,
+ .read_signal_strength = stv0288_read_signal_strength,
+ .read_snr = stv0288_read_snr,
+ .read_ucblocks = stv0288_read_ucblocks,
+ .diseqc_send_master_cmd = stv0288_send_diseqc_msg,
+ .diseqc_send_burst = stv0288_send_diseqc_burst,
+ .set_tone = stv0288_set_tone,
+ .set_voltage = stv0288_set_voltage,
+
+ .set_property = stv0288_set_property,
+ .get_property = stv0288_get_property,
+ .set_frontend = stv0288_set_frontend,
+};
+
+struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct stv0288_state *state = NULL;
+ int id;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->initialised = 0;
+ state->tuner_frequency = 0;
+ state->symbol_rate = 0;
+ state->fec_inner = 0;
+ state->errmode = STATUS_BER;
+
+ stv0288_writeregI(state, 0x41, 0x04);
+ msleep(200);
+ id = stv0288_readreg(state, 0x00);
+ dprintk("stv0288 id %x\n", id);
+
+ /* register 0x00 contains 0x11 for STV0288 */
+ if (id != 0x11)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &stv0288_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+
+ return NULL;
+}
+EXPORT_SYMBOL(stv0288_attach);
+
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch,
+ "Enable timing analysis for Dish Network legacy switches");
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
+MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h
new file mode 100644
index 00000000000..f2b53db0606
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0288.h
@@ -0,0 +1,67 @@
+/*
+ Driver for ST STV0288 demodulator
+
+ Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+ for Reel Multimedia
+ Copyright (C) 2008 TurboSight.com, <bob@turbosight.com>
+ Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+ Removed stb6000 specific tuner code and revised some
+ procedures.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef STV0288_H
+#define STV0288_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0288_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ u8* inittab;
+
+ /* minimum delay before retuning */
+ int min_delay_ms;
+
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
+ defined(MODULE))
+extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_STV0288 */
+
+static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+ int r = 0;
+ u8 buf[] = { reg, val };
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 2);
+ return r;
+}
+
+#endif /* STV0288_H */
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 35435bef8e7..6c1cb1973c6 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -559,6 +559,8 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
int invval = 0;
dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
// set the inversion
if (p->inversion == INVERSION_OFF) invval = 0;
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 3282f43022f..0fd96e22b65 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -89,15 +89,18 @@ struct stv0299_config
int min_delay_ms;
/* Set the symbol rate */
- int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
+ int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio);
+
+ /* Set device param to start dma */
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
};
#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE))
-extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
- struct i2c_adapter* i2c);
+extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 0ab8d86b3ae..2a8bbcd44cd 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -1,7 +1,7 @@
/*
NXP TDA10048HN DVB OFDM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
@@ -195,7 +195,7 @@ static struct init_tab {
static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
{
int ret;
- u8 buf [] = { reg, data };
+ u8 buf[] = { reg, data };
struct i2c_msg msg = {
.addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 2 };
@@ -213,9 +213,9 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
- struct i2c_msg msg [] = {
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
{ .addr = state->config->demod_address,
.flags = 0, .buf = b0, .len = 1 },
{ .addr = state->config->demod_address,
@@ -303,7 +303,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe)
if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
- return -EIO;
+ ret = -EIO;
} else {
printk(KERN_INFO "%s: firmware uploading\n", __func__);
@@ -393,43 +393,89 @@ static int tda10048_get_tps(struct tda10048_state *state,
val = tda10048_readreg(state, TDA10048_OUT_CONF2);
switch ((val & 0x60) >> 5) {
- case 0: p->constellation = QPSK; break;
- case 1: p->constellation = QAM_16; break;
- case 2: p->constellation = QAM_64; break;
+ case 0:
+ p->constellation = QPSK;
+ break;
+ case 1:
+ p->constellation = QAM_16;
+ break;
+ case 2:
+ p->constellation = QAM_64;
+ break;
}
switch ((val & 0x18) >> 3) {
- case 0: p->hierarchy_information = HIERARCHY_NONE; break;
- case 1: p->hierarchy_information = HIERARCHY_1; break;
- case 2: p->hierarchy_information = HIERARCHY_2; break;
- case 3: p->hierarchy_information = HIERARCHY_4; break;
+ case 0:
+ p->hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ p->hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ p->hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ p->hierarchy_information = HIERARCHY_4;
+ break;
}
switch (val & 0x07) {
- case 0: p->code_rate_HP = FEC_1_2; break;
- case 1: p->code_rate_HP = FEC_2_3; break;
- case 2: p->code_rate_HP = FEC_3_4; break;
- case 3: p->code_rate_HP = FEC_5_6; break;
- case 4: p->code_rate_HP = FEC_7_8; break;
+ case 0:
+ p->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_HP = FEC_7_8;
+ break;
}
val = tda10048_readreg(state, TDA10048_OUT_CONF3);
switch (val & 0x07) {
- case 0: p->code_rate_LP = FEC_1_2; break;
- case 1: p->code_rate_LP = FEC_2_3; break;
- case 2: p->code_rate_LP = FEC_3_4; break;
- case 3: p->code_rate_LP = FEC_5_6; break;
- case 4: p->code_rate_LP = FEC_7_8; break;
+ case 0:
+ p->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_LP = FEC_7_8;
+ break;
}
val = tda10048_readreg(state, TDA10048_OUT_CONF1);
switch ((val & 0x0c) >> 2) {
- case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
+ case 0:
+ p->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ p->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ p->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ p->guard_interval = GUARD_INTERVAL_1_4;
+ break;
}
switch (val & 0x02) {
- case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+ case 0:
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
}
return 0;
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 2b5c78e62c8..0457b24601f 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -1,7 +1,7 @@
/*
NXP TDA10048HN DVB OFDM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h
new file mode 100644
index 00000000000..51f17067865
--- /dev/null
+++ b/drivers/media/dvb/frontends/tdhd1.h
@@ -0,0 +1,73 @@
+/*
+ * tdhd1.h - ALPS TDHD1-204A tuner support
+ *
+ * Copyright (C) 2008 Oliver Endriss <o.endriss@gmx.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * The project's page is at http://www.linuxtv.org
+ */
+
+#ifndef TDHD1_H
+#define TDHD1_H
+
+#include "tda1004x.h"
+
+static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name);
+
+static struct tda1004x_config alps_tdhd1_204a_config = {
+ .demod_address = 0x8,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_4M,
+ .agc_config = TDA10046_AGC_DEFAULT,
+ .if_freq = TDA10046_FREQ_3617,
+ .request_firmware = alps_tdhd1_204_request_firmware
+};
+
+static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct i2c_adapter *i2c = fe->tuner_priv;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+ u32 div;
+
+ div = (params->frequency + 36166666) / 166666;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x85;
+
+ if (params->frequency >= 174000000 && params->frequency <= 230000000)
+ data[3] = 0x02;
+ else if (params->frequency >= 470000000 && params->frequency <= 823000000)
+ data[3] = 0x0C;
+ else if (params->frequency > 823000000 && params->frequency <= 862000000)
+ data[3] = 0x8C;
+ else
+ return -EINVAL;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
+#endif /* TDHD1_H */
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
index d2876d2e176..07f3fc0998f 100644
--- a/drivers/media/dvb/frontends/z0194a.h
+++ b/drivers/media/dvb/frontends/z0194a.h
@@ -12,7 +12,7 @@
#ifndef Z0194A
#define Z0194A
-static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
u32 srate, u32 ratio)
{
u8 aclk = 0;
@@ -40,7 +40,7 @@ static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
return 0;
}
-static u8 sharp_z0194a__inittab[] = {
+static u8 sharp_z0194a_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
@@ -82,16 +82,4 @@ static u8 sharp_z0194a__inittab[] = {
0xff, 0xff
};
-static struct stv0299_config sharp_z0194a_config = {
- .demod_address = 0x68,
- .inittab = sharp_z0194a__inittab,
- .mclk = 88000000UL,
- .invert = 1,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP1,
- .min_delay_ms = 100,
- .set_symbol_rate = sharp_z0194a__set_symbol_rate,
-};
-
#endif
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index e7a8ac0c404..6f9b7736044 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -4,7 +4,7 @@
* Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
@@ -40,6 +40,12 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
{ USB_DEVICE(0x2040, 0x5500),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5510),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5520),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5530),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5580),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5590),
@@ -87,7 +93,7 @@ static struct sms_board sms_boards[] = {
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
},
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
- .name = "Hauppauge WinTV-Nova-T-MiniStick",
+ .name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
},
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
index 83b39bc203f..c8f3da6f9bc 100644
--- a/drivers/media/dvb/siano/sms-cards.h
+++ b/drivers/media/dvb/siano/sms-cards.h
@@ -4,7 +4,7 @@
* Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index c5f45fed69d..6576fbb40fc 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -8,7 +8,7 @@
* Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index c1f8f1dccb1..8d973f726fb 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -6,7 +6,7 @@
* Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 229274a1411..8d490e133f3 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -6,7 +6,7 @@
* Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index c10b1849c6a..87a3c24454b 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -6,7 +6,7 @@
* Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
+ * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* Software distributed under the License is distributed on an "AS IS"
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 41b5a988b61..867027ceab3 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -86,6 +86,7 @@ config DVB_BUDGET
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select DVB_TDA1004X if !DVB_FE_CUSTOMISE
help
Support for simple SAA7146 based DVB cards (so called Budget-
or Nova-PCI cards) without onboard MPEG2 decoder, and without
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 0777e8f9544..c7c770c2898 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -88,6 +88,7 @@ static int budgetpatch;
static int wss_cfg_4_3 = 0x4008;
static int wss_cfg_16_9 = 0x0007;
static int tv_standard;
+static int full_ts;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -106,6 +107,8 @@ module_param(volume, int, 0444);
MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
module_param(budgetpatch, int, 0444);
MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
+module_param(full_ts, int, 0444);
+MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
module_param(wss_cfg_4_3, int, 0444);
MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
module_param(wss_cfg_16_9, int, 0444);
@@ -116,6 +119,8 @@ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static void restart_feeds(struct av7110 *av7110);
+static int budget_start_feed(struct dvb_demux_feed *feed);
+static int budget_stop_feed(struct dvb_demux_feed *feed);
static int av7110_num;
@@ -376,9 +381,9 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
irdebi(av7110, DEBISWAB, addr, 0, len);
}
-static void debiirq(unsigned long data)
+static void debiirq(unsigned long cookie)
{
- struct av7110 *av7110 = (struct av7110 *) data;
+ struct av7110 *av7110 = (struct av7110 *)cookie;
int type = av7110->debitype;
int handle = (type >> 8) & 0x1f;
unsigned int xfer = 0;
@@ -487,9 +492,9 @@ debi_done:
}
/* irq from av7110 firmware writing the mailbox register in the DPRAM */
-static void gpioirq(unsigned long data)
+static void gpioirq(unsigned long cookie)
{
- struct av7110 *av7110 = (struct av7110 *) data;
+ struct av7110 *av7110 = (struct av7110 *)cookie;
u32 rxbuf, txbuf;
int len;
@@ -806,6 +811,9 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
dprintk(4, "%p\n", av7110);
+ if (av7110->full_ts)
+ return 0;
+
if (dvbdmxfilter->type == DMX_TYPE_SEC) {
if (hw_sections) {
buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
@@ -854,6 +862,9 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
dprintk(4, "%p\n", av7110);
+ if (av7110->full_ts)
+ return 0;
+
handle = dvbdmxfilter->hw_handle;
if (handle >= 32) {
printk("%s tried to stop invalid filter %04x, filter type = %x\n",
@@ -913,7 +924,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
return ret;
}
- if ((dvbdmxfeed->ts_type & TS_PACKET)) {
+ if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
@@ -974,7 +985,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
- if (feed->pid > 0x1fff)
+ if (!av7110->full_ts && feed->pid > 0x1fff)
return -EINVAL;
if (feed->type == DMX_TYPE_TS) {
@@ -1003,7 +1014,12 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
}
}
- else if (feed->type == DMX_TYPE_SEC) {
+ if (av7110->full_ts) {
+ budget_start_feed(feed);
+ return ret;
+ }
+
+ if (feed->type == DMX_TYPE_SEC) {
int i;
for (i = 0; i < demux->filternum; i++) {
@@ -1050,7 +1066,12 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
ret = StopHWFilter(feed->filter);
}
- if (!ret && feed->type == DMX_TYPE_SEC) {
+ if (av7110->full_ts) {
+ budget_stop_feed(feed);
+ return ret;
+ }
+
+ if (feed->type == DMX_TYPE_SEC) {
for (i = 0; i<demux->filternum; i++) {
if (demux->filter[i].state == DMX_STATE_GO &&
demux->filter[i].filter.parent == &feed->feed.sec) {
@@ -1074,6 +1095,7 @@ static void restart_feeds(struct av7110 *av7110)
struct dvb_demux *dvbdmx = &av7110->demux;
struct dvb_demux_feed *feed;
int mode;
+ int feeding;
int i, j;
dprintk(4, "%p\n", av7110);
@@ -1082,6 +1104,8 @@ static void restart_feeds(struct av7110 *av7110)
av7110->playing = 0;
av7110->rec_mode = 0;
+ feeding = av7110->feeding1; /* full_ts mod */
+
for (i = 0; i < dvbdmx->feednum; i++) {
feed = &dvbdmx->feed[i];
if (feed->state == DMX_STATE_GO) {
@@ -1099,6 +1123,8 @@ static void restart_feeds(struct av7110 *av7110)
}
}
+ av7110->feeding1 = feeding; /* full_ts mod */
+
if (mode)
av7110_av_start_play(av7110, mode);
}
@@ -1197,8 +1223,9 @@ static int start_ts_capture(struct av7110 *budget)
if (budget->feeding1)
return ++budget->feeding1;
- memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
+ memset(budget->grabbing, 0x00, TS_BUFLEN);
budget->ttbp = 0;
+ SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
return ++budget->feeding1;
@@ -1233,18 +1260,14 @@ static int budget_stop_feed(struct dvb_demux_feed *feed)
return status;
}
-static void vpeirq(unsigned long data)
+static void vpeirq(unsigned long cookie)
{
- struct av7110 *budget = (struct av7110 *) data;
+ struct av7110 *budget = (struct av7110 *)cookie;
u8 *mem = (u8 *) (budget->grabbing);
u32 olddma = budget->ttbp;
u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+ struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
- if (!budgetpatch) {
- printk("av7110.c: vpeirq() called while budgetpatch disabled!"
- " check saa7146 IER register\n");
- BUG();
- }
/* nearest lower position divisible by 188 */
newdma -= newdma % 188;
@@ -1268,11 +1291,11 @@ static void vpeirq(unsigned long data)
if (newdma > olddma)
/* no wraparound, dump olddma..newdma */
- dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
+ dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
else {
/* wraparound, dump olddma..buflen and 0..newdma */
- dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
- dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
+ dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+ dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
}
}
@@ -1294,8 +1317,8 @@ static int av7110_register(struct av7110 *av7110)
for (i = 0; i < 32; i++)
av7110->handle2filter[i] = NULL;
- dvbdemux->filternum = 32;
- dvbdemux->feednum = 32;
+ dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
+ dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
dvbdemux->start_feed = av7110_start_feed;
dvbdemux->stop_feed = av7110_stop_feed;
dvbdemux->write_to_decoder = av7110_write_to_decoder;
@@ -1305,7 +1328,7 @@ static int av7110_register(struct av7110 *av7110)
dvb_dmx_init(&av7110->demux);
av7110->demux.dmx.get_stc = dvb_get_stc;
- av7110->dmxdev.filternum = 32;
+ av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
av7110->dmxdev.demux = &dvbdemux->dmx;
av7110->dmxdev.capabilities = 0;
@@ -1422,7 +1445,6 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
}
-#if 0
u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
{
u8 mm1[] = {0x00};
@@ -1439,7 +1461,6 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
return mm2[0];
}
-#endif
/****************************************************************************
* INITIALIZATION
@@ -2256,7 +2277,7 @@ static int frontend_init(struct av7110 *av7110)
if (!av7110->fe) {
/* FIXME: propagate the failure code from the lower layers */
ret = -ENOMEM;
- printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+ printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
av7110->dev->pci->vendor,
av7110->dev->pci->device,
av7110->dev->pci->subsystem_vendor,
@@ -2484,7 +2505,47 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
av7110->dvb_adapter.proposed_mac);
ret = -ENOMEM;
- if (budgetpatch) {
+ /* full-ts mod? */
+ if (full_ts)
+ av7110->full_ts = true;
+
+ /* check for full-ts flag in eeprom */
+ if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
+ u8 flags = i2c_readreg(av7110, 0xaa, 2);
+ if (flags != 0xff && (flags & 0x01))
+ av7110->full_ts = true;
+ }
+
+ if (av7110->full_ts) {
+ printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
+ spin_lock_init(&av7110->feedlock1);
+ av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+ &av7110->pt);
+ if (!av7110->grabbing)
+ goto err_i2c_del_3;
+
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, MC2, (MASK_10 | MASK_26));
+
+ saa7146_write(dev, DD1_INIT, 0x00000600);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, MC2, MASK_08 | MASK_24);
+
+ /* dma3 */
+ saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, 0);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, PITCH3, TS_WIDTH);
+ saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
+ saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
+ saa7146_write(dev, MC2, MASK_04 | MASK_20);
+
+ tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
+
+ } else if (budgetpatch) {
spin_lock_init(&av7110->feedlock1);
av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
&av7110->pt);
@@ -2710,11 +2771,13 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
av7110_ir_exit(av7110);
#endif
- if (budgetpatch) {
- /* Disable RPS1 */
- saa7146_write(saa, MC1, MASK_29);
- /* VSYNC LOW (inactive) */
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+ if (budgetpatch || av7110->full_ts) {
+ if (budgetpatch) {
+ /* Disable RPS1 */
+ saa7146_write(saa, MC1, MASK_29);
+ /* VSYNC LOW (inactive) */
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+ }
saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
SAA7146_IER_DISABLE(saa, MASK_10);
SAA7146_ISR_CLEAR(saa, MASK_10);
@@ -2794,7 +2857,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
tasklet_schedule(&av7110->gpio_tasklet);
}
- if ((*isr & MASK_10) && budgetpatch)
+ if (*isr & MASK_10)
tasklet_schedule(&av7110->vpe_tasklet);
}
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 55f23ddcb99..d85b8512ac3 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -192,6 +192,7 @@ struct av7110 {
unsigned char *grabbing;
struct saa7146_pgtable pt;
struct tasklet_struct vpe_tasklet;
+ bool full_ts;
int fe_synced;
struct mutex pid_mutex;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 184647ad1c7..bdc62acf209 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -788,6 +788,9 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l
dprintk(2, "av7110:%p, \n", av7110);
+ if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE)
+ return 0;
+
switch (feed->pes_type) {
case 0:
if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index b7d1f2f18d3..1032ea77837 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -57,6 +57,8 @@
#define SLOTSTATUS_READY 8
#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
struct budget_av {
struct budget budget;
struct video_device *vd;
@@ -1049,7 +1051,7 @@ static void frontend_init(struct budget_av *budget_av)
if (fe == NULL) {
printk(KERN_ERR "budget-av: A frontend driver was not found "
- "for device %04x/%04x subsystem %04x/%04x\n",
+ "for device [%04x:%04x] subsystem [%04x:%04x]\n",
saa->pci->vendor,
saa->pci->device,
saa->pci->subsystem_vendor,
@@ -1127,7 +1129,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
dev->ext_priv = budget_av;
- if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
+ err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
+ adapter_nr);
+ if (err) {
kfree(budget_av);
return err;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 060e7c78532..0a5aad45435 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -92,6 +92,8 @@ static int ir_debug;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
struct budget_ci_ir {
struct input_dev *dev;
struct tasklet_struct msp430_irq_tasklet;
@@ -1153,7 +1155,7 @@ static void frontend_init(struct budget_ci *budget_ci)
}
if (budget_ci->budget.dvb_frontend == NULL) {
- printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+ printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
budget_ci->budget.dev->pci->vendor,
budget_ci->budget.dev->pci->device,
budget_ci->budget.dev->pci->subsystem_vendor,
@@ -1183,7 +1185,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
dev->ext_priv = budget_ci;
- err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
+ err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
+ adapter_nr);
if (err)
goto out2;
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 6f4ddb643fe..ba18e56d5f1 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -57,8 +57,6 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
/****************************************************************************
* TT budget / WinTV Nova
****************************************************************************/
@@ -411,7 +409,7 @@ static void budget_unregister(struct budget *budget)
int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
- struct module *owner)
+ struct module *owner, short *adapter_nums)
{
int ret = 0;
struct budget_info *bi = info->ext_priv;
@@ -474,7 +472,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
- owner, &budget->dev->pci->dev, adapter_nr);
+ owner, &budget->dev->pci->dev, adapter_nums);
if (ret < 0)
return ret;
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 39bd0a20f53..60136688a9a 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -39,6 +39,8 @@
#include "bsru6.h"
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define budget_patch budget
static struct saa7146_extension budget_extension;
@@ -116,7 +118,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
DiseqcSendByte(budget, 0xff);
else {
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
- udelay(12500);
+ mdelay(12);
+ udelay(500);
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
}
msleep(20);
@@ -359,7 +362,7 @@ static void frontend_init(struct budget_patch* budget)
}
if (budget->dvb_frontend == NULL) {
- printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+ printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
budget->dev->pci->vendor,
budget->dev->pci->device,
budget->dev->pci->subsystem_vendor,
@@ -591,8 +594,9 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
dprintk(2, "budget: %p\n", budget);
- if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
- kfree (budget);
+ err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
+ if (err) {
+ kfree(budget);
return err;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 2293d80c6e5..1638e1d9f53 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -46,11 +46,14 @@
#include "lnbp21.h"
#include "bsru6.h"
#include "bsbe1.h"
+#include "tdhd1.h"
static int diseqc_method;
module_param(diseqc_method, int, 0444);
MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static void Set22K (struct budget *budget, int state)
{
struct saa7146_dev *dev=budget->dev;
@@ -108,7 +111,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
DiseqcSendByte(budget, 0xff);
else {
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
- udelay(12500);
+ mdelay(12);
+ udelay(500);
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
}
msleep(20);
@@ -389,6 +393,13 @@ static struct stv0299_config alps_bsbe1_config_activy = {
.set_symbol_rate = alps_bsbe1_set_symbol_rate,
};
+static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
+{
+ struct budget *budget = (struct budget *)fe->dvb->priv;
+
+ return request_firmware(fw, name, &budget->dev->pci->dev);
+}
+
static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
{
@@ -510,6 +521,14 @@ static void frontend_init(struct budget *budget)
}
break;
+ case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
+ budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ }
+ break;
+
case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
if (budget->dvb_frontend) {
@@ -549,7 +568,7 @@ static void frontend_init(struct budget *budget)
}
if (budget->dvb_frontend == NULL) {
- printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+ printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
budget->dev->pci->vendor,
budget->dev->pci->device,
budget->dev->pci->subsystem_vendor,
@@ -581,7 +600,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
dev->ext_priv = budget;
- if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
+ err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
+ if (err) {
printk("==> failed\n");
kfree (budget);
return err;
@@ -623,6 +643,7 @@ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
@@ -633,6 +654,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
+ MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
{
.vendor = 0,
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index dd450b739bf..86435bf1626 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -109,7 +109,7 @@ static struct saa7146_pci_extension_data x_var = { \
extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
- struct module *owner);
+ struct module *owner, short *adapter_nums);
extern void ttpci_budget_init_hooks(struct budget *budget);
extern int ttpci_budget_deinit(struct budget *budget);
extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index e6c9cd2e3b9..66ab0c6e978 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1614,7 +1614,7 @@ static void frontend_init(struct ttusb* ttusb)
}
if (ttusb->fe == NULL) {
- printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n",
+ printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n",
le16_to_cpu(ttusb->dev->descriptor.idVendor),
le16_to_cpu(ttusb->dev->descriptor.idProduct));
} else {
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index de5829b863f..ab33fec8a19 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1665,7 +1665,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
}
if (dec->fe == NULL) {
- printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n",
+ printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n",
le16_to_cpu(dec->udev->descriptor.idVendor),
le16_to_cpu(dec->udev->descriptor.idProduct));
} else {
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 443af24097f..21260aad1e5 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -38,7 +38,17 @@ struct ttusbdecfe_state {
};
-static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
+ fe_status_t *status)
+{
+ *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ return 0;
+}
+
+
+static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
+ fe_status_t *status)
{
struct ttusbdecfe_state* state = fe->demodulator_priv;
u8 b[] = { 0x00, 0x00, 0x00, 0x00,
@@ -251,7 +261,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
- .read_status = ttusbdecfe_read_status,
+ .read_status = ttusbdecfe_dvbt_read_status,
};
static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
@@ -273,7 +283,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
.set_frontend = ttusbdecfe_dvbs_set_frontend,
- .read_status = ttusbdecfe_read_status,
+ .read_status = ttusbdecfe_dvbs_read_status,
.diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
.set_voltage = ttusbdecfe_dvbs_set_voltage,
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 1b41b3f77cf..04cd7c04bdd 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -359,6 +359,18 @@ config USB_SI470X
computer's USB port.
To compile this driver as a module, choose M here: the
- module will be called radio-silabs.
+ module will be called radio-si470x.
+
+config USB_MR800
+ tristate "AverMedia MR 800 USB FM radio support"
+ depends on USB && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-mr800.
endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index a30159f6fa4..240ec63cdaf 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -2,8 +2,6 @@
# Makefile for the kernel character device drivers.
#
-miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o
-
obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
@@ -14,13 +12,12 @@ obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o
obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
-obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o
-obj-$(CONFIG_RADIO_MIROPCM20_RDS) += miropcm20-rds.o
obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_SI470X) += radio-si470x.o
+obj-$(CONFIG_USB_MR800) += radio-mr800.o
EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 1ed88f3abe6..78f56944e64 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -274,7 +274,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -306,18 +306,18 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
radio->curfreq = f->frequency;
if (dsbr100_setfreq(radio, radio->curfreq)==-1)
- warn("Set frequency failed");
+ dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = radio->curfreq;
@@ -342,7 +342,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -355,16 +355,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value) {
- if (dsbr100_stop(radio)==-1)
- warn("Radio did not respond properly");
+ if (dsbr100_stop(radio) == -1) {
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
+ return -EBUSY;
+ }
} else {
- if (dsbr100_start(radio)==-1)
- warn("Radio did not respond properly");
+ if (dsbr100_start(radio) == -1) {
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
+ return -EBUSY;
+ }
}
return 0;
}
@@ -405,23 +411,27 @@ static int vidioc_s_audio(struct file *file, void *priv,
static int usb_dsbr100_open(struct inode *inode, struct file *file)
{
- struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
+ lock_kernel();
radio->users = 1;
radio->muted = 1;
if (dsbr100_start(radio)<0) {
- warn("Radio did not start up properly");
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not start up properly\n");
radio->users = 0;
+ unlock_kernel();
return -EIO;
}
dsbr100_setfreq(radio, radio->curfreq);
+ unlock_kernel();
return 0;
}
static int usb_dsbr100_close(struct inode *inode, struct file *file)
{
- struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
if (!radio)
return -ENODEV;
@@ -493,8 +503,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->usbdev = interface_to_usbdev(intf);
radio->curfreq = FREQ_MIN*FREQ_MUL;
video_set_drvdata(radio->videodev, radio);
- if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
- warn("Could not register video device");
+ if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ dev_warn(&intf->dev, "Could not register video device\n");
video_device_release(radio->videodev);
kfree(radio->transfer_buffer);
kfree(radio);
@@ -507,7 +517,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
static int __init dsbr100_init(void)
{
int retval = usb_register(&usb_dsbr100_driver);
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
deleted file mode 100644
index 7fd7ee2d32c..00000000000
--- a/drivers/media/radio/miropcm20-radio.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/* Miro PCM20 radio driver for Linux radio support
- * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * Thanks to Norberto Pellici for the ACI device interface specification
- * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer (drivers/sound/aci.c)
- * Look there for further info...
- */
-
-/* Revision history:
- *
- * 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * 2000-09-05 Robert Siemer <Robert.Siemer@gmx.de>
- * removed unfinished volume control (maybe adding it later again)
- * use OSS-mixer; added stereo control
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions... Robert
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "oss/aci.h"
-#include "miropcm20-rds-core.h"
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-
-struct pcm20_device {
- unsigned long freq;
- int muted;
- int stereo;
-};
-
-
-static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
-{
- dev->muted = mute;
- return aci_write_cmd(ACI_SET_TUNERMUTE, mute);
-}
-
-static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
-{
- dev->stereo = stereo;
- return aci_write_cmd(ACI_SET_TUNERMONO, !stereo);
-}
-
-static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
-{
- unsigned char freql;
- unsigned char freqh;
-
- dev->freq=freq;
-
- freq /= 160;
- if (!(aci_version==0x07 || aci_version>=0xb0))
- freq /= 10; /* I don't know exactly which version
- * needs this hack */
- freql = freq & 0xff;
- freqh = freq >> 8;
-
- aci_rds_cmd(RDS_RESET, NULL, 0);
- pcm20_stereo(dev, 1);
-
- return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh);
-}
-
-static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
-{
- /* okay, check for signal, stereo and rds here... */
- int i;
- unsigned char buf;
-
- if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
- return i;
- pr_debug("check_sig: 0x%x\n", i);
- if (i & 0x80) {
- /* no signal from tuner */
- *flags=0;
- *signal=0;
- return 0;
- } else
- *signal=0xffff;
-
- if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0)
- return i;
- if (i & 0x40) {
- *flags=0;
- } else {
- /* stereo */
- *flags=VIDEO_TUNER_STEREO_ON;
- /* I can't see stereo, when forced to mono */
- dev->stereo=1;
- }
-
- if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
- return i;
- if (buf & 1)
- /* RDS available */
- *flags|=VIDEO_TUNER_RDS_ON;
- else
- return 0;
-
- if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
- return i;
- pr_debug("rds-signal: %d\n", buf);
- if (buf > 15) {
- printk("miropcm20-radio: RX strengths unexpected high...\n");
- buf=15;
- }
- /* refine signal */
- if ((*signal=SCALE(15, 0xffff, buf))==0)
- *signal = 1;
-
- return 0;
-}
-
-static int pcm20_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
-{
- struct video_device *dev = video_devdata(file);
- struct pcm20_device *pcm20 = dev->priv;
- int i;
-
- switch(cmd)
- {
- case VIDIOCGCAP:
- {
- struct video_capability *v = arg;
- memset(v,0,sizeof(*v));
- v->type=VID_TYPE_TUNER;
- strcpy(v->name, "Miro PCM20");
- v->channels=1;
- v->audios=1;
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner *v = arg;
- if(v->tuner) /* Only 1 tuner */
- return -EINVAL;
- v->rangelow=87*16000;
- v->rangehigh=108*16000;
- pcm20_getflags(pcm20, &v->flags, &v->signal);
- v->flags|=VIDEO_TUNER_LOW;
- v->mode=VIDEO_MODE_AUTO;
- strcpy(v->name, "FM");
- return 0;
- }
- case VIDIOCSTUNER:
- {
- struct video_tuner *v = arg;
- if(v->tuner!=0)
- return -EINVAL;
- /* Only 1 tuner so no setting needed ! */
- return 0;
- }
- case VIDIOCGFREQ:
- {
- unsigned long *freq = arg;
- *freq = pcm20->freq;
- return 0;
- }
- case VIDIOCSFREQ:
- {
- unsigned long *freq = arg;
- pcm20->freq = *freq;
- i=pcm20_setfreq(pcm20, pcm20->freq);
- pr_debug("First view (setfreq): 0x%x\n", i);
- return i;
- }
- case VIDIOCGAUDIO:
- {
- struct video_audio *v = arg;
- memset(v,0, sizeof(*v));
- v->flags=VIDEO_AUDIO_MUTABLE;
- if (pcm20->muted)
- v->flags|=VIDEO_AUDIO_MUTE;
- v->mode=VIDEO_SOUND_STEREO;
- if (pcm20->stereo)
- v->mode|=VIDEO_SOUND_MONO;
- /* v->step=2048; */
- strcpy(v->name, "Radio");
- return 0;
- }
- case VIDIOCSAUDIO:
- {
- struct video_audio *v = arg;
- if(v->audio)
- return -EINVAL;
-
- pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE));
- if(v->flags&VIDEO_SOUND_MONO)
- pcm20_stereo(pcm20, 0);
- if(v->flags&VIDEO_SOUND_STEREO)
- pcm20_stereo(pcm20, 1);
-
- return 0;
- }
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static int pcm20_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return video_usercopy(inode, file, cmd, arg, pcm20_do_ioctl);
-}
-
-static struct pcm20_device pcm20_unit = {
- .freq = 87*16000,
- .muted = 1,
-};
-
-static const struct file_operations pcm20_fops = {
- .owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = pcm20_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
-};
-
-static struct video_device pcm20_radio = {
- .name = "Miro PCM 20 radio",
- .fops = &pcm20_fops,
- .priv = &pcm20_unit
-};
-
-static int __init pcm20_init(void)
-{
- if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- goto video_register_device;
-
- if(attach_aci_rds()<0)
- goto attach_aci_rds;
-
- printk(KERN_INFO "Miro PCM20 radio card driver.\n");
-
- return 0;
-
- attach_aci_rds:
- video_unregister_device(&pcm20_radio);
- video_register_device:
- return -EINVAL;
-}
-
-MODULE_AUTHOR("Ruurd Reitsma");
-MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
-MODULE_LICENSE("GPL");
-
-static void __exit pcm20_cleanup(void)
-{
- unload_aci_rds();
- video_unregister_device(&pcm20_radio);
-}
-
-module_init(pcm20_init);
-module_exit(pcm20_cleanup);
diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c
deleted file mode 100644
index 9428d8b2642..00000000000
--- a/drivers/media/radio/miropcm20-rds-core.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Many thanks to Fred Seidel <seidel@metabox.de>, the
- * designer of the RDS decoder hardware. With his help
- * I was able to code this driver.
- * Thanks also to Norberto Pellicci, Dominic Mounteney
- * <DMounteney@pinnaclesys.com> and www.teleauskunft.de
- * for good hints on finding Fred. It was somewhat hard
- * to locate him here in Germany... [:
- *
- * Revision history:
- *
- * 2000-08-09 Robert Siemer <Robert.Siemer@gmx.de>
- * RDS support for MiroSound PCM20 radio
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include "oss/aci.h"
-#include "miropcm20-rds-core.h"
-
-#define DEBUG 0
-
-static struct mutex aci_rds_mutex;
-
-#define RDS_DATASHIFT 2 /* Bit 2 */
-#define RDS_DATAMASK (1 << RDS_DATASHIFT)
-#define RDS_BUSYMASK 0x10 /* Bit 4 */
-#define RDS_CLOCKMASK 0x08 /* Bit 3 */
-
-#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1)
-
-
-#if DEBUG
-static void print_matrix(char array[], unsigned int length)
-{
- int i, j;
-
- for (i=0; i<length; i++) {
- printk(KERN_DEBUG "aci-rds: ");
- for (j=7; j>=0; j--) {
- printk("%d", (array[i] >> j) & 0x1);
- }
- if (i%8 == 0)
- printk(" byte-border\n");
- else
- printk("\n");
- }
-}
-#endif /* DEBUG */
-
-static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
-{
- int i;
-
- if (size != 8)
- return -1;
- for (i = 7; i >= 0; i--)
- sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
- sendbuffer[0] |= RDS_CLOCKMASK;
-
- return 0;
-}
-
-static int rds_waitread(void)
-{
- unsigned char byte;
- int i=2000;
-
- do {
- byte=inb(RDS_REGISTER);
- i--;
- }
- while ((byte & RDS_BUSYMASK) && i);
-
- if (i) {
- #if DEBUG
- printk(KERN_DEBUG "rds_waitread()");
- print_matrix(&byte, 1);
- #endif
- return (byte);
- } else {
- printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n");
- return -1;
- }
-}
-
-/* don't use any ..._nowait() function if you are not sure what you do... */
-
-static inline void rds_rawwrite_nowait(unsigned char byte)
-{
- #if DEBUG
- printk(KERN_DEBUG "rds_rawwrite()");
- print_matrix(&byte, 1);
- #endif
- outb(byte, RDS_REGISTER);
-}
-
-static int rds_rawwrite(unsigned char byte)
-{
- if (rds_waitread() >= 0) {
- rds_rawwrite_nowait(byte);
- return 0;
- } else
- return -1;
-}
-
-static int rds_write(unsigned char cmd)
-{
- unsigned char sendbuffer[8];
- int i;
-
- if (byte2trans(cmd, sendbuffer, 8) != 0){
- return -1;
- } else {
- for (i=0; i<8; i++) {
- rds_rawwrite(sendbuffer[i]);
- }
- }
- return 0;
-}
-
-static int rds_readcycle_nowait(void)
-{
- rds_rawwrite_nowait(0);
- return rds_waitread();
-}
-
-static int rds_readcycle(void)
-{
- if (rds_rawwrite(0) < 0)
- return -1;
- return rds_waitread();
-}
-
-static int rds_read(unsigned char databuffer[], int datasize)
-{
- #define READSIZE (8*datasize)
-
- int i,j;
-
- if (datasize < 1) /* nothing to read */
- return 0;
-
- /* to be able to use rds_readcycle_nowait()
- I have to waitread() here */
- if (rds_waitread() < 0)
- return -1;
-
- memset(databuffer, 0, datasize);
-
- for (i=0; i< READSIZE; i++)
- if((j=rds_readcycle_nowait()) < 0) {
- return -1;
- } else {
- databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8)));
- }
-
- return 0;
-}
-
-static int rds_ack(void)
-{
- int i=rds_readcycle();
-
- if (i < 0)
- return -1;
- if (i & RDS_DATAMASK) {
- return 0; /* ACK */
- } else {
- printk(KERN_DEBUG "aci-rds: NACK\n");
- return 1; /* NACK */
- }
-}
-
-int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
-{
- int ret;
-
- if (mutex_lock_interruptible(&aci_rds_mutex))
- return -EINTR;
-
- rds_write(cmd);
-
- /* RDS_RESET doesn't need further processing */
- if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
- ret = -1;
- else
- ret = 0;
-
- mutex_unlock(&aci_rds_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(aci_rds_cmd);
-
-int __init attach_aci_rds(void)
-{
- mutex_init(&aci_rds_mutex);
- return 0;
-}
-
-void __exit unload_aci_rds(void)
-{
-}
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/miropcm20-rds-core.h b/drivers/media/radio/miropcm20-rds-core.h
deleted file mode 100644
index aeb5761f046..00000000000
--- a/drivers/media/radio/miropcm20-rds-core.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _MIROPCM20_RDS_CORE_H_
-#define _MIROPCM20_RDS_CORE_H_
-
-extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
-
-#define RDS_STATUS 0x01
-#define RDS_STATIONNAME 0x02
-#define RDS_TEXT 0x03
-#define RDS_ALTFREQ 0x04
-#define RDS_TIMEDATE 0x05
-#define RDS_PI_CODE 0x06
-#define RDS_PTYTATP 0x07
-#define RDS_RESET 0x08
-#define RDS_RXVALUE 0x09
-
-extern void __exit unload_aci_rds(void);
-extern int __init attach_aci_rds(void);
-
-#endif /* _MIROPCM20_RDS_CORE_H_ */
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
deleted file mode 100644
index 3e840f74d45..00000000000
--- a/drivers/media/radio/miropcm20-rds.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* MiroSOUND PCM20 radio rds interface driver
- * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
- * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information.
- */
-
-/* Revision history:
- *
- * 2001-04-18 Robert Siemer <Robert.Siemer@gmx.de>
- * separate file for user interface driver
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include "miropcm20-rds-core.h"
-
-static char * text_buffer;
-static int rds_users;
-
-
-static int rds_f_open(struct inode *in, struct file *fi)
-{
- if (rds_users)
- return -EBUSY;
-
- lock_kernel();
- rds_users++;
- if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
- rds_users--;
- printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
- unlock_kernel();
- return -ENOMEM;
- }
-
- unlock_kernel();
- return 0;
-}
-
-static int rds_f_release(struct inode *in, struct file *fi)
-{
- kfree(text_buffer);
-
- rds_users--;
- return 0;
-}
-
-static void print_matrix(char *ch, char out[])
-{
- int j;
-
- for (j=7; j>=0; j--) {
- out[7-j] = ((*ch >> j) & 0x1) + '0';
- }
-}
-
-static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
-{
-// i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset);
-
- char c;
- char bits[8];
-
- msleep(2000);
- aci_rds_cmd(RDS_STATUS, &c, 1);
- print_matrix(&c, bits);
- if (copy_to_user(buffer, bits, 8))
- return -EFAULT;
-
-/* if ((c >> 3) & 1) {
- aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8);
- text_buffer[0] = ' ' ;
- text_buffer[9] = '\n';
- return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18;
- }
-*/
-/* if ((c >> 6) & 1) {
- aci_rds_cmd(RDS_PTYTATP, &c, 1);
- if ( c & 1)
- sprintf(text_buffer, " M");
- else
- sprintf(text_buffer, " S");
- if ((c >> 1) & 1)
- sprintf(text_buffer+2, " TA");
- else
- sprintf(text_buffer+2, " --");
- if ((c >> 7) & 1)
- sprintf(text_buffer+5, " TP");
- else
- sprintf(text_buffer+5, " --");
- sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f);
- return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20;
- }
-*/
-
- if ((c >> 4) & 1) {
- aci_rds_cmd(RDS_TEXT, text_buffer, 65);
- text_buffer[0] = ' ' ;
- text_buffer[65] = '\n';
- return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8;
- } else {
- put_user('\n', buffer+8);
- return 9;
- }
-}
-
-static const struct file_operations rds_fops = {
- .owner = THIS_MODULE,
- .read = rds_f_read,
- .open = rds_f_open,
- .release = rds_f_release
-};
-
-static struct miscdevice rds_miscdev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "radiotext",
- .fops = &rds_fops,
-};
-
-static int __init miropcm20_rds_init(void)
-{
- return misc_register(&rds_miscdev);
-}
-
-static void __exit miropcm20_rds_cleanup(void)
-{
- misc_deregister(&rds_miscdev);
-}
-
-module_init(miropcm20_rds_init);
-module_exit(miropcm20_rds_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index eba9209b302..9305e958fc6 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -51,6 +51,7 @@ static struct mutex lock;
struct rt_device
{
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -245,8 +246,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -273,8 +273,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
rt->curfreq = f->frequency;
rt_setfreq(rt, rt->curfreq);
@@ -284,8 +283,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
@@ -310,8 +308,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -327,8 +324,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -378,10 +374,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack_unit;
+static int rtrack_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rtrack_unit.in_use);
+ return 0;
+}
+
static const struct file_operations rtrack_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = rtrack_exclusive_open,
+ .release = rtrack_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -408,6 +415,7 @@ static struct video_device rtrack_radio = {
.name = "RadioTrack radio",
.fops = &rtrack_fops,
.ioctl_ops = &rtrack_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init rtrack_init(void)
@@ -424,10 +432,9 @@ static int __init rtrack_init(void)
return -EBUSY;
}
- rtrack_radio.priv=&rtrack_unit;
+ video_set_drvdata(&rtrack_radio, &rtrack_unit);
- if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
+ if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 3fe5504428c..d7848957323 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -70,6 +70,7 @@ static struct mutex lock;
struct az_device
{
+ unsigned long in_use;
int curvol;
unsigned long curfreq;
int stereo;
@@ -195,8 +196,7 @@ static int vidioc_querycap (struct file *file, void *priv,
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -264,8 +264,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
static int vidioc_s_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
az->curfreq = f->frequency;
az_setfreq(az, az->curfreq);
@@ -275,8 +274,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = az->curfreq;
@@ -302,8 +300,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -322,8 +319,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -342,10 +338,21 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
static struct az_device aztech_unit;
+static int aztech_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
+}
+
+static int aztech_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &aztech_unit.in_use);
+ return 0;
+}
+
static const struct file_operations aztech_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = aztech_exclusive_open,
+ .release = aztech_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -369,9 +376,10 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
};
static struct video_device aztech_radio = {
- .name = "Aztech radio",
- .fops = &aztech_fops,
- .ioctl_ops = &aztech_ioctl_ops,
+ .name = "Aztech radio",
+ .fops = &aztech_fops,
+ .ioctl_ops = &aztech_ioctl_ops,
+ .release = video_device_release_empty,
};
module_param_named(debug,aztech_radio.debug, int, 0644);
@@ -392,10 +400,9 @@ static int __init aztech_init(void)
}
mutex_init(&lock);
- aztech_radio.priv=&aztech_unit;
+ video_set_drvdata(&aztech_radio, &aztech_unit);
- if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
+ if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io,2);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 6166e726ed7..0490a1fa999 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -589,6 +589,7 @@ static struct video_device cadet_radio = {
.name = "Cadet radio",
.fops = &cadet_fops,
.ioctl_ops = &cadet_ioctl_ops,
+ .release = video_device_release_empty,
};
#ifdef CONFIG_PNP
@@ -682,7 +683,7 @@ static int __init cadet_init(void)
}
if (!request_region(io,2,"cadet"))
goto fail;
- if(video_register_device(&cadet_radio,VFL_TYPE_RADIO,radio_nr)==-1) {
+ if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io,2);
goto fail;
}
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 36e754e3ffb..e15bee6d7cf 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -100,9 +100,8 @@ struct gemtek_pci_card {
u8 mute;
};
-static const char rcsid[] = "$Id: radio-gemtek-pci.c,v 1.1 2001/07/23 08:08:16 ted Exp ted $";
-
static int nr_radio = -1;
+static unsigned long in_use;
static inline u8 gemtek_pci_out( u16 value, u32 port )
{
@@ -205,8 +204,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -233,8 +231,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) ||
(f->frequency > GEMTEK_PCI_RANGE_HIGH) )
@@ -248,8 +245,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = card->current_frequency;
@@ -273,8 +269,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -293,8 +288,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -364,10 +358,21 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
static int mx = 1;
+static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations gemtek_pci_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = gemtek_pci_exclusive_open,
+ .release = gemtek_pci_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -391,9 +396,10 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
};
static struct video_device vdev_template = {
- .name = "Gemtek PCI Radio",
- .fops = &gemtek_pci_fops,
- .ioctl_ops = &gemtek_pci_ioctl_ops,
+ .name = "Gemtek PCI Radio",
+ .fops = &gemtek_pci_fops,
+ .ioctl_ops = &gemtek_pci_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
@@ -425,13 +431,13 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
}
*devradio = vdev_template;
- if ( video_register_device( devradio, VFL_TYPE_RADIO , nr_radio) == -1 ) {
+ if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) {
kfree( devradio );
goto err_video;
}
card->videodev = devradio;
- devradio->priv = card;
+ video_set_drvdata(devradio, card);
gemtek_pci_mute( card );
printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 2b1a6221de6..d131a5d3812 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -57,6 +57,7 @@ static int shutdown = 1;
static int keepmuted = 1;
static int initmute = 1;
static int radio_nr = -1;
+static unsigned long in_use;
module_param(io, int, 0444);
MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
@@ -393,10 +394,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
}
};
+static int gemtek_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations gemtek_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = gemtek_exclusive_open,
+ .release = gemtek_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -447,8 +459,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
gemtek_setfreq(rt, f->frequency);
@@ -458,8 +469,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->lastfreq;
@@ -483,8 +493,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -503,8 +512,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -569,9 +577,10 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
};
static struct video_device gemtek_radio = {
- .name = "GemTek Radio card",
- .fops = &gemtek_fops,
- .ioctl_ops = &gemtek_ioctl_ops,
+ .name = "GemTek Radio card",
+ .fops = &gemtek_fops,
+ .ioctl_ops = &gemtek_ioctl_ops,
+ .release = video_device_release_empty,
};
/*
@@ -610,10 +619,9 @@ static int __init gemtek_init(void)
return -EINVAL;
}
- gemtek_radio.priv = &gemtek_unit;
+ video_set_drvdata(&gemtek_radio, &gemtek_unit);
- if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO,
- radio_nr) == -1) {
+ if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 1);
return -EBUSY;
}
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 0ada1c697e8..4bf4d007bcf 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -75,7 +75,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
static int radio_nr = -1;
module_param(radio_nr, int, 0);
+static unsigned long in_use;
+
static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static int maestro_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maestro_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static void maestro_remove(struct pci_dev *pdev);
static struct pci_device_id maestro_r_pci_tbl[] = {
@@ -98,8 +112,8 @@ static struct pci_driver maestro_r_driver = {
static const struct file_operations maestro_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = maestro_exclusive_open,
+ .release = maestro_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -196,8 +210,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -229,8 +242,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
return -EINVAL;
@@ -241,8 +253,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = BITS2FREQ(radio_bits_get(card));
@@ -267,8 +278,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -281,8 +291,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
register u16 io = card->io;
register u16 omask = inw(io + IO_MASK);
@@ -374,6 +383,7 @@ static struct video_device maestro_radio = {
.name = "Maestro radio",
.fops = &maestro_fops,
.ioctl_ops = &maestro_ioctl_ops,
+ .release = video_device_release,
};
static int __devinit maestro_probe(struct pci_dev *pdev,
@@ -409,8 +419,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
video_set_drvdata(maestro_radio_inst, radio_unit);
pci_set_drvdata(pdev, maestro_radio_inst);
- retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
- radio_nr);
+ retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr);
if (retval) {
printk(KERN_ERR "can't register video device!\n");
goto errfr1;
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 43c75497dc4..c777a17b00b 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -85,6 +85,7 @@ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ;
static int radio_nr = -1;
module_param(radio_nr, int, 0);
+static unsigned long in_use;
#define FREQ_LO 50*16000
#define FREQ_HI 150*16000
@@ -99,10 +100,21 @@ module_param(radio_nr, int, 0);
#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
+static int maxiradio_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maxiradio_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations maxiradio_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = maxiradio_exclusive_open,
+ .release = maxiradio_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -156,28 +168,28 @@ static void set_freq(__u16 io, __u32 freq)
{
unsigned long int si;
int bl;
- int data = FREQ2BITS(freq);
+ int val = FREQ2BITS(freq);
/* TEA5757 shift register bits (see pdf) */
- outbit(0,io); // 24 search
- outbit(1,io); // 23 search up/down
+ outbit(0, io); /* 24 search */
+ outbit(1, io); /* 23 search up/down */
- outbit(0,io); // 22 stereo/mono
+ outbit(0, io); /* 22 stereo/mono */
- outbit(0,io); // 21 band
- outbit(0,io); // 20 band (only 00=FM works I think)
+ outbit(0, io); /* 21 band */
+ outbit(0, io); /* 20 band (only 00=FM works I think) */
- outbit(0,io); // 19 port ?
- outbit(0,io); // 18 port ?
+ outbit(0, io); /* 19 port ? */
+ outbit(0, io); /* 18 port ? */
- outbit(0,io); // 17 search level
- outbit(0,io); // 16 search level
+ outbit(0, io); /* 17 search level */
+ outbit(0, io); /* 16 search level */
si = 0x8000;
- for (bl = 1; bl <= 16 ; bl++) {
- outbit(data & si,io);
- si >>=1;
+ for (bl = 1; bl <= 16; bl++) {
+ outbit(val & si, io);
+ si >>= 1;
}
dprintk(1, "Radio freq set to %d.%02d MHz\n",
@@ -219,8 +231,7 @@ static int vidioc_querycap (struct file *file, void *priv,
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -290,8 +301,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
static int vidioc_s_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
@@ -312,8 +322,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = card->freq;
@@ -343,8 +352,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -358,8 +366,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -390,9 +397,10 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
};
static struct video_device maxiradio_radio = {
- .name = "Maxi Radio FM2000 radio",
- .fops = &maxiradio_fops,
- .ioctl_ops = &maxiradio_ioctl_ops,
+ .name = "Maxi Radio FM2000 radio",
+ .fops = &maxiradio_fops,
+ .ioctl_ops = &maxiradio_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -408,9 +416,9 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d
radio_unit.io = pci_resource_start(pdev, 0);
mutex_init(&radio_unit.lock);
- maxiradio_radio.priv = &radio_unit;
+ video_set_drvdata(&maxiradio_radio, &radio_unit);
- if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
+ if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
printk("radio-maxiradio: can't register device!");
goto err_out_free_region;
}
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
new file mode 100644
index 00000000000..a33717c4800
--- /dev/null
+++ b/drivers/media/radio/radio-mr800.c
@@ -0,0 +1,628 @@
+/*
+ * A driver for the AverMedia MR 800 USB FM radio. This device plugs
+ * into both the USB and an analog audio input, so this thing
+ * only deals with initialization and frequency setting, the
+ * audio data has to be handled by a sound driver.
+ *
+ * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Big thanks to authors of dsbr100.c and radio-si470x.c
+ *
+ * When work was looked pretty good, i discover this:
+ * http://av-usbradio.sourceforge.net/index.php
+ * http://sourceforge.net/projects/av-usbradio/
+ * Latest release of theirs project was in 2005.
+ * Probably, this driver could be improved trough using their
+ * achievements (specifications given).
+ * So, we have smth to begin with.
+ *
+ * History:
+ * Version 0.01: First working version.
+ * It's required to blacklist AverMedia USB Radio
+ * in usbhid/hid-quirks.c
+ *
+ * Many things to do:
+ * - Correct power managment of device (suspend & resume)
+ * - Make x86 independance (little-endian and big-endian stuff)
+ * - Add code for scanning and smooth tuning
+ * - Checked and add stereo&mono stuff
+ * - Add code for sensitivity value
+ * - Correct mistakes
+ * - In Japan another FREQ_MIN and FREQ_MAX
+ */
+
+/* kernel includes */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/usb.h>
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+
+/* driver and module definitions */
+#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
+#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
+#define DRIVER_VERSION "0.01"
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define USB_AMRADIO_VENDOR 0x07ca
+#define USB_AMRADIO_PRODUCT 0xb800
+
+/* Probably USB_TIMEOUT should be modified in module parameter */
+#define BUFFER_LENGTH 8
+#define USB_TIMEOUT 500
+
+/* Frequency limits in MHz -- these are European values. For Japanese
+devices, that would be 76 and 91. */
+#define FREQ_MIN 87.5
+#define FREQ_MAX 108.0
+#define FREQ_MUL 16000
+
+/* module parameter */
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+/* HINT: the disabled controls are only here to satify kradio and such apps */
+ { .id = V4L2_CID_AUDIO_VOLUME,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BASS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_LOUDNESS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+};
+
+static int usb_amradio_probe(struct usb_interface *intf,
+ const struct usb_device_id *id);
+static void usb_amradio_disconnect(struct usb_interface *intf);
+static int usb_amradio_open(struct inode *inode, struct file *file);
+static int usb_amradio_close(struct inode *inode, struct file *file);
+static int usb_amradio_suspend(struct usb_interface *intf,
+ pm_message_t message);
+static int usb_amradio_resume(struct usb_interface *intf);
+
+/* Data for one (physical) device */
+struct amradio_device {
+ /* reference to USB and video device */
+ struct usb_device *usbdev;
+ struct video_device *videodev;
+
+ unsigned char *buffer;
+ struct mutex lock; /* buffer locking */
+ int curfreq;
+ int stereo;
+ int users;
+ int removed;
+ int muted;
+};
+
+/* USB Device ID List */
+static struct usb_device_id usb_amradio_device_table[] = {
+ {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
+ USB_CLASS_HID, 0, 0) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
+
+/* USB subsystem interface */
+static struct usb_driver usb_amradio_driver = {
+ .name = "radio-mr800",
+ .probe = usb_amradio_probe,
+ .disconnect = usb_amradio_disconnect,
+ .suspend = usb_amradio_suspend,
+ .resume = usb_amradio_resume,
+ .reset_resume = usb_amradio_resume,
+ .id_table = usb_amradio_device_table,
+ .supports_autosuspend = 1,
+};
+
+/* switch on radio. Send 8 bytes to device. */
+static int amradio_start(struct amradio_device *radio)
+{
+ int retval;
+ int size;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0xab;
+ radio->buffer[5] = 0x00;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->muted = 0;
+
+ return retval;
+}
+
+/* switch off radio */
+static int amradio_stop(struct amradio_device *radio)
+{
+ int retval;
+ int size;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0xab;
+ radio->buffer[5] = 0x01;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->muted = 1;
+
+ return retval;
+}
+
+/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static int amradio_setfreq(struct amradio_device *radio, int freq)
+{
+ int retval;
+ int size;
+ unsigned short freq_send = 0x13 + (freq >> 3) / 25;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x03;
+ radio->buffer[4] = 0xa4;
+ radio->buffer[5] = 0x00;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x08;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ /* frequency is calculated from freq_send and placed in first 2 bytes */
+ radio->buffer[0] = (freq_send >> 8) & 0xff;
+ radio->buffer[1] = freq_send & 0xff;
+ radio->buffer[2] = 0x01;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0x00;
+ /* 5 and 6 bytes of buffer already = 0x00 */
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->stereo = 0;
+
+ return retval;
+}
+
+/* USB subsystem interface begins here */
+
+/* handle unplugging of the device, release data structures
+if nothing keeps us from doing it. If something is still
+keeping us busy, the release callback of v4l will take care
+of releasing it. */
+static void usb_amradio_disconnect(struct usb_interface *intf)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (radio) {
+ video_unregister_device(radio->videodev);
+ radio->videodev = NULL;
+ if (radio->users) {
+ kfree(radio->buffer);
+ kfree(radio);
+ } else {
+ radio->removed = 1;
+ }
+ }
+}
+
+/* vidioc_querycap - query device capabilities */
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
+ strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
+ sprintf(v->bus_info, "USB");
+ v->version = RADIO_VERSION;
+ v->capabilities = V4L2_CAP_TUNER;
+ return 0;
+}
+
+/* vidioc_g_tuner - get tuner attributes */
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ if (v->index > 0)
+ return -EINVAL;
+
+/* TODO: Add function which look is signal stereo or not
+ * amradio_getstat(radio);
+ */
+ radio->stereo = -1;
+ strcpy(v->name, "FM");
+ v->type = V4L2_TUNER_RADIO;
+ v->rangelow = FREQ_MIN * FREQ_MUL;
+ v->rangehigh = FREQ_MAX * FREQ_MUL;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ v->capability = V4L2_TUNER_CAP_LOW;
+ if (radio->stereo)
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->signal = 0xffff; /* Can't get the signal strength, sad.. */
+ v->afc = 0; /* Don't know what is this */
+ return 0;
+}
+
+/* vidioc_s_tuner - set tuner attributes */
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ if (v->index > 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* vidioc_s_frequency - set tuner radio frequency */
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ radio->curfreq = f->frequency;
+ if (amradio_setfreq(radio, radio->curfreq) < 0)
+ warn("Set frequency failed");
+ return 0;
+}
+
+/* vidioc_g_frequency - get tuner radio frequency */
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = radio->curfreq;
+ return 0;
+}
+
+/* vidioc_queryctrl - enumerate control items */
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+ if (qc->id && qc->id == radio_qctrl[i].id) {
+ memcpy(qc, &(radio_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+/* vidioc_g_ctrl - get the value of a control */
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = radio->muted;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/* vidioc_s_ctrl - set the value of a control */
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value) {
+ if (amradio_stop(radio) < 0) {
+ warn("amradio_stop() failed");
+ return -1;
+ }
+ } else {
+ if (amradio_start(radio) < 0) {
+ warn("amradio_start() failed");
+ return -1;
+ }
+ }
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/* vidioc_g_audio - get audio attributes */
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index > 1)
+ return -EINVAL;
+
+ strcpy(a->name, "Radio");
+ a->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
+
+/* vidioc_s_audio - set audio attributes */
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* vidioc_g_input - get input */
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+/* vidioc_s_input - set input */
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* open device - amradio_start() and amradio_setfreq() */
+static int usb_amradio_open(struct inode *inode, struct file *file)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ radio->users = 1;
+ radio->muted = 1;
+
+ if (amradio_start(radio) < 0) {
+ warn("Radio did not start up properly");
+ radio->users = 0;
+ return -EIO;
+ }
+ if (amradio_setfreq(radio, radio->curfreq) < 0)
+ warn("Set frequency failed");
+ return 0;
+}
+
+/*close device - free driver structures */
+static int usb_amradio_close(struct inode *inode, struct file *file)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ if (!radio)
+ return -ENODEV;
+ radio->users = 0;
+ if (radio->removed) {
+ kfree(radio->buffer);
+ kfree(radio);
+ }
+ return 0;
+}
+
+/* Suspend device - stop device. Need to be checked and fixed */
+static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ if (amradio_stop(radio) < 0)
+ warn("amradio_stop() failed");
+
+ info("radio-mr800: Going into suspend..");
+
+ return 0;
+}
+
+/* Resume device - start device. Need to be checked and fixed */
+static int usb_amradio_resume(struct usb_interface *intf)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ if (amradio_start(radio) < 0)
+ warn("amradio_start() failed");
+
+ info("radio-mr800: Coming out of suspend..");
+
+ return 0;
+}
+
+/* File system interface */
+static const struct file_operations usb_amradio_fops = {
+ .owner = THIS_MODULE,
+ .open = usb_amradio_open,
+ .release = usb_amradio_close,
+ .ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
+#endif
+ .llseek = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+};
+
+/* V4L2 interface */
+static struct video_device amradio_videodev_template = {
+ .name = "AverMedia MR 800 USB FM Radio",
+ .fops = &usb_amradio_fops,
+ .ioctl_ops = &usb_amradio_ioctl_ops,
+ .release = video_device_release,
+};
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_amradio_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct amradio_device *radio;
+
+ radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
+
+ if (!(radio))
+ return -ENOMEM;
+
+ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
+
+ if (!(radio->buffer)) {
+ kfree(radio);
+ return -ENOMEM;
+ }
+
+ radio->videodev = video_device_alloc();
+
+ if (!(radio->videodev)) {
+ kfree(radio->buffer);
+ kfree(radio);
+ return -ENOMEM;
+ }
+
+ memcpy(radio->videodev, &amradio_videodev_template,
+ sizeof(amradio_videodev_template));
+
+ radio->removed = 0;
+ radio->users = 0;
+ radio->usbdev = interface_to_usbdev(intf);
+ radio->curfreq = 95.16 * FREQ_MUL;
+
+ mutex_init(&radio->lock);
+
+ video_set_drvdata(radio->videodev, radio);
+ if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+ warn("Could not register video device");
+ video_device_release(radio->videodev);
+ kfree(radio->buffer);
+ kfree(radio);
+ return -EIO;
+ }
+
+ usb_set_intfdata(intf, radio);
+ return 0;
+}
+
+static int __init amradio_init(void)
+{
+ int retval = usb_register(&usb_amradio_driver);
+
+ info(DRIVER_VERSION " " DRIVER_DESC);
+ if (retval)
+ err("usb_register failed. Error number %d", retval);
+ return retval;
+}
+
+static void __exit amradio_exit(void)
+{
+ usb_deregister(&usb_amradio_driver);
+}
+
+module_init(amradio_init);
+module_exit(amradio_exit);
+
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index e2dde080726..a6707977741 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -52,6 +52,7 @@ static spinlock_t lock;
struct rt_device
{
+ unsigned long in_use;
int port;
unsigned long curfreq;
int muted;
@@ -153,8 +154,7 @@ static int rt_getsigstr(struct rt_device *dev)
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -173,8 +173,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
rt->curfreq = f->frequency;
rt_setfreq(rt, rt->curfreq);
@@ -184,8 +183,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
@@ -210,8 +208,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -230,8 +227,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack2_unit;
+static int rtrack2_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack2_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rtrack2_unit.in_use);
+ return 0;
+}
+
static const struct file_operations rtrack2_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = rtrack2_exclusive_open,
+ .release = rtrack2_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device rtrack2_radio = {
.name = "RadioTrack II radio",
.fops = &rtrack2_fops,
.ioctl_ops = &rtrack2_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init rtrack2_init(void)
@@ -329,11 +337,10 @@ static int __init rtrack2_init(void)
return -EBUSY;
}
- rtrack2_radio.priv=&rtrack2_unit;
+ video_set_drvdata(&rtrack2_radio, &rtrack2_unit);
spin_lock_init(&lock);
- if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
+ if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 4);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index bb5d92f104a..329c90bddad 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -45,6 +45,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
struct fmi_device
{
+ unsigned long in_use;
int port;
int curvol; /* 1 or 0 */
unsigned long curfreq; /* freq in kHz */
@@ -146,8 +147,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
int mult;
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -175,8 +175,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
f->frequency *= 1000;
@@ -193,8 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = fmi->curfreq;
@@ -221,8 +219,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -235,8 +232,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmi_device fmi_unit;
+static int fmi_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmi_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &fmi_unit.in_use);
+ return 0;
+}
+
static const struct file_operations fmi_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = fmi_exclusive_open,
+ .release = fmi_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device fmi_radio = {
.name = "SF16FMx radio",
.fops = &fmi_fops,
.ioctl_ops = &fmi_ioctl_ops,
+ .release = video_device_release_empty,
};
/* ladis: this is my card. does any other types exist? */
@@ -373,11 +381,11 @@ static int __init fmi_init(void)
fmi_unit.curvol = 0;
fmi_unit.curfreq = 0;
fmi_unit.flags = V4L2_TUNER_CAP_LOW;
- fmi_radio.priv = &fmi_unit;
+ video_set_drvdata(&fmi_radio, &fmi_unit);
mutex_init(&lock);
- if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) {
+ if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 6290553d24b..b1f47c322e0 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -64,6 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
/* this should be static vars for module size */
struct fmr2_device
{
+ unsigned long in_use;
int port;
int curvol; /* 0-15 */
int mute;
@@ -229,8 +230,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
int mult;
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -262,8 +262,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
f->frequency *= 1000;
@@ -286,8 +285,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = fmr2->curfreq;
@@ -313,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -400,10 +396,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmr2_device fmr2_unit;
+static int fmr2_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmr2_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &fmr2_unit.in_use);
+ return 0;
+}
+
static const struct file_operations fmr2_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = fmr2_exclusive_open,
+ .release = fmr2_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -430,6 +437,7 @@ static struct video_device fmr2_radio = {
.name = "SF16FMR2 radio",
.fops = &fmr2_fops,
.ioctl_ops = &fmr2_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init fmr2_init(void)
@@ -441,7 +449,7 @@ static int __init fmr2_init(void)
fmr2_unit.stereo = 1;
fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
fmr2_unit.card_type = 0;
- fmr2_radio.priv = &fmr2_unit;
+ video_set_drvdata(&fmr2_radio, &fmr2_unit);
mutex_init(&lock);
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index a4984ff87c9..5920cd30697 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -104,6 +104,7 @@
* - hardware frequency seek support
* - afc indication
* - more safety checks, let si470x_get_freq return errno
+ * - vidioc behavior corrected according to v4l2 spec
*
* ToDo:
* - add firmware download/update support
@@ -141,9 +142,9 @@
/* USB Device ID List */
static struct usb_device_id si470x_usb_driver_id_table[] = {
/* Silicon Labs USB FM Radio Reference Design */
- { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
/* Terminating entry */
{ }
};
@@ -157,7 +158,7 @@ MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
/* Radio Nr */
static int radio_nr = -1;
-module_param(radio_nr, int, 0);
+module_param(radio_nr, int, 0444);
MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* Spacing (kHz) */
@@ -165,42 +166,42 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* 1: 100 kHz (Europe, Japan) */
/* 2: 50 kHz */
static unsigned short space = 2;
-module_param(space, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
+module_param(space, ushort, 0444);
+MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
/* Bottom of Band (MHz) */
/* 0: 87.5 - 108 MHz (USA, Europe)*/
/* 1: 76 - 108 MHz (Japan wide band) */
/* 2: 76 - 90 MHz (Japan) */
static unsigned short band = 1;
-module_param(band, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
+module_param(band, ushort, 0444);
+MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
/* De-emphasis */
/* 0: 75 us (USA) */
/* 1: 50 us (Europe, Australia, Japan) */
static unsigned short de = 1;
-module_param(de, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*");
+module_param(de, ushort, 0444);
+MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
/* USB timeout */
static unsigned int usb_timeout = 500;
-module_param(usb_timeout, uint, 0);
+module_param(usb_timeout, uint, 0644);
MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
/* Tune timeout */
static unsigned int tune_timeout = 3000;
-module_param(tune_timeout, uint, 0);
+module_param(tune_timeout, uint, 0644);
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
/* Seek timeout */
static unsigned int seek_timeout = 5000;
-module_param(seek_timeout, uint, 0);
+module_param(seek_timeout, uint, 0644);
MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
/* RDS buffer blocks */
static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0);
+module_param(rds_buf, uint, 0444);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
/* RDS maximum block errors */
@@ -209,7 +210,7 @@ static unsigned short max_rds_errors = 1;
/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
/* 2 means 3-5 errors requiring correction */
/* 3 means 6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, ushort, 0);
+module_param(max_rds_errors, ushort, 0644);
MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
/* RDS poll frequency */
@@ -218,7 +219,7 @@ static unsigned int rds_poll_time = 40;
/* 50 is used by radio-cadet */
/* 75 should be okay */
/* 80 is the usual RDS receive interval */
-module_param(rds_poll_time, uint, 0);
+module_param(rds_poll_time, uint, 0644);
MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
@@ -667,23 +668,29 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
int retval;
/* Spacing (kHz) */
- switch (space) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
+ case 0:
+ spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
+ case 1:
+ spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
+ default:
+ spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
- switch (band) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+ case 0:
+ band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
+ default:
+ band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
+ case 2:
+ band_bottom = 76 * FREQ_MUL; break;
};
/* read channel */
@@ -706,23 +713,29 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
unsigned short chan;
/* Spacing (kHz) */
- switch (space) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
+ case 0:
+ spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
+ case 1:
+ spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
+ default:
+ spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
- switch (band) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+ case 0:
+ band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
+ default:
+ band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
+ case 2:
+ band_bottom = 76 * FREQ_MUL; break;
};
/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
@@ -986,7 +999,7 @@ static void si470x_work(struct work_struct *work)
static ssize_t si470x_fops_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
unsigned int block_count = 0;
@@ -1047,7 +1060,7 @@ done:
static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* switch on rds reception */
@@ -1071,9 +1084,10 @@ static unsigned int si470x_fops_poll(struct file *file,
*/
static int si470x_fops_open(struct inode *inode, struct file *file)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval;
+ lock_kernel();
radio->users++;
retval = usb_autopm_get_interface(radio->intf);
@@ -1090,6 +1104,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
}
done:
+ unlock_kernel();
return retval;
}
@@ -1099,7 +1114,7 @@ done:
*/
static int si470x_fops_release(struct inode *inode, struct file *file)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety check */
@@ -1162,7 +1177,6 @@ static const struct file_operations si470x_fops = {
* si470x_v4l2_queryctrl - query control
*/
static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
-/* HINT: the disabled controls are only here to satify kradio and such apps */
{
.id = V4L2_CID_AUDIO_VOLUME,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -1173,18 +1187,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
.default_value = 15,
},
{
- .id = V4L2_CID_AUDIO_BALANCE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_BASS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_TREBLE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
.id = V4L2_CID_AUDIO_MUTE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Mute",
@@ -1193,10 +1195,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
.step = 1,
.default_value = 1,
},
- {
- .id = V4L2_CID_AUDIO_LOUDNESS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
};
@@ -1218,56 +1216,34 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
/*
- * si470x_vidioc_g_input - get input
- */
-static int si470x_vidioc_g_input(struct file *file, void *priv,
- unsigned int *i)
-{
- *i = 0;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_input - set input
- */
-static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
- int retval = 0;
-
- /* safety checks */
- if (i != 0)
- retval = -EINVAL;
-
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": set input failed with %d\n", retval);
- return retval;
-}
-
-
-/*
* si470x_vidioc_queryctrl - enumerate control items
*/
static int si470x_vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
- unsigned char i;
+ unsigned char i = 0;
int retval = -EINVAL;
- /* safety checks */
- if (!qc->id)
+ /* abort if qc->id is below V4L2_CID_BASE */
+ if (qc->id < V4L2_CID_BASE)
goto done;
+ /* search video control */
for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
if (qc->id == si470x_v4l2_queryctrl[i].id) {
memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
- retval = 0;
+ retval = 0; /* found */
break;
}
}
+ /* disable unsupported base controls */
+ /* to satisfy kradio and such apps */
+ if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
+ qc->flags = V4L2_CTRL_FLAG_DISABLED;
+ retval = 0;
+ }
+
done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
@@ -1282,7 +1258,7 @@ done:
static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1318,7 +1294,7 @@ done:
static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1358,44 +1334,13 @@ done:
static int si470x_vidioc_g_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
- int retval = 0;
-
- /* safety checks */
- if (audio->index != 0) {
- retval = -EINVAL;
- goto done;
- }
-
+ /* driver constants */
+ audio->index = 0;
strcpy(audio->name, "Radio");
audio->capability = V4L2_AUDCAP_STEREO;
+ audio->mode = 0;
-done:
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": get audio failed with %d\n", retval);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_audio - set audio attributes
- */
-static int si470x_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- int retval = 0;
-
- /* safety checks */
- if (audio->index != 0) {
- retval = -EINVAL;
- goto done;
- }
-
-done:
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": set audio failed with %d\n", retval);
- return retval;
+ return 0;
}
@@ -1405,7 +1350,7 @@ done:
static int si470x_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1413,7 +1358,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
+ if (tuner->index != 0) {
retval = -EINVAL;
goto done;
}
@@ -1422,8 +1367,13 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
if (retval < 0)
goto done;
+ /* driver constants */
strcpy(tuner->name, "FM");
- switch (band) {
+ tuner->type = V4L2_TUNER_RADIO;
+ tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+
+ /* range limits */
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe, default) */
default:
tuner->rangelow = 87.5 * FREQ_MUL;
@@ -1440,14 +1390,18 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
tuner->rangehigh = 90 * FREQ_MUL;
break;
};
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- tuner->capability = V4L2_TUNER_CAP_LOW;
- /* Stereo indicator == Stereo (instead of Mono) */
+ /* stereo indicator == stereo (instead of mono) */
if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
- tuner->audmode = V4L2_TUNER_MODE_STEREO;
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
else
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+ /* mono/stereo selector */
+ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
tuner->audmode = V4L2_TUNER_MODE_MONO;
+ else
+ tuner->audmode = V4L2_TUNER_MODE_STEREO;
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
@@ -1471,23 +1425,28 @@ done:
static int si470x_vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval = 0;
+ struct si470x_device *radio = video_drvdata(file);
+ int retval = -EINVAL;
/* safety checks */
if (radio->disconnected) {
retval = -EIO;
goto done;
}
- if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
- retval = -EINVAL;
+ if (tuner->index != 0)
goto done;
- }
- if (tuner->audmode == V4L2_TUNER_MODE_MONO)
+ /* mono/stereo selector */
+ switch (tuner->audmode) {
+ case V4L2_TUNER_MODE_MONO:
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
- else
+ break;
+ case V4L2_TUNER_MODE_STEREO:
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
+ break;
+ default:
+ goto done;
+ }
retval = si470x_set_register(radio, POWERCFG);
@@ -1505,7 +1464,7 @@ done:
static int si470x_vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1513,11 +1472,12 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
+ freq->type = V4L2_TUNER_RADIO;
retval = si470x_get_freq(radio, &freq->frequency);
done:
@@ -1534,7 +1494,7 @@ done:
static int si470x_vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1542,7 +1502,7 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
@@ -1563,7 +1523,7 @@ done:
static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
struct v4l2_hw_freq_seek *seek)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1571,7 +1531,7 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
+ if (seek->tuner != 0) {
retval = -EINVAL;
goto done;
}
@@ -1586,15 +1546,16 @@ done:
return retval;
}
+
+/*
+ * si470x_ioctl_ops - video device ioctl operations
+ */
static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
.vidioc_querycap = si470x_vidioc_querycap,
- .vidioc_g_input = si470x_vidioc_g_input,
- .vidioc_s_input = si470x_vidioc_s_input,
.vidioc_queryctrl = si470x_vidioc_queryctrl,
.vidioc_g_ctrl = si470x_vidioc_g_ctrl,
.vidioc_s_ctrl = si470x_vidioc_s_ctrl,
.vidioc_g_audio = si470x_vidioc_g_audio,
- .vidioc_s_audio = si470x_vidioc_s_audio,
.vidioc_g_tuner = si470x_vidioc_g_tuner,
.vidioc_s_tuner = si470x_vidioc_s_tuner,
.vidioc_g_frequency = si470x_vidioc_g_frequency,
@@ -1602,14 +1563,15 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
.vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
};
+
/*
- * si470x_viddev_tamples - video device interface
+ * si470x_viddev_template - video device interface
*/
static struct video_device si470x_viddev_template = {
.fops = &si470x_fops,
- .ioctl_ops = &si470x_ioctl_ops,
.name = DRIVER_NAME,
.release = video_device_release,
+ .ioctl_ops = &si470x_ioctl_ops,
};
@@ -1694,8 +1656,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
INIT_DELAYED_WORK(&radio->work, si470x_work);
/* register video device */
- if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
- retval = -EIO;
+ retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+ if (retval) {
printk(KERN_WARNING DRIVER_NAME
": Could not register video device\n");
goto err_all;
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index cefa44fc5ae..0abb186a947 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -79,6 +79,7 @@ static spinlock_t lock;
struct tt_device
{
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -220,8 +221,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -248,8 +248,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
tt->curfreq = f->frequency;
tt_setfreq(tt, tt->curfreq);
@@ -259,8 +258,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = tt->curfreq;
@@ -285,8 +283,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -305,8 +302,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -356,10 +352,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct tt_device terratec_unit;
+static int terratec_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
+}
+
+static int terratec_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &terratec_unit.in_use);
+ return 0;
+}
+
static const struct file_operations terratec_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = terratec_exclusive_open,
+ .release = terratec_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -386,6 +393,7 @@ static struct video_device terratec_radio = {
.name = "TerraTec ActiveRadio",
.fops = &terratec_fops,
.ioctl_ops = &terratec_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init terratec_init(void)
@@ -401,12 +409,11 @@ static int __init terratec_init(void)
return -EBUSY;
}
- terratec_radio.priv=&terratec_unit;
+ video_set_drvdata(&terratec_radio, &terratec_unit);
spin_lock_init(&lock);
- if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
+ if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io,2);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index d70172d23ed..e7b111fcd10 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -78,6 +78,7 @@ static __u16 curtreble;
static unsigned long curfreq;
static int curstereo;
static int curmute;
+static unsigned long in_use;
/* i2c addresses */
#define TDA7318_ADDR 0x88
@@ -336,10 +337,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
+static int trust_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int trust_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations trust_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = trust_exclusive_open,
+ .release = trust_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -366,6 +378,7 @@ static struct video_device trust_radio = {
.name = "Trust FM Radio",
.fops = &trust_fops,
.ioctl_ops = &trust_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init trust_init(void)
@@ -378,8 +391,7 @@ static int __init trust_init(void)
printk(KERN_ERR "trust: port 0x%x already in use\n", io);
return -EBUSY;
}
- if(video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
+ if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index f8d62cfea77..952ec35a841 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -79,7 +79,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
#endif
struct typhoon_device {
- int users;
+ unsigned long in_use;
int iobase;
int curvol;
int muted;
@@ -223,8 +223,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
typhoon->curfreq = f->frequency;
typhoon_setfreq(typhoon, typhoon->curfreq);
@@ -234,8 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = typhoon->curfreq;
@@ -261,8 +259,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -278,8 +275,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -334,10 +330,21 @@ static struct typhoon_device typhoon_unit =
.mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ,
};
+static int typhoon_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
+}
+
+static int typhoon_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &typhoon_unit.in_use);
+ return 0;
+}
+
static const struct file_operations typhoon_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = typhoon_exclusive_open,
+ .release = typhoon_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -364,6 +371,7 @@ static struct video_device typhoon_radio = {
.name = "Typhoon Radio",
.fops = &typhoon_fops,
.ioctl_ops = &typhoon_ioctl_ops,
+ .release = video_device_release_empty,
};
#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
@@ -446,9 +454,8 @@ static int __init typhoon_init(void)
return -EBUSY;
}
- typhoon_radio.priv = &typhoon_unit;
- if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1)
- {
+ video_set_drvdata(&typhoon_radio, &typhoon_unit);
+ if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 8);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 9f17a332fa1..15b10bad679 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -69,6 +69,7 @@ static int io = CONFIG_RADIO_ZOLTRIX_PORT;
static int radio_nr = -1;
struct zol_device {
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -122,8 +123,11 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
unsigned int stereo = dev->stereo;
int i;
- if (freq == 0)
- return 1;
+ if (freq == 0) {
+ printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n");
+ return -EINVAL;
+ }
+
m = (freq / 160 - 8800) * 2;
f = (unsigned long long) m + 0x4d1c;
@@ -245,8 +249,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -276,19 +279,20 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
zol->curfreq = f->frequency;
- zol_setfreq(zol, zol->curfreq);
+ if (zol_setfreq(zol, zol->curfreq) != 0) {
+ printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+ return -EINVAL;
+ }
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = zol->curfreq;
@@ -313,8 +317,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +333,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -347,7 +349,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return 0;
}
zol->stereo = 1;
- zol_setfreq(zol, zol->curfreq);
+ if (zol_setfreq(zol, zol->curfreq) != 0) {
+ printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+ return -EINVAL;
+ }
#if 0
/* FIXME: Implement stereo/mono switch on V4L2 */
if (v->mode & VIDEO_SOUND_STEREO) {
@@ -396,11 +401,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct zol_device zoltrix_unit;
+static int zoltrix_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
+}
+
+static int zoltrix_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &zoltrix_unit.in_use);
+ return 0;
+}
+
static const struct file_operations zoltrix_fops =
{
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = zoltrix_exclusive_open,
+ .release = zoltrix_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -427,6 +443,7 @@ static struct video_device zoltrix_radio = {
.name = "Zoltrix Radio Plus",
.fops = &zoltrix_fops,
.ioctl_ops = &zoltrix_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init zoltrix_init(void)
@@ -440,14 +457,13 @@ static int __init zoltrix_init(void)
return -ENXIO;
}
- zoltrix_radio.priv = &zoltrix_unit;
+ video_set_drvdata(&zoltrix_radio, &zoltrix_unit);
if (!request_region(io, 2, "zoltrix")) {
printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
return -EBUSY;
}
- if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) == -1)
- {
+ if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
return -EINVAL;
}
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index ecbfa1b39b7..47102c2c825 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -34,6 +34,7 @@ config VIDEOBUF_DVB
select VIDEOBUF_GEN
config VIDEO_BTCX
+ depends on PCI
tristate
config VIDEO_IR
@@ -71,6 +72,15 @@ config VIDEO_ADV_DEBUG
V4L devices.
In doubt, say N.
+config VIDEO_FIXED_MINOR_RANGES
+ bool "Enable old-style fixed minor ranges for video devices"
+ default n
+ ---help---
+ Say Y here to enable the old-style fixed-range minor assignments.
+ Only useful if you rely on the old behavior and use mknod instead of udev.
+
+ When in doubt, say N.
+
config VIDEO_HELPER_CHIPS_AUTO
bool "Autoselect pertinent encoders/decoders and other helper chips"
default y
@@ -578,13 +588,6 @@ config VIDEO_SAA5249
To compile this driver as a module, choose M here: the
module will be called saa5249.
-config TUNER_3036
- tristate "SAB3036 tuner"
- depends on I2C && VIDEO_V4L1
- help
- Say Y here to include support for Philips SAB3036 compatible tuners.
- If in doubt, say N.
-
config VIDEO_VINO
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
@@ -602,79 +605,7 @@ config VIDEO_STRADIS
driver for PCI. There is a product page at
<http://www.stradis.com/>.
-config VIDEO_ZORAN
- tristate "Zoran ZR36057/36067 Video For Linux"
- depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
- help
- Say Y for support for MJPEG capture cards based on the Zoran
- 36057/36067 PCI controller chipset. This includes the Iomega
- Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
- a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
- more information, check <file:Documentation/video4linux/Zoran>.
-
- To compile this driver as a module, choose M here: the
- module will be called zr36067.
-
-config VIDEO_ZORAN_DC30
- tristate "Pinnacle/Miro DC30(+) support"
- depends on VIDEO_ZORAN
- select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
- card. This also supports really old DC10 cards based on the
- zr36050 MJPEG codec and zr36016 VFE.
-
-config VIDEO_ZORAN_ZR36060
- tristate "Zoran ZR36060"
- depends on VIDEO_ZORAN
- help
- Say Y to support Zoran boards based on 36060 chips.
- This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
- and 33 R10 and AverMedia 6 boards.
-
-config VIDEO_ZORAN_BUZ
- tristate "Iomega Buz support"
- depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the Iomega Buz MJPEG capture/playback card.
-
-config VIDEO_ZORAN_DC10
- tristate "Pinnacle/Miro DC10(+) support"
- depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
- card.
-
-config VIDEO_ZORAN_LML33
- tristate "Linux Media Labs LML33 support"
- depends on VIDEO_ZORAN_ZR36060
- select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the Linux Media Labs LML33 MJPEG capture/playback
- card.
-
-config VIDEO_ZORAN_LML33R10
- tristate "Linux Media Labs LML33R10 support"
- depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
- help
- support for the Linux Media Labs LML33R10 MJPEG capture/playback
- card.
-
-config VIDEO_ZORAN_AVS6EYES
- tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
- depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
- select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the AverMedia 6 Eyes video surveillance card.
+source "drivers/media/video/zoran/Kconfig"
config VIDEO_MEYE
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
@@ -697,7 +628,7 @@ config VIDEO_MXB
depends on PCI && VIDEO_V4L1 && I2C
select VIDEO_SAA7146_VV
select VIDEO_TUNER
- select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
@@ -708,21 +639,6 @@ config VIDEO_MXB
To compile this driver as a module, choose M here: the
module will be called mxb.
-config VIDEO_DPC
- tristate "Philips-Semiconductors 'dpc7146 demonstration board'"
- depends on PCI && VIDEO_V4L1 && I2C
- select VIDEO_SAA7146_VV
- select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
- ---help---
- This is a video4linux driver for the 'dpc7146 demonstration
- board' by Philips-Semiconductors. It's the reference design
- for SAA7146 bases boards, so if you have some unsupported
- saa7146 based, analog video card, chances are good that it
- will work with this skeleton driver.
-
- To compile this driver as a module, choose M here: the
- module will be called dpc7146.
-
config VIDEO_HEXIUM_ORION
tristate "Hexium HV-PCI6 and Orion frame grabber"
depends on PCI && VIDEO_V4L2 && I2C
@@ -784,6 +700,70 @@ config VIDEO_CAFE_CCIC
CMOS camera controller. This is the controller found on first-
generation OLPC systems.
+config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA
+ select VIDEOBUF_GEN
+ help
+ SoC Camera is a common API to several cameras, not connecting
+ over a bus like PCI or USB. For example some i2c camera connected
+ directly to the data bus of an SoC.
+
+config SOC_CAMERA_MT9M001
+ tristate "mt9m001 support"
+ depends on SOC_CAMERA && I2C
+ select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+ help
+ This driver supports MT9M001 cameras from Micron, monochrome
+ and colour models.
+
+config MT9M001_PCA9536_SWITCH
+ bool "pca9536 datawidth switch for mt9m001"
+ depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
+ help
+ Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
+ extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_MT9M111
+ tristate "mt9m111 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This driver supports MT9M111 cameras from Micron
+
+config SOC_CAMERA_MT9V022
+ tristate "mt9v022 support"
+ depends on SOC_CAMERA && I2C
+ select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+ help
+ This driver supports MT9V022 cameras from Micron
+
+config MT9V022_PCA9536_SWITCH
+ bool "pca9536 datawidth switch for mt9v022"
+ depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
+ help
+ Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
+ extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_PLATFORM
+ tristate "platform camera support"
+ depends on SOC_CAMERA
+ help
+ This is a generic SoC camera platform driver, useful for testing
+
+config VIDEO_PXA27x
+ tristate "PXA27x Quick Capture Interface driver"
+ depends on VIDEO_DEV && PXA27x && SOC_CAMERA
+ select VIDEOBUF_DMA_SG
+ ---help---
+ This is a v4l2 driver for the PXA27x Quick Capture Interface
+
+config VIDEO_SH_MOBILE_CEU
+ tristate "SuperH Mobile CEU Interface driver"
+ depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA
+ select VIDEOBUF_DMA_CONTIG
+ ---help---
+ This is a v4l2 driver for the SuperH Mobile CEU Interface
+
#
# USB Multimedia device configuration
#
@@ -822,8 +802,7 @@ config VIDEO_OVCAMCHIP
config USB_W9968CF
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
- depends on VIDEO_V4L1 && I2C
- select VIDEO_OVCAMCHIP
+ depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
---help---
Say Y here if you want support for cameras based on OV681 or
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
@@ -914,64 +893,4 @@ config USB_S2255
endif # V4L_USB_DRIVERS
-config SOC_CAMERA
- tristate "SoC camera support"
- depends on VIDEO_V4L2 && HAS_DMA
- select VIDEOBUF_GEN
- help
- SoC Camera is a common API to several cameras, not connecting
- over a bus like PCI or USB. For example some i2c camera connected
- directly to the data bus of an SoC.
-
-config SOC_CAMERA_MT9M001
- tristate "mt9m001 support"
- depends on SOC_CAMERA && I2C
- select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
- help
- This driver supports MT9M001 cameras from Micron, monochrome
- and colour models.
-
-config MT9M001_PCA9536_SWITCH
- bool "pca9536 datawidth switch for mt9m001"
- depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
- help
- Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
- extender to switch between 8 and 10 bit datawidth modes
-
-config SOC_CAMERA_MT9V022
- tristate "mt9v022 support"
- depends on SOC_CAMERA && I2C
- select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
- help
- This driver supports MT9V022 cameras from Micron
-
-config MT9V022_PCA9536_SWITCH
- bool "pca9536 datawidth switch for mt9v022"
- depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
- help
- Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
- extender to switch between 8 and 10 bit datawidth modes
-
-config SOC_CAMERA_PLATFORM
- tristate "platform camera support"
- depends on SOC_CAMERA
- help
- This is a generic SoC camera platform driver, useful for testing
-
-config VIDEO_PXA27x
- tristate "PXA27x Quick Capture Interface driver"
- depends on VIDEO_DEV && PXA27x
- select SOC_CAMERA
- select VIDEOBUF_DMA_SG
- ---help---
- This is a v4l2 driver for the PXA27x Quick Capture Interface
-
-config VIDEO_SH_MOBILE_CEU
- tristate "SuperH Mobile CEU Interface driver"
- depends on VIDEO_DEV
- select SOC_CAMERA
- select VIDEOBUF_DMA_CONTIG
- ---help---
- This is a v4l2 driver for the SuperH Mobile CEU Interface
-
endif # VIDEO_CAPTURE_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index bbc6f8b8229..16962f3aa15 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -2,8 +2,6 @@
# Makefile for the video capture/playback device drivers.
#
-zr36067-objs := zoran_procfs.o zoran_device.o \
- zoran_driver.o zoran_card.o
tuner-objs := tuner-core.o
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
@@ -20,6 +18,8 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
endif
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
@@ -52,9 +52,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o
obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
-obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
-obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
obj-$(CONFIG_VIDEO_PMS) += pms.o
obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
@@ -82,10 +80,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_MXB) += mxb.o
obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
-obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
-obj-$(CONFIG_TUNER_3036) += tuner-3036.o
-
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@@ -137,6 +131,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index f794f2dbfb3..e0eb4f32144 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -29,43 +29,24 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(x) (x)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
struct adv7170 {
@@ -80,21 +61,12 @@ struct adv7170 {
int sat;
};
-#define I2C_ADV7170 0xd4
-#define I2C_ADV7171 0x54
-
-static char adv7170_name[] = "adv7170";
-static char adv7171_name[] = "adv7171";
-
static char *inputs[] = { "pass_through", "play_back" };
static char *norms[] = { "PAL", "NTSC" };
/* ----------------------------------------------------------------------- */
-static inline int
-adv7170_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value)
{
struct adv7170 *encoder = i2c_get_clientdata(client);
@@ -102,17 +74,13 @@ adv7170_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline int
-adv7170_read (struct i2c_client *client,
- u8 reg)
+static inline int adv7170_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
-static int
-adv7170_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int adv7170_write_block(struct i2c_client *client,
+ const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -133,33 +101,25 @@ adv7170_write_block (struct i2c_client *client,
encoder->reg[reg++] = data[1];
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
- if ((ret = adv7170_write(client, reg,
- *data++)) < 0)
+ ret = adv7170_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
}
-
return ret;
}
/* ----------------------------------------------------------------------- */
-// Output filter: S-Video Composite
-
-#define MR050 0x11 //0x09
-#define MR060 0x14 //0x0c
-
-//---------------------------------------------------------------------------
#define TR0MODE 0x4c
#define TR0RST 0x80
@@ -167,7 +127,6 @@ adv7170_write_block (struct i2c_client *client,
#define TR1CAPT 0x00
#define TR1PLAY 0x00
-
static const unsigned char init_NTSC[] = {
0x00, 0x10, // MR0
0x01, 0x20, // MR1
@@ -227,15 +186,11 @@ static const unsigned char init_PAL[] = {
};
-static int
-adv7170_command (struct i2c_client *client,
- unsigned int cmd,
- void * arg)
+static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct adv7170 *encoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
#if 0
/* This is just for testing!!! */
@@ -254,18 +209,16 @@ adv7170_command (struct i2c_client *client,
VIDEO_ENCODER_NTSC;
cap->inputs = 2;
cap->outputs = 1;
- }
break;
+ }
case ENCODER_SET_NORM:
{
int iarg = *(int *) arg;
- dprintk(1, KERN_DEBUG "%s_command: set norm %d",
- I2C_NAME(client), iarg);
+ v4l_dbg(1, debug, client, "set norm %d\n", iarg);
switch (iarg) {
-
case VIDEO_MODE_NTSC:
adv7170_write_block(client, init_NTSC,
sizeof(init_NTSC));
@@ -285,16 +238,13 @@ adv7170_command (struct i2c_client *client,
break;
default:
- dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
- I2C_NAME(client), iarg);
+ v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
return -EINVAL;
-
}
- dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
- norms[iarg]);
+ v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
encoder->norm = iarg;
- }
break;
+ }
case ENCODER_SET_INPUT:
{
@@ -304,19 +254,17 @@ adv7170_command (struct i2c_client *client,
*iarg = 1: input is from ZR36060
*iarg = 2: color bar */
- dprintk(1, KERN_DEBUG "%s_command: set input from %s\n",
- I2C_NAME(client),
+ v4l_dbg(1, debug, client, "set input from %s\n",
iarg == 0 ? "decoder" : "ZR36060");
switch (iarg) {
-
case 0:
adv7170_write(client, 0x01, 0x20);
adv7170_write(client, 0x08, TR1CAPT); /* TR1 */
adv7170_write(client, 0x02, 0x0e); // Enable genlock
adv7170_write(client, 0x07, TR0MODE | TR0RST);
adv7170_write(client, 0x07, TR0MODE);
- //udelay(10);
+ /* udelay(10); */
break;
case 1:
@@ -325,20 +273,17 @@ adv7170_command (struct i2c_client *client,
adv7170_write(client, 0x02, 0x08);
adv7170_write(client, 0x07, TR0MODE | TR0RST);
adv7170_write(client, 0x07, TR0MODE);
- //udelay(10);
+ /* udelay(10); */
break;
default:
- dprintk(1, KERN_ERR "%s: illegal input: %d\n",
- I2C_NAME(client), iarg);
+ v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
return -EINVAL;
-
}
- dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
- inputs[iarg]);
+ v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
encoder->input = iarg;
- }
break;
+ }
case ENCODER_SET_OUTPUT:
{
@@ -348,16 +293,16 @@ adv7170_command (struct i2c_client *client,
if (*iarg != 0) {
return -EINVAL;
}
- }
break;
+ }
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
- }
break;
+ }
default:
return -EINVAL;
@@ -368,149 +313,67 @@ adv7170_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
- { I2C_ADV7170 >> 1, (I2C_ADV7170 >> 1) + 1,
- I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
+static unsigned short normal_i2c[] = {
+ 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */
+ 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */
I2C_CLIENT_END
};
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-static struct i2c_driver i2c_driver_adv7170;
-
-static int
-adv7170_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int adv7170_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- int i;
- struct i2c_client *client;
struct adv7170 *encoder;
- char *dname;
-
- dprintk(1,
- KERN_INFO
- "adv7170.c: detecting adv7170 client on address 0x%x\n",
- address << 1);
+ int i;
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_adv7170;
- if ((client->addr == I2C_ADV7170 >> 1) ||
- (client->addr == (I2C_ADV7170 >> 1) + 1)) {
- dname = adv7170_name;
- } else if ((client->addr == I2C_ADV7171 >> 1) ||
- (client->addr == (I2C_ADV7171 >> 1) + 1)) {
- dname = adv7171_name;
- } else {
- /* We should never get here!!! */
- kfree(client);
- return 0;
- }
- strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
- if (encoder == NULL) {
- kfree(client);
+ if (encoder == NULL)
return -ENOMEM;
- }
encoder->norm = VIDEO_MODE_NTSC;
encoder->input = 0;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(encoder);
- return i;
- }
-
i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC));
if (i >= 0) {
i = adv7170_write(client, 0x07, TR0MODE | TR0RST);
i = adv7170_write(client, 0x07, TR0MODE);
i = adv7170_read(client, 0x12);
- dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%02x\n",
- I2C_NAME(client), i & 1, client->addr << 1);
- }
- if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
- I2C_NAME(client), i);
+ v4l_dbg(1, debug, client, "revision %d\n", i & 1);
}
-
+ if (i < 0)
+ v4l_dbg(1, debug, client, "init error 0x%x\n", i);
return 0;
}
-static int
-adv7170_attach_adapter (struct i2c_adapter *adapter)
-{
- dprintk(1,
- KERN_INFO
- "adv7170.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &adv7170_detect_client);
-}
-
-static int
-adv7170_detach_client (struct i2c_client *client)
+static int adv7170_remove(struct i2c_client *client)
{
- struct adv7170 *encoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(encoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_adv7170 = {
- .driver = {
- .name = "adv7170", /* name */
- },
-
- .id = I2C_DRIVERID_ADV7170,
+static const struct i2c_device_id adv7170_id[] = {
+ { "adv7170", 0 },
+ { "adv7171", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adv7170_id);
- .attach_adapter = adv7170_attach_adapter,
- .detach_client = adv7170_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "adv7170",
+ .driverid = I2C_DRIVERID_ADV7170,
.command = adv7170_command,
+ .probe = adv7170_probe,
+ .remove = adv7170_remove,
+ .id_table = adv7170_id,
};
-
-static int __init
-adv7170_init (void)
-{
- return i2c_add_driver(&i2c_driver_adv7170);
-}
-
-static void __exit
-adv7170_exit (void)
-{
- i2c_del_driver(&i2c_driver_adv7170);
-}
-
-module_init(adv7170_init);
-module_exit(adv7170_exit);
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 8ee07a68f70..6008e84653f 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -25,43 +25,24 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(s) (s)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
struct adv7175 {
@@ -77,33 +58,23 @@ struct adv7175 {
#define I2C_ADV7175 0xd4
#define I2C_ADV7176 0x54
-static char adv7175_name[] = "adv7175";
-static char adv7176_name[] = "adv7176";
-
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
/* ----------------------------------------------------------------------- */
-static inline int
-adv7175_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline int
-adv7175_read (struct i2c_client *client,
- u8 reg)
+static inline int adv7175_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
-static int
-adv7175_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int adv7175_write_block(struct i2c_client *client,
+ const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -123,18 +94,17 @@ adv7175_write_block (struct i2c_client *client,
reg++;
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
- if ((ret = adv7175_write(client, reg,
- *data++)) < 0)
+ ret = adv7175_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
@@ -143,13 +113,11 @@ adv7175_write_block (struct i2c_client *client,
return ret;
}
-static void
-set_subcarrier_freq (struct i2c_client *client,
- int pass_through)
+static void set_subcarrier_freq(struct i2c_client *client, int pass_through)
{
/* for some reason pass_through NTSC needs
* a different sub-carrier freq to remain stable. */
- if(pass_through)
+ if (pass_through)
adv7175_write(client, 0x02, 0x00);
else
adv7175_write(client, 0x02, 0x55);
@@ -160,12 +128,12 @@ set_subcarrier_freq (struct i2c_client *client,
}
/* ----------------------------------------------------------------------- */
-// Output filter: S-Video Composite
+/* Output filter: S-Video Composite */
-#define MR050 0x11 //0x09
-#define MR060 0x14 //0x0c
+#define MR050 0x11 /* 0x09 */
+#define MR060 0x14 /* 0x0c */
-//---------------------------------------------------------------------------
+/* ----------------------------------------------------------------------- */
#define TR0MODE 0x46
#define TR0RST 0x80
@@ -216,15 +184,11 @@ static const unsigned char init_ntsc[] = {
0x06, 0x1a, /* subc. phase */
};
-static int
-adv7175_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct adv7175 *encoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
/* This is just for testing!!! */
adv7175_write_block(client, init_common,
@@ -242,15 +206,14 @@ adv7175_command (struct i2c_client *client,
VIDEO_ENCODER_SECAM; /* well, hacky */
cap->inputs = 2;
cap->outputs = 1;
- }
break;
+ }
case ENCODER_SET_NORM:
{
int iarg = *(int *) arg;
switch (iarg) {
-
case VIDEO_MODE_NTSC:
adv7175_write_block(client, init_ntsc,
sizeof(init_ntsc));
@@ -284,16 +247,13 @@ adv7175_command (struct i2c_client *client,
adv7175_write(client, 0x07, TR0MODE);
break;
default:
- dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
- I2C_NAME(client), iarg);
+ v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
return -EINVAL;
-
}
- dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
- norms[iarg]);
+ v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
encoder->norm = iarg;
- }
break;
+ }
case ENCODER_SET_INPUT:
{
@@ -304,7 +264,6 @@ adv7175_command (struct i2c_client *client,
*iarg = 2: color bar */
switch (iarg) {
-
case 0:
adv7175_write(client, 0x01, 0x00);
@@ -331,7 +290,7 @@ adv7175_command (struct i2c_client *client,
adv7175_write(client, 0x0d, 0x49);
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
- //udelay(10);
+ /* udelay(10); */
break;
case 2:
@@ -343,39 +302,35 @@ adv7175_command (struct i2c_client *client,
adv7175_write(client, 0x0d, 0x49);
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
- //udelay(10);
+ /* udelay(10); */
break;
default:
- dprintk(1, KERN_ERR "%s: illegal input: %d\n",
- I2C_NAME(client), iarg);
+ v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
return -EINVAL;
-
}
- dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
- inputs[iarg]);
+ v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
encoder->input = iarg;
- }
break;
+ }
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
- if (*iarg != 0) {
+ if (*iarg != 0)
return -EINVAL;
- }
- }
break;
+ }
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
- }
break;
+ }
default:
return -EINVAL;
@@ -390,145 +345,67 @@ adv7175_command (struct i2c_client *client,
* Generic i2c probe
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static unsigned short normal_i2c[] =
- { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
+static unsigned short normal_i2c[] = {
+ I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
I2C_CLIENT_END
};
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-static struct i2c_driver i2c_driver_adv7175;
+I2C_CLIENT_INSMOD;
-static int
-adv7175_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int adv7175_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i;
- struct i2c_client *client;
struct adv7175 *encoder;
- char *dname;
-
- dprintk(1,
- KERN_INFO
- "adv7175.c: detecting adv7175 client on address 0x%x\n",
- address << 1);
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_adv7175;
- if ((client->addr == I2C_ADV7175 >> 1) ||
- (client->addr == (I2C_ADV7175 >> 1) + 1)) {
- dname = adv7175_name;
- } else if ((client->addr == I2C_ADV7176 >> 1) ||
- (client->addr == (I2C_ADV7176 >> 1) + 1)) {
- dname = adv7176_name;
- } else {
- /* We should never get here!!! */
- kfree(client);
- return 0;
- }
- strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
- if (encoder == NULL) {
- kfree(client);
+ if (encoder == NULL)
return -ENOMEM;
- }
encoder->norm = VIDEO_MODE_PAL;
encoder->input = 0;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(encoder);
- return i;
- }
-
i = adv7175_write_block(client, init_common, sizeof(init_common));
if (i >= 0) {
i = adv7175_write(client, 0x07, TR0MODE | TR0RST);
i = adv7175_write(client, 0x07, TR0MODE);
i = adv7175_read(client, 0x12);
- dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%x\n",
- I2C_NAME(client), i & 1, client->addr << 1);
+ v4l_dbg(1, debug, client, "revision %d\n", i & 1);
}
- if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
- I2C_NAME(client), i);
- }
-
+ if (i < 0)
+ v4l_dbg(1, debug, client, "init error 0x%x\n", i);
return 0;
}
-static int
-adv7175_attach_adapter (struct i2c_adapter *adapter)
-{
- dprintk(1,
- KERN_INFO
- "adv7175.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &adv7175_detect_client);
-}
-
-static int
-adv7175_detach_client (struct i2c_client *client)
+static int adv7175_remove(struct i2c_client *client)
{
- struct adv7175 *encoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(encoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_adv7175 = {
- .driver = {
- .name = "adv7175", /* name */
- },
-
- .id = I2C_DRIVERID_ADV7175,
+static const struct i2c_device_id adv7175_id[] = {
+ { "adv7175", 0 },
+ { "adv7176", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adv7175_id);
- .attach_adapter = adv7175_attach_adapter,
- .detach_client = adv7175_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "adv7175",
+ .driverid = I2C_DRIVERID_ADV7175,
.command = adv7175_command,
+ .probe = adv7175_probe,
+ .remove = adv7175_remove,
+ .id_table = adv7175_id,
};
-
-static int __init
-adv7175_init (void)
-{
- return i2c_add_driver(&i2c_driver_adv7175);
-}
-
-static void __exit
-adv7175_exit (void)
-{
- i2c_del_driver(&i2c_driver_adv7175);
-}
-
-module_init(adv7175_init);
-module_exit(adv7175_exit);
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 9e436ad3d34..218754b4906 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -116,6 +116,7 @@ struct ar_device {
int width, height;
int frame_bytes, line_bytes;
wait_queue_head_t wait;
+ unsigned long in_use;
struct mutex lock;
};
@@ -269,7 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line)
static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
struct video_device *v = video_devdata(file);
- struct ar_device *ar = v->priv;
+ struct ar_device *ar = video_get_drvdata(v);
long ret = ar->frame_bytes; /* return read bytes */
unsigned long arvcr1 = 0;
unsigned long flags;
@@ -399,7 +400,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
- struct ar_device *ar = dev->priv;
+ struct ar_device *ar = video_get_drvdata(dev);
DEBUG(1, "ar_ioctl()\n");
switch(cmd) {
@@ -625,7 +626,7 @@ static void ar_interrupt(int irq, void *dev)
*/
static int ar_initialize(struct video_device *dev)
{
- struct ar_device *ar = dev->priv;
+ struct ar_device *ar = video_get_drvdata(dev);
unsigned long cr = 0;
int i,found=0;
@@ -732,7 +733,7 @@ static int ar_initialize(struct video_device *dev)
void ar_release(struct video_device *vfd)
{
- struct ar_device *ar = vfd->priv;
+ struct ar_device *ar = video_get_drvdata(vfd);
mutex_lock(&ar->lock);
video_device_release(vfd);
}
@@ -742,10 +743,23 @@ void ar_release(struct video_device *vfd)
* Video4Linux Module functions
*
****************************************************************************/
+static struct ar_device ardev;
+
+static int ar_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0;
+}
+
+static int ar_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &ardev.in_use);
+ return 0;
+}
+
static const struct file_operations ar_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = ar_exclusive_open,
+ .release = ar_exclusive_release,
.read = ar_read,
.ioctl = ar_ioctl,
#ifdef CONFIG_COMPAT
@@ -762,7 +776,6 @@ static struct video_device ar_template = {
};
#define ALIGN4(x) ((((int)(x)) & 0x3) == 0)
-static struct ar_device ardev;
static int __init ar_init(void)
{
@@ -802,7 +815,7 @@ static int __init ar_init(void)
return -ENOMEM;
}
memcpy(ar->vdev, &ar_template, sizeof(ar_template));
- ar->vdev->priv = ar;
+ video_set_drvdata(ar->vdev, ar);
if (vga) {
ar->width = AR_WIDTH_VGA;
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
index ed9a50f189f..018f72b8e3e 100644
--- a/drivers/media/video/au0828/Kconfig
+++ b/drivers/media/video/au0828/Kconfig
@@ -7,6 +7,7 @@ config VIDEO_AU0828
select DVB_AU8522 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
---help---
This is a video4linux driver for Auvitek's USB device.
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
index 443e5900976..d60123b413f 100644
--- a/drivers/media/video/au0828/au0828-cards.c
+++ b/drivers/media/video/au0828/au0828-cards.c
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -38,12 +38,15 @@ struct au0828_board au0828_boards[] = {
[AU0828_BOARD_DVICO_FUSIONHDTV7] = {
.name = "DViCO FusionHDTV USB",
},
+ [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
+ .name = "Hauppauge Woodbury",
+ },
};
/* Tuner callback function for au0828 boards. Currently only needed
* for HVR1500Q, which has an xc5000 tuner.
*/
-int au0828_tuner_callback(void *priv, int command, int arg)
+int au0828_tuner_callback(void *priv, int component, int command, int arg)
{
struct au0828_dev *dev = priv;
@@ -87,6 +90,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */
+ case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
break;
@@ -115,6 +119,7 @@ void au0828_card_setup(struct au0828_dev *dev)
case AU0828_BOARD_HAUPPAUGE_HVR850:
case AU0828_BOARD_HAUPPAUGE_HVR950Q:
case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+ case AU0828_BOARD_HAUPPAUGE_WOODBURY:
if (dev->i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xa0);
break;
@@ -134,6 +139,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
case AU0828_BOARD_HAUPPAUGE_HVR850:
case AU0828_BOARD_HAUPPAUGE_HVR950Q:
case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+ case AU0828_BOARD_HAUPPAUGE_WOODBURY:
/* GPIO's
* 4 - CS5340
* 5 - AU8522 Demodulator
@@ -180,7 +186,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
}
/* table of devices that work with this driver */
-struct usb_device_id au0828_usb_id_table [] = {
+struct usb_device_id au0828_usb_id_table[] = {
{ USB_DEVICE(0x2040, 0x7200),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x7240),
@@ -193,6 +199,8 @@ struct usb_device_id au0828_usb_id_table [] = {
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x721b),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+ { USB_DEVICE(0x2040, 0x721e),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x721f),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x7280),
@@ -205,6 +213,8 @@ struct usb_device_id au0828_usb_id_table [] = {
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
{ USB_DEVICE(0x2040, 0x7281),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+ { USB_DEVICE(0x2040, 0x8200),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
{ },
};
diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
index c37f5fd0fa8..48a1882c2b6 100644
--- a/drivers/media/video/au0828/au0828-cards.h
+++ b/drivers/media/video/au0828/au0828-cards.h
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -24,3 +24,4 @@
#define AU0828_BOARD_HAUPPAUGE_HVR850 2
#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL 4
+#define AU0828_BOARD_HAUPPAUGE_WOODBURY 5
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index 54bfc0f0529..5765e865637 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -91,7 +91,8 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
request,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
value, index,
cp, size, 1000);
@@ -252,5 +253,5 @@ module_init(au0828_init);
module_exit(au0828_exit);
MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index 584a83a94a2..a882cf546d0 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -29,21 +29,58 @@
#include "au8522.h"
#include "xc5000.h"
#include "mxl5007t.h"
+#include "tda18271.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define _AU0828_BULKPIPE 0x83
#define _BULKPIPESIZE 0xe522
+static u8 hauppauge_hvr950q_led_states[] = {
+ 0x00, /* off */
+ 0x02, /* yellow */
+ 0x04, /* green */
+};
+
+static struct au8522_led_config hauppauge_hvr950q_led_cfg = {
+ .gpio_output = 0x00e0,
+ .gpio_output_enable = 0x6006,
+ .gpio_output_disable = 0x0660,
+
+ .gpio_leds = 0x00e2,
+ .led_states = hauppauge_hvr950q_led_states,
+ .num_led_states = sizeof(hauppauge_hvr950q_led_states),
+
+ .vsb8_strong = 20 /* dB */ * 10,
+ .qam64_strong = 25 /* dB */ * 10,
+ .qam256_strong = 32 /* dB */ * 10,
+};
+
static struct au8522_config hauppauge_hvr950q_config = {
.demod_address = 0x8e >> 1,
.status_mode = AU8522_DEMODLOCKING,
+ .qam_if = AU8522_IF_6MHZ,
+ .vsb_if = AU8522_IF_6MHZ,
+ .led_cfg = &hauppauge_hvr950q_led_cfg,
+};
+
+static struct au8522_config fusionhdtv7usb_config = {
+ .demod_address = 0x8e >> 1,
+ .status_mode = AU8522_DEMODLOCKING,
+ .qam_if = AU8522_IF_6MHZ,
+ .vsb_if = AU8522_IF_6MHZ,
+};
+
+static struct au8522_config hauppauge_woodbury_config = {
+ .demod_address = 0x8e >> 1,
+ .status_mode = AU8522_DEMODLOCKING,
+ .qam_if = AU8522_IF_4MHZ,
+ .vsb_if = AU8522_IF_3_25MHZ,
};
static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
.i2c_address = 0x61,
.if_khz = 6000,
- .tuner_callback = au0828_tuner_callback
};
static struct mxl5007t_config mxl5007t_hvr950q_config = {
@@ -51,6 +88,10 @@ static struct mxl5007t_config mxl5007t_hvr950q_config = {
.if_freq_hz = MxL_IF_6_MHZ,
};
+static struct tda18271_config hauppauge_woodbury_tunerconfig = {
+ .gate = TDA18271_GATE_DIGITAL,
+};
+
/*-------------------------------------------------------------------*/
static void urb_completion(struct urb *purb)
{
@@ -132,7 +173,8 @@ static int start_urb_transfer(struct au0828_dev *dev)
purb->status = -EINPROGRESS;
usb_fill_bulk_urb(purb,
dev->usbdev,
- usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+ usb_rcvbulkpipe(dev->usbdev,
+ _AU0828_BULKPIPE),
purb->transfer_buffer,
URB_BUFSIZE,
urb_completion,
@@ -339,14 +381,12 @@ int au0828_dvb_register(struct au0828_dev *dev)
switch (dev->board) {
case AU0828_BOARD_HAUPPAUGE_HVR850:
case AU0828_BOARD_HAUPPAUGE_HVR950Q:
- case AU0828_BOARD_DVICO_FUSIONHDTV7:
dvb->frontend = dvb_attach(au8522_attach,
&hauppauge_hvr950q_config,
&dev->i2c_adap);
if (dvb->frontend != NULL)
- dvb_attach(xc5000_attach, dvb->frontend,
- &dev->i2c_adap,
- &hauppauge_hvr950q_tunerconfig, dev);
+ dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap,
+ &hauppauge_hvr950q_tunerconfig);
break;
case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
dvb->frontend = dvb_attach(au8522_attach,
@@ -357,6 +397,25 @@ int au0828_dvb_register(struct au0828_dev *dev)
&dev->i2c_adap, 0x60,
&mxl5007t_hvr950q_config);
break;
+ case AU0828_BOARD_HAUPPAUGE_WOODBURY:
+ dvb->frontend = dvb_attach(au8522_attach,
+ &hauppauge_woodbury_config,
+ &dev->i2c_adap);
+ if (dvb->frontend != NULL)
+ dvb_attach(tda18271_attach, dvb->frontend,
+ 0x60, &dev->i2c_adap,
+ &hauppauge_woodbury_tunerconfig);
+ break;
+ case AU0828_BOARD_DVICO_FUSIONHDTV7:
+ dvb->frontend = dvb_attach(au8522_attach,
+ &fusionhdtv7usb_config,
+ &dev->i2c_adap);
+ if (dvb->frontend != NULL) {
+ dvb_attach(xc5000_attach, dvb->frontend,
+ &dev->i2c_adap,
+ &hauppauge_hvr950q_tunerconfig);
+ }
+ break;
default:
printk(KERN_WARNING "The frontend of your DVB/ATSC card "
"isn't supported yet\n");
@@ -367,6 +426,8 @@ int au0828_dvb_register(struct au0828_dev *dev)
__func__);
return -1;
}
+ /* define general-purpose callback pointer */
+ dvb->frontend->callback = au0828_tuner_callback;
/* register everything */
ret = dvb_register(dev);
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
index 741a4937b05..d618fbaade1 100644
--- a/drivers/media/video/au0828/au0828-i2c.c
+++ b/drivers/media/video/au0828/au0828-i2c.c
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek AU0828 USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
index 39827550891..1e87fa0c684 100644
--- a/drivers/media/video/au0828/au0828-reg.h
+++ b/drivers/media/video/au0828/au0828-reg.h
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 7beb571798e..9d6a1161dc9 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -1,7 +1,7 @@
/*
* Driver for the Auvitek AU0828 USB bridge
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -103,7 +103,8 @@ extern int au0828_debug;
extern struct au0828_board au0828_boards[];
extern struct usb_device_id au0828_usb_id_table[];
extern void au0828_gpio_setup(struct au0828_dev *dev);
-extern int au0828_tuner_callback(void *priv, int command, int arg);
+extern int au0828_tuner_callback(void *priv, int component,
+ int command, int arg);
extern void au0828_card_setup(struct au0828_dev *dev);
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index ddd2a7964de..a07b7b88e5b 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -29,44 +29,25 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(s) (s)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
struct bt819 {
@@ -97,14 +78,9 @@ static struct timing timing_data[] = {
{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
};
-#define I2C_BT819 0x8a
-
/* ----------------------------------------------------------------------- */
-static inline int
-bt819_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value)
{
struct bt819 *decoder = i2c_get_clientdata(client);
@@ -112,24 +88,15 @@ bt819_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline int
-bt819_setbit (struct i2c_client *client,
- u8 reg,
- u8 bit,
- u8 value)
+static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
{
struct bt819 *decoder = i2c_get_clientdata(client);
return bt819_write(client, reg,
- (decoder->
- reg[reg] & ~(1 << bit)) |
- (value ? (1 << bit) : 0));
+ (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
}
-static int
-bt819_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -150,10 +117,9 @@ bt819_write_block (struct i2c_client *client,
decoder->reg[reg++] = data[1];
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
@@ -169,20 +135,17 @@ bt819_write_block (struct i2c_client *client,
return ret;
}
-static inline int
-bt819_read (struct i2c_client *client,
- u8 reg)
+static inline int bt819_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
-static int
-bt819_init (struct i2c_client *client)
+static int bt819_init(struct i2c_client *client)
{
struct bt819 *decoder = i2c_get_clientdata(client);
static unsigned char init[] = {
- //0x1f, 0x00, /* Reset */
+ /*0x1f, 0x00,*/ /* Reset */
0x01, 0x59, /* 0x01 input format */
0x02, 0x00, /* 0x02 temporal decimation */
0x03, 0x12, /* 0x03 Cropping msb */
@@ -218,12 +181,10 @@ bt819_init (struct i2c_client *client)
struct timing *timing = &timing_data[decoder->norm];
init[0x03 * 2 - 1] =
- (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
- vactive >> 8) &
- 0x03) << 4) |
- (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
- hactive >> 8) &
- 0x03);
+ (((timing->vdelay >> 8) & 0x03) << 6) |
+ (((timing->vactive >> 8) & 0x03) << 4) |
+ (((timing->hdelay >> 8) & 0x03) << 2) |
+ ((timing->hactive >> 8) & 0x03);
init[0x04 * 2 - 1] = timing->vdelay & 0xff;
init[0x05 * 2 - 1] = timing->vactive & 0xff;
init[0x06 * 2 - 1] = timing->hdelay & 0xff;
@@ -238,27 +199,22 @@ bt819_init (struct i2c_client *client)
/* init */
return bt819_write_block(client, init, sizeof(init));
-
}
/* ----------------------------------------------------------------------- */
-static int
-bt819_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
{
int temp;
struct bt819 *decoder = i2c_get_clientdata(client);
- if (!decoder->initialized) { // First call to bt819_init could be
- bt819_init(client); // without #FRST = 0
+ if (!decoder->initialized) { /* First call to bt819_init could be */
+ bt819_init(client); /* without #FRST = 0 */
decoder->initialized = 1;
}
switch (cmd) {
-
case 0:
/* This is just for testing!!! */
bt819_init(client);
@@ -274,8 +230,8 @@ bt819_command (struct i2c_client *client,
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
- }
break;
+ }
case DECODER_GET_STATUS:
{
@@ -285,9 +241,9 @@ bt819_command (struct i2c_client *client,
status = bt819_read(client, 0x00);
res = 0;
- if ((status & 0x80)) {
+ if ((status & 0x80))
res |= DECODER_STATUS_GOOD;
- }
+
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
res |= DECODER_STATUS_NTSC;
@@ -297,28 +253,25 @@ bt819_command (struct i2c_client *client,
break;
default:
case VIDEO_MODE_AUTO:
- if ((status & 0x10)) {
+ if ((status & 0x10))
res |= DECODER_STATUS_PAL;
- } else {
+ else
res |= DECODER_STATUS_NTSC;
- }
break;
}
res |= DECODER_STATUS_COLOR;
*iarg = res;
- dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
- *iarg);
- }
+ v4l_dbg(1, debug, client, "get status %x\n", *iarg);
break;
+ }
case DECODER_SET_NORM:
{
int *iarg = arg;
struct timing *timing = NULL;
- dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set norm %x\n", *iarg);
switch (*iarg) {
case VIDEO_MODE_NTSC:
@@ -327,7 +280,7 @@ bt819_command (struct i2c_client *client,
bt819_setbit(client, 0x01, 5, 0);
bt819_write(client, 0x18, 0x68);
bt819_write(client, 0x19, 0x5d);
- //bt819_setbit(client, 0x1a, 5, 1);
+ /* bt819_setbit(client, 0x1a, 5, 1); */
timing = &timing_data[VIDEO_MODE_NTSC];
break;
case VIDEO_MODE_PAL:
@@ -336,7 +289,7 @@ bt819_command (struct i2c_client *client,
bt819_setbit(client, 0x01, 5, 1);
bt819_write(client, 0x18, 0x7f);
bt819_write(client, 0x19, 0x72);
- //bt819_setbit(client, 0x1a, 5, 0);
+ /* bt819_setbit(client, 0x1a, 5, 0); */
timing = &timing_data[VIDEO_MODE_PAL];
break;
case VIDEO_MODE_AUTO:
@@ -344,10 +297,7 @@ bt819_command (struct i2c_client *client,
bt819_setbit(client, 0x01, 1, 0);
break;
default:
- dprintk(1,
- KERN_ERR
- "%s: unsupported norm %d\n",
- I2C_NAME(client), *iarg);
+ v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg);
return -EINVAL;
}
@@ -366,19 +316,17 @@ bt819_command (struct i2c_client *client,
}
decoder->norm = *iarg;
- }
break;
+ }
case DECODER_SET_INPUT:
{
int *iarg = arg;
- dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set input %x\n", *iarg);
- if (*iarg < 0 || *iarg > 7) {
+ if (*iarg < 0 || *iarg > 7)
return -EINVAL;
- }
if (decoder->input != *iarg) {
decoder->input = *iarg;
@@ -391,52 +339,42 @@ bt819_command (struct i2c_client *client,
bt819_setbit(client, 0x1a, 1, 0);
}
}
- }
break;
+ }
case DECODER_SET_OUTPUT:
{
int *iarg = arg;
- dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set output %x\n", *iarg);
/* not much choice of outputs */
- if (*iarg != 0) {
+ if (*iarg != 0)
return -EINVAL;
- }
- }
break;
+ }
case DECODER_ENABLE_OUTPUT:
{
int *iarg = arg;
int enable = (*iarg != 0);
- dprintk(1, KERN_INFO "%s: enable output %x\n",
- I2C_NAME(client), *iarg);
+ v4l_dbg(1, debug, client, "enable output %x\n", *iarg);
if (decoder->enable != enable) {
decoder->enable = enable;
-
- if (decoder->enable) {
- bt819_setbit(client, 0x16, 7, 0);
- } else {
- bt819_setbit(client, 0x16, 7, 1);
- }
+ bt819_setbit(client, 0x16, 7, !enable);
}
- }
break;
+ }
case DECODER_SET_PICTURE:
{
struct video_picture *pic = arg;
- dprintk(1,
- KERN_INFO
- "%s: set picture brightness %d contrast %d colour %d\n",
- I2C_NAME(client), pic->brightness, pic->contrast,
- pic->colour);
+ v4l_dbg(1, debug, client,
+ "set picture brightness %d contrast %d colour %d\n",
+ pic->brightness, pic->contrast, pic->colour);
if (decoder->bright != pic->brightness) {
@@ -474,8 +412,8 @@ bt819_command (struct i2c_client *client,
bt819_write(client, 0x0f,
128 - (decoder->hue >> 8));
}
- }
break;
+ }
default:
return -EINVAL;
@@ -486,55 +424,44 @@ bt819_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = {
- I2C_BT819 >> 1,
- I2C_CLIENT_END,
-};
-
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END };
-static struct i2c_driver i2c_driver_bt819;
+I2C_CLIENT_INSMOD;
-static int
-bt819_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int bt819_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- int i, id;
+ int i, ver;
struct bt819 *decoder;
- struct i2c_client *client;
-
- dprintk(1,
- KERN_INFO
- "bt819: detecting bt819 client on address 0x%x\n",
- address << 1);
+ const char *name;
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_bt819;
+ ver = bt819_read(client, 0x17);
+ switch (ver & 0xf0) {
+ case 0x70:
+ name = "bt819a";
+ break;
+ case 0x60:
+ name = "bt817a";
+ break;
+ case 0x20:
+ name = "bt815a";
+ break;
+ default:
+ v4l_dbg(1, debug, client,
+ "unknown chip version 0x%02x\n", ver);
+ return -ENODEV;
+ }
+
+ v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+ client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
- if (decoder == NULL) {
- kfree(client);
+ if (decoder == NULL)
return -ENOMEM;
- }
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
@@ -545,97 +472,33 @@ bt819_detect_client (struct i2c_adapter *adapter,
decoder->initialized = 0;
i2c_set_clientdata(client, decoder);
- id = bt819_read(client, 0x17);
- switch (id & 0xf0) {
- case 0x70:
- strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
- break;
- case 0x60:
- strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
- break;
- case 0x20:
- strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
- break;
- default:
- dprintk(1,
- KERN_ERR
- "bt819: unknown chip version 0x%x (ver 0x%x)\n",
- id & 0xf0, id & 0x0f);
- kfree(decoder);
- kfree(client);
- return 0;
- }
-
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(decoder);
- return i;
- }
-
i = bt819_init(client);
- if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach: init status %d\n",
- I2C_NAME(client), i);
- } else {
- dprintk(1,
- KERN_INFO
- "%s_attach: chip version 0x%x at address 0x%x\n",
- I2C_NAME(client), id & 0x0f,
- client->addr << 1);
- }
-
+ if (i < 0)
+ v4l_dbg(1, debug, client, "init status %d\n", i);
return 0;
}
-static int
-bt819_attach_adapter (struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, &bt819_detect_client);
-}
-
-static int
-bt819_detach_client (struct i2c_client *client)
+static int bt819_remove(struct i2c_client *client)
{
- struct bt819 *decoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(decoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_bt819 = {
- .driver = {
- .name = "bt819",
- },
-
- .id = I2C_DRIVERID_BT819,
+static const struct i2c_device_id bt819_id[] = {
+ { "bt819a", 0 },
+ { "bt817a", 0 },
+ { "bt815a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bt819_id);
- .attach_adapter = bt819_attach_adapter,
- .detach_client = bt819_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "bt819",
+ .driverid = I2C_DRIVERID_BT819,
.command = bt819_command,
+ .probe = bt819_probe,
+ .remove = bt819_remove,
+ .id_table = bt819_id,
};
-
-static int __init
-bt819_init_module (void)
-{
- return i2c_add_driver(&i2c_driver_bt819);
-}
-
-static void __exit
-bt819_exit (void)
-{
- i2c_del_driver(&i2c_driver_bt819);
-}
-
-module_init(bt819_init_module);
-module_exit(bt819_exit);
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 98ee2d8feb3..4213867507f 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -29,47 +29,28 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/video_encoder.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
+#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(s) (s)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
-#define REG_OFFSET 0xDA
-#define BT856_NR_REG 6
+#define BT856_REG_OFFSET 0xDA
+#define BT856_NR_REG 6
struct bt856 {
unsigned char reg[BT856_NR_REG];
@@ -78,61 +59,46 @@ struct bt856 {
int enable;
};
-#define I2C_BT856 0x88
-
/* ----------------------------------------------------------------------- */
-static inline int
-bt856_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value)
{
struct bt856 *encoder = i2c_get_clientdata(client);
- encoder->reg[reg - REG_OFFSET] = value;
+ encoder->reg[reg - BT856_REG_OFFSET] = value;
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline int
-bt856_setbit (struct i2c_client *client,
- u8 reg,
- u8 bit,
- u8 value)
+static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
{
struct bt856 *encoder = i2c_get_clientdata(client);
return bt856_write(client, reg,
- (encoder->
- reg[reg - REG_OFFSET] & ~(1 << bit)) |
- (value ? (1 << bit) : 0));
+ (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
+ (value ? (1 << bit) : 0));
}
-static void
-bt856_dump (struct i2c_client *client)
+static void bt856_dump(struct i2c_client *client)
{
int i;
struct bt856 *encoder = i2c_get_clientdata(client);
- printk(KERN_INFO "%s: register dump:", I2C_NAME(client));
+ v4l_info(client, "register dump:\n");
for (i = 0; i < BT856_NR_REG; i += 2)
- printk(" %02x", encoder->reg[i]);
- printk("\n");
+ printk(KERN_CONT " %02x", encoder->reg[i]);
+ printk(KERN_CONT "\n");
}
/* ----------------------------------------------------------------------- */
-static int
-bt856_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct bt856 *encoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
/* This is just for testing!!! */
- dprintk(1, KERN_INFO "bt856: init\n");
+ v4l_dbg(1, debug, client, "init\n");
bt856_write(client, 0xdc, 0x18);
bt856_write(client, 0xda, 0);
bt856_write(client, 0xde, 0);
@@ -142,7 +108,6 @@ bt856_command (struct i2c_client *client,
bt856_setbit(client, 0xdc, 4, 1);
switch (encoder->norm) {
-
case VIDEO_MODE_NTSC:
bt856_setbit(client, 0xdc, 2, 0);
break;
@@ -163,26 +128,23 @@ bt856_command (struct i2c_client *client,
{
struct video_encoder_capability *cap = arg;
- dprintk(1, KERN_INFO "%s: get capabilities\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "get capabilities\n");
cap->flags = VIDEO_ENCODER_PAL |
VIDEO_ENCODER_NTSC |
VIDEO_ENCODER_CCIR;
cap->inputs = 2;
cap->outputs = 1;
- }
break;
+ }
case ENCODER_SET_NORM:
{
int *iarg = arg;
- dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
switch (*iarg) {
-
case VIDEO_MODE_NTSC:
bt856_setbit(client, 0xdc, 2, 0);
break;
@@ -195,27 +157,23 @@ bt856_command (struct i2c_client *client,
default:
return -EINVAL;
-
}
encoder->norm = *iarg;
if (debug != 0)
bt856_dump(client);
- }
break;
+ }
case ENCODER_SET_INPUT:
{
int *iarg = arg;
- dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set input %d\n", *iarg);
/* We only have video bus.
* iarg = 0: input is from bt819
* iarg = 1: input is from ZR36060 */
-
switch (*iarg) {
-
case 0:
bt856_setbit(client, 0xde, 4, 0);
bt856_setbit(client, 0xde, 3, 1);
@@ -234,27 +192,24 @@ bt856_command (struct i2c_client *client,
break;
default:
return -EINVAL;
-
}
if (debug != 0)
bt856_dump(client);
- }
break;
+ }
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
- dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client),
- *iarg);
+ v4l_dbg(1, debug, client, "set output %d\n", *iarg);
/* not much choice of outputs */
- if (*iarg != 0) {
+ if (*iarg != 0)
return -EINVAL;
- }
- }
break;
+ }
case ENCODER_ENABLE_OUTPUT:
{
@@ -262,10 +217,9 @@ bt856_command (struct i2c_client *client,
encoder->enable = !!*iarg;
- dprintk(1, KERN_INFO "%s: enable output %d\n",
- I2C_NAME(client), encoder->enable);
- }
+ v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
break;
+ }
default:
return -EINVAL;
@@ -276,64 +230,29 @@ bt856_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
-
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-static struct i2c_driver i2c_driver_bt856;
+I2C_CLIENT_INSMOD;
-static int
-bt856_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int bt856_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- int i;
- struct i2c_client *client;
struct bt856 *encoder;
- dprintk(1,
- KERN_INFO
- "bt856.c: detecting bt856 client on address 0x%x\n",
- address << 1);
-
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_bt856;
- strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
- if (encoder == NULL) {
- kfree(client);
+ if (encoder == NULL)
return -ENOMEM;
- }
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(encoder);
- return i;
- }
-
bt856_write(client, 0xdc, 0x18);
bt856_write(client, 0xda, 0);
bt856_write(client, 0xde, 0);
@@ -359,65 +278,26 @@ bt856_detect_client (struct i2c_adapter *adapter,
if (debug != 0)
bt856_dump(client);
-
- dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client),
- client->addr << 1);
-
return 0;
}
-static int
-bt856_attach_adapter (struct i2c_adapter *adapter)
+static int bt856_remove(struct i2c_client *client)
{
- dprintk(1,
- KERN_INFO
- "bt856.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &bt856_detect_client);
-}
-
-static int
-bt856_detach_client (struct i2c_client *client)
-{
- struct bt856 *encoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(encoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver i2c_driver_bt856 = {
- .driver = {
- .name = "bt856",
- },
-
- .id = I2C_DRIVERID_BT856,
+static const struct i2c_device_id bt856_id[] = {
+ { "bt856", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bt856_id);
- .attach_adapter = bt856_attach_adapter,
- .detach_client = bt856_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "bt856",
+ .driverid = I2C_DRIVERID_BT856,
.command = bt856_command,
+ .probe = bt856_probe,
+ .remove = bt856_remove,
+ .id_table = bt856_id,
};
-
-static int __init
-bt856_init (void)
-{
- return i2c_add_driver(&i2c_driver_bt856);
-}
-
-static void __exit
-bt856_exit (void)
-{
- i2c_del_driver(&i2c_driver_bt856);
-}
-
-module_init(bt856_init);
-module_exit(bt856_exit);
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index 96b415576f0..596f9e2376b 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -29,42 +29,28 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
#include <linux/i2c.h>
-
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
-
#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
+MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");
-#define BT866_DEVNAME "bt866"
-#define I2C_BT866 0x88
-
-MODULE_LICENSE("GPL");
-
-#define DEBUG(x) /* Debug driver */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* ----------------------------------------------------------------------- */
struct bt866 {
- struct i2c_client *i2c;
- int addr;
- unsigned char reg[256];
+ u8 reg[256];
int norm;
int enable;
@@ -74,20 +60,45 @@ struct bt866 {
int sat;
};
-static int bt866_write(struct bt866 *dev,
- unsigned char subaddr, unsigned char data);
+static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data)
+{
+ struct bt866 *encoder = i2c_get_clientdata(client);
+ u8 buffer[2];
+ int err;
+
+ buffer[0] = subaddr;
+ buffer[1] = data;
+
+ encoder->reg[subaddr] = data;
+
+ v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
+
+ for (err = 0; err < 3;) {
+ if (i2c_master_send(client, buffer, 2) == 2)
+ break;
+ err++;
+ v4l_warn(client, "error #%d writing to 0x%02x\n",
+ err, subaddr);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
+ }
+ if (err == 3) {
+ v4l_warn(client, "giving up\n");
+ return -1;
+ }
+
+ return 0;
+}
-static int bt866_do_command(struct bt866 *encoder,
- unsigned int cmd, void *arg)
+static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
{
+ struct bt866 *encoder = i2c_get_clientdata(client);
+
switch (cmd) {
case ENCODER_GET_CAPABILITIES:
{
struct video_encoder_capability *cap = arg;
- DEBUG(printk
- (KERN_INFO "%s: get capabilities\n",
- encoder->i2c->name));
+ v4l_dbg(1, debug, client, "get capabilities\n");
cap->flags
= VIDEO_ENCODER_PAL
@@ -95,18 +106,16 @@ static int bt866_do_command(struct bt866 *encoder,
| VIDEO_ENCODER_CCIR;
cap->inputs = 2;
cap->outputs = 1;
+ break;
}
- break;
case ENCODER_SET_NORM:
{
int *iarg = arg;
- DEBUG(printk(KERN_INFO "%s: set norm %d\n",
- encoder->i2c->name, *iarg));
+ v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
switch (*iarg) {
-
case VIDEO_MODE_NTSC:
break;
@@ -115,11 +124,10 @@ static int bt866_do_command(struct bt866 *encoder,
default:
return -EINVAL;
-
}
encoder->norm = *iarg;
+ break;
}
- break;
case ENCODER_SET_INPUT:
{
@@ -155,7 +163,7 @@ static int bt866_do_command(struct bt866 *encoder,
u8 val;
for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
- bt866_write(encoder, init[i], init[i+1]);
+ bt866_write(client, init[i], init[i+1]);
val = encoder->reg[0xdc];
@@ -164,17 +172,16 @@ static int bt866_do_command(struct bt866 *encoder,
else
val &= ~0x40; /* !CBSWAP */
- bt866_write(encoder, 0xdc, val);
+ bt866_write(client, 0xdc, val);
val = encoder->reg[0xcc];
if (*iarg == 2)
val |= 0x01; /* OSDBAR */
else
val &= ~0x01; /* !OSDBAR */
- bt866_write(encoder, 0xcc, val);
+ bt866_write(client, 0xcc, val);
- DEBUG(printk(KERN_INFO "%s: set input %d\n",
- encoder->i2c->name, *iarg));
+ v4l_dbg(1, debug, client, "set input %d\n", *iarg);
switch (*iarg) {
case 0:
@@ -183,48 +190,44 @@ static int bt866_do_command(struct bt866 *encoder,
break;
default:
return -EINVAL;
-
}
+ break;
}
- break;
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
- DEBUG(printk(KERN_INFO "%s: set output %d\n",
- encoder->i2c->name, *iarg));
+ v4l_dbg(1, debug, client, "set output %d\n", *iarg);
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
+ break;
}
- break;
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
- DEBUG(printk
- (KERN_INFO "%s: enable output %d\n",
- encoder->i2c->name, encoder->enable));
+ v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
+ break;
}
- break;
case 4711:
{
int *iarg = arg;
__u8 val;
- printk("bt866: square = %d\n", *iarg);
+ v4l_dbg(1, debug, client, "square %d\n", *iarg);
val = encoder->reg[0xdc];
if (*iarg)
val |= 1; /* SQUARE */
else
val &= ~1; /* !SQUARE */
- bt866_write(encoder, 0xdc, val);
+ bt866_write(client, 0xdc, val);
break;
}
@@ -235,141 +238,49 @@ static int bt866_do_command(struct bt866 *encoder,
return 0;
}
-static int bt866_write(struct bt866 *encoder,
- unsigned char subaddr, unsigned char data)
-{
- unsigned char buffer[2];
- int err;
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
- buffer[0] = subaddr;
- buffer[1] = data;
-
- encoder->reg[subaddr] = data;
+I2C_CLIENT_INSMOD;
- DEBUG(printk
- ("%s: write 0x%02X = 0x%02X\n",
- encoder->i2c->name, subaddr, data));
-
- for (err = 0; err < 3;) {
- if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
- break;
- err++;
- printk(KERN_WARNING "%s: I/O error #%d "
- "(write 0x%02x/0x%02x)\n",
- encoder->i2c->name, err, encoder->addr, subaddr);
- schedule_timeout_interruptible(msecs_to_jiffies(100));
- }
- if (err == 3) {
- printk(KERN_WARNING "%s: giving up\n",
- encoder->i2c->name);
- return -1;
- }
-
- return 0;
-}
-
-static int bt866_attach(struct i2c_adapter *adapter);
-static int bt866_detach(struct i2c_client *client);
-static int bt866_command(struct i2c_client *client,
- unsigned int cmd, void *arg);
-
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END};
-static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
-static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
-
-static struct i2c_client_address_data addr_data = {
- normal_i2c,
- probe,
- ignore,
-};
-
-static struct i2c_driver i2c_driver_bt866 = {
- .driver.name = BT866_DEVNAME,
- .id = I2C_DRIVERID_BT866,
- .attach_adapter = bt866_attach,
- .detach_client = bt866_detach,
- .command = bt866_command
-};
-
-
-static struct i2c_client bt866_client_tmpl =
-{
- .name = "(nil)",
- .addr = 0,
- .adapter = NULL,
- .driver = &i2c_driver_bt866,
-};
-
-static int bt866_found_proc(struct i2c_adapter *adapter,
- int addr, int kind)
+static int bt866_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct bt866 *encoder;
- struct i2c_client *client;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &bt866_client_tmpl, sizeof(*client));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
- if (encoder == NULL) {
- kfree(client);
+ if (encoder == NULL)
return -ENOMEM;
- }
i2c_set_clientdata(client, encoder);
- client->adapter = adapter;
- client->addr = addr;
- sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
-
- encoder->i2c = client;
- encoder->addr = addr;
- //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
-
- /* initialize */
-
- i2c_attach_client(client);
-
- return 0;
-}
-
-static int bt866_attach(struct i2c_adapter *adapter)
-{
- if (adapter->id == I2C_HW_B_ZR36067)
- return i2c_probe(adapter, &addr_data, bt866_found_proc);
- return 0;
-}
-
-static int bt866_detach(struct i2c_client *client)
-{
- struct bt866 *encoder = i2c_get_clientdata(client);
-
- i2c_detach_client(client);
- kfree(encoder);
- kfree(client);
-
return 0;
}
-static int bt866_command(struct i2c_client *client,
- unsigned int cmd, void *arg)
+static int bt866_remove(struct i2c_client *client)
{
- struct bt866 *encoder = i2c_get_clientdata(client);
- return bt866_do_command(encoder, cmd, arg);
-}
-
-static int __devinit bt866_init(void)
-{
- i2c_add_driver(&i2c_driver_bt866);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-static void __devexit bt866_exit(void)
+static int bt866_legacy_probe(struct i2c_adapter *adapter)
{
- i2c_del_driver(&i2c_driver_bt866);
+ return adapter->id == I2C_HW_B_ZR36067;
}
-module_init(bt866_init);
-module_exit(bt866_exit);
+static const struct i2c_device_id bt866_id[] = {
+ { "bt866", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bt866_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "bt866",
+ .driverid = I2C_DRIVERID_BT866,
+ .command = bt866_command,
+ .probe = bt866_probe,
+ .remove = bt866_remove,
+ .legacy_probe = bt866_legacy_probe,
+ .id_table = bt866_id,
+};
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 1c56ae92ce7..13742b0bbe3 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -305,7 +305,7 @@ static struct CARD {
{ 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "},
{ 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" },
{ 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" },
-
+ { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" },
{ 0, -1, NULL }
};
@@ -3037,6 +3037,31 @@ struct tvcard bttv_tvcards[] = {
.has_radio = 1,
.has_remote = 1,
},
+ [BTTV_BOARD_ENLTV_FM_2] = {
+ /* Encore TV Tuner Pro ENL TV-FM-2
+ Mauro Carvalho Chehab <mchehab@infradead.org */
+ .name = "Encore ENL TV-FM-2",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ /* bit 6 -> IR disabled
+ bit 18/17 = 00 -> mute
+ 01 -> enable external audio input
+ 10 -> internal audio input (mono?)
+ 11 -> internal audio input
+ */
+ .gpiomask = 0x060040,
+ .muxsel = { 2, 3, 3 },
+ .gpiomux = { 0x60000, 0x60000, 0x20000, 0x20000 },
+ .gpiomute = 0,
+ .tuner_type = TUNER_TCL_MF02GIP_5N,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .has_radio = 1,
+ .has_remote = 1,
+ }
};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3144,8 +3169,9 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
static void flyvideo_gpio(struct bttv *btv)
{
- int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
- int tuner=UNSET,ttype;
+ int gpio, has_remote, has_radio, is_capture_only;
+ int is_lr90, has_tda9820_tda9821;
+ int tuner_type = UNSET, ttype;
gpio_inout(0xffffff, 0);
udelay(8); /* without this we would see the 0x1800 mask */
@@ -3163,20 +3189,26 @@ static void flyvideo_gpio(struct bttv *btv)
* xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
* Note: Some bits are Audio_Mask !
*/
- ttype=(gpio&0x0f0000)>>16;
- switch(ttype) {
- case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
+ ttype = (gpio & 0x0f0000) >> 16;
+ switch (ttype) {
+ case 0x0:
+ tuner_type = 2; /* NTSC, e.g. TPI8NSR11P */
break;
- case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
+ case 0x2:
+ tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
break;
- case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
+ case 0x4:
+ tuner_type = 5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
break;
- case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
+ case 0x6:
+ tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
break;
- case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
+ case 0xC:
+ tuner_type = 3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+ break;
}
has_remote = gpio & 0x800000;
@@ -3189,23 +3221,26 @@ static void flyvideo_gpio(struct bttv *btv)
/*
* gpio & 0x001000 output bit for audio routing */
- if(is_capture_only)
- tuner = TUNER_ABSENT; /* No tuner present */
+ if (is_capture_only)
+ tuner_type = TUNER_ABSENT; /* No tuner present */
printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
- btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
+ btv->c.nr, has_radio ? "yes" : "no ",
+ has_remote ? "yes" : "no ", tuner_type, gpio);
printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
- btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
- is_capture_only?"yes":"no ");
+ btv->c.nr, is_lr90 ? "yes" : "no ",
+ has_tda9820_tda9821 ? "yes" : "no ",
+ is_capture_only ? "yes" : "no ");
- if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */
- btv->tuner_type = tuner;
+ if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
+ btv->tuner_type = tuner_type;
btv->has_radio = has_radio;
/* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
* LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
* Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
- if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio;
+ if (has_tda9820_tda9821)
+ btv->audio_mode_gpio = lt9415_audio;
/* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
}
@@ -3962,7 +3997,7 @@ static int tuner_1_table[] = {
static void __devinit avermedia_eeprom(struct bttv *btv)
{
- int tuner_make,tuner_tv_fm,tuner_format,tuner=0;
+ int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
tuner_make = (eeprom_data[0x41] & 0x7);
tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3;
@@ -3970,24 +4005,24 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
btv->has_remote = (eeprom_data[0x42] & 0x01);
if (tuner_make == 0 || tuner_make == 2)
- if(tuner_format <=0x0a)
- tuner = tuner_0_table[tuner_format];
+ if (tuner_format <= 0x0a)
+ tuner_type = tuner_0_table[tuner_format];
if (tuner_make == 1)
- if(tuner_format <=9)
- tuner = tuner_1_table[tuner_format];
+ if (tuner_format <= 9)
+ tuner_type = tuner_1_table[tuner_format];
if (tuner_make == 4)
- if(tuner_format == 0x09)
- tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
+ if (tuner_format == 0x09)
+ tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
- btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
- if(tuner) {
- btv->tuner_type=tuner;
- printk("%d",tuner);
+ btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
+ if (tuner_type) {
+ btv->tuner_type = tuner_type;
+ printk(KERN_CONT "%d", tuner_type);
} else
- printk("Unknown type");
- printk(" radio:%s remote control:%s\n",
+ printk(KERN_CONT "Unknown type");
+ printk(KERN_CONT " radio:%s remote control:%s\n",
tuner_tv_fm ? "yes" : "no",
btv->has_remote ? "yes" : "no");
}
@@ -4029,7 +4064,8 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
gpio_inout(mask,mask);
gpio_bits(mask,0);
- udelay(2500);
+ mdelay(2);
+ udelay(500);
gpio_bits(mask,mask);
if (bttv_gpio)
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 85bf31ab878..5858bf5ff41 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -76,9 +76,9 @@ static unsigned int gbuffers = 8;
static unsigned int gbufsize = 0x208000;
static unsigned int reset_crop = 1;
-static int video_nr = -1;
-static int radio_nr = -1;
-static int vbi_nr = -1;
+static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
static int debug_latency;
static unsigned int fdsr;
@@ -96,7 +96,6 @@ static unsigned int irq_iswitch;
static unsigned int uv_ratio = 50;
static unsigned int full_luma_range;
static unsigned int coring;
-extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
@@ -109,9 +108,6 @@ module_param(irq_debug, int, 0644);
module_param(debug_latency, int, 0644);
module_param(fdsr, int, 0444);
-module_param(video_nr, int, 0444);
-module_param(radio_nr, int, 0444);
-module_param(vbi_nr, int, 0444);
module_param(gbuffers, int, 0444);
module_param(gbufsize, int, 0444);
module_param(reset_crop, int, 0444);
@@ -131,7 +127,10 @@ module_param(uv_ratio, int, 0444);
module_param(full_luma_range, int, 0444);
module_param(coring, int, 0444);
-module_param_array(radio, int, NULL, 0444);
+module_param_array(radio, int, NULL, 0444);
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+module_param_array(vbi_nr, int, NULL, 0444);
MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
@@ -153,6 +152,9 @@ MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
@@ -1368,7 +1370,7 @@ static void init_irqreg(struct bttv *btv)
(btv->gpioirq ? BT848_INT_GPINT : 0) |
BT848_INT_SCERR |
(fdsr ? BT848_INT_FDSR : 0) |
- BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
+ BT848_INT_RISCI | BT848_INT_OCERR |
BT848_INT_FMTCHG|BT848_INT_HLOCK|
BT848_INT_I2CDONE,
BT848_INT_MASK);
@@ -2662,18 +2664,6 @@ static int bttv_querycap(struct file *file, void *priv,
return 0;
}
-static int bttv_enum_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (0 != f->index)
- return -EINVAL;
-
- f->pixelformat = V4L2_PIX_FMT_GREY;
- strcpy(f->description, "vbi data");
-
- return 0;
-}
-
static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
{
int index = -1, i;
@@ -3228,6 +3218,7 @@ static int bttv_open(struct inode *inode, struct file *file)
dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
+ lock_kernel();
for (i = 0; i < bttv_num; i++) {
if (bttvs[i].video_dev &&
bttvs[i].video_dev->minor == minor) {
@@ -3242,16 +3233,20 @@ static int bttv_open(struct inode *inode, struct file *file)
break;
}
}
- if (NULL == btv)
+ if (NULL == btv) {
+ unlock_kernel();
return -ENODEV;
+ }
dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
btv->c.nr,v4l2_type_names[type]);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
*fh = btv->init;
fh->type = type;
@@ -3271,6 +3266,7 @@ static int bttv_open(struct inode *inode, struct file *file)
sizeof(struct bttv_buffer),
fh);
set_tvnorm(btv,btv->tvnorm);
+ set_input(btv, btv->input, btv->tvnorm);
btv->users++;
@@ -3291,6 +3287,7 @@ static int bttv_open(struct inode *inode, struct file *file)
bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
bttv_field_count(btv);
+ unlock_kernel();
return 0;
}
@@ -3331,6 +3328,10 @@ static int bttv_release(struct inode *inode, struct file *file)
btv->users--;
bttv_field_count(btv);
+
+ if (!btv->users)
+ audio_mute(btv, 1);
+
return 0;
}
@@ -3368,7 +3369,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
.vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
.vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
.vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
- .vidioc_enum_fmt_vbi_cap = bttv_enum_fmt_vbi_cap,
.vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
.vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
@@ -3431,21 +3431,26 @@ static int radio_open(struct inode *inode, struct file *file)
dprintk("bttv: open minor=%d\n",minor);
+ lock_kernel();
for (i = 0; i < bttv_num; i++) {
- if (bttvs[i].radio_dev->minor == minor) {
+ if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {
btv = &bttvs[i];
break;
}
}
- if (NULL == btv)
+ if (NULL == btv) {
+ unlock_kernel();
return -ENODEV;
+ }
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
*fh = btv->init;
v4l2_prio_open(&btv->prio, &fh->prio);
@@ -3458,6 +3463,7 @@ static int radio_open(struct inode *inode, struct file *file)
audio_input(btv,TVAUDIO_INPUT_RADIO);
mutex_unlock(&btv->lock);
+ unlock_kernel();
return 0;
}
@@ -4236,7 +4242,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (NULL == btv->video_dev)
goto err;
- if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
+ if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
+ video_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->c.nr,btv->video_dev->minor & 0x1f);
@@ -4252,7 +4259,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (NULL == btv->vbi_dev)
goto err;
- if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
+ if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
+ vbi_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device vbi%d\n",
btv->c.nr,btv->vbi_dev->minor & 0x1f);
@@ -4263,7 +4271,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
btv->radio_dev = vdev_init(btv, &radio_template, "radio");
if (NULL == btv->radio_dev)
goto err;
- if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
+ if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
+ radio_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device radio%d\n",
btv->c.nr,btv->radio_dev->minor & 0x1f);
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index a38af98f4ca..2f289d981fe 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -28,8 +28,8 @@
#include "bttvp.h"
-static int debug;
-module_param(debug, int, 0644); /* debug level (0,1,2) */
+static int ir_debug;
+module_param(ir_debug, int, 0644);
static int repeat_delay = 500;
module_param(repeat_delay, int, 0644);
static int repeat_period = 33;
@@ -40,6 +40,12 @@ module_param(ir_rc5_remote_gap, int, 0644);
static int ir_rc5_key_timeout = 200;
module_param(ir_rc5_key_timeout, int, 0644);
+#undef dprintk
+#define dprintk(arg...) do { \
+ if (ir_debug >= 1) \
+ printk(arg); \
+} while (0)
+
#define DEVNAME "bttv-input"
/* ---------------------------------------------------------------------- */
@@ -79,6 +85,45 @@ static void ir_handle_key(struct bttv *btv)
}
+static void ir_enltv_handle_key(struct bttv *btv)
+{
+ struct card_ir *ir = btv->remote;
+ u32 gpio, data, keyup;
+
+ /* read gpio value */
+ gpio = bttv_gpio_read(&btv->c);
+
+ /* extract data */
+ data = ir_extract_bits(gpio, ir->mask_keycode);
+
+ /* Check if it is keyup */
+ keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
+
+ if ((ir->last_gpio & 0x7f) != data) {
+ dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+ gpio, data,
+ (gpio & ir->mask_keyup) ? " up" : "up/down");
+
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
+ if (keyup)
+ ir_input_nokey(ir->dev, &ir->ir);
+ } else {
+ if ((ir->last_gpio & 1 << 31) == keyup)
+ return;
+
+ dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+ gpio, data,
+ (gpio & ir->mask_keyup) ? " up" : "down");
+
+ if (keyup)
+ ir_input_nokey(ir->dev, &ir->ir);
+ else
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
+ }
+
+ ir->last_gpio = data | keyup;
+}
+
void bttv_input_irq(struct bttv *btv)
{
struct card_ir *ir = btv->remote;
@@ -92,7 +137,10 @@ static void bttv_input_timer(unsigned long data)
struct bttv *btv = (struct bttv*)data;
struct card_ir *ir = btv->remote;
- ir_handle_key(btv);
+ if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
+ ir_enltv_handle_key(btv);
+ else
+ ir_handle_key(btv);
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
@@ -284,6 +332,14 @@ int bttv_input_init(struct bttv *btv)
ir->mask_keyup = 0x006000;
ir->polling = 50; /* ms */
break;
+ case BTTV_BOARD_ENLTV_FM_2:
+ ir_codes = ir_codes_encore_enltv2;
+ ir->mask_keycode = 0x00fd00;
+ ir->mask_keyup = 0x000080;
+ ir->polling = 1; /* ms */
+ ir->last_gpio = ir_extract_bits(bttv_gpio_read(&btv->c),
+ ir->mask_keycode);
+ break;
}
if (NULL == ir_codes) {
dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 649682aac1a..5b1b8e4c78b 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -244,7 +244,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
const struct bttv_format *fmt, struct bttv_overlay *ov,
int skip_even, int skip_odd)
{
- int dwords,rc,line,maxy,start,end,skip,nskips;
+ int dwords, rc, line, maxy, start, end;
+ unsigned skip, nskips;
struct btcx_skiplist *skips;
__le32 *rp;
u32 ri,ra;
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 6d93d16c96e..46cb90e0985 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -176,7 +176,7 @@
#define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95
#define BTTV_BOARD_GEOVISION_GV600 0x96
#define BTTV_BOARD_KOZUMI_KTV_01C 0x97
-
+#define BTTV_BOARD_ENLTV_FM_2 0x98
/* more card-specific defines */
#define PT2254_L_CHANNEL 0x10
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 08ef54a22c9..b4d940b2e44 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -267,6 +267,11 @@ int bttv_sub_add_device(struct bttv_core *core, char *name);
int bttv_sub_del_devices(struct bttv_core *core);
/* ---------------------------------------------------------- */
+/* bttv-cards.c */
+
+extern int no_overlay;
+
+/* ---------------------------------------------------------- */
/* bttv-driver.c */
/* insmod options */
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index f42701f82e7..ac1b2687a20 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
unsigned int size)
{
__le32 *cpu;
- dma_addr_t dma;
+ dma_addr_t dma = 0;
if (NULL != risc->cpu && risc->size < size)
btcx_riscmem_free(pci,risc);
@@ -184,12 +184,12 @@ btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
}
void
-btcx_calc_skips(int line, int width, unsigned int *maxy,
+btcx_calc_skips(int line, int width, int *maxy,
struct btcx_skiplist *skips, unsigned int *nskips,
const struct v4l2_clip *clips, unsigned int nclips)
{
unsigned int clip,skip;
- int end,maxline;
+ int end, maxline;
skip=0;
maxline = 9999;
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h
index 861bc811282..f8bc6e8e7b5 100644
--- a/drivers/media/video/btcx-risc.h
+++ b/drivers/media/video/btcx-risc.h
@@ -23,7 +23,7 @@ int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
unsigned int n, int mask);
void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
-void btcx_calc_skips(int line, int width, unsigned int *maxy,
+void btcx_calc_skips(int line, int width, int *maxy,
struct btcx_skiplist *skips, unsigned int *nskips,
const struct v4l2_clip *clips, unsigned int nclips);
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index d3b3268bace..ace4ff9ea02 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -495,7 +495,7 @@ static void qc_set(struct qcam_device *q)
val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
q->transfer_scale;
}
- val = (val + val2 - 1) / val2;
+ val = DIV_ROUND_UP(val, val2);
qc_command(q, 0x13);
qc_command(q, val);
@@ -651,7 +651,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
transperline = q->width * q->bpp;
divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
q->transfer_scale;
- transperline = (transperline + divisor - 1) / divisor;
+ transperline = DIV_ROUND_UP(transperline, divisor);
for (i = 0, yield = yieldlines; i < linestotrans; i++)
{
@@ -894,10 +894,27 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len;
}
+static int qcam_exclusive_open(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct qcam_device *qcam = (struct qcam_device *)dev;
+
+ return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+}
+
+static int qcam_exclusive_release(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct qcam_device *qcam = (struct qcam_device *)dev;
+
+ clear_bit(0, &qcam->in_use);
+ return 0;
+}
+
static const struct file_operations qcam_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = qcam_exclusive_open,
+ .release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -909,6 +926,7 @@ static struct video_device qcam_template=
{
.name = "Connectix Quickcam",
.fops = &qcam_fops,
+ .release = video_device_release_empty,
};
#define MAX_CAMS 4
@@ -946,8 +964,7 @@ static int init_bwqcam(struct parport *port)
printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
- if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
- {
+ if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
parport_unregister_device(qcam->pdev);
kfree(qcam);
return -ENODEV;
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h
index 6701dafbc0d..8a60c5de093 100644
--- a/drivers/media/video/bw-qcam.h
+++ b/drivers/media/video/bw-qcam.h
@@ -65,4 +65,5 @@ struct qcam_device {
int top, left;
int status;
unsigned int saved_bits;
+ unsigned long in_use;
};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index fe9379b282d..17aa0adb346 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -51,6 +51,7 @@ struct qcam_device {
int contrast, brightness, whitebal;
int top, left;
unsigned int bidirectional;
+ unsigned long in_use;
struct mutex lock;
};
@@ -687,11 +688,28 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len;
}
+static int qcam_exclusive_open(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct qcam_device *qcam = (struct qcam_device *)dev;
+
+ return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+}
+
+static int qcam_exclusive_release(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct qcam_device *qcam = (struct qcam_device *)dev;
+
+ clear_bit(0, &qcam->in_use);
+ return 0;
+}
+
/* video device template */
static const struct file_operations qcam_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = qcam_exclusive_open,
+ .release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -704,6 +722,7 @@ static struct video_device qcam_template=
{
.name = "Colour QuickCam",
.fops = &qcam_fops,
+ .release = video_device_release_empty,
};
/* Initialize the QuickCam driver control structure. */
@@ -787,8 +806,7 @@ static int init_cqcam(struct parport *port)
parport_release(qcam->pdev);
- if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
- {
+ if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
qcam->pport->name);
parport_unregister_device(qcam->pdev);
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index c149b7d712e..fc9497bdd32 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -1475,9 +1476,12 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
{
struct cafe_camera *cam;
+ lock_kernel();
cam = cafe_find_dev(iminor(inode));
- if (cam == NULL)
+ if (cam == NULL) {
+ unlock_kernel();
return -ENODEV;
+ }
filp->private_data = cam;
mutex_lock(&cam->s_mutex);
@@ -1489,6 +1493,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
}
(cam->users)++;
mutex_unlock(&cam->s_mutex);
+ unlock_kernel();
return 0;
}
@@ -2091,15 +2096,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
- u16 classword;
struct cafe_camera *cam;
- /*
- * Make sure we have a camera here - we'll get calls for
- * the other cafe devices as well.
- */
- pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword);
- if (classword != PCI_CLASS_MULTIMEDIA_VIDEO)
- return -ENODEV;
+
/*
* Start putting together one of our big camera structures.
*/
@@ -2287,8 +2285,8 @@ static int cafe_pci_resume(struct pci_dev *pdev)
static struct pci_device_id cafe_ids[] = {
- { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
- { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
+ PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) },
{ 0, }
};
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index dc8cc6115e2..1798b779a25 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -39,10 +39,6 @@
#include <asm/io.h>
#include <linux/mutex.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "cpia.h"
static int video_nr = -1;
@@ -3155,7 +3151,7 @@ static void put_cam(struct cpia_camera_ops* ops)
static int cpia_open(struct inode *inode, struct file *file)
{
struct video_device *dev = video_devdata(file);
- struct cam_data *cam = dev->priv;
+ struct cam_data *cam = video_get_drvdata(dev);
int err;
if (!cam) {
@@ -3202,7 +3198,7 @@ static int cpia_open(struct inode *inode, struct file *file)
/* Set ownership of /proc/cpia/videoX to current user */
if(cam->proc_entry)
- cam->proc_entry->uid = current->uid;
+ cam->proc_entry->uid = current_uid();
/* set mark for loading first frame uncompressed */
cam->first_frame = 1;
@@ -3232,7 +3228,7 @@ static int cpia_open(struct inode *inode, struct file *file)
static int cpia_close(struct inode *inode, struct file *file)
{
struct video_device *dev = file->private_data;
- struct cam_data *cam = dev->priv;
+ struct cam_data *cam = video_get_drvdata(dev);
if (cam->ops) {
/* Return ownership of /proc/cpia/videoX to root */
@@ -3284,7 +3280,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct video_device *dev = file->private_data;
- struct cam_data *cam = dev->priv;
+ struct cam_data *cam = video_get_drvdata(dev);
int err;
/* make this _really_ smp and multithread-safe */
@@ -3341,7 +3337,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
unsigned int ioctlnr, void *arg)
{
struct video_device *dev = file->private_data;
- struct cam_data *cam = dev->priv;
+ struct cam_data *cam = video_get_drvdata(dev);
int retval = 0;
if (!cam || !cam->ops)
@@ -3739,7 +3735,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long page, pos;
- struct cam_data *cam = dev->priv;
+ struct cam_data *cam = video_get_drvdata(dev);
int retval;
if (!cam || !cam->ops)
@@ -3801,6 +3797,7 @@ static const struct file_operations cpia_fops = {
static struct video_device cpia_template = {
.name = "CPiA Camera",
.fops = &cpia_fops,
+ .release = video_device_release_empty,
};
/* initialise cam_data structure */
@@ -3928,7 +3925,7 @@ static void init_camera_struct(struct cam_data *cam,
cam->proc_entry = NULL;
memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
- cam->vdev.priv = cam;
+ video_set_drvdata(&cam->vdev, cam);
cam->curframe = 0;
for (i = 0; i < FRAME_NUM; i++) {
@@ -3955,7 +3952,7 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve
camera->lowlevel_data = lowlevel;
/* register v4l device */
- if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
kfree(camera);
printk(KERN_DEBUG "video_register_device failed\n");
return NULL;
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
index af8b9ec8e35..7e791b6923f 100644
--- a/drivers/media/video/cpia2/cpia2_core.c
+++ b/drivers/media/video/cpia2/cpia2_core.c
@@ -1537,7 +1537,7 @@ static int config_sensor_500(struct camera_data *cam,
*
* This sets all user changeable properties to the values in cam->params.
*****************************************************************************/
-int set_all_properties(struct camera_data *cam)
+static int set_all_properties(struct camera_data *cam)
{
/**
* Don't set target_kb here, it will be set later.
@@ -1588,7 +1588,7 @@ void cpia2_save_camera_state(struct camera_data *cam)
* get_color_params
*
*****************************************************************************/
-void get_color_params(struct camera_data *cam)
+static void get_color_params(struct camera_data *cam)
{
cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0);
cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0);
@@ -1881,7 +1881,7 @@ void cpia2_set_saturation(struct camera_data *cam, unsigned char value)
* wake_system
*
*****************************************************************************/
-void wake_system(struct camera_data *cam)
+static void wake_system(struct camera_data *cam)
{
cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0);
}
@@ -1892,7 +1892,7 @@ void wake_system(struct camera_data *cam)
*
* Valid for STV500 sensor only
*****************************************************************************/
-void set_lowlight_boost(struct camera_data *cam)
+static void set_lowlight_boost(struct camera_data *cam)
{
struct cpia2_command cmd;
@@ -2169,7 +2169,7 @@ void cpia2_dbg_dump_registers(struct camera_data *cam)
*
* Sets all values to the defaults
*****************************************************************************/
-void reset_camera_struct(struct camera_data *cam)
+static void reset_camera_struct(struct camera_data *cam)
{
/***
* The following parameter values are the defaults from the register map.
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index a4574740350..73511a54207 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -478,7 +478,7 @@ int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
* set_alternate
*
*****************************************************************************/
-int set_alternate(struct camera_data *cam, unsigned int alt)
+static int set_alternate(struct camera_data *cam, unsigned int alt)
{
int ret = 0;
@@ -632,7 +632,7 @@ int cpia2_usb_transfer_cmd(struct camera_data *cam,
static int submit_urbs(struct camera_data *cam)
{
struct urb *urb;
- int fx, err, i;
+ int fx, err, i, j;
for(i=0; i<NUM_SBUF; ++i) {
if (cam->sbuf[i].data)
@@ -657,6 +657,9 @@ static int submit_urbs(struct camera_data *cam)
}
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
+ ERR("%s: usb_alloc_urb error!\n", __func__);
+ for (j = 0; j < i; j++)
+ usb_free_urb(cam->sbuf[j].urb);
return -ENOMEM;
}
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 515c8b57a60..897e8d1a5c3 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -241,8 +241,7 @@ static struct v4l2_queryctrl controls[] = {
*****************************************************************************/
static int cpia2_open(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct camera_data *cam = video_get_drvdata(dev);
+ struct camera_data *cam = video_drvdata(file);
int retval = 0;
if (!cam) {
@@ -357,8 +356,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
loff_t *off)
{
- struct video_device *dev = video_devdata(file);
- struct camera_data *cam = video_get_drvdata(dev);
+ struct camera_data *cam = video_drvdata(file);
int noblock = file->f_flags&O_NONBLOCK;
struct cpia2_fh *fh = file->private_data;
@@ -382,9 +380,7 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
*****************************************************************************/
static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
{
- struct video_device *dev = video_devdata(filp);
- struct camera_data *cam = video_get_drvdata(dev);
-
+ struct camera_data *cam = video_drvdata(filp);
struct cpia2_fh *fh = filp->private_data;
if(!cam)
@@ -1024,7 +1020,6 @@ static int ioctl_queryctrl(void *arg,struct camera_data *cam)
if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){
// Maximum 15fps
- int i;
for(i=0; i<c->maximum; ++i) {
if(framerate_controls[i].value ==
CPIA2_VP_FRAMERATE_15) {
@@ -1580,8 +1575,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
static int cpia2_do_ioctl(struct inode *inode, struct file *file,
unsigned int ioctl_nr, void *arg)
{
- struct video_device *dev = video_devdata(file);
- struct camera_data *cam = video_get_drvdata(dev);
+ struct camera_data *cam = video_drvdata(file);
int retval = 0;
if (!cam)
@@ -1861,9 +1855,8 @@ static int cpia2_ioctl(struct inode *inode, struct file *file,
*****************************************************************************/
static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
{
+ struct camera_data *cam = video_drvdata(file);
int retval;
- struct video_device *dev = video_devdata(file);
- struct camera_data *cam = video_get_drvdata(dev);
/* Priority check */
struct cpia2_fh *fh = file->private_data;
@@ -1959,8 +1952,7 @@ int cpia2_register_camera(struct camera_data *cam)
reset_camera_struct_v4l(cam);
/* register v4l device */
- if (video_register_device
- (cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
ERR("video_register_device failed\n");
video_device_release(cam->vdev);
return -ENODEV;
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
index b23d2e26120..f7bf0edf93f 100644
--- a/drivers/media/video/cx18/Makefile
+++ b/drivers/media/video/cx18/Makefile
@@ -2,7 +2,7 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.
cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
- cx18-dvb.o
+ cx18-dvb.o cx18-io.o
obj-$(CONFIG_VIDEO_CX18) += cx18.o
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
index 6d5b94fc708..57beddf0af4 100644
--- a/drivers/media/video/cx18/cx18-audio.c
+++ b/drivers/media/video/cx18/cx18-audio.c
@@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-i2c.h"
#include "cx18-cards.h"
#include "cx18-audio.h"
@@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx)
if (err)
return err;
- val = read_reg(CX18_AUDIO_ENABLE) & ~0x30;
+ val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
(audio_input << 4);
- write_reg(val | 0xb00, CX18_AUDIO_ENABLE);
+ cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE);
cx18_vapi(cx, CX18_APU_RESETAI, 1, 0);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 3b0a2c45060..73f5141a42d 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -22,27 +22,35 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
{
- u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+ u32 reg = 0xc40000 + (addr & ~3);
u32 mask = 0xff;
int shift = (addr & 3) * 8;
+ u32 x = cx18_read_reg(cx, reg);
x = (x & ~(mask << shift)) | ((u32)value << shift);
- writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
+ cx18_write_reg(cx, x, reg);
return 0;
}
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
{
- writel(value, cx->reg_mem + 0xc40000 + addr);
+ cx18_write_reg(cx, value, 0xc40000 + addr);
+ return 0;
+}
+
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
+{
+ cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
return 0;
}
u8 cx18_av_read(struct cx18 *cx, u16 addr)
{
- u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+ u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
int shift = (addr & 3) * 8;
return (x >> shift) & 0xff;
@@ -50,7 +58,12 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr)
u32 cx18_av_read4(struct cx18 *cx, u16 addr)
{
- return readl(cx->reg_mem + 0xc40000 + addr);
+ return cx18_read_reg(cx, 0xc40000 + addr);
+}
+
+u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr)
+{
+ return cx18_read_reg_noretry(cx, 0xc40000 + addr);
}
int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index eb61fa1e096..b67d8df20cc 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -301,8 +301,10 @@ struct cx18_av_state {
/* cx18_av-core.c */
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
u8 cx18_av_read(struct cx18 *cx, u16 addr);
u32 cx18_av_read4(struct cx18 *cx, u16 addr);
+u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index 834b9248242..522a035b2e8 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include <linux/firmware.h>
#define CX18_AUDIO_ENABLE 0xc72014
@@ -32,7 +33,7 @@ int cx18_av_loadfw(struct cx18 *cx)
u32 v;
const u8 *ptr;
int i;
- int retries = 0;
+ int retries1 = 0;
if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
CX18_ERR("unable to open firmware %s\n", FWFILE);
@@ -41,7 +42,7 @@ int cx18_av_loadfw(struct cx18 *cx)
/* The firmware load often has byte errors, so allow for several
retries, both at byte level and at the firmware load level. */
- while (retries < 5) {
+ while (retries1 < 5) {
cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
@@ -49,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx)
cx18_av_write4(cx, 0x8100, 0x00010000);
/* Put the 8051 in reset and enable firmware upload */
- cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+ cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
ptr = fw->data;
size = fw->size;
@@ -57,30 +58,36 @@ int cx18_av_loadfw(struct cx18 *cx)
for (i = 0; i < size; i++) {
u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
u32 value = 0;
- int retries;
+ int retries2;
+ int unrec_err = 0;
- for (retries = 0; retries < 5; retries++) {
- cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
+ for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES;
+ retries2++) {
+ cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
+ dl_control);
udelay(10);
- value = cx18_av_read4(cx, CXADEC_DL_CTL);
+ value = cx18_av_read4_noretry(cx,
+ CXADEC_DL_CTL);
if (value == dl_control)
break;
/* Check if we can correct the byte by changing
the address. We can only write the lower
address byte of the address. */
if ((value & 0x3F00) != (dl_control & 0x3F00)) {
- retries = 5;
+ unrec_err = 1;
break;
}
}
- if (retries >= 5)
+ cx18_log_write_retries(cx, retries2,
+ cx->reg_mem + 0xc40000 + CXADEC_DL_CTL);
+ if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES)
break;
}
if (i == size)
break;
- retries++;
+ retries1++;
}
- if (retries >= 5) {
+ if (retries1 >= 5) {
CX18_ERR("unable to load firmware %s\n", FWFILE);
release_firmware(fw);
return -EIO;
@@ -119,10 +126,10 @@ int cx18_av_loadfw(struct cx18 *cx)
have a name in the spec. */
cx18_av_write4(cx, 0x09CC, 1);
- v = read_reg(CX18_AUDIO_ENABLE);
- /* If bit 11 is 1 */
+ v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+ /* If bit 11 is 1, clear bit 10 */
if (v & 0x800)
- write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
+ cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE);
/* Enable WW auto audio standard detection */
v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 8fe5f38c4d7..5efe01ebe9d 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = {
},
.audio_inputs = {
{ CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO8, 0 },
+ CX18_AV_AUDIO5, 0 },
{ CX18_CARD_INPUT_LINE_IN1,
CX18_AV_AUDIO_SERIAL1, 0 },
},
@@ -292,12 +292,111 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = {
/* ------------------------------------------------------------------------- */
+/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */
+
+static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = {
+ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 },
+ { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
+ .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT,
+ .name = "Toshiba Qosmio DVB-T/Analog",
+ .comment = "Experimenters and photos needed for device to work well.\n"
+ "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_all = CX18_HW_TUNER,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 },
+ { CX18_CARD_INPUT_SVIDEO1, 1,
+ CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
+ { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 },
+ },
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .ddr = {
+ .chip_config = 0x202,
+ .refresh = 0x3bb,
+ .timing1 = 0x33320a63,
+ .timing2 = 0x0a,
+ .tune_lane = 0,
+ .initial_emrs = 0x42,
+ },
+ .xceive_pin = 15,
+ .pci_list = cx18_pci_toshiba_qosmio_dvbt,
+ .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast PVR2100 */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
+ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 },
+ { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_pvr2100 = {
+ .type = CX18_CARD_LEADTEK_PVR2100,
+ .name = "Leadtek WinFast PVR2100",
+ .comment = "Experimenters and photos needed for device to work well.\n"
+ "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_muxer = CX18_HW_GPIO,
+ .hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },
+ { CX18_CARD_INPUT_SVIDEO1, 1,
+ CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
+ { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 },
+ },
+ .tuners = {
+ /* XC3028 tuner */
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+ .ddr = {
+ /*
+ * Pointer to proper DDR config values provided by
+ * Terry Wu <terrywu at leadtek.com.tw>
+ */
+ .chip_config = 0x303,
+ .refresh = 0x3bb,
+ .timing1 = 0x24220e83,
+ .timing2 = 0x1f,
+ .tune_lane = 0,
+ .initial_emrs = 0x2,
+ },
+ .gpio_init.initial_value = 0x6,
+ .gpio_init.direction = 0x7,
+ .gpio_audio_input = { .mask = 0x7,
+ .tuner = 0x6, .linein = 0x2, .radio = 0x2 },
+ .xceive_pin = 15,
+ .pci_list = cx18_pci_leadtek_pvr2100,
+ .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
static const struct cx18_card *cx18_card_list[] = {
&cx18_card_hvr1600_esmt,
&cx18_card_hvr1600_samsung,
&cx18_card_h900,
&cx18_card_mpc718,
&cx18_card_cnxt_raptor_pal,
+ &cx18_card_toshiba_qosmio_dvbt,
+ &cx18_card_leadtek_pvr2100,
};
const struct cx18_card *cx18_get_card(u16 index)
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 22434aadde3..085121c2b47 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -4,6 +4,7 @@
* Derived from ivtv-driver.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ * Copyright (C) 2008 Andy Walls <awalls@radix.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
@@ -22,6 +23,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-version.h"
#include "cx18-cards.h"
#include "cx18-i2c.h"
@@ -73,10 +75,14 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
-
-static int cardtype_c = 1;
-static int tuner_c = 1;
-static int radio_c = 1;
+static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+static unsigned cardtype_c = 1;
+static unsigned tuner_c = 1;
+static unsigned radio_c = 1;
+static unsigned mmio_ndelay_c = 1;
static char pal[] = "--";
static char secam[] = "--";
static char ntsc[] = "-";
@@ -90,15 +96,18 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
static int cx18_pci_latency = 1;
+int cx18_retry_mmio = 1;
int cx18_debug;
module_param_array(tuner, int, &tuner_c, 0644);
module_param_array(radio, bool, &radio_c, 0644);
module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644);
module_param_string(pal, pal, sizeof(pal), 0644);
module_param_string(secam, secam, sizeof(secam), 0644);
module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
module_param_named(debug, cx18_debug, int, 0644);
+module_param_named(retry_mmio, cx18_retry_mmio, int, 0644);
module_param(cx18_pci_latency, int, 0644);
module_param(cx18_first_minor, int, 0644);
@@ -121,6 +130,8 @@ MODULE_PARM_DESC(cardtype,
"\t\t\t 3 = Compro VideoMate H900\n"
"\t\t\t 4 = Yuan MPC718\n"
"\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
+ "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
+ "\t\t\t 7 = Leadtek WinFast PVR2100\n"
"\t\t\t 0 = Autodetect (default)\n"
"\t\t\t-1 = Ignore this card\n\t\t");
MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -140,6 +151,14 @@ MODULE_PARM_DESC(debug,
MODULE_PARM_DESC(cx18_pci_latency,
"Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
"\t\t\tDefault: Yes");
+MODULE_PARM_DESC(retry_mmio,
+ "Check and retry memory mapped IO accesses\n"
+ "\t\t\tDefault: 1 [Yes]");
+MODULE_PARM_DESC(mmio_ndelay,
+ "Delay (ns) for each CX23418 memory mapped IO access.\n"
+ "\t\t\tTry larger values that are close to a multiple of the\n"
+ "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY));
MODULE_PARM_DESC(enc_mpg_buffers,
"Encoder MPG Buffers (in MB)\n"
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
@@ -156,7 +175,7 @@ MODULE_PARM_DESC(enc_pcm_buffers,
"Encoder PCM buffers (in MB)\n"
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
-MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card");
+MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card");
MODULE_AUTHOR("Hans Verkuil");
MODULE_DESCRIPTION("CX23418 driver");
@@ -356,6 +375,11 @@ static void cx18_process_options(struct cx18 *cx)
cx->options.tuner = tuner[cx->num];
cx->options.radio = radio[cx->num];
+ if (mmio_ndelay[cx->num] < 0)
+ cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY;
+ else
+ cx->options.mmio_ndelay = mmio_ndelay[cx->num];
+
cx->std = cx18_parse_std(cx);
if (cx->options.cardtype == -1) {
CX18_INFO("Ignore card\n");
@@ -395,9 +419,9 @@ done:
if (cx->card == NULL) {
cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
- CX18_ERR("Unknown card: vendor/device: %04x/%04x\n",
+ CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
cx->dev->vendor, cx->dev->device);
- CX18_ERR(" subsystem vendor/device: %04x/%04x\n",
+ CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n",
cx->dev->subsystem_vendor, cx->dev->subsystem_device);
CX18_ERR("Defaulting to %s card\n", cx->card->name);
CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
@@ -511,9 +535,9 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
return -EIO;
}
- /* Check for bus mastering */
+ /* Enable bus mastering and memory mapped IO for the CX23418 */
pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
@@ -525,11 +549,6 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
}
- /* This config space value relates to DMA latencies. The
- default value 0x8080 is too low however and will lead
- to DMA errors. 0xffff is the max value which solves
- these problems. */
- pci_write_config_dword(dev, 0x40, 0xffff);
CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
"irq: %d, latency: %d, memory: 0x%lx\n",
@@ -656,7 +675,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
goto free_mem;
}
cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
- devtype = read_reg(0xC72028);
+ devtype = cx18_read_reg(cx, 0xC72028);
switch (devtype & 0xff000000) {
case 0xff000000:
CX18_INFO("cx23418 revision %08x (A)\n", devtype);
@@ -815,6 +834,7 @@ err:
if (retval == 0)
retval = -ENODEV;
CX18_ERR("Error %d on initialization\n", retval);
+ cx18_log_statistics(cx);
kfree(cx18_cards[cx18_cards_active]);
cx18_cards[cx18_cards_active] = NULL;
@@ -902,8 +922,8 @@ static void cx18_remove(struct pci_dev *pci_dev)
cx18_stop_all_captures(cx);
/* Interrupts */
- sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
- sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+ cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+ cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
cx18_halt_firmware(cx);
@@ -919,6 +939,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
pci_disable_device(cx->dev);
+ cx18_log_statistics(cx);
CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
}
@@ -938,7 +959,7 @@ static int module_start(void)
/* Validate parameters */
if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
- printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n",
+ printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n",
CX18_MAX_CARDS - 1);
return -1;
}
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 4801bc7fb5b..fa8be0731a3 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -38,7 +38,6 @@
#include <linux/i2c-algo-bit.h>
#include <linux/list.h>
#include <linux/unistd.h>
-#include <linux/byteorder/swab.h>
#include <linux/pagemap.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
@@ -64,6 +63,9 @@
# error "This driver requires kernel PCI support."
#endif
+/* Default delay to throttle mmio access to the CX23418 */
+#define CX18_DEFAULT_MMIO_NDELAY 0 /* 0 ns = 0 PCI clock(s) / 33 MHz */
+
#define CX18_MEM_OFFSET 0x00000000
#define CX18_MEM_SIZE 0x04000000
#define CX18_REG_OFFSET 0x02000000
@@ -77,7 +79,9 @@
#define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */
#define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */
#define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */
-#define CX18_CARD_LAST 4
+#define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
+#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LAST 6
#define CX18_ENC_STREAM_TYPE_MPG 0
#define CX18_ENC_STREAM_TYPE_TS 1
@@ -97,6 +101,8 @@
#define CX18_PCI_ID_COMPRO 0x185b
#define CX18_PCI_ID_YUAN 0x12ab
#define CX18_PCI_ID_CONEXANT 0x14f1
+#define CX18_PCI_ID_TOSHIBA 0x1179
+#define CX18_PCI_ID_LEADTEK 0x107D
/* ======================================================================== */
/* ========================== START USER SETTABLE DMA VARIABLES =========== */
@@ -169,6 +175,7 @@
#define CX18_MAX_PGM_INDEX (400)
+extern int cx18_retry_mmio; /* enable check & retry of mmio accesses */
extern int cx18_debug;
@@ -177,6 +184,7 @@ struct cx18_options {
int cardtype; /* force card type on load */
int tuner; /* set tuner on load */
int radio; /* enable/disable radio */
+ unsigned long mmio_ndelay; /* delay in ns after every PCI mmio access */
};
/* per-buffer bit flags */
@@ -216,8 +224,7 @@ struct cx18_buffer {
struct cx18_queue {
struct list_head list;
- u32 buffers;
- u32 length;
+ atomic_t buffers;
u32 bytesused;
};
@@ -237,6 +244,8 @@ struct cx18_dvb {
struct cx18; /* forward reference */
struct cx18_scb; /* forward reference */
+#define CX18_INVALID_TASK_HANDLE 0xffffffff
+
struct cx18_stream {
/* These first four fields are always set, even if the stream
is not actually created. */
@@ -259,7 +268,6 @@ struct cx18_stream {
/* Buffer Stats */
u32 buffers;
u32 buf_size;
- u32 buffers_stolen;
/* Buffer Queues */
struct cx18_queue q_free; /* free buffers */
@@ -341,6 +349,13 @@ struct cx18_i2c_algo_callback_data {
int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
};
+#define CX18_MAX_MMIO_RETRIES 10
+
+struct cx18_mmio_stats {
+ atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1];
+ atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1];
+};
+
/* Struct to hold info about cx18 cards */
struct cx18 {
int num; /* board number, -1 during init! */
@@ -430,6 +445,9 @@ struct cx18 {
u32 gpio_val;
struct mutex gpio_lock;
+ /* Statistics */
+ struct cx18_mmio_stats mmio_stats;
+
/* v4l2 and User settings */
/* codec settings */
@@ -458,47 +476,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
/* First-open initialization: load firmware, etc. */
int cx18_init_on_first_open(struct cx18 *cx);
-/* This is a PCI post thing, where if the pci register is not read, then
- the write doesn't always take effect right away. By reading back the
- register any pending PCI writes will be performed (in order), and so
- you can be sure that the writes are guaranteed to be done.
-
- Rarely needed, only in some timing sensitive cases.
- Apparently if this is not done some motherboards seem
- to kill the firmware and get into the broken state until computer is
- rebooted. */
-#define write_sync(val, reg) \
- do { writel(val, reg); readl(reg); } while (0)
-
-#define read_reg(reg) readl(cx->reg_mem + (reg))
-#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
-#define write_reg_sync(val, reg) \
- do { write_reg(val, reg); read_reg(reg); } while (0)
-
-#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
-#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
-#define write_enc_sync(val, addr) \
- do { write_enc(val, addr); read_enc(addr); } while (0)
-
-#define sw1_irq_enable(val) do { \
- write_reg(val, SW1_INT_STATUS); \
- write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
-} while (0)
-
-#define sw1_irq_disable(val) \
- write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
-
-#define sw2_irq_enable(val) do { \
- write_reg(val, SW2_INT_STATUS); \
- write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
-} while (0)
-
-#define sw2_irq_disable(val) \
- write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
-
-#define setup_page(addr) do { \
- u32 val = read_reg(0xD000F8) & ~0x1f00; \
- write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
-} while (0)
-
#endif /* CX18_DRIVER_H */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index cae38985b13..afc694e7bdb 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -1,7 +1,7 @@
/*
* cx18 functions for DVB support
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
@@ -21,6 +21,7 @@
#include "cx18-version.h"
#include "cx18-dvb.h"
+#include "cx18-io.h"
#include "cx18-streams.h"
#include "cx18-cards.h"
#include "s5h1409.h"
@@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
switch (cx->card->type) {
case CX18_CARD_HVR_1600_ESMT:
case CX18_CARD_HVR_1600_SAMSUNG:
- v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+ v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
v |= 0x00400000; /* Serial Mode */
v |= 0x00002000; /* Data Length - Byte */
v |= 0x00010000; /* Error - Polarity */
v |= 0x00020000; /* Error - Passthru */
v |= 0x000c0000; /* Error - Ignore */
- write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+ cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
break;
default:
diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h
index d6a6ccda79a..bf8d8f6f545 100644
--- a/drivers/media/video/cx18/cx18-dvb.h
+++ b/drivers/media/video/cx18/cx18-dvb.h
@@ -1,7 +1,7 @@
/*
* cx18 functions for DVB support
*
- * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2008 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 1e537fe04a2..5f908990754 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx)
u16 new_stereo_mode;
const u16 stereo_mask = 0x0300;
const u16 dual = 0x0200;
+ u32 h;
new_stereo_mode = cx->params.audio_properties & stereo_mask;
memset(&vt, 0, sizeof(vt));
@@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx)
if (new_stereo_mode == cx->dualwatch_stereo_mode)
return;
- new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+ new_bitmap = new_stereo_mode
+ | (cx->params.audio_properties & ~stereo_mask);
- CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
- cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+ CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
+ "new audio_bitmask=0x%ux\n",
+ cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
- if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
- cx18_find_handle(cx), new_bitmap) == 0) {
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
+ return;
+ }
+
+ if (cx18_vapi(cx,
+ CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
cx->dualwatch_stereo_mode = new_stereo_mode;
return;
}
@@ -223,7 +232,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added
to the waitqueue */
- if (!s->q_full.buffers)
+ if (!atomic_read(&s->q_full.buffers))
schedule();
finish_wait(&s->waitq, &wait);
if (signal_pending(current)) {
@@ -509,7 +518,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
CX18_DEBUG_HI_FILE("Encoder poll\n");
poll_wait(filp, &s->waitq, wait);
- if (s->q_full.length || s->q_io.length)
+ if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers))
return POLLIN | POLLRDNORM;
if (eof)
return POLLHUP;
@@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
void cx18_mute(struct cx18 *cx)
{
- if (atomic_read(&cx->ana_capturing))
- cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
- cx18_find_handle(cx), 1);
+ u32 h;
+ if (atomic_read(&cx->ana_capturing)) {
+ h = cx18_find_handle(cx);
+ if (h != CX18_INVALID_TASK_HANDLE)
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
+ else
+ CX18_ERR("Can't find valid task handle for mute\n");
+ }
CX18_DEBUG_INFO("Mute\n");
}
void cx18_unmute(struct cx18 *cx)
{
+ u32 h;
if (atomic_read(&cx->ana_capturing)) {
- cx18_msleep_timeout(100, 0);
- cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
- cx18_find_handle(cx), 12);
- cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
- cx18_find_handle(cx), 0);
+ h = cx18_find_handle(cx);
+ if (h != CX18_INVALID_TASK_HANDLE) {
+ cx18_msleep_timeout(100, 0);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
+ } else
+ CX18_ERR("Can't find valid task handle for unmute\n");
}
CX18_DEBUG_INFO("Unmute\n");
}
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 78fadd2ada5..51534428cd0 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-scb.h"
#include "cx18-irq.h"
#include "cx18-firmware.h"
@@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
src = (const u32 *)fw->data;
for (i = 0; i < fw->size; i += 4096) {
- setup_page(i);
+ cx18_setup_page(cx, i);
for (j = i; j < fw->size && j < i + 4096; j += 4) {
/* no need for endianness conversion on the ppc */
- __raw_writel(*src, dst);
- if (__raw_readl(dst) != *src) {
+ cx18_raw_writel(cx, *src, dst);
+ if (cx18_raw_readl(cx, dst) != *src) {
CX18_ERR("Mismatch at offset %x\n", i);
release_firmware(fw);
return -EIO;
@@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
if (offset + seghdr.size > sz)
break;
for (i = 0; i < seghdr.size; i += 4096) {
- setup_page(offset + i);
+ cx18_setup_page(cx, offset + i);
for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
/* no need for endianness conversion on the ppc */
- __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
- if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
- CX18_ERR("Mismatch at offset %x\n", offset + j);
+ cx18_raw_writel(cx, src[(offset + j) / 4],
+ dst + seghdr.addr + j);
+ if (cx18_raw_readl(cx, dst + seghdr.addr + j)
+ != src[(offset + j) / 4]) {
+ CX18_ERR("Mismatch at offset %x\n",
+ offset + j);
release_firmware(fw);
return -EIO;
}
@@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
size = fw->size;
release_firmware(fw);
/* Clear bit0 for APU to start from 0 */
- write_reg(read_reg(0xc72030) & ~1, 0xc72030);
+ cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
return size;
}
void cx18_halt_firmware(struct cx18 *cx)
{
CX18_DEBUG_INFO("Preparing for firmware halt.\n");
- write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
- write_reg(0x00020002, CX18_ADEC_CONTROL);
+ cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+ cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
}
void cx18_init_power(struct cx18 *cx, int lowpwr)
{
/* power-down Spare and AOM PLLs */
/* power-up fast, slow and mpeg PLLs */
- write_reg(0x00000008, CX18_PLL_POWER_DOWN);
+ cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
/* ADEC out of sleep */
- write_reg(0x00020000, CX18_ADEC_CONTROL);
+ cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL);
/* The fast clock is at 200/245 MHz */
- write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
- write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
+ cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+ cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
+ CX18_FAST_CLOCK_PLL_FRAC);
- write_reg(2, CX18_FAST_CLOCK_PLL_POST);
- write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
- write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+ cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
+ cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
+ cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
/* set slow clock to 125/120 MHz */
- write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
- write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
- write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
+ cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
+ cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8,
+ CX18_SLOW_CLOCK_PLL_FRAC);
+ cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST);
/* mpeg clock pll 54MHz */
- write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
- write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
- write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
+ cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
+ cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
+ cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
/* Defaults */
/* APU = SC or SC/2 = 125/62.5 */
@@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
/* VFC = disabled */
/* USB = disabled */
- write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
- write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
+ cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
+ CX18_CLOCK_SELECT1);
+ cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
+ CX18_CLOCK_SELECT2);
- write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
- write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
+ cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
+ cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
- write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
- write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
+ cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
+ cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
}
void cx18_init_memory(struct cx18 *cx)
{
cx18_msleep_timeout(10, 0);
- write_reg(0x10000, CX18_DDR_SOFT_RESET);
+ cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET);
cx18_msleep_timeout(10, 0);
- write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+ cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
cx18_msleep_timeout(10, 0);
- write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
- write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
- write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
+ cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
+ cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
+ cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
cx18_msleep_timeout(10, 0);
/* Initialize DQS pad time */
- write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
- write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+ cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+ cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
cx18_msleep_timeout(10, 0);
- write_reg(0x20000, CX18_DDR_SOFT_RESET);
+ cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET);
cx18_msleep_timeout(10, 0);
/* use power-down mode when idle */
- write_reg(0x00000010, CX18_DDR_POWER_REG);
-
- write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
-
- write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
- write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
-
- write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */
- write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */
- write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
- write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */
- write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
- write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */
- write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */
- write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */
- write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */
- write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */
+ cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
+
+ cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN);
+
+ cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
+ cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
+
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */
+ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */
}
int cx18_firmware_init(struct cx18 *cx)
{
/* Allow chip to control CLKRUN */
- write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
+ cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
- write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+ cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
cx18_msleep_timeout(1, 0);
- sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
- sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+ cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+ cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
/* Only if the processor is not running */
- if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
+ if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) {
int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
cx->enc_mem, cx);
- write_enc(0xE51FF004, 0);
- write_enc(0xa00000, 4); /* todo: not hardcoded */
- write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */
+ cx18_write_enc(cx, 0xE51FF004, 0);
+ cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
+ /* Start APU */
+ cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET);
cx18_msleep_timeout(500, 0);
sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
@@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx)
int retries = 0;
/* start the CPU */
- write_reg(0x00080000, CX18_PROC_SOFT_RESET);
+ cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET);
while (retries++ < 50) { /* Loop for max 500mS */
- if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
+ if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
+ & 1) == 0)
break;
cx18_msleep_timeout(10, 0);
}
@@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx)
return -EIO;
}
/* initialize GPIO */
- write_reg(0x14001400, 0xC78110);
+ cx18_write_reg(cx, 0x14001400, 0xC78110);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index 3d495dba498..0e560421989 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-cards.h"
#include "cx18-gpio.h"
#include "tuner-xc2028.h"
@@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx)
u32 dir = cx->gpio_dir;
u32 val = cx->gpio_val;
- write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
- write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
+ cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
+ cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff),
CX18_REG_GPIO_OUT1);
- write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
- write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
+ cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2);
+ cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
CX18_REG_GPIO_OUT2);
}
@@ -141,15 +142,17 @@ void cx18_gpio_init(struct cx18 *cx)
}
CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
- read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
- read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
+ cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
+ cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
+ cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
+ cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
gpio_write(cx);
mutex_unlock(&cx->gpio_lock);
}
/* Xceive tuner reset function */
-int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
{
struct i2c_algo_bit_data *algo = dev;
struct cx18_i2c_algo_callback_data *cb_data = algo->data;
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index 22cd7ddf855..beb7424b994 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -23,5 +23,5 @@
void cx18_gpio_init(struct cx18 *cx);
void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
void cx18_reset_ir_gpio(void *data);
-int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 6023ba3bd3a..aa09e557b19 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -22,13 +22,12 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-cards.h"
#include "cx18-gpio.h"
#include "cx18-av-core.h"
#include "cx18-i2c.h"
-#include <media/ir-kbd-i2c.h>
-
#define CX18_REG_I2C_1_WR 0xf15000
#define CX18_REG_I2C_1_RD 0xf15008
#define CX18_REG_I2C_2_WR 0xf25100
@@ -158,12 +157,12 @@ static void cx18_setscl(void *data, int state)
struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
- u32 r = read_reg(addr);
+ u32 r = cx18_read_reg(cx, addr);
if (state)
- write_reg_sync(r | SETSCL_BIT, addr);
+ cx18_write_reg_sync(cx, r | SETSCL_BIT, addr);
else
- write_reg_sync(r & ~SETSCL_BIT, addr);
+ cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr);
}
static void cx18_setsda(void *data, int state)
@@ -171,12 +170,12 @@ static void cx18_setsda(void *data, int state)
struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
- u32 r = read_reg(addr);
+ u32 r = cx18_read_reg(cx, addr);
if (state)
- write_reg_sync(r | SETSDL_BIT, addr);
+ cx18_write_reg_sync(cx, r | SETSDL_BIT, addr);
else
- write_reg_sync(r & ~SETSDL_BIT, addr);
+ cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr);
}
static int cx18_getscl(void *data)
@@ -185,7 +184,7 @@ static int cx18_getscl(void *data)
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
- return read_reg(addr) & GETSCL_BIT;
+ return cx18_read_reg(cx, addr) & GETSCL_BIT;
}
static int cx18_getsda(void *data)
@@ -194,7 +193,7 @@ static int cx18_getsda(void *data)
int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
- return read_reg(addr) & GETSDL_BIT;
+ return cx18_read_reg(cx, addr) & GETSDL_BIT;
}
/* template for i2c-bit-algo */
@@ -394,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx)
cx->i2c_adap[i].dev.parent = &cx->dev->dev;
}
- if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
+ if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
/* Reset/Unreset I2C hardware block */
- write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
- write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
+ /* Clock select 220MHz */
+ cx18_write_reg(cx, 0x10000000, 0xc71004);
+ /* Clock Enable */
+ cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
}
/* courtesy of Steven Toth <stoth@hauppauge.com> */
- write_reg_sync(0x00c00000, 0xc7001c);
+ cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
mdelay(10);
- write_reg_sync(0x00c000c0, 0xc7001c);
+ cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
mdelay(10);
- write_reg_sync(0x00c00000, 0xc7001c);
+ cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
mdelay(10);
- write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
- write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
+ /* Set to edge-triggered intrs. */
+ cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
+ /* Clear any stale intrs */
+ cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
/* Hw I2C1 Clock Freq ~100kHz */
- write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+ cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
/* Hw I2C2 Clock Freq ~100kHz */
- write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+ cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
@@ -430,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx)
{
int i;
CX18_DEBUG_I2C("i2c exit\n");
- write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
- write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
+ cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
+ CX18_REG_I2C_1_WR);
+ cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
+ CX18_REG_I2C_2_WR);
for (i = 0; i < 2; i++) {
i2c_del_adapter(&cx->i2c_adap[i]);
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
new file mode 100644
index 00000000000..700ab9439c1
--- /dev/null
+++ b/drivers/media/video/cx18/cx18-io.c
@@ -0,0 +1,254 @@
+/*
+ * cx18 driver PCI memory mapped IO access routines
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ * Copyright (C) 2008 Andy Walls <awalls@radix.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+
+void cx18_log_statistics(struct cx18 *cx)
+{
+ int i;
+
+ if (!(cx18_debug & CX18_DBGFLG_INFO))
+ return;
+
+ for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+ CX18_DEBUG_INFO("retried_write[%d] = %d\n", i,
+ atomic_read(&cx->mmio_stats.retried_write[i]));
+ for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+ CX18_DEBUG_INFO("retried_read[%d] = %d\n", i,
+ atomic_read(&cx->mmio_stats.retried_read[i]));
+ return;
+}
+
+void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ cx18_raw_writel_noretry(cx, val, addr);
+ if (val == cx18_raw_readl_noretry(cx, addr))
+ break;
+ }
+ cx18_log_write_retries(cx, i, addr);
+}
+
+u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr)
+{
+ int i;
+ u32 val;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ val = cx18_raw_readl_noretry(cx, addr);
+ if (val != 0xffffffff) /* PCI bus read error */
+ break;
+ }
+ cx18_log_read_retries(cx, i, addr);
+ return val;
+}
+
+u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr)
+{
+ int i;
+ u16 val;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ val = cx18_raw_readw_noretry(cx, addr);
+ if (val != 0xffff) /* PCI bus read error */
+ break;
+ }
+ cx18_log_read_retries(cx, i, addr);
+ return val;
+}
+
+void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ cx18_writel_noretry(cx, val, addr);
+ if (val == cx18_readl_noretry(cx, addr))
+ break;
+ }
+ cx18_log_write_retries(cx, i, addr);
+}
+
+void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ cx18_writew_noretry(cx, val, addr);
+ if (val == cx18_readw_noretry(cx, addr))
+ break;
+ }
+ cx18_log_write_retries(cx, i, addr);
+}
+
+void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ cx18_writeb_noretry(cx, val, addr);
+ if (val == cx18_readb_noretry(cx, addr))
+ break;
+ }
+ cx18_log_write_retries(cx, i, addr);
+}
+
+u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr)
+{
+ int i;
+ u32 val;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ val = cx18_readl_noretry(cx, addr);
+ if (val != 0xffffffff) /* PCI bus read error */
+ break;
+ }
+ cx18_log_read_retries(cx, i, addr);
+ return val;
+}
+
+u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr)
+{
+ int i;
+ u16 val;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ val = cx18_readw_noretry(cx, addr);
+ if (val != 0xffff) /* PCI bus read error */
+ break;
+ }
+ cx18_log_read_retries(cx, i, addr);
+ return val;
+}
+
+u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr)
+{
+ int i;
+ u8 val;
+ for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ val = cx18_readb_noretry(cx, addr);
+ if (val != 0xff) /* PCI bus read error */
+ break;
+ }
+ cx18_log_read_retries(cx, i, addr);
+ return val;
+}
+
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+ const void __iomem *from, unsigned int len)
+{
+ const u8 __iomem *src = from;
+ u8 *dst = to;
+
+ /* Align reads on the CX23418's addresses */
+ if ((len > 0) && ((unsigned long) src & 1)) {
+ *dst = cx18_readb(cx, src);
+ len--;
+ dst++;
+ src++;
+ }
+ if ((len > 1) && ((unsigned long) src & 2)) {
+ *((u16 *)dst) = cx18_raw_readw(cx, src);
+ len -= 2;
+ dst += 2;
+ src += 2;
+ }
+ while (len > 3) {
+ *((u32 *)dst) = cx18_raw_readl(cx, src);
+ len -= 4;
+ dst += 4;
+ src += 4;
+ }
+ if (len > 1) {
+ *((u16 *)dst) = cx18_raw_readw(cx, src);
+ len -= 2;
+ dst += 2;
+ src += 2;
+ }
+ if (len > 0)
+ *dst = cx18_readb(cx, src);
+}
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
+{
+ u8 __iomem *dst = addr;
+ u16 val2 = val | (val << 8);
+ u32 val4 = val2 | (val2 << 16);
+
+ /* Align writes on the CX23418's addresses */
+ if ((count > 0) && ((unsigned long)dst & 1)) {
+ cx18_writeb(cx, (u8) val, dst);
+ count--;
+ dst++;
+ }
+ if ((count > 1) && ((unsigned long)dst & 2)) {
+ cx18_writew(cx, val2, dst);
+ count -= 2;
+ dst += 2;
+ }
+ while (count > 3) {
+ cx18_writel(cx, val4, dst);
+ count -= 4;
+ dst += 4;
+ }
+ if (count > 1) {
+ cx18_writew(cx, val2, dst);
+ count -= 2;
+ dst += 2;
+ }
+ if (count > 0)
+ cx18_writeb(cx, (u8) val, dst);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
+{
+ u32 r;
+ cx18_write_reg(cx, val, SW1_INT_STATUS);
+ r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
+ cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
+{
+ u32 r;
+ r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
+ cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
+{
+ u32 r;
+ cx18_write_reg(cx, val, SW2_INT_STATUS);
+ r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
+ cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
+{
+ u32 r;
+ r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
+ cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_setup_page(struct cx18 *cx, u32 addr)
+{
+ u32 val;
+ val = cx18_read_reg(cx, 0xD000F8);
+ val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
+ cx18_write_reg(cx, val, 0xD000F8);
+}
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
new file mode 100644
index 00000000000..197d4fbd9f9
--- /dev/null
+++ b/drivers/media/video/cx18/cx18-io.h
@@ -0,0 +1,378 @@
+/*
+ * cx18 driver PCI memory mapped IO access routines
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ * Copyright (C) 2008 Andy Walls <awalls@radix.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef CX18_IO_H
+#define CX18_IO_H
+
+#include "cx18-driver.h"
+
+static inline void cx18_io_delay(struct cx18 *cx)
+{
+ if (cx->options.mmio_ndelay)
+ ndelay(cx->options.mmio_ndelay);
+}
+
+/*
+ * Readback and retry of MMIO access for reliability:
+ * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
+ * The implmentation is the fault of Andy Walls <awalls@radix.net>.
+ */
+
+/* Statistics gathering */
+static inline
+void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
+{
+ if (i > CX18_MAX_MMIO_RETRIES)
+ i = CX18_MAX_MMIO_RETRIES;
+ atomic_inc(&cx->mmio_stats.retried_write[i]);
+ return;
+}
+
+static inline
+void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr)
+{
+ if (i > CX18_MAX_MMIO_RETRIES)
+ i = CX18_MAX_MMIO_RETRIES;
+ atomic_inc(&cx->mmio_stats.retried_read[i]);
+ return;
+}
+
+void cx18_log_statistics(struct cx18 *cx);
+
+/* Non byteswapping memory mapped IO */
+static inline
+void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ __raw_writel(val, addr);
+ cx18_io_delay(cx);
+}
+
+void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
+
+static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ cx18_raw_writel_retry(cx, val, addr);
+ else
+ cx18_raw_writel_noretry(cx, val, addr);
+}
+
+
+static inline
+u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+ u32 ret = __raw_readl(addr);
+ cx18_io_delay(cx);
+ return ret;
+}
+
+u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_raw_readl_retry(cx, addr);
+
+ return cx18_raw_readl_noretry(cx, addr);
+}
+
+
+static inline
+u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+ u16 ret = __raw_readw(addr);
+ cx18_io_delay(cx);
+ return ret;
+}
+
+u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_raw_readw_retry(cx, addr);
+
+ return cx18_raw_readw_noretry(cx, addr);
+}
+
+
+/* Normal memory mapped IO */
+static inline
+void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+ cx18_io_delay(cx);
+}
+
+void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
+
+static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ cx18_writel_retry(cx, val, addr);
+ else
+ cx18_writel_noretry(cx, val, addr);
+}
+
+
+static inline
+void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+ writew(val, addr);
+ cx18_io_delay(cx);
+}
+
+void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr);
+
+static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ cx18_writew_retry(cx, val, addr);
+ else
+ cx18_writew_noretry(cx, val, addr);
+}
+
+
+static inline
+void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+ writeb(val, addr);
+ cx18_io_delay(cx);
+}
+
+void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr);
+
+static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ cx18_writeb_retry(cx, val, addr);
+ else
+ cx18_writeb_noretry(cx, val, addr);
+}
+
+
+static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+ u32 ret = readl(addr);
+ cx18_io_delay(cx);
+ return ret;
+}
+
+u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_readl_retry(cx, addr);
+
+ return cx18_readl_noretry(cx, addr);
+}
+
+
+static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+ u16 ret = readw(addr);
+ cx18_io_delay(cx);
+ return ret;
+}
+
+u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_readw_retry(cx, addr);
+
+ return cx18_readw_noretry(cx, addr);
+}
+
+
+static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+ u8 ret = readb(addr);
+ cx18_io_delay(cx);
+ return ret;
+}
+
+u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_readb_retry(cx, addr);
+
+ return cx18_readb_noretry(cx, addr);
+}
+
+
+static inline
+u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ cx18_writel_noretry(cx, val, addr);
+ return cx18_readl_noretry(cx, addr);
+}
+
+static inline
+u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ cx18_writel_retry(cx, val, addr);
+ return cx18_readl_retry(cx, addr);
+}
+
+static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_write_sync_retry(cx, val, addr);
+
+ return cx18_write_sync_noretry(cx, val, addr);
+}
+
+
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+ const void __iomem *from, unsigned int len);
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
+
+
+/* Access "register" region of CX23418 memory mapped I/O */
+static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+ cx18_writel_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg)
+{
+ cx18_writel_retry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
+{
+ if (cx18_retry_mmio)
+ cx18_write_reg_retry(cx, val, reg);
+ else
+ cx18_write_reg_noretry(cx, val, reg);
+}
+
+
+static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg)
+{
+ return cx18_readl_noretry(cx, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg)
+{
+ return cx18_readl_retry(cx, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
+{
+ if (cx18_retry_mmio)
+ return cx18_read_reg_retry(cx, reg);
+
+ return cx18_read_reg_noretry(cx, reg);
+}
+
+
+static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+ return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg)
+{
+ return cx18_write_sync_retry(cx, val, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg)
+{
+ if (cx18_retry_mmio)
+ return cx18_write_reg_sync_retry(cx, val, reg);
+
+ return cx18_write_reg_sync_noretry(cx, val, reg);
+}
+
+
+/* Access "encoder memory" region of CX23418 memory mapped I/O */
+static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr)
+{
+ cx18_writel_noretry(cx, val, cx->enc_mem + addr);
+}
+
+static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr)
+{
+ cx18_writel_retry(cx, val, cx->enc_mem + addr);
+}
+
+static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
+{
+ if (cx18_retry_mmio)
+ cx18_write_enc_retry(cx, val, addr);
+ else
+ cx18_write_enc_noretry(cx, val, addr);
+}
+
+
+static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr)
+{
+ return cx18_readl_noretry(cx, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr)
+{
+ return cx18_readl_retry(cx, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_read_enc_retry(cx, addr);
+
+ return cx18_read_enc_noretry(cx, addr);
+}
+
+static inline
+u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr)
+{
+ return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr);
+}
+
+static inline
+u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr)
+{
+ return cx18_write_sync_retry(cx, val, cx->enc_mem + addr);
+}
+
+static inline
+u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr)
+{
+ if (cx18_retry_mmio)
+ return cx18_write_enc_sync_retry(cx, val, addr);
+
+ return cx18_write_enc_sync_noretry(cx, val, addr);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
+void cx18_setup_page(struct cx18 *cx, u32 addr);
+
+#endif /* CX18_IO_H */
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index a7f839631d6..f0ca50f5fdd 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-version.h"
#include "cx18-mailbox.h"
#include "cx18-i2c.h"
@@ -170,7 +171,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
{
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
-
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
@@ -202,8 +202,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
int ret;
- int w = fmt->fmt.pix.width;
- int h = fmt->fmt.pix.height;
+ int w, h;
ret = v4l2_prio_check(&cx->prio, &id->prio);
if (ret)
@@ -212,6 +211,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
ret = cx18_try_fmt_vid_cap(file, fh, fmt);
if (ret)
return ret;
+ w = fmt->fmt.pix.width;
+ h = fmt->fmt.pix.height;
if (cx->params.width == w && cx->params.height == h)
return 0;
@@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
spin_lock_irqsave(&cx18_cards_lock, flags);
if (cmd == VIDIOC_DBG_G_REGISTER)
- regs->val = read_enc(regs->reg);
+ regs->val = cx18_read_enc(cx, regs->reg);
else
- write_enc(regs->val, regs->reg);
+ cx18_write_enc(cx, regs->val, regs->reg);
spin_unlock_irqrestore(&cx18_cards_lock, flags);
return 0;
}
@@ -345,7 +346,7 @@ static int cx18_querycap(struct file *file, void *fh,
strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
- strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
+ snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev));
vcap->version = CX18_DRIVER_VERSION; /* version */
vcap->capabilities = cx->v4l2_cap; /* capabilities */
return 0;
@@ -622,6 +623,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
{
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
+ u32 h;
switch (enc->cmd) {
case V4L2_ENC_CMD_START:
@@ -643,8 +645,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
return -EPERM;
if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_ERR("Can't find valid task handle for "
+ "V4L2_ENC_CMD_PAUSE\n");
+ return -EBADFD;
+ }
cx18_mute(cx);
- cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
+ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
break;
case V4L2_ENC_CMD_RESUME:
@@ -654,7 +662,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
return -EPERM;
if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
- cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_ERR("Can't find valid task handle for "
+ "V4L2_ENC_CMD_RESUME\n");
+ return -EBADFD;
+ }
+ cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
cx18_unmute(cx);
break;
@@ -731,12 +745,14 @@ static int cx18_log_status(struct file *file, void *fh)
continue;
CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
s->name, s->s_flags,
- (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+ (s->buffers - atomic_read(&s->q_free.buffers))
+ * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
(long long)cx->mpg_data_received,
(long long)cx->vbi_data_inserted);
+ cx18_log_statistics(cx);
CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
index 25114a5cbd5..360330f5463 100644
--- a/drivers/media/video/cx18/cx18-irq.c
+++ b/drivers/media/video/cx18/cx18-irq.c
@@ -20,6 +20,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-firmware.h"
#include "cx18-fileops.h"
#include "cx18-queue.h"
@@ -48,8 +49,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
break;
}
if (i == CX18_MAX_STREAMS) {
- CX18_WARN("DMA done for unknown handle %d for stream %s\n",
- handle, s->name);
+ CX18_WARN("Got DMA done notification for unknown/inactive"
+ " handle %d\n", handle);
mb->error = CXERR_NOT_OPEN;
mb->cmd = 0;
cx18_mb_ack(cx, mb);
@@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
if (mb->args[2] != 1)
CX18_WARN("Ack struct = %d for %s\n",
mb->args[2], s->name);
- id = read_enc(off);
- buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
+ id = cx18_read_enc(cx, off);
+ buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4));
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
if (buf) {
cx18_buf_sync_for_cpu(s, buf);
@@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
} else {
CX18_WARN("Could not find buf %d for stream %s\n",
- read_enc(off), s->name);
+ cx18_read_enc(cx, off), s->name);
}
mb->error = 0;
mb->cmd = 0;
@@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
char *p;
if (mb->args[1]) {
- setup_page(mb->args[1]);
- memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
+ cx18_setup_page(cx, mb->args[1]);
+ cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252);
str[252] = 0;
}
cx18_mb_ack(cx, mb);
@@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1)
struct cx18_mailbox mb;
if (sw1 & IRQ_CPU_TO_EPU) {
- memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
+ cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb));
mb.error = 0;
switch (mb.cmd) {
@@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
spin_lock(&cx->dma_reg_lock);
- hw2_mask = read_reg(HW2_INT_MASK5_PCI);
- hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
- sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
- sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
- sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
- sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
+ hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
+ hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
+ sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
+ sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
+ sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
+ sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
- write_reg(sw2&sw2_mask, SW2_INT_STATUS);
- write_reg(sw1&sw1_mask, SW1_INT_STATUS);
- write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
+ cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS);
+ cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS);
+ cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS);
if (sw1 || sw2 || hw2)
CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
@@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
*/
if (sw2) {
- if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) |
- readl(&cx->scb->cpu2epu_irq_ack)))
+ if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) |
+ cx18_readl(cx, &cx->scb->cpu2epu_irq_ack)))
wake_up(&cx->mb_cpu_waitq);
- if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) |
- readl(&cx->scb->apu2epu_irq_ack)))
+ if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) |
+ cx18_readl(cx, &cx->scb->apu2epu_irq_ack)))
wake_up(&cx->mb_apu_waitq);
- if (sw2 & readl(&cx->scb->epu2hpu_irq_ack))
+ if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack))
wake_up(&cx->mb_epu_waitq);
- if (sw2 & readl(&cx->scb->hpu2epu_irq_ack))
+ if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack))
wake_up(&cx->mb_hpu_waitq);
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 93177514e84..9d18dd22de7 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -22,6 +22,7 @@
#include <stdarg.h>
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-scb.h"
#include "cx18-irq.h"
#include "cx18-mailbox.h"
@@ -82,6 +83,7 @@ static const struct cx18_api_info api_info[] = {
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST),
+ API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0),
API_ENTRY(0, 0, 0),
};
@@ -105,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
switch (rpu) {
case APU:
mb = &cx->scb->epu2apu_mb;
- *state = readl(&cx->scb->apu_state);
- *irq = readl(&cx->scb->epu2apu_irq);
+ *state = cx18_readl(cx, &cx->scb->apu_state);
+ *irq = cx18_readl(cx, &cx->scb->epu2apu_irq);
break;
case CPU:
mb = &cx->scb->epu2cpu_mb;
- *state = readl(&cx->scb->cpu_state);
- *irq = readl(&cx->scb->epu2cpu_irq);
+ *state = cx18_readl(cx, &cx->scb->cpu_state);
+ *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
break;
case HPU:
mb = &cx->scb->epu2hpu_mb;
- *state = readl(&cx->scb->hpu_state);
- *irq = readl(&cx->scb->epu2hpu_irq);
+ *state = cx18_readl(cx, &cx->scb->hpu_state);
+ *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq);
break;
}
@@ -126,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
return mb;
do {
- *req = readl(&mb->request);
- ack = readl(&mb->ack);
+ *req = cx18_readl(cx, &mb->request);
+ ack = cx18_readl(cx, &mb->ack);
wait_count++;
} while (*req != ack && wait_count < 600);
@@ -172,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
return -EINVAL;
}
- setup_page(SCB_OFFSET);
- write_sync(mb->request, &ack_mb->ack);
- write_reg(ack_irq, SW2_INT_SET);
+ cx18_setup_page(cx, SCB_OFFSET);
+ cx18_write_sync(cx, mb->request, &ack_mb->ack);
+ cx18_write_reg(cx, ack_irq, SW2_INT_SET);
return 0;
}
@@ -199,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
CX18_DEBUG_HI_API("%s\n", info->name);
else
CX18_DEBUG_API("%s\n", info->name);
- setup_page(SCB_OFFSET);
+ cx18_setup_page(cx, SCB_OFFSET);
mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
if (mb == NULL) {
@@ -208,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
}
oldreq = req - 1;
- writel(cmd, &mb->cmd);
+ cx18_writel(cx, cmd, &mb->cmd);
for (i = 0; i < args; i++)
- writel(data[i], &mb->args[i]);
- writel(0, &mb->error);
- writel(req, &mb->request);
+ cx18_writel(cx, data[i], &mb->args[i]);
+ cx18_writel(cx, 0, &mb->error);
+ cx18_writel(cx, req, &mb->request);
switch (info->rpu) {
case APU: waitq = &cx->mb_apu_waitq; break;
@@ -223,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
}
if (info->flags & API_FAST)
timeout /= 2;
- write_reg(irq, SW1_INT_SET);
+ cx18_write_reg(cx, irq, SW1_INT_SET);
- while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
+ while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request)
+ && cnt < 660) {
if (cnt > 200 && !in_atomic())
sig = cx18_msleep_timeout(10, 1);
cnt++;
@@ -233,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
if (sig)
return -EINTR;
if (cnt == 660) {
- writel(oldreq, &mb->request);
+ cx18_writel(cx, oldreq, &mb->request);
CX18_ERR("mb %s failed\n", info->name);
return -EINVAL;
}
for (i = 0; i < MAX_MB_ARGUMENTS; i++)
- data[i] = readl(&mb->args[i]);
- err = readl(&mb->error);
+ data[i] = cx18_readl(cx, &mb->args[i]);
+ err = cx18_readl(cx, &mb->error);
if (!in_atomic() && (info->flags & API_SLOW))
cx18_msleep_timeout(300, 0);
if (err)
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index 6990b77c620..a33ba04a268 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -37,8 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf)
void cx18_queue_init(struct cx18_queue *q)
{
INIT_LIST_HEAD(&q->list);
- q->buffers = 0;
- q->length = 0;
+ atomic_set(&q->buffers, 0);
q->bytesused = 0;
}
@@ -55,8 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
}
spin_lock_irqsave(&s->qlock, flags);
list_add_tail(&buf->list, &q->list);
- q->buffers++;
- q->length += s->buf_size;
+ atomic_inc(&q->buffers);
q->bytesused += buf->bytesused - buf->readpos;
spin_unlock_irqrestore(&s->qlock, flags);
}
@@ -70,20 +68,20 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
if (!list_empty(&q->list)) {
buf = list_entry(q->list.next, struct cx18_buffer, list);
list_del_init(q->list.next);
- q->buffers--;
- q->length -= s->buf_size;
+ atomic_dec(&q->buffers);
q->bytesused -= buf->bytesused - buf->readpos;
}
spin_unlock_irqrestore(&s->qlock, flags);
return buf;
}
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
u32 bytesused)
{
struct cx18 *cx = s->cx;
struct list_head *p;
+ spin_lock(&s->qlock);
list_for_each(p, &s->q_free.list) {
struct cx18_buffer *buf =
list_entry(p, struct cx18_buffer, list);
@@ -92,114 +90,45 @@ struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
continue;
buf->bytesused = bytesused;
/* the transport buffers are handled differently,
- so there is no need to move them to the full queue */
- if (s->type == CX18_ENC_STREAM_TYPE_TS)
- return buf;
- s->q_free.buffers--;
- s->q_free.length -= s->buf_size;
- s->q_full.buffers++;
- s->q_full.length += s->buf_size;
- s->q_full.bytesused += buf->bytesused;
- list_move_tail(&buf->list, &s->q_full.list);
+ they are not moved to the full queue */
+ if (s->type != CX18_ENC_STREAM_TYPE_TS) {
+ atomic_dec(&s->q_free.buffers);
+ atomic_inc(&s->q_full.buffers);
+ s->q_full.bytesused += buf->bytesused;
+ list_move_tail(&buf->list, &s->q_full.list);
+ }
+ spin_unlock(&s->qlock);
return buf;
}
+ spin_unlock(&s->qlock);
CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
return NULL;
}
-static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
- struct cx18_queue *to, int clear, int full)
-{
- struct cx18_buffer *buf =
- list_entry(from->list.next, struct cx18_buffer, list);
-
- list_move_tail(from->list.next, &to->list);
- from->buffers--;
- from->length -= s->buf_size;
- from->bytesused -= buf->bytesused - buf->readpos;
- /* special handling for q_free */
- if (clear)
- buf->bytesused = buf->readpos = buf->b_flags = 0;
- else if (full) {
- /* special handling for stolen buffers, assume
- all bytes are used. */
- buf->bytesused = s->buf_size;
- buf->readpos = buf->b_flags = 0;
- }
- to->buffers++;
- to->length += s->buf_size;
- to->bytesused += buf->bytesused - buf->readpos;
-}
-
-/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
- If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
- If 'steal' != NULL, then buffers may also taken from that queue if
- needed.
-
- The buffer is automatically cleared if it goes to the free queue. It is
- also cleared if buffers need to be taken from the 'steal' queue and
- the 'from' queue is the free queue.
-
- When 'from' is q_free, then needed_bytes is compared to the total
- available buffer length, otherwise needed_bytes is compared to the
- bytesused value. For the 'steal' queue the total available buffer
- length is always used.
-
- -ENOMEM is returned if the buffers could not be obtained, 0 if all
- buffers where obtained from the 'from' list and if non-zero then
- the number of stolen buffers is returned. */
-static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
- struct cx18_queue *steal, struct cx18_queue *to,
- int needed_bytes)
+/* Move all buffers of a queue to q_free, while flushing the buffers */
+static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
{
unsigned long flags;
- int rc = 0;
- int from_free = from == &s->q_free;
- int to_free = to == &s->q_free;
- int bytes_available;
-
- spin_lock_irqsave(&s->qlock, flags);
- if (needed_bytes == 0) {
- from_free = 1;
- needed_bytes = from->length;
- }
-
- bytes_available = from_free ? from->length : from->bytesused;
- bytes_available += steal ? steal->length : 0;
+ struct cx18_buffer *buf;
- if (bytes_available < needed_bytes) {
- spin_unlock_irqrestore(&s->qlock, flags);
- return -ENOMEM;
- }
- if (from_free) {
- u32 old_length = to->length;
+ if (q == &s->q_free)
+ return;
- while (to->length - old_length < needed_bytes) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- cx18_queue_move_buf(s, from, to, 1, 0);
- }
- } else {
- u32 old_bytesused = to->bytesused;
-
- while (to->bytesused - old_bytesused < needed_bytes) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- cx18_queue_move_buf(s, from, to, to_free, rc);
- }
+ spin_lock_irqsave(&s->qlock, flags);
+ while (!list_empty(&q->list)) {
+ buf = list_entry(q->list.next, struct cx18_buffer, list);
+ list_move_tail(q->list.next, &s->q_free.list);
+ buf->bytesused = buf->readpos = buf->b_flags = 0;
+ atomic_inc(&s->q_free.buffers);
}
+ cx18_queue_init(q);
spin_unlock_irqrestore(&s->qlock, flags);
- return rc;
}
void cx18_flush_queues(struct cx18_stream *s)
{
- cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
- cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+ cx18_queue_flush(s, &s->q_io);
+ cx18_queue_flush(s, &s->q_full);
}
int cx18_stream_alloc(struct cx18_stream *s)
@@ -214,10 +143,10 @@ int cx18_stream_alloc(struct cx18_stream *s)
s->name, s->buffers, s->buf_size,
s->buffers * s->buf_size / 1024);
- if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
- (char *)cx->scb) > SCB_RESERVED_SIZE) {
- unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
- ((char *)cx->scb->cpu_mdl));
+ if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
+ (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
+ unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
+ ((char __iomem *)cx->scb->cpu_mdl));
CX18_ERR("Too many buffers, cannot fit in SCB area\n");
CX18_ERR("Max buffers = %zd\n",
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
index 91423b9863a..7f93bb13c09 100644
--- a/drivers/media/video/cx18/cx18-queue.h
+++ b/drivers/media/video/cx18/cx18-queue.h
@@ -46,7 +46,7 @@ void cx18_queue_init(struct cx18_queue *q);
void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
struct cx18_queue *q);
struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
u32 bytesused);
void cx18_flush_queues(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
index 30bc803e30d..f56d3772aa6 100644
--- a/drivers/media/video/cx18/cx18-scb.c
+++ b/drivers/media/video/cx18/cx18-scb.c
@@ -20,102 +20,103 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-scb.h"
void cx18_init_scb(struct cx18 *cx)
{
- setup_page(SCB_OFFSET);
- memset_io(cx->scb, 0, 0x10000);
+ cx18_setup_page(cx, SCB_OFFSET);
+ cx18_memset_io(cx, cx->scb, 0, 0x10000);
- writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
- writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
- writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
- writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
- writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
- writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
- writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
- writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+ cx18_writel(cx, IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
+ cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+ cx18_writel(cx, IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
+ cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+ cx18_writel(cx, IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
+ cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+ cx18_writel(cx, IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
+ cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
- writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
- writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
- writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
- writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
- writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
- writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
- writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
- writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+ cx18_writel(cx, IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
+ cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+ cx18_writel(cx, IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
+ cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+ cx18_writel(cx, IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
+ cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+ cx18_writel(cx, IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
+ cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
- writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
- writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
- writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
- writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
- writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
- writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
- writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
- writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+ cx18_writel(cx, IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
+ cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+ cx18_writel(cx, IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
+ cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+ cx18_writel(cx, IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
+ cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+ cx18_writel(cx, IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
+ cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
- writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
- writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
- writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
- writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
- writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
- writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
- writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
- writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+ cx18_writel(cx, IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
+ cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+ cx18_writel(cx, IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
+ cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+ cx18_writel(cx, IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
+ cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+ cx18_writel(cx, IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
+ cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
- writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
- writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
- writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
- writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
- writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
- writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
- writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
- writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+ cx18_writel(cx, IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
+ cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+ cx18_writel(cx, IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
+ cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+ cx18_writel(cx, IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
+ cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+ cx18_writel(cx, IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
+ cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
&cx->scb->apu2cpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
&cx->scb->hpu2cpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
&cx->scb->ppu2cpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
&cx->scb->epu2cpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
&cx->scb->cpu2apu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
&cx->scb->hpu2apu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
&cx->scb->ppu2apu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
&cx->scb->epu2apu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
&cx->scb->cpu2hpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
&cx->scb->apu2hpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
&cx->scb->ppu2hpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
&cx->scb->epu2hpu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
&cx->scb->cpu2ppu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
&cx->scb->apu2ppu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
&cx->scb->hpu2ppu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
&cx->scb->epu2ppu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
&cx->scb->cpu2epu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
&cx->scb->apu2epu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
&cx->scb->hpu2epu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
&cx->scb->ppu2epu_mb_offset);
- writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+ cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
&cx->scb->ipc_offset);
- writel(1, &cx->scb->hpu_state);
- writel(1, &cx->scb->epu_state);
+ cx18_writel(cx, 1, &cx->scb->hpu_state);
+ cx18_writel(cx, 1, &cx->scb->epu_state);
}
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 0da57f583bf..0c8e7542cf6 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -22,6 +22,7 @@
*/
#include "cx18-driver.h"
+#include "cx18-io.h"
#include "cx18-fileops.h"
#include "cx18-mailbox.h"
#include "cx18-i2c.h"
@@ -56,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = {
static struct {
const char *name;
int vfl_type;
- int minor_offset;
+ int num_offset;
int dma;
enum v4l2_buf_type buf_type;
struct file_operations *fops;
@@ -119,7 +120,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->cx = cx;
s->type = type;
s->name = cx18_stream_info[type].name;
- s->handle = 0xffffffff;
+ s->handle = CX18_INVALID_TASK_HANDLE;
s->dma = cx18_stream_info[type].dma;
s->buf_size = cx->stream_buf_size[type];
@@ -143,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
{
struct cx18_stream *s = &cx->streams[type];
u32 cap = cx->v4l2_cap;
- int minor_offset = cx18_stream_info[type].minor_offset;
- int minor;
+ int num_offset = cx18_stream_info[type].num_offset;
+ int num = cx->num + cx18_first_minor + num_offset;
/* These four fields are always initialized. If v4l2dev == NULL, then
this stream is not in use. In that case no other fields but these
@@ -163,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
!(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
return 0;
- /* card number + user defined offset + device offset */
- minor = cx->num + cx18_first_minor + minor_offset;
-
/* User explicitly selected 0 buffers for these streams, so don't
create them. */
if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
@@ -176,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
cx18_stream_init(cx, type);
- if (minor_offset == -1)
+ if (num_offset == -1)
return 0;
/* allocate and initialize the v4l2 video device structure */
@@ -190,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
cx->num);
- s->v4l2dev->minor = minor;
+ s->v4l2dev->num = num;
s->v4l2dev->parent = &cx->dev->dev;
s->v4l2dev->fops = cx18_stream_info[type].fops;
s->v4l2dev->release = video_device_release;
@@ -226,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
{
struct cx18_stream *s = &cx->streams[type];
int vfl_type = cx18_stream_info[type].vfl_type;
- int minor;
+ int num;
/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
* We need a VFL_TYPE_TS defined.
@@ -244,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
if (s->v4l2dev == NULL)
return 0;
- minor = s->v4l2dev->minor;
+ num = s->v4l2dev->num;
+ /* card number + user defined offset + device offset */
+ if (type != CX18_ENC_STREAM_TYPE_MPG) {
+ struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
+ if (s_mpg->v4l2dev)
+ num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset;
+ }
/* Register device. First try the desired minor, then any free one. */
- if (video_register_device(s->v4l2dev, vfl_type, minor) &&
- video_register_device(s->v4l2dev, vfl_type, -1)) {
- CX18_ERR("Couldn't register v4l2 device for %s minor %d\n",
- s->name, minor);
+ if (video_register_device(s->v4l2dev, vfl_type, num)) {
+ CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
+ s->name, num);
video_device_release(s->v4l2dev);
s->v4l2dev = NULL;
return -ENOMEM;
}
- minor = s->v4l2dev->minor;
+ num = s->v4l2dev->num;
switch (vfl_type) {
case VFL_TYPE_GRABBER:
CX18_INFO("Registered device video%d for %s (%d MB)\n",
- minor, s->name, cx->options.megabytes[type]);
+ num, s->name, cx->options.megabytes[type]);
break;
case VFL_TYPE_RADIO:
CX18_INFO("Registered device radio%d for %s\n",
- minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+ num, s->name);
break;
case VFL_TYPE_VBI:
if (cx->options.megabytes[type])
CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
- minor - MINOR_VFL_TYPE_VBI_MIN,
+ num,
s->name, cx->options.megabytes[type]);
else
CX18_INFO("Registered device vbi%d for %s\n",
- minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+ num, s->name);
break;
}
@@ -432,7 +436,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
default:
return -EINVAL;
}
- s->buffers_stolen = 0;
/* mute/unmute video */
cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
@@ -470,7 +473,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
if (atomic_read(&cx->tot_capturing) == 0) {
clear_bit(CX18_F_I_EOS, &cx->i_flags);
- write_reg(7, CX18_DSP0_INTERRUPT_MASK);
+ cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
}
cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
@@ -480,8 +483,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
list_for_each(p, &s->q_free.list) {
struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
- writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
- writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
+ cx18_writel(cx, buf->dma_handle,
+ &cx->scb->cpu_mdl[buf->id].paddr);
+ cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
(void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
1, buf->id, s->buf_size);
@@ -489,7 +493,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
/* begin_capture */
if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
CX18_DEBUG_WARN("Error starting capture!\n");
+ /* Ensure we're really not capturing before releasing MDLs */
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
+ else
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+ /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */
return -EINVAL;
}
@@ -541,6 +552,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
}
+ /* Tell the CX23418 it can't use our buffers anymore */
+ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
if (s->type != CX18_ENC_STREAM_TYPE_TS)
atomic_dec(&cx->ana_capturing);
atomic_dec(&cx->tot_capturing);
@@ -549,12 +563,12 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
- s->handle = 0xffffffff;
+ s->handle = CX18_INVALID_TASK_HANDLE;
if (atomic_read(&cx->tot_capturing) > 0)
return 0;
- write_reg(5, CX18_DSP0_INTERRUPT_MASK);
+ cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
wake_up(&s->waitq);
return 0;
@@ -568,8 +582,8 @@ u32 cx18_find_handle(struct cx18 *cx)
for (i = 0; i < CX18_MAX_STREAMS; i++) {
struct cx18_stream *s = &cx->streams[i];
- if (s->v4l2dev && s->handle)
+ if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE))
return s->handle;
}
- return 0;
+ return CX18_INVALID_TASK_HANDLE;
}
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index d5c7a6f968d..9f6be2d457f 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -25,7 +25,7 @@
#define CX18_DRIVER_NAME "cx18"
#define CX18_DRIVER_VERSION_MAJOR 1
#define CX18_DRIVER_VERSION_MINOR 0
-#define CX18_DRIVER_VERSION_PATCHLEVEL 0
+#define CX18_DRIVER_VERSION_PATCHLEVEL 1
#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index e7ed053059a..668f968d776 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -351,7 +351,7 @@
Descriptor Lists to the driver
IN[0] - Task handle. Handle of the task to start
ReturnCode - One of the ERR_DE_... */
-/* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */
+#define CX18_CPU_DE_RELEASE_MDL (CPU_CMD_MASK_DE | 0x0006)
/* Description: This command signals the cpu that the dat buffer has been
consumed and ready for re-use.
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 22847a0444f..cbbe47fb87b 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -508,7 +508,10 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
/* this setting is read-only for the cx2341x since the
V4L2_CID_MPEG_STREAM_TYPE really determines the
MPEG-1/2 setting */
- err = v4l2_ctrl_query_fill_std(qctrl);
+ err = v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
if (err == 0)
qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
return err;
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index e60bd31b51a..8c1b7fa47a4 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -15,6 +15,7 @@ config VIDEO_CX23885
select DVB_S5H1409 if !DVB_FE_CUSTOMISE
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 8118091568f..395c11fa47c 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -4,7 +4,7 @@
*
* (c) 2004 Jelle Foks <jelle@foks.8m.com>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org>
- * (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * (c) 2008 Steven Toth <stoth@linuxtv.org>
* - CX23885/7/8 support
*
* Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
@@ -36,7 +36,6 @@
#include <media/cx2341x.h>
#include "cx23885.h"
-#include "media/cx2341x.h"
#define CX23885_FIRM_IMAGE_SIZE 376836
#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -632,7 +631,7 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
/* ------------------------------------------------------------------ */
/* MPEG encoder API */
-char *cmd_to_str(int cmd)
+static char *cmd_to_str(int cmd)
{
switch (cmd) {
case CX2341X_ENC_PING_FW:
@@ -1583,6 +1582,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
dprintk(2, "%s()\n", __func__);
+ lock_kernel();
list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist);
if (h->v4l_device->minor == minor) {
@@ -1591,13 +1591,17 @@ static int mpeg_open(struct inode *inode, struct file *file)
}
}
- if (dev == NULL)
+ if (dev == NULL) {
+ unlock_kernel();
return -ENODEV;
+ }
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
@@ -1608,6 +1612,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
V4L2_FIELD_INTERLACED,
sizeof(struct cx23885_buffer),
fh);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index a19de850955..dac5ccc9ba7 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
@@ -26,6 +26,7 @@
#include <media/cx25840.h>
#include "cx23885.h"
+#include "tuner-xc2028.h"
/* ------------------------------------------------------------------ */
/* board config info */
@@ -38,16 +39,16 @@ struct cx23885_board cx23885_boards[] = {
.input = {{
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 0,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE2,
.vmux = 1,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE3,
.vmux = 2,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE4,
.vmux = 3,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
.name = "Hauppauge WinTV-HVR1800lp",
@@ -56,19 +57,19 @@ struct cx23885_board cx23885_boards[] = {
.type = CX23885_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xff00,
- },{
+ }, {
.type = CX23885_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff01,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xff02,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
.name = "Hauppauge WinTV-HVR1800",
@@ -83,20 +84,20 @@ struct cx23885_board cx23885_boards[] = {
CX25840_VIN5_CH2 |
CX25840_VIN2_CH1,
.gpio0 = 0,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN6_CH1,
.gpio0 = 0,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN8_CH1 |
CX25840_SVIDEO_ON,
.gpio0 = 0,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1250] = {
.name = "Hauppauge WinTV-HVR1250",
@@ -105,19 +106,19 @@ struct cx23885_board cx23885_boards[] = {
.type = CX23885_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xff00,
- },{
+ }, {
.type = CX23885_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff01,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xff02,
- }},
+ } },
},
[CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
.name = "DViCO FusionHDTV5 Express",
@@ -148,6 +149,15 @@ struct cx23885_board cx23885_boards[] = {
.portb = CX23885_MPEG_DVB,
.portc = CX23885_MPEG_DVB,
},
+ [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = {
+ .name = "DViCO FusionHDTV DVB-T Dual Express",
+ .portb = CX23885_MPEG_DVB,
+ .portc = CX23885_MPEG_DVB,
+ },
+ [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
+ .name = "Leadtek Winfast PxDVR3200 H",
+ .portc = CX23885_MPEG_DVB,
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -159,43 +169,43 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x3400,
.card = CX23885_BOARD_UNKNOWN,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7600,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7800,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7801,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7809,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7911,
.card = CX23885_BOARD_HAUPPAUGE_HVR1250,
- },{
+ }, {
.subvendor = 0x18ac,
.subdevice = 0xd500,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7790,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7797,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7710,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7717,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500,
@@ -215,10 +225,18 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x8010,
.card = CX23885_BOARD_HAUPPAUGE_HVR1400,
- },{
+ }, {
.subvendor = 0x18ac,
.subdevice = 0xd618,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
+ }, {
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb78,
+ .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
+ }, {
+ .subvendor = 0x107d,
+ .subdevice = 0x6681,
+ .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -229,23 +247,25 @@ void cx23885_card_list(struct cx23885_dev *dev)
if (0 == dev->pci->subsystem_vendor &&
0 == dev->pci->subsystem_device) {
- printk("%s: Your board has no valid PCIe Subsystem ID and thus can't\n"
- "%s: be autodetected. Please pass card=<n> insmod option to\n"
- "%s: workaround that. Redirect complaints to the vendor of\n"
- "%s: the TV card. Best regards,\n"
+ printk(KERN_INFO
+ "%s: Board has no valid PCIe Subsystem ID and can't\n"
+ "%s: be autodetected. Pass card=<n> insmod option\n"
+ "%s: to workaround that. Redirect complaints to the\n"
+ "%s: vendor of the TV card. Best regards,\n"
"%s: -- tux\n",
dev->name, dev->name, dev->name, dev->name, dev->name);
} else {
- printk("%s: Your board isn't known (yet) to the driver. You can\n"
- "%s: try to pick one of the existing card configs via\n"
+ printk(KERN_INFO
+ "%s: Your board isn't known (yet) to the driver.\n"
+ "%s: Try to pick one of the existing card configs via\n"
"%s: card=<n> insmod option. Updating to the latest\n"
"%s: version might help as well.\n",
dev->name, dev->name, dev->name, dev->name);
}
- printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+ printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
dev->name);
for (i = 0; i < cx23885_bcount; i++)
- printk("%s: card=%d -> %s\n",
+ printk(KERN_INFO "%s: card=%d -> %s\n",
dev->name, i, cx23885_boards[i].name);
}
@@ -253,11 +273,11 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, eeprom_data);
+ tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+ eeprom_data);
/* Make sure we support the board model */
- switch (tv.model)
- {
+ switch (tv.model) {
case 71009:
/* WinTV-HVR1200 (PCIe, Retail, full height)
* DVB-T and basic analog */
@@ -285,21 +305,51 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 71999:
/* WinTV-HVR1200 (PCIe, OEM, full height)
* DVB-T and basic analog */
- case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
- case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */
- case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
- case 77041: /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM and Basic analog */
- case 77051: /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM and Basic analog */
- case 78011: /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78501: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78521: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78531: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78631: /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 79001: /* WinTV-HVR1250 (PCIe, Retail, IR, full height, ATSC and Basic analog */
- case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */
- case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
- case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
- case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ case 76601:
+ /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
+ channel ATSC and MPEG2 HW Encoder */
+ case 77001:
+ /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
+ and Basic analog */
+ case 77011:
+ /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
+ and Basic analog */
+ case 77041:
+ /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
+ and Basic analog */
+ case 77051:
+ /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
+ and Basic analog */
+ case 78011:
+ /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78501:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78521:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78531:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78631:
+ /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 79001:
+ /* WinTV-HVR1250 (PCIe, Retail, IR, full height,
+ ATSC and Basic analog */
+ case 79101:
+ /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
+ ATSC and Basic analog */
+ case 79561:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+ ATSC and Basic analog */
+ case 79571:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, full height,
+ ATSC and Basic analog */
+ case 79671:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+ ATSC and Basic analog */
case 80019:
/* WinTV-HVR1400 (Express Card, Retail, IR,
* DVB-T and Basic analog */
@@ -311,7 +361,8 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
* DVB-T and MPEG2 HW Encoder */
break;
default:
- printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
+ printk(KERN_WARNING "%s: warning: unknown hauppauge model #%d\n",
+ dev->name, tv.model);
break;
}
@@ -319,37 +370,37 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
dev->name, tv.model);
}
-/* Tuner callback function for cx23885 boards. Currently only needed
- * for HVR1500Q, which has an xc5000 tuner.
- */
-int cx23885_tuner_callback(void *priv, int command, int arg)
+int cx23885_tuner_callback(void *priv, int component, int command, int arg)
{
- struct cx23885_i2c *bus = priv;
- struct cx23885_dev *dev = bus->dev;
+ struct cx23885_tsport *port = priv;
+ struct cx23885_dev *dev = port->dev;
u32 bitmask = 0;
+ if (command == XC2028_RESET_CLK)
+ return 0;
+
if (command != 0) {
printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
__func__, command);
return -EINVAL;
}
- switch(dev->board) {
+ switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
- /* Tuner Reset Command from xc5000 */
- if (command == 0)
- bitmask = 0x04;
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ /* Tuner Reset Command */
+ bitmask = 0x04;
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
- if (command == 0) {
-
- /* Two identical tuners on two different i2c buses,
- * we need to reset the correct gpio. */
- if (bus->nr == 0)
- bitmask = 0x01;
- else if (bus->nr == 1)
- bitmask = 0x04;
- }
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ /* Two identical tuners on two different i2c buses,
+ * we need to reset the correct gpio. */
+ if (port->nr == 0)
+ bitmask = 0x01;
+ else if (port->nr == 1)
+ bitmask = 0x04;
break;
}
@@ -365,7 +416,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
void cx23885_gpio_setup(struct cx23885_dev *dev)
{
- switch(dev->board) {
+ switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
/* GPIO-0 cx24227 demodulator reset */
cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
@@ -465,6 +516,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
mdelay(20);
cx_set(GP0_IO, 0x000f000f);
break;
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ /* GPIO-0 portb xc3028 reset */
+ /* GPIO-1 portb zl10353 reset */
+ /* GPIO-2 portc xc3028 reset */
+ /* GPIO-3 portc zl10353 reset */
+
+ /* Put the parts into reset and back */
+ cx_set(GP0_IO, 0x000f0000);
+ mdelay(20);
+ cx_clear(GP0_IO, 0x0000000f);
+ mdelay(20);
+ cx_set(GP0_IO, 0x000f000f);
+ break;
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ /* GPIO-2 xc3028 tuner reset */
+
+ /* The following GPIO's are on the internal AVCore (cx25840) */
+ /* GPIO-? zl10353 demod reset */
+
+ /* Put the parts into reset and back */
+ cx_set(GP0_IO, 0x00040000);
+ mdelay(20);
+ cx_clear(GP0_IO, 0x00000004);
+ mdelay(20);
+ cx_set(GP0_IO, 0x00040004);
+ break;
}
}
@@ -479,6 +556,9 @@ int cx23885_ir_init(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1400:
/* FIXME: Implement me */
break;
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ request_module("ir-kbd-i2c");
+ break;
}
return 0;
@@ -516,6 +596,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
switch (dev->board) {
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -548,6 +629,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
default:
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
@@ -561,16 +643,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
request_module("cx25840");
break;
}
}
/* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 6286a9cf957..8f6fb2add7d 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
@@ -33,16 +33,16 @@
#include "cx23885.h"
MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card,"card type");
+MODULE_PARM_DESC(card, "card type");
#define dprintk(level, fmt, arg...)\
do { if (debug >= level)\
@@ -364,13 +364,12 @@ void cx23885_wakeup(struct cx23885_tsport *port,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
- if (list_empty(&q->active)) {
+ if (list_empty(&q->active))
del_timer(&q->timeout);
- } else {
+ else
mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
- }
if (bc != 1)
- printk("%s: %d buffers handled (should be 1)\n",
+ printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
__func__, bc);
}
@@ -381,8 +380,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
unsigned int i, lines;
u32 cdt;
- if (ch->cmds_start == 0)
- {
+ if (ch->cmds_start == 0) {
dprintk(1, "%s() Erasing channel [%s]\n", __func__,
ch->name);
cx_write(ch->ptr1_reg, 0);
@@ -418,15 +416,15 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
/* write CMDS */
if (ch->jumponly)
- cx_write(ch->cmds_start + 0, 8);
+ cx_write(ch->cmds_start + 0, 8);
else
- cx_write(ch->cmds_start + 0, risc);
+ cx_write(ch->cmds_start + 0, risc);
cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
cx_write(ch->cmds_start + 8, cdt);
cx_write(ch->cmds_start + 12, (lines*16) >> 3);
cx_write(ch->cmds_start + 16, ch->ctrl_start);
if (ch->jumponly)
- cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2) );
+ cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
else
cx_write(ch->cmds_start + 20, 64 >> 2);
for (i = 24; i < 80; i += 4)
@@ -436,9 +434,9 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
cx_write(ch->ptr1_reg, ch->fifo_start);
cx_write(ch->ptr2_reg, cdt);
cx_write(ch->cnt2_reg, (lines*16) >> 3);
- cx_write(ch->cnt1_reg, (bpl >> 3) -1);
+ cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
- dprintk(2,"[bridge %d] sram setup %s: bpl=%d lines=%d\n",
+ dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
dev->bridge,
ch->name,
bpl,
@@ -469,43 +467,43 @@ void cx23885_sram_channel_dump(struct cx23885_dev *dev,
u32 risc;
unsigned int i, j, n;
- printk("%s: %s - dma channel status dump\n",
+ printk(KERN_WARNING "%s: %s - dma channel status dump\n",
dev->name, ch->name);
for (i = 0; i < ARRAY_SIZE(name); i++)
- printk("%s: cmds: %-15s: 0x%08x\n",
+ printk(KERN_WARNING "%s: cmds: %-15s: 0x%08x\n",
dev->name, name[i],
cx_read(ch->cmds_start + 4*i));
for (i = 0; i < 4; i++) {
risc = cx_read(ch->cmds_start + 4 * (i + 14));
- printk("%s: risc%d: ", dev->name, i);
+ printk(KERN_WARNING "%s: risc%d: ", dev->name, i);
cx23885_risc_decode(risc);
}
for (i = 0; i < (64 >> 2); i += n) {
risc = cx_read(ch->ctrl_start + 4 * i);
/* No consideration for bits 63-32 */
- printk("%s: (0x%08x) iq %x: ", dev->name,
+ printk(KERN_WARNING "%s: (0x%08x) iq %x: ", dev->name,
ch->ctrl_start + 4 * i, i);
n = cx23885_risc_decode(risc);
for (j = 1; j < n; j++) {
risc = cx_read(ch->ctrl_start + 4 * (i + j));
- printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
+ printk(KERN_WARNING "%s: iq %x: 0x%08x [ arg #%d ]\n",
dev->name, i+j, risc, j);
}
}
- printk("%s: fifo: 0x%08x -> 0x%x\n",
+ printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
- printk("%s: ctrl: 0x%08x -> 0x%x\n",
+ printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
- printk("%s: ptr1_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: ptr1_reg: 0x%08x\n",
dev->name, cx_read(ch->ptr1_reg));
- printk("%s: ptr2_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: ptr2_reg: 0x%08x\n",
dev->name, cx_read(ch->ptr2_reg));
- printk("%s: cnt1_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: cnt1_reg: 0x%08x\n",
dev->name, cx_read(ch->cnt1_reg));
- printk("%s: cnt2_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: cnt2_reg: 0x%08x\n",
dev->name, cx_read(ch->cnt2_reg));
}
@@ -515,13 +513,13 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
struct cx23885_dev *dev = port->dev;
unsigned int i, j, n;
- printk("%s: risc disasm: %p [dma=0x%08lx]\n",
+ printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
dev->name, risc->cpu, (unsigned long)risc->dma);
for (i = 0; i < (risc->size >> 2); i += n) {
- printk("%s: %04d: ", dev->name, i);
+ printk(KERN_INFO "%s: %04d: ", dev->name, i);
n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
for (j = 1; j < n; j++)
- printk("%s: %04d: 0x%08x [ arg #%d ]\n",
+ printk(KERN_INFO "%s: %04d: 0x%08x [ arg #%d ]\n",
dev->name, i + j, risc->cpu[i + j], j);
if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
break;
@@ -600,7 +598,7 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev)
* when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
* occur on the cx23887 bridge.
*/
- if(dev->bridge == CX23885_BRIDGE_885)
+ if (dev->bridge == CX23885_BRIDGE_885)
cx_clear(RDR_TLCTL0, 1 << 4);
return 0;
@@ -608,13 +606,13 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev)
static int get_resources(struct cx23885_dev *dev)
{
- if (request_mem_region(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0),
+ if (request_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0),
dev->name))
return 0;
printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
- dev->name, (unsigned long long)pci_resource_start(dev->pci,0));
+ dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
return -EBUSY;
}
@@ -623,7 +621,8 @@ static void cx23885_timeout(unsigned long data);
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value);
-static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
+static int cx23885_init_tsport(struct cx23885_dev *dev,
+ struct cx23885_tsport *port, int portno)
{
dprintk(1, "%s(portno=%d)\n", __func__, portno);
@@ -643,7 +642,18 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
port->mpegq.timeout.data = (unsigned long)port;
init_timer(&port->mpegq.timeout);
- switch(portno) {
+ mutex_init(&port->frontends.lock);
+ INIT_LIST_HEAD(&port->frontends.felist);
+ port->frontends.active_fe_id = 0;
+
+ /* This should be hardcoded allow a single frontend
+ * attachment to this tsport, keeping the -dvb.c
+ * code clean and safe.
+ */
+ if (!port->num_frontends)
+ port->num_frontends = 1;
+
+ switch (portno) {
case 1:
port->reg_gpcnt = VID_B_GPCNT;
port->reg_gpcnt_ctl = VID_B_GPCNT_CTL;
@@ -744,13 +754,13 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
mutex_unlock(&devlist);
/* Configure the internal memory */
- if(dev->pci->device == 0x8880) {
+ if (dev->pci->device == 0x8880) {
dev->bridge = CX23885_BRIDGE_887;
/* Apply a sensible clock frequency for the PCIe bridge */
dev->clk_freq = 25000000;
dev->sram_channels = cx23887_sram_channels;
} else
- if(dev->pci->device == 0x8852) {
+ if (dev->pci->device == 0x8852) {
dev->bridge = CX23885_BRIDGE_885;
/* Apply a sensible clock frequency for the PCIe bridge */
dev->clk_freq = 28000000;
@@ -831,8 +841,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
}
/* PCIe stuff */
- dev->lmmio = ioremap(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0));
+ dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0));
dev->bmmio = (u8 __iomem *)dev->lmmio;
@@ -862,7 +872,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_i2c_register(&dev->i2c_bus[1]);
cx23885_i2c_register(&dev->i2c_bus[2]);
cx23885_card_setup(dev);
- cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
cx23885_ir_init(dev);
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
@@ -908,8 +918,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
static void cx23885_dev_unregister(struct cx23885_dev *dev)
{
- release_mem_region(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0));
+ release_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0));
if (!atomic_dec_and_test(&dev->refcount))
return;
@@ -936,7 +946,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
iounmap(dev->lmmio);
}
-static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
+static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines)
@@ -957,31 +967,31 @@ static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
}
if (bpl <= sg_dma_len(sg)-offset) {
/* fits into current chunk */
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
- *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
- offset+=bpl;
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += bpl;
} else {
/* scanline needs to be split */
todo = bpl;
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
(sg_dma_len(sg)-offset));
- *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg)-offset);
offset = 0;
sg++;
while (todo > sg_dma_len(sg)) {
- *(rp++)=cpu_to_le32(RISC_WRITE|
+ *(rp++) = cpu_to_le32(RISC_WRITE|
sg_dma_len(sg));
- *(rp++)=cpu_to_le32(sg_dma_address(sg));
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
sg++;
}
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
- *(rp++)=cpu_to_le32(sg_dma_address(sg));
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += todo;
}
offset += padding;
@@ -1010,9 +1020,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
can cause next bpl to start close to a page border. First DMA
region may be smaller than PAGE_SIZE */
/* write and jump need and extra dword */
- instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+ instructions = fields * (1 + ((bpl + padding) * lines)
+ / PAGE_SIZE + lines);
instructions += 2;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1026,7 +1038,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
/* save pointer to jmp instruction address */
risc->jmp = rp;
- BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@@ -1048,7 +1060,8 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
instructions += 1;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1057,7 +1070,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
/* save pointer to jmp instruction address */
risc->jmp = rp;
- BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@@ -1067,7 +1080,8 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
__le32 *rp;
int rc;
- if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, 4*16);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1161,22 +1175,23 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
/* setup fifo + format */
cx23885_sram_channel_setup(dev,
- &dev->sram_channels[ port->sram_chno ],
+ &dev->sram_channels[port->sram_chno],
port->ts_packet_size, buf->risc.dma);
- if(debug > 5) {
- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ] );
+ if (debug > 5) {
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
cx23885_risc_disasm(port, &buf->risc);
}
/* write TS length to chip */
cx_write(port->reg_lngth, buf->vb.width);
- if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
- (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
- printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+ if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+ (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
+ printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
__func__,
cx23885_boards[dev->board].portb,
- cx23885_boards[dev->board].portc );
+ cx23885_boards[dev->board].portc);
return -EINVAL;
}
@@ -1186,7 +1201,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
udelay(100);
/* If the port supports SRC SELECT, configure it */
- if(port->reg_src_sel)
+ if (port->reg_src_sel)
cx_write(port->reg_src_sel, port->src_sel_val);
cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
@@ -1195,7 +1210,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
udelay(100);
- // NOTE: this is 2 (reserved) for portb, does it matter?
+ /* NOTE: this is 2 (reserved) for portb, does it matter? */
/* reset counter to zero */
cx_write(port->reg_gpcnt_ctl, 3);
q->count = 1;
@@ -1229,11 +1244,11 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_write(ALT_PIN_OUT_SEL, 0x10100045);
}
- switch(dev->bridge) {
+ switch (dev->bridge) {
case CX23885_BRIDGE_885:
case CX23885_BRIDGE_887:
/* enable irqs */
- dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
+ dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
cx_set(port->reg_dma_ctl, port->dma_ctl_val);
cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1292,8 +1307,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
struct cx23885_buffer *buf;
dprintk(5, "%s()\n", __func__);
- if (list_empty(&q->active))
- {
+ if (list_empty(&q->active)) {
struct cx23885_buffer *prev;
prev = NULL;
@@ -1311,7 +1325,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(5, "[%p/%d] restart_queue - first active\n",
+ dprintk(5, "[%p/%d] restart_queue - f/active\n",
buf, buf->vb.i);
} else if (prev->vb.width == buf->vb.width &&
@@ -1322,8 +1336,9 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
- dprintk(5,"[%p/%d] restart_queue - move to active\n",
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(5, "[%p/%d] restart_queue - m/active\n",
buf, buf->vb.i);
} else {
return 0;
@@ -1362,7 +1377,8 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
buf->vb.size = size;
buf->vb.field = field /*V4L2_FIELD_TOP*/;
- if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+ rc = videobuf_iolock(q, &buf->vb, NULL);
+ if (0 != rc)
goto fail;
cx23885_risc_databuffer(dev->pci, &buf->risc,
videobuf_to_dma(&buf->vb)->sglist,
@@ -1388,7 +1404,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
if (list_empty(&cx88q->active)) {
- dprintk( 1, "queue is empty - first active\n" );
+ dprintk(1, "queue is empty - first active\n");
list_add_tail(&buf->vb.queue, &cx88q->active);
cx23885_start_dma(port, cx88q, buf);
buf->vb.state = VIDEOBUF_ACTIVE;
@@ -1397,7 +1413,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
dprintk(1, "[%p/%d] %s - first active\n",
buf, buf->vb.i, __func__);
} else {
- dprintk( 1, "queue is not empty - append to active\n" );
+ dprintk(1, "queue is not empty - append to active\n");
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
vb.queue);
list_add_tail(&buf->vb.queue, &cx88q->active);
@@ -1405,7 +1421,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
- dprintk( 1, "[%p/%d] %s - append to active\n",
+ dprintk(1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __func__);
}
}
@@ -1431,7 +1447,7 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
}
if (restart) {
- dprintk(1, "restarting queue\n" );
+ dprintk(1, "restarting queue\n");
cx23885_restart_queue(port, q);
}
spin_unlock_irqrestore(&port->slock, flags);
@@ -1442,7 +1458,7 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port)
struct cx23885_dev *dev = port->dev;
struct cx23885_dmaqueue *q = &port->mpegq;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
del_timer_sync(&q->timeout);
cx23885_stop_dma(port);
do_cancel_buffers(port, "cancel", 0);
@@ -1453,10 +1469,11 @@ static void cx23885_timeout(unsigned long data)
struct cx23885_tsport *port = (struct cx23885_tsport *)data;
struct cx23885_dev *dev = port->dev;
- dprintk(1, "%s()\n",__func__);
+ dprintk(1, "%s()\n", __func__);
if (debug > 5)
- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
cx23885_stop_dma(port);
do_cancel_buffers(port, "timeout", 1);
@@ -1532,16 +1549,23 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
if ((status & VID_BC_MSK_OPC_ERR) ||
(status & VID_BC_MSK_BAD_PKT) ||
(status & VID_BC_MSK_SYNC) ||
- (status & VID_BC_MSK_OF))
- {
+ (status & VID_BC_MSK_OF)) {
+
if (status & VID_BC_MSK_OPC_ERR)
- dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
+ dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+ VID_BC_MSK_OPC_ERR);
+
if (status & VID_BC_MSK_BAD_PKT)
- dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n", VID_BC_MSK_BAD_PKT);
+ dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
+ VID_BC_MSK_BAD_PKT);
+
if (status & VID_BC_MSK_SYNC)
- dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n", VID_BC_MSK_SYNC);
+ dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n",
+ VID_BC_MSK_SYNC);
+
if (status & VID_BC_MSK_OF)
- dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n", VID_BC_MSK_OF);
+ dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n",
+ VID_BC_MSK_OF);
printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
@@ -1595,7 +1619,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
ts2_status = cx_read(VID_C_INT_STAT);
ts2_mask = cx_read(VID_C_INT_MSK);
- if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) )
+ if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
goto out;
vida_count = cx_read(VID_A_GPCNT);
@@ -1610,38 +1634,56 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
ts2_status, ts2_mask, ts2_count);
- if ( (pci_status & PCI_MSK_RISC_RD) ||
- (pci_status & PCI_MSK_RISC_WR) ||
- (pci_status & PCI_MSK_AL_RD) ||
- (pci_status & PCI_MSK_AL_WR) ||
- (pci_status & PCI_MSK_APB_DMA) ||
- (pci_status & PCI_MSK_VID_C) ||
- (pci_status & PCI_MSK_VID_B) ||
- (pci_status & PCI_MSK_VID_A) ||
- (pci_status & PCI_MSK_AUD_INT) ||
- (pci_status & PCI_MSK_AUD_EXT) )
- {
+ if ((pci_status & PCI_MSK_RISC_RD) ||
+ (pci_status & PCI_MSK_RISC_WR) ||
+ (pci_status & PCI_MSK_AL_RD) ||
+ (pci_status & PCI_MSK_AL_WR) ||
+ (pci_status & PCI_MSK_APB_DMA) ||
+ (pci_status & PCI_MSK_VID_C) ||
+ (pci_status & PCI_MSK_VID_B) ||
+ (pci_status & PCI_MSK_VID_A) ||
+ (pci_status & PCI_MSK_AUD_INT) ||
+ (pci_status & PCI_MSK_AUD_EXT)) {
if (pci_status & PCI_MSK_RISC_RD)
- dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", PCI_MSK_RISC_RD);
+ dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
+ PCI_MSK_RISC_RD);
+
if (pci_status & PCI_MSK_RISC_WR)
- dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n", PCI_MSK_RISC_WR);
+ dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n",
+ PCI_MSK_RISC_WR);
+
if (pci_status & PCI_MSK_AL_RD)
- dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n", PCI_MSK_AL_RD);
+ dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n",
+ PCI_MSK_AL_RD);
+
if (pci_status & PCI_MSK_AL_WR)
- dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n", PCI_MSK_AL_WR);
+ dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n",
+ PCI_MSK_AL_WR);
+
if (pci_status & PCI_MSK_APB_DMA)
- dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n", PCI_MSK_APB_DMA);
+ dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n",
+ PCI_MSK_APB_DMA);
+
if (pci_status & PCI_MSK_VID_C)
- dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n", PCI_MSK_VID_C);
+ dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n",
+ PCI_MSK_VID_C);
+
if (pci_status & PCI_MSK_VID_B)
- dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n", PCI_MSK_VID_B);
+ dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n",
+ PCI_MSK_VID_B);
+
if (pci_status & PCI_MSK_VID_A)
- dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n", PCI_MSK_VID_A);
+ dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n",
+ PCI_MSK_VID_A);
+
if (pci_status & PCI_MSK_AUD_INT)
- dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n", PCI_MSK_AUD_INT);
+ dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n",
+ PCI_MSK_AUD_INT);
+
if (pci_status & PCI_MSK_AUD_EXT)
- dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n", PCI_MSK_AUD_EXT);
+ dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n",
+ PCI_MSK_AUD_EXT);
}
@@ -1753,13 +1795,13 @@ static struct pci_device_id cx23885_pci_tbl[] = {
.device = 0x8852,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- },{
+ }, {
/* CX23887 Rev 2 */
.vendor = 0x14f1,
.device = 0x8880,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- },{
+ }, {
/* --- end of list --- */
}
};
@@ -1797,9 +1839,3 @@ module_init(cx23885_init);
module_exit(cx23885_fini);
/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 0a2e6558cd6..e1aac07b315 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
@@ -42,6 +42,7 @@
#include "tuner-simple.h"
#include "dib7000p.h"
#include "dibx000_common.h"
+#include "zl10353.h"
static unsigned int debug;
@@ -77,19 +78,19 @@ static int dvb_buf_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb, enum v4l2_field field)
{
struct cx23885_tsport *port = q->priv_data;
- return cx23885_buf_prepare(q, port, (struct cx23885_buffer*)vb, field);
+ return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
}
static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct cx23885_tsport *port = q->priv_data;
- cx23885_buf_queue(port, (struct cx23885_buffer*)vb);
+ cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
}
static void dvb_buf_release(struct videobuf_queue *q,
struct videobuf_buffer *vb)
{
- cx23885_free_buffer(q, (struct cx23885_buffer*)vb);
+ cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
}
static struct videobuf_queue_ops dvb_qops = {
@@ -188,13 +189,11 @@ static struct s5h1411_config dvico_s5h1411_config = {
static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
.i2c_address = 0x61,
.if_khz = 5380,
- .tuner_callback = cx23885_tuner_callback
};
static struct xc5000_config dvico_xc5000_tunerconfig = {
.i2c_address = 0x64,
.if_khz = 5380,
- .tuner_callback = cx23885_tuner_callback
};
static struct tda829x_config tda829x_no_probe = {
@@ -303,53 +302,35 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
.output_mode = OUTMODE_MPEG2_SERIAL,
};
-static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
-{
- struct cx23885_tsport *port = ptr;
- struct cx23885_dev *dev = port->dev;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- /* Send the tuner in then out of reset */
- /* GPIO-2 xc3028 tuner */
- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
-
- cx_set(GP0_IO, 0x00040000);
- cx_clear(GP0_IO, 0x00000004);
- msleep(5);
-
- cx_set(GP0_IO, 0x00040004);
- msleep(5);
- break;
- case XC2028_RESET_CLK:
- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
- break;
- default:
- dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
- command, arg);
- return -EINVAL;
- }
-
- return 0;
-}
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+ .demod_address = 0x0f,
+ .if2 = 45600,
+ .no_tuner = 1,
+};
static int dvb_register(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
struct cx23885_i2c *i2c_bus = NULL;
+ struct videobuf_dvb_frontend *fe0;
+
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
/* init struct videobuf_dvb */
- port->dvb.name = dev->name;
+ fe0->dvb.name = dev->name;
/* init frontend */
switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
i2c_bus = &dev->i2c_bus[0];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_generic_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(mt2131_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&hauppauge_generic_tunerconfig, 0);
}
@@ -358,27 +339,27 @@ static int dvb_register(struct cx23885_tsport *port)
i2c_bus = &dev->i2c_bus[0];
switch (alt_tuner) {
case 1:
- port->dvb.frontend =
+ fe0->dvb.frontend =
dvb_attach(s5h1409_attach,
&hauppauge_ezqam_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(tda829x_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda829x_attach, fe0->dvb.frontend,
&dev->i2c_bus[1].i2c_adap, 0x42,
&tda829x_no_probe);
- dvb_attach(tda18271_attach, port->dvb.frontend,
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
0x60, &dev->i2c_bus[1].i2c_adap,
&hauppauge_tda18271_config);
}
break;
case 0:
default:
- port->dvb.frontend =
+ fe0->dvb.frontend =
dvb_attach(s5h1409_attach,
&hauppauge_generic_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL)
- dvb_attach(mt2131_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&hauppauge_generic_tunerconfig, 0);
break;
@@ -386,56 +367,55 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
i2c_bus = &dev->i2c_bus[0];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1800lp_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(mt2131_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&hauppauge_generic_tunerconfig, 0);
}
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
i2c_bus = &dev->i2c_bus[0];
- port->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_5_express,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap, 0x61,
TUNER_LG_TDVS_H06XF);
}
break;
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
i2c_bus = &dev->i2c_bus[1];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1500q_config,
&dev->i2c_bus[0].i2c_adap);
- if (port->dvb.frontend != NULL)
- dvb_attach(xc5000_attach, port->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_hvr1500q_tunerconfig, i2c_bus);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(xc5000_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_hvr1500q_tunerconfig);
break;
case CX23885_BOARD_HAUPPAUGE_HVR1500:
i2c_bus = &dev->i2c_bus[1];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1500_config,
&dev->i2c_bus[0].i2c_adap);
- if (port->dvb.frontend != NULL) {
+ if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
struct xc2028_config cfg = {
.i2c_adap = &i2c_bus->i2c_adap,
.i2c_addr = 0x61,
- .callback = cx23885_hvr1500_xc3028_callback,
};
static struct xc2028_ctrl ctl = {
- .fname = "xc3028-v27.fw",
+ .fname = XC2028_DEFAULT_FIRMWARE,
.max_len = 64,
.scode_table = XC3028_FE_OREN538,
};
fe = dvb_attach(xc2028_attach,
- port->dvb.frontend, &cfg);
+ fe0->dvb.frontend, &cfg);
if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
@@ -443,39 +423,40 @@ static int dvb_register(struct cx23885_tsport *port)
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
i2c_bus = &dev->i2c_bus[0];
- port->dvb.frontend = dvb_attach(tda10048_attach,
+ fe0->dvb.frontend = dvb_attach(tda10048_attach,
&hauppauge_hvr1200_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL) {
- dvb_attach(tda829x_attach, port->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda829x_attach, fe0->dvb.frontend,
&dev->i2c_bus[1].i2c_adap, 0x42,
&tda829x_no_probe);
- dvb_attach(tda18271_attach, port->dvb.frontend,
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
0x60, &dev->i2c_bus[1].i2c_adap,
&hauppauge_hvr1200_tuner_config);
}
break;
case CX23885_BOARD_HAUPPAUGE_HVR1400:
i2c_bus = &dev->i2c_bus[0];
- port->dvb.frontend = dvb_attach(dib7000p_attach,
+ fe0->dvb.frontend = dvb_attach(dib7000p_attach,
&i2c_bus->i2c_adap,
0x12, &hauppauge_hvr1400_dib7000_config);
- if (port->dvb.frontend != NULL) {
+ if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
struct xc2028_config cfg = {
.i2c_adap = &dev->i2c_bus[1].i2c_adap,
.i2c_addr = 0x64,
- .callback = cx23885_hvr1500_xc3028_callback,
};
static struct xc2028_ctrl ctl = {
- .fname = "xc3028L-v36.fw",
+ .fname = XC3028L_DEFAULT_FIRMWARE,
.max_len = 64,
.demod = 5000,
- .d2633 = 1
+ /* This is true for all demods with
+ v36 firmware? */
+ .type = XC2028_D2633,
};
fe = dvb_attach(xc2028_attach,
- port->dvb.frontend, &cfg);
+ fe0->dvb.frontend, &cfg);
if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
@@ -483,77 +464,163 @@ static int dvb_register(struct cx23885_tsport *port)
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
i2c_bus = &dev->i2c_bus[port->nr - 1];
- port->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&dvico_s5h1409_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend == NULL)
- port->dvb.frontend = dvb_attach(s5h1411_attach,
+ if (fe0->dvb.frontend == NULL)
+ fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&dvico_s5h1411_config,
&i2c_bus->i2c_adap);
- if (port->dvb.frontend != NULL)
- dvb_attach(xc5000_attach, port->dvb.frontend,
- &i2c_bus->i2c_adap,
- &dvico_xc5000_tunerconfig, i2c_bus);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(xc5000_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &dvico_xc5000_tunerconfig);
+ break;
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
+ i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &dvico_fusionhdtv_xc3028,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ struct dvb_frontend *fe;
+ struct xc2028_config cfg = {
+ .i2c_adap = &i2c_bus->i2c_adap,
+ .i2c_addr = 0x61,
+ };
+ static struct xc2028_ctrl ctl = {
+ .fname = XC2028_DEFAULT_FIRMWARE,
+ .max_len = 64,
+ .demod = XC3028_FE_ZARLINK456,
+ };
+
+ fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
+ &cfg);
+ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+ fe->ops.tuner_ops.set_config(fe, &ctl);
+ }
+ break;
+ }
+ case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+ i2c_bus = &dev->i2c_bus[0];
+
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &dvico_fusionhdtv_xc3028,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ struct dvb_frontend *fe;
+ struct xc2028_config cfg = {
+ .i2c_adap = &dev->i2c_bus[1].i2c_adap,
+ .i2c_addr = 0x61,
+ };
+ static struct xc2028_ctrl ctl = {
+ .fname = XC2028_DEFAULT_FIRMWARE,
+ .max_len = 64,
+ .demod = XC3028_FE_ZARLINK456,
+ };
+
+ fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
+ &cfg);
+ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+ fe->ops.tuner_ops.set_config(fe, &ctl);
+ }
break;
default:
- printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+ printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
+ " isn't supported yet\n",
dev->name);
break;
}
- if (NULL == port->dvb.frontend) {
- printk("%s: frontend initialization failed\n", dev->name);
+ if (NULL == fe0->dvb.frontend) {
+ printk(KERN_ERR "%s: frontend initialization failed\n",
+ dev->name);
return -1;
}
+ /* define general-purpose callback pointer */
+ fe0->dvb.frontend->callback = cx23885_tuner_callback;
/* Put the analog decoder in standby to keep it quiet */
cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
- if (port->dvb.frontend->ops.analog_ops.standby)
- port->dvb.frontend->ops.analog_ops.standby(port->dvb.frontend);
+ if (fe0->dvb.frontend->ops.analog_ops.standby)
+ fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
/* register everything */
- return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
- &dev->pci->dev, adapter_nr);
+ return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+ &dev->pci->dev, adapter_nr, 0);
+
}
int cx23885_dvb_register(struct cx23885_tsport *port)
{
+
+ struct videobuf_dvb_frontend *fe0;
struct cx23885_dev *dev = port->dev;
- int err;
+ int err, i;
+
+ /* Here we need to allocate the correct number of frontends,
+ * as reflected in the cards struct. The reality is that currrently
+ * no cx23885 boards support this - yet. But, if we don't modify this
+ * code then the second frontend would never be allocated (later)
+ * and fail with error before the attach in dvb_register().
+ * Without these changes we risk an OOPS later. The changes here
+ * are for safety, and should provide a good foundation for the
+ * future addition of any multi-frontend cx23885 based boards.
+ */
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+ port->num_frontends);
+
+ for (i = 1; i <= port->num_frontends; i++) {
+ if (videobuf_dvb_alloc_frontend(
+ &port->frontends, i) == NULL) {
+ printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ return -ENOMEM;
+ }
+
+ fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
+ if (!fe0)
+ err = -EINVAL;
- dprintk(1, "%s\n", __func__);
- dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
- dev->board,
- dev->name,
- dev->pci_bus,
- dev->pci_slot);
+ dprintk(1, "%s\n", __func__);
+ dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ dev->board,
+ dev->name,
+ dev->pci_bus,
+ dev->pci_slot);
- err = -ENODEV;
+ err = -ENODEV;
- /* dvb stuff */
- printk("%s: cx23885 based dvb card\n", dev->name);
- videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+ /* dvb stuff */
+ /* We have to init the queue for each frontend on a port. */
+ printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+ videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
+ &dev->pci->dev, &port->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
sizeof(struct cx23885_buffer), port);
+ }
err = dvb_register(port);
if (err != 0)
- printk("%s() dvb_register failed err = %d\n", __func__, err);
+ printk(KERN_ERR "%s() dvb_register failed err = %d\n",
+ __func__, err);
return err;
}
int cx23885_dvb_unregister(struct cx23885_tsport *port)
{
- /* dvb */
- if(port->dvb.frontend)
- videobuf_dvb_unregister(&port->dvb);
+ struct videobuf_dvb_frontend *fe0;
+
+ /* FIXME: in an error condition where the we have
+ * an expected number of frontends (attach problem)
+ * then this might not clean up correctly, if 1
+ * is invalid.
+ * This comment only applies to future boards IF they
+ * implement MFE support.
+ */
+ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+ if (fe0->dvb.frontend)
+ videobuf_dvb_unregister_bus(&port->frontends);
return 0;
}
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
-*/
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index c6bb0a05bc1..bb7f71a1fcb 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
@@ -131,7 +131,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
printk(" >\n");
}
- for (cnt = 1; cnt < msg->len; cnt++ ) {
+ for (cnt = 1; cnt < msg->len; cnt++) {
/* following bytes */
wdata = msg->buf[cnt];
ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
@@ -151,9 +151,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
if (retval == 0)
goto eio;
if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
+ dprintk(1, " %02x", msg->buf[cnt]);
if (!(ctrl & I2C_NOSTOP))
- printk(" >\n");
+ dprintk(1, " >\n");
}
}
return msg->len;
@@ -162,7 +162,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(KERN_ERR " ERR: %d\n", retval);
return retval;
}
@@ -194,12 +194,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
if (i2c_debug) {
if (joined)
- printk(" R");
+ dprintk(1, " R");
else
- printk(" <R %02x", (msg->addr << 1) + 1);
+ dprintk(1, " <R %02x", (msg->addr << 1) + 1);
}
- for(cnt = 0; cnt < msg->len; cnt++) {
+ for (cnt = 0; cnt < msg->len; cnt++) {
ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
@@ -216,9 +216,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
goto eio;
msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
+ dprintk(1, " %02x", msg->buf[cnt]);
if (!(ctrl & I2C_NOSTOP))
- printk(" >\n");
+ dprintk(1, " >\n");
}
}
return msg->len;
@@ -227,7 +227,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(KERN_ERR " ERR: %d\n", retval);
return retval;
}
@@ -353,17 +353,17 @@ static struct i2c_client cx23885_i2c_client_template = {
};
static char *i2c_devs[128] = {
- [0x10 >> 1] = "tda10048",
- [0x12 >> 1] = "dib7000pc",
- [ 0x1c >> 1 ] = "lgdt3303",
- [ 0x86 >> 1 ] = "tda9887",
- [ 0x32 >> 1 ] = "cx24227",
- [ 0x88 >> 1 ] = "cx25837",
- [ 0x84 >> 1 ] = "tda8295",
- [ 0xa0 >> 1 ] = "eeprom",
- [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+ [0x10 >> 1] = "tda10048",
+ [0x12 >> 1] = "dib7000pc",
+ [0x1c >> 1] = "lgdt3303",
+ [0x86 >> 1] = "tda9887",
+ [0x32 >> 1] = "cx24227",
+ [0x88 >> 1] = "cx25837",
+ [0x84 >> 1] = "tda8295",
+ [0xa0 >> 1] = "eeprom",
+ [0xc0 >> 1] = "tuner/mt2131/tda8275",
[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
- [0xc8 >> 1] = "tuner/xc3028L",
+ [0xc8 >> 1] = "tuner/xc3028L",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -376,7 +376,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
rc = i2c_master_recv(c, &buf, 0);
if (rc < 0)
continue;
- printk("%s: i2c scan: found device @ 0x%x [%s]\n",
+ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
@@ -408,11 +408,12 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
bus->i2c_client.adapter = &bus->i2c_adap;
if (0 == bus->i2c_rc) {
- printk("%s: i2c bus %d registered\n", dev->name, bus->nr);
+ dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
if (i2c_scan)
do_i2c_scan(dev->name, &bus->i2c_client);
} else
- printk("%s: i2c bus %d register FAILED\n", dev->name, bus->nr);
+ printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
+ dev->name, bus->nr);
return bus->i2c_rc;
}
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index bdd11bc513a..20b68a23626 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c
index e36e3fcae2f..5b297f0323b 100644
--- a/drivers/media/video/cx23885/cx23885-vbi.c
+++ b/drivers/media/video/cx23885/cx23885-vbi.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2007 Steven Toth <stoth@linuxtv.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
@@ -85,18 +85,8 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
return 0;
}
-int cx23885_stop_vbi_dma(struct cx23885_dev *dev)
-{
- /* stop dma */
- cx_clear(VID_A_DMA_CTL, 0x00000022);
-
- /* disable irqs */
- cx_clear(PCI_INT_MSK, 0x000001);
- cx_clear(VID_A_INT_MSK, 0x00000022);
- return 0;
-}
-int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+static int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q)
{
struct cx23885_buffer *buf;
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index ad2235dab5b..ab3110d6046 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2007 Steven Toth <stoth@linuxtv.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
@@ -41,7 +41,7 @@
#endif
MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------------ */
@@ -244,7 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = {
};
static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
-const u32 cx23885_user_ctrls[] = {
+static const u32 cx23885_user_ctrls[] = {
V4L2_CID_USER_CLASS,
V4L2_CID_BRIGHTNESS,
V4L2_CID_CONTRAST,
@@ -254,14 +254,13 @@ const u32 cx23885_user_ctrls[] = {
V4L2_CID_AUDIO_MUTE,
0
};
-EXPORT_SYMBOL(cx23885_user_ctrls);
static const u32 *ctrl_classes[] = {
cx23885_user_ctrls,
NULL
};
-void cx23885_video_wakeup(struct cx23885_dev *dev,
+static void cx23885_video_wakeup(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q, u32 count)
{
struct cx23885_buffer *buf;
@@ -286,17 +285,16 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
- if (list_empty(&q->active)) {
+ if (list_empty(&q->active))
del_timer(&q->timeout);
- } else {
+ else
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- }
if (bc != 1)
printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
__func__, bc);
}
-int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
{
dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
__func__,
@@ -314,7 +312,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
return 0;
}
-struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
struct pci_dev *pci,
struct video_device *template,
char *type)
@@ -334,7 +332,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
return vfd;
}
-int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
+static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
{
int i;
@@ -351,7 +349,6 @@ int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
*qctrl = cx23885_ctls[i].v;
return 0;
}
-EXPORT_SYMBOL(cx23885_ctrl_query);
/* ------------------------------------------------------------------- */
/* resource management */
@@ -381,12 +378,12 @@ static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
static int res_check(struct cx23885_fh *fh, unsigned int bit)
{
- return (fh->resources & bit);
+ return fh->resources & bit;
}
static int res_locked(struct cx23885_dev *dev, unsigned int bit)
{
- return (dev->resources & bit);
+ return dev->resources & bit;
}
static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
@@ -402,7 +399,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
mutex_unlock(&dev->lock);
}
-int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
{
struct v4l2_routing route;
memset(&route, 0, sizeof(route));
@@ -422,10 +419,9 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
return 0;
}
-EXPORT_SYMBOL(cx23885_video_mux);
/* ------------------------------------------------------------------ */
-int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
+static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
unsigned int height, enum v4l2_field field)
{
dprintk(1, "%s()\n", __func__);
@@ -731,6 +727,7 @@ static int video_open(struct inode *inode, struct file *file)
enum v4l2_buf_type type = 0;
int radio = 0;
+ lock_kernel();
list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist);
if (h->video_dev->minor == minor) {
@@ -748,16 +745,20 @@ static int video_open(struct inode *inode, struct file *file)
dev = h;
}
}
- if (NULL == dev)
+ if (NULL == dev) {
+ unlock_kernel();
return -ENODEV;
+ }
dprintk(1, "open minor=%d radio=%d type=%s\n",
minor, radio, v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -775,6 +776,7 @@ static int video_open(struct inode *inode, struct file *file)
dprintk(1, "post videobuf_queue_init()\n");
+ unlock_kernel();
return 0;
}
@@ -884,21 +886,21 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS */
-int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_get_control(struct cx23885_dev *dev,
+ struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
return 0;
}
-EXPORT_SYMBOL(cx23885_get_control);
-int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_set_control(struct cx23885_dev *dev,
+ struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
" (disabled - no action)\n", __func__);
return 0;
}
-EXPORT_SYMBOL(cx23885_set_control);
static void init_controls(struct cx23885_dev *dev)
{
@@ -1072,29 +1074,29 @@ static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_reqbufs(get_queue(fh), p));
+ return videobuf_reqbufs(get_queue(fh), p);
}
static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_querybuf(get_queue(fh), p));
+ return videobuf_querybuf(get_queue(fh), p);
}
static int vidioc_qbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_qbuf(get_queue(fh), p));
+ return videobuf_qbuf(get_queue(fh), p);
}
static int vidioc_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_dqbuf(get_queue(fh), p,
- file->f_flags & O_NONBLOCK));
+ return videobuf_dqbuf(get_queue(fh), p,
+ file->f_flags & O_NONBLOCK);
}
static int vidioc_streamon(struct file *file, void *priv,
@@ -1146,7 +1148,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
return 0;
}
-int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
{
static const char *iname[] = {
[CX23885_VMUX_COMPOSITE1] = "Composite1",
@@ -1179,7 +1181,6 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
i->std = CX23885_NORMS;
return 0;
}
-EXPORT_SYMBOL(cx23885_enum_input);
static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
@@ -1288,7 +1289,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
return 0;
}
-int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
+static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
{
if (unlikely(UNSET == dev->tuner_type))
return -EINVAL;
@@ -1307,7 +1308,6 @@ int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
return 0;
}
-EXPORT_SYMBOL(cx23885_set_freq);
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index 00dfdc89d64..1d53f54cd94 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -1,7 +1,7 @@
/*
* Driver for the Conexant CX23885 PCIe bridge
*
- * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ * Copyright (c) 2006 Steven Toth <stoth@linuxtv.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
@@ -37,7 +37,7 @@
#include <linux/version.h>
#include <linux/mutex.h>
-#define CX23885_VERSION_CODE KERNEL_VERSION(0,0,1)
+#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 1)
#define UNSET (-1U)
@@ -64,6 +64,8 @@
#define CX23885_BOARD_HAUPPAUGE_HVR1700 8
#define CX23885_BOARD_HAUPPAUGE_HVR1400 9
#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
+#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12
/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
#define CX23885_NORMS (\
@@ -223,7 +225,7 @@ struct cx23885_tsport {
int nr;
int sram_chno;
- struct videobuf_dvb dvb;
+ struct videobuf_dvb_frontends frontends;
/* dma queues */
struct cx23885_dmaqueue mpegq;
@@ -260,6 +262,9 @@ struct cx23885_tsport {
u32 src_sel_val;
u32 vld_misc_val;
u32 hw_sop_ctrl_val;
+
+ /* Allow a single tsport to have multiple frontends */
+ u32 num_frontends;
};
struct cx23885_dev {
@@ -365,14 +370,14 @@ struct sram_channel {
/* ----------------------------------------------------------- */
#define cx_read(reg) readl(dev->lmmio + ((reg)>>2))
-#define cx_write(reg,value) writel((value), dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2))
-#define cx_andor(reg,mask,value) \
+#define cx_andor(reg, mask, value) \
writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
((value) & (mask)), dev->lmmio+((reg)>>2))
-#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
-#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
+#define cx_set(reg, bit) cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit) cx_andor((reg), (bit), 0)
/* ----------------------------------------------------------- */
/* cx23885-core.c */
@@ -409,7 +414,8 @@ extern const unsigned int cx23885_bcount;
extern struct cx23885_subid cx23885_subids[];
extern const unsigned int cx23885_idcount;
-extern int cx23885_tuner_callback(void *priv, int command, int arg);
+extern int cx23885_tuner_callback(void *priv, int component,
+ int command, int arg);
extern void cx23885_card_list(struct cx23885_dev *dev);
extern int cx23885_ir_init(struct cx23885_dev *dev);
extern void cx23885_gpio_setup(struct cx23885_dev *dev);
@@ -477,11 +483,3 @@ static inline unsigned int norm_swidth(v4l2_std_id norm)
{
return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
}
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 209d3bcb5db..4da8cd74f00 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -13,7 +13,7 @@
* NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
* with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
*
- * CX23885 support by Steven Toth <stoth@hauppauge.com>.
+ * CX23885 support by Steven Toth <stoth@linuxtv.org>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 69f2bbdbb92..58e6ef1c28a 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -141,10 +141,11 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
u8 lcr[24];
fmt = arg;
- if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
+ fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
return -EINVAL;
svbi = &fmt->fmt.sliced;
- if (svbi->service_set == 0) {
+ if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
/* raw VBI */
memset(svbi, 0, sizeof(*svbi));
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 9dd7bdf659b..0b9e5fac623 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -58,6 +58,10 @@ config VIDEO_CX88_DVB
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+ select DVB_CX24116 if !DVB_FE_CUSTOMISE
+ select DVB_STV0299 if !DVB_FE_CUSTOMISE
+ select DVB_STV0288 if !DVB_FE_CUSTOMISE
+ select DVB_STB6000 if !DVB_FE_CUSTOMISE
---help---
This adds support for DVB/ATSC cards based on the
Conexant 2388x chip.
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 9a1374a38ec..e7136975430 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1057,12 +1057,15 @@ static int mpeg_open(struct inode *inode, struct file *file)
struct cx8802_driver *drv = NULL;
int err;
+ lock_kernel();
dev = cx8802_get_device(inode);
dprintk( 1, "%s\n", __func__);
- if (dev == NULL)
+ if (dev == NULL) {
+ unlock_kernel();
return -ENODEV;
+ }
/* Make sure we can acquire the hardware */
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
@@ -1070,6 +1073,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
err = drv->request_acquire(drv);
if(err != 0) {
dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+ unlock_kernel();
return err;
}
}
@@ -1077,6 +1081,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
if (blackbird_initialize_codec(dev) < 0) {
if (drv)
drv->request_release(drv);
+ unlock_kernel();
return -EINVAL;
}
dprintk(1,"open minor=%d\n",minor);
@@ -1086,6 +1091,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
if (NULL == fh) {
if (drv)
drv->request_release(drv);
+ unlock_kernel();
return -ENOMEM;
}
file->private_data = fh;
@@ -1101,6 +1107,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
/* FIXME: locking against other video device */
cx88_set_scale(dev->core, dev->width, dev->height,
fh->mpegq.field);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index de199a206a1..fbc224f46e0 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1270,27 +1270,40 @@ static const struct cx88_board cx88_boards[] = {
.mpeg = CX88_MPEG_DVB,
},
[CX88_BOARD_HAUPPAUGE_HVR3000] = {
- /* FIXME: Add dvb & radio support */
.name = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
.tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .audio_chip = V4L2_IDENT_WM8775,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x84bf,
+ /* 1: TV Audio / FM Mono */
+ .audioroute = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x84bf,
+ /* 2: Line-In */
+ .audioroute = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x84bf,
+ /* 2: Line-In */
+ .audioroute = 2,
}},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x84bf,
+ /* 4: FM Stereo (untested) */
+ .audioroute = 8,
+ },
.mpeg = CX88_MPEG_DVB,
+ .num_frontends = 2,
},
[CX88_BOARD_NORWOOD_MICRO] = {
.name = "Norwood Micro TV Tuner",
@@ -1349,27 +1362,34 @@ static const struct cx88_board cx88_boards[] = {
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.audio_chip = V4L2_IDENT_WM8775,
+ /*
+ * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
+ */
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0xe780,
+ .gpio0 = 0xef88,
+ /* 1: TV Audio / FM Mono */
.audioroute = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0xe780,
+ .gpio0 = 0xef88,
+ /* 2: Line-In */
.audioroute = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0xe780,
+ .gpio0 = 0xef88,
+ /* 2: Line-In */
.audioroute = 2,
}},
- /* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
.radio = {
.type = CX88_RADIO,
- .gpio0 = 0xe780,
+ .gpio0 = 0xef88,
+ /* 4: FM Stereo (untested) */
+ .audioroute = 8,
},
},
[CX88_BOARD_ADSTECH_PTV_390] = {
@@ -1446,15 +1466,26 @@ static const struct cx88_board cx88_boards[] = {
.name = "Pinnacle Hybrid PCTV",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
+ .radio_type = TUNER_XC2028,
+ .radio_addr = 0x61,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .gpio0 = 0x004ff,
+ .gpio1 = 0x010ff,
+ .gpio2 = 0x00001,
}, {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ .gpio0 = 0x004fb,
+ .gpio1 = 0x010ef,
+ .audioroute = 1,
}, {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x004fb,
+ .gpio1 = 0x010ef,
+ .audioroute = 1,
} },
.radio = {
.type = CX88_RADIO,
@@ -1462,6 +1493,7 @@ static const struct cx88_board cx88_boards[] = {
.gpio1 = 0x010ff,
.gpio2 = 0x0ff,
},
+ .mpeg = CX88_MPEG_DVB,
},
[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
.name = "Winfast TV2000 XP Global",
@@ -1566,9 +1598,9 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
.name = "DViCO FusionHDTV DVB-T PRO",
- .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */
+ .tuner_type = TUNER_XC2028,
+ .tuner_addr = 0x61,
.radio_type = UNSET,
- .tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_COMPOSITE1,
@@ -1625,6 +1657,36 @@ static const struct cx88_board cx88_boards[] = {
.gpio2 = 0x0cfb,
},
},
+ [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
+ .name = "Prolink Pixelview Global Extreme",
+ .tuner_type = TUNER_XC2028,
+ .tuner_addr = 0x61,
+ .input = { {
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x04fb,
+ .gpio1 = 0x04080,
+ .gpio2 = 0x0cf7,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x04fb,
+ .gpio1 = 0x04080,
+ .gpio2 = 0x0cfb,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x04fb,
+ .gpio1 = 0x04080,
+ .gpio2 = 0x0cfb,
+ } },
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x04ff,
+ .gpio1 = 0x04080,
+ .gpio2 = 0x0cf7,
+ },
+ },
/* Both radio, analog and ATSC work with this board.
However, for analog to work, s5h1409 gate should be open,
otherwise, tuner-xc3028 won't be detected.
@@ -1664,6 +1726,151 @@ static const struct cx88_board cx88_boards[] = {
},
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_HAUPPAUGE_HVR4000] = {
+ .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .audio_chip = V4L2_IDENT_WM8775,
+ /*
+ * GPIO0 (WINTV2000)
+ *
+ * Analogue SAT DVB-T
+ * Antenna 0xc4bf 0xc4bb
+ * Composite 0xc4bf 0xc4bb
+ * S-Video 0xc4bf 0xc4bb
+ * Composite1 0xc4ff 0xc4fb
+ * S-Video1 0xc4ff 0xc4fb
+ *
+ * BIT VALUE FUNCTION GP{x}_IO
+ * 0 1 I:?
+ * 1 1 I:?
+ * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S
+ * 3 1 I:?
+ * 4 1 I:?
+ * 5 1 I:?
+ * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
+ * 7 1 O:DVB-T DEMOD RESET LOW
+ *
+ * BIT VALUE FUNCTION GP{x}_OE
+ * 8 0 I
+ * 9 0 I
+ * a 1 O
+ * b 0 I
+ * c 0 I
+ * d 0 I
+ * e 1 O
+ * f 1 O
+ *
+ * WM8775 ADC
+ *
+ * 1: TV Audio / FM Mono
+ * 2: Line-In
+ * 3: Line-In Expansion
+ * 4: FM Stereo
+ */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xc4bf,
+ /* 1: TV Audio / FM Mono */
+ .audioroute = 1,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xc4bf,
+ /* 2: Line-In */
+ .audioroute = 2,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xc4bf,
+ /* 2: Line-In */
+ .audioroute = 2,
+ } },
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xc4bf,
+ /* 4: FM Stereo */
+ .audioroute = 8,
+ },
+ .mpeg = CX88_MPEG_DVB,
+ .num_frontends = 2,
+ },
+ [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
+ .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_TEVII_S420] = {
+ .name = "TeVii S420 DVB-S",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_TEVII_S460] = {
+ .name = "TeVii S460 DVB-S/S2",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_OMICOM_SS4_PCI] = {
+ .name = "Omicom SS4 DVB-S/S2 PCI",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_TBS_8920] = {
+ .name = "TBS 8920 DVB-S/S2",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 1,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
+ [CX88_BOARD_PROF_7300] = {
+ .name = "PROF 7300 DVB-S/S2",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
};
/* ------------------------------------------------------------------ */
@@ -2010,9 +2217,53 @@ static const struct cx88_subid cx88_subids[] = {
.subdevice = 0x4935,
.card = CX88_BOARD_PROLINK_PV_8000GT,
}, {
+ .subvendor = 0x1554,
+ .subdevice = 0x4976,
+ .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
+ }, {
.subvendor = 0x17de,
.subdevice = 0x08c1,
.card = CX88_BOARD_KWORLD_ATSC_120,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6900,
+ .card = CX88_BOARD_HAUPPAUGE_HVR4000,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6904,
+ .card = CX88_BOARD_HAUPPAUGE_HVR4000,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6902,
+ .card = CX88_BOARD_HAUPPAUGE_HVR4000,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6905,
+ .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6906,
+ .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+ }, {
+ .subvendor = 0xd420,
+ .subdevice = 0x9022,
+ .card = CX88_BOARD_TEVII_S420,
+ }, {
+ .subvendor = 0xd460,
+ .subdevice = 0x9022,
+ .card = CX88_BOARD_TEVII_S460,
+ }, {
+ .subvendor = 0xA044,
+ .subdevice = 0x2011,
+ .card = CX88_BOARD_OMICOM_SS4_PCI,
+ }, {
+ .subvendor = 0x8920,
+ .subdevice = 0x8888,
+ .card = CX88_BOARD_TBS_8920,
+ }, {
+ .subvendor = 0xB033,
+ .subdevice = 0x3033,
+ .card = CX88_BOARD_PROF_7300,
},
};
@@ -2065,6 +2316,13 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
case 34519: /* WinTV-PCI-FM */
+ case 69009:
+ /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
+ case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
+ case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
+ case 69559:
+ /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
+ case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */
@@ -2149,9 +2407,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core,
{
switch (command) {
case XC2028_TUNER_RESET:
- cx_write(MO_GP0_IO, 0x101000);
- mdelay(5);
- cx_set(MO_GP0_IO, 0x101010);
+ switch (core->boardnr) {
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+ /* GPIO-4 xc3028 tuner */
+
+ cx_set(MO_GP0_IO, 0x00001000);
+ cx_clear(MO_GP0_IO, 0x00000010);
+ msleep(100);
+ cx_set(MO_GP0_IO, 0x00000010);
+ msleep(100);
+ break;
+ default:
+ cx_write(MO_GP0_IO, 0x101000);
+ mdelay(5);
+ cx_set(MO_GP0_IO, 0x101010);
+ }
break;
default:
return -EINVAL;
@@ -2258,8 +2528,10 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
return cx88_xc3028_geniatech_tuner_callback(core,
command, arg);
case CX88_BOARD_PROLINK_PV_8000GT:
+ case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
return cx88_pv_8000gt_callback(core, command, arg);
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
return cx88_dvico_xc2028_callback(core, command, arg);
}
@@ -2327,7 +2599,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core,
return 0; /* Should never be here */
}
-int cx88_tuner_callback(void *priv, int command, int arg)
+int cx88_tuner_callback(void *priv, int component, int command, int arg)
{
struct i2c_algo_bit_data *i2c_algo = priv;
struct cx88_core *core;
@@ -2344,6 +2616,9 @@ int cx88_tuner_callback(void *priv, int command, int arg)
return -EINVAL;
}
+ if (component != DVB_FRONTEND_COMPONENT_TUNER)
+ return -EINVAL;
+
switch (core->board.tuner_type) {
case TUNER_XC2028:
info_printk(core, "Calling XC2028/3028 callback\n");
@@ -2392,16 +2667,22 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
{
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_HVR1300:
- /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */
- /* We leave here with the 702 on the bus */
- cx_write(MO_GP0_IO, 0x0000e780);
+ /*
+ * Bring the 702 demod up before i2c scanning/attach or devices are hidden
+ * We leave here with the 702 on the bus
+ *
+ * "reset the IR receiver on GPIO[3]"
+ * Reported by Mike Crash <mike AT mikecrash.com>
+ */
+ cx_write(MO_GP0_IO, 0x0000ef88);
udelay(1000);
- cx_clear(MO_GP0_IO, 0x00000080);
+ cx_clear(MO_GP0_IO, 0x00000088);
udelay(50);
- cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+ cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
udelay(1000);
break;
+ case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
case CX88_BOARD_PROLINK_PV_8000GT:
cx_write(MO_GP2_IO, 0xcf7);
mdelay(50);
@@ -2411,10 +2692,21 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
msleep(10);
break;
- case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
/* Enable the xc5000 tuner */
cx_set(MO_GP0_IO, 0x00001010);
break;
+
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ /* Init GPIO */
+ cx_write(MO_GP0_IO, core->board.input[0].gpio0);
+ udelay(1000);
+ cx_clear(MO_GP0_IO, 0x00000080);
+ udelay(50);
+ cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+ udelay(1000);
+ break;
}
}
@@ -2435,17 +2727,22 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
core->i2c_algo.udelay = 16;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
- ctl->scode_table = XC3028_FE_ZARLINK456;
+ ctl->demod = XC3028_FE_ZARLINK456;
break;
case CX88_BOARD_KWORLD_ATSC_120:
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
ctl->demod = XC3028_FE_OREN538;
break;
+ case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
case CX88_BOARD_PROLINK_PV_8000GT:
/*
- * This board uses non-MTS firmware
+ * Those boards uses non-MTS firmware
*/
break;
+ case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+ ctl->demod = XC3028_FE_ZARLINK456;
+ ctl->mts = 1;
+ break;
default:
ctl->demod = XC3028_FE_OREN538;
ctl->mts = 1;
@@ -2489,6 +2786,8 @@ static void cx88_card_setup(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
case CX88_BOARD_HAUPPAUGE_HVR3000:
case CX88_BOARD_HAUPPAUGE_HVR1300:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
if (0 == core->i2c_rc)
hauppauge_eeprom(core, eeprom);
break;
@@ -2570,7 +2869,18 @@ static void cx88_card_setup(struct cx88_core *core)
tea5767_cfg.priv = &ctl;
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
+ break;
}
+ case CX88_BOARD_TEVII_S420:
+ case CX88_BOARD_TEVII_S460:
+ case CX88_BOARD_OMICOM_SS4_PCI:
+ case CX88_BOARD_TBS_8920:
+ case CX88_BOARD_PROF_7300:
+ cx_write(MO_SRST_IO, 0);
+ msleep(100);
+ cx_write(MO_SRST_IO, 1);
+ msleep(100);
+ break;
} /*end switch() */
@@ -2734,10 +3044,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
- info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ if (!core->board.num_frontends)
+ core->board.num_frontends=1;
+
+ info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
pci->subsystem_vendor, pci->subsystem_device, core->board.name,
core->boardnr, card[core->nr] == core->boardnr ?
- "insmod option" : "autodetected");
+ "insmod option" : "autodetected",
+ core->board.num_frontends);
if (tuner[core->nr] != UNSET)
core->board.tuner_type = tuner[core->nr];
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index d656fec5901..60705b08bfe 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -549,7 +549,8 @@ void cx88_wakeup(struct cx88_core *core,
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
}
if (bc != 1)
- printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
+ dprintk(2, "%s: %d buffers handled (should be 1)\n",
+ __func__, bc);
}
void cx88_shutdown(struct cx88_core *core)
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index d96173ff1db..6968ab0181a 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -48,6 +48,11 @@
#include "tuner-simple.h"
#include "tda9887.h"
#include "s5h1411.h"
+#include "stv0299.h"
+#include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "cx24116.h"
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -111,13 +116,23 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
struct cx8802_dev *dev= fe->dvb->priv;
struct cx8802_driver *drv = NULL;
int ret = 0;
+ int fe_id;
+
+ fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+ if (!fe_id) {
+ printk(KERN_ERR "%s() No frontend found\n", __func__);
+ return -EINVAL;
+ }
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
if (drv) {
- if (acquire)
+ if (acquire){
+ dev->frontends.active_fe_id = fe_id;
ret = drv->request_acquire(drv);
- else
+ } else {
ret = drv->request_release(drv);
+ dev->frontends.active_fe_id = 0;
+ }
}
return ret;
@@ -375,37 +390,28 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
return 0;
}
-static int cx88_pci_nano_callback(void *ptr, int command, int arg)
+static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t voltage)
{
- struct cx88_core *core = ptr;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- /* Send the tuner in then out of reset */
- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
-
- switch (core->boardnr) {
- case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
- /* GPIO-4 xc3028 tuner */
-
- cx_set(MO_GP0_IO, 0x00001000);
- cx_clear(MO_GP0_IO, 0x00000010);
- msleep(100);
- cx_set(MO_GP0_IO, 0x00000010);
- msleep(100);
- break;
- }
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
- break;
- case XC2028_RESET_CLK:
- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
- break;
- default:
- dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
- command, arg);
- return -EINVAL;
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ printk("LNB Voltage SEC_VOLTAGE_13\n");
+ cx_write(MO_GP0_IO, 0x00006040);
+ break;
+ case SEC_VOLTAGE_18:
+ printk("LNB Voltage SEC_VOLTAGE_18\n");
+ cx_write(MO_GP0_IO, 0x00006060);
+ break;
+ case SEC_VOLTAGE_OFF:
+ printk("LNB Voltage SEC_VOLTAGE_off\n");
+ break;
}
+ if (core->prev_set_voltage)
+ return core->prev_set_voltage(fe, voltage);
return 0;
}
@@ -456,7 +462,12 @@ static struct s5h1409_config kworld_atsc_120_config = {
static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
.i2c_address = 0x64,
.if_khz = 5380,
- .tuner_callback = cx88_tuner_callback,
+};
+
+static struct zl10353_config cx88_pinnacle_hybrid_pctv = {
+ .demod_address = (0x1e >> 1),
+ .no_tuner = 1,
+ .if2 = 45600,
};
static struct zl10353_config cx88_geniatech_x8000_mt = {
@@ -477,21 +488,25 @@ static struct s5h1411_config dvico_fusionhdtv7_config = {
static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
.i2c_address = 0xc2 >> 1,
.if_khz = 5380,
- .tuner_callback = cx88_tuner_callback,
};
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
struct dvb_frontend *fe;
+ struct videobuf_dvb_frontend *fe0 = NULL;
struct xc2028_ctrl ctl;
struct xc2028_config cfg = {
.i2c_adap = &dev->core->i2c_adap,
.i2c_addr = addr,
.ctrl = &ctl,
- .callback = cx88_tuner_callback,
};
- if (!dev->dvb.frontend) {
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
+
+ if (!fe0->dvb.frontend) {
printk(KERN_ERR "%s/2: dvb frontend not attached. "
"Can't attach xc3028\n",
dev->core->name);
@@ -505,10 +520,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
*/
cx88_setup_xc3028(dev->core, &ctl);
- fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+ fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
if (!fe) {
printk(KERN_ERR "%s/2: xc3028 attach failed\n",
dev->core->name);
+ dvb_frontend_detach(fe0->dvb.frontend);
+ dvb_unregister_frontend(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
return -EINVAL;
}
@@ -518,22 +536,84 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
return 0;
}
+static int cx24116_set_ts_param(struct dvb_frontend *fe,
+ int is_punctured)
+{
+ struct cx8802_dev *dev = fe->dvb->priv;
+ dev->ts_gen_cntrl = 0x2;
+
+ return 0;
+}
+
+static int cx24116_reset_device(struct dvb_frontend *fe)
+{
+ struct cx8802_dev *dev = fe->dvb->priv;
+ struct cx88_core *core = dev->core;
+
+ /* Reset the part */
+ /* Put the cx24116 into reset */
+ cx_write(MO_SRST_IO, 0);
+ msleep(10);
+ /* Take the cx24116 out of reset */
+ cx_write(MO_SRST_IO, 1);
+ msleep(10);
+
+ return 0;
+}
+
+static struct cx24116_config hauppauge_hvr4000_config = {
+ .demod_address = 0x05,
+ .set_ts_params = cx24116_set_ts_param,
+ .reset_device = cx24116_reset_device,
+};
+
+static struct cx24116_config tevii_s460_config = {
+ .demod_address = 0x55,
+ .set_ts_params = cx24116_set_ts_param,
+ .reset_device = cx24116_reset_device,
+};
+
+static struct stv0299_config tevii_tuner_sharp_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = 1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+ .set_ts_params = cx24116_set_ts_param,
+};
+
+static struct stv0288_config tevii_tuner_earda_config = {
+ .demod_address = 0x68,
+ .min_delay_ms = 100,
+ .set_ts_params = cx24116_set_ts_param,
+};
+
static int dvb_register(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
+ struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+ int mfe_shared = 0; /* bus not shared by default */
- /* init struct videobuf_dvb */
- dev->dvb.name = core->name;
- dev->ts_gen_cntrl = 0x0c;
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
+
+ /* multi-frontend gate control is undefined or defaults to fe0 */
+ dev->frontends.gate = 0;
- /* init frontend */
+ /* init frontend(s) */
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, &core->i2c_adap,
DVB_PLL_THOMSON_DTT759X))
goto frontend_detach;
@@ -543,11 +623,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_CONEXANT_DVB_T1:
case CX88_BOARD_KWORLD_DVB_T_CX22702:
case CX88_BOARD_WINFAST_DTV1000:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, &core->i2c_adap,
DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
@@ -557,33 +637,67 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
case CX88_BOARD_HAUPPAUGE_HVR1300:
- case CX88_BOARD_HAUPPAUGE_HVR3000:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&hauppauge_hvr_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3))
goto frontend_detach;
}
break;
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ /* DVB-S init */
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
+ &hauppauge_novas_config,
+ &dev->core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+ dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __func__);
+ }
+ /* DVB-T init */
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ if (fe1) {
+ dev->frontends.gate = 2;
+ mfe_shared = 1;
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+ &dev->core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3)) {
+ dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __func__);
+ }
+ break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
}
@@ -591,31 +705,31 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
/* The tin box says DEE1601, but it seems to be DTT7579
* compatible, with a slightly different MT352 AGC gain. */
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_dual,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_LG_Z201))
goto frontend_detach;
}
@@ -623,11 +737,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_ADSTECH_DVB_T_PCI:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dntv_live_dvbt_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_UNKNOWN_1))
goto frontend_detach;
}
@@ -635,10 +749,10 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
/* MT352 is on a secondary I2C bus made from some GPIO lines */
- dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+ fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
&dev->vp3054->adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3))
goto frontend_detach;
@@ -649,22 +763,22 @@ static int dvb_register(struct cx8802_dev *dev)
#endif
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_hybrid,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_FE6600))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_xc3028,
&core->i2c_adap);
- if (dev->dvb.frontend == NULL)
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ if (fe0->dvb.frontend == NULL)
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_mt352_xc3028,
&core->i2c_adap);
/*
@@ -672,16 +786,16 @@ static int dvb_register(struct cx8802_dev *dev)
* We must not permit gate_ctrl to be performed, or
* the xc3028 cannot communicate on the bus.
*/
- if (dev->dvb.frontend)
- dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (fe0->dvb.frontend)
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (attach_xc3028(0x61, dev) < 0)
return -EINVAL;
break;
case CX88_BOARD_PCHDTV_HD3000:
- dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+ fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_DTT761X))
goto frontend_detach;
@@ -698,11 +812,11 @@ static int dvb_register(struct cx8802_dev *dev)
/* Select RF connector callback */
fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_MICROTUNE_4042FI5))
goto frontend_detach;
@@ -716,11 +830,11 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 9);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_DTT761X))
goto frontend_detach;
@@ -734,15 +848,15 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_5_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_LG_TDVS_H06XF))
goto frontend_detach;
- if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x43))
goto frontend_detach;
}
@@ -755,25 +869,25 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&pchdtv_hd5500,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_LG_TDVS_H06XF))
goto frontend_detach;
- if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x43))
goto frontend_detach;
}
break;
case CX88_BOARD_ATI_HDTVWONDER:
- dev->dvb.frontend = dvb_attach(nxt200x_attach,
+ fe0->dvb.frontend = dvb_attach(nxt200x_attach,
&ati_hdtvwonder,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_TUV1236D))
goto frontend_detach;
@@ -781,135 +895,224 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&hauppauge_novas_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
- &core->i2c_adap, 0x08, 0x00, 0x00))
+ if (fe0->dvb.frontend) {
+ if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
goto frontend_detach;
}
break;
case CX88_BOARD_KWORLD_DVBS_100:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&kworld_dvbs_100_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+ if (fe0->dvb.frontend) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
}
break;
case CX88_BOARD_GENIATECH_DVBS:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&geniatech_dvbs_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
+ if (fe0->dvb.frontend) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
}
break;
case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&pinnacle_pctv_hd_800i_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- /* tuner_config.video_dev must point to
- * i2c_adap.algo_data
- */
- if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
&core->i2c_adap,
- &pinnacle_pctv_hd_800i_tuner_config,
- core->i2c_adap.algo_data))
+ &pinnacle_pctv_hd_800i_tuner_config))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&dvico_hdtv5_pci_nano_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
+ if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
struct xc2028_config cfg = {
.i2c_adap = &core->i2c_adap,
.i2c_addr = 0x61,
- .callback = cx88_pci_nano_callback,
};
static struct xc2028_ctrl ctl = {
- .fname = "xc3028-v27.fw",
+ .fname = XC2028_DEFAULT_FIRMWARE,
.max_len = 64,
.scode_table = XC3028_FE_OREN538,
};
fe = dvb_attach(xc2028_attach,
- dev->dvb.frontend, &cfg);
+ fe0->dvb.frontend, &cfg);
if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
break;
case CX88_BOARD_PINNACLE_HYBRID_PCTV:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
- &cx88_geniatech_x8000_mt,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &cx88_pinnacle_hybrid_pctv,
&core->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0)
- goto frontend_detach;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (attach_xc3028(0x61, dev) < 0)
+ goto frontend_detach;
+ }
break;
case CX88_BOARD_GENIATECH_X8000_MT:
dev->ts_gen_cntrl = 0x00;
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_geniatech_x8000_mt,
&core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
goto frontend_detach;
break;
case CX88_BOARD_KWORLD_ATSC_120:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&kworld_atsc_120_config,
&core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
goto frontend_detach;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
- dev->dvb.frontend = dvb_attach(s5h1411_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&dvico_fusionhdtv7_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- /* tuner_config.video_dev must point to
- * i2c_adap.algo_data
- */
- if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
&core->i2c_adap,
- &dvico_fusionhdtv7_tuner_config,
- core->i2c_adap.algo_data))
+ &dvico_fusionhdtv7_tuner_config))
goto frontend_detach;
}
break;
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ /* DVB-S/S2 Init */
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
+ &hauppauge_hvr4000_config,
+ &dev->core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if(!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+ dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __func__);
+ }
+ /* DVB-T Init */
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ if (fe1) {
+ dev->frontends.gate = 2;
+ mfe_shared = 1;
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+ &dev->core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3)) {
+ dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __func__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __func__);
+ }
+ break;
+ case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
+ &hauppauge_hvr4000_config,
+ &dev->core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x08, ISL6421_DCL, 0x00);
+ }
+ break;
+ case CX88_BOARD_TEVII_S420:
+ fe0->dvb.frontend = dvb_attach(stv0299_attach,
+ &tevii_tuner_sharp_config,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
+ &core->i2c_adap, DVB_PLL_OPERA1))
+ goto frontend_detach;
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+ } else {
+ fe0->dvb.frontend = dvb_attach(stv0288_attach,
+ &tevii_tuner_earda_config,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
+ &core->i2c_adap))
+ goto frontend_detach;
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+ }
+ }
+ break;
+ case CX88_BOARD_TEVII_S460:
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
+ &tevii_s460_config,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ }
+ break;
+ case CX88_BOARD_OMICOM_SS4_PCI:
+ case CX88_BOARD_TBS_8920:
+ case CX88_BOARD_PROF_7300:
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
+ &hauppauge_hvr4000_config,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ }
+ break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
core->name);
break;
}
- if (NULL == dev->dvb.frontend) {
+
+ if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
printk(KERN_ERR
"%s/2: frontend initialization failed\n",
core->name);
return -EINVAL;
}
+ /* define general-purpose callback pointer */
+ fe0->dvb.frontend->callback = cx88_tuner_callback;
/* Ensure all frontends negotiate bus access */
- dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+ fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+ if (fe1)
+ fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
/* Put the analog decoder in standby to keep it quiet */
cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
/* register everything */
- return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
- &dev->pci->dev, adapter_nr);
+ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ &dev->pci->dev, adapter_nr, mfe_shared);
frontend_detach:
- if (dev->dvb.frontend) {
- dvb_frontend_detach(dev->dvb.frontend);
- dev->dvb.frontend = NULL;
+ if (fe0->dvb.frontend) {
+ dvb_frontend_detach(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
}
return -EINVAL;
}
@@ -933,6 +1136,38 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
cx_clear(MO_GP0_IO, 0x00000004);
udelay(1000);
break;
+
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ if(core->dvbdev->frontends.active_fe_id == 1) {
+ /* DVB-S/S2 Enabled */
+
+ /* Toggle reset on cx22702 leaving i2c active */
+ cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080);
+ udelay(1000);
+ cx_clear(MO_GP0_IO, 0x00000080);
+ udelay(50);
+ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */
+ cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */
+ udelay(1000);
+
+ cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */
+ core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+ } else
+ if (core->dvbdev->frontends.active_fe_id == 2) {
+ /* DVB-T Enabled */
+
+ /* Put the cx24116/cx24123 into reset */
+ cx_write(MO_SRST_IO, 0);
+
+ /* cx22702 out of reset and enable it */
+ cx_set(MO_GP0_IO, 0x00000080);
+ cx_clear(MO_GP0_IO, 0x00000004);
+ core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+ udelay(1000);
+ }
+ break;
+
default:
err = -ENODEV;
}
@@ -950,6 +1185,9 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
case CX88_BOARD_HAUPPAUGE_HVR1300:
/* Do Nothing, leave the cx22702 on the bus. */
break;
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ break;
default:
err = -ENODEV;
}
@@ -960,7 +1198,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
- int err;
+ int err, i;
+ struct videobuf_dvb_frontend *fe;
dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -980,18 +1219,28 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
/* dvb stuff */
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
- videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
+ dev->ts_gen_cntrl = 0x0c;
+
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+ if (!fe) {
+ printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i);
+ continue;
+ }
+ videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP,
sizeof(struct cx88_buffer),
dev);
+ /* init struct videobuf_dvb */
+ fe->dvb.name = dev->core->name;
+ }
err = dvb_register(dev);
if (err != 0)
printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
core->name, err);
-
- fail_core:
+fail_core:
return err;
}
@@ -999,9 +1248,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
struct cx8802_dev *dev = drv->core->dvbdev;
- /* dvb */
- if (dev->dvb.frontend)
- videobuf_dvb_unregister(&dev->dvb);
+ videobuf_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index d7406a994f0..01de2300709 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -116,18 +116,25 @@ static int detach_inform(struct i2c_client *client)
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
+ struct videobuf_dvb_frontends *f = &core->dvbdev->frontends;
+ struct videobuf_dvb_frontend *fe = NULL;
if (0 != core->i2c_rc)
return;
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
- if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
- if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
- core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+ if (core->dvbdev && f) {
+ if(f->gate <= 1) /* undefined or fe0 */
+ fe = videobuf_dvb_get_frontend(f, 1);
+ else
+ fe = videobuf_dvb_get_frontend(f, f->gate);
+
+ if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+ fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 1);
i2c_clients_command(&core->i2c_adap, cmd, arg);
- if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
- core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+ if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+ fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 0);
} else
#endif
i2c_clients_command(&core->i2c_adap, cmd, arg);
@@ -201,7 +208,23 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
if (0 == core->i2c_rc) {
+ static u8 tuner_data[] =
+ { 0x0b, 0xdc, 0x86, 0x52 };
+ static struct i2c_msg tuner_msg =
+ { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
+
dprintk(1, "i2c register ok\n");
+ switch( core->boardnr ) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
+ core->name);
+ i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
+ break;
+ default:
+ break;
+ }
if (i2c_scan)
do_i2c_scan(core->name,&core->i2c_client);
} else
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 53526d997a4..8683d104de7 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -224,6 +224,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
ir->sampling = 1;
@@ -259,6 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->polling = 1; /* ms */
break;
case CX88_BOARD_PROLINK_PV_8000GT:
+ case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
ir_codes = ir_codes_pixelview_new;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x3f;
@@ -392,7 +395,7 @@ void cx88_ir_irq(struct cx88_core *core)
{
struct cx88_IR *ir = core->ir;
u32 samples, ircode;
- int i;
+ int i, start, range, toggle, dev, code;
if (NULL == ir)
return;
@@ -461,6 +464,34 @@ void cx88_ir_irq(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+ ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+ ir_dprintk("biphase decoded: %x\n", ircode);
+ /*
+ * RC5 has an extension bit which adds a new range
+ * of available codes, this is detected here. Also
+ * hauppauge remotes (black/silver) always use
+ * specific device ids. If we do not filter the
+ * device ids then messages destined for devices
+ * such as TVs (id=0) will get through to the
+ * device causing mis-fired events.
+ */
+ /* split rc5 data block ... */
+ start = (ircode & 0x2000) >> 13;
+ range = (ircode & 0x1000) >> 12;
+ toggle= (ircode & 0x0800) >> 11;
+ dev = (ircode & 0x07c0) >> 6;
+ code = (ircode & 0x003f) | ((range << 6) ^ 0x0040);
+ if( start != 1)
+ /* no key pressed */
+ break;
+ if ( dev != 0x1e && dev != 0x1f )
+ /* not a hauppauge remote */
+ break;
+ ir_input_keydown(ir->input, &ir->ir, code, ircode);
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
case CX88_BOARD_PINNACLE_PCTV_HD_800i:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index a6b061c2644..6df5cf31418 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -768,7 +768,8 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
{
struct cx8802_dev *dev;
struct cx88_core *core;
- int err;
+ struct videobuf_dvb_frontend *demod;
+ int err,i;
/* general setup */
core = cx88_core_get(pci_dev);
@@ -781,6 +782,11 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
if (!core->board.mpeg)
goto fail_core;
+ if (!core->board.num_frontends) {
+ printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __func__, err);
+ goto fail_core;
+ }
+
err = -ENOMEM;
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
@@ -795,6 +801,20 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&dev->drvlist);
list_add_tail(&dev->devlist,&cx8802_devlist);
+ mutex_init(&dev->frontends.lock);
+ INIT_LIST_HEAD(&dev->frontends.felist);
+
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends);
+
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ demod = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+ if(demod == NULL) {
+ printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ err = -ENOMEM;
+ goto fail_free;
+ }
+ }
+
/* Maintain a reference so cx88-video can query the 8802 device. */
core->dvbdev = dev;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 3a1977f41e2..7dd506b987f 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -767,6 +767,14 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_FM:
set_audio_standard_FM(core, radio_deemphasis);
break;
+ case WW_I2SADC:
+ set_audio_start(core, 0x01);
+ /* Slave/Philips/Autobaud */
+ cx_write(AUD_I2SINPUTCNTL, 0);
+ /* Switch to "I2S ADC mode" */
+ cx_write(AUD_I2SCNTL, 0x1);
+ set_audio_finish(core, EN_I2SIN_ENABLE);
+ break;
case WW_NONE:
default:
printk("%s/0: unknown tv audio mode [%d]\n",
@@ -895,6 +903,9 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
break;
}
break;
+ case WW_I2SADC:
+ /* DO NOTHING */
+ break;
}
if (UNSET != ctl) {
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index ef4d56ea002..3904b73f52e 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -426,24 +426,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
/* if there are audioroutes defined, we have an external
ADC to deal with audio */
-
if (INPUT(input).audioroute) {
-
- /* cx2388's C-ADC is connected to the tuner only.
- When used with S-Video, that ADC is busy dealing with
- chroma, so an external must be used for baseband audio */
-
- if (INPUT(input).type != CX88_VMUX_TELEVISION &&
- INPUT(input).type != CX88_RADIO) {
- /* "ADC mode" */
- cx_write(AUD_I2SCNTL, 0x1);
- cx_set(AUD_CTL, EN_I2SIN_ENABLE);
- } else {
- /* Normal mode */
- cx_write(AUD_I2SCNTL, 0x0);
- cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
- }
-
/* The wm8775 module has the "2" route hardwired into
the initialization. Some boards may use different
routes for different inputs. HVR-1300 surely does */
@@ -454,9 +437,19 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
route.input = INPUT(input).audioroute;
cx88_call_i2c_clients(core,
VIDIOC_INT_S_AUDIO_ROUTING, &route);
-
}
-
+ /* cx2388's C-ADC is connected to the tuner only.
+ When used with S-Video, that ADC is busy dealing with
+ chroma, so an external must be used for baseband audio */
+ if (INPUT(input).type != CX88_VMUX_TELEVISION ) {
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
+ } else {
+ /* Normal mode */
+ cx_write(AUD_I2SCNTL, 0x0);
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ }
}
return 0;
@@ -773,6 +766,7 @@ static int video_open(struct inode *inode, struct file *file)
enum v4l2_buf_type type = 0;
int radio = 0;
+ lock_kernel();
list_for_each_entry(h, &cx8800_devlist, devlist) {
if (h->video_dev->minor == minor) {
dev = h;
@@ -788,8 +782,10 @@ static int video_open(struct inode *inode, struct file *file)
dev = h;
}
}
- if (NULL == dev)
+ if (NULL == dev) {
+ unlock_kernel();
return -ENODEV;
+ }
core = dev->core;
@@ -798,8 +794,10 @@ static int video_open(struct inode *inode, struct file *file)
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -827,11 +825,29 @@ static int video_open(struct inode *inode, struct file *file)
cx_write(MO_GP0_IO, core->board.radio.gpio0);
cx_write(MO_GP1_IO, core->board.radio.gpio1);
cx_write(MO_GP2_IO, core->board.radio.gpio2);
- core->tvaudio = WW_FM;
- cx88_set_tvaudio(core);
- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+ if (core->board.radio.audioroute) {
+ if(core->board.audio_chip &&
+ core->board.audio_chip == V4L2_IDENT_WM8775) {
+ struct v4l2_routing route;
+
+ route.input = core->board.radio.audioroute;
+ cx88_call_i2c_clients(core,
+ VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
+ } else {
+ /* FM Mode */
+ core->tvaudio = WW_FM;
+ cx88_set_tvaudio(core);
+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+ }
cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
}
+ unlock_kernel();
+
+ atomic_inc(&core->users);
return 0;
}
@@ -920,7 +936,8 @@ static int video_release(struct inode *inode, struct file *file)
file->private_data = NULL;
kfree(fh);
- cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+ if(atomic_dec_and_test(&dev->core->users))
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
return 0;
}
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 54fe6509471..76207c2856b 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -221,6 +221,14 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
#define CX88_BOARD_PROLINK_PV_8000GT 66
#define CX88_BOARD_KWORLD_ATSC_120 67
+#define CX88_BOARD_HAUPPAUGE_HVR4000 68
+#define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69
+#define CX88_BOARD_TEVII_S460 70
+#define CX88_BOARD_OMICOM_SS4_PCI 71
+#define CX88_BOARD_TBS_8920 72
+#define CX88_BOARD_TEVII_S420 73
+#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
+#define CX88_BOARD_PROF_7300 75
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -239,7 +247,7 @@ struct cx88_input {
enum cx88_itype type;
u32 gpio0, gpio1, gpio2, gpio3;
unsigned int vmux:2;
- unsigned int audioroute:2;
+ unsigned int audioroute:4;
};
struct cx88_board {
@@ -253,6 +261,7 @@ struct cx88_board {
struct cx88_input radio;
enum cx88_board_type mpeg;
unsigned int audio_chip;
+ int num_frontends;
};
struct cx88_subid {
@@ -342,11 +351,13 @@ struct cx88_core {
struct mutex lock;
/* various v4l controls */
u32 freq;
+ atomic_t users;
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev;
enum cx88_board_type active_type_id;
int active_ref;
+ int active_fe_id;
};
struct cx8800_dev;
@@ -481,7 +492,7 @@ struct cx8802_dev {
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
/* for dvb only */
- struct videobuf_dvb dvb;
+ struct videobuf_dvb_frontends frontends;
#endif
#if defined(CONFIG_VIDEO_CX88_VP3054) || \
@@ -601,7 +612,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core,
/* ----------------------------------------------------------- */
/* cx88-cards.c */
-extern int cx88_tuner_callback(void *dev, int command, int arg);
+extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
extern int cx88_get_resources(const struct cx88_core *core,
struct pci_dev *pci);
extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
@@ -619,6 +630,7 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
#define WW_EIAJ 7
#define WW_I2SPT 8
#define WW_FM 9
+#define WW_I2SADC 10
void cx88_set_tvaudio(struct cx88_core *core);
void cx88_newstation(struct cx88_core *core);
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 48f4b92a8f8..298810d5262 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -192,7 +192,7 @@ static void dabusb_iso_complete (struct urb *purb)
err("dabusb_iso_complete: invalid len %d", len);
}
else
- warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
+ dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status);
if (dst != purb->actual_length)
err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
}
@@ -289,7 +289,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
}
if( ret == -EPIPE ) {
- warn("CLEAR_FEATURE request to remove STALL condition.");
+ dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n");
if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
err("request failed");
}
@@ -403,6 +403,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev);
if (ret) {
err("Failed to load \"dabusb/bitstream.bin\": %d\n", ret);
+ kfree(b);
return ret;
}
@@ -865,7 +866,8 @@ static int __init dabusb_init (void)
dbg("dabusb_init: driver registered");
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
out:
return retval;
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
deleted file mode 100644
index 88d6df71d05..00000000000
--- a/drivers/media/video/dpc7146.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- dpc7146.c - v4l2 driver for the dpc7146 demonstration board
-
- Copyright (C) 2000-2003 Michael Hunold <michael@mihu.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define DEBUG_VARIABLE debug
-
-#include <media/saa7146_vv.h>
-#include <linux/video_decoder.h> /* for saa7111a */
-
-#define I2C_SAA7111A 0x24
-
-/* All unused bytes are reserverd. */
-#define SAA711X_CHIP_VERSION 0x00
-#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02
-#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03
-#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04
-#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05
-#define SAA711X_HORIZONTAL_SYNC_START 0x06
-#define SAA711X_HORIZONTAL_SYNC_STOP 0x07
-#define SAA711X_SYNC_CONTROL 0x08
-#define SAA711X_LUMINANCE_CONTROL 0x09
-#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A
-#define SAA711X_LUMINANCE_CONTRAST 0x0B
-#define SAA711X_CHROMA_SATURATION 0x0C
-#define SAA711X_CHROMA_HUE_CONTROL 0x0D
-#define SAA711X_CHROMA_CONTROL 0x0E
-#define SAA711X_FORMAT_DELAY_CONTROL 0x10
-#define SAA711X_OUTPUT_CONTROL_1 0x11
-#define SAA711X_OUTPUT_CONTROL_2 0x12
-#define SAA711X_OUTPUT_CONTROL_3 0x13
-#define SAA711X_V_GATE_1_START 0x15
-#define SAA711X_V_GATE_1_STOP 0x16
-#define SAA711X_V_GATE_1_MSB 0x17
-#define SAA711X_TEXT_SLICER_STATUS 0x1A
-#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B
-#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C
-#define SAA711X_STATUS_BYTE 0x1F
-
-#define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "debug verbosity");
-
-static int dpc_num;
-
-#define DPC_INPUTS 2
-static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
- { 0, "Port A", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
- { 1, "Port B", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-};
-
-#define DPC_AUDIOS 0
-
-static struct saa7146_extension_ioctls ioctls[] = {
- { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
- { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
- { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
- { VIDIOC_S_STD, SAA7146_AFTER },
- { 0, 0 }
-};
-
-struct dpc
-{
- struct video_device *video_dev;
- struct video_device *vbi_dev;
-
- struct i2c_adapter i2c_adapter;
- struct i2c_client *saa7111a;
-
- int cur_input; /* current input */
-};
-
-static int dpc_check_clients(struct device *dev, void *data)
-{
- struct dpc* dpc = data;
- struct i2c_client *client = i2c_verify_client(dev);
-
- if( !client )
- return 0;
-
- if( I2C_SAA7111A == client->addr )
- dpc->saa7111a = client;
-
- return 0;
-}
-
-/* fixme: add vbi stuff here */
-static int dpc_probe(struct saa7146_dev* dev)
-{
- struct dpc* dpc = NULL;
-
- dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
- if( NULL == dpc ) {
- printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
- return -ENOMEM;
- }
-
- /* FIXME: enable i2c-port pins, video-port-pins
- video port pins should be enabled here ?! */
- saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
-
- dpc->i2c_adapter = (struct i2c_adapter) {
- .class = I2C_CLASS_TV_ANALOG,
- .name = "dpc7146",
- };
- saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
- if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
- DEB_S(("cannot register i2c-device. skipping.\n"));
- kfree(dpc);
- return -EFAULT;
- }
-
- /* loop through all i2c-devices on the bus and look who is there */
- device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients);
-
- /* check if all devices are present */
- if (!dpc->saa7111a) {
- DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
- i2c_del_adapter(&dpc->i2c_adapter);
- kfree(dpc);
- return -ENODEV;
- }
-
- /* all devices are present, probe was successful */
- DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n"));
-
- /* we store the pointer in our private data field */
- dev->ext_priv = dpc;
-
- return 0;
-}
-
-/* bring hardware to a sane state. this has to be done, just in case someone
- wants to capture from this device before it has been properly initialized.
- the capture engine would badly fail, because no valid signal arrives on the
- saa7146, thus leading to timeouts and stuff. */
-static int dpc_init_done(struct saa7146_dev* dev)
-{
- struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
- DEB_D(("dpc_v4l2.o: dpc_init_done called.\n"));
-
- /* initialize the helper ics to useful values */
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11);
-
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03);
-
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1);
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30);
-
- i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81);
-
- return 0;
-}
-
-static struct saa7146_ext_vv vv_data;
-
-/* this function only gets called when the probing was successful */
-static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
-{
- struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
- DEB_D(("dpc_v4l2.o: dpc_attach called.\n"));
-
- /* checking for i2c-devices can be omitted here, because we
- already did this in "dpc_vl42_probe" */
-
- saa7146_vv_init(dev,&vv_data);
- if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
- ERR(("cannot register capture v4l2 device. skipping.\n"));
- return -1;
- }
-
- /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
- if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
- if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) {
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
- }
- }
-
- i2c_use_client(dpc->saa7111a);
-
- printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num);
- dpc_num++;
-
- /* the rest */
- dpc->cur_input = 0;
- dpc_init_done(dev);
-
- return 0;
-}
-
-static int dpc_detach(struct saa7146_dev* dev)
-{
- struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
- DEB_EE(("dev:%p\n",dev));
-
- i2c_release_client(dpc->saa7111a);
-
- saa7146_unregister_device(&dpc->video_dev,dev);
- if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
- saa7146_unregister_device(&dpc->vbi_dev,dev);
- }
- saa7146_vv_release(dev);
-
- dpc_num--;
-
- i2c_del_adapter(&dpc->i2c_adapter);
- kfree(dpc);
- return 0;
-}
-
-#ifdef axa
-int dpc_vbi_bypass(struct saa7146_dev* dev)
-{
- struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
- int i = 1;
-
- /* switch bypass in saa7111a */
- if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) {
- printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n");
- return -1;
- }
-
- return 0;
-}
-#endif
-
-static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
- struct saa7146_dev *dev = fh->dev;
- struct dpc* dpc = (struct dpc*)dev->ext_priv;
-/*
- struct saa7146_vv *vv = dev->vv_data;
-*/
- switch(cmd)
- {
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *i = arg;
- DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
-
- if( i->index < 0 || i->index >= DPC_INPUTS) {
- return -EINVAL;
- }
-
- memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input));
-
- DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index));
- return 0;
- }
- case VIDIOC_G_INPUT:
- {
- int *input = (int *)arg;
- *input = dpc->cur_input;
-
- DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input));
- return 0;
- }
- case VIDIOC_S_INPUT:
- {
- int input = *(int *)arg;
-
- if (input < 0 || input >= DPC_INPUTS) {
- return -EINVAL;
- }
-
- dpc->cur_input = input;
-
- /* fixme: switch input here, switch audio, too! */
-// saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
- printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n");
-
- return 0;
- }
- default:
-/*
- DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n"));
-*/
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
-{
- return 0;
-}
-
-static struct saa7146_standard standard[] = {
- {
- .name = "PAL", .id = V4L2_STD_PAL,
- .v_offset = 0x17, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 680,
- .v_max_out = 576, .h_max_out = 768,
- }, {
- .name = "NTSC", .id = V4L2_STD_NTSC,
- .v_offset = 0x16, .v_field = 240,
- .h_offset = 0x06, .h_pixels = 708,
- .v_max_out = 480, .h_max_out = 640,
- }, {
- .name = "SECAM", .id = V4L2_STD_SECAM,
- .v_offset = 0x14, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 720,
- .v_max_out = 576, .h_max_out = 768,
- }
-};
-
-static struct saa7146_extension extension;
-
-static struct saa7146_pci_extension_data dpc = {
- .ext_priv = "Multimedia eXtension Board",
- .ext = &extension,
-};
-
-static struct pci_device_id pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x0000,
- .subdevice = 0x0000,
- .driver_data = (unsigned long)&dpc,
- }, {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_ext_vv vv_data = {
- .inputs = DPC_INPUTS,
- .capabilities = V4L2_CAP_VBI_CAPTURE,
- .stds = &standard[0],
- .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
- .std_callback = &std_callback,
- .ioctls = &ioctls[0],
- .ioctl = dpc_ioctl,
-};
-
-static struct saa7146_extension extension = {
- .name = "dpc7146 demonstration board",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .pci_tbl = &pci_tbl[0],
- .module = THIS_MODULE,
-
- .probe = dpc_probe,
- .attach = dpc_attach,
- .detach = dpc_detach,
-
- .irq_mask = 0,
- .irq_func = NULL,
-};
-
-static int __init dpc_init_module(void)
-{
- if( 0 != saa7146_register_extension(&extension)) {
- DEB_S(("failed to register extension.\n"));
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit dpc_cleanup_module(void)
-{
- saa7146_unregister_extension(&extension);
-}
-
-module_init(dpc_init_module);
-module_exit(dpc_cleanup_module);
-
-MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'");
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 3c006103c1e..ac3292d7646 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -117,10 +117,10 @@ static void em28xx_audio_isocirq(struct urb *urb)
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt =
- runtime->buffer_size - oldptr - 1;
+ runtime->buffer_size - oldptr;
memcpy(runtime->dma_area + oldptr * stride, cp,
cnt * stride);
- memcpy(runtime->dma_area, cp + cnt,
+ memcpy(runtime->dma_area, cp + cnt * stride,
length * stride - cnt * stride);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp,
@@ -161,8 +161,14 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
- if (!urb)
+ if (!urb) {
+ em28xx_errdev("usb_alloc_urb failed!\n");
+ for (j = 0; j < i; j++) {
+ usb_free_urb(dev->adev->urb[j]);
+ kfree(dev->adev->transfer_buffer[j]);
+ }
return -ENOMEM;
+ }
urb->dev = dev->udev;
urb->context = dev;
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 452da70e719..d65d0572403 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {
.amux = 0,
} },
},
- [EM2800_BOARD_KWORLD_USB2800] = {
- .name = "Kworld USB2800",
- .valid = EM28XX_BOARD_NOT_VALIDATED,
- .is_em2800 = 1,
- .vchannels = 3,
- .tuner_type = TUNER_PHILIPS_FCV1236D,
- .tda9887_conf = TDA9887_PRESENT,
- .decoder = EM28XX_SAA7113,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = SAA7115_COMPOSITE2,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = SAA7115_COMPOSITE0,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3,
- .amux = 1,
- } },
- },
[EM2820_BOARD_KWORLD_PVRTV2800RF] = {
.name = "Kworld PVR TV 2800 RF",
.is_em2800 = 0,
@@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
- .amux = 1,
+ .amux = 3,
}, {
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
@@ -952,22 +930,23 @@ struct em28xx_board em28xx_boards[] = {
},
[EM2880_BOARD_KWORLD_DVB_310U] = {
.name = "KWorld DVB-T 310U",
- .valid = EM28XX_BOARD_NOT_VALIDATED,
.vchannels = 3,
.tuner_type = TUNER_XC2028,
+ .has_dvb = 1,
+ .mts_firmware = 1,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0,
- .amux = 0,
+ .amux = EM28XX_AMUX_VIDEO,
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
- .amux = 1,
- }, {
+ .amux = EM28XX_AMUX_AC97_LINE_IN,
+ }, { /* S-video has not been tested yet */
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
- .amux = 1,
+ .amux = EM28XX_AMUX_AC97_LINE_IN,
} },
},
[EM2881_BOARD_DNT_DA2_HYBRID] = {
@@ -1122,7 +1101,7 @@ struct usb_device_id em28xx_id_table [] = {
{ USB_DEVICE(0xeb1a, 0x2820),
.driver_info = EM2820_BOARD_UNKNOWN },
{ USB_DEVICE(0xeb1a, 0x2821),
- .driver_info = EM2820_BOARD_UNKNOWN },
+ .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 },
{ USB_DEVICE(0xeb1a, 0x2860),
.driver_info = EM2820_BOARD_UNKNOWN },
{ USB_DEVICE(0xeb1a, 0x2861),
@@ -1282,6 +1261,7 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
static struct em28xx_hash_table em28xx_eeprom_hash [] = {
/* P/N: SA 60002070465 Tuner: TVF7533-MF */
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+ {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
};
/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1291,7 +1271,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
{0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
};
-int em28xx_tuner_callback(void *ptr, int command, int arg)
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
{
int rc = 0;
struct em28xx *dev = ptr;
@@ -1552,9 +1532,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
/* djh - Not sure which demod we need here */
ctl->demod = XC3028_FE_DEFAULT;
break;
+ case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+ ctl->demod = XC3028_FE_DEFAULT;
+ ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+ break;
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
- case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
/* FIXME: Better to specify the needed IF */
ctl->demod = XC3028_FE_DEFAULT;
break;
@@ -1764,6 +1747,20 @@ void em28xx_card_setup(struct em28xx *dev)
break;
case EM2820_BOARD_UNKNOWN:
case EM2800_BOARD_UNKNOWN:
+ /*
+ * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
+ *
+ * This occurs because they share identical USB vendor and
+ * product IDs.
+ *
+ * What we do here is look up the EEPROM hash of the K-WORLD
+ * and if it is found then we decide that we do not have
+ * a DIGIVOX and reset the device to the K-WORLD instead.
+ *
+ * This solution is only valid if they do not share eeprom
+ * hash identities which has not been determined as yet.
+ */
+ case EM2880_BOARD_MSI_DIGIVOX_AD:
if (!em28xx_hint_board(dev))
em28xx_set_model(dev);
break;
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 4b992bc0083..c99e2383b7e 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -249,7 +249,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
memset(&cfg, 0, sizeof(cfg));
cfg.i2c_adap = &dev->i2c_adap;
cfg.i2c_addr = addr;
- cfg.callback = em28xx_tuner_callback;
if (!dev->dvb->frontend) {
printk(KERN_ERR "%s/2: dvb frontend not attached. "
@@ -274,7 +273,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
/* ------------------------------------------------------------------ */
-int register_dvb(struct em28xx_dvb *dvb,
+static int register_dvb(struct em28xx_dvb *dvb,
struct module *module,
struct em28xx *dev,
struct device *device)
@@ -422,6 +421,8 @@ static int dvb_init(struct em28xx *dev)
}
break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+ case EM2880_BOARD_TERRATEC_HYBRID_XS:
+ case EM2880_BOARD_KWORLD_DVB_310U:
dvb->frontend = dvb_attach(zl10353_attach,
&em28xx_zl10353_with_xc3028,
&dev->i2c_adap);
@@ -443,15 +444,6 @@ static int dvb_init(struct em28xx *dev)
}
break;
#endif
- case EM2880_BOARD_TERRATEC_HYBRID_XS:
- dvb->frontend = dvb_attach(zl10353_attach,
- &em28xx_zl10353_with_xc3028,
- &dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
- result = -EINVAL;
- goto out_free;
- }
- break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n",
@@ -465,6 +457,8 @@ static int dvb_init(struct em28xx *dev)
result = -EINVAL;
goto out_free;
}
+ /* define general-purpose callback pointer */
+ dvb->frontend->callback = em28xx_tuner_callback;
/* register everything */
result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 97853384c94..3bab56b997f 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -143,10 +143,11 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
}
for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
write_timeout -= 5) {
- unsigned msg = dev->em28xx_read_reg(dev, 0x5);
- if (msg == 0x94)
+ unsigned reg = dev->em28xx_read_reg(dev, 0x5);
+
+ if (reg == 0x94)
return -ENODEV;
- else if (msg == 0x84)
+ else if (reg == 0x84)
return 0;
msleep(5);
}
@@ -335,8 +336,11 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
/* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0);
- if (err < 0)
- return -1;
+ if (err < 0) {
+ em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n",
+ __func__, err);
+ return err;
+ }
buf = 0;
@@ -344,7 +348,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
if (err != 1) {
printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
dev->name, err);
- return -1;
+ return err;
}
while (size > 0) {
if (size > 16)
@@ -357,7 +361,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
printk(KERN_WARNING
"%s: i2c eeprom read error (err=%d)\n",
dev->name, err);
- return -1;
+ return err;
}
size -= block;
p += block;
@@ -585,18 +589,31 @@ void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg)
*/
int em28xx_i2c_register(struct em28xx *dev)
{
+ int retval;
+
BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
dev->i2c_adap = em28xx_adap_template;
dev->i2c_adap.dev.parent = &dev->udev->dev;
strcpy(dev->i2c_adap.name, dev->name);
dev->i2c_adap.algo_data = dev;
- i2c_add_adapter(&dev->i2c_adap);
+
+ retval = i2c_add_adapter(&dev->i2c_adap);
+ if (retval < 0) {
+ em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
+ __func__, retval);
+ return retval;
+ }
dev->i2c_client = em28xx_client_template;
dev->i2c_client.adapter = &dev->i2c_adap;
- em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+ retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
+ __func__, retval);
+ return retval;
+ }
if (i2c_scan)
em28xx_do_i2c_scan(dev);
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 49ab0629702..c53649e5315 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -513,10 +513,17 @@ static struct videobuf_queue_ops em28xx_video_qops = {
*/
static int em28xx_config(struct em28xx *dev)
{
+ int retval;
/* Sets I2C speed to 100 KHz */
- if (!dev->is_em2800)
- em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1);
+ if (!dev->is_em2800) {
+ retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n",
+ __func__, retval);
+ return retval;
+ }
+ }
/* enable vbi capturing */
@@ -1512,6 +1519,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
struct em28xx_fh *fh;
enum v4l2_buf_type fh_type = 0;
+ lock_kernel();
list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor) {
dev = h;
@@ -1527,8 +1535,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
dev = h;
}
}
- if (NULL == dev)
+ if (NULL == dev) {
+ unlock_kernel();
return -ENODEV;
+ }
em28xx_videodbg("open minor=%d type=%s users=%d\n",
minor, v4l2_type_names[fh_type], dev->users);
@@ -1537,6 +1547,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
if (!fh) {
em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+ unlock_kernel();
return -ENOMEM;
}
mutex_lock(&dev->lock);
@@ -1573,6 +1584,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
sizeof(struct em28xx_buffer), fh);
mutex_unlock(&dev->lock);
+ unlock_kernel();
return errCode;
}
@@ -1588,8 +1600,7 @@ static void em28xx_release_resources(struct em28xx *dev)
/*FIXME: I2C IR should be disconnected */
em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
- dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
+ dev->vdev->num, dev->vbi_dev->num);
list_del(&dev->devlist);
if (dev->sbutton_input_dev)
em28xx_deregister_snapshot_button(dev);
@@ -1948,13 +1959,23 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
}
/* register i2c bus */
- em28xx_i2c_register(dev);
+ errCode = em28xx_i2c_register(dev);
+ if (errCode < 0) {
+ em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
+ __func__, errCode);
+ return errCode;
+ }
/* Do board specific init and eeprom reading */
em28xx_card_setup(dev);
/* Configure audio */
- em28xx_audio_analog_set(dev);
+ errCode = em28xx_audio_analog_set(dev);
+ if (errCode < 0) {
+ em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n",
+ __func__, errCode);
+ return errCode;
+ }
/* configure the device */
em28xx_config_i2c(dev);
@@ -1974,6 +1995,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->ctl_input = 2;
errCode = em28xx_config(dev);
+ if (errCode < 0) {
+ em28xx_errdev("%s: em28xx_config - errCode [%d]!\n",
+ __func__, errCode);
+ return errCode;
+ }
list_add_tail(&dev->devlist, &em28xx_devlist);
@@ -2026,17 +2052,27 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (dev->has_msp34xx) {
/* Send a reset to other chips via gpio */
- em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
+ errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
+ if (errCode < 0) {
+ em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n",
+ __func__, errCode);
+ return errCode;
+ }
msleep(3);
- em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
+
+ errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
+ if (errCode < 0) {
+ em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n",
+ __func__, errCode);
+ return errCode;
+ }
msleep(3);
}
video_mux(dev, 0);
em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
- dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
+ dev->vdev->num, dev->vbi_dev->num);
mutex_lock(&em28xx_extension_devlist_lock);
if (!list_empty(&em28xx_extension_devlist)) {
@@ -2236,7 +2272,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
em28xx_warn
("device /dev/video%d is open! Deregistration and memory "
"deallocation are deferred on close.\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
+ dev->vdev->num);
dev->state |= DEV_MISCONFIGURED;
em28xx_uninit_isoc(dev);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 9a331074868..82781178e0a 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -411,8 +411,8 @@ struct em28xx {
/* frame properties */
int width; /* current frame width */
int height; /* current frame height */
- int hscale; /* horizontal scale factor (see datasheet) */
- int vscale; /* vertical scale factor (see datasheet) */
+ unsigned hscale; /* horizontal scale factor (see datasheet) */
+ unsigned vscale; /* vertical scale factor (see datasheet) */
int interlaced; /* 1=interlace fileds, 0=just top fileds */
unsigned int video_bytesread; /* Number of bytes read */
@@ -528,7 +528,7 @@ extern struct em28xx_board em28xx_boards[];
extern struct usb_device_id em28xx_id_table[];
extern const unsigned int em28xx_bcount;
void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
-int em28xx_tuner_callback(void *ptr, int command, int arg);
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
/* Provided by em28xx-input.c */
/* TODO: Check if the standard get_key handlers on ir-common can be used */
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 2d170d101c2..7a85c41b0ee 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -1214,7 +1214,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
if (!down_read_trylock(&et61x251_dev_lock))
return -ERESTARTSYS;
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
if (wait_for_completion_interruptible(&cam->probe)) {
up_read(&et61x251_dev_lock);
@@ -1297,7 +1297,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
down_write(&et61x251_dev_lock);
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
et61x251_stop_transfer(cam);
et61x251_release_buffers(cam);
@@ -1318,7 +1318,7 @@ static ssize_t
et61x251_read(struct file* filp, char __user * buf,
size_t count, loff_t* f_pos)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device *cam = video_drvdata(filp);
struct et61x251_frame_t* f, * i;
unsigned long lock_flags;
long timeout;
@@ -1426,7 +1426,7 @@ exit:
static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device *cam = video_drvdata(filp);
struct et61x251_frame_t* f;
unsigned long lock_flags;
unsigned int mask = 0;
@@ -1502,7 +1502,7 @@ static struct vm_operations_struct et61x251_vm_ops = {
static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device *cam = video_drvdata(filp);
unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start;
void *pos;
@@ -2395,7 +2395,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
unsigned int cmd, void __user * arg)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device *cam = video_drvdata(filp);
switch (cmd) {
@@ -2490,7 +2490,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
static int et61x251_ioctl(struct inode* inode, struct file* filp,
unsigned int cmd, unsigned long arg)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device *cam = video_drvdata(filp);
int err = 0;
if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -2588,6 +2588,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->fops = &et61x251_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
+ cam->v4ldev->parent = &udev->dev;
video_set_drvdata(cam->v4ldev, cam);
init_completion(&cam->probe);
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 42b90742b40..4d0817471c9 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -1,13 +1,212 @@
-config USB_GSPCA
- tristate "USB GSPCA driver"
+menuconfig USB_GSPCA
+ tristate "GSPCA based webcams"
depends on VIDEO_V4L2
+ default m
---help---
- Say Y here if you want support for various USB webcams.
+ Say Y here if you want to enable selecting webcams based
+ on the GSPCA framework.
- See <file:Documentation/video4linux/gspca.txt> for more info.
+ See <file:Documentation/video4linux/gspca.txt> for more info.
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
- To compile this driver as modules, choose M here: the
- modules will be called gspca_xxxx.
+ To compile this driver as modules, choose M here: the
+ modules will be called gspca_main.
+
+
+if USB_GSPCA && VIDEO_V4L2
+
+source "drivers/media/video/gspca/m5602/Kconfig"
+
+config USB_GSPCA_CONEX
+ tristate "Conexant Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the Conexant chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_conex.
+
+config USB_GSPCA_ETOMS
+ tristate "Etoms USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the Etoms chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_etoms.
+
+config USB_GSPCA_FINEPIX
+ tristate "Fujifilm FinePix USB V4L2 driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the FinePix chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_finepix.
+
+config USB_GSPCA_MARS
+ tristate "Mars USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the Mars chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_mars.
+
+config USB_GSPCA_OV519
+ tristate "OV519 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the OV519 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_ov519.
+
+config USB_GSPCA_PAC207
+ tristate "Pixart PAC207 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the PAC207 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_pac207.
+
+config USB_GSPCA_PAC7311
+ tristate "Pixart PAC7311 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the PAC7311 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_pac7311.
+
+config USB_GSPCA_SONIXB
+ tristate "SN9C102 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SONIXB chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sonixb.
+
+config USB_GSPCA_SONIXJ
+ tristate "SONIX JPEG USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SONIXJ chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sonixj
+
+config USB_GSPCA_SPCA500
+ tristate "SPCA500 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA500 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca500.
+
+config USB_GSPCA_SPCA501
+ tristate "SPCA501 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA501 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca501.
+
+config USB_GSPCA_SPCA505
+ tristate "SPCA505 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA505 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca505.
+
+config USB_GSPCA_SPCA506
+ tristate "SPCA506 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA506 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca506.
+
+config USB_GSPCA_SPCA508
+ tristate "SPCA508 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA508 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca508.
+
+config USB_GSPCA_SPCA561
+ tristate "SPCA561 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SPCA561 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca561.
+
+config USB_GSPCA_STK014
+ tristate "Syntek DV4000 (STK014) USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the STK014 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_stk014.
+
+config USB_GSPCA_SUNPLUS
+ tristate "SUNPLUS USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the Sunplus
+ SPCA504(abc) SPCA533 SPCA536 chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca5xx.
+
+config USB_GSPCA_T613
+ tristate "T613 (JPEG Compliance) USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the T613 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_t613.
+
+config USB_GSPCA_TV8532
+ tristate "TV8532 USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the TV8531 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_tv8532.
+
+config USB_GSPCA_VC032X
+ tristate "VC032X USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the VC032X chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_vc032x.
+
+config USB_GSPCA_ZC3XX
+ tristate "VC3xx USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the ZC3XX chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_zc3xx.
+
+endif
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index e68a8965297..22734f5a6c3 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -1,29 +1,48 @@
-obj-$(CONFIG_USB_GSPCA) += gspca_main.o \
- gspca_conex.o gspca_etoms.o gspca_mars.o \
- gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
- gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
- gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
- gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
- gspca_vc032x.o gspca_zc3xx.o
+obj-$(CONFIG_USB_GSPCA) += gspca_main.o
+obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o
+obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o
+obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o
+obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
+obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
+obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
+obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
+obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
+obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
+obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o
+obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
+obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
+obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
+obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
+obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
+obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
+obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
+obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
+obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o
+
+gspca_main-objs := gspca.o
+gspca_conex-objs := conex.o
+gspca_etoms-objs := etoms.o
+gspca_finepix-objs := finepix.o
+gspca_mars-objs := mars.o
+gspca_ov519-objs := ov519.o
+gspca_pac207-objs := pac207.o
+gspca_pac7311-objs := pac7311.o
+gspca_sonixb-objs := sonixb.o
+gspca_sonixj-objs := sonixj.o
+gspca_spca500-objs := spca500.o
+gspca_spca501-objs := spca501.o
+gspca_spca505-objs := spca505.o
+gspca_spca506-objs := spca506.o
+gspca_spca508-objs := spca508.o
+gspca_spca561-objs := spca561.o
+gspca_stk014-objs := stk014.o
+gspca_sunplus-objs := sunplus.o
+gspca_t613-objs := t613.o
+gspca_tv8532-objs := tv8532.o
+gspca_vc032x-objs := vc032x.o
+gspca_zc3xx-objs := zc3xx.o
+
+obj-$(CONFIG_USB_M5602) += m5602/
-gspca_main-objs := gspca.o
-gspca_conex-objs := conex.o
-gspca_etoms-objs := etoms.o
-gspca_mars-objs := mars.o
-gspca_ov519-objs := ov519.o
-gspca_pac207-objs := pac207.o
-gspca_pac7311-objs := pac7311.o
-gspca_sonixb-objs := sonixb.o
-gspca_sonixj-objs := sonixj.o
-gspca_spca500-objs := spca500.o
-gspca_spca501-objs := spca501.o
-gspca_spca505-objs := spca505.o
-gspca_spca506-objs := spca506.o
-gspca_spca508-objs := spca508.o
-gspca_spca561-objs := spca561.o
-gspca_stk014-objs := stk014.o
-gspca_sunplus-objs := sunplus.o
-gspca_t613-objs := t613.o
-gspca_tv8532-objs := tv8532.o
-gspca_vc032x-objs := vc032x.o
-gspca_zc3xx-objs := zc3xx.o
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index cd3a3f5829b..a9d51ba7c57 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -124,7 +124,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;
#ifdef GSPCA_DEBUG
- if (len > sizeof gspca_dev->usb_buf) {
+ if (len > USB_BUF_SZ) {
err("reg_r: buffer overflow");
return;
}
@@ -164,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;
#ifdef GSPCA_DEBUG
- if (len > sizeof gspca_dev->usb_buf) {
+ if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
@@ -731,13 +731,13 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
reg_w_val(gspca_dev, 0x0000, 0x00);
/* wait for completion */
retry = 50;
- while (retry--) {
+ do {
reg_r(gspca_dev, 0x0002, 1);
/* 0x07 until 0x00 */
if (gspca_dev->usb_buf[0] == 0x00)
break;
reg_w_val(gspca_dev, 0x0053, 0x00);
- }
+ } while (--retry);
if (retry == 0)
PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
/* send the qtable now */
@@ -826,8 +826,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
cx11646_init1(gspca_dev);
cx11646_initsize(gspca_dev);
@@ -837,16 +837,13 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
cx11646_initsize(gspca_dev);
cx11646_fw(gspca_dev);
cx_sensor(gspca_dev);
cx11646_jpeg(gspca_dev);
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
+ return 0;
}
static void sd_stop0(struct gspca_dev *gspca_dev)
@@ -871,10 +868,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev, 0x00fc, 0xe0);
}
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -998,11 +991,9 @@ static struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
- .stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -1026,6 +1017,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index 1dbe92d01e6..3be30b420a2 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -81,6 +81,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcontrast,
.get = sd_getcontrast,
},
+#define COLOR_IDX 2
{
{
.id = V4L2_CID_SATURATION,
@@ -234,7 +235,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;
#ifdef GSPCA_DEBUG
- if (len > sizeof gspca_dev->usb_buf) {
+ if (len > USB_BUF_SZ) {
err("reg_r: buffer overflow");
return;
}
@@ -272,7 +273,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;
#ifdef GSPCA_DEBUG
- if (len > sizeof gspca_dev->usb_buf) {
+ if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
@@ -665,6 +666,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
} else {
cam->cam_mode = vga_mode;
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ gspca_dev->ctrl_dis = (1 << COLOR_IDX);
}
sd->brightness = BRIGHTNESS_DEF;
sd->contrast = CONTRAST_DEF;
@@ -674,8 +676,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -689,7 +691,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -702,6 +704,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
et_video(gspca_dev, 1); /* video on */
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -709,14 +712,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
et_video(gspca_dev, 0); /* video off */
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -893,21 +888,19 @@ static struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.dq_callback = do_autogain,
};
/* -- module initialisation -- */
static __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_ET61X251
{USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
-#endif
+#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
{USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
+#endif
{}
};
@@ -926,6 +919,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
new file mode 100644
index 00000000000..65d3cbfe6b2
--- /dev/null
+++ b/drivers/media/video/gspca/finepix.c
@@ -0,0 +1,466 @@
+/*
+ * Fujifilm Finepix subdriver
+ *
+ * Copyright (C) 2008 Frank Zago
+ *
+ * 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
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define MODULE_NAME "finepix"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Frank Zago <frank@zago.net>");
+MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeout, in ms */
+#define FPIX_TIMEOUT (HZ / 10)
+
+/* Maximum transfer size to use. The windows driver reads by chunks of
+ * 0x2000 bytes, so do the same. Note: reading more seems to work
+ * too. */
+#define FPIX_MAX_TRANSFER 0x2000
+
+/* Structure to hold all of our device specific stuff */
+struct usb_fpix {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+
+ /*
+ * USB stuff
+ */
+ struct usb_ctrlrequest ctrlreq;
+ struct urb *control_urb;
+ struct timer_list bulk_timer;
+
+ enum {
+ FPIX_NOP, /* inactive, else streaming */
+ FPIX_RESET, /* must reset */
+ FPIX_REQ_FRAME, /* requesting a frame */
+ FPIX_READ_FRAME, /* reading frame */
+ } state;
+
+ /*
+ * Driver stuff
+ */
+ struct delayed_work wqe;
+ struct completion can_close;
+ int streaming;
+};
+
+/* Delay after which claim the next frame. If the delay is too small,
+ * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
+ * will fail every 4 or 5 frames, but 30ms is perfect. */
+#define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000)
+
+#define dev_new_state(new_state) { \
+ PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \
+ dev->state, new_state, __func__, __LINE__); \
+ dev->state = new_state; \
+}
+
+/* These cameras only support 320x200. */
+static struct v4l2_pix_format fpix_mode[1] = {
+ { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0}
+};
+
+/* Reads part of a frame */
+static void read_frame_part(struct usb_fpix *dev)
+{
+ int ret;
+
+ PDEBUG(D_STREAM, "read_frame_part");
+
+ /* Reads part of a frame */
+ ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC);
+ if (ret) {
+ dev_new_state(FPIX_RESET);
+ schedule_delayed_work(&dev->wqe, 1);
+ PDEBUG(D_STREAM, "usb_submit_urb failed with %d",
+ ret);
+ } else {
+ /* Sometimes we never get a callback, so use a timer.
+ * Is this masking a bug somewhere else? */
+ dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150);
+ add_timer(&dev->bulk_timer);
+ }
+}
+
+/* Callback for URBs. */
+static void urb_callback(struct urb *urb)
+{
+ struct gspca_dev *gspca_dev = urb->context;
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+ PDEBUG(D_PACK,
+ "enter urb_callback - status=%d, length=%d",
+ urb->status, urb->actual_length);
+
+ if (dev->state == FPIX_READ_FRAME)
+ del_timer(&dev->bulk_timer);
+
+ if (urb->status != 0) {
+ /* We kill a stuck urb every 50 frames on average, so don't
+ * display a log message for that. */
+ if (urb->status != -ECONNRESET)
+ PDEBUG(D_STREAM, "bad URB status %d", urb->status);
+ dev_new_state(FPIX_RESET);
+ schedule_delayed_work(&dev->wqe, 1);
+ }
+
+ switch (dev->state) {
+ case FPIX_REQ_FRAME:
+ dev_new_state(FPIX_READ_FRAME);
+ read_frame_part(dev);
+ break;
+
+ case FPIX_READ_FRAME: {
+ unsigned char *data = urb->transfer_buffer;
+ struct gspca_frame *frame;
+
+ frame = gspca_get_i_frame(&dev->gspca_dev);
+ if (frame == NULL)
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ if (urb->actual_length < FPIX_MAX_TRANSFER ||
+ (data[urb->actual_length-2] == 0xff &&
+ data[urb->actual_length-1] == 0xd9)) {
+
+ /* If the result is less than what was asked
+ * for, then it's the end of the
+ * frame. Sometime the jpeg is not complete,
+ * but there's nothing we can do. We also end
+ * here if the the jpeg ends right at the end
+ * of the frame. */
+ if (frame)
+ gspca_frame_add(gspca_dev, LAST_PACKET,
+ frame,
+ data, urb->actual_length);
+ dev_new_state(FPIX_REQ_FRAME);
+ schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY);
+ } else {
+
+ /* got a partial image */
+ if (frame)
+ gspca_frame_add(gspca_dev,
+ gspca_dev->last_packet_type
+ == LAST_PACKET
+ ? FIRST_PACKET : INTER_PACKET,
+ frame,
+ data, urb->actual_length);
+ read_frame_part(dev);
+ }
+ break;
+ }
+
+ case FPIX_NOP:
+ case FPIX_RESET:
+ PDEBUG(D_STREAM, "invalid state %d", dev->state);
+ break;
+ }
+}
+
+/* Request a new frame */
+static void request_frame(struct usb_fpix *dev)
+{
+ int ret;
+ struct gspca_dev *gspca_dev = &dev->gspca_dev;
+
+ /* Setup command packet */
+ memset(gspca_dev->usb_buf, 0, 12);
+ gspca_dev->usb_buf[0] = 0xd3;
+ gspca_dev->usb_buf[7] = 0x01;
+
+ /* Request a frame */
+ dev->ctrlreq.bRequestType =
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ dev->ctrlreq.bRequest = USB_REQ_GET_STATUS;
+ dev->ctrlreq.wValue = 0;
+ dev->ctrlreq.wIndex = 0;
+ dev->ctrlreq.wLength = cpu_to_le16(12);
+
+ usb_fill_control_urb(dev->control_urb,
+ gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ (unsigned char *) &dev->ctrlreq,
+ gspca_dev->usb_buf,
+ 12, urb_callback, gspca_dev);
+
+ ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC);
+ if (ret) {
+ dev_new_state(FPIX_RESET);
+ schedule_delayed_work(&dev->wqe, 1);
+ PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* State machine. */
+static void fpix_sm(struct work_struct *work)
+{
+ struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work);
+
+ PDEBUG(D_STREAM, "fpix_sm state %d", dev->state);
+
+ /* verify that the device wasn't unplugged */
+ if (!dev->gspca_dev.present) {
+ PDEBUG(D_STREAM, "device is gone");
+ dev_new_state(FPIX_NOP);
+ complete(&dev->can_close);
+ return;
+ }
+
+ if (!dev->streaming) {
+ PDEBUG(D_STREAM, "stopping state machine");
+ dev_new_state(FPIX_NOP);
+ complete(&dev->can_close);
+ return;
+ }
+
+ switch (dev->state) {
+ case FPIX_RESET:
+ dev_new_state(FPIX_REQ_FRAME);
+ schedule_delayed_work(&dev->wqe, HZ / 10);
+ break;
+
+ case FPIX_REQ_FRAME:
+ /* get an image */
+ request_frame(dev);
+ break;
+
+ case FPIX_NOP:
+ case FPIX_READ_FRAME:
+ PDEBUG(D_STREAM, "invalid state %d", dev->state);
+ break;
+ }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct cam *cam = &gspca_dev->cam;
+
+ cam->cam_mode = fpix_mode;
+ cam->nmodes = 1;
+ cam->epaddr = 0x01; /* todo: correct for all cams? */
+ cam->bulk_size = FPIX_MAX_TRANSFER;
+
+/* gspca_dev->nbalt = 1; * use bulk transfer */
+ return 0;
+}
+
+/* Stop streaming and free the ressources allocated by sd_start. */
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+ dev->streaming = 0;
+
+ /* Stop the state machine */
+ if (dev->state != FPIX_NOP)
+ wait_for_completion(&dev->can_close);
+
+ usb_free_urb(dev->control_urb);
+ dev->control_urb = NULL;
+}
+
+/* Kill an URB that hasn't completed. */
+static void timeout_kill(unsigned long data)
+{
+ struct urb *urb = (struct urb *) data;
+
+ usb_unlink_urb(urb);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+ INIT_DELAYED_WORK(&dev->wqe, fpix_sm);
+
+ init_timer(&dev->bulk_timer);
+ dev->bulk_timer.function = timeout_kill;
+
+ return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+ int ret;
+ int size_ret;
+
+ /* Reset bulk in endpoint */
+ usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
+
+ /* Init the device */
+ memset(gspca_dev->usb_buf, 0, 12);
+ gspca_dev->usb_buf[0] = 0xc6;
+ gspca_dev->usb_buf[8] = 0x20;
+
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_GET_STATUS,
+ USB_DIR_OUT | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+ 12, FPIX_TIMEOUT);
+
+ if (ret != 12) {
+ PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
+ ret = -EIO;
+ goto error;
+ }
+
+ /* Read the result of the command. Ignore the result, for it
+ * varies with the device. */
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev,
+ gspca_dev->cam.epaddr),
+ gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret,
+ FPIX_TIMEOUT);
+ if (ret != 0) {
+ PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret);
+ ret = -EIO;
+ goto error;
+ }
+
+ /* Request a frame, but don't read it */
+ memset(gspca_dev->usb_buf, 0, 12);
+ gspca_dev->usb_buf[0] = 0xd3;
+ gspca_dev->usb_buf[7] = 0x01;
+
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_GET_STATUS,
+ USB_DIR_OUT | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+ 12, FPIX_TIMEOUT);
+ if (ret != 12) {
+ PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
+ ret = -EIO;
+ goto error;
+ }
+
+ /* Again, reset bulk in endpoint */
+ usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
+
+ /* Allocate a control URB */
+ dev->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->control_urb) {
+ PDEBUG(D_STREAM, "No free urbs available");
+ ret = -EIO;
+ goto error;
+ }
+
+ /* Various initializations. */
+ init_completion(&dev->can_close);
+ dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0];
+ dev->gspca_dev.urb[0]->complete = urb_callback;
+ dev->streaming = 1;
+
+ /* Schedule a frame request. */
+ dev_new_state(FPIX_REQ_FRAME);
+ schedule_delayed_work(&dev->wqe, 1);
+
+ return 0;
+
+error:
+ /* Free the ressources */
+ sd_stopN(gspca_dev);
+ return ret;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x04cb, 0x0104)},
+ {USB_DEVICE(0x04cb, 0x0109)},
+ {USB_DEVICE(0x04cb, 0x010b)},
+ {USB_DEVICE(0x04cb, 0x010f)},
+ {USB_DEVICE(0x04cb, 0x0111)},
+ {USB_DEVICE(0x04cb, 0x0113)},
+ {USB_DEVICE(0x04cb, 0x0115)},
+ {USB_DEVICE(0x04cb, 0x0117)},
+ {USB_DEVICE(0x04cb, 0x0119)},
+ {USB_DEVICE(0x04cb, 0x011b)},
+ {USB_DEVICE(0x04cb, 0x011d)},
+ {USB_DEVICE(0x04cb, 0x0121)},
+ {USB_DEVICE(0x04cb, 0x0123)},
+ {USB_DEVICE(0x04cb, 0x0125)},
+ {USB_DEVICE(0x04cb, 0x0127)},
+ {USB_DEVICE(0x04cb, 0x0129)},
+ {USB_DEVICE(0x04cb, 0x012b)},
+ {USB_DEVICE(0x04cb, 0x012d)},
+ {USB_DEVICE(0x04cb, 0x012f)},
+ {USB_DEVICE(0x04cb, 0x0131)},
+ {USB_DEVICE(0x04cb, 0x013b)},
+ {USB_DEVICE(0x04cb, 0x013d)},
+ {USB_DEVICE(0x04cb, 0x013f)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ .config = sd_config,
+ .init = sd_init,
+ .start = sd_start,
+ .stopN = sd_stopN,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id,
+ &sd_desc,
+ sizeof(struct usb_fpix),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ if (usb_register(&sd_driver) < 0)
+ return -1;
+ PDEBUG(D_PROBE, "registered");
+ return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+ PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 15d302b28b7..e48fbfc8ad0 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -21,6 +21,7 @@
#define MODULE_NAME "gspca"
#include <linux/init.h>
+#include <linux/version.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
@@ -29,6 +30,7 @@
#include <linux/string.h>
#include <linux/pagemap.h>
#include <linux/io.h>
+#include <linux/kref.h>
#include <asm/page.h>
#include <linux/uaccess.h>
#include <linux/jiffies.h>
@@ -43,7 +45,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 2, 0)
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0)
static int video_nr = -1;
@@ -102,6 +104,22 @@ static struct vm_operations_struct gspca_vm_ops = {
.close = gspca_vm_close,
};
+/* get the current input frame buffer */
+struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
+{
+ struct gspca_frame *frame;
+ int i;
+
+ i = gspca_dev->fr_i;
+ i = gspca_dev->fr_queue[i];
+ frame = &gspca_dev->frame[i];
+ if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
+ != V4L2_BUF_FLAG_QUEUED)
+ return NULL;
+ return frame;
+}
+EXPORT_SYMBOL(gspca_get_i_frame);
+
/*
* fill a video frame from an URB and resubmit
*/
@@ -110,22 +128,22 @@ static void fill_frame(struct gspca_dev *gspca_dev,
{
struct gspca_frame *frame;
__u8 *data; /* address of data in the iso message */
- int i, j, len, st;
+ int i, len, st;
cam_pkt_op pkt_scan;
if (urb->status != 0) {
- PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+#ifdef CONFIG_PM
+ if (!gspca_dev->frozen)
+#endif
+ PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
return; /* disconnection ? */
}
pkt_scan = gspca_dev->sd_desc->pkt_scan;
for (i = 0; i < urb->number_of_packets; i++) {
/* check the availability of the frame buffer */
- j = gspca_dev->fr_i;
- j = gspca_dev->fr_queue[j];
- frame = &gspca_dev->frame[j];
- if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
- != V4L2_BUF_FLAG_QUEUED) {
+ frame = gspca_get_i_frame(gspca_dev);
+ if (!frame) {
gspca_dev->last_packet_type = DISCARD_PACKET;
break;
}
@@ -175,6 +193,39 @@ static void isoc_irq(struct urb *urb
}
/*
+ * bulk message interrupt from the USB device
+ */
+static void bulk_irq(struct urb *urb
+)
+{
+ struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+ struct gspca_frame *frame;
+
+ PDEBUG(D_PACK, "bulk irq");
+ if (!gspca_dev->streaming)
+ return;
+ if (urb->status != 0 && urb->status != -ECONNRESET) {
+#ifdef CONFIG_PM
+ if (!gspca_dev->frozen)
+#endif
+ PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+ return; /* disconnection ? */
+ }
+
+ /* check the availability of the frame buffer */
+ frame = gspca_get_i_frame(gspca_dev);
+ if (!frame) {
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ } else {
+ PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
+ gspca_dev->sd_desc->pkt_scan(gspca_dev,
+ frame,
+ urb->transfer_buffer,
+ urb->actual_length);
+ }
+}
+
+/*
* add data to the current frame
*
* This function is called by the subdrivers at interrupt level.
@@ -187,7 +238,7 @@ static void isoc_irq(struct urb *urb
* On LAST_PACKET, a new frame is returned.
*/
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
- int packet_type,
+ enum gspca_packet_type packet_type,
struct gspca_frame *frame,
const __u8 *data,
int len)
@@ -229,7 +280,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
}
gspca_dev->last_packet_type = packet_type;
- /* if last packet, wake the application and advance in the queue */
+ /* if last packet, wake up the application and advance in the queue */
if (packet_type == LAST_PACKET) {
frame->v4l2_buf.bytesused = frame->data_end - frame->data;
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
@@ -267,7 +318,6 @@ static void *rvmalloc(unsigned long size)
void *mem;
unsigned long adr;
-/* size = PAGE_ALIGN(size); (already done) */
mem = vmalloc_32(size);
if (mem != NULL) {
adr = (unsigned long) mem;
@@ -354,7 +404,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
unsigned int i;
PDEBUG(D_STREAM, "kill transfer");
- for (i = 0; i < MAX_NURBS; ++i) {
+ for (i = 0; i < MAX_NURBS; i++) {
urb = gspca_dev->urb[i];
if (urb == NULL)
break;
@@ -371,10 +421,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
}
/*
- * search an input isochronous endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting
*/
-static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
- __u8 epaddr)
+static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
+ __u8 epaddr,
+ __u8 xfer)
{
struct usb_host_endpoint *ep;
int i, attr;
@@ -385,7 +436,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
if (ep->desc.bEndpointAddress == epaddr) {
attr = ep->desc.bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK;
- if (attr == USB_ENDPOINT_XFER_ISOC)
+ if (attr == xfer)
return ep;
break;
}
@@ -394,14 +445,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
}
/*
- * search an input isochronous endpoint
+ * look for an input (isoc or bulk) endpoint
*
* The endpoint is defined by the subdriver.
* Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
* This routine may be called many times when the bandwidth is too small
* (the bandwidth is checked on urb submit).
*/
-static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
+static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
{
struct usb_interface *intf;
struct usb_host_endpoint *ep;
@@ -410,28 +461,41 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
ep = NULL;
i = gspca_dev->alt; /* previous alt setting */
+
+ /* try isoc */
while (--i > 0) { /* alt 0 is unusable */
- ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
+ ep = alt_xfer(&intf->altsetting[i],
+ gspca_dev->cam.epaddr,
+ USB_ENDPOINT_XFER_ISOC);
if (ep)
break;
}
+
+ /* if no isoc, try bulk */
if (ep == NULL) {
- err("no ISOC endpoint found");
- return NULL;
+ ep = alt_xfer(&intf->altsetting[0],
+ gspca_dev->cam.epaddr,
+ USB_ENDPOINT_XFER_BULK);
+ if (ep == NULL) {
+ err("no transfer endpoint found");
+ return NULL;
+ }
}
- PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
+ PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
i, ep->desc.bEndpointAddress);
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
- if (ret < 0) {
- err("set interface err %d", ret);
- return NULL;
+ if (i > 0) {
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
+ if (ret < 0) {
+ err("set interface err %d", ret);
+ return NULL;
+ }
}
gspca_dev->alt = i; /* memorize the current alt setting */
return ep;
}
/*
- * create the isochronous URBs
+ * create the URBs for image transfer
*/
static int create_urbs(struct gspca_dev *gspca_dev,
struct usb_host_endpoint *ep)
@@ -442,20 +506,33 @@ static int create_urbs(struct gspca_dev *gspca_dev,
/* calculate the packet size and the number of packets */
psize = le16_to_cpu(ep->desc.wMaxPacketSize);
- /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
- psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
- npkt = ISO_MAX_SIZE / psize;
- if (npkt > ISO_MAX_PKT)
- npkt = ISO_MAX_PKT;
- bsize = psize * npkt;
- PDEBUG(D_STREAM,
- "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
- nurbs = DEF_NURBS;
+ if (gspca_dev->alt != 0) { /* isoc */
+
+ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
+ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+ npkt = ISO_MAX_SIZE / psize;
+ if (npkt > ISO_MAX_PKT)
+ npkt = ISO_MAX_PKT;
+ bsize = psize * npkt;
+ PDEBUG(D_STREAM,
+ "isoc %d pkts size %d = bsize:%d",
+ npkt, psize, bsize);
+ nurbs = DEF_NURBS;
+ } else { /* bulk */
+ npkt = 0;
+ bsize = gspca_dev->cam. bulk_size;
+ if (bsize == 0)
+ bsize = psize;
+ PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
+ nurbs = 1;
+ }
+
gspca_dev->nurbs = nurbs;
for (n = 0; n < nurbs; n++) {
urb = usb_alloc_urb(npkt, GFP_KERNEL);
if (!urb) {
err("usb_alloc_urb failed");
+ destroy_urbs(gspca_dev);
return -ENOMEM;
}
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
@@ -465,24 +542,31 @@ static int create_urbs(struct gspca_dev *gspca_dev,
if (urb->transfer_buffer == NULL) {
usb_free_urb(urb);
- destroy_urbs(gspca_dev);
err("usb_buffer_urb failed");
+ destroy_urbs(gspca_dev);
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
urb->dev = gspca_dev->dev;
urb->context = gspca_dev;
- urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
- ep->desc.bEndpointAddress);
- urb->transfer_flags = URB_ISO_ASAP
- | URB_NO_TRANSFER_DMA_MAP;
- urb->interval = ep->desc.bInterval;
- urb->complete = isoc_irq;
- urb->number_of_packets = npkt;
urb->transfer_buffer_length = bsize;
- for (i = 0; i < npkt; i++) {
- urb->iso_frame_desc[i].length = psize;
- urb->iso_frame_desc[i].offset = psize * i;
+ if (npkt != 0) { /* ISOC */
+ urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
+ ep->desc.bEndpointAddress);
+ urb->transfer_flags = URB_ISO_ASAP
+ | URB_NO_TRANSFER_DMA_MAP;
+ urb->interval = ep->desc.bInterval;
+ urb->complete = isoc_irq;
+ urb->number_of_packets = npkt;
+ for (i = 0; i < npkt; i++) {
+ urb->iso_frame_desc[i].length = psize;
+ urb->iso_frame_desc[i].offset = psize * i;
+ }
+ } else { /* bulk */
+ urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
+ ep->desc.bEndpointAddress),
+ urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+ urb->complete = bulk_irq;
}
}
return 0;
@@ -504,7 +588,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
gspca_dev->alt = gspca_dev->nbalt;
for (;;) {
PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
- ep = get_isoc_ep(gspca_dev);
+ ep = get_ep(gspca_dev);
if (ep == NULL) {
ret = -EIO;
goto out;
@@ -514,10 +598,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
goto out;
/* start the cam */
- gspca_dev->sd_desc->start(gspca_dev);
+ ret = gspca_dev->sd_desc->start(gspca_dev);
+ if (ret < 0) {
+ destroy_urbs(gspca_dev);
+ goto out;
+ }
gspca_dev->streaming = 1;
atomic_set(&gspca_dev->nevent, 0);
+ /* bulk transfers are started by the subdriver */
+ if (gspca_dev->alt == 0)
+ break;
+
/* submit the URBs */
for (n = 0; n < gspca_dev->nurbs; n++) {
ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
@@ -549,16 +641,18 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
return ret;
}
-/* Note both the queue and the usb lock should be hold when calling this */
+/* Note: both the queue and the usb locks should be held when calling this */
static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
atomic_set(&gspca_dev->nevent, 0);
if (gspca_dev->present) {
- gspca_dev->sd_desc->stopN(gspca_dev);
+ if (gspca_dev->sd_desc->stopN)
+ gspca_dev->sd_desc->stopN(gspca_dev);
destroy_urbs(gspca_dev);
gspca_set_alt0(gspca_dev);
- gspca_dev->sd_desc->stop0(gspca_dev);
+ if (gspca_dev->sd_desc->stop0)
+ gspca_dev->sd_desc->stop0(gspca_dev);
PDEBUG(D_STREAM, "stream off OK");
}
}
@@ -753,6 +847,16 @@ out:
return ret;
}
+static void gspca_delete(struct kref *kref)
+{
+ struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref);
+
+ PDEBUG(D_STREAM, "device deleted");
+
+ kfree(gspca_dev->usb_buf);
+ kfree(gspca_dev);
+}
+
static int dev_open(struct inode *inode, struct file *file)
{
struct gspca_dev *gspca_dev;
@@ -767,31 +871,26 @@ static int dev_open(struct inode *inode, struct file *file)
goto out;
}
- /* if not done yet, initialize the sensor */
- if (gspca_dev->users == 0) {
- if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
- ret = -ERESTARTSYS;
- goto out;
- }
- ret = gspca_dev->sd_desc->open(gspca_dev);
- mutex_unlock(&gspca_dev->usb_lock);
- if (ret != 0) {
- PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
- goto out;
- }
- } else if (gspca_dev->users > 4) { /* (arbitrary value) */
+ if (gspca_dev->users > 4) { /* (arbitrary value) */
ret = -EBUSY;
goto out;
}
gspca_dev->users++;
+
+ /* one more user */
+ kref_get(&gspca_dev->kref);
+
file->private_data = gspca_dev;
#ifdef GSPCA_DEBUG
/* activate the v4l2 debug */
if (gspca_debug & D_V4L2)
- gspca_dev->vdev.debug |= 3;
+ gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+ | V4L2_DEBUG_IOCTL_ARG;
else
- gspca_dev->vdev.debug &= ~3;
+ gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+ | V4L2_DEBUG_IOCTL_ARG);
#endif
+ ret = 0;
out:
mutex_unlock(&gspca_dev->queue_lock);
if (ret != 0)
@@ -812,18 +911,22 @@ static int dev_close(struct inode *inode, struct file *file)
/* if the file did the capture, free the streaming resources */
if (gspca_dev->capt_file == file) {
- mutex_lock(&gspca_dev->usb_lock);
- if (gspca_dev->streaming)
+ if (gspca_dev->streaming) {
+ mutex_lock(&gspca_dev->usb_lock);
gspca_stream_off(gspca_dev);
- gspca_dev->sd_desc->close(gspca_dev);
- mutex_unlock(&gspca_dev->usb_lock);
+ mutex_unlock(&gspca_dev->usb_lock);
+ }
frame_free(gspca_dev);
gspca_dev->capt_file = NULL;
gspca_dev->memory = GSPCA_MEMORY_NO;
}
file->private_data = NULL;
mutex_unlock(&gspca_dev->queue_lock);
+
PDEBUG(D_STREAM, "close done");
+
+ kref_put(&gspca_dev->kref, gspca_delete);
+
return 0;
}
@@ -834,7 +937,6 @@ static int vidioc_querycap(struct file *file, void *priv,
memset(cap, 0, sizeof *cap);
strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
-/* strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */
if (gspca_dev->dev->product != NULL) {
strncpy(cap->card, gspca_dev->dev->product,
sizeof cap->card);
@@ -853,42 +955,44 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *q_ctrl)
{
struct gspca_dev *gspca_dev = priv;
- int i;
+ int i, ix;
u32 id;
+ ix = -1;
id = q_ctrl->id;
if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
id &= V4L2_CTRL_ID_MASK;
id++;
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
- if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
- memcpy(q_ctrl,
- &gspca_dev->sd_desc->ctrls[i].qctrl,
- sizeof *q_ctrl);
- return 0;
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
+ continue;
+ if (ix < 0) {
+ ix = i;
+ continue;
}
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id
+ > gspca_dev->sd_desc->ctrls[ix].qctrl.id)
+ continue;
+ ix = i;
}
- return -EINVAL;
}
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
- memcpy(q_ctrl,
- &gspca_dev->sd_desc->ctrls[i].qctrl,
- sizeof *q_ctrl);
- return 0;
+ ix = i;
+ break;
}
}
- if (id >= V4L2_CID_BASE
- && id <= V4L2_CID_LASTP1) {
+ if (ix < 0)
+ return -EINVAL;
+ memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl,
+ sizeof *q_ctrl);
+ if (gspca_dev->ctrl_dis & (1 << ix))
q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
- return 0;
- }
- return -EINVAL;
+ return 0;
}
static int vidioc_s_ctrl(struct file *file, void *priv,
@@ -903,6 +1007,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
i++, ctrls++) {
if (ctrl->id != ctrls->qctrl.id)
continue;
+ if (gspca_dev->ctrl_dis & (1 << i))
+ return -EINVAL;
if (ctrl->value < ctrls->qctrl.minimum
|| ctrl->value > ctrls->qctrl.maximum)
return -ERANGE;
@@ -929,6 +1035,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
i++, ctrls++) {
if (ctrl->id != ctrls->qctrl.id)
continue;
+ if (gspca_dev->ctrl_dis & (1 << i))
+ return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
ret = ctrls->get(gspca_dev, &ctrl->value);
@@ -1403,7 +1511,7 @@ static int vidioc_dqbuf(struct file *file, void *priv,
i = ret; /* frame index */
frame = &gspca_dev->frame[i];
if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
- if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr,
+ if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
frame->data,
frame->v4l2_buf.bytesused)) {
PDEBUG(D_ERR|D_STREAM,
@@ -1462,7 +1570,6 @@ static int vidioc_qbuf(struct file *file, void *priv,
}
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
-/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
@@ -1609,7 +1716,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
}
/* if the process slept for more than 1 second,
- * get anewer frame */
+ * get a newer frame */
frame = &gspca_dev->frame[v4l2_buf.index];
if (--n < 0)
break; /* avoid infinite loop */
@@ -1727,21 +1834,30 @@ int gspca_dev_probe(struct usb_interface *intf,
if (dev_size < sizeof *gspca_dev)
dev_size = sizeof *gspca_dev;
gspca_dev = kzalloc(dev_size, GFP_KERNEL);
- if (gspca_dev == NULL) {
+ if (!gspca_dev) {
err("couldn't kzalloc gspca struct");
- return -EIO;
+ return -ENOMEM;
+ }
+ kref_init(&gspca_dev->kref);
+ gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
+ if (!gspca_dev->usb_buf) {
+ err("out of memory");
+ ret = -ENOMEM;
+ goto out;
}
gspca_dev->dev = dev;
gspca_dev->iface = interface->bInterfaceNumber;
gspca_dev->nbalt = intf->num_altsetting;
gspca_dev->sd_desc = sd_desc;
-/* gspca_dev->users = 0; (done by kzalloc) */
gspca_dev->nbufread = 2;
- /* configure the subdriver */
+ /* configure the subdriver and initialize the USB device */
ret = gspca_dev->sd_desc->config(gspca_dev, id);
if (ret < 0)
goto out;
+ ret = gspca_dev->sd_desc->init(gspca_dev);
+ if (ret < 0)
+ goto out;
ret = gspca_set_alt0(gspca_dev);
if (ret < 0)
goto out;
@@ -1771,7 +1887,7 @@ int gspca_dev_probe(struct usb_interface *intf,
PDEBUG(D_PROBE, "probe ok");
return 0;
out:
- kfree(gspca_dev);
+ kref_put(&gspca_dev->kref, gspca_delete);
return ret;
}
EXPORT_SYMBOL(gspca_dev_probe);
@@ -1786,28 +1902,50 @@ void gspca_disconnect(struct usb_interface *intf)
{
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
- if (!gspca_dev)
- return;
- gspca_dev->present = 0;
- mutex_lock(&gspca_dev->queue_lock);
- mutex_lock(&gspca_dev->usb_lock);
- gspca_dev->streaming = 0;
- destroy_urbs(gspca_dev);
- mutex_unlock(&gspca_dev->usb_lock);
- mutex_unlock(&gspca_dev->queue_lock);
- while (gspca_dev->users != 0) { /* wait until fully closed */
- atomic_inc(&gspca_dev->nevent);
- wake_up_interruptible(&gspca_dev->wq); /* wake processes */
- schedule();
- }
+ usb_set_intfdata(intf, NULL);
+
/* We don't want people trying to open up the device */
video_unregister_device(&gspca_dev->vdev);
-/* Free the memory */
- kfree(gspca_dev);
+
+ gspca_dev->present = 0;
+ gspca_dev->streaming = 0;
+
+ kref_put(&gspca_dev->kref, gspca_delete);
+
PDEBUG(D_PROBE, "disconnect complete");
}
EXPORT_SYMBOL(gspca_disconnect);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+ if (!gspca_dev->streaming)
+ return 0;
+ gspca_dev->frozen = 1; /* avoid urb error messages */
+ if (gspca_dev->sd_desc->stopN)
+ gspca_dev->sd_desc->stopN(gspca_dev);
+ destroy_urbs(gspca_dev);
+ gspca_set_alt0(gspca_dev);
+ if (gspca_dev->sd_desc->stop0)
+ gspca_dev->sd_desc->stop0(gspca_dev);
+ return 0;
+}
+EXPORT_SYMBOL(gspca_suspend);
+
+int gspca_resume(struct usb_interface *intf)
+{
+ struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+ gspca_dev->frozen = 0;
+ gspca_dev->sd_desc->init(gspca_dev);
+ if (gspca_dev->streaming)
+ return gspca_init_transfer(gspca_dev);
+ return 0;
+}
+EXPORT_SYMBOL(gspca_resume);
+#endif
/* -- cam driver utility functions -- */
/* auto gain and exposure algorithm based on the knee algorithm described here:
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 67e448940ea..1d9dc90b479 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -2,7 +2,6 @@
#define GSPCAV2_H
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
@@ -49,14 +48,14 @@ extern int gspca_debug;
} while (0)
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
-/* ISOC transfers */
-#define MAX_NURBS 16 /* max number of URBs */
+/* image transfers */
+#define MAX_NURBS 4 /* max number of URBs */
#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
/* device information - set at probe time */
struct cam {
- char *dev_name;
+ int bulk_size; /* buffer size when image transfer by bulk */
struct v4l2_pix_format *cam_mode; /* size nmodes */
char nmodes;
__u8 epaddr;
@@ -91,15 +90,14 @@ struct sd_desc {
/* controls */
const struct ctrl *ctrls;
int nctrls;
-/* operations */
+/* mandatory operations */
cam_cf_op config; /* called on probe */
- cam_op open; /* called on open */
- cam_v_op start; /* called on stream on */
- cam_v_op stopN; /* called on stream off - main alt */
- cam_v_op stop0; /* called on stream off - alt 0 */
- cam_v_op close; /* called on close */
+ cam_op init; /* called on probe and resume */
+ cam_op start; /* called on stream on */
cam_pkt_op pkt_scan;
/* optional operations */
+ cam_v_op stopN; /* called on stream off - main alt */
+ cam_v_op stop0; /* called on stream off - alt 0 */
cam_v_op dq_callback; /* called when a frame has been dequeued */
cam_jpg_op get_jcomp;
cam_jpg_op set_jcomp;
@@ -107,10 +105,12 @@ struct sd_desc {
};
/* packet types when moving from iso buf to frame buf */
-#define DISCARD_PACKET 0
-#define FIRST_PACKET 1
-#define INTER_PACKET 2
-#define LAST_PACKET 3
+enum gspca_packet_type {
+ DISCARD_PACKET,
+ FIRST_PACKET,
+ INTER_PACKET,
+ LAST_PACKET
+};
struct gspca_frame {
__u8 *data; /* frame buffer */
@@ -123,12 +123,15 @@ struct gspca_dev {
struct video_device vdev; /* !! must be the first item */
struct file_operations fops;
struct usb_device *dev;
+ struct kref kref;
struct file *capt_file; /* file doing video capture */
struct cam cam; /* device information */
const struct sd_desc *sd_desc; /* subdriver description */
+ unsigned ctrl_dis; /* disabled controls (bit map) */
- __u8 usb_buf[8]; /* buffer for USB exchanges */
+#define USB_BUF_SZ 64
+ __u8 *usb_buf; /* buffer for USB exchanges */
struct urb *urb[MAX_NURBS];
__u8 *frbuf; /* buffer for nframes */
@@ -155,6 +158,9 @@ struct gspca_dev {
struct mutex queue_lock; /* ISOC queue protection */
__u32 sequence; /* frame sequence number */
char streaming;
+#ifdef CONFIG_PM
+ char frozen; /* suspend - resume */
+#endif
char users; /* number of opens */
char present; /* device connected */
char nbufread; /* number of buffers for read() */
@@ -170,10 +176,15 @@ int gspca_dev_probe(struct usb_interface *intf,
struct module *module);
void gspca_disconnect(struct usb_interface *intf);
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
- int packet_type,
+ enum gspca_packet_type packet_type,
struct gspca_frame *frame,
const __u8 *data,
int len);
+struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message);
+int gspca_resume(struct usb_interface *intf);
+#endif
int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
#endif /* GSPCAV2_H */
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig
new file mode 100644
index 00000000000..5a69016ed75
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/Kconfig
@@ -0,0 +1,11 @@
+config USB_M5602
+ tristate "ALi USB m5602 Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the
+ ALi m5602 connected to various image sensors.
+
+ See <file:Documentation/video4linux/m5602.txt> for more info.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_m5602.
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
new file mode 100644
index 00000000000..226ab4fc9d6
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_USB_M5602) += gspca_m5602.o
+
+gspca_m5602-objs := m5602_core.o \
+ m5602_ov9650.o \
+ m5602_mt9m111.o \
+ m5602_po1030.o \
+ m5602_s5k83a.o \
+ m5602_s5k4aa.o
+
+EXTRA_CFLAGS += -Idrivers/media/video/gspca
+
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
new file mode 100644
index 00000000000..1a37ae4bc82
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_bridge.h
@@ -0,0 +1,143 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_BRIDGE_H_
+#define M5602_BRIDGE_H_
+
+#include "gspca.h"
+
+#define MODULE_NAME "ALi m5602"
+
+/*****************************************************************************/
+
+#define M5602_XB_SENSOR_TYPE 0x00
+#define M5602_XB_SENSOR_CTRL 0x01
+#define M5602_XB_LINE_OF_FRAME_H 0x02
+#define M5602_XB_LINE_OF_FRAME_L 0x03
+#define M5602_XB_PIX_OF_LINE_H 0x04
+#define M5602_XB_PIX_OF_LINE_L 0x05
+#define M5602_XB_VSYNC_PARA 0x06
+#define M5602_XB_HSYNC_PARA 0x07
+#define M5602_XB_TEST_MODE_1 0x08
+#define M5602_XB_TEST_MODE_2 0x09
+#define M5602_XB_SIG_INI 0x0a
+#define M5602_XB_DS_PARA 0x0e
+#define M5602_XB_TRIG_PARA 0x0f
+#define M5602_XB_CLK_PD 0x10
+#define M5602_XB_MCU_CLK_CTRL 0x12
+#define M5602_XB_MCU_CLK_DIV 0x13
+#define M5602_XB_SEN_CLK_CTRL 0x14
+#define M5602_XB_SEN_CLK_DIV 0x15
+#define M5602_XB_AUD_CLK_CTRL 0x16
+#define M5602_XB_AUD_CLK_DIV 0x17
+#define M5602_XB_DEVCTR1 0x41
+#define M5602_XB_EPSETR0 0x42
+#define M5602_XB_EPAFCTR 0x47
+#define M5602_XB_EPBFCTR 0x49
+#define M5602_XB_EPEFCTR 0x4f
+#define M5602_XB_TEST_REG 0x53
+#define M5602_XB_ALT2SIZE 0x54
+#define M5602_XB_ALT3SIZE 0x55
+#define M5602_XB_OBSFRAME 0x56
+#define M5602_XB_PWR_CTL 0x59
+#define M5602_XB_ADC_CTRL 0x60
+#define M5602_XB_ADC_DATA 0x61
+#define M5602_XB_MISC_CTRL 0x62
+#define M5602_XB_SNAPSHOT 0x63
+#define M5602_XB_SCRATCH_1 0x64
+#define M5602_XB_SCRATCH_2 0x65
+#define M5602_XB_SCRATCH_3 0x66
+#define M5602_XB_SCRATCH_4 0x67
+#define M5602_XB_I2C_CTRL 0x68
+#define M5602_XB_I2C_CLK_DIV 0x69
+#define M5602_XB_I2C_DEV_ADDR 0x6a
+#define M5602_XB_I2C_REG_ADDR 0x6b
+#define M5602_XB_I2C_DATA 0x6c
+#define M5602_XB_I2C_STATUS 0x6d
+#define M5602_XB_GPIO_DAT_H 0x70
+#define M5602_XB_GPIO_DAT_L 0x71
+#define M5602_XB_GPIO_DIR_H 0x72
+#define M5602_XB_GPIO_DIR_L 0x73
+#define M5602_XB_GPIO_EN_H 0x74
+#define M5602_XB_GPIO_EN_L 0x75
+#define M5602_XB_GPIO_DAT 0x76
+#define M5602_XB_GPIO_DIR 0x77
+#define M5602_XB_MISC_CTL 0x70
+
+#define I2C_BUSY 0x80
+
+/*****************************************************************************/
+
+/* Driver info */
+#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
+#define DRIVER_DESC "ALi m5602 webcam driver"
+
+#define M5602_ISOC_ENDPOINT_ADDR 0x81
+#define M5602_INTR_ENDPOINT_ADDR 0x82
+
+#define M5602_MAX_FRAMES 32
+#define M5602_URBS 2
+#define M5602_ISOC_PACKETS 14
+
+#define M5602_URB_TIMEOUT msecs_to_jiffies(2 * M5602_ISOC_PACKETS)
+#define M5602_URB_MSG_TIMEOUT 5000
+#define M5602_FRAME_TIMEOUT 2
+
+/*****************************************************************************/
+
+/* A skeleton used for sending messages to the m5602 bridge */
+static const unsigned char bridge_urb_skeleton[] = {
+ 0x13, 0x00, 0x81, 0x00
+};
+
+/* A skeleton used for sending messages to the sensor */
+static const unsigned char sensor_urb_skeleton[] = {
+ 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
+ 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
+ 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
+ 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
+ 0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
+ 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
+};
+
+/* m5602 device descriptor, currently it just wraps the m5602_camera struct */
+struct sd {
+ struct gspca_dev gspca_dev;
+
+ /* The name of the m5602 camera */
+ char *name;
+
+ /* A pointer to the currently connected sensor */
+ struct m5602_sensor *sensor;
+
+ struct sd_desc *desc;
+
+ /* The current frame's id, used to detect frame boundaries */
+ u8 frame_id;
+
+ /* The current frame count */
+ u32 frame_count;
+};
+
+int m5602_read_bridge(
+ struct sd *sd, u8 address, u8 *i2c_data);
+
+int m5602_write_bridge(
+ struct sd *sd, u8 address, u8 i2c_data);
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
new file mode 100644
index 00000000000..fd6ce384b48
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -0,0 +1,309 @@
+ /*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_ov9650.h"
+#include "m5602_mt9m111.h"
+#include "m5602_po1030.h"
+#include "m5602_s5k83a.h"
+#include "m5602_s5k4aa.h"
+
+/* Kernel module parameters */
+int force_sensor;
+int dump_bridge;
+int dump_sensor;
+
+static const __devinitdata struct usb_device_id m5602_table[] = {
+ {USB_DEVICE(0x0402, 0x5602)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, m5602_table);
+
+/* Reads a byte from the m5602 */
+int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
+{
+ int err;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x04, 0xc0, 0x14,
+ 0x8100 + address, buf,
+ 1, M5602_URB_MSG_TIMEOUT);
+ *i2c_data = buf[0];
+
+ PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
+ address, *i2c_data);
+
+ /* usb_control_msg(...) returns the number of bytes sent upon success,
+ mask that and return zero upon success instead*/
+ return (err < 0) ? err : 0;
+}
+
+/* Writes a byte to to the m5602 */
+int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
+{
+ int err;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
+ address, i2c_data);
+
+ memcpy(buf, bridge_urb_skeleton,
+ sizeof(bridge_urb_skeleton));
+ buf[1] = address;
+ buf[3] = i2c_data;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 4, M5602_URB_MSG_TIMEOUT);
+
+ /* usb_control_msg(...) returns the number of bytes sent upon success,
+ mask that and return zero upon success instead */
+ return (err < 0) ? err : 0;
+}
+
+/* Dump all the registers of the m5602 bridge,
+ unfortunately this breaks the camera until it's power cycled */
+static void m5602_dump_bridge(struct sd *sd)
+{
+ int i;
+ for (i = 0; i < 0x80; i++) {
+ unsigned char val = 0;
+ m5602_read_bridge(sd, i, &val);
+ info("ALi m5602 address 0x%x contains 0x%x", i, val);
+ }
+ info("Warning: The ALi m5602 webcam probably won't work "
+ "until it's power cycled");
+}
+
+static int m5602_probe_sensor(struct sd *sd)
+{
+ /* Try the po1030 */
+ sd->sensor = &po1030;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
+ /* Try the mt9m111 sensor */
+ sd->sensor = &mt9m111;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
+ /* Try the s5k4aa */
+ sd->sensor = &s5k4aa;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
+ /* Try the ov9650 */
+ sd->sensor = &ov9650;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
+ /* Try the s5k83a */
+ sd->sensor = &s5k83a;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
+ /* More sensor probe function goes here */
+ info("Failed to find a sensor");
+ sd->sensor = NULL;
+ return -ENODEV;
+}
+
+static int m5602_configure(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id);
+
+static int m5602_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int err;
+
+ PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
+ /* Run the init sequence */
+ err = sd->sensor->init(sd);
+
+ return err;
+}
+
+static int m5602_start_transfer(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+ int err;
+
+ /* Send start command to the camera */
+ const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
+ memcpy(buf, buffer, sizeof(buffer));
+ err = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0x04, 0x40, 0x19, 0x0000, buf,
+ 4, M5602_URB_MSG_TIMEOUT);
+
+ PDEBUG(D_STREAM, "Transfer started");
+ return (err < 0) ? err : 0;
+}
+
+static void m5602_urb_complete(struct gspca_dev *gspca_dev,
+ struct gspca_frame *frame,
+ __u8 *data, int len)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (len < 6) {
+ PDEBUG(D_PACK, "Packet is less than 6 bytes");
+ return;
+ }
+
+ /* Frame delimiter: ff xx xx xx ff ff */
+ if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
+ data[2] != sd->frame_id) {
+ PDEBUG(D_FRAM, "Frame delimiter detected");
+ sd->frame_id = data[2];
+
+ /* Remove the extra fluff appended on each header */
+ data += 6;
+ len -= 6;
+
+ /* Complete the last frame (if any) */
+ frame = gspca_frame_add(gspca_dev, LAST_PACKET,
+ frame, data, 0);
+ sd->frame_count++;
+
+ /* Create a new frame */
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
+
+ PDEBUG(D_FRAM, "Starting new frame %d",
+ sd->frame_count);
+
+ } else {
+ int cur_frame_len = frame->data_end - frame->data;
+
+ /* Remove urb header */
+ data += 4;
+ len -= 4;
+
+ if (cur_frame_len + len <= frame->v4l2_buf.length) {
+ PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
+ sd->frame_count, len);
+
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ data, len);
+ } else if (frame->v4l2_buf.length - cur_frame_len > 0) {
+ /* Add the remaining data up to frame size */
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data,
+ frame->v4l2_buf.length - cur_frame_len);
+ }
+ }
+}
+
+static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
+{
+ /* Is there are a command to stop a data transfer? */
+}
+
+/* sub-driver description, the ctrl and nctrl is filled at probe time */
+static struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ .config = m5602_configure,
+ .init = m5602_init,
+ .start = m5602_start_transfer,
+ .stopN = m5602_stop_transfer,
+ .pkt_scan = m5602_urb_complete
+};
+
+/* this function is called at probe time */
+static int m5602_configure(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct cam *cam;
+ int err;
+
+ cam = &gspca_dev->cam;
+ cam->epaddr = M5602_ISOC_ENDPOINT_ADDR;
+ sd->desc = &sd_desc;
+
+ if (dump_bridge)
+ m5602_dump_bridge(sd);
+
+ /* Probe sensor */
+ err = m5602_probe_sensor(sd);
+ if (err)
+ goto fail;
+
+ return 0;
+
+fail:
+ PDEBUG(D_ERR, "ALi m5602 webcam failed");
+ cam->cam_mode = NULL;
+ cam->nmodes = 0;
+
+ return err;
+}
+
+static int m5602_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = m5602_table,
+ .probe = m5602_probe,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+ .disconnect = gspca_disconnect
+};
+
+/* -- module insert / remove -- */
+static int __init mod_m5602_init(void)
+{
+ if (usb_register(&sd_driver) < 0)
+ return -1;
+ PDEBUG(D_PROBE, "registered");
+ return 0;
+}
+static void __exit mod_m5602_exit(void)
+{
+ usb_deregister(&sd_driver);
+ PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(mod_m5602_init);
+module_exit(mod_m5602_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+module_param(force_sensor, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(force_sensor,
+ "force detection of sensor, "
+ "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030");
+
+module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
+
+module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
+ "at startup providing a sensor is found");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
new file mode 100644
index 00000000000..fb700c2d055
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -0,0 +1,345 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_mt9m111.h"
+
+int mt9m111_probe(struct sd *sd)
+{
+ u8 data[2] = {0x00, 0x00};
+ int i;
+
+ if (force_sensor) {
+ if (force_sensor == MT9M111_SENSOR) {
+ info("Forcing a %s sensor", mt9m111.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor, don't try to probe this
+ * one */
+ return -ENODEV;
+ }
+
+ info("Probing for a mt9m111 sensor");
+
+ /* Do the preinit */
+ for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
+ if (preinit_mt9m111[i][0] == BRIDGE) {
+ m5602_write_bridge(sd,
+ preinit_mt9m111[i][1],
+ preinit_mt9m111[i][2]);
+ } else {
+ data[0] = preinit_mt9m111[i][2];
+ data[1] = preinit_mt9m111[i][3];
+ mt9m111_write_sensor(sd,
+ preinit_mt9m111[i][1], data, 2);
+ }
+ }
+
+ if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+ return -ENODEV;
+
+ if ((data[0] == 0x14) && (data[1] == 0x3a)) {
+ info("Detected a mt9m111 sensor");
+ goto sensor_found;
+ }
+
+ return -ENODEV;
+
+sensor_found:
+ sd->gspca_dev.cam.cam_mode = mt9m111.modes;
+ sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
+ sd->desc->ctrls = mt9m111.ctrls;
+ sd->desc->nctrls = mt9m111.nctrls;
+ return 0;
+}
+
+int mt9m111_init(struct sd *sd)
+{
+ int i, err = 0;
+
+ /* Init the sensor */
+ for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
+ u8 data[2];
+
+ if (init_mt9m111[i][0] == BRIDGE) {
+ err = m5602_write_bridge(sd,
+ init_mt9m111[i][1],
+ init_mt9m111[i][2]);
+ } else {
+ data[0] = init_mt9m111[i][2];
+ data[1] = init_mt9m111[i][3];
+ err = mt9m111_write_sensor(sd,
+ init_mt9m111[i][1], data, 2);
+ }
+ }
+
+ if (dump_sensor)
+ mt9m111_dump_registers(sd);
+
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_power_down(struct sd *sd)
+{
+ return 0;
+}
+
+int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ data, 2);
+ *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
+ PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+
+ /* Set the correct page map */
+ err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ if (err < 0)
+ goto out;
+
+ err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ if (err < 0)
+ goto out;
+
+ data[0] = (data[0] & 0xfe) | val;
+ err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ data, 2);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ data, 2);
+ *val = data[0] & MT9M111_RMB_MIRROR_COLS;
+ PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+
+ /* Set the correct page map */
+ err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ if (err < 0)
+ goto out;
+
+ err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ if (err < 0)
+ goto out;
+
+ data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
+ err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ data, 2);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err, tmp;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
+ tmp = ((data[1] << 8) | data[0]);
+
+ *val = ((tmp & (1 << 10)) * 2) |
+ ((tmp & (1 << 9)) * 2) |
+ ((tmp & (1 << 8)) * 2) |
+ (tmp & 0x7f);
+
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err, tmp;
+ u8 data[2] = {0x00, 0x00};
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* Set the correct page map */
+ err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ if (err < 0)
+ goto out;
+
+ if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
+ return -EINVAL;
+
+ if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
+ (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
+ tmp = (1 << 10) | (val << 9) |
+ (val << 8) | (val / 8);
+ else if ((val >= INITIAL_MAX_GAIN * 2) &&
+ (val < INITIAL_MAX_GAIN * 2 * 2))
+ tmp = (1 << 9) | (1 << 8) | (val / 4);
+ else if ((val >= INITIAL_MAX_GAIN) &&
+ (val < INITIAL_MAX_GAIN * 2))
+ tmp = (1 << 8) | (val / 2);
+ else
+ tmp = val;
+
+ data[1] = (tmp & 0xff00) >> 8;
+ data[0] = (tmp & 0xff);
+ PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+ data[1], data[0]);
+
+ err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+ data, 2);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len) {
+ int err, i;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ sd->sensor->i2c_slave_id);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
+ if (err < 0)
+ goto out;
+
+ for (i = 0; i < len && !err; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x contains 0x%x ", address, *i2c_data);
+ }
+out:
+ return (err < 0) ? err : 0;
+}
+
+int mt9m111_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* No sensor with a data width larger
+ than 16 bits has yet been seen, nor with 0 :p*/
+ if (len > 2 || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton,
+ sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the tailer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
+void mt9m111_dump_registers(struct sd *sd)
+{
+ u8 address, value[2] = {0x00, 0x00};
+
+ info("Dumping the mt9m111 register state");
+
+ info("Dumping the mt9m111 sensor core registers");
+ value[1] = MT9M111_SENSOR_CORE;
+ mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ for (address = 0; address < 0xff; address++) {
+ mt9m111_read_sensor(sd, address, value, 2);
+ info("register 0x%x contains 0x%x%x",
+ address, value[0], value[1]);
+ }
+
+ info("Dumping the mt9m111 color pipeline registers");
+ value[1] = MT9M111_COLORPIPE;
+ mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ for (address = 0; address < 0xff; address++) {
+ mt9m111_read_sensor(sd, address, value, 2);
+ info("register 0x%x contains 0x%x%x",
+ address, value[0], value[1]);
+ }
+
+ info("Dumping the mt9m111 camera control registers");
+ value[1] = MT9M111_CAMERA_CONTROL;
+ mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ for (address = 0; address < 0xff; address++) {
+ mt9m111_read_sensor(sd, address, value, 2);
+ info("register 0x%x contains 0x%x%x",
+ address, value[0], value[1]);
+ }
+
+ info("mt9m111 register state dump complete");
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
new file mode 100644
index 00000000000..315209d5aee
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -0,0 +1,1019 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Some defines taken from the mt9m111 sensor driver
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@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 the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_MT9M111_H_
+#define M5602_MT9M111_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define MT9M111_SC_CHIPVER 0x00
+#define MT9M111_SC_ROWSTART 0x01
+#define MT9M111_SC_COLSTART 0x02
+#define MT9M111_SC_WINDOW_HEIGHT 0x03
+#define MT9M111_SC_WINDOW_WIDTH 0x04
+#define MT9M111_SC_HBLANK_CONTEXT_B 0x05
+#define MT9M111_SC_VBLANK_CONTEXT_B 0x06
+#define MT9M111_SC_HBLANK_CONTEXT_A 0x07
+#define MT9M111_SC_VBLANK_CONTEXT_A 0x08
+#define MT9M111_SC_SHUTTER_WIDTH 0x09
+#define MT9M111_SC_ROW_SPEED 0x0a
+
+#define MT9M111_SC_EXTRA_DELAY 0x0b
+#define MT9M111_SC_SHUTTER_DELAY 0x0c
+#define MT9M111_SC_RESET 0x0d
+#define MT9M111_SC_R_MODE_CONTEXT_B 0x20
+#define MT9M111_SC_R_MODE_CONTEXT_A 0x21
+#define MT9M111_SC_FLASH_CONTROL 0x23
+#define MT9M111_SC_GREEN_1_GAIN 0x2b
+#define MT9M111_SC_BLUE_GAIN 0x2c
+#define MT9M111_SC_RED_GAIN 0x2d
+#define MT9M111_SC_GREEN_2_GAIN 0x2e
+#define MT9M111_SC_GLOBAL_GAIN 0x2f
+
+#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
+#define MT9M111_RMB_MIRROR_COLS (1 << 1)
+
+#define MT9M111_CONTEXT_CONTROL 0xc8
+#define MT9M111_PAGE_MAP 0xf0
+#define MT9M111_BYTEWISE_ADDRESS 0xf1
+
+#define MT9M111_CP_OPERATING_MODE_CTL 0x06
+#define MT9M111_CP_LUMA_OFFSET 0x34
+#define MT9M111_CP_LUMA_CLIP 0x35
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
+#define MT9M111_CP_LENS_CORRECTION_1 0x3b
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
+#define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3
+
+#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65
+#define MT9M111_CC_AWB_PARAMETER_7 0x28
+
+#define MT9M111_SENSOR_CORE 0x00
+#define MT9M111_COLORPIPE 0x01
+#define MT9M111_CAMERA_CONTROL 0x02
+
+#define INITIAL_MAX_GAIN 64
+#define DEFAULT_GAIN 283
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int mt9m111_probe(struct sd *sd);
+int mt9m111_init(struct sd *sd);
+int mt9m111_power_down(struct sd *sd);
+
+int mt9m111_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+int mt9m111_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+void mt9m111_dump_registers(struct sd *sd);
+
+int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor mt9m111 = {
+ .name = "MT9M111",
+
+ .i2c_slave_id = 0xba,
+
+ .probe = mt9m111_probe,
+ .init = mt9m111_init,
+ .power_down = mt9m111_power_down,
+
+ .read_sensor = mt9m111_read_sensor,
+ .write_sensor = mt9m111_write_sensor,
+
+ .nctrls = 3,
+ .ctrls = {
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = mt9m111_set_vflip,
+ .get = mt9m111_get_vflip
+ }, {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = mt9m111_set_hflip,
+ .get = mt9m111_get_hflip
+ }, {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "gain",
+ .minimum = 0,
+ .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
+ .step = 1,
+ .default_value = DEFAULT_GAIN,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = mt9m111_set_gain,
+ .get = mt9m111_get_gain
+ }
+ },
+
+ .nmodes = 1,
+ .modes = {
+ {
+ M5602_DEFAULT_FRAME_WIDTH,
+ M5602_DEFAULT_FRAME_HEIGHT,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+ .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ }
+ }
+};
+
+static const unsigned char preinit_mt9m111[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
+};
+
+static const unsigned char init_mt9m111[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xde},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+ {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+
+ {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+ {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+
+ {SENSOR, 0xcd, 0x00, 0x0e},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+ {SENSOR, 0xd0, 0x00, 0x40},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+ {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {SENSOR, 0x33, 0x03, 0x49},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+ {SENSOR, 0x33, 0x03, 0x49},
+ {SENSOR, 0x34, 0xc0, 0x19},
+ {SENSOR, 0x3f, 0x20, 0x20},
+ {SENSOR, 0x40, 0x20, 0x20},
+ {SENSOR, 0x5a, 0xc0, 0x0a},
+ {SENSOR, 0x70, 0x7b, 0x0a},
+ {SENSOR, 0x71, 0xff, 0x00},
+ {SENSOR, 0x72, 0x19, 0x0e},
+ {SENSOR, 0x73, 0x18, 0x0f},
+ {SENSOR, 0x74, 0x57, 0x32},
+ {SENSOR, 0x75, 0x56, 0x34},
+ {SENSOR, 0x76, 0x73, 0x35},
+ {SENSOR, 0x77, 0x30, 0x12},
+ {SENSOR, 0x78, 0x79, 0x02},
+ {SENSOR, 0x79, 0x75, 0x06},
+ {SENSOR, 0x7a, 0x77, 0x0a},
+ {SENSOR, 0x7b, 0x78, 0x09},
+ {SENSOR, 0x7c, 0x7d, 0x06},
+ {SENSOR, 0x7d, 0x31, 0x10},
+ {SENSOR, 0x7e, 0x00, 0x7e},
+ {SENSOR, 0x80, 0x59, 0x04},
+ {SENSOR, 0x81, 0x59, 0x04},
+ {SENSOR, 0x82, 0x57, 0x0a},
+ {SENSOR, 0x83, 0x58, 0x0b},
+ {SENSOR, 0x84, 0x47, 0x0c},
+ {SENSOR, 0x85, 0x48, 0x0e},
+ {SENSOR, 0x86, 0x5b, 0x02},
+ {SENSOR, 0x87, 0x00, 0x5c},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, 0x60, 0x00, 0x80},
+ {SENSOR, 0x61, 0x00, 0x00},
+ {SENSOR, 0x62, 0x00, 0x00},
+ {SENSOR, 0x63, 0x00, 0x00},
+ {SENSOR, 0x64, 0x00, 0x00},
+
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+ {SENSOR, 0x30, 0x04, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+ {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+ {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+ {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+ {SENSOR, 0xcd, 0x00, 0x0e},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+ {SENSOR, 0xd0, 0x00, 0x40},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+ {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {SENSOR, 0x33, 0x03, 0x49},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+ {SENSOR, 0x33, 0x03, 0x49},
+ {SENSOR, 0x34, 0xc0, 0x19},
+ {SENSOR, 0x3f, 0x20, 0x20},
+ {SENSOR, 0x40, 0x20, 0x20},
+ {SENSOR, 0x5a, 0xc0, 0x0a},
+ {SENSOR, 0x70, 0x7b, 0x0a},
+ {SENSOR, 0x71, 0xff, 0x00},
+ {SENSOR, 0x72, 0x19, 0x0e},
+ {SENSOR, 0x73, 0x18, 0x0f},
+ {SENSOR, 0x74, 0x57, 0x32},
+ {SENSOR, 0x75, 0x56, 0x34},
+ {SENSOR, 0x76, 0x73, 0x35},
+ {SENSOR, 0x77, 0x30, 0x12},
+ {SENSOR, 0x78, 0x79, 0x02},
+ {SENSOR, 0x79, 0x75, 0x06},
+ {SENSOR, 0x7a, 0x77, 0x0a},
+ {SENSOR, 0x7b, 0x78, 0x09},
+ {SENSOR, 0x7c, 0x7d, 0x06},
+ {SENSOR, 0x7d, 0x31, 0x10},
+ {SENSOR, 0x7e, 0x00, 0x7e},
+ {SENSOR, 0x80, 0x59, 0x04},
+ {SENSOR, 0x81, 0x59, 0x04},
+ {SENSOR, 0x82, 0x57, 0x0a},
+ {SENSOR, 0x83, 0x58, 0x0b},
+ {SENSOR, 0x84, 0x47, 0x0c},
+ {SENSOR, 0x85, 0x48, 0x0e},
+ {SENSOR, 0x86, 0x5b, 0x02},
+ {SENSOR, 0x87, 0x00, 0x5c},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, 0x60, 0x00, 0x80},
+ {SENSOR, 0x61, 0x00, 0x00},
+ {SENSOR, 0x62, 0x00, 0x00},
+ {SENSOR, 0x63, 0x00, 0x00},
+ {SENSOR, 0x64, 0x00, 0x00},
+
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+ {SENSOR, 0x30, 0x04, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+ {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+ {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+ {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+ {SENSOR, 0xcd, 0x00, 0x0e},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+ {SENSOR, 0xd0, 0x00, 0x40},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+ {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {SENSOR, 0x33, 0x03, 0x49},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+ {SENSOR, 0x33, 0x03, 0x49},
+ {SENSOR, 0x34, 0xc0, 0x19},
+ {SENSOR, 0x3f, 0x20, 0x20},
+ {SENSOR, 0x40, 0x20, 0x20},
+ {SENSOR, 0x5a, 0xc0, 0x0a},
+ {SENSOR, 0x70, 0x7b, 0x0a},
+ {SENSOR, 0x71, 0xff, 0x00},
+ {SENSOR, 0x72, 0x19, 0x0e},
+ {SENSOR, 0x73, 0x18, 0x0f},
+ {SENSOR, 0x74, 0x57, 0x32},
+ {SENSOR, 0x75, 0x56, 0x34},
+ {SENSOR, 0x76, 0x73, 0x35},
+ {SENSOR, 0x77, 0x30, 0x12},
+ {SENSOR, 0x78, 0x79, 0x02},
+ {SENSOR, 0x79, 0x75, 0x06},
+ {SENSOR, 0x7a, 0x77, 0x0a},
+ {SENSOR, 0x7b, 0x78, 0x09},
+ {SENSOR, 0x7c, 0x7d, 0x06},
+ {SENSOR, 0x7d, 0x31, 0x10},
+ {SENSOR, 0x7e, 0x00, 0x7e},
+ {SENSOR, 0x80, 0x59, 0x04},
+ {SENSOR, 0x81, 0x59, 0x04},
+ {SENSOR, 0x82, 0x57, 0x0a},
+ {SENSOR, 0x83, 0x58, 0x0b},
+ {SENSOR, 0x84, 0x47, 0x0c},
+ {SENSOR, 0x85, 0x48, 0x0e},
+ {SENSOR, 0x86, 0x5b, 0x02},
+ {SENSOR, 0x87, 0x00, 0x5c},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, 0x60, 0x00, 0x80},
+ {SENSOR, 0x61, 0x00, 0x00},
+ {SENSOR, 0x62, 0x00, 0x00},
+ {SENSOR, 0x63, 0x00, 0x00},
+ {SENSOR, 0x64, 0x00, 0x00},
+
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+ {SENSOR, 0x30, 0x04, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+ {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+ {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0xcd, 0x00, 0x0e},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0xd0, 0x00, 0x40},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+ {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0x33, 0x03, 0x49},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+ {SENSOR, 0x33, 0x03, 0x49},
+ {SENSOR, 0x34, 0xc0, 0x19},
+ {SENSOR, 0x3f, 0x20, 0x20},
+ {SENSOR, 0x40, 0x20, 0x20},
+ {SENSOR, 0x5a, 0xc0, 0x0a},
+ {SENSOR, 0x70, 0x7b, 0x0a},
+ {SENSOR, 0x71, 0xff, 0x00},
+ {SENSOR, 0x72, 0x19, 0x0e},
+ {SENSOR, 0x73, 0x18, 0x0f},
+ {SENSOR, 0x74, 0x57, 0x32},
+ {SENSOR, 0x75, 0x56, 0x34},
+ {SENSOR, 0x76, 0x73, 0x35},
+ {SENSOR, 0x77, 0x30, 0x12},
+ {SENSOR, 0x78, 0x79, 0x02},
+ {SENSOR, 0x79, 0x75, 0x06},
+ {SENSOR, 0x7a, 0x77, 0x0a},
+ {SENSOR, 0x7b, 0x78, 0x09},
+ {SENSOR, 0x7c, 0x7d, 0x06},
+ {SENSOR, 0x7d, 0x31, 0x10},
+ {SENSOR, 0x7e, 0x00, 0x7e},
+ {SENSOR, 0x80, 0x59, 0x04},
+ {SENSOR, 0x81, 0x59, 0x04},
+ {SENSOR, 0x82, 0x57, 0x0a},
+ {SENSOR, 0x83, 0x58, 0x0b},
+ {SENSOR, 0x84, 0x47, 0x0c},
+ {SENSOR, 0x85, 0x48, 0x0e},
+ {SENSOR, 0x86, 0x5b, 0x02},
+ {SENSOR, 0x87, 0x00, 0x5c},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, 0x60, 0x00, 0x80},
+ {SENSOR, 0x61, 0x00, 0x00},
+ {SENSOR, 0x62, 0x00, 0x00},
+ {SENSOR, 0x63, 0x00, 0x00},
+ {SENSOR, 0x64, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+ {SENSOR, 0x30, 0x04, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+ {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+ {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+ {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+ {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+ {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0xcd, 0x00, 0x0e},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0xd0, 0x00, 0x40},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+ {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+ {SENSOR, 0x33, 0x03, 0x49},
+ {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+ {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+ {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+ {SENSOR, 0x33, 0x03, 0x49},
+ {SENSOR, 0x34, 0xc0, 0x19},
+ {SENSOR, 0x3f, 0x20, 0x20},
+ {SENSOR, 0x40, 0x20, 0x20},
+ {SENSOR, 0x5a, 0xc0, 0x0a},
+ {SENSOR, 0x70, 0x7b, 0x0a},
+ {SENSOR, 0x71, 0xff, 0x00},
+ {SENSOR, 0x72, 0x19, 0x0e},
+ {SENSOR, 0x73, 0x18, 0x0f},
+ {SENSOR, 0x74, 0x57, 0x32},
+ {SENSOR, 0x75, 0x56, 0x34},
+ {SENSOR, 0x76, 0x73, 0x35},
+ {SENSOR, 0x77, 0x30, 0x12},
+ {SENSOR, 0x78, 0x79, 0x02},
+ {SENSOR, 0x79, 0x75, 0x06},
+ {SENSOR, 0x7a, 0x77, 0x0a},
+ {SENSOR, 0x7b, 0x78, 0x09},
+ {SENSOR, 0x7c, 0x7d, 0x06},
+ {SENSOR, 0x7d, 0x31, 0x10},
+ {SENSOR, 0x7e, 0x00, 0x7e},
+ {SENSOR, 0x80, 0x59, 0x04},
+ {SENSOR, 0x81, 0x59, 0x04},
+ {SENSOR, 0x82, 0x57, 0x0a},
+ {SENSOR, 0x83, 0x58, 0x0b},
+ {SENSOR, 0x84, 0x47, 0x0c},
+ {SENSOR, 0x85, 0x48, 0x0e},
+ {SENSOR, 0x86, 0x5b, 0x02},
+ {SENSOR, 0x87, 0x00, 0x5c},
+ {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+ {SENSOR, 0x60, 0x00, 0x80},
+ {SENSOR, 0x61, 0x00, 0x00},
+ {SENSOR, 0x62, 0x00, 0x00},
+ {SENSOR, 0x63, 0x00, 0x00},
+ {SENSOR, 0x64, 0x00, 0x00},
+
+ {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+ {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
+ {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
+ {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
+ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
+ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+ {SENSOR, 0x30, 0x04, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+ /* Set number of blank rows chosen to 400 */
+ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+ /* Set the global gain to 283 (of 512) */
+ {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63}
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
new file mode 100644
index 00000000000..837c7e47661
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -0,0 +1,546 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_ov9650.h"
+
+int ov9650_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+
+ /* The ov9650 registers have a max depth of one byte */
+ if (len > 1 || !len)
+ return -EINVAL;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+
+ m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ ov9650.i2c_slave_id);
+ m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
+ m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+
+ for (i = 0; i < len; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x containing 0x%x ", address, *i2c_data);
+ }
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* The ov9650 only supports one byte writes */
+ if (len > 1 || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton,
+ sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ /* Special case larger sensor writes */
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the tailer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_probe(struct sd *sd)
+{
+ u8 prod_id = 0, ver_id = 0, i;
+
+ if (force_sensor) {
+ if (force_sensor == OV9650_SENSOR) {
+ info("Forcing an %s sensor", ov9650.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor,
+ don't try to probe this one */
+ return -ENODEV;
+ }
+
+ info("Probing for an ov9650 sensor");
+
+ /* Run the pre-init to actually probe the unit */
+ for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
+ u8 data = preinit_ov9650[i][2];
+ if (preinit_ov9650[i][0] == SENSOR)
+ ov9650_write_sensor(sd,
+ preinit_ov9650[i][1], &data, 1);
+ else
+ m5602_write_bridge(sd, preinit_ov9650[i][1], data);
+ }
+
+ if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1))
+ return -ENODEV;
+
+ if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1))
+ return -ENODEV;
+
+ if ((prod_id == 0x96) && (ver_id == 0x52)) {
+ info("Detected an ov9650 sensor");
+ goto sensor_found;
+ }
+
+ return -ENODEV;
+
+sensor_found:
+ sd->gspca_dev.cam.cam_mode = ov9650.modes;
+ sd->gspca_dev.cam.nmodes = ov9650.nmodes;
+ sd->desc->ctrls = ov9650.ctrls;
+ sd->desc->nctrls = ov9650.nctrls;
+ return 0;
+}
+
+int ov9650_init(struct sd *sd)
+{
+ int i, err = 0;
+ u8 data;
+
+ if (dump_sensor)
+ ov9650_dump_registers(sd);
+
+ for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
+ data = init_ov9650[i][2];
+ if (init_ov9650[i][0] == SENSOR)
+ err = ov9650_write_sensor(sd, init_ov9650[i][1],
+ &data, 1);
+ else
+ err = m5602_write_bridge(sd, init_ov9650[i][1], data);
+ }
+
+ if (!err && dmi_check_system(ov9650_flip_dmi_table)) {
+ info("vflip quirk active");
+ data = 0x30;
+ err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1);
+ }
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_power_down(struct sd *sd)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) {
+ u8 data = power_down_ov9650[i][2];
+ if (power_down_ov9650[i][0] == SENSOR)
+ ov9650_write_sensor(sd,
+ power_down_ov9650[i][1], &data, 1);
+ else
+ m5602_write_bridge(sd, power_down_ov9650[i][1], data);
+ }
+
+ return 0;
+}
+
+int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+ *val = i2c_data & 0x03;
+
+ err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+ *val |= (i2c_data << 2);
+
+ err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+ *val |= (i2c_data & 0x3f) << 10;
+
+ PDEBUG(D_V4L2, "Read exposure %d", *val);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ PDEBUG(D_V4L2, "Set exposure to %d",
+ val & 0xffff);
+
+ /* The 6 MSBs */
+ i2c_data = (val >> 10) & 0x3f;
+ err = ov9650_write_sensor(sd, OV9650_AECHM,
+ &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ /* The 8 middle bits */
+ i2c_data = (val >> 2) & 0xff;
+ err = ov9650_write_sensor(sd, OV9650_AECH,
+ &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ /* The 2 LSBs */
+ i2c_data = val & 0x03;
+ err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ *val = (i2c_data & 0x03) << 8;
+
+ err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ *val |= i2c_data;
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* The 2 MSB */
+ /* Read the OV9650_VREF register first to avoid
+ corrupting the VREF high and low bits */
+ ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ /* Mask away all uninteresting bits */
+ i2c_data = ((val & 0x0300) >> 2) |
+ (i2c_data & 0x3F);
+ err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+
+ /* The 8 LSBs */
+ i2c_data = val & 0xff;
+ err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1);
+ *val = i2c_data;
+
+ PDEBUG(D_V4L2, "Read red gain %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set red gain to %d",
+ val & 0xff);
+
+ i2c_data = val & 0xff;
+ err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+ *val = i2c_data;
+
+ PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set blue gain to %d",
+ val & 0xff);
+
+ i2c_data = val & 0xff;
+ err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ if (dmi_check_system(ov9650_flip_dmi_table))
+ *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
+ else
+ *val = (i2c_data & OV9650_HFLIP) >> 5;
+ PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+ err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ if (dmi_check_system(ov9650_flip_dmi_table))
+ i2c_data = ((i2c_data & 0xdf) |
+ (((val ? 0 : 1) & 0x01) << 5));
+ else
+ i2c_data = ((i2c_data & 0xdf) |
+ ((val & 0x01) << 5));
+
+ err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ if (dmi_check_system(ov9650_flip_dmi_table))
+ *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
+ else
+ *val = (i2c_data & 0x10) >> 4;
+ PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+ err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ if (dmi_check_system(ov9650_flip_dmi_table))
+ i2c_data = ((i2c_data & 0xef) |
+ (((val ? 0 : 1) & 0x01) << 4));
+ else
+ i2c_data = ((i2c_data & 0xef) |
+ ((val & 0x01) << 4));
+
+ err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+ *val = (i2c_data & 0x03) << 8;
+
+ err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ *val |= i2c_data;
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff);
+
+ /* Read the OV9650_VREF register first to avoid
+ corrupting the VREF high and low bits */
+ err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ /* Mask away all uninteresting bits */
+ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
+ err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ /* The 8 LSBs */
+ i2c_data = val & 0xff;
+ err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ *val = (i2c_data & OV9650_AWB_EN) >> 1;
+ PDEBUG(D_V4L2, "Read auto white balance %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+ err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
+ err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ *val = (i2c_data & OV9650_AGC_EN) >> 2;
+ PDEBUG(D_V4L2, "Read auto gain control %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 i2c_data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_V4L2, "Set auto gain control to %d", val);
+ err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
+ err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+out:
+ return (err < 0) ? err : 0;
+}
+
+void ov9650_dump_registers(struct sd *sd)
+{
+ int address;
+ info("Dumping the ov9650 register state");
+ for (address = 0; address < 0xa9; address++) {
+ u8 value;
+ ov9650_read_sensor(sd, address, &value, 1);
+ info("register 0x%x contains 0x%x",
+ address, value);
+ }
+
+ info("ov9650 register state dump complete");
+
+ info("Probing for which registers that are read/write");
+ for (address = 0; address < 0xff; address++) {
+ u8 old_value, ctrl_value;
+ u8 test_value[2] = {0xff, 0xff};
+
+ ov9650_read_sensor(sd, address, &old_value, 1);
+ ov9650_write_sensor(sd, address, test_value, 1);
+ ov9650_read_sensor(sd, address, &ctrl_value, 1);
+
+ if (ctrl_value == test_value[0])
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original value */
+ ov9650_write_sensor(sd, address, &old_value, 1);
+ }
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
new file mode 100644
index 00000000000..065632f0378
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -0,0 +1,502 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_OV9650_H_
+#define M5602_OV9650_H_
+
+#include <linux/dmi.h>
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define OV9650_GAIN 0x00
+#define OV9650_BLUE 0x01
+#define OV9650_RED 0x02
+#define OV9650_VREF 0x03
+#define OV9650_COM1 0x04
+#define OV9650_BAVE 0x05
+#define OV9650_GEAVE 0x06
+#define OV9650_RSVD7 0x07
+#define OV9650_PID 0x0a
+#define OV9650_VER 0x0b
+#define OV9650_COM3 0x0c
+#define OV9650_COM5 0x0e
+#define OV9650_COM6 0x0f
+#define OV9650_AECH 0x10
+#define OV9650_CLKRC 0x11
+#define OV9650_COM7 0x12
+#define OV9650_COM8 0x13
+#define OV9650_COM9 0x14
+#define OV9650_COM10 0x15
+#define OV9650_RSVD16 0x16
+#define OV9650_HSTART 0x17
+#define OV9650_HSTOP 0x18
+#define OV9650_VSTRT 0x19
+#define OV9650_VSTOP 0x1a
+#define OV9650_PSHFT 0x1b
+#define OV9650_MVFP 0x1e
+#define OV9650_AEW 0x24
+#define OV9650_AEB 0x25
+#define OV9650_VPT 0x26
+#define OV9650_BBIAS 0x27
+#define OV9650_GbBIAS 0x28
+#define OV9650_Gr_COM 0x29
+#define OV9650_RBIAS 0x2c
+#define OV9650_HREF 0x32
+#define OV9650_CHLF 0x33
+#define OV9650_ARBLM 0x34
+#define OV9650_RSVD35 0x35
+#define OV9650_RSVD36 0x36
+#define OV9650_ADC 0x37
+#define OV9650_ACOM38 0x38
+#define OV9650_OFON 0x39
+#define OV9650_TSLB 0x3a
+#define OV9650_COM12 0x3c
+#define OV9650_COM13 0x3d
+#define OV9650_COM15 0x40
+#define OV9650_COM16 0x41
+#define OV9650_LCC1 0x62
+#define OV9650_LCC2 0x63
+#define OV9650_LCC3 0x64
+#define OV9650_LCC4 0x65
+#define OV9650_LCC5 0x66
+#define OV9650_HV 0x69
+#define OV9650_DBLV 0x6b
+#define OV9650_COM21 0x8b
+#define OV9650_COM22 0x8c
+#define OV9650_COM24 0x8e
+#define OV9650_DBLC1 0x8f
+#define OV9650_RSVD94 0x94
+#define OV9650_RSVD95 0x95
+#define OV9650_RSVD96 0x96
+#define OV9650_LCCFB 0x9d
+#define OV9650_LCCFR 0x9e
+#define OV9650_AECHM 0xa1
+#define OV9650_COM26 0xa5
+#define OV9650_ACOMA8 0xa8
+#define OV9650_ACOMA9 0xa9
+
+#define OV9650_REGISTER_RESET (1 << 7)
+#define OV9650_VGA_SELECT (1 << 6)
+#define OV9650_RGB_SELECT (1 << 2)
+#define OV9650_RAW_RGB_SELECT (1 << 0)
+
+#define OV9650_FAST_AGC_AEC (1 << 7)
+#define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6)
+#define OV9650_BANDING (1 << 5)
+#define OV9650_AGC_EN (1 << 2)
+#define OV9650_AWB_EN (1 << 1)
+#define OV9650_AEC_EN (1 << 0)
+
+#define OV9650_VARIOPIXEL (1 << 2)
+#define OV9650_SYSTEM_CLK_SEL (1 << 7)
+#define OV9650_SLAM_MODE (1 << 4)
+
+#define OV9650_VFLIP (1 << 4)
+#define OV9650_HFLIP (1 << 5)
+
+#define GAIN_DEFAULT 0x14
+#define RED_GAIN_DEFAULT 0x70
+#define BLUE_GAIN_DEFAULT 0x20
+#define EXPOSURE_DEFAULT 0x5003
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int ov9650_probe(struct sd *sd);
+int ov9650_init(struct sd *sd);
+int ov9650_power_down(struct sd *sd);
+
+int ov9650_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+int ov9650_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+void ov9650_dump_registers(struct sd *sd);
+
+int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor ov9650 = {
+ .name = "OV9650",
+ .i2c_slave_id = 0x60,
+ .probe = ov9650_probe,
+ .init = ov9650_init,
+ .power_down = ov9650_power_down,
+ .read_sensor = ov9650_read_sensor,
+ .write_sensor = ov9650_write_sensor,
+
+ .nctrls = 8,
+ .ctrls = {
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0xffff,
+ .step = 0x1,
+ .default_value = EXPOSURE_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = ov9650_set_exposure,
+ .get = ov9650_get_exposure
+ }, {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "gain",
+ .minimum = 0x00,
+ .maximum = 0x3ff,
+ .step = 0x1,
+ .default_value = GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = ov9650_set_gain,
+ .get = ov9650_get_gain
+ }, {
+ {
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = RED_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = ov9650_set_red_balance,
+ .get = ov9650_get_red_balance
+ }, {
+ {
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = BLUE_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = ov9650_set_blue_balance,
+ .get = ov9650_get_blue_balance
+ }, {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = ov9650_set_hflip,
+ .get = ov9650_get_hflip
+ }, {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = ov9650_set_vflip,
+ .get = ov9650_get_vflip
+ }, {
+ {
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto white balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = ov9650_set_auto_white_balance,
+ .get = ov9650_get_auto_white_balance
+ }, {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto gain control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = ov9650_set_auto_gain,
+ .get = ov9650_get_auto_gain
+ }
+ },
+
+ .nmodes = 1,
+ .modes = {
+ {
+ M5602_DEFAULT_FRAME_WIDTH,
+ M5602_DEFAULT_FRAME_HEIGHT,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+ .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ }
+ }
+};
+
+static const unsigned char preinit_ov9650[][3] =
+{
+ /* [INITCAM] */
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+ /* Reset chip */
+ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+ /* Enable double clock */
+ {SENSOR, OV9650_CLKRC, 0x80},
+ /* Do something out of spec with the power */
+ {SENSOR, OV9650_OFON, 0x40}
+};
+
+static const unsigned char init_ov9650[][3] =
+{
+ /* [INITCAM] */
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+ /* Reset chip */
+ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+ /* Enable double clock */
+ {SENSOR, OV9650_CLKRC, 0x80},
+ /* Do something out of spec with the power */
+ {SENSOR, OV9650_OFON, 0x40},
+
+ /* Set QQVGA */
+ {SENSOR, OV9650_COM1, 0x20},
+ /* Set fast AGC/AEC algorithm with unlimited step size */
+ {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
+ OV9650_AEC_UNLIM_STEP_SIZE |
+ OV9650_AWB_EN | OV9650_AGC_EN},
+
+ {SENSOR, OV9650_CHLF, 0x10},
+ {SENSOR, OV9650_ARBLM, 0xbf},
+ {SENSOR, OV9650_ACOM38, 0x81},
+ /* Turn off color matrix coefficient double option */
+ {SENSOR, OV9650_COM16, 0x00},
+ /* Enable color matrix for RGB/YUV, Delay Y channel,
+ set output Y/UV delay to 1 */
+ {SENSOR, OV9650_COM13, 0x19},
+ /* Enable digital BLC, Set output mode to U Y V Y */
+ {SENSOR, OV9650_TSLB, 0x0c},
+ /* Limit the AGC/AEC stable upper region */
+ {SENSOR, OV9650_COM24, 0x00},
+ /* Enable HREF and some out of spec things */
+ {SENSOR, OV9650_COM12, 0x73},
+ /* Set all DBLC offset signs to positive and
+ do some out of spec stuff */
+ {SENSOR, OV9650_DBLC1, 0xdf},
+ {SENSOR, OV9650_COM21, 0x06},
+ {SENSOR, OV9650_RSVD35, 0x91},
+ /* Necessary, no camera stream without it */
+ {SENSOR, OV9650_RSVD16, 0x06},
+ {SENSOR, OV9650_RSVD94, 0x99},
+ {SENSOR, OV9650_RSVD95, 0x99},
+ {SENSOR, OV9650_RSVD96, 0x04},
+ /* Enable full range output */
+ {SENSOR, OV9650_COM15, 0x0},
+ /* Enable HREF at optical black, enable ADBLC bias,
+ enable ADBLC, reset timings at format change */
+ {SENSOR, OV9650_COM6, 0x4b},
+ /* Subtract 32 from the B channel bias */
+ {SENSOR, OV9650_BBIAS, 0xa0},
+ /* Subtract 32 from the Gb channel bias */
+ {SENSOR, OV9650_GbBIAS, 0xa0},
+ /* Do not bypass the analog BLC and to some out of spec stuff */
+ {SENSOR, OV9650_Gr_COM, 0x00},
+ /* Subtract 32 from the R channel bias */
+ {SENSOR, OV9650_RBIAS, 0xa0},
+ /* Subtract 32 from the R channel bias */
+ {SENSOR, OV9650_RBIAS, 0x0},
+ {SENSOR, OV9650_COM26, 0x80},
+ {SENSOR, OV9650_ACOMA9, 0x98},
+ /* Set the AGC/AEC stable region upper limit */
+ {SENSOR, OV9650_AEW, 0x68},
+ /* Set the AGC/AEC stable region lower limit */
+ {SENSOR, OV9650_AEB, 0x5c},
+ /* Set the high and low limit nibbles to 3 */
+ {SENSOR, OV9650_VPT, 0xc3},
+ /* Set the Automatic Gain Ceiling (AGC) to 128x,
+ drop VSYNC at frame drop,
+ limit exposure timing,
+ drop frame when the AEC step is larger than the exposure gap */
+ {SENSOR, OV9650_COM9, 0x6e},
+ /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
+ and set PWDN to SLVS (slave mode vertical sync) */
+ {SENSOR, OV9650_COM10, 0x42},
+ /* Set horizontal column start high to default value */
+ {SENSOR, OV9650_HSTART, 0x1a},
+ /* Set horizontal column end */
+ {SENSOR, OV9650_HSTOP, 0xbf},
+ /* Complementing register to the two writes above */
+ {SENSOR, OV9650_HREF, 0xb2},
+ /* Set vertical row start high bits */
+ {SENSOR, OV9650_VSTRT, 0x02},
+ /* Set vertical row end low bits */
+ {SENSOR, OV9650_VSTOP, 0x7e},
+ /* Set complementing vertical frame control */
+ {SENSOR, OV9650_VREF, 0x10},
+ /* Set raw RGB output format with VGA resolution */
+ {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
+ OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT},
+ {SENSOR, OV9650_ADC, 0x04},
+ {SENSOR, OV9650_HV, 0x40},
+ /* Enable denoise, and white-pixel erase */
+ {SENSOR, OV9650_COM22, 0x23},
+
+ /* Set the high bits of the exposure value */
+ {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)},
+
+ /* Set the low bits of the exposure value */
+ {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)},
+ {SENSOR, OV9650_GAIN, GAIN_DEFAULT},
+ {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT},
+ {SENSOR, OV9650_RED, RED_GAIN_DEFAULT},
+
+ {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
+ {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL},
+
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0xde}
+};
+
+static const unsigned char power_down_ov9650[][3] =
+{
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {SENSOR, OV9650_COM7, 0x80},
+ {SENSOR, OV9650_OFON, 0xf4},
+ {SENSOR, OV9650_MVFP, 0x80},
+ {SENSOR, OV9650_DBLV, 0x3f},
+ {SENSOR, OV9650_RSVD36, 0x49},
+ {SENSOR, OV9650_COM7, 0x05},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
+};
+
+/* Vertically and horizontally flips the image if matched, needed for machines
+ where the sensor is mounted upside down */
+static
+ const
+ struct dmi_system_id ov9650_flip_dmi_table[] = {
+ {
+ .ident = "ASUS A6VC",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+ }
+ },
+ {
+ .ident = "ASUS A6VM",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+ }
+ },
+ {
+ .ident = "ASUS A6JC",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
+ }
+ },
+ {
+ .ident = "ASUS A6Kt",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
+ }
+ },
+ { }
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
new file mode 100644
index 00000000000..d17ac52566e
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -0,0 +1,400 @@
+/*
+ * Driver for the po1030 sensor
+ *
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_po1030.h"
+
+int po1030_probe(struct sd *sd)
+{
+ u8 prod_id = 0, ver_id = 0, i;
+
+ if (force_sensor) {
+ if (force_sensor == PO1030_SENSOR) {
+ info("Forcing a %s sensor", po1030.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor, don't try to probe this
+ * one */
+ return -ENODEV;
+ }
+
+ info("Probing for a po1030 sensor");
+
+ /* Run the pre-init to actually probe the unit */
+ for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
+ u8 data = preinit_po1030[i][2];
+ if (preinit_po1030[i][0] == SENSOR)
+ po1030_write_sensor(sd,
+ preinit_po1030[i][1], &data, 1);
+ else
+ m5602_write_bridge(sd, preinit_po1030[i][1], data);
+ }
+
+ if (po1030_read_sensor(sd, 0x3, &prod_id, 1))
+ return -ENODEV;
+
+ if (po1030_read_sensor(sd, 0x4, &ver_id, 1))
+ return -ENODEV;
+
+ if ((prod_id == 0x02) && (ver_id == 0xef)) {
+ info("Detected a po1030 sensor");
+ goto sensor_found;
+ }
+ return -ENODEV;
+
+sensor_found:
+ sd->gspca_dev.cam.cam_mode = po1030.modes;
+ sd->gspca_dev.cam.nmodes = po1030.nmodes;
+ sd->desc->ctrls = po1030.ctrls;
+ sd->desc->nctrls = po1030.nctrls;
+ return 0;
+}
+
+int po1030_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+
+ m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ sd->sensor->i2c_slave_id);
+ m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
+ m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+
+ for (i = 0; i < len; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x containing 0x%x ", address, *i2c_data);
+ }
+ return (err < 0) ? err : 0;
+}
+
+int po1030_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* The po1030 only supports one byte writes */
+ if (len > 1 || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the footer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_init(struct sd *sd)
+{
+ int i, err = 0;
+
+ /* Init the sensor */
+ for (i = 0; i < ARRAY_SIZE(init_po1030); i++) {
+ u8 data[2] = {0x00, 0x00};
+
+ switch (init_po1030[i][0]) {
+ case BRIDGE:
+ err = m5602_write_bridge(sd,
+ init_po1030[i][1],
+ init_po1030[i][2]);
+ break;
+
+ case SENSOR:
+ data[0] = init_po1030[i][2];
+ err = po1030_write_sensor(sd,
+ init_po1030[i][1], data, 1);
+ break;
+
+ case SENSOR_LONG:
+ data[0] = init_po1030[i][2];
+ data[1] = init_po1030[i][3];
+ err = po1030_write_sensor(sd,
+ init_po1030[i][1], data, 2);
+ break;
+ default:
+ info("Invalid stream command, exiting init");
+ return -EINVAL;
+ }
+ }
+
+ if (dump_sensor)
+ po1030_dump_registers(sd);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H,
+ &i2c_data, 1);
+ if (err < 0)
+ goto out;
+ *val = (i2c_data << 8);
+
+ err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M,
+ &i2c_data, 1);
+ *val |= i2c_data;
+
+ PDEBUG(D_V4L2, "Exposure read as %d", *val);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
+
+ i2c_data = ((val & 0xff00) >> 8);
+ PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
+ i2c_data);
+
+ err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H,
+ &i2c_data, 1);
+ if (err < 0)
+ goto out;
+
+ i2c_data = (val & 0xff);
+ PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
+ i2c_data);
+ err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M,
+ &i2c_data, 1);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+ &i2c_data, 1);
+ *val = i2c_data;
+ PDEBUG(D_V4L2, "Read global gain %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_CONTROL2,
+ &i2c_data, 1);
+
+ *val = (i2c_data >> 7) & 0x01 ;
+
+ PDEBUG(D_V4L2, "Read hflip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ PDEBUG(D_V4L2, "Set hflip %d", val);
+
+ i2c_data = (val & 0x01) << 7;
+
+ err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
+ &i2c_data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+ &i2c_data, 1);
+
+ *val = (i2c_data >> 6) & 0x01;
+
+ PDEBUG(D_V4L2, "Read vflip %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ PDEBUG(D_V4L2, "Set vflip %d", val);
+
+ i2c_data = (val & 0x01) << 6;
+
+ err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
+ &i2c_data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ i2c_data = val & 0xff;
+ PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
+ err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN,
+ &i2c_data, 1);
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN,
+ &i2c_data, 1);
+ *val = i2c_data;
+ PDEBUG(D_V4L2, "Read red gain %d", *val);
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ i2c_data = val & 0xff;
+ PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
+ err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN,
+ &i2c_data, 1);
+ return (err < 0) ? err : 0;
+}
+
+int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+
+ err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN,
+ &i2c_data, 1);
+ *val = i2c_data;
+ PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 i2c_data;
+ int err;
+ i2c_data = val & 0xff;
+ PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
+ err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN,
+ &i2c_data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int po1030_power_down(struct sd *sd)
+{
+ return 0;
+}
+
+void po1030_dump_registers(struct sd *sd)
+{
+ int address;
+ u8 value = 0;
+
+ info("Dumping the po1030 sensor core registers");
+ for (address = 0; address < 0x7f; address++) {
+ po1030_read_sensor(sd, address, &value, 1);
+ info("register 0x%x contains 0x%x",
+ address, value);
+ }
+
+ info("po1030 register state dump complete");
+
+ info("Probing for which registers that are read/write");
+ for (address = 0; address < 0xff; address++) {
+ u8 old_value, ctrl_value;
+ u8 test_value[2] = {0xff, 0xff};
+
+ po1030_read_sensor(sd, address, &old_value, 1);
+ po1030_write_sensor(sd, address, test_value, 1);
+ po1030_read_sensor(sd, address, &ctrl_value, 1);
+
+ if (ctrl_value == test_value[0])
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original value */
+ po1030_write_sensor(sd, address, &old_value, 1);
+ }
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
new file mode 100644
index 00000000000..a0b75ff61d7
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -0,0 +1,508 @@
+/*
+ * Driver for the po1030 sensor.
+ *
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Register defines taken from Pascal Stangs Proxycon Armlib
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_PO1030_H_
+#define M5602_PO1030_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define PO1030_REG_DEVID_H 0x00
+#define PO1030_REG_DEVID_L 0x01
+#define PO1030_REG_FRAMEWIDTH_H 0x04
+#define PO1030_REG_FRAMEWIDTH_L 0x05
+#define PO1030_REG_FRAMEHEIGHT_H 0x06
+#define PO1030_REG_FRAMEHEIGHT_L 0x07
+#define PO1030_REG_WINDOWX_H 0x08
+#define PO1030_REG_WINDOWX_L 0x09
+#define PO1030_REG_WINDOWY_H 0x0a
+#define PO1030_REG_WINDOWY_L 0x0b
+#define PO1030_REG_WINDOWWIDTH_H 0x0c
+#define PO1030_REG_WINDOWWIDTH_L 0x0d
+#define PO1030_REG_WINDOWHEIGHT_H 0x0e
+#define PO1030_REG_WINDOWHEIGHT_L 0x0f
+
+#define PO1030_REG_GLOBALIBIAS 0x12
+#define PO1030_REG_PIXELIBIAS 0x13
+
+#define PO1030_REG_GLOBALGAIN 0x15
+#define PO1030_REG_RED_GAIN 0x16
+#define PO1030_REG_GREEN_1_GAIN 0x17
+#define PO1030_REG_BLUE_GAIN 0x18
+#define PO1030_REG_GREEN_2_GAIN 0x19
+
+#define PO1030_REG_INTEGLINES_H 0x1a
+#define PO1030_REG_INTEGLINES_M 0x1b
+#define PO1030_REG_INTEGLINES_L 0x1c
+
+#define PO1030_REG_CONTROL1 0x1d
+#define PO1030_REG_CONTROL2 0x1e
+#define PO1030_REG_CONTROL3 0x1f
+#define PO1030_REG_CONTROL4 0x20
+
+#define PO1030_REG_PERIOD50_H 0x23
+#define PO1030_REG_PERIOD50_L 0x24
+#define PO1030_REG_PERIOD60_H 0x25
+#define PO1030_REG_PERIOD60_L 0x26
+#define PO1030_REG_REGCLK167 0x27
+#define PO1030_REG_DELTA50 0x28
+#define PO1030_REG_DELTA60 0x29
+
+#define PO1030_REG_ADCOFFSET 0x2c
+
+/* Gamma Correction Coeffs */
+#define PO1030_REG_GC0 0x2d
+#define PO1030_REG_GC1 0x2e
+#define PO1030_REG_GC2 0x2f
+#define PO1030_REG_GC3 0x30
+#define PO1030_REG_GC4 0x31
+#define PO1030_REG_GC5 0x32
+#define PO1030_REG_GC6 0x33
+#define PO1030_REG_GC7 0x34
+
+/* Color Transform Matrix */
+#define PO1030_REG_CT0 0x35
+#define PO1030_REG_CT1 0x36
+#define PO1030_REG_CT2 0x37
+#define PO1030_REG_CT3 0x38
+#define PO1030_REG_CT4 0x39
+#define PO1030_REG_CT5 0x3a
+#define PO1030_REG_CT6 0x3b
+#define PO1030_REG_CT7 0x3c
+#define PO1030_REG_CT8 0x3d
+
+#define PO1030_REG_AUTOCTRL1 0x3e
+#define PO1030_REG_AUTOCTRL2 0x3f
+
+#define PO1030_REG_YTARGET 0x40
+#define PO1030_REG_GLOBALGAINMIN 0x41
+#define PO1030_REG_GLOBALGAINMAX 0x42
+
+/* Output format control */
+#define PO1030_REG_OUTFORMCTRL1 0x5a
+#define PO1030_REG_OUTFORMCTRL2 0x5b
+#define PO1030_REG_OUTFORMCTRL3 0x5c
+#define PO1030_REG_OUTFORMCTRL4 0x5d
+#define PO1030_REG_OUTFORMCTRL5 0x5e
+
+/* Imaging coefficients */
+#define PO1030_REG_YBRIGHT 0x73
+#define PO1030_REG_YCONTRAST 0x74
+#define PO1030_REG_YSATURATION 0x75
+
+#define PO1030_HFLIP (1 << 7)
+#define PO1030_VFLIP (1 << 6)
+
+/*****************************************************************************/
+
+#define PO1030_GLOBAL_GAIN_DEFAULT 0x12
+#define PO1030_EXPOSURE_DEFAULT 0x0085
+#define PO1030_BLUE_GAIN_DEFAULT 0x40
+#define PO1030_RED_GAIN_DEFAULT 0x40
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int po1030_probe(struct sd *sd);
+int po1030_init(struct sd *sd);
+int po1030_power_down(struct sd *sd);
+
+void po1030_dump_registers(struct sd *sd);
+
+int po1030_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+int po1030_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor po1030 = {
+ .name = "PO1030",
+
+ .i2c_slave_id = 0xdc,
+
+ .probe = po1030_probe,
+ .init = po1030_init,
+ .power_down = po1030_power_down,
+
+ .nctrls = 6,
+ .ctrls = {
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "gain",
+ .minimum = 0x00,
+ .maximum = 0x4f,
+ .step = 0x1,
+ .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = po1030_set_gain,
+ .get = po1030_get_gain
+ }, {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0x02ff,
+ .step = 0x1,
+ .default_value = PO1030_EXPOSURE_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = po1030_set_exposure,
+ .get = po1030_get_exposure
+ }, {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = PO1030_RED_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = po1030_set_red_balance,
+ .get = po1030_get_red_balance
+ }, {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x1,
+ .default_value = PO1030_BLUE_GAIN_DEFAULT,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = po1030_set_blue_balance,
+ .get = po1030_get_blue_balance
+ }, {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = po1030_set_hflip,
+ .get = po1030_get_hflip
+ }, {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = po1030_set_vflip,
+ .get = po1030_get_vflip
+ }
+ },
+
+ .nmodes = 1,
+ .modes = {
+ {
+ M5602_DEFAULT_FRAME_WIDTH,
+ M5602_DEFAULT_FRAME_HEIGHT,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+ .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ }
+ }
+};
+
+static const unsigned char preinit_po1030[][3] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+ {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+
+ {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
+};
+
+static const unsigned char init_po1030[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+ /*sequence 1*/
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ /*end of sequence 1*/
+
+ /*sequence 2 (same as stop sequence)*/
+ {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ /*end of sequence 2*/
+
+ /*sequence 5*/
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ /*end of sequence 5*/
+
+ /*sequence 2 stop */
+ {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ /*end of sequence 2 stop */
+
+/* ---------------------------------
+ * end of init - begin of start
+ * --------------------------------- */
+
+ /*sequence 3*/
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ /*end of sequence 3*/
+ /*sequence 4*/
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+ {SENSOR, PO1030_REG_AUTOCTRL2, 0x04},
+
+ /* Set the width to 751 */
+ {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
+ {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef},
+
+ /* Set the height to 540 */
+ {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02},
+ {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c},
+
+ /* Set the x window to 1 */
+ {SENSOR, PO1030_REG_WINDOWX_H, 0x00},
+ {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+
+ /* Set the y window to 1 */
+ {SENSOR, PO1030_REG_WINDOWY_H, 0x00},
+ {SENSOR, PO1030_REG_WINDOWY_L, 0x01},
+
+ {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
+ {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
+ {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01},
+ {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3},
+
+ {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
+ {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
+ {SENSOR, PO1030_REG_AUTOCTRL1, 0x08},
+ {SENSOR, PO1030_REG_CONTROL2, 0x03},
+ {SENSOR, 0x21, 0x90},
+ {SENSOR, PO1030_REG_YTARGET, 0x60},
+ {SENSOR, 0x59, 0x13},
+ {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40},
+ {SENSOR, 0x5f, 0x00},
+ {SENSOR, 0x60, 0x80},
+ {SENSOR, 0x78, 0x14},
+ {SENSOR, 0x6f, 0x01},
+ {SENSOR, PO1030_REG_CONTROL1, 0x18},
+ {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14},
+ {SENSOR, 0x63, 0x38},
+ {SENSOR, 0x64, 0x38},
+ {SENSOR, PO1030_REG_CONTROL1, 0x58},
+ {SENSOR, PO1030_REG_RED_GAIN, 0x30},
+ {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30},
+ {SENSOR, PO1030_REG_BLUE_GAIN, 0x30},
+ {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30},
+ {SENSOR, PO1030_REG_GC0, 0x10},
+ {SENSOR, PO1030_REG_GC1, 0x20},
+ {SENSOR, PO1030_REG_GC2, 0x40},
+ {SENSOR, PO1030_REG_GC3, 0x60},
+ {SENSOR, PO1030_REG_GC4, 0x80},
+ {SENSOR, PO1030_REG_GC5, 0xa0},
+ {SENSOR, PO1030_REG_GC6, 0xc0},
+ {SENSOR, PO1030_REG_GC7, 0xff},
+ /*end of sequence 4*/
+ /*sequence 5*/
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00},
+ /*end of sequence 5*/
+
+ /*sequence 6*/
+ /* Changing 40 in f0 the image becomes green in bayer mode and red in
+ * rgb mode */
+ {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT},
+ /* in changing 40 in f0 the image becomes green in bayer mode and red in
+ * rgb mode */
+ {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT},
+
+ /* with a very low lighted environment increase the exposure but
+ * decrease the FPS (Frame Per Second) */
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+ /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in
+ * low lighted environment (f0 is more than ff ?)*/
+ {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2)
+ & 0xff)},
+
+ /* Controls middle exposure, use only in high lighted environment */
+ {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff},
+
+ /* Controls clarity (not sure) */
+ {SENSOR, PO1030_REG_INTEGLINES_L, 0x00},
+ /* Controls gain (the image is more lighted) */
+ {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT},
+
+ /* Sets the width */
+ {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
+ {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}
+ /*end of sequence 6*/
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
new file mode 100644
index 00000000000..14b1eac5b81
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -0,0 +1,463 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_s5k4aa.h"
+
+int s5k4aa_probe(struct sd *sd)
+{
+ u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
+ int i, err = 0;
+
+ if (force_sensor) {
+ if (force_sensor == S5K4AA_SENSOR) {
+ info("Forcing a %s sensor", s5k4aa.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor, don't try to probe this
+ * one */
+ return -ENODEV;
+ }
+
+ info("Probing for a s5k4aa sensor");
+
+ /* Preinit the sensor */
+ for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
+ u8 data[2] = {0x00, 0x00};
+
+ switch (preinit_s5k4aa[i][0]) {
+ case BRIDGE:
+ err = m5602_write_bridge(sd,
+ preinit_s5k4aa[i][1],
+ preinit_s5k4aa[i][2]);
+ break;
+
+ case SENSOR:
+ data[0] = preinit_s5k4aa[i][2];
+ err = s5k4aa_write_sensor(sd,
+ preinit_s5k4aa[i][1],
+ data, 1);
+ break;
+
+ case SENSOR_LONG:
+ data[0] = preinit_s5k4aa[i][2];
+ data[1] = preinit_s5k4aa[i][3];
+ err = s5k4aa_write_sensor(sd,
+ preinit_s5k4aa[i][1],
+ data, 2);
+ break;
+ default:
+ info("Invalid stream command, exiting init");
+ return -EINVAL;
+ }
+ }
+
+ /* Test some registers, but we don't know their exact meaning yet */
+ if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
+ return -ENODEV;
+
+ if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
+ return -ENODEV;
+ else
+ info("Detected a s5k4aa sensor");
+sensor_found:
+ sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
+ sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
+ sd->desc->ctrls = s5k4aa.ctrls;
+ sd->desc->nctrls = s5k4aa.nctrls;
+
+ return 0;
+}
+
+int s5k4aa_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ sd->sensor->i2c_slave_id);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+ if (err < 0)
+ goto out;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+ if (err < 0)
+ goto out;
+
+ for (i = 0; (i < len) & !err; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x containing 0x%x ", address, *i2c_data);
+ }
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* No sensor with a data width larger than 16 bits has yet been seen */
+ if (len > 2 || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton,
+ sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ /* Special case larger sensor writes */
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the tailer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_init(struct sd *sd)
+{
+ int i, err = 0;
+
+ for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
+ u8 data[2] = {0x00, 0x00};
+
+ switch (init_s5k4aa[i][0]) {
+ case BRIDGE:
+ err = m5602_write_bridge(sd,
+ init_s5k4aa[i][1],
+ init_s5k4aa[i][2]);
+ break;
+
+ case SENSOR:
+ data[0] = init_s5k4aa[i][2];
+ err = s5k4aa_write_sensor(sd,
+ init_s5k4aa[i][1], data, 1);
+ break;
+
+ case SENSOR_LONG:
+ data[0] = init_s5k4aa[i][2];
+ data[1] = init_s5k4aa[i][3];
+ err = s5k4aa_write_sensor(sd,
+ init_s5k4aa[i][1], data, 2);
+ break;
+ default:
+ info("Invalid stream command, exiting init");
+ return -EINVAL;
+ }
+ }
+
+ if (dump_sensor)
+ s5k4aa_dump_registers(sd);
+
+ if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
+ u8 data = 0x02;
+ info("vertical flip quirk active");
+ s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ data |= S5K4AA_RM_V_FLIP;
+ data &= ~S5K4AA_RM_H_FLIP;
+ s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+
+ /* Decrement COLSTART to preserve color order (BGGR) */
+ s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ data--;
+ s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+
+ /* Increment ROWSTART to preserve color order (BGGR) */
+ s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ data++;
+ s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ }
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_power_down(struct sd *sd)
+{
+ return 0;
+}
+
+int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+
+ err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+ if (err < 0)
+ goto out;
+
+ *val = data << 8;
+ err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+ *val |= data;
+ PDEBUG(D_V4L2, "Read exposure %d", *val);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ PDEBUG(D_V4L2, "Set exposure to %d", val);
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+ data = (val >> 8) & 0xff;
+ err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+ if (err < 0)
+ goto out;
+ data = val & 0xff;
+ err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+
+ err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ *val = (data & S5K4AA_RM_V_FLIP) >> 7;
+ PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+ err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ goto out;
+ data = ((data & ~S5K4AA_RM_V_FLIP)
+ | ((val & 0x01) << 7));
+ err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ goto out;
+
+ if (val) {
+ err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ if (err < 0)
+ goto out;
+
+ data++;
+ err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ } else {
+ err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ if (err < 0)
+ goto out;
+
+ data--;
+ err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ }
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+
+ err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ *val = (data & S5K4AA_RM_H_FLIP) >> 6;
+ PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ PDEBUG(D_V4L2, "Set horizontal flip to %d",
+ val);
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+ err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ goto out;
+
+ data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
+ err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ if (err < 0)
+ goto out;
+
+ if (val) {
+ err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ if (err < 0)
+ goto out;
+ data++;
+ err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ if (err < 0)
+ goto out;
+ } else {
+ err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ if (err < 0)
+ goto out;
+ data--;
+ err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ }
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+
+ err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+ *val = data;
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 data = S5K4AA_PAGE_MAP_2;
+ int err;
+
+ PDEBUG(D_V4L2, "Set gain to %d", val);
+ err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ if (err < 0)
+ goto out;
+
+ data = val & 0xff;
+ err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+void s5k4aa_dump_registers(struct sd *sd)
+{
+ int address;
+ u8 page, old_page;
+ s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+ for (page = 0; page < 16; page++) {
+ s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+ info("Dumping the s5k4aa register state for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 value = 0;
+ s5k4aa_read_sensor(sd, address, &value, 1);
+ info("register 0x%x contains 0x%x",
+ address, value);
+ }
+ }
+ info("s5k4aa register state dump complete");
+
+ for (page = 0; page < 16; page++) {
+ s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+ info("Probing for which registers that are "
+ "read/write for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 old_value, ctrl_value, test_value = 0xff;
+
+ s5k4aa_read_sensor(sd, address, &old_value, 1);
+ s5k4aa_write_sensor(sd, address, &test_value, 1);
+ s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
+
+ if (ctrl_value == test_value)
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original value */
+ s5k4aa_write_sensor(sd, address, &old_value, 1);
+ }
+ }
+ info("Read/write register probing complete");
+ s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
new file mode 100644
index 00000000000..eaef67655af
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -0,0 +1,369 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_S5K4AA_H_
+#define M5602_S5K4AA_H_
+
+#include <linux/dmi.h>
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define S5K4AA_PAGE_MAP 0xec
+
+#define S5K4AA_PAGE_MAP_0 0x00
+#define S5K4AA_PAGE_MAP_1 0x01
+#define S5K4AA_PAGE_MAP_2 0x02
+
+/* Sensor register definitions for page 0x02 */
+#define S5K4AA_READ_MODE 0x03
+#define S5K4AA_ROWSTART_HI 0x04
+#define S5K4AA_ROWSTART_LO 0x05
+#define S5K4AA_COLSTART_HI 0x06
+#define S5K4AA_COLSTART_LO 0x07
+#define S5K4AA_WINDOW_HEIGHT_HI 0x08
+#define S5K4AA_WINDOW_HEIGHT_LO 0x09
+#define S5K4AA_WINDOW_WIDTH_HI 0x0a
+#define S5K4AA_WINDOW_WIDTH_LO 0x0b
+#define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */
+#define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost
+ if too low, reduces frame rate
+ if too high */
+#define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */
+#define S5K4AA_EXPOSURE_HI 0x17
+#define S5K4AA_EXPOSURE_LO 0x18
+#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */
+#define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */
+
+#define S5K4AA_RM_ROW_SKIP_4X 0x08
+#define S5K4AA_RM_ROW_SKIP_2X 0x04
+#define S5K4AA_RM_COL_SKIP_4X 0x02
+#define S5K4AA_RM_COL_SKIP_2X 0x01
+#define S5K4AA_RM_H_FLIP 0x40
+#define S5K4AA_RM_V_FLIP 0x80
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int s5k4aa_probe(struct sd *sd);
+int s5k4aa_init(struct sd *sd);
+int s5k4aa_power_down(struct sd *sd);
+
+void s5k4aa_dump_registers(struct sd *sd);
+
+int s5k4aa_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+int s5k4aa_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor s5k4aa = {
+ .name = "S5K4AA",
+ .probe = s5k4aa_probe,
+ .init = s5k4aa_init,
+ .power_down = s5k4aa_power_down,
+ .read_sensor = s5k4aa_read_sensor,
+ .write_sensor = s5k4aa_write_sensor,
+ .i2c_slave_id = 0x5a,
+ .nctrls = 4,
+ .ctrls = {
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = s5k4aa_set_vflip,
+ .get = s5k4aa_get_vflip
+
+ }, {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = s5k4aa_set_hflip,
+ .get = s5k4aa_get_hflip
+
+ }, {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0xa0,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = s5k4aa_set_gain,
+ .get = s5k4aa_get_gain
+ }, {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = 13,
+ .maximum = 0xfff,
+ .step = 1,
+ .default_value = 0x100,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = s5k4aa_set_exposure,
+ .get = s5k4aa_get_exposure
+ }
+ },
+
+ .nmodes = 1,
+ .modes = {
+ {
+ M5602_DEFAULT_FRAME_WIDTH,
+ M5602_DEFAULT_FRAME_HEIGHT,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+ .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ }
+ }
+};
+
+static const unsigned char preinit_s5k4aa[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+ {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
+};
+
+static const unsigned char init_s5k4aa[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+ {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
+ {SENSOR, 0x36, 0x01, 0x00},
+ {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, 0x7b, 0xff, 0x00},
+ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+ {SENSOR, 0x0c, 0x05, 0x00},
+ {SENSOR, 0x02, 0x0e, 0x00},
+ {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00},
+ {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00},
+ {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00},
+ {SENSOR, 0x11, 0x00, 0x00},
+ {SENSOR, 0x12, 0x00, 0x00},
+ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+ {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
+ {SENSOR, 0x37, 0x00, 0x00},
+ {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+ {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+ {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+ {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00},
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00},
+ {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+ {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00},
+ {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
+ {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00},
+ {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00},
+ {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00},
+ {SENSOR, 0x11, 0x04, 0x00},
+ {SENSOR, 0x12, 0xc3, 0x00},
+ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
+
+ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+ {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
+ | S5K4AA_RM_COL_SKIP_2X, 0x00},
+ /* 0x37 : Fix image stability when light is too bright and improves
+ * image quality in 640x480, but worsens it in 1280x1024 */
+ {SENSOR, 0x37, 0x01, 0x00},
+ /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
+ {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+ {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+ {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+ {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
+ /* window_height_hi, window_height_lo : 960 = 0x03c0 */
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
+ {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
+ /* window_width_hi, window_width_lo : 1280 = 0x0500 */
+ {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+ {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
+ {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
+ {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
+ {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
+ {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
+ {SENSOR, 0x11, 0x04, 0x00},
+ {SENSOR, 0x12, 0xc3, 0x00},
+ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+ {SENSOR, 0x02, 0x0e, 0x00},
+ {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
+ {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
+ {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
+};
+
+static
+ const
+ struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
+ {
+ .ident = "Fujitsu-Siemens Amilo Xa 2528",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
+ }
+ },
+ {
+ .ident = "Fujitsu-Siemens Amilo Xi 2550",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
+ }
+ },
+ {
+ .ident = "MSI GX700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+ DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
+ }
+ },
+ { }
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
new file mode 100644
index 00000000000..8988a728e0b
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -0,0 +1,423 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#include "m5602_s5k83a.h"
+
+int s5k83a_probe(struct sd *sd)
+{
+ u8 prod_id = 0, ver_id = 0;
+ int i, err = 0;
+
+ if (force_sensor) {
+ if (force_sensor == S5K83A_SENSOR) {
+ info("Forcing a %s sensor", s5k83a.name);
+ goto sensor_found;
+ }
+ /* If we want to force another sensor, don't try to probe this
+ * one */
+ return -ENODEV;
+ }
+
+ info("Probing for a s5k83a sensor");
+
+ /* Preinit the sensor */
+ for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
+ u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
+ if (preinit_s5k83a[i][0] == SENSOR)
+ err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1],
+ data, 2);
+ else
+ err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
+ data[0]);
+ }
+
+ /* We don't know what register (if any) that contain the product id
+ * Just pick the first addresses that seem to produce the same results
+ * on multiple machines */
+ if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1))
+ return -ENODEV;
+
+ if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1))
+ return -ENODEV;
+
+ if ((prod_id == 0xff) || (ver_id == 0xff))
+ return -ENODEV;
+ else
+ info("Detected a s5k83a sensor");
+
+sensor_found:
+ sd->gspca_dev.cam.cam_mode = s5k83a.modes;
+ sd->gspca_dev.cam.nmodes = s5k83a.nmodes;
+ sd->desc->ctrls = s5k83a.ctrls;
+ sd->desc->nctrls = s5k83a.nctrls;
+ return 0;
+}
+
+int s5k83a_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ sd->sensor->i2c_slave_id);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+ if (err < 0)
+ goto out;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+
+ if (err < 0)
+ goto out;
+ for (i = 0; i < len && !len; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x containing 0x%x ", address, *i2c_data);
+ }
+
+out:
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* No sensor with a data width larger than 16 bits has yet been seen */
+ if (len > 2 || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton,
+ sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ /* Special case larger sensor writes */
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the tailer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_init(struct sd *sd)
+{
+ int i, err = 0;
+
+ for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
+ u8 data[2] = {0x00, 0x00};
+
+ switch (init_s5k83a[i][0]) {
+ case BRIDGE:
+ err = m5602_write_bridge(sd,
+ init_s5k83a[i][1],
+ init_s5k83a[i][2]);
+ break;
+
+ case SENSOR:
+ data[0] = init_s5k83a[i][2];
+ err = s5k83a_write_sensor(sd,
+ init_s5k83a[i][1], data, 1);
+ break;
+
+ case SENSOR_LONG:
+ data[0] = init_s5k83a[i][2];
+ data[1] = init_s5k83a[i][3];
+ err = s5k83a_write_sensor(sd,
+ init_s5k83a[i][1], data, 2);
+ break;
+ default:
+ info("Invalid stream command, exiting init");
+ return -EINVAL;
+ }
+ }
+
+ if (dump_sensor)
+ s5k83a_dump_registers(sd);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_power_down(struct sd *sd)
+{
+ return 0;
+}
+
+void s5k83a_dump_registers(struct sd *sd)
+{
+ int address;
+ u8 page, old_page;
+ s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+
+ for (page = 0; page < 16; page++) {
+ s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ info("Dumping the s5k83a register state for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 val = 0;
+ s5k83a_read_sensor(sd, address, &val, 1);
+ info("register 0x%x contains 0x%x",
+ address, val);
+ }
+ }
+ info("s5k83a register state dump complete");
+
+ for (page = 0; page < 16; page++) {
+ s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ info("Probing for which registers that are read/write "
+ "for page 0x%x", page);
+ for (address = 0; address <= 0xff; address++) {
+ u8 old_val, ctrl_val, test_val = 0xff;
+
+ s5k83a_read_sensor(sd, address, &old_val, 1);
+ s5k83a_write_sensor(sd, address, &test_val, 1);
+ s5k83a_read_sensor(sd, address, &ctrl_val, 1);
+
+ if (ctrl_val == test_val)
+ info("register 0x%x is writeable", address);
+ else
+ info("register 0x%x is read only", address);
+
+ /* Restore original val */
+ s5k83a_write_sensor(sd, address, &old_val, 1);
+ }
+ }
+ info("Read/write register probing complete");
+ s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+}
+
+int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+ data[1] = data[1] << 1;
+ *val = data[1];
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0x00;
+ data[1] = 0x20;
+ err = s5k83a_write_sensor(sd, 0x14, data, 2);
+ if (err < 0)
+ return err;
+
+ data[0] = 0x01;
+ data[1] = 0x00;
+ err = s5k83a_write_sensor(sd, 0x0d, data, 2);
+ if (err < 0)
+ return err;
+
+ /* FIXME: This is not sane, we need to figure out the composition
+ of these registers */
+ data[0] = val >> 3; /* brightness, high 5 bits */
+ data[1] = val >> 1; /* brightness, high 7 bits */
+ err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
+
+ *val = data;
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[1];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = val;
+ err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2);
+
+ data[1] = data[1] & 0x3f;
+ if (data[1] > S5K83A_MAXIMUM_GAIN)
+ data[1] = S5K83A_MAXIMUM_GAIN;
+
+ *val = data[1];
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[2];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0;
+ data[1] = val;
+ err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[1];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0x05;
+ err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ *val = (data[0] | 0x40) ? 1 : 0;
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[1];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0x05;
+ err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ if (err < 0)
+ return err;
+
+ /* set or zero six bit, seven is hflip */
+ data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
+ : (data[0] & 0x80) | S5K83A_FLIP_MASK;
+ err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+ if (err < 0)
+ return err;
+
+ data[0] = (val) ? 0x0b : 0x0a;
+ err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ int err;
+ u8 data[1];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0x05;
+ err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ *val = (data[0] | 0x80) ? 1 : 0;
+
+ return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ u8 data[1];
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ data[0] = 0x05;
+ err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ if (err < 0)
+ return err;
+
+ err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ if (err < 0)
+ return err;
+
+ /* set or zero seven bit, six is vflip */
+ data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
+ : (data[0] & 0x40) | S5K83A_FLIP_MASK;
+ err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+ if (err < 0)
+ return err;
+
+ data[0] = (val) ? 0x0a : 0x0b;
+ err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
+
+ return (err < 0) ? err : 0;
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
new file mode 100644
index 00000000000..ee3ee9cfca1
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -0,0 +1,482 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_S5K83A_H_
+#define M5602_S5K83A_H_
+
+#include "m5602_sensor.h"
+
+#define S5K83A_FLIP 0x01
+#define S5K83A_HFLIP_TUNE 0x03
+#define S5K83A_VFLIP_TUNE 0x05
+#define S5K83A_WHITENESS 0x0a
+#define S5K83A_GAIN 0x18
+#define S5K83A_BRIGHTNESS 0x1b
+#define S5K83A_PAGE_MAP 0xec
+
+#define S5K83A_DEFAULT_BRIGHTNESS 0x71
+#define S5K83A_DEFAULT_WHITENESS 0x7e
+#define S5K83A_DEFAULT_GAIN 0x00
+#define S5K83A_MAXIMUM_GAIN 0x3c
+#define S5K83A_FLIP_MASK 0x10
+
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int s5k83a_probe(struct sd *sd);
+int s5k83a_init(struct sd *sd);
+int s5k83a_power_down(struct sd *sd);
+
+void s5k83a_dump_registers(struct sd *sd);
+
+int s5k83a_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+int s5k83a_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+
+
+static struct m5602_sensor s5k83a = {
+ .name = "S5K83A",
+ .probe = s5k83a_probe,
+ .init = s5k83a_init,
+ .power_down = s5k83a_power_down,
+ .read_sensor = s5k83a_read_sensor,
+ .write_sensor = s5k83a_write_sensor,
+ .i2c_slave_id = 0x5a,
+ .nctrls = 5,
+ .ctrls = {
+ {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "brightness",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = S5K83A_DEFAULT_BRIGHTNESS,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = s5k83a_set_brightness,
+ .get = s5k83a_get_brightness
+
+ }, {
+ {
+ .id = V4L2_CID_WHITENESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "whiteness",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = S5K83A_DEFAULT_WHITENESS,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = s5k83a_set_whiteness,
+ .get = s5k83a_get_whiteness,
+ }, {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "gain",
+ .minimum = 0x00,
+ .maximum = S5K83A_MAXIMUM_GAIN,
+ .step = 0x01,
+ .default_value = S5K83A_DEFAULT_GAIN,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .set = s5k83a_set_gain,
+ .get = s5k83a_get_gain
+ }, {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = s5k83a_set_hflip,
+ .get = s5k83a_get_hflip
+ }, {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0
+ },
+ .set = s5k83a_set_vflip,
+ .get = s5k83a_get_vflip
+ }
+ },
+ .nmodes = 1,
+ .modes = {
+ {
+ M5602_DEFAULT_FRAME_WIDTH,
+ M5602_DEFAULT_FRAME_HEIGHT,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+ .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ }
+ }
+};
+
+static const unsigned char preinit_s5k83a[][4] =
+{
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}
+};
+
+/* This could probably be considerably shortened.
+ I don't have the hardware to experiment with it, patches welcome
+*/
+static const unsigned char init_s5k83a[][4] =
+{
+ {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+ {SENSOR, 0xaf, 0x01, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, 0x7b, 0xff, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x01, 0x50, 0x00},
+ {SENSOR, 0x12, 0x20, 0x00},
+ {SENSOR, 0x17, 0x40, 0x00},
+ {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+ {SENSOR, 0x1c, 0x00, 0x00},
+ {SENSOR, 0x02, 0x70, 0x00},
+ {SENSOR, 0x03, 0x0b, 0x00},
+ {SENSOR, 0x04, 0xf0, 0x00},
+ {SENSOR, 0x05, 0x0b, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x06, 0x71, 0x00},
+ {SENSOR, 0x07, 0xe8, 0x00},
+ {SENSOR, 0x08, 0x02, 0x00},
+ {SENSOR, 0x09, 0x88, 0x00},
+ {SENSOR, 0x14, 0x00, 0x00},
+ {SENSOR, 0x15, 0x20, 0x00},
+ {SENSOR, 0x19, 0x00, 0x00},
+ {SENSOR, 0x1a, 0x98, 0x00},
+ {SENSOR, 0x0f, 0x02, 0x00},
+ {SENSOR, 0x10, 0xe5, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR_LONG, 0x14, 0x00, 0x20},
+ {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+ {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+ {SENSOR, 0xaf, 0x01, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ /* ff ( init value )is very dark) || 71 and f0 better */
+ {SENSOR, 0x7b, 0xff, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x01, 0x50, 0x00},
+ {SENSOR, 0x12, 0x20, 0x00},
+ {SENSOR, 0x17, 0x40, 0x00},
+ {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+ {SENSOR, 0x1c, 0x00, 0x00},
+ {SENSOR, 0x02, 0x70, 0x00},
+ /* some values like 0x10 give a blue-purple image */
+ {SENSOR, 0x03, 0x0b, 0x00},
+ {SENSOR, 0x04, 0xf0, 0x00},
+ {SENSOR, 0x05, 0x0b, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ /* under 80 don't work, highter depend on value */
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x06, 0x71, 0x00},
+ {SENSOR, 0x07, 0xe8, 0x00},
+ {SENSOR, 0x08, 0x02, 0x00},
+ {SENSOR, 0x09, 0x88, 0x00},
+ {SENSOR, 0x14, 0x00, 0x00},
+ {SENSOR, 0x15, 0x20, 0x00},
+ {SENSOR, 0x19, 0x00, 0x00},
+ {SENSOR, 0x1a, 0x98, 0x00},
+ {SENSOR, 0x0f, 0x02, 0x00},
+ {SENSOR, 0x10, 0xe5, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR_LONG, 0x14, 0x00, 0x20},
+ {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+ {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+ /* The following sequence is useless after a clean boot
+ but is necessary after resume from suspend */
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+ {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+ {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+ {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+ {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+ {SENSOR, 0xaf, 0x01, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
+ {SENSOR, 0x7b, 0xff, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x01, 0x50, 0x00},
+ {SENSOR, 0x12, 0x20, 0x00},
+ {SENSOR, 0x17, 0x40, 0x00},
+ {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+ {SENSOR, 0x1c, 0x00, 0x00},
+ {SENSOR, 0x02, 0x70, 0x00},
+ {SENSOR, 0x03, 0x0b, 0x00},
+ {SENSOR, 0x04, 0xf0, 0x00},
+ {SENSOR, 0x05, 0x0b, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+ {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+ {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+ {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+ {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, 0x06, 0x71, 0x00},
+ {SENSOR, 0x07, 0xe8, 0x00},
+ {SENSOR, 0x08, 0x02, 0x00},
+ {SENSOR, 0x09, 0x88, 0x00},
+ {SENSOR, 0x14, 0x00, 0x00},
+ {SENSOR, 0x15, 0x20, 0x00},
+ {SENSOR, 0x19, 0x00, 0x00},
+ {SENSOR, 0x1a, 0x98, 0x00},
+ {SENSOR, 0x0f, 0x02, 0x00},
+
+ {SENSOR, 0x10, 0xe5, 0x00},
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR_LONG, 0x14, 0x00, 0x20},
+ {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+ {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+ /* normal colors
+ (this is value after boot, but after tries can be different) */
+ {SENSOR, 0x00, 0x06, 0x00},
+
+ /* set default brightness */
+ {SENSOR_LONG, 0x14, 0x00, 0x20},
+ {SENSOR_LONG, 0x0d, 0x01, 0x00},
+ {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3,
+ S5K83A_DEFAULT_BRIGHTNESS >> 1},
+
+ /* set default whiteness */
+ {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00},
+
+ /* set default gain */
+ {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN},
+
+ /* set default flip */
+ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+ {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00},
+ {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00},
+ {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00}
+
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
new file mode 100644
index 00000000000..60c9a48e0c0
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_sensor.h
@@ -0,0 +1,76 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * 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, version 2.
+ *
+ */
+
+#ifndef M5602_SENSOR_H_
+#define M5602_SENSOR_H_
+
+#include "m5602_bridge.h"
+
+#define M5602_DEFAULT_FRAME_WIDTH 640
+#define M5602_DEFAULT_FRAME_HEIGHT 480
+
+#define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
+
+/* Enumerates all supported sensors */
+enum sensors {
+ OV9650_SENSOR = 1,
+ S5K83A_SENSOR = 2,
+ S5K4AA_SENSOR = 3,
+ MT9M111_SENSOR = 4,
+ PO1030_SENSOR = 5
+};
+
+/* Enumerates all possible instruction types */
+enum instruction {
+ BRIDGE,
+ SENSOR,
+ SENSOR_LONG
+};
+
+struct m5602_sensor {
+ /* Defines the name of a sensor */
+ char name[32];
+
+ /* What i2c address the sensor is connected to */
+ u8 i2c_slave_id;
+
+ /* Probes if the sensor is connected */
+ int (*probe)(struct sd *sd);
+
+ /* Performs a initialization sequence */
+ int (*init)(struct sd *sd);
+
+ /* Performs a power down sequence */
+ int (*power_down)(struct sd *sd);
+
+ /* Reads a sensor register */
+ int (*read_sensor)(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+ /* Writes to a sensor register */
+ int (*write_sensor)(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+ int nctrls;
+ struct ctrl ctrls[M5602_MAX_CTRLS];
+
+ char nmodes;
+ struct v4l2_pix_format modes[];
+};
+
+#endif
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 21c4ee56a10..277ca34a881 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -100,22 +100,6 @@ static int reg_w(struct gspca_dev *gspca_dev,
return rc;
}
-static int reg_w_buf(struct gspca_dev *gspca_dev,
- __u16 index, __u8 *buf, int len)
-{
- int rc;
-
- rc = usb_control_msg(gspca_dev->dev,
- usb_sndbulkpipe(gspca_dev->dev, 4),
- 0x12,
- 0xc8, /* ?? */
- 0, /* value */
- index, buf, len, 500);
- if (rc < 0)
- PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
- return rc;
-}
-
static void bulk_w(struct gspca_dev *gspca_dev,
__u16 *pch,
__u16 Address)
@@ -144,13 +128,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
int err_code;
__u8 *data;
@@ -159,9 +143,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
int intpipe;
PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
- if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) {
+ err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8);
+ if (err_code < 0) {
PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
- return;
+ return err_code;
}
data = gspca_dev->usb_buf;
@@ -170,12 +155,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
err_code = reg_w(gspca_dev, data[0], 2);
if (err_code < 0)
- return;
+ return err_code;
/*
Initialize the MR97113 chip register
*/
- data = kmalloc(16, GFP_KERNEL);
data[0] = 0x00; /* address */
data[1] = 0x0c | 0x01; /* reg 0 */
data[2] = 0x01; /* reg 1 */
@@ -195,18 +179,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
data[10] = 0x5d; /* reg 9, I2C device address
* [for PAS5101 (0x40)] [for MI (0x5d)] */
- err_code = reg_w_buf(gspca_dev, data[0], data, 11);
- kfree(data);
+ err_code = reg_w(gspca_dev, data[0], 11);
if (err_code < 0)
- return;
+ return err_code;
- data = gspca_dev->usb_buf;
data[0] = 0x23; /* address */
data[1] = 0x09; /* reg 35, append frame header */
err_code = reg_w(gspca_dev, data[0], 2);
if (err_code < 0)
- return;
+ return err_code;
data[0] = 0x3c; /* address */
/* if (gspca_dev->width == 1280) */
@@ -217,7 +199,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
* (unit: 4KB) 200KB */
err_code = reg_w(gspca_dev, data[0], 2);
if (err_code < 0)
- return;
+ return err_code;
if (0) { /* fixed dark-gain */
data[1] = 0; /* reg 94, Y Gain (1.75) */
@@ -259,13 +241,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
err_code = reg_w(gspca_dev, data[0], 6);
if (err_code < 0)
- return;
+ return err_code;
data[0] = 0x67;
data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
err_code = reg_w(gspca_dev, data[0], 2);
if (err_code < 0)
- return;
+ return err_code;
/*
* initialize the value of MI sensor...
@@ -345,6 +327,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
data[0] = 0x00;
data[1] = 0x4d; /* ISOC transfering enable... */
reg_w(gspca_dev, data[0], 2);
+ return err_code;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -358,14 +341,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
PDEBUG(D_ERR, "Camera Stop failed");
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -411,11 +386,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -439,6 +412,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index b4f00ec0885..ca671194679 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -63,11 +63,10 @@ struct sd {
#define SEN_OV6630 2
#define SEN_OV7610 3
#define SEN_OV7620 4
-#define SEN_OV7630 5
-#define SEN_OV7640 6
-#define SEN_OV7670 7
-#define SEN_OV76BE 8
-#define SEN_OV8610 9
+#define SEN_OV7640 5
+#define SEN_OV7670 6
+#define SEN_OV76BE 7
+#define SEN_OV8610 8
};
@@ -127,6 +126,7 @@ static struct ctrl sd_ctrls[] = {
.get = sd_getcolors,
},
/* next controls work with ov7670 only */
+#define HFLIP_IDX 3
{
{
.id = V4L2_CID_HFLIP,
@@ -141,6 +141,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_sethflip,
.get = sd_gethflip,
},
+#define VFLIP_IDX 4
{
{
.id = V4L2_CID_VFLIP,
@@ -293,6 +294,541 @@ static struct v4l2_pix_format sif_mode[] = {
#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
+struct ov_regvals {
+ __u8 reg;
+ __u8 val;
+};
+struct ov_i2c_regvals {
+ __u8 reg;
+ __u8 val;
+};
+
+static const struct ov_i2c_regvals norm_6x20[] = {
+ { 0x12, 0x80 }, /* reset */
+ { 0x11, 0x01 },
+ { 0x03, 0x60 },
+ { 0x05, 0x7f }, /* For when autoadjust is off */
+ { 0x07, 0xa8 },
+ /* The ratio of 0x0c and 0x0d controls the white point */
+ { 0x0c, 0x24 },
+ { 0x0d, 0x24 },
+ { 0x0f, 0x15 }, /* COMS */
+ { 0x10, 0x75 }, /* AEC Exposure time */
+ { 0x12, 0x24 }, /* Enable AGC */
+ { 0x14, 0x04 },
+ /* 0x16: 0x06 helps frame stability with moving objects */
+ { 0x16, 0x06 },
+/* { 0x20, 0x30 }, * Aperture correction enable */
+ { 0x26, 0xb2 }, /* BLC enable */
+ /* 0x28: 0x05 Selects RGB format if RGB on */
+ { 0x28, 0x05 },
+ { 0x2a, 0x04 }, /* Disable framerate adjust */
+/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
+ { 0x2d, 0x99 },
+ { 0x33, 0xa0 }, /* Color Processing Parameter */
+ { 0x34, 0xd2 }, /* Max A/D range */
+ { 0x38, 0x8b },
+ { 0x39, 0x40 },
+
+ { 0x3c, 0x39 }, /* Enable AEC mode changing */
+ { 0x3c, 0x3c }, /* Change AEC mode */
+ { 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+ { 0x3d, 0x80 },
+ /* These next two registers (0x4a, 0x4b) are undocumented.
+ * They control the color balance */
+ { 0x4a, 0x80 },
+ { 0x4b, 0x80 },
+ { 0x4d, 0xd2 }, /* This reduces noise a bit */
+ { 0x4e, 0xc1 },
+ { 0x4f, 0x04 },
+/* Do 50-53 have any effect? */
+/* Toggle 0x12[2] off and on here? */
+};
+
+static const struct ov_i2c_regvals norm_6x30[] = {
+ { 0x12, 0x80 }, /* Reset */
+ { 0x00, 0x1f }, /* Gain */
+ { 0x01, 0x99 }, /* Blue gain */
+ { 0x02, 0x7c }, /* Red gain */
+ { 0x03, 0xc0 }, /* Saturation */
+ { 0x05, 0x0a }, /* Contrast */
+ { 0x06, 0x95 }, /* Brightness */
+ { 0x07, 0x2d }, /* Sharpness */
+ { 0x0c, 0x20 },
+ { 0x0d, 0x20 },
+ { 0x0e, 0x20 },
+ { 0x0f, 0x05 },
+ { 0x10, 0x9a },
+ { 0x11, 0x00 }, /* Pixel clock = fastest */
+ { 0x12, 0x24 }, /* Enable AGC and AWB */
+ { 0x13, 0x21 },
+ { 0x14, 0x80 },
+ { 0x15, 0x01 },
+ { 0x16, 0x03 },
+ { 0x17, 0x38 },
+ { 0x18, 0xea },
+ { 0x19, 0x04 },
+ { 0x1a, 0x93 },
+ { 0x1b, 0x00 },
+ { 0x1e, 0xc4 },
+ { 0x1f, 0x04 },
+ { 0x20, 0x20 },
+ { 0x21, 0x10 },
+ { 0x22, 0x88 },
+ { 0x23, 0xc0 }, /* Crystal circuit power level */
+ { 0x25, 0x9a }, /* Increase AEC black ratio */
+ { 0x26, 0xb2 }, /* BLC enable */
+ { 0x27, 0xa2 },
+ { 0x28, 0x00 },
+ { 0x29, 0x00 },
+ { 0x2a, 0x84 }, /* 60 Hz power */
+ { 0x2b, 0xa8 }, /* 60 Hz power */
+ { 0x2c, 0xa0 },
+ { 0x2d, 0x95 }, /* Enable auto-brightness */
+ { 0x2e, 0x88 },
+ { 0x33, 0x26 },
+ { 0x34, 0x03 },
+ { 0x36, 0x8f },
+ { 0x37, 0x80 },
+ { 0x38, 0x83 },
+ { 0x39, 0x80 },
+ { 0x3a, 0x0f },
+ { 0x3b, 0x3c },
+ { 0x3c, 0x1a },
+ { 0x3d, 0x80 },
+ { 0x3e, 0x80 },
+ { 0x3f, 0x0e },
+ { 0x40, 0x00 }, /* White bal */
+ { 0x41, 0x00 }, /* White bal */
+ { 0x42, 0x80 },
+ { 0x43, 0x3f }, /* White bal */
+ { 0x44, 0x80 },
+ { 0x45, 0x20 },
+ { 0x46, 0x20 },
+ { 0x47, 0x80 },
+ { 0x48, 0x7f },
+ { 0x49, 0x00 },
+ { 0x4a, 0x00 },
+ { 0x4b, 0x80 },
+ { 0x4c, 0xd0 },
+ { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
+ { 0x4e, 0x40 },
+ { 0x4f, 0x07 }, /* UV avg., col. killer: max */
+ { 0x50, 0xff },
+ { 0x54, 0x23 }, /* Max AGC gain: 18dB */
+ { 0x55, 0xff },
+ { 0x56, 0x12 },
+ { 0x57, 0x81 },
+ { 0x58, 0x75 },
+ { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
+ { 0x5a, 0x2c },
+ { 0x5b, 0x0f }, /* AWB chrominance levels */
+ { 0x5c, 0x10 },
+ { 0x3d, 0x80 },
+ { 0x27, 0xa6 },
+ { 0x12, 0x20 }, /* Toggle AWB */
+ { 0x12, 0x24 },
+};
+
+/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+ *
+ * Register 0x0f in the 7610 has the following effects:
+ *
+ * 0x85 (AEC method 1): Best overall, good contrast range
+ * 0x45 (AEC method 2): Very overexposed
+ * 0xa5 (spec sheet default): Ok, but the black level is
+ * shifted resulting in loss of contrast
+ * 0x05 (old driver setting): very overexposed, too much
+ * contrast
+ */
+static const struct ov_i2c_regvals norm_7610[] = {
+ { 0x10, 0xff },
+ { 0x16, 0x06 },
+ { 0x28, 0x24 },
+ { 0x2b, 0xac },
+ { 0x12, 0x00 },
+ { 0x38, 0x81 },
+ { 0x28, 0x24 }, /* 0c */
+ { 0x0f, 0x85 }, /* lg's setting */
+ { 0x15, 0x01 },
+ { 0x20, 0x1c },
+ { 0x23, 0x2a },
+ { 0x24, 0x10 },
+ { 0x25, 0x8a },
+ { 0x26, 0xa2 },
+ { 0x27, 0xc2 },
+ { 0x2a, 0x04 },
+ { 0x2c, 0xfe },
+ { 0x2d, 0x93 },
+ { 0x30, 0x71 },
+ { 0x31, 0x60 },
+ { 0x32, 0x26 },
+ { 0x33, 0x20 },
+ { 0x34, 0x48 },
+ { 0x12, 0x24 },
+ { 0x11, 0x01 },
+ { 0x0c, 0x24 },
+ { 0x0d, 0x24 },
+};
+
+static const struct ov_i2c_regvals norm_7620[] = {
+ { 0x00, 0x00 }, /* gain */
+ { 0x01, 0x80 }, /* blue gain */
+ { 0x02, 0x80 }, /* red gain */
+ { 0x03, 0xc0 }, /* OV7670_REG_VREF */
+ { 0x06, 0x60 },
+ { 0x07, 0x00 },
+ { 0x0c, 0x24 },
+ { 0x0c, 0x24 },
+ { 0x0d, 0x24 },
+ { 0x11, 0x01 },
+ { 0x12, 0x24 },
+ { 0x13, 0x01 },
+ { 0x14, 0x84 },
+ { 0x15, 0x01 },
+ { 0x16, 0x03 },
+ { 0x17, 0x2f },
+ { 0x18, 0xcf },
+ { 0x19, 0x06 },
+ { 0x1a, 0xf5 },
+ { 0x1b, 0x00 },
+ { 0x20, 0x18 },
+ { 0x21, 0x80 },
+ { 0x22, 0x80 },
+ { 0x23, 0x00 },
+ { 0x26, 0xa2 },
+ { 0x27, 0xea },
+ { 0x28, 0x20 },
+ { 0x29, 0x00 },
+ { 0x2a, 0x10 },
+ { 0x2b, 0x00 },
+ { 0x2c, 0x88 },
+ { 0x2d, 0x91 },
+ { 0x2e, 0x80 },
+ { 0x2f, 0x44 },
+ { 0x60, 0x27 },
+ { 0x61, 0x02 },
+ { 0x62, 0x5f },
+ { 0x63, 0xd5 },
+ { 0x64, 0x57 },
+ { 0x65, 0x83 },
+ { 0x66, 0x55 },
+ { 0x67, 0x92 },
+ { 0x68, 0xcf },
+ { 0x69, 0x76 },
+ { 0x6a, 0x22 },
+ { 0x6b, 0x00 },
+ { 0x6c, 0x02 },
+ { 0x6d, 0x44 },
+ { 0x6e, 0x80 },
+ { 0x6f, 0x1d },
+ { 0x70, 0x8b },
+ { 0x71, 0x00 },
+ { 0x72, 0x14 },
+ { 0x73, 0x54 },
+ { 0x74, 0x00 },
+ { 0x75, 0x8e },
+ { 0x76, 0x00 },
+ { 0x77, 0xff },
+ { 0x78, 0x80 },
+ { 0x79, 0x80 },
+ { 0x7a, 0x80 },
+ { 0x7b, 0xe2 },
+ { 0x7c, 0x00 },
+};
+
+/* 7640 and 7648. The defaults should be OK for most registers. */
+static const struct ov_i2c_regvals norm_7640[] = {
+ { 0x12, 0x80 },
+ { 0x12, 0x14 },
+};
+
+/* 7670. Defaults taken from OmniVision provided data,
+* as provided by Jonathan Corbet of OLPC */
+static const struct ov_i2c_regvals norm_7670[] = {
+ { OV7670_REG_COM7, OV7670_COM7_RESET },
+ { OV7670_REG_TSLB, 0x04 }, /* OV */
+ { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
+ { OV7670_REG_CLKRC, 0x01 },
+/*
+ * Set the hardware window. These values from OV don't entirely
+ * make sense - hstop is less than hstart. But they work...
+ */
+ { OV7670_REG_HSTART, 0x13 },
+ { OV7670_REG_HSTOP, 0x01 },
+ { OV7670_REG_HREF, 0xb6 },
+ { OV7670_REG_VSTART, 0x02 },
+ { OV7670_REG_VSTOP, 0x7a },
+ { OV7670_REG_VREF, 0x0a },
+
+ { OV7670_REG_COM3, 0 },
+ { OV7670_REG_COM14, 0 },
+/* Mystery scaling numbers */
+ { 0x70, 0x3a },
+ { 0x71, 0x35 },
+ { 0x72, 0x11 },
+ { 0x73, 0xf0 },
+ { 0xa2, 0x02 },
+/* { OV7670_REG_COM10, 0x0 }, */
+
+/* Gamma curve values */
+ { 0x7a, 0x20 },
+ { 0x7b, 0x10 },
+ { 0x7c, 0x1e },
+ { 0x7d, 0x35 },
+ { 0x7e, 0x5a },
+ { 0x7f, 0x69 },
+ { 0x80, 0x76 },
+ { 0x81, 0x80 },
+ { 0x82, 0x88 },
+ { 0x83, 0x8f },
+ { 0x84, 0x96 },
+ { 0x85, 0xa3 },
+ { 0x86, 0xaf },
+ { 0x87, 0xc4 },
+ { 0x88, 0xd7 },
+ { 0x89, 0xe8 },
+
+/* AGC and AEC parameters. Note we start by disabling those features,
+ then turn them only after tweaking the values. */
+ { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+ | OV7670_COM8_AECSTEP
+ | OV7670_COM8_BFILT },
+ { OV7670_REG_GAIN, 0 },
+ { OV7670_REG_AECH, 0 },
+ { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
+ { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+ { OV7670_REG_BD50MAX, 0x05 },
+ { OV7670_REG_BD60MAX, 0x07 },
+ { OV7670_REG_AEW, 0x95 },
+ { OV7670_REG_AEB, 0x33 },
+ { OV7670_REG_VPT, 0xe3 },
+ { OV7670_REG_HAECC1, 0x78 },
+ { OV7670_REG_HAECC2, 0x68 },
+ { 0xa1, 0x03 }, /* magic */
+ { OV7670_REG_HAECC3, 0xd8 },
+ { OV7670_REG_HAECC4, 0xd8 },
+ { OV7670_REG_HAECC5, 0xf0 },
+ { OV7670_REG_HAECC6, 0x90 },
+ { OV7670_REG_HAECC7, 0x94 },
+ { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+ | OV7670_COM8_AECSTEP
+ | OV7670_COM8_BFILT
+ | OV7670_COM8_AGC
+ | OV7670_COM8_AEC },
+
+/* Almost all of these are magic "reserved" values. */
+ { OV7670_REG_COM5, 0x61 },
+ { OV7670_REG_COM6, 0x4b },
+ { 0x16, 0x02 },
+ { OV7670_REG_MVFP, 0x07 },
+ { 0x21, 0x02 },
+ { 0x22, 0x91 },
+ { 0x29, 0x07 },
+ { 0x33, 0x0b },
+ { 0x35, 0x0b },
+ { 0x37, 0x1d },
+ { 0x38, 0x71 },
+ { 0x39, 0x2a },
+ { OV7670_REG_COM12, 0x78 },
+ { 0x4d, 0x40 },
+ { 0x4e, 0x20 },
+ { OV7670_REG_GFIX, 0 },
+ { 0x6b, 0x4a },
+ { 0x74, 0x10 },
+ { 0x8d, 0x4f },
+ { 0x8e, 0 },
+ { 0x8f, 0 },
+ { 0x90, 0 },
+ { 0x91, 0 },
+ { 0x96, 0 },
+ { 0x9a, 0 },
+ { 0xb0, 0x84 },
+ { 0xb1, 0x0c },
+ { 0xb2, 0x0e },
+ { 0xb3, 0x82 },
+ { 0xb8, 0x0a },
+
+/* More reserved magic, some of which tweaks white balance */
+ { 0x43, 0x0a },
+ { 0x44, 0xf0 },
+ { 0x45, 0x34 },
+ { 0x46, 0x58 },
+ { 0x47, 0x28 },
+ { 0x48, 0x3a },
+ { 0x59, 0x88 },
+ { 0x5a, 0x88 },
+ { 0x5b, 0x44 },
+ { 0x5c, 0x67 },
+ { 0x5d, 0x49 },
+ { 0x5e, 0x0e },
+ { 0x6c, 0x0a },
+ { 0x6d, 0x55 },
+ { 0x6e, 0x11 },
+ { 0x6f, 0x9f },
+ /* "9e for advance AWB" */
+ { 0x6a, 0x40 },
+ { OV7670_REG_BLUE, 0x40 },
+ { OV7670_REG_RED, 0x60 },
+ { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+ | OV7670_COM8_AECSTEP
+ | OV7670_COM8_BFILT
+ | OV7670_COM8_AGC
+ | OV7670_COM8_AEC
+ | OV7670_COM8_AWB },
+
+/* Matrix coefficients */
+ { 0x4f, 0x80 },
+ { 0x50, 0x80 },
+ { 0x51, 0 },
+ { 0x52, 0x22 },
+ { 0x53, 0x5e },
+ { 0x54, 0x80 },
+ { 0x58, 0x9e },
+
+ { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
+ { OV7670_REG_EDGE, 0 },
+ { 0x75, 0x05 },
+ { 0x76, 0xe1 },
+ { 0x4c, 0 },
+ { 0x77, 0x01 },
+ { OV7670_REG_COM13, OV7670_COM13_GAMMA
+ | OV7670_COM13_UVSAT
+ | 2}, /* was 3 */
+ { 0x4b, 0x09 },
+ { 0xc9, 0x60 },
+ { OV7670_REG_COM16, 0x38 },
+ { 0x56, 0x40 },
+
+ { 0x34, 0x11 },
+ { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
+ { 0xa4, 0x88 },
+ { 0x96, 0 },
+ { 0x97, 0x30 },
+ { 0x98, 0x20 },
+ { 0x99, 0x30 },
+ { 0x9a, 0x84 },
+ { 0x9b, 0x29 },
+ { 0x9c, 0x03 },
+ { 0x9d, 0x4c },
+ { 0x9e, 0x3f },
+ { 0x78, 0x04 },
+
+/* Extra-weird stuff. Some sort of multiplexor register */
+ { 0x79, 0x01 },
+ { 0xc8, 0xf0 },
+ { 0x79, 0x0f },
+ { 0xc8, 0x00 },
+ { 0x79, 0x10 },
+ { 0xc8, 0x7e },
+ { 0x79, 0x0a },
+ { 0xc8, 0x80 },
+ { 0x79, 0x0b },
+ { 0xc8, 0x01 },
+ { 0x79, 0x0c },
+ { 0xc8, 0x0f },
+ { 0x79, 0x0d },
+ { 0xc8, 0x20 },
+ { 0x79, 0x09 },
+ { 0xc8, 0x80 },
+ { 0x79, 0x02 },
+ { 0xc8, 0xc0 },
+ { 0x79, 0x03 },
+ { 0xc8, 0x40 },
+ { 0x79, 0x05 },
+ { 0xc8, 0x30 },
+ { 0x79, 0x26 },
+};
+
+static const struct ov_i2c_regvals norm_8610[] = {
+ { 0x12, 0x80 },
+ { 0x00, 0x00 },
+ { 0x01, 0x80 },
+ { 0x02, 0x80 },
+ { 0x03, 0xc0 },
+ { 0x04, 0x30 },
+ { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
+ { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
+ { 0x0a, 0x86 },
+ { 0x0b, 0xb0 },
+ { 0x0c, 0x20 },
+ { 0x0d, 0x20 },
+ { 0x11, 0x01 },
+ { 0x12, 0x25 },
+ { 0x13, 0x01 },
+ { 0x14, 0x04 },
+ { 0x15, 0x01 }, /* Lin and Win think different about UV order */
+ { 0x16, 0x03 },
+ { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
+ { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
+ { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
+ { 0x1a, 0xf5 },
+ { 0x1b, 0x00 },
+ { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
+ { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
+ { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
+ { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
+ { 0x26, 0xa2 },
+ { 0x27, 0xea },
+ { 0x28, 0x00 },
+ { 0x29, 0x00 },
+ { 0x2a, 0x80 },
+ { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
+ { 0x2c, 0xac },
+ { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
+ { 0x2e, 0x80 },
+ { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
+ { 0x4c, 0x00 },
+ { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
+ { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
+ { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
+ { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
+ { 0x63, 0xff },
+ { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
+ * maybe thats wrong */
+ { 0x65, 0x00 },
+ { 0x66, 0x55 },
+ { 0x67, 0xb0 },
+ { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
+ { 0x69, 0x02 },
+ { 0x6a, 0x22 },
+ { 0x6b, 0x00 },
+ { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
+ * deleting bit7 colors the first images red */
+ { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
+ { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
+ { 0x6f, 0x01 },
+ { 0x70, 0x8b },
+ { 0x71, 0x00 },
+ { 0x72, 0x14 },
+ { 0x73, 0x54 },
+ { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
+ { 0x75, 0x0e },
+ { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
+ { 0x77, 0xff },
+ { 0x78, 0x80 },
+ { 0x79, 0x80 },
+ { 0x7a, 0x80 },
+ { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
+ { 0x7c, 0x00 },
+ { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
+ { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
+ { 0x7f, 0xfb },
+ { 0x80, 0x28 },
+ { 0x81, 0x00 },
+ { 0x82, 0x23 },
+ { 0x83, 0x0b },
+ { 0x84, 0x00 },
+ { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
+ { 0x86, 0xc9 },
+ { 0x87, 0x00 },
+ { 0x88, 0x00 },
+ { 0x89, 0x01 },
+ { 0x12, 0x20 },
+ { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
+};
+
static unsigned char ov7670_abs_to_sm(unsigned char v)
{
if (v > 127)
@@ -537,18 +1073,10 @@ static int ov51x_set_slave_ids(struct sd *sd,
rc = reg_w(sd, R51x_I2C_W_SID, slave);
if (rc < 0)
return rc;
+ sd->primary_i2c_slave = slave;
return reg_w(sd, R51x_I2C_R_SID, slave + 1);
}
-struct ov_regvals {
- __u8 reg;
- __u8 val;
-};
-struct ov_i2c_regvals {
- __u8 reg;
- __u8 val;
-};
-
static int write_regvals(struct sd *sd,
const struct ov_regvals *regvals,
int n)
@@ -591,101 +1119,9 @@ static int write_i2c_regvals(struct sd *sd,
static int ov8xx0_configure(struct sd *sd)
{
int rc;
- static const struct ov_i2c_regvals norm_8610[] = {
- { 0x12, 0x80 },
- { 0x00, 0x00 },
- { 0x01, 0x80 },
- { 0x02, 0x80 },
- { 0x03, 0xc0 },
- { 0x04, 0x30 },
- { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
- { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
- { 0x0a, 0x86 },
- { 0x0b, 0xb0 },
- { 0x0c, 0x20 },
- { 0x0d, 0x20 },
- { 0x11, 0x01 },
- { 0x12, 0x25 },
- { 0x13, 0x01 },
- { 0x14, 0x04 },
- { 0x15, 0x01 }, /* Lin and Win think different about UV order */
- { 0x16, 0x03 },
- { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
- { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
- { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
- { 0x1a, 0xf5 },
- { 0x1b, 0x00 },
- { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
- { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
- { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
- { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
- { 0x26, 0xa2 },
- { 0x27, 0xea },
- { 0x28, 0x00 },
- { 0x29, 0x00 },
- { 0x2a, 0x80 },
- { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
- { 0x2c, 0xac },
- { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
- { 0x2e, 0x80 },
- { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
- { 0x4c, 0x00 },
- { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
- { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
- { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
- { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
- { 0x63, 0xff },
- { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
- * maybe thats wrong */
- { 0x65, 0x00 },
- { 0x66, 0x55 },
- { 0x67, 0xb0 },
- { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
- { 0x69, 0x02 },
- { 0x6a, 0x22 },
- { 0x6b, 0x00 },
- { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
- deleting bit7 colors the first images red */
- { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
- { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
- { 0x6f, 0x01 },
- { 0x70, 0x8b },
- { 0x71, 0x00 },
- { 0x72, 0x14 },
- { 0x73, 0x54 },
- { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
- { 0x75, 0x0e },
- { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
- { 0x77, 0xff },
- { 0x78, 0x80 },
- { 0x79, 0x80 },
- { 0x7a, 0x80 },
- { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
- { 0x7c, 0x00 },
- { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
- { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
- { 0x7f, 0xfb },
- { 0x80, 0x28 },
- { 0x81, 0x00 },
- { 0x82, 0x23 },
- { 0x83, 0x0b },
- { 0x84, 0x00 },
- { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
- { 0x86, 0xc9 },
- { 0x87, 0x00 },
- { 0x88, 0x00 },
- { 0x89, 0x01 },
- { 0x12, 0x20 },
- { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
- };
PDEBUG(D_PROBE, "starting ov8xx0 configuration");
- if (init_ov_sensor(sd) < 0)
- PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID");
- else
- PDEBUG(D_PROBE, "OV86x0 initialized");
-
/* Detect sensor (sub)type */
rc = i2c_r(sd, OV7610_REG_COM_I);
if (rc < 0) {
@@ -698,9 +1134,6 @@ static int ov8xx0_configure(struct sd *sd)
PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
return -1;
}
- PDEBUG(D_PROBE, "Writing 8610 registers");
- if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
- return -1;
/* Set sensor-specific vars */
/* sd->sif = 0; already done */
@@ -714,252 +1147,6 @@ static int ov7xx0_configure(struct sd *sd)
{
int rc, high, low;
- /* Lawrence Glaister <lg@jfm.bc.ca> reports:
- *
- * Register 0x0f in the 7610 has the following effects:
- *
- * 0x85 (AEC method 1): Best overall, good contrast range
- * 0x45 (AEC method 2): Very overexposed
- * 0xa5 (spec sheet default): Ok, but the black level is
- * shifted resulting in loss of contrast
- * 0x05 (old driver setting): very overexposed, too much
- * contrast
- */
- static const struct ov_i2c_regvals norm_7610[] = {
- { 0x10, 0xff },
- { 0x16, 0x06 },
- { 0x28, 0x24 },
- { 0x2b, 0xac },
- { 0x12, 0x00 },
- { 0x38, 0x81 },
- { 0x28, 0x24 }, /* 0c */
- { 0x0f, 0x85 }, /* lg's setting */
- { 0x15, 0x01 },
- { 0x20, 0x1c },
- { 0x23, 0x2a },
- { 0x24, 0x10 },
- { 0x25, 0x8a },
- { 0x26, 0xa2 },
- { 0x27, 0xc2 },
- { 0x2a, 0x04 },
- { 0x2c, 0xfe },
- { 0x2d, 0x93 },
- { 0x30, 0x71 },
- { 0x31, 0x60 },
- { 0x32, 0x26 },
- { 0x33, 0x20 },
- { 0x34, 0x48 },
- { 0x12, 0x24 },
- { 0x11, 0x01 },
- { 0x0c, 0x24 },
- { 0x0d, 0x24 },
- };
-
- static const struct ov_i2c_regvals norm_7620[] = {
- { 0x00, 0x00 }, /* gain */
- { 0x01, 0x80 }, /* blue gain */
- { 0x02, 0x80 }, /* red gain */
- { 0x03, 0xc0 }, /* OV7670_REG_VREF */
- { 0x06, 0x60 },
- { 0x07, 0x00 },
- { 0x0c, 0x24 },
- { 0x0c, 0x24 },
- { 0x0d, 0x24 },
- { 0x11, 0x01 },
- { 0x12, 0x24 },
- { 0x13, 0x01 },
- { 0x14, 0x84 },
- { 0x15, 0x01 },
- { 0x16, 0x03 },
- { 0x17, 0x2f },
- { 0x18, 0xcf },
- { 0x19, 0x06 },
- { 0x1a, 0xf5 },
- { 0x1b, 0x00 },
- { 0x20, 0x18 },
- { 0x21, 0x80 },
- { 0x22, 0x80 },
- { 0x23, 0x00 },
- { 0x26, 0xa2 },
- { 0x27, 0xea },
- { 0x28, 0x20 },
- { 0x29, 0x00 },
- { 0x2a, 0x10 },
- { 0x2b, 0x00 },
- { 0x2c, 0x88 },
- { 0x2d, 0x91 },
- { 0x2e, 0x80 },
- { 0x2f, 0x44 },
- { 0x60, 0x27 },
- { 0x61, 0x02 },
- { 0x62, 0x5f },
- { 0x63, 0xd5 },
- { 0x64, 0x57 },
- { 0x65, 0x83 },
- { 0x66, 0x55 },
- { 0x67, 0x92 },
- { 0x68, 0xcf },
- { 0x69, 0x76 },
- { 0x6a, 0x22 },
- { 0x6b, 0x00 },
- { 0x6c, 0x02 },
- { 0x6d, 0x44 },
- { 0x6e, 0x80 },
- { 0x6f, 0x1d },
- { 0x70, 0x8b },
- { 0x71, 0x00 },
- { 0x72, 0x14 },
- { 0x73, 0x54 },
- { 0x74, 0x00 },
- { 0x75, 0x8e },
- { 0x76, 0x00 },
- { 0x77, 0xff },
- { 0x78, 0x80 },
- { 0x79, 0x80 },
- { 0x7a, 0x80 },
- { 0x7b, 0xe2 },
- { 0x7c, 0x00 },
- };
-
- /* 7640 and 7648. The defaults should be OK for most registers. */
- static const struct ov_i2c_regvals norm_7640[] = {
- { 0x12, 0x80 },
- { 0x12, 0x14 },
- };
-
- /* 7670. Defaults taken from OmniVision provided data,
- * as provided by Jonathan Corbet of OLPC */
- static const struct ov_i2c_regvals norm_7670[] = {
- { OV7670_REG_COM7, OV7670_COM7_RESET },
- { OV7670_REG_TSLB, 0x04 }, /* OV */
- { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
- { OV7670_REG_CLKRC, 0x01 },
- /*
- * Set the hardware window. These values from OV don't entirely
- * make sense - hstop is less than hstart. But they work...
- */
- { OV7670_REG_HSTART, 0x13 }, { OV7670_REG_HSTOP, 0x01 },
- { OV7670_REG_HREF, 0xb6 }, { OV7670_REG_VSTART, 0x02 },
- { OV7670_REG_VSTOP, 0x7a }, { OV7670_REG_VREF, 0x0a },
-
- { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 },
- /* Mystery scaling numbers */
- { 0x70, 0x3a }, { 0x71, 0x35 },
- { 0x72, 0x11 }, { 0x73, 0xf0 },
- { 0xa2, 0x02 },
-/* { OV7670_REG_COM10, 0x0 }, */
-
- /* Gamma curve values */
- { 0x7a, 0x20 },
- { 0x7b, 0x10 },
- { 0x7c, 0x1e },
- { 0x7d, 0x35 },
- { 0x7e, 0x5a }, { 0x7f, 0x69 },
- { 0x80, 0x76 }, { 0x81, 0x80 },
- { 0x82, 0x88 }, { 0x83, 0x8f },
- { 0x84, 0x96 }, { 0x85, 0xa3 },
- { 0x86, 0xaf }, { 0x87, 0xc4 },
- { 0x88, 0xd7 }, { 0x89, 0xe8 },
-
- /* AGC and AEC parameters. Note we start by disabling those features,
- then turn them only after tweaking the values. */
- { OV7670_REG_COM8, OV7670_COM8_FASTAEC
- | OV7670_COM8_AECSTEP
- | OV7670_COM8_BFILT },
- { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
- { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
- { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
- { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
- { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
- { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
- { OV7670_REG_HAECC2, 0x68 },
- { 0xa1, 0x03 }, /* magic */
- { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
- { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
- { OV7670_REG_HAECC7, 0x94 },
- { OV7670_REG_COM8, OV7670_COM8_FASTAEC
- | OV7670_COM8_AECSTEP
- | OV7670_COM8_BFILT
- | OV7670_COM8_AGC
- | OV7670_COM8_AEC },
-
- /* Almost all of these are magic "reserved" values. */
- { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
- { 0x16, 0x02 },
- { OV7670_REG_MVFP, 0x07 },
- { 0x21, 0x02 }, { 0x22, 0x91 },
- { 0x29, 0x07 }, { 0x33, 0x0b },
- { 0x35, 0x0b }, { 0x37, 0x1d },
- { 0x38, 0x71 }, { 0x39, 0x2a },
- { OV7670_REG_COM12, 0x78 }, { 0x4d, 0x40 },
- { 0x4e, 0x20 }, { OV7670_REG_GFIX, 0 },
- { 0x6b, 0x4a }, { 0x74, 0x10 },
- { 0x8d, 0x4f }, { 0x8e, 0 },
- { 0x8f, 0 }, { 0x90, 0 },
- { 0x91, 0 }, { 0x96, 0 },
- { 0x9a, 0 }, { 0xb0, 0x84 },
- { 0xb1, 0x0c }, { 0xb2, 0x0e },
- { 0xb3, 0x82 }, { 0xb8, 0x0a },
-
- /* More reserved magic, some of which tweaks white balance */
- { 0x43, 0x0a }, { 0x44, 0xf0 },
- { 0x45, 0x34 }, { 0x46, 0x58 },
- { 0x47, 0x28 }, { 0x48, 0x3a },
- { 0x59, 0x88 }, { 0x5a, 0x88 },
- { 0x5b, 0x44 }, { 0x5c, 0x67 },
- { 0x5d, 0x49 }, { 0x5e, 0x0e },
- { 0x6c, 0x0a }, { 0x6d, 0x55 },
- { 0x6e, 0x11 }, { 0x6f, 0x9f },
- /* "9e for advance AWB" */
- { 0x6a, 0x40 }, { OV7670_REG_BLUE, 0x40 },
- { OV7670_REG_RED, 0x60 },
- { OV7670_REG_COM8, OV7670_COM8_FASTAEC
- | OV7670_COM8_AECSTEP
- | OV7670_COM8_BFILT
- | OV7670_COM8_AGC
- | OV7670_COM8_AEC
- | OV7670_COM8_AWB },
-
- /* Matrix coefficients */
- { 0x4f, 0x80 }, { 0x50, 0x80 },
- { 0x51, 0 }, { 0x52, 0x22 },
- { 0x53, 0x5e }, { 0x54, 0x80 },
- { 0x58, 0x9e },
-
- { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
- { OV7670_REG_EDGE, 0 },
- { 0x75, 0x05 }, { 0x76, 0xe1 },
- { 0x4c, 0 }, { 0x77, 0x01 },
- { OV7670_REG_COM13, OV7670_COM13_GAMMA
- | OV7670_COM13_UVSAT
- | 2}, /* was 3 */
- { 0x4b, 0x09 },
- { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
- { 0x56, 0x40 },
-
- { 0x34, 0x11 },
- { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
- { 0xa4, 0x88 }, { 0x96, 0 },
- { 0x97, 0x30 }, { 0x98, 0x20 },
- { 0x99, 0x30 }, { 0x9a, 0x84 },
- { 0x9b, 0x29 }, { 0x9c, 0x03 },
- { 0x9d, 0x4c }, { 0x9e, 0x3f },
- { 0x78, 0x04 },
-
- /* Extra-weird stuff. Some sort of multiplexor register */
- { 0x79, 0x01 }, { 0xc8, 0xf0 },
- { 0x79, 0x0f }, { 0xc8, 0x00 },
- { 0x79, 0x10 }, { 0xc8, 0x7e },
- { 0x79, 0x0a }, { 0xc8, 0x80 },
- { 0x79, 0x0b }, { 0xc8, 0x01 },
- { 0x79, 0x0c }, { 0xc8, 0x0f },
- { 0x79, 0x0d }, { 0xc8, 0x20 },
- { 0x79, 0x09 }, { 0xc8, 0x80 },
- { 0x79, 0x02 }, { 0xc8, 0xc0 },
- { 0x79, 0x03 }, { 0xc8, 0x40 },
- { 0x79, 0x05 }, { 0xc8, 0x30 },
- { 0x79, 0x26 },
- };
PDEBUG(D_PROBE, "starting OV7xx0 configuration");
@@ -1011,8 +1198,9 @@ static int ov7xx0_configure(struct sd *sd)
switch (low) {
case 0x30:
PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
- sd->sensor = SEN_OV7630;
- break;
+ PDEBUG(D_ERR,
+ "7630 is not supported by this driver");
+ return -1;
case 0x40:
PDEBUG(D_PROBE, "Sensor is an OV7645");
sd->sensor = SEN_OV7640; /* FIXME */
@@ -1038,32 +1226,6 @@ static int ov7xx0_configure(struct sd *sd)
return -1;
}
- switch (sd->sensor) {
- case SEN_OV7620:
- PDEBUG(D_PROBE, "Writing 7620 registers");
- if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
- return -1;
- break;
- case SEN_OV7630:
- PDEBUG(D_ERR, "7630 is not supported by this driver version");
- return -1;
- case SEN_OV7640:
- PDEBUG(D_PROBE, "Writing 7640 registers");
- if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
- return -1;
- break;
- case SEN_OV7670:
- PDEBUG(D_PROBE, "Writing 7670 registers");
- if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
- return -1;
- break;
- default:
- PDEBUG(D_PROBE, "Writing 7610 registers");
- if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
- return -1;
- break;
- }
-
/* Set sensor-specific vars */
/* sd->sif = 0; already done */
return 0;
@@ -1073,141 +1235,7 @@ static int ov7xx0_configure(struct sd *sd)
static int ov6xx0_configure(struct sd *sd)
{
int rc;
- static const struct ov_i2c_regvals norm_6x20[] = {
- { 0x12, 0x80 }, /* reset */
- { 0x11, 0x01 },
- { 0x03, 0x60 },
- { 0x05, 0x7f }, /* For when autoadjust is off */
- { 0x07, 0xa8 },
- /* The ratio of 0x0c and 0x0d controls the white point */
- { 0x0c, 0x24 },
- { 0x0d, 0x24 },
- { 0x0f, 0x15 }, /* COMS */
- { 0x10, 0x75 }, /* AEC Exposure time */
- { 0x12, 0x24 }, /* Enable AGC */
- { 0x14, 0x04 },
- /* 0x16: 0x06 helps frame stability with moving objects */
- { 0x16, 0x06 },
-/* { 0x20, 0x30 }, * Aperture correction enable */
- { 0x26, 0xb2 }, /* BLC enable */
- /* 0x28: 0x05 Selects RGB format if RGB on */
- { 0x28, 0x05 },
- { 0x2a, 0x04 }, /* Disable framerate adjust */
-/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
- { 0x2d, 0x99 },
- { 0x33, 0xa0 }, /* Color Processing Parameter */
- { 0x34, 0xd2 }, /* Max A/D range */
- { 0x38, 0x8b },
- { 0x39, 0x40 },
-
- { 0x3c, 0x39 }, /* Enable AEC mode changing */
- { 0x3c, 0x3c }, /* Change AEC mode */
- { 0x3c, 0x24 }, /* Disable AEC mode changing */
-
- { 0x3d, 0x80 },
- /* These next two registers (0x4a, 0x4b) are undocumented.
- * They control the color balance */
- { 0x4a, 0x80 },
- { 0x4b, 0x80 },
- { 0x4d, 0xd2 }, /* This reduces noise a bit */
- { 0x4e, 0xc1 },
- { 0x4f, 0x04 },
-/* Do 50-53 have any effect? */
-/* Toggle 0x12[2] off and on here? */
- };
-
- static const struct ov_i2c_regvals norm_6x30[] = {
- { 0x12, 0x80 }, /* Reset */
- { 0x00, 0x1f }, /* Gain */
- { 0x01, 0x99 }, /* Blue gain */
- { 0x02, 0x7c }, /* Red gain */
- { 0x03, 0xc0 }, /* Saturation */
- { 0x05, 0x0a }, /* Contrast */
- { 0x06, 0x95 }, /* Brightness */
- { 0x07, 0x2d }, /* Sharpness */
- { 0x0c, 0x20 },
- { 0x0d, 0x20 },
- { 0x0e, 0x20 },
- { 0x0f, 0x05 },
- { 0x10, 0x9a },
- { 0x11, 0x00 }, /* Pixel clock = fastest */
- { 0x12, 0x24 }, /* Enable AGC and AWB */
- { 0x13, 0x21 },
- { 0x14, 0x80 },
- { 0x15, 0x01 },
- { 0x16, 0x03 },
- { 0x17, 0x38 },
- { 0x18, 0xea },
- { 0x19, 0x04 },
- { 0x1a, 0x93 },
- { 0x1b, 0x00 },
- { 0x1e, 0xc4 },
- { 0x1f, 0x04 },
- { 0x20, 0x20 },
- { 0x21, 0x10 },
- { 0x22, 0x88 },
- { 0x23, 0xc0 }, /* Crystal circuit power level */
- { 0x25, 0x9a }, /* Increase AEC black ratio */
- { 0x26, 0xb2 }, /* BLC enable */
- { 0x27, 0xa2 },
- { 0x28, 0x00 },
- { 0x29, 0x00 },
- { 0x2a, 0x84 }, /* 60 Hz power */
- { 0x2b, 0xa8 }, /* 60 Hz power */
- { 0x2c, 0xa0 },
- { 0x2d, 0x95 }, /* Enable auto-brightness */
- { 0x2e, 0x88 },
- { 0x33, 0x26 },
- { 0x34, 0x03 },
- { 0x36, 0x8f },
- { 0x37, 0x80 },
- { 0x38, 0x83 },
- { 0x39, 0x80 },
- { 0x3a, 0x0f },
- { 0x3b, 0x3c },
- { 0x3c, 0x1a },
- { 0x3d, 0x80 },
- { 0x3e, 0x80 },
- { 0x3f, 0x0e },
- { 0x40, 0x00 }, /* White bal */
- { 0x41, 0x00 }, /* White bal */
- { 0x42, 0x80 },
- { 0x43, 0x3f }, /* White bal */
- { 0x44, 0x80 },
- { 0x45, 0x20 },
- { 0x46, 0x20 },
- { 0x47, 0x80 },
- { 0x48, 0x7f },
- { 0x49, 0x00 },
- { 0x4a, 0x00 },
- { 0x4b, 0x80 },
- { 0x4c, 0xd0 },
- { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
- { 0x4e, 0x40 },
- { 0x4f, 0x07 }, /* UV avg., col. killer: max */
- { 0x50, 0xff },
- { 0x54, 0x23 }, /* Max AGC gain: 18dB */
- { 0x55, 0xff },
- { 0x56, 0x12 },
- { 0x57, 0x81 },
- { 0x58, 0x75 },
- { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
- { 0x5a, 0x2c },
- { 0x5b, 0x0f }, /* AWB chrominance levels */
- { 0x5c, 0x10 },
- { 0x3d, 0x80 },
- { 0x27, 0xa6 },
- { 0x12, 0x20 }, /* Toggle AWB */
- { 0x12, 0x24 },
- };
-
- PDEBUG(D_PROBE, "starting sensor configuration");
-
- if (init_ov_sensor(sd) < 0) {
- PDEBUG(D_ERR, "Failed to read sensor ID.");
- return -1;
- }
- PDEBUG(D_PROBE, "OV6xx0 sensor detected");
+ PDEBUG(D_PROBE, "starting OV6xx0 configuration");
/* Detect sensor (sub)type */
rc = i2c_r(sd, OV7610_REG_COM_I);
@@ -1251,15 +1279,6 @@ static int ov6xx0_configure(struct sd *sd)
/* Set sensor-specific vars */
sd->sif = 1;
- if (sd->sensor == SEN_OV6620) {
- PDEBUG(D_PROBE, "Writing 6x20 registers");
- if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
- return -1;
- } else {
- PDEBUG(D_PROBE, "Writing 6x30 registers");
- if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
- return -1;
- }
return 0;
}
@@ -1298,22 +1317,31 @@ static int sd_config(struct gspca_dev *gspca_dev,
ov51x_led_control(sd, 0); /* turn LED off */
/* Test for 76xx */
- sd->primary_i2c_slave = OV7xx0_SID;
if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
goto error;
/* The OV519 must be more aggressive about sensor detection since
* I2C write will never fail if the sensor is not present. We have
* to try to initialize the sensor to detect its presence */
- if (init_ov_sensor(sd) < 0) {
+ if (init_ov_sensor(sd) >= 0) {
+ if (ov7xx0_configure(sd) < 0) {
+ PDEBUG(D_ERR, "Failed to configure OV7xx0");
+ goto error;
+ }
+ } else {
+
/* Test for 6xx0 */
- sd->primary_i2c_slave = OV6xx0_SID;
if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
goto error;
- if (init_ov_sensor(sd) < 0) {
+ if (init_ov_sensor(sd) >= 0) {
+ if (ov6xx0_configure(sd) < 0) {
+ PDEBUG(D_ERR, "Failed to configure OV6xx0");
+ goto error;
+ }
+ } else {
+
/* Test for 8xx0 */
- sd->primary_i2c_slave = OV8xx0_SID;
if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
goto error;
@@ -1321,24 +1349,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
PDEBUG(D_ERR,
"Can't determine sensor slave IDs");
goto error;
- } else {
- if (ov8xx0_configure(sd) < 0) {
- PDEBUG(D_ERR,
- "Failed to configure OV8xx0 sensor");
- goto error;
- }
}
- } else {
- if (ov6xx0_configure(sd) < 0) {
- PDEBUG(D_ERR, "Failed to configure OV6xx0");
+ if (ov8xx0_configure(sd) < 0) {
+ PDEBUG(D_ERR,
+ "Failed to configure OV8xx0 sensor");
goto error;
}
}
- } else {
- if (ov7xx0_configure(sd) < 0) {
- PDEBUG(D_ERR, "Failed to configure OV7xx0");
- goto error;
- }
}
cam = &gspca_dev->cam;
@@ -1355,15 +1372,53 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->colors = COLOR_DEF;
sd->hflip = HFLIP_DEF;
sd->vflip = VFLIP_DEF;
+ if (sd->sensor != SEN_OV7670)
+ gspca_dev->ctrl_dis = (1 << HFLIP_IDX)
+ | (1 << VFLIP_IDX);
return 0;
error:
PDEBUG(D_ERR, "OV519 Config failed");
return -EBUSY;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* initialize the sensor */
+ switch (sd->sensor) {
+ case SEN_OV6620:
+ if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
+ return -EIO;
+ break;
+ case SEN_OV6630:
+ if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
+ return -EIO;
+ break;
+ default:
+/* case SEN_OV7610: */
+/* case SEN_OV76BE: */
+ if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
+ return -EIO;
+ break;
+ case SEN_OV7620:
+ if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
+ return -EIO;
+ break;
+ case SEN_OV7640:
+ if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
+ return -EIO;
+ break;
+ case SEN_OV7670:
+ if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
+ return -EIO;
+ break;
+ case SEN_OV8610:
+ if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
+ return -EIO;
+ break;
+ }
return 0;
}
@@ -1799,7 +1854,7 @@ static int set_ov_sensor_window(struct sd *sd)
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
@@ -1816,9 +1871,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
goto out;
PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
ov51x_led_control(sd, 1);
- return;
+ return 0;
out:
PDEBUG(D_ERR, "camera start error:%d", ret);
+ return ret;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1827,14 +1883,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
ov51x_led_control((struct sd *) gspca_dev, 0);
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -2091,11 +2139,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -2132,6 +2178,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index 7ef18d57881..0b0c573d06d 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -56,12 +56,6 @@ MODULE_LICENSE("GPL");
#define PAC207_GAIN_KNEE 20
#define PAC207_AUTOGAIN_DEADZONE 30
-/* We calculating the autogain at the end of the transfer of a frame, at this
- moment a frame with the old settings is being transmitted, and a frame is
- being captured with the old settings. So if we adjust the autogain we must
- ignore atleast the 2 next frames for the new settings to come into effect
- before doing any other adjustments */
-#define PAC207_AUTOGAIN_IGNORE_FRAMES 3
/* specific webcam descriptor */
struct sd {
@@ -131,7 +125,8 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 1,
.step = 1,
- .default_value = 1,
+#define AUTOGAIN_DEF 1
+ .default_value = AUTOGAIN_DEF,
.flags = 0,
},
.set = sd_setautogain,
@@ -181,9 +176,6 @@ static const __u8 pac207_sensor_init[][8] = {
/* 48 reg_72 Rate Control end BalSize_4a =0x36 */
static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
-static const unsigned char pac207_sof_marker[5] =
- { 0xff, 0xff, 0x00, 0xff, 0x96 };
-
static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
const u8 *buffer, u16 length)
{
@@ -259,40 +251,37 @@ static int sd_config(struct gspca_dev *gspca_dev,
return -ENODEV;
}
- pac207_write_reg(gspca_dev, 0x41, 0x00);
- /* Bit_0=Image Format,
- * Bit_1=LED,
- * Bit_2=Compression test mode enable */
- pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
- pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
-
PDEBUG(D_PROBE,
"Pixart PAC207BCA Image Processor and Control Chip detected"
" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
cam = &gspca_dev->cam;
- cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x05;
cam->cam_mode = sif_mode;
cam->nmodes = ARRAY_SIZE(sif_mode);
sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
sd->exposure = PAC207_EXPOSURE_DEFAULT;
sd->gain = PAC207_GAIN_DEFAULT;
+ sd->autogain = AUTOGAIN_DEF;
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
- struct sd *sd = (struct sd *) gspca_dev;
+ pac207_write_reg(gspca_dev, 0x41, 0x00);
+ /* Bit_0=Image Format,
+ * Bit_1=LED,
+ * Bit_2=Compression test mode enable */
+ pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
+ pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
- sd->autogain = 1;
return 0;
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 mode;
@@ -334,6 +323,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
sd->sof_read = 0;
sd->autogain_ignore_frames = 0;
atomic_set(&sd->avg_lum, -1);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -343,14 +333,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
+/* Include pac common sof detection functions */
+#include "pac_common.h"
static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
{
@@ -365,33 +349,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
- sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
-}
-
-static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
- unsigned char *m, int len)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- int i;
-
- /* Search for the SOF marker (fixed part) in the header */
- for (i = 0; i < len; i++) {
- if (m[i] == pac207_sof_marker[sd->sof_read]) {
- sd->sof_read++;
- if (sd->sof_read == sizeof(pac207_sof_marker)) {
- PDEBUG(D_STREAM,
- "SOF found, bytes to analyze: %u."
- " Frame starts at byte #%u",
- len, i + 1);
- sd->sof_read = 0;
- return m + i + 1;
- }
- } else {
- sd->sof_read = 0;
- }
- }
-
- return NULL;
+ sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -402,14 +360,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct sd *sd = (struct sd *) gspca_dev;
unsigned char *sof;
- sof = pac207_find_sof(gspca_dev, data, len);
+ sof = pac_find_sof(gspca_dev, data, len);
if (sof) {
int n;
/* finish decoding current frame */
n = sof - data;
- if (n > sizeof pac207_sof_marker)
- n -= sizeof pac207_sof_marker;
+ if (n > sizeof pac_sof_marker)
+ n -= sizeof pac_sof_marker;
else
n = 0;
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
@@ -537,7 +495,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
sd->gain = PAC207_GAIN_DEFAULT;
if (gspca_dev->streaming) {
sd->autogain_ignore_frames =
- PAC207_AUTOGAIN_IGNORE_FRAMES;
+ PAC_AUTOGAIN_IGNORE_FRAMES;
setexposure(gspca_dev);
setgain(gspca_dev);
}
@@ -560,11 +518,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.dq_callback = pac207_do_auto_gain,
.pkt_scan = sd_pkt_scan,
};
@@ -579,6 +535,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2470)},
{USB_DEVICE(0x093a, 0x2471)},
{USB_DEVICE(0x093a, 0x2472)},
+ {USB_DEVICE(0x093a, 0x2476)},
{USB_DEVICE(0x2001, 0xf115)},
{}
};
@@ -597,6 +554,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index 815bea6edc4..e5ff9a6199e 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -19,6 +19,36 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* Some documentation about various registers as determined by trial and error.
+ When the register addresses differ between the 7202 and the 7311 the 2
+ different addresses are written as 7302addr/7311addr, when one of the 2
+ addresses is a - sign that register description is not valid for the
+ matching IC.
+
+ Register page 1:
+
+ Address Description
+ -/0x08 Unknown compressor related, must always be 8 except when not
+ in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
+ -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
+ bits 345 seem to toggle per color gains on/off (inverted)
+ 0x78 Global control, bit 6 controls the LED (inverted)
+ -/0x80 JPEG compression ratio ? Best not touched
+
+ Register page 3/4:
+
+ Address Description
+ 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
+ the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
+ -/0x0f Master gain 1-245, low value = high gain
+ 0x10/- Master gain 0-31
+ -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
+ 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
+ -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
+ completely disable the analog amplification block. Set to 0x68
+ for max gain, 0x14 for minimal gain.
+*/
+
#define MODULE_NAME "pac7311"
#include "gspca.h"
@@ -31,18 +61,23 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- int lum_sum;
- atomic_t avg_lum;
- atomic_t do_gain;
-
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
+ unsigned char gain;
+ unsigned char exposure;
unsigned char autogain;
+ __u8 hflip;
+ __u8 vflip;
+
+ __u8 sensor;
+#define SENSOR_PAC7302 0
+#define SENSOR_PAC7311 1
- char ffseq;
- signed char ag_cnt;
-#define AG_CNT_START 13
+ u8 sof_read;
+ u8 autogain_ignore_frames;
+
+ atomic_t avg_lum;
};
/* V4L2 controls supported by the driver */
@@ -54,8 +89,18 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
+/* This control is pac7302 only */
+#define BRIGHTNESS_IDX 0
{
{
.id = V4L2_CID_BRIGHTNESS,
@@ -71,13 +116,15 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setbrightness,
.get = sd_getbrightness,
},
+/* This control is for both the 7302 and the 7311 */
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 255,
+#define CONTRAST_MAX 255
+ .maximum = CONTRAST_MAX,
.step = 1,
#define CONTRAST_DEF 127
.default_value = CONTRAST_DEF,
@@ -85,13 +132,16 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcontrast,
.get = sd_getcontrast,
},
+/* This control is pac7302 only */
+#define SATURATION_IDX 2
{
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Color",
+ .name = "Saturation",
.minimum = 0,
- .maximum = 255,
+#define COLOR_MAX 255
+ .maximum = COLOR_MAX,
.step = 1,
#define COLOR_DEF 127
.default_value = COLOR_DEF,
@@ -99,6 +149,39 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcolors,
.get = sd_getcolors,
},
+/* All controls below are for both the 7302 and the 7311 */
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+#define GAIN_MAX 255
+ .maximum = GAIN_MAX,
+ .step = 1,
+#define GAIN_DEF 127
+#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
+ .default_value = GAIN_DEF,
+ },
+ .set = sd_setgain,
+ .get = sd_getgain,
+ },
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = 0,
+#define EXPOSURE_MAX 255
+ .maximum = EXPOSURE_MAX,
+ .step = 1,
+#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
+#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
+ .default_value = EXPOSURE_DEF,
+ },
+ .set = sd_setexposure,
+ .get = sd_getexposure,
+ },
{
{
.id = V4L2_CID_AUTOGAIN,
@@ -113,101 +196,207 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+ {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define HFLIP_DEF 0
+ .default_value = HFLIP_DEF,
+ },
+ .set = sd_sethflip,
+ .get = sd_gethflip,
+ },
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vflip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define VFLIP_DEF 0
+ .default_value = VFLIP_DEF,
+ },
+ .set = sd_setvflip,
+ .get = sd_getvflip,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
- {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 2},
- {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1},
- {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
.bytesperline = 640,
.sizeimage = 640 * 480 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0},
};
-#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
-
-static const __u8 pac7311_jpeg_header[] = {
- 0xff, 0xd8,
- 0xff, 0xe0, 0x00, 0x03, 0x20,
- 0xff, 0xc0, 0x00, 0x11, 0x08,
- 0x01, 0xe0, /* 12: height */
- 0x02, 0x80, /* 14: width */
- 0x03, /* 16 */
- 0x01, 0x21, 0x00,
- 0x02, 0x11, 0x01,
- 0x03, 0x11, 0x01,
- 0xff, 0xdb, 0x00, 0x84,
- 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
- 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
- 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
- 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
- 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
- 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
- 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
- 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
- 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
- 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
- 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
- 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
- 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
- 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
- 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
- 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
- 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
- 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
- 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
- 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
- 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
- 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
- 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
- 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
- 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
- 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
- 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
- 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
- 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
- 0x11, 0x00, 0x3f, 0x00
+/* pac 7302 */
+static const __u8 init_7302[] = {
+/* index,value */
+ 0xff, 0x01, /* page 1 */
+ 0x78, 0x00, /* deactivate */
+ 0xff, 0x01,
+ 0x78, 0x40, /* led off */
+};
+static const __u8 start_7302[] = {
+/* index, len, [value]* */
+ 0xff, 1, 0x00, /* page 0 */
+ 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
+ 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
+ 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
+ 0x26, 2, 0xaa, 0xaa,
+ 0x2e, 1, 0x31,
+ 0x38, 1, 0x01,
+ 0x3a, 3, 0x14, 0xff, 0x5a,
+ 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
+ 0x00, 0x54, 0x11,
+ 0x55, 1, 0x00,
+ 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
+ 0x6b, 1, 0x00,
+ 0x6e, 3, 0x08, 0x06, 0x00,
+ 0x72, 3, 0x00, 0xff, 0x00,
+ 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
+ 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
+ 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
+ 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
+ 0xd2, 0xeb,
+ 0xaf, 1, 0x02,
+ 0xb5, 2, 0x08, 0x08,
+ 0xb8, 2, 0x08, 0x88,
+ 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
+ 0xcc, 1, 0x00,
+ 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
+ 0xc1, 0xd7, 0xec,
+ 0xdc, 1, 0x01,
+ 0xff, 1, 0x01, /* page 1 */
+ 0x12, 3, 0x02, 0x00, 0x01,
+ 0x3e, 2, 0x00, 0x00,
+ 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
+ 0x7c, 1, 0x00,
+ 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
+ 0x02, 0x00,
+ 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
+ 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
+ 0xd8, 1, 0x01,
+ 0xdb, 2, 0x00, 0x01,
+ 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
+ 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
+ 0xeb, 1, 0x00,
+ 0xff, 1, 0x02, /* page 2 */
+ 0x22, 1, 0x00,
+ 0xff, 1, 0x03, /* page 3 */
+ 0x00, 255, /* load the page 3 */
+ 0x11, 1, 0x01,
+ 0xff, 1, 0x02, /* page 2 */
+ 0x13, 1, 0x00,
+ 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
+ 0x27, 2, 0x14, 0x0c,
+ 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
+ 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
+ 0x6e, 1, 0x08,
+ 0xff, 1, 0x01, /* page 1 */
+ 0x78, 1, 0x00,
+ 0, 0 /* end of sequence */
+};
+
+/* page 3 - the value 0xaa says skip the index - see reg_w_page() */
+static const __u8 page3_7302[] = {
+ 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
+ 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
+ 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
+ 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
+ 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
+ 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
+ 0x00
+};
+
+/* pac 7311 */
+static const __u8 init_7311[] = {
+ 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
+ 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
+ 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
+ 0xff, 0x04,
+ 0x27, 0x80,
+ 0x28, 0xca,
+ 0x29, 0x53,
+ 0x2a, 0x0e,
+ 0xff, 0x01,
+ 0x3e, 0x20,
+};
+
+static const __u8 start_7311[] = {
+/* index, len, [value]* */
+ 0xff, 1, 0x01, /* page 1 */
+ 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
+ 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
+ 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
+ 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
+ 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
+ 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
+ 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
+ 0xd0, 0xff,
+ 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
+ 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
+ 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
+ 0x18, 0x20,
+ 0x96, 3, 0x01, 0x08, 0x04,
+ 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
+ 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
+ 0x3f, 0x00, 0x0a, 0x01, 0x00,
+ 0xff, 1, 0x04, /* page 4 */
+ 0x00, 254, /* load the page 4 */
+ 0x11, 1, 0x01,
+ 0, 0 /* end of sequence */
+};
+
+/* page 4 - the value 0xaa says skip the index - see reg_w_page() */
+static const __u8 page4_7311[] = {
+ 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
+ 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
+ 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
+ 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
+ 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
+ 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
};
static void reg_w_buf(struct gspca_dev *gspca_dev,
- __u16 index,
- const char *buffer, __u16 len)
+ __u8 index,
+ const char *buffer, int len)
{
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(gspca_dev->dev,
@@ -219,21 +408,9 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
500);
}
-static __u8 reg_r(struct gspca_dev *gspca_dev,
- __u16 index)
-{
- usb_control_msg(gspca_dev->dev,
- usb_rcvctrlpipe(gspca_dev->dev, 0),
- 0, /* request */
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, /* value */
- index, gspca_dev->usb_buf, 1,
- 500);
- return gspca_dev->usb_buf[0];
-}
static void reg_w(struct gspca_dev *gspca_dev,
- __u16 index,
+ __u8 index,
__u8 value)
{
gspca_dev->usb_buf[0] = value;
@@ -241,10 +418,78 @@ static void reg_w(struct gspca_dev *gspca_dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0, /* request */
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, index, gspca_dev->usb_buf, 1,
+ 0, index, gspca_dev->usb_buf, 1,
500);
}
+static void reg_w_seq(struct gspca_dev *gspca_dev,
+ const __u8 *seq, int len)
+{
+ while (--len >= 0) {
+ reg_w(gspca_dev, seq[0], seq[1]);
+ seq += 2;
+ }
+}
+
+/* load the beginning of a page */
+static void reg_w_page(struct gspca_dev *gspca_dev,
+ const __u8 *page, int len)
+{
+ int index;
+
+ for (index = 0; index < len; index++) {
+ if (page[index] == 0xaa) /* skip this index */
+ continue;
+ gspca_dev->usb_buf[0] = page[index];
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, gspca_dev->usb_buf, 1,
+ 500);
+ }
+}
+
+/* output a variable sequence */
+static void reg_w_var(struct gspca_dev *gspca_dev,
+ const __u8 *seq)
+{
+ int index, len;
+
+ for (;;) {
+ index = *seq++;
+ len = *seq++;
+ switch (len) {
+ case 0:
+ return;
+ case 254:
+ reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
+ break;
+ case 255:
+ reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
+ break;
+ default:
+ if (len > 64) {
+ PDEBUG(D_ERR|D_STREAM,
+ "Incorrect variable sequence");
+ return;
+ }
+ while (len > 0) {
+ if (len < 8) {
+ reg_w_buf(gspca_dev, index, seq, len);
+ seq += len;
+ break;
+ }
+ reg_w_buf(gspca_dev, index, seq, 8);
+ seq += 8;
+ index += 8;
+ len -= 8;
+ }
+ }
+ }
+ /* not reached */
+}
+
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
@@ -252,203 +497,246 @@ static int sd_config(struct gspca_dev *gspca_dev,
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
- PDEBUG(D_CONF, "Find Sensor PAC7311");
- reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x27, 0x80);
- reg_w(gspca_dev, 0x28, 0xca);
- reg_w(gspca_dev, 0x29, 0x53);
- reg_w(gspca_dev, 0x2a, 0x0e);
- reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x3e, 0x20);
-
cam = &gspca_dev->cam;
cam->epaddr = 0x05;
- cam->cam_mode = vga_mode;
- cam->nmodes = ARRAY_SIZE(vga_mode);
+
+ sd->sensor = id->driver_info;
+ if (sd->sensor == SENSOR_PAC7302) {
+ PDEBUG(D_CONF, "Find Sensor PAC7302");
+ cam->cam_mode = &vga_mode[2]; /* only 640x480 */
+ cam->nmodes = 1;
+ } else {
+ PDEBUG(D_CONF, "Find Sensor PAC7311");
+ cam->cam_mode = vga_mode;
+ cam->nmodes = ARRAY_SIZE(vga_mode);
+ gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
+ | (1 << SATURATION_IDX);
+ }
sd->brightness = BRIGHTNESS_DEF;
sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
+ sd->gain = GAIN_DEF;
+ sd->exposure = EXPOSURE_DEF;
sd->autogain = AUTOGAIN_DEF;
- sd->ag_cnt = -1;
+ sd->hflip = HFLIP_DEF;
+ sd->vflip = VFLIP_DEF;
return 0;
}
-static void setbrightness(struct gspca_dev *gspca_dev)
+/* This function is used by pac7302 only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i, v;
+ static const __u8 max[10] =
+ {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
+ 0xd4, 0xec};
+ static const __u8 delta[10] =
+ {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
+ 0x11, 0x0b};
+
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ for (i = 0; i < 10; i++) {
+ v = max[i];
+ v += (sd->brightness - BRIGHTNESS_MAX)
+ * 150 / BRIGHTNESS_MAX; /* 200 ? */
+ v -= delta[i] * sd->contrast / CONTRAST_MAX;
+ if (v < 0)
+ v = 0;
+ else if (v > 0xff)
+ v = 0xff;
+ reg_w(gspca_dev, 0xa2 + i, v);
+ }
+ reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+/* This function is used by pac7311 only */
+static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int brightness;
-/*jfm: inverted?*/
- brightness = BRIGHTNESS_MAX - sd->brightness;
reg_w(gspca_dev, 0xff, 0x04);
-/* reg_w(gspca_dev, 0x0e, 0x00); */
- reg_w(gspca_dev, 0x0f, brightness);
+ reg_w(gspca_dev, 0x10, sd->contrast >> 4);
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
- PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
}
-static void setcontrast(struct gspca_dev *gspca_dev)
+/* This function is used by pac7302 only */
+static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ int i, v;
+ static const int a[9] =
+ {217, -212, 0, -101, 170, -67, -38, -315, 355};
+ static const int b[9] =
+ {19, 106, 0, 19, 106, 1, 19, 106, 1};
- reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x80, sd->contrast);
- /* load registers to sensor (Bit 0, auto clear) */
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
reg_w(gspca_dev, 0x11, 0x01);
- PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ for (i = 0; i < 9; i++) {
+ v = a[i] * sd->colors / COLOR_MAX + b[i];
+ reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
+ reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
+ }
+ reg_w(gspca_dev, 0xdc, 0x01);
+ PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
}
-static void setcolors(struct gspca_dev *gspca_dev)
+static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x10, sd->colors);
+ if (sd->sensor == SENSOR_PAC7302) {
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
+ reg_w(gspca_dev, 0x10, sd->gain >> 3);
+ } else {
+ int gain = GAIN_MAX - sd->gain;
+ if (gain < 1)
+ gain = 1;
+ else if (gain > 245)
+ gain = 245;
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
+ reg_w(gspca_dev, 0x0e, 0x00);
+ reg_w(gspca_dev, 0x0f, gain);
+ }
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
- PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
}
-static void setautogain(struct gspca_dev *gspca_dev)
+static void setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ __u8 reg;
+
+ /* register 2 of frame 3/4 contains the clock divider configuring the
+ no fps according to the formula: 60 / reg. sd->exposure is the
+ desired exposure time in ms. */
+ reg = 120 * sd->exposure / 1000;
+ if (reg < 2)
+ reg = 2;
+ else if (reg > 63)
+ reg = 63;
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
+ the nearest multiple of 3, except when between 6 and 12? */
+ if (reg < 6 || reg > 12)
+ reg = ((reg + 1) / 3) * 3;
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
+ reg_w(gspca_dev, 0x02, reg);
+ } else {
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
+ reg_w(gspca_dev, 0x02, reg);
+ /* Page 1 register 8 must always be 0x08 except when not in
+ 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
+ reg_w(gspca_dev, 0xff, 0x01);
+ if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
+ reg <= 3)
+ reg_w(gspca_dev, 0x08, 0x09);
+ else
+ reg_w(gspca_dev, 0x08, 0x08);
+ }
+ /* load registers to sensor (Bit 0, auto clear) */
+ reg_w(gspca_dev, 0x11, 0x01);
+}
- if (sd->autogain) {
- sd->lum_sum = 0;
- sd->ag_cnt = AG_CNT_START;
+static void sethvflip(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 data;
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
+ data = (sd->hflip ? 0x08 : 0x00)
+ | (sd->vflip ? 0x04 : 0x00);
} else {
- sd->ag_cnt = -1;
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
+ data = (sd->hflip ? 0x04 : 0x00)
+ | (sd->vflip ? 0x08 : 0x00);
}
+ reg_w(gspca_dev, 0x21, data);
+ /* load registers to sensor (Bit 0, auto clear) */
+ reg_w(gspca_dev, 0x11, 0x01);
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
- reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_PAC7302)
+ reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
+ else
+ reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
+
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
- reg_w(gspca_dev, 0xff, 0x01);
- reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
- reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
- reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
- reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
- reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
- reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3);
- reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
- reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
- reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
- reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
- reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
- reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2);
- reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
- reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
- reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
- reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2);
- reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3);
- reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4);
- reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
- reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
+ struct sd *sd = (struct sd *) gspca_dev;
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x04);
- reg_w(gspca_dev, 0x03, 0x54);
- reg_w(gspca_dev, 0x04, 0x07);
- reg_w(gspca_dev, 0x05, 0x2b);
- reg_w(gspca_dev, 0x06, 0x09);
- reg_w(gspca_dev, 0x07, 0x0f);
- reg_w(gspca_dev, 0x08, 0x09);
- reg_w(gspca_dev, 0x09, 0x00);
- reg_w(gspca_dev, 0x0c, 0x07);
- reg_w(gspca_dev, 0x0d, 0x00);
- reg_w(gspca_dev, 0x0e, 0x00);
- reg_w(gspca_dev, 0x0f, 0x62);
- reg_w(gspca_dev, 0x10, 0x08);
- reg_w(gspca_dev, 0x12, 0x07);
- reg_w(gspca_dev, 0x13, 0x00);
- reg_w(gspca_dev, 0x14, 0x00);
- reg_w(gspca_dev, 0x15, 0x00);
- reg_w(gspca_dev, 0x16, 0x00);
- reg_w(gspca_dev, 0x17, 0x00);
- reg_w(gspca_dev, 0x18, 0x00);
- reg_w(gspca_dev, 0x19, 0x00);
- reg_w(gspca_dev, 0x1a, 0x00);
- reg_w(gspca_dev, 0x1b, 0x03);
- reg_w(gspca_dev, 0x1c, 0xa0);
- reg_w(gspca_dev, 0x1d, 0x01);
- reg_w(gspca_dev, 0x1e, 0xf4);
- reg_w(gspca_dev, 0x21, 0x00);
- reg_w(gspca_dev, 0x22, 0x08);
- reg_w(gspca_dev, 0x24, 0x03);
- reg_w(gspca_dev, 0x26, 0x00);
- reg_w(gspca_dev, 0x27, 0x01);
- reg_w(gspca_dev, 0x28, 0xca);
- reg_w(gspca_dev, 0x29, 0x10);
- reg_w(gspca_dev, 0x2a, 0x06);
- reg_w(gspca_dev, 0x2b, 0x78);
- reg_w(gspca_dev, 0x2c, 0x00);
- reg_w(gspca_dev, 0x2d, 0x00);
- reg_w(gspca_dev, 0x2e, 0x00);
- reg_w(gspca_dev, 0x2f, 0x00);
- reg_w(gspca_dev, 0x30, 0x23);
- reg_w(gspca_dev, 0x31, 0x28);
- reg_w(gspca_dev, 0x32, 0x04);
- reg_w(gspca_dev, 0x33, 0x11);
- reg_w(gspca_dev, 0x34, 0x00);
- reg_w(gspca_dev, 0x35, 0x00);
- reg_w(gspca_dev, 0x11, 0x01);
- setcontrast(gspca_dev);
- setbrightness(gspca_dev);
- setcolors(gspca_dev);
- setautogain(gspca_dev);
+ sd->sof_read = 0;
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ reg_w_var(gspca_dev, start_7302);
+ setbrightcont(gspca_dev);
+ setcolors(gspca_dev);
+ } else {
+ reg_w_var(gspca_dev, start_7311);
+ setcontrast(gspca_dev);
+ }
+ setgain(gspca_dev);
+ setexposure(gspca_dev);
+ sethvflip(gspca_dev);
/* set correct resolution */
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
- case 2: /* 160x120 */
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x03);
+ case 2: /* 160x120 pac7311 */
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x08, 0x09);
reg_w(gspca_dev, 0x17, 0x20);
- reg_w(gspca_dev, 0x1b, 0x00);
-/* reg_w(gspca_dev, 0x80, 0x69); */
reg_w(gspca_dev, 0x87, 0x10);
break;
- case 1: /* 320x240 */
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x03);
+ case 1: /* 320x240 pac7311 */
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x08, 0x09);
reg_w(gspca_dev, 0x17, 0x30);
-/* reg_w(gspca_dev, 0x80, 0x3f); */
reg_w(gspca_dev, 0x87, 0x11);
break;
case 0: /* 640x480 */
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x03);
+ if (sd->sensor == SENSOR_PAC7302)
+ break;
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x08, 0x08);
reg_w(gspca_dev, 0x17, 0x00);
-/* reg_w(gspca_dev, 0x80, 0x1c); */
reg_w(gspca_dev, 0x87, 0x12);
break;
}
+ sd->sof_read = 0;
+ sd->autogain_ignore_frames = 0;
+ atomic_set(&sd->avg_lum, -1);
+
/* start stream */
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x78, 0x04);
- reg_w(gspca_dev, 0x78, 0x05);
+ if (sd->sensor == SENSOR_PAC7302)
+ reg_w(gspca_dev, 0x78, 0x01);
+ else
+ reg_w(gspca_dev, 0x78, 0x05);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ reg_w(gspca_dev, 0xff, 0x01);
+ reg_w(gspca_dev, 0x78, 0x00);
+ reg_w(gspca_dev, 0x78, 0x00);
+ return;
+ }
reg_w(gspca_dev, 0xff, 0x04);
reg_w(gspca_dev, 0x27, 0x80);
reg_w(gspca_dev, 0x28, 0xca);
@@ -456,187 +744,147 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x2a, 0x0e);
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x3e, 0x20);
- reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
-}
+ struct sd *sd = (struct sd *) gspca_dev;
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x27, 0x80);
- reg_w(gspca_dev, 0x28, 0xca);
- reg_w(gspca_dev, 0x29, 0x53);
- reg_w(gspca_dev, 0x2a, 0x0e);
- reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x3e, 0x20);
- reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
- reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
+ if (sd->sensor == SENSOR_PAC7302) {
+ reg_w(gspca_dev, 0xff, 0x01);
+ reg_w(gspca_dev, 0x78, 0x40);
+ }
}
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int luma;
- int luma_mean = 128;
- int luma_delta = 20;
- __u8 spring = 5;
- int Gbright;
+ int avg_lum = atomic_read(&sd->avg_lum);
+ int desired_lum, deadzone;
- if (!atomic_read(&sd->do_gain))
+ if (avg_lum == -1)
return;
- atomic_set(&sd->do_gain, 0);
-
- luma = atomic_read(&sd->avg_lum);
- Gbright = reg_r(gspca_dev, 0x02);
- PDEBUG(D_FRAM, "luma mean %d", luma);
- if (luma < luma_mean - luma_delta ||
- luma > luma_mean + luma_delta) {
- Gbright += (luma_mean - luma) >> spring;
- if (Gbright > 0x1a)
- Gbright = 0x1a;
- else if (Gbright < 4)
- Gbright = 4;
- PDEBUG(D_FRAM, "gbright %d", Gbright);
- reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x0f, Gbright);
- /* load registers to sensor (Bit 0, auto clear) */
- reg_w(gspca_dev, 0x11, 0x01);
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ desired_lum = 270 + sd->brightness * 4;
+ /* Hack hack, with the 7202 the first exposure step is
+ pretty large, so if we're about to make the first
+ exposure increase make the deadzone large to avoid
+ oscilating */
+ if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
+ sd->exposure > EXPOSURE_DEF &&
+ sd->exposure < 42)
+ deadzone = 90;
+ else
+ deadzone = 30;
+ } else {
+ desired_lum = 200;
+ deadzone = 20;
}
+
+ if (sd->autogain_ignore_frames > 0)
+ sd->autogain_ignore_frames--;
+ else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
+ deadzone, GAIN_KNEE, EXPOSURE_KNEE))
+ sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
}
+static const unsigned char pac7311_jpeg_header1[] = {
+ 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
+};
+
+static const unsigned char pac7311_jpeg_header2[] = {
+ 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
+ 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+};
+
+/* this function is run at interrupt level */
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
- unsigned char tmpbuf[4];
- int i, p, ffseq;
-
-/* if (len < 5) { */
- if (len < 6) {
-/* gspca_dev->last_packet_type = DISCARD_PACKET; */
- return;
- }
-
- ffseq = sd->ffseq;
-
- for (p = 0; p < len - 6; p++) {
- if ((data[0 + p] == 0xff)
- && (data[1 + p] == 0xff)
- && (data[2 + p] == 0x00)
- && (data[3 + p] == 0xff)
- && (data[4 + p] == 0x96)) {
-
- /* start of frame */
- if (sd->ag_cnt >= 0 && p > 28) {
- sd->lum_sum += data[p - 23];
- if (--sd->ag_cnt < 0) {
- sd->ag_cnt = AG_CNT_START;
- atomic_set(&sd->avg_lum,
- sd->lum_sum / AG_CNT_START);
- sd->lum_sum = 0;
- atomic_set(&sd->do_gain, 1);
- }
- }
+ unsigned char *sof;
+
+ sof = pac_find_sof(gspca_dev, data, len);
+ if (sof) {
+ unsigned char tmpbuf[4];
+ int n, lum_offset, footer_length;
+
+ if (sd->sensor == SENSOR_PAC7302) {
+ /* 6 bytes after the FF D9 EOF marker a number of lumination
+ bytes are send corresponding to different parts of the
+ image, the 14th and 15th byte after the EOF seem to
+ correspond to the center of the image */
+ lum_offset = 61 + sizeof pac_sof_marker;
+ footer_length = 74;
+ } else {
+ lum_offset = 24 + sizeof pac_sof_marker;
+ footer_length = 26;
+ }
- /* copy the end of data to the current frame */
+ /* Finish decoding current frame */
+ n = (sof - data) - (footer_length + sizeof pac_sof_marker);
+ if (n < 0) {
+ frame->data_end += n;
+ n = 0;
+ }
+ frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ data, n);
+ if (gspca_dev->last_packet_type != DISCARD_PACKET &&
+ frame->data_end[-2] == 0xff &&
+ frame->data_end[-1] == 0xd9)
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
- data, p);
-
- /* put the JPEG header in the new frame */
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
- (unsigned char *) pac7311_jpeg_header,
- 12);
+ NULL, 0);
+
+ n = sof - data;
+ len -= n;
+ data = sof;
+
+ /* Get average lumination */
+ if (gspca_dev->last_packet_type == LAST_PACKET &&
+ n >= lum_offset)
+ atomic_set(&sd->avg_lum, data[-lum_offset] +
+ data[-lum_offset + 1]);
+ else
+ atomic_set(&sd->avg_lum, -1);
+
+ /* Start the new frame with the jpeg header */
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
+ if (sd->sensor == SENSOR_PAC7302) {
+ /* The PAC7302 has the image rotated 90 degrees */
+ tmpbuf[0] = gspca_dev->width >> 8;
+ tmpbuf[1] = gspca_dev->width & 0xff;
+ tmpbuf[2] = gspca_dev->height >> 8;
+ tmpbuf[3] = gspca_dev->height & 0xff;
+ } else {
tmpbuf[0] = gspca_dev->height >> 8;
tmpbuf[1] = gspca_dev->height & 0xff;
tmpbuf[2] = gspca_dev->width >> 8;
tmpbuf[3] = gspca_dev->width & 0xff;
- gspca_frame_add(gspca_dev, INTER_PACKET, frame,
- tmpbuf, 4);
- gspca_frame_add(gspca_dev, INTER_PACKET, frame,
- (unsigned char *) &pac7311_jpeg_header[16],
- PAC7311_JPEG_HEADER_SIZE - 16);
-
- data += p + 7;
- len -= p + 7;
- ffseq = 0;
- break;
}
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+ pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
}
-
- /* remove the 'ff ff ff xx' sequences */
- switch (ffseq) {
- case 3:
- data += 1;
- len -= 1;
- break;
- case 2:
- if (data[0] == 0xff) {
- data += 2;
- len -= 2;
- frame->data_end -= 2;
- }
- break;
- case 1:
- if (data[0] == 0xff
- && data[1] == 0xff) {
- data += 3;
- len -= 3;
- frame->data_end -= 1;
- }
- break;
- }
- for (i = 0; i < len - 4; i++) {
- if (data[i] == 0xff
- && data[i + 1] == 0xff
- && data[i + 2] == 0xff) {
- memmove(&data[i], &data[i + 4], len - i - 4);
- len -= 4;
- }
- }
- ffseq = 0;
- if (data[len - 4] == 0xff) {
- if (data[len - 3] == 0xff
- && data[len - 2] == 0xff) {
- len -= 4;
- }
- } else if (data[len - 3] == 0xff) {
- if (data[len - 2] == 0xff
- && data[len - 1] == 0xff)
- ffseq = 3;
- } else if (data[len - 2] == 0xff) {
- if (data[len - 1] == 0xff)
- ffseq = 2;
- } else if (data[len - 1] == 0xff)
- ffseq = 1;
- sd->ffseq = ffseq;
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-/* sd->brightness = reg_r(gspca_dev, 0x08);
- return sd->brightness; */
-/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
-}
-
-
-
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
- setbrightness(gspca_dev);
+ setbrightcont(gspca_dev);
return 0;
}
@@ -644,7 +892,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
@@ -654,8 +901,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
- if (gspca_dev->streaming)
- setcontrast(gspca_dev);
+ if (gspca_dev->streaming) {
+ if (sd->sensor == SENSOR_PAC7302)
+ setbrightcont(gspca_dev);
+ else
+ setcontrast(gspca_dev);
+ }
return 0;
}
@@ -663,7 +914,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
-/* getcontrast(gspca_dev); */
*val = sd->contrast;
return 0;
}
@@ -682,18 +932,66 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
-/* getcolors(gspca_dev); */
*val = sd->colors;
return 0;
}
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->gain = val;
+ if (gspca_dev->streaming)
+ setgain(gspca_dev);
+ return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->gain;
+ return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->exposure = val;
+ if (gspca_dev->streaming)
+ setexposure(gspca_dev);
+ return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->exposure;
+ return 0;
+}
+
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
- if (gspca_dev->streaming)
- setautogain(gspca_dev);
+ /* when switching to autogain set defaults to make sure
+ we are on a valid point of the autogain gain /
+ exposure knee graph, and give this change time to
+ take effect before doing autogain. */
+ if (sd->autogain) {
+ sd->exposure = EXPOSURE_DEF;
+ sd->gain = GAIN_DEF;
+ if (gspca_dev->streaming) {
+ sd->autogain_ignore_frames =
+ PAC_AUTOGAIN_IGNORE_FRAMES;
+ setexposure(gspca_dev);
+ setgain(gspca_dev);
+ }
+ }
+
return 0;
}
@@ -705,30 +1003,68 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->hflip = val;
+ if (gspca_dev->streaming)
+ sethvflip(gspca_dev);
+ return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->hflip;
+ return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->vflip = val;
+ if (gspca_dev->streaming)
+ sethvflip(gspca_dev);
+ return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->vflip;
+ return 0;
+}
+
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.dq_callback = do_autogain,
};
/* -- module initialisation -- */
static __devinitdata struct usb_device_id device_table[] = {
- {USB_DEVICE(0x093a, 0x2600)},
- {USB_DEVICE(0x093a, 0x2601)},
- {USB_DEVICE(0x093a, 0x2603)},
- {USB_DEVICE(0x093a, 0x2608)},
- {USB_DEVICE(0x093a, 0x260e)},
- {USB_DEVICE(0x093a, 0x260f)},
- {USB_DEVICE(0x093a, 0x2621)},
+ {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
+ {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
+ {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
+ {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
@@ -746,6 +1082,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
new file mode 100644
index 00000000000..34d4b1494cd
--- /dev/null
+++ b/drivers/media/video/gspca/pac_common.h
@@ -0,0 +1,60 @@
+/*
+ * Pixart PAC207BCA / PAC73xx common functions
+ *
+ * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.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
+ * 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
+ *
+ */
+
+/* We calculate the autogain at the end of the transfer of a frame, at this
+ moment a frame with the old settings is being transmitted, and a frame is
+ being captured with the old settings. So if we adjust the autogain we must
+ ignore atleast the 2 next frames for the new settings to come into effect
+ before doing any other adjustments */
+#define PAC_AUTOGAIN_IGNORE_FRAMES 3
+
+static const unsigned char pac_sof_marker[5] =
+ { 0xff, 0xff, 0x00, 0xff, 0x96 };
+
+static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev,
+ unsigned char *m, int len)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+
+ /* Search for the SOF marker (fixed part) in the header */
+ for (i = 0; i < len; i++) {
+ if (m[i] == pac_sof_marker[sd->sof_read]) {
+ sd->sof_read++;
+ if (sd->sof_read == sizeof(pac_sof_marker)) {
+ PDEBUG(D_FRAM,
+ "SOF found, bytes to analyze: %u."
+ " Frame starts at byte #%u",
+ len, i + 1);
+ sd->sof_read = 0;
+ return m + i + 1;
+ }
+ } else {
+ sd->sof_read = 0;
+ }
+ }
+
+ return NULL;
+}
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 11210c71f66..6c69bc7778f 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -20,6 +20,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* Some documentation on known sonixb registers:
+
+Reg Use
+0x10 high nibble red gain low nibble blue gain
+0x11 low nibble green gain
+0x12 hstart
+0x13 vstart
+0x15 hsize (hsize = register-value * 16)
+0x16 vsize (vsize = register-value * 16)
+0x17 bit 0 toggle compression quality (according to sn9c102 driver)
+0x18 bit 7 enables compression, bit 4-5 set image down scaling:
+ 00 scale 1, 01 scale 1/2, 10, scale 1/4
+0x19 high-nibble is sensor clock divider, changes exposure on sensors which
+ use a clock generated by the bridge. Some sensors have their own clock.
+0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
+0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
+0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
+0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
+*/
+
#define MODULE_NAME "sonixb"
#include "gspca.h"
@@ -31,10 +51,8 @@ MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
-
- struct sd_desc sd_desc; /* our nctrls differ dependend upon the
- sensor, so we use a per cam copy */
atomic_t avg_lum;
+ int prev_avg_lum;
unsigned char gain;
unsigned char exposure;
@@ -44,8 +62,12 @@ struct sd {
unsigned char frames_to_drop;
unsigned char freq; /* light freq filter setting */
- unsigned char fr_h_sz; /* size of frame header */
- char sensor; /* Type of image sensor chip */
+ __u8 bridge; /* Type of bridge */
+#define BRIDGE_101 0
+#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
+#define BRIDGE_103 1
+
+ __u8 sensor; /* Type of image sensor chip */
#define SENSOR_HV7131R 0
#define SENSOR_OV6650 1
#define SENSOR_OV7630 2
@@ -53,16 +75,35 @@ struct sd {
#define SENSOR_PAS202 4
#define SENSOR_TAS5110 5
#define SENSOR_TAS5130CXX 6
- char sensor_has_gain;
- __u8 sensor_addr;
__u8 reg11;
};
-/* flags used in the device id table */
+typedef const __u8 sensor_init_t[8];
+
+struct sensor_data {
+ const __u8 *bridge_init[2];
+ int bridge_init_size[2];
+ sensor_init_t *sensor_init;
+ int sensor_init_size;
+ sensor_init_t *sensor_bridge_init[2];
+ int sensor_bridge_init_size[2];
+ int flags;
+ unsigned ctrl_dis;
+ __u8 sensor_addr;
+};
+
+/* sensor_data flags */
#define F_GAIN 0x01 /* has gain */
-#define F_AUTO 0x02 /* has autogain */
-#define F_SIF 0x04 /* sif or vga */
-#define F_H18 0x08 /* long (18 b) or short (12 b) frame header */
+#define F_SIF 0x02 /* sif or vga */
+
+/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
+#define MODE_RAW 0x10 /* raw bayer mode */
+#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
+
+/* ctrl_dis helper macros */
+#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
+#define NO_FREQ (1 << FREQ_IDX)
+#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
#define COMP2 0x8f
#define COMP 0xc7 /* 0x87 //0x07 */
@@ -73,6 +114,18 @@ struct sd {
#define SYS_CLK 0x04
+#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
+ sensor_3, _flags, _ctrl_dis, _sensor_addr) \
+{ \
+ .bridge_init = { bridge_1, bridge_3 }, \
+ .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
+ .sensor_init = sensor, \
+ .sensor_init_size = sizeof(sensor), \
+ .sensor_bridge_init = { sensor_1, sensor_3,}, \
+ .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
+ .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
+}
+
/* We calculate the autogain at the end of the transfer of a frame, at this
moment a frame with the old settings is being transmitted, and a frame is
being captured with the old settings. So if we adjust the autogain we must
@@ -95,6 +148,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
{
{
.id = V4L2_CID_BRIGHTNESS,
@@ -109,6 +163,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setbrightness,
.get = sd_getbrightness,
},
+#define GAIN_IDX 1
{
{
.id = V4L2_CID_GAIN,
@@ -124,6 +179,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setgain,
.get = sd_getgain,
},
+#define EXPOSURE_IDX 2
{
{
.id = V4L2_CID_EXPOSURE,
@@ -140,6 +196,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setexposure,
.get = sd_getexposure,
},
+#define AUTOGAIN_IDX 3
{
{
.id = V4L2_CID_AUTOGAIN,
@@ -155,6 +212,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+#define FREQ_IDX 4
{
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -172,31 +230,56 @@ static struct ctrl sd_ctrls[] = {
};
static struct v4l2_pix_format vga_mode[] = {
- {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120,
.colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 2 | MODE_RAW},
+ {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 160 * 120 * 5 / 4,
+ .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2},
{320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 320,
- .sizeimage = 320 * 240,
+ .sizeimage = 320 * 240 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
{640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 640,
- .sizeimage = 640 * 480,
+ .sizeimage = 640 * 480 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
};
static struct v4l2_pix_format sif_mode[] = {
- {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 160 * 120,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
+ {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 160 * 120 * 5 / 4,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1 | MODE_REDUCED_SIF},
+ {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 176,
.sizeimage = 176 * 144,
.colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1 | MODE_RAW},
+ {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ .bytesperline = 176,
+ .sizeimage = 176 * 144 * 5 / 4,
+ .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
+ {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 5 / 4,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0 | MODE_REDUCED_SIF},
{352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 352,
- .sizeimage = 352 * 288,
+ .sizeimage = 352 * 288 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
};
@@ -204,7 +287,7 @@ static struct v4l2_pix_format sif_mode[] = {
static const __u8 initHv7131[] = {
0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
0x28, 0x1e, 0x60, 0x8a, 0x20,
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
};
@@ -218,8 +301,8 @@ static const __u8 hv7131_sensor_init[][8] = {
static const __u8 initOv6650[] = {
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
- 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
+ 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
+ 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
};
static const __u8 ov6650_sensor_init[][8] =
{
@@ -257,15 +340,15 @@ static const __u8 ov6650_sensor_init[][8] =
static const __u8 initOv7630[] = {
0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
- 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
+ 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
0x28, 0x1e, /* H & V sizes r15 .. r16 */
- 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
+ 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
};
static const __u8 initOv7630_3[] = {
0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
- 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
+ 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
0x28, 0x1e, /* H & V sizes r15 .. r16 */
0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
@@ -294,47 +377,65 @@ static const __u8 ov7630_sensor_init[][8] = {
{0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
};
+static const __u8 ov7630_sensor_init_3[][8] = {
+ {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
+};
+
static const __u8 initPas106[] = {
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00,
- 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
- 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
- 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
+ 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
+ 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
+ 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
};
/* compression 0x86 mckinit1 0x2b */
-static const __u8 pas106_data[][2] = {
- {0x02, 0x04}, /* Pixel Clock Divider 6 */
- {0x03, 0x13}, /* Frame Time MSB */
-/* {0x03, 0x12}, * Frame Time MSB */
- {0x04, 0x06}, /* Frame Time LSB */
-/* {0x04, 0x05}, * Frame Time LSB */
- {0x05, 0x65}, /* Shutter Time Line Offset */
-/* {0x05, 0x6d}, * Shutter Time Line Offset */
-/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
- {0x06, 0xcd}, /* Shutter Time Pixel Offset */
- {0x07, 0xc1}, /* Black Level Subtract Sign */
-/* {0x07, 0x00}, * Black Level Subtract Sign */
- {0x08, 0x06}, /* Black Level Subtract Level */
- {0x08, 0x06}, /* Black Level Subtract Level */
-/* {0x08, 0x01}, * Black Level Subtract Level */
- {0x09, 0x05}, /* Color Gain B Pixel 5 a */
- {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
- {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
- {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
- {0x0d, 0x00}, /* Color GainH Pixel */
- {0x0e, 0x0e}, /* Global Gain */
- {0x0f, 0x00}, /* Contrast */
- {0x10, 0x06}, /* H&V synchro polarity */
- {0x11, 0x06}, /* ?default */
- {0x12, 0x06}, /* DAC scale */
- {0x14, 0x02}, /* ?default */
- {0x13, 0x01}, /* Validate Settings */
+static const __u8 pas106_sensor_init[][8] = {
+ /* Pixel Clock Divider 6 */
+ { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
+ /* Frame Time MSB (also seen as 0x12) */
+ { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
+ /* Frame Time LSB (also seen as 0x05) */
+ { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ /* Shutter Time Line Offset (also seen as 0x6d) */
+ { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
+ /* Shutter Time Pixel Offset (also seen as 0xb1) */
+ { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
+ /* Black Level Subtract Sign (also seen 0x00) */
+ { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
+ /* Black Level Subtract Level (also seen 0x01) */
+ { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ /* Color Gain B Pixel 5 a */
+ { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
+ /* Color Gain G1 Pixel 1 5 */
+ { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
+ /* Color Gain G2 Pixel 1 0 5 */
+ { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
+ /* Color Gain R Pixel 3 1 */
+ { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
+ /* Color GainH Pixel */
+ { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
+ /* Global Gain */
+ { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
+ /* Contrast */
+ { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
+ /* H&V synchro polarity */
+ { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ /* ?default */
+ { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ /* DAC scale */
+ { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
+ /* ?default */
+ { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
+ /* Validate Settings */
+ { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
};
+
static const __u8 initPas202[] = {
0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
- 0x28, 0x1e, 0x28, 0x89, 0x30,
+ 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
+ 0x28, 0x1e, 0x28, 0x89, 0x20,
0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
};
static const __u8 pas202_sensor_init[][8] = {
@@ -364,7 +465,7 @@ static const __u8 pas202_sensor_init[][8] = {
static const __u8 initTas5110[] = {
0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
- 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
+ 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
0x16, 0x12, 0x60, 0x86, 0x2b,
0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
};
@@ -377,7 +478,7 @@ static const __u8 tas5110_sensor_init[][8] = {
static const __u8 initTas5130[] = {
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
- 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
+ 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
0x28, 0x1e, 0x60, COMP, MCK_INIT,
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
};
@@ -389,6 +490,21 @@ static const __u8 tas5130_sensor_init[][8] = {
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
};
+static struct sensor_data sensor_data[] = {
+SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
+SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
+SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
+ F_GAIN, 0, 0x21),
+SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
+ 0),
+SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
+ NO_EXPO|NO_FREQ, 0),
+SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
+ NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
+ 0),
+};
+
/* get one byte in gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
__u16 value)
@@ -409,7 +525,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
int len)
{
#ifdef GSPCA_DEBUG
- if (len > sizeof gspca_dev->usb_buf) {
+ if (len > USB_BUF_SZ) {
PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
return;
}
@@ -425,26 +541,6 @@ static void reg_w(struct gspca_dev *gspca_dev,
500);
}
-static void reg_w_big(struct gspca_dev *gspca_dev,
- __u16 value,
- const __u8 *buffer,
- int len)
-{
- __u8 *tmpbuf;
-
- tmpbuf = kmalloc(len, GFP_KERNEL);
- memcpy(tmpbuf, buffer, len);
- usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- 0x08, /* request */
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value,
- 0, /* index */
- tmpbuf, len,
- 500);
- kfree(tmpbuf);
-}
-
static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
{
int retry = 60;
@@ -487,7 +583,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
{0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
/* change reg 0x06 */
- i2cOV[1] = sd->sensor_addr;
+ i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
i2cOV[3] = sd->brightness;
if (i2c_w(gspca_dev, i2cOV) < 0)
goto err;
@@ -545,9 +641,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
goto err;
break;
}
- case SENSOR_TAS5110:
- /* FIXME figure out howto control brightness on TAS5110 */
- break;
}
return;
err:
@@ -577,7 +670,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
case SENSOR_OV7630: {
__u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
- i2c[1] = sd->sensor_addr;
+ i2c[1] = sensor_data[sd->sensor].sensor_addr;
i2c[3] = gain >> 2;
if (i2c_w(gspca_dev, i2c) < 0)
goto err;
@@ -604,7 +697,7 @@ static void setgain(struct gspca_dev *gspca_dev)
rgb_value = gain;
reg_w(gspca_dev, 0x11, &rgb_value, 1);
- if (sd->sensor_has_gain)
+ if (sensor_data[sd->sensor].flags & F_GAIN)
setsensorgain(gspca_dev);
}
@@ -665,6 +758,11 @@ static void setexposure(struct gspca_dev *gspca_dev)
else if (reg11 > 16)
reg11 = 16;
+ /* In 640x480, if the reg11 has less than 3, the image is
+ unstable (not enough bandwidth). */
+ if (gspca_dev->width == 640 && reg11 < 3)
+ reg11 = 3;
+
/* frame exposure time in ms = 1000 * reg11 / 30 ->
reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
@@ -678,13 +776,8 @@ static void setexposure(struct gspca_dev *gspca_dev)
else if (reg10 > reg10_max)
reg10 = reg10_max;
- /* In 640x480, if the reg11 has less than 3, the image is
- unstable (not enough bandwidth). */
- if (gspca_dev->width == 640 && reg11 < 3)
- reg11 = 3;
-
/* Write reg 10 and reg11 low nibble */
- i2c[1] = sd->sensor_addr;
+ i2c[1] = sensor_data[sd->sensor].sensor_addr;
i2c[3] = reg10;
i2c[4] |= reg11 - 1;
@@ -724,7 +817,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
? 0x4f : 0x8a;
break;
}
- i2c[1] = sd->sensor_addr;
+ i2c[1] = sensor_data[sd->sensor].sensor_addr;
if (i2c_w(gspca_dev, i2c) < 0)
PDEBUG(D_ERR, "i2c error setfreq");
break;
@@ -757,30 +850,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
- int sif = 0;
- /* nctrls depends upon the sensor, so we use a per cam copy */
- memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
- gspca_dev->sd_desc = &sd->sd_desc;
+ reg_r(gspca_dev, 0x00);
+ if (gspca_dev->usb_buf[0] != 0x10)
+ return -ENODEV;
/* copy the webcam info from the device id */
- sd->sensor = (id->driver_info >> 24) & 0xff;
- if (id->driver_info & (F_GAIN << 16))
- sd->sensor_has_gain = 1;
- if (id->driver_info & (F_AUTO << 16))
- sd->sd_desc.dq_callback = do_autogain;
- if (id->driver_info & (F_SIF << 16))
- sif = 1;
- if (id->driver_info & (F_H18 << 16))
- sd->fr_h_sz = 18; /* size of frame header */
- else
- sd->fr_h_sz = 12;
- sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff;
- sd->sensor_addr = id->driver_info & 0xff;
+ sd->sensor = id->driver_info >> 8;
+ sd->bridge = id->driver_info & 0xff;
+ gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
cam = &gspca_dev->cam;
cam->epaddr = 0x01;
- if (!sif) {
+ if (!(sensor_data[sd->sensor].flags & F_SIF)) {
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
} else {
@@ -790,157 +872,98 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->brightness = BRIGHTNESS_DEF;
sd->gain = GAIN_DEF;
sd->exposure = EXPOSURE_DEF;
- sd->autogain = AUTOGAIN_DEF;
+ if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
+ sd->autogain = 0; /* Disable do_autogain callback */
+ else
+ sd->autogain = AUTOGAIN_DEF;
sd->freq = FREQ_DEF;
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
- reg_r(gspca_dev, 0x00);
- if (gspca_dev->usb_buf[0] != 0x10)
- return -ENODEV;
- return 0;
-}
+ const __u8 stop = 0x09; /* Disable stream turn of LED */
-static void pas106_i2cinit(struct gspca_dev *gspca_dev)
-{
- int i;
- const __u8 *data;
- __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
-
- i = ARRAY_SIZE(pas106_data);
- data = pas106_data[0];
- while (--i >= 0) {
- memcpy(&i2c1[2], data, 2);
- /* copy 2 bytes from the template */
- if (i2c_w(gspca_dev, i2c1) < 0)
- PDEBUG(D_ERR, "i2c error pas106");
- data += 2;
- }
+ reg_w(gspca_dev, 0x01, &stop, 1);
+
+ return 0;
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int mode, l = 0x1f;
+ struct cam *cam = &gspca_dev->cam;
+ int mode, l;
const __u8 *sn9c10x;
- __u8 reg17_19[3];
-
- mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+ __u8 reg12_19[8];
+
+ mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
+ sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
+ l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
+ memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
+ reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
+ /* Special cases where reg 17 and or 19 value depends on mode */
switch (sd->sensor) {
- case SENSOR_HV7131R:
- sn9c10x = initHv7131;
- reg17_19[0] = 0x60;
- reg17_19[1] = (mode << 4) | 0x8a;
- reg17_19[2] = 0x20;
- break;
- case SENSOR_OV6650:
- sn9c10x = initOv6650;
- reg17_19[0] = 0x68;
- reg17_19[1] = (mode << 4) | 0x8b;
- reg17_19[2] = 0x20;
- break;
- case SENSOR_OV7630:
- if (sd->fr_h_sz == 18) { /* SN9C103 */
- sn9c10x = initOv7630_3;
- l = sizeof initOv7630_3;
- } else
- sn9c10x = initOv7630;
- reg17_19[0] = 0x68;
- reg17_19[1] = (mode << 4) | COMP2;
- reg17_19[2] = MCK_INIT1;
- break;
- case SENSOR_PAS106:
- sn9c10x = initPas106;
- reg17_19[0] = 0x24; /* 0x28 */
- reg17_19[1] = (mode << 4) | COMP1;
- reg17_19[2] = MCK_INIT1;
- break;
case SENSOR_PAS202:
- sn9c10x = initPas202;
- reg17_19[0] = mode ? 0x24 : 0x20;
- reg17_19[1] = (mode << 4) | 0x89;
- reg17_19[2] = 0x20;
+ reg12_19[5] = mode ? 0x24 : 0x20;
break;
- case SENSOR_TAS5110:
- sn9c10x = initTas5110;
- reg17_19[0] = 0x60;
- reg17_19[1] = (mode << 4) | 0x86;
- reg17_19[2] = 0x2b; /* 0xf3; */
- break;
- default:
-/* case SENSOR_TAS5130CXX: */
- sn9c10x = initTas5130;
- reg17_19[0] = 0x60;
- reg17_19[1] = (mode << 4) | COMP;
- reg17_19[2] = mode ? 0x23 : 0x43;
+ case SENSOR_TAS5130CXX:
+ /* probably not mode specific at all most likely the upper
+ nibble of 0x19 is exposure (clock divider) just as with
+ the tas5110, we need someone to test this. */
+ reg12_19[7] = mode ? 0x23 : 0x43;
break;
}
+ /* Disable compression when the raw bayer format has been selected */
+ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
+ reg12_19[6] &= ~0x80;
+
+ /* Vga mode emulation on SIF sensor? */
+ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
+ reg12_19[0] += 16; /* 0x12: hstart adjust */
+ reg12_19[1] += 24; /* 0x13: vstart adjust */
+ reg12_19[3] = 320 / 16; /* 0x15: hsize */
+ reg12_19[4] = 240 / 16; /* 0x16: vsize */
+ }
/* reg 0x01 bit 2 video transfert on */
reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
/* reg 0x17 SensorClk enable inv Clk 0x60 */
reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
/* Set the registers from the template */
- reg_w_big(gspca_dev, 0x01, sn9c10x, l);
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- i2c_w_vector(gspca_dev, hv7131_sensor_init,
- sizeof hv7131_sensor_init);
- break;
- case SENSOR_OV6650:
- i2c_w_vector(gspca_dev, ov6650_sensor_init,
- sizeof ov6650_sensor_init);
- break;
- case SENSOR_OV7630:
- i2c_w_vector(gspca_dev, ov7630_sensor_init,
- sizeof ov7630_sensor_init);
- if (sd->fr_h_sz == 18) { /* SN9C103 */
- const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
- 0x00, 0x00, 0x10 };
- i2c_w(gspca_dev, i2c);
- }
- break;
- case SENSOR_PAS106:
- pas106_i2cinit(gspca_dev);
- break;
- case SENSOR_PAS202:
- i2c_w_vector(gspca_dev, pas202_sensor_init,
- sizeof pas202_sensor_init);
- break;
- case SENSOR_TAS5110:
- i2c_w_vector(gspca_dev, tas5110_sensor_init,
- sizeof tas5110_sensor_init);
- break;
- default:
-/* case SENSOR_TAS5130CXX: */
- i2c_w_vector(gspca_dev, tas5130_sensor_init,
- sizeof tas5130_sensor_init);
- break;
- }
+ reg_w(gspca_dev, 0x01, sn9c10x, l);
+
+ /* Init the sensor */
+ i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
+ sensor_data[sd->sensor].sensor_init_size);
+ if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
+ i2c_w_vector(gspca_dev,
+ sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
+ sensor_data[sd->sensor].sensor_bridge_init_size[
+ sd->bridge]);
+
/* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
- reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
+ reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
/* compression register */
- reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
+ reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
/* H_start */
- reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
+ reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
/* V_START */
- reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
+ reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
/* reset 0x17 SensorClk enable inv Clk 0x60 */
/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
- reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
+ reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
/*MCKSIZE ->3 */ /*fixme: not ov7630*/
- reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
+ reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
/* Enable video transfert */
reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
/* Compression */
- reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
+ reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
msleep(20);
sd->reg11 = -1;
@@ -953,22 +976,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
sd->frames_to_drop = 0;
sd->autogain_ignore_frames = 0;
atomic_set(&sd->avg_lum, -1);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
- __u8 ByteSend;
-
- ByteSend = 0x09; /* 0X00 */
- reg_w(gspca_dev, 0x01, &ByteSend, 1);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
+ sd_init(gspca_dev);
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -978,6 +991,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
{
int i;
struct sd *sd = (struct sd *) gspca_dev;
+ struct cam *cam = &gspca_dev->cam;
/* frames start with:
* ff ff 00 c4 c4 96 synchro
@@ -998,20 +1012,31 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
&& data[5 + i] == 0x96) { /* start of frame */
int lum = -1;
int pkt_type = LAST_PACKET;
+ int fr_h_sz = (sd->bridge == BRIDGE_103) ?
+ 18 : 12;
- if (len - i < sd->fr_h_sz) {
+ if (len - i < fr_h_sz) {
PDEBUG(D_STREAM, "packet too short to"
" get avg brightness");
- } else if (sd->fr_h_sz == 12) {
- lum = data[i + 8] + (data[i + 9] << 8);
- } else {
+ } else if (sd->bridge == BRIDGE_103) {
lum = data[i + 9] +
(data[i + 10] << 8);
+ } else {
+ lum = data[i + 8] + (data[i + 9] << 8);
}
- if (lum == 0) {
+ /* When exposure changes midway a frame we
+ get a lum of 0 in this case drop 2 frames
+ as the frames directly after an exposure
+ change have an unstable image. Sometimes lum
+ *really* is 0 (cam used in low light with
+ low exposure setting), so do not drop frames
+ if the previous lum was 0 too. */
+ if (lum == 0 && sd->prev_avg_lum != 0) {
lum = -1;
sd->frames_to_drop = 2;
- }
+ sd->prev_avg_lum = 0;
+ } else
+ sd->prev_avg_lum = lum;
atomic_set(&sd->avg_lum, lum);
if (sd->frames_to_drop) {
@@ -1021,14 +1046,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
frame = gspca_frame_add(gspca_dev, pkt_type,
frame, data, 0);
- data += i + sd->fr_h_sz;
- len -= i + sd->fr_h_sz;
+ data += i + fr_h_sz;
+ len -= i + fr_h_sz;
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, len);
return;
}
}
}
+
+ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
+ /* In raw mode we sometimes get some garbage after the frame
+ ignore this */
+ int used = frame->data_end - frame->data;
+ int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
+
+ if (used + len > size)
+ len = size - used;
+ }
+
gspca_frame_add(gspca_dev, INTER_PACKET,
frame, data, len);
}
@@ -1162,58 +1198,45 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
+ .dq_callback = do_autogain,
};
/* -- module initialisation -- */
-#define SFCI(sensor, flags, nctrls, i2c_addr) \
- .driver_info = (SENSOR_ ## sensor << 24) \
- | ((flags) << 16) \
- | ((nctrls) << 8) \
- | (i2c_addr)
+#define SB(sensor, bridge) \
+ .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
+
+
static __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_SN9C102
- {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */
- SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
- {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */
- SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
- {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */
- SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
- {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */
- SFCI(PAS106, F_SIF, 2, 0)},
- {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */
- SFCI(PAS106, F_SIF, 2, 0)},
+ {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
+ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
+ {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
+ {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
#endif
- {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */
- SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)},
-#ifndef CONFIG_USB_SN9C102
- {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */
- SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
- {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */
- SFCI(TAS5130CXX, 0, 2, 0)},
- {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */
- SFCI(TAS5130CXX, 0, 2, 0)},
- {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */
- SFCI(PAS202, 0, 2, 0)},
- {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */
- SFCI(PAS106, F_SIF, 2, 0)},
- {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */
- SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
- {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */
- SFCI(HV7131R, 0, 2, 0)},
- {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */
- SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
- {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */
- SFCI(PAS202, F_H18, 2, 0)},
- {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */
- SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)},
+ {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
+ {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
+ {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
+ {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
+ {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
+ {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
#endif
+ {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
+#endif
+ {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
+#endif
+ {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
@@ -1231,6 +1254,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 245a30ec5fb..53cb82d9e7c 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -39,6 +39,7 @@ struct sd {
unsigned char contrast;
unsigned char colors;
unsigned char autogain;
+ __u8 vflip; /* ov7630 only */
signed char ag_cnt;
#define AG_CNT_START 13
@@ -54,8 +55,10 @@ struct sd {
#define SENSOR_HV7131R 0
#define SENSOR_MI0360 1
#define SENSOR_MO4000 2
-#define SENSOR_OV7648 3
-#define SENSOR_OV7660 4
+#define SENSOR_OM6802 3
+#define SENSOR_OV7630 4
+#define SENSOR_OV7648 5
+#define SENSOR_OV7660 6
unsigned char i2c_base;
};
@@ -68,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
{
@@ -76,7 +81,8 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
- .maximum = 0xffff,
+#define BRIGHTNESS_MAX 0xffff
+ .maximum = BRIGHTNESS_MAX,
.step = 1,
#define BRIGHTNESS_DEF 0x7fff
.default_value = BRIGHTNESS_DEF,
@@ -90,7 +96,8 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 127,
+#define CONTRAST_MAX 127
+ .maximum = CONTRAST_MAX,
.step = 1,
#define CONTRAST_DEF 63
.default_value = CONTRAST_DEF,
@@ -104,14 +111,15 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Color",
.minimum = 0,
- .maximum = 255,
+ .maximum = 64,
.step = 1,
-#define COLOR_DEF 127
+#define COLOR_DEF 32
.default_value = COLOR_DEF,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
+#define AUTOGAIN_IDX 3
{
{
.id = V4L2_CID_AUTOGAIN,
@@ -126,12 +134,28 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+/* ov7630 only */
+#define VFLIP_IDX 4
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vflip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define VFLIP_DEF 1
+ .default_value = VFLIP_DEF,
+ },
+ .set = sd_setvflip,
+ .get = sd_getvflip,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 8 + 590,
+ .sizeimage = 160 * 120 * 4 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 2},
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -180,6 +204,31 @@ static const __u8 sn_mo4000[] = {
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+static const __u8 sn_om6802[] = {
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
+ 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
+ 0xf7
+};
+
+static const __u8 sn_ov7630[] = {
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
static const __u8 sn_ov7648[] = {
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
@@ -207,31 +256,24 @@ static const __u8 *sn_tb[] = {
sn_hv7131,
sn_mi0360,
sn_mo4000,
+ sn_om6802,
+ sn_ov7630,
sn_ov7648,
sn_ov7660
};
-static const __u8 regsn20[] = {
+static const __u8 gamma_def[] = {
0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
};
-static const __u8 regsn20_sn9c325[] = {
- 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
- 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
-};
+/* color matrix and offsets */
static const __u8 reg84[] = {
- 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
- 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
-/* 0x00, 0x00, 0x00, 0x00, 0x00 */
- 0xf7, 0x0f, 0x0a, 0x00, 0x00
+ 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
+ 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
+ 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
+ 0x00, 0x00, 0x00 /* YUV offsets */
};
-static const __u8 reg84_sn9c325[] = {
- 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
- 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
- 0xf8, 0x0f, 0x00, 0x00, 0x00
-};
-
static const __u8 hv7131r_sensor_init[][8] = {
{0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
{0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
@@ -340,6 +382,93 @@ static const __u8 mo4000_sensor_init[][8] = {
{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
{}
};
+static __u8 om6802_sensor_init[][8] = {
+ {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
+ {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
+ {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
+ {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
+/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
+ {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
+ /* white balance & auto-exposure */
+/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
+ * set color mode */
+/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
+ * max AGC value in AE */
+/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
+ * preset AGC */
+/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
+ * preset brightness */
+/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
+ * preset contrast */
+/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
+ * preset gamma */
+ {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
+ /* luminance mode (0x4f = AE) */
+ {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
+ /* preset shutter */
+/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
+ * auto frame rate */
+/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
+
+/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
+/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
+/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
+/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
+ {}
+};
+static const __u8 ov7630_sensor_init[][8] = {
+ {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+/* win: delay 20ms */
+ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+/* win: delay 20ms */
+ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/* win: i2c_r from 00 to 80 */
+ {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
+ {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
+ {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+ {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
+ {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
+ {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
+ {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
+ {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
+ {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
+ {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
+ {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
+ {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
+ {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
+ {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
+ {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+ {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+/* */
+ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/*fixme: + 0x12, 0x04*/
+/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
+ * set by setvflip */
+ {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
+/* */
+ {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
+/* */
+ {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
+/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
+ {}
+};
static const __u8 ov7660_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
/* (delay 20ms) */
@@ -506,10 +635,16 @@ static const __u8 qtable4[] = {
0x29, 0x29, 0x29, 0x29
};
-/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
+/* read <len> bytes to gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
__u16 value, int len)
{
+#ifdef GSPCA_DEBUG
+ if (len > USB_BUF_SZ) {
+ err("reg_r: buffer overflow");
+ return;
+ }
+#endif
usb_control_msg(gspca_dev->dev,
usb_rcvctrlpipe(gspca_dev->dev, 0),
0,
@@ -542,29 +677,20 @@ static void reg_w(struct gspca_dev *gspca_dev,
{
PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
value, buffer[0], buffer[1]);
- if (len <= sizeof gspca_dev->usb_buf) {
- memcpy(gspca_dev->usb_buf, buffer, len);
- usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- 0x08,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, 0,
- gspca_dev->usb_buf, len,
- 500);
- } else {
- __u8 *tmpbuf;
-
- tmpbuf = kmalloc(len, GFP_KERNEL);
- memcpy(tmpbuf, buffer, len);
- usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- 0x08,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, 0,
- tmpbuf, len,
- 500);
- kfree(tmpbuf);
+#ifdef GSPCA_DEBUG
+ if (len > USB_BUF_SZ) {
+ err("reg_w: buffer overflow");
+ return;
}
+#endif
+ memcpy(gspca_dev->usb_buf, buffer, len);
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0x08,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+ value, 0,
+ gspca_dev->usb_buf, len,
+ 500);
}
/* I2C write 1 byte */
@@ -603,6 +729,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
0x08, 0, /* value, index */
gspca_dev->usb_buf, 8,
500);
+ msleep(2);
}
/* read 5 bytes in gspca_dev->usb_buf */
@@ -665,7 +792,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
static const __u8 regd4[] = {0x60, 0x00, 0x00};
reg_w1(gspca_dev, 0xf1, 0x00);
- reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
+ reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
/* configure gpio */
reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
@@ -685,21 +812,41 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
- switch (sd->bridge) {
- case BRIDGE_SN9C325:
+ switch (sd->sensor) {
+ case SENSOR_OM6802:
+ reg_w1(gspca_dev, 0x02, 0x71);
+ reg_w1(gspca_dev, 0x01, 0x42);
+ reg_w1(gspca_dev, 0x17, 0x64);
+ reg_w1(gspca_dev, 0x01, 0x42);
+ break;
+/*jfm: from win trace */
+ case SENSOR_OV7630:
+ reg_w1(gspca_dev, 0x01, 0x61);
+ reg_w1(gspca_dev, 0x17, 0xe2);
+ reg_w1(gspca_dev, 0x01, 0x60);
+ reg_w1(gspca_dev, 0x01, 0x40);
+ break;
+ case SENSOR_OV7648:
reg_w1(gspca_dev, 0x01, 0x43);
reg_w1(gspca_dev, 0x17, 0xae);
reg_w1(gspca_dev, 0x01, 0x42);
break;
+/*jfm: from win trace */
+ case SENSOR_OV7660:
+ reg_w1(gspca_dev, 0x01, 0x61);
+ reg_w1(gspca_dev, 0x17, 0x20);
+ reg_w1(gspca_dev, 0x01, 0x60);
+ reg_w1(gspca_dev, 0x01, 0x40);
+ break;
default:
reg_w1(gspca_dev, 0x01, 0x43);
reg_w1(gspca_dev, 0x17, 0x61);
reg_w1(gspca_dev, 0x01, 0x42);
- }
-
- if (sd->sensor == SENSOR_HV7131R) {
- if (probesensor(gspca_dev) < 0)
- return -ENODEV;
+ if (sd->sensor == SENSOR_HV7131R) {
+ if (probesensor(gspca_dev) < 0)
+ return -ENODEV;
+ }
+ break;
}
return 0;
}
@@ -737,6 +884,40 @@ static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
}
}
+static void om6802_InitSensor(struct gspca_dev *gspca_dev)
+{
+ int i = 0;
+
+ while (om6802_sensor_init[i][0]) {
+ i2c_w8(gspca_dev, om6802_sensor_init[i]);
+ i++;
+ }
+}
+
+static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
+{
+ int i = 0;
+
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
+ i++;
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
+ i++;
+ msleep(20);
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
+ i++;
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
+ i++;
+ msleep(20);
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
+ i++;
+/*jfm:win i2c_r from 00 to 80*/
+
+ while (ov7630_sensor_init[i][0]) {
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]);
+ i++;
+ }
+}
+
static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
{
int i = 0;
@@ -783,11 +964,21 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->autogain = AUTOGAIN_DEF;
sd->ag_cnt = -1;
+ switch (sd->sensor) {
+ case SENSOR_OV7630:
+ case SENSOR_OV7648:
+ case SENSOR_OV7660:
+ gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
+ break;
+ }
+ if (sd->sensor != SENSOR_OV7630)
+ gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
+
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
/* const __u8 *sn9c1xx; */
@@ -810,13 +1001,13 @@ static int sd_open(struct gspca_dev *gspca_dev)
case BRIDGE_SN9C105:
if (regF1 != 0x11)
return -ENODEV;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
case BRIDGE_SN9C120:
if (regF1 != 0x12)
return -ENODEV;
regGpio[1] = 0x70;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
default:
/* case BRIDGE_SN9C110: */
@@ -891,16 +1082,50 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
| ((expoMo10[3] & 0x30) >> 4));
break;
}
+ case SENSOR_OM6802: {
+ __u8 gainOm[] =
+ { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
+
+ if (expo > 0x03ff)
+ expo = 0x03ff;
+ if (expo < 0x0001)
+ expo = 0x0001;
+ gainOm[3] = expo >> 2;
+ i2c_w8(gspca_dev, gainOm);
+ reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
+ PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
+ break;
+ }
}
return expo;
}
+/* this function is used for sensors o76xx only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int val;
+ __u8 reg84_full[0x15];
+
+ memcpy(reg84_full, reg84, sizeof reg84_full);
+ val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */
+ reg84_full[0] = (val + 1) / 2; /* red */
+ reg84_full[2] = val; /* green */
+ reg84_full[4] = (val + 1) / 5; /* blue */
+ val = (sd->brightness - BRIGHTNESS_DEF) * 0x10
+ / BRIGHTNESS_MAX;
+ reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */
+ reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
+}
+
+/* sensor != ov76xx */
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
unsigned int expo;
__u8 k2;
+ k2 = sd->brightness >> 10;
switch (sd->sensor) {
case SENSOR_HV7131R:
expo = sd->brightness << 4;
@@ -915,12 +1140,17 @@ static void setbrightness(struct gspca_dev *gspca_dev)
expo = sd->brightness >> 4;
sd->exposure = setexposure(gspca_dev, expo);
break;
+ case SENSOR_OM6802:
+ expo = sd->brightness >> 6;
+ sd->exposure = setexposure(gspca_dev, expo);
+ k2 = sd->brightness >> 11;
+ break;
}
- k2 = sd->brightness >> 10;
reg_w1(gspca_dev, 0x96, k2);
}
+/* sensor != ov76xx */
static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -937,35 +1167,42 @@ static void setcontrast(struct gspca_dev *gspca_dev)
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- __u8 data;
- int colour;
+ __u8 blue, red;
- colour = sd->colors - 128;
- if (colour > 0)
- data = (colour + 32) & 0x7f; /* blue */
- else
- data = (-colour + 32) & 0x7f; /* red */
- reg_w1(gspca_dev, 0x05, data);
+ if (sd->colors >= 32) {
+ red = 32 + (sd->colors - 32) / 2;
+ blue = 64 - sd->colors;
+ } else {
+ red = sd->colors;
+ blue = 32 + (32 - sd->colors) / 2;
+ }
+ reg_w1(gspca_dev, 0x05, red);
+/* reg_w1(gspca_dev, 0x07, 32); */
+ reg_w1(gspca_dev, 0x06, blue);
}
static void setautogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- case SENSOR_MO4000:
- case SENSOR_MI0360:
- if (sd->autogain)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
- break;
- }
+ if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
+ return;
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
+}
+
+static void setvflip(struct sd *sd)
+{
+ if (sd->sensor != SENSOR_OV7630)
+ return;
+ i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
+ sd->vflip ? 0x82 : 0x02);
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
@@ -975,13 +1212,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
- static const __u8 CE_sn9c325[] =
- { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
+ static const __u8 CE_ov76xx[] =
+ { 0x32, 0xdd, 0x32, 0xdd };
sn9c1xx = sn_tb[(int) sd->sensor];
configure_gpio(gspca_dev, sn9c1xx);
-/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
@@ -994,10 +1230,17 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0xc8, 0x50);
reg_w1(gspca_dev, 0xc9, 0x3c);
reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
- switch (sd->bridge) {
- case BRIDGE_SN9C325:
+ switch (sd->sensor) {
+ case SENSOR_OV7630:
+ reg17 = 0xe2;
+ break;
+ case SENSOR_OV7648:
reg17 = 0xae;
break;
+/*jfm: from win trace */
+ case SENSOR_OV7660:
+ reg17 = 0xa0;
+ break;
default:
reg17 = 0x60;
break;
@@ -1007,20 +1250,14 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
- switch (sd->bridge) {
- case BRIDGE_SN9C325:
- reg_w(gspca_dev, 0x20, regsn20_sn9c325,
- sizeof regsn20_sn9c325);
- for (i = 0; i < 8; i++)
- reg_w(gspca_dev, 0x84, reg84_sn9c325,
- sizeof reg84_sn9c325);
- reg_w1(gspca_dev, 0x9a, 0x0a);
- reg_w1(gspca_dev, 0x99, 0x60);
+ reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
+ for (i = 0; i < 8; i++)
+ reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+ switch (sd->sensor) {
+ case SENSOR_OV7660:
+ reg_w1(gspca_dev, 0x9a, 0x05);
break;
default:
- reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
- for (i = 0; i < 8; i++)
- reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
reg_w1(gspca_dev, 0x9a, 0x08);
reg_w1(gspca_dev, 0x99, 0x59);
break;
@@ -1049,6 +1286,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg1 = 0x06; * 640 clk 24Mz (done) */
}
break;
+ case SENSOR_OM6802:
+ om6802_InitSensor(gspca_dev);
+ reg17 = 0x64; /* 640 MCKSIZE */
+ break;
+ case SENSOR_OV7630:
+ ov7630_InitSensor(gspca_dev);
+ setvflip(sd);
+ reg17 = 0xe2;
+ reg1 = 0x44;
+ break;
case SENSOR_OV7648:
ov7648_InitSensor(gspca_dev);
reg17 = 0xa2;
@@ -1066,16 +1313,18 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg1 = 0x44; */
/* reg1 = 0x46; (done) */
} else {
- reg17 = 0x22; /* 640 MCKSIZE */
- reg1 = 0x06;
+ reg17 = 0xa2; /* 640 */
+ reg1 = 0x44;
}
break;
}
reg_w(gspca_dev, 0xc0, C0, 6);
reg_w(gspca_dev, 0xca, CA, 4);
- switch (sd->bridge) {
- case BRIDGE_SN9C325:
- reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
+ switch (sd->sensor) {
+ case SENSOR_OV7630:
+ case SENSOR_OV7648:
+ case SENSOR_OV7660:
+ reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
break;
default:
reg_w(gspca_dev, 0xce, CE, 4);
@@ -1093,10 +1342,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x18, reg18);
reg_w1(gspca_dev, 0x17, reg17);
- reg_w1(gspca_dev, 0x01, reg1);
- setbrightness(gspca_dev);
- setcontrast(gspca_dev);
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ break;
+ case SENSOR_OV7630:
+ setvflip(sd);
+ /* fall thru */
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
setautogain(gspca_dev);
+ reg_w1(gspca_dev, 0x01, reg1);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1119,6 +1382,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
i2c_w8(gspca_dev, stopmi0360);
data = 0x29;
break;
+ case SENSOR_OV7630:
case SENSOR_OV7648:
data = 0x29;
break;
@@ -1132,15 +1396,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
reg_w1(gspca_dev, 0x01, data);
- reg_w1(gspca_dev, 0xf1, 0x01);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
+ reg_w1(gspca_dev, 0xf1, 0x00);
}
static void do_autogain(struct gspca_dev *gspca_dev)
@@ -1174,6 +1430,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
default:
/* case SENSOR_MO4000: */
/* case SENSOR_MI0360: */
+/* case SENSOR_OM6802: */
expotimes = sd->exposure;
expotimes += (luma_mean - delta) >> 6;
if (expotimes < 0)
@@ -1229,69 +1486,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
-static unsigned int getexposure(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u8 hexpo, mexpo, lexpo;
-
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x25);
- return (gspca_dev->usb_buf[0] << 16)
- | (gspca_dev->usb_buf[1] << 8)
- | gspca_dev->usb_buf[2];
- case SENSOR_MI0360:
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x09);
- return (gspca_dev->usb_buf[0] << 8)
- | gspca_dev->usb_buf[1];
- case SENSOR_MO4000:
- i2c_r5(gspca_dev, 0x0e);
- hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
- mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
- lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
- PDEBUG(D_CONF, "exposure %d",
- (hexpo << 10) | (mexpo << 2) | lexpo);
- return (hexpo << 10) | (mexpo << 2) | lexpo;
- default:
-/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
-/* case SENSOR_OV7660: */
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x04);
- hexpo = gspca_dev->usb_buf[3] & 0x2f;
- lexpo = gspca_dev->usb_buf[0] & 0x02;
- i2c_r5(gspca_dev, 0x08);
- mexpo = gspca_dev->usb_buf[2];
- return (hexpo << 10) | (mexpo << 2) | lexpo;
- }
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- /* hardcoded registers seem not readable */
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- sd->brightness = getexposure(gspca_dev) >> 4;
- break;
- case SENSOR_MI0360:
- sd->brightness = getexposure(gspca_dev) << 4;
- break;
- case SENSOR_MO4000:
- sd->brightness = getexposure(gspca_dev) << 4;
- break;
- }
-}
-
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
- if (gspca_dev->streaming)
- setbrightness(gspca_dev);
+ if (gspca_dev->streaming) {
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setbrightness(gspca_dev);
+ break;
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
+ }
return 0;
}
@@ -1299,7 +1511,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
@@ -1309,8 +1520,19 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
- if (gspca_dev->streaming)
- setcontrast(gspca_dev);
+ if (gspca_dev->streaming) {
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setcontrast(gspca_dev);
+ break;
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
+ }
return 0;
}
@@ -1358,17 +1580,33 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->vflip = val;
+ if (gspca_dev->streaming)
+ setvflip(sd);
+ return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->vflip;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.dq_callback = do_autogain,
};
@@ -1379,8 +1617,9 @@ static const struct sd_desc sd_desc = {
| (SENSOR_ ## sensor << 8) \
| (i2c_addr)
static const __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_SN9C102
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
+ {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
{USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
@@ -1402,19 +1641,23 @@ static const __devinitdata struct usb_device_id device_table[] = {
/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
-/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
+#endif
/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
- {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
-/* bw600.inf:
- {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
+ {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
+/*bw600.inf:*/
+ {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
{USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
-/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
+ {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
-#ifndef CONFIG_USB_SN9C102
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
+#endif
{USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
{USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
@@ -1438,6 +1681,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 17fe2c2a440..bca106c153f 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -645,8 +645,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -660,7 +660,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int err;
@@ -867,6 +867,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
write_vector(gspca_dev, Clicksmart510_defaults);
break;
}
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -880,14 +881,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
gspca_dev->usb_buf[0]);
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1051,11 +1044,9 @@ static struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -1093,6 +1084,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
index 51a3c3429ef..b742f260c7c 100644
--- a/drivers/media/video/gspca/spca501.c
+++ b/drivers/media/video/gspca/spca501.c
@@ -1953,8 +1953,8 @@ error:
return -EINVAL;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1980,7 +1980,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
int mode;
@@ -2012,6 +2012,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
setbrightness(gspca_dev);
setcontrast(gspca_dev);
setcolors(gspca_dev);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -2023,11 +2024,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
static void sd_stop0(struct gspca_dev *gspca_dev)
{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
}
@@ -2120,11 +2116,10 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -2154,6 +2149,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index eda29d60935..b345749213c 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -655,8 +655,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
@@ -688,7 +688,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
int ret;
@@ -733,6 +733,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg_write(dev, 0x5, 0x0, 0x0); */
/* reg_write(dev, 0x5, 0x0, 0x1); */
/* reg_write(dev, 0x5, 0x11, 0x2); */
+ return ret;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -743,11 +744,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
static void sd_stop0(struct gspca_dev *gspca_dev)
{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
/* This maybe reset or power control */
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
@@ -825,11 +821,10 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -855,6 +850,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index f622fa75766..645ee9d44d0 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -313,8 +313,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
@@ -422,7 +422,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u16 norme;
@@ -549,6 +549,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
PDEBUG(D_STREAM, "webcam started");
spca506_GetNormeInput(gspca_dev, &norme, &channel);
spca506_SetNormeInput(gspca_dev, norme, channel);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -560,14 +561,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(dev, 0x03, 0x00, 0x0003);
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -740,11 +733,9 @@ static struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -772,6 +763,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index 699340c17de..63ec902c895 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -1521,14 +1521,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0; /* success */
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
/* write_vector(gspca_dev, spca508_open_data); */
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
int mode;
@@ -1546,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
break;
}
reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1554,15 +1555,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, 0x8112, 0x20);
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1633,11 +1625,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -1667,6 +1657,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index 1073ac3d2ec..020a03c466c 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -32,69 +32,48 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- unsigned short contrast;
- __u8 brightness;
+ __u16 contrast; /* rev72a only */
+#define CONTRAST_MIN 0x0000
+#define CONTRAST_DEF 0x2000
+#define CONTRAST_MAX 0x3fff
+
+ __u16 exposure; /* rev12a only */
+#define EXPOSURE_MIN 1
+#define EXPOSURE_DEF 200
+#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */
+
+ __u8 brightness; /* rev72a only */
+#define BRIGHTNESS_MIN 0
+#define BRIGHTNESS_DEF 32
+#define BRIGHTNESS_MAX 63
+
+ __u8 white; /* rev12a only */
+#define WHITE_MIN 1
+#define WHITE_DEF 0x40
+#define WHITE_MAX 0x7f
+
__u8 autogain;
+#define AUTOGAIN_MIN 0
+#define AUTOGAIN_DEF 1
+#define AUTOGAIN_MAX 1
+
+ __u8 gain; /* rev12a only */
+#define GAIN_MIN 0x0
+#define GAIN_DEF 0x24
+#define GAIN_MAX 0x24
+
+#define EXPO12A_DEF 3
+ __u8 expo12a; /* expo/gain? for rev 12a */
__u8 chip_revision;
+#define Rev012A 0
+#define Rev072A 1
+
signed char ag_cnt;
#define AG_CNT_START 13
};
-/* V4L2 controls supported by the driver */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
-
-static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
- {
- {
- .id = V4L2_CID_BRIGHTNESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 63,
- .step = 1,
- .default_value = 32,
- },
- .set = sd_setbrightness,
- .get = sd_getbrightness,
- },
-#define SD_CONTRAST 1
- {
- {
- .id = V4L2_CID_CONTRAST,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 0x3fff,
- .step = 1,
- .default_value = 0x2000,
- },
- .set = sd_setcontrast,
- .get = sd_getcontrast,
- },
-#define SD_AUTOGAIN 2
- {
- {
- .id = V4L2_CID_AUTOGAIN,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Auto Gain",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- },
- .set = sd_setautogain,
- .get = sd_getautogain,
- },
-};
-
-static struct v4l2_pix_format sif_mode[] = {
+static struct v4l2_pix_format sif_012a_mode[] = {
{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120,
@@ -117,6 +96,29 @@ static struct v4l2_pix_format sif_mode[] = {
.priv = 0},
};
+static struct v4l2_pix_format sif_072a_mode[] = {
+ {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 160 * 120,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 3},
+ {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+ .bytesperline = 176,
+ .sizeimage = 176 * 144,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 2},
+ {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1},
+ {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+ .bytesperline = 352,
+ .sizeimage = 352 * 288,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+};
+
/*
* Initialization data
* I'm not very sure how to split initialization from open data
@@ -143,18 +145,14 @@ static struct v4l2_pix_format sif_mode[] = {
#define SPCA561_INDEX_I2C_BASE 0x8800
#define SPCA561_SNAPBIT 0x20
#define SPCA561_SNAPCTRL 0x40
-enum {
- Rev072A = 0,
- Rev012A,
-};
-static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value)
+static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
{
int ret;
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
0, /* request */
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
if (ret < 0)
@@ -198,12 +196,6 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len, 500);
}
-static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode)
-{
- reg_w_val(gspca_dev->dev, 0x92, 0x8804);
- reg_w_val(gspca_dev->dev, mode, 0x8802);
-}
-
static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
{
int retry = 60;
@@ -212,9 +204,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
DataLow = valeur;
DataHight = valeur >> 8;
- reg_w_val(gspca_dev->dev, reg, 0x8801);
- reg_w_val(gspca_dev->dev, DataLow, 0x8805);
- reg_w_val(gspca_dev->dev, DataHight, 0x8800);
+ reg_w_val(gspca_dev->dev, 0x8801, reg);
+ reg_w_val(gspca_dev->dev, 0x8805, DataLow);
+ reg_w_val(gspca_dev->dev, 0x8800, DataHight);
while (retry--) {
reg_r(gspca_dev, 0x8803, 1);
if (!gspca_dev->usb_buf[0])
@@ -228,14 +220,14 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
__u8 value;
__u8 vallsb;
- reg_w_val(gspca_dev->dev, 0x92, 0x8804);
- reg_w_val(gspca_dev->dev, reg, 0x8801);
- reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802);
- while (retry--) {
+ reg_w_val(gspca_dev->dev, 0x8804, 0x92);
+ reg_w_val(gspca_dev->dev, 0x8801, reg);
+ reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
+ do {
reg_r(gspca_dev, 0x8803, 1);
- if (!gspca_dev->usb_buf)
+ if (!gspca_dev->usb_buf[0])
break;
- }
+ } while (--retry);
if (retry == 0)
return -1;
reg_r(gspca_dev, 0x8800, 1);
@@ -438,21 +430,10 @@ static const __u16 spca561_init_data[][2] = {
{0x0035, 0x8801}, /* 0x14 - set gain general */
{0x001f, 0x8805}, /* 0x14 */
{0x0000, 0x8800},
- {0x0030, 0x8112},
+ {0x000e, 0x8112}, /* white balance - was 30 */
{}
};
-static void sensor_reset(struct gspca_dev *gspca_dev)
-{
- reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
- reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
- reg_w_val(gspca_dev->dev, 0x8112, 0x00);
- reg_w_val(gspca_dev->dev, 0x8114, 0x00);
- reg_w_val(gspca_dev->dev, 0x8118, 0x21);
- i2c_init(gspca_dev, 0x14);
- i2c_write(gspca_dev, 1, 0x0d);
- i2c_write(gspca_dev, 0, 0x0d);
-}
/******************** QC Express etch2 stuff ********************/
static const __u16 Pb100_1map8300[][2] = {
@@ -462,9 +443,9 @@ static const __u16 Pb100_1map8300[][2] = {
{0x8303, 0x0125}, /* image area */
{0x8304, 0x0169},
{0x8328, 0x000b},
- {0x833c, 0x0001},
+ {0x833c, 0x0001}, /*fixme: win:07*/
- {0x832f, 0x0419},
+ {0x832f, 0x1904}, /*fixme: was 0419*/
{0x8307, 0x00aa},
{0x8301, 0x0003},
{0x8302, 0x000e},
@@ -478,9 +459,10 @@ static const __u16 Pb100_2map8300[][2] = {
};
static const __u16 spca561_161rev12A_data1[][2] = {
- {0x21, 0x8118},
- {0x01, 0x8114},
- {0x00, 0x8112},
+ {0x29, 0x8118}, /* white balance - was 21 */
+ {0x08, 0x8114}, /* white balance - was 01 */
+ {0x0e, 0x8112}, /* white balance - was 00 */
+ {0x00, 0x8102}, /* white balance - new */
{0x92, 0x8804},
{0x04, 0x8802}, /* windows uses 08 */
{}
@@ -505,14 +487,16 @@ static const __u16 spca561_161rev12A_data2[][2] = {
{0xb0, 0x8603},
/* sensor gains */
+ {0x07, 0x8601}, /* white balance - new */
+ {0x07, 0x8602}, /* white balance - new */
{0x00, 0x8610}, /* *red */
{0x00, 0x8611}, /* 3f *green */
{0x00, 0x8612}, /* green *blue */
{0x00, 0x8613}, /* blue *green */
- {0x35, 0x8614}, /* green *red */
- {0x35, 0x8615}, /* 40 *green */
- {0x35, 0x8616}, /* 7a *blue */
- {0x35, 0x8617}, /* 40 *green */
+ {0x43, 0x8614}, /* green *red - white balance - was 0x35 */
+ {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */
+ {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */
+ {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */
{0x0c, 0x8620}, /* 0c */
{0xc8, 0x8631}, /* c8 */
@@ -527,6 +511,7 @@ static const __u16 spca561_161rev12A_data2[][2] = {
{0xdf, 0x863c}, /* df */
{0xf0, 0x8505},
{0x32, 0x850a},
+/* {0x99, 0x8700}, * - white balance - new (removed) */
{}
};
@@ -545,9 +530,10 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev,
}
static void init_161rev12A(struct gspca_dev *gspca_dev)
{
- sensor_reset(gspca_dev);
+/* sensor_reset(gspca_dev); (not in win) */
write_vector(gspca_dev, spca561_161rev12A_data1);
sensor_mapwrite(gspca_dev, Pb100_1map8300);
+/*fixme: should be in sd_start*/
write_vector(gspca_dev, spca561_161rev12A_data2);
sensor_mapwrite(gspca_dev, Pb100_2map8300);
}
@@ -581,35 +567,38 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
cam = &gspca_dev->cam;
- cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x01;
gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
- cam->cam_mode = sif_mode;
- cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
sd->chip_revision = id->driver_info;
- sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
- sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
- sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
+ if (sd->chip_revision == Rev012A) {
+ cam->cam_mode = sif_012a_mode;
+ cam->nmodes = ARRAY_SIZE(sif_012a_mode);
+ } else {
+ cam->cam_mode = sif_072a_mode;
+ cam->nmodes = ARRAY_SIZE(sif_072a_mode);
+ }
+ sd->brightness = BRIGHTNESS_DEF;
+ sd->contrast = CONTRAST_DEF;
+ sd->white = WHITE_DEF;
+ sd->exposure = EXPOSURE_DEF;
+ sd->autogain = AUTOGAIN_DEF;
+ sd->gain = GAIN_DEF;
+ sd->expo12a = EXPO12A_DEF;
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init_12a(struct gspca_dev *gspca_dev)
{
- struct sd *sd = (struct sd *) gspca_dev;
-
- switch (sd->chip_revision) {
- case Rev072A:
- PDEBUG(D_STREAM, "Chip revision id: 072a");
- write_vector(gspca_dev, spca561_init_data);
- break;
- default:
-/* case Rev012A: */
- PDEBUG(D_STREAM, "Chip revision id: 012a");
- init_161rev12A(gspca_dev);
- break;
- }
+ PDEBUG(D_STREAM, "Chip revision: 012a");
+ init_161rev12A(gspca_dev);
+ return 0;
+}
+static int sd_init_72a(struct gspca_dev *gspca_dev)
+{
+ PDEBUG(D_STREAM, "Chip revision: 072a");
+ write_vector(gspca_dev, spca561_init_data);
return 0;
}
@@ -618,25 +607,20 @@ static void setcontrast(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
__u8 lowb;
- int expotimes;
switch (sd->chip_revision) {
case Rev072A:
lowb = sd->contrast >> 8;
- reg_w_val(dev, lowb, 0x8651);
- reg_w_val(dev, lowb, 0x8652);
- reg_w_val(dev, lowb, 0x8653);
- reg_w_val(dev, lowb, 0x8654);
+ reg_w_val(dev, 0x8651, lowb);
+ reg_w_val(dev, 0x8652, lowb);
+ reg_w_val(dev, 0x8653, lowb);
+ reg_w_val(dev, 0x8654, lowb);
break;
- case Rev012A: {
- __u8 Reg8391[] =
- { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 };
-
- /* Write camera sensor settings */
- expotimes = (sd->contrast >> 5) & 0x07ff;
- Reg8391[0] = expotimes & 0xff; /* exposure */
- Reg8391[1] = 0x18 | (expotimes >> 8);
- Reg8391[2] = sd->brightness; /* gain */
+ default: {
+/* case Rev012A: { */
+ static const __u8 Reg8391[] =
+ { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
+
reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
break;
@@ -644,93 +628,153 @@ static void setcontrast(struct gspca_dev *gspca_dev)
}
}
-static void setautogain(struct gspca_dev *gspca_dev)
+/* rev12a only */
+static void setwhite(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ __u16 white;
+ __u8 reg8614, reg8616;
+
+ white = sd->white;
+ /* try to emulate MS-win as possible */
+ reg8616 = 0x90 - white * 5 / 8;
+ reg_w_val(gspca_dev->dev, 0x8616, reg8616);
+ reg8614 = 0x20 + white * 3 / 8;
+ reg_w_val(gspca_dev->dev, 0x8614, reg8614);
+}
- if (sd->chip_revision == Rev072A) {
- if (sd->autogain)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
+/* rev 12a only */
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int expo;
+ int clock_divider;
+ __u8 data[2];
+
+ /* Register 0x8309 controls exposure for the spca561,
+ the basic exposure setting goes from 1-2047, where 1 is completely
+ dark and 2047 is very bright. It not only influences exposure but
+ also the framerate (to allow for longer exposure) from 1 - 300 it
+ only raises the exposure time then from 300 - 600 it halves the
+ framerate to be able to further raise the exposure time and for every
+ 300 more it halves the framerate again. This allows for a maximum
+ exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
+ Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
+ configure a divider for the base framerate which us used at the
+ exposure setting of 1-300. These bits configure the base framerate
+ according to the following formula: fps = 60 / (value + 2) */
+ if (sd->exposure < 2048) {
+ expo = sd->exposure;
+ clock_divider = 0;
+ } else {
+ /* Add 900 to make the 0 setting of the second part of the
+ exposure equal to the 2047 setting of the first part. */
+ expo = (sd->exposure - 2048) + 900;
+ clock_divider = 3;
}
+ expo |= clock_divider << 11;
+ data[0] = expo;
+ data[1] = expo >> 8;
+ reg_w_buf(gspca_dev, 0x8309, data, 2);
}
-static void sd_start(struct gspca_dev *gspca_dev)
+/* rev 12a only */
+static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ __u8 data[2];
+
+ data[0] = sd->gain;
+ data[1] = 0;
+ reg_w_buf(gspca_dev, 0x8335, data, 2);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
+}
+
+static int sd_start_12a(struct gspca_dev *gspca_dev)
+{
struct usb_device *dev = gspca_dev->dev;
- int Clck;
+ int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */
__u8 Reg8307[] = { 0xaa, 0x00 };
int mode;
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
- switch (sd->chip_revision) {
- case Rev072A:
- switch (mode) {
- default:
-/* case 0:
- case 1: */
- Clck = 0x25;
- break;
- case 2:
- Clck = 0x22;
- break;
- case 3:
- Clck = 0x21;
- break;
- }
- reg_w_val(dev, 0x8500, mode); /* mode */
- reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
- reg_w_val(dev, 0x8112, 0x10 | 0x20);
- setautogain(gspca_dev);
- break;
+ if (mode <= 1) {
+ /* Use compression on 320x240 and above */
+ reg_w_val(dev, 0x8500, 0x10 | mode);
+ } else {
+ /* I couldn't get the compression to work below 320x240
+ * Fortunately at these resolutions the bandwidth
+ * is sufficient to push raw frames at ~20fps */
+ reg_w_val(dev, 0x8500, mode);
+ } /* -- qq@kuku.eu.org */
+ reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
+ reg_w_val(gspca_dev->dev, 0x8700, Clck);
+ /* 0x8f 0x85 0x27 clock */
+ reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
+ reg_w_val(gspca_dev->dev, 0x850b, 0x03);
+ setcontrast(gspca_dev);
+ setwhite(gspca_dev);
+ setautogain(gspca_dev);
+ setexposure(gspca_dev);
+ return 0;
+}
+static int sd_start_72a(struct gspca_dev *gspca_dev)
+{
+ struct usb_device *dev = gspca_dev->dev;
+ int Clck;
+ int mode;
+
+ mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+ switch (mode) {
default:
-/* case Rev012A: */
- switch (mode) {
- case 0:
- case 1:
- Clck = 0x8a;
- break;
- case 2:
- Clck = 0x85;
- break;
- default:
- Clck = 0x83;
- break;
- }
- if (mode <= 1) {
- /* Use compression on 320x240 and above */
- reg_w_val(dev, 0x8500, 0x10 | mode);
- } else {
- /* I couldn't get the compression to work below 320x240
- * Fortunately at these resolutions the bandwidth
- * is sufficient to push raw frames at ~20fps */
- reg_w_val(dev, 0x8500, mode);
- } /* -- qq@kuku.eu.org */
- reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
- reg_w_val(gspca_dev->dev, 0x8700, Clck);
- /* 0x8f 0x85 0x27 clock */
- reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
- reg_w_val(gspca_dev->dev, 0x850b, 0x03);
- setcontrast(gspca_dev);
+/* case 0:
+ case 1: */
+ Clck = 0x25;
+ break;
+ case 2:
+ Clck = 0x22;
+ break;
+ case 3:
+ Clck = 0x21;
break;
}
+ reg_w_val(dev, 0x8500, mode); /* mode */
+ reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
+ reg_w_val(dev, 0x8112, 0x10 | 0x20);
+ setautogain(gspca_dev);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
- reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->chip_revision == Rev012A) {
+ reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
+ } else {
+ reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
+ }
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
-}
+ struct sd *sd = (struct sd *) gspca_dev;
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
- reg_w_val(gspca_dev->dev, 0x8114, 0);
+ if (sd->chip_revision == Rev012A) {
+ reg_w_val(gspca_dev->dev, 0x8118, 0x29);
+ reg_w_val(gspca_dev->dev, 0x8114, 0x08);
+ }
+/* reg_w_val(gspca_dev->dev, 0x8114, 0); */
}
static void do_autogain(struct gspca_dev *gspca_dev)
@@ -744,6 +788,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
__u8 luma_mean = 110;
__u8 luma_delta = 20;
__u8 spring = 4;
+ __u8 reg8339[2];
if (sd->ag_cnt < 0)
return;
@@ -798,13 +843,16 @@ static void do_autogain(struct gspca_dev *gspca_dev)
}
break;
case Rev012A:
- /* sensor registers is access and memory mapped to 0x8300 */
- /* readind all 0x83xx block the sensor */
- /*
- * The data from the header seem wrong where is the luma
- * and chroma mean value
- * at the moment set exposure in contrast set
- */
+ reg_r(gspca_dev, 0x8330, 2);
+ if (gspca_dev->usb_buf[1] > 0x08) {
+ reg8339[0] = ++sd->expo12a;
+ reg8339[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ } else if (gspca_dev->usb_buf[1] < 0x02) {
+ reg8339[0] = --sd->expo12a;
+ reg8339[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ }
break;
}
}
@@ -814,6 +862,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
switch (data[0]) {
case 0: /* start of frame */
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
@@ -826,8 +876,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
frame, data, len);
} else {
/* raw bayer (with a header, which we skip) */
- data += 20;
- len -= 20;
+ if (sd->chip_revision == Rev012A) {
+ data += 20;
+ len -= 20;
+ } else {
+ data += 16;
+ len -= 16;
+ }
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, len);
}
@@ -841,24 +896,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
+/* rev 72a only */
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 value;
- switch (sd->chip_revision) {
- case Rev072A:
- value = sd->brightness;
- reg_w_val(gspca_dev->dev, value, 0x8611);
- reg_w_val(gspca_dev->dev, value, 0x8612);
- reg_w_val(gspca_dev->dev, value, 0x8613);
- reg_w_val(gspca_dev->dev, value, 0x8614);
- break;
- default:
-/* case Rev012A: */
- setcontrast(gspca_dev);
- break;
- }
+ value = sd->brightness;
+ reg_w_val(gspca_dev->dev, 0x8611, value);
+ reg_w_val(gspca_dev->dev, 0x8612, value);
+ reg_w_val(gspca_dev->dev, 0x8613, value);
+ reg_w_val(gspca_dev->dev, 0x8614, value);
}
static void getbrightness(struct gspca_dev *gspca_dev)
@@ -866,52 +914,38 @@ static void getbrightness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
__u16 tot;
- switch (sd->chip_revision) {
- case Rev072A:
- tot = 0;
- reg_r(gspca_dev, 0x8611, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8612, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8613, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8614, 1);
- tot += gspca_dev->usb_buf[0];
- sd->brightness = tot >> 2;
- break;
- default:
-/* case Rev012A: */
- /* no way to read sensor settings */
- break;
- }
+ tot = 0;
+ reg_r(gspca_dev, 0x8611, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8612, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8613, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8614, 1);
+ tot += gspca_dev->usb_buf[0];
+ sd->brightness = tot >> 2;
}
+/* rev72a only */
static void getcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u16 tot;
- switch (sd->chip_revision) {
- case Rev072A:
- tot = 0;
- reg_r(gspca_dev, 0x8651, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8652, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8653, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8654, 1);
- tot += gspca_dev->usb_buf[0];
- sd->contrast = tot << 6;
- break;
- default:
-/* case Rev012A: */
- /* no way to read sensor settings */
- break;
- }
+ tot = 0;
+ reg_r(gspca_dev, 0x8651, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8652, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8653, 1);
+ tot += gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8654, 1);
+ tot += gspca_dev->usb_buf[0];
+ sd->contrast = tot << 6;
PDEBUG(D_CONF, "get contrast %d", sd->contrast);
}
+/* rev 72a only */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -931,6 +965,7 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+/* rev 72a only */
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -968,20 +1003,190 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+/* rev12a only */
+static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->white = val;
+ if (gspca_dev->streaming)
+ setwhite(gspca_dev);
+ return 0;
+}
+
+static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->white;
+ return 0;
+}
+
+/* rev12a only */
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->exposure = val;
+ if (gspca_dev->streaming)
+ setexposure(gspca_dev);
+ return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->exposure;
+ return 0;
+}
+
+/* rev12a only */
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->gain = val;
+ if (gspca_dev->streaming)
+ setgain(gspca_dev);
+ return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->gain;
+ return 0;
+}
+
+/* control tables */
+static struct ctrl sd_ctrls_12a[] = {
+ {
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "White Balance",
+ .minimum = WHITE_MIN,
+ .maximum = WHITE_MAX,
+ .step = 1,
+ .default_value = WHITE_DEF,
+ },
+ .set = sd_setwhite,
+ .get = sd_getwhite,
+ },
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = EXPOSURE_MIN,
+ .maximum = EXPOSURE_MAX,
+ .step = 1,
+ .default_value = EXPOSURE_DEF,
+ },
+ .set = sd_setexposure,
+ .get = sd_getexposure,
+ },
+ {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Gain",
+ .minimum = AUTOGAIN_MIN,
+ .maximum = AUTOGAIN_MAX,
+ .step = 1,
+ .default_value = AUTOGAIN_DEF,
+ },
+ .set = sd_setautogain,
+ .get = sd_getautogain,
+ },
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = GAIN_MIN,
+ .maximum = GAIN_MAX,
+ .step = 1,
+ .default_value = GAIN_DEF,
+ },
+ .set = sd_setgain,
+ .get = sd_getgain,
+ },
+};
+
+static struct ctrl sd_ctrls_72a[] = {
+ {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = BRIGHTNESS_MIN,
+ .maximum = BRIGHTNESS_MAX,
+ .step = 1,
+ .default_value = BRIGHTNESS_DEF,
+ },
+ .set = sd_setbrightness,
+ .get = sd_getbrightness,
+ },
+ {
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = CONTRAST_MIN,
+ .maximum = CONTRAST_MAX,
+ .step = 1,
+ .default_value = CONTRAST_DEF,
+ },
+ .set = sd_setcontrast,
+ .get = sd_getcontrast,
+ },
+ {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Gain",
+ .minimum = AUTOGAIN_MIN,
+ .maximum = AUTOGAIN_MAX,
+ .step = 1,
+ .default_value = AUTOGAIN_DEF,
+ },
+ .set = sd_setautogain,
+ .get = sd_getautogain,
+ },
+};
+
/* sub-driver description */
-static const struct sd_desc sd_desc = {
+static const struct sd_desc sd_desc_12a = {
.name = MODULE_NAME,
- .ctrls = sd_ctrls,
- .nctrls = ARRAY_SIZE(sd_ctrls),
+ .ctrls = sd_ctrls_12a,
+ .nctrls = ARRAY_SIZE(sd_ctrls_12a),
.config = sd_config,
- .open = sd_open,
- .start = sd_start,
+ .init = sd_init_12a,
+ .start = sd_start_12a,
+ .stopN = sd_stopN,
+ .stop0 = sd_stop0,
+ .pkt_scan = sd_pkt_scan,
+/* .dq_callback = do_autogain, * fixme */
+};
+static const struct sd_desc sd_desc_72a = {
+ .name = MODULE_NAME,
+ .ctrls = sd_ctrls_72a,
+ .nctrls = ARRAY_SIZE(sd_ctrls_72a),
+ .config = sd_config,
+ .init = sd_init_72a,
+ .start = sd_start_72a,
.stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.dq_callback = do_autogain,
};
+static const struct sd_desc *sd_desc[2] = {
+ &sd_desc_12a,
+ &sd_desc_72a
+};
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
@@ -1009,7 +1214,9 @@ MODULE_DEVICE_TABLE(usb, device_table);
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+ return gspca_dev_probe(intf, id,
+ sd_desc[id->driver_info],
+ sizeof(struct sd),
THIS_MODULE);
}
@@ -1018,6 +1225,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index 16219cf6a6d..d9d64911f22 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -306,8 +306,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
int ret;
@@ -324,7 +324,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
int ret, value;
@@ -374,9 +374,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
set_par(gspca_dev, 0x01000000);
set_par(gspca_dev, 0x01000000);
PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
- return;
+ return 0;
out:
PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
+ return ret;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -398,14 +399,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
PDEBUG(D_STREAM, "camera stopped");
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -535,11 +528,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
};
@@ -564,6 +555,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index 54efa48bee0..bd9288665a8 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -449,31 +449,47 @@ static const __u8 qtable_spca504_default[2][64] = {
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
};
-static void reg_r(struct usb_device *dev,
- __u16 req,
- __u16 index,
- __u8 *buffer, __u16 length)
+/* read <len> bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+ __u16 req,
+ __u16 index,
+ __u16 len)
{
- usb_control_msg(dev,
- usb_rcvctrlpipe(dev, 0),
+#ifdef GSPCA_DEBUG
+ if (len > USB_BUF_SZ) {
+ err("reg_r: buffer overflow");
+ return;
+ }
+#endif
+ usb_control_msg(gspca_dev->dev,
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
- index, buffer, length,
+ index,
+ len ? gspca_dev->usb_buf : NULL, len,
500);
}
-static void reg_w(struct usb_device *dev,
- __u16 req,
- __u16 value,
- __u16 index,
- __u8 *buffer, __u16 length)
+/* write <len> bytes from gspca_dev->usb_buf */
+static void reg_w(struct gspca_dev *gspca_dev,
+ __u16 req,
+ __u16 value,
+ __u16 index,
+ __u16 len)
{
- usb_control_msg(dev,
- usb_sndctrlpipe(dev, 0),
+#ifdef GSPCA_DEBUG
+ if (len > USB_BUF_SZ) {
+ err("reg_w: buffer overflow");
+ return;
+ }
+#endif
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, index, buffer, length,
+ value, index,
+ len ? gspca_dev->usb_buf : NULL, len,
500);
}
@@ -634,7 +650,7 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
int count = 10;
while (--count > 0) {
- reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
+ reg_r(gspca_dev, 0x21, 0, 1);
if ((gspca_dev->usb_buf[0] & 0x01) == 0)
break;
msleep(10);
@@ -644,15 +660,14 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
{
- struct usb_device *dev = gspca_dev->dev;
int count = 50;
while (--count > 0) {
- reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
+ reg_r(gspca_dev, 0x21, 1, 1);
if (gspca_dev->usb_buf[0] != 0) {
gspca_dev->usb_buf[0] = 0;
- reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
+ reg_w(gspca_dev, 0x21, 0, 1, 1);
+ reg_r(gspca_dev, 0x21, 1, 1);
spca504B_PollingDataReady(gspca_dev);
break;
}
@@ -662,16 +677,14 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
{
- struct usb_device *dev = gspca_dev->dev;
__u8 *data;
- data = kmalloc(64, GFP_KERNEL);
- reg_r(dev, 0x20, 0, data, 5);
+ data = gspca_dev->usb_buf;
+ reg_r(gspca_dev, 0x20, 0, 5);
PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
data[0], data[1], data[2], data[3], data[4]);
- reg_r(dev, 0x23, 0, data, 64);
- reg_r(dev, 0x23, 1, data, 64);
- kfree(data);
+ reg_r(gspca_dev, 0x23, 0, 64);
+ reg_r(gspca_dev, 0x23, 1, 64);
}
static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
@@ -686,21 +699,21 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
Type = 0;
switch (sd->bridge) {
case BRIDGE_SPCA533:
- reg_w(dev, 0x31, 0, 0, NULL, 0);
+ reg_w(gspca_dev, 0x31, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
spca50x_GetFirmware(gspca_dev);
gspca_dev->usb_buf[0] = 2; /* type */
- reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
+ reg_w(gspca_dev, 0x24, 0, 8, 1);
+ reg_r(gspca_dev, 0x24, 8, 1);
gspca_dev->usb_buf[0] = Size;
- reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
+ reg_w(gspca_dev, 0x25, 0, 4, 1);
+ reg_r(gspca_dev, 0x25, 4, 1); /* size */
rc = spca504B_PollingDataReady(gspca_dev);
/* Init the cam width height with some values get on init ? */
- reg_w(dev, 0x31, 0, 4, NULL, 0);
+ reg_w(gspca_dev, 0x31, 0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
break;
@@ -708,12 +721,12 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA504B: */
/* case BRIDGE_SPCA536: */
gspca_dev->usb_buf[0] = Size;
- reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
+ reg_w(gspca_dev, 0x25, 0, 4, 1);
+ reg_r(gspca_dev, 0x25, 4, 1); /* size */
Type = 6;
gspca_dev->usb_buf[0] = Type;
- reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
+ reg_w(gspca_dev, 0x27, 0, 0, 1);
+ reg_r(gspca_dev, 0x27, 0, 1); /* type */
rc = spca504B_PollingDataReady(gspca_dev);
break;
case BRIDGE_SPCA504:
@@ -752,18 +765,15 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev)
static void spca504B_setQtable(struct gspca_dev *gspca_dev)
{
- struct usb_device *dev = gspca_dev->dev;
-
gspca_dev->usb_buf[0] = 3;
- reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
+ reg_w(gspca_dev, 0x26, 0, 0, 1);
+ reg_r(gspca_dev, 0x26, 0, 1);
spca504B_PollingDataReady(gspca_dev);
}
static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
int pollreg = 1;
switch (sd->bridge) {
@@ -774,20 +784,20 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
default:
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA504B: */
- reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
- reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
- reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
- reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
- reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
- reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
+ reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
+ reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
+ reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
+ reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
+ reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
+ reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
break;
case BRIDGE_SPCA536:
- reg_w(dev, 0, 0, 0x20f0, NULL, 0);
- reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
- reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
- reg_w(dev, 0, 1, 0x20f4, NULL, 0);
- reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
- reg_w(dev, 0, 0, 0x2089, NULL, 0);
+ reg_w(gspca_dev, 0, 0, 0x20f0, 0);
+ reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
+ reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
+ reg_w(gspca_dev, 0, 1, 0x20f4, 0);
+ reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
+ reg_w(gspca_dev, 0, 0, 0x2089, 0);
break;
}
if (pollreg)
@@ -799,7 +809,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
struct cam *cam;
cam = &gspca_dev->cam;
@@ -811,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
if (sd->subtype == AiptekMiniPenCam13) {
/* try to get the firmware as some cam answer 2.0.1.2.2
* and should be a spca504b then overwrite that setting */
- reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
+ reg_r(gspca_dev, 0x20, 0, 1);
switch (gspca_dev->usb_buf[0]) {
case 1:
break; /* (right bridge/subtype) */
@@ -848,8 +857,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
@@ -860,12 +869,12 @@ static int sd_open(struct gspca_dev *gspca_dev)
switch (sd->bridge) {
case BRIDGE_SPCA504B:
- reg_w(dev, 0x1d, 0, 0, NULL, 0);
- reg_w(dev, 0, 1, 0x2306, NULL, 0);
- reg_w(dev, 0, 0, 0x0d04, NULL, 0);
- reg_w(dev, 0, 0, 0x2000, NULL, 0);
- reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
- reg_w(dev, 0, 0, 0x2306, NULL, 0);
+ reg_w(gspca_dev, 0x1d, 0, 0, 0);
+ reg_w(gspca_dev, 0, 1, 0x2306, 0);
+ reg_w(gspca_dev, 0, 0, 0x0d04, 0);
+ reg_w(gspca_dev, 0, 0, 0x2000, 0);
+ reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
+ reg_w(gspca_dev, 0, 0, 0x2306, 0);
/* fall thru */
case BRIDGE_SPCA533:
rc = spca504B_PollingDataReady(gspca_dev);
@@ -873,12 +882,12 @@ static int sd_open(struct gspca_dev *gspca_dev)
break;
case BRIDGE_SPCA536:
spca50x_GetFirmware(gspca_dev);
- reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
+ reg_r(gspca_dev, 0x00, 0x5002, 1);
gspca_dev->usb_buf[0] = 0;
- reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
- reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
+ reg_w(gspca_dev, 0x24, 0, 0, 1);
+ reg_r(gspca_dev, 0x24, 0, 1);
rc = spca504B_PollingDataReady(gspca_dev);
- reg_w(dev, 0x34, 0, 0, NULL, 0);
+ reg_w(gspca_dev, 0x34, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
break;
case BRIDGE_SPCA504C: /* pccam600 */
@@ -952,7 +961,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
@@ -971,12 +980,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA536: */
if (sd->subtype == MegapixV4 ||
sd->subtype == LogitechClickSmart820) {
- reg_w(dev, 0xf0, 0, 0, NULL, 0);
+ reg_w(gspca_dev, 0xf0, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
- reg_r(dev, 0xf0, 4, NULL, 0);
+ reg_r(gspca_dev, 0xf0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
} else {
- reg_w(dev, 0x31, 0, 4, NULL, 0);
+ reg_w(gspca_dev, 0x31, 0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
}
@@ -1033,6 +1042,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
break;
}
sp5xx_initContBrigHueRegisters(gspca_dev);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1045,7 +1055,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA536: */
/* case BRIDGE_SPCA504B: */
- reg_w(dev, 0x31, 0, 0, NULL, 0);
+ reg_w(gspca_dev, 0x31, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
spca504B_PollingDataReady(gspca_dev);
break;
@@ -1069,14 +1079,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
}
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1369,11 +1371,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -1456,6 +1456,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index 91b555c34c6..eac245d7a75 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -28,9 +28,7 @@
#include "gspca.h"
-#define MAX_GAMMA 0x10 /* 0 to 15 */
-
-#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
@@ -49,6 +47,10 @@ struct sd {
unsigned char whitebalance;
unsigned char mirror;
unsigned char effect;
+
+ __u8 sensor;
+#define SENSOR_TAS5130A 0
+#define SENSOR_OM6802 1
};
/* V4L2 controls supported by the driver */
@@ -83,9 +85,9 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
- .maximum = 0x0f,
+ .maximum = 14,
.step = 1,
- .default_value = 0x09,
+ .default_value = 8,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
@@ -118,16 +120,17 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcolors,
.get = sd_getcolors,
},
-#define SD_GAMMA 3
+#define GAMMA_MAX 16
+#define GAMMA_DEF 10
{
{
.id = V4L2_CID_GAMMA, /* (gamma on win) */
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Gamma (Untested)",
+ .name = "Gamma",
.minimum = 0,
- .maximum = MAX_GAMMA,
+ .maximum = GAMMA_MAX - 1,
.step = 1,
- .default_value = 0x09,
+ .default_value = GAMMA_DEF,
},
.set = sd_setgamma,
.get = sd_getgamma,
@@ -185,7 +188,7 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 1,
.step = 1,
- .default_value = 1,
+ .default_value = 0,
},
.set = sd_setwhitebalance,
.get = sd_getwhitebalance
@@ -197,7 +200,7 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Sharpness",
.minimum = 0,
- .maximum = MAX_GAMMA, /* 0 to 16 */
+ .maximum = 15,
.step = 1,
.default_value = 0x06,
},
@@ -233,7 +236,7 @@ static char *effects_control[] = {
static struct v4l2_pix_format vga_mode_t16[] = {
{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 8 + 590,
+ .sizeimage = 160 * 120 * 4 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 4},
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -258,7 +261,59 @@ static struct v4l2_pix_format vga_mode_t16[] = {
.priv = 0},
};
-#define T16_OFFSET_DATA 631
+/* sensor specific data */
+struct additional_sensor_data {
+ const __u8 data1[20];
+ const __u8 data2[18];
+ const __u8 data3[18];
+ const __u8 data4[4];
+ const __u8 data5[6];
+ const __u8 stream[4];
+};
+
+const static struct additional_sensor_data sensor_data[] = {
+ { /* TAS5130A */
+ .data1 =
+ {0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10,
+ 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
+ 0xd8, 0xc8, 0xd9, 0xfc},
+ .data2 =
+ {0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60,
+ 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
+ 0xe8, 0xe0},
+ .data3 =
+ {0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60,
+ 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
+ 0xcf, 0xe0},
+ .data4 = /* Freq (50/60Hz). Splitted for test purpose */
+ {0x66, 0x00, 0xa8, 0xe8},
+ .data5 =
+ {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
+ .stream =
+ {0x0b, 0x04, 0x0a, 0x40},
+ },
+ { /* OM6802 */
+ .data1 =
+ {0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22,
+ 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06,
+ 0xd8, 0xb3, 0xd9, 0xfc},
+ .data2 =
+ {0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80,
+ 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff,
+ 0xe8, 0xff},
+ .data3 =
+ {0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80,
+ 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff,
+ 0xcf, 0xff},
+ .data4 = /*Freq (50/60Hz). Splitted for test purpose */
+ {0x66, 0xca, 0xa8, 0xf0 },
+ .data5 = /* this could be removed later */
+ {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
+ .stream =
+ {0x0b, 0x04, 0x0a, 0x78},
+ }
+};
+
#define MAX_EFFECTS 7
/* easily done by soft, this table could be removed,
* i keep it here just in case */
@@ -272,87 +327,87 @@ static const __u8 effects_table[MAX_EFFECTS][6] = {
{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
};
-static const __u8 gamma_table[MAX_GAMMA][34] = {
- {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
+static const __u8 gamma_table[GAMMA_MAX][34] = {
+ {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */
0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
- 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
- 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
- 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
+ {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */
+ 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
+ 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
+ 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
- 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
- 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
- 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
+ {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */
+ 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
+ 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
+ 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
- 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
- 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
- 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
+ {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */
+ 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
+ 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
+ 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
+ {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */
0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
- 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
- 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
+ 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
+ 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
+ {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */
0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
- 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
- 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
+ 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
+ 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
+ {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */
0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
- 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
- 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
- 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
+ {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */
+ 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
+ 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
+ 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
- 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
- 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
- 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
+ {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */
+ 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
+ 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
+ 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
+ {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */
0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
- 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
- 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
- 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
+ {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */
+ 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
+ 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
+ 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
- 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
- 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
- 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
+ {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */
+ 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
+ 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
+ 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
- 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
- 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
- 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
- 0xA0, 0xFF},
- {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
- 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
- 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
- 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
+ {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */
+ 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
+ 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
+ 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
- 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
- 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
- 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
+ {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */
+ 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
+ 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
+ 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
0xa0, 0xff},
- {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
- 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
- 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
- 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
- 0xA0, 0xFF}
+ {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */
+ 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
+ 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
+ 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
+ 0xa0, 0xff},
+ {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */
+ 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
+ 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
+ 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
+ 0xa0, 0xff}
};
static const __u8 tas5130a_sensor_init[][8] = {
@@ -363,8 +418,10 @@ static const __u8 tas5130a_sensor_init[][8] = {
{},
};
+static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
+
/* read 1 byte */
-static int reg_r_1(struct gspca_dev *gspca_dev,
+static int reg_r(struct gspca_dev *gspca_dev,
__u16 index)
{
usb_control_msg(gspca_dev->dev,
@@ -378,26 +435,26 @@ static int reg_r_1(struct gspca_dev *gspca_dev,
}
static void reg_w(struct gspca_dev *gspca_dev,
- __u16 value,
- __u16 index,
- const __u8 *buffer, __u16 len)
+ __u16 index)
{
- if (buffer == NULL) {
- usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- 0,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, index,
- NULL, 0, 500);
- return;
- }
- if (len <= sizeof gspca_dev->usb_buf) {
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index,
+ NULL, 0, 500);
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+ const __u8 *buffer, __u16 len)
+{
+ if (len <= USB_BUF_SZ) {
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, index,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x01, 0,
gspca_dev->usb_buf, len, 500);
} else {
__u8 *tmpbuf;
@@ -407,13 +464,72 @@ static void reg_w(struct gspca_dev *gspca_dev,
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, index,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x01, 0,
tmpbuf, len, 500);
kfree(tmpbuf);
}
}
+/* Reported as OM6802*/
+static void om6802_sensor_init(struct gspca_dev *gspca_dev)
+{
+ int i;
+ const __u8 *p;
+ __u8 byte;
+ __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
+ static const __u8 sensor_init[] = {
+ 0xdf, 0x6d,
+ 0xdd, 0x18,
+ 0x5a, 0xe0,
+ 0x5c, 0x07,
+ 0x5d, 0xb0,
+ 0x5e, 0x1e,
+ 0x60, 0x71,
+ 0xef, 0x00,
+ 0xe9, 0x00,
+ 0xea, 0x00,
+ 0x90, 0x24,
+ 0x91, 0xb2,
+ 0x82, 0x32,
+ 0xfd, 0x41,
+ 0x00 /* table end */
+ };
+
+ reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+ msleep(5);
+ i = 4;
+ while (--i < 0) {
+ byte = reg_r(gspca_dev, 0x0060);
+ if (!(byte & 0x01))
+ break;
+ msleep(100);
+ }
+ byte = reg_r(gspca_dev, 0x0063);
+ if (byte != 0x17) {
+ err("Bad sensor reset %02x", byte);
+ /* continue? */
+ }
+
+ p = sensor_init;
+ while (*p != 0) {
+ val[1] = *p++;
+ val[3] = *p++;
+ if (*p == 0)
+ reg_w(gspca_dev, 0x3c80);
+ reg_w_buf(gspca_dev, val, sizeof val);
+ i = 4;
+ while (--i >= 0) {
+ msleep(15);
+ byte = reg_r(gspca_dev, 0x60);
+ if (!(byte & 0x01))
+ break;
+ }
+ }
+ msleep(15);
+ reg_w(gspca_dev, 0x3c80);
+}
+
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
@@ -430,7 +546,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
- sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
+ sd->gamma = GAMMA_DEF;
sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
@@ -439,27 +555,98 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-static int init_default_parameters(struct gspca_dev *gspca_dev)
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ unsigned int brightness;
+ __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
+
+ brightness = sd->brightness;
+ if (brightness < 7) {
+ set6[1] = 0x26;
+ set6[3] = 0x70 - brightness * 0x10;
+ } else {
+ set6[3] = 0x00 + ((brightness - 7) * 0x10);
+ }
+
+ reg_w_buf(gspca_dev, set6, sizeof set6);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ unsigned int contrast = sd->contrast;
+ __u16 reg_to_write;
+
+ if (contrast < 7)
+ reg_to_write = 0x8ea9 - contrast * 0x200;
+ else
+ reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
+
+ reg_w(gspca_dev, reg_to_write);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u16 reg_to_write;
+
+ reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
+ reg_w(gspca_dev, reg_to_write);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
+ reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
+}
+
+static void setwhitebalance(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ __u8 white_balance[8] =
+ {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
+
+ if (sd->whitebalance)
+ white_balance[7] = 0x3c;
+
+ reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u16 reg_to_write;
+
+ reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
+
+ reg_w(gspca_dev, reg_to_write);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
/* some of this registers are not really neded, because
* they are overriden by setbrigthness, setcontrast, etc,
* but wont hurt anyway, and can help someone with similar webcam
* to see the initial parameters.*/
- int i = 0;
- __u8 test_byte;
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+ __u8 byte, test_byte;
static const __u8 read_indexs[] =
{ 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
- static const __u8 n1[6] =
+ static const __u8 n1[] =
{0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
- static const __u8 n2[2] =
+ static const __u8 n2[] =
{0x08, 0x00};
- static const __u8 nset[6] =
- { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
- static const __u8 n3[6] =
+ static const __u8 n3[] =
{0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
- static const __u8 n4[0x46] =
+ static const __u8 n4[] =
{0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
@@ -469,124 +656,113 @@ static int init_default_parameters(struct gspca_dev *gspca_dev)
0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
- static const __u8 nset4[18] = {
- 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
- 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
- 0xe8, 0xe0
- };
- /* ojo puede ser 0xe6 en vez de 0xe9 */
- static const __u8 nset2[20] = {
- 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
- 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
- 0xd8, 0xc8, 0xd9, 0xfc
- };
- static const __u8 missing[8] =
- { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
- static const __u8 nset3[18] = {
- 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
- 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
- 0xcf, 0xe0
- };
- static const __u8 nset5[4] =
- { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
- static const __u8 nset6[34] = {
- 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
- 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
- 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
- 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
- 0xa0, 0xff
- }; /* Gamma */
- static const __u8 nset7[4] =
- { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
static const __u8 nset9[4] =
{ 0x0b, 0x04, 0x0a, 0x78 };
static const __u8 nset8[6] =
{ 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
- static const __u8 nset10[6] =
- { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
- reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
- reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
- reg_r_1(gspca_dev, 0x0063);
- reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
+ byte = reg_r(gspca_dev, 0x06);
+ test_byte = reg_r(gspca_dev, 0x07);
+ if (byte == 0x08 && test_byte == 0x07) {
+ PDEBUG(D_CONF, "sensor om6802");
+ sd->sensor = SENSOR_OM6802;
+ } else if (byte == 0x08 && test_byte == 0x01) {
+ PDEBUG(D_CONF, "sensor tas5130a");
+ sd->sensor = SENSOR_TAS5130A;
+ } else {
+ PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
+ sd->sensor = SENSOR_TAS5130A;
+ }
+ reg_w_buf(gspca_dev, n1, sizeof n1);
+ test_byte = 0;
+ i = 5;
+ while (--i >= 0) {
+ reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+ test_byte = reg_r(gspca_dev, 0x0063);
+ msleep(100);
+ if (test_byte == 0x17)
+ break; /* OK */
+ }
+ if (i < 0) {
+ err("Bad sensor reset %02x", test_byte);
+/* return -EIO; */
+/*fixme: test - continue */
+ }
+ reg_w_buf(gspca_dev, n2, sizeof n2);
+
+ i = 0;
while (read_indexs[i] != 0x00) {
- test_byte = reg_r_1(gspca_dev, read_indexs[i]);
- PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
+ test_byte = reg_r(gspca_dev, read_indexs[i]);
+ PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
test_byte);
i++;
}
- reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
- reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
- reg_r_1(gspca_dev, 0x0080);
- reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
- reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
- reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
- reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
- reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
- reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
- reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
- reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
- reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
- reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
- reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
- reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
-
- reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
-
- reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
- reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
- reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
-
- reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
- reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
- reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
- reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
-
- reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
- reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
- reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
- reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
+ reg_w_buf(gspca_dev, n3, sizeof n3);
+ reg_w_buf(gspca_dev, n4, sizeof n4);
+ reg_r(gspca_dev, 0x0080);
+ reg_w(gspca_dev, 0x2c80);
- return 0;
-}
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+ sizeof sensor_data[sd->sensor].data1);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
+ sizeof sensor_data[sd->sensor].data3);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+ sizeof sensor_data[sd->sensor].data2);
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- unsigned int brightness;
- __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
- brightness = sd->brightness;
+ reg_w(gspca_dev, 0x3880);
+ reg_w(gspca_dev, 0x3880);
+ reg_w(gspca_dev, 0x338e);
- if (brightness < 7) {
- set6[3] = 0x70 - (brightness * 0xa);
- } else {
- set6[1] = 0x24;
- set6[3] = 0x00 + ((brightness - 7) * 0xa);
- }
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ setgamma(gspca_dev);
+ setcolors(gspca_dev);
+ setsharpness(gspca_dev);
+ setwhitebalance(gspca_dev);
+
+ reg_w(gspca_dev, 0x2087); /* tied to white balance? */
+ reg_w(gspca_dev, 0x2088);
+ reg_w(gspca_dev, 0x2089);
+
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
+ sizeof sensor_data[sd->sensor].data4);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
+ sizeof sensor_data[sd->sensor].data5);
+ reg_w_buf(gspca_dev, nset8, sizeof nset8);
+ reg_w_buf(gspca_dev, nset9, sizeof nset9);
- reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
+ reg_w(gspca_dev, 0x2880);
+
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+ sizeof sensor_data[sd->sensor].data1);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
+ sizeof sensor_data[sd->sensor].data3);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+ sizeof sensor_data[sd->sensor].data2);
+
+ return 0;
}
static void setflip(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
-
__u8 flipcmd[8] =
- { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
+ {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
- if (sd->mirror == 1)
+ if (sd->mirror)
flipcmd[3] = 0x01;
- reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
+ reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
}
static void seteffect(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
+ reg_w_buf(gspca_dev, effects_table[sd->effect],
+ sizeof effects_table[0]);
if (sd->effect == 1 || sd->effect == 5) {
PDEBUG(D_CONF,
"This effect have been disabled for webcam \"safety\"");
@@ -594,22 +770,9 @@ static void seteffect(struct gspca_dev *gspca_dev)
}
if (sd->effect == 1 || sd->effect == 4)
- reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
+ reg_w(gspca_dev, 0x4aa6);
else
- reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
-}
-
-static void setwhitebalance(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- __u8 white_balance[8] =
- { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
-
- if (sd->whitebalance == 1)
- white_balance[7] = 0x3c;
-
- reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
+ reg_w(gspca_dev, 0xfaa6);
}
static void setlightfreq(struct gspca_dev *gspca_dev)
@@ -620,44 +783,143 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
if (sd->freq == 2) /* 60hz */
freq[1] = 0x00;
- reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
+ reg_w_buf(gspca_dev, freq, sizeof freq);
}
-static void setcontrast(struct gspca_dev *gspca_dev)
+/* Is this really needed?
+ * i added some module parameters for test with some users */
+static void poll_sensor(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- unsigned int contrast = sd->contrast;
- __u16 reg_to_write = 0x00;
-
- if (contrast < 7)
- reg_to_write = 0x8ea9 - (0x200 * contrast);
- else
- reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
-
- reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
+ static const __u8 poll1[] =
+ {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
+ 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
+ 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
+ 0x60, 0x14};
+ static const __u8 poll2[] =
+ {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
+ 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
+ static const __u8 poll3[] =
+ {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
+ static const __u8 poll4[] =
+ {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
+ 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
+ 0xc2, 0x80, 0xc3, 0x10};
+
+ if (sd->sensor != SENSOR_TAS5130A) {
+ PDEBUG(D_STREAM, "[Sensor requires polling]");
+ reg_w_buf(gspca_dev, poll1, sizeof poll1);
+ reg_w_buf(gspca_dev, poll2, sizeof poll2);
+ reg_w_buf(gspca_dev, poll3, sizeof poll3);
+ reg_w_buf(gspca_dev, poll4, sizeof poll4);
+ }
}
-static void setcolors(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- __u16 reg_to_write;
+ int i, mode;
+ __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
+ static const __u8 t3[] =
+ { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
+ 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
+
+ mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
+ switch (mode) {
+ case 1: /* 352x288 */
+ t2[1] = 0x40;
+ break;
+ case 2: /* 320x240 */
+ t2[1] = 0x10;
+ break;
+ case 3: /* 176x144 */
+ t2[1] = 0x50;
+ break;
+ case 4: /* 160x120 */
+ t2[1] = 0x20;
+ break;
+ default: /* 640x480 (0x00) */
+ break;
+ }
- reg_to_write = 0xc0bb + sd->colors * 0x100;
- reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
+ if (sd->sensor == SENSOR_TAS5130A) {
+ i = 0;
+ while (tas5130a_sensor_init[i][0] != 0) {
+ reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
+ sizeof tas5130a_sensor_init[0]);
+ i++;
+ }
+ reg_w(gspca_dev, 0x3c80);
+ /* just in case and to keep sync with logs (for mine) */
+ reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
+ sizeof tas5130a_sensor_init[0]);
+ reg_w(gspca_dev, 0x3c80);
+ } else {
+ om6802_sensor_init(gspca_dev);
+ }
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
+ sizeof sensor_data[sd->sensor].data4);
+ reg_r(gspca_dev, 0x0012);
+ reg_w_buf(gspca_dev, t2, sizeof t2);
+ reg_w_buf(gspca_dev, t3, sizeof t3);
+ reg_w(gspca_dev, 0x0013);
+ msleep(15);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+ sizeof sensor_data[sd->sensor].stream);
+ poll_sensor(gspca_dev);
+
+ /* restart on each start, just in case, sometimes regs goes wrong
+ * when using controls from app */
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ setcolors(gspca_dev);
+ return 0;
}
-static void setgamma(struct gspca_dev *gspca_dev)
+static void sd_stopN(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+ sizeof sensor_data[sd->sensor].stream);
+ msleep(20);
+ reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+ sizeof sensor_data[sd->sensor].stream);
+ msleep(20);
+ reg_w(gspca_dev, 0x0309);
}
-static void setsharpness(struct gspca_dev *gspca_dev)
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ struct gspca_frame *frame, /* target */
+ __u8 *data, /* isoc packet */
+ int len) /* iso packet length */
{
- struct sd *sd = (struct sd *) gspca_dev;
- __u16 reg_to_write;
+ static __u8 ffd9[] = { 0xff, 0xd9 };
- reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
+ if (data[0] == 0x5a) {
+ /* Control Packet, after this came the header again,
+ * but extra bytes came in the packet before this,
+ * sometimes an EOF arrives, sometimes not... */
+ return;
+ }
+ data += 2;
+ len -= 2;
+ if (data[0] == 0xff && data[1] == 0xd8) {
+ /* extra bytes....., could be processed too but would be
+ * a waste of time, right now leave the application and
+ * libjpeg do it for ourserlves.. */
+ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+ ffd9, 2);
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
+ return;
+ }
- reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
+ if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+ /* Just in case, i have seen packets with the marker,
+ * other's do not include it... */
+ len -= 2;
+ }
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -781,6 +1043,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
+
*val = sd->gamma;
return 0;
}
@@ -828,9 +1091,9 @@ static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
sd->autogain = val;
if (val != 0)
- reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
+ reg_w(gspca_dev, 0xf48e);
else
- reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
+ reg_w(gspca_dev, 0xb48e);
return 0;
}
@@ -842,111 +1105,6 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
-{
- int mode;
-
- static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
- __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
- static const __u8 t3[] =
- { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
- 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
- static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
-
- mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
- switch (mode) {
- case 1: /* 352x288 */
- t2[1] = 0x40;
- break;
- case 2: /* 320x240 */
- t2[1] = 0x10;
- break;
- case 3: /* 176x144 */
- t2[1] = 0x50;
- break;
- case 4: /* 160x120 */
- t2[1] = 0x20;
- break;
- default: /* 640x480 (0x00) */
- break;
- }
-
- reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
- reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
- reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
- reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
- reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
- /* just in case and to keep sync with logs (for mine) */
- reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
- reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
- /* just in case and to keep sync with logs (for mine) */
- reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
- reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
- reg_r_1(gspca_dev, 0x0012);
- reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
- reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
- reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
- /* restart on each start, just in case, sometimes regs goes wrong
- * when using controls from app */
- setbrightness(gspca_dev);
- setcontrast(gspca_dev);
- setcolors(gspca_dev);
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
- struct gspca_frame *frame, /* target */
- __u8 *data, /* isoc packet */
- int len) /* iso packet length */
-{
- int sof = 0;
- static __u8 ffd9[] = { 0xff, 0xd9 };
-
- if (data[0] == 0x5a) {
- /* Control Packet, after this came the header again,
- * but extra bytes came in the packet before this,
- * sometimes an EOF arrives, sometimes not... */
- return;
- }
-
- if (data[len - 1] == 0xff && data[len] == 0xd9) {
- /* Just in case, i have seen packets with the marker,
- * other's do not include it... */
- data += 2;
- len -= 4;
- } else if (data[2] == 0xff && data[3] == 0xd8) {
- sof = 1;
- data += 2;
- len -= 2;
- } else {
- data += 2;
- len -= 2;
- }
-
- if (sof) {
- /* extra bytes....., could be processed too but would be
- * a waste of time, right now leave the application and
- * libjpeg do it for ourserlves.. */
- frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
- ffd9, 2);
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
- return;
- }
-
- gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
-}
-
static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu)
{
@@ -972,24 +1130,15 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
return -EINVAL;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
-{
- init_default_parameters(gspca_dev);
- return 0;
-}
-
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
};
@@ -1014,6 +1163,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
index 1ff8ba2f7fe..968a5911704 100644
--- a/drivers/media/video/gspca/tv8532.c
+++ b/drivers/media/video/gspca/tv8532.c
@@ -331,8 +331,8 @@ static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
}
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
@@ -390,7 +390,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
}
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
@@ -443,6 +443,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
/************************************************/
tv_8532_PollReg(gspca_dev);
reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -450,14 +451,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
}
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void tv8532_preprocess(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -611,11 +604,9 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
- .stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
};
@@ -644,6 +635,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index f4a52956e0d..be46d923254 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -69,6 +69,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+#define LIGHTFREQ_IDX 1
{
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -79,7 +80,6 @@ static struct ctrl sd_ctrls[] = {
.step = 1,
#define FREQ_DEF 1
.default_value = FREQ_DEF,
- .default_value = 1,
},
.set = sd_setfreq,
.get = sd_getfreq,
@@ -87,12 +87,12 @@ static struct ctrl sd_ctrls[] = {
};
static struct v4l2_pix_format vc0321_mode[] = {
- {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
+ {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
- {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
+ {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
.bytesperline = 640,
.sizeimage = 640 * 480 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
@@ -1463,6 +1463,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->qindex = 7;
sd->autogain = AUTOGAIN_DEF;
sd->lightfreq = FREQ_DEF;
+ if (sd->sensor != SENSOR_OV7670)
+ gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
if (sd->bridge == BRIDGE_VC0321) {
reg_r(gspca_dev, 0x8a, 0, 3);
@@ -1474,8 +1476,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
return 0;
}
@@ -1499,7 +1501,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
const __u8 *GammaT = NULL;
@@ -1583,7 +1585,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
break;
default:
PDEBUG(D_PROBE, "Damned !! no sensor found Bye");
- return;
+ return -EMEDIUMTYPE;
}
if (GammaT && MatrixT) {
put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
@@ -1619,6 +1621,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
setautogain(gspca_dev);
setlightfreq(gspca_dev);
}
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1637,19 +1640,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
reg_w(dev, 0x89, 0xffff, 0xffff);
}
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-/* struct usb_device *dev = gspca_dev->dev;
- __u8 buffread;
-
- reg_w(dev, 0x89, 0xffff, 0xffff);
- reg_w(dev, 0xa0, 0x01, 0xb301);
- reg_w(dev, 0xa0, 0x09, 0xb303);
- reg_w(dev, 0x89, 0xffff, 0xffff);
-*/
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1738,11 +1728,10 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
};
@@ -1774,6 +1763,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index bc7d0eedcd8..d0a4451dc46 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -85,6 +85,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
#define SD_BRIGHTNESS 0
{
{
@@ -141,6 +142,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+#define LIGHTFREQ_IDX 4
#define SD_FREQ 4
{
{
@@ -6574,8 +6576,8 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
cs2102_60HZ, cs2102_60HZScale},
/* SENSOR_CS2102K 1 */
{cs2102_NoFliker, cs2102_NoFlikerScale,
- cs2102_50HZ, cs2102_50HZScale,
- cs2102_60HZ, cs2102_60HZScale},
+ NULL, NULL, /* currently disabled */
+ NULL, NULL},
/* SENSOR_GC0305 2 */
{gc0305_NoFliker, gc0305_NoFliker,
gc0305_50HZ, gc0305_50HZ,
@@ -6964,8 +6966,13 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
case SENSOR_MC501CB:
return -1; /* don't probe */
case SENSOR_TAS5130C_VF0250:
- /* may probe but with write in reg 0x0010 */
+ /* may probe but with no write in reg 0x0010 */
return -1; /* don't probe */
+ case SENSOR_PAS106:
+ sensor = sif_probe(gspca_dev);
+ if (sensor >= 0)
+ return sensor;
+ break;
}
sensor = vga_2wr_probe(gspca_dev);
if (sensor >= 0) {
@@ -6974,12 +6981,10 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
/* next probe is needed for OmniVision ? */
}
sensor2 = vga_3wr_probe(gspca_dev);
- if (sensor2 >= 0) {
- if (sensor >= 0)
- return sensor;
- return sensor2;
- }
- return sif_probe(gspca_dev);
+ if (sensor2 >= 0
+ && sensor >= 0)
+ return sensor;
+ return sensor2;
}
/* this function is called at probe time */
@@ -7147,19 +7152,33 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
+ switch (sd->sensor) {
+ case SENSOR_GC0305:
+ case SENSOR_OV7620:
+ case SENSOR_PO2030:
+ gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX);
+ break;
+ case SENSOR_HDCS2020:
+ case SENSOR_HV7131B:
+ case SENSOR_HV7131C:
+ case SENSOR_OV7630C:
+ gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
+ break;
+ }
+
/* switch the led off */
reg_w(gspca_dev->dev, 0x01, 0x0000);
return 0;
}
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
{
reg_w(gspca_dev->dev, 0x01, 0x0000);
return 0;
}
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
@@ -7312,10 +7331,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w(dev, 0x02, 0x0008);
break;
}
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
+ return 0;
}
static void sd_stop0(struct gspca_dev *gspca_dev)
@@ -7325,11 +7341,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
send_unknown(gspca_dev->dev, sd->sensor);
}
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame,
__u8 *data,
@@ -7489,37 +7500,30 @@ static const struct sd_desc sd_desc = {
.ctrls = sd_ctrls,
.nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
.config = sd_config,
- .open = sd_open,
+ .init = sd_init,
.start = sd_start,
- .stopN = sd_stopN,
.stop0 = sd_stop0,
- .close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
};
static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x041e)},
-#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x041e, 0x4017)},
- {USB_DEVICE(0x041e, 0x401c)},
+ {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
{USB_DEVICE(0x041e, 0x401e)},
{USB_DEVICE(0x041e, 0x401f)},
-#endif
+ {USB_DEVICE(0x041e, 0x4022)},
{USB_DEVICE(0x041e, 0x4029)},
-#ifndef CONFIG_USB_ZC0301
- {USB_DEVICE(0x041e, 0x4034)},
- {USB_DEVICE(0x041e, 0x4035)},
+ {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
{USB_DEVICE(0x041e, 0x4036)},
{USB_DEVICE(0x041e, 0x403a)},
-#endif
{USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250},
{USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250},
-#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x0458, 0x7007)},
{USB_DEVICE(0x0458, 0x700c)},
{USB_DEVICE(0x0458, 0x700f)},
-#endif
{USB_DEVICE(0x0461, 0x0a00)},
{USB_DEVICE(0x046d, 0x08a0)},
{USB_DEVICE(0x046d, 0x08a1)},
@@ -7531,7 +7535,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x046d, 0x08aa)},
{USB_DEVICE(0x046d, 0x08ac)},
{USB_DEVICE(0x046d, 0x08ad)},
-#ifndef CONFIG_USB_ZC0301
+#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
{USB_DEVICE(0x046d, 0x08ae)},
#endif
{USB_DEVICE(0x046d, 0x08af)},
@@ -7541,27 +7545,25 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x046d, 0x08d8)},
{USB_DEVICE(0x046d, 0x08da)},
{USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
- {USB_DEVICE(0x0471, 0x0325)},
- {USB_DEVICE(0x0471, 0x0326)},
- {USB_DEVICE(0x0471, 0x032d)},
- {USB_DEVICE(0x0471, 0x032e)},
+ {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
{USB_DEVICE(0x055f, 0xc005)},
-#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x055f, 0xd003)},
{USB_DEVICE(0x055f, 0xd004)},
-#endif
{USB_DEVICE(0x0698, 0x2003)},
+ {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
{USB_DEVICE(0x0ac8, 0x0302)},
-#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x0ac8, 0x301b)},
+#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
{USB_DEVICE(0x0ac8, 0x303b)},
#endif
{USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
-#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x0ac8, 0x307b)},
{USB_DEVICE(0x10fd, 0x0128)},
+ {USB_DEVICE(0x10fd, 0x804d)},
{USB_DEVICE(0x10fd, 0x8050)},
-#endif
{} /* end of entry */
};
#undef DVNAME
@@ -7581,6 +7583,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
static int __init sd_mod_init(void)
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index a30254bed31..efe849981ab 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -12,6 +12,10 @@
* Markus Rechberger <mrechberger@gmail.com>
* modified for DViCO Fusion HDTV 5 RT GOLD by
* Chaogui Zhang <czhang1974@gmail.com>
+ * modified for MSI TV@nywhere Plus by
+ * Henry Wong <henry@stuffedcow.net>
+ * Mark Schultz <n9xmj@yahoo.com>
+ * Brian Rogers <brian_rogers@comcast.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
@@ -65,7 +69,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int size, int offset)
{
unsigned char buf[6];
- int start, range, toggle, dev, code;
+ int start, range, toggle, dev, code, ircode;
/* poll IR chip */
if (size != i2c_master_recv(&ir->c,buf,size))
@@ -85,6 +89,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
if (!start)
/* no key pressed */
return 0;
+ /*
+ * Hauppauge remotes (black/silver) always use
+ * specific device ids. If we do not filter the
+ * device ids then messages destined for devices
+ * such as TVs (id=0) will get through causing
+ * mis-fired events.
+ *
+ * We also filter out invalid key presses which
+ * produce annoying debug log entries.
+ */
+ ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
+ if ((ircode & 0x1fff)==0x1fff)
+ /* invalid key press */
+ return 0;
+
+ if (dev!=0x1e && dev!=0x1f)
+ /* not a hauppauge remote */
+ return 0;
if (!range)
code += 64;
@@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
/* return key */
*ir_key = code;
- *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code;
+ *ir_raw = ircode;
return 1;
}
@@ -224,9 +246,15 @@ static void ir_timer(unsigned long data)
static void ir_work(struct work_struct *work)
{
struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+ int polling_interval = 100;
+
+ /* MSI TV@nywhere Plus requires more frequent polling
+ otherwise it will miss some keypresses */
+ if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+ polling_interval = 50;
ir_key_poll(ir);
- mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100));
+ mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval));
}
/* ----------------------------------------------------------------------- */
@@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap)
(1 == rc) ? "yes" : "no");
if (1 == rc) {
ir_attach(adap, probe[i], 0, 0);
- break;
+ return 0;
}
}
+
+ /* Special case for MSI TV@nywhere Plus remote */
+ if (adap->id == I2C_HW_SAA7134) {
+ u8 temp;
+
+ /* MSI TV@nywhere Plus controller doesn't seem to
+ respond to probes unless we read something from
+ an existing device. Weird... */
+
+ msg.addr = 0x50;
+ rc = i2c_transfer(adap, &msg, 1);
+ dprintk(1, "probe 0x%02x @ %s: %s\n",
+ msg.addr, adap->name,
+ (1 == rc) ? "yes" : "no");
+
+ /* Now do the probe. The controller does not respond
+ to 0-byte reads, so we use a 1-byte read instead. */
+ msg.addr = 0x30;
+ msg.len = 1;
+ msg.buf = &temp;
+ rc = i2c_transfer(adap, &msg, 1);
+ dprintk(1, "probe 0x%02x @ %s: %s\n",
+ msg.addr, adap->name,
+ (1 == rc) ? "yes" : "no");
+ if (1 == rc)
+ ir_attach(adap, msg.addr, 0, 0);
+ }
+
return 0;
}
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 381af1bceef..0b8fe85fb69 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -154,7 +154,7 @@
#define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
V4L2_CAP_SLICED_VBI_CAPTURE)
-#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
+#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \
V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
struct ivtv_card_video_input {
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index aea1664948c..aeaa13f6cb3 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -61,14 +61,14 @@
#include "tuner-xc2028.h"
/* var to keep track of the number of array elements in use */
-int ivtv_cards_active = 0;
+int ivtv_cards_active;
/* If you have already X v4l cards, then set this to X. This way
the device numbers stay matched. Example: you have a WinTV card
without radio and a PVR-350 with. Normally this would give a
video1 device together with a radio0 device for the PVR. By
setting this to 1 you ensure that radio0 is now also radio1. */
-int ivtv_first_minor = 0;
+int ivtv_first_minor;
/* Master variable for all ivtv info */
struct ivtv *ivtv_cards[IVTV_MAX_CARDS];
@@ -251,7 +251,7 @@ MODULE_PARM_DESC(newi2c,
"\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
"\t\t\tDefault is autodetect");
-MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card");
+MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card");
MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
MODULE_DESCRIPTION("CX23415/CX23416 driver");
@@ -655,9 +655,9 @@ done:
if (itv->card == NULL) {
itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
- IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n",
+ IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
itv->dev->vendor, itv->dev->device);
- IVTV_ERR(" subsystem vendor/device: %04x/%04x\n",
+ IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n",
itv->dev->subsystem_vendor, itv->dev->subsystem_device);
IVTV_ERR(" %s based\n", chipname);
IVTV_ERR("Defaulting to %s card\n", itv->card->name);
@@ -688,7 +688,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
spin_lock_init(&itv->lock);
spin_lock_init(&itv->dma_reg_lock);
- itv->irq_work_queues = create_workqueue(itv->name);
+ itv->irq_work_queues = create_singlethread_workqueue(itv->name);
if (itv->irq_work_queues == NULL) {
IVTV_ERR("Could not create ivtv workqueue\n");
return -1;
@@ -720,7 +720,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->speed = 1000;
/* VBI */
- itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
/* Init the sg table for osd/yuv output */
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index ab287b48fc2..bc29436e8a3 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -49,7 +49,6 @@
#include <linux/i2c-algo-bit.h>
#include <linux/list.h>
#include <linux/unistd.h>
-#include <linux/byteorder/swab.h>
#include <linux/pagemap.h>
#include <linux/scatterlist.h>
#include <linux/workqueue.h>
@@ -251,6 +250,7 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */
#define IVTV_F_I_INITED 21 /* set after first open */
#define IVTV_F_I_FAILED 22 /* set if first open failed */
+#define IVTV_F_I_WORK_INITED 23 /* worker thread was initialized */
/* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@@ -506,6 +506,8 @@ struct yuv_playback_info
struct v4l2_rect main_rect;
u32 v4l2_src_w;
u32 v4l2_src_h;
+
+ u8 running; /* Have any frames been displayed */
};
#define IVTV_VBI_FRAMES 32
@@ -750,6 +752,12 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
/* First-open initialization: load firmware, init cx25840, etc. */
int ivtv_init_on_first_open(struct ivtv *itv);
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int ivtv_raw_vbi(const struct ivtv *itv)
+{
+ return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
+}
+
/* This is a PCI post thing, where if the pci register is not read, then
the write doesn't always take effect right away. By reading back the
register any pending PCI writes will be performed (in order), and so
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 7ec5c99f9ad..1c404e454a3 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -39,7 +39,7 @@
associated VBI streams are also automatically claimed.
Possible error returns: -EBUSY if someone else has claimed
the stream or 0 on success. */
-int ivtv_claim_stream(struct ivtv_open_id *id, int type)
+static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
{
struct ivtv *itv = id->itv;
struct ivtv_stream *s = &itv->streams[type];
@@ -78,7 +78,7 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type)
if (type == IVTV_DEC_STREAM_TYPE_MPG) {
vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
} else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
- itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) {
+ itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
} else {
return 0;
@@ -305,7 +305,7 @@ static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *b
if (len > ucount) len = ucount;
if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
- itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) {
+ !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
const char *start = buf->buf + buf->readpos;
const char *p = start + 1;
const u8 *q;
@@ -372,7 +372,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
/* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
arrive one-by-one, so make sure we never output more than one VBI frame at a time */
if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
- (s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set))
+ (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
single_frame = 1;
for (;;) {
@@ -600,13 +600,14 @@ retry:
since we may get here before the stream has been fully set-up */
if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
while (count >= itv->dma_data_req_size) {
- if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) {
- bytes_written += itv->dma_data_req_size;
- user_buf += itv->dma_data_req_size;
- count -= itv->dma_data_req_size;
- } else {
- break;
- }
+ rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf);
+
+ if (rc < 0)
+ return rc;
+
+ bytes_written += itv->dma_data_req_size;
+ user_buf += itv->dma_data_req_size;
+ count -= itv->dma_data_req_size;
}
if (count == 0) {
IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h
index 2c8d5186c9c..df81e790147 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.h
+++ b/drivers/media/video/ivtv/ivtv-fileops.h
@@ -38,11 +38,6 @@ void ivtv_unmute(struct ivtv *itv);
/* Utilities */
-/* Try to claim a stream for the filehandle. Return 0 on success,
- -EBUSY if stream already claimed. Once a stream is claimed, it
- remains claimed until the associated filehandle is closed. */
-int ivtv_claim_stream(struct ivtv_open_id *id, int type);
-
/* Release a previously claimed stream. */
void ivtv_release_stream(struct ivtv_stream *s);
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index bc22905ea20..74a44844cca 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv)
}
/* Xceive tuner reset function */
-int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
{
struct i2c_algo_bit_data *algo = dev;
struct ivtv *itv = algo->data;
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h
index 964a265d91a..48b6291613a 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.h
+++ b/drivers/media/video/ivtv/ivtv-gpio.h
@@ -24,7 +24,7 @@
/* GPIO stuff */
void ivtv_gpio_init(struct ivtv *itv);
void ivtv_reset_ir_gpio(struct ivtv *itv);
-int ivtv_reset_tuner_gpio(void *dev, int cmd, int value);
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg);
#endif
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index af154238fb9..24700c211d5 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -64,8 +64,6 @@
#include "ivtv-gpio.h"
#include "ivtv-i2c.h"
-#include <media/ir-kbd-i2c.h>
-
/* i2c implementation for cx23415/6 chip, ivtv project.
* Author: Kevin Thayer (nufan_wfk at yahoo.com)
*/
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 61030309d0a..208fb54842f 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
}
}
-static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
{
int f, l;
- u16 set = 0;
for (f = 0; f < 2; f++) {
for (l = 0; l < 24; l++) {
fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
- set |= fmt->service_lines[f][l];
}
}
- return set != 0;
}
u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
@@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
int h = fmt->fmt.pix.height;
w = min(w, 720);
- w = max(w, 1);
+ w = max(w, 2);
h = min(h, itv->is_50hz ? 576 : 480);
h = max(h, 2);
ivtv_g_fmt_vid_cap(file, fh, fmt);
@@ -512,27 +509,34 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_
static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct ivtv_open_id *id = fh;
- s32 w, h;
- int field;
- int ret;
+ s32 w = fmt->fmt.pix.width;
+ s32 h = fmt->fmt.pix.height;
+ int field = fmt->fmt.pix.field;
+ int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
- w = fmt->fmt.pix.width;
- h = fmt->fmt.pix.height;
- field = fmt->fmt.pix.field;
- ret = ivtv_g_fmt_vid_out(file, fh, fmt);
+ w = min(w, 720);
+ w = max(w, 2);
+ /* Why can the height be 576 even when the output is NTSC?
+
+ Internally the buffers of the PVR350 are always set to 720x576. The
+ decoded video frame will always be placed in the top left corner of
+ this buffer. For any video which is not 720x576, the buffer will
+ then be cropped to remove the unused right and lower areas, with
+ the remaining image being scaled by the hardware to fit the display
+ area. The video can be scaled both up and down, so a 720x480 video
+ can be displayed full-screen on PAL and a 720x576 video can be
+ displayed without cropping on NTSC.
+
+ Note that the scaling only occurs on the video stream, the osd
+ resolution is locked to the broadcast standard and not scaled.
+
+ Thanks to Ian Armstrong for this explanation. */
+ h = min(h, 576);
+ h = max(h, 2);
+ if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
+ fmt->fmt.pix.field = field;
fmt->fmt.pix.width = w;
fmt->fmt.pix.height = h;
- if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) {
- fmt->fmt.pix.field = field;
- if (fmt->fmt.pix.width < 2)
- fmt->fmt.pix.width = 2;
- if (fmt->fmt.pix.width > 720)
- fmt->fmt.pix.width = 720;
- if (fmt->fmt.pix.height < 2)
- fmt->fmt.pix.height = 2;
- if (fmt->fmt.pix.height > 576)
- fmt->fmt.pix.height = 576;
- }
return ret;
}
@@ -560,9 +564,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
struct ivtv_open_id *id = fh;
struct ivtv *itv = id->itv;
struct cx2341x_mpeg_params *p = &itv->params;
+ int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
- int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
if (ret)
return ret;
@@ -585,8 +589,11 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+ if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+ return -EBUSY;
itv->vbi.sliced_in->service_set = 0;
- itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
+ itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
return ivtv_g_fmt_vbi_cap(file, fh, fmt);
}
@@ -600,10 +607,10 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
return ret;
- if (check_service_set(vbifmt, itv->is_50hz) == 0)
- return -EINVAL;
- if (atomic_read(&itv->capturing) > 0)
+ check_service_set(vbifmt, itv->is_50hz);
+ if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
return -EBUSY;
+ itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
return 0;
@@ -651,8 +658,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
itv->dma_data_req_size =
1080 * ((yi->v4l2_src_h + 31) & ~31);
- /* Force update of yuv registers */
- yi->yuv_forced_update = 1;
return 0;
}
@@ -761,7 +766,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
- strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
+ snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev));
vcap->version = IVTV_DRIVER_VERSION; /* version */
vcap->capabilities = itv->v4l2_cap; /* capabilities */
return 0;
@@ -1370,6 +1375,9 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
if (itv->osd_global_alpha_state)
fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ if (yi->track_osd)
+ fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+
pixfmt &= 7;
/* no local alpha for RGB565 or unknown formats */
@@ -1389,8 +1397,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
else
fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
}
- if (yi->track_osd)
- fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
return 0;
}
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index fba150a6cd2..f5d00ec5da7 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -76,6 +76,13 @@ void ivtv_irq_work_handler(struct work_struct *work)
DEFINE_WAIT(wait);
+ if (test_and_clear_bit(IVTV_F_I_WORK_INITED, &itv->i_flags)) {
+ struct sched_param param = { .sched_priority = 99 };
+
+ /* This thread must use the FIFO scheduler as it
+ is realtime sensitive. */
+ sched_setscheduler(current, SCHED_FIFO, &param);
+ }
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
ivtv_pio_work_handler(itv);
@@ -678,34 +685,14 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
{
- struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s;
IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
- /* If more than two VBI buffers are pending, then
- clear the old ones and start with this new one.
- This can happen during transition stages when MPEG capturing is
- started, but the first interrupts haven't arrived yet. During
- that period VBI requests can accumulate without being able to
- DMA the data. Since at most four VBI DMA buffers are available,
- we just drop the old requests when there are already three
- requests queued. */
- if (s->sg_pending_size > 2) {
- struct ivtv_buffer *buf;
- list_for_each_entry(buf, &s->q_predma.list, list)
- ivtv_buf_sync_for_cpu(s, buf);
- ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
- s->sg_pending_size = 0;
- }
- /* if we can append the data, and the MPEG stream isn't capturing,
- then start a DMA request for just the VBI data. */
- if (!stream_enc_dma_append(s, data) &&
- !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
+ if (!stream_enc_dma_append(s, data))
set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
- }
}
static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
@@ -766,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
*/
unsigned int frame = read_reg(0x28c0) & 1;
struct yuv_playback_info *yi = &itv->yuv_info;
- int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame);
+ int last_dma_frame = atomic_read(&yi->next_dma_frame);
struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
@@ -785,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
atomic_set(&yi->next_dma_frame, next_dma_frame);
yi->fields_lapsed = -1;
+ yi->running = 1;
}
}
}
@@ -817,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
/* Check if we need to update the yuv registers */
- if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) {
+ if (yi->running && (yi->yuv_forced_update || f->update)) {
if (!f->update) {
- last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS;
+ last_dma_frame =
+ (u8)(atomic_read(&yi->next_dma_frame) -
+ 1) % IVTV_YUV_BUFFERS;
f = &yi->new_frame_info[last_dma_frame];
}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
index 7cfc0c9ab05..476556afd39 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -23,7 +23,7 @@
#define IVTV_QUEUE_H
#define IVTV_DMA_UNMAPPED ((u32) -1)
-#define SLICED_VBI_PIO 1
+#define SLICED_VBI_PIO 0
/* ivtv_buffer utility functions */
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 54d2023b26c..5bbf31e3930 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = {
static struct {
const char *name;
int vfl_type;
- int minor_offset;
+ int num_offset;
int dma, pio;
enum v4l2_buf_type buf_type;
const struct file_operations *fops;
@@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
static int ivtv_prep_dev(struct ivtv *itv, int type)
{
struct ivtv_stream *s = &itv->streams[type];
- int minor_offset = ivtv_stream_info[type].minor_offset;
- int minor;
+ int num_offset = ivtv_stream_info[type].num_offset;
+ int num = itv->num + ivtv_first_minor + num_offset;
/* These four fields are always initialized. If v4l2dev == NULL, then
this stream is not in use. In that case no other fields but these
@@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return 0;
- /* card number + user defined offset + device offset */
- minor = itv->num + ivtv_first_minor + minor_offset;
-
/* User explicitly selected 0 buffers for these streams, so don't
create them. */
if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
@@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s",
itv->num, s->name);
- s->v4l2dev->minor = minor;
+ s->v4l2dev->num = num;
s->v4l2dev->parent = &itv->dev->dev;
s->v4l2dev->fops = ivtv_stream_info[type].fops;
s->v4l2dev->release = video_device_release;
@@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
{
struct ivtv_stream *s = &itv->streams[type];
int vfl_type = ivtv_stream_info[type].vfl_type;
- int minor;
+ int num;
if (s->v4l2dev == NULL)
return 0;
- minor = s->v4l2dev->minor;
+ num = s->v4l2dev->num;
+ /* card number + user defined offset + device offset */
+ if (type != IVTV_ENC_STREAM_TYPE_MPG) {
+ struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
+
+ if (s_mpg->v4l2dev)
+ num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
+ }
+
/* Register device. First try the desired minor, then any free one. */
- if (video_register_device(s->v4l2dev, vfl_type, minor) &&
- video_register_device(s->v4l2dev, vfl_type, -1)) {
- IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n",
- s->name, minor);
+ if (video_register_device(s->v4l2dev, vfl_type, num)) {
+ IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
+ s->name, num);
video_device_release(s->v4l2dev);
s->v4l2dev = NULL;
return -ENOMEM;
}
+ num = s->v4l2dev->num;
switch (vfl_type) {
case VFL_TYPE_GRABBER:
IVTV_INFO("Registered device video%d for %s (%d kB)\n",
- s->v4l2dev->minor, s->name, itv->options.kilobytes[type]);
+ num, s->name, itv->options.kilobytes[type]);
break;
case VFL_TYPE_RADIO:
IVTV_INFO("Registered device radio%d for %s\n",
- s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+ num, s->name);
break;
case VFL_TYPE_VBI:
if (itv->options.kilobytes[type])
IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
- s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN,
- s->name, itv->options.kilobytes[type]);
+ num, s->name, itv->options.kilobytes[type]);
else
IVTV_INFO("Registered device vbi%d for %s\n",
- s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+ num, s->name);
break;
}
return 0;
@@ -330,7 +334,7 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
static void ivtv_vbi_setup(struct ivtv *itv)
{
- int raw = itv->vbi.sliced_in->service_set == 0;
+ int raw = ivtv_raw_vbi(itv);
u32 data[CX2341X_MBOX_MAX_DATA];
int lines;
int i;
@@ -363,7 +367,7 @@ static void ivtv_vbi_setup(struct ivtv *itv)
/* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
data[1] = 1;
/* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
- data[2] = raw ? 4 : 8;
+ data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
/* The start/stop codes determine which VBI lines end up in the raw VBI data area.
The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index 71798f0da27..4a37a7d2e69 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -293,6 +293,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
u32 line_size = itv->vbi.sliced_decoder_line_size;
struct v4l2_decode_vbi_line vbi;
int i;
+ unsigned lines = 0;
/* find the first valid line */
for (i = 0; i < size; i++, buf++) {
@@ -313,7 +314,8 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
}
vbi.p = p + 4;
itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
- if (vbi.type) {
+ if (vbi.type && !(lines & (1 << vbi.line))) {
+ lines |= 1 << vbi.line;
itv->vbi.sliced_data[line].id = vbi.type;
itv->vbi.sliced_data[line].field = vbi.is_second_field;
itv->vbi.sliced_data[line].line = vbi.line;
@@ -332,7 +334,7 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
int y;
/* Raw VBI data */
- if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
+ if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
u8 type;
ivtv_buf_swap(buf);
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
index 442f43f11b7..8cd753d30bf 100644
--- a/drivers/media/video/ivtv/ivtv-version.h
+++ b/drivers/media/video/ivtv/ivtv-version.h
@@ -22,7 +22,7 @@
#define IVTV_DRIVER_NAME "ivtv"
#define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 3
+#define IVTV_DRIVER_VERSION_MINOR 4
#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index 3092ff1d00a..ee91107376c 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv)
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
ivtv_waitq(&itv->vsync_waitq);
+ yi->running = 0;
atomic_set(&yi->next_dma_frame, -1);
atomic_set(&yi->next_fill_frame, 0);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index bdfda48e56b..8a4a150b12f 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
int size_in_bytes)
{
DEFINE_WAIT(wait);
- int ret = 0;
int got_sig = 0;
mutex_lock(&itv->udma.lock);
@@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
return -EINTR;
}
- return ret;
+ return 0;
}
static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
@@ -368,11 +367,12 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
}
static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
void *dst;
int err = 0;
+ int dma_err;
unsigned long total_size;
struct ivtv *itv = (struct ivtv *) info->par;
unsigned long dma_offset =
@@ -399,7 +399,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
if (count + p > total_size) {
if (!err)
err = -ENOSPC;
-
count = total_size - p;
}
@@ -408,39 +407,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (!access_ok(VERIFY_READ, buf, count)) {
- IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
- (unsigned long)buf);
- err = -EFAULT;
- }
-
- if (!err) {
- /* If transfer size > threshold and both src/dst
- addresses are aligned, use DMA */
- if (count >= 4096 &&
- ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
- /* Odd address = can't DMA. Align */
- if ((unsigned long)dst & 3) {
- lead = 4 - ((unsigned long)dst & 3);
- memcpy(dst, buf, lead);
- buf += lead;
- dst += lead;
- }
- /* DMA resolution is 32 bits */
- if ((count - lead) & 3)
- tail = (count - lead) & 3;
- /* DMA the data */
- dma_size = count - lead - tail;
- err = ivtvfb_prep_dec_dma_to_device(itv,
- p + lead + dma_offset, (void *)buf, dma_size);
- dst += dma_size;
- buf += dma_size;
- /* Copy any leftover data */
- if (tail)
- memcpy(dst, buf, tail);
- } else {
- memcpy(dst, buf, count);
+ /* If transfer size > threshold and both src/dst
+ addresses are aligned, use DMA */
+ if (count >= 4096 &&
+ ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
+ /* Odd address = can't DMA. Align */
+ if ((unsigned long)dst & 3) {
+ lead = 4 - ((unsigned long)dst & 3);
+ if (copy_from_user(dst, buf, lead))
+ return -EFAULT;
+ buf += lead;
+ dst += lead;
}
+ /* DMA resolution is 32 bits */
+ if ((count - lead) & 3)
+ tail = (count - lead) & 3;
+ /* DMA the data */
+ dma_size = count - lead - tail;
+ dma_err = ivtvfb_prep_dec_dma_to_device(itv,
+ p + lead + dma_offset, (void __user *)buf, dma_size);
+ if (dma_err)
+ return dma_err;
+ dst += dma_size;
+ buf += dma_size;
+ /* Copy any leftover data */
+ if (tail && copy_from_user(dst, buf, tail))
+ return -EFAULT;
+ } else if (copy_from_user(dst, buf, count)) {
+ return -EFAULT;
}
if (!err)
@@ -463,9 +457,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
FB_VBLANK_HAVE_VSYNC;
trace = read_reg(0x028c0) >> 16;
- if (itv->is_50hz && trace > 312) trace -= 312;
- else if (itv->is_60hz && trace > 262) trace -= 262;
- if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
+ if (itv->is_50hz && trace > 312)
+ trace -= 312;
+ else if (itv->is_60hz && trace > 262)
+ trace -= 262;
+ if (trace == 1)
+ vblank.flags |= FB_VBLANK_VSYNCING;
vblank.count = itv->last_vsync_field;
vblank.vcount = trace;
vblank.hcount = 0;
@@ -476,7 +473,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
case FBIO_WAITFORVSYNC:
prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
- if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
+ if (!schedule_timeout(msecs_to_jiffies(50)))
+ rc = -ETIMEDOUT;
finish_wait(&itv->vsync_waitq, &wait);
return rc;
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index 4895540be19..bae2d2beb70 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -33,27 +33,20 @@
* V1.1 Gerard v.d. Horst Added some debugoutput, reset the video-standard
*/
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include "ks0127.h"
-
#include <linux/i2c.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+#include "ks0127.h"
-#define dprintk if (debug) printk
-
-/* i2c identification */
-#define I2C_KS0127_ADDON 0xD8
-#define I2C_KS0127_ONBOARD 0xDA
+MODULE_DESCRIPTION("KS0127 video decoder driver");
+MODULE_AUTHOR("Ryan Drake");
+MODULE_LICENSE("GPL");
#define KS_TYPE_UNKNOWN 0
#define KS_TYPE_0122S 1
@@ -204,8 +197,6 @@ struct adjust {
};
struct ks0127 {
- struct i2c_client *client;
- unsigned char addr;
int format_width;
int format_height;
int cap_width;
@@ -220,16 +211,18 @@ static int debug; /* insmod parameter */
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug output");
-MODULE_LICENSE("GPL");
static u8 reg_defaults[64];
-
-
static void init_reg_defaults(void)
{
+ static int initialized;
u8 *table = reg_defaults;
+ if (initialized)
+ return;
+ initialized = 1;
+
table[KS_CMDA] = 0x2c; /* VSE=0, CCIR 601, autodetect standard */
table[KS_CMDB] = 0x12; /* VALIGN=0, AGC control and input */
table[KS_CMDC] = 0x00; /* Test options */
@@ -308,50 +301,53 @@ static void init_reg_defaults(void)
* An explanation from kayork@mail.utexas.edu:
*
* During I2C reads, the KS0127 only samples for a stop condition
- * during the place where the acknoledge bit should be. Any standard
+ * during the place where the acknowledge bit should be. Any standard
* I2C implementation (correctly) throws in another clock transition
* at the 9th bit, and the KS0127 will not recognize the stop condition
* and will continue to clock out data.
*
* So we have to do the read ourself. Big deal.
- workaround in i2c-algo-bit
+ * workaround in i2c-algo-bit
*/
-static u8 ks0127_read(struct ks0127 *ks, u8 reg)
+static u8 ks0127_read(struct i2c_client *c, u8 reg)
{
- struct i2c_client *c = ks->client;
char val = 0;
struct i2c_msg msgs[] = {
- {c->addr, 0, sizeof(reg), &reg},
- {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}};
+ { c->addr, 0, sizeof(reg), &reg },
+ { c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
+ };
int ret;
ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs))
- dprintk("ks0127_write error\n");
+ v4l_dbg(1, debug, c, "read error\n");
return val;
}
-static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val)
+static void ks0127_write(struct i2c_client *c, u8 reg, u8 val)
{
- char msg[] = {reg, val};
+ struct ks0127 *ks = i2c_get_clientdata(c);
+ char msg[] = { reg, val };
- if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg))
- dprintk("ks0127_write error\n");
+ if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg))
+ v4l_dbg(1, debug, c, "write error\n");
ks->regs[reg] = val;
}
/* generic bit-twiddling */
-static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
+static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v)
{
+ struct ks0127 *ks = i2c_get_clientdata(client);
+
u8 val = ks->regs[reg];
val = (val & and_v) | or_v;
- ks0127_write(ks, reg, val);
+ ks0127_write(client, reg, val);
}
@@ -359,73 +355,69 @@ static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
/****************************************************************************
* ks0127 private api
****************************************************************************/
-static void ks0127_reset(struct ks0127* ks)
+static void ks0127_reset(struct i2c_client *c)
{
- int i;
+ struct ks0127 *ks = i2c_get_clientdata(c);
u8 *table = reg_defaults;
+ int i;
ks->ks_type = KS_TYPE_UNKNOWN;
- dprintk("ks0127: reset\n");
+ v4l_dbg(1, debug, c, "reset\n");
msleep(1);
/* initialize all registers to known values */
/* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
- for(i = 1; i < 33; i++)
- ks0127_write(ks, i, table[i]);
+ for (i = 1; i < 33; i++)
+ ks0127_write(c, i, table[i]);
- for(i = 35; i < 40; i++)
- ks0127_write(ks, i, table[i]);
+ for (i = 35; i < 40; i++)
+ ks0127_write(c, i, table[i]);
- for(i = 41; i < 56; i++)
- ks0127_write(ks, i, table[i]);
+ for (i = 41; i < 56; i++)
+ ks0127_write(c, i, table[i]);
- for(i = 58; i < 64; i++)
- ks0127_write(ks, i, table[i]);
+ for (i = 58; i < 64; i++)
+ ks0127_write(c, i, table[i]);
- if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) {
+ if ((ks0127_read(c, KS_STAT) & 0x80) == 0) {
ks->ks_type = KS_TYPE_0122S;
- dprintk("ks0127: ks0122s Found\n");
+ v4l_dbg(1, debug, c, "ks0122s found\n");
return;
}
- switch(ks0127_read(ks, KS_CMDE) & 0x0f) {
-
+ switch (ks0127_read(c, KS_CMDE) & 0x0f) {
case 0:
ks->ks_type = KS_TYPE_0127;
- dprintk("ks0127: ks0127 found\n");
+ v4l_dbg(1, debug, c, "ks0127 found\n");
break;
case 9:
ks->ks_type = KS_TYPE_0127B;
- dprintk("ks0127: ks0127B Revision A found\n");
+ v4l_dbg(1, debug, c, "ks0127B Revision A found\n");
break;
default:
- dprintk("ks0127: unknown revision\n");
+ v4l_dbg(1, debug, c, "unknown revision\n");
break;
}
}
-static int ks0127_command(struct i2c_client *client,
- unsigned int cmd, void *arg)
+static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
{
- struct ks0127 *ks = i2c_get_clientdata(client);
-
- int *iarg = (int*)arg;
-
+ struct ks0127 *ks = i2c_get_clientdata(c);
+ int *iarg = (int *)arg;
int status;
if (!ks)
return -ENODEV;
switch (cmd) {
-
case DECODER_INIT:
- dprintk("ks0127: command DECODER_INIT\n");
- ks0127_reset(ks);
+ v4l_dbg(1, debug, c, "DECODER_INIT\n");
+ ks0127_reset(c);
break;
case DECODER_SET_INPUT:
@@ -436,161 +428,160 @@ static int ks0127_command(struct i2c_client *client,
case KS_INPUT_COMPOSITE_4:
case KS_INPUT_COMPOSITE_5:
case KS_INPUT_COMPOSITE_6:
- dprintk("ks0127: command DECODER_SET_INPUT %d: "
- "Composite\n", *iarg);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_INPUT %d: Composite\n", *iarg);
/* autodetect 50/60 Hz */
- ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00);
+ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
/* VSE=0 */
- ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00);
+ ks0127_and_or(c, KS_CMDA, ~0x40, 0x00);
/* set input line */
- ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg);
+ ks0127_and_or(c, KS_CMDB, 0xb0, *iarg);
/* non-freerunning mode */
- ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a);
+ ks0127_and_or(c, KS_CMDC, 0x70, 0x0a);
/* analog input */
- ks0127_and_or(ks, KS_CMDD, 0x03, 0x00);
+ ks0127_and_or(c, KS_CMDD, 0x03, 0x00);
/* enable chroma demodulation */
- ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+ ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
/* chroma trap, HYBWR=1 */
- ks0127_and_or(ks, KS_LUMA, 0x00,
+ ks0127_and_or(c, KS_LUMA, 0x00,
(reg_defaults[KS_LUMA])|0x0c);
/* scaler fullbw, luma comb off */
- ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+ ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
/* manual chroma comb .25 .5 .25 */
- ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);
+ ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90);
/* chroma path delay */
- ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);
+ ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90);
- ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
- ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
- ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
- ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+ ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
+ ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
+ ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+ ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
break;
case KS_INPUT_SVIDEO_1:
case KS_INPUT_SVIDEO_2:
case KS_INPUT_SVIDEO_3:
- dprintk("ks0127: command DECODER_SET_INPUT %d: "
- "S-Video\n", *iarg);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_INPUT %d: S-Video\n", *iarg);
/* autodetect 50/60 Hz */
- ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00);
+ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
/* VSE=0 */
- ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00);
+ ks0127_and_or(c, KS_CMDA, ~0x40, 0x00);
/* set input line */
- ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg);
+ ks0127_and_or(c, KS_CMDB, 0xb0, *iarg);
/* non-freerunning mode */
- ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a);
+ ks0127_and_or(c, KS_CMDC, 0x70, 0x0a);
/* analog input */
- ks0127_and_or(ks, KS_CMDD, 0x03, 0x00);
+ ks0127_and_or(c, KS_CMDD, 0x03, 0x00);
/* enable chroma demodulation */
- ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
- ks0127_and_or(ks, KS_LUMA, 0x00,
+ ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
+ ks0127_and_or(c, KS_LUMA, 0x00,
reg_defaults[KS_LUMA]);
/* disable luma comb */
- ks0127_and_or(ks, KS_VERTIA, 0x08,
+ ks0127_and_or(c, KS_VERTIA, 0x08,
(reg_defaults[KS_VERTIA]&0xf0)|0x01);
- ks0127_and_or(ks, KS_VERTIC, 0x0f,
+ ks0127_and_or(c, KS_VERTIC, 0x0f,
reg_defaults[KS_VERTIC]&0xf0);
- ks0127_and_or(ks, KS_CHROMB, 0x0f,
+ ks0127_and_or(c, KS_CHROMB, 0x0f,
reg_defaults[KS_CHROMB]&0xf0);
- ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
- ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
- ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
- ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+ ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
+ ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
+ ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+ ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
break;
case KS_INPUT_YUV656:
- dprintk("ks0127: command DECODER_SET_INPUT 15: "
- "YUV656\n");
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_INPUT 15: YUV656\n");
if (ks->norm == VIDEO_MODE_NTSC ||
ks->norm == KS_STD_PAL_M)
/* force 60 Hz */
- ks0127_and_or(ks, KS_CMDA, 0xfc, 0x03);
+ ks0127_and_or(c, KS_CMDA, 0xfc, 0x03);
else
/* force 50 Hz */
- ks0127_and_or(ks, KS_CMDA, 0xfc, 0x02);
+ ks0127_and_or(c, KS_CMDA, 0xfc, 0x02);
- ks0127_and_or(ks, KS_CMDA, 0xff, 0x40); /* VSE=1 */
+ ks0127_and_or(c, KS_CMDA, 0xff, 0x40); /* VSE=1 */
/* set input line and VALIGN */
- ks0127_and_or(ks, KS_CMDB, 0xb0, (*iarg | 0x40));
+ ks0127_and_or(c, KS_CMDB, 0xb0, (*iarg | 0x40));
/* freerunning mode, */
/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/
- ks0127_and_or(ks, KS_CMDC, 0x70, 0x87);
+ ks0127_and_or(c, KS_CMDC, 0x70, 0x87);
/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
- ks0127_and_or(ks, KS_CMDD, 0x03, 0x08);
+ ks0127_and_or(c, KS_CMDD, 0x03, 0x08);
/* disable chroma demodulation */
- ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);
+ ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30);
/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
- ks0127_and_or(ks, KS_LUMA, 0x00, 0x71);
- ks0127_and_or(ks, KS_VERTIC, 0x0f,
+ ks0127_and_or(c, KS_LUMA, 0x00, 0x71);
+ ks0127_and_or(c, KS_VERTIC, 0x0f,
reg_defaults[KS_VERTIC]&0xf0);
/* scaler fullbw, luma comb off */
- ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+ ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
- ks0127_and_or(ks, KS_CHROMB, 0x0f,
+ ks0127_and_or(c, KS_CHROMB, 0x0f,
reg_defaults[KS_CHROMB]&0xf0);
- ks0127_and_or(ks, KS_CON, 0x00, 0x00);
- ks0127_and_or(ks, KS_BRT, 0x00, 32); /* spec: 34 */
+ ks0127_and_or(c, KS_CON, 0x00, 0x00);
+ ks0127_and_or(c, KS_BRT, 0x00, 32); /* spec: 34 */
/* spec: 229 (e5) */
- ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);
- ks0127_and_or(ks, KS_HUE, 0x00, 0);
+ ks0127_and_or(c, KS_SAT, 0x00, 0xe8);
+ ks0127_and_or(c, KS_HUE, 0x00, 0);
- ks0127_and_or(ks, KS_UGAIN, 0x00, 238);
- ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);
+ ks0127_and_or(c, KS_UGAIN, 0x00, 238);
+ ks0127_and_or(c, KS_VGAIN, 0x00, 0x00);
/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
- ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);
- ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);
+ ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f);
+ ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00);
break;
default:
- dprintk("ks0127: command DECODER_SET_INPUT: "
- "Unknown input %d\n", *iarg);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_INPUT: Unknown input %d\n", *iarg);
break;
}
/* hack: CDMLPF sometimes spontaneously switches on; */
/* force back off */
- ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);
+ ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);
break;
case DECODER_SET_OUTPUT:
switch(*iarg) {
case KS_OUTPUT_YUV656E:
- dprintk("ks0127: command DECODER_SET_OUTPUT: "
- "OUTPUT_YUV656E (Missing)\n");
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n");
return -EINVAL;
- break;
case KS_OUTPUT_EXV:
- dprintk("ks0127: command DECODER_SET_OUTPUT: "
- "OUTPUT_EXV\n");
- ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_OUTPUT: OUTPUT_EXV\n");
+ ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09);
break;
}
break;
- case DECODER_SET_NORM: //sam This block mixes old and new norm names...
+ case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */
/* Set to automatic SECAM/Fsc mode */
- ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+ ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
ks->norm = *iarg;
- switch(*iarg)
- {
+ switch (*iarg) {
/* this is untested !! */
/* It just detects PAL_N/NTSC_M (no special frequencies) */
/* And you have to set the standard a second time afterwards */
case VIDEO_MODE_AUTO:
- dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_NORM: AUTO\n");
/* The chip determines the format */
/* based on the current field rate */
- ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00);
- ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
+ ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
/* This is wrong for PAL ! As I said, */
/* you need to set the standard once again !! */
ks->format_height = 240;
@@ -598,119 +589,120 @@ static int ks0127_command(struct i2c_client *client,
break;
case VIDEO_MODE_NTSC:
- dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");
- ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_NORM: NTSC_M\n");
+ ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
ks->format_height = 240;
ks->format_width = 704;
break;
case KS_STD_NTSC_N:
- dprintk("ks0127: command KS0127_SET_STANDARD: "
- "NTSC_N (fixme)\n");
- ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+ v4l_dbg(1, debug, c,
+ "KS0127_SET_NORM: NTSC_N (fixme)\n");
+ ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
ks->format_height = 240;
ks->format_width = 704;
break;
case VIDEO_MODE_PAL:
- dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");
- ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_NORM: PAL_N\n");
+ ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
ks->format_height = 290;
ks->format_width = 704;
break;
case KS_STD_PAL_M:
- dprintk("ks0127: command KS0127_SET_STANDARD: "
- "PAL_M (fixme)\n");
- ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+ v4l_dbg(1, debug, c,
+ "KS0127_SET_NORM: PAL_M (fixme)\n");
+ ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
ks->format_height = 290;
ks->format_width = 704;
break;
case VIDEO_MODE_SECAM:
- dprintk("ks0127: command KS0127_SET_STANDARD: "
- "SECAM\n");
+ v4l_dbg(1, debug, c,
+ "KS0127_SET_NORM: SECAM\n");
ks->format_height = 290;
ks->format_width = 704;
/* set to secam autodetection */
- ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);
- ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+ ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20);
+ ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
schedule_timeout_interruptible(HZ/10+1);
/* did it autodetect? */
- if (ks0127_read(ks, KS_DEMOD) & 0x40)
+ if (ks0127_read(c, KS_DEMOD) & 0x40)
break;
/* force to secam mode */
- ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);
+ ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
break;
default:
- dprintk("ks0127: command DECODER_SET_NORM: "
- "Unknown norm %d\n", *iarg);
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_NORM: Unknown norm %d\n", *iarg);
break;
}
break;
case DECODER_SET_PICTURE:
- dprintk("ks0127: command DECODER_SET_PICTURE "
- "not yet supported (fixme)\n");
+ v4l_dbg(1, debug, c,
+ "DECODER_SET_PICTURE: not yet supported\n");
return -EINVAL;
- //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE
- //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE
- //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE?
- //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE
- //sam todo: KS0127_SET_AGC_MODE:
- //sam todo: KS0127_SET_AGC:
- //sam todo: KS0127_SET_CHROMA_MODE:
- //sam todo: KS0127_SET_PIXCLK_MODE:
- //sam todo: KS0127_SET_GAMMA_MODE:
- //sam todo: KS0127_SET_UGAIN:
- //sam todo: KS0127_SET_VGAIN:
- //sam todo: KS0127_SET_INVALY:
- //sam todo: KS0127_SET_INVALU:
- //sam todo: KS0127_SET_INVALV:
- //sam todo: KS0127_SET_UNUSEY:
- //sam todo: KS0127_SET_UNUSEU:
- //sam todo: KS0127_SET_UNUSEV:
- //sam todo: KS0127_SET_VSALIGN_MODE:
+ /* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */
+ /* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */
+ /* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */
+ /* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */
+ /* sam todo: KS0127_SET_AGC_MODE: */
+ /* sam todo: KS0127_SET_AGC: */
+ /* sam todo: KS0127_SET_CHROMA_MODE: */
+ /* sam todo: KS0127_SET_PIXCLK_MODE: */
+ /* sam todo: KS0127_SET_GAMMA_MODE: */
+ /* sam todo: KS0127_SET_UGAIN: */
+ /* sam todo: KS0127_SET_VGAIN: */
+ /* sam todo: KS0127_SET_INVALY: */
+ /* sam todo: KS0127_SET_INVALU: */
+ /* sam todo: KS0127_SET_INVALV: */
+ /* sam todo: KS0127_SET_UNUSEY: */
+ /* sam todo: KS0127_SET_UNUSEU: */
+ /* sam todo: KS0127_SET_UNUSEV: */
+ /* sam todo: KS0127_SET_VSALIGN_MODE: */
case DECODER_ENABLE_OUTPUT:
{
-
- int *iarg = arg;
- int enable = (*iarg != 0);
- if (enable) {
- dprintk("ks0127: command "
- "DECODER_ENABLE_OUTPUT on "
- "(%d)\n", enable);
- /* All output pins on */
- ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
- /* Obey the OEN pin */
- ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
- } else {
- dprintk("ks0127: command "
- "DECODER_ENABLE_OUTPUT off "
- "(%d)\n", enable);
- /* Video output pins off */
- ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
- /* Ignore the OEN pin */
- ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
- }
- }
+ int enable;
+
+ iarg = arg;
+ enable = (*iarg != 0);
+ if (enable) {
+ v4l_dbg(1, debug, c,
+ "DECODER_ENABLE_OUTPUT on\n");
+ /* All output pins on */
+ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);
+ /* Obey the OEN pin */
+ ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);
+ } else {
+ v4l_dbg(1, debug, c,
+ "DECODER_ENABLE_OUTPUT off\n");
+ /* Video output pins off */
+ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);
+ /* Ignore the OEN pin */
+ ks0127_and_or(c, KS_CDEM, 0x7f, 0x80);
+ }
break;
+ }
- //sam todo: KS0127_SET_OUTPUT_MODE:
- //sam todo: KS0127_SET_WIDTH:
- //sam todo: KS0127_SET_HEIGHT:
- //sam todo: KS0127_SET_HSCALE:
+ /* sam todo: KS0127_SET_OUTPUT_MODE: */
+ /* sam todo: KS0127_SET_WIDTH: */
+ /* sam todo: KS0127_SET_HEIGHT: */
+ /* sam todo: KS0127_SET_HSCALE: */
case DECODER_GET_STATUS:
- dprintk("ks0127: command DECODER_GET_STATUS\n");
+ v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n");
*iarg = 0;
- status = ks0127_read(ks, KS_STAT);
+ status = ks0127_read(c, KS_STAT);
if (!(status & 0x20)) /* NOVID not set */
*iarg = (*iarg | DECODER_STATUS_GOOD);
if ((status & 0x01)) /* CLOCK set */
@@ -721,124 +713,81 @@ static int ks0127_command(struct i2c_client *client,
*iarg = (*iarg | DECODER_STATUS_NTSC);
break;
- //Catch any unknown command
+ /* Catch any unknown command */
default:
- dprintk("ks0127: command unknown: %04X\n", cmd);
+ v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd);
return -EINVAL;
}
return 0;
}
-
-
-static int ks0127_probe(struct i2c_adapter *adapter);
-static int ks0127_detach(struct i2c_client *client);
-static int ks0127_command(struct i2c_client *client,
- unsigned int cmd, void *arg);
-
-
-
/* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,
- I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};
-static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
-static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
-static struct i2c_client_address_data addr_data = {
- normal_i2c,
- probe,
- ignore,
-};
+#define I2C_KS0127_ADDON 0xD8
+#define I2C_KS0127_ONBOARD 0xDA
-static struct i2c_driver i2c_driver_ks0127 = {
- .driver.name = "ks0127",
- .id = I2C_DRIVERID_KS0127,
- .attach_adapter = ks0127_probe,
- .detach_client = ks0127_detach,
- .command = ks0127_command
+static unsigned short normal_i2c[] = {
+ I2C_KS0127_ADDON >> 1,
+ I2C_KS0127_ONBOARD >> 1,
+ I2C_CLIENT_END
};
-static struct i2c_client ks0127_client_tmpl =
-{
- .name = "(ks0127 unset)",
- .addr = 0,
- .adapter = NULL,
- .driver = &i2c_driver_ks0127,
-};
+I2C_CLIENT_INSMOD;
-static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind)
+static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id)
{
struct ks0127 *ks;
- struct i2c_client *client;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &ks0127_client_tmpl, sizeof(*client));
+ v4l_info(c, "%s chip found @ 0x%x (%s)\n",
+ c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
+ c->addr << 1, c->adapter->name);
ks = kzalloc(sizeof(*ks), GFP_KERNEL);
- if (ks == NULL) {
- kfree(client);
+ if (ks == NULL)
return -ENOMEM;
- }
- i2c_set_clientdata(client, ks);
- client->adapter = adapter;
- client->addr = addr;
- sprintf(client->name, "ks0127-%02x", adapter->id);
+ i2c_set_clientdata(c, ks);
- ks->client = client;
- ks->addr = addr;
ks->ks_type = KS_TYPE_UNKNOWN;
/* power up */
- ks0127_write(ks, KS_CMDA, 0x2c);
+ init_reg_defaults();
+ ks0127_write(c, KS_CMDA, 0x2c);
mdelay(10);
/* reset the device */
- ks0127_reset(ks);
- printk(KERN_INFO "ks0127: attach: %s video decoder\n",
- ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");
-
- i2c_attach_client(client);
- return 0;
-}
-
-
-static int ks0127_probe(struct i2c_adapter *adapter)
-{
- if (adapter->id == I2C_HW_B_ZR36067)
- return i2c_probe(adapter, &addr_data, ks0127_found_proc);
+ ks0127_reset(c);
return 0;
}
-static int ks0127_detach(struct i2c_client *client)
+static int ks0127_remove(struct i2c_client *c)
{
- struct ks0127 *ks = i2c_get_clientdata(client);
+ struct ks0127 *ks = i2c_get_clientdata(c);
- ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/
- ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */
+ ks0127_write(c, KS_OFMTA, 0x20); /* tristate */
+ ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */
- i2c_detach_client(client);
kfree(ks);
- kfree(client);
-
- dprintk("ks0127: detach\n");
return 0;
}
-
-static int __devinit ks0127_init_module(void)
-{
- init_reg_defaults();
- return i2c_add_driver(&i2c_driver_ks0127);
-}
-
-static void __devexit ks0127_cleanup_module(void)
+static int ks0127_legacy_probe(struct i2c_adapter *adapter)
{
- i2c_del_driver(&i2c_driver_ks0127);
+ return adapter->id == I2C_HW_B_ZR36067;
}
-
-module_init(ks0127_init_module);
-module_exit(ks0127_cleanup_module);
+static const struct i2c_device_id ks0127_id[] = {
+ { "ks0127", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ks0127_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "ks0127",
+ .driverid = I2C_DRIVERID_KS0127,
+ .command = ks0127_command,
+ .probe = ks0127_probe,
+ .remove = ks0127_remove,
+ .legacy_probe = ks0127_legacy_probe,
+ .id_table = ks0127_id,
+};
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 7c8ef6ac6c3..6418f4a78f2 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -843,17 +843,16 @@ again:
static int meye_open(struct inode *inode, struct file *file)
{
- int i, err;
+ int i;
- err = video_exclusive_open(inode, file);
- if (err < 0)
- return err;
+ if (test_and_set_bit(0, &meye.in_use))
+ return -EBUSY;
mchip_hic_stop();
if (mchip_dma_alloc()) {
printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
- video_exclusive_release(inode, file);
+ clear_bit(0, &meye.in_use);
return -ENOBUFS;
}
@@ -868,7 +867,7 @@ static int meye_release(struct inode *inode, struct file *file)
{
mchip_hic_stop();
mchip_dma_free();
- video_exclusive_release(inode, file);
+ clear_bit(0, &meye.in_use);
return 0;
}
@@ -1774,6 +1773,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outnotdev;
}
+ ret = -ENOMEM;
meye.mchip_dev = pcidev;
meye.video_dev = video_device_alloc();
if (!meye.video_dev) {
@@ -1781,7 +1781,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outnotdev;
}
- ret = -ENOMEM;
meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
if (!meye.grab_temp) {
printk(KERN_ERR "meye: grab buffer allocation failed\n");
@@ -1806,6 +1805,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
meye.video_dev->parent = &meye.mchip_dev->dev;
+ ret = -EIO;
if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
printk(KERN_ERR "meye: unable to power on the camera\n");
printk(KERN_ERR "meye: did you enable the camera in "
@@ -1813,7 +1813,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outsonypienable;
}
- ret = -EIO;
if ((ret = pci_enable_device(meye.mchip_dev))) {
printk(KERN_ERR "meye: pci_enable_device failed\n");
goto outenabledev;
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h
index d535748df44..5f70a106ba2 100644
--- a/drivers/media/video/meye.h
+++ b/drivers/media/video/meye.h
@@ -311,6 +311,7 @@ struct meye {
struct video_device *video_dev; /* video device parameters */
struct video_picture picture; /* video picture parameters */
struct meye_params params; /* additional parameters */
+ unsigned long in_use; /* set to 1 if the device is in use */
#ifdef CONFIG_PM
u8 pm_mchip_mode; /* old mchip mode */
#endif
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 554d2295484..0c524376b67 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -117,24 +117,51 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg,
static int mt9m001_init(struct soc_camera_device *icd)
{
+ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
int ret;
- /* Disable chip, synchronous option update */
dev_dbg(icd->vdev->parent, "%s\n", __func__);
- ret = reg_write(icd, MT9M001_RESET, 1);
- if (ret >= 0)
- ret = reg_write(icd, MT9M001_RESET, 0);
- if (ret >= 0)
+ if (icl->power) {
+ ret = icl->power(&mt9m001->client->dev, 1);
+ if (ret < 0) {
+ dev_err(icd->vdev->parent,
+ "Platform failed to power-on the camera.\n");
+ return ret;
+ }
+ }
+
+ /* The camera could have been already on, we reset it additionally */
+ if (icl->reset)
+ ret = icl->reset(&mt9m001->client->dev);
+ else
+ ret = -ENODEV;
+
+ if (ret < 0) {
+ /* Either no platform reset, or platform reset failed */
+ ret = reg_write(icd, MT9M001_RESET, 1);
+ if (!ret)
+ ret = reg_write(icd, MT9M001_RESET, 0);
+ }
+ /* Disable chip, synchronous option update */
+ if (!ret)
ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
- return ret >= 0 ? 0 : -EIO;
+ return ret;
}
static int mt9m001_release(struct soc_camera_device *icd)
{
+ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+
/* Disable the chip */
reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+
+ if (icl->power)
+ icl->power(&mt9m001->client->dev, 0);
+
return 0;
}
@@ -267,24 +294,24 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
/* Blanking and start values - default... */
ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
/* The caller provides a supported format, as verified per
* call to icd->try_fmt_cap() */
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9M001_ROW_START, rect->top);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
rect->height + icd->y_skip_top - 1);
- if (ret >= 0 && mt9m001->autoexposure) {
+ if (!ret && mt9m001->autoexposure) {
ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + vblank);
- if (ret >= 0) {
+ if (!ret) {
const struct v4l2_queryctrl *qctrl =
soc_camera_find_qctrl(icd->ops,
V4L2_CID_EXPOSURE);
@@ -295,7 +322,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
}
}
- return ret < 0 ? ret : 0;
+ return ret;
}
static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
new file mode 100644
index 00000000000..da0b2d553fd
--- /dev/null
+++ b/drivers/media/video/mt9m111.c
@@ -0,0 +1,973 @@
+/*
+ * Driver for MT9M111 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+/*
+ * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin)
+ * The platform has to define i2c_board_info and call i2c_register_board_info()
+ */
+
+/* mt9m111: Sensor register addresses */
+#define MT9M111_CHIP_VERSION 0x000
+#define MT9M111_ROW_START 0x001
+#define MT9M111_COLUMN_START 0x002
+#define MT9M111_WINDOW_HEIGHT 0x003
+#define MT9M111_WINDOW_WIDTH 0x004
+#define MT9M111_HORIZONTAL_BLANKING_B 0x005
+#define MT9M111_VERTICAL_BLANKING_B 0x006
+#define MT9M111_HORIZONTAL_BLANKING_A 0x007
+#define MT9M111_VERTICAL_BLANKING_A 0x008
+#define MT9M111_SHUTTER_WIDTH 0x009
+#define MT9M111_ROW_SPEED 0x00a
+#define MT9M111_EXTRA_DELAY 0x00b
+#define MT9M111_SHUTTER_DELAY 0x00c
+#define MT9M111_RESET 0x00d
+#define MT9M111_READ_MODE_B 0x020
+#define MT9M111_READ_MODE_A 0x021
+#define MT9M111_FLASH_CONTROL 0x023
+#define MT9M111_GREEN1_GAIN 0x02b
+#define MT9M111_BLUE_GAIN 0x02c
+#define MT9M111_RED_GAIN 0x02d
+#define MT9M111_GREEN2_GAIN 0x02e
+#define MT9M111_GLOBAL_GAIN 0x02f
+#define MT9M111_CONTEXT_CONTROL 0x0c8
+#define MT9M111_PAGE_MAP 0x0f0
+#define MT9M111_BYTE_WISE_ADDR 0x0f1
+
+#define MT9M111_RESET_SYNC_CHANGES (1 << 15)
+#define MT9M111_RESET_RESTART_BAD_FRAME (1 << 9)
+#define MT9M111_RESET_SHOW_BAD_FRAMES (1 << 8)
+#define MT9M111_RESET_RESET_SOC (1 << 5)
+#define MT9M111_RESET_OUTPUT_DISABLE (1 << 4)
+#define MT9M111_RESET_CHIP_ENABLE (1 << 3)
+#define MT9M111_RESET_ANALOG_STANDBY (1 << 2)
+#define MT9M111_RESET_RESTART_FRAME (1 << 1)
+#define MT9M111_RESET_RESET_MODE (1 << 0)
+
+#define MT9M111_RMB_MIRROR_COLS (1 << 1)
+#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
+#define MT9M111_CTXT_CTRL_RESTART (1 << 15)
+#define MT9M111_CTXT_CTRL_DEFECTCOR_B (1 << 12)
+#define MT9M111_CTXT_CTRL_RESIZE_B (1 << 10)
+#define MT9M111_CTXT_CTRL_CTRL2_B (1 << 9)
+#define MT9M111_CTXT_CTRL_GAMMA_B (1 << 8)
+#define MT9M111_CTXT_CTRL_XENON_EN (1 << 7)
+#define MT9M111_CTXT_CTRL_READ_MODE_B (1 << 3)
+#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2)
+#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1)
+#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0)
+/*
+ * mt9m111: Colorpipe register addresses (0x100..0x1ff)
+ */
+#define MT9M111_OPER_MODE_CTRL 0x106
+#define MT9M111_OUTPUT_FORMAT_CTRL 0x108
+#define MT9M111_REDUCER_XZOOM_B 0x1a0
+#define MT9M111_REDUCER_XSIZE_B 0x1a1
+#define MT9M111_REDUCER_YZOOM_B 0x1a3
+#define MT9M111_REDUCER_YSIZE_B 0x1a4
+#define MT9M111_REDUCER_XZOOM_A 0x1a6
+#define MT9M111_REDUCER_XSIZE_A 0x1a7
+#define MT9M111_REDUCER_YZOOM_A 0x1a9
+#define MT9M111_REDUCER_YSIZE_A 0x1aa
+
+#define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a
+#define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b
+
+#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14)
+
+
+#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)
+#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10)
+#define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9)
+#define MT9M111_OUTFMT_RGB (1 << 8)
+#define MT9M111_OUTFMT_RGB565 (0x0 << 6)
+#define MT9M111_OUTFMT_RGB555 (0x1 << 6)
+#define MT9M111_OUTFMT_RGB444x (0x2 << 6)
+#define MT9M111_OUTFMT_RGBx444 (0x3 << 6)
+#define MT9M111_OUTFMT_TST_RAMP_OFF (0x0 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_COL (0x1 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_ROW (0x2 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_FRAME (0x3 << 4)
+#define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3)
+#define MT9M111_OUTFMT_AVG_CHROMA (1 << 2)
+#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1)
+#define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1)
+#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0)
+/*
+ * mt9m111: Camera control register addresses (0x200..0x2ff not implemented)
+ */
+
+#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val))
+
+#define MT9M111_MIN_DARK_ROWS 8
+#define MT9M111_MIN_DARK_COLS 24
+#define MT9M111_MAX_HEIGHT 1024
+#define MT9M111_MAX_WIDTH 1280
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+#define RGB_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB)
+
+static const struct soc_camera_data_format mt9m111_colour_formats[] = {
+ COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG),
+ RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565),
+ RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555),
+ RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16),
+ RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8),
+};
+
+enum mt9m111_context {
+ HIGHPOWER = 0,
+ LOWPOWER,
+};
+
+struct mt9m111 {
+ struct i2c_client *client;
+ struct soc_camera_device icd;
+ int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */
+ enum mt9m111_context context;
+ unsigned int left, top, width, height;
+ u32 pixfmt;
+ unsigned char autoexposure;
+ unsigned char datawidth;
+ unsigned int powered:1;
+ unsigned int hflip:1;
+ unsigned int vflip:1;
+ unsigned int swap_rgb_even_odd:1;
+ unsigned int swap_rgb_red_blue:1;
+ unsigned int swap_yuv_y_chromas:1;
+ unsigned int swap_yuv_cb_cr:1;
+};
+
+static int reg_page_map_set(struct i2c_client *client, const u16 reg)
+{
+ int ret;
+ u16 page;
+ static int lastpage = -1; /* PageMap cache value */
+
+ page = (reg >> 8);
+ if (page == lastpage)
+ return 0;
+ if (page > 2)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
+ if (!ret)
+ lastpage = page;
+ return ret;
+}
+
+static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = mt9m111->client;
+ int ret;
+
+ ret = reg_page_map_set(client, reg);
+ if (!ret)
+ ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff)));
+
+ dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret);
+ return ret;
+}
+
+static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg,
+ const u16 data)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = mt9m111->client;
+ int ret;
+
+ ret = reg_page_map_set(client, reg);
+ if (!ret)
+ ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff),
+ swab16(data));
+ dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+ return ret;
+}
+
+static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg,
+ const u16 data)
+{
+ int ret;
+
+ ret = mt9m111_reg_read(icd, reg);
+ if (ret >= 0)
+ ret = mt9m111_reg_write(icd, reg, ret | data);
+ return ret;
+}
+
+static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg,
+ const u16 data)
+{
+ int ret;
+
+ ret = mt9m111_reg_read(icd, reg);
+ return mt9m111_reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9m111_set_context(struct soc_camera_device *icd,
+ enum mt9m111_context ctxt)
+{
+ int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
+ | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
+ | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
+ | MT9M111_CTXT_CTRL_VBLANK_SEL_B
+ | MT9M111_CTXT_CTRL_HBLANK_SEL_B;
+ int valA = MT9M111_CTXT_CTRL_RESTART;
+
+ if (ctxt == HIGHPOWER)
+ return reg_write(CONTEXT_CONTROL, valB);
+ else
+ return reg_write(CONTEXT_CONTROL, valA);
+}
+
+static int mt9m111_setup_rect(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret, is_raw_format;
+ int width = mt9m111->width;
+ int height = mt9m111->height;
+
+ if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8)
+ || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16))
+ is_raw_format = 1;
+ else
+ is_raw_format = 0;
+
+ ret = reg_write(COLUMN_START, mt9m111->left);
+ if (!ret)
+ ret = reg_write(ROW_START, mt9m111->top);
+
+ if (is_raw_format) {
+ if (!ret)
+ ret = reg_write(WINDOW_WIDTH, width);
+ if (!ret)
+ ret = reg_write(WINDOW_HEIGHT, height);
+ } else {
+ if (!ret)
+ ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH);
+ if (!ret)
+ ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
+ if (!ret)
+ ret = reg_write(REDUCER_XSIZE_B, width);
+ if (!ret)
+ ret = reg_write(REDUCER_YSIZE_B, height);
+ if (!ret)
+ ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
+ if (!ret)
+ ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
+ if (!ret)
+ ret = reg_write(REDUCER_XSIZE_A, width);
+ if (!ret)
+ ret = reg_write(REDUCER_YSIZE_A, height);
+ }
+
+ return ret;
+}
+
+static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
+{
+ int ret;
+
+ ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
+ if (!ret)
+ ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt);
+ return ret;
+}
+
+static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd)
+{
+ return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER);
+}
+
+static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
+{
+ return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP);
+}
+
+static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int val = 0;
+
+ if (mt9m111->swap_rgb_red_blue)
+ val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+ if (mt9m111->swap_rgb_even_odd)
+ val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
+ val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
+
+ return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int val = 0;
+
+ if (mt9m111->swap_rgb_red_blue)
+ val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+ if (mt9m111->swap_rgb_even_odd)
+ val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
+ val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
+
+ return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int val = 0;
+
+ if (mt9m111->swap_yuv_cb_cr)
+ val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+ if (mt9m111->swap_yuv_y_chromas)
+ val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
+
+ return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_enable(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ int ret;
+
+ if (icl->power) {
+ ret = icl->power(&mt9m111->client->dev, 1);
+ if (ret < 0) {
+ dev_err(icd->vdev->parent,
+ "Platform failed to power-on the camera.\n");
+ return ret;
+ }
+ }
+
+ ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE);
+ if (!ret)
+ mt9m111->powered = 1;
+ return ret;
+}
+
+static int mt9m111_disable(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ int ret;
+
+ ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
+ if (!ret)
+ mt9m111->powered = 0;
+
+ if (icl->power)
+ icl->power(&mt9m111->client->dev, 0);
+
+ return ret;
+}
+
+static int mt9m111_reset(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+ if (!ret)
+ ret = reg_set(RESET, MT9M111_RESET_RESET_SOC);
+ if (!ret)
+ ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE
+ | MT9M111_RESET_RESET_SOC);
+ return ret;
+}
+
+static int mt9m111_start_capture(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static int mt9m111_stop_capture(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
+{
+ return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
+ SOCAM_DATAWIDTH_8;
+}
+
+static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
+{
+ return 0;
+}
+
+static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret;
+
+ switch (pixfmt) {
+ case V4L2_PIX_FMT_SBGGR8:
+ ret = mt9m111_setfmt_bayer8(icd);
+ break;
+ case V4L2_PIX_FMT_SBGGR16:
+ ret = mt9m111_setfmt_bayer10(icd);
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ ret = mt9m111_setfmt_rgb555(icd);
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ ret = mt9m111_setfmt_rgb565(icd);
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ ret = mt9m111_setfmt_yuv(icd);
+ break;
+ default:
+ dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt);
+ ret = -EINVAL;
+ }
+
+ if (!ret)
+ mt9m111->pixfmt = pixfmt;
+
+ return ret;
+}
+
+static int mt9m111_set_fmt_cap(struct soc_camera_device *icd,
+ __u32 pixfmt, struct v4l2_rect *rect)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret;
+
+ mt9m111->left = rect->left;
+ mt9m111->top = rect->top;
+ mt9m111->width = rect->width;
+ mt9m111->height = rect->height;
+
+ dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n",
+ __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width,
+ mt9m111->height);
+
+ ret = mt9m111_setup_rect(icd);
+ if (!ret)
+ ret = mt9m111_set_pixfmt(icd, pixfmt);
+ return ret;
+}
+
+static int mt9m111_try_fmt_cap(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ if (f->fmt.pix.height > MT9M111_MAX_HEIGHT)
+ f->fmt.pix.height = MT9M111_MAX_HEIGHT;
+ if (f->fmt.pix.width > MT9M111_MAX_WIDTH)
+ f->fmt.pix.width = MT9M111_MAX_WIDTH;
+
+ return 0;
+}
+
+static int mt9m111_get_chip_id(struct soc_camera_device *icd,
+ struct v4l2_chip_ident *id)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+ if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match_chip != mt9m111->client->addr)
+ return -ENODEV;
+
+ id->ident = mt9m111->model;
+ id->revision = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m111_get_register(struct soc_camera_device *icd,
+ struct v4l2_register *reg)
+{
+ int val;
+
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+ return -EINVAL;
+ if (reg->match_chip != mt9m111->client->addr)
+ return -ENODEV;
+
+ val = mt9m111_reg_read(icd, reg->reg);
+ reg->val = (u64)val;
+
+ if (reg->val > 0xffff)
+ return -EIO;
+
+ return 0;
+}
+
+static int mt9m111_set_register(struct soc_camera_device *icd,
+ struct v4l2_register *reg)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+ return -EINVAL;
+
+ if (reg->match_chip != mt9m111->client->addr)
+ return -ENODEV;
+
+ if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
+ return -EIO;
+
+ return 0;
+}
+#endif
+
+static const struct v4l2_queryctrl mt9m111_controls[] = {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Verticaly",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Horizontaly",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, { /* gain = 1/32*val (=>gain=1 if val==32) */
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+ .maximum = 63 * 2 * 2,
+ .step = 1,
+ .default_value = 32,
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ }, {
+ .id = V4L2_CID_EXPOSURE_AUTO,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Exposure",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ }
+};
+
+static int mt9m111_video_probe(struct soc_camera_device *);
+static void mt9m111_video_remove(struct soc_camera_device *);
+static int mt9m111_get_control(struct soc_camera_device *,
+ struct v4l2_control *);
+static int mt9m111_set_control(struct soc_camera_device *,
+ struct v4l2_control *);
+static int mt9m111_resume(struct soc_camera_device *icd);
+static int mt9m111_init(struct soc_camera_device *icd);
+static int mt9m111_release(struct soc_camera_device *icd);
+
+static struct soc_camera_ops mt9m111_ops = {
+ .owner = THIS_MODULE,
+ .probe = mt9m111_video_probe,
+ .remove = mt9m111_video_remove,
+ .init = mt9m111_init,
+ .resume = mt9m111_resume,
+ .release = mt9m111_release,
+ .start_capture = mt9m111_start_capture,
+ .stop_capture = mt9m111_stop_capture,
+ .set_fmt_cap = mt9m111_set_fmt_cap,
+ .try_fmt_cap = mt9m111_try_fmt_cap,
+ .query_bus_param = mt9m111_query_bus_param,
+ .set_bus_param = mt9m111_set_bus_param,
+ .controls = mt9m111_controls,
+ .num_controls = ARRAY_SIZE(mt9m111_controls),
+ .get_control = mt9m111_get_control,
+ .set_control = mt9m111_set_control,
+ .get_chip_id = mt9m111_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .get_register = mt9m111_get_register,
+ .set_register = mt9m111_set_register,
+#endif
+};
+
+static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret;
+
+ if (mt9m111->context == HIGHPOWER) {
+ if (flip)
+ ret = reg_set(READ_MODE_B, mask);
+ else
+ ret = reg_clear(READ_MODE_B, mask);
+ } else {
+ if (flip)
+ ret = reg_set(READ_MODE_A, mask);
+ else
+ ret = reg_clear(READ_MODE_A, mask);
+ }
+
+ return ret;
+}
+
+static int mt9m111_get_global_gain(struct soc_camera_device *icd)
+{
+ unsigned int data, gain;
+
+ data = reg_read(GLOBAL_GAIN);
+ if (data >= 0)
+ gain = ((data & (1 << 10)) * 2)
+ | ((data & (1 << 9)) * 2)
+ | (data & 0x2f);
+ else
+ gain = data;
+
+ return gain;
+}
+static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
+{
+ u16 val;
+
+ if (gain > 63 * 2 * 2)
+ return -EINVAL;
+
+ icd->gain = gain;
+ if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
+ val = (1 << 10) | (1 << 9) | (gain / 4);
+ else if ((gain >= 64) && (gain < 64 * 2))
+ val = (1 << 9) | (gain / 2);
+ else
+ val = gain;
+
+ return reg_write(GLOBAL_GAIN, val);
+}
+
+static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret;
+
+ if (on)
+ ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+ else
+ ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+
+ if (!ret)
+ mt9m111->autoexposure = on;
+
+ return ret;
+}
+static int mt9m111_get_control(struct soc_camera_device *icd,
+ struct v4l2_control *ctrl)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int data;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VFLIP:
+ if (mt9m111->context == HIGHPOWER)
+ data = reg_read(READ_MODE_B);
+ else
+ data = reg_read(READ_MODE_A);
+
+ if (data < 0)
+ return -EIO;
+ ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS);
+ break;
+ case V4L2_CID_HFLIP:
+ if (mt9m111->context == HIGHPOWER)
+ data = reg_read(READ_MODE_B);
+ else
+ data = reg_read(READ_MODE_A);
+
+ if (data < 0)
+ return -EIO;
+ ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
+ break;
+ case V4L2_CID_GAIN:
+ data = mt9m111_get_global_gain(icd);
+ if (data < 0)
+ return data;
+ ctrl->value = data;
+ break;
+ case V4L2_CID_EXPOSURE_AUTO:
+ ctrl->value = mt9m111->autoexposure;
+ break;
+ }
+ return 0;
+}
+
+static int mt9m111_set_control(struct soc_camera_device *icd,
+ struct v4l2_control *ctrl)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ const struct v4l2_queryctrl *qctrl;
+ int ret;
+
+ qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id);
+
+ if (!qctrl)
+ return -EINVAL;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VFLIP:
+ mt9m111->vflip = ctrl->value;
+ ret = mt9m111_set_flip(icd, ctrl->value,
+ MT9M111_RMB_MIRROR_ROWS);
+ break;
+ case V4L2_CID_HFLIP:
+ mt9m111->hflip = ctrl->value;
+ ret = mt9m111_set_flip(icd, ctrl->value,
+ MT9M111_RMB_MIRROR_COLS);
+ break;
+ case V4L2_CID_GAIN:
+ ret = mt9m111_set_global_gain(icd, ctrl->value);
+ break;
+ case V4L2_CID_EXPOSURE_AUTO:
+ ret = mt9m111_set_autoexposure(icd, ctrl->value);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int mt9m111_restore_state(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+ mt9m111_set_context(icd, mt9m111->context);
+ mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
+ mt9m111_setup_rect(icd);
+ mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
+ mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
+ mt9m111_set_global_gain(icd, icd->gain);
+ mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
+ return 0;
+}
+
+static int mt9m111_resume(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret = 0;
+
+ if (mt9m111->powered) {
+ ret = mt9m111_enable(icd);
+ if (!ret)
+ ret = mt9m111_reset(icd);
+ if (!ret)
+ ret = mt9m111_restore_state(icd);
+ }
+ return ret;
+}
+
+static int mt9m111_init(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ int ret;
+
+ mt9m111->context = HIGHPOWER;
+ ret = mt9m111_enable(icd);
+ if (!ret)
+ ret = mt9m111_reset(icd);
+ if (!ret)
+ ret = mt9m111_set_context(icd, mt9m111->context);
+ if (!ret)
+ ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
+ if (ret)
+ dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret);
+ return ret;
+}
+
+static int mt9m111_release(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = mt9m111_disable(icd);
+ if (ret < 0)
+ dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret);
+
+ return ret;
+}
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9m111_video_probe(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ s32 data;
+ int ret;
+
+ /*
+ * We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant.
+ */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ ret = mt9m111_enable(icd);
+ if (ret)
+ goto ei2c;
+ ret = mt9m111_reset(icd);
+ if (ret)
+ goto ei2c;
+
+ data = reg_read(CHIP_VERSION);
+
+ switch (data) {
+ case 0x143a:
+ mt9m111->model = V4L2_IDENT_MT9M111;
+ icd->formats = mt9m111_colour_formats;
+ icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats);
+ break;
+ default:
+ ret = -ENODEV;
+ dev_err(&icd->dev,
+ "No MT9M111 chip detected, register read %x\n", data);
+ goto ei2c;
+ }
+
+ dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n");
+
+ ret = soc_camera_video_start(icd);
+ if (ret)
+ goto eisis;
+
+ mt9m111->autoexposure = 1;
+
+ mt9m111->swap_rgb_even_odd = 1;
+ mt9m111->swap_rgb_red_blue = 1;
+
+ return 0;
+eisis:
+ei2c:
+ return ret;
+}
+
+static void mt9m111_video_remove(struct soc_camera_device *icd)
+{
+ struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
+ mt9m111->icd.dev.parent, mt9m111->icd.vdev);
+ soc_camera_video_stop(&mt9m111->icd);
+}
+
+static int mt9m111_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct mt9m111 *mt9m111;
+ struct soc_camera_device *icd;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl = client->dev.platform_data;
+ int ret;
+
+ if (!icl) {
+ dev_err(&client->dev, "MT9M111 driver needs platform data\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+ return -EIO;
+ }
+
+ mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL);
+ if (!mt9m111)
+ return -ENOMEM;
+
+ mt9m111->client = client;
+ i2c_set_clientdata(client, mt9m111);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd = &mt9m111->icd;
+ icd->ops = &mt9m111_ops;
+ icd->control = &client->dev;
+ icd->x_min = MT9M111_MIN_DARK_COLS;
+ icd->y_min = MT9M111_MIN_DARK_ROWS;
+ icd->x_current = icd->x_min;
+ icd->y_current = icd->y_min;
+ icd->width_min = MT9M111_MIN_DARK_ROWS;
+ icd->width_max = MT9M111_MAX_WIDTH;
+ icd->height_min = MT9M111_MIN_DARK_COLS;
+ icd->height_max = MT9M111_MAX_HEIGHT;
+ icd->y_skip_top = 0;
+ icd->iface = icl->bus_id;
+
+ ret = soc_camera_device_register(icd);
+ if (ret)
+ goto eisdr;
+ return 0;
+
+eisdr:
+ kfree(mt9m111);
+ return ret;
+}
+
+static int mt9m111_remove(struct i2c_client *client)
+{
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
+ soc_camera_device_unregister(&mt9m111->icd);
+ kfree(mt9m111);
+
+ return 0;
+}
+
+static const struct i2c_device_id mt9m111_id[] = {
+ { "mt9m111", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m111_id);
+
+static struct i2c_driver mt9m111_i2c_driver = {
+ .driver = {
+ .name = "mt9m111",
+ },
+ .probe = mt9m111_probe,
+ .remove = mt9m111_remove,
+ .id_table = mt9m111_id,
+};
+
+static int __init mt9m111_mod_init(void)
+{
+ return i2c_add_driver(&mt9m111_i2c_driver);
+}
+
+static void __exit mt9m111_mod_exit(void)
+{
+ i2c_del_driver(&mt9m111_i2c_driver);
+}
+
+module_init(mt9m111_mod_init);
+module_exit(mt9m111_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9M111 Camera driver");
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 56808cd2f8a..2584201059d 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -134,34 +134,56 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg,
static int mt9v022_init(struct soc_camera_device *icd)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
int ret;
+ if (icl->power) {
+ ret = icl->power(&mt9v022->client->dev, 1);
+ if (ret < 0) {
+ dev_err(icd->vdev->parent,
+ "Platform failed to power-on the camera.\n");
+ return ret;
+ }
+ }
+
+ /*
+ * The camera could have been already on, we hard-reset it additionally,
+ * if available. Soft reset is done in video_probe().
+ */
+ if (icl->reset)
+ icl->reset(&mt9v022->client->dev);
+
/* Almost the default mode: master, parallel, simultaneous, and an
* undocumented bit 0x200, which is present in table 7, but not in 8,
* plus snapshot mode to disable scan for now */
mt9v022->chip_control |= 0x10;
ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
- if (ret >= 0)
- reg_write(icd, MT9V022_READ_MODE, 0x300);
+ if (!ret)
+ ret = reg_write(icd, MT9V022_READ_MODE, 0x300);
/* All defaults */
- if (ret >= 0)
+ if (!ret)
/* AEC, AGC on */
ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
- if (ret >= 0)
+ if (!ret)
/* default - auto */
ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
- return ret >= 0 ? 0 : -EIO;
+ return ret;
}
static int mt9v022_release(struct soc_camera_device *icd)
{
- /* Nothing? */
+ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+
+ if (icl->power)
+ icl->power(&mt9v022->client->dev, 0);
+
return 0;
}
@@ -352,21 +374,21 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
rect->height + icd->y_skip_top + 43);
}
/* Setup frame format: defaults apart from width and height */
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_ROW_START, rect->top);
- if (ret >= 0)
+ if (!ret)
/* Default 94, Phytec driver says:
* "width + horizontal blank >= 660" */
ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
rect->width > 660 - 43 ? 43 :
660 - rect->width);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
- if (ret >= 0)
+ if (!ret)
ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
rect->height + icd->y_skip_top);
@@ -717,7 +739,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
icd->num_formats = 1;
}
- if (ret >= 0)
+ if (!ret)
ret = soc_camera_video_start(icd);
if (ret < 0)
goto eisis;
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index f68e91fbe7f..7f130284b5c 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -27,6 +27,7 @@
#include <media/tuner.h>
#include <linux/video_decoder.h>
#include <media/v4l2-common.h>
+#include <media/saa7115.h>
#include "mxb.h"
#include "tea6415c.h"
@@ -122,6 +123,8 @@ static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
+ { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE },
+ { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE },
{ MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */
{ MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */
{ 0, 0 }
@@ -134,12 +137,12 @@ struct mxb
struct i2c_adapter i2c_adapter;
- struct i2c_client* saa7111a;
- struct i2c_client* tda9840;
- struct i2c_client* tea6415c;
- struct i2c_client* tuner;
- struct i2c_client* tea6420_1;
- struct i2c_client* tea6420_2;
+ struct i2c_client *saa7111a;
+ struct i2c_client *tda9840;
+ struct i2c_client *tea6415c;
+ struct i2c_client *tuner;
+ struct i2c_client *tea6420_1;
+ struct i2c_client *tea6420_2;
int cur_mode; /* current audio mode (mono, stereo, ...) */
int cur_input; /* current input */
@@ -151,23 +154,23 @@ static struct saa7146_extension extension;
static int mxb_check_clients(struct device *dev, void *data)
{
- struct mxb* mxb = data;
+ struct mxb *mxb = data;
struct i2c_client *client = i2c_verify_client(dev);
- if( !client )
+ if (!client)
return 0;
- if( I2C_ADDR_TEA6420_1 == client->addr )
+ if (I2C_ADDR_TEA6420_1 == client->addr)
mxb->tea6420_1 = client;
- if( I2C_ADDR_TEA6420_2 == client->addr )
+ if (I2C_ADDR_TEA6420_2 == client->addr)
mxb->tea6420_2 = client;
- if( I2C_TEA6415C_2 == client->addr )
+ if (I2C_TEA6415C_2 == client->addr)
mxb->tea6415c = client;
- if( I2C_ADDR_TDA9840 == client->addr )
+ if (I2C_ADDR_TDA9840 == client->addr)
mxb->tda9840 = client;
- if( I2C_SAA7111 == client->addr )
+ if (I2C_SAA7111 == client->addr)
mxb->saa7111a = client;
- if( 0x60 == client->addr )
+ if (0x60 == client->addr)
mxb->tuner = client;
return 0;
@@ -178,23 +181,28 @@ static int mxb_probe(struct saa7146_dev* dev)
struct mxb* mxb = NULL;
int result;
- if ((result = request_module("saa7111")) < 0) {
+ result = request_module("saa7115");
+ if (result < 0) {
printk("mxb: saa7111 i2c module not available.\n");
return -ENODEV;
}
- if ((result = request_module("tea6420")) < 0) {
+ result = request_module("tea6420");
+ if (result < 0) {
printk("mxb: tea6420 i2c module not available.\n");
return -ENODEV;
}
- if ((result = request_module("tea6415c")) < 0) {
+ result = request_module("tea6415c");
+ if (result < 0) {
printk("mxb: tea6415c i2c module not available.\n");
return -ENODEV;
}
- if ((result = request_module("tda9840")) < 0) {
+ result = request_module("tda9840");
+ if (result < 0) {
printk("mxb: tda9840 i2c module not available.\n");
return -ENODEV;
}
- if ((result = request_module("tuner")) < 0) {
+ result = request_module("tuner");
+ if (result < 0) {
printk("mxb: tuner i2c module not available.\n");
return -ENODEV;
}
@@ -207,9 +215,10 @@ static int mxb_probe(struct saa7146_dev* dev)
mxb->i2c_adapter = (struct i2c_adapter) {
.class = I2C_CLASS_TV_ANALOG,
- .name = "mxb",
};
+ snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
+
saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
DEB_S(("cannot register i2c-device. skipping.\n"));
@@ -290,38 +299,7 @@ static struct {
{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
{ 3, { 0x80, 0xb3, 0x0a } },
- {-1, { 0} }
-};
-
-static const unsigned char mxb_saa7111_init[] = {
- 0x00, 0x00, /* 00 - ID byte */
- 0x01, 0x00, /* 01 - reserved */
-
- /*front end */
- 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */
- 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
- 0x04, 0x00, /* 04 - GAI1=256 */
- 0x05, 0x00, /* 05 - GAI2=256 */
-
- /* decoder */
- 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */
- 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */
- 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */
- 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */
- 0x0a, 0x80, /* 0a - BRIG=128 */
- 0x0b, 0x47, /* 0b - CONT=1.109 */
- 0x0c, 0x40, /* 0c - SATN=1.0 */
- 0x0d, 0x00, /* 0d - HUE=0 */
- 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
- 0x0f, 0x00, /* 0f - reserved */
- 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */
- 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
- 0x12, 0x80, /* 12 - xx output control 2 */
- 0x13, 0x30, /* 13 - xx output control 3 */
- 0x14, 0x00, /* 14 - reserved */
- 0x15, 0x15, /* 15 - VBI */
- 0x16, 0x04, /* 16 - VBI */
- 0x17, 0x00, /* 17 - VBI */
+ {-1, { 0 } }
};
/* bring hardware to a sane state. this has to be done, just in case someone
@@ -331,37 +309,28 @@ static const unsigned char mxb_saa7111_init[] = {
static int mxb_init_done(struct saa7146_dev* dev)
{
struct mxb* mxb = (struct mxb*)dev->ext_priv;
- struct video_decoder_init init;
struct i2c_msg msg;
struct tuner_setup tun_setup;
v4l2_std_id std = V4L2_STD_PAL_BG;
+ struct v4l2_routing route;
int i = 0, err = 0;
- struct tea6415c_multiplex vm;
+ struct tea6415c_multiplex vm;
/* select video mode in saa7111a */
- i = VIDEO_MODE_PAL;
- /* fixme: currently pointless: gets overwritten by configuration below */
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
-
- /* write configuration to saa7111a */
- init.data = mxb_saa7111_init;
- init.len = sizeof(mxb_saa7111_init);
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init);
+ mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std);
/* select tuner-output on saa7111a */
i = 0;
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
-
- /* enable vbi bypass */
- i = 1;
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i);
+ route.input = SAA7115_COMPOSITE0;
+ route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
+ mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route);
/* select a tuner type */
tun_setup.mode_mask = T_ANALOG_TV;
tun_setup.addr = ADDR_UNSET;
tun_setup.type = TUNER_PHILIPS_PAL;
- mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup);
+ mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup);
/* tune in some frequency on tuner */
mxb->cur_freq.tuner = 0;
mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
@@ -373,27 +342,26 @@ static int mxb_init_done(struct saa7146_dev* dev)
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
/* mute audio on tea6420s */
- mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
- mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
- mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
- mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
+ mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]);
+ mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]);
+ mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]);
+ mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]);
/* switch to tuner-channel on tea6415c*/
vm.out = 17;
vm.in = 3;
- mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
+ mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
/* select tuner-output on multicable on tea6415c*/
vm.in = 3;
vm.out = 13;
- mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
+ mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
/* the rest for mxb */
mxb->cur_input = 0;
mxb->cur_mute = 1;
mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
- mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
/* check if the saa7740 (aka 'sound arena module') is present
on the mxb. if so, we must initialize it. due to lack of
@@ -404,21 +372,22 @@ static int mxb_init_done(struct saa7146_dev* dev)
msg.len = mxb_saa7740_init[0].length;
msg.buf = &mxb_saa7740_init[0].data[0];
- if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
+ err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
+ if (err == 1) {
/* the sound arena module is a pos, that's probably the reason
philips refuses to hand out a datasheet for the saa7740...
it seems to screw up the i2c bus, so we disable fast irq
based i2c transactions here and rely on the slow and safe
polling method ... */
extension.flags &= ~SAA7146_USE_I2C_IRQ;
- for(i = 1;;i++) {
- if( -1 == mxb_saa7740_init[i].length ) {
+ for (i = 1; ; i++) {
+ if (-1 == mxb_saa7740_init[i].length)
break;
- }
msg.len = mxb_saa7740_init[i].length;
msg.buf = &mxb_saa7740_init[i].data[0];
- if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
+ err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
+ if (err != 1) {
DEB_D(("failed to initialize 'sound arena module'.\n"));
goto err;
}
@@ -432,7 +401,8 @@ err:
/* ext->saa has been filled by the core driver */
/* some stuff is done via variables */
- saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
+ saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
+ input_port_selection[mxb->cur_input].hps_sync);
/* some stuff is done via direct write to the registers */
@@ -457,24 +427,24 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
static struct saa7146_ext_vv vv_data;
/* this function only gets called when the probing was successful */
-static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
+static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
+ struct mxb *mxb = (struct mxb *)dev->ext_priv;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE(("dev:%p\n", dev));
/* checking for i2c-devices can be omitted here, because we
already did this in "mxb_vl42_probe" */
- saa7146_vv_init(dev,&vv_data);
- if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
+ saa7146_vv_init(dev, &vv_data);
+ if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
ERR(("cannot register capture v4l2 device. skipping.\n"));
return -1;
}
/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
- if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
- if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
+ if (MXB_BOARD_CAN_DO_VBI(dev)) {
+ if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
ERR(("cannot register vbi v4l2 device. skipping.\n"));
}
}
@@ -486,18 +456,18 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data
i2c_use_client(mxb->saa7111a);
i2c_use_client(mxb->tuner);
- printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
+ printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
mxb_num++;
mxb_init_done(dev);
return 0;
}
-static int mxb_detach(struct saa7146_dev* dev)
+static int mxb_detach(struct saa7146_dev *dev)
{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
+ struct mxb *mxb = (struct mxb *)dev->ext_priv;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE(("dev:%p\n", dev));
i2c_release_client(mxb->tea6420_1);
i2c_release_client(mxb->tea6420_2);
@@ -507,9 +477,8 @@ static int mxb_detach(struct saa7146_dev* dev)
i2c_release_client(mxb->tuner);
saa7146_unregister_device(&mxb->video_dev,dev);
- if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
- saa7146_unregister_device(&mxb->vbi_dev,dev);
- }
+ if (MXB_BOARD_CAN_DO_VBI(dev))
+ saa7146_unregister_device(&mxb->vbi_dev, dev);
saa7146_vv_release(dev);
mxb_num--;
@@ -523,7 +492,7 @@ static int mxb_detach(struct saa7146_dev* dev)
static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
+ struct mxb *mxb = (struct mxb *)dev->ext_priv;
struct saa7146_vv *vv = dev->vv_data;
switch(cmd) {
@@ -532,11 +501,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
struct v4l2_input *i = arg;
DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
- if( i->index < 0 || i->index >= MXB_INPUTS) {
+ if (i->index < 0 || i->index >= MXB_INPUTS)
return -EINVAL;
- }
memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
-
return 0;
}
/* the saa7146 provides some controls (brightness, contrast, saturation)
@@ -550,7 +517,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
for (i = MAXCONTROLS - 1; i >= 0; i--) {
if (mxb_controls[i].id == qc->id) {
*qc = mxb_controls[i];
- DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
+ DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
return 0;
}
}
@@ -562,56 +529,51 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
int i;
for (i = MAXCONTROLS - 1; i >= 0; i--) {
- if (mxb_controls[i].id == vc->id) {
+ if (mxb_controls[i].id == vc->id)
break;
- }
}
- if( i < 0 ) {
+ if (i < 0)
return -EAGAIN;
- }
- switch (vc->id ) {
- case V4L2_CID_AUDIO_MUTE: {
- vc->value = mxb->cur_mute;
- DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
- return 0;
- }
+ if (vc->id == V4L2_CID_AUDIO_MUTE) {
+ vc->value = mxb->cur_mute;
+ DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+ return 0;
}
- DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
+ DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
return 0;
}
case VIDIOC_S_CTRL:
{
- struct v4l2_control *vc = arg;
+ struct v4l2_control *vc = arg;
int i = 0;
for (i = MAXCONTROLS - 1; i >= 0; i--) {
- if (mxb_controls[i].id == vc->id) {
+ if (mxb_controls[i].id == vc->id)
break;
- }
}
- if( i < 0 ) {
+ if (i < 0)
return -EAGAIN;
- }
- switch (vc->id ) {
- case V4L2_CID_AUDIO_MUTE: {
- mxb->cur_mute = vc->value;
- if( 0 == vc->value ) {
- /* switch the audio-source */
- mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
- mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
- } else {
- mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
- mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
- }
- DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
- break;
+ if (vc->id == V4L2_CID_AUDIO_MUTE) {
+ mxb->cur_mute = vc->value;
+ if (!vc->value) {
+ /* switch the audio-source */
+ mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+ &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
+ mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+ &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
+ } else {
+ mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+ &TEA6420_line[6][0]);
+ mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+ &TEA6420_line[6][1]);
}
+ DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
}
return 0;
}
@@ -620,106 +582,84 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
int *input = (int *)arg;
*input = mxb->cur_input;
- DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
+ DEB_EE(("VIDIOC_G_INPUT %d.\n", *input));
return 0;
}
case VIDIOC_S_INPUT:
{
int input = *(int *)arg;
- struct tea6415c_multiplex vm;
+ struct tea6415c_multiplex vm;
+ struct v4l2_routing route;
int i = 0;
- DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
+ DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
- if (input < 0 || input >= MXB_INPUTS) {
+ if (input < 0 || input >= MXB_INPUTS)
return -EINVAL;
- }
-
- /* fixme: locke das setzen des inputs mit hilfe des mutexes
- mutex_lock(&dev->lock);
- video_mux(dev,*i);
- mutex_unlock(&dev->lock);
- */
-
- /* fixme: check if streaming capture
- if ( 0 != dev->streaming ) {
- DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
- return -EPERM;
- }
- */
mxb->cur_input = input;
- saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
+ saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
+ input_port_selection[input].hps_sync);
/* prepare switching of tea6415c and saa7111a;
have a look at the 'background'-file for further informations */
- switch( input ) {
-
- case TUNER:
- {
- i = 0;
- vm.in = 3;
- vm.out = 17;
-
- if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
- printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
- return -EFAULT;
- }
- /* connect tuner-output always to multicable */
- vm.in = 3;
- vm.out = 13;
- break;
- }
- case AUX3_YC:
- {
- /* nothing to be done here. aux3_yc is
- directly connected to the saa711a */
- i = 5;
- break;
- }
- case AUX3:
- {
- /* nothing to be done here. aux3 is
- directly connected to the saa711a */
- i = 1;
- break;
- }
- case AUX1:
- {
- i = 0;
- vm.in = 1;
- vm.out = 17;
- break;
+ switch (input) {
+ case TUNER:
+ i = SAA7115_COMPOSITE0;
+ vm.in = 3;
+ vm.out = 17;
+
+ if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
+ printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
+ return -EFAULT;
}
+ /* connect tuner-output always to multicable */
+ vm.in = 3;
+ vm.out = 13;
+ break;
+ case AUX3_YC:
+ /* nothing to be done here. aux3_yc is
+ directly connected to the saa711a */
+ i = SAA7115_SVIDEO1;
+ break;
+ case AUX3:
+ /* nothing to be done here. aux3 is
+ directly connected to the saa711a */
+ i = SAA7115_COMPOSITE1;
+ break;
+ case AUX1:
+ i = SAA7115_COMPOSITE0;
+ vm.in = 1;
+ vm.out = 17;
+ break;
}
/* switch video in tea6415c only if necessary */
- switch( input ) {
- case TUNER:
- case AUX1:
- {
- if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
- printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
- return -EFAULT;
- }
- break;
- }
- default:
- {
- break;
+ switch (input) {
+ case TUNER:
+ case AUX1:
+ if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
+ printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
+ return -EFAULT;
}
+ break;
+ default:
+ break;
}
/* switch video in saa7111a */
- if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
+ route.input = i;
+ route.output = 0;
+ if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route))
printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
- }
/* switch the audio-source only if necessary */
if( 0 == mxb->cur_mute ) {
- mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
- mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
+ mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+ &TEA6420_line[video_audio_connect[input]][0]);
+ mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+ &TEA6420_line[video_audio_connect[input]][1]);
}
return 0;
@@ -727,114 +667,44 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
- int byte = 0;
- if( 0 != t->index ) {
+ if (t->index) {
DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
return -EINVAL;
}
DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
- memset(t,0,sizeof(*t));
- strcpy(t->name, "Television");
+ memset(t, 0, sizeof(*t));
+ i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
+ strlcpy(t->name, "TV Tuner", sizeof(t->name));
t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
- t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
- t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
- /* FIXME: add the real signal strength here */
- t->signal = 0xffff;
- t->afc = 0;
-
- mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte);
+ t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
t->audmode = mxb->cur_mode;
-
- if( byte < 0 ) {
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- } else {
- switch(byte) {
- case TDA9840_MONO_DETECT: {
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
- break;
- }
- case TDA9840_DUAL_DETECT: {
- t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
- break;
- }
- case TDA9840_STEREO_DETECT: {
- t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
- DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
- break;
- }
- default: { /* TDA9840_INCORRECT_DETECT */
- t->rxsubchans = V4L2_TUNER_MODE_MONO;
- DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
- break;
- }
- }
- }
-
return 0;
}
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *t = arg;
- int result = 0;
- int byte = 0;
- if( 0 != t->index ) {
+ if (t->index) {
DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
return -EINVAL;
}
- switch(t->audmode) {
- case V4L2_TUNER_MODE_STEREO: {
- mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
- byte = TDA9840_SET_STEREO;
- DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
- break;
- }
- case V4L2_TUNER_MODE_LANG1_LANG2: {
- mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2;
- byte = TDA9840_SET_BOTH;
- DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"));
- break;
- }
- case V4L2_TUNER_MODE_LANG1: {
- mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
- byte = TDA9840_SET_LANG1;
- DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
- break;
- }
- case V4L2_TUNER_MODE_LANG2: {
- mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
- byte = TDA9840_SET_LANG2;
- DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
- break;
- }
- default: { /* case V4L2_TUNER_MODE_MONO: {*/
- mxb->cur_mode = V4L2_TUNER_MODE_MONO;
- byte = TDA9840_SET_MONO;
- DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
- break;
- }
- }
-
- if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
- printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
- }
-
+ mxb->cur_mode = t->audmode;
+ i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
return 0;
}
case VIDIOC_G_FREQUENCY:
{
struct v4l2_frequency *f = arg;
- if(0 != mxb->cur_input) {
- DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
+ if (mxb->cur_input) {
+ DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
+ mxb->cur_input));
return -EINVAL;
}
@@ -847,14 +717,14 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct v4l2_frequency *f = arg;
- if (0 != f->tuner)
+ if (f->tuner)
return -EINVAL;
if (V4L2_TUNER_ANALOG_TV != f->type)
return -EINVAL;
- if(0 != mxb->cur_input) {
- DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
+ if (mxb->cur_input) {
+ DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
return -EINVAL;
}
@@ -875,7 +745,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
int i = *(int*)arg;
- if( i < 0 || i >= MXB_AUDIOS ) {
+ if (i < 0 || i >= MXB_AUDIOS) {
DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
return -EINVAL;
}
@@ -891,7 +761,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
int i = *(int*)arg;
- if( i < 0 || i >= MXB_AUDIOS ) {
+ if (i < 0 || i >= MXB_AUDIOS) {
DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
return -EINVAL;
}
@@ -906,12 +776,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct v4l2_audio *a = arg;
- if( a->index < 0 || a->index > MXB_INPUTS ) {
- DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
+ if (a->index < 0 || a->index > MXB_INPUTS) {
+ DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
return -EINVAL;
}
- DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
+ DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
return 0;
@@ -919,9 +789,16 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
case VIDIOC_S_AUDIO:
{
struct v4l2_audio *a = arg;
- DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
+
+ DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
return 0;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_S_REGISTER:
+ case VIDIOC_DBG_G_REGISTER:
+ i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
+ return 0;
+#endif
default:
/*
DEB2(printk("does not handle this ioctl.\n"));
@@ -931,27 +808,29 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
+static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
+ struct mxb *mxb = (struct mxb *)dev->ext_priv;
int zero = 0;
int one = 1;
- if(V4L2_STD_PAL_I == std->id ) {
+ if (V4L2_STD_PAL_I == standard->id) {
v4l2_std_id std = V4L2_STD_PAL_I;
+
DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* unset the 7111 gpio register -- I don't know what this does exactly */
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
+ mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero);
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
} else {
v4l2_std_id std = V4L2_STD_PAL_BG;
+
DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* set the 7111 gpio register -- I don't know what this does exactly */
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
+ mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one);
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
}
return 0;
@@ -1027,7 +906,7 @@ static struct saa7146_extension extension = {
static int __init mxb_init_module(void)
{
- if( 0 != saa7146_register_extension(&extension)) {
+ if (saa7146_register_extension(&extension)) {
DEB_S(("failed to register extension.\n"));
return -ENODEV;
}
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 9edaca4371d..210f1240b33 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -626,9 +626,9 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
break;
/* Retry until idle */
- do
+ do {
rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ } while (rc > 0 && ((rc&1) == 0));
if (rc < 0)
break;
@@ -703,9 +703,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
return rc;
/* Retry until idle */
- do
- rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ do {
+ rc = reg_r(ov, R511_I2C_CTL);
+ } while (rc > 0 && ((rc & 1) == 0));
if (rc < 0)
return rc;
@@ -729,9 +729,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
return rc;
/* Retry until idle */
- do
+ do {
rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ } while (rc > 0 && ((rc&1) == 0));
if (rc < 0)
return rc;
@@ -974,14 +974,14 @@ dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
for (i = reg1; i <= regn; i++) {
rc = i2c_r(ov, i);
- info("Sensor[0x%02X] = 0x%02X", i, rc);
+ dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc);
}
}
static void
dump_i2c_regs(struct usb_ov511 *ov)
{
- info("I2C REGS");
+ dev_info(&ov->dev->dev, "I2C REGS\n");
dump_i2c_range(ov, 0x00, 0x7C);
}
@@ -992,28 +992,28 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
for (i = reg1; i <= regn; i++) {
rc = reg_r(ov, i);
- info("OV511[0x%02X] = 0x%02X", i, rc);
+ dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc);
}
}
static void
ov511_dump_regs(struct usb_ov511 *ov)
{
- info("CAMERA INTERFACE REGS");
+ dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n");
dump_reg_range(ov, 0x10, 0x1f);
- info("DRAM INTERFACE REGS");
+ dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n");
dump_reg_range(ov, 0x20, 0x23);
- info("ISO FIFO REGS");
+ dev_info(&ov->dev->dev, "ISO FIFO REGS\n");
dump_reg_range(ov, 0x30, 0x31);
- info("PIO REGS");
+ dev_info(&ov->dev->dev, "PIO REGS\n");
dump_reg_range(ov, 0x38, 0x39);
dump_reg_range(ov, 0x3e, 0x3e);
- info("I2C REGS");
+ dev_info(&ov->dev->dev, "I2C REGS\n");
dump_reg_range(ov, 0x40, 0x49);
- info("SYSTEM CONTROL REGS");
+ dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n");
dump_reg_range(ov, 0x50, 0x55);
dump_reg_range(ov, 0x5e, 0x5f);
- info("OmniCE REGS");
+ dev_info(&ov->dev->dev, "OmniCE REGS\n");
dump_reg_range(ov, 0x70, 0x79);
/* NOTE: Quantization tables are not readable. You will get the value
* in reg. 0x79 for every table register */
@@ -1025,25 +1025,25 @@ ov511_dump_regs(struct usb_ov511 *ov)
static void
ov518_dump_regs(struct usb_ov511 *ov)
{
- info("VIDEO MODE REGS");
+ dev_info(&ov->dev->dev, "VIDEO MODE REGS\n");
dump_reg_range(ov, 0x20, 0x2f);
- info("DATA PUMP AND SNAPSHOT REGS");
+ dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n");
dump_reg_range(ov, 0x30, 0x3f);
- info("I2C REGS");
+ dev_info(&ov->dev->dev, "I2C REGS\n");
dump_reg_range(ov, 0x40, 0x4f);
- info("SYSTEM CONTROL AND VENDOR REGS");
+ dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n");
dump_reg_range(ov, 0x50, 0x5f);
- info("60 - 6F");
+ dev_info(&ov->dev->dev, "60 - 6F\n");
dump_reg_range(ov, 0x60, 0x6f);
- info("70 - 7F");
+ dev_info(&ov->dev->dev, "70 - 7F\n");
dump_reg_range(ov, 0x70, 0x7f);
- info("Y QUANTIZATION TABLE");
+ dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n");
dump_reg_range(ov, 0x80, 0x8f);
- info("UV QUANTIZATION TABLE");
+ dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n");
dump_reg_range(ov, 0x90, 0x9f);
- info("A0 - BF");
+ dev_info(&ov->dev->dev, "A0 - BF\n");
dump_reg_range(ov, 0xa0, 0xbf);
- info("CBR");
+ dev_info(&ov->dev->dev, "CBR\n");
dump_reg_range(ov, 0xc0, 0xcf);
}
#endif
@@ -1098,9 +1098,10 @@ ov51x_clear_snapshot(struct usb_ov511 *ov)
reg_w(ov, R51x_SYS_SNAP, 0x02);
reg_w(ov, R51x_SYS_SNAP, 0x00);
} else if (ov->bclass == BCL_OV518) {
- warn("snapshot reset not supported yet on OV518(+)");
+ dev_warn(&ov->dev->dev,
+ "snapshot reset not supported yet on OV518(+)\n");
} else {
- err("clear snap: invalid bridge type");
+ dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n");
}
}
@@ -1115,14 +1116,16 @@ ov51x_check_snapshot(struct usb_ov511 *ov)
if (ov->bclass == BCL_OV511) {
ret = reg_r(ov, R51x_SYS_SNAP);
if (ret < 0) {
- err("Error checking snspshot status (%d)", ret);
+ dev_err(&ov->dev->dev,
+ "Error checking snspshot status (%d)\n", ret);
} else if (ret & 0x08) {
status = 1;
}
} else if (ov->bclass == BCL_OV518) {
- warn("snapshot check not supported yet on OV518(+)");
+ dev_warn(&ov->dev->dev,
+ "snapshot check not supported yet on OV518(+)\n");
} else {
- err("check snap: invalid bridge type");
+ dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n");
}
return status;
@@ -3205,9 +3208,10 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
*/
if (printph) {
- info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
- pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
- in[7], in[8], in[9], in[10], in[11]);
+ dev_info(&ov->dev->dev,
+ "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",
+ pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
+ in[7], in[8], in[9], in[10], in[11]);
}
/* Check for SOF/EOF packet */
@@ -3366,8 +3370,10 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
* the definitive SOF/EOF format */
if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
if (printph) {
- info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0],
- in[1], in[2], in[3], in[4], in[5], in[6], in[7]);
+ dev_info(&ov->dev->dev,
+ "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+ in[0], in[1], in[2], in[3], in[4], in[5],
+ in[6], in[7]);
}
if (frame->scanstate == STATE_LINES) {
@@ -3591,7 +3597,7 @@ static int
ov51x_init_isoc(struct usb_ov511 *ov)
{
struct urb *urb;
- int fx, err, n, size;
+ int fx, err, n, i, size;
PDEBUG(3, "*** Initializing capture ***");
@@ -3646,14 +3652,16 @@ ov51x_init_isoc(struct usb_ov511 *ov)
if (packetsize == -1) {
ov518_set_packet_size(ov, 640);
} else {
- info("Forcing packet size to %d", packetsize);
+ dev_info(&ov->dev->dev, "Forcing packet size to %d\n",
+ packetsize);
ov518_set_packet_size(ov, packetsize);
}
} else {
if (packetsize == -1) {
ov511_set_packet_size(ov, size);
} else {
- info("Forcing packet size to %d", packetsize);
+ dev_info(&ov->dev->dev, "Forcing packet size to %d\n",
+ packetsize);
ov511_set_packet_size(ov, packetsize);
}
}
@@ -3662,6 +3670,8 @@ ov51x_init_isoc(struct usb_ov511 *ov)
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
+ for (i = 0; i < n; i++)
+ usb_free_urb(ov->sbuf[i].urb);
return -ENOMEM;
}
ov->sbuf[n].urb = urb;
@@ -4119,7 +4129,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
return -EIO;
if (force_palette && p->palette != force_palette) {
- info("Palette rejected (%s)",
+ dev_info(&ov->dev->dev, "Palette rejected (%s)\n",
symbolic(v4l1_plist, p->palette));
return -EINVAL;
}
@@ -4847,26 +4857,27 @@ ov7xx0_configure(struct usb_ov511 *ov)
err("Error detecting sensor type");
return -1;
} else if ((rc & 3) == 3) {
- info("Sensor is an OV7610");
+ dev_info(&ov->dev->dev, "Sensor is an OV7610\n");
ov->sensor = SEN_OV7610;
} else if ((rc & 3) == 1) {
/* I don't know what's different about the 76BE yet. */
if (i2c_r(ov, 0x15) & 1)
- info("Sensor is an OV7620AE");
+ dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n");
else
- info("Sensor is an OV76BE");
+ dev_info(&ov->dev->dev, "Sensor is an OV76BE\n");
/* OV511+ will return all zero isoc data unless we
* configure the sensor as a 7620. Someone needs to
* find the exact reg. setting that causes this. */
if (ov->bridge == BRG_OV511PLUS) {
- info("Enabling 511+/7620AE workaround");
+ dev_info(&ov->dev->dev,
+ "Enabling 511+/7620AE workaround\n");
ov->sensor = SEN_OV7620;
} else {
ov->sensor = SEN_OV76BE;
}
} else if ((rc & 3) == 0) {
- info("Sensor is an OV7620");
+ dev_info(&ov->dev->dev, "Sensor is an OV7620\n");
ov->sensor = SEN_OV7620;
} else {
err("Unknown image sensor version: %d", rc & 3);
@@ -5022,16 +5033,16 @@ ov6xx0_configure(struct usb_ov511 *ov)
if ((rc & 3) == 0) {
ov->sensor = SEN_OV6630;
- info("Sensor is an OV6630");
+ dev_info(&ov->dev->dev, "Sensor is an OV6630\n");
} else if ((rc & 3) == 1) {
ov->sensor = SEN_OV6620;
- info("Sensor is an OV6620");
+ dev_info(&ov->dev->dev, "Sensor is an OV6620\n");
} else if ((rc & 3) == 2) {
ov->sensor = SEN_OV6630;
- info("Sensor is an OV6630AE");
+ dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n");
} else if ((rc & 3) == 3) {
ov->sensor = SEN_OV6630;
- info("Sensor is an OV6630AF");
+ dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n");
}
/* Set sensor-specific vars */
@@ -5086,10 +5097,10 @@ ks0127_configure(struct usb_ov511 *ov)
err("Error detecting sensor type");
return -1;
} else if ((rc & 0x0f) == 0) {
- info("Sensor is a KS0127");
+ dev_info(&ov->dev->dev, "Sensor is a KS0127\n");
ov->sensor = SEN_KS0127;
} else if ((rc & 0x0f) == 9) {
- info("Sensor is a KS0127B Rev. A");
+ dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n");
ov->sensor = SEN_KS0127B;
}
} else {
@@ -5198,7 +5209,8 @@ saa7111a_configure(struct usb_ov511 *ov)
err("Error detecting sensor version");
return -1;
} else {
- info("Sensor is an SAA7111A (version 0x%x)", rc);
+ dev_info(&ov->dev->dev,
+ "Sensor is an SAA7111A (version 0x%x)\n", rc);
ov->sensor = SEN_SAA7111A;
}
@@ -5208,7 +5220,8 @@ saa7111a_configure(struct usb_ov511 *ov)
if (ov->bclass == BCL_OV511)
reg_w(ov, 0x11, 0x00);
else
- warn("SAA7111A not yet supported with OV518/OV518+");
+ dev_warn(&ov->dev->dev,
+ "SAA7111A not yet supported with OV518/OV518+\n");
return 0;
}
@@ -5260,7 +5273,7 @@ ov511_configure(struct usb_ov511 *ov)
PDEBUG (1, "CustomID = %d", ov->customid);
ov->desc = symbolic(camlist, ov->customid);
- info("model: %s", ov->desc);
+ dev_info(&ov->dev->dev, "model: %s\n", ov->desc);
if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
err("Camera type (%d) not recognized", ov->customid);
@@ -5424,7 +5437,8 @@ ov518_configure(struct usb_ov511 *ov)
PDEBUG(4, "");
/* First 5 bits of custom ID reg are a revision ID on OV518 */
- info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
+ dev_info(&ov->dev->dev, "Device revision %d\n",
+ 0x1F & reg_r(ov, R511_SYS_CUST_ID));
/* Give it the default description */
ov->desc = symbolic(camlist, 0);
@@ -5446,7 +5460,8 @@ ov518_configure(struct usb_ov511 *ov)
* required. OV518 has no uncompressed mode, to save RAM. */
if (!dumppix && !ov->compress) {
ov->compress = 1;
- warn("Compression required with OV518...enabling");
+ dev_warn(&ov->dev->dev,
+ "Compression required with OV518...enabling\n");
}
if (ov->bridge == BRG_OV518) {
@@ -5651,7 +5666,7 @@ static ssize_t show_exposure(struct device *cd,
if (!ov->dev)
return -ENODEV;
sensor_get_exposure(ov, &exp);
- return sprintf(buf, "%d\n", exp >> 8);
+ return sprintf(buf, "%d\n", exp);
}
static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
@@ -5771,7 +5786,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
- info("USB %s video device found", symbolic(brglist, ov->bridge));
+ dev_info(&intf->dev, "USB %s video device found\n",
+ symbolic(brglist, ov->bridge));
init_waitqueue_head(&ov->wq);
@@ -5852,8 +5868,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
- info("Device at %s registered to minor %d", ov->usb_path,
- ov->vdev->minor);
+ dev_info(&intf->dev, "Device at %s registered to minor %d\n",
+ ov->usb_path, ov->vdev->minor);
usb_set_intfdata(intf, ov);
if (ov_create_sysfs(ov->vdev)) {
@@ -5956,7 +5972,8 @@ usb_ov511_init(void)
if (retval)
goto out;
- info(DRIVER_VERSION " : " DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
out:
return retval;
@@ -5966,8 +5983,7 @@ static void __exit
usb_ov511_exit(void)
{
usb_deregister(&ov511_driver);
- info("driver deregistered");
-
+ printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n");
}
module_init(usb_ov511_init);
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h
index baded1262ca..70d99e52329 100644
--- a/drivers/media/video/ov511.h
+++ b/drivers/media/video/ov511.h
@@ -12,7 +12,8 @@
#ifdef OV511_DEBUG
#define PDEBUG(level, fmt, args...) \
- if (debug >= (level)) info("[%s:%d] " fmt, \
+ if (debug >= (level)) \
+ printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \
__func__, __LINE__ , ## args)
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 065c2454113..2c4acbf5a4f 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -49,12 +49,6 @@ MODULE_LICENSE("GPL");
#define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */
#define GENERIC_REG_COM_I 0x29 /* misc ID bits */
-extern struct ovcamchip_ops ov6x20_ops;
-extern struct ovcamchip_ops ov6x30_ops;
-extern struct ovcamchip_ops ov7x10_ops;
-extern struct ovcamchip_ops ov7x20_ops;
-extern struct ovcamchip_ops ov76be_ops;
-
static char *chip_names[NUM_CC_TYPES] = {
[CC_UNKNOWN] = "Unknown chip",
[CC_OV76BE] = "OV76BE",
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index 9afa4fe4772..a05650faedd 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -53,6 +53,12 @@ struct ovcamchip {
int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */
};
+extern struct ovcamchip_ops ov6x20_ops;
+extern struct ovcamchip_ops ov6x30_ops;
+extern struct ovcamchip_ops ov7x10_ops;
+extern struct ovcamchip_ops ov7x20_ops;
+extern struct ovcamchip_ops ov76be_ops;
+
/* --------------------------------- */
/* I2C I/O */
/* --------------------------------- */
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 00425d74365..994807818aa 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -47,6 +47,7 @@ struct pms_device
struct video_picture picture;
int height;
int width;
+ unsigned long in_use;
struct mutex lock;
};
@@ -881,10 +882,27 @@ static ssize_t pms_read(struct file *file, char __user *buf,
return len;
}
+static int pms_exclusive_open(struct inode *inode, struct file *file)
+{
+ struct video_device *v = video_devdata(file);
+ struct pms_device *pd = (struct pms_device *)v;
+
+ return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0;
+}
+
+static int pms_exclusive_release(struct inode *inode, struct file *file)
+{
+ struct video_device *v = video_devdata(file);
+ struct pms_device *pd = (struct pms_device *)v;
+
+ clear_bit(0, &pd->in_use);
+ return 0;
+}
+
static const struct file_operations pms_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = pms_exclusive_open,
+ .release = pms_exclusive_release,
.ioctl = pms_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -897,6 +915,7 @@ static struct video_device pms_template=
{
.name = "Mediavision PMS",
.fops = &pms_fops,
+ .release = video_device_release_empty,
};
static struct pms_device pms_device;
@@ -1019,10 +1038,23 @@ static int init_mediavision(void)
* Initialization and module stuff
*/
+#ifndef MODULE
+static int enable;
+module_param(enable, int, 0);
+#endif
+
static int __init init_pms_cards(void)
{
printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
+#ifndef MODULE
+ if (!enable) {
+ printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to "
+ "probe\n");
+ return -ENODEV;
+ }
+#endif
+
data_port = io_port +1;
if(init_mediavision())
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 0764fbfffb7..203f54cd18a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -134,13 +134,17 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
/* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
{
int ret = 0;
if (!cptr) return 0;
LOCK_TAKE(cptr->hdw->big_lock); do {
if (cptr->info->type == pvr2_ctl_int) {
- ret = cptr->info->default_value;
+ if (cptr->info->get_def_value) {
+ ret = cptr->info->get_def_value(cptr, valptr);
+ } else {
+ *valptr = cptr->info->default_value;
+ }
}
} while(0); LOCK_GIVE(cptr->hdw->big_lock);
return ret;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
index 0371ae6e6e4..794ff90121c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
@@ -49,7 +49,7 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *);
int pvr2_ctrl_get_min(struct pvr2_ctrl *);
/* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *);
+int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr);
/* Retrieve control's enumeration count (enum only) */
int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 88e17516843..cbe2a341785 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -489,6 +489,8 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
struct usb_device_id pvr2_device_table[] = {
{ USB_DEVICE(0x2040, 0x2900),
.driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
+ { USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
+ .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
{ USB_DEVICE(0x2040, 0x2400),
.driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
{ USB_DEVICE(0x1164, 0x0622),
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 657f861593b..de7ee7264be 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -82,6 +82,7 @@ struct pvr2_ctl_info {
/* Control's implementation */
pvr2_ctlf_get_value get_value; /* Get its value */
+ pvr2_ctlf_get_value get_def_value; /* Get its default value */
pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */
pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */
pvr2_ctlf_set_value set_value; /* Set its value */
@@ -307,6 +308,10 @@ struct pvr2_hdw {
struct v4l2_tuner tuner_signal_info;
int tuner_signal_stale;
+ /* Cropping capability info */
+ struct v4l2_cropcap cropcap_info;
+ int cropcap_stale;
+
/* Video standard handling */
v4l2_std_id std_mask_eeprom; // Hardware supported selections
v4l2_std_id std_mask_avail; // Which standards we may select from
@@ -367,6 +372,10 @@ struct pvr2_hdw {
VCREATE_DATA(bass);
VCREATE_DATA(treble);
VCREATE_DATA(mute);
+ VCREATE_DATA(cropl);
+ VCREATE_DATA(cropt);
+ VCREATE_DATA(cropw);
+ VCREATE_DATA(croph);
VCREATE_DATA(input);
VCREATE_DATA(audiomode);
VCREATE_DATA(res_hor);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index f051c6aa7f1..94265bd3d92 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
unsigned int timeout,int probe_fl,
void *write_data,unsigned int write_len,
void *read_data,unsigned int read_len);
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw);
static void trace_stbit(const char *name,int val)
@@ -402,6 +403,194 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
return 0;
}
+static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *left = cap->bounds.left;
+ return 0;
+}
+
+static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *left = cap->bounds.left;
+ if (cap->bounds.width > cptr->hdw->cropw_val) {
+ *left += cap->bounds.width - cptr->hdw->cropw_val;
+ }
+ return 0;
+}
+
+static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *top = cap->bounds.top;
+ return 0;
+}
+
+static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *top = cap->bounds.top;
+ if (cap->bounds.height > cptr->hdw->croph_val) {
+ *top += cap->bounds.height - cptr->hdw->croph_val;
+ }
+ return 0;
+}
+
+static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = 0;
+ if (cap->bounds.width > cptr->hdw->cropl_val) {
+ *val = cap->bounds.width - cptr->hdw->cropl_val;
+ }
+ return 0;
+}
+
+static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = 0;
+ if (cap->bounds.height > cptr->hdw->cropt_val) {
+ *val = cap->bounds.height - cptr->hdw->cropt_val;
+ }
+ return 0;
+}
+
+static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->bounds.left;
+ return 0;
+}
+
+static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->bounds.top;
+ return 0;
+}
+
+static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->bounds.width;
+ return 0;
+}
+
+static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->bounds.height;
+ return 0;
+}
+
+static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->defrect.left;
+ return 0;
+}
+
+static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->defrect.top;
+ return 0;
+}
+
+static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->defrect.width;
+ return 0;
+}
+
+static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->defrect.height;
+ return 0;
+}
+
+static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->pixelaspect.numerator;
+ return 0;
+}
+
+static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val)
+{
+ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+ int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+ if (stat != 0) {
+ return stat;
+ }
+ *val = cap->pixelaspect.denominator;
+ return 0;
+}
+
static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
{
/* Actual maximum depends on the video standard in effect. */
@@ -779,6 +968,10 @@ VCREATE_FUNCS(balance)
VCREATE_FUNCS(bass)
VCREATE_FUNCS(treble)
VCREATE_FUNCS(mute)
+VCREATE_FUNCS(cropl)
+VCREATE_FUNCS(cropt)
+VCREATE_FUNCS(cropw)
+VCREATE_FUNCS(croph)
VCREATE_FUNCS(audiomode)
VCREATE_FUNCS(res_hor)
VCREATE_FUNCS(res_ver)
@@ -849,6 +1042,72 @@ static const struct pvr2_ctl_info control_defs[] = {
.default_value = 0,
DEFREF(mute),
DEFBOOL,
+ }, {
+ .desc = "Capture crop left margin",
+ .name = "crop_left",
+ .internal_id = PVR2_CID_CROPL,
+ .default_value = 0,
+ DEFREF(cropl),
+ DEFINT(-129, 340),
+ .get_min_value = ctrl_cropl_min_get,
+ .get_max_value = ctrl_cropl_max_get,
+ .get_def_value = ctrl_get_cropcapdl,
+ }, {
+ .desc = "Capture crop top margin",
+ .name = "crop_top",
+ .internal_id = PVR2_CID_CROPT,
+ .default_value = 0,
+ DEFREF(cropt),
+ DEFINT(-35, 544),
+ .get_min_value = ctrl_cropt_min_get,
+ .get_max_value = ctrl_cropt_max_get,
+ .get_def_value = ctrl_get_cropcapdt,
+ }, {
+ .desc = "Capture crop width",
+ .name = "crop_width",
+ .internal_id = PVR2_CID_CROPW,
+ .default_value = 720,
+ DEFREF(cropw),
+ .get_max_value = ctrl_cropw_max_get,
+ .get_def_value = ctrl_get_cropcapdw,
+ }, {
+ .desc = "Capture crop height",
+ .name = "crop_height",
+ .internal_id = PVR2_CID_CROPH,
+ .default_value = 480,
+ DEFREF(croph),
+ .get_max_value = ctrl_croph_max_get,
+ .get_def_value = ctrl_get_cropcapdh,
+ }, {
+ .desc = "Capture capability pixel aspect numerator",
+ .name = "cropcap_pixel_numerator",
+ .internal_id = PVR2_CID_CROPCAPPAN,
+ .get_value = ctrl_get_cropcappan,
+ }, {
+ .desc = "Capture capability pixel aspect denominator",
+ .name = "cropcap_pixel_denominator",
+ .internal_id = PVR2_CID_CROPCAPPAD,
+ .get_value = ctrl_get_cropcappad,
+ }, {
+ .desc = "Capture capability bounds top",
+ .name = "cropcap_bounds_top",
+ .internal_id = PVR2_CID_CROPCAPBT,
+ .get_value = ctrl_get_cropcapbt,
+ }, {
+ .desc = "Capture capability bounds left",
+ .name = "cropcap_bounds_left",
+ .internal_id = PVR2_CID_CROPCAPBL,
+ .get_value = ctrl_get_cropcapbl,
+ }, {
+ .desc = "Capture capability bounds width",
+ .name = "cropcap_bounds_width",
+ .internal_id = PVR2_CID_CROPCAPBW,
+ .get_value = ctrl_get_cropcapbw,
+ }, {
+ .desc = "Capture capability bounds height",
+ .name = "cropcap_bounds_height",
+ .internal_id = PVR2_CID_CROPCAPBH,
+ .get_value = ctrl_get_cropcapbh,
},{
.desc = "Video Source",
.name = "input",
@@ -1313,9 +1572,19 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
/* Usbsnoop log shows that we must swap bytes... */
+ /* Some background info: The data being swapped here is a
+ firmware image destined for the mpeg encoder chip that
+ lives at the other end of a USB endpoint. The encoder
+ chip always talks in 32 bit chunks and its storage is
+ organized into 32 bit words. However from the file
+ system to the encoder chip everything is purely a byte
+ stream. The firmware file's contents are always 32 bit
+ swapped from what the encoder expects. Thus the need
+ always exists to swap the bytes regardless of the endian
+ type of the host processor and therefore swab32() makes
+ the most sense. */
for (icnt = 0; icnt < bcnt/4 ; icnt++)
- ((u32 *)fw_ptr)[icnt] =
- ___swab32(((u32 *)fw_ptr)[icnt]);
+ ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
&actual_length, HZ);
@@ -1905,7 +2174,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
const struct usb_device_id *devid)
{
unsigned int idx,cnt1,cnt2,m;
- struct pvr2_hdw *hdw;
+ struct pvr2_hdw *hdw = NULL;
int valid_std_mask;
struct pvr2_ctrl *cptr;
const struct pvr2_device_desc *hdw_desc;
@@ -1915,6 +2184,16 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
+ if (hdw_desc == NULL) {
+ pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:"
+ " No device description pointer,"
+ " unable to continue.");
+ pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type,"
+ " please contact Mike Isely <isely@pobox.com>"
+ " to get it included in the driver\n");
+ goto fail;
+ }
+
hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
hdw,hdw_desc->description);
@@ -2072,6 +2351,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
valid_std_mask;
}
+ hdw->cropcap_stale = !0;
hdw->eeprom_addr = -1;
hdw->unit_number = -1;
hdw->v4l_minor_number_video = -1;
@@ -2508,6 +2788,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
/* Can't commit anything until pathway is ok. */
return 0;
}
+ /* The broadcast decoder can only scale down, so if
+ * res_*_dirty && crop window < output format ==> enlarge crop.
+ *
+ * The mpeg encoder receives fields of res_hor_val dots and
+ * res_ver_val halflines. Limits: hor<=720, ver<=576.
+ */
+ if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
+ hdw->cropw_val = hdw->res_hor_val;
+ hdw->cropw_dirty = !0;
+ } else if (hdw->cropw_dirty) {
+ hdw->res_hor_dirty = !0; /* must rescale */
+ hdw->res_hor_val = min(720, hdw->cropw_val);
+ }
+ if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
+ hdw->croph_val = hdw->res_ver_val;
+ hdw->croph_dirty = !0;
+ } else if (hdw->croph_dirty) {
+ int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
+ hdw->res_ver_dirty = !0;
+ hdw->res_ver_val = min(nvres, hdw->croph_val);
+ }
+
/* If any of the below has changed, then we can't do the update
while the pipeline is running. Pipeline must be paused first
and decoder -> encoder connection be made quiescent before we
@@ -2518,6 +2820,8 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
hdw->srate_dirty ||
hdw->res_ver_dirty ||
hdw->res_hor_dirty ||
+ hdw->cropw_dirty ||
+ hdw->croph_dirty ||
hdw->input_dirty ||
(hdw->active_stream_type != hdw->desired_stream_type));
if (disruptive_change && !hdw->state_pipeline_idle) {
@@ -2587,6 +2891,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
}
hdw->state_pipeline_config = !0;
+ /* Hardware state may have changed in a way to cause the cropping
+ capabilities to have changed. So mark it stale, which will
+ cause a later re-fetch. */
trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
return !0;
}
@@ -2677,6 +2984,33 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
}
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
+{
+ if (!hdw->cropcap_stale) {
+ return 0;
+ }
+ pvr2_i2c_core_status_poll(hdw);
+ if (hdw->cropcap_stale) {
+ return -EIO;
+ }
+ return 0;
+}
+
+
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp)
+{
+ int stat = 0;
+ LOCK_TAKE(hdw->big_lock);
+ stat = pvr2_hdw_check_cropcap(hdw);
+ if (!stat) {
+ memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info));
+ }
+ LOCK_GIVE(hdw->big_lock);
+ return stat;
+}
+
+
/* Return information about the tuner */
int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
{
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index c04956d304a..49482d1f2b2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -36,6 +36,16 @@
#define PVR2_CID_FREQUENCY 6
#define PVR2_CID_HRES 7
#define PVR2_CID_VRES 8
+#define PVR2_CID_CROPL 9
+#define PVR2_CID_CROPT 10
+#define PVR2_CID_CROPW 11
+#define PVR2_CID_CROPH 12
+#define PVR2_CID_CROPCAPPAN 13
+#define PVR2_CID_CROPCAPPAD 14
+#define PVR2_CID_CROPCAPBL 15
+#define PVR2_CID_CROPCAPBT 16
+#define PVR2_CID_CROPCAPBW 17
+#define PVR2_CID_CROPCAPBH 18
/* Legal values for the INPUT state variable */
#define PVR2_CVAL_INPUT_TV 0
@@ -170,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
/* Return information about the tuner */
int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *);
+
/* Query device and see if it thinks it is on a high-speed USB link */
int pvr2_hdw_is_hsm(struct pvr2_hdw *);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index ccdb429fc7a..94a47718e88 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -37,8 +37,9 @@
#define OP_VOLUME 3
#define OP_FREQ 4
#define OP_AUDIORATE 5
-#define OP_SIZE 6
-#define OP_LOG 7
+#define OP_CROP 6
+#define OP_SIZE 7
+#define OP_LOG 8
static const struct pvr2_i2c_op * const ops[] = {
[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
@@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = {
[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
+ [OP_CROP] = &pvr2_i2c_op_v4l2_crop,
[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
[OP_LOG] = &pvr2_i2c_op_v4l2_log,
};
@@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
(1 << OP_BCSH) |
(1 << OP_VOLUME) |
(1 << OP_FREQ) |
+ (1 << OP_CROP) |
(1 << OP_SIZE) |
(1 << OP_LOG));
cp->status_poll = pvr2_v4l2_cmd_status_poll;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index 55f04a0b204..16bb11902a5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw)
pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
}
hdw->tuner_signal_stale = !0;
+ hdw->cropcap_stale = !0;
}
@@ -233,6 +234,37 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
};
+static void set_crop(struct pvr2_hdw *hdw)
+{
+ struct v4l2_crop crop;
+
+ memset(&crop, 0, sizeof crop);
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c.left = hdw->cropl_val;
+ crop.c.top = hdw->cropt_val;
+ crop.c.height = hdw->croph_val;
+ crop.c.width = hdw->cropw_val;
+
+ pvr2_trace(PVR2_TRACE_CHIPS,
+ "i2c v4l2 set_crop crop=%d:%d:%d:%d",
+ crop.c.width, crop.c.height, crop.c.left, crop.c.top);
+
+ pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
+}
+
+static int check_crop(struct pvr2_hdw *hdw)
+{
+ return (hdw->cropl_dirty || hdw->cropt_dirty ||
+ hdw->cropw_dirty || hdw->croph_dirty);
+}
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
+ .check = check_crop,
+ .update = set_crop,
+ .name = "v4l2_crop",
+};
+
+
static void do_log(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
@@ -263,7 +295,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
{
- pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info);
+ int stat;
+ struct pvr2_hdw *hdw = cp->hdw;
+ if (hdw->cropcap_stale) {
+ hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP,
+ &hdw->cropcap_info);
+ if (stat == 0) {
+ /* Check was successful, so the data is no
+ longer considered stale. */
+ hdw->cropcap_stale = 0;
+ }
+ }
+ pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index 7fa38683b3b..eb744a20610 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index e600576a6c4..d6a35401fef 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -827,7 +827,7 @@ static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
unsigned int idx;
unsigned long msk,sm;
- int spcfl;
+
bcnt = scnprintf(buf,maxlen," [");
ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
sm = 0;
@@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client)
INIT_LIST_HEAD(&cp->list);
cp->client = client;
mutex_lock(&hdw->i2c_list_lock); do {
+ hdw->cropcap_stale = !0;
list_add_tail(&cp->list,&hdw->i2c_clients);
hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
} while (0); mutex_unlock(&hdw->i2c_list_lock);
@@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client)
unsigned long amask = 0;
int foundfl = 0;
mutex_lock(&hdw->i2c_list_lock); do {
+ hdw->cropcap_stale = !0;
list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
if (cp->client == client) {
trace_i2c("pvr2_i2c_detach"
@@ -946,22 +948,32 @@ static struct i2c_adapter pvr2_i2c_adap_template = {
.client_unregister = pvr2_i2c_detach_inform,
};
-static void do_i2c_scan(struct pvr2_hdw *hdw)
+
+/* Return true if device exists at given address */
+static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
{
struct i2c_msg msg[1];
- int i,rc;
+ int rc;
msg[0].addr = 0;
msg[0].flags = I2C_M_RD;
msg[0].len = 0;
msg[0].buf = NULL;
- printk("%s: i2c scan beginning\n",hdw->name);
+ msg[0].addr = addr;
+ rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg));
+ return rc == 1;
+}
+
+static void do_i2c_scan(struct pvr2_hdw *hdw)
+{
+ int i;
+ printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
for (i = 0; i < 128; i++) {
- msg[0].addr = i;
- rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg));
- if (rc != 1) continue;
- printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
+ if (do_i2c_probe(hdw, i)) {
+ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
+ hdw->name, i);
+ }
}
- printk("%s: i2c scan done.\n",hdw->name);
+ printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
}
void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
@@ -980,8 +992,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
hdw->i2c_func[0x18] = i2c_black_hole;
} else if (ir_mode[hdw->unit_number] == 1) {
if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) {
- /* This comment is present PURELY to get
- checkpatch.pl to STFU. Lovely, eh? */
hdw->i2c_func[0x18] = i2c_24xxx_ir;
}
}
@@ -1006,6 +1016,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
mutex_init(&hdw->i2c_list_lock);
hdw->i2c_linked = !0;
i2c_add_adapter(&hdw->i2c_adap);
+ if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
+ /* Probe for a different type of IR receiver on this
+ device. If present, disable the emulated IR receiver. */
+ if (do_i2c_probe(hdw, 0x71)) {
+ pvr2_trace(PVR2_TRACE_INFO,
+ "Device has newer IR hardware;"
+ " disabling unneeded virtual IR device");
+ hdw->i2c_func[0x18] = NULL;
+ }
+ }
if (i2c_scan) do_i2c_scan(hdw);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index ad0d98c2ebb..9b3c874d96d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -137,9 +137,11 @@ static int __init pvr_init(void)
ret = usb_register(&pvr_driver);
if (ret == 0)
- info(DRIVER_DESC " : " DRIVER_VERSION);
- if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
- pvrusb2_debug,pvrusb2_debug);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
+ if (pvrusb2_debug)
+ printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n",
+ pvrusb2_debug,pvrusb2_debug);
pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 46a8c39ba03..733680f2131 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -65,6 +65,7 @@ struct pvr2_sysfs_ctl_item {
struct device_attribute attr_type;
struct device_attribute attr_min;
struct device_attribute attr_max;
+ struct device_attribute attr_def;
struct device_attribute attr_enum;
struct device_attribute attr_bits;
struct device_attribute attr_val;
@@ -145,6 +146,23 @@ static ssize_t show_max(struct device *class_dev,
return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
}
+static ssize_t show_def(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pvr2_sysfs_ctl_item *cip;
+ int val;
+ int ret;
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
+ ret = pvr2_ctrl_get_def(cip->cptr, &val);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d",
+ cip->chptr, cip->ctl_id, val, ret);
+ if (ret < 0) {
+ return ret;
+ }
+ return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
static ssize_t show_val_norm(struct device *class_dev,
struct device_attribute *attr,
char *buf)
@@ -320,6 +338,10 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_max.attr.mode = S_IRUGO;
cip->attr_max.show = show_max;
+ cip->attr_def.attr.name = "def_val";
+ cip->attr_def.attr.mode = S_IRUGO;
+ cip->attr_def.show = show_def;
+
cip->attr_val.attr.name = "cur_val";
cip->attr_val.attr.mode = S_IRUGO;
@@ -343,6 +365,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_gen[acnt++] = &cip->attr_name.attr;
cip->attr_gen[acnt++] = &cip->attr_type.attr;
cip->attr_gen[acnt++] = &cip->attr_val.attr;
+ cip->attr_gen[acnt++] = &cip->attr_def.attr;
cip->attr_val.show = show_val_norm;
cip->attr_val.store = store_val_norm;
if (pvr2_ctrl_has_custom_symbols(cptr)) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 00306faeac0..f048d80b77e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -533,7 +533,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
lmin = pvr2_ctrl_get_min(hcp);
lmax = pvr2_ctrl_get_max(hcp);
- ldef = pvr2_ctrl_get_def(hcp);
+ pvr2_ctrl_get_def(hcp, &ldef);
if (w == -1) {
w = ldef;
} else if (w < lmin) {
@@ -543,7 +543,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
}
lmin = pvr2_ctrl_get_min(vcp);
lmax = pvr2_ctrl_get_max(vcp);
- ldef = pvr2_ctrl_get_def(vcp);
+ pvr2_ctrl_get_def(vcp, &ldef);
if (h == -1) {
h = ldef;
} else if (h < lmin) {
@@ -604,6 +604,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_QUERYCTRL:
{
struct pvr2_ctrl *cptr;
+ int val;
struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
ret = 0;
if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
@@ -627,7 +628,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
pvr2_ctrl_get_desc(cptr));
strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
vc->flags = pvr2_ctrl_get_v4lflags(cptr);
- vc->default_value = pvr2_ctrl_get_def(cptr);
+ pvr2_ctrl_get_def(cptr, &val);
+ vc->default_value = val;
switch (pvr2_ctrl_get_type(cptr)) {
case pvr2_ctl_enum:
vc->type = V4L2_CTRL_TYPE_MENU;
@@ -753,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
break;
}
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = pvr2_hdw_get_cropcap(hdw, cap);
+ cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
+ break;
+ }
+ case VIDIOC_G_CROP:
+ {
+ struct v4l2_crop *crop = (struct v4l2_crop *)arg;
+ int val = 0;
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ crop->c.left = val;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ crop->c.top = val;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ crop->c.width = val;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ crop->c.height = val;
+ }
+ case VIDIOC_S_CROP:
+ {
+ struct v4l2_crop *crop = (struct v4l2_crop *)arg;
+ struct v4l2_cropcap cap;
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = -EINVAL;
+ break;
+ }
+ cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
+ crop->c.left);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
+ crop->c.top);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
+ crop->c.width);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
+ crop->c.height);
+ if (ret != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ }
case VIDIOC_LOG_STATUS:
{
pvr2_hdw_trigger_module_log(hdw);
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 1cccd5c7704..c6653021019 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -41,7 +41,6 @@
#include <asm/uaccess.h>
#endif
#include <asm/errno.h>
-#include <linux/version.h>
#include "pwc.h"
#include "pwc-uncompress.h"
@@ -1635,15 +1634,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCGVIDCMD:
{
- ARG_DEF(struct pwc_video_command, cmd);
-
- ARGR(cmd).type = pdev->type;
- ARGR(cmd).release = pdev->release;
- ARGR(cmd).command_len = pdev->cmd_len;
- memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
- ARGR(cmd).bandlength = pdev->vbandlength;
- ARGR(cmd).frame_size = pdev->frame_size;
- ARG_OUT(cmd)
+ ARG_DEF(struct pwc_video_command, vcmd);
+
+ ARGR(vcmd).type = pdev->type;
+ ARGR(vcmd).release = pdev->release;
+ ARGR(vcmd).command_len = pdev->cmd_len;
+ memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+ ARGR(vcmd).bandlength = pdev->vbandlength;
+ ARGR(vcmd).frame_size = pdev->frame_size;
+ ARG_OUT(vcmd)
break;
}
/*
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 9aee7cb6f79..ab28389b4cd 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1112,7 +1112,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
- pdev = (struct pwc_device *)vdev->priv;
+ pdev = video_get_drvdata(vdev);
BUG_ON(!pdev);
if (pdev->vopen) {
PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
@@ -1233,7 +1233,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
lock_kernel();
- pdev = (struct pwc_device *)vdev->priv;
+ pdev = video_get_drvdata(vdev);
if (pdev->vopen == 0)
PWC_DEBUG_MODULE("video_close() called on closed device?\n");
@@ -1304,7 +1304,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
vdev, buf, count);
if (vdev == NULL)
return -EFAULT;
- pdev = vdev->priv;
+ pdev = video_get_drvdata(vdev);
if (pdev == NULL)
return -EFAULT;
@@ -1386,7 +1386,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
if (vdev == NULL)
return -EFAULT;
- pdev = vdev->priv;
+ pdev = video_get_drvdata(vdev);
if (pdev == NULL)
return -EFAULT;
@@ -1408,7 +1408,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file,
if (!vdev)
goto out;
- pdev = vdev->priv;
+ pdev = video_get_drvdata(vdev);
mutex_lock(&pdev->modlock);
if (!pdev->unplugged)
@@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
int index;
PWC_DEBUG_MEMORY(">> %s\n", __func__);
- pdev = vdev->priv;
+ pdev = video_get_drvdata(vdev);
size = vma->vm_end - vma->vm_start;
start = vma->vm_start;
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 1742889874d..76a1376c975 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -346,7 +346,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
if (vdev == NULL)
return -EFAULT;
- pdev = vdev->priv;
+ pdev = video_get_drvdata(vdev);
if (pdev == NULL)
return -EFAULT;
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 388cf94055d..eb6be580292 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -629,17 +629,6 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
pdata->init(pcdev->dev);
}
- if (pdata && pdata->power) {
- dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
- pdata->power(pcdev->dev, 1);
- }
-
- if (pdata && pdata->reset) {
- dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
- __func__);
- pdata->reset(pcdev->dev, 1);
- }
-
CICR0 = 0x3FF; /* disable all interrupts */
if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
@@ -660,20 +649,7 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
{
- struct pxacamera_platform_data *board = pcdev->pdata;
-
clk_disable(pcdev->clk);
-
- if (board && board->reset) {
- dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
- __func__);
- board->reset(pcdev->dev, 0);
- }
-
- if (board && board->power) {
- dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
- board->power(pcdev->dev, 0);
- }
}
static irqreturn_t pxa_camera_irq(int irq, void *data)
@@ -1025,9 +1001,9 @@ static int pxa_camera_resume(struct soc_camera_device *icd)
struct pxa_camera_dev *pcdev = ici->priv;
int i = 0, ret = 0;
- DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
- DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
- DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
+ DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+ DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+ DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB;
CICR1 = pcdev->save_cicr[i++];
@@ -1144,36 +1120,36 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->dev = &pdev->dev;
/* request dma */
- pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
- pxa_camera_dma_irq_y, pcdev);
- if (pcdev->dma_chans[0] < 0) {
+ err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_y, pcdev);
+ if (err < 0) {
dev_err(pcdev->dev, "Can't request DMA for Y\n");
- err = -ENOMEM;
goto exit_iounmap;
}
+ pcdev->dma_chans[0] = err;
dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
- pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
- pxa_camera_dma_irq_u, pcdev);
- if (pcdev->dma_chans[1] < 0) {
+ err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_u, pcdev);
+ if (err < 0) {
dev_err(pcdev->dev, "Can't request DMA for U\n");
- err = -ENOMEM;
goto exit_free_dma_y;
}
+ pcdev->dma_chans[1] = err;
dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
- pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
- pxa_camera_dma_irq_v, pcdev);
- if (pcdev->dma_chans[0] < 0) {
+ err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_v, pcdev);
+ if (err < 0) {
dev_err(pcdev->dev, "Can't request DMA for V\n");
- err = -ENOMEM;
goto exit_free_dma_u;
}
+ pcdev->dma_chans[2] = err;
dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
- DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
- DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
- DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
+ DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+ DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+ DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
/* request irq */
err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index b1d09d8e2b8..5272926db73 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -58,6 +58,8 @@
+/* default JPEG quality */
+#define S2255_DEF_JPEG_QUAL 50
/* vendor request in */
#define S2255_VR_IN 0
/* vendor request out */
@@ -67,20 +69,21 @@
/* USB endpoint number for configuring the device */
#define S2255_CONFIG_EP 2
/* maximum time for DSP to start responding after last FW word loaded(ms) */
-#define S2255_DSP_BOOTTIME 400
+#define S2255_DSP_BOOTTIME 800
/* maximum time to wait for firmware to load (ms) */
#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
#define S2255_DEF_BUFS 16
+#define S2255_SETMODE_TIMEOUT 500
#define MAX_CHANNELS 4
-#define FRAME_MARKER 0x2255DA4AL
-#define MAX_PIPE_USBBLOCK (40 * 1024)
-#define DEFAULT_PIPE_USBBLOCK (16 * 1024)
+#define S2255_MARKER_FRAME 0x2255DA4AL
+#define S2255_MARKER_RESPONSE 0x2255ACACL
+#define S2255_USB_XFER_SIZE (16 * 1024)
#define MAX_CHANNELS 4
#define MAX_PIPE_BUFFERS 1
#define SYS_FRAMES 4
/* maximum size is PAL full size plus room for the marker header(s) */
-#define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096)
-#define DEF_USB_BLOCK (4096)
+#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096)
+#define DEF_USB_BLOCK S2255_USB_XFER_SIZE
#define LINE_SZ_4CIFS_NTSC 640
#define LINE_SZ_2CIFS_NTSC 640
#define LINE_SZ_1CIFS_NTSC 320
@@ -108,6 +111,9 @@
#define COLOR_YUVPL 1 /* YUV planar */
#define COLOR_YUVPK 2 /* YUV packed */
#define COLOR_Y8 4 /* monochrome */
+#define COLOR_JPG 5 /* JPEG */
+#define MASK_COLOR 0xff
+#define MASK_JPG_QUALITY 0xff00
/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
#define FDEC_1 1 /* capture every frame. default */
@@ -148,16 +154,14 @@ struct s2255_mode {
u32 restart; /* if DSP requires restart */
};
-/* frame structure */
-#define FRAME_STATE_UNUSED 0
-#define FRAME_STATE_FILLING 1
-#define FRAME_STATE_FULL 2
+#define S2255_READ_IDLE 0
+#define S2255_READ_FRAME 1
+/* frame structure */
struct s2255_framei {
unsigned long size;
-
- unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */
+ unsigned long ulState; /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/
void *lpvbits; /* image data */
unsigned long cur_size; /* current data copied to it */
};
@@ -188,6 +192,10 @@ struct s2255_dmaqueue {
#define S2255_FW_FAILED 3
#define S2255_FW_DISCONNECTING 4
+#define S2255_FW_MARKER 0x22552f2f
+/* 2255 read states */
+#define S2255_READ_IDLE 0
+#define S2255_READ_FRAME 1
struct s2255_fw {
int fw_loaded;
int fw_size;
@@ -195,7 +203,6 @@ struct s2255_fw {
atomic_t fw_state;
void *pfw_data;
wait_queue_head_t wait_fw;
- struct timer_list dsp_wait;
const struct firmware *fw;
};
@@ -237,15 +244,27 @@ struct s2255_dev {
struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS];
struct s2255_bufferi buffer[MAX_CHANNELS];
struct s2255_mode mode[MAX_CHANNELS];
+ /* jpeg compression */
+ struct v4l2_jpegcompression jc[MAX_CHANNELS];
const struct s2255_fmt *cur_fmt[MAX_CHANNELS];
int cur_frame[MAX_CHANNELS];
int last_frame[MAX_CHANNELS];
u32 cc; /* current channel */
int b_acquire[MAX_CHANNELS];
+ /* allocated image size */
unsigned long req_image_size[MAX_CHANNELS];
+ /* received packet size */
+ unsigned long pkt_size[MAX_CHANNELS];
int bad_payload[MAX_CHANNELS];
unsigned long frame_count[MAX_CHANNELS];
int frame_ready;
+ /* if JPEG image */
+ int jpg_size[MAX_CHANNELS];
+ /* if channel configured to default state */
+ int chn_configured[MAX_CHANNELS];
+ wait_queue_head_t wait_setmode[MAX_CHANNELS];
+ int setmode_ready[MAX_CHANNELS];
+ int chn_ready;
struct kref kref;
spinlock_t slock;
};
@@ -306,12 +325,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev);
static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn);
static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
- int chn);
+ int chn, int jpgsize);
static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
struct s2255_mode *mode);
static int s2255_board_shutdown(struct s2255_dev *dev);
static void s2255_exit_v4l(struct s2255_dev *dev);
-static void s2255_fwload_start(struct s2255_dev *dev);
+static void s2255_fwload_start(struct s2255_dev *dev, int reset);
+static void s2255_destroy(struct kref *kref);
+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
+ u16 index, u16 value, void *buf,
+ s32 buf_len, int bOut);
#define dprintk(level, fmt, arg...) \
do { \
@@ -407,6 +430,10 @@ static const struct s2255_fmt formats[] = {
.fourcc = V4L2_PIX_FMT_UYVY,
.depth = 16
}, {
+ .name = "JPG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .depth = 24
+ }, {
.name = "8bpp GREY",
.fourcc = V4L2_PIX_FMT_GREY,
.depth = 8
@@ -464,6 +491,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in,
return;
}
+static void s2255_reset_dsppower(struct s2255_dev *dev)
+{
+ s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1);
+ msleep(10);
+ s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
+ return;
+}
/* kickstarts the firmware loading. from probe
*/
@@ -480,18 +514,6 @@ static void s2255_timer(unsigned long user_data)
}
}
-/* called when DSP is up and running. DSP is guaranteed to
- be running after S2255_DSP_BOOTTIME */
-static void s2255_dsp_running(unsigned long user_data)
-{
- struct s2255_fw *data = (struct s2255_fw *)user_data;
- dprintk(1, "dsp running\n");
- atomic_set(&data->fw_state, S2255_FW_SUCCESS);
- wake_up(&data->wait_fw);
- printk(KERN_INFO "s2255: firmware loaded successfully\n");
- return;
-}
-
/* this loads the firmware asynchronously.
Originally this was done synchroously in probe.
@@ -549,19 +571,14 @@ static void s2255_fwchunk_complete(struct urb *urb)
}
data->fw_loaded += len;
} else {
- init_timer(&data->dsp_wait);
- data->dsp_wait.function = s2255_dsp_running;
- data->dsp_wait.data = (unsigned long)data;
atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
- mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME)
- + jiffies);
}
dprintk(100, "2255 complete done\n");
return;
}
-static int s2255_got_frame(struct s2255_dev *dev, int chn)
+static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
{
struct s2255_dmaqueue *dma_q = &dev->vidq[chn];
struct s2255_buffer *buf;
@@ -586,8 +603,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn)
list_del(&buf->vb.queue);
do_gettimeofday(&buf->vb.ts);
dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
-
- s2255_fillbuff(dev, buf, dma_q->channel);
+ s2255_fillbuff(dev, buf, dma_q->channel, jpgsize);
wake_up(&buf->vb.done);
dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
unlock:
@@ -621,7 +637,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc)
*
*/
static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
- int chn)
+ int chn, int jpgsize)
{
int pos = 0;
struct timeval ts;
@@ -649,6 +665,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
case V4L2_PIX_FMT_GREY:
memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
break;
+ case V4L2_PIX_FMT_JPEG:
+ buf->vb.size = jpgsize;
+ memcpy(vbuf, tmpbuf, buf->vb.size);
+ break;
case V4L2_PIX_FMT_YUV422P:
memcpy(vbuf, tmpbuf,
buf->vb.width * buf->vb.height * 2);
@@ -657,9 +677,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
printk(KERN_DEBUG "s2255: unknown format?\n");
}
dev->last_frame[chn] = -1;
- /* done with the frame, free it */
- frm->ulState = 0;
- dprintk(4, "freeing buffer\n");
} else {
printk(KERN_ERR "s2255: =======no frame\n");
return;
@@ -669,7 +686,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
(unsigned long)vbuf, pos);
/* tell v4l buffer was filled */
- buf->vb.field_count++;
+ buf->vb.field_count = dev->frame_count[chn] * 2;
do_gettimeofday(&ts);
buf->vb.ts = ts;
buf->vb.state = VIDEOBUF_DONE;
@@ -1021,6 +1038,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
case V4L2_PIX_FMT_GREY:
fh->mode.color = COLOR_Y8;
break;
+ case V4L2_PIX_FMT_JPEG:
+ fh->mode.color = COLOR_JPG |
+ (fh->dev->jc[fh->channel].quality << 8);
+ break;
case V4L2_PIX_FMT_YUV422P:
fh->mode.color = COLOR_YUVPL;
break;
@@ -1139,7 +1160,7 @@ static u32 get_transfer_size(struct s2255_mode *mode)
}
}
outImageSize = linesPerFrame * pixelsPerLine;
- if (mode->color != COLOR_Y8) {
+ if ((mode->color & MASK_COLOR) != COLOR_Y8) {
/* 2 bytes/pixel if not monochrome */
outImageSize *= 2;
}
@@ -1185,12 +1206,17 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
u32 *buffer;
unsigned long chn_rev;
+ mutex_lock(&dev->lock);
chn_rev = G_chnmap[chn];
dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
dev->mode[chn].scale);
dprintk(2, "mode contrast %x\n", mode->contrast);
+ /* if JPEG, set the quality */
+ if ((mode->color & MASK_COLOR) == COLOR_JPG)
+ mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG;
+
/* save the mode */
dev->mode[chn] = *mode;
dev->req_image_size[chn] = get_transfer_size(mode);
@@ -1199,6 +1225,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) {
dev_err(&dev->udev->dev, "out of mem\n");
+ mutex_unlock(&dev->lock);
return -ENOMEM;
}
@@ -1214,12 +1241,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
dprintk(1, "set mode done chn %lu, %d\n", chn, res);
/* wait at least 3 frames before continuing */
- if (mode->restart)
- msleep(125);
+ if (mode->restart) {
+ dev->setmode_ready[chn] = 0;
+ wait_event_timeout(dev->wait_setmode[chn],
+ (dev->setmode_ready[chn] != 0),
+ msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
+ if (dev->setmode_ready[chn] != 1) {
+ printk(KERN_DEBUG "s2255: no set mode response\n");
+ res = -EFAULT;
+ }
+ }
/* clear the restart flag */
dev->mode[chn].restart = 0;
-
+ mutex_unlock(&dev->lock);
return res;
}
@@ -1268,8 +1303,9 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
dev->last_frame[chn] = -1;
dev->bad_payload[chn] = 0;
dev->cur_frame[chn] = 0;
+ dev->frame_count[chn] = 0;
for (j = 0; j < SYS_FRAMES; j++) {
- dev->buffer[chn].frame[j].ulState = 0;
+ dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE;
dev->buffer[chn].frame[j].cur_size = 0;
}
res = videobuf_streamon(&fh->vb_vidq);
@@ -1445,6 +1481,27 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return -EINVAL;
}
+static int vidioc_g_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *jc)
+{
+ struct s2255_fh *fh = priv;
+ struct s2255_dev *dev = fh->dev;
+ *jc = dev->jc[fh->channel];
+ dprintk(2, "getting jpegcompression, quality %d\n", jc->quality);
+ return 0;
+}
+
+static int vidioc_s_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *jc)
+{
+ struct s2255_fh *fh = priv;
+ struct s2255_dev *dev = fh->dev;
+ if (jc->quality < 0 || jc->quality > 100)
+ return -EINVAL;
+ dev->jc[fh->channel].quality = jc->quality;
+ dprintk(2, "setting jpeg quality %d\n", jc->quality);
+ return 0;
+}
static int s2255_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
@@ -1454,8 +1511,10 @@ static int s2255_open(struct inode *inode, struct file *file)
enum v4l2_buf_type type = 0;
int i = 0;
int cur_channel = -1;
+ int state;
dprintk(1, "s2255: open called (minor=%d)\n", minor);
+ lock_kernel();
list_for_each(list, &s2255_devlist) {
h = list_entry(list, struct s2255_dev, s2255_devlist);
for (i = 0; i < MAX_CHANNELS; i++) {
@@ -1468,45 +1527,78 @@ static int s2255_open(struct inode *inode, struct file *file)
}
if ((NULL == dev) || (cur_channel == -1)) {
- dprintk(1, "s2255: openv4l no dev\n");
+ unlock_kernel();
+ printk(KERN_INFO "s2255: openv4l no dev\n");
return -ENODEV;
}
+ if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) {
+ unlock_kernel();
+ printk(KERN_INFO "disconnecting\n");
+ return -ENODEV;
+ }
+ kref_get(&dev->kref);
mutex_lock(&dev->open_lock);
dev->users[cur_channel]++;
dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
- if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
+ switch (atomic_read(&dev->fw_data->fw_state)) {
+ case S2255_FW_FAILED:
err("2255 firmware load failed. retrying.\n");
- s2255_fwload_start(dev);
+ s2255_fwload_start(dev, 1);
wait_event_timeout(dev->fw_data->wait_fw,
- (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_NOTLOADED),
+ ((atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_SUCCESS) ||
+ (atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_DISCONNECTING)),
msecs_to_jiffies(S2255_LOAD_TIMEOUT));
- if (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_SUCCESS) {
- printk(KERN_INFO "2255 FW load failed.\n");
- dev->users[cur_channel]--;
- mutex_unlock(&dev->open_lock);
- return -EFAULT;
- }
- } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) {
+ break;
+ case S2255_FW_NOTLOADED:
+ case S2255_FW_LOADED_DSPWAIT:
/* give S2255_LOAD_TIMEOUT time for firmware to load in case
driver loaded and then device immediately opened */
printk(KERN_INFO "%s waiting for firmware load\n", __func__);
wait_event_timeout(dev->fw_data->wait_fw,
- (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_NOTLOADED),
- msecs_to_jiffies(S2255_LOAD_TIMEOUT));
- if (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_SUCCESS) {
- printk(KERN_INFO "2255 firmware not loaded"
- "try again\n");
- dev->users[cur_channel]--;
- mutex_unlock(&dev->open_lock);
- return -EBUSY;
+ ((atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_SUCCESS) ||
+ (atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_DISCONNECTING)),
+ msecs_to_jiffies(S2255_LOAD_TIMEOUT));
+ break;
+ case S2255_FW_SUCCESS:
+ default:
+ break;
+ }
+ state = atomic_read(&dev->fw_data->fw_state);
+ if (state != S2255_FW_SUCCESS) {
+ int rc;
+ switch (state) {
+ case S2255_FW_FAILED:
+ printk(KERN_INFO "2255 FW load failed. %d\n", state);
+ rc = -ENODEV;
+ break;
+ case S2255_FW_DISCONNECTING:
+ printk(KERN_INFO "%s: disconnecting\n", __func__);
+ rc = -ENODEV;
+ break;
+ case S2255_FW_LOADED_DSPWAIT:
+ case S2255_FW_NOTLOADED:
+ printk(KERN_INFO "%s: firmware not loaded yet"
+ "please try again later\n",
+ __func__);
+ rc = -EAGAIN;
+ break;
+ default:
+ printk(KERN_INFO "%s: unknown state\n", __func__);
+ rc = -EFAULT;
+ break;
}
+ dev->users[cur_channel]--;
+ mutex_unlock(&dev->open_lock);
+ kref_put(&dev->kref, s2255_destroy);
+ unlock_kernel();
+ return rc;
}
/* allocate + initialize per filehandle data */
@@ -1514,6 +1606,8 @@ static int s2255_open(struct inode *inode, struct file *file)
if (NULL == fh) {
dev->users[cur_channel]--;
mutex_unlock(&dev->open_lock);
+ kref_put(&dev->kref, s2255_destroy);
+ unlock_kernel();
return -ENOMEM;
}
@@ -1527,6 +1621,13 @@ static int s2255_open(struct inode *inode, struct file *file)
fh->height = NUM_LINES_4CIFS_NTSC * 2;
fh->channel = cur_channel;
+ /* configure channel to default state */
+ if (!dev->chn_configured[cur_channel]) {
+ s2255_set_mode(dev, cur_channel, &fh->mode);
+ dev->chn_configured[cur_channel] = 1;
+ }
+
+
/* Put all controls at a sane state */
for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
qctl_regs[i] = s2255_qctrl[i].default_value;
@@ -1545,8 +1646,8 @@ static int s2255_open(struct inode *inode, struct file *file)
V4L2_FIELD_INTERLACED,
sizeof(struct s2255_buffer), fh);
- kref_get(&dev->kref);
mutex_unlock(&dev->open_lock);
+ unlock_kernel();
return 0;
}
@@ -1568,30 +1669,24 @@ static unsigned int s2255_poll(struct file *file,
static void s2255_destroy(struct kref *kref)
{
struct s2255_dev *dev = to_s2255_dev(kref);
+ struct list_head *list;
+ int i;
if (!dev) {
printk(KERN_ERR "s2255drv: kref problem\n");
return;
}
-
- /*
- * Wake up any firmware load waiting (only done in .open,
- * which holds the open_lock mutex)
- */
atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
wake_up(&dev->fw_data->wait_fw);
-
- /* prevent s2255_disconnect from racing s2255_open */
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ dev->setmode_ready[i] = 1;
+ wake_up(&dev->wait_setmode[i]);
+ }
mutex_lock(&dev->open_lock);
+ /* reset the DSP so firmware can be reload next time */
+ s2255_reset_dsppower(dev);
s2255_exit_v4l(dev);
- /*
- * device unregistered so no longer possible to open. open_mutex
- * can be unlocked and timers deleted afterwards.
- */
- mutex_unlock(&dev->open_lock);
-
/* board shutdown stops the read pipe if it is running */
s2255_board_shutdown(dev);
-
/* make sure firmware still not trying to load */
del_timer(&dev->timer); /* only started in .probe and .open */
@@ -1601,23 +1696,19 @@ static void s2255_destroy(struct kref *kref)
usb_free_urb(dev->fw_data->fw_urb);
dev->fw_data->fw_urb = NULL;
}
-
- /*
- * delete the dsp_wait timer, which sets the firmware
- * state on completion. This is done before fw_data
- * is freed below.
- */
-
- del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
-
if (dev->fw_data->fw)
release_firmware(dev->fw_data->fw);
kfree(dev->fw_data->pfw_data);
kfree(dev->fw_data);
-
usb_put_dev(dev->udev);
dprintk(1, "%s", __func__);
kfree(dev);
+
+ while (!list_empty(&s2255_devlist)) {
+ list = s2255_devlist.next;
+ list_del(list);
+ }
+ mutex_unlock(&dev->open_lock);
}
static int s2255_close(struct inode *inode, struct file *file)
@@ -1701,6 +1792,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidioc_cgmbuf,
#endif
+ .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
+ .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
};
static struct video_device template = {
@@ -1739,7 +1832,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
ret = video_register_device(dev->vdev[i],
VFL_TYPE_GRABBER,
cur_nr + i);
- dev->vdev[i]->priv = dev;
+ video_set_drvdata(dev->vdev[i], dev);
if (ret != 0) {
dev_err(&dev->udev->dev,
@@ -1753,18 +1846,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
static void s2255_exit_v4l(struct s2255_dev *dev)
{
- struct list_head *list;
+
int i;
- /* unregister the video devices */
- while (!list_empty(&s2255_devlist)) {
- list = s2255_devlist.next;
- list_del(list);
- }
for (i = 0; i < MAX_CHANNELS; i++) {
- if (-1 != dev->vdev[i]->minor)
+ if (-1 != dev->vdev[i]->minor) {
video_unregister_device(dev->vdev[i]);
- else
+ printk(KERN_INFO "s2255 unregistered\n");
+ } else {
video_device_release(dev->vdev[i]);
+ printk(KERN_INFO "s2255 released\n");
+ }
}
}
@@ -1774,134 +1865,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev)
* function again).
*
* Received frame structure:
- * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER)
+ * bytes 0-3: marker : 0x2255DA4AL (S2255_MARKER_FRAME)
* bytes 4-7: channel: 0-3
* bytes 8-11: payload size: size of the frame
* bytes 12-payloadsize+12: frame data
*/
static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
{
- static int dbgsync; /* = 0; */
char *pdest;
u32 offset = 0;
- int bsync = 0;
- int btrunc = 0;
+ int bframe = 0;
char *psrc;
unsigned long copy_size;
unsigned long size;
s32 idx = -1;
struct s2255_framei *frm;
unsigned char *pdata;
- unsigned long cur_size;
- int bsearch = 0;
- struct s2255_bufferi *buf;
+
dprintk(100, "buffer to user\n");
idx = dev->cur_frame[dev->cc];
- buf = &dev->buffer[dev->cc];
- frm = &buf->frame[idx];
-
- if (frm->ulState == 0) {
- frm->ulState = 1;
- frm->cur_size = 0;
- bsearch = 1;
- } else if (frm->ulState == 2) {
- /* system frame was not freed */
- dprintk(2, "sys frame not free. overrun ringbuf\n");
- bsearch = 1;
- frm->ulState = 1;
- frm->cur_size = 0;
- }
-
- if (bsearch) {
- if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) {
- u32 jj;
- if (dbgsync == 0) {
- dprintk(3, "not synched, discarding all packets"
- "until marker\n");
+ frm = &dev->buffer[dev->cc].frame[idx];
- dbgsync++;
- }
- pdata = (unsigned char *)pipe_info->transfer_buffer;
- for (jj = 0; jj < (pipe_info->cur_transfer_size - 12);
- jj++) {
- if (*(s32 *) pdata == FRAME_MARKER) {
- int cc;
- dprintk(3,
- "found frame marker at offset:"
- " %d [%x %x]\n", jj, pdata[0],
- pdata[1]);
- offset = jj;
- bsync = 1;
- cc = *(u32 *) (pdata + sizeof(u32));
- if (cc >= MAX_CHANNELS) {
- printk(KERN_ERR
- "bad channel\n");
- return -EINVAL;
- }
- /* reverse it */
- dev->cc = G_chnmap[cc];
+ if (frm->ulState == S2255_READ_IDLE) {
+ int jj;
+ unsigned int cc;
+ s32 *pdword;
+ int payload;
+ /* search for marker codes */
+ pdata = (unsigned char *)pipe_info->transfer_buffer;
+ for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) {
+ switch (*(s32 *) pdata) {
+ case S2255_MARKER_FRAME:
+ pdword = (s32 *)pdata;
+ dprintk(4, "found frame marker at offset:"
+ " %d [%x %x]\n", jj, pdata[0],
+ pdata[1]);
+ offset = jj + PREFIX_SIZE;
+ bframe = 1;
+ cc = pdword[1];
+ if (cc >= MAX_CHANNELS) {
+ printk(KERN_ERR
+ "bad channel\n");
+ return -EINVAL;
+ }
+ /* reverse it */
+ dev->cc = G_chnmap[cc];
+ payload = pdword[3];
+ if (payload > dev->req_image_size[dev->cc]) {
+ dev->bad_payload[dev->cc]++;
+ /* discard the bad frame */
+ return -EINVAL;
+ }
+ dev->pkt_size[dev->cc] = payload;
+ dev->jpg_size[dev->cc] = pdword[4];
+ break;
+ case S2255_MARKER_RESPONSE:
+ pdword = (s32 *)pdata;
+ pdata += DEF_USB_BLOCK;
+ jj += DEF_USB_BLOCK;
+ if (pdword[1] >= MAX_CHANNELS)
+ break;
+ cc = G_chnmap[pdword[1]];
+ if (!(cc >= 0 && cc < MAX_CHANNELS))
+ break;
+ switch (pdword[2]) {
+ case 0x01:
+ /* check if channel valid */
+ /* set mode ready */
+ dev->setmode_ready[cc] = 1;
+ wake_up(&dev->wait_setmode[cc]);
+ dprintk(5, "setmode ready %d\n", cc);
break;
+ case 0x10:
+
+ dev->chn_ready |= (1 << cc);
+ if ((dev->chn_ready & 0x0f) != 0x0f)
+ break;
+ /* all channels ready */
+ printk(KERN_INFO "s2255: fw loaded\n");
+ atomic_set(&dev->fw_data->fw_state,
+ S2255_FW_SUCCESS);
+ wake_up(&dev->fw_data->wait_fw);
+ break;
+ default:
+ printk(KERN_INFO "s2255 unknwn resp\n");
}
+ default:
pdata++;
+ break;
}
- if (bsync == 0)
- return -EINVAL;
- } else {
- u32 *pword;
- u32 payload;
- int cc;
- dbgsync = 0;
- bsync = 1;
- pword = (u32 *) pipe_info->transfer_buffer;
- cc = pword[1];
-
- if (cc >= MAX_CHANNELS) {
- printk("invalid channel found. "
- "throwing out data!\n");
- return -EINVAL;
- }
- dev->cc = G_chnmap[cc];
- payload = pword[2];
- if (payload != dev->req_image_size[dev->cc]) {
- dprintk(1, "[%d][%d]unexpected payload: %d"
- "required: %lu \n", cc, dev->cc,
- payload, dev->req_image_size[dev->cc]);
- dev->bad_payload[dev->cc]++;
- /* discard the bad frame */
- return -EINVAL;
- }
-
- }
- }
- /* search done. now find out if should be acquiring
- on this channel */
- if (!dev->b_acquire[dev->cc]) {
- frm->ulState = 0;
- return -EINVAL;
+ if (bframe)
+ break;
+ } /* for */
+ if (!bframe)
+ return -EINVAL;
}
+
idx = dev->cur_frame[dev->cc];
frm = &dev->buffer[dev->cc].frame[idx];
- if (frm->ulState == 0) {
- frm->ulState = 1;
- frm->cur_size = 0;
- } else if (frm->ulState == 2) {
- /* system frame ring buffer overrun */
- dprintk(2, "sys frame overrun. overwriting frame %d %d\n",
- dev->cc, idx);
- frm->ulState = 1;
- frm->cur_size = 0;
+ /* search done. now find out if should be acquiring on this channel */
+ if (!dev->b_acquire[dev->cc]) {
+ /* we found a frame, but this channel is turned off */
+ frm->ulState = S2255_READ_IDLE;
+ return -EINVAL;
}
- if (bsync) {
- /* skip the marker 512 bytes (and offset if out of sync) */
- psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE;
- } else {
- psrc = (u8 *)pipe_info->transfer_buffer;
+ if (frm->ulState == S2255_READ_IDLE) {
+ frm->ulState = S2255_READ_FRAME;
+ frm->cur_size = 0;
}
+ /* skip the marker 512 bytes (and offset if out of sync) */
+ psrc = (u8 *)pipe_info->transfer_buffer + offset;
+
+
if (frm->lpvbits == NULL) {
dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
frm, dev, dev->cc, idx);
@@ -1910,33 +1990,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
pdest = frm->lpvbits + frm->cur_size;
- if (bsync) {
- copy_size =
- (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE;
- if (copy_size > pipe_info->cur_transfer_size) {
- printk("invalid copy size, overflow!\n");
- return -ENOMEM;
- }
- } else {
- copy_size = pipe_info->cur_transfer_size;
- }
+ copy_size = (pipe_info->cur_transfer_size - offset);
- cur_size = frm->cur_size;
- size = dev->req_image_size[dev->cc];
+ size = dev->pkt_size[dev->cc] - PREFIX_SIZE;
- if ((copy_size + cur_size) > size) {
- copy_size = size - cur_size;
- btrunc = 1;
- }
+ /* sanity check on pdest */
+ if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc])
+ memcpy(pdest, psrc, copy_size);
- memcpy(pdest, psrc, copy_size);
- cur_size += copy_size;
frm->cur_size += copy_size;
- dprintk(50, "cur_size size %lu size %lu \n", cur_size, size);
+ dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size);
+
+ if (frm->cur_size >= size) {
- if (cur_size >= (size - PREFIX_SIZE)) {
u32 cc = dev->cc;
- frm->ulState = 2;
dprintk(2, "****************[%d]Buffer[%d]full*************\n",
cc, idx);
dev->last_frame[cc] = dev->cur_frame[cc];
@@ -1945,16 +2012,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
if ((dev->cur_frame[cc] == SYS_FRAMES) ||
(dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
dev->cur_frame[cc] = 0;
-
- /* signal the semaphore for this channel */
+ /* frame ready */
if (dev->b_acquire[cc])
- s2255_got_frame(dev, cc);
+ s2255_got_frame(dev, cc, dev->jpg_size[cc]);
dev->frame_count[cc]++;
- }
- /* frame was truncated */
- if (btrunc) {
- /* return more data to process */
- return EAGAIN;
+ frm->ulState = S2255_READ_IDLE;
+ frm->cur_size = 0;
+
}
/* done successfully */
return 0;
@@ -1973,8 +2037,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev,
}
/* otherwise copy to the system buffers */
res = save_frame(dev, pipe_info);
- if (res == EAGAIN)
- save_frame(dev, pipe_info);
+ if (res != 0)
+ dprintk(4, "s2255: read callback failed\n");
dprintk(50, "callback read video done\n");
return;
@@ -2094,11 +2158,9 @@ static int s2255_board_init(struct s2255_dev *dev)
memset(pipe, 0, sizeof(*pipe));
pipe->dev = dev;
- pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
- pipe->max_transfer_size = MAX_PIPE_USBBLOCK;
+ pipe->cur_transfer_size = S2255_USB_XFER_SIZE;
+ pipe->max_transfer_size = S2255_USB_XFER_SIZE;
- if (pipe->cur_transfer_size > pipe->max_transfer_size)
- pipe->cur_transfer_size = pipe->max_transfer_size;
pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
GFP_KERNEL);
if (pipe->transfer_buffer == NULL) {
@@ -2118,6 +2180,7 @@ static int s2255_board_init(struct s2255_dev *dev)
for (j = 0; j < MAX_CHANNELS; j++) {
dev->b_acquire[j] = 0;
dev->mode[j] = mode_def;
+ dev->jc[j].quality = S2255_DEF_JPEG_QUAL;
dev->cur_fmt[j] = &formats[0];
dev->mode[j].restart = 1;
dev->req_image_size[j] = get_transfer_size(&mode_def);
@@ -2322,7 +2385,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
kfree(buffer);
dev->b_acquire[chn] = 0;
- return 0;
+ return res;
}
static void s2255_stop_readpipe(struct s2255_dev *dev)
@@ -2358,8 +2421,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev)
return;
}
-static void s2255_fwload_start(struct s2255_dev *dev)
+static void s2255_fwload_start(struct s2255_dev *dev, int reset)
{
+ if (reset)
+ s2255_reset_dsppower(dev);
dev->fw_data->fw_size = dev->fw_data->fw->size;
atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
memcpy(dev->fw_data->pfw_data,
@@ -2382,6 +2447,8 @@ static int s2255_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *endpoint;
int i;
int retval = -ENOMEM;
+ __le32 *pdata;
+ int fw_size;
dprintk(2, "s2255: probe\n");
@@ -2436,6 +2503,8 @@ static int s2255_probe(struct usb_interface *interface,
dev->timer.data = (unsigned long)dev->fw_data;
init_waitqueue_head(&dev->fw_data->wait_fw);
+ for (i = 0; i < MAX_CHANNELS; i++)
+ init_waitqueue_head(&dev->wait_setmode[i]);
dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -2455,16 +2524,30 @@ static int s2255_probe(struct usb_interface *interface,
printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
goto error;
}
+ /* check the firmware is valid */
+ fw_size = dev->fw_data->fw->size;
+ pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
+ if (*pdata != S2255_FW_MARKER) {
+ printk(KERN_INFO "Firmware invalid.\n");
+ retval = -ENODEV;
+ goto error;
+ } else {
+ /* make sure firmware is the latest */
+ __le32 *pRel;
+ pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
+ printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
+ }
/* loads v4l specific */
s2255_probe_v4l(dev);
+ usb_reset_device(dev->udev);
/* load 2255 board specific */
s2255_board_init(dev);
dprintk(4, "before probe done %p\n", dev);
spin_lock_init(&dev->slock);
- s2255_fwload_start(dev);
+ s2255_fwload_start(dev, 0);
dev_info(&interface->dev, "Sensoray 2255 detected\n");
return 0;
error:
@@ -2475,14 +2558,30 @@ error:
static void s2255_disconnect(struct usb_interface *interface)
{
struct s2255_dev *dev = NULL;
+ int i;
dprintk(1, "s2255: disconnect interface %p\n", interface);
dev = usb_get_intfdata(interface);
+
+ /*
+ * wake up any of the timers to allow open_lock to be
+ * acquired sooner
+ */
+ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
+ wake_up(&dev->fw_data->wait_fw);
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ dev->setmode_ready[i] = 1;
+ wake_up(&dev->wait_setmode[i]);
+ }
+
+ mutex_lock(&dev->open_lock);
+ usb_set_intfdata(interface, NULL);
+ mutex_unlock(&dev->open_lock);
+
if (dev) {
kref_put(&dev->kref, s2255_destroy);
dprintk(1, "s2255drv: disconnect\n");
dev_info(&interface->dev, "s2255usb now disconnected\n");
}
- usb_set_intfdata(interface, NULL);
}
static struct usb_driver s2255_driver = {
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 6ee63e69b36..4a21b8a6a70 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -43,135 +43,363 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/videotext.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
-#include "saa5246a.h"
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver");
MODULE_LICENSE("GPL");
-struct saa5246a_device
-{
- u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
- int is_searching[NUM_DAUS];
- struct i2c_client *client;
- struct mutex lock;
-};
+#define MAJOR_VERSION 1 /* driver major version number */
+#define MINOR_VERSION 8 /* driver minor version number */
+
+/* Number of DAUs = number of pages that can be searched at the same time. */
+#define NUM_DAUS 4
+
+#define NUM_ROWS_PER_PAGE 40
+
+/* first column is 0 (not 1) */
+#define POS_TIME_START 32
+#define POS_TIME_END 39
+
+#define POS_HEADER_START 7
+#define POS_HEADER_END 31
+
+/* Returns 'true' if the part of the videotext page described with req contains
+ (at least parts of) the time field */
+#define REQ_CONTAINS_TIME(p_req) \
+ ((p_req)->start <= POS_TIME_END && \
+ (p_req)->end >= POS_TIME_START)
+
+/* Returns 'true' if the part of the videotext page described with req contains
+ (at least parts of) the page header */
+#define REQ_CONTAINS_HEADER(p_req) \
+ ((p_req)->start <= POS_HEADER_END && \
+ (p_req)->end >= POS_HEADER_START)
+
+/*****************************************************************************/
+/* Mode register numbers of the SAA5246A */
+/*****************************************************************************/
+#define SAA5246A_REGISTER_R0 0
+#define SAA5246A_REGISTER_R1 1
+#define SAA5246A_REGISTER_R2 2
+#define SAA5246A_REGISTER_R3 3
+#define SAA5246A_REGISTER_R4 4
+#define SAA5246A_REGISTER_R5 5
+#define SAA5246A_REGISTER_R6 6
+#define SAA5246A_REGISTER_R7 7
+#define SAA5246A_REGISTER_R8 8
+#define SAA5246A_REGISTER_R9 9
+#define SAA5246A_REGISTER_R10 10
+#define SAA5246A_REGISTER_R11 11
+#define SAA5246A_REGISTER_R11B 11
+
+/* SAA5246A mode registers often autoincrement to the next register.
+ Therefore we use variable argument lists. The following macro indicates
+ the end of a command list. */
+#define COMMAND_END (-1)
+
+/*****************************************************************************/
+/* Contents of the mode registers of the SAA5246A */
+/*****************************************************************************/
+/* Register R0 (Advanced Control) */
+#define R0_SELECT_R11 0x00
+#define R0_SELECT_R11B 0x01
+
+#define R0_PLL_TIME_CONSTANT_LONG 0x00
+#define R0_PLL_TIME_CONSTANT_SHORT 0x02
+
+#define R0_ENABLE_nODD_EVEN_OUTPUT 0x00
+#define R0_DISABLE_nODD_EVEN_OUTPUT 0x04
+
+#define R0_ENABLE_HDR_POLL 0x00
+#define R0_DISABLE_HDR_POLL 0x10
+
+#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00
+#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20
+
+#define R0_NO_FREE_RUN_PLL 0x00
+#define R0_FREE_RUN_PLL 0x40
+
+#define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00
+#define R0_AUTOMATIC_FASTEXT_PROMPT 0x80
+
+/* Register R1 (Mode) */
+#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00
+#define R1_NON_INTERLACED_312_313_LINES 0x01
+#define R1_NON_INTERLACED_312_312_LINES 0x02
+#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03
+#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07
+
+#define R1_DEW 0x00
+#define R1_FULL_FIELD 0x08
+
+#define R1_EXTENDED_PACKET_DISABLE 0x00
+#define R1_EXTENDED_PACKET_ENABLE 0x10
+
+#define R1_DAUS_ALL_ON 0x00
+#define R1_DAUS_ALL_OFF 0x20
+
+#define R1_7_BITS_PLUS_PARITY 0x00
+#define R1_8_BITS_NO_PARITY 0x40
+
+#define R1_VCS_TO_SCS 0x00
+#define R1_NO_VCS_TO_SCS 0x80
+
+/* Register R2 (Page request address) */
+#define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00
+#define R2_IN_R3_SELECT_PAGE_TENS 0x01
+#define R2_IN_R3_SELECT_PAGE_UNITS 0x02
+#define R2_IN_R3_SELECT_HOURS_TENS 0x03
+#define R2_IN_R3_SELECT_HOURS_UNITS 0x04
+#define R2_IN_R3_SELECT_MINUTES_TENS 0x05
+#define R2_IN_R3_SELECT_MINUTES_UNITS 0x06
+
+#define R2_DAU_0 0x00
+#define R2_DAU_1 0x10
+#define R2_DAU_2 0x20
+#define R2_DAU_3 0x30
+
+#define R2_BANK_0 0x00
+#define R2_BANK 1 0x40
+
+#define R2_HAMMING_CHECK_ON 0x80
+#define R2_HAMMING_CHECK_OFF 0x00
+
+/* Register R3 (Page request data) */
+#define R3_PAGE_HUNDREDS_0 0x00
+#define R3_PAGE_HUNDREDS_1 0x01
+#define R3_PAGE_HUNDREDS_2 0x02
+#define R3_PAGE_HUNDREDS_3 0x03
+#define R3_PAGE_HUNDREDS_4 0x04
+#define R3_PAGE_HUNDREDS_5 0x05
+#define R3_PAGE_HUNDREDS_6 0x06
+#define R3_PAGE_HUNDREDS_7 0x07
-static struct video_device saa_template; /* Declared near bottom */
+#define R3_HOLD_PAGE 0x00
+#define R3_UPDATE_PAGE 0x08
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END };
+#define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00
+#define R3_PAGE_HUNDREDS_DO_CARE 0x10
-I2C_CLIENT_INSMOD;
+#define R3_PAGE_TENS_DO_NOT_CARE 0x00
+#define R3_PAGE_TENS_DO_CARE 0x10
-static struct i2c_client client_template;
+#define R3_PAGE_UNITS_DO_NOT_CARE 0x00
+#define R3_PAGE_UNITS_DO_CARE 0x10
-static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- int pgbuf;
- int err;
- struct i2c_client *client;
- struct video_device *vd;
- struct saa5246a_device *t;
+#define R3_HOURS_TENS_DO_NOT_CARE 0x00
+#define R3_HOURS_TENS_DO_CARE 0x10
- printk(KERN_INFO "saa5246a: teletext chip found.\n");
- client=kmalloc(sizeof(*client), GFP_KERNEL);
- if(client==NULL)
- return -ENOMEM;
- client_template.adapter = adap;
- client_template.addr = addr;
- memcpy(client, &client_template, sizeof(*client));
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if(t==NULL)
- {
- kfree(client);
- return -ENOMEM;
- }
- strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
- mutex_init(&t->lock);
+#define R3_HOURS_UNITS_DO_NOT_CARE 0x00
+#define R3_HOURS_UNITS_DO_CARE 0x10
- /*
- * Now create a video4linux device
- */
+#define R3_MINUTES_TENS_DO_NOT_CARE 0x00
+#define R3_MINUTES_TENS_DO_CARE 0x10
- vd = video_device_alloc();
- if(vd==NULL)
- {
- kfree(t);
- kfree(client);
- return -ENOMEM;
- }
- i2c_set_clientdata(client, vd);
- memcpy(vd, &saa_template, sizeof(*vd));
+#define R3_MINUTES_UNITS_DO_NOT_CARE 0x00
+#define R3_MINUTES_UNITS_DO_CARE 0x10
- for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
- {
- memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
- t->is_searching[pgbuf] = false;
- }
- vd->priv=t;
+/* Register R4 (Display chapter) */
+#define R4_DISPLAY_PAGE_0 0x00
+#define R4_DISPLAY_PAGE_1 0x01
+#define R4_DISPLAY_PAGE_2 0x02
+#define R4_DISPLAY_PAGE_3 0x03
+#define R4_DISPLAY_PAGE_4 0x04
+#define R4_DISPLAY_PAGE_5 0x05
+#define R4_DISPLAY_PAGE_6 0x06
+#define R4_DISPLAY_PAGE_7 0x07
+/* Register R5 (Normal display control) */
+#define R5_PICTURE_INSIDE_BOXING_OFF 0x00
+#define R5_PICTURE_INSIDE_BOXING_ON 0x01
- /*
- * Register it
- */
+#define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00
+#define R5_PICTURE_OUTSIDE_BOXING_ON 0x02
- if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
- {
- kfree(t);
- kfree(client);
- video_device_release(vd);
- return err;
- }
- t->client = client;
- i2c_attach_client(client);
- return 0;
-}
+#define R5_TEXT_INSIDE_BOXING_OFF 0x00
+#define R5_TEXT_INSIDE_BOXING_ON 0x04
-/*
- * We do most of the hard work when we become a device on the i2c.
- */
-static int saa5246a_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, saa5246a_attach);
- return 0;
-}
+#define R5_TEXT_OUTSIDE_BOXING_OFF 0x00
+#define R5_TEXT_OUTSIDE_BOXING_ON 0x08
-static int saa5246a_detach(struct i2c_client *client)
-{
- struct video_device *vd = i2c_get_clientdata(client);
- i2c_detach_client(client);
- video_unregister_device(vd);
- kfree(vd->priv);
- kfree(client);
- return 0;
-}
+#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00
+#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10
-/*
- * I2C interfaces
- */
+#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
+#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20
+
+#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00
+#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40
+
+#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00
+#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80
+
+/* Register R6 (Newsflash display) */
+#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01
+
+#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02
+
+#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04
+
+#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08
+
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10
+
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20
+
+#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40
+
+#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80
+
+/* Register R7 (Display mode) */
+#define R7_BOX_OFF_ROW_0 0x00
+#define R7_BOX_ON_ROW_0 0x01
+
+#define R7_BOX_OFF_ROW_1_TO_23 0x00
+#define R7_BOX_ON_ROW_1_TO_23 0x02
+
+#define R7_BOX_OFF_ROW_24 0x00
+#define R7_BOX_ON_ROW_24 0x04
+
+#define R7_SINGLE_HEIGHT 0x00
+#define R7_DOUBLE_HEIGHT 0x08
+
+#define R7_TOP_HALF 0x00
+#define R7_BOTTOM_HALF 0x10
+
+#define R7_REVEAL_OFF 0x00
+#define R7_REVEAL_ON 0x20
+
+#define R7_CURSER_OFF 0x00
+#define R7_CURSER_ON 0x40
+
+#define R7_STATUS_BOTTOM 0x00
+#define R7_STATUS_TOP 0x80
+
+/* Register R8 (Active chapter) */
+#define R8_ACTIVE_CHAPTER_0 0x00
+#define R8_ACTIVE_CHAPTER_1 0x01
+#define R8_ACTIVE_CHAPTER_2 0x02
+#define R8_ACTIVE_CHAPTER_3 0x03
+#define R8_ACTIVE_CHAPTER_4 0x04
+#define R8_ACTIVE_CHAPTER_5 0x05
+#define R8_ACTIVE_CHAPTER_6 0x06
+#define R8_ACTIVE_CHAPTER_7 0x07
+
+#define R8_CLEAR_MEMORY 0x08
+#define R8_DO_NOT_CLEAR_MEMORY 0x00
+
+/* Register R9 (Curser row) */
+#define R9_CURSER_ROW_0 0x00
+#define R9_CURSER_ROW_1 0x01
+#define R9_CURSER_ROW_2 0x02
+#define R9_CURSER_ROW_25 0x19
+
+/* Register R10 (Curser column) */
+#define R10_CURSER_COLUMN_0 0x00
+#define R10_CURSER_COLUMN_6 0x06
+#define R10_CURSER_COLUMN_8 0x08
+
+/*****************************************************************************/
+/* Row 25 control data in column 0 to 9 */
+/*****************************************************************************/
+#define ROW25_COLUMN0_PAGE_UNITS 0x0F
+
+#define ROW25_COLUMN1_PAGE_TENS 0x0F
+
+#define ROW25_COLUMN2_MINUTES_UNITS 0x0F
-static struct i2c_driver i2c_driver_videotext =
+#define ROW25_COLUMN3_MINUTES_TENS 0x07
+#define ROW25_COLUMN3_DELETE_PAGE 0x08
+
+#define ROW25_COLUMN4_HOUR_UNITS 0x0F
+
+#define ROW25_COLUMN5_HOUR_TENS 0x03
+#define ROW25_COLUMN5_INSERT_HEADLINE 0x04
+#define ROW25_COLUMN5_INSERT_SUBTITLE 0x08
+
+#define ROW25_COLUMN6_SUPPRESS_HEADER 0x01
+#define ROW25_COLUMN6_UPDATE_PAGE 0x02
+#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04
+#define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08
+
+#define ROW25_COLUMN7_SERIAL_MODE 0x01
+#define ROW25_COLUMN7_CHARACTER_SET 0x0E
+
+#define ROW25_COLUMN8_PAGE_HUNDREDS 0x07
+#define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10
+
+#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20
+
+#define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10
+
+/*****************************************************************************/
+/* Helper macros for extracting page, hour and minute digits */
+/*****************************************************************************/
+/* BYTE_POS 0 is at row 0, column 0,
+ BYTE_POS 1 is at row 0, column 1,
+ BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40)
+ BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40),
+ ... */
+#define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE)
+#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE)
+
+/*****************************************************************************/
+/* Helper macros for extracting page, hour and minute digits */
+/*****************************************************************************/
+/* Macros for extracting hundreds, tens and units of a page number which
+ must be in the range 0 ... 0x799.
+ Note that page is coded in hexadecimal, i.e. 0x123 means page 123.
+ page 0x.. means page 8.. */
+#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7)
+#define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF)
+#define UNITS_OF_PAGE(page) ((page) & 0xF)
+
+/* Macros for extracting tens and units of a hour information which
+ must be in the range 0 ... 0x24.
+ Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */
+#define TENS_OF_HOUR(hour) ((hour) / 0x10)
+#define UNITS_OF_HOUR(hour) ((hour) & 0xF)
+
+/* Macros for extracting tens and units of a minute information which
+ must be in the range 0 ... 0x59.
+ Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */
+#define TENS_OF_MINUTE(minute) ((minute) / 0x10)
+#define UNITS_OF_MINUTE(minute) ((minute) & 0xF)
+
+#define HOUR_MAX 0x23
+#define MINUTE_MAX 0x59
+#define PAGE_MAX 0x8FF
+
+
+struct saa5246a_device
{
- .driver = {
- .name = IF_NAME, /* name */
- },
- .id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .attach_adapter = saa5246a_probe,
- .detach_client = saa5246a_detach,
+ u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
+ int is_searching[NUM_DAUS];
+ struct i2c_client *client;
+ unsigned long in_use;
+ struct mutex lock;
};
-static struct i2c_client client_template = {
- .driver = &i2c_driver_videotext,
- .name = "(unset)",
-};
+static struct video_device saa_template; /* Declared near bottom */
+
+/*
+ * I2C interfaces
+ */
static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data)
{
@@ -579,8 +807,8 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
static int do_saa5246a_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
- struct video_device *vd = video_devdata(file);
- struct saa5246a_device *t=vd->priv;
+ struct saa5246a_device *t = video_drvdata(file);
+
switch(cmd)
{
case VTXIOCGETINFO:
@@ -720,8 +948,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
static int saa5246a_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct video_device *vd = video_devdata(file);
- struct saa5246a_device *t = vd->priv;
+ struct saa5246a_device *t = video_drvdata(file);
int err;
cmd = vtx_fix_command(cmd);
@@ -733,21 +960,15 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file,
static int saa5246a_open(struct inode *inode, struct file *file)
{
- struct video_device *vd = video_devdata(file);
- struct saa5246a_device *t = vd->priv;
- int err;
+ struct saa5246a_device *t = video_drvdata(file);
- err = video_exclusive_open(inode,file);
- if (err < 0)
- return err;
+ if (t->client == NULL)
+ return -ENODEV;
- if (t->client==NULL) {
- err = -ENODEV;
- goto fail;
- }
+ if (test_and_set_bit(0, &t->in_use))
+ return -EBUSY;
if (i2c_senddata(t, SAA5246A_REGISTER_R0,
-
R0_SELECT_R11 |
R0_PLL_TIME_CONSTANT_LONG |
R0_ENABLE_nODD_EVEN_OUTPUT |
@@ -773,21 +994,15 @@ static int saa5246a_open(struct inode *inode, struct file *file)
COMMAND_END))
{
- err = -EIO;
- goto fail;
+ clear_bit(0, &t->in_use);
+ return -EIO;
}
-
return 0;
-
-fail:
- video_exclusive_release(inode,file);
- return err;
}
static int saa5246a_release(struct inode *inode, struct file *file)
{
- struct video_device *vd = video_devdata(file);
- struct saa5246a_device *t = vd->priv;
+ struct saa5246a_device *t = video_drvdata(file);
/* Stop all acquisition circuits. */
i2c_senddata(t, SAA5246A_REGISTER_R1,
@@ -800,26 +1015,10 @@ static int saa5246a_release(struct inode *inode, struct file *file)
R1_VCS_TO_SCS,
COMMAND_END);
- video_exclusive_release(inode,file);
+ clear_bit(0, &t->in_use);
return 0;
}
-static int __init init_saa_5246a (void)
-{
- printk(KERN_INFO
- "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n",
- MAJOR_VERSION, MINOR_VERSION);
- return i2c_add_driver(&i2c_driver_videotext);
-}
-
-static void __exit cleanup_saa_5246a (void)
-{
- i2c_del_driver(&i2c_driver_videotext);
-}
-
-module_init(init_saa_5246a);
-module_exit(cleanup_saa_5246a);
-
static const struct file_operations saa_fops = {
.owner = THIS_MODULE,
.open = saa5246a_open,
@@ -830,8 +1029,79 @@ static const struct file_operations saa_fops = {
static struct video_device saa_template =
{
- .name = IF_NAME,
+ .name = "saa5246a",
.fops = &saa_fops,
.release = video_device_release,
.minor = -1,
};
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int saa5246a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int pgbuf;
+ int err;
+ struct video_device *vd;
+ struct saa5246a_device *t;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+ v4l_info(client, "VideoText version %d.%d\n",
+ MAJOR_VERSION, MINOR_VERSION);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL)
+ return -ENOMEM;
+ mutex_init(&t->lock);
+
+ /* Now create a video4linux device */
+ vd = video_device_alloc();
+ if (vd == NULL) {
+ kfree(t);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, vd);
+ memcpy(vd, &saa_template, sizeof(*vd));
+
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
+ memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
+ t->is_searching[pgbuf] = false;
+ }
+ video_set_drvdata(vd, t);
+
+ /* Register it */
+ err = video_register_device(vd, VFL_TYPE_VTX, -1);
+ if (err < 0) {
+ kfree(t);
+ video_device_release(vd);
+ return err;
+ }
+ t->client = client;
+ return 0;
+}
+
+static int saa5246a_remove(struct i2c_client *client)
+{
+ struct video_device *vd = i2c_get_clientdata(client);
+
+ video_unregister_device(vd);
+ kfree(video_get_drvdata(vd));
+ return 0;
+}
+
+static const struct i2c_device_id saa5246a_id[] = {
+ { "saa5246a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa5246a_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa5246a",
+ .driverid = I2C_DRIVERID_SAA5249,
+ .probe = saa5246a_probe,
+ .remove = saa5246a_remove,
+ .id_table = saa5246a_id,
+};
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h
deleted file mode 100644
index 64394c036c6..00000000000
--- a/drivers/media/video/saa5246a.h
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from
- Philips.
-
- Copyright (C) 2004 Michael Geng (linux@MichaelGeng.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-#ifndef __SAA5246A_H__
-#define __SAA5246A_H__
-
-#define MAJOR_VERSION 1 /* driver major version number */
-#define MINOR_VERSION 8 /* driver minor version number */
-
-#define IF_NAME "SAA5246A"
-
-#define I2C_ADDRESS 17
-
-/* Number of DAUs = number of pages that can be searched at the same time. */
-#define NUM_DAUS 4
-
-#define NUM_ROWS_PER_PAGE 40
-
-/* first column is 0 (not 1) */
-#define POS_TIME_START 32
-#define POS_TIME_END 39
-
-#define POS_HEADER_START 7
-#define POS_HEADER_END 31
-
-/* Returns 'true' if the part of the videotext page described with req contains
- (at least parts of) the time field */
-#define REQ_CONTAINS_TIME(p_req) \
- ((p_req)->start <= POS_TIME_END && \
- (p_req)->end >= POS_TIME_START)
-
-/* Returns 'true' if the part of the videotext page described with req contains
- (at least parts of) the page header */
-#define REQ_CONTAINS_HEADER(p_req) \
- ((p_req)->start <= POS_HEADER_END && \
- (p_req)->end >= POS_HEADER_START)
-
-/*****************************************************************************/
-/* Mode register numbers of the SAA5246A */
-/*****************************************************************************/
-#define SAA5246A_REGISTER_R0 0
-#define SAA5246A_REGISTER_R1 1
-#define SAA5246A_REGISTER_R2 2
-#define SAA5246A_REGISTER_R3 3
-#define SAA5246A_REGISTER_R4 4
-#define SAA5246A_REGISTER_R5 5
-#define SAA5246A_REGISTER_R6 6
-#define SAA5246A_REGISTER_R7 7
-#define SAA5246A_REGISTER_R8 8
-#define SAA5246A_REGISTER_R9 9
-#define SAA5246A_REGISTER_R10 10
-#define SAA5246A_REGISTER_R11 11
-#define SAA5246A_REGISTER_R11B 11
-
-/* SAA5246A mode registers often autoincrement to the next register.
- Therefore we use variable argument lists. The following macro indicates
- the end of a command list. */
-#define COMMAND_END (- 1)
-
-/*****************************************************************************/
-/* Contents of the mode registers of the SAA5246A */
-/*****************************************************************************/
-/* Register R0 (Advanced Control) */
-#define R0_SELECT_R11 0x00
-#define R0_SELECT_R11B 0x01
-
-#define R0_PLL_TIME_CONSTANT_LONG 0x00
-#define R0_PLL_TIME_CONSTANT_SHORT 0x02
-
-#define R0_ENABLE_nODD_EVEN_OUTPUT 0x00
-#define R0_DISABLE_nODD_EVEN_OUTPUT 0x04
-
-#define R0_ENABLE_HDR_POLL 0x00
-#define R0_DISABLE_HDR_POLL 0x10
-
-#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00
-#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20
-
-#define R0_NO_FREE_RUN_PLL 0x00
-#define R0_FREE_RUN_PLL 0x40
-
-#define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00
-#define R0_AUTOMATIC_FASTEXT_PROMPT 0x80
-
-/* Register R1 (Mode) */
-#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00
-#define R1_NON_INTERLACED_312_313_LINES 0x01
-#define R1_NON_INTERLACED_312_312_LINES 0x02
-#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03
-#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07
-
-#define R1_DEW 0x00
-#define R1_FULL_FIELD 0x08
-
-#define R1_EXTENDED_PACKET_DISABLE 0x00
-#define R1_EXTENDED_PACKET_ENABLE 0x10
-
-#define R1_DAUS_ALL_ON 0x00
-#define R1_DAUS_ALL_OFF 0x20
-
-#define R1_7_BITS_PLUS_PARITY 0x00
-#define R1_8_BITS_NO_PARITY 0x40
-
-#define R1_VCS_TO_SCS 0x00
-#define R1_NO_VCS_TO_SCS 0x80
-
-/* Register R2 (Page request address) */
-#define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00
-#define R2_IN_R3_SELECT_PAGE_TENS 0x01
-#define R2_IN_R3_SELECT_PAGE_UNITS 0x02
-#define R2_IN_R3_SELECT_HOURS_TENS 0x03
-#define R2_IN_R3_SELECT_HOURS_UNITS 0x04
-#define R2_IN_R3_SELECT_MINUTES_TENS 0x05
-#define R2_IN_R3_SELECT_MINUTES_UNITS 0x06
-
-#define R2_DAU_0 0x00
-#define R2_DAU_1 0x10
-#define R2_DAU_2 0x20
-#define R2_DAU_3 0x30
-
-#define R2_BANK_0 0x00
-#define R2_BANK 1 0x40
-
-#define R2_HAMMING_CHECK_ON 0x80
-#define R2_HAMMING_CHECK_OFF 0x00
-
-/* Register R3 (Page request data) */
-#define R3_PAGE_HUNDREDS_0 0x00
-#define R3_PAGE_HUNDREDS_1 0x01
-#define R3_PAGE_HUNDREDS_2 0x02
-#define R3_PAGE_HUNDREDS_3 0x03
-#define R3_PAGE_HUNDREDS_4 0x04
-#define R3_PAGE_HUNDREDS_5 0x05
-#define R3_PAGE_HUNDREDS_6 0x06
-#define R3_PAGE_HUNDREDS_7 0x07
-
-#define R3_HOLD_PAGE 0x00
-#define R3_UPDATE_PAGE 0x08
-
-#define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00
-#define R3_PAGE_HUNDREDS_DO_CARE 0x10
-
-#define R3_PAGE_TENS_DO_NOT_CARE 0x00
-#define R3_PAGE_TENS_DO_CARE 0x10
-
-#define R3_PAGE_UNITS_DO_NOT_CARE 0x00
-#define R3_PAGE_UNITS_DO_CARE 0x10
-
-#define R3_HOURS_TENS_DO_NOT_CARE 0x00
-#define R3_HOURS_TENS_DO_CARE 0x10
-
-#define R3_HOURS_UNITS_DO_NOT_CARE 0x00
-#define R3_HOURS_UNITS_DO_CARE 0x10
-
-#define R3_MINUTES_TENS_DO_NOT_CARE 0x00
-#define R3_MINUTES_TENS_DO_CARE 0x10
-
-#define R3_MINUTES_UNITS_DO_NOT_CARE 0x00
-#define R3_MINUTES_UNITS_DO_CARE 0x10
-
-/* Register R4 (Display chapter) */
-#define R4_DISPLAY_PAGE_0 0x00
-#define R4_DISPLAY_PAGE_1 0x01
-#define R4_DISPLAY_PAGE_2 0x02
-#define R4_DISPLAY_PAGE_3 0x03
-#define R4_DISPLAY_PAGE_4 0x04
-#define R4_DISPLAY_PAGE_5 0x05
-#define R4_DISPLAY_PAGE_6 0x06
-#define R4_DISPLAY_PAGE_7 0x07
-
-/* Register R5 (Normal display control) */
-#define R5_PICTURE_INSIDE_BOXING_OFF 0x00
-#define R5_PICTURE_INSIDE_BOXING_ON 0x01
-
-#define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00
-#define R5_PICTURE_OUTSIDE_BOXING_ON 0x02
-
-#define R5_TEXT_INSIDE_BOXING_OFF 0x00
-#define R5_TEXT_INSIDE_BOXING_ON 0x04
-
-#define R5_TEXT_OUTSIDE_BOXING_OFF 0x00
-#define R5_TEXT_OUTSIDE_BOXING_ON 0x08
-
-#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00
-#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10
-
-#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
-#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20
-
-#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00
-#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40
-
-#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00
-#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80
-
-/* Register R6 (Newsflash display) */
-#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01
-
-#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02
-
-#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04
-
-#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08
-
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10
-
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20
-
-#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40
-
-#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80
-
-/* Register R7 (Display mode) */
-#define R7_BOX_OFF_ROW_0 0x00
-#define R7_BOX_ON_ROW_0 0x01
-
-#define R7_BOX_OFF_ROW_1_TO_23 0x00
-#define R7_BOX_ON_ROW_1_TO_23 0x02
-
-#define R7_BOX_OFF_ROW_24 0x00
-#define R7_BOX_ON_ROW_24 0x04
-
-#define R7_SINGLE_HEIGHT 0x00
-#define R7_DOUBLE_HEIGHT 0x08
-
-#define R7_TOP_HALF 0x00
-#define R7_BOTTOM_HALF 0x10
-
-#define R7_REVEAL_OFF 0x00
-#define R7_REVEAL_ON 0x20
-
-#define R7_CURSER_OFF 0x00
-#define R7_CURSER_ON 0x40
-
-#define R7_STATUS_BOTTOM 0x00
-#define R7_STATUS_TOP 0x80
-
-/* Register R8 (Active chapter) */
-#define R8_ACTIVE_CHAPTER_0 0x00
-#define R8_ACTIVE_CHAPTER_1 0x01
-#define R8_ACTIVE_CHAPTER_2 0x02
-#define R8_ACTIVE_CHAPTER_3 0x03
-#define R8_ACTIVE_CHAPTER_4 0x04
-#define R8_ACTIVE_CHAPTER_5 0x05
-#define R8_ACTIVE_CHAPTER_6 0x06
-#define R8_ACTIVE_CHAPTER_7 0x07
-
-#define R8_CLEAR_MEMORY 0x08
-#define R8_DO_NOT_CLEAR_MEMORY 0x00
-
-/* Register R9 (Curser row) */
-#define R9_CURSER_ROW_0 0x00
-#define R9_CURSER_ROW_1 0x01
-#define R9_CURSER_ROW_2 0x02
-#define R9_CURSER_ROW_25 0x19
-
-/* Register R10 (Curser column) */
-#define R10_CURSER_COLUMN_0 0x00
-#define R10_CURSER_COLUMN_6 0x06
-#define R10_CURSER_COLUMN_8 0x08
-
-/*****************************************************************************/
-/* Row 25 control data in column 0 to 9 */
-/*****************************************************************************/
-#define ROW25_COLUMN0_PAGE_UNITS 0x0F
-
-#define ROW25_COLUMN1_PAGE_TENS 0x0F
-
-#define ROW25_COLUMN2_MINUTES_UNITS 0x0F
-
-#define ROW25_COLUMN3_MINUTES_TENS 0x07
-#define ROW25_COLUMN3_DELETE_PAGE 0x08
-
-#define ROW25_COLUMN4_HOUR_UNITS 0x0F
-
-#define ROW25_COLUMN5_HOUR_TENS 0x03
-#define ROW25_COLUMN5_INSERT_HEADLINE 0x04
-#define ROW25_COLUMN5_INSERT_SUBTITLE 0x08
-
-#define ROW25_COLUMN6_SUPPRESS_HEADER 0x01
-#define ROW25_COLUMN6_UPDATE_PAGE 0x02
-#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04
-#define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08
-
-#define ROW25_COLUMN7_SERIAL_MODE 0x01
-#define ROW25_COLUMN7_CHARACTER_SET 0x0E
-
-#define ROW25_COLUMN8_PAGE_HUNDREDS 0x07
-#define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10
-
-#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20
-
-#define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10
-
-/*****************************************************************************/
-/* Helper macros for extracting page, hour and minute digits */
-/*****************************************************************************/
-/* BYTE_POS 0 is at row 0, column 0,
- BYTE_POS 1 is at row 0, column 1,
- BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40)
- BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40),
- ... */
-#define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE)
-#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE)
-
-/*****************************************************************************/
-/* Helper macros for extracting page, hour and minute digits */
-/*****************************************************************************/
-/* Macros for extracting hundreds, tens and units of a page number which
- must be in the range 0 ... 0x799.
- Note that page is coded in hexadecimal, i.e. 0x123 means page 123.
- page 0x.. means page 8.. */
-#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7)
-#define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF)
-#define UNITS_OF_PAGE(page) ((page) & 0xF)
-
-/* Macros for extracting tens and units of a hour information which
- must be in the range 0 ... 0x24.
- Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */
-#define TENS_OF_HOUR(hour) ((hour) / 0x10)
-#define UNITS_OF_HOUR(hour) ((hour) & 0xF)
-
-/* Macros for extracting tens and units of a minute information which
- must be in the range 0 ... 0x59.
- Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */
-#define TENS_OF_MINUTE(minute) ((minute) / 0x10)
-#define UNITS_OF_MINUTE(minute) ((minute) & 0xF)
-
-#define HOUR_MAX 0x23
-#define MINUTE_MAX 0x59
-#define PAGE_MAX 0x8FF
-
-#endif /* __SAA5246A_H__ */
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 0d639738d4e..3bb959c25d9 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -15,8 +15,6 @@
*
* Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de>
*
- * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $
- *
* Derived From
*
* vtx.c:
@@ -45,33 +43,28 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
#include <linux/init.h>
-#include <stdarg.h>
#include <linux/i2c.h>
+#include <linux/smp_lock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
#include <linux/videotext.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
+#include <media/v4l2-i2c-drv-legacy.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
+MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver");
+MODULE_LICENSE("GPL");
#define VTX_VER_MAJ 1
#define VTX_VER_MIN 8
-
#define NUM_DAUS 4
#define NUM_BUFS 8
-#define IF_NAME "SAA5249"
static const int disp_modes[8][3] =
{
@@ -109,6 +102,7 @@ struct saa5249_device
int disp_mode;
int virtual_mode;
struct i2c_client *client;
+ unsigned long in_use;
struct mutex lock;
};
@@ -123,125 +117,8 @@ struct saa5249_device
#define VTX_DEV_MINOR 0
-/* General defines and debugging support */
-
-#define RESCHED do { cond_resched(); } while(0)
-
static struct video_device saa_template; /* Declared near bottom */
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
-
-I2C_CLIENT_INSMOD;
-
-static struct i2c_client client_template;
-
-static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- int pgbuf;
- int err;
- struct i2c_client *client;
- struct video_device *vd;
- struct saa5249_device *t;
-
- printk(KERN_INFO "saa5249: teletext chip found.\n");
- client=kmalloc(sizeof(*client), GFP_KERNEL);
- if(client==NULL)
- return -ENOMEM;
- client_template.adapter = adap;
- client_template.addr = addr;
- memcpy(client, &client_template, sizeof(*client));
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if(t==NULL)
- {
- kfree(client);
- return -ENOMEM;
- }
- strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
- mutex_init(&t->lock);
-
- /*
- * Now create a video4linux device
- */
-
- vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
- if(vd==NULL)
- {
- kfree(t);
- kfree(client);
- return -ENOMEM;
- }
- i2c_set_clientdata(client, vd);
- memcpy(vd, &saa_template, sizeof(*vd));
-
- for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
- {
- memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
- memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
- memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
- t->vdau[pgbuf].expire = 0;
- t->vdau[pgbuf].clrfound = true;
- t->vdau[pgbuf].stopped = true;
- t->is_searching[pgbuf] = false;
- }
- vd->priv=t;
-
-
- /*
- * Register it
- */
-
- if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
- {
- kfree(t);
- kfree(vd);
- kfree(client);
- return err;
- }
- t->client = client;
- i2c_attach_client(client);
- return 0;
-}
-
-/*
- * We do most of the hard work when we become a device on the i2c.
- */
-
-static int saa5249_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, saa5249_attach);
- return 0;
-}
-
-static int saa5249_detach(struct i2c_client *client)
-{
- struct video_device *vd = i2c_get_clientdata(client);
- i2c_detach_client(client);
- video_unregister_device(vd);
- kfree(vd->priv);
- kfree(vd);
- kfree(client);
- return 0;
-}
-
-/* new I2C driver support */
-
-static struct i2c_driver i2c_driver_videotext =
-{
- .driver = {
- .name = IF_NAME, /* name */
- },
- .id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .attach_adapter = saa5249_probe,
- .detach_client = saa5249_detach,
-};
-
-static struct i2c_client client_template = {
- .driver = &i2c_driver_videotext,
- .name = "(unset)",
-};
-
/*
* Wait the given number of jiffies (10ms). This calls the scheduler, so the actual
* delay may be longer.
@@ -275,7 +152,7 @@ static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
buf[0] = reg;
memcpy(buf+1, data, count);
- if(i2c_master_send(t->client, buf, count+1)==count+1)
+ if (i2c_master_send(t->client, buf, count + 1) == count + 1)
return 0;
return -1;
}
@@ -317,246 +194,236 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
static int virtual_mode = false;
- struct video_device *vd = video_devdata(file);
- struct saa5249_device *t=vd->priv;
+ struct saa5249_device *t = video_drvdata(file);
- switch(cmd)
+ switch (cmd) {
+ case VTXIOCGETINFO:
{
- case VTXIOCGETINFO:
- {
- vtx_info_t *info = arg;
- info->version_major = VTX_VER_MAJ;
- info->version_minor = VTX_VER_MIN;
- info->numpages = NUM_DAUS;
- /*info->cct_type = CCT_TYPE;*/
- return 0;
- }
+ vtx_info_t *info = arg;
+ info->version_major = VTX_VER_MAJ;
+ info->version_minor = VTX_VER_MIN;
+ info->numpages = NUM_DAUS;
+ /*info->cct_type = CCT_TYPE;*/
+ return 0;
+ }
- case VTXIOCCLRPAGE:
- {
- vtx_pagereq_t *req = arg;
+ case VTXIOCCLRPAGE:
+ {
+ vtx_pagereq_t *req = arg;
- if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
- return -EINVAL;
- memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
- t->vdau[req->pgbuf].clrfound = true;
- return 0;
- }
+ if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+ return -EINVAL;
+ memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
+ t->vdau[req->pgbuf].clrfound = true;
+ return 0;
+ }
- case VTXIOCCLRFOUND:
- {
- vtx_pagereq_t *req = arg;
+ case VTXIOCCLRFOUND:
+ {
+ vtx_pagereq_t *req = arg;
- if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
- return -EINVAL;
- t->vdau[req->pgbuf].clrfound = true;
- return 0;
- }
+ if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+ return -EINVAL;
+ t->vdau[req->pgbuf].clrfound = true;
+ return 0;
+ }
- case VTXIOCPAGEREQ:
- {
- vtx_pagereq_t *req = arg;
- if (!(req->pagemask & PGMASK_PAGE))
- req->page = 0;
- if (!(req->pagemask & PGMASK_HOUR))
- req->hour = 0;
- if (!(req->pagemask & PGMASK_MINUTE))
- req->minute = 0;
- if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */
- return -EINVAL;
- req->page &= 0x7ff;
- if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f ||
- req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
- return -EINVAL;
- t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100);
- t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf);
- t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf);
- t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10);
- t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
- t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
- t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
- t->vdau[req->pgbuf].stopped = false;
- t->vdau[req->pgbuf].clrfound = true;
- t->is_searching[req->pgbuf] = true;
- return 0;
- }
+ case VTXIOCPAGEREQ:
+ {
+ vtx_pagereq_t *req = arg;
+ if (!(req->pagemask & PGMASK_PAGE))
+ req->page = 0;
+ if (!(req->pagemask & PGMASK_HOUR))
+ req->hour = 0;
+ if (!(req->pagemask & PGMASK_MINUTE))
+ req->minute = 0;
+ if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */
+ return -EINVAL;
+ req->page &= 0x7ff;
+ if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f ||
+ req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+ return -EINVAL;
+ t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100);
+ t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf);
+ t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf);
+ t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10);
+ t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
+ t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
+ t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
+ t->vdau[req->pgbuf].stopped = false;
+ t->vdau[req->pgbuf].clrfound = true;
+ t->is_searching[req->pgbuf] = true;
+ return 0;
+ }
- case VTXIOCGETSTAT:
- {
- vtx_pagereq_t *req = arg;
- u8 infobits[10];
- vtx_pageinfo_t info;
- int a;
-
- if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
- return -EINVAL;
- if (!t->vdau[req->pgbuf].stopped)
- {
- if (i2c_senddata(t, 2, 0, -1) ||
- i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
- i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
- i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) ||
- i2c_senddata(t, 8, 0, 25, 0, -1))
- return -EIO;
- jdelay(PAGE_WAIT);
- if (i2c_getdata(t, 10, infobits))
- return -EIO;
+ case VTXIOCGETSTAT:
+ {
+ vtx_pagereq_t *req = arg;
+ u8 infobits[10];
+ vtx_pageinfo_t info;
+ int a;
+
+ if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+ return -EINVAL;
+ if (!t->vdau[req->pgbuf].stopped) {
+ if (i2c_senddata(t, 2, 0, -1) ||
+ i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
+ i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
+ i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) ||
+ i2c_senddata(t, 8, 0, 25, 0, -1))
+ return -EIO;
+ jdelay(PAGE_WAIT);
+ if (i2c_getdata(t, 10, infobits))
+ return -EIO;
- if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
- (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
- time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
- { /* check if new page arrived */
- if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
- i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf))
+ if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
+ (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
+ time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
+ { /* check if new page arrived */
+ if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
+ i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf))
+ return -EIO;
+ t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
+ memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
+ if (t->virtual_mode) {
+ /* Packet X/24 */
+ if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
+ i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40))
+ return -EIO;
+ /* Packet X/27/0 */
+ if (i2c_senddata(t, 8, 0, 0x21, 0, -1) ||
+ i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40))
+ return -EIO;
+ /* Packet 8/30/0...8/30/15
+ * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
+ * so we should undo this here.
+ */
+ if (i2c_senddata(t, 8, 0, 0x22, 0, -1) ||
+ i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
return -EIO;
- t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
- memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
- if (t->virtual_mode)
- {
- /* Packet X/24 */
- if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
- i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40))
- return -EIO;
- /* Packet X/27/0 */
- if (i2c_senddata(t, 8, 0, 0x21, 0, -1) ||
- i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40))
- return -EIO;
- /* Packet 8/30/0...8/30/15
- * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
- * so we should undo this here.
- */
- if (i2c_senddata(t, 8, 0, 0x22, 0, -1) ||
- i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
- return -EIO;
- }
- t->vdau[req->pgbuf].clrfound = false;
- memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
- }
- else
- {
- memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
}
- }
- else
- {
+ t->vdau[req->pgbuf].clrfound = false;
+ memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
+ } else {
memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
}
+ } else {
+ memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
+ }
- info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f);
- if (info.pagenum < 0x100)
- info.pagenum += 0x800;
- info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
- info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
- info.charset = ((infobits[7] >> 1) & 7);
- info.delete = !!(infobits[3] & 8);
- info.headline = !!(infobits[5] & 4);
- info.subtitle = !!(infobits[5] & 8);
- info.supp_header = !!(infobits[6] & 1);
- info.update = !!(infobits[6] & 2);
- info.inter_seq = !!(infobits[6] & 4);
- info.dis_disp = !!(infobits[6] & 8);
- info.serial = !!(infobits[7] & 1);
- info.notfound = !!(infobits[8] & 0x10);
- info.pblf = !!(infobits[9] & 0x20);
- info.hamming = 0;
- for (a = 0; a <= 7; a++)
- {
- if (infobits[a] & 0xf0)
- {
- info.hamming = 1;
- break;
- }
- }
- if (t->vdau[req->pgbuf].clrfound)
- info.notfound = 1;
- if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
- return -EFAULT;
- if (!info.hamming && !info.notfound)
- {
- t->is_searching[req->pgbuf] = false;
+ info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f);
+ if (info.pagenum < 0x100)
+ info.pagenum += 0x800;
+ info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
+ info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
+ info.charset = ((infobits[7] >> 1) & 7);
+ info.delete = !!(infobits[3] & 8);
+ info.headline = !!(infobits[5] & 4);
+ info.subtitle = !!(infobits[5] & 8);
+ info.supp_header = !!(infobits[6] & 1);
+ info.update = !!(infobits[6] & 2);
+ info.inter_seq = !!(infobits[6] & 4);
+ info.dis_disp = !!(infobits[6] & 8);
+ info.serial = !!(infobits[7] & 1);
+ info.notfound = !!(infobits[8] & 0x10);
+ info.pblf = !!(infobits[9] & 0x20);
+ info.hamming = 0;
+ for (a = 0; a <= 7; a++) {
+ if (infobits[a] & 0xf0) {
+ info.hamming = 1;
+ break;
}
- return 0;
}
+ if (t->vdau[req->pgbuf].clrfound)
+ info.notfound = 1;
+ if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
+ return -EFAULT;
+ if (!info.hamming && !info.notfound)
+ t->is_searching[req->pgbuf] = false;
+ return 0;
+ }
- case VTXIOCGETPAGE:
- {
- vtx_pagereq_t *req = arg;
- int start, end;
-
- if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 ||
- req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
- return -EINVAL;
- if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
+ case VTXIOCGETPAGE:
+ {
+ vtx_pagereq_t *req = arg;
+ int start, end;
+
+ if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 ||
+ req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
+ return -EINVAL;
+ if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
+ return -EFAULT;
+
+ /*
+ * Always read the time directly from SAA5249
+ */
+
+ if (req->start <= 39 && req->end >= 32) {
+ int len;
+ char buf[16];
+ start = max(req->start, 32);
+ end = min(req->end, 39);
+ len = end - start + 1;
+ if (i2c_senddata(t, 8, 0, 0, start, -1) ||
+ i2c_getdata(t, len, buf))
+ return -EIO;
+ if (copy_to_user(req->buffer + start - req->start, buf, len))
+ return -EFAULT;
+ }
+ /* Insert the current header if DAU is still searching for a page */
+ if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) {
+ char buf[32];
+ int len;
+
+ start = max(req->start, 7);
+ end = min(req->end, 31);
+ len = end - start + 1;
+ if (i2c_senddata(t, 8, 0, 0, start, -1) ||
+ i2c_getdata(t, len, buf))
+ return -EIO;
+ if (copy_to_user(req->buffer + start - req->start, buf, len))
return -EFAULT;
-
- /*
- * Always read the time directly from SAA5249
- */
-
- if (req->start <= 39 && req->end >= 32)
- {
- int len;
- char buf[16];
- start = max(req->start, 32);
- end = min(req->end, 39);
- len=end-start+1;
- if (i2c_senddata(t, 8, 0, 0, start, -1) ||
- i2c_getdata(t, len, buf))
- return -EIO;
- if(copy_to_user(req->buffer+start-req->start, buf, len))
- return -EFAULT;
- }
- /* Insert the current header if DAU is still searching for a page */
- if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf])
- {
- char buf[32];
- int len;
- start = max(req->start, 7);
- end = min(req->end, 31);
- len=end-start+1;
- if (i2c_senddata(t, 8, 0, 0, start, -1) ||
- i2c_getdata(t, len, buf))
- return -EIO;
- if(copy_to_user(req->buffer+start-req->start, buf, len))
- return -EFAULT;
- }
- return 0;
}
+ return 0;
+ }
- case VTXIOCSTOPDAU:
- {
- vtx_pagereq_t *req = arg;
+ case VTXIOCSTOPDAU:
+ {
+ vtx_pagereq_t *req = arg;
- if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
- return -EINVAL;
- t->vdau[req->pgbuf].stopped = true;
- t->is_searching[req->pgbuf] = false;
- return 0;
- }
+ if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+ return -EINVAL;
+ t->vdau[req->pgbuf].stopped = true;
+ t->is_searching[req->pgbuf] = false;
+ return 0;
+ }
- case VTXIOCPUTPAGE:
- case VTXIOCSETDISP:
- case VTXIOCPUTSTAT:
- return 0;
+ case VTXIOCPUTPAGE:
+ case VTXIOCSETDISP:
+ case VTXIOCPUTSTAT:
+ return 0;
- case VTXIOCCLRCACHE:
- {
- if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
- ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
- ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1))
- return -EIO;
- if (i2c_senddata(t, 3, 0x20, -1))
- return -EIO;
- jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */
- return 0;
- }
+ case VTXIOCCLRCACHE:
+ {
+ if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
+ ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ',
+ -1))
+ return -EIO;
+ if (i2c_senddata(t, 3, 0x20, -1))
+ return -EIO;
+ jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */
+ return 0;
+ }
- case VTXIOCSETVIRT:
- {
- /* The SAA5249 has virtual-row reception turned on always */
- t->virtual_mode = (int)(long)arg;
- return 0;
- }
+ case VTXIOCSETVIRT:
+ {
+ /* The SAA5249 has virtual-row reception turned on always */
+ t->virtual_mode = (int)(long)arg;
+ return 0;
+ }
}
return -EINVAL;
}
@@ -616,8 +483,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
static int saa5249_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct video_device *vd = video_devdata(file);
- struct saa5249_device *t=vd->priv;
+ struct saa5249_device *t = video_drvdata(file);
int err;
cmd = vtx_fix_command(cmd);
@@ -629,32 +495,27 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
static int saa5249_open(struct inode *inode, struct file *file)
{
- struct video_device *vd = video_devdata(file);
- struct saa5249_device *t=vd->priv;
- int err,pgbuf;
+ struct saa5249_device *t = video_drvdata(file);
+ int pgbuf;
- err = video_exclusive_open(inode,file);
- if (err < 0)
- return err;
+ if (t->client == NULL)
+ return -ENODEV;
- if (t->client==NULL) {
- err = -ENODEV;
- goto fail;
- }
+ if (test_and_set_bit(0, &t->in_use))
+ return -EBUSY;
- if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */
- /* Turn off parity checks (we do this ourselves) */
+ if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */
+ /* Turn off parity checks (we do this ourselves) */
i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) ||
- /* Display TV-picture, no virtual rows */
- i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */
-
+ /* Display TV-picture, no virtual rows */
+ i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1))
+ /* Set display to page 4 */
{
- err = -EIO;
- goto fail;
+ clear_bit(0, &t->in_use);
+ return -EIO;
}
- for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
- {
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
@@ -665,39 +526,20 @@ static int saa5249_open(struct inode *inode, struct file *file)
}
t->virtual_mode = false;
return 0;
-
- fail:
- video_exclusive_release(inode,file);
- return err;
}
static int saa5249_release(struct inode *inode, struct file *file)
{
- struct video_device *vd = video_devdata(file);
- struct saa5249_device *t=vd->priv;
+ struct saa5249_device *t = video_drvdata(file);
+
i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */
i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */
- video_exclusive_release(inode,file);
+ clear_bit(0, &t->in_use);
return 0;
}
-static int __init init_saa_5249 (void)
-{
- printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n",
- VTX_VER_MAJ, VTX_VER_MIN);
- return i2c_add_driver(&i2c_driver_videotext);
-}
-
-static void __exit cleanup_saa_5249 (void)
-{
- i2c_del_driver(&i2c_driver_videotext);
-}
-
-module_init(init_saa_5249);
-module_exit(cleanup_saa_5249);
-
static const struct file_operations saa_fops = {
.owner = THIS_MODULE,
.open = saa5249_open,
@@ -711,8 +553,84 @@ static const struct file_operations saa_fops = {
static struct video_device saa_template =
{
- .name = IF_NAME,
+ .name = "saa5249",
.fops = &saa_fops,
+ .release = video_device_release,
};
-MODULE_LICENSE("GPL");
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int saa5249_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int pgbuf;
+ int err;
+ struct video_device *vd;
+ struct saa5249_device *t;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+ v4l_info(client, "VideoText version %d.%d\n",
+ VTX_VER_MAJ, VTX_VER_MIN);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL)
+ return -ENOMEM;
+ mutex_init(&t->lock);
+
+ /* Now create a video4linux device */
+ vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+ if (vd == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, vd);
+ memcpy(vd, &saa_template, sizeof(*vd));
+
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
+ memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
+ memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
+ memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
+ t->vdau[pgbuf].expire = 0;
+ t->vdau[pgbuf].clrfound = true;
+ t->vdau[pgbuf].stopped = true;
+ t->is_searching[pgbuf] = false;
+ }
+ video_set_drvdata(vd, t);
+
+ /* Register it */
+ err = video_register_device(vd, VFL_TYPE_VTX, -1);
+ if (err < 0) {
+ kfree(t);
+ kfree(vd);
+ return err;
+ }
+ t->client = client;
+ return 0;
+}
+
+static int saa5249_remove(struct i2c_client *client)
+{
+ struct video_device *vd = i2c_get_clientdata(client);
+
+ video_unregister_device(vd);
+ kfree(video_get_drvdata(vd));
+ kfree(vd);
+ return 0;
+}
+
+static const struct i2c_device_id saa5249_id[] = {
+ { "saa5249", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa5249_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa5249",
+ .driverid = I2C_DRIVERID_SAA5249,
+ .probe = saa5249_probe,
+ .remove = saa5249_remove,
+ .id_table = saa5249_id,
+};
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 4aa82b31070..adf2ba79496 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -31,36 +31,24 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/wait.h>
-#include <asm/io.h>
#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
MODULE_AUTHOR("Pauline Middelink");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
-
-#define I2C_NAME(s) (s)->name
-
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <linux/video_decoder.h>
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
#define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */
#define SAA7110_MAX_OUTPUT 0 /* its a decoder only */
-#define I2C_SAA7110 0x9C /* or 0x9E */
-
#define SAA7110_NR_REG 0x35
struct saa7110 {
@@ -81,10 +69,7 @@ struct saa7110 {
/* I2C support functions */
/* ----------------------------------------------------------------------- */
-static int
-saa7110_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static int saa7110_write(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7110 *decoder = i2c_get_clientdata(client);
@@ -92,10 +77,7 @@ saa7110_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
-static int
-saa7110_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg = *data; /* first register to write to */
@@ -115,8 +97,8 @@ saa7110_write_block (struct i2c_client *client,
memcpy(decoder->reg + reg, data + 1, len - 1);
} else {
for (++data, --len; len; len--) {
- if ((ret = saa7110_write(client, reg++,
- *data++)) < 0)
+ ret = saa7110_write(client, reg++, *data++);
+ if (ret < 0)
break;
}
}
@@ -124,8 +106,7 @@ saa7110_write_block (struct i2c_client *client,
return ret;
}
-static inline int
-saa7110_read (struct i2c_client *client)
+static inline int saa7110_read(struct i2c_client *client)
{
return i2c_smbus_read_byte(client);
}
@@ -138,9 +119,7 @@ saa7110_read (struct i2c_client *client)
#define FRESP_06H_SVIDEO 0x83 //0xC0
-static int
-saa7110_selmux (struct i2c_client *client,
- int chan)
+static int saa7110_selmux(struct i2c_client *client, int chan)
{
static const unsigned char modes[9][8] = {
/* mode 0 */
@@ -197,8 +176,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = {
/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
};
-static int
-determine_norm (struct i2c_client *client)
+static int determine_norm(struct i2c_client *client)
{
DEFINE_WAIT(wait);
struct saa7110 *decoder = i2c_get_clientdata(client);
@@ -212,29 +190,23 @@ determine_norm (struct i2c_client *client)
finish_wait(&decoder->wq, &wait);
status = saa7110_read(client);
if (status & 0x40) {
- dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n",
- I2C_NAME(client), status);
+ v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status);
return decoder->norm; // no change
}
if ((status & 3) == 0) {
saa7110_write(client, 0x06, 0x83);
if (status & 0x20) {
- dprintk(1,
- KERN_INFO
- "%s: status=0x%02x (NTSC/no color)\n",
- I2C_NAME(client), status);
+ v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status);
//saa7110_write(client,0x2E,0x81);
return VIDEO_MODE_NTSC;
}
- dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n",
- I2C_NAME(client), status);
+ v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status);
//saa7110_write(client,0x2E,0x9A);
return VIDEO_MODE_PAL;
}
//saa7110_write(client,0x06,0x03);
if (status & 0x20) { /* 60Hz */
- dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n",
- I2C_NAME(client), status);
+ v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status);
saa7110_write(client, 0x0D, 0x86);
saa7110_write(client, 0x0F, 0x50);
saa7110_write(client, 0x11, 0x2C);
@@ -254,13 +226,11 @@ determine_norm (struct i2c_client *client)
status = saa7110_read(client);
if ((status & 0x03) == 0x01) {
- dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n",
- I2C_NAME(client), status);
+ v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status);
saa7110_write(client, 0x0D, 0x87);
return VIDEO_MODE_SECAM;
}
- dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client),
- status);
+ v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status);
return VIDEO_MODE_PAL;
}
@@ -286,8 +256,8 @@ saa7110_command (struct i2c_client *client,
VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
dc->inputs = SAA7110_MAX_INPUT;
dc->outputs = SAA7110_MAX_OUTPUT;
- }
break;
+ }
case DECODER_GET_STATUS:
{
@@ -295,8 +265,8 @@ saa7110_command (struct i2c_client *client,
int res = 0;
status = saa7110_read(client);
- dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n",
- I2C_NAME(client), status, decoder->norm);
+ v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n",
+ status, decoder->norm);
if (!(status & 0x40))
res |= DECODER_STATUS_GOOD;
if (status & 0x03)
@@ -314,8 +284,8 @@ saa7110_command (struct i2c_client *client,
break;
}
*(int *) arg = res;
- }
break;
+ }
case DECODER_SET_NORM:
v = *(int *) arg;
@@ -328,34 +298,24 @@ saa7110_command (struct i2c_client *client,
saa7110_write(client, 0x0F, 0x50);
saa7110_write(client, 0x11, 0x2C);
//saa7110_write(client, 0x2E, 0x81);
- dprintk(1,
- KERN_INFO "%s: switched to NTSC\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "switched to NTSC\n");
break;
case VIDEO_MODE_PAL:
saa7110_write(client, 0x0D, 0x86);
saa7110_write(client, 0x0F, 0x10);
saa7110_write(client, 0x11, 0x59);
//saa7110_write(client, 0x2E, 0x9A);
- dprintk(1,
- KERN_INFO "%s: switched to PAL\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "switched to PAL\n");
break;
case VIDEO_MODE_SECAM:
saa7110_write(client, 0x0D, 0x87);
saa7110_write(client, 0x0F, 0x10);
saa7110_write(client, 0x11, 0x59);
//saa7110_write(client, 0x2E, 0x9A);
- dprintk(1,
- KERN_INFO
- "%s: switched to SECAM\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "switched to SECAM\n");
break;
case VIDEO_MODE_AUTO:
- dprintk(1,
- KERN_INFO
- "%s: TV standard detection...\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "switched to AUTO\n");
decoder->norm = determine_norm(client);
*(int *) arg = decoder->norm;
break;
@@ -368,15 +328,12 @@ saa7110_command (struct i2c_client *client,
case DECODER_SET_INPUT:
v = *(int *) arg;
if (v < 0 || v > SAA7110_MAX_INPUT) {
- dprintk(1,
- KERN_INFO "%s: input=%d not available\n",
- I2C_NAME(client), v);
+ v4l_dbg(1, debug, client, "input=%d not available\n", v);
return -EINVAL;
}
if (decoder->input != v) {
saa7110_selmux(client, v);
- dprintk(1, KERN_INFO "%s: switched to input=%d\n",
- I2C_NAME(client), v);
+ v4l_dbg(1, debug, client, "switched to input=%d\n", v);
}
break;
@@ -392,8 +349,7 @@ saa7110_command (struct i2c_client *client,
if (decoder->enable != v) {
decoder->enable = v;
saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
- dprintk(1, KERN_INFO "%s: YUV %s\n", I2C_NAME(client),
- v ? "on" : "off");
+ v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off");
}
break;
@@ -423,23 +379,23 @@ saa7110_command (struct i2c_client *client,
saa7110_write(client, 0x07,
(decoder->hue >> 8) - 128);
}
- }
break;
+ }
case DECODER_DUMP:
+ if (!debug)
+ break;
for (v = 0; v < SAA7110_NR_REG; v += 16) {
int j;
- dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client),
- v);
+ v4l_dbg(1, debug, client, "%02x:", v);
for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++)
- dprintk(1, " %02x", decoder->reg[v + j]);
- dprintk(1, "\n");
+ printk(KERN_CONT " %02x", decoder->reg[v + j]);
+ printk(KERN_CONT "\n");
}
break;
default:
- dprintk(1, KERN_INFO "unknown saa7110_command??(%d)\n",
- cmd);
+ v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
return -EINVAL;
}
return 0;
@@ -451,55 +407,28 @@ saa7110_command (struct i2c_client *client,
* Generic i2c probe
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static unsigned short normal_i2c[] = {
- I2C_SAA7110 >> 1,
- (I2C_SAA7110 >> 1) + 1,
- I2C_CLIENT_END
-};
-
-static unsigned short ignore = I2C_CLIENT_END;
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END };
-static struct i2c_driver i2c_driver_saa7110;
+I2C_CLIENT_INSMOD;
-static int
-saa7110_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int saa7110_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
struct saa7110 *decoder;
int rv;
- dprintk(1,
- KERN_INFO
- "saa7110.c: detecting saa7110 client on address 0x%x\n",
- address << 1);
-
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality
- (adapter,
- I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_saa7110;
- strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
- if (!decoder) {
- kfree(client);
+ if (!decoder)
return -ENOMEM;
- }
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
@@ -510,18 +439,10 @@ saa7110_detect_client (struct i2c_adapter *adapter,
init_waitqueue_head(&decoder->wq);
i2c_set_clientdata(client, decoder);
- rv = i2c_attach_client(client);
- if (rv) {
- kfree(client);
- kfree(decoder);
- return rv;
- }
-
rv = saa7110_write_block(client, initseq, sizeof(initseq));
- if (rv < 0)
- dprintk(1, KERN_ERR "%s_attach: init status %d\n",
- I2C_NAME(client), rv);
- else {
+ if (rv < 0) {
+ v4l_dbg(1, debug, client, "init status %d\n", rv);
+ } else {
int ver, status;
saa7110_write(client, 0x21, 0x10);
saa7110_write(client, 0x0e, 0x18);
@@ -530,10 +451,8 @@ saa7110_detect_client (struct i2c_adapter *adapter,
saa7110_write(client, 0x0D, 0x06);
//mdelay(150);
status = saa7110_read(client);
- dprintk(1,
- KERN_INFO
- "%s_attach: SAA7110A version %x at 0x%02x, status=0x%02x\n",
- I2C_NAME(client), ver, client->addr << 1, status);
+ v4l_dbg(1, debug, client, "version %x, status=0x%02x\n",
+ ver, status);
saa7110_write(client, 0x0D, 0x86);
saa7110_write(client, 0x0F, 0x10);
saa7110_write(client, 0x11, 0x59);
@@ -547,58 +466,25 @@ saa7110_detect_client (struct i2c_adapter *adapter,
return 0;
}
-static int
-saa7110_attach_adapter (struct i2c_adapter *adapter)
-{
- dprintk(1,
- KERN_INFO
- "saa7110.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &saa7110_detect_client);
-}
-
-static int
-saa7110_detach_client (struct i2c_client *client)
+static int saa7110_remove(struct i2c_client *client)
{
- struct saa7110 *decoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(decoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_saa7110 = {
- .driver = {
- .name = "saa7110",
- },
-
- .id = I2C_DRIVERID_SAA7110,
+static const struct i2c_device_id saa7110_id[] = {
+ { "saa7110", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7110_id);
- .attach_adapter = saa7110_attach_adapter,
- .detach_client = saa7110_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa7110",
+ .driverid = I2C_DRIVERID_SAA7110,
.command = saa7110_command,
+ .probe = saa7110_probe,
+ .remove = saa7110_remove,
+ .id_table = saa7110_id,
};
-
-static int __init
-saa7110_init (void)
-{
- return i2c_add_driver(&i2c_driver_saa7110);
-}
-
-static void __exit
-saa7110_exit (void)
-{
- i2c_del_driver(&i2c_driver_saa7110);
-}
-
-module_init(saa7110_init);
-module_exit(saa7110_exit);
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 96c3d435772..a4738a2fb4d 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -28,43 +28,24 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(s) (s)->name
-
-
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
#define SAA7111_NR_REG 0x18
@@ -77,14 +58,9 @@ struct saa7111 {
int enable;
};
-#define I2C_SAA7111 0x48
-
/* ----------------------------------------------------------------------- */
-static inline int
-saa7111_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
@@ -92,8 +68,7 @@ saa7111_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline void
-saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
+static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
@@ -103,10 +78,7 @@ saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
}
}
-static int
-saa7111_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -127,18 +99,17 @@ saa7111_write_block (struct i2c_client *client,
decoder->reg[reg++] = data[1];
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
- if ((ret = saa7111_write(client, reg,
- *data++)) < 0)
+ ret = saa7111_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
@@ -147,16 +118,13 @@ saa7111_write_block (struct i2c_client *client,
return ret;
}
-static int
-saa7111_init_decoder (struct i2c_client *client,
- struct video_decoder_init *init)
+static int saa7111_init_decoder(struct i2c_client *client,
+ struct video_decoder_init *init)
{
return saa7111_write_block(client, init->data, init->len);
}
-static inline int
-saa7111_read (struct i2c_client *client,
- u8 reg)
+static inline int saa7111_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
@@ -203,28 +171,23 @@ static const unsigned char saa7111_i2c_init[] = {
0x17, 0x00, /* 17 - VBI */
};
-static int
-saa7111_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
break;
case DECODER_INIT:
{
struct video_decoder_init *init = arg;
+ struct video_decoder_init vdi;
+
if (NULL != init)
return saa7111_init_decoder(client, init);
- else {
- struct video_decoder_init vdi;
- vdi.data = saa7111_i2c_init;
- vdi.len = sizeof(saa7111_i2c_init);
- return saa7111_init_decoder(client, &vdi);
- }
+ vdi.data = saa7111_i2c_init;
+ vdi.len = sizeof(saa7111_i2c_init);
+ return saa7111_init_decoder(client, &vdi);
}
case DECODER_DUMP:
@@ -234,15 +197,15 @@ saa7111_command (struct i2c_client *client,
for (i = 0; i < SAA7111_NR_REG; i += 16) {
int j;
- printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
+ v4l_info(client, "%03x", i);
for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
- printk(" %02x",
+ printk(KERN_CONT " %02x",
saa7111_read(client, i + j));
}
- printk("\n");
+ printk(KERN_CONT "\n");
}
- }
break;
+ }
case DECODER_GET_CAPABILITIES:
{
@@ -255,8 +218,8 @@ saa7111_command (struct i2c_client *client,
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
- }
break;
+ }
case DECODER_GET_STATUS:
{
@@ -265,8 +228,7 @@ saa7111_command (struct i2c_client *client,
int res;
status = saa7111_read(client, 0x1f);
- dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
- status);
+ v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
res = 0;
if ((status & (1 << 6)) == 0) {
res |= DECODER_STATUS_GOOD;
@@ -294,8 +256,8 @@ saa7111_command (struct i2c_client *client,
res |= DECODER_STATUS_COLOR;
}
*iarg = res;
- }
break;
+ }
case DECODER_SET_GPIO:
{
@@ -362,8 +324,8 @@ saa7111_command (struct i2c_client *client,
}
decoder->norm = *iarg;
- }
break;
+ }
case DECODER_SET_INPUT:
{
@@ -387,8 +349,8 @@ saa7111_command (struct i2c_client *client,
3) ? 0x80 :
0));
}
- }
break;
+ }
case DECODER_SET_OUTPUT:
{
@@ -398,8 +360,8 @@ saa7111_command (struct i2c_client *client,
if (*iarg != 0) {
return -EINVAL;
}
- }
break;
+ }
case DECODER_ENABLE_OUTPUT:
{
@@ -439,8 +401,8 @@ saa7111_command (struct i2c_client *client,
(decoder->reg[0x11] & 0xf3));
}
}
- }
break;
+ }
case DECODER_SET_PICTURE:
{
@@ -454,8 +416,8 @@ saa7111_command (struct i2c_client *client,
saa7111_write(client, 0x0c, pic->colour >> 9);
/* We want -128 to 127 we get 0-65535 */
saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
- }
break;
+ }
default:
return -EINVAL;
@@ -466,48 +428,23 @@ saa7111_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
-
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END };
-static struct i2c_driver i2c_driver_saa7111;
+I2C_CLIENT_INSMOD;
-static int
-saa7111_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int saa7111_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i;
- struct i2c_client *client;
struct saa7111 *decoder;
struct video_decoder_init vdi;
- dprintk(1,
- KERN_INFO
- "saa7111.c: detecting saa7111 client on address 0x%x\n",
- address << 1);
-
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_saa7111;
- strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
if (decoder == NULL) {
@@ -519,82 +456,37 @@ saa7111_detect_client (struct i2c_adapter *adapter,
decoder->enable = 1;
i2c_set_clientdata(client, decoder);
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(decoder);
- return i;
- }
-
vdi.data = saa7111_i2c_init;
vdi.len = sizeof(saa7111_i2c_init);
i = saa7111_init_decoder(client, &vdi);
if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
- I2C_NAME(client), i);
+ v4l_dbg(1, debug, client, "init status %d\n", i);
} else {
- dprintk(1,
- KERN_INFO
- "%s_attach: chip version %x at address 0x%x\n",
- I2C_NAME(client), saa7111_read(client, 0x00) >> 4,
- client->addr << 1);
+ v4l_dbg(1, debug, client, "revision %x\n",
+ saa7111_read(client, 0x00) >> 4);
}
-
return 0;
}
-static int
-saa7111_attach_adapter (struct i2c_adapter *adapter)
+static int saa7111_remove(struct i2c_client *client)
{
- dprintk(1,
- KERN_INFO
- "saa7111.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &saa7111_detect_client);
-}
-
-static int
-saa7111_detach_client (struct i2c_client *client)
-{
- struct saa7111 *decoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(decoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_saa7111 = {
- .driver = {
- .name = "saa7111",
- },
-
- .id = I2C_DRIVERID_SAA7111A,
+static const struct i2c_device_id saa7111_id[] = {
+ { "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7111_id);
- .attach_adapter = saa7111_attach_adapter,
- .detach_client = saa7111_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa7111",
+ .driverid = I2C_DRIVERID_SAA7111A,
.command = saa7111_command,
+ .probe = saa7111_probe,
+ .remove = saa7111_remove,
+ .id_table = saa7111_id,
};
-
-static int __init
-saa7111_init (void)
-{
- return i2c_add_driver(&i2c_driver_saa7111);
-}
-
-static void __exit
-saa7111_exit (void)
-{
- i2c_del_driver(&i2c_driver_saa7111);
-}
-
-module_init(saa7111_init);
-module_exit(saa7111_exit);
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index e79075533be..7ca709fda5f 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -29,43 +29,24 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
-
-#define I2C_NAME(x) (x)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
struct saa7114 {
@@ -81,9 +62,6 @@ struct saa7114 {
int playback;
};
-#define I2C_SAA7114 0x42
-#define I2C_SAA7114A 0x40
-
#define I2C_DELAY 10
@@ -129,18 +107,12 @@ struct saa7114 {
/* ----------------------------------------------------------------------- */
-static inline int
-saa7114_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
-static int
-saa7114_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -160,18 +132,17 @@ saa7114_write_block (struct i2c_client *client,
reg++;
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
- if ((ret = saa7114_write(client, reg,
- *data++)) < 0)
+ ret = saa7114_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
@@ -180,9 +151,7 @@ saa7114_write_block (struct i2c_client *client,
return ret;
}
-static inline int
-saa7114_read (struct i2c_client *client,
- u8 reg)
+static inline int saa7114_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
@@ -452,15 +421,11 @@ static const unsigned char init[] = {
0xef, 0x00
};
-static int
-saa7114_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct saa7114 *decoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
//dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
//saa7114_write_block(client, init, sizeof(init));
@@ -470,27 +435,28 @@ saa7114_command (struct i2c_client *client,
{
int i;
- dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client));
+ if (!debug)
+ break;
+ v4l_info(client, "decoder dump\n");
for (i = 0; i < 32; i += 16) {
int j;
- printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
+ v4l_info(client, "%03x", i);
for (j = 0; j < 16; ++j) {
- printk(" %02x",
+ printk(KERN_CONT " %02x",
saa7114_read(client, i + j));
}
- printk("\n");
+ printk(KERN_CONT "\n");
}
- }
break;
+ }
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
- dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "get capabilities\n");
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
@@ -498,8 +464,8 @@ saa7114_command (struct i2c_client *client,
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
- }
break;
+ }
case DECODER_GET_STATUS:
{
@@ -509,8 +475,7 @@ saa7114_command (struct i2c_client *client,
status = saa7114_read(client, 0x1f);
- dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
- status);
+ v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
res = 0;
if ((status & (1 << 6)) == 0) {
res |= DECODER_STATUS_GOOD;
@@ -538,8 +503,8 @@ saa7114_command (struct i2c_client *client,
res |= DECODER_STATUS_COLOR;
}
*iarg = res;
- }
break;
+ }
case DECODER_SET_NORM:
{
@@ -547,12 +512,11 @@ saa7114_command (struct i2c_client *client,
short int hoff = 0, voff = 0, w = 0, h = 0;
- dprintk(1, KERN_DEBUG "%s: decoder set norm ",
- I2C_NAME(client));
- switch (*iarg) {
+ v4l_dbg(1, debug, client, "set norm\n");
+ switch (*iarg) {
case VIDEO_MODE_NTSC:
- dprintk(1, "NTSC\n");
+ v4l_dbg(1, debug, client, "NTSC\n");
decoder->reg[REG_ADDR(0x06)] =
SAA_7114_NTSC_HSYNC_START;
decoder->reg[REG_ADDR(0x07)] =
@@ -571,7 +535,7 @@ saa7114_command (struct i2c_client *client,
break;
case VIDEO_MODE_PAL:
- dprintk(1, "PAL\n");
+ v4l_dbg(1, debug, client, "PAL\n");
decoder->reg[REG_ADDR(0x06)] =
SAA_7114_PAL_HSYNC_START;
decoder->reg[REG_ADDR(0x07)] =
@@ -590,9 +554,8 @@ saa7114_command (struct i2c_client *client,
break;
default:
- dprintk(1, " Unknown video mode!!!\n");
+ v4l_dbg(1, debug, client, "Unknown video mode\n");
return -EINVAL;
-
}
@@ -644,22 +607,20 @@ saa7114_command (struct i2c_client *client,
saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection
decoder->norm = *iarg;
- }
break;
+ }
case DECODER_SET_INPUT:
{
int *iarg = arg;
- dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n",
- I2C_NAME(client), *iarg);
+ v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
if (*iarg < 0 || *iarg > 7) {
return -EINVAL;
}
if (decoder->input != *iarg) {
- dprintk(1, KERN_DEBUG "%s: now setting %s input\n",
- I2C_NAME(client),
+ v4l_dbg(1, debug, client, "now setting %s input\n",
*iarg >= 6 ? "S-Video" : "Composite");
decoder->input = *iarg;
@@ -690,30 +651,29 @@ saa7114_command (struct i2c_client *client,
saa7114_write(client, 0x0e,
decoder->reg[REG_ADDR(0x0e)]);
}
- }
break;
+ }
case DECODER_SET_OUTPUT:
{
int *iarg = arg;
- dprintk(1, KERN_DEBUG "%s: decoder set output\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "set output\n");
/* not much choice of outputs */
if (*iarg != 0) {
return -EINVAL;
}
- }
break;
+ }
case DECODER_ENABLE_OUTPUT:
{
int *iarg = arg;
int enable = (*iarg != 0);
- dprintk(1, KERN_DEBUG "%s: decoder %s output\n",
- I2C_NAME(client), enable ? "enable" : "disable");
+ v4l_dbg(1, debug, client, "%s output\n",
+ enable ? "enable" : "disable");
decoder->playback = !enable;
@@ -754,18 +714,16 @@ saa7114_command (struct i2c_client *client,
saa7114_write(client, 0x80, 0x36);
}
- }
break;
+ }
case DECODER_SET_PICTURE:
{
struct video_picture *pic = arg;
- dprintk(1,
- KERN_DEBUG
- "%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
- I2C_NAME(client), pic->brightness, pic->contrast,
- pic->colour, pic->hue);
+ v4l_dbg(1, debug, client,
+ "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
+ pic->brightness, pic->contrast, pic->colour, pic->hue);
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
@@ -789,8 +747,8 @@ saa7114_command (struct i2c_client *client,
saa7114_write(client, 0x0d,
(decoder->hue - 32768) >> 8);
}
- }
break;
+ }
default:
return -EINVAL;
@@ -801,58 +759,30 @@ saa7114_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
- { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
-
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
-static struct i2c_driver i2c_driver_saa7114;
+I2C_CLIENT_INSMOD;
-static int
-saa7114_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int saa7114_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i, err[30];
short int hoff = SAA_7114_NTSC_HOFFSET;
short int voff = SAA_7114_NTSC_VOFFSET;
short int w = SAA_7114_NTSC_WIDTH;
short int h = SAA_7114_NTSC_HEIGHT;
- struct i2c_client *client;
struct saa7114 *decoder;
- dprintk(1,
- KERN_INFO
- "saa7114.c: detecting saa7114 client on address 0x%x\n",
- address << 1);
-
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_saa7114;
- strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
- if (decoder == NULL) {
- kfree(client);
+ if (decoder == NULL)
return -ENOMEM;
- }
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = -1;
decoder->enable = 1;
@@ -937,8 +867,7 @@ saa7114_detect_client (struct i2c_adapter *adapter,
decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on
- dprintk(1, KERN_DEBUG "%s_attach: starting decoder init\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "starting init\n");
err[0] =
saa7114_write_block(client, decoder->reg + (0x20 << 1),
@@ -962,28 +891,23 @@ saa7114_detect_client (struct i2c_adapter *adapter,
for (i = 0; i <= 5; i++) {
if (err[i] < 0) {
- dprintk(1,
- KERN_ERR
- "%s_attach: init error %d at stage %d, leaving attach.\n",
- I2C_NAME(client), i, err[i]);
+ v4l_dbg(1, debug, client,
+ "init error %d at stage %d, leaving attach.\n",
+ i, err[i]);
kfree(decoder);
- kfree(client);
- return 0;
+ return -EIO;
}
}
for (i = 6; i < 8; i++) {
- dprintk(1,
- KERN_DEBUG
- "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
- I2C_NAME(client), i, saa7114_read(client, i),
+ v4l_dbg(1, debug, client,
+ "reg[0x%02x] = 0x%02x (0x%02x)\n",
+ i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
- dprintk(1,
- KERN_DEBUG
- "%s_attach: performing decoder reset sequence\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client,
+ "performing decoder reset sequence\n");
err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off
err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
@@ -991,19 +915,15 @@ saa7114_detect_client (struct i2c_adapter *adapter,
for (i = 6; i <= 8; i++) {
if (err[i] < 0) {
- dprintk(1,
- KERN_ERR
- "%s_attach: init error %d at stage %d, leaving attach.\n",
- I2C_NAME(client), i, err[i]);
+ v4l_dbg(1, debug, client,
+ "init error %d at stage %d, leaving attach.\n",
+ i, err[i]);
kfree(decoder);
- kfree(client);
- return 0;
+ return -EIO;
}
}
- dprintk(1, KERN_INFO "%s_attach: performing the rest of init\n",
- I2C_NAME(client));
-
+ v4l_dbg(1, debug, client, "performing the rest of init\n");
err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq
@@ -1039,37 +959,32 @@ saa7114_detect_client (struct i2c_adapter *adapter,
for (i = 9; i <= 18; i++) {
if (err[i] < 0) {
- dprintk(1,
- KERN_ERR
- "%s_attach: init error %d at stage %d, leaving attach.\n",
- I2C_NAME(client), i, err[i]);
+ v4l_dbg(1, debug, client,
+ "init error %d at stage %d, leaving attach.\n",
+ i, err[i]);
kfree(decoder);
- kfree(client);
- return 0;
+ return -EIO;
}
}
for (i = 6; i < 8; i++) {
- dprintk(1,
- KERN_DEBUG
- "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
- I2C_NAME(client), i, saa7114_read(client, i),
+ v4l_dbg(1, debug, client,
+ "reg[0x%02x] = 0x%02x (0x%02x)\n",
+ i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
for (i = 0x11; i <= 0x13; i++) {
- dprintk(1,
- KERN_DEBUG
- "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
- I2C_NAME(client), i, saa7114_read(client, i),
+ v4l_dbg(1, debug, client,
+ "reg[0x%02x] = 0x%02x (0x%02x)\n",
+ i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
- dprintk(1, KERN_DEBUG "%s_attach: setting video input\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "setting video input\n");
err[19] =
saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
@@ -1080,20 +995,15 @@ saa7114_detect_client (struct i2c_adapter *adapter,
for (i = 19; i <= 21; i++) {
if (err[i] < 0) {
- dprintk(1,
- KERN_ERR
- "%s_attach: init error %d at stage %d, leaving attach.\n",
- I2C_NAME(client), i, err[i]);
+ v4l_dbg(1, debug, client,
+ "init error %d at stage %d, leaving attach.\n",
+ i, err[i]);
kfree(decoder);
- kfree(client);
- return 0;
+ return -EIO;
}
}
- dprintk(1,
- KERN_DEBUG
- "%s_attach: performing decoder reset sequence\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
@@ -1102,13 +1012,11 @@ saa7114_detect_client (struct i2c_adapter *adapter,
for (i = 22; i <= 24; i++) {
if (err[i] < 0) {
- dprintk(1,
- KERN_ERR
- "%s_attach: init error %d at stage %d, leaving attach.\n",
- I2C_NAME(client), i, err[i]);
+ v4l_dbg(1, debug, client,
+ "init error %d at stage %d, leaving attach.\n",
+ i, err[i]);
kfree(decoder);
- kfree(client);
- return 0;
+ return -EIO;
}
}
@@ -1116,101 +1024,45 @@ saa7114_detect_client (struct i2c_adapter *adapter,
err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
- dprintk(1,
- KERN_INFO
- "%s_attach: chip version %x, decoder status 0x%02x\n",
- I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
+ v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
+ saa7114_read(client, 0x00) >> 4,
saa7114_read(client, 0x1f));
- dprintk(1,
- KERN_DEBUG
- "%s_attach: power save control: 0x%02x, scaler status: 0x%02x\n",
- I2C_NAME(client), saa7114_read(client, 0x88),
+ v4l_dbg(1, debug, client,
+ "power save control: 0x%02x, scaler status: 0x%02x\n",
+ saa7114_read(client, 0x88),
saa7114_read(client, 0x8f));
for (i = 0x94; i < 0x96; i++) {
- dprintk(1,
- KERN_DEBUG
- "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
- I2C_NAME(client), i, saa7114_read(client, i),
+ v4l_dbg(1, debug, client,
+ "reg[0x%02x] = 0x%02x (0x%02x)\n",
+ i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(decoder);
- return i;
- }
-
//i = saa7114_write_block(client, init, sizeof(init));
- i = 0;
- if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
- I2C_NAME(client), i);
- } else {
- dprintk(1,
- KERN_INFO
- "%s_attach: chip version %x at address 0x%x\n",
- I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
- client->addr << 1);
- }
-
return 0;
}
-static int
-saa7114_attach_adapter (struct i2c_adapter *adapter)
-{
- dprintk(1,
- KERN_INFO
- "saa7114.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &saa7114_detect_client);
-}
-
-static int
-saa7114_detach_client (struct i2c_client *client)
+static int saa7114_remove(struct i2c_client *client)
{
- struct saa7114 *decoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(decoder);
- kfree(client);
-
+ kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_saa7114 = {
- .driver = {
- .name = "saa7114",
- },
-
- .id = I2C_DRIVERID_SAA7114,
+static const struct i2c_device_id saa7114_id[] = {
+ { "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7114_id);
- .attach_adapter = saa7114_attach_adapter,
- .detach_client = saa7114_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa7114",
+ .driverid = I2C_DRIVERID_SAA7114,
.command = saa7114_command,
+ .probe = saa7114_probe,
+ .remove = saa7114_remove,
+ .id_table = saa7114_id,
};
-
-static int __init
-saa7114_init (void)
-{
- return i2c_add_driver(&i2c_driver_saa7114);
-}
-
-static void __exit
-saa7114_exit (void)
-{
- i2c_del_driver(&i2c_driver_saa7114);
-}
-
-module_init(saa7114_init);
-module_exit(saa7114_exit);
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index bcd1c8f6cf6..c8e9cb3db30 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1057,7 +1057,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
for (i = 0; i <= 23; i++)
lcr[i] = 0xff;
- if (fmt->service_set == 0) {
+ if (fmt == NULL) {
/* raw VBI */
if (is_50hz)
for (i = 6; i <= 23; i++)
@@ -1113,7 +1113,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
}
/* enable/disable raw VBI capturing */
- saa711x_writeregs(client, fmt->service_set == 0 ?
+ saa711x_writeregs(client, fmt == NULL ?
saa7115_cfg_vbi_on :
saa7115_cfg_vbi_off);
}
@@ -1153,6 +1153,10 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
saa711x_set_lcr(client, &fmt->fmt.sliced);
return 0;
}
+ if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ saa711x_set_lcr(client, NULL);
+ return 0;
+ }
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1309,10 +1313,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
case VIDIOC_INT_S_VIDEO_ROUTING:
{
struct v4l2_routing *route = arg;
+ u32 input = route->input;
+ u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;
v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);
- /* saa7113 does not have these inputs */
- if (state->ident == V4L2_IDENT_SAA7113 &&
+ /* saa7111/3 does not have these inputs */
+ if ((state->ident == V4L2_IDENT_SAA7113 ||
+ state->ident == V4L2_IDENT_SAA7111) &&
(route->input == SAA7115_COMPOSITE4 ||
route->input == SAA7115_COMPOSITE5)) {
return -EINVAL;
@@ -1327,10 +1334,23 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
state->input = route->input;
+ /* saa7111 has slightly different input numbering */
+ if (state->ident == V4L2_IDENT_SAA7111) {
+ if (input >= SAA7115_COMPOSITE4)
+ input -= 2;
+ /* saa7111 specific */
+ saa711x_write(client, R_10_CHROMA_CNTL_2,
+ (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) |
+ ((route->output & 0xc0) ^ 0x40));
+ saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL,
+ (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
+ ((route->output & 2) ? 0x0a : 0));
+ }
+
/* select mode */
saa711x_write(client, R_02_INPUT_CNTL_1,
- (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |
- state->input);
+ (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) |
+ input);
/* bypass chrominance trap for S-Video modes */
saa711x_write(client, R_09_LUMA_CNTL,
@@ -1384,6 +1404,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
saa711x_writeregs(client, saa7115_cfg_reset_scaler);
break;
+ case VIDIOC_INT_S_GPIO:
+ if (state->ident != V4L2_IDENT_SAA7111)
+ return -EINVAL;
+ saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) |
+ (*(u32 *)arg ? 0x80 : 0));
+ break;
+
case VIDIOC_INT_G_VBI_DATA:
{
struct v4l2_sliced_vbi_data *data = arg;
@@ -1489,10 +1516,9 @@ static int saa7115_probe(struct i2c_client *client,
client->addr << 1, client->adapter->name);
state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
- i2c_set_clientdata(client, state);
- if (state == NULL) {
+ if (state == NULL)
return -ENOMEM;
- }
+ i2c_set_clientdata(client, state);
state->input = -1;
state->output = SAA7115_IPORT_ON;
state->enable = 1;
@@ -1540,7 +1566,8 @@ static int saa7115_probe(struct i2c_client *client,
state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
saa711x_writeregs(client, saa7115_init_auto_input);
}
- saa711x_writeregs(client, saa7115_init_misc);
+ if (state->ident != V4L2_IDENT_SAA7111)
+ saa711x_writeregs(client, saa7115_init_misc);
saa711x_set_v4lstd(client, V4L2_STD_NTSC);
v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index d0e83fe0ff5..cc02fb18efa 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -29,7 +29,7 @@
* Note: the saa7126 is identical to the saa7127, and the saa7128 is
* identical to the saa7129, except that the saa7126 and saa7128 have
* macrovision anti-taping support. This driver will almost certainly
- * work find for those chips, except of course for the missing anti-taping
+ * work fine for those chips, except of course for the missing anti-taping
* support.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 707be175509..1fb6eccdade 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -1,3 +1,27 @@
+ /*
+ saa6752hs - i2c-driver for the saa6752hs by Philips
+
+ Copyright (C) 2004 Andrew de Quincey
+
+ AC-3 support:
+
+ Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA.
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -10,6 +34,8 @@
#include <linux/types.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv-legacy.h>
#include <linux/init.h>
#include <linux/crc32.h>
@@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
MODULE_AUTHOR("Andrew de Quincey");
MODULE_LICENSE("GPL");
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
enum saa6752hs_videoformat {
SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */
SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
@@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params {
__u16 ts_pid_pcr;
/* audio */
- enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+ enum v4l2_mpeg_audio_encoding au_encoding;
+ enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+ enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
/* video */
enum v4l2_mpeg_video_aspect vi_aspect;
@@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] =
};
struct saa6752hs_state {
- struct i2c_client client;
+ int chip;
+ u32 revision;
+ int has_ac3;
struct saa6752hs_mpeg_params params;
enum saa6752hs_videoformat video_format;
v4l2_std_id standard;
@@ -145,6 +172,39 @@ static u8 PMT[] = {
0x00, 0x00, 0x00, 0x00 /* CRC32 */
};
+static u8 PMT_AC3[] = {
+ 0xc2, /* i2c register */
+ 0x01, /* table number for encoder(1) */
+ 0x47, /* sync */
+
+ 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
+ 0x10, /* PMT PID (0x0010) */
+ 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+ 0x00, /* PSI pointer to start of table */
+
+ 0x02, /* TID (2) */
+ 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
+
+ 0x00, 0x01, /* program_number(1) */
+
+ 0xc1, /* version_number(0), current_next_indicator(1) */
+
+ 0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+ 0xe1, 0x04, /* PCR_PID (0x0104) */
+
+ 0xf0, 0x00, /* program_info_length(0) */
+
+ 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+ 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
+ 0x6a, /* AC3 */
+ 0x01, /* Descriptor_length(1) */
+ 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
+
+ 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
+};
+
static struct saa6752hs_mpeg_params param_defaults =
{
.ts_pid_pmt = 16,
@@ -157,12 +217,14 @@ static struct saa6752hs_mpeg_params param_defaults =
.vi_bitrate_peak = 6000,
.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+ .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
};
/* ---------------------------------------------------------------------- */
-static int saa6752hs_chip_command(struct i2c_client* client,
+static int saa6752hs_chip_command(struct i2c_client *client,
enum saa6752hs_command command)
{
unsigned char buf[3];
@@ -229,45 +291,61 @@ static int saa6752hs_chip_command(struct i2c_client* client,
}
-static int saa6752hs_set_bitrate(struct i2c_client* client,
- struct saa6752hs_mpeg_params* params)
+static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
+{
+ u8 buf[2];
+
+ buf[0] = reg;
+ buf[1] = val;
+ i2c_master_send(client, buf, 2);
+}
+
+static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
{
u8 buf[3];
+
+ buf[0] = reg;
+ buf[1] = val >> 8;
+ buf[2] = val & 0xff;
+ i2c_master_send(client, buf, 3);
+}
+
+static int saa6752hs_set_bitrate(struct i2c_client *client,
+ struct saa6752hs_state *h)
+{
+ struct saa6752hs_mpeg_params *params = &h->params;
int tot_bitrate;
+ int is_384k;
/* set the bitrate mode */
- buf[0] = 0x71;
- buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0x71,
+ params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
/* set the video bitrate */
if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
/* set the target bitrate */
- buf[0] = 0x80;
- buf[1] = params->vi_bitrate >> 8;
- buf[2] = params->vi_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
+ set_reg16(client, 0x80, params->vi_bitrate);
/* set the max bitrate */
- buf[0] = 0x81;
- buf[1] = params->vi_bitrate_peak >> 8;
- buf[2] = params->vi_bitrate_peak & 0xff;
- i2c_master_send(client, buf, 3);
+ set_reg16(client, 0x81, params->vi_bitrate_peak);
tot_bitrate = params->vi_bitrate_peak;
} else {
/* set the target bitrate (no max bitrate for CBR) */
- buf[0] = 0x81;
- buf[1] = params->vi_bitrate >> 8;
- buf[2] = params->vi_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
+ set_reg16(client, 0x81, params->vi_bitrate);
tot_bitrate = params->vi_bitrate;
}
+ /* set the audio encoding */
+ set_reg8(client, 0x93,
+ params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
+
/* set the audio bitrate */
- buf[0] = 0x94;
- buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
- i2c_master_send(client, buf, 2);
- tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
+ if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
+ is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
+ else
+ is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
+ set_reg8(client, 0x94, is_384k);
+ tot_bitrate += is_384k ? 384 : 256;
/* Note: the total max bitrate is determined by adding the video and audio
bitrates together and also adding an extra 768kbit/s to stay on the
@@ -278,16 +356,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client,
tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
/* set the total bitrate */
- buf[0] = 0xb1;
- buf[1] = tot_bitrate >> 8;
- buf[2] = tot_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
-
+ set_reg16(client, 0xb1, tot_bitrate);
return 0;
}
-static void saa6752hs_set_subsampling(struct i2c_client* client,
- struct v4l2_format* f)
+static void saa6752hs_set_subsampling(struct i2c_client *client,
+ struct v4l2_format *f)
{
struct saa6752hs_state *h = i2c_get_clientdata(client);
int dist_352, dist_480, dist_720;
@@ -332,7 +406,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client,
}
-static int handle_ctrl(struct saa6752hs_mpeg_params *params,
+static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
struct v4l2_ext_control *ctrl, unsigned int cmd)
{
int old = 0, new;
@@ -379,8 +453,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
params->ts_pid_pcr = new;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
- old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
- if (set && new != old)
+ old = params->au_encoding;
+ if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+ (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
return -ERANGE;
new = old;
break;
@@ -395,6 +470,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
params->au_l2_bitrate = new;
break;
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!has_ac3)
+ return -EINVAL;
+ old = params->au_ac3_bitrate;
+ if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
+ new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
+ return -ERANGE;
+ if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
+ new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
+ else
+ new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
+ params->au_ac3_bitrate = new;
+ break;
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
if (set && new != old)
@@ -448,17 +536,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
return 0;
}
-static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qctrl(struct saa6752hs_state *h,
struct v4l2_queryctrl *qctrl)
{
+ struct saa6752hs_mpeg_params *params = &h->params;
int err;
switch (qctrl->id) {
case V4L2_CID_MPEG_AUDIO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+ h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
return v4l2_ctrl_query_fill(qctrl,
@@ -466,6 +556,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!h->has_ac3)
+ return -EINVAL;
+ return v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
@@ -512,44 +610,57 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
return -EINVAL;
}
-static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qmenu(struct saa6752hs_state *h,
struct v4l2_querymenu *qmenu)
{
- static const char *mpeg_audio_l2_bitrate[] = {
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "256 kbps",
- "",
- "384 kbps",
- NULL
+ static const u32 mpeg_audio_encoding[] = {
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static const u32 mpeg_audio_ac3_encoding[] = {
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ V4L2_MPEG_AUDIO_ENCODING_AC3,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static u32 mpeg_audio_l2_bitrate[] = {
+ V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+ V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static u32 mpeg_audio_ac3_bitrate[] = {
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+ V4L2_CTRL_MENU_IDS_END
};
struct v4l2_queryctrl qctrl;
int err;
qctrl.id = qmenu->id;
- err = saa6752hs_qctrl(params, &qctrl);
+ err = saa6752hs_qctrl(h, &qctrl);
if (err)
return err;
- if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
- return v4l2_ctrl_query_menu(qmenu, &qctrl,
+ switch (qmenu->id) {
+ case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
mpeg_audio_l2_bitrate);
- return v4l2_ctrl_query_menu(qmenu, &qctrl,
- v4l2_ctrl_get_menu(qmenu->id));
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!h->has_ac3)
+ return -EINVAL;
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
+ mpeg_audio_ac3_bitrate);
+ case V4L2_CID_MPEG_AUDIO_ENCODING:
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
+ h->has_ac3 ? mpeg_audio_ac3_encoding :
+ mpeg_audio_encoding);
+ }
+ return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
}
-static int saa6752hs_init(struct i2c_client* client)
+static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes)
{
unsigned char buf[9], buf2[4];
struct saa6752hs_state *h;
+ unsigned size;
u32 crc;
unsigned char localPAT[256];
unsigned char localPMT[256];
@@ -557,45 +668,31 @@ static int saa6752hs_init(struct i2c_client* client)
h = i2c_get_clientdata(client);
/* Set video format - must be done first as it resets other settings */
- buf[0] = 0x41;
- buf[1] = h->video_format;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0x41, h->video_format);
/* Set number of lines in input signal */
- buf[0] = 0x40;
- buf[1] = 0x00;
- if (h->standard & V4L2_STD_525_60)
- buf[1] = 0x01;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
/* set bitrate */
- saa6752hs_set_bitrate(client, &h->params);
+ saa6752hs_set_bitrate(client, h);
/* Set GOP structure {3, 13} */
- buf[0] = 0x72;
- buf[1] = 0x03;
- buf[2] = 0x0D;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0x72, 0x030d);
/* Set minimum Q-scale {4} */
- buf[0] = 0x82;
- buf[1] = 0x04;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0x82, 0x04);
/* Set maximum Q-scale {12} */
- buf[0] = 0x83;
- buf[1] = 0x0C;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0x83, 0x0c);
/* Set Output Protocol */
- buf[0] = 0xD0;
- buf[1] = 0x81;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0xd0, 0x81);
/* Set video output stream format {TS} */
- buf[0] = 0xB0;
- buf[1] = 0x05;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0xb0, 0x05);
+
+ /* Set leading null byte for TS */
+ set_reg16(client, 0xf6, leading_null_bytes);
/* compute PAT */
memcpy(localPAT, PAT, sizeof(PAT));
@@ -608,7 +705,13 @@ static int saa6752hs_init(struct i2c_client* client)
localPAT[sizeof(PAT) - 1] = crc & 0xFF;
/* compute PMT */
- memcpy(localPMT, PMT, sizeof(PMT));
+ if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+ size = sizeof(PMT_AC3);
+ memcpy(localPMT, PMT_AC3, size);
+ } else {
+ size = sizeof(PMT);
+ memcpy(localPMT, PMT, size);
+ }
localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
localPMT[4] = h->params.ts_pid_pmt & 0xff;
localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
@@ -617,40 +720,28 @@ static int saa6752hs_init(struct i2c_client* client)
localPMT[21] = h->params.ts_pid_video & 0xFF;
localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
localPMT[26] = h->params.ts_pid_audio & 0xFF;
- crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
- localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
- localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
- localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
- localPMT[sizeof(PMT) - 1] = crc & 0xFF;
+ crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
+ localPMT[size - 4] = (crc >> 24) & 0xFF;
+ localPMT[size - 3] = (crc >> 16) & 0xFF;
+ localPMT[size - 2] = (crc >> 8) & 0xFF;
+ localPMT[size - 1] = crc & 0xFF;
/* Set Audio PID */
- buf[0] = 0xC1;
- buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_audio & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc1, h->params.ts_pid_audio);
/* Set Video PID */
- buf[0] = 0xC0;
- buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_video & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc0, h->params.ts_pid_video);
/* Set PCR PID */
- buf[0] = 0xC4;
- buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_pcr & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc4, h->params.ts_pid_pcr);
/* Send SI tables */
- i2c_master_send(client,localPAT,sizeof(PAT));
- i2c_master_send(client,localPMT,sizeof(PMT));
+ i2c_master_send(client, localPAT, sizeof(PAT));
+ i2c_master_send(client, localPMT, size);
/* mute then unmute audio. This removes buzzing artefacts */
- buf[0] = 0xa4;
- buf[1] = 1;
- i2c_master_send(client, buf, 2);
- buf[1] = 0;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0xa4, 1);
+ set_reg8(client, 0xa4, 0);
/* start it going */
saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
@@ -688,45 +779,6 @@ static int saa6752hs_init(struct i2c_client* client)
return 0;
}
-static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- struct saa6752hs_state *h;
-
-
- if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
- return -ENOMEM;
- h->client = client_template;
- h->params = param_defaults;
- h->client.adapter = adap;
- h->client.addr = addr;
-
- /* Assume 625 input lines */
- h->standard = 0;
-
- i2c_set_clientdata(&h->client, h);
- i2c_attach_client(&h->client);
-
- v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
- return 0;
-}
-
-static int saa6752hs_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, saa6752hs_attach);
- return 0;
-}
-
-static int saa6752hs_detach(struct i2c_client *client)
-{
- struct saa6752hs_state *h;
-
- h = i2c_get_clientdata(client);
- i2c_detach_client(client);
- kfree(h);
- return 0;
-}
-
static int
saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
@@ -737,14 +789,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
int i;
switch (cmd) {
+ case VIDIOC_INT_INIT:
+ /* apply settings and start encoder */
+ saa6752hs_init(client, *(u32 *)arg);
+ break;
case VIDIOC_S_EXT_CTRLS:
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
- if (ctrls->count == 0) {
- /* apply settings and start encoder */
- saa6752hs_init(client);
- break;
- }
/* fall through */
case VIDIOC_TRY_EXT_CTRLS:
case VIDIOC_G_EXT_CTRLS:
@@ -752,7 +803,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
params = h->params;
for (i = 0; i < ctrls->count; i++) {
- if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
+ err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, cmd);
+ if (err) {
ctrls->error_idx = i;
return err;
}
@@ -760,9 +812,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
h->params = params;
break;
case VIDIOC_QUERYCTRL:
- return saa6752hs_qctrl(&h->params, arg);
+ return saa6752hs_qctrl(h, arg);
case VIDIOC_QUERYMENU:
- return saa6752hs_qmenu(&h->params, arg);
+ return saa6752hs_qmenu(h, arg);
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
@@ -785,6 +837,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
case VIDIOC_S_STD:
h->standard = *((v4l2_std_id *) arg);
break;
+
+ case VIDIOC_G_CHIP_IDENT:
+ return v4l2_chip_ident_i2c_client(client,
+ arg, h->chip, h->revision);
+
default:
/* nothing */
break;
@@ -793,36 +850,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
return err;
}
-/* ----------------------------------------------------------------------- */
+static int saa6752hs_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+ u8 addr = 0x13;
+ u8 data[12];
-static struct i2c_driver driver = {
- .driver = {
- .name = "saa6752hs",
- },
- .id = I2C_DRIVERID_SAA6752HS,
- .attach_adapter = saa6752hs_probe,
- .detach_client = saa6752hs_detach,
- .command = saa6752hs_command,
-};
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+ if (h == NULL)
+ return -ENOMEM;
-static struct i2c_client client_template =
-{
- .name = "saa6752hs",
- .driver = &driver,
-};
+ i2c_master_send(client, &addr, 1);
+ i2c_master_recv(client, data, sizeof(data));
+ h->chip = V4L2_IDENT_SAA6752HS;
+ h->revision = (data[8] << 8) | data[9];
+ h->has_ac3 = 0;
+ if (h->revision == 0x0206) {
+ h->chip = V4L2_IDENT_SAA6752HS_AC3;
+ h->has_ac3 = 1;
+ v4l_info(client, "support AC-3\n");
+ }
+ h->params = param_defaults;
+ h->standard = 0; /* Assume 625 input lines */
-static int __init saa6752hs_init_module(void)
-{
- return i2c_add_driver(&driver);
+ i2c_set_clientdata(client, h);
+ return 0;
}
-static void __exit saa6752hs_cleanup_module(void)
+static int saa6752hs_remove(struct i2c_client *client)
{
- i2c_del_driver(&driver);
+ kfree(i2c_get_clientdata(client));
+ return 0;
}
-module_init(saa6752hs_init_module);
-module_exit(saa6752hs_cleanup_module);
+static const struct i2c_device_id saa6752hs_id[] = {
+ { "saa6752hs", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa6752hs",
+ .driverid = I2C_DRIVERID_SAA6752HS,
+ .command = saa6752hs_command,
+ .probe = saa6752hs_probe,
+ .remove = saa6752hs_remove,
+ .id_table = saa6752hs_id,
+};
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 9929d20320b..26194a0ce92 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -488,10 +488,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
period_size = params_period_bytes(hw_params);
periods = params_periods(hw_params);
- snd_assert(period_size >= 0x100 && period_size <= 0x10000,
- return -EINVAL);
- snd_assert(periods >= 4, return -EINVAL);
- snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL);
+ if (period_size < 0x100 || period_size > 0x10000)
+ return -EINVAL;
+ if (periods < 4)
+ return -EINVAL;
+ if (period_size * periods > 1024 * 1024)
+ return -EINVAL;
dev = saa7134->dev;
@@ -942,7 +944,8 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
unsigned int idx;
int err;
- snd_assert(chip != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip))
+ return -EINVAL;
strcpy(card->mixername, "SAA7134 Mixer");
for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 98364d171de..ddc5402c5fb 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -3260,6 +3260,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
/* Thomas Genty <tomlohave@gmail.com> */
+ /* David Bentham <db260179@hotmail.com> */
.name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_TDA8290,
@@ -3268,23 +3269,26 @@ struct saa7134_board saa7134_boards[] = {
.radio_addr = ADDR_UNSET,
.tuner_config = 1,
.mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 0x0200100,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
.tv = 1,
- },{
- .name = name_comp1,
- .vmux = 3,
- .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
- },{
- .name = name_svideo,
- .vmux = 8,
- .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
- }},
+ .gpio = 0x0000100,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
.radio = {
.name = name_radio,
- .amux = TV,
+ .amux = TV,
+ .gpio = 0x0200100,
},
},
[SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
@@ -3388,6 +3392,42 @@ struct saa7134_board saa7134_boards[] = {
.amux = 0,
},
},
+ [SAA7134_BOARD_ENCORE_ENLTV_FM53] = {
+ .name = "Encore ENLTV-FM v5.3",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_TNF_5335MF,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x7000,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = 1,
+ .tv = 1,
+ .gpio = 0x50000,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = 2,
+ .gpio = 0x2000,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = 2,
+ .gpio = 0x2000,
+ } },
+ .radio = {
+ .name = name_radio,
+ .vmux = 1,
+ .amux = 1,
+ },
+ .mute = {
+ .name = name_mute,
+ .gpio = 0xf000,
+ .amux = 0,
+ },
+ },
[SAA7134_BOARD_CINERGY_HT_PCI] = {
.name = "Terratec Cinergy HT PCI",
.audio_clock = 0x00187de7,
@@ -3631,6 +3671,40 @@ struct saa7134_board saa7134_boards[] = {
.tv = 1,
}},
},
+ [SAA7134_BOARD_AVERMEDIA_M135A] = {
+ .name = "Avermedia PCI pure analog (M135A)",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tuner_config = 2,
+ .gpiomask = 0x020200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x00200000,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x01,
+ },
+ },
[SAA7134_BOARD_BEHOLD_401] = {
/* Beholder Intl. Ltd. 2008 */
/*Dmitry Belimov <d.belimov@gmail.com> */
@@ -4409,6 +4483,129 @@ struct saa7134_board saa7134_boards[] = {
/* no DVB support for now */
/* .mpeg = SAA7134_MPEG_DVB, */
},
+ [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
+ .name = "Asus Tiger 3in1",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tuner_config = 2,
+ .gpiomask = 1 << 21,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp,
+ .vmux = 0,
+ .amux = LINE2,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_REAL_ANGEL_220] = {
+ .name = "Zogis Real Angel 220",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_TNF_5335MF,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x801a8087,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 3,
+ .amux = LINE2,
+ .tv = 1,
+ .gpio = 0x624000,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ .gpio = 0x624000,
+ }, {
+ .name = name_svideo,
+ .vmux = 1,
+ .amux = LINE1,
+ .gpio = 0x624000,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x624001,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ },
+ },
+ [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = {
+ .name = "ADS Tech Instant HDTV",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TUV1236D,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp,
+ .vmux = 4,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ },
+ [SAA7134_BOARD_ASUSTeK_TIGER] = {
+ .name = "Asus Tiger Rev:1.00",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tuner_config = 0,
+ .mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 0x0200000,
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ }, {
+ .name = name_comp2,
+ .vmux = 0,
+ .amux = LINE2,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -4777,6 +4974,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xf11d,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_M135A,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = PCI_VENDOR_ID_PHILIPS,
.subdevice = 0x2004,
@@ -5157,6 +5360,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1a7f,
+ .subdevice = 0x2008,
+ .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x153b,
.subdevice = 0x1175,
@@ -5183,8 +5392,8 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1043,
- .subdevice = 0x4857,
- .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+ .subdevice = 0x4857, /* REV:1.00 */
+ .driver_data = SAA7134_BOARD_ASUSTeK_TIGER,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5415,6 +5624,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_VIDEOMATE_T750,
}, {
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+ .subvendor = 0x1421,
+ .subdevice = 0x0380,
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5169,
.subdevice = 0x1502,
@@ -5432,6 +5647,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0xf636,
.driver_data = SAA7134_BOARD_AVERMEDIA_M103,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1043,
+ .subdevice = 0x4878, /* REV:1.02G */
+ .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5540,7 +5761,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev,
return 0;
}
-int saa7134_tuner_callback(void *priv, int command, int arg)
+int saa7134_tuner_callback(void *priv, int component, int command, int arg)
{
struct saa7134_dev *dev = priv;
if (dev != NULL) {
@@ -5620,6 +5841,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
case SAA7134_BOARD_AVERMEDIA_777:
+ case SAA7134_BOARD_AVERMEDIA_M135A:
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
@@ -5644,6 +5866,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_A16AR:
case SAA7134_BOARD_ENCORE_ENLTV:
case SAA7134_BOARD_ENCORE_ENLTV_FM:
+ case SAA7134_BOARD_ENCORE_ENLTV_FM53:
case SAA7134_BOARD_10MOONSTVMASTER3:
case SAA7134_BOARD_BEHOLD_401:
case SAA7134_BOARD_BEHOLD_403:
@@ -5656,6 +5879,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_505FM:
case SAA7134_BOARD_BEHOLD_507_9FM:
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
+ case SAA7134_BOARD_REAL_ANGEL_220:
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
@@ -5745,6 +5969,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_PINNACLE_PCTV_110i:
case SAA7134_BOARD_PINNACLE_PCTV_310i:
case SAA7134_BOARD_UPMOST_PURPLE_TV:
+ case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
case SAA7134_BOARD_BEHOLD_607_9FM:
case SAA7134_BOARD_BEHOLD_M6:
@@ -5987,6 +6212,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_PINNACLE_PCTV_310i:
case SAA7134_BOARD_KWORLD_DVBT_210:
case SAA7134_BOARD_TEVION_DVBT_220RF:
+ case SAA7134_BOARD_ASUSTeK_TIGER:
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
case SAA7134_BOARD_MEDION_MD8800_QUADRO:
@@ -6002,6 +6228,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
i2c_transfer(&dev->i2c_adap, &msg, 1);
break;
}
+ case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+ {
+ u8 data[] = { 0x3c, 0x33, 0x60};
+ struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+ .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+ break;
+ }
case SAA7134_BOARD_FLYDVB_TRIO:
{
u8 data[] = { 0x3c, 0x33, 0x62};
@@ -6027,6 +6261,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
i2c_transfer(&dev->i2c_adap, &msg, 1);
break;
}
+ case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
case SAA7134_BOARD_KWORLD_ATSC110:
{
/* enable tuner */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 75d618415f4..b686bfabbde 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -215,7 +215,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
{
__le32 *cpu;
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr = 0;
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
if (NULL == cpu)
@@ -359,32 +359,6 @@ void saa7134_buffer_timeout(unsigned long data)
spin_unlock_irqrestore(&dev->slock,flags);
}
-/* resends a current buffer in queue after resume */
-
-static int saa7134_buffer_requeue(struct saa7134_dev *dev,
- struct saa7134_dmaqueue *q)
-{
- struct saa7134_buf *buf, *next;
-
- assert_spin_locked(&dev->slock);
-
- buf = q->curr;
- next = buf;
- dprintk("buffer_requeue\n");
-
- if (!buf)
- return 0;
-
- dprintk("buffer_requeue : resending active buffers \n");
-
- if (!list_empty(&q->queue))
- next = list_entry(q->queue.next, struct saa7134_buf,
- vb.queue);
- buf->activate(dev, buf, next);
-
- return 0;
-}
-
/* ------------------------------------------------------------------ */
int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -442,9 +416,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
/* TS capture -- dma 5 */
if (dev->ts_q.curr) {
ctrl |= SAA7134_MAIN_CTRL_TE5;
- irq |= SAA7134_IRQ1_INTE_RA2_3 |
- SAA7134_IRQ1_INTE_RA2_2 |
- SAA7134_IRQ1_INTE_RA2_1 |
+ irq |= SAA7134_IRQ1_INTE_RA2_1 |
SAA7134_IRQ1_INTE_RA2_0;
}
@@ -727,6 +699,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev)
irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
}
+ if (dev->has_remote == SAA7134_REMOTE_I2C) {
+ request_module("ir-kbd-i2c");
+ }
+
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, irq2_mask);
@@ -1139,6 +1115,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
+
+/* resends a current buffer in queue after resume */
+static int saa7134_buffer_requeue(struct saa7134_dev *dev,
+ struct saa7134_dmaqueue *q)
+{
+ struct saa7134_buf *buf, *next;
+
+ assert_spin_locked(&dev->slock);
+
+ buf = q->curr;
+ next = buf;
+ dprintk("buffer_requeue\n");
+
+ if (!buf)
+ return 0;
+
+ dprintk("buffer_requeue : resending active buffers \n");
+
+ if (!list_empty(&q->queue))
+ next = list_entry(q->queue.next, struct saa7134_buf,
+ vb.queue);
+ buf->activate(dev, buf, next);
+
+ return 0;
+}
+
static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
{
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index be48b9b66a6..8c46115d4c7 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -535,11 +535,16 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
struct tda1004x_config *cdec_conf,
struct tda827x_config *tuner_conf)
{
- dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
- if (dev->dvb.frontend) {
+ struct videobuf_dvb_frontend *fe0;
+
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+
+ fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+ if (fe0->dvb.frontend) {
if (cdec_conf->i2c_gate)
- dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
- if (dvb_attach(tda827x_attach, dev->dvb.frontend,
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+ if (dvb_attach(tda827x_attach, fe0->dvb.frontend,
cdec_conf->tuner_address,
&dev->i2c_adap, tuner_conf))
return 0;
@@ -553,7 +558,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
/* ------------------------------------------------------------------ */
static struct tda827x_config tda827x_cfg_0 = {
- .tuner_callback = saa7134_tuner_callback,
.init = philips_tda827x_tuner_init,
.sleep = philips_tda827x_tuner_sleep,
.config = 0,
@@ -561,7 +565,6 @@ static struct tda827x_config tda827x_cfg_0 = {
};
static struct tda827x_config tda827x_cfg_1 = {
- .tuner_callback = saa7134_tuner_callback,
.init = philips_tda827x_tuner_init,
.sleep = philips_tda827x_tuner_sleep,
.config = 1,
@@ -569,7 +572,6 @@ static struct tda827x_config tda827x_cfg_1 = {
};
static struct tda827x_config tda827x_cfg_2 = {
- .tuner_callback = saa7134_tuner_callback,
.init = philips_tda827x_tuner_init,
.sleep = philips_tda827x_tuner_sleep,
.config = 2,
@@ -577,7 +579,6 @@ static struct tda827x_config tda827x_cfg_2 = {
};
static struct tda827x_config tda827x_cfg_2_sw42 = {
- .tuner_callback = saa7134_tuner_callback,
.init = philips_tda827x_tuner_init,
.sleep = philips_tda827x_tuner_sleep,
.config = 2,
@@ -799,6 +800,20 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
.request_firmware = philips_tda1004x_request_firmware
};
+static struct tda1004x_config asus_tiger_3in1_config = {
+ .demod_address = 0x0b,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X,
+ .gpio_config = TDA10046_GP11_I,
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+ .antenna_switch = 1,
+ .request_firmware = philips_tda1004x_request_firmware
+};
+
/* ------------------------------------------------------------------
* special case: this card uses saa713x GPIO22 for the mode switch
*/
@@ -822,7 +837,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
}
static struct tda827x_config ads_duo_cfg = {
- .tuner_callback = saa7134_tuner_callback,
.init = ads_duo_tuner_init,
.sleep = ads_duo_tuner_sleep,
.config = 0
@@ -935,12 +949,30 @@ static int dvb_init(struct saa7134_dev *dev)
{
int ret;
int attach_xc3028 = 0;
+ struct videobuf_dvb_frontend *fe0;
+
+ /* FIXME: add support for multi-frontend */
+ mutex_init(&dev->frontends.lock);
+ INIT_LIST_HEAD(&dev->frontends.felist);
+ dev->frontends.active_fe_id = 0;
+
+ printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
+
+ if (videobuf_dvb_alloc_frontend(&dev->frontends, 1) == NULL) {
+ printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
/* init struct videobuf_dvb */
dev->ts.nr_bufs = 32;
dev->ts.nr_packets = 32*4;
- dev->dvb.name = dev->name;
- videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+ fe0->dvb.name = dev->name;
+ videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
@@ -950,47 +982,47 @@ static int dvb_init(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
dprintk("pinnacle 300i dvb setup\n");
- dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
+ fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
}
break;
case SAA7134_BOARD_AVERMEDIA_777:
case SAA7134_BOARD_AVERMEDIA_A16AR:
dprintk("avertv 777 dvb setup\n");
- dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+ fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend) {
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0x61,
TUNER_PHILIPS_TD1316);
}
break;
case SAA7134_BOARD_AVERMEDIA_A16D:
dprintk("AverMedia A16D dvb setup\n");
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&avermedia_xc3028_mt352_dev,
&dev->i2c_adap);
attach_xc3028 = 1;
break;
case SAA7134_BOARD_MD7134:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&medion_cardbus,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend) {
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&dev->i2c_adap, medion_cardbus.tuner_address,
TUNER_PHILIPS_FMD1216ME_MK3);
}
break;
case SAA7134_BOARD_PHILIPS_TOUGH:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&philips_tu1216_60_config,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+ fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
}
break;
case SAA7134_BOARD_FLYDVBTDUO:
@@ -1001,24 +1033,24 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_PHILIPS_EUROPA:
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&philips_europa_config,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
- dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
- dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
- dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+ if (fe0->dvb.frontend) {
+ dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+ fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+ fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+ fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+ fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
}
break;
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&philips_tu1216_61_config,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+ fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
}
break;
case SAA7134_BOARD_KWORLD_DVBT_210:
@@ -1057,14 +1089,14 @@ static int dvb_init(struct saa7134_dev *dev)
&tda827x_cfg_0) < 0)
goto dettach_frontend;
} else { /* satellite */
- dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
- if (dev->dvb.frontend) {
- if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
&dev->i2c_adap, 0) == NULL) {
wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
goto dettach_frontend;
}
- if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+ if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
0x08, 0, 0) == NULL) {
wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
goto dettach_frontend;
@@ -1074,11 +1106,11 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&ads_tech_duo_config,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- if (dvb_attach(tda827x_attach,dev->dvb.frontend,
+ if (fe0->dvb.frontend) {
+ if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
ads_tech_duo_config.tuner_address, &dev->i2c_adap,
&ads_duo_cfg) == NULL) {
wprintk("no tda827x tuner found at addr: %02x\n",
@@ -1099,15 +1131,15 @@ static int dvb_init(struct saa7134_dev *dev)
&tda827x_cfg_0) < 0)
goto dettach_frontend;
} else { /* satellite */
- dev->dvb.frontend = dvb_attach(tda10086_attach,
+ fe0->dvb.frontend = dvb_attach(tda10086_attach,
&flydvbs, &dev->i2c_adap);
- if (dev->dvb.frontend) {
- struct dvb_frontend *fe = dev->dvb.frontend;
+ if (fe0->dvb.frontend) {
+ struct dvb_frontend *fe = fe0->dvb.frontend;
u8 dev_id = dev->eedata[2];
u8 data = 0xc4;
struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
- if (dvb_attach(tda826x_attach, dev->dvb.frontend,
+ if (dvb_attach(tda826x_attach, fe0->dvb.frontend,
0x60, &dev->i2c_adap, 0) == NULL) {
wprintk("%s: Medion Quadro, no tda826x "
"found !\n", __func__);
@@ -1141,30 +1173,31 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
- dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+ fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
&dev->i2c_adap);
- if (dev->dvb.frontend)
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ if (fe0->dvb.frontend)
+ dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61,
NULL, DVB_PLL_TDHU2);
break;
+ case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
case SAA7134_BOARD_KWORLD_ATSC110:
- dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+ fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
&dev->i2c_adap);
- if (dev->dvb.frontend)
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend)
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0x61,
TUNER_PHILIPS_TUV1236D);
break;
case SAA7134_BOARD_FLYDVBS_LR300:
- dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+ if (fe0->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
wprintk("%s: No tda826x found!\n", __func__);
goto dettach_frontend;
}
- if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+ if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0x08, 0, 0) == NULL) {
wprintk("%s: No ISL6421 found!\n", __func__);
goto dettach_frontend;
@@ -1172,25 +1205,25 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&medion_cardbus,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
- dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+ if (fe0->dvb.frontend) {
+ dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+ fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&dev->i2c_adap, medion_cardbus.tuner_address,
TUNER_PHILIPS_FMD1216ME_MK3);
}
break;
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
+ fe0->dvb.frontend = dvb_attach(tda10046_attach,
&philips_europa_config,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+ fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
}
break;
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
@@ -1229,15 +1262,15 @@ static int dvb_init(struct saa7134_dev *dev)
goto dettach_frontend;
break;
case SAA7134_BOARD_PHILIPS_SNAKE:
- dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+ fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
- if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+ if (fe0->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
wprintk("%s: No tda826x found!\n", __func__);
goto dettach_frontend;
}
- if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+ if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0, 0) == NULL) {
wprintk("%s: No lnbp21 found!\n", __func__);
goto dettach_frontend;
@@ -1259,24 +1292,24 @@ static int dvb_init(struct saa7134_dev *dev)
saa7134_set_gpio(dev, 25, 0);
msleep(10);
saa7134_set_gpio(dev, 25, 1);
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&avermedia_xc3028_mt352_dev,
&dev->i2c_adap);
attach_xc3028 = 1;
break;
case SAA7134_BOARD_MD7134_BRIDGE_2:
- dev->dvb.frontend = dvb_attach(tda10086_attach,
+ fe0->dvb.frontend = dvb_attach(tda10086_attach,
&sd1878_4m, &dev->i2c_adap);
- if (dev->dvb.frontend) {
+ if (fe0->dvb.frontend) {
struct dvb_frontend *fe;
- if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+ if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
wprintk("%s: MD7134 DVB-S, no SD1878 "
"found !\n", __func__);
goto dettach_frontend;
}
/* we need to open the i2c gate (we know it exists) */
- fe = dev->dvb.frontend;
+ fe = fe0->dvb.frontend;
fe->ops.i2c_gate_ctrl(fe, 1);
if (dvb_attach(isl6405_attach, fe,
&dev->i2c_adap, 0x08, 0, 0) == NULL) {
@@ -1295,11 +1328,41 @@ static int dvb_init(struct saa7134_dev *dev)
saa7134_set_gpio(dev, 25, 0);
msleep(10);
saa7134_set_gpio(dev, 25, 1);
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&avermedia_xc3028_mt352_dev,
&dev->i2c_adap);
attach_xc3028 = 1;
break;
+ case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+ if (!use_frontend) { /* terrestrial */
+ if (configure_tda827x_fe(dev, &asus_tiger_3in1_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
+ } else { /* satellite */
+ fe0->dvb.frontend = dvb_attach(tda10086_attach,
+ &flydvbs, &dev->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if (dvb_attach(tda826x_attach,
+ fe0->dvb.frontend, 0x60,
+ &dev->i2c_adap, 0) == NULL) {
+ wprintk("%s: Asus Tiger 3in1, no "
+ "tda826x found!\n", __func__);
+ goto dettach_frontend;
+ }
+ if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+ &dev->i2c_adap, 0, 0) == NULL) {
+ wprintk("%s: Asus Tiger 3in1, no lnbp21"
+ " found!\n", __func__);
+ goto dettach_frontend;
+ }
+ }
+ }
+ break;
+ case SAA7134_BOARD_ASUSTeK_TIGER:
+ if (configure_tda827x_fe(dev, &philips_tiger_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
+ break;
default:
wprintk("Huh? unknown DVB card?\n");
break;
@@ -1312,10 +1375,10 @@ static int dvb_init(struct saa7134_dev *dev)
.i2c_addr = 0x61,
};
- if (!dev->dvb.frontend)
+ if (!fe0->dvb.frontend)
return -1;
- fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+ fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
if (!fe) {
printk(KERN_ERR "%s/2: xc3028 attach failed\n",
dev->name);
@@ -1323,38 +1386,47 @@ static int dvb_init(struct saa7134_dev *dev)
}
}
- if (NULL == dev->dvb.frontend) {
+ if (NULL == fe0->dvb.frontend) {
printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
return -1;
}
+ /* define general-purpose callback pointer */
+ fe0->dvb.frontend->callback = saa7134_tuner_callback;
/* register everything else */
- ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
- adapter_nr);
+ ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ &dev->pci->dev, adapter_nr, 0);
/* this sequence is necessary to make the tda1004x load its firmware
* and to enter analog mode of hybrid boards
*/
if (!ret) {
- if (dev->dvb.frontend->ops.init)
- dev->dvb.frontend->ops.init(dev->dvb.frontend);
- if (dev->dvb.frontend->ops.sleep)
- dev->dvb.frontend->ops.sleep(dev->dvb.frontend);
- if (dev->dvb.frontend->ops.tuner_ops.sleep)
- dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend);
+ if (fe0->dvb.frontend->ops.init)
+ fe0->dvb.frontend->ops.init(fe0->dvb.frontend);
+ if (fe0->dvb.frontend->ops.sleep)
+ fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend);
+ if (fe0->dvb.frontend->ops.tuner_ops.sleep)
+ fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
}
return ret;
dettach_frontend:
- if (dev->dvb.frontend)
- dvb_frontend_detach(dev->dvb.frontend);
- dev->dvb.frontend = NULL;
+ if (fe0->dvb.frontend)
+ dvb_frontend_detach(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
return -1;
}
static int dvb_fini(struct saa7134_dev *dev)
{
+ struct videobuf_dvb_frontend *fe0;
+
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
+
/* FIXME: I suspect that this code is bogus, since the entry for
Pinnacle 300I DVB-T PAL already defines the proper init to allow
the detection of mt2032 (TDA9887_PORT2_INACTIVE)
@@ -1374,7 +1446,7 @@ static int dvb_fini(struct saa7134_dev *dev)
u8 data = 0x80;
struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
struct dvb_frontend *fe;
- fe = dev->dvb.frontend;
+ fe = fe0->dvb.frontend;
if (fe->ops.i2c_gate_ctrl) {
fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(&dev->i2c_adap, &msg, 1);
@@ -1382,8 +1454,8 @@ static int dvb_fini(struct saa7134_dev *dev)
}
}
}
- if (dev->dvb.frontend)
- videobuf_dvb_unregister(&dev->dvb);
+ if (fe0->dvb.frontend)
+ videobuf_dvb_unregister_bus(&dev->frontends);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index c0c5d7509c2..9a8766a78a0 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -29,6 +29,7 @@
#include <media/saa6752hs.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
/* ------------------------------------------------------------------ */
@@ -63,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
static int ts_init_encoder(struct saa7134_dev* dev)
{
- struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 };
+ u32 leading_null_bytes = 0;
+ /* If more cards start to need this, then this
+ should probably be added to the card definitions. */
+ switch (dev->board) {
+ case SAA7134_BOARD_BEHOLD_M6:
+ case SAA7134_BOARD_BEHOLD_M63:
+ case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+ leading_null_bytes = 1;
+ break;
+ }
ts_reset_encoder(dev);
- saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls);
+ saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes);
dev->empress_started = 1;
return 0;
}
@@ -79,9 +89,11 @@ static int ts_open(struct inode *inode, struct file *file)
struct saa7134_dev *dev;
int err;
+ lock_kernel();
list_for_each_entry(dev, &saa7134_devlist, devlist)
if (dev->empress_dev && dev->empress_dev->minor == minor)
goto found;
+ unlock_kernel();
return -ENODEV;
found:
@@ -103,6 +115,7 @@ static int ts_open(struct inode *inode, struct file *file)
done_up:
mutex_unlock(&dev->empress_tsq.vb_lock);
done:
+ unlock_kernel();
return err;
}
@@ -290,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv,
return videobuf_streamoff(&dev->empress_tsq);
}
-static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
- unsigned int cmd, void *arg)
-{
- if (dev->mpeg_i2c_client == NULL)
- return -EINVAL;
- return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
- cmd, arg);
-}
-
static int empress_s_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctrls)
{
@@ -400,6 +404,39 @@ static int empress_querymenu(struct file *file, void *priv,
return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
}
+static int empress_g_chip_ident(struct file *file, void *fh,
+ struct v4l2_chip_ident *chip)
+{
+ struct saa7134_dev *dev = file->private_data;
+
+ chip->ident = V4L2_IDENT_NONE;
+ chip->revision = 0;
+ if (dev->mpeg_i2c_client == NULL)
+ return -EINVAL;
+ if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+ chip->match_chip == I2C_DRIVERID_SAA6752HS)
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+ if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR &&
+ chip->match_chip == dev->mpeg_i2c_client->addr)
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+ return -EINVAL;
+}
+
+static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_dev *dev = file->private_data;
+
+ return saa7134_s_std_internal(dev, NULL, id);
+}
+
+static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_dev *dev = file->private_data;
+
+ *id = dev->tvnorm->id;
+ return 0;
+}
+
static const struct file_operations ts_fops =
{
.owner = THIS_MODULE,
@@ -428,11 +465,13 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
.vidioc_enum_input = empress_enum_input,
.vidioc_g_input = empress_g_input,
.vidioc_s_input = empress_s_input,
-
.vidioc_queryctrl = empress_queryctrl,
.vidioc_querymenu = empress_querymenu,
.vidioc_g_ctrl = empress_g_ctrl,
.vidioc_s_ctrl = empress_s_ctrl,
+ .vidioc_g_chip_ident = empress_g_chip_ident,
+ .vidioc_s_std = empress_s_std,
+ .vidioc_g_std = empress_g_std,
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 5f713e63768..20c1b33caf7 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -337,6 +337,7 @@ static int attach_inform(struct i2c_client *client)
case 0x47:
case 0x71:
case 0x2d:
+ case 0x30:
{
struct IR_i2c *ir = i2c_get_clientdata(client);
d1printk("%s i2c IR detected (%s).\n",
@@ -427,6 +428,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev,
i2c_clients_command(&dev->i2c_adap, cmd, arg);
}
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+ unsigned int cmd, void *arg)
+{
+ if (dev->mpeg_i2c_client == NULL)
+ return -EINVAL;
+ return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
+ cmd, arg);
+}
+EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752);
+
int saa7134_i2c_register(struct saa7134_dev *dev)
{
dev->i2c_adap = saa7134_adap_template;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ad08d13dffd..c53fd5f9f6b 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
#define i2cdprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
-/** rc5 functions */
+/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
static int saa7134_rc5_irq(struct saa7134_dev *dev);
+static int saa7134_nec_irq(struct saa7134_dev *dev);
+static void nec_task(unsigned long data);
+static void saa7134_nec_timer(unsigned long data);
/* -------------------- GPIO generic keycode builder -------------------- */
@@ -115,6 +118,53 @@ static int build_key(struct saa7134_dev *dev)
/* --------------------- Chip specific I2C key builders ----------------- */
+static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
+ u32 *ir_raw)
+{
+ unsigned char b;
+ int gpio;
+
+ /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
+ struct saa7134_dev *dev = ir->c.adapter->algo_data;
+ if (dev == NULL) {
+ dprintk("get_key_msi_tvanywhere_plus: "
+ "gir->c.adapter->algo_data is NULL!\n");
+ return -EIO;
+ }
+
+ /* rising SAA7134_GPIO_GPRESCAN reads the status */
+
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+ gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+ /* GPIO&0x40 is pulsed low when a button is pressed. Don't do
+ I2C receive if gpio&0x40 is not low. */
+
+ if (gpio & 0x40)
+ return 0; /* No button press */
+
+ /* GPIO says there is a button press. Get it. */
+
+ if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+ i2cdprintk("read error\n");
+ return -EIO;
+ }
+
+ /* No button press */
+
+ if (b == 0xff)
+ return 0;
+
+ /* Button pressed */
+
+ dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
+ *ir_key = b;
+ *ir_raw = b;
+ return 1;
+}
+
static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char b;
@@ -280,7 +330,9 @@ void saa7134_input_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;
- if (!ir->polling && !ir->rc5_gpio) {
+ if (ir->nec_gpio) {
+ saa7134_nec_irq(dev);
+ } else if (!ir->polling && !ir->rc5_gpio) {
build_key(dev);
} else if (ir->rc5_gpio) {
saa7134_rc5_irq(dev);
@@ -316,6 +368,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
ir->addr = 0x17;
ir->rc5_key_timeout = ir_rc5_key_timeout;
ir->rc5_remote_gap = ir_rc5_remote_gap;
+ } else if (ir->nec_gpio) {
+ setup_timer(&ir->timer_keyup, saa7134_nec_timer,
+ (unsigned long)dev);
+ tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
}
}
@@ -335,6 +391,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
u32 mask_keyup = 0;
int polling = 0;
int rc5_gpio = 0;
+ int nec_gpio = 0;
int ir_type = IR_TYPE_OTHER;
int err;
@@ -391,6 +448,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
+ case SAA7134_BOARD_AVERMEDIA_M135A:
+ ir_codes = ir_codes_avermedia_m135a;
+ mask_keydown = 0x0040000;
+ mask_keycode = 0x00013f;
+ nec_gpio = 1;
+ break;
case SAA7134_BOARD_AVERMEDIA_777:
case SAA7134_BOARD_AVERMEDIA_A16AR:
ir_codes = ir_codes_avermedia;
@@ -499,6 +562,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keyup = 0x040000;
polling = 50; // ms
break;
+ case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+ ir_codes = ir_codes_encore_enltv_fm53;
+ mask_keydown = 0x0040000;
+ mask_keycode = 0x00007f;
+ nec_gpio = 1;
+ break;
case SAA7134_BOARD_10MOONSTVMASTER3:
ir_codes = ir_codes_encore_enltv;
mask_keycode = 0x5f80000;
@@ -511,6 +580,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keydown = 0xf00000;
polling = 50; /* ms */
break;
+ case SAA7134_BOARD_REAL_ANGEL_220:
+ ir_codes = ir_codes_real_audio_220_32_keys;
+ mask_keycode = 0x3f00;
+ mask_keyup = 0x4000;
+ polling = 50; /* ms */
+ break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
@@ -533,6 +608,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
ir->mask_keyup = mask_keyup;
ir->polling = polling;
ir->rc5_gpio = rc5_gpio;
+ ir->nec_gpio = nec_gpio;
/* init input device */
snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -612,6 +688,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
ir->get_key = get_key_purpletv;
ir->ir_codes = ir_codes_purpletv;
break;
+ case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
+ snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus");
+ ir->get_key = get_key_msi_tvanywhere_plus;
+ ir->ir_codes = ir_codes_msi_tvanywhere_plus;
+ break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
ir->get_key = get_key_hvr1110;
@@ -675,8 +756,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev)
return 1;
}
-/* ----------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
+
+/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
+ The first pulse (start) has 9 + 4.5 ms
*/
+
+static void saa7134_nec_timer(unsigned long data)
+{
+ struct saa7134_dev *dev = (struct saa7134_dev *) data;
+ struct card_ir *ir = dev->remote;
+
+ dprintk("Cancel key repeat\n");
+
+ ir_input_nokey(ir->dev, &ir->ir);
+}
+
+static void nec_task(unsigned long data)
+{
+ struct saa7134_dev *dev = (struct saa7134_dev *) data;
+ struct card_ir *ir;
+ struct timeval tv;
+ int count, pulse, oldpulse, gap;
+ u32 ircode = 0, not_code = 0;
+ int ngap = 0;
+
+ if (!data) {
+ printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n");
+ /* GPIO will be kept disabled */
+ return;
+ }
+
+ ir = dev->remote;
+
+ /* rising SAA7134_GPIO_GPRESCAN reads the status */
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+ oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
+ pulse = oldpulse;
+
+ do_gettimeofday(&tv);
+ ir->base_time = tv;
+
+ /* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
+ Unfortunately, using IRQ to decode pulse didn't work, since it uses
+ a pulse train of 38KHz. This means one pulse on each 52 us
+ */
+ do {
+ /* Wait until the end of pulse/space or 5 ms */
+ for (count = 0; count < 500; count++) {
+ udelay(10);
+ /* rising SAA7134_GPIO_GPRESCAN reads the status */
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
+ & ir->mask_keydown;
+ if (pulse != oldpulse)
+ break;
+ }
+
+ do_gettimeofday(&tv);
+ gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+ tv.tv_usec - ir->base_time.tv_usec;
+
+ if (!pulse) {
+ /* Bit 0 has 560 us, while bit 1 has 1120 us.
+ Do something only if bit == 1
+ */
+ if (ngap && (gap > 560 + 280)) {
+ unsigned int shift = ngap - 1;
+
+ /* Address first, then command */
+ if (shift < 8) {
+ shift += 8;
+ ircode |= 1 << shift;
+ } else if (shift < 16) {
+ not_code |= 1 << shift;
+ } else if (shift < 24) {
+ shift -= 16;
+ ircode |= 1 << shift;
+ } else {
+ shift -= 24;
+ not_code |= 1 << shift;
+ }
+ }
+ ngap++;
+ }
+
+
+ ir->base_time = tv;
+
+ /* TIMEOUT - Long pulse */
+ if (gap >= 5000)
+ break;
+ oldpulse = pulse;
+ } while (ngap < 32);
+
+ if (ngap == 32) {
+ /* FIXME: should check if not_code == ~ircode */
+ ir->code = ir_extract_bits(ircode, ir->mask_keycode);
+
+ dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n",
+ ir->code, ircode, not_code);
+
+ ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code);
+ } else
+ dprintk("Repeat last key\n");
+
+ /* Keep repeating the last key */
+ mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150));
+
+ saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
+}
+
+static int saa7134_nec_irq(struct saa7134_dev *dev)
+{
+ struct card_ir *ir = dev->remote;
+
+ saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
+ tasklet_schedule(&ir->tlet);
+
+ return 1;
+}
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index eae72fd60ce..ef55a59f0cd 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev,
saa7134_set_dmabits(dev);
mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT);
+
+ if (dev->ts_state == SAA7134_TS_BUFF_DONE) {
+ /* Clear TS cache */
+ dev->buff_cnt = 0;
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+ /* TS clock non-inverted */
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+ /* Start TS stream */
+ saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+ saa_writeb(SAA7134_TS_PARALLEL, 0xEC);
+ dev->ts_state = SAA7134_TS_STARTED;
+ }
+
return 0;
}
static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+ enum v4l2_field field)
{
struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
@@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
goto oops;
}
- /* dma: setup channel 5 (= TS) */
- control = SAA7134_RS_CONTROL_BURST_16 |
- SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
-
- saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff));
- saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff));
- saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
- saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE);
- saa_writel(SAA7134_RS_CONTROL(5),control);
+ dev->buff_cnt++;
+
+ if (dev->buff_cnt == dev->ts.nr_bufs) {
+ dev->ts_state = SAA7134_TS_BUFF_DONE;
+ /* dma: setup channel 5 (= TS) */
+ control = SAA7134_RS_CONTROL_BURST_16 |
+ SAA7134_RS_CONTROL_ME |
+ (buf->pt->dma >> 12);
+
+ saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff);
+ saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff);
+ /* TSNOPIT=0, TSCOLAP=0 */
+ saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00);
+ saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+ saa_writel(SAA7134_RS_CONTROL(5), control);
+ }
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
@@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
if (0 == *count)
*count = dev->ts.nr_bufs;
*count = saa7134_buffer_count(*size,*count);
+ dev->buff_cnt = 0;
+ dev->ts_state = SAA7134_TS_STOPPED;
return 0;
}
@@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dev *dev = q->priv_data;
+ if (dev->ts_state == SAA7134_TS_STARTED) {
+ /* Stop TS transport */
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+ dev->ts_state = SAA7134_TS_STOPPED;
+ }
saa7134_dma_free(q,buf);
}
@@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev)
/* deactivate TS softreset */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
/* TSSOP high active, TSVAL high active, TSLOCK ignored */
- saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 68c26898186..02bb6747a39 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
if (card_in(dev, dev->ctl_input).tv)
saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+ /* Set the correct norm for the saa6752hs. This function
+ does nothing if there is no saa6752hs. */
+ saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);
}
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1330,6 +1333,8 @@ static int video_open(struct inode *inode, struct file *file)
struct saa7134_fh *fh;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int radio = 0;
+
+ lock_kernel();
list_for_each_entry(dev, &saa7134_devlist, devlist) {
if (dev->video_dev && (dev->video_dev->minor == minor))
goto found;
@@ -1342,6 +1347,7 @@ static int video_open(struct inode *inode, struct file *file)
goto found;
}
}
+ unlock_kernel();
return -ENODEV;
found:
@@ -1350,8 +1356,10 @@ static int video_open(struct inode *inode, struct file *file)
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ unlock_kernel();
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -1384,6 +1392,7 @@ static int video_open(struct inode *inode, struct file *file)
/* switch to video/vbi mode */
video_mux(dev,dev->ctl_input);
}
+ unlock_kernel();
return 0;
}
@@ -1790,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void *priv,
return 0;
}
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
unsigned long flags;
unsigned int i;
v4l2_std_id fixup;
int err;
- err = v4l2_prio_check(&dev->prio, &fh->prio);
- if (0 != err)
- return err;
+ /* When called from the empress code fh == NULL.
+ That needs to be fixed somehow, but for now this is
+ good enough. */
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ } else if (res_locked(dev, RESOURCE_OVERLAY)) {
+ /* Don't change the std from the mpeg device
+ if overlay is active. */
+ return -EBUSY;
+ }
for (i = 0; i < TVNORMS; i++)
if (*id == tvnorms[i].id)
@@ -1834,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
*id = tvnorms[i].id;
mutex_lock(&dev->lock);
- if (res_check(fh, RESOURCE_OVERLAY)) {
+ if (fh && res_check(fh, RESOURCE_OVERLAY)) {
spin_lock_irqsave(&dev->slock, flags);
stop_preview(dev, fh);
spin_unlock_irqrestore(&dev->slock, flags);
@@ -1851,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
mutex_unlock(&dev->lock);
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_fh *fh = priv;
+
+ return saa7134_s_std_internal(fh->dev, fh, id);
+}
+
+static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_fh *fh = priv;
+ struct saa7134_dev *dev = fh->dev;
+
+ *id = dev->tvnorm->id;
+ return 0;
+}
static int saa7134_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cap)
@@ -2077,18 +2110,6 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
return 0;
}
-static int saa7134_enum_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (0 != f->index)
- return -EINVAL;
-
- f->pixelformat = V4L2_PIX_FMT_GREY;
- strcpy(f->description, "vbi data");
-
- return 0;
-}
-
static int saa7134_g_fbuf(struct file *file, void *f,
struct v4l2_framebuffer *fb)
{
@@ -2379,7 +2400,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay,
.vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay,
.vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay,
- .vidioc_enum_fmt_vbi_cap = saa7134_enum_fmt_vbi_cap,
.vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
.vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
@@ -2391,6 +2411,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_qbuf = saa7134_qbuf,
.vidioc_dqbuf = saa7134_dqbuf,
.vidioc_s_std = saa7134_s_std,
+ .vidioc_g_std = saa7134_g_std,
.vidioc_enum_input = saa7134_enum_input,
.vidioc_g_input = saa7134_g_input,
.vidioc_s_input = saa7134_s_input,
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index a0884f639f6..24096d6e1ef 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -269,6 +269,12 @@ struct saa7134_format {
#define SAA7134_BOARD_BEHOLD_M6_EXTRA 144
#define SAA7134_BOARD_AVERMEDIA_M103 145
#define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
+#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147
+#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148
+#define SAA7134_BOARD_AVERMEDIA_M135A 149
+#define SAA7134_BOARD_REAL_ANGEL_220 150
+#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151
+#define SAA7134_BOARD_ASUSTeK_TIGER 152
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -462,6 +468,12 @@ struct saa7134_mpeg_ops {
void (*signal_change)(struct saa7134_dev *dev);
};
+enum saa7134_ts_status {
+ SAA7134_TS_STOPPED,
+ SAA7134_TS_BUFF_DONE,
+ SAA7134_TS_STARTED,
+};
+
/* global device status */
struct saa7134_dev {
struct list_head devlist;
@@ -555,6 +567,8 @@ struct saa7134_dev {
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
+ enum saa7134_ts_status ts_state;
+ unsigned int buff_cnt;
struct saa7134_mpeg_ops *mops;
struct i2c_client *mpeg_i2c_client;
@@ -567,7 +581,7 @@ struct saa7134_dev {
#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
/* SAA7134_MPEG_DVB only */
- struct videobuf_dvb dvb;
+ struct videobuf_dvb_frontends frontends;
int (*original_demod_sleep)(struct dvb_frontend *fe);
int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
@@ -644,7 +658,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
extern int saa7134_board_init1(struct saa7134_dev *dev);
extern int saa7134_board_init2(struct saa7134_dev *dev);
-int saa7134_tuner_callback(void *priv, int command, int arg);
+int saa7134_tuner_callback(void *priv, int component, int command, int arg);
/* ----------------------------------------------------------- */
@@ -654,6 +668,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev);
int saa7134_i2c_unregister(struct saa7134_dev *dev);
void saa7134_i2c_call_clients(struct saa7134_dev *dev,
unsigned int cmd, void *arg);
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+ unsigned int cmd, void *arg);
/* ----------------------------------------------------------- */
@@ -666,6 +682,7 @@ extern struct video_device saa7134_radio_template;
int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id);
int saa7134_videoport_init(struct saa7134_dev *dev);
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 02fda4eecea..6debb65152e 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -25,43 +25,25 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
#include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-#define I2C_NAME(s) (s)->name
-
-
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
/* ----------------------------------------------------------------------- */
struct saa7185 {
@@ -75,32 +57,24 @@ struct saa7185 {
int sat;
};
-#define I2C_SAA7185 0x88
-
/* ----------------------------------------------------------------------- */
-static inline int
-saa7185_read (struct i2c_client *client)
+static inline int saa7185_read(struct i2c_client *client)
{
return i2c_smbus_read_byte(client);
}
-static int
-saa7185_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+static int saa7185_write(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7185 *encoder = i2c_get_clientdata(client);
- dprintk(1, KERN_DEBUG "SAA7185: %02x set to %02x\n", reg, value);
+ v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value);
encoder->reg[reg] = value;
return i2c_smbus_write_byte_data(client, reg, value);
}
-static int
-saa7185_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int saa7185_write_block(struct i2c_client *client,
+ const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
@@ -121,18 +95,17 @@ saa7185_write_block (struct i2c_client *client,
encoder->reg[reg++] = data[1];
len -= 2;
data += 2;
- } while (len >= 2 && data[0] == reg &&
- block_len < 32);
- if ((ret = i2c_master_send(client, block_data,
- block_len)) < 0)
+ } while (len >= 2 && data[0] == reg && block_len < 32);
+ ret = i2c_master_send(client, block_data, block_len);
+ if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
- if ((ret = saa7185_write(client, reg,
- *data++)) < 0)
+ ret = saa7185_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
@@ -240,15 +213,11 @@ static const unsigned char init_ntsc[] = {
0x66, 0x21, /* FSC3 */
};
-static int
-saa7185_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct saa7185 *encoder = i2c_get_clientdata(client);
switch (cmd) {
-
case 0:
saa7185_write_block(client, init_common,
sizeof(init_common));
@@ -264,7 +233,6 @@ saa7185_command (struct i2c_client *client,
sizeof(init_pal));
break;
}
-
break;
case ENCODER_GET_CAPABILITIES:
@@ -276,8 +244,8 @@ saa7185_command (struct i2c_client *client,
VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
cap->inputs = 1;
cap->outputs = 1;
- }
break;
+ }
case ENCODER_SET_NORM:
{
@@ -286,7 +254,6 @@ saa7185_command (struct i2c_client *client,
//saa7185_write_block(client, init_common, sizeof(init_common));
switch (*iarg) {
-
case VIDEO_MODE_NTSC:
saa7185_write_block(client, init_ntsc,
sizeof(init_ntsc));
@@ -300,11 +267,10 @@ saa7185_command (struct i2c_client *client,
case VIDEO_MODE_SECAM:
default:
return -EINVAL;
-
}
encoder->norm = *iarg;
- }
break;
+ }
case ENCODER_SET_INPUT:
{
@@ -314,7 +280,6 @@ saa7185_command (struct i2c_client *client,
*iarg = 1: input is from ZR36060 */
switch (*iarg) {
-
case 0:
/* Switch RTCE to 1 */
saa7185_write(client, 0x61,
@@ -332,21 +297,19 @@ saa7185_command (struct i2c_client *client,
default:
return -EINVAL;
-
}
- }
break;
+ }
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
- if (*iarg != 0) {
+ if (*iarg != 0)
return -EINVAL;
- }
- }
break;
+ }
case ENCODER_ENABLE_OUTPUT:
{
@@ -356,8 +319,8 @@ saa7185_command (struct i2c_client *client,
saa7185_write(client, 0x61,
(encoder->reg[0x61] & 0xbf) |
(encoder->enable ? 0x00 : 0x40));
- }
break;
+ }
default:
return -EINVAL;
@@ -368,138 +331,65 @@ saa7185_command (struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-static struct i2c_driver i2c_driver_saa7185;
-
-static int
-saa7185_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int saa7185_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i;
- struct i2c_client *client;
struct saa7185 *encoder;
- dprintk(1,
- KERN_INFO
- "saa7185.c: detecting saa7185 client on address 0x%x\n",
- address << 1);
-
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &i2c_driver_saa7185;
- strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
- if (encoder == NULL) {
- kfree(client);
+ if (encoder == NULL)
return -ENOMEM;
- }
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
- i = i2c_attach_client(client);
- if (i) {
- kfree(client);
- kfree(encoder);
- return i;
- }
-
i = saa7185_write_block(client, init_common, sizeof(init_common));
- if (i >= 0) {
- i = saa7185_write_block(client, init_ntsc,
- sizeof(init_ntsc));
- }
- if (i < 0) {
- dprintk(1, KERN_ERR "%s_attach: init error %d\n",
- I2C_NAME(client), i);
- } else {
- dprintk(1,
- KERN_INFO
- "%s_attach: chip version %d at address 0x%x\n",
- I2C_NAME(client), saa7185_read(client) >> 5,
- client->addr << 1);
- }
-
+ if (i >= 0)
+ i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc));
+ if (i < 0)
+ v4l_dbg(1, debug, client, "init error %d\n", i);
+ else
+ v4l_dbg(1, debug, client, "revision 0x%x\n",
+ saa7185_read(client) >> 5);
return 0;
}
-static int
-saa7185_attach_adapter (struct i2c_adapter *adapter)
-{
- dprintk(1,
- KERN_INFO
- "saa7185.c: starting probe for adapter %s (0x%x)\n",
- I2C_NAME(adapter), adapter->id);
- return i2c_probe(adapter, &addr_data, &saa7185_detect_client);
-}
-
-static int
-saa7185_detach_client (struct i2c_client *client)
+static int saa7185_remove(struct i2c_client *client)
{
struct saa7185 *encoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */
//saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
kfree(encoder);
- kfree(client);
-
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver i2c_driver_saa7185 = {
- .driver = {
- .name = "saa7185", /* name */
- },
-
- .id = I2C_DRIVERID_SAA7185B,
+static const struct i2c_device_id saa7185_id[] = {
+ { "saa7185", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7185_id);
- .attach_adapter = saa7185_attach_adapter,
- .detach_client = saa7185_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa7185",
+ .driverid = I2C_DRIVERID_SAA7185B,
.command = saa7185_command,
+ .probe = saa7185_probe,
+ .remove = saa7185_remove,
+ .id_table = saa7185_id,
};
-
-static int __init
-saa7185_init (void)
-{
- return i2c_add_driver(&i2c_driver_saa7185);
-}
-
-static void __exit
-saa7185_exit (void)
-{
- i2c_del_driver(&i2c_driver_saa7185);
-}
-
-module_init(saa7185_init);
-module_exit(saa7185_exit);
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index f481277892d..ae3949180c4 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -288,7 +288,7 @@ static void se401_button_irq(struct urb *urb)
int status;
if (!se401->dev) {
- info("ohoh: device vapourished");
+ dev_info(&urb->dev->dev, "device vapourished\n");
return;
}
@@ -328,7 +328,7 @@ static void se401_video_irq(struct urb *urb)
return;
if (!se401->dev) {
- info ("ohoh: device vapourished");
+ dev_info(&urb->dev->dev, "device vapourished\n");
return;
}
@@ -375,7 +375,7 @@ static void se401_video_irq(struct urb *urb)
urb->status=0;
urb->dev=se401->dev;
if(usb_submit_urb(urb, GFP_KERNEL))
- info("urb burned down");
+ dev_info(&urb->dev->dev, "urb burned down\n");
return;
}
@@ -860,7 +860,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr)
);
if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
se401->nullpackets=0;
- info("to many null length packets, restarting capture");
+ dev_info(&se401->dev->dev,
+ "too many null length packets, restarting capture\n");
se401_stop_stream(se401);
se401_start_stream(se401);
} else {
@@ -880,7 +881,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr)
se401->scratch_use=0;
if (errors > SE401_MAX_ERRORS) {
errors=0;
- info("to much errors, restarting capture");
+ dev_info(&se401->dev->dev,
+ "too many errors, restarting capture\n");
se401_stop_stream(se401);
se401_start_stream(se401);
}
@@ -913,7 +915,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
usb_kill_urb(se401->inturb);
usb_free_urb(se401->inturb);
}
- info("%s disconnected", se401->camera_name);
+ dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name);
/* Free the memory */
kfree(se401->width);
@@ -936,14 +938,18 @@ static int se401_open(struct inode *inode, struct file *file)
struct usb_se401 *se401 = (struct usb_se401 *)dev;
int err = 0;
- if (se401->user)
+ lock_kernel();
+ if (se401->user) {
+ unlock_kernel();
return -EBUSY;
+ }
se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
if (se401->fbuf)
file->private_data = dev;
else
err = -ENOMEM;
se401->user = !err;
+ unlock_kernel();
return err;
}
@@ -956,8 +962,8 @@ static int se401_close(struct inode *inode, struct file *file)
rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
if (se401->removed) {
+ dev_info(&se401->dev->dev, "device unregistered\n");
usb_se401_remove_disconnected(se401);
- info("device unregistered");
} else {
for (i=0; i<SE401_NUMFRAMES; i++)
se401->frame[i].grabstate=FRAME_UNUSED;
@@ -1232,6 +1238,7 @@ static const struct file_operations se401_fops = {
static struct video_device se401_template = {
.name = "se401 USB camera",
.fops = &se401_fops,
+ .release = video_device_release_empty,
};
@@ -1271,7 +1278,7 @@ static int se401_init(struct usb_se401 *se401, int button)
for (i=0; i<se401->sizes; i++) {
sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
}
- info("%s", temp);
+ dev_info(&se401->dev->dev, "%s\n", temp);
se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
@@ -1305,7 +1312,8 @@ static int se401_init(struct usb_se401 *se401, int button)
if (button) {
se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
if (!se401->inturb) {
- info("Allocation of inturb failed");
+ dev_info(&se401->dev->dev,
+ "Allocation of inturb failed\n");
return 1;
}
usb_fill_int_urb(se401->inturb, se401->dev,
@@ -1316,7 +1324,7 @@ static int se401_init(struct usb_se401 *se401, int button)
8
);
if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
- info("int urb burned down");
+ dev_info(&se401->dev->dev, "int urb burned down\n");
return 1;
}
} else
@@ -1373,7 +1381,7 @@ static int se401_probe(struct usb_interface *intf,
return -ENODEV;
/* We found one */
- info("SE401 camera found: %s", camera_name);
+ dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
err("couldn't kmalloc se401 struct");
@@ -1384,7 +1392,8 @@ static int se401_probe(struct usb_interface *intf,
se401->iface = interface->bInterfaceNumber;
se401->camera_name = camera_name;
- info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
+ dev_info(&intf->dev, "firmware version: %02x\n",
+ le16_to_cpu(dev->descriptor.bcdDevice) & 255);
if (se401_init(se401, button)) {
kfree(se401);
@@ -1397,12 +1406,13 @@ static int se401_probe(struct usb_interface *intf,
mutex_init(&se401->lock);
wmb();
- if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
kfree(se401);
err("video_register_device failed");
return -EIO;
}
- info("registered new video device: video%d", se401->vdev.minor);
+ dev_info(&intf->dev, "registered new video device: video%d\n",
+ se401->vdev.minor);
usb_set_intfdata (intf, se401);
return 0;
@@ -1446,10 +1456,10 @@ static struct usb_driver se401_driver = {
static int __init usb_se401_init(void)
{
- info("SE401 usb camera driver version %s registering", version);
+ printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version);
if (flickerless)
if (flickerless!=50 && flickerless!=60) {
- info("Invallid flickerless value, use 0, 50 or 60.");
+ printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
return -1;
}
return usb_register(&se401_driver);
@@ -1458,7 +1468,7 @@ static int __init usb_se401_init(void)
static void __exit usb_se401_exit(void)
{
usb_deregister(&se401_driver);
- info("SE401 driver deregistered");
+ printk(KERN_INFO "SE401 driver deregistered\frame");
}
module_init(usb_se401_init);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 318754e7313..2407607f2ef 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -40,39 +40,39 @@
/* register offsets for sh7722 / sh7723 */
-#define CAPSR 0x00
-#define CAPCR 0x04
-#define CAMCR 0x08
-#define CMCYR 0x0c
-#define CAMOR 0x10
-#define CAPWR 0x14
-#define CAIFR 0x18
-#define CSTCR 0x20 /* not on sh7723 */
-#define CSECR 0x24 /* not on sh7723 */
-#define CRCNTR 0x28
-#define CRCMPR 0x2c
-#define CFLCR 0x30
-#define CFSZR 0x34
-#define CDWDR 0x38
-#define CDAYR 0x3c
-#define CDACR 0x40
-#define CDBYR 0x44
-#define CDBCR 0x48
-#define CBDSR 0x4c
-#define CFWCR 0x5c
-#define CLFCR 0x60
-#define CDOCR 0x64
-#define CDDCR 0x68
-#define CDDAR 0x6c
-#define CEIER 0x70
-#define CETCR 0x74
-#define CSTSR 0x7c
-#define CSRTR 0x80
-#define CDSSR 0x84
-#define CDAYR2 0x90
-#define CDACR2 0x94
-#define CDBYR2 0x98
-#define CDBCR2 0x9c
+#define CAPSR 0x00 /* Capture start register */
+#define CAPCR 0x04 /* Capture control register */
+#define CAMCR 0x08 /* Capture interface control register */
+#define CMCYR 0x0c /* Capture interface cycle register */
+#define CAMOR 0x10 /* Capture interface offset register */
+#define CAPWR 0x14 /* Capture interface width register */
+#define CAIFR 0x18 /* Capture interface input format register */
+#define CSTCR 0x20 /* Camera strobe control register (<= sh7722) */
+#define CSECR 0x24 /* Camera strobe emission count register (<= sh7722) */
+#define CRCNTR 0x28 /* CEU register control register */
+#define CRCMPR 0x2c /* CEU register forcible control register */
+#define CFLCR 0x30 /* Capture filter control register */
+#define CFSZR 0x34 /* Capture filter size clip register */
+#define CDWDR 0x38 /* Capture destination width register */
+#define CDAYR 0x3c /* Capture data address Y register */
+#define CDACR 0x40 /* Capture data address C register */
+#define CDBYR 0x44 /* Capture data bottom-field address Y register */
+#define CDBCR 0x48 /* Capture data bottom-field address C register */
+#define CBDSR 0x4c /* Capture bundle destination size register */
+#define CFWCR 0x5c /* Firewall operation control register */
+#define CLFCR 0x60 /* Capture low-pass filter control register */
+#define CDOCR 0x64 /* Capture data output control register */
+#define CDDCR 0x68 /* Capture data complexity level register */
+#define CDDAR 0x6c /* Capture data complexity level address register */
+#define CEIER 0x70 /* Capture event interrupt enable register */
+#define CETCR 0x74 /* Capture event flag clear register */
+#define CSTSR 0x7c /* Capture status register */
+#define CSRTR 0x80 /* Capture software reset register */
+#define CDSSR 0x84 /* Capture data size register */
+#define CDAYR2 0x90 /* Capture data address Y register 2 */
+#define CDACR2 0x94 /* Capture data address C register 2 */
+#define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */
+#define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */
static DEFINE_MUTEX(camera_lock);
@@ -165,6 +165,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10);
if (pcdev->active) {
+ pcdev->active->state = VIDEOBUF_ACTIVE;
ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active));
ceu_write(pcdev, CAPSR, 0x1); /* start capture */
}
@@ -236,7 +237,7 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
vb, vb->baddr, vb->bsize);
- vb->state = VIDEOBUF_ACTIVE;
+ vb->state = VIDEOBUF_QUEUED;
spin_lock_irqsave(&pcdev->lock, flags);
list_add_tail(&vb->queue, &pcdev->capture);
@@ -304,9 +305,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
"SuperH Mobile CEU driver attached to camera %d\n",
icd->devnum);
- if (pcdev->pdata->enable_camera)
- pcdev->pdata->enable_camera();
-
ret = icd->ops->init(icd);
if (ret)
goto err;
@@ -326,15 +324,25 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ unsigned long flags;
BUG_ON(icd != pcdev->icd);
/* disable capture, disable interrupts */
ceu_write(pcdev, CEIER, 0);
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
+
+ /* make sure active buffer is canceled */
+ spin_lock_irqsave(&pcdev->lock, flags);
+ if (pcdev->active) {
+ list_del(&pcdev->active->queue);
+ pcdev->active->state = VIDEOBUF_ERROR;
+ wake_up_all(&pcdev->active->done);
+ pcdev->active = NULL;
+ }
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+
icd->ops->release(icd);
- if (pcdev->pdata->disable_camera)
- pcdev->pdata->disable_camera();
dev_info(&icd->dev,
"SuperH Mobile CEU driver detached from camera %d\n",
@@ -396,7 +404,20 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */
ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */
- ceu_write(pcdev, CDOCR, 0x00000016);
+
+ /* A few words about byte order (observed in Big Endian mode)
+ *
+ * In data fetch mode bytes are received in chunks of 8 bytes.
+ * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
+ *
+ * The data is however by default written to memory in reverse order:
+ * D7, D6, D5, D4, D3, D2, D1, D0 (D7 written to lowest byte)
+ *
+ * The lowest three bits of CDOCR allows us to do swapping,
+ * using 7 we swap the data bytes to match the incoming order:
+ * D0, D1, D2, D3, D4, D5, D6, D7
+ */
+ ceu_write(pcdev, CDOCR, 0x00000017);
ceu_write(pcdev, CDWDR, cdwdr_width);
ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 23408764d0e..20e30bd9364 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -116,6 +116,26 @@ MODULE_PARM_DESC(debug,
"\n");
#endif
+/*
+ Add the probe entries to this table. Be sure to add the entry in the right
+ place, since, on failure, the next probing routine is called according to
+ the order of the list below, from top to bottom.
+*/
+static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
+ &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+ &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
+ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
+};
+
/*****************************************************************************/
static u32
@@ -1746,7 +1766,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
if (!down_read_trylock(&sn9c102_dev_lock))
return -ERESTARTSYS;
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
if (wait_for_completion_interruptible(&cam->probe)) {
up_read(&sn9c102_dev_lock);
@@ -1843,7 +1863,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
down_write(&sn9c102_dev_lock);
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
sn9c102_stop_transfer(cam);
sn9c102_release_buffers(cam);
@@ -1863,7 +1883,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
static ssize_t
sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device *cam = video_drvdata(filp);
struct sn9c102_frame_t* f, * i;
unsigned long lock_flags;
long timeout;
@@ -1987,7 +2007,7 @@ exit:
static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device *cam = video_drvdata(filp);
struct sn9c102_frame_t* f;
unsigned long lock_flags;
unsigned int mask = 0;
@@ -2063,7 +2083,7 @@ static struct vm_operations_struct sn9c102_vm_ops = {
static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device *cam = video_drvdata(filp);
unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start;
void *pos;
@@ -3075,7 +3095,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
unsigned int cmd, void __user * arg)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device *cam = video_drvdata(filp);
switch (cmd) {
@@ -3179,7 +3199,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
static int sn9c102_ioctl(struct inode* inode, struct file* filp,
unsigned int cmd, unsigned long arg)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device *cam = video_drvdata(filp);
int err = 0;
if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -3312,6 +3332,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->fops = &sn9c102_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
+ cam->v4ldev->parent = &udev->dev;
init_completion(&cam->probe);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 6ff489baacf..e23734f6d6e 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -40,11 +40,14 @@ struct sn9c102_device;
static const struct usb_device_id sn9c102_id_table[] = {
/* SN9C101 and SN9C102 */
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
{ SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
@@ -53,29 +56,33 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
/* SN9C103 */
{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
{ SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
+/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
+/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5130 */
{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
@@ -105,7 +112,7 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), },
+/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
@@ -133,24 +140,4 @@ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
-/*
- Add the above entries to this table. Be sure to add the entry in the right
- place, since, on failure, the next probing routine is called according to
- the order of the list below, from top to bottom.
-*/
-static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
- &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
- &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
- &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
- &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
- &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
- &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
- &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
- &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
- &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-};
-
#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index eaf9ad0dc8a..db243494893 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int hv7131d_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
index 0fc401223cf..4295887ff60 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int hv7131r_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index 00b134ca0a3..1f5b09bec89 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int mi0343_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c
index f8d81d82e8d..d973fc1973d 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0360.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int mi0360_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c
index 3b98ac3bbc3..95986eb492e 100644
--- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c
+++ b/drivers/media/video/sn9c102/sn9c102_mt9v111.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int mt9v111_init(struct sn9c102_device *cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index e4856fd7798..803712c29f0 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int ov7630_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
index 8aae416ba8e..7977795d342 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int ov7660_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 360f2a848bc..81cd969c1b7 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int pas106b_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index ca4a1506ed3..2782f94cf6f 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int pas202bcb_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index e7d2de2bace..04cdfdde856 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int tas5110c1b_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
index d32fdbccdc5..9372e6f9fcf 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int tas5110d_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index 56fb1d575a8..a30bbc4389f 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -20,6 +20,7 @@
***************************************************************************/
#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
static int tas5130d1b_init(struct sn9c102_device* cam)
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 1adc257ebdb..bb7a9d480e8 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -18,15 +18,7 @@
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/soc_camera.h>
-
-struct soc_camera_platform_info {
- int iface;
- char *format_name;
- unsigned long format_depth;
- struct v4l2_pix_format format;
- unsigned long bus_param;
- int (*set_capture)(struct soc_camera_platform_info *info, int enable);
-};
+#include <media/soc_camera_platform.h>
struct soc_camera_platform_priv {
struct soc_camera_platform_info *info;
@@ -44,11 +36,21 @@ soc_camera_platform_get_info(struct soc_camera_device *icd)
static int soc_camera_platform_init(struct soc_camera_device *icd)
{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+ if (p->power)
+ p->power(1);
+
return 0;
}
static int soc_camera_platform_release(struct soc_camera_device *icd)
{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+ if (p->power)
+ p->power(0);
+
return 0;
}
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index ad36af30e09..edaea496451 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -27,7 +27,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <linux/kref.h>
#include <linux/usb.h>
#include <linux/mm.h>
@@ -65,22 +64,6 @@ static struct usb_device_id stkwebcam_table[] = {
};
MODULE_DEVICE_TABLE(usb, stkwebcam_table);
-static void stk_camera_cleanup(struct kref *kref)
-{
- struct stk_camera *dev = to_stk_camera(kref);
-
- STK_INFO("Syntek USB2.0 Camera release resources"
- " video device /dev/video%d\n", dev->vdev.minor);
- video_unregister_device(&dev->vdev);
- dev->vdev.priv = NULL;
-
- if (dev->sio_bufs != NULL || dev->isobufs != NULL)
- STK_ERROR("We are leaking memory\n");
- usb_put_intf(dev->interface);
- kfree(dev);
-}
-
-
/*
* Basic stuff
*/
@@ -576,7 +559,7 @@ static void stk_clean_iso(struct stk_camera *dev)
urb = dev->isobufs[i].urb;
if (urb) {
- if (atomic_read(&dev->urbs_used))
+ if (atomic_read(&dev->urbs_used) && is_present(dev))
usb_kill_urb(urb);
usb_free_urb(urb);
}
@@ -689,45 +672,30 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
vdev = video_devdata(fp);
dev = vdev_to_camera(vdev);
- if (dev == NULL || !is_present(dev))
+ lock_kernel();
+ if (dev == NULL || !is_present(dev)) {
+ unlock_kernel();
return -ENXIO;
- fp->private_data = vdev;
- kref_get(&dev->kref);
+ }
+ fp->private_data = dev;
usb_autopm_get_interface(dev->interface);
+ unlock_kernel();
return 0;
}
static int v4l_stk_release(struct inode *inode, struct file *fp)
{
- struct stk_camera *dev;
- struct video_device *vdev;
+ struct stk_camera *dev = fp->private_data;
- vdev = video_devdata(fp);
- if (vdev == NULL) {
- STK_ERROR("v4l_release called w/o video devdata\n");
- return -EFAULT;
- }
- dev = vdev_to_camera(vdev);
- if (dev == NULL) {
- STK_ERROR("v4l_release called on removed device\n");
- return -ENODEV;
+ if (dev->owner == fp) {
+ stk_stop_stream(dev);
+ stk_free_buffers(dev);
+ dev->owner = NULL;
}
- if (dev->owner != fp) {
+ if(is_present(dev))
usb_autopm_put_interface(dev->interface);
- kref_put(&dev->kref, stk_camera_cleanup);
- return 0;
- }
-
- stk_stop_stream(dev);
-
- stk_free_buffers(dev);
-
- dev->owner = NULL;
-
- usb_autopm_put_interface(dev->interface);
- kref_put(&dev->kref, stk_camera_cleanup);
return 0;
}
@@ -738,17 +706,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
int i;
int ret;
unsigned long flags;
- struct stk_camera *dev;
- struct video_device *vdev;
struct stk_sio_buffer *sbuf;
-
- vdev = video_devdata(fp);
- if (vdev == NULL)
- return -EFAULT;
- dev = vdev_to_camera(vdev);
-
- if (dev == NULL)
- return -EIO;
+ struct stk_camera *dev = fp->private_data;
if (!is_present(dev))
return -EIO;
@@ -804,17 +763,7 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
{
- struct stk_camera *dev;
- struct video_device *vdev;
-
- vdev = video_devdata(fp);
-
- if (vdev == NULL)
- return -EFAULT;
-
- dev = vdev_to_camera(vdev);
- if (dev == NULL)
- return -ENODEV;
+ struct stk_camera *dev = fp->private_data;
poll_wait(fp, &dev->wait_frame, wait);
@@ -850,16 +799,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
unsigned int i;
int ret;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- struct stk_camera *dev;
- struct video_device *vdev;
+ struct stk_camera *dev = fp->private_data;
struct stk_sio_buffer *sbuf = NULL;
if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
return -EINVAL;
- vdev = video_devdata(fp);
- dev = vdev_to_camera(vdev);
-
for (i = 0; i < dev->n_sbufs; i++) {
if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
sbuf = dev->sio_bufs + i;
@@ -1355,6 +1300,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
static void stk_v4l_dev_release(struct video_device *vd)
{
+ struct stk_camera *dev = vdev_to_camera(vd);
+
+ if (dev->sio_bufs != NULL || dev->isobufs != NULL)
+ STK_ERROR("We are leaking memory\n");
+ usb_put_intf(dev->interface);
+ kfree(dev);
}
static struct video_device stk_v4l_data = {
@@ -1375,7 +1326,6 @@ static int stk_register_video_device(struct stk_camera *dev)
dev->vdev = stk_v4l_data;
dev->vdev.debug = debug;
dev->vdev.parent = &dev->interface->dev;
- dev->vdev.priv = dev;
err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
if (err)
STK_ERROR("v4l registration failed\n");
@@ -1392,7 +1342,7 @@ static int stk_camera_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
int i;
- int err;
+ int err = 0;
struct stk_camera *dev = NULL;
struct usb_device *udev = interface_to_usbdev(interface);
@@ -1405,7 +1355,6 @@ static int stk_camera_probe(struct usb_interface *interface,
return -ENOMEM;
}
- kref_init(&dev->kref);
spin_lock_init(&dev->spinlock);
init_waitqueue_head(&dev->wait_frame);
@@ -1438,8 +1387,8 @@ static int stk_camera_probe(struct usb_interface *interface,
}
if (!dev->isoc_ep) {
STK_ERROR("Could not find isoc-in endpoint");
- kref_put(&dev->kref, stk_camera_cleanup);
- return -ENODEV;
+ err = -ENODEV;
+ goto error;
}
dev->vsettings.brightness = 0x7fff;
dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
@@ -1453,14 +1402,17 @@ static int stk_camera_probe(struct usb_interface *interface,
err = stk_register_video_device(dev);
if (err) {
- kref_put(&dev->kref, stk_camera_cleanup);
- return err;
+ goto error;
}
stk_create_sysfs_files(&dev->vdev);
usb_autopm_enable(dev->interface);
return 0;
+
+error:
+ kfree(dev);
+ return err;
}
static void stk_camera_disconnect(struct usb_interface *interface)
@@ -1473,7 +1425,10 @@ static void stk_camera_disconnect(struct usb_interface *interface)
wake_up_interruptible(&dev->wait_frame);
stk_remove_sysfs_files(&dev->vdev);
- kref_put(&dev->kref, stk_camera_cleanup);
+ STK_INFO("Syntek USB2.0 Camera release resources "
+ "video device /dev/video%d\n", dev->vdev.minor);
+
+ video_unregister_device(&dev->vdev);
}
#ifdef CONFIG_PM
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h
index df4dfefc532..9f673663757 100644
--- a/drivers/media/video/stk-webcam.h
+++ b/drivers/media/video/stk-webcam.h
@@ -99,7 +99,6 @@ struct stk_camera {
u8 isoc_ep;
- struct kref kref;
/* Not sure if this is right */
atomic_t urbs_used;
@@ -121,10 +120,8 @@ struct stk_camera {
unsigned sequence;
};
-#define to_stk_camera(d) container_of(d, struct stk_camera, kref)
#define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
-void stk_camera_delete(struct kref *);
int stk_camera_write_reg(struct stk_camera *, u16, u8);
int stk_camera_read_reg(struct stk_camera *, u16, int *);
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 276bded06ab..bbad54f85c8 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1882,12 +1882,16 @@ static int saa_open(struct inode *inode, struct file *file)
struct video_device *vdev = video_devdata(file);
struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
+ lock_kernel();
file->private_data = saa;
saa->user++;
- if (saa->user > 1)
+ if (saa->user > 1) {
+ unlock_kernel();
return 0; /* device open already, don't reset */
+ }
saa->writemode = VID_WRITE_MPEG_VID; /* default to video */
+ unlock_kernel();
return 0;
}
@@ -1921,6 +1925,7 @@ static struct video_device saa_template = {
.name = "SAA7146A",
.fops = &saa_fops,
.minor = -1,
+ .release = video_device_release_empty,
};
static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 56dc3d6b5b2..9c549d93599 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -84,7 +84,8 @@ static unsigned int debug;
#define PDEBUG(level, fmt, args...) \
do { \
if (debug >= level) \
- info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+ printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt, \
+ __func__, __LINE__ , ## args); \
} while (0)
@@ -1086,6 +1087,7 @@ static int stv_open (struct inode *inode, struct file *file)
int err = 0;
/* we are called with the BKL held */
+ lock_kernel();
stv680->user = 1;
err = stv_init (stv680); /* main initialization routine for camera */
@@ -1099,6 +1101,7 @@ static int stv_open (struct inode *inode, struct file *file)
}
if (err)
stv680->user = 0;
+ unlock_kernel();
return err;
}
@@ -1462,7 +1465,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
mutex_init (&stv680->lock);
wmb ();
- if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ if (video_register_device(stv680->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
PDEBUG (0, "STV(e): video_register_device failed");
retval = -EIO;
goto error_vdev;
@@ -1550,7 +1553,8 @@ static int __init usb_stv680_init (void)
}
PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 2437c1a269c..1c391f0328f 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -2,6 +2,7 @@
tda9840 - i2c-driver for the tda9840 by SGS Thomson
Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+ Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
The tda9840 is a stereo/dual sound processor with digital
identification. It can be found at address 0x84 on the i2c-bus.
@@ -28,59 +29,118 @@
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
#include "tda9840.h"
-static int debug; /* insmod parameter */
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tda9840 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
-#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define SWITCH 0x00
#define LEVEL_ADJUST 0x02
#define STEREO_ADJUST 0x03
#define TEST 0x04
+#define TDA9840_SET_MUTE 0x00
+#define TDA9840_SET_MONO 0x10
+#define TDA9840_SET_STEREO 0x2a
+#define TDA9840_SET_LANG1 0x12
+#define TDA9840_SET_LANG2 0x1e
+#define TDA9840_SET_BOTH 0x1a
+#define TDA9840_SET_BOTH_R 0x16
+#define TDA9840_SET_EXTERNAL 0x7a
+
/* addresses to scan, found only at 0x42 (7-Bit) */
static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
-static struct i2c_driver driver;
-static struct i2c_client client_template;
+static void tda9840_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ if (i2c_smbus_write_byte_data(client, reg, val))
+ v4l_dbg(1, debug, client, "error writing %02x to %02x\n",
+ val, reg);
+}
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg)
{
- int result;
int byte = *(int *)arg;
switch (cmd) {
- case TDA9840_SWITCH:
-
- dprintk("TDA9840_SWITCH: 0x%02x\n", byte);
-
- if (byte != TDA9840_SET_MONO
- && byte != TDA9840_SET_MUTE
- && byte != TDA9840_SET_STEREO
- && byte != TDA9840_SET_LANG1
- && byte != TDA9840_SET_LANG2
- && byte != TDA9840_SET_BOTH
- && byte != TDA9840_SET_BOTH_R
- && byte != TDA9840_SET_EXTERNAL) {
+ case VIDIOC_S_TUNER: {
+ struct v4l2_tuner *t = arg;
+ int byte;
+
+ if (t->index)
return -EINVAL;
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_STEREO:
+ byte = TDA9840_SET_STEREO;
+ break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ byte = TDA9840_SET_BOTH;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ byte = TDA9840_SET_LANG1;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ byte = TDA9840_SET_LANG2;
+ break;
+ default:
+ byte = TDA9840_SET_MONO;
+ break;
+ }
+ v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte);
+ tda9840_write(client, SWITCH, byte);
+ break;
+ }
+
+ case VIDIOC_G_TUNER: {
+ struct v4l2_tuner *t = arg;
+ u8 byte;
+
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ if (1 != i2c_master_recv(client, &byte, 1)) {
+ v4l_dbg(1, debug, client,
+ "i2c_master_recv() failed\n");
+ return -EIO;
}
- result = i2c_smbus_write_byte_data(client, SWITCH, byte);
- if (result)
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+ if (byte & 0x80) {
+ v4l_dbg(1, debug, client,
+ "TDA9840_DETECT: register contents invalid\n");
+ return -EINVAL;
+ }
+
+ v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte);
+
+ switch (byte & 0x60) {
+ case 0x00:
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ break;
+ case 0x20:
+ t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ break;
+ case 0x40:
+ t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+ break;
+ default: /* Incorrect detect */
+ t->rxsubchans = V4L2_TUNER_MODE_MONO;
+ break;
+ }
break;
+ }
case TDA9840_LEVEL_ADJUST:
-
- dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte);
+ v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte);
/* check for correct range */
if (byte > 25 || byte < -20)
@@ -92,15 +152,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
byte += 0x8;
else
byte = -byte;
-
- result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte);
- if (result)
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+ tda9840_write(client, LEVEL_ADJUST, byte);
break;
case TDA9840_STEREO_ADJUST:
-
- dprintk("TDA9840_STEREO_ADJUST: %d\n", byte);
+ v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte);
/* check for correct range */
if (byte > 25 || byte < -24)
@@ -113,143 +169,59 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
else
byte = -byte;
- result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte);
- if (result)
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
- break;
-
- case TDA9840_DETECT: {
- int *ret = (int *)arg;
-
- byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST);
- if (byte == -1) {
- dprintk("i2c_smbus_read_byte_data() failed\n");
- return -EIO;
- }
-
- if (0 != (byte & 0x80)) {
- dprintk("TDA9840_DETECT: register contents invalid\n");
- return -EINVAL;
- }
-
- dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte);
- *ret = ((byte & 0x60) >> 5);
- result = 0;
- break;
- }
- case TDA9840_TEST:
- dprintk("TDA9840_TEST: 0x%02x\n", byte);
-
- /* mask out irrelevant bits */
- byte &= 0x3;
-
- result = i2c_smbus_write_byte_data(client, TEST, byte);
- if (result)
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+ tda9840_write(client, STEREO_ADJUST, byte);
break;
default:
return -ENOIOCTLCMD;
}
- if (result)
- return -EIO;
-
return 0;
}
-static int detect(struct i2c_adapter *adapter, int address, int kind)
+static int tda9840_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client;
- int result = 0;
-
- int byte = 0x0;
+ int result;
+ int byte;
/* let's see whether this adapter can support what we need */
- if (0 == i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_READ_BYTE_DATA |
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return 0;
- }
-
- /* allocate memory for client structure */
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client) {
- printk("not enough kernel memory\n");
- return -ENOMEM;
- }
-
- /* fill client structure */
- memcpy(client, &client_template, sizeof(struct i2c_client));
- client->addr = address;
- client->adapter = adapter;
- /* tell the i2c layer a new client has arrived */
- if (0 != (result = i2c_attach_client(client))) {
- kfree(client);
- return result;
- }
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
/* set initial values for level & stereo - adjustment, mode */
byte = 0;
- result = command(client, TDA9840_LEVEL_ADJUST, &byte);
- result += command(client, TDA9840_STEREO_ADJUST, &byte);
- byte = TDA9840_SET_MONO;
- result = command(client, TDA9840_SWITCH, &byte);
+ result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte);
+ result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte);
+ tda9840_write(client, SWITCH, TDA9840_SET_STEREO);
if (result) {
- dprintk("could not initialize tda9840\n");
+ v4l_dbg(1, debug, client, "could not initialize tda9840\n");
return -ENODEV;
}
-
- printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
return 0;
}
-static int attach(struct i2c_adapter *adapter)
-{
- /* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_HW_SAA7146) {
- dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
- return -ENODEV;
- }
-
- return i2c_probe(adapter, &addr_data, &detect);
-}
-
-static int detach(struct i2c_client *client)
+static int tda9840_legacy_probe(struct i2c_adapter *adapter)
{
- int ret = i2c_detach_client(client);
- kfree(client);
- return ret;
+ /* Let's see whether this is a known adapter we can attach to.
+ Prevents conflicts with tvaudio.c. */
+ return adapter->id == I2C_HW_SAA7146;
}
-
-static struct i2c_driver driver = {
- .driver = {
- .name = "tda9840",
- },
- .id = I2C_DRIVERID_TDA9840,
- .attach_adapter = attach,
- .detach_client = detach,
- .command = command,
+static const struct i2c_device_id tda9840_id[] = {
+ { "tda9840", 0 },
+ { }
};
+MODULE_DEVICE_TABLE(i2c, tda9840_id);
-static struct i2c_client client_template = {
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "tda9840",
- .driver = &driver,
+ .driverid = I2C_DRIVERID_TDA9840,
+ .command = tda9840_command,
+ .probe = tda9840_probe,
+ .legacy_probe = tda9840_legacy_probe,
+ .id_table = tda9840_id,
};
-
-static int __init this_module_init(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit this_module_exit(void)
-{
- i2c_del_driver(&driver);
-}
-
-module_init(this_module_init);
-module_exit(this_module_exit);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tda9840 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h
index 7da8432cdca..dc12ae7caf6 100644
--- a/drivers/media/video/tda9840.h
+++ b/drivers/media/video/tda9840.h
@@ -3,24 +3,6 @@
#define I2C_ADDR_TDA9840 0x42
-#define TDA9840_DETECT _IOR('v',1,int)
-/* return values for TDA9840_DETCT */
-#define TDA9840_MONO_DETECT 0x0
-#define TDA9840_DUAL_DETECT 0x1
-#define TDA9840_STEREO_DETECT 0x2
-#define TDA9840_INCORRECT_DETECT 0x3
-
-#define TDA9840_SWITCH _IOW('v',2,int)
-/* modes than can be set with TDA9840_SWITCH */
-#define TDA9840_SET_MUTE 0x00
-#define TDA9840_SET_MONO 0x10
-#define TDA9840_SET_STEREO 0x2a
-#define TDA9840_SET_LANG1 0x12
-#define TDA9840_SET_LANG2 0x1e
-#define TDA9840_SET_BOTH 0x1a
-#define TDA9840_SET_BOTH_R 0x16
-#define TDA9840_SET_EXTERNAL 0x7a
-
/* values may range between +2.5 and -2.0;
the value has to be multiplied with 10 */
#define TDA9840_LEVEL_ADJUST _IOW('v',3,int)
@@ -29,7 +11,4 @@
the value has to be multiplied with 10 */
#define TDA9840_STEREO_ADJUST _IOW('v',4,int)
-/* currently not implemented */
-#define TDA9840_TEST _IOW('v',5,int)
-
#endif
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 421c1445e96..cde092adbb5 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -2,6 +2,7 @@
tea6415c - i2c-driver for the tea6415c by SGS Thomson
Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+ Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
The tea6415c is a bus controlled video-matrix-switch
with 8 inputs and 6 outputs.
@@ -30,18 +31,18 @@
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
#include "tea6415c.h"
-static int debug; /* insmod parameter */
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6415c driver");
+MODULE_LICENSE("GPL");
-#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+static int debug;
+module_param(debug, int, 0644);
-#define TEA6415C_NUM_INPUTS 8
-#define TEA6415C_NUM_OUTPUTS 6
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */
static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END };
@@ -49,60 +50,6 @@ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIEN
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-/* this function is called by i2c_probe */
-static int detect(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *client = NULL;
- int err = 0;
-
- /* let's see whether this adapter can support what we need */
- if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) {
- return 0;
- }
-
- /* allocate memory for client structure */
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client) {
- return -ENOMEM;
- }
-
- /* fill client structure */
- memcpy(client, &client_template, sizeof(struct i2c_client));
- client->addr = address;
- client->adapter = adapter;
-
- /* tell the i2c layer a new client has arrived */
- if (0 != (err = i2c_attach_client(client))) {
- kfree(client);
- return err;
- }
-
- printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
-
- return 0;
-}
-
-static int attach(struct i2c_adapter *adapter)
-{
- /* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_HW_SAA7146) {
- dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
- return -ENODEV;
- }
-
- return i2c_probe(adapter, &addr_data, &detect);
-}
-
-static int detach(struct i2c_client *client)
-{
- int ret = i2c_detach_client(client);
- kfree(client);
- return ret;
-}
-
/* makes a connection between the input-pin 'i' and the output-pin 'o'
for the tea6415c-client 'client' */
static int switch_matrix(struct i2c_client *client, int i, int o)
@@ -110,7 +57,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
u8 byte = 0;
int ret;
- dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o);
+ v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o);
/* check if the pins are valid */
if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i)
@@ -168,14 +115,14 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
ret = i2c_smbus_write_byte(client, byte);
if (ret) {
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret);
+ v4l_dbg(1, debug, client,
+ "i2c_smbus_write_byte() failed, ret:%d\n", ret);
return -EIO;
}
-
return ret;
}
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg;
int result = 0;
@@ -187,38 +134,40 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
default:
return -ENOIOCTLCMD;
}
-
return result;
}
-static struct i2c_driver driver = {
- .driver = {
- .name = "tea6415c",
- },
- .id = I2C_DRIVERID_TEA6415C,
- .attach_adapter = attach,
- .detach_client = detach,
- .command = command,
-};
-
-static struct i2c_client client_template = {
- .name = "tea6415c",
- .driver = &driver,
-};
-
-static int __init this_module_init(void)
+/* this function is called by i2c_probe */
+static int tea6415c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- return i2c_add_driver(&driver);
+ /* let's see whether this adapter can support what we need */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+ return 0;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+ return 0;
}
-static void __exit this_module_exit(void)
+static int tea6415c_legacy_probe(struct i2c_adapter *adapter)
{
- i2c_del_driver(&driver);
+ /* Let's see whether this is a known adapter we can attach to.
+ Prevents conflicts with tvaudio.c. */
+ return adapter->id == I2C_HW_SAA7146;
}
-module_init(this_module_init);
-module_exit(this_module_exit);
+static const struct i2c_device_id tea6415c_id[] = {
+ { "tea6415c", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tea6415c_id);
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tea6415c driver");
-MODULE_LICENSE("GPL");
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "tea6415c",
+ .driverid = I2C_DRIVERID_TEA6415C,
+ .command = tea6415c_command,
+ .probe = tea6415c_probe,
+ .legacy_probe = tea6415c_legacy_probe,
+ .id_table = tea6415c_id,
+};
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index b5c8957d130..e50820969e6 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -2,6 +2,7 @@
tea6420 - i2c-driver for the tea6420 by SGS Thomson
Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+ Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
The tea6420 is a bus controlled audio-matrix with 5 stereo inputs,
4 stereo outputs and gain control for each output.
@@ -30,15 +31,18 @@
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
#include "tea6420.h"
-static int debug; /* insmod parameter */
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6420 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
-#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
@@ -46,23 +50,20 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
/* make a connection between the input 'i' and the output 'o'
with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */
static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
{
- u8 byte = 0;
+ u8 byte;
int ret;
- dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g);
+ v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g);
/* check if the parameters are valid */
if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0)
return -1;
- byte = ((o - 1) << 5);
+ byte = ((o - 1) << 5);
byte |= (i - 1);
/* to understand this, have a look at the tea6420-specs (p.5) */
@@ -82,40 +83,41 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
ret = i2c_smbus_write_byte(client, byte);
if (ret) {
- dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret);
+ v4l_dbg(1, debug, client,
+ "i2c_smbus_write_byte() failed, ret:%d\n", ret);
return -EIO;
}
-
return 0;
}
-/* this function is called by i2c_probe */
-static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
+static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg)
{
- struct i2c_client *client;
- int err = 0, i = 0;
+ struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg;
+ int result = 0;
- /* let's see whether this adapter can support what we need */
- if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) {
- return 0;
+ switch (cmd) {
+ case TEA6420_SWITCH:
+ result = tea6420_switch(client, a->in, a->out, a->gain);
+ break;
+ default:
+ return -ENOIOCTLCMD;
}
- /* allocate memory for client structure */
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (!client) {
- return -ENOMEM;
- }
+ return result;
+}
- /* fill client structure */
- memcpy(client, &client_template, sizeof(struct i2c_client));
- client->addr = address;
- client->adapter = adapter;
+/* this function is called by i2c_probe */
+static int tea6420_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err, i;
- /* tell the i2c layer a new client has arrived */
- if (0 != (err = i2c_attach_client(client))) {
- kfree(client);
- return err;
- }
+ /* let's see whether this adapter can support what we need */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+ return -EIO;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
/* set initial values: set "mute"-input to all outputs at gain 0 */
err = 0;
@@ -123,78 +125,31 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
err += tea6420_switch(client, 6, i, 0);
}
if (err) {
- dprintk("could not initialize tea6420\n");
+ v4l_dbg(1, debug, client, "could not initialize tea6420\n");
kfree(client);
return -ENODEV;
}
-
- printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
-
return 0;
}
-static int attach(struct i2c_adapter *adapter)
+static int tea6420_legacy_probe(struct i2c_adapter *adapter)
{
- /* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_HW_SAA7146) {
- dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
- return -ENODEV;
- }
-
- return i2c_probe(adapter, &addr_data, &tea6420_detect);
-}
-
-static int detach(struct i2c_client *client)
-{
- int ret = i2c_detach_client(client);
- kfree(client);
- return ret;
-}
-
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
- struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg;
- int result = 0;
-
- switch (cmd) {
- case TEA6420_SWITCH:
- result = tea6420_switch(client, a->in, a->out, a->gain);
- break;
- default:
- return -ENOIOCTLCMD;
- }
-
- return result;
+ /* Let's see whether this is a known adapter we can attach to.
+ Prevents conflicts with tvaudio.c. */
+ return adapter->id == I2C_HW_SAA7146;
}
-static struct i2c_driver driver = {
- .driver = {
- .name = "tea6420",
- },
- .id = I2C_DRIVERID_TEA6420,
- .attach_adapter = attach,
- .detach_client = detach,
- .command = command,
+static const struct i2c_device_id tea6420_id[] = {
+ { "tea6420", 0 },
+ { }
};
+MODULE_DEVICE_TABLE(i2c, tea6420_id);
-static struct i2c_client client_template = {
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "tea6420",
- .driver = &driver,
+ .driverid = I2C_DRIVERID_TEA6420,
+ .command = tea6420_command,
+ .probe = tea6420_probe,
+ .legacy_probe = tea6420_legacy_probe,
+ .id_table = tea6420_id,
};
-
-static int __init this_module_init(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit this_module_exit(void)
-{
- i2c_del_driver(&driver);
-}
-
-module_init(this_module_init);
-module_exit(this_module_exit);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tea6420 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
deleted file mode 100644
index bdf506e6ae2..00000000000
--- a/drivers/media/video/tuner-3036.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Driver for Philips SAB3036 "CITAC" tuner control chip.
- *
- * Author: Phil Blundell <philb@gnu.org>
- *
- * The SAB3036 is just about different enough from the chips that
- * tuner.c copes with to make it not worth the effort to crowbar
- * the support into that file. So instead we have a separate driver.
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-
-#include <media/tuner.h>
-
-static int debug; /* insmod parameter */
-static int this_adap;
-
-static struct i2c_client client_template;
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned char
-tuner_getstatus (struct i2c_client *c)
-{
- unsigned char byte;
- if (i2c_master_recv(c, &byte, 1) != 1)
- printk(KERN_ERR "tuner-3036: I/O error.\n");
- return byte;
-}
-
-#define TUNER_FL 0x80
-
-static int
-tuner_islocked (struct i2c_client *c)
-{
- return (tuner_getstatus(c) & TUNER_FL);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void
-set_tv_freq(struct i2c_client *c, int freq)
-{
- u16 div = ((freq * 20) / 16);
- unsigned long give_up = jiffies + HZ;
- unsigned char buffer[2];
-
- if (debug)
- printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div);
-
- /* Select high tuning current */
- buffer[0] = 0x29;
- buffer[1] = 0x3e;
-
- if (i2c_master_send(c, buffer, 2) != 2)
- printk("tuner: i2c i/o error 1\n");
-
- buffer[0] = 0x80 | ((div>>8) & 0x7f);
- buffer[1] = div & 0xff;
-
- if (i2c_master_send(c, buffer, 2) != 2)
- printk("tuner: i2c i/o error 2\n");
-
- while (!tuner_islocked(c) && time_before(jiffies, give_up))
- schedule();
-
- if (!tuner_islocked(c))
- printk(KERN_WARNING "tuner: failed to achieve PLL lock\n");
-
- /* Select low tuning current and engage AFC */
- buffer[0] = 0x29;
- buffer[1] = 0xb2;
-
- if (i2c_master_send(c, buffer, 2) != 2)
- printk("tuner: i2c i/o error 3\n");
-
- if (debug)
- printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c));
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-tuner_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 };
-
- struct i2c_client *client;
-
- if (this_adap > 0)
- return -1;
- this_adap++;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &client_template, sizeof(struct i2c_client));
-
- printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client));
-
- i2c_attach_client(client);
-
- if (i2c_master_send(client, buffer, 2) != 2)
- printk("tuner: i2c i/o error 1\n");
- if (i2c_master_send(client, buffer+2, 2) != 2)
- printk("tuner: i2c i/o error 2\n");
- if (i2c_master_send(client, buffer+4, 2) != 2)
- printk("tuner: i2c i/o error 3\n");
- return 0;
-}
-
-static int
-tuner_detach(struct i2c_client *c)
-{
- return 0;
-}
-
-static int
-tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
- int *iarg = (int*)arg;
-
- switch (cmd)
- {
- case VIDIOCSFREQ:
- set_tv_freq(client, *iarg);
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int
-tuner_probe(struct i2c_adapter *adap)
-{
- this_adap = 0;
- if (adap->id == I2C_HW_B_LP)
- return i2c_probe(adap, &addr_data, tuner_attach);
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver
-i2c_driver_tuner =
-{
- .driver = {
- .name = "sab3036",
- },
- .id = I2C_DRIVERID_SAB3036,
- .attach_adapter = tuner_probe,
- .detach_client = tuner_detach,
- .command = tuner_command
-};
-
-static struct i2c_client client_template =
-{
- .driver = &i2c_driver_tuner,
- .name = "SAB3036",
-};
-
-static int __init
-tuner3036_init(void)
-{
- return i2c_add_driver(&i2c_driver_tuner);
-}
-
-static void __exit
-tuner3036_exit(void)
-{
- i2c_del_driver(&i2c_driver_tuner);
-}
-
-MODULE_DESCRIPTION("SAB3036 tuner driver");
-MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
-MODULE_LICENSE("GPL");
-
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug,"Enable debugging output");
-
-module_init(tuner3036_init);
-module_exit(tuner3036_exit);
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index d806a3556ee..4a7735c6c1a 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -92,7 +92,6 @@ struct tuner {
unsigned int type; /* chip type id */
unsigned int config;
- int (*tuner_callback) (void *dev, int command, int arg);
const char *name;
};
@@ -346,7 +345,7 @@ static struct xc5000_config xc5000_cfg;
static void set_type(struct i2c_client *c, unsigned int type,
unsigned int new_mode_mask, unsigned int new_config,
- int (*tuner_callback) (void *dev, int command,int arg))
+ int (*tuner_callback) (void *dev, int component, int cmd, int arg))
{
struct tuner *t = i2c_get_clientdata(c);
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
@@ -362,7 +361,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
t->config = new_config;
if (tuner_callback != NULL) {
tuner_dbg("defining GPIO callback\n");
- t->tuner_callback = tuner_callback;
+ t->fe.callback = tuner_callback;
}
if (t->mode == T_UNINITIALIZED) {
@@ -385,7 +384,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
{
struct tda829x_config cfg = {
.lna_cfg = t->config,
- .tuner_callback = t->tuner_callback,
};
if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
t->i2c->addr, &cfg))
@@ -433,7 +431,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
struct xc2028_config cfg = {
.i2c_adap = t->i2c->adapter,
.i2c_addr = t->i2c->addr,
- .callback = t->tuner_callback,
};
if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
goto attach_failed;
@@ -450,10 +447,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
xc5000_cfg.i2c_address = t->i2c->addr;
xc5000_cfg.if_khz = 5380;
- xc5000_cfg.tuner_callback = t->tuner_callback;
if (!dvb_attach(xc5000_attach,
- &t->fe, t->i2c->adapter, &xc5000_cfg,
- c->adapter->algo_data))
+ &t->fe, t->i2c->adapter, &xc5000_cfg))
goto attach_failed;
xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -1225,7 +1220,7 @@ register_client:
} else {
t->mode = V4L2_TUNER_DIGITAL_TV;
}
- set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback);
+ set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
list_add_tail(&t->list, &tuner_list);
return 0;
}
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 463680b1328..b59e47272ab 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1792,7 +1792,7 @@ static int chip_command(struct i2c_client *client,
break;
case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
- if (desc->checkmode) {
+ if (desc->checkmode && desc->setmode) {
desc->setmode(chip,V4L2_TUNER_MODE_MONO);
if (chip->prevmode != V4L2_TUNER_MODE_MONO)
chip->prevmode = -1; /* reset previous mode */
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index bcc32fa92a8..3b0b84c2e45 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -242,7 +242,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "TCL M2523_3DBH_E"},
{ TUNER_ABSENT, "TCL M2523_3DIH_E"},
{ TUNER_ABSENT, "TCL MFPE05_2_U"},
- { TUNER_PHILIPS_FMD1216ME_MK3, "Philips FMD1216MEX"},
+ { TUNER_PHILIPS_FMD1216MEX_MK3, "Philips FMD1216MEX"},
{ TUNER_ABSENT, "Philips FRH2036B"},
{ TUNER_ABSENT, "Panasonic ENGF75_01GF"},
{ TUNER_ABSENT, "MaxLinear MXL5005"},
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
index 59166b76010..28421d386f1 100644
--- a/drivers/media/video/usbvideo/ibmcam.c
+++ b/drivers/media/video/usbvideo/ibmcam.c
@@ -258,7 +258,9 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h
(RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
{
#if 0 /* This code helps to detect new frame markers */
- info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3));
+ dev_info(&uvd->dev->dev,
+ "Header sig: 00 FF 00 %02X\n",
+ RING_QUEUE_PEEK(&uvd->dp, 3));
#endif
frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
if ((frame->header == HDRSIG_MODEL1_128x96) ||
@@ -266,7 +268,8 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h
(frame->header == HDRSIG_MODEL1_352x288))
{
#if 0
- info("Header found.");
+ dev_info(&uvd->dev->dev,
+ "Header found.\n");
#endif
RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
icam->has_hdr = 1;
@@ -295,7 +298,7 @@ case IBMCAM_MODEL_4:
(RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
{
#if 0
- info("Header found.");
+ dev_info(&uvd->dev->dev, "Header found.\n");
#endif
RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
icam->has_hdr = 1;
@@ -338,7 +341,7 @@ case IBMCAM_MODEL_4:
byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
frame->header = (byte3 << 8) | byte4;
#if 0
- info("Header found.");
+ dev_info(&uvd->dev->dev, "Header found.\n");
#endif
RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
icam->has_hdr = 1;
@@ -354,7 +357,8 @@ case IBMCAM_MODEL_4:
}
if (!icam->has_hdr) {
if (uvd->debug > 2)
- info("Skipping frame, no header");
+ dev_info(&uvd->dev->dev,
+ "Skipping frame, no header\n");
return scan_EndParse;
}
@@ -736,12 +740,12 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
* make black color and quit the horizontal scanning loop.
*/
if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
- const int j = i * V4L_BYTES_PER_PIXEL;
+ const int offset = i * V4L_BYTES_PER_PIXEL;
#if USES_IBMCAM_PUTPIXEL
/* Refresh 'f' because we don't use it much with PUTPIXEL */
- f = frame->data + (v4l_linesize * frame->curline) + j;
+ f = frame->data + (v4l_linesize * frame->curline) + offset;
#endif
- memset(f, 0, v4l_linesize - j);
+ memset(f, 0, v4l_linesize - offset);
break;
}
@@ -881,7 +885,9 @@ static enum ParseState ibmcam_model3_parse_lines(
*/
if ((frame->curline + 1) >= data_h) {
if (uvd->debug >= 3)
- info("Reached line %d. (frame is done)", frame->curline);
+ dev_info(&uvd->dev->dev,
+ "Reached line %d. (frame is done)\n",
+ frame->curline);
return scan_NextFrame;
}
@@ -954,8 +960,9 @@ static enum ParseState ibmcam_model3_parse_lines(
if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
if (uvd->debug >= 3) {
- info("All requested lines (%ld.) done.",
- VIDEOSIZE_Y(frame->request));
+ dev_info(&uvd->dev->dev,
+ "All requested lines (%ld.) done.\n",
+ VIDEOSIZE_Y(frame->request));
}
return scan_NextFrame;
} else
@@ -1000,7 +1007,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
*/
if ((frame->curline + 1) >= data_h) {
if (uvd->debug >= 3)
- info("Reached line %d. (frame is done)", frame->curline);
+ dev_info(&uvd->dev->dev,
+ "Reached line %d. (frame is done)\n",
+ frame->curline);
return scan_NextFrame;
}
@@ -1049,8 +1058,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
if (uvd->debug >= 3) {
- info("All requested lines (%ld.) done.",
- VIDEOSIZE_Y(frame->request));
+ dev_info(&uvd->dev->dev,
+ "All requested lines (%ld.) done.\n",
+ VIDEOSIZE_Y(frame->request));
}
return scan_NextFrame;
} else
@@ -1171,10 +1181,11 @@ static int ibmcam_veio(
sizeof(cp),
1000);
#if 0
- info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
- "(req=$%02x val=$%04x ind=$%04x)",
- cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
- req, value, index);
+ dev_info(&uvd->dev->dev,
+ "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+ "(req=$%02x val=$%04x ind=$%04x)\n",
+ cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+ req, value, index);
#endif
} else {
i = usb_control_msg(
@@ -1449,10 +1460,9 @@ static void ibmcam_adjust_contrast(struct uvd *uvd)
*/
static void ibmcam_change_lighting_conditions(struct uvd *uvd)
{
- static const char proc[] = "ibmcam_change_lighting_conditions";
-
if (debug > 0)
- info("%s: Set lighting to %hu.", proc, lighting);
+ dev_info(&uvd->dev->dev,
+ "%s: Set lighting to %hu.\n", __func__, lighting);
switch (IBMCAM_T(uvd)->camera_model) {
case IBMCAM_MODEL_1:
@@ -1495,8 +1505,6 @@ static void ibmcam_change_lighting_conditions(struct uvd *uvd)
*/
static void ibmcam_set_sharpness(struct uvd *uvd)
{
- static const char proc[] = "ibmcam_set_sharpness";
-
switch (IBMCAM_T(uvd)->camera_model) {
case IBMCAM_MODEL_1:
{
@@ -1505,7 +1513,8 @@ static void ibmcam_set_sharpness(struct uvd *uvd)
RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
if (debug > 0)
- info("%s: Set sharpness to %hu.", proc, sharpness);
+ dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n",
+ __func__, sharpness);
sv = sa[sharpness - SHARPNESS_MIN];
for (i=0; i < 2; i++) {
@@ -1564,11 +1573,11 @@ static void ibmcam_set_sharpness(struct uvd *uvd)
*/
static void ibmcam_set_brightness(struct uvd *uvd)
{
- static const char proc[] = "ibmcam_set_brightness";
static const unsigned short n = 1;
if (debug > 0)
- info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
+ dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n",
+ __func__, uvd->vpic.brightness);
switch (IBMCAM_T(uvd)->camera_model) {
case IBMCAM_MODEL_1:
@@ -2115,7 +2124,8 @@ static void ibmcam_model2_setup_after_video_if(struct uvd *uvd)
break;
}
if (uvd->debug > 0)
- info("Framerate (hardware): %hd.", hw_fps);
+ dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n",
+ hw_fps);
RESTRICT_TO_RANGE(hw_fps, 0, 31);
ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
}
@@ -3487,7 +3497,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
/* 01.01.08 - Added for RCA video in support -LO */
if(init_model3_input) {
if (debug > 0)
- info("Setting input to RCA.");
+ dev_info(&uvd->dev->dev, "Setting input to RCA.\n");
for (i=0; i < ARRAY_SIZE(initData); i++) {
ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
}
@@ -3685,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
unsigned char video_ep = 0;
if (debug >= 1)
- info("ibmcam_probe(%p,%u.)", intf, ifnum);
+ dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum);
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
@@ -3736,14 +3746,16 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
break;
}
- info("%s USB camera found (model %d, rev. 0x%04x)",
- brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
+ dev_info(&uvd->dev->dev,
+ "%s USB camera found (model %d, rev. 0x%04x)\n",
+ brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
} while (0);
/* Validate found interface: must have one ISO endpoint */
nas = intf->num_altsetting;
if (debug > 0)
- info("Number of alternate settings=%d.", nas);
+ dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n",
+ nas);
if (nas < 2) {
err("Too few alternate settings for this camera!");
return -ENODEV;
@@ -3787,7 +3799,9 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
actInterface = i;
maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0)
- info("Active setting=%d. maxPS=%d.", i, maxPS);
+ dev_info(&uvd->dev->dev,
+ "Active setting=%d. "
+ "maxPS=%d.\n", i, maxPS);
} else
err("More than one active alt. setting! Ignoring #%d.", i);
}
@@ -3826,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
RESTRICT_TO_RANGE(framerate, 0, 5);
break;
default:
- info("IBM camera: using 320x240");
+ dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n");
size = SIZE_320x240;
/* No break here */
case SIZE_320x240:
@@ -3855,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
canvasY = 120;
break;
default:
- info("IBM NetCamera: using 176x144");
+ dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n");
size = SIZE_176x144;
/* No break here */
case SIZE_176x144:
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index 1c180284ec6..da27a528798 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -229,7 +229,8 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
cam->input = input_dev = input_allocate_device();
if (!input_dev) {
- warn("Not enough memory for camera's input device\n");
+ dev_warn(&dev->dev,
+ "Not enough memory for camera's input device\n");
return;
}
@@ -243,8 +244,9 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
error = input_register_device(cam->input);
if (error) {
- warn("Failed to register camera's input device, err: %d\n",
- error);
+ dev_warn(&dev->dev,
+ "Failed to register camera's input device, err: %d\n",
+ error);
input_free_device(cam->input);
cam->input = NULL;
}
@@ -337,7 +339,8 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
}
if((sts > 0x01) && (sts < 0x80)) {
- info("unknown status %2.2x", sts);
+ dev_info(&uvd->dev->dev, "unknown status %2.2x\n",
+ sts);
bad++;
continue;
}
@@ -568,8 +571,12 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
fdrops = (0x80 + curframe - cam->lastframe) & 0x7F;
fdrops--;
if(fdrops) {
- info("Dropped %d frames (%d -> %d)", fdrops,
- cam->lastframe, curframe);
+ dev_info(&uvd->dev->dev,
+ "Dropped %d frames "
+ "(%d -> %d)\n",
+ fdrops,
+ cam->lastframe,
+ curframe);
}
}
cam->lastframe = curframe;
@@ -784,7 +791,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
if (dev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice));
+ dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n",
+ le16_to_cpu(dev->descriptor.bcdDevice));
RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
/* Validate found interface: must have one ISO endpoint */
@@ -925,7 +933,8 @@ static struct usb_device_id id_table[] = {
static int __init konicawc_init(void)
{
struct usbvideo_cb cbTbl;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
memset(&cbTbl, 0, sizeof(cbTbl));
cbTbl.probe = konicawc_probe;
cbTbl.setupOnOpen = konicawc_setup_on_open;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index 3d26a30abe1..4459b8a7f81 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -93,7 +93,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
cam->input = input_dev = input_allocate_device();
if (!input_dev) {
- warn("insufficient mem for cam input device");
+ dev_warn(&dev->dev, "insufficient mem for cam input device\n");
return;
}
@@ -107,8 +107,9 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
error = input_register_device(cam->input);
if (error) {
- warn("Failed to register camera's input device, err: %d\n",
- error);
+ dev_warn(&dev->dev,
+ "Failed to register camera's input device, err: %d\n",
+ error);
input_free_device(cam->input);
cam->input = NULL;
}
@@ -587,8 +588,9 @@ static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
dataurb->iso_frame_desc[i].offset;
if (st < 0) {
- warn("Data error: packet=%d. len=%d. status=%d.",
- i, n, st);
+ dev_warn(&uvd->dev->dev,
+ "Data error: packet=%d. len=%d. status=%d.\n",
+ i, n, st);
uvd->stats.iso_err_count++;
continue;
}
@@ -699,7 +701,7 @@ static void qcm_stop_data(struct uvd *uvd)
ret = qcm_camera_off(uvd);
if (ret)
- warn("couldn't turn the cam off.");
+ dev_warn(&uvd->dev->dev, "couldn't turn the cam off.\n");
uvd->streaming = 0;
@@ -1080,7 +1082,8 @@ static struct usbvideo_cb qcm_driver = {
static int __init qcm_init(void)
{
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return usbvideo_register(
&cams,
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
index 9544e644bf0..9714baab783 100644
--- a/drivers/media/video/usbvideo/ultracam.c
+++ b/drivers/media/video/usbvideo/ultracam.c
@@ -156,10 +156,11 @@ static int ultracam_veio(
sizeof(cp),
1000);
#if 1
- info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
- "(req=$%02x val=$%04x ind=$%04x)",
- cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
- req, value, index);
+ dev_info(&uvd->dev->dev,
+ "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+ "(req=$%02x val=$%04x ind=$%04x)\n",
+ cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+ req, value, index);
#endif
} else {
i = usb_control_msg(
@@ -517,19 +518,20 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
unsigned char video_ep = 0;
if (debug >= 1)
- info("ultracam_probe(%p)", intf);
+ dev_info(&intf->dev, "ultracam_probe\n");
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- info("IBM Ultra camera found (rev. 0x%04x)",
- le16_to_cpu(dev->descriptor.bcdDevice));
+ dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n",
+ le16_to_cpu(dev->descriptor.bcdDevice));
/* Validate found interface: must have one ISO endpoint */
nas = intf->num_altsetting;
if (debug > 0)
- info("Number of alternate settings=%d.", nas);
+ dev_info(&intf->dev, "Number of alternate settings=%d.\n",
+ nas);
if (nas < 8) {
err("Too few alternate settings for this camera!");
return -ENODEV;
@@ -576,7 +578,9 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
actInterface = i;
maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0)
- info("Active setting=%d. maxPS=%d.", i, maxPS);
+ dev_info(&intf->dev,
+ "Active setting=%d. "
+ "maxPS=%d.\n", i, maxPS);
} else {
/* Got another active alt. setting */
if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
@@ -584,8 +588,11 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
actInterface = i;
maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0) {
- info("Even better ctive setting=%d. maxPS=%d.",
- i, maxPS);
+ dev_info(&intf->dev,
+ "Even better ctive "
+ "setting=%d. "
+ "maxPS=%d.\n",
+ i, maxPS);
}
}
}
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index bf1bc2f69b0..07cd87d16f6 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -468,8 +468,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd)
percent = (100 * goodPackets) / allPackets;
else
percent = goodPackets / (allPackets / 100);
- info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",
- allPackets, badPackets, percent);
+ dev_info(&uvd->dev->dev,
+ "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n",
+ allPackets, badPackets, percent);
if (uvd->iso_packet_len > 0) {
unsigned long allBytes, xferBytes;
char multiplier = ' ';
@@ -497,8 +498,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd)
}
}
}
- info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",
- xferBytes, multiplier, percent);
+ dev_info(&uvd->dev->dev,
+ "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n",
+ xferBytes, multiplier, percent);
}
}
}
@@ -545,7 +547,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
{ /* For debugging purposes only */
char tmp[20];
usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
- info("testpattern: frame=%s", tmp);
+ dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp);
}
#endif
/* Form every scan line */
@@ -854,7 +856,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
usbvideo_ClientIncModCount(uvd);
if (uvd->debug > 0)
- info("%s(%p.)", __func__, intf);
+ dev_info(&intf->dev, "%s(%p.)\n", __func__, intf);
mutex_lock(&uvd->lock);
uvd->remove_pending = 1; /* Now all ISO data will be ignored */
@@ -870,14 +872,15 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
video_unregister_device(&uvd->vdev);
if (uvd->debug > 0)
- info("%s: Video unregistered.", __func__);
+ dev_info(&intf->dev, "%s: Video unregistered.\n", __func__);
if (uvd->user)
- info("%s: In use, disconnect pending.", __func__);
+ dev_info(&intf->dev, "%s: In use, disconnect pending.\n",
+ __func__);
else
usbvideo_CameraRelease(uvd);
mutex_unlock(&uvd->lock);
- info("USB camera disconnected.");
+ dev_info(&intf->dev, "USB camera disconnected.\n");
usbvideo_ClientDecModCount(uvd);
}
@@ -1015,14 +1018,17 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
return -EINVAL;
}
if (uvd->video_endp == 0) {
- info("%s: No video endpoint specified; data pump disabled.", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: No video endpoint specified; data pump disabled.\n",
+ __func__);
}
if (uvd->paletteBits == 0) {
err("%s: No palettes specified!", __func__);
return -EINVAL;
}
if (uvd->defaultPalette == 0) {
- info("%s: No default palette!", __func__);
+ dev_info(&uvd->dev->dev, "%s: No default palette!\n",
+ __func__);
}
uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
@@ -1031,25 +1037,29 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
if (uvd->debug > 0) {
- info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
- __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+ dev_info(&uvd->dev->dev,
+ "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n",
+ __func__, uvd->iface, uvd->video_endp,
+ uvd->paletteBits);
}
if (uvd->dev == NULL) {
err("%s: uvd->dev == NULL", __func__);
return -EINVAL;
}
uvd->vdev.parent = &uvd->dev->dev;
- if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ uvd->vdev.release = video_device_release_empty;
+ if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
err("%s: video_register_device failed", __func__);
return -EPIPE;
}
if (uvd->debug > 1) {
- info("%s: video_register_device() successful", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: video_register_device() successful\n", __func__);
}
- info("%s on /dev/video%d: canvas=%s videosize=%s",
- (uvd->handle != NULL) ? uvd->handle->drvName : "???",
- uvd->vdev.minor, tmp2, tmp1);
+ dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n",
+ (uvd->handle != NULL) ? uvd->handle->drvName : "???",
+ uvd->vdev.minor, tmp2, tmp1);
usb_get_dev(uvd->dev);
return 0;
@@ -1111,7 +1121,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
int i, errCode = 0;
if (uvd->debug > 1)
- info("%s($%p)", __func__, dev);
+ dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
if (0 < usbvideo_ClientIncModCount(uvd))
return -ENODEV;
@@ -1178,19 +1188,25 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
if (errCode == 0) {
if (VALID_CALLBACK(uvd, setupOnOpen)) {
if (uvd->debug > 1)
- info("%s: setupOnOpen callback", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: setupOnOpen callback\n",
+ __func__);
errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
if (errCode < 0) {
err("%s: setupOnOpen callback failed (%d.).",
__func__, errCode);
} else if (uvd->debug > 1) {
- info("%s: setupOnOpen callback successful", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: setupOnOpen callback successful\n",
+ __func__);
}
}
if (errCode == 0) {
uvd->settingsAdjusted = 0;
if (uvd->debug > 1)
- info("%s: Open succeeded.", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Open succeeded.\n",
+ __func__);
uvd->user++;
file->private_data = uvd;
}
@@ -1200,7 +1216,8 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
if (errCode != 0)
usbvideo_ClientDecModCount(uvd);
if (uvd->debug > 0)
- info("%s: Returning %d.", __func__, errCode);
+ dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__,
+ errCode);
return errCode;
}
@@ -1223,7 +1240,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
int i;
if (uvd->debug > 1)
- info("%s($%p)", __func__, dev);
+ dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
mutex_lock(&uvd->lock);
GET_CALLBACK(uvd, stopDataPump)(uvd);
@@ -1243,14 +1260,15 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
uvd->user--;
if (uvd->remove_pending) {
if (uvd->debug > 0)
- info("usbvideo_v4l_close: Final disconnect.");
+ dev_info(&uvd->dev->dev, "%s: Final disconnect.\n",
+ __func__);
usbvideo_CameraRelease(uvd);
}
mutex_unlock(&uvd->lock);
usbvideo_ClientDecModCount(uvd);
if (uvd->debug > 1)
- info("%s: Completed.", __func__);
+ dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__);
file->private_data = NULL;
return 0;
}
@@ -1364,8 +1382,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
struct video_mmap *vm = arg;
if (uvd->debug >= 1) {
- info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.",
- vm->frame, vm->width, vm->height, vm->format);
+ dev_info(&uvd->dev->dev,
+ "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n",
+ vm->frame, vm->width, vm->height, vm->format);
}
/*
* Check if the requested size is supported. If the requestor
@@ -1383,18 +1402,24 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
(vm->height > VIDEOSIZE_Y(uvd->canvas))) {
if (uvd->debug > 0) {
- info("VIDIOCMCAPTURE: Size=%dx%d too large; "
- "allowed only up to %ldx%ld", vm->width, vm->height,
- VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas));
+ dev_info(&uvd->dev->dev,
+ "VIDIOCMCAPTURE: Size=%dx%d "
+ "too large; allowed only up "
+ "to %ldx%ld\n", vm->width,
+ vm->height,
+ VIDEOSIZE_X(uvd->canvas),
+ VIDEOSIZE_Y(uvd->canvas));
}
return -EINVAL;
}
/* Check if the palette is supported */
if (((1L << vm->format) & uvd->paletteBits) == 0) {
if (uvd->debug > 0) {
- info("VIDIOCMCAPTURE: format=%d. not supported"
- " (paletteBits=$%08lx)",
- vm->format, uvd->paletteBits);
+ dev_info(&uvd->dev->dev,
+ "VIDIOCMCAPTURE: format=%d. "
+ "not supported "
+ "(paletteBits=$%08lx)\n",
+ vm->format, uvd->paletteBits);
}
return -EINVAL;
}
@@ -1422,7 +1447,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (uvd->debug >= 1)
- info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
+ dev_info(&uvd->dev->dev,
+ "VIDIOCSYNC: syncing to frame %d.\n",
+ *frameNum);
if (uvd->flags & FLAGS_NO_DECODING)
ret = usbvideo_GetFrame(uvd, *frameNum);
else if (VALID_CALLBACK(uvd, getFrame)) {
@@ -1504,7 +1531,9 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
return -EFAULT;
if (uvd->debug >= 1)
- info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
+ dev_info(&uvd->dev->dev,
+ "%s: %Zd. bytes, noblock=%d.\n",
+ __func__, count, noblock);
mutex_lock(&uvd->lock);
@@ -1685,18 +1714,21 @@ static void usbvideo_IsocIrq(struct urb *urb)
return;
#if 0
if (urb->actual_length > 0) {
- info("urb=$%p status=%d. errcount=%d. length=%d.",
- urb, urb->status, urb->error_count, urb->actual_length);
+ dev_info(&uvd->dev->dev,
+ "urb=$%p status=%d. errcount=%d. length=%d.\n",
+ urb, urb->status, urb->error_count,
+ urb->actual_length);
} else {
static int c = 0;
if (c++ % 100 == 0)
- info("No Isoc data");
+ dev_info(&uvd->dev->dev, "No Isoc data\n");
}
#endif
if (!uvd->streaming) {
if (uvd->debug >= 1)
- info("Not streaming, but interrupt!");
+ dev_info(&uvd->dev->dev,
+ "Not streaming, but interrupt!\n");
return;
}
@@ -1741,7 +1773,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
int i, errFlag;
if (uvd->debug > 1)
- info("%s($%p)", __func__, uvd);
+ dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
if (!CAMERA_IS_OPERATIONAL(uvd)) {
err("%s: Camera is not operational", __func__);
@@ -1789,7 +1821,9 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
uvd->streaming = 1;
if (uvd->debug > 1)
- info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
+ dev_info(&uvd->dev->dev,
+ "%s: streaming=1 video_endp=$%02x\n", __func__,
+ uvd->video_endp);
return 0;
}
@@ -1811,14 +1845,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
return;
if (uvd->debug > 1)
- info("%s($%p)", __func__, uvd);
+ dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
/* Unschedule all of the iso td's */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
usb_kill_urb(uvd->sbuf[i].urb);
}
if (uvd->debug > 1)
- info("%s: streaming=0", __func__);
+ dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__);
uvd->streaming = 0;
if (!uvd->remove_pending) {
@@ -1850,7 +1884,8 @@ static int usbvideo_NewFrame(struct uvd *uvd, int framenum)
int n;
if (uvd->debug > 1)
- info("usbvideo_NewFrame($%p,%d.)", uvd, framenum);
+ dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd,
+ framenum);
/* If we're not grabbing a frame right now and the other frame is */
/* ready to be grabbed into, then use it instead */
@@ -1955,12 +1990,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
struct usbvideo_frame *frame = &uvd->frame[frameNum];
if (uvd->debug >= 2)
- info("%s($%p,%d.)", __func__, uvd, frameNum);
+ dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd,
+ frameNum);
switch (frame->frameState) {
case FrameState_Unused:
if (uvd->debug >= 2)
- info("%s: FrameState_Unused", __func__);
+ dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n",
+ __func__);
return -EINVAL;
case FrameState_Ready:
case FrameState_Grabbing:
@@ -1970,7 +2007,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
redo:
if (!CAMERA_IS_OPERATIONAL(uvd)) {
if (uvd->debug >= 2)
- info("%s: Camera is not operational (1)", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Camera is not operational (1)\n",
+ __func__);
return -EIO;
}
ntries = 0;
@@ -1979,24 +2018,33 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
signalPending = signal_pending(current);
if (!CAMERA_IS_OPERATIONAL(uvd)) {
if (uvd->debug >= 2)
- info("%s: Camera is not operational (2)", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Camera is not "
+ "operational (2)\n", __func__);
return -EIO;
}
assert(uvd->fbuf != NULL);
if (signalPending) {
if (uvd->debug >= 2)
- info("%s: Signal=$%08x", __func__, signalPending);
+ dev_info(&uvd->dev->dev,
+ "%s: Signal=$%08x\n", __func__,
+ signalPending);
if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
usbvideo_TestPattern(uvd, 1, 0);
uvd->curframe = -1;
uvd->stats.frame_num++;
if (uvd->debug >= 2)
- info("%s: Forced test pattern screen", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Forced test "
+ "pattern screen\n",
+ __func__);
return 0;
} else {
/* Standard answer: Interrupted! */
if (uvd->debug >= 2)
- info("%s: Interrupted!", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Interrupted!\n",
+ __func__);
return -EINTR;
}
} else {
@@ -2010,8 +2058,10 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
}
} while (frame->frameState == FrameState_Grabbing);
if (uvd->debug >= 2) {
- info("%s: Grabbing done; state=%d. (%lu. bytes)",
- __func__, frame->frameState, frame->seqRead_Length);
+ dev_info(&uvd->dev->dev,
+ "%s: Grabbing done; state=%d. (%lu. bytes)\n",
+ __func__, frame->frameState,
+ frame->seqRead_Length);
}
if (frame->frameState == FrameState_Error) {
int ret = usbvideo_NewFrame(uvd, frameNum);
@@ -2048,7 +2098,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
}
frame->frameState = FrameState_Done_Hold;
if (uvd->debug >= 2)
- info("%s: Entered FrameState_Done_Hold state.", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: Entered FrameState_Done_Hold state.\n",
+ __func__);
return 0;
case FrameState_Done_Hold:
@@ -2059,7 +2111,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
* it will be released back into the wild to roam freely.
*/
if (uvd->debug >= 2)
- info("%s: FrameState_Done_Hold state.", __func__);
+ dev_info(&uvd->dev->dev,
+ "%s: FrameState_Done_Hold state.\n",
+ __func__);
return 0;
}
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index b7792451a29..7a127d6bfde 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -472,9 +472,8 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
static int
vicam_open(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct vicam_camera *cam =
- (struct vicam_camera *) dev->priv;
+ struct vicam_camera *cam = video_drvdata(file);
+
DBG("open\n");
if (!cam) {
@@ -488,20 +487,24 @@ vicam_open(struct inode *inode, struct file *file)
* rely on this fact forever.
*/
+ lock_kernel();
if (cam->open_count > 0) {
printk(KERN_INFO
"vicam_open called on already opened camera");
+ unlock_kernel();
return -EBUSY;
}
cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
if (!cam->raw_image) {
+ unlock_kernel();
return -ENOMEM;
}
cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
if (!cam->framebuf) {
kfree(cam->raw_image);
+ unlock_kernel();
return -ENOMEM;
}
@@ -509,6 +512,7 @@ vicam_open(struct inode *inode, struct file *file)
if (!cam->cntrlbuf) {
kfree(cam->raw_image);
rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+ unlock_kernel();
return -ENOMEM;
}
@@ -526,6 +530,7 @@ vicam_open(struct inode *inode, struct file *file)
cam->open_count++;
file->private_data = cam;
+ unlock_kernel();
return 0;
}
@@ -795,6 +800,7 @@ static struct video_device vicam_template = {
.name = "ViCam-based USB Camera",
.fops = &vicam_fops,
.minor = -1,
+ .release = video_device_release_empty,
};
/* table of devices that work with this driver */
@@ -859,14 +865,13 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
mutex_init(&cam->cam_lock);
- memcpy(&cam->vdev, &vicam_template,
- sizeof (vicam_template));
- cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only
+ memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template));
+ video_set_drvdata(&cam->vdev, cam);
cam->udev = dev;
cam->bulkEndpoint = bulkEndpoint;
- if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) {
kfree(cam);
printk(KERN_WARNING "video_register_device failed\n");
return -EIO;
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index c317ed7a848..9e4f5063997 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -45,10 +45,6 @@
#include <linux/workqueue.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "usbvision.h"
static unsigned int core_debug;
@@ -84,7 +80,8 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
#ifdef USBVISION_DEBUG
#define PDEBUG(level, fmt, args...) { \
if (core_debug & (level)) \
- info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+ printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+ __func__, __LINE__ , ## args); \
}
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index a6d00858b07..92427fdc145 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -47,7 +47,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
#define PDEBUG(level, fmt, args...) { \
if (i2c_debug & (level)) \
- info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+ printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+ __func__, __LINE__ , ## args); \
}
static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index b977116a0dd..77aeb39b275 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -69,10 +69,6 @@
#include <linux/workqueue.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "usbvision.h"
#include "usbvision-cards.h"
@@ -98,7 +94,8 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
#ifdef USBVISION_DEBUG
#define PDEBUG(level, fmt, args...) { \
if (video_debug & (level)) \
- info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+ printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+ __func__, __LINE__ , ## args); \
}
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
@@ -360,13 +357,12 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
*/
static int usbvision_v4l2_open(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
PDEBUG(DBG_IO, "open");
+ lock_kernel();
usbvision_reset_powerOffTimer(usbvision);
if (usbvision->user)
@@ -424,6 +420,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
usbvision_empty_framequeues(usbvision);
PDEBUG(DBG_IO, "success");
+ unlock_kernel();
return errCode;
}
@@ -437,9 +434,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
*/
static int usbvision_v4l2_close(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
PDEBUG(DBG_IO, "close");
mutex_lock(&usbvision->lock);
@@ -484,9 +479,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
static int vidioc_g_register (struct file *file, void *priv,
struct v4l2_register *reg)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int errCode;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
@@ -505,9 +498,7 @@ static int vidioc_g_register (struct file *file, void *priv,
static int vidioc_s_register (struct file *file, void *priv,
struct v4l2_register *reg)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int errCode;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
@@ -526,9 +517,7 @@ static int vidioc_s_register (struct file *file, void *priv,
static int vidioc_querycap (struct file *file, void *priv,
struct v4l2_capability *vc)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
strlcpy(vc->card,
@@ -548,9 +537,7 @@ static int vidioc_querycap (struct file *file, void *priv,
static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *vi)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int chan;
if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
@@ -603,9 +590,7 @@ static int vidioc_enum_input (struct file *file, void *priv,
static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
*input = usbvision->ctl_input;
return 0;
@@ -613,9 +598,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
if ((input >= usbvision->video_inputs) || (input < 0) )
return -EINVAL;
@@ -632,9 +615,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
+
usbvision->tvnormId=*id;
mutex_lock(&usbvision->lock);
@@ -650,9 +632,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *vt)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
if (!usbvision->have_tuner || vt->index) // Only tuner 0
return -EINVAL;
@@ -671,9 +651,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
static int vidioc_s_tuner (struct file *file, void *priv,
struct v4l2_tuner *vt)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
// Only no or one tuner for now
if (!usbvision->have_tuner || vt->index)
@@ -687,9 +665,7 @@ static int vidioc_s_tuner (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
freq->tuner = 0; // Only one tuner
if(usbvision->radio) {
@@ -705,9 +681,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
static int vidioc_s_frequency (struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
// Only no or one tuner for now
if (!usbvision->have_tuner || freq->tuner)
@@ -721,9 +695,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
memset(a,0,sizeof(*a));
if(usbvision->radio) {
@@ -748,9 +720,7 @@ static int vidioc_s_audio (struct file *file, void *fh,
static int vidioc_queryctrl (struct file *file, void *priv,
struct v4l2_queryctrl *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int id=ctrl->id;
memset(ctrl,0,sizeof(*ctrl));
@@ -767,9 +737,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
return 0;
@@ -778,9 +746,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
return 0;
@@ -789,9 +755,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
static int vidioc_reqbufs (struct file *file,
void *priv, struct v4l2_requestbuffers *vr)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int ret;
RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
@@ -819,9 +783,7 @@ static int vidioc_reqbufs (struct file *file,
static int vidioc_querybuf (struct file *file,
void *priv, struct v4l2_buffer *vb)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
struct usbvision_frame *frame;
/* FIXME : must control
@@ -857,9 +819,7 @@ static int vidioc_querybuf (struct file *file,
static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
struct usbvision_frame *frame;
unsigned long lock_flags;
@@ -896,9 +856,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int ret;
struct usbvision_frame *f;
unsigned long lock_flags;
@@ -939,9 +897,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
usbvision->streaming = Stream_On;
@@ -953,9 +909,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
static int vidioc_streamoff(struct file *file,
void *priv, enum v4l2_buf_type type)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -988,9 +942,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *vf)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
vf->fmt.pix.width = usbvision->curwidth;
vf->fmt.pix.height = usbvision->curheight;
vf->fmt.pix.pixelformat = usbvision->palette.format;
@@ -1006,9 +958,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *vf)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int formatIdx;
/* Find requested format in available ones */
@@ -1036,9 +986,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *vf)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int ret;
if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) {
@@ -1066,9 +1014,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int noblock = file->f_flags & O_NONBLOCK;
unsigned long lock_flags;
@@ -1177,10 +1123,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
start = vma->vm_start;
void *pos;
u32 i;
-
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
PDEBUG(DBG_MMAP, "mmap");
@@ -1237,9 +1180,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
*/
static int usbvision_radio_open(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
PDEBUG(DBG_IO, "%s:", __func__);
@@ -1289,9 +1230,7 @@ out:
static int usbvision_radio_close(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision =
- (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
PDEBUG(DBG_IO, "");
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 6ef3e5297de..f16aafe9cf1 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -83,6 +83,22 @@ static struct uvc_control_info uvc_ctrls[] = {
},
{
.entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+ .index = 6,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL,
+ .index = 7,
+ .size = 4,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
.selector = PU_BACKLIGHT_COMPENSATION_CONTROL,
.index = 8,
.size = 2,
@@ -114,6 +130,60 @@ static struct uvc_control_info uvc_ctrls[] = {
| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
},
{
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+ .index = 12,
+ .size = 1,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+ | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+ .index = 13,
+ .size = 1,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+ | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_DIGITAL_MULTIPLIER_CONTROL,
+ .index = 14,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
+ .index = 15,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL,
+ .index = 16,
+ .size = 1,
+ .flags = UVC_CONTROL_GET_CUR,
+ },
+ {
+ .entity = UVC_GUID_UVC_PROCESSING,
+ .selector = PU_ANALOG_LOCK_STATUS_CONTROL,
+ .index = 17,
+ .size = 1,
+ .flags = UVC_CONTROL_GET_CUR,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_SCANNING_MODE_CONTROL,
+ .index = 0,
+ .size = 1,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+ | UVC_CONTROL_RESTORE,
+ },
+ {
.entity = UVC_GUID_UVC_CAMERA,
.selector = CT_AE_MODE_CONTROL,
.index = 1,
@@ -140,6 +210,14 @@ static struct uvc_control_info uvc_ctrls[] = {
},
{
.entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL,
+ .index = 4,
+ .size = 1,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+ | UVC_CONTROL_RESTORE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
.selector = CT_FOCUS_ABSOLUTE_CONTROL,
.index = 5,
.size = 2,
@@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = {
},
{
.entity = UVC_GUID_UVC_CAMERA,
- .selector = CT_FOCUS_AUTO_CONTROL,
- .index = 17,
- .size = 1,
- .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
- | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+ .selector = CT_FOCUS_RELATIVE_CONTROL,
+ .index = 6,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_AUTO_UPDATE,
},
{
- .entity = UVC_GUID_UVC_PROCESSING,
- .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
- .index = 12,
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_IRIS_ABSOLUTE_CONTROL,
+ .index = 7,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_IRIS_RELATIVE_CONTROL,
+ .index = 8,
.size = 1,
.flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
- | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+ | UVC_CONTROL_AUTO_UPDATE,
},
{
- .entity = UVC_GUID_UVC_PROCESSING,
- .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
- .index = 6,
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_ZOOM_ABSOLUTE_CONTROL,
+ .index = 9,
.size = 2,
.flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
},
{
- .entity = UVC_GUID_UVC_PROCESSING,
- .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_ZOOM_RELATIVE_CONTROL,
+ .index = 10,
+ .size = 3,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_PANTILT_ABSOLUTE_CONTROL,
+ .index = 11,
+ .size = 8,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_PANTILT_RELATIVE_CONTROL,
+ .index = 12,
+ .size = 4,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_ROLL_ABSOLUTE_CONTROL,
.index = 13,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_ROLL_RELATIVE_CONTROL,
+ .index = 14,
+ .size = 2,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ | UVC_CONTROL_AUTO_UPDATE,
+ },
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_FOCUS_AUTO_CONTROL,
+ .index = 17,
.size = 1,
.flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
},
{
- .entity = UVC_GUID_UVC_PROCESSING,
- .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL,
- .index = 7,
- .size = 4,
- .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = CT_PRIVACY_CONTROL,
+ .index = 18,
+ .size = 1,
+ .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
},
};
@@ -592,7 +718,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
if (ctrl == NULL)
return -EINVAL;
- data = kmalloc(8, GFP_KERNEL);
+ data = kmalloc(ctrl->info->size, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
for (i = 0; i < entity->ncontrols; ++i) {
ctrl = &entity->controls[i];
- if (ctrl->info == NULL || !ctrl->dirty)
+ if (ctrl->info == NULL)
+ continue;
+
+ /* Reset the loaded flag for auto-update controls that were
+ * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
+ * uvc_ctrl_get from using the cached value.
+ */
+ if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE)
+ ctrl->loaded = 0;
+
+ if (!ctrl->dirty)
continue;
if (!rollback)
@@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
ctrl->info->size);
- if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
- ctrl->loaded = 0;
-
ctrl->dirty = 0;
if (ret < 0)
@@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video,
if (ret < 0)
return ret;
- if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
- ctrl->loaded = 1;
+ ctrl->loaded = 1;
}
xctrl->value = uvc_get_le_value(
@@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video,
return ret;
}
- if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
- ctrl->loaded = 1;
+ ctrl->loaded = 1;
}
if (!ctrl->dirty) {
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 7e102034d38..d7ad060640b 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
return uvc_video_suspend(&dev->video);
}
-static int uvc_resume(struct usb_interface *intf)
+static int __uvc_resume(struct usb_interface *intf, int reset)
{
struct uvc_device *dev = usb_get_intfdata(intf);
int ret;
@@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf)
intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
- if ((ret = uvc_ctrl_resume_device(dev)) < 0)
+ if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0)
return ret;
return uvc_status_resume(dev);
@@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf)
return uvc_video_resume(&dev->video);
}
+static int uvc_resume(struct usb_interface *intf)
+{
+ return __uvc_resume(intf, 0);
+}
+
+static int uvc_reset_resume(struct usb_interface *intf)
+{
+ return __uvc_resume(intf, 1);
+}
+
/* ------------------------------------------------------------------------
* Driver initialization and cleanup
*/
@@ -1902,6 +1912,24 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Compaq Presario B1200 - Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0104,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Acer Travelmate 7720 - Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0105,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Medion Akoya Mini E1210 - Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1920,6 +1948,24 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Fujitsu Amilo SI2636 - Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0202,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Advent 4211 - Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0203,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1952,6 +1998,7 @@ struct uvc_driver uvc_driver = {
.disconnect = uvc_disconnect,
.suspend = uvc_suspend,
.resume = uvc_resume,
+ .reset_resume = uvc_reset_resume,
.id_table = uvc_ids,
.supports_autosuspend = 1,
},
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
index 75e678ac54e..5d60b264d59 100644
--- a/drivers/media/video/uvc/uvc_status.c
+++ b/drivers/media/video/uvc/uvc_status.c
@@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev)
uvc_input_init(dev);
+ dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
+ if (dev->status == NULL)
+ return -ENOMEM;
+
dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (dev->int_urb == NULL)
+ if (dev->int_urb == NULL) {
+ kfree(dev->status);
return -ENOMEM;
+ }
pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
@@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev)
interval = fls(interval) - 1;
usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
- dev->status, sizeof dev->status, uvc_status_complete,
+ dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
dev, interval);
return usb_submit_urb(dev->int_urb, GFP_KERNEL);
@@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev)
{
usb_kill_urb(dev->int_urb);
usb_free_urb(dev->int_urb);
+ kfree(dev->status);
uvc_input_cleanup(dev);
}
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index d7bd71be40a..78e4c4e09d8 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -400,15 +400,13 @@ static int uvc_has_privileges(struct uvc_fh *handle)
static int uvc_v4l2_open(struct inode *inode, struct file *file)
{
- struct video_device *vdev;
struct uvc_video_device *video;
struct uvc_fh *handle;
int ret = 0;
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
mutex_lock(&uvc_driver.open_mutex);
- vdev = video_devdata(file);
- video = video_get_drvdata(vdev);
+ video = video_drvdata(file);
if (video->dev->state & UVC_DEV_DISCONNECTED) {
ret = -ENODEV;
@@ -440,8 +438,7 @@ done:
static int uvc_v4l2_release(struct inode *inode, struct file *file)
{
- struct video_device *vdev = video_devdata(file);
- struct uvc_video_device *video = video_get_drvdata(vdev);
+ struct uvc_video_device *video = video_drvdata(file);
struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
@@ -845,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
if (ret < 0)
return ret;
- if (!(video->streaming->cur_format->flags &
- UVC_FMT_FLAG_COMPRESSED))
- video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
-
rb->count = ret;
ret = 0;
break;
@@ -1031,8 +1024,7 @@ static struct vm_operations_struct uvc_vm_ops = {
static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct video_device *vdev = video_devdata(file);
- struct uvc_video_device *video = video_get_drvdata(vdev);
+ struct uvc_video_device *video = video_drvdata(file);
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
unsigned long addr, start, size;
@@ -1085,8 +1077,7 @@ done:
static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
{
- struct video_device *vdev = video_devdata(file);
- struct uvc_video_device *video = video_get_drvdata(vdev);
+ struct uvc_video_device *video = video_drvdata(file);
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 6854ac78a16..b7bb23820d8 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -455,7 +455,8 @@ static void uvc_video_decode_isoc(struct urb *urb,
urb->iso_frame_desc[i].actual_length - ret);
/* Process the header again. */
- uvc_video_decode_end(video, buf, mem, ret);
+ uvc_video_decode_end(video, buf, mem,
+ urb->iso_frame_desc[i].actual_length);
if (buf->state == UVC_BUF_STATE_DONE ||
buf->state == UVC_BUF_STATE_ERROR)
@@ -512,7 +513,7 @@ static void uvc_video_decode_bulk(struct urb *urb,
video->bulk.payload_size >= video->bulk.max_payload_size) {
if (!video->bulk.skip_payload && buf != NULL) {
uvc_video_decode_end(video, buf, video->bulk.header,
- video->bulk.header_size);
+ video->bulk.payload_size);
if (buf->state == UVC_BUF_STATE_DONE ||
buf->state == UVC_BUF_STATE_ERROR)
buf = uvc_queue_next_buffer(&video->queue, buf);
@@ -655,7 +656,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
if (size > UVC_MAX_FRAME_SIZE)
return -EINVAL;
- npackets = (size + psize - 1) / psize;
+ npackets = DIV_ROUND_UP(size, psize);
if (npackets > UVC_MAX_ISO_PACKETS)
npackets = UVC_MAX_ISO_PACKETS;
@@ -970,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable)
return 0;
}
+ if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED)
+ video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
+ else
+ video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
+
if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
return ret;
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index bafe3406e30..9a6bc1aafb1 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -303,6 +303,8 @@ struct uvc_xu_control {
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
/* Maximum number of video buffers. */
#define UVC_MAX_VIDEO_BUFFERS 32
+/* Maximum status buffer size in bytes of interrupt URB. */
+#define UVC_MAX_STATUS_SIZE 16
#define UVC_CTRL_CONTROL_TIMEOUT 300
#define UVC_CTRL_STREAMING_TIMEOUT 1000
@@ -634,7 +636,7 @@ struct uvc_device {
/* Status Interrupt Endpoint */
struct usb_host_endpoint *int_ep;
struct urb *int_urb;
- __u8 status[16];
+ __u8 *status;
struct input_dev *input;
/* Video Streaming interfaces */
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 79937d1031f..928cb403737 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -36,10 +36,6 @@
#include <asm/system.h>
#include <asm/pgtable.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 88ca1310441..846763d7349 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -60,10 +60,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include <linux/videodev2.h>
MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
@@ -187,9 +183,11 @@ const char **v4l2_ctrl_get_menu(u32 id)
NULL
};
static const char *mpeg_audio_encoding[] = {
- "Layer I",
- "Layer II",
- "Layer III",
+ "MPEG-1/2 Layer I",
+ "MPEG-1/2 Layer II",
+ "MPEG-1/2 Layer III",
+ "MPEG-2/4 AAC",
+ "AC-3",
NULL
};
static const char *mpeg_audio_l1_bitrate[] = {
@@ -243,6 +241,28 @@ const char **v4l2_ctrl_get_menu(u32 id)
"320 kbps",
NULL
};
+ static const char *mpeg_audio_ac3_bitrate[] = {
+ "32 kbps",
+ "40 kbps",
+ "48 kbps",
+ "56 kbps",
+ "64 kbps",
+ "80 kbps",
+ "96 kbps",
+ "112 kbps",
+ "128 kbps",
+ "160 kbps",
+ "192 kbps",
+ "224 kbps",
+ "256 kbps",
+ "320 kbps",
+ "384 kbps",
+ "448 kbps",
+ "512 kbps",
+ "576 kbps",
+ "640 kbps",
+ NULL
+ };
static const char *mpeg_audio_mode[] = {
"Stereo",
"Joint Stereo",
@@ -271,6 +291,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
static const char *mpeg_video_encoding[] = {
"MPEG-1",
"MPEG-2",
+ "MPEG-4 AVC",
NULL
};
static const char *mpeg_video_aspect[] = {
@@ -311,6 +332,8 @@ const char **v4l2_ctrl_get_menu(u32 id)
return mpeg_audio_l2_bitrate;
case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
return mpeg_audio_l3_bitrate;
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ return mpeg_audio_ac3_bitrate;
case V4L2_CID_MPEG_AUDIO_MODE:
return mpeg_audio_mode;
case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
@@ -335,62 +358,73 @@ const char **v4l2_ctrl_get_menu(u32 id)
}
EXPORT_SYMBOL(v4l2_ctrl_get_menu);
-/* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+/* Return the control name. */
+const char *v4l2_ctrl_get_name(u32 id)
{
- const char *name;
-
- qctrl->flags = 0;
- switch (qctrl->id) {
+ switch (id) {
/* USER controls */
- case V4L2_CID_USER_CLASS: name = "User Controls"; break;
- case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break;
- case V4L2_CID_AUDIO_MUTE: name = "Mute"; break;
- case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break;
- case V4L2_CID_AUDIO_BASS: name = "Bass"; break;
- case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break;
- case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break;
- case V4L2_CID_BRIGHTNESS: name = "Brightness"; break;
- case V4L2_CID_CONTRAST: name = "Contrast"; break;
- case V4L2_CID_SATURATION: name = "Saturation"; break;
- case V4L2_CID_HUE: name = "Hue"; break;
+ case V4L2_CID_USER_CLASS: return "User Controls";
+ case V4L2_CID_AUDIO_VOLUME: return "Volume";
+ case V4L2_CID_AUDIO_MUTE: return "Mute";
+ case V4L2_CID_AUDIO_BALANCE: return "Balance";
+ case V4L2_CID_AUDIO_BASS: return "Bass";
+ case V4L2_CID_AUDIO_TREBLE: return "Treble";
+ case V4L2_CID_AUDIO_LOUDNESS: return "Loudness";
+ case V4L2_CID_BRIGHTNESS: return "Brightness";
+ case V4L2_CID_CONTRAST: return "Contrast";
+ case V4L2_CID_SATURATION: return "Saturation";
+ case V4L2_CID_HUE: return "Hue";
/* MPEG controls */
- case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break;
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break;
- case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break;
- case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break;
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break;
- case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break;
- case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break;
- case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break;
- case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break;
- case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break;
- case V4L2_CID_MPEG_AUDIO_MUTE: name = "Audio Mute"; break;
- case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break;
- case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break;
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break;
- case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break;
- case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break;
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break;
- case V4L2_CID_MPEG_VIDEO_MUTE: name = "Video Mute"; break;
- case V4L2_CID_MPEG_VIDEO_MUTE_YUV: name = "Video Mute YUV"; break;
- case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break;
- case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break;
- case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break;
- case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break;
- case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break;
- case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break;
- case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break;
- case V4L2_CID_MPEG_STREAM_VBI_FMT: name = "Stream VBI Format"; break;
+ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
+ case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency";
+ case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding";
+ case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate";
+ case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate";
+ case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate";
+ case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate";
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate";
+ case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode";
+ case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension";
+ case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis";
+ case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC";
+ case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute";
+ case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding";
+ case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect";
+ case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames";
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size";
+ case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure";
+ case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown";
+ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode";
+ case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate";
+ case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate";
+ case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
+ case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute";
+ case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
+ case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type";
+ case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID";
+ case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID";
+ case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID";
+ case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID";
+ case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID";
+ case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID";
+ case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format";
default:
- return -EINVAL;
+ return NULL;
}
+}
+EXPORT_SYMBOL(v4l2_ctrl_get_name);
+
+/* Fill in a struct v4l2_queryctrl */
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+ const char *name = v4l2_ctrl_get_name(qctrl->id);
+
+ qctrl->flags = 0;
+ if (name == NULL)
+ return -EINVAL;
+
switch (qctrl->id) {
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_LOUDNESS:
@@ -407,6 +441,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
case V4L2_CID_MPEG_AUDIO_MODE:
case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
case V4L2_CID_MPEG_AUDIO_EMPHASIS:
@@ -493,7 +528,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
case V4L2_CID_MPEG_AUDIO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_1,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1,
+ V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
return v4l2_ctrl_query_fill(qctrl,
@@ -510,6 +545,13 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
V4L2_MPEG_AUDIO_L3_BITRATE_32K,
V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1,
V4L2_MPEG_AUDIO_L3_BITRATE_192K);
+ case V4L2_CID_MPEG_AUDIO_AAC_BITRATE:
+ return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000);
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ return v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_32K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K);
case V4L2_CID_MPEG_AUDIO_MODE:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_MODE_STEREO,
@@ -535,7 +577,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
case V4L2_CID_MPEG_VIDEO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
case V4L2_CID_MPEG_VIDEO_ASPECT:
return v4l2_ctrl_query_fill(qctrl,
@@ -594,12 +636,17 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
- the menu. The qctrl pointer may be NULL, in which case it is ignored. */
+ the menu. The qctrl pointer may be NULL, in which case it is ignored.
+ If menu_items is NULL, then the menu items are retrieved using
+ v4l2_ctrl_get_menu. */
int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
const char **menu_items)
{
int i;
+ qmenu->reserved = 0;
+ if (menu_items == NULL)
+ menu_items = v4l2_ctrl_get_menu(qmenu->id);
if (menu_items == NULL ||
(qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
return -EINVAL;
@@ -607,11 +654,31 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc
if (menu_items[i] == NULL || menu_items[i][0] == '\0')
return -EINVAL;
snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]);
- qmenu->reserved = 0;
return 0;
}
EXPORT_SYMBOL(v4l2_ctrl_query_menu);
+/* Fill in a struct v4l2_querymenu based on the specified array of valid
+ menu items (terminated by V4L2_CTRL_MENU_IDS_END).
+ Use this if there are 'holes' in the list of valid menu items. */
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
+{
+ const char **menu_items = v4l2_ctrl_get_menu(qmenu->id);
+
+ qmenu->reserved = 0;
+ if (menu_items == NULL || ids == NULL)
+ return -EINVAL;
+ while (*ids != V4L2_CTRL_MENU_IDS_END) {
+ if (*ids++ == qmenu->index) {
+ snprintf(qmenu->name, sizeof(qmenu->name),
+ menu_items[qmenu->index]);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
+
/* ctrl_classes points to an array of u32 pointers, the last element is
a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
Each array must be sorted low to high and belong to the same control
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 6f36006aecd..ccd6566a515 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -42,6 +42,7 @@ static ssize_t show_index(struct device *cd,
struct device_attribute *attr, char *buf)
{
struct video_device *vfd = container_of(cd, struct video_device, dev);
+
return sprintf(buf, "%i\n", vfd->index);
}
@@ -49,6 +50,7 @@ static ssize_t show_name(struct device *cd,
struct device_attribute *attr, char *buf)
{
struct video_device *vfd = container_of(cd, struct video_device, dev);
+
return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
}
@@ -58,12 +60,16 @@ static struct device_attribute video_device_attrs[] = {
__ATTR_NULL
};
+/*
+ * Active devices
+ */
+static struct video_device *video_device[VIDEO_NUM_DEVICES];
+static DEFINE_MUTEX(videodev_lock);
+static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES);
+
struct video_device *video_device_alloc(void)
{
- struct video_device *vfd;
-
- vfd = kzalloc(sizeof(*vfd), GFP_KERNEL);
- return vfd;
+ return kzalloc(sizeof(struct video_device), GFP_KERNEL);
}
EXPORT_SYMBOL(video_device_alloc);
@@ -73,16 +79,52 @@ void video_device_release(struct video_device *vfd)
}
EXPORT_SYMBOL(video_device_release);
+void video_device_release_empty(struct video_device *vfd)
+{
+ /* Do nothing */
+ /* Only valid when the video_device struct is a static. */
+}
+EXPORT_SYMBOL(video_device_release_empty);
+
+/* Called when the last user of the character device is gone. */
+static void v4l2_chardev_release(struct kobject *kobj)
+{
+ struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj);
+
+ mutex_lock(&videodev_lock);
+ if (video_device[vfd->minor] != vfd) {
+ mutex_unlock(&videodev_lock);
+ BUG();
+ return;
+ }
+
+ /* Free up this device for reuse */
+ video_device[vfd->minor] = NULL;
+ clear_bit(vfd->num, video_nums[vfd->vfl_type]);
+ mutex_unlock(&videodev_lock);
+
+ /* Release the character device */
+ vfd->cdev_release(kobj);
+ /* Release video_device and perform other
+ cleanups as needed. */
+ if (vfd->release)
+ vfd->release(vfd);
+}
+
+/* The new kobj_type for the character device */
+static struct kobj_type v4l2_ktype_cdev_default = {
+ .release = v4l2_chardev_release,
+};
+
static void video_release(struct device *cd)
{
struct video_device *vfd = container_of(cd, struct video_device, dev);
-#if 1
- /* needed until all drivers are fixed */
- if (!vfd->release)
- return;
-#endif
- vfd->release(vfd);
+ /* It's now safe to delete the char device.
+ This will either trigger the v4l2_chardev_release immediately (if
+ the refcount goes to 0) or later when the last user of the
+ character device closes it. */
+ cdev_del(&vfd->cdev);
}
static struct class video_class = {
@@ -91,87 +133,12 @@ static struct class video_class = {
.dev_release = video_release,
};
-/*
- * Active devices
- */
-
-static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DEFINE_MUTEX(videodev_lock);
-
struct video_device *video_devdata(struct file *file)
{
return video_device[iminor(file->f_path.dentry->d_inode)];
}
EXPORT_SYMBOL(video_devdata);
-/*
- * Open a video device - FIXME: Obsoleted
- */
-static int video_open(struct inode *inode, struct file *file)
-{
- unsigned int minor = iminor(inode);
- int err = 0;
- struct video_device *vfl;
- const struct file_operations *old_fops;
-
- if (minor >= VIDEO_NUM_DEVICES)
- return -ENODEV;
- lock_kernel();
- mutex_lock(&videodev_lock);
- vfl = video_device[minor];
- if (vfl == NULL) {
- mutex_unlock(&videodev_lock);
- request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
- mutex_lock(&videodev_lock);
- vfl = video_device[minor];
- if (vfl == NULL) {
- mutex_unlock(&videodev_lock);
- unlock_kernel();
- return -ENODEV;
- }
- }
- old_fops = file->f_op;
- file->f_op = fops_get(vfl->fops);
- if (file->f_op->open)
- err = file->f_op->open(inode, file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
- mutex_unlock(&videodev_lock);
- unlock_kernel();
- return err;
-}
-
-/*
- * open/release helper functions -- handle exclusive opens
- * Should be removed soon
- */
-int video_exclusive_open(struct inode *inode, struct file *file)
-{
- struct video_device *vfl = video_devdata(file);
- int retval = 0;
-
- mutex_lock(&vfl->lock);
- if (vfl->users)
- retval = -EBUSY;
- else
- vfl->users++;
- mutex_unlock(&vfl->lock);
- return retval;
-}
-EXPORT_SYMBOL(video_exclusive_open);
-
-int video_exclusive_release(struct inode *inode, struct file *file)
-{
- struct video_device *vfl = video_devdata(file);
-
- vfl->users--;
- return 0;
-}
-EXPORT_SYMBOL(video_exclusive_release);
-
/**
* get_index - assign stream number based on parent device
* @vdev: video_device to assign index number to, vdev->dev should be assigned
@@ -252,60 +219,101 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
int index)
{
int i = 0;
- int base;
- int end;
int ret;
- char *name_base;
+ int minor_offset = 0;
+ int minor_cnt = VIDEO_NUM_DEVICES;
+ const char *name_base;
+ void *priv = video_get_drvdata(vfd);
+
+ /* the release callback MUST be present */
+ BUG_ON(!vfd->release);
+
+ if (vfd == NULL)
+ return -EINVAL;
switch (type) {
case VFL_TYPE_GRABBER:
- base = MINOR_VFL_TYPE_GRABBER_MIN;
- end = MINOR_VFL_TYPE_GRABBER_MAX+1;
name_base = "video";
break;
case VFL_TYPE_VTX:
- base = MINOR_VFL_TYPE_VTX_MIN;
- end = MINOR_VFL_TYPE_VTX_MAX+1;
name_base = "vtx";
break;
case VFL_TYPE_VBI:
- base = MINOR_VFL_TYPE_VBI_MIN;
- end = MINOR_VFL_TYPE_VBI_MAX+1;
name_base = "vbi";
break;
case VFL_TYPE_RADIO:
- base = MINOR_VFL_TYPE_RADIO_MIN;
- end = MINOR_VFL_TYPE_RADIO_MAX+1;
name_base = "radio";
break;
default:
printk(KERN_ERR "%s called with unknown type: %d\n",
__func__, type);
- return -1;
+ return -EINVAL;
}
+ vfd->vfl_type = type;
+
+#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
+ /* Keep the ranges for the first four types for historical
+ * reasons.
+ * Newer devices (not yet in place) should use the range
+ * of 128-191 and just pick the first free minor there
+ * (new style). */
+ switch (type) {
+ case VFL_TYPE_GRABBER:
+ minor_offset = 0;
+ minor_cnt = 64;
+ break;
+ case VFL_TYPE_RADIO:
+ minor_offset = 64;
+ minor_cnt = 64;
+ break;
+ case VFL_TYPE_VTX:
+ minor_offset = 192;
+ minor_cnt = 32;
+ break;
+ case VFL_TYPE_VBI:
+ minor_offset = 224;
+ minor_cnt = 32;
+ break;
+ default:
+ minor_offset = 128;
+ minor_cnt = 64;
+ break;
+ }
+#endif
+
+ /* Initialize the character device */
+ cdev_init(&vfd->cdev, vfd->fops);
+ vfd->cdev.owner = vfd->fops->owner;
/* pick a minor number */
mutex_lock(&videodev_lock);
- if (nr >= 0 && nr < end-base) {
- /* use the one the driver asked for */
- i = base + nr;
- if (NULL != video_device[i]) {
- mutex_unlock(&videodev_lock);
- return -ENFILE;
- }
- } else {
- /* use first free */
- for (i = base; i < end; i++)
- if (NULL == video_device[i])
- break;
- if (i == end) {
- mutex_unlock(&videodev_lock);
- return -ENFILE;
- }
+ nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr);
+ if (nr == minor_cnt)
+ nr = find_first_zero_bit(video_nums[type], minor_cnt);
+ if (nr == minor_cnt) {
+ printk(KERN_ERR "could not get a free kernel number\n");
+ mutex_unlock(&videodev_lock);
+ return -ENFILE;
}
- video_device[i] = vfd;
- vfd->vfl_type = type;
- vfd->minor = i;
+#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
+ /* 1-on-1 mapping of kernel number to minor number */
+ i = nr;
+#else
+ /* The kernel number and minor numbers are independent */
+ for (i = 0; i < VIDEO_NUM_DEVICES; i++)
+ if (video_device[i] == NULL)
+ break;
+ if (i == VIDEO_NUM_DEVICES) {
+ mutex_unlock(&videodev_lock);
+ printk(KERN_ERR "could not get a free minor\n");
+ return -ENFILE;
+ }
+#endif
+ vfd->minor = i + minor_offset;
+ vfd->num = nr;
+ set_bit(nr, video_nums[type]);
+ BUG_ON(video_device[vfd->minor]);
+ video_device[vfd->minor] = vfd;
ret = get_index(vfd, index);
vfd->index = ret;
@@ -317,35 +325,41 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
goto fail_minor;
}
- mutex_init(&vfd->lock);
-
+ ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: cdev_add failed\n", __func__);
+ goto fail_minor;
+ }
/* sysfs class */
- memset(&vfd->dev, 0x00, sizeof(vfd->dev));
+ memset(&vfd->dev, 0, sizeof(vfd->dev));
+ /* The memset above cleared the device's drvdata, so
+ put back the copy we made earlier. */
+ video_set_drvdata(vfd, priv);
vfd->dev.class = &video_class;
vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
if (vfd->parent)
vfd->dev.parent = vfd->parent;
- sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base);
+ sprintf(vfd->dev.bus_id, "%s%d", name_base, nr);
ret = device_register(&vfd->dev);
if (ret < 0) {
printk(KERN_ERR "%s: device_register failed\n", __func__);
- goto fail_minor;
+ goto del_cdev;
}
-
-#if 1
- /* needed until all drivers are fixed */
- if (!vfd->release)
- printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
- "Please fix your driver for proper sysfs support, see "
- "http://lwn.net/Articles/36850/\n", vfd->name);
-#endif
+ /* Remember the cdev's release function */
+ vfd->cdev_release = vfd->cdev.kobj.ktype->release;
+ /* Install our own */
+ vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default;
return 0;
+del_cdev:
+ cdev_del(&vfd->cdev);
+
fail_minor:
mutex_lock(&videodev_lock);
video_device[vfd->minor] = NULL;
- vfd->minor = -1;
+ clear_bit(vfd->num, video_nums[type]);
mutex_unlock(&videodev_lock);
+ vfd->minor = -1;
return ret;
}
EXPORT_SYMBOL(video_register_device_index);
@@ -360,42 +374,29 @@ EXPORT_SYMBOL(video_register_device_index);
void video_unregister_device(struct video_device *vfd)
{
- mutex_lock(&videodev_lock);
- if (video_device[vfd->minor] != vfd)
- panic("videodev: bad unregister");
-
- video_device[vfd->minor] = NULL;
device_unregister(&vfd->dev);
- mutex_unlock(&videodev_lock);
}
EXPORT_SYMBOL(video_unregister_device);
/*
- * Video fs operations
- */
-static const struct file_operations video_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .open = video_open,
-};
-
-/*
* Initialise video for linux
*/
-
static int __init videodev_init(void)
{
+ dev_t dev = MKDEV(VIDEO_MAJOR, 0);
int ret;
printk(KERN_INFO "Linux video capture interface: v2.00\n");
- if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
- printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
- return -EIO;
+ ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);
+ if (ret < 0) {
+ printk(KERN_WARNING "videodev: unable to get major %d\n",
+ VIDEO_MAJOR);
+ return ret;
}
ret = class_register(&video_class);
if (ret < 0) {
- unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+ unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
printk(KERN_WARNING "video_dev: class_register failed\n");
return -EIO;
}
@@ -405,8 +406,10 @@ static int __init videodev_init(void)
static void __exit videodev_exit(void)
{
+ dev_t dev = MKDEV(VIDEO_MAJOR, 0);
+
class_unregister(&video_class);
- unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+ unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
}
module_init(videodev_init)
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index fdfe7739c96..155c9d77a46 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -499,7 +499,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
p->timestamp.tv_sec / 3600,
(int)(p->timestamp.tv_sec / 60) % 60,
(int)(p->timestamp.tv_sec % 60),
- p->timestamp.tv_usec,
+ (long)p->timestamp.tv_usec,
p->index,
prt_names(p->type, v4l2_type_names),
p->bytesused, p->flags,
@@ -674,7 +674,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
__video_do_ioctl will be called again, with one or more
V4L2 ioctls.
********************************************************/
- if (_IOC_TYPE(cmd) == 'v')
+ if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE)
return v4l_compat_translate_ioctl(inode, file, cmd, arg,
__video_do_ioctl);
#endif
@@ -746,18 +746,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret = ops->vidioc_enum_fmt_vid_overlay(file,
fh, f);
break;
-#if 1
- /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
- * according to the spec. The bttv and saa7134 drivers support
- * it though, so just warn that this is deprecated and will be
- * removed in the near future. */
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (ops->vidioc_enum_fmt_vbi_cap) {
- printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
- ret = ops->vidioc_enum_fmt_vbi_cap(file, fh, f);
- }
- break;
-#endif
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (ops->vidioc_enum_fmt_vid_out)
ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index b56cffcbfd4..917277d3660 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -126,7 +126,6 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
mutex_lock(&dvb->lock);
dvb->nfeeds--;
if (0 == dvb->nfeeds && NULL != dvb->thread) {
- // FIXME: cx8802_cancel_buffers(dev);
err = kthread_stop(dvb->thread);
dvb->thread = NULL;
}
@@ -134,30 +133,38 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
return err;
}
-/* ------------------------------------------------------------------ */
-
-int videobuf_dvb_register(struct videobuf_dvb *dvb,
+static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
struct module *module,
void *adapter_priv,
struct device *device,
- short *adapter_nr)
+ char *adapter_name,
+ short *adapter_nr,
+ int mfe_shared)
{
int result;
- mutex_init(&dvb->lock);
+ mutex_init(&fe->lock);
/* register adapter */
- result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
- adapter_nr);
+ result = dvb_register_adapter(&fe->adapter, adapter_name, module,
+ device, adapter_nr);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
- dvb->name, result);
- goto fail_adapter;
+ adapter_name, result);
}
- dvb->adapter.priv = adapter_priv;
+ fe->adapter.priv = adapter_priv;
+ fe->adapter.mfe_shared = mfe_shared;
+
+ return result;
+}
+
+static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter,
+ struct videobuf_dvb *dvb)
+{
+ int result;
/* register frontend */
- result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+ result = dvb_register_frontend(adapter, dvb->frontend);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
dvb->name, result);
@@ -183,7 +190,8 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb,
dvb->dmxdev.filternum = 256;
dvb->dmxdev.demux = &dvb->demux.dmx;
dvb->dmxdev.capabilities = 0;
- result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+ result = dvb_dmxdev_init(&dvb->dmxdev, adapter);
+
if (result < 0) {
printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
dvb->name, result);
@@ -214,7 +222,11 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb,
}
/* register network adapter */
- dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+ dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
+ if (dvb->net.dvbdev == NULL) {
+ result = -ENOMEM;
+ goto fail_fe_conn;
+ }
return 0;
fail_fe_conn:
@@ -229,30 +241,151 @@ fail_dmx:
dvb_unregister_frontend(dvb->frontend);
fail_frontend:
dvb_frontend_detach(dvb->frontend);
- dvb_unregister_adapter(&dvb->adapter);
-fail_adapter:
+ dvb->frontend = NULL;
+
return result;
}
-void videobuf_dvb_unregister(struct videobuf_dvb *dvb)
+/* ------------------------------------------------------------------ */
+/* Register a single adapter and one or more frontends */
+int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
+ struct module *module,
+ void *adapter_priv,
+ struct device *device,
+ short *adapter_nr,
+ int mfe_shared)
{
- dvb_net_release(&dvb->net);
- dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
- dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
- dvb_dmxdev_release(&dvb->dmxdev);
- dvb_dmx_release(&dvb->demux);
- dvb_unregister_frontend(dvb->frontend);
- dvb_frontend_detach(dvb->frontend);
- dvb_unregister_adapter(&dvb->adapter);
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe;
+ int res;
+
+ fe = videobuf_dvb_get_frontend(f, 1);
+ if (!fe) {
+ printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
+ return -EINVAL;
+ }
+
+ /* Bring up the adapter */
+ res = videobuf_dvb_register_adapter(f, module, adapter_priv, device,
+ fe->dvb.name, adapter_nr, mfe_shared);
+ if (res < 0) {
+ printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
+ return res;
+ }
+
+ /* Attach all of the frontends to the adapter */
+ mutex_lock(&f->lock);
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb);
+ if (res < 0) {
+ printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
+ fe->dvb.name, res);
+ goto err;
+ }
+ }
+ mutex_unlock(&f->lock);
+ return 0;
+
+err:
+ mutex_unlock(&f->lock);
+ videobuf_dvb_unregister_bus(f);
+ return res;
}
+EXPORT_SYMBOL(videobuf_dvb_register_bus);
-EXPORT_SYMBOL(videobuf_dvb_register);
-EXPORT_SYMBOL(videobuf_dvb_unregister);
+void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
+{
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe;
+
+ mutex_lock(&f->lock);
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ if (fe->dvb.net.dvbdev) {
+ dvb_net_release(&fe->dvb.net);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_mem);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_hw);
+ dvb_dmxdev_release(&fe->dvb.dmxdev);
+ dvb_dmx_release(&fe->dvb.demux);
+ dvb_unregister_frontend(fe->dvb.frontend);
+ }
+ if (fe->dvb.frontend)
+ /* always allocated, may have been reset */
+ dvb_frontend_detach(fe->dvb.frontend);
+ list_del(list);
+ kfree(fe);
+ }
+ mutex_unlock(&f->lock);
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
+ dvb_unregister_adapter(&f->adapter);
+}
+EXPORT_SYMBOL(videobuf_dvb_unregister_bus);
+
+struct videobuf_dvb_frontend *videobuf_dvb_get_frontend(
+ struct videobuf_dvb_frontends *f, int id)
+{
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe, *ret = NULL;
+
+ mutex_lock(&f->lock);
+
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ if (fe->id == id) {
+ ret = fe;
+ break;
+ }
+ }
+
+ mutex_unlock(&f->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(videobuf_dvb_get_frontend);
+
+int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f,
+ struct dvb_frontend *p)
+{
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe = NULL;
+ int ret = 0;
+
+ mutex_lock(&f->lock);
+
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ if (fe->dvb.frontend == p) {
+ ret = fe->id;
+ break;
+ }
+ }
+
+ mutex_unlock(&f->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(videobuf_dvb_find_frontend);
+
+struct videobuf_dvb_frontend *videobuf_dvb_alloc_frontend(
+ struct videobuf_dvb_frontends *f, int id)
+{
+ struct videobuf_dvb_frontend *fe;
+
+ fe = kzalloc(sizeof(struct videobuf_dvb_frontend), GFP_KERNEL);
+ if (fe == NULL)
+ goto fail_alloc;
+
+ fe->id = id;
+ mutex_init(&fe->dvb.lock);
+
+ mutex_lock(&f->lock);
+ list_add_tail(&fe->felist, &f->felist);
+ mutex_unlock(&f->lock);
+
+fail_alloc:
+ return fe;
+}
+EXPORT_SYMBOL(videobuf_dvb_alloc_frontend);
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 1edda456fc6..1efc5f3462c 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -30,16 +30,12 @@
#include <linux/mm.h>
#include <linux/time.h>
#include <linux/version.h>
-
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#include <linux/i2c.h>
#include <linux/i2c-algo-sgi.h>
#include <linux/videodev2.h>
-#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/video_decoder.h>
@@ -810,7 +806,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
dprintk("vino_free_buffer_with_count(): count = %d\n", count);
for (i = 0; i < count; i++) {
- ClearPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+ ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
dma_unmap_single(NULL,
fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
PAGE_SIZE, DMA_FROM_DEVICE);
@@ -888,7 +884,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb,
dma_data_addr + VINO_PAGE_SIZE * j;
}
- SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+ SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
}
/* page_count needs to be set anyway, because the descriptor table has
@@ -975,7 +971,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
dma_data_addr + VINO_PAGE_SIZE * j;
}
- SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+ SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
}
/* page_count needs to be set anyway, because the descriptor table has
@@ -4025,8 +4021,7 @@ out:
static int vino_open(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
int ret = 0;
dprintk("open(): channel = %c\n",
(vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
@@ -4057,8 +4052,7 @@ static int vino_open(struct inode *inode, struct file *file)
static int vino_close(struct inode *inode, struct file *file)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
dprintk("close():\n");
mutex_lock(&vcs->mutex);
@@ -4101,8 +4095,7 @@ static struct vm_operations_struct vino_vm_ops = {
static int vino_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start;
@@ -4207,8 +4200,7 @@ out:
static unsigned int vino_poll(struct file *file, poll_table *pt)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
unsigned int outgoing;
unsigned int ret = 0;
@@ -4248,8 +4240,7 @@ error:
static int vino_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
#ifdef VINO_DEBUG
switch (_IOC_TYPE(cmd)) {
@@ -4356,8 +4347,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file,
static int vino_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct video_device *dev = video_devdata(file);
- struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ struct vino_channel_settings *vcs = video_drvdata(file);
int ret;
if (mutex_lock_interruptible(&vcs->mutex))
@@ -4641,7 +4631,7 @@ static int __init vino_module_init(void)
}
vino_init_stage++;
-#if defined(CONFIG_KMOD) && defined(MODULE)
+#ifdef MODULE
request_module("saa7191");
request_module("indycam");
#endif
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 3518af071a2..7d7e51def46 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -128,12 +128,56 @@ struct vivi_fmt {
int depth;
};
-static struct vivi_fmt format = {
- .name = "4:2:2, packed, YUYV",
- .fourcc = V4L2_PIX_FMT_YUYV,
- .depth = 16,
+static struct vivi_fmt formats[] = {
+ {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ },
+ {
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ },
+ {
+ .name = "RGB565 (LE)",
+ .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+ .depth = 16,
+ },
+ {
+ .name = "RGB565 (BE)",
+ .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+ .depth = 16,
+ },
+ {
+ .name = "RGB555 (LE)",
+ .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+ .depth = 16,
+ },
+ {
+ .name = "RGB555 (BE)",
+ .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+ .depth = 16,
+ },
};
+static struct vivi_fmt *get_format(struct v4l2_format *f)
+{
+ struct vivi_fmt *fmt;
+ unsigned int k;
+
+ for (k = 0; k < ARRAY_SIZE(formats); k++) {
+ fmt = &formats[k];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+
+ if (k == ARRAY_SIZE(formats))
+ return NULL;
+
+ return &formats[k];
+}
+
struct sg_to_addr {
int pos;
struct scatterlist *sg;
@@ -190,6 +234,7 @@ struct vivi_fh {
struct videobuf_queue vb_vidq;
enum v4l2_buf_type type;
+ unsigned char bars[8][3];
};
/* ------------------------------------------------------------------
@@ -234,42 +279,118 @@ static u8 bars[8][3] = {
#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
#define TSTAMP_MIN_X 64
-static void gen_line(char *basep, int inipos, int wmax,
- int hmax, int line, int count, char *timestr)
+static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
{
- int w, i, j, y;
- int pos = inipos;
- char *p, *s;
- u8 chr, r, g, b, color;
-
- /* We will just duplicate the second pixel at the packet */
- wmax /= 2;
+ unsigned char r_y, g_u, b_v;
+ unsigned char *p;
+ int color;
- /* Generate a standard color bar pattern */
- for (w = 0; w < wmax; w++) {
- int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
- r = bars[colorpos][0];
- g = bars[colorpos][1];
- b = bars[colorpos][2];
+ r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
+ g_u = fh->bars[colorpos][1]; /* G or precalculated U */
+ b_v = fh->bars[colorpos][2]; /* B or precalculated V */
- for (color = 0; color < 4; color++) {
- p = basep + pos;
+ for (color = 0; color < 4; color++) {
+ p = buf + color;
+ switch (fh->fmt->fourcc) {
+ case V4L2_PIX_FMT_YUYV:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = r_y;
+ break;
+ case 1:
+ *p = g_u;
+ break;
+ case 3:
+ *p = b_v;
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ switch (color) {
+ case 1:
+ case 3:
+ *p = r_y;
+ break;
+ case 0:
+ *p = g_u;
+ break;
+ case 2:
+ *p = b_v;
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (g_u << 5) | b_v;
+ break;
+ case 1:
+ case 3:
+ *p = (r_y << 3) | (g_u >> 3);
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (r_y << 3) | (g_u >> 3);
+ break;
+ case 1:
+ case 3:
+ *p = (g_u << 5) | b_v;
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB555:
switch (color) {
case 0:
case 2:
- *p = TO_Y(r, g, b); /* Luma */
+ *p = (g_u << 5) | b_v;
break;
case 1:
- *p = TO_U(r, g, b); /* Cb */
+ case 3:
+ *p = (r_y << 2) | (g_u >> 3);
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB555X:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (r_y << 2) | (g_u >> 3);
break;
+ case 1:
case 3:
- *p = TO_V(r, g, b); /* Cr */
+ *p = (g_u << 5) | b_v;
break;
}
- pos++;
+ break;
}
}
+}
+
+static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
+ int hmax, int line, int count, char *timestr)
+{
+ int w, i, j;
+ int pos = inipos;
+ char *s;
+ u8 chr;
+
+ /* We will just duplicate the second pixel at the packet */
+ wmax /= 2;
+
+ /* Generate a standard color bar pattern */
+ for (w = 0; w < wmax; w++) {
+ int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
+
+ gen_twopix(fh, basep + pos, colorpos);
+ pos += 4; /* only 16 bpp supported for now */
+ }
/* Checks if it is possible to show timestamp */
if (TSTAMP_MAX_Y >= hmax)
@@ -283,38 +404,12 @@ static void gen_line(char *basep, int inipos, int wmax,
for (s = timestr; *s; s++) {
chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
for (i = 0; i < 7; i++) {
- if (chr & 1 << (7 - i)) {
- /* Font color*/
- r = 0;
- g = 198;
- b = 0;
- } else {
- /* Background color */
- r = bars[BLACK][0];
- g = bars[BLACK][1];
- b = bars[BLACK][2];
- }
-
pos = inipos + j * 2;
- for (color = 0; color < 4; color++) {
- p = basep + pos;
-
- y = TO_Y(r, g, b);
-
- switch (color) {
- case 0:
- case 2:
- *p = TO_Y(r, g, b); /* Luma */
- break;
- case 1:
- *p = TO_U(r, g, b); /* Cb */
- break;
- case 3:
- *p = TO_V(r, g, b); /* Cr */
- break;
- }
- pos++;
- }
+ /* Draw white font on black background */
+ if (chr & 1 << (7 - i))
+ gen_twopix(fh, basep + pos, WHITE);
+ else
+ gen_twopix(fh, basep + pos, BLACK);
j++;
}
}
@@ -324,8 +419,9 @@ end:
return;
}
-static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
{
+ struct vivi_dev *dev = fh->dev;
int h , pos = 0;
int hmax = buf->vb.height;
int wmax = buf->vb.width;
@@ -341,7 +437,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
return;
for (h = 0; h < hmax; h++) {
- gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
+ gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
dev->timestr);
memcpy(vbuf + pos, tmpbuf, wmax * 2);
pos += wmax*2;
@@ -410,7 +506,7 @@ static void vivi_thread_tick(struct vivi_fh *fh)
do_gettimeofday(&buf->vb.ts);
/* Fill buffer */
- vivi_fillbuff(dev, buf);
+ vivi_fillbuff(fh, buf);
dprintk(dev, 1, "filled buffer %p\n", buf);
wake_up(&buf->vb.done);
@@ -636,11 +732,15 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- if (f->index > 0)
+ struct vivi_fmt *fmt;
+
+ if (f->index >= ARRAY_SIZE(formats))
return -EINVAL;
- strlcpy(f->description, format.name, sizeof(f->description));
- f->pixelformat = format.fourcc;
+ fmt = &formats[f->index];
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
return 0;
}
@@ -670,13 +770,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
enum v4l2_field field;
unsigned int maxw, maxh;
- if (format.fourcc != f->fmt.pix.pixelformat) {
- dprintk(dev, 1, "Fourcc format (0x%08x) invalid. "
- "Driver accepts only 0x%08x\n",
- f->fmt.pix.pixelformat, format.fourcc);
+ fmt = get_format(f);
+ if (!fmt) {
+ dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
return -EINVAL;
}
- fmt = &format;
field = f->fmt.pix.field;
@@ -714,6 +813,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
{
struct vivi_fh *fh = priv;
struct videobuf_queue *q = &fh->vb_vidq;
+ unsigned char r, g, b;
+ int k, is_yuv;
int ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
@@ -727,12 +828,49 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
goto out;
}
- fh->fmt = &format;
+ fh->fmt = get_format(f);
fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height;
fh->vb_vidq.field = f->fmt.pix.field;
fh->type = f->type;
+ /* precalculate color bar values to speed up rendering */
+ for (k = 0; k < 8; k++) {
+ r = bars[k][0];
+ g = bars[k][1];
+ b = bars[k][2];
+ is_yuv = 0;
+
+ switch (fh->fmt->fourcc) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ is_yuv = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ r >>= 3;
+ g >>= 2;
+ b >>= 3;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ case V4L2_PIX_FMT_RGB555X:
+ r >>= 3;
+ g >>= 3;
+ b >>= 3;
+ break;
+ }
+
+ if (is_yuv) {
+ fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
+ fh->bars[k][1] = TO_U(r, g, b); /* Cb */
+ fh->bars[k][2] = TO_V(r, g, b); /* Cr */
+ } else {
+ fh->bars[k][0] = r;
+ fh->bars[k][1] = g;
+ fh->bars[k][2] = b;
+ }
+ }
+
ret = 0;
out:
mutex_unlock(&q->vb_lock);
@@ -886,8 +1024,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
File operations for the device
------------------------------------------------------------------*/
-#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
-
static int vivi_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
@@ -898,9 +1034,11 @@ static int vivi_open(struct inode *inode, struct file *file)
printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
+ lock_kernel();
list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
if (dev->vfd->minor == minor)
goto found;
+ unlock_kernel();
return -ENODEV;
found:
@@ -925,14 +1063,16 @@ found:
}
unlock:
mutex_unlock(&dev->mutex);
- if (retval)
+ if (retval) {
+ unlock_kernel();
return retval;
+ }
file->private_data = fh;
fh->dev = dev;
fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fh->fmt = &format;
+ fh->fmt = &formats[0];
fh->width = 640;
fh->height = 480;
@@ -955,6 +1095,7 @@ unlock:
sizeof(struct vivi_buffer), fh);
vivi_start_thread(fh);
+ unlock_kernel();
return 0;
}
@@ -1021,13 +1162,13 @@ static int vivi_release(void)
dev = list_entry(list, struct vivi_dev, vivi_devlist);
if (-1 != dev->vfd->minor) {
- video_unregister_device(dev->vfd);
- printk(KERN_INFO "%s: /dev/video%d unregistered.\n",
+ printk(KERN_INFO "%s: unregistering /dev/video%d\n",
VIVI_MODULE_NAME, dev->vfd->minor);
+ video_unregister_device(dev->vfd);
} else {
- video_device_release(dev->vfd);
- printk(KERN_INFO "%s: /dev/video%d released.\n",
+ printk(KERN_INFO "%s: releasing /dev/video%d\n",
VIVI_MODULE_NAME, dev->vfd->minor);
+ video_device_release(dev->vfd);
}
kfree(dev);
@@ -1104,19 +1245,29 @@ static struct video_device vivi_template = {
Initialization and module stuff
------------------------------------------------------------------*/
+/* This routine allocates from 1 to n_devs virtual drivers.
+
+ The real maximum number of virtual drivers will depend on how many drivers
+ will succeed. This is limited to the maximum number of devices that
+ videodev supports. Since there are 64 minors for video grabbers, this is
+ currently the theoretical maximum limit. However, a further limit does
+ exist at videodev that forbids any driver to register more than 32 video
+ grabbers.
+ */
static int __init vivi_init(void)
{
int ret = -ENOMEM, i;
struct vivi_dev *dev;
struct video_device *vfd;
+ if (n_devs <= 0)
+ n_devs = 1;
+
for (i = 0; i < n_devs; i++) {
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (NULL == dev)
+ if (!dev)
break;
- list_add_tail(&dev->vivi_devlist, &vivi_devlist);
-
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
init_waitqueue_head(&dev->vidq.wq);
@@ -1126,14 +1277,27 @@ static int __init vivi_init(void)
mutex_init(&dev->mutex);
vfd = video_device_alloc();
- if (NULL == vfd)
+ if (!vfd) {
+ kfree(dev);
break;
+ }
*vfd = vivi_template;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
- if (ret < 0)
+ if (ret < 0) {
+ video_device_release(vfd);
+ kfree(dev);
+
+ /* If some registers succeeded, keep driver */
+ if (i)
+ ret = 0;
+
break;
+ }
+
+ /* Now that everything is fine, let's add it to device list */
+ list_add_tail(&dev->vivi_devlist, &vivi_devlist);
snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
vivi_template.name, vfd->minor);
@@ -1149,11 +1313,16 @@ static int __init vivi_init(void)
if (ret < 0) {
vivi_release();
printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
- } else
+ } else {
printk(KERN_INFO "Video Technology Magazine Virtual Video "
"Capture Board ver %u.%u.%u successfully loaded.\n",
(VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
VIVI_VERSION & 0xFF);
+
+ /* n_devs will reflect the actual number of allocated devices */
+ n_devs = i;
+ }
+
return ret;
}
@@ -1169,10 +1338,10 @@ MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
MODULE_LICENSE("Dual BSD/GPL");
-module_param(video_nr, int, 0);
+module_param(video_nr, uint, 0444);
MODULE_PARM_DESC(video_nr, "video iminor start number");
-module_param(n_devs, int, 0);
+module_param(n_devs, uint, 0444);
MODULE_PARM_DESC(n_devs, "number of video devices to create");
module_param_named(debug, vivi_template.debug, int, 0444);
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 35293029da0..67aa0db4b81 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -22,34 +22,21 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <linux/byteorder/swab.h>
-
-#include <asm/io.h>
#include <asm/uaccess.h>
-
#include <linux/i2c.h>
-
-#define I2C_NAME(x) (x)->name
-
-#include <linux/videodev.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev.h>
#include <linux/video_decoder.h>
-#define I2C_VPX3220 0x86
-#define VPX3220_DEBUG KERN_DEBUG "vpx3220: "
+MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
+MODULE_AUTHOR("Laurent Pinchart");
+MODULE_LICENSE("GPL");
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
- do { \
- if (debug >= num) \
- printk(format, ##args); \
- } while (0)
-
#define VPX_TIMEOUT_COUNT 10
/* ----------------------------------------------------------------------- */
@@ -69,10 +56,8 @@ struct vpx3220 {
static char *inputs[] = { "internal", "composite", "svideo" };
/* ----------------------------------------------------------------------- */
-static inline int
-vpx3220_write (struct i2c_client *client,
- u8 reg,
- u8 value)
+
+static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value)
{
struct vpx3220 *decoder = i2c_get_clientdata(client);
@@ -80,15 +65,12 @@ vpx3220_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
-static inline int
-vpx3220_read (struct i2c_client *client,
- u8 reg)
+static inline int vpx3220_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
-static int
-vpx3220_fp_status (struct i2c_client *client)
+static int vpx3220_fp_status(struct i2c_client *client)
{
unsigned char status;
unsigned int i;
@@ -108,14 +90,11 @@ vpx3220_fp_status (struct i2c_client *client)
return -1;
}
-static int
-vpx3220_fp_write (struct i2c_client *client,
- u8 fpaddr,
- u16 data)
+static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data)
{
/* Write the 16-bit address to the FPWR register */
if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
- dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+ v4l_dbg(1, debug, client, "%s: failed\n", __func__);
return -1;
}
@@ -124,22 +103,20 @@ vpx3220_fp_write (struct i2c_client *client,
/* Write the 16-bit data to the FPDAT register */
if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
- dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+ v4l_dbg(1, debug, client, "%s: failed\n", __func__);
return -1;
}
return 0;
}
-static u16
-vpx3220_fp_read (struct i2c_client *client,
- u16 fpaddr)
+static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr)
{
s16 data;
/* Write the 16-bit address to the FPRD register */
if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
- dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+ v4l_dbg(1, debug, client, "%s: failed\n", __func__);
return -1;
}
@@ -149,25 +126,22 @@ vpx3220_fp_read (struct i2c_client *client,
/* Read the 16-bit data from the FPDAT register */
data = i2c_smbus_read_word_data(client, 0x28);
if (data == -1) {
- dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+ v4l_dbg(1, debug, client, "%s: failed\n", __func__);
return -1;
}
return swab16(data);
}
-static int
-vpx3220_write_block (struct i2c_client *client,
- const u8 *data,
- unsigned int len)
+static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
u8 reg;
int ret = -1;
while (len >= 2) {
reg = *data++;
- if ((ret =
- vpx3220_write(client, reg, *data++)) < 0)
+ ret = vpx3220_write(client, reg, *data++);
+ if (ret < 0)
break;
len -= 2;
}
@@ -175,10 +149,8 @@ vpx3220_write_block (struct i2c_client *client,
return ret;
}
-static int
-vpx3220_write_fp_block (struct i2c_client *client,
- const u16 *data,
- unsigned int len)
+static int vpx3220_write_fp_block(struct i2c_client *client,
+ const u16 *data, unsigned int len)
{
u8 reg;
int ret = 0;
@@ -287,25 +259,20 @@ static const unsigned short init_fp[] = {
0x4b, 0x298, /* PLL gain */
};
-static void
-vpx3220_dump_i2c (struct i2c_client *client)
+static void vpx3220_dump_i2c(struct i2c_client *client)
{
int len = sizeof(init_common);
const unsigned char *data = init_common;
while (len > 1) {
- dprintk(1,
- KERN_DEBUG "vpx3216b i2c reg 0x%02x data 0x%02x\n",
+ v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
*data, vpx3220_read(client, *data));
data += 2;
len -= 2;
}
}
-static int
-vpx3220_command (struct i2c_client *client,
- unsigned int cmd,
- void *arg)
+static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct vpx3220 *decoder = i2c_get_clientdata(client);
@@ -317,7 +284,6 @@ vpx3220_command (struct i2c_client *client,
vpx3220_write_fp_block(client, init_fp,
sizeof(init_fp) >> 1);
switch (decoder->norm) {
-
case VIDEO_MODE_NTSC:
vpx3220_write_fp_block(client, init_ntsc,
sizeof(init_ntsc) >> 1);
@@ -336,21 +302,20 @@ vpx3220_command (struct i2c_client *client,
sizeof(init_pal) >> 1);
break;
}
- }
break;
+ }
case DECODER_DUMP:
{
vpx3220_dump_i2c(client);
- }
break;
+ }
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
- dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
@@ -359,20 +324,18 @@ vpx3220_command (struct i2c_client *client,
VIDEO_DECODER_CCIR;
cap->inputs = 3;
cap->outputs = 1;
- }
break;
+ }
case DECODER_GET_STATUS:
{
int res = 0, status;
- dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n");
status = vpx3220_fp_read(client, 0x0f3);
- dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client),
- status);
+ v4l_dbg(1, debug, client, "status: 0x%04x\n", status);
if (status < 0)
return status;
@@ -381,7 +344,6 @@ vpx3220_command (struct i2c_client *client,
res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
switch (status & 0x18) {
-
case 0x00:
case 0x10:
case 0x14:
@@ -402,8 +364,8 @@ vpx3220_command (struct i2c_client *client,
}
*(int *) arg = res;
- }
break;
+ }
case DECODER_SET_NORM:
{
@@ -415,50 +377,43 @@ vpx3220_command (struct i2c_client *client,
choosen video norm */
temp_input = vpx3220_fp_read(client, 0xf2);
- dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
- I2C_NAME(client), *iarg);
+ v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg);
switch (*iarg) {
-
case VIDEO_MODE_NTSC:
vpx3220_write_fp_block(client, init_ntsc,
sizeof(init_ntsc) >> 1);
- dprintk(1, KERN_INFO "%s: norm switched to NTSC\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "norm switched to NTSC\n");
break;
case VIDEO_MODE_PAL:
vpx3220_write_fp_block(client, init_pal,
sizeof(init_pal) >> 1);
- dprintk(1, KERN_INFO "%s: norm switched to PAL\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "norm switched to PAL\n");
break;
case VIDEO_MODE_SECAM:
vpx3220_write_fp_block(client, init_secam,
sizeof(init_secam) >> 1);
- dprintk(1, KERN_INFO "%s: norm switched to SECAM\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "norm switched to SECAM\n");
break;
case VIDEO_MODE_AUTO:
/* FIXME This is only preliminary support */
data = vpx3220_fp_read(client, 0xf2) & 0x20;
vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
- dprintk(1, KERN_INFO "%s: norm switched to Auto\n",
- I2C_NAME(client));
+ v4l_dbg(1, debug, client, "norm switched to AUTO\n");
break;
default:
return -EINVAL;
-
}
decoder->norm = *iarg;
/* And here we set the backed up video input again */
vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
udelay(10);
- }
break;
+ }
case DECODER_SET_INPUT:
{
@@ -477,8 +432,7 @@ vpx3220_command (struct i2c_client *client,
if (*iarg < 0 || *iarg > 2)
return -EINVAL;
- dprintk(1, KERN_INFO "%s: input switched to %s\n",
- I2C_NAME(client), inputs[*iarg]);
+ v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]);
vpx3220_write(client, 0x33, input[*iarg][0]);
@@ -490,8 +444,8 @@ vpx3220_command (struct i2c_client *client,
data | (input[*iarg][1] << 5) | 0x0010);
udelay(10);
- }
break;
+ }
case DECODER_SET_OUTPUT:
{
@@ -501,19 +455,18 @@ vpx3220_command (struct i2c_client *client,
if (*iarg != 0) {
return -EINVAL;
}
- }
break;
+ }
case DECODER_ENABLE_OUTPUT:
{
int *iarg = arg;
- dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n",
- I2C_NAME(client), *iarg);
+ v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg);
vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
- }
break;
+ }
case DECODER_SET_PICTURE:
{
@@ -544,8 +497,8 @@ vpx3220_command (struct i2c_client *client,
vpx3220_fp_write(client, 0x1c,
((decoder->hue - 32768) >> 6) & 0xFFF);
}
- }
break;
+ }
default:
return -EINVAL;
@@ -554,8 +507,7 @@ vpx3220_command (struct i2c_client *client,
return 0;
}
-static int
-vpx3220_init_client (struct i2c_client *client)
+static int vpx3220_init_client(struct i2c_client *client)
{
vpx3220_write_block(client, init_common, sizeof(init_common));
vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1);
@@ -569,115 +521,26 @@ vpx3220_init_client (struct i2c_client *client)
* Client management code
*/
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
- { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
- I2C_CLIENT_END
-};
-
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-static struct i2c_driver vpx3220_i2c_driver;
-
-static int
-vpx3220_detach_client (struct i2c_client *client)
-{
- struct vpx3220 *decoder = i2c_get_clientdata(client);
- int err;
-
- err = i2c_detach_client(client);
- if (err) {
- return err;
- }
-
- kfree(decoder);
- kfree(client);
+static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END };
- return 0;
-}
+I2C_CLIENT_INSMOD;
-static int
-vpx3220_detect_client (struct i2c_adapter *adapter,
- int address,
- int kind)
+static int vpx3220_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- int err;
- struct i2c_client *client;
struct vpx3220 *decoder;
-
- dprintk(1, VPX3220_DEBUG "%s\n", __func__);
+ const char *name = NULL;
+ u8 ver;
+ u16 pn;
/* Check if the adapter supports the needed features */
- if (!i2c_check_functionality
- (adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
- return 0;
-
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL) {
- return -ENOMEM;
- }
-
- client->addr = address;
- client->adapter = adapter;
- client->driver = &vpx3220_i2c_driver;
-
- /* Check for manufacture ID and part number */
- if (kind < 0) {
- u8 id;
- u16 pn;
-
- id = vpx3220_read(client, 0x00);
- if (id != 0xec) {
- dprintk(1,
- KERN_INFO
- "vpx3220_attach: Wrong manufacturer ID (0x%02x)\n",
- id);
- kfree(client);
- return 0;
- }
-
- pn = (vpx3220_read(client, 0x02) << 8) +
- vpx3220_read(client, 0x01);
- switch (pn) {
- case 0x4680:
- strlcpy(I2C_NAME(client), "vpx3220a",
- sizeof(I2C_NAME(client)));
- break;
- case 0x4260:
- strlcpy(I2C_NAME(client), "vpx3216b",
- sizeof(I2C_NAME(client)));
- break;
- case 0x4280:
- strlcpy(I2C_NAME(client), "vpx3214c",
- sizeof(I2C_NAME(client)));
- break;
- default:
- dprintk(1,
- KERN_INFO
- "%s: Wrong part number (0x%04x)\n",
- __func__, pn);
- kfree(client);
- return 0;
- }
- } else {
- strlcpy(I2C_NAME(client), "forced vpx32xx",
- sizeof(I2C_NAME(client)));
- }
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
- if (decoder == NULL) {
- kfree(client);
+ if (decoder == NULL)
return -ENOMEM;
- }
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
@@ -687,63 +550,52 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
decoder->sat = 32768;
i2c_set_clientdata(client, decoder);
- err = i2c_attach_client(client);
- if (err) {
- kfree(client);
- kfree(decoder);
- return err;
+ ver = i2c_smbus_read_byte_data(client, 0x00);
+ pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
+ i2c_smbus_read_byte_data(client, 0x01);
+ if (ver == 0xec) {
+ switch (pn) {
+ case 0x4680:
+ name = "vpx3220a";
+ break;
+ case 0x4260:
+ name = "vpx3216b";
+ break;
+ case 0x4280:
+ name = "vpx3214c";
+ break;
+ }
}
-
- dprintk(1, KERN_INFO "%s: vpx32xx client found at address 0x%02x\n",
- I2C_NAME(client), client->addr << 1);
+ if (name)
+ v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+ client->addr << 1, client->adapter->name);
+ else
+ v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n",
+ ver, pn, client->addr << 1, client->adapter->name);
vpx3220_init_client(client);
-
return 0;
}
-static int
-vpx3220_attach_adapter (struct i2c_adapter *adapter)
+static int vpx3220_remove(struct i2c_client *client)
{
- int ret;
-
- ret = i2c_probe(adapter, &addr_data, &vpx3220_detect_client);
- dprintk(1, VPX3220_DEBUG "%s: i2c_probe returned %d\n",
- __func__, ret);
- return ret;
+ kfree(i2c_get_clientdata(client));
+ return 0;
}
-/* -----------------------------------------------------------------------
- * Driver initialization and cleanup code
- */
-
-static struct i2c_driver vpx3220_i2c_driver = {
- .driver = {
- .name = "vpx3220",
- },
-
- .id = I2C_DRIVERID_VPX3220,
+static const struct i2c_device_id vpx3220_id[] = {
+ { "vpx3220a", 0 },
+ { "vpx3216b", 0 },
+ { "vpx3214c", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, vpx3220_id);
- .attach_adapter = vpx3220_attach_adapter,
- .detach_client = vpx3220_detach_client,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "vpx3220",
+ .driverid = I2C_DRIVERID_VPX3220,
.command = vpx3220_command,
+ .probe = vpx3220_probe,
+ .remove = vpx3220_remove,
+ .id_table = vpx3220_id,
};
-
-static int __init
-vpx3220_init (void)
-{
- return i2c_add_driver(&vpx3220_i2c_driver);
-}
-
-static void __exit
-vpx3220_cleanup (void)
-{
- i2c_del_driver(&vpx3220_i2c_driver);
-}
-
-module_init(vpx3220_init);
-module_exit(vpx3220_cleanup);
-
-MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
-MODULE_AUTHOR("Laurent Pinchart");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 9402f40095b..b2dbe48a92b 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -113,6 +113,7 @@ struct w9966_dev {
signed char contrast;
signed char color;
signed char hue;
+ unsigned long in_use;
};
/*
@@ -184,10 +185,25 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
+static int w9966_exclusive_open(struct inode *inode, struct file *file)
+{
+ struct w9966_dev *cam = video_drvdata(file);
+
+ return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
+}
+
+static int w9966_exclusive_release(struct inode *inode, struct file *file)
+{
+ struct w9966_dev *cam = video_drvdata(file);
+
+ clear_bit(0, &cam->in_use);
+ return 0;
+}
+
static const struct file_operations w9966_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = w9966_exclusive_open,
+ .release = w9966_exclusive_release,
.ioctl = w9966_v4l_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -198,6 +214,7 @@ static const struct file_operations w9966_fops = {
static struct video_device w9966_template = {
.name = W9966_DRIVERNAME,
.fops = &w9966_fops,
+ .release = video_device_release_empty,
};
/*
@@ -332,9 +349,9 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
// Fill in the video_device struct and register us to v4l
memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
- cam->vdev.priv = cam;
+ video_set_drvdata(&cam->vdev, cam);
- if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
return -1;
w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
@@ -713,8 +730,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
- struct video_device *vdev = video_devdata(file);
- struct w9966_dev *cam = vdev->priv;
+ struct w9966_dev *cam = video_drvdata(file);
switch(cmd)
{
@@ -872,8 +888,7 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *vdev = video_devdata(file);
- struct w9966_dev *cam = vdev->priv;
+ struct w9966_dev *cam = video_drvdata(file);
unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000
unsigned char __user *dest = (unsigned char __user *)buf;
unsigned long dleft = count;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 168baabe465..dcd45dbd82d 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -111,7 +111,7 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG;
static unsigned int param_nv[24]; /* number of values per parameter */
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
module_param(ovmod_load, bool, 0644);
#endif
module_param(simcams, ushort, 0644);
@@ -144,7 +144,7 @@ module_param(debug, ushort, 0644);
module_param(specific_debug, bool, 0644);
#endif
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
MODULE_PARM_DESC(ovmod_load,
"\n<0|1> Automatic 'ovcamchip' module loading."
"\n0 disabled, 1 enabled."
@@ -911,7 +911,6 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
for (i = 0; i < W9968CF_URBS; i++) {
urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
- cam->urb[i] = urb;
if (!urb) {
for (j = 0; j < i; j++)
usb_free_urb(cam->urb[j]);
@@ -919,6 +918,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
return -ENOMEM;
}
+ cam->urb[i] = urb;
urb->dev = udev;
urb->context = (void*)cam;
urb->pipe = usb_rcvisocpipe(udev, 1);
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index 95c79ad8048..54ac3fe26ec 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -274,10 +274,8 @@ static int wm8739_probe(struct i2c_client *client,
client->addr << 1, client->adapter->name);
state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
- if (state == NULL) {
- kfree(client);
+ if (state == NULL)
return -ENOMEM;
- }
state->vol_l = 0x17; /* 0dB */
state->vol_r = 0x17; /* 0dB */
state->muted = 0;
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 550ce7bd5c8..6a0902bcba6 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -657,7 +657,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
if (!down_read_trylock(&zc0301_dev_lock))
return -EAGAIN;
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
if (wait_for_completion_interruptible(&cam->probe)) {
up_read(&zc0301_dev_lock);
@@ -739,7 +739,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
down_write(&zc0301_dev_lock);
- cam = video_get_drvdata(video_devdata(filp));
+ cam = video_drvdata(filp);
zc0301_stop_transfer(cam);
zc0301_release_buffers(cam);
@@ -759,7 +759,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
static ssize_t
zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device *cam = video_drvdata(filp);
struct zc0301_frame_t* f, * i;
unsigned long lock_flags;
long timeout;
@@ -866,7 +866,7 @@ exit:
static unsigned int zc0301_poll(struct file *filp, poll_table *wait)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device *cam = video_drvdata(filp);
struct zc0301_frame_t* f;
unsigned long lock_flags;
unsigned int mask = 0;
@@ -941,7 +941,7 @@ static struct vm_operations_struct zc0301_vm_ops = {
static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device *cam = video_drvdata(filp);
unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start;
void *pos;
@@ -1796,7 +1796,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg)
static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
unsigned int cmd, void __user * arg)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device *cam = video_drvdata(filp);
switch (cmd) {
@@ -1891,7 +1891,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
static int zc0301_ioctl(struct inode* inode, struct file* filp,
unsigned int cmd, unsigned long arg)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device *cam = video_drvdata(filp);
int err = 0;
if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -1988,6 +1988,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->fops = &zc0301_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
+ cam->v4ldev->parent = &udev->dev;
video_set_drvdata(cam->v4ldev, cam);
init_completion(&cam->probe);
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index 70fe6fc6cdd..b0cd49c438a 100644
--- a/drivers/media/video/zc0301/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -60,27 +60,8 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
#define ZC0301_ID_TABLE \
static const struct usb_device_id zc0301_id_table[] = { \
- { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), }, \
- { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \
- { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \
- { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \
{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \
- { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \
- { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */ \
{ ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \
- { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */ \
- { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */ \
{ } \
};
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig
new file mode 100644
index 00000000000..4ea5fa71de8
--- /dev/null
+++ b/drivers/media/video/zoran/Kconfig
@@ -0,0 +1,73 @@
+config VIDEO_ZORAN
+ tristate "Zoran ZR36057/36067 Video For Linux"
+ depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
+ help
+ Say Y for support for MJPEG capture cards based on the Zoran
+ 36057/36067 PCI controller chipset. This includes the Iomega
+ Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
+ a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
+ more information, check <file:Documentation/video4linux/Zoran>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called zr36067.
+
+config VIDEO_ZORAN_DC30
+ tristate "Pinnacle/Miro DC30(+) support"
+ depends on VIDEO_ZORAN
+ select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+ card. This also supports really old DC10 cards based on the
+ zr36050 MJPEG codec and zr36016 VFE.
+
+config VIDEO_ZORAN_ZR36060
+ tristate "Zoran ZR36060"
+ depends on VIDEO_ZORAN
+ help
+ Say Y to support Zoran boards based on 36060 chips.
+ This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
+ and 33 R10 and AverMedia 6 boards.
+
+config VIDEO_ZORAN_BUZ
+ tristate "Iomega Buz support"
+ depends on VIDEO_ZORAN_ZR36060
+ select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the Iomega Buz MJPEG capture/playback card.
+
+config VIDEO_ZORAN_DC10
+ tristate "Pinnacle/Miro DC10(+) support"
+ depends on VIDEO_ZORAN_ZR36060
+ select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_LML33
+ tristate "Linux Media Labs LML33 support"
+ depends on VIDEO_ZORAN_ZR36060
+ select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the Linux Media Labs LML33 MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_LML33R10
+ tristate "Linux Media Labs LML33R10 support"
+ depends on VIDEO_ZORAN_ZR36060
+ select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ support for the Linux Media Labs LML33R10 MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_AVS6EYES
+ tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
+ depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
+ select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile
new file mode 100644
index 00000000000..44cc13352c8
--- /dev/null
+++ b/drivers/media/video/zoran/Makefile
@@ -0,0 +1,6 @@
+zr36067-objs := zoran_procfs.o zoran_device.o \
+ zoran_driver.o zoran_card.o
+
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
+obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/zoran/videocodec.c
index cf24956f320..cf24956f320 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/zoran/videocodec.c
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/zoran/videocodec.h
index 97a3bbeda50..97a3bbeda50 100644
--- a/drivers/media/video/videocodec.h
+++ b/drivers/media/video/zoran/videocodec.h
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran/zoran.h
index 46b7ad477ce..46b7ad477ce 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index d842a7cb99d..fa5f2f8f518 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -817,6 +817,7 @@ zoran_register_i2c (struct zoran *zr)
memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
sizeof(struct i2c_algo_bit_data));
zr->i2c_algo.data = zr;
+ zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG;
zr->i2c_adapter.id = I2C_HW_B_ZR36067;
zr->i2c_adapter.client_register = zoran_i2c_client_register;
zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
@@ -988,7 +989,7 @@ zoran_open_init_params (struct zoran *zr)
zr->v4l_grab_seq = 0;
zr->v4l_settings.width = 192;
zr->v4l_settings.height = 144;
- zr->v4l_settings.format = &zoran_formats[4]; /* YUY2 - YUV-4:2:2 packed */
+ zr->v4l_settings.format = &zoran_formats[7]; /* YUY2 - YUV-4:2:2 packed */
zr->v4l_settings.bytesperline =
zr->v4l_settings.width *
((zr->v4l_settings.format->depth + 7) / 8);
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran/zoran_card.h
index e4dc9d29b40..e4dc9d29b40 100644
--- a/drivers/media/video/zoran_card.h
+++ b/drivers/media/video/zoran/zoran_card.h
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
index 88d369708e4..5d948ff7faf 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran/zoran_device.c
@@ -58,8 +58,6 @@
ZR36057_ISR_GIRQ1 | \
ZR36057_ISR_JPEGRepIRQ )
-extern const struct zoran_format zoran_formats[];
-
static int lml33dpath; /* default = 0
* 1 will use digital path in capture
* mode instead of analog. It can be
@@ -377,7 +375,7 @@ zr36057_set_vfe (struct zoran *zr,
/* horizontal */
VidWinWid = video_width;
- X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa;
+ X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa);
We = (VidWinWid * 64) / X;
HorDcm = 64 - X;
hcrop1 = 2 * ((tvn->Wa - We) / 4);
@@ -403,7 +401,7 @@ zr36057_set_vfe (struct zoran *zr,
/* Vertical */
DispMode = !(video_height > BUZ_MAX_HEIGHT / 2);
VidWinHt = DispMode ? video_height : video_height / 2;
- Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha;
+ Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha);
He = (VidWinHt * 64) / Y;
VerDcm = 64 - Y;
vcrop1 = (tvn->Ha / 2 - He) / 2;
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran/zoran_device.h
index 37fa86a3408..74c6c8edb7d 100644
--- a/drivers/media/video/zoran_device.h
+++ b/drivers/media/video/zoran/zoran_device.h
@@ -78,6 +78,14 @@ extern void zoran_set_pci_master(struct zoran *zr,
extern void zoran_init_hardware(struct zoran *zr);
extern void zr36057_restart(struct zoran *zr);
+extern const struct zoran_format zoran_formats[];
+
+extern int v4l_nbufs;
+extern int v4l_bufsize;
+extern int jpg_nbufs;
+extern int jpg_bufsize;
+extern int pass_through;
+
/* i2c */
extern int decoder_command(struct zoran *zr,
int cmd,
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index ec6f59674b1..db11ab9e60d 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -134,7 +134,7 @@ const struct zoran_format zoran_formats[] = {
}, {
.name = "16-bit RGB BE",
ZFMT(-1,
- V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+ V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
.depth = 16,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
@@ -194,12 +194,6 @@ const struct zoran_format zoran_formats[] = {
// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
-extern int v4l_nbufs;
-extern int v4l_bufsize;
-extern int jpg_nbufs;
-extern int jpg_bufsize;
-extern int pass_through;
-
static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */
module_param(lock_norm, int, 0644);
MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
@@ -1211,6 +1205,7 @@ zoran_open (struct inode *inode,
struct zoran_fh *fh;
int i, res, first_open = 0, have_module_locks = 0;
+ lock_kernel();
/* find the device */
for (i = 0; i < zoran_num; i++) {
if (zoran[i]->video_dev->minor == minor) {
@@ -1321,6 +1316,7 @@ zoran_open (struct inode *inode,
file->private_data = fh;
fh->zr = zr;
zoran_open_init_session(file);
+ unlock_kernel();
return 0;
@@ -1338,6 +1334,7 @@ open_unlock_and_return:
if (zr) {
/*mutex_unlock(&zr->resource_lock);*/
}
+ unlock_kernel();
return res;
}
@@ -2737,7 +2734,8 @@ zoran_do_ioctl (struct inode *inode,
fh->v4l_settings.format->fourcc;
fmt->fmt.pix.colorspace =
fh->v4l_settings.format->colorspace;
- fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.bytesperline =
+ fh->v4l_settings.bytesperline;
if (BUZ_MAX_HEIGHT <
(fh->v4l_settings.height * 2))
fmt->fmt.pix.field =
@@ -2833,13 +2831,6 @@ zoran_do_ioctl (struct inode *inode,
fmt->fmt.pix.pixelformat,
(char *) &printformat);
- if (fmt->fmt.pix.bytesperline > 0) {
- dprintk(5,
- KERN_ERR "%s: bpl not supported\n",
- ZR_DEVNAME(zr));
- return -EINVAL;
- }
-
/* we can be requested to do JPEG/raw playback/capture */
if (!
(fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
@@ -2923,8 +2914,11 @@ zoran_do_ioctl (struct inode *inode,
fh->jpg_buffers.buffer_size =
zoran_v4l2_calc_bufsize(&fh->
jpg_settings);
+ fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.sizeimage =
fh->jpg_buffers.buffer_size;
+ fmt->fmt.pix.colorspace =
+ V4L2_COLORSPACE_SMPTE170M;
/* we hereby abuse this variable to show that
* we're gonna do mjpeg capture */
@@ -2979,9 +2973,13 @@ zoran_do_ioctl (struct inode *inode,
/* tell the user the
* results/missing stuff */
+ fmt->fmt.pix.bytesperline =
+ fh->v4l_settings.bytesperline;
fmt->fmt.pix.sizeimage =
fh->v4l_settings.height *
fh->v4l_settings.bytesperline;
+ fmt->fmt.pix.colorspace =
+ fh->v4l_settings.format->colorspace;
if (BUZ_MAX_HEIGHT <
(fh->v4l_settings.height * 2))
fmt->fmt.pix.field =
@@ -2998,7 +2996,6 @@ zoran_do_ioctl (struct inode *inode,
break;
default:
- dprintk(3, "unsupported\n");
dprintk(1,
KERN_ERR
"%s: VIDIOC_S_FMT - unsupported type %d\n",
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c
index 870bc5a70e3..870bc5a70e3 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran/zoran_procfs.c
diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h
index f2d5b1ba448..f2d5b1ba448 100644
--- a/drivers/media/video/zoran_procfs.h
+++ b/drivers/media/video/zoran/zoran_procfs.h
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zoran/zr36016.c
index 00d132bcd1e..00d132bcd1e 100644
--- a/drivers/media/video/zr36016.c
+++ b/drivers/media/video/zoran/zr36016.c
diff --git a/drivers/media/video/zr36016.h b/drivers/media/video/zoran/zr36016.h
index 8c79229f69d..8c79229f69d 100644
--- a/drivers/media/video/zr36016.h
+++ b/drivers/media/video/zoran/zr36016.h
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zoran/zr36050.c
index cf8b271a1c8..cf8b271a1c8 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zoran/zr36050.c
diff --git a/drivers/media/video/zr36050.h b/drivers/media/video/zoran/zr36050.h
index 9f52f0cdde5..9f52f0cdde5 100644
--- a/drivers/media/video/zr36050.h
+++ b/drivers/media/video/zoran/zr36050.h
diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zoran/zr36057.h
index 54c9362aa98..54c9362aa98 100644
--- a/drivers/media/video/zr36057.h
+++ b/drivers/media/video/zoran/zr36057.h
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zoran/zr36060.c
index 8e74054d5ef..8e74054d5ef 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zoran/zr36060.c
diff --git a/drivers/media/video/zr36060.h b/drivers/media/video/zoran/zr36060.h
index 914ffa4ad8d..914ffa4ad8d 100644
--- a/drivers/media/video/zr36060.h
+++ b/drivers/media/video/zoran/zr36060.h
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index 18d1c4ba79f..7cdac99deea 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -52,7 +52,7 @@
/* Debug macro */
-#define DBG(x...) if (debug) info(x)
+#define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x)
/* Init methods, need to find nicer names for these
@@ -116,6 +116,7 @@ struct zr364xx_camera {
int height;
int method;
struct mutex lock;
+ int users;
};
@@ -127,7 +128,7 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
if (!transfer_buffer) {
- info("kmalloc(%d) failed", size);
+ dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
return -ENOMEM;
}
@@ -143,7 +144,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
kfree(transfer_buffer);
if (status < 0)
- info("Failed sending control message, error %d.", status);
+ dev_err(&udev->dev,
+ "Failed sending control message, error %d.\n", status);
return status;
}
@@ -303,11 +305,11 @@ static int read_frame(struct zr364xx_camera *cam, int framenum)
DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]);
DBG("bulk : n=%d size=%d", n, actual_length);
if (n < 0) {
- info("error reading bulk msg");
+ dev_err(&cam->udev->dev, "error reading bulk msg\n");
return 0;
}
if (actual_length < 0 || actual_length > BUFFER_SIZE) {
- info("wrong number of bytes");
+ dev_err(&cam->udev->dev, "wrong number of bytes\n");
return 0;
}
@@ -641,42 +643,47 @@ static int zr364xx_open(struct inode *inode, struct file *file)
DBG("zr364xx_open");
- cam->skip = 2;
+ mutex_lock(&cam->lock);
- err = video_exclusive_open(inode, file);
- if (err < 0)
- return err;
+ if (cam->users) {
+ err = -EBUSY;
+ goto out;
+ }
if (!cam->framebuf) {
cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES);
if (!cam->framebuf) {
- info("vmalloc_32 failed!");
- return -ENOMEM;
+ dev_err(&cam->udev->dev, "vmalloc_32 failed!\n");
+ err = -ENOMEM;
+ goto out;
}
}
- mutex_lock(&cam->lock);
for (i = 0; init[cam->method][i].size != -1; i++) {
err =
send_control_msg(udev, 1, init[cam->method][i].value,
0, init[cam->method][i].bytes,
init[cam->method][i].size);
if (err < 0) {
- info("error during open sequence: %d", i);
- mutex_unlock(&cam->lock);
- return err;
+ dev_err(&cam->udev->dev,
+ "error during open sequence: %d\n", i);
+ goto out;
}
}
+ cam->skip = 2;
+ cam->users++;
file->private_data = vdev;
/* Added some delay here, since opening/closing the camera quickly,
* like Ekiga does during its startup, can crash the webcam
*/
mdelay(100);
+ err = 0;
+out:
mutex_unlock(&cam->lock);
- return 0;
+ return err;
}
@@ -697,28 +704,30 @@ static int zr364xx_release(struct inode *inode, struct file *file)
udev = cam->udev;
mutex_lock(&cam->lock);
+
+ cam->users--;
+ file->private_data = NULL;
+
for (i = 0; i < 2; i++) {
err =
send_control_msg(udev, 1, init[cam->method][i].value,
0, init[i][cam->method].bytes,
init[cam->method][i].size);
if (err < 0) {
- info("error during release sequence");
- mutex_unlock(&cam->lock);
- return err;
+ dev_err(&udev->dev, "error during release sequence\n");
+ goto out;
}
}
- file->private_data = NULL;
- video_exclusive_release(inode, file);
-
/* Added some delay here, since opening/closing the camera quickly,
* like Ekiga does during its startup, can crash the webcam
*/
mdelay(100);
+ err = 0;
+out:
mutex_unlock(&cam->lock);
- return 0;
+ return err;
}
@@ -801,13 +810,14 @@ static int zr364xx_probe(struct usb_interface *intf,
DBG("probing...");
- info(DRIVER_DESC " compatible webcam plugged");
- info("model %04x:%04x detected", udev->descriptor.idVendor,
- udev->descriptor.idProduct);
+ dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
+ dev_info(&intf->dev, "model %04x:%04x detected\n",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
if (cam == NULL) {
- info("cam: out of memory !");
+ dev_err(&udev->dev, "cam: out of memory !\n");
return -ENOMEM;
}
/* save the init method used by this camera */
@@ -815,7 +825,7 @@ static int zr364xx_probe(struct usb_interface *intf,
cam->vdev = video_device_alloc();
if (cam->vdev == NULL) {
- info("cam->vdev: out of memory !");
+ dev_err(&udev->dev, "cam->vdev: out of memory !\n");
kfree(cam);
return -ENOMEM;
}
@@ -827,7 +837,7 @@ static int zr364xx_probe(struct usb_interface *intf,
cam->udev = udev;
if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) {
- info("cam->buffer: out of memory !");
+ dev_info(&udev->dev, "cam->buffer: out of memory !\n");
video_device_release(cam->vdev);
kfree(cam);
return -ENODEV;
@@ -835,17 +845,17 @@ static int zr364xx_probe(struct usb_interface *intf,
switch (mode) {
case 1:
- info("160x120 mode selected");
+ dev_info(&udev->dev, "160x120 mode selected\n");
cam->width = 160;
cam->height = 120;
break;
case 2:
- info("640x480 mode selected");
+ dev_info(&udev->dev, "640x480 mode selected\n");
cam->width = 640;
cam->height = 480;
break;
default:
- info("320x240 mode selected");
+ dev_info(&udev->dev, "320x240 mode selected\n");
cam->width = 320;
cam->height = 240;
break;
@@ -865,7 +875,7 @@ static int zr364xx_probe(struct usb_interface *intf,
err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
if (err) {
- info("video_register_device failed");
+ dev_err(&udev->dev, "video_register_device failed\n");
video_device_release(cam->vdev);
kfree(cam->buffer);
kfree(cam);
@@ -874,7 +884,8 @@ static int zr364xx_probe(struct usb_interface *intf,
usb_set_intfdata(intf, cam);
- info(DRIVER_DESC " controlling video device %d", cam->vdev->minor);
+ dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
+ cam->vdev->minor);
return 0;
}
@@ -884,7 +895,7 @@ static void zr364xx_disconnect(struct usb_interface *intf)
struct zr364xx_camera *cam = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
dev_set_drvdata(&intf->dev, NULL);
- info(DRIVER_DESC " webcam unplugged");
+ dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
if (cam->vdev)
video_unregister_device(cam->vdev);
cam->vdev = NULL;
@@ -913,16 +924,16 @@ static int __init zr364xx_init(void)
int retval;
retval = usb_register(&zr364xx_driver);
if (retval)
- info("usb_register failed!");
+ printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n");
else
- info(DRIVER_DESC " module loaded");
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return retval;
}
static void __exit zr364xx_exit(void)
{
- info(DRIVER_DESC " module unloaded");
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n");
usb_deregister(&zr364xx_driver);
}
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index a38005008a2..cea46906408 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -185,7 +185,7 @@ static void memstick_free(struct device *dev)
}
static struct class memstick_host_class = {
- .name = "memstick_host",
+ .name = "memstick_host",
.dev_release = memstick_free
};
@@ -264,7 +264,7 @@ EXPORT_SYMBOL(memstick_new_req);
* @sg - TPC argument
*/
void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
- struct scatterlist *sg)
+ const struct scatterlist *sg)
{
mrq->tpc = tpc;
if (tpc & 8)
@@ -294,7 +294,7 @@ EXPORT_SYMBOL(memstick_init_req_sg);
* user supplied buffer.
*/
void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
- void *buf, size_t length)
+ const void *buf, size_t length)
{
mrq->tpc = tpc;
if (tpc & 8)
@@ -439,7 +439,7 @@ static void memstick_check(struct work_struct *work)
if (!host->card) {
if (memstick_power_on(host))
goto out_power_off;
- } else
+ } else if (host->card->stop)
host->card->stop(host->card);
card = memstick_alloc_card(host);
@@ -458,7 +458,7 @@ static void memstick_check(struct work_struct *work)
|| !(host->card->check(host->card))) {
device_unregister(&host->card->dev);
host->card = NULL;
- } else
+ } else if (host->card->start)
host->card->start(host->card);
}
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 44b1817f2f2..6e291bf8237 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -30,6 +30,8 @@ module_param(major, int, 0644);
#define MSPRO_BLOCK_SIGNATURE 0xa5c3
#define MSPRO_BLOCK_MAX_ATTRIBUTES 41
+#define MSPRO_BLOCK_PART_SHIFT 3
+
enum {
MSPRO_BLOCK_ID_SYSINFO = 0x10,
MSPRO_BLOCK_ID_MODELNAME = 0x15,
@@ -195,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp)
static int mspro_block_disk_release(struct gendisk *disk)
{
struct mspro_block_data *msb = disk->private_data;
- int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT;
+ int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT;
mutex_lock(&mspro_block_disk_lock);
@@ -826,7 +828,7 @@ static void mspro_block_submit_req(struct request_queue *q)
if (msb->eject) {
while ((req = elv_next_request(q)) != NULL)
- end_queued_request(req, -ENODEV);
+ __blk_end_request(req, -ENODEV, blk_rq_bytes(req));
return;
}
@@ -877,6 +879,7 @@ static int mspro_block_switch_interface(struct memstick_dev *card)
struct mspro_block_data *msb = memstick_get_drvdata(card);
int rc = 0;
+try_again:
if (msb->caps & MEMSTICK_CAP_PAR4)
rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4);
else
@@ -930,6 +933,18 @@ static int mspro_block_switch_interface(struct memstick_dev *card)
rc = memstick_set_rw_addr(card);
if (!rc)
rc = mspro_block_set_interface(card, msb->system);
+
+ if (!rc) {
+ msleep(150);
+ rc = mspro_block_wait_for_ced(card);
+ if (rc)
+ return rc;
+
+ if (msb->caps & MEMSTICK_CAP_PAR8) {
+ msb->caps &= ~MEMSTICK_CAP_PAR8;
+ goto try_again;
+ }
+ }
}
return rc;
}
@@ -1117,14 +1132,16 @@ static int mspro_block_init_card(struct memstick_dev *card)
return -EIO;
msb->caps = host->caps;
- rc = mspro_block_switch_interface(card);
+
+ msleep(150);
+ rc = mspro_block_wait_for_ced(card);
if (rc)
return rc;
- msleep(200);
- rc = mspro_block_wait_for_ced(card);
+ rc = mspro_block_switch_interface(card);
if (rc)
return rc;
+
dev_dbg(&card->dev, "card activated\n");
if (msb->system != MEMSTICK_SYS_SERIAL)
msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
@@ -1192,12 +1209,12 @@ static int mspro_block_init_disk(struct memstick_dev *card)
if (rc)
return rc;
- if ((disk_id << MEMSTICK_PART_SHIFT) > 255) {
+ if ((disk_id << MSPRO_BLOCK_PART_SHIFT) > 255) {
rc = -ENOSPC;
goto out_release_id;
}
- msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT);
+ msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT);
if (!msb->disk) {
rc = -ENOMEM;
goto out_release_id;
@@ -1220,7 +1237,7 @@ static int mspro_block_init_disk(struct memstick_dev *card)
MSPRO_BLOCK_MAX_PAGES * msb->page_size);
msb->disk->major = major;
- msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT;
+ msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT;
msb->disk->fops = &ms_block_bdops;
msb->usage_count = 1;
msb->disk->private_data = msb;
@@ -1416,7 +1433,7 @@ out_unlock:
static struct memstick_device_id mspro_block_id_tbl[] = {
{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO,
- MEMSTICK_CLASS_GENERIC_DUO},
+ MEMSTICK_CLASS_DUO},
{}
};
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 3485c63d20b..2fb95a5b72e 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -81,6 +81,8 @@ struct jmb38x_ms {
#define TPC_CODE_SZ_MASK 0x00000700
#define TPC_DATA_SZ_MASK 0x00000007
+#define HOST_CONTROL_TDELAY_EN 0x00040000
+#define HOST_CONTROL_HW_OC_P 0x00010000
#define HOST_CONTROL_RESET_REQ 0x00008000
#define HOST_CONTROL_REI 0x00004000
#define HOST_CONTROL_LED 0x00000400
@@ -88,6 +90,7 @@ struct jmb38x_ms {
#define HOST_CONTROL_RESET 0x00000100
#define HOST_CONTROL_POWER_EN 0x00000080
#define HOST_CONTROL_CLOCK_EN 0x00000040
+#define HOST_CONTROL_REO 0x00000008
#define HOST_CONTROL_IF_SHIFT 4
#define HOST_CONTROL_IF_SERIAL 0x0
@@ -133,11 +136,15 @@ struct jmb38x_ms {
#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
#define CLOCK_CONTROL_40MHZ 0x00000001
-#define CLOCK_CONTROL_50MHZ 0x00000002
+#define CLOCK_CONTROL_50MHZ 0x0000000a
#define CLOCK_CONTROL_60MHZ 0x00000008
#define CLOCK_CONTROL_62_5MHZ 0x0000000c
#define CLOCK_CONTROL_OFF 0x00000000
+#define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0
+#define PCI_CTL_CLOCK_DLY_MASK_A 0x00000f00
+#define PCI_CTL_CLOCK_DLY_MASK_B 0x0000f000
+
enum {
CMD_READY = 0x01,
FIFO_READY = 0x02,
@@ -367,8 +374,7 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
return host->req->error;
}
- dev_dbg(&msh->dev, "control %08x\n",
- readl(host->addr + HOST_CONTROL));
+ dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL));
dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));
dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
@@ -637,7 +643,7 @@ static int jmb38x_ms_reset(struct jmb38x_ms_host *host)
ndelay(20);
}
dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");
- return -EIO;
+ /* return -EIO; */
reset_next:
writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN
@@ -680,7 +686,9 @@ static int jmb38x_ms_set_param(struct memstick_host *msh,
host_ctl = 7;
host_ctl |= HOST_CONTROL_POWER_EN
- | HOST_CONTROL_CLOCK_EN;
+ | HOST_CONTROL_CLOCK_EN
+ | HOST_CONTROL_HW_OC_P
+ | HOST_CONTROL_TDELAY_EN;
writel(host_ctl, host->addr + HOST_CONTROL);
writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
@@ -704,33 +712,40 @@ static int jmb38x_ms_set_param(struct memstick_host *msh,
break;
case MEMSTICK_INTERFACE:
host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
+ pci_read_config_dword(host->chip->pdev,
+ PCI_CTL_CLOCK_DLY_ADDR,
+ &clock_delay);
+ clock_delay &= host->id ? ~PCI_CTL_CLOCK_DLY_MASK_B
+ : ~PCI_CTL_CLOCK_DLY_MASK_A;
if (value == MEMSTICK_SERIAL) {
host_ctl &= ~HOST_CONTROL_FAST_CLK;
+ host_ctl &= ~HOST_CONTROL_REO;
host_ctl |= HOST_CONTROL_IF_SERIAL
<< HOST_CONTROL_IF_SHIFT;
host_ctl |= HOST_CONTROL_REI;
clock_ctl = CLOCK_CONTROL_40MHZ;
- clock_delay = 0;
} else if (value == MEMSTICK_PAR4) {
- host_ctl |= HOST_CONTROL_FAST_CLK;
+ host_ctl |= HOST_CONTROL_FAST_CLK | HOST_CONTROL_REO;
host_ctl |= HOST_CONTROL_IF_PAR4
<< HOST_CONTROL_IF_SHIFT;
host_ctl &= ~HOST_CONTROL_REI;
clock_ctl = CLOCK_CONTROL_40MHZ;
- clock_delay = 4;
+ clock_delay |= host->id ? (4 << 12) : (4 << 8);
} else if (value == MEMSTICK_PAR8) {
host_ctl |= HOST_CONTROL_FAST_CLK;
host_ctl |= HOST_CONTROL_IF_PAR8
<< HOST_CONTROL_IF_SHIFT;
- host_ctl &= ~HOST_CONTROL_REI;
- clock_ctl = CLOCK_CONTROL_60MHZ;
- clock_delay = 0;
+ host_ctl &= ~(HOST_CONTROL_REI | HOST_CONTROL_REO);
+ clock_ctl = CLOCK_CONTROL_50MHZ;
} else
return -EINVAL;
+
writel(host_ctl, host->addr + HOST_CONTROL);
writel(clock_ctl, host->addr + CLOCK_CONTROL);
- writel(clock_delay, host->addr + CLOCK_DELAY);
+ pci_write_config_dword(host->chip->pdev,
+ PCI_CTL_CLOCK_DLY_ADDR,
+ clock_delay);
break;
};
return 0;
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
index 2c2e39aa1ef..b0982dacfd0 100644
--- a/drivers/message/i2o/Makefile
+++ b/drivers/message/i2o/Makefile
@@ -5,7 +5,7 @@
# In the future, some of these should be built conditionally.
#
-i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o
+i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o
i2o_bus-y += bus-osm.o
i2o_config-y += config-osm.o
obj-$(CONFIG_I2O) += i2o_core.o
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 8774c670e66..54c2e9ae23e 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -467,7 +467,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
res.virt = NULL;
- if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
+ if (i2o_dma_alloc(dev, &res, reslen))
return -ENOMEM;
msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 6cbcc21de51..56faef1a1d5 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -388,8 +388,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
dev = &c->pdev->dev;
- if (i2o_dma_realloc
- (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
+ if (i2o_dma_realloc(dev, &c->dlct,
+ le32_to_cpu(sb->expected_lct_size)))
return -ENOMEM;
msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 4238de98d4a..a3fabdbe6ca 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -260,7 +260,7 @@ static int i2o_cfg_swdl(unsigned long arg)
if (IS_ERR(msg))
return PTR_ERR(msg);
- if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+ if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
i2o_msg_nop(c, msg);
return -ENOMEM;
}
@@ -339,7 +339,7 @@ static int i2o_cfg_swul(unsigned long arg)
if (IS_ERR(msg))
return PTR_ERR(msg);
- if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+ if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
i2o_msg_nop(c, msg);
return -ENOMEM;
}
@@ -634,9 +634,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
sg_size = sg[i].flag_count & 0xffffff;
p = &(sg_list[sg_index]);
/* Allocate memory for the transfer */
- if (i2o_dma_alloc
- (&c->pdev->dev, p, sg_size,
- PCI_DMA_BIDIRECTIONAL)) {
+ if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
printk(KERN_DEBUG
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
@@ -780,12 +778,11 @@ static int i2o_cfg_passthru(unsigned long arg)
u32 size = 0;
u32 reply_size = 0;
u32 rcode = 0;
- void *sg_list[SG_TABLESIZE];
+ struct i2o_dma sg_list[SG_TABLESIZE];
u32 sg_offset = 0;
u32 sg_count = 0;
int sg_index = 0;
u32 i = 0;
- void *p = NULL;
i2o_status_block *sb;
struct i2o_message *msg;
unsigned int iop;
@@ -842,6 +839,7 @@ static int i2o_cfg_passthru(unsigned long arg)
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
+ struct i2o_dma *p;
if (sg_offset * 4 >= size) {
rcode = -EFAULT;
@@ -871,22 +869,22 @@ static int i2o_cfg_passthru(unsigned long arg)
goto sg_list_cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
+ p = &(sg_list[sg_index]);
+ if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
/* Allocate memory for the transfer */
- p = kmalloc(sg_size, GFP_KERNEL);
- if (!p) {
printk(KERN_DEBUG
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
rcode = -ENOMEM;
goto sg_list_cleanup;
}
- sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
+ sg_index++;
/* Copy in the user's SG buffer if necessary */
if (sg[i].
flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
// TODO 64bit fix
if (copy_from_user
- (p, (void __user *)sg[i].addr_bus,
+ (p->virt, (void __user *)sg[i].addr_bus,
sg_size)) {
printk(KERN_DEBUG
"%s: Could not copy SG buf %d FROM user\n",
@@ -895,8 +893,7 @@ static int i2o_cfg_passthru(unsigned long arg)
goto sg_list_cleanup;
}
}
- //TODO 64bit fix
- sg[i].addr_bus = virt_to_bus(p);
+ sg[i].addr_bus = p->phys;
}
}
@@ -908,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg)
}
if (sg_offset) {
- u32 rmsg[128];
+ u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
@@ -942,11 +939,11 @@ static int i2o_cfg_passthru(unsigned long arg)
sg_size = sg[j].flag_count & 0xffffff;
// TODO 64bit fix
if (copy_to_user
- ((void __user *)sg[j].addr_bus, sg_list[j],
+ ((void __user *)sg[j].addr_bus, sg_list[j].virt,
sg_size)) {
printk(KERN_WARNING
"%s: Could not copy %p TO user %x\n",
- c->name, sg_list[j],
+ c->name, sg_list[j].virt,
sg[j].addr_bus);
rcode = -EFAULT;
goto sg_list_cleanup;
@@ -973,7 +970,7 @@ sg_list_cleanup:
}
for (i = 0; i < sg_index; i++)
- kfree(sg_list[i]);
+ i2o_dma_free(&c->pdev->dev, &sg_list[i]);
cleanup:
kfree(reply);
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index da715e11c1b..be2b5926d26 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1004,7 +1004,7 @@ static int i2o_hrt_get(struct i2o_controller *c)
size = hrt->num_entries * hrt->entry_len << 2;
if (size > c->hrt.len) {
- if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL))
+ if (i2o_dma_realloc(dev, &c->hrt, size))
return -ENOMEM;
else
hrt = c->hrt.virt;
diff --git a/drivers/message/i2o/memory.c b/drivers/message/i2o/memory.c
new file mode 100644
index 00000000000..f5cc95c564e
--- /dev/null
+++ b/drivers/message/i2o/memory.c
@@ -0,0 +1,313 @@
+/*
+ * Functions to handle I2O memory
+ *
+ * Pulled from the inlines in i2o headers and uninlined
+ *
+ *
+ * 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/module.h>
+#include <linux/i2o.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "core.h"
+
+/* Protects our 32/64bit mask switching */
+static DEFINE_MUTEX(mem_lock);
+
+/**
+ * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
+ * @c: I2O controller for which the calculation should be done
+ * @body_size: maximum body size used for message in 32-bit words.
+ *
+ * Return the maximum number of SG elements in a SG list.
+ */
+u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
+{
+ i2o_status_block *sb = c->status_block.virt;
+ u16 sg_count =
+ (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
+ body_size;
+
+ if (c->pae_support) {
+ /*
+ * for 64-bit a SG attribute element must be added and each
+ * SG element needs 12 bytes instead of 8.
+ */
+ sg_count -= 2;
+ sg_count /= 3;
+ } else
+ sg_count /= 2;
+
+ if (c->short_req && (sg_count > 8))
+ sg_count = 8;
+
+ return sg_count;
+}
+EXPORT_SYMBOL_GPL(i2o_sg_tablesize);
+
+
+/**
+ * i2o_dma_map_single - Map pointer to controller and fill in I2O message.
+ * @c: I2O controller
+ * @ptr: pointer to the data which should be mapped
+ * @size: size of data in bytes
+ * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ * @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ * This function does all necessary DMA handling and also writes the I2O
+ * SGL elements into the I2O message. For details on DMA handling see also
+ * dma_map_single(). The pointer sg_ptr will only be set to the end of the
+ * SG list if the allocation was successful.
+ *
+ * Returns DMA address which must be checked for failures using
+ * dma_mapping_error().
+ */
+dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
+ size_t size,
+ enum dma_data_direction direction,
+ u32 ** sg_ptr)
+{
+ u32 sg_flags;
+ u32 *mptr = *sg_ptr;
+ dma_addr_t dma_addr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ sg_flags = 0xd4000000;
+ break;
+ case DMA_FROM_DEVICE:
+ sg_flags = 0xd0000000;
+ break;
+ default:
+ return 0;
+ }
+
+ dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
+ if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+ *mptr++ = cpu_to_le32(0x7C020002);
+ *mptr++ = cpu_to_le32(PAGE_SIZE);
+ }
+#endif
+
+ *mptr++ = cpu_to_le32(sg_flags | size);
+ *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+ *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));
+#endif
+ *sg_ptr = mptr;
+ }
+ return dma_addr;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_map_single);
+
+/**
+ * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
+ * @c: I2O controller
+ * @sg: SG list to be mapped
+ * @sg_count: number of elements in the SG list
+ * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ * @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ * This function does all necessary DMA handling and also writes the I2O
+ * SGL elements into the I2O message. For details on DMA handling see also
+ * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
+ * list if the allocation was successful.
+ *
+ * Returns 0 on failure or 1 on success.
+ */
+int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg,
+ int sg_count, enum dma_data_direction direction, u32 ** sg_ptr)
+{
+ u32 sg_flags;
+ u32 *mptr = *sg_ptr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ sg_flags = 0x14000000;
+ break;
+ case DMA_FROM_DEVICE:
+ sg_flags = 0x10000000;
+ break;
+ default:
+ return 0;
+ }
+
+ sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
+ if (!sg_count)
+ return 0;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+ *mptr++ = cpu_to_le32(0x7C020002);
+ *mptr++ = cpu_to_le32(PAGE_SIZE);
+ }
+#endif
+
+ while (sg_count-- > 0) {
+ if (!sg_count)
+ sg_flags |= 0xC0000000;
+ *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));
+ *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+ *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
+#endif
+ sg = sg_next(sg);
+ }
+ *sg_ptr = mptr;
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_map_sg);
+
+/**
+ * i2o_dma_alloc - Allocate DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: i2o_dma struct which should get the DMA buffer
+ * @len: length of the new DMA memory
+ *
+ * Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ * Returns 0 on success or -ENOMEM on failure.
+ */
+int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int dma_64 = 0;
+
+ mutex_lock(&mem_lock);
+ if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
+ dma_64 = 1;
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ mutex_unlock(&mem_lock);
+ return -ENOMEM;
+ }
+ }
+
+ addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL);
+
+ if ((sizeof(dma_addr_t) > 4) && dma_64)
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+ printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
+ mutex_unlock(&mem_lock);
+
+ if (!addr->virt)
+ return -ENOMEM;
+
+ memset(addr->virt, 0, len);
+ addr->len = len;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_alloc);
+
+
+/**
+ * i2o_dma_free - Free DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: i2o_dma struct which contains the DMA buffer
+ *
+ * Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+ if (addr->virt) {
+ if (addr->phys)
+ dma_free_coherent(dev, addr->len, addr->virt,
+ addr->phys);
+ else
+ kfree(addr->virt);
+ addr->virt = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(i2o_dma_free);
+
+
+/**
+ * i2o_dma_realloc - Realloc DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: pointer to a i2o_dma struct DMA buffer
+ * @len: new length of memory
+ *
+ * If there was something allocated in the addr, free it first. If len > 0
+ * than try to allocate it and write the addresses back to the addr
+ * structure. If len == 0 set the virtual address to NULL.
+ *
+ * Returns the 0 on success or negative error code on failure.
+ */
+int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len)
+{
+ i2o_dma_free(dev, addr);
+
+ if (len)
+ return i2o_dma_alloc(dev, addr, len);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_realloc);
+
+/*
+ * i2o_pool_alloc - Allocate an slab cache and mempool
+ * @mempool: pointer to struct i2o_pool to write data into.
+ * @name: name which is used to identify cache
+ * @size: size of each object
+ * @min_nr: minimum number of objects
+ *
+ * First allocates a slab cache with name and size. Then allocates a
+ * mempool which uses the slab cache for allocation and freeing.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
+ size_t size, int min_nr)
+{
+ pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (!pool->name)
+ goto exit;
+ strcpy(pool->name, name);
+
+ pool->slab =
+ kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!pool->slab)
+ goto free_name;
+
+ pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);
+ if (!pool->mempool)
+ goto free_slab;
+
+ return 0;
+
+free_slab:
+ kmem_cache_destroy(pool->slab);
+
+free_name:
+ kfree(pool->name);
+
+exit:
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(i2o_pool_alloc);
+
+/*
+ * i2o_pool_free - Free slab cache and mempool again
+ * @mempool: pointer to struct i2o_pool which should be freed
+ *
+ * Note that you have to return all objects to the mempool again before
+ * calling i2o_pool_free().
+ */
+void i2o_pool_free(struct i2o_pool *pool)
+{
+ mempool_destroy(pool->mempool);
+ kmem_cache_destroy(pool->slab);
+ kfree(pool->name);
+};
+EXPORT_SYMBOL_GPL(i2o_pool_free);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 685a89547a5..610ef1204e6 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -186,31 +186,29 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
}
}
- if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
+ if (i2o_dma_alloc(dev, &c->status, 8)) {
i2o_pci_free(c);
return -ENOMEM;
}
- if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) {
+ if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) {
i2o_pci_free(c);
return -ENOMEM;
}
- if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) {
+ if (i2o_dma_alloc(dev, &c->dlct, 8192)) {
i2o_pci_free(c);
return -ENOMEM;
}
- if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block),
- GFP_KERNEL)) {
+ if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) {
i2o_pci_free(c);
return -ENOMEM;
}
- if (i2o_dma_alloc
- (dev, &c->out_queue,
- I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
- sizeof(u32), GFP_KERNEL)) {
+ if (i2o_dma_alloc(dev, &c->out_queue,
+ I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
+ sizeof(u32))) {
i2o_pci_free(c);
return -ENOMEM;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 10c44d3fe01..5eff8ad834d 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -21,7 +21,7 @@ config MFD_SM501
config MFD_SM501_GPIO
bool "Export GPIO via GPIO layer"
- depends on MFD_SM501 && HAVE_GPIO_LIB
+ depends on MFD_SM501 && GPIOLIB
---help---
This option uses the gpio library layer to export the 64 GPIO
lines on the SM501. The platform data is used to supply the
@@ -29,7 +29,7 @@ config MFD_SM501_GPIO
config MFD_ASIC3
bool "Support for Compaq ASIC3"
- depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
+ depends on GENERIC_HARDIRQS && GPIOLIB && ARM
---help---
This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones)
@@ -50,6 +50,15 @@ config HTC_PASIC3
HTC Magician devices, respectively. Actual functionality is
handled by the leds-pasic3 and ds1wm drivers.
+config UCB1400_CORE
+ tristate "Philips UCB1400 Core driver"
+ help
+ This enables support for the Philips UCB1400 core functions.
+ The UCB1400 is an AC97 audio codec.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ucb1400_core.
+
config MFD_TMIO
bool
default n
@@ -78,6 +87,44 @@ config MFD_TC6393XB
help
Support for Toshiba Mobile IO Controller TC6393XB
+config MFD_WM8400
+ tristate "Support Wolfson Microelectronics WM8400"
+ help
+ Support for the Wolfson Microelecronics WM8400 PMIC and audio
+ CODEC. This driver adds provides common support for accessing
+ the device, additional drivers must be enabled in order to use
+ the functionality of the device.
+
+config MFD_WM8350
+ tristate
+
+config MFD_WM8350_CONFIG_MODE_0
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_1
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_2
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_3
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8350_I2C
+ tristate "Support Wolfson Microelectronics WM8350 with I2C"
+ select MFD_WM8350
+ depends on I2C
+ help
+ The WM8350 is an integrated audio and power management
+ subsystem with watchdog and RTC functionality for embedded
+ systems. This option enables core support for the WM8350 with
+ I2C as the control interface. Additional options must be
+ selected to enable support for the functionality of the chip.
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 03ad239ecef..759b1fe1c89 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -12,6 +12,11 @@ obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
+obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
+wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
+obj-$(CONFIG_MFD_WM8350) += wm8350.o
+obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_MCP) += mcp-core.o
@@ -22,3 +27,4 @@ obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
ifeq ($(CONFIG_SA1100_ASSABET),y)
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
endif
+obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index bc2a807f210..ba5aa200827 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -312,7 +312,6 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
struct asic3 *asic = platform_get_drvdata(pdev);
unsigned long clksel = 0;
unsigned int irq, irq_base;
- int map_size;
int ret;
ret = platform_get_irq(pdev, 0);
@@ -534,6 +533,7 @@ static int __init asic3_probe(struct platform_device *pdev)
struct asic3 *asic;
struct resource *mem;
unsigned long clksel;
+ int map_size;
int ret = 0;
asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c
new file mode 100644
index 00000000000..178159e264c
--- /dev/null
+++ b/drivers/mfd/ucb1400_core.c
@@ -0,0 +1,106 @@
+/*
+ * Core functions for:
+ * Philips UCB1400 multifunction chip
+ *
+ * Based on ucb1400_ts.c:
+ * Author: Nicolas Pitre
+ * Created: September 25, 2006
+ * Copyright: MontaVista Software, Inc.
+ *
+ * Spliting done by: Marek Vasut <marek.vasut@gmail.com>
+ * If something doesnt work and it worked before spliting, e-mail me,
+ * dont bother Nicolas please ;-)
+ *
+ * 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.
+ *
+ * This code is heavily based on ucb1x00-*.c copyrighted by Russell King
+ * covering the UCB1100, UCB1200 and UCB1300.. Support for the UCB1400 has
+ * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request.
+ */
+
+#include <linux/module.h>
+#include <linux/ucb1400.h>
+
+static int ucb1400_core_probe(struct device *dev)
+{
+ int err;
+ struct ucb1400 *ucb;
+ struct ucb1400_ts ucb_ts;
+ struct snd_ac97 *ac97;
+
+ memset(&ucb_ts, 0, sizeof(ucb_ts));
+
+ ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL);
+ if (!ucb) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ dev_set_drvdata(dev, ucb);
+
+ ac97 = to_ac97_t(dev);
+
+ ucb_ts.id = ucb1400_reg_read(ac97, UCB_ID);
+ if (ucb_ts.id != UCB_ID_1400) {
+ err = -ENODEV;
+ goto err0;
+ }
+
+ /* TOUCHSCREEN */
+ ucb_ts.ac97 = ac97;
+ ucb->ucb1400_ts = platform_device_alloc("ucb1400_ts", -1);
+ if (!ucb->ucb1400_ts) {
+ err = -ENOMEM;
+ goto err0;
+ }
+ err = platform_device_add_data(ucb->ucb1400_ts, &ucb_ts,
+ sizeof(ucb_ts));
+ if (err)
+ goto err1;
+ err = platform_device_add(ucb->ucb1400_ts);
+ if (err)
+ goto err1;
+
+ return 0;
+
+err1:
+ platform_device_put(ucb->ucb1400_ts);
+err0:
+ kfree(ucb);
+err:
+ return err;
+}
+
+static int ucb1400_core_remove(struct device *dev)
+{
+ struct ucb1400 *ucb = dev_get_drvdata(dev);
+
+ platform_device_unregister(ucb->ucb1400_ts);
+ kfree(ucb);
+ return 0;
+}
+
+static struct device_driver ucb1400_core_driver = {
+ .name = "ucb1400_core",
+ .bus = &ac97_bus_type,
+ .probe = ucb1400_core_probe,
+ .remove = ucb1400_core_remove,
+};
+
+static int __init ucb1400_core_init(void)
+{
+ return driver_register(&ucb1400_core_driver);
+}
+
+static void __exit ucb1400_core_exit(void)
+{
+ driver_unregister(&ucb1400_core_driver);
+}
+
+module_init(ucb1400_core_init);
+module_exit(ucb1400_core_exit);
+
+MODULE_DESCRIPTION("Philips UCB1400 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
new file mode 100644
index 00000000000..25a7a5d08bc
--- /dev/null
+++ b/drivers/mfd/wm8350-core.c
@@ -0,0 +1,1273 @@
+/*
+ * wm8350-core.c -- Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood, Mark Brown
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/comparator.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/wdt.h>
+
+#define WM8350_UNLOCK_KEY 0x0013
+#define WM8350_LOCK_KEY 0x0000
+
+#define WM8350_CLOCK_CONTROL_1 0x28
+#define WM8350_AIF_TEST 0x74
+
+/* debug */
+#define WM8350_BUS_DEBUG 0
+#if WM8350_BUS_DEBUG
+#define dump(regs, src) do { \
+ int i_; \
+ u16 *src_ = src; \
+ printk(KERN_DEBUG); \
+ for (i_ = 0; i_ < regs; i_++) \
+ printk(" 0x%4.4x", *src_++); \
+ printk("\n"); \
+} while (0);
+#else
+#define dump(bytes, src)
+#endif
+
+#define WM8350_LOCK_DEBUG 0
+#if WM8350_LOCK_DEBUG
+#define ldbg(format, arg...) printk(format, ## arg)
+#else
+#define ldbg(format, arg...)
+#endif
+
+/*
+ * WM8350 Device IO
+ */
+static DEFINE_MUTEX(io_mutex);
+static DEFINE_MUTEX(reg_lock_mutex);
+static DEFINE_MUTEX(auxadc_mutex);
+
+/* Perform a physical read from the device.
+ */
+static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
+ u16 *dest)
+{
+ int i, ret;
+ int bytes = num_regs * 2;
+
+ dev_dbg(wm8350->dev, "volatile read\n");
+ ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
+
+ for (i = reg; i < reg + num_regs; i++) {
+ /* Cache is CPU endian */
+ dest[i - reg] = be16_to_cpu(dest[i - reg]);
+
+ /* Satisfy non-volatile bits from cache */
+ dest[i - reg] &= wm8350_reg_io_map[i].vol;
+ dest[i - reg] |= wm8350->reg_cache[i];
+
+ /* Mask out non-readable bits */
+ dest[i - reg] &= wm8350_reg_io_map[i].readable;
+ }
+
+ dump(num_regs, dest);
+
+ return ret;
+}
+
+static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
+{
+ int i;
+ int end = reg + num_regs;
+ int ret = 0;
+ int bytes = num_regs * 2;
+
+ if (wm8350->read_dev == NULL)
+ return -ENODEV;
+
+ if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+ dev_err(wm8350->dev, "invalid reg %x\n",
+ reg + num_regs - 1);
+ return -EINVAL;
+ }
+
+ dev_dbg(wm8350->dev,
+ "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs);
+
+#if WM8350_BUS_DEBUG
+ /* we can _safely_ read any register, but warn if read not supported */
+ for (i = reg; i < end; i++) {
+ if (!wm8350_reg_io_map[i].readable)
+ dev_warn(wm8350->dev,
+ "reg R%d is not readable\n", i);
+ }
+#endif
+
+ /* if any volatile registers are required, then read back all */
+ for (i = reg; i < end; i++)
+ if (wm8350_reg_io_map[i].vol)
+ return wm8350_phys_read(wm8350, reg, num_regs, dest);
+
+ /* no volatiles, then cache is good */
+ dev_dbg(wm8350->dev, "cache read\n");
+ memcpy(dest, &wm8350->reg_cache[reg], bytes);
+ dump(num_regs, dest);
+ return ret;
+}
+
+static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
+{
+ if (reg == WM8350_SECURITY ||
+ wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
+ return 0;
+
+ if ((reg == WM8350_GPIO_CONFIGURATION_I_O) ||
+ (reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
+ reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
+ (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
+ reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
+ return 1;
+ return 0;
+}
+
+static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
+{
+ int i;
+ int end = reg + num_regs;
+ int bytes = num_regs * 2;
+
+ if (wm8350->write_dev == NULL)
+ return -ENODEV;
+
+ if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+ dev_err(wm8350->dev, "invalid reg %x\n",
+ reg + num_regs - 1);
+ return -EINVAL;
+ }
+
+ /* it's generally not a good idea to write to RO or locked registers */
+ for (i = reg; i < end; i++) {
+ if (!wm8350_reg_io_map[i].writable) {
+ dev_err(wm8350->dev,
+ "attempted write to read only reg R%d\n", i);
+ return -EINVAL;
+ }
+
+ if (is_reg_locked(wm8350, i)) {
+ dev_err(wm8350->dev,
+ "attempted write to locked reg R%d\n", i);
+ return -EINVAL;
+ }
+
+ src[i - reg] &= wm8350_reg_io_map[i].writable;
+
+ wm8350->reg_cache[i] =
+ (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
+ | src[i - reg];
+
+ src[i - reg] = cpu_to_be16(src[i - reg]);
+ }
+
+ /* Actually write it out */
+ return wm8350->write_dev(wm8350, reg, bytes, (char *)src);
+}
+
+/*
+ * Safe read, modify, write methods
+ */
+int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+ u16 data;
+ int err;
+
+ mutex_lock(&io_mutex);
+ err = wm8350_read(wm8350, reg, 1, &data);
+ if (err) {
+ dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+ goto out;
+ }
+
+ data &= ~mask;
+ err = wm8350_write(wm8350, reg, 1, &data);
+ if (err)
+ dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+ mutex_unlock(&io_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_clear_bits);
+
+int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+ u16 data;
+ int err;
+
+ mutex_lock(&io_mutex);
+ err = wm8350_read(wm8350, reg, 1, &data);
+ if (err) {
+ dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+ goto out;
+ }
+
+ data |= mask;
+ err = wm8350_write(wm8350, reg, 1, &data);
+ if (err)
+ dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+ mutex_unlock(&io_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_set_bits);
+
+u16 wm8350_reg_read(struct wm8350 *wm8350, int reg)
+{
+ u16 data;
+ int err;
+
+ mutex_lock(&io_mutex);
+ err = wm8350_read(wm8350, reg, 1, &data);
+ if (err)
+ dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+
+ mutex_unlock(&io_mutex);
+ return data;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_read);
+
+int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val)
+{
+ int ret;
+ u16 data = val;
+
+ mutex_lock(&io_mutex);
+ ret = wm8350_write(wm8350, reg, 1, &data);
+ if (ret)
+ dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+ mutex_unlock(&io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_write);
+
+int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs,
+ u16 *dest)
+{
+ int err = 0;
+
+ mutex_lock(&io_mutex);
+ err = wm8350_read(wm8350, start_reg, regs, dest);
+ if (err)
+ dev_err(wm8350->dev, "block read starting from R%d failed\n",
+ start_reg);
+ mutex_unlock(&io_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_read);
+
+int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
+ u16 *src)
+{
+ int ret = 0;
+
+ mutex_lock(&io_mutex);
+ ret = wm8350_write(wm8350, start_reg, regs, src);
+ if (ret)
+ dev_err(wm8350->dev, "block write starting at R%d failed\n",
+ start_reg);
+ mutex_unlock(&io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_write);
+
+int wm8350_reg_lock(struct wm8350 *wm8350)
+{
+ u16 key = WM8350_LOCK_KEY;
+ int ret;
+
+ ldbg(__func__);
+ mutex_lock(&io_mutex);
+ ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+ if (ret)
+ dev_err(wm8350->dev, "lock failed\n");
+ mutex_unlock(&io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_lock);
+
+int wm8350_reg_unlock(struct wm8350 *wm8350)
+{
+ u16 key = WM8350_UNLOCK_KEY;
+ int ret;
+
+ ldbg(__func__);
+ mutex_lock(&io_mutex);
+ ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+ if (ret)
+ dev_err(wm8350->dev, "unlock failed\n");
+ mutex_unlock(&io_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
+
+static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
+{
+ mutex_lock(&wm8350->irq_mutex);
+
+ if (wm8350->irq[irq].handler)
+ wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data);
+ else {
+ dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
+ irq);
+ wm8350_mask_irq(wm8350, irq);
+ }
+
+ mutex_unlock(&wm8350->irq_mutex);
+}
+
+/*
+ * wm8350_irq_worker actually handles the interrupts. Since all
+ * interrupts are clear on read the IRQ line will be reasserted and
+ * the physical IRQ will be handled again if another interrupt is
+ * asserted while we run - in the normal course of events this is a
+ * rare occurrence so we save I2C/SPI reads.
+ */
+static void wm8350_irq_worker(struct work_struct *work)
+{
+ struct wm8350 *wm8350 = container_of(work, struct wm8350, irq_work);
+ u16 level_one, status1, status2, comp;
+
+ /* TODO: Use block reads to improve performance? */
+ level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
+ & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
+ status1 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1)
+ & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_1_MASK);
+ status2 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_2)
+ & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_2_MASK);
+ comp = wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS)
+ & ~wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK);
+
+ /* over current */
+ if (level_one & WM8350_OC_INT) {
+ u16 oc;
+
+ oc = wm8350_reg_read(wm8350, WM8350_OVER_CURRENT_INT_STATUS);
+ oc &= ~wm8350_reg_read(wm8350,
+ WM8350_OVER_CURRENT_INT_STATUS_MASK);
+
+ if (oc & WM8350_OC_LS_EINT) /* limit switch */
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_OC_LS);
+ }
+
+ /* under voltage */
+ if (level_one & WM8350_UV_INT) {
+ u16 uv;
+
+ uv = wm8350_reg_read(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS);
+ uv &= ~wm8350_reg_read(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK);
+
+ if (uv & WM8350_UV_DC1_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC1);
+ if (uv & WM8350_UV_DC2_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC2);
+ if (uv & WM8350_UV_DC3_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC3);
+ if (uv & WM8350_UV_DC4_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC4);
+ if (uv & WM8350_UV_DC5_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC5);
+ if (uv & WM8350_UV_DC6_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC6);
+ if (uv & WM8350_UV_LDO1_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO1);
+ if (uv & WM8350_UV_LDO2_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO2);
+ if (uv & WM8350_UV_LDO3_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO3);
+ if (uv & WM8350_UV_LDO4_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO4);
+ }
+
+ /* charger, RTC */
+ if (status1) {
+ if (status1 & WM8350_CHG_BAT_HOT_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_BAT_HOT);
+ if (status1 & WM8350_CHG_BAT_COLD_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_BAT_COLD);
+ if (status1 & WM8350_CHG_BAT_FAIL_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_BAT_FAIL);
+ if (status1 & WM8350_CHG_TO_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_TO);
+ if (status1 & WM8350_CHG_END_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_END);
+ if (status1 & WM8350_CHG_START_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_START);
+ if (status1 & WM8350_CHG_FAST_RDY_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_FAST_RDY);
+ if (status1 & WM8350_CHG_VBATT_LT_3P9_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_VBATT_LT_3P9);
+ if (status1 & WM8350_CHG_VBATT_LT_3P1_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_VBATT_LT_3P1);
+ if (status1 & WM8350_CHG_VBATT_LT_2P85_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CHG_VBATT_LT_2P85);
+ if (status1 & WM8350_RTC_ALM_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_ALM);
+ if (status1 & WM8350_RTC_SEC_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_SEC);
+ if (status1 & WM8350_RTC_PER_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_PER);
+ }
+
+ /* current sink, system, aux adc */
+ if (status2) {
+ if (status2 & WM8350_CS1_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS1);
+ if (status2 & WM8350_CS2_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS2);
+
+ if (status2 & WM8350_SYS_HYST_COMP_FAIL_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_SYS_HYST_COMP_FAIL);
+ if (status2 & WM8350_SYS_CHIP_GT115_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_SYS_CHIP_GT115);
+ if (status2 & WM8350_SYS_CHIP_GT140_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_SYS_CHIP_GT140);
+ if (status2 & WM8350_SYS_WDOG_TO_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_SYS_WDOG_TO);
+
+ if (status2 & WM8350_AUXADC_DATARDY_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_AUXADC_DATARDY);
+ if (status2 & WM8350_AUXADC_DCOMP4_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_AUXADC_DCOMP4);
+ if (status2 & WM8350_AUXADC_DCOMP3_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_AUXADC_DCOMP3);
+ if (status2 & WM8350_AUXADC_DCOMP2_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_AUXADC_DCOMP2);
+ if (status2 & WM8350_AUXADC_DCOMP1_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_AUXADC_DCOMP1);
+
+ if (status2 & WM8350_USB_LIMIT_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_USB_LIMIT);
+ }
+
+ /* wake, codec, ext */
+ if (comp) {
+ if (comp & WM8350_WKUP_OFF_STATE_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_OFF_STATE);
+ if (comp & WM8350_WKUP_HIB_STATE_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_HIB_STATE);
+ if (comp & WM8350_WKUP_CONV_FAULT_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_CONV_FAULT);
+ if (comp & WM8350_WKUP_WDOG_RST_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_WDOG_RST);
+ if (comp & WM8350_WKUP_GP_PWR_ON_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_GP_PWR_ON);
+ if (comp & WM8350_WKUP_ONKEY_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_WKUP_ONKEY);
+ if (comp & WM8350_WKUP_GP_WAKEUP_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_WKUP_GP_WAKEUP);
+
+ if (comp & WM8350_CODEC_JCK_DET_L_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CODEC_JCK_DET_L);
+ if (comp & WM8350_CODEC_JCK_DET_R_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CODEC_JCK_DET_R);
+ if (comp & WM8350_CODEC_MICSCD_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_CODEC_MICSCD);
+ if (comp & WM8350_CODEC_MICD_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_CODEC_MICD);
+
+ if (comp & WM8350_EXT_USB_FB_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_USB_FB);
+ if (comp & WM8350_EXT_WALL_FB_EINT)
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_EXT_WALL_FB);
+ if (comp & WM8350_EXT_BAT_FB_EINT)
+ wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_BAT_FB);
+ }
+
+ if (level_one & WM8350_GP_INT) {
+ int i;
+ u16 gpio;
+
+ gpio = wm8350_reg_read(wm8350, WM8350_GPIO_INT_STATUS);
+ gpio &= ~wm8350_reg_read(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK);
+
+ for (i = 0; i < 12; i++) {
+ if (gpio & (1 << i))
+ wm8350_irq_call_handler(wm8350,
+ WM8350_IRQ_GPIO(i));
+ }
+ }
+
+ enable_irq(wm8350->chip_irq);
+}
+
+static irqreturn_t wm8350_irq(int irq, void *data)
+{
+ struct wm8350 *wm8350 = data;
+
+ disable_irq_nosync(irq);
+ schedule_work(&wm8350->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+ void (*handler) (struct wm8350 *, int, void *),
+ void *data)
+{
+ if (irq < 0 || irq > WM8350_NUM_IRQ || !handler)
+ return -EINVAL;
+
+ if (wm8350->irq[irq].handler)
+ return -EBUSY;
+
+ mutex_lock(&wm8350->irq_mutex);
+ wm8350->irq[irq].handler = handler;
+ wm8350->irq[irq].data = data;
+ mutex_unlock(&wm8350->irq_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_irq);
+
+int wm8350_free_irq(struct wm8350 *wm8350, int irq)
+{
+ if (irq < 0 || irq > WM8350_NUM_IRQ)
+ return -EINVAL;
+
+ mutex_lock(&wm8350->irq_mutex);
+ wm8350->irq[irq].handler = NULL;
+ mutex_unlock(&wm8350->irq_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_free_irq);
+
+int wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+{
+ switch (irq) {
+ case WM8350_IRQ_CHG_BAT_HOT:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_HOT_EINT);
+ case WM8350_IRQ_CHG_BAT_COLD:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_COLD_EINT);
+ case WM8350_IRQ_CHG_BAT_FAIL:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_FAIL_EINT);
+ case WM8350_IRQ_CHG_TO:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_TO_EINT);
+ case WM8350_IRQ_CHG_END:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_END_EINT);
+ case WM8350_IRQ_CHG_START:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_START_EINT);
+ case WM8350_IRQ_CHG_FAST_RDY:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_FAST_RDY_EINT);
+ case WM8350_IRQ_RTC_PER:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_PER_EINT);
+ case WM8350_IRQ_RTC_SEC:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_SEC_EINT);
+ case WM8350_IRQ_RTC_ALM:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_ALM_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_3P9:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_3P1:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_2P85:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+ case WM8350_IRQ_CS1:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_CS1_EINT);
+ case WM8350_IRQ_CS2:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_CS2_EINT);
+ case WM8350_IRQ_USB_LIMIT:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_USB_LIMIT_EINT);
+ case WM8350_IRQ_AUXADC_DATARDY:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DATARDY_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP4:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP4_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP3:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP3_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP2:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP2_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP1:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP1_EINT);
+ case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+ case WM8350_IRQ_SYS_CHIP_GT115:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_CHIP_GT115_EINT);
+ case WM8350_IRQ_SYS_CHIP_GT140:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_CHIP_GT140_EINT);
+ case WM8350_IRQ_SYS_WDOG_TO:
+ return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_WDOG_TO_EINT);
+ case WM8350_IRQ_UV_LDO4:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO4_EINT);
+ case WM8350_IRQ_UV_LDO3:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO3_EINT);
+ case WM8350_IRQ_UV_LDO2:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO2_EINT);
+ case WM8350_IRQ_UV_LDO1:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO1_EINT);
+ case WM8350_IRQ_UV_DC6:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC6_EINT);
+ case WM8350_IRQ_UV_DC5:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC5_EINT);
+ case WM8350_IRQ_UV_DC4:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC4_EINT);
+ case WM8350_IRQ_UV_DC3:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC3_EINT);
+ case WM8350_IRQ_UV_DC2:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC2_EINT);
+ case WM8350_IRQ_UV_DC1:
+ return wm8350_set_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC1_EINT);
+ case WM8350_IRQ_OC_LS:
+ return wm8350_set_bits(wm8350,
+ WM8350_OVER_CURRENT_INT_STATUS_MASK,
+ WM8350_IM_OC_LS_EINT);
+ case WM8350_IRQ_EXT_USB_FB:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_USB_FB_EINT);
+ case WM8350_IRQ_EXT_WALL_FB:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_WALL_FB_EINT);
+ case WM8350_IRQ_EXT_BAT_FB:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_BAT_FB_EINT);
+ case WM8350_IRQ_CODEC_JCK_DET_L:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_JCK_DET_L_EINT);
+ case WM8350_IRQ_CODEC_JCK_DET_R:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_JCK_DET_R_EINT);
+ case WM8350_IRQ_CODEC_MICSCD:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_MICSCD_EINT);
+ case WM8350_IRQ_CODEC_MICD:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_MICD_EINT);
+ case WM8350_IRQ_WKUP_OFF_STATE:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_OFF_STATE_EINT);
+ case WM8350_IRQ_WKUP_HIB_STATE:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_HIB_STATE_EINT);
+ case WM8350_IRQ_WKUP_CONV_FAULT:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_CONV_FAULT_EINT);
+ case WM8350_IRQ_WKUP_WDOG_RST:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_OFF_STATE_EINT);
+ case WM8350_IRQ_WKUP_GP_PWR_ON:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_GP_PWR_ON_EINT);
+ case WM8350_IRQ_WKUP_ONKEY:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_ONKEY_EINT);
+ case WM8350_IRQ_WKUP_GP_WAKEUP:
+ return wm8350_set_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_GP_WAKEUP_EINT);
+ case WM8350_IRQ_GPIO(0):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP0_EINT);
+ case WM8350_IRQ_GPIO(1):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP1_EINT);
+ case WM8350_IRQ_GPIO(2):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP2_EINT);
+ case WM8350_IRQ_GPIO(3):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP3_EINT);
+ case WM8350_IRQ_GPIO(4):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP4_EINT);
+ case WM8350_IRQ_GPIO(5):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP5_EINT);
+ case WM8350_IRQ_GPIO(6):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP6_EINT);
+ case WM8350_IRQ_GPIO(7):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP7_EINT);
+ case WM8350_IRQ_GPIO(8):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP8_EINT);
+ case WM8350_IRQ_GPIO(9):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP9_EINT);
+ case WM8350_IRQ_GPIO(10):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP10_EINT);
+ case WM8350_IRQ_GPIO(11):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP11_EINT);
+ case WM8350_IRQ_GPIO(12):
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP12_EINT);
+ default:
+ dev_warn(wm8350->dev, "Attempting to mask unknown IRQ %d\n",
+ irq);
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_mask_irq);
+
+int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+{
+ switch (irq) {
+ case WM8350_IRQ_CHG_BAT_HOT:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_HOT_EINT);
+ case WM8350_IRQ_CHG_BAT_COLD:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_COLD_EINT);
+ case WM8350_IRQ_CHG_BAT_FAIL:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_BAT_FAIL_EINT);
+ case WM8350_IRQ_CHG_TO:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_TO_EINT);
+ case WM8350_IRQ_CHG_END:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_END_EINT);
+ case WM8350_IRQ_CHG_START:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_START_EINT);
+ case WM8350_IRQ_CHG_FAST_RDY:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_FAST_RDY_EINT);
+ case WM8350_IRQ_RTC_PER:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_PER_EINT);
+ case WM8350_IRQ_RTC_SEC:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_SEC_EINT);
+ case WM8350_IRQ_RTC_ALM:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_RTC_ALM_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_3P9:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_3P1:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+ case WM8350_IRQ_CHG_VBATT_LT_2P85:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+ WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+ case WM8350_IRQ_CS1:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_CS1_EINT);
+ case WM8350_IRQ_CS2:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_CS2_EINT);
+ case WM8350_IRQ_USB_LIMIT:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_USB_LIMIT_EINT);
+ case WM8350_IRQ_AUXADC_DATARDY:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DATARDY_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP4:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP4_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP3:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP3_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP2:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP2_EINT);
+ case WM8350_IRQ_AUXADC_DCOMP1:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_AUXADC_DCOMP1_EINT);
+ case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+ case WM8350_IRQ_SYS_CHIP_GT115:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_CHIP_GT115_EINT);
+ case WM8350_IRQ_SYS_CHIP_GT140:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_CHIP_GT140_EINT);
+ case WM8350_IRQ_SYS_WDOG_TO:
+ return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+ WM8350_IM_SYS_WDOG_TO_EINT);
+ case WM8350_IRQ_UV_LDO4:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO4_EINT);
+ case WM8350_IRQ_UV_LDO3:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO3_EINT);
+ case WM8350_IRQ_UV_LDO2:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO2_EINT);
+ case WM8350_IRQ_UV_LDO1:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_LDO1_EINT);
+ case WM8350_IRQ_UV_DC6:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC6_EINT);
+ case WM8350_IRQ_UV_DC5:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC5_EINT);
+ case WM8350_IRQ_UV_DC4:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC4_EINT);
+ case WM8350_IRQ_UV_DC3:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC3_EINT);
+ case WM8350_IRQ_UV_DC2:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC2_EINT);
+ case WM8350_IRQ_UV_DC1:
+ return wm8350_clear_bits(wm8350,
+ WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+ WM8350_IM_UV_DC1_EINT);
+ case WM8350_IRQ_OC_LS:
+ return wm8350_clear_bits(wm8350,
+ WM8350_OVER_CURRENT_INT_STATUS_MASK,
+ WM8350_IM_OC_LS_EINT);
+ case WM8350_IRQ_EXT_USB_FB:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_USB_FB_EINT);
+ case WM8350_IRQ_EXT_WALL_FB:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_WALL_FB_EINT);
+ case WM8350_IRQ_EXT_BAT_FB:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_EXT_BAT_FB_EINT);
+ case WM8350_IRQ_CODEC_JCK_DET_L:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_JCK_DET_L_EINT);
+ case WM8350_IRQ_CODEC_JCK_DET_R:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_JCK_DET_R_EINT);
+ case WM8350_IRQ_CODEC_MICSCD:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_MICSCD_EINT);
+ case WM8350_IRQ_CODEC_MICD:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_CODEC_MICD_EINT);
+ case WM8350_IRQ_WKUP_OFF_STATE:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_OFF_STATE_EINT);
+ case WM8350_IRQ_WKUP_HIB_STATE:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_HIB_STATE_EINT);
+ case WM8350_IRQ_WKUP_CONV_FAULT:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_CONV_FAULT_EINT);
+ case WM8350_IRQ_WKUP_WDOG_RST:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_OFF_STATE_EINT);
+ case WM8350_IRQ_WKUP_GP_PWR_ON:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_GP_PWR_ON_EINT);
+ case WM8350_IRQ_WKUP_ONKEY:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_ONKEY_EINT);
+ case WM8350_IRQ_WKUP_GP_WAKEUP:
+ return wm8350_clear_bits(wm8350,
+ WM8350_COMPARATOR_INT_STATUS_MASK,
+ WM8350_IM_WKUP_GP_WAKEUP_EINT);
+ case WM8350_IRQ_GPIO(0):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP0_EINT);
+ case WM8350_IRQ_GPIO(1):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP1_EINT);
+ case WM8350_IRQ_GPIO(2):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP2_EINT);
+ case WM8350_IRQ_GPIO(3):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP3_EINT);
+ case WM8350_IRQ_GPIO(4):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP4_EINT);
+ case WM8350_IRQ_GPIO(5):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP5_EINT);
+ case WM8350_IRQ_GPIO(6):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP6_EINT);
+ case WM8350_IRQ_GPIO(7):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP7_EINT);
+ case WM8350_IRQ_GPIO(8):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP8_EINT);
+ case WM8350_IRQ_GPIO(9):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP9_EINT);
+ case WM8350_IRQ_GPIO(10):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP10_EINT);
+ case WM8350_IRQ_GPIO(11):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP11_EINT);
+ case WM8350_IRQ_GPIO(12):
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_STATUS_MASK,
+ WM8350_IM_GP12_EINT);
+ default:
+ dev_warn(wm8350->dev, "Attempting to unmask unknown IRQ %d\n",
+ irq);
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+
+/*
+ * Cache is always host endian.
+ */
+static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
+{
+ int i, ret = 0;
+ u16 value;
+ const u16 *reg_map;
+
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8350_mode0_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+ case 1:
+ reg_map = wm8350_mode1_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+ case 2:
+ reg_map = wm8350_mode2_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+ case 3:
+ reg_map = wm8350_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev, "Configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
+
+ wm8350->reg_cache =
+ kzalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
+ if (wm8350->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* Read the initial cache state back from the device - this is
+ * a PMIC so the device many not be in a virgin state and we
+ * can't rely on the silicon values.
+ */
+ for (i = 0; i < WM8350_MAX_REGISTER; i++) {
+ /* audio register range */
+ if (wm8350_reg_io_map[i].readable &&
+ (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
+ ret = wm8350->read_dev(wm8350, i, 2, (char *)&value);
+ if (ret < 0) {
+ dev_err(wm8350->dev,
+ "failed to read initial cache value\n");
+ goto out;
+ }
+ value = be16_to_cpu(value);
+ value &= wm8350_reg_io_map[i].readable;
+ wm8350->reg_cache[i] = value;
+ } else
+ wm8350->reg_cache[i] = reg_map[i];
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_create_cache);
+
+/*
+ * Register a client device. This is non-fatal since there is no need to
+ * fail the entire device init due to a single platform device failing.
+ */
+static void wm8350_client_dev_register(struct wm8350 *wm8350,
+ const char *name,
+ struct platform_device **pdev)
+{
+ int ret;
+
+ *pdev = platform_device_alloc(name, -1);
+ if (pdev == NULL) {
+ dev_err(wm8350->dev, "Failed to allocate %s\n", name);
+ return;
+ }
+
+ (*pdev)->dev.parent = wm8350->dev;
+ platform_set_drvdata(*pdev, wm8350);
+ ret = platform_device_add(*pdev);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret);
+ platform_device_put(*pdev);
+ *pdev = NULL;
+ }
+}
+
+int wm8350_device_init(struct wm8350 *wm8350, int irq,
+ struct wm8350_platform_data *pdata)
+{
+ int ret = -EINVAL;
+ u16 id1, id2, mask, mode;
+
+ /* get WM8350 revision and config mode */
+ wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
+ wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+
+ id1 = be16_to_cpu(id1);
+ id2 = be16_to_cpu(id2);
+
+ if (id1 == 0x6143) {
+ switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
+ case WM8350_REV_E:
+ dev_info(wm8350->dev, "Found Rev E device\n");
+ wm8350->rev = WM8350_REV_E;
+ break;
+ case WM8350_REV_F:
+ dev_info(wm8350->dev, "Found Rev F device\n");
+ wm8350->rev = WM8350_REV_F;
+ break;
+ case WM8350_REV_G:
+ dev_info(wm8350->dev, "Found Rev G device\n");
+ wm8350->rev = WM8350_REV_G;
+ break;
+ default:
+ /* For safety we refuse to run on unknown hardware */
+ dev_info(wm8350->dev, "Found unknown rev\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ } else {
+ dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
+ id1);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ mode = id2 & WM8350_CONF_STS_MASK >> 10;
+ mask = id2 & WM8350_CUST_ID_MASK;
+ dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
+
+ ret = wm8350_create_cache(wm8350, mode);
+ if (ret < 0) {
+ printk(KERN_ERR "wm8350: failed to create register cache\n");
+ return ret;
+ }
+
+ if (pdata->init) {
+ ret = pdata->init(wm8350);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Platform init() failed: %d\n",
+ ret);
+ goto err;
+ }
+ }
+
+ mutex_init(&wm8350->irq_mutex);
+ INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
+ if (irq != NO_IRQ) {
+ ret = request_irq(irq, wm8350_irq, 0,
+ "wm8350", wm8350);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to request IRQ: %d\n",
+ ret);
+ goto err;
+ }
+ } else {
+ dev_err(wm8350->dev, "No IRQ configured\n");
+ goto err;
+ }
+ wm8350->chip_irq = irq;
+
+ wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
+
+ wm8350_client_dev_register(wm8350, "wm8350-codec",
+ &(wm8350->codec.pdev));
+ wm8350_client_dev_register(wm8350, "wm8350-gpio",
+ &(wm8350->gpio.pdev));
+ wm8350_client_dev_register(wm8350, "wm8350-power",
+ &(wm8350->power.pdev));
+ wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
+ wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev));
+
+ return 0;
+
+err:
+ kfree(wm8350->reg_cache);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_device_init);
+
+void wm8350_device_exit(struct wm8350 *wm8350)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
+ platform_device_unregister(wm8350->pmic.pdev[i]);
+
+ platform_device_unregister(wm8350->wdt.pdev);
+ platform_device_unregister(wm8350->rtc.pdev);
+ platform_device_unregister(wm8350->power.pdev);
+ platform_device_unregister(wm8350->gpio.pdev);
+ platform_device_unregister(wm8350->codec.pdev);
+
+ free_irq(wm8350->chip_irq, wm8350);
+ flush_work(&wm8350->irq_work);
+ kfree(wm8350->reg_cache);
+}
+EXPORT_SYMBOL_GPL(wm8350_device_exit);
+
+MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-gpio.c b/drivers/mfd/wm8350-gpio.c
new file mode 100644
index 00000000000..ebf99bef392
--- /dev/null
+++ b/drivers/mfd/wm8350-gpio.c
@@ -0,0 +1,222 @@
+/*
+ * wm8350-core.c -- Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+
+static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
+{
+ int ret;
+
+ wm8350_reg_unlock(wm8350);
+ if (dir == WM8350_GPIO_DIR_OUT)
+ ret = wm8350_clear_bits(wm8350,
+ WM8350_GPIO_CONFIGURATION_I_O,
+ 1 << gpio);
+ else
+ ret = wm8350_set_bits(wm8350,
+ WM8350_GPIO_CONFIGURATION_I_O,
+ 1 << gpio);
+ wm8350_reg_lock(wm8350);
+ return ret;
+}
+
+static int gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
+{
+ if (db == WM8350_GPIO_DEBOUNCE_ON)
+ return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
+ 1 << gpio);
+ else
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_DEBOUNCE, 1 << gpio);
+}
+
+static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
+{
+ u16 reg;
+
+ wm8350_reg_unlock(wm8350);
+ switch (gpio) {
+ case 0:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+ & ~WM8350_GP0_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+ reg | ((func & 0xf) << 0));
+ break;
+ case 1:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+ & ~WM8350_GP1_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+ reg | ((func & 0xf) << 4));
+ break;
+ case 2:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+ & ~WM8350_GP2_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+ reg | ((func & 0xf) << 8));
+ break;
+ case 3:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+ & ~WM8350_GP3_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+ reg | ((func & 0xf) << 12));
+ break;
+ case 4:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+ & ~WM8350_GP4_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+ reg | ((func & 0xf) << 0));
+ break;
+ case 5:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+ & ~WM8350_GP5_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+ reg | ((func & 0xf) << 4));
+ break;
+ case 6:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+ & ~WM8350_GP6_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+ reg | ((func & 0xf) << 8));
+ break;
+ case 7:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+ & ~WM8350_GP7_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+ reg | ((func & 0xf) << 12));
+ break;
+ case 8:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+ & ~WM8350_GP8_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+ reg | ((func & 0xf) << 0));
+ break;
+ case 9:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+ & ~WM8350_GP9_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+ reg | ((func & 0xf) << 4));
+ break;
+ case 10:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+ & ~WM8350_GP10_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+ reg | ((func & 0xf) << 8));
+ break;
+ case 11:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+ & ~WM8350_GP11_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+ reg | ((func & 0xf) << 12));
+ break;
+ case 12:
+ reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
+ & ~WM8350_GP12_FN_MASK;
+ wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
+ reg | ((func & 0xf) << 0));
+ break;
+ default:
+ wm8350_reg_lock(wm8350);
+ return -EINVAL;
+ }
+
+ wm8350_reg_lock(wm8350);
+ return 0;
+}
+
+static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
+{
+ if (up)
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_PIN_PULL_UP_CONTROL,
+ 1 << gpio);
+ else
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_PIN_PULL_UP_CONTROL,
+ 1 << gpio);
+}
+
+static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
+{
+ if (down)
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_PULL_DOWN_CONTROL,
+ 1 << gpio);
+ else
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_PULL_DOWN_CONTROL,
+ 1 << gpio);
+}
+
+static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
+{
+ if (pol == WM8350_GPIO_ACTIVE_HIGH)
+ return wm8350_set_bits(wm8350,
+ WM8350_GPIO_PIN_POLARITY_TYPE,
+ 1 << gpio);
+ else
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_PIN_POLARITY_TYPE,
+ 1 << gpio);
+}
+
+static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
+{
+ if (invert == WM8350_GPIO_INVERT_ON)
+ return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
+ else
+ return wm8350_clear_bits(wm8350,
+ WM8350_GPIO_INT_MODE, 1 << gpio);
+}
+
+int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
+ int pol, int pull, int invert, int debounce)
+{
+ /* make sure we never pull up and down at the same time */
+ if (pull == WM8350_GPIO_PULL_NONE) {
+ if (gpio_set_pull_up(wm8350, gpio, 0))
+ goto err;
+ if (gpio_set_pull_down(wm8350, gpio, 0))
+ goto err;
+ } else if (pull == WM8350_GPIO_PULL_UP) {
+ if (gpio_set_pull_down(wm8350, gpio, 0))
+ goto err;
+ if (gpio_set_pull_up(wm8350, gpio, 1))
+ goto err;
+ } else if (pull == WM8350_GPIO_PULL_DOWN) {
+ if (gpio_set_pull_up(wm8350, gpio, 0))
+ goto err;
+ if (gpio_set_pull_down(wm8350, gpio, 1))
+ goto err;
+ }
+
+ if (gpio_set_invert(wm8350, gpio, invert))
+ goto err;
+ if (gpio_set_polarity(wm8350, gpio, pol))
+ goto err;
+ if (gpio_set_debounce(wm8350, gpio, debounce))
+ goto err;
+ if (gpio_set_dir(wm8350, gpio, dir))
+ goto err;
+ return gpio_set_func(wm8350, gpio, func);
+
+err:
+ return -EIO;
+}
+EXPORT_SYMBOL_GPL(wm8350_gpio_config);
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
new file mode 100644
index 00000000000..8dfe21bb3bd
--- /dev/null
+++ b/drivers/mfd/wm8350-i2c.c
@@ -0,0 +1,120 @@
+/*
+ * wm8350-i2c.c -- Generic I2C driver for Wolfson WM8350 PMIC
+ *
+ * This driver defines and configures the WM8350 for the Freescale i.MX32ADS.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ * linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm8350/core.h>
+
+static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg,
+ int bytes, void *dest)
+{
+ int ret;
+
+ ret = i2c_master_send(wm8350->i2c_client, &reg, 1);
+ if (ret < 0)
+ return ret;
+ return i2c_master_recv(wm8350->i2c_client, dest, bytes);
+}
+
+static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
+ int bytes, void *src)
+{
+ /* we add 1 byte for device register */
+ u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+
+ if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
+ return -EINVAL;
+
+ msg[0] = reg;
+ memcpy(&msg[1], src, bytes);
+ return i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+}
+
+static int wm8350_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8350 *wm8350;
+ int ret = 0;
+
+ wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
+ if (wm8350 == NULL) {
+ kfree(i2c);
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(i2c, wm8350);
+ wm8350->dev = &i2c->dev;
+ wm8350->i2c_client = i2c;
+ wm8350->read_dev = wm8350_i2c_read_device;
+ wm8350->write_dev = wm8350_i2c_write_device;
+
+ ret = wm8350_device_init(wm8350, i2c->irq, i2c->dev.platform_data);
+ if (ret < 0)
+ goto err;
+
+ return ret;
+
+err:
+ kfree(wm8350);
+ return ret;
+}
+
+static int wm8350_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
+
+ wm8350_device_exit(wm8350);
+ kfree(wm8350);
+
+ return 0;
+}
+
+static const struct i2c_device_id wm8350_i2c_id[] = {
+ { "wm8350", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
+
+
+static struct i2c_driver wm8350_i2c_driver = {
+ .driver = {
+ .name = "wm8350",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8350_i2c_probe,
+ .remove = wm8350_i2c_remove,
+ .id_table = wm8350_i2c_id,
+};
+
+static int __init wm8350_i2c_init(void)
+{
+ return i2c_add_driver(&wm8350_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(wm8350_i2c_init);
+
+static void __exit wm8350_i2c_exit(void)
+{
+ i2c_del_driver(&wm8350_i2c_driver);
+}
+module_exit(wm8350_i2c_exit);
+
+MODULE_DESCRIPTION("I2C support for the WM8350 AudioPlus PMIC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
new file mode 100644
index 00000000000..974678db22c
--- /dev/null
+++ b/drivers/mfd/wm8350-regmap.c
@@ -0,0 +1,1347 @@
+/*
+ * wm8350-regmap.c -- Wolfson Microelectronics WM8350 register map
+ *
+ * This file splits out the tables describing the defaults and access
+ * status of the WM8350 registers since they are rather large.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * 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/mfd/wm8350/core.h>
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode0_defaults[] = {
+ 0x17FF, /* R0 - Reset/ID */
+ 0x1000, /* R1 - ID */
+ 0x0000, /* R2 */
+ 0x1002, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 - Power Up Interrupt Status */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 - Power Up Interrupt Status Mask */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3B00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - LOUT1 Volume */
+ 0x00E4, /* R105 - ROUT1 Volume */
+ 0x00E4, /* R106 - LOUT2 Volume */
+ 0x02E4, /* R107 - ROUT2 Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 - AIF Test */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x03FC, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0FFC, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFC, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0013, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x0000, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x002D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0000, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0000, /* R186 - DCDC3 Control */
+ 0x0000, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0000, /* R189 - DCDC4 Control */
+ 0x0000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0000, /* R195 - DCDC6 Control */
+ 0x0000, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001B, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 */
+ 0x4000, /* R220 - RAM BIST 1 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 */
+ 0x0000, /* R227 */
+ 0x0000, /* R228 */
+ 0x0000, /* R229 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 */
+ 0x0000, /* R234 */
+ 0x0000, /* R235 */
+ 0x0000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0000, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0000, /* R243 */
+ 0x0000, /* R244 */
+ 0x0000, /* R245 */
+ 0x0000, /* R246 */
+ 0x0000, /* R247 */
+ 0x0000, /* R248 */
+ 0x0000, /* R249 */
+ 0x0000, /* R250 */
+ 0x0000, /* R251 */
+ 0x0000, /* R252 */
+ 0x0000, /* R253 */
+ 0x0000, /* R254 */
+ 0x0000, /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode1_defaults[] = {
+ 0x17FF, /* R0 - Reset/ID */
+ 0x1000, /* R1 - ID */
+ 0x0000, /* R2 */
+ 0x1002, /* R3 - System Control 1 */
+ 0x0014, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 - Power Up Interrupt Status */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 - Power Up Interrupt Status Mask */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3B00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - LOUT1 Volume */
+ 0x00E4, /* R105 - ROUT1 Volume */
+ 0x00E4, /* R106 - LOUT2 Volume */
+ 0x02E4, /* R107 - ROUT2 Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 - AIF Test */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x03FC, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x00FB, /* R134 - GPIO Configuration (i/o) */
+ 0x04FE, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0312, /* R140 - GPIO Function Select 1 */
+ 0x1003, /* R141 - GPIO Function Select 2 */
+ 0x1331, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x002D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x0062, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0026, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0062, /* R189 - DCDC4 Control */
+ 0x0400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x0800, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0006, /* R200 - LDO1 Control */
+ 0x0400, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0006, /* R203 - LDO2 Control */
+ 0x0400, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 */
+ 0x4000, /* R220 - RAM BIST 1 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 */
+ 0x0000, /* R227 */
+ 0x0000, /* R228 */
+ 0x0000, /* R229 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 */
+ 0x0000, /* R234 */
+ 0x0000, /* R235 */
+ 0x0000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0000, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0000, /* R243 */
+ 0x0000, /* R244 */
+ 0x0000, /* R245 */
+ 0x0000, /* R246 */
+ 0x0000, /* R247 */
+ 0x0000, /* R248 */
+ 0x0000, /* R249 */
+ 0x0000, /* R250 */
+ 0x0000, /* R251 */
+ 0x0000, /* R252 */
+ 0x0000, /* R253 */
+ 0x0000, /* R254 */
+ 0x0000, /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode2_defaults[] = {
+ 0x17FF, /* R0 - Reset/ID */
+ 0x1000, /* R1 - ID */
+ 0x0000, /* R2 */
+ 0x1002, /* R3 - System Control 1 */
+ 0x0014, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 - Power Up Interrupt Status */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 - Power Up Interrupt Status Mask */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3B00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - LOUT1 Volume */
+ 0x00E4, /* R105 - ROUT1 Volume */
+ 0x00E4, /* R106 - LOUT2 Volume */
+ 0x02E4, /* R107 - ROUT2 Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 - AIF Test */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x03FC, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x08FB, /* R134 - GPIO Configuration (i/o) */
+ 0x0CFE, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0312, /* R140 - GPIO Function Select 1 */
+ 0x0003, /* R141 - GPIO Function Select 2 */
+ 0x2331, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x002D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x002E, /* R186 - DCDC3 Control */
+ 0x0800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x000E, /* R189 - DCDC4 Control */
+ 0x0800, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x0C00, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001A, /* R200 - LDO1 Control */
+ 0x0800, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0010, /* R203 - LDO2 Control */
+ 0x0800, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x000A, /* R206 - LDO3 Control */
+ 0x0C00, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x0800, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 */
+ 0x4000, /* R220 - RAM BIST 1 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 */
+ 0x0000, /* R227 */
+ 0x0000, /* R228 */
+ 0x0000, /* R229 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 */
+ 0x0000, /* R234 */
+ 0x0000, /* R235 */
+ 0x0000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0000, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0000, /* R243 */
+ 0x0000, /* R244 */
+ 0x0000, /* R245 */
+ 0x0000, /* R246 */
+ 0x0000, /* R247 */
+ 0x0000, /* R248 */
+ 0x0000, /* R249 */
+ 0x0000, /* R250 */
+ 0x0000, /* R251 */
+ 0x0000, /* R252 */
+ 0x0000, /* R253 */
+ 0x0000, /* R254 */
+ 0x0000, /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode3_defaults[] = {
+ 0x17FF, /* R0 - Reset/ID */
+ 0x1000, /* R1 - ID */
+ 0x0000, /* R2 */
+ 0x1000, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 - Power Up Interrupt Status */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 - Power Up Interrupt Status Mask */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3B00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - LOUT1 Volume */
+ 0x00E4, /* R105 - ROUT1 Volume */
+ 0x00E4, /* R106 - LOUT2 Volume */
+ 0x02E4, /* R107 - ROUT2 Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 - AIF Test */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x03FC, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0A7B, /* R134 - GPIO Configuration (i/o) */
+ 0x06FE, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x1312, /* R140 - GPIO Function Select 1 */
+ 0x1030, /* R141 - GPIO Function Select 2 */
+ 0x2231, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x002D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x000E, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0026, /* R189 - DCDC4 Control */
+ 0x0400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x0400, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001C, /* R203 - LDO2 Control */
+ 0x0400, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001C, /* R206 - LDO3 Control */
+ 0x0400, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001F, /* R209 - LDO4 Control */
+ 0x0400, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 */
+ 0x4000, /* R220 - RAM BIST 1 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 */
+ 0x0000, /* R227 */
+ 0x0000, /* R228 */
+ 0x0000, /* R229 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 */
+ 0x0000, /* R234 */
+ 0x0000, /* R235 */
+ 0x0000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0000, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0000, /* R243 */
+ 0x0000, /* R244 */
+ 0x0000, /* R245 */
+ 0x0000, /* R246 */
+ 0x0000, /* R247 */
+ 0x0000, /* R248 */
+ 0x0000, /* R249 */
+ 0x0000, /* R250 */
+ 0x0000, /* R251 */
+ 0x0000, /* R252 */
+ 0x0000, /* R253 */
+ 0x0000, /* R254 */
+ 0x0000, /* R255 */
+};
+#endif
+
+/* The register defaults for the config mode used must be compiled in but
+ * due to the impact on kernel size it is possible to disable
+ */
+#ifndef WM8350_HAVE_CONFIG_MODE
+#warning No WM8350 config modes supported - select at least one of the
+#warning MFD_WM8350_CONFIG_MODE_n options from the board driver.
+#endif
+
+/*
+ * Access masks.
+ */
+
+const struct wm8350_reg_access wm8350_reg_io_map[] = {
+ /* read write volatile */
+ { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */
+ { 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */
+ { 0x0000, 0x0000, 0x0000 }, /* R2 */
+ { 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */
+ { 0xFCF7, 0xFCF7, 0xF800 }, /* R4 - System Control 2 */
+ { 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */
+ { 0xFB0E, 0xFB0E, 0x0000 }, /* R6 - Interface Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R7 */
+ { 0xE537, 0xE537, 0xFFFF }, /* R8 - Power mgmt (1) */
+ { 0x0FF3, 0x0FF3, 0xFFFF }, /* R9 - Power mgmt (2) */
+ { 0x008F, 0x008F, 0xFFFF }, /* R10 - Power mgmt (3) */
+ { 0x6D3C, 0x6D3C, 0xFFFF }, /* R11 - Power mgmt (4) */
+ { 0x1F8F, 0x1F8F, 0xFFFF }, /* R12 - Power mgmt (5) */
+ { 0x8F3F, 0x8F3F, 0xFFFF }, /* R13 - Power mgmt (6) */
+ { 0x0003, 0x0003, 0xFFFF }, /* R14 - Power mgmt (7) */
+ { 0x0000, 0x0000, 0x0000 }, /* R15 */
+ { 0x7F7F, 0x7F7F, 0xFFFF }, /* R16 - RTC Seconds/Minutes */
+ { 0x073F, 0x073F, 0xFFFF }, /* R17 - RTC Hours/Day */
+ { 0x1F3F, 0x1F3F, 0xFFFF }, /* R18 - RTC Date/Month */
+ { 0x3FFF, 0x00FF, 0xFFFF }, /* R19 - RTC Year */
+ { 0x7F7F, 0x7F7F, 0x0000 }, /* R20 - Alarm Seconds/Minutes */
+ { 0x0F3F, 0x0F3F, 0x0000 }, /* R21 - Alarm Hours/Day */
+ { 0x1F3F, 0x1F3F, 0x0000 }, /* R22 - Alarm Date/Month */
+ { 0xEF7F, 0xEA7F, 0xFFFF }, /* R23 - RTC Time Control */
+ { 0x3BFF, 0x0000, 0xFFFF }, /* R24 - System Interrupts */
+ { 0xFEE7, 0x0000, 0xFFFF }, /* R25 - Interrupt Status 1 */
+ { 0x35FF, 0x0000, 0xFFFF }, /* R26 - Interrupt Status 2 */
+ { 0x0F3F, 0x0000, 0xFFFF }, /* R27 - Power Up Interrupt Status */
+ { 0x0F3F, 0x0000, 0xFFFF }, /* R28 - Under Voltage Interrupt status */
+ { 0x8000, 0x0000, 0xFFFF }, /* R29 - Over Current Interrupt status */
+ { 0x1FFF, 0x0000, 0xFFFF }, /* R30 - GPIO Interrupt Status */
+ { 0xEF7F, 0x0000, 0xFFFF }, /* R31 - Comparator Interrupt Status */
+ { 0x3FFF, 0x3FFF, 0x0000 }, /* R32 - System Interrupts Mask */
+ { 0xFEE7, 0xFEE7, 0x0000 }, /* R33 - Interrupt Status 1 Mask */
+ { 0xF5FF, 0xF5FF, 0x0000 }, /* R34 - Interrupt Status 2 Mask */
+ { 0x0F3F, 0x0F3F, 0x0000 }, /* R35 - Power Up Interrupt Status Mask */
+ { 0x0F3F, 0x0F3F, 0x0000 }, /* R36 - Under Voltage Int status Mask */
+ { 0x8000, 0x8000, 0x0000 }, /* R37 - Over Current Int status Mask */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R38 - GPIO Interrupt Status Mask */
+ { 0xEF7F, 0xEF7F, 0x0000 }, /* R39 - Comparator IntStatus Mask */
+ { 0xC9F7, 0xC9F7, 0xFFFF }, /* R40 - Clock Control 1 */
+ { 0x8001, 0x8001, 0x0000 }, /* R41 - Clock Control 2 */
+ { 0xFFF7, 0xFFF7, 0xFFFF }, /* R42 - FLL Control 1 */
+ { 0xFBFF, 0xFBFF, 0x0000 }, /* R43 - FLL Control 2 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R44 - FLL Control 3 */
+ { 0x0033, 0x0033, 0x0000 }, /* R45 - FLL Control 4 */
+ { 0x0000, 0x0000, 0x0000 }, /* R46 */
+ { 0x0000, 0x0000, 0x0000 }, /* R47 */
+ { 0x3033, 0x3033, 0x0000 }, /* R48 - DAC Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R49 */
+ { 0x81FF, 0x81FF, 0xFFFF }, /* R50 - DAC Digital Volume L */
+ { 0x81FF, 0x81FF, 0xFFFF }, /* R51 - DAC Digital Volume R */
+ { 0x0000, 0x0000, 0x0000 }, /* R52 */
+ { 0x0FFF, 0x0FFF, 0xFFFF }, /* R53 - DAC LR Rate */
+ { 0x0017, 0x0017, 0x0000 }, /* R54 - DAC Clock Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R55 */
+ { 0x0000, 0x0000, 0x0000 }, /* R56 */
+ { 0x0000, 0x0000, 0x0000 }, /* R57 */
+ { 0x4000, 0x4000, 0x0000 }, /* R58 - DAC Mute */
+ { 0x7000, 0x7000, 0x0000 }, /* R59 - DAC Mute Volume */
+ { 0x3C00, 0x3C00, 0x0000 }, /* R60 - DAC Side */
+ { 0x0000, 0x0000, 0x0000 }, /* R61 */
+ { 0x0000, 0x0000, 0x0000 }, /* R62 */
+ { 0x0000, 0x0000, 0x0000 }, /* R63 */
+ { 0x8303, 0x8303, 0xFFFF }, /* R64 - ADC Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R65 */
+ { 0x81FF, 0x81FF, 0xFFFF }, /* R66 - ADC Digital Volume L */
+ { 0x81FF, 0x81FF, 0xFFFF }, /* R67 - ADC Digital Volume R */
+ { 0x0FFF, 0x0FFF, 0x0000 }, /* R68 - ADC Divider */
+ { 0x0000, 0x0000, 0x0000 }, /* R69 */
+ { 0x0FFF, 0x0FFF, 0xFFFF }, /* R70 - ADC LR Rate */
+ { 0x0000, 0x0000, 0x0000 }, /* R71 */
+ { 0x0707, 0x0707, 0xFFFF }, /* R72 - Input Control */
+ { 0xC0C0, 0xC0C0, 0xFFFF }, /* R73 - IN3 Input Control */
+ { 0xC09F, 0xC09F, 0xFFFF }, /* R74 - Mic Bias Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R75 */
+ { 0x0F15, 0x0F15, 0xFFFF }, /* R76 - Output Control */
+ { 0xC000, 0xC000, 0xFFFF }, /* R77 - Jack Detect */
+ { 0x03FF, 0x03FF, 0x0000 }, /* R78 - Anti Pop Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R79 */
+ { 0xE1FC, 0xE1FC, 0x8000 }, /* R80 - Left Input Volume */
+ { 0xE1FC, 0xE1FC, 0x8000 }, /* R81 - Right Input Volume */
+ { 0x0000, 0x0000, 0x0000 }, /* R82 */
+ { 0x0000, 0x0000, 0x0000 }, /* R83 */
+ { 0x0000, 0x0000, 0x0000 }, /* R84 */
+ { 0x0000, 0x0000, 0x0000 }, /* R85 */
+ { 0x0000, 0x0000, 0x0000 }, /* R86 */
+ { 0x0000, 0x0000, 0x0000 }, /* R87 */
+ { 0x9807, 0x9807, 0xFFFF }, /* R88 - Left Mixer Control */
+ { 0x980B, 0x980B, 0xFFFF }, /* R89 - Right Mixer Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R90 */
+ { 0x0000, 0x0000, 0x0000 }, /* R91 */
+ { 0x8909, 0x8909, 0xFFFF }, /* R92 - OUT3 Mixer Control */
+ { 0x9E07, 0x9E07, 0xFFFF }, /* R93 - OUT4 Mixer Control */
+ { 0x0000, 0x0000, 0x0000 }, /* R94 */
+ { 0x0000, 0x0000, 0x0000 }, /* R95 */
+ { 0x0EEE, 0x0EEE, 0x0000 }, /* R96 - Output Left Mixer Volume */
+ { 0xE0EE, 0xE0EE, 0x0000 }, /* R97 - Output Right Mixer Volume */
+ { 0x0E0F, 0x0E0F, 0x0000 }, /* R98 - Input Mixer Volume L */
+ { 0xE0E1, 0xE0E1, 0x0000 }, /* R99 - Input Mixer Volume R */
+ { 0x800E, 0x800E, 0x0000 }, /* R100 - Input Mixer Volume */
+ { 0x0000, 0x0000, 0x0000 }, /* R101 */
+ { 0x0000, 0x0000, 0x0000 }, /* R102 */
+ { 0x0000, 0x0000, 0x0000 }, /* R103 */
+ { 0xE1FC, 0xE1FC, 0xFFFF }, /* R104 - LOUT1 Volume */
+ { 0xE1FC, 0xE1FC, 0xFFFF }, /* R105 - ROUT1 Volume */
+ { 0xE1FC, 0xE1FC, 0xFFFF }, /* R106 - LOUT2 Volume */
+ { 0xE7FC, 0xE7FC, 0xFFFF }, /* R107 - ROUT2 Volume */
+ { 0x0000, 0x0000, 0x0000 }, /* R108 */
+ { 0x0000, 0x0000, 0x0000 }, /* R109 */
+ { 0x0000, 0x0000, 0x0000 }, /* R110 */
+ { 0x80E0, 0x80E0, 0xFFFF }, /* R111 - BEEP Volume */
+ { 0xBF00, 0xBF00, 0x0000 }, /* R112 - AI Formating */
+ { 0x00F1, 0x00F1, 0x0000 }, /* R113 - ADC DAC COMP */
+ { 0x00F8, 0x00F8, 0x0000 }, /* R114 - AI ADC Control */
+ { 0x40FB, 0x40FB, 0x0000 }, /* R115 - AI DAC Control */
+ { 0x7C30, 0x7C30, 0x0000 }, /* R116 - AIF Test */
+ { 0x0000, 0x0000, 0x0000 }, /* R117 */
+ { 0x0000, 0x0000, 0x0000 }, /* R118 */
+ { 0x0000, 0x0000, 0x0000 }, /* R119 */
+ { 0x0000, 0x0000, 0x0000 }, /* R120 */
+ { 0x0000, 0x0000, 0x0000 }, /* R121 */
+ { 0x0000, 0x0000, 0x0000 }, /* R122 */
+ { 0x0000, 0x0000, 0x0000 }, /* R123 */
+ { 0x0000, 0x0000, 0x0000 }, /* R124 */
+ { 0x0000, 0x0000, 0x0000 }, /* R125 */
+ { 0x0000, 0x0000, 0x0000 }, /* R126 */
+ { 0x0000, 0x0000, 0x0000 }, /* R127 */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R128 - GPIO Debounce */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R129 - GPIO Pin pull up Control */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R130 - GPIO Pull down Control */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R131 - GPIO Interrupt Mode */
+ { 0x0000, 0x0000, 0x0000 }, /* R132 */
+ { 0x00C0, 0x00C0, 0x0000 }, /* R133 - GPIO Control */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R134 - GPIO Configuration (i/o) */
+ { 0x1FFF, 0x1FFF, 0x0000 }, /* R135 - GPIO Pin Polarity / Type */
+ { 0x0000, 0x0000, 0x0000 }, /* R136 */
+ { 0x0000, 0x0000, 0x0000 }, /* R137 */
+ { 0x0000, 0x0000, 0x0000 }, /* R138 */
+ { 0x0000, 0x0000, 0x0000 }, /* R139 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R140 - GPIO Function Select 1 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R141 - GPIO Function Select 2 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R142 - GPIO Function Select 3 */
+ { 0x000F, 0x000F, 0x0000 }, /* R143 - GPIO Function Select 4 */
+ { 0xF0FF, 0xF0FF, 0xA000 }, /* R144 - Digitiser Control (1) */
+ { 0x3707, 0x3707, 0x0000 }, /* R145 - Digitiser Control (2) */
+ { 0x0000, 0x0000, 0x0000 }, /* R146 */
+ { 0x0000, 0x0000, 0x0000 }, /* R147 */
+ { 0x0000, 0x0000, 0x0000 }, /* R148 */
+ { 0x0000, 0x0000, 0x0000 }, /* R149 */
+ { 0x0000, 0x0000, 0x0000 }, /* R150 */
+ { 0x0000, 0x0000, 0x0000 }, /* R151 */
+ { 0x7FFF, 0x7000, 0xFFFF }, /* R152 - AUX1 Readback */
+ { 0x7FFF, 0x7000, 0xFFFF }, /* R153 - AUX2 Readback */
+ { 0x7FFF, 0x7000, 0xFFFF }, /* R154 - AUX3 Readback */
+ { 0x7FFF, 0x7000, 0xFFFF }, /* R155 - AUX4 Readback */
+ { 0x0FFF, 0x0000, 0xFFFF }, /* R156 - USB Voltage Readback */
+ { 0x0FFF, 0x0000, 0xFFFF }, /* R157 - LINE Voltage Readback */
+ { 0x0FFF, 0x0000, 0xFFFF }, /* R158 - BATT Voltage Readback */
+ { 0x0FFF, 0x0000, 0xFFFF }, /* R159 - Chip Temp Readback */
+ { 0x0000, 0x0000, 0x0000 }, /* R160 */
+ { 0x0000, 0x0000, 0x0000 }, /* R161 */
+ { 0x0000, 0x0000, 0x0000 }, /* R162 */
+ { 0x000F, 0x000F, 0x0000 }, /* R163 - Generic Comparator Control */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R164 - Generic comparator 1 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R165 - Generic comparator 2 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R166 - Generic comparator 3 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R167 - Generic comparator 4 */
+ { 0xBFFF, 0xBFFF, 0x8000 }, /* R168 - Battery Charger Control 1 */
+ { 0xFFFF, 0x4FFF, 0xB000 }, /* R169 - Battery Charger Control 2 */
+ { 0x007F, 0x007F, 0x0000 }, /* R170 - Battery Charger Control 3 */
+ { 0x0000, 0x0000, 0x0000 }, /* R171 */
+ { 0x903F, 0x903F, 0xFFFF }, /* R172 - Current Sink Driver A */
+ { 0xE333, 0xE333, 0xFFFF }, /* R173 - CSA Flash control */
+ { 0x903F, 0x903F, 0xFFFF }, /* R174 - Current Sink Driver B */
+ { 0xE333, 0xE333, 0xFFFF }, /* R175 - CSB Flash control */
+ { 0x8F3F, 0x8F3F, 0xFFFF }, /* R176 - DCDC/LDO requested */
+ { 0x332D, 0x332D, 0x0000 }, /* R177 - DCDC Active options */
+ { 0x002D, 0x002D, 0x0000 }, /* R178 - DCDC Sleep options */
+ { 0x5177, 0x5177, 0x8000 }, /* R179 - Power-check comparator */
+ { 0x047F, 0x047F, 0x0000 }, /* R180 - DCDC1 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R181 - DCDC1 Timeouts */
+ { 0x737F, 0x737F, 0x0000 }, /* R182 - DCDC1 Low Power */
+ { 0x535B, 0x535B, 0x0000 }, /* R183 - DCDC2 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R184 - DCDC2 Timeouts */
+ { 0x0000, 0x0000, 0x0000 }, /* R185 */
+ { 0x047F, 0x047F, 0x0000 }, /* R186 - DCDC3 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R187 - DCDC3 Timeouts */
+ { 0x737F, 0x737F, 0x0000 }, /* R188 - DCDC3 Low Power */
+ { 0x047F, 0x047F, 0x0000 }, /* R189 - DCDC4 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R190 - DCDC4 Timeouts */
+ { 0x737F, 0x737F, 0x0000 }, /* R191 - DCDC4 Low Power */
+ { 0x535B, 0x535B, 0x0000 }, /* R192 - DCDC5 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R193 - DCDC5 Timeouts */
+ { 0x0000, 0x0000, 0x0000 }, /* R194 */
+ { 0x047F, 0x047F, 0x0000 }, /* R195 - DCDC6 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R196 - DCDC6 Timeouts */
+ { 0x737F, 0x737F, 0x0000 }, /* R197 - DCDC6 Low Power */
+ { 0x0000, 0x0000, 0x0000 }, /* R198 */
+ { 0xFFD3, 0xFFD3, 0x0000 }, /* R199 - Limit Switch Control */
+ { 0x441F, 0x441F, 0x0000 }, /* R200 - LDO1 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R201 - LDO1 Timeouts */
+ { 0x331F, 0x331F, 0x0000 }, /* R202 - LDO1 Low Power */
+ { 0x441F, 0x441F, 0x0000 }, /* R203 - LDO2 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R204 - LDO2 Timeouts */
+ { 0x331F, 0x331F, 0x0000 }, /* R205 - LDO2 Low Power */
+ { 0x441F, 0x441F, 0x0000 }, /* R206 - LDO3 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R207 - LDO3 Timeouts */
+ { 0x331F, 0x331F, 0x0000 }, /* R208 - LDO3 Low Power */
+ { 0x441F, 0x441F, 0x0000 }, /* R209 - LDO4 Control */
+ { 0xFFC0, 0xFFC0, 0x0000 }, /* R210 - LDO4 Timeouts */
+ { 0x331F, 0x331F, 0x0000 }, /* R211 - LDO4 Low Power */
+ { 0x0000, 0x0000, 0x0000 }, /* R212 */
+ { 0x0000, 0x0000, 0x0000 }, /* R213 */
+ { 0x0000, 0x0000, 0x0000 }, /* R214 */
+ { 0x8F3F, 0x8F3F, 0x0000 }, /* R215 - VCC_FAULT Masks */
+ { 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */
+ { 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */
+ { 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */
+ { 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */
+ { 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */
+ { 0x0000, 0x0000, 0x0000 }, /* R221 */
+ { 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */
+ { 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */
+ { 0x0000, 0x0000, 0x0000 }, /* R224 */
+ { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
+ { 0x0000, 0x0000, 0x0000 }, /* R226 */
+ { 0x0000, 0x0000, 0xFFFF }, /* R227 */
+ { 0x0000, 0x0000, 0x0000 }, /* R228 */
+ { 0x0000, 0x0000, 0x0000 }, /* R229 */
+ { 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
+ { 0xFFFF, 0x1FFF, 0xFFFF }, /* R231 */
+ { 0xFFFF, 0x1FFF, 0xFFFF }, /* R232 */
+ { 0xFFFF, 0x1FFF, 0xFFFF }, /* R233 */
+ { 0x0000, 0x0000, 0x0000 }, /* R234 */
+ { 0x0000, 0x0000, 0x0000 }, /* R235 */
+ { 0x0000, 0x0000, 0x0000 }, /* R236 */
+ { 0x0000, 0x0000, 0x0000 }, /* R237 */
+ { 0x0000, 0x0000, 0x0000 }, /* R238 */
+ { 0x0000, 0x0000, 0x0000 }, /* R239 */
+ { 0x0000, 0x0000, 0x0000 }, /* R240 */
+ { 0x0000, 0x0000, 0x0000 }, /* R241 */
+ { 0x0000, 0x0000, 0x0000 }, /* R242 */
+ { 0x0000, 0x0000, 0x0000 }, /* R243 */
+ { 0x0000, 0x0000, 0x0000 }, /* R244 */
+ { 0x0000, 0x0000, 0x0000 }, /* R245 */
+ { 0x0000, 0x0000, 0x0000 }, /* R246 */
+ { 0x0000, 0x0000, 0x0000 }, /* R247 */
+ { 0xFFFF, 0x0010, 0xFFFF }, /* R248 */
+ { 0x0000, 0x0000, 0x0000 }, /* R249 */
+ { 0xFFFF, 0x0010, 0xFFFF }, /* R250 */
+ { 0xFFFF, 0x0010, 0xFFFF }, /* R251 */
+ { 0x0000, 0x0000, 0x0000 }, /* R252 */
+ { 0xFFFF, 0x0010, 0xFFFF }, /* R253 */
+ { 0x0000, 0x0000, 0x0000 }, /* R254 */
+ { 0x0000, 0x0000, 0x0000 }, /* R255 */
+};
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
new file mode 100644
index 00000000000..6a0cedb5bb8
--- /dev/null
+++ b/drivers/mfd/wm8400-core.c
@@ -0,0 +1,455 @@
+/*
+ * Core driver for WM8400.
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/wm8400-private.h>
+#include <linux/mfd/wm8400-audio.h>
+
+static struct {
+ u16 readable; /* Mask of readable bits */
+ u16 writable; /* Mask of writable bits */
+ u16 vol; /* Mask of volatile bits */
+ int is_codec; /* Register controlled by codec reset */
+ u16 default_val; /* Value on reset */
+} reg_data[] = {
+ { 0xFFFF, 0xFFFF, 0x0000, 0, 0x6172 }, /* R0 */
+ { 0x7000, 0x0000, 0x8000, 0, 0x0000 }, /* R1 */
+ { 0xFF17, 0xFF17, 0x0000, 0, 0x0000 }, /* R2 */
+ { 0xEBF3, 0xEBF3, 0x0000, 1, 0x6000 }, /* R3 */
+ { 0x3CF3, 0x3CF3, 0x0000, 1, 0x0000 }, /* R4 */
+ { 0xF1F8, 0xF1F8, 0x0000, 1, 0x4050 }, /* R5 */
+ { 0xFC1F, 0xFC1F, 0x0000, 1, 0x4000 }, /* R6 */
+ { 0xDFDE, 0xDFDE, 0x0000, 1, 0x01C8 }, /* R7 */
+ { 0xFCFC, 0xFCFC, 0x0000, 1, 0x0000 }, /* R8 */
+ { 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R9 */
+ { 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R10 */
+ { 0x27F7, 0x27F7, 0x0000, 1, 0x0004 }, /* R11 */
+ { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R12 */
+ { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R13 */
+ { 0x1FEF, 0x1FEF, 0x0000, 1, 0x0000 }, /* R14 */
+ { 0x0163, 0x0163, 0x0000, 1, 0x0100 }, /* R15 */
+ { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R16 */
+ { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R17 */
+ { 0x1FFF, 0x0FFF, 0x0000, 1, 0x0000 }, /* R18 */
+ { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1000 }, /* R19 */
+ { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R20 */
+ { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R21 */
+ { 0x0FDD, 0x0FDD, 0x0000, 1, 0x8000 }, /* R22 */
+ { 0x1FFF, 0x1FFF, 0x0000, 1, 0x0800 }, /* R23 */
+ { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R24 */
+ { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R25 */
+ { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R26 */
+ { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R27 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R28 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R29 */
+ { 0x0000, 0x0077, 0x0000, 1, 0x0066 }, /* R30 */
+ { 0x0000, 0x0033, 0x0000, 1, 0x0022 }, /* R31 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R32 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R33 */
+ { 0x0000, 0x0003, 0x0000, 1, 0x0003 }, /* R34 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0003 }, /* R35 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R36 */
+ { 0x0000, 0x003F, 0x0000, 1, 0x0100 }, /* R37 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R38 */
+ { 0x0000, 0x000F, 0x0000, 0, 0x0000 }, /* R39 */
+ { 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R40 */
+ { 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R41 */
+ { 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R42 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R43 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R44 */
+ { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R45 */
+ { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R46 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R47 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R48 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R49 */
+ { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R50 */
+ { 0x0000, 0x01B3, 0x0000, 1, 0x0180 }, /* R51 */
+ { 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R52 */
+ { 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R53 */
+ { 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R54 */
+ { 0x0000, 0x0001, 0x0000, 1, 0x0000 }, /* R55 */
+ { 0x0000, 0x003F, 0x0000, 1, 0x0000 }, /* R56 */
+ { 0x0000, 0x004F, 0x0000, 1, 0x0000 }, /* R57 */
+ { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R58 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R59 */
+ { 0x1FFF, 0x1FFF, 0x0000, 1, 0x0000 }, /* R60 */
+ { 0xFFFF, 0xFFFF, 0x0000, 1, 0x0000 }, /* R61 */
+ { 0x03FF, 0x03FF, 0x0000, 1, 0x0000 }, /* R62 */
+ { 0x007F, 0x007F, 0x0000, 1, 0x0000 }, /* R63 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R64 */
+ { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R65 */
+ { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R66 */
+ { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R67 */
+ { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R68 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R69 */
+ { 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R70 */
+ { 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R71 */
+ { 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R72 */
+ { 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R73 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R74 */
+ { 0x000E, 0x000E, 0x0000, 0, 0x0008 }, /* R75 */
+ { 0xE00F, 0xE00F, 0x0000, 0, 0x0000 }, /* R76 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R77 */
+ { 0x03C0, 0x03C0, 0x0000, 0, 0x02C0 }, /* R78 */
+ { 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R79 */
+ { 0xFFFF, 0xFFFF, 0x0000, 0, 0x0000 }, /* R80 */
+ { 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R81 */
+ { 0x2BFF, 0x0000, 0xffff, 0, 0x0000 }, /* R82 */
+ { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R83 */
+ { 0x80FF, 0x80FF, 0x0000, 0, 0x00ff }, /* R84 */
+};
+
+static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
+{
+ int i, ret = 0;
+
+ BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+ /* If there are any volatile reads then read back the entire block */
+ for (i = reg; i < reg + num_regs; i++)
+ if (reg_data[i].vol) {
+ ret = wm8400->read_dev(wm8400->io_data, reg,
+ num_regs, dest);
+ if (ret != 0)
+ return ret;
+ for (i = 0; i < num_regs; i++)
+ dest[i] = be16_to_cpu(dest[i]);
+
+ return 0;
+ }
+
+ /* Otherwise use the cache */
+ memcpy(dest, &wm8400->reg_cache[reg], num_regs * sizeof(u16));
+
+ return 0;
+}
+
+static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
+ u16 *src)
+{
+ int ret, i;
+
+ BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+ for (i = 0; i < num_regs; i++) {
+ BUG_ON(!reg_data[reg + i].writable);
+ wm8400->reg_cache[reg + i] = src[i];
+ src[i] = cpu_to_be16(src[i]);
+ }
+
+ /* Do the actual I/O */
+ ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src);
+ if (ret != 0)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * wm8400_reg_read - Single register read
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg: Register to read
+ *
+ * @return Read value
+ */
+u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg)
+{
+ u16 val;
+
+ mutex_lock(&wm8400->io_lock);
+
+ wm8400_read(wm8400, reg, 1, &val);
+
+ mutex_unlock(&wm8400->io_lock);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(wm8400_reg_read);
+
+int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data)
+{
+ int ret;
+
+ mutex_lock(&wm8400->io_lock);
+
+ ret = wm8400_read(wm8400, reg, count, data);
+
+ mutex_unlock(&wm8400->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_block_read);
+
+/**
+ * wm8400_set_bits - Bitmask write
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg: Register to access
+ * @mask: Mask of bits to change
+ * @val: Value to set for masked bits
+ */
+int wm8400_set_bits(struct wm8400 *wm8400, u8 reg, u16 mask, u16 val)
+{
+ u16 tmp;
+ int ret;
+
+ mutex_lock(&wm8400->io_lock);
+
+ ret = wm8400_read(wm8400, reg, 1, &tmp);
+ tmp = (tmp & ~mask) | val;
+ if (ret == 0)
+ ret = wm8400_write(wm8400, reg, 1, &tmp);
+
+ mutex_unlock(&wm8400->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_set_bits);
+
+/**
+ * wm8400_reset_codec_reg_cache - Reset cached codec registers to
+ * their default values.
+ */
+void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
+{
+ int i;
+
+ mutex_lock(&wm8400->io_lock);
+
+ /* Reset all codec registers to their initial value */
+ for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+ if (reg_data[i].is_codec)
+ wm8400->reg_cache[i] = reg_data[i].default_val;
+
+ mutex_unlock(&wm8400->io_lock);
+}
+EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
+
+/*
+ * wm8400_init - Generic initialisation
+ *
+ * The WM8400 can be configured as either an I2C or SPI device. Probe
+ * functions for each bus set up the accessors then call into this to
+ * set up the device itself.
+ */
+static int wm8400_init(struct wm8400 *wm8400,
+ struct wm8400_platform_data *pdata)
+{
+ u16 reg;
+ int ret, i;
+
+ mutex_init(&wm8400->io_lock);
+
+ wm8400->dev->driver_data = wm8400;
+
+ /* Check that this is actually a WM8400 */
+ ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
+ if (ret != 0) {
+ dev_err(wm8400->dev, "Chip ID register read failed\n");
+ return -EIO;
+ }
+ if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) {
+ dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
+ be16_to_cpu(reg));
+ return -ENODEV;
+ }
+
+ /* We don't know what state the hardware is in and since this
+ * is a PMIC we can't reset it safely so initialise the register
+ * cache from the hardware.
+ */
+ ret = wm8400->read_dev(wm8400->io_data, 0,
+ ARRAY_SIZE(wm8400->reg_cache),
+ wm8400->reg_cache);
+ if (ret != 0) {
+ dev_err(wm8400->dev, "Register cache read failed\n");
+ return -EIO;
+ }
+ for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+ wm8400->reg_cache[i] = be16_to_cpu(wm8400->reg_cache[i]);
+
+ /* If the codec is in reset use hard coded values */
+ if (!(wm8400->reg_cache[WM8400_POWER_MANAGEMENT_1] & WM8400_CODEC_ENA))
+ for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+ if (reg_data[i].is_codec)
+ wm8400->reg_cache[i] = reg_data[i].default_val;
+
+ ret = wm8400_read(wm8400, WM8400_ID, 1, &reg);
+ if (ret != 0) {
+ dev_err(wm8400->dev, "ID register read failed: %d\n", ret);
+ return ret;
+ }
+ reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
+ dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
+
+ if (pdata && pdata->platform_init) {
+ ret = pdata->platform_init(wm8400->dev);
+ if (ret != 0)
+ dev_err(wm8400->dev, "Platform init failed: %d\n",
+ ret);
+ } else
+ dev_warn(wm8400->dev, "No platform initialisation supplied\n");
+
+ return ret;
+}
+
+static void wm8400_release(struct wm8400 *wm8400)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++)
+ if (wm8400->regulators[i].name)
+ platform_device_unregister(&wm8400->regulators[i]);
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest)
+{
+ struct i2c_client *i2c = io_data;
+ struct i2c_msg xfer[2];
+ int ret;
+
+ /* Write register */
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = &reg;
+
+ /* Read data */
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = count * sizeof(u16);
+ xfer[1].buf = (u8 *)dest;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+
+ return ret;
+}
+
+static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src)
+{
+ struct i2c_client *i2c = io_data;
+ u8 *msg;
+ int ret;
+
+ /* We add 1 byte for device register - ideally I2C would gather. */
+ msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL);
+ if (msg == NULL)
+ return -ENOMEM;
+
+ msg[0] = reg;
+ memcpy(&msg[1], src, count * sizeof(u16));
+
+ ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1);
+
+ if (ret == (count * 2) + 1)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+
+ kfree(msg);
+
+ return ret;
+}
+
+static int wm8400_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8400 *wm8400;
+ int ret;
+
+ wm8400 = kzalloc(sizeof(struct wm8400), GFP_KERNEL);
+ if (wm8400 == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ wm8400->io_data = i2c;
+ wm8400->read_dev = wm8400_i2c_read;
+ wm8400->write_dev = wm8400_i2c_write;
+ wm8400->dev = &i2c->dev;
+ i2c_set_clientdata(i2c, wm8400);
+
+ ret = wm8400_init(wm8400, i2c->dev.platform_data);
+ if (ret != 0)
+ goto struct_err;
+
+ return 0;
+
+struct_err:
+ i2c_set_clientdata(i2c, NULL);
+ kfree(wm8400);
+err:
+ return ret;
+}
+
+static int wm8400_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
+
+ wm8400_release(wm8400);
+ i2c_set_clientdata(i2c, NULL);
+ kfree(wm8400);
+
+ return 0;
+}
+
+static const struct i2c_device_id wm8400_i2c_id[] = {
+ { "wm8400", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8400_i2c_id);
+
+static struct i2c_driver wm8400_i2c_driver = {
+ .driver = {
+ .name = "WM8400",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8400_i2c_probe,
+ .remove = wm8400_i2c_remove,
+ .id_table = wm8400_i2c_id,
+};
+#endif
+
+static int __init wm8400_module_init(void)
+{
+ int ret = -ENODEV;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8400_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register I2C driver: %d\n", ret);
+#endif
+
+ return ret;
+}
+module_init(wm8400_module_init);
+
+static void __exit wm8400_module_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8400_i2c_driver);
+#endif
+}
+module_exit(wm8400_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a726f3b01a6..efd3aa08b88 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -15,7 +15,7 @@ if MISC_DEVICES
config ATMEL_PWM
tristate "Atmel AT32/AT91 PWM support"
- depends on AVR32 || ARCH_AT91
+ depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
help
This option enables device driver support for the PWM channels
on certain Atmel prcoessors. Pulse Width Modulation is used for
@@ -409,6 +409,7 @@ config EEEPC_LAPTOP
depends on BACKLIGHT_CLASS_DEVICE
depends on HWMON
depends on EXPERIMENTAL
+ depends on RFKILL
---help---
This driver supports the Fn-Fx keys on Eee PC laptops.
It also adds the ability to switch camera/wlan on/off.
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index c6c77a505ec..d8b0d326e45 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -1189,7 +1189,7 @@ static int create_debugfs(void)
return 0;
error_debugfs:
- remove_debugfs();
+ remove_debugfs();
return -ENOMEM;
}
@@ -1272,6 +1272,7 @@ error_platform_register:
static void __exit acer_wmi_exit(void)
{
remove_sysfs(acer_platform_device);
+ remove_debugfs();
platform_device_del(acer_platform_device);
platform_driver_unregister(&acer_platform_driver);
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index facdb9893c8..1ee8501e90f 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -450,12 +450,14 @@ static int eeepc_get_fan_pwm(void)
int value = 0;
read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
+ value = value * 255 / 100;
return (value);
}
static void eeepc_set_fan_pwm(int value)
{
- value = SENSORS_LIMIT(value, 0, 100);
+ value = SENSORS_LIMIT(value, 0, 255);
+ value = value * 100 / 255;
ec_write(EEEPC_EC_SC02, value);
}
@@ -520,15 +522,23 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
-EEEPC_CREATE_SENSOR_ATTR(fan1_pwm, S_IRUGO | S_IWUSR,
+EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
eeepc_get_fan_pwm, eeepc_set_fan_pwm);
EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "eeepc\n");
+}
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
static struct attribute *hwmon_attributes[] = {
- &sensor_dev_attr_fan1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_name.dev_attr.attr,
NULL
};
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 7a1ef6c262d..3e56203e494 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -463,6 +463,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
},
.callback = dmi_check_cb_s6410},
+ {
+ .ident = "FUJITSU LifeBook P8010",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
+ },
+ .callback = dmi_check_cb_s6410},
{}
};
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c
index 1dbcbcb323a..5dabfb69ee5 100644
--- a/drivers/misc/hp-wmi.c
+++ b/drivers/misc/hp-wmi.c
@@ -49,6 +49,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
#define HPWMI_ALS_QUERY 0x3
#define HPWMI_DOCK_QUERY 0x4
#define HPWMI_WIRELESS_QUERY 0x5
+#define HPWMI_HOTKEY_QUERY 0xc
static int __init hp_wmi_bios_setup(struct platform_device *device);
static int __exit hp_wmi_bios_remove(struct platform_device *device);
@@ -69,7 +70,7 @@ struct bios_return {
struct key_entry {
char type; /* See KE_* below */
- u8 code;
+ u16 code;
u16 keycode;
};
@@ -79,7 +80,9 @@ static struct key_entry hp_wmi_keymap[] = {
{KE_SW, 0x01, SW_DOCK},
{KE_KEY, 0x02, KEY_BRIGHTNESSUP},
{KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
- {KE_KEY, 0x04, KEY_HELP},
+ {KE_KEY, 0x20e6, KEY_PROG1},
+ {KE_KEY, 0x2142, KEY_MEDIA},
+ {KE_KEY, 0x231b, KEY_HELP},
{KE_END, 0}
};
@@ -177,9 +180,9 @@ static int hp_wmi_wifi_state(void)
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
if (wireless & 0x100)
- return 1;
+ return RFKILL_STATE_UNBLOCKED;
else
- return 0;
+ return RFKILL_STATE_SOFT_BLOCKED;
}
static int hp_wmi_bluetooth_state(void)
@@ -187,9 +190,9 @@ static int hp_wmi_bluetooth_state(void)
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
if (wireless & 0x10000)
- return 1;
+ return RFKILL_STATE_UNBLOCKED;
else
- return 0;
+ return RFKILL_STATE_SOFT_BLOCKED;
}
static int hp_wmi_wwan_state(void)
@@ -197,9 +200,9 @@ static int hp_wmi_wwan_state(void)
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
if (wireless & 0x1000000)
- return 1;
+ return RFKILL_STATE_UNBLOCKED;
else
- return 0;
+ return RFKILL_STATE_SOFT_BLOCKED;
}
static ssize_t show_display(struct device *dev, struct device_attribute *attr,
@@ -306,7 +309,7 @@ static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
return -EINVAL;
}
-void hp_wmi_notify(u32 value, void *context)
+static void hp_wmi_notify(u32 value, void *context)
{
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
static struct key_entry *key;
@@ -318,6 +321,9 @@ void hp_wmi_notify(u32 value, void *context)
if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
int eventcode = *((u8 *) obj->buffer.pointer);
+ if (eventcode == 0x4)
+ eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
+ 0);
key = hp_wmi_get_entry_by_scancode(eventcode);
if (key) {
switch (key->type) {
@@ -338,12 +344,14 @@ void hp_wmi_notify(u32 value, void *context)
}
} else if (eventcode == 0x5) {
if (wifi_rfkill)
- wifi_rfkill->state = hp_wmi_wifi_state();
+ rfkill_force_state(wifi_rfkill,
+ hp_wmi_wifi_state());
if (bluetooth_rfkill)
- bluetooth_rfkill->state =
- hp_wmi_bluetooth_state();
+ rfkill_force_state(bluetooth_rfkill,
+ hp_wmi_bluetooth_state());
if (wwan_rfkill)
- wwan_rfkill->state = hp_wmi_wwan_state();
+ rfkill_force_state(wwan_rfkill,
+ hp_wmi_wwan_state());
} else
printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
eventcode);
@@ -398,6 +406,7 @@ static void cleanup_sysfs(struct platform_device *device)
static int __init hp_wmi_bios_setup(struct platform_device *device)
{
int err;
+ int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
err = device_create_file(&device->dev, &dev_attr_display);
if (err)
@@ -412,28 +421,33 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
if (err)
goto add_sysfs_error;
- wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
- wifi_rfkill->name = "hp-wifi";
- wifi_rfkill->state = hp_wmi_wifi_state();
- wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
- wifi_rfkill->user_claim_unsupported = 1;
-
- bluetooth_rfkill = rfkill_allocate(&device->dev,
- RFKILL_TYPE_BLUETOOTH);
- bluetooth_rfkill->name = "hp-bluetooth";
- bluetooth_rfkill->state = hp_wmi_bluetooth_state();
- bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
- bluetooth_rfkill->user_claim_unsupported = 1;
-
- wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
- wwan_rfkill->name = "hp-wwan";
- wwan_rfkill->state = hp_wmi_wwan_state();
- wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
- wwan_rfkill->user_claim_unsupported = 1;
-
- rfkill_register(wifi_rfkill);
- rfkill_register(bluetooth_rfkill);
- rfkill_register(wwan_rfkill);
+ if (wireless & 0x1) {
+ wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
+ wifi_rfkill->name = "hp-wifi";
+ wifi_rfkill->state = hp_wmi_wifi_state();
+ wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
+ wifi_rfkill->user_claim_unsupported = 1;
+ rfkill_register(wifi_rfkill);
+ }
+
+ if (wireless & 0x2) {
+ bluetooth_rfkill = rfkill_allocate(&device->dev,
+ RFKILL_TYPE_BLUETOOTH);
+ bluetooth_rfkill->name = "hp-bluetooth";
+ bluetooth_rfkill->state = hp_wmi_bluetooth_state();
+ bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
+ bluetooth_rfkill->user_claim_unsupported = 1;
+ rfkill_register(bluetooth_rfkill);
+ }
+
+ if (wireless & 0x4) {
+ wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
+ wwan_rfkill->name = "hp-wwan";
+ wwan_rfkill->state = hp_wmi_wwan_state();
+ wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
+ wwan_rfkill->user_claim_unsupported = 1;
+ rfkill_register(wwan_rfkill);
+ }
return 0;
add_sysfs_error:
@@ -445,9 +459,12 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
{
cleanup_sysfs(device);
- rfkill_unregister(wifi_rfkill);
- rfkill_unregister(bluetooth_rfkill);
- rfkill_unregister(wwan_rfkill);
+ if (wifi_rfkill)
+ rfkill_unregister(wifi_rfkill);
+ if (bluetooth_rfkill)
+ rfkill_unregister(bluetooth_rfkill);
+ if (wwan_rfkill)
+ rfkill_unregister(wwan_rfkill);
return 0;
}
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index daf585689ce..abdebe34738 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -399,9 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
goto err_irq;
}
- if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
- MKDEV(phantom_major, minor),
- NULL, "phantom%u", minor)))
+ if (IS_ERR(device_create(phantom_class, &pdev->dev,
+ MKDEV(phantom_major, minor), NULL,
+ "phantom%u", minor)))
dev_err(&pdev->dev, "can't create device\n");
pci_set_drvdata(pdev, pht);
diff --git a/drivers/misc/sgi-gru/gru.h b/drivers/misc/sgi-gru/gru.h
index 40df7cb3f0a..f93f03a9e6e 100644
--- a/drivers/misc/sgi-gru/gru.h
+++ b/drivers/misc/sgi-gru/gru.h
@@ -30,9 +30,9 @@
/*
* Size used to map GRU GSeg
*/
-#if defined CONFIG_IA64
+#if defined(CONFIG_IA64)
#define GRU_GSEG_PAGESIZE (256 * 1024UL)
-#elif defined CONFIG_X86_64
+#elif defined(CONFIG_X86_64)
#define GRU_GSEG_PAGESIZE (256 * 1024UL) /* ZZZ 2MB ??? */
#else
#error "Unsupported architecture"
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h
index 0dc36225c7c..48762e7b98b 100644
--- a/drivers/misc/sgi-gru/gru_instructions.h
+++ b/drivers/misc/sgi-gru/gru_instructions.h
@@ -26,7 +26,7 @@
* Architecture dependent functions
*/
-#if defined CONFIG_IA64
+#if defined(CONFIG_IA64)
#include <linux/compiler.h>
#include <asm/intrinsics.h>
#define __flush_cache(p) ia64_fc(p)
@@ -36,7 +36,7 @@
barrier(); \
*((volatile int *)(p)) = v; /* force st.rel */ \
} while (0)
-#elif defined CONFIG_X86_64
+#elif defined(CONFIG_X86_64)
#define __flush_cache(p) clflush(p)
#define gru_ordered_store_int(p,v) \
do { \
@@ -299,6 +299,7 @@ static inline void gru_flush_cache(void *p)
static inline void gru_start_instruction(struct gru_instruction *ins, int op32)
{
gru_ordered_store_int(ins, op32);
+ gru_flush_cache(ins);
}
@@ -604,8 +605,9 @@ static inline int gru_get_cb_substatus(void *cb)
static inline int gru_check_status(void *cb)
{
struct gru_control_block_status *cbs = (void *)cb;
- int ret = cbs->istatus;
+ int ret;
+ ret = cbs->istatus;
if (ret == CBS_CALL_OS)
ret = gru_check_status_proc(cb);
return ret;
@@ -617,7 +619,7 @@ static inline int gru_check_status(void *cb)
static inline int gru_wait(void *cb)
{
struct gru_control_block_status *cbs = (void *)cb;
- int ret = cbs->istatus;;
+ int ret = cbs->istatus;
if (ret != CBS_IDLE)
ret = gru_wait_proc(cb);
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 3d33015bbf3..8c389d606c3 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -214,12 +214,14 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
}
/*
- *
* atomic_pte_lookup
*
* Convert a user virtual address to a physical address
* Only supports Intel large pages (2MB only) on x86_64.
* ZZZ - hugepage support is incomplete
+ *
+ * NOTE: mmap_sem is already held on entry to this function. This
+ * guarantees existence of the page tables.
*/
static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
int write, unsigned long *paddr, int *pageshift)
@@ -229,9 +231,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
pud_t *pudp;
pte_t pte;
- WARN_ON(irqs_disabled()); /* ZZZ debug */
-
- local_irq_disable();
pgdp = pgd_offset(vma->vm_mm, vaddr);
if (unlikely(pgd_none(*pgdp)))
goto err;
@@ -250,8 +249,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
#endif
pte = *pte_offset_kernel(pmdp, vaddr);
- local_irq_enable();
-
if (unlikely(!pte_present(pte) ||
(write && (!pte_write(pte) || !pte_dirty(pte)))))
return 1;
@@ -324,6 +321,7 @@ static int gru_try_dropin(struct gru_thread_state *gts,
* Atomic lookup is faster & usually works even if called in non-atomic
* context.
*/
+ rmb(); /* Must/check ms_range_active before loading PTEs */
ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift);
if (ret) {
if (!cb)
@@ -543,6 +541,7 @@ int gru_get_exception_detail(unsigned long arg)
ucbnum = get_cb_number((void *)excdet.cb);
cbrnum = thread_cbr_number(gts, ucbnum);
cbe = get_cbe_by_index(gts->ts_gru, cbrnum);
+ prefetchw(cbe); /* Harmless on hardware, required for emulator */
excdet.opc = cbe->opccpy;
excdet.exopc = cbe->exopccpy;
excdet.ecause = cbe->ecause;
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 23c91f5f6b6..5c027b6b4e5 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -113,7 +113,7 @@ static int gru_file_mmap(struct file *file, struct vm_area_struct *vma)
return -EPERM;
if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) ||
- vma->vm_end & (GRU_GSEG_PAGESIZE - 1))
+ vma->vm_end & (GRU_GSEG_PAGESIZE - 1))
return -EINVAL;
vma->vm_flags |=
@@ -398,6 +398,12 @@ static int __init gru_init(void)
irq = get_base_irq();
for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) {
ret = request_irq(irq + chip, gru_intr, 0, id, NULL);
+ /* TODO: fix irq handling on x86. For now ignore failures because
+ * interrupts are not required & not yet fully supported */
+ if (ret) {
+ printk("!!!WARNING: GRU ignoring request failure!!!\n");
+ ret = 0;
+ }
if (ret) {
printk(KERN_ERR "%s: request_irq failed\n",
GRU_DRIVER_ID_STR);
@@ -445,6 +451,9 @@ static void __exit gru_exit(void)
int order = get_order(sizeof(struct gru_state) *
GRU_CHIPLETS_PER_BLADE);
+ if (!IS_UV())
+ return;
+
for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++)
free_irq(IRQ_GRU + i, NULL);
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index d16031d6267..b63018d60fe 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -91,12 +91,7 @@
#define GSEGPOFF(h) ((h) & (GRU_SIZE - 1))
/* Convert an arbitrary handle address to the beginning of the GRU segment */
-#ifndef __PLUGIN__
#define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1)))
-#else
-extern void *gmu_grubase(void *h);
-#define GRUBASE(h) gmu_grubase(h)
-#endif
/* General addressing macros. */
static inline void *get_gseg_base_address(void *base, int ctxnum)
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index dfd49af0fe1..880c55dfb66 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -122,6 +122,7 @@ int gru_get_cb_exception_detail(void *cb,
struct gru_control_block_extended *cbe;
cbe = get_cbe(GRUBASE(cb), get_cb_number(cb));
+ prefetchw(cbe); /* Harmless on hardware, required for emulator */
excdet->opc = cbe->opccpy;
excdet->exopc = cbe->exopccpy;
excdet->ecause = cbe->ecause;
@@ -466,7 +467,7 @@ int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes)
STAT(mesq_send);
BUG_ON(bytes < sizeof(int) || bytes > 2 * GRU_CACHE_LINE_BYTES);
- clines = (bytes + GRU_CACHE_LINE_BYTES - 1) / GRU_CACHE_LINE_BYTES;
+ clines = DIV_ROUND_UP(bytes, GRU_CACHE_LINE_BYTES);
if (gru_get_cpu_resources(bytes, &cb, &dsr))
return MQE_BUG_NO_RESOURCES;
memcpy(dsr, mesg, bytes);
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 0eeb8dddd2f..e11e1ac5090 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -432,29 +432,35 @@ static inline long gru_copy_handle(void *d, void *s)
return GRU_HANDLE_BYTES;
}
-/* rewrite in assembly & use lots of prefetch */
-static void gru_load_context_data(void *save, void *grubase, int ctxnum,
- unsigned long cbrmap, unsigned long dsrmap)
+static void gru_prefetch_context(void *gseg, void *cb, void *cbe, unsigned long cbrmap,
+ unsigned long length)
{
- void *gseg, *cb, *cbe;
- unsigned long length;
int i, scr;
- gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
- length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES,
GRU_CACHE_LINE_BYTES);
- cb = gseg + GRU_CB_BASE;
- cbe = grubase + GRU_CBE_BASE;
for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES);
prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1,
GRU_CACHE_LINE_BYTES);
cb += GRU_HANDLE_STRIDE;
}
+}
+
+static void gru_load_context_data(void *save, void *grubase, int ctxnum,
+ unsigned long cbrmap, unsigned long dsrmap)
+{
+ void *gseg, *cb, *cbe;
+ unsigned long length;
+ int i, scr;
+ gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
cb = gseg + GRU_CB_BASE;
+ cbe = grubase + GRU_CBE_BASE;
+ length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
+ gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
+
for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
save += gru_copy_handle(cb, save);
save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save);
@@ -472,15 +478,16 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum,
int i, scr;
gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
-
cb = gseg + GRU_CB_BASE;
cbe = grubase + GRU_CBE_BASE;
+ length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
+ gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
+
for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
save += gru_copy_handle(save, cb);
save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE);
cb += GRU_HANDLE_STRIDE;
}
- length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
memcpy(save, gseg + GRU_DS_BASE, length);
}
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index d3eb7903c34..6b9300779a4 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -3086,7 +3086,6 @@ static struct ibm_struct wan_driver_data = {
.read = wan_read,
.write = wan_write,
.exit = wan_exit,
- .flags.experimental = 1,
};
/*************************************************************************
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c0b41e8bcd9..f2eeb38efa6 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -3,13 +3,14 @@
#
menuconfig MMC
- tristate "MMC/SD card support"
+ tristate "MMC/SD/SDIO card support"
depends on HAS_IOMEM
help
- MMC is the "multi-media card" bus protocol.
+ This selects MultiMediaCard, Secure Digital and Secure
+ Digital I/O support.
- If you want MMC support, you should say Y here and also
- to the specific driver for your MMC interface.
+ If you want MMC/SD/SDIO support, you should say Y here and
+ also to your specific host controller driver.
config MMC_DEBUG
bool "MMC debugging"
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index dd0f398ee2f..3f2a912659a 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -2,7 +2,7 @@
# MMC/SD card drivers
#
-comment "MMC/SD Card Drivers"
+comment "MMC/SD/SDIO Card Drivers"
config MMC_BLOCK
tristate "MMC block device driver"
@@ -34,7 +34,6 @@ config MMC_BLOCK_BOUNCE
config SDIO_UART
tristate "SDIO UART/GPS class support"
- depends on MMC
help
SDIO function driver for SDIO cards that implements the UART
class, as well as the GPS class which appears like a UART.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 86dbb366415..24c97d3d16b 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -29,6 +29,7 @@
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
+#include <linux/string_helpers.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -57,7 +58,6 @@ struct mmc_blk_data {
struct mmc_queue queue;
unsigned int usage;
- unsigned int block_bits;
unsigned int read_only;
};
@@ -83,7 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_lock(&open_lock);
md->usage--;
if (md->usage == 0) {
- int devidx = md->disk->first_minor >> MMC_SHIFT;
+ int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
__clear_bit(devidx, dev_use);
put_disk(md->disk);
@@ -103,8 +103,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
check_disk_change(inode->i_bdev);
ret = 0;
- if ((filp->f_mode & FMODE_WRITE) && md->read_only)
+ if ((filp->f_mode & FMODE_WRITE) && md->read_only) {
+ mmc_blk_put(md);
ret = -EROFS;
+ }
}
return ret;
@@ -213,8 +215,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
struct mmc_blk_request brq;
- int ret = 1, data_size, i;
- struct scatterlist *sg;
+ int ret = 1;
mmc_claim_host(card->host);
@@ -230,13 +231,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
if (!mmc_card_blockaddr(card))
brq.cmd.arg <<= 9;
brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- brq.data.blksz = 1 << md->block_bits;
+ brq.data.blksz = 512;
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
- if (brq.data.blocks > card->host->max_blk_count)
- brq.data.blocks = card->host->max_blk_count;
+ brq.data.blocks = req->nr_sectors;
if (brq.data.blocks > 1) {
/* SPI multiblock writes terminate using a special
@@ -268,24 +267,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
mmc_queue_bounce_pre(mq);
- /*
- * Adjust the sg list so it is the same size as the
- * request.
- */
- if (brq.data.blocks !=
- (req->nr_sectors >> (md->block_bits - 9))) {
- data_size = brq.data.blocks * brq.data.blksz;
- for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
- data_size -= sg->length;
- if (data_size <= 0) {
- sg->length += data_size;
- i++;
- break;
- }
- }
- brq.data.sg_len = i;
- }
-
mmc_wait_for_req(card->host, &brq.mrq);
mmc_queue_bounce_post(mq);
@@ -370,16 +351,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
if (rq_data_dir(req) != READ) {
if (mmc_card_sd(card)) {
u32 blocks;
- unsigned int bytes;
blocks = mmc_sd_num_wr_blocks(card);
if (blocks != (u32)-1) {
- if (card->csd.write_partial)
- bytes = blocks << md->block_bits;
- else
- bytes = blocks << 9;
spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, bytes);
+ ret = __blk_end_request(req, 0, blocks << 9);
spin_unlock_irq(&md->lock);
}
} else {
@@ -429,13 +405,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
*/
md->read_only = mmc_blk_readonly(card);
- /*
- * Both SD and MMC specifications state (although a bit
- * unclearly in the MMC case) that a block size of 512
- * bytes must always be supported by the card.
- */
- md->block_bits = 9;
-
md->disk = alloc_disk(1 << MMC_SHIFT);
if (md->disk == NULL) {
ret = -ENOMEM;
@@ -473,7 +442,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
sprintf(md->disk->disk_name, "mmcblk%d", devidx);
- blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+ blk_queue_hardsect_size(md->queue.queue, 512);
if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
/*
@@ -511,7 +480,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
mmc_claim_host(card->host);
cmd.opcode = MMC_SET_BLOCKLEN;
- cmd.arg = 1 << md->block_bits;
+ cmd.arg = 512;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
mmc_release_host(card->host);
@@ -530,6 +499,8 @@ static int mmc_blk_probe(struct mmc_card *card)
struct mmc_blk_data *md;
int err;
+ char cap_str[10];
+
/*
* Check that the card supports the command class(es) we need.
*/
@@ -544,10 +515,11 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
+ string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
+ cap_str, sizeof(cap_str));
+ printk(KERN_INFO "%s: %s %s %s %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- (unsigned long long)(get_capacity(md->disk) >> 1),
- md->read_only ? "(ro)" : "");
+ cap_str, md->read_only ? "(ro)" : "");
mmc_set_drvdata(card, md);
add_disk(md->disk);
@@ -613,14 +585,19 @@ static struct mmc_driver mmc_driver = {
static int __init mmc_blk_init(void)
{
- int res = -ENOMEM;
+ int res;
res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
if (res)
goto out;
- return mmc_register_driver(&mmc_driver);
+ res = mmc_register_driver(&mmc_driver);
+ if (res)
+ goto out2;
+ return 0;
+ out2:
+ unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
out:
return res;
}
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index f26b01d811a..b92b172074e 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -1040,7 +1040,7 @@ static const struct mmc_test_case mmc_test_cases[] = {
};
-static struct mutex mmc_test_lock;
+static DEFINE_MUTEX(mmc_test_lock);
static void mmc_test_run(struct mmc_test_card *test, int testcase)
{
@@ -1171,8 +1171,6 @@ static int mmc_test_probe(struct mmc_card *card)
if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD))
return -ENODEV;
- mutex_init(&mmc_test_lock);
-
ret = device_create_file(&card->dev, &dev_attr_test);
if (ret)
return ret;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 3dee97e7d16..406989e992b 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -31,7 +31,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
/*
* We only like normal block requests.
*/
- if (!blk_fs_request(req) && !blk_pc_request(req)) {
+ if (!blk_fs_request(req)) {
blk_dump_rq_flags(req, "MMC bad request");
return BLKPREP_KILL;
}
@@ -131,6 +131,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
mq->req = NULL;
blk_queue_prep_rq(mq->queue, mmc_prep_request);
+ blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);
#ifdef CONFIG_MMC_BLOCK_BOUNCE
if (host->max_hw_segs == 1) {
@@ -142,12 +143,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
bouncesz = host->max_req_size;
if (bouncesz > host->max_seg_size)
bouncesz = host->max_seg_size;
+ if (bouncesz > (host->max_blk_count * 512))
+ bouncesz = host->max_blk_count * 512;
+
+ if (bouncesz > 512) {
+ mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mq->bounce_buf) {
+ printk(KERN_WARNING "%s: unable to "
+ "allocate bounce buffer\n",
+ mmc_card_name(card));
+ }
+ }
- mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
- if (!mq->bounce_buf) {
- printk(KERN_WARNING "%s: unable to allocate "
- "bounce buffer\n", mmc_card_name(card));
- } else {
+ if (mq->bounce_buf) {
blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_sectors(mq->queue, bouncesz / 512);
blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
@@ -175,7 +183,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
if (!mq->bounce_buf) {
blk_queue_bounce_limit(mq->queue, limit);
- blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+ blk_queue_max_sectors(mq->queue,
+ min(host->max_blk_count, host->max_req_size / 512));
blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 64b05c6270f..9c50e6f1c23 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -248,8 +248,12 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
sg_init_one(&sg, data_buf, len);
- if (card)
- mmc_set_data_timeout(&data, card);
+ /*
+ * The spec states that CSR and CID accesses have a timeout
+ * of 64 clock cycles.
+ */
+ data.timeout_ns = 0;
+ data.timeout_clks = 64;
mmc_wait_for_req(host, &mrq);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 4eab79e09cc..fb99ccff908 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -165,6 +165,36 @@ static int sdio_enable_wide(struct mmc_card *card)
}
/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int sdio_enable_hs(struct mmc_card *card)
+{
+ int ret;
+ u8 speed;
+
+ if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+ return 0;
+
+ if (!card->cccr.high_speed)
+ return 0;
+
+ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
+ if (ret)
+ return ret;
+
+ speed |= SDIO_SPEED_EHS;
+
+ ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
+ if (ret)
+ return ret;
+
+ mmc_card_set_highspeed(card);
+ mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+
+ return 0;
+}
+
+/*
* Host is being removed. Free up the current card.
*/
static void mmc_sdio_remove(struct mmc_host *host)
@@ -333,10 +363,26 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
goto remove;
/*
- * No support for high-speed yet, so just set
- * the card's maximum speed.
+ * Switch to high-speed (if supported).
*/
- mmc_set_clock(host, card->cis.max_dtr);
+ err = sdio_enable_hs(card);
+ if (err)
+ goto remove;
+
+ /*
+ * Change to the card's maximum speed.
+ */
+ if (mmc_card_highspeed(card)) {
+ /*
+ * The SDIO specification doesn't mention how
+ * the CIS transfer speed register relates to
+ * high-speed, but it seems that 50 MHz is
+ * mandatory.
+ */
+ mmc_set_clock(host, 50000000);
+ } else {
+ mmc_set_clock(host, card->cis.max_dtr);
+ }
/*
* Switch to wider bus (if supported).
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index c292e124107..bb192f90e8e 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -5,6 +5,8 @@
* Created: June 18, 2007
* Copyright: MontaVista Software Inc.
*
+ * Copyright 2008 Pierre Ossman
+ *
* 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
@@ -107,11 +109,14 @@ static int sdio_irq_thread(void *_host)
/*
* Give other threads a chance to run in the presence of
- * errors. FIXME: determine if due to card removal and
- * possibly exit this thread if so.
+ * errors.
*/
- if (ret < 0)
- ssleep(1);
+ if (ret < 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!kthread_should_stop())
+ schedule_timeout(HZ);
+ set_current_state(TASK_RUNNING);
+ }
/*
* Adaptive polling frequency based on the assumption
@@ -154,7 +159,8 @@ static int sdio_card_irq_get(struct mmc_card *card)
if (!host->sdio_irqs++) {
atomic_set(&host->sdio_irq_thread_abort, 0);
host->sdio_irq_thread =
- kthread_run(sdio_irq_thread, host, "ksdiorqd");
+ kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
+ mmc_hostname(host));
if (IS_ERR(host->sdio_irq_thread)) {
int err = PTR_ERR(host->sdio_irq_thread);
host->sdio_irqs--;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index ea8d7a3490d..dfa585f7fea 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -2,7 +2,7 @@
# MMC/SD host controller drivers
#
-comment "MMC/SD Host Controller Drivers"
+comment "MMC/SD/SDIO Host Controller Drivers"
config MMC_ARMMMCI
tristate "ARM AMBA Multimedia Card Interface support"
@@ -114,6 +114,17 @@ config MMC_ATMELMCI
If unsure, say N.
+config MMC_ATMELMCI_DMA
+ bool "Atmel MCI DMA support (EXPERIMENTAL)"
+ depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL
+ help
+ Say Y here to have the Atmel MCI driver use a DMA engine to
+ do data transfers and thus increase the throughput and
+ reduce the CPU utilization. Note that this is highly
+ experimental and may cause the driver to lock up.
+
+ If unsure, say N.
+
config MMC_IMX
tristate "Motorola i.MX Multimedia Card Interface support"
depends on ARCH_IMX
@@ -141,21 +152,22 @@ config MMC_TIFM_SD
module will be called tifm_sd.
config MMC_SPI
- tristate "MMC/SD over SPI"
- depends on MMC && SPI_MASTER && !HIGHMEM && HAS_DMA
+ tristate "MMC/SD/SDIO over SPI"
+ depends on SPI_MASTER && !HIGHMEM && HAS_DMA
select CRC7
select CRC_ITU_T
help
- Some systems accss MMC/SD cards using a SPI controller instead of
- using a "native" MMC/SD controller. This has a disadvantage of
- being relatively high overhead, but a compensating advantage of
- working on many systems without dedicated MMC/SD controllers.
+ Some systems accss MMC/SD/SDIO cards using a SPI controller
+ instead of using a "native" MMC/SD/SDIO controller. This has a
+ disadvantage of being relatively high overhead, but a compensating
+ advantage of working on many systems without dedicated MMC/SD/SDIO
+ controllers.
If unsure, or if your system has no SPI master driver, say N.
config MMC_S3C
tristate "Samsung S3C SD/MMC Card Interface support"
- depends on ARCH_S3C2410 && MMC
+ depends on ARCH_S3C2410
help
This selects a driver for the MCI interface found in
Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@@ -166,7 +178,7 @@ config MMC_S3C
config MMC_SDRICOH_CS
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
- depends on EXPERIMENTAL && MMC && PCI && PCMCIA
+ depends on EXPERIMENTAL && PCI && PCMCIA
help
Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
card whenever you insert a MMC or SD card into the card slot.
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 6915f40ac8a..1f8b5b36222 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -621,12 +621,21 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
if (host->total_length < 12)
host->total_length = 12;
- host->buffer = dma_alloc_coherent(NULL,
- host->total_length,
- &host->physical_address, GFP_KERNEL);
+
+ host->buffer = kmalloc(host->total_length, GFP_KERNEL);
+ if (!host->buffer) {
+ pr_debug("Can't alloc tx buffer\n");
+ cmd->error = -ENOMEM;
+ mmc_request_done(host->mmc, host->request);
+ return;
+ }
at91_mci_sg_to_dma(host, data);
+ host->physical_address = dma_map_single(NULL,
+ host->buffer, host->total_length,
+ DMA_TO_DEVICE);
+
pr_debug("Transmitting %d bytes\n", host->total_length);
at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
@@ -694,7 +703,10 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s
cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
if (host->buffer) {
- dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+ dma_unmap_single(NULL,
+ host->physical_address, host->total_length,
+ DMA_TO_DEVICE);
+ kfree(host->buffer);
host->buffer = NULL;
}
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index 26bd80e6503..b58364ed6bb 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -25,8 +25,10 @@
#define MCI_SDCR 0x000c /* SD Card / SDIO */
# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
-# define MCI_SDCBUS_1BIT ( 0 << 7) /* 1-bit data bus */
-# define MCI_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */
+# define MCI_SDCSEL_MASK ( 3 << 0)
+# define MCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
+# define MCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
+# define MCI_SDCBUS_MASK ( 3 << 6)
#define MCI_ARGR 0x0010 /* Command Argument */
#define MCI_CMDR 0x0014 /* Command */
# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 0bd06f5bd62..7a3f2436b01 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -11,6 +11,8 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
@@ -33,64 +35,178 @@
#include "atmel-mci-regs.h"
#define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE)
+#define ATMCI_DMA_THRESHOLD 16
enum {
EVENT_CMD_COMPLETE = 0,
- EVENT_DATA_ERROR,
- EVENT_DATA_COMPLETE,
- EVENT_STOP_SENT,
- EVENT_STOP_COMPLETE,
EVENT_XFER_COMPLETE,
+ EVENT_DATA_COMPLETE,
+ EVENT_DATA_ERROR,
+};
+
+enum atmel_mci_state {
+ STATE_IDLE = 0,
+ STATE_SENDING_CMD,
+ STATE_SENDING_DATA,
+ STATE_DATA_BUSY,
+ STATE_SENDING_STOP,
+ STATE_DATA_ERROR,
+};
+
+struct atmel_mci_dma {
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+ struct dma_client client;
+ struct dma_chan *chan;
+ struct dma_async_tx_descriptor *data_desc;
+#endif
};
+/**
+ * struct atmel_mci - MMC controller state shared between all slots
+ * @lock: Spinlock protecting the queue and associated data.
+ * @regs: Pointer to MMIO registers.
+ * @sg: Scatterlist entry currently being processed by PIO code, if any.
+ * @pio_offset: Offset into the current scatterlist entry.
+ * @cur_slot: The slot which is currently using the controller.
+ * @mrq: The request currently being processed on @cur_slot,
+ * or NULL if the controller is idle.
+ * @cmd: The command currently being sent to the card, or NULL.
+ * @data: The data currently being transferred, or NULL if no data
+ * transfer is in progress.
+ * @dma: DMA client state.
+ * @data_chan: DMA channel being used for the current data transfer.
+ * @cmd_status: Snapshot of SR taken upon completion of the current
+ * command. Only valid when EVENT_CMD_COMPLETE is pending.
+ * @data_status: Snapshot of SR taken upon completion of the current
+ * data transfer. Only valid when EVENT_DATA_COMPLETE or
+ * EVENT_DATA_ERROR is pending.
+ * @stop_cmdr: Value to be loaded into CMDR when the stop command is
+ * to be sent.
+ * @tasklet: Tasklet running the request state machine.
+ * @pending_events: Bitmask of events flagged by the interrupt handler
+ * to be processed by the tasklet.
+ * @completed_events: Bitmask of events which the state machine has
+ * processed.
+ * @state: Tasklet state.
+ * @queue: List of slots waiting for access to the controller.
+ * @need_clock_update: Update the clock rate before the next request.
+ * @need_reset: Reset controller before next request.
+ * @mode_reg: Value of the MR register.
+ * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus
+ * rate and timeout calculations.
+ * @mapbase: Physical address of the MMIO registers.
+ * @mck: The peripheral bus clock hooked up to the MMC controller.
+ * @pdev: Platform device associated with the MMC controller.
+ * @slot: Slots sharing this MMC controller.
+ *
+ * Locking
+ * =======
+ *
+ * @lock is a softirq-safe spinlock protecting @queue as well as
+ * @cur_slot, @mrq and @state. These must always be updated
+ * at the same time while holding @lock.
+ *
+ * @lock also protects mode_reg and need_clock_update since these are
+ * used to synchronize mode register updates with the queue
+ * processing.
+ *
+ * The @mrq field of struct atmel_mci_slot is also protected by @lock,
+ * and must always be written at the same time as the slot is added to
+ * @queue.
+ *
+ * @pending_events and @completed_events are accessed using atomic bit
+ * operations, so they don't need any locking.
+ *
+ * None of the fields touched by the interrupt handler need any
+ * locking. However, ordering is important: Before EVENT_DATA_ERROR or
+ * EVENT_DATA_COMPLETE is set in @pending_events, all data-related
+ * interrupts must be disabled and @data_status updated with a
+ * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the
+ * CMDRDY interupt must be disabled and @cmd_status updated with a
+ * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the
+ * bytes_xfered field of @data must be written. This is ensured by
+ * using barriers.
+ */
struct atmel_mci {
- struct mmc_host *mmc;
+ spinlock_t lock;
void __iomem *regs;
struct scatterlist *sg;
unsigned int pio_offset;
+ struct atmel_mci_slot *cur_slot;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
+ struct atmel_mci_dma dma;
+ struct dma_chan *data_chan;
+
u32 cmd_status;
u32 data_status;
- u32 stop_status;
u32 stop_cmdr;
- u32 mode_reg;
- u32 sdc_reg;
-
struct tasklet_struct tasklet;
unsigned long pending_events;
unsigned long completed_events;
+ enum atmel_mci_state state;
+ struct list_head queue;
- int present;
- int detect_pin;
- int wp_pin;
-
- /* For detect pin debouncing */
- struct timer_list detect_timer;
-
+ bool need_clock_update;
+ bool need_reset;
+ u32 mode_reg;
unsigned long bus_hz;
unsigned long mapbase;
struct clk *mck;
struct platform_device *pdev;
+
+ struct atmel_mci_slot *slot[ATMEL_MCI_MAX_NR_SLOTS];
+};
+
+/**
+ * struct atmel_mci_slot - MMC slot state
+ * @mmc: The mmc_host representing this slot.
+ * @host: The MMC controller this slot is using.
+ * @sdc_reg: Value of SDCR to be written before using this slot.
+ * @mrq: mmc_request currently being processed or waiting to be
+ * processed, or NULL when the slot is idle.
+ * @queue_node: List node for placing this node in the @queue list of
+ * &struct atmel_mci.
+ * @clock: Clock rate configured by set_ios(). Protected by host->lock.
+ * @flags: Random state bits associated with the slot.
+ * @detect_pin: GPIO pin used for card detection, or negative if not
+ * available.
+ * @wp_pin: GPIO pin used for card write protect sending, or negative
+ * if not available.
+ * @detect_timer: Timer used for debouncing @detect_pin interrupts.
+ */
+struct atmel_mci_slot {
+ struct mmc_host *mmc;
+ struct atmel_mci *host;
+
+ u32 sdc_reg;
+
+ struct mmc_request *mrq;
+ struct list_head queue_node;
+
+ unsigned int clock;
+ unsigned long flags;
+#define ATMCI_CARD_PRESENT 0
+#define ATMCI_CARD_NEED_INIT 1
+#define ATMCI_SHUTDOWN 2
+
+ int detect_pin;
+ int wp_pin;
+
+ struct timer_list detect_timer;
};
-#define atmci_is_completed(host, event) \
- test_bit(event, &host->completed_events)
#define atmci_test_and_clear_pending(host, event) \
test_and_clear_bit(event, &host->pending_events)
-#define atmci_test_and_set_completed(host, event) \
- test_and_set_bit(event, &host->completed_events)
#define atmci_set_completed(host, event) \
set_bit(event, &host->completed_events)
#define atmci_set_pending(host, event) \
set_bit(event, &host->pending_events)
-#define atmci_clear_pending(host, event) \
- clear_bit(event, &host->pending_events)
/*
* The debugfs stuff below is mostly optimized away when
@@ -98,14 +214,15 @@ struct atmel_mci {
*/
static int atmci_req_show(struct seq_file *s, void *v)
{
- struct atmel_mci *host = s->private;
- struct mmc_request *mrq = host->mrq;
+ struct atmel_mci_slot *slot = s->private;
+ struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_command *stop;
struct mmc_data *data;
/* Make sure we get a consistent snapshot */
- spin_lock_irq(&host->mmc->lock);
+ spin_lock_bh(&slot->host->lock);
+ mrq = slot->mrq;
if (mrq) {
cmd = mrq->cmd;
@@ -130,7 +247,7 @@ static int atmci_req_show(struct seq_file *s, void *v)
stop->resp[2], stop->error);
}
- spin_unlock_irq(&host->mmc->lock);
+ spin_unlock_bh(&slot->host->lock);
return 0;
}
@@ -193,10 +310,16 @@ static int atmci_regs_show(struct seq_file *s, void *v)
if (!buf)
return -ENOMEM;
- /* Grab a more or less consistent snapshot */
- spin_lock_irq(&host->mmc->lock);
+ /*
+ * Grab a more or less consistent snapshot. Note that we're
+ * not disabling interrupts, so IMR and SR may not be
+ * consistent.
+ */
+ spin_lock_bh(&host->lock);
+ clk_enable(host->mck);
memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
- spin_unlock_irq(&host->mmc->lock);
+ clk_disable(host->mck);
+ spin_unlock_bh(&host->lock);
seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
buf[MCI_MR / 4],
@@ -216,6 +339,8 @@ static int atmci_regs_show(struct seq_file *s, void *v)
atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
+ kfree(buf);
+
return 0;
}
@@ -232,14 +357,13 @@ static const struct file_operations atmci_regs_fops = {
.release = single_release,
};
-static void atmci_init_debugfs(struct atmel_mci *host)
+static void atmci_init_debugfs(struct atmel_mci_slot *slot)
{
- struct mmc_host *mmc;
- struct dentry *root;
- struct dentry *node;
- struct resource *res;
+ struct mmc_host *mmc = slot->mmc;
+ struct atmel_mci *host = slot->host;
+ struct dentry *root;
+ struct dentry *node;
- mmc = host->mmc;
root = mmc->debugfs_root;
if (!root)
return;
@@ -251,10 +375,11 @@ static void atmci_init_debugfs(struct atmel_mci *host)
if (!node)
goto err;
- res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
- node->d_inode->i_size = res->end - res->start + 1;
+ node = debugfs_create_file("req", S_IRUSR, root, slot, &atmci_req_fops);
+ if (!node)
+ goto err;
- node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops);
+ node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
if (!node)
goto err;
@@ -271,25 +396,7 @@ static void atmci_init_debugfs(struct atmel_mci *host)
return;
err:
- dev_err(&host->pdev->dev,
- "failed to initialize debugfs for controller\n");
-}
-
-static void atmci_enable(struct atmel_mci *host)
-{
- clk_enable(host->mck);
- mci_writel(host, CR, MCI_CR_MCIEN);
- mci_writel(host, MR, host->mode_reg);
- mci_writel(host, SDCR, host->sdc_reg);
-}
-
-static void atmci_disable(struct atmel_mci *host)
-{
- mci_writel(host, CR, MCI_CR_SWRST);
-
- /* Stall until write is complete, then disable the bus clock */
- mci_readl(host, SR);
- clk_disable(host->mck);
+ dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
}
static inline unsigned int ns_to_clocks(struct atmel_mci *host,
@@ -299,7 +406,7 @@ static inline unsigned int ns_to_clocks(struct atmel_mci *host,
}
static void atmci_set_timeout(struct atmel_mci *host,
- struct mmc_data *data)
+ struct atmel_mci_slot *slot, struct mmc_data *data)
{
static unsigned dtomul_to_shift[] = {
0, 4, 7, 8, 10, 12, 16, 20
@@ -322,7 +429,7 @@ static void atmci_set_timeout(struct atmel_mci *host,
dtocyc = 15;
}
- dev_vdbg(&host->mmc->class_dev, "setting timeout to %u cycles\n",
+ dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n",
dtocyc << dtomul_to_shift[dtomul]);
mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc)));
}
@@ -375,15 +482,12 @@ static u32 atmci_prepare_command(struct mmc_host *mmc,
}
static void atmci_start_command(struct atmel_mci *host,
- struct mmc_command *cmd,
- u32 cmd_flags)
+ struct mmc_command *cmd, u32 cmd_flags)
{
- /* Must read host->cmd after testing event flags */
- smp_rmb();
WARN_ON(host->cmd);
host->cmd = cmd;
- dev_vdbg(&host->mmc->class_dev,
+ dev_vdbg(&host->pdev->dev,
"start command: ARGR=0x%08x CMDR=0x%08x\n",
cmd->arg, cmd_flags);
@@ -391,34 +495,157 @@ static void atmci_start_command(struct atmel_mci *host,
mci_writel(host, CMDR, cmd_flags);
}
-static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data)
+static void send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
{
- struct atmel_mci *host = mmc_priv(mmc);
-
atmci_start_command(host, data->stop, host->stop_cmdr);
mci_writel(host, IER, MCI_CMDRDY);
}
-static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq)
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+static void atmci_dma_cleanup(struct atmel_mci *host)
{
- struct atmel_mci *host = mmc_priv(mmc);
+ struct mmc_data *data = host->data;
- WARN_ON(host->cmd || host->data);
- host->mrq = NULL;
+ dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+ ((data->flags & MMC_DATA_WRITE)
+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+}
+
+static void atmci_stop_dma(struct atmel_mci *host)
+{
+ struct dma_chan *chan = host->data_chan;
+
+ if (chan) {
+ chan->device->device_terminate_all(chan);
+ atmci_dma_cleanup(host);
+ } else {
+ /* Data transfer was stopped by the interrupt handler */
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
+ mci_writel(host, IER, MCI_NOTBUSY);
+ }
+}
+
+/* This function is called by the DMA driver from tasklet context. */
+static void atmci_dma_complete(void *arg)
+{
+ struct atmel_mci *host = arg;
+ struct mmc_data *data = host->data;
+
+ dev_vdbg(&host->pdev->dev, "DMA complete\n");
+
+ atmci_dma_cleanup(host);
+
+ /*
+ * If the card was removed, data will be NULL. No point trying
+ * to send the stop command or waiting for NBUSY in this case.
+ */
+ if (data) {
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
+ tasklet_schedule(&host->tasklet);
+
+ /*
+ * Regardless of what the documentation says, we have
+ * to wait for NOTBUSY even after block read
+ * operations.
+ *
+ * When the DMA transfer is complete, the controller
+ * may still be reading the CRC from the card, i.e.
+ * the data transfer is still in progress and we
+ * haven't seen all the potential error bits yet.
+ *
+ * The interrupt handler will schedule a different
+ * tasklet to finish things up when the data transfer
+ * is completely done.
+ *
+ * We may not complete the mmc request here anyway
+ * because the mmc layer may call back and cause us to
+ * violate the "don't submit new operations from the
+ * completion callback" rule of the dma engine
+ * framework.
+ */
+ mci_writel(host, IER, MCI_NOTBUSY);
+ }
+}
+
+static int
+atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
+{
+ struct dma_chan *chan;
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist *sg;
+ unsigned int i;
+ enum dma_data_direction direction;
+
+ /*
+ * We don't do DMA on "complex" transfers, i.e. with
+ * non-word-aligned buffers or lengths. Also, we don't bother
+ * with all the DMA setup overhead for short transfers.
+ */
+ if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD)
+ return -EINVAL;
+ if (data->blksz & 3)
+ return -EINVAL;
+
+ for_each_sg(data->sg, sg, data->sg_len, i) {
+ if (sg->offset & 3 || sg->length & 3)
+ return -EINVAL;
+ }
+
+ /* If we don't have a channel, we can't do DMA */
+ chan = host->dma.chan;
+ if (chan) {
+ dma_chan_get(chan);
+ host->data_chan = chan;
+ }
+
+ if (!chan)
+ return -ENODEV;
+
+ if (data->flags & MMC_DATA_READ)
+ direction = DMA_FROM_DEVICE;
+ else
+ direction = DMA_TO_DEVICE;
+
+ desc = chan->device->device_prep_slave_sg(chan,
+ data->sg, data->sg_len, direction,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc)
+ return -ENOMEM;
+
+ host->dma.data_desc = desc;
+ desc->callback = atmci_dma_complete;
+ desc->callback_param = host;
+ desc->tx_submit(desc);
+
+ /* Go! */
+ chan->device->device_issue_pending(chan);
+
+ return 0;
+}
- atmci_disable(host);
+#else /* CONFIG_MMC_ATMELMCI_DMA */
- mmc_request_done(mmc, mrq);
+static int atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
+{
+ return -ENOSYS;
}
+static void atmci_stop_dma(struct atmel_mci *host)
+{
+ /* Data transfer was stopped by the interrupt handler */
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
+ mci_writel(host, IER, MCI_NOTBUSY);
+}
+
+#endif /* CONFIG_MMC_ATMELMCI_DMA */
+
/*
* Returns a mask of interrupt flags to be enabled after the whole
* request has been prepared.
*/
-static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)
+static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data)
{
- struct atmel_mci *host = mmc_priv(mmc);
- u32 iflags;
+ u32 iflags;
data->error = -EINPROGRESS;
@@ -426,75 +653,89 @@ static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)
host->sg = NULL;
host->data = data;
- mci_writel(host, BLKR, MCI_BCNT(data->blocks)
- | MCI_BLKLEN(data->blksz));
- dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
- MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
-
iflags = ATMCI_DATA_ERROR_FLAGS;
- host->sg = data->sg;
- host->pio_offset = 0;
- if (data->flags & MMC_DATA_READ)
- iflags |= MCI_RXRDY;
- else
- iflags |= MCI_TXRDY;
+ if (atmci_submit_data_dma(host, data)) {
+ host->data_chan = NULL;
+
+ /*
+ * Errata: MMC data write operation with less than 12
+ * bytes is impossible.
+ *
+ * Errata: MCI Transmit Data Register (TDR) FIFO
+ * corruption when length is not multiple of 4.
+ */
+ if (data->blocks * data->blksz < 12
+ || (data->blocks * data->blksz) & 3)
+ host->need_reset = true;
+
+ host->sg = data->sg;
+ host->pio_offset = 0;
+ if (data->flags & MMC_DATA_READ)
+ iflags |= MCI_RXRDY;
+ else
+ iflags |= MCI_TXRDY;
+ }
return iflags;
}
-static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+static void atmci_start_request(struct atmel_mci *host,
+ struct atmel_mci_slot *slot)
{
- struct atmel_mci *host = mmc_priv(mmc);
- struct mmc_data *data;
+ struct mmc_request *mrq;
struct mmc_command *cmd;
+ struct mmc_data *data;
u32 iflags;
- u32 cmdflags = 0;
-
- iflags = mci_readl(host, IMR);
- if (iflags)
- dev_warn(&mmc->class_dev, "WARNING: IMR=0x%08x\n",
- mci_readl(host, IMR));
-
- WARN_ON(host->mrq != NULL);
-
- /*
- * We may "know" the card is gone even though there's still an
- * electrical connection. If so, we really need to communicate
- * this to the MMC core since there won't be any more
- * interrupts as the card is completely removed. Otherwise,
- * the MMC core might believe the card is still there even
- * though the card was just removed very slowly.
- */
- if (!host->present) {
- mrq->cmd->error = -ENOMEDIUM;
- mmc_request_done(mmc, mrq);
- return;
- }
+ u32 cmdflags;
+ mrq = slot->mrq;
+ host->cur_slot = slot;
host->mrq = mrq;
+
host->pending_events = 0;
host->completed_events = 0;
+ host->data_status = 0;
- atmci_enable(host);
+ if (host->need_reset) {
+ mci_writel(host, CR, MCI_CR_SWRST);
+ mci_writel(host, CR, MCI_CR_MCIEN);
+ mci_writel(host, MR, host->mode_reg);
+ host->need_reset = false;
+ }
+ mci_writel(host, SDCR, slot->sdc_reg);
- /* We don't support multiple blocks of weird lengths. */
+ iflags = mci_readl(host, IMR);
+ if (iflags)
+ dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
+ iflags);
+
+ if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) {
+ /* Send init sequence (74 clock cycles) */
+ mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT);
+ while (!(mci_readl(host, SR) & MCI_CMDRDY))
+ cpu_relax();
+ }
data = mrq->data;
if (data) {
- if (data->blocks > 1 && data->blksz & 3)
- goto fail;
- atmci_set_timeout(host, data);
+ atmci_set_timeout(host, slot, data);
+
+ /* Must set block count/size before sending command */
+ mci_writel(host, BLKR, MCI_BCNT(data->blocks)
+ | MCI_BLKLEN(data->blksz));
+ dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n",
+ MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
}
iflags = MCI_CMDRDY;
cmd = mrq->cmd;
- cmdflags = atmci_prepare_command(mmc, cmd);
+ cmdflags = atmci_prepare_command(slot->mmc, cmd);
atmci_start_command(host, cmd, cmdflags);
if (data)
- iflags |= atmci_submit_data(mmc, data);
+ iflags |= atmci_submit_data(host, data);
if (mrq->stop) {
- host->stop_cmdr = atmci_prepare_command(mmc, mrq->stop);
+ host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop);
host->stop_cmdr |= MCI_CMDR_STOP_XFER;
if (!(data->flags & MMC_DATA_WRITE))
host->stop_cmdr |= MCI_CMDR_TRDIR_READ;
@@ -511,59 +752,156 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
* prepared yet.)
*/
mci_writel(host, IER, iflags);
+}
- return;
+static void atmci_queue_request(struct atmel_mci *host,
+ struct atmel_mci_slot *slot, struct mmc_request *mrq)
+{
+ dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
+ host->state);
+
+ spin_lock_bh(&host->lock);
+ slot->mrq = mrq;
+ if (host->state == STATE_IDLE) {
+ host->state = STATE_SENDING_CMD;
+ atmci_start_request(host, slot);
+ } else {
+ list_add_tail(&slot->queue_node, &host->queue);
+ }
+ spin_unlock_bh(&host->lock);
+}
-fail:
- atmci_disable(host);
- host->mrq = NULL;
- mrq->cmd->error = -EINVAL;
- mmc_request_done(mmc, mrq);
+static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct atmel_mci_slot *slot = mmc_priv(mmc);
+ struct atmel_mci *host = slot->host;
+ struct mmc_data *data;
+
+ WARN_ON(slot->mrq);
+
+ /*
+ * We may "know" the card is gone even though there's still an
+ * electrical connection. If so, we really need to communicate
+ * this to the MMC core since there won't be any more
+ * interrupts as the card is completely removed. Otherwise,
+ * the MMC core might believe the card is still there even
+ * though the card was just removed very slowly.
+ */
+ if (!test_bit(ATMCI_CARD_PRESENT, &slot->flags)) {
+ mrq->cmd->error = -ENOMEDIUM;
+ mmc_request_done(mmc, mrq);
+ return;
+ }
+
+ /* We don't support multiple blocks of weird lengths. */
+ data = mrq->data;
+ if (data && data->blocks > 1 && data->blksz & 3) {
+ mrq->cmd->error = -EINVAL;
+ mmc_request_done(mmc, mrq);
+ }
+
+ atmci_queue_request(host, slot, mrq);
}
static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
- struct atmel_mci *host = mmc_priv(mmc);
+ struct atmel_mci_slot *slot = mmc_priv(mmc);
+ struct atmel_mci *host = slot->host;
+ unsigned int i;
+
+ slot->sdc_reg &= ~MCI_SDCBUS_MASK;
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_1:
+ slot->sdc_reg |= MCI_SDCBUS_1BIT;
+ break;
+ case MMC_BUS_WIDTH_4:
+ slot->sdc_reg = MCI_SDCBUS_4BIT;
+ break;
+ }
if (ios->clock) {
+ unsigned int clock_min = ~0U;
u32 clkdiv;
- /* Set clock rate */
- clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1;
+ spin_lock_bh(&host->lock);
+ if (!host->mode_reg) {
+ clk_enable(host->mck);
+ mci_writel(host, CR, MCI_CR_SWRST);
+ mci_writel(host, CR, MCI_CR_MCIEN);
+ }
+
+ /*
+ * Use mirror of ios->clock to prevent race with mmc
+ * core ios update when finding the minimum.
+ */
+ slot->clock = ios->clock;
+ for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ if (host->slot[i] && host->slot[i]->clock
+ && host->slot[i]->clock < clock_min)
+ clock_min = host->slot[i]->clock;
+ }
+
+ /* Calculate clock divider */
+ clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
if (clkdiv > 255) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
- ios->clock, host->bus_hz / (2 * 256));
+ clock_min, host->bus_hz / (2 * 256));
clkdiv = 255;
}
+ /*
+ * WRPROOF and RDPROOF prevent overruns/underruns by
+ * stopping the clock when the FIFO is full/empty.
+ * This state is not expected to last for long.
+ */
host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF
| MCI_MR_RDPROOF;
- }
- switch (ios->bus_width) {
- case MMC_BUS_WIDTH_1:
- host->sdc_reg = 0;
- break;
- case MMC_BUS_WIDTH_4:
- host->sdc_reg = MCI_SDCBUS_4BIT;
- break;
+ if (list_empty(&host->queue))
+ mci_writel(host, MR, host->mode_reg);
+ else
+ host->need_clock_update = true;
+
+ spin_unlock_bh(&host->lock);
+ } else {
+ bool any_slot_active = false;
+
+ spin_lock_bh(&host->lock);
+ slot->clock = 0;
+ for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ if (host->slot[i] && host->slot[i]->clock) {
+ any_slot_active = true;
+ break;
+ }
+ }
+ if (!any_slot_active) {
+ mci_writel(host, CR, MCI_CR_MCIDIS);
+ if (host->mode_reg) {
+ mci_readl(host, MR);
+ clk_disable(host->mck);
+ }
+ host->mode_reg = 0;
+ }
+ spin_unlock_bh(&host->lock);
}
switch (ios->power_mode) {
- case MMC_POWER_ON:
- /* Send init sequence (74 clock cycles) */
- atmci_enable(host);
- mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT);
- while (!(mci_readl(host, SR) & MCI_CMDRDY))
- cpu_relax();
- atmci_disable(host);
+ case MMC_POWER_UP:
+ set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
break;
default:
/*
* TODO: None of the currently available AVR32-based
* boards allow MMC power to be turned off. Implement
* power control when this can be tested properly.
+ *
+ * We also need to hook this into the clock management
+ * somehow so that newly inserted cards aren't
+ * subjected to a fast clock before we have a chance
+ * to figure out what the maximum rate is. Currently,
+ * there's no way to avoid this, and there never will
+ * be for boards that don't support power control.
*/
break;
}
@@ -571,31 +909,82 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int atmci_get_ro(struct mmc_host *mmc)
{
- int read_only = 0;
- struct atmel_mci *host = mmc_priv(mmc);
+ int read_only = -ENOSYS;
+ struct atmel_mci_slot *slot = mmc_priv(mmc);
- if (gpio_is_valid(host->wp_pin)) {
- read_only = gpio_get_value(host->wp_pin);
+ if (gpio_is_valid(slot->wp_pin)) {
+ read_only = gpio_get_value(slot->wp_pin);
dev_dbg(&mmc->class_dev, "card is %s\n",
read_only ? "read-only" : "read-write");
- } else {
- dev_dbg(&mmc->class_dev,
- "no pin for checking read-only switch."
- " Assuming write-enable.\n");
}
return read_only;
}
-static struct mmc_host_ops atmci_ops = {
+static int atmci_get_cd(struct mmc_host *mmc)
+{
+ int present = -ENOSYS;
+ struct atmel_mci_slot *slot = mmc_priv(mmc);
+
+ if (gpio_is_valid(slot->detect_pin)) {
+ present = !gpio_get_value(slot->detect_pin);
+ dev_dbg(&mmc->class_dev, "card is %spresent\n",
+ present ? "" : "not ");
+ }
+
+ return present;
+}
+
+static const struct mmc_host_ops atmci_ops = {
.request = atmci_request,
.set_ios = atmci_set_ios,
.get_ro = atmci_get_ro,
+ .get_cd = atmci_get_cd,
};
+/* Called with host->lock held */
+static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq)
+ __releases(&host->lock)
+ __acquires(&host->lock)
+{
+ struct atmel_mci_slot *slot = NULL;
+ struct mmc_host *prev_mmc = host->cur_slot->mmc;
+
+ WARN_ON(host->cmd || host->data);
+
+ /*
+ * Update the MMC clock rate if necessary. This may be
+ * necessary if set_ios() is called when a different slot is
+ * busy transfering data.
+ */
+ if (host->need_clock_update)
+ mci_writel(host, MR, host->mode_reg);
+
+ host->cur_slot->mrq = NULL;
+ host->mrq = NULL;
+ if (!list_empty(&host->queue)) {
+ slot = list_entry(host->queue.next,
+ struct atmel_mci_slot, queue_node);
+ list_del(&slot->queue_node);
+ dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n",
+ mmc_hostname(slot->mmc));
+ host->state = STATE_SENDING_CMD;
+ atmci_start_request(host, slot);
+ } else {
+ dev_vdbg(&host->pdev->dev, "list empty\n");
+ host->state = STATE_IDLE;
+ }
+
+ spin_unlock(&host->lock);
+ mmc_request_done(prev_mmc, mrq);
+ spin_lock(&host->lock);
+}
+
static void atmci_command_complete(struct atmel_mci *host,
- struct mmc_command *cmd, u32 status)
+ struct mmc_command *cmd)
{
+ u32 status = host->cmd_status;
+
/* Read the response from the card (up to 16 bytes) */
cmd->resp[0] = mci_readl(host, RSPR);
cmd->resp[1] = mci_readl(host, RSPR);
@@ -612,11 +1001,12 @@ static void atmci_command_complete(struct atmel_mci *host,
cmd->error = 0;
if (cmd->error) {
- dev_dbg(&host->mmc->class_dev,
+ dev_dbg(&host->pdev->dev,
"command error: status=0x%08x\n", status);
if (cmd->data) {
host->data = NULL;
+ atmci_stop_dma(host);
mci_writel(host, IDR, MCI_NOTBUSY
| MCI_TXRDY | MCI_RXRDY
| ATMCI_DATA_ERROR_FLAGS);
@@ -626,146 +1016,222 @@ static void atmci_command_complete(struct atmel_mci *host,
static void atmci_detect_change(unsigned long data)
{
- struct atmel_mci *host = (struct atmel_mci *)data;
- struct mmc_request *mrq = host->mrq;
- int present;
+ struct atmel_mci_slot *slot = (struct atmel_mci_slot *)data;
+ bool present;
+ bool present_old;
/*
- * atmci_remove() sets detect_pin to -1 before freeing the
- * interrupt. We must not re-enable the interrupt if it has
- * been freed.
+ * atmci_cleanup_slot() sets the ATMCI_SHUTDOWN flag before
+ * freeing the interrupt. We must not re-enable the interrupt
+ * if it has been freed, and if we're shutting down, it
+ * doesn't really matter whether the card is present or not.
*/
smp_rmb();
- if (!gpio_is_valid(host->detect_pin))
+ if (test_bit(ATMCI_SHUTDOWN, &slot->flags))
return;
- enable_irq(gpio_to_irq(host->detect_pin));
- present = !gpio_get_value(host->detect_pin);
+ enable_irq(gpio_to_irq(slot->detect_pin));
+ present = !gpio_get_value(slot->detect_pin);
+ present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags);
- dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n",
- present, host->present);
+ dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n",
+ present, present_old);
- if (present != host->present) {
- dev_dbg(&host->mmc->class_dev, "card %s\n",
+ if (present != present_old) {
+ struct atmel_mci *host = slot->host;
+ struct mmc_request *mrq;
+
+ dev_dbg(&slot->mmc->class_dev, "card %s\n",
present ? "inserted" : "removed");
- host->present = present;
- /* Reset controller if card is gone */
- if (!present) {
- mci_writel(host, CR, MCI_CR_SWRST);
- mci_writel(host, IDR, ~0UL);
- mci_writel(host, CR, MCI_CR_MCIEN);
- }
+ spin_lock(&host->lock);
+
+ if (!present)
+ clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
+ else
+ set_bit(ATMCI_CARD_PRESENT, &slot->flags);
/* Clean up queue if present */
+ mrq = slot->mrq;
if (mrq) {
- /*
- * Reset controller to terminate any ongoing
- * commands or data transfers.
- */
- mci_writel(host, CR, MCI_CR_SWRST);
-
- if (!atmci_is_completed(host, EVENT_CMD_COMPLETE))
- mrq->cmd->error = -ENOMEDIUM;
+ if (mrq == host->mrq) {
+ /*
+ * Reset controller to terminate any ongoing
+ * commands or data transfers.
+ */
+ mci_writel(host, CR, MCI_CR_SWRST);
+ mci_writel(host, CR, MCI_CR_MCIEN);
+ mci_writel(host, MR, host->mode_reg);
- if (mrq->data && !atmci_is_completed(host,
- EVENT_DATA_COMPLETE)) {
host->data = NULL;
- mrq->data->error = -ENOMEDIUM;
+ host->cmd = NULL;
+
+ switch (host->state) {
+ case STATE_IDLE:
+ break;
+ case STATE_SENDING_CMD:
+ mrq->cmd->error = -ENOMEDIUM;
+ if (!mrq->data)
+ break;
+ /* fall through */
+ case STATE_SENDING_DATA:
+ mrq->data->error = -ENOMEDIUM;
+ atmci_stop_dma(host);
+ break;
+ case STATE_DATA_BUSY:
+ case STATE_DATA_ERROR:
+ if (mrq->data->error == -EINPROGRESS)
+ mrq->data->error = -ENOMEDIUM;
+ if (!mrq->stop)
+ break;
+ /* fall through */
+ case STATE_SENDING_STOP:
+ mrq->stop->error = -ENOMEDIUM;
+ break;
+ }
+
+ atmci_request_end(host, mrq);
+ } else {
+ list_del(&slot->queue_node);
+ mrq->cmd->error = -ENOMEDIUM;
+ if (mrq->data)
+ mrq->data->error = -ENOMEDIUM;
+ if (mrq->stop)
+ mrq->stop->error = -ENOMEDIUM;
+
+ spin_unlock(&host->lock);
+ mmc_request_done(slot->mmc, mrq);
+ spin_lock(&host->lock);
}
- if (mrq->stop && !atmci_is_completed(host,
- EVENT_STOP_COMPLETE))
- mrq->stop->error = -ENOMEDIUM;
-
- host->cmd = NULL;
- atmci_request_end(host->mmc, mrq);
}
+ spin_unlock(&host->lock);
- mmc_detect_change(host->mmc, 0);
+ mmc_detect_change(slot->mmc, 0);
}
}
static void atmci_tasklet_func(unsigned long priv)
{
- struct mmc_host *mmc = (struct mmc_host *)priv;
- struct atmel_mci *host = mmc_priv(mmc);
+ struct atmel_mci *host = (struct atmel_mci *)priv;
struct mmc_request *mrq = host->mrq;
struct mmc_data *data = host->data;
+ struct mmc_command *cmd = host->cmd;
+ enum atmel_mci_state state = host->state;
+ enum atmel_mci_state prev_state;
+ u32 status;
- dev_vdbg(&mmc->class_dev,
- "tasklet: pending/completed/mask %lx/%lx/%x\n",
- host->pending_events, host->completed_events,
+ spin_lock(&host->lock);
+
+ state = host->state;
+
+ dev_vdbg(&host->pdev->dev,
+ "tasklet: state %u pending/completed/mask %lx/%lx/%x\n",
+ state, host->pending_events, host->completed_events,
mci_readl(host, IMR));
- if (atmci_test_and_clear_pending(host, EVENT_CMD_COMPLETE)) {
- /*
- * host->cmd must be set to NULL before the interrupt
- * handler sees EVENT_CMD_COMPLETE
- */
- host->cmd = NULL;
- smp_wmb();
- atmci_set_completed(host, EVENT_CMD_COMPLETE);
- atmci_command_complete(host, mrq->cmd, host->cmd_status);
-
- if (!mrq->cmd->error && mrq->stop
- && atmci_is_completed(host, EVENT_XFER_COMPLETE)
- && !atmci_test_and_set_completed(host,
- EVENT_STOP_SENT))
- send_stop_cmd(host->mmc, mrq->data);
- }
- if (atmci_test_and_clear_pending(host, EVENT_STOP_COMPLETE)) {
- /*
- * host->cmd must be set to NULL before the interrupt
- * handler sees EVENT_STOP_COMPLETE
- */
- host->cmd = NULL;
- smp_wmb();
- atmci_set_completed(host, EVENT_STOP_COMPLETE);
- atmci_command_complete(host, mrq->stop, host->stop_status);
- }
- if (atmci_test_and_clear_pending(host, EVENT_DATA_ERROR)) {
- u32 status = host->data_status;
+ do {
+ prev_state = state;
- dev_vdbg(&mmc->class_dev, "data error: status=%08x\n", status);
+ switch (state) {
+ case STATE_IDLE:
+ break;
- atmci_set_completed(host, EVENT_DATA_ERROR);
- atmci_set_completed(host, EVENT_DATA_COMPLETE);
+ case STATE_SENDING_CMD:
+ if (!atmci_test_and_clear_pending(host,
+ EVENT_CMD_COMPLETE))
+ break;
- if (status & MCI_DTOE) {
- dev_dbg(&mmc->class_dev,
- "data timeout error\n");
- data->error = -ETIMEDOUT;
- } else if (status & MCI_DCRCE) {
- dev_dbg(&mmc->class_dev, "data CRC error\n");
- data->error = -EILSEQ;
- } else {
- dev_dbg(&mmc->class_dev,
- "data FIFO error (status=%08x)\n",
- status);
- data->error = -EIO;
- }
+ host->cmd = NULL;
+ atmci_set_completed(host, EVENT_CMD_COMPLETE);
+ atmci_command_complete(host, mrq->cmd);
+ if (!mrq->data || cmd->error) {
+ atmci_request_end(host, host->mrq);
+ goto unlock;
+ }
- if (host->present && data->stop
- && atmci_is_completed(host, EVENT_CMD_COMPLETE)
- && !atmci_test_and_set_completed(
- host, EVENT_STOP_SENT))
- send_stop_cmd(host->mmc, data);
+ prev_state = state = STATE_SENDING_DATA;
+ /* fall through */
+
+ case STATE_SENDING_DATA:
+ if (atmci_test_and_clear_pending(host,
+ EVENT_DATA_ERROR)) {
+ atmci_stop_dma(host);
+ if (data->stop)
+ send_stop_cmd(host, data);
+ state = STATE_DATA_ERROR;
+ break;
+ }
- host->data = NULL;
- }
- if (atmci_test_and_clear_pending(host, EVENT_DATA_COMPLETE)) {
- atmci_set_completed(host, EVENT_DATA_COMPLETE);
+ if (!atmci_test_and_clear_pending(host,
+ EVENT_XFER_COMPLETE))
+ break;
+
+ atmci_set_completed(host, EVENT_XFER_COMPLETE);
+ prev_state = state = STATE_DATA_BUSY;
+ /* fall through */
- if (!atmci_is_completed(host, EVENT_DATA_ERROR)) {
- data->bytes_xfered = data->blocks * data->blksz;
- data->error = 0;
+ case STATE_DATA_BUSY:
+ if (!atmci_test_and_clear_pending(host,
+ EVENT_DATA_COMPLETE))
+ break;
+
+ host->data = NULL;
+ atmci_set_completed(host, EVENT_DATA_COMPLETE);
+ status = host->data_status;
+ if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) {
+ if (status & MCI_DTOE) {
+ dev_dbg(&host->pdev->dev,
+ "data timeout error\n");
+ data->error = -ETIMEDOUT;
+ } else if (status & MCI_DCRCE) {
+ dev_dbg(&host->pdev->dev,
+ "data CRC error\n");
+ data->error = -EILSEQ;
+ } else {
+ dev_dbg(&host->pdev->dev,
+ "data FIFO error (status=%08x)\n",
+ status);
+ data->error = -EIO;
+ }
+ } else {
+ data->bytes_xfered = data->blocks * data->blksz;
+ data->error = 0;
+ }
+
+ if (!data->stop) {
+ atmci_request_end(host, host->mrq);
+ goto unlock;
+ }
+
+ prev_state = state = STATE_SENDING_STOP;
+ if (!data->error)
+ send_stop_cmd(host, data);
+ /* fall through */
+
+ case STATE_SENDING_STOP:
+ if (!atmci_test_and_clear_pending(host,
+ EVENT_CMD_COMPLETE))
+ break;
+
+ host->cmd = NULL;
+ atmci_command_complete(host, mrq->stop);
+ atmci_request_end(host, host->mrq);
+ goto unlock;
+
+ case STATE_DATA_ERROR:
+ if (!atmci_test_and_clear_pending(host,
+ EVENT_XFER_COMPLETE))
+ break;
+
+ state = STATE_DATA_BUSY;
+ break;
}
+ } while (state != prev_state);
- host->data = NULL;
- }
+ host->state = state;
- if (host->mrq && !host->cmd && !host->data)
- atmci_request_end(mmc, host->mrq);
+unlock:
+ spin_unlock(&host->lock);
}
static void atmci_read_data_pio(struct atmel_mci *host)
@@ -787,6 +1253,7 @@ static void atmci_read_data_pio(struct atmel_mci *host)
nbytes += 4;
if (offset == sg->length) {
+ flush_dcache_page(sg_page(sg));
host->sg = sg = sg_next(sg);
if (!sg)
goto done;
@@ -815,9 +1282,11 @@ static void atmci_read_data_pio(struct atmel_mci *host)
mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY
| ATMCI_DATA_ERROR_FLAGS));
host->data_status = status;
+ data->bytes_xfered += nbytes;
+ smp_wmb();
atmci_set_pending(host, EVENT_DATA_ERROR);
tasklet_schedule(&host->tasklet);
- break;
+ return;
}
} while (status & MCI_RXRDY);
@@ -830,10 +1299,8 @@ done:
mci_writel(host, IDR, MCI_RXRDY);
mci_writel(host, IER, MCI_NOTBUSY);
data->bytes_xfered += nbytes;
- atmci_set_completed(host, EVENT_XFER_COMPLETE);
- if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE)
- && !atmci_test_and_set_completed(host, EVENT_STOP_SENT))
- send_stop_cmd(host->mmc, data);
+ smp_wmb();
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
}
static void atmci_write_data_pio(struct atmel_mci *host)
@@ -886,9 +1353,11 @@ static void atmci_write_data_pio(struct atmel_mci *host)
mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY
| ATMCI_DATA_ERROR_FLAGS));
host->data_status = status;
+ data->bytes_xfered += nbytes;
+ smp_wmb();
atmci_set_pending(host, EVENT_DATA_ERROR);
tasklet_schedule(&host->tasklet);
- break;
+ return;
}
} while (status & MCI_TXRDY);
@@ -901,38 +1370,26 @@ done:
mci_writel(host, IDR, MCI_TXRDY);
mci_writel(host, IER, MCI_NOTBUSY);
data->bytes_xfered += nbytes;
- atmci_set_completed(host, EVENT_XFER_COMPLETE);
- if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE)
- && !atmci_test_and_set_completed(host, EVENT_STOP_SENT))
- send_stop_cmd(host->mmc, data);
+ smp_wmb();
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
}
-static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
+static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status)
{
- struct atmel_mci *host = mmc_priv(mmc);
-
mci_writel(host, IDR, MCI_CMDRDY);
- if (atmci_is_completed(host, EVENT_STOP_SENT)) {
- host->stop_status = status;
- atmci_set_pending(host, EVENT_STOP_COMPLETE);
- } else {
- host->cmd_status = status;
- atmci_set_pending(host, EVENT_CMD_COMPLETE);
- }
-
+ host->cmd_status = status;
+ smp_wmb();
+ atmci_set_pending(host, EVENT_CMD_COMPLETE);
tasklet_schedule(&host->tasklet);
}
static irqreturn_t atmci_interrupt(int irq, void *dev_id)
{
- struct mmc_host *mmc = dev_id;
- struct atmel_mci *host = mmc_priv(mmc);
+ struct atmel_mci *host = dev_id;
u32 status, mask, pending;
unsigned int pass_count = 0;
- spin_lock(&mmc->lock);
-
do {
status = mci_readl(host, SR);
mask = mci_readl(host, IMR);
@@ -944,13 +1401,18 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS
| MCI_RXRDY | MCI_TXRDY);
pending &= mci_readl(host, IMR);
+
host->data_status = status;
+ smp_wmb();
atmci_set_pending(host, EVENT_DATA_ERROR);
tasklet_schedule(&host->tasklet);
}
if (pending & MCI_NOTBUSY) {
- mci_writel(host, IDR, (MCI_NOTBUSY
- | ATMCI_DATA_ERROR_FLAGS));
+ mci_writel(host, IDR,
+ ATMCI_DATA_ERROR_FLAGS | MCI_NOTBUSY);
+ if (!host->data_status)
+ host->data_status = status;
+ smp_wmb();
atmci_set_pending(host, EVENT_DATA_COMPLETE);
tasklet_schedule(&host->tasklet);
}
@@ -960,18 +1422,15 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
atmci_write_data_pio(host);
if (pending & MCI_CMDRDY)
- atmci_cmd_interrupt(mmc, status);
+ atmci_cmd_interrupt(host, status);
} while (pass_count++ < 5);
- spin_unlock(&mmc->lock);
-
return pass_count ? IRQ_HANDLED : IRQ_NONE;
}
static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
{
- struct mmc_host *mmc = dev_id;
- struct atmel_mci *host = mmc_priv(mmc);
+ struct atmel_mci_slot *slot = dev_id;
/*
* Disable interrupts until the pin has stabilized and check
@@ -979,19 +1438,176 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
* middle of the timer routine when this interrupt triggers.
*/
disable_irq_nosync(irq);
- mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20));
+ mod_timer(&slot->detect_timer, jiffies + msecs_to_jiffies(20));
return IRQ_HANDLED;
}
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+
+static inline struct atmel_mci *
+dma_client_to_atmel_mci(struct dma_client *client)
+{
+ return container_of(client, struct atmel_mci, dma.client);
+}
+
+static enum dma_state_client atmci_dma_event(struct dma_client *client,
+ struct dma_chan *chan, enum dma_state state)
+{
+ struct atmel_mci *host;
+ enum dma_state_client ret = DMA_NAK;
+
+ host = dma_client_to_atmel_mci(client);
+
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ spin_lock_bh(&host->lock);
+ if (!host->dma.chan) {
+ host->dma.chan = chan;
+ ret = DMA_ACK;
+ }
+ spin_unlock_bh(&host->lock);
+
+ if (ret == DMA_ACK)
+ dev_info(&host->pdev->dev,
+ "Using %s for DMA transfers\n",
+ chan->dev.bus_id);
+ break;
+
+ case DMA_RESOURCE_REMOVED:
+ spin_lock_bh(&host->lock);
+ if (host->dma.chan == chan) {
+ host->dma.chan = NULL;
+ ret = DMA_ACK;
+ }
+ spin_unlock_bh(&host->lock);
+
+ if (ret == DMA_ACK)
+ dev_info(&host->pdev->dev,
+ "Lost %s, falling back to PIO\n",
+ chan->dev.bus_id);
+ break;
+
+ default:
+ break;
+ }
+
+
+ return ret;
+}
+#endif /* CONFIG_MMC_ATMELMCI_DMA */
+
+static int __init atmci_init_slot(struct atmel_mci *host,
+ struct mci_slot_pdata *slot_data, unsigned int id,
+ u32 sdc_reg)
+{
+ struct mmc_host *mmc;
+ struct atmel_mci_slot *slot;
+
+ mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev);
+ if (!mmc)
+ return -ENOMEM;
+
+ slot = mmc_priv(mmc);
+ slot->mmc = mmc;
+ slot->host = host;
+ slot->detect_pin = slot_data->detect_pin;
+ slot->wp_pin = slot_data->wp_pin;
+ slot->sdc_reg = sdc_reg;
+
+ mmc->ops = &atmci_ops;
+ mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
+ mmc->f_max = host->bus_hz / 2;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+ if (slot_data->bus_width >= 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ mmc->max_hw_segs = 64;
+ mmc->max_phys_segs = 64;
+ mmc->max_req_size = 32768 * 512;
+ mmc->max_blk_size = 32768;
+ mmc->max_blk_count = 512;
+
+ /* Assume card is present initially */
+ set_bit(ATMCI_CARD_PRESENT, &slot->flags);
+ if (gpio_is_valid(slot->detect_pin)) {
+ if (gpio_request(slot->detect_pin, "mmc_detect")) {
+ dev_dbg(&mmc->class_dev, "no detect pin available\n");
+ slot->detect_pin = -EBUSY;
+ } else if (gpio_get_value(slot->detect_pin)) {
+ clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
+ }
+ }
+
+ if (!gpio_is_valid(slot->detect_pin))
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+ if (gpio_is_valid(slot->wp_pin)) {
+ if (gpio_request(slot->wp_pin, "mmc_wp")) {
+ dev_dbg(&mmc->class_dev, "no WP pin available\n");
+ slot->wp_pin = -EBUSY;
+ }
+ }
+
+ host->slot[id] = slot;
+ mmc_add_host(mmc);
+
+ if (gpio_is_valid(slot->detect_pin)) {
+ int ret;
+
+ setup_timer(&slot->detect_timer, atmci_detect_change,
+ (unsigned long)slot);
+
+ ret = request_irq(gpio_to_irq(slot->detect_pin),
+ atmci_detect_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "mmc-detect", slot);
+ if (ret) {
+ dev_dbg(&mmc->class_dev,
+ "could not request IRQ %d for detect pin\n",
+ gpio_to_irq(slot->detect_pin));
+ gpio_free(slot->detect_pin);
+ slot->detect_pin = -EBUSY;
+ }
+ }
+
+ atmci_init_debugfs(slot);
+
+ return 0;
+}
+
+static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
+ unsigned int id)
+{
+ /* Debugfs stuff is cleaned up by mmc core */
+
+ set_bit(ATMCI_SHUTDOWN, &slot->flags);
+ smp_wmb();
+
+ mmc_remove_host(slot->mmc);
+
+ if (gpio_is_valid(slot->detect_pin)) {
+ int pin = slot->detect_pin;
+
+ free_irq(gpio_to_irq(pin), slot);
+ del_timer_sync(&slot->detect_timer);
+ gpio_free(pin);
+ }
+ if (gpio_is_valid(slot->wp_pin))
+ gpio_free(slot->wp_pin);
+
+ slot->host->slot[id] = NULL;
+ mmc_free_host(slot->mmc);
+}
+
static int __init atmci_probe(struct platform_device *pdev)
{
struct mci_platform_data *pdata;
- struct atmel_mci *host;
- struct mmc_host *mmc;
- struct resource *regs;
- int irq;
- int ret;
+ struct atmel_mci *host;
+ struct resource *regs;
+ unsigned int nr_slots;
+ int irq;
+ int ret;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs)
@@ -1003,15 +1619,13 @@ static int __init atmci_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
- if (!mmc)
+ host = kzalloc(sizeof(struct atmel_mci), GFP_KERNEL);
+ if (!host)
return -ENOMEM;
- host = mmc_priv(mmc);
host->pdev = pdev;
- host->mmc = mmc;
- host->detect_pin = pdata->detect_pin;
- host->wp_pin = pdata->wp_pin;
+ spin_lock_init(&host->lock);
+ INIT_LIST_HEAD(&host->queue);
host->mck = clk_get(&pdev->dev, "mci_clk");
if (IS_ERR(host->mck)) {
@@ -1031,118 +1645,102 @@ static int __init atmci_probe(struct platform_device *pdev)
host->mapbase = regs->start;
- mmc->ops = &atmci_ops;
- mmc->f_min = (host->bus_hz + 511) / 512;
- mmc->f_max = host->bus_hz / 2;
- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-
- mmc->max_hw_segs = 64;
- mmc->max_phys_segs = 64;
- mmc->max_req_size = 32768 * 512;
- mmc->max_blk_size = 32768;
- mmc->max_blk_count = 512;
-
- tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc);
+ tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host);
- ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, mmc);
+ ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, host);
if (ret)
goto err_request_irq;
- /* Assume card is present if we don't have a detect pin */
- host->present = 1;
- if (gpio_is_valid(host->detect_pin)) {
- if (gpio_request(host->detect_pin, "mmc_detect")) {
- dev_dbg(&mmc->class_dev, "no detect pin available\n");
- host->detect_pin = -1;
- } else {
- host->present = !gpio_get_value(host->detect_pin);
- }
- }
- if (gpio_is_valid(host->wp_pin)) {
- if (gpio_request(host->wp_pin, "mmc_wp")) {
- dev_dbg(&mmc->class_dev, "no WP pin available\n");
- host->wp_pin = -1;
- }
- }
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+ if (pdata->dma_slave) {
+ struct dma_slave *slave = pdata->dma_slave;
- platform_set_drvdata(pdev, host);
+ slave->tx_reg = regs->start + MCI_TDR;
+ slave->rx_reg = regs->start + MCI_RDR;
- mmc_add_host(mmc);
+ /* Try to grab a DMA channel */
+ host->dma.client.event_callback = atmci_dma_event;
+ dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask);
+ host->dma.client.slave = slave;
- if (gpio_is_valid(host->detect_pin)) {
- setup_timer(&host->detect_timer, atmci_detect_change,
- (unsigned long)host);
+ dma_async_client_register(&host->dma.client);
+ dma_async_client_chan_request(&host->dma.client);
+ } else {
+ dev_notice(&pdev->dev, "DMA not available, using PIO\n");
+ }
+#endif /* CONFIG_MMC_ATMELMCI_DMA */
- ret = request_irq(gpio_to_irq(host->detect_pin),
- atmci_detect_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "mmc-detect", mmc);
- if (ret) {
- dev_dbg(&mmc->class_dev,
- "could not request IRQ %d for detect pin\n",
- gpio_to_irq(host->detect_pin));
- gpio_free(host->detect_pin);
- host->detect_pin = -1;
- }
+ platform_set_drvdata(pdev, host);
+
+ /* We need at least one slot to succeed */
+ nr_slots = 0;
+ ret = -ENODEV;
+ if (pdata->slot[0].bus_width) {
+ ret = atmci_init_slot(host, &pdata->slot[0],
+ MCI_SDCSEL_SLOT_A, 0);
+ if (!ret)
+ nr_slots++;
+ }
+ if (pdata->slot[1].bus_width) {
+ ret = atmci_init_slot(host, &pdata->slot[1],
+ MCI_SDCSEL_SLOT_B, 1);
+ if (!ret)
+ nr_slots++;
}
- dev_info(&mmc->class_dev,
- "Atmel MCI controller at 0x%08lx irq %d\n",
- host->mapbase, irq);
+ if (!nr_slots)
+ goto err_init_slot;
- atmci_init_debugfs(host);
+ dev_info(&pdev->dev,
+ "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
+ host->mapbase, irq, nr_slots);
return 0;
+err_init_slot:
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+ if (pdata->dma_slave)
+ dma_async_client_unregister(&host->dma.client);
+#endif
+ free_irq(irq, host);
err_request_irq:
iounmap(host->regs);
err_ioremap:
clk_put(host->mck);
err_clk_get:
- mmc_free_host(mmc);
+ kfree(host);
return ret;
}
static int __exit atmci_remove(struct platform_device *pdev)
{
- struct atmel_mci *host = platform_get_drvdata(pdev);
+ struct atmel_mci *host = platform_get_drvdata(pdev);
+ unsigned int i;
platform_set_drvdata(pdev, NULL);
- if (host) {
- /* Debugfs stuff is cleaned up by mmc core */
-
- if (gpio_is_valid(host->detect_pin)) {
- int pin = host->detect_pin;
-
- /* Make sure the timer doesn't enable the interrupt */
- host->detect_pin = -1;
- smp_wmb();
-
- free_irq(gpio_to_irq(pin), host->mmc);
- del_timer_sync(&host->detect_timer);
- gpio_free(pin);
- }
-
- mmc_remove_host(host->mmc);
+ for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ if (host->slot[i])
+ atmci_cleanup_slot(host->slot[i], i);
+ }
- clk_enable(host->mck);
- mci_writel(host, IDR, ~0UL);
- mci_writel(host, CR, MCI_CR_MCIDIS);
- mci_readl(host, SR);
- clk_disable(host->mck);
+ clk_enable(host->mck);
+ mci_writel(host, IDR, ~0UL);
+ mci_writel(host, CR, MCI_CR_MCIDIS);
+ mci_readl(host, SR);
+ clk_disable(host->mck);
- if (gpio_is_valid(host->wp_pin))
- gpio_free(host->wp_pin);
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+ if (host->dma.client.slave)
+ dma_async_client_unregister(&host->dma.client);
+#endif
- free_irq(platform_get_irq(pdev, 0), host->mmc);
- iounmap(host->regs);
+ free_irq(platform_get_irq(pdev, 0), host);
+ iounmap(host->regs);
- clk_put(host->mck);
+ clk_put(host->mck);
+ kfree(host);
- mmc_free_host(host->mmc);
- }
return 0;
}
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 7503b81374e..07faf5412a1 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -95,8 +95,6 @@
* reads which takes nowhere near that long. Older cards may be able to use
* shorter timeouts ... but why bother?
*/
-#define readblock_timeout ktime_set(0, 100 * 1000 * 1000)
-#define writeblock_timeout ktime_set(0, 250 * 1000 * 1000)
#define r1b_timeout ktime_set(3, 0)
@@ -220,9 +218,9 @@ mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
}
-static int mmc_spi_readtoken(struct mmc_spi_host *host)
+static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
{
- return mmc_spi_skip(host, readblock_timeout, 1, 0xff);
+ return mmc_spi_skip(host, timeout, 1, 0xff);
}
@@ -605,7 +603,8 @@ mmc_spi_setup_data_message(
* Return negative errno, else success.
*/
static int
-mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ ktime_t timeout)
{
struct spi_device *spi = host->spi;
int status, i;
@@ -673,7 +672,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
if (scratch->status[i] != 0)
return 0;
}
- return mmc_spi_wait_unbusy(host, writeblock_timeout);
+ return mmc_spi_wait_unbusy(host, timeout);
}
/*
@@ -693,7 +692,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
* STOP_TRANSMISSION command.
*/
static int
-mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ ktime_t timeout)
{
struct spi_device *spi = host->spi;
int status;
@@ -707,7 +707,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
return status;
status = scratch->status[0];
if (status == 0xff || status == 0)
- status = mmc_spi_readtoken(host);
+ status = mmc_spi_readtoken(host, timeout);
if (status == SPI_TOKEN_SINGLE) {
if (host->dma_dev) {
@@ -778,6 +778,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
struct scatterlist *sg;
unsigned n_sg;
int multiple = (data->blocks > 1);
+ u32 clock_rate;
+ ktime_t timeout;
if (data->flags & MMC_DATA_READ)
direction = DMA_FROM_DEVICE;
@@ -786,6 +788,14 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
mmc_spi_setup_data_message(host, multiple, direction);
t = &host->t;
+ if (t->speed_hz)
+ clock_rate = t->speed_hz;
+ else
+ clock_rate = spi->max_speed_hz;
+
+ timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns +
+ data->timeout_clks * 1000000 / clock_rate);
+
/* Handle scatterlist segments one at a time, with synch for
* each 512-byte block
*/
@@ -832,9 +842,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
t->len);
if (direction == DMA_TO_DEVICE)
- status = mmc_spi_writeblock(host, t);
+ status = mmc_spi_writeblock(host, t, timeout);
else
- status = mmc_spi_readblock(host, t);
+ status = mmc_spi_readblock(host, t, timeout);
if (status < 0)
break;
@@ -917,7 +927,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
if (scratch->status[tmp] != 0)
return;
}
- tmp = mmc_spi_wait_unbusy(host, writeblock_timeout);
+ tmp = mmc_spi_wait_unbusy(host, timeout);
if (tmp < 0 && !data->error)
data->error = tmp;
}
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index c16028872bb..1b9fc3c6b87 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -172,7 +172,7 @@ struct mmc_omap_host {
struct omap_mmc_platform_data *pdata;
};
-void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
+static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
{
unsigned long tick_ns;
@@ -182,7 +182,7 @@ void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
}
}
-void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
+static void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
{
unsigned long flags;
@@ -1455,7 +1455,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
host->irq = irq;
host->phys_base = host->mem_res->start;
- host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
+ host->virt_base = ioremap(res->start, res->end - res->start + 1);
+ if (!host->virt_base)
+ goto err_ioremap;
if (cpu_is_omap24xx()) {
host->iclk = clk_get(&pdev->dev, "mmc_ick");
@@ -1510,6 +1512,8 @@ err_free_iclk:
clk_put(host->iclk);
}
err_free_mmc_host:
+ iounmap(host->virt_base);
+err_ioremap:
kfree(host);
err_free_mem_region:
release_mem_region(res->start, res->end - res->start + 1);
@@ -1536,6 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
if (host->fclk && !IS_ERR(host->fclk))
clk_put(host->fclk);
+ iounmap(host->virt_base);
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 55093ad132c..ebfaa996093 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -520,7 +520,7 @@ static int pxamci_probe(struct platform_device *pdev)
/*
* Block length register is only 10 bits before PXA27x.
*/
- mmc->max_blk_size = (cpu_is_pxa21x() || cpu_is_pxa25x()) ? 1023 : 2048;
+ mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048;
/*
* Block count register is 16 bits.
@@ -554,7 +554,7 @@ static int pxamci_probe(struct platform_device *pdev)
MMC_VDD_32_33|MMC_VDD_33_34;
mmc->caps = 0;
host->cmdat = 0;
- if (!cpu_is_pxa21x() && !cpu_is_pxa25x()) {
+ if (!cpu_is_pxa25x()) {
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
host->cmdat |= CMDAT_SDIO_INT_EN;
if (cpu_is_pxa300() || cpu_is_pxa310())
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index fcb14c2346c..9bd7026b002 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -144,7 +144,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
SDHCI_QUIRK_32BIT_DMA_SIZE |
SDHCI_QUIRK_32BIT_ADMA_SIZE |
SDHCI_QUIRK_RESET_AFTER_REQUEST |
- SDHCI_QUIRK_BROKEN_SMALL_PIO;
+ SDHCI_QUIRK_BROKEN_SMALL_PIO |
+ SDHCI_QUIRK_FORCE_HIGHSPEED;
}
/*
@@ -326,7 +327,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_MARVELL,
- .device = PCI_DEVICE_ID_MARVELL_CAFE_SD,
+ .device = PCI_DEVICE_ID_MARVELL_88ALP01_SD,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (kernel_ulong_t)&sdhci_cafe,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index e3a8133560a..30f64b1f235 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
{
unsigned long flags;
size_t blksize, len, chunk;
- u32 scratch;
+ u32 uninitialized_var(scratch);
u8 *buf;
DBG("PIO reading\n");
@@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param)
spin_unlock_irqrestore(&host->lock, flags);
- mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+ mmc_detect_change(host->mmc, msecs_to_jiffies(200));
}
static void sdhci_tasklet_finish(unsigned long param)
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
SDHCI_INT_INDEX))
host->cmd->error = -EILSEQ;
- if (host->cmd->error)
+ if (host->cmd->error) {
tasklet_schedule(&host->finish_tasklet);
- else if (intmask & SDHCI_INT_RESPONSE)
+ return;
+ }
+
+ /*
+ * The host can send and interrupt when the busy state has
+ * ended, allowing us to wait without wasting CPU cycles.
+ * Unfortunately this is overloaded on the "data complete"
+ * interrupt, so we need to take some care when handling
+ * it.
+ *
+ * Note: The 1.0 specification is a bit ambiguous about this
+ * feature so there might be some problems with older
+ * controllers.
+ */
+ if (host->cmd->flags & MMC_RSP_BUSY) {
+ if (host->cmd->data)
+ DBG("Cannot wait for busy signal when also "
+ "doing a data transfer");
+ else
+ return;
+ }
+
+ if (intmask & SDHCI_INT_RESPONSE)
sdhci_finish_command(host);
}
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (!host->data) {
/*
- * A data end interrupt is sent together with the response
- * for the stop command.
+ * The "data complete" interrupt is also used to
+ * indicate that a busy state has ended. See comment
+ * above in sdhci_cmd_irq().
*/
- if (intmask & SDHCI_INT_DATA_END)
- return;
+ if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
+ if (intmask & SDHCI_INT_DATA_END) {
+ sdhci_finish_command(host);
+ return;
+ }
+ }
printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
"though no data operation was in progress.\n",
@@ -1604,7 +1631,8 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
- if (caps & SDHCI_CAN_DO_HISPD)
+ if ((caps & SDHCI_CAN_DO_HISPD) ||
+ (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
mmc->ocr_avail = 0;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 197d4a05f4a..31f4b1528e7 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -208,6 +208,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
/* Controller has an issue with buffer bits for small transfers */
#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
+/* Controller supports high speed but doesn't have the caps bit set */
+#define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14)
int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 9e647a06054..ba2b4240a86 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -159,10 +159,10 @@ static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host,
#define STATUS_TO_TEXT(a) \
do { \
if (status & TMIO_STAT_##a) \
- printf(#a); \
+ printk(#a); \
} while (0)
-void debug_status(u32 status)
+void pr_debug_status(u32 status)
{
printk(KERN_DEBUG "status: %08x = ", status);
STATUS_TO_TEXT(CARD_REMOVE);
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index f34f20c7891..9bf581c4f74 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1005,6 +1005,29 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
return ftl_write((void *)dev, buf, block, 1);
}
+static int ftl_discardsect(struct mtd_blktrans_dev *dev,
+ unsigned long sector, unsigned nr_sects)
+{
+ partition_t *part = (void *)dev;
+ uint32_t bsize = 1 << part->header.EraseUnitSize;
+
+ DEBUG(1, "FTL erase sector %ld for %d sectors\n",
+ sector, nr_sects);
+
+ while (nr_sects) {
+ uint32_t old_addr = part->VirtualBlockMap[sector];
+ if (old_addr != 0xffffffff) {
+ part->VirtualBlockMap[sector] = 0xffffffff;
+ part->EUNInfo[old_addr/bsize].Deleted++;
+ if (set_bam_entry(part, old_addr, 0))
+ return -EIO;
+ }
+ nr_sects--;
+ sector++;
+ }
+
+ return 0;
+}
/*====================================================================*/
static void ftl_freepart(partition_t *part)
@@ -1069,6 +1092,7 @@ static struct mtd_blktrans_ops ftl_tr = {
.blksize = SECTOR_SIZE,
.readsect = ftl_readsect,
.writesect = ftl_writesect,
+ .discard = ftl_discardsect,
.getgeo = ftl_getgeo,
.add_mtd = ftl_add_mtd,
.remove_dev = ftl_remove_dev,
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 90924fb0048..d600c2deff7 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -118,7 +118,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
dev->offset, mrq.CardOffset);
mrq.Page = 0;
- if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
+ ret = pcmcia_map_mem_page(win, &mrq);
+ if (ret != 0) {
cs_error(dev->p_dev, MapMemPage, ret);
return NULL;
}
@@ -326,9 +327,8 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
ret = pcmcia_modify_configuration(link, &mod);
- if(ret != CS_SUCCESS) {
+ if (ret != 0)
cs_error(link, ModifyConfiguration, ret);
- }
}
@@ -368,14 +368,14 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link,
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
rc = pcmcia_get_first_tuple(link, &tuple);
- while(rc == CS_SUCCESS) {
+ while (rc == 0) {
rc = pcmcia_get_tuple_data(link, &tuple);
- if(rc != CS_SUCCESS) {
+ if (rc != 0) {
cs_error(link, GetTupleData, rc);
break;
}
- rc = pcmcia_parse_tuple(link, &tuple, &parse);
- if(rc != CS_SUCCESS) {
+ rc = pcmcia_parse_tuple(&tuple, &parse);
+ if (rc != 0) {
cs_error(link, ParseTuple, rc);
break;
}
@@ -493,18 +493,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
int last_ret = 0, last_fn = 0;
int ret;
int i;
- config_info_t t;
static char *probes[] = { "jedec_probe", "cfi_probe" };
int new_name = 0;
DEBUG(3, "link=0x%p", link);
- DEBUG(2, "Validating CIS");
- ret = pcmcia_validate_cis(link, NULL);
- if(ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- }
-
card_settings(dev, link, &new_name);
dev->pcmcia_map.phys = NO_XIP;
@@ -571,10 +564,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
- DEBUG(2, "Getting configuration");
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
- DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
- dev->vpp = (vpp) ? vpp : t.Vpp1;
+ dev->vpp = (vpp) ? vpp : link->socket.socket.Vpp;
link->conf.Attributes = 0;
if(setvpp == 2) {
link->conf.Vpp = dev->vpp;
@@ -583,16 +573,10 @@ static int pcmciamtd_config(struct pcmcia_device *link)
}
link->conf.IntType = INT_MEMORY;
- link->conf.ConfigBase = t.ConfigBase;
- link->conf.Status = t.Status;
- link->conf.Pin = t.Pin;
- link->conf.Copy = t.Copy;
- link->conf.ExtStatus = t.ExtStatus;
link->conf.ConfigIndex = 0;
- link->conf.Present = t.Present;
DEBUG(2, "Setting Configuration");
ret = pcmcia_request_configuration(link, &link->conf);
- if(ret != CS_SUCCESS) {
+ if (ret != 0) {
cs_error(link, RequestConfiguration, ret);
if (dev->win_base) {
iounmap(dev->win_base);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 0d7c88396c8..fd7a1017399 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -1,13 +1,10 @@
-/*
- *
- * sun_uflash - Driver implementation for user-programmable flash
- * present on many Sun Microsystems SME boardsets.
+/* sun_uflash.c - Driver for user-programmable flash on
+ * Sun Microsystems SME boardsets.
*
* This driver does NOT provide access to the OBP-flash for
* safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
*
* Copyright (c) 2001 Eric Brower (ebrower@usa.net)
- *
*/
#include <linux/kernel.h>
@@ -16,8 +13,8 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <asm/ebus.h>
-#include <asm/oplib.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/prom.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -26,67 +23,65 @@
#include <linux/mtd/map.h>
#define UFLASH_OBPNAME "flashprom"
-#define UFLASH_DEVNAME "userflash"
+#define DRIVER_NAME "sun_uflash"
+#define PFX DRIVER_NAME ": "
#define UFLASH_WINDOW_SIZE 0x200000
#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets");
-MODULE_SUPPORTED_DEVICE("userflash");
+MODULE_SUPPORTED_DEVICE(DRIVER_NAME);
MODULE_LICENSE("GPL");
-MODULE_VERSION("2.0");
+MODULE_VERSION("2.1");
-static LIST_HEAD(device_list);
struct uflash_dev {
const char *name; /* device name */
struct map_info map; /* mtd map info */
struct mtd_info *mtd; /* mtd info */
};
-
struct map_info uflash_map_templ = {
.name = "SUNW,???-????",
.size = UFLASH_WINDOW_SIZE,
.bankwidth = UFLASH_BUSWIDTH,
};
-int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
+int uflash_devinit(struct of_device *op, struct device_node *dp)
{
struct uflash_dev *up;
- struct resource *res;
- res = &edev->resource[0];
-
- if (edev->num_addrs != 1) {
+ if (op->resource[1].flags) {
/* Non-CFI userflash device-- once I find one we
* can work on supporting it.
*/
- printk("%s: unsupported device at 0x%llx (%d regs): " \
- "email ebrower@usa.net\n",
- dp->full_name, (unsigned long long)res->start,
- edev->num_addrs);
+ printk(KERN_ERR PFX "Unsupported device at %s, 0x%llx\n",
+ dp->full_name, (unsigned long long)op->resource[0].start);
return -ENODEV;
}
up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL);
- if (!up)
+ if (!up) {
+ printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n");
return -ENOMEM;
+ }
/* copy defaults and tweak parameters */
memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ));
- up->map.size = (res->end - res->start) + 1UL;
+
+ up->map.size = resource_size(&op->resource[0]);
up->name = of_get_property(dp, "model", NULL);
if (up->name && 0 < strlen(up->name))
up->map.name = (char *)up->name;
- up->map.phys = res->start;
+ up->map.phys = op->resource[0].start;
- up->map.virt = ioremap_nocache(res->start, up->map.size);
+ up->map.virt = of_ioremap(&op->resource[0], 0, up->map.size,
+ DRIVER_NAME);
if (!up->map.virt) {
- printk("%s: Failed to map device.\n", dp->full_name);
+ printk(KERN_ERR PFX "Failed to map device.\n");
kfree(up);
return -EINVAL;
@@ -97,7 +92,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
/* MTD registration */
up->mtd = do_map_probe("cfi_probe", &up->map);
if (!up->mtd) {
- iounmap(up->map.virt);
+ of_iounmap(&op->resource[0], up->map.virt, up->map.size);
kfree(up);
return -ENXIO;
@@ -107,32 +102,34 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
add_mtd_device(up->mtd);
- dev_set_drvdata(&edev->ofdev.dev, up);
+ dev_set_drvdata(&op->dev, up);
return 0;
}
-static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match)
{
- struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
- struct device_node *dp = dev->node;
+ struct device_node *dp = op->node;
- if (of_find_property(dp, "user", NULL))
+ /* Flashprom must have the "user" property in order to
+ * be used by this driver.
+ */
+ if (!of_find_property(dp, "user", NULL))
return -ENODEV;
- return uflash_devinit(edev, dp);
+ return uflash_devinit(op, dp);
}
-static int __devexit uflash_remove(struct of_device *dev)
+static int __devexit uflash_remove(struct of_device *op)
{
- struct uflash_dev *up = dev_get_drvdata(&dev->dev);
+ struct uflash_dev *up = dev_get_drvdata(&op->dev);
if (up->mtd) {
del_mtd_device(up->mtd);
map_destroy(up->mtd);
}
if (up->map.virt) {
- iounmap(up->map.virt);
+ of_iounmap(&op->resource[0], up->map.virt, up->map.size);
up->map.virt = NULL;
}
@@ -141,7 +138,7 @@ static int __devexit uflash_remove(struct of_device *dev)
return 0;
}
-static struct of_device_id uflash_match[] = {
+static const struct of_device_id uflash_match[] = {
{
.name = UFLASH_OBPNAME,
},
@@ -151,7 +148,7 @@ static struct of_device_id uflash_match[] = {
MODULE_DEVICE_TABLE(of, uflash_match);
static struct of_platform_driver uflash_driver = {
- .name = UFLASH_DEVNAME,
+ .name = DRIVER_NAME,
.match_table = uflash_match,
.probe = uflash_probe,
.remove = __devexit_p(uflash_remove),
@@ -159,7 +156,7 @@ static struct of_platform_driver uflash_driver = {
static int __init uflash_init(void)
{
- return of_register_driver(&uflash_driver, &ebus_bus_type);
+ return of_register_driver(&uflash_driver, &of_bus_type);
}
static void __exit uflash_exit(void)
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 9ff007c4962..681d5aca2af 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -32,6 +32,14 @@ struct mtd_blkcore_priv {
spinlock_t queue_lock;
};
+static int blktrans_discard_request(struct request_queue *q,
+ struct request *req)
+{
+ req->cmd_type = REQ_TYPE_LINUX_BLOCK;
+ req->cmd[0] = REQ_LB_OP_DISCARD;
+ return 0;
+}
+
static int do_blktrans_request(struct mtd_blktrans_ops *tr,
struct mtd_blktrans_dev *dev,
struct request *req)
@@ -44,6 +52,10 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
buf = req->buffer;
+ if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
+ req->cmd[0] == REQ_LB_OP_DISCARD)
+ return !tr->discard(dev, block, nsect);
+
if (!blk_fs_request(req))
return 0;
@@ -367,6 +379,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
tr->blkcore_priv->rq->queuedata = tr;
blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
+ if (tr->discard)
+ blk_queue_set_discard(tr->blkcore_priv->rq,
+ blktrans_discard_request);
+
tr->blkshift = ffs(tr->blksize) - 1;
tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index d2f331876e4..1c74762dec8 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -26,13 +26,11 @@ static void mtd_notify_add(struct mtd_info* mtd)
if (!mtd)
return;
- device_create_drvdata(mtd_class, NULL,
- MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
- NULL, "mtd%d", mtd->index);
+ device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ NULL, "mtd%d", mtd->index);
- device_create_drvdata(mtd_class, NULL,
- MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
- NULL, "mtd%dro", mtd->index);
+ device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ NULL, "mtd%dro", mtd->index);
}
static void mtd_notify_remove(struct mtd_info* mtd)
@@ -410,16 +408,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
case MEMGETREGIONINFO:
{
- struct region_info_user ur;
+ uint32_t ur_idx;
+ struct mtd_erase_region_info *kr;
+ struct region_info_user *ur = (struct region_info_user *) argp;
- if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
+ if (get_user(ur_idx, &(ur->regionindex)))
return -EFAULT;
- if (ur.regionindex >= mtd->numeraseregions)
- return -EINVAL;
- if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
- sizeof(struct mtd_erase_region_info)))
+ kr = &(mtd->eraseregions[ur_idx]);
+
+ if (put_user(kr->offset, &(ur->offset))
+ || put_user(kr->erasesize, &(ur->erasesize))
+ || put_user(kr->numblocks, &(ur->numblocks)))
return -EFAULT;
+
break;
}
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index edb90b58a9b..9a06dc93ee0 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -564,10 +564,8 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
for ( ; ret <= 0 && *types; types++) {
parser = get_partition_parser(*types);
-#ifdef CONFIG_KMOD
if (!parser && !request_module("%s", *types))
parser = get_partition_parser(*types);
-#endif
if (!parser) {
printk(KERN_NOTICE "%s partition parsing not available\n",
*types);
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 257937cd99b..96238039485 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -691,7 +691,7 @@ static int alauda_probe(struct usb_interface *interface,
al[0].port = ALAUDA_PORT_XD;
al[1].port = ALAUDA_PORT_SM;
- info("alauda probed");
+ dev_info(&interface->dev, "alauda probed\n");
alauda_check_media(al);
alauda_check_media(al+1);
@@ -716,7 +716,7 @@ static void alauda_disconnect(struct usb_interface *interface)
if (al)
kref_put(&al->kref, alauda_delete);
- info("alauda gone");
+ dev_info(&interface->dev, "alauda gone");
}
static struct usb_driver alauda_driver = {
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 26d42987971..782994ead0e 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -145,7 +145,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
static int ams_delta_nand_ready(struct mtd_info *mtd)
{
- return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
+ return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
}
/*
@@ -185,7 +185,7 @@ static int __init ams_delta_init(void)
this->read_buf = ams_delta_read_buf;
this->verify_buf = ams_delta_verify_buf;
this->cmd_ctrl = ams_delta_hwcontrol;
- if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
+ if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
this->dev_ready = ams_delta_nand_ready;
} else {
this->dev_ready = NULL;
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
index 1ee7f993db1..578c776e135 100644
--- a/drivers/mtd/nand/atmel_nand_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -2,6 +2,9 @@
* Error Corrected Code Controller (ECC) - System peripherals regsters.
* Based on AT91SAM9260 datasheet revision B.
*
+ * Copyright (C) 2007 Andrew Victor
+ * Copyright (C) 2007 Atmel Corporation.
+ *
* 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
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 95345d05157..b8064bf3aee 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -1,6 +1,9 @@
/*
* Driver for One Laptop Per Child â€CAFÉ’ controller, aka Marvell 88ALP01
*
+ * The data sheet for this device can be found at:
+ * http://www.marvell.com/products/pcconn/88ALP01.jsp
+ *
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
*/
@@ -842,7 +845,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
}
static struct pci_device_id cafe_nand_tbl[] = {
- { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_88ALP01_NAND,
+ PCI_ANY_ID, PCI_ANY_ID },
{ }
};
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index 9eba3f04783..fa129c09bca 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -156,7 +156,7 @@ static int cmx270_init(void)
int mtd_parts_nb = 0;
int ret;
- if (!machine_is_armcore())
+ if (!(machine_is_armcore() && cpu_is_pxa27x()))
return -ENODEV;
ret = gpio_request(GPIO_NAND_CS, "NAND CS");
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index cbab654b03c..edb1e322113 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -109,7 +109,7 @@ struct tmio_nand {
void __iomem *ccr;
void __iomem *fcr;
- unsigned long fcr_phys;
+ unsigned long fcr_base;
unsigned int irq;
@@ -316,8 +316,8 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
tmio_iowrite8(0x81, tmio->ccr + CCR_ICC);
/* (10h)BaseAddress 0x1000 spba.spba2 */
- tmio_iowrite16(tmio->fcr_phys, tmio->ccr + CCR_BASE);
- tmio_iowrite16(tmio->fcr_phys >> 16, tmio->ccr + CCR_BASE + 16);
+ tmio_iowrite16(tmio->fcr_base, tmio->ccr + CCR_BASE);
+ tmio_iowrite16(tmio->fcr_base >> 16, tmio->ccr + CCR_BASE + 2);
/* (04h)Command Register I/O spcmd */
tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND);
@@ -395,7 +395,7 @@ static int tmio_probe(struct platform_device *dev)
goto err_iomap_ccr;
}
- tmio->fcr_phys = (unsigned long)fcr->start;
+ tmio->fcr_base = fcr->start & 0xfffff;
tmio->fcr = ioremap(fcr->start, fcr->end - fcr->start + 1);
if (!tmio->fcr) {
retval = -EIO;
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 5ba4bab6d43..7d15e7c6bca 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -17,7 +17,7 @@
Annapolis MD 21403
Fixed (again!) the missing interrupt locking on TX/RX shifting.
- Alan Cox <Alan.Cox@linux.org>
+ Alan Cox <alan@lxorguk.ukuu.org.uk>
Removed calls to init_etherdev since they are no longer needed, and
cleaned up modularization just a bit. The driver still allows only
@@ -29,16 +29,16 @@
the board. Now getting 150K/second FTP with a 3c501 card. Still playing
with a TX-TX optimisation to see if we can touch 180-200K/second as seems
theoretically maximum.
- 19950402 Alan Cox <Alan.Cox@linux.org>
+ 19950402 Alan Cox <alan@lxorguk.ukuu.org.uk>
Cleaned up for 2.3.x because we broke SMP now.
- 20000208 Alan Cox <alan@redhat.com>
+ 20000208 Alan Cox <alan@lxorguk.ukuu.org.uk>
Check up pass for 2.5. Nothing significant changed
- 20021009 Alan Cox <alan@redhat.com>
+ 20021009 Alan Cox <alan@lxorguk.ukuu.org.uk>
Fixed zero fill corner case
- 20030104 Alan Cox <alan@redhat.com>
+ 20030104 Alan Cox <alan@lxorguk.ukuu.org.uk>
For the avoidance of doubt the "preferred form" of this code is one which
@@ -104,7 +104,7 @@
static const char version[] =
- DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@redhat.com).\n";
+ DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@lxorguk.ukuu.org.uk).\n";
/*
* Braindamage remaining:
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index fdfb2b2cb73..a424869707a 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -130,12 +130,12 @@ static const char filename[] = __FILE__;
static const char timeout_msg[] = "*** timeout at %s:%s (line %d) ***\n";
#define TIMEOUT_MSG(lineno) \
- printk(timeout_msg, filename,__FUNCTION__,(lineno))
+ printk(timeout_msg, filename,__func__,(lineno))
static const char invalid_pcb_msg[] =
"*** invalid pcb length %d at %s:%s (line %d) ***\n";
#define INVALID_PCB_MSG(len) \
- printk(invalid_pcb_msg, (len),filename,__FUNCTION__,__LINE__)
+ printk(invalid_pcb_msg, (len),filename,__func__,__LINE__)
static char search_msg[] __initdata = KERN_INFO "%s: Looking for 3c505 adapter at address %#x...";
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index b9d097c9f6b..3a7bc524af3 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -40,7 +40,7 @@
v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
v1.15 1/31/98 Faster recovery for Tx errors. -djb
v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
- v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
+ v1.18 12Mar2001 Andrew Morton
- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
- Reviewed against 1.18 from scyld.com
v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index e4e3241628d..a0f8b6e2d0a 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -18,7 +18,7 @@
2001/11/17 - Added ethtool support (jgarzik)
- 2002/10/28 - Locking updates for 2.5 (alan@redhat.com)
+ 2002/10/28 - Locking updates for 2.5 (alan@lxorguk.ukuu.org.uk)
*/
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 6011d6fabef..85fa40a0a66 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -127,7 +127,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
(CP)->tx_tail - (CP)->tx_head - 1)
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#define RX_OFFSET 2
#define CP_INTERNAL_PHY 32
/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */
@@ -552,14 +551,14 @@ rx_status_loop:
printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
dev->name, rx_tail, status, len);
- buflen = cp->rx_buf_sz + RX_OFFSET;
- new_skb = dev_alloc_skb (buflen);
+ buflen = cp->rx_buf_sz + NET_IP_ALIGN;
+ new_skb = netdev_alloc_skb(dev, buflen);
if (!new_skb) {
dev->stats.rx_dropped++;
goto rx_next;
}
- skb_reserve(new_skb, RX_OFFSET);
+ skb_reserve(new_skb, NET_IP_ALIGN);
dma_unmap_single(&cp->pdev->dev, mapping,
buflen, PCI_DMA_FROMDEVICE);
@@ -1051,19 +1050,20 @@ static void cp_init_hw (struct cp_private *cp)
cpw8_f(Cfg9346, Cfg9346_Lock);
}
-static int cp_refill_rx (struct cp_private *cp)
+static int cp_refill_rx(struct cp_private *cp)
{
+ struct net_device *dev = cp->dev;
unsigned i;
for (i = 0; i < CP_RX_RING_SIZE; i++) {
struct sk_buff *skb;
dma_addr_t mapping;
- skb = dev_alloc_skb(cp->rx_buf_sz + RX_OFFSET);
+ skb = netdev_alloc_skb(dev, cp->rx_buf_sz + NET_IP_ALIGN);
if (!skb)
goto err_out;
- skb_reserve(skb, RX_OFFSET);
+ skb_reserve(skb, NET_IP_ALIGN);
mapping = dma_map_single(&cp->pdev->dev, skb->data,
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 8a5b0d293f7..0daf8c15e38 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -309,7 +309,7 @@ enum RTL8139_registers {
Cfg9346 = 0x50,
Config0 = 0x51,
Config1 = 0x52,
- FlashReg = 0x54,
+ TimerInt = 0x54,
MediaStatus = 0x58,
Config3 = 0x59,
Config4 = 0x5A, /* absent on RTL-8139A */
@@ -325,6 +325,7 @@ enum RTL8139_registers {
FIFOTMS = 0x70, /* FIFO Control and test. */
CSCR = 0x74, /* Chip Status and Configuration Register. */
PARA78 = 0x78,
+ FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */
PARA7c = 0x7c, /* Magic transceiver parameter register. */
Config5 = 0xD8, /* absent on RTL-8139A */
};
@@ -1722,13 +1723,18 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
}
spin_lock_irqsave(&tp->lock, flags);
+ /*
+ * Writing to TxStatus triggers a DMA transfer of the data
+ * copied to tp->tx_buf[entry] above. Use a memory barrier
+ * to make sure that the device sees the updated data.
+ */
+ wmb();
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
dev->trans_start = jiffies;
tp->cur_tx++;
- wmb();
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
@@ -2009,9 +2015,9 @@ no_early_rx:
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
- skb = dev_alloc_skb (pkt_size + 2);
+ skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN);
if (likely(skb)) {
- skb_reserve (skb, 2); /* 16 byte align the IP fields. */
+ skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */
#if RX_BUF_IDX == 3
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
#else
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4a11296a951..ad301ace608 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1386,7 +1386,8 @@ config FORCEDETH_NAPI
config CS89x0
tristate "CS89x0 support"
- depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
+ depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
+ || ARCH_IXDP2X01 || ARCH_PNX010X || MACH_MX31ADS)
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@@ -1397,6 +1398,11 @@ config CS89x0
To compile this driver as a module, choose M here. The module
will be called cs89x0.
+config CS89x0_NONISA_IRQ
+ def_bool y
+ depends on CS89x0 != n
+ depends on MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X || MACH_MX31ADS
+
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
depends on NET_PCI && PCI && MIPS
@@ -1813,7 +1819,7 @@ config FEC2
config FEC_MPC52xx
tristate "MPC52xx FEC driver"
- depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC
+ depends on PPC_MPC52xx && PPC_BESTCOMM_FEC
select CRC32
select PHYLIB
---help---
@@ -1840,6 +1846,17 @@ config NE_H8300
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
+config ATL2
+ tristate "Atheros L2 Fast Ethernet support"
+ depends on PCI
+ select CRC32
+ select MII
+ help
+ This driver supports the Atheros L2 fast ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl2.
+
source "drivers/net/fs_enet/Kconfig"
endif # NET_ETHERNET
@@ -1927,15 +1944,6 @@ config E1000
To compile this driver as a module, choose M here. The module
will be called e1000.
-config E1000_DISABLE_PACKET_SPLIT
- bool "Disable Packet Split for PCI express adapters"
- depends on E1000
- help
- Say Y here if you want to use the legacy receive path for PCI express
- hardware.
-
- If in doubt, say N.
-
config E1000E
tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
depends on PCI && (!SPARC32 || BROKEN)
@@ -2046,6 +2054,7 @@ config R8169
tristate "Realtek 8169 gigabit ethernet support"
depends on PCI
select CRC32
+ select MII
---help---
Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
@@ -2262,7 +2271,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "Marvell Discovery (643XX) and Orion ethernet support"
depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION
- select MII
+ select PHYLIB
help
This driver supports the gigabit ethernet MACs in the
Marvell Discovery PPC/MIPS chipset family (MV643XX) and
@@ -2281,12 +2290,13 @@ config QLA3XXX
will be called qla3xxx.
config ATL1
- tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ tristate "Atheros/Attansic L1 Gigabit Ethernet support"
+ depends on PCI
select CRC32
select MII
help
- This driver supports the Attansic L1 gigabit ethernet adapter.
+ This driver supports the Atheros/Attansic L1 gigabit ethernet
+ adapter.
To compile this driver as a module, choose M here. The module
will be called atl1.
@@ -2302,6 +2312,18 @@ config ATL1E
To compile this driver as a module, choose M here. The module
will be called atl1e.
+config JME
+ tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
+ depends on PCI
+ select CRC32
+ select MII
+ ---help---
+ This driver supports the PCI-Express gigabit ethernet adapters
+ based on JMicron JMC250 chipset.
+
+ To compile this driver as a module, choose M here. The module
+ will be called jme.
+
endif # NETDEV_1000
#
@@ -2377,6 +2399,13 @@ config EHEA
To compile the driver as a module, choose M here. The module
will be called ehea.
+config ENIC
+ tristate "Cisco 10G Ethernet NIC support"
+ depends on PCI && INET
+ select INET_LRO
+ help
+ This enables the support for the Cisco 10G Ethernet card.
+
config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
depends on PCI && INET
@@ -2396,6 +2425,11 @@ config IXGBE
To compile this driver as a module, choose M here. The module
will be called ixgbe.
+config IXGBE_DCA
+ bool
+ default y
+ depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
+
config IXGB
tristate "Intel(R) PRO/10GbE support"
depends on PCI
@@ -2443,6 +2477,11 @@ config MYRI10GE
To compile this driver as a module, choose M here. The module
will be called myri10ge.
+config MYRI10GE_DCA
+ bool
+ default y
+ depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
+
config NETXEN_NIC
tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
depends on PCI
@@ -2496,6 +2535,15 @@ config BNX2X
To compile this driver as a module, choose M here: the module
will be called bnx2x. This is recommended.
+config QLGE
+ tristate "QLogic QLGE 10Gb Ethernet Driver Support"
+ depends on PCI
+ help
+ This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called qlge.
+
source "drivers/net/sfc/Kconfig"
endif # NETDEV_10000
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7629c901721..fa2510b2e60 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,9 +15,12 @@ obj-$(CONFIG_EHEA) += ehea/
obj-$(CONFIG_CAN) += can/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL2) += atlx/
obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_TEHUTI) += tehuti.o
+obj-$(CONFIG_ENIC) += enic/
+obj-$(CONFIG_JME) += jme.o
gianfar_driver-objs := gianfar.o \
gianfar_ethtool.o \
@@ -111,7 +114,7 @@ obj-$(CONFIG_EL2) += 3c503.o 8390p.o
obj-$(CONFIG_NE2000) += ne.o 8390p.o
obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
obj-$(CONFIG_HPLAN) += hp.o 8390p.o
-obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
@@ -128,6 +131,7 @@ obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
obj-$(CONFIG_QLA3XXX) += qla3xxx.o
+obj-$(CONFIG_QLGE) += qlge/
obj-$(CONFIG_PPP) += ppp_generic.o
obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index a0b4c851607..735fc947640 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -4,7 +4,7 @@
* - Jay Schulist <jschlst@samba.org>
*
* With more than a little help from;
- * - Alan Cox <Alan.Cox@linux.org>
+ * - Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* Derived from:
* - skeleton.c: A network driver outline for linux.
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index bdc4c0bb56d..a5b07691e46 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -442,24 +442,24 @@ static int arcnet_open(struct net_device *dev)
BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse "
"DOS networking programs!\n");
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
if (ASTATUS() & RESETflag) {
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
ACOMMAND(CFLAGScmd | RESETclear);
}
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
/* make sure we're ready to receive IRQ's. */
AINTMASK(0);
udelay(1); /* give it time to set the mask before
* we reset it again. (may not even be
* necessary)
*/
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
lp->intmask = NORXflag | RECONflag;
AINTMASK(lp->intmask);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
netif_start_queue(dev);
@@ -670,14 +670,14 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
freeskb = 0;
}
- BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
+ BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS());
/* make sure we didn't ignore a TX IRQ while we were in here */
AINTMASK(0);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
lp->intmask |= TXFREEflag|EXCNAKflag;
AINTMASK(lp->intmask);
- BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
+ BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS());
spin_unlock_irqrestore(&lp->lock, flags);
if (freeskb) {
@@ -798,7 +798,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
diagstatus = (status >> 8) & 0xFF;
BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",
- __FILE__,__LINE__,__FUNCTION__,status);
+ __FILE__,__LINE__,__func__,status);
didsomething = 0;
/*
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 8b51313b130..70124a944e7 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -238,15 +238,15 @@ static int com20020_reset(struct net_device *dev, int really_reset)
u_char inbyte;
BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n",
- __FILE__,__LINE__,__FUNCTION__,dev,lp,dev->name);
+ __FILE__,__LINE__,__func__,dev,lp,dev->name);
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
dev->name, ASTATUS());
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
/* power-up defaults */
SETCONF;
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
if (really_reset) {
/* reset the card */
@@ -254,22 +254,22 @@ static int com20020_reset(struct net_device *dev, int really_reset)
mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */
}
/* clear flags & end reset */
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
/* verify that the ARCnet signature byte is present */
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
com20020_copy_from_card(dev, 0, 0, &inbyte, 1);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
if (inbyte != TESTvalue) {
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
return 1;
}
/* enable extended (512-byte) packets */
ACOMMAND(CONFIGcmd | EXTconf);
- BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);
+ BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__);
/* done! return success. */
return 0;
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
index 949e75358bf..8cbc1b59bd6 100644
--- a/drivers/net/atl1e/atl1e_hw.c
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -397,7 +397,7 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
*/
int atl1e_phy_commit(struct atl1e_hw *hw)
{
- struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct atl1e_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
int ret_val;
u16 phy_data;
@@ -431,7 +431,7 @@ int atl1e_phy_commit(struct atl1e_hw *hw)
int atl1e_phy_init(struct atl1e_hw *hw)
{
- struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct atl1e_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
s32 ret_val;
u16 phy_val;
@@ -525,7 +525,7 @@ int atl1e_phy_init(struct atl1e_hw *hw)
*/
int atl1e_reset_hw(struct atl1e_hw *hw)
{
- struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct atl1e_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
u32 idle_status_data = 0;
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 7685b995ff9..9b603528143 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -2390,9 +2390,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev,
}
/* Init GPHY as early as possible due to power saving issue */
- spin_lock(&adapter->mdio_lock);
atl1e_phy_init(&adapter->hw);
- spin_unlock(&adapter->mdio_lock);
/* reset the controller to
* put the device in a known good starting state */
err = atl1e_reset_hw(&adapter->hw);
diff --git a/drivers/net/atlx/Makefile b/drivers/net/atlx/Makefile
index ca45553a040..e4f6022ca55 100644
--- a/drivers/net/atlx/Makefile
+++ b/drivers/net/atlx/Makefile
@@ -1 +1,3 @@
obj-$(CONFIG_ATL1) += atl1.o
+obj-$(CONFIG_ATL2) += atl2.o
+
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index e23ce77712f..3cf59a7f5a1 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -24,16 +24,12 @@
* file called COPYING.
*
* Contact Information:
- * Xiong Huang <xiong_huang@attansic.com>
- * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
- * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA
- *
+ * Xiong Huang <xiong.huang@atheros.com>
+ * Jie Yang <jie.yang@atheros.com>
* Chris Snook <csnook@redhat.com>
* Jay Cliburn <jcliburn@gmail.com>
*
- * This version is adapted from the Attansic reference driver for
- * inclusion in the Linux kernel. It is currently under heavy development.
- * A very incomplete list of things that need to be dealt with:
+ * This version is adapted from the Attansic reference driver.
*
* TODO:
* Add more ethtool functions.
@@ -2109,7 +2105,6 @@ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
struct tx_packet_desc *ptpd)
{
- /* spinlock held */
u8 hdr_len, ip_off;
u32 real_len;
int err;
@@ -2196,7 +2191,6 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
struct tx_packet_desc *ptpd)
{
- /* spinlock held */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info;
u16 buf_len = skb->len;
@@ -2303,7 +2297,6 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
struct tx_packet_desc *ptpd)
{
- /* spinlock held */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info;
struct tx_packet_desc *tpd;
@@ -2361,7 +2354,6 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct tx_packet_desc *ptpd;
u16 frag_size;
u16 vlan_tag;
- unsigned long flags;
unsigned int nr_frags = 0;
unsigned int mss = 0;
unsigned int f;
@@ -2399,18 +2391,9 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
}
- if (!spin_trylock_irqsave(&adapter->lock, flags)) {
- /* Can't get lock - tell upper layer to requeue */
- if (netif_msg_tx_queued(adapter))
- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
- "tx locked\n");
- return NETDEV_TX_LOCKED;
- }
-
if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
/* not enough descriptors */
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&adapter->lock, flags);
if (netif_msg_tx_queued(adapter))
dev_printk(KERN_DEBUG, &adapter->pdev->dev,
"tx busy\n");
@@ -2432,7 +2415,6 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tso = atl1_tso(adapter, skb, ptpd);
if (tso < 0) {
- spin_unlock_irqrestore(&adapter->lock, flags);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2440,7 +2422,6 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (!tso) {
ret_val = atl1_tx_csum(adapter, skb, ptpd);
if (ret_val < 0) {
- spin_unlock_irqrestore(&adapter->lock, flags);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2449,7 +2430,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
atl1_tx_map(adapter, skb, ptpd);
atl1_tx_queue(adapter, count, ptpd);
atl1_update_mailbox(adapter);
- spin_unlock_irqrestore(&adapter->lock, flags);
+ mmiowb();
netdev->trans_start = jiffies;
return NETDEV_TX_OK;
}
@@ -2642,6 +2623,7 @@ static void atl1_down(struct atl1_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ netif_stop_queue(netdev);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_config_timer);
adapter->phy_timer_pending = false;
@@ -2655,7 +2637,6 @@ static void atl1_down(struct atl1_adapter *adapter)
adapter->link_speed = SPEED_0;
adapter->link_duplex = -1;
netif_carrier_off(netdev);
- netif_stop_queue(netdev);
atl1_clean_tx_ring(adapter);
atl1_clean_rx_ring(adapter);
@@ -2724,6 +2705,8 @@ static int atl1_open(struct net_device *netdev)
struct atl1_adapter *adapter = netdev_priv(netdev);
int err;
+ netif_carrier_off(netdev);
+
/* allocate transmit descriptors */
err = atl1_setup_ring_resources(adapter);
if (err)
@@ -3022,7 +3005,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netdev->features = NETIF_F_HW_CSUM;
netdev->features |= NETIF_F_SG;
netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
- netdev->features |= NETIF_F_LLTX;
/*
* patch for some L1 of old version,
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
new file mode 100644
index 00000000000..f5bdc92c1a6
--- /dev/null
+++ b/drivers/net/atlx/atl2.c
@@ -0,0 +1,3119 @@
+/*
+ * Copyright(c) 2006 - 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2008 Chris Snook <csnook@redhat.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 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.
+ */
+
+#include <asm/atomic.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/hardirq.h>
+#include <linux/if_vlan.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/irqflags.h>
+#include <linux/irqreturn.h>
+#include <linux/mii.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/pm.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/tcp.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "atl2.h"
+
+#define ATL2_DRV_VERSION "2.2.3"
+
+static char atl2_driver_name[] = "atl2";
+static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver";
+static char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
+static char atl2_driver_version[] = ATL2_DRV_VERSION;
+
+MODULE_AUTHOR("Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>");
+MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ATL2_DRV_VERSION);
+
+/*
+ * atl2_pci_tbl - PCI Device ID Table
+ */
+static struct pci_device_id atl2_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)},
+ /* required last entry */
+ {0,}
+};
+MODULE_DEVICE_TABLE(pci, atl2_pci_tbl);
+
+static void atl2_set_ethtool_ops(struct net_device *netdev);
+
+static void atl2_check_options(struct atl2_adapter *adapter);
+
+/*
+ * atl2_sw_init - Initialize general software structures (struct atl2_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl2_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
+{
+ struct atl2_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+
+ /* PCI config space info */
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_id = pdev->subsystem_device;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+ adapter->wol = 0;
+ adapter->ict = 50000; /* ~100ms */
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+
+ hw->phy_configured = false;
+ hw->preamble_len = 7;
+ hw->ipgt = 0x60;
+ hw->min_ifg = 0x50;
+ hw->ipgr1 = 0x40;
+ hw->ipgr2 = 0x60;
+ hw->retry_buf = 2;
+ hw->max_retry = 0xf;
+ hw->lcol = 0x37;
+ hw->jam_ipg = 7;
+ hw->fc_rxd_hi = 0;
+ hw->fc_rxd_lo = 0;
+ hw->max_frame_size = adapter->netdev->mtu;
+
+ spin_lock_init(&adapter->stats_lock);
+
+ set_bit(__ATL2_DOWN, &adapter->flags);
+
+ return 0;
+}
+
+/*
+ * atl2_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl2_set_multi(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+ u32 rctl;
+ u32 hash_value;
+
+ /* Check for Promiscuous and All Multicast modes */
+ rctl = ATL2_READ_REG(hw, REG_MAC_CTRL);
+
+ if (netdev->flags & IFF_PROMISC) {
+ rctl |= MAC_CTRL_PROMIS_EN;
+ } else if (netdev->flags & IFF_ALLMULTI) {
+ rctl |= MAC_CTRL_MC_ALL_EN;
+ rctl &= ~MAC_CTRL_PROMIS_EN;
+ } else
+ rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, rctl);
+
+ /* clear the old settings from the multicast hash table */
+ ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ /* comoute mc addresses' hash value ,and put it into hash table */
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ hash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr);
+ atl2_hash_set(hw, hash_value);
+ }
+}
+
+static void init_ring_ptrs(struct atl2_adapter *adapter)
+{
+ /* Read / Write Ptr Initialize: */
+ adapter->txd_write_ptr = 0;
+ atomic_set(&adapter->txd_read_ptr, 0);
+
+ adapter->rxd_read_ptr = 0;
+ adapter->rxd_write_ptr = 0;
+
+ atomic_set(&adapter->txs_write_ptr, 0);
+ adapter->txs_next_clear = 0;
+}
+
+/*
+ * atl2_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl2_configure(struct atl2_adapter *adapter)
+{
+ struct atl2_hw *hw = &adapter->hw;
+ u32 value;
+
+ /* clear interrupt status */
+ ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff);
+
+ /* set MAC Address */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5]));
+ ATL2_WRITE_REG(hw, REG_MAC_STA_ADDR, value);
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1]));
+ ATL2_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value);
+
+ /* HI base address */
+ ATL2_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
+ (u32)((adapter->ring_dma & 0xffffffff00000000ULL) >> 32));
+
+ /* LO base address */
+ ATL2_WRITE_REG(hw, REG_TXD_BASE_ADDR_LO,
+ (u32)(adapter->txd_dma & 0x00000000ffffffffULL));
+ ATL2_WRITE_REG(hw, REG_TXS_BASE_ADDR_LO,
+ (u32)(adapter->txs_dma & 0x00000000ffffffffULL));
+ ATL2_WRITE_REG(hw, REG_RXD_BASE_ADDR_LO,
+ (u32)(adapter->rxd_dma & 0x00000000ffffffffULL));
+
+ /* element count */
+ ATL2_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4));
+ ATL2_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size);
+ ATL2_WRITE_REGW(hw, REG_RXD_BUF_NUM, (u16)adapter->rxd_ring_size);
+
+ /* config Internal SRAM */
+/*
+ ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end);
+ ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end);
+*/
+
+ /* config IPG/IFG */
+ value = (((u32)hw->ipgt & MAC_IPG_IFG_IPGT_MASK) <<
+ MAC_IPG_IFG_IPGT_SHIFT) |
+ (((u32)hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) <<
+ MAC_IPG_IFG_MIFG_SHIFT) |
+ (((u32)hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) <<
+ MAC_IPG_IFG_IPGR1_SHIFT)|
+ (((u32)hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) <<
+ MAC_IPG_IFG_IPGR2_SHIFT);
+ ATL2_WRITE_REG(hw, REG_MAC_IPG_IFG, value);
+
+ /* config Half-Duplex Control */
+ value = ((u32)hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+ (((u32)hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) <<
+ MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+ MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+ (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+ (((u32)hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) <<
+ MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+ ATL2_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value);
+
+ /* set Interrupt Moderator Timer */
+ ATL2_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt);
+ ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN);
+
+ /* set Interrupt Clear Timer */
+ ATL2_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict);
+
+ /* set MTU */
+ ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +
+ ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);
+
+ /* 1590 */
+ ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);
+
+ /* flow control */
+ ATL2_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi);
+ ATL2_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo);
+
+ /* Init mailbox */
+ ATL2_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr);
+ ATL2_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr);
+
+ /* enable DMA read/write */
+ ATL2_WRITE_REGB(hw, REG_DMAR, DMAR_EN);
+ ATL2_WRITE_REGB(hw, REG_DMAW, DMAW_EN);
+
+ value = ATL2_READ_REG(&adapter->hw, REG_ISR);
+ if ((value & ISR_PHY_LINKDOWN) != 0)
+ value = 1; /* config failed */
+ else
+ value = 0;
+
+ /* clear all interrupt status */
+ ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff);
+ ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ return value;
+}
+
+/*
+ * atl2_setup_ring_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int size;
+ u8 offset = 0;
+
+ /* real ring DMA buffer */
+ adapter->ring_size = size =
+ adapter->txd_ring_size * 1 + 7 + /* dword align */
+ adapter->txs_ring_size * 4 + 7 + /* dword align */
+ adapter->rxd_ring_size * 1536 + 127; /* 128bytes align */
+
+ adapter->ring_vir_addr = pci_alloc_consistent(pdev, size,
+ &adapter->ring_dma);
+ if (!adapter->ring_vir_addr)
+ return -ENOMEM;
+ memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+ /* Init TXD Ring */
+ adapter->txd_dma = adapter->ring_dma ;
+ offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;
+ adapter->txd_dma += offset;
+ adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr +
+ offset);
+
+ /* Init TXS Ring */
+ adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;
+ offset = (adapter->txs_dma & 0x7) ? (8 - (adapter->txs_dma & 0x7)) : 0;
+ adapter->txs_dma += offset;
+ adapter->txs_ring = (struct tx_pkt_status *)
+ (((u8 *)adapter->txd_ring) + (adapter->txd_ring_size + offset));
+
+ /* Init RXD Ring */
+ adapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size * 4;
+ offset = (adapter->rxd_dma & 127) ?
+ (128 - (adapter->rxd_dma & 127)) : 0;
+ if (offset > 7)
+ offset -= 8;
+ else
+ offset += (128 - 8);
+
+ adapter->rxd_dma += offset;
+ adapter->rxd_ring = (struct rx_desc *) (((u8 *)adapter->txs_ring) +
+ (adapter->txs_ring_size * 4 + offset));
+
+/*
+ * Read / Write Ptr Initialize:
+ * init_ring_ptrs(adapter);
+ */
+ return 0;
+}
+
+/*
+ * atl2_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl2_irq_enable(struct atl2_adapter *adapter)
+{
+ ATL2_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+ ATL2_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl2_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl2_irq_disable(struct atl2_adapter *adapter)
+{
+ ATL2_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ ATL2_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+}
+
+#ifdef NETIF_F_HW_VLAN_TX
+static void atl2_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ u32 ctrl;
+
+ atl2_irq_disable(adapter);
+ adapter->vlgrp = grp;
+
+ if (grp) {
+ /* enable VLAN tag insert/strip */
+ ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
+ ctrl |= MAC_CTRL_RMV_VLAN;
+ ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
+ } else {
+ /* disable VLAN tag insert/strip */
+ ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
+ ctrl &= ~MAC_CTRL_RMV_VLAN;
+ ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
+ }
+
+ atl2_irq_enable(adapter);
+}
+
+static void atl2_restore_vlan(struct atl2_adapter *adapter)
+{
+ atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+#endif
+
+static void atl2_intr_rx(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct rx_desc *rxd;
+ struct sk_buff *skb;
+
+ do {
+ rxd = adapter->rxd_ring+adapter->rxd_write_ptr;
+ if (!rxd->status.update)
+ break; /* end of tx */
+
+ /* clear this flag at once */
+ rxd->status.update = 0;
+
+ if (rxd->status.ok && rxd->status.pkt_size >= 60) {
+ int rx_size = (int)(rxd->status.pkt_size - 4);
+ /* alloc new buffer */
+ skb = netdev_alloc_skb(netdev, rx_size + NET_IP_ALIGN);
+ if (NULL == skb) {
+ printk(KERN_WARNING
+ "%s: Mem squeeze, deferring packet.\n",
+ netdev->name);
+ /*
+ * Check that some rx space is free. If not,
+ * free one and mark stats->rx_dropped++.
+ */
+ adapter->net_stats.rx_dropped++;
+ break;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb->dev = netdev;
+ memcpy(skb->data, rxd->packet, rx_size);
+ skb_put(skb, rx_size);
+ skb->protocol = eth_type_trans(skb, netdev);
+#ifdef NETIF_F_HW_VLAN_TX
+ if (adapter->vlgrp && (rxd->status.vlan)) {
+ u16 vlan_tag = (rxd->status.vtag>>4) |
+ ((rxd->status.vtag&7) << 13) |
+ ((rxd->status.vtag&8) << 9);
+ vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+ } else
+#endif
+ netif_rx(skb);
+ adapter->net_stats.rx_bytes += rx_size;
+ adapter->net_stats.rx_packets++;
+ netdev->last_rx = jiffies;
+ } else {
+ adapter->net_stats.rx_errors++;
+
+ if (rxd->status.ok && rxd->status.pkt_size <= 60)
+ adapter->net_stats.rx_length_errors++;
+ if (rxd->status.mcast)
+ adapter->net_stats.multicast++;
+ if (rxd->status.crc)
+ adapter->net_stats.rx_crc_errors++;
+ if (rxd->status.align)
+ adapter->net_stats.rx_frame_errors++;
+ }
+
+ /* advance write ptr */
+ if (++adapter->rxd_write_ptr == adapter->rxd_ring_size)
+ adapter->rxd_write_ptr = 0;
+ } while (1);
+
+ /* update mailbox? */
+ adapter->rxd_read_ptr = adapter->rxd_write_ptr;
+ ATL2_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr);
+}
+
+static void atl2_intr_tx(struct atl2_adapter *adapter)
+{
+ u32 txd_read_ptr;
+ u32 txs_write_ptr;
+ struct tx_pkt_status *txs;
+ struct tx_pkt_header *txph;
+ int free_hole = 0;
+
+ do {
+ txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);
+ txs = adapter->txs_ring + txs_write_ptr;
+ if (!txs->update)
+ break; /* tx stop here */
+
+ free_hole = 1;
+ txs->update = 0;
+
+ if (++txs_write_ptr == adapter->txs_ring_size)
+ txs_write_ptr = 0;
+ atomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr);
+
+ txd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr);
+ txph = (struct tx_pkt_header *)
+ (((u8 *)adapter->txd_ring) + txd_read_ptr);
+
+ if (txph->pkt_size != txs->pkt_size) {
+ struct tx_pkt_status *old_txs = txs;
+ printk(KERN_WARNING
+ "%s: txs packet size not consistent with txd"
+ " txd_:0x%08x, txs_:0x%08x!\n",
+ adapter->netdev->name,
+ *(u32 *)txph, *(u32 *)txs);
+ printk(KERN_WARNING
+ "txd read ptr: 0x%x\n",
+ txd_read_ptr);
+ txs = adapter->txs_ring + txs_write_ptr;
+ printk(KERN_WARNING
+ "txs-behind:0x%08x\n",
+ *(u32 *)txs);
+ if (txs_write_ptr < 2) {
+ txs = adapter->txs_ring +
+ (adapter->txs_ring_size +
+ txs_write_ptr - 2);
+ } else {
+ txs = adapter->txs_ring + (txs_write_ptr - 2);
+ }
+ printk(KERN_WARNING
+ "txs-before:0x%08x\n",
+ *(u32 *)txs);
+ txs = old_txs;
+ }
+
+ /* 4for TPH */
+ txd_read_ptr += (((u32)(txph->pkt_size) + 7) & ~3);
+ if (txd_read_ptr >= adapter->txd_ring_size)
+ txd_read_ptr -= adapter->txd_ring_size;
+
+ atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr);
+
+ /* tx statistics: */
+ if (txs->ok) {
+ adapter->net_stats.tx_bytes += txs->pkt_size;
+ adapter->net_stats.tx_packets++;
+ }
+ else
+ adapter->net_stats.tx_errors++;
+
+ if (txs->defer)
+ adapter->net_stats.collisions++;
+ if (txs->abort_col)
+ adapter->net_stats.tx_aborted_errors++;
+ if (txs->late_col)
+ adapter->net_stats.tx_window_errors++;
+ if (txs->underun)
+ adapter->net_stats.tx_fifo_errors++;
+ } while (1);
+
+ if (free_hole) {
+ if (netif_queue_stopped(adapter->netdev) &&
+ netif_carrier_ok(adapter->netdev))
+ netif_wake_queue(adapter->netdev);
+ }
+}
+
+static void atl2_check_for_link(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u16 phy_data = 0;
+
+ spin_lock(&adapter->stats_lock);
+ atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ spin_unlock(&adapter->stats_lock);
+
+ /* notify upper layer link down ASAP */
+ if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ printk(KERN_INFO "%s: %s NIC Link is Down\n",
+ atl2_driver_name, netdev->name);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ }
+ schedule_work(&adapter->link_chg_task);
+}
+
+static inline void atl2_clear_phy_int(struct atl2_adapter *adapter)
+{
+ u16 phy_data;
+ spin_lock(&adapter->stats_lock);
+ atl2_read_phy_reg(&adapter->hw, 19, &phy_data);
+ spin_unlock(&adapter->stats_lock);
+}
+
+/*
+ * atl2_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl2_intr(int irq, void *data)
+{
+ struct atl2_adapter *adapter = netdev_priv(data);
+ struct atl2_hw *hw = &adapter->hw;
+ u32 status;
+
+ status = ATL2_READ_REG(hw, REG_ISR);
+ if (0 == status)
+ return IRQ_NONE;
+
+ /* link event */
+ if (status & ISR_PHY)
+ atl2_clear_phy_int(adapter);
+
+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+ ATL2_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ if (netif_running(adapter->netdev)) { /* reset MAC */
+ ATL2_WRITE_REG(hw, REG_ISR, 0);
+ ATL2_WRITE_REG(hw, REG_IMR, 0);
+ ATL2_WRITE_FLUSH(hw);
+ schedule_work(&adapter->reset_task);
+ return IRQ_HANDLED;
+ }
+ }
+
+ /* check if DMA read/write error? */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ ATL2_WRITE_REG(hw, REG_ISR, 0);
+ ATL2_WRITE_REG(hw, REG_IMR, 0);
+ ATL2_WRITE_FLUSH(hw);
+ schedule_work(&adapter->reset_task);
+ return IRQ_HANDLED;
+ }
+
+ /* link event */
+ if (status & (ISR_PHY | ISR_MANUAL)) {
+ adapter->net_stats.tx_carrier_errors++;
+ atl2_check_for_link(adapter);
+ }
+
+ /* transmit event */
+ if (status & ISR_TX_EVENT)
+ atl2_intr_tx(adapter);
+
+ /* rx exception */
+ if (status & ISR_RX_EVENT)
+ atl2_intr_rx(adapter);
+
+ /* re-enable Interrupt */
+ ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ return IRQ_HANDLED;
+}
+
+static int atl2_request_irq(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int flags, err = 0;
+
+ flags = IRQF_SHARED;
+#ifdef CONFIG_PCI_MSI
+ adapter->have_msi = true;
+ err = pci_enable_msi(adapter->pdev);
+ if (err)
+ adapter->have_msi = false;
+
+ if (adapter->have_msi)
+ flags &= ~IRQF_SHARED;
+#endif
+
+ return request_irq(adapter->pdev->irq, &atl2_intr, flags, netdev->name,
+ netdev);
+}
+
+/*
+ * atl2_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl2_free_ring_resources(struct atl2_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ pci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr,
+ adapter->ring_dma);
+}
+
+/*
+ * atl2_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl2_open(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ int err;
+ u32 val;
+
+ /* disallow open during test */
+ if (test_bit(__ATL2_TESTING, &adapter->flags))
+ return -EBUSY;
+
+ /* allocate transmit descriptors */
+ err = atl2_setup_ring_resources(adapter);
+ if (err)
+ return err;
+
+ err = atl2_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_init_hw;
+ }
+
+ /* hardware has been reset, we need to reload some things */
+ atl2_set_multi(netdev);
+ init_ring_ptrs(adapter);
+
+#ifdef NETIF_F_HW_VLAN_TX
+ atl2_restore_vlan(adapter);
+#endif
+
+ if (atl2_configure(adapter)) {
+ err = -EIO;
+ goto err_config;
+ }
+
+ err = atl2_request_irq(adapter);
+ if (err)
+ goto err_req_irq;
+
+ clear_bit(__ATL2_DOWN, &adapter->flags);
+
+ mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ);
+
+ val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+ val | MASTER_CTRL_MANUAL_INT);
+
+ atl2_irq_enable(adapter);
+
+ return 0;
+
+err_init_hw:
+err_req_irq:
+err_config:
+ atl2_free_ring_resources(adapter);
+ atl2_reset_hw(&adapter->hw);
+
+ return err;
+}
+
+static void atl2_down(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* signal that we're down so the interrupt handler does not
+ * reschedule our watchdog timer */
+ set_bit(__ATL2_DOWN, &adapter->flags);
+
+ netif_tx_disable(netdev);
+
+ /* reset MAC to disable all RX/TX */
+ atl2_reset_hw(&adapter->hw);
+ msleep(1);
+
+ atl2_irq_disable(adapter);
+
+ del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->phy_config_timer);
+ clear_bit(0, &adapter->cfg_phy);
+
+ netif_carrier_off(netdev);
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+}
+
+static void atl2_free_irq(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ free_irq(adapter->pdev->irq, netdev);
+
+#ifdef CONFIG_PCI_MSI
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+#endif
+}
+
+/*
+ * atl2_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl2_close(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));
+
+ atl2_down(adapter);
+ atl2_free_irq(adapter);
+ atl2_free_ring_resources(adapter);
+
+ return 0;
+}
+
+static inline int TxsFreeUnit(struct atl2_adapter *adapter)
+{
+ u32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);
+
+ return (adapter->txs_next_clear >= txs_write_ptr) ?
+ (int) (adapter->txs_ring_size - adapter->txs_next_clear +
+ txs_write_ptr - 1) :
+ (int) (txs_write_ptr - adapter->txs_next_clear - 1);
+}
+
+static inline int TxdFreeBytes(struct atl2_adapter *adapter)
+{
+ u32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr);
+
+ return (adapter->txd_write_ptr >= txd_read_ptr) ?
+ (int) (adapter->txd_ring_size - adapter->txd_write_ptr +
+ txd_read_ptr - 1) :
+ (int) (txd_read_ptr - adapter->txd_write_ptr - 1);
+}
+
+static int atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct tx_pkt_header *txph;
+ u32 offset, copy_len;
+ int txs_unused;
+ int txbuf_unused;
+
+ if (test_bit(__ATL2_DOWN, &adapter->flags)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ txs_unused = TxsFreeUnit(adapter);
+ txbuf_unused = TxdFreeBytes(adapter);
+
+ if (skb->len + sizeof(struct tx_pkt_header) + 4 > txbuf_unused ||
+ txs_unused < 1) {
+ /* not enough resources */
+ netif_stop_queue(netdev);
+ return NETDEV_TX_BUSY;
+ }
+
+ offset = adapter->txd_write_ptr;
+
+ txph = (struct tx_pkt_header *) (((u8 *)adapter->txd_ring) + offset);
+
+ *(u32 *)txph = 0;
+ txph->pkt_size = skb->len;
+
+ offset += 4;
+ if (offset >= adapter->txd_ring_size)
+ offset -= adapter->txd_ring_size;
+ copy_len = adapter->txd_ring_size - offset;
+ if (copy_len >= skb->len) {
+ memcpy(((u8 *)adapter->txd_ring) + offset, skb->data, skb->len);
+ offset += ((u32)(skb->len + 3) & ~3);
+ } else {
+ memcpy(((u8 *)adapter->txd_ring)+offset, skb->data, copy_len);
+ memcpy((u8 *)adapter->txd_ring, skb->data+copy_len,
+ skb->len-copy_len);
+ offset = ((u32)(skb->len-copy_len + 3) & ~3);
+ }
+#ifdef NETIF_F_HW_VLAN_TX
+ if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ u16 vlan_tag = vlan_tx_tag_get(skb);
+ vlan_tag = (vlan_tag << 4) |
+ (vlan_tag >> 13) |
+ ((vlan_tag >> 9) & 0x8);
+ txph->ins_vlan = 1;
+ txph->vlan = vlan_tag;
+ }
+#endif
+ if (offset >= adapter->txd_ring_size)
+ offset -= adapter->txd_ring_size;
+ adapter->txd_write_ptr = offset;
+
+ /* clear txs before send */
+ adapter->txs_ring[adapter->txs_next_clear].update = 0;
+ if (++adapter->txs_next_clear == adapter->txs_ring_size)
+ adapter->txs_next_clear = 0;
+
+ ATL2_WRITE_REGW(&adapter->hw, REG_MB_TXD_WR_IDX,
+ (adapter->txd_write_ptr >> 2));
+
+ mmiowb();
+ netdev->trans_start = jiffies;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+/*
+ * atl2_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl2_get_stats(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ return &adapter->net_stats;
+}
+
+/*
+ * atl2_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl2_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+
+ if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
+ return -EINVAL;
+
+ /* set MTU */
+ if (hw->max_frame_size != new_mtu) {
+ netdev->mtu = new_mtu;
+ ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE +
+ VLAN_SIZE + ETHERNET_FCS_SIZE);
+ }
+
+ return 0;
+}
+
+/*
+ * atl2_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl2_set_mac(struct net_device *netdev, void *p)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+ atl2_set_mac_addr(&adapter->hw);
+
+ return 0;
+}
+
+/*
+ * atl2_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+ unsigned long flags;
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = 0;
+ break;
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ if (atl2_read_phy_reg(&adapter->hw,
+ data->reg_num & 0x1F, &data->val_out)) {
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ return -EIO;
+ }
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ break;
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (data->reg_num & ~(0x1F))
+ return -EFAULT;
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ if (atl2_write_phy_reg(&adapter->hw, data->reg_num,
+ data->val_in)) {
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ return -EIO;
+ }
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+/*
+ * atl2_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ return atl2_mii_ioctl(netdev, ifr, cmd);
+#ifdef ETHTOOL_OPS_COMPAT
+ case SIOCETHTOOL:
+ return ethtool_ioctl(ifr);
+#endif
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/*
+ * atl2_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl2_tx_timeout(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ /* Do the reset outside of interrupt context */
+ schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl2_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl2_watchdog(unsigned long data)
+{
+ struct atl2_adapter *adapter = (struct atl2_adapter *) data;
+ u32 drop_rxd, drop_rxs;
+ unsigned long flags;
+
+ if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV);
+ drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV);
+ adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs);
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+
+ /* Reset the timer */
+ mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ);
+ }
+}
+
+/*
+ * atl2_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl2_phy_config(unsigned long data)
+{
+ struct atl2_adapter *adapter = (struct atl2_adapter *) data;
+ struct atl2_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ atl2_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ atl2_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+ MII_CR_RESTART_AUTO_NEG);
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ clear_bit(0, &adapter->cfg_phy);
+}
+
+static int atl2_up(struct atl2_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u32 val;
+
+ /* hardware has been reset, we need to reload some things */
+
+ err = atl2_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ return err;
+ }
+
+ atl2_set_multi(netdev);
+ init_ring_ptrs(adapter);
+
+#ifdef NETIF_F_HW_VLAN_TX
+ atl2_restore_vlan(adapter);
+#endif
+
+ if (atl2_configure(adapter)) {
+ err = -EIO;
+ goto err_up;
+ }
+
+ clear_bit(__ATL2_DOWN, &adapter->flags);
+
+ val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val |
+ MASTER_CTRL_MANUAL_INT);
+
+ atl2_irq_enable(adapter);
+
+err_up:
+ return err;
+}
+
+static void atl2_reinit_locked(struct atl2_adapter *adapter)
+{
+ WARN_ON(in_interrupt());
+ while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
+ msleep(1);
+ atl2_down(adapter);
+ atl2_up(adapter);
+ clear_bit(__ATL2_RESETTING, &adapter->flags);
+}
+
+static void atl2_reset_task(struct work_struct *work)
+{
+ struct atl2_adapter *adapter;
+ adapter = container_of(work, struct atl2_adapter, reset_task);
+
+ atl2_reinit_locked(adapter);
+}
+
+static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)
+{
+ u32 value;
+ struct atl2_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;
+
+ /* duplex */
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+
+ /* flow control */
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+ /* PAD & CRC */
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+
+ /* preamble length */
+ value |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) <<
+ MAC_CTRL_PRMLEN_SHIFT);
+
+ /* vlan */
+ if (adapter->vlgrp)
+ value |= MAC_CTRL_RMV_VLAN;
+
+ /* filter mode */
+ value |= MAC_CTRL_BC_EN;
+ if (netdev->flags & IFF_PROMISC)
+ value |= MAC_CTRL_PROMIS_EN;
+ else if (netdev->flags & IFF_ALLMULTI)
+ value |= MAC_CTRL_MC_ALL_EN;
+
+ /* half retry buffer */
+ value |= (((u32)(adapter->hw.retry_buf &
+ MAC_CTRL_HALF_LEFT_BUF_MASK)) << MAC_CTRL_HALF_LEFT_BUF_SHIFT);
+
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+static int atl2_check_link(struct atl2_adapter *adapter)
+{
+ struct atl2_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ int ret_val;
+ u16 speed, duplex, phy_data;
+ int reconfig = 0;
+
+ /* MII_BMSR must read twise */
+ atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
+ if (!(phy_data&BMSR_LSTATUS)) { /* link down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ u32 value;
+ /* disable rx */
+ value = ATL2_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ return 0;
+ }
+
+ /* Link Up */
+ ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val)
+ return ret_val;
+ switch (hw->MediaType) {
+ case MEDIA_TYPE_100M_FULL:
+ if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_HALF:
+ if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ }
+ /* link result is our setting */
+ if (reconfig == 0) {
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl2_setup_mac_ctrl(adapter);
+ printk(KERN_INFO "%s: %s NIC Link is Up<%d Mbps %s>\n",
+ atl2_driver_name, netdev->name,
+ adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "Full Duplex" : "Half Duplex");
+ }
+
+ if (!netif_carrier_ok(netdev)) { /* Link down -> Up */
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ return 0;
+ }
+
+ /* change original link status */
+ if (netif_carrier_ok(netdev)) {
+ u32 value;
+ /* disable rx */
+ value = ATL2_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
+
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+
+ /* auto-neg, insert timer to re-config phy
+ * (if interval smaller than 5 seconds, something strange) */
+ if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
+ if (!test_and_set_bit(0, &adapter->cfg_phy))
+ mod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ);
+ }
+
+ return 0;
+}
+
+/*
+ * atl2_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl2_link_chg_task(struct work_struct *work)
+{
+ struct atl2_adapter *adapter;
+ unsigned long flags;
+
+ adapter = container_of(work, struct atl2_adapter, link_chg_task);
+
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+ atl2_check_link(adapter);
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+}
+
+static void atl2_setup_pcicmd(struct pci_dev *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+
+ if (cmd & PCI_COMMAND_INTX_DISABLE)
+ cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ if (cmd & PCI_COMMAND_IO)
+ cmd &= ~PCI_COMMAND_IO;
+ if (0 == (cmd & PCI_COMMAND_MEMORY))
+ cmd |= PCI_COMMAND_MEMORY;
+ if (0 == (cmd & PCI_COMMAND_MASTER))
+ cmd |= PCI_COMMAND_MASTER;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /*
+ * some motherboards BIOS(PXE/EFI) driver may set PME
+ * while they transfer control to OS (Windows/Linux)
+ * so we should clear this bit before NIC work normally
+ */
+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void atl2_poll_controller(struct net_device *netdev)
+{
+ disable_irq(netdev->irq);
+ atl2_intr(netdev->irq, netdev);
+ enable_irq(netdev->irq);
+}
+#endif
+
+/*
+ * atl2_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl2_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl2_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl2_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct atl2_adapter *adapter;
+ static int cards_found;
+ unsigned long mmio_start;
+ int mmio_len;
+ int err;
+
+ cards_found = 0;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ /*
+ * atl2 is a shared-high-32-bit device, so we're stuck with 32-bit DMA
+ * until the kernel has the proper infrastructure to support 64-bit DMA
+ * on these devices.
+ */
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) &&
+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n");
+ goto err_dma;
+ }
+
+ /* Mark all PCI regions associated with PCI device
+ * pdev as being reserved by owner atl2_driver_name */
+ err = pci_request_regions(pdev, atl2_driver_name);
+ if (err)
+ goto err_pci_reg;
+
+ /* Enables bus-mastering on the device and calls
+ * pcibios_set_master to do the needed arch specific settings */
+ pci_set_master(pdev);
+
+ err = -ENOMEM;
+ netdev = alloc_etherdev(sizeof(struct atl2_adapter));
+ if (!netdev)
+ goto err_alloc_etherdev;
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ pci_set_drvdata(pdev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.back = adapter;
+
+ mmio_start = pci_resource_start(pdev, 0x0);
+ mmio_len = pci_resource_len(pdev, 0x0);
+
+ adapter->hw.mem_rang = (u32)mmio_len;
+ adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+ if (!adapter->hw.hw_addr) {
+ err = -EIO;
+ goto err_ioremap;
+ }
+
+ atl2_setup_pcicmd(pdev);
+
+ netdev->open = &atl2_open;
+ netdev->stop = &atl2_close;
+ netdev->hard_start_xmit = &atl2_xmit_frame;
+ netdev->get_stats = &atl2_get_stats;
+ netdev->set_multicast_list = &atl2_set_multi;
+ netdev->set_mac_address = &atl2_set_mac;
+ netdev->change_mtu = &atl2_change_mtu;
+ netdev->do_ioctl = &atl2_ioctl;
+ atl2_set_ethtool_ops(netdev);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = atl2_poll_controller;
+#endif
+#ifdef HAVE_TX_TIMEOUT
+ netdev->tx_timeout = &atl2_tx_timeout;
+ netdev->watchdog_timeo = 5 * HZ;
+#endif
+#ifdef NETIF_F_HW_VLAN_TX
+ netdev->vlan_rx_register = atl2_vlan_rx_register;
+#endif
+ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+
+ netdev->mem_start = mmio_start;
+ netdev->mem_end = mmio_start + mmio_len;
+ adapter->bd_number = cards_found;
+ adapter->pci_using_64 = false;
+
+ /* setup the private structure */
+ err = atl2_sw_init(adapter);
+ if (err)
+ goto err_sw_init;
+
+ err = -EIO;
+
+#ifdef NETIF_F_HW_VLAN_TX
+ netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+#endif
+
+ /* Init PHY as early as possible due to power saving issue */
+ atl2_phy_init(&adapter->hw);
+
+ /* reset the controller to
+ * put the device in a known good starting state */
+
+ if (atl2_reset_hw(&adapter->hw)) {
+ err = -EIO;
+ goto err_reset;
+ }
+
+ /* copy the MAC address out of the EEPROM */
+ atl2_read_mac_addr(&adapter->hw);
+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+/* FIXME: do we still need this? */
+#ifdef ETHTOOL_GPERMADDR
+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+#else
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+#endif
+ err = -EIO;
+ goto err_eeprom;
+ }
+
+ atl2_check_options(adapter);
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->watchdog_timer.function = &atl2_watchdog;
+ adapter->watchdog_timer.data = (unsigned long) adapter;
+
+ init_timer(&adapter->phy_config_timer);
+ adapter->phy_config_timer.function = &atl2_phy_config;
+ adapter->phy_config_timer.data = (unsigned long) adapter;
+
+ INIT_WORK(&adapter->reset_task, atl2_reset_task);
+ INIT_WORK(&adapter->link_chg_task, atl2_link_chg_task);
+
+ strcpy(netdev->name, "eth%d"); /* ?? */
+ err = register_netdev(netdev);
+ if (err)
+ goto err_register;
+
+ /* assume we have no link for now */
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ cards_found++;
+
+ return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+ iounmap(adapter->hw.hw_addr);
+err_ioremap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+ pci_disable_device(pdev);
+ return err;
+}
+
+/*
+ * atl2_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl2_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+/* FIXME: write the original MAC address back in case it was changed from a
+ * BIOS-set value, as in atl1 -- CHS */
+static void __devexit atl2_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ /* flush_scheduled work may reschedule our watchdog task, so
+ * explicitly disable watchdog tasks from being rescheduled */
+ set_bit(__ATL2_DOWN, &adapter->flags);
+
+ del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->phy_config_timer);
+
+ flush_scheduled_work();
+
+ unregister_netdev(netdev);
+
+ atl2_force_ps(&adapter->hw);
+
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+
+ free_netdev(netdev);
+
+ pci_disable_device(pdev);
+}
+
+static int atl2_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+ u16 speed, duplex;
+ u32 ctrl = 0;
+ u32 wufc = adapter->wol;
+
+#ifdef CONFIG_PM
+ int retval = 0;
+#endif
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev)) {
+ WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));
+ atl2_down(adapter);
+ }
+
+#ifdef CONFIG_PM
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+#endif
+
+ atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);
+ atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);
+ if (ctrl & BMSR_LSTATUS)
+ wufc &= ~ATLX_WUFC_LNKC;
+
+ if (0 != (ctrl & BMSR_LSTATUS) && 0 != wufc) {
+ u32 ret_val;
+ /* get current link speed & duplex */
+ ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ printk(KERN_DEBUG
+ "%s: get speed&duplex error while suspend\n",
+ atl2_driver_name);
+ goto wol_dis;
+ }
+
+ ctrl = 0;
+
+ /* turn on magic packet wol */
+ if (wufc & ATLX_WUFC_MAG)
+ ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
+
+ /* ignore Link Chg event when Link is up */
+ ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
+
+ /* Config MAC CTRL Register */
+ ctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;
+ if (FULL_DUPLEX == adapter->link_duplex)
+ ctrl |= MAC_CTRL_DUPLX;
+ ctrl |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ ctrl |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+ ctrl |= (((u32)(adapter->hw.retry_buf &
+ MAC_CTRL_HALF_LEFT_BUF_MASK)) <<
+ MAC_CTRL_HALF_LEFT_BUF_SHIFT);
+ if (wufc & ATLX_WUFC_MAG) {
+ /* magic packet maybe Broadcast&multicast&Unicast */
+ ctrl |= MAC_CTRL_BC_EN;
+ }
+
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, ctrl);
+
+ /* pcie patch */
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
+ ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
+ ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
+
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+ goto suspend_exit;
+ }
+
+ if (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&ATLX_WUFC_LNKC)) {
+ /* link is down, so only LINK CHG WOL event enable */
+ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+ ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
+ ATL2_WRITE_REG(hw, REG_MAC_CTRL, 0);
+
+ /* pcie patch */
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
+ ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
+ ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
+
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+
+ goto suspend_exit;
+ }
+
+wol_dis:
+ /* WOL disabled */
+ ATL2_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* pcie patch */
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+ ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
+ ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
+ ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
+
+ atl2_force_ps(hw);
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+suspend_exit:
+ if (netif_running(netdev))
+ atl2_free_irq(adapter);
+
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int atl2_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR
+ "atl2: Cannot enable PCI device from suspend\n");
+ return err;
+ }
+
+ pci_set_master(pdev);
+
+ ATL2_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+ err = atl2_request_irq(adapter);
+ if (netif_running(netdev) && err)
+ return err;
+
+ atl2_reset_hw(&adapter->hw);
+
+ if (netif_running(netdev))
+ atl2_up(adapter);
+
+ netif_device_attach(netdev);
+
+ return 0;
+}
+#endif
+
+static void atl2_shutdown(struct pci_dev *pdev)
+{
+ atl2_suspend(pdev, PMSG_SUSPEND);
+}
+
+static struct pci_driver atl2_driver = {
+ .name = atl2_driver_name,
+ .id_table = atl2_pci_tbl,
+ .probe = atl2_probe,
+ .remove = __devexit_p(atl2_remove),
+ /* Power Managment Hooks */
+ .suspend = atl2_suspend,
+#ifdef CONFIG_PM
+ .resume = atl2_resume,
+#endif
+ .shutdown = atl2_shutdown,
+};
+
+/*
+ * atl2_init_module - Driver Registration Routine
+ *
+ * atl2_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl2_init_module(void)
+{
+ printk(KERN_INFO "%s - version %s\n", atl2_driver_string,
+ atl2_driver_version);
+ printk(KERN_INFO "%s\n", atl2_copyright);
+ return pci_register_driver(&atl2_driver);
+}
+module_init(atl2_init_module);
+
+/*
+ * atl2_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl2_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl2_exit_module(void)
+{
+ pci_unregister_driver(&atl2_driver);
+}
+module_exit(atl2_exit_module);
+
+static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)
+{
+ struct atl2_adapter *adapter = hw->back;
+ pci_read_config_word(adapter->pdev, reg, value);
+}
+
+static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)
+{
+ struct atl2_adapter *adapter = hw->back;
+ pci_write_config_word(adapter->pdev, reg, *value);
+}
+
+static int atl2_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_TP);
+ ecmd->advertising = ADVERTISED_TP;
+
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->advertising |= hw->autoneg_advertised;
+
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = 0;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (adapter->link_speed != SPEED_0) {
+ ecmd->speed = adapter->link_speed;
+ if (adapter->link_duplex == FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ ecmd->autoneg = AUTONEG_ENABLE;
+ return 0;
+}
+
+static int atl2_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+
+ while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
+ msleep(1);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+#define MY_ADV_MASK (ADVERTISE_10_HALF | \
+ ADVERTISE_10_FULL | \
+ ADVERTISE_100_HALF| \
+ ADVERTISE_100_FULL)
+
+ if ((ecmd->advertising & MY_ADV_MASK) == MY_ADV_MASK) {
+ hw->MediaType = MEDIA_TYPE_AUTO_SENSOR;
+ hw->autoneg_advertised = MY_ADV_MASK;
+ } else if ((ecmd->advertising & MY_ADV_MASK) ==
+ ADVERTISE_100_FULL) {
+ hw->MediaType = MEDIA_TYPE_100M_FULL;
+ hw->autoneg_advertised = ADVERTISE_100_FULL;
+ } else if ((ecmd->advertising & MY_ADV_MASK) ==
+ ADVERTISE_100_HALF) {
+ hw->MediaType = MEDIA_TYPE_100M_HALF;
+ hw->autoneg_advertised = ADVERTISE_100_HALF;
+ } else if ((ecmd->advertising & MY_ADV_MASK) ==
+ ADVERTISE_10_FULL) {
+ hw->MediaType = MEDIA_TYPE_10M_FULL;
+ hw->autoneg_advertised = ADVERTISE_10_FULL;
+ } else if ((ecmd->advertising & MY_ADV_MASK) ==
+ ADVERTISE_10_HALF) {
+ hw->MediaType = MEDIA_TYPE_10M_HALF;
+ hw->autoneg_advertised = ADVERTISE_10_HALF;
+ } else {
+ clear_bit(__ATL2_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+ ecmd->advertising = hw->autoneg_advertised |
+ ADVERTISED_TP | ADVERTISED_Autoneg;
+ } else {
+ clear_bit(__ATL2_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+
+ /* reset the link */
+ if (netif_running(adapter->netdev)) {
+ atl2_down(adapter);
+ atl2_up(adapter);
+ } else
+ atl2_reset_hw(&adapter->hw);
+
+ clear_bit(__ATL2_RESETTING, &adapter->flags);
+ return 0;
+}
+
+static u32 atl2_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl2_get_msglevel(struct net_device *netdev)
+{
+ return 0;
+}
+
+/*
+ * It's sane for this to be empty, but we might want to take advantage of this.
+ */
+static void atl2_set_msglevel(struct net_device *netdev, u32 data)
+{
+}
+
+static int atl2_get_regs_len(struct net_device *netdev)
+{
+#define ATL2_REGS_LEN 42
+ return sizeof(u32) * ATL2_REGS_LEN;
+}
+
+static void atl2_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+ u32 *regs_buff = p;
+ u16 phy_data;
+
+ memset(p, 0, sizeof(u32) * ATL2_REGS_LEN);
+
+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+ regs_buff[0] = ATL2_READ_REG(hw, REG_VPD_CAP);
+ regs_buff[1] = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ regs_buff[2] = ATL2_READ_REG(hw, REG_SPI_FLASH_CONFIG);
+ regs_buff[3] = ATL2_READ_REG(hw, REG_TWSI_CTRL);
+ regs_buff[4] = ATL2_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
+ regs_buff[5] = ATL2_READ_REG(hw, REG_MASTER_CTRL);
+ regs_buff[6] = ATL2_READ_REG(hw, REG_MANUAL_TIMER_INIT);
+ regs_buff[7] = ATL2_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
+ regs_buff[8] = ATL2_READ_REG(hw, REG_PHY_ENABLE);
+ regs_buff[9] = ATL2_READ_REG(hw, REG_CMBDISDMA_TIMER);
+ regs_buff[10] = ATL2_READ_REG(hw, REG_IDLE_STATUS);
+ regs_buff[11] = ATL2_READ_REG(hw, REG_MDIO_CTRL);
+ regs_buff[12] = ATL2_READ_REG(hw, REG_SERDES_LOCK);
+ regs_buff[13] = ATL2_READ_REG(hw, REG_MAC_CTRL);
+ regs_buff[14] = ATL2_READ_REG(hw, REG_MAC_IPG_IFG);
+ regs_buff[15] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);
+ regs_buff[16] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR+4);
+ regs_buff[17] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE);
+ regs_buff[18] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE+4);
+ regs_buff[19] = ATL2_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
+ regs_buff[20] = ATL2_READ_REG(hw, REG_MTU);
+ regs_buff[21] = ATL2_READ_REG(hw, REG_WOL_CTRL);
+ regs_buff[22] = ATL2_READ_REG(hw, REG_SRAM_TXRAM_END);
+ regs_buff[23] = ATL2_READ_REG(hw, REG_DESC_BASE_ADDR_HI);
+ regs_buff[24] = ATL2_READ_REG(hw, REG_TXD_BASE_ADDR_LO);
+ regs_buff[25] = ATL2_READ_REG(hw, REG_TXD_MEM_SIZE);
+ regs_buff[26] = ATL2_READ_REG(hw, REG_TXS_BASE_ADDR_LO);
+ regs_buff[27] = ATL2_READ_REG(hw, REG_TXS_MEM_SIZE);
+ regs_buff[28] = ATL2_READ_REG(hw, REG_RXD_BASE_ADDR_LO);
+ regs_buff[29] = ATL2_READ_REG(hw, REG_RXD_BUF_NUM);
+ regs_buff[30] = ATL2_READ_REG(hw, REG_DMAR);
+ regs_buff[31] = ATL2_READ_REG(hw, REG_TX_CUT_THRESH);
+ regs_buff[32] = ATL2_READ_REG(hw, REG_DMAW);
+ regs_buff[33] = ATL2_READ_REG(hw, REG_PAUSE_ON_TH);
+ regs_buff[34] = ATL2_READ_REG(hw, REG_PAUSE_OFF_TH);
+ regs_buff[35] = ATL2_READ_REG(hw, REG_MB_TXD_WR_IDX);
+ regs_buff[36] = ATL2_READ_REG(hw, REG_MB_RXD_RD_IDX);
+ regs_buff[38] = ATL2_READ_REG(hw, REG_ISR);
+ regs_buff[39] = ATL2_READ_REG(hw, REG_IMR);
+
+ atl2_read_phy_reg(hw, MII_BMCR, &phy_data);
+ regs_buff[40] = (u32)phy_data;
+ atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
+ regs_buff[41] = (u32)phy_data;
+}
+
+static int atl2_get_eeprom_len(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ if (!atl2_check_eeprom_exist(&adapter->hw))
+ return 512;
+ else
+ return 0;
+}
+
+static int atl2_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ int first_dword, last_dword;
+ int ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ if (atl2_check_eeprom_exist(hw))
+ return -EINVAL;
+
+ eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+ eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1),
+ GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+
+ for (i = first_dword; i < last_dword; i++) {
+ if (!atl2_read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword])))
+ return -EIO;
+ }
+
+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+ return ret_val;
+}
+
+static int atl2_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ struct atl2_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ u32 *ptr;
+ int max_len, first_dword, last_dword, ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ return -EFAULT;
+
+ max_len = 512;
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+ eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+
+ ptr = (u32 *)eeprom_buff;
+
+ if (eeprom->offset & 3) {
+ /* need read/modify/write of first changed EEPROM word */
+ /* only the second byte of the word is being modified */
+ if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0])))
+ return -EIO;
+ ptr++;
+ }
+ if (((eeprom->offset + eeprom->len) & 3)) {
+ /*
+ * need read/modify/write of last changed EEPROM word
+ * only the first byte of the word is being modified
+ */
+ if (!atl2_read_eeprom(hw, last_dword * 4,
+ &(eeprom_buff[last_dword - first_dword])))
+ return -EIO;
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ memcpy(ptr, bytes, eeprom->len);
+
+ for (i = 0; i < last_dword - first_dword + 1; i++) {
+ if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i]))
+ return -EIO;
+ }
+
+ kfree(eeprom_buff);
+ return ret_val;
+}
+
+static void atl2_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ strncpy(drvinfo->driver, atl2_driver_name, 32);
+ strncpy(drvinfo->version, atl2_driver_version, 32);
+ strncpy(drvinfo->fw_version, "L2", 32);
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_stats = 0;
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = atl2_get_regs_len(netdev);
+ drvinfo->eedump_len = atl2_get_eeprom_len(netdev);
+}
+
+static void atl2_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = 0;
+
+ if (adapter->wol & ATLX_WUFC_EX)
+ wol->wolopts |= WAKE_UCAST;
+ if (adapter->wol & ATLX_WUFC_MC)
+ wol->wolopts |= WAKE_MCAST;
+ if (adapter->wol & ATLX_WUFC_BC)
+ wol->wolopts |= WAKE_BCAST;
+ if (adapter->wol & ATLX_WUFC_MAG)
+ wol->wolopts |= WAKE_MAGIC;
+ if (adapter->wol & ATLX_WUFC_LNKC)
+ wol->wolopts |= WAKE_PHY;
+}
+
+static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
+ return -EOPNOTSUPP;
+
+ if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST))
+ return -EOPNOTSUPP;
+
+ /* these settings will always override what we currently have */
+ adapter->wol = 0;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ adapter->wol |= ATLX_WUFC_MAG;
+ if (wol->wolopts & WAKE_PHY)
+ adapter->wol |= ATLX_WUFC_LNKC;
+
+ return 0;
+}
+
+static int atl2_nway_reset(struct net_device *netdev)
+{
+ struct atl2_adapter *adapter = netdev_priv(netdev);
+ if (netif_running(netdev))
+ atl2_reinit_locked(adapter);
+ return 0;
+}
+
+static struct ethtool_ops atl2_ethtool_ops = {
+ .get_settings = atl2_get_settings,
+ .set_settings = atl2_set_settings,
+ .get_drvinfo = atl2_get_drvinfo,
+ .get_regs_len = atl2_get_regs_len,
+ .get_regs = atl2_get_regs,
+ .get_wol = atl2_get_wol,
+ .set_wol = atl2_set_wol,
+ .get_msglevel = atl2_get_msglevel,
+ .set_msglevel = atl2_set_msglevel,
+ .nway_reset = atl2_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = atl2_get_eeprom_len,
+ .get_eeprom = atl2_get_eeprom,
+ .set_eeprom = atl2_set_eeprom,
+ .get_tx_csum = atl2_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+ .get_tso = ethtool_op_get_tso,
+#endif
+};
+
+static void atl2_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops);
+}
+
+#define LBYTESWAP(a) ((((a) & 0x00ff00ff) << 8) | \
+ (((a) & 0xff00ff00) >> 8))
+#define LONGSWAP(a) ((LBYTESWAP(a) << 16) | (LBYTESWAP(a) >> 16))
+#define SHORTSWAP(a) (((a) << 8) | ((a) >> 8))
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+static s32 atl2_reset_hw(struct atl2_hw *hw)
+{
+ u32 icr;
+ u16 pci_cfg_cmd_word;
+ int i;
+
+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+ atl2_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+ if ((pci_cfg_cmd_word &
+ (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) !=
+ (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) {
+ pci_cfg_cmd_word |=
+ (CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER);
+ atl2_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+ }
+
+ /* Clear Interrupt mask to stop board from generating
+ * interrupts & Clear any pending interrupt events
+ */
+ /* FIXME */
+ /* ATL2_WRITE_REG(hw, REG_IMR, 0); */
+ /* ATL2_WRITE_REG(hw, REG_ISR, 0xffffffff); */
+
+ /* Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
+ wmb();
+ msleep(1); /* delay about 1ms */
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (i = 0; i < 10; i++) {
+ icr = ATL2_READ_REG(hw, REG_IDLE_STATUS);
+ if (!icr)
+ break;
+ msleep(1); /* delay 1 ms */
+ cpu_relax();
+ }
+
+ if (icr)
+ return icr;
+
+ return 0;
+}
+
+#define CUSTOM_SPI_CS_SETUP 2
+#define CUSTOM_SPI_CLK_HI 2
+#define CUSTOM_SPI_CLK_LO 2
+#define CUSTOM_SPI_CS_HOLD 2
+#define CUSTOM_SPI_CS_HI 3
+
+static struct atl2_spi_flash_dev flash_table[] =
+{
+/* MFR WRSR READ PROGRAM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE */
+{"Atmel", 0x0, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 },
+{"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 },
+{"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7 },
+};
+
+static bool atl2_spi_read(struct atl2_hw *hw, u32 addr, u32 *buf)
+{
+ int i;
+ u32 value;
+
+ ATL2_WRITE_REG(hw, REG_SPI_DATA, 0);
+ ATL2_WRITE_REG(hw, REG_SPI_ADDR, addr);
+
+ value = SPI_FLASH_CTRL_WAIT_READY |
+ (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+ SPI_FLASH_CTRL_CS_SETUP_SHIFT |
+ (CUSTOM_SPI_CLK_HI & SPI_FLASH_CTRL_CLK_HI_MASK) <<
+ SPI_FLASH_CTRL_CLK_HI_SHIFT |
+ (CUSTOM_SPI_CLK_LO & SPI_FLASH_CTRL_CLK_LO_MASK) <<
+ SPI_FLASH_CTRL_CLK_LO_SHIFT |
+ (CUSTOM_SPI_CS_HOLD & SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+ SPI_FLASH_CTRL_CS_HOLD_SHIFT |
+ (CUSTOM_SPI_CS_HI & SPI_FLASH_CTRL_CS_HI_MASK) <<
+ SPI_FLASH_CTRL_CS_HI_SHIFT |
+ (0x1 & SPI_FLASH_CTRL_INS_MASK) << SPI_FLASH_CTRL_INS_SHIFT;
+
+ ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+
+ value |= SPI_FLASH_CTRL_START;
+
+ ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+
+ for (i = 0; i < 10; i++) {
+ msleep(1);
+ value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (!(value & SPI_FLASH_CTRL_START))
+ break;
+ }
+
+ if (value & SPI_FLASH_CTRL_START)
+ return false;
+
+ *buf = ATL2_READ_REG(hw, REG_SPI_DATA);
+
+ return true;
+}
+
+/*
+ * get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int get_permanent_address(struct atl2_hw *hw)
+{
+ u32 Addr[2];
+ u32 i, Control;
+ u16 Register;
+ u8 EthAddr[NODE_ADDRESS_SIZE];
+ bool KeyValid;
+
+ if (is_valid_ether_addr(hw->perm_mac_addr))
+ return 0;
+
+ Addr[0] = 0;
+ Addr[1] = 0;
+
+ if (!atl2_check_eeprom_exist(hw)) { /* eeprom exists */
+ Register = 0;
+ KeyValid = false;
+
+ /* Read out all EEPROM content */
+ i = 0;
+ while (1) {
+ if (atl2_read_eeprom(hw, i + 0x100, &Control)) {
+ if (KeyValid) {
+ if (Register == REG_MAC_STA_ADDR)
+ Addr[0] = Control;
+ else if (Register ==
+ (REG_MAC_STA_ADDR + 4))
+ Addr[1] = Control;
+ KeyValid = false;
+ } else if ((Control & 0xff) == 0x5A) {
+ KeyValid = true;
+ Register = (u16) (Control >> 16);
+ } else {
+ /* assume data end while encount an invalid KEYWORD */
+ break;
+ }
+ } else {
+ break; /* read error */
+ }
+ i += 4;
+ }
+
+ *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
+ *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);
+
+ if (is_valid_ether_addr(EthAddr)) {
+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
+ return 0;
+ }
+ return 1;
+ }
+
+ /* see if SPI flash exists? */
+ Addr[0] = 0;
+ Addr[1] = 0;
+ Register = 0;
+ KeyValid = false;
+ i = 0;
+ while (1) {
+ if (atl2_spi_read(hw, i + 0x1f000, &Control)) {
+ if (KeyValid) {
+ if (Register == REG_MAC_STA_ADDR)
+ Addr[0] = Control;
+ else if (Register == (REG_MAC_STA_ADDR + 4))
+ Addr[1] = Control;
+ KeyValid = false;
+ } else if ((Control & 0xff) == 0x5A) {
+ KeyValid = true;
+ Register = (u16) (Control >> 16);
+ } else {
+ break; /* data end */
+ }
+ } else {
+ break; /* read error */
+ }
+ i += 4;
+ }
+
+ *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
+ *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *)&Addr[1]);
+ if (is_valid_ether_addr(EthAddr)) {
+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
+ return 0;
+ }
+ /* maybe MAC-address is from BIOS */
+ Addr[0] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);
+ Addr[1] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+ *(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
+ *(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);
+
+ if (is_valid_ether_addr(EthAddr)) {
+ memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static s32 atl2_read_mac_addr(struct atl2_hw *hw)
+{
+ u16 i;
+
+ if (get_permanent_address(hw)) {
+ /* for test */
+ /* FIXME: shouldn't we use random_ether_addr() here? */
+ hw->perm_mac_addr[0] = 0x00;
+ hw->perm_mac_addr[1] = 0x13;
+ hw->perm_mac_addr[2] = 0x74;
+ hw->perm_mac_addr[3] = 0x00;
+ hw->perm_mac_addr[4] = 0x5c;
+ hw->perm_mac_addr[5] = 0x38;
+ }
+
+ for (i = 0; i < NODE_ADDRESS_SIZE; i++)
+ hw->mac_addr[i] = hw->perm_mac_addr[i];
+
+ return 0;
+}
+
+/*
+ * Hashes an address to determine its location in the multicast table
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * atl2_hash_mc_addr
+ * purpose
+ * set hash value for a multicast address
+ * hash calcu processing :
+ * 1. calcu 32bit CRC for multicast address
+ * 2. reverse crc with MSB to LSB
+ */
+static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr)
+{
+ u32 crc32, value;
+ int i;
+
+ value = 0;
+ crc32 = ether_crc_le(6, mc_addr);
+
+ for (i = 0; i < 32; i++)
+ value |= (((crc32 >> i) & 1) << (31 - i));
+
+ return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value)
+{
+ u32 hash_bit, hash_reg;
+ u32 mta;
+
+ /* The HASH Table is a register array of 2 32-bit registers.
+ * It is treated like an array of 64 bits. We want to set
+ * bit BitArray[hash_value]. So we figure out what register
+ * the bit is in, read it, OR in the new bit, then write
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
+ * register are determined by the lower 5 bits of the value.
+ */
+ hash_reg = (hash_value >> 31) & 0x1;
+ hash_bit = (hash_value >> 26) & 0x1F;
+
+ mta = ATL2_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+ mta |= (1 << hash_bit);
+
+ ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+
+/*
+ * atl2_init_pcie - init PCIE module
+ */
+static void atl2_init_pcie(struct atl2_hw *hw)
+{
+ u32 value;
+ value = LTSSM_TEST_MODE_DEF;
+ ATL2_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+
+ value = PCIE_DLL_TX_CTRL1_DEF;
+ ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, value);
+}
+
+static void atl2_init_flash_opcode(struct atl2_hw *hw)
+{
+ if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
+ hw->flash_vendor = 0; /* ATMEL */
+
+ /* Init OP table */
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM,
+ flash_table[hw->flash_vendor].cmdPROGRAM);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE,
+ flash_table[hw->flash_vendor].cmdSECTOR_ERASE);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE,
+ flash_table[hw->flash_vendor].cmdCHIP_ERASE);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID,
+ flash_table[hw->flash_vendor].cmdRDID);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN,
+ flash_table[hw->flash_vendor].cmdWREN);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR,
+ flash_table[hw->flash_vendor].cmdRDSR);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR,
+ flash_table[hw->flash_vendor].cmdWRSR);
+ ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ,
+ flash_table[hw->flash_vendor].cmdREAD);
+}
+
+/********************************************************************
+* Performs basic configuration of the adapter.
+*
+* hw - Struct containing variables accessed by shared code
+* Assumes that the controller has previously been reset and is in a
+* post-reset uninitialized state. Initializes multicast table,
+* and Calls routines to setup link
+* Leaves the transmit and receive units disabled and uninitialized.
+********************************************************************/
+static s32 atl2_init_hw(struct atl2_hw *hw)
+{
+ u32 ret_val = 0;
+
+ atl2_init_pcie(hw);
+
+ /* Zero out the Multicast HASH table */
+ /* clear the old settings from the multicast hash table */
+ ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ atl2_init_flash_opcode(hw);
+
+ ret_val = atl2_phy_init(hw);
+
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
+ u16 *duplex)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Read PHY Specific Status Register (17) */
+ ret_val = atl2_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
+ return ATLX_ERR_PHY_RES;
+
+ switch (phy_data & MII_ATLX_PSSR_SPEED) {
+ case MII_ATLX_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_ATLX_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ return ATLX_ERR_PHY_SPEED;
+ break;
+ }
+
+ if (phy_data & MII_ATLX_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START |
+ MDIO_SUP_PREAMBLE |
+ MDIO_RW |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+ ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16)val;
+ return 0;
+ }
+
+ return ATLX_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+ ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+
+ wmb();
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return ATLX_ERR_PHY;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static s32 atl2_phy_setup_autoneg_adv(struct atl2_hw *hw)
+{
+ s32 ret_val;
+ s16 mii_autoneg_adv_reg;
+
+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+
+ /* Need to parse autoneg_advertised and set up
+ * the appropriate PHY registers. First we will parse for
+ * autoneg_advertised software override. Since we can advertise
+ * a plethora of combinations, we need to check each bit
+ * individually.
+ */
+
+ /* First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T Control Register (Address 9). */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+
+ /* Need to parse MediaType and setup the
+ * appropriate PHY registers. */
+ switch (hw->MediaType) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ mii_autoneg_adv_reg |=
+ (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS|
+ MII_AR_100TX_FD_CAPS);
+ hw->autoneg_advertised =
+ ADVERTISE_10_HALF |
+ ADVERTISE_10_FULL |
+ ADVERTISE_100_HALF|
+ ADVERTISE_100_FULL;
+ break;
+ case MEDIA_TYPE_100M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_FULL;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_HALF;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_FULL;
+ break;
+ default:
+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_HALF;
+ break;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+
+ ret_val = atl2_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+
+ if (ret_val)
+ return ret_val;
+
+ return 0;
+}
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+ */
+static s32 atl2_phy_commit(struct atl2_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+ ret_val = atl2_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /* pcie serdes link may be down ! */
+ for (i = 0; i < 25; i++) {
+ msleep(1);
+ val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+ printk(KERN_ERR "atl2: PCIe link down for at least 25ms !\n");
+ return ret_val;
+ }
+ }
+ return 0;
+}
+
+static s32 atl2_phy_init(struct atl2_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_val;
+
+ if (hw->phy_configured)
+ return 0;
+
+ /* Enable PHY */
+ ATL2_WRITE_REGW(hw, REG_PHY_ENABLE, 1);
+ ATL2_WRITE_FLUSH(hw);
+ msleep(1);
+
+ /* check if the PHY is in powersaving mode */
+ atl2_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);
+
+ /* 024E / 124E 0r 0274 / 1274 ? */
+ if (phy_val & 0x1000) {
+ phy_val &= ~0x1000;
+ atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+ }
+
+ msleep(1);
+
+ /*Enable PHY LinkChange Interrupt */
+ ret_val = atl2_write_phy_reg(hw, 18, 0xC00);
+ if (ret_val)
+ return ret_val;
+
+ /* setup AutoNeg parameters */
+ ret_val = atl2_phy_setup_autoneg_adv(hw);
+ if (ret_val)
+ return ret_val;
+
+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg */
+ ret_val = atl2_phy_commit(hw);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy_configured = true;
+
+ return ret_val;
+}
+
+static void atl2_set_mac_addr(struct atl2_hw *hw)
+{
+ u32 value;
+ /* 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5]));
+ ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+ /* hight dword */
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1]));
+ ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+static int atl2_check_eeprom_exist(struct atl2_hw *hw)
+{
+ u32 value;
+
+ value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+ }
+ value = ATL2_READ_REGW(hw, REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+/* FIXME: This doesn't look right. -- CHS */
+static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value)
+{
+ return true;
+}
+
+static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue)
+{
+ int i;
+ u32 Control;
+
+ if (Offset & 0x3)
+ return false; /* address do not align */
+
+ ATL2_WRITE_REG(hw, REG_VPD_DATA, 0);
+ Control = (Offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+ ATL2_WRITE_REG(hw, REG_VPD_CAP, Control);
+
+ for (i = 0; i < 10; i++) {
+ msleep(2);
+ Control = ATL2_READ_REG(hw, REG_VPD_CAP);
+ if (Control & VPD_CAP_VPD_FLAG)
+ break;
+ }
+
+ if (Control & VPD_CAP_VPD_FLAG) {
+ *pValue = ATL2_READ_REG(hw, REG_VPD_DATA);
+ return true;
+ }
+ return false; /* timeout */
+}
+
+static void atl2_force_ps(struct atl2_hw *hw)
+{
+ u16 phy_val;
+
+ atl2_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);
+ atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val | 0x1000);
+
+ atl2_write_phy_reg(hw, MII_DBG_ADDR, 2);
+ atl2_write_phy_reg(hw, MII_DBG_DATA, 0x3000);
+ atl2_write_phy_reg(hw, MII_DBG_ADDR, 3);
+ atl2_write_phy_reg(hw, MII_DBG_DATA, 0);
+}
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL2_MAX_NIC 4
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+#define ATL2_PARAM_INIT {[0 ... ATL2_MAX_NIC] = OPTION_UNSET}
+#ifndef module_param_array
+/* Module Parameters are always initialized to -1, so that the driver
+ * can tell the difference between no user specified value or the
+ * user asking for the default value.
+ * The true default values are loaded in when atl2_check_options is called.
+ *
+ * This is a GCC extension to ANSI C.
+ * See the item "Labeled Elements in Initializers" in the section
+ * "Extensions to the C Language Family" of the GCC documentation.
+ */
+
+#define ATL2_PARAM(X, desc) \
+ static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
+ MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
+ MODULE_PARM_DESC(X, desc);
+#else
+#define ATL2_PARAM(X, desc) \
+ static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
+ static int num_##X = 0; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
+ MODULE_PARM_DESC(X, desc);
+#endif
+
+/*
+ * Transmit Memory Size
+ * Valid Range: 64-2048
+ * Default Value: 128
+ */
+#define ATL2_MIN_TX_MEMSIZE 4 /* 4KB */
+#define ATL2_MAX_TX_MEMSIZE 64 /* 64KB */
+#define ATL2_DEFAULT_TX_MEMSIZE 8 /* 8KB */
+ATL2_PARAM(TxMemSize, "Bytes of Transmit Memory");
+
+/*
+ * Receive Memory Block Count
+ * Valid Range: 16-512
+ * Default Value: 128
+ */
+#define ATL2_MIN_RXD_COUNT 16
+#define ATL2_MAX_RXD_COUNT 512
+#define ATL2_DEFAULT_RXD_COUNT 64
+ATL2_PARAM(RxMemBlock, "Number of receive memory block");
+
+/*
+ * User Specified MediaType Override
+ *
+ * Valid Range: 0-5
+ * - 0 - auto-negotiate at all supported speeds
+ * - 1 - only link at 1000Mbps Full Duplex
+ * - 2 - only link at 100Mbps Full Duplex
+ * - 3 - only link at 100Mbps Half Duplex
+ * - 4 - only link at 10Mbps Full Duplex
+ * - 5 - only link at 10Mbps Half Duplex
+ * Default Value: 0
+ */
+ATL2_PARAM(MediaType, "MediaType Select");
+
+/*
+ * Interrupt Moderate Timer in units of 2048 ns (~2 us)
+ * Valid Range: 10-65535
+ * Default Value: 45000(90ms)
+ */
+#define INT_MOD_DEFAULT_CNT 100 /* 200us */
+#define INT_MOD_MAX_CNT 65000
+#define INT_MOD_MIN_CNT 50
+ATL2_PARAM(IntModTimer, "Interrupt Moderator Timer");
+
+/*
+ * FlashVendor
+ * Valid Range: 0-2
+ * 0 - Atmel
+ * 1 - SST
+ * 2 - ST
+ */
+ATL2_PARAM(FlashVendor, "SPI Flash Vendor");
+
+#define AUTONEG_ADV_DEFAULT 0x2F
+#define AUTONEG_ADV_MASK 0x2F
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
+
+#define FLASH_VENDOR_DEFAULT 0
+#define FLASH_VENDOR_MIN 0
+#define FLASH_VENDOR_MAX 2
+
+struct atl2_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct atl2_opt_list { int i; char *str; } *p;
+ } l;
+ } arg;
+};
+
+static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
+{
+ int i;
+ struct atl2_opt_list *ent;
+
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ printk(KERN_INFO "%s Enabled\n", opt->name);
+ return 0;
+ break;
+ case OPTION_DISABLED:
+ printk(KERN_INFO "%s Disabled\n", opt->name);
+ return 0;
+ break;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ printk(KERN_INFO "%s set to %i\n", opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option:
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ printk(KERN_INFO "%s\n", ent->str);
+ return 0;
+ }
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ printk(KERN_INFO "Invalid %s specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*
+ * atl2_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+static void __devinit atl2_check_options(struct atl2_adapter *adapter)
+{
+ int val;
+ struct atl2_option opt;
+ int bd = adapter->bd_number;
+ if (bd >= ATL2_MAX_NIC) {
+ printk(KERN_NOTICE "Warning: no configuration for board #%i\n",
+ bd);
+ printk(KERN_NOTICE "Using defaults for all values\n");
+#ifndef module_param_array
+ bd = ATL2_MAX_NIC;
+#endif
+ }
+
+ /* Bytes of Transmit Memory */
+ opt.type = range_option;
+ opt.name = "Bytes of Transmit Memory";
+ opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_TX_MEMSIZE);
+ opt.def = ATL2_DEFAULT_TX_MEMSIZE;
+ opt.arg.r.min = ATL2_MIN_TX_MEMSIZE;
+ opt.arg.r.max = ATL2_MAX_TX_MEMSIZE;
+#ifdef module_param_array
+ if (num_TxMemSize > bd) {
+#endif
+ val = TxMemSize[bd];
+ atl2_validate_option(&val, &opt);
+ adapter->txd_ring_size = ((u32) val) * 1024;
+#ifdef module_param_array
+ } else
+ adapter->txd_ring_size = ((u32)opt.def) * 1024;
+#endif
+ /* txs ring size: */
+ adapter->txs_ring_size = adapter->txd_ring_size / 128;
+ if (adapter->txs_ring_size > 160)
+ adapter->txs_ring_size = 160;
+
+ /* Receive Memory Block Count */
+ opt.type = range_option;
+ opt.name = "Number of receive memory block";
+ opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_RXD_COUNT);
+ opt.def = ATL2_DEFAULT_RXD_COUNT;
+ opt.arg.r.min = ATL2_MIN_RXD_COUNT;
+ opt.arg.r.max = ATL2_MAX_RXD_COUNT;
+#ifdef module_param_array
+ if (num_RxMemBlock > bd) {
+#endif
+ val = RxMemBlock[bd];
+ atl2_validate_option(&val, &opt);
+ adapter->rxd_ring_size = (u32)val;
+ /* FIXME */
+ /* ((u16)val)&~1; */ /* even number */
+#ifdef module_param_array
+ } else
+ adapter->rxd_ring_size = (u32)opt.def;
+#endif
+ /* init RXD Flow control value */
+ adapter->hw.fc_rxd_hi = (adapter->rxd_ring_size / 8) * 7;
+ adapter->hw.fc_rxd_lo = (ATL2_MIN_RXD_COUNT / 8) >
+ (adapter->rxd_ring_size / 12) ? (ATL2_MIN_RXD_COUNT / 8) :
+ (adapter->rxd_ring_size / 12);
+
+ /* Interrupt Moderate Timer */
+ opt.type = range_option;
+ opt.name = "Interrupt Moderate Timer";
+ opt.err = "using default of " __MODULE_STRING(INT_MOD_DEFAULT_CNT);
+ opt.def = INT_MOD_DEFAULT_CNT;
+ opt.arg.r.min = INT_MOD_MIN_CNT;
+ opt.arg.r.max = INT_MOD_MAX_CNT;
+#ifdef module_param_array
+ if (num_IntModTimer > bd) {
+#endif
+ val = IntModTimer[bd];
+ atl2_validate_option(&val, &opt);
+ adapter->imt = (u16) val;
+#ifdef module_param_array
+ } else
+ adapter->imt = (u16)(opt.def);
+#endif
+ /* Flash Vendor */
+ opt.type = range_option;
+ opt.name = "SPI Flash Vendor";
+ opt.err = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT);
+ opt.def = FLASH_VENDOR_DEFAULT;
+ opt.arg.r.min = FLASH_VENDOR_MIN;
+ opt.arg.r.max = FLASH_VENDOR_MAX;
+#ifdef module_param_array
+ if (num_FlashVendor > bd) {
+#endif
+ val = FlashVendor[bd];
+ atl2_validate_option(&val, &opt);
+ adapter->hw.flash_vendor = (u8) val;
+#ifdef module_param_array
+ } else
+ adapter->hw.flash_vendor = (u8)(opt.def);
+#endif
+ /* MediaType */
+ opt.type = range_option;
+ opt.name = "Speed/Duplex Selection";
+ opt.err = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR);
+ opt.def = MEDIA_TYPE_AUTO_SENSOR;
+ opt.arg.r.min = MEDIA_TYPE_AUTO_SENSOR;
+ opt.arg.r.max = MEDIA_TYPE_10M_HALF;
+#ifdef module_param_array
+ if (num_MediaType > bd) {
+#endif
+ val = MediaType[bd];
+ atl2_validate_option(&val, &opt);
+ adapter->hw.MediaType = (u16) val;
+#ifdef module_param_array
+ } else
+ adapter->hw.MediaType = (u16)(opt.def);
+#endif
+}
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
new file mode 100644
index 00000000000..09974df76b1
--- /dev/null
+++ b/drivers/net/atlx/atl2.h
@@ -0,0 +1,529 @@
+/* atl2.h -- atl2 driver definitions
+ *
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.com>
+ * Copyright(c) 2007 Chris Snook <csnook@redhat.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 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.
+ */
+
+#ifndef _ATL2_H_
+#define _ATL2_H_
+
+#include <asm/atomic.h>
+#include <linux/netdevice.h>
+
+#ifndef _ATL2_HW_H_
+#define _ATL2_HW_H_
+
+#ifndef _ATL2_OSDEP_H_
+#define _ATL2_OSDEP_H_
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+
+#include "atlx.h"
+
+#ifdef ETHTOOL_OPS_COMPAT
+extern int ethtool_ioctl(struct ifreq *ifr);
+#endif
+
+#define PCI_COMMAND_REGISTER PCI_COMMAND
+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
+#define ETH_ADDR_LEN ETH_ALEN
+
+#define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \
+ ((a)->hw_addr + (reg))))
+
+#define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr))
+
+#define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg)))
+
+#define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \
+ ((a)->hw_addr + (reg))))
+
+#define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg)))
+
+#define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \
+ ((a)->hw_addr + (reg))))
+
+#define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg)))
+
+#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \
+ (iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2))))
+
+#define ATL2_READ_REG_ARRAY(a, reg, offset) \
+ (ioread32(((a)->hw_addr + (reg)) + ((offset) << 2)))
+
+#endif /* _ATL2_OSDEP_H_ */
+
+struct atl2_adapter;
+struct atl2_hw;
+
+/* function prototype */
+static s32 atl2_reset_hw(struct atl2_hw *hw);
+static s32 atl2_read_mac_addr(struct atl2_hw *hw);
+static s32 atl2_init_hw(struct atl2_hw *hw);
+static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
+ u16 *duplex);
+static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr);
+static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value);
+static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data);
+static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data);
+static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
+static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
+static void atl2_set_mac_addr(struct atl2_hw *hw);
+static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue);
+static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value);
+static s32 atl2_phy_init(struct atl2_hw *hw);
+static int atl2_check_eeprom_exist(struct atl2_hw *hw);
+static void atl2_force_ps(struct atl2_hw *hw);
+
+/* register definition */
+
+/* Block IDLE Status Register */
+#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC is non-IDLE */
+#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC is non-IDLE */
+#define IDLE_STATUS_DMAR 8 /* 1: DMAR is non-IDLE */
+#define IDLE_STATUS_DMAW 4 /* 1: DMAW is non-IDLE */
+
+/* MDIO Control Register */
+#define MDIO_WAIT_TIMES 10
+
+/* MAC Control Register */
+#define MAC_CTRL_DBG_TX_BKPRESURE 0x100000 /* 1: TX max backoff */
+#define MAC_CTRL_MACLP_CLK_PHY 0x8000000 /* 1: 25MHz from phy */
+#define MAC_CTRL_HALF_LEFT_BUF_SHIFT 28
+#define MAC_CTRL_HALF_LEFT_BUF_MASK 0xF /* MAC retry buf x32B */
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TXRAM_END 0x1500 /* Internal tail address of TXRAM
+ * default: 2byte*1024 */
+#define REG_SRAM_RXRAM_END 0x1502 /* Internal tail address of RXRAM
+ * default: 2byte*1024 */
+
+/* Descriptor Control register */
+#define REG_TXD_BASE_ADDR_LO 0x1544 /* The base address of the Transmit
+ * Data Mem low 32-bit(dword align) */
+#define REG_TXD_MEM_SIZE 0x1548 /* Transmit Data Memory size(by
+ * double word , max 256KB) */
+#define REG_TXS_BASE_ADDR_LO 0x154C /* The base address of the Transmit
+ * Status Memory low 32-bit(dword word
+ * align) */
+#define REG_TXS_MEM_SIZE 0x1550 /* double word unit, max 4*2047
+ * bytes. */
+#define REG_RXD_BASE_ADDR_LO 0x1554 /* The base address of the Transmit
+ * Status Memory low 32-bit(unit 8
+ * bytes) */
+#define REG_RXD_BUF_NUM 0x1558 /* Receive Data & Status Memory buffer
+ * number (unit 1536bytes, max
+ * 1536*2047) */
+
+/* DMAR Control Register */
+#define REG_DMAR 0x1580
+#define DMAR_EN 0x1 /* 1: Enable DMAR */
+
+/* TX Cur-Through (early tx threshold) Control Register */
+#define REG_TX_CUT_THRESH 0x1590 /* TxMac begin transmit packet
+ * threshold(unit word) */
+
+/* DMAW Control Register */
+#define REG_DMAW 0x15A0
+#define DMAW_EN 0x1
+
+/* Flow control register */
+#define REG_PAUSE_ON_TH 0x15A8 /* RXD high watermark of overflow
+ * threshold configuration register */
+#define REG_PAUSE_OFF_TH 0x15AA /* RXD lower watermark of overflow
+ * threshold configuration register */
+
+/* Mailbox Register */
+#define REG_MB_TXD_WR_IDX 0x15f0 /* double word align */
+#define REG_MB_RXD_RD_IDX 0x15F4 /* RXD Read index (unit: 1536byets) */
+
+/* Interrupt Status Register */
+#define ISR_TIMER 1 /* Interrupt when Timer counts down to zero */
+#define ISR_MANUAL 2 /* Software manual interrupt, for debug. Set
+ * when SW_MAN_INT_EN is set in Table 51
+ * Selene Master Control Register
+ * (Offset 0x1400). */
+#define ISR_RXF_OV 4 /* RXF overflow interrupt */
+#define ISR_TXF_UR 8 /* TXF underrun interrupt */
+#define ISR_TXS_OV 0x10 /* Internal transmit status buffer full
+ * interrupt */
+#define ISR_RXS_OV 0x20 /* Internal receive status buffer full
+ * interrupt */
+#define ISR_LINK_CHG 0x40 /* Link Status Change Interrupt */
+#define ISR_HOST_TXD_UR 0x80
+#define ISR_HOST_RXD_OV 0x100 /* Host rx data memory full , one pulse */
+#define ISR_DMAR_TO_RST 0x200 /* DMAR op timeout interrupt. SW should
+ * do Reset */
+#define ISR_DMAW_TO_RST 0x400
+#define ISR_PHY 0x800 /* phy interrupt */
+#define ISR_TS_UPDATE 0x10000 /* interrupt after new tx pkt status written
+ * to host */
+#define ISR_RS_UPDATE 0x20000 /* interrupt ater new rx pkt status written
+ * to host. */
+#define ISR_TX_EARLY 0x40000 /* interrupt when txmac begin transmit one
+ * packet */
+
+#define ISR_TX_EVENT (ISR_TXF_UR | ISR_TXS_OV | ISR_HOST_TXD_UR |\
+ ISR_TS_UPDATE | ISR_TX_EARLY)
+#define ISR_RX_EVENT (ISR_RXF_OV | ISR_RXS_OV | ISR_HOST_RXD_OV |\
+ ISR_RS_UPDATE)
+
+#define IMR_NORMAL_MASK (\
+ /*ISR_LINK_CHG |*/\
+ ISR_MANUAL |\
+ ISR_DMAR_TO_RST |\
+ ISR_DMAW_TO_RST |\
+ ISR_PHY |\
+ ISR_PHY_LINKDOWN |\
+ ISR_TS_UPDATE |\
+ ISR_RS_UPDATE)
+
+/* Receive MAC Statistics Registers */
+#define REG_STS_RX_PAUSE 0x1700 /* Num pause packets received */
+#define REG_STS_RXD_OV 0x1704 /* Num frames dropped due to RX
+ * FIFO overflow */
+#define REG_STS_RXS_OV 0x1708 /* Num frames dropped due to RX
+ * Status Buffer Overflow */
+#define REG_STS_RX_FILTER 0x170C /* Num packets dropped due to
+ * address filtering */
+
+/* MII definitions */
+
+/* PHY Common Register */
+#define MII_SMARTSPEED 0x14
+#define MII_DBG_ADDR 0x1D
+#define MII_DBG_DATA 0x1E
+
+/* PCI Command Register Bit Definitions */
+#define PCI_REG_COMMAND 0x04
+#define CMD_IO_SPACE 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER 0x0004
+
+#define MEDIA_TYPE_100M_FULL 1
+#define MEDIA_TYPE_100M_HALF 2
+#define MEDIA_TYPE_10M_FULL 3
+#define MEDIA_TYPE_10M_HALF 4
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x000F /* Everything */
+
+/* The size (in bytes) of a ethernet packet */
+#define ENET_HEADER_SIZE 14
+#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */
+#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */
+#define ETHERNET_FCS_SIZE 4
+#define MAX_JUMBO_FRAME_SIZE 0x2000
+#define VLAN_SIZE 4
+
+struct tx_pkt_header {
+ unsigned pkt_size:11;
+ unsigned:4; /* reserved */
+ unsigned ins_vlan:1; /* txmac should insert vlan */
+ unsigned short vlan; /* vlan tag */
+};
+/* FIXME: replace above bitfields with MASK/SHIFT defines below */
+#define TX_PKT_HEADER_SIZE_MASK 0x7FF
+#define TX_PKT_HEADER_SIZE_SHIFT 0
+#define TX_PKT_HEADER_INS_VLAN_MASK 0x1
+#define TX_PKT_HEADER_INS_VLAN_SHIFT 15
+#define TX_PKT_HEADER_VLAN_TAG_MASK 0xFFFF
+#define TX_PKT_HEADER_VLAN_TAG_SHIFT 16
+
+struct tx_pkt_status {
+ unsigned pkt_size:11;
+ unsigned:5; /* reserved */
+ unsigned ok:1; /* current packet transmitted without error */
+ unsigned bcast:1; /* broadcast packet */
+ unsigned mcast:1; /* multicast packet */
+ unsigned pause:1; /* transmiited a pause frame */
+ unsigned ctrl:1;
+ unsigned defer:1; /* current packet is xmitted with defer */
+ unsigned exc_defer:1;
+ unsigned single_col:1;
+ unsigned multi_col:1;
+ unsigned late_col:1;
+ unsigned abort_col:1;
+ unsigned underun:1; /* current packet is aborted
+ * due to txram underrun */
+ unsigned:3; /* reserved */
+ unsigned update:1; /* always 1'b1 in tx_status_buf */
+};
+/* FIXME: replace above bitfields with MASK/SHIFT defines below */
+#define TX_PKT_STATUS_SIZE_MASK 0x7FF
+#define TX_PKT_STATUS_SIZE_SHIFT 0
+#define TX_PKT_STATUS_OK_MASK 0x1
+#define TX_PKT_STATUS_OK_SHIFT 16
+#define TX_PKT_STATUS_BCAST_MASK 0x1
+#define TX_PKT_STATUS_BCAST_SHIFT 17
+#define TX_PKT_STATUS_MCAST_MASK 0x1
+#define TX_PKT_STATUS_MCAST_SHIFT 18
+#define TX_PKT_STATUS_PAUSE_MASK 0x1
+#define TX_PKT_STATUS_PAUSE_SHIFT 19
+#define TX_PKT_STATUS_CTRL_MASK 0x1
+#define TX_PKT_STATUS_CTRL_SHIFT 20
+#define TX_PKT_STATUS_DEFER_MASK 0x1
+#define TX_PKT_STATUS_DEFER_SHIFT 21
+#define TX_PKT_STATUS_EXC_DEFER_MASK 0x1
+#define TX_PKT_STATUS_EXC_DEFER_SHIFT 22
+#define TX_PKT_STATUS_SINGLE_COL_MASK 0x1
+#define TX_PKT_STATUS_SINGLE_COL_SHIFT 23
+#define TX_PKT_STATUS_MULTI_COL_MASK 0x1
+#define TX_PKT_STATUS_MULTI_COL_SHIFT 24
+#define TX_PKT_STATUS_LATE_COL_MASK 0x1
+#define TX_PKT_STATUS_LATE_COL_SHIFT 25
+#define TX_PKT_STATUS_ABORT_COL_MASK 0x1
+#define TX_PKT_STATUS_ABORT_COL_SHIFT 26
+#define TX_PKT_STATUS_UNDERRUN_MASK 0x1
+#define TX_PKT_STATUS_UNDERRUN_SHIFT 27
+#define TX_PKT_STATUS_UPDATE_MASK 0x1
+#define TX_PKT_STATUS_UPDATE_SHIFT 31
+
+struct rx_pkt_status {
+ unsigned pkt_size:11; /* packet size, max 2047 bytes */
+ unsigned:5; /* reserved */
+ unsigned ok:1; /* current packet received ok without error */
+ unsigned bcast:1; /* current packet is broadcast */
+ unsigned mcast:1; /* current packet is multicast */
+ unsigned pause:1;
+ unsigned ctrl:1;
+ unsigned crc:1; /* received a packet with crc error */
+ unsigned code:1; /* received a packet with code error */
+ unsigned runt:1; /* received a packet less than 64 bytes
+ * with good crc */
+ unsigned frag:1; /* received a packet less than 64 bytes
+ * with bad crc */
+ unsigned trunc:1; /* current frame truncated due to rxram full */
+ unsigned align:1; /* this packet is alignment error */
+ unsigned vlan:1; /* this packet has vlan */
+ unsigned:3; /* reserved */
+ unsigned update:1;
+ unsigned short vtag; /* vlan tag */
+ unsigned:16;
+};
+/* FIXME: replace above bitfields with MASK/SHIFT defines below */
+#define RX_PKT_STATUS_SIZE_MASK 0x7FF
+#define RX_PKT_STATUS_SIZE_SHIFT 0
+#define RX_PKT_STATUS_OK_MASK 0x1
+#define RX_PKT_STATUS_OK_SHIFT 16
+#define RX_PKT_STATUS_BCAST_MASK 0x1
+#define RX_PKT_STATUS_BCAST_SHIFT 17
+#define RX_PKT_STATUS_MCAST_MASK 0x1
+#define RX_PKT_STATUS_MCAST_SHIFT 18
+#define RX_PKT_STATUS_PAUSE_MASK 0x1
+#define RX_PKT_STATUS_PAUSE_SHIFT 19
+#define RX_PKT_STATUS_CTRL_MASK 0x1
+#define RX_PKT_STATUS_CTRL_SHIFT 20
+#define RX_PKT_STATUS_CRC_MASK 0x1
+#define RX_PKT_STATUS_CRC_SHIFT 21
+#define RX_PKT_STATUS_CODE_MASK 0x1
+#define RX_PKT_STATUS_CODE_SHIFT 22
+#define RX_PKT_STATUS_RUNT_MASK 0x1
+#define RX_PKT_STATUS_RUNT_SHIFT 23
+#define RX_PKT_STATUS_FRAG_MASK 0x1
+#define RX_PKT_STATUS_FRAG_SHIFT 24
+#define RX_PKT_STATUS_TRUNK_MASK 0x1
+#define RX_PKT_STATUS_TRUNK_SHIFT 25
+#define RX_PKT_STATUS_ALIGN_MASK 0x1
+#define RX_PKT_STATUS_ALIGN_SHIFT 26
+#define RX_PKT_STATUS_VLAN_MASK 0x1
+#define RX_PKT_STATUS_VLAN_SHIFT 27
+#define RX_PKT_STATUS_UPDATE_MASK 0x1
+#define RX_PKT_STATUS_UPDATE_SHIFT 31
+#define RX_PKT_STATUS_VLAN_TAG_MASK 0xFFFF
+#define RX_PKT_STATUS_VLAN_TAG_SHIFT 32
+
+struct rx_desc {
+ struct rx_pkt_status status;
+ unsigned char packet[1536-sizeof(struct rx_pkt_status)];
+};
+
+enum atl2_speed_duplex {
+ atl2_10_half = 0,
+ atl2_10_full = 1,
+ atl2_100_half = 2,
+ atl2_100_full = 3
+};
+
+struct atl2_spi_flash_dev {
+ const char *manu_name; /* manufacturer id */
+ /* op-code */
+ u8 cmdWRSR;
+ u8 cmdREAD;
+ u8 cmdPROGRAM;
+ u8 cmdWREN;
+ u8 cmdWRDI;
+ u8 cmdRDSR;
+ u8 cmdRDID;
+ u8 cmdSECTOR_ERASE;
+ u8 cmdCHIP_ERASE;
+};
+
+/* Structure containing variables used by the shared code (atl2_hw.c) */
+struct atl2_hw {
+ u8 __iomem *hw_addr;
+ void *back;
+
+ u8 preamble_len;
+ u8 max_retry; /* Retransmission maximum, afterwards the
+ * packet will be discarded. */
+ u8 jam_ipg; /* IPG to start JAM for collision based flow
+ * control in half-duplex mode. In unit of
+ * 8-bit time. */
+ u8 ipgt; /* Desired back to back inter-packet gap. The
+ * default is 96-bit time. */
+ u8 min_ifg; /* Minimum number of IFG to enforce in between
+ * RX frames. Frame gap below such IFP is
+ * dropped. */
+ u8 ipgr1; /* 64bit Carrier-Sense window */
+ u8 ipgr2; /* 96-bit IPG window */
+ u8 retry_buf; /* When half-duplex mode, should hold some
+ * bytes for mac retry . (8*4bytes unit) */
+
+ u16 fc_rxd_hi;
+ u16 fc_rxd_lo;
+ u16 lcol; /* Collision Window */
+ u16 max_frame_size;
+
+ u16 MediaType;
+ u16 autoneg_advertised;
+ u16 pci_cmd_word;
+
+ u16 mii_autoneg_adv_reg;
+
+ u32 mem_rang;
+ u32 txcw;
+ u32 mc_filter_type;
+ u32 num_mc_addrs;
+ u32 collision_delta;
+ u32 tx_packet_delta;
+ u16 phy_spd_default;
+
+ u16 device_id;
+ u16 vendor_id;
+ u16 subsystem_id;
+ u16 subsystem_vendor_id;
+ u8 revision_id;
+
+ /* spi flash */
+ u8 flash_vendor;
+
+ u8 dma_fairness;
+ u8 mac_addr[NODE_ADDRESS_SIZE];
+ u8 perm_mac_addr[NODE_ADDRESS_SIZE];
+
+ /* FIXME */
+ /* bool phy_preamble_sup; */
+ bool phy_configured;
+};
+
+#endif /* _ATL2_HW_H_ */
+
+struct atl2_ring_header {
+ /* pointer to the descriptor ring memory */
+ void *desc;
+ /* physical adress of the descriptor ring */
+ dma_addr_t dma;
+ /* length of descriptor ring in bytes */
+ unsigned int size;
+};
+
+/* board specific private data structure */
+struct atl2_adapter {
+ /* OS defined structs */
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct net_device_stats net_stats;
+#ifdef NETIF_F_HW_VLAN_TX
+ struct vlan_group *vlgrp;
+#endif
+ u32 wol;
+ u16 link_speed;
+ u16 link_duplex;
+
+ spinlock_t stats_lock;
+
+ struct work_struct reset_task;
+ struct work_struct link_chg_task;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_config_timer;
+
+ unsigned long cfg_phy;
+ bool mac_disabled;
+
+ /* All Descriptor memory */
+ dma_addr_t ring_dma;
+ void *ring_vir_addr;
+ int ring_size;
+
+ struct tx_pkt_header *txd_ring;
+ dma_addr_t txd_dma;
+
+ struct tx_pkt_status *txs_ring;
+ dma_addr_t txs_dma;
+
+ struct rx_desc *rxd_ring;
+ dma_addr_t rxd_dma;
+
+ u32 txd_ring_size; /* bytes per unit */
+ u32 txs_ring_size; /* dwords per unit */
+ u32 rxd_ring_size; /* 1536 bytes per unit */
+
+ /* read /write ptr: */
+ /* host */
+ u32 txd_write_ptr;
+ u32 txs_next_clear;
+ u32 rxd_read_ptr;
+
+ /* nic */
+ atomic_t txd_read_ptr;
+ atomic_t txs_write_ptr;
+ u32 rxd_write_ptr;
+
+ /* Interrupt Moderator timer ( 2us resolution) */
+ u16 imt;
+ /* Interrupt Clear timer (2us resolution) */
+ u16 ict;
+
+ unsigned long flags;
+ /* structs defined in atl2_hw.h */
+ u32 bd_number; /* board number */
+ bool pci_using_64;
+ bool have_msi;
+ struct atl2_hw hw;
+
+ u32 usr_cmd;
+ /* FIXME */
+ /* u32 regs_buff[ATL2_REGS_LEN]; */
+ u32 pci_state[16];
+
+ u32 *config_space;
+};
+
+enum atl2_state_t {
+ __ATL2_TESTING,
+ __ATL2_RESETTING,
+ __ATL2_DOWN
+};
+
+#endif /* _ATL2_H_ */
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index b3e7fcf0f6e..3cc9d1089ca 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -105,7 +105,6 @@ static void atlx_check_for_link(struct atlx_adapter *adapter)
netdev->name);
adapter->link_speed = SPEED_0;
netif_carrier_off(netdev);
- netif_stop_queue(netdev);
}
}
schedule_work(&adapter->link_chg_task);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 5ee1b0557a0..019b13c08ae 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -94,8 +94,8 @@ static irqreturn_t au1000_interrupt(int, void *);
static void au1000_tx_timeout(struct net_device *);
static void set_rx_mode(struct net_device *);
static int au1000_ioctl(struct net_device *, struct ifreq *, int);
-static int mdio_read(struct net_device *, int, int);
-static void mdio_write(struct net_device *, int, int, u16);
+static int au1000_mdio_read(struct net_device *, int, int);
+static void au1000_mdio_write(struct net_device *, int, int, u16);
static void au1000_adjust_link(struct net_device *);
static void enable_mac(struct net_device *, int);
@@ -191,7 +191,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
/*
* MII operations
*/
-static int mdio_read(struct net_device *dev, int phy_addr, int reg)
+static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
@@ -225,7 +225,8 @@ static int mdio_read(struct net_device *dev, int phy_addr, int reg)
return (int)*mii_data_reg;
}
-static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
+static void au1000_mdio_write(struct net_device *dev, int phy_addr,
+ int reg, u16 value)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
@@ -249,7 +250,7 @@ static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
*mii_control_reg = mii_control;
}
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
{
/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
* _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
@@ -257,21 +258,21 @@ static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
enable_mac(dev, 0); /* make sure the MAC associated with this
* mii_bus is enabled */
- return mdio_read(dev, phy_addr, regnum);
+ return au1000_mdio_read(dev, phy_addr, regnum);
}
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
- u16 value)
+static int au1000_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 value)
{
struct net_device *const dev = bus->priv;
enable_mac(dev, 0); /* make sure the MAC associated with this
* mii_bus is enabled */
- mdio_write(dev, phy_addr, regnum, value);
+ au1000_mdio_write(dev, phy_addr, regnum, value);
return 0;
}
-static int mdiobus_reset(struct mii_bus *bus)
+static int au1000_mdiobus_reset(struct mii_bus *bus)
{
struct net_device *const dev = bus->priv;
@@ -290,7 +291,7 @@ static int mii_probe (struct net_device *dev)
if(aup->mac_id == 0) { /* get PHY0 */
# if defined(AU1XXX_PHY0_ADDR)
- phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus.phy_map[AU1XXX_PHY0_ADDR];
+ phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus->phy_map[AU1XXX_PHY0_ADDR];
# else
printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
dev->name);
@@ -298,7 +299,7 @@ static int mii_probe (struct net_device *dev)
# endif /* defined(AU1XXX_PHY0_ADDR) */
} else if (aup->mac_id == 1) { /* get PHY1 */
# if defined(AU1XXX_PHY1_ADDR)
- phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus.phy_map[AU1XXX_PHY1_ADDR];
+ phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus->phy_map[AU1XXX_PHY1_ADDR];
# else
printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
dev->name);
@@ -311,8 +312,8 @@ static int mii_probe (struct net_device *dev)
/* find the first (lowest address) PHY on the current MAC's MII bus */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
- if (aup->mii_bus.phy_map[phy_addr]) {
- phydev = aup->mii_bus.phy_map[phy_addr];
+ if (aup->mii_bus->phy_map[phy_addr]) {
+ phydev = aup->mii_bus->phy_map[phy_addr];
# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
break; /* break out with first one found */
# endif
@@ -331,7 +332,7 @@ static int mii_probe (struct net_device *dev)
* the MAC0 MII bus */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
struct phy_device *const tmp_phydev =
- au_macs[0]->mii_bus.phy_map[phy_addr];
+ au_macs[0]->mii_bus->phy_map[phy_addr];
if (!tmp_phydev)
continue; /* no PHY here... */
@@ -653,6 +654,8 @@ static struct net_device * au1000_probe(int port_num)
aup = dev->priv;
+ spin_lock_init(&aup->lock);
+
/* Allocate the data buffers */
/* Snooping works fine with eth on all au1xxx */
aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
@@ -696,28 +699,32 @@ static struct net_device * au1000_probe(int port_num)
*aup->enable = 0;
aup->mac_enabled = 0;
- aup->mii_bus.priv = dev;
- aup->mii_bus.read = mdiobus_read;
- aup->mii_bus.write = mdiobus_write;
- aup->mii_bus.reset = mdiobus_reset;
- aup->mii_bus.name = "au1000_eth_mii";
- snprintf(aup->mii_bus.id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
- aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ aup->mii_bus = mdiobus_alloc();
+ if (aup->mii_bus == NULL)
+ goto err_out;
+
+ aup->mii_bus->priv = dev;
+ aup->mii_bus->read = au1000_mdiobus_read;
+ aup->mii_bus->write = au1000_mdiobus_write;
+ aup->mii_bus->reset = au1000_mdiobus_reset;
+ aup->mii_bus->name = "au1000_eth_mii";
+ snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+ aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
for(i = 0; i < PHY_MAX_ADDR; ++i)
- aup->mii_bus.irq[i] = PHY_POLL;
+ aup->mii_bus->irq[i] = PHY_POLL;
/* if known, set corresponding PHY IRQs */
#if defined(AU1XXX_PHY_STATIC_CONFIG)
# if defined(AU1XXX_PHY0_IRQ)
if (AU1XXX_PHY0_BUSID == aup->mac_id)
- aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+ aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
# endif
# if defined(AU1XXX_PHY1_IRQ)
if (AU1XXX_PHY1_BUSID == aup->mac_id)
- aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+ aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
# endif
#endif
- mdiobus_register(&aup->mii_bus);
+ mdiobus_register(aup->mii_bus);
if (mii_probe(dev) != 0) {
goto err_out;
@@ -753,7 +760,6 @@ static struct net_device * au1000_probe(int port_num)
aup->tx_db_inuse[i] = pDB;
}
- spin_lock_init(&aup->lock);
dev->base_addr = base;
dev->irq = irq;
dev->open = au1000_open;
@@ -774,6 +780,11 @@ static struct net_device * au1000_probe(int port_num)
return dev;
err_out:
+ if (aup->mii_bus != NULL) {
+ mdiobus_unregister(aup->mii_bus);
+ mdiobus_free(aup->mii_bus);
+ }
+
/* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.*/
reset_mac(dev);
@@ -1004,6 +1015,8 @@ static void __exit au1000_cleanup_module(void)
if (dev) {
aup = (struct au1000_private *) dev->priv;
unregister_netdev(dev);
+ mdiobus_unregister(aup->mii_bus);
+ mdiobus_free(aup->mii_bus);
for (j = 0; j < NUM_RX_DMA; j++)
if (aup->rx_db_inuse[j])
ReleaseDB(aup, aup->rx_db_inuse[j]);
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index f3baeaa1285..824ecd5ff3a 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -106,7 +106,7 @@ struct au1000_private {
int old_duplex;
struct phy_device *phy_dev;
- struct mii_bus mii_bus;
+ struct mii_bus *mii_bus;
/* These variables are just for quick access to certain regs addresses. */
volatile mac_reg_t *mac; /* mac registers */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index a886a4b9f7e..4207d6efddc 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -153,7 +153,7 @@ static void ax_reset_8390(struct net_device *dev)
while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
if (jiffies - reset_start_time > 2*HZ/100) {
dev_warn(&ax->dev->dev, "%s: %s did not complete.\n",
- __FUNCTION__, dev->name);
+ __func__, dev->name);
break;
}
}
@@ -173,7 +173,7 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
if (ei_status.dmaing) {
dev_err(&ax->dev->dev, "%s: DMAing conflict in %s "
"[DMAstat:%d][irqlock:%d].\n",
- dev->name, __FUNCTION__,
+ dev->name, __func__,
ei_status.dmaing, ei_status.irqlock);
return;
}
@@ -215,7 +215,7 @@ static void ax_block_input(struct net_device *dev, int count,
dev_err(&ax->dev->dev,
"%s: DMAing conflict in %s "
"[DMAstat:%d][irqlock:%d].\n",
- dev->name, __FUNCTION__,
+ dev->name, __func__,
ei_status.dmaing, ei_status.irqlock);
return;
}
@@ -260,7 +260,7 @@ static void ax_block_output(struct net_device *dev, int count,
if (ei_status.dmaing) {
dev_err(&ax->dev->dev, "%s: DMAing conflict in %s."
"[DMAstat:%d][irqlock:%d]\n",
- dev->name, __FUNCTION__,
+ dev->name, __func__,
ei_status.dmaing, ei_status.irqlock);
return;
}
@@ -396,7 +396,7 @@ ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
{
if (phy_debug)
pr_debug("%s: dev %p, %04x, %04x, %d\n",
- __FUNCTION__, dev, phy_addr, reg, opc);
+ __func__, dev, phy_addr, reg, opc);
ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */
ax_mii_ei_outbits(dev, 1, 2); /* frame-start */
@@ -422,7 +422,7 @@ ax_phy_read(struct net_device *dev, int phy_addr, int reg)
spin_unlock_irqrestore(&ei_local->page_lock, flags);
if (phy_debug)
- pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+ pr_debug("%s: %04x.%04x => read %04x\n", __func__,
phy_addr, reg, result);
return result;
@@ -436,7 +436,7 @@ ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
unsigned long flags;
dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n",
- __FUNCTION__, dev, phy_addr, reg, value);
+ __func__, dev, phy_addr, reg, value);
spin_lock_irqsave(&ei->page_lock, flags);
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 3db7db1828e..b458d607a9c 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -253,7 +253,7 @@ init_error:
* MII operations
*/
/* Wait until the previous MDC/MDIO transaction has completed */
-static void mdio_poll(void)
+static void bfin_mdio_poll(void)
{
int timeout_cnt = MAX_TIMEOUT_CNT;
@@ -269,25 +269,25 @@ static void mdio_poll(void)
}
/* Read an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
{
- mdio_poll();
+ bfin_mdio_poll();
/* read mode */
bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
SET_REGAD((u16) regnum) |
STABUSY);
- mdio_poll();
+ bfin_mdio_poll();
return (int) bfin_read_EMAC_STADAT();
}
/* Write an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
- u16 value)
+static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 value)
{
- mdio_poll();
+ bfin_mdio_poll();
bfin_write_EMAC_STADAT((u32) value);
@@ -297,12 +297,12 @@ static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
STAOP |
STABUSY);
- mdio_poll();
+ bfin_mdio_poll();
return 0;
}
-static int mdiobus_reset(struct mii_bus *bus)
+static int bfin_mdiobus_reset(struct mii_bus *bus)
{
return 0;
}
@@ -398,7 +398,7 @@ static int mii_probe(struct net_device *dev)
/* search for connect PHY device */
for (i = 0; i < PHY_MAX_ADDR; i++) {
- struct phy_device *const tmp_phydev = lp->mii_bus.phy_map[i];
+ struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
if (!tmp_phydev)
continue; /* no PHY here... */
@@ -811,14 +811,14 @@ static void bfin_mac_enable(void)
{
u32 opmode;
- pr_debug("%s: %s\n", DRV_NAME, __FUNCTION__);
+ pr_debug("%s: %s\n", DRV_NAME, __func__);
/* Set RX DMA */
bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
/* Wait MII done */
- mdio_poll();
+ bfin_mdio_poll();
/* We enable only RX here */
/* ASTP : Enable Automatic Pad Stripping
@@ -847,7 +847,7 @@ static void bfin_mac_enable(void)
/* Our watchdog timed out. Called by the networking layer */
static void bfin_mac_timeout(struct net_device *dev)
{
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
bfin_mac_disable();
@@ -949,7 +949,7 @@ static int bfin_mac_open(struct net_device *dev)
{
struct bfin_mac_local *lp = netdev_priv(dev);
int retval;
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
/*
* Check that the address is valid. If its not, refuse
@@ -989,7 +989,7 @@ static int bfin_mac_open(struct net_device *dev)
static int bfin_mac_close(struct net_device *dev)
{
struct bfin_mac_local *lp = netdev_priv(dev);
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
netif_stop_queue(dev);
netif_carrier_off(dev);
@@ -1058,17 +1058,21 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
setup_mac_addr(ndev->dev_addr);
/* MDIO bus initial */
- lp->mii_bus.priv = ndev;
- lp->mii_bus.read = mdiobus_read;
- lp->mii_bus.write = mdiobus_write;
- lp->mii_bus.reset = mdiobus_reset;
- lp->mii_bus.name = "bfin_mac_mdio";
- snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "0");
- lp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ lp->mii_bus = mdiobus_alloc();
+ if (lp->mii_bus == NULL)
+ goto out_err_mdiobus_alloc;
+
+ lp->mii_bus->priv = ndev;
+ lp->mii_bus->read = bfin_mdiobus_read;
+ lp->mii_bus->write = bfin_mdiobus_write;
+ lp->mii_bus->reset = bfin_mdiobus_reset;
+ lp->mii_bus->name = "bfin_mac_mdio";
+ snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0");
+ lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
for (i = 0; i < PHY_MAX_ADDR; ++i)
- lp->mii_bus.irq[i] = PHY_POLL;
+ lp->mii_bus->irq[i] = PHY_POLL;
- rc = mdiobus_register(&lp->mii_bus);
+ rc = mdiobus_register(lp->mii_bus);
if (rc) {
dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
goto out_err_mdiobus_register;
@@ -1121,8 +1125,10 @@ out_err_reg_ndev:
free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
out_err_mii_probe:
- mdiobus_unregister(&lp->mii_bus);
+ mdiobus_unregister(lp->mii_bus);
out_err_mdiobus_register:
+ mdiobus_free(lp->mii_bus);
+out_err_mdiobus_alloc:
peripheral_free_list(pin_req);
out_err_setup_pin_mux:
out_err_probe_mac:
@@ -1139,7 +1145,8 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- mdiobus_unregister(&lp->mii_bus);
+ mdiobus_unregister(lp->mii_bus);
+ mdiobus_free(lp->mii_bus);
unregister_netdev(ndev);
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
index beff51064ff..052b5dce3e3 100644
--- a/drivers/net/bfin_mac.h
+++ b/drivers/net/bfin_mac.h
@@ -66,7 +66,7 @@ struct bfin_mac_local {
int old_duplex;
struct phy_device *phydev;
- struct mii_bus mii_bus;
+ struct mii_bus *mii_bus;
};
extern void bfin_get_ether_addr(char *addr);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2486a656f12..430d430bce2 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -57,8 +57,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.8.0"
-#define DRV_MODULE_RELDATE "Aug 14, 2008"
+#define DRV_MODULE_VERSION "1.8.1"
+#define DRV_MODULE_RELDATE "Oct 7, 2008"
#define RUN_AT(x) (jiffies + (x))
@@ -69,7 +69,7 @@ static char version[] __devinitdata =
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -1127,7 +1127,7 @@ bnx2_init_all_rx_contexts(struct bnx2 *bp)
}
}
-static int
+static void
bnx2_set_mac_link(struct bnx2 *bp)
{
u32 val;
@@ -1193,8 +1193,6 @@ bnx2_set_mac_link(struct bnx2 *bp)
if (CHIP_NUM(bp) == CHIP_NUM_5709)
bnx2_init_all_rx_contexts(bp);
-
- return 0;
}
static void
@@ -2478,6 +2476,11 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
return -ENOMEM;
mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(bp->pdev, mapping)) {
+ __free_page(page);
+ return -EIO;
+ }
+
rx_pg->page = page;
pci_unmap_addr_set(rx_pg, mapping, mapping);
rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
@@ -2520,6 +2523,10 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(bp->pdev, mapping)) {
+ dev_kfree_skb(skb);
+ return -EIO;
+ }
rx_buf->skb = skb;
pci_unmap_addr_set(rx_buf, mapping, mapping);
@@ -2594,7 +2601,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
sw_cons = txr->tx_cons;
while (sw_cons != hw_cons) {
- struct sw_bd *tx_buf;
+ struct sw_tx_bd *tx_buf;
struct sk_buff *skb;
int i, last;
@@ -2619,21 +2626,13 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
}
}
- pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping),
- skb_headlen(skb), PCI_DMA_TODEVICE);
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
tx_buf->skb = NULL;
last = skb_shinfo(skb)->nr_frags;
for (i = 0; i < last; i++) {
sw_cons = NEXT_TX_BD(sw_cons);
-
- pci_unmap_page(bp->pdev,
- pci_unmap_addr(
- &txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
- mapping),
- skb_shinfo(skb)->frags[i].size,
- PCI_DMA_TODEVICE);
}
sw_cons = NEXT_TX_BD(sw_cons);
@@ -2674,11 +2673,31 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
{
struct sw_pg *cons_rx_pg, *prod_rx_pg;
struct rx_bd *cons_bd, *prod_bd;
- dma_addr_t mapping;
int i;
- u16 hw_prod = rxr->rx_pg_prod, prod;
+ u16 hw_prod, prod;
u16 cons = rxr->rx_pg_cons;
+ cons_rx_pg = &rxr->rx_pg_ring[cons];
+
+ /* The caller was unable to allocate a new page to replace the
+ * last one in the frags array, so we need to recycle that page
+ * and then free the skb.
+ */
+ if (skb) {
+ struct page *page;
+ struct skb_shared_info *shinfo;
+
+ shinfo = skb_shinfo(skb);
+ shinfo->nr_frags--;
+ page = shinfo->frags[shinfo->nr_frags].page;
+ shinfo->frags[shinfo->nr_frags].page = NULL;
+
+ cons_rx_pg->page = page;
+ dev_kfree_skb(skb);
+ }
+
+ hw_prod = rxr->rx_pg_prod;
+
for (i = 0; i < count; i++) {
prod = RX_PG_RING_IDX(hw_prod);
@@ -2687,20 +2706,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
- if (i == 0 && skb) {
- struct page *page;
- struct skb_shared_info *shinfo;
-
- shinfo = skb_shinfo(skb);
- shinfo->nr_frags--;
- page = shinfo->frags[shinfo->nr_frags].page;
- shinfo->frags[shinfo->nr_frags].page = NULL;
- mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- cons_rx_pg->page = page;
- pci_unmap_addr_set(cons_rx_pg, mapping, mapping);
- dev_kfree_skb(skb);
- }
if (prod != cons) {
prod_rx_pg->page = cons_rx_pg->page;
cons_rx_pg->page = NULL;
@@ -2786,6 +2791,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
skb_put(skb, hdr_len);
for (i = 0; i < pages; i++) {
+ dma_addr_t mapping_old;
+
frag_len = min(frag_size, (unsigned int) PAGE_SIZE);
if (unlikely(frag_len <= 4)) {
unsigned int tail = 4 - frag_len;
@@ -2808,9 +2815,10 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
}
rx_pg = &rxr->rx_pg_ring[pg_cons];
- pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping),
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
-
+ /* Don't unmap yet. If we're unable to allocate a new
+ * page, we need to recycle the page and the DMA addr.
+ */
+ mapping_old = pci_unmap_addr(rx_pg, mapping);
if (i == pages - 1)
frag_len -= 4;
@@ -2827,6 +2835,9 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
return err;
}
+ pci_unmap_page(bp->pdev, mapping_old,
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+
frag_size -= frag_len;
skb->data_len += frag_len;
skb->truesize += frag_len;
@@ -3250,6 +3261,9 @@ bnx2_set_rx_mode(struct net_device *dev)
struct dev_addr_list *uc_ptr;
int i;
+ if (!netif_running(dev))
+ return;
+
spin_lock_bh(&bp->phy_lock);
rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
@@ -4970,31 +4984,20 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
continue;
for (j = 0; j < TX_DESC_CNT; ) {
- struct sw_bd *tx_buf = &txr->tx_buf_ring[j];
+ struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
struct sk_buff *skb = tx_buf->skb;
- int k, last;
if (skb == NULL) {
j++;
continue;
}
- pci_unmap_single(bp->pdev,
- pci_unmap_addr(tx_buf, mapping),
- skb_headlen(skb), PCI_DMA_TODEVICE);
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
tx_buf->skb = NULL;
- last = skb_shinfo(skb)->nr_frags;
- for (k = 0; k < last; k++) {
- tx_buf = &txr->tx_buf_ring[j + k + 1];
- pci_unmap_page(bp->pdev,
- pci_unmap_addr(tx_buf, mapping),
- skb_shinfo(skb)->frags[j].size,
- PCI_DMA_TODEVICE);
- }
+ j += skb_shinfo(skb)->nr_frags + 1;
dev_kfree_skb(skb);
- j += k + 1;
}
}
}
@@ -5075,6 +5078,21 @@ bnx2_init_nic(struct bnx2 *bp, int reset_phy)
}
static int
+bnx2_shutdown_chip(struct bnx2 *bp)
+{
+ u32 reset_code;
+
+ if (bp->flags & BNX2_FLAG_NO_WOL)
+ reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
+ else if (bp->wol)
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
+ else
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+
+ return bnx2_reset_chip(bp, reset_code);
+}
+
+static int
bnx2_test_registers(struct bnx2 *bp)
{
int ret;
@@ -5357,8 +5375,11 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
for (i = 14; i < pkt_size; i++)
packet[i] = (unsigned char) (i & 0xff);
- map = pci_map_single(bp->pdev, skb->data, pkt_size,
- PCI_DMA_TODEVICE);
+ if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ return -EIO;
+ }
+ map = skb_shinfo(skb)->dma_maps[0];
REG_WR(bp, BNX2_HC_COMMAND,
bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
@@ -5393,7 +5414,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
udelay(5);
- pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
dev_kfree_skb(skb);
if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod)
@@ -5508,6 +5529,9 @@ bnx2_test_link(struct bnx2 *bp)
{
u32 bmsr;
+ if (!netif_running(bp->dev))
+ return -ENODEV;
+
if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
if (bp->link_up)
return 0;
@@ -5600,7 +5624,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
} else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
u32 bmcr;
- bp->current_interval = bp->timer_interval;
+ bp->current_interval = BNX2_TIMER_INTERVAL;
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
@@ -5629,7 +5653,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
}
} else
- bp->current_interval = bp->timer_interval;
+ bp->current_interval = BNX2_TIMER_INTERVAL;
if (check_link) {
u32 val;
@@ -5674,11 +5698,11 @@ bnx2_5708_serdes_timer(struct bnx2 *bp)
} else {
bnx2_disable_forced_2g5(bp);
bp->serdes_an_pending = 2;
- bp->current_interval = bp->timer_interval;
+ bp->current_interval = BNX2_TIMER_INTERVAL;
}
} else
- bp->current_interval = bp->timer_interval;
+ bp->current_interval = BNX2_TIMER_INTERVAL;
spin_unlock(&bp->phy_lock);
}
@@ -5951,13 +5975,14 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
dma_addr_t mapping;
struct tx_bd *txbd;
- struct sw_bd *tx_buf;
+ struct sw_tx_bd *tx_buf;
u32 len, vlan_tag_flags, last_frag, mss;
u16 prod, ring_prod;
int i;
struct bnx2_napi *bnapi;
struct bnx2_tx_ring_info *txr;
struct netdev_queue *txq;
+ struct skb_shared_info *sp;
/* Determine which tx ring we will be placed on */
i = skb_get_queue_mapping(skb);
@@ -5989,7 +6014,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
#endif
if ((mss = skb_shinfo(skb)->gso_size)) {
- u32 tcp_opt_len, ip_tcp_len;
+ u32 tcp_opt_len;
struct iphdr *iph;
vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
@@ -6013,21 +6038,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
}
} else {
- if (skb_header_cloned(skb) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
- ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
iph = ip_hdr(skb);
- iph->check = 0;
- iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
if (tcp_opt_len || (iph->ihl > 5)) {
vlan_tag_flags |= ((iph->ihl - 5) +
(tcp_opt_len >> 2)) << 8;
@@ -6036,11 +6047,16 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
} else
mss = 0;
- mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ sp = skb_shinfo(skb);
+ mapping = sp->dma_maps[0];
tx_buf = &txr->tx_buf_ring[ring_prod];
tx_buf->skb = skb;
- pci_unmap_addr_set(tx_buf, mapping, mapping);
txbd = &txr->tx_desc_ring[ring_prod];
@@ -6059,10 +6075,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbd = &txr->tx_desc_ring[ring_prod];
len = frag->size;
- mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset,
- len, PCI_DMA_TODEVICE);
- pci_unmap_addr_set(&txr->tx_buf_ring[ring_prod],
- mapping, mapping);
+ mapping = sp->dma_maps[i + 1];
txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
@@ -6097,20 +6110,13 @@ static int
bnx2_close(struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
- u32 reset_code;
cancel_work_sync(&bp->reset_task);
bnx2_disable_int_sync(bp);
bnx2_napi_disable(bp);
del_timer_sync(&bp->timer);
- if (bp->flags & BNX2_FLAG_NO_WOL)
- reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
- else if (bp->wol)
- reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
- else
- reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
- bnx2_reset_chip(bp, reset_code);
+ bnx2_shutdown_chip(bp);
bnx2_free_irq(bp);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
@@ -6479,6 +6485,9 @@ bnx2_nway_reset(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
u32 bmcr;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
if (!(bp->autoneg & AUTONEG_SPEED)) {
return -EINVAL;
}
@@ -6534,6 +6543,9 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
struct bnx2 *bp = netdev_priv(dev);
int rc;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
/* parameters already validated in ethtool_get_eeprom */
rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
@@ -6548,6 +6560,9 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
struct bnx2 *bp = netdev_priv(dev);
int rc;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
/* parameters already validated in ethtool_set_eeprom */
rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
@@ -6712,11 +6727,11 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
bp->autoneg &= ~AUTONEG_FLOW_CTRL;
}
- spin_lock_bh(&bp->phy_lock);
-
- bnx2_setup_phy(bp, bp->phy_port);
-
- spin_unlock_bh(&bp->phy_lock);
+ if (netif_running(dev)) {
+ spin_lock_bh(&bp->phy_lock);
+ bnx2_setup_phy(bp, bp->phy_port);
+ spin_unlock_bh(&bp->phy_lock);
+ }
return 0;
}
@@ -6907,6 +6922,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
{
struct bnx2 *bp = netdev_priv(dev);
+ bnx2_set_power_state(bp, PCI_D0);
+
memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
if (etest->flags & ETH_TEST_FL_OFFLINE) {
int i;
@@ -6926,9 +6943,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
if ((buf[2] = bnx2_test_loopback(bp)) != 0)
etest->flags |= ETH_TEST_FL_FAILED;
- if (!netif_running(bp->dev)) {
- bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
- }
+ if (!netif_running(bp->dev))
+ bnx2_shutdown_chip(bp);
else {
bnx2_init_nic(bp, 1);
bnx2_netif_start(bp);
@@ -6956,6 +6972,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
etest->flags |= ETH_TEST_FL_FAILED;
}
+ if (!netif_running(bp->dev))
+ bnx2_set_power_state(bp, PCI_D3hot);
}
static void
@@ -7021,6 +7039,8 @@ bnx2_phys_id(struct net_device *dev, u32 data)
int i;
u32 save;
+ bnx2_set_power_state(bp, PCI_D0);
+
if (data == 0)
data = 2;
@@ -7045,6 +7065,10 @@ bnx2_phys_id(struct net_device *dev, u32 data)
}
REG_WR(bp, BNX2_EMAC_LED, 0);
REG_WR(bp, BNX2_MISC_CFG, save);
+
+ if (!netif_running(dev))
+ bnx2_set_power_state(bp, PCI_D3hot);
+
return 0;
}
@@ -7516,8 +7540,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
- bp->timer_interval = HZ;
- bp->current_interval = HZ;
+ bp->current_interval = BNX2_TIMER_INTERVAL;
bp->phy_addr = 1;
@@ -7607,7 +7630,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
init_timer(&bp->timer);
- bp->timer.expires = RUN_AT(bp->timer_interval);
+ bp->timer.expires = RUN_AT(BNX2_TIMER_INTERVAL);
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2_timer;
@@ -7720,7 +7743,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
memcpy(dev->dev_addr, bp->mac_addr, 6);
memcpy(dev->perm_addr, bp->mac_addr, 6);
- bp->name = board_info[ent->driver_data].name;
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (CHIP_NUM(bp) == CHIP_NUM_5709)
@@ -7747,7 +7769,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
"IRQ %d, node addr %s\n",
dev->name,
- bp->name,
+ board_info[ent->driver_data].name,
((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
((CHIP_ID(bp) & 0x0ff0) >> 4),
bnx2_bus_string(bp, str),
@@ -7781,7 +7803,6 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);
- u32 reset_code;
/* PCI register 4 needs to be saved whether netif_running() or not.
* MSI address and data need to be saved if using MSI and
@@ -7795,13 +7816,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
bnx2_netif_stop(bp);
netif_device_detach(dev);
del_timer_sync(&bp->timer);
- if (bp->flags & BNX2_FLAG_NO_WOL)
- reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
- else if (bp->wol)
- reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
- else
- reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
- bnx2_reset_chip(bp, reset_code);
+ bnx2_shutdown_chip(bp);
bnx2_free_skbs(bp);
bnx2_set_power_state(bp, pci_choose_state(pdev, state));
return 0;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index c3c579f98ed..617d9534016 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6526,10 +6526,14 @@ struct sw_pg {
DECLARE_PCI_UNMAP_ADDR(mapping)
};
+struct sw_tx_bd {
+ struct sk_buff *skb;
+};
+
#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
-#define SW_TXBD_RING_SIZE (sizeof(struct sw_bd) * TX_DESC_CNT)
+#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT)
#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
/* Buffered flash (Atmel: AT45DB011B) specific information */
@@ -6597,7 +6601,7 @@ struct flash_spec {
struct bnx2_irq {
irq_handler_t handler;
- u16 vector;
+ unsigned int vector;
u8 requested;
char name[16];
};
@@ -6609,7 +6613,7 @@ struct bnx2_tx_ring_info {
u32 tx_bseq_addr;
struct tx_bd *tx_desc_ring;
- struct sw_bd *tx_buf_ring;
+ struct sw_tx_bd *tx_buf_ring;
u16 tx_cons;
u16 hw_tx_cons;
@@ -6654,6 +6658,8 @@ struct bnx2_napi {
struct bnx2_tx_ring_info tx_ring;
};
+#define BNX2_TIMER_INTERVAL HZ
+
struct bnx2 {
/* Fields used in the tx and intr/napi performance paths are grouped */
/* together in the beginning of the structure. */
@@ -6701,9 +6707,6 @@ struct bnx2 {
/* End of fields used in the performance code paths. */
- char *name;
-
- int timer_interval;
int current_interval;
struct timer_list timer;
struct work_struct reset_task;
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index e4b1de43556..24c3cc40c23 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -15,854 +15,854 @@
*/
static u8 bnx2_COM_b06FwText[] = {
- 0xcd, 0x7c, 0x0d, 0x70, 0x5c, 0xd5, 0x95, 0xe6, 0xe9, 0xd7, 0xdd, 0x52,
- 0x4b, 0x96, 0xe5, 0x27, 0xb9, 0x51, 0x1a, 0xa2, 0x24, 0xef, 0xa9, 0x9f,
- 0xa4, 0x06, 0x29, 0xe4, 0xd9, 0x08, 0x10, 0x49, 0x0f, 0x34, 0xdd, 0x92,
- 0x11, 0x89, 0x77, 0x24, 0x40, 0x61, 0xbc, 0x3b, 0xae, 0xac, 0xa6, 0x2d,
- 0x13, 0x42, 0x31, 0x35, 0xae, 0x0a, 0x3b, 0x71, 0xb2, 0x04, 0x37, 0x2d,
- 0x99, 0x38, 0x8c, 0xec, 0x56, 0x64, 0x59, 0x66, 0x67, 0xd8, 0xd9, 0x4e,
- 0x4b, 0xb2, 0x19, 0xa6, 0xed, 0xc6, 0x90, 0x1f, 0xa6, 0x92, 0x0c, 0x5a,
- 0xe3, 0x00, 0x93, 0xcd, 0x56, 0x41, 0x2a, 0xb5, 0xcb, 0x6c, 0x51, 0xbb,
- 0x5e, 0x27, 0x4c, 0xb2, 0xa9, 0xda, 0x0a, 0x3b, 0x93, 0xda, 0x65, 0xf2,
- 0x33, 0x6f, 0xbf, 0xef, 0xbe, 0xfb, 0xa4, 0x96, 0xac, 0x38, 0x4c, 0xa6,
- 0x52, 0x35, 0xaa, 0xea, 0xba, 0xef, 0xde, 0x77, 0x7f, 0xce, 0x3d, 0xf7,
- 0xdc, 0x73, 0xbe, 0x73, 0xee, 0x7d, 0xba, 0x55, 0xa4, 0x59, 0xf4, 0xdf,
- 0x56, 0xfc, 0x06, 0x7e, 0xff, 0x0f, 0xf6, 0xdd, 0x78, 0xbd, 0x7b, 0x3d,
- 0xf3, 0x46, 0x54, 0x22, 0x4c, 0xc3, 0xf8, 0xc5, 0xf1, 0xdb, 0xa9, 0x9f,
- 0x37, 0xfb, 0x33, 0xf1, 0xbb, 0x29, 0x24, 0x32, 0xf1, 0x23, 0x91, 0xd0,
- 0x86, 0x77, 0xb1, 0x4d, 0xea, 0x7b, 0xde, 0x2f, 0xe9, 0x48, 0xff, 0x19,
- 0xf8, 0x59, 0x57, 0xae, 0xb2, 0x3a, 0xee, 0xaf, 0xfb, 0x17, 0xd6, 0xcd,
- 0xb7, 0xea, 0x9f, 0xc4, 0x8c, 0xf4, 0xc5, 0xdf, 0xce, 0x3a, 0x12, 0x0b,
- 0xa7, 0xbf, 0x3b, 0xba, 0xcf, 0x11, 0xc9, 0x54, 0xfb, 0xac, 0x9c, 0xfc,
- 0xc2, 0x2b, 0xc4, 0x23, 0xc2, 0xf2, 0xf7, 0xa4, 0x7f, 0x7e, 0xe8, 0x1b,
- 0x37, 0xdb, 0x6f, 0x95, 0xc3, 0x12, 0x33, 0xd3, 0x6f, 0x8b, 0xd9, 0x23,
- 0xb1, 0x4e, 0xb4, 0x79, 0xb2, 0xf7, 0x29, 0x43, 0x5a, 0x83, 0xbe, 0xcc,
- 0x89, 0x70, 0x5a, 0xc6, 0x26, 0x67, 0x0e, 0x79, 0x86, 0x23, 0x85, 0x6b,
- 0xd2, 0x8e, 0x55, 0x94, 0x96, 0xc1, 0xe9, 0x81, 0x9b, 0x05, 0xf9, 0xb1,
- 0xc9, 0x6a, 0x4c, 0xb2, 0xb5, 0x42, 0x8b, 0xe1, 0x38, 0x48, 0x63, 0x85,
- 0x77, 0xa7, 0x25, 0xd6, 0x90, 0x9e, 0x6f, 0x7c, 0xc9, 0xe1, 0xf8, 0x89,
- 0xd1, 0xac, 0xf3, 0x6e, 0x89, 0x38, 0x9e, 0x37, 0x8d, 0xf1, 0x77, 0x55,
- 0x7f, 0xe1, 0x3d, 0x1a, 0xf1, 0xc7, 0x36, 0xd2, 0x07, 0xc3, 0x4c, 0x43,
- 0x69, 0x6b, 0xb4, 0xab, 0xaa, 0xf2, 0x0d, 0x7e, 0xde, 0xd1, 0xf9, 0x58,
- 0xb3, 0x4f, 0xbb, 0x34, 0x81, 0xf6, 0x58, 0x24, 0x9d, 0x6e, 0x42, 0x1f,
- 0xb1, 0x68, 0xfa, 0x99, 0xdf, 0x5a, 0x56, 0xf5, 0xee, 0xd7, 0xf5, 0xee,
- 0x8f, 0xfa, 0xed, 0x26, 0x47, 0x7b, 0xaa, 0x4c, 0x1f, 0x1a, 0xed, 0x56,
- 0xe9, 0xc3, 0xa3, 0x49, 0x95, 0x16, 0x54, 0xbd, 0x50, 0x7a, 0x7a, 0xd4,
- 0x51, 0x69, 0xa7, 0x2e, 0x4f, 0x8d, 0x5a, 0x2a, 0xed, 0xd7, 0xa9, 0xab,
- 0xd3, 0x01, 0x9d, 0x0e, 0xea, 0x34, 0xad, 0xd3, 0x8c, 0x4e, 0x87, 0x74,
- 0x3f, 0x23, 0x3a, 0xbf, 0x5b, 0xa7, 0x63, 0x3a, 0x1d, 0xd7, 0xe9, 0x1e,
- 0x9d, 0xee, 0xd5, 0x74, 0x4d, 0xe8, 0xf4, 0x41, 0x5d, 0x7e, 0x40, 0xd3,
- 0x79, 0x10, 0xf4, 0x7c, 0xa6, 0x51, 0xcb, 0x2d, 0xe6, 0x6b, 0xc9, 0xbe,
- 0x99, 0x98, 0x14, 0x4b, 0x61, 0xc9, 0xa9, 0xf5, 0xfc, 0x7c, 0x54, 0x9a,
- 0x63, 0x32, 0x55, 0x8b, 0xc9, 0x45, 0x25, 0xae, 0x3f, 0xf4, 0xbe, 0xd1,
- 0x6b, 0xca, 0x33, 0xb5, 0xb8, 0xbc, 0x50, 0x93, 0xd0, 0x58, 0x6f, 0x93,
- 0x18, 0x73, 0xd7, 0x48, 0xc6, 0x0c, 0x49, 0x58, 0xf1, 0xd5, 0x92, 0xec,
- 0x4c, 0x07, 0xf2, 0x76, 0x42, 0xe4, 0xe5, 0xa8, 0xbf, 0x8e, 0x31, 0x09,
- 0x2f, 0x70, 0x5d, 0x16, 0x46, 0x5f, 0x9a, 0x4f, 0x48, 0xe4, 0x98, 0x85,
- 0xfe, 0x5b, 0x24, 0xba, 0x20, 0x9d, 0x61, 0xe9, 0x4e, 0xdc, 0x87, 0x1a,
- 0x43, 0xd5, 0x88, 0x0c, 0x57, 0x43, 0x58, 0xab, 0x18, 0xe4, 0xa4, 0x05,
- 0x3f, 0x13, 0xbf, 0x38, 0x7e, 0x09, 0xfc, 0x3c, 0xf4, 0xd3, 0x29, 0xb9,
- 0x2a, 0xfb, 0xc4, 0xb8, 0x25, 0x8c, 0x5f, 0xb2, 0xcd, 0x09, 0x21, 0x4d,
- 0x09, 0xf9, 0x46, 0xaf, 0x4f, 0xd3, 0x0b, 0xb5, 0x58, 0x28, 0x7b, 0x52,
- 0x0e, 0xe4, 0x5c, 0xb1, 0x0c, 0xa7, 0x59, 0xf2, 0x66, 0xc8, 0x9a, 0x4c,
- 0xb5, 0x4b, 0x61, 0x1c, 0xef, 0x4a, 0x92, 0x31, 0xd0, 0x77, 0xde, 0x94,
- 0x09, 0xff, 0x1d, 0xcb, 0xfe, 0x1e, 0xfb, 0xd5, 0x36, 0x29, 0xb8, 0x2f,
- 0x94, 0xfe, 0x02, 0xcf, 0xec, 0xeb, 0xcd, 0x88, 0x4f, 0xf3, 0xdb, 0xc8,
- 0xb3, 0xfc, 0x67, 0xdb, 0xfc, 0x3c, 0x9f, 0x59, 0x37, 0x18, 0x33, 0x98,
- 0x2b, 0xc7, 0xee, 0xc5, 0x7c, 0x39, 0xfe, 0xea, 0x7c, 0x41, 0x47, 0x4b,
- 0x28, 0x77, 0xd2, 0x92, 0xc3, 0xa5, 0x5b, 0x25, 0xeb, 0x7a, 0xde, 0x3e,
- 0x57, 0xe2, 0x86, 0x74, 0x9b, 0x39, 0xbc, 0xad, 0x54, 0x25, 0x94, 0x2d,
- 0x05, 0xfc, 0x60, 0xbf, 0x11, 0x94, 0x75, 0xa0, 0x7e, 0x6b, 0x68, 0xe8,
- 0x24, 0x68, 0x4f, 0x93, 0x2f, 0x90, 0x59, 0xb7, 0x3b, 0x31, 0x89, 0xf1,
- 0x16, 0xab, 0xdd, 0xee, 0x79, 0x31, 0xd1, 0x67, 0x3b, 0xea, 0x90, 0x47,
- 0xec, 0x8b, 0x7d, 0xb2, 0xbf, 0x16, 0xb4, 0x8d, 0xe3, 0x1d, 0x69, 0xf2,
- 0xbc, 0xac, 0x6b, 0x32, 0x2f, 0x65, 0xf0, 0xad, 0x4c, 0xbe, 0x35, 0x77,
- 0xca, 0xa9, 0x2a, 0xc7, 0xd8, 0x8c, 0xee, 0xeb, 0xfe, 0x99, 0xd1, 0x9d,
- 0x40, 0xff, 0x71, 0xa4, 0x5b, 0x42, 0xd9, 0xe3, 0x1e, 0xc6, 0x4f, 0xe0,
- 0x79, 0xb3, 0x39, 0x5c, 0xd4, 0x32, 0x98, 0x00, 0xed, 0x71, 0x39, 0xa7,
- 0xe4, 0x70, 0x8b, 0x84, 0x21, 0x87, 0x5c, 0xe3, 0xb6, 0x85, 0x1b, 0x25,
- 0x1f, 0xb7, 0x2d, 0xea, 0xce, 0xae, 0x9d, 0x4d, 0x98, 0xa3, 0xd6, 0x82,
- 0xc7, 0xe2, 0x90, 0xc3, 0xf3, 0x6d, 0x06, 0x4a, 0x0c, 0xb1, 0xcd, 0x7f,
- 0x25, 0x05, 0xc9, 0x2d, 0x7d, 0x2a, 0x24, 0xcd, 0x06, 0xea, 0x5d, 0x1b,
- 0xf2, 0x79, 0x40, 0xfe, 0x64, 0xc0, 0x9f, 0x90, 0xf8, 0xfb, 0x3a, 0x23,
- 0x5d, 0x55, 0xbe, 0xef, 0xb3, 0x0c, 0xf5, 0x6e, 0x08, 0xef, 0x22, 0x92,
- 0xdc, 0x19, 0xbc, 0x1f, 0xc2, 0xfb, 0x6b, 0x64, 0xc2, 0x04, 0x2d, 0xa5,
- 0xe7, 0x8d, 0x2c, 0x68, 0xbc, 0x3d, 0xa2, 0xe6, 0x8a, 0xba, 0x13, 0x75,
- 0xfd, 0x4c, 0xa0, 0xde, 0x1f, 0x63, 0x2c, 0xd0, 0x5b, 0xb2, 0x40, 0x4b,
- 0x07, 0x68, 0x21, 0x8d, 0x05, 0x23, 0x5b, 0x8b, 0x20, 0x3f, 0x6d, 0xe4,
- 0x4e, 0x1f, 0xc1, 0xb3, 0x98, 0x46, 0xfa, 0x79, 0xa6, 0x68, 0xbf, 0xb7,
- 0xae, 0xfd, 0x5e, 0xb4, 0xe7, 0x18, 0x6c, 0xef, 0xcb, 0x7f, 0x41, 0xc9,
- 0xa2, 0x75, 0x05, 0x7e, 0x84, 0x7f, 0x0d, 0x7e, 0x7c, 0x4d, 0xf3, 0xe3,
- 0x67, 0xf2, 0x9b, 0xe7, 0xc7, 0x7f, 0xff, 0x0d, 0xf1, 0x43, 0x24, 0x7f,
- 0x9c, 0xcf, 0x11, 0x29, 0x28, 0xbd, 0xc5, 0x7d, 0x4b, 0x79, 0xa7, 0xce,
- 0x22, 0x9f, 0x28, 0xc7, 0xd8, 0x03, 0xb5, 0x08, 0xd2, 0xa7, 0x90, 0x6e,
- 0x09, 0x8d, 0x1d, 0xbf, 0x84, 0xf5, 0xf7, 0xc4, 0xdc, 0x19, 0xd8, 0x8d,
- 0x42, 0xc2, 0x94, 0x4e, 0x31, 0xaf, 0x87, 0xd1, 0xee, 0xb0, 0xcd, 0xbc,
- 0xbc, 0x89, 0xf7, 0xbf, 0x08, 0x05, 0xf6, 0x3d, 0x3b, 0xd3, 0xf4, 0x76,
- 0x46, 0x3d, 0x45, 0xc9, 0xcf, 0x8c, 0x91, 0x8e, 0x84, 0x72, 0x25, 0x6b,
- 0xc2, 0x48, 0xc7, 0xa1, 0xa7, 0x98, 0x1f, 0x0c, 0xf9, 0x34, 0x0f, 0xa0,
- 0x6e, 0xa0, 0xb3, 0x02, 0xda, 0x07, 0x40, 0xfb, 0x46, 0xdd, 0x95, 0x01,
- 0x2d, 0xa4, 0x81, 0x74, 0x55, 0xc2, 0x9a, 0xf7, 0xe8, 0xe7, 0xa0, 0xea,
- 0x27, 0x9c, 0x1e, 0x14, 0xda, 0xd0, 0xfc, 0x0c, 0xf7, 0x01, 0xdb, 0xb1,
- 0x2f, 0x5f, 0x27, 0xe7, 0xab, 0x41, 0x1f, 0x85, 0xba, 0x3e, 0x0a, 0xa0,
- 0x47, 0xb6, 0x19, 0x4e, 0x14, 0x6b, 0xcf, 0xae, 0x8e, 0xe0, 0xdd, 0x93,
- 0x92, 0x3d, 0x7d, 0xb3, 0x81, 0x39, 0xa0, 0x5f, 0xf2, 0x68, 0x0c, 0x3a,
- 0x9b, 0xfb, 0x2c, 0x26, 0xb9, 0x38, 0xcb, 0x3e, 0xa6, 0xc7, 0x8d, 0x48,
- 0x46, 0xe5, 0x5f, 0x69, 0x5d, 0xa3, 0xe3, 0x79, 0x3d, 0x9f, 0x34, 0xe6,
- 0x43, 0x1a, 0x82, 0xb9, 0xa4, 0xeb, 0xe6, 0x12, 0xf0, 0x9a, 0xbc, 0x30,
- 0xa1, 0xe3, 0x63, 0xda, 0x86, 0xb0, 0xdd, 0x74, 0xdd, 0xda, 0x4d, 0xa3,
- 0x0d, 0x79, 0x8f, 0x3a, 0x1b, 0xec, 0x0a, 0x6d, 0xca, 0x10, 0xfa, 0x29,
- 0xce, 0x1b, 0x92, 0x73, 0x61, 0xab, 0xdd, 0x77, 0x6b, 0x79, 0x5d, 0x93,
- 0xa5, 0xe8, 0xa6, 0xb2, 0x74, 0xc8, 0xf0, 0xf5, 0x35, 0x6c, 0x0b, 0xec,
- 0xcf, 0xd4, 0xbc, 0x9d, 0x0a, 0x64, 0xa9, 0x38, 0xf3, 0x4e, 0x64, 0x29,
- 0x68, 0x1f, 0x83, 0xec, 0x06, 0x63, 0x6c, 0xa4, 0x39, 0xa8, 0x03, 0x1a,
- 0x4b, 0x59, 0x8d, 0x51, 0x38, 0x8e, 0x6f, 0x1b, 0xca, 0xeb, 0x6c, 0xc3,
- 0x11, 0xb4, 0x95, 0x50, 0xae, 0xb7, 0x45, 0xf6, 0xcf, 0x07, 0x7d, 0x1c,
- 0x51, 0x32, 0x3b, 0x39, 0x63, 0x9b, 0xc3, 0x61, 0xc9, 0x0c, 0xcf, 0x0e,
- 0xca, 0x50, 0xad, 0x13, 0x6b, 0xfa, 0xb6, 0x07, 0xdb, 0x79, 0x7d, 0x54,
- 0x1c, 0xe8, 0x45, 0xcc, 0x79, 0x00, 0x3c, 0xae, 0x45, 0xc5, 0x48, 0xbb,
- 0x48, 0xeb, 0x31, 0x56, 0x24, 0x32, 0xbc, 0x2e, 0xdf, 0x80, 0x3a, 0xe8,
- 0x7b, 0x60, 0x63, 0x3d, 0xc8, 0x27, 0x78, 0x9b, 0x75, 0x7f, 0xe1, 0xc1,
- 0x0e, 0x6b, 0x9b, 0xc5, 0x52, 0xea, 0x89, 0x40, 0x47, 0x7c, 0x14, 0xfb,
- 0x5b, 0xed, 0x85, 0x82, 0x91, 0x3e, 0x80, 0x3e, 0x44, 0xc9, 0x69, 0xb1,
- 0xf6, 0x4c, 0xb0, 0xef, 0x55, 0xf9, 0xae, 0x01, 0xca, 0x5e, 0x19, 0x98,
- 0x80, 0x73, 0x5a, 0x52, 0x7b, 0x3d, 0x67, 0xc6, 0x65, 0xba, 0xc4, 0xf9,
- 0x2c, 0x49, 0xb2, 0xfa, 0xa7, 0x92, 0x3b, 0x2d, 0xf2, 0xad, 0x19, 0xd6,
- 0xfb, 0xba, 0xae, 0xf7, 0x3c, 0xea, 0x25, 0xad, 0xa1, 0x90, 0x0d, 0x3b,
- 0x60, 0x63, 0x9b, 0xf4, 0x59, 0x48, 0xcd, 0x11, 0xfc, 0x86, 0x68, 0x64,
- 0x50, 0xcf, 0xc7, 0x40, 0xcf, 0x83, 0x1f, 0x22, 0x77, 0x95, 0x1a, 0xa1,
- 0x4f, 0xfe, 0x27, 0x68, 0x8d, 0xcb, 0xe3, 0x98, 0xc7, 0x4b, 0x33, 0xc4,
- 0x59, 0x5f, 0x97, 0xe5, 0x19, 0xe2, 0xae, 0xe7, 0x65, 0x7a, 0x26, 0xe9,
- 0x7e, 0x0b, 0x7c, 0x3e, 0x25, 0x9c, 0x4b, 0x9f, 0x8b, 0x14, 0x18, 0xd0,
- 0xb6, 0x1e, 0x83, 0x3e, 0xeb, 0xdd, 0xe9, 0xf7, 0xd7, 0xad, 0xfb, 0x73,
- 0xaa, 0xb6, 0x5c, 0x34, 0xa9, 0x9f, 0x2e, 0xdf, 0xe3, 0x59, 0xbd, 0xc7,
- 0xc7, 0xdc, 0x4e, 0x31, 0xb0, 0xaf, 0x33, 0xe3, 0x05, 0x58, 0x3f, 0xee,
- 0xeb, 0xff, 0x6b, 0xac, 0xe1, 0x9f, 0x04, 0xb0, 0xaa, 0xad, 0xec, 0xdd,
- 0x3f, 0x6e, 0x8f, 0xd7, 0xef, 0x6d, 0x8e, 0xdf, 0x8a, 0x36, 0x11, 0xa4,
- 0x57, 0xde, 0xd7, 0xe8, 0xa3, 0xae, 0xed, 0x20, 0xf7, 0x05, 0xda, 0xfc,
- 0x09, 0x78, 0x41, 0xfe, 0xbf, 0x93, 0xfd, 0xdc, 0x17, 0x7e, 0x47, 0xfb,
- 0x79, 0xfc, 0x4a, 0xfb, 0xb9, 0x7e, 0x2f, 0x9f, 0x25, 0x2f, 0x30, 0xb6,
- 0xcc, 0xfa, 0xb2, 0xd5, 0x0d, 0x5e, 0x5b, 0x90, 0x53, 0xd0, 0x50, 0xfa,
- 0x07, 0x2f, 0x13, 0xf1, 0xf1, 0x9c, 0x2f, 0x4f, 0xac, 0x17, 0xd4, 0xf1,
- 0x75, 0xef, 0x50, 0xed, 0xa2, 0xd2, 0xb3, 0xe7, 0x94, 0x9e, 0xb5, 0x8f,
- 0x14, 0x84, 0xf2, 0x76, 0x43, 0x98, 0x7c, 0x7f, 0xc6, 0xfd, 0x2c, 0x68,
- 0xb4, 0x2d, 0xcb, 0xe8, 0x2e, 0x18, 0xc6, 0x67, 0xe5, 0xc0, 0xe2, 0x43,
- 0x72, 0xa0, 0xc4, 0x3e, 0xd2, 0x78, 0xef, 0xa0, 0xac, 0x09, 0xba, 0x96,
- 0x3a, 0xfd, 0xed, 0x90, 0x3f, 0x96, 0x01, 0xfb, 0xb5, 0x12, 0xba, 0xab,
- 0x76, 0x21, 0x94, 0x5d, 0xe4, 0xde, 0x45, 0x79, 0xad, 0x5e, 0xe7, 0x07,
- 0xfa, 0xbe, 0x5e, 0xb7, 0x17, 0x42, 0x63, 0xa5, 0x69, 0xe2, 0x40, 0x23,
- 0xeb, 0x46, 0xb5, 0xee, 0xf8, 0x9a, 0x29, 0xad, 0xb0, 0x2d, 0xc6, 0x3c,
- 0x78, 0x45, 0x9c, 0x4a, 0xde, 0xa5, 0x24, 0x13, 0x21, 0x9e, 0xe4, 0xb3,
- 0x78, 0xe1, 0x34, 0xf7, 0x9e, 0x44, 0xc2, 0xe9, 0x2e, 0xf0, 0x8e, 0x75,
- 0x6e, 0x05, 0xad, 0xb0, 0x7b, 0xee, 0xfb, 0x84, 0x72, 0xf9, 0x42, 0xe9,
- 0x36, 0xe4, 0x23, 0x9a, 0xbf, 0x51, 0xd4, 0x61, 0x7f, 0x3f, 0x6d, 0x90,
- 0xd6, 0xe3, 0xd0, 0x15, 0x41, 0xbf, 0xac, 0x93, 0xd0, 0x75, 0x5a, 0x74,
- 0x9d, 0x5b, 0xf0, 0x7e, 0x0e, 0xf5, 0x6c, 0x57, 0x84, 0x7c, 0x60, 0x59,
- 0x3b, 0xe6, 0x85, 0xba, 0x8b, 0xe9, 0xf0, 0x7a, 0xba, 0x6e, 0xaa, 0xab,
- 0xcb, 0xfc, 0x66, 0x58, 0x97, 0xf2, 0x24, 0x5a, 0x97, 0xb1, 0x6c, 0x10,
- 0xcf, 0x5d, 0x32, 0xb1, 0x98, 0x81, 0x4e, 0xba, 0x5d, 0xf5, 0x13, 0x75,
- 0xd6, 0xd9, 0x3a, 0xd0, 0x64, 0x69, 0x9a, 0xb6, 0x04, 0xfa, 0x18, 0x65,
- 0xae, 0x2e, 0x6b, 0xa8, 0x2b, 0x0b, 0xe4, 0xe7, 0x5f, 0x83, 0x76, 0x8e,
- 0x3d, 0xa2, 0x71, 0x98, 0xe7, 0xe5, 0x28, 0x77, 0xfd, 0xff, 0x52, 0xf3,
- 0xa2, 0x60, 0x86, 0xd5, 0x5e, 0xa9, 0xfe, 0xf6, 0xda, 0x5e, 0x01, 0x6e,
- 0x57, 0xbd, 0x70, 0x8e, 0xa4, 0xa5, 0x05, 0x6b, 0x3b, 0x04, 0x5a, 0xb1,
- 0x86, 0x1d, 0x21, 0xcc, 0xb7, 0x45, 0xf2, 0xb5, 0xb4, 0x7e, 0xc7, 0xf2,
- 0x88, 0x8c, 0xc5, 0x83, 0xf9, 0x7d, 0xc0, 0xf4, 0xb1, 0x37, 0xea, 0x94,
- 0xb6, 0x44, 0xfc, 0xbd, 0x68, 0x4a, 0xfe, 0xe4, 0x10, 0x64, 0x9e, 0xd8,
- 0xb0, 0x01, 0x32, 0x1f, 0x57, 0x36, 0xc7, 0x70, 0x58, 0x1f, 0xef, 0x4e,
- 0xff, 0xbb, 0xb0, 0xdf, 0x86, 0xf5, 0x82, 0x36, 0xc1, 0xd8, 0xed, 0xab,
- 0x6d, 0xc7, 0x5c, 0x43, 0xc2, 0x6a, 0x7c, 0x94, 0x9d, 0x5e, 0x3f, 0xbe,
- 0xd1, 0x11, 0x8c, 0xff, 0xa7, 0xba, 0xaf, 0xf6, 0xba, 0xbe, 0xe2, 0x57,
- 0x18, 0x1f, 0xef, 0x4e, 0xff, 0xee, 0x76, 0xbf, 0x4d, 0xbc, 0xae, 0x4d,
- 0xc7, 0x86, 0x36, 0xac, 0x1f, 0x8c, 0x81, 0x77, 0xa7, 0xef, 0x6b, 0xf1,
- 0xdb, 0xb0, 0x5e, 0x03, 0x6c, 0x2c, 0xdf, 0x71, 0x0f, 0x1e, 0xa8, 0xdb,
- 0x83, 0x07, 0xb0, 0x07, 0x03, 0xd9, 0xde, 0x88, 0xd7, 0x03, 0xbf, 0x8b,
- 0xfe, 0x16, 0x31, 0xde, 0x9a, 0x7f, 0x15, 0x59, 0x68, 0x01, 0x7e, 0x6a,
- 0xa5, 0x4f, 0xa5, 0xf1, 0x39, 0x7d, 0x2c, 0xe2, 0x71, 0x71, 0x22, 0xd2,
- 0x0d, 0x5d, 0xd9, 0x9d, 0xd8, 0xcf, 0x8d, 0x5f, 0x8d, 0x2b, 0xdc, 0x9e,
- 0xd1, 0x63, 0xd0, 0xbf, 0x22, 0xdf, 0x99, 0xcf, 0xad, 0xfa, 0x5b, 0x9d,
- 0xf0, 0xc7, 0x88, 0xbb, 0x89, 0xdb, 0x02, 0xfa, 0x03, 0x7a, 0x0e, 0x1a,
- 0x6b, 0x7b, 0x33, 0x63, 0x0c, 0xd5, 0x86, 0x0c, 0x7f, 0x6f, 0xf2, 0xfd,
- 0x41, 0x6d, 0x5b, 0x37, 0xd2, 0xfb, 0x9e, 0x0d, 0xf4, 0x12, 0xdf, 0x59,
- 0x32, 0x05, 0x19, 0x89, 0x2c, 0x50, 0xd7, 0x2f, 0x8c, 0x2e, 0xcf, 0x13,
- 0xc7, 0xf4, 0x83, 0x2f, 0xa4, 0x97, 0xfc, 0xa3, 0x4e, 0x69, 0x85, 0x9e,
- 0xea, 0x4e, 0x55, 0x50, 0x9f, 0x7e, 0xfe, 0x84, 0xf2, 0x0f, 0x5b, 0x90,
- 0xc2, 0x89, 0x03, 0xad, 0x13, 0xa0, 0x75, 0x42, 0xfb, 0x86, 0xfb, 0x61,
- 0x47, 0x22, 0xc7, 0x02, 0x5a, 0x6f, 0x89, 0x04, 0x6b, 0xb3, 0x9e, 0xf6,
- 0x7a, 0xfb, 0xe7, 0xe3, 0xc0, 0xbb, 0x7a, 0xd5, 0x9e, 0x2c, 0x10, 0x3b,
- 0x4e, 0x9c, 0x0e, 0xf6, 0xa3, 0xf8, 0x7b, 0xa9, 0x35, 0xc0, 0x01, 0x9c,
- 0x0f, 0x71, 0x08, 0x75, 0x4f, 0x30, 0x87, 0x16, 0xe9, 0x5a, 0xe0, 0x1c,
- 0x56, 0xe9, 0x8f, 0x33, 0xca, 0x72, 0x00, 0xfa, 0x3b, 0xaf, 0x68, 0xdd,
- 0x2d, 0x93, 0xa5, 0xf7, 0x69, 0xfa, 0x5b, 0x40, 0xff, 0x18, 0x64, 0x7b,
- 0x4d, 0x77, 0xe5, 0xab, 0xe3, 0xc8, 0xfb, 0x98, 0x90, 0x3c, 0xce, 0x57,
- 0xa9, 0xc7, 0xf4, 0x7c, 0x9a, 0x39, 0x9f, 0x8d, 0x3a, 0x6e, 0x33, 0xbe,
- 0xbe, 0x77, 0x03, 0x5f, 0x45, 0xf3, 0x35, 0x26, 0x0d, 0x0b, 0xca, 0xbf,
- 0x46, 0xbf, 0xe4, 0x35, 0xed, 0xe8, 0xc2, 0xe8, 0xf4, 0xbc, 0xf4, 0x33,
- 0x08, 0x95, 0x07, 0xdf, 0x50, 0x36, 0xd0, 0x20, 0xdd, 0xee, 0x05, 0xcc,
- 0x3b, 0x8f, 0xf5, 0x36, 0x8e, 0xf9, 0xf2, 0x4d, 0xfe, 0xe6, 0xab, 0xcd,
- 0xf0, 0xe9, 0x39, 0x36, 0x79, 0x46, 0xfa, 0x4d, 0x45, 0xcf, 0x2a, 0xbf,
- 0x41, 0xdf, 0x7d, 0xd5, 0x8d, 0xbc, 0xad, 0xd7, 0x33, 0x41, 0xec, 0xe0,
- 0x35, 0xd3, 0xdf, 0x17, 0x9b, 0xc5, 0x0e, 0x5a, 0xa0, 0xa3, 0x23, 0x8c,
- 0x13, 0x80, 0xf7, 0x8c, 0xf3, 0x5c, 0x8a, 0xd0, 0x17, 0x78, 0xa1, 0x04,
- 0x3d, 0x73, 0x9c, 0xd8, 0xa5, 0x55, 0xef, 0x8f, 0x1b, 0xb4, 0x0d, 0x8b,
- 0x2a, 0xdb, 0x21, 0x86, 0x49, 0x7c, 0x84, 0x32, 0xe4, 0x17, 0x99, 0x0f,
- 0xe8, 0xb8, 0x7b, 0x4f, 0xd4, 0x79, 0x21, 0x12, 0xe8, 0x84, 0x35, 0xba,
- 0xea, 0x63, 0x03, 0x1e, 0x30, 0xe5, 0xfb, 0x20, 0xb7, 0xb7, 0xc3, 0xff,
- 0xb7, 0x24, 0x9f, 0xe2, 0x3e, 0x1a, 0x54, 0x3e, 0x92, 0xe1, 0xec, 0x47,
- 0x59, 0x13, 0xca, 0x60, 0x4c, 0x4d, 0xcc, 0xdf, 0xf9, 0x3d, 0x99, 0x80,
- 0x8c, 0xe7, 0x53, 0x7d, 0xa0, 0x83, 0xf8, 0x0e, 0x58, 0xcb, 0x49, 0x31,
- 0x7e, 0x80, 0xbf, 0x7b, 0xa3, 0xfe, 0xbc, 0xf6, 0x20, 0xdf, 0x8c, 0x3a,
- 0x5d, 0xba, 0xce, 0x16, 0x61, 0x1c, 0x2a, 0x6f, 0xb6, 0x22, 0xed, 0xd9,
- 0x50, 0xf7, 0x43, 0xc8, 0xdf, 0xa2, 0xfb, 0x2f, 0xe0, 0xfd, 0x4d, 0xf8,
- 0x0d, 0xa1, 0xec, 0x66, 0x94, 0xb9, 0x28, 0xbb, 0x11, 0xf9, 0x0f, 0xe9,
- 0xb8, 0x44, 0xd0, 0xa6, 0x15, 0xf9, 0x47, 0xf1, 0x1e, 0xba, 0xc2, 0x7c,
- 0x05, 0xef, 0x6f, 0xc1, 0xef, 0xfa, 0x0d, 0x75, 0xda, 0x37, 0xe4, 0x4f,
- 0xae, 0xf2, 0xe0, 0x85, 0xd2, 0x55, 0xfa, 0x99, 0xf2, 0xcc, 0xfc, 0x2b,
- 0x3a, 0x7f, 0xfb, 0x86, 0xf2, 0xfb, 0x83, 0x7c, 0xdd, 0x1a, 0xc2, 0x0e,
- 0x9a, 0x01, 0xd6, 0xbd, 0xda, 0xf4, 0xd7, 0xe0, 0x3d, 0x7e, 0xbc, 0xa0,
- 0x14, 0xb4, 0x23, 0xf6, 0xbd, 0x3d, 0xbc, 0xbe, 0xaf, 0xff, 0xd6, 0xb0,
- 0x96, 0x6f, 0x09, 0x0d, 0x9f, 0x64, 0xd9, 0x4f, 0x1b, 0xd6, 0xd7, 0x79,
- 0x5f, 0xe3, 0x5a, 0x7e, 0x6b, 0x68, 0xf8, 0x38, 0xcb, 0xee, 0x6b, 0x5c,
- 0x5f, 0x67, 0xb8, 0x71, 0x6d, 0x1e, 0x6b, 0xba, 0x30, 0x92, 0xae, 0x50,
- 0x8e, 0xb1, 0x17, 0xaa, 0xa3, 0xd9, 0x19, 0xcf, 0x9b, 0x72, 0x57, 0x12,
- 0x61, 0xa1, 0x0d, 0x22, 0x66, 0x66, 0xf9, 0x53, 0x28, 0x07, 0xa6, 0xaa,
- 0x8d, 0x09, 0x75, 0xd2, 0xe6, 0xd8, 0xd8, 0xd2, 0xd8, 0x58, 0x65, 0x23,
- 0x59, 0x85, 0x65, 0x9f, 0x18, 0x05, 0xf6, 0xd2, 0xcf, 0x4f, 0xe2, 0xd9,
- 0xaa, 0xc7, 0xdf, 0xe8, 0xb7, 0x3c, 0x9a, 0x9d, 0xa7, 0xcd, 0x5b, 0x1a,
- 0xdd, 0x37, 0xcf, 0x3d, 0x7f, 0x0a, 0x7b, 0x3e, 0x24, 0xd3, 0xca, 0xfe,
- 0x91, 0x0e, 0xb6, 0x2b, 0x8f, 0x76, 0x2d, 0x31, 0xad, 0x8c, 0x3a, 0x4b,
- 0x61, 0xd9, 0x1f, 0xf7, 0xdb, 0x32, 0x6f, 0x2d, 0x05, 0x7b, 0xa0, 0x59,
- 0xa2, 0x69, 0xca, 0xa4, 0x9d, 0x82, 0x0f, 0x80, 0xf9, 0x1c, 0x19, 0x9d,
- 0x76, 0x28, 0x9f, 0x9f, 0x82, 0xdd, 0x6f, 0x96, 0x06, 0xa5, 0x6f, 0x1e,
- 0xd7, 0x63, 0x9d, 0xc2, 0x58, 0xdb, 0xd4, 0x7e, 0xca, 0x3a, 0x91, 0x04,
- 0xc6, 0x39, 0x64, 0x38, 0x7d, 0x18, 0x8f, 0x1e, 0x7b, 0xa7, 0x4c, 0xd5,
- 0xb8, 0x6f, 0xf6, 0x44, 0xd7, 0xfc, 0xf4, 0x39, 0xb4, 0x0b, 0xfc, 0x43,
- 0x8e, 0x57, 0x01, 0x3e, 0x84, 0x2c, 0xa7, 0x6d, 0x33, 0x1b, 0x86, 0x9d,
- 0x9f, 0x0f, 0xea, 0x90, 0xa6, 0x63, 0xa3, 0xc9, 0xa5, 0x24, 0xfa, 0xea,
- 0xa4, 0x0e, 0x83, 0xee, 0x0a, 0xe3, 0xc7, 0xbe, 0xd9, 0x0e, 0xb6, 0x68,
- 0x90, 0x76, 0x64, 0x0e, 0x76, 0xa4, 0x53, 0x0e, 0x97, 0x54, 0x1f, 0x16,
- 0xfb, 0x28, 0xea, 0xb6, 0x5d, 0x4b, 0x0d, 0xf0, 0xb1, 0x92, 0xe6, 0x8b,
- 0xb2, 0xd6, 0x76, 0x58, 0xfc, 0x76, 0x7e, 0xdf, 0x3f, 0xf1, 0x32, 0xf1,
- 0xfa, 0xbd, 0xdf, 0x2c, 0x61, 0xd0, 0x91, 0x43, 0x1f, 0x1c, 0x7f, 0xad,
- 0xef, 0xa0, 0xbf, 0xa4, 0x79, 0xfe, 0xb2, 0xbe, 0xb6, 0x69, 0xfc, 0x66,
- 0x5b, 0xb9, 0x5f, 0x6b, 0x6c, 0xce, 0xf7, 0x09, 0xc8, 0x83, 0x44, 0x72,
- 0xbd, 0xd0, 0x8b, 0xb5, 0x41, 0x2d, 0x23, 0x4f, 0xa2, 0xac, 0xde, 0xc7,
- 0xf2, 0xe5, 0xab, 0x00, 0x6c, 0x59, 0xc4, 0x3e, 0x0f, 0xa7, 0x33, 0x6d,
- 0x7e, 0xcc, 0xeb, 0x4a, 0x7e, 0x15, 0xe4, 0x06, 0x7d, 0x16, 0x57, 0xdb,
- 0x72, 0x4e, 0x4f, 0x8e, 0xbe, 0x34, 0x93, 0xc0, 0x9c, 0x7c, 0xbb, 0xe0,
- 0xf3, 0x9a, 0x36, 0x27, 0x24, 0xcb, 0x8e, 0x05, 0xff, 0x9d, 0x36, 0xde,
- 0x92, 0x97, 0x9d, 0xc0, 0xfe, 0xd0, 0x16, 0xa1, 0x7e, 0x8d, 0xb4, 0x91,
- 0xf6, 0x39, 0xcc, 0xcd, 0x93, 0x59, 0xd7, 0x97, 0xc1, 0x5e, 0xd8, 0x91,
- 0xff, 0x18, 0xb1, 0x8f, 0xd0, 0xcf, 0xbb, 0x18, 0xa9, 0x9f, 0x4f, 0x80,
- 0x15, 0x9e, 0xd0, 0x31, 0xe8, 0x39, 0x2d, 0x2f, 0x65, 0xc8, 0x4b, 0x9f,
- 0x65, 0x4a, 0x0f, 0x68, 0x47, 0x9d, 0xfe, 0x6e, 0xf8, 0x5b, 0xf4, 0xe5,
- 0x13, 0xa0, 0xc7, 0x84, 0xee, 0xd8, 0xa6, 0x7d, 0x87, 0xb7, 0xa2, 0xb4,
- 0x6d, 0x6d, 0x2a, 0xbe, 0x3d, 0xa7, 0xe4, 0xd9, 0x97, 0xef, 0xb0, 0x7e,
- 0x1f, 0xc8, 0x54, 0x98, 0x90, 0x46, 0xd6, 0xe2, 0xb8, 0xac, 0xbf, 0xa0,
- 0xeb, 0xcf, 0xa3, 0x7e, 0x08, 0x73, 0xf2, 0xbc, 0x49, 0x45, 0xef, 0x02,
- 0xf8, 0x1e, 0x96, 0xe2, 0xaa, 0xcc, 0x2f, 0x40, 0xe6, 0x29, 0xdf, 0x73,
- 0xd8, 0xaf, 0x20, 0xfe, 0x6e, 0xca, 0x7d, 0x45, 0x86, 0x4e, 0xef, 0x6f,
- 0x60, 0xcc, 0xd5, 0x32, 0xe8, 0x03, 0x53, 0x26, 0x3b, 0xe5, 0xb1, 0x52,
- 0xd2, 0x9c, 0xaa, 0x5b, 0xcb, 0x5d, 0xeb, 0xd6, 0x92, 0x32, 0xa0, 0xea,
- 0xa7, 0x58, 0xbf, 0x52, 0x27, 0x03, 0x8b, 0xf3, 0x57, 0x6a, 0x47, 0x19,
- 0x60, 0xbb, 0xcd, 0xfc, 0x05, 0xc6, 0x28, 0x3d, 0x6f, 0xd9, 0x25, 0xfe,
- 0x6f, 0x94, 0x82, 0x92, 0xb1, 0x90, 0x14, 0x5d, 0xee, 0xab, 0xac, 0x15,
- 0x11, 0x1b, 0x58, 0xe9, 0xf7, 0x41, 0x67, 0x26, 0x15, 0x15, 0x3f, 0xa6,
- 0x31, 0x81, 0x35, 0x58, 0x31, 0x3d, 0xef, 0x25, 0x47, 0xa4, 0x02, 0x1f,
- 0x78, 0x19, 0x69, 0xb1, 0x8a, 0x3d, 0xdb, 0x1c, 0x81, 0x0e, 0x08, 0x64,
- 0x3c, 0x26, 0x65, 0xd4, 0x59, 0xc4, 0xbb, 0xc7, 0xaa, 0x81, 0xc4, 0x78,
- 0x9e, 0x01, 0x1e, 0xed, 0x73, 0x7e, 0xea, 0xe5, 0xe3, 0xf5, 0x75, 0x03,
- 0x4c, 0x4c, 0x2c, 0x4b, 0x6c, 0x4a, 0x4c, 0xc9, 0x77, 0xc4, 0x89, 0x87,
- 0x40, 0x0b, 0xf7, 0x6c, 0xab, 0xc4, 0xd2, 0x76, 0x62, 0x44, 0x02, 0xdb,
- 0xff, 0x3a, 0x64, 0xa9, 0xe0, 0x35, 0x3a, 0x9d, 0xf2, 0x1c, 0xe4, 0xe6,
- 0xd9, 0x55, 0x1c, 0x63, 0x41, 0x8e, 0x68, 0x47, 0x3d, 0x39, 0xe7, 0x3a,
- 0xd6, 0xe7, 0x90, 0x7e, 0xc7, 0xfd, 0x00, 0xf9, 0xf6, 0x84, 0x48, 0x3f,
- 0x7c, 0x32, 0xe8, 0xf5, 0xd9, 0x00, 0xdb, 0xb7, 0xd2, 0x37, 0xd4, 0xb2,
- 0x74, 0x11, 0x7d, 0xda, 0xa6, 0x01, 0x50, 0x7b, 0x07, 0xea, 0xf9, 0x7b,
- 0x23, 0x28, 0x3b, 0x84, 0xba, 0xa4, 0x81, 0x7e, 0xfb, 0x77, 0xb1, 0x67,
- 0x3d, 0xef, 0x1e, 0xf7, 0xe5, 0x3a, 0x5d, 0xb3, 0x80, 0xf5, 0x57, 0x72,
- 0x3e, 0xd0, 0x26, 0x8c, 0xf3, 0x4a, 0x7f, 0xbb, 0xf2, 0x2b, 0xf9, 0x0c,
- 0x79, 0x1f, 0x20, 0x16, 0xb2, 0x14, 0xd6, 0x24, 0x6e, 0x78, 0x16, 0xbc,
- 0xff, 0xa4, 0xc2, 0x34, 0xc4, 0x6f, 0xa0, 0xbf, 0x44, 0x4c, 0xe1, 0x63,
- 0x69, 0x1f, 0xd7, 0x11, 0x5b, 0xa4, 0xb8, 0x36, 0x1a, 0x5f, 0xb0, 0x2d,
- 0xeb, 0xb1, 0x6d, 0xfd, 0xfa, 0xb1, 0xce, 0xb6, 0x50, 0xee, 0x38, 0xe5,
- 0x99, 0xf6, 0xb1, 0x4d, 0xf6, 0xa7, 0x1a, 0xc1, 0xf7, 0x76, 0x6d, 0xc7,
- 0x3f, 0x08, 0xcc, 0x06, 0xec, 0x6d, 0xd2, 0x87, 0x0a, 0x78, 0x7d, 0x23,
- 0xca, 0x7e, 0x0e, 0xfe, 0xb3, 0x0c, 0xfe, 0x95, 0xb2, 0x93, 0x0f, 0x61,
- 0x2f, 0x97, 0xb7, 0xf9, 0x31, 0x34, 0xae, 0x43, 0x80, 0x13, 0x02, 0xdc,
- 0x67, 0x6a, 0xbc, 0xcf, 0xb5, 0xf1, 0xe3, 0x6d, 0x86, 0xaa, 0x4b, 0x5f,
- 0xab, 0xde, 0xc7, 0xe5, 0x1e, 0xf6, 0xbc, 0x73, 0x6e, 0x80, 0x23, 0xeb,
- 0xfd, 0xc4, 0xc0, 0x07, 0x8c, 0x89, 0xd5, 0x4e, 0x4c, 0xf1, 0x47, 0x0d,
- 0x6b, 0x58, 0xe6, 0x1f, 0xbc, 0xb0, 0x43, 0x9f, 0x93, 0x38, 0x26, 0xf0,
- 0x07, 0x59, 0x97, 0xd8, 0xe6, 0x51, 0x8c, 0x11, 0x16, 0xab, 0x83, 0xf9,
- 0x1f, 0xeb, 0x36, 0x7c, 0xf6, 0xa4, 0x67, 0x67, 0xbd, 0x3c, 0x0f, 0xfa,
- 0xfe, 0x62, 0x73, 0x10, 0x03, 0xee, 0x54, 0xfa, 0x64, 0x4d, 0x2e, 0x02,
- 0x9a, 0x82, 0x71, 0x7d, 0xff, 0xb4, 0x1d, 0xb4, 0xdd, 0x05, 0x9b, 0xb2,
- 0xb3, 0xdd, 0xae, 0xf3, 0x45, 0xeb, 0x69, 0xaa, 0xc7, 0x57, 0x16, 0xc6,
- 0x68, 0x94, 0x9d, 0x1d, 0xe4, 0x5d, 0xa7, 0xb2, 0x2d, 0x6b, 0xeb, 0x41,
- 0xdb, 0xcf, 0xb1, 0x37, 0x96, 0xdf, 0x52, 0x47, 0xd7, 0x46, 0xcc, 0x47,
- 0x1f, 0xd7, 0xc7, 0x7c, 0x99, 0xb8, 0x27, 0xbb, 0xdc, 0x00, 0xdf, 0xd5,
- 0xd3, 0x41, 0x8c, 0x47, 0x9a, 0xa3, 0x75, 0x3e, 0xf2, 0xef, 0xea, 0x33,
- 0xaa, 0x39, 0x3d, 0x97, 0xc0, 0x97, 0x4e, 0xa2, 0xfe, 0x7f, 0x00, 0xdd,
- 0x7c, 0x26, 0xed, 0x01, 0x1e, 0x4c, 0xfa, 0x6d, 0x9b, 0x37, 0xc3, 0xfd,
- 0xdc, 0x27, 0x01, 0x6f, 0xda, 0xf5, 0xba, 0xd4, 0xfb, 0xe3, 0xea, 0xe7,
- 0xae, 0xd7, 0x1d, 0x37, 0xd6, 0xcd, 0xa9, 0x5f, 0x0a, 0x8b, 0x94, 0x85,
- 0xf7, 0x23, 0x0d, 0xfc, 0xa1, 0x01, 0xd8, 0x8e, 0x0c, 0xfc, 0x1f, 0xfa,
- 0x45, 0x97, 0xf9, 0x44, 0x3c, 0xc3, 0x1c, 0xcf, 0xc3, 0x47, 0x56, 0xb6,
- 0xc3, 0xb7, 0x8b, 0xc8, 0x43, 0x87, 0xd4, 0xee, 0xa6, 0x5c, 0x8d, 0x4f,
- 0x54, 0xdd, 0xf1, 0xc9, 0xea, 0xc0, 0x38, 0x7d, 0x07, 0x5f, 0xce, 0x50,
- 0xbf, 0x2a, 0x13, 0x06, 0xda, 0x65, 0x55, 0x3b, 0x15, 0xcb, 0xd8, 0xa4,
- 0x1f, 0xe1, 0x1e, 0x9c, 0xf0, 0xc7, 0x8a, 0x8d, 0xe7, 0xa0, 0x77, 0x16,
- 0x67, 0x61, 0xd7, 0x1c, 0x3b, 0x43, 0x59, 0xdc, 0xe7, 0xda, 0x23, 0x4a,
- 0xde, 0xe2, 0xf6, 0x18, 0xd7, 0xaf, 0x32, 0xfb, 0x5e, 0xe8, 0x4d, 0x4f,
- 0xee, 0x84, 0xfe, 0x7b, 0x00, 0xf2, 0x29, 0x67, 0xa0, 0xfc, 0xce, 0x40,
- 0x61, 0x9d, 0x89, 0x8b, 0x71, 0xa2, 0x53, 0xa2, 0x47, 0x13, 0x12, 0x39,
- 0x4a, 0xff, 0x2b, 0x69, 0xde, 0x29, 0x02, 0x3b, 0xf8, 0xe2, 0xcd, 0x86,
- 0xd8, 0x83, 0x19, 0x49, 0xc2, 0x87, 0xec, 0x33, 0x2b, 0x48, 0x8b, 0x92,
- 0x4c, 0x9d, 0x46, 0x5f, 0xd1, 0x33, 0xa8, 0x8b, 0x76, 0x4d, 0xcb, 0x16,
- 0x7e, 0x1d, 0xd2, 0xbc, 0xec, 0xef, 0x8f, 0xe6, 0xe5, 0xf5, 0xf1, 0x9b,
- 0xa1, 0xd5, 0xf8, 0x0d, 0xdf, 0xbf, 0xad, 0xe3, 0x4e, 0x5f, 0xd2, 0xbe,
- 0x0c, 0xe5, 0x82, 0xf6, 0x4c, 0xf9, 0x63, 0xd0, 0xdd, 0x5f, 0x82, 0xff,
- 0xeb, 0x48, 0xae, 0x04, 0x9c, 0x9e, 0xf6, 0xe4, 0x69, 0xb7, 0xe0, 0x65,
- 0x07, 0x3c, 0x79, 0xdd, 0x75, 0x0a, 0x79, 0xb1, 0xdf, 0xa6, 0x8e, 0xfb,
- 0xb1, 0xfb, 0x21, 0xd9, 0xd3, 0x66, 0xef, 0xc9, 0x84, 0x0a, 0x5e, 0x8b,
- 0xd3, 0x2c, 0x57, 0xa7, 0x0f, 0xc9, 0xbe, 0x1d, 0x2b, 0x66, 0x58, 0x32,
- 0x57, 0x03, 0x0b, 0x26, 0xf2, 0x4a, 0x3f, 0xbd, 0xa1, 0x7c, 0xea, 0xfb,
- 0xbb, 0x0f, 0xc9, 0xd6, 0x1d, 0xb6, 0x79, 0x29, 0x4c, 0x9c, 0x76, 0x08,
- 0xf8, 0xdf, 0x4e, 0xe4, 0xc2, 0x8e, 0xb9, 0x5b, 0xec, 0x91, 0x4f, 0x0b,
- 0xcf, 0x8c, 0x1d, 0xe9, 0x3a, 0xea, 0x24, 0x1e, 0x0c, 0xf5, 0x1c, 0x78,
- 0x90, 0x3e, 0xdd, 0x19, 0xe6, 0x3d, 0x89, 0xed, 0x30, 0xf1, 0x1c, 0x97,
- 0xae, 0x13, 0x96, 0x24, 0xc1, 0x97, 0x5e, 0xc5, 0x13, 0x9e, 0x5d, 0x25,
- 0xa4, 0xe7, 0x28, 0x71, 0x93, 0xe2, 0x4d, 0x2f, 0x78, 0x93, 0x02, 0x6f,
- 0xe0, 0x47, 0xf5, 0x99, 0x97, 0x90, 0x9e, 0x97, 0xe4, 0xe0, 0x9b, 0xe0,
- 0x4d, 0x2f, 0x78, 0xd3, 0x73, 0xc6, 0x42, 0x7b, 0xf4, 0xb1, 0xdc, 0x85,
- 0xb4, 0x59, 0x3e, 0x72, 0x55, 0x07, 0x9e, 0x1d, 0x49, 0x1e, 0x8d, 0x61,
- 0x8c, 0x90, 0xec, 0xea, 0x2e, 0xc8, 0xf0, 0x0e, 0xf8, 0x63, 0xf1, 0x43,
- 0x72, 0x01, 0xb6, 0xa7, 0x04, 0xbf, 0xe0, 0xe9, 0x41, 0x7b, 0x6c, 0x05,
- 0xfa, 0xb3, 0x76, 0x97, 0x27, 0xaf, 0xec, 0xf8, 0x2b, 0x2f, 0x71, 0x95,
- 0xbd, 0x47, 0x42, 0x03, 0x32, 0x5d, 0x52, 0x36, 0x21, 0x91, 0x0d, 0x2b,
- 0x2c, 0x86, 0x39, 0x16, 0x60, 0x57, 0x78, 0x16, 0xee, 0x40, 0xbf, 0x7f,
- 0x5a, 0x1e, 0x28, 0x4f, 0xe1, 0x07, 0x1f, 0x73, 0x86, 0x75, 0x0f, 0xc0,
- 0x87, 0x7b, 0x48, 0xf6, 0xcf, 0x00, 0x2f, 0xa6, 0x41, 0xf7, 0x80, 0x03,
- 0x1f, 0xee, 0x7c, 0xa3, 0xb4, 0xa2, 0x0c, 0xbc, 0x1d, 0xab, 0x6d, 0xf4,
- 0xdd, 0x56, 0xb0, 0x0e, 0x83, 0xf2, 0x97, 0xb5, 0x01, 0xf9, 0x6a, 0xad,
- 0x5f, 0xbe, 0x0c, 0x7b, 0xf2, 0x6c, 0xad, 0x13, 0x7b, 0x25, 0x81, 0x35,
- 0x49, 0x63, 0x7d, 0x5c, 0xf9, 0x4a, 0x2d, 0x25, 0x5f, 0x02, 0xaf, 0x9e,
- 0xc3, 0x6f, 0xb8, 0x94, 0x92, 0x5d, 0xa5, 0x7e, 0xbd, 0x46, 0x5c, 0x1f,
- 0x07, 0xf4, 0x38, 0x98, 0xbb, 0xfd, 0x54, 0x01, 0xfb, 0x6f, 0xb1, 0xe6,
- 0xbc, 0x55, 0x91, 0xc7, 0x1a, 0x19, 0x5f, 0x3e, 0xb5, 0x6a, 0x53, 0x0a,
- 0x9e, 0xe9, 0xd8, 0x47, 0x26, 0xb0, 0x0e, 0x15, 0xec, 0xd3, 0x31, 0xc5,
- 0xfb, 0x35, 0x7b, 0x53, 0xf1, 0xed, 0x4d, 0x30, 0xbf, 0xd9, 0xbc, 0x7c,
- 0x47, 0xb2, 0x73, 0xd3, 0xb2, 0xef, 0xb8, 0x27, 0xbf, 0xe3, 0x7a, 0x90,
- 0x63, 0xea, 0xdf, 0x01, 0xea, 0x75, 0x6b, 0x22, 0x6c, 0x28, 0xff, 0xc9,
- 0xc7, 0x2a, 0xbd, 0xdb, 0xb1, 0x67, 0x53, 0x19, 0x63, 0x4a, 0x92, 0x73,
- 0x53, 0xd2, 0x35, 0x07, 0x59, 0x70, 0xd9, 0xd7, 0x8a, 0x69, 0x5c, 0x26,
- 0x0f, 0x1c, 0xc7, 0x1e, 0xcc, 0x89, 0x63, 0xbe, 0x25, 0x29, 0x8c, 0x7f,
- 0x50, 0xba, 0xd1, 0xc6, 0x41, 0x9b, 0x4b, 0x6a, 0xec, 0x16, 0x8c, 0xdd,
- 0x28, 0x87, 0xe3, 0x36, 0x64, 0x8d, 0x76, 0xfb, 0xff, 0x48, 0xb6, 0xc2,
- 0xf4, 0x6f, 0x25, 0x7b, 0xea, 0x91, 0x98, 0x34, 0xf3, 0x19, 0xaa, 0x61,
- 0x81, 0xe5, 0x5d, 0x48, 0x59, 0xee, 0xc0, 0x77, 0xfe, 0x89, 0x64, 0xcf,
- 0x72, 0xec, 0xb7, 0x50, 0xfe, 0x8a, 0x64, 0x8f, 0xfd, 0x1c, 0xf9, 0x0b,
- 0x48, 0xdf, 0x46, 0x3a, 0x26, 0x5d, 0xc7, 0x24, 0x94, 0x3d, 0xfb, 0x6d,
- 0xe4, 0x23, 0x48, 0x0f, 0xa3, 0xde, 0x6d, 0xa0, 0xef, 0xaf, 0xd1, 0x5f,
- 0x06, 0x7a, 0xee, 0xc3, 0x9a, 0x7e, 0x96, 0xb3, 0x8c, 0xef, 0x0e, 0x43,
- 0xa7, 0xfd, 0x0f, 0x8f, 0xf1, 0x44, 0xf5, 0xbc, 0xc8, 0x3c, 0x75, 0x1b,
- 0x9f, 0xa7, 0xc0, 0x93, 0x83, 0xc8, 0x7b, 0xf2, 0x90, 0x4b, 0x1b, 0x73,
- 0x93, 0x8c, 0x9b, 0x05, 0xaf, 0x19, 0x58, 0xa2, 0x05, 0xfb, 0x60, 0x6a,
- 0xe7, 0xe6, 0xfb, 0xe0, 0x48, 0xcf, 0x21, 0x69, 0xda, 0x11, 0xcc, 0x3f,
- 0x98, 0xaf, 0x63, 0xfe, 0x48, 0xf1, 0xc1, 0x2e, 0x3c, 0x28, 0x9c, 0x87,
- 0x93, 0x78, 0xdc, 0xe8, 0xd9, 0xf3, 0x00, 0xf6, 0x81, 0x71, 0x96, 0x79,
- 0x7f, 0x1f, 0x18, 0x67, 0xa1, 0x1b, 0x16, 0xe0, 0x17, 0x2e, 0x74, 0x4a,
- 0xe3, 0xb1, 0xb5, 0x7d, 0xd0, 0x70, 0xec, 0x57, 0xef, 0x83, 0xc6, 0xb3,
- 0xa8, 0x77, 0x96, 0x3c, 0x43, 0x1f, 0xa7, 0xc8, 0xb3, 0x0e, 0xa4, 0x9f,
- 0xc6, 0x5c, 0x49, 0x7b, 0x23, 0x68, 0xf7, 0xb1, 0xd0, 0xcd, 0x90, 0xf7,
- 0xfb, 0x77, 0x1c, 0xd4, 0xe5, 0xff, 0xd9, 0x1b, 0x89, 0xdb, 0x65, 0x09,
- 0x91, 0xa7, 0xa8, 0x5b, 0x21, 0x0f, 0x6f, 0x69, 0x92, 0xe6, 0x03, 0xd2,
- 0x45, 0xfe, 0x55, 0x76, 0x23, 0x5f, 0xf0, 0xa2, 0x4e, 0x8b, 0xe6, 0x27,
- 0xb0, 0xd1, 0x00, 0xcb, 0x5f, 0x83, 0xcc, 0x10, 0xa3, 0xbe, 0x21, 0xfb,
- 0x66, 0x3c, 0x19, 0x77, 0x39, 0xff, 0xef, 0x63, 0xfe, 0x99, 0x1d, 0x71,
- 0x59, 0xb1, 0xe2, 0xe0, 0xc9, 0x22, 0x74, 0xfb, 0x05, 0xf1, 0xf9, 0xc0,
- 0x33, 0x89, 0x5d, 0xe2, 0x24, 0x86, 0xc5, 0x49, 0xbd, 0x09, 0x3e, 0x0c,
- 0x43, 0xf6, 0x73, 0x35, 0xca, 0xce, 0xab, 0x32, 0x04, 0x99, 0xf8, 0x9e,
- 0x6b, 0xa7, 0x80, 0x7f, 0xa0, 0x2f, 0x28, 0x17, 0x94, 0x89, 0x56, 0xa5,
- 0x93, 0x16, 0x5c, 0xfb, 0x89, 0x8a, 0x5c, 0x27, 0x0b, 0xed, 0xa4, 0x1d,
- 0xef, 0x8e, 0x29, 0x7b, 0x91, 0x9a, 0x30, 0xba, 0xa1, 0xa3, 0x53, 0x62,
- 0xf6, 0x7c, 0xb1, 0x31, 0xb8, 0xbf, 0x92, 0x9f, 0x0b, 0xc9, 0x54, 0x0f,
- 0xd7, 0x8a, 0xfd, 0x22, 0x5f, 0x29, 0x78, 0x11, 0xe7, 0x2d, 0xef, 0x64,
- 0x87, 0x25, 0x9f, 0xec, 0x59, 0x95, 0xcb, 0xb2, 0x88, 0xbf, 0x2f, 0x86,
- 0xd4, 0x7a, 0x04, 0x74, 0x07, 0x73, 0x09, 0xde, 0xf5, 0xd7, 0xbd, 0xe3,
- 0x5c, 0x28, 0xeb, 0xab, 0x7b, 0xc7, 0xba, 0x9c, 0xd6, 0x9f, 0x41, 0x9e,
- 0xec, 0x27, 0x8a, 0xf2, 0x3a, 0x64, 0x0f, 0x3c, 0x3c, 0xcb, 0x94, 0x3c,
- 0x9c, 0x82, 0xdc, 0xbf, 0x26, 0xbb, 0xe6, 0xb8, 0x67, 0x5e, 0xc3, 0x5c,
- 0x95, 0x2e, 0x81, 0x8e, 0x60, 0x7f, 0x9e, 0x4c, 0xbb, 0xdd, 0xa9, 0x53,
- 0x72, 0x5d, 0x62, 0x12, 0x7e, 0xe6, 0x84, 0xe9, 0xc9, 0xb2, 0x5b, 0x90,
- 0xe5, 0x41, 0xb4, 0xa9, 0x7c, 0x1a, 0xbf, 0x79, 0x3d, 0xb7, 0x47, 0xc0,
- 0x77, 0xdb, 0x2a, 0x1b, 0x9f, 0x01, 0xdf, 0x1f, 0x92, 0xe4, 0xb1, 0x55,
- 0x5d, 0x03, 0xb9, 0xf3, 0x75, 0x4d, 0xf2, 0xac, 0x29, 0x95, 0x92, 0x23,
- 0x1f, 0xa3, 0x0e, 0x29, 0x71, 0x5e, 0xd0, 0x31, 0x3c, 0xdf, 0x2f, 0x41,
- 0xcf, 0x94, 0xa0, 0x53, 0xa0, 0x43, 0xbe, 0x8c, 0xf2, 0x2f, 0xa1, 0xce,
- 0x73, 0xf0, 0x99, 0x9e, 0x05, 0xde, 0x3b, 0x07, 0x1c, 0xf1, 0x4c, 0x29,
- 0xa3, 0xfd, 0x57, 0x35, 0x5f, 0xd8, 0x2c, 0xe5, 0xef, 0x48, 0xa5, 0x4c,
- 0x7e, 0xfc, 0x44, 0xad, 0x6d, 0xd6, 0xdd, 0x46, 0x6c, 0x05, 0xca, 0x44,
- 0xca, 0xe5, 0x80, 0x27, 0xd4, 0x7d, 0x3c, 0x1b, 0x0a, 0x74, 0x65, 0xcb,
- 0x06, 0x5d, 0x29, 0xf2, 0x62, 0xd5, 0xc7, 0x90, 0xc4, 0xc4, 0xc5, 0x19,
- 0x6b, 0xf5, 0x0c, 0xb5, 0x08, 0xbb, 0x79, 0x1e, 0xbe, 0x45, 0x2c, 0xfd,
- 0x2d, 0x89, 0x9d, 0xf0, 0xbc, 0x1f, 0xc0, 0x6e, 0x16, 0xb0, 0x26, 0x46,
- 0x08, 0xe5, 0x4b, 0x7c, 0x47, 0xb9, 0xa7, 0x6c, 0x87, 0x78, 0x96, 0x22,
- 0x2f, 0xa3, 0xac, 0xa2, 0x7c, 0xae, 0x6f, 0x83, 0x1e, 0x4d, 0x9f, 0x2a,
- 0x63, 0xbd, 0x46, 0xc9, 0x8d, 0xa7, 0xe0, 0xd7, 0xf4, 0x99, 0x8d, 0x68,
- 0x5f, 0x5e, 0x62, 0x1b, 0x7b, 0x90, 0x57, 0xb9, 0x5e, 0x5e, 0x62, 0x79,
- 0xa7, 0x5c, 0x80, 0xff, 0x49, 0x1a, 0x2a, 0xf3, 0x69, 0xf1, 0xe3, 0xc5,
- 0xd4, 0x57, 0xa4, 0x15, 0x79, 0xf0, 0x2b, 0x5b, 0xa2, 0x9d, 0x8d, 0x48,
- 0x21, 0x41, 0x5e, 0x27, 0xe4, 0xfc, 0xcc, 0x1f, 0x37, 0x31, 0x1e, 0x9b,
- 0x75, 0xf8, 0x1c, 0xc4, 0x37, 0xcc, 0x77, 0x10, 0xdf, 0x60, 0x4c, 0x23,
- 0x02, 0x5b, 0xa6, 0xe2, 0x1c, 0x48, 0xad, 0x3a, 0x9f, 0x97, 0xef, 0x7d,
- 0x6c, 0xb4, 0x86, 0x19, 0x89, 0x21, 0x39, 0x5f, 0xbb, 0xb0, 0x02, 0xfd,
- 0xd1, 0x9e, 0x7e, 0x49, 0xee, 0x5e, 0xf0, 0xe7, 0x67, 0x9c, 0x12, 0xde,
- 0xe3, 0x91, 0x4b, 0xf3, 0xb6, 0x7b, 0x51, 0x78, 0x06, 0xe2, 0x62, 0xbd,
- 0xfe, 0xa0, 0x09, 0xfa, 0x6b, 0x30, 0x63, 0x7c, 0xbb, 0xc9, 0xc7, 0x67,
- 0x11, 0x99, 0x9a, 0xe1, 0x99, 0x2b, 0x74, 0x1b, 0x70, 0xe3, 0xef, 0x45,
- 0xf0, 0x5c, 0x65, 0x1e, 0x7e, 0xa8, 0xef, 0xc3, 0xe2, 0xd9, 0xef, 0x8f,
- 0x3c, 0x37, 0x16, 0x38, 0xf7, 0x90, 0xdc, 0x0d, 0x74, 0x22, 0xe8, 0xbf,
- 0x4b, 0x8f, 0xd5, 0x75, 0x2a, 0xc5, 0xf8, 0xb5, 0x24, 0xa1, 0x2f, 0xb2,
- 0xf0, 0x1f, 0x73, 0xf1, 0x4e, 0x8d, 0xc7, 0xf9, 0x6e, 0x23, 0xde, 0x0c,
- 0xfc, 0xba, 0x94, 0x7c, 0xbe, 0x14, 0x60, 0xbd, 0x14, 0x6c, 0xac, 0x44,
- 0x46, 0x7a, 0x3d, 0xf9, 0x81, 0x4b, 0x7e, 0xf5, 0x23, 0xef, 0xca, 0x91,
- 0xda, 0x2f, 0x3b, 0x5b, 0xad, 0xff, 0x6b, 0x01, 0x8d, 0xfc, 0x81, 0x3e,
- 0xe0, 0x23, 0xd2, 0x6e, 0xc0, 0x9e, 0x17, 0x81, 0xbb, 0x8c, 0x33, 0x9d,
- 0xea, 0x9d, 0x01, 0x6c, 0x50, 0x99, 0x81, 0x6e, 0x3c, 0xc3, 0xf3, 0x66,
- 0xe8, 0xb6, 0x33, 0x51, 0x29, 0xce, 0x52, 0x2e, 0xa5, 0xdd, 0xc0, 0x7a,
- 0xb1, 0x7e, 0x65, 0xa6, 0x13, 0x69, 0x0b, 0x52, 0x4b, 0xf5, 0x53, 0x99,
- 0x71, 0x54, 0xfb, 0xca, 0x4c, 0x4a, 0xb5, 0xab, 0xcc, 0xf4, 0x23, 0x75,
- 0xa5, 0xe1, 0x0c, 0x9c, 0xa5, 0x33, 0x3d, 0x32, 0x75, 0x12, 0xf6, 0x65,
- 0xc0, 0x50, 0x77, 0x35, 0x26, 0x60, 0x7f, 0x22, 0xf0, 0xac, 0x2e, 0x9a,
- 0x83, 0xc0, 0x58, 0x37, 0x01, 0x83, 0xdc, 0x24, 0xce, 0x09, 0xce, 0x9f,
- 0xba, 0xf7, 0x3c, 0x63, 0x5e, 0x89, 0x4f, 0x48, 0x46, 0xf6, 0xcf, 0x36,
- 0x62, 0xbf, 0x46, 0xcc, 0xa2, 0x74, 0x9b, 0xc3, 0xc8, 0xe7, 0xcb, 0xe4,
- 0xdb, 0xbd, 0xca, 0x5f, 0xcb, 0xba, 0x37, 0x34, 0x4b, 0x73, 0x1a, 0x63,
- 0xbc, 0x93, 0xf6, 0xbd, 0x90, 0x3f, 0x47, 0xf7, 0x91, 0x06, 0x3d, 0xf5,
- 0xfc, 0xe0, 0x39, 0x73, 0xe6, 0x57, 0x9c, 0x33, 0x53, 0xae, 0xc9, 0xdf,
- 0x7b, 0xe5, 0xbc, 0x93, 0x96, 0x97, 0x9d, 0x94, 0x5c, 0x70, 0x76, 0xca,
- 0x37, 0x61, 0xa7, 0x5f, 0x72, 0xce, 0x34, 0x11, 0x0b, 0x54, 0xd4, 0xd9,
- 0x5d, 0xb0, 0x56, 0x8e, 0x8e, 0x9d, 0xff, 0x50, 0x96, 0x67, 0x88, 0x9d,
- 0xbd, 0xdb, 0xf6, 0xb9, 0x05, 0xda, 0x2d, 0xd0, 0x40, 0xac, 0x56, 0x80,
- 0xfd, 0x3b, 0x24, 0xc3, 0x2e, 0xed, 0x9e, 0xb2, 0x51, 0x89, 0x61, 0x7f,
- 0x3f, 0xbb, 0x79, 0xe8, 0xd5, 0xf3, 0xb3, 0xd8, 0x4f, 0x42, 0xf9, 0xc7,
- 0x73, 0x99, 0xeb, 0xee, 0xc8, 0xe3, 0x25, 0xce, 0xb3, 0xb8, 0xbd, 0x59,
- 0xc2, 0x32, 0xa2, 0xf0, 0x42, 0xab, 0xbc, 0xb8, 0xb4, 0x45, 0x0c, 0x58,
- 0x28, 0xe3, 0xda, 0xa8, 0xba, 0xe5, 0x42, 0x9f, 0x5b, 0xda, 0x78, 0xb6,
- 0xf6, 0x87, 0xe0, 0x0d, 0xfd, 0x7f, 0xcc, 0xad, 0x8d, 0x33, 0x09, 0xf2,
- 0xfd, 0xd8, 0x5f, 0x7c, 0x0e, 0x49, 0xce, 0x89, 0xe3, 0x99, 0x29, 0xf7,
- 0x1c, 0x63, 0x63, 0x61, 0xf1, 0x31, 0xf7, 0x21, 0xf5, 0xbe, 0xd1, 0xb9,
- 0x15, 0xb8, 0x8e, 0xf2, 0x8a, 0x74, 0xd9, 0x1f, 0x37, 0x07, 0x1c, 0x97,
- 0xef, 0xe7, 0x1d, 0x1b, 0x3b, 0x55, 0xc0, 0x5e, 0x98, 0x50, 0xf5, 0x07,
- 0xe4, 0xa5, 0x99, 0x52, 0xb3, 0xbf, 0x3f, 0x06, 0xf5, 0x33, 0xdf, 0xd3,
- 0xa7, 0x62, 0x8c, 0xe4, 0x99, 0xd1, 0x69, 0xe7, 0xa2, 0xde, 0x3f, 0x12,
- 0xba, 0xb3, 0x17, 0x38, 0xf4, 0x68, 0x03, 0xe6, 0x62, 0x5b, 0x56, 0xc8,
- 0xe8, 0x30, 0x80, 0xe3, 0x87, 0x95, 0xcd, 0xed, 0x55, 0x31, 0xe8, 0x53,
- 0xa9, 0x56, 0xa9, 0x98, 0x8e, 0xba, 0x93, 0xb7, 0x62, 0xee, 0x20, 0xd6,
- 0xc7, 0xaf, 0x09, 0x65, 0xdd, 0x48, 0x1b, 0x91, 0xbe, 0x5f, 0x8a, 0xc7,
- 0xcf, 0xe8, 0xf1, 0xa2, 0x1b, 0xf2, 0x1f, 0xd1, 0xe9, 0x67, 0xb5, 0x3f,
- 0xc5, 0x71, 0xa2, 0xe2, 0x7c, 0xa1, 0x45, 0xba, 0x8f, 0x9a, 0xc0, 0xb6,
- 0x09, 0x60, 0xdd, 0x4e, 0x49, 0x1d, 0xb5, 0xe4, 0xda, 0xa3, 0x41, 0x9c,
- 0xe9, 0x2b, 0xa3, 0x49, 0x15, 0xd7, 0xfc, 0xf2, 0xa8, 0x53, 0x56, 0xe7,
- 0xed, 0xfa, 0xee, 0xe0, 0x8a, 0xbe, 0x53, 0xf8, 0xca, 0x68, 0xaf, 0x4a,
- 0xbf, 0x3d, 0x9a, 0x52, 0xe9, 0xab, 0xa3, 0xd7, 0x56, 0x7d, 0xff, 0xa8,
- 0xb8, 0x98, 0x92, 0xcf, 0x95, 0x88, 0x2f, 0x07, 0x80, 0x1d, 0x5d, 0xe8,
- 0x99, 0x7e, 0xe8, 0x99, 0x14, 0xf4, 0xcc, 0x20, 0xf5, 0x0c, 0xf4, 0xf6,
- 0xab, 0xd0, 0xdb, 0xae, 0x7c, 0x0f, 0xf2, 0xfa, 0x8c, 0xdb, 0x08, 0x5c,
- 0xe8, 0x79, 0xfe, 0x5c, 0xed, 0x27, 0x56, 0xb0, 0xbe, 0x95, 0xd3, 0x12,
- 0x6b, 0x83, 0x0e, 0xda, 0xb1, 0xd0, 0x20, 0x8b, 0x71, 0xcf, 0x9b, 0x73,
- 0x1d, 0xb9, 0x84, 0xfa, 0x59, 0x87, 0xfb, 0xf8, 0x6f, 0x9a, 0xe9, 0x8f,
- 0x5d, 0x9a, 0xd9, 0x09, 0x9d, 0x44, 0x79, 0x8f, 0x49, 0x65, 0x3c, 0x21,
- 0x4b, 0xf0, 0xcf, 0xd6, 0xea, 0xa4, 0xf0, 0xcc, 0xfd, 0xff, 0x13, 0xd4,
- 0x4d, 0xc1, 0x3e, 0x98, 0xb2, 0xdc, 0x6b, 0xc9, 0xa9, 0x5e, 0x7b, 0xd0,
- 0x32, 0xa8, 0xbb, 0x2c, 0x29, 0xc3, 0xbf, 0xaf, 0x94, 0x58, 0x9f, 0xf5,
- 0xb0, 0x3f, 0x4b, 0x7e, 0xbb, 0xe9, 0x52, 0xa0, 0x27, 0x06, 0x18, 0x7b,
- 0x8c, 0xe4, 0x7a, 0x7d, 0x1b, 0x60, 0x18, 0x8d, 0x90, 0x03, 0x17, 0xfc,
- 0x1f, 0x47, 0xf9, 0x00, 0xef, 0x9a, 0xa0, 0x8c, 0x58, 0x28, 0xb6, 0x85,
- 0x18, 0x31, 0xe7, 0x8e, 0xa3, 0x8c, 0x6d, 0xec, 0x44, 0x12, 0xe5, 0x63,
- 0x92, 0x4c, 0xe4, 0xd5, 0xbd, 0xb7, 0x0e, 0x94, 0xb1, 0x8f, 0xb0, 0x8e,
- 0xc1, 0x74, 0x6c, 0xf1, 0xcf, 0x7d, 0x83, 0xf2, 0x3e, 0x15, 0x0f, 0xc8,
- 0x98, 0x2e, 0xf6, 0x03, 0xcb, 0x92, 0x26, 0xdb, 0xe5, 0x5c, 0x57, 0xe9,
- 0xc2, 0x7b, 0xaa, 0x3c, 0xb7, 0x8b, 0xc9, 0xdd, 0xd5, 0x16, 0xc9, 0x55,
- 0x1b, 0xae, 0xa0, 0xff, 0x83, 0x3d, 0x79, 0x3e, 0x61, 0x0a, 0xef, 0x60,
- 0xf8, 0xfb, 0x3c, 0xb2, 0x93, 0x7b, 0x02, 0x7c, 0x87, 0xfd, 0x7d, 0x0e,
- 0xf3, 0x7d, 0x16, 0xf6, 0xf7, 0x1c, 0xec, 0xef, 0x33, 0xa5, 0x35, 0xfd,
- 0xe1, 0xdb, 0x5d, 0xea, 0x80, 0xa7, 0xb0, 0x66, 0x63, 0xc0, 0xfd, 0xbb,
- 0xe1, 0x0f, 0x8c, 0x00, 0xfb, 0x0f, 0x61, 0xfd, 0xd2, 0x58, 0xbb, 0x71,
- 0xde, 0x55, 0xc2, 0x3a, 0x0e, 0xaa, 0xb3, 0xe5, 0x59, 0x75, 0xdf, 0xe3,
- 0x87, 0xca, 0xf6, 0x3e, 0x56, 0x32, 0x60, 0x1f, 0x0a, 0xde, 0x76, 0xc7,
- 0x06, 0xfe, 0x5b, 0xdd, 0xcf, 0x83, 0x2f, 0x42, 0xaf, 0xfc, 0x1d, 0xe8,
- 0x7a, 0x76, 0x96, 0xf6, 0x1c, 0x75, 0x7c, 0xbc, 0xed, 0x32, 0xbe, 0x85,
- 0xfd, 0x7c, 0xe4, 0xbc, 0xac, 0x00, 0x77, 0x64, 0x28, 0xc7, 0xf0, 0x1f,
- 0xec, 0x67, 0xca, 0xd2, 0x43, 0x1d, 0x58, 0xe6, 0x5e, 0x19, 0x38, 0x96,
- 0x00, 0xd6, 0x03, 0x92, 0x57, 0x67, 0xa9, 0x78, 0x3e, 0xbb, 0x55, 0x0c,
- 0xe2, 0x3d, 0xf7, 0x2a, 0x94, 0x51, 0x6f, 0x04, 0x18, 0x69, 0x65, 0xb0,
- 0x5d, 0x32, 0x3b, 0xda, 0x95, 0xee, 0xb0, 0xdd, 0x97, 0x31, 0xee, 0x2e,
- 0x69, 0x04, 0x86, 0x2b, 0x60, 0x8c, 0x83, 0xf2, 0x37, 0x2e, 0xe3, 0x52,
- 0xbe, 0xef, 0x07, 0x5a, 0x62, 0xe0, 0x59, 0xd3, 0x3e, 0xc7, 0x8c, 0xed,
- 0xaa, 0xb1, 0xff, 0x98, 0xc2, 0x58, 0x39, 0x61, 0xff, 0xb0, 0x13, 0x18,
- 0x33, 0x79, 0x8c, 0xb2, 0xdf, 0x87, 0x75, 0xfb, 0x2d, 0x60, 0x20, 0x72,
- 0xf5, 0x5b, 0x5b, 0xfc, 0xfd, 0x42, 0xfa, 0x57, 0x88, 0x27, 0x18, 0xf7,
- 0xf7, 0xfd, 0xf2, 0x55, 0xda, 0x06, 0x40, 0xef, 0x73, 0x5b, 0x82, 0xf3,
- 0xe3, 0xae, 0x63, 0xbe, 0xbd, 0xee, 0x3a, 0x8b, 0x56, 0x73, 0xd2, 0xc1,
- 0x93, 0x68, 0x43, 0xae, 0x95, 0xdb, 0x23, 0x7e, 0x3f, 0xc6, 0x82, 0x09,
- 0x59, 0xa5, 0x1e, 0xe8, 0x80, 0x9c, 0x33, 0x4f, 0x9d, 0x42, 0x9d, 0x40,
- 0x59, 0x70, 0xa4, 0x58, 0x83, 0x4e, 0x68, 0xed, 0x94, 0x32, 0x79, 0xb6,
- 0x40, 0x3d, 0xf1, 0x43, 0x99, 0xde, 0xa0, 0x2b, 0x87, 0x24, 0xf0, 0x6b,
- 0x5b, 0x24, 0x9a, 0x76, 0xcc, 0x7b, 0xd4, 0x1c, 0x7d, 0x7d, 0xb9, 0x9f,
- 0xf8, 0x73, 0x36, 0x63, 0xb7, 0x8b, 0xc6, 0x9e, 0x0a, 0x3f, 0x7d, 0x1f,
- 0x73, 0x65, 0x1f, 0x8a, 0x4f, 0x83, 0x43, 0xbe, 0x2f, 0xa0, 0xe2, 0x7c,
- 0xc0, 0xc1, 0x89, 0xbf, 0x83, 0xae, 0xcd, 0x11, 0x97, 0x80, 0xcf, 0x5d,
- 0x73, 0x94, 0xa3, 0xed, 0xd4, 0x65, 0xc0, 0x79, 0x29, 0xea, 0x6b, 0x59,
- 0x3a, 0x06, 0xcc, 0x65, 0xdc, 0x2a, 0x79, 0xca, 0x2b, 0xef, 0x48, 0x2c,
- 0x19, 0x32, 0x3d, 0xdf, 0x2a, 0xdd, 0x0b, 0x8c, 0xa9, 0x7e, 0xb3, 0x59,
- 0x5a, 0x19, 0x57, 0xa5, 0x0d, 0x1a, 0x90, 0x1c, 0xca, 0xbb, 0x16, 0xc2,
- 0x2a, 0x06, 0x56, 0x36, 0xc8, 0xa3, 0x7e, 0xe8, 0x03, 0x3b, 0xb5, 0x62,
- 0x7c, 0xb4, 0xc9, 0xc7, 0x90, 0x90, 0xa5, 0x12, 0x64, 0xac, 0x04, 0x19,
- 0x2b, 0x41, 0xc6, 0x4a, 0x90, 0x31, 0x60, 0xbf, 0x67, 0xb1, 0xff, 0xce,
- 0x95, 0x06, 0xb5, 0x5d, 0xdf, 0xa3, 0xec, 0xfa, 0xe1, 0xd2, 0xab, 0x1e,
- 0xd3, 0x2f, 0x29, 0xdf, 0xb4, 0x1f, 0x32, 0x48, 0x5f, 0x34, 0xf0, 0x51,
- 0x5f, 0x95, 0xa7, 0x66, 0x5f, 0x93, 0x53, 0xb3, 0x6b, 0x38, 0x70, 0xaa,
- 0xe4, 0xc9, 0xcb, 0x2e, 0xfc, 0xcf, 0x45, 0x62, 0xaa, 0x4c, 0x5b, 0xa3,
- 0xc2, 0x56, 0x87, 0x24, 0xaf, 0x70, 0xb2, 0xb2, 0x23, 0xc0, 0x57, 0x0a,
- 0x17, 0x72, 0x6f, 0x4a, 0xfb, 0x8e, 0xd7, 0xe5, 0x1c, 0xec, 0xf8, 0x52,
- 0xed, 0x0d, 0x79, 0x4e, 0xe1, 0x71, 0xf2, 0xe1, 0x7d, 0xf2, 0xb7, 0xa6,
- 0x7f, 0x86, 0x7f, 0x0a, 0x58, 0x63, 0xa9, 0x97, 0xba, 0x23, 0x02, 0x5b,
- 0x60, 0x17, 0xba, 0xb0, 0xaf, 0x0f, 0x18, 0xef, 0x02, 0xa6, 0xe1, 0xfb,
- 0xad, 0xf2, 0xe2, 0x6c, 0xa1, 0x4e, 0x26, 0xa8, 0x1f, 0xec, 0x23, 0x62,
- 0xd0, 0x4e, 0xd1, 0x6e, 0x72, 0xbe, 0xb4, 0x53, 0x6d, 0x2d, 0xbc, 0x3f,
- 0x56, 0x39, 0x7e, 0xc3, 0x16, 0xc6, 0x18, 0xe3, 0x0e, 0x79, 0xfa, 0xba,
- 0x1c, 0xa8, 0xb2, 0xec, 0x35, 0xac, 0x0f, 0xd3, 0x37, 0xbd, 0xbb, 0xe3,
- 0x1c, 0x8f, 0xfd, 0x02, 0x37, 0x75, 0x60, 0xae, 0xa5, 0xcf, 0x6a, 0xcc,
- 0xdd, 0xaf, 0x70, 0xf4, 0xe5, 0x78, 0x99, 0x7c, 0x72, 0xc1, 0xa7, 0xd7,
- 0x55, 0x0c, 0x70, 0x93, 0xd8, 0xf0, 0x13, 0xd8, 0x57, 0x85, 0x8b, 0xc2,
- 0x38, 0x25, 0x63, 0xb8, 0x8c, 0x0f, 0xd7, 0x6b, 0x0c, 0x75, 0x57, 0x40,
- 0xee, 0x82, 0x7e, 0xb9, 0x1b, 0xfa, 0xe5, 0x9e, 0xcb, 0xee, 0x5f, 0x07,
- 0x71, 0xff, 0xee, 0x42, 0xd8, 0xe8, 0x94, 0xb1, 0x6a, 0x7d, 0x5b, 0xc6,
- 0x6e, 0x37, 0x8b, 0xd5, 0x32, 0x8e, 0x9b, 0xda, 0x10, 0xff, 0xa3, 0x6c,
- 0x78, 0xf2, 0x92, 0xcb, 0xb8, 0x5b, 0x70, 0x67, 0x7f, 0x33, 0xfc, 0x65,
- 0xb5, 0x04, 0x71, 0xe6, 0x48, 0xfa, 0xa2, 0xf0, 0xee, 0x7e, 0x71, 0x86,
- 0x78, 0x20, 0xae, 0xee, 0xd9, 0x19, 0x2a, 0xce, 0xe7, 0xb7, 0x2d, 0xce,
- 0xa8, 0x73, 0xa5, 0x02, 0xe3, 0xd5, 0xe6, 0x4e, 0xdb, 0x1c, 0x0b, 0xfb,
- 0xf7, 0x65, 0xb8, 0x97, 0x7d, 0x5d, 0x06, 0x59, 0xac, 0xad, 0xdd, 0xb1,
- 0x1c, 0x52, 0xfa, 0xe2, 0x22, 0xf6, 0x00, 0xd7, 0x0b, 0xfe, 0x02, 0xf6,
- 0xc9, 0x14, 0xf4, 0x53, 0x5e, 0xf5, 0x17, 0xa3, 0x5c, 0x64, 0xb2, 0x61,
- 0x43, 0xa2, 0x27, 0xe8, 0x0b, 0xf9, 0xb1, 0x96, 0x5c, 0xd8, 0x56, 0xfa,
- 0x1b, 0xb4, 0x03, 0x9f, 0x71, 0x7f, 0x5a, 0x13, 0x8d, 0xe9, 0x06, 0xd8,
- 0x55, 0xac, 0x5f, 0x8d, 0x31, 0x01, 0xec, 0xdd, 0xe5, 0xef, 0xca, 0xfe,
- 0xf9, 0xe1, 0x16, 0x5f, 0xfe, 0x19, 0x3b, 0xe6, 0xfc, 0x02, 0x1a, 0xd6,
- 0xf7, 0x6d, 0x9c, 0x90, 0x58, 0x33, 0x6c, 0xda, 0x87, 0xe1, 0x67, 0xec,
- 0x82, 0xac, 0xac, 0xc4, 0xd9, 0xaf, 0xbf, 0x67, 0xa6, 0x4b, 0xec, 0xfb,
- 0xbb, 0x32, 0x3c, 0x7f, 0xb6, 0x85, 0xb6, 0x64, 0x19, 0x7a, 0xe0, 0xbc,
- 0x49, 0x1b, 0x3a, 0x0e, 0x1b, 0xd7, 0x21, 0xdf, 0x9f, 0xa7, 0x7d, 0x4c,
- 0x9a, 0xa7, 0xa4, 0x2f, 0x71, 0x0a, 0x34, 0x7d, 0xde, 0x8d, 0xd0, 0x47,
- 0xf3, 0x86, 0x50, 0xf6, 0x4d, 0x49, 0x9a, 0x5d, 0x21, 0x3e, 0xf7, 0x99,
- 0x8f, 0x03, 0xc3, 0x66, 0xcc, 0xa4, 0x79, 0x5d, 0x88, 0x72, 0x04, 0x9f,
- 0x7b, 0x79, 0x8d, 0xce, 0x37, 0xe7, 0x95, 0x9f, 0xa4, 0xf4, 0xcc, 0xb2,
- 0xcb, 0xf1, 0x40, 0xb7, 0xd2, 0x59, 0xd7, 0x41, 0x9f, 0xc4, 0xf4, 0x99,
- 0x1b, 0xda, 0x10, 0xdb, 0xb8, 0x11, 0x9d, 0x7f, 0x44, 0xb2, 0x27, 0xe3,
- 0xd0, 0x67, 0xec, 0x2b, 0xf0, 0x1d, 0x68, 0x23, 0x03, 0xbc, 0x4d, 0x7b,
- 0x77, 0x2b, 0xec, 0xde, 0x35, 0x8a, 0x9e, 0x11, 0xb7, 0x5f, 0xa6, 0x8e,
- 0x73, 0xec, 0x5e, 0xe8, 0xf2, 0x84, 0x92, 0xdb, 0x62, 0xe9, 0x7c, 0x22,
- 0x06, 0x9d, 0x1c, 0xdb, 0x41, 0x7e, 0x7e, 0x50, 0xee, 0x70, 0xc6, 0xe5,
- 0x4e, 0xc8, 0xce, 0x90, 0xe3, 0xca, 0x30, 0xd6, 0x62, 0x97, 0x03, 0xbb,
- 0xa3, 0x30, 0x74, 0x23, 0xfc, 0x2e, 0x8e, 0xdd, 0xa1, 0xef, 0x5c, 0xf8,
- 0xf8, 0xf1, 0xcf, 0x6a, 0x3e, 0x8f, 0xb2, 0xf3, 0x2f, 0x2b, 0xde, 0x8c,
- 0xb8, 0x37, 0x69, 0x3b, 0xdb, 0x2a, 0x39, 0x55, 0xef, 0x26, 0x65, 0x8f,
- 0x8b, 0x4b, 0xf7, 0x22, 0x85, 0x6d, 0x5e, 0x82, 0xbe, 0x01, 0xe6, 0x2e,
- 0x56, 0x77, 0x22, 0x0f, 0x1b, 0xba, 0x94, 0x46, 0xfa, 0x41, 0xa4, 0xac,
- 0xfb, 0xb9, 0x16, 0x3f, 0x96, 0x5b, 0x7f, 0x87, 0xcc, 0xbf, 0x7f, 0xfa,
- 0x61, 0x85, 0x4b, 0x2f, 0xaa, 0xfb, 0x87, 0x06, 0xb0, 0x4e, 0x16, 0x7a,
- 0xa5, 0x05, 0x18, 0x68, 0xe6, 0x84, 0x9d, 0x1a, 0x0e, 0xdd, 0x26, 0x1f,
- 0x81, 0x2f, 0x5f, 0x71, 0xb9, 0x96, 0x3b, 0xe5, 0x13, 0xb7, 0x50, 0x46,
- 0x6e, 0x93, 0x7d, 0xb7, 0x84, 0x64, 0x5f, 0xbf, 0x9d, 0x21, 0xdd, 0xd7,
- 0xbe, 0x3f, 0xf0, 0xa7, 0xbb, 0x47, 0x92, 0xa1, 0x01, 0x79, 0x1c, 0x32,
- 0x56, 0x80, 0x7c, 0x0d, 0xd7, 0xc8, 0x73, 0xea, 0x7b, 0xea, 0xf9, 0x14,
- 0xb0, 0x72, 0x80, 0xfd, 0x1c, 0x99, 0xa9, 0x35, 0x88, 0x75, 0x15, 0xe3,
- 0xc9, 0x96, 0x7f, 0xae, 0x71, 0x15, 0x65, 0x02, 0x3e, 0xc8, 0x55, 0xfe,
- 0xfe, 0x54, 0xf7, 0xfe, 0xae, 0xf2, 0xed, 0x0a, 0xfc, 0x5f, 0x8f, 0x38,
- 0xcf, 0xbf, 0x5f, 0x70, 0x51, 0xeb, 0xd2, 0xe4, 0xd6, 0x55, 0x7c, 0xd7,
- 0x4a, 0xff, 0xe1, 0xeb, 0x2d, 0x6b, 0xdf, 0x2d, 0x6c, 0x94, 0xc5, 0x20,
- 0xee, 0x56, 0xc6, 0x9c, 0x69, 0xd3, 0x6d, 0x93, 0xba, 0xb0, 0xcd, 0xd9,
- 0x23, 0x7f, 0x09, 0xfb, 0xfe, 0xd5, 0x55, 0xfb, 0xbe, 0x17, 0xfc, 0xd8,
- 0x88, 0x01, 0x1c, 0xf3, 0x2e, 0xcc, 0x65, 0x04, 0xeb, 0x79, 0x27, 0x7e,
- 0x77, 0x94, 0xd6, 0xc5, 0xf1, 0x66, 0x0b, 0xc0, 0x93, 0x0d, 0x0e, 0xfb,
- 0x5b, 0x17, 0xcf, 0x2b, 0xe4, 0x65, 0x35, 0x56, 0x38, 0x78, 0x49, 0x68,
- 0xf7, 0xde, 0x92, 0x68, 0x8f, 0xf3, 0x56, 0x57, 0xc8, 0x79, 0xde, 0x08,
- 0xf1, 0xec, 0xdb, 0x95, 0xd3, 0x35, 0xe2, 0xb0, 0x0b, 0x62, 0x9c, 0x25,
- 0x06, 0x7b, 0x45, 0xc5, 0xa0, 0x2a, 0xa5, 0x6f, 0x23, 0x45, 0x7d, 0xe8,
- 0xc7, 0xb0, 0x1f, 0xa7, 0x50, 0x58, 0x85, 0x7a, 0xf6, 0x4e, 0xac, 0xc3,
- 0x14, 0x7e, 0x5d, 0x3b, 0xae, 0xc3, 0xfe, 0xa5, 0x9c, 0x32, 0xf6, 0xd5,
- 0x63, 0xee, 0x08, 0xf1, 0xdd, 0x66, 0x71, 0xb0, 0xef, 0x48, 0x64, 0x0e,
- 0xb6, 0xce, 0xa0, 0x7e, 0xe0, 0x3c, 0x68, 0x27, 0x4d, 0x59, 0x3c, 0xce,
- 0xbd, 0xbe, 0x59, 0xfd, 0xa0, 0x6e, 0x30, 0x17, 0x65, 0x37, 0x32, 0x79,
- 0xc6, 0x38, 0x4b, 0x5c, 0x03, 0x17, 0x6b, 0xe0, 0xc9, 0x09, 0xb7, 0x0d,
- 0x7a, 0x3b, 0x2e, 0xe1, 0x13, 0x9e, 0x0c, 0x29, 0xec, 0xda, 0x07, 0xcc,
- 0xb5, 0x55, 0xe3, 0x86, 0xb8, 0x44, 0x4e, 0x74, 0x4a, 0x23, 0x70, 0x75,
- 0xc3, 0x51, 0xda, 0xc8, 0xa4, 0x35, 0x04, 0x21, 0x88, 0xa8, 0xbb, 0xac,
- 0xf6, 0xe0, 0xf7, 0xa5, 0xcf, 0xfa, 0xbe, 0x10, 0x2f, 0xfd, 0x7b, 0xac,
- 0x9f, 0xed, 0x5e, 0xd8, 0xa4, 0x7e, 0x71, 0xad, 0x3e, 0xe4, 0x88, 0xb1,
- 0x35, 0xb6, 0x61, 0xac, 0x2d, 0x39, 0xf8, 0x3d, 0xc6, 0xd8, 0xe0, 0x6b,
- 0x36, 0x9c, 0xf1, 0x69, 0x30, 0x96, 0xdb, 0xa5, 0x72, 0x92, 0x7b, 0x94,
- 0x71, 0x16, 0xd3, 0xf7, 0x53, 0x4b, 0xf4, 0x57, 0xf9, 0xde, 0xd2, 0xef,
- 0xbb, 0xf4, 0x7b, 0xfa, 0xa3, 0x05, 0xaf, 0x01, 0x3c, 0xdd, 0x05, 0xfd,
- 0x79, 0xef, 0x4e, 0x47, 0xe1, 0x86, 0x7b, 0x57, 0xd7, 0x6c, 0xb7, 0xba,
- 0x4f, 0x54, 0x29, 0x1d, 0x12, 0x67, 0xc7, 0x4a, 0x2a, 0x22, 0x63, 0x58,
- 0x0b, 0xe6, 0x33, 0xa4, 0x27, 0x75, 0x58, 0x0e, 0xa8, 0xb5, 0xa9, 0x1c,
- 0xb7, 0x8f, 0x58, 0xa1, 0x29, 0x31, 0x2a, 0x7c, 0xfe, 0x34, 0xd2, 0xc3,
- 0xc0, 0x3b, 0x7e, 0xec, 0xd2, 0xa8, 0xac, 0xe7, 0x25, 0x30, 0x86, 0xb9,
- 0x6b, 0x5d, 0x1c, 0x6b, 0x2d, 0xc6, 0xc5, 0xf7, 0x43, 0xea, 0x7d, 0x6a,
- 0x5d, 0x9c, 0x2b, 0x67, 0x10, 0xcb, 0x04, 0xef, 0xb9, 0x16, 0x5c, 0x2f,
- 0xd8, 0xe2, 0xe3, 0x41, 0xcc, 0xab, 0x55, 0xaf, 0x0b, 0xd7, 0x67, 0x46,
- 0xce, 0x99, 0xf6, 0x08, 0xe5, 0xef, 0x86, 0x9d, 0x57, 0xcb, 0x44, 0x07,
- 0xe3, 0x6d, 0xf5, 0x34, 0x6c, 0x8c, 0xa3, 0xd5, 0x8f, 0xbf, 0x31, 0xfe,
- 0xc6, 0xb1, 0xfd, 0x18, 0x5b, 0x76, 0x5d, 0x8c, 0xad, 0x7e, 0x3c, 0x8e,
- 0xb5, 0x15, 0xfe, 0x53, 0xc1, 0x8b, 0x3b, 0x5c, 0xa3, 0x6e, 0x6b, 0x9e,
- 0xf9, 0x2f, 0x1a, 0x58, 0xc7, 0x38, 0xec, 0x08, 0xd7, 0x32, 0x38, 0x6f,
- 0xe6, 0x9a, 0x26, 0xad, 0xc3, 0xfe, 0x7a, 0x0e, 0xfa, 0xeb, 0xee, 0xaf,
- 0xff, 0x85, 0xd5, 0x75, 0xa4, 0x7d, 0xe0, 0x3a, 0x76, 0x88, 0x40, 0xcf,
- 0x1a, 0x47, 0xb9, 0x86, 0x4c, 0xb9, 0x86, 0x7c, 0xc7, 0x35, 0xec, 0xd2,
- 0xef, 0xb8, 0x7e, 0xc0, 0x69, 0x5f, 0xe0, 0x3d, 0xd5, 0xac, 0xfa, 0x06,
- 0xab, 0xab, 0x27, 0xd8, 0x8b, 0x29, 0x79, 0x6e, 0xb1, 0x59, 0xcc, 0xb4,
- 0x3f, 0xaf, 0xf1, 0x75, 0xf1, 0x76, 0x9e, 0x5f, 0xf5, 0x13, 0x7b, 0x06,
- 0xf3, 0x4a, 0x70, 0x5e, 0x07, 0xe4, 0x75, 0xc9, 0xcf, 0x44, 0xe0, 0x03,
- 0xa6, 0x80, 0x73, 0xfa, 0xa1, 0x6f, 0x19, 0x1f, 0x45, 0x59, 0x95, 0x78,
- 0x85, 0xb6, 0x2e, 0x85, 0xbd, 0x42, 0x1d, 0x4c, 0x3c, 0xf2, 0x9a, 0xe4,
- 0xca, 0x81, 0x8e, 0x41, 0xff, 0x46, 0xd0, 0x3f, 0xf9, 0x9c, 0xb9, 0x76,
- 0xbb, 0xac, 0x58, 0xdb, 0xc5, 0xb6, 0x96, 0x64, 0x6d, 0x5d, 0xc7, 0x37,
- 0xe7, 0xbb, 0x7b, 0x6f, 0x78, 0x4d, 0x36, 0xc6, 0x37, 0x59, 0xfb, 0x49,
- 0x09, 0xde, 0x07, 0x6b, 0xbf, 0xe9, 0x3a, 0x14, 0x5e, 0x15, 0xae, 0x05,
- 0x79, 0x40, 0x3c, 0x1c, 0x95, 0x7f, 0x13, 0xe7, 0x7e, 0x2c, 0xa8, 0x33,
- 0xcd, 0xa4, 0xd1, 0xa3, 0x74, 0xc6, 0x90, 0xeb, 0xcb, 0x6b, 0x01, 0xe3,
- 0xc4, 0xba, 0xff, 0xd0, 0x1b, 0x8a, 0xc3, 0xcf, 0xed, 0xa6, 0x7e, 0x09,
- 0xf6, 0x74, 0xb3, 0xda, 0xd3, 0x9f, 0x77, 0x43, 0x52, 0x74, 0x42, 0x32,
- 0xe5, 0x1c, 0x52, 0x18, 0xff, 0xa3, 0xe8, 0xeb, 0x13, 0xba, 0xaf, 0x29,
- 0xe9, 0xd1, 0xfa, 0xe7, 0x20, 0xe4, 0xdc, 0x93, 0x7b, 0xdc, 0x9d, 0x72,
- 0x43, 0x1b, 0xf7, 0x40, 0x30, 0xff, 0x43, 0xd2, 0xbd, 0x73, 0xc5, 0x82,
- 0x67, 0x70, 0x6d, 0x74, 0x95, 0x07, 0xdc, 0x67, 0x81, 0x7c, 0xfb, 0x7c,
- 0xf0, 0xe7, 0xbf, 0x6e, 0xae, 0x7a, 0x9e, 0x9c, 0x33, 0xeb, 0x71, 0xae,
- 0x3e, 0x96, 0x5f, 0x9b, 0x6b, 0x50, 0xbf, 0x05, 0xb2, 0x64, 0x5b, 0x12,
- 0xaa, 0xe7, 0xcd, 0xaa, 0x8e, 0x1a, 0x61, 0x8c, 0x64, 0xc5, 0xb4, 0x53,
- 0x56, 0x28, 0x88, 0x45, 0xfb, 0x58, 0xb7, 0x0b, 0x38, 0xdc, 0xe9, 0xe9,
- 0x49, 0xe5, 0x55, 0x8c, 0xd4, 0x50, 0xf3, 0x9a, 0x02, 0x26, 0x5b, 0x74,
- 0x5f, 0xf5, 0x3e, 0x09, 0xcc, 0x3a, 0x21, 0x0f, 0x49, 0x78, 0x5d, 0x2c,
- 0x17, 0xf9, 0xb3, 0x8c, 0xe7, 0xda, 0x56, 0x06, 0x6b, 0xfc, 0x3b, 0xf0,
- 0xe1, 0x2b, 0xd0, 0xfb, 0x1f, 0xa3, 0x6d, 0x28, 0xc1, 0x5e, 0x00, 0x97,
- 0x7c, 0xf5, 0x8a, 0x18, 0x7e, 0xa2, 0x2e, 0x96, 0xeb, 0xe3, 0xd3, 0x73,
- 0x0a, 0x93, 0x12, 0xb7, 0x1f, 0x09, 0xdd, 0xd5, 0x1b, 0x86, 0x9f, 0x51,
- 0xf0, 0x62, 0x0e, 0x71, 0xdc, 0x21, 0xb9, 0x03, 0xeb, 0x73, 0x7a, 0xb1,
- 0x10, 0xda, 0x55, 0x0a, 0x64, 0x15, 0x7e, 0x65, 0xcd, 0x4e, 0x9d, 0x07,
- 0x3f, 0x9e, 0xd2, 0x98, 0x8f, 0xe7, 0x35, 0x15, 0xed, 0xb3, 0x30, 0x36,
- 0x54, 0xac, 0x1d, 0x92, 0x69, 0x97, 0xb1, 0x9d, 0x6e, 0x29, 0xc6, 0x33,
- 0x57, 0x37, 0xae, 0xf2, 0xc8, 0x36, 0xe1, 0xf3, 0xa5, 0xa8, 0xbf, 0x2b,
- 0xfa, 0xbc, 0xe3, 0x29, 0x25, 0x5f, 0x41, 0x5c, 0x98, 0xfe, 0x11, 0xcf,
- 0xab, 0xba, 0xcd, 0x11, 0x3e, 0x97, 0x29, 0x03, 0xca, 0x67, 0x02, 0x2f,
- 0xef, 0x90, 0xcc, 0x98, 0xa5, 0x70, 0xcb, 0x63, 0x25, 0xee, 0x17, 0xe2,
- 0xff, 0xd7, 0x81, 0xfd, 0x23, 0x58, 0x33, 0xfa, 0x01, 0x1c, 0x9b, 0xfb,
- 0x02, 0x65, 0x55, 0xf3, 0x97, 0xec, 0x8b, 0x0f, 0x6d, 0x23, 0xc6, 0x78,
- 0xa1, 0xf4, 0x98, 0xe2, 0xdf, 0x8a, 0x04, 0xb1, 0x73, 0x85, 0x05, 0x0b,
- 0xd9, 0x70, 0x48, 0x92, 0x73, 0xff, 0x16, 0x32, 0xd4, 0x0f, 0x1f, 0x89,
- 0xf5, 0x44, 0x9d, 0x5f, 0x0d, 0x01, 0x73, 0x19, 0xce, 0xbb, 0xa4, 0x68,
- 0x46, 0xa5, 0xa8, 0xee, 0xfe, 0xf1, 0x3c, 0x37, 0xac, 0x62, 0x3b, 0x45,
- 0x93, 0x98, 0x3f, 0xbd, 0x2d, 0xb8, 0xfb, 0x57, 0x34, 0xd9, 0x8e, 0x79,
- 0x96, 0x4f, 0x49, 0x74, 0xee, 0xa0, 0x34, 0xcc, 0x3d, 0x24, 0x8d, 0xc7,
- 0x88, 0xf1, 0x18, 0xbb, 0x37, 0x6e, 0x6d, 0x14, 0x62, 0xee, 0x6f, 0x61,
- 0xec, 0x43, 0xf2, 0x03, 0x37, 0xa0, 0xe9, 0xba, 0xad, 0xd2, 0xca, 0x3a,
- 0x41, 0x9e, 0xcf, 0xc4, 0x09, 0x3c, 0x17, 0x77, 0xfc, 0x18, 0xa9, 0x3a,
- 0x57, 0x41, 0x5a, 0xe1, 0xb9, 0x38, 0xdf, 0xbf, 0x66, 0xfa, 0xa9, 0x8f,
- 0xf7, 0x7d, 0xdf, 0x83, 0x6d, 0x52, 0x75, 0xd8, 0x62, 0xfd, 0xf7, 0xa1,
- 0x39, 0x94, 0xe7, 0xe7, 0x83, 0x3b, 0x3a, 0x06, 0x7c, 0x5f, 0xbb, 0x40,
- 0x9f, 0xc1, 0xe4, 0xb7, 0x98, 0xf3, 0x05, 0xf0, 0xf9, 0x1a, 0x75, 0xbf,
- 0x87, 0x77, 0x24, 0x50, 0xcf, 0xf2, 0x31, 0x1f, 0xf3, 0x09, 0xf0, 0xf9,
- 0xfd, 0x9d, 0x46, 0xfa, 0x7f, 0x5f, 0x9d, 0x1d, 0x20, 0xa6, 0xd8, 0xc6,
- 0xb3, 0x3f, 0x60, 0x55, 0xae, 0xed, 0x77, 0xb1, 0xb6, 0x8d, 0xea, 0xac,
- 0xa5, 0x58, 0xa2, 0x0f, 0x95, 0xc7, 0x9a, 0xf1, 0x9e, 0x1c, 0x7d, 0xad,
- 0xbc, 0x8e, 0x81, 0x92, 0x4e, 0xe2, 0xe8, 0x00, 0x93, 0xb3, 0xcf, 0xcd,
- 0xee, 0x03, 0x07, 0x7e, 0x12, 0xd7, 0x38, 0xa1, 0x68, 0x1e, 0xde, 0xe0,
- 0x23, 0x1c, 0xc6, 0xfe, 0x5b, 0x84, 0x0c, 0x4d, 0x42, 0xef, 0x0c, 0x85,
- 0xb9, 0x27, 0x9a, 0xb5, 0xff, 0xe8, 0xd0, 0x57, 0x0e, 0x8d, 0xa1, 0x0f,
- 0xe3, 0xd8, 0x1b, 0x32, 0x05, 0x9d, 0x3b, 0x5d, 0x4b, 0xaa, 0x6f, 0x78,
- 0x32, 0x09, 0xde, 0xdb, 0x62, 0xf9, 0x7f, 0x81, 0x8c, 0xbc, 0x01, 0x0c,
- 0xba, 0x05, 0xfc, 0x34, 0xf4, 0xbd, 0x90, 0x0f, 0xe8, 0xf8, 0x4f, 0x8c,
- 0xf1, 0x6f, 0xe8, 0xaa, 0xa2, 0x8f, 0xef, 0xe2, 0xd3, 0x48, 0xbf, 0xd0,
- 0xec, 0xcb, 0xc8, 0xcb, 0x7a, 0x8d, 0x9b, 0x50, 0xfe, 0xa8, 0x8a, 0xfb,
- 0xf9, 0x73, 0xb2, 0xb5, 0x7f, 0x10, 0xc5, 0x3a, 0x73, 0x5e, 0x5f, 0x41,
- 0x3d, 0xae, 0x6f, 0xaf, 0x3e, 0x0f, 0x6d, 0x56, 0x3a, 0x29, 0xe7, 0x5a,
- 0xf0, 0x75, 0x89, 0x89, 0x80, 0xa9, 0x5d, 0xb6, 0x7b, 0x76, 0x1b, 0xcf,
- 0x1b, 0x1b, 0x1c, 0x85, 0xe7, 0x3b, 0xc2, 0x12, 0x94, 0xdd, 0x8e, 0x32,
- 0xc6, 0x25, 0xde, 0x85, 0xb5, 0x61, 0x59, 0x16, 0x79, 0x8e, 0x75, 0xb5,
- 0x1e, 0x87, 0x63, 0x0c, 0xb7, 0xac, 0xa7, 0x89, 0x73, 0xe9, 0xd8, 0xf0,
- 0xfd, 0x00, 0xcb, 0xde, 0xa5, 0xcb, 0x22, 0x7a, 0x7e, 0xb7, 0xeb, 0x6f,
- 0x67, 0xed, 0x23, 0x99, 0x55, 0x3c, 0x4a, 0xfa, 0x62, 0xaa, 0x5d, 0xc6,
- 0xf4, 0x65, 0xe7, 0x30, 0xd6, 0x23, 0x92, 0xf6, 0xda, 0xb9, 0x47, 0x86,
- 0xc2, 0x81, 0x5f, 0x98, 0x50, 0xbe, 0x9e, 0x65, 0xf8, 0x77, 0x84, 0xce,
- 0x5d, 0x76, 0x0f, 0xda, 0xbf, 0x53, 0x3e, 0xdc, 0xdb, 0x24, 0x8b, 0xb3,
- 0x31, 0x7d, 0x3f, 0x31, 0xa1, 0xf6, 0x49, 0x7e, 0x9c, 0xf9, 0x1f, 0x6d,
- 0xe3, 0x77, 0xcb, 0x86, 0xc3, 0xf2, 0x0e, 0xcd, 0xdf, 0x77, 0xa9, 0xfb,
- 0x3c, 0xbc, 0x67, 0x52, 0x2c, 0xff, 0x44, 0xbd, 0x3f, 0x3d, 0xdf, 0xa0,
- 0xea, 0x9f, 0x9e, 0xdf, 0x78, 0x27, 0x87, 0x65, 0xef, 0x66, 0x4c, 0x41,
- 0x96, 0x66, 0x1a, 0x64, 0x79, 0xde, 0xa2, 0x8f, 0x94, 0x6e, 0x5c, 0xfb,
- 0xf6, 0x45, 0x7f, 0xa7, 0xe6, 0xc9, 0x30, 0xd6, 0x6f, 0x71, 0x70, 0x5a,
- 0x2a, 0x83, 0xf4, 0x01, 0xd4, 0xbd, 0x3b, 0xc8, 0x48, 0x03, 0xf0, 0x5f,
- 0xc1, 0xab, 0x38, 0x8c, 0xbd, 0xb6, 0x6a, 0x1f, 0xea, 0xc7, 0xda, 0xcf,
- 0x22, 0x8f, 0x0c, 0xc9, 0xf5, 0x4f, 0x29, 0xba, 0x2a, 0x8a, 0x57, 0xc1,
- 0xb7, 0x45, 0xec, 0x9f, 0xdf, 0x17, 0x85, 0x35, 0x7e, 0x7c, 0x50, 0xf3,
- 0xfc, 0xaf, 0x75, 0xfa, 0x88, 0xec, 0x3b, 0xfe, 0x19, 0xd0, 0xda, 0xe4,
- 0xdf, 0x2d, 0x92, 0xfa, 0xef, 0x36, 0x22, 0xea, 0xdb, 0x95, 0x88, 0xf3,
- 0x08, 0xca, 0x18, 0x7b, 0x7a, 0x44, 0xcd, 0x83, 0xf7, 0xd7, 0x0a, 0xf2,
- 0xab, 0xee, 0x64, 0x04, 0xfe, 0x0f, 0xef, 0x08, 0x35, 0xeb, 0xfe, 0x76,
- 0xe9, 0x75, 0x1c, 0x97, 0x7d, 0xd0, 0xef, 0x79, 0xe0, 0x40, 0xde, 0xab,
- 0x9a, 0x08, 0xd7, 0x8f, 0x19, 0xc8, 0xb2, 0xef, 0x5b, 0x07, 0x67, 0xfd,
- 0x61, 0xe5, 0x03, 0xac, 0xfa, 0xe9, 0xba, 0x7c, 0x5c, 0xf6, 0x97, 0x94,
- 0xbf, 0xae, 0xce, 0xe8, 0xa6, 0xb1, 0x27, 0x87, 0x94, 0x0e, 0x8f, 0x85,
- 0x86, 0xab, 0x69, 0xc9, 0x9f, 0xdc, 0x8d, 0x71, 0x18, 0xfb, 0xca, 0xe8,
- 0xb3, 0xb0, 0xbd, 0xb2, 0xaf, 0xe6, 0x8f, 0x3d, 0x59, 0xe2, 0xfb, 0x24,
- 0xec, 0x22, 0xdf, 0xe7, 0x12, 0x61, 0x15, 0xcd, 0xbf, 0x0e, 0x6d, 0x1b,
- 0x34, 0x6f, 0x79, 0x9f, 0x9e, 0xed, 0xb9, 0xff, 0x3e, 0x6e, 0x4a, 0x73,
- 0x0e, 0xef, 0xd9, 0x26, 0xe8, 0x6f, 0x12, 0x7a, 0x9a, 0xfe, 0xe8, 0xc3,
- 0xb2, 0x52, 0x9e, 0x96, 0xf3, 0xe5, 0x40, 0xce, 0x78, 0xb7, 0x99, 0xb4,
- 0xdf, 0xa9, 0xef, 0x36, 0x67, 0xb0, 0x0e, 0xeb, 0x79, 0x95, 0x5b, 0xf7,
- 0xfd, 0xd1, 0x5f, 0x98, 0xfe, 0x37, 0x80, 0xb7, 0xa9, 0x7b, 0x4a, 0xeb,
- 0xe5, 0x9d, 0xfd, 0x2c, 0x9b, 0x8c, 0xed, 0xfb, 0x77, 0xad, 0x3a, 0xea,
- 0xde, 0xc7, 0xf5, 0xfd, 0xa6, 0xe7, 0xf4, 0x9d, 0x78, 0xf2, 0x73, 0x4c,
- 0xd3, 0x7b, 0x1d, 0xf6, 0x1e, 0xfb, 0x7c, 0x54, 0xaf, 0x1b, 0xd2, 0x45,
- 0x3e, 0x53, 0x0f, 0xad, 0xe8, 0xf3, 0x4e, 0x53, 0x8f, 0x51, 0x7f, 0xbf,
- 0xac, 0xa1, 0x6e, 0x5c, 0xb6, 0xe7, 0xb7, 0x48, 0xc1, 0x5d, 0x6b, 0x96,
- 0x1d, 0xd7, 0xf7, 0xd8, 0x82, 0xbb, 0xd5, 0x2c, 0x0b, 0xee, 0x5b, 0x91,
- 0x5f, 0x8c, 0xe1, 0x21, 0xad, 0x8d, 0xe9, 0xe7, 0xb1, 0xba, 0x6f, 0x74,
- 0x82, 0x3e, 0x23, 0xe8, 0xe3, 0xf6, 0xf0, 0xe5, 0x77, 0xb1, 0xf9, 0xdd,
- 0x14, 0x65, 0xd1, 0xe0, 0x37, 0xdd, 0xf4, 0x7b, 0x80, 0x55, 0xb6, 0xca,
- 0xa4, 0xa2, 0xa7, 0xa0, 0xee, 0x27, 0x64, 0xdd, 0x26, 0x19, 0x32, 0xfd,
- 0xfc, 0xe4, 0xe2, 0x46, 0x39, 0x65, 0xf9, 0xf5, 0x31, 0x69, 0x2e, 0x60,
- 0x1c, 0xbe, 0xdf, 0xec, 0x1b, 0x81, 0xa8, 0xfe, 0x4e, 0xc9, 0x45, 0x9b,
- 0xcf, 0x53, 0xde, 0x0b, 0x85, 0xd5, 0xbb, 0x90, 0x05, 0x15, 0x97, 0x14,
- 0x23, 0xb8, 0x93, 0xc8, 0x6f, 0xd6, 0x45, 0x9e, 0xa9, 0xf2, 0xbb, 0xad,
- 0xdb, 0xd4, 0xbd, 0x11, 0xff, 0x2c, 0x8e, 0x74, 0x75, 0x2b, 0x9d, 0x5c,
- 0xa9, 0x16, 0xc9, 0x53, 0x1d, 0x87, 0x8d, 0xea, 0x38, 0x2c, 0x79, 0x3c,
- 0x02, 0x1e, 0xff, 0x3f, 0xbd, 0x2e, 0xc1, 0x77, 0x5f, 0x3c, 0xeb, 0xe1,
- 0x79, 0xd0, 0xa3, 0x6a, 0x2e, 0xd4, 0xd1, 0x68, 0xfb, 0xde, 0xb0, 0xda,
- 0xbb, 0xea, 0x9b, 0x78, 0xc8, 0x27, 0xbf, 0x71, 0x87, 0x7e, 0x2d, 0xf1,
- 0x5b, 0xf6, 0x11, 0xf5, 0x3d, 0x47, 0xa5, 0xca, 0x75, 0xe5, 0x37, 0xec,
- 0x63, 0x75, 0xf2, 0x18, 0xd6, 0x63, 0x6d, 0x69, 0x93, 0x66, 0x7f, 0xdd,
- 0xf9, 0x2d, 0x48, 0xa5, 0x1a, 0xdc, 0xa3, 0xdc, 0xb2, 0xc2, 0x3d, 0x21,
- 0xbe, 0x5f, 0xab, 0xbe, 0x67, 0xa9, 0xa8, 0xef, 0x43, 0x2c, 0x7e, 0x67,
- 0x09, 0xdb, 0xb1, 0x07, 0xcf, 0x3c, 0x47, 0xdd, 0x8b, 0x14, 0x3a, 0xa7,
- 0x3a, 0x81, 0xf4, 0x21, 0xc9, 0xa9, 0x38, 0x57, 0x0b, 0xf2, 0x93, 0x6a,
- 0xec, 0x62, 0xf5, 0x7e, 0xd9, 0x77, 0xf2, 0x01, 0x7e, 0x43, 0xa3, 0xbe,
- 0xc3, 0xcf, 0xba, 0xa4, 0x31, 0x2e, 0x53, 0x6a, 0xde, 0x85, 0xb5, 0x6f,
- 0x33, 0x7c, 0x39, 0x6a, 0xe3, 0x9a, 0x16, 0xaa, 0x2d, 0xa0, 0x31, 0xa4,
- 0xef, 0x52, 0x12, 0xff, 0x06, 0xf3, 0x6f, 0xe6, 0xfd, 0x3c, 0x8f, 0xe7,
- 0x65, 0xfb, 0x4a, 0xbc, 0x2b, 0x99, 0xd4, 0x7e, 0x31, 0x63, 0x65, 0x8c,
- 0xc7, 0x53, 0xc6, 0xed, 0xd4, 0x04, 0xb4, 0x7f, 0x54, 0x12, 0x3c, 0xcb,
- 0xd5, 0x73, 0x69, 0xa9, 0x9b, 0x0b, 0xef, 0x87, 0xfa, 0xf3, 0xe1, 0x37,
- 0x27, 0xf9, 0x52, 0xfd, 0xf7, 0x32, 0xea, 0x9b, 0x70, 0xf5, 0x7d, 0xca,
- 0x44, 0xf5, 0x41, 0xb9, 0xaf, 0xb4, 0x55, 0x7f, 0x2b, 0x13, 0x93, 0xfb,
- 0xaa, 0x6f, 0x28, 0x9e, 0xe6, 0xd5, 0x77, 0x3e, 0x51, 0xbd, 0x66, 0x71,
- 0xd5, 0xc7, 0xda, 0xf7, 0x3e, 0x76, 0xdd, 0xb7, 0x1f, 0x51, 0x99, 0x58,
- 0xfc, 0x65, 0xdf, 0xfc, 0x3c, 0x2c, 0xfc, 0xee, 0xe3, 0x25, 0x77, 0x5a,
- 0x1e, 0x2b, 0x7b, 0xde, 0x1d, 0x2e, 0xb1, 0xd4, 0x16, 0x39, 0x1f, 0xcf,
- 0x0c, 0x7e, 0xcf, 0x69, 0x0f, 0x55, 0x66, 0x1b, 0xa1, 0xaf, 0x1b, 0x95,
- 0x2d, 0x61, 0x7e, 0x71, 0x96, 0x7b, 0x3e, 0x82, 0x39, 0xda, 0xe6, 0x25,
- 0xf9, 0x54, 0x1b, 0xe3, 0x4c, 0x77, 0xc0, 0x77, 0xfb, 0xb8, 0xeb, 0xeb,
- 0xe5, 0xcf, 0x2d, 0xed, 0x96, 0xcf, 0x55, 0x63, 0xa1, 0xca, 0x0c, 0xef,
- 0xd7, 0xd9, 0x23, 0x65, 0x49, 0xa2, 0x1e, 0xfb, 0x87, 0xbc, 0x24, 0xb6,
- 0xcb, 0xd3, 0xc7, 0x7f, 0xee, 0x5d, 0x72, 0xf0, 0x1e, 0xba, 0xe6, 0xbc,
- 0x1b, 0xc4, 0xd2, 0xe0, 0x37, 0x1f, 0x65, 0xbd, 0xed, 0x90, 0x03, 0xd8,
- 0x6d, 0xec, 0x39, 0xfa, 0x75, 0x97, 0xb4, 0xde, 0x32, 0x8e, 0x5e, 0x23,
- 0x97, 0x56, 0xef, 0xe4, 0xbe, 0x0e, 0xd9, 0xb6, 0x7c, 0xfe, 0xab, 0xd8,
- 0xf3, 0x41, 0x09, 0x7f, 0x01, 0x76, 0xe2, 0x0b, 0x0d, 0x4a, 0xb7, 0xd3,
- 0x9e, 0x01, 0xf3, 0x03, 0xd7, 0x47, 0xd0, 0xcf, 0xfe, 0x36, 0x5f, 0x66,
- 0xa7, 0x45, 0xbe, 0xd8, 0x24, 0x99, 0x36, 0xfa, 0x8d, 0xf2, 0x2b, 0xf4,
- 0x57, 0xfd, 0x3e, 0x4b, 0xc9, 0x9f, 0x71, 0x8f, 0xd7, 0x38, 0x97, 0x64,
- 0xe2, 0x7f, 0xc9, 0x27, 0x65, 0x22, 0xc1, 0xb9, 0x3c, 0x2c, 0x85, 0xf2,
- 0xa3, 0xf8, 0x71, 0x9e, 0xa4, 0xfb, 0x5f, 0xe8, 0xb3, 0xfb, 0x31, 0x29,
- 0xce, 0xa4, 0x65, 0x6a, 0x7e, 0x92, 0xdf, 0xe4, 0x8e, 0xdc, 0xa1, 0xce,
- 0xb4, 0xec, 0x44, 0x32, 0xd4, 0x67, 0x4d, 0xf1, 0xae, 0x82, 0x9a, 0xcf,
- 0x24, 0xe6, 0xf3, 0x4a, 0x1b, 0xef, 0x78, 0x5f, 0x82, 0xfe, 0x35, 0x4e,
- 0x50, 0x0e, 0x6d, 0xb3, 0x2b, 0xc4, 0xfc, 0x5e, 0xf8, 0xab, 0x2c, 0xdb,
- 0x2b, 0xe1, 0xa3, 0xab, 0x7a, 0x1e, 0xe5, 0xfa, 0x6c, 0x55, 0xb5, 0xff,
- 0xaf, 0x68, 0x8b, 0x7a, 0x47, 0x83, 0xb6, 0x41, 0x1d, 0xb6, 0xe5, 0x3c,
- 0x77, 0xc3, 0x4f, 0x0e, 0xe8, 0x82, 0x1c, 0x26, 0xea, 0xf9, 0xdd, 0xbc,
- 0x81, 0xdf, 0x11, 0xe2, 0x4d, 0xf0, 0x8b, 0x3c, 0x0e, 0x6b, 0x1e, 0xff,
- 0x3d, 0xfa, 0x0f, 0xd6, 0xe0, 0x0e, 0x94, 0x99, 0xfa, 0x1b, 0xbc, 0x77,
- 0xc2, 0x77, 0xf2, 0x9c, 0xf5, 0xf7, 0xb7, 0xf9, 0xb2, 0x46, 0x7a, 0x36,
- 0xe3, 0xf9, 0x7b, 0xdb, 0xfd, 0x75, 0xd9, 0x0b, 0x7e, 0xf1, 0x1e, 0x65,
- 0x9f, 0xba, 0x8f, 0x9f, 0x19, 0xdf, 0x0b, 0xd9, 0x09, 0xe6, 0xd5, 0x07,
- 0x19, 0xe3, 0x39, 0x01, 0xeb, 0xd7, 0xf3, 0xc4, 0xb7, 0x7b, 0x61, 0xfa,
- 0xfa, 0x0e, 0xe7, 0x0a, 0x4c, 0xf8, 0x45, 0xf5, 0xfd, 0x0d, 0xf4, 0xe4,
- 0xbb, 0x57, 0xbf, 0xbf, 0xb9, 0xf2, 0x1a, 0x0f, 0xb4, 0xfb, 0x36, 0xca,
- 0x04, 0x4f, 0x5a, 0x75, 0x9b, 0xbd, 0xc0, 0xa7, 0x8c, 0x7f, 0x26, 0x13,
- 0x9f, 0x90, 0x60, 0x1c, 0xef, 0x36, 0xfa, 0x79, 0x43, 0x03, 0x7d, 0xf0,
- 0x69, 0xd5, 0x1d, 0x95, 0x04, 0xef, 0xbc, 0x24, 0x43, 0x7b, 0xd5, 0x7d,
- 0x85, 0x17, 0xd6, 0x7d, 0x43, 0x95, 0x92, 0xa7, 0xd7, 0x64, 0x65, 0xe4,
- 0x47, 0x62, 0x8b, 0x75, 0x35, 0x65, 0x85, 0xfd, 0x4e, 0x72, 0x9e, 0x89,
- 0x07, 0xd4, 0x3c, 0x4d, 0xf8, 0x4d, 0xbc, 0x5b, 0x60, 0x86, 0x2a, 0xf3,
- 0x5c, 0x77, 0xa4, 0x4b, 0x7c, 0x0e, 0xce, 0x37, 0x95, 0x5e, 0xc1, 0xb8,
- 0x2c, 0xa3, 0x6e, 0xe4, 0xfb, 0xb4, 0x3e, 0xff, 0xbc, 0xa7, 0x9d, 0x67,
- 0xf0, 0x79, 0x94, 0x95, 0x97, 0x36, 0xa7, 0xed, 0xe3, 0x4a, 0x0e, 0x1e,
- 0x06, 0xdf, 0xff, 0x04, 0x75, 0x1f, 0x45, 0xca, 0x39, 0xa6, 0x57, 0xd7,
- 0x9d, 0xfc, 0xfe, 0xb0, 0x0c, 0x42, 0x2e, 0x98, 0x7f, 0x58, 0x8a, 0xea,
- 0xee, 0x10, 0xd2, 0x32, 0x9f, 0xa9, 0xeb, 0x1d, 0x6d, 0x4f, 0x49, 0xcb,
- 0x5e, 0xfd, 0xdd, 0x56, 0x20, 0x4f, 0x7b, 0x74, 0xbb, 0xf1, 0x55, 0x5e,
- 0x3d, 0x70, 0x19, 0xde, 0x88, 0xae, 0xe2, 0x0d, 0x7f, 0xac, 0x62, 0x7b,
- 0x80, 0x35, 0xfc, 0x39, 0xf8, 0x58, 0xc3, 0x97, 0xf3, 0x49, 0x89, 0x40,
- 0x8e, 0xc3, 0x6b, 0x72, 0x0c, 0xdc, 0xe3, 0xef, 0x99, 0x29, 0x9e, 0xdb,
- 0x29, 0x3e, 0x53, 0x0e, 0x29, 0xbf, 0x5c, 0xc7, 0xfa, 0xb5, 0xbe, 0xf1,
- 0x97, 0xac, 0xf5, 0x85, 0xf6, 0x00, 0x3f, 0xfc, 0xd3, 0xf6, 0xc1, 0xd7,
- 0xda, 0xd7, 0xf6, 0xc1, 0x35, 0xbf, 0xa1, 0x7d, 0xb0, 0x51, 0x2e, 0xeb,
- 0x65, 0xca, 0x84, 0x3c, 0x71, 0xbd, 0x28, 0x4f, 0x94, 0x23, 0xf2, 0x92,
- 0xfa, 0xb4, 0x91, 0xbe, 0x53, 0xe2, 0xa2, 0xfa, 0x3e, 0x62, 0x1a, 0x3a,
- 0xa8, 0x3d, 0x54, 0x86, 0x5f, 0x5e, 0x5c, 0xba, 0x49, 0xc9, 0xf4, 0xd3,
- 0x35, 0xea, 0xa5, 0x2b, 0xcd, 0x7d, 0xbd, 0xce, 0xcd, 0x6f, 0xd0, 0xb9,
- 0xf9, 0x55, 0x9d, 0xdb, 0xa6, 0xfd, 0xa5, 0x7f, 0x8a, 0xce, 0x8d, 0xd7,
- 0x9d, 0x85, 0x04, 0xe7, 0x20, 0x12, 0xca, 0xf6, 0x36, 0xcb, 0xae, 0xd9,
- 0xb8, 0x8c, 0xcc, 0xec, 0x96, 0x3f, 0x9a, 0x99, 0x56, 0xf7, 0x82, 0xfe,
- 0xca, 0x4d, 0x26, 0xee, 0x0f, 0x79, 0xf2, 0x61, 0xf8, 0xbb, 0x13, 0x9d,
- 0x0d, 0xb2, 0xeb, 0xfd, 0xea, 0x7c, 0xcf, 0xcc, 0x86, 0x3a, 0x84, 0x91,
- 0xe7, 0x9c, 0x6b, 0xbb, 0x56, 0x88, 0x77, 0xc4, 0x1a, 0x65, 0x22, 0xde,
- 0x22, 0xbb, 0x81, 0x9d, 0x0a, 0x57, 0xb9, 0xea, 0x9b, 0xed, 0x8c, 0x3a,
- 0x3f, 0xe9, 0xde, 0xee, 0x8f, 0x0b, 0x3e, 0xb4, 0x9a, 0xf2, 0xe7, 0xb5,
- 0x6e, 0xf5, 0xfd, 0xf1, 0x0b, 0xa5, 0x3f, 0x6f, 0x5b, 0x9f, 0xe7, 0xf3,
- 0x7f, 0x42, 0x9d, 0x38, 0x78, 0x55, 0x7f, 0xdf, 0x26, 0xac, 0xf8, 0x59,
- 0x2c, 0x8f, 0xab, 0x7b, 0x4c, 0x17, 0xc3, 0xe4, 0x97, 0xf2, 0x9b, 0x12,
- 0xd9, 0x30, 0x30, 0xce, 0x2c, 0x90, 0xb4, 0x43, 0x9f, 0x4f, 0xe3, 0x4f,
- 0xe8, 0xff, 0x7d, 0xea, 0x3c, 0x75, 0x05, 0xbc, 0xf1, 0x54, 0xbc, 0x35,
- 0x1f, 0x27, 0xae, 0x5f, 0xbb, 0xb3, 0x7b, 0x39, 0xbe, 0xf7, 0xbf, 0xf1,
- 0xd2, 0xb1, 0x7f, 0x1d, 0x9f, 0xd1, 0x3e, 0xb8, 0x3a, 0xcb, 0xda, 0xec,
- 0xff, 0x50, 0xf8, 0xdf, 0xec, 0x67, 0x4b, 0xc4, 0x76, 0xf6, 0x91, 0xb2,
- 0xf4, 0x6f, 0x57, 0xb1, 0x26, 0xf2, 0xb7, 0x82, 0x75, 0x3a, 0x96, 0x08,
- 0xec, 0x79, 0xa8, 0xeb, 0x6c, 0xbd, 0x1f, 0xc8, 0x3e, 0x62, 0xea, 0x0e,
- 0xc4, 0xda, 0xff, 0xbd, 0x61, 0x4c, 0x25, 0x13, 0xba, 0xab, 0x34, 0x2d,
- 0xe1, 0xb9, 0x31, 0x89, 0x1c, 0x63, 0xfc, 0x3a, 0x23, 0xc5, 0xb8, 0x27,
- 0xf7, 0xb9, 0xeb, 0x7d, 0x93, 0x2e, 0x63, 0x23, 0xed, 0x0f, 0xcb, 0xd0,
- 0xc9, 0x47, 0x25, 0x3a, 0xc7, 0x77, 0xeb, 0xce, 0x2e, 0xa0, 0x8f, 0xb6,
- 0x48, 0x39, 0xce, 0x18, 0x6e, 0x54, 0x9d, 0x05, 0x9f, 0x1f, 0x5f, 0x90,
- 0x22, 0xb0, 0x42, 0x5e, 0xe9, 0x16, 0xa4, 0xab, 0xbe, 0xc4, 0xf4, 0x76,
- 0xee, 0x29, 0xf8, 0x98, 0xa1, 0x89, 0x72, 0x54, 0xdd, 0xc9, 0x39, 0x1f,
- 0x67, 0x5d, 0xf8, 0xef, 0x73, 0xc4, 0x19, 0xd0, 0x1d, 0x63, 0x12, 0x62,
- 0x3e, 0x3c, 0xb7, 0x86, 0x33, 0xa8, 0x13, 0x86, 0xdc, 0xb8, 0x44, 0x4e,
- 0xf9, 0x73, 0xe7, 0x3f, 0x52, 0x32, 0x16, 0x76, 0x4b, 0xf8, 0x18, 0x9f,
- 0xeb, 0xfd, 0x21, 0x62, 0x77, 0xd8, 0x86, 0xb3, 0x9f, 0x45, 0x7f, 0x7c,
- 0x97, 0xd1, 0xdf, 0xc2, 0x22, 0x5f, 0xf9, 0xc7, 0xfe, 0xcf, 0x04, 0xca,
- 0xfe, 0xff, 0x07, 0x3b, 0x97, 0x22, 0x9a, 0xb0, 0x4e, 0x00, 0x00, 0x00 };
+ 0xcd, 0x7c, 0x0d, 0x70, 0x5b, 0xd7, 0x95, 0xde, 0xc1, 0x03, 0x40, 0x82,
+ 0x10, 0x45, 0x3d, 0x52, 0x30, 0x0d, 0x3b, 0x4c, 0x82, 0x47, 0x3c, 0x92,
+ 0xb0, 0xc9, 0x64, 0x9f, 0x64, 0x46, 0x66, 0x12, 0xac, 0x05, 0x03, 0xa4,
+ 0x4c, 0x27, 0xea, 0x92, 0xb6, 0x19, 0x47, 0x6d, 0x35, 0x09, 0x17, 0x92,
+ 0x12, 0xdb, 0x4d, 0xa7, 0x9a, 0xc6, 0xe9, 0x2a, 0x1b, 0xc7, 0x82, 0x41,
+ 0xca, 0x51, 0x52, 0x8a, 0x60, 0x24, 0x4a, 0xf2, 0x74, 0xb3, 0xbb, 0x0c,
+ 0x48, 0x4a, 0x8e, 0x03, 0x09, 0x96, 0xec, 0x75, 0xdc, 0xad, 0xb3, 0x62,
+ 0x68, 0xad, 0xec, 0x4d, 0xb3, 0xad, 0x9d, 0x49, 0x3a, 0x9a, 0xa9, 0xb7,
+ 0x55, 0x95, 0xa4, 0xf9, 0x99, 0xfe, 0xb8, 0x49, 0xa6, 0x75, 0xbb, 0xf1,
+ 0xbe, 0x7e, 0xdf, 0x7d, 0xf7, 0x11, 0x20, 0xc5, 0x28, 0xde, 0xec, 0x64,
+ 0x66, 0x39, 0x83, 0xb9, 0xef, 0xde, 0x77, 0x7f, 0xce, 0x3d, 0xf7, 0xfc,
+ 0x7c, 0xe7, 0xde, 0xfb, 0x78, 0x87, 0x48, 0x54, 0xf4, 0xdf, 0x46, 0xfc,
+ 0xfa, 0xff, 0xe9, 0x3f, 0xdb, 0xb3, 0xf5, 0xdd, 0xfd, 0xef, 0x66, 0xde,
+ 0x30, 0x42, 0x21, 0xa6, 0x41, 0xfc, 0x62, 0xf8, 0x6d, 0xd5, 0xcf, 0xeb,
+ 0xfd, 0x99, 0xf8, 0x6d, 0x0b, 0x88, 0x8c, 0xff, 0x44, 0x24, 0xb0, 0xe6,
+ 0x5d, 0x64, 0x9d, 0xfa, 0xae, 0xfb, 0x4b, 0x3a, 0xd2, 0x7f, 0x06, 0x7e,
+ 0x89, 0xeb, 0x57, 0x59, 0x19, 0xf7, 0xd7, 0xfd, 0x0b, 0xea, 0xe6, 0x1b,
+ 0xf5, 0x4f, 0x22, 0x46, 0x5a, 0x46, 0xb2, 0xb6, 0x44, 0x82, 0xe9, 0x9f,
+ 0x8f, 0xec, 0xb1, 0x45, 0x32, 0x95, 0xde, 0x44, 0x4e, 0xde, 0x74, 0x0b,
+ 0xb1, 0x90, 0xb0, 0xfc, 0xed, 0xe9, 0x5f, 0x1c, 0xfc, 0xfa, 0xed, 0xd6,
+ 0xeb, 0x73, 0x41, 0x89, 0x98, 0xe9, 0x37, 0xc4, 0xec, 0x96, 0x48, 0x07,
+ 0xda, 0x7c, 0xa9, 0xe7, 0x49, 0x43, 0x5a, 0xfc, 0xbe, 0xcc, 0xf1, 0x60,
+ 0x5a, 0x46, 0xf7, 0x4e, 0x1d, 0x74, 0x0d, 0x5b, 0x0a, 0x37, 0xa7, 0xed,
+ 0x44, 0x51, 0x9a, 0x07, 0x26, 0xfb, 0x6f, 0x17, 0xe4, 0x47, 0xf7, 0x56,
+ 0x22, 0x92, 0xad, 0x16, 0x9a, 0x0d, 0xdb, 0x46, 0x1a, 0x29, 0xbc, 0x2d,
+ 0x2d, 0x91, 0x86, 0xf4, 0x6c, 0xe3, 0x25, 0x9b, 0xe3, 0x0f, 0x60, 0xfc,
+ 0xb7, 0x49, 0xc8, 0x76, 0xdd, 0x49, 0x8c, 0xbf, 0xa3, 0xf2, 0xa6, 0xfb,
+ 0x58, 0xc8, 0x1b, 0xdb, 0x48, 0x1f, 0x08, 0x32, 0x0d, 0xa4, 0x33, 0x23,
+ 0x9d, 0x15, 0x95, 0x6f, 0xf0, 0xf2, 0x83, 0x3a, 0x1f, 0x89, 0x7a, 0xb4,
+ 0x4b, 0x13, 0x68, 0x8f, 0x84, 0xd2, 0xe9, 0x26, 0xf4, 0x11, 0x09, 0xa7,
+ 0x97, 0x7e, 0x7b, 0x51, 0xd5, 0x3b, 0xac, 0xeb, 0x3d, 0x10, 0xf6, 0xda,
+ 0x4d, 0x8e, 0x74, 0x57, 0x98, 0xce, 0x8e, 0x74, 0xa9, 0xf4, 0x4b, 0x23,
+ 0x49, 0x95, 0xce, 0xa9, 0x7a, 0x81, 0xf4, 0xc2, 0x88, 0xad, 0xd2, 0xb4,
+ 0x2e, 0x1f, 0x1e, 0x49, 0xa8, 0x74, 0xa7, 0x4e, 0x47, 0x75, 0x3a, 0xa6,
+ 0xd3, 0x5d, 0x3a, 0xdd, 0xad, 0xd3, 0x71, 0x9d, 0xee, 0xd5, 0xfd, 0x3c,
+ 0xa0, 0xf3, 0x9f, 0xd0, 0xe9, 0x7e, 0x9d, 0x3e, 0xac, 0xd3, 0x03, 0x3a,
+ 0x7d, 0x44, 0xd3, 0x55, 0xd0, 0xe9, 0x94, 0x2e, 0x9f, 0xd1, 0x74, 0x3e,
+ 0x01, 0x7a, 0xfe, 0x71, 0xa3, 0x96, 0x5b, 0xcc, 0x37, 0x21, 0x7b, 0xa6,
+ 0x22, 0x52, 0x2c, 0x05, 0x25, 0xa7, 0xd6, 0xf3, 0xe3, 0x61, 0x89, 0x46,
+ 0x64, 0xa2, 0x1a, 0x91, 0x2b, 0x4a, 0x5c, 0x7f, 0xe4, 0x7e, 0xbd, 0xc7,
+ 0x94, 0xa7, 0xab, 0x31, 0xb9, 0x50, 0x95, 0xc0, 0x68, 0x4f, 0x93, 0x18,
+ 0x47, 0x6f, 0x96, 0x8c, 0x19, 0x90, 0xa0, 0xe2, 0x6b, 0x42, 0xb2, 0x53,
+ 0xed, 0xc8, 0x5b, 0x71, 0x91, 0xc5, 0xb0, 0xb7, 0x8e, 0x11, 0x09, 0x9e,
+ 0xe0, 0xba, 0x3c, 0x37, 0x72, 0x69, 0x36, 0x2e, 0xa1, 0xe9, 0x04, 0xfa,
+ 0x6f, 0x96, 0xf0, 0x09, 0xe9, 0x08, 0x4a, 0x57, 0xfc, 0x63, 0xa8, 0x31,
+ 0x58, 0x09, 0xc9, 0x50, 0x25, 0x80, 0xb5, 0x8a, 0x40, 0x4e, 0x9a, 0xf1,
+ 0x33, 0xf1, 0x8b, 0xe1, 0x17, 0xc7, 0xef, 0xaf, 0xd0, 0x4f, 0x87, 0xe4,
+ 0x2a, 0xec, 0x13, 0xe3, 0x96, 0x30, 0x7e, 0xc9, 0x32, 0xc7, 0x85, 0x34,
+ 0xc5, 0xe5, 0xeb, 0x3d, 0x1e, 0x4d, 0x17, 0xaa, 0x91, 0x40, 0xf6, 0xa4,
+ 0xec, 0xcf, 0x39, 0x92, 0x30, 0xec, 0xa8, 0xe4, 0xcd, 0x40, 0x62, 0x6f,
+ 0xaa, 0x4d, 0x0a, 0x63, 0x78, 0x57, 0x92, 0x8c, 0x81, 0xbe, 0xf3, 0xa6,
+ 0x8c, 0x7b, 0xef, 0x58, 0xf6, 0x7f, 0xa1, 0xaf, 0x96, 0x49, 0xc1, 0xbd,
+ 0x50, 0xfa, 0xd7, 0x78, 0x66, 0x5f, 0x2f, 0x86, 0x3c, 0x9a, 0xdf, 0x40,
+ 0x9e, 0xe5, 0xee, 0x26, 0x2f, 0xcf, 0x67, 0xd6, 0xf5, 0xc7, 0xf4, 0xe7,
+ 0xca, 0xb1, 0x7b, 0x30, 0x5f, 0x8e, 0xbf, 0x32, 0x5f, 0xd0, 0xd1, 0x1c,
+ 0xc8, 0x9d, 0x4c, 0xc8, 0xa1, 0xd2, 0x1d, 0x92, 0x75, 0x5c, 0x77, 0x8f,
+ 0x23, 0x31, 0x43, 0xba, 0xcc, 0x1c, 0xde, 0x96, 0x2b, 0x12, 0xc8, 0x96,
+ 0x7c, 0x7e, 0xb0, 0xdf, 0x10, 0xca, 0xda, 0x51, 0xbf, 0x25, 0x30, 0x78,
+ 0x12, 0xb4, 0xa7, 0xc9, 0x17, 0xc8, 0xac, 0xd3, 0x15, 0xdf, 0x8b, 0xf1,
+ 0xe6, 0x2b, 0x5d, 0xce, 0xb2, 0x98, 0xe8, 0xb3, 0x0d, 0x75, 0xc8, 0x23,
+ 0xf6, 0xc5, 0x3e, 0xd9, 0x5f, 0x33, 0xda, 0xc6, 0xf0, 0x8e, 0x34, 0xb9,
+ 0x6e, 0xd6, 0x31, 0x99, 0x97, 0x39, 0xf0, 0x6d, 0x8e, 0x7c, 0x8b, 0x76,
+ 0xc8, 0xa9, 0x0a, 0xc7, 0x58, 0x8f, 0xee, 0x5b, 0xff, 0x9e, 0xd1, 0x1d,
+ 0x47, 0xff, 0x31, 0xa4, 0x1b, 0x02, 0xd9, 0x63, 0x2e, 0xc6, 0x8f, 0xe3,
+ 0x79, 0xbd, 0x39, 0x5c, 0xd1, 0x32, 0x18, 0x07, 0xed, 0x31, 0x39, 0xa7,
+ 0xe4, 0x70, 0x83, 0x04, 0x21, 0x87, 0x5c, 0xe3, 0xd6, 0x13, 0xef, 0x91,
+ 0x7c, 0xcc, 0x4a, 0xd0, 0x76, 0x76, 0x6e, 0x6d, 0xc2, 0x1c, 0xb5, 0x15,
+ 0x9c, 0x8e, 0x41, 0x0e, 0x97, 0x5b, 0x0d, 0x94, 0x18, 0x62, 0x99, 0xff,
+ 0x48, 0x0a, 0x92, 0x5b, 0xf8, 0xbd, 0x80, 0x44, 0x0d, 0xd4, 0xbb, 0x25,
+ 0xe0, 0xf1, 0x80, 0xfc, 0xc9, 0x80, 0x3f, 0x01, 0xd1, 0xf6, 0x41, 0x3a,
+ 0x2b, 0x7c, 0xdf, 0x9b, 0x30, 0xd4, 0xbb, 0x41, 0xbc, 0x0b, 0x49, 0x72,
+ 0xab, 0xff, 0x7e, 0x10, 0xef, 0x6f, 0x96, 0x71, 0x13, 0xb4, 0x94, 0x9e,
+ 0x37, 0xb2, 0xa0, 0xf1, 0xce, 0x90, 0x9a, 0x2b, 0xea, 0x8e, 0xd7, 0xf5,
+ 0x33, 0x8e, 0x7a, 0xff, 0x0a, 0x63, 0x81, 0xde, 0x52, 0x02, 0xb4, 0xb4,
+ 0x83, 0x16, 0xd2, 0x58, 0x30, 0xb2, 0xd5, 0x10, 0xf2, 0x93, 0x46, 0xee,
+ 0xf4, 0x61, 0x3c, 0x8b, 0x69, 0xa4, 0x9f, 0x67, 0x8a, 0xf6, 0xbb, 0xeb,
+ 0xda, 0xef, 0x46, 0x7b, 0x8e, 0xc1, 0xf6, 0x9e, 0xfc, 0x17, 0x94, 0x2c,
+ 0x26, 0xae, 0xc3, 0x8f, 0xe0, 0xaf, 0xc1, 0x8f, 0x7f, 0xa3, 0xf9, 0xf1,
+ 0xd7, 0xf2, 0x9b, 0xe7, 0xc7, 0x7f, 0xfa, 0x0d, 0xf1, 0x43, 0x24, 0x7f,
+ 0x8c, 0xcf, 0x21, 0x29, 0x28, 0xbb, 0x45, 0xbd, 0xa5, 0xbc, 0xd3, 0x66,
+ 0x91, 0x4f, 0x94, 0x63, 0xe8, 0x40, 0x35, 0x84, 0xf4, 0x49, 0xa4, 0x1b,
+ 0x02, 0xa3, 0xc7, 0xae, 0x62, 0xfd, 0x5d, 0x31, 0xb7, 0xfa, 0x7e, 0xa3,
+ 0x10, 0x37, 0xa5, 0x43, 0xcc, 0x77, 0xc3, 0x69, 0xb7, 0x5b, 0x66, 0x5e,
+ 0x7e, 0x80, 0xf7, 0x6f, 0x06, 0x7c, 0xff, 0x9e, 0x9d, 0x6a, 0x7a, 0x23,
+ 0xa3, 0x9e, 0xc2, 0xe4, 0x67, 0xc6, 0x48, 0x87, 0x02, 0xb9, 0x52, 0x62,
+ 0xdc, 0x48, 0xc7, 0x60, 0xa7, 0x98, 0x1f, 0x08, 0x78, 0x34, 0xf7, 0xa3,
+ 0xae, 0x6f, 0xb3, 0x7c, 0xda, 0xfb, 0x41, 0xfb, 0x5a, 0xdb, 0x95, 0x01,
+ 0x2d, 0xa4, 0x81, 0x74, 0x15, 0x82, 0x9a, 0xf7, 0xe8, 0xe7, 0x80, 0xea,
+ 0x27, 0x98, 0x1e, 0x10, 0xfa, 0xd0, 0xfc, 0x14, 0xf5, 0x80, 0xed, 0xd8,
+ 0x97, 0x67, 0x93, 0xf3, 0x15, 0xbf, 0x8f, 0x42, 0x7d, 0x1f, 0xa0, 0x47,
+ 0x36, 0x19, 0x76, 0x18, 0x6b, 0xcf, 0xae, 0x0e, 0xe3, 0xdd, 0x97, 0x24,
+ 0x7b, 0xfa, 0x76, 0x03, 0x73, 0x40, 0xbf, 0xe4, 0xd1, 0x28, 0x6c, 0x36,
+ 0xf5, 0x2c, 0x22, 0xb9, 0x18, 0xcb, 0x3e, 0xa2, 0xc7, 0x0d, 0x49, 0x46,
+ 0xe5, 0xbf, 0xd2, 0x52, 0xa3, 0xe3, 0x79, 0x3d, 0x9f, 0x34, 0xe6, 0x43,
+ 0x1a, 0xfc, 0xb9, 0xa4, 0xeb, 0xe6, 0xe2, 0xf3, 0x9a, 0xbc, 0x30, 0x61,
+ 0xe3, 0x23, 0xda, 0x87, 0xb0, 0xdd, 0x64, 0xdd, 0xda, 0x4d, 0xa2, 0x0d,
+ 0x79, 0x8f, 0x3a, 0x6b, 0xfc, 0x0a, 0x7d, 0xca, 0x20, 0xfa, 0x29, 0xce,
+ 0x1a, 0x92, 0x73, 0xe0, 0xab, 0x9d, 0xb7, 0x69, 0x79, 0xad, 0xc9, 0x52,
+ 0x78, 0x5d, 0x59, 0x3a, 0x68, 0x78, 0xf6, 0x1a, 0xbe, 0x05, 0xfe, 0x67,
+ 0x62, 0xd6, 0x4a, 0xf9, 0xb2, 0x54, 0x9c, 0x7a, 0x2b, 0xb2, 0xe4, 0xb7,
+ 0x8f, 0x40, 0x76, 0xfd, 0x31, 0xd6, 0xd2, 0xec, 0xd7, 0x01, 0x8d, 0xa5,
+ 0xac, 0xc6, 0x28, 0x1c, 0xc7, 0xf3, 0x0d, 0x73, 0xab, 0x7c, 0xc3, 0x61,
+ 0xb4, 0x95, 0x40, 0xae, 0xa7, 0x59, 0xf6, 0xcd, 0xfa, 0x7d, 0x1c, 0x56,
+ 0x32, 0xbb, 0x77, 0xca, 0x32, 0x87, 0x82, 0x92, 0x19, 0x9a, 0x19, 0x90,
+ 0xc1, 0x6a, 0x07, 0xd6, 0xf4, 0x0d, 0x17, 0xbe, 0xf3, 0xdd, 0x61, 0xb1,
+ 0x61, 0x17, 0x31, 0xe7, 0x7e, 0xf0, 0xb8, 0x1a, 0x16, 0x23, 0xed, 0x20,
+ 0xad, 0xc7, 0x58, 0xa1, 0xd0, 0xd0, 0xaa, 0x7c, 0x03, 0xea, 0xa0, 0xef,
+ 0xfe, 0xb5, 0xf5, 0x20, 0x9f, 0xe0, 0x6d, 0xd6, 0x79, 0xd3, 0x85, 0x1f,
+ 0xd6, 0x3e, 0x8b, 0xa5, 0xb4, 0x13, 0xbe, 0x8d, 0xf8, 0x10, 0xf4, 0x5b,
+ 0xe9, 0x42, 0xc1, 0x48, 0xef, 0x47, 0x1f, 0xa2, 0xe4, 0xb4, 0x58, 0x7d,
+ 0xda, 0xd7, 0x7b, 0x55, 0xbe, 0xa3, 0x9f, 0xb2, 0x37, 0x07, 0x4c, 0xc0,
+ 0x39, 0x2d, 0x28, 0x5d, 0xcf, 0x99, 0x31, 0x99, 0x2c, 0x29, 0x4c, 0x23,
+ 0xc9, 0xca, 0x1f, 0x49, 0xee, 0xb4, 0xc8, 0x37, 0xa7, 0x58, 0xef, 0x05,
+ 0x5d, 0xef, 0x79, 0xd4, 0x4b, 0x26, 0x06, 0x03, 0x16, 0xfc, 0x80, 0x05,
+ 0x35, 0xe9, 0x4d, 0x20, 0x35, 0x87, 0xf1, 0x1b, 0xa4, 0x93, 0x41, 0x3d,
+ 0x0f, 0x03, 0x3d, 0x0f, 0x7e, 0x88, 0xdc, 0x53, 0x6a, 0x84, 0x3d, 0xf9,
+ 0x2f, 0xa0, 0x35, 0x26, 0x5f, 0xc0, 0x3c, 0x2e, 0x4d, 0x11, 0x67, 0xbd,
+ 0x20, 0x8b, 0x53, 0xc4, 0x5d, 0xcf, 0xcb, 0xe4, 0x54, 0xd2, 0xf9, 0x26,
+ 0xf8, 0x7c, 0x4a, 0x38, 0x97, 0x5e, 0x07, 0x29, 0x30, 0xa0, 0x95, 0x78,
+ 0x1c, 0xf6, 0xac, 0x67, 0xab, 0xd7, 0x5f, 0x97, 0xee, 0xcf, 0xae, 0x58,
+ 0x72, 0xc5, 0xa4, 0x7d, 0xba, 0x56, 0xc7, 0xb3, 0x5a, 0xc7, 0x47, 0x9d,
+ 0x0e, 0x31, 0xa0, 0xd7, 0x99, 0xb1, 0x02, 0xbc, 0x1f, 0xf5, 0xfa, 0x7f,
+ 0x1b, 0x35, 0xfc, 0x33, 0x00, 0xac, 0x6a, 0x29, 0x7f, 0xf7, 0xb7, 0xd3,
+ 0xf1, 0x7a, 0xdd, 0xe6, 0xf8, 0x2d, 0x68, 0x13, 0x42, 0x7a, 0x7d, 0xbd,
+ 0x46, 0x1f, 0x75, 0x6d, 0x07, 0xa8, 0x17, 0x68, 0xf3, 0x07, 0xe0, 0x05,
+ 0xf9, 0xff, 0x56, 0xf4, 0xb9, 0x37, 0xf8, 0x96, 0xf4, 0x79, 0xec, 0x7a,
+ 0xfa, 0x5c, 0xaf, 0xcb, 0x67, 0xc9, 0x0b, 0x8c, 0x2d, 0x33, 0x9e, 0x6c,
+ 0x75, 0x81, 0xd7, 0x09, 0xc8, 0x29, 0x68, 0x28, 0xfd, 0x8d, 0x9b, 0x09,
+ 0x79, 0x78, 0xce, 0x93, 0x27, 0xd6, 0xf3, 0xeb, 0x78, 0xb6, 0x77, 0xb0,
+ 0x7a, 0x45, 0xd9, 0xd9, 0x73, 0xca, 0xce, 0x5a, 0x87, 0x0b, 0x42, 0x79,
+ 0xbb, 0x2d, 0x48, 0xbe, 0x3f, 0xed, 0x7c, 0x16, 0x34, 0x5a, 0x89, 0x84,
+ 0xd1, 0x55, 0x30, 0x8c, 0xcf, 0xca, 0xfe, 0xf9, 0x87, 0x65, 0x7f, 0x89,
+ 0x7d, 0xa4, 0xf1, 0xde, 0x46, 0x59, 0x13, 0x6c, 0x2d, 0x6d, 0xfa, 0x1b,
+ 0x01, 0x6f, 0x2c, 0x03, 0xfe, 0x6b, 0x29, 0x70, 0x4f, 0xf5, 0x62, 0x20,
+ 0x3b, 0x4f, 0xdd, 0x45, 0x79, 0xb5, 0xde, 0xe6, 0xfb, 0xf6, 0xbe, 0x66,
+ 0xff, 0x06, 0x4b, 0x93, 0xc4, 0x80, 0x46, 0xd6, 0xe1, 0x9a, 0x51, 0x37,
+ 0x2f, 0x98, 0xde, 0x9c, 0x3f, 0x09, 0x3e, 0x51, 0xaf, 0xc9, 0x37, 0xf8,
+ 0xc0, 0x10, 0x75, 0x96, 0xcf, 0xe2, 0x06, 0xd3, 0xd4, 0x3b, 0x09, 0x05,
+ 0x41, 0x46, 0x2e, 0xc6, 0x3a, 0x77, 0x80, 0xce, 0xb5, 0x3a, 0xcd, 0x75,
+ 0x14, 0x6d, 0x43, 0x58, 0x36, 0x80, 0xe7, 0x4e, 0x19, 0x9f, 0xcf, 0x60,
+ 0xcc, 0x3b, 0x75, 0xdf, 0xab, 0x7c, 0x0c, 0xfa, 0x48, 0xe8, 0xf5, 0xd8,
+ 0xe0, 0xdb, 0x41, 0x94, 0x39, 0xba, 0xac, 0xa1, 0xae, 0xcc, 0x5f, 0xb7,
+ 0x8f, 0x62, 0x7c, 0xfa, 0x8a, 0x61, 0x8d, 0x7f, 0x5c, 0x37, 0xc7, 0xf5,
+ 0xee, 0xfb, 0x87, 0x42, 0xdd, 0xb8, 0x50, 0x2a, 0x98, 0x41, 0x25, 0xa3,
+ 0x2f, 0xfc, 0x4e, 0x4d, 0x46, 0x81, 0x97, 0x55, 0x2f, 0xe4, 0x31, 0x69,
+ 0x69, 0x06, 0x4f, 0x07, 0x41, 0x2b, 0x78, 0xd7, 0x1e, 0x00, 0xff, 0x9a,
+ 0x25, 0x5f, 0x4d, 0xeb, 0x77, 0x2c, 0x0f, 0xc9, 0x68, 0xcc, 0xf7, 0x47,
+ 0xb7, 0x99, 0x1e, 0xe6, 0x45, 0x9d, 0xd2, 0x8f, 0x83, 0x9e, 0x0e, 0x98,
+ 0x92, 0x3f, 0x39, 0x08, 0x59, 0x23, 0x26, 0x6b, 0x80, 0xac, 0xc5, 0x94,
+ 0xad, 0x37, 0x6c, 0xd6, 0xc7, 0xbb, 0xd3, 0xbf, 0x17, 0xf4, 0xda, 0xb0,
+ 0x9e, 0xdf, 0xc6, 0x1f, 0xbb, 0x6d, 0xa5, 0xed, 0xa8, 0x63, 0x48, 0x50,
+ 0x8d, 0x8f, 0xb2, 0xd3, 0xab, 0xc7, 0x37, 0xda, 0xfd, 0xf1, 0x1f, 0xd1,
+ 0x7d, 0xb5, 0xd5, 0xf5, 0x15, 0xbb, 0xce, 0xf8, 0x78, 0x77, 0xfa, 0xa3,
+ 0x9b, 0xbd, 0x36, 0xb1, 0xba, 0x36, 0xed, 0x6b, 0xda, 0xb0, 0xbe, 0x3f,
+ 0x06, 0xde, 0x9d, 0xbe, 0xab, 0xd9, 0x6b, 0xc3, 0x7a, 0x0d, 0xf0, 0x6d,
+ 0x7c, 0x47, 0xd9, 0xdf, 0x5f, 0x27, 0xfb, 0xfb, 0x21, 0xfb, 0xbe, 0x4c,
+ 0xad, 0xc5, 0xc9, 0x7e, 0xbc, 0xc3, 0x38, 0x87, 0xd8, 0xaa, 0x16, 0xd7,
+ 0x84, 0x4e, 0x34, 0x03, 0xb7, 0xb4, 0x30, 0x96, 0xd1, 0xb8, 0x98, 0xb1,
+ 0x0d, 0x71, 0xb0, 0xd8, 0x21, 0xe9, 0x82, 0x8d, 0xea, 0x8a, 0xef, 0xa3,
+ 0xc2, 0x55, 0x62, 0x0a, 0x2f, 0x67, 0xf4, 0x18, 0x8c, 0x6b, 0xc8, 0x77,
+ 0xe6, 0x73, 0x2b, 0x71, 0x4e, 0x07, 0xe2, 0x20, 0xe2, 0x5d, 0xe2, 0x25,
+ 0x9f, 0x7e, 0x9f, 0x9e, 0x03, 0x46, 0x4d, 0x27, 0x32, 0xc6, 0x60, 0x75,
+ 0xd0, 0xf0, 0x74, 0x82, 0xef, 0x0f, 0x68, 0x9f, 0xb6, 0x96, 0xde, 0xb7,
+ 0xaf, 0xa1, 0x97, 0xb8, 0x2a, 0x21, 0x13, 0x90, 0x91, 0xd0, 0x09, 0xda,
+ 0xd8, 0xe7, 0x46, 0x16, 0x67, 0x89, 0x1f, 0xfa, 0xc0, 0x17, 0xd2, 0x4b,
+ 0xfe, 0x51, 0x97, 0x5b, 0x60, 0x1f, 0xba, 0x52, 0x65, 0xd4, 0x67, 0x7c,
+ 0x3d, 0xae, 0xe2, 0xb2, 0x66, 0xa4, 0x08, 0x9e, 0x40, 0xeb, 0x38, 0x68,
+ 0x1d, 0xd7, 0x31, 0xd9, 0x3e, 0xd8, 0xef, 0xd0, 0xb4, 0x4f, 0xeb, 0x8d,
+ 0x21, 0x7f, 0x6d, 0x56, 0xd3, 0x5e, 0xef, 0x77, 0x3c, 0xfc, 0x75, 0x4f,
+ 0x0f, 0x65, 0xc6, 0x2a, 0x10, 0xb3, 0x8d, 0x2b, 0xf9, 0x00, 0xf6, 0x33,
+ 0xc4, 0xd3, 0xa5, 0x16, 0xdf, 0xff, 0x72, 0x3e, 0xf4, 0xff, 0xd4, 0x79,
+ 0x7f, 0x0e, 0xcd, 0xd2, 0x79, 0x82, 0x73, 0x58, 0xa1, 0x3f, 0xc6, 0xdd,
+ 0x8d, 0xfd, 0xb0, 0x9b, 0x79, 0x45, 0xeb, 0x4e, 0xd9, 0x5b, 0x7a, 0xa7,
+ 0xa6, 0xbf, 0x19, 0xf4, 0x8f, 0x42, 0xb6, 0x6b, 0x36, 0x23, 0x5f, 0x19,
+ 0x43, 0xde, 0xc3, 0x62, 0xe4, 0x71, 0xbe, 0x42, 0xfb, 0xa1, 0xe7, 0x13,
+ 0xe5, 0x7c, 0xd6, 0xda, 0x96, 0xf5, 0xf8, 0xfa, 0x8e, 0x35, 0x7c, 0x15,
+ 0xcd, 0xd7, 0x88, 0x34, 0x9c, 0x50, 0x71, 0x2d, 0xfa, 0x25, 0xaf, 0xe9,
+ 0xbf, 0x9e, 0x1b, 0x99, 0x9c, 0x95, 0xbe, 0xb0, 0x90, 0xbe, 0x38, 0xcb,
+ 0xfa, 0x1b, 0xa4, 0xcb, 0xb9, 0x88, 0x79, 0xe7, 0xb1, 0xde, 0xc6, 0xb4,
+ 0x27, 0xdf, 0xe4, 0x6f, 0xbe, 0x12, 0x45, 0x2c, 0xcd, 0xb1, 0xc9, 0x33,
+ 0xd2, 0x6f, 0x2a, 0x7a, 0x56, 0xf8, 0x0d, 0xfa, 0x3e, 0x56, 0x59, 0xcb,
+ 0xdb, 0x7a, 0x3b, 0xe3, 0xc7, 0xec, 0xdf, 0x35, 0x3d, 0xbd, 0x58, 0x2f,
+ 0x66, 0x6f, 0x86, 0x7d, 0x0c, 0xd1, 0x36, 0x82, 0xf7, 0xdc, 0x5f, 0x59,
+ 0x0a, 0x11, 0x83, 0x5f, 0x28, 0x85, 0x95, 0xcd, 0xcb, 0x3a, 0x2d, 0x5a,
+ 0x3f, 0x6e, 0xd3, 0xbe, 0x23, 0xac, 0x6c, 0xb6, 0x18, 0x26, 0x71, 0x09,
+ 0xca, 0x90, 0x9f, 0x67, 0xde, 0xa7, 0xe3, 0xde, 0x5d, 0x61, 0xfb, 0x0f,
+ 0x43, 0xbe, 0x4d, 0xa8, 0xd1, 0x55, 0x1f, 0x93, 0xbb, 0xc0, 0x72, 0xef,
+ 0x84, 0xdc, 0xde, 0x89, 0xb8, 0x3b, 0x21, 0xf9, 0x14, 0xf5, 0x68, 0x40,
+ 0xc5, 0x26, 0x86, 0xbd, 0x0f, 0x65, 0x4d, 0x28, 0x83, 0x13, 0x33, 0x31,
+ 0x7f, 0xfb, 0x77, 0x65, 0x1c, 0x32, 0x9e, 0x4f, 0xf5, 0x82, 0x0e, 0xda,
+ 0x60, 0x60, 0x1c, 0x3b, 0xc5, 0xb8, 0x1d, 0x7f, 0xfd, 0x61, 0x6f, 0x5e,
+ 0xbb, 0x90, 0x47, 0x0c, 0x9f, 0xea, 0xd4, 0x75, 0x36, 0x08, 0xf7, 0x7f,
+ 0xf2, 0x66, 0x0b, 0xd2, 0xee, 0x35, 0x75, 0xdf, 0x8f, 0xfc, 0x7b, 0x75,
+ 0xff, 0x05, 0xbc, 0xdf, 0x86, 0xdf, 0x20, 0xca, 0x6e, 0x47, 0x99, 0x83,
+ 0xb2, 0xf7, 0x20, 0xff, 0x7e, 0xbd, 0x1f, 0xe0, 0xb7, 0x69, 0x41, 0xfe,
+ 0x31, 0xbc, 0x87, 0xad, 0x30, 0x5f, 0xc6, 0xfb, 0xf7, 0xe2, 0xf7, 0xee,
+ 0x35, 0x75, 0xda, 0xd6, 0xe4, 0x3f, 0xb5, 0xc2, 0x83, 0x0b, 0xa5, 0x9f,
+ 0x69, 0xbb, 0x46, 0x79, 0x66, 0xfe, 0x94, 0x7e, 0xf7, 0xce, 0xd0, 0xea,
+ 0xf2, 0x1d, 0x7e, 0xbe, 0x6e, 0x0d, 0x3b, 0xb1, 0x86, 0x3e, 0xc6, 0x7c,
+ 0xbb, 0xf6, 0x5d, 0x6f, 0xf7, 0xe2, 0xf4, 0x92, 0xdf, 0x8e, 0x7e, 0xed,
+ 0xce, 0x35, 0x63, 0x3c, 0xdf, 0x50, 0xcb, 0x37, 0x07, 0x86, 0x4e, 0xb2,
+ 0xec, 0x72, 0xc3, 0xea, 0x3a, 0x6f, 0xd6, 0xe5, 0x37, 0x06, 0x86, 0x94,
+ 0x8f, 0xbb, 0xab, 0x71, 0x75, 0x9d, 0x64, 0x63, 0x6d, 0x1e, 0x35, 0x5b,
+ 0x18, 0x4a, 0x2f, 0x53, 0x8e, 0xa1, 0x0b, 0xdf, 0x1a, 0xc9, 0x4e, 0xb9,
+ 0xee, 0x84, 0xb3, 0x14, 0x0f, 0x0a, 0x7d, 0x10, 0xb1, 0x2a, 0xcb, 0x5f,
+ 0x46, 0x39, 0xb0, 0x4c, 0x75, 0x54, 0x68, 0x93, 0xd6, 0xc7, 0xa4, 0x09,
+ 0x8d, 0x49, 0x55, 0x36, 0x94, 0x55, 0x18, 0xf2, 0xf9, 0x11, 0x60, 0x1e,
+ 0xfd, 0xfc, 0x02, 0x9e, 0x13, 0xf5, 0xb8, 0x17, 0xfd, 0x2e, 0x8d, 0x64,
+ 0x67, 0xe9, 0xf3, 0x2e, 0x8e, 0xec, 0x99, 0xa5, 0xce, 0x5f, 0x82, 0xce,
+ 0x07, 0x64, 0x52, 0xf9, 0x3f, 0xd2, 0xc1, 0x76, 0x4b, 0x23, 0x9d, 0x0b,
+ 0x4c, 0x97, 0x47, 0xec, 0x85, 0xa0, 0xec, 0x8b, 0x79, 0x6d, 0x99, 0x4f,
+ 0x2c, 0xf8, 0x3a, 0x10, 0x95, 0x70, 0x9a, 0x32, 0x69, 0xa5, 0x80, 0xbd,
+ 0x31, 0x9f, 0x27, 0x47, 0x26, 0x6d, 0xca, 0xe7, 0x87, 0x1a, 0xa4, 0x25,
+ 0x2a, 0x0d, 0xca, 0xde, 0x3c, 0xa5, 0xc7, 0xba, 0x84, 0xb1, 0x36, 0x29,
+ 0x7d, 0xca, 0xda, 0xa1, 0x38, 0xc6, 0x39, 0x68, 0xd8, 0xbd, 0x18, 0x8f,
+ 0x91, 0x72, 0x87, 0x4c, 0x54, 0xa9, 0x37, 0xdb, 0xc2, 0xb5, 0xf8, 0xf8,
+ 0x3c, 0xda, 0xf9, 0x71, 0x19, 0xc7, 0x2b, 0x03, 0x97, 0x41, 0x96, 0xd3,
+ 0x96, 0x99, 0x0d, 0xc2, 0xcf, 0xcf, 0xfa, 0x75, 0x48, 0xd3, 0xd9, 0x91,
+ 0xe4, 0x42, 0x12, 0x7d, 0x75, 0xd0, 0x86, 0xc1, 0x76, 0x05, 0xf1, 0x63,
+ 0xdf, 0x6c, 0x07, 0x5f, 0x34, 0x40, 0x3f, 0x72, 0x1e, 0x7e, 0xa4, 0x43,
+ 0x0e, 0x95, 0x54, 0x1f, 0x09, 0xf6, 0x51, 0xd4, 0x6d, 0x3b, 0x17, 0x1a,
+ 0x10, 0xdb, 0x24, 0xcd, 0x17, 0xa5, 0xd6, 0x76, 0x48, 0xbc, 0x76, 0x5e,
+ 0xdf, 0x3f, 0x77, 0x33, 0xb1, 0x7a, 0xdd, 0x8f, 0x4a, 0x10, 0x74, 0xe4,
+ 0xd0, 0x07, 0xc7, 0xaf, 0xf5, 0xed, 0xf7, 0x97, 0x34, 0x97, 0xaf, 0xe9,
+ 0x6b, 0x93, 0x8e, 0xb9, 0xac, 0x44, 0xee, 0xd7, 0x1a, 0x5b, 0xc5, 0x00,
+ 0x90, 0x07, 0x09, 0xe5, 0x7a, 0x60, 0x17, 0xab, 0x03, 0x5a, 0x46, 0x5e,
+ 0x40, 0x59, 0x7d, 0x6c, 0xe3, 0xc9, 0x57, 0x01, 0x98, 0xae, 0x08, 0x3d,
+ 0x0f, 0xa6, 0x33, 0xad, 0xde, 0x5e, 0xd3, 0xf5, 0xe2, 0x19, 0xc8, 0x0d,
+ 0xfa, 0x2c, 0xae, 0xb4, 0xe5, 0x9c, 0x5e, 0x18, 0xb9, 0x34, 0x15, 0xc7,
+ 0x9c, 0x3c, 0xbf, 0xe0, 0xf1, 0x9a, 0x3e, 0x27, 0x20, 0x8b, 0x76, 0x02,
+ 0x71, 0x33, 0x7d, 0x7c, 0x42, 0x5e, 0xb2, 0x7d, 0xff, 0x43, 0x5f, 0x84,
+ 0xfa, 0x55, 0xd2, 0x46, 0xda, 0xcf, 0x63, 0x6e, 0xae, 0xcc, 0x38, 0x9e,
+ 0x0c, 0xf6, 0xc0, 0x8f, 0x7c, 0x23, 0x64, 0x1d, 0x66, 0x7c, 0x75, 0x25,
+ 0x54, 0x3f, 0x1f, 0x1f, 0x2b, 0x3c, 0xaf, 0xf7, 0x7e, 0xcf, 0x6b, 0x79,
+ 0x59, 0x82, 0xbc, 0xf4, 0x26, 0x4c, 0xe9, 0x06, 0xed, 0xa8, 0xd3, 0xd7,
+ 0x85, 0x38, 0x87, 0x31, 0x74, 0x1c, 0xf4, 0x98, 0xb0, 0x1d, 0x9b, 0x34,
+ 0x66, 0xff, 0x77, 0x61, 0xfa, 0xb6, 0x56, 0xb5, 0xaf, 0x7c, 0x5e, 0xc9,
+ 0xb3, 0x27, 0xdf, 0x41, 0xfd, 0xde, 0x97, 0xa9, 0x20, 0x21, 0x8d, 0xd4,
+ 0xf6, 0x4f, 0x59, 0xff, 0x39, 0x5d, 0xff, 0x59, 0xd4, 0x0f, 0x60, 0x4e,
+ 0xae, 0xbb, 0x57, 0xd1, 0xfb, 0x1c, 0xf8, 0x1e, 0x94, 0xe2, 0x8a, 0xcc,
+ 0x3f, 0x07, 0x99, 0xa7, 0x7c, 0x9f, 0x87, 0xbe, 0x82, 0xf8, 0x7b, 0x29,
+ 0xf7, 0x65, 0x19, 0x3c, 0x9d, 0x6b, 0xe0, 0x5e, 0x67, 0xc2, 0x60, 0xec,
+ 0x49, 0x99, 0xec, 0x90, 0xc7, 0x4b, 0x49, 0x73, 0xa2, 0x6e, 0x2d, 0x77,
+ 0xac, 0x5a, 0x4b, 0xca, 0x80, 0xaa, 0x9f, 0x62, 0xfd, 0x72, 0x9d, 0x0c,
+ 0xcc, 0xcf, 0x5e, 0xaf, 0x1d, 0x65, 0x80, 0xed, 0xd6, 0xc3, 0xe9, 0xdc,
+ 0x1b, 0x74, 0xdd, 0x45, 0x87, 0xfb, 0xb8, 0x8d, 0x52, 0x50, 0x32, 0x16,
+ 0x90, 0xa2, 0x43, 0xbd, 0xca, 0x26, 0x42, 0x62, 0x01, 0x2b, 0x7d, 0x10,
+ 0x74, 0x66, 0x52, 0x61, 0xf1, 0xf6, 0x12, 0xc6, 0xb1, 0x06, 0x4b, 0xa6,
+ 0xeb, 0x5e, 0xb2, 0x45, 0xca, 0x88, 0x3d, 0x17, 0x91, 0x16, 0x2b, 0xd0,
+ 0xd9, 0x68, 0x08, 0x36, 0xc0, 0x97, 0xf1, 0x88, 0xcc, 0xa1, 0xce, 0x3c,
+ 0xde, 0x3d, 0x5e, 0xf1, 0x25, 0xc6, 0x75, 0x0d, 0xf0, 0x68, 0x8f, 0xfd,
+ 0xff, 0xdc, 0x7c, 0xac, 0xbe, 0xae, 0x8f, 0x89, 0x89, 0x65, 0x89, 0x4d,
+ 0x89, 0x29, 0xf9, 0x8e, 0x38, 0xf1, 0x20, 0x68, 0xa1, 0xce, 0xb6, 0x48,
+ 0x24, 0x6d, 0xc5, 0x87, 0xc5, 0xf7, 0xfd, 0x97, 0x21, 0x4b, 0x05, 0xb7,
+ 0xd1, 0xee, 0x90, 0x67, 0x20, 0x37, 0xe7, 0x57, 0x70, 0x4c, 0x02, 0x72,
+ 0x44, 0x3f, 0xea, 0xca, 0x39, 0xc7, 0x4e, 0x7c, 0x0e, 0xe9, 0xb7, 0x9d,
+ 0xdf, 0x22, 0xdf, 0x9e, 0x10, 0xe9, 0x43, 0x2c, 0x04, 0xbb, 0x3e, 0xe3,
+ 0x63, 0xfb, 0x16, 0xc6, 0x64, 0x5a, 0x96, 0xae, 0xa0, 0x4f, 0xcb, 0x34,
+ 0x00, 0x6a, 0xef, 0x42, 0x3d, 0x4f, 0x37, 0xfc, 0xb2, 0x83, 0xa8, 0x4b,
+ 0x1a, 0x18, 0x2f, 0x7f, 0x07, 0x3a, 0xeb, 0xba, 0xf7, 0x39, 0x8b, 0x75,
+ 0xb6, 0xe6, 0x39, 0xac, 0xbf, 0x92, 0xf3, 0xfe, 0x56, 0xe1, 0xfe, 0xaa,
+ 0xf4, 0xb5, 0xa9, 0x78, 0x8e, 0xcf, 0x90, 0xf7, 0x7e, 0x62, 0xa1, 0x84,
+ 0xc2, 0x9a, 0xc4, 0x0d, 0xe7, 0xc1, 0xfb, 0x4f, 0x2a, 0x4c, 0x43, 0xfc,
+ 0x06, 0xfa, 0x4b, 0xc4, 0x14, 0x1e, 0x96, 0xf6, 0x70, 0x1d, 0xb1, 0x45,
+ 0x0a, 0x6b, 0xe3, 0xe3, 0x0b, 0xb6, 0x65, 0x3d, 0xb6, 0xad, 0x5f, 0x3f,
+ 0xd6, 0xd9, 0x14, 0xc8, 0x1d, 0xa3, 0x3c, 0xd3, 0x3f, 0xb6, 0xca, 0xbe,
+ 0x54, 0x23, 0xf8, 0xde, 0xa6, 0xfd, 0xf8, 0xfb, 0x80, 0xd9, 0x80, 0xbd,
+ 0x4d, 0xcb, 0xa9, 0xd9, 0x9e, 0xf7, 0xa0, 0xec, 0x17, 0xe0, 0x3f, 0xcb,
+ 0xf6, 0x37, 0x78, 0x7e, 0xf2, 0x61, 0xe8, 0xf2, 0xdc, 0x26, 0x6f, 0xef,
+ 0x8a, 0xeb, 0xe0, 0xe3, 0x04, 0x1f, 0xf7, 0x99, 0x1a, 0xef, 0x73, 0x6d,
+ 0xbc, 0x7d, 0x2e, 0x43, 0xd5, 0x65, 0xac, 0x55, 0x1f, 0x5b, 0x52, 0x87,
+ 0x5d, 0xf7, 0x9c, 0xe3, 0xe3, 0xc8, 0xed, 0xf0, 0xa1, 0x21, 0xcd, 0xeb,
+ 0x66, 0xf0, 0x9a, 0x18, 0x25, 0x22, 0x89, 0x36, 0x62, 0x8a, 0x07, 0x1b,
+ 0x6a, 0x58, 0xe6, 0x6f, 0xdc, 0xa0, 0xcd, 0x78, 0x8f, 0x38, 0x86, 0xb4,
+ 0x6f, 0xd7, 0x78, 0x86, 0xd8, 0xe6, 0x31, 0x8c, 0x11, 0x94, 0x44, 0x3b,
+ 0xf3, 0x7f, 0xa9, 0xdb, 0xf0, 0xd9, 0x95, 0xee, 0xad, 0xf5, 0xf2, 0x3c,
+ 0x00, 0x3a, 0x39, 0x1f, 0x7f, 0xef, 0xb5, 0x43, 0xd9, 0x93, 0x9a, 0x5c,
+ 0xf8, 0x34, 0xf9, 0xe3, 0x92, 0xb6, 0xb8, 0xb4, 0x81, 0xb6, 0x7b, 0xe0,
+ 0x53, 0xb6, 0xb6, 0xb1, 0x4f, 0x7f, 0xec, 0x7a, 0x9a, 0xea, 0xf1, 0x55,
+ 0x02, 0x63, 0x34, 0xca, 0xd6, 0x76, 0xf2, 0xae, 0x43, 0xf9, 0x96, 0xda,
+ 0x7a, 0xd0, 0xf7, 0x73, 0xec, 0xb5, 0xe5, 0xef, 0xad, 0xa3, 0x6b, 0x2d,
+ 0xe6, 0xdb, 0x86, 0x77, 0xa4, 0xc9, 0x84, 0x5d, 0x72, 0x65, 0x87, 0xe3,
+ 0xe3, 0xbb, 0x7a, 0x3a, 0x88, 0xf1, 0x48, 0x33, 0x69, 0xf0, 0x31, 0x39,
+ 0x7f, 0x5c, 0x1b, 0xd2, 0x93, 0xd6, 0xe7, 0x44, 0xfb, 0xf5, 0xbc, 0x6e,
+ 0xd3, 0x75, 0x92, 0x68, 0xfb, 0xc7, 0x98, 0x03, 0x9f, 0x39, 0x0f, 0x1f,
+ 0x1b, 0x26, 0xbd, 0x7e, 0xa2, 0xeb, 0xc5, 0x00, 0xd4, 0x19, 0x9f, 0x4f,
+ 0x6d, 0x7a, 0x8d, 0xb6, 0xaf, 0x19, 0xd7, 0x72, 0x56, 0xdb, 0x91, 0xf7,
+ 0xd4, 0xcd, 0xaf, 0x4f, 0x0a, 0xf3, 0x94, 0x8b, 0x77, 0x21, 0xf5, 0x63,
+ 0xa3, 0x7e, 0xf8, 0x91, 0x0c, 0x62, 0x21, 0xc6, 0x48, 0xd7, 0xc4, 0x47,
+ 0x3c, 0x47, 0x1c, 0xcb, 0x23, 0x5e, 0x56, 0x7e, 0xc4, 0xf3, 0x91, 0xc8,
+ 0xc3, 0x9e, 0x54, 0xef, 0xa5, 0x8c, 0x8d, 0x8d, 0x57, 0x9c, 0xb1, 0xbd,
+ 0x95, 0xfe, 0x31, 0xc6, 0x11, 0x9e, 0xcc, 0xa1, 0x7e, 0x45, 0xc6, 0x0d,
+ 0xb4, 0xcb, 0xaa, 0x76, 0x6a, 0x1f, 0x68, 0x9d, 0x7e, 0x84, 0xfa, 0x38,
+ 0xee, 0x8d, 0x15, 0x19, 0xcb, 0xc1, 0x06, 0xcd, 0xcf, 0xc0, 0xc7, 0xd9,
+ 0x56, 0x86, 0x72, 0xb9, 0xc7, 0xb1, 0x86, 0x95, 0xec, 0xc5, 0xac, 0x51,
+ 0xae, 0x65, 0x79, 0xe6, 0x1d, 0xb0, 0xa1, 0xae, 0xdc, 0x0d, 0x5b, 0xf8,
+ 0x10, 0x64, 0x55, 0xce, 0xc0, 0x10, 0x9e, 0x81, 0xf1, 0x3a, 0x13, 0x13,
+ 0xe3, 0x78, 0x87, 0x84, 0x8f, 0xc4, 0x25, 0x74, 0x84, 0xb1, 0x58, 0xd2,
+ 0xbc, 0x5b, 0x04, 0x3e, 0xf1, 0xc5, 0xdb, 0x0d, 0xb1, 0x06, 0x32, 0x92,
+ 0x44, 0x3c, 0xd9, 0x6b, 0x96, 0x91, 0x16, 0x25, 0x99, 0x3a, 0x8d, 0xbe,
+ 0xc2, 0x67, 0x50, 0x17, 0xed, 0x9a, 0x16, 0x13, 0xf8, 0xb5, 0x4b, 0x74,
+ 0xd1, 0xd3, 0x95, 0xe8, 0xe2, 0xea, 0x3d, 0x94, 0xc1, 0x95, 0x3d, 0x14,
+ 0xbe, 0x7f, 0x43, 0xef, 0xfd, 0x3c, 0xab, 0xe3, 0x1a, 0xca, 0x08, 0x7d,
+ 0x9b, 0x8a, 0xcd, 0x60, 0xc7, 0x9f, 0x45, 0x2c, 0x6c, 0x4b, 0xae, 0x04,
+ 0xcc, 0x9e, 0x76, 0xe5, 0x29, 0xa7, 0xe0, 0x66, 0xfb, 0x5d, 0xb9, 0xec,
+ 0xd8, 0x85, 0xbc, 0x58, 0x6f, 0xd0, 0xde, 0xfd, 0x4f, 0xe7, 0xfd, 0xb2,
+ 0xab, 0xd5, 0xda, 0x95, 0x09, 0x14, 0xdc, 0x66, 0x3b, 0x2a, 0x37, 0xa5,
+ 0x0f, 0xca, 0x9e, 0x2d, 0x4b, 0x66, 0x50, 0x32, 0x37, 0x01, 0x17, 0xc6,
+ 0xf3, 0xca, 0x56, 0xbd, 0xa6, 0xe2, 0xeb, 0x07, 0xba, 0x0e, 0xca, 0xc6,
+ 0x2d, 0x96, 0x79, 0x35, 0x48, 0xcc, 0x76, 0x10, 0xb1, 0x80, 0x15, 0xcf,
+ 0x05, 0x6d, 0x73, 0xa7, 0x58, 0xc3, 0x9f, 0x16, 0x9e, 0xdb, 0xda, 0xd2,
+ 0x79, 0xc4, 0x8e, 0x7f, 0x22, 0xd0, 0xbd, 0xff, 0x13, 0x8c, 0xef, 0xce,
+ 0x30, 0xef, 0x4a, 0x64, 0x8b, 0x89, 0xe7, 0x98, 0x74, 0x1e, 0x4f, 0x48,
+ 0x12, 0x7c, 0xe9, 0x51, 0x3c, 0xe1, 0xf9, 0x51, 0x5c, 0xba, 0x8f, 0x10,
+ 0x43, 0x29, 0xde, 0xf4, 0x80, 0x37, 0x29, 0xf0, 0x06, 0x31, 0x55, 0xaf,
+ 0x79, 0x15, 0xe9, 0xb2, 0x24, 0x07, 0x7e, 0x00, 0xde, 0xf4, 0x80, 0x37,
+ 0xdd, 0x67, 0x12, 0x68, 0x8f, 0x3e, 0x16, 0x3b, 0x91, 0x46, 0xe5, 0x83,
+ 0x37, 0xb4, 0xe3, 0xd9, 0x96, 0xe4, 0x91, 0x08, 0xc6, 0x08, 0xc8, 0x8e,
+ 0xae, 0x82, 0x0c, 0x6d, 0x41, 0x6c, 0x16, 0x3b, 0x28, 0x17, 0xe1, 0x87,
+ 0x4a, 0x88, 0x11, 0x9e, 0x1a, 0xb0, 0x46, 0x97, 0x60, 0x4b, 0xab, 0xf7,
+ 0xb8, 0xf2, 0xf2, 0x96, 0xbf, 0x70, 0xe3, 0x37, 0x58, 0xbb, 0x24, 0xd0,
+ 0x2f, 0x93, 0x25, 0xe5, 0x1f, 0xe2, 0xd9, 0xa0, 0xc2, 0x65, 0x98, 0x63,
+ 0x01, 0x3e, 0x86, 0xe7, 0xd1, 0x36, 0x6c, 0xfd, 0xa7, 0xe5, 0xa1, 0xb9,
+ 0x09, 0xfc, 0x10, 0x6f, 0x4e, 0xb1, 0xee, 0x7e, 0xc4, 0x73, 0x0f, 0xcb,
+ 0xbe, 0x29, 0x60, 0xc7, 0x34, 0xe8, 0xee, 0xb7, 0x11, 0xcf, 0xcd, 0x37,
+ 0x4a, 0x0b, 0xca, 0xc0, 0xdb, 0xd1, 0xea, 0xda, 0x38, 0x6e, 0x09, 0xeb,
+ 0x30, 0x20, 0x7f, 0x56, 0xed, 0x97, 0xaf, 0x55, 0xfb, 0xe4, 0x4f, 0xe0,
+ 0x5b, 0xce, 0x57, 0x3b, 0xa0, 0x2b, 0x71, 0xac, 0x49, 0x1a, 0xeb, 0xe3,
+ 0xc8, 0x73, 0xd5, 0x94, 0x3c, 0x0b, 0x5e, 0x3d, 0x83, 0xdf, 0x50, 0x29,
+ 0x25, 0x3b, 0x4a, 0x7d, 0x7a, 0x8d, 0xb8, 0x3e, 0x36, 0xe8, 0xb1, 0x31,
+ 0x77, 0xeb, 0xc9, 0x02, 0xf4, 0x6f, 0xbe, 0x6a, 0xbf, 0x5e, 0x96, 0x8f,
+ 0x37, 0x72, 0x8f, 0xf7, 0xd4, 0x8a, 0x7f, 0x29, 0xb8, 0xa6, 0x6d, 0x1d,
+ 0x1e, 0xc7, 0x3a, 0x94, 0xa1, 0xa7, 0xa3, 0x8a, 0xf7, 0x35, 0xdf, 0x53,
+ 0xf6, 0x7c, 0x8f, 0x3f, 0xbf, 0x99, 0xbc, 0x7c, 0x5b, 0xb2, 0x47, 0x27,
+ 0x65, 0xcf, 0x31, 0x57, 0x3e, 0xec, 0xb8, 0x90, 0x63, 0xda, 0xe2, 0x7e,
+ 0xda, 0xf8, 0xc4, 0x78, 0xd0, 0x50, 0xb1, 0x94, 0x87, 0x5b, 0x7a, 0x37,
+ 0x43, 0x67, 0x53, 0x19, 0x63, 0x42, 0x92, 0x47, 0x27, 0xa4, 0xf3, 0x28,
+ 0x64, 0xc1, 0x61, 0x5f, 0x4b, 0xa6, 0x71, 0x8d, 0x3c, 0x70, 0x1c, 0x6b,
+ 0x20, 0x27, 0xb6, 0xf9, 0xba, 0xa4, 0x30, 0xfe, 0x01, 0xe9, 0x42, 0x1b,
+ 0x1b, 0x6d, 0xae, 0xaa, 0xb1, 0x9b, 0x31, 0x76, 0xa3, 0x1c, 0x8a, 0x59,
+ 0x90, 0x35, 0xfa, 0xf0, 0xff, 0x25, 0xd9, 0x32, 0xd3, 0x9f, 0x4a, 0xf6,
+ 0xd4, 0x47, 0x23, 0x12, 0xe5, 0x33, 0x4c, 0xc3, 0x09, 0x96, 0x77, 0x22,
+ 0x65, 0xb9, 0x8d, 0x38, 0xfa, 0xe7, 0x92, 0x3d, 0xcb, 0xb1, 0x5f, 0x47,
+ 0xf9, 0xcb, 0x92, 0x9d, 0xfe, 0x05, 0xf2, 0x17, 0x91, 0xbe, 0x81, 0x74,
+ 0x54, 0x3a, 0xa7, 0x25, 0x90, 0x3d, 0xfb, 0x2d, 0xe4, 0x43, 0x48, 0x0f,
+ 0xa1, 0xde, 0x76, 0xd0, 0xf7, 0xa7, 0xe8, 0x2f, 0x03, 0x9b, 0xf7, 0x3b,
+ 0x9a, 0x7e, 0x96, 0xb3, 0x8c, 0xef, 0x0e, 0xc1, 0xa6, 0xfd, 0x67, 0xd8,
+ 0x34, 0xfd, 0x3c, 0xcf, 0x3c, 0x6d, 0x1b, 0x9f, 0x27, 0xc0, 0x93, 0x03,
+ 0xc8, 0xbb, 0xf2, 0xb0, 0x43, 0x7f, 0xb3, 0x4d, 0xc6, 0xcc, 0x82, 0x1b,
+ 0x05, 0xae, 0x68, 0x86, 0x1e, 0x4c, 0x6c, 0x5d, 0x5f, 0x0f, 0x0e, 0x77,
+ 0x1f, 0x94, 0xa6, 0x2d, 0xfe, 0xfc, 0xfd, 0xf9, 0xda, 0xe6, 0x4f, 0x14,
+ 0x1f, 0xac, 0xc2, 0x27, 0x84, 0xf3, 0xb0, 0xe3, 0x5f, 0x30, 0xba, 0x77,
+ 0x3d, 0x04, 0x3d, 0x30, 0xce, 0x32, 0xef, 0xe9, 0x81, 0x71, 0x16, 0xb6,
+ 0xe1, 0x04, 0x62, 0xc4, 0x13, 0x1d, 0xd2, 0x38, 0x5d, 0xd3, 0x83, 0x86,
+ 0xe9, 0x5f, 0xad, 0x07, 0x8d, 0x67, 0x51, 0xef, 0x2c, 0x79, 0x86, 0x3e,
+ 0x4e, 0x91, 0x67, 0xed, 0x48, 0x3f, 0x8d, 0xb9, 0x92, 0xf6, 0x46, 0xd0,
+ 0xee, 0xe1, 0xa2, 0xdb, 0x21, 0xef, 0x0f, 0x6c, 0x39, 0xa0, 0xcb, 0xff,
+ 0xd2, 0x1d, 0x8e, 0x59, 0x73, 0x12, 0x20, 0x4f, 0x51, 0xb7, 0x4c, 0x1e,
+ 0xde, 0xdc, 0x24, 0xd1, 0xfd, 0xd2, 0x49, 0xfe, 0x95, 0x77, 0x22, 0x5f,
+ 0x70, 0xc3, 0x76, 0xb3, 0xe6, 0x27, 0x70, 0x52, 0x3f, 0xcb, 0x5f, 0x85,
+ 0xcc, 0x10, 0xaf, 0xbe, 0x26, 0x7b, 0xa6, 0x5c, 0x19, 0x73, 0x38, 0xff,
+ 0xef, 0x63, 0xfe, 0x99, 0x2d, 0x31, 0x59, 0x4a, 0xc4, 0xc0, 0x93, 0x79,
+ 0xd8, 0xf6, 0x8b, 0xe2, 0xf1, 0x81, 0xe7, 0x02, 0x3b, 0xc4, 0x8e, 0x0f,
+ 0x89, 0x9d, 0xfa, 0x01, 0xf8, 0x30, 0x04, 0xd9, 0xcf, 0x55, 0x29, 0x3b,
+ 0xaf, 0xc8, 0x20, 0x64, 0xe2, 0x7b, 0x8e, 0x95, 0x02, 0x16, 0x82, 0xbd,
+ 0xa0, 0x5c, 0x50, 0x26, 0x5a, 0x94, 0x4d, 0x3a, 0xe1, 0x58, 0x4f, 0x94,
+ 0xe5, 0x56, 0x39, 0xd1, 0x46, 0xda, 0xf1, 0x6e, 0x5a, 0xf9, 0x8b, 0xd4,
+ 0xb8, 0xd1, 0x05, 0x1b, 0x9d, 0x12, 0xb3, 0xbb, 0xd8, 0xe8, 0xdf, 0x21,
+ 0xc9, 0x1f, 0x0d, 0xc8, 0x44, 0x37, 0xd7, 0x8a, 0xfd, 0x22, 0x5f, 0x2e,
+ 0xb8, 0x21, 0xfb, 0x75, 0xf7, 0x64, 0x7b, 0x42, 0x3e, 0xd9, 0xbd, 0x22,
+ 0x97, 0x73, 0x22, 0x9e, 0x5e, 0x0c, 0xaa, 0xf5, 0xf0, 0xe9, 0xf6, 0xe7,
+ 0xe2, 0xbf, 0xeb, 0xab, 0x7b, 0xc7, 0xb9, 0x50, 0xd6, 0x57, 0x74, 0x27,
+ 0x71, 0x2d, 0xad, 0xaf, 0x41, 0x9e, 0xac, 0x27, 0x8a, 0x72, 0x19, 0xb2,
+ 0x07, 0x1e, 0x9e, 0x65, 0x4a, 0x1e, 0x4e, 0x40, 0xee, 0x5f, 0x95, 0x1d,
+ 0x47, 0xa9, 0x33, 0xaf, 0x62, 0xae, 0xca, 0x96, 0xc0, 0x46, 0xb0, 0x3f,
+ 0x57, 0x26, 0x9d, 0xae, 0xd4, 0x29, 0xb9, 0x35, 0xbe, 0x17, 0x31, 0xe7,
+ 0xb8, 0xe9, 0xca, 0xa2, 0x53, 0x90, 0xc5, 0x01, 0xb4, 0x29, 0x7f, 0x1a,
+ 0xbf, 0x4f, 0xe9, 0xb9, 0x3d, 0x0a, 0xbe, 0x5b, 0x89, 0x39, 0xe3, 0xf7,
+ 0xc1, 0xf7, 0x87, 0x25, 0x39, 0xbd, 0x62, 0x6b, 0x20, 0x77, 0x9e, 0xad,
+ 0x49, 0x9e, 0x35, 0xa5, 0x5c, 0xb2, 0xe5, 0x23, 0xb4, 0x21, 0x25, 0xce,
+ 0x0b, 0x36, 0x86, 0x67, 0xec, 0x25, 0xd8, 0x99, 0x12, 0x6c, 0x0a, 0x6c,
+ 0xc8, 0x9f, 0xa0, 0xfc, 0x59, 0xd4, 0x79, 0x06, 0xf1, 0xd3, 0x79, 0x60,
+ 0xbf, 0x73, 0xc0, 0x14, 0x4f, 0x97, 0x32, 0x3a, 0x96, 0x55, 0xf3, 0x85,
+ 0xcf, 0x52, 0xb1, 0x8f, 0x94, 0xe7, 0xd4, 0x7d, 0x1e, 0xb5, 0xb6, 0x59,
+ 0x67, 0x13, 0x71, 0x16, 0x28, 0x13, 0x99, 0x9b, 0xf3, 0x79, 0x42, 0xdb,
+ 0xc7, 0xf3, 0x19, 0xdf, 0x56, 0x36, 0xaf, 0xb1, 0x95, 0x22, 0x2f, 0x56,
+ 0x3c, 0x3c, 0x49, 0x7c, 0x5c, 0x9c, 0x4a, 0xac, 0x9c, 0x63, 0x16, 0xe1,
+ 0x37, 0x97, 0x11, 0x67, 0x44, 0xd2, 0xdf, 0x94, 0xc8, 0x71, 0xd7, 0xfd,
+ 0x21, 0xfc, 0x66, 0x01, 0x6b, 0x62, 0x04, 0x50, 0xbe, 0xc0, 0x77, 0x94,
+ 0x7b, 0xca, 0x76, 0x80, 0xe7, 0x19, 0xf2, 0x12, 0xca, 0xca, 0x2a, 0xfe,
+ 0xfa, 0x16, 0xe8, 0xd1, 0xf4, 0xa9, 0x32, 0xd6, 0x6b, 0x94, 0xdc, 0x58,
+ 0x0a, 0x31, 0x4e, 0xaf, 0xd9, 0x88, 0xf6, 0x73, 0x0b, 0x6c, 0x63, 0x0d,
+ 0xf0, 0x3a, 0xd5, 0x4b, 0x0b, 0x2c, 0xef, 0x90, 0x8b, 0x88, 0x45, 0x49,
+ 0x43, 0x79, 0x36, 0x2d, 0xde, 0xde, 0x31, 0xed, 0x15, 0x69, 0x45, 0x1e,
+ 0xfc, 0xca, 0x96, 0xe8, 0x67, 0x43, 0x52, 0x88, 0x93, 0xd7, 0x71, 0x59,
+ 0x9e, 0xfa, 0x4c, 0x13, 0xf7, 0x66, 0xb3, 0x36, 0x9f, 0xfd, 0xbd, 0x0e,
+ 0xf3, 0x2d, 0xec, 0x75, 0x70, 0x7f, 0x23, 0x04, 0x5f, 0xa6, 0xf6, 0x3c,
+ 0x90, 0x26, 0xea, 0xe2, 0x5f, 0xbe, 0xf7, 0xb0, 0x51, 0x0d, 0x3f, 0x12,
+ 0x4f, 0x72, 0xbe, 0x56, 0x61, 0x09, 0xf6, 0xa3, 0x2d, 0x7d, 0x49, 0xee,
+ 0x3d, 0xe1, 0xcd, 0xcf, 0x38, 0x25, 0xbc, 0x4b, 0x23, 0x57, 0x67, 0x2d,
+ 0xe7, 0x0a, 0x30, 0x45, 0x2e, 0xe6, 0x60, 0xbd, 0x46, 0x9b, 0x60, 0xbf,
+ 0x06, 0x32, 0xc6, 0x99, 0x26, 0x0f, 0x9f, 0x85, 0x64, 0x62, 0x8a, 0xe7,
+ 0x9e, 0xb0, 0x6d, 0xc0, 0x90, 0xbf, 0x1b, 0xc2, 0x73, 0x85, 0x79, 0xc4,
+ 0xa4, 0x5e, 0x3c, 0x8b, 0x67, 0xaf, 0x3f, 0xf2, 0xdc, 0x38, 0xc1, 0xb9,
+ 0x07, 0xe4, 0x5e, 0xa0, 0x13, 0x41, 0xff, 0x9d, 0x7a, 0xac, 0xce, 0x53,
+ 0x29, 0xee, 0x65, 0x4b, 0x12, 0xf6, 0x22, 0x8b, 0x58, 0x32, 0x17, 0xeb,
+ 0xd0, 0xd8, 0x9c, 0xef, 0xd6, 0x62, 0x4f, 0x3f, 0xc6, 0x4b, 0xc9, 0xe7,
+ 0x4b, 0x3e, 0xd6, 0x4b, 0xc1, 0xc7, 0x4a, 0x68, 0xb8, 0xc7, 0x95, 0x1f,
+ 0x3a, 0xe4, 0x57, 0x1f, 0xf2, 0x8e, 0x1c, 0xae, 0xfe, 0xb2, 0xf3, 0xcd,
+ 0xfa, 0xbf, 0x66, 0xd0, 0xc8, 0x1f, 0xe8, 0x03, 0x3e, 0x22, 0xed, 0x06,
+ 0xfc, 0x79, 0x11, 0xb8, 0xcb, 0x38, 0xd3, 0xa1, 0xde, 0x19, 0xc0, 0x06,
+ 0xe5, 0x29, 0xd8, 0xc6, 0x33, 0x3c, 0xf3, 0x85, 0x6d, 0x3b, 0x13, 0x96,
+ 0xe2, 0x0c, 0xe5, 0x52, 0xda, 0x0c, 0xac, 0x17, 0xeb, 0x97, 0xa7, 0x3a,
+ 0x90, 0x36, 0x23, 0x4d, 0xa8, 0x7e, 0xca, 0x53, 0xb6, 0x6a, 0x5f, 0x9e,
+ 0x4a, 0xa9, 0x76, 0xe5, 0xa9, 0x3e, 0xa4, 0x8e, 0x34, 0x9c, 0x41, 0xe0,
+ 0x74, 0xa6, 0x5b, 0x26, 0x4e, 0xc2, 0xbf, 0xf4, 0x1b, 0xea, 0xbe, 0xc4,
+ 0x38, 0xfc, 0x4f, 0x08, 0x51, 0xd6, 0x15, 0x73, 0x00, 0x18, 0x6b, 0x1b,
+ 0x30, 0xc8, 0x36, 0xb1, 0x8f, 0x73, 0xfe, 0xb4, 0xbd, 0xcb, 0xdc, 0xff,
+ 0x8a, 0x3f, 0x28, 0x19, 0xd9, 0x37, 0xd3, 0x08, 0x7d, 0x0d, 0x99, 0x45,
+ 0xe9, 0x32, 0x87, 0x90, 0xcf, 0xcf, 0x91, 0x6f, 0xf7, 0xab, 0xd8, 0x2d,
+ 0xeb, 0xc4, 0xa2, 0x12, 0x4d, 0x63, 0x8c, 0xb7, 0xd2, 0xbe, 0x07, 0xf2,
+ 0x67, 0xeb, 0x3e, 0xd2, 0xa0, 0xa7, 0x9e, 0x1f, 0x3c, 0xeb, 0xcd, 0xfc,
+ 0x8a, 0xb3, 0x5e, 0xca, 0x35, 0xf9, 0x7b, 0xbf, 0x2c, 0xdb, 0x69, 0x79,
+ 0xc9, 0x4e, 0xc9, 0x45, 0x7b, 0xab, 0xfc, 0x39, 0xfc, 0xf4, 0x25, 0x7b,
+ 0xba, 0x89, 0x58, 0xa0, 0xac, 0xce, 0xcf, 0xfc, 0xb5, 0xb2, 0xf5, 0x3e,
+ 0xfa, 0x8f, 0x64, 0x71, 0x8a, 0xd8, 0xd9, 0xdd, 0xbe, 0xc7, 0x29, 0xd0,
+ 0x6f, 0x81, 0x06, 0x62, 0xb5, 0x02, 0xfc, 0xdf, 0x41, 0x19, 0x72, 0xe8,
+ 0xf7, 0x94, 0x8f, 0x8a, 0x0f, 0x79, 0xfa, 0xec, 0xe4, 0x61, 0x57, 0x97,
+ 0x67, 0xa0, 0x4f, 0x42, 0xf9, 0xc7, 0xf3, 0x1c, 0xd7, 0xdd, 0x96, 0x2f,
+ 0x94, 0x38, 0xcf, 0xe2, 0xe6, 0xa8, 0x04, 0x65, 0x58, 0xe1, 0x85, 0x16,
+ 0x79, 0x71, 0x61, 0x83, 0x18, 0xf0, 0x50, 0xc6, 0x2d, 0x61, 0x75, 0xd3,
+ 0x84, 0xf1, 0xb7, 0xb4, 0xf2, 0xbe, 0xd8, 0x87, 0xc1, 0x1b, 0xee, 0x05,
+ 0x60, 0x6e, 0xad, 0x9c, 0x89, 0x9f, 0xef, 0x83, 0x7e, 0xf1, 0x39, 0x20,
+ 0x39, 0x3b, 0x86, 0x67, 0xa6, 0xd4, 0x39, 0xee, 0x93, 0x05, 0xc5, 0xc3,
+ 0xdc, 0xe3, 0xea, 0x7d, 0xa3, 0x7d, 0x07, 0x70, 0x1d, 0xe5, 0x15, 0xe9,
+ 0xa2, 0x37, 0x6e, 0x0e, 0x38, 0x2e, 0xdf, 0xd7, 0xa4, 0xce, 0xff, 0x0a,
+ 0xd0, 0x85, 0x71, 0x55, 0xbf, 0x5f, 0x2e, 0x4d, 0xed, 0x8f, 0x7a, 0xfa,
+ 0x31, 0xa0, 0x9f, 0xf9, 0x9e, 0xf1, 0x15, 0xf7, 0x4b, 0x5e, 0x19, 0x99,
+ 0xb4, 0xbf, 0xa1, 0xf5, 0x47, 0x02, 0x77, 0xf7, 0x00, 0x87, 0x1e, 0x69,
+ 0xc0, 0x5c, 0xac, 0x44, 0x22, 0x60, 0xb4, 0x1b, 0xc0, 0xf1, 0x43, 0xca,
+ 0xe7, 0xf6, 0xa8, 0xfd, 0xe8, 0x53, 0xa9, 0x16, 0x29, 0x9b, 0xb6, 0xba,
+ 0x17, 0xb7, 0x64, 0x6e, 0x21, 0xd6, 0xc7, 0xaf, 0x09, 0x65, 0x5d, 0x48,
+ 0x1b, 0x91, 0xbe, 0x4b, 0x8a, 0xc7, 0xa6, 0xf5, 0x78, 0xe1, 0x35, 0xf9,
+ 0x3e, 0x9d, 0x7e, 0x44, 0xc7, 0x53, 0x1c, 0x27, 0x2c, 0xf6, 0x17, 0x9b,
+ 0xa5, 0xeb, 0x88, 0x09, 0x6c, 0x1b, 0x07, 0xd6, 0xed, 0x90, 0xd4, 0x91,
+ 0x84, 0xdc, 0x72, 0xc4, 0xdf, 0x73, 0xfa, 0x0f, 0x23, 0x49, 0xb5, 0xc7,
+ 0xf9, 0xdd, 0x11, 0x7b, 0x8e, 0xe9, 0x6b, 0xfa, 0xfe, 0xde, 0x15, 0x7d,
+ 0xaf, 0xef, 0x47, 0x23, 0x3d, 0x2a, 0xfd, 0x6f, 0x23, 0x29, 0x95, 0xbe,
+ 0x3e, 0x72, 0x4b, 0xc5, 0x8b, 0x8f, 0x8a, 0xf3, 0x29, 0xf9, 0x5c, 0x89,
+ 0xf8, 0xb2, 0x1f, 0xd8, 0xd1, 0x81, 0x9d, 0xe9, 0x83, 0x9d, 0x49, 0xc1,
+ 0xce, 0x0c, 0xd0, 0xce, 0xc0, 0x6e, 0xbf, 0x02, 0xbb, 0xed, 0xc8, 0xf7,
+ 0x20, 0xaf, 0x4f, 0x3b, 0x8d, 0xc0, 0x85, 0xae, 0xeb, 0xcd, 0xd5, 0x7a,
+ 0x62, 0x09, 0xeb, 0x5b, 0x3e, 0x2d, 0x91, 0x56, 0xd8, 0xa0, 0x2d, 0x27,
+ 0x1a, 0x64, 0x3e, 0xe6, 0xba, 0x47, 0x1d, 0x5b, 0xae, 0xa2, 0x7e, 0xd6,
+ 0xa6, 0x1e, 0xbf, 0x14, 0x65, 0x3c, 0x76, 0x75, 0x6a, 0x2b, 0x6c, 0x12,
+ 0xe5, 0x3d, 0x22, 0xe5, 0xb1, 0xb8, 0x2c, 0x20, 0x3e, 0xab, 0xd5, 0x49,
+ 0xe1, 0x99, 0xfa, 0xff, 0x5d, 0xd4, 0x4d, 0xc1, 0x3f, 0x98, 0xb2, 0xd8,
+ 0x93, 0x90, 0x53, 0x3d, 0xd6, 0x40, 0xc2, 0xa0, 0xed, 0x4a, 0xc8, 0x1c,
+ 0x62, 0xfd, 0x72, 0x89, 0xf5, 0x59, 0x0f, 0xfa, 0x59, 0xf2, 0xda, 0x4d,
+ 0x96, 0x7c, 0x3b, 0xd1, 0xcf, 0x7d, 0xc8, 0x50, 0xae, 0xc7, 0xf3, 0x01,
+ 0x86, 0xd1, 0x08, 0x39, 0x70, 0xc0, 0xff, 0x31, 0x94, 0xf7, 0xf3, 0xbe,
+ 0x07, 0xca, 0x88, 0x85, 0x7e, 0x1c, 0x25, 0x46, 0xcc, 0x39, 0x63, 0x28,
+ 0x63, 0x1b, 0x2b, 0x9e, 0x44, 0xf9, 0xa8, 0x24, 0xe3, 0x79, 0x75, 0xf7,
+ 0xac, 0x1d, 0x65, 0xec, 0x23, 0xa8, 0xf7, 0x63, 0xfe, 0x8f, 0x92, 0xa3,
+ 0xa0, 0xed, 0x97, 0xf7, 0xaa, 0xbd, 0x81, 0x8c, 0xe9, 0x40, 0x1f, 0x58,
+ 0x96, 0x34, 0xd9, 0x2e, 0xe7, 0x38, 0xca, 0x16, 0xde, 0x57, 0xe1, 0x19,
+ 0x5e, 0x44, 0xee, 0xad, 0x34, 0x4b, 0xae, 0xd2, 0x70, 0x1d, 0xfb, 0xef,
+ 0xeb, 0xe4, 0x72, 0xdc, 0x14, 0xde, 0x83, 0xf0, 0xf4, 0x3c, 0xb4, 0x95,
+ 0x3a, 0x31, 0xc0, 0x73, 0x03, 0xf8, 0x5b, 0xac, 0x05, 0xfc, 0xef, 0x39,
+ 0xf8, 0xdf, 0xa7, 0x4b, 0x35, 0xfb, 0xe1, 0xf9, 0x5d, 0xda, 0x80, 0x27,
+ 0xb1, 0x66, 0xa3, 0xc0, 0xfd, 0x3b, 0x11, 0x0f, 0x0c, 0x03, 0xfb, 0x0f,
+ 0x62, 0xfd, 0xd2, 0x58, 0xbb, 0x31, 0xde, 0x17, 0xc2, 0x3a, 0x0e, 0xa8,
+ 0x73, 0xe6, 0x19, 0x75, 0xe7, 0xe2, 0x47, 0xca, 0xf7, 0x3e, 0x5e, 0x32,
+ 0xe0, 0x1f, 0x0a, 0xee, 0x66, 0xdb, 0x02, 0xfe, 0x5b, 0xd1, 0xe7, 0x81,
+ 0x17, 0x61, 0x57, 0x7e, 0x06, 0xba, 0xce, 0xcf, 0xd0, 0x9f, 0xa3, 0x8e,
+ 0x87, 0xb7, 0x1d, 0xee, 0x75, 0x41, 0x9f, 0x0f, 0x2f, 0xcb, 0x12, 0x70,
+ 0x47, 0x86, 0x72, 0x8c, 0xf8, 0xc1, 0x7a, 0x7a, 0x4e, 0xba, 0x69, 0x03,
+ 0xe7, 0xa8, 0x2b, 0xfd, 0xd3, 0x71, 0x60, 0x3d, 0x20, 0x79, 0x75, 0xae,
+ 0x8a, 0xe7, 0xb3, 0x1b, 0xc5, 0x20, 0xde, 0x73, 0x6e, 0x40, 0x19, 0xed,
+ 0x86, 0x8f, 0x91, 0x96, 0x06, 0xda, 0x24, 0xb3, 0xa5, 0x4d, 0xd9, 0x0e,
+ 0xcb, 0x79, 0x09, 0xe3, 0xee, 0x90, 0x46, 0x60, 0xb8, 0x02, 0xc6, 0x38,
+ 0x20, 0xff, 0xd5, 0xe1, 0x1e, 0x95, 0x17, 0xfb, 0x81, 0x96, 0x08, 0x78,
+ 0xd6, 0xb4, 0xc7, 0x36, 0x23, 0x3b, 0xaa, 0xec, 0x3f, 0xa2, 0x30, 0x56,
+ 0x4e, 0xd8, 0x3f, 0xfc, 0x04, 0xc6, 0x4c, 0x4e, 0x53, 0xf6, 0x7b, 0xb1,
+ 0x6e, 0xbf, 0x0d, 0x0c, 0x44, 0xae, 0x7e, 0x75, 0x83, 0xa7, 0x2f, 0xa4,
+ 0x7f, 0x89, 0x78, 0x82, 0x67, 0x00, 0x5e, 0x5c, 0xbe, 0x42, 0x5b, 0x3f,
+ 0xe8, 0x9d, 0xdd, 0xe0, 0x9f, 0x25, 0x77, 0x4e, 0x7b, 0xfe, 0xba, 0xf3,
+ 0x2c, 0x5a, 0x1d, 0x95, 0x76, 0x9e, 0x4a, 0x1b, 0x72, 0x8b, 0xdc, 0x19,
+ 0xf2, 0xfa, 0x31, 0x4e, 0x98, 0x90, 0x55, 0xda, 0x81, 0x76, 0xc8, 0x39,
+ 0xf3, 0xb4, 0x29, 0xb4, 0x09, 0x94, 0x05, 0x5b, 0x8a, 0x55, 0xd8, 0x84,
+ 0x96, 0x0e, 0x99, 0x23, 0xcf, 0x4e, 0xd0, 0x4e, 0xfc, 0x48, 0x26, 0xd7,
+ 0xd8, 0xca, 0x41, 0xf1, 0xe3, 0xda, 0x66, 0x09, 0xa7, 0x6d, 0xf3, 0x3e,
+ 0x35, 0x47, 0xcf, 0x5e, 0xee, 0x23, 0xfe, 0x9c, 0xc9, 0x58, 0x6d, 0xa2,
+ 0xb1, 0xa7, 0xc2, 0x4f, 0xdf, 0xc7, 0x5c, 0xd9, 0x87, 0xe2, 0xd3, 0xc0,
+ 0xa0, 0x17, 0x0b, 0xa8, 0x3d, 0x3f, 0xe0, 0xe0, 0xf8, 0xcf, 0x60, 0x6b,
+ 0x73, 0xc4, 0x25, 0xe0, 0x73, 0xe7, 0x51, 0xca, 0xd1, 0x66, 0xda, 0x32,
+ 0xe0, 0xbc, 0x14, 0xed, 0xb5, 0x2c, 0x4c, 0x03, 0x73, 0x19, 0x77, 0x48,
+ 0x9e, 0xf2, 0xca, 0xbb, 0x0a, 0x0b, 0x86, 0x4c, 0xce, 0xb6, 0x48, 0xd7,
+ 0x09, 0xee, 0xaf, 0x9e, 0x8a, 0x4a, 0x0b, 0xf7, 0x58, 0xe9, 0x83, 0xfa,
+ 0x25, 0x87, 0xf2, 0xce, 0x13, 0x41, 0xb5, 0x1f, 0x36, 0x67, 0x90, 0x47,
+ 0x7d, 0xb0, 0x07, 0x56, 0x6a, 0xc9, 0xd8, 0xd6, 0xe4, 0x61, 0x48, 0xc8,
+ 0x52, 0x09, 0x32, 0x56, 0x82, 0x8c, 0x95, 0x20, 0x63, 0x25, 0xc8, 0x18,
+ 0xb0, 0xdf, 0x79, 0xe8, 0xdf, 0xb9, 0xd2, 0x80, 0xf6, 0xeb, 0xbb, 0x94,
+ 0x5f, 0x3f, 0x54, 0x7a, 0xc5, 0x65, 0xfa, 0xac, 0x8a, 0x4d, 0xfb, 0x20,
+ 0x83, 0x8c, 0x45, 0xfd, 0x18, 0xf5, 0x15, 0x79, 0x72, 0xe6, 0x55, 0x39,
+ 0x35, 0x53, 0xc3, 0x81, 0x13, 0x25, 0x57, 0x5e, 0x72, 0x10, 0x7f, 0xce,
+ 0x13, 0x53, 0x65, 0x5a, 0x1b, 0x15, 0xb6, 0x3a, 0x28, 0x79, 0x85, 0x93,
+ 0x95, 0x1f, 0x01, 0xbe, 0x52, 0xb8, 0x90, 0xba, 0x29, 0x6d, 0x5b, 0x2e,
+ 0xcb, 0x39, 0xf8, 0xf1, 0x85, 0xea, 0x6b, 0xf2, 0x8c, 0xc2, 0xe3, 0xe4,
+ 0xc3, 0x3b, 0xe5, 0xa7, 0xa6, 0x77, 0x9e, 0x7f, 0x0a, 0x58, 0x63, 0xa1,
+ 0x87, 0xb6, 0x23, 0x04, 0x5f, 0x60, 0x15, 0x3a, 0xa1, 0xd7, 0xfb, 0x8d,
+ 0x1b, 0x81, 0x69, 0xf8, 0x7e, 0xa3, 0xbc, 0x38, 0x53, 0xa8, 0x93, 0x09,
+ 0xda, 0x07, 0xeb, 0xb0, 0x18, 0xf4, 0x53, 0xf4, 0x9b, 0x9c, 0x2f, 0xfd,
+ 0xd4, 0x4f, 0x37, 0xf0, 0x0e, 0x57, 0xf9, 0x58, 0x6c, 0x03, 0xf7, 0x1b,
+ 0x63, 0x36, 0x79, 0x7a, 0x59, 0xf6, 0x57, 0x58, 0xf6, 0x2a, 0xd6, 0x87,
+ 0xe9, 0x0f, 0xdc, 0x7b, 0x63, 0x1c, 0x8f, 0xfd, 0x02, 0x37, 0xb5, 0x63,
+ 0xae, 0xa5, 0x8f, 0x68, 0xcc, 0xdd, 0xa7, 0x70, 0xf4, 0xb5, 0x78, 0x99,
+ 0x7c, 0x72, 0xc0, 0xa7, 0xcb, 0x6a, 0x3f, 0x70, 0x9d, 0x7d, 0xe2, 0x27,
+ 0xa0, 0x57, 0x85, 0x2b, 0xc2, 0x3d, 0x4b, 0xee, 0xe7, 0x72, 0xaf, 0xb8,
+ 0xde, 0x62, 0xa8, 0x7b, 0x03, 0x72, 0x0f, 0xec, 0xcb, 0xbd, 0xb0, 0x2f,
+ 0xf7, 0x5d, 0x73, 0x07, 0xda, 0x3f, 0x03, 0xe8, 0x2a, 0x04, 0x8d, 0x0e,
+ 0x19, 0xad, 0xd4, 0xb7, 0xe5, 0x3e, 0xee, 0x7a, 0xfb, 0xb6, 0xdc, 0xd3,
+ 0x4d, 0xad, 0xd9, 0x0b, 0xa4, 0x6c, 0xb8, 0x72, 0xc9, 0xe1, 0xbe, 0x9b,
+ 0x7f, 0x6f, 0x7e, 0x3d, 0xfc, 0x15, 0x68, 0xf6, 0xf7, 0x9c, 0x43, 0xe9,
+ 0x2b, 0xc2, 0xfb, 0xf3, 0xc5, 0x29, 0xe2, 0x81, 0x98, 0xba, 0x17, 0x63,
+ 0xa8, 0x7d, 0x3e, 0xaf, 0x6d, 0x71, 0x4a, 0x9d, 0x31, 0x15, 0xb8, 0x77,
+ 0x6d, 0x6e, 0xb5, 0xcc, 0xd1, 0xa0, 0x77, 0x1f, 0x93, 0xba, 0xec, 0xd9,
+ 0x32, 0xc8, 0x62, 0xb5, 0x76, 0xcf, 0x71, 0x50, 0xd9, 0x8b, 0x2b, 0xd0,
+ 0x01, 0xae, 0x17, 0xe2, 0x05, 0xe8, 0xc9, 0x04, 0xec, 0x53, 0x5e, 0xf5,
+ 0x17, 0xa1, 0x5c, 0x64, 0xb2, 0x41, 0x43, 0xc2, 0xc7, 0x19, 0x0b, 0x79,
+ 0x7b, 0x2d, 0xb9, 0xa0, 0xa5, 0xec, 0x37, 0x68, 0x07, 0x3e, 0xa3, 0x7e,
+ 0x26, 0xc6, 0x1b, 0xd3, 0x0d, 0xf0, 0xab, 0x58, 0xbf, 0x2a, 0xf7, 0x04,
+ 0xa0, 0xbb, 0x8b, 0xdf, 0x91, 0x7d, 0xb3, 0xdd, 0xcd, 0x9e, 0xfc, 0x73,
+ 0x1f, 0x99, 0xf3, 0xf3, 0x69, 0x58, 0xdd, 0xb7, 0x71, 0x5c, 0x22, 0x51,
+ 0xf8, 0xb4, 0x0f, 0x20, 0xce, 0xd8, 0x01, 0x59, 0x59, 0x8a, 0xb1, 0x5f,
+ 0x4f, 0x67, 0x26, 0x4b, 0xec, 0xfb, 0x3b, 0x32, 0x34, 0x5b, 0x6a, 0xa6,
+ 0x2f, 0x59, 0x84, 0x1d, 0x58, 0x36, 0xe9, 0x43, 0xc7, 0xe0, 0xe3, 0xda,
+ 0xe5, 0xfb, 0xb3, 0xf4, 0x8f, 0x49, 0xf3, 0x94, 0xf4, 0xc6, 0x4f, 0x81,
+ 0xa6, 0xcf, 0x3b, 0x21, 0xc6, 0x68, 0xee, 0x20, 0xca, 0xfe, 0x5c, 0x92,
+ 0x66, 0x67, 0x80, 0xcf, 0xbd, 0xe6, 0x17, 0x80, 0x61, 0x33, 0x66, 0xd2,
+ 0xbc, 0x35, 0x40, 0x39, 0x42, 0xcc, 0xbd, 0x58, 0xa3, 0xf3, 0x07, 0xb3,
+ 0x2a, 0x4e, 0x52, 0x76, 0x66, 0xd1, 0xe1, 0x78, 0xa0, 0x5b, 0xd9, 0xac,
+ 0x5b, 0x61, 0x4f, 0x22, 0xfa, 0xfc, 0x0d, 0x6d, 0x88, 0x6d, 0x9c, 0x90,
+ 0xce, 0x3f, 0x2a, 0xd9, 0x93, 0x31, 0xd8, 0x33, 0xf6, 0xe5, 0xc7, 0x0e,
+ 0xf4, 0x91, 0x3e, 0xde, 0xa6, 0xbf, 0xbb, 0x03, 0x7e, 0xef, 0x66, 0x45,
+ 0xcf, 0xb0, 0xd3, 0x27, 0x13, 0xc7, 0x38, 0x76, 0x0f, 0x6c, 0x79, 0x5c,
+ 0xc9, 0x6d, 0xb1, 0xb4, 0x1c, 0x8f, 0xc0, 0x26, 0x47, 0xb6, 0x90, 0x9f,
+ 0xef, 0x93, 0xbb, 0xec, 0x31, 0xb9, 0x1b, 0xb2, 0x33, 0x68, 0x3b, 0x32,
+ 0x84, 0xb5, 0xd8, 0x61, 0xc3, 0xef, 0x28, 0x0c, 0xdd, 0x88, 0xb8, 0x8b,
+ 0x63, 0xb7, 0xeb, 0xfb, 0x17, 0x1e, 0x7e, 0xfc, 0x4a, 0xd5, 0xe3, 0x51,
+ 0x76, 0xf6, 0x49, 0xc5, 0x9b, 0x61, 0x67, 0x9b, 0xf6, 0xb3, 0x2d, 0x92,
+ 0x53, 0xf5, 0xb6, 0x29, 0x7f, 0x5c, 0x5c, 0xb8, 0x1f, 0x29, 0x7c, 0xf3,
+ 0x02, 0xec, 0x0d, 0x30, 0x77, 0xb1, 0xb2, 0x15, 0x79, 0xf8, 0xd0, 0x85,
+ 0x34, 0xd2, 0xf7, 0x21, 0x65, 0xdd, 0x07, 0x9a, 0xbd, 0xbd, 0xdc, 0xb5,
+ 0xf7, 0xb8, 0x24, 0xf0, 0x01, 0x85, 0x4b, 0xaf, 0xa8, 0x3b, 0x80, 0x88,
+ 0xa1, 0x47, 0xb2, 0xb0, 0x2b, 0xcd, 0xc0, 0x40, 0x53, 0xc7, 0xad, 0xd4,
+ 0x50, 0x60, 0xbb, 0x7c, 0x10, 0xb1, 0x7c, 0xd9, 0xe1, 0x5a, 0x6e, 0x95,
+ 0x07, 0xdf, 0x4b, 0x19, 0xd9, 0x2e, 0x7b, 0xde, 0x1b, 0x90, 0x3d, 0x7d,
+ 0x56, 0x86, 0x74, 0xdf, 0xf2, 0x2e, 0x3f, 0x9e, 0xee, 0x1a, 0x4e, 0x06,
+ 0xfa, 0xe5, 0x0b, 0x90, 0xb1, 0x02, 0xe4, 0x6b, 0xa8, 0x4a, 0x9e, 0xd3,
+ 0xde, 0xd3, 0xce, 0xa7, 0x80, 0x95, 0x7d, 0xec, 0x67, 0xcb, 0x54, 0xb5,
+ 0x41, 0x12, 0x37, 0x70, 0x3f, 0x39, 0xe1, 0x9d, 0x71, 0xdc, 0x40, 0x99,
+ 0x40, 0x0c, 0x72, 0x83, 0xa7, 0x9f, 0xea, 0xee, 0xdd, 0x0d, 0x9e, 0x5f,
+ 0x41, 0xfc, 0xeb, 0x12, 0xe7, 0x79, 0x77, 0x0d, 0xbe, 0xa1, 0x6d, 0x69,
+ 0x68, 0xe3, 0x0a, 0xbe, 0x6b, 0x61, 0xfc, 0xf0, 0x87, 0xcd, 0xb5, 0x6f,
+ 0x07, 0xd6, 0xca, 0xa2, 0xbf, 0xef, 0x36, 0x87, 0x39, 0xd3, 0xa7, 0x5b,
+ 0x26, 0x6d, 0x61, 0xab, 0xbd, 0x4b, 0xfe, 0x0c, 0xfe, 0xfd, 0x6b, 0x2b,
+ 0xfe, 0x7d, 0x37, 0xf8, 0xb1, 0x16, 0x03, 0xd8, 0xe6, 0x3d, 0x98, 0xcb,
+ 0x30, 0xd6, 0xf3, 0x6e, 0xfc, 0xee, 0x2a, 0xad, 0xda, 0xc7, 0x9b, 0x29,
+ 0x00, 0x4f, 0x36, 0xd8, 0xec, 0x6f, 0xd5, 0x7e, 0x5e, 0x21, 0x2f, 0x2b,
+ 0x7b, 0x85, 0x03, 0x57, 0x85, 0x7e, 0xef, 0x75, 0x09, 0x77, 0xdb, 0xaf,
+ 0x77, 0x06, 0xec, 0xe7, 0x8d, 0x00, 0xcf, 0xc1, 0x1d, 0x39, 0x5d, 0x25,
+ 0x0e, 0xbb, 0x28, 0xc6, 0x59, 0x62, 0xb0, 0x97, 0xd5, 0x1e, 0x54, 0xb9,
+ 0xf4, 0x2d, 0xa4, 0xa8, 0x0f, 0xfb, 0x18, 0xf4, 0xf6, 0x29, 0x14, 0x56,
+ 0xa1, 0x9d, 0xbd, 0x1b, 0xeb, 0x30, 0x81, 0x5f, 0xe7, 0x96, 0x5b, 0xa1,
+ 0xbf, 0x94, 0x53, 0xee, 0x7d, 0x75, 0x9b, 0x5b, 0x02, 0x7c, 0xb7, 0xde,
+ 0x3e, 0xd8, 0xb7, 0x25, 0x74, 0x14, 0xbe, 0xce, 0xa0, 0x7d, 0xe0, 0x3c,
+ 0xe8, 0x27, 0x4d, 0x99, 0x3f, 0x46, 0x5d, 0x5f, 0xaf, 0xbe, 0x5f, 0xd7,
+ 0x9f, 0x8b, 0xf2, 0x1b, 0x99, 0x3c, 0xf7, 0x38, 0x4b, 0x5c, 0x03, 0x07,
+ 0x6b, 0xe0, 0xca, 0x71, 0xa7, 0x95, 0x36, 0x5d, 0x82, 0xc7, 0x5d, 0x19,
+ 0x54, 0xd8, 0xb5, 0x17, 0x98, 0x6b, 0xa3, 0xc6, 0x0d, 0x31, 0x09, 0x1d,
+ 0xef, 0x90, 0x46, 0xe0, 0xea, 0x86, 0x23, 0xf4, 0x91, 0xc9, 0xc4, 0x20,
+ 0x84, 0x20, 0xa4, 0xee, 0x93, 0x5a, 0x03, 0xdf, 0x97, 0xde, 0xc4, 0xf7,
+ 0x85, 0x78, 0xe9, 0x51, 0xac, 0x9f, 0xe5, 0x5c, 0x5c, 0xa7, 0x7e, 0xb1,
+ 0x56, 0x1f, 0x72, 0xc4, 0xbd, 0x35, 0xb6, 0xe1, 0x5e, 0x5b, 0x72, 0xe0,
+ 0x7b, 0xdc, 0x63, 0x43, 0xac, 0xd9, 0x70, 0xc6, 0xa3, 0xc1, 0x58, 0x6c,
+ 0x93, 0xf2, 0x49, 0xea, 0x28, 0xf7, 0x59, 0x4c, 0x2f, 0x4e, 0x2d, 0x31,
+ 0x5e, 0xe5, 0xfb, 0x84, 0x7e, 0xdf, 0xa9, 0xdf, 0x33, 0x1e, 0x2d, 0xb8,
+ 0x0d, 0xe0, 0xe9, 0x0e, 0xd8, 0xcf, 0xfb, 0xb7, 0xda, 0x0a, 0x37, 0xdc,
+ 0xbf, 0xb2, 0x66, 0x3b, 0xd5, 0xdd, 0xa2, 0x72, 0xe9, 0xa0, 0xd8, 0x5b,
+ 0x96, 0x52, 0x21, 0x19, 0xc5, 0x5a, 0x30, 0x9f, 0x21, 0x3d, 0xa9, 0x43,
+ 0xb2, 0x5f, 0xad, 0x4d, 0xf9, 0x98, 0x75, 0x38, 0x11, 0x98, 0x10, 0xa3,
+ 0xcc, 0xe7, 0x4f, 0x23, 0x3d, 0x04, 0xbc, 0xe3, 0xed, 0x5d, 0x1a, 0xe5,
+ 0xd5, 0xbc, 0x04, 0xc6, 0x30, 0x77, 0xac, 0xda, 0xc7, 0xaa, 0xed, 0x71,
+ 0xf1, 0xfd, 0xa0, 0x7a, 0x9f, 0x5a, 0xb5, 0xcf, 0x95, 0x33, 0x88, 0x65,
+ 0xfc, 0xf7, 0x5c, 0x0b, 0xae, 0x17, 0x7c, 0xf1, 0x31, 0x7f, 0xcf, 0xab,
+ 0x45, 0xaf, 0x0b, 0xd7, 0x67, 0x4a, 0xce, 0x99, 0xd6, 0x30, 0xe5, 0xef,
+ 0xb6, 0xad, 0x37, 0xc9, 0x78, 0x3b, 0xf7, 0xdb, 0xea, 0x69, 0x58, 0xbb,
+ 0x8f, 0x56, 0x3f, 0xfe, 0xda, 0xfd, 0x37, 0x8e, 0xed, 0xed, 0xb1, 0x65,
+ 0x57, 0xed, 0xb1, 0xd5, 0x8f, 0xc7, 0xb1, 0x36, 0x22, 0x7e, 0x2a, 0xb8,
+ 0x31, 0x9b, 0x6b, 0xd4, 0x95, 0x98, 0x65, 0xfe, 0xcb, 0x06, 0xd6, 0x31,
+ 0x06, 0x3f, 0xc2, 0xb5, 0xf4, 0xcf, 0x9e, 0xb9, 0xa6, 0xc9, 0xc4, 0x21,
+ 0x6f, 0x3d, 0x07, 0xbc, 0x75, 0xf7, 0xd6, 0xff, 0xe2, 0xca, 0x3a, 0xd2,
+ 0x3f, 0x70, 0x1d, 0xdb, 0x45, 0x60, 0x67, 0x8d, 0x23, 0x5c, 0x43, 0xa6,
+ 0x5c, 0x43, 0xbe, 0xe3, 0x1a, 0x76, 0xea, 0x77, 0x5c, 0x3f, 0xe0, 0xb4,
+ 0x2f, 0x02, 0x63, 0x38, 0x59, 0xf5, 0x1d, 0x54, 0x67, 0xb7, 0xaf, 0x8b,
+ 0x29, 0x79, 0x66, 0x3e, 0x2a, 0x66, 0xda, 0x9b, 0xd7, 0xd8, 0xaa, 0xfd,
+ 0x76, 0x9e, 0x5f, 0xf5, 0x11, 0x7b, 0xfa, 0xf3, 0x8a, 0x73, 0x5e, 0xfb,
+ 0xe5, 0xb2, 0xe4, 0xa7, 0x42, 0x88, 0x01, 0x53, 0xc0, 0x39, 0x7d, 0xb0,
+ 0xb7, 0xdc, 0x1f, 0x45, 0x59, 0x85, 0x78, 0x85, 0xbe, 0x2e, 0x05, 0x5d,
+ 0xa1, 0x0d, 0x26, 0x1e, 0x79, 0x55, 0x72, 0x73, 0xbe, 0x8d, 0x41, 0xff,
+ 0x86, 0xdf, 0x3f, 0xf9, 0x9c, 0xb9, 0x65, 0xb3, 0x2c, 0x25, 0x36, 0x8b,
+ 0x95, 0x58, 0x90, 0xda, 0xba, 0x8e, 0xad, 0xcf, 0x77, 0xe7, 0xfe, 0x60,
+ 0x4d, 0x36, 0xc6, 0xd6, 0x59, 0xfb, 0xbd, 0xe2, 0xbf, 0xf7, 0xd7, 0x7e,
+ 0xdd, 0x75, 0x28, 0xbc, 0x22, 0x5c, 0x0b, 0xf2, 0x80, 0x78, 0x38, 0x2c,
+ 0x9f, 0x8a, 0x51, 0x1f, 0x0b, 0xea, 0x7c, 0x33, 0x69, 0x74, 0x2b, 0x9b,
+ 0x31, 0xe8, 0x78, 0xf2, 0x5a, 0xc0, 0x38, 0x91, 0xae, 0x7f, 0xe1, 0x0e,
+ 0xc6, 0x10, 0xe7, 0x76, 0xd1, 0xbe, 0xf8, 0x3a, 0x1d, 0x55, 0x3a, 0xfd,
+ 0x79, 0x27, 0x20, 0x45, 0x3b, 0x20, 0x13, 0xf6, 0x41, 0x85, 0xf1, 0x3f,
+ 0x84, 0xbe, 0x1e, 0xd4, 0x7d, 0x4d, 0x48, 0xb7, 0xb6, 0x3f, 0x07, 0x20,
+ 0xe7, 0xae, 0xdc, 0xe7, 0x6c, 0x95, 0xdb, 0x5a, 0xa9, 0x03, 0xfe, 0xfc,
+ 0x0f, 0x4a, 0xd7, 0xd6, 0xa5, 0x04, 0x22, 0x83, 0x5b, 0xc2, 0x2b, 0x3c,
+ 0xa0, 0x9e, 0xf9, 0xf2, 0xed, 0xf1, 0xc1, 0x9b, 0xff, 0xaa, 0xb9, 0xea,
+ 0x79, 0x72, 0xce, 0xac, 0xc7, 0xb9, 0x7a, 0x58, 0xbe, 0x36, 0x57, 0xbf,
+ 0x7e, 0x33, 0x64, 0xc9, 0x4a, 0x48, 0xa0, 0x9e, 0x37, 0x2b, 0x36, 0x6a,
+ 0x98, 0x7b, 0x24, 0x4b, 0xa6, 0x95, 0x4a, 0x04, 0xfc, 0xbd, 0x68, 0x0f,
+ 0xeb, 0x76, 0x02, 0x87, 0xdb, 0xdd, 0xdd, 0xa9, 0xbc, 0xda, 0x23, 0x35,
+ 0xd4, 0xbc, 0x26, 0x80, 0xc9, 0xe6, 0x9d, 0x57, 0xdc, 0x4f, 0x02, 0xb3,
+ 0x8e, 0xcb, 0xc3, 0x12, 0x5c, 0xb5, 0x97, 0x8b, 0xfc, 0x59, 0xee, 0xe7,
+ 0x5a, 0x89, 0x0c, 0xd6, 0xf8, 0xc3, 0x88, 0xe1, 0xcb, 0xb0, 0xfb, 0x1f,
+ 0xa1, 0x6f, 0x28, 0xc1, 0x5f, 0x00, 0x97, 0x7c, 0xed, 0xba, 0x18, 0x7e,
+ 0xbc, 0x6e, 0x2f, 0xd7, 0xc3, 0xa7, 0xe7, 0x14, 0x26, 0x25, 0x6e, 0x3f,
+ 0x1c, 0xb8, 0xa7, 0x27, 0x88, 0x38, 0xa3, 0xe0, 0x46, 0x6c, 0xe2, 0xb8,
+ 0x83, 0x72, 0x17, 0xd6, 0xe7, 0xf4, 0x7c, 0x21, 0xb0, 0xa3, 0xe4, 0xcb,
+ 0x2a, 0xe2, 0xca, 0xaa, 0x95, 0x5a, 0x06, 0x3f, 0x9e, 0xd4, 0x98, 0x8f,
+ 0xe7, 0x35, 0x65, 0x1d, 0xb3, 0x70, 0x6f, 0xa8, 0x58, 0x3d, 0x28, 0x93,
+ 0x0e, 0xf7, 0x76, 0xba, 0xa4, 0x18, 0xcb, 0xdc, 0xd4, 0xb8, 0xc2, 0x23,
+ 0xcb, 0x44, 0xcc, 0x97, 0xa2, 0xfd, 0x2e, 0xeb, 0xf3, 0x8e, 0x27, 0x95,
+ 0x7c, 0xf9, 0xfb, 0xc2, 0x8c, 0x8f, 0x78, 0x5e, 0xd5, 0x65, 0x0e, 0xf3,
+ 0x79, 0x8e, 0x32, 0xa0, 0x62, 0x26, 0xf0, 0xf2, 0x21, 0xc9, 0x8c, 0x26,
+ 0x14, 0x6e, 0x79, 0xbc, 0x44, 0x7d, 0x21, 0xfe, 0xbf, 0x0c, 0xec, 0x1f,
+ 0xc2, 0x9a, 0x31, 0x0e, 0xe0, 0xd8, 0xd4, 0x0b, 0x94, 0x55, 0xcc, 0x5f,
+ 0xa2, 0x17, 0xdb, 0x37, 0x11, 0x63, 0x5c, 0x28, 0x7d, 0x5c, 0xf1, 0x6f,
+ 0x49, 0xfc, 0xbd, 0x73, 0x85, 0x05, 0x0b, 0xd9, 0x60, 0x40, 0x92, 0x47,
+ 0x3f, 0x03, 0x19, 0x1a, 0x41, 0x8c, 0xc4, 0x7a, 0xa2, 0xce, 0xaf, 0x06,
+ 0x81, 0xb9, 0x0c, 0xfb, 0x46, 0x29, 0x9a, 0x61, 0x29, 0xaa, 0x7b, 0x80,
+ 0x3c, 0xcf, 0x0d, 0xaa, 0xbd, 0x9d, 0xa2, 0x49, 0xcc, 0x9f, 0xd9, 0xe4,
+ 0xdf, 0x03, 0x2c, 0x9a, 0x6c, 0xc7, 0x3c, 0xcb, 0x27, 0x24, 0x7c, 0xf4,
+ 0x80, 0x34, 0x1c, 0x7d, 0x58, 0x1a, 0xa7, 0x89, 0xf1, 0xb8, 0x77, 0x6f,
+ 0xdc, 0xd1, 0x28, 0xc4, 0xdc, 0x5f, 0xc5, 0xd8, 0x07, 0xe5, 0x87, 0x8e,
+ 0x4f, 0xd3, 0x86, 0x8d, 0xd2, 0xc2, 0x3a, 0x7e, 0xde, 0xc7, 0xe3, 0x77,
+ 0x80, 0x1e, 0xce, 0x3f, 0xa1, 0x71, 0xdf, 0x1d, 0x75, 0xb1, 0x6b, 0x83,
+ 0x8e, 0x5d, 0xd9, 0xee, 0x32, 0x7c, 0xf6, 0x31, 0x09, 0xdb, 0x7e, 0xfb,
+ 0xed, 0xa8, 0x17, 0xaf, 0xbb, 0x03, 0xc1, 0x3a, 0xfa, 0x4e, 0x40, 0x0b,
+ 0x71, 0x0f, 0xcf, 0xdb, 0x59, 0xe6, 0x9d, 0xf9, 0x1b, 0xe5, 0x74, 0x70,
+ 0xf5, 0xf8, 0xdb, 0xea, 0xea, 0xfa, 0x65, 0x7e, 0x9b, 0xb0, 0x17, 0xf3,
+ 0xf7, 0x87, 0xeb, 0xda, 0x7d, 0xd7, 0xf4, 0x52, 0x2f, 0xf6, 0xf0, 0xe2,
+ 0x20, 0xce, 0x21, 0x55, 0x87, 0x73, 0x56, 0x7f, 0x2f, 0x9a, 0x43, 0x79,
+ 0x7e, 0xd6, 0xbf, 0x3b, 0x64, 0x60, 0x2e, 0x56, 0x81, 0xf1, 0x8b, 0xc9,
+ 0x6f, 0x33, 0x67, 0x0b, 0xa0, 0xfb, 0x66, 0x75, 0xef, 0x88, 0x77, 0x37,
+ 0x50, 0x2f, 0xe1, 0xe1, 0x4f, 0xe6, 0xe3, 0x58, 0xf3, 0x77, 0x75, 0x18,
+ 0xe9, 0xff, 0x7e, 0x53, 0xb6, 0x9f, 0xf8, 0x66, 0x13, 0xcf, 0x21, 0x81,
+ 0x9b, 0x29, 0x67, 0xdf, 0x81, 0x9c, 0x35, 0xaa, 0x73, 0x9f, 0x62, 0x89,
+ 0xf1, 0x5c, 0x1e, 0xf2, 0xc3, 0xfb, 0x7b, 0x8c, 0xfb, 0xf2, 0x7a, 0x3f,
+ 0x96, 0x74, 0x12, 0xd3, 0xfb, 0xf1, 0x01, 0xfb, 0x5c, 0xef, 0x9e, 0xb2,
+ 0x1f, 0xb3, 0x51, 0xde, 0xe2, 0x8a, 0xe6, 0xa1, 0x35, 0xf1, 0xca, 0x21,
+ 0xd8, 0x82, 0x79, 0xc8, 0xf3, 0x5e, 0xd8, 0xc0, 0xc1, 0x20, 0xf5, 0x33,
+ 0xaa, 0x63, 0x59, 0x9b, 0x71, 0x7b, 0x60, 0x14, 0x7d, 0x18, 0xd3, 0xaf,
+ 0xc9, 0x04, 0xec, 0xff, 0x64, 0x35, 0xa9, 0xbe, 0xe9, 0xc9, 0xc4, 0x79,
+ 0x9f, 0x8c, 0xe5, 0x5f, 0x83, 0xbc, 0xbe, 0x06, 0x3c, 0xbc, 0x01, 0xfc,
+ 0x34, 0xf4, 0x5a, 0xfd, 0x96, 0xde, 0x8b, 0x8a, 0x70, 0x2f, 0x1e, 0x76,
+ 0xb3, 0xe8, 0x61, 0xcd, 0xd8, 0x24, 0xd2, 0x7f, 0x1e, 0xf5, 0xe4, 0xf5,
+ 0xdf, 0x6a, 0x79, 0x6b, 0x42, 0xf9, 0x63, 0x6a, 0x0f, 0xd2, 0x9b, 0x93,
+ 0xa5, 0x63, 0x95, 0x30, 0x64, 0x8e, 0xf3, 0xfa, 0x53, 0xd4, 0xa3, 0xac,
+ 0xf5, 0xe8, 0xb3, 0xd9, 0xa8, 0xb2, 0x8f, 0x39, 0xc8, 0x52, 0x5e, 0xc5,
+ 0x11, 0xc0, 0xf7, 0x0e, 0xdb, 0x3d, 0xb7, 0x89, 0x67, 0x9f, 0x0d, 0xb6,
+ 0x8a, 0x2d, 0xda, 0x83, 0xe2, 0x97, 0xdd, 0x89, 0x32, 0xca, 0xd9, 0x8d,
+ 0x58, 0x1b, 0x96, 0x65, 0x91, 0xe7, 0x58, 0x37, 0xe9, 0x71, 0x38, 0x46,
+ 0x77, 0xf3, 0x6a, 0x9a, 0x38, 0x97, 0xf6, 0x35, 0xdf, 0x35, 0xb0, 0xec,
+ 0x46, 0x5d, 0x16, 0xd2, 0xf3, 0x1b, 0xd2, 0xdf, 0xd2, 0x5a, 0x87, 0x33,
+ 0x2b, 0xd8, 0x98, 0xf4, 0x45, 0x54, 0xbb, 0x8c, 0xe9, 0xc9, 0xce, 0x21,
+ 0xac, 0x47, 0x28, 0x1d, 0xe4, 0x99, 0x2c, 0xf8, 0xeb, 0xeb, 0x44, 0x5c,
+ 0xc5, 0x9d, 0x09, 0xc3, 0xbb, 0xbb, 0x74, 0xee, 0x9a, 0xfb, 0xd9, 0xde,
+ 0x5d, 0xf7, 0xa1, 0x9e, 0x26, 0x99, 0x9f, 0x89, 0xe8, 0x7b, 0x93, 0x71,
+ 0xa5, 0xb3, 0xf9, 0x31, 0xe6, 0xff, 0xc7, 0x26, 0x7e, 0xc7, 0x6c, 0xd8,
+ 0x2c, 0x6f, 0xd7, 0xfc, 0xbd, 0x51, 0xdd, 0x33, 0xa2, 0x2e, 0x14, 0xe7,
+ 0xde, 0x50, 0xef, 0x4f, 0xcf, 0x36, 0xa8, 0xfa, 0xa7, 0x67, 0xd7, 0xde,
+ 0x15, 0x62, 0xd9, 0xdb, 0xb8, 0xbf, 0x21, 0x0b, 0x53, 0x0d, 0xb2, 0x38,
+ 0x1b, 0x60, 0xbc, 0x96, 0x6e, 0xac, 0x7d, 0x0b, 0xa3, 0xbf, 0x5b, 0x73,
+ 0x65, 0x08, 0xeb, 0x37, 0x3f, 0x30, 0x29, 0xe5, 0x01, 0xc6, 0x23, 0xea,
+ 0x3e, 0x20, 0x64, 0xa4, 0x01, 0x58, 0xb4, 0xe0, 0x96, 0x6d, 0xee, 0x03,
+ 0xb7, 0x68, 0xbd, 0x7e, 0x45, 0xc7, 0x7c, 0xe4, 0x91, 0x21, 0xb9, 0xbe,
+ 0x09, 0x45, 0x57, 0x59, 0xf1, 0xca, 0xff, 0xd6, 0x88, 0xfd, 0xf3, 0x7b,
+ 0xa3, 0xa0, 0xc6, 0xb2, 0xfb, 0x35, 0xcf, 0xff, 0x4a, 0xa7, 0x8f, 0xca,
+ 0x9e, 0x63, 0xbf, 0x0f, 0x5a, 0x9b, 0xbc, 0x3b, 0x4f, 0x52, 0xff, 0x3d,
+ 0x49, 0x48, 0x7d, 0xcf, 0x12, 0xb2, 0x1f, 0x45, 0x19, 0xf7, 0xc1, 0x1e,
+ 0x55, 0xf3, 0xe0, 0xbd, 0xba, 0x82, 0xfc, 0xaa, 0xfb, 0x21, 0x7e, 0x2c,
+ 0xc6, 0xbb, 0x4b, 0x51, 0xdd, 0xdf, 0x0e, 0xbd, 0x8e, 0x63, 0xb2, 0x07,
+ 0xbe, 0x26, 0x0f, 0x4c, 0xca, 0xfb, 0x5e, 0xe3, 0xc1, 0xfa, 0x31, 0x7d,
+ 0x59, 0xf6, 0xe2, 0x7c, 0xff, 0xde, 0x41, 0x50, 0xc5, 0x23, 0x2b, 0x7b,
+ 0x06, 0xba, 0x7c, 0x4c, 0xf6, 0x95, 0xd4, 0xde, 0x81, 0x3a, 0x2f, 0x9c,
+ 0x84, 0x4e, 0x0e, 0x2a, 0x7f, 0x12, 0x09, 0x0c, 0x55, 0xd2, 0x92, 0x3f,
+ 0xb9, 0x13, 0xe3, 0x70, 0x1f, 0x2e, 0xa3, 0xcf, 0xe5, 0x76, 0xcb, 0x9e,
+ 0xaa, 0x37, 0xf6, 0xde, 0x12, 0xdf, 0x27, 0xe1, 0xa3, 0xf9, 0x3e, 0x17,
+ 0x0f, 0xaa, 0x93, 0x85, 0x5b, 0xd1, 0xb6, 0x41, 0xf3, 0x96, 0xf7, 0xfc,
+ 0xd9, 0x9e, 0xfa, 0xf7, 0x4f, 0x4c, 0x89, 0xe6, 0xf0, 0x9e, 0x6d, 0xfc,
+ 0xfe, 0xf6, 0xc2, 0x67, 0x30, 0x36, 0x7e, 0x44, 0x96, 0xe6, 0x26, 0x65,
+ 0x79, 0xce, 0x97, 0x33, 0xde, 0xb9, 0x26, 0xed, 0x77, 0xeb, 0x3b, 0xd7,
+ 0x19, 0xac, 0xc3, 0x6a, 0x5e, 0xe5, 0x56, 0x7d, 0x8f, 0xf4, 0x75, 0xd3,
+ 0xfb, 0x26, 0x70, 0xbb, 0xba, 0x3f, 0xb5, 0x5a, 0xde, 0xd9, 0xcf, 0x57,
+ 0x4c, 0x9e, 0x33, 0x78, 0x77, 0xc0, 0xda, 0xeb, 0xde, 0xc7, 0xf4, 0xbd,
+ 0xab, 0xaf, 0xe9, 0xbb, 0xfa, 0xe4, 0xe7, 0xa8, 0xa6, 0xf7, 0x56, 0xe8,
+ 0x1e, 0xfb, 0x7c, 0x4c, 0xaf, 0x1b, 0xd2, 0x79, 0x3e, 0xab, 0xbb, 0xa6,
+ 0xfa, 0xec, 0xd5, 0xd4, 0x63, 0xd4, 0xdf, 0x7b, 0x6b, 0xa8, 0x1b, 0x97,
+ 0xed, 0xe9, 0x1b, 0xfc, 0x3b, 0xe0, 0x2c, 0x3b, 0xa6, 0xef, 0xd7, 0xf9,
+ 0x77, 0xbe, 0x59, 0xe6, 0xdf, 0x03, 0x23, 0xbf, 0xb8, 0x9f, 0x88, 0xb4,
+ 0x3a, 0xaa, 0x9f, 0x47, 0xeb, 0xbe, 0x1d, 0xf2, 0xfb, 0x0c, 0xa1, 0x8f,
+ 0x3b, 0x83, 0xd7, 0xde, 0x11, 0xe7, 0xb7, 0x54, 0x94, 0x45, 0x83, 0xdf,
+ 0x78, 0x33, 0x06, 0x03, 0x6e, 0xda, 0x28, 0x7b, 0x15, 0x3d, 0x05, 0x75,
+ 0x57, 0x22, 0xeb, 0x34, 0xc9, 0xa0, 0xe9, 0xe5, 0xf7, 0xce, 0xaf, 0x95,
+ 0x53, 0x96, 0x6f, 0x8a, 0x48, 0x94, 0xdf, 0x70, 0xf1, 0xfd, 0x7a, 0xdf,
+ 0x2e, 0x84, 0xf5, 0xf7, 0x53, 0x0e, 0xda, 0x7c, 0x9e, 0xf2, 0x5e, 0x28,
+ 0xac, 0xdc, 0xd1, 0x2c, 0xa8, 0x3d, 0x52, 0x00, 0x73, 0x7d, 0x57, 0x92,
+ 0xdf, 0xb0, 0x8b, 0x3c, 0x5d, 0xe1, 0xb7, 0x5c, 0xdb, 0xd5, 0x1d, 0x16,
+ 0xef, 0x5c, 0x90, 0x74, 0x75, 0x29, 0x9b, 0x5c, 0xae, 0x14, 0xc9, 0x53,
+ 0xed, 0x57, 0xc3, 0xda, 0xaf, 0x92, 0xc7, 0xc3, 0xe0, 0xf1, 0x5f, 0xeb,
+ 0x75, 0x61, 0xfb, 0x8c, 0xba, 0x0b, 0x9e, 0x89, 0xf1, 0x6c, 0xea, 0x31,
+ 0x35, 0x17, 0xda, 0x68, 0xb4, 0x7d, 0x47, 0x50, 0xe9, 0xae, 0xfa, 0x46,
+ 0x1e, 0xf2, 0xc9, 0x6f, 0xde, 0x61, 0x5f, 0x4b, 0xfc, 0xb6, 0x7d, 0x58,
+ 0x7d, 0x67, 0x52, 0xae, 0x70, 0x5d, 0xf9, 0x4d, 0xfb, 0x68, 0x9d, 0x3c,
+ 0x06, 0xf5, 0x58, 0x9b, 0x5a, 0x25, 0xea, 0xad, 0x3b, 0xbf, 0x51, 0x29,
+ 0x57, 0xfc, 0xfb, 0x9d, 0x1b, 0x96, 0xa8, 0x13, 0xa2, 0x62, 0x6c, 0xef,
+ 0x3b, 0x9b, 0xb2, 0xfa, 0x6e, 0x25, 0xc1, 0xef, 0x2e, 0xe1, 0x3b, 0x76,
+ 0xe1, 0x99, 0x67, 0xba, 0xbb, 0x91, 0xc2, 0xe6, 0x54, 0xc6, 0x91, 0x3e,
+ 0x2c, 0x39, 0xb5, 0xe7, 0xd6, 0x8c, 0xfc, 0x5e, 0x35, 0x76, 0xb1, 0xf2,
+ 0x80, 0xec, 0x39, 0xf9, 0x10, 0xbf, 0xed, 0x51, 0xdf, 0xe5, 0x67, 0x1d,
+ 0xd2, 0x18, 0x93, 0x09, 0x35, 0xef, 0x42, 0xed, 0x9b, 0x11, 0xc5, 0xfb,
+ 0x5c, 0x2b, 0xd7, 0xb4, 0x50, 0x69, 0x06, 0x8d, 0x01, 0x7d, 0xc7, 0x93,
+ 0x58, 0xdc, 0x9f, 0x7f, 0x94, 0xf7, 0x06, 0x5d, 0x9e, 0xdd, 0xed, 0x29,
+ 0xf1, 0x0e, 0x67, 0x52, 0xc7, 0xe8, 0xdc, 0xb7, 0xe3, 0xd9, 0x00, 0x65,
+ 0xdc, 0x4a, 0x8d, 0xc3, 0xfa, 0x87, 0x25, 0xce, 0x73, 0x65, 0x3d, 0x97,
+ 0xe6, 0xba, 0xb9, 0xf0, 0xde, 0xaa, 0x37, 0x1f, 0x7e, 0x0b, 0x93, 0x2f,
+ 0xd5, 0x7f, 0xc7, 0xa3, 0xbe, 0x11, 0x57, 0xdf, 0xcd, 0x8c, 0x57, 0x3e,
+ 0x21, 0x1f, 0x2b, 0x6d, 0xd4, 0xdf, 0xf0, 0x44, 0xe4, 0x63, 0x95, 0xd7,
+ 0x14, 0x4f, 0xf3, 0xea, 0xfb, 0xa3, 0xb0, 0x5e, 0xb3, 0x98, 0xea, 0xa3,
+ 0xf6, 0x1d, 0x92, 0x55, 0xf7, 0x4d, 0x4a, 0x58, 0xc6, 0xe7, 0x7f, 0xd9,
+ 0xb7, 0x48, 0x8f, 0x08, 0xbf, 0x47, 0xb9, 0xe4, 0x4c, 0xca, 0xe3, 0x73,
+ 0xae, 0x7b, 0x97, 0x43, 0x5c, 0xb7, 0x41, 0x96, 0x63, 0xa3, 0x3b, 0xbe,
+ 0x67, 0xb7, 0x05, 0xca, 0x33, 0x8d, 0xb0, 0xd7, 0xc4, 0x12, 0x12, 0x65,
+ 0x7e, 0x7e, 0x86, 0x7a, 0x1a, 0xc2, 0x1c, 0x2d, 0xf3, 0xaa, 0x7c, 0xa6,
+ 0x95, 0x7b, 0x5e, 0x77, 0x21, 0x8e, 0xfc, 0xb8, 0xe3, 0xd9, 0xe5, 0xcf,
+ 0x2d, 0xec, 0x94, 0xcf, 0x55, 0x22, 0x81, 0xf2, 0x14, 0xef, 0xfa, 0x59,
+ 0xc3, 0x73, 0x92, 0x44, 0x3d, 0xf6, 0x0f, 0x79, 0x89, 0x6f, 0x96, 0xa7,
+ 0x8e, 0xfd, 0xc2, 0xbd, 0x6a, 0xe3, 0x3d, 0x6c, 0xcd, 0xb2, 0xe3, 0xef,
+ 0xeb, 0x21, 0x86, 0x3f, 0xc2, 0x7a, 0x9b, 0x21, 0x07, 0xf0, 0xdb, 0xd0,
+ 0x39, 0xc6, 0x98, 0x57, 0xb5, 0xdd, 0x32, 0x8e, 0xdc, 0x2c, 0x57, 0x57,
+ 0xee, 0x0a, 0x5f, 0x86, 0x6c, 0x27, 0x3c, 0xfe, 0xab, 0x7d, 0xf0, 0x03,
+ 0x12, 0xfc, 0x22, 0xfc, 0xc4, 0x17, 0x1b, 0x94, 0x6d, 0xa7, 0x3f, 0x43,
+ 0xfc, 0x81, 0x18, 0x23, 0x84, 0x7e, 0x1e, 0x6c, 0xf5, 0x64, 0x76, 0x52,
+ 0xe4, 0xcb, 0x4d, 0x92, 0x69, 0x65, 0x0c, 0x2b, 0xbf, 0xc2, 0x7e, 0xd5,
+ 0xeb, 0x59, 0x4a, 0xbe, 0x42, 0x1d, 0xaf, 0x72, 0x2e, 0xc9, 0xf8, 0x8f,
+ 0xe5, 0x93, 0x32, 0x1e, 0xe7, 0x5c, 0x1e, 0x91, 0xc2, 0xdc, 0x63, 0xf8,
+ 0x71, 0x9e, 0xa4, 0xfb, 0x1f, 0xe8, 0x7b, 0x04, 0xa3, 0x52, 0x9c, 0x4a,
+ 0xcb, 0xc4, 0xec, 0x5e, 0x7e, 0xa3, 0x3b, 0x7c, 0x97, 0x3a, 0x5f, 0xb3,
+ 0xe2, 0xc9, 0x40, 0x6f, 0x62, 0x82, 0xf7, 0x26, 0xd4, 0x7c, 0xf6, 0x62,
+ 0x3e, 0xdf, 0x6a, 0xe5, 0xdd, 0xf3, 0xab, 0xb0, 0xbf, 0xc6, 0x71, 0xca,
+ 0xa1, 0x65, 0x76, 0x06, 0x98, 0xdf, 0x8d, 0xd8, 0x99, 0x65, 0xbb, 0x25,
+ 0x78, 0x64, 0xc5, 0xce, 0xa3, 0x5c, 0x9f, 0xf3, 0xaa, 0xf6, 0xff, 0x11,
+ 0x6d, 0x51, 0xef, 0x88, 0xdf, 0xd6, 0xaf, 0xc3, 0xb6, 0x9c, 0xe7, 0x4e,
+ 0xc4, 0xec, 0x3e, 0x5d, 0x90, 0xc3, 0x78, 0x3d, 0xbf, 0xa3, 0x6b, 0xf8,
+ 0x1d, 0x22, 0xde, 0x04, 0xbf, 0xc8, 0xe3, 0xa0, 0xe6, 0xf1, 0x9b, 0xe8,
+ 0xdf, 0x5f, 0x83, 0xbb, 0x50, 0x66, 0xea, 0x6f, 0x03, 0xdf, 0x0a, 0xdf,
+ 0xc9, 0x73, 0xd6, 0x7f, 0xb0, 0xd5, 0x93, 0x35, 0xd2, 0xb3, 0x1e, 0xcf,
+ 0x3b, 0xdb, 0xbc, 0x75, 0xd9, 0x0d, 0x7e, 0xf1, 0x4e, 0x67, 0xaf, 0xfa,
+ 0x4e, 0x20, 0x33, 0xb6, 0x1b, 0xb2, 0xe3, 0xcf, 0xab, 0x17, 0x32, 0xc6,
+ 0x33, 0x0b, 0xd6, 0xaf, 0xe7, 0x89, 0xe7, 0xf7, 0x82, 0xdc, 0x77, 0xb0,
+ 0x39, 0x57, 0x60, 0xc2, 0x2f, 0xab, 0xef, 0x82, 0x60, 0x27, 0xdf, 0xb6,
+ 0xf2, 0x5d, 0xd0, 0xf5, 0xd7, 0x78, 0xa0, 0xcd, 0xf3, 0x51, 0x26, 0x78,
+ 0xd2, 0xa2, 0xdb, 0xec, 0x06, 0x3e, 0xe5, 0x5e, 0x6c, 0x32, 0xfe, 0xa0,
+ 0xf8, 0xe3, 0xb8, 0xdb, 0x19, 0x73, 0x0e, 0xf6, 0xf7, 0x22, 0xbe, 0x56,
+ 0xf7, 0x65, 0xe2, 0xbc, 0x7f, 0x93, 0x0c, 0xec, 0x56, 0x77, 0x27, 0x2e,
+ 0xac, 0xfa, 0xb6, 0x2b, 0x25, 0x4f, 0xd5, 0x64, 0x65, 0xf8, 0x27, 0x62,
+ 0x49, 0xe2, 0x26, 0xca, 0x0a, 0xfb, 0xdd, 0xcb, 0x79, 0xc6, 0x1f, 0x52,
+ 0xf3, 0x34, 0x11, 0xc3, 0xf1, 0x9e, 0x83, 0x19, 0x28, 0xcf, 0x72, 0xdd,
+ 0x91, 0x2e, 0xf0, 0xd9, 0x3f, 0x6b, 0x55, 0x76, 0x05, 0xe3, 0xb2, 0x8c,
+ 0xb6, 0x91, 0xef, 0xd3, 0xfa, 0x2c, 0xf6, 0xc3, 0x6d, 0xbc, 0x0f, 0x90,
+ 0x47, 0xd9, 0xdc, 0xc2, 0xfa, 0xb4, 0x7d, 0x5c, 0xc9, 0xc1, 0x23, 0xe0,
+ 0xfb, 0x1f, 0xa3, 0xee, 0x63, 0x48, 0x39, 0xc7, 0xf4, 0xca, 0xba, 0x93,
+ 0xdf, 0x1f, 0x90, 0x01, 0xc8, 0x05, 0xf3, 0x8f, 0x48, 0x51, 0xdd, 0x63,
+ 0x42, 0x3a, 0xc7, 0x67, 0xda, 0x7a, 0x5b, 0xfb, 0x53, 0xd2, 0xb2, 0x5b,
+ 0x7f, 0x4f, 0xe6, 0xcb, 0xd3, 0x2e, 0xdd, 0x6e, 0x6c, 0x85, 0x57, 0x0f,
+ 0x5d, 0x83, 0x37, 0xc2, 0x2b, 0x78, 0xc3, 0x1b, 0xeb, 0xf1, 0x36, 0x1f,
+ 0x6b, 0x78, 0x73, 0xf0, 0xb0, 0x86, 0x27, 0xe7, 0x7b, 0x25, 0x04, 0x39,
+ 0x0e, 0xd6, 0xe4, 0x18, 0xb8, 0xc7, 0xd3, 0x99, 0x09, 0x9e, 0x21, 0x2a,
+ 0x3e, 0x53, 0x0e, 0x29, 0xbf, 0x5c, 0xc7, 0xfa, 0xb5, 0x7e, 0xcf, 0x2f,
+ 0x59, 0xeb, 0x97, 0xdb, 0x7c, 0xfc, 0xf0, 0x77, 0xd3, 0x83, 0x0b, 0x6d,
+ 0x35, 0x3d, 0xb8, 0xf9, 0x37, 0xa4, 0x07, 0x6b, 0xe5, 0xb2, 0x5e, 0xa6,
+ 0x4c, 0xc8, 0x13, 0xd7, 0x8b, 0xf2, 0x44, 0x39, 0x22, 0x2f, 0x69, 0x4f,
+ 0x1b, 0x19, 0x3b, 0xc5, 0xaf, 0xa8, 0xef, 0x36, 0x26, 0x61, 0x83, 0xda,
+ 0x02, 0x73, 0x73, 0x31, 0x29, 0x2e, 0xbc, 0x4f, 0xc9, 0xf4, 0x53, 0x55,
+ 0xda, 0xa5, 0xeb, 0xcd, 0x7d, 0xb5, 0xcd, 0xcd, 0xaf, 0xb1, 0xb9, 0xf9,
+ 0x15, 0x9b, 0xdb, 0xaa, 0xe3, 0xa5, 0xbf, 0x8b, 0xcd, 0x8d, 0xd5, 0x9d,
+ 0xcb, 0xf8, 0x67, 0x32, 0x12, 0xc8, 0xf6, 0x44, 0x65, 0x07, 0xfc, 0xc8,
+ 0xf0, 0xd4, 0x4e, 0xf9, 0x97, 0x53, 0x93, 0xea, 0x8e, 0xd2, 0x5f, 0x38,
+ 0xc9, 0xf8, 0x03, 0x01, 0x57, 0x3e, 0x80, 0x78, 0x77, 0xbc, 0xa3, 0x41,
+ 0x76, 0xbc, 0x4b, 0x9d, 0x35, 0x9a, 0xd9, 0x40, 0xbb, 0x70, 0x17, 0x3c,
+ 0xe7, 0x58, 0x4e, 0x22, 0xc0, 0xfb, 0x6a, 0x8d, 0x32, 0x1e, 0x6b, 0x96,
+ 0x9d, 0xc0, 0x4e, 0x85, 0x1b, 0x1c, 0xf5, 0x2d, 0x79, 0x46, 0x9d, 0xe5,
+ 0xdc, 0xb2, 0xd9, 0x1b, 0x17, 0x7c, 0x68, 0x31, 0xe5, 0xab, 0xd5, 0x5b,
+ 0xd4, 0x77, 0xd1, 0x17, 0x4a, 0xd5, 0xd6, 0xd5, 0x79, 0x3e, 0xff, 0x7b,
+ 0xd4, 0x89, 0x81, 0x57, 0xf5, 0x77, 0x7f, 0x82, 0x8a, 0x9f, 0xc5, 0xb9,
+ 0x31, 0x75, 0xa7, 0xea, 0x4a, 0x90, 0xfc, 0x52, 0x71, 0x53, 0x3c, 0x1b,
+ 0x04, 0xc6, 0x99, 0x01, 0x92, 0xb6, 0x19, 0xf3, 0x69, 0xfc, 0x09, 0xfb,
+ 0xbf, 0x47, 0x9d, 0xed, 0x2e, 0x81, 0x37, 0xae, 0xda, 0xfb, 0xcd, 0xc7,
+ 0x88, 0xeb, 0x6b, 0xf7, 0x87, 0xaf, 0xc5, 0xf7, 0xde, 0xb7, 0x67, 0xfa,
+ 0x1c, 0x42, 0xef, 0x15, 0xe9, 0x18, 0x5c, 0x9d, 0xab, 0xad, 0xf7, 0x7f,
+ 0x29, 0x88, 0xf5, 0xf8, 0x7f, 0x0f, 0x88, 0xed, 0xac, 0xc3, 0x73, 0xe2,
+ 0xa8, 0x38, 0x30, 0x43, 0xfe, 0x96, 0xb1, 0x4e, 0xd3, 0x71, 0xdf, 0x9f,
+ 0x07, 0x3a, 0xcf, 0xd6, 0xc7, 0x81, 0xec, 0x23, 0xa2, 0xee, 0x63, 0xd4,
+ 0xfe, 0x0f, 0x0e, 0xf7, 0x77, 0x32, 0x81, 0x7b, 0x4a, 0x93, 0x12, 0x3c,
+ 0x3a, 0x2a, 0xa1, 0x69, 0xee, 0xa5, 0x67, 0xa4, 0x18, 0x73, 0xe5, 0x63,
+ 0xce, 0xea, 0xd8, 0xa4, 0xd3, 0x58, 0x4b, 0xfb, 0x23, 0x32, 0x78, 0xf2,
+ 0x31, 0x09, 0x1f, 0xe5, 0xbb, 0x55, 0xe7, 0x28, 0xb0, 0x47, 0x1b, 0x64,
+ 0x2e, 0xc6, 0xfd, 0xe4, 0xb0, 0x3a, 0x97, 0x5e, 0x1e, 0x7b, 0x2d, 0x5c,
+ 0x04, 0x56, 0xc8, 0x2b, 0xdb, 0x82, 0x74, 0x25, 0x96, 0x38, 0xbc, 0x99,
+ 0x3a, 0x85, 0x18, 0x33, 0x30, 0x3e, 0x17, 0x56, 0xf7, 0x83, 0x96, 0x63,
+ 0xac, 0x8b, 0xf8, 0xfd, 0x28, 0x71, 0x06, 0x6c, 0xc7, 0xa8, 0x44, 0x99,
+ 0x0f, 0x1e, 0xad, 0xe1, 0x0c, 0xda, 0x84, 0x41, 0x27, 0x26, 0xa1, 0x53,
+ 0xde, 0xdc, 0xf9, 0x8f, 0x95, 0x8c, 0x13, 0x3b, 0x25, 0x38, 0xcd, 0xe7,
+ 0xfa, 0x78, 0x88, 0xd8, 0x1d, 0xbe, 0xe1, 0xec, 0x67, 0xd1, 0x1f, 0xdf,
+ 0x65, 0xf4, 0x37, 0xba, 0xc8, 0x97, 0xff, 0xb6, 0xff, 0x43, 0x81, 0xb2,
+ 0xff, 0xff, 0x01, 0xe6, 0x8e, 0x9a, 0x21, 0xc0, 0x4e, 0x00, 0x00, 0x00 };
static const u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_COM_b06FwRodata[(0x14/4) + 1] = {
- 0x08000f04, 0x08000f4c, 0x08000f80, 0x08000fcc, 0x08001000, 0x00000000
+ 0x08000e7c, 0x08000ec4, 0x08000ef8, 0x08000f44, 0x08000f78, 0x00000000
};
static struct fw_info bnx2_com_fw_06 = {
- /* Firmware version: 4.0.5 */
+ /* Firmware version: 4.4.2 */
.ver_major = 0x4,
- .ver_minor = 0x0,
- .ver_fix = 0x5,
+ .ver_minor = 0x4,
+ .ver_fix = 0x2,
.start_addr = 0x080000f8,
.text_addr = 0x08000000,
- .text_len = 0x4eac,
+ .text_len = 0x4ebc,
.text_index = 0x0,
.gz_text = bnx2_COM_b06FwText,
.gz_text_len = sizeof(bnx2_COM_b06FwText),
@@ -872,15 +872,15 @@ static struct fw_info bnx2_com_fw_06 = {
.data_index = 0x0,
.data = bnx2_COM_b06FwData,
- .sbss_addr = 0x08004ee0,
+ .sbss_addr = 0x08004f00,
.sbss_len = 0x38,
.sbss_index = 0x0,
- .bss_addr = 0x08004f18,
+ .bss_addr = 0x08004f38,
.bss_len = 0xbc,
.bss_index = 0x0,
- .rodata_addr = 0x08004eac,
+ .rodata_addr = 0x08004ebc,
.rodata_len = 0x14,
.rodata_index = 0x0,
.rodata = bnx2_COM_b06FwRodata,
@@ -902,1231 +902,1232 @@ static const struct cpu_reg cpu_reg_com = {
.mips_view_base = 0x8000000,
};
-
static u8 bnx2_CP_b06FwText[] = {
- 0x9d, 0xbc, 0x0d, 0x78, 0x13, 0xe7, 0x99, 0x2e, 0x7c, 0xcf, 0x48, 0xb2,
- 0x65, 0x5b, 0xb6, 0xc7, 0xb6, 0x0c, 0x22, 0x65, 0x41, 0x83, 0x47, 0x20,
- 0x62, 0x27, 0x1d, 0x81, 0x49, 0x94, 0xac, 0x36, 0xa8, 0xc6, 0x01, 0x93,
- 0x90, 0xc6, 0x34, 0xb4, 0x75, 0x7a, 0xd2, 0x8d, 0x62, 0x0c, 0x21, 0x84,
- 0x10, 0x67, 0x9b, 0x9e, 0xe3, 0x7c, 0x5f, 0xce, 0x5a, 0x35, 0x06, 0x0c,
- 0xc8, 0x96, 0x31, 0x0e, 0x90, 0xfd, 0x7a, 0x9d, 0x18, 0x6c, 0x30, 0x49,
- 0x65, 0x8b, 0x34, 0x74, 0x97, 0xf4, 0xa3, 0x45, 0x07, 0xf2, 0xe3, 0xfc,
- 0x35, 0xa4, 0xed, 0x76, 0xdb, 0x3d, 0x39, 0x89, 0x0f, 0x25, 0x84, 0xb4,
- 0xdd, 0xfc, 0xb4, 0xdd, 0x2d, 0x69, 0x9b, 0xcc, 0x77, 0x3f, 0x23, 0x09,
- 0x0c, 0x4d, 0x7f, 0xf6, 0xf3, 0x75, 0xcd, 0x65, 0xcd, 0xcc, 0xfb, 0xf3,
- 0xbc, 0xcf, 0xfb, 0x3c, 0xf7, 0x73, 0x3f, 0xef, 0xbc, 0x33, 0xb3, 0x80,
- 0x62, 0xe4, 0xfe, 0x4a, 0x79, 0x5c, 0x5d, 0xdf, 0xbe, 0x1a, 0x8b, 0xae,
- 0x36, 0xe5, 0xdc, 0xe9, 0x82, 0x13, 0x7f, 0xe1, 0x9f, 0xff, 0x2f, 0x2d,
- 0x38, 0xe5, 0xcf, 0x01, 0x68, 0xf9, 0x7e, 0xe5, 0x80, 0x5b, 0x8d, 0x3c,
- 0xf3, 0x5f, 0x1a, 0x0c, 0xb8, 0x1d, 0x91, 0x9e, 0xd6, 0xd5, 0x06, 0x10,
- 0x4d, 0xd5, 0xfa, 0x97, 0xe0, 0x23, 0x2b, 0xee, 0x75, 0x42, 0xae, 0xff,
- 0x55, 0xe4, 0xf7, 0x9d, 0xdf, 0xb9, 0x56, 0x7f, 0x7f, 0xc8, 0x01, 0xb7,
- 0x16, 0xe9, 0x80, 0x36, 0x17, 0xee, 0x99, 0xac, 0xf3, 0xf5, 0x79, 0xdb,
- 0x15, 0x94, 0xe5, 0xdb, 0x3a, 0x67, 0x7d, 0x67, 0x9e, 0x2f, 0x56, 0x14,
- 0xd1, 0x70, 0x3c, 0x8d, 0xe6, 0xba, 0xde, 0x4e, 0xab, 0xd4, 0x08, 0xc1,
- 0x6d, 0x18, 0x2d, 0xbd, 0x8a, 0x27, 0xbc, 0x7e, 0x11, 0x3c, 0x85, 0x06,
- 0xe2, 0x57, 0x44, 0xd0, 0x7c, 0xe5, 0x58, 0x71, 0xdc, 0x19, 0x71, 0xa3,
- 0x29, 0xed, 0x8e, 0x7f, 0x2a, 0x62, 0x60, 0x59, 0xfa, 0xfa, 0x62, 0x94,
- 0xb9, 0xd1, 0x9d, 0xfe, 0xa8, 0x28, 0xdb, 0x5e, 0x73, 0xee, 0xff, 0xec,
- 0xaa, 0xec, 0xff, 0x69, 0x31, 0x67, 0x04, 0xd8, 0x9c, 0xb0, 0xac, 0x82,
- 0xc8, 0x6d, 0xb7, 0xa9, 0x11, 0xc3, 0x77, 0x10, 0x8b, 0xd1, 0xaa, 0xe1,
- 0xe1, 0x2d, 0xf5, 0xbf, 0x54, 0x4e, 0x0c, 0xb2, 0xe1, 0x51, 0x07, 0xa2,
- 0xda, 0x33, 0xfc, 0x3f, 0x6b, 0x56, 0x4b, 0xd8, 0xc0, 0xde, 0xd1, 0xf3,
- 0xbc, 0xee, 0xb4, 0xaf, 0x6d, 0xda, 0x33, 0x6b, 0xd6, 0xed, 0xe1, 0x67,
- 0xf0, 0xe8, 0xa8, 0xfc, 0xbe, 0x1b, 0x9d, 0x75, 0x0a, 0x26, 0x6f, 0x5b,
- 0x0b, 0x87, 0x61, 0xa0, 0x7b, 0x8f, 0xe2, 0xec, 0xaa, 0x53, 0x11, 0xf5,
- 0xea, 0xc1, 0x18, 0x95, 0xef, 0x34, 0x10, 0x2b, 0x8c, 0x84, 0x9d, 0xef,
- 0x24, 0x22, 0x9a, 0xc3, 0xb0, 0xac, 0x60, 0x68, 0x3a, 0x1c, 0x15, 0x96,
- 0xf5, 0xb4, 0xe9, 0x81, 0xff, 0x8b, 0xcf, 0x21, 0x3e, 0xdc, 0x0c, 0xd5,
- 0x78, 0x0e, 0x5d, 0xc3, 0xcf, 0xe1, 0xb1, 0x5d, 0xc5, 0x98, 0xac, 0xe2,
- 0x78, 0x93, 0x3e, 0x7c, 0x67, 0x9e, 0xf4, 0x2d, 0x72, 0xd4, 0xf1, 0x70,
- 0x63, 0xd2, 0xf1, 0x06, 0xff, 0x4b, 0x99, 0xf3, 0xd6, 0xe4, 0xf4, 0x8b,
- 0x65, 0x36, 0xb3, 0x4c, 0xf7, 0x65, 0x65, 0xe2, 0xc3, 0x11, 0xbc, 0x94,
- 0x50, 0xb0, 0x3e, 0x54, 0x86, 0x68, 0x85, 0x8c, 0xd7, 0xb2, 0x46, 0xcd,
- 0xb3, 0xd6, 0xa4, 0x26, 0x7d, 0x4d, 0xe0, 0x65, 0xde, 0xdb, 0x12, 0x3a,
- 0x63, 0x65, 0xbc, 0xd2, 0x5e, 0x3b, 0x6d, 0x67, 0x25, 0xaf, 0x3b, 0x91,
- 0x4c, 0x20, 0x56, 0x16, 0xb9, 0x8d, 0xe7, 0xba, 0xf9, 0xae, 0xe2, 0x76,
- 0xbf, 0x97, 0x70, 0x7f, 0xb1, 0xd4, 0x50, 0x1f, 0x2c, 0xa7, 0x01, 0xbd,
- 0x42, 0x99, 0x8f, 0x9a, 0x6b, 0xe1, 0x32, 0x1e, 0x10, 0x5b, 0xe3, 0xb8,
- 0x7e, 0x68, 0x61, 0x7a, 0xbe, 0xbe, 0xb4, 0xeb, 0xc6, 0x96, 0xa4, 0x65,
- 0x6d, 0x33, 0xa3, 0xd7, 0x15, 0xd1, 0x20, 0x4e, 0x26, 0x9a, 0xe1, 0x8e,
- 0x04, 0xfc, 0xe7, 0x10, 0xc6, 0x92, 0xb4, 0x17, 0xcf, 0x26, 0xe0, 0x6c,
- 0x98, 0xe7, 0x45, 0x57, 0x3a, 0x82, 0x1b, 0xd3, 0x26, 0x1a, 0xd3, 0x7f,
- 0xde, 0xb2, 0x6e, 0x4e, 0xfa, 0x39, 0x86, 0x8f, 0xac, 0xec, 0x18, 0x64,
- 0x7c, 0xd9, 0xff, 0xdd, 0xc9, 0x2b, 0xb0, 0x9d, 0x73, 0xb4, 0x95, 0xf3,
- 0xb7, 0x3c, 0x94, 0x89, 0x16, 0x41, 0x37, 0xcf, 0x21, 0x82, 0xa5, 0x69,
- 0x83, 0x73, 0x1a, 0xc1, 0x92, 0x64, 0x8d, 0x36, 0x8c, 0xf9, 0x88, 0xfa,
- 0xb2, 0x36, 0xbd, 0x83, 0xe3, 0x6d, 0x0d, 0x34, 0xa3, 0x94, 0x36, 0x92,
- 0x5a, 0x14, 0x46, 0x03, 0xfb, 0x5f, 0xf1, 0x17, 0xf4, 0x7f, 0x2b, 0xfb,
- 0x7f, 0x97, 0xfd, 0x67, 0xec, 0xfe, 0xe1, 0xbc, 0x89, 0xe7, 0x6e, 0xda,
- 0xe3, 0xf6, 0x94, 0xd3, 0xb9, 0x3c, 0xe9, 0xc5, 0xb6, 0x94, 0x49, 0x9b,
- 0x93, 0x5b, 0x3e, 0x6c, 0x19, 0x9c, 0x89, 0xad, 0x83, 0xba, 0xef, 0x79,
- 0xfe, 0xde, 0x34, 0x72, 0x05, 0x36, 0x0f, 0x2a, 0xd8, 0x6f, 0x5c, 0x81,
- 0x2e, 0xfe, 0xde, 0x3b, 0x38, 0x0b, 0x8f, 0x0e, 0x3a, 0x10, 0xae, 0xba,
- 0x74, 0x1c, 0x93, 0x8e, 0x2b, 0x10, 0x1f, 0xf1, 0xa3, 0x2b, 0xf1, 0xa2,
- 0xad, 0xc3, 0xd2, 0xc8, 0xff, 0x9b, 0xf7, 0x63, 0xfa, 0x8e, 0x1f, 0xab,
- 0x13, 0x1a, 0xba, 0x92, 0x0e, 0xb1, 0x4b, 0xfe, 0xfd, 0x92, 0xf7, 0x34,
- 0x6c, 0x4a, 0xe7, 0xeb, 0x8b, 0x9f, 0xf9, 0xd1, 0x90, 0x98, 0xa0, 0x9f,
- 0xd4, 0xd3, 0x47, 0x4c, 0x7c, 0x37, 0x5d, 0x87, 0x7f, 0x4a, 0x07, 0xf1,
- 0x8f, 0xd4, 0xc3, 0xb7, 0xd2, 0x7e, 0x1c, 0x49, 0xcf, 0xc4, 0x53, 0x69,
- 0x1f, 0xbe, 0x49, 0xfd, 0x3f, 0x99, 0x6e, 0xa6, 0xed, 0x6a, 0x38, 0x9c,
- 0x16, 0xfd, 0x15, 0x50, 0xde, 0x62, 0x6c, 0x1a, 0xac, 0x09, 0x9e, 0xa4,
- 0x6d, 0xfc, 0xa3, 0x79, 0x13, 0x32, 0x95, 0xf5, 0xb6, 0x4d, 0x6d, 0xe3,
- 0xf5, 0xed, 0x83, 0x35, 0xd1, 0x2b, 0x15, 0xcb, 0x52, 0x43, 0xb5, 0xe1,
- 0x13, 0xaa, 0x8a, 0x49, 0xaf, 0xee, 0xcf, 0xa8, 0xba, 0x3f, 0x0a, 0x17,
- 0x12, 0xb4, 0xed, 0x78, 0xb5, 0x3e, 0x14, 0xa7, 0x4d, 0x78, 0x8d, 0x7d,
- 0x40, 0x99, 0xee, 0x8f, 0xab, 0x6e, 0x6c, 0x4d, 0xea, 0x7b, 0xe3, 0xaa,
- 0x07, 0xf1, 0x74, 0x31, 0xfe, 0x6d, 0x50, 0xef, 0x89, 0xab, 0x9f, 0x45,
- 0xbc, 0xd2, 0xb2, 0xbe, 0x19, 0x42, 0xfb, 0xf4, 0x08, 0xa2, 0xd5, 0x11,
- 0xc4, 0x66, 0x45, 0xbc, 0x48, 0x26, 0x81, 0x77, 0x7b, 0x0d, 0xdf, 0xbf,
- 0x28, 0xcd, 0xf8, 0x6a, 0xb3, 0xee, 0xf7, 0xab, 0xb5, 0xf1, 0x61, 0x75,
- 0x11, 0x5d, 0x12, 0x7e, 0x5f, 0x64, 0x19, 0x3a, 0xec, 0x6b, 0x0a, 0x34,
- 0xc3, 0x83, 0x4d, 0xc9, 0xeb, 0x10, 0xf3, 0xd6, 0xb4, 0xec, 0x54, 0x6b,
- 0xce, 0x9b, 0xaa, 0x3e, 0xd1, 0xac, 0x5a, 0xd6, 0x07, 0x0b, 0xdf, 0xb5,
- 0xfc, 0xd3, 0x2c, 0x6b, 0xc1, 0x42, 0xe9, 0xd3, 0x8f, 0x8a, 0x88, 0x89,
- 0x95, 0xf6, 0x1c, 0x14, 0xe3, 0xec, 0x60, 0x25, 0xfb, 0xd0, 0xf0, 0xcf,
- 0xd7, 0xea, 0xc1, 0xb5, 0x6a, 0x31, 0xde, 0x1a, 0x29, 0xc6, 0x69, 0x8e,
- 0xe7, 0x97, 0x83, 0x3e, 0xfc, 0x7a, 0xd0, 0xb2, 0xbe, 0x68, 0xfe, 0x35,
- 0x06, 0x2a, 0xfb, 0xf1, 0x4f, 0xe3, 0x5e, 0xfc, 0x1b, 0x75, 0x7b, 0x26,
- 0x11, 0x7d, 0xa0, 0x0a, 0x7a, 0x74, 0x5c, 0x39, 0x79, 0x67, 0x19, 0x6a,
- 0x9b, 0xcb, 0x14, 0xbd, 0x69, 0x07, 0x74, 0xdf, 0x95, 0x8a, 0x17, 0xe7,
- 0x52, 0x1a, 0x7e, 0x9a, 0xaa, 0x09, 0xff, 0x80, 0x7d, 0xfe, 0x87, 0xf9,
- 0xb4, 0x95, 0x99, 0x26, 0x7a, 0x13, 0x1d, 0x51, 0xcf, 0x49, 0xea, 0x39,
- 0x49, 0x3d, 0x27, 0xa9, 0x67, 0xca, 0x70, 0x24, 0x49, 0x3d, 0x53, 0x77,
- 0xdf, 0xa4, 0x4d, 0x3c, 0x99, 0xa4, 0x8e, 0x93, 0x32, 0x47, 0x61, 0xfa,
- 0xe7, 0xa7, 0xf0, 0xf7, 0xf6, 0xdc, 0xbd, 0x6c, 0xfd, 0x37, 0xaf, 0x8c,
- 0xe9, 0xfe, 0x69, 0x59, 0xfc, 0x91, 0xb1, 0xbd, 0x64, 0xc5, 0x34, 0x19,
- 0x97, 0x8c, 0xcf, 0xd6, 0x9f, 0xbf, 0x5d, 0xf9, 0xaa, 0x82, 0x62, 0xcb,
- 0xda, 0x65, 0xe6, 0xee, 0x7b, 0xf3, 0xe3, 0xfb, 0x8c, 0x92, 0xb5, 0x8b,
- 0x7f, 0x72, 0x53, 0xdf, 0xc1, 0xa8, 0xba, 0x88, 0xe7, 0x7a, 0x3c, 0x8a,
- 0x9b, 0x0a, 0x2f, 0x3d, 0xbf, 0xb6, 0x5a, 0xe6, 0xc3, 0x7f, 0xe1, 0x9c,
- 0xf6, 0x64, 0xf7, 0xf7, 0x45, 0x9e, 0xcb, 0x58, 0x04, 0x53, 0xc5, 0x06,
- 0xbc, 0xb4, 0x97, 0x45, 0xb9, 0x7b, 0x88, 0xab, 0x91, 0x76, 0x34, 0xd7,
- 0xef, 0xb5, 0xfb, 0x28, 0xe8, 0x13, 0xbb, 0x57, 0xf0, 0xee, 0x75, 0x0a,
- 0x4e, 0x84, 0x0c, 0xda, 0xcc, 0x10, 0xfd, 0x1a, 0x28, 0xec, 0x83, 0xdb,
- 0x13, 0x89, 0x20, 0xd1, 0x0b, 0x77, 0x51, 0x24, 0x8c, 0xf9, 0xbd, 0x35,
- 0xeb, 0xce, 0x42, 0x0f, 0xf6, 0x2a, 0x7a, 0x33, 0x50, 0x6b, 0x8e, 0x51,
- 0x8f, 0x57, 0x2a, 0xba, 0xbf, 0x40, 0x81, 0x5b, 0x61, 0xb9, 0x40, 0x6a,
- 0x08, 0x5b, 0xd3, 0xf2, 0x3b, 0x0c, 0x23, 0xf5, 0xeb, 0x7c, 0x5f, 0xb4,
- 0xeb, 0x76, 0xda, 0xf5, 0x59, 0x8e, 0x5d, 0xf7, 0x13, 0x1f, 0xdd, 0xae,
- 0xc8, 0x3a, 0x1c, 0x48, 0xc0, 0x5d, 0x10, 0xd9, 0x80, 0xe7, 0x12, 0x1f,
- 0x57, 0xe7, 0xcb, 0x29, 0x2c, 0xe7, 0x4f, 0x4d, 0x95, 0xe5, 0x0d, 0x2b,
- 0xea, 0xcd, 0xca, 0x52, 0xdc, 0x37, 0x84, 0x1d, 0x49, 0xa9, 0x1b, 0xb1,
- 0xeb, 0x3a, 0xd9, 0x47, 0x77, 0xa2, 0xa6, 0xe9, 0x66, 0x45, 0x0f, 0x3f,
- 0x8e, 0xda, 0xe8, 0x3b, 0x9c, 0xc3, 0x2e, 0xe8, 0xe7, 0xd7, 0x21, 0x2b,
- 0xcb, 0xbc, 0x54, 0x56, 0x8e, 0xc5, 0x29, 0x28, 0xb7, 0x27, 0xe1, 0xf1,
- 0x19, 0x55, 0x39, 0x5f, 0x84, 0x72, 0x0b, 0xe7, 0x4f, 0x35, 0xfc, 0xb8,
- 0x85, 0x36, 0xb4, 0x61, 0x97, 0x85, 0x4d, 0xa1, 0x4a, 0xfa, 0x5b, 0x33,
- 0xca, 0x88, 0x87, 0x1b, 0x35, 0x44, 0xcb, 0x23, 0x61, 0xe5, 0xd6, 0xf4,
- 0xce, 0x9c, 0xfe, 0x9f, 0xae, 0xa4, 0x7c, 0x4a, 0x63, 0xf2, 0xf2, 0xeb,
- 0x1f, 0xe5, 0xc7, 0x77, 0xd9, 0xf5, 0xb9, 0x05, 0x9f, 0x5c, 0xbe, 0x56,
- 0x1b, 0x81, 0xc2, 0x78, 0x51, 0x44, 0xfd, 0xea, 0x8c, 0xd2, 0xd1, 0xa0,
- 0xcb, 0xbe, 0xe6, 0xc0, 0x90, 0x33, 0xea, 0x73, 0xe0, 0xf7, 0x56, 0x74,
- 0x95, 0x5c, 0x2b, 0x46, 0xac, 0xb9, 0xd6, 0xe7, 0x44, 0x6d, 0x78, 0x33,
- 0xfd, 0x6d, 0x72, 0x55, 0x03, 0xef, 0x05, 0xcc, 0x93, 0xa8, 0xf1, 0x6f,
- 0x86, 0xfc, 0xfe, 0x90, 0x36, 0xd2, 0x20, 0x75, 0x59, 0x46, 0x6c, 0x4e,
- 0xd7, 0x4e, 0xc2, 0x8b, 0xcd, 0xb4, 0xbf, 0xc2, 0x88, 0x6e, 0x2e, 0x73,
- 0x38, 0x71, 0x88, 0x38, 0xec, 0x30, 0x7a, 0x50, 0xc8, 0x31, 0x32, 0x3e,
- 0xe2, 0xf1, 0x04, 0xf0, 0x62, 0xbf, 0x85, 0x86, 0x90, 0x07, 0x4b, 0x6c,
- 0xdb, 0x3c, 0xaa, 0xdc, 0x98, 0xfc, 0xd8, 0x1a, 0x72, 0x16, 0x45, 0xd5,
- 0x48, 0xc0, 0x77, 0x9a, 0xd1, 0xbc, 0x20, 0x52, 0xab, 0x39, 0x11, 0x57,
- 0x9a, 0xd2, 0xdd, 0xca, 0xf2, 0x74, 0x8f, 0xb2, 0xc4, 0xc6, 0x9c, 0xa3,
- 0xca, 0xd2, 0xb4, 0x07, 0xa9, 0x7e, 0x05, 0x3b, 0x42, 0x94, 0xab, 0x3a,
- 0x6b, 0xc7, 0xe9, 0x7e, 0x95, 0x18, 0xf9, 0x2e, 0x31, 0x52, 0x0f, 0x83,
- 0x7d, 0x3f, 0x9d, 0xa8, 0xc4, 0x51, 0x62, 0xe1, 0x4f, 0x52, 0xe5, 0x2a,
- 0x8a, 0xaf, 0xc0, 0x8f, 0x47, 0xca, 0x30, 0x36, 0x38, 0x8b, 0xbf, 0xeb,
- 0xf0, 0xca, 0x88, 0x65, 0x75, 0x9b, 0x96, 0x75, 0xc0, 0x3c, 0xaa, 0x34,
- 0xb0, 0xcf, 0xa8, 0x33, 0x1e, 0x2d, 0x8c, 0x04, 0xcc, 0xad, 0xec, 0xd3,
- 0x11, 0x89, 0x2b, 0x51, 0xf6, 0x77, 0x23, 0xfb, 0x5b, 0x9a, 0xeb, 0x2f,
- 0xdb, 0xaf, 0xc8, 0x22, 0xf5, 0xf2, 0x75, 0xc2, 0xac, 0x03, 0x1c, 0x4c,
- 0x04, 0x82, 0xf9, 0x7a, 0x4b, 0x59, 0xe7, 0xc6, 0x0b, 0x75, 0x80, 0xe1,
- 0x44, 0x90, 0x73, 0x2a, 0xb6, 0xee, 0x67, 0xec, 0xf9, 0x1a, 0x9c, 0x46,
- 0x3d, 0x5a, 0x87, 0x85, 0x47, 0x84, 0xd5, 0xec, 0x3c, 0x49, 0xfc, 0x74,
- 0xdb, 0x31, 0x6b, 0xd2, 0x21, 0x71, 0x34, 0x88, 0x5e, 0xfa, 0x75, 0x57,
- 0x52, 0x6c, 0xbc, 0xfe, 0xcb, 0x89, 0x80, 0x82, 0x6f, 0x04, 0x32, 0xcd,
- 0xa5, 0x28, 0xc7, 0xba, 0x90, 0xd8, 0xa6, 0xf9, 0xe5, 0xe7, 0x0c, 0x3d,
- 0xbc, 0x42, 0xe1, 0x9c, 0x05, 0xf4, 0xa6, 0xa5, 0x0a, 0x10, 0x18, 0x03,
- 0xce, 0xa4, 0xca, 0xb1, 0xda, 0x74, 0x40, 0xad, 0x08, 0xa2, 0x27, 0x3d,
- 0x15, 0xd7, 0x4d, 0xe2, 0xb4, 0xb4, 0x17, 0xa4, 0x5f, 0x97, 0x60, 0x99,
- 0x96, 0xb5, 0x69, 0x37, 0xdb, 0x76, 0x07, 0x32, 0x41, 0x95, 0xf1, 0xea,
- 0x10, 0x2f, 0x9c, 0x64, 0x5c, 0x6a, 0x30, 0x5c, 0x68, 0xd3, 0xca, 0xd1,
- 0x60, 0xfe, 0xd6, 0x5a, 0xb6, 0x4a, 0xee, 0x5d, 0xc4, 0xf7, 0x42, 0xf6,
- 0xfb, 0xb6, 0xa1, 0xfb, 0x47, 0x79, 0x92, 0x49, 0x65, 0xaf, 0xc7, 0x19,
- 0x73, 0x36, 0xb1, 0xdd, 0x2d, 0x6c, 0x77, 0xad, 0xa6, 0x47, 0xe3, 0x17,
- 0xca, 0x65, 0x82, 0x0e, 0xe8, 0x9a, 0x94, 0x6d, 0x64, 0xbb, 0xab, 0xd9,
- 0x6e, 0x8f, 0x26, 0xf2, 0xfd, 0xd6, 0x5a, 0xbb, 0x4a, 0xee, 0x65, 0xed,
- 0x23, 0xdb, 0x6e, 0xbd, 0xb4, 0x6b, 0x8e, 0xe6, 0xfa, 0x3a, 0x91, 0x40,
- 0xbf, 0x23, 0xc2, 0x18, 0x59, 0x1f, 0xf0, 0x77, 0x31, 0x5e, 0x36, 0x32,
- 0x76, 0x64, 0x6d, 0x62, 0x6a, 0xbc, 0x42, 0xfc, 0x62, 0x19, 0xb9, 0x26,
- 0xe5, 0xc4, 0xd6, 0x26, 0xa9, 0x67, 0x89, 0x2f, 0x3e, 0xea, 0x57, 0xb0,
- 0xc5, 0x89, 0xc3, 0x09, 0xe2, 0x3f, 0xbe, 0x46, 0xbb, 0xf3, 0xa3, 0x39,
- 0x5d, 0x83, 0xb6, 0x5d, 0x8c, 0x63, 0x66, 0x05, 0x6d, 0x3d, 0x6b, 0x6f,
- 0xcb, 0xd8, 0xf6, 0xa4, 0xdd, 0x76, 0x5c, 0x69, 0x4e, 0xd7, 0x6a, 0x15,
- 0x8c, 0x99, 0xc7, 0x2f, 0x60, 0xe7, 0xec, 0x68, 0x71, 0x24, 0xd0, 0xb4,
- 0x9e, 0x93, 0xe4, 0x66, 0x7c, 0xfb, 0xce, 0xbc, 0x6e, 0xda, 0x45, 0x0f,
- 0xed, 0x30, 0x3b, 0xbf, 0x4d, 0x62, 0x70, 0xc4, 0x38, 0xa8, 0x35, 0x58,
- 0xbb, 0x4b, 0xfe, 0x93, 0x6b, 0xd4, 0x3f, 0xca, 0x6b, 0x35, 0x58, 0x3d,
- 0xfc, 0x0d, 0xda, 0x99, 0xee, 0x13, 0x3b, 0xec, 0xba, 0x20, 0x97, 0xc8,
- 0x24, 0xb2, 0x89, 0x4c, 0xff, 0x37, 0xcb, 0xcd, 0xa4, 0x7e, 0x04, 0x1b,
- 0x2b, 0x29, 0xcf, 0x36, 0xf2, 0x99, 0xa3, 0xca, 0x67, 0x29, 0x4f, 0xc6,
- 0xe5, 0xc5, 0x63, 0x49, 0x91, 0x47, 0x89, 0xce, 0x88, 0xcc, 0xc4, 0xf9,
- 0x64, 0x20, 0xfe, 0x34, 0x44, 0xb6, 0x6e, 0xa5, 0x45, 0xea, 0x27, 0x7b,
- 0x78, 0x2f, 0x2f, 0x23, 0xb4, 0x72, 0x5b, 0xb6, 0xac, 0x4c, 0xb7, 0x72,
- 0xae, 0x5d, 0xc6, 0xfd, 0xa5, 0x28, 0x73, 0xd2, 0xd6, 0xa4, 0xed, 0x9f,
- 0x59, 0x51, 0x6d, 0x13, 0xaf, 0x79, 0x39, 0x4f, 0x6e, 0xc6, 0x75, 0x3d,
- 0x78, 0x8b, 0x43, 0x69, 0xf6, 0x48, 0xbc, 0xa6, 0x7d, 0xa6, 0x52, 0x4e,
- 0x3c, 0x93, 0x58, 0xba, 0xb4, 0xc4, 0xb8, 0x1a, 0xdf, 0x18, 0xf1, 0x61,
- 0x84, 0x73, 0xfb, 0x62, 0x42, 0xe2, 0xeb, 0x4c, 0x3c, 0x91, 0xf2, 0xe0,
- 0x85, 0x84, 0x1f, 0x8f, 0x33, 0xfe, 0x4c, 0x24, 0x0c, 0x1c, 0x4a, 0x79,
- 0xf1, 0x3c, 0xed, 0x79, 0x34, 0xe5, 0xa3, 0xbd, 0xd4, 0x61, 0x38, 0xd5,
- 0x6c, 0x8f, 0xe1, 0xd9, 0xc4, 0xab, 0x32, 0xd6, 0xa0, 0x8c, 0x75, 0x8b,
- 0x3d, 0xd6, 0x7c, 0x9c, 0x9f, 0x79, 0x61, 0x1e, 0x4e, 0x25, 0x6c, 0x1c,
- 0xe8, 0x59, 0xe6, 0x90, 0x79, 0xa0, 0xcd, 0x0e, 0x08, 0x16, 0xe8, 0xfd,
- 0x71, 0x58, 0xd8, 0x6f, 0xce, 0xa0, 0xff, 0xf7, 0x50, 0x5e, 0xea, 0x94,
- 0xe3, 0x87, 0xab, 0x2c, 0x5a, 0x1a, 0x09, 0xc4, 0x7a, 0xa9, 0x77, 0x67,
- 0x44, 0xf4, 0x90, 0xd5, 0xfb, 0x8a, 0xf4, 0x51, 0x45, 0xb8, 0xda, 0x95,
- 0x03, 0x71, 0xab, 0xc4, 0x10, 0x7d, 0x07, 0x88, 0xb3, 0xc0, 0xfc, 0xfd,
- 0x4e, 0x8e, 0x6f, 0x25, 0xc7, 0x6c, 0xa2, 0xc0, 0xa8, 0xd5, 0x2a, 0x29,
- 0xfb, 0xf1, 0x3f, 0x88, 0x81, 0xa2, 0xa3, 0x35, 0xb9, 0xf9, 0x2a, 0x77,
- 0x50, 0x5e, 0x3f, 0x90, 0x9f, 0x17, 0xcb, 0xda, 0x69, 0xe6, 0xe7, 0xa6,
- 0x1a, 0xfe, 0x4a, 0x3d, 0x3e, 0x44, 0x8b, 0x18, 0x49, 0x54, 0x21, 0xae,
- 0xa9, 0xb9, 0xb6, 0xa3, 0x4a, 0x01, 0xf3, 0x07, 0x8c, 0x8b, 0xef, 0x97,
- 0x22, 0xea, 0x94, 0xfa, 0x88, 0x16, 0x44, 0x02, 0xc1, 0xb9, 0xea, 0x54,
- 0x9b, 0x11, 0x1c, 0x90, 0xbe, 0xe2, 0x94, 0xf5, 0x52, 0x2c, 0x18, 0x49,
- 0xe4, 0x71, 0xe3, 0x3f, 0x53, 0xcf, 0x4b, 0x1f, 0x9b, 0xaa, 0x53, 0x91,
- 0x53, 0xf4, 0xaa, 0xa2, 0x75, 0x50, 0xf4, 0xe7, 0xc4, 0x4a, 0x73, 0x51,
- 0x4e, 0xe6, 0x99, 0x68, 0x4b, 0xa8, 0xd8, 0x30, 0xc8, 0xbe, 0x52, 0x0a,
- 0x36, 0x87, 0x96, 0x60, 0xc8, 0x6b, 0xd3, 0x45, 0xb4, 0x26, 0x1a, 0x69,
- 0x63, 0xc4, 0x99, 0x71, 0x3b, 0x7e, 0xda, 0xfe, 0x33, 0x9b, 0x3e, 0xb1,
- 0x2c, 0xfd, 0x20, 0xd6, 0x26, 0x03, 0xfe, 0x93, 0x78, 0x10, 0x6d, 0x69,
- 0x17, 0x62, 0xc3, 0x1e, 0x74, 0xb2, 0x6f, 0xb5, 0x4f, 0xfc, 0x49, 0x43,
- 0xe7, 0xe8, 0x89, 0x17, 0x54, 0xda, 0x67, 0xe7, 0xa8, 0x97, 0xc7, 0x34,
- 0x1e, 0x6e, 0x3c, 0xc4, 0xe3, 0x28, 0xe7, 0xbf, 0x83, 0x18, 0x9c, 0x4e,
- 0x98, 0xb8, 0x9f, 0x32, 0x8d, 0x27, 0xea, 0xb1, 0x91, 0xf2, 0x8d, 0x25,
- 0x1c, 0xf0, 0x4f, 0x0b, 0xe3, 0x3e, 0xea, 0xf2, 0xc9, 0x44, 0x58, 0x79,
- 0x80, 0xff, 0x0f, 0x51, 0x26, 0xc9, 0x47, 0xd6, 0xd1, 0x0e, 0xa2, 0xd3,
- 0x68, 0x27, 0x6a, 0xad, 0xc3, 0x9e, 0x07, 0x88, 0x7f, 0x5c, 0x3e, 0x57,
- 0xba, 0x16, 0x43, 0x7e, 0xbe, 0x80, 0xa1, 0x14, 0x62, 0xee, 0x48, 0x5d,
- 0x63, 0x41, 0x6f, 0xeb, 0x86, 0xc2, 0x48, 0xfb, 0x43, 0x3f, 0xad, 0x9f,
- 0x85, 0x93, 0x9c, 0x13, 0xa7, 0x6d, 0xe3, 0x51, 0xc5, 0x65, 0x18, 0xb6,
- 0x2f, 0xab, 0xe3, 0xed, 0xb9, 0xbc, 0x4a, 0x97, 0x38, 0xc6, 0x3e, 0x44,
- 0x6f, 0xa2, 0x0b, 0xd1, 0xc3, 0x71, 0x6b, 0xc8, 0xf6, 0x77, 0xf1, 0x39,
- 0x27, 0x75, 0xf4, 0x5d, 0xc6, 0x6f, 0xd1, 0x85, 0x94, 0xdb, 0xca, 0xb6,
- 0x44, 0x1e, 0x3b, 0x16, 0xfa, 0xfe, 0xd0, 0x76, 0xa6, 0xca, 0x53, 0x87,
- 0xed, 0x7b, 0x0c, 0xec, 0xd8, 0x53, 0x4b, 0xbb, 0xfb, 0xa5, 0xe5, 0xaf,
- 0x18, 0x60, 0xdd, 0xa9, 0xb2, 0x08, 0x2f, 0x40, 0xae, 0x5d, 0x69, 0x73,
- 0x13, 0xef, 0x1d, 0xa6, 0xad, 0x49, 0xbb, 0x96, 0xb5, 0xe5, 0x42, 0xdc,
- 0x28, 0x88, 0x16, 0x31, 0x6e, 0x1c, 0x4a, 0x04, 0xc2, 0x2f, 0xd8, 0xb1,
- 0xcd, 0x49, 0xdb, 0x90, 0xf9, 0xef, 0xb6, 0xe7, 0x7e, 0xd9, 0x85, 0xb9,
- 0x9f, 0xbc, 0xc0, 0x91, 0xfa, 0x93, 0x53, 0x7d, 0x2a, 0x3b, 0xef, 0xce,
- 0x3e, 0xbd, 0xc7, 0xb6, 0xd3, 0x94, 0xe0, 0x9f, 0x03, 0x8e, 0x01, 0xce,
- 0xb3, 0x79, 0x15, 0xc7, 0x5f, 0xc9, 0x78, 0x52, 0xc0, 0x83, 0x79, 0xe4,
- 0xf0, 0xa7, 0x50, 0x3c, 0x90, 0xb1, 0x8a, 0xf8, 0xbb, 0x29, 0x14, 0x08,
- 0x17, 0x29, 0x37, 0xe0, 0xee, 0x61, 0x07, 0x0a, 0x06, 0x14, 0x3c, 0x6b,
- 0xd6, 0xe5, 0xec, 0x43, 0xe6, 0xfb, 0x2a, 0xdb, 0x3e, 0xe6, 0x8c, 0xcb,
- 0x7c, 0xcb, 0x1c, 0x7b, 0xe0, 0xeb, 0x53, 0xe0, 0x21, 0x6e, 0x94, 0x18,
- 0x32, 0xd7, 0x1a, 0xca, 0xfb, 0x64, 0xae, 0x49, 0x1b, 0x77, 0x87, 0xb1,
- 0x91, 0xf6, 0x50, 0xba, 0xfb, 0x7a, 0xdc, 0xc7, 0x72, 0x1b, 0x78, 0x6f,
- 0xc3, 0x68, 0x25, 0x0f, 0x2f, 0x8f, 0x69, 0x3c, 0xea, 0x71, 0xef, 0x70,
- 0x0d, 0xa2, 0x95, 0x7a, 0xd0, 0xaf, 0x3a, 0x50, 0x39, 0x20, 0x3a, 0x55,
- 0xb1, 0x72, 0x81, 0x02, 0xf3, 0xea, 0x42, 0xa8, 0x73, 0x3f, 0xc9, 0x37,
- 0xff, 0x9c, 0xac, 0x3f, 0x9a, 0x32, 0x87, 0x6e, 0x8e, 0xfd, 0x9f, 0xed,
- 0x39, 0x9c, 0x33, 0x2e, 0x7d, 0x48, 0x2c, 0xb5, 0xe7, 0xf1, 0x4f, 0xf8,
- 0xfe, 0x73, 0x9c, 0x8f, 0x2e, 0x96, 0xf9, 0xc3, 0xf9, 0xc5, 0x85, 0xf9,
- 0x9d, 0xca, 0x49, 0x25, 0xae, 0xeb, 0xe1, 0x21, 0x9b, 0xc3, 0xf8, 0x99,
- 0xcf, 0xe9, 0x71, 0xd1, 0x39, 0x39, 0x8b, 0x5b, 0x35, 0xe0, 0x2f, 0x30,
- 0xee, 0xc0, 0x3d, 0x9c, 0xa7, 0x03, 0x09, 0x75, 0xa9, 0x0b, 0xea, 0x4c,
- 0x17, 0x13, 0xdb, 0x11, 0x53, 0xc7, 0xba, 0x61, 0xe6, 0x4a, 0xc3, 0xa5,
- 0xe8, 0xd2, 0x14, 0xf7, 0xf6, 0xba, 0x45, 0x92, 0xf3, 0xfa, 0xcb, 0x0d,
- 0xa8, 0x25, 0x8c, 0xef, 0x3b, 0x34, 0x38, 0x0b, 0x0c, 0x45, 0x4d, 0xd4,
- 0x35, 0x22, 0x5e, 0x01, 0x67, 0x99, 0x01, 0x85, 0x39, 0x2d, 0x7a, 0x35,
- 0x08, 0xb6, 0x44, 0x0b, 0x8c, 0x07, 0x71, 0x4f, 0x12, 0x56, 0x71, 0x84,
- 0xf9, 0x4e, 0xc4, 0x20, 0x87, 0x0d, 0xf8, 0x0a, 0x94, 0x07, 0xb1, 0x9a,
- 0xbc, 0x61, 0xcd, 0xb0, 0xc8, 0xe1, 0x21, 0x9f, 0x30, 0xfc, 0xad, 0x60,
- 0x8e, 0xdd, 0xac, 0x07, 0x27, 0x99, 0x67, 0xae, 0xa6, 0xee, 0x47, 0x12,
- 0x0f, 0xa2, 0x21, 0x79, 0xdc, 0xf2, 0x90, 0x27, 0x16, 0x18, 0x35, 0xe7,
- 0xbb, 0x10, 0xa3, 0x0f, 0x0b, 0xff, 0x69, 0xc3, 0x43, 0xf4, 0xbf, 0x74,
- 0x42, 0x7d, 0x86, 0xec, 0x01, 0x1d, 0xa3, 0xeb, 0x71, 0xff, 0xe8, 0x4c,
- 0xfa, 0xea, 0x06, 0xfa, 0x2a, 0xb9, 0x50, 0xff, 0x0d, 0xb8, 0x6f, 0xf8,
- 0x06, 0xdc, 0xbb, 0xcb, 0x08, 0x6e, 0xa0, 0xae, 0xd7, 0x0c, 0x33, 0x10,
- 0x4e, 0x93, 0x76, 0xf3, 0xba, 0x12, 0x3e, 0x48, 0x5d, 0xe4, 0xf4, 0x94,
- 0x41, 0x9e, 0xa3, 0xfc, 0xb3, 0xc5, 0x4b, 0xf1, 0x82, 0x7a, 0xc5, 0xbf,
- 0xb7, 0xee, 0xfb, 0xcc, 0xbd, 0x45, 0x76, 0x44, 0x67, 0x18, 0xaf, 0x5a,
- 0x8f, 0x6a, 0x0a, 0x0a, 0x22, 0x88, 0xcf, 0xae, 0x7f, 0xd9, 0x7a, 0x6c,
- 0x95, 0x5c, 0xbf, 0xd5, 0x89, 0x62, 0x95, 0xd7, 0xa4, 0xcd, 0x1d, 0x32,
- 0x47, 0x44, 0xda, 0x4f, 0x6a, 0x33, 0x63, 0xf5, 0x5d, 0x28, 0x4f, 0xde,
- 0x47, 0xac, 0x7d, 0x3a, 0xe1, 0x45, 0x4f, 0x32, 0xcb, 0x9d, 0x6e, 0x4f,
- 0x0b, 0x67, 0x72, 0xa3, 0xb8, 0x57, 0xe2, 0x46, 0x14, 0xeb, 0xf9, 0xbb,
- 0xa8, 0x57, 0x6f, 0x8e, 0x83, 0xc9, 0xbc, 0xd1, 0xc8, 0xb9, 0xa0, 0xbd,
- 0xf6, 0x3a, 0x50, 0x64, 0x34, 0x65, 0x6d, 0xb5, 0x77, 0x85, 0x8d, 0x4b,
- 0x65, 0xbd, 0xdd, 0x36, 0x2e, 0x95, 0xb2, 0x9e, 0x60, 0x92, 0xa7, 0x77,
- 0x15, 0xed, 0x75, 0x26, 0x4a, 0x7a, 0x5b, 0x70, 0x2f, 0xe7, 0x78, 0x2d,
- 0x79, 0xf6, 0x09, 0xb3, 0x3c, 0xc7, 0x3f, 0x9b, 0x70, 0x77, 0x32, 0x8a,
- 0xd6, 0x64, 0x4d, 0xf4, 0xb4, 0xac, 0x25, 0xb9, 0xb2, 0xd8, 0x19, 0xad,
- 0x16, 0x5d, 0x3c, 0x97, 0xc3, 0x08, 0xbd, 0x29, 0xcb, 0xd9, 0x74, 0xcd,
- 0xaf, 0xe4, 0x65, 0xef, 0x46, 0x8c, 0xf9, 0xc5, 0xec, 0x48, 0x33, 0xac,
- 0xa4, 0xc8, 0x1d, 0xb7, 0x7c, 0xcc, 0x19, 0x3d, 0x11, 0xbd, 0x7d, 0xb1,
- 0xc3, 0xe8, 0xf8, 0xb1, 0x12, 0xc4, 0xad, 0x94, 0xa1, 0xa4, 0xb7, 0x13,
- 0xaf, 0x84, 0x74, 0xdf, 0xb7, 0x15, 0xfd, 0xfc, 0x06, 0xfc, 0x18, 0x3f,
- 0xe7, 0xb5, 0x82, 0xde, 0x09, 0x3c, 0x96, 0x7e, 0x1d, 0x67, 0x29, 0xab,
- 0xda, 0xfb, 0xb1, 0xb5, 0xcc, 0x20, 0x18, 0x14, 0xbb, 0x95, 0xb7, 0xd3,
- 0x53, 0x6d, 0xf1, 0x06, 0xac, 0xde, 0x25, 0xf6, 0xa7, 0x07, 0xe3, 0xa0,
- 0x7c, 0x66, 0x99, 0x60, 0x9c, 0xc4, 0x1f, 0xca, 0xdf, 0x4c, 0xd9, 0x2c,
- 0xfa, 0x07, 0xed, 0xc0, 0x1e, 0xc3, 0x43, 0x36, 0x0e, 0x3a, 0xfb, 0xe4,
- 0xc8, 0xeb, 0x39, 0xa2, 0xb4, 0x8e, 0x5e, 0x53, 0x8c, 0x62, 0x5f, 0xce,
- 0x0f, 0xb2, 0x6b, 0x0a, 0x17, 0xeb, 0xfe, 0xd2, 0x1a, 0xf1, 0x5e, 0x5a,
- 0xb7, 0x8c, 0x39, 0x56, 0x39, 0xc7, 0xf3, 0x5e, 0x6f, 0xdc, 0x2a, 0xce,
- 0x8e, 0xa5, 0xe9, 0x55, 0x45, 0x6c, 0x32, 0x48, 0xee, 0xde, 0x89, 0xab,
- 0x42, 0x7a, 0xcb, 0xb7, 0x15, 0x29, 0xab, 0x87, 0x37, 0x28, 0xf9, 0x7e,
- 0x7e, 0x84, 0xd3, 0x23, 0xd2, 0x87, 0xf4, 0x35, 0xc1, 0x9c, 0xeb, 0x52,
- 0x7f, 0x4a, 0xd9, 0xf3, 0xa9, 0x9b, 0x43, 0xe4, 0x75, 0x2b, 0x38, 0xcc,
- 0x92, 0x5e, 0x19, 0x93, 0xa9, 0xdc, 0x3b, 0x2a, 0xf3, 0xba, 0x40, 0x59,
- 0x4f, 0x2c, 0x29, 0xea, 0xad, 0x57, 0xee, 0x21, 0x96, 0x14, 0xee, 0xac,
- 0x51, 0xee, 0xb6, 0x6d, 0xbe, 0x0a, 0x23, 0xfd, 0xd7, 0x28, 0x6d, 0xc3,
- 0xa2, 0x03, 0x37, 0xc7, 0x3e, 0x8d, 0x63, 0xf7, 0xa2, 0x8f, 0xfe, 0xfb,
- 0x4a, 0x6f, 0x9d, 0x72, 0x1f, 0x7d, 0xa3, 0x73, 0x97, 0x8a, 0xc9, 0x2a,
- 0x85, 0x78, 0x47, 0xfe, 0x6b, 0xf8, 0x94, 0xd6, 0xe1, 0xef, 0x3b, 0x25,
- 0xbe, 0x64, 0x70, 0x03, 0x5a, 0x79, 0x6f, 0xa9, 0xe9, 0x42, 0x46, 0xab,
- 0xd5, 0x34, 0xac, 0xc0, 0xea, 0xe4, 0x2a, 0xb4, 0x25, 0x8b, 0xc9, 0x73,
- 0x65, 0xbc, 0x79, 0xb9, 0xf3, 0xf3, 0xf8, 0x20, 0x5a, 0x92, 0x88, 0xcf,
- 0x88, 0x04, 0x3a, 0x66, 0x38, 0xe8, 0xd2, 0xc5, 0x75, 0xca, 0xfd, 0xe9,
- 0x1a, 0x65, 0xcd, 0xae, 0x72, 0x64, 0xb1, 0xe7, 0x61, 0x34, 0xed, 0xa9,
- 0x57, 0xee, 0xde, 0x53, 0x85, 0x49, 0xcd, 0xb2, 0x9c, 0xa1, 0x7a, 0xa5,
- 0x75, 0x8f, 0x65, 0xdd, 0x64, 0x46, 0x9b, 0x8a, 0xc9, 0x77, 0xb7, 0xb1,
- 0xbd, 0xd6, 0x51, 0xe9, 0xe7, 0xf2, 0x76, 0x4d, 0x65, 0xe3, 0x9e, 0x87,
- 0xb1, 0x82, 0x65, 0x5f, 0x09, 0x45, 0x5b, 0x4a, 0x59, 0x56, 0x74, 0xd6,
- 0x3a, 0xfa, 0x19, 0xf6, 0x21, 0xe5, 0x17, 0x4c, 0x69, 0x67, 0x31, 0xaf,
- 0x49, 0x5b, 0x59, 0xdd, 0x89, 0xde, 0x1e, 0xcf, 0xea, 0x2d, 0x2c, 0x7a,
- 0x5b, 0x4e, 0x5d, 0xba, 0x7a, 0x7d, 0x3c, 0x5c, 0xf4, 0x75, 0x1f, 0xd6,
- 0xa4, 0x65, 0x4c, 0x33, 0x89, 0x03, 0xcd, 0xb4, 0xdb, 0x76, 0xb4, 0x52,
- 0xaf, 0x71, 0x2d, 0x6b, 0x9f, 0x17, 0x7d, 0x4b, 0xf7, 0x4f, 0x72, 0xec,
- 0xad, 0x49, 0xd1, 0x4b, 0x33, 0xcb, 0xdb, 0xf7, 0xe9, 0xdb, 0x53, 0xcb,
- 0x5c, 0x3a, 0x57, 0xfb, 0x13, 0xc2, 0x27, 0x0a, 0xc8, 0x7d, 0x0a, 0xd8,
- 0x5e, 0x96, 0x2b, 0x8a, 0xbd, 0x38, 0x68, 0x2f, 0xcf, 0x98, 0xc5, 0xd8,
- 0xe4, 0x95, 0x31, 0x66, 0xf5, 0x0c, 0x15, 0x58, 0xc7, 0x7b, 0x2e, 0xde,
- 0x2b, 0x0c, 0x15, 0xe2, 0x2d, 0x5b, 0x57, 0x59, 0x3e, 0x98, 0xf7, 0xf3,
- 0xa1, 0x0b, 0xfd, 0x1c, 0xab, 0xce, 0xda, 0xd8, 0x26, 0x57, 0x96, 0x33,
- 0xe6, 0xb9, 0x8d, 0x65, 0x0d, 0x98, 0x79, 0x6e, 0x23, 0x71, 0xee, 0x53,
- 0xc2, 0x15, 0x6c, 0x1e, 0xd6, 0x96, 0xeb, 0xb7, 0xcb, 0x0c, 0xd0, 0x4f,
- 0x85, 0xfb, 0x45, 0x94, 0xb6, 0x3d, 0xa7, 0x68, 0xab, 0x92, 0x8b, 0x01,
- 0x1b, 0x79, 0xbf, 0x94, 0xf7, 0x5f, 0x0b, 0xb9, 0x70, 0xd5, 0x34, 0xe9,
- 0xfb, 0x06, 0x74, 0xec, 0x8a, 0xa2, 0x7c, 0x61, 0x00, 0x93, 0xf6, 0x7a,
- 0x59, 0x9e, 0xa7, 0xbb, 0x70, 0xdf, 0xae, 0x8f, 0xad, 0x32, 0x9b, 0x3b,
- 0x1a, 0xb1, 0x71, 0x45, 0xc5, 0x8e, 0x45, 0xc2, 0xd7, 0x5d, 0x8c, 0x57,
- 0xe4, 0xce, 0x92, 0x0b, 0xb8, 0x4a, 0xc8, 0xb9, 0x85, 0x73, 0x06, 0x32,
- 0xb7, 0xab, 0xd0, 0xb4, 0x88, 0x70, 0xcf, 0x99, 0x36, 0xe7, 0x16, 0xee,
- 0xfd, 0xcd, 0xe4, 0xd1, 0x29, 0xdc, 0xfb, 0x02, 0x4f, 0x61, 0xae, 0xd6,
- 0x8c, 0x44, 0xaf, 0x07, 0xee, 0x88, 0xde, 0xbc, 0x59, 0xe9, 0xc4, 0xf2,
- 0x90, 0x61, 0xca, 0x1a, 0xc0, 0xf5, 0x8a, 0x1e, 0x3c, 0x87, 0x20, 0xe3,
- 0xc7, 0x8f, 0x30, 0x32, 0xf8, 0x0f, 0x2e, 0xf1, 0x8b, 0xcd, 0xe9, 0x8b,
- 0xf2, 0xdc, 0x4d, 0x79, 0xdc, 0x59, 0x79, 0xcc, 0x73, 0x54, 0xe4, 0xb3,
- 0xf5, 0x2e, 0xe2, 0xf0, 0x7f, 0xb7, 0xed, 0x76, 0x89, 0x9d, 0x4b, 0xfc,
- 0x77, 0xc6, 0x93, 0x70, 0x71, 0x5e, 0xcf, 0x9d, 0xc4, 0xab, 0x0f, 0x17,
- 0x16, 0x21, 0x44, 0x7b, 0xaf, 0x30, 0x3a, 0x98, 0xcf, 0x7f, 0x6c, 0xc5,
- 0x9d, 0xa4, 0xdf, 0x06, 0xb4, 0xa2, 0x48, 0x94, 0xb2, 0x35, 0x2a, 0x37,
- 0x0d, 0x8f, 0xb3, 0x9f, 0x0e, 0xe6, 0x29, 0x1e, 0x3c, 0x40, 0x5c, 0x79,
- 0x80, 0xfe, 0xf4, 0x00, 0x63, 0xf3, 0x03, 0xa3, 0xff, 0x8b, 0xd7, 0xa7,
- 0xd9, 0xbf, 0x37, 0x27, 0xf3, 0xf6, 0xe5, 0x64, 0x9c, 0x13, 0xfd, 0x6e,
- 0x21, 0x16, 0x48, 0x9c, 0x03, 0x65, 0xb2, 0x70, 0xda, 0x2c, 0xa4, 0xae,
- 0xf5, 0x60, 0x06, 0x09, 0xd7, 0xc5, 0x3c, 0x35, 0x1f, 0x2b, 0x65, 0x1e,
- 0x5d, 0xb8, 0x87, 0x32, 0x06, 0x43, 0xbf, 0xb1, 0x50, 0x21, 0x58, 0x74,
- 0xf9, 0xfd, 0xec, 0xbc, 0x1e, 0xbf, 0xc0, 0x59, 0x15, 0xc9, 0x91, 0xe8,
- 0xef, 0xfd, 0x36, 0x07, 0x7b, 0x8d, 0x3e, 0xd9, 0xb6, 0xeb, 0xc4, 0x7c,
- 0x31, 0x95, 0x35, 0xa3, 0x51, 0x6c, 0xe2, 0xb8, 0x57, 0x0f, 0x3f, 0x9a,
- 0xd3, 0x4b, 0x7e, 0xbc, 0xe2, 0xd3, 0x1e, 0xda, 0x74, 0x36, 0xb7, 0x6a,
- 0x1d, 0x15, 0x2e, 0x5e, 0xc9, 0xff, 0xc2, 0xc5, 0xc5, 0x7f, 0x84, 0x97,
- 0x4f, 0xe3, 0x7f, 0x27, 0x39, 0xa7, 0x70, 0xe9, 0x3a, 0xf4, 0xd0, 0x8f,
- 0x0a, 0x03, 0x75, 0xd8, 0x3a, 0x7a, 0xf9, 0x1c, 0x5d, 0x2e, 0x8f, 0x3d,
- 0x07, 0xcc, 0xc3, 0x5c, 0x82, 0xad, 0x7e, 0xbf, 0x2a, 0x7d, 0x5b, 0x68,
- 0x37, 0x6f, 0xc8, 0x72, 0xa7, 0x4a, 0xb9, 0x36, 0x95, 0x9f, 0xe7, 0xdb,
- 0x99, 0x7a, 0x4d, 0x2d, 0x40, 0x71, 0x9e, 0x37, 0x78, 0x73, 0xb9, 0x0e,
- 0xf3, 0x9b, 0xa4, 0xe8, 0x4b, 0xc6, 0x90, 0xcd, 0x5f, 0xc5, 0x5e, 0x2e,
- 0xc5, 0x83, 0xf8, 0xb4, 0x22, 0x43, 0x6c, 0x25, 0x48, 0x7f, 0xd6, 0xc3,
- 0x4d, 0x0c, 0x35, 0x67, 0x13, 0x88, 0x39, 0x22, 0x4d, 0x8d, 0x6b, 0x12,
- 0x73, 0xb5, 0x67, 0x72, 0xf9, 0xf1, 0x7e, 0xc6, 0x1e, 0xd5, 0x90, 0xb5,
- 0x19, 0xda, 0xc3, 0xb0, 0xe8, 0xa7, 0x43, 0xb9, 0x98, 0x0b, 0x47, 0xc9,
- 0x15, 0x19, 0x57, 0x0d, 0xc9, 0x91, 0x1a, 0x95, 0xa5, 0xc3, 0x52, 0x87,
- 0xf6, 0x70, 0x19, 0x67, 0xcc, 0x8e, 0xb7, 0x0c, 0x9e, 0x01, 0xe1, 0x8a,
- 0x3a, 0x36, 0x90, 0x9b, 0x94, 0x0c, 0xf8, 0x69, 0xef, 0x95, 0x28, 0xde,
- 0x1d, 0xc1, 0xfa, 0x51, 0x0d, 0x45, 0xbb, 0x2d, 0x6b, 0x6e, 0xa8, 0x1b,
- 0x6b, 0xd3, 0xcb, 0x0b, 0x24, 0x9f, 0x73, 0xf6, 0x11, 0x2b, 0x88, 0x2b,
- 0xeb, 0x92, 0x0a, 0x6e, 0x24, 0x07, 0x88, 0xa2, 0x99, 0xdc, 0x5d, 0xf0,
- 0xc5, 0xea, 0x9c, 0x1d, 0x71, 0xd1, 0x4e, 0x56, 0xf1, 0x7e, 0x0b, 0xb1,
- 0xa7, 0x85, 0x58, 0x62, 0x59, 0x1f, 0x5e, 0x8b, 0xce, 0x92, 0xc8, 0x1d,
- 0xc4, 0xa0, 0x1a, 0xe6, 0x0f, 0xc2, 0x39, 0xae, 0x45, 0x1b, 0xb1, 0xbb,
- 0xb0, 0xcf, 0xce, 0xf1, 0xa8, 0x47, 0xc6, 0xd5, 0x34, 0xe3, 0x32, 0x65,
- 0x7f, 0x9e, 0x7c, 0xbd, 0x83, 0x7e, 0x54, 0xde, 0xb7, 0x81, 0xf1, 0xd9,
- 0x83, 0xb2, 0x81, 0x6b, 0xb0, 0x91, 0xd8, 0x7e, 0xdf, 0x2e, 0x3f, 0x52,
- 0x8b, 0x6e, 0xa0, 0x7c, 0x0f, 0x62, 0x7d, 0xd2, 0x90, 0xbc, 0x2e, 0x1a,
- 0x5c, 0xf4, 0x20, 0xfb, 0xa5, 0x7d, 0xec, 0x92, 0x1c, 0xb1, 0x04, 0x4b,
- 0x9a, 0x81, 0x60, 0x9f, 0x60, 0x8e, 0x8c, 0xff, 0x36, 0x59, 0xcf, 0x82,
- 0xd1, 0x37, 0x75, 0x3e, 0xa6, 0x72, 0x39, 0x59, 0x1b, 0x6c, 0xc6, 0x7c,
- 0xc6, 0x2f, 0xb1, 0x21, 0x8d, 0x79, 0x6f, 0x91, 0x62, 0xf8, 0xf6, 0xd3,
- 0x17, 0x25, 0x17, 0xbb, 0xae, 0x2f, 0x1f, 0xaf, 0xf5, 0xcc, 0x62, 0x47,
- 0x27, 0xb1, 0x42, 0x6f, 0xff, 0xad, 0xa2, 0xaf, 0x3b, 0xa5, 0xfc, 0x18,
- 0x07, 0xc7, 0x5e, 0xc7, 0xd0, 0x98, 0x5b, 0x19, 0x1d, 0x93, 0xbe, 0x26,
- 0xd0, 0x9b, 0xfe, 0x73, 0x7d, 0x4d, 0x5d, 0x13, 0x5a, 0x74, 0xc9, 0x3a,
- 0xd2, 0x8d, 0xb9, 0xdc, 0x75, 0xe9, 0x25, 0x9c, 0x5e, 0xe6, 0x44, 0x6c,
- 0xcf, 0x8b, 0xee, 0xe4, 0xc5, 0xb5, 0x8a, 0xfe, 0xc4, 0x76, 0xdb, 0x07,
- 0x9b, 0xd3, 0x62, 0x93, 0xcc, 0xef, 0xcc, 0x39, 0xf6, 0xb3, 0x1b, 0x59,
- 0x5f, 0x58, 0xb3, 0xab, 0xd7, 0xbe, 0x77, 0xd0, 0xfc, 0x2b, 0x64, 0xec,
- 0x6b, 0x8b, 0xe9, 0x7f, 0x8c, 0x93, 0xc4, 0xbd, 0x60, 0xc8, 0x87, 0xc2,
- 0x0a, 0x59, 0x5b, 0xba, 0xb8, 0x1e, 0xb1, 0x61, 0x17, 0x69, 0x84, 0x8d,
- 0x2b, 0x0d, 0xc4, 0xb8, 0x1a, 0xce, 0x77, 0x16, 0x4b, 0xd6, 0xd3, 0x86,
- 0x6e, 0x11, 0x1b, 0x72, 0x65, 0x6d, 0xe8, 0x0f, 0xd7, 0x3c, 0x54, 0x90,
- 0xaf, 0x6a, 0x65, 0x76, 0x2e, 0xda, 0xa8, 0xdc, 0x9a, 0xb3, 0xab, 0xcf,
- 0xa6, 0xbf, 0x53, 0x90, 0xcb, 0x91, 0x2e, 0x2b, 0xff, 0x49, 0x3a, 0xb8,
- 0xe6, 0x2f, 0xd0, 0x81, 0x60, 0xbe, 0xe4, 0x31, 0xa2, 0x83, 0x99, 0x53,
- 0xfc, 0xf2, 0x93, 0xf4, 0x50, 0x9b, 0xd3, 0xc3, 0x62, 0x62, 0x48, 0x25,
- 0x71, 0x4f, 0x38, 0x4b, 0x00, 0x4f, 0x6a, 0x79, 0x3d, 0x38, 0x73, 0x7a,
- 0xd0, 0xff, 0x40, 0x0f, 0xf7, 0x13, 0x5f, 0x4b, 0xd9, 0x56, 0x31, 0x8f,
- 0x77, 0xa9, 0x87, 0x8d, 0xc3, 0x8b, 0xf1, 0x00, 0x7d, 0x69, 0x83, 0xbd,
- 0x5e, 0x23, 0xcf, 0xef, 0x5c, 0x97, 0xe8, 0x66, 0x25, 0xe5, 0xf7, 0x17,
- 0xa8, 0x98, 0x41, 0x1d, 0xf8, 0x6c, 0x3c, 0x95, 0x3e, 0x1a, 0x95, 0xdb,
- 0x87, 0x05, 0xe3, 0x3e, 0xa6, 0x0e, 0x3a, 0x18, 0x07, 0xfe, 0x54, 0x9e,
- 0x21, 0xfd, 0x7f, 0x7c, 0x41, 0x57, 0x7f, 0xbc, 0xdc, 0x8f, 0xa9, 0x03,
- 0x79, 0x26, 0x22, 0x6b, 0xec, 0xf2, 0x7c, 0x44, 0xf4, 0x61, 0x4c, 0xd1,
- 0x83, 0x65, 0x1d, 0x31, 0xe7, 0x21, 0x56, 0xa9, 0xf7, 0x4b, 0x1c, 0xed,
- 0x27, 0xa6, 0x38, 0x98, 0xb7, 0x17, 0x44, 0xa2, 0x14, 0x5b, 0xbd, 0x81,
- 0x4c, 0xa7, 0xce, 0x81, 0x4e, 0x9c, 0x31, 0x8d, 0x9e, 0xb5, 0xf8, 0x2b,
- 0x74, 0x79, 0x2d, 0x1c, 0x60, 0x3b, 0x9b, 0x92, 0x45, 0x58, 0x57, 0x47,
- 0xd3, 0x5c, 0xe9, 0xc1, 0xce, 0x64, 0xbc, 0x85, 0xd0, 0xc2, 0xd8, 0x74,
- 0xe6, 0xf6, 0x44, 0x40, 0x6f, 0xde, 0x40, 0xbe, 0xb6, 0xbc, 0xd7, 0x0d,
- 0xbf, 0x92, 0x8d, 0xcf, 0x03, 0xaa, 0xac, 0x7f, 0x5e, 0xc9, 0xb1, 0x77,
- 0xdb, 0x79, 0xac, 0x7f, 0x9a, 0xf4, 0xe3, 0x47, 0x3c, 0x2d, 0x75, 0xa9,
- 0xb3, 0xb9, 0x0a, 0x96, 0xcf, 0xd5, 0xe3, 0x51, 0xc5, 0xb2, 0x16, 0x84,
- 0x9c, 0xf6, 0xfd, 0xed, 0xe9, 0xda, 0x96, 0xdb, 0xd4, 0xd7, 0xad, 0xec,
- 0x9a, 0xab, 0xae, 0x45, 0x99, 0x0c, 0x1d, 0xff, 0xa3, 0xcf, 0x1d, 0x82,
- 0x90, 0xe7, 0x41, 0x6e, 0x63, 0x25, 0x0e, 0xe5, 0xd6, 0x1d, 0x5d, 0x91,
- 0xc3, 0x5f, 0x3e, 0x60, 0x48, 0xbe, 0x26, 0x7a, 0x92, 0xfe, 0xc4, 0x9e,
- 0x1e, 0x28, 0x14, 0x1c, 0xed, 0x4a, 0x2f, 0xe4, 0x3c, 0xfe, 0x87, 0x35,
- 0xea, 0x9d, 0x5a, 0x76, 0x89, 0x9a, 0x7d, 0x8e, 0x20, 0x65, 0xf3, 0xe5,
- 0xe6, 0x10, 0x57, 0x1a, 0x30, 0x7c, 0x49, 0x9b, 0x92, 0x6f, 0xe7, 0xdb,
- 0xec, 0x2d, 0x14, 0x5e, 0x55, 0x81, 0x42, 0xe2, 0xe3, 0x6f, 0xac, 0x83,
- 0x97, 0xb4, 0xb7, 0xd1, 0x95, 0x6d, 0x6f, 0x0f, 0xcb, 0x48, 0xd9, 0x02,
- 0xd6, 0x79, 0x37, 0xc7, 0x7f, 0xf3, 0x65, 0x3e, 0x77, 0x59, 0x19, 0x66,
- 0x78, 0xc6, 0x5b, 0xd6, 0xfe, 0x4b, 0xca, 0x7c, 0xda, 0x79, 0x69, 0x19,
- 0x27, 0x66, 0x1b, 0xaf, 0x5b, 0xc7, 0x2f, 0x29, 0x33, 0x70, 0x59, 0x99,
- 0x6b, 0x31, 0x56, 0xf7, 0xb8, 0x35, 0x94, 0x9d, 0x9b, 0x0c, 0x5d, 0xd0,
- 0x3d, 0x23, 0xe2, 0xfe, 0xd2, 0x75, 0xf3, 0x74, 0xf2, 0x4d, 0x79, 0x16,
- 0xe5, 0x46, 0x26, 0x3b, 0x37, 0x71, 0x99, 0x1b, 0xd7, 0x82, 0xfc, 0xdc,
- 0x3c, 0x90, 0xab, 0x9f, 0x6f, 0x37, 0x56, 0x70, 0x69, 0xbb, 0xf9, 0xeb,
- 0x8e, 0xcb, 0xe4, 0x9e, 0xb8, 0xac, 0x5c, 0x51, 0xe1, 0x27, 0xd7, 0xfb,
- 0x81, 0xe3, 0xd2, 0xeb, 0xff, 0x43, 0xbd, 0xf4, 0xfc, 0x9a, 0xdc, 0x79,
- 0x5e, 0xff, 0xd6, 0x65, 0xf7, 0x1d, 0x97, 0x9d, 0x3f, 0xa3, 0x7e, 0x72,
- 0x3f, 0xab, 0x2e, 0xeb, 0xc7, 0x5e, 0x83, 0xc7, 0x73, 0x17, 0x70, 0x03,
- 0x8d, 0x05, 0x08, 0x98, 0x4e, 0x05, 0x7e, 0xe2, 0x87, 0xff, 0xf9, 0xcb,
- 0xd6, 0xe2, 0x1b, 0x2f, 0xe0, 0xc7, 0x25, 0x5c, 0x35, 0x56, 0x18, 0x91,
- 0x38, 0x28, 0x3c, 0x55, 0xf8, 0xe2, 0x27, 0xf1, 0xef, 0xb2, 0x58, 0x51,
- 0xa4, 0x1e, 0xfe, 0xb1, 0x99, 0xfe, 0xb7, 0x12, 0xb2, 0x1e, 0xfb, 0x7b,
- 0x72, 0x2e, 0xc3, 0x77, 0x08, 0x33, 0xfd, 0x3f, 0x4d, 0x95, 0xb8, 0x51,
- 0xe6, 0xc1, 0x8d, 0x89, 0x4f, 0xae, 0xa7, 0x46, 0xa0, 0x2c, 0xab, 0xf7,
- 0x31, 0xaf, 0x84, 0xf3, 0xa6, 0x79, 0x98, 0xf2, 0xd7, 0x2c, 0x79, 0xae,
- 0x7a, 0xb2, 0x3e, 0xcc, 0x18, 0x9f, 0x7d, 0x8e, 0xbc, 0x24, 0xad, 0xfb,
- 0xa2, 0x4a, 0xf6, 0x59, 0xf1, 0xba, 0xd0, 0x47, 0xe4, 0x45, 0x9d, 0x94,
- 0xcb, 0x62, 0x5f, 0xc0, 0x86, 0x84, 0x65, 0x3d, 0xc7, 0xfc, 0x5c, 0xf6,
- 0x20, 0xfc, 0x22, 0xf5, 0x3b, 0x6b, 0xc2, 0xeb, 0xc4, 0xdb, 0xc6, 0xd4,
- 0xf6, 0xfc, 0x28, 0x8f, 0x98, 0xcc, 0x13, 0xed, 0x13, 0x75, 0xcc, 0xa8,
- 0x6d, 0x3f, 0x40, 0xbf, 0x9b, 0x1f, 0xd0, 0xfd, 0x7d, 0xf8, 0x3f, 0x96,
- 0xbf, 0x5a, 0x0f, 0x0e, 0x29, 0xf9, 0xf5, 0xef, 0xcb, 0xd7, 0xb9, 0xcb,
- 0x62, 0x2e, 0x8e, 0x6f, 0xbf, 0xbd, 0xd6, 0x5d, 0x40, 0xac, 0x44, 0xcc,
- 0x19, 0x99, 0xe9, 0xdf, 0x9a, 0xb0, 0xc7, 0x49, 0x5e, 0xa9, 0xe0, 0x64,
- 0xfd, 0x4c, 0xff, 0xa6, 0x94, 0x17, 0x3b, 0x18, 0xd3, 0x8b, 0x8c, 0x7a,
- 0x3c, 0x9e, 0x52, 0x71, 0xcf, 0x23, 0x5e, 0xac, 0x21, 0x67, 0x6d, 0xef,
- 0xfd, 0x1a, 0x8c, 0xab, 0x9c, 0xb8, 0x9b, 0xf6, 0xb7, 0x96, 0xae, 0x23,
- 0xf9, 0xc3, 0xfa, 0x5e, 0x27, 0xea, 0xae, 0x2a, 0x43, 0xbc, 0xba, 0x10,
- 0xdf, 0x33, 0x1d, 0xcc, 0xf7, 0x4a, 0x30, 0x64, 0x73, 0x69, 0xc9, 0xe1,
- 0x05, 0x13, 0x45, 0x6f, 0x0e, 0x7b, 0xbd, 0xf5, 0x93, 0xe3, 0xc1, 0x7f,
- 0x58, 0x99, 0xea, 0x1d, 0x36, 0x8e, 0x3b, 0x22, 0xa6, 0x1d, 0x73, 0x81,
- 0x2c, 0x9f, 0xeb, 0xba, 0xe4, 0x79, 0x77, 0xb3, 0x32, 0x3b, 0x12, 0x98,
- 0x58, 0xac, 0x38, 0x10, 0x0e, 0x94, 0xc5, 0xca, 0x23, 0x61, 0x2c, 0x4b,
- 0x77, 0xf9, 0x7c, 0xf6, 0x33, 0xf4, 0x08, 0xce, 0x2d, 0x32, 0x99, 0xfb,
- 0xc3, 0xb9, 0x8c, 0xba, 0x6f, 0xa4, 0x5e, 0xb7, 0x98, 0x1f, 0x59, 0x19,
- 0xdb, 0xef, 0xdd, 0x88, 0x31, 0x07, 0x5b, 0x4b, 0xfd, 0x3a, 0xa8, 0xc7,
- 0x9f, 0xe7, 0xf4, 0x2b, 0x3a, 0x2d, 0x19, 0xfb, 0x9d, 0x75, 0x92, 0xfa,
- 0x75, 0xb3, 0x3d, 0x37, 0xdb, 0x2b, 0x1a, 0xbb, 0x54, 0xcf, 0x85, 0x94,
- 0x67, 0x99, 0x2d, 0xc3, 0x42, 0x79, 0x86, 0xe9, 0x8f, 0x2a, 0x32, 0x1e,
- 0xc1, 0xf7, 0x3f, 0x37, 0xa6, 0x1f, 0x4f, 0xc9, 0x55, 0x44, 0xff, 0x7e,
- 0xea, 0x5f, 0x30, 0x5c, 0xe6, 0xa0, 0x4e, 0xd6, 0xbb, 0x7a, 0x80, 0x97,
- 0x98, 0xcc, 0x2a, 0xa8, 0x32, 0x22, 0x78, 0xaa, 0xd9, 0x83, 0xb7, 0x12,
- 0xa5, 0xf6, 0xb8, 0xaf, 0x9a, 0x6b, 0x59, 0x4f, 0x86, 0xfc, 0xf8, 0x85,
- 0x51, 0x1b, 0x5e, 0xa0, 0xea, 0xcc, 0x1f, 0xbd, 0x48, 0x10, 0x67, 0xbb,
- 0x92, 0xb3, 0x38, 0x5f, 0x5e, 0x6c, 0x4d, 0xa2, 0x9d, 0xf6, 0xe4, 0x77,
- 0x44, 0x80, 0x33, 0x09, 0x23, 0xb8, 0x85, 0xfd, 0x0f, 0x7b, 0xeb, 0xc9,
- 0xd3, 0xd5, 0x46, 0xd2, 0xbd, 0x78, 0x51, 0xc4, 0x88, 0x6f, 0xc3, 0xcf,
- 0xac, 0x21, 0xe2, 0x7c, 0x41, 0x48, 0xd6, 0x1c, 0x67, 0xe3, 0x19, 0xcd,
- 0x81, 0x17, 0x83, 0xcc, 0x87, 0x2b, 0x1c, 0x28, 0x31, 0xde, 0xb6, 0x7e,
- 0xe0, 0x95, 0x7e, 0x64, 0x2c, 0x33, 0x38, 0x0e, 0xc5, 0xc6, 0xc2, 0xad,
- 0xc9, 0x7a, 0xea, 0xfb, 0xf2, 0xfe, 0xff, 0x8f, 0x35, 0xe9, 0x95, 0xfe,
- 0x75, 0xcd, 0xaf, 0x72, 0x0c, 0x7f, 0x14, 0xbb, 0xbf, 0x6f, 0xbd, 0x64,
- 0xb7, 0x79, 0xbb, 0x3b, 0x1b, 0x4f, 0xa5, 0xbd, 0xb7, 0x38, 0x3e, 0x69,
- 0x33, 0xdf, 0x8f, 0xe8, 0xed, 0x8c, 0x5b, 0xfc, 0x79, 0x6b, 0x52, 0xf4,
- 0x27, 0x78, 0x75, 0xd2, 0xc2, 0x34, 0x39, 0x7f, 0xd6, 0x2e, 0x1b, 0xa7,
- 0xbe, 0xba, 0x68, 0x43, 0x8c, 0xe1, 0x3e, 0xd8, 0xbb, 0x3b, 0x34, 0x3b,
- 0x9f, 0xdb, 0xcc, 0x1c, 0x60, 0xc8, 0x5b, 0x8e, 0xad, 0x26, 0xed, 0xce,
- 0x50, 0xe7, 0x38, 0x61, 0xe1, 0xa4, 0x29, 0xe7, 0x2e, 0x4c, 0x7a, 0x1d,
- 0xd8, 0x66, 0x3a, 0xb1, 0xce, 0x50, 0x75, 0xb9, 0xee, 0x08, 0xc9, 0xb9,
- 0x0b, 0xfe, 0x6a, 0x05, 0x3b, 0x18, 0x3e, 0xd6, 0x1b, 0x5d, 0x7e, 0xb9,
- 0xbe, 0x24, 0x24, 0xe7, 0x0a, 0xda, 0xa8, 0x93, 0xb8, 0xa6, 0x60, 0x83,
- 0x21, 0xcf, 0x4d, 0xb3, 0xfc, 0x39, 0x06, 0xcb, 0xda, 0x61, 0x36, 0x5c,
- 0x57, 0xc2, 0x72, 0x67, 0x4d, 0xe1, 0x83, 0x87, 0xef, 0x98, 0x1f, 0x88,
- 0x47, 0x0b, 0xa0, 0xc7, 0x8a, 0xe8, 0xa7, 0x5b, 0x7b, 0x67, 0xb3, 0x9e,
- 0x42, 0x6e, 0xe0, 0xf4, 0x6d, 0x87, 0xc4, 0xcf, 0x80, 0xff, 0xa7, 0x4c,
- 0xb2, 0x86, 0xbc, 0xf3, 0xa8, 0x59, 0xc3, 0x7f, 0x9a, 0xf3, 0x56, 0x6e,
- 0x38, 0xdb, 0x5f, 0x85, 0xbe, 0xae, 0x48, 0x99, 0x17, 0x2c, 0x63, 0xae,
- 0x10, 0x27, 0xbe, 0x8f, 0x8c, 0x39, 0xb1, 0x25, 0x69, 0x68, 0x07, 0x6d,
- 0xfe, 0xe7, 0xa4, 0x2e, 0x9c, 0xcc, 0xcf, 0x03, 0xda, 0x84, 0x92, 0x3f,
- 0x9f, 0x2d, 0xd8, 0x40, 0x3e, 0x2f, 0xf8, 0x16, 0xb7, 0x9e, 0xad, 0x17,
- 0xaa, 0xe1, 0xf6, 0xc7, 0x52, 0x1e, 0x1e, 0x1a, 0x0f, 0xaf, 0x7f, 0x4d,
- 0xca, 0xe7, 0x6f, 0x4b, 0xc1, 0xdf, 0x9a, 0xca, 0xdb, 0x65, 0xde, 0xb7,
- 0x05, 0xdb, 0x2c, 0x72, 0xd6, 0x6c, 0x6e, 0xd6, 0x25, 0xb9, 0x0f, 0xe4,
- 0xb9, 0xdf, 0xe1, 0x3b, 0x9e, 0xa3, 0xad, 0xbb, 0x98, 0x0f, 0x6c, 0x33,
- 0xe2, 0x51, 0x79, 0x0e, 0x69, 0x84, 0x74, 0x5f, 0x81, 0xe2, 0xc7, 0xd6,
- 0xba, 0xdf, 0x72, 0x3e, 0xc9, 0x93, 0x53, 0x9f, 0x29, 0xca, 0xce, 0x87,
- 0xf8, 0x99, 0x60, 0x80, 0x9f, 0xf9, 0x92, 0xcf, 0xdf, 0xc5, 0x7e, 0x36,
- 0xa7, 0xa6, 0xfa, 0x80, 0x82, 0x9b, 0xd8, 0x56, 0x43, 0x08, 0xce, 0xa5,
- 0x75, 0xbf, 0xb1, 0x32, 0xde, 0xec, 0x33, 0xc8, 0x2c, 0xe6, 0x81, 0x36,
- 0x67, 0xf7, 0xe9, 0xdc, 0x5f, 0x27, 0xfb, 0x8e, 0x14, 0x0c, 0xd3, 0xa7,
- 0x36, 0xa5, 0xc5, 0x9e, 0xb2, 0x7a, 0x8d, 0xff, 0x01, 0xfe, 0x98, 0xb8,
- 0x37, 0x89, 0x58, 0x41, 0x44, 0xf0, 0xc7, 0xed, 0x7f, 0x29, 0x55, 0x47,
- 0x0e, 0x2f, 0xcf, 0xf2, 0xdd, 0x9c, 0x67, 0x8f, 0xff, 0xc5, 0xd4, 0xf5,
- 0xb8, 0x67, 0x4f, 0x18, 0xeb, 0xf6, 0xa0, 0xae, 0x88, 0x72, 0x17, 0x86,
- 0x02, 0xfe, 0x51, 0x68, 0xfe, 0x67, 0xa8, 0x87, 0x13, 0x94, 0xed, 0xe4,
- 0x25, 0xb2, 0x89, 0xde, 0xe0, 0xbf, 0x2f, 0xe1, 0x46, 0x2a, 0xf4, 0xa1,
- 0x15, 0xb7, 0x79, 0x86, 0xd7, 0xbf, 0x31, 0xe1, 0x47, 0xc6, 0xe6, 0xac,
- 0xae, 0x22, 0xc9, 0x1f, 0xbb, 0x93, 0xf1, 0x28, 0xd3, 0xe1, 0xdc, 0x9c,
- 0xea, 0x61, 0x99, 0xcf, 0x33, 0x09, 0xb9, 0x17, 0xfd, 0x9a, 0x0a, 0xdd,
- 0xaf, 0x32, 0x7e, 0xf6, 0x9b, 0x62, 0xb3, 0x35, 0xa2, 0x93, 0x20, 0x2b,
- 0xc6, 0x3d, 0x91, 0x40, 0x4b, 0x1d, 0xaf, 0x6b, 0x0b, 0x10, 0xab, 0x88,
- 0x08, 0x27, 0xf4, 0xfa, 0x6b, 0xc7, 0x7d, 0x7e, 0x73, 0x1c, 0xfe, 0x2b,
- 0xc7, 0xa7, 0x8a, 0x40, 0x6e, 0xff, 0x89, 0xb9, 0x9f, 0xd7, 0xbf, 0x36,
- 0x31, 0x1b, 0x6a, 0x24, 0x6e, 0x2d, 0xa9, 0x3f, 0x67, 0xcd, 0x8e, 0x18,
- 0x99, 0x93, 0x94, 0xe1, 0xc3, 0x6b, 0xf5, 0xf8, 0x0c, 0xc7, 0x89, 0x87,
- 0xb4, 0x29, 0x7d, 0xbc, 0x1f, 0xfa, 0xff, 0xdb, 0x47, 0x3e, 0xb6, 0x89,
- 0xfc, 0x12, 0xdf, 0x72, 0x73, 0xaa, 0xe6, 0xc7, 0xa2, 0x70, 0x4e, 0x39,
- 0x1f, 0xc9, 0x7c, 0xac, 0xb2, 0xac, 0x56, 0xc3, 0x97, 0x7b, 0xfe, 0x07,
- 0xda, 0xcb, 0x89, 0xeb, 0x9c, 0x58, 0x4c, 0x7b, 0x6f, 0xf8, 0x6b, 0x27,
- 0xa2, 0xbe, 0x42, 0xc6, 0x50, 0xd9, 0x53, 0xf0, 0x4c, 0xdd, 0xa4, 0x35,
- 0x61, 0xd4, 0xa1, 0x21, 0x2d, 0xcf, 0x63, 0x1d, 0xb4, 0x63, 0x0b, 0x8f,
- 0x9b, 0x72, 0x5f, 0xf0, 0x24, 0x1e, 0x73, 0xd0, 0x26, 0xdc, 0x86, 0xde,
- 0xf2, 0x0f, 0x4a, 0x19, 0x8a, 0x23, 0xce, 0xe0, 0x04, 0xf4, 0xf0, 0x7a,
- 0x72, 0x63, 0x7f, 0xc5, 0x3c, 0x53, 0xd4, 0xfe, 0x4e, 0x22, 0x60, 0x06,
- 0x72, 0xf1, 0xe7, 0x2c, 0xe7, 0xeb, 0xdd, 0x84, 0xb1, 0xee, 0xb9, 0xdc,
- 0xf9, 0xbf, 0xa5, 0xa6, 0xe6, 0xbf, 0x62, 0x77, 0x6e, 0xf7, 0xe6, 0x04,
- 0xde, 0x77, 0xd4, 0xe3, 0xfd, 0xfd, 0x66, 0x01, 0xf3, 0x36, 0xb1, 0x47,
- 0xb7, 0x7b, 0x6b, 0x02, 0x93, 0x4e, 0x5e, 0x3b, 0x6b, 0xce, 0x22, 0x76,
- 0xa9, 0xbc, 0x16, 0x96, 0x58, 0x10, 0xd3, 0x18, 0x47, 0x8b, 0x23, 0x5e,
- 0x77, 0xf1, 0x38, 0xb4, 0x22, 0xa3, 0x8c, 0x79, 0x31, 0x1a, 0x1d, 0x7d,
- 0xba, 0xbf, 0xc9, 0x51, 0xc7, 0xfc, 0xd8, 0xaf, 0xb8, 0x8c, 0x6f, 0x31,
- 0xcf, 0x97, 0xf5, 0xaa, 0x30, 0xc7, 0xed, 0x64, 0x85, 0x9d, 0xd3, 0xd4,
- 0x88, 0x42, 0xcc, 0x2b, 0xc3, 0xbd, 0xda, 0x86, 0xc5, 0x6a, 0xa4, 0x1f,
- 0xb7, 0xd6, 0xbb, 0x1b, 0xcb, 0xc7, 0xf3, 0x3a, 0x41, 0xcc, 0x13, 0x61,
- 0x0e, 0x63, 0x40, 0x2d, 0x8d, 0x88, 0x6e, 0xfc, 0x8d, 0x7d, 0x63, 0x22,
- 0xab, 0xe6, 0xee, 0x1d, 0xf3, 0x14, 0xa3, 0x38, 0x4c, 0x4c, 0xfa, 0x57,
- 0xdf, 0x7f, 0xae, 0xde, 0x64, 0x91, 0xe0, 0xba, 0xcb, 0x90, 0xff, 0xb6,
- 0x3d, 0xb9, 0xdd, 0x91, 0x63, 0x31, 0x77, 0xc0, 0xb2, 0x18, 0x0f, 0x7d,
- 0x50, 0x66, 0x71, 0x3c, 0xf4, 0x29, 0xce, 0x4d, 0x5b, 0xea, 0x23, 0xeb,
- 0x33, 0x4e, 0x3b, 0xd6, 0xbb, 0x0b, 0x23, 0xe1, 0xbb, 0xde, 0x36, 0x7e,
- 0x6f, 0xbd, 0x95, 0x60, 0x5e, 0x4d, 0xdf, 0x2d, 0x20, 0x6e, 0x6f, 0x37,
- 0x9d, 0x4d, 0x4b, 0x15, 0x05, 0xdd, 0xc6, 0x3c, 0xad, 0x88, 0xf1, 0x68,
- 0x13, 0xfd, 0x37, 0xe6, 0x35, 0x82, 0xfb, 0xc1, 0x72, 0xa9, 0xb5, 0x6b,
- 0x5d, 0x91, 0x8d, 0x77, 0x8d, 0xd4, 0x8b, 0xcf, 0x9f, 0xbf, 0xeb, 0x39,
- 0xa3, 0x19, 0xdd, 0xe9, 0x41, 0xf4, 0xa4, 0xb3, 0xfd, 0x64, 0x30, 0xfb,
- 0x13, 0xfa, 0x59, 0xbb, 0xb6, 0x30, 0x22, 0x1c, 0xeb, 0xe8, 0x5d, 0x07,
- 0x8c, 0x28, 0xb6, 0xa4, 0x37, 0xde, 0x75, 0xb6, 0xbe, 0x9f, 0xff, 0xb3,
- 0x75, 0x86, 0x50, 0xfe, 0x89, 0x75, 0x4a, 0x22, 0xd2, 0x47, 0x98, 0x7d,
- 0x6c, 0xbc, 0x6b, 0xdd, 0xa2, 0xaf, 0x63, 0x73, 0x7a, 0xdd, 0x9f, 0xed,
- 0xa7, 0x94, 0x75, 0x8a, 0x23, 0x1d, 0xad, 0x37, 0x05, 0x36, 0xde, 0x95,
- 0x5a, 0xd4, 0xc3, 0x3e, 0x56, 0x31, 0x8e, 0x64, 0xeb, 0x44, 0x15, 0xc7,
- 0x27, 0xea, 0xa0, 0x28, 0xd2, 0xd3, 0x3a, 0x3f, 0xf0, 0x7b, 0x6b, 0x5e,
- 0x6f, 0x81, 0xad, 0x03, 0x17, 0x75, 0xf0, 0xa8, 0xe9, 0xcc, 0x04, 0x1c,
- 0xb6, 0x0e, 0x3a, 0x7c, 0xd4, 0x41, 0x1f, 0x75, 0x90, 0xa9, 0x36, 0xc2,
- 0xef, 0x51, 0x07, 0xf3, 0xc6, 0xd6, 0xae, 0x2d, 0x8a, 0xc0, 0xe9, 0x30,
- 0x5e, 0x77, 0x38, 0x39, 0x17, 0x2e, 0x63, 0x2d, 0xf5, 0xb6, 0xf1, 0xae,
- 0x39, 0x8b, 0x6c, 0x9d, 0x7f, 0xd9, 0x1d, 0xd8, 0x60, 0xef, 0xdd, 0xdb,
- 0x94, 0x6e, 0xe3, 0xd1, 0xc4, 0xe3, 0x61, 0x1e, 0xdd, 0xcc, 0x4d, 0xee,
- 0xa0, 0xae, 0x1a, 0x39, 0x8e, 0x15, 0x94, 0xab, 0x9d, 0xbf, 0x5b, 0xf8,
- 0xbb, 0x83, 0xbf, 0x65, 0x7e, 0xd4, 0x0b, 0xb2, 0xc5, 0x2e, 0xc8, 0xe6,
- 0xa0, 0x3c, 0x1e, 0x62, 0x94, 0x8c, 0x69, 0xe2, 0xcb, 0x37, 0x05, 0x62,
- 0x6c, 0xe3, 0xa9, 0x62, 0xd9, 0xf7, 0xe4, 0x32, 0xe2, 0x3e, 0x27, 0x44,
- 0x3e, 0xbd, 0x65, 0x1d, 0x32, 0xc4, 0xd8, 0xdf, 0x65, 0x31, 0x96, 0xb2,
- 0x95, 0x71, 0x7e, 0x5e, 0x59, 0x34, 0x34, 0xdd, 0x63, 0xc0, 0xe7, 0x36,
- 0xe2, 0xe8, 0x4d, 0x27, 0xa8, 0x03, 0xb1, 0x93, 0x07, 0xa9, 0xbf, 0x4e,
- 0x74, 0x19, 0x27, 0xf4, 0xec, 0xde, 0x89, 0xbd, 0x94, 0x21, 0x48, 0x7e,
- 0xe8, 0x81, 0x33, 0xa2, 0xfb, 0x1b, 0x1d, 0x5d, 0x41, 0x17, 0x68, 0xcb,
- 0xc5, 0x62, 0xcb, 0x71, 0xc6, 0x35, 0xc1, 0x3a, 0xb7, 0xd6, 0x66, 0xe3,
- 0x5f, 0x7c, 0xbe, 0x0b, 0x1e, 0x6d, 0x4d, 0x2a, 0x1f, 0x0b, 0x3c, 0x5a,
- 0x6b, 0x42, 0xfc, 0x4a, 0xd6, 0xfc, 0xc3, 0x76, 0x2c, 0x3f, 0x9e, 0x7e,
- 0xb1, 0x18, 0x65, 0xb6, 0x8f, 0x95, 0x39, 0x8d, 0x6c, 0xbb, 0x1a, 0xdb,
- 0x6d, 0x76, 0x68, 0xb8, 0xe8, 0x23, 0xba, 0xd6, 0xec, 0x90, 0x7d, 0xae,
- 0xf4, 0xfe, 0x54, 0xae, 0x5e, 0x16, 0x27, 0x16, 0xbb, 0x6c, 0x9c, 0x60,
- 0x1b, 0xc5, 0xc0, 0x92, 0xc4, 0xe5, 0xfd, 0x4b, 0x7f, 0xd2, 0x6f, 0x57,
- 0x85, 0x8a, 0x09, 0xfb, 0x99, 0xcb, 0x91, 0x74, 0x0c, 0x83, 0xc9, 0xa9,
- 0x7b, 0xf9, 0xf4, 0xa3, 0x6c, 0xff, 0x70, 0x9c, 0xfa, 0x98, 0x65, 0xc8,
- 0x3e, 0x3f, 0xd9, 0xdb, 0x37, 0x75, 0x5f, 0x9f, 0xc8, 0x56, 0x58, 0x42,
- 0x00, 0xc1, 0x01, 0xe2, 0x4c, 0xb4, 0x59, 0xea, 0x5b, 0xd6, 0x1b, 0xf3,
- 0x82, 0xc8, 0x54, 0x39, 0x31, 0x38, 0x17, 0x18, 0xe8, 0x93, 0x7d, 0x57,
- 0x47, 0x63, 0xab, 0x99, 0x97, 0x45, 0x2b, 0x6b, 0xb5, 0x4d, 0xaa, 0xec,
- 0x99, 0x3a, 0xf6, 0xe5, 0x6e, 0xa3, 0x46, 0xeb, 0x56, 0x33, 0x87, 0x88,
- 0xdd, 0x7b, 0x81, 0x69, 0x25, 0xe2, 0x6b, 0x15, 0x46, 0xb4, 0xa7, 0x02,
- 0x73, 0xe1, 0xaf, 0xb4, 0xf1, 0x32, 0xfe, 0x94, 0x6a, 0x04, 0x57, 0xda,
- 0x38, 0xf8, 0xa1, 0x35, 0xc4, 0xb8, 0xf4, 0x95, 0xb9, 0x3f, 0x28, 0xce,
- 0xe6, 0xd9, 0xd1, 0x75, 0xd3, 0x38, 0x57, 0xbf, 0x58, 0xa0, 0xfb, 0x53,
- 0x8a, 0xe8, 0x48, 0xb8, 0x49, 0x02, 0xdb, 0xc8, 0x75, 0x7f, 0x33, 0x37,
- 0x82, 0x83, 0xfc, 0xff, 0xf3, 0xeb, 0x65, 0x0f, 0xaa, 0x65, 0x05, 0x03,
- 0xf3, 0xc2, 0x15, 0x1c, 0xc3, 0x8b, 0xbc, 0xdf, 0x93, 0x7e, 0xdb, 0x3a,
- 0x3b, 0xcd, 0xe8, 0x5f, 0xc6, 0x40, 0x32, 0x30, 0xae, 0x6b, 0x93, 0xea,
- 0x7f, 0x76, 0x4f, 0x1d, 0xdc, 0x65, 0x1c, 0xcb, 0xf7, 0x02, 0xb5, 0x5a,
- 0x9f, 0xaa, 0x96, 0x88, 0x5e, 0x07, 0xc6, 0x7f, 0x3c, 0x65, 0xaf, 0x47,
- 0x9e, 0x1f, 0xda, 0x6b, 0x1d, 0x3d, 0x43, 0xf4, 0xa9, 0x21, 0x2d, 0x1a,
- 0xa7, 0xde, 0xdd, 0x55, 0x1c, 0xf3, 0x57, 0xe6, 0xde, 0x6a, 0x8f, 0xb3,
- 0xd2, 0x98, 0xc1, 0x31, 0x2a, 0xd0, 0xe6, 0xfe, 0x2c, 0xb7, 0xee, 0xd9,
- 0x40, 0x36, 0x33, 0x64, 0x35, 0xd2, 0x06, 0x0b, 0x58, 0xe7, 0x46, 0x73,
- 0xdf, 0xf4, 0xae, 0x3a, 0xdd, 0xf7, 0x15, 0xc6, 0xce, 0xd0, 0xdc, 0x5f,
- 0x5b, 0x51, 0xcd, 0x69, 0x7e, 0x93, 0xa3, 0xbe, 0x27, 0x21, 0x65, 0x65,
- 0x5e, 0x8d, 0xe8, 0x5c, 0xe5, 0x5d, 0x0b, 0xd5, 0x81, 0xf0, 0x5c, 0x7b,
- 0xfc, 0xc0, 0xdd, 0xa9, 0x04, 0xb6, 0x27, 0xa5, 0x4d, 0x05, 0xcb, 0x02,
- 0xef, 0x58, 0xfe, 0x69, 0x09, 0x6c, 0x4d, 0xff, 0x29, 0xae, 0x37, 0x28,
- 0x71, 0xbf, 0x25, 0x0e, 0x3d, 0x9a, 0x7d, 0xc6, 0x35, 0x5b, 0xd6, 0x94,
- 0x65, 0x0f, 0xd2, 0x5d, 0x89, 0x00, 0xdc, 0xa5, 0xc4, 0xba, 0xb1, 0x80,
- 0x3c, 0x13, 0xf5, 0x22, 0xd3, 0x2c, 0x65, 0x6a, 0xb4, 0x31, 0x64, 0xc8,
- 0xc4, 0x64, 0x7d, 0xb2, 0xa7, 0x24, 0xbb, 0x9f, 0x82, 0x86, 0x57, 0xad,
- 0x6b, 0x67, 0xc8, 0x9d, 0x9a, 0x0c, 0x69, 0x43, 0xc1, 0xfc, 0x40, 0x15,
- 0x6a, 0x57, 0xbe, 0xfe, 0x66, 0x41, 0xa0, 0x80, 0xb8, 0x2d, 0xfe, 0x64,
- 0xb4, 0x9f, 0xc4, 0xbf, 0xd3, 0xd7, 0x65, 0x6f, 0xd9, 0x16, 0xa9, 0xc7,
- 0xb6, 0xe6, 0x22, 0xa5, 0x39, 0xc9, 0x33, 0x64, 0x9f, 0xb2, 0x65, 0xdd,
- 0x14, 0x78, 0xcb, 0x8a, 0x56, 0x53, 0x1e, 0xf2, 0x9f, 0x6c, 0x5d, 0x29,
- 0x93, 0xdb, 0x33, 0xa4, 0x34, 0xdc, 0x25, 0x3a, 0x79, 0xd6, 0x8c, 0x93,
- 0x5d, 0x0b, 0xbe, 0x1e, 0x8b, 0xbd, 0x6d, 0x28, 0xf6, 0xb3, 0xca, 0x65,
- 0x4a, 0x39, 0xe3, 0x95, 0xd3, 0x3f, 0x62, 0xe7, 0xdf, 0x61, 0x62, 0xa1,
- 0xf0, 0x35, 0xc9, 0xa1, 0x9c, 0x78, 0xce, 0xa8, 0xc0, 0xb3, 0x5a, 0x96,
- 0xfb, 0x10, 0x53, 0xf0, 0x6a, 0x62, 0x5e, 0x86, 0x1e, 0x42, 0x0e, 0x69,
- 0xac, 0x3b, 0xaf, 0xfc, 0x3b, 0xf3, 0x2b, 0xe0, 0x95, 0x54, 0x3b, 0x1e,
- 0x95, 0x75, 0x3d, 0xa5, 0xa6, 0xa9, 0xd6, 0x21, 0xfd, 0xb5, 0x63, 0x5b,
- 0x5a, 0xda, 0x3a, 0x16, 0x3b, 0x60, 0xf4, 0xe7, 0x64, 0x15, 0xcc, 0x3c,
- 0x16, 0x7b, 0xce, 0x78, 0xdc, 0x9e, 0x3b, 0x79, 0x7e, 0xd6, 0x63, 0x0a,
- 0xb6, 0x14, 0x43, 0x25, 0x0f, 0x77, 0x18, 0x77, 0xc0, 0x51, 0xf1, 0x75,
- 0xda, 0x9e, 0xec, 0xbf, 0xb9, 0x13, 0xce, 0x0a, 0x17, 0x7d, 0xf3, 0x6e,
- 0xb8, 0x2a, 0x84, 0xfb, 0xe6, 0x79, 0x69, 0x94, 0xf7, 0x45, 0xb7, 0xe7,
- 0x6d, 0xdd, 0x3a, 0x89, 0xa7, 0xdd, 0x92, 0x27, 0x19, 0xe5, 0xd4, 0x91,
- 0xde, 0x42, 0x8e, 0x8c, 0x52, 0x62, 0x13, 0xe3, 0x90, 0xbb, 0x9c, 0x65,
- 0xde, 0xa3, 0xde, 0xe7, 0xf5, 0x96, 0x90, 0x13, 0x5b, 0xd6, 0x87, 0xe4,
- 0xc4, 0xf3, 0x03, 0xb5, 0x19, 0x83, 0xf1, 0x03, 0xb7, 0xe9, 0x4d, 0x71,
- 0xe6, 0x88, 0xab, 0x8d, 0xf3, 0x56, 0x6c, 0x95, 0x94, 0xd1, 0x7d, 0x31,
- 0x25, 0xdf, 0xc7, 0x02, 0xf8, 0xab, 0x2c, 0xb8, 0x22, 0xb2, 0x96, 0x2f,
- 0x6b, 0xb8, 0x0d, 0xf2, 0xcc, 0xb0, 0x59, 0xc6, 0xef, 0x92, 0x75, 0x41,
- 0x44, 0x27, 0x5c, 0x30, 0x32, 0x07, 0x65, 0xce, 0xa6, 0x5b, 0x08, 0x2c,
- 0xfc, 0x1d, 0x73, 0x0b, 0x99, 0x9f, 0x9a, 0x4c, 0x9d, 0x92, 0x09, 0xfa,
- 0xc8, 0x91, 0x9f, 0x80, 0xde, 0x9c, 0xa0, 0xae, 0x1b, 0x43, 0xb2, 0x0f,
- 0xc0, 0xe9, 0x4b, 0xc0, 0xe6, 0xc5, 0xe6, 0x69, 0x7c, 0x06, 0xa5, 0xcc,
- 0x05, 0xe7, 0x8e, 0xad, 0x40, 0x59, 0x45, 0xd4, 0x57, 0x8c, 0x6b, 0x78,
- 0xde, 0x46, 0xbe, 0xff, 0x05, 0x94, 0xad, 0x6c, 0x41, 0x82, 0x63, 0x2f,
- 0x35, 0xbe, 0xc4, 0x6b, 0x0f, 0xa3, 0x2f, 0xe9, 0xe2, 0x38, 0xfe, 0xd5,
- 0x2a, 0xab, 0x16, 0xd9, 0x4c, 0x6f, 0x09, 0xf3, 0xf4, 0xa8, 0xad, 0x0b,
- 0x62, 0x63, 0x52, 0xb8, 0x48, 0x6d, 0x74, 0x3d, 0x98, 0x2b, 0x57, 0xeb,
- 0x2d, 0x6d, 0x4a, 0x07, 0x6d, 0xb6, 0x9b, 0x3a, 0x97, 0xb2, 0x96, 0xb5,
- 0x3c, 0x30, 0x49, 0x1d, 0x77, 0xf0, 0xdc, 0xf0, 0xbf, 0x05, 0xf5, 0x9a,
- 0x42, 0x9c, 0xb2, 0xe2, 0x9a, 0x8f, 0x76, 0xa9, 0xae, 0x12, 0xde, 0xb2,
- 0x34, 0x74, 0xae, 0x44, 0xf6, 0x21, 0x67, 0xed, 0xf4, 0x68, 0x4e, 0x97,
- 0xe7, 0xef, 0xea, 0x36, 0x5e, 0xb5, 0xaf, 0x3b, 0xec, 0xeb, 0xe1, 0xdc,
- 0xf5, 0xa3, 0xbc, 0xfe, 0x3d, 0x5e, 0xef, 0xa1, 0xee, 0xd5, 0x2b, 0xa4,
- 0xfe, 0x5a, 0x53, 0xea, 0x33, 0x45, 0x31, 0xba, 0x73, 0xf3, 0xd1, 0xd1,
- 0x9a, 0x2d, 0xdb, 0xd3, 0x9a, 0x6d, 0xc3, 0xc9, 0x36, 0xe2, 0xd1, 0x62,
- 0x98, 0x28, 0x61, 0x9c, 0x3f, 0x6b, 0x88, 0x5c, 0x9c, 0xbb, 0xb4, 0xc8,
- 0xd5, 0xc6, 0xb8, 0xd2, 0xf5, 0x42, 0x31, 0xe2, 0x1d, 0x33, 0x6c, 0x3b,
- 0x3c, 0x7a, 0x97, 0xec, 0x8f, 0x7b, 0x5b, 0x69, 0xf0, 0xc9, 0xb6, 0xca,
- 0x24, 0x79, 0xe2, 0x43, 0xa6, 0x33, 0x5c, 0xe7, 0x98, 0x97, 0x29, 0x84,
- 0x11, 0x3b, 0xaf, 0x7c, 0x64, 0xe3, 0x43, 0x22, 0xd5, 0xc0, 0x4c, 0x26,
- 0x1e, 0x64, 0x0e, 0x12, 0x4c, 0x53, 0xb7, 0xad, 0x44, 0xec, 0xa3, 0xf6,
- 0x1e, 0x39, 0xe7, 0xc4, 0x0a, 0x34, 0xe8, 0x0e, 0xcc, 0x0b, 0xcf, 0x60,
- 0x26, 0x43, 0xbb, 0x34, 0x0b, 0x1d, 0xba, 0xff, 0x56, 0x7c, 0xc6, 0x23,
- 0xf5, 0x0e, 0xa6, 0x32, 0xeb, 0x8a, 0x39, 0xa7, 0xdf, 0xa0, 0x1c, 0xdb,
- 0x03, 0x22, 0xc7, 0xd7, 0x73, 0x72, 0xb4, 0x30, 0x66, 0x99, 0xda, 0xcd,
- 0x81, 0x9e, 0x0b, 0x7a, 0x7b, 0xc1, 0xd6, 0xdb, 0xc3, 0x3c, 0x2f, 0x64,
- 0xbe, 0x5c, 0x80, 0x13, 0x75, 0xde, 0xdc, 0x7e, 0x37, 0xc9, 0x7d, 0x04,
- 0x7f, 0xcf, 0x7c, 0x69, 0xb5, 0xa1, 0x87, 0x1d, 0x36, 0x67, 0x76, 0x23,
- 0x6e, 0xf3, 0x51, 0x79, 0x76, 0x5e, 0x86, 0xc7, 0xed, 0x72, 0x2e, 0xea,
- 0xa4, 0x04, 0x4f, 0xe4, 0xfc, 0x45, 0xf6, 0x2e, 0x7c, 0xc3, 0xfe, 0xbd,
- 0x97, 0x73, 0xeb, 0xa2, 0xaf, 0xe6, 0x63, 0x94, 0xac, 0x81, 0x6f, 0xb4,
- 0x7d, 0x7f, 0x08, 0xc7, 0xec, 0xff, 0x99, 0x6c, 0xfe, 0x82, 0x6e, 0x53,
- 0xf6, 0xfc, 0x94, 0x60, 0x93, 0x3c, 0x8b, 0x4c, 0x4b, 0x4e, 0x7d, 0x3d,
- 0xb6, 0x70, 0x54, 0x6e, 0x83, 0x1c, 0x43, 0x13, 0x9b, 0xe8, 0x44, 0x9f,
- 0x66, 0x7a, 0xd3, 0x75, 0x53, 0x73, 0x0f, 0x13, 0xfb, 0xeb, 0x7e, 0x6f,
- 0x45, 0xed, 0x7c, 0xe4, 0x94, 0x75, 0xc0, 0x38, 0x11, 0xa2, 0x07, 0xaf,
- 0x2b, 0xb0, 0xf5, 0x7b, 0xfe, 0x2e, 0x7b, 0x9f, 0x20, 0x65, 0x7e, 0x21,
- 0x21, 0x71, 0x74, 0x36, 0x52, 0xa6, 0xc8, 0xe6, 0x6c, 0xde, 0xc1, 0x39,
- 0xe9, 0x4e, 0x06, 0xa2, 0x57, 0xf2, 0xde, 0x04, 0x63, 0xd9, 0x26, 0xea,
- 0x33, 0xd6, 0x2c, 0x3c, 0xa8, 0x0d, 0x7b, 0x69, 0x63, 0xe3, 0xa6, 0x65,
- 0x1d, 0x24, 0x46, 0x94, 0xcf, 0x53, 0x91, 0xa9, 0x6e, 0x43, 0x92, 0xb1,
- 0xe9, 0xa0, 0xd1, 0xf0, 0x99, 0x02, 0xc4, 0xfd, 0x6e, 0xe8, 0xbe, 0xad,
- 0x1c, 0xcd, 0x43, 0x9c, 0xaf, 0x13, 0xa6, 0xf0, 0x33, 0xe7, 0xf9, 0xa5,
- 0x30, 0xc2, 0x8b, 0x1d, 0xff, 0x6a, 0x4d, 0xda, 0xcf, 0x51, 0xbb, 0xfe,
- 0x27, 0x65, 0x68, 0x17, 0xe7, 0x2d, 0xe7, 0x1c, 0xbf, 0x17, 0x90, 0xe7,
- 0xe0, 0x40, 0x6d, 0x6f, 0xc3, 0x3a, 0x91, 0xe1, 0x40, 0xc8, 0x19, 0x3b,
- 0x88, 0x40, 0xf3, 0x06, 0xe5, 0x22, 0x07, 0xbf, 0x72, 0xcc, 0xc4, 0x68,
- 0xdd, 0x8b, 0xe4, 0x0b, 0x52, 0xbf, 0x10, 0x4f, 0x9b, 0xcf, 0x5b, 0x35,
- 0xd3, 0xbf, 0x67, 0x1d, 0x32, 0xd4, 0xf5, 0xd4, 0x76, 0xac, 0x94, 0x6d,
- 0x95, 0xb0, 0xad, 0x7b, 0x03, 0xba, 0xb9, 0x83, 0x6d, 0x3d, 0x93, 0x38,
- 0x11, 0x74, 0xb3, 0xad, 0x27, 0x4c, 0xe1, 0xe0, 0xce, 0xa6, 0x26, 0xce,
- 0x6d, 0x57, 0x32, 0xe0, 0xdb, 0x46, 0xb9, 0x24, 0x37, 0xba, 0x33, 0x21,
- 0xef, 0x74, 0x7c, 0x9d, 0xe3, 0x89, 0xb6, 0xbb, 0xd0, 0xf0, 0x50, 0x19,
- 0xed, 0xa7, 0x1c, 0x79, 0x5b, 0xd7, 0x7d, 0xc4, 0x3b, 0xdc, 0xcb, 0x32,
- 0x6f, 0x06, 0x66, 0xe3, 0x95, 0x50, 0xc3, 0xca, 0xd9, 0x70, 0xc6, 0x0e,
- 0x29, 0x81, 0xa6, 0x0d, 0x4a, 0x5c, 0x13, 0x5b, 0xbc, 0x27, 0xa5, 0x07,
- 0x1b, 0x21, 0xd8, 0xdd, 0x42, 0x7d, 0xcc, 0xc6, 0x87, 0x0b, 0x45, 0x2e,
- 0x67, 0x38, 0xe8, 0x08, 0x74, 0x3c, 0xcf, 0xf9, 0x2d, 0x9b, 0x97, 0xcd,
- 0xfb, 0xd2, 0xf6, 0xbe, 0xce, 0x16, 0xf4, 0xa5, 0x4f, 0xbd, 0x77, 0xc0,
- 0x80, 0xf3, 0x68, 0xdd, 0xa3, 0x16, 0xec, 0x77, 0x40, 0x1a, 0x64, 0x1e,
- 0x5a, 0x64, 0x1e, 0x8a, 0xe9, 0x4f, 0x37, 0x51, 0xee, 0xf5, 0xb6, 0xdc,
- 0xb3, 0x31, 0x6c, 0xca, 0x7a, 0x92, 0x53, 0xbb, 0x07, 0x3d, 0xc4, 0xce,
- 0xc0, 0xf9, 0x2e, 0xf6, 0xf3, 0x26, 0x65, 0x9e, 0x47, 0xbd, 0x4f, 0x36,
- 0x0b, 0x3f, 0x7c, 0x18, 0xbd, 0xc9, 0xfc, 0x3b, 0x22, 0x0a, 0x52, 0x01,
- 0xe9, 0xe3, 0x61, 0xf2, 0xa5, 0x2e, 0x6b, 0xb2, 0x5a, 0xae, 0xef, 0x65,
- 0x2e, 0x1d, 0xd5, 0xe8, 0x0f, 0xd4, 0x3b, 0xf4, 0xd9, 0xd0, 0x27, 0xce,
- 0x38, 0xa2, 0xf4, 0x01, 0xd3, 0x7b, 0x9e, 0xd8, 0x70, 0x14, 0x1d, 0x16,
- 0x2a, 0x6c, 0x7b, 0xf8, 0xf9, 0x88, 0xf1, 0x0b, 0x45, 0x62, 0x7b, 0x86,
- 0x3a, 0x60, 0xb6, 0xdf, 0x2e, 0x3a, 0x28, 0xa5, 0xcf, 0x8e, 0x05, 0x74,
- 0xff, 0x2b, 0x94, 0x67, 0x07, 0xe5, 0x59, 0x91, 0x9d, 0x43, 0xdf, 0x16,
- 0x45, 0x7c, 0x3a, 0xd0, 0xbc, 0x9a, 0xd7, 0xb7, 0x53, 0x9e, 0x40, 0xaf,
- 0x82, 0xa1, 0xe6, 0x6e, 0xf2, 0xb1, 0x0e, 0xea, 0xe0, 0xa2, 0x3c, 0x6e,
- 0x7b, 0xce, 0x3a, 0xc8, 0x05, 0x0a, 0x99, 0xff, 0x0b, 0x7e, 0x6b, 0x18,
- 0xa6, 0x9d, 0xee, 0xe7, 0x8c, 0x44, 0xbd, 0x2a, 0x0a, 0x0d, 0xc1, 0x80,
- 0x6a, 0x5e, 0x73, 0x71, 0x6e, 0xca, 0x71, 0x48, 0xdb, 0x6b, 0xef, 0x69,
- 0xce, 0xe6, 0xea, 0x1f, 0x59, 0xa3, 0x5e, 0xe1, 0x67, 0xb2, 0xde, 0x24,
- 0x6b, 0x32, 0x71, 0x4f, 0x76, 0x4f, 0xb5, 0x8b, 0x3a, 0xc9, 0x5e, 0x7f,
- 0x41, 0x73, 0xe4, 0xf2, 0x66, 0xb9, 0xfe, 0x81, 0xf5, 0xac, 0x5d, 0x5e,
- 0xca, 0xb9, 0x6c, 0x2e, 0x5c, 0x6c, 0x97, 0xfb, 0xc0, 0x7a, 0x51, 0x73,
- 0x4e, 0x29, 0x97, 0x7f, 0x86, 0x77, 0xe2, 0x6b, 0x4e, 0x62, 0x5e, 0xe1,
- 0xdc, 0xc5, 0x38, 0x69, 0x9c, 0xaa, 0x39, 0x5d, 0xd7, 0xc9, 0x38, 0x36,
- 0x75, 0x1f, 0x98, 0x85, 0x27, 0xed, 0x1c, 0xb7, 0x6b, 0xbe, 0x03, 0x27,
- 0x76, 0x16, 0xd0, 0x27, 0xa3, 0x9a, 0xac, 0x87, 0x45, 0x4b, 0x72, 0x7b,
- 0x55, 0x24, 0x6f, 0x0c, 0xfa, 0xd5, 0xab, 0x6d, 0x6e, 0x18, 0x55, 0xff,
- 0xdc, 0x7e, 0x3b, 0xe1, 0x2e, 0x9d, 0xd8, 0x6f, 0xe4, 0x39, 0xcb, 0x89,
- 0x47, 0x55, 0xe2, 0xe4, 0x80, 0xb9, 0x58, 0x62, 0xb3, 0x9f, 0xf5, 0x83,
- 0x31, 0x75, 0x2a, 0xb7, 0x59, 0xed, 0x41, 0x59, 0xd7, 0x36, 0x07, 0x64,
- 0x9f, 0xa9, 0xec, 0x19, 0x95, 0xbe, 0x8a, 0x72, 0xeb, 0x3c, 0x9f, 0xc4,
- 0x35, 0xf2, 0x7d, 0x09, 0xdf, 0xf8, 0x20, 0xc7, 0xdd, 0xf4, 0x60, 0xd4,
- 0x96, 0xf3, 0x57, 0xd6, 0x4a, 0x2d, 0x33, 0x43, 0xc3, 0xa5, 0xb2, 0x47,
- 0x73, 0xb2, 0xc7, 0x3e, 0x71, 0x9d, 0x4a, 0xfa, 0x99, 0xda, 0x66, 0x7e,
- 0x4f, 0xb7, 0xac, 0x61, 0xca, 0x3d, 0x05, 0x5d, 0xc4, 0xa1, 0xa8, 0xd6,
- 0xc0, 0x38, 0xaf, 0xfb, 0xd6, 0x70, 0x3e, 0xe2, 0x5e, 0xd9, 0xcb, 0x9e,
- 0x8f, 0x91, 0x85, 0xc8, 0xae, 0x25, 0xca, 0x7e, 0x87, 0xec, 0xfa, 0x21,
- 0xed, 0x1e, 0x5d, 0xa9, 0xdf, 0x59, 0x19, 0xaf, 0x93, 0xb1, 0xf0, 0xe2,
- 0x3e, 0xea, 0x21, 0xea, 0x55, 0xd6, 0x41, 0xb6, 0x5c, 0x58, 0xab, 0x90,
- 0x35, 0x1a, 0x89, 0xbd, 0xbf, 0xb5, 0x5a, 0x2f, 0x29, 0x3b, 0x75, 0x4f,
- 0x79, 0x75, 0x4c, 0x9e, 0x83, 0x8d, 0xe6, 0xd6, 0xb1, 0x1b, 0xff, 0xe0,
- 0x39, 0xd8, 0x04, 0x6d, 0x09, 0xd1, 0x2d, 0xe4, 0x76, 0x71, 0x74, 0x63,
- 0x34, 0x51, 0xab, 0x6d, 0x85, 0x26, 0xeb, 0xb7, 0xfc, 0xeb, 0xc6, 0xa1,
- 0x04, 0xa2, 0x05, 0x57, 0x95, 0x93, 0x6f, 0x21, 0xea, 0x60, 0x8c, 0x7a,
- 0x22, 0x51, 0xdb, 0xb4, 0x9d, 0x63, 0xf2, 0xaf, 0xec, 0xc6, 0x70, 0xa2,
- 0xe1, 0x4b, 0x8c, 0x23, 0xfe, 0x12, 0x9b, 0xeb, 0x44, 0xff, 0xcb, 0x01,
- 0xe2, 0xc0, 0xe6, 0xdc, 0x1a, 0x52, 0x6b, 0xe2, 0xd7, 0x94, 0xdf, 0x16,
- 0x92, 0xf5, 0xfe, 0x54, 0xb9, 0x09, 0xe6, 0xd3, 0xa7, 0xb0, 0xb6, 0x5f,
- 0xc1, 0xb3, 0xc6, 0x29, 0xac, 0x19, 0x12, 0x79, 0x4e, 0xa1, 0xad, 0xff,
- 0xfb, 0xd8, 0xdf, 0x3f, 0x1d, 0x8d, 0xb6, 0x6e, 0x3a, 0xb0, 0x61, 0xd7,
- 0x11, 0xec, 0x48, 0x5a, 0xd8, 0x1e, 0xf2, 0x60, 0xfd, 0x3e, 0x05, 0xcb,
- 0x03, 0xc7, 0xb0, 0x75, 0x97, 0x85, 0x39, 0xa1, 0x4e, 0x34, 0x99, 0x25,
- 0x28, 0xac, 0x98, 0xb7, 0x4e, 0x65, 0xb9, 0xd6, 0xe1, 0x8e, 0xdc, 0xfe,
- 0xe5, 0x43, 0xc4, 0x02, 0x15, 0x3e, 0x43, 0xf6, 0x26, 0x47, 0x95, 0xdb,
- 0xd3, 0x8d, 0x4a, 0x4b, 0xee, 0x39, 0xe2, 0xad, 0xe9, 0x8f, 0x99, 0xff,
- 0xc4, 0xb1, 0x3f, 0x74, 0x0a, 0x43, 0x43, 0xbf, 0x2e, 0xcd, 0xfa, 0xcb,
- 0x04, 0xb9, 0x83, 0xe4, 0x1c, 0x26, 0x6d, 0xea, 0x4f, 0xbd, 0x37, 0x24,
- 0x76, 0x37, 0x89, 0x9f, 0x0e, 0x9e, 0xc6, 0xe9, 0xc1, 0x7f, 0xc1, 0x12,
- 0x4d, 0xf2, 0x34, 0xab, 0xd3, 0x19, 0xb1, 0xac, 0x3d, 0xf5, 0x71, 0xab,
- 0xda, 0x78, 0xab, 0x0c, 0xc5, 0x65, 0x98, 0x16, 0x79, 0x0d, 0xdb, 0x35,
- 0xb6, 0x95, 0x3c, 0x84, 0x9d, 0x8c, 0xeb, 0xbe, 0xc8, 0x1d, 0xf0, 0x25,
- 0x33, 0x66, 0x25, 0xa2, 0x3b, 0x2b, 0xa1, 0xb7, 0x57, 0x38, 0x8c, 0x8e,
- 0x7f, 0x56, 0xea, 0x70, 0x6b, 0xfa, 0x34, 0x7e, 0x31, 0x68, 0xef, 0xc9,
- 0x6a, 0xf9, 0xb6, 0x62, 0x75, 0x6e, 0x0f, 0xe9, 0x4d, 0xff, 0x55, 0x89,
- 0xc6, 0x65, 0x2f, 0x4f, 0x11, 0x73, 0x82, 0xdb, 0x06, 0x25, 0xdf, 0x6c,
- 0x81, 0xbb, 0x57, 0xcf, 0x2c, 0x25, 0xcf, 0xfe, 0xca, 0x82, 0xf8, 0x8c,
- 0x2a, 0xda, 0xa5, 0x43, 0xd1, 0x83, 0x86, 0xda, 0x89, 0xe3, 0xa6, 0x3e,
- 0xf1, 0x5b, 0x87, 0x31, 0xf4, 0x2d, 0xd4, 0x61, 0x55, 0x5a, 0x1f, 0xba,
- 0x86, 0x79, 0xd8, 0xd6, 0x3e, 0x13, 0xc9, 0x3e, 0xbd, 0xa5, 0xc3, 0xd1,
- 0x83, 0xfb, 0x02, 0x35, 0xed, 0xef, 0x91, 0xcb, 0x79, 0x88, 0x29, 0x7d,
- 0xe3, 0x23, 0xcc, 0x13, 0x7b, 0xb0, 0x61, 0x5f, 0x04, 0xeb, 0xf7, 0x98,
- 0xe8, 0xee, 0x1b, 0xa1, 0x6c, 0x2f, 0x95, 0xca, 0x1e, 0x96, 0xe6, 0x50,
- 0xfc, 0x66, 0x15, 0x81, 0x28, 0xfb, 0x6c, 0x50, 0x23, 0x01, 0xbf, 0xaa,
- 0x30, 0xfa, 0x8f, 0x3b, 0xb1, 0x89, 0x65, 0x7a, 0x93, 0xb4, 0xb9, 0x3e,
- 0x37, 0xe3, 0xe5, 0x4c, 0x0c, 0x8f, 0xf9, 0x70, 0x70, 0xcc, 0x83, 0xa1,
- 0x31, 0x8d, 0x47, 0x31, 0x1e, 0x1b, 0x90, 0xbd, 0x20, 0x5e, 0x3c, 0x7d,
- 0xc0, 0x8d, 0xcd, 0xbb, 0x3d, 0x98, 0x1d, 0x99, 0x86, 0x03, 0x07, 0x8a,
- 0xb1, 0x97, 0xd7, 0x2b, 0x16, 0xfa, 0xf1, 0x24, 0xaf, 0xf7, 0xef, 0x76,
- 0x71, 0x1e, 0xe6, 0xe0, 0x30, 0x0d, 0x7b, 0x68, 0xac, 0x04, 0xc9, 0x01,
- 0x9a, 0x3c, 0x39, 0xeb, 0xdb, 0xcc, 0x30, 0x46, 0x0f, 0x30, 0x36, 0xee,
- 0x33, 0x91, 0x60, 0x3f, 0x3b, 0xa8, 0xab, 0x6e, 0xe2, 0xda, 0x86, 0x31,
- 0xc1, 0xf8, 0x55, 0xb8, 0xa9, 0x57, 0x6f, 0x6a, 0x54, 0x8c, 0xe8, 0x22,
- 0x7b, 0xbf, 0x97, 0xbc, 0xdf, 0xb5, 0x0a, 0x0d, 0x09, 0xdd, 0x6c, 0x44,
- 0x27, 0x4e, 0x72, 0xdc, 0xff, 0x17, 0xfd, 0x76, 0xb1, 0x43, 0xef, 0xb9,
- 0x51, 0x3d, 0x82, 0x9d, 0xe9, 0xa3, 0xe4, 0xea, 0x40, 0x78, 0xff, 0x11,
- 0xf2, 0xb7, 0xe3, 0xc4, 0x9f, 0x37, 0x2d, 0x9f, 0xa1, 0xe2, 0xd6, 0x47,
- 0x8c, 0xf0, 0xfb, 0x4a, 0xa0, 0xfd, 0x57, 0xd4, 0xc1, 0x67, 0x0f, 0xa8,
- 0xb8, 0x65, 0xe7, 0x62, 0xa4, 0x42, 0x51, 0xec, 0x58, 0xa4, 0xe2, 0xe6,
- 0x7d, 0x47, 0x88, 0xfb, 0x13, 0x36, 0x4f, 0xce, 0xa4, 0x1e, 0x46, 0xb0,
- 0x57, 0xd6, 0xb8, 0xdd, 0x8c, 0xdf, 0xa5, 0x78, 0xa6, 0x9f, 0x39, 0xb4,
- 0x59, 0x8a, 0x13, 0x43, 0x47, 0x68, 0x8f, 0xa5, 0x38, 0xde, 0x6f, 0x4c,
- 0xfc, 0xd4, 0x51, 0x8a, 0xa7, 0x79, 0xbe, 0x93, 0xe7, 0x0b, 0x07, 0x8c,
- 0xfe, 0x0e, 0xb5, 0x14, 0x0b, 0xf6, 0xd7, 0xa3, 0xbf, 0x4f, 0x6c, 0x53,
- 0x43, 0xfb, 0x58, 0x5d, 0x4e, 0xf7, 0xa2, 0x73, 0x2f, 0x36, 0x52, 0x57,
- 0xf7, 0xed, 0xec, 0x64, 0x7f, 0x3e, 0xea, 0xfc, 0x08, 0x1e, 0x63, 0x5e,
- 0xb7, 0xbd, 0xcf, 0x87, 0x73, 0x49, 0xc3, 0xff, 0x45, 0xc5, 0x30, 0x8b,
- 0x94, 0x80, 0xf6, 0x0c, 0x7c, 0x38, 0x9d, 0x2e, 0xc6, 0xa6, 0x81, 0x99,
- 0xf8, 0x29, 0xed, 0xf3, 0xd1, 0xdd, 0xd2, 0xdf, 0x04, 0xe3, 0xc3, 0x2c,
- 0x3c, 0x3d, 0x62, 0xb2, 0x6d, 0x99, 0x27, 0x89, 0x39, 0xdd, 0x70, 0x25,
- 0xc5, 0x37, 0xa2, 0x3b, 0x69, 0x16, 0xc4, 0xc4, 0x63, 0x48, 0xf7, 0xeb,
- 0x3d, 0xb7, 0xa9, 0xc2, 0xab, 0x55, 0xea, 0xd2, 0x81, 0x49, 0x4d, 0x8f,
- 0x57, 0xa8, 0xf1, 0x7e, 0xe6, 0xaf, 0xf1, 0x4a, 0xf5, 0x18, 0x9e, 0xee,
- 0x77, 0x62, 0xde, 0x42, 0x95, 0xd7, 0xe3, 0xe7, 0x19, 0xdb, 0xe2, 0xb3,
- 0x55, 0x13, 0x7b, 0x6d, 0x59, 0x11, 0x2f, 0x20, 0xb7, 0x2f, 0x5f, 0x58,
- 0xc3, 0xf8, 0xe5, 0x10, 0xdb, 0x8b, 0x95, 0xaa, 0x4e, 0xea, 0xfd, 0x34,
- 0x46, 0x68, 0xd7, 0x4f, 0xf0, 0x38, 0x3c, 0x68, 0x75, 0x2e, 0x27, 0xe7,
- 0x9e, 0x13, 0xb0, 0x3a, 0x6f, 0x33, 0x0d, 0x5f, 0x81, 0x1a, 0x88, 0x7e,
- 0x05, 0xa7, 0x71, 0x68, 0x44, 0xca, 0xc0, 0xed, 0x8d, 0x30, 0xaf, 0xee,
- 0xb3, 0x3a, 0x77, 0x9a, 0x73, 0x50, 0x6f, 0xe7, 0xc6, 0x3f, 0x2f, 0xcd,
- 0x62, 0xa6, 0xf8, 0x91, 0xbd, 0xa7, 0x0a, 0xbf, 0x62, 0x3b, 0xef, 0x0f,
- 0x96, 0xa3, 0xaa, 0x52, 0xfc, 0xe0, 0x14, 0xde, 0xe9, 0x7f, 0x0d, 0xe7,
- 0xfa, 0x2d, 0x2c, 0x08, 0x59, 0x70, 0x86, 0x6a, 0xcd, 0x46, 0xf5, 0x1a,
- 0x62, 0x84, 0x82, 0x9b, 0xe6, 0x7e, 0x1f, 0xef, 0xd2, 0xff, 0x6f, 0x9e,
- 0x6b, 0xd9, 0xb2, 0xf4, 0x62, 0xa1, 0xb5, 0xa3, 0x5a, 0xfc, 0xc6, 0xb4,
- 0xf7, 0xd3, 0xfc, 0xe9, 0x3c, 0x38, 0xbf, 0xaf, 0x4b, 0x72, 0xe1, 0xd3,
- 0x18, 0x1e, 0x34, 0xa2, 0x6b, 0xf3, 0x72, 0xf6, 0x9f, 0xa6, 0x0e, 0x2c,
- 0xec, 0x34, 0x4f, 0xec, 0xab, 0xc0, 0xbc, 0xf3, 0xcc, 0x1a, 0xaf, 0x9b,
- 0x4d, 0xdb, 0x59, 0xb0, 0x30, 0x60, 0x2e, 0x53, 0xff, 0x37, 0xfd, 0xf4,
- 0x34, 0x0e, 0x0e, 0xe5, 0xf1, 0xda, 0x87, 0x46, 0xfa, 0x79, 0x76, 0xcf,
- 0xbb, 0x17, 0x0d, 0xc9, 0xa3, 0xf6, 0xfa, 0xc3, 0x61, 0xe2, 0x63, 0xf6,
- 0x19, 0xa1, 0x86, 0x91, 0x74, 0x23, 0xb1, 0x21, 0x8a, 0xef, 0xa6, 0x23,
- 0xc4, 0x87, 0x30, 0xf1, 0xa1, 0x9e, 0xf8, 0x60, 0x12, 0x1f, 0xea, 0x88,
- 0x0f, 0x41, 0xfb, 0xd9, 0xb9, 0xac, 0x47, 0x0f, 0x8d, 0xbe, 0x86, 0x82,
- 0x81, 0x53, 0x70, 0x0d, 0xc8, 0x3e, 0x35, 0x8b, 0xfc, 0xa4, 0x56, 0x6b,
- 0xc3, 0x1c, 0x45, 0xf6, 0x0c, 0x0e, 0xa5, 0x4f, 0xa1, 0x68, 0x40, 0xe3,
- 0x58, 0x64, 0xaf, 0x40, 0x4d, 0xb8, 0x87, 0x58, 0xfd, 0x6b, 0xa3, 0xb6,
- 0xc7, 0x8b, 0xda, 0xbd, 0xd5, 0x30, 0xfa, 0x17, 0xaa, 0x73, 0x95, 0xe8,
- 0xe7, 0xbc, 0x1c, 0x67, 0x25, 0x66, 0xed, 0xd6, 0x30, 0x9b, 0xc7, 0x3f,
- 0x25, 0x6b, 0x26, 0xde, 0x74, 0xc0, 0x3b, 0x9d, 0x74, 0x67, 0x06, 0x99,
- 0x00, 0x59, 0xad, 0xd7, 0x87, 0x2b, 0x0f, 0x9f, 0x56, 0x15, 0x64, 0x3e,
- 0x27, 0x31, 0xaf, 0x36, 0xd8, 0xad, 0x32, 0x5b, 0xd7, 0x04, 0xc3, 0x79,
- 0xa8, 0x88, 0x90, 0x45, 0xcc, 0x64, 0x7e, 0x61, 0xb5, 0x99, 0x45, 0xd8,
- 0x52, 0xa7, 0xca, 0x7e, 0x8d, 0xa3, 0x12, 0xa3, 0xa6, 0x33, 0x46, 0x14,
- 0xf7, 0xc5, 0xef, 0x99, 0x0e, 0x0f, 0x8a, 0xfa, 0x2c, 0xeb, 0x1b, 0x21,
- 0x0d, 0x9e, 0x48, 0x20, 0xba, 0x81, 0x69, 0xe4, 0xe7, 0xe6, 0x85, 0x71,
- 0x53, 0xfa, 0x30, 0x06, 0x38, 0xbe, 0xe5, 0xe9, 0xfc, 0xbb, 0x9c, 0x7f,
- 0xfa, 0xef, 0xe2, 0x3b, 0xa1, 0x57, 0xee, 0x9d, 0x0e, 0x43, 0x7b, 0x40,
- 0xed, 0x28, 0x27, 0x07, 0x3f, 0xcc, 0xb8, 0xa7, 0x4c, 0x7e, 0x5e, 0x41,
- 0xcb, 0x40, 0x1c, 0x55, 0xa1, 0x53, 0x4a, 0x4c, 0xf6, 0x32, 0x29, 0x95,
- 0xf8, 0xfc, 0x6e, 0xea, 0x7a, 0x41, 0x86, 0xb6, 0xe2, 0xc3, 0xb7, 0x46,
- 0x45, 0xb7, 0x35, 0x43, 0x3b, 0x39, 0x8e, 0x37, 0xe6, 0x1e, 0x16, 0x9c,
- 0x3c, 0x32, 0x0b, 0x8e, 0x23, 0xd3, 0x98, 0x9b, 0xd6, 0xcc, 0xbd, 0xf2,
- 0xfc, 0xbf, 0xa8, 0xa2, 0x17, 0x85, 0xd8, 0xa1, 0xf7, 0xc7, 0xd8, 0xf6,
- 0x07, 0x8e, 0xc3, 0xd8, 0x44, 0x0c, 0x3e, 0x9a, 0xfe, 0x0e, 0x75, 0x79,
- 0x28, 0x97, 0x2f, 0xad, 0x42, 0xa2, 0x57, 0xf6, 0xe3, 0x9d, 0xc2, 0xac,
- 0x01, 0xbd, 0x79, 0x9b, 0x62, 0x04, 0x6f, 0x56, 0x4e, 0x61, 0xc6, 0x40,
- 0x90, 0x73, 0xa9, 0x61, 0x59, 0x5f, 0x1e, 0x3f, 0x05, 0x83, 0x57, 0x11,
- 0x83, 0xad, 0xc5, 0x3f, 0x35, 0xe3, 0xcc, 0x71, 0x74, 0xd3, 0xa9, 0xe8,
- 0x2d, 0x73, 0x15, 0xd9, 0x9b, 0x63, 0x9c, 0x6f, 0x65, 0x1d, 0xcf, 0x40,
- 0x1d, 0xee, 0xe4, 0x98, 0x9b, 0x38, 0x6f, 0xaf, 0x2d, 0xb4, 0xb0, 0x68,
- 0xa1, 0xbe, 0xb7, 0xc8, 0x11, 0x7d, 0xa0, 0x02, 0x99, 0x8e, 0x6a, 0xda,
- 0xcd, 0x7d, 0x0b, 0xf4, 0xf0, 0xab, 0xc4, 0x5d, 0xe2, 0x34, 0x36, 0x31,
- 0xee, 0xb4, 0x31, 0x16, 0x15, 0x47, 0xf4, 0x1e, 0xe6, 0xa8, 0xef, 0xdf,
- 0xed, 0x88, 0x86, 0xe4, 0x7d, 0xa3, 0x7f, 0xc0, 0x62, 0xb8, 0x43, 0x65,
- 0xc4, 0x41, 0x3d, 0xf3, 0x1a, 0xf4, 0xbd, 0x77, 0x92, 0x93, 0xfe, 0x84,
- 0xfc, 0xae, 0xfa, 0xaa, 0xa3, 0xc4, 0xa8, 0x11, 0x3c, 0x9a, 0x3e, 0x82,
- 0xbd, 0xe9, 0x14, 0x76, 0xa5, 0x77, 0x28, 0x43, 0xf6, 0xb3, 0x3a, 0x45,
- 0xde, 0xad, 0x8b, 0x96, 0x29, 0x5f, 0x46, 0x69, 0xe8, 0x9b, 0xd6, 0x50,
- 0x85, 0x8a, 0xf2, 0x50, 0x10, 0x37, 0xf5, 0xc5, 0xe1, 0x88, 0xbc, 0x67,
- 0xc9, 0x7b, 0xd9, 0xeb, 0xc7, 0x0d, 0xdc, 0xd8, 0x57, 0x8c, 0xd8, 0x7e,
- 0xcb, 0xea, 0xa9, 0x77, 0x62, 0xcd, 0x78, 0x1d, 0x96, 0x0d, 0x3c, 0x66,
- 0xcd, 0x66, 0xcc, 0xf9, 0xf8, 0x5a, 0x0f, 0xee, 0xde, 0xef, 0x41, 0x6b,
- 0x5f, 0x14, 0xbe, 0x48, 0x09, 0x7f, 0x07, 0xcc, 0x25, 0x30, 0x26, 0x26,
- 0x60, 0xf4, 0xdc, 0xe0, 0x08, 0x1c, 0x0a, 0xab, 0x1e, 0x7c, 0x95, 0x38,
- 0xbe, 0x9c, 0xb8, 0x13, 0x1b, 0xb7, 0x50, 0x1e, 0xf1, 0xe2, 0x1e, 0xd6,
- 0xbf, 0x85, 0x73, 0xff, 0xee, 0xa2, 0x43, 0xc4, 0x02, 0xd9, 0x83, 0xa8,
- 0x61, 0xc3, 0xb8, 0x9b, 0xba, 0x72, 0x23, 0x76, 0xb0, 0x12, 0x37, 0xee,
- 0xf6, 0xe3, 0xee, 0x71, 0x0f, 0x1a, 0xfa, 0xac, 0xc5, 0x87, 0xcd, 0xf8,
- 0x4a, 0x0d, 0x06, 0x5a, 0xc7, 0xbd, 0xf8, 0xdb, 0x3e, 0xdd, 0x77, 0x33,
- 0x73, 0xfe, 0x11, 0x33, 0x88, 0xbf, 0x1f, 0xf7, 0xe1, 0xf6, 0xbe, 0x13,
- 0x92, 0x47, 0x2e, 0x71, 0x32, 0xf6, 0x3c, 0x34, 0x3e, 0x13, 0x2b, 0xfb,
- 0xf4, 0xf3, 0x13, 0xe4, 0x76, 0x9d, 0x07, 0x4d, 0x3c, 0x30, 0xae, 0xa2,
- 0x85, 0xed, 0x7c, 0xbe, 0x6f, 0x16, 0x3a, 0x0e, 0xd6, 0x53, 0x86, 0x85,
- 0x58, 0x3e, 0xe0, 0x84, 0x49, 0x16, 0x8f, 0x2f, 0x00, 0xcd, 0x03, 0x13,
- 0xcc, 0xe3, 0x1e, 0xc6, 0x8e, 0x5e, 0x13, 0xf7, 0x8e, 0xcb, 0xf9, 0x11,
- 0xfb, 0x5d, 0xd8, 0xf7, 0xf7, 0x2d, 0xc4, 0x67, 0x07, 0x54, 0xe2, 0x40,
- 0x21, 0x86, 0x56, 0x2a, 0xf8, 0x5b, 0x5e, 0xdf, 0x96, 0x94, 0xbd, 0xcc,
- 0x40, 0x68, 0x67, 0xe0, 0x50, 0x05, 0x39, 0xc3, 0xa2, 0x7d, 0xd9, 0xeb,
- 0x8f, 0x12, 0xe7, 0x8b, 0x88, 0xf3, 0x25, 0xe4, 0xb0, 0x37, 0x0c, 0x1f,
- 0xc1, 0x23, 0xc4, 0xe5, 0xa3, 0x03, 0x9d, 0x8c, 0x3b, 0xa5, 0x78, 0x92,
- 0x71, 0xa0, 0x8f, 0xe7, 0xa7, 0x76, 0x1a, 0x1d, 0x45, 0xc4, 0xe9, 0x57,
- 0x89, 0xbf, 0x3d, 0xc4, 0x8c, 0xfb, 0xfa, 0x18, 0xee, 0x77, 0x32, 0x07,
- 0xb8, 0x2a, 0x3a, 0xdf, 0xc3, 0x1c, 0xeb, 0x66, 0x25, 0xe0, 0x7b, 0x0b,
- 0xa5, 0x70, 0xec, 0xab, 0x44, 0xc3, 0x6e, 0x29, 0x23, 0xf8, 0xa5, 0x42,
- 0x3d, 0xe0, 0xa4, 0xce, 0x8f, 0xc1, 0xea, 0x77, 0x70, 0xbc, 0x35, 0x26,
- 0x19, 0x38, 0xde, 0x30, 0x75, 0xed, 0xbb, 0xc4, 0xda, 0x0f, 0x89, 0xa9,
- 0xfe, 0xe9, 0xf5, 0x68, 0x34, 0x4c, 0x1e, 0xc7, 0x70, 0xba, 0xdf, 0x30,
- 0x65, 0x9f, 0xdc, 0x9b, 0xe4, 0x79, 0x93, 0xd3, 0x19, 0x33, 0x0d, 0xf1,
- 0xc3, 0x11, 0x8e, 0x47, 0x95, 0xbc, 0x04, 0x8e, 0x31, 0xe0, 0x9d, 0x7d,
- 0x8b, 0x39, 0x2e, 0x89, 0xa5, 0x12, 0xef, 0x46, 0x28, 0xeb, 0x62, 0xac,
- 0xa0, 0x3e, 0x1a, 0xfb, 0x54, 0xa4, 0x0e, 0x46, 0x70, 0xef, 0x9e, 0x6c,
- 0x1c, 0x6e, 0x0f, 0xc5, 0x6f, 0x63, 0x1c, 0x0e, 0x17, 0x33, 0x0e, 0xbb,
- 0x22, 0x22, 0x9b, 0x13, 0xc3, 0x8c, 0xdb, 0x5b, 0x92, 0x61, 0x34, 0x71,
- 0x0e, 0x27, 0x52, 0xec, 0xb7, 0x6f, 0x26, 0x9e, 0x49, 0x79, 0x18, 0xb3,
- 0x34, 0x1e, 0x44, 0xb5, 0x91, 0x69, 0x3c, 0xfc, 0x3c, 0xe6, 0xf0, 0x30,
- 0xec, 0x6b, 0x6d, 0x7d, 0x0a, 0xe2, 0xcd, 0xd9, 0xe7, 0x65, 0xcf, 0xa4,
- 0x04, 0x9b, 0x65, 0x2d, 0xf3, 0xde, 0x72, 0xd9, 0xfb, 0xd9, 0x9f, 0xfc,
- 0x3e, 0xca, 0x89, 0x4f, 0x65, 0x39, 0x1c, 0xfa, 0x79, 0x48, 0x70, 0xb7,
- 0x86, 0xb8, 0x2b, 0xfb, 0x73, 0x2c, 0x6b, 0x55, 0x60, 0x2a, 0x1e, 0xfd,
- 0xef, 0x8f, 0xa3, 0xf6, 0x7e, 0x56, 0xc1, 0x24, 0xe2, 0x5f, 0x92, 0xf8,
- 0xc7, 0x31, 0x74, 0x5d, 0x4f, 0x0c, 0xa4, 0x4c, 0xff, 0x98, 0x24, 0x06,
- 0x12, 0xa7, 0x8f, 0x10, 0xa7, 0x9f, 0x22, 0x4e, 0x7f, 0x93, 0x38, 0xfd,
- 0x24, 0x31, 0x21, 0xbb, 0xa6, 0xd7, 0x24, 0xcf, 0x2f, 0x38, 0x1f, 0xef,
- 0xd9, 0x6b, 0x8b, 0xd5, 0xd4, 0xd5, 0xac, 0x01, 0x79, 0xe7, 0x47, 0x3f,
- 0x24, 0x76, 0xff, 0x13, 0xce, 0x93, 0xbf, 0x2a, 0xbb, 0xef, 0xaa, 0xb1,
- 0xaf, 0x1b, 0xee, 0xbe, 0x5a, 0xad, 0x07, 0xf6, 0xb7, 0x02, 0x4c, 0xe1,
- 0xa2, 0x05, 0x7d, 0x6d, 0x70, 0xf4, 0xd5, 0x1e, 0x3a, 0x29, 0xcf, 0x43,
- 0xa7, 0x49, 0x5e, 0xdf, 0x26, 0x7b, 0xbd, 0x0f, 0xc9, 0x7e, 0xad, 0x65,
- 0xbc, 0xe7, 0xea, 0xab, 0x35, 0xdf, 0x82, 0x8d, 0x6d, 0xfe, 0x49, 0xfb,
- 0x5e, 0xcd, 0xfb, 0x8f, 0x50, 0x5f, 0x19, 0xb6, 0x99, 0x4a, 0xca, 0x7e,
- 0xd4, 0x99, 0x78, 0x22, 0x2d, 0xbf, 0x6b, 0x5b, 0x12, 0xea, 0xe3, 0x88,
- 0x55, 0x0b, 0x1f, 0x0f, 0xe3, 0xd6, 0x3e, 0x0f, 0xed, 0x20, 0x8e, 0x32,
- 0xfa, 0xd6, 0xfd, 0xe3, 0xf5, 0xf4, 0xb5, 0xc7, 0x2c, 0x2d, 0x12, 0x68,
- 0x19, 0x27, 0xe7, 0x59, 0x3f, 0xbe, 0x18, 0x4b, 0x07, 0x2c, 0xcb, 0x73,
- 0x8d, 0x11, 0xde, 0xa0, 0xf8, 0xe1, 0xa2, 0x0f, 0x3a, 0xe8, 0x57, 0x6b,
- 0xf7, 0x07, 0xb4, 0xb7, 0x88, 0xa7, 0xeb, 0xea, 0x0f, 0xd3, 0x3e, 0x8c,
- 0xf3, 0x4d, 0xc4, 0x52, 0x67, 0x24, 0xc0, 0x3c, 0xd1, 0x43, 0xdb, 0xf7,
- 0xe2, 0x7c, 0x42, 0xfc, 0x4b, 0xef, 0xf8, 0x2e, 0x73, 0x93, 0x0e, 0xfa,
- 0xc6, 0x07, 0x89, 0xeb, 0xe9, 0x4b, 0x61, 0x1e, 0x33, 0xe9, 0x0b, 0x6e,
- 0xbc, 0x93, 0x30, 0xe8, 0x77, 0x1e, 0xbc, 0x9b, 0xa8, 0x63, 0x9f, 0x41,
- 0x96, 0xf5, 0x63, 0xa3, 0xfd, 0xde, 0x75, 0x4d, 0xfc, 0x5b, 0x4a, 0x4d,
- 0xff, 0x2c, 0xb5, 0x02, 0xd1, 0x4a, 0x0d, 0x7f, 0x37, 0xfe, 0x37, 0xf8,
- 0x19, 0xe3, 0xf6, 0x9a, 0x3e, 0x70, 0x0e, 0x11, 0x22, 0x0f, 0x9c, 0x38,
- 0x28, 0xcf, 0xe9, 0x50, 0x1b, 0x9d, 0xeb, 0xd0, 0x99, 0xdb, 0xea, 0x99,
- 0x73, 0x0e, 0x27, 0xfb, 0x24, 0x2b, 0x66, 0xd9, 0x0f, 0xfa, 0x8b, 0xf1,
- 0xc0, 0xfe, 0xc3, 0xf4, 0x91, 0x02, 0x2c, 0x78, 0xc4, 0x8d, 0xbf, 0x3b,
- 0x38, 0x22, 0x6b, 0x4b, 0x82, 0x99, 0xfe, 0x21, 0x12, 0x85, 0x30, 0xb9,
- 0xde, 0xfd, 0x7b, 0x46, 0x30, 0x90, 0xe3, 0x79, 0x1f, 0x84, 0xe2, 0x5f,
- 0x51, 0x71, 0x98, 0x3c, 0x22, 0x10, 0xbf, 0x9a, 0x36, 0x26, 0xef, 0xb8,
- 0x49, 0xec, 0x5f, 0x41, 0x1b, 0xeb, 0xe6, 0x7c, 0x7e, 0x83, 0xe3, 0xd8,
- 0x41, 0x1b, 0x1b, 0x4d, 0xcc, 0xc4, 0x56, 0xda, 0x58, 0x9c, 0x36, 0x16,
- 0xa7, 0x3d, 0xc5, 0x69, 0x63, 0xf2, 0x6e, 0x7e, 0x9c, 0x36, 0x16, 0xa7,
- 0x8d, 0xc5, 0x53, 0x8b, 0xf1, 0x14, 0x99, 0xc6, 0xae, 0x91, 0x45, 0xc4,
- 0x31, 0x79, 0xb6, 0xc6, 0x79, 0xb8, 0xed, 0x6f, 0xc8, 0xd9, 0x6f, 0xe0,
- 0xa1, 0xe0, 0x4e, 0xfa, 0xe4, 0x63, 0x43, 0xc4, 0x3b, 0xda, 0xc1, 0xa2,
- 0xb4, 0x70, 0xfc, 0x7a, 0xe6, 0xb1, 0xc7, 0xc8, 0xf3, 0x55, 0x3c, 0x6b,
- 0x4a, 0x1e, 0x6c, 0xf2, 0x9c, 0xb1, 0x26, 0x29, 0x1c, 0xec, 0x18, 0x36,
- 0xf4, 0x03, 0x37, 0x91, 0x17, 0x56, 0x92, 0x97, 0x8c, 0x2c, 0x00, 0x5e,
- 0x1c, 0x12, 0x19, 0xc5, 0xc7, 0xb3, 0xfb, 0x4f, 0x8f, 0xf7, 0xd7, 0x44,
- 0x1b, 0x65, 0x7d, 0x88, 0x9c, 0x64, 0xf1, 0xb0, 0x70, 0xbc, 0xc3, 0xe4,
- 0x48, 0x7a, 0xf8, 0xdf, 0x21, 0x1c, 0xaf, 0x12, 0x65, 0x7b, 0xf4, 0xf0,
- 0x3b, 0x30, 0xd6, 0xfd, 0x52, 0xb1, 0x16, 0xbf, 0x16, 0x0a, 0xc4, 0x9f,
- 0x54, 0x54, 0x34, 0x93, 0xef, 0xdd, 0xbc, 0xd3, 0x89, 0x9e, 0xd0, 0x62,
- 0x7c, 0x85, 0x9c, 0x6f, 0xf5, 0x35, 0x2a, 0x96, 0xec, 0xa3, 0x2d, 0x55,
- 0x0a, 0xc7, 0xd2, 0xc3, 0xe7, 0x30, 0x61, 0xaf, 0x13, 0x8e, 0xa6, 0x8e,
- 0x5b, 0x55, 0x86, 0x60, 0x11, 0xb1, 0xed, 0xea, 0x37, 0x2d, 0xb7, 0xac,
- 0x35, 0x91, 0x03, 0x0e, 0xf7, 0x47, 0x5f, 0x70, 0x12, 0xf7, 0xd7, 0x93,
- 0x07, 0x3e, 0x91, 0xe3, 0x81, 0x07, 0xfb, 0x0d, 0xed, 0x07, 0xc4, 0x8b,
- 0xfd, 0x3c, 0xdf, 0xca, 0x73, 0xab, 0xdf, 0xe0, 0x7c, 0x04, 0x9a, 0x66,
- 0x90, 0x1b, 0xbe, 0x43, 0x99, 0x7b, 0x29, 0x73, 0x82, 0xf6, 0x9f, 0xee,
- 0xd5, 0x90, 0x1c, 0x33, 0x30, 0xde, 0xeb, 0x45, 0xdf, 0x58, 0x10, 0x4f,
- 0xf6, 0xfa, 0xb0, 0x93, 0xfc, 0xf0, 0x70, 0xaf, 0xf8, 0xe2, 0x4c, 0xf4,
- 0x8f, 0xcd, 0xc4, 0x37, 0x92, 0xb2, 0x3e, 0xf5, 0x2e, 0x56, 0x57, 0x88,
- 0x7e, 0xc4, 0x2f, 0xc9, 0xaf, 0x93, 0x7a, 0x4f, 0x8c, 0x63, 0x8a, 0x79,
- 0xf5, 0x43, 0x31, 0xe8, 0x43, 0x9c, 0xc1, 0x8f, 0x87, 0xbe, 0x20, 0x31,
- 0x52, 0x7c, 0x52, 0xc3, 0x13, 0xe4, 0x3c, 0xa5, 0xc4, 0xd5, 0x92, 0x48,
- 0x4d, 0xf4, 0x0b, 0x8a, 0x1e, 0x7b, 0x45, 0xb5, 0xac, 0x4a, 0x89, 0xe1,
- 0x07, 0x35, 0xf2, 0x0f, 0x13, 0x37, 0xdb, 0x31, 0x5b, 0xc3, 0xf4, 0xdd,
- 0x95, 0xa8, 0xda, 0xdd, 0x87, 0xff, 0x56, 0x19, 0xff, 0x60, 0x1a, 0x63,
- 0xfd, 0x34, 0x62, 0xfb, 0xec, 0xbe, 0x93, 0xd3, 0x67, 0x91, 0x33, 0xbf,
- 0xa1, 0xd6, 0x66, 0xbe, 0x0b, 0xfd, 0xd0, 0x69, 0x87, 0x3e, 0x71, 0x94,
- 0xf1, 0xc1, 0x45, 0xfb, 0x9c, 0x31, 0xae, 0xd1, 0x7f, 0x6b, 0x8f, 0x56,
- 0xc1, 0x88, 0x5f, 0xab, 0x3a, 0x2d, 0x54, 0x8a, 0x3c, 0xa1, 0xf2, 0x6c,
- 0x6e, 0x14, 0x26, 0xf6, 0x4b, 0x6c, 0x70, 0x40, 0x23, 0x0e, 0xff, 0x3d,
- 0x7d, 0xe6, 0x4e, 0x3b, 0x1e, 0x1d, 0xb6, 0x9f, 0x85, 0x76, 0x8e, 0xc7,
- 0xe9, 0x27, 0x8b, 0xd1, 0xd1, 0xef, 0x41, 0xbb, 0x1d, 0x8b, 0x1e, 0xb3,
- 0x2a, 0xe8, 0x33, 0x1d, 0xfb, 0x03, 0x4d, 0x37, 0xd2, 0x67, 0xae, 0xbb,
- 0x46, 0xe2, 0xd8, 0x61, 0xf2, 0x5f, 0xc3, 0xbc, 0x8e, 0xf8, 0xb2, 0xb5,
- 0xde, 0xe8, 0x78, 0x9e, 0x32, 0xdd, 0x4f, 0xfb, 0x7f, 0x97, 0x3c, 0xe7,
- 0xdc, 0x9e, 0x43, 0xd4, 0x99, 0x66, 0xfb, 0xc3, 0xcf, 0x92, 0x3e, 0xdb,
- 0x37, 0x62, 0xfc, 0x2d, 0x71, 0x2f, 0x46, 0x5f, 0xfa, 0x37, 0xc6, 0xec,
- 0xe2, 0x50, 0xfc, 0xf6, 0x62, 0x04, 0x71, 0x1f, 0x65, 0xfd, 0x38, 0xa9,
- 0xf7, 0x6f, 0x90, 0x77, 0x8f, 0x43, 0x26, 0x65, 0xf1, 0xe0, 0x83, 0xa4,
- 0xd8, 0xd9, 0x89, 0xff, 0x59, 0x89, 0xf8, 0x26, 0xc6, 0xe0, 0xa0, 0xe6,
- 0x90, 0xb5, 0xf0, 0x99, 0x58, 0x73, 0xf0, 0x1a, 0xca, 0x5c, 0x47, 0xff,
- 0x03, 0xe6, 0x0c, 0x47, 0x70, 0xcf, 0x1e, 0xc9, 0x31, 0xd0, 0x20, 0xb9,
- 0xda, 0xbc, 0x50, 0xc0, 0x3c, 0x43, 0xac, 0x58, 0x3b, 0x76, 0x98, 0x71,
- 0x42, 0xd6, 0x96, 0x91, 0xf1, 0x19, 0x61, 0xbc, 0xda, 0x5b, 0x6f, 0xbf,
- 0xd3, 0x70, 0xff, 0x58, 0x3d, 0x5e, 0xe9, 0x9d, 0x89, 0xfb, 0x98, 0xeb,
- 0xc4, 0x98, 0xeb, 0xc4, 0xc6, 0xbc, 0x88, 0x1d, 0x98, 0xc6, 0x83, 0xb2,
- 0x1d, 0x98, 0xc3, 0x83, 0xb2, 0x8d, 0xa9, 0xf8, 0x2a, 0xf3, 0x97, 0x0d,
- 0xc4, 0xf3, 0x1e, 0xda, 0xe3, 0xff, 0xe0, 0xdc, 0x0f, 0xd0, 0xde, 0xab,
- 0x89, 0xf7, 0x6f, 0xee, 0x02, 0xee, 0xb4, 0xf5, 0x73, 0x84, 0x7a, 0x54,
- 0xf0, 0x15, 0xfa, 0x44, 0x15, 0x63, 0x52, 0x37, 0xe7, 0x7c, 0xe7, 0xa0,
- 0x11, 0x0c, 0xab, 0x01, 0xed, 0x09, 0xce, 0x73, 0xd7, 0x88, 0x8a, 0x47,
- 0xfb, 0x17, 0x63, 0x3e, 0x63, 0xca, 0xb6, 0xa1, 0x09, 0xbb, 0x7c, 0x37,
- 0xfd, 0xe1, 0x6e, 0xfa, 0xc9, 0x7b, 0xf4, 0x93, 0xc9, 0x95, 0xf2, 0x3e,
- 0xa9, 0x93, 0x39, 0xff, 0xc3, 0x58, 0x93, 0x90, 0x78, 0xa7, 0xf7, 0x0c,
- 0xa9, 0xcc, 0xb5, 0x68, 0x9f, 0x5d, 0xcc, 0x51, 0x6e, 0xa7, 0x6d, 0x3e,
- 0x3a, 0x24, 0x3e, 0x24, 0x39, 0x8b, 0x11, 0xde, 0x46, 0xdb, 0x7c, 0x7e,
- 0x48, 0xfc, 0xa3, 0x14, 0xb7, 0xee, 0x94, 0xfd, 0xa6, 0xa5, 0xf8, 0xec,
- 0xbe, 0xc3, 0x94, 0xef, 0x08, 0x76, 0xd1, 0x2e, 0x4b, 0x69, 0x97, 0xf7,
- 0x51, 0xaf, 0x1e, 0xda, 0xe5, 0x06, 0xe2, 0x50, 0x09, 0xed, 0xf2, 0x5e,
- 0xf2, 0x81, 0xca, 0x9c, 0x5d, 0xfe, 0xdd, 0xf8, 0xc2, 0x8a, 0x6c, 0x8c,
- 0xf0, 0x42, 0xdd, 0x2d, 0xef, 0xf7, 0x59, 0xd6, 0xed, 0x66, 0xa6, 0x69,
- 0x06, 0x74, 0xb6, 0x1d, 0xc1, 0xb2, 0xb4, 0x13, 0xe5, 0x7d, 0x11, 0x2c,
- 0x4d, 0xd6, 0xb4, 0x9f, 0x55, 0x22, 0xc8, 0xcc, 0xc8, 0xf2, 0x40, 0x57,
- 0x9f, 0x7c, 0xdf, 0x43, 0x23, 0x07, 0xe1, 0xf8, 0xaf, 0xcd, 0x7e, 0x53,
- 0xe4, 0xf3, 0x7f, 0x01, 0x7f, 0x5c, 0x42, 0x99, 0x3a, 0xcd, 0x8f, 0xac,
- 0xc9, 0xec, 0xf7, 0x07, 0x9c, 0xb7, 0xf1, 0x7c, 0x16, 0xdb, 0xa8, 0x1a,
- 0x77, 0x3a, 0xbf, 0x98, 0xf4, 0x60, 0xfa, 0xb8, 0x89, 0xbf, 0xcd, 0xb6,
- 0xe3, 0x2e, 0x88, 0x34, 0xe2, 0xb9, 0x84, 0x82, 0x69, 0xc6, 0xd3, 0xf8,
- 0x91, 0xbd, 0x2e, 0x50, 0x89, 0xf2, 0xdd, 0xf6, 0x9a, 0x02, 0x0e, 0x24,
- 0xf4, 0xf6, 0x34, 0xcf, 0xcb, 0x0e, 0x7a, 0x51, 0xbc, 0x5b, 0xc1, 0x2d,
- 0x01, 0x2f, 0x4a, 0xf9, 0xdb, 0x43, 0xbe, 0xd9, 0x1d, 0x5a, 0x6e, 0x6d,
- 0x59, 0x25, 0xf6, 0xed, 0x05, 0x0e, 0x96, 0x94, 0x0b, 0x0e, 0x1e, 0x30,
- 0x65, 0xed, 0xd2, 0x40, 0x77, 0xa2, 0x12, 0x85, 0xbb, 0x6b, 0x9a, 0x1a,
- 0x51, 0x63, 0xbe, 0xc3, 0xfa, 0x05, 0x07, 0x3f, 0x5b, 0x21, 0xeb, 0xf6,
- 0x4f, 0x49, 0x8c, 0x1b, 0x92, 0x79, 0xcd, 0xc6, 0x50, 0xe7, 0xd8, 0x5b,
- 0x9a, 0xe8, 0x65, 0x13, 0x39, 0x8a, 0xda, 0xf7, 0xa6, 0x5d, 0xc6, 0x17,
- 0x39, 0x4a, 0x0c, 0x90, 0xf8, 0x72, 0x0a, 0xed, 0xfd, 0xa7, 0x68, 0xff,
- 0xb2, 0x8e, 0xc1, 0xbc, 0x77, 0x81, 0x85, 0xe2, 0x85, 0x99, 0x60, 0x31,
- 0xa2, 0x15, 0x15, 0xc4, 0x6f, 0xfa, 0x00, 0x5e, 0x30, 0xf5, 0x96, 0x87,
- 0x1c, 0xd1, 0x87, 0x8a, 0xa0, 0xaf, 0x7b, 0x5b, 0xe9, 0xc1, 0xc6, 0xc0,
- 0x08, 0xfa, 0xc8, 0x05, 0xf3, 0xf9, 0xf8, 0xba, 0x3d, 0x8c, 0x6f, 0x8e,
- 0x8b, 0xf9, 0xb8, 0x16, 0x8a, 0xff, 0x8e, 0x3c, 0xc0, 0x3f, 0x9b, 0x18,
- 0xed, 0xb0, 0x7d, 0x27, 0x90, 0xd9, 0x44, 0x7b, 0x0d, 0x8f, 0x87, 0xe9,
- 0x23, 0x23, 0x82, 0x7d, 0xf2, 0x35, 0xa3, 0x17, 0x0a, 0x98, 0x3f, 0x16,
- 0x33, 0x0f, 0x39, 0x9d, 0xb4, 0x3a, 0xdd, 0xb4, 0x6b, 0xe7, 0xa2, 0x99,
- 0x50, 0xd3, 0x37, 0xe0, 0x9d, 0x5d, 0x33, 0x51, 0x48, 0x5f, 0xaa, 0x48,
- 0xca, 0x0b, 0x55, 0xea, 0xa7, 0xd9, 0x6f, 0xec, 0x3d, 0x04, 0xda, 0x03,
- 0x8e, 0xda, 0x75, 0x49, 0x45, 0x27, 0xf6, 0xeb, 0x2d, 0xa5, 0xea, 0x4c,
- 0x78, 0x98, 0xaf, 0x94, 0xa4, 0x3d, 0x00, 0xb9, 0x32, 0x58, 0xef, 0xa7,
- 0xbb, 0x5c, 0x28, 0x37, 0x8c, 0xe8, 0x33, 0xcc, 0x81, 0x1c, 0xa3, 0x4e,
- 0xfc, 0xcc, 0x96, 0x6b, 0x1a, 0x8a, 0x47, 0x6f, 0xc0, 0xe9, 0x5d, 0x7e,
- 0xa8, 0xbc, 0x76, 0x76, 0xcf, 0x1c, 0x14, 0x8c, 0x12, 0x08, 0xd2, 0x8b,
- 0xf1, 0xd6, 0x2e, 0x15, 0xae, 0xd1, 0xbf, 0xc1, 0x87, 0xbb, 0x14, 0xcc,
- 0x9f, 0xa7, 0xa0, 0x68, 0x78, 0x84, 0x3a, 0x11, 0xee, 0x45, 0x3f, 0x4d,
- 0xc1, 0xe6, 0x5d, 0x5b, 0x92, 0xc2, 0xed, 0xc9, 0xe9, 0x06, 0x2b, 0x61,
- 0xee, 0x7e, 0xd3, 0xaa, 0x30, 0x8c, 0xd8, 0x2d, 0xaa, 0xb5, 0xb8, 0x72,
- 0x41, 0xa0, 0x65, 0x80, 0x38, 0xfd, 0x12, 0x7d, 0xe0, 0x64, 0x7f, 0xdc,
- 0xf2, 0x18, 0x8b, 0x89, 0xb5, 0x51, 0x34, 0x30, 0x37, 0x97, 0xbc, 0x7b,
- 0x9b, 0x9d, 0xef, 0xca, 0x7e, 0x63, 0x27, 0xfc, 0x63, 0x0f, 0xe3, 0x78,
- 0xc2, 0x8d, 0xc5, 0x63, 0xa5, 0xb8, 0x8e, 0x39, 0x75, 0x98, 0xdc, 0x21,
- 0xbc, 0x2f, 0xcb, 0xf1, 0x9e, 0x27, 0xc7, 0xfb, 0x15, 0xb2, 0x1c, 0x6f,
- 0x80, 0xb9, 0x5a, 0x95, 0x51, 0x8a, 0x5b, 0x06, 0x0c, 0xc6, 0x80, 0x52,
- 0x34, 0xdb, 0xeb, 0x01, 0x1a, 0x6e, 0xa3, 0xff, 0x7e, 0x9e, 0xf9, 0xf8,
- 0xcd, 0x3b, 0x03, 0xbe, 0x1d, 0x8a, 0x8f, 0x71, 0x40, 0xda, 0x3f, 0x4c,
- 0xdc, 0xf0, 0x61, 0x4e, 0xaf, 0x11, 0x5c, 0x8a, 0xc0, 0xf9, 0x43, 0xd4,
- 0xe5, 0xe2, 0xb1, 0x1b, 0x10, 0xa6, 0xee, 0xc2, 0xfb, 0x0e, 0xe7, 0xc6,
- 0x31, 0x41, 0xd9, 0x9d, 0x78, 0x6f, 0x70, 0x16, 0x5e, 0x3d, 0x90, 0xcd,
- 0xc3, 0x03, 0x7d, 0x13, 0xb2, 0x5e, 0xfc, 0x35, 0x86, 0xd7, 0x7b, 0x24,
- 0x0f, 0xff, 0x41, 0xbf, 0xde, 0x5f, 0x2a, 0xeb, 0x84, 0xf4, 0xe7, 0xaf,
- 0x2e, 0x70, 0x30, 0xbe, 0xe8, 0xfe, 0xef, 0x3b, 0xe2, 0xf2, 0x1c, 0xd9,
- 0xff, 0x08, 0xef, 0x7f, 0x9f, 0xf1, 0xfc, 0x36, 0x5e, 0x8f, 0x55, 0x32,
- 0xd7, 0x5e, 0x18, 0x3f, 0xef, 0xe2, 0xf5, 0xc7, 0x38, 0x97, 0x65, 0x46,
- 0x4d, 0xec, 0x15, 0xe5, 0x08, 0x71, 0xc3, 0x81, 0x1d, 0x21, 0x3d, 0xba,
- 0xc3, 0xce, 0xa1, 0x9d, 0x98, 0x48, 0x5f, 0x9d, 0xf3, 0xc1, 0x4a, 0x94,
- 0xec, 0x96, 0xfc, 0xc5, 0x90, 0xf5, 0x9f, 0xfe, 0x12, 0xe6, 0x4f, 0x95,
- 0x17, 0xec, 0x33, 0xbf, 0xff, 0x09, 0xee, 0x8a, 0x48, 0x33, 0x42, 0x7d,
- 0xf9, 0x7d, 0x50, 0x87, 0xd0, 0x9d, 0x7e, 0x10, 0xed, 0xbb, 0xf4, 0x76,
- 0x59, 0x1f, 0x7a, 0x25, 0x14, 0xb7, 0xca, 0x8d, 0x4e, 0xb8, 0x16, 0x18,
- 0xcd, 0xcc, 0x5d, 0x62, 0xdf, 0x56, 0x8a, 0x19, 0x3b, 0x8e, 0x61, 0xf3,
- 0xb0, 0x1e, 0xdc, 0xa1, 0x18, 0xcc, 0xf7, 0x34, 0x1c, 0x1a, 0x2c, 0xc0,
- 0xdd, 0x7b, 0x5a, 0x19, 0xdb, 0x4c, 0xe2, 0x66, 0x8d, 0xff, 0x1c, 0xde,
- 0xc7, 0x49, 0x53, 0xde, 0x11, 0x2a, 0x42, 0xab, 0x26, 0x7b, 0x80, 0x98,
- 0x79, 0x4e, 0xbb, 0xe4, 0x3d, 0x71, 0x4f, 0x91, 0x91, 0x7f, 0xdf, 0xdf,
- 0x60, 0xae, 0x38, 0x89, 0xfd, 0x83, 0xb2, 0x2e, 0x50, 0xa5, 0x1c, 0xef,
- 0x9f, 0xeb, 0xeb, 0x22, 0xe6, 0x3f, 0x64, 0x66, 0x70, 0x7e, 0x61, 0x25,
- 0x30, 0x5d, 0x41, 0xe8, 0xd3, 0x01, 0xf9, 0x9e, 0x0d, 0xff, 0xde, 0xb3,
- 0xfc, 0x5f, 0x90, 0x76, 0x4a, 0xcb, 0xb2, 0x6b, 0x05, 0x3f, 0xaa, 0x94,
- 0xf7, 0x01, 0x8f, 0x27, 0x2b, 0xca, 0xb3, 0xcf, 0x9c, 0xff, 0x54, 0x1f,
- 0x6f, 0x58, 0x7e, 0xbb, 0x8d, 0x7c, 0xdd, 0xd7, 0xad, 0xa8, 0x57, 0xca,
- 0x17, 0xb0, 0x6d, 0xf1, 0xcb, 0x2a, 0x65, 0x1d, 0x71, 0x54, 0x0d, 0x55,
- 0x29, 0xad, 0x43, 0x97, 0xb7, 0xfb, 0x9a, 0x15, 0x6d, 0x96, 0xf3, 0x7c,
- 0x39, 0x8b, 0xf7, 0xa5, 0x6c, 0xfe, 0xfe, 0x0b, 0xb9, 0xb6, 0x0a, 0xc9,
- 0x53, 0xb3, 0x65, 0xee, 0xee, 0x97, 0xfd, 0x4b, 0x51, 0x9c, 0xa8, 0x9f,
- 0xda, 0x5e, 0xbe, 0xef, 0xef, 0x5c, 0xd2, 0x5e, 0xb6, 0x6c, 0x55, 0x15,
- 0x8a, 0xa5, 0x7c, 0x06, 0xff, 0x8f, 0xbd, 0x86, 0x70, 0xc6, 0xde, 0x73,
- 0xb8, 0xcd, 0x6c, 0x88, 0x16, 0xe1, 0x33, 0x50, 0xaf, 0x8a, 0xcf, 0x2f,
- 0xb2, 0xb9, 0x6d, 0xb4, 0xb9, 0x88, 0xf9, 0xad, 0xdb, 0x88, 0x3e, 0xe4,
- 0x46, 0x26, 0xe3, 0x86, 0xde, 0x72, 0x5e, 0x39, 0xa4, 0xdc, 0x1d, 0xd0,
- 0xdb, 0xdf, 0x23, 0xd7, 0x78, 0x39, 0x10, 0xb7, 0x4a, 0x0d, 0xc3, 0xd7,
- 0xab, 0xe8, 0xe6, 0x1a, 0xc6, 0xb2, 0x17, 0x99, 0x3f, 0xb6, 0x05, 0x7a,
- 0xec, 0xe7, 0x8b, 0x4a, 0x64, 0x05, 0xae, 0xb4, 0xbf, 0xdd, 0xd2, 0x0c,
- 0x23, 0xf5, 0xb2, 0xac, 0x77, 0xf1, 0x77, 0x0c, 0xf3, 0xed, 0x6b, 0x6d,
- 0x08, 0xda, 0xff, 0x57, 0xe5, 0xbe, 0xef, 0xd2, 0x82, 0x1a, 0xfb, 0xff,
- 0x1d, 0x98, 0x9b, 0xba, 0xb0, 0x2e, 0x8c, 0x4d, 0xa6, 0x65, 0x3d, 0x67,
- 0x5a, 0x38, 0x73, 0x71, 0xbf, 0xf3, 0x0a, 0x07, 0xf3, 0x0d, 0x52, 0xac,
- 0x58, 0xf6, 0xfb, 0x54, 0x17, 0xdf, 0x97, 0x58, 0x7a, 0xc9, 0x7e, 0x67,
- 0xf9, 0xae, 0x42, 0xa5, 0xfd, 0xfd, 0xb1, 0x79, 0x8b, 0x9c, 0x78, 0x29,
- 0x51, 0x16, 0xf3, 0xf0, 0xf7, 0xe6, 0x45, 0x05, 0x58, 0x4f, 0x4e, 0xd6,
- 0x74, 0xd5, 0x33, 0x38, 0x67, 0x7f, 0xc7, 0x21, 0x1e, 0x92, 0xef, 0x37,
- 0x9c, 0x48, 0xd0, 0xa7, 0x07, 0xbb, 0x43, 0xfb, 0xed, 0xbe, 0x5f, 0xc7,
- 0xa6, 0x51, 0x79, 0xe6, 0xd7, 0x8c, 0xd5, 0x89, 0x49, 0xc6, 0x37, 0x69,
- 0x4b, 0xf2, 0x6e, 0x3d, 0xd3, 0xc6, 0x5c, 0x55, 0x75, 0x04, 0x71, 0x3b,
- 0xe3, 0xca, 0x2b, 0x09, 0xda, 0xe9, 0x42, 0xbd, 0xe3, 0xdb, 0xe4, 0x06,
- 0x65, 0x11, 0x3d, 0xf8, 0xae, 0xd2, 0x82, 0x31, 0xd6, 0x9f, 0x48, 0x88,
- 0x2d, 0x56, 0xc6, 0x0a, 0x39, 0x96, 0x43, 0xe4, 0xa3, 0x2f, 0x27, 0x34,
- 0x9c, 0xab, 0xf7, 0x20, 0x45, 0x7e, 0xfa, 0x52, 0x42, 0xb8, 0x9a, 0x17,
- 0x4f, 0x0c, 0xca, 0xfa, 0x60, 0x23, 0x1a, 0x12, 0xb2, 0x36, 0xec, 0xc5,
- 0xe3, 0x23, 0x5e, 0xda, 0xa3, 0x65, 0x6d, 0xa2, 0xed, 0xb6, 0x6a, 0x13,
- 0xec, 0x53, 0xd6, 0x14, 0xa3, 0xb8, 0xa9, 0xb7, 0x12, 0x4f, 0x8c, 0xf8,
- 0xf0, 0x3d, 0xf2, 0xf1, 0x3e, 0xd6, 0x7b, 0x25, 0xe1, 0x47, 0x6f, 0xca,
- 0x87, 0xe7, 0xc9, 0xcb, 0xb7, 0xf2, 0x5c, 0xbe, 0x05, 0x56, 0x60, 0x04,
- 0x91, 0x48, 0x1d, 0x63, 0x6c, 0xbc, 0x02, 0x6b, 0x57, 0x1e, 0x81, 0xda,
- 0x7b, 0x94, 0xc7, 0xf5, 0x8c, 0xd5, 0xd7, 0x23, 0x39, 0x18, 0x41, 0x72,
- 0xe4, 0x87, 0xe8, 0x19, 0x94, 0x71, 0xc9, 0x37, 0xa1, 0x64, 0x6f, 0x91,
- 0x81, 0xf9, 0x8c, 0xa7, 0x43, 0x23, 0xd2, 0x4f, 0x25, 0xfb, 0xfe, 0x4b,
- 0xdb, 0xff, 0x99, 0xb5, 0xf6, 0xf3, 0xd2, 0xf6, 0x91, 0x3f, 0xd1, 0xbe,
- 0xe8, 0x2a, 0xff, 0x6e, 0x9f, 0xac, 0x73, 0xb8, 0xd9, 0xa6, 0x07, 0x8e,
- 0x48, 0x66, 0x65, 0x29, 0xf4, 0xe8, 0x76, 0xc5, 0x68, 0x2a, 0x51, 0x26,
- 0xb1, 0x3d, 0x2d, 0xef, 0x71, 0x15, 0xe2, 0x79, 0x72, 0x02, 0x57, 0x48,
- 0xd7, 0xbe, 0x4d, 0xdb, 0x59, 0x42, 0x8c, 0x39, 0x63, 0x7e, 0x1a, 0x71,
- 0x4d, 0xf4, 0x57, 0x88, 0x57, 0xfb, 0xdd, 0x78, 0x37, 0xc4, 0x98, 0x6d,
- 0xef, 0xa1, 0xf6, 0xe0, 0x27, 0x09, 0x2f, 0xe7, 0xab, 0x36, 0x63, 0x38,
- 0xe6, 0x02, 0x55, 0xd9, 0x6b, 0x27, 0x12, 0x6d, 0xd8, 0x4f, 0x79, 0x5f,
- 0x49, 0x9c, 0xe7, 0xfc, 0xac, 0xa3, 0xfe, 0x45, 0xdf, 0xf1, 0x9c, 0xae,
- 0xbb, 0xa9, 0xeb, 0x99, 0x78, 0x31, 0xf1, 0x30, 0x9e, 0xa0, 0xfc, 0x8f,
- 0xf7, 0x1b, 0xd1, 0x39, 0xca, 0x31, 0x1c, 0x1a, 0x2a, 0x24, 0x7e, 0xbb,
- 0x71, 0x37, 0xb3, 0xe4, 0x49, 0xe9, 0x2b, 0x29, 0x6b, 0x93, 0x0a, 0xb9,
- 0xc7, 0x31, 0x8c, 0xf3, 0xde, 0x4f, 0xf8, 0x3b, 0xbc, 0xb0, 0x9c, 0x7d,
- 0x88, 0x7e, 0xfc, 0x76, 0x1e, 0xd0, 0x45, 0x7e, 0xb3, 0xbc, 0xfe, 0x98,
- 0xcd, 0x79, 0xba, 0x93, 0xad, 0xe8, 0xe9, 0x7f, 0x9f, 0x7c, 0x8e, 0x38,
- 0xe4, 0xad, 0xa7, 0xad, 0x67, 0xb0, 0x3d, 0xf5, 0xef, 0x55, 0x59, 0xee,
- 0xf9, 0x6a, 0x95, 0xec, 0xeb, 0x3d, 0x91, 0x28, 0xc4, 0x4b, 0xac, 0xb3,
- 0x36, 0xe4, 0xca, 0x3d, 0x2f, 0x39, 0x86, 0x5e, 0xe2, 0x6a, 0x8a, 0x7d,
- 0x24, 0xec, 0x36, 0xaa, 0x94, 0xbd, 0xf4, 0xc3, 0xf2, 0x85, 0x55, 0x4a,
- 0x92, 0xe7, 0x7d, 0xc9, 0x1f, 0xe2, 0xd9, 0x47, 0xb2, 0x3a, 0xdc, 0x6f,
- 0xb6, 0x61, 0x28, 0x75, 0x2a, 0xd7, 0xde, 0x8f, 0xa7, 0xbc, 0x9b, 0x26,
- 0xef, 0xba, 0xe4, 0xdf, 0x7b, 0xc9, 0x3e, 0xcf, 0x7a, 0x2a, 0x5d, 0x46,
- 0xde, 0x5c, 0x4c, 0x5b, 0x2b, 0x88, 0x79, 0x19, 0x4f, 0xdb, 0x16, 0x68,
- 0xd8, 0x75, 0xcd, 0x9c, 0x2a, 0x94, 0x69, 0xee, 0x5f, 0xd7, 0xbf, 0xcc,
- 0x7e, 0xca, 0x62, 0x15, 0x91, 0x8c, 0xbd, 0x07, 0x2a, 0x74, 0x4d, 0x35,
- 0x73, 0x68, 0x79, 0x2e, 0x1c, 0xc3, 0xdb, 0x89, 0xca, 0x58, 0x65, 0xa4,
- 0x9c, 0x78, 0x7b, 0x0e, 0xbd, 0xc3, 0xc4, 0x76, 0xf2, 0xe5, 0xd2, 0xbe,
- 0x4a, 0xb8, 0xed, 0x35, 0xbc, 0x2b, 0x30, 0x63, 0xf7, 0x2c, 0xf8, 0x76,
- 0xcf, 0x24, 0x5f, 0x61, 0x6e, 0x19, 0xb2, 0xac, 0x9f, 0x2f, 0xb4, 0xac,
- 0x2b, 0x79, 0x14, 0xf1, 0x38, 0x1b, 0x12, 0x3f, 0x8d, 0xa2, 0xd6, 0xf6,
- 0x57, 0x03, 0x75, 0xf6, 0xff, 0x46, 0xfa, 0x7a, 0x47, 0x68, 0xfe, 0xf8,
- 0xc3, 0xa1, 0xb9, 0xe3, 0xd5, 0x50, 0x07, 0xa6, 0xc1, 0xc1, 0xb6, 0x3e,
- 0x77, 0x8d, 0x85, 0x46, 0xfa, 0xf0, 0x1a, 0x53, 0xf8, 0x50, 0x1b, 0xf9,
- 0x50, 0x4f, 0xc8, 0x18, 0x3f, 0x82, 0x1b, 0xc9, 0x97, 0xdd, 0x03, 0x3e,
- 0xf6, 0x23, 0xf9, 0xb5, 0x33, 0x33, 0x9b, 0x3c, 0xfb, 0xd3, 0x0b, 0x85,
- 0x1b, 0xb5, 0x90, 0x1b, 0x1d, 0x45, 0xcb, 0xf8, 0x31, 0xdc, 0xca, 0x32,
- 0x1e, 0xe6, 0xfd, 0x7d, 0xe9, 0x1f, 0x92, 0x77, 0x58, 0x8c, 0x39, 0x19,
- 0xdc, 0xcc, 0xb6, 0x8b, 0x07, 0x9a, 0x70, 0xf7, 0xf8, 0x0a, 0xac, 0x1d,
- 0xb7, 0xb0, 0x3c, 0x34, 0x81, 0xe5, 0xe3, 0xe4, 0x9a, 0xe3, 0x79, 0x7f,
- 0x15, 0x9e, 0xb4, 0x82, 0x3c, 0x49, 0xe2, 0xd0, 0x2a, 0x7b, 0x1d, 0x4d,
- 0xa5, 0x1f, 0x36, 0x24, 0xe4, 0x9d, 0x9b, 0x38, 0x56, 0x8f, 0x0b, 0x56,
- 0x3f, 0x88, 0x4d, 0xe3, 0xb2, 0x2e, 0xfb, 0xf5, 0xd0, 0x9c, 0xf1, 0xd7,
- 0xd1, 0x30, 0x3e, 0x14, 0x9a, 0x37, 0x3e, 0x42, 0xb9, 0x13, 0x94, 0xad,
- 0x3f, 0x54, 0x33, 0x3e, 0x18, 0x0a, 0x8e, 0xef, 0x0d, 0x05, 0xc6, 0x9b,
- 0xb1, 0x75, 0x7c, 0x15, 0xb6, 0x8c, 0xb7, 0x63, 0xf3, 0xb8, 0xe0, 0xfc,
- 0x24, 0x96, 0x8d, 0x9f, 0xc1, 0xd2, 0xf1, 0x97, 0xd1, 0x38, 0x7e, 0x0a,
- 0x4b, 0xc6, 0x7f, 0x88, 0xa6, 0xf1, 0x1f, 0x73, 0x2c, 0xb2, 0xce, 0x2b,
- 0x6b, 0xbc, 0xf9, 0x67, 0x6a, 0xf9, 0xf7, 0x44, 0xf3, 0xdf, 0xd7, 0x70,
- 0x21, 0xaa, 0xbd, 0x81, 0xee, 0x3d, 0xf2, 0xbd, 0xc1, 0x5a, 0x6d, 0x93,
- 0xfd, 0xbe, 0xc1, 0xcb, 0xb2, 0x4f, 0x1d, 0x45, 0xc6, 0xe5, 0xef, 0xc5,
- 0xcb, 0x77, 0x31, 0xe4, 0x39, 0xe7, 0x24, 0xba, 0xd2, 0xe7, 0xad, 0xa8,
- 0x26, 0x65, 0xde, 0xc0, 0xe6, 0x3d, 0xf2, 0x3e, 0x71, 0x06, 0x5d, 0x49,
- 0x79, 0x0e, 0x2f, 0xef, 0xa0, 0xbf, 0x81, 0x2d, 0xa3, 0xb6, 0xaf, 0xa1,
- 0x71, 0x48, 0xde, 0x89, 0x69, 0xc3, 0x75, 0xc9, 0x8c, 0xbd, 0x56, 0x5e,
- 0x66, 0xe0, 0xef, 0x67, 0xe0, 0x41, 0xe6, 0x04, 0x05, 0xe4, 0xfd, 0xc5,
- 0xe8, 0x7c, 0x24, 0x6e, 0x15, 0x1a, 0x1e, 0xcc, 0x88, 0x18, 0x99, 0x77,
- 0x1d, 0xc5, 0xe8, 0xe0, 0xb5, 0xfb, 0x76, 0xc2, 0xef, 0x33, 0x44, 0xf7,
- 0x81, 0xd8, 0x28, 0x63, 0xec, 0x86, 0x7d, 0x19, 0xf2, 0x8b, 0x0e, 0xf8,
- 0xf9, 0x7f, 0x7b, 0x52, 0xf6, 0x21, 0x6d, 0x42, 0x74, 0x9f, 0xe8, 0xb0,
- 0x99, 0x3a, 0x9c, 0x64, 0xdc, 0x90, 0x67, 0x38, 0x46, 0x70, 0x2b, 0x64,
- 0x9d, 0x52, 0xc5, 0xf7, 0x06, 0xe5, 0x79, 0x83, 0xde, 0xf1, 0x25, 0xfa,
- 0xf4, 0x87, 0xca, 0x0f, 0x51, 0x76, 0x40, 0xf8, 0xd2, 0x04, 0x7a, 0x84,
- 0x6f, 0x47, 0x14, 0x23, 0x15, 0x38, 0x0b, 0xcf, 0x01, 0xc1, 0x5d, 0x27,
- 0x4a, 0xc6, 0xe4, 0xfb, 0x38, 0x40, 0x31, 0xf3, 0x12, 0x1c, 0x20, 0xa7,
- 0x3d, 0x70, 0x0a, 0xd8, 0x27, 0xeb, 0x56, 0xaf, 0x61, 0x72, 0x48, 0xe6,
- 0xad, 0x8d, 0xf3, 0x26, 0x7e, 0xf8, 0x7d, 0x0c, 0x0f, 0x79, 0xe8, 0xe3,
- 0x13, 0x1c, 0xc7, 0xeb, 0x78, 0x74, 0x8f, 0x3c, 0x17, 0x99, 0x89, 0x36,
- 0xd6, 0x3b, 0xc1, 0x3c, 0xbf, 0x75, 0xcc, 0xe4, 0x78, 0x56, 0xa1, 0xf3,
- 0xc0, 0x17, 0x78, 0x4c, 0xc3, 0x43, 0x07, 0xd6, 0x71, 0x8c, 0x71, 0x74,
- 0x8c, 0x75, 0xf3, 0x68, 0xc5, 0xc6, 0x9d, 0x26, 0xb9, 0xa0, 0xd8, 0xb4,
- 0x46, 0x3f, 0x6b, 0xe5, 0x98, 0xa4, 0x8f, 0xd5, 0xf8, 0x19, 0x31, 0xa6,
- 0x29, 0xb4, 0x1a, 0xe7, 0x6c, 0xbf, 0x5b, 0x8d, 0x2d, 0xfd, 0x46, 0xf0,
- 0x24, 0x56, 0x63, 0x33, 0xcf, 0x1f, 0xa5, 0xef, 0xcf, 0x21, 0x17, 0xbc,
- 0x93, 0xbe, 0xbd, 0x78, 0x78, 0x42, 0xbe, 0x9d, 0x80, 0xbe, 0x5d, 0x32,
- 0x1f, 0x6d, 0xf0, 0x8d, 0x65, 0x50, 0x3e, 0xc6, 0xec, 0x79, 0x27, 0xee,
- 0x2a, 0x43, 0x39, 0xbe, 0x11, 0x92, 0x3d, 0x0b, 0x3f, 0x40, 0xf1, 0x3e,
- 0x91, 0xf5, 0x87, 0x6c, 0xfb, 0x1c, 0x73, 0xf1, 0x53, 0x9c, 0x83, 0xfc,
- 0xb3, 0xf1, 0x5f, 0xe0, 0x60, 0x6a, 0x92, 0xb8, 0x7a, 0x9a, 0xc7, 0xe5,
- 0xcf, 0xa5, 0xbd, 0x76, 0x8e, 0x92, 0xdd, 0xff, 0xed, 0xc4, 0x8c, 0x3e,
- 0x59, 0xdf, 0x6d, 0x86, 0x2f, 0x29, 0x7c, 0x27, 0xb3, 0x8d, 0xf9, 0x4a,
- 0x7b, 0xd8, 0xe6, 0x3f, 0x46, 0x8c, 0xbc, 0xa7, 0xf9, 0xdb, 0x8a, 0x87,
- 0xbc, 0x27, 0x88, 0x15, 0x69, 0x3d, 0x7a, 0x33, 0xf5, 0x5b, 0xf4, 0xc8,
- 0x8f, 0xe0, 0x7c, 0xc4, 0x89, 0x42, 0xe6, 0x37, 0xa1, 0x90, 0xe8, 0x59,
- 0xde, 0x95, 0xcd, 0xe8, 0x85, 0xc4, 0xcc, 0x82, 0xbe, 0x0c, 0xe7, 0x27,
- 0x33, 0xbf, 0x00, 0x7e, 0xce, 0xcd, 0x0d, 0x68, 0xeb, 0x8f, 0x72, 0x6e,
- 0x3e, 0x45, 0x1b, 0x9b, 0xa0, 0xbd, 0x48, 0x4e, 0xf4, 0x32, 0x65, 0x74,
- 0xe5, 0xbe, 0xc9, 0x93, 0xd1, 0x9d, 0xd0, 0x4d, 0xbf, 0x5a, 0x95, 0x7d,
- 0x27, 0x05, 0xf6, 0xb3, 0xe7, 0x30, 0xf0, 0x06, 0x6d, 0x33, 0xcf, 0x67,
- 0x2c, 0xab, 0x9d, 0xf6, 0xd5, 0x3f, 0x2a, 0xbe, 0xb2, 0xb4, 0x2a, 0xfb,
- 0xbe, 0xee, 0x54, 0xae, 0x93, 0xaf, 0xeb, 0x20, 0x36, 0xe6, 0xef, 0xff,
- 0x08, 0x77, 0x32, 0x7e, 0x9d, 0x59, 0x78, 0x2a, 0x67, 0xf3, 0xd3, 0xab,
- 0xb3, 0xf8, 0xf5, 0x49, 0xdf, 0x0b, 0xfa, 0x2b, 0xfb, 0xdb, 0x3b, 0xd9,
- 0x6f, 0x1f, 0x01, 0xcf, 0x26, 0x0a, 0xe4, 0x29, 0xc1, 0x62, 0x17, 0x54,
- 0xaf, 0x0b, 0x85, 0x8c, 0x01, 0xd5, 0xd8, 0xe4, 0xb5, 0x70, 0xa3, 0x59,
- 0x80, 0x43, 0x75, 0xb7, 0x00, 0x15, 0xf1, 0x16, 0x97, 0xfd, 0x4e, 0xde,
- 0xef, 0xbf, 0xf4, 0x87, 0xef, 0xe4, 0x9d, 0xb1, 0xf3, 0xe1, 0x52, 0xe3,
- 0x76, 0xbc, 0x62, 0xc7, 0x09, 0x05, 0x25, 0x73, 0x65, 0x5d, 0xd2, 0x8f,
- 0x17, 0x8d, 0x5a, 0x7f, 0x85, 0x3c, 0x6f, 0x52, 0xce, 0x5a, 0x71, 0xaf,
- 0xbc, 0x87, 0xf7, 0xc7, 0xf6, 0x8f, 0x3f, 0x87, 0xad, 0xbb, 0xc2, 0x90,
- 0xf7, 0x3b, 0x9c, 0x46, 0xa1, 0x37, 0x2b, 0xbf, 0xc8, 0x26, 0xeb, 0x44,
- 0xb7, 0x71, 0x1c, 0x67, 0xe8, 0x8b, 0x67, 0xec, 0x75, 0x2a, 0xb7, 0xf1,
- 0xd7, 0x08, 0x56, 0xe4, 0xc7, 0x2f, 0x39, 0x8d, 0x92, 0xd5, 0x41, 0xf6,
- 0xfd, 0xda, 0x6a, 0xc1, 0xfe, 0x2d, 0xc9, 0x33, 0xf6, 0x9a, 0xac, 0xcb,
- 0xf8, 0x0f, 0xeb, 0x2d, 0x6f, 0x25, 0xcb, 0x3e, 0x95, 0xbb, 0x3f, 0x29,
- 0xeb, 0x38, 0xa6, 0x7c, 0xbb, 0xca, 0x69, 0xd7, 0x11, 0xbd, 0x5f, 0xac,
- 0xb3, 0x89, 0xbc, 0x7a, 0xb6, 0x71, 0xca, 0xea, 0xf4, 0xca, 0x18, 0xd6,
- 0x5c, 0x56, 0x47, 0xd6, 0x08, 0x34, 0xe9, 0x37, 0x2c, 0x63, 0xee, 0x4a,
- 0xff, 0x61, 0x9f, 0xb2, 0x7e, 0x5b, 0x60, 0x94, 0xe0, 0x6c, 0x45, 0x76,
- 0x4d, 0xe5, 0xa2, 0x8c, 0xed, 0xd5, 0xb2, 0xef, 0xae, 0xd0, 0x3e, 0xb7,
- 0xfb, 0x35, 0x2f, 0xd6, 0x7b, 0x30, 0x37, 0xde, 0x4a, 0xfb, 0x9d, 0x9a,
- 0x47, 0x6d, 0xae, 0xe3, 0x98, 0x32, 0xee, 0xdf, 0x78, 0x2f, 0xed, 0xe7,
- 0xf3, 0xb9, 0x7e, 0x45, 0x1e, 0xef, 0x94, 0x3e, 0x44, 0xae, 0xde, 0x5c,
- 0x1d, 0x3d, 0x1c, 0xb5, 0xfb, 0x57, 0x11, 0xde, 0x93, 0xef, 0xd3, 0xb2,
- 0x0a, 0x16, 0xe6, 0xdb, 0xc8, 0xd0, 0x0f, 0xad, 0xce, 0x42, 0xc6, 0xab,
- 0xb3, 0xf5, 0x0f, 0x62, 0x73, 0x42, 0xf4, 0x2c, 0xdf, 0x70, 0x25, 0x2e,
- 0xdb, 0xfc, 0xcb, 0xc5, 0x5c, 0xf6, 0x1a, 0x0c, 0x69, 0x71, 0xec, 0xaf,
- 0x93, 0x77, 0xc8, 0x5c, 0xf4, 0x85, 0x38, 0x71, 0xb0, 0x90, 0x38, 0x1a,
- 0xb7, 0xf7, 0x94, 0x1c, 0x34, 0xf5, 0xe8, 0xb3, 0xf2, 0x8d, 0xb2, 0xab,
- 0xec, 0xb5, 0xa7, 0xa6, 0x21, 0xc8, 0xf5, 0xfc, 0x7a, 0x52, 0xfe, 0xaf,
- 0x88, 0xb6, 0x23, 0x72, 0x89, 0x0d, 0x50, 0xba, 0x84, 0xbc, 0xeb, 0x54,
- 0x1b, 0x23, 0x67, 0xc4, 0x2b, 0x29, 0xd9, 0x7f, 0xf0, 0x5b, 0x2b, 0x5e,
- 0x2d, 0xfb, 0x1c, 0xa7, 0xd6, 0x29, 0x20, 0x97, 0x0b, 0x84, 0xcb, 0x94,
- 0xfc, 0xfb, 0x4e, 0x17, 0xff, 0x6e, 0xa5, 0xcd, 0x9c, 0xb3, 0xdf, 0x51,
- 0x93, 0xb3, 0x08, 0x1a, 0x92, 0xf2, 0xad, 0x52, 0x7d, 0x62, 0x39, 0x6a,
- 0x33, 0x35, 0x0e, 0x67, 0x8e, 0x93, 0x84, 0xb1, 0x82, 0x76, 0xb3, 0x25,
- 0x10, 0xb6, 0xdf, 0xc5, 0x5a, 0x96, 0xac, 0x09, 0x3e, 0xce, 0x1c, 0xfa,
- 0x1d, 0x96, 0xbf, 0x25, 0xfd, 0x3d, 0x6b, 0xc8, 0x2b, 0x63, 0xca, 0x63,
- 0xc3, 0x29, 0xfa, 0x06, 0xf5, 0x18, 0x11, 0xff, 0xf0, 0xa0, 0x22, 0x12,
- 0xa6, 0xff, 0x4a, 0x4c, 0x97, 0xf7, 0xb8, 0xf4, 0xbd, 0x71, 0x98, 0xc4,
- 0xfc, 0x1e, 0xda, 0x91, 0xec, 0x5b, 0xd6, 0xfd, 0x2b, 0x19, 0x5b, 0x8e,
- 0x5f, 0x78, 0xc6, 0x2f, 0x1c, 0xe0, 0xd9, 0xea, 0xdc, 0xde, 0x66, 0xf7,
- 0x6c, 0xc6, 0x3c, 0xcb, 0x7e, 0x6e, 0xdf, 0x66, 0x63, 0x8a, 0x66, 0xe8,
- 0x87, 0x7e, 0xe5, 0xe8, 0xc4, 0xd3, 0x0b, 0x8c, 0x8e, 0xc3, 0x6a, 0x66,
- 0xc8, 0x47, 0x7c, 0xb9, 0xde, 0x11, 0xdd, 0xc9, 0xff, 0xfe, 0xd7, 0xec,
- 0x6f, 0xab, 0x48, 0x5d, 0x3d, 0xb8, 0x4a, 0x95, 0xfd, 0x40, 0xcd, 0x18,
- 0xeb, 0x95, 0x77, 0x06, 0xf4, 0x96, 0xa7, 0x94, 0x4e, 0x6c, 0x08, 0x19,
- 0xcd, 0xed, 0x8a, 0xde, 0xf4, 0x0f, 0x8a, 0xee, 0x0f, 0x29, 0x52, 0x2e,
- 0xc8, 0xbc, 0xeb, 0x62, 0x3c, 0x75, 0xb1, 0x8f, 0x03, 0x09, 0x3d, 0x5c,
- 0xc5, 0xb2, 0x67, 0x4d, 0xc3, 0xf7, 0x3e, 0xdb, 0xfc, 0x57, 0x1e, 0x3b,
- 0xed, 0xf7, 0xc4, 0xa5, 0x7c, 0x74, 0xbe, 0xcb, 0xfe, 0xbe, 0x69, 0x0b,
- 0xe3, 0xae, 0x7c, 0x23, 0x38, 0x06, 0xad, 0x6f, 0x26, 0x4d, 0x4c, 0xef,
- 0xb9, 0x0d, 0xb2, 0xe7, 0xa0, 0x89, 0x09, 0xba, 0x07, 0xde, 0x48, 0x27,
+ 0x9d, 0xbc, 0x0d, 0x78, 0x1b, 0xe5, 0x95, 0x36, 0x7c, 0xcf, 0x48, 0xb2,
+ 0x65, 0x5b, 0xb6, 0xc7, 0x8e, 0x9c, 0x28, 0x6c, 0x9a, 0x68, 0xf0, 0x28,
+ 0x51, 0xb0, 0x69, 0x47, 0x89, 0x03, 0x82, 0x55, 0x89, 0xea, 0x98, 0xc4,
+ 0x81, 0x50, 0x9c, 0x12, 0x5a, 0xb3, 0x4b, 0x5b, 0xe1, 0xfc, 0x60, 0x42,
+ 0xa0, 0xa1, 0xb0, 0xef, 0x9a, 0xef, 0x65, 0x5f, 0xab, 0xb6, 0x93, 0x38,
+ 0x89, 0x2c, 0x39, 0x8e, 0x21, 0x61, 0xbf, 0x5e, 0x8b, 0x89, 0x9d, 0x38,
+ 0x80, 0x6c, 0x85, 0x36, 0xdd, 0x0d, 0x7d, 0xd3, 0x8d, 0x36, 0x09, 0x60,
+ 0xfe, 0xda, 0x40, 0xbb, 0x2c, 0xed, 0xcb, 0x07, 0xde, 0x14, 0x42, 0xd8,
+ 0xb6, 0x40, 0xb7, 0x3f, 0x1b, 0x5a, 0xca, 0xbc, 0xf7, 0x19, 0x49, 0x89,
+ 0x13, 0x28, 0xed, 0x7e, 0xbe, 0xae, 0xb9, 0xac, 0x99, 0x79, 0x7e, 0xce,
+ 0x73, 0x9e, 0x73, 0xee, 0x73, 0x9f, 0x67, 0x9e, 0x19, 0x3f, 0x50, 0x8a,
+ 0xfc, 0x5f, 0x39, 0x8f, 0x4f, 0x37, 0x6c, 0x5c, 0xbd, 0x60, 0xc1, 0xa7,
+ 0x1b, 0xe4, 0xdc, 0x39, 0xdd, 0xe9, 0xc4, 0x9f, 0xf9, 0xe7, 0xff, 0x73,
+ 0x0b, 0x7e, 0xcc, 0x9f, 0x03, 0xd0, 0x0a, 0xfd, 0xcb, 0x01, 0xb7, 0x1a,
+ 0x71, 0xde, 0xdc, 0x68, 0xc0, 0xed, 0x88, 0x4c, 0xb4, 0xad, 0x36, 0x80,
+ 0x68, 0xba, 0xce, 0xbf, 0x04, 0x7f, 0xb0, 0xe2, 0x5e, 0x27, 0xe4, 0xfa,
+ 0xa7, 0x22, 0x1f, 0x74, 0x7e, 0xef, 0x72, 0xfd, 0xbd, 0x21, 0x07, 0xdc,
+ 0x5a, 0x24, 0x0e, 0x6d, 0x2e, 0xdc, 0xb3, 0x58, 0xe7, 0x9b, 0xf3, 0xbe,
+ 0xa9, 0xa0, 0xa2, 0xd0, 0xd6, 0x69, 0xeb, 0x7b, 0xf3, 0x7c, 0xb1, 0x92,
+ 0x88, 0x86, 0x23, 0x19, 0xb4, 0xd4, 0xf7, 0x75, 0x5a, 0xe5, 0x46, 0x08,
+ 0x6e, 0xc3, 0x68, 0xed, 0x53, 0x3c, 0xe1, 0xf5, 0x8b, 0xe0, 0x29, 0x36,
+ 0x10, 0xbf, 0x28, 0x82, 0x96, 0x4b, 0xc6, 0x4a, 0xe3, 0xce, 0x88, 0x1b,
+ 0xcd, 0x19, 0x77, 0xfc, 0x2f, 0x22, 0x06, 0x96, 0x65, 0x66, 0x95, 0xa2,
+ 0xc2, 0x8d, 0x9e, 0xcc, 0xeb, 0x25, 0xb9, 0xf6, 0xea, 0xf3, 0xff, 0x83,
+ 0xd3, 0x72, 0xff, 0xa7, 0xc7, 0x9c, 0x11, 0x60, 0x53, 0xc2, 0xb2, 0x8a,
+ 0x22, 0x37, 0xdc, 0xa0, 0x46, 0x0c, 0xdf, 0x3e, 0x2c, 0x46, 0x9b, 0x86,
+ 0xfb, 0x36, 0x37, 0xfc, 0xa7, 0x72, 0x74, 0x90, 0x0d, 0x8f, 0x3a, 0x10,
+ 0xd5, 0x8e, 0xf3, 0xff, 0xec, 0xd9, 0xad, 0x61, 0x03, 0xbb, 0x47, 0xcf,
+ 0xf0, 0xba, 0xd3, 0xbe, 0xd6, 0xbd, 0x6b, 0xf6, 0xec, 0x9b, 0xc2, 0xc7,
+ 0xf1, 0xe0, 0xa8, 0xfc, 0xbe, 0x15, 0x9d, 0xf5, 0x0a, 0x26, 0x6f, 0x58,
+ 0x07, 0x87, 0x61, 0xa0, 0x67, 0x97, 0xe2, 0xec, 0xaa, 0x57, 0x11, 0xf5,
+ 0xea, 0xc1, 0x18, 0x27, 0xc1, 0x69, 0x20, 0x56, 0x1c, 0x09, 0x3b, 0xdf,
+ 0x4e, 0x44, 0x34, 0x87, 0x61, 0x59, 0xc1, 0xd0, 0x0c, 0x38, 0xaa, 0x2c,
+ 0xeb, 0x09, 0xd3, 0x03, 0xff, 0x97, 0x9e, 0x42, 0x7c, 0xb8, 0x05, 0xaa,
+ 0xf1, 0x14, 0xba, 0x86, 0x9f, 0xc2, 0x43, 0x3b, 0x4b, 0x31, 0x39, 0x8d,
+ 0xe3, 0x4d, 0xf9, 0xf0, 0xbd, 0x79, 0xd2, 0xb7, 0xc8, 0x51, 0xcf, 0xc3,
+ 0x8d, 0x49, 0xc7, 0x6b, 0xfc, 0x2f, 0x65, 0xce, 0x58, 0x93, 0x33, 0xce,
+ 0x95, 0xd9, 0xc4, 0x32, 0x3d, 0x17, 0x94, 0x89, 0x0f, 0x47, 0xf0, 0x5c,
+ 0x42, 0xc1, 0xfa, 0x50, 0x05, 0xa2, 0x55, 0x32, 0x5e, 0xcb, 0x1a, 0x35,
+ 0x4f, 0x59, 0x93, 0x9a, 0xf4, 0x35, 0x81, 0xe7, 0x79, 0x6f, 0x73, 0xe8,
+ 0x0d, 0x2b, 0xeb, 0x95, 0xf6, 0xbe, 0x4e, 0x1b, 0x5a, 0xc9, 0xeb, 0x4e,
+ 0xa4, 0x12, 0x88, 0x55, 0x44, 0x6e, 0xe4, 0xb9, 0x6e, 0xbe, 0xa3, 0xb8,
+ 0xdd, 0xef, 0x26, 0xdc, 0x5f, 0x2a, 0x37, 0xd4, 0x7b, 0x2a, 0xe1, 0xc4,
+ 0x0b, 0x94, 0xf9, 0x90, 0xb9, 0x0e, 0x2e, 0xe3, 0x6e, 0xb1, 0x39, 0x8e,
+ 0xeb, 0x47, 0x16, 0x66, 0x14, 0xea, 0x4b, 0xbb, 0x6e, 0x6c, 0x4e, 0x59,
+ 0xd6, 0x56, 0x33, 0x7a, 0x45, 0x09, 0x0d, 0xe2, 0x58, 0xa2, 0x05, 0xee,
+ 0x48, 0xc0, 0x7f, 0x1a, 0x61, 0x2c, 0xc9, 0x78, 0xf1, 0x64, 0x02, 0xce,
+ 0xc6, 0x79, 0x5e, 0x74, 0x65, 0x22, 0xb8, 0x3a, 0x63, 0xa2, 0x29, 0xf3,
+ 0xa7, 0x2d, 0xeb, 0xda, 0x94, 0x9f, 0x63, 0xf8, 0x83, 0x95, 0x1b, 0x83,
+ 0x8c, 0x2f, 0xf7, 0xbf, 0x27, 0x75, 0x11, 0xb6, 0x71, 0x8e, 0xb6, 0x70,
+ 0xfe, 0x96, 0x87, 0xb2, 0xd1, 0x12, 0xe8, 0xe6, 0x69, 0x44, 0xb0, 0x34,
+ 0x63, 0x70, 0x4e, 0x23, 0x58, 0x92, 0xaa, 0xd5, 0x86, 0x31, 0x1f, 0x51,
+ 0x5f, 0xce, 0xb6, 0xb7, 0x73, 0xbc, 0x6d, 0x81, 0x16, 0x94, 0xd3, 0x46,
+ 0xd2, 0x8b, 0xc2, 0x68, 0x64, 0xff, 0x2b, 0xfe, 0x8c, 0xfe, 0xaf, 0x67,
+ 0xff, 0xef, 0xb0, 0xff, 0xac, 0xdd, 0x3f, 0x9c, 0xd7, 0xf0, 0xdc, 0x4d,
+ 0x7b, 0xdc, 0x96, 0x76, 0x3a, 0x97, 0xa7, 0xbc, 0xd8, 0x9a, 0x36, 0x69,
+ 0x73, 0x72, 0xcb, 0x87, 0xcd, 0x83, 0xb3, 0xb0, 0x65, 0x50, 0xf7, 0x3d,
+ 0xcd, 0xdf, 0xdd, 0x23, 0x17, 0x61, 0xd3, 0xa0, 0x82, 0x3d, 0xc6, 0x45,
+ 0xe8, 0xe2, 0xef, 0xdd, 0x83, 0xb3, 0xf1, 0xe0, 0xa0, 0x03, 0xe1, 0x69,
+ 0xe7, 0x8f, 0x63, 0xd2, 0x71, 0x11, 0xe2, 0x23, 0x7e, 0x74, 0x25, 0x9e,
+ 0xb7, 0x75, 0x58, 0x1e, 0xf9, 0x5e, 0xc1, 0x9f, 0xe9, 0x3b, 0x7e, 0xac,
+ 0x4e, 0x68, 0xe8, 0x4a, 0x89, 0x1f, 0xb8, 0x69, 0x9b, 0xe2, 0x07, 0xbf,
+ 0x06, 0x2a, 0x34, 0x74, 0x67, 0x0a, 0xf7, 0x15, 0x38, 0x39, 0x6f, 0x6b,
+ 0x34, 0x37, 0xb6, 0xa6, 0xc4, 0x26, 0xa4, 0x4d, 0xb1, 0x0b, 0xf9, 0x5d,
+ 0x4d, 0xbb, 0x2b, 0x85, 0x7f, 0x6f, 0x29, 0x82, 0xf7, 0x6b, 0x78, 0xb3,
+ 0x41, 0xae, 0xd3, 0xde, 0x43, 0x52, 0xa6, 0x1f, 0xfb, 0xd2, 0xe2, 0xa7,
+ 0x7e, 0x34, 0x26, 0x26, 0xd8, 0x7e, 0x03, 0xdb, 0x36, 0xf1, 0xcf, 0x99,
+ 0x7a, 0xfc, 0x53, 0x26, 0x88, 0x7f, 0xa4, 0x1e, 0xbf, 0x93, 0xf1, 0xe3,
+ 0x60, 0x66, 0x16, 0xbe, 0x9d, 0xf1, 0xe1, 0x5b, 0x9c, 0xbf, 0xc7, 0x33,
+ 0x2d, 0xb4, 0x7d, 0x0d, 0x07, 0x32, 0xa2, 0xff, 0x22, 0x8e, 0xb7, 0x14,
+ 0xdd, 0x83, 0xb5, 0xc1, 0x63, 0xb4, 0xad, 0x7f, 0x34, 0xaf, 0x41, 0xb6,
+ 0xba, 0xc1, 0xb6, 0xc9, 0xad, 0xbc, 0xbe, 0x6d, 0xb0, 0x36, 0x7a, 0x89,
+ 0x62, 0x59, 0x6a, 0xa8, 0x2e, 0x7c, 0x54, 0x55, 0x31, 0xe9, 0xd5, 0xfd,
+ 0x59, 0x55, 0xf7, 0x47, 0xe1, 0x42, 0x82, 0xbe, 0x11, 0xaf, 0xd1, 0x87,
+ 0xe2, 0xb4, 0x29, 0xaf, 0x31, 0xcc, 0xf1, 0xe8, 0xfe, 0xb8, 0xea, 0xc6,
+ 0x96, 0x94, 0xbe, 0x3b, 0xae, 0x7a, 0x10, 0xcf, 0x94, 0xe2, 0x17, 0x83,
+ 0x7a, 0x6f, 0x5c, 0xfd, 0x3c, 0xe2, 0xd5, 0x96, 0xf5, 0xad, 0x10, 0x36,
+ 0xce, 0x88, 0x20, 0x5a, 0x13, 0x41, 0x6c, 0x76, 0xc4, 0x8b, 0x54, 0x0a,
+ 0x78, 0xa7, 0xcf, 0xf0, 0xfd, 0x9b, 0xd2, 0x82, 0xbf, 0x69, 0xd1, 0xfd,
+ 0x7e, 0xb5, 0x2e, 0x3e, 0xac, 0x2e, 0xa2, 0x4b, 0xc3, 0xef, 0x8b, 0x2c,
+ 0x43, 0x87, 0x7d, 0x4d, 0x81, 0x66, 0x78, 0xd0, 0x9d, 0xba, 0x02, 0x31,
+ 0x6f, 0x6d, 0xeb, 0x0e, 0xb5, 0xf6, 0x8c, 0xa9, 0xea, 0x13, 0x2d, 0xaa,
+ 0x65, 0xfd, 0x72, 0xe1, 0x3b, 0x96, 0x7f, 0xba, 0x65, 0x2d, 0x58, 0x28,
+ 0x7d, 0xfa, 0x51, 0x15, 0x31, 0xb1, 0xd2, 0x9e, 0xc3, 0x52, 0x9c, 0x1a,
+ 0xac, 0x66, 0x1f, 0x1a, 0xfe, 0xf5, 0x72, 0x3d, 0xb8, 0x4e, 0x2d, 0xc5,
+ 0x9b, 0x23, 0xa5, 0x38, 0xc9, 0xf1, 0xfc, 0xe7, 0xa0, 0x0f, 0xbf, 0x1e,
+ 0xb4, 0xac, 0x2f, 0x99, 0x7f, 0x89, 0x81, 0xea, 0x7e, 0xfc, 0xd3, 0xb8,
+ 0x17, 0xbf, 0xe0, 0xdc, 0xbc, 0x91, 0x88, 0xde, 0x35, 0x0d, 0x7a, 0x74,
+ 0x5c, 0x39, 0xf6, 0xd5, 0x0a, 0xd4, 0xb5, 0x54, 0x28, 0x7a, 0xf3, 0x76,
+ 0xe8, 0xbe, 0x4b, 0x14, 0x2f, 0x4e, 0xa7, 0x35, 0xfc, 0x34, 0x5d, 0x1b,
+ 0xfe, 0x21, 0xfb, 0xfc, 0xad, 0xf9, 0x84, 0x95, 0x9d, 0x2e, 0x7a, 0x13,
+ 0x1d, 0x51, 0xcf, 0x29, 0xea, 0x39, 0x45, 0x3d, 0xa7, 0xa8, 0x67, 0xca,
+ 0x70, 0x30, 0x45, 0x3d, 0x53, 0x77, 0xdf, 0xa2, 0x4d, 0x3d, 0xce, 0x79,
+ 0x3c, 0x60, 0xcf, 0x63, 0x98, 0xf3, 0xf5, 0x17, 0xf8, 0x5f, 0x36, 0xb6,
+ 0x3e, 0x6f, 0xfd, 0xad, 0x57, 0xc6, 0xd4, 0x3d, 0x3d, 0x87, 0x5f, 0x32,
+ 0xb6, 0xe7, 0xac, 0x98, 0x26, 0xe3, 0x92, 0xf1, 0xd9, 0xfa, 0xf3, 0x6f,
+ 0x54, 0xb6, 0x28, 0x28, 0xb5, 0xac, 0x9d, 0x66, 0xfe, 0xbe, 0xb7, 0x30,
+ 0xbe, 0x1b, 0x94, 0x9c, 0x5d, 0xed, 0x74, 0x53, 0xdf, 0xc1, 0xa8, 0xba,
+ 0x8c, 0xe7, 0x7a, 0x3c, 0x8a, 0xb9, 0xc5, 0xe7, 0x9f, 0x5f, 0x5b, 0x23,
+ 0xf3, 0xe1, 0x3f, 0x7b, 0x4e, 0x7b, 0xb4, 0xfb, 0xbb, 0x8d, 0xe7, 0x32,
+ 0x16, 0xb1, 0x45, 0xb1, 0x01, 0x2f, 0xed, 0xe5, 0xf2, 0xfc, 0x3d, 0xc4,
+ 0xd5, 0xc8, 0x46, 0xb4, 0x34, 0x3c, 0x6a, 0xf7, 0x51, 0x94, 0x14, 0xbf,
+ 0x51, 0xf0, 0xce, 0x15, 0x0a, 0x8e, 0x86, 0x0c, 0xda, 0xcc, 0x10, 0x71,
+ 0x01, 0x28, 0x4e, 0xc2, 0xed, 0x89, 0x44, 0x90, 0xe8, 0x83, 0xbb, 0x24,
+ 0x12, 0xc6, 0xfc, 0xbe, 0xda, 0xf6, 0x53, 0xd0, 0x83, 0x7d, 0x8a, 0xde,
+ 0x02, 0xd4, 0x99, 0x63, 0xd4, 0xe3, 0x25, 0x8a, 0xee, 0x2f, 0x52, 0xe0,
+ 0x56, 0x58, 0x2e, 0x90, 0x1e, 0xc2, 0x96, 0x8c, 0xfc, 0x0e, 0xc3, 0x48,
+ 0xff, 0xb6, 0xd0, 0x17, 0xed, 0x7e, 0x23, 0xed, 0xfe, 0x14, 0xc7, 0xae,
+ 0xfb, 0x89, 0xaf, 0x6e, 0x57, 0xa4, 0x1d, 0x7b, 0x13, 0x70, 0x17, 0x45,
+ 0x36, 0xe0, 0xa9, 0x44, 0xf5, 0xf4, 0x42, 0x39, 0x85, 0xe5, 0xfc, 0xe9,
+ 0xa9, 0xb2, 0xbc, 0x66, 0x45, 0xbd, 0x39, 0x59, 0x4a, 0x93, 0x43, 0xd8,
+ 0x9e, 0x92, 0xba, 0x11, 0xbb, 0xae, 0x93, 0x7d, 0xf4, 0x24, 0x6a, 0x9b,
+ 0xaf, 0x55, 0xf4, 0xf0, 0x23, 0xa8, 0x8b, 0xbe, 0xcd, 0x39, 0xec, 0x82,
+ 0x7e, 0xa6, 0x1d, 0x39, 0x59, 0xe6, 0xa5, 0x73, 0x72, 0x2c, 0x4e, 0x43,
+ 0xb9, 0x29, 0x05, 0x8f, 0xcf, 0x98, 0x96, 0xf7, 0x65, 0x28, 0xd7, 0x71,
+ 0xfe, 0x54, 0xc3, 0x8f, 0xeb, 0x68, 0x43, 0x1b, 0x76, 0x5a, 0xe8, 0x0e,
+ 0x55, 0xd3, 0x57, 0x5b, 0x50, 0x41, 0xbf, 0xbc, 0x53, 0x43, 0xb4, 0x32,
+ 0x12, 0x56, 0xae, 0xcf, 0x0c, 0xe7, 0xf5, 0x7f, 0xb4, 0x9a, 0xf2, 0x29,
+ 0x4d, 0xa9, 0x0b, 0xaf, 0x57, 0xe6, 0xe3, 0xde, 0x85, 0xd7, 0x3d, 0x45,
+ 0x1f, 0x5f, 0xbe, 0x4e, 0x1b, 0x81, 0xc2, 0x78, 0x53, 0x42, 0xfd, 0xea,
+ 0x26, 0xab, 0x05, 0x5d, 0xf6, 0x35, 0x07, 0x86, 0x9c, 0x51, 0x9f, 0x03,
+ 0x1f, 0x58, 0xd1, 0x55, 0x72, 0xad, 0x14, 0xb1, 0x96, 0x3a, 0x9f, 0x13,
+ 0x75, 0xe1, 0x4d, 0xf4, 0xb7, 0xc9, 0x55, 0x8d, 0xbc, 0x17, 0x30, 0x8f,
+ 0xa1, 0xd6, 0xbf, 0x09, 0xf2, 0xfb, 0x7d, 0xda, 0x48, 0xa3, 0xd4, 0x65,
+ 0x19, 0xb1, 0x39, 0x5d, 0x3b, 0x06, 0x2f, 0x36, 0xd1, 0xfe, 0x8a, 0x23,
+ 0xba, 0xb9, 0xcc, 0xe1, 0xc4, 0x7e, 0xe2, 0xb8, 0xc3, 0xe8, 0x45, 0x31,
+ 0xc7, 0xc8, 0xf8, 0x8a, 0x47, 0x12, 0xc0, 0xb3, 0xfd, 0x16, 0x1a, 0x43,
+ 0x1e, 0x2c, 0xb1, 0x6d, 0xf3, 0x90, 0x72, 0x75, 0xea, 0x43, 0x6b, 0xc8,
+ 0x59, 0x12, 0x55, 0x23, 0x01, 0xdf, 0x49, 0xb2, 0x81, 0xa2, 0x48, 0x9d,
+ 0xe6, 0x44, 0x5c, 0x69, 0xce, 0xf4, 0x28, 0xcb, 0x33, 0xbd, 0xca, 0x92,
+ 0x8c, 0xb4, 0x7d, 0x48, 0x59, 0x9a, 0xf1, 0x20, 0xdd, 0xaf, 0x60, 0x7b,
+ 0x88, 0x72, 0xd5, 0xe4, 0xec, 0x38, 0xd3, 0xaf, 0x12, 0x63, 0xdf, 0x21,
+ 0xc6, 0xea, 0x61, 0xb0, 0xef, 0x27, 0x12, 0xd5, 0x38, 0x44, 0x2c, 0xfd,
+ 0x71, 0x5a, 0x57, 0x51, 0x7a, 0x11, 0x5e, 0x19, 0xa9, 0xc0, 0xd8, 0xa0,
+ 0xc9, 0xdf, 0xf5, 0x78, 0x61, 0xc4, 0xb2, 0x7a, 0x4c, 0xcb, 0xda, 0x6b,
+ 0x1e, 0x52, 0x1a, 0xd9, 0x67, 0xd4, 0x19, 0x8f, 0x16, 0x47, 0x02, 0xe6,
+ 0x16, 0xf6, 0xe9, 0x88, 0xc4, 0x95, 0x28, 0xfb, 0xbb, 0x9a, 0xfd, 0x2d,
+ 0xcd, 0xf7, 0x97, 0xeb, 0x57, 0x64, 0x91, 0x7a, 0x85, 0x3a, 0x61, 0xd6,
+ 0x01, 0xf6, 0x25, 0x02, 0xc1, 0x42, 0xbd, 0xa5, 0xac, 0x73, 0xf5, 0xd9,
+ 0x3a, 0xc0, 0x70, 0x22, 0xc8, 0x39, 0x15, 0x5b, 0xf7, 0x33, 0x76, 0x7d,
+ 0x83, 0x18, 0xdb, 0x80, 0xb6, 0x61, 0xc1, 0xdf, 0x6b, 0xd4, 0xdc, 0x3c,
+ 0xe5, 0xb0, 0x56, 0x62, 0x5e, 0x0e, 0x6f, 0x83, 0xe8, 0xa3, 0x5f, 0x77,
+ 0xa5, 0xc4, 0xc6, 0xef, 0xf9, 0x72, 0x22, 0xa0, 0xe0, 0xb1, 0x40, 0xb6,
+ 0xa5, 0x1c, 0x95, 0x68, 0x0f, 0x89, 0x6d, 0x6e, 0xfc, 0xf2, 0x53, 0x86,
+ 0x1e, 0x5e, 0xa1, 0x70, 0xce, 0x02, 0x7a, 0xf3, 0x52, 0x05, 0x08, 0x8c,
+ 0x01, 0x6f, 0xa4, 0x2b, 0xb1, 0xda, 0x74, 0x40, 0xad, 0x0a, 0xa2, 0x37,
+ 0x33, 0x35, 0x2e, 0x98, 0xc4, 0x78, 0x69, 0x2f, 0x48, 0xbf, 0x2e, 0xc3,
+ 0x32, 0x2d, 0x67, 0xd3, 0x6e, 0xb6, 0xed, 0x0e, 0x64, 0x83, 0x2a, 0xe3,
+ 0xdd, 0x7e, 0x5e, 0x38, 0x46, 0xfc, 0x6f, 0x34, 0x5c, 0xc4, 0xff, 0x4a,
+ 0x34, 0x9a, 0xbf, 0xb3, 0x96, 0xad, 0x92, 0x7b, 0x85, 0x76, 0xe0, 0x2e,
+ 0x66, 0xbf, 0x6f, 0x19, 0xba, 0x7f, 0x94, 0x27, 0xd9, 0x74, 0xee, 0x7a,
+ 0x9c, 0x31, 0xab, 0x9b, 0xed, 0x6e, 0x66, 0xbb, 0xeb, 0x34, 0x3d, 0x1a,
+ 0x3f, 0x5b, 0x2e, 0x1b, 0x74, 0x40, 0xd7, 0xa4, 0x6c, 0x13, 0xdb, 0x5d,
+ 0xcd, 0x76, 0x7b, 0x35, 0x91, 0xef, 0x77, 0xd6, 0xba, 0x55, 0x72, 0x2f,
+ 0x67, 0x1f, 0xb9, 0x76, 0xef, 0x91, 0x76, 0xcd, 0xd1, 0x7c, 0x5f, 0x47,
+ 0x13, 0xe8, 0x77, 0x44, 0x18, 0x63, 0x1b, 0x02, 0xfe, 0x2e, 0xc6, 0xdb,
+ 0x26, 0xc6, 0x8e, 0x9c, 0x4d, 0x4c, 0x8d, 0x77, 0x88, 0x9f, 0x2b, 0x23,
+ 0xd7, 0xa4, 0x9c, 0xd8, 0xda, 0x24, 0xf5, 0x2c, 0xf1, 0xc5, 0x47, 0xfd,
+ 0x0a, 0xb6, 0x38, 0x71, 0x20, 0x41, 0xfc, 0xc7, 0x37, 0x68, 0x77, 0x7e,
+ 0xb4, 0x64, 0x6a, 0xb1, 0x66, 0x27, 0xe3, 0xa0, 0x59, 0x45, 0x5b, 0xcf,
+ 0xd9, 0xdb, 0x32, 0xb6, 0x3d, 0x69, 0xb7, 0x1d, 0x57, 0x5a, 0x32, 0x75,
+ 0x5a, 0x15, 0x63, 0xee, 0x91, 0xb3, 0xd8, 0x39, 0x27, 0x5a, 0x1a, 0x09,
+ 0x34, 0xaf, 0xe7, 0x24, 0xb9, 0x19, 0xdf, 0xbe, 0x37, 0xaf, 0x87, 0x76,
+ 0xd1, 0x4b, 0x3b, 0xcc, 0xcd, 0x6f, 0x73, 0x66, 0x8f, 0x2a, 0x18, 0x07,
+ 0xb5, 0x16, 0xeb, 0x76, 0xca, 0x7f, 0x72, 0x95, 0x86, 0xc7, 0x78, 0xad,
+ 0x16, 0xab, 0x87, 0xbf, 0x47, 0x3b, 0xd3, 0x7d, 0x62, 0x87, 0x5d, 0x67,
+ 0xe5, 0x12, 0x99, 0x44, 0x36, 0x91, 0xa9, 0x8f, 0xe5, 0x66, 0x51, 0x3f,
+ 0x82, 0x8d, 0xd5, 0x94, 0x67, 0x2b, 0xf9, 0xd0, 0x21, 0xe5, 0xf3, 0x94,
+ 0x27, 0xeb, 0xf2, 0xe2, 0xa1, 0x94, 0xc8, 0xa3, 0x44, 0x67, 0x46, 0x66,
+ 0xe1, 0x4c, 0x2a, 0x10, 0x7f, 0x02, 0x22, 0x5b, 0x8f, 0xd2, 0x2a, 0xf5,
+ 0x53, 0xbd, 0xbc, 0x57, 0x90, 0x11, 0x5a, 0xa5, 0x2d, 0x5b, 0x4e, 0xa6,
+ 0xeb, 0x39, 0xd7, 0x2e, 0xe3, 0x6f, 0xcb, 0x51, 0xe1, 0xa4, 0xad, 0x49,
+ 0xdb, 0xff, 0x61, 0x45, 0xb5, 0x6e, 0x5e, 0xf3, 0x72, 0x9e, 0xdc, 0xe4,
+ 0x05, 0x7a, 0xf0, 0x3a, 0x87, 0xd2, 0xe2, 0x91, 0x78, 0x4d, 0xfb, 0x4c,
+ 0xa7, 0x9d, 0x38, 0x9e, 0x58, 0xba, 0xb4, 0xcc, 0xf8, 0x34, 0x1e, 0x1b,
+ 0xf1, 0x61, 0x84, 0x73, 0xfb, 0x6c, 0x42, 0xe2, 0xeb, 0x2c, 0x3c, 0x9a,
+ 0xf6, 0xe0, 0x99, 0x84, 0x1f, 0x8f, 0x30, 0xfe, 0x4c, 0x24, 0x0c, 0xec,
+ 0x4f, 0x7b, 0xf1, 0x34, 0xed, 0x79, 0x34, 0xed, 0xa3, 0xbd, 0xd4, 0x63,
+ 0x38, 0xdd, 0x66, 0x8f, 0xe1, 0xc9, 0xc4, 0xbf, 0xcb, 0x58, 0x83, 0x32,
+ 0xd6, 0xcd, 0xf6, 0x58, 0x0b, 0x71, 0x7e, 0xd6, 0xd9, 0x79, 0x38, 0x91,
+ 0xb0, 0x71, 0xa0, 0x77, 0x99, 0x43, 0xe6, 0x81, 0x36, 0x3b, 0x20, 0x58,
+ 0xa0, 0xf7, 0xc7, 0x61, 0x61, 0x8f, 0x39, 0x93, 0xfe, 0xdf, 0x4b, 0x79,
+ 0xa9, 0x53, 0x8e, 0x1f, 0xae, 0x8a, 0x68, 0x79, 0x24, 0x10, 0xeb, 0xa3,
+ 0xde, 0x9d, 0x11, 0xd1, 0x43, 0x4e, 0xef, 0x2b, 0x32, 0x87, 0x14, 0xe1,
+ 0x7a, 0x97, 0x0c, 0xc4, 0xad, 0x32, 0x43, 0xf4, 0x1d, 0x20, 0xce, 0x02,
+ 0xf3, 0xf7, 0x38, 0x39, 0xbe, 0x9b, 0x38, 0x66, 0x13, 0x45, 0x46, 0x9d,
+ 0x56, 0x4d, 0xd9, 0x8f, 0x7c, 0x24, 0x06, 0x8a, 0x8e, 0xfe, 0x36, 0x3f,
+ 0x5f, 0xba, 0x83, 0xf2, 0xfa, 0x81, 0xc2, 0xbc, 0x58, 0xd6, 0x0e, 0xb3,
+ 0x30, 0x37, 0x35, 0xf0, 0x57, 0xeb, 0xf1, 0x21, 0x5a, 0xc4, 0x48, 0x62,
+ 0x1a, 0xe2, 0x9a, 0x9a, 0x6f, 0x3b, 0xaa, 0x14, 0x31, 0xff, 0xc0, 0xb8,
+ 0xf8, 0x7e, 0x39, 0xa2, 0x4e, 0xa9, 0x8f, 0x68, 0x51, 0x24, 0x10, 0x9c,
+ 0xab, 0x4e, 0xb5, 0x19, 0xc1, 0x01, 0xe9, 0x2b, 0x4e, 0x59, 0xcf, 0xc7,
+ 0x82, 0x91, 0x44, 0x01, 0x37, 0xfe, 0x3b, 0xf5, 0x2e, 0xd4, 0xa9, 0xc8,
+ 0x29, 0x7a, 0x55, 0x71, 0x74, 0x50, 0xf4, 0xe7, 0xc4, 0x4a, 0x73, 0x7a,
+ 0x5e, 0xe6, 0x59, 0x9c, 0x17, 0x62, 0x0e, 0xe7, 0xeb, 0x85, 0x7e, 0x2f,
+ 0xe5, 0xb6, 0x90, 0x0e, 0x5d, 0x8c, 0x4d, 0x36, 0xe7, 0x5c, 0x95, 0xcf,
+ 0x5b, 0x38, 0x4f, 0xea, 0x76, 0xea, 0xfa, 0xb3, 0x8e, 0xdc, 0x79, 0x9d,
+ 0xef, 0xa3, 0xfa, 0xd2, 0xb5, 0x18, 0x0a, 0x3a, 0x03, 0x86, 0xd2, 0x88,
+ 0xb9, 0x23, 0xf5, 0x4d, 0xce, 0xbe, 0xb6, 0x0d, 0xf4, 0xef, 0x7b, 0x4f,
+ 0x35, 0x7c, 0x16, 0x9b, 0xa9, 0x17, 0xa7, 0x6d, 0x67, 0x51, 0xc5, 0x65,
+ 0x2c, 0xb1, 0xfd, 0x49, 0x1d, 0x5f, 0x91, 0xef, 0x23, 0x6a, 0xe7, 0x2c,
+ 0x50, 0x5b, 0xf2, 0xe7, 0x77, 0x53, 0xdf, 0x32, 0x0e, 0x15, 0x3f, 0x20,
+ 0x97, 0x7d, 0x27, 0xf4, 0x59, 0x64, 0x6d, 0xcc, 0x76, 0xd2, 0xdf, 0xaf,
+ 0x62, 0x5d, 0xe2, 0xdf, 0xb8, 0xc4, 0x52, 0xc4, 0x4b, 0xe8, 0xd7, 0x45,
+ 0xf4, 0xd5, 0x6b, 0x32, 0xf7, 0xa0, 0x3d, 0x15, 0x08, 0x97, 0x28, 0xf7,
+ 0xe0, 0xd6, 0x8c, 0x0b, 0xb1, 0x61, 0x0f, 0xd6, 0x51, 0x27, 0xce, 0xa4,
+ 0xf8, 0xb9, 0x86, 0x75, 0xa3, 0x47, 0x67, 0x3a, 0xe9, 0x37, 0xeb, 0x46,
+ 0xbd, 0x3c, 0xa6, 0xf3, 0x70, 0x63, 0x35, 0x8f, 0x3d, 0xb4, 0xcb, 0x36,
+ 0xc6, 0x86, 0x23, 0x09, 0x13, 0x9d, 0xd4, 0xd5, 0x13, 0x89, 0x06, 0xdc,
+ 0x4b, 0xbd, 0x1d, 0x4a, 0x7c, 0x8a, 0x3a, 0x0a, 0xa3, 0x83, 0x73, 0xfc,
+ 0x58, 0x42, 0xb5, 0xf3, 0xab, 0xdb, 0x33, 0xff, 0x62, 0x45, 0xa7, 0x8b,
+ 0x9c, 0xa2, 0x0b, 0x99, 0xcf, 0x8f, 0xe8, 0x81, 0xfe, 0x3b, 0x55, 0x17,
+ 0xf5, 0xd8, 0xb6, 0xcb, 0xc0, 0xf6, 0x5d, 0x75, 0xb4, 0xbb, 0x8c, 0xe5,
+ 0xaf, 0x1a, 0xa0, 0x0e, 0xa6, 0xea, 0xe1, 0x08, 0x79, 0x81, 0xe8, 0x41,
+ 0xda, 0xbc, 0x8f, 0x63, 0xee, 0xe6, 0x3d, 0x1f, 0x1e, 0x4f, 0x7c, 0x97,
+ 0xbf, 0xc3, 0xca, 0x5d, 0x19, 0xf1, 0x79, 0xf1, 0xb7, 0x7f, 0x70, 0xe4,
+ 0x62, 0x6f, 0xa1, 0xdc, 0x16, 0x96, 0xb3, 0xac, 0xcd, 0x67, 0xe3, 0x4a,
+ 0x51, 0xb4, 0x84, 0x71, 0x65, 0x7f, 0x22, 0x10, 0x7e, 0xc6, 0x8e, 0x7d,
+ 0x4e, 0xda, 0x8e, 0xd8, 0x47, 0x8f, 0x6d, 0x1b, 0xcb, 0xce, 0xda, 0xc6,
+ 0xe4, 0x59, 0x0e, 0xd5, 0x9f, 0x9a, 0xea, 0x73, 0x39, 0xbb, 0x70, 0x26,
+ 0xf5, 0x5e, 0xdb, 0x8e, 0xd3, 0x82, 0x8f, 0x0e, 0x38, 0x06, 0x9c, 0x68,
+ 0x33, 0x2f, 0xa5, 0xbe, 0xab, 0x19, 0x6f, 0x8a, 0x78, 0x30, 0x4f, 0x1d,
+ 0xfe, 0x0b, 0x94, 0x0e, 0x64, 0xad, 0x12, 0xfe, 0x6e, 0x0e, 0x89, 0xbe,
+ 0xaf, 0xc2, 0xad, 0xc3, 0x0e, 0x14, 0x0d, 0x28, 0x78, 0xd2, 0xac, 0xc7,
+ 0x90, 0x37, 0x87, 0xbb, 0x6a, 0xf2, 0x52, 0x7b, 0x9e, 0x2e, 0x1e, 0x3f,
+ 0xfa, 0x8c, 0xc4, 0x85, 0x7b, 0x47, 0x3d, 0xf0, 0x25, 0x15, 0x78, 0x88,
+ 0x2b, 0x65, 0x46, 0x3d, 0xf5, 0xaa, 0xa1, 0x32, 0x69, 0xe2, 0x6b, 0x19,
+ 0xd2, 0xa6, 0x07, 0xc2, 0xb8, 0x93, 0xf3, 0x52, 0xfe, 0xc0, 0x95, 0xb8,
+ 0x83, 0xe5, 0x36, 0xf0, 0xde, 0x86, 0xd1, 0x6a, 0x1e, 0x5e, 0x1e, 0xd3,
+ 0x79, 0x34, 0xe0, 0xf6, 0xe1, 0x5a, 0x44, 0xab, 0xf5, 0xa0, 0x5f, 0x75,
+ 0xa0, 0x7a, 0x40, 0xf4, 0xae, 0x62, 0xe5, 0x02, 0x05, 0xe6, 0xa7, 0x8b,
+ 0xa1, 0xce, 0xfd, 0x38, 0xdf, 0xfd, 0x53, 0xb2, 0xbe, 0x6c, 0x0d, 0xd9,
+ 0x98, 0x2e, 0x3a, 0x16, 0x3b, 0xf9, 0x57, 0xce, 0x85, 0xc8, 0x2b, 0x7d,
+ 0x48, 0xac, 0x15, 0x1d, 0x7f, 0x12, 0x36, 0x30, 0xb2, 0x54, 0x74, 0xb1,
+ 0xcc, 0x47, 0x7d, 0x01, 0x67, 0xe7, 0x7f, 0x2a, 0x67, 0x95, 0xb8, 0xaf,
+ 0x87, 0x87, 0x6c, 0x8e, 0xe3, 0x67, 0xbe, 0xa8, 0xc7, 0x45, 0xe7, 0xe4,
+ 0x34, 0x6e, 0xd5, 0x80, 0xbf, 0xc8, 0xb8, 0x19, 0xb7, 0x71, 0x9e, 0xf6,
+ 0x26, 0xd4, 0xa5, 0x2e, 0xa8, 0xb3, 0x5c, 0x4c, 0x9c, 0x47, 0x4c, 0x1d,
+ 0xed, 0xc3, 0xcc, 0xb5, 0x86, 0xcb, 0xd1, 0xa5, 0x29, 0xee, 0x6d, 0xf5,
+ 0x8b, 0x24, 0xa7, 0xf6, 0x57, 0x1a, 0x50, 0xcb, 0x18, 0xff, 0xb7, 0x6b,
+ 0x70, 0x16, 0x19, 0x8a, 0x9a, 0xa8, 0x6f, 0x42, 0xbc, 0x0a, 0xce, 0x0a,
+ 0x03, 0x0a, 0x73, 0x66, 0xf4, 0x69, 0x10, 0xec, 0x89, 0x16, 0x19, 0xf7,
+ 0xe0, 0xb6, 0x14, 0xac, 0xd2, 0x08, 0xf3, 0xa1, 0x88, 0x41, 0x8e, 0x1b,
+ 0xf0, 0x15, 0xd1, 0x3f, 0x56, 0x93, 0x57, 0xac, 0x1d, 0x16, 0x39, 0x3c,
+ 0xe4, 0x1b, 0x86, 0xbf, 0x0d, 0xcc, 0xe1, 0x5b, 0xf4, 0xe0, 0x24, 0xf3,
+ 0xd8, 0xd5, 0xd4, 0xfd, 0x48, 0xe2, 0x1e, 0x34, 0xa6, 0x8e, 0x58, 0x1e,
+ 0xf2, 0xc8, 0x22, 0xa3, 0xf6, 0x4c, 0x17, 0x62, 0xf4, 0x0d, 0xe1, 0x47,
+ 0x6b, 0xe8, 0x1b, 0x3e, 0x64, 0x12, 0xea, 0x71, 0xb2, 0x0b, 0x74, 0x8c,
+ 0xae, 0xc7, 0xd7, 0x46, 0x67, 0x61, 0x3c, 0xb1, 0x01, 0x77, 0x66, 0xc8,
+ 0x95, 0xfa, 0xaf, 0xc2, 0x1d, 0xc3, 0x57, 0xe1, 0xf6, 0x9d, 0x46, 0x70,
+ 0x03, 0x75, 0xbd, 0x76, 0x98, 0x81, 0x72, 0xba, 0xb4, 0x5b, 0xd0, 0x95,
+ 0xf0, 0x45, 0xea, 0x22, 0xaf, 0xa7, 0x2c, 0x0a, 0x1c, 0xe6, 0x5f, 0x2d,
+ 0x5e, 0x8a, 0x17, 0x35, 0x28, 0xfe, 0xdd, 0xf5, 0x2f, 0x31, 0xb7, 0x17,
+ 0xd9, 0x11, 0x9d, 0x69, 0xfc, 0xc0, 0x7a, 0x50, 0xa3, 0x7f, 0x47, 0x10,
+ 0x9f, 0xd3, 0xf0, 0xbc, 0xf5, 0xd0, 0x2a, 0xb9, 0x7e, 0x9b, 0x13, 0xa5,
+ 0x2a, 0xaf, 0x49, 0x9b, 0x82, 0x4b, 0x75, 0x44, 0xe2, 0x8f, 0x6b, 0x33,
+ 0x6b, 0x25, 0xcf, 0x96, 0x27, 0x2f, 0x24, 0x16, 0x3f, 0x91, 0xf0, 0xa2,
+ 0x37, 0x95, 0xe3, 0x56, 0x37, 0x65, 0x84, 0x53, 0xb9, 0x51, 0xda, 0x27,
+ 0x71, 0x25, 0x8a, 0xf5, 0xfc, 0x5d, 0xd2, 0xa7, 0xb7, 0xc4, 0x91, 0x60,
+ 0x9b, 0x4d, 0x9c, 0x0b, 0xda, 0x6b, 0x9f, 0x03, 0x25, 0x46, 0x73, 0xce,
+ 0x56, 0xfb, 0x56, 0xd0, 0x56, 0x35, 0x54, 0xf4, 0xf5, 0x70, 0xac, 0xb4,
+ 0x55, 0xd6, 0xbb, 0x83, 0xba, 0xf0, 0xf4, 0xad, 0xa2, 0xbd, 0xce, 0x42,
+ 0x59, 0x5f, 0x2b, 0xf1, 0x01, 0x8c, 0xeb, 0x16, 0x8e, 0x9a, 0x95, 0x79,
+ 0x7e, 0xda, 0x8c, 0x5b, 0x53, 0x51, 0xb4, 0xa5, 0x6a, 0xa3, 0x27, 0x65,
+ 0xad, 0xca, 0x95, 0xc3, 0xb0, 0x68, 0x8d, 0xe8, 0x62, 0x32, 0x8f, 0xa7,
+ 0x7a, 0x73, 0x8e, 0xd3, 0xe9, 0x9a, 0x5f, 0x29, 0xc8, 0xde, 0x83, 0x18,
+ 0xf3, 0x8f, 0x39, 0x91, 0x16, 0x58, 0x29, 0x91, 0x3b, 0x6e, 0xf9, 0x98,
+ 0x53, 0x7a, 0x22, 0xfa, 0xc6, 0xc5, 0x0e, 0xa3, 0xe3, 0x15, 0x25, 0x88,
+ 0xeb, 0x29, 0x43, 0x59, 0x5f, 0x27, 0x5e, 0x08, 0xe9, 0xbe, 0xef, 0x2a,
+ 0xfa, 0x99, 0x0d, 0x78, 0x05, 0x3f, 0xe3, 0xb5, 0xa2, 0xbe, 0x09, 0x3c,
+ 0x94, 0x79, 0x15, 0xa7, 0x28, 0xab, 0xda, 0xf7, 0xa1, 0xb5, 0xcc, 0x78,
+ 0x86, 0xe3, 0x77, 0x2b, 0x6f, 0x65, 0xa6, 0xda, 0xe2, 0x55, 0x58, 0xbd,
+ 0x53, 0xec, 0x4f, 0x0f, 0xc6, 0x89, 0xbd, 0x6d, 0x66, 0x85, 0x70, 0x79,
+ 0x89, 0x4f, 0x94, 0xbf, 0x45, 0xb0, 0x85, 0xfe, 0x41, 0x3b, 0xb0, 0xc7,
+ 0xd0, 0x6a, 0x63, 0xb2, 0x33, 0x09, 0x1b, 0x4b, 0x73, 0x7a, 0x8e, 0x28,
+ 0x6d, 0xa3, 0xbe, 0x52, 0x94, 0xfa, 0xf2, 0x7e, 0x90, 0x5b, 0xb3, 0x38,
+ 0x57, 0xf7, 0x3f, 0xad, 0x11, 0xef, 0xf9, 0x75, 0x2b, 0x98, 0x83, 0x55,
+ 0x72, 0x3c, 0xef, 0xf6, 0xc5, 0xad, 0xd2, 0xdc, 0x58, 0x9a, 0x7f, 0xa0,
+ 0x88, 0x4d, 0x06, 0xc9, 0xed, 0x3b, 0x71, 0x69, 0x48, 0x6f, 0xfd, 0xae,
+ 0x22, 0x65, 0xf5, 0xf0, 0x06, 0xa5, 0xd0, 0xcf, 0xcb, 0x38, 0x39, 0x22,
+ 0x7d, 0x48, 0x5f, 0x13, 0xcc, 0xc9, 0x72, 0x63, 0x10, 0x5f, 0x7a, 0xc4,
+ 0x9e, 0x4b, 0xf1, 0x27, 0x3f, 0x96, 0x73, 0x4c, 0xae, 0x3e, 0x1f, 0x0f,
+ 0x17, 0xed, 0xd5, 0x87, 0xb5, 0x99, 0x15, 0x58, 0xcd, 0xbc, 0x76, 0x75,
+ 0xa6, 0x85, 0xba, 0xdf, 0x48, 0x7c, 0x67, 0x46, 0xa0, 0xe5, 0x74, 0x7c,
+ 0xce, 0x3e, 0x74, 0xff, 0x24, 0x56, 0xf0, 0xfe, 0xcf, 0x9d, 0xa8, 0x68,
+ 0x61, 0x79, 0xfb, 0xbe, 0x29, 0xf8, 0x7d, 0xae, 0xcc, 0x47, 0x78, 0x98,
+ 0x1d, 0xe7, 0xf7, 0xda, 0x1c, 0xb1, 0xc5, 0xce, 0xbd, 0xae, 0xb6, 0xe7,
+ 0x5c, 0x38, 0x82, 0x85, 0x63, 0x66, 0x31, 0xf3, 0xaf, 0xba, 0xe0, 0xf9,
+ 0x9c, 0x50, 0x67, 0x16, 0x5a, 0xc0, 0x03, 0xe9, 0x4b, 0xf4, 0x72, 0xa2,
+ 0x26, 0xa7, 0x97, 0x4f, 0x2a, 0x7b, 0x3e, 0x76, 0xec, 0x49, 0x48, 0xdf,
+ 0x45, 0x36, 0x2f, 0x6d, 0xcc, 0x94, 0x22, 0xee, 0x15, 0x1d, 0x49, 0x7b,
+ 0xba, 0x5f, 0x64, 0x5a, 0xbb, 0x53, 0xec, 0xd8, 0xc2, 0x08, 0x65, 0xe8,
+ 0xb6, 0xe7, 0x2d, 0xc7, 0x25, 0x8f, 0x9c, 0x17, 0x9f, 0x65, 0x4c, 0x85,
+ 0xbe, 0x6f, 0x73, 0xe5, 0xf8, 0x66, 0x81, 0x2b, 0x58, 0xd6, 0x80, 0x59,
+ 0xe0, 0x0a, 0x32, 0xe6, 0xbf, 0x00, 0x63, 0x9d, 0x3d, 0xde, 0x35, 0xf9,
+ 0xb6, 0xbb, 0xcc, 0x00, 0xed, 0x5a, 0xb8, 0x54, 0x44, 0x59, 0xb3, 0x2b,
+ 0xc3, 0xb9, 0x95, 0xdc, 0x06, 0xb8, 0x93, 0xf7, 0xcb, 0x79, 0xff, 0xc5,
+ 0x90, 0x0b, 0x97, 0x4e, 0x97, 0xbe, 0xaf, 0x42, 0xc7, 0xce, 0x28, 0x2a,
+ 0x17, 0x06, 0x30, 0x69, 0x73, 0x89, 0x02, 0xef, 0x75, 0xe1, 0x8e, 0x9d,
+ 0x1f, 0x5a, 0x15, 0x36, 0x17, 0x33, 0x62, 0xe3, 0x8a, 0x8a, 0xed, 0x8b,
+ 0x84, 0xff, 0xba, 0x88, 0xef, 0xe4, 0xa2, 0xc2, 0xad, 0x5d, 0x65, 0xe4,
+ 0xb0, 0xc2, 0xe1, 0x02, 0xd9, 0x9b, 0x54, 0x68, 0x5a, 0x44, 0xb8, 0xdc,
+ 0x2c, 0x9b, 0xc3, 0x0a, 0x97, 0xfd, 0x56, 0xea, 0xd0, 0x14, 0x2e, 0x7b,
+ 0x96, 0x73, 0x30, 0xf7, 0x69, 0x61, 0x7e, 0xef, 0x81, 0x3b, 0xa2, 0xb7,
+ 0x6c, 0x52, 0x3a, 0xb1, 0x3c, 0x64, 0x98, 0x92, 0x53, 0x5f, 0xa9, 0xe8,
+ 0xc1, 0xd3, 0x08, 0x12, 0x6f, 0x5f, 0xc6, 0xc8, 0x60, 0xdc, 0x25, 0x76,
+ 0xb4, 0x29, 0x73, 0x4e, 0x9e, 0x5b, 0x29, 0x8f, 0x3b, 0x27, 0x8f, 0x79,
+ 0x1a, 0x2a, 0x9e, 0x6c, 0x70, 0x11, 0xb7, 0xfe, 0x0e, 0x6d, 0x3b, 0x55,
+ 0x2c, 0xb1, 0xb9, 0xf9, 0xdf, 0x11, 0x7f, 0x2f, 0x2a, 0xcd, 0x95, 0x07,
+ 0x3a, 0xe9, 0xdf, 0xef, 0x2f, 0x2c, 0x41, 0x68, 0x9a, 0x82, 0x2a, 0xa3,
+ 0x83, 0xf9, 0xf1, 0x87, 0x56, 0xdc, 0x49, 0x3a, 0x6b, 0x40, 0x2b, 0x89,
+ 0x44, 0x29, 0x5b, 0x93, 0x72, 0xcd, 0xf0, 0x20, 0xfb, 0xe9, 0x20, 0xef,
+ 0xf7, 0xe0, 0x2e, 0xda, 0xce, 0x5d, 0x8c, 0x65, 0x77, 0x31, 0x96, 0xdd,
+ 0x35, 0xfa, 0x2f, 0xbc, 0x3e, 0xdd, 0xfe, 0xbd, 0x29, 0x55, 0xb0, 0x65,
+ 0x27, 0xe3, 0x82, 0xe8, 0x77, 0x33, 0x7d, 0x47, 0xe2, 0x02, 0x28, 0x93,
+ 0x85, 0x93, 0x9c, 0xc7, 0x25, 0x9a, 0x1e, 0xcc, 0xe2, 0xeb, 0xae, 0x73,
+ 0x79, 0x5f, 0x21, 0xb6, 0xc8, 0x3c, 0xba, 0x70, 0x1b, 0x65, 0x0c, 0x86,
+ 0xfe, 0xcb, 0x42, 0x95, 0xf8, 0xee, 0x85, 0xf7, 0x73, 0xf3, 0x7a, 0xe4,
+ 0x2c, 0x07, 0x54, 0xc4, 0x4e, 0xe9, 0xf3, 0x7b, 0x6c, 0x4e, 0xf1, 0xa2,
+ 0xc9, 0xdc, 0x6d, 0xe7, 0xd1, 0xf9, 0x62, 0x2a, 0x6b, 0x47, 0xa3, 0xe8,
+ 0xe6, 0xb8, 0x57, 0x0f, 0x3f, 0x96, 0xd7, 0x4b, 0x61, 0xbc, 0x0a, 0xd5,
+ 0xe2, 0xa1, 0xff, 0xe4, 0x72, 0x95, 0xb6, 0x51, 0xe1, 0xb6, 0xd5, 0xfc,
+ 0x2f, 0xdc, 0xd6, 0xcb, 0xff, 0xc2, 0x73, 0xa7, 0xf3, 0xbf, 0x13, 0xfe,
+ 0xe9, 0x62, 0xc7, 0xf5, 0xe8, 0xdd, 0x65, 0x59, 0xc5, 0x81, 0x7a, 0x6c,
+ 0x19, 0xfd, 0x48, 0xbc, 0xbc, 0x40, 0x1e, 0x7b, 0x0e, 0xe8, 0x47, 0x2e,
+ 0xc1, 0x22, 0xbf, 0x5f, 0x95, 0xbe, 0x2d, 0x6c, 0x34, 0xaf, 0x62, 0x9f,
+ 0x8c, 0x80, 0xd5, 0x53, 0xfd, 0xa2, 0xd0, 0x46, 0x41, 0xdf, 0xc5, 0xf4,
+ 0x73, 0x68, 0x2e, 0xea, 0x7b, 0x65, 0x46, 0xea, 0x36, 0x29, 0x4b, 0x87,
+ 0xa7, 0x96, 0xef, 0x20, 0x1f, 0x3e, 0x4d, 0x5d, 0x17, 0xfc, 0xc8, 0x9b,
+ 0xcf, 0x2b, 0x98, 0x4b, 0xa4, 0x44, 0x97, 0x32, 0xbe, 0x5c, 0xae, 0x28,
+ 0xb6, 0x74, 0xe4, 0x6c, 0x1f, 0xa2, 0xb7, 0xf8, 0xf4, 0x12, 0x43, 0xec,
+ 0x28, 0x48, 0x5c, 0xd1, 0xc3, 0xcd, 0x84, 0xed, 0x53, 0x09, 0xc4, 0x1c,
+ 0x91, 0xe6, 0xa6, 0xb5, 0x89, 0xb9, 0xda, 0xf1, 0x7c, 0x2e, 0xba, 0x87,
+ 0x38, 0xae, 0x1a, 0xb2, 0x0e, 0x42, 0x5b, 0x19, 0x16, 0xdd, 0x75, 0x28,
+ 0xe7, 0xf2, 0xce, 0x28, 0x79, 0x97, 0x6a, 0xcb, 0xe8, 0x8c, 0x88, 0x6c,
+ 0x52, 0x87, 0xb2, 0x5f, 0xc0, 0xbf, 0x72, 0xba, 0xa8, 0x80, 0x67, 0x40,
+ 0x78, 0x97, 0x8e, 0x0d, 0x8c, 0xf3, 0x65, 0x03, 0x7e, 0xfa, 0x42, 0x35,
+ 0x4a, 0x1f, 0x88, 0x60, 0xfd, 0xa8, 0x86, 0x92, 0x07, 0x2c, 0x6b, 0x6e,
+ 0xa8, 0x87, 0x5c, 0xf6, 0xb2, 0x22, 0xc9, 0x9d, 0x9c, 0x49, 0x62, 0x16,
+ 0xf1, 0xad, 0x3d, 0xa5, 0xe0, 0x6a, 0xc6, 0xd3, 0x28, 0x71, 0xa8, 0xdd,
+ 0xc6, 0x39, 0xab, 0x73, 0x4e, 0xc4, 0x45, 0x1b, 0x5a, 0xc5, 0xfb, 0xad,
+ 0xc4, 0xc0, 0x56, 0x62, 0x9a, 0x65, 0xbd, 0x7f, 0x39, 0x3a, 0xcb, 0x22,
+ 0x37, 0x13, 0x0b, 0x6b, 0xc9, 0x89, 0x25, 0x7e, 0x5f, 0x8e, 0x35, 0x8c,
+ 0xfd, 0xc5, 0x49, 0x3b, 0x9f, 0xa2, 0xee, 0x18, 0xa3, 0x32, 0x8c, 0x71,
+ 0x94, 0xfd, 0x69, 0x72, 0x5c, 0xe1, 0xbb, 0x95, 0xc9, 0x0d, 0x8c, 0x75,
+ 0x1e, 0x54, 0x0c, 0x5c, 0x86, 0x3b, 0x19, 0xcf, 0xef, 0xd8, 0xe9, 0x47,
+ 0x7a, 0xd1, 0x55, 0x94, 0xef, 0x1e, 0xac, 0x4f, 0x19, 0x92, 0x43, 0x45,
+ 0x83, 0x8b, 0xc8, 0xb7, 0x33, 0x82, 0x3b, 0x92, 0x8f, 0x95, 0x61, 0x49,
+ 0x0b, 0x10, 0x4c, 0x16, 0xf0, 0x2d, 0x2a, 0x6b, 0x47, 0x30, 0x92, 0xe7,
+ 0x63, 0xdb, 0x39, 0x5e, 0x24, 0xeb, 0x70, 0x2d, 0x98, 0xcf, 0x58, 0x20,
+ 0xf6, 0xa5, 0x31, 0xc7, 0x2c, 0x51, 0x0c, 0xdf, 0x1e, 0xfa, 0xa9, 0xe4,
+ 0x3d, 0x57, 0x24, 0x0b, 0xb1, 0x4f, 0xcf, 0x2e, 0x76, 0x74, 0x12, 0x47,
+ 0xf4, 0x8d, 0xbf, 0x53, 0xf4, 0xf6, 0x13, 0xca, 0x2b, 0xd8, 0x37, 0xf6,
+ 0x2a, 0x86, 0xc6, 0xdc, 0xca, 0xe8, 0x98, 0xf4, 0x35, 0x81, 0xbe, 0xcc,
+ 0x9f, 0xea, 0x6b, 0xea, 0xfa, 0xcb, 0xa2, 0xf3, 0xd6, 0x6c, 0xae, 0xce,
+ 0xe7, 0x89, 0x4b, 0xcf, 0xe3, 0xc7, 0x32, 0x27, 0x62, 0x97, 0x5e, 0xf4,
+ 0xa4, 0xce, 0xad, 0x0b, 0xf4, 0x27, 0xb6, 0xd9, 0xfe, 0xd9, 0x92, 0x11,
+ 0x7b, 0x55, 0x19, 0x33, 0x2f, 0xce, 0xe7, 0x2c, 0xb5, 0xd4, 0x41, 0x9f,
+ 0x7d, 0x6f, 0x9f, 0xf9, 0x29, 0x64, 0xed, 0x6b, 0x8b, 0xe9, 0x9b, 0xd5,
+ 0x28, 0x26, 0x26, 0x06, 0x43, 0x3e, 0x14, 0x57, 0xc9, 0x3a, 0xce, 0xb9,
+ 0xdc, 0x7f, 0xc3, 0x4e, 0x86, 0x64, 0x1b, 0x73, 0x1a, 0x89, 0x7f, 0xb5,
+ 0x9c, 0xef, 0x1c, 0xce, 0xac, 0xa7, 0x0d, 0x5d, 0x27, 0x36, 0xe4, 0xca,
+ 0xd9, 0xd0, 0x47, 0xd7, 0x17, 0x54, 0x90, 0xfb, 0x69, 0x15, 0x76, 0xde,
+ 0xd7, 0xa4, 0x5c, 0x9f, 0xb7, 0xab, 0xcf, 0x67, 0x1e, 0x2d, 0xca, 0xe7,
+ 0x66, 0x17, 0x94, 0xff, 0x38, 0x1d, 0x5c, 0xf6, 0x67, 0xe8, 0x40, 0xe2,
+ 0x81, 0xe4, 0x04, 0xa2, 0x83, 0xf3, 0xf3, 0xf2, 0xfe, 0x44, 0x35, 0x71,
+ 0xef, 0x42, 0x5d, 0xcc, 0xcc, 0xeb, 0x62, 0x31, 0xb1, 0x4b, 0xfe, 0x5b,
+ 0x38, 0x65, 0x7a, 0xf1, 0xa2, 0x26, 0xe3, 0x5e, 0x8c, 0xf5, 0x1c, 0xaf,
+ 0x9b, 0xba, 0x58, 0x1e, 0xaa, 0x44, 0xf0, 0xbc, 0x78, 0x50, 0xcb, 0xd8,
+ 0xf1, 0x21, 0x79, 0xa6, 0xfc, 0xf6, 0xe3, 0x05, 0xea, 0xe2, 0x8e, 0xe1,
+ 0xc5, 0xb8, 0x8b, 0xfe, 0x94, 0xe3, 0x90, 0xb9, 0xd8, 0xb0, 0x76, 0x58,
+ 0xda, 0x14, 0x8c, 0xfb, 0xd9, 0xd9, 0x71, 0xfe, 0x71, 0x5e, 0xfe, 0x0a,
+ 0xe5, 0x97, 0x67, 0x07, 0xb2, 0x16, 0x2d, 0xcf, 0x11, 0x64, 0x2c, 0xc6,
+ 0x14, 0xdc, 0xb1, 0xac, 0x83, 0xe6, 0x3c, 0xc4, 0xaa, 0xf5, 0x7e, 0x89,
+ 0x8f, 0xfd, 0xc4, 0x03, 0x07, 0xf3, 0xc8, 0xa2, 0x48, 0x94, 0xfe, 0xac,
+ 0x5e, 0xe5, 0x80, 0x5a, 0xef, 0x40, 0x27, 0xde, 0x30, 0x8d, 0xde, 0x75,
+ 0xf8, 0x14, 0xba, 0xbc, 0x16, 0xf6, 0xb2, 0x9d, 0xee, 0x54, 0x09, 0xda,
+ 0xeb, 0x69, 0x56, 0x2b, 0x3d, 0xd8, 0x91, 0x8a, 0xb7, 0x12, 0x16, 0x18,
+ 0x73, 0x1a, 0xfe, 0x2a, 0x11, 0xd0, 0x5b, 0x36, 0x90, 0xb7, 0x2c, 0xef,
+ 0x73, 0xc3, 0xaf, 0xe4, 0x72, 0xb4, 0x01, 0x55, 0xd6, 0x09, 0x23, 0x94,
+ 0xbd, 0xc7, 0xce, 0xf7, 0xfc, 0xd3, 0xa5, 0x1f, 0x3f, 0xe2, 0x19, 0xa9,
+ 0xeb, 0x47, 0xe9, 0x5c, 0x05, 0xcb, 0xe7, 0xea, 0xf1, 0xa8, 0x62, 0x59,
+ 0x0b, 0x42, 0x4e, 0xfb, 0xfe, 0xb6, 0x4c, 0x5d, 0xeb, 0x0d, 0xea, 0xab,
+ 0x56, 0x6e, 0x6d, 0x52, 0xd7, 0xa2, 0x4c, 0x0a, 0x8e, 0xfc, 0xd1, 0xf5,
+ 0xf9, 0x20, 0xe4, 0xb9, 0x89, 0xdb, 0x58, 0x89, 0xfd, 0xf9, 0xf5, 0x39,
+ 0x57, 0xe4, 0xbd, 0x2f, 0xef, 0x35, 0x24, 0x6f, 0x11, 0x9d, 0x4b, 0x7f,
+ 0x62, 0x0b, 0xd7, 0x15, 0x0b, 0x06, 0x76, 0x65, 0x16, 0xd2, 0x16, 0x7f,
+ 0x6b, 0x8d, 0x7a, 0xa7, 0x96, 0xbd, 0x51, 0xcd, 0xad, 0xb7, 0x4b, 0xd9,
+ 0x42, 0xb9, 0x8b, 0x89, 0x09, 0x8d, 0x18, 0x3e, 0xaf, 0x4d, 0xc9, 0x75,
+ 0x0b, 0x6d, 0xde, 0xc6, 0x72, 0xd2, 0xae, 0xe0, 0xef, 0x7f, 0x59, 0xfb,
+ 0xce, 0x6b, 0xaf, 0xd5, 0x95, 0x6b, 0xef, 0xee, 0x62, 0xc9, 0xdd, 0xfb,
+ 0x53, 0x45, 0xac, 0xf3, 0x4e, 0x9e, 0x07, 0x16, 0xca, 0x7c, 0xea, 0x82,
+ 0x32, 0xc4, 0x79, 0xe3, 0x4d, 0x6b, 0xcf, 0x79, 0x65, 0x96, 0x3b, 0xcf,
+ 0x2f, 0xe3, 0xc4, 0x1c, 0xe3, 0x55, 0xeb, 0xc8, 0x79, 0x65, 0xd2, 0x17,
+ 0x94, 0xb9, 0x1c, 0x63, 0xf5, 0x8f, 0x58, 0x43, 0xb9, 0xb9, 0xc9, 0xd2,
+ 0x7d, 0xdc, 0x33, 0x23, 0xad, 0x7f, 0x75, 0xc5, 0x3c, 0xbd, 0x63, 0xa6,
+ 0x43, 0x9e, 0xd9, 0xb8, 0x91, 0xcd, 0xcd, 0x4d, 0x5c, 0xe6, 0xc6, 0xb5,
+ 0xa0, 0x30, 0x37, 0xd7, 0xe5, 0xeb, 0x17, 0xda, 0xbd, 0xae, 0xe8, 0xfc,
+ 0x76, 0x0b, 0xd7, 0xaf, 0xb8, 0x40, 0xee, 0xef, 0x5c, 0x50, 0xee, 0xb7,
+ 0x7f, 0xa4, 0xde, 0x2f, 0x1c, 0xe7, 0x5f, 0x3f, 0xa0, 0x9e, 0x7f, 0xde,
+ 0x9c, 0x3f, 0x2f, 0xe8, 0xbf, 0xea, 0x82, 0xf2, 0x35, 0x17, 0x94, 0x7f,
+ 0x59, 0xfd, 0xf8, 0x7e, 0xd6, 0x5d, 0x50, 0xcf, 0x5e, 0xab, 0xc6, 0x53,
+ 0x67, 0x7d, 0x1e, 0x4d, 0x45, 0x08, 0x98, 0x4e, 0x05, 0x7e, 0xfa, 0xbe,
+ 0xff, 0xe9, 0x0b, 0xd6, 0xac, 0x9b, 0xce, 0xfa, 0xfe, 0x79, 0x9c, 0x33,
+ 0x56, 0x1c, 0x91, 0x18, 0x56, 0x44, 0xee, 0x2c, 0x3c, 0xb0, 0x4e, 0x3b,
+ 0x97, 0x67, 0x15, 0x62, 0x65, 0x45, 0xac, 0x24, 0xd2, 0x00, 0xff, 0xd8,
+ 0x2c, 0xff, 0x9b, 0x09, 0x59, 0xb7, 0xfc, 0x80, 0x5c, 0xca, 0xf0, 0xed,
+ 0xc7, 0x2c, 0xff, 0x4f, 0xd3, 0x6f, 0x15, 0xa3, 0xc2, 0x83, 0xab, 0x13,
+ 0x1f, 0x5f, 0x4f, 0x8d, 0x40, 0x59, 0xd6, 0xe0, 0x63, 0x7e, 0x05, 0xe7,
+ 0x35, 0xf3, 0x30, 0xe5, 0xaf, 0x45, 0xf2, 0x3d, 0xf5, 0x58, 0x43, 0x98,
+ 0xf1, 0x39, 0xf7, 0xbc, 0x76, 0x49, 0x46, 0xf7, 0x45, 0x95, 0xdc, 0x33,
+ 0xd9, 0xf6, 0xd0, 0x1f, 0xc8, 0x77, 0x3a, 0x29, 0x97, 0xc5, 0xbe, 0x80,
+ 0x0d, 0x09, 0xcb, 0x7a, 0x8a, 0x79, 0xaa, 0x3c, 0xeb, 0xff, 0x79, 0xfa,
+ 0xf7, 0xd6, 0x84, 0xd7, 0x89, 0xb7, 0x8c, 0xa9, 0xed, 0xf9, 0x51, 0x19,
+ 0x31, 0x99, 0x2f, 0xd9, 0x27, 0xea, 0x98, 0x51, 0xb7, 0x71, 0x2f, 0xfd,
+ 0x6e, 0x7e, 0x40, 0xf7, 0x27, 0xf1, 0xef, 0x96, 0xbf, 0x46, 0x0f, 0x0e,
+ 0x29, 0x85, 0x75, 0xe2, 0x0b, 0xd7, 0x83, 0x2b, 0x62, 0x2e, 0x8e, 0x6f,
+ 0x8f, 0xcd, 0xf7, 0x8b, 0x88, 0x71, 0x88, 0x39, 0x23, 0xb3, 0xfc, 0x5b,
+ 0x12, 0xf6, 0x38, 0xc9, 0x17, 0x15, 0x1c, 0x6b, 0x98, 0xe5, 0xef, 0x4e,
+ 0x7b, 0xb1, 0x9d, 0xf1, 0xb8, 0xc4, 0x68, 0xc0, 0x23, 0x69, 0x15, 0xb7,
+ 0xdd, 0xef, 0xc5, 0x5a, 0x72, 0xd1, 0x8d, 0x7d, 0xdf, 0x80, 0x71, 0xa9,
+ 0x13, 0xb7, 0xd2, 0xfe, 0xd6, 0xf5, 0x15, 0xdb, 0x39, 0xc8, 0xfa, 0x3e,
+ 0x27, 0xea, 0x2f, 0xad, 0x40, 0xbc, 0xa6, 0x18, 0xdf, 0x37, 0x1d, 0xcc,
+ 0x7b, 0xca, 0x30, 0x64, 0x63, 0xa2, 0xe4, 0xb2, 0x82, 0x73, 0xa2, 0x37,
+ 0x87, 0xbd, 0x2e, 0xf9, 0xf1, 0x58, 0xfe, 0x5b, 0x2b, 0x5b, 0xb3, 0xdd,
+ 0xc6, 0x5f, 0x47, 0xc4, 0xb4, 0xe3, 0x25, 0x90, 0xe3, 0x69, 0x5d, 0xe7,
+ 0x3d, 0x57, 0x6e, 0x51, 0xe6, 0x44, 0x02, 0x13, 0x8b, 0x15, 0x07, 0xc2,
+ 0x81, 0x8a, 0x58, 0x65, 0x24, 0x8c, 0x65, 0x99, 0x2e, 0x9f, 0xcf, 0x7e,
+ 0x56, 0x1d, 0xc1, 0xe9, 0x45, 0x26, 0x73, 0x60, 0x38, 0x97, 0x51, 0xf7,
+ 0x4d, 0xd4, 0xeb, 0x66, 0xf3, 0x0f, 0x56, 0xd6, 0xf6, 0x7b, 0x37, 0x62,
+ 0x9a, 0x65, 0xad, 0xa3, 0x7e, 0x1d, 0xd4, 0xe3, 0xcf, 0xf2, 0xfa, 0x15,
+ 0x9d, 0x96, 0x8d, 0xfd, 0xde, 0x3a, 0x46, 0xfd, 0xba, 0xd9, 0x9e, 0x9b,
+ 0xed, 0x95, 0x8c, 0x9d, 0xaf, 0xe7, 0x62, 0xca, 0xb3, 0xcc, 0x96, 0xa1,
+ 0x52, 0x9e, 0xf5, 0xf9, 0xa3, 0x4a, 0x01, 0xb7, 0xff, 0xd4, 0x98, 0x5e,
+ 0x99, 0x92, 0x83, 0x88, 0xfe, 0xfd, 0xd4, 0xbf, 0x60, 0xb8, 0xcc, 0x41,
+ 0xbd, 0xac, 0xfb, 0xf4, 0x02, 0xa3, 0x4c, 0xd6, 0x15, 0x4c, 0x33, 0x22,
+ 0xf8, 0x76, 0x8b, 0x07, 0x6f, 0x26, 0xca, 0xed, 0x71, 0x5f, 0x3a, 0xd7,
+ 0xb2, 0x1e, 0x0f, 0xf9, 0xf1, 0x73, 0xa3, 0x2e, 0xbc, 0x40, 0xd5, 0x31,
+ 0xa9, 0x79, 0x91, 0x20, 0xce, 0x76, 0xa5, 0x66, 0x73, 0xbe, 0xbc, 0xd8,
+ 0x92, 0xc2, 0x46, 0xda, 0x93, 0xdf, 0x11, 0x01, 0xde, 0x48, 0x18, 0xc1,
+ 0xcd, 0xec, 0x7f, 0xd8, 0xdb, 0x40, 0xfe, 0xad, 0x36, 0x91, 0xaa, 0xc5,
+ 0x4b, 0x22, 0x46, 0x7c, 0x2b, 0xfe, 0xc3, 0x1a, 0x22, 0xce, 0x17, 0x85,
+ 0x64, 0x6d, 0x6e, 0x0e, 0x8e, 0x6b, 0x0e, 0x3c, 0x1b, 0x9c, 0x8e, 0x28,
+ 0xdd, 0xb1, 0xcc, 0x78, 0xcb, 0xfa, 0xa1, 0x57, 0xfa, 0x91, 0xb1, 0xfc,
+ 0x86, 0xe3, 0x50, 0x6c, 0x2c, 0xdc, 0x92, 0x6a, 0xa0, 0xbe, 0x2f, 0xec,
+ 0xff, 0xdf, 0xad, 0x49, 0xaf, 0xf4, 0xcf, 0x5c, 0x9e, 0xf1, 0xec, 0xc8,
+ 0x1f, 0xc5, 0xee, 0x97, 0xac, 0xe7, 0xec, 0x36, 0x17, 0xb9, 0x73, 0x71,
+ 0x50, 0xda, 0xfb, 0x17, 0x8e, 0x4f, 0xda, 0x2c, 0xf4, 0x23, 0x7a, 0xcb,
+ 0xba, 0xc5, 0x9f, 0xb7, 0xa4, 0x44, 0x7f, 0x82, 0x57, 0xc7, 0x2c, 0x4c,
+ 0x97, 0xf3, 0x87, 0xed, 0xb2, 0x71, 0xea, 0xab, 0x8b, 0x36, 0xc4, 0xd8,
+ 0xcb, 0x3c, 0x4e, 0x76, 0x51, 0x68, 0x76, 0x9e, 0xb6, 0x89, 0xdc, 0x7e,
+ 0xc8, 0x5b, 0x89, 0x2d, 0x26, 0xed, 0xce, 0x50, 0x2f, 0x76, 0x42, 0x72,
+ 0x53, 0x39, 0x77, 0x61, 0xd2, 0xeb, 0xc0, 0x56, 0xd3, 0x89, 0x76, 0x43,
+ 0xd5, 0xe5, 0xba, 0x23, 0x24, 0xe7, 0x2e, 0xf8, 0x6b, 0x14, 0x6c, 0x0f,
+ 0xab, 0x58, 0x6f, 0x74, 0xf9, 0xe5, 0xfa, 0x92, 0x90, 0x9c, 0x2b, 0x58,
+ 0x43, 0x9d, 0xc4, 0x35, 0x05, 0x1b, 0x0c, 0x79, 0xbe, 0x98, 0xe3, 0xbe,
+ 0x31, 0x58, 0xd6, 0x76, 0xb3, 0xf1, 0x8a, 0x32, 0x48, 0x9c, 0x17, 0x2e,
+ 0xf7, 0xde, 0xcd, 0xf3, 0x03, 0x71, 0x12, 0x31, 0x3d, 0x56, 0x42, 0x3f,
+ 0xdd, 0xd2, 0x37, 0x87, 0xf5, 0x14, 0x72, 0x1c, 0xa7, 0x6f, 0x1b, 0x24,
+ 0x7e, 0x06, 0xfc, 0x3f, 0x65, 0xf2, 0x34, 0xe4, 0x9d, 0x47, 0xcd, 0x1a,
+ 0xfe, 0x93, 0x9c, 0xb7, 0x4a, 0xc3, 0xb9, 0xf1, 0x07, 0xd0, 0xdb, 0x4b,
+ 0x94, 0x79, 0xc1, 0x0a, 0xe6, 0x00, 0x71, 0xe2, 0xfb, 0xc8, 0x98, 0x13,
+ 0x9b, 0x53, 0x86, 0xb6, 0xcf, 0xe6, 0x6e, 0x4e, 0xea, 0xc2, 0xc9, 0x1c,
+ 0x3f, 0xa0, 0x4d, 0x28, 0x85, 0xf3, 0x39, 0x82, 0x0d, 0xe4, 0xe2, 0x82,
+ 0x6f, 0x71, 0xeb, 0xc9, 0x06, 0x49, 0xdb, 0xdc, 0xfe, 0x58, 0xda, 0xc3,
+ 0x43, 0xe3, 0xe1, 0xf5, 0xaf, 0x4d, 0xfb, 0xfc, 0x6b, 0xd2, 0xf0, 0xb7,
+ 0xa5, 0x0b, 0x76, 0x59, 0xf0, 0x6d, 0xc1, 0x36, 0x8b, 0x7c, 0x33, 0x97,
+ 0x73, 0x75, 0x49, 0x4e, 0x03, 0x79, 0x3e, 0xf6, 0xde, 0xcd, 0x4f, 0xd1,
+ 0xd6, 0x5d, 0xe4, 0xf2, 0x5b, 0x8d, 0x78, 0x54, 0x9e, 0xd7, 0x19, 0x21,
+ 0xdd, 0x57, 0xa4, 0xf8, 0xb1, 0xa5, 0xfe, 0x77, 0x9c, 0x4f, 0x72, 0xdc,
+ 0xf4, 0xa7, 0x4a, 0x72, 0xf3, 0x21, 0x7e, 0x26, 0x18, 0xe0, 0x67, 0x1e,
+ 0xe4, 0xf3, 0x77, 0xb1, 0x9f, 0x4d, 0xe9, 0xa9, 0x3e, 0xa0, 0xe0, 0x1a,
+ 0xb6, 0xd5, 0x18, 0x82, 0x73, 0x69, 0xfd, 0x7f, 0x59, 0x59, 0xef, 0xd4,
+ 0x7d, 0x11, 0x20, 0x87, 0x80, 0xb3, 0xad, 0x5e, 0xce, 0x15, 0x34, 0x86,
+ 0xe5, 0x5c, 0x41, 0x9b, 0x91, 0x93, 0x4f, 0x7c, 0xb7, 0x9b, 0xb8, 0x7d,
+ 0xee, 0xfc, 0x42, 0x2c, 0x32, 0x71, 0x7b, 0x0a, 0xb1, 0xa2, 0x88, 0x60,
+ 0x91, 0xdb, 0xff, 0x5c, 0xba, 0x9e, 0x5c, 0x5c, 0x9e, 0x7f, 0xbb, 0x39,
+ 0xe7, 0x1e, 0xff, 0xb3, 0xe9, 0x2b, 0x71, 0xdb, 0xae, 0x30, 0xda, 0x77,
+ 0xc9, 0x86, 0x23, 0xe6, 0x60, 0xa1, 0x80, 0x7f, 0x14, 0x9a, 0xff, 0x38,
+ 0x75, 0x72, 0x94, 0x72, 0x1e, 0x3b, 0x4f, 0x4e, 0xd1, 0x21, 0xfc, 0x77,
+ 0x24, 0xdc, 0x48, 0x87, 0xde, 0xb7, 0xe2, 0x36, 0xe7, 0xf0, 0xfa, 0xef,
+ 0x4c, 0xf8, 0x91, 0xb5, 0xb9, 0xe7, 0xbf, 0xbb, 0x25, 0x47, 0xec, 0x49,
+ 0xc5, 0xa3, 0x4c, 0x79, 0xf3, 0xf3, 0xab, 0x87, 0x65, 0x6e, 0xdf, 0x48,
+ 0xc8, 0xbd, 0xe8, 0x37, 0x54, 0xe8, 0x7e, 0x95, 0xb1, 0xb4, 0xdf, 0x14,
+ 0xfb, 0xb5, 0xec, 0x67, 0xfb, 0xac, 0x18, 0xf7, 0x44, 0x02, 0xad, 0xf5,
+ 0xbc, 0xae, 0x2d, 0x40, 0xac, 0x8a, 0x7a, 0x2a, 0x35, 0xbc, 0xfe, 0xba,
+ 0x71, 0x9f, 0xdf, 0x1c, 0x87, 0xff, 0x92, 0xf1, 0xa9, 0x22, 0x90, 0xa3,
+ 0xab, 0x1f, 0x87, 0x05, 0x5e, 0xff, 0xba, 0xc4, 0x1c, 0xa8, 0x91, 0xb8,
+ 0xb5, 0xa4, 0xe1, 0xb4, 0x35, 0x27, 0x62, 0x64, 0x8f, 0x51, 0x86, 0xf7,
+ 0x2f, 0xd7, 0xe3, 0x33, 0x1d, 0x47, 0xef, 0xd5, 0xa6, 0xf4, 0xf1, 0x5e,
+ 0xe8, 0xff, 0x6f, 0x1f, 0x85, 0x38, 0x47, 0x7b, 0x68, 0x90, 0x31, 0x48,
+ 0xbc, 0x2b, 0x62, 0xce, 0x29, 0x63, 0xf9, 0x54, 0xe1, 0xb9, 0x47, 0x7e,
+ 0x5c, 0x0a, 0xe7, 0x1a, 0x36, 0x0f, 0xce, 0xc5, 0x30, 0xcb, 0xea, 0x36,
+ 0x7c, 0xf9, 0xe7, 0x67, 0x9c, 0xb3, 0xcc, 0xd1, 0x2b, 0x9c, 0x58, 0x4c,
+ 0x3f, 0x68, 0xfc, 0x4b, 0x27, 0xa2, 0xbe, 0x62, 0xc6, 0x56, 0x59, 0x17,
+ 0x3a, 0x5e, 0x3f, 0x69, 0x4d, 0x18, 0xf5, 0x68, 0xcc, 0xc8, 0xf3, 0x4c,
+ 0x07, 0xed, 0xdb, 0xc2, 0x23, 0xa6, 0xdc, 0x17, 0x9c, 0x89, 0xc7, 0x1c,
+ 0xb4, 0x15, 0xb7, 0xa1, 0xb7, 0xfe, 0xbd, 0x52, 0x81, 0xd2, 0x88, 0x33,
+ 0x38, 0x01, 0x3d, 0xbc, 0x5e, 0xa1, 0x1f, 0x56, 0xcd, 0x33, 0x65, 0x0a,
+ 0xde, 0x4e, 0x04, 0xcc, 0x40, 0x3e, 0x2e, 0x9d, 0xe2, 0xdc, 0xbd, 0x93,
+ 0x30, 0xda, 0x9f, 0xca, 0x9f, 0xff, 0x22, 0x3d, 0x35, 0xa7, 0x15, 0x7b,
+ 0x74, 0xbb, 0x37, 0x25, 0xf0, 0x9e, 0xa3, 0x01, 0xef, 0xed, 0x31, 0x8b,
+ 0x98, 0x8b, 0x89, 0x9d, 0xba, 0xdd, 0x5b, 0x12, 0x98, 0x74, 0xf2, 0xda,
+ 0x29, 0x73, 0x36, 0x31, 0x4d, 0xe5, 0xb5, 0xb0, 0xd8, 0x59, 0x4c, 0x63,
+ 0x7c, 0x2d, 0x8d, 0x78, 0xdd, 0xa5, 0xe3, 0xd0, 0x4a, 0x8c, 0x0a, 0xe6,
+ 0xba, 0x68, 0x72, 0x24, 0x75, 0x7f, 0xb3, 0xa3, 0x9e, 0x39, 0xaf, 0x5f,
+ 0x71, 0x19, 0xdf, 0x63, 0x5e, 0x2f, 0x6b, 0x61, 0x61, 0xda, 0xa4, 0x93,
+ 0x15, 0x76, 0x4c, 0x57, 0x23, 0x0a, 0xb1, 0xb0, 0x02, 0xb7, 0x6b, 0x1b,
+ 0x3e, 0xab, 0x46, 0xfa, 0x71, 0x7d, 0x83, 0xbb, 0xa9, 0x72, 0xbc, 0xa0,
+ 0x13, 0xc4, 0x3c, 0x11, 0xe6, 0x25, 0x06, 0xd4, 0xf2, 0x88, 0xe8, 0xc6,
+ 0xdf, 0x94, 0x1c, 0x13, 0x59, 0x35, 0x77, 0xdf, 0xd8, 0x3b, 0x25, 0x28,
+ 0x0d, 0x13, 0xab, 0x7e, 0xe2, 0xfb, 0xef, 0xd5, 0x3b, 0x5a, 0x22, 0x78,
+ 0xef, 0x32, 0xe4, 0xbf, 0x6d, 0x5b, 0x6e, 0x77, 0xe4, 0x83, 0x98, 0x3b,
+ 0x60, 0x59, 0x8c, 0x93, 0x3e, 0x28, 0xb3, 0x39, 0x1e, 0xfa, 0x1a, 0xe7,
+ 0x66, 0x4d, 0xfa, 0x0f, 0xd6, 0xe7, 0x9c, 0x36, 0x07, 0x70, 0x17, 0x47,
+ 0x3a, 0x6e, 0x79, 0xcb, 0xf8, 0xc0, 0x7a, 0x33, 0xc1, 0x5c, 0xd9, 0x90,
+ 0x67, 0x43, 0x73, 0xb0, 0xcd, 0x74, 0x36, 0x2f, 0x55, 0x14, 0xf4, 0x18,
+ 0xf3, 0xb4, 0x12, 0xc6, 0xa9, 0x6e, 0xfa, 0x75, 0xcc, 0x6b, 0x04, 0xf7,
+ 0x80, 0xe5, 0xd2, 0xeb, 0xd6, 0xb9, 0x22, 0x77, 0xde, 0x32, 0xd2, 0x20,
+ 0x58, 0x10, 0x6e, 0x7b, 0xca, 0x68, 0x41, 0x4f, 0x66, 0x10, 0xbd, 0x99,
+ 0x5c, 0x3f, 0x59, 0xcc, 0xf9, 0x98, 0x7e, 0xd6, 0xad, 0x2b, 0x8e, 0x08,
+ 0xf7, 0x3a, 0x73, 0xcb, 0x5e, 0x23, 0x8a, 0xcd, 0x99, 0x3b, 0x6f, 0x39,
+ 0xd5, 0xd0, 0xcf, 0xff, 0xb9, 0x3a, 0x43, 0xa8, 0xfc, 0xd8, 0x3a, 0x65,
+ 0x11, 0xe9, 0xa3, 0xe3, 0x96, 0xa7, 0x8c, 0x3b, 0x6f, 0x69, 0x5f, 0xf4,
+ 0x4d, 0x6c, 0xca, 0xb4, 0xff, 0xc9, 0x7e, 0xca, 0x59, 0xa7, 0x34, 0x72,
+ 0xa8, 0xed, 0x9a, 0xc0, 0x9d, 0xb7, 0xa4, 0x17, 0xf5, 0xb2, 0x8f, 0x55,
+ 0x8c, 0x2f, 0xb9, 0x3a, 0x51, 0xc6, 0xf6, 0x8f, 0xd3, 0x41, 0x49, 0x64,
+ 0xa2, 0x6d, 0x7e, 0xe0, 0x03, 0x6b, 0x5e, 0x5f, 0x91, 0xad, 0x03, 0x17,
+ 0x75, 0xf0, 0xa0, 0xe9, 0xcc, 0x06, 0x1c, 0xb6, 0x0e, 0x3a, 0x7c, 0xd4,
+ 0x41, 0x92, 0x3a, 0xc8, 0xd6, 0x18, 0xe1, 0x77, 0xa9, 0x83, 0x79, 0x63,
+ 0xeb, 0xd6, 0x95, 0x44, 0xe0, 0x74, 0x18, 0xaf, 0x3a, 0x9c, 0x9c, 0x0b,
+ 0x97, 0xb1, 0x8e, 0x7a, 0xbb, 0xf3, 0x96, 0x8b, 0x17, 0xd9, 0x3a, 0xff,
+ 0xb2, 0x3b, 0xb0, 0xc1, 0xde, 0x3b, 0xd7, 0x9d, 0x59, 0xc3, 0xa3, 0x99,
+ 0xc7, 0x7d, 0x3c, 0x7a, 0x98, 0xb3, 0xdc, 0x4c, 0x5d, 0x35, 0x71, 0x1c,
+ 0x2b, 0x28, 0xd7, 0x46, 0xfe, 0x6e, 0xe5, 0xef, 0x0e, 0xfe, 0x96, 0xf9,
+ 0x51, 0xcf, 0xca, 0x16, 0x3b, 0x2b, 0x9b, 0x83, 0xf2, 0x78, 0x88, 0x57,
+ 0x32, 0x26, 0xf7, 0x57, 0xae, 0x09, 0xc4, 0xd8, 0xc6, 0xfd, 0xa5, 0xb2,
+ 0x6f, 0xc8, 0x65, 0xc4, 0x7d, 0x4e, 0x88, 0x7c, 0x7a, 0x6b, 0x3b, 0xb2,
+ 0xc4, 0xde, 0xdf, 0xe7, 0xb0, 0x97, 0xb2, 0x55, 0x70, 0x7e, 0x5e, 0x58,
+ 0x34, 0x34, 0xc3, 0x63, 0xc0, 0xe7, 0x36, 0xe2, 0xcc, 0xf9, 0x13, 0xd4,
+ 0x81, 0xd8, 0xc9, 0x3d, 0xd4, 0x5f, 0x27, 0xeb, 0x1c, 0x65, 0x2c, 0xdb,
+ 0xcd, 0xfe, 0xed, 0xf5, 0xdb, 0xb0, 0xfd, 0x9c, 0x0c, 0xba, 0x79, 0x9c,
+ 0xed, 0xed, 0x35, 0x7e, 0x53, 0x76, 0xb4, 0x5e, 0xf6, 0x53, 0x3a, 0x31,
+ 0x6c, 0xcf, 0xbb, 0x42, 0x2e, 0x73, 0x11, 0x79, 0x82, 0x65, 0xfd, 0xd4,
+ 0x68, 0x9c, 0xef, 0xb0, 0xed, 0xea, 0x50, 0x9b, 0x3b, 0xe0, 0xc6, 0x90,
+ 0xbd, 0x06, 0x6e, 0x59, 0x45, 0xb6, 0x7d, 0x89, 0x2c, 0x75, 0xcd, 0x9b,
+ 0x68, 0x78, 0xeb, 0xd2, 0x1f, 0x90, 0x27, 0x8a, 0xfc, 0x73, 0x70, 0x92,
+ 0x31, 0x35, 0xaa, 0xc5, 0xdb, 0x45, 0xd6, 0x32, 0xc3, 0x19, 0xbe, 0x16,
+ 0xf1, 0x16, 0x27, 0xfb, 0x6b, 0x26, 0xa7, 0x3c, 0x95, 0xc7, 0xee, 0x7d,
+ 0x69, 0x3d, 0xb6, 0x5f, 0xc9, 0xf1, 0xd3, 0xde, 0xb1, 0x42, 0xfc, 0x09,
+ 0x92, 0xcf, 0x7a, 0xe0, 0x8c, 0xe8, 0xfe, 0x26, 0x47, 0x57, 0xd0, 0x05,
+ 0xfa, 0x58, 0xa9, 0xc8, 0x1b, 0xa7, 0xec, 0x82, 0xc7, 0x6e, 0x6d, 0x8d,
+ 0x8d, 0xd1, 0xf1, 0xf9, 0x2e, 0x78, 0xb4, 0xb5, 0xe9, 0x42, 0xec, 0xf2,
+ 0x68, 0x6d, 0x09, 0xf1, 0x77, 0x59, 0xab, 0x0f, 0xdb, 0xdc, 0xe3, 0x48,
+ 0xe6, 0xa5, 0x52, 0xd9, 0x8b, 0x47, 0xdf, 0xaf, 0x70, 0x1a, 0xb9, 0x76,
+ 0x35, 0xb6, 0xdb, 0xe2, 0xd0, 0x70, 0xce, 0x77, 0x75, 0xad, 0xc5, 0x21,
+ 0xfb, 0x5f, 0x89, 0x4a, 0xe9, 0x7c, 0xbd, 0x1c, 0x7e, 0x2d, 0x76, 0xd9,
+ 0xf8, 0xc5, 0x36, 0x4a, 0x81, 0x25, 0x89, 0x0b, 0xfb, 0x97, 0xfe, 0xa4,
+ 0xdf, 0xae, 0x2a, 0x15, 0x13, 0xf6, 0xb3, 0x92, 0x83, 0x99, 0x18, 0x06,
+ 0x53, 0x53, 0xf7, 0xe8, 0xe9, 0x87, 0xd8, 0xfe, 0x81, 0x38, 0xe7, 0x69,
+ 0xb6, 0x21, 0xfb, 0xf7, 0x64, 0xcf, 0xde, 0xd4, 0xfd, 0x7a, 0x22, 0x5b,
+ 0x65, 0x19, 0x81, 0x0d, 0x7b, 0x89, 0x7f, 0xd1, 0x16, 0xa9, 0x6f, 0x59,
+ 0xaf, 0xcd, 0x0b, 0x22, 0x3b, 0xcd, 0x89, 0xc1, 0xb9, 0xc0, 0x40, 0x52,
+ 0xf6, 0x53, 0x9d, 0x89, 0xad, 0x66, 0x1e, 0x19, 0xad, 0xae, 0xd3, 0xba,
+ 0x55, 0xd9, 0x0b, 0xf5, 0xc1, 0x97, 0x7b, 0x8c, 0x5a, 0xad, 0x47, 0xcd,
+ 0xee, 0x67, 0x7c, 0xd9, 0x0d, 0xcc, 0x2e, 0x13, 0x0c, 0xa8, 0x32, 0xa2,
+ 0xbd, 0x55, 0x98, 0x0b, 0x7f, 0xb5, 0x8d, 0xcb, 0xf1, 0x6f, 0xab, 0x46,
+ 0x70, 0xa5, 0xf0, 0x4a, 0xf5, 0x7d, 0x6b, 0x88, 0xdc, 0xe4, 0xee, 0xb9,
+ 0xff, 0xa7, 0x34, 0xbf, 0xee, 0xd4, 0x3e, 0x9d, 0xf3, 0xf2, 0xf3, 0x05,
+ 0xba, 0x3f, 0xad, 0x88, 0x8e, 0x84, 0x4b, 0x25, 0xb0, 0x95, 0x71, 0xf6,
+ 0xbf, 0xe6, 0x46, 0xb0, 0x8f, 0xff, 0x7f, 0x76, 0xa5, 0xec, 0x4d, 0xb5,
+ 0xac, 0x60, 0x60, 0x5e, 0xb8, 0x8a, 0x63, 0x78, 0x96, 0xf7, 0x7b, 0x33,
+ 0x6f, 0x59, 0xa7, 0xa6, 0x1b, 0xfd, 0xcb, 0x18, 0xec, 0x06, 0xc6, 0x75,
+ 0x6d, 0x52, 0xfd, 0xef, 0xee, 0x95, 0x83, 0xbb, 0x82, 0x63, 0xf9, 0x7e,
+ 0xa0, 0x4e, 0x4b, 0xaa, 0xa5, 0x65, 0xa2, 0xd7, 0x81, 0xf1, 0x57, 0xa6,
+ 0x3c, 0x3b, 0x28, 0xf0, 0x59, 0x7b, 0x5d, 0xa5, 0x77, 0x88, 0xbe, 0x3e,
+ 0xa4, 0x45, 0xe3, 0xd4, 0xbb, 0x7b, 0x1a, 0xc7, 0x7c, 0xf7, 0xdc, 0x2f,
+ 0xd9, 0xe3, 0xac, 0x36, 0x66, 0x72, 0x8c, 0x0a, 0xb4, 0xb9, 0xff, 0x99,
+ 0x5f, 0x7f, 0x6d, 0x24, 0xfb, 0x1a, 0xb2, 0x9a, 0xe8, 0x1b, 0x45, 0xac,
+ 0x73, 0xb5, 0xf9, 0xf0, 0x8c, 0xae, 0x7a, 0xdd, 0x77, 0x37, 0x6d, 0x34,
+ 0x34, 0xf7, 0xd7, 0x16, 0x6d, 0xda, 0xfc, 0x16, 0x47, 0x7d, 0x5b, 0xc2,
+ 0x8e, 0x55, 0x9c, 0x57, 0x23, 0x3a, 0x57, 0x79, 0xc7, 0x42, 0x4d, 0x20,
+ 0x3c, 0xd7, 0x1e, 0x3f, 0x70, 0x6b, 0x3a, 0x81, 0x6d, 0x29, 0x69, 0x53,
+ 0xc1, 0xb2, 0xc0, 0xdb, 0x96, 0x7f, 0x7a, 0x02, 0x5b, 0x32, 0x9f, 0xc4,
+ 0x4d, 0x07, 0xc9, 0x8d, 0xf5, 0xd6, 0x38, 0xf4, 0x68, 0xee, 0xd9, 0xd4,
+ 0x1c, 0x59, 0xdb, 0x96, 0xbd, 0x45, 0xb7, 0x24, 0x02, 0x70, 0x97, 0x13,
+ 0x83, 0xc7, 0x02, 0xf2, 0x2c, 0xd3, 0x8b, 0x6c, 0x8b, 0x94, 0xa9, 0xd5,
+ 0xc6, 0x90, 0x25, 0x73, 0x94, 0xb5, 0xd0, 0xfe, 0xb2, 0xdc, 0x3e, 0x09,
+ 0x1a, 0x5e, 0x8d, 0xae, 0xbd, 0x41, 0xae, 0xd7, 0x6c, 0x48, 0x1b, 0x0a,
+ 0xe6, 0x07, 0xa6, 0xa1, 0x6e, 0xe5, 0xab, 0xaf, 0x17, 0x05, 0x8a, 0x18,
+ 0x4f, 0xc4, 0xb7, 0x8c, 0x8d, 0xc7, 0xf0, 0x1b, 0x62, 0x90, 0xec, 0x19,
+ 0x4b, 0x4a, 0x3d, 0xb6, 0x35, 0x17, 0x69, 0xf1, 0x53, 0x43, 0xf6, 0x2f,
+ 0x5b, 0xd6, 0x35, 0x81, 0x37, 0xad, 0x68, 0x0d, 0xe5, 0x21, 0x5f, 0xcb,
+ 0xd5, 0x95, 0x32, 0xf9, 0xbd, 0x40, 0x4a, 0xe3, 0x2d, 0xa2, 0x93, 0x27,
+ 0xcd, 0x38, 0xb3, 0x01, 0xc1, 0xfd, 0x0f, 0x62, 0x6f, 0x19, 0x8a, 0xfd,
+ 0x8c, 0x71, 0x99, 0x52, 0xc9, 0x38, 0xea, 0xf4, 0x8f, 0xd8, 0xeb, 0x05,
+ 0x1d, 0xc4, 0x68, 0xe1, 0x97, 0x92, 0xf3, 0x39, 0xf1, 0x94, 0x51, 0x85,
+ 0x27, 0xb5, 0x1c, 0x57, 0x23, 0xd6, 0xe1, 0x07, 0x89, 0x79, 0x59, 0x7a,
+ 0x08, 0x39, 0xaf, 0xd1, 0x7e, 0x46, 0xf9, 0x0d, 0xfd, 0x1c, 0x78, 0x21,
+ 0xbd, 0x11, 0x0f, 0xca, 0x1a, 0xa2, 0x52, 0xdb, 0x5c, 0xe7, 0x90, 0xfe,
+ 0x36, 0x62, 0x6b, 0x46, 0xda, 0xfa, 0x20, 0xb6, 0xd7, 0xd8, 0x9d, 0x97,
+ 0x55, 0xb0, 0xfc, 0x83, 0xd8, 0x53, 0xc6, 0xe3, 0xf6, 0xdc, 0xc9, 0x73,
+ 0xaf, 0x5e, 0x53, 0x30, 0xaf, 0x14, 0x2a, 0xf3, 0x06, 0x87, 0x71, 0x33,
+ 0x1c, 0x55, 0xdf, 0xa4, 0xed, 0xc9, 0xbe, 0x9a, 0xaf, 0xc2, 0x59, 0xe5,
+ 0xa2, 0x6f, 0xde, 0x0a, 0x57, 0x95, 0x70, 0xf5, 0x02, 0x8f, 0x8e, 0xf2,
+ 0xbe, 0xe8, 0x36, 0xdc, 0x26, 0xba, 0x75, 0x12, 0x87, 0x7a, 0x24, 0xaf,
+ 0x33, 0x2a, 0xa9, 0x23, 0xbd, 0x95, 0x9c, 0x1e, 0xe5, 0xc4, 0x4c, 0xc6,
+ 0x47, 0x37, 0xf3, 0xb7, 0xb6, 0x77, 0xa9, 0xf7, 0x79, 0x7d, 0x65, 0xe4,
+ 0xf0, 0x96, 0xf5, 0x3e, 0x39, 0xfc, 0xfc, 0x40, 0x5d, 0xd6, 0x20, 0x4e,
+ 0xe1, 0x06, 0xbd, 0x39, 0x4e, 0xbc, 0x59, 0x6d, 0x9c, 0xb1, 0x62, 0xab,
+ 0xa4, 0x8c, 0xee, 0x8b, 0x29, 0x85, 0x3e, 0x16, 0xc0, 0x3f, 0xcd, 0x82,
+ 0x2b, 0x22, 0xcf, 0x14, 0x64, 0xbd, 0xb8, 0x51, 0x9e, 0xf5, 0xb5, 0xc8,
+ 0xf8, 0x5d, 0xb2, 0xee, 0x86, 0xe8, 0x84, 0x0b, 0x46, 0x76, 0x9f, 0xcc,
+ 0xd9, 0x0c, 0x0b, 0x81, 0x85, 0xbf, 0x67, 0x2e, 0x24, 0xf3, 0x53, 0x9b,
+ 0xad, 0x57, 0xb2, 0x41, 0x1f, 0x39, 0xfd, 0xa3, 0xd0, 0x5b, 0x12, 0xd4,
+ 0x75, 0x53, 0x48, 0x9e, 0xdf, 0x3b, 0x7d, 0x09, 0xd8, 0x3c, 0xde, 0x3c,
+ 0x89, 0xcf, 0xa1, 0x9c, 0xb9, 0xeb, 0xdc, 0xb1, 0x15, 0xa8, 0xa8, 0x8a,
+ 0xfa, 0x4a, 0x71, 0x19, 0xcf, 0xd7, 0x30, 0x3f, 0xf9, 0x22, 0x2a, 0x56,
+ 0xb6, 0x22, 0xc1, 0xb1, 0x97, 0x1b, 0x7f, 0xc5, 0x6b, 0xf7, 0x21, 0x99,
+ 0x72, 0x71, 0x1c, 0x3f, 0xb1, 0x2a, 0x6a, 0x44, 0x36, 0xd3, 0x5b, 0x66,
+ 0x30, 0x9f, 0xb6, 0x75, 0x41, 0xdc, 0x4e, 0x09, 0x47, 0xaa, 0x8b, 0xae,
+ 0x07, 0x73, 0xfb, 0x1a, 0xbd, 0x75, 0x8d, 0xd2, 0x41, 0x9b, 0xed, 0xa1,
+ 0xce, 0xa5, 0xac, 0x65, 0x2d, 0x0f, 0x9c, 0xa6, 0x8e, 0x3b, 0x78, 0x6e,
+ 0xf8, 0xdf, 0x84, 0x7a, 0x59, 0x31, 0x4e, 0x58, 0x71, 0xcd, 0x47, 0xbb,
+ 0x54, 0x57, 0x09, 0x9f, 0x5a, 0x1a, 0x7a, 0x8f, 0xf7, 0xb5, 0xbc, 0x9d,
+ 0x9e, 0xb9, 0x25, 0xa7, 0xcb, 0x30, 0x75, 0xf9, 0x6f, 0xf6, 0x75, 0x87,
+ 0x7d, 0xbd, 0x23, 0x7f, 0xfd, 0xcc, 0x2d, 0x3d, 0xc6, 0xcb, 0xbc, 0xde,
+ 0x4b, 0xdd, 0xab, 0x17, 0x49, 0xfd, 0x75, 0xa6, 0xd4, 0x67, 0x4a, 0x65,
+ 0xf4, 0xe4, 0xe7, 0xe3, 0x50, 0x7e, 0x3e, 0x26, 0xf2, 0x6d, 0x38, 0xd9,
+ 0x46, 0x3c, 0x5a, 0x0a, 0x13, 0x65, 0x01, 0xc1, 0x79, 0x91, 0x8b, 0x73,
+ 0x97, 0x11, 0xb9, 0xd6, 0x30, 0xde, 0x75, 0x3d, 0x53, 0x8a, 0x78, 0xc7,
+ 0x4c, 0xdb, 0x0e, 0xcf, 0xdc, 0x22, 0xfb, 0xde, 0xde, 0x52, 0x1a, 0x7d,
+ 0xb2, 0x65, 0x23, 0x45, 0x2e, 0x7b, 0xaf, 0xe9, 0x0c, 0xd7, 0x3b, 0xe6,
+ 0x65, 0x8b, 0x61, 0xc4, 0xce, 0x28, 0x2e, 0x8f, 0xe0, 0x43, 0x22, 0xdd,
+ 0xc8, 0xcc, 0x2b, 0x1e, 0x64, 0xce, 0x14, 0xcc, 0x50, 0xb7, 0x6d, 0x44,
+ 0xec, 0x43, 0xf6, 0xde, 0x37, 0xe7, 0xc4, 0x0a, 0x34, 0xea, 0x0e, 0xcc,
+ 0x0b, 0xcf, 0x64, 0xe6, 0x45, 0xbb, 0x34, 0x8b, 0x1d, 0xba, 0xff, 0x7a,
+ 0x2c, 0xb7, 0xeb, 0xed, 0x4b, 0x67, 0xdb, 0x4b, 0x39, 0xa7, 0x8f, 0x51,
+ 0x8e, 0x6d, 0x01, 0x91, 0xe3, 0x9b, 0x79, 0x39, 0x5a, 0x19, 0x4b, 0x4d,
+ 0xed, 0xda, 0x40, 0xef, 0x59, 0xbd, 0x3d, 0x63, 0xeb, 0xed, 0x3e, 0x9e,
+ 0x17, 0x33, 0xbf, 0x2f, 0xc2, 0xd1, 0x7a, 0x6f, 0x7e, 0x1f, 0x9b, 0xe4,
+ 0x6a, 0x82, 0xbf, 0x0d, 0x7f, 0xbd, 0xda, 0xd0, 0xc3, 0x0e, 0x9b, 0xd7,
+ 0xbb, 0x11, 0xb7, 0x39, 0xb3, 0x3c, 0xf3, 0xae, 0xc0, 0x23, 0x76, 0x39,
+ 0x17, 0x75, 0x52, 0x86, 0x47, 0xf3, 0xfe, 0x22, 0x7b, 0x0e, 0x1e, 0xb3,
+ 0x7f, 0xef, 0xe6, 0xdc, 0xba, 0xe8, 0xab, 0x85, 0x18, 0x25, 0xeb, 0xed,
+ 0xff, 0xc3, 0xf6, 0xfd, 0x21, 0x1c, 0xb7, 0xff, 0x67, 0x73, 0xf9, 0x16,
+ 0x7a, 0x4c, 0xd9, 0x3b, 0x53, 0x86, 0x6e, 0x7b, 0x0f, 0xb9, 0xac, 0x01,
+ 0x5c, 0x89, 0xcd, 0x9a, 0xac, 0x07, 0x93, 0xfb, 0x68, 0x62, 0x13, 0x9d,
+ 0x48, 0x6a, 0xa6, 0x37, 0x53, 0x3f, 0x35, 0x57, 0x32, 0xb1, 0xa7, 0xfe,
+ 0x03, 0x2b, 0x6a, 0xe7, 0x4f, 0x27, 0xac, 0xbd, 0xc6, 0xd1, 0x10, 0x3d,
+ 0xb8, 0xbd, 0xc8, 0xd6, 0x6f, 0xb8, 0xcd, 0xde, 0xff, 0x47, 0x99, 0x9f,
+ 0x49, 0x48, 0x1c, 0x9d, 0x83, 0xb4, 0x69, 0xc7, 0xe2, 0x96, 0xed, 0x9c,
+ 0x93, 0x9e, 0x54, 0x20, 0x7a, 0x09, 0xef, 0x4d, 0x30, 0x96, 0x75, 0x53,
+ 0x9f, 0xb1, 0x16, 0xe1, 0x67, 0x6b, 0xb0, 0x9b, 0x36, 0x36, 0x6e, 0x5a,
+ 0xd6, 0x3e, 0x62, 0x44, 0xe5, 0x3c, 0x15, 0xd9, 0x9a, 0x35, 0x48, 0x31,
+ 0x36, 0xed, 0x33, 0x1a, 0x3f, 0x57, 0x84, 0xb8, 0xdf, 0x0d, 0xdd, 0xb7,
+ 0x85, 0xa3, 0xb9, 0x97, 0xf3, 0x75, 0xd4, 0x14, 0xde, 0xe8, 0x3c, 0xb3,
+ 0x14, 0x46, 0x78, 0xb1, 0xe3, 0x27, 0xd6, 0xa4, 0xfd, 0xec, 0xb8, 0xeb,
+ 0x5f, 0x28, 0xc3, 0x46, 0x71, 0xde, 0x4a, 0xce, 0xf1, 0xbb, 0x01, 0x79,
+ 0x7e, 0x0d, 0xd4, 0xf5, 0x35, 0xb6, 0x8b, 0x0c, 0x7b, 0x43, 0xce, 0xd8,
+ 0x3e, 0x04, 0x5a, 0x36, 0x28, 0xe7, 0x72, 0x83, 0x4b, 0xc6, 0x4c, 0x8c,
+ 0xd6, 0x3f, 0x4b, 0x1e, 0x23, 0xf5, 0x8b, 0xf1, 0x84, 0xf9, 0xb4, 0x55,
+ 0x3b, 0xe3, 0xfb, 0xd6, 0x7e, 0x43, 0x5d, 0x4f, 0x6d, 0xc7, 0xca, 0xd9,
+ 0x56, 0x19, 0xdb, 0xba, 0x3d, 0xa0, 0x9b, 0xdb, 0xd9, 0xd6, 0xf1, 0xc4,
+ 0xd1, 0xa0, 0x9b, 0x6d, 0x3d, 0x6a, 0x4a, 0x6e, 0xe0, 0x6c, 0x6e, 0xe6,
+ 0xdc, 0x76, 0xa5, 0x02, 0xbe, 0xad, 0x94, 0x4b, 0xf2, 0xb7, 0xaf, 0x26,
+ 0xe4, 0x5d, 0x8f, 0x6f, 0x72, 0x3c, 0xd1, 0x8d, 0x2e, 0x34, 0xde, 0x5b,
+ 0x41, 0xfb, 0xa9, 0x44, 0xc1, 0xd6, 0x75, 0x1f, 0xf1, 0x0e, 0xb7, 0xb3,
+ 0xcc, 0xeb, 0x81, 0x39, 0x78, 0x21, 0xd4, 0xb8, 0x72, 0x0e, 0x9c, 0xe4,
+ 0x21, 0x81, 0xe6, 0x0d, 0x4a, 0x5c, 0x13, 0x5b, 0xbc, 0x2d, 0xad, 0x07,
+ 0x9b, 0x20, 0xd8, 0xdd, 0x4a, 0x7d, 0xcc, 0xc1, 0xfb, 0x0b, 0x45, 0x2e,
+ 0x67, 0x38, 0xe8, 0x08, 0x74, 0x3c, 0xcd, 0xf9, 0xad, 0x98, 0x97, 0xcb,
+ 0x53, 0x33, 0xf6, 0x7e, 0xcd, 0x56, 0x24, 0x33, 0x27, 0xde, 0xdd, 0x6b,
+ 0xc0, 0x79, 0xa8, 0xfe, 0x41, 0x0b, 0xf6, 0xbb, 0x21, 0x8d, 0x32, 0x0f,
+ 0xad, 0x32, 0x0f, 0xa5, 0xf4, 0xa7, 0x6b, 0x28, 0xf7, 0x7a, 0x5b, 0xee,
+ 0x39, 0x18, 0x36, 0x65, 0xfd, 0xcb, 0xa9, 0xdd, 0x86, 0x5e, 0x62, 0x67,
+ 0xe0, 0x4c, 0x17, 0xfb, 0x79, 0x9d, 0x32, 0xcf, 0xa3, 0xde, 0x27, 0x5b,
+ 0x84, 0xb7, 0xde, 0x87, 0xbe, 0x54, 0xe1, 0xdd, 0x11, 0x05, 0xe9, 0x80,
+ 0xf4, 0x71, 0x1f, 0x79, 0x5c, 0x97, 0x35, 0x59, 0x23, 0xd7, 0x77, 0x33,
+ 0xf7, 0x8f, 0x6a, 0xf4, 0x07, 0xea, 0x1d, 0xfa, 0x1c, 0xe8, 0x13, 0x6f,
+ 0x38, 0xa2, 0xf4, 0x01, 0xd3, 0x7b, 0x86, 0xd8, 0x70, 0x08, 0x1d, 0x16,
+ 0xaa, 0x6c, 0x7b, 0xf8, 0xd9, 0x88, 0xf1, 0xa1, 0x22, 0xb1, 0x3d, 0x4b,
+ 0x1d, 0xa8, 0x9c, 0x13, 0xd1, 0x41, 0x39, 0x7d, 0x76, 0x2c, 0xa0, 0xfb,
+ 0x5f, 0xa0, 0x3c, 0xdb, 0x29, 0xcf, 0x8a, 0xdc, 0x1c, 0xfa, 0x36, 0x2b,
+ 0xe2, 0xd3, 0x81, 0x96, 0xd5, 0xbc, 0xbe, 0x8d, 0xf2, 0x04, 0xfa, 0x14,
+ 0x0c, 0xb5, 0xf4, 0x90, 0x2b, 0x76, 0x50, 0x07, 0xe7, 0xe4, 0x71, 0xdb,
+ 0x73, 0xd6, 0x41, 0x2e, 0x50, 0x8c, 0xbd, 0xa6, 0xe0, 0xb7, 0x86, 0x61,
+ 0xda, 0xe9, 0x1e, 0xce, 0x48, 0xd4, 0xab, 0xa2, 0xd8, 0x10, 0x0c, 0xa8,
+ 0xe1, 0x35, 0x17, 0xe7, 0xa6, 0x12, 0xfb, 0xb5, 0xdd, 0xf6, 0x5e, 0xe5,
+ 0x1c, 0xb7, 0xfb, 0x83, 0x35, 0xea, 0x15, 0x7e, 0x26, 0xeb, 0x63, 0xb2,
+ 0x86, 0xd4, 0xeb, 0xc9, 0xed, 0xd7, 0x72, 0x51, 0x27, 0xb9, 0xeb, 0xcf,
+ 0x68, 0xc2, 0x7d, 0x0b, 0xe5, 0x7f, 0x69, 0x3d, 0x69, 0x97, 0x97, 0x72,
+ 0x2e, 0x9b, 0xa3, 0x97, 0xda, 0xe5, 0x7e, 0x69, 0x3d, 0xab, 0x39, 0xa7,
+ 0x94, 0x2b, 0x3c, 0x2f, 0x3c, 0xfa, 0x0d, 0x27, 0x31, 0xaf, 0x78, 0xee,
+ 0x62, 0x1c, 0x33, 0x4e, 0xd4, 0x9e, 0xac, 0xef, 0x64, 0x1c, 0x9b, 0xba,
+ 0x7f, 0xcb, 0xc2, 0xe3, 0x76, 0x1e, 0xde, 0x45, 0x3e, 0x7b, 0x74, 0x47,
+ 0x11, 0x84, 0xa3, 0xca, 0xfa, 0x5d, 0x73, 0xd9, 0xb9, 0x5c, 0x56, 0xf6,
+ 0x35, 0x5d, 0x66, 0x73, 0xc3, 0xa8, 0x2a, 0xb8, 0xfb, 0x49, 0x7b, 0xf8,
+ 0x84, 0xbb, 0x74, 0x62, 0x8f, 0x51, 0xe0, 0x2c, 0x47, 0x1f, 0x54, 0x89,
+ 0x93, 0x03, 0xe6, 0x62, 0x89, 0xcd, 0x7e, 0xd6, 0x0f, 0xc6, 0xd4, 0xa9,
+ 0xdc, 0xe6, 0x76, 0x0f, 0x2a, 0xba, 0xb6, 0x3a, 0x20, 0xfb, 0x47, 0x65,
+ 0x2f, 0xa8, 0xf4, 0x55, 0x92, 0x5f, 0x97, 0xfa, 0x38, 0xae, 0x51, 0xe8,
+ 0x4b, 0xf8, 0xc6, 0xfb, 0xa5, 0x85, 0x7d, 0x86, 0x51, 0x5b, 0xce, 0x5f,
+ 0x59, 0x2b, 0xb5, 0xec, 0x4c, 0x0d, 0xe7, 0xcb, 0x1e, 0xcd, 0xcb, 0x1e,
+ 0xfb, 0xd8, 0x75, 0xb5, 0xa9, 0xfb, 0xee, 0x82, 0xf9, 0xe7, 0x5d, 0xf2,
+ 0x0c, 0x46, 0xd6, 0x5c, 0xe5, 0x9e, 0x82, 0x2e, 0xe2, 0x50, 0x54, 0x6b,
+ 0x64, 0x9c, 0xd7, 0x7d, 0x6b, 0x39, 0x1f, 0x71, 0xaf, 0xec, 0x51, 0x2f,
+ 0xc4, 0xc8, 0x62, 0xe4, 0xd6, 0x3e, 0x65, 0x9f, 0x45, 0x6e, 0xbd, 0x93,
+ 0x76, 0x8f, 0xae, 0xf4, 0xef, 0xad, 0xac, 0xd7, 0xc9, 0x58, 0x78, 0x6e,
+ 0x7f, 0xf4, 0x10, 0xf5, 0x3a, 0xcc, 0x7b, 0x9b, 0xcf, 0xae, 0xa7, 0xc8,
+ 0x9a, 0x92, 0xc4, 0xde, 0xdf, 0x59, 0x6d, 0xe7, 0x95, 0x9d, 0xba, 0x57,
+ 0xbc, 0x26, 0x26, 0xcf, 0xdc, 0x46, 0xf3, 0xeb, 0xee, 0x4d, 0x1f, 0x79,
+ 0xe6, 0x36, 0x41, 0x5b, 0x42, 0x74, 0x33, 0xb9, 0x5d, 0x1c, 0x3d, 0x18,
+ 0x4d, 0xd4, 0x69, 0x5b, 0xa0, 0xc9, 0x7a, 0x33, 0xff, 0x7a, 0xb0, 0x3f,
+ 0x81, 0x68, 0xd1, 0xa5, 0x95, 0xe4, 0x5b, 0x88, 0x3a, 0x18, 0xa3, 0x1e,
+ 0x4d, 0xd4, 0x35, 0x6f, 0xe3, 0x98, 0xfc, 0x2b, 0x7b, 0x30, 0x9c, 0x68,
+ 0xfc, 0x2b, 0xc6, 0x11, 0x7f, 0x99, 0xcd, 0x75, 0xe2, 0x7f, 0xbd, 0x97,
+ 0x38, 0xb0, 0x29, 0xbf, 0xe6, 0xd5, 0x96, 0xf8, 0x35, 0xe5, 0xb7, 0x85,
+ 0x64, 0xbd, 0x4f, 0x2a, 0x37, 0xc1, 0x3c, 0xff, 0x04, 0xd6, 0xf5, 0x2b,
+ 0x78, 0xd2, 0x38, 0x81, 0xb5, 0x43, 0x22, 0xcf, 0x09, 0xac, 0xe9, 0x7f,
+ 0x09, 0x7b, 0xfa, 0x67, 0xa0, 0xc9, 0xd6, 0x4d, 0x07, 0x36, 0xec, 0x3c,
+ 0x88, 0xed, 0x29, 0x0b, 0xdb, 0x42, 0x1e, 0xac, 0x7f, 0x58, 0xc1, 0xf2,
+ 0xc0, 0x61, 0x6c, 0xd9, 0x69, 0xe1, 0xe2, 0x50, 0x27, 0x9a, 0xcd, 0x32,
+ 0x14, 0x57, 0xcd, 0x6b, 0x57, 0x59, 0xae, 0x6d, 0xb8, 0x23, 0xbf, 0x2f,
+ 0x79, 0x3f, 0xb1, 0x40, 0x85, 0xcf, 0x90, 0x3d, 0xc7, 0x51, 0xe5, 0xa6,
+ 0x4c, 0x93, 0xd2, 0x9a, 0x7f, 0x66, 0x79, 0x7d, 0xa6, 0xa8, 0x02, 0xa5,
+ 0x71, 0xec, 0x09, 0x9d, 0xc0, 0xd0, 0xd0, 0x07, 0xe5, 0x39, 0x7f, 0x99,
+ 0x20, 0x77, 0x90, 0x9c, 0xc3, 0xa4, 0x4d, 0x7d, 0xd2, 0xfb, 0x40, 0x62,
+ 0x77, 0x93, 0xf8, 0xe9, 0xe0, 0x49, 0x9c, 0x1c, 0xfc, 0x37, 0x2c, 0xd1,
+ 0x24, 0x7f, 0xb4, 0x3a, 0x9d, 0x11, 0xcb, 0xda, 0xd5, 0x10, 0xb7, 0x6a,
+ 0x8c, 0x5f, 0xb0, 0xed, 0x0a, 0x4c, 0x8f, 0xbc, 0x88, 0x6d, 0x1a, 0xdb,
+ 0x4a, 0xed, 0xc7, 0x0e, 0xc6, 0x75, 0x5f, 0xe4, 0x66, 0xf8, 0x52, 0x59,
+ 0xb3, 0x1a, 0xd1, 0x1d, 0xd5, 0xd0, 0x37, 0x56, 0x39, 0x8c, 0x8e, 0x7f,
+ 0x55, 0xea, 0x71, 0x7d, 0xe6, 0x24, 0x7e, 0x3e, 0x68, 0xef, 0xa5, 0x6a,
+ 0xfd, 0xae, 0x62, 0x75, 0x6e, 0x0b, 0xe9, 0xcd, 0xff, 0x43, 0x89, 0xc6,
+ 0x4b, 0x69, 0x53, 0x25, 0xcc, 0x09, 0x6e, 0x18, 0x94, 0x1c, 0xb1, 0x15,
+ 0xee, 0x3e, 0x3d, 0xbb, 0x94, 0x3c, 0xfb, 0xee, 0x05, 0xf1, 0x99, 0xd3,
+ 0x68, 0x97, 0x0e, 0x45, 0x0f, 0x1a, 0x6a, 0x27, 0x8e, 0x98, 0xfa, 0xc4,
+ 0xef, 0x1c, 0xc6, 0xd0, 0x77, 0x50, 0x8f, 0x55, 0x19, 0x7d, 0xe8, 0x32,
+ 0xe6, 0x61, 0x5b, 0x92, 0x26, 0x52, 0x49, 0xbd, 0xb5, 0xc3, 0xd1, 0x8b,
+ 0x3b, 0x02, 0xb5, 0x1b, 0xdf, 0x25, 0x97, 0xf3, 0x10, 0x53, 0x92, 0xe3,
+ 0x23, 0xcc, 0x5f, 0x7b, 0xb1, 0xe1, 0xe1, 0x08, 0xd6, 0xef, 0x32, 0xd1,
+ 0x93, 0x1c, 0xa1, 0x6c, 0x3f, 0x2c, 0x97, 0xbd, 0x34, 0x2d, 0xa1, 0xf8,
+ 0xb5, 0x2a, 0x02, 0x51, 0xf6, 0xd9, 0xa8, 0x46, 0x02, 0x7e, 0x55, 0x61,
+ 0xf4, 0x1f, 0x77, 0xa2, 0x9b, 0x65, 0xfa, 0x52, 0xb4, 0xb9, 0xa4, 0x9b,
+ 0xf1, 0x72, 0x16, 0x86, 0xc7, 0x7c, 0xd8, 0x37, 0xe6, 0xc1, 0xd0, 0x98,
+ 0xc6, 0xa3, 0x14, 0x0f, 0x0d, 0xc8, 0x9e, 0x14, 0x2f, 0x9e, 0xd8, 0xeb,
+ 0xc6, 0xa6, 0x07, 0x3c, 0x98, 0x13, 0x99, 0x8e, 0xbd, 0x7b, 0x4b, 0xb1,
+ 0x9b, 0xd7, 0xab, 0x16, 0xfa, 0xf1, 0x38, 0xaf, 0xf7, 0x3f, 0xe0, 0xe2,
+ 0x3c, 0x5c, 0x8c, 0x03, 0x34, 0xec, 0xa1, 0xb1, 0x32, 0xa4, 0x06, 0x68,
+ 0xf2, 0xe4, 0xac, 0x6f, 0x31, 0xc3, 0x18, 0xdd, 0xcb, 0xd8, 0xf8, 0xb0,
+ 0x89, 0x04, 0xfb, 0xd9, 0x4e, 0x5d, 0xf5, 0x10, 0xd7, 0x36, 0x8c, 0x09,
+ 0xc6, 0xaf, 0xc2, 0x35, 0x7d, 0x7a, 0x73, 0x93, 0x62, 0x44, 0x17, 0xd9,
+ 0xfb, 0xb4, 0xe4, 0xbd, 0xad, 0x55, 0x68, 0x4c, 0xe8, 0x66, 0x13, 0x3a,
+ 0x71, 0x8c, 0xe3, 0xfe, 0x7f, 0xe8, 0xb7, 0x8b, 0x1d, 0x7a, 0xef, 0xd5,
+ 0xea, 0x41, 0xec, 0xc8, 0x1c, 0x22, 0x57, 0x07, 0xc2, 0x7b, 0x0e, 0x92,
+ 0xbf, 0x1d, 0x21, 0xfe, 0xbc, 0x6e, 0xf9, 0x0c, 0x15, 0xd7, 0xdf, 0x6f,
+ 0x84, 0xdf, 0x53, 0x02, 0x1b, 0x7f, 0x45, 0x1d, 0x7c, 0x7e, 0xaf, 0x8a,
+ 0xeb, 0x76, 0x2c, 0x46, 0x3a, 0x14, 0xc5, 0xf6, 0x45, 0x2a, 0xae, 0x7d,
+ 0xf8, 0x20, 0x71, 0x7f, 0xc2, 0xe6, 0xc9, 0xd9, 0xf4, 0x7d, 0x08, 0xf6,
+ 0xc9, 0x9a, 0xbc, 0x9b, 0xf1, 0xbb, 0x1c, 0xc7, 0xfb, 0x3b, 0xe9, 0xb7,
+ 0xe5, 0x38, 0x3a, 0x74, 0x90, 0xf6, 0x58, 0x8e, 0x23, 0xfd, 0xc6, 0xc4,
+ 0x4f, 0x1d, 0xe5, 0x78, 0x82, 0xe7, 0x3b, 0x78, 0xbe, 0x70, 0xc0, 0xe8,
+ 0xef, 0x50, 0xcb, 0xb1, 0x60, 0x4f, 0x03, 0xfa, 0x93, 0x62, 0x9b, 0x1a,
+ 0x36, 0x8e, 0xd5, 0xe7, 0x75, 0x2f, 0x3a, 0xf7, 0xe2, 0x4e, 0xea, 0xea,
+ 0x8e, 0x1d, 0x9d, 0xec, 0xcf, 0x47, 0x9d, 0x1f, 0xc4, 0x43, 0xcc, 0xeb,
+ 0xb6, 0x25, 0x7d, 0x38, 0x9d, 0x32, 0xfc, 0x5f, 0x52, 0x0c, 0xb3, 0x44,
+ 0x09, 0x68, 0xc7, 0xe1, 0xc3, 0xc9, 0x4c, 0x29, 0xba, 0x07, 0x66, 0xe1,
+ 0xa7, 0xb4, 0xcf, 0x07, 0x1f, 0x90, 0xfe, 0x26, 0x18, 0x1f, 0x66, 0xe3,
+ 0x89, 0x11, 0x93, 0x6d, 0xcb, 0x3c, 0x49, 0xcc, 0xe9, 0x81, 0x2b, 0x25,
+ 0xbe, 0x11, 0xdd, 0x41, 0xb3, 0x20, 0x26, 0x1e, 0x46, 0xa6, 0x5f, 0xef,
+ 0xbd, 0x41, 0x15, 0x5e, 0xad, 0x52, 0x97, 0x0e, 0x4c, 0x6a, 0x7a, 0xbc,
+ 0x4a, 0x8d, 0xf7, 0x33, 0x7f, 0x8d, 0x57, 0xab, 0x87, 0xf1, 0x44, 0xbf,
+ 0x13, 0xf3, 0x16, 0xaa, 0xbc, 0x1e, 0x3f, 0xc3, 0xd8, 0x16, 0x9f, 0xa3,
+ 0x9a, 0xd8, 0x6d, 0xcb, 0x8a, 0x78, 0x11, 0xb9, 0x7d, 0xe5, 0xc2, 0x5a,
+ 0xc6, 0x2f, 0x87, 0xd8, 0x5e, 0xac, 0x5c, 0x75, 0x52, 0xef, 0x27, 0x31,
+ 0x42, 0xbb, 0x7e, 0x94, 0xc7, 0x81, 0x41, 0xab, 0x73, 0x39, 0x39, 0xf7,
+ 0xc5, 0x01, 0xab, 0xf3, 0x06, 0xd3, 0xf0, 0x15, 0xa9, 0x81, 0xe8, 0xdd,
+ 0x38, 0x89, 0xfd, 0x23, 0x52, 0x06, 0x6e, 0x6f, 0x84, 0x79, 0x75, 0xd2,
+ 0xea, 0xdc, 0x61, 0x5e, 0x8c, 0x06, 0x3b, 0x37, 0xfe, 0x55, 0x79, 0x0e,
+ 0x33, 0xc5, 0x8f, 0x64, 0x0d, 0x64, 0x12, 0xbf, 0x62, 0x3b, 0xef, 0x0d,
+ 0x56, 0x62, 0x5a, 0xb5, 0xf8, 0xc1, 0x09, 0xbc, 0xdd, 0xff, 0x22, 0x4e,
+ 0xf7, 0x5b, 0x58, 0x10, 0xb2, 0xe0, 0x0c, 0xd5, 0x99, 0x4d, 0xea, 0x65,
+ 0xc4, 0x08, 0x05, 0xd7, 0xcc, 0x7d, 0x09, 0xef, 0xd0, 0xff, 0xaf, 0x9d,
+ 0x6b, 0xd9, 0xb2, 0xf4, 0x61, 0xa1, 0xb5, 0xbd, 0x46, 0xfc, 0xc6, 0xb4,
+ 0xf7, 0xf5, 0x7c, 0x72, 0x1e, 0x5c, 0xd8, 0xb7, 0x26, 0xb9, 0xf0, 0x49,
+ 0x0c, 0x0f, 0x1a, 0xd1, 0x75, 0x05, 0x39, 0xfb, 0x4f, 0x52, 0x07, 0x16,
+ 0x76, 0x98, 0x47, 0x1f, 0xae, 0xc2, 0xbc, 0x33, 0xcc, 0x1a, 0xaf, 0x98,
+ 0x43, 0xdb, 0x59, 0xb0, 0x30, 0x60, 0x2e, 0x53, 0xdf, 0xa4, 0x9f, 0x9e,
+ 0xc4, 0xbe, 0xa1, 0x02, 0x5e, 0xfb, 0xd0, 0x44, 0x3f, 0xcf, 0xed, 0x65,
+ 0xf7, 0xa2, 0x31, 0x75, 0xc8, 0x5e, 0x7f, 0x38, 0x40, 0x7c, 0xcc, 0x3d,
+ 0xd3, 0xd4, 0x30, 0x92, 0x69, 0x22, 0x36, 0x44, 0xf1, 0xcf, 0x99, 0x08,
+ 0xf1, 0x21, 0x4c, 0x7c, 0x68, 0x20, 0x3e, 0x98, 0xc4, 0x87, 0x7a, 0xe2,
+ 0x43, 0xd0, 0x7e, 0xd6, 0x2f, 0x6b, 0xe6, 0x43, 0xa3, 0x2f, 0xa2, 0x68,
+ 0xe0, 0x04, 0x5c, 0xf4, 0x81, 0xe3, 0xa6, 0x45, 0x7e, 0x52, 0xa7, 0xad,
+ 0xc1, 0xc5, 0x4a, 0x54, 0xf3, 0x62, 0x28, 0x73, 0x02, 0x25, 0x03, 0x1a,
+ 0xc7, 0x22, 0xfb, 0x33, 0x6a, 0xc3, 0xbd, 0xc4, 0xea, 0x5f, 0x1b, 0x75,
+ 0xbd, 0x5e, 0xd4, 0xed, 0xae, 0x81, 0xd1, 0xbf, 0x50, 0x9d, 0xab, 0x44,
+ 0xbf, 0xe0, 0xe5, 0x38, 0xab, 0x31, 0xfb, 0x01, 0x0d, 0x73, 0x78, 0xfc,
+ 0x53, 0xaa, 0x76, 0xe2, 0x75, 0x07, 0xbc, 0x33, 0x48, 0x77, 0x66, 0x92,
+ 0x09, 0x90, 0xd5, 0x7a, 0x7d, 0xb8, 0xe4, 0xc0, 0x49, 0x55, 0x41, 0xf6,
+ 0x0b, 0x12, 0xf3, 0xea, 0x82, 0x3d, 0xaa, 0x2a, 0x6b, 0x48, 0xc4, 0x70,
+ 0x1e, 0x2a, 0x22, 0x64, 0x11, 0xb3, 0x98, 0x5f, 0x58, 0x6b, 0xcc, 0x12,
+ 0x6c, 0xae, 0x57, 0x65, 0x6f, 0xc8, 0x21, 0x89, 0x51, 0x33, 0x18, 0x23,
+ 0x4a, 0x93, 0xf1, 0xdb, 0x66, 0xc0, 0x83, 0x92, 0xa4, 0x65, 0x3d, 0x16,
+ 0xd2, 0xe0, 0x89, 0x04, 0xa2, 0x1b, 0x98, 0x46, 0x7e, 0x61, 0x5e, 0x18,
+ 0xd7, 0x64, 0x0e, 0x60, 0x80, 0xe3, 0x5b, 0x9e, 0x29, 0xbc, 0xe3, 0xf9,
+ 0xc9, 0x7f, 0xe7, 0xde, 0x15, 0xbd, 0x64, 0xf7, 0x0c, 0x18, 0xda, 0x5d,
+ 0x6a, 0xbc, 0x92, 0x1c, 0xfc, 0x00, 0xe3, 0x9e, 0x32, 0x79, 0xa3, 0x82,
+ 0xd6, 0x81, 0x38, 0xa6, 0x85, 0x7e, 0xa0, 0xc4, 0xaa, 0x75, 0xbf, 0x5f,
+ 0xa9, 0xc6, 0x8d, 0x0f, 0x50, 0xd7, 0x0b, 0x26, 0x68, 0x2b, 0x3e, 0x7c,
+ 0x67, 0x54, 0x74, 0x5b, 0x3b, 0xb4, 0x83, 0xe3, 0x98, 0x98, 0x7b, 0x40,
+ 0x70, 0xf2, 0xa0, 0x1b, 0x8e, 0x83, 0xd3, 0x99, 0x9b, 0xd6, 0xcf, 0xbd,
+ 0xa4, 0xe3, 0xdf, 0x54, 0xd1, 0x8b, 0xf0, 0x6b, 0xbd, 0x3f, 0xae, 0x18,
+ 0xda, 0x2f, 0x95, 0x03, 0xe4, 0x6c, 0x5e, 0x3c, 0x96, 0x39, 0x4c, 0x5d,
+ 0xee, 0xcf, 0xe7, 0x4b, 0xab, 0x90, 0xe8, 0x93, 0x7d, 0x81, 0x27, 0x30,
+ 0x7b, 0x40, 0x6f, 0xd9, 0xaa, 0x18, 0xc1, 0x6b, 0x95, 0x13, 0x98, 0x39,
+ 0x10, 0xe4, 0x5c, 0x6a, 0x58, 0x96, 0x2c, 0xe0, 0xa7, 0x60, 0xf0, 0x2a,
+ 0x62, 0xb0, 0xb5, 0xf8, 0xa7, 0x66, 0x9c, 0x39, 0x8e, 0x6e, 0x3a, 0x15,
+ 0xbd, 0x75, 0xae, 0x22, 0xfb, 0x80, 0x8c, 0x33, 0x6d, 0xac, 0xe3, 0x19,
+ 0xa8, 0xc7, 0x57, 0x39, 0xe6, 0x66, 0xce, 0xdb, 0x8b, 0x0b, 0x2d, 0x2c,
+ 0x5a, 0xa8, 0xef, 0x2e, 0x71, 0x44, 0xef, 0xaa, 0x42, 0xb6, 0xa3, 0x86,
+ 0x76, 0x73, 0xc7, 0x02, 0x3d, 0xfc, 0x03, 0xe2, 0x2e, 0x71, 0x1a, 0xdd,
+ 0x8c, 0x3b, 0x6b, 0x18, 0x8b, 0x4a, 0x23, 0x7a, 0x2f, 0x73, 0xd4, 0xf7,
+ 0x6e, 0x75, 0x44, 0x43, 0xf2, 0x1e, 0xd1, 0xdf, 0x63, 0x31, 0xdc, 0xa1,
+ 0x0a, 0xe2, 0xa0, 0x9e, 0x7d, 0x11, 0xfa, 0xee, 0xaf, 0x92, 0x93, 0xfe,
+ 0x98, 0xfc, 0xae, 0xe6, 0xd2, 0x43, 0xc4, 0xa8, 0x11, 0x3c, 0x98, 0x39,
+ 0x88, 0xdd, 0x99, 0x34, 0x76, 0x66, 0xb6, 0x29, 0x43, 0xf6, 0xb3, 0x45,
+ 0x45, 0xde, 0x99, 0x8b, 0x56, 0x28, 0x5f, 0x46, 0x79, 0xe8, 0x5b, 0xd6,
+ 0x50, 0x95, 0x8a, 0xca, 0x50, 0x10, 0xd7, 0x24, 0xe3, 0x70, 0x44, 0xde,
+ 0xb5, 0xe4, 0x7d, 0xed, 0xf5, 0xe3, 0x06, 0xae, 0x4e, 0x96, 0x22, 0xb6,
+ 0xc7, 0xb2, 0x7a, 0x1b, 0x9c, 0x58, 0x3b, 0x5e, 0x8f, 0x65, 0x03, 0x0f,
+ 0x59, 0x73, 0x18, 0x73, 0x3e, 0xbc, 0xdc, 0x83, 0x5b, 0xf7, 0x78, 0xd0,
+ 0x96, 0x8c, 0xc2, 0x17, 0x29, 0xe3, 0xef, 0x80, 0xb9, 0x04, 0xc6, 0xc4,
+ 0x04, 0x8c, 0xde, 0xab, 0x1c, 0x81, 0xfd, 0x61, 0xd5, 0x83, 0xbf, 0x21,
+ 0x8e, 0x2f, 0x27, 0xee, 0xc4, 0xc6, 0x2d, 0x54, 0x46, 0xbc, 0xb8, 0x8d,
+ 0xf5, 0xaf, 0xe3, 0xdc, 0xbf, 0xb3, 0x68, 0x3f, 0xb1, 0x40, 0xf6, 0x42,
+ 0x6a, 0xd8, 0x30, 0xee, 0xa6, 0xae, 0xdc, 0x88, 0xed, 0xab, 0xc6, 0xd5,
+ 0x0f, 0xf8, 0x71, 0xeb, 0xb8, 0x07, 0x8d, 0x49, 0x6b, 0xf1, 0x01, 0x33,
+ 0xbe, 0x52, 0x83, 0x81, 0xb6, 0x71, 0x2f, 0xbe, 0x92, 0xd4, 0x7d, 0xd7,
+ 0x32, 0xe7, 0x1f, 0x31, 0x83, 0xf8, 0x5f, 0xe3, 0x3e, 0xdc, 0x94, 0x3c,
+ 0x2a, 0x79, 0xe4, 0x12, 0x27, 0x63, 0xcf, 0xbd, 0xe3, 0xb3, 0xb0, 0x32,
+ 0xa9, 0x9f, 0x99, 0x20, 0xb7, 0xeb, 0xdc, 0x67, 0xe2, 0xae, 0x71, 0x15,
+ 0xad, 0x6c, 0xe7, 0xc6, 0xe4, 0x6c, 0x74, 0xec, 0x6b, 0xa0, 0x0c, 0x0b,
+ 0xb1, 0x7c, 0xc0, 0x09, 0x93, 0x2c, 0x1e, 0x5f, 0x04, 0x5a, 0x06, 0x26,
+ 0x98, 0xc7, 0xdd, 0x87, 0xed, 0x7d, 0x26, 0x6e, 0x1f, 0x97, 0xf3, 0x83,
+ 0xf6, 0x3b, 0xae, 0xef, 0x3d, 0xbc, 0x10, 0x9f, 0x1f, 0x50, 0x89, 0x03,
+ 0xc5, 0x18, 0x5a, 0xa9, 0xe0, 0x2b, 0xbc, 0xbe, 0x35, 0x25, 0x7b, 0x90,
+ 0x81, 0xd0, 0x8e, 0xc0, 0xfe, 0x2a, 0x72, 0x86, 0x45, 0x0f, 0xe7, 0xae,
+ 0x3f, 0x48, 0x9c, 0x2f, 0x21, 0xce, 0x97, 0x91, 0xc3, 0x5e, 0x35, 0x7c,
+ 0x10, 0xf7, 0x13, 0x97, 0x0f, 0x0d, 0x74, 0x32, 0xee, 0x94, 0xe3, 0x71,
+ 0xc6, 0x81, 0x24, 0xcf, 0x4f, 0xec, 0x30, 0x3a, 0x4a, 0x88, 0xd3, 0x3f,
+ 0x20, 0xfe, 0xf6, 0x12, 0x33, 0xee, 0x48, 0x32, 0xdc, 0xef, 0x60, 0x0e,
+ 0x70, 0x69, 0x74, 0xbe, 0x87, 0x39, 0xd6, 0xb5, 0x4a, 0xc0, 0xf7, 0x26,
+ 0xca, 0xe1, 0x78, 0xb8, 0x1a, 0x8d, 0x0f, 0x48, 0x19, 0xc1, 0x2f, 0x15,
+ 0xea, 0x5e, 0x27, 0x75, 0x7e, 0x18, 0x56, 0xbf, 0x83, 0xe3, 0xad, 0x35,
+ 0xc9, 0xc0, 0xf1, 0x9a, 0xa9, 0x6b, 0xff, 0x4c, 0xac, 0x7d, 0x9f, 0x98,
+ 0xea, 0x9f, 0xd1, 0x80, 0x26, 0xc3, 0xe4, 0x71, 0x18, 0x27, 0xfb, 0x0d,
+ 0x53, 0xf6, 0xe4, 0xbd, 0x4e, 0x9e, 0x37, 0x39, 0x83, 0x31, 0xd3, 0x10,
+ 0x3f, 0x1c, 0xe1, 0x78, 0x54, 0xc9, 0x4b, 0xe0, 0x18, 0x03, 0xde, 0x7e,
+ 0x78, 0x31, 0xc7, 0x25, 0xb1, 0x54, 0xe2, 0xdd, 0x08, 0x65, 0x5d, 0x8c,
+ 0x15, 0xd4, 0x47, 0x53, 0x52, 0x45, 0x7a, 0x5f, 0x04, 0xb7, 0xef, 0xca,
+ 0xc5, 0xe1, 0x8d, 0xa1, 0xf8, 0x0d, 0x8c, 0xc3, 0xe1, 0x52, 0xc6, 0x61,
+ 0x57, 0x44, 0x64, 0x73, 0x62, 0x98, 0x71, 0x7b, 0x73, 0x2a, 0x8c, 0x66,
+ 0xce, 0xe1, 0x44, 0x9a, 0xfd, 0x26, 0x67, 0xe1, 0x78, 0xda, 0xc3, 0x98,
+ 0xa5, 0xf1, 0x20, 0xaa, 0x8d, 0x4c, 0xe7, 0xe1, 0xe7, 0x71, 0x31, 0x0f,
+ 0xc3, 0xbe, 0xb6, 0x26, 0xa9, 0x20, 0xde, 0xa2, 0xd8, 0x7c, 0xfe, 0x78,
+ 0x5a, 0xb0, 0x59, 0xd6, 0x32, 0xef, 0xae, 0x94, 0x3d, 0xa8, 0xfd, 0xa9,
+ 0x97, 0x50, 0x49, 0x7c, 0xaa, 0xc8, 0xe3, 0xd0, 0xcf, 0x42, 0x82, 0xbb,
+ 0xb5, 0xc4, 0x5d, 0xd9, 0x4f, 0x64, 0x59, 0xab, 0x02, 0x53, 0xf1, 0xe8,
+ 0xff, 0xfb, 0x30, 0x6a, 0xef, 0xab, 0x15, 0x4c, 0x22, 0xfe, 0xa5, 0x88,
+ 0x7f, 0x1c, 0x43, 0xd7, 0x95, 0xc4, 0x40, 0xca, 0xf4, 0x8f, 0x29, 0x62,
+ 0x20, 0x71, 0xfa, 0x20, 0x71, 0xfa, 0xdb, 0xc4, 0xe9, 0x6f, 0x11, 0xa7,
+ 0x1f, 0x27, 0x26, 0xe4, 0xd6, 0xf4, 0x9a, 0xe5, 0xb9, 0x0a, 0xe7, 0xe3,
+ 0x1d, 0x7b, 0x6d, 0xb1, 0x86, 0xba, 0x9a, 0x3d, 0xa0, 0x60, 0x8e, 0xa1,
+ 0xef, 0x17, 0xbb, 0xff, 0x31, 0xe7, 0xc9, 0x3f, 0x2d, 0xb7, 0xe7, 0xb7,
+ 0x29, 0xd9, 0x03, 0x77, 0xb2, 0x4e, 0xeb, 0x85, 0xfd, 0x0d, 0x01, 0x53,
+ 0xb8, 0x68, 0x51, 0x72, 0x0d, 0x1c, 0xc9, 0xba, 0xfd, 0xc7, 0xe4, 0xf9,
+ 0xed, 0x74, 0xc9, 0xeb, 0xd7, 0xc8, 0x1e, 0xed, 0xfd, 0xb2, 0x37, 0x6c,
+ 0x19, 0xef, 0xb9, 0x92, 0x75, 0xe6, 0x9b, 0xb0, 0xb1, 0xcd, 0x3f, 0x69,
+ 0xdf, 0xab, 0x7d, 0xef, 0x7e, 0xea, 0x2b, 0xcb, 0x36, 0xd3, 0x29, 0xd9,
+ 0x17, 0x3b, 0x0b, 0x8f, 0x66, 0xe4, 0x77, 0x5d, 0x6b, 0x42, 0xdd, 0x8f,
+ 0x58, 0x8d, 0xf0, 0xf1, 0x30, 0xae, 0x4f, 0x7a, 0x68, 0x07, 0x71, 0x54,
+ 0xd0, 0xb7, 0xbe, 0x36, 0xde, 0x40, 0x5f, 0x7b, 0xc8, 0xd2, 0x22, 0x81,
+ 0xd6, 0x71, 0x72, 0x9e, 0xf5, 0xe3, 0x8b, 0xb1, 0x74, 0xc0, 0xb2, 0x3c,
+ 0x97, 0x19, 0xe1, 0x0d, 0x8a, 0x1f, 0x2e, 0xfa, 0xa0, 0x83, 0x7e, 0xb5,
+ 0x6e, 0x4f, 0x40, 0x7b, 0x93, 0x78, 0xda, 0xde, 0x70, 0x80, 0xf6, 0x61,
+ 0x9c, 0x69, 0x26, 0x96, 0x3a, 0x23, 0x01, 0xe6, 0x89, 0x1e, 0xda, 0xbe,
+ 0x17, 0x67, 0x12, 0xe2, 0x5f, 0x7a, 0xc7, 0x3f, 0x33, 0x37, 0xe9, 0xa0,
+ 0x6f, 0xfc, 0x32, 0x31, 0x8b, 0x3e, 0xe0, 0xc6, 0xdb, 0x09, 0x83, 0xfe,
+ 0xe6, 0xc1, 0x3b, 0x89, 0x7a, 0xf6, 0x15, 0x64, 0x19, 0x3f, 0xee, 0x1c,
+ 0x0f, 0xd3, 0xcf, 0xae, 0xe4, 0x21, 0xef, 0x53, 0xd7, 0xc6, 0xbf, 0xa3,
+ 0xd4, 0xf6, 0xcf, 0x56, 0xab, 0x10, 0xad, 0xd6, 0xf0, 0xf5, 0xf1, 0xcf,
+ 0xe2, 0x3f, 0x18, 0xb7, 0xd7, 0x26, 0xc1, 0x39, 0x44, 0x88, 0x3c, 0x70,
+ 0x62, 0x9f, 0x3c, 0x4b, 0x44, 0x5d, 0x74, 0xae, 0x43, 0x67, 0x6e, 0xab,
+ 0x67, 0x4f, 0x3b, 0x9c, 0xec, 0x93, 0xac, 0x98, 0x65, 0x7f, 0xd9, 0x5f,
+ 0x8a, 0xbb, 0xf6, 0x1c, 0xa0, 0x8f, 0x14, 0x61, 0xc1, 0xfd, 0x6e, 0x7c,
+ 0x7d, 0xdf, 0x08, 0xb9, 0x83, 0x8a, 0x99, 0xcc, 0x95, 0x86, 0x48, 0x14,
+ 0x66, 0x0e, 0x47, 0x70, 0xdb, 0xae, 0x11, 0x0c, 0xe4, 0x79, 0x5e, 0x28,
+ 0x14, 0xff, 0x9f, 0x2a, 0x0e, 0x90, 0x47, 0x04, 0xda, 0x3f, 0x43, 0x1b,
+ 0xab, 0x88, 0x04, 0xe2, 0x32, 0xee, 0x16, 0xda, 0x58, 0x0f, 0xe7, 0x33,
+ 0xcd, 0x71, 0x24, 0x68, 0x63, 0x8f, 0x51, 0xfe, 0xed, 0xb4, 0xb1, 0x38,
+ 0x6d, 0x2c, 0x4e, 0x7b, 0x8a, 0xd3, 0xc6, 0xe4, 0x9d, 0xfd, 0x38, 0x6d,
+ 0x2c, 0x4e, 0x1b, 0x8b, 0xa7, 0x17, 0x63, 0x94, 0x4c, 0x63, 0xcb, 0x48,
+ 0x03, 0x71, 0x4c, 0xb1, 0xa3, 0x52, 0xf6, 0x86, 0xcf, 0x92, 0xb3, 0x5f,
+ 0xc5, 0x43, 0x41, 0x33, 0x7d, 0xb2, 0x77, 0x68, 0x84, 0x9c, 0xc7, 0x8d,
+ 0xdf, 0x64, 0x84, 0xe3, 0x37, 0x30, 0x8f, 0x3d, 0x4c, 0x9e, 0xaf, 0xe2,
+ 0x49, 0x53, 0xf2, 0x60, 0x93, 0xe7, 0x8c, 0x35, 0x29, 0xe1, 0x6b, 0x87,
+ 0x71, 0x47, 0x3f, 0x70, 0x2d, 0x79, 0x61, 0x35, 0x79, 0xc9, 0xde, 0x05,
+ 0xfc, 0xfd, 0xf0, 0x01, 0xda, 0xbc, 0xf8, 0x63, 0x6e, 0xaf, 0xeb, 0xf1,
+ 0xfe, 0x5a, 0xdf, 0xd5, 0xf4, 0xc1, 0x7b, 0x59, 0xd7, 0xf9, 0xb0, 0xd4,
+ 0x39, 0xc0, 0xb6, 0xf5, 0xf0, 0x6f, 0x38, 0xff, 0xad, 0xf7, 0x57, 0xe3,
+ 0xed, 0x5d, 0x7a, 0xf8, 0x7d, 0x62, 0x5e, 0xb5, 0xc3, 0x5a, 0xfc, 0x99,
+ 0x50, 0x60, 0xe3, 0x67, 0xd4, 0x1c, 0xdf, 0x6b, 0xd9, 0xe1, 0xc4, 0xfe,
+ 0xd0, 0x62, 0x78, 0x16, 0x14, 0x38, 0x1f, 0x6d, 0xa9, 0x5a, 0x38, 0x96,
+ 0x1e, 0x3e, 0x4d, 0xae, 0x92, 0x64, 0xfb, 0xa3, 0xe9, 0x23, 0xc4, 0x90,
+ 0xfb, 0xf0, 0x02, 0xf3, 0xf3, 0x91, 0x4f, 0xbf, 0x4e, 0xee, 0xe8, 0xc6,
+ 0x18, 0x39, 0xe0, 0x81, 0xfe, 0xe8, 0xe7, 0x9c, 0xc4, 0x7d, 0xcf, 0x82,
+ 0x72, 0xa4, 0x87, 0x84, 0x2b, 0x96, 0xe3, 0xd9, 0x7e, 0x43, 0xbb, 0x56,
+ 0xc9, 0xf1, 0xc2, 0x2d, 0x3c, 0x7f, 0xb3, 0xdf, 0x38, 0x33, 0x8c, 0xc0,
+ 0xc4, 0x69, 0x72, 0xc3, 0xf7, 0x87, 0x24, 0x86, 0x1d, 0xa4, 0x8f, 0xfb,
+ 0x11, 0x4e, 0x6a, 0x38, 0x34, 0x66, 0x60, 0x7e, 0xd2, 0x8b, 0x47, 0xc6,
+ 0x82, 0xf8, 0x0c, 0x7d, 0x37, 0x43, 0x7e, 0xf8, 0xe9, 0xa4, 0xf8, 0xe2,
+ 0x2c, 0x8c, 0x8f, 0xcd, 0xb2, 0xf7, 0x54, 0x7a, 0x8c, 0x5f, 0xc0, 0x53,
+ 0x2d, 0x3e, 0x49, 0x6e, 0x9d, 0xd2, 0x7b, 0x63, 0x1c, 0x4f, 0xcc, 0xab,
+ 0xef, 0x8f, 0x41, 0x1f, 0x02, 0xae, 0xf8, 0x70, 0xe8, 0x8b, 0x12, 0x1f,
+ 0xc5, 0x1f, 0x35, 0x8c, 0x93, 0xef, 0x14, 0x13, 0x53, 0x4b, 0x23, 0xb5,
+ 0xef, 0xbd, 0xac, 0xe8, 0xd9, 0xa7, 0x55, 0xcb, 0x7a, 0x69, 0xa1, 0x06,
+ 0xdf, 0x3e, 0x8d, 0xdc, 0xc3, 0x64, 0xec, 0x16, 0x3f, 0xd5, 0x30, 0xe3,
+ 0x81, 0x6a, 0x4c, 0x7b, 0x20, 0x89, 0xbf, 0xad, 0x8e, 0x7f, 0x6e, 0x3a,
+ 0xe3, 0xfc, 0x74, 0xe2, 0x7a, 0x65, 0xf2, 0xd8, 0x0c, 0x37, 0xf9, 0xf2,
+ 0x84, 0x5a, 0xd7, 0xba, 0x1f, 0xfa, 0xfe, 0x93, 0x8a, 0xee, 0x7b, 0x8c,
+ 0xb1, 0xc1, 0x45, 0x1b, 0x75, 0x8c, 0x6b, 0xf4, 0xdd, 0xba, 0x43, 0xd3,
+ 0x60, 0xc4, 0x2f, 0x57, 0x5d, 0x16, 0x6c, 0x79, 0xae, 0xa8, 0xcc, 0xe5,
+ 0x45, 0x82, 0x3b, 0x12, 0x17, 0x1c, 0xb2, 0xff, 0x13, 0xed, 0xf4, 0x97,
+ 0x15, 0x76, 0x2c, 0x3a, 0x60, 0xef, 0x8f, 0xdb, 0x30, 0x1e, 0xa7, 0x8f,
+ 0x2c, 0x46, 0xd9, 0x80, 0x07, 0x5f, 0xb3, 0xe3, 0xd0, 0x43, 0x56, 0x15,
+ 0xfd, 0xe5, 0xf6, 0x3d, 0x81, 0xf6, 0xab, 0xe9, 0x2f, 0xb5, 0x97, 0x49,
+ 0x0c, 0x63, 0xdc, 0x4e, 0x19, 0xe6, 0x30, 0xb1, 0xe5, 0xa1, 0x06, 0x63,
+ 0xe2, 0x75, 0xe4, 0x7c, 0x66, 0x6b, 0x5f, 0x35, 0xfe, 0xe1, 0xfe, 0xfd,
+ 0xf6, 0x5a, 0xc8, 0x6d, 0x3c, 0x4f, 0xf6, 0xf9, 0x6c, 0xff, 0x88, 0xf1,
+ 0xf7, 0x9d, 0x8c, 0x79, 0x31, 0xfa, 0xd1, 0x96, 0x3e, 0x6b, 0xf1, 0xf7,
+ 0x17, 0xc6, 0x57, 0x56, 0x20, 0xc8, 0x98, 0xe4, 0x46, 0x6f, 0x9f, 0xde,
+ 0xdf, 0xca, 0x18, 0x74, 0x62, 0xa1, 0x49, 0x59, 0x3c, 0xd8, 0xd1, 0x27,
+ 0x98, 0x7a, 0xf4, 0xa6, 0x6a, 0xc4, 0xff, 0xa7, 0xc6, 0xf1, 0x7d, 0xcd,
+ 0x7e, 0xf6, 0x37, 0x0b, 0x6b, 0xf7, 0x5d, 0x46, 0x99, 0xeb, 0xe9, 0x83,
+ 0xcc, 0xab, 0x99, 0xef, 0xac, 0xde, 0x25, 0x7e, 0x81, 0x46, 0xc9, 0xd3,
+ 0x3a, 0xcd, 0x80, 0xf9, 0x06, 0x7d, 0xa8, 0x88, 0x5c, 0xe7, 0x41, 0x62,
+ 0x59, 0x31, 0x21, 0xb3, 0xcc, 0x08, 0x63, 0x21, 0x6d, 0x54, 0xde, 0xe1,
+ 0x98, 0x46, 0x5e, 0x37, 0x9f, 0xf3, 0x51, 0x92, 0xf1, 0x00, 0xe4, 0x10,
+ 0x20, 0x3e, 0x61, 0x94, 0x20, 0x38, 0xea, 0xe7, 0x71, 0x31, 0x0f, 0x2a,
+ 0x22, 0xa3, 0xa2, 0x66, 0x94, 0x75, 0x87, 0x47, 0x6c, 0x5b, 0xfc, 0x07,
+ 0xce, 0x7b, 0x82, 0xb6, 0x7e, 0x23, 0xb1, 0x7e, 0x62, 0x27, 0xd0, 0xfb,
+ 0x70, 0xce, 0xb6, 0x53, 0x6c, 0xbf, 0x85, 0x98, 0xf7, 0x1e, 0x6d, 0xb6,
+ 0x87, 0xf3, 0xbd, 0x63, 0xd0, 0x08, 0xd6, 0xa9, 0x01, 0x6d, 0x9c, 0xf3,
+ 0xdc, 0x35, 0xa2, 0xa2, 0xaf, 0x7f, 0x31, 0x86, 0x99, 0x07, 0x75, 0x0f,
+ 0x89, 0x8f, 0x48, 0x99, 0xc3, 0xe8, 0xa4, 0x8f, 0xfc, 0x6a, 0xa1, 0x82,
+ 0xd8, 0x17, 0xe4, 0x1d, 0x51, 0x27, 0xf3, 0xfd, 0xfb, 0xb0, 0x36, 0x71,
+ 0xc4, 0x2a, 0x37, 0xf4, 0xde, 0x21, 0x95, 0x79, 0x16, 0x6d, 0xb3, 0x8b,
+ 0xf9, 0xc9, 0x12, 0xe6, 0x27, 0xdd, 0x79, 0xbb, 0x3c, 0x4e, 0x3b, 0xec,
+ 0x63, 0x1c, 0x7b, 0x7d, 0x28, 0x17, 0xf7, 0x7e, 0xbc, 0xc3, 0x8f, 0xf9,
+ 0x97, 0x97, 0xe3, 0x99, 0x87, 0x73, 0xb2, 0xed, 0xa4, 0x4d, 0x3e, 0x4d,
+ 0x3d, 0xdf, 0x4a, 0xbd, 0xbe, 0x92, 0x12, 0x8c, 0x0a, 0xe2, 0x59, 0xf2,
+ 0xe8, 0xf5, 0xe4, 0x02, 0x2f, 0xa5, 0x72, 0x36, 0xf9, 0xf5, 0xf1, 0x2b,
+ 0xab, 0x72, 0xf1, 0xc1, 0x0b, 0xf5, 0x01, 0x79, 0x27, 0xcf, 0xb2, 0x96,
+ 0x98, 0xd9, 0x76, 0xf2, 0x1a, 0xb6, 0x1d, 0x21, 0x37, 0x72, 0x62, 0x66,
+ 0x32, 0x82, 0xa5, 0xa9, 0xda, 0xe6, 0xb9, 0xb2, 0x89, 0x63, 0x66, 0x8e,
+ 0x03, 0xba, 0x92, 0xf2, 0xcd, 0x0f, 0x0d, 0x65, 0xcc, 0x9d, 0xfe, 0x26,
+ 0xff, 0x9d, 0x91, 0x1b, 0xff, 0x0c, 0xee, 0xb8, 0x82, 0x32, 0xa5, 0xc8,
+ 0x1d, 0x27, 0xf3, 0xdf, 0x19, 0xb9, 0xc1, 0xfe, 0xce, 0x88, 0x1b, 0xd3,
+ 0xc6, 0x9d, 0xce, 0x2f, 0xa5, 0x3c, 0x98, 0x31, 0x7e, 0x96, 0x83, 0xba,
+ 0x8b, 0x22, 0x4d, 0x78, 0x2a, 0xa1, 0x60, 0xba, 0xf1, 0xbf, 0xf1, 0xb2,
+ 0xbd, 0x26, 0x50, 0x8d, 0x99, 0x0f, 0xc8, 0x7a, 0x42, 0x54, 0xde, 0x89,
+ 0x69, 0x7e, 0x82, 0xe7, 0x25, 0xc4, 0xd3, 0x8a, 0x07, 0x14, 0x3c, 0x1d,
+ 0xf0, 0xa2, 0x98, 0xbf, 0x7d, 0xe4, 0x9a, 0xce, 0x85, 0xcb, 0xad, 0xcd,
+ 0xab, 0xc4, 0xbe, 0x39, 0x87, 0xfb, 0xa6, 0x55, 0x0a, 0x06, 0xee, 0x35,
+ 0x65, 0xdd, 0xd2, 0x40, 0x4f, 0xa2, 0x9a, 0xfc, 0xba, 0xb6, 0xbd, 0x09,
+ 0xb5, 0xe6, 0x2f, 0x1c, 0xd5, 0x28, 0xda, 0x77, 0x63, 0x95, 0xac, 0xd9,
+ 0x7f, 0x9b, 0x73, 0xd6, 0x4d, 0xec, 0xea, 0x4a, 0xe5, 0xe2, 0x67, 0x53,
+ 0xfa, 0x17, 0x9a, 0xe8, 0xa5, 0x9b, 0xfc, 0x44, 0x4d, 0x9e, 0xb2, 0xcb,
+ 0x94, 0x45, 0x0e, 0x11, 0x7f, 0x66, 0xe1, 0x10, 0xf3, 0x1a, 0x89, 0xa5,
+ 0x65, 0x3c, 0xca, 0xc9, 0x1b, 0x7f, 0xc9, 0x58, 0x7a, 0x67, 0x28, 0x1b,
+ 0x94, 0x2f, 0xd0, 0x54, 0x91, 0x8b, 0xd3, 0x07, 0xb0, 0x2f, 0xa4, 0xb7,
+ 0xac, 0x76, 0x44, 0x9f, 0x61, 0x0e, 0x16, 0x5e, 0xcc, 0x9c, 0x7c, 0x79,
+ 0x60, 0x04, 0x5b, 0xc9, 0x03, 0xb7, 0x30, 0x17, 0x6f, 0xa5, 0x6d, 0xb6,
+ 0xef, 0x62, 0x6c, 0x73, 0x9c, 0xcb, 0xc5, 0xb5, 0x50, 0x7c, 0x35, 0x39,
+ 0x40, 0x87, 0x47, 0x15, 0x7b, 0x15, 0xdf, 0x09, 0xb4, 0xbe, 0x41, 0x8c,
+ 0xae, 0x63, 0xdc, 0x10, 0x7b, 0xdf, 0x9e, 0xd2, 0xdb, 0xa9, 0x80, 0xaa,
+ 0x72, 0xe6, 0x8e, 0x77, 0x8d, 0x35, 0xd0, 0x6f, 0xac, 0x4e, 0x37, 0xed,
+ 0xda, 0xb9, 0x68, 0x16, 0x73, 0xce, 0xab, 0xd0, 0xbd, 0x83, 0xf6, 0x4f,
+ 0x5f, 0xba, 0xb7, 0x0f, 0xe4, 0x67, 0xea, 0x16, 0xce, 0x5f, 0x76, 0x1f,
+ 0x02, 0x67, 0x5a, 0x50, 0xd7, 0x5c, 0xe4, 0x10, 0x19, 0xf4, 0x96, 0xb7,
+ 0xc9, 0xd3, 0x3a, 0x98, 0x9f, 0xae, 0x67, 0x2e, 0x1f, 0x63, 0x2e, 0x1f,
+ 0x63, 0xbd, 0xd4, 0x0e, 0x79, 0x4e, 0x64, 0xb4, 0x1c, 0x67, 0xfe, 0xf3,
+ 0x35, 0xf2, 0x9f, 0x1d, 0xf7, 0x8b, 0x5c, 0xd3, 0x71, 0xd7, 0xde, 0xab,
+ 0x90, 0xa4, 0x3d, 0xdd, 0xc9, 0x6b, 0x7d, 0xf7, 0x5f, 0x8c, 0x3b, 0x98,
+ 0xc7, 0xc7, 0xc6, 0x16, 0xa3, 0x9f, 0x99, 0xe8, 0xc6, 0xbd, 0x9f, 0x45,
+ 0x17, 0xf9, 0xd4, 0x12, 0x62, 0xf4, 0xea, 0x87, 0x47, 0x6c, 0xcc, 0x16,
+ 0xcc, 0x7f, 0x2d, 0x0d, 0xbc, 0x49, 0x4e, 0xd6, 0x9f, 0x3a, 0x60, 0xf3,
+ 0x34, 0x17, 0xe3, 0x43, 0x31, 0x71, 0x29, 0xbc, 0xcb, 0xe8, 0x58, 0xa6,
+ 0x5a, 0x8b, 0x4b, 0x16, 0x06, 0x7a, 0xdf, 0xa6, 0xaf, 0x56, 0xed, 0x53,
+ 0x51, 0x3d, 0x20, 0xb9, 0x3a, 0xf9, 0x11, 0x31, 0xfa, 0x05, 0x62, 0x74,
+ 0xf9, 0x9e, 0x5c, 0x5e, 0x9e, 0x60, 0xde, 0x55, 0x6d, 0xe4, 0x72, 0xf3,
+ 0xed, 0x7d, 0xb2, 0xf7, 0xc6, 0x8d, 0xe7, 0x68, 0xfb, 0x47, 0xf3, 0xb6,
+ 0x7f, 0x2c, 0x8f, 0xc1, 0x16, 0x73, 0xf3, 0x37, 0x6d, 0xfc, 0xcd, 0xe5,
+ 0xe6, 0xf3, 0x07, 0x8c, 0x8e, 0x30, 0x31, 0xfa, 0x33, 0x7b, 0xa4, 0x7f,
+ 0x0d, 0xd5, 0xc4, 0x93, 0x1a, 0x62, 0x49, 0xc5, 0x80, 0xac, 0xcf, 0x04,
+ 0xda, 0xc7, 0x55, 0x9f, 0xdd, 0xc7, 0x26, 0xca, 0xd6, 0x9d, 0x92, 0x77,
+ 0x6c, 0x0d, 0x6d, 0x83, 0x12, 0x30, 0xaf, 0xa1, 0x3e, 0xf7, 0xa5, 0xaf,
+ 0x42, 0x7b, 0xff, 0x2c, 0xec, 0x1f, 0x92, 0xf8, 0x22, 0xed, 0x4b, 0x2e,
+ 0xee, 0xc4, 0xfb, 0xbb, 0x66, 0xe3, 0xfd, 0x91, 0x73, 0x79, 0xf8, 0xe6,
+ 0x54, 0xf4, 0x5e, 0x86, 0xd7, 0xe5, 0x92, 0x87, 0xbf, 0xc4, 0x3c, 0xfc,
+ 0x6d, 0x45, 0xd6, 0x10, 0x55, 0xdc, 0xb8, 0xc0, 0xc1, 0xf8, 0xa2, 0xfb,
+ 0x5f, 0x74, 0xc4, 0xe5, 0x39, 0xb2, 0xff, 0x7e, 0xde, 0x7f, 0x9e, 0xf1,
+ 0x7c, 0x80, 0x33, 0x11, 0xad, 0x76, 0xe0, 0x99, 0x85, 0xf1, 0xa8, 0x8b,
+ 0xd7, 0x7b, 0xc9, 0x53, 0x66, 0x1a, 0x07, 0xe9, 0x9b, 0xb5, 0xe1, 0xf9,
+ 0x0e, 0x07, 0xce, 0x98, 0x7a, 0xcb, 0x6e, 0x5e, 0x7b, 0x36, 0x23, 0xbe,
+ 0x18, 0x26, 0x7e, 0x2d, 0xca, 0xfb, 0xa2, 0xbc, 0x8f, 0x01, 0xf7, 0x6c,
+ 0xda, 0xeb, 0x6b, 0x29, 0xbd, 0xff, 0x59, 0xda, 0x69, 0xf5, 0x59, 0x3b,
+ 0x2d, 0xec, 0xd3, 0x82, 0xbb, 0x2a, 0xd2, 0x82, 0x50, 0xb2, 0xb0, 0x5f,
+ 0x6b, 0x3f, 0x7a, 0x32, 0xf7, 0x60, 0xe3, 0x4e, 0x7d, 0xa3, 0xac, 0x11,
+ 0xbd, 0x10, 0x8a, 0x5b, 0x95, 0x46, 0x27, 0x5c, 0x0b, 0x8c, 0x16, 0xe6,
+ 0x2f, 0xb1, 0xef, 0x2a, 0xa5, 0xb4, 0xdf, 0xc3, 0xd8, 0x34, 0xac, 0x07,
+ 0xb7, 0x2b, 0x06, 0xe3, 0x86, 0x86, 0xfd, 0x83, 0x45, 0xb8, 0x75, 0x57,
+ 0x1b, 0xf6, 0xf5, 0x9b, 0xc4, 0xcf, 0x5a, 0xff, 0x69, 0xbc, 0x87, 0x63,
+ 0xa6, 0xbc, 0xaf, 0x54, 0x82, 0x36, 0x4d, 0xf6, 0x29, 0x31, 0xfb, 0x9c,
+ 0x7e, 0xde, 0x3b, 0xe0, 0x9e, 0x12, 0xa3, 0xf0, 0x2e, 0xbf, 0xc1, 0x7c,
+ 0x71, 0x12, 0x7b, 0x06, 0x65, 0x6d, 0x60, 0x9a, 0x72, 0xa4, 0x7f, 0xae,
+ 0xaf, 0x8b, 0xd8, 0x7f, 0xaf, 0x99, 0xc5, 0x99, 0x85, 0xd5, 0xc0, 0x0c,
+ 0x05, 0xa1, 0xcf, 0x04, 0xe4, 0x5b, 0x35, 0xfc, 0x7b, 0xd7, 0xf2, 0x7f,
+ 0x51, 0xda, 0xa9, 0xa9, 0xc8, 0xad, 0x17, 0xbc, 0x5e, 0x2d, 0xef, 0xf2,
+ 0x1d, 0x49, 0xcd, 0xac, 0xcc, 0x3d, 0x77, 0xfe, 0xa4, 0x3e, 0x5e, 0xb3,
+ 0xfc, 0x76, 0x1b, 0x85, 0xba, 0xaf, 0x5a, 0x51, 0xaf, 0x94, 0x2f, 0x62,
+ 0xdb, 0xe2, 0x9f, 0xd3, 0x94, 0x76, 0xe2, 0xa9, 0x1a, 0x9a, 0xa6, 0xb4,
+ 0x0d, 0x5d, 0xd8, 0xee, 0x8b, 0x56, 0xb4, 0x45, 0xce, 0x0b, 0xe5, 0xdc,
+ 0xd3, 0x50, 0x2a, 0x65, 0x0b, 0xf7, 0x9f, 0xc9, 0xb7, 0x55, 0x4c, 0xae,
+ 0x9a, 0x2b, 0x73, 0x6b, 0xbf, 0xec, 0xad, 0x8a, 0xe2, 0x68, 0xc3, 0xd4,
+ 0xf6, 0x0a, 0x7d, 0x7f, 0xef, 0xbc, 0xf6, 0x72, 0x65, 0x67, 0xb1, 0x4d,
+ 0x29, 0x9f, 0xc5, 0xff, 0x6b, 0xaf, 0x23, 0xbc, 0x61, 0xef, 0x93, 0xdc,
+ 0x6a, 0x36, 0x46, 0x4b, 0xf0, 0x39, 0xa8, 0x97, 0xc6, 0xe7, 0x97, 0xd8,
+ 0xfc, 0x36, 0xda, 0x52, 0xc2, 0x1c, 0xd7, 0x6d, 0x44, 0xef, 0x75, 0x23,
+ 0x9b, 0x65, 0x5c, 0x6e, 0x3d, 0xa3, 0xec, 0x57, 0x6e, 0x0d, 0xe8, 0x1b,
+ 0xdf, 0x25, 0xdf, 0x78, 0x3e, 0x10, 0x27, 0xd6, 0x1b, 0xbe, 0x3e, 0x45,
+ 0x37, 0xd7, 0x32, 0xa6, 0x3d, 0xcb, 0x1c, 0x72, 0x4d, 0xa0, 0xd7, 0x7e,
+ 0xc6, 0xa8, 0x44, 0x56, 0xe0, 0x12, 0xfb, 0xbb, 0x2c, 0x2d, 0x30, 0xd2,
+ 0xcf, 0xcb, 0x9a, 0x17, 0x7f, 0xc7, 0x30, 0xdf, 0xbe, 0xb6, 0x06, 0x41,
+ 0xfb, 0xff, 0xaa, 0xfc, 0xb7, 0x5b, 0x5a, 0x51, 0x6b, 0xff, 0xbf, 0x19,
+ 0x73, 0xd3, 0x67, 0xd7, 0x86, 0xd1, 0x6d, 0x5a, 0xd6, 0x53, 0xa6, 0x85,
+ 0x37, 0xce, 0xed, 0xd1, 0x5e, 0xe1, 0x60, 0xce, 0x41, 0x17, 0x8e, 0xe5,
+ 0xbe, 0x5d, 0x75, 0xee, 0xfd, 0x8c, 0xa5, 0xe7, 0xed, 0xd1, 0x96, 0xf7,
+ 0xe2, 0xab, 0xed, 0x6f, 0x93, 0xcd, 0x5b, 0xe4, 0xc4, 0x73, 0x89, 0x8a,
+ 0x98, 0x87, 0xbf, 0x37, 0x2d, 0x2a, 0xc2, 0xfa, 0x10, 0x39, 0xdf, 0xa5,
+ 0xc7, 0x71, 0xda, 0xfe, 0x46, 0x43, 0x3c, 0x24, 0xdf, 0x66, 0x38, 0x9a,
+ 0x50, 0x71, 0x6c, 0xb0, 0x27, 0xb4, 0xc7, 0xee, 0xfb, 0x55, 0x74, 0x8f,
+ 0xca, 0x73, 0xbf, 0x16, 0xac, 0x4e, 0x4c, 0xda, 0x7b, 0xda, 0x36, 0xa7,
+ 0x24, 0xf7, 0xd6, 0xb3, 0x6b, 0x98, 0xaf, 0xaa, 0x8e, 0x20, 0x6e, 0x62,
+ 0x7c, 0x79, 0x21, 0x41, 0x3b, 0x5d, 0xa8, 0x77, 0x7c, 0x97, 0x1c, 0xa1,
+ 0x22, 0xa2, 0x07, 0xdf, 0x51, 0x5a, 0xc9, 0xc5, 0xdc, 0x98, 0x48, 0x88,
+ 0x2d, 0xca, 0xb7, 0x9d, 0x6e, 0xc6, 0x7e, 0x72, 0xd2, 0xe7, 0x13, 0x1a,
+ 0x4e, 0x37, 0x78, 0x90, 0x26, 0x47, 0x7d, 0x2e, 0xe1, 0xc6, 0x63, 0xe4,
+ 0xa8, 0x8f, 0x0e, 0xca, 0x1a, 0x61, 0x13, 0x1a, 0x13, 0xb2, 0x3e, 0x4c,
+ 0xde, 0x35, 0xe2, 0xa5, 0x3d, 0x5a, 0x56, 0x37, 0x6d, 0xb7, 0x4d, 0x9b,
+ 0x60, 0x9f, 0xb2, 0xae, 0x18, 0xc5, 0x35, 0xe4, 0x1d, 0x8f, 0x8e, 0xf8,
+ 0xf0, 0x7d, 0x72, 0xf3, 0x24, 0xeb, 0xbd, 0x90, 0xf0, 0xa3, 0x2f, 0xed,
+ 0xc3, 0xd3, 0xe4, 0xe8, 0x5b, 0x78, 0x2e, 0xdf, 0x09, 0x2b, 0x32, 0x82,
+ 0xe4, 0xc1, 0x87, 0x51, 0xd6, 0x77, 0x11, 0xd6, 0xad, 0x3c, 0x08, 0xb5,
+ 0xef, 0x10, 0x8f, 0x2b, 0x19, 0xb3, 0xaf, 0x44, 0x6a, 0x30, 0x82, 0xd4,
+ 0xc8, 0x8f, 0xd0, 0x3b, 0x28, 0xe3, 0x92, 0xef, 0x3d, 0xc9, 0xbe, 0x27,
+ 0x72, 0xbd, 0x3e, 0x2f, 0x86, 0x46, 0xa4, 0x9f, 0x6a, 0xf6, 0xfd, 0xe7,
+ 0xb6, 0xff, 0x1f, 0xd6, 0xba, 0x1b, 0xa5, 0xed, 0x83, 0x9f, 0xd0, 0xbe,
+ 0xe8, 0xaa, 0xf0, 0x9e, 0xa1, 0xac, 0x75, 0xb8, 0xd9, 0xa6, 0x07, 0x8e,
+ 0x48, 0x76, 0x65, 0x39, 0xf4, 0xe8, 0x36, 0xc5, 0x68, 0x2e, 0x53, 0x26,
+ 0xb1, 0x2d, 0x23, 0xef, 0x8d, 0x15, 0xe3, 0x69, 0xe2, 0xa3, 0x2b, 0xa4,
+ 0x6b, 0xdf, 0xa5, 0xed, 0x2c, 0x21, 0xa6, 0xbc, 0x61, 0x7e, 0x06, 0x71,
+ 0x4d, 0xf4, 0x57, 0x8c, 0x1f, 0xf4, 0xbb, 0xf1, 0x4e, 0x28, 0x82, 0xdc,
+ 0xb7, 0xbd, 0x3c, 0xf8, 0x71, 0xc2, 0xcb, 0xf9, 0xaa, 0xcb, 0x1a, 0x8e,
+ 0xb9, 0xc0, 0xb4, 0xdc, 0xb5, 0xa3, 0x89, 0x35, 0xd8, 0x43, 0x79, 0x5f,
+ 0x48, 0x9c, 0xe1, 0xfc, 0xb4, 0x53, 0xff, 0xa2, 0xef, 0x78, 0x5e, 0xd7,
+ 0x3d, 0xd4, 0xf5, 0x2c, 0x3c, 0x9b, 0xb8, 0x0f, 0x8f, 0x52, 0xfe, 0x47,
+ 0xfa, 0x8d, 0xe8, 0xc5, 0xca, 0x61, 0xe2, 0x65, 0x31, 0x8e, 0xb1, 0xed,
+ 0x5b, 0x99, 0x29, 0x4f, 0x4a, 0x5f, 0x29, 0x59, 0x9f, 0x54, 0xf0, 0xce,
+ 0xa2, 0xc3, 0x18, 0xe7, 0xbd, 0x1f, 0xf3, 0x77, 0x78, 0x61, 0x25, 0xfb,
+ 0x10, 0xfd, 0xf8, 0xed, 0x5c, 0xa0, 0x8b, 0x3c, 0x67, 0x79, 0xc3, 0x61,
+ 0x6c, 0x1d, 0x92, 0x6b, 0x6d, 0xe8, 0xed, 0x7f, 0x0f, 0x8e, 0x10, 0x71,
+ 0xc8, 0xdb, 0x40, 0x5b, 0xcf, 0x62, 0x5b, 0xfa, 0xc3, 0x69, 0x39, 0x0e,
+ 0xfa, 0xca, 0x34, 0xd9, 0x8b, 0x7c, 0x34, 0x51, 0x8c, 0xe7, 0x58, 0x67,
+ 0x5d, 0xc8, 0x95, 0x7f, 0x66, 0x72, 0x98, 0xfc, 0xc9, 0x89, 0x34, 0xfb,
+ 0x48, 0xd8, 0x6d, 0x4c, 0x53, 0x76, 0xd3, 0x0f, 0x2b, 0x17, 0x4e, 0x53,
+ 0x52, 0x43, 0xc2, 0xed, 0x7f, 0x84, 0x27, 0xef, 0xcf, 0xe9, 0x70, 0x8f,
+ 0xb9, 0x06, 0x43, 0xe9, 0x1f, 0x17, 0xda, 0x9b, 0xf2, 0x2e, 0x9c, 0xbc,
+ 0x9f, 0x53, 0x78, 0x57, 0x27, 0xf7, 0x4c, 0xeb, 0xdb, 0x99, 0x0a, 0xf2,
+ 0xe7, 0x52, 0xda, 0x5a, 0x51, 0xcc, 0xcb, 0xb8, 0xba, 0x66, 0x81, 0x86,
+ 0x9d, 0x97, 0xd5, 0x4d, 0x43, 0x85, 0xe6, 0xfc, 0x75, 0xc3, 0xf3, 0xec,
+ 0xa7, 0x22, 0x56, 0x15, 0xd9, 0x63, 0xef, 0x83, 0x0a, 0x5d, 0x56, 0xc3,
+ 0xb8, 0x22, 0xcf, 0x86, 0x63, 0x78, 0x2b, 0x51, 0x1d, 0xab, 0x8e, 0x54,
+ 0x12, 0x6f, 0x4f, 0xa3, 0x6f, 0xd8, 0x89, 0x0a, 0xf2, 0xe6, 0xf2, 0x64,
+ 0x35, 0xdc, 0xf6, 0x3a, 0xde, 0x45, 0xe4, 0x2b, 0xb3, 0xc9, 0x49, 0x66,
+ 0xa1, 0x92, 0xbc, 0xc4, 0x13, 0xb2, 0xac, 0x9f, 0x2d, 0xb4, 0xac, 0x4b,
+ 0x78, 0x94, 0xf0, 0x38, 0x15, 0x12, 0x3f, 0x8d, 0xa2, 0xce, 0xf6, 0x57,
+ 0x03, 0xf5, 0xf6, 0xff, 0x26, 0xfa, 0x7a, 0x47, 0x68, 0xfe, 0xf8, 0x7d,
+ 0xa1, 0xb9, 0xe3, 0x35, 0x50, 0x07, 0xa6, 0xc3, 0xc1, 0xb6, 0xbe, 0x70,
+ 0x99, 0x85, 0x26, 0xfa, 0xf0, 0x5a, 0x53, 0x78, 0xd1, 0x1a, 0xf2, 0xa2,
+ 0xde, 0x90, 0x31, 0x7e, 0x10, 0x57, 0x33, 0xce, 0xb9, 0x07, 0x7c, 0xec,
+ 0x47, 0x72, 0x6c, 0x67, 0x76, 0x0e, 0xf9, 0xf6, 0x67, 0x16, 0x0a, 0x47,
+ 0x6a, 0x25, 0x47, 0x3a, 0x84, 0xd6, 0xf1, 0xc3, 0xb8, 0x9e, 0x65, 0x3c,
+ 0xe4, 0x2a, 0xc9, 0xcc, 0x8f, 0xd0, 0x97, 0xb1, 0xb0, 0x3d, 0x94, 0xc5,
+ 0xb5, 0x6c, 0xbb, 0x74, 0xa0, 0x99, 0xdc, 0x70, 0x05, 0xd6, 0x8d, 0xcb,
+ 0xbb, 0x52, 0x13, 0x58, 0x3e, 0x4e, 0xce, 0x39, 0x5e, 0xf0, 0x57, 0xe1,
+ 0x4b, 0x2b, 0xc8, 0x97, 0x64, 0x2d, 0x6d, 0x95, 0xbd, 0x96, 0xa6, 0xd2,
+ 0x0f, 0x1b, 0x13, 0xf2, 0x9e, 0x50, 0x1c, 0xab, 0xc7, 0x05, 0xab, 0xef,
+ 0x41, 0xf7, 0xb8, 0xac, 0xcd, 0x7e, 0x33, 0x74, 0xf1, 0xf8, 0xab, 0x68,
+ 0x1c, 0x1f, 0x0a, 0xcd, 0x1b, 0x1f, 0xa1, 0xdc, 0x09, 0xca, 0xd6, 0x1f,
+ 0xaa, 0x1d, 0x1f, 0x0c, 0x05, 0xc7, 0x77, 0x87, 0x02, 0xe3, 0x2d, 0xd8,
+ 0x32, 0xbe, 0x0a, 0x9b, 0xc7, 0x37, 0x62, 0xd3, 0xb8, 0xe0, 0xfc, 0x24,
+ 0x96, 0x8d, 0xbf, 0x81, 0xa5, 0xe3, 0xcf, 0xa3, 0x69, 0xfc, 0x04, 0x96,
+ 0x8c, 0xff, 0x08, 0xcd, 0xe3, 0xaf, 0x70, 0x2c, 0xb2, 0xd6, 0x2b, 0xeb,
+ 0xbc, 0x85, 0xe7, 0x6a, 0x53, 0xf7, 0x24, 0xcb, 0x5a, 0x86, 0x7c, 0xbf,
+ 0x43, 0xe6, 0xd0, 0x85, 0x95, 0xda, 0x6b, 0xe8, 0xd9, 0x25, 0xdf, 0x24,
+ 0xac, 0xd3, 0xba, 0xe5, 0xf9, 0xa3, 0xf7, 0x79, 0xd9, 0x63, 0x4f, 0x1b,
+ 0x3b, 0xff, 0xbd, 0xbc, 0xc9, 0xb3, 0xcf, 0x18, 0xe5, 0x1b, 0x18, 0xf2,
+ 0xec, 0x73, 0x12, 0x5d, 0x99, 0xdf, 0x5a, 0x51, 0x4d, 0xca, 0xca, 0xf7,
+ 0x3f, 0xc4, 0x1e, 0x5e, 0xc3, 0x43, 0xbb, 0x26, 0xc9, 0x59, 0xb2, 0xf6,
+ 0x5a, 0xcd, 0xbb, 0xf3, 0xe4, 0x9b, 0x56, 0xf2, 0xce, 0xfe, 0x6b, 0x48,
+ 0x8d, 0x02, 0xe3, 0x0f, 0x8b, 0x1f, 0xae, 0xa1, 0x1f, 0x66, 0xc5, 0x27,
+ 0xe3, 0xc4, 0xe4, 0xaf, 0x78, 0x70, 0x0f, 0x79, 0x49, 0x11, 0xb2, 0x23,
+ 0xa5, 0x78, 0x66, 0x30, 0x6e, 0xcd, 0x31, 0x3c, 0x28, 0x8f, 0x18, 0xd9,
+ 0x4b, 0x18, 0x67, 0x5f, 0xe1, 0xb5, 0x89, 0x7e, 0xf8, 0x7d, 0x46, 0xc0,
+ 0x37, 0x87, 0xe7, 0xc7, 0x86, 0xb2, 0xe4, 0x14, 0x1d, 0x98, 0xe4, 0x7f,
+ 0xc9, 0x41, 0x81, 0x6e, 0x0c, 0x0d, 0x89, 0x3e, 0x5b, 0xa8, 0x4f, 0xc1,
+ 0x45, 0xbd, 0xa3, 0x89, 0x78, 0x68, 0x29, 0x82, 0x87, 0x2a, 0xca, 0x1e,
+ 0xe8, 0xa4, 0xbf, 0xea, 0xb1, 0x9f, 0x30, 0x16, 0xf4, 0x29, 0x3f, 0xc2,
+ 0x73, 0xcc, 0x19, 0x4a, 0x1f, 0x20, 0xff, 0x20, 0x56, 0x56, 0x44, 0x14,
+ 0x63, 0x79, 0xe0, 0x14, 0x9e, 0x19, 0x71, 0xc2, 0x9d, 0x74, 0x62, 0x82,
+ 0x38, 0xe9, 0x48, 0xca, 0xf3, 0x7a, 0x8d, 0xb2, 0xc8, 0xba, 0xd0, 0x09,
+ 0x64, 0xed, 0xe7, 0x69, 0xf2, 0x3c, 0xe4, 0x45, 0xbb, 0x1f, 0x27, 0x65,
+ 0xef, 0x21, 0x96, 0x76, 0xa5, 0x5e, 0x42, 0xd3, 0x90, 0x07, 0x73, 0x92,
+ 0x13, 0xcc, 0x5f, 0x5e, 0x45, 0x6a, 0xd7, 0x2c, 0x7c, 0x95, 0x3c, 0x70,
+ 0x66, 0xd2, 0x84, 0x46, 0xbd, 0xdd, 0x34, 0x66, 0x22, 0xba, 0x77, 0x15,
+ 0x56, 0xee, 0xfd, 0x22, 0x8f, 0xe9, 0xb8, 0x7e, 0x6f, 0x3b, 0x3e, 0x3f,
+ 0x16, 0x47, 0xeb, 0x58, 0x0f, 0x8f, 0x36, 0x5c, 0xb7, 0xa3, 0x12, 0xe9,
+ 0x90, 0xc6, 0x9c, 0xba, 0x8d, 0x39, 0xb5, 0xf0, 0xa1, 0xd5, 0x78, 0x86,
+ 0xb8, 0x13, 0x0c, 0xad, 0xc6, 0x84, 0xed, 0x8b, 0xb2, 0x97, 0x71, 0x35,
+ 0x36, 0x31, 0x5f, 0x1e, 0xc6, 0x6a, 0x74, 0xf1, 0xda, 0x0e, 0x7b, 0x0e,
+ 0x0e, 0x63, 0x31, 0xf3, 0xa1, 0xf7, 0x2f, 0x3f, 0x8c, 0x2b, 0xf6, 0x48,
+ 0xdf, 0xa7, 0x91, 0xda, 0xb9, 0x86, 0x6d, 0x66, 0xd1, 0x32, 0xf6, 0x43,
+ 0x7c, 0x7e, 0x07, 0x6e, 0xab, 0x44, 0x25, 0x9e, 0x0f, 0x05, 0x5a, 0xfb,
+ 0x94, 0x1f, 0xda, 0x6d, 0x6f, 0xa2, 0x1f, 0x6f, 0x65, 0xb9, 0x47, 0xd2,
+ 0x27, 0xd0, 0x9b, 0x9a, 0x3a, 0xa7, 0xf6, 0x7b, 0xed, 0x8c, 0x07, 0x2f,
+ 0x63, 0xdf, 0xc8, 0x24, 0xb1, 0xf7, 0x24, 0x8f, 0x0b, 0x9f, 0x5f, 0x7b,
+ 0xed, 0x7c, 0x26, 0x67, 0x37, 0x92, 0xbf, 0xc8, 0x3a, 0x70, 0x0b, 0x7c,
+ 0x29, 0xe1, 0x44, 0xd9, 0xad, 0x33, 0xa1, 0x6f, 0x0c, 0xdb, 0x1c, 0xc9,
+ 0x88, 0x91, 0x1b, 0xb5, 0x7c, 0x57, 0xf1, 0x90, 0x1b, 0x05, 0xb1, 0x22,
+ 0xa3, 0x47, 0xaf, 0xa5, 0xbe, 0x4b, 0xee, 0x7f, 0x19, 0xce, 0xfb, 0x9d,
+ 0x28, 0x4e, 0xca, 0xda, 0xc9, 0x04, 0x7a, 0x33, 0xf2, 0xfe, 0x6e, 0x56,
+ 0x2f, 0x26, 0xae, 0x16, 0x25, 0xb3, 0x8c, 0xfd, 0xd9, 0xf9, 0x45, 0x90,
+ 0x77, 0xf1, 0xaf, 0xc2, 0x9a, 0xfe, 0x28, 0xba, 0x4c, 0x79, 0x57, 0x27,
+ 0x37, 0xfe, 0x39, 0x0d, 0x2f, 0xa3, 0x9b, 0xf1, 0xa7, 0x8d, 0x98, 0xf8,
+ 0x55, 0xfb, 0x59, 0xe8, 0xcb, 0xe8, 0x19, 0x2c, 0xbc, 0xbb, 0x2e, 0x6d,
+ 0x3e, 0x4f, 0xbd, 0xb9, 0xf2, 0xdf, 0xec, 0x91, 0x36, 0x75, 0xd3, 0xaf,
+ 0x4e, 0xcb, 0xbd, 0x8b, 0x03, 0xfb, 0x19, 0x36, 0xed, 0xe3, 0x35, 0xf4,
+ 0xee, 0x2a, 0x8c, 0x99, 0xb9, 0x41, 0xe0, 0x35, 0xf4, 0x8f, 0xca, 0xd8,
+ 0xaf, 0x9f, 0x96, 0x7b, 0xc7, 0x78, 0xaa, 0x3e, 0x0a, 0x75, 0x1d, 0xb4,
+ 0xe7, 0xc2, 0xfd, 0x8f, 0xfb, 0x6e, 0xd0, 0xa7, 0xec, 0x6f, 0xf0, 0xe4,
+ 0xbe, 0x81, 0x04, 0x3c, 0x99, 0x90, 0x77, 0xfb, 0xd5, 0xc5, 0x2e, 0xa8,
+ 0x5e, 0x17, 0x8a, 0x19, 0x2f, 0x6a, 0xd0, 0xed, 0xb5, 0x70, 0x35, 0xc7,
+ 0xb2, 0xbf, 0xfe, 0x3a, 0x66, 0x1a, 0xf1, 0x56, 0x97, 0xfd, 0xce, 0xe1,
+ 0x8a, 0xbf, 0xfe, 0xe8, 0x3b, 0x87, 0x6f, 0x10, 0x67, 0x15, 0x94, 0x1b,
+ 0x37, 0xe1, 0x05, 0x3b, 0xa6, 0x28, 0x28, 0x9b, 0x2b, 0xeb, 0x98, 0x7e,
+ 0x3c, 0x6b, 0xd4, 0xf9, 0xab, 0xe4, 0xf9, 0x94, 0x72, 0xca, 0x92, 0x6f,
+ 0x06, 0x6c, 0xcb, 0xfc, 0xb1, 0x3d, 0xf1, 0x4f, 0x61, 0xcb, 0xce, 0x30,
+ 0xe4, 0xfd, 0x15, 0xa7, 0xa1, 0x79, 0x73, 0xfc, 0x4a, 0x64, 0x93, 0xbd,
+ 0xe4, 0xb7, 0x12, 0x9c, 0xde, 0xa0, 0x9f, 0xbe, 0x21, 0x7b, 0xa6, 0xc8,
+ 0x99, 0xfe, 0x12, 0xc1, 0xaa, 0xc2, 0x38, 0x65, 0xaf, 0xa9, 0x92, 0x1b,
+ 0xab, 0x5d, 0x47, 0xca, 0x4a, 0xbd, 0x37, 0xec, 0x35, 0x5c, 0x97, 0xf1,
+ 0x5b, 0xeb, 0x4d, 0x6f, 0x35, 0xcb, 0x1e, 0xce, 0xdf, 0x9f, 0x14, 0x9f,
+ 0x33, 0xe5, 0x1b, 0x56, 0x4e, 0xbb, 0x8e, 0xe8, 0xf7, 0x5c, 0x9d, 0xee,
+ 0x94, 0x83, 0xb8, 0x79, 0xc2, 0xea, 0xf4, 0xca, 0x18, 0xee, 0xbc, 0xa0,
+ 0x8e, 0xac, 0x2b, 0x68, 0xd2, 0x6f, 0x58, 0xc6, 0xdc, 0x95, 0xf9, 0x68,
+ 0x9f, 0xb2, 0xde, 0x5b, 0x64, 0x94, 0xe1, 0x54, 0x55, 0x6e, 0x1d, 0xe6,
+ 0x9c, 0x8c, 0x3d, 0x35, 0xb2, 0x4f, 0xaf, 0xd8, 0x3e, 0xb7, 0xfb, 0x35,
+ 0xcf, 0xd5, 0xfb, 0xbb, 0xfc, 0x78, 0xab, 0xed, 0x77, 0x86, 0x1e, 0xb4,
+ 0x79, 0x91, 0x63, 0xca, 0xb8, 0x4b, 0x6a, 0xce, 0xef, 0xe7, 0x2b, 0xf9,
+ 0x7e, 0x45, 0x1e, 0xef, 0x94, 0x3e, 0x44, 0xae, 0x87, 0xf3, 0x75, 0xf4,
+ 0x70, 0xd4, 0xee, 0x5f, 0x65, 0xbe, 0x55, 0xe8, 0x93, 0xfe, 0xb8, 0xb0,
+ 0xd0, 0x46, 0x56, 0xec, 0xb3, 0xb3, 0x98, 0xb1, 0xed, 0x54, 0xc3, 0x3d,
+ 0xd8, 0x94, 0x10, 0x3d, 0xcb, 0xb7, 0x60, 0x89, 0xe1, 0x36, 0x57, 0x73,
+ 0xd1, 0x5f, 0x2f, 0xc3, 0x90, 0x16, 0xc7, 0x9e, 0x7a, 0x79, 0x47, 0xce,
+ 0x45, 0x9f, 0x88, 0xa3, 0xc4, 0x28, 0x96, 0xfd, 0xc7, 0xf6, 0x1e, 0x94,
+ 0x7d, 0xa6, 0x1e, 0x7d, 0x52, 0xbe, 0x55, 0x76, 0xa9, 0xbd, 0x5e, 0xd5,
+ 0x3c, 0x04, 0xb9, 0x6e, 0xe2, 0xda, 0xf3, 0xf2, 0xfe, 0x12, 0xda, 0x8e,
+ 0xbd, 0x27, 0xda, 0x94, 0x77, 0xe8, 0xfa, 0x12, 0xf2, 0x2e, 0x57, 0x5d,
+ 0x8c, 0xfc, 0x12, 0x2f, 0xa4, 0x65, 0xbf, 0xc2, 0xef, 0xac, 0x78, 0x8d,
+ 0xec, 0x8b, 0x9c, 0x5a, 0xa7, 0x88, 0xb8, 0x16, 0x08, 0x57, 0x28, 0x85,
+ 0xf7, 0xb9, 0xce, 0xfd, 0x5d, 0x4f, 0x9b, 0x39, 0x6d, 0xbf, 0x83, 0x27,
+ 0x67, 0x11, 0x34, 0xa6, 0xe4, 0x9b, 0xa7, 0xfa, 0xc4, 0x72, 0xd4, 0x65,
+ 0x6b, 0x1d, 0xce, 0x3c, 0x7f, 0x09, 0x63, 0x05, 0xed, 0x66, 0x73, 0x20,
+ 0x6c, 0xbf, 0x6b, 0xb6, 0x2c, 0x55, 0x1b, 0x7c, 0x04, 0x7a, 0xfb, 0xdb,
+ 0x2c, 0x7f, 0x5d, 0xe6, 0xfb, 0xd6, 0x90, 0x57, 0xc6, 0x54, 0xc0, 0x88,
+ 0x13, 0xf4, 0x0d, 0xea, 0x31, 0x22, 0xfe, 0xe1, 0x41, 0x55, 0x24, 0x4c,
+ 0x3f, 0x96, 0xf8, 0x2f, 0xef, 0xa9, 0xe9, 0xbb, 0xe3, 0x30, 0xd1, 0xc8,
+ 0x1c, 0xdd, 0x65, 0xef, 0x73, 0xd6, 0xfd, 0x2b, 0x19, 0x87, 0x8e, 0x9c,
+ 0xdd, 0x13, 0x20, 0x7c, 0xe1, 0xc7, 0x35, 0xf9, 0xbd, 0xd0, 0xee, 0x39,
+ 0x8c, 0x8f, 0x96, 0xfd, 0x9c, 0x7f, 0x8d, 0x8d, 0x2d, 0x9a, 0xa1, 0xef,
+ 0xff, 0x95, 0xa3, 0x13, 0x4f, 0x2c, 0x30, 0x3a, 0x0e, 0xa8, 0xd9, 0x21,
+ 0x1f, 0x71, 0xe6, 0x4a, 0x47, 0x74, 0x07, 0xff, 0xfb, 0x5f, 0xb4, 0xbf,
+ 0xa1, 0x22, 0x75, 0xf5, 0xe0, 0x2a, 0x55, 0xf6, 0x0f, 0xb5, 0x60, 0xac,
+ 0x4f, 0xde, 0x7d, 0xd0, 0x5b, 0xbf, 0xad, 0x74, 0x62, 0x43, 0xc8, 0x68,
+ 0xd9, 0xa8, 0xe8, 0xcd, 0x7f, 0xaf, 0xe8, 0xfe, 0x90, 0x22, 0xe5, 0x82,
+ 0xb2, 0xb6, 0x77, 0x36, 0xf6, 0xba, 0xd8, 0xc7, 0xde, 0x84, 0x1e, 0x9e,
+ 0xc6, 0xb2, 0xa7, 0x4c, 0xc3, 0xf7, 0x1e, 0xdb, 0xfc, 0x09, 0x8f, 0x1d,
+ 0xf6, 0x3b, 0xec, 0x52, 0x3e, 0x3a, 0xdf, 0x65, 0x7f, 0x8f, 0xb8, 0x95,
+ 0x31, 0x45, 0xbe, 0x35, 0x1c, 0x83, 0x96, 0x9c, 0x45, 0x13, 0xd3, 0x7b,
+ 0x6f, 0x80, 0xe4, 0xc0, 0x37, 0x4f, 0x47, 0xa9, 0x07, 0xde, 0x48, 0x27,
0xe6, 0x2e, 0x30, 0x7c, 0x8b, 0x54, 0xbb, 0x7e, 0x30, 0xaa, 0x4a, 0x7d,
- 0xdd, 0x3f, 0x08, 0x69, 0x23, 0x63, 0x69, 0x73, 0xcb, 0xed, 0x3a, 0x0b,
- 0xd4, 0xcf, 0xc0, 0x75, 0xf5, 0xaf, 0xe5, 0x5b, 0x46, 0x5a, 0xa5, 0x21,
- 0x75, 0xe2, 0x3b, 0x35, 0xfc, 0xb1, 0x7a, 0x82, 0x2b, 0xbf, 0xb2, 0x30,
- 0x4d, 0xea, 0xc9, 0x9e, 0xb1, 0x3b, 0x70, 0xaf, 0xfd, 0x3d, 0x16, 0xf1,
- 0x47, 0x3d, 0xfa, 0x15, 0xf2, 0xcf, 0x62, 0x45, 0xb8, 0xa7, 0xf0, 0x84,
- 0x56, 0x74, 0x33, 0x8e, 0x69, 0x21, 0xbd, 0xe7, 0x0a, 0xd5, 0x83, 0xc2,
- 0xc8, 0x63, 0xb2, 0x6f, 0x66, 0xef, 0x3c, 0x35, 0xbb, 0xbf, 0x26, 0xc6,
- 0x76, 0x8f, 0xff, 0xd1, 0xe7, 0xb8, 0xec, 0xab, 0xd8, 0x94, 0xf7, 0x5b,
- 0xec, 0x35, 0xc5, 0xd6, 0x84, 0x23, 0xb7, 0x5f, 0x30, 0x3f, 0xb7, 0x1a,
- 0xda, 0xc8, 0xf5, 0xd7, 0xc8, 0x37, 0x31, 0x39, 0xd6, 0xb5, 0x09, 0x59,
- 0x4d, 0xfa, 0xff, 0x00, 0x85, 0x57, 0x0f, 0xe7, 0xe8, 0x59, 0x00, 0x00,
+ 0xdd, 0x3f, 0x08, 0x69, 0x23, 0x6b, 0x69, 0x73, 0x2b, 0xed, 0x3a, 0x0b,
+ 0xd4, 0xcf, 0xc1, 0xf5, 0xe9, 0x5f, 0xcb, 0x37, 0x8b, 0xb4, 0x6a, 0x43,
+ 0xea, 0xc4, 0x77, 0x68, 0xf8, 0x63, 0xf5, 0x04, 0x57, 0x7e, 0x65, 0x61,
+ 0xba, 0xd4, 0x93, 0x3d, 0x66, 0x37, 0xe3, 0x76, 0xfb, 0xbb, 0x2b, 0xe2,
+ 0x8f, 0x7a, 0xf4, 0x6e, 0x72, 0xd5, 0x52, 0x45, 0x78, 0xaa, 0xc4, 0xa2,
+ 0x36, 0xe2, 0x61, 0x27, 0xb4, 0x90, 0xde, 0x7b, 0x91, 0xea, 0x41, 0x71,
+ 0x64, 0x54, 0xf6, 0xd9, 0xec, 0x9e, 0xa7, 0xe6, 0xf6, 0xe3, 0xc4, 0xd8,
+ 0xee, 0x91, 0x3f, 0xfa, 0xdc, 0x97, 0x7d, 0x95, 0x9a, 0xf2, 0xce, 0x8e,
+ 0xfd, 0x9e, 0x48, 0x5b, 0xc2, 0x91, 0xdf, 0x5f, 0x58, 0x98, 0x5b, 0x0d,
+ 0x6b, 0x98, 0x17, 0xac, 0x95, 0x6f, 0x63, 0x72, 0xac, 0xeb, 0x12, 0xb2,
+ 0x0a, 0xf5, 0x7f, 0x01, 0x28, 0xfc, 0xfc, 0x40, 0x38, 0x5a, 0x00, 0x00,
0x00 };
static const u32 bnx2_CP_b06FwData[(0x84/4) + 1] = {
@@ -2137,48 +2138,48 @@ static const u32 bnx2_CP_b06FwData[(0x84/4) + 1] = {
0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002,
0x00000001, 0x00000001, 0x00000001, 0x00000000 };
static const u32 bnx2_CP_b06FwRodata[(0x130/4) + 1] = {
- 0x08001f1c, 0x08001da8, 0x08001ef8, 0x08001ed4, 0x08001eb0, 0x08001e8c,
- 0x08001e64, 0x08001e3c, 0x08001e10, 0x08002014, 0x08002004, 0x08001dc4,
- 0x08001dc4, 0x08001dc4, 0x08001f44, 0x08001f44, 0x08001dc4, 0x08001dc4,
- 0x08001ff4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001fe4,
- 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4,
- 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4,
- 0x08001dc4, 0x08001dc4, 0x08001fd4, 0x08001dc4, 0x08001dc4, 0x08001fc4,
- 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4,
- 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4,
- 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001dc4, 0x08001fac,
- 0x08001dc4, 0x08001dc4, 0x08001f9c, 0x08001f8c, 0x080031e8, 0x080031f0,
- 0x080031b8, 0x080031c4, 0x080031d0, 0x080031dc, 0x08005644, 0x08005604,
- 0x080055d0, 0x080055a4, 0x08005580, 0x0800553c, 0x00000000 };
+ 0x08001e8c, 0x08001d18, 0x08001e68, 0x08001e44, 0x08001e20, 0x08001dfc,
+ 0x08001dd4, 0x08001dac, 0x08001d80, 0x08001f84, 0x08001f74, 0x08001d34,
+ 0x08001d34, 0x08001d34, 0x08001eb4, 0x08001eb4, 0x08001d34, 0x08001d34,
+ 0x08001f64, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001f54,
+ 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34,
+ 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34,
+ 0x08001d34, 0x08001d34, 0x08001f44, 0x08001d34, 0x08001d34, 0x08001f34,
+ 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34,
+ 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34,
+ 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001d34, 0x08001f1c,
+ 0x08001d34, 0x08001d34, 0x08001f0c, 0x08001efc, 0x08003208, 0x08003210,
+ 0x080031d8, 0x080031e4, 0x080031f0, 0x080031fc, 0x08005694, 0x08005654,
+ 0x08005620, 0x080055f4, 0x080055d0, 0x0800558c, 0x00000000 };
static struct fw_info bnx2_cp_fw_06 = {
- /* Firmware version: 4.0.5 */
+ /* Firmware version: 4.4.22 */
.ver_major = 0x4,
- .ver_minor = 0x0,
- .ver_fix = 0x5,
+ .ver_minor = 0x4,
+ .ver_fix = 0x16,
- .start_addr = 0x08000078,
+ .start_addr = 0x08000080,
.text_addr = 0x08000000,
- .text_len = 0x59e4,
+ .text_len = 0x5a34,
.text_index = 0x0,
.gz_text = bnx2_CP_b06FwText,
.gz_text_len = sizeof(bnx2_CP_b06FwText),
- .data_addr = 0x08005b40,
+ .data_addr = 0x08005b80,
.data_len = 0x84,
.data_index = 0x0,
.data = bnx2_CP_b06FwData,
- .sbss_addr = 0x08005bc4,
+ .sbss_addr = 0x08005c04,
.sbss_len = 0xe9,
.sbss_index = 0x0,
- .bss_addr = 0x08005cb0,
+ .bss_addr = 0x08005cf0,
.bss_len = 0x5d8,
.bss_index = 0x0,
- .rodata_addr = 0x080059e4,
+ .rodata_addr = 0x08005a34,
.rodata_len = 0x130,
.rodata_index = 0x0,
.rodata = bnx2_CP_b06FwRodata,
@@ -2201,761 +2202,761 @@ static const struct cpu_reg cpu_reg_cp = {
};
static u8 bnx2_RXP_b06FwText[] = {
- 0xec, 0x5b, 0x5d, 0x70, 0x5c, 0xd7, 0x5d, 0xff, 0xdf, 0xb3, 0x2b, 0x69,
- 0x2d, 0x4b, 0xf2, 0x95, 0xbc, 0x71, 0x56, 0xa9, 0x92, 0xec, 0x5a, 0x57,
- 0xd2, 0xa6, 0x12, 0xe1, 0xca, 0x6c, 0x12, 0x75, 0xd8, 0x69, 0xb6, 0xbb,
- 0xb2, 0xa3, 0xb4, 0x66, 0x46, 0x49, 0x0d, 0xcd, 0xb4, 0x65, 0x10, 0xbb,
- 0x0e, 0xa4, 0x0f, 0x0c, 0xc6, 0x40, 0x26, 0x80, 0xc1, 0xcb, 0x4a, 0x71,
- 0x94, 0x74, 0xad, 0xdd, 0xda, 0x0a, 0x86, 0x69, 0x61, 0x94, 0xd5, 0x87,
- 0x53, 0x66, 0xad, 0x4d, 0xcb, 0x4b, 0x99, 0xd6, 0xb1, 0xea, 0xb8, 0x26,
- 0x0f, 0x3c, 0xa4, 0x94, 0xce, 0x64, 0x20, 0x33, 0x35, 0xb2, 0x63, 0xfb,
- 0x81, 0x8f, 0xc0, 0x4c, 0x49, 0x20, 0x6e, 0x2e, 0xbf, 0xdf, 0xb9, 0xf7,
- 0xca, 0x2b, 0x45, 0xd0, 0x3c, 0xf0, 0x78, 0xcf, 0x8c, 0xe6, 0xde, 0x7b,
- 0xce, 0xff, 0xfc, 0xcf, 0xff, 0xfb, 0xe3, 0xac, 0xfd, 0x3b, 0x1d, 0xd2,
- 0x2e, 0xde, 0xe8, 0xc4, 0x5f, 0xea, 0xc8, 0x33, 0x47, 0x47, 0xef, 0x1f,
- 0xbd, 0x9f, 0xdf, 0x21, 0xc3, 0x08, 0xf3, 0x69, 0x48, 0x30, 0x82, 0x11,
- 0x8c, 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c,
- 0x60, 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60,
- 0x04, 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04,
- 0x23, 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23,
- 0x18, 0xc1, 0x08, 0x46, 0x30, 0x82, 0x11, 0x8c, 0x60, 0x04, 0x23, 0x18,
- 0xc1, 0x08, 0x46, 0x30, 0xfe, 0x3f, 0x47, 0x48, 0xc4, 0xe4, 0xb3, 0xd3,
- 0xfb, 0x93, 0x88, 0x4a, 0xc7, 0x8f, 0x66, 0x2d, 0x89, 0x84, 0xd2, 0x97,
- 0x9e, 0x2e, 0x58, 0x22, 0x99, 0xfa, 0x70, 0x3c, 0x27, 0x3f, 0x71, 0x8a,
- 0xd1, 0xb0, 0x70, 0xfe, 0xee, 0xf4, 0xad, 0xe3, 0xe7, 0x1f, 0x4a, 0xbc,
- 0xb3, 0x10, 0x92, 0x88, 0x99, 0x7e, 0x63, 0xd4, 0x1c, 0x94, 0x48, 0x1f,
- 0xf6, 0x7c, 0x6d, 0x68, 0x6d, 0x97, 0x74, 0xf9, 0xb8, 0x44, 0x6a, 0xe5,
- 0x84, 0x7d, 0x40, 0x86, 0xcd, 0x8b, 0x12, 0x96, 0x0c, 0xce, 0x58, 0xa9,
- 0x8b, 0x94, 0xca, 0x06, 0x71, 0x48, 0xa9, 0x1e, 0x91, 0x2b, 0x21, 0x42,
- 0x7d, 0xcb, 0xc8, 0x56, 0x3e, 0x70, 0x32, 0x61, 0x9c, 0x6b, 0xe1, 0xbd,
- 0xe1, 0xcf, 0x47, 0x44, 0xa5, 0x13, 0xc9, 0x6c, 0x68, 0x42, 0x6a, 0xf3,
- 0x8e, 0x33, 0x63, 0x7f, 0x0c, 0x38, 0x7a, 0x64, 0xc6, 0x72, 0xbf, 0xb3,
- 0xf6, 0xc7, 0xcd, 0x71, 0xb9, 0x13, 0x73, 0x21, 0x51, 0xd6, 0x5d, 0xf8,
- 0x8b, 0x1b, 0xb9, 0xd3, 0x5f, 0x36, 0xb2, 0x8b, 0x1d, 0x52, 0xaa, 0x38,
- 0x52, 0xb0, 0x25, 0x93, 0xb5, 0x77, 0x60, 0xfd, 0x03, 0xa7, 0xb0, 0xb1,
- 0x67, 0xd8, 0xcc, 0x49, 0x8b, 0x64, 0xa2, 0x31, 0xc0, 0xcc, 0x1b, 0xb9,
- 0xb3, 0x7f, 0xdd, 0x21, 0xed, 0xa0, 0x27, 0xc5, 0xef, 0x0f, 0x9c, 0x90,
- 0x65, 0x61, 0x9d, 0xe7, 0xe3, 0xbb, 0x41, 0xbc, 0x7c, 0x27, 0xce, 0x2b,
- 0xce, 0xf9, 0xa1, 0x98, 0x7c, 0xb3, 0x11, 0x95, 0x6f, 0x34, 0x4c, 0x79,
- 0xa5, 0xd1, 0x27, 0x17, 0x1a, 0x8e, 0xf3, 0x0d, 0xdb, 0x71, 0xde, 0xc0,
- 0xdf, 0x7f, 0xd8, 0x1b, 0x3c, 0x60, 0x14, 0x8d, 0xf1, 0xc6, 0x57, 0x3b,
- 0xa4, 0x2b, 0x11, 0x17, 0xd5, 0x21, 0xd3, 0x95, 0x98, 0xcc, 0x54, 0xca,
- 0xc6, 0x63, 0x67, 0xe7, 0x8c, 0xc9, 0xb3, 0x55, 0x9c, 0x19, 0xc6, 0x9c,
- 0x14, 0x4b, 0xf6, 0xcb, 0x46, 0xae, 0x31, 0x6b, 0x3c, 0x7e, 0xb6, 0x0b,
- 0x34, 0xf2, 0xfc, 0x3d, 0x46, 0xf6, 0xf4, 0x2d, 0xc9, 0xda, 0x94, 0x71,
- 0xc2, 0xfc, 0x3c, 0xc4, 0x9e, 0x2d, 0x93, 0xe6, 0x56, 0x8f, 0x5e, 0xc7,
- 0x51, 0x69, 0xe7, 0x78, 0x36, 0x65, 0x99, 0x25, 0x21, 0x7d, 0x7a, 0xee,
- 0x82, 0x4b, 0xf3, 0x8a, 0x91, 0x3d, 0xdb, 0x61, 0xe4, 0xce, 0x84, 0x41,
- 0x87, 0xf4, 0x85, 0x84, 0xfb, 0x06, 0x62, 0x79, 0xa9, 0xe3, 0x0c, 0x31,
- 0x55, 0x9a, 0x72, 0x05, 0xcd, 0xa0, 0xe5, 0x9b, 0x15, 0xf0, 0x50, 0x01,
- 0x0f, 0x15, 0xf2, 0x16, 0x97, 0xf3, 0x43, 0x3e, 0x6f, 0x8e, 0xf3, 0x77,
- 0x36, 0x69, 0x4f, 0xc4, 0x33, 0xca, 0xe7, 0xd3, 0x71, 0xfe, 0xdd, 0x26,
- 0xaf, 0xe4, 0xc7, 0x71, 0x5e, 0xb1, 0x63, 0xa0, 0xdd, 0xb9, 0xa0, 0xac,
- 0x32, 0x78, 0xb1, 0x80, 0x9f, 0xb2, 0x9e, 0x03, 0x0f, 0xb3, 0xe0, 0x6f,
- 0x05, 0xbc, 0x55, 0x41, 0xc7, 0x4f, 0x3b, 0xaf, 0x68, 0xe4, 0x86, 0x36,
- 0xe4, 0x15, 0xa7, 0x8c, 0xf3, 0x4b, 0x0a, 0xb2, 0xde, 0x29, 0xf9, 0x05,
- 0x53, 0xa6, 0x96, 0xfc, 0xfd, 0xbe, 0x1d, 0x1c, 0x91, 0x83, 0x95, 0x1e,
- 0xc8, 0x86, 0xb2, 0x4c, 0xd8, 0x22, 0x0e, 0x64, 0x54, 0x4a, 0x2a, 0x11,
- 0x23, 0x6f, 0x1f, 0xd7, 0xfa, 0x5f, 0xb2, 0x24, 0x93, 0xb7, 0x29, 0x47,
- 0x89, 0xe7, 0xed, 0x62, 0x2c, 0x0c, 0x7b, 0x5b, 0xb2, 0x8a, 0x66, 0x58,
- 0x28, 0xc7, 0x44, 0xec, 0xf7, 0x21, 0xcb, 0x27, 0xcb, 0x92, 0xf9, 0x74,
- 0xd9, 0x97, 0xb1, 0x2b, 0xdf, 0xcf, 0x94, 0x3f, 0xd5, 0x29, 0xed, 0xea,
- 0x9e, 0x16, 0xf9, 0x0d, 0xec, 0x25, 0xee, 0x4d, 0x7b, 0xb1, 0xcf, 0x85,
- 0x73, 0xf7, 0x26, 0x9e, 0x10, 0x21, 0x6c, 0xa9, 0xbf, 0x45, 0xfb, 0x88,
- 0x18, 0x59, 0xab, 0x18, 0x0b, 0x01, 0x2e, 0x2f, 0xa5, 0x51, 0x6f, 0xae,
- 0x25, 0x6b, 0xdd, 0x0a, 0xcd, 0xd8, 0x89, 0x78, 0x49, 0x6e, 0x85, 0x2e,
- 0xdb, 0x7a, 0x6e, 0x47, 0xd6, 0x72, 0x64, 0x19, 0xd8, 0x9f, 0x83, 0x3f,
- 0x5c, 0x04, 0x47, 0x5f, 0x2a, 0xeb, 0xf9, 0x4e, 0xec, 0x4f, 0xb6, 0x00,
- 0x67, 0xbb, 0x24, 0x92, 0x35, 0xcc, 0x5f, 0x76, 0xe7, 0xbb, 0x5d, 0xbc,
- 0xa5, 0xfe, 0x76, 0x8d, 0x5b, 0xe4, 0x65, 0x77, 0xfe, 0x0e, 0x17, 0x77,
- 0xe9, 0x3e, 0xcc, 0x03, 0xff, 0xe0, 0xc4, 0x90, 0xa1, 0xe7, 0x7b, 0xe9,
- 0x4f, 0xbf, 0x5e, 0xbe, 0x15, 0x5a, 0xb6, 0x1d, 0xc9, 0x8d, 0x0e, 0x4e,
- 0x0c, 0x1a, 0x2e, 0xbe, 0x13, 0xee, 0xbe, 0xbb, 0x5d, 0x7c, 0x83, 0x13,
- 0x49, 0xc3, 0xc5, 0xb7, 0x54, 0xd6, 0x7b, 0x25, 0x5f, 0x26, 0xec, 0xe0,
- 0x84, 0x65, 0xdc, 0x2d, 0x53, 0xdd, 0x83, 0x13, 0x7b, 0x0d, 0x75, 0xcf,
- 0x4e, 0x97, 0x8f, 0x84, 0x4f, 0xc3, 0x4e, 0x4d, 0x03, 0xcf, 0xd5, 0xf3,
- 0x03, 0x59, 0xab, 0x74, 0xdf, 0x4e, 0x7d, 0x3e, 0xcf, 0xd4, 0x73, 0xf7,
- 0x91, 0x2e, 0x9e, 0x5d, 0x18, 0xdd, 0x74, 0xee, 0xcf, 0xdc, 0x96, 0xcf,
- 0x76, 0x67, 0xf2, 0x3c, 0x89, 0x84, 0xd3, 0xe1, 0xd1, 0x99, 0xf2, 0x11,
- 0xc9, 0x56, 0xe2, 0x32, 0x3d, 0xb2, 0x43, 0xa6, 0xcc, 0xfe, 0xa9, 0x83,
- 0xc2, 0xd8, 0x13, 0x19, 0x2d, 0x78, 0x3a, 0xcc, 0x89, 0x21, 0xd3, 0xe0,
- 0xf1, 0x60, 0x5d, 0x22, 0x06, 0xe0, 0xfb, 0xeb, 0x61, 0x79, 0xbe, 0x61,
- 0x48, 0xab, 0xf6, 0xcf, 0x84, 0xb9, 0x06, 0x3b, 0x7c, 0xb6, 0x42, 0x3b,
- 0xa6, 0xcd, 0x4a, 0xa6, 0x06, 0x3b, 0xbd, 0xa0, 0x7d, 0xb5, 0x9d, 0x7a,
- 0x2d, 0x16, 0x05, 0xae, 0x98, 0xb6, 0xcc, 0x9a, 0xb4, 0x49, 0x66, 0x52,
- 0x8a, 0x5c, 0xf7, 0x7c, 0x27, 0xb6, 0x28, 0xdf, 0x85, 0x0d, 0x88, 0x99,
- 0x4d, 0x71, 0x9e, 0xf0, 0x4d, 0xb0, 0xa6, 0xeb, 0x77, 0x21, 0xf8, 0x5d,
- 0x21, 0x45, 0x58, 0x29, 0xea, 0x58, 0xd1, 0x80, 0x2d, 0x36, 0xee, 0xee,
- 0x74, 0x63, 0x5d, 0x04, 0xfe, 0xd9, 0x01, 0x1f, 0xbf, 0x07, 0xfe, 0xd7,
- 0x67, 0x64, 0xcf, 0x38, 0x0e, 0x62, 0x4f, 0x54, 0x09, 0xfd, 0x0f, 0xbe,
- 0xde, 0xe0, 0x5a, 0x07, 0xe6, 0xc5, 0x9c, 0xb6, 0xbb, 0xc1, 0x9f, 0xe3,
- 0x4c, 0xd8, 0x71, 0x29, 0xd9, 0xbb, 0xb0, 0xaf, 0x45, 0xba, 0x2d, 0xda,
- 0x3b, 0x7d, 0x7a, 0x27, 0xce, 0x33, 0xf8, 0xdd, 0x85, 0xf3, 0x3a, 0x31,
- 0x17, 0x9b, 0xa6, 0x1f, 0xa7, 0x18, 0xb3, 0xdc, 0xf8, 0x29, 0x72, 0x15,
- 0xb4, 0x72, 0x8f, 0x86, 0x8b, 0xb4, 0xa5, 0x53, 0x72, 0xa3, 0xdc, 0x2b,
- 0x57, 0xa2, 0xe4, 0x1f, 0x38, 0x2b, 0x88, 0x87, 0x51, 0x03, 0xf4, 0x93,
- 0x6e, 0xc6, 0xbf, 0xdd, 0xde, 0xb7, 0x71, 0xaf, 0x7b, 0x86, 0x98, 0xa1,
- 0x74, 0x97, 0xe4, 0xf4, 0x9c, 0x28, 0x35, 0xba, 0xd3, 0x5b, 0xef, 0x32,
- 0x0e, 0x9c, 0x51, 0x32, 0xf4, 0x20, 0x62, 0x16, 0xce, 0xba, 0x6c, 0x39,
- 0xce, 0x65, 0xfb, 0xc7, 0xf0, 0x79, 0x25, 0x2d, 0xd6, 0x7a, 0x97, 0xb4,
- 0x43, 0x9e, 0x15, 0xa3, 0x49, 0x86, 0x31, 0x39, 0x51, 0xe1, 0x9e, 0xa2,
- 0x84, 0x2d, 0xc2, 0x10, 0xfe, 0x47, 0x80, 0x0b, 0x49, 0x1b, 0x7c, 0xf1,
- 0xa2, 0x1d, 0x25, 0xbd, 0xbb, 0x5c, 0xf8, 0x6e, 0x9c, 0x41, 0xda, 0xe9,
- 0x7b, 0x8e, 0xf6, 0xbd, 0x6c, 0x48, 0x65, 0xc6, 0xe7, 0xe1, 0x49, 0x23,
- 0x94, 0x77, 0xb6, 0x1b, 0xa1, 0x5f, 0xa6, 0x87, 0x8a, 0xa6, 0xd2, 0xba,
- 0x16, 0xc9, 0x95, 0xef, 0x95, 0x19, 0x1b, 0xe7, 0x59, 0x61, 0xd0, 0xcc,
- 0x38, 0x33, 0x50, 0x0c, 0x29, 0x78, 0x58, 0x0f, 0x65, 0xe5, 0xd3, 0xfa,
- 0x16, 0xce, 0x2b, 0x1a, 0x61, 0x8b, 0x67, 0xfc, 0xb2, 0x27, 0x1f, 0xda,
- 0x9d, 0x2d, 0xd9, 0x72, 0x07, 0xbf, 0x41, 0x47, 0xbb, 0xa6, 0x23, 0x94,
- 0xd6, 0xba, 0x33, 0x54, 0xda, 0x8f, 0xff, 0x04, 0xdd, 0x84, 0x07, 0x7c,
- 0x70, 0xaf, 0x85, 0xbd, 0x11, 0xd0, 0xd8, 0xd9, 0x44, 0x7f, 0x3b, 0xe1,
- 0x21, 0xab, 0x88, 0x77, 0x86, 0xe6, 0xdb, 0x70, 0xf9, 0xf6, 0x65, 0xf5,
- 0x2a, 0x64, 0xf5, 0xbe, 0x33, 0xb4, 0x8f, 0x38, 0x52, 0xc0, 0x01, 0xb9,
- 0x9b, 0x8c, 0x57, 0x8c, 0x51, 0xe6, 0x06, 0x2e, 0xf8, 0x81, 0x0a, 0xa5,
- 0x3b, 0x24, 0x67, 0xea, 0x1c, 0x00, 0xd8, 0x31, 0xd1, 0x31, 0xde, 0x22,
- 0x8f, 0xde, 0xb7, 0x95, 0xd0, 0x76, 0x93, 0xaf, 0x32, 0x0f, 0xfc, 0x31,
- 0x68, 0x5b, 0x4b, 0x28, 0xcd, 0x5a, 0x07, 0x64, 0x2e, 0x91, 0x96, 0xf4,
- 0x1b, 0xb2, 0x5c, 0x56, 0x7b, 0x5a, 0x65, 0x97, 0x4c, 0x42, 0x46, 0xb5,
- 0x31, 0xe4, 0xaf, 0x91, 0x0e, 0x09, 0xdd, 0xcf, 0x3c, 0x10, 0x03, 0xad,
- 0x6b, 0x09, 0x53, 0x6e, 0x39, 0x6a, 0x10, 0xfb, 0x47, 0xa0, 0x87, 0x43,
- 0xd4, 0xa9, 0xf2, 0xe0, 0x08, 0x13, 0xa2, 0xcc, 0x7b, 0x5a, 0x85, 0xb8,
- 0xb9, 0x36, 0x1c, 0x33, 0x85, 0xf3, 0xc8, 0x95, 0x93, 0xdc, 0x4b, 0xfe,
- 0xdc, 0x3d, 0x1f, 0xe6, 0xcf, 0x5f, 0xa7, 0xcc, 0x28, 0x3b, 0xd8, 0x18,
- 0x78, 0xcc, 0xda, 0xbf, 0xe0, 0xc9, 0xe6, 0x4e, 0xb9, 0x62, 0x8a, 0x51,
- 0xb3, 0xef, 0x68, 0x92, 0x1f, 0x79, 0xee, 0xde, 0xc2, 0x33, 0x71, 0x6c,
- 0xcf, 0xf7, 0xe1, 0x2a, 0xcf, 0x74, 0xcf, 0x9e, 0xb1, 0xd6, 0x12, 0x61,
- 0xd9, 0x2c, 0x5f, 0xe8, 0x52, 0x0a, 0x65, 0xda, 0x46, 0xab, 0xe4, 0x51,
- 0x8f, 0xd8, 0xfb, 0x10, 0x54, 0x1e, 0x57, 0x32, 0xfa, 0x20, 0x71, 0xfe,
- 0x23, 0x79, 0x1a, 0x8b, 0x2b, 0x43, 0xf2, 0x3a, 0xf7, 0xfb, 0xfa, 0xe2,
- 0x5c, 0xb3, 0x6d, 0xbf, 0xea, 0xd9, 0xf6, 0xfb, 0xce, 0xe8, 0x3e, 0x5f,
- 0xef, 0x90, 0xd7, 0x87, 0xf6, 0x08, 0xf4, 0xfc, 0x7f, 0xed, 0xa1, 0xad,
- 0x44, 0xb6, 0xec, 0x29, 0x6e, 0xb3, 0x67, 0xb7, 0xc8, 0x2f, 0xd1, 0x87,
- 0xba, 0xbd, 0x98, 0xe1, 0xfb, 0x94, 0x8f, 0x07, 0xba, 0xd1, 0xb6, 0xca,
- 0xb9, 0xed, 0x7c, 0x91, 0x38, 0x88, 0x8b, 0x7b, 0x09, 0xe3, 0xe7, 0x54,
- 0xa8, 0x43, 0xb6, 0xcd, 0xab, 0x18, 0x13, 0x78, 0x57, 0x88, 0x43, 0xcd,
- 0xf9, 0x95, 0x73, 0x26, 0xbe, 0xc7, 0xf1, 0xb4, 0x24, 0x5f, 0xa7, 0x3f,
- 0x71, 0x3f, 0xf3, 0xed, 0x4d, 0x2f, 0x7e, 0x76, 0x4c, 0x85, 0xd3, 0x51,
- 0xc4, 0x4f, 0x99, 0x2c, 0x95, 0x8f, 0xa3, 0x26, 0x92, 0xe2, 0x5d, 0x69,
- 0xda, 0x47, 0xc7, 0x18, 0x62, 0xe4, 0x64, 0xa9, 0xce, 0xba, 0x08, 0x61,
- 0x0c, 0xfb, 0x90, 0xa3, 0x23, 0x6a, 0x2e, 0x52, 0xfc, 0x58, 0x9a, 0x71,
- 0x39, 0x2e, 0xf1, 0xfa, 0x3b, 0xa8, 0x3b, 0x4c, 0xc9, 0x6a, 0x5b, 0xfb,
- 0xb3, 0x5e, 0xd2, 0x5b, 0x42, 0x0d, 0x11, 0x4e, 0x4b, 0x58, 0xa5, 0x5b,
- 0x23, 0xd3, 0xa9, 0x0e, 0xd4, 0x5a, 0x13, 0xbd, 0x6a, 0xf5, 0x60, 0x6f,
- 0x68, 0x75, 0xcf, 0x54, 0x4b, 0xba, 0xd8, 0xab, 0xe6, 0x44, 0x16, 0xcb,
- 0xa2, 0x50, 0xd7, 0xc4, 0x0e, 0x0b, 0xbe, 0x57, 0x3f, 0xfb, 0x59, 0x95,
- 0x0e, 0x41, 0xb7, 0x72, 0x6c, 0x29, 0x15, 0x66, 0x0d, 0x19, 0x9f, 0x94,
- 0x63, 0xa8, 0x1b, 0x9f, 0x91, 0xe9, 0x32, 0xe8, 0xd2, 0x7c, 0xc7, 0xc0,
- 0x6f, 0x1f, 0x70, 0x93, 0xf6, 0x28, 0x62, 0xac, 0x4b, 0x3b, 0x68, 0xce,
- 0xe4, 0x58, 0x27, 0xa5, 0x98, 0x57, 0xde, 0x81, 0xfd, 0xd0, 0x5f, 0xfe,
- 0x59, 0x96, 0xad, 0x1d, 0x92, 0x77, 0xe3, 0x03, 0xed, 0x15, 0x6b, 0x37,
- 0xbd, 0xb5, 0x6b, 0x58, 0xa3, 0xfd, 0xee, 0x6c, 0xd2, 0xe1, 0x97, 0x75,
- 0xad, 0x73, 0xd9, 0xe6, 0x3b, 0x61, 0xff, 0x76, 0xd4, 0x85, 0x7d, 0x7d,
- 0x74, 0xd9, 0xfa, 0xdc, 0x2e, 0x69, 0x37, 0xa9, 0x37, 0x9c, 0x13, 0x65,
- 0x8c, 0xc5, 0xfa, 0x15, 0x0f, 0xd7, 0x5b, 0xc0, 0xd5, 0x41, 0xba, 0x31,
- 0xc2, 0x58, 0x07, 0x7d, 0xa8, 0x79, 0xf2, 0x1b, 0xb1, 0x86, 0xb0, 0xdf,
- 0xf1, 0x70, 0x7d, 0xab, 0x09, 0x17, 0xd7, 0xf8, 0xe4, 0x99, 0x38, 0xbb,
- 0x9d, 0xbc, 0x91, 0x1f, 0xea, 0x80, 0xfa, 0x48, 0x1a, 0x93, 0x88, 0xed,
- 0x93, 0x0d, 0x5d, 0xdb, 0x19, 0xb9, 0x0a, 0x6a, 0xae, 0xc6, 0x8b, 0xa0,
- 0x11, 0xb5, 0x58, 0x63, 0xd0, 0xab, 0xb7, 0x69, 0x47, 0x6b, 0xda, 0x1e,
- 0x19, 0x77, 0x4a, 0xda, 0xae, 0x2e, 0xb9, 0x76, 0x65, 0x51, 0x37, 0x97,
- 0x64, 0x6f, 0xbd, 0xba, 0xcb, 0xfd, 0xbf, 0xdb, 0xa6, 0x84, 0xb4, 0x3e,
- 0x99, 0xdf, 0x68, 0x63, 0x77, 0x22, 0xae, 0x3b, 0xef, 0x32, 0xcf, 0x4c,
- 0x32, 0x07, 0x4d, 0x32, 0x77, 0x18, 0x5e, 0x3c, 0x8c, 0x37, 0xe1, 0x88,
- 0x03, 0xc7, 0x8a, 0x67, 0xbf, 0x73, 0x1e, 0x2e, 0xbf, 0xfe, 0xf4, 0x63,
- 0xea, 0x9f, 0xdf, 0xb5, 0x79, 0x5d, 0x99, 0xee, 0x77, 0xab, 0x8e, 0xc7,
- 0xb0, 0x75, 0xd0, 0x1f, 0x9f, 0x52, 0xb0, 0xaf, 0x5c, 0xdd, 0xd5, 0x07,
- 0x7c, 0x1f, 0xb6, 0xc7, 0x57, 0x5f, 0xb7, 0x6e, 0xfd, 0xed, 0xca, 0x80,
- 0x3a, 0xcd, 0x90, 0xef, 0x4c, 0x98, 0xb4, 0x34, 0x26, 0xb0, 0x5f, 0x8e,
- 0x30, 0x37, 0xe6, 0xc1, 0xc7, 0x61, 0x73, 0xd8, 0x9c, 0x26, 0xee, 0xa8,
- 0x00, 0x27, 0x6a, 0xc9, 0x74, 0x9b, 0xa7, 0xe7, 0x6f, 0xf3, 0x7c, 0xe0,
- 0xde, 0xc9, 0x6f, 0x3c, 0xbf, 0xed, 0xd1, 0x73, 0xa3, 0xcb, 0xa5, 0xc7,
- 0x5f, 0x1f, 0x34, 0x37, 0x7f, 0xaf, 0xf4, 0x7a, 0xf2, 0xc4, 0xfb, 0x33,
- 0x1e, 0x5d, 0xd4, 0x4d, 0x33, 0x4d, 0xd4, 0xcb, 0xbb, 0xc0, 0xa3, 0x6b,
- 0x8d, 0xa2, 0x4a, 0xa3, 0x76, 0x49, 0x31, 0x67, 0x25, 0xc6, 0x32, 0x62,
- 0x41, 0x27, 0x09, 0x7b, 0x0a, 0xbb, 0x6e, 0x96, 0xa9, 0xe7, 0x5b, 0x88,
- 0xd5, 0xd4, 0xfb, 0x7b, 0x32, 0x53, 0xee, 0xb7, 0x5b, 0x0d, 0xfa, 0x6b,
- 0x22, 0xb9, 0x22, 0xc3, 0xf6, 0x8a, 0xae, 0xa1, 0x12, 0xf1, 0x13, 0x42,
- 0xd9, 0xde, 0x92, 0x01, 0x5d, 0xdb, 0xbc, 0x27, 0x16, 0xe4, 0x32, 0x59,
- 0x81, 0x8f, 0xed, 0xfb, 0x57, 0x47, 0xd7, 0xa4, 0x08, 0x6f, 0xd7, 0xb7,
- 0xc1, 0xf5, 0xba, 0xc6, 0x43, 0x7c, 0xcd, 0xb8, 0x0c, 0x69, 0xdb, 0xe7,
- 0xe3, 0xb3, 0x64, 0xb6, 0xe1, 0xe3, 0x0c, 0x23, 0x2e, 0x23, 0x06, 0xec,
- 0xfb, 0xbc, 0x67, 0x2f, 0x7c, 0xff, 0xbe, 0xc3, 0x5a, 0x48, 0xa5, 0xbf,
- 0xea, 0xcd, 0x7d, 0x8f, 0x32, 0xc0, 0xb7, 0x2f, 0xf7, 0x17, 0xbd, 0x78,
- 0x53, 0x34, 0x32, 0x0d, 0xca, 0x80, 0xb6, 0x02, 0xfd, 0x6b, 0xfb, 0x84,
- 0xcf, 0x54, 0x3e, 0x89, 0x98, 0xd5, 0xed, 0xd6, 0x0f, 0xe8, 0xaf, 0x32,
- 0x0d, 0xce, 0xad, 0xb5, 0x65, 0xed, 0x16, 0xcf, 0x97, 0x0e, 0x62, 0x6e,
- 0x12, 0x7f, 0x94, 0x1d, 0x61, 0x0e, 0xe1, 0x3d, 0xe3, 0xc1, 0xc9, 0x58,
- 0x16, 0xb9, 0x2b, 0x73, 0x68, 0x1c, 0xdf, 0x86, 0xd7, 0x67, 0x69, 0xb9,
- 0x57, 0x51, 0xab, 0x40, 0x9e, 0x03, 0xe0, 0x27, 0x2e, 0xe3, 0x0d, 0xe8,
- 0x7c, 0x23, 0x9e, 0x6d, 0xc0, 0x14, 0x6f, 0xc3, 0xb8, 0xb1, 0x6f, 0xbc,
- 0xf1, 0xa6, 0xc3, 0x78, 0xf0, 0x57, 0xda, 0x5f, 0xe2, 0xa0, 0xdd, 0xef,
- 0xd5, 0x32, 0xc6, 0x63, 0x95, 0x09, 0xe3, 0xf1, 0x0a, 0xf7, 0xa8, 0xaf,
- 0xf5, 0x88, 0x15, 0xcf, 0x2a, 0xd4, 0xa9, 0xfb, 0xba, 0x70, 0xe6, 0x09,
- 0xd8, 0x46, 0xd1, 0x98, 0x1c, 0xda, 0x25, 0xf9, 0x64, 0x0f, 0x68, 0x7e,
- 0x08, 0xcf, 0x56, 0xcc, 0xff, 0x3c, 0xe6, 0x61, 0x47, 0x49, 0xfa, 0xc7,
- 0x0e, 0xdd, 0x5b, 0x4e, 0x99, 0xa4, 0x71, 0xc0, 0xb3, 0xad, 0x37, 0x4d,
- 0xd7, 0x96, 0x9e, 0xc6, 0xf7, 0x4e, 0xcc, 0x7f, 0x01, 0x4f, 0xe4, 0xb2,
- 0x7d, 0xfe, 0x3c, 0x7d, 0x70, 0x0c, 0xf3, 0x0f, 0x00, 0xc7, 0x1f, 0xe0,
- 0xfd, 0x5e, 0xbc, 0xff, 0xde, 0x96, 0xbd, 0xbf, 0xcb, 0xb3, 0x31, 0x9f,
- 0xdd, 0x32, 0xef, 0xc7, 0x6f, 0x9e, 0x27, 0xd2, 0xbd, 0x0a, 0xc6, 0x57,
- 0x23, 0xb2, 0x7b, 0xa5, 0x5d, 0x54, 0xcd, 0x8d, 0xe1, 0xaa, 0x66, 0x4a,
- 0xcf, 0x0a, 0xe3, 0xf7, 0x0f, 0xb0, 0xc7, 0x12, 0xb5, 0x0a, 0xa5, 0x51,
- 0xb7, 0xda, 0x47, 0x9f, 0x39, 0xba, 0x77, 0x81, 0xcf, 0xe2, 0xd1, 0xd1,
- 0x3a, 0x61, 0xf8, 0x7e, 0xec, 0xe8, 0xde, 0xfa, 0x3f, 0x00, 0x16, 0x72,
- 0xa9, 0xf8, 0xf8, 0x09, 0x7f, 0x7e, 0xcb, 0x99, 0x5a, 0xb6, 0x38, 0x93,
- 0x7e, 0xff, 0xcc, 0xd1, 0x6c, 0x95, 0x75, 0x42, 0x22, 0x26, 0xba, 0x16,
- 0x2f, 0x1e, 0x2d, 0x20, 0x3f, 0x86, 0x34, 0x2d, 0xfe, 0x3a, 0xd7, 0xa8,
- 0x87, 0xed, 0x68, 0x23, 0x5d, 0xcd, 0x78, 0x98, 0x67, 0x88, 0xe7, 0x18,
- 0xf0, 0x24, 0x81, 0x87, 0xf9, 0xc6, 0xa5, 0x37, 0xbe, 0xb0, 0x1d, 0x6d,
- 0xc4, 0xc5, 0xb3, 0x7c, 0x7c, 0x3d, 0xa2, 0x56, 0x7e, 0x48, 0x7a, 0x4d,
- 0xd6, 0xb6, 0x6e, 0xac, 0x69, 0x91, 0xfc, 0x69, 0xe6, 0xec, 0x7d, 0xde,
- 0x37, 0xca, 0x18, 0xf4, 0xdc, 0x71, 0xc5, 0x79, 0x3e, 0xb1, 0x96, 0x62,
- 0xb9, 0x82, 0xef, 0x45, 0x1f, 0x56, 0x79, 0xb0, 0x9d, 0x4d, 0x7c, 0xb7,
- 0x78, 0xb2, 0xe6, 0x99, 0x7e, 0xef, 0xd9, 0x4c, 0x0b, 0x40, 0xa1, 0x87,
- 0xee, 0x0d, 0x3d, 0xf8, 0x7c, 0x62, 0x61, 0x95, 0xb4, 0x25, 0xc1, 0xab,
- 0x4f, 0xdb, 0x47, 0xd5, 0x1f, 0xf7, 0x26, 0xf1, 0xe7, 0x9f, 0xe7, 0xcb,
- 0x80, 0x74, 0xf1, 0x09, 0x5b, 0xfe, 0x50, 0xef, 0x9c, 0x84, 0xdf, 0xf1,
- 0x1e, 0xc4, 0x71, 0x96, 0x6d, 0xca, 0xbe, 0x0d, 0x7a, 0x27, 0x2f, 0x06,
- 0x7a, 0x09, 0xc5, 0x9a, 0x2e, 0xce, 0x9e, 0xf5, 0x49, 0xb9, 0x0a, 0x5c,
- 0x19, 0xf4, 0x95, 0x6e, 0x6f, 0x34, 0x85, 0xf8, 0xb8, 0x06, 0xfb, 0xbc,
- 0x6c, 0xf1, 0x3e, 0x26, 0xcc, 0x7c, 0x27, 0xa5, 0xfa, 0xbf, 0x00, 0x86,
- 0xf5, 0xd5, 0xed, 0xbb, 0x96, 0x05, 0xc0, 0x2c, 0x62, 0xed, 0x84, 0x1b,
- 0x97, 0x19, 0xdb, 0x1d, 0x85, 0xda, 0xa3, 0x60, 0xfd, 0xb7, 0xc3, 0x3a,
- 0xeb, 0x36, 0xec, 0x76, 0x77, 0x21, 0xc8, 0x39, 0xf3, 0x89, 0xd9, 0x05,
- 0xc4, 0xf0, 0xaa, 0xa5, 0x76, 0x2b, 0x6d, 0x91, 0x89, 0x2a, 0x62, 0x12,
- 0xba, 0xde, 0x44, 0x7c, 0x41, 0xfe, 0x53, 0xeb, 0xa1, 0xc5, 0x1a, 0x36,
- 0x7b, 0xd4, 0xe7, 0x68, 0x57, 0x9a, 0xf2, 0xd0, 0x29, 0xe4, 0xe5, 0x91,
- 0xc7, 0x90, 0x73, 0x20, 0xaf, 0x53, 0x45, 0x74, 0xf2, 0xb4, 0x91, 0x37,
- 0x7e, 0xab, 0x60, 0xb9, 0x7d, 0x80, 0xce, 0x67, 0xe2, 0xf2, 0x18, 0x3a,
- 0xd5, 0xa1, 0xe3, 0x4c, 0x5e, 0xc7, 0x9b, 0x7e, 0x73, 0x52, 0xb5, 0xa3,
- 0xc6, 0x40, 0x01, 0x8a, 0x0a, 0xc7, 0x1c, 0x14, 0xd9, 0x3b, 0x87, 0xb8,
- 0x82, 0x38, 0xbc, 0x77, 0x15, 0xd1, 0xed, 0x14, 0xe1, 0x95, 0x84, 0x4f,
- 0x85, 0xa4, 0xe5, 0x14, 0xef, 0x43, 0x64, 0x0f, 0xfa, 0x31, 0xe2, 0xdc,
- 0x1b, 0xc6, 0x73, 0x1c, 0x7f, 0xfb, 0x51, 0x5b, 0x99, 0xa8, 0x91, 0xb7,
- 0x81, 0x07, 0x2c, 0xf7, 0x6c, 0x07, 0x6f, 0x76, 0x4b, 0x7b, 0x04, 0x7b,
- 0x08, 0x1f, 0x06, 0x1d, 0x7b, 0x40, 0x8f, 0x7b, 0x3e, 0x71, 0x84, 0x4f,
- 0x89, 0xf4, 0xcf, 0x49, 0x8f, 0xd2, 0x7b, 0xc2, 0x52, 0x48, 0x71, 0xad,
- 0x03, 0xf0, 0xdc, 0x87, 0x35, 0xbd, 0xcf, 0xbd, 0x57, 0xca, 0xdf, 0xa6,
- 0x1b, 0x73, 0x06, 0xde, 0x51, 0x4f, 0xa5, 0x4c, 0xe9, 0xaf, 0xb9, 0xb0,
- 0x7b, 0x57, 0xbf, 0xd4, 0xcd, 0xbb, 0x29, 0x65, 0xb9, 0xb4, 0x29, 0xd4,
- 0xc4, 0x79, 0x48, 0x35, 0x3c, 0xc8, 0xfb, 0x19, 0xc2, 0xb0, 0xaf, 0x35,
- 0x35, 0x8c, 0x39, 0x48, 0xf9, 0xb9, 0x73, 0x4a, 0xfd, 0x6f, 0xf7, 0x2e,
- 0xcd, 0x35, 0x85, 0xf6, 0x15, 0xec, 0xff, 0x43, 0xed, 0x2b, 0xa2, 0xe2,
- 0x9e, 0xaf, 0xe0, 0x7b, 0x91, 0xdf, 0x7e, 0x2e, 0xfe, 0xed, 0xbb, 0xdc,
- 0x78, 0xef, 0xc8, 0xb4, 0xcd, 0x3b, 0x0c, 0x47, 0x2e, 0xdb, 0x45, 0xe3,
- 0x91, 0x4d, 0x75, 0x66, 0x52, 0xe7, 0xe7, 0x02, 0x64, 0xbf, 0x5e, 0xd7,
- 0x3d, 0x9b, 0x5c, 0xa9, 0x47, 0xe4, 0xea, 0x52, 0xbb, 0xac, 0x2f, 0xb8,
- 0x36, 0xbf, 0xbe, 0x40, 0x3b, 0x37, 0xe5, 0xed, 0x25, 0x0b, 0x6b, 0x49,
- 0xfc, 0xf5, 0xc8, 0xf5, 0xa5, 0xcd, 0x75, 0xe7, 0x85, 0xc6, 0xc3, 0xa0,
- 0xa5, 0x47, 0x42, 0x96, 0xa3, 0xfb, 0xaf, 0x1c, 0x72, 0x5f, 0x51, 0xc6,
- 0x25, 0x5f, 0xe9, 0x47, 0x0f, 0x88, 0xe4, 0x1c, 0x66, 0x0e, 0x82, 0xfe,
- 0x2b, 0x9f, 0x40, 0x6d, 0x92, 0x80, 0xf3, 0xf4, 0xeb, 0x7b, 0xc5, 0x4f,
- 0x85, 0x7b, 0xa4, 0xd5, 0xfa, 0xa3, 0x6e, 0x37, 0x57, 0x99, 0x6e, 0x9f,
- 0x6a, 0xf9, 0xf9, 0xfa, 0x75, 0xe0, 0x1e, 0x81, 0x9d, 0xd2, 0x36, 0x6d,
- 0xd8, 0xac, 0x29, 0xcb, 0x43, 0x89, 0x6a, 0x51, 0x18, 0x1f, 0x52, 0x38,
- 0xd3, 0xc0, 0xbe, 0x24, 0xe4, 0xb1, 0x43, 0xd7, 0x42, 0x19, 0x05, 0xdd,
- 0xce, 0xcd, 0x48, 0xbe, 0xf1, 0x9b, 0x98, 0xcf, 0xc8, 0x54, 0x63, 0x0c,
- 0x67, 0x9d, 0xa4, 0xdd, 0xf6, 0x48, 0x3b, 0xcf, 0x49, 0x81, 0xc6, 0x87,
- 0xa4, 0x70, 0x7a, 0x46, 0x0e, 0x57, 0x48, 0x27, 0xef, 0x19, 0x13, 0xc9,
- 0x9c, 0x0c, 0xc7, 0x97, 0x50, 0x3b, 0xb9, 0xfe, 0x98, 0x96, 0xc2, 0x19,
- 0xe0, 0xa8, 0xf0, 0x1e, 0xa0, 0x1f, 0x76, 0x33, 0xac, 0xfb, 0x9a, 0x29,
- 0x1d, 0x77, 0x38, 0xff, 0x43, 0xe8, 0xa9, 0xbf, 0xb8, 0x1f, 0x70, 0x79,
- 0xf4, 0x40, 0x93, 0xa8, 0x97, 0x17, 0x2b, 0xe8, 0xf7, 0xec, 0x10, 0x6b,
- 0x2f, 0xa5, 0xee, 0xef, 0x93, 0x5a, 0x65, 0xd8, 0x54, 0x8a, 0x35, 0x15,
- 0x75, 0xc1, 0x35, 0xfa, 0x77, 0x4c, 0x85, 0xad, 0x3e, 0x59, 0xaa, 0x14,
- 0xd1, 0x37, 0x2b, 0xef, 0x5e, 0x03, 0x16, 0x60, 0xb9, 0x71, 0x2f, 0xa3,
- 0xc8, 0x37, 0xea, 0xcf, 0xc6, 0x27, 0x41, 0x63, 0x26, 0x6e, 0xca, 0x71,
- 0xd0, 0x87, 0xf7, 0x45, 0xd8, 0xf8, 0x1c, 0x6b, 0xb8, 0x0c, 0xd6, 0xd2,
- 0x72, 0xe4, 0xec, 0x24, 0x68, 0xe8, 0x92, 0xfe, 0x3f, 0xa1, 0x8f, 0x3d,
- 0x81, 0x39, 0x7e, 0x27, 0x60, 0xaf, 0x5f, 0xc4, 0x3b, 0x61, 0x63, 0x78,
- 0x52, 0x0e, 0x7d, 0x78, 0x9a, 0xa0, 0x25, 0xe2, 0xf6, 0x26, 0x87, 0xe2,
- 0x52, 0x3b, 0xfd, 0xa0, 0x4c, 0x2d, 0x3e, 0x08, 0xfc, 0x3f, 0x42, 0x5f,
- 0x80, 0xfc, 0xb6, 0xc8, 0xb3, 0x58, 0xff, 0xf1, 0x9c, 0x9d, 0x3d, 0xda,
- 0x37, 0xe6, 0x38, 0xcf, 0xe7, 0x41, 0xec, 0x47, 0x8f, 0x51, 0xc9, 0x48,
- 0xa1, 0xc2, 0xb3, 0xa0, 0x3b, 0xd4, 0x53, 0xf9, 0xd3, 0x93, 0x9e, 0x8e,
- 0x7b, 0x24, 0x17, 0x2d, 0xb2, 0xbf, 0x40, 0x9e, 0x58, 0x18, 0xcd, 0x96,
- 0x13, 0x66, 0x56, 0x11, 0x57, 0x52, 0x98, 0x1b, 0xdc, 0xb9, 0x88, 0x58,
- 0x73, 0xe8, 0x6d, 0xd3, 0x5c, 0x3b, 0xee, 0xdd, 0x1d, 0x10, 0xd7, 0x9b,
- 0x32, 0x0e, 0x1b, 0xeb, 0x9f, 0x1b, 0x41, 0x2d, 0xfc, 0x16, 0x6a, 0xc9,
- 0x84, 0x27, 0x83, 0x31, 0xcf, 0x36, 0xda, 0x9b, 0x6c, 0x02, 0x7a, 0xae,
- 0x40, 0xf7, 0x15, 0xd8, 0x01, 0x62, 0xf5, 0x2b, 0x1b, 0xf6, 0x31, 0xd6,
- 0x54, 0x63, 0x76, 0xca, 0xdf, 0x54, 0x13, 0xc9, 0x35, 0xd8, 0xcf, 0x75,
- 0xf4, 0x02, 0x6b, 0xe8, 0x55, 0xd7, 0xd1, 0xd7, 0x2d, 0x96, 0x0f, 0x81,
- 0x7e, 0xd6, 0x94, 0xfc, 0x8e, 0xe9, 0x5a, 0xa7, 0xcd, 0x7a, 0xe1, 0x2e,
- 0x7d, 0xb7, 0x2b, 0x4f, 0xf4, 0xb0, 0xd7, 0x64, 0x5f, 0xce, 0x7b, 0xe9,
- 0xab, 0xd0, 0xe3, 0x9a, 0xc9, 0x75, 0x7f, 0x1f, 0x7b, 0x01, 0xdf, 0x7e,
- 0x48, 0x0b, 0xed, 0x87, 0x7b, 0x08, 0xd3, 0xa3, 0xfd, 0x24, 0xaf, 0xf1,
- 0xd1, 0x66, 0xeb, 0xdd, 0xae, 0x9f, 0xe9, 0x3a, 0xcb, 0xbc, 0x22, 0xbe,
- 0xfd, 0xbe, 0xe7, 0xb0, 0xaf, 0xcb, 0x0e, 0x21, 0x76, 0x37, 0x1c, 0x79,
- 0xc1, 0xde, 0xec, 0x77, 0x07, 0x2a, 0xbe, 0x9c, 0x28, 0xc7, 0x43, 0x72,
- 0xa2, 0x91, 0x80, 0x4f, 0x50, 0x86, 0x56, 0x93, 0x0c, 0x45, 0xbe, 0x5e,
- 0x11, 0x79, 0xb9, 0xc2, 0x35, 0x2d, 0xc3, 0x58, 0x36, 0xd4, 0xce, 0xbb,
- 0x75, 0xd8, 0xe5, 0xdf, 0xcb, 0xe1, 0x79, 0x91, 0xb3, 0x58, 0x5f, 0xae,
- 0xd0, 0x57, 0x47, 0x50, 0xbf, 0xee, 0x94, 0xda, 0x02, 0x7a, 0xb2, 0x8a,
- 0x4c, 0x65, 0x1f, 0x60, 0xbe, 0x89, 0xc8, 0xba, 0xbe, 0x93, 0x15, 0x19,
- 0x3c, 0x17, 0x96, 0xf0, 0x39, 0x34, 0x7f, 0x90, 0xfd, 0xf9, 0x21, 0xff,
- 0x8e, 0xd6, 0xf5, 0xf9, 0x52, 0x19, 0x7b, 0x2b, 0xfd, 0x3a, 0x4e, 0x96,
- 0xea, 0x05, 0xc9, 0x57, 0x79, 0x16, 0x9e, 0x0b, 0x71, 0xac, 0xa5, 0x64,
- 0xfa, 0xf4, 0x88, 0x3c, 0x8b, 0x33, 0xd0, 0xff, 0xe1, 0x8c, 0x71, 0x29,
- 0x9e, 0xc5, 0x7c, 0xfd, 0x9a, 0x2c, 0x2c, 0x15, 0xa4, 0x56, 0xbd, 0xd0,
- 0x74, 0xf7, 0x8e, 0xef, 0x85, 0xe6, 0x5e, 0xf6, 0x10, 0xfb, 0x19, 0xf4,
- 0xaa, 0x16, 0xbe, 0x21, 0xb3, 0xfa, 0xf4, 0xd4, 0xe6, 0x3b, 0xe3, 0xe6,
- 0x1e, 0x76, 0x42, 0x66, 0x2b, 0x29, 0x29, 0x9d, 0x1e, 0xd1, 0x77, 0x0d,
- 0x6d, 0xe9, 0xea, 0xd3, 0x37, 0x90, 0x2b, 0x26, 0xf4, 0x9d, 0xf1, 0x2d,
- 0x79, 0xd4, 0x9e, 0x95, 0x27, 0xad, 0x83, 0x72, 0x02, 0xf5, 0xf5, 0xa7,
- 0xd1, 0xeb, 0xc7, 0xbb, 0xa9, 0x47, 0xd0, 0x6b, 0xb1, 0x07, 0x75, 0x64,
- 0xdc, 0xfe, 0xb8, 0xf9, 0x3c, 0x24, 0x7b, 0xb5, 0xce, 0x3c, 0xf9, 0x5f,
- 0x4e, 0x06, 0x79, 0xef, 0x06, 0x7a, 0xc7, 0x8c, 0x86, 0x33, 0x5c, 0xb8,
- 0x2a, 0xe1, 0x86, 0xcd, 0x17, 0x08, 0xb7, 0x60, 0x78, 0x70, 0x06, 0xe0,
- 0x42, 0x72, 0xd1, 0x0e, 0xc3, 0x46, 0x26, 0xc0, 0x27, 0x62, 0xfc, 0x68,
- 0xa7, 0x57, 0x07, 0xef, 0x40, 0x6e, 0xbd, 0xbd, 0xff, 0x35, 0x6f, 0xff,
- 0xb3, 0xde, 0xfe, 0xcb, 0x1b, 0xfb, 0xfd, 0xfc, 0xfa, 0x13, 0x47, 0x9a,
- 0xe8, 0x7a, 0xad, 0xec, 0xc2, 0xcf, 0x7a, 0x74, 0x5d, 0xde, 0xa0, 0xcb,
- 0x87, 0x87, 0x3c, 0x35, 0xcf, 0x8c, 0xcd, 0x8c, 0xd1, 0xfd, 0x90, 0xa3,
- 0x23, 0x39, 0x1b, 0xbe, 0x51, 0x49, 0x8c, 0x15, 0xf5, 0x9d, 0x9a, 0x92,
- 0xb5, 0xe8, 0xac, 0x4c, 0x58, 0x89, 0xb1, 0x69, 0x09, 0xc1, 0x96, 0x19,
- 0x5b, 0x42, 0x52, 0x63, 0xcc, 0xc1, 0x33, 0x6f, 0x6f, 0x4f, 0xeb, 0xd5,
- 0x26, 0x5a, 0x43, 0x2f, 0x91, 0x46, 0x97, 0xd6, 0xc8, 0xc0, 0x6d, 0x5a,
- 0x5d, 0x78, 0x97, 0xd6, 0xab, 0xe5, 0x26, 0xf8, 0x73, 0x61, 0x0f, 0x3e,
- 0xdc, 0x04, 0x4f, 0x7b, 0x66, 0x5d, 0x41, 0x7b, 0x26, 0x6d, 0x3f, 0x0b,
- 0xdf, 0x90, 0xc8, 0x8e, 0x74, 0xf5, 0xe8, 0x7d, 0x03, 0x8e, 0x44, 0x50,
- 0x6f, 0xb4, 0x62, 0x6d, 0xbd, 0xca, 0x5a, 0x44, 0xed, 0x6d, 0x95, 0x41,
- 0xd8, 0x2c, 0x75, 0xe7, 0xde, 0x0d, 0x3e, 0xaa, 0x6b, 0x02, 0x47, 0x9e,
- 0xb4, 0x49, 0xcb, 0x8f, 0x9d, 0x97, 0xa3, 0x83, 0x76, 0x49, 0x86, 0xcc,
- 0x56, 0x9c, 0x5f, 0x6b, 0x68, 0x9c, 0x49, 0xd2, 0xb2, 0x32, 0xd4, 0x6f,
- 0x7e, 0x0f, 0x7c, 0x8e, 0x57, 0x0d, 0xa9, 0x59, 0x89, 0xd8, 0x79, 0xe0,
- 0xd8, 0x0f, 0xdd, 0xd4, 0x46, 0x48, 0x8f, 0xc8, 0x61, 0xd8, 0x77, 0x4d,
- 0xe7, 0x45, 0xda, 0x71, 0x62, 0xa2, 0x88, 0x5a, 0xe7, 0x2f, 0x75, 0x6e,
- 0x73, 0x9c, 0x1b, 0xc8, 0x6f, 0x13, 0x5b, 0x6c, 0x4f, 0x9d, 0x73, 0x6d,
- 0x4f, 0x9d, 0x43, 0x0f, 0x7c, 0x32, 0x22, 0x6d, 0xcb, 0xf0, 0x9f, 0x97,
- 0xf6, 0xb8, 0xf5, 0xdc, 0x4b, 0xfc, 0xdd, 0x09, 0xf1, 0xee, 0x64, 0x58,
- 0xac, 0x93, 0x3a, 0x1f, 0x40, 0xde, 0xe3, 0x32, 0x7d, 0x86, 0x31, 0xd5,
- 0x92, 0x81, 0x93, 0xd4, 0x07, 0xeb, 0x9a, 0x85, 0xd1, 0x02, 0x7c, 0x64,
- 0x06, 0x71, 0x41, 0x2d, 0xdf, 0x94, 0x82, 0x45, 0x39, 0x74, 0x49, 0xfb,
- 0x32, 0xfa, 0xf1, 0x65, 0xc4, 0x86, 0xe5, 0x98, 0xb4, 0xc0, 0xb7, 0xd4,
- 0xb9, 0xa8, 0x51, 0x9a, 0x7f, 0x17, 0xfe, 0xc0, 0xdf, 0x70, 0x50, 0x5b,
- 0x9e, 0x8b, 0x19, 0xf4, 0x2d, 0x75, 0x8e, 0x76, 0x8e, 0x72, 0xea, 0x1c,
- 0xed, 0x9c, 0x74, 0xf8, 0xfe, 0x82, 0xf7, 0x73, 0x23, 0xfa, 0x9e, 0xfa,
- 0x86, 0x4d, 0x5e, 0x7e, 0x20, 0xd9, 0x2a, 0x6b, 0x44, 0xf2, 0x23, 0xdd,
- 0xa8, 0x65, 0x76, 0x65, 0xed, 0x81, 0xb1, 0x75, 0xf9, 0xa8, 0x7c, 0xdd,
- 0xf9, 0x11, 0xf8, 0x22, 0x1f, 0xcd, 0x7c, 0x91, 0xa7, 0x2e, 0x69, 0xd1,
- 0x7c, 0xf9, 0xfc, 0x40, 0xd0, 0xe0, 0x67, 0xef, 0xc9, 0x18, 0xf0, 0x7f,
- 0x11, 0x31, 0xa0, 0x0f, 0xcf, 0x27, 0xf0, 0x44, 0x4a, 0x3b, 0x47, 0xde,
- 0xc9, 0xeb, 0x75, 0xd4, 0x8d, 0x3e, 0x9f, 0x53, 0x78, 0x7f, 0x55, 0xa6,
- 0xe7, 0x9d, 0xe3, 0xc8, 0xab, 0xbc, 0x43, 0xef, 0x71, 0xef, 0x83, 0xb7,
- 0xf2, 0xfe, 0xaa, 0xb8, 0xf2, 0x49, 0x98, 0x35, 0xc1, 0xfb, 0xd2, 0x56,
- 0x59, 0x34, 0xc7, 0x8e, 0x98, 0xae, 0xc3, 0x0f, 0xd7, 0x19, 0x27, 0x28,
- 0xa3, 0xeb, 0x92, 0x9d, 0xe7, 0xfd, 0x97, 0x8b, 0x6f, 0xaa, 0xee, 0xc7,
- 0x8d, 0xe6, 0x3d, 0x36, 0xe0, 0xfa, 0x00, 0x47, 0xba, 0xd6, 0x28, 0x3f,
- 0xc4, 0x9c, 0xde, 0xa6, 0x58, 0xd3, 0xbc, 0x6f, 0x4c, 0x9e, 0x43, 0x1d,
- 0xf0, 0x9a, 0xbd, 0x49, 0xae, 0x53, 0xac, 0x85, 0x6a, 0xf5, 0x49, 0xf8,
- 0x64, 0x0b, 0x62, 0x99, 0x29, 0xeb, 0xe5, 0x56, 0xa9, 0xa1, 0xde, 0x59,
- 0x5c, 0x62, 0x2c, 0x24, 0xed, 0xed, 0x98, 0x77, 0xe3, 0x17, 0x63, 0xed,
- 0x7a, 0x19, 0x79, 0x16, 0xbe, 0xbd, 0x5e, 0x8e, 0xe2, 0xd9, 0x87, 0xa7,
- 0x85, 0x67, 0x1c, 0xcf, 0x24, 0x9e, 0x23, 0x78, 0x8e, 0xe0, 0x69, 0x61,
- 0x6f, 0x0c, 0x4f, 0xbf, 0x67, 0x20, 0xae, 0xdb, 0x7c, 0x97, 0xf4, 0x79,
- 0xa8, 0x15, 0x2d, 0xe6, 0xb4, 0xb0, 0x9d, 0x43, 0x1f, 0x91, 0x1d, 0x61,
- 0xad, 0xc7, 0x9a, 0xef, 0x03, 0xc7, 0xb4, 0xd8, 0x97, 0x17, 0x8d, 0xfd,
- 0x43, 0xcc, 0x0b, 0x55, 0xe4, 0x85, 0xf7, 0x76, 0xa3, 0x7f, 0x34, 0x0f,
- 0xe8, 0xbb, 0xa3, 0x79, 0x7c, 0xf3, 0x1d, 0x3d, 0x6f, 0x74, 0x06, 0x79,
- 0x8a, 0xf1, 0xd3, 0xc1, 0x9e, 0x3c, 0xe2, 0xf8, 0x2e, 0xf8, 0x5f, 0x06,
- 0x71, 0x1b, 0xef, 0x0b, 0x97, 0x76, 0xbb, 0x39, 0x15, 0xf9, 0x56, 0x6d,
- 0xbd, 0xaf, 0xb1, 0xb1, 0x67, 0xbb, 0xde, 0xa0, 0x13, 0x38, 0x12, 0xd5,
- 0x05, 0xf8, 0xe0, 0xf7, 0xed, 0xe3, 0xba, 0xb6, 0xa3, 0x2e, 0x9e, 0x45,
- 0x8d, 0x9a, 0x9b, 0x63, 0x0d, 0x73, 0x0c, 0x7d, 0x09, 0xfa, 0xb3, 0x28,
- 0x7b, 0x72, 0xe6, 0x02, 0x5d, 0x8b, 0x46, 0xa5, 0x9d, 0x79, 0xe0, 0x06,
- 0xce, 0x03, 0x5f, 0x8b, 0x0e, 0x64, 0xf6, 0x08, 0x6a, 0x42, 0xc7, 0x09,
- 0x5b, 0xfb, 0x25, 0xfe, 0x38, 0x63, 0x8e, 0x60, 0xbf, 0x29, 0xee, 0xbd,
- 0x3a, 0xe2, 0xee, 0xa4, 0xfe, 0xbd, 0x18, 0xc6, 0x65, 0x63, 0xef, 0x1d,
- 0xc0, 0xc5, 0x79, 0xde, 0x69, 0x8b, 0xec, 0x9f, 0x73, 0x6b, 0x5a, 0x65,
- 0x35, 0xe3, 0xfb, 0x39, 0x0f, 0x1f, 0xd7, 0x95, 0xf7, 0xdb, 0xc6, 0x1e,
- 0xc8, 0x08, 0xfe, 0x00, 0x1d, 0x9f, 0x40, 0xfd, 0x7c, 0x11, 0x7a, 0x79,
- 0x0d, 0x3a, 0xb9, 0x54, 0xa6, 0xad, 0x0f, 0xc3, 0xee, 0x21, 0xc3, 0x49,
- 0xe2, 0x1a, 0xd1, 0x67, 0x5f, 0x2c, 0x23, 0x76, 0x32, 0xfe, 0xa9, 0x5f,
- 0x8d, 0xb2, 0x3e, 0x64, 0x1e, 0x74, 0xf1, 0xf4, 0xb9, 0x70, 0xe2, 0xaf,
- 0xed, 0xd6, 0xf4, 0xd4, 0xf4, 0x3d, 0x18, 0xe5, 0x04, 0x1b, 0xe4, 0x6f,
- 0x04, 0x1a, 0xe6, 0x0b, 0x51, 0x7d, 0x0f, 0xaf, 0x38, 0x47, 0x3e, 0x46,
- 0x24, 0x3b, 0xe7, 0xef, 0xeb, 0xc6, 0xbe, 0x1d, 0x4d, 0xb8, 0xee, 0xdc,
- 0xc2, 0x83, 0xf2, 0x78, 0xe0, 0xfa, 0xd6, 0xba, 0x3f, 0x61, 0x16, 0x37,
- 0xee, 0x86, 0x99, 0x7f, 0xa9, 0x9b, 0x14, 0xf6, 0xfb, 0xfa, 0xe9, 0xf3,
- 0x7a, 0x81, 0xc4, 0x6c, 0x51, 0x58, 0xab, 0x50, 0x47, 0x63, 0xf0, 0x6b,
- 0x13, 0xf8, 0x6d, 0xa9, 0x96, 0xdb, 0x44, 0xf5, 0xb0, 0x37, 0x66, 0xad,
- 0xdc, 0x7c, 0xe6, 0xaf, 0x78, 0x67, 0xa2, 0x9f, 0x3e, 0xc5, 0xba, 0x59,
- 0xe7, 0x19, 0xc0, 0x74, 0x6c, 0xa1, 0xed, 0x17, 0x3d, 0x38, 0xae, 0x27,
- 0xa5, 0x88, 0x3a, 0x34, 0x37, 0x87, 0x8a, 0x1e, 0xf1, 0x5b, 0xa5, 0xf9,
- 0xbb, 0x16, 0xef, 0xf0, 0x86, 0xe3, 0xd3, 0xa0, 0xb1, 0x68, 0x66, 0x78,
- 0x6f, 0x06, 0x1c, 0xbd, 0x5b, 0x70, 0x8c, 0x7b, 0x38, 0xc6, 0xa5, 0x74,
- 0x66, 0x02, 0xbe, 0x96, 0x41, 0x7e, 0xef, 0x37, 0x1f, 0x91, 0x4f, 0xa0,
- 0xb9, 0xc6, 0xdc, 0xd9, 0x11, 0xe8, 0xc9, 0x71, 0xf6, 0xdb, 0x87, 0x40,
- 0xf7, 0x77, 0x90, 0x5b, 0xfd, 0x9a, 0xa7, 0x14, 0x0b, 0x21, 0x87, 0x1d,
- 0xd1, 0xbf, 0xc3, 0x16, 0x4d, 0x13, 0xf6, 0xaa, 0x8c, 0xe1, 0x24, 0xda,
- 0x7b, 0xe4, 0xb7, 0x59, 0xe4, 0x2a, 0xf2, 0xd9, 0x29, 0x25, 0xd3, 0x78,
- 0x38, 0x84, 0xba, 0x26, 0x3b, 0x47, 0x3f, 0x92, 0x81, 0x50, 0xba, 0x15,
- 0x35, 0xa9, 0x23, 0x6f, 0xdb, 0xfc, 0x77, 0x0a, 0xb3, 0x72, 0xb1, 0x6e,
- 0xe2, 0xf9, 0x5d, 0xe8, 0xe1, 0x4f, 0xf1, 0xfe, 0x76, 0x0f, 0xea, 0x3e,
- 0xac, 0x64, 0x60, 0xbb, 0x49, 0x5d, 0xcf, 0xb0, 0x8e, 0xa8, 0x21, 0xdf,
- 0x2a, 0xe4, 0x1a, 0xd4, 0x55, 0x63, 0xac, 0x5d, 0x9f, 0x5b, 0xbc, 0x26,
- 0x97, 0xe6, 0xf9, 0x3b, 0x28, 0xf3, 0xf2, 0x41, 0xc6, 0x03, 0x73, 0x26,
- 0x85, 0xb9, 0x25, 0xc6, 0x32, 0x7c, 0x37, 0xe0, 0x40, 0x3d, 0xa8, 0x11,
- 0x50, 0x6b, 0xaf, 0x5b, 0x49, 0xf0, 0x79, 0x4d, 0x2e, 0xce, 0x87, 0x65,
- 0xd1, 0x62, 0x5d, 0x24, 0xf1, 0x2c, 0x60, 0x2f, 0x2e, 0xfd, 0x93, 0x6b,
- 0x13, 0x84, 0x47, 0xcf, 0x53, 0x44, 0x5d, 0xf7, 0x88, 0xde, 0xfb, 0xd3,
- 0xf4, 0x4c, 0x9a, 0x9a, 0xfb, 0xbc, 0x82, 0x5c, 0xa4, 0x3f, 0xe9, 0xdf,
- 0x28, 0x58, 0x1b, 0x1c, 0x83, 0xcd, 0xb2, 0x76, 0x67, 0x3f, 0x80, 0xf7,
- 0x3a, 0xd7, 0xc9, 0x3b, 0x9e, 0x0b, 0xfd, 0x90, 0x0d, 0xfd, 0x9e, 0x77,
- 0x62, 0xc8, 0xa3, 0x8a, 0xbe, 0x5e, 0xd2, 0xb1, 0xa0, 0x54, 0x29, 0x20,
- 0xa7, 0x20, 0x06, 0xd8, 0xbd, 0xb0, 0xc5, 0x49, 0xe8, 0x72, 0x0c, 0x70,
- 0x5b, 0x72, 0xc9, 0x6a, 0x49, 0xd7, 0x65, 0x6a, 0xe5, 0xf6, 0xfd, 0x4d,
- 0x1e, 0xfe, 0xa3, 0x56, 0x61, 0x5b, 0xf0, 0x21, 0xb5, 0x1a, 0xc5, 0x13,
- 0xf1, 0x78, 0x15, 0xfd, 0x45, 0x99, 0xf7, 0x43, 0xe8, 0x0d, 0xca, 0xbc,
- 0x3b, 0x49, 0xe2, 0x39, 0xc2, 0xfb, 0x22, 0x2f, 0xae, 0x11, 0x3f, 0xe9,
- 0xf0, 0xe3, 0x0b, 0x6b, 0x49, 0xc6, 0x17, 0xbf, 0x9e, 0x74, 0x6d, 0xe1,
- 0x44, 0x85, 0x31, 0x84, 0x76, 0xdd, 0x8f, 0xb8, 0x45, 0x5b, 0x70, 0x6b,
- 0xc9, 0xa5, 0xaa, 0x2b, 0xb3, 0xe9, 0xc6, 0x05, 0x9d, 0x23, 0x0e, 0x88,
- 0x05, 0x1b, 0xa3, 0xec, 0xb0, 0xa6, 0x73, 0xc0, 0x79, 0xc9, 0xe8, 0x27,
- 0x65, 0xf6, 0xaa, 0x64, 0x96, 0x46, 0xe4, 0x05, 0x1d, 0xb7, 0xfc, 0x98,
- 0xc5, 0x1a, 0x92, 0xbf, 0x1f, 0x27, 0xe5, 0xf9, 0xd3, 0xd7, 0x24, 0xfb,
- 0x22, 0xe3, 0xd6, 0x70, 0x6c, 0x87, 0xc1, 0x58, 0xe5, 0x48, 0x1d, 0xb9,
- 0xe9, 0x11, 0x9b, 0xff, 0x16, 0x20, 0x84, 0x9e, 0xce, 0x91, 0xd6, 0xd1,
- 0x84, 0x1d, 0x37, 0xfa, 0x9f, 0xd8, 0x61, 0x30, 0x37, 0x0e, 0x9b, 0x4f,
- 0x89, 0x7f, 0x1f, 0xd5, 0x26, 0x4f, 0xe9, 0xbb, 0x0a, 0xb8, 0xed, 0xdc,
- 0xfb, 0xfa, 0x77, 0x94, 0x1b, 0x29, 0xca, 0x1a, 0xdf, 0xab, 0x9c, 0x2f,
- 0x46, 0x6e, 0xa4, 0x5a, 0xa4, 0x74, 0x87, 0xe3, 0x3c, 0x39, 0xfa, 0xc0,
- 0x6e, 0xf7, 0xdf, 0x8b, 0x3c, 0x7d, 0x87, 0x1b, 0x0b, 0x7e, 0xcd, 0xfb,
- 0xfe, 0x3a, 0x9e, 0xb4, 0x6d, 0xe6, 0x5b, 0xe6, 0x47, 0xea, 0x0d, 0xcf,
- 0x25, 0xbe, 0x33, 0xf7, 0xce, 0x22, 0xf7, 0x32, 0x5f, 0xee, 0x92, 0x1c,
- 0x7f, 0xe7, 0x53, 0x7a, 0xbe, 0xe8, 0xd6, 0xd2, 0x1e, 0x5c, 0x75, 0x4a,
- 0xa6, 0xab, 0xac, 0xa1, 0x2e, 0x22, 0x97, 0x0d, 0xc1, 0x56, 0x99, 0xd3,
- 0x8e, 0x23, 0x9f, 0xf3, 0xf7, 0x69, 0xac, 0x2d, 0x70, 0x5f, 0x22, 0x19,
- 0x57, 0xcd, 0xbf, 0x2b, 0xdd, 0x8c, 0xf2, 0x3e, 0xea, 0xfc, 0x10, 0xf4,
- 0xfe, 0x15, 0xf6, 0x16, 0x03, 0xda, 0x46, 0xb2, 0x2f, 0x51, 0xf6, 0xee,
- 0xef, 0xd7, 0xd2, 0xed, 0xfa, 0x00, 0xeb, 0x80, 0xcf, 0x40, 0x2e, 0x07,
- 0xec, 0x6b, 0xcc, 0xdd, 0xff, 0xa6, 0xac, 0xe1, 0xe4, 0x53, 0x06, 0x7d,
- 0x1b, 0xdf, 0x4b, 0x21, 0x59, 0x88, 0x92, 0x7f, 0xc8, 0xcb, 0xa0, 0xef,
- 0x6c, 0x27, 0x87, 0xad, 0x32, 0xf8, 0x0b, 0xc8, 0x80, 0xb2, 0xf4, 0x65,
- 0xc0, 0xf7, 0x09, 0xe8, 0x8b, 0x3d, 0x43, 0xbf, 0xee, 0x23, 0x4b, 0x0d,
- 0xf7, 0xec, 0x52, 0xa5, 0x99, 0x66, 0xd2, 0x4b, 0x9d, 0x9e, 0x97, 0x9c,
- 0xd6, 0xef, 0xac, 0xe4, 0xaa, 0xe7, 0x65, 0x7f, 0x75, 0x56, 0x1e, 0xb5,
- 0x1e, 0x06, 0xbf, 0x57, 0x9c, 0x82, 0xa5, 0x7b, 0x95, 0xb1, 0x3c, 0xce,
- 0x2e, 0x8c, 0xf4, 0xca, 0x4d, 0xd4, 0x1d, 0xcf, 0x2e, 0x9a, 0xf2, 0x3f,
- 0x9d, 0x5b, 0x5f, 0x6c, 0x5b, 0xd5, 0x19, 0xff, 0x7c, 0x6d, 0x27, 0x69,
- 0x68, 0xc2, 0xad, 0xeb, 0x24, 0x6e, 0x9a, 0x51, 0x3b, 0xbe, 0x6d, 0x23,
- 0x92, 0xa2, 0xdb, 0x10, 0x68, 0xd4, 0x65, 0x8a, 0x71, 0x42, 0x17, 0xb6,
- 0x22, 0xd2, 0xae, 0xab, 0x2a, 0x8d, 0x81, 0xe5, 0xa6, 0x7f, 0xd8, 0xc3,
- 0x0a, 0x85, 0x75, 0x08, 0x21, 0xd5, 0xb8, 0xe9, 0xd6, 0x69, 0x21, 0x4e,
- 0xff, 0x2d, 0x8c, 0x87, 0xcd, 0x4a, 0xd2, 0x96, 0x4d, 0x11, 0x2e, 0x88,
- 0xb2, 0x3d, 0x6c, 0xa3, 0x4a, 0x01, 0xed, 0x79, 0x7b, 0x99, 0x34, 0x36,
- 0x65, 0x05, 0x36, 0x5e, 0x36, 0xf5, 0x81, 0x07, 0xa6, 0xd1, 0x79, 0xbf,
- 0xdf, 0x77, 0xee, 0x75, 0x6c, 0x13, 0x84, 0xb4, 0x48, 0x91, 0xef, 0x39,
- 0xf7, 0xdc, 0x73, 0xce, 0x3d, 0xdf, 0xff, 0xef, 0xfb, 0xdd, 0x8c, 0x3d,
- 0x28, 0x3f, 0xd2, 0x5c, 0x3e, 0xe3, 0x93, 0x00, 0x7c, 0x52, 0x83, 0x2d,
- 0x90, 0x36, 0x27, 0x76, 0x53, 0xe8, 0x53, 0x86, 0x41, 0xeb, 0xb8, 0xf1,
- 0x9b, 0x6d, 0x73, 0x7f, 0xcb, 0x59, 0xf8, 0xee, 0xee, 0x7d, 0x6d, 0x7e,
- 0xce, 0xd7, 0xf8, 0xb7, 0x7f, 0xf2, 0x6a, 0x68, 0x83, 0x32, 0x83, 0xfd,
- 0xbc, 0xa1, 0x7a, 0xd6, 0x01, 0x2f, 0x31, 0x37, 0x1d, 0xd3, 0xfc, 0x43,
- 0x78, 0x9a, 0x3a, 0xea, 0x2a, 0x74, 0xd4, 0x10, 0x75, 0xd7, 0xf0, 0xbc,
- 0xcb, 0xfc, 0x40, 0x54, 0xfe, 0x38, 0x45, 0x3d, 0x1c, 0x97, 0x3f, 0x4c,
- 0x3d, 0x8b, 0xfd, 0x24, 0x8a, 0xcc, 0x51, 0xde, 0x98, 0xc9, 0xd1, 0x4f,
- 0x52, 0x7f, 0x3e, 0xed, 0x3e, 0xad, 0x76, 0x20, 0x6e, 0xe5, 0xd7, 0x87,
- 0x55, 0xdf, 0x1c, 0xd3, 0xda, 0x6e, 0xdc, 0xea, 0x92, 0x1b, 0x17, 0x8c,
- 0x8e, 0x0d, 0x4f, 0x47, 0x03, 0x23, 0x0b, 0xb4, 0x4b, 0xc9, 0x58, 0xd6,
- 0x6a, 0x94, 0x43, 0x51, 0xe6, 0x9e, 0x53, 0xd4, 0xcf, 0xb0, 0x85, 0xbd,
- 0x76, 0xd6, 0x6a, 0xf2, 0xec, 0x4f, 0xac, 0x4e, 0xcf, 0x1e, 0xf3, 0xf4,
- 0x2c, 0xef, 0xa5, 0x68, 0x03, 0x20, 0x93, 0x89, 0x99, 0x51, 0x2b, 0x09,
- 0x9b, 0x87, 0xeb, 0x45, 0xce, 0x1f, 0x97, 0xe3, 0x8b, 0x47, 0xe1, 0x7f,
- 0xf7, 0xda, 0x7b, 0x69, 0x57, 0xed, 0x21, 0xe2, 0x71, 0xb0, 0xfe, 0x97,
- 0xea, 0xe6, 0x7a, 0xd4, 0x9b, 0x8b, 0xf7, 0x21, 0xe7, 0xd3, 0xac, 0xd7,
- 0x36, 0x32, 0x9f, 0xa3, 0x7b, 0xad, 0x1d, 0xbb, 0xa7, 0xb2, 0xee, 0x64,
- 0xc1, 0xf1, 0xb0, 0x61, 0xf8, 0x85, 0x2f, 0xf4, 0x8d, 0x08, 0xd7, 0xe4,
- 0x7a, 0xad, 0x92, 0xde, 0x0f, 0xfd, 0x32, 0xcd, 0xff, 0x9c, 0x57, 0xbb,
- 0x42, 0xbc, 0x12, 0xed, 0x5c, 0xc5, 0x36, 0x7d, 0xc5, 0x9b, 0xaf, 0xbf,
- 0x5d, 0x9a, 0xa3, 0x55, 0xe3, 0x99, 0x5b, 0x61, 0x3b, 0x2e, 0xb9, 0x45,
- 0xfe, 0x96, 0xcb, 0x11, 0xa7, 0x41, 0xf6, 0xda, 0x1b, 0xeb, 0xe6, 0xd8,
- 0x86, 0x3e, 0xe3, 0x13, 0x04, 0xa7, 0x03, 0x9e, 0x6f, 0xb1, 0x89, 0x7e,
- 0x93, 0x77, 0xdd, 0xa4, 0x39, 0x99, 0xb8, 0xd5, 0x59, 0xf7, 0x1e, 0x9b,
- 0x2a, 0x76, 0x38, 0x6e, 0x51, 0x77, 0x36, 0x46, 0xa5, 0x95, 0x3c, 0x54,
- 0x56, 0x3f, 0x3e, 0xe4, 0x18, 0xcc, 0x45, 0xd4, 0x39, 0xd2, 0xce, 0x9c,
- 0xfd, 0x5b, 0x7a, 0x6e, 0x2d, 0xf4, 0x09, 0x70, 0x0d, 0x3e, 0xf9, 0x4c,
- 0xbe, 0x97, 0xb9, 0x5e, 0xcc, 0xdf, 0xcc, 0xf9, 0x5d, 0xef, 0x9c, 0x13,
- 0x6e, 0xce, 0xba, 0x5f, 0xb2, 0x17, 0x0c, 0xff, 0xa5, 0x1d, 0xf0, 0x5e,
- 0x2b, 0xda, 0x0b, 0xb4, 0x09, 0x9f, 0x37, 0x8f, 0x6f, 0x1b, 0x7a, 0xd4,
- 0x36, 0x9c, 0x2a, 0x90, 0x3f, 0xc9, 0x97, 0x3e, 0x3f, 0xfa, 0x3a, 0x8f,
- 0x3c, 0x4a, 0x3d, 0x3b, 0x28, 0x67, 0x0b, 0x3c, 0x9b, 0x94, 0xd6, 0xb4,
- 0x36, 0x9f, 0x3b, 0xa8, 0x98, 0xac, 0xee, 0xe9, 0xc4, 0x4b, 0x39, 0x19,
- 0x96, 0xab, 0x2e, 0xcf, 0x2c, 0x51, 0xcc, 0x04, 0x5b, 0xaa, 0xde, 0x7f,
- 0xbf, 0x9e, 0x59, 0x58, 0x7d, 0xc6, 0x18, 0xc6, 0x3e, 0xef, 0xd1, 0xbb,
- 0x55, 0xcf, 0x36, 0x53, 0x43, 0x9f, 0xaf, 0xeb, 0x39, 0x85, 0xa1, 0x13,
- 0x59, 0xdf, 0x0f, 0x47, 0xf8, 0x0c, 0xd7, 0xa5, 0xcf, 0xc7, 0xb5, 0xc8,
- 0x7b, 0xdd, 0xb0, 0xd8, 0xfd, 0x12, 0xdc, 0x09, 0xd1, 0xdf, 0xc9, 0x3a,
- 0x72, 0x00, 0xb2, 0xba, 0xd9, 0x60, 0x60, 0xc6, 0x8d, 0xaf, 0x91, 0xb1,
- 0xae, 0xe1, 0x1c, 0x11, 0xab, 0xc0, 0x8f, 0x3e, 0xf5, 0x93, 0xdb, 0x98,
- 0x2f, 0xe3, 0xf9, 0xeb, 0x03, 0x98, 0xdf, 0xf1, 0xea, 0xea, 0x53, 0xdb,
- 0xc9, 0xab, 0xa3, 0x5a, 0x1f, 0xe4, 0x33, 0x94, 0x63, 0x9e, 0x19, 0xe9,
- 0xf2, 0x1e, 0x9e, 0x67, 0x7b, 0x5b, 0x1d, 0x1d, 0x93, 0xde, 0xfe, 0xfc,
- 0xfb, 0x61, 0x09, 0xb7, 0x53, 0xc7, 0x45, 0x25, 0x39, 0xcd, 0x98, 0x05,
- 0xb6, 0x6b, 0x9c, 0x73, 0x7d, 0xb1, 0x2e, 0xce, 0xfc, 0x9f, 0xba, 0x38,
- 0x63, 0x7d, 0xa4, 0xbc, 0x13, 0xd6, 0x3c, 0xd6, 0xe7, 0xd3, 0xb5, 0x58,
- 0x43, 0x57, 0xbf, 0x76, 0x1f, 0xad, 0xd0, 0xf1, 0x87, 0x05, 0xda, 0xab,
- 0x94, 0xe6, 0x94, 0xff, 0x3e, 0xc5, 0xb3, 0xe5, 0x1e, 0xaf, 0x72, 0x8f,
- 0xc3, 0x4b, 0x8a, 0x83, 0x7c, 0x58, 0x65, 0xf8, 0x74, 0x81, 0x3a, 0xa6,
- 0x45, 0xe6, 0x67, 0x7c, 0x3d, 0x33, 0xe6, 0xf9, 0xb8, 0xf9, 0xf5, 0x0d,
- 0xaa, 0x67, 0xe0, 0xdd, 0x38, 0x23, 0x9e, 0x7d, 0xe9, 0x92, 0xb9, 0x0b,
- 0xb4, 0xbb, 0x49, 0xf4, 0x45, 0x03, 0x73, 0x0b, 0xac, 0x4d, 0x12, 0x8b,
- 0x32, 0x2c, 0xac, 0xfb, 0x8f, 0xd8, 0xa7, 0x20, 0x6f, 0x31, 0x79, 0x7f,
- 0x8a, 0x3e, 0x7d, 0x03, 0x7c, 0xe3, 0xd6, 0xba, 0xf3, 0xdd, 0x51, 0xf1,
- 0x09, 0x6b, 0xe9, 0x1e, 0xef, 0x90, 0x66, 0xf2, 0xb9, 0x63, 0xdf, 0x10,
- 0xfa, 0x60, 0xbc, 0xce, 0x22, 0x16, 0x60, 0xec, 0x11, 0xd7, 0xd8, 0x63,
- 0xae, 0xc8, 0xbe, 0x16, 0x2f, 0xaf, 0xd4, 0xa2, 0xbc, 0x42, 0x7e, 0xcb,
- 0xa8, 0xff, 0x3d, 0xa4, 0x3a, 0x2b, 0x3f, 0xd5, 0x6b, 0x70, 0x2c, 0x76,
- 0x4c, 0x79, 0x4f, 0x6a, 0x78, 0x2f, 0xe6, 0xad, 0x3d, 0xd6, 0x61, 0x7c,
- 0x2b, 0x5b, 0xf5, 0x4d, 0x58, 0xc7, 0xd1, 0xae, 0x70, 0x7e, 0xf2, 0x06,
- 0x79, 0x84, 0x3a, 0xcf, 0x1f, 0xe7, 0xd3, 0xc3, 0x6f, 0x73, 0x3c, 0xf9,
- 0xbf, 0x1a, 0x8b, 0xe0, 0xcb, 0xaa, 0xdf, 0xe7, 0xcb, 0x1d, 0xef, 0x55,
- 0xdb, 0x04, 0xca, 0x5d, 0x75, 0x7d, 0xd2, 0x96, 0xc8, 0xf4, 0x0a, 0x5d,
- 0xd2, 0xfd, 0xdc, 0xff, 0xf3, 0xcc, 0xed, 0x42, 0xde, 0x56, 0xa3, 0xcd,
- 0x09, 0xa5, 0x4d, 0x06, 0xb4, 0x89, 0x28, 0x6d, 0x18, 0xef, 0x3d, 0xe5,
- 0xf1, 0x5b, 0x0b, 0xce, 0x8b, 0xb9, 0x5a, 0xe8, 0xba, 0x7d, 0xd4, 0xf9,
- 0xcf, 0x76, 0x68, 0x7d, 0xd0, 0xa1, 0xee, 0x5b, 0x0b, 0x7d, 0xc6, 0xf6,
- 0x56, 0xf5, 0x47, 0x4c, 0xbc, 0x15, 0xd7, 0x3c, 0x68, 0x10, 0xfa, 0x79,
- 0x6e, 0x0a, 0xbe, 0x1a, 0x71, 0x6f, 0x35, 0xb4, 0xfa, 0x8e, 0x77, 0x5e,
- 0xf3, 0x4a, 0x1b, 0xca, 0x00, 0xf5, 0xe6, 0x3a, 0xcc, 0xb7, 0x27, 0xda,
- 0x07, 0xfe, 0xfa, 0x19, 0xfa, 0x37, 0x6b, 0x3c, 0x11, 0x84, 0xcc, 0xdf,
- 0x9c, 0x6a, 0xf7, 0x62, 0x38, 0x07, 0x6d, 0xc4, 0xad, 0x53, 0x11, 0xc6,
- 0x14, 0x68, 0xf7, 0x48, 0xc3, 0x34, 0xe2, 0x57, 0xe8, 0xf1, 0x25, 0xb5,
- 0x47, 0x7d, 0xb8, 0x7f, 0x07, 0x71, 0x7e, 0xb8, 0x3e, 0x8a, 0xe7, 0x7a,
- 0x0d, 0x16, 0x21, 0xba, 0x45, 0xcf, 0x74, 0x6e, 0x2a, 0x11, 0x3b, 0x2c,
- 0x5e, 0xdf, 0xb8, 0xab, 0xfa, 0x60, 0x65, 0x5f, 0x0f, 0xca, 0x9e, 0x8a,
- 0xbd, 0x60, 0x1c, 0x0d, 0x1f, 0x7e, 0xc6, 0xd8, 0x83, 0x7c, 0xb1, 0x4f,
- 0xf1, 0x51, 0xc1, 0xa1, 0x45, 0x9c, 0x25, 0x7d, 0xd2, 0x65, 0xf8, 0xe1,
- 0x2e, 0xce, 0x90, 0x7e, 0x77, 0xf9, 0xe4, 0xa4, 0x9b, 0x62, 0x7d, 0x0c,
- 0xfa, 0xe0, 0xa4, 0x8c, 0x20, 0x2e, 0x18, 0x09, 0xb6, 0x32, 0xaf, 0x0c,
- 0xdf, 0x30, 0xe7, 0xe5, 0x1e, 0xfb, 0x98, 0x33, 0x95, 0x73, 0x0b, 0xdc,
- 0x3b, 0x65, 0xdb, 0xc4, 0xde, 0x73, 0x53, 0xdc, 0xaf, 0xc9, 0x43, 0xb0,
- 0x6d, 0x4d, 0xbb, 0xf8, 0xe5, 0x59, 0x0c, 0xe0, 0x77, 0x10, 0xf2, 0xc0,
- 0xb1, 0xf8, 0x5d, 0x58, 0x96, 0x77, 0x2f, 0xf8, 0xb6, 0x3d, 0x20, 0x6f,
- 0x3b, 0xe5, 0x93, 0xa7, 0xdc, 0xf5, 0x3c, 0x03, 0x37, 0xc7, 0x9a, 0xb5,
- 0xe3, 0xb8, 0x79, 0x29, 0x97, 0x97, 0xdc, 0xa5, 0xf5, 0x96, 0xd2, 0x92,
- 0xf2, 0xbf, 0x8c, 0x33, 0xbc, 0x7e, 0xaf, 0x25, 0x86, 0x7e, 0xa4, 0xcd,
- 0x67, 0x6b, 0x7f, 0xd5, 0xb6, 0xc0, 0xd7, 0x7f, 0xe4, 0x47, 0xf2, 0xe5,
- 0xb2, 0xec, 0x52, 0xfd, 0xbf, 0xda, 0x73, 0xd5, 0xba, 0xdf, 0xf7, 0x6f,
- 0xa9, 0xdf, 0xb5, 0xfe, 0xa3, 0xf1, 0xc1, 0x96, 0xe9, 0x7a, 0x9d, 0xf0,
- 0x98, 0x57, 0x57, 0x58, 0x8d, 0xf7, 0x0e, 0x78, 0x7a, 0x21, 0xa5, 0xbe,
- 0x73, 0xca, 0xa6, 0x7e, 0xe0, 0x7e, 0x9a, 0xe5, 0xe0, 0xec, 0x6d, 0xd0,
- 0xc4, 0xd7, 0xc1, 0x8c, 0xfb, 0x7c, 0xdd, 0xd1, 0xea, 0xf9, 0xc2, 0x96,
- 0x74, 0x9f, 0xa3, 0xef, 0xe4, 0x40, 0x8f, 0xb6, 0x49, 0x66, 0x3c, 0x28,
- 0xc9, 0x73, 0x1b, 0x62, 0xc6, 0xd7, 0x25, 0xff, 0x41, 0xde, 0xb4, 0x4f,
- 0x7d, 0x51, 0xf4, 0xdf, 0x29, 0x5c, 0xdb, 0xf0, 0x33, 0xe4, 0x79, 0x9f,
- 0x7f, 0xcf, 0xae, 0xe3, 0xd1, 0x9d, 0x1e, 0x8f, 0xf2, 0xbe, 0x65, 0xea,
- 0x1f, 0x18, 0xdb, 0x7d, 0x8e, 0x7b, 0x34, 0xcf, 0x75, 0x9f, 0x33, 0xf1,
- 0x7a, 0xed, 0x73, 0x7d, 0x95, 0xe7, 0x70, 0xbf, 0x47, 0xb1, 0x61, 0x98,
- 0x7b, 0xd7, 0x20, 0x7c, 0xba, 0x3e, 0xda, 0x1c, 0xda, 0xef, 0xcd, 0xee,
- 0x2e, 0x21, 0xbf, 0x27, 0x3c, 0x9e, 0xa3, 0xbe, 0x89, 0x78, 0xfa, 0x66,
- 0xc5, 0xbe, 0x8c, 0x18, 0xfc, 0x09, 0x73, 0x22, 0x55, 0xf6, 0xe5, 0x71,
- 0xf3, 0x6e, 0x35, 0xf6, 0xe5, 0x4e, 0x6f, 0x1e, 0xff, 0x9e, 0xaf, 0x57,
- 0xfc, 0xb6, 0xaf, 0x57, 0xea, 0x7d, 0x5a, 0x9f, 0xf6, 0xb5, 0xb8, 0xaf,
- 0xea, 0x98, 0x2f, 0xbf, 0x6a, 0xde, 0x25, 0x8b, 0x98, 0x8d, 0x3e, 0x65,
- 0x22, 0x67, 0x30, 0xd3, 0xd6, 0x59, 0x8b, 0xb8, 0x0f, 0xe7, 0xc7, 0x92,
- 0x8e, 0xdc, 0xd6, 0xd8, 0xfa, 0xf4, 0xec, 0x98, 0xe6, 0x79, 0xe6, 0x5c,
- 0x4f, 0xef, 0x44, 0x77, 0x43, 0xae, 0x5e, 0x89, 0xac, 0x60, 0x8a, 0x66,
- 0x4e, 0xa4, 0x61, 0x87, 0x52, 0x5a, 0x2f, 0xfb, 0x2e, 0xf6, 0x3b, 0xa8,
- 0x78, 0xae, 0x35, 0xce, 0x73, 0xf2, 0x90, 0x5d, 0xd6, 0xda, 0x4d, 0xd3,
- 0x50, 0xf1, 0x44, 0xd3, 0x8b, 0x3e, 0xdf, 0x93, 0x9f, 0x66, 0x4e, 0x1c,
- 0x9c, 0x29, 0x0f, 0x87, 0xb6, 0xf7, 0xda, 0x79, 0x21, 0x66, 0x7f, 0x58,
- 0x8e, 0x28, 0x76, 0xf8, 0x15, 0xdc, 0xdf, 0xc7, 0xf8, 0x32, 0x11, 0x52,
- 0x4c, 0x70, 0x22, 0x36, 0x01, 0x59, 0xcc, 0xba, 0xc4, 0xf8, 0xaf, 0x55,
- 0xac, 0xff, 0x9c, 0xd0, 0xcf, 0x22, 0xa6, 0xe0, 0x59, 0x39, 0xec, 0x6e,
- 0x76, 0x97, 0xc4, 0xf8, 0xbf, 0x59, 0xad, 0x09, 0x35, 0xca, 0x84, 0x1b,
- 0x6a, 0x4a, 0x97, 0x8c, 0x0c, 0x8c, 0x06, 0x53, 0x6b, 0x26, 0x9d, 0x68,
- 0xd3, 0xae, 0x12, 0x64, 0xbc, 0x04, 0xfd, 0x5f, 0x8a, 0x05, 0x46, 0x14,
- 0x9b, 0xf6, 0x65, 0x49, 0xb7, 0xd3, 0xcf, 0xa7, 0x3e, 0xf9, 0x8a, 0xdc,
- 0xb4, 0xb7, 0xca, 0xcd, 0x1e, 0xe2, 0x31, 0xfb, 0xd1, 0xa6, 0x2e, 0x19,
- 0x44, 0x5f, 0x12, 0x7d, 0x4d, 0xca, 0x8f, 0x1a, 0x9f, 0x41, 0x67, 0xdd,
- 0xb4, 0xa9, 0xab, 0xee, 0xe2, 0x2f, 0xde, 0xf5, 0x6f, 0xa0, 0x09, 0xb1,
- 0x1d, 0xdb, 0xd0, 0xa6, 0x8e, 0xb3, 0xeb, 0xfa, 0x3b, 0xd1, 0xbe, 0x17,
- 0x73, 0x34, 0xe8, 0xfb, 0x59, 0xce, 0x76, 0x53, 0xe7, 0xac, 0x19, 0xb3,
- 0xae, 0xae, 0xfd, 0xfb, 0x36, 0x83, 0x4f, 0xf8, 0x94, 0xf4, 0xce, 0xa5,
- 0xe4, 0xe1, 0x8e, 0xda, 0xf6, 0xbf, 0xea, 0xda, 0xad, 0xb2, 0xa6, 0x8d,
- 0x64, 0x38, 0xd6, 0x5e, 0xdb, 0xef, 0xf3, 0x93, 0xdf, 0xee, 0xc0, 0xfb,
- 0x42, 0x66, 0xac, 0xa4, 0xc6, 0x52, 0x37, 0xa3, 0x5c, 0xeb, 0xc3, 0xba,
- 0x67, 0x78, 0xcd, 0x67, 0xf8, 0x2c, 0xf3, 0x7a, 0xb7, 0xd9, 0x8f, 0x67,
- 0x98, 0x13, 0x60, 0x5e, 0x83, 0x3c, 0xbb, 0x5a, 0x9c, 0xc5, 0x31, 0x9f,
- 0xcd, 0x37, 0x64, 0x2a, 0xbc, 0xe7, 0xeb, 0x95, 0x58, 0x05, 0xab, 0xb6,
- 0xab, 0xe0, 0xe7, 0x84, 0x49, 0x3b, 0xad, 0x49, 0xc5, 0x6e, 0x80, 0xce,
- 0x87, 0x40, 0xe7, 0x07, 0x83, 0x8c, 0x0b, 0x9b, 0x3d, 0x5a, 0x3b, 0x32,
- 0x52, 0xfa, 0x0d, 0x64, 0x9c, 0x3c, 0x0a, 0x9f, 0xa2, 0x64, 0x79, 0xf8,
- 0x8c, 0x01, 0xd8, 0x34, 0x57, 0x82, 0x9a, 0x77, 0x40, 0x7c, 0x3f, 0x7f,
- 0x5d, 0x46, 0xa6, 0x98, 0x13, 0x20, 0x3f, 0x33, 0xae, 0x4f, 0xe1, 0xde,
- 0x2d, 0x8c, 0x75, 0x21, 0xc3, 0x63, 0xe0, 0xd7, 0x90, 0x38, 0xd3, 0xdb,
- 0x24, 0x37, 0x3e, 0xa6, 0x3e, 0x40, 0x37, 0x6c, 0xd4, 0x29, 0x77, 0x54,
- 0x26, 0xaf, 0x6c, 0x82, 0xac, 0x32, 0xee, 0xd7, 0x9c, 0x46, 0x39, 0xac,
- 0xbe, 0x39, 0x7d, 0x0e, 0xe6, 0xe1, 0x4c, 0x8d, 0xd9, 0xc8, 0xed, 0xa1,
- 0x98, 0xb4, 0x8e, 0xca, 0xcc, 0xac, 0xad, 0x78, 0x97, 0x94, 0xdc, 0x2e,
- 0x93, 0x76, 0xd9, 0x7d, 0x71, 0xe8, 0x2a, 0xfa, 0xf2, 0x3f, 0x88, 0x98,
- 0xb3, 0xdc, 0xbd, 0x81, 0x31, 0x71, 0x72, 0xba, 0x7a, 0x0e, 0xc5, 0xc8,
- 0xe0, 0xde, 0x2f, 0xdb, 0x8c, 0xcc, 0x30, 0x3e, 0xfe, 0xa0, 0x9c, 0x8a,
- 0x72, 0x4d, 0x8e, 0x65, 0xed, 0x96, 0x3c, 0xc2, 0xbd, 0xfd, 0xc7, 0xe3,
- 0xe5, 0x97, 0x31, 0x5f, 0x5c, 0xba, 0x5f, 0x1d, 0xd3, 0xb8, 0xfe, 0x54,
- 0x4d, 0x0c, 0x6b, 0xf2, 0x05, 0x26, 0x8e, 0xbd, 0x2e, 0x13, 0x8b, 0xa4,
- 0x0f, 0x6d, 0x7c, 0x40, 0x7e, 0xe1, 0xf4, 0xda, 0x4f, 0x68, 0xad, 0x31,
- 0x91, 0x62, 0x7d, 0xa6, 0xd9, 0x49, 0xda, 0xf3, 0x12, 0x1a, 0xfc, 0x1a,
- 0xae, 0x19, 0xd7, 0xe6, 0xdd, 0x5e, 0xf7, 0x09, 0xf1, 0x71, 0x20, 0x9b,
- 0x53, 0x8d, 0x81, 0x4f, 0xca, 0xd7, 0xf7, 0x71, 0x8c, 0xc1, 0x81, 0x48,
- 0x80, 0xb4, 0x7a, 0xef, 0x2e, 0xe2, 0x67, 0x6a, 0xf3, 0x7f, 0x0f, 0x1c,
- 0xdb, 0x3b, 0x90, 0x38, 0xc3, 0x18, 0x36, 0xec, 0x3c, 0xba, 0xc1, 0xbc,
- 0x6b, 0x2e, 0xb7, 0x4e, 0xb4, 0x7e, 0x76, 0xfc, 0x1f, 0x0e, 0xf1, 0x10,
- 0x89, 0x58, 0xa3, 0xc5, 0x3c, 0x38, 0x75, 0x1c, 0x6b, 0x2a, 0xcc, 0xb9,
- 0x11, 0xcb, 0xdf, 0x24, 0x97, 0xfb, 0x2c, 0x79, 0x20, 0x94, 0x8a, 0x5b,
- 0xb2, 0x25, 0x7e, 0x4e, 0xb0, 0x26, 0xeb, 0x2b, 0x8b, 0x89, 0x1c, 0xc7,
- 0x87, 0xa6, 0x39, 0x5f, 0x5c, 0xe3, 0x95, 0xe4, 0x96, 0x72, 0xf9, 0x29,
- 0x57, 0x02, 0xc9, 0x7b, 0x3e, 0x2c, 0xb3, 0x16, 0x6e, 0xbd, 0xfa, 0x79,
- 0x38, 0x05, 0xea, 0x0a, 0x7b, 0xc2, 0x60, 0x0e, 0x27, 0x8f, 0x77, 0x2f,
- 0xb2, 0xfd, 0xe4, 0x43, 0xa6, 0x7d, 0x06, 0xed, 0x06, 0x0f, 0xeb, 0x34,
- 0x75, 0xbc, 0xbb, 0x78, 0x6c, 0x83, 0x89, 0xbf, 0x97, 0x15, 0xff, 0xf5,
- 0x56, 0x4d, 0x4c, 0x93, 0x0a, 0x8c, 0x17, 0xc6, 0x02, 0x63, 0x05, 0xab,
- 0xaf, 0x09, 0xb4, 0x5a, 0x70, 0x99, 0xab, 0xf1, 0x73, 0x56, 0xcc, 0xf7,
- 0x8b, 0x3c, 0xa9, 0x18, 0x29, 0xd6, 0x14, 0x2d, 0xf5, 0x85, 0x0e, 0x2d,
- 0x30, 0xc7, 0x1f, 0x51, 0x7d, 0x70, 0x78, 0xb1, 0x55, 0xf2, 0xf6, 0x7a,
- 0xc9, 0xab, 0x8c, 0x47, 0x55, 0x07, 0x58, 0xce, 0x3d, 0xe8, 0xe3, 0xbe,
- 0x1f, 0x57, 0x5c, 0xc4, 0xeb, 0x85, 0x4e, 0xb4, 0x99, 0x6b, 0xde, 0x51,
- 0xd7, 0x5f, 0x5d, 0x97, 0x4d, 0xd8, 0x96, 0x55, 0x5f, 0x93, 0x65, 0x5f,
- 0x7d, 0x2d, 0xf6, 0xb4, 0x5c, 0x27, 0xdf, 0x94, 0xfc, 0x9c, 0xbb, 0xeb,
- 0xe5, 0xdc, 0x1f, 0xc3, 0x9c, 0x9c, 0x5b, 0x32, 0xa1, 0xa1, 0xa6, 0xbe,
- 0x53, 0x53, 0xc1, 0x5b, 0x2b, 0xf9, 0x53, 0xb4, 0x17, 0x2b, 0xb5, 0x72,
- 0xdc, 0x7b, 0x06, 0xbe, 0x48, 0x1e, 0x7e, 0x45, 0xce, 0xfb, 0xfe, 0x80,
- 0xf7, 0x2b, 0xcf, 0x7f, 0xc1, 0x9e, 0x9a, 0xb5, 0xce, 0x6e, 0xd5, 0xd4,
- 0xd9, 0xbf, 0x8d, 0x67, 0x59, 0x63, 0xcf, 0x95, 0x1b, 0xc0, 0xbb, 0x0d,
- 0xc4, 0x89, 0x54, 0xc6, 0x53, 0xc7, 0xab, 0x2e, 0xd7, 0xb9, 0x76, 0x79,
- 0x73, 0x05, 0xa1, 0xe7, 0x0f, 0x4e, 0xf9, 0x63, 0x4e, 0x4a, 0x63, 0x7f,
- 0x22, 0x16, 0xb4, 0x38, 0xc6, 0xe8, 0xfb, 0xb4, 0x7b, 0x12, 0x7a, 0x9c,
- 0x3a, 0x9f, 0xef, 0xed, 0xc0, 0xd7, 0xa3, 0x2e, 0xa0, 0x3e, 0x57, 0x1b,
- 0x10, 0xcf, 0x43, 0xd7, 0x8f, 0x94, 0x34, 0x97, 0x1f, 0xfb, 0x6a, 0x30,
- 0x31, 0x93, 0x55, 0xdd, 0x00, 0x7f, 0xaf, 0xf4, 0x26, 0xf3, 0x41, 0x67,
- 0x24, 0x50, 0x5d, 0xa7, 0x61, 0x6c, 0xc6, 0x9a, 0x46, 0x0b, 0x74, 0x83,
- 0xc8, 0x55, 0xf0, 0xc6, 0x6b, 0x0b, 0xe4, 0xd7, 0x60, 0xbb, 0x89, 0xaf,
- 0x96, 0x76, 0x58, 0xd2, 0xae, 0xb5, 0xcf, 0xbc, 0x13, 0xa1, 0x7f, 0x32,
- 0x9c, 0xec, 0x87, 0x9f, 0xad, 0xd8, 0x03, 0xe6, 0x2b, 0x0f, 0x22, 0x1e,
- 0xab, 0xce, 0xb1, 0x40, 0xbe, 0xc6, 0xd9, 0x9f, 0x85, 0x5f, 0xb9, 0x52,
- 0xf7, 0xc8, 0x17, 0x27, 0x35, 0xb7, 0x39, 0xb7, 0xd0, 0xa2, 0x3a, 0x76,
- 0xae, 0x38, 0x86, 0x73, 0x91, 0xad, 0xd6, 0x50, 0xde, 0xeb, 0x0f, 0x4b,
- 0xb1, 0xc8, 0xb6, 0x74, 0x35, 0xe8, 0xb9, 0xfb, 0xb5, 0x1d, 0x5b, 0xe6,
- 0xe1, 0x2b, 0x16, 0x17, 0x1d, 0xfc, 0xf7, 0xe0, 0xbf, 0x0f, 0xff, 0xbb,
- 0x25, 0x3d, 0x4d, 0xff, 0x95, 0xb5, 0x9c, 0x96, 0xba, 0xf5, 0xe9, 0x23,
- 0x75, 0x29, 0x0e, 0x2c, 0xef, 0xc5, 0x39, 0xf9, 0x62, 0xbd, 0x9c, 0x30,
- 0x4f, 0xea, 0xeb, 0x08, 0xe6, 0x4b, 0xfd, 0x5a, 0x5f, 0x75, 0x0d, 0xcb,
- 0xf2, 0xea, 0x5e, 0xe4, 0xe9, 0x66, 0x39, 0x5c, 0xf4, 0x6b, 0x57, 0x31,
- 0x39, 0x52, 0xa9, 0x5d, 0x49, 0x26, 0x38, 0xf4, 0xc9, 0x23, 0xd9, 0x29,
- 0xc5, 0x13, 0x58, 0xd6, 0xd0, 0xf5, 0x47, 0x26, 0x16, 0xdf, 0x7e, 0x64,
- 0x05, 0x13, 0x8e, 0x7b, 0x8b, 0xab, 0x61, 0x86, 0x88, 0xa5, 0xe3, 0xb7,
- 0x72, 0xea, 0xbb, 0x61, 0xdf, 0x7e, 0xcc, 0x43, 0x9c, 0x1d, 0xf4, 0x4c,
- 0xf3, 0x0a, 0x76, 0xd7, 0xc4, 0xa3, 0xc4, 0x91, 0xf2, 0xb9, 0x6a, 0xec,
- 0x47, 0x08, 0xe7, 0x2f, 0x01, 0xcb, 0xc9, 0x61, 0x1f, 0x3f, 0xed, 0x34,
- 0x7e, 0x20, 0x71, 0xa6, 0x89, 0x2a, 0xec, 0x91, 0x8f, 0x35, 0x7d, 0x09,
- 0x73, 0x65, 0xe4, 0x77, 0xa5, 0x47, 0xe5, 0x57, 0xa5, 0x31, 0xc8, 0xf7,
- 0x04, 0xe6, 0x3c, 0x20, 0x6f, 0x96, 0xf6, 0xc9, 0xb5, 0xd2, 0xb8, 0xbc,
- 0x51, 0xda, 0x8d, 0x98, 0x6a, 0x94, 0x58, 0x4f, 0x0f, 0x2b, 0x3d, 0x2c,
- 0x07, 0xcf, 0x2b, 0x06, 0xf0, 0x16, 0xfd, 0x9e, 0xe3, 0xea, 0x67, 0x13,
- 0x5f, 0x9f, 0xf8, 0x35, 0xe3, 0x79, 0x62, 0x33, 0x8b, 0x25, 0x1f, 0xc3,
- 0x71, 0xb4, 0x0b, 0x6b, 0xdb, 0xfc, 0x36, 0x65, 0xe4, 0x7c, 0x24, 0x30,
- 0x7a, 0x3e, 0x14, 0x78, 0x50, 0xbf, 0x73, 0x61, 0xbd, 0xb3, 0x2c, 0x93,
- 0xae, 0x43, 0xde, 0x1c, 0x1c, 0x81, 0x2c, 0x8c, 0x42, 0xd5, 0x3f, 0xe4,
- 0xac, 0x17, 0x90, 0x34, 0xf5, 0x11, 0xfc, 0xcc, 0xe4, 0x8b, 0xae, 0x64,
- 0x0b, 0xf3, 0x01, 0x83, 0x47, 0xb3, 0xd1, 0xee, 0x43, 0xfb, 0xe7, 0x5e,
- 0x7b, 0xa7, 0x64, 0x67, 0x25, 0xf5, 0xbe, 0xfa, 0xc3, 0x2f, 0x7b, 0x7d,
- 0x83, 0xe8, 0x03, 0x67, 0x5e, 0x64, 0xdf, 0x45, 0xaf, 0x8f, 0x67, 0xc2,
- 0x5a, 0x7d, 0x5c, 0xf9, 0x2a, 0x6b, 0x8f, 0x8b, 0x7e, 0xd7, 0xa0, 0xb5,
- 0xf8, 0x0f, 0x3a, 0x8d, 0x6e, 0x23, 0x26, 0xf0, 0x9f, 0x9d, 0x8c, 0xc1,
- 0x8a, 0x90, 0xaf, 0xbb, 0xa0, 0x13, 0xff, 0xba, 0x75, 0xa5, 0x6d, 0x0d,
- 0x7d, 0x5c, 0x85, 0xd1, 0xfe, 0x58, 0xba, 0x17, 0xff, 0xed, 0xe1, 0x79,
- 0x9f, 0xc0, 0xbb, 0xe1, 0xac, 0x0a, 0xc4, 0x8d, 0xc7, 0x21, 0xdb, 0x2d,
- 0xb2, 0xfe, 0x2c, 0xe9, 0xd5, 0x0b, 0x5d, 0x9d, 0x82, 0xdc, 0xba, 0xb2,
- 0x50, 0x0a, 0x05, 0x46, 0x0a, 0x29, 0x31, 0x78, 0x6a, 0x4b, 0x32, 0xd1,
- 0x94, 0x9c, 0x1e, 0x48, 0xf4, 0x30, 0x0f, 0x99, 0xed, 0x77, 0xe5, 0x52,
- 0x89, 0xf6, 0x38, 0x27, 0x97, 0x07, 0x12, 0x6e, 0x51, 0x88, 0x8b, 0x71,
- 0xe5, 0x32, 0x64, 0xf3, 0x9d, 0xf3, 0xbb, 0xe5, 0x48, 0x41, 0xfd, 0xe0,
- 0xde, 0xb0, 0xbc, 0x20, 0x97, 0x06, 0x5e, 0xb8, 0x75, 0xc9, 0x3d, 0x84,
- 0x33, 0x25, 0x1f, 0x1e, 0xee, 0x32, 0xfb, 0x56, 0x1c, 0x92, 0x30, 0x1f,
- 0xa2, 0x35, 0x35, 0xa7, 0x51, 0xd2, 0xfb, 0x23, 0x5e, 0x5c, 0x0e, 0x9f,
- 0x3b, 0x30, 0x60, 0xea, 0x29, 0x01, 0x7f, 0x9f, 0x61, 0xf8, 0x31, 0x7c,
- 0xce, 0xa7, 0x8d, 0x3f, 0x4f, 0x67, 0x20, 0x3d, 0xdb, 0x2a, 0xa1, 0x8b,
- 0xf7, 0x81, 0xae, 0x21, 0x39, 0xd4, 0x5f, 0x2e, 0x7f, 0xd3, 0x0d, 0xc5,
- 0x27, 0x10, 0xa3, 0x60, 0xff, 0xb2, 0xee, 0xc5, 0x36, 0xd0, 0xa4, 0x49,
- 0xa2, 0x2f, 0xfa, 0xeb, 0x35, 0x7a, 0x58, 0x86, 0x8b, 0xeb, 0x8c, 0x2d,
- 0xf3, 0xb1, 0x0d, 0xfe, 0x7c, 0x06, 0x53, 0xd6, 0x6d, 0xf5, 0x07, 0xbc,
- 0xef, 0x24, 0xbc, 0xf6, 0x3d, 0x81, 0x07, 0x42, 0xed, 0x12, 0x72, 0x9e,
- 0xdf, 0x48, 0x6c, 0xe4, 0x52, 0xc1, 0xef, 0x87, 0x9f, 0x18, 0xf2, 0xfd,
- 0x61, 0xd9, 0xbe, 0x72, 0xd6, 0xb2, 0xbd, 0x7b, 0xf1, 0x5b, 0xde, 0x9c,
- 0x29, 0x6f, 0x2c, 0x62, 0x8e, 0xd8, 0x5a, 0xb5, 0x4f, 0x66, 0xec, 0xa7,
- 0xf2, 0x74, 0x7f, 0xe2, 0x15, 0xc5, 0xc9, 0x56, 0x9e, 0xe1, 0x7d, 0xc4,
- 0x90, 0x25, 0x7d, 0x26, 0xb6, 0x07, 0xf4, 0xcd, 0xc4, 0xee, 0xb6, 0xe7,
- 0xad, 0x60, 0xc0, 0xf8, 0x23, 0x0d, 0xf2, 0xbd, 0x28, 0xec, 0x36, 0xbf,
- 0x61, 0x61, 0xfe, 0xcb, 0xbd, 0xed, 0xf9, 0x29, 0xec, 0x4b, 0x9c, 0x49,
- 0x5a, 0x13, 0xd8, 0x1f, 0xcf, 0x80, 0x18, 0x50, 0x0b, 0x74, 0xea, 0xc4,
- 0xfb, 0x21, 0x7e, 0xea, 0xf7, 0xdf, 0x7f, 0x1d, 0x74, 0x18, 0xf7, 0x6f,
- 0x70, 0x61, 0x62, 0x31, 0x17, 0x32, 0xec, 0x61, 0x60, 0xab, 0xe5, 0xd6,
- 0xc7, 0xc6, 0xfa, 0x78, 0x3a, 0x62, 0x94, 0x62, 0xf0, 0x03, 0x29, 0x13,
- 0xe4, 0xcd, 0x0e, 0xf4, 0xaf, 0xf9, 0x24, 0xa5, 0xaf, 0xee, 0xf7, 0x7d,
- 0x58, 0xc1, 0x76, 0x4f, 0x14, 0xf6, 0x19, 0x6c, 0x9e, 0xb5, 0x2c, 0xa9,
- 0xae, 0xa4, 0x3d, 0x89, 0xfd, 0xa6, 0x43, 0x89, 0x62, 0x4e, 0x62, 0x32,
- 0x0f, 0x7d, 0xf1, 0x1a, 0x64, 0xff, 0x5a, 0x29, 0x1e, 0x48, 0x63, 0x4f,
- 0x87, 0x0b, 0x43, 0x32, 0x31, 0xab, 0xdf, 0x7e, 0x41, 0xef, 0x0f, 0xc9,
- 0x5c, 0x21, 0xd1, 0x33, 0x0f, 0xfe, 0x9b, 0x2f, 0x10, 0x5f, 0xd4, 0x1b,
- 0x1f, 0xc5, 0x8c, 0x4b, 0x85, 0xcd, 0xb0, 0x0f, 0x92, 0xba, 0x04, 0xff,
- 0xe7, 0x52, 0xa9, 0x07, 0x7c, 0x86, 0xfb, 0x25, 0x07, 0xbf, 0xd0, 0x99,
- 0xa5, 0x01, 0xc8, 0x39, 0xf7, 0x62, 0xcb, 0xc2, 0x56, 0x9c, 0x1d, 0x71,
- 0x44, 0x8a, 0x1f, 0xff, 0x2f, 0xce, 0xd7, 0x7f, 0xef, 0x1d, 0x6a, 0xa7,
- 0xe7, 0x75, 0x5f, 0xb0, 0xcb, 0x88, 0x01, 0xb2, 0xfd, 0xc6, 0x6e, 0xa7,
- 0x23, 0x6d, 0x92, 0xbe, 0x9b, 0x76, 0xbc, 0x5d, 0x63, 0x44, 0xe5, 0xc5,
- 0x08, 0xef, 0xbf, 0xb3, 0xd1, 0xd0, 0x2f, 0x5c, 0xd7, 0xbe, 0x8e, 0xdf,
- 0x56, 0xe9, 0x70, 0xf8, 0x6b, 0xe3, 0xf7, 0xed, 0x8d, 0xac, 0xef, 0x76,
- 0x38, 0x49, 0xac, 0xf5, 0x5b, 0x2f, 0x5f, 0x80, 0xeb, 0x79, 0x3e, 0xb3,
- 0xc1, 0x5b, 0x97, 0xf3, 0xb6, 0x62, 0x9e, 0x16, 0x6f, 0xad, 0x56, 0xcd,
- 0x4f, 0x9a, 0xb5, 0x10, 0xe3, 0x16, 0xfe, 0xb2, 0x51, 0xbf, 0x35, 0x86,
- 0xbd, 0xa8, 0x6d, 0xff, 0x79, 0x23, 0x71, 0x73, 0x1d, 0x4e, 0xab, 0x62,
- 0x3c, 0x6f, 0xb6, 0xb7, 0xe3, 0x9a, 0x6b, 0x72, 0x8c, 0xc9, 0x87, 0xcf,
- 0x95, 0x38, 0x3f, 0xdb, 0x29, 0x39, 0xa1, 0xf9, 0x0c, 0x83, 0xe5, 0x9b,
- 0x2b, 0xdc, 0x2f, 0x13, 0xe7, 0x15, 0x5f, 0x37, 0x93, 0xb7, 0xf8, 0xdd,
- 0x0b, 0xbf, 0x97, 0xa3, 0x2f, 0x31, 0x26, 0x07, 0x71, 0x7e, 0x97, 0xe1,
- 0x53, 0x2d, 0x99, 0xef, 0x62, 0xf1, 0x77, 0x00, 0xe7, 0x12, 0x82, 0x8c,
- 0x51, 0x46, 0x29, 0x53, 0x38, 0xbf, 0x71, 0x5b, 0xde, 0x1d, 0xa0, 0x3c,
- 0x0f, 0xc8, 0x95, 0x8a, 0x3c, 0xe7, 0x20, 0xcf, 0x94, 0xe5, 0x1c, 0x64,
- 0xda, 0xf0, 0xf5, 0x7e, 0x7e, 0x67, 0x1d, 0x83, 0xbd, 0x52, 0x1f, 0xe2,
- 0x25, 0xf0, 0xb5, 0xed, 0x7d, 0x2b, 0x15, 0xd0, 0x1c, 0x4e, 0x76, 0xb6,
- 0xc1, 0xfb, 0x0e, 0x00, 0xd7, 0x57, 0x9e, 0x93, 0xf4, 0x6c, 0x33, 0xbf,
- 0xe7, 0xea, 0xe2, 0x99, 0x65, 0xaf, 0xf0, 0xdf, 0xe7, 0x45, 0xe2, 0x4d,
- 0xe9, 0xcf, 0xf2, 0x9a, 0x71, 0xde, 0x26, 0x8c, 0x19, 0x04, 0x9d, 0x9b,
- 0x31, 0x3f, 0xf7, 0xb8, 0xda, 0x38, 0xde, 0x0f, 0x55, 0xe1, 0x53, 0x7d,
- 0x7a, 0xaf, 0xd5, 0x35, 0xb3, 0xfd, 0xcd, 0xde, 0xfb, 0xf1, 0x1c, 0x94,
- 0xef, 0xc1, 0xb7, 0xf4, 0x89, 0xc9, 0x2f, 0x29, 0x3d, 0x87, 0xb9, 0x02,
- 0xf9, 0x37, 0xa4, 0x39, 0x8c, 0x2c, 0x6c, 0xcb, 0x5e, 0x1d, 0x1f, 0x5b,
- 0x91, 0xef, 0xae, 0x80, 0xc6, 0xdd, 0xd9, 0xc2, 0x1a, 0xe9, 0x56, 0x1d,
- 0xd4, 0xe5, 0xf1, 0x36, 0xec, 0x85, 0x62, 0xb9, 0x0f, 0xc8, 0xf1, 0xd2,
- 0x20, 0xe8, 0x10, 0x93, 0xa7, 0xe0, 0x37, 0x3f, 0x53, 0xba, 0x43, 0x96,
- 0x23, 0xd8, 0x57, 0x45, 0xc6, 0x86, 0xe5, 0xfb, 0xf3, 0x09, 0xef, 0x3a,
- 0xe1, 0x2e, 0x5b, 0x3b, 0xb0, 0x07, 0xca, 0x13, 0xe5, 0x8a, 0xe3, 0x82,
- 0x88, 0x45, 0x38, 0xef, 0xd3, 0x46, 0xb7, 0x61, 0xde, 0x62, 0x84, 0xf2,
- 0xcb, 0xbd, 0x85, 0x3c, 0x99, 0x65, 0x5c, 0xc5, 0x77, 0x36, 0x36, 0x29,
- 0x53, 0x73, 0x16, 0x09, 0xc5, 0x81, 0xae, 0x9c, 0x81, 0x3f, 0x8f, 0x2f,
- 0x97, 0xfe, 0x77, 0x14, 0xd4, 0xa3, 0xb0, 0x95, 0x05, 0xd8, 0xca, 0x02,
- 0x6c, 0x24, 0x64, 0xe1, 0x5a, 0x01, 0x36, 0xb2, 0x00, 0x1b, 0x09, 0x7d,
- 0xf6, 0x3a, 0x62, 0xbb, 0xd7, 0xc0, 0x43, 0xc6, 0xd7, 0x3e, 0x4a, 0x5f,
- 0x1b, 0x7f, 0xff, 0x03, 0x4c, 0x03, 0x3a, 0xe1, 0xd4, 0x71, 0x00, 0x00,
- 0x00 };
+ 0xec, 0x5b, 0x5f, 0x6c, 0x5b, 0xd7, 0x79, 0xff, 0xee, 0x21, 0x25, 0x51,
+ 0xb2, 0xfe, 0x5c, 0xc9, 0x8c, 0x43, 0x27, 0x4a, 0x43, 0x4a, 0x57, 0x12,
+ 0x13, 0x69, 0xe9, 0x95, 0xc6, 0x26, 0x2a, 0x46, 0x34, 0x2c, 0x29, 0xdb,
+ 0x4a, 0xe3, 0x07, 0xc5, 0xf5, 0xda, 0xac, 0xeb, 0x30, 0x81, 0xb2, 0xb1,
+ 0xec, 0x61, 0x83, 0x67, 0xac, 0x41, 0xb6, 0xb9, 0x30, 0x41, 0x29, 0x8e,
+ 0x92, 0xd2, 0x22, 0x67, 0x2b, 0x73, 0xb1, 0x65, 0x80, 0x42, 0x49, 0x76,
+ 0xb6, 0xd1, 0x62, 0xda, 0xbd, 0x74, 0x45, 0x1c, 0x0b, 0x8a, 0xe7, 0xe5,
+ 0xa1, 0x0f, 0x69, 0x17, 0x60, 0xed, 0xd0, 0x61, 0x86, 0xe2, 0xda, 0x79,
+ 0x28, 0xb6, 0x6c, 0x40, 0x96, 0x6c, 0x71, 0x73, 0xf7, 0xfb, 0x9d, 0x7b,
+ 0xaf, 0x4c, 0x2b, 0x1a, 0x9a, 0x87, 0x3d, 0xde, 0x03, 0x08, 0xe7, 0x9e,
+ 0x73, 0xbe, 0xf3, 0x9d, 0xef, 0xfb, 0xce, 0xf7, 0xf7, 0xd0, 0xfe, 0xc3,
+ 0x76, 0x69, 0x13, 0xaf, 0x75, 0xe0, 0x2f, 0x75, 0xec, 0x99, 0xe3, 0x63,
+ 0x0f, 0xa5, 0x1e, 0xe2, 0x38, 0xa4, 0xc2, 0x61, 0xf6, 0x86, 0x04, 0x2d,
+ 0x68, 0x41, 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68,
+ 0x41, 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41,
+ 0x0b, 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b,
+ 0x5a, 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b, 0x5a,
+ 0xd0, 0x82, 0x16, 0xb4, 0xa0, 0x05, 0x2d, 0x68, 0x41, 0x0b, 0x5a, 0xd0,
+ 0x82, 0x16, 0xb4, 0xa0, 0x05, 0xed, 0xff, 0xb3, 0x85, 0x44, 0x4c, 0xf6,
+ 0x1d, 0xde, 0x9f, 0x44, 0x54, 0x3a, 0x7e, 0x3c, 0x6b, 0x49, 0x24, 0x94,
+ 0xbe, 0xf2, 0xf4, 0x8c, 0x25, 0x92, 0xa9, 0x0d, 0xc7, 0x73, 0xf2, 0x0b,
+ 0xa7, 0x10, 0x0d, 0x0b, 0xe7, 0xef, 0x4b, 0xdf, 0x3a, 0x79, 0xe9, 0x91,
+ 0xc4, 0x7b, 0x4b, 0x21, 0x89, 0x98, 0xe9, 0xb7, 0x46, 0xcd, 0x41, 0x89,
+ 0xf4, 0x62, 0xcf, 0x4b, 0x43, 0x97, 0xbb, 0xa4, 0xd3, 0xc7, 0x25, 0x52,
+ 0x2d, 0x25, 0xec, 0xfd, 0x32, 0x6c, 0x6e, 0x48, 0x58, 0x32, 0x38, 0xe3,
+ 0x7c, 0x4d, 0xa4, 0x58, 0x32, 0x88, 0x43, 0x8a, 0xb5, 0x88, 0x5c, 0x0b,
+ 0x11, 0xea, 0x7b, 0x46, 0xb6, 0xfc, 0xb1, 0x93, 0x09, 0xe3, 0x5c, 0x0b,
+ 0xdf, 0x75, 0x7f, 0x3e, 0x22, 0x2a, 0x9d, 0x48, 0x66, 0x43, 0x93, 0x52,
+ 0x5d, 0x74, 0x9c, 0x39, 0xfb, 0x5e, 0xe0, 0xe8, 0x91, 0x39, 0xcb, 0x1d,
+ 0x67, 0xed, 0x07, 0xcd, 0x09, 0xb9, 0x1b, 0x73, 0x21, 0x51, 0xd6, 0x3d,
+ 0xf8, 0x8b, 0x1b, 0xb9, 0xb3, 0xdf, 0x32, 0xb2, 0xcb, 0xed, 0x52, 0x2c,
+ 0x3b, 0x32, 0x63, 0x4b, 0x26, 0x6b, 0xb7, 0x62, 0xfd, 0x63, 0x67, 0x66,
+ 0x6b, 0xcf, 0xb0, 0x99, 0x93, 0x26, 0xc9, 0x44, 0x63, 0x80, 0x59, 0x34,
+ 0x72, 0x17, 0xfe, 0xae, 0x5d, 0xda, 0x40, 0x4f, 0x8a, 0xe3, 0x8f, 0x9d,
+ 0x90, 0x65, 0x61, 0x9d, 0xe7, 0x63, 0x5c, 0x27, 0x5e, 0x7e, 0x13, 0xe7,
+ 0x35, 0xe7, 0xd2, 0x50, 0x4c, 0xbe, 0x5b, 0x8f, 0xca, 0x77, 0xea, 0xa6,
+ 0xbc, 0x5a, 0xef, 0x95, 0xcb, 0x75, 0xc7, 0xf9, 0x8e, 0xed, 0x38, 0x6f,
+ 0xe1, 0xef, 0x3f, 0xed, 0x2d, 0x1e, 0xd0, 0x0a, 0xc6, 0x44, 0xfd, 0x2f,
+ 0xda, 0xa5, 0x33, 0x11, 0x17, 0xd5, 0x2e, 0xb3, 0xe5, 0x98, 0xcc, 0x95,
+ 0x4b, 0xc6, 0x13, 0x17, 0x16, 0x8c, 0xa9, 0x0b, 0x15, 0x9c, 0x19, 0xc6,
+ 0x9c, 0x14, 0x8a, 0xf6, 0x2b, 0x46, 0xae, 0x3e, 0x6f, 0x1c, 0xba, 0xd0,
+ 0x09, 0x1a, 0x79, 0xfe, 0x1e, 0x23, 0x7b, 0xf6, 0x96, 0x64, 0x6d, 0xca,
+ 0x38, 0x61, 0x7e, 0x0d, 0x62, 0xcf, 0x96, 0x48, 0x73, 0xb3, 0x47, 0xaf,
+ 0xe3, 0xa8, 0xb4, 0x73, 0x32, 0x9b, 0xb2, 0xcc, 0xa2, 0x90, 0x3e, 0x3d,
+ 0x77, 0xd9, 0xa5, 0xf9, 0xbc, 0x91, 0xbd, 0xd0, 0x6e, 0xe4, 0xce, 0x85,
+ 0x41, 0x87, 0xf4, 0x86, 0x84, 0xfb, 0x06, 0x62, 0x79, 0xa9, 0xe1, 0x0c,
+ 0x31, 0x55, 0x9a, 0x72, 0x05, 0xcd, 0xa0, 0xe5, 0xbb, 0x65, 0xf0, 0x50,
+ 0x06, 0x0f, 0x65, 0xf2, 0x16, 0x97, 0x4b, 0x43, 0x3e, 0x6f, 0x8e, 0xf3,
+ 0x23, 0x9b, 0xb4, 0x27, 0xe2, 0x19, 0xe5, 0xf3, 0xe9, 0x38, 0xff, 0x61,
+ 0x93, 0x57, 0xf2, 0xe3, 0x38, 0xaf, 0xda, 0x31, 0xd0, 0xee, 0x5c, 0x56,
+ 0x56, 0x09, 0xbc, 0x58, 0xc0, 0x4f, 0x59, 0x2f, 0x80, 0x87, 0x79, 0xf0,
+ 0x77, 0x1e, 0xbc, 0x55, 0x40, 0xc7, 0x2f, 0x3b, 0xaf, 0x60, 0xe4, 0x86,
+ 0xb6, 0xe4, 0x15, 0xa7, 0x8c, 0xf3, 0x2b, 0x0a, 0xb2, 0xde, 0x25, 0xf9,
+ 0x25, 0x53, 0xa6, 0x57, 0xfc, 0xfd, 0xbe, 0x1e, 0x1c, 0x93, 0x83, 0xe5,
+ 0x1e, 0xc8, 0x86, 0xb2, 0x4c, 0xd8, 0x22, 0x0e, 0x64, 0x54, 0x4c, 0x2a,
+ 0x11, 0x23, 0x6f, 0x9f, 0xd4, 0xf7, 0xbf, 0x62, 0x49, 0x26, 0x6f, 0x53,
+ 0x8e, 0x12, 0xcf, 0xdb, 0x85, 0x58, 0x18, 0xfa, 0xb6, 0x62, 0x15, 0xcc,
+ 0xb0, 0x50, 0x8e, 0x89, 0xd8, 0x1f, 0x43, 0x96, 0x47, 0x4b, 0x92, 0xf9,
+ 0x52, 0xc9, 0x97, 0xb1, 0x2b, 0xdf, 0xc7, 0x4b, 0x5f, 0xec, 0x90, 0x36,
+ 0xf5, 0x99, 0x26, 0xf9, 0x3d, 0xec, 0x25, 0xee, 0x3b, 0xf6, 0x62, 0x9f,
+ 0x0b, 0xe7, 0xee, 0x4d, 0x3c, 0x29, 0x42, 0xd8, 0x62, 0x7f, 0x93, 0xb6,
+ 0x11, 0x31, 0xb2, 0x56, 0x21, 0x16, 0x02, 0x5c, 0x5e, 0x8a, 0xa3, 0xde,
+ 0x5c, 0x53, 0xd6, 0xba, 0x15, 0x9a, 0xb3, 0x13, 0xf1, 0xa2, 0xdc, 0x0a,
+ 0x5d, 0xb5, 0xf5, 0x5c, 0x6b, 0xd6, 0x72, 0x64, 0x15, 0xd8, 0x9f, 0x83,
+ 0x3d, 0x6c, 0x80, 0xa3, 0xdf, 0x2d, 0xe9, 0xf9, 0x0e, 0xec, 0x4f, 0x36,
+ 0x01, 0x67, 0x9b, 0x24, 0x92, 0x55, 0xcc, 0x5f, 0x75, 0xe7, 0xbb, 0x5d,
+ 0xbc, 0xc5, 0xfe, 0x36, 0x8d, 0x5b, 0xe4, 0x15, 0x77, 0xfe, 0x2e, 0x17,
+ 0x77, 0xf1, 0x01, 0xcc, 0x03, 0xff, 0xe0, 0xe4, 0x90, 0xa1, 0xe7, 0xf7,
+ 0xd2, 0x9e, 0x7e, 0xa7, 0x74, 0x2b, 0xb4, 0x6a, 0x3b, 0x92, 0x1b, 0x1d,
+ 0x9c, 0x1c, 0x34, 0x5c, 0x7c, 0xa7, 0xdc, 0x7d, 0xf7, 0xb9, 0xf8, 0x06,
+ 0x27, 0x93, 0x86, 0x8b, 0x6f, 0xa5, 0xa4, 0xf7, 0x4a, 0xbe, 0x44, 0xd8,
+ 0xc1, 0x49, 0xcb, 0xb8, 0x4f, 0xa6, 0xbb, 0x07, 0x27, 0xfb, 0x0c, 0xf5,
+ 0x99, 0x5d, 0x2e, 0x1f, 0x09, 0x9f, 0x86, 0x5d, 0x9a, 0x06, 0x9e, 0xab,
+ 0xe7, 0x07, 0xb2, 0x56, 0xf1, 0x81, 0x5d, 0xfa, 0x7c, 0x9e, 0xa9, 0xe7,
+ 0x1e, 0x20, 0x5d, 0x3c, 0x7b, 0x66, 0xf4, 0x8e, 0x73, 0x7f, 0xe5, 0xb6,
+ 0x7c, 0x76, 0x3a, 0x93, 0xe7, 0x49, 0x24, 0x9c, 0x0e, 0x8f, 0xce, 0x95,
+ 0x8e, 0x49, 0xb6, 0x1c, 0x97, 0xd9, 0x91, 0x56, 0x99, 0x36, 0xfb, 0xa7,
+ 0x0f, 0x0a, 0x7d, 0x4f, 0x64, 0x74, 0xc6, 0xbb, 0xc3, 0x9c, 0x18, 0x32,
+ 0x0b, 0x1e, 0x0f, 0xd6, 0x24, 0x62, 0x00, 0xbe, 0xbf, 0x16, 0x96, 0xe7,
+ 0xeb, 0x86, 0x34, 0x6b, 0xfb, 0x4c, 0x98, 0xeb, 0xd0, 0xc3, 0x67, 0xcb,
+ 0xd4, 0x63, 0xea, 0xac, 0x64, 0xaa, 0x5a, 0x67, 0x7d, 0x7b, 0x6d, 0xe3,
+ 0xdd, 0x16, 0x0a, 0x02, 0x73, 0x4c, 0x5b, 0x66, 0x55, 0x5a, 0x24, 0x33,
+ 0x25, 0x85, 0xaa, 0xbd, 0x65, 0x3f, 0xb1, 0x65, 0xd9, 0x80, 0x1e, 0x88,
+ 0x99, 0x4d, 0x71, 0x9e, 0xf0, 0x0d, 0xb0, 0xa6, 0x6b, 0x7b, 0x21, 0xd8,
+ 0xde, 0x4c, 0x8a, 0xb0, 0x52, 0xd0, 0xfe, 0xa2, 0x0e, 0x7d, 0xac, 0xdf,
+ 0xd7, 0xe1, 0xfa, 0xbb, 0x08, 0x6c, 0xb4, 0x1d, 0x76, 0xfe, 0x19, 0xd8,
+ 0x60, 0xaf, 0x91, 0x3d, 0xe7, 0x38, 0xf0, 0x3f, 0x51, 0x25, 0xb4, 0x41,
+ 0xd8, 0x7b, 0x9d, 0x6b, 0xed, 0x98, 0x17, 0x73, 0xd6, 0xee, 0x06, 0x8f,
+ 0x8e, 0x33, 0x69, 0xc7, 0xa5, 0x68, 0x77, 0x61, 0x5f, 0x93, 0xf4, 0x58,
+ 0xd4, 0x79, 0xda, 0xf5, 0x2e, 0x9c, 0x67, 0x70, 0xdc, 0x89, 0xf3, 0x3a,
+ 0x30, 0x17, 0x9b, 0xa5, 0x2d, 0xa7, 0xe8, 0xb7, 0x5c, 0x1f, 0x2a, 0x72,
+ 0x1d, 0xb4, 0x72, 0x8f, 0x86, 0x8b, 0xb4, 0xa4, 0x53, 0x72, 0xb3, 0xb4,
+ 0x57, 0xae, 0x45, 0x29, 0x03, 0xe0, 0x2c, 0xc3, 0x27, 0x46, 0x0d, 0xd0,
+ 0x4f, 0xba, 0xe9, 0x03, 0x77, 0x7b, 0x63, 0xe3, 0x7e, 0xf7, 0x0c, 0x31,
+ 0x43, 0xe9, 0x4e, 0xc9, 0xe9, 0x39, 0x51, 0x6a, 0x74, 0x97, 0xb7, 0xde,
+ 0x69, 0xec, 0x3f, 0xa7, 0xe4, 0xc0, 0xc3, 0xf0, 0x5b, 0x38, 0xeb, 0xaa,
+ 0xe5, 0x38, 0x57, 0xed, 0xf7, 0x61, 0xf7, 0x4a, 0x9a, 0xac, 0x6b, 0x9d,
+ 0xd2, 0x46, 0x7b, 0x36, 0x1a, 0x64, 0x18, 0x93, 0x53, 0x65, 0xee, 0x29,
+ 0x48, 0xd8, 0x22, 0x0c, 0xe1, 0xff, 0x05, 0x70, 0x21, 0x69, 0x81, 0x3d,
+ 0x6e, 0xd8, 0x51, 0xd2, 0xdb, 0xe5, 0xc2, 0x77, 0xe3, 0x0c, 0xd2, 0x4e,
+ 0xfb, 0x73, 0xb4, 0xfd, 0x65, 0x43, 0x2a, 0x33, 0xb1, 0x08, 0x6b, 0x1a,
+ 0xa1, 0xbc, 0xb3, 0xdd, 0x70, 0xff, 0x32, 0x3b, 0x54, 0x30, 0x95, 0xbe,
+ 0x6f, 0x91, 0x5c, 0xe9, 0x7e, 0x99, 0xb3, 0x71, 0x9e, 0x15, 0x06, 0xcd,
+ 0xf4, 0x35, 0x03, 0x85, 0x90, 0x82, 0x95, 0xf5, 0x50, 0x56, 0x3e, 0xad,
+ 0xff, 0x8c, 0xf3, 0x0a, 0x46, 0xd8, 0xe2, 0x19, 0xbf, 0xe5, 0xc9, 0x87,
+ 0xba, 0x67, 0x4b, 0xb6, 0xd4, 0xce, 0x31, 0xe8, 0x68, 0xd3, 0x74, 0x84,
+ 0xd2, 0xfa, 0xee, 0x0c, 0x95, 0xf6, 0x63, 0x00, 0x41, 0xef, 0xc0, 0x03,
+ 0x3e, 0xb8, 0xd7, 0xc2, 0xde, 0x08, 0x68, 0xec, 0x68, 0xa0, 0xbf, 0x8d,
+ 0xf0, 0x90, 0x55, 0xc4, 0x3b, 0x43, 0xf3, 0x6d, 0xb8, 0x7c, 0xfb, 0xb2,
+ 0x7a, 0x1d, 0xb2, 0xfa, 0xc8, 0x39, 0x30, 0x46, 0x1c, 0x29, 0xe0, 0x80,
+ 0xdc, 0x4d, 0xfa, 0x2c, 0xfa, 0x29, 0x73, 0x0b, 0x17, 0x6c, 0x41, 0x85,
+ 0xd2, 0xed, 0x92, 0x33, 0x75, 0x1c, 0x00, 0xec, 0xb8, 0x68, 0x3f, 0x6f,
+ 0x91, 0x47, 0x6f, 0x6c, 0x25, 0xb4, 0xde, 0xe4, 0x2b, 0x8c, 0x05, 0x45,
+ 0xd0, 0xb6, 0x9e, 0x50, 0x9a, 0xb5, 0x76, 0xc8, 0x5c, 0x22, 0x4d, 0xe9,
+ 0xb7, 0x64, 0xb5, 0xa4, 0xf6, 0x34, 0x4b, 0x97, 0x4c, 0x41, 0x46, 0xd5,
+ 0x71, 0xc4, 0xb0, 0x91, 0x76, 0x09, 0x3d, 0xc4, 0x58, 0x10, 0x03, 0xad,
+ 0xeb, 0x09, 0x53, 0x6e, 0x39, 0x6a, 0x10, 0xfb, 0x47, 0x70, 0x0f, 0x87,
+ 0x79, 0xa7, 0xca, 0x83, 0x23, 0x4c, 0x88, 0x32, 0xef, 0x69, 0x16, 0xe2,
+ 0xe6, 0xda, 0x70, 0xcc, 0x14, 0xce, 0x23, 0x5e, 0x4e, 0x71, 0x2f, 0xf9,
+ 0x73, 0xf7, 0x7c, 0x92, 0x3f, 0x7f, 0x9d, 0x32, 0xa3, 0xec, 0xa0, 0x63,
+ 0xa0, 0xa9, 0x1b, 0x72, 0x1b, 0x5d, 0x80, 0x4f, 0xb4, 0x1f, 0xd7, 0x3a,
+ 0xdc, 0x37, 0x76, 0xaf, 0x5c, 0x83, 0xdd, 0xc5, 0x95, 0x18, 0x55, 0x7b,
+ 0xaf, 0x9e, 0x53, 0x96, 0x2f, 0x4f, 0xca, 0x60, 0xf7, 0x36, 0x19, 0x10,
+ 0xe7, 0xce, 0x72, 0x38, 0x52, 0x21, 0x0d, 0x2e, 0x2d, 0x73, 0xd6, 0x7a,
+ 0x22, 0x2c, 0x8d, 0xf4, 0x7c, 0xec, 0x28, 0xcb, 0x2a, 0xf4, 0x29, 0xe2,
+ 0x6f, 0x16, 0xb5, 0x27, 0x2c, 0x4f, 0x8c, 0x19, 0x12, 0x3f, 0xa4, 0xe4,
+ 0xd0, 0xc3, 0xc4, 0xf9, 0x13, 0xf2, 0x38, 0x9e, 0xe1, 0xfa, 0x18, 0x75,
+ 0x21, 0x8c, 0x5e, 0xf3, 0x87, 0xb9, 0x46, 0x5d, 0x7f, 0xdd, 0xd3, 0xf5,
+ 0x8f, 0x9c, 0x43, 0x63, 0x61, 0x0f, 0x36, 0xd2, 0x00, 0x2b, 0xb8, 0xef,
+ 0x9d, 0x60, 0x09, 0xd3, 0xa8, 0x17, 0x84, 0x2d, 0xec, 0x00, 0x8b, 0xe0,
+ 0xf4, 0x15, 0xda, 0x50, 0xb7, 0xe7, 0x33, 0x7c, 0x9b, 0xe2, 0x39, 0xec,
+ 0x77, 0xb2, 0x3f, 0xee, 0xe3, 0x7e, 0xc2, 0x6f, 0x8f, 0xa7, 0xb8, 0x06,
+ 0xd9, 0x31, 0xa6, 0xa2, 0x4d, 0xe2, 0x5b, 0xc1, 0xff, 0x34, 0xc6, 0x56,
+ 0xce, 0x99, 0x18, 0x4f, 0xa0, 0xb7, 0x24, 0x5f, 0xa3, 0x1d, 0x71, 0x3f,
+ 0x63, 0xed, 0xbb, 0x9e, 0xef, 0x6c, 0x9f, 0x0e, 0xa7, 0xa3, 0xf0, 0x9d,
+ 0x32, 0x55, 0x2c, 0x9d, 0x44, 0x3e, 0x24, 0x85, 0x7b, 0xd2, 0xd4, 0x8b,
+ 0xf6, 0x71, 0xf8, 0xc6, 0xa9, 0x62, 0x8d, 0x39, 0x11, 0xdc, 0x17, 0xf6,
+ 0x21, 0x3e, 0x47, 0xd4, 0x42, 0xa4, 0x70, 0x6f, 0x9a, 0x3e, 0x39, 0x2e,
+ 0xf1, 0xda, 0x7b, 0xc8, 0x39, 0x4c, 0xc9, 0x6a, 0x1d, 0xfb, 0xf6, 0x5e,
+ 0xd2, 0x5c, 0x44, 0xfe, 0x10, 0x4e, 0x4b, 0x58, 0xa5, 0x9b, 0x23, 0xb3,
+ 0xa9, 0x76, 0xe4, 0x59, 0x93, 0x7b, 0xd5, 0xda, 0xc1, 0xbd, 0xa1, 0xb5,
+ 0x3d, 0xd3, 0x4d, 0xe9, 0xc2, 0x5e, 0xb5, 0x20, 0xb2, 0x5c, 0x12, 0x85,
+ 0x9c, 0x26, 0x76, 0x44, 0x30, 0x5e, 0xfb, 0xf2, 0x97, 0x55, 0x3a, 0x24,
+ 0xf9, 0xa8, 0x9c, 0x58, 0x49, 0x85, 0x99, 0x3f, 0xc6, 0xa7, 0xe4, 0x04,
+ 0x72, 0xc6, 0x67, 0x64, 0xb6, 0x04, 0xba, 0x34, 0xdf, 0x31, 0xf0, 0xdb,
+ 0x0b, 0xdc, 0xa4, 0x3d, 0x0a, 0xdf, 0xea, 0xd2, 0x0e, 0x9a, 0x33, 0x39,
+ 0xe6, 0x48, 0x29, 0xc6, 0x94, 0xf7, 0xa0, 0x27, 0xb4, 0x93, 0x9f, 0xcb,
+ 0xaa, 0xd5, 0x2a, 0x79, 0xd7, 0x2f, 0x68, 0x3d, 0x0d, 0xa7, 0xdf, 0xf5,
+ 0xd6, 0xae, 0x63, 0x8d, 0xfa, 0xba, 0xab, 0xe1, 0xee, 0xbe, 0xa5, 0xf3,
+ 0x9c, 0xab, 0x36, 0xbf, 0x09, 0xfb, 0x83, 0x51, 0x17, 0xf6, 0xcd, 0xd1,
+ 0x55, 0xeb, 0x2b, 0x5d, 0xd2, 0x86, 0x73, 0xca, 0x3c, 0x27, 0x4a, 0xdf,
+ 0x8a, 0xf5, 0x6b, 0x1e, 0xae, 0x9f, 0x02, 0x57, 0x3b, 0xe9, 0x46, 0x0b,
+ 0x63, 0x1d, 0xf4, 0x21, 0xdf, 0xc9, 0x6f, 0xf9, 0x18, 0xc2, 0xbe, 0xe6,
+ 0xe1, 0xfa, 0x5e, 0x03, 0x2e, 0xae, 0xb1, 0xe7, 0x99, 0x38, 0xbb, 0x8d,
+ 0xbc, 0x91, 0x1f, 0xde, 0x01, 0xef, 0x23, 0x69, 0x4c, 0xc1, 0xa7, 0x4f,
+ 0xd5, 0x75, 0x5e, 0x67, 0xe4, 0xca, 0xc8, 0xb7, 0xea, 0x2f, 0x82, 0x46,
+ 0xe4, 0x61, 0xf5, 0x01, 0x2f, 0xd7, 0xa6, 0xad, 0xac, 0x6b, 0x9f, 0x45,
+ 0x7f, 0x53, 0xd4, 0xf6, 0x74, 0x05, 0x63, 0x9d, 0x67, 0xe3, 0x6e, 0xae,
+ 0x48, 0x5f, 0xad, 0xdc, 0xe5, 0xfe, 0xbf, 0x6d, 0x53, 0x42, 0xfa, 0x3e,
+ 0x19, 0xd7, 0xa8, 0x67, 0x77, 0xc3, 0x9f, 0x3b, 0x1f, 0x30, 0xbe, 0x4c,
+ 0x31, 0xf6, 0x4c, 0x31, 0x66, 0x18, 0x9e, 0x1f, 0x8c, 0x37, 0xe0, 0x88,
+ 0x03, 0xc7, 0x79, 0x4f, 0x6f, 0x4f, 0x7b, 0xb8, 0xfc, 0xdc, 0xd3, 0xf7,
+ 0xa5, 0x2f, 0xdd, 0x73, 0xe7, 0xba, 0x61, 0xba, 0xe3, 0x66, 0xed, 0x87,
+ 0x61, 0xf7, 0xa0, 0x3f, 0x3e, 0xad, 0xa0, 0x5f, 0xb9, 0x9a, 0x7b, 0x1f,
+ 0xb0, 0x71, 0xe8, 0x1e, 0x3f, 0xfd, 0xbb, 0x75, 0x73, 0x6f, 0x57, 0x06,
+ 0xbc, 0xd3, 0x0c, 0xf9, 0xce, 0x84, 0x49, 0x4b, 0x7d, 0x12, 0xfb, 0xe5,
+ 0x18, 0x63, 0x62, 0x1e, 0x7c, 0x1c, 0x31, 0x87, 0xcd, 0x59, 0xe2, 0x8e,
+ 0x0a, 0x70, 0x22, 0x8f, 0x4c, 0xb7, 0x78, 0xf7, 0xfc, 0x7d, 0x9e, 0x0f,
+ 0xdc, 0xbb, 0x38, 0x46, 0xff, 0x7d, 0x8f, 0x9e, 0x1b, 0x9d, 0x2e, 0x3d,
+ 0xfe, 0xfa, 0x80, 0x79, 0xe7, 0x78, 0x75, 0xaf, 0x27, 0x4f, 0x7c, 0x3f,
+ 0xe3, 0xd1, 0xc5, 0xbb, 0x69, 0xa4, 0x89, 0xf7, 0xf2, 0x5f, 0xc0, 0xa3,
+ 0xf3, 0x8c, 0x82, 0x4a, 0x23, 0x6f, 0x49, 0x31, 0x56, 0xc1, 0xe6, 0xc5,
+ 0xc2, 0x9d, 0x24, 0xec, 0x69, 0xec, 0x7a, 0xb7, 0xc4, 0x7b, 0xbe, 0x05,
+ 0x1f, 0xcd, 0x7b, 0xff, 0x50, 0xe6, 0x4a, 0xfd, 0x76, 0xb3, 0x41, 0x7b,
+ 0x4d, 0x24, 0xcf, 0xcb, 0xb0, 0x7d, 0x5e, 0xe7, 0x4f, 0x89, 0xf8, 0x29,
+ 0xa1, 0x6c, 0x6f, 0xc9, 0x80, 0xce, 0x6b, 0x3e, 0x14, 0x0b, 0x72, 0x99,
+ 0x2a, 0xc3, 0xc6, 0xc6, 0xfe, 0xcd, 0xd1, 0xf9, 0x28, 0xf2, 0xa5, 0x1b,
+ 0x3b, 0xe0, 0x7a, 0x53, 0xe3, 0x21, 0xbe, 0x46, 0x5c, 0x86, 0xb4, 0x8c,
+ 0xf9, 0xf8, 0x2c, 0x99, 0xaf, 0xfb, 0x38, 0xc3, 0xf0, 0xc3, 0xf0, 0x01,
+ 0x63, 0xbf, 0xe1, 0xe9, 0x0b, 0xbf, 0x7f, 0xe8, 0x30, 0x07, 0x52, 0xe9,
+ 0x3f, 0xf7, 0xe6, 0xae, 0x50, 0x06, 0x18, 0xfb, 0x72, 0x7f, 0xd1, 0xf3,
+ 0x39, 0x05, 0x23, 0x53, 0xa7, 0x0c, 0xa8, 0x2b, 0xb8, 0x7f, 0xad, 0x9f,
+ 0xb0, 0x99, 0xf2, 0x17, 0x10, 0x1f, 0xbb, 0xdd, 0xbc, 0x01, 0xb5, 0x55,
+ 0xa6, 0xce, 0xb9, 0xf5, 0x96, 0xac, 0xdd, 0xe4, 0xd9, 0xd2, 0x41, 0xcc,
+ 0x4d, 0xe1, 0x8f, 0xb2, 0x23, 0xcc, 0x61, 0x7c, 0x67, 0x3c, 0x38, 0x19,
+ 0xcf, 0x22, 0x66, 0x65, 0x0e, 0x4f, 0x60, 0x6c, 0x78, 0x35, 0x96, 0x96,
+ 0x7b, 0x05, 0x39, 0x0a, 0xe4, 0x39, 0x00, 0x7e, 0xe2, 0x32, 0x51, 0xc7,
+ 0x9d, 0x6f, 0xf9, 0xb3, 0x2d, 0x98, 0xc2, 0x6d, 0x18, 0xd7, 0xf7, 0x4d,
+ 0xd4, 0x7f, 0xec, 0xd0, 0x1f, 0xfc, 0xad, 0xb6, 0x97, 0x78, 0x43, 0xde,
+ 0x97, 0x31, 0x9e, 0x28, 0x4f, 0x1a, 0x87, 0xca, 0xdc, 0xa3, 0x5e, 0xea,
+ 0x11, 0x2b, 0x9e, 0x55, 0xc8, 0x51, 0xc7, 0x3a, 0x71, 0xe6, 0x29, 0xe8,
+ 0x46, 0xc1, 0x98, 0x1a, 0xea, 0x92, 0x7c, 0xb2, 0x07, 0x34, 0x3f, 0x82,
+ 0x1e, 0xb1, 0xc3, 0xfa, 0x35, 0xcc, 0x43, 0x8f, 0x92, 0xb4, 0x8f, 0x56,
+ 0x5d, 0x57, 0x4e, 0xeb, 0xb8, 0x35, 0xe0, 0xe9, 0xd6, 0x3f, 0x99, 0xae,
+ 0x2e, 0x3d, 0x8d, 0xf1, 0x2e, 0xcc, 0xff, 0x26, 0x7a, 0xc4, 0xac, 0x31,
+ 0x7f, 0x9e, 0x36, 0x38, 0x8e, 0xf9, 0xcf, 0x01, 0xc7, 0x9f, 0xe0, 0xfb,
+ 0x7e, 0x7c, 0xff, 0xd1, 0xb6, 0xbd, 0xdf, 0xe0, 0xd9, 0x98, 0xcf, 0x6e,
+ 0x9b, 0xf7, 0xfd, 0xb7, 0x8e, 0x93, 0xd2, 0xbd, 0x06, 0xc6, 0xd7, 0x22,
+ 0xb2, 0xfb, 0x7c, 0x9b, 0xa8, 0xaa, 0xeb, 0xc3, 0x55, 0xd5, 0x94, 0x9e,
+ 0xf3, 0xf4, 0xdf, 0x3f, 0xc2, 0x1e, 0x4b, 0xd4, 0x1a, 0x2e, 0x8d, 0x77,
+ 0xab, 0x6d, 0xf4, 0x99, 0xe3, 0x7d, 0x4b, 0xec, 0x0b, 0xc7, 0x47, 0x6b,
+ 0x84, 0xe1, 0xf7, 0x89, 0xe3, 0x7d, 0xb5, 0x9f, 0x00, 0x16, 0x72, 0x29,
+ 0xfb, 0xf8, 0x09, 0xff, 0xda, 0xb6, 0x33, 0xb5, 0x6c, 0x71, 0x26, 0xed,
+ 0xfe, 0x99, 0xe3, 0xd9, 0x0a, 0xf3, 0x83, 0x44, 0x4c, 0x74, 0x1e, 0x5e,
+ 0x38, 0x3e, 0x53, 0x0a, 0x4b, 0x48, 0xd3, 0xe2, 0xaf, 0x73, 0x8d, 0xf7,
+ 0xb0, 0x13, 0x6d, 0xa4, 0xab, 0x11, 0x0f, 0xe3, 0x0c, 0xf1, 0x9c, 0x00,
+ 0x9e, 0x24, 0xf0, 0x30, 0xde, 0xb8, 0xf4, 0xc6, 0x97, 0x76, 0xa2, 0x8d,
+ 0xb8, 0x78, 0x96, 0x8f, 0xaf, 0x47, 0xd4, 0xf9, 0xb7, 0x49, 0xaf, 0xc9,
+ 0x9c, 0xd6, 0xf5, 0x35, 0x4d, 0x92, 0x3f, 0x8b, 0xdc, 0xc6, 0x1e, 0xf3,
+ 0xc6, 0x77, 0x9b, 0xac, 0xb7, 0xe3, 0x8a, 0xf3, 0xec, 0xb1, 0x96, 0x8a,
+ 0x63, 0x0e, 0xe3, 0x65, 0x1f, 0x56, 0x79, 0xb0, 0x1d, 0x0d, 0x7c, 0x37,
+ 0x79, 0xb2, 0xe6, 0x99, 0x7e, 0xdd, 0xd9, 0x48, 0x0b, 0x40, 0x71, 0x0f,
+ 0xdd, 0x5b, 0xf7, 0xe0, 0xf3, 0x89, 0x85, 0x35, 0xd2, 0x96, 0x04, 0xaf,
+ 0x3e, 0x6d, 0x9f, 0xf6, 0xfe, 0xb8, 0x37, 0x89, 0x3f, 0xff, 0x3c, 0x5f,
+ 0x06, 0xa4, 0x8b, 0x3d, 0x74, 0xf9, 0x13, 0x75, 0x73, 0x12, 0x76, 0xc7,
+ 0x37, 0x10, 0xc7, 0x59, 0xb5, 0x29, 0xfb, 0x16, 0xdc, 0xbb, 0xf6, 0xb1,
+ 0xa8, 0x21, 0x14, 0x73, 0xb9, 0x38, 0xeb, 0xd5, 0xa3, 0xb2, 0x09, 0x5c,
+ 0x19, 0xd4, 0x94, 0x6e, 0x5d, 0x34, 0x0d, 0xff, 0xb8, 0x0e, 0xfd, 0xbc,
+ 0x6a, 0xf1, 0x2d, 0x26, 0xcc, 0x78, 0x27, 0xc5, 0xda, 0xcf, 0x01, 0xc3,
+ 0x3c, 0xea, 0xf6, 0x3b, 0xcb, 0x12, 0x60, 0x96, 0xb1, 0x76, 0xca, 0xf5,
+ 0xcb, 0xf4, 0xed, 0xc8, 0xa9, 0x50, 0xc3, 0x58, 0xff, 0xe3, 0xe4, 0xa3,
+ 0x8d, 0xb0, 0x3b, 0xbd, 0x83, 0x20, 0xe6, 0x2c, 0x26, 0xe6, 0x97, 0xe0,
+ 0xc3, 0x2b, 0x96, 0xda, 0xad, 0xb4, 0x46, 0x26, 0x2a, 0xf0, 0x49, 0xa8,
+ 0x78, 0x13, 0xf1, 0x25, 0x79, 0x5f, 0xdf, 0x43, 0x93, 0x35, 0x6c, 0xf6,
+ 0xa8, 0xaf, 0x52, 0xaf, 0x34, 0xe5, 0xa1, 0x33, 0x88, 0xcb, 0x23, 0x4f,
+ 0x20, 0xe6, 0x40, 0x5e, 0x67, 0x0a, 0xa8, 0xe2, 0xa9, 0x23, 0x3f, 0xf8,
+ 0x83, 0x19, 0xcb, 0xcd, 0xff, 0x75, 0x3c, 0x13, 0x97, 0xc7, 0xd0, 0x99,
+ 0x76, 0xed, 0x67, 0xf2, 0xda, 0xdf, 0xf4, 0x9b, 0x53, 0xaa, 0x0d, 0x39,
+ 0x06, 0x12, 0x4f, 0x64, 0x38, 0xe6, 0xa0, 0x48, 0x1f, 0xf3, 0x4e, 0xf8,
+ 0xe1, 0xbe, 0x35, 0x78, 0xb7, 0x33, 0x84, 0x57, 0x12, 0x3e, 0x13, 0x92,
+ 0xa6, 0x33, 0x7c, 0x0b, 0x91, 0x3d, 0xa8, 0xc3, 0x88, 0xb3, 0x2f, 0x8c,
+ 0x7e, 0x02, 0x7f, 0xfb, 0x90, 0x5f, 0x99, 0xc8, 0x8d, 0x77, 0x80, 0x07,
+ 0x2c, 0xf7, 0xec, 0x04, 0xdf, 0xd5, 0x2d, 0x6d, 0x11, 0xec, 0x21, 0x3c,
+ 0xf2, 0x43, 0x6b, 0x0f, 0xe8, 0x71, 0xcf, 0x27, 0x8e, 0xf0, 0x19, 0x91,
+ 0xfe, 0x05, 0xe9, 0x51, 0x7a, 0x4f, 0x58, 0x66, 0x52, 0x5c, 0x6b, 0x07,
+ 0x3c, 0xf7, 0x61, 0x4d, 0xef, 0x73, 0xdf, 0x94, 0xf2, 0xb7, 0xe9, 0xc6,
+ 0x9c, 0x81, 0x6f, 0xe4, 0x53, 0x29, 0x53, 0xfa, 0xab, 0x2e, 0x6c, 0xdf,
+ 0xda, 0x53, 0xdd, 0x7c, 0x97, 0x52, 0x96, 0x4b, 0x9b, 0x42, 0xee, 0x9b,
+ 0x87, 0x54, 0xc3, 0x83, 0x7c, 0x9b, 0x21, 0x0c, 0xeb, 0xd9, 0x2e, 0x0d,
+ 0x63, 0x0e, 0x52, 0x7e, 0xee, 0x9c, 0x52, 0xff, 0xd7, 0x9b, 0x4b, 0x63,
+ 0x4e, 0xa1, 0x6d, 0x05, 0xfb, 0xbf, 0xa9, 0x6d, 0x45, 0x54, 0xdc, 0xb3,
+ 0x15, 0x8c, 0x97, 0x39, 0xf6, 0x63, 0xf1, 0xf1, 0x7b, 0x5c, 0x7f, 0xef,
+ 0xc8, 0xac, 0xcd, 0xf7, 0x0b, 0x47, 0xae, 0xda, 0x05, 0xe3, 0xc0, 0x1d,
+ 0x79, 0x66, 0x52, 0xc7, 0xe7, 0x19, 0xc8, 0x7e, 0xb3, 0xa6, 0x6b, 0x35,
+ 0xb9, 0x56, 0x8b, 0xc8, 0x3b, 0x2b, 0x6d, 0xb2, 0xb9, 0xe4, 0xea, 0xfc,
+ 0xe6, 0x12, 0xf5, 0xdc, 0x94, 0x9f, 0xad, 0x58, 0x58, 0x4b, 0xe2, 0xaf,
+ 0x47, 0x6e, 0xac, 0xdc, 0x99, 0x77, 0x5e, 0xae, 0x3f, 0x0a, 0x5a, 0x7a,
+ 0x24, 0x64, 0x39, 0xba, 0xee, 0xca, 0x21, 0xf6, 0x15, 0x64, 0x42, 0xf2,
+ 0xe5, 0x7e, 0xd4, 0x7e, 0x08, 0xce, 0x61, 0xc6, 0x20, 0xdc, 0x7f, 0xf9,
+ 0xf3, 0xc8, 0x4d, 0x12, 0x30, 0x9e, 0x7e, 0xfd, 0xa6, 0xf8, 0xc5, 0x70,
+ 0x8f, 0x34, 0x5b, 0xdf, 0xec, 0x76, 0x63, 0x95, 0xe9, 0xd6, 0xa7, 0x96,
+ 0x1f, 0xaf, 0xdf, 0x04, 0xee, 0x11, 0xe8, 0x29, 0x75, 0xd3, 0x86, 0xce,
+ 0x9a, 0xb2, 0x3a, 0x94, 0xa8, 0x14, 0x84, 0xfe, 0x21, 0xc5, 0x7c, 0x11,
+ 0xfb, 0x92, 0x90, 0x47, 0xab, 0xce, 0x85, 0x32, 0x0a, 0x77, 0xbb, 0x30,
+ 0x27, 0xf9, 0xfa, 0xef, 0x63, 0x3e, 0x23, 0xd3, 0xf5, 0x71, 0x9c, 0x75,
+ 0x1a, 0x7a, 0xfb, 0x60, 0x8f, 0xb4, 0xf1, 0x9c, 0x14, 0x68, 0x7c, 0x44,
+ 0x66, 0xce, 0xce, 0xc9, 0x91, 0x32, 0xe9, 0xe4, 0x1b, 0x63, 0x22, 0x99,
+ 0x93, 0xe1, 0xf8, 0x0a, 0x72, 0x27, 0xd7, 0x1e, 0xd3, 0x32, 0x73, 0x0e,
+ 0x38, 0xca, 0xac, 0xff, 0xfb, 0xa1, 0x37, 0xc3, 0xba, 0x7e, 0x99, 0xd6,
+ 0x7e, 0x87, 0xf3, 0x6f, 0xe3, 0x9e, 0xfa, 0x0b, 0xfb, 0x00, 0x97, 0x47,
+ 0xad, 0x33, 0x85, 0x7c, 0x79, 0xb9, 0x8c, 0x3a, 0xcf, 0x0e, 0x31, 0xf7,
+ 0x52, 0xea, 0xa1, 0x5e, 0xa9, 0x96, 0x87, 0x4d, 0xa5, 0x98, 0x53, 0xf1,
+ 0x2e, 0xb8, 0x46, 0xfb, 0x8e, 0xa9, 0xb0, 0xd5, 0x2b, 0x2b, 0xe5, 0x02,
+ 0xea, 0x65, 0xe5, 0xbd, 0x67, 0x14, 0xc4, 0xb4, 0x5c, 0xbf, 0xa7, 0x6b,
+ 0x1b, 0xe6, 0x9f, 0xf5, 0x2f, 0x80, 0xc6, 0x0c, 0x2e, 0xf3, 0x24, 0xe8,
+ 0xc3, 0xf7, 0x32, 0x74, 0x7c, 0x81, 0x39, 0x5c, 0x06, 0x6b, 0x69, 0x39,
+ 0x76, 0x61, 0x0a, 0x34, 0x74, 0x4a, 0xff, 0x9f, 0xd1, 0xc6, 0x9e, 0xc4,
+ 0x1c, 0xc7, 0x09, 0xe8, 0xeb, 0xd7, 0xf1, 0x4d, 0xd8, 0x18, 0x7a, 0xca,
+ 0xa1, 0x17, 0xbd, 0x09, 0x5a, 0x58, 0x07, 0x43, 0xfe, 0x87, 0xe3, 0x52,
+ 0x3d, 0xfb, 0xb0, 0x4c, 0x2f, 0x3f, 0x0c, 0xfc, 0xff, 0x8a, 0xba, 0x00,
+ 0xf1, 0x6d, 0x99, 0x67, 0x31, 0xff, 0xe3, 0x39, 0x10, 0x10, 0x6d, 0x63,
+ 0x81, 0xf3, 0xec, 0x0f, 0x62, 0x3f, 0x6a, 0x8c, 0x72, 0x46, 0x66, 0xca,
+ 0x3c, 0x0b, 0x77, 0x87, 0x7c, 0x2a, 0x7f, 0x76, 0xca, 0xbb, 0xe3, 0x1e,
+ 0xc9, 0x45, 0x0b, 0xac, 0x2f, 0x10, 0x27, 0x96, 0x46, 0xb3, 0xa5, 0x84,
+ 0x99, 0x55, 0xc4, 0x95, 0x14, 0xc6, 0x06, 0x77, 0x2e, 0x22, 0xd6, 0x02,
+ 0x6a, 0xda, 0x34, 0xd7, 0x4e, 0x7a, 0x6f, 0x06, 0xc4, 0xf5, 0x63, 0x99,
+ 0x80, 0x8e, 0xf5, 0x2f, 0x8c, 0x20, 0x17, 0xfe, 0x29, 0x72, 0xc9, 0xb8,
+ 0x27, 0x83, 0x71, 0x4f, 0x37, 0xda, 0x1a, 0x74, 0x02, 0xf7, 0x5c, 0xc6,
+ 0xdd, 0x97, 0xa1, 0x07, 0xf0, 0xd5, 0xaf, 0x6e, 0xe9, 0xc7, 0x78, 0x43,
+ 0x8e, 0xd9, 0x21, 0xff, 0x50, 0x49, 0x24, 0xd7, 0xa1, 0x3f, 0x37, 0x50,
+ 0x0b, 0xac, 0xa3, 0x3e, 0xdc, 0xb4, 0x23, 0xa8, 0x4b, 0x0e, 0x83, 0x7e,
+ 0xe6, 0x94, 0x1c, 0xc7, 0x74, 0xae, 0xd3, 0x62, 0x3d, 0x7f, 0x8f, 0x7e,
+ 0xd7, 0x95, 0xaf, 0xf6, 0xb0, 0xa6, 0x64, 0x3d, 0xce, 0x37, 0xe9, 0x77,
+ 0x70, 0x8f, 0xeb, 0x26, 0xd7, 0xfd, 0x7d, 0xac, 0x05, 0x7c, 0xfd, 0x21,
+ 0x2d, 0xd4, 0x1f, 0xee, 0x21, 0x4c, 0x8f, 0xb6, 0x93, 0xbc, 0xc6, 0x47,
+ 0x9d, 0xfd, 0x9b, 0x6e, 0xd7, 0xce, 0x74, 0x9e, 0x65, 0x5e, 0x13, 0x5f,
+ 0x7f, 0x3f, 0x74, 0x58, 0xd7, 0x65, 0x87, 0xe0, 0xbb, 0xeb, 0x8e, 0xbc,
+ 0x60, 0xdf, 0x69, 0x77, 0xfb, 0xcb, 0xbe, 0x9c, 0x28, 0xc7, 0xc3, 0x72,
+ 0xaa, 0x9e, 0x80, 0x4d, 0x50, 0x86, 0x56, 0x83, 0x0c, 0x45, 0xfe, 0xaa,
+ 0x2c, 0xf2, 0x4a, 0x99, 0x6b, 0x5a, 0x86, 0xb1, 0x6c, 0xa8, 0x8d, 0xef,
+ 0xea, 0xd0, 0xcb, 0xb7, 0xe5, 0xc8, 0xa2, 0xc8, 0x05, 0xac, 0xaf, 0x96,
+ 0x69, 0xab, 0x23, 0xc8, 0x5f, 0x77, 0x49, 0x75, 0x09, 0x35, 0x59, 0x59,
+ 0xa6, 0xb3, 0x9f, 0x63, 0xbc, 0x89, 0xc8, 0xa6, 0x7e, 0x8f, 0x15, 0x19,
+ 0xbc, 0x18, 0x96, 0xf0, 0x45, 0x14, 0x7f, 0x90, 0xfd, 0xa5, 0x21, 0xff,
+ 0x7d, 0xd6, 0xb5, 0xf9, 0x62, 0x09, 0x7b, 0xcb, 0xfd, 0xda, 0x4f, 0x16,
+ 0x6b, 0x33, 0x92, 0xaf, 0xf0, 0x2c, 0xf4, 0x4b, 0x71, 0xac, 0xa5, 0x64,
+ 0xf6, 0xec, 0x88, 0x3c, 0x8b, 0x33, 0x50, 0xff, 0xe1, 0x8c, 0x09, 0x29,
+ 0x5c, 0xc0, 0x7c, 0xed, 0xba, 0x2c, 0xad, 0xcc, 0x48, 0xb5, 0x72, 0xb9,
+ 0xe1, 0xdd, 0x1d, 0xe3, 0xa5, 0xc6, 0x5a, 0xf6, 0x30, 0xeb, 0x19, 0xd4,
+ 0xaa, 0x16, 0xc6, 0x90, 0x59, 0x6d, 0x76, 0xfa, 0xce, 0xf7, 0xe2, 0xc6,
+ 0x1a, 0x76, 0x52, 0xe6, 0xcb, 0x29, 0x29, 0x9e, 0x1d, 0xd1, 0x6f, 0x0a,
+ 0x2d, 0xe9, 0xca, 0xd3, 0x37, 0x11, 0x2b, 0x26, 0xf5, 0x7b, 0xf1, 0x2d,
+ 0x79, 0xcc, 0x9e, 0x97, 0xa3, 0xd6, 0x41, 0x39, 0x85, 0xfc, 0xfa, 0x4b,
+ 0x76, 0xab, 0xc4, 0xbb, 0x79, 0x8f, 0xa0, 0xd7, 0x62, 0x0d, 0xea, 0xc8,
+ 0x84, 0xfd, 0xa0, 0xf9, 0x3c, 0x24, 0xfb, 0x4e, 0x8d, 0x71, 0xf2, 0xbf,
+ 0x9d, 0x0c, 0xe2, 0xde, 0x4d, 0xd4, 0x8e, 0x19, 0x0d, 0x67, 0xb8, 0x70,
+ 0x15, 0xc2, 0x0d, 0x9b, 0x2f, 0x10, 0x6e, 0xc9, 0xf0, 0xe0, 0x0c, 0xc0,
+ 0x85, 0x64, 0xc3, 0x0e, 0x43, 0x47, 0x26, 0xc1, 0x27, 0x7c, 0xfc, 0x68,
+ 0x87, 0x97, 0x07, 0xb7, 0x22, 0xb6, 0xde, 0xde, 0xff, 0x86, 0xb7, 0xff,
+ 0x59, 0x6f, 0xff, 0xd5, 0xad, 0xfd, 0x7e, 0x7c, 0xfd, 0x85, 0x23, 0x0d,
+ 0x74, 0xbd, 0x51, 0x72, 0xe1, 0xe7, 0x3d, 0xba, 0xae, 0x6e, 0xd1, 0xe5,
+ 0xc3, 0x43, 0x9e, 0x9a, 0x67, 0xfa, 0x66, 0xfa, 0xe8, 0x7e, 0xc8, 0xd1,
+ 0x91, 0x9c, 0x0d, 0xdb, 0x28, 0x27, 0xc6, 0x0b, 0xfa, 0x2d, 0x4d, 0xc9,
+ 0x7a, 0x74, 0x5e, 0x26, 0xad, 0xc4, 0xf8, 0xac, 0x84, 0xa0, 0xcb, 0xf4,
+ 0x2d, 0x21, 0xa9, 0xd2, 0xe7, 0xa0, 0xcf, 0xdb, 0x3b, 0xd3, 0xfa, 0x4e,
+ 0x03, 0xad, 0xa1, 0x97, 0x49, 0xa3, 0x4b, 0x6b, 0x64, 0xe0, 0x36, 0xad,
+ 0x2e, 0xbc, 0x4b, 0xeb, 0x3b, 0xa5, 0x06, 0xf8, 0x8b, 0x61, 0x0f, 0x3e,
+ 0xdc, 0x00, 0x4f, 0x7d, 0x66, 0x5e, 0x41, 0x7d, 0x26, 0x6d, 0x9f, 0x85,
+ 0x6d, 0x48, 0xa4, 0x35, 0x5d, 0x39, 0xfe, 0xc0, 0x80, 0x23, 0x11, 0xe4,
+ 0x1b, 0xcd, 0x58, 0xdb, 0xac, 0x30, 0x17, 0x51, 0x7d, 0xcd, 0x32, 0x08,
+ 0x9d, 0xe5, 0xdd, 0xb9, 0x6f, 0x82, 0x8f, 0xe9, 0x9c, 0xc0, 0x91, 0xa3,
+ 0x36, 0x69, 0x79, 0xdf, 0x79, 0x25, 0x3a, 0x68, 0x17, 0x65, 0xc8, 0x6c,
+ 0xc6, 0xf9, 0xd5, 0xba, 0xc6, 0x99, 0x24, 0x2d, 0xe7, 0x87, 0xfa, 0xcd,
+ 0xbf, 0x07, 0x9f, 0x13, 0x15, 0x43, 0xaa, 0x56, 0x22, 0x76, 0x09, 0x38,
+ 0xf6, 0xe1, 0x6e, 0xaa, 0x23, 0xa4, 0x47, 0xe4, 0x08, 0xf4, 0xbb, 0xaa,
+ 0xe3, 0x22, 0xf5, 0x38, 0x31, 0x59, 0x40, 0xae, 0xf3, 0xd7, 0x3a, 0xb6,
+ 0x39, 0xce, 0x4d, 0xc4, 0xb7, 0xc9, 0x6d, 0xba, 0xa7, 0x2e, 0xba, 0xba,
+ 0xa7, 0x2e, 0xa2, 0x06, 0x3e, 0x1d, 0x91, 0x96, 0x55, 0xd8, 0xcf, 0xcb,
+ 0x7b, 0xdc, 0x7c, 0xee, 0x65, 0xfe, 0xe6, 0x04, 0x7f, 0x77, 0x3a, 0x2c,
+ 0xd6, 0x69, 0x1d, 0x0f, 0x20, 0xef, 0x09, 0x99, 0x3d, 0x47, 0x9f, 0x6a,
+ 0xc9, 0xc0, 0x69, 0xde, 0x07, 0xf3, 0x9a, 0xa5, 0xd1, 0x19, 0xd8, 0xc8,
+ 0x1c, 0xfc, 0x82, 0x5a, 0x7d, 0x57, 0x66, 0x2c, 0xca, 0xa1, 0x53, 0xda,
+ 0x56, 0x51, 0x8f, 0xaf, 0xc2, 0x37, 0xac, 0xc6, 0xa4, 0x09, 0xb6, 0xa5,
+ 0x2e, 0x46, 0x8d, 0xe2, 0xe2, 0x07, 0xb0, 0x07, 0xfe, 0x7e, 0x83, 0xdc,
+ 0xf2, 0x62, 0xcc, 0xa0, 0x6d, 0xa9, 0x8b, 0xd4, 0x73, 0xa4, 0x53, 0x17,
+ 0xa9, 0xe7, 0xa4, 0xc3, 0xb7, 0x17, 0x7c, 0x5f, 0x1c, 0xd1, 0xef, 0xd3,
+ 0x37, 0x6d, 0xf2, 0xf2, 0x8f, 0x92, 0xad, 0x30, 0x47, 0x24, 0x3f, 0xd2,
+ 0x8d, 0x5c, 0xa6, 0x2b, 0x6b, 0x0f, 0x8c, 0x6f, 0xca, 0xa7, 0xe5, 0xeb,
+ 0xee, 0x4f, 0xc1, 0x17, 0xf9, 0x68, 0xe4, 0x8b, 0x3c, 0x75, 0x4a, 0x93,
+ 0xe6, 0xcb, 0xe7, 0x07, 0x82, 0x06, 0x3f, 0x7d, 0xa7, 0x63, 0xc0, 0xff,
+ 0x75, 0xf8, 0x80, 0x5e, 0xf4, 0x4f, 0xa2, 0x47, 0x48, 0xbb, 0x48, 0xde,
+ 0xc9, 0xeb, 0x0d, 0xe4, 0x8d, 0x3e, 0x9f, 0xd3, 0xf8, 0x7e, 0x5d, 0x66,
+ 0x17, 0x9d, 0x93, 0x88, 0xab, 0x7c, 0x3b, 0xef, 0x71, 0xdf, 0x81, 0xb7,
+ 0xf3, 0xfe, 0xba, 0xb8, 0xf2, 0x49, 0x98, 0x55, 0xc1, 0xf7, 0xca, 0x76,
+ 0x59, 0x34, 0xfa, 0x8e, 0x98, 0xce, 0xc3, 0x8f, 0xd4, 0xe8, 0x27, 0x28,
+ 0xa3, 0x1b, 0x92, 0x5d, 0xe4, 0xfb, 0x97, 0x8b, 0x6f, 0xba, 0xe6, 0xfb,
+ 0x8d, 0xc6, 0x3d, 0x36, 0xe0, 0x7a, 0x01, 0x47, 0xba, 0xd6, 0x29, 0x3f,
+ 0xf8, 0x9c, 0xbd, 0x0d, 0xbe, 0xa6, 0x71, 0xdf, 0xb8, 0x3c, 0x87, 0x3c,
+ 0xe0, 0x0d, 0xfb, 0x0e, 0xb9, 0x4e, 0x33, 0x17, 0xaa, 0xd6, 0xa6, 0x60,
+ 0x93, 0x4d, 0xf0, 0x65, 0xa6, 0x6c, 0x96, 0x9a, 0xa5, 0x8a, 0x7c, 0x67,
+ 0x79, 0x85, 0xbe, 0x90, 0xb4, 0xb7, 0x61, 0xde, 0xf5, 0x5f, 0xf4, 0xb5,
+ 0x9b, 0x25, 0xc4, 0x59, 0xd8, 0xf6, 0x66, 0x29, 0x8a, 0xbe, 0x17, 0xbd,
+ 0x85, 0x3e, 0x8e, 0x3e, 0x89, 0x7e, 0x04, 0xfd, 0x08, 0x7a, 0x0b, 0x7b,
+ 0x63, 0xe8, 0xfd, 0x9a, 0x81, 0xb8, 0x6e, 0xf3, 0x5d, 0xd4, 0xe7, 0x21,
+ 0x57, 0xb4, 0x18, 0xd3, 0xc2, 0x76, 0x0e, 0x75, 0x44, 0x76, 0x84, 0xb9,
+ 0x1e, 0x73, 0xbe, 0x8f, 0x1d, 0xd3, 0x62, 0x5d, 0x5e, 0x30, 0xf6, 0x0d,
+ 0x31, 0x2e, 0x54, 0x10, 0x17, 0x3e, 0xd8, 0x8d, 0xfa, 0xd1, 0xdc, 0xaf,
+ 0xdf, 0x8e, 0x16, 0x31, 0xe6, 0x37, 0x6a, 0xde, 0xe8, 0x1c, 0xe2, 0x14,
+ 0xfd, 0xa7, 0x83, 0x3d, 0x79, 0xf8, 0xf1, 0x2e, 0xd8, 0x5f, 0x06, 0x7e,
+ 0x1b, 0xdf, 0x4b, 0x6f, 0xec, 0x76, 0x63, 0x2a, 0xf2, 0x77, 0xb5, 0xfd,
+ 0xbd, 0xc6, 0xc6, 0x9e, 0x9d, 0x6a, 0x83, 0x0e, 0xe0, 0x48, 0x54, 0x96,
+ 0x60, 0x83, 0x3f, 0xb4, 0x4f, 0xea, 0xdc, 0x8e, 0x77, 0xf1, 0x2c, 0x72,
+ 0xd4, 0xdc, 0x02, 0x73, 0x98, 0x13, 0xa8, 0x4b, 0x50, 0x9f, 0x45, 0x59,
+ 0x93, 0x33, 0x16, 0xe8, 0x5c, 0x34, 0x2a, 0x6d, 0x8c, 0x03, 0x37, 0x70,
+ 0x1e, 0xf8, 0x5a, 0x76, 0x20, 0xb3, 0x03, 0xc8, 0x09, 0x1d, 0x27, 0x6c,
+ 0xed, 0x93, 0xf8, 0x21, 0xfa, 0x1c, 0xc1, 0x7e, 0x53, 0xdc, 0xf7, 0x74,
+ 0xf8, 0xdd, 0x29, 0xfd, 0x5b, 0x31, 0x94, 0xeb, 0xb3, 0xd8, 0x7b, 0x17,
+ 0x70, 0x71, 0x9e, 0x6f, 0xd9, 0x22, 0xfb, 0x16, 0xdc, 0x9c, 0x56, 0x59,
+ 0x8d, 0xf8, 0x7e, 0xd5, 0xc3, 0xc7, 0x75, 0xe5, 0xfd, 0xa6, 0xb1, 0xc7,
+ 0x7d, 0x1b, 0xc6, 0x1d, 0x9f, 0x42, 0xfe, 0xbc, 0x81, 0x7b, 0x79, 0x03,
+ 0x77, 0x72, 0xa5, 0x44, 0x5d, 0x1f, 0x86, 0xde, 0x43, 0x86, 0x53, 0xc4,
+ 0x35, 0xa2, 0xcf, 0xde, 0x28, 0xc1, 0x77, 0xd2, 0xff, 0x29, 0x64, 0x77,
+ 0x6d, 0x6e, 0x4c, 0x77, 0xf1, 0xf4, 0xba, 0x70, 0xe2, 0xaf, 0xed, 0xd6,
+ 0xf4, 0x54, 0xf5, 0x3b, 0x18, 0xe5, 0x04, 0x1d, 0xe4, 0x6f, 0x03, 0x1a,
+ 0xe6, 0x6b, 0x51, 0xfd, 0xfe, 0xae, 0x38, 0x47, 0x3e, 0x46, 0x24, 0xbb,
+ 0xe0, 0xef, 0xeb, 0xc6, 0xbe, 0xd6, 0x06, 0x5c, 0x77, 0x6f, 0xe3, 0x41,
+ 0x79, 0x3c, 0x70, 0xfd, 0x93, 0x6f, 0xc3, 0x85, 0xad, 0xb7, 0x61, 0xc6,
+ 0x5f, 0xde, 0x4d, 0x0a, 0xfb, 0xfd, 0xfb, 0xe9, 0xf5, 0x6a, 0x81, 0xc4,
+ 0x7c, 0x41, 0x98, 0xab, 0xf0, 0x8e, 0xc6, 0x61, 0xd7, 0x5d, 0xc0, 0x6f,
+ 0x4b, 0xa5, 0xd4, 0x22, 0xaa, 0x87, 0xb5, 0x31, 0x73, 0xe5, 0xc6, 0x33,
+ 0x7f, 0xdb, 0x3b, 0x13, 0xf5, 0xf4, 0x19, 0xe6, 0xcd, 0x3a, 0xce, 0x00,
+ 0xa6, 0x7d, 0x1b, 0x6d, 0xbf, 0xee, 0xc1, 0x71, 0x3d, 0x29, 0x05, 0xe4,
+ 0xa1, 0xb9, 0x05, 0x64, 0xf4, 0xf0, 0xdf, 0x2a, 0xcd, 0xdf, 0xb3, 0xf8,
+ 0x86, 0x37, 0x1c, 0x9f, 0x05, 0x8d, 0x05, 0x33, 0xc3, 0x77, 0x33, 0xe0,
+ 0xd8, 0xbb, 0x0d, 0xc7, 0x84, 0x87, 0x63, 0x42, 0x8a, 0xe7, 0x26, 0x61,
+ 0x6b, 0x19, 0xc4, 0xf7, 0x7e, 0xf3, 0x80, 0x7c, 0x1e, 0xc5, 0x35, 0xe6,
+ 0x2e, 0x8c, 0xe0, 0x9e, 0x1c, 0x67, 0x9f, 0x7d, 0x18, 0x74, 0xbf, 0x86,
+ 0xd8, 0xea, 0xe7, 0x3c, 0xc5, 0x58, 0x08, 0x31, 0xec, 0x98, 0xfe, 0x0d,
+ 0xb6, 0x60, 0x9a, 0xd0, 0x57, 0x65, 0x0c, 0x27, 0x51, 0xde, 0x23, 0xbe,
+ 0xcd, 0x23, 0x56, 0x91, 0xcf, 0x0e, 0x29, 0x9a, 0xc6, 0xa3, 0x21, 0xe4,
+ 0x35, 0xd9, 0x05, 0xda, 0x91, 0x0c, 0x84, 0xd2, 0xcd, 0xc8, 0x49, 0x1d,
+ 0xf9, 0x99, 0xcd, 0x7f, 0xa3, 0x30, 0x2f, 0x1b, 0x35, 0x13, 0xfd, 0x3a,
+ 0xee, 0xe1, 0xdb, 0xf8, 0xbe, 0xde, 0x83, 0xbc, 0x0f, 0x2b, 0x19, 0xe8,
+ 0x6e, 0x52, 0xe7, 0x33, 0xcc, 0x23, 0xaa, 0x88, 0xb7, 0x0a, 0xb1, 0x06,
+ 0x79, 0xd5, 0x38, 0x73, 0xd7, 0xe7, 0x96, 0xaf, 0xcb, 0x95, 0x45, 0xfe,
+ 0x06, 0xca, 0xb8, 0x7c, 0x90, 0xfe, 0xc0, 0x9c, 0x4b, 0x61, 0x6e, 0x85,
+ 0xbe, 0x0c, 0xe3, 0x3a, 0x0c, 0xa8, 0x07, 0x39, 0x02, 0x72, 0xed, 0x4d,
+ 0x2b, 0x09, 0x3e, 0xaf, 0xcb, 0xc6, 0x62, 0x58, 0x96, 0x2d, 0xe6, 0x45,
+ 0x12, 0xcf, 0x02, 0x76, 0x63, 0xe5, 0x9a, 0xab, 0x13, 0x84, 0x47, 0xcd,
+ 0x53, 0x40, 0x5e, 0x77, 0x40, 0xef, 0xfd, 0x65, 0xf7, 0x4c, 0x9a, 0x1a,
+ 0xeb, 0xbc, 0x19, 0xd9, 0xa0, 0x3d, 0xd9, 0x7c, 0x93, 0x62, 0x6e, 0x70,
+ 0x02, 0x3a, 0xcb, 0xdc, 0x9d, 0xf5, 0x00, 0xbe, 0x6b, 0x5c, 0x27, 0xef,
+ 0xe8, 0x97, 0xfa, 0x21, 0x1b, 0xda, 0x3d, 0xdf, 0xc4, 0x10, 0x47, 0x15,
+ 0x6d, 0xbd, 0xa8, 0x7d, 0x41, 0xb1, 0x3c, 0x83, 0x98, 0x02, 0x1f, 0xc0,
+ 0xdf, 0x70, 0xa6, 0xa6, 0x70, 0x97, 0xe3, 0x80, 0xdb, 0x16, 0x4b, 0xd6,
+ 0x8a, 0x3a, 0x2f, 0x53, 0xe7, 0x6f, 0xbf, 0xdf, 0xe4, 0x61, 0x3f, 0x6a,
+ 0x0d, 0xba, 0x05, 0x1b, 0x52, 0x6b, 0x51, 0xf4, 0xf0, 0xc7, 0x6b, 0xa8,
+ 0x2f, 0x4a, 0x7c, 0x1f, 0x42, 0x6d, 0x50, 0xe2, 0xdb, 0x49, 0x12, 0xfd,
+ 0x08, 0xdf, 0x8b, 0x3c, 0xbf, 0x46, 0xfc, 0xa4, 0xc3, 0xf7, 0x2f, 0xcc,
+ 0x25, 0xe9, 0x5f, 0xfc, 0x7c, 0xd2, 0xd5, 0x85, 0x53, 0x65, 0xfa, 0x10,
+ 0xea, 0x75, 0x3f, 0xfc, 0x16, 0x75, 0xc1, 0xcd, 0x25, 0x57, 0x2a, 0xae,
+ 0xcc, 0x66, 0xeb, 0x97, 0x75, 0x8c, 0xd8, 0x2f, 0x16, 0x74, 0x8c, 0xb2,
+ 0xc3, 0x9a, 0x8e, 0x01, 0x97, 0x24, 0xa3, 0x7b, 0xca, 0xec, 0x75, 0xc9,
+ 0xac, 0x8c, 0xc8, 0x0b, 0xda, 0x6f, 0xf9, 0x3e, 0x8b, 0x39, 0x64, 0x0c,
+ 0xf2, 0x4b, 0xca, 0xf3, 0x67, 0xaf, 0x4b, 0xf6, 0x45, 0xfa, 0xad, 0xe1,
+ 0x58, 0xab, 0x41, 0x5f, 0xe5, 0x48, 0x0d, 0xb1, 0xe9, 0x80, 0xcd, 0x7f,
+ 0x07, 0x10, 0x42, 0x4d, 0xe7, 0x48, 0xf3, 0x68, 0xc2, 0x8e, 0x1b, 0xfd,
+ 0x4f, 0xb6, 0x1a, 0x8c, 0x8d, 0xc3, 0xe6, 0x53, 0xe2, 0xbf, 0x47, 0xb5,
+ 0xc8, 0x53, 0xfa, 0xad, 0x02, 0x66, 0xbb, 0xf0, 0x91, 0xfe, 0x1d, 0xe5,
+ 0x66, 0x8a, 0xb2, 0xc6, 0x78, 0x8d, 0xf3, 0x85, 0xc8, 0xcd, 0x54, 0x93,
+ 0x14, 0xef, 0x72, 0x9c, 0xa3, 0xa3, 0xa9, 0xdd, 0xee, 0xbf, 0x15, 0xf9,
+ 0xc6, 0x5d, 0xae, 0x2f, 0x38, 0xea, 0x8d, 0x5f, 0x41, 0x4f, 0xdd, 0x66,
+ 0xbc, 0x65, 0x7c, 0xe4, 0xbd, 0xa1, 0x5f, 0xe1, 0x37, 0x63, 0xef, 0x3c,
+ 0x62, 0x2f, 0xe3, 0x65, 0x97, 0xe4, 0x0e, 0x6b, 0x9f, 0xc1, 0xf9, 0x82,
+ 0x9b, 0x4b, 0x7b, 0x70, 0x95, 0x69, 0x99, 0xad, 0x30, 0x87, 0xda, 0x40,
+ 0x2c, 0x1b, 0x82, 0xae, 0x32, 0xa6, 0x9d, 0x44, 0x3c, 0xe7, 0xef, 0xd2,
+ 0x58, 0x5b, 0xe2, 0xbe, 0x44, 0x32, 0xae, 0xc0, 0xf3, 0x96, 0x4e, 0xdd,
+ 0x8c, 0xf2, 0x3d, 0xea, 0xd2, 0x10, 0xee, 0xfd, 0x4f, 0x59, 0x5b, 0x0c,
+ 0x68, 0x1d, 0xc9, 0xbe, 0x4c, 0xd9, 0xbb, 0xbf, 0x5b, 0x4b, 0xb7, 0x6b,
+ 0x03, 0xcc, 0x03, 0x1e, 0x87, 0x5c, 0xf6, 0xdb, 0xd7, 0x19, 0xbb, 0xff,
+ 0x5d, 0x59, 0xc3, 0xc9, 0xa7, 0x0c, 0xda, 0x36, 0xc6, 0x2b, 0x21, 0x59,
+ 0x8a, 0x92, 0x7f, 0xc8, 0xcb, 0xa0, 0xed, 0xec, 0x24, 0x87, 0xed, 0x32,
+ 0xf8, 0x4b, 0xc8, 0x80, 0xb2, 0xf4, 0x65, 0xc0, 0xef, 0x49, 0xdc, 0x17,
+ 0x6b, 0x86, 0x7e, 0x5d, 0x47, 0x16, 0xeb, 0xee, 0xd9, 0xc5, 0x72, 0x23,
+ 0xcd, 0xa4, 0x97, 0x77, 0x7a, 0x49, 0x72, 0xfa, 0x7e, 0xe7, 0x25, 0x57,
+ 0xb9, 0x24, 0xfb, 0x2a, 0xf3, 0xf2, 0x98, 0xf5, 0x28, 0xf8, 0xbd, 0xe6,
+ 0xcc, 0x58, 0xba, 0x56, 0x19, 0xcf, 0xff, 0x6f, 0xe7, 0x56, 0x1b, 0xdb,
+ 0x56, 0x75, 0x86, 0x5f, 0x5f, 0xdb, 0x69, 0x1a, 0x9a, 0x70, 0xeb, 0x3a,
+ 0x89, 0x9b, 0x66, 0xad, 0x1d, 0xdf, 0x7e, 0x88, 0xa4, 0xe8, 0x36, 0x64,
+ 0x34, 0xea, 0x82, 0x62, 0x9c, 0x50, 0xc2, 0xe8, 0x44, 0xda, 0x75, 0x55,
+ 0xb5, 0x31, 0x64, 0x39, 0xe9, 0x07, 0xd3, 0x06, 0xa3, 0xb0, 0x82, 0x18,
+ 0x52, 0x8d, 0xdb, 0x6a, 0x9d, 0x96, 0xc6, 0xe9, 0x07, 0x6b, 0x37, 0x69,
+ 0x9a, 0xe5, 0xa4, 0x2d, 0x48, 0x11, 0x2e, 0x88, 0x6e, 0xfb, 0xb1, 0x8d,
+ 0x2a, 0x65, 0xec, 0xff, 0xf6, 0x67, 0xda, 0xd0, 0x16, 0x15, 0x18, 0xfc,
+ 0xd8, 0xa4, 0xfe, 0xe0, 0x47, 0x25, 0xe8, 0xbc, 0xe7, 0x79, 0xcf, 0xbd,
+ 0x8e, 0x6d, 0x82, 0x26, 0x2d, 0x52, 0xe4, 0x7b, 0xce, 0x3d, 0xf7, 0x9c,
+ 0x73, 0xcf, 0xfb, 0xfd, 0xbe, 0xcf, 0xc5, 0xda, 0x13, 0x7d, 0x6b, 0xe5,
+ 0x63, 0xf8, 0x1d, 0x27, 0x67, 0x6d, 0xc9, 0xd8, 0x83, 0xf2, 0x63, 0xcd,
+ 0xe5, 0x33, 0x3e, 0x09, 0xc0, 0x27, 0x35, 0xb8, 0x02, 0x69, 0x77, 0x62,
+ 0x37, 0x85, 0x3e, 0x65, 0x18, 0xb4, 0x8e, 0x1b, 0xbf, 0xd9, 0x36, 0xf7,
+ 0x37, 0x9d, 0x81, 0xef, 0xee, 0x0e, 0xb4, 0xfb, 0x39, 0x5f, 0xe3, 0xdf,
+ 0xfe, 0xc5, 0xab, 0xa1, 0x0d, 0xca, 0x0c, 0xf6, 0xf3, 0x96, 0xea, 0x59,
+ 0x07, 0xbc, 0xc4, 0xdc, 0x74, 0x4c, 0xf3, 0x0f, 0xe1, 0x69, 0xea, 0xa8,
+ 0xab, 0xd0, 0x51, 0x43, 0xd4, 0x5d, 0xc3, 0xb3, 0x2e, 0xf3, 0x03, 0x51,
+ 0xf9, 0xf3, 0x14, 0xf5, 0x70, 0x5c, 0xfe, 0x34, 0xf5, 0x02, 0xf6, 0x93,
+ 0x28, 0x32, 0x47, 0x79, 0x63, 0x26, 0x47, 0x3f, 0x49, 0xfd, 0xf9, 0xb4,
+ 0xfb, 0xac, 0xda, 0x81, 0xb8, 0x95, 0x5f, 0x13, 0x56, 0x7d, 0xf3, 0xb4,
+ 0xd6, 0x74, 0xe3, 0x56, 0xb7, 0xdc, 0x38, 0x6f, 0x74, 0x6c, 0x78, 0x3a,
+ 0x1a, 0x18, 0x99, 0xa3, 0x5d, 0x4a, 0xc6, 0xb2, 0xd6, 0x0a, 0x39, 0x10,
+ 0x65, 0xee, 0x39, 0x45, 0xfd, 0x0c, 0x5b, 0xd8, 0x6b, 0x67, 0xad, 0x66,
+ 0xcf, 0xfe, 0xc4, 0x1a, 0xf4, 0xec, 0xd3, 0x9e, 0x9e, 0xe5, 0xbd, 0x14,
+ 0x68, 0x4a, 0x5b, 0x94, 0x98, 0x19, 0xb5, 0x92, 0xb0, 0x79, 0xb8, 0x9e,
+ 0xe7, 0xfc, 0x71, 0x39, 0x32, 0x7f, 0x18, 0xfe, 0x77, 0xaf, 0xbd, 0x87,
+ 0x76, 0xd5, 0x1e, 0x22, 0x16, 0x07, 0xeb, 0x7f, 0xa9, 0x61, 0xae, 0xc7,
+ 0xbd, 0xb9, 0x78, 0x1f, 0x72, 0x3e, 0xed, 0xc8, 0x04, 0x6c, 0xc9, 0x88,
+ 0x6d, 0xf6, 0x5a, 0x3f, 0x76, 0x77, 0x75, 0xdd, 0x13, 0x05, 0xc7, 0xc3,
+ 0x85, 0xe1, 0x17, 0xbe, 0xd0, 0xd7, 0x23, 0x5c, 0x93, 0xeb, 0xb5, 0x49,
+ 0x7a, 0x1f, 0xf4, 0xcb, 0x34, 0xff, 0x73, 0x5e, 0xed, 0x0a, 0xf1, 0x4a,
+ 0xb4, 0x6b, 0x19, 0xdb, 0xf4, 0x80, 0x37, 0xdf, 0xb6, 0x0e, 0x69, 0x89,
+ 0xd6, 0x8c, 0x67, 0x6e, 0x85, 0xed, 0xb8, 0xe4, 0xe6, 0xf9, 0x5b, 0xa9,
+ 0x44, 0x9c, 0x26, 0xd9, 0x63, 0xaf, 0x6b, 0x98, 0x63, 0x2b, 0xfa, 0x8c,
+ 0x4f, 0x10, 0x9c, 0x0e, 0x78, 0xbe, 0xc5, 0x06, 0xfa, 0x4d, 0xde, 0x75,
+ 0xb3, 0xe6, 0x64, 0xe2, 0x56, 0x57, 0xc3, 0x7b, 0x6c, 0xa8, 0xda, 0xe1,
+ 0xb8, 0x45, 0xdd, 0xd9, 0x14, 0x95, 0x36, 0xf2, 0x50, 0x45, 0xfd, 0xf8,
+ 0x90, 0x63, 0xb0, 0x16, 0x51, 0xe7, 0x60, 0x07, 0x73, 0xf6, 0x6f, 0xeb,
+ 0xb9, 0xb5, 0xd2, 0x27, 0xc0, 0x35, 0xf8, 0xe4, 0x73, 0xf9, 0x5e, 0xe6,
+ 0x7a, 0x31, 0x7f, 0x0b, 0xe7, 0x77, 0xbd, 0x73, 0x4e, 0xb8, 0x39, 0xeb,
+ 0x7e, 0xc9, 0x9e, 0x37, 0xfc, 0x97, 0x76, 0xc0, 0x7b, 0x6d, 0x68, 0xcf,
+ 0xd1, 0x26, 0x7c, 0xd1, 0x3c, 0xbe, 0x6d, 0xd8, 0xa2, 0xb6, 0xe1, 0x78,
+ 0x81, 0xfc, 0x49, 0xbe, 0xf4, 0xf9, 0xd1, 0xd7, 0x79, 0xe4, 0x51, 0xea,
+ 0xd9, 0x41, 0x39, 0x53, 0xe0, 0xd9, 0xa4, 0xb4, 0xa6, 0xb5, 0xf1, 0xec,
+ 0x84, 0xe2, 0xb1, 0x7a, 0xa6, 0x13, 0x17, 0x73, 0x32, 0x2c, 0x57, 0x5d,
+ 0x9e, 0x59, 0xa2, 0x98, 0x09, 0xb6, 0xd6, 0xbc, 0xff, 0x3e, 0x3d, 0xb3,
+ 0xb0, 0xfa, 0x8c, 0x31, 0x8c, 0x7d, 0xc9, 0xa3, 0x77, 0x9b, 0x9e, 0x6d,
+ 0xa6, 0x8e, 0x3e, 0x8f, 0xea, 0x39, 0x85, 0xa1, 0x13, 0x59, 0xc7, 0x0f,
+ 0x47, 0xf8, 0x0c, 0xd7, 0xa5, 0xcf, 0xc7, 0xb5, 0xc8, 0x7b, 0x3d, 0xb0,
+ 0xd8, 0xfd, 0x12, 0xdc, 0x01, 0xd1, 0xdf, 0xc1, 0x3a, 0x72, 0x00, 0xb2,
+ 0xba, 0xd1, 0x60, 0x5f, 0xc6, 0x8d, 0xaf, 0x91, 0xb1, 0xde, 0xc2, 0x39,
+ 0x22, 0x56, 0x81, 0x1f, 0x7d, 0xfc, 0xa7, 0x77, 0x30, 0x5f, 0xc6, 0xf3,
+ 0xd7, 0x07, 0x30, 0x3f, 0xcf, 0x82, 0x32, 0x36, 0xb5, 0x8d, 0xbc, 0x3a,
+ 0xaa, 0xf5, 0x41, 0x3e, 0x43, 0x39, 0xe6, 0x99, 0x91, 0x2e, 0x7f, 0xc3,
+ 0xf3, 0x6c, 0x6f, 0x6d, 0xa0, 0x63, 0xd2, 0xdb, 0x9f, 0x7f, 0x3f, 0x2c,
+ 0xe1, 0x0e, 0xea, 0xb8, 0xa8, 0x24, 0xa7, 0x19, 0xb3, 0xc0, 0x76, 0x8d,
+ 0x73, 0xae, 0xff, 0xad, 0x8b, 0x33, 0xff, 0xa7, 0x2e, 0xce, 0x58, 0x1f,
+ 0x29, 0xef, 0x84, 0x35, 0x8f, 0xf5, 0xc5, 0x74, 0x2d, 0xd6, 0xd1, 0xd5,
+ 0xaf, 0xdd, 0x47, 0xab, 0x74, 0xfc, 0x51, 0x81, 0xf6, 0x2a, 0xa5, 0x39,
+ 0xe5, 0x7f, 0x4e, 0xf1, 0x6c, 0xb9, 0xc7, 0xab, 0xdc, 0xe3, 0xf0, 0x82,
+ 0x62, 0x20, 0xbf, 0xa6, 0x32, 0x7c, 0xb2, 0x40, 0x1d, 0xd3, 0x2a, 0xb3,
+ 0x33, 0xbe, 0x9e, 0x19, 0xf3, 0x7c, 0xdc, 0xfc, 0x9a, 0x26, 0xd5, 0x33,
+ 0xf0, 0x6e, 0x9c, 0x11, 0xcf, 0xbe, 0x74, 0x4b, 0xe9, 0x3c, 0xed, 0x6e,
+ 0x12, 0x7d, 0xd1, 0x40, 0x69, 0x8e, 0xb5, 0x49, 0x62, 0x50, 0x86, 0x85,
+ 0x75, 0xff, 0x11, 0xfb, 0x38, 0xe4, 0x2d, 0x26, 0xef, 0x4f, 0xd1, 0xa7,
+ 0x6f, 0x82, 0x6f, 0xdc, 0xd6, 0x70, 0xbe, 0xdb, 0xab, 0x3e, 0x61, 0x3d,
+ 0xdd, 0x37, 0x74, 0x4a, 0x0b, 0xf9, 0xdc, 0xb1, 0x6f, 0x08, 0x7d, 0x30,
+ 0x5e, 0x67, 0x11, 0x0b, 0x30, 0xf6, 0x88, 0x6b, 0xec, 0x51, 0x2a, 0xb2,
+ 0xaf, 0xd5, 0xcb, 0x2b, 0xb5, 0x2a, 0xaf, 0x90, 0xdf, 0x32, 0xea, 0x7f,
+ 0x0f, 0xa9, 0xce, 0xca, 0x4f, 0xf5, 0x1a, 0xfc, 0x8a, 0x1d, 0x53, 0xde,
+ 0x93, 0x3a, 0xde, 0x8b, 0x79, 0x6b, 0x3f, 0xdc, 0x69, 0x7c, 0x2b, 0x5b,
+ 0xf5, 0x4d, 0x58, 0xc7, 0xd1, 0xae, 0x70, 0x7e, 0xf2, 0x06, 0x79, 0x84,
+ 0x3a, 0xcf, 0x1f, 0xe7, 0xd3, 0xc3, 0x6f, 0x73, 0x3c, 0xf9, 0xbf, 0x16,
+ 0x8b, 0xe0, 0xcb, 0xaa, 0xdf, 0xe7, 0xcb, 0x1d, 0xef, 0xd5, 0xda, 0x04,
+ 0xca, 0x5d, 0x6d, 0x7d, 0xd2, 0x96, 0xc8, 0xf4, 0x12, 0x5d, 0xd2, 0xfd,
+ 0xdc, 0xff, 0x4b, 0xcc, 0xed, 0x42, 0xde, 0x96, 0xa3, 0xcd, 0x51, 0xa5,
+ 0x4d, 0x06, 0xb4, 0x89, 0x28, 0x6d, 0x18, 0xef, 0x3d, 0xe3, 0xf1, 0x5b,
+ 0x2b, 0xce, 0x8b, 0xb9, 0x5a, 0xe8, 0xba, 0xbd, 0xd4, 0xf9, 0xcf, 0x77,
+ 0x6a, 0x7d, 0xd0, 0xa1, 0xee, 0x5b, 0x05, 0x7d, 0xc6, 0xf6, 0x66, 0xf5,
+ 0x47, 0x4c, 0xbc, 0x15, 0xd7, 0x3c, 0x68, 0x10, 0xfa, 0xb9, 0x34, 0x05,
+ 0x5f, 0x8d, 0x78, 0xb7, 0x3a, 0x5a, 0x7d, 0xc7, 0x3b, 0xaf, 0x92, 0xd2,
+ 0x86, 0x32, 0x40, 0xbd, 0xb9, 0x1a, 0xf3, 0xed, 0x8e, 0xf6, 0x81, 0xbf,
+ 0x7e, 0x81, 0xfe, 0x8d, 0x1a, 0x4f, 0x04, 0x21, 0xf3, 0x37, 0xa7, 0x3a,
+ 0xbc, 0x18, 0xce, 0x41, 0x1b, 0x71, 0xeb, 0x54, 0x84, 0x31, 0x05, 0xda,
+ 0x5b, 0xa4, 0x69, 0x1a, 0xf1, 0x2b, 0xf4, 0xf8, 0x82, 0xda, 0xa3, 0x3e,
+ 0xdc, 0xbf, 0x8b, 0x18, 0x3f, 0x5c, 0x1f, 0xc6, 0x73, 0xbd, 0x06, 0x8b,
+ 0x10, 0xdd, 0xa4, 0x67, 0x5a, 0x9a, 0x4a, 0xc4, 0x0e, 0x8a, 0xd7, 0x37,
+ 0xee, 0xaa, 0x3e, 0x58, 0xda, 0xd7, 0x43, 0xb2, 0xbb, 0x6a, 0x2f, 0x18,
+ 0x47, 0xc3, 0x87, 0x9f, 0x31, 0xf6, 0x20, 0x5f, 0xec, 0x53, 0x5c, 0x54,
+ 0x70, 0x68, 0x1e, 0x67, 0x49, 0x9f, 0x74, 0x11, 0x7e, 0xb8, 0x8b, 0x33,
+ 0xa4, 0xdf, 0x5d, 0x39, 0x76, 0xc2, 0x4d, 0xb1, 0x3e, 0x06, 0x7d, 0x70,
+ 0x4c, 0x46, 0x10, 0x17, 0x8c, 0x04, 0xdb, 0x98, 0x57, 0x86, 0x6f, 0x98,
+ 0xf3, 0x72, 0x8f, 0x7d, 0xcc, 0x99, 0xca, 0xd9, 0x39, 0xee, 0x9d, 0xb2,
+ 0x6d, 0x62, 0xef, 0xd2, 0x14, 0xf7, 0x6b, 0xf2, 0x10, 0x6c, 0x5b, 0xd3,
+ 0x2e, 0x7e, 0x79, 0x16, 0x03, 0xf8, 0x1d, 0x84, 0x3c, 0x70, 0x2c, 0x7e,
+ 0xe7, 0x16, 0xe5, 0xdd, 0xf3, 0xbe, 0x6d, 0x0f, 0xc8, 0x3b, 0x4e, 0xe5,
+ 0xd8, 0x71, 0x77, 0x0d, 0xcf, 0xc0, 0xcd, 0xb1, 0x66, 0xed, 0x38, 0x6e,
+ 0x5e, 0x2a, 0x95, 0x05, 0x77, 0x61, 0x8d, 0xa5, 0xb4, 0xa4, 0xfc, 0xff,
+ 0x03, 0x67, 0x78, 0xfd, 0x3e, 0x4b, 0x0c, 0xfd, 0x48, 0x9b, 0xcf, 0xd7,
+ 0xfe, 0x6a, 0x6d, 0x81, 0xaf, 0xff, 0xc8, 0x8f, 0xe4, 0xcb, 0x45, 0xd9,
+ 0xa9, 0xfa, 0x7f, 0xb9, 0xe7, 0x6a, 0x75, 0xbf, 0xef, 0xdf, 0x52, 0xbf,
+ 0x93, 0x17, 0x63, 0x1a, 0x1f, 0x6c, 0x9a, 0x6e, 0xd4, 0x09, 0x4f, 0x78,
+ 0x75, 0x85, 0xe5, 0x78, 0x6f, 0xbf, 0xa7, 0x17, 0x52, 0xea, 0x3b, 0xa7,
+ 0x6c, 0xea, 0x07, 0xee, 0xa7, 0x45, 0x26, 0x2e, 0xdc, 0x01, 0x4d, 0x7c,
+ 0x1d, 0xcc, 0xb8, 0xcf, 0xd7, 0x1d, 0x6d, 0x9e, 0x2f, 0x6c, 0x49, 0xcf,
+ 0x59, 0xfa, 0x4e, 0x0e, 0xf4, 0x68, 0xbb, 0x64, 0xc6, 0x83, 0x92, 0x3c,
+ 0x1b, 0x8b, 0x19, 0x5f, 0x97, 0xfc, 0x07, 0x79, 0xd3, 0x3e, 0xad, 0x45,
+ 0xa1, 0xff, 0x6e, 0xe1, 0xda, 0x86, 0x9f, 0x21, 0xcf, 0x7b, 0xfd, 0x7b,
+ 0x76, 0x03, 0x8f, 0xee, 0xf0, 0x78, 0x94, 0xf7, 0x2d, 0x53, 0xff, 0xc0,
+ 0xd8, 0x9e, 0xb3, 0xdc, 0xa3, 0x79, 0xae, 0xe7, 0xac, 0x89, 0xd7, 0xeb,
+ 0x9f, 0xeb, 0xab, 0x3e, 0x87, 0xfb, 0xf0, 0x7d, 0xcd, 0xdc, 0x3b, 0x07,
+ 0xe1, 0xd3, 0xf5, 0xd1, 0xe6, 0xd0, 0x7e, 0x6f, 0x74, 0x77, 0x0a, 0xf9,
+ 0x3d, 0xe1, 0xf1, 0x1c, 0xf5, 0x4d, 0xc4, 0xd3, 0x37, 0x4b, 0xf6, 0x65,
+ 0xc4, 0xe0, 0x4f, 0x98, 0x13, 0xa9, 0xb1, 0x2f, 0x4f, 0x98, 0x77, 0xab,
+ 0xb3, 0x2f, 0x77, 0x7b, 0xf3, 0xf8, 0xf7, 0x7c, 0xbd, 0xe2, 0xb7, 0x7d,
+ 0xbd, 0xd2, 0xe8, 0xd3, 0xfa, 0xb4, 0xaf, 0xed, 0xaf, 0x8f, 0xf9, 0xf2,
+ 0xcb, 0xe6, 0x5d, 0xb2, 0x88, 0xd9, 0xe8, 0x53, 0x26, 0x72, 0x06, 0x2f,
+ 0x6d, 0x9d, 0xb1, 0x88, 0xfb, 0x70, 0x7e, 0x22, 0xe9, 0xc8, 0x1d, 0x8d,
+ 0xad, 0x4f, 0x5e, 0x18, 0xd3, 0x3c, 0x4f, 0xc9, 0xf5, 0xf4, 0x4e, 0x74,
+ 0x17, 0xe4, 0xea, 0x4a, 0x64, 0x09, 0x53, 0x34, 0x73, 0x34, 0x0d, 0x3b,
+ 0x94, 0xd2, 0x7a, 0xd9, 0xf7, 0xb0, 0xdf, 0x41, 0xc5, 0x73, 0xad, 0x74,
+ 0x5e, 0x94, 0x47, 0xec, 0x8a, 0xd6, 0x6e, 0x9a, 0x87, 0x8a, 0x47, 0x9b,
+ 0x4f, 0xfb, 0x7c, 0x4f, 0x7e, 0x9a, 0x39, 0x3a, 0x31, 0x53, 0x19, 0x0e,
+ 0x6d, 0xeb, 0xb5, 0xf3, 0x42, 0xbc, 0xfe, 0xb0, 0x1c, 0x52, 0xdc, 0xf0,
+ 0xab, 0xb8, 0xbf, 0x97, 0xf1, 0x65, 0x22, 0xa4, 0x78, 0xe0, 0x44, 0x6c,
+ 0x12, 0xb2, 0x98, 0x75, 0x89, 0xef, 0x5f, 0xa5, 0x38, 0xff, 0x92, 0xd0,
+ 0xcf, 0x22, 0xa6, 0xe0, 0x05, 0x39, 0xe8, 0x6e, 0x74, 0x17, 0xc4, 0xf8,
+ 0xbf, 0x59, 0xad, 0x09, 0xad, 0x90, 0x49, 0x37, 0xd4, 0x9c, 0x2e, 0x1b,
+ 0x19, 0x18, 0x0d, 0xa6, 0x56, 0x9e, 0x70, 0xa2, 0xcd, 0x3b, 0xcb, 0x90,
+ 0xf1, 0x32, 0xf4, 0x7f, 0x39, 0x16, 0x18, 0x51, 0x6c, 0xda, 0x57, 0x24,
+ 0xdd, 0x41, 0x3f, 0x9f, 0xfa, 0xe4, 0x01, 0xb9, 0x69, 0x6f, 0x96, 0x9b,
+ 0x5b, 0x88, 0xc3, 0xec, 0x47, 0x9b, 0xba, 0x64, 0x10, 0x7d, 0x49, 0xf4,
+ 0x35, 0x2b, 0x3f, 0x6a, 0x7c, 0x06, 0x9d, 0x75, 0xd3, 0xa6, 0xae, 0x5a,
+ 0xcf, 0x5f, 0xbc, 0xeb, 0x22, 0x68, 0x42, 0x6c, 0xc7, 0x56, 0xb4, 0xa9,
+ 0xe3, 0xec, 0x86, 0xfe, 0x2e, 0xb4, 0xef, 0xc3, 0x1c, 0x4d, 0xfa, 0x7e,
+ 0x96, 0xb3, 0xcd, 0xd4, 0x39, 0xeb, 0xc6, 0xac, 0x6e, 0x68, 0xff, 0xb1,
+ 0xdd, 0xe0, 0x13, 0x3e, 0x25, 0xbd, 0x73, 0x29, 0xd9, 0xd5, 0x59, 0xdf,
+ 0xfe, 0x77, 0x43, 0xbb, 0x4d, 0x56, 0xb6, 0x93, 0x0c, 0x4f, 0x75, 0xd4,
+ 0xf7, 0xfb, 0xfc, 0xe4, 0xb7, 0x3b, 0xf1, 0xbe, 0x09, 0x18, 0xbc, 0xa4,
+ 0xc6, 0x52, 0x37, 0xa3, 0x5c, 0xeb, 0x83, 0x86, 0x67, 0x78, 0xcd, 0x67,
+ 0xf8, 0x2c, 0xf3, 0x7a, 0x9f, 0xb1, 0x1f, 0xcf, 0x30, 0x27, 0xc0, 0xbc,
+ 0x06, 0x79, 0x76, 0xb9, 0x38, 0x8b, 0x63, 0x3e, 0x9f, 0x6f, 0xc8, 0x54,
+ 0x79, 0xcf, 0xd7, 0x2b, 0xb1, 0x2a, 0x56, 0x6d, 0x67, 0xc1, 0xcf, 0x09,
+ 0x93, 0x76, 0x5a, 0x93, 0x8a, 0xdd, 0x00, 0x9d, 0x0f, 0x80, 0xce, 0x0f,
+ 0x05, 0x19, 0x17, 0xb6, 0x78, 0xb4, 0x76, 0x64, 0xa4, 0xfc, 0x5b, 0xc8,
+ 0x38, 0x79, 0x14, 0x3e, 0x45, 0xd9, 0xf2, 0xf0, 0x19, 0x03, 0xb0, 0x69,
+ 0xae, 0x04, 0x35, 0xef, 0x80, 0xf8, 0x7e, 0xf6, 0xba, 0x8c, 0x4c, 0x31,
+ 0x27, 0x40, 0x7e, 0x66, 0x5c, 0x9f, 0xc2, 0xbd, 0x5b, 0x18, 0xeb, 0x42,
+ 0x86, 0xc7, 0xc0, 0xaf, 0x21, 0x71, 0xa6, 0xb7, 0x4a, 0x6e, 0x7c, 0x4c,
+ 0x7d, 0x80, 0x1e, 0xd8, 0xa8, 0xe3, 0xee, 0xa8, 0x9c, 0xb8, 0xb2, 0x01,
+ 0xb2, 0xca, 0xb8, 0x5f, 0x73, 0x1a, 0x95, 0xb0, 0xfa, 0xe6, 0xf4, 0x39,
+ 0x98, 0x87, 0x33, 0x35, 0x66, 0x23, 0xb7, 0x93, 0x31, 0x69, 0x1b, 0x95,
+ 0x99, 0x0b, 0xb6, 0xe2, 0x5d, 0x52, 0x72, 0xa7, 0x42, 0xda, 0x65, 0xf7,
+ 0xc6, 0xa1, 0xab, 0xe8, 0xcb, 0x9f, 0x8c, 0x98, 0xb3, 0x7c, 0x74, 0x2d,
+ 0x63, 0xe2, 0xe4, 0x74, 0xed, 0x1c, 0x8a, 0x91, 0xc1, 0xbd, 0xd7, 0xda,
+ 0x8d, 0xcc, 0x30, 0x3e, 0xfe, 0xa0, 0x92, 0x8a, 0x72, 0x4d, 0x8e, 0x65,
+ 0xed, 0x96, 0x3c, 0xc2, 0xbd, 0x7d, 0xea, 0xf1, 0xf2, 0xcf, 0x30, 0x5f,
+ 0x5c, 0x7a, 0x5e, 0x1f, 0xd3, 0xb8, 0xfe, 0x78, 0x5d, 0x0c, 0x6b, 0xf2,
+ 0x05, 0x26, 0x8e, 0xbd, 0x2e, 0x93, 0xf3, 0xa4, 0x0f, 0x6d, 0x7c, 0x40,
+ 0x5e, 0x73, 0x7a, 0xed, 0x27, 0xb5, 0xd6, 0x98, 0x48, 0xb1, 0x3e, 0xd3,
+ 0xe2, 0x24, 0xed, 0x59, 0x09, 0x0d, 0x7e, 0x15, 0xd7, 0x8c, 0x6b, 0xf3,
+ 0x6e, 0xaf, 0xfb, 0xa4, 0xf8, 0x38, 0x90, 0x8d, 0xa9, 0x15, 0x81, 0xdb,
+ 0x95, 0xeb, 0x7b, 0x39, 0xc6, 0xe0, 0x40, 0x24, 0x40, 0x5a, 0xbd, 0xb7,
+ 0x9e, 0xf8, 0x99, 0xfa, 0xfc, 0xdf, 0x83, 0x4f, 0xef, 0x19, 0x48, 0x9c,
+ 0x62, 0x0c, 0x1b, 0x76, 0xbe, 0xb5, 0xd6, 0xbc, 0x6b, 0x2e, 0xb7, 0x5a,
+ 0xb4, 0x7e, 0x76, 0xe4, 0x23, 0x87, 0x78, 0x88, 0x44, 0x6c, 0x85, 0xc5,
+ 0x3c, 0x38, 0x75, 0x1c, 0x6b, 0x2a, 0xcc, 0xb9, 0x11, 0xc7, 0xdf, 0x2c,
+ 0x97, 0xfb, 0x2c, 0x79, 0x30, 0x94, 0x8a, 0x5b, 0xb2, 0x29, 0x7e, 0x56,
+ 0xb0, 0x26, 0xeb, 0x2b, 0xf3, 0x89, 0x1c, 0xc7, 0x87, 0xa6, 0x39, 0x5f,
+ 0x5c, 0xe3, 0x95, 0xe4, 0xa6, 0x4a, 0xe5, 0x19, 0x57, 0x02, 0xc9, 0x7b,
+ 0x3f, 0xac, 0xb0, 0x16, 0x6e, 0xbd, 0xfe, 0x45, 0x38, 0x05, 0xea, 0x8a,
+ 0x55, 0x93, 0x06, 0x73, 0x78, 0xe2, 0x48, 0xcf, 0x3c, 0xdb, 0xdf, 0x7d,
+ 0xc4, 0xb4, 0x4f, 0xa1, 0xdd, 0xe4, 0x61, 0x9d, 0xa6, 0x8e, 0xf4, 0x14,
+ 0x9f, 0x5a, 0x6b, 0xe2, 0xef, 0x45, 0xc5, 0x7f, 0xbd, 0x5d, 0x17, 0xd3,
+ 0xa4, 0x02, 0xe3, 0x85, 0xb1, 0xc0, 0x58, 0xc1, 0xea, 0x6b, 0x06, 0xad,
+ 0xe6, 0x5c, 0xe6, 0x6a, 0xfc, 0x9c, 0x15, 0xf3, 0xfd, 0x22, 0xdf, 0x57,
+ 0x8c, 0x14, 0x6b, 0x8a, 0x96, 0xfa, 0x42, 0x07, 0xe6, 0x98, 0xe3, 0x8f,
+ 0xa8, 0x3e, 0x38, 0x38, 0xdf, 0x26, 0x79, 0x7b, 0x8d, 0xe4, 0x55, 0xc6,
+ 0xa3, 0xaa, 0x03, 0x2c, 0xe7, 0x5e, 0xf4, 0x71, 0xdf, 0x4f, 0x28, 0x2e,
+ 0xe2, 0xcd, 0x42, 0x17, 0xda, 0xcc, 0x35, 0x6f, 0x6f, 0xe8, 0xaf, 0xad,
+ 0xcb, 0x26, 0x6c, 0xcb, 0x6a, 0xac, 0xc9, 0xb2, 0xaf, 0xb1, 0x16, 0x7b,
+ 0x52, 0xae, 0x93, 0x6f, 0xca, 0x7e, 0xce, 0xdd, 0xf5, 0x72, 0xee, 0xdf,
+ 0xee, 0x32, 0x18, 0x61, 0xc9, 0x84, 0x86, 0x9a, 0xfb, 0x8e, 0x4f, 0x05,
+ 0x6f, 0x2d, 0xe5, 0x4f, 0xd1, 0x9e, 0xaf, 0xd6, 0xca, 0x71, 0xef, 0x39,
+ 0x62, 0xc5, 0xe1, 0x57, 0xe4, 0xbc, 0xef, 0x0e, 0x78, 0xbf, 0xfa, 0xfc,
+ 0xff, 0xd8, 0x53, 0x8b, 0xd6, 0xd9, 0xad, 0xba, 0x3a, 0xfb, 0xe3, 0x78,
+ 0x96, 0x35, 0xf6, 0x5c, 0xa5, 0x09, 0xbc, 0xdb, 0x44, 0x9c, 0x48, 0x75,
+ 0x3c, 0x75, 0xbc, 0xea, 0x72, 0x9d, 0x6b, 0xa7, 0x37, 0x57, 0x10, 0x7a,
+ 0x7e, 0x62, 0xca, 0x1f, 0x73, 0x4c, 0x56, 0xf4, 0x27, 0x62, 0x41, 0x8b,
+ 0x63, 0x8c, 0xbe, 0x4f, 0xbb, 0xc7, 0xa0, 0xc7, 0xa9, 0xf3, 0xf9, 0xde,
+ 0x0e, 0x7c, 0x3d, 0xea, 0x02, 0xea, 0x73, 0xb5, 0x01, 0xf1, 0x3c, 0x74,
+ 0xfd, 0x48, 0x59, 0x73, 0xf9, 0xb1, 0x87, 0x83, 0x89, 0x99, 0xac, 0xea,
+ 0x06, 0xf8, 0x7b, 0xe5, 0x6b, 0xcc, 0x07, 0x9d, 0x92, 0x40, 0x6d, 0x9d,
+ 0x86, 0xb1, 0x19, 0x6b, 0x1a, 0xad, 0xd0, 0x0d, 0x22, 0x57, 0xc1, 0x1b,
+ 0x6f, 0xcc, 0x91, 0x5f, 0x83, 0x1d, 0x26, 0xbe, 0x5a, 0xd8, 0x6e, 0x49,
+ 0x87, 0xd6, 0x3e, 0xf3, 0x4e, 0x84, 0xfe, 0xc9, 0x70, 0xb2, 0x1f, 0x7e,
+ 0xb6, 0x62, 0x0f, 0x98, 0xaf, 0x9c, 0x40, 0x3c, 0x56, 0x9b, 0x63, 0x81,
+ 0x7c, 0x8d, 0xb3, 0x3f, 0x0b, 0xbf, 0x72, 0xa9, 0xee, 0x91, 0x2f, 0x9e,
+ 0xd0, 0xdc, 0x66, 0x69, 0xae, 0x55, 0x75, 0x6c, 0xa9, 0xf8, 0x30, 0xce,
+ 0x45, 0x36, 0x5b, 0x43, 0x79, 0xaf, 0x3f, 0x2c, 0xc5, 0x22, 0xdb, 0xd2,
+ 0xdd, 0xa4, 0xe7, 0xee, 0xd7, 0x76, 0x6c, 0x99, 0x85, 0xaf, 0x58, 0x9c,
+ 0x77, 0xf0, 0xbf, 0x05, 0xff, 0x7d, 0xf8, 0xdf, 0x25, 0xe9, 0x69, 0xfa,
+ 0xaf, 0xac, 0xe5, 0xb4, 0x36, 0xac, 0x1f, 0xf6, 0x70, 0xe0, 0xf4, 0x6b,
+ 0x4d, 0x9c, 0x93, 0x2f, 0x36, 0xca, 0x09, 0xf3, 0xa4, 0xbe, 0x8e, 0x60,
+ 0xbe, 0xd4, 0xaf, 0xf5, 0xd5, 0xd6, 0xb0, 0x2c, 0xaf, 0xee, 0x45, 0x9e,
+ 0x6e, 0x91, 0x83, 0x45, 0xbf, 0x76, 0x15, 0x93, 0x43, 0xd5, 0xda, 0x95,
+ 0x64, 0x82, 0x43, 0xb7, 0x1f, 0xcb, 0x4e, 0x29, 0x9e, 0xc0, 0xb2, 0x86,
+ 0xae, 0x3f, 0x36, 0x39, 0xff, 0xce, 0x63, 0x4b, 0x98, 0x70, 0xdc, 0x9b,
+ 0x5f, 0x0e, 0x33, 0x44, 0x2c, 0x1d, 0xbf, 0x93, 0x53, 0xdf, 0x0d, 0xfb,
+ 0xf6, 0x63, 0x1e, 0xe2, 0xec, 0xe2, 0xf6, 0x12, 0x7e, 0xd9, 0x8f, 0x47,
+ 0x89, 0x23, 0xe5, 0x73, 0xb5, 0xd8, 0x8f, 0x10, 0xce, 0x5f, 0x02, 0x96,
+ 0x93, 0xc3, 0x3e, 0x2e, 0x76, 0x19, 0x3f, 0x90, 0x38, 0xd3, 0x44, 0x0d,
+ 0xf6, 0xc8, 0xc7, 0x9a, 0x5e, 0xc4, 0x5c, 0x19, 0xf9, 0x7d, 0xf9, 0x71,
+ 0xf9, 0x75, 0x79, 0x0c, 0xf2, 0x3d, 0x89, 0x39, 0xf7, 0xcb, 0xaf, 0xca,
+ 0x7b, 0xe5, 0x5a, 0x79, 0x5c, 0xde, 0x2a, 0xef, 0x42, 0x4c, 0x35, 0x4a,
+ 0xac, 0xa7, 0x87, 0x95, 0x1e, 0x96, 0x89, 0x73, 0x8a, 0x01, 0xbc, 0x45,
+ 0xbf, 0xe7, 0x88, 0xfa, 0xd9, 0x01, 0xf2, 0xf4, 0x6f, 0x18, 0xcf, 0x13,
+ 0x9b, 0x59, 0x2c, 0xfb, 0x18, 0x8e, 0x43, 0xdd, 0x58, 0xdb, 0xe6, 0x37,
+ 0x29, 0x23, 0xe7, 0x22, 0x81, 0xd1, 0x73, 0xa1, 0xc0, 0x43, 0xfa, 0x7d,
+ 0x0b, 0xeb, 0x9d, 0x15, 0x39, 0xe1, 0x3a, 0xe4, 0xcd, 0xc1, 0x11, 0xc8,
+ 0xc2, 0x28, 0x54, 0xfd, 0x23, 0xce, 0x1a, 0x01, 0x49, 0x53, 0x1f, 0xc3,
+ 0xcf, 0x4c, 0x9e, 0x76, 0x25, 0x5b, 0x98, 0x0d, 0x18, 0x3c, 0x9a, 0x8d,
+ 0x76, 0x1f, 0xda, 0xbf, 0xf4, 0xda, 0x3b, 0x24, 0x7b, 0x41, 0x52, 0xef,
+ 0xab, 0x3f, 0xfc, 0x73, 0xaf, 0x6f, 0x10, 0x7d, 0xe0, 0xcc, 0x57, 0xd8,
+ 0xf7, 0x8a, 0xd7, 0xc7, 0x33, 0x61, 0xad, 0x3e, 0xae, 0x7c, 0x95, 0xb5,
+ 0xc7, 0x85, 0xdf, 0x2f, 0x18, 0x4c, 0xe8, 0xfb, 0x5d, 0x46, 0xb7, 0x11,
+ 0x13, 0xf8, 0xaf, 0x2e, 0xc6, 0x60, 0x45, 0xc8, 0xd7, 0x7a, 0xe8, 0xc4,
+ 0xbf, 0x6f, 0x5e, 0x6a, 0x5b, 0x43, 0x9f, 0xd4, 0x60, 0xb4, 0x3f, 0x91,
+ 0x9e, 0xf9, 0xdb, 0x1e, 0x9e, 0xf7, 0x30, 0xde, 0x0d, 0x67, 0x55, 0x20,
+ 0x6e, 0x3c, 0x0e, 0xd9, 0x6e, 0x95, 0x35, 0x67, 0x48, 0xaf, 0x5e, 0xe8,
+ 0xea, 0x14, 0xe4, 0xd6, 0x95, 0xb9, 0x72, 0x28, 0x30, 0x52, 0x48, 0x89,
+ 0xc1, 0x53, 0x5b, 0x92, 0x89, 0xa6, 0xe4, 0xe4, 0x40, 0x62, 0x0b, 0xf3,
+ 0x90, 0xd9, 0x7e, 0x57, 0x2e, 0x95, 0x69, 0x8f, 0x73, 0x72, 0x79, 0x20,
+ 0xe1, 0x16, 0x85, 0xb8, 0x18, 0x57, 0x2e, 0x43, 0x36, 0xff, 0x70, 0x6e,
+ 0x97, 0x1c, 0x2a, 0xa8, 0x1f, 0xdc, 0x1b, 0x96, 0x97, 0xe5, 0xd2, 0xc0,
+ 0xcb, 0xb7, 0x2e, 0xb9, 0x93, 0x38, 0x53, 0xf2, 0xe1, 0x81, 0x6e, 0xb3,
+ 0x6f, 0xc5, 0x21, 0x09, 0xf3, 0x21, 0x5a, 0x53, 0x73, 0x56, 0x48, 0x7a,
+ 0x5f, 0xc4, 0x8b, 0xcb, 0xe1, 0x73, 0x07, 0xee, 0x33, 0xf5, 0x94, 0x80,
+ 0xbf, 0xcf, 0x30, 0xfc, 0x18, 0x3e, 0xe7, 0xd3, 0xc6, 0x9f, 0xa7, 0x2b,
+ 0x90, 0xbe, 0xd0, 0x26, 0xa1, 0x57, 0xbe, 0x0c, 0xba, 0x86, 0xe4, 0x40,
+ 0x7f, 0xa5, 0xf2, 0x0d, 0x37, 0x14, 0x9f, 0x44, 0x8c, 0x82, 0xfd, 0xcb,
+ 0xea, 0xd3, 0xed, 0xa0, 0x49, 0xb3, 0x44, 0x4f, 0xfb, 0xeb, 0xad, 0xf0,
+ 0xb0, 0x0c, 0xe7, 0x57, 0x1b, 0x5b, 0xe6, 0x63, 0x1b, 0xfc, 0xf9, 0x0c,
+ 0xa6, 0xac, 0xc7, 0xea, 0x0f, 0x78, 0xdf, 0x49, 0x78, 0xed, 0x7b, 0x03,
+ 0x0f, 0x86, 0x3a, 0x24, 0xe4, 0xfc, 0x70, 0x1d, 0xb1, 0x91, 0x0b, 0x05,
+ 0xbf, 0x1f, 0x7e, 0x62, 0xc8, 0xf7, 0x87, 0x65, 0xdb, 0xd2, 0x59, 0xcb,
+ 0xb6, 0x9e, 0xf9, 0x6f, 0x7a, 0x73, 0xa6, 0xbc, 0xb1, 0x88, 0x39, 0x62,
+ 0xab, 0xd4, 0x3e, 0x99, 0xb1, 0x9f, 0xc9, 0xb3, 0xfd, 0x89, 0x57, 0x15,
+ 0x27, 0x5b, 0x7d, 0x86, 0xf7, 0x11, 0x43, 0x96, 0xf5, 0x99, 0xd8, 0x6e,
+ 0xd0, 0x37, 0x13, 0xbb, 0xc7, 0x9e, 0xb5, 0x82, 0x01, 0xe3, 0x8f, 0x34,
+ 0xc9, 0x0f, 0xa2, 0xb0, 0xdb, 0x88, 0xf1, 0xb2, 0xcc, 0x7f, 0xb9, 0x77,
+ 0x3c, 0x3f, 0x85, 0x7d, 0x89, 0x53, 0x49, 0x6b, 0x02, 0xfb, 0xe3, 0x19,
+ 0x10, 0x03, 0x6a, 0x81, 0x4e, 0x5d, 0x78, 0x3f, 0xc4, 0x4f, 0xfd, 0xfe,
+ 0xfb, 0xaf, 0x86, 0x0e, 0xe3, 0xfe, 0x0d, 0x2e, 0x4c, 0x2c, 0xe6, 0x42,
+ 0x86, 0x3d, 0x0c, 0x6c, 0xad, 0xdc, 0xfa, 0xd8, 0x58, 0x1f, 0x4f, 0x47,
+ 0x8c, 0x52, 0x0c, 0x7e, 0x20, 0x65, 0x82, 0xbc, 0xd9, 0x89, 0xfe, 0x95,
+ 0xb7, 0x53, 0xfa, 0xea, 0x7e, 0xdf, 0x87, 0x55, 0x6c, 0xf7, 0x64, 0x61,
+ 0xaf, 0xc1, 0xe6, 0x59, 0x8b, 0x92, 0xea, 0x4e, 0xda, 0x27, 0xb0, 0xdf,
+ 0x74, 0x28, 0x51, 0xcc, 0x49, 0x4c, 0x66, 0xa1, 0x2f, 0xde, 0x80, 0xec,
+ 0x5f, 0x2b, 0xc7, 0x03, 0x69, 0xec, 0xe9, 0x60, 0x61, 0x48, 0x26, 0x2f,
+ 0xe8, 0x37, 0x5f, 0xd0, 0xfb, 0x43, 0x52, 0x2a, 0x24, 0xb6, 0xcc, 0x82,
+ 0xff, 0x66, 0x0b, 0xc4, 0x17, 0xf5, 0xc6, 0x47, 0x31, 0xe3, 0x42, 0x61,
+ 0x23, 0xec, 0x83, 0xa4, 0x2e, 0xc1, 0xff, 0xb9, 0x54, 0xde, 0x02, 0x3e,
+ 0xc3, 0xfd, 0xb2, 0x83, 0x5f, 0xe8, 0xcc, 0xf2, 0x00, 0xe4, 0x9c, 0x7b,
+ 0xb1, 0x65, 0x6e, 0x33, 0xce, 0x8e, 0x38, 0x22, 0xc5, 0x8f, 0xff, 0x07,
+ 0xe7, 0xeb, 0xbf, 0xf7, 0x76, 0xb5, 0xd3, 0xb3, 0xba, 0x2f, 0xd8, 0x65,
+ 0xc4, 0x00, 0xd9, 0x7e, 0x63, 0xb7, 0xd3, 0x91, 0x76, 0x49, 0xdf, 0x43,
+ 0x3b, 0xde, 0xa1, 0x31, 0xa2, 0xf2, 0x62, 0x84, 0xf7, 0xdf, 0x59, 0x67,
+ 0xe8, 0x17, 0x6e, 0x68, 0xbf, 0x8d, 0xdf, 0x36, 0xe9, 0x74, 0xf8, 0x6b,
+ 0xe3, 0xf7, 0xc6, 0x3a, 0xd6, 0x77, 0x3b, 0x9d, 0x24, 0xd6, 0xfa, 0x9d,
+ 0x97, 0x2f, 0xc0, 0xf5, 0x2c, 0x9f, 0x59, 0xeb, 0xad, 0xcb, 0x79, 0xdb,
+ 0x30, 0x4f, 0xab, 0xb7, 0x56, 0x9b, 0xe6, 0x27, 0xcd, 0x5a, 0x88, 0x71,
+ 0x0b, 0xef, 0xad, 0xd3, 0xef, 0x8c, 0x61, 0x2f, 0xea, 0xdb, 0x7f, 0x5d,
+ 0x47, 0xdc, 0x5c, 0xa7, 0xd3, 0xa6, 0x18, 0xcf, 0x9b, 0x1d, 0x1d, 0xb8,
+ 0xe6, 0x9a, 0x1c, 0x63, 0xf2, 0xe1, 0xa5, 0x32, 0xe7, 0x67, 0x3b, 0x25,
+ 0x47, 0x35, 0x9f, 0x61, 0xb0, 0x7c, 0xa5, 0xc2, 0xfd, 0x32, 0x79, 0x4e,
+ 0xf1, 0x75, 0x33, 0x79, 0x8b, 0xdf, 0xbd, 0xf0, 0x3b, 0x39, 0xfa, 0x12,
+ 0x63, 0x32, 0x81, 0xf3, 0xbb, 0x0c, 0x9f, 0x6a, 0xc1, 0x7c, 0x13, 0x8b,
+ 0xbf, 0xfd, 0x38, 0x97, 0x10, 0x64, 0x8c, 0x32, 0x4a, 0x99, 0xc2, 0xf9,
+ 0x8d, 0xdb, 0xf2, 0xee, 0x00, 0xe5, 0x79, 0x40, 0xae, 0x54, 0xe5, 0x39,
+ 0x07, 0x79, 0xa6, 0x2c, 0xe7, 0x20, 0xd3, 0x86, 0xaf, 0xf7, 0xf1, 0x1b,
+ 0x6b, 0x84, 0xeb, 0x25, 0xf5, 0x21, 0x2e, 0x82, 0xaf, 0x6d, 0x13, 0x97,
+ 0x2b, 0x2e, 0xfe, 0x30, 0xf4, 0x5a, 0x93, 0xf7, 0x1d, 0x00, 0xae, 0xaf,
+ 0xbc, 0x28, 0xe9, 0x0b, 0x2d, 0xd8, 0x77, 0xbc, 0x9b, 0x67, 0x96, 0xbd,
+ 0xc2, 0x7f, 0x9f, 0x17, 0x89, 0x37, 0xa5, 0x3f, 0xcb, 0x6b, 0xc6, 0x79,
+ 0xeb, 0x31, 0x66, 0x10, 0x74, 0x6e, 0xc1, 0xfc, 0xdc, 0xe3, 0x72, 0xe3,
+ 0x78, 0x3f, 0x54, 0x83, 0x4f, 0xf5, 0xe9, 0xbd, 0x4a, 0xd7, 0xcc, 0xea,
+ 0x37, 0x5a, 0x46, 0x06, 0x27, 0x0a, 0xe4, 0xfb, 0x18, 0xf8, 0x96, 0x3e,
+ 0x31, 0xf9, 0x25, 0xa5, 0xe7, 0x50, 0x2a, 0x90, 0x7f, 0x43, 0x9a, 0xc3,
+ 0xc8, 0xc2, 0xb6, 0xec, 0xd1, 0xf1, 0xb1, 0x25, 0xf9, 0xee, 0x0e, 0x68,
+ 0xdc, 0x9d, 0x2d, 0xac, 0x94, 0x1e, 0xd5, 0x41, 0xdd, 0x1e, 0x6f, 0xc3,
+ 0x5e, 0x28, 0x96, 0x7b, 0xbf, 0x1c, 0x29, 0x0f, 0x82, 0x0e, 0x31, 0x79,
+ 0x06, 0x7e, 0xf3, 0x73, 0xe5, 0xbb, 0x64, 0x31, 0x82, 0x7d, 0x55, 0x65,
+ 0x6c, 0x58, 0x9e, 0x9f, 0x8d, 0x7b, 0xd7, 0x09, 0x77, 0xd1, 0xda, 0x8e,
+ 0x3d, 0x50, 0x9e, 0x28, 0x57, 0x1c, 0x17, 0x44, 0x2c, 0xc2, 0x79, 0x8f,
+ 0x18, 0xdd, 0x86, 0x79, 0x8b, 0x11, 0xca, 0x2f, 0xf7, 0x16, 0xf2, 0x64,
+ 0x96, 0x71, 0x15, 0xdf, 0xd9, 0xd8, 0xa4, 0x4c, 0xdd, 0x59, 0x24, 0x14,
+ 0x07, 0xba, 0x74, 0x06, 0xfe, 0x3c, 0xbe, 0x5c, 0xfa, 0xdf, 0x51, 0x50,
+ 0x8f, 0xc2, 0x56, 0x16, 0x60, 0x2b, 0x0b, 0xb0, 0x91, 0x90, 0x85, 0x6b,
+ 0x05, 0xd8, 0xc8, 0x02, 0x6c, 0x24, 0xf4, 0xd9, 0x9b, 0x88, 0xed, 0xde,
+ 0x00, 0x0f, 0x19, 0x5f, 0xfb, 0x30, 0x7d, 0x6d, 0xfc, 0xfd, 0x17, 0xea,
+ 0x52, 0x61, 0x78, 0xd0, 0x71, 0x00, 0x00, 0x00 };
static const u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_RXP_b06FwRodata[(0x24/4) + 1] = {
- 0x08004590, 0x08004590, 0x08004508, 0x08004540, 0x08004574, 0x08004598,
- 0x08004598, 0x08004598, 0x08004478, 0x00000000 };
+ 0x0800458c, 0x0800458c, 0x08004504, 0x0800453c, 0x08004570, 0x08004594,
+ 0x08004594, 0x08004594, 0x08004474, 0x00000000 };
static struct fw_info bnx2_rxp_fw_06 = {
- /* Firmware version: 4.1.1 */
+ /* Firmware version: 4.4.2 */
.ver_major = 0x4,
- .ver_minor = 0x1,
- .ver_fix = 0x1,
+ .ver_minor = 0x4,
+ .ver_fix = 0x2,
.start_addr = 0x080031d0,
.text_addr = 0x08000000,
- .text_len = 0x71d0,
+ .text_len = 0x71cc,
.text_index = 0x0,
.gz_text = bnx2_RXP_b06FwText,
.gz_text_len = sizeof(bnx2_RXP_b06FwText),
@@ -2973,7 +2974,7 @@ static struct fw_info bnx2_rxp_fw_06 = {
.bss_len = 0x44c,
.bss_index = 0x0,
- .rodata_addr = 0x080071d0,
+ .rodata_addr = 0x080071cc,
.rodata_len = 0x24,
.rodata_index = 0x0,
.rodata = bnx2_RXP_b06FwRodata,
@@ -2996,687 +2997,639 @@ static const struct cpu_reg cpu_reg_rxp = {
};
static u8 bnx2_rv2p_proc1[] = {
- /* Date: 12/07/2007 15:02 */
- 0xd5, 0x56, 0x41, 0x6b, 0x13, 0x51, 0x10, 0x9e, 0xdd, 0x6c, 0xbb, 0xdb,
- 0x64, 0xb3, 0x59, 0xaa, 0xd6, 0x50, 0x53, 0x93, 0x06, 0x2f, 0xad, 0x29,
- 0x6d, 0xaa, 0x82, 0x42, 0xa1, 0x92, 0x4b, 0xc1, 0xf6, 0x20, 0xf5, 0x22,
- 0x22, 0xd8, 0x46, 0xd1, 0x5f, 0x21, 0x06, 0xdb, 0xd4, 0x73, 0x05, 0x0b,
- 0xf5, 0xa0, 0x3d, 0x59, 0x11, 0xc1, 0x04, 0x14, 0x44, 0x04, 0x41, 0x45,
- 0x04, 0x3d, 0x78, 0xa8, 0x60, 0x2f, 0xad, 0x22, 0x56, 0x3c, 0x78, 0xd4,
- 0x93, 0x26, 0xbe, 0x37, 0x33, 0xaf, 0xdd, 0xdd, 0x66, 0x9b, 0x2a, 0x82,
- 0x18, 0x68, 0x3f, 0xde, 0xec, 0xbc, 0x37, 0x33, 0xdf, 0xcc, 0x9b, 0x79,
- 0x2e, 0x00, 0xe8, 0x50, 0xaa, 0xa6, 0x05, 0x82, 0xa5, 0x69, 0x96, 0x00,
- 0x0d, 0xe0, 0xae, 0x8d, 0x58, 0xea, 0x77, 0x05, 0xda, 0xda, 0x70, 0x46,
- 0x62, 0x04, 0x86, 0xbb, 0x25, 0xee, 0x87, 0x27, 0x99, 0xa4, 0xc0, 0x9f,
- 0x75, 0x28, 0xc9, 0xf5, 0xee, 0xca, 0xc3, 0x6a, 0x0c, 0xcf, 0x59, 0xed,
- 0x07, 0xfc, 0xbd, 0x8b, 0x10, 0x1e, 0xce, 0x59, 0x88, 0x25, 0x46, 0xe8,
- 0x73, 0x11, 0x96, 0x66, 0x2d, 0x34, 0x57, 0xea, 0xb3, 0x70, 0x1f, 0xe8,
- 0x24, 0x5f, 0x99, 0x4d, 0x88, 0xff, 0x29, 0x78, 0x5f, 0x90, 0x6b, 0x2b,
- 0x3a, 0x8d, 0x7a, 0x15, 0xde, 0x2f, 0xfe, 0x50, 0xff, 0xb8, 0xd8, 0x07,
- 0xfc, 0x53, 0xfb, 0x5c, 0x3c, 0xa7, 0x98, 0x93, 0x7e, 0xb5, 0x0b, 0x83,
- 0xca, 0x1f, 0x9b, 0xe2, 0x4b, 0x93, 0xb6, 0x89, 0xdf, 0xd7, 0x84, 0xdf,
- 0xca, 0x6e, 0x33, 0x7b, 0x41, 0x7f, 0x83, 0x76, 0xe5, 0x79, 0x86, 0xb0,
- 0xe7, 0xb7, 0x03, 0x20, 0xe5, 0xcb, 0xf5, 0x75, 0x79, 0x8f, 0xff, 0xfb,
- 0x6a, 0xaf, 0x3c, 0xaf, 0x05, 0xa0, 0x57, 0xea, 0x2d, 0xb1, 0x3f, 0x83,
- 0xb0, 0x4f, 0x4f, 0xe2, 0x77, 0x03, 0xf7, 0xef, 0x11, 0xe7, 0x4a, 0xec,
- 0x62, 0xec, 0x66, 0x1c, 0x67, 0xbc, 0xca, 0xb8, 0x8b, 0x71, 0x27, 0xe3,
- 0x0e, 0xc6, 0x76, 0xc6, 0x97, 0x8c, 0x2e, 0x63, 0x82, 0xd1, 0x61, 0x7c,
- 0xce, 0x68, 0x33, 0xc6, 0x18, 0x5f, 0x30, 0xbe, 0x62, 0xb4, 0x18, 0x6f,
- 0x30, 0x7e, 0x61, 0xfc, 0xaa, 0xfc, 0xd0, 0x08, 0x1f, 0xf1, 0xfa, 0x10,
- 0xaf, 0x8f, 0x30, 0x02, 0xf3, 0xa4, 0x05, 0x78, 0xba, 0xcf, 0x75, 0x24,
- 0x79, 0xe6, 0xef, 0x3d, 0x4a, 0x8f, 0xf3, 0x84, 0x3c, 0xdd, 0x63, 0xbd,
- 0xf6, 0xca, 0x42, 0xa0, 0xde, 0x32, 0x5b, 0xd6, 0x59, 0xaa, 0x41, 0xde,
- 0x12, 0x18, 0xcf, 0xc4, 0x48, 0x02, 0xed, 0x38, 0xad, 0x24, 0x57, 0x6e,
- 0x9d, 0x4c, 0x10, 0x9e, 0x8b, 0x12, 0x7e, 0x62, 0x3c, 0x1f, 0x23, 0x9c,
- 0x8c, 0x2b, 0x9e, 0xd5, 0x39, 0xca, 0x9f, 0x66, 0x7e, 0x84, 0xd9, 0x53,
- 0x7e, 0x35, 0xb3, 0x4b, 0x58, 0xd4, 0xfd, 0xf1, 0x5f, 0x1f, 0x20, 0x34,
- 0xf2, 0x44, 0xea, 0x9c, 0xdd, 0x26, 0xa0, 0x5e, 0x9f, 0xb7, 0x0d, 0xb9,
- 0x3e, 0x38, 0xff, 0x1a, 0xef, 0xc7, 0xe0, 0x5c, 0x95, 0xfd, 0x4b, 0x28,
- 0x9e, 0xe9, 0xde, 0x64, 0x81, 0xd6, 0xe3, 0xc8, 0xbb, 0xa8, 0xb0, 0x1e,
- 0xee, 0x03, 0x59, 0x7f, 0xbe, 0xa8, 0x6e, 0x23, 0x9c, 0x8f, 0x8b, 0x9c,
- 0x8f, 0xae, 0x90, 0x7c, 0x84, 0xdd, 0xa3, 0xcd, 0xf7, 0xf7, 0x4c, 0x26,
- 0xc8, 0x5b, 0xd8, 0x7d, 0x53, 0x7c, 0x93, 0xf4, 0x77, 0x79, 0xbc, 0xc0,
- 0x3c, 0x16, 0x89, 0xc7, 0xe4, 0xe7, 0x86, 0x3c, 0x65, 0x3c, 0x3c, 0xc9,
- 0x38, 0xf7, 0x86, 0xe4, 0x39, 0x2c, 0xbe, 0xdc, 0x1f, 0xe7, 0x39, 0xe0,
- 0x1f, 0x9c, 0xc5, 0xfe, 0xe4, 0x42, 0x71, 0x44, 0xf9, 0xeb, 0xe7, 0xb9,
- 0x93, 0xf2, 0x0d, 0xd3, 0x79, 0x29, 0xaf, 0x03, 0x3c, 0xd5, 0x71, 0x6d,
- 0x14, 0x34, 0x09, 0x56, 0x31, 0x4f, 0xfb, 0x1d, 0x5d, 0xe7, 0xf5, 0x76,
- 0xeb, 0x42, 0xe5, 0x5d, 0x62, 0x2b, 0x14, 0x26, 0x39, 0xce, 0x2c, 0xd9,
- 0xa3, 0x3a, 0x30, 0xb8, 0x0e, 0x86, 0xb8, 0x7f, 0x05, 0xf9, 0xb0, 0x2a,
- 0x0b, 0xb3, 0xde, 0x7b, 0x9d, 0x84, 0x62, 0x9e, 0xea, 0x6a, 0x73, 0x5e,
- 0xd5, 0xdc, 0x51, 0x7d, 0x09, 0xc5, 0x95, 0x52, 0xc4, 0x17, 0xef, 0x51,
- 0xc8, 0x79, 0x79, 0xd6, 0x1a, 0xd4, 0x47, 0x33, 0x3b, 0xbe, 0xf3, 0x1c,
- 0xc8, 0x35, 0xea, 0x37, 0x26, 0xc7, 0xd5, 0xcd, 0xf5, 0xdd, 0xb1, 0xa9,
- 0xbe, 0xd5, 0x7c, 0xfb, 0x7b, 0x75, 0xce, 0xf1, 0x9b, 0xa8, 0x97, 0x5a,
- 0x79, 0xe0, 0x9d, 0x67, 0x51, 0xcf, 0x3c, 0xa3, 0x6d, 0xa6, 0xf2, 0x3b,
- 0xed, 0x9d, 0x43, 0xb1, 0x90, 0x3c, 0x78, 0xe7, 0x57, 0x30, 0x5e, 0x7f,
- 0x3d, 0x52, 0x5e, 0xa3, 0x1c, 0xbf, 0xd6, 0xa4, 0x2f, 0xb7, 0xb1, 0xde,
- 0x8f, 0x5a, 0xb8, 0x1e, 0x9d, 0x5b, 0xe8, 0xf1, 0xf6, 0xf1, 0xef, 0x35,
- 0x9a, 0x07, 0xdf, 0x6a, 0x8a, 0xdf, 0xc7, 0x21, 0xfc, 0x0e, 0xfd, 0x53,
- 0x7e, 0x21, 0xc0, 0xef, 0x6a, 0x6d, 0x7b, 0xfc, 0x02, 0xc7, 0x0f, 0x21,
- 0xfc, 0xb6, 0x32, 0x0f, 0x6f, 0xb7, 0xe0, 0x4d, 0xea, 0xc5, 0x58, 0xef,
- 0x8d, 0x47, 0x0f, 0xfd, 0x1e, 0xa2, 0x7b, 0x65, 0x16, 0xd7, 0x02, 0xbc,
- 0xe5, 0x73, 0xf2, 0x7e, 0x5f, 0x82, 0x2a, 0xc7, 0xbf, 0xec, 0xe3, 0x21,
- 0x2e, 0xfc, 0x73, 0xd1, 0xfe, 0xed, 0xaa, 0xe2, 0x8b, 0x3e, 0x67, 0x72,
- 0x84, 0x8b, 0xa8, 0xef, 0x7a, 0x78, 0xf3, 0xbe, 0xaf, 0x5c, 0xb8, 0x55,
- 0x55, 0xfd, 0x4c, 0xf6, 0x15, 0x13, 0x06, 0x78, 0x4e, 0x4e, 0x70, 0xff,
- 0xfa, 0x10, 0xa5, 0x3e, 0x59, 0x1c, 0xc5, 0x3e, 0x03, 0x1d, 0xeb, 0xfd,
- 0x8c, 0xd6, 0x9d, 0x71, 0x7a, 0x47, 0x0e, 0x98, 0x36, 0xea, 0x75, 0xc6,
- 0x09, 0x3b, 0x62, 0x72, 0x5f, 0x12, 0x3e, 0x8e, 0xa1, 0x7a, 0x6e, 0xa3,
- 0x3f, 0x05, 0xfb, 0x12, 0xc7, 0x79, 0x40, 0xca, 0x3b, 0x02, 0xfd, 0x48,
- 0xe8, 0xf4, 0x92, 0x7f, 0x37, 0x81, 0xe3, 0x52, 0xfb, 0xd2, 0x92, 0xc7,
- 0xc5, 0x9a, 0xea, 0xe3, 0xd9, 0x11, 0xe9, 0x4f, 0x02, 0x1c, 0x93, 0xf2,
- 0x48, 0x28, 0xf4, 0x74, 0x53, 0x6e, 0x4b, 0x95, 0x75, 0x5a, 0x97, 0x2f,
- 0xe3, 0x31, 0x63, 0x65, 0x25, 0x2f, 0x60, 0x61, 0x8e, 0xdf, 0x79, 0x86,
- 0x72, 0xa7, 0x1a, 0x21, 0xb9, 0x39, 0xaa, 0xf8, 0x48, 0x60, 0x7c, 0x73,
- 0xc4, 0xc7, 0xe9, 0x6b, 0x84, 0xa7, 0xe0, 0x18, 0x62, 0x74, 0x63, 0x2e,
- 0x5b, 0x88, 0x10, 0xf7, 0xf6, 0xdf, 0x16, 0xe1, 0x1e, 0xf6, 0x4d, 0x4f,
- 0x7e, 0x82, 0x73, 0xb5, 0x59, 0x9e, 0xbc, 0x73, 0x5d, 0xe6, 0xa9, 0xd1,
- 0xfc, 0x8e, 0x73, 0x5d, 0x95, 0x9b, 0xd4, 0x9f, 0xea, 0x83, 0x25, 0xae,
- 0xfb, 0x46, 0xef, 0x1a, 0x89, 0x4e, 0xc8, 0xfc, 0x4f, 0xad, 0xfb, 0x95,
- 0x0e, 0x7d, 0x77, 0x91, 0xfe, 0xf6, 0xde, 0x5b, 0x6e, 0xc8, 0x1c, 0xfe,
- 0x1f, 0xde, 0x55, 0x5b, 0xbd, 0xa7, 0x1c, 0xe6, 0xf9, 0x04, 0xf3, 0x6c,
- 0x40, 0x4b, 0x04, 0x89, 0xb1, 0x8d, 0x29, 0x3c, 0x57, 0x2f, 0xd3, 0x58,
- 0xb7, 0x5b, 0x66, 0x70, 0xae, 0x3b, 0xf6, 0x0c, 0xe9, 0x19, 0x24, 0x4f,
- 0x2a, 0xbc, 0x32, 0x45, 0xef, 0x6c, 0x1d, 0x7e, 0x01, 0x50, 0xb6, 0x82,
- 0xa7, 0xd8, 0x0d, 0x00, 0x00, 0x00 };
+ /* Date: 05/13/2008 13:50 */
+ 0xa5, 0x56, 0x4f, 0x48, 0x14, 0x61, 0x14, 0x7f, 0x3b, 0xfb, 0x67, 0xd6,
+ 0xdd, 0xd9, 0x9d, 0x25, 0xff, 0x6d, 0x66, 0xb8, 0x49, 0x97, 0xd5, 0x15,
+ 0xb5, 0x22, 0x3a, 0x18, 0x86, 0x17, 0x21, 0x3b, 0x84, 0x20, 0x45, 0x04,
+ 0xd9, 0x12, 0xde, 0x82, 0x0e, 0xd1, 0x29, 0x68, 0xd1, 0x34, 0x8a, 0x0a,
+ 0x16, 0x52, 0x30, 0xa2, 0xa4, 0x43, 0x85, 0x04, 0xed, 0x74, 0x0a, 0x12,
+ 0x82, 0x8a, 0x88, 0xea, 0x12, 0x78, 0xa8, 0x4b, 0x16, 0x61, 0xd0, 0xa1,
+ 0x83, 0x9d, 0xba, 0xe4, 0xf4, 0xbd, 0xef, 0xbd, 0xcf, 0x9d, 0xf9, 0x9c,
+ 0x55, 0x21, 0x41, 0x7f, 0xbc, 0x6f, 0xde, 0x7b, 0xdf, 0x9b, 0xdf, 0x7b,
+ 0xef, 0x37, 0x66, 0x00, 0xc0, 0x80, 0x92, 0xd3, 0x26, 0x10, 0x52, 0x46,
+ 0x28, 0x2e, 0x20, 0x04, 0xf0, 0x18, 0xe8, 0x27, 0x6a, 0x49, 0xbb, 0xd4,
+ 0xcd, 0x76, 0x27, 0x41, 0xa9, 0x33, 0x23, 0xfe, 0x9e, 0x85, 0xfe, 0x1c,
+ 0x62, 0x18, 0xfa, 0x77, 0x21, 0x1e, 0x84, 0x17, 0xb9, 0xac, 0xc0, 0xbf,
+ 0x2e, 0x94, 0xd0, 0x6e, 0xa8, 0x3c, 0x73, 0x92, 0x32, 0xff, 0x12, 0xc7,
+ 0x7f, 0x0a, 0x13, 0x1e, 0x28, 0xc4, 0x29, 0x0f, 0x23, 0x74, 0x65, 0x24,
+ 0x2c, 0x96, 0xd1, 0x1e, 0x19, 0x81, 0x18, 0xe6, 0x99, 0x12, 0x0e, 0x68,
+ 0xb7, 0x86, 0x4a, 0x5d, 0x5c, 0x97, 0x41, 0x7e, 0x5f, 0xca, 0x36, 0x9e,
+ 0xc3, 0xd7, 0x01, 0xb4, 0xb7, 0x27, 0x2e, 0x97, 0x11, 0xb3, 0x30, 0x16,
+ 0xb7, 0xe8, 0x7d, 0xda, 0x28, 0xed, 0x52, 0x07, 0xc6, 0x09, 0xdf, 0x0e,
+ 0xce, 0x1b, 0xc5, 0xbc, 0x3f, 0x5d, 0xca, 0x8b, 0xf9, 0xbc, 0x79, 0x5a,
+ 0x45, 0x1e, 0x3c, 0x8f, 0x71, 0x5d, 0x31, 0xad, 0xae, 0x98, 0xa8, 0x83,
+ 0x79, 0x00, 0x55, 0x07, 0x62, 0xa3, 0xb8, 0x17, 0xf3, 0xae, 0xf0, 0x7b,
+ 0x03, 0x9c, 0xca, 0x71, 0x7e, 0x07, 0xb1, 0xc2, 0xf9, 0xc4, 0x2f, 0xbf,
+ 0xc7, 0xfa, 0x3c, 0x8a, 0x27, 0x7f, 0xfd, 0x66, 0x41, 0x3d, 0x57, 0xfd,
+ 0xc0, 0x7b, 0x3e, 0x8a, 0x7b, 0xbc, 0xfe, 0xb0, 0x89, 0xff, 0x7b, 0xe1,
+ 0xef, 0xcf, 0x4b, 0xe7, 0x6f, 0xab, 0xe7, 0xf9, 0x20, 0xde, 0xa2, 0x1a,
+ 0x6f, 0x2f, 0x99, 0xb7, 0x41, 0xd8, 0x6d, 0x64, 0xa5, 0x5f, 0x04, 0x10,
+ 0x77, 0x88, 0x02, 0x10, 0x77, 0x32, 0x1e, 0x63, 0xbc, 0xc9, 0x78, 0x83,
+ 0xb1, 0x91, 0xb1, 0x81, 0xb1, 0x9e, 0x71, 0x1b, 0xe3, 0x3b, 0xc6, 0x0c,
+ 0xa3, 0xcd, 0x98, 0x66, 0x7c, 0xc3, 0x68, 0x31, 0x26, 0xb5, 0x7c, 0x2d,
+ 0x8c, 0x71, 0xc6, 0xbb, 0x8c, 0xfb, 0xb5, 0xf8, 0xdf, 0x8c, 0x0b, 0x8c,
+ 0xcd, 0x21, 0xc2, 0x43, 0x6c, 0x23, 0xa1, 0x3c, 0xf7, 0x3e, 0xbe, 0xee,
+ 0xaf, 0xf5, 0x77, 0xb1, 0xcc, 0xcf, 0xf3, 0xca, 0x2f, 0x2e, 0xf9, 0x83,
+ 0x0e, 0xaf, 0xff, 0x9d, 0x0d, 0xfc, 0xc9, 0x6d, 0x20, 0x1f, 0x14, 0x37,
+ 0xed, 0x52, 0x1d, 0xb7, 0x38, 0xbe, 0xbe, 0xb2, 0x50, 0x63, 0x8f, 0xfa,
+ 0x0a, 0xfa, 0x7c, 0x05, 0xed, 0xd1, 0x4e, 0xde, 0xa3, 0xa3, 0xeb, 0xe6,
+ 0x97, 0xe6, 0xd4, 0xbb, 0x87, 0x32, 0x4f, 0x8d, 0x39, 0x7f, 0x1a, 0x2a,
+ 0x16, 0xb2, 0x34, 0x17, 0xa5, 0x8d, 0xee, 0xc5, 0x78, 0x9e, 0xcb, 0xbc,
+ 0x9a, 0x4f, 0xff, 0x5c, 0xd2, 0x7c, 0xc5, 0xb4, 0xf9, 0xba, 0xb0, 0x09,
+ 0xbf, 0x49, 0x8d, 0xa7, 0x73, 0xae, 0xea, 0x97, 0xc1, 0xc7, 0xe3, 0xb1,
+ 0x8c, 0xcc, 0x7b, 0xcd, 0x91, 0x66, 0x83, 0x35, 0x85, 0x76, 0x04, 0xae,
+ 0x3b, 0x2a, 0x8e, 0xf7, 0xb2, 0x43, 0xdd, 0x43, 0xf1, 0x29, 0x20, 0x9e,
+ 0xe7, 0x34, 0x9e, 0x73, 0x5b, 0xd2, 0xa9, 0x15, 0xb7, 0xaa, 0x53, 0xf4,
+ 0xbc, 0x0d, 0xbc, 0x3a, 0x15, 0x87, 0xd1, 0x41, 0x5b, 0xde, 0x9b, 0x8e,
+ 0x51, 0x9a, 0xe3, 0x36, 0xe1, 0x99, 0x04, 0xe1, 0x72, 0xa2, 0x4e, 0xfc,
+ 0x75, 0xdd, 0xb1, 0x24, 0xd9, 0xa7, 0x53, 0x6a, 0x3f, 0x54, 0xbc, 0xaa,
+ 0x6b, 0xa3, 0x7a, 0xf0, 0x7e, 0x75, 0x8f, 0xaa, 0x43, 0xdd, 0xe7, 0xe7,
+ 0xbf, 0xf6, 0xbd, 0x84, 0x45, 0xc3, 0xcf, 0xc3, 0xed, 0x1e, 0xc2, 0x48,
+ 0xaf, 0x84, 0xec, 0x8c, 0x45, 0x71, 0xb3, 0x56, 0x04, 0xed, 0x7d, 0xb3,
+ 0x1f, 0x30, 0xbf, 0xb1, 0x67, 0xc6, 0xe1, 0xfa, 0x6c, 0xd5, 0x3f, 0x79,
+ 0x0e, 0xed, 0x40, 0xf6, 0x30, 0xcf, 0xc3, 0xb0, 0x9c, 0x7b, 0xb1, 0xd7,
+ 0x06, 0x62, 0x0b, 0x94, 0xa4, 0xae, 0x1b, 0x89, 0xd7, 0x32, 0x3e, 0xcc,
+ 0xe7, 0xa2, 0x4f, 0xed, 0xfe, 0x7d, 0x59, 0xa2, 0xfe, 0xc7, 0xfd, 0x73,
+ 0xd3, 0xed, 0x06, 0xcf, 0x63, 0xa2, 0x32, 0x57, 0x0e, 0xea, 0xd7, 0x73,
+ 0xd6, 0xbd, 0x2c, 0x14, 0x7b, 0x6b, 0xe9, 0xb1, 0xfa, 0x0e, 0x2a, 0x3d,
+ 0x92, 0xc7, 0x95, 0x52, 0xd8, 0xc7, 0xcb, 0x21, 0x28, 0x04, 0xe5, 0x7f,
+ 0xa2, 0xbe, 0x2f, 0x01, 0x7b, 0xb4, 0xd9, 0xbd, 0xbe, 0xfc, 0x69, 0x28,
+ 0x04, 0xed, 0x81, 0xa9, 0xed, 0x8d, 0xcd, 0x7b, 0xd3, 0xbc, 0x6e, 0x7e,
+ 0x95, 0x4e, 0xe4, 0x36, 0xd4, 0x89, 0xff, 0xd5, 0x05, 0x03, 0x48, 0x17,
+ 0x50, 0x8f, 0xfd, 0xf7, 0x9b, 0xaa, 0x7e, 0x6d, 0xff, 0xa9, 0xee, 0x3f,
+ 0xab, 0x5b, 0xd3, 0x11, 0xef, 0xfb, 0x07, 0xe9, 0x48, 0x42, 0xd3, 0x85,
+ 0x5f, 0xab, 0x55, 0x1d, 0xc1, 0xe7, 0xf3, 0xf3, 0xd4, 0x97, 0x8b, 0xee,
+ 0x9a, 0xae, 0xfb, 0xf8, 0xac, 0x63, 0x3e, 0x85, 0x9f, 0x8c, 0x5f, 0xd6,
+ 0xe2, 0x55, 0x5f, 0xcf, 0x33, 0xcf, 0x46, 0x1f, 0xcd, 0x95, 0x59, 0xfc,
+ 0xa1, 0xf1, 0xdd, 0x5b, 0xc0, 0xbd, 0xb8, 0x04, 0x0e, 0xf3, 0xf6, 0xd9,
+ 0xc7, 0x5f, 0x8a, 0xf5, 0xc1, 0x84, 0x47, 0x8e, 0xe2, 0x59, 0xf5, 0x87,
+ 0xf0, 0xa1, 0xf4, 0xcf, 0x6c, 0xc2, 0x77, 0x06, 0x1e, 0x38, 0x6a, 0xbf,
+ 0x6d, 0x99, 0xaf, 0x87, 0xf5, 0x64, 0x94, 0xf7, 0xfa, 0x5b, 0x82, 0x74,
+ 0xa3, 0x38, 0x24, 0xf7, 0x14, 0x9a, 0x78, 0xbf, 0x8b, 0x29, 0xb2, 0x5b,
+ 0x52, 0xf4, 0x7f, 0x5b, 0x8f, 0x69, 0x49, 0xbf, 0x96, 0x14, 0x61, 0x53,
+ 0x12, 0xe3, 0xb2, 0xf0, 0xfd, 0x88, 0x74, 0x2f, 0x54, 0xf7, 0x5b, 0xdf,
+ 0x6b, 0x7e, 0xdf, 0xbd, 0x78, 0xde, 0x24, 0xf6, 0xd4, 0xdb, 0x0f, 0x6b,
+ 0x4d, 0x5f, 0xef, 0x71, 0xf5, 0x39, 0xdb, 0xcb, 0xb7, 0x9a, 0xdb, 0x67,
+ 0x35, 0xfa, 0x34, 0xe8, 0x2a, 0xdd, 0x6b, 0x1f, 0xc4, 0x7a, 0x6d, 0x48,
+ 0x9b, 0x34, 0x1f, 0x84, 0x22, 0x8f, 0x61, 0x62, 0x58, 0xeb, 0x24, 0xeb,
+ 0xc4, 0xe4, 0xb8, 0x4c, 0x73, 0x64, 0x52, 0x9d, 0x0f, 0xc8, 0xc1, 0x1f,
+ 0x9e, 0x7f, 0x25, 0xcf, 0xd3, 0x4e, 0x98, 0xce, 0xcd, 0x21, 0xc5, 0x97,
+ 0x2d, 0xdf, 0x7f, 0x86, 0xf8, 0x3a, 0x39, 0x4d, 0x78, 0x02, 0x0e, 0x4b,
+ 0x4c, 0x54, 0xf5, 0x2d, 0x2e, 0x11, 0x52, 0x5e, 0x7d, 0x8b, 0x8a, 0xf2,
+ 0xd0, 0xae, 0xf3, 0xf4, 0x51, 0xff, 0x6e, 0x6c, 0xb5, 0x9f, 0x5e, 0x9d,
+ 0xc4, 0x7e, 0xea, 0x7a, 0x27, 0xe7, 0x46, 0x9b, 0xcf, 0x72, 0x8d, 0xf9,
+ 0xcc, 0xd5, 0x98, 0x6f, 0x5d, 0x2f, 0xae, 0xf2, 0xde, 0x45, 0x20, 0x1a,
+ 0x96, 0x1f, 0x24, 0x2b, 0x32, 0x21, 0xfb, 0x6b, 0x4c, 0xd2, 0x87, 0xd4,
+ 0x8a, 0x4e, 0x85, 0x24, 0x6f, 0xd6, 0x14, 0xf9, 0x45, 0xe8, 0x3c, 0xab,
+ 0xf0, 0xca, 0x84, 0xfa, 0xee, 0xfe, 0x03, 0x65, 0x6c, 0x9a, 0x59, 0x40,
+ 0x0c, 0x00, 0x00, 0x00 };
static u8 bnx2_rv2p_proc2[] = {
- /* Date: 12/07/2007 15:02 */
- 0xed, 0x59, 0x5d, 0x6c, 0x54, 0xc7, 0x15, 0x9e, 0xbd, 0xbb, 0x7b, 0xf7,
- 0x7a, 0x7d, 0xf7, 0xae, 0x71, 0xa8, 0xff, 0xf9, 0xb3, 0x09, 0xd8, 0xa9,
- 0x21, 0xce, 0x9a, 0x98, 0x02, 0x55, 0x63, 0x39, 0x95, 0x81, 0xa6, 0x55,
- 0x0c, 0x49, 0x9b, 0xbe, 0x35, 0x76, 0x02, 0xb6, 0xa9, 0x4d, 0x2d, 0x43,
- 0x83, 0x4a, 0x1b, 0x65, 0x85, 0xd7, 0xf6, 0xcb, 0x26, 0xea, 0x22, 0xc0,
- 0x24, 0xaa, 0xa8, 0x1b, 0xa4, 0x28, 0xea, 0xdb, 0x56, 0x6a, 0x6d, 0xda,
- 0x97, 0xfe, 0x10, 0xb7, 0x4a, 0xa4, 0x42, 0xa5, 0xf6, 0xa1, 0x52, 0x85,
- 0x44, 0xda, 0x62, 0x99, 0xc4, 0x20, 0x63, 0xba, 0x79, 0x21, 0x75, 0x67,
- 0xce, 0x77, 0xe6, 0xee, 0xbd, 0xeb, 0xb5, 0x21, 0x2d, 0x8f, 0xdd, 0x07,
- 0x1f, 0x66, 0xee, 0x99, 0x33, 0xe7, 0xe7, 0x9b, 0x33, 0x67, 0x0e, 0x65,
- 0x42, 0x08, 0x43, 0x24, 0xb3, 0x1b, 0x24, 0x15, 0x56, 0x20, 0x20, 0xf0,
- 0x7b, 0xac, 0x8c, 0xc8, 0x9f, 0xb3, 0x96, 0xfc, 0x1b, 0x16, 0xcf, 0x1b,
- 0x55, 0x34, 0x0e, 0x09, 0x45, 0x1d, 0x21, 0x92, 0x5e, 0x5a, 0xce, 0xf4,
- 0x67, 0x4c, 0x77, 0x1b, 0xa0, 0x3d, 0x4c, 0xeb, 0x98, 0x9e, 0x64, 0xba,
- 0x91, 0xe9, 0x56, 0xa6, 0x27, 0x98, 0x7e, 0x8f, 0xe9, 0x07, 0x4c, 0x77,
- 0xb2, 0x3c, 0xf9, 0x4b, 0xda, 0xf2, 0x4f, 0x40, 0x24, 0x9b, 0xb4, 0x7e,
- 0x36, 0xa6, 0x9b, 0xa0, 0xe7, 0x73, 0x1b, 0x15, 0xdf, 0xcd, 0xa5, 0x3c,
- 0x1f, 0xe6, 0xaf, 0x65, 0x40, 0x37, 0x60, 0xd5, 0x4f, 0x93, 0x8f, 0xeb,
- 0xf5, 0x20, 0xdd, 0x31, 0xd0, 0x9e, 0x20, 0x68, 0x7b, 0x33, 0x91, 0xf4,
- 0x4b, 0x06, 0xc6, 0x9d, 0x5b, 0x2c, 0xb2, 0x2f, 0x64, 0x28, 0x39, 0xeb,
- 0x2d, 0xf3, 0x12, 0xe6, 0xbf, 0x19, 0x07, 0x7d, 0x39, 0x0a, 0xfa, 0x4f,
- 0xa6, 0x87, 0x4b, 0x59, 0xbe, 0xcd, 0x6a, 0x97, 0x62, 0xfd, 0x8c, 0xad,
- 0x68, 0x50, 0x24, 0x79, 0x9d, 0x10, 0xd0, 0xeb, 0xc7, 0x02, 0xdf, 0xd7,
- 0x6c, 0xc5, 0xec, 0x0f, 0x0f, 0x63, 0x5c, 0x7b, 0xb1, 0x8c, 0xf8, 0xcf,
- 0x67, 0xb5, 0xfe, 0x16, 0x79, 0x3f, 0x19, 0x87, 0x1c, 0x51, 0x6f, 0xd1,
- 0x26, 0xc9, 0x66, 0x50, 0xb1, 0x4d, 0xcb, 0xc3, 0xef, 0xdc, 0xa3, 0xda,
- 0x3f, 0x18, 0xaf, 0x4d, 0x80, 0x9e, 0x65, 0x5a, 0xd1, 0x4a, 0x64, 0xfb,
- 0xdf, 0x9f, 0xb0, 0x48, 0x97, 0xe4, 0x36, 0xaf, 0x1f, 0x7f, 0x23, 0xfd,
- 0xc8, 0x82, 0x1a, 0x40, 0x6e, 0x3c, 0xaa, 0xf8, 0xa4, 0x71, 0xf5, 0x90,
- 0x7b, 0xb0, 0xbf, 0x98, 0xff, 0x7f, 0xf9, 0x19, 0xfc, 0xaf, 0xe4, 0xb5,
- 0xb3, 0xfe, 0x1b, 0xa5, 0xfe, 0x8a, 0xd6, 0x05, 0x92, 0xdb, 0xfc, 0xfe,
- 0xb9, 0x96, 0x89, 0xd3, 0xbf, 0x6f, 0x76, 0x94, 0x91, 0xfd, 0xcf, 0x62,
- 0xfe, 0x74, 0xe7, 0x14, 0xfc, 0xb4, 0x9f, 0xe2, 0x22, 0xa2, 0xa9, 0x9f,
- 0x63, 0x55, 0x77, 0x4c, 0x8d, 0x5f, 0xd8, 0x71, 0x23, 0x8b, 0xef, 0xe1,
- 0x11, 0x35, 0x36, 0xe4, 0x3a, 0xfc, 0xf6, 0x07, 0x09, 0xe0, 0x69, 0x73,
- 0x84, 0x86, 0xf6, 0x0c, 0x7d, 0xb7, 0xc5, 0x78, 0x16, 0xdf, 0x8f, 0x96,
- 0xaa, 0xf1, 0xb3, 0xcd, 0x73, 0x18, 0x37, 0xf7, 0x8f, 0xf1, 0x42, 0xa3,
- 0x44, 0xfe, 0x59, 0x5a, 0xba, 0x69, 0x40, 0x1e, 0x87, 0x37, 0x1a, 0x32,
- 0xe2, 0x64, 0xaf, 0xdd, 0x09, 0x3a, 0x4a, 0xdf, 0xef, 0x05, 0xd2, 0x64,
- 0x77, 0xa7, 0x13, 0x9a, 0x02, 0x23, 0xe3, 0xca, 0xc5, 0x8d, 0xc6, 0xdd,
- 0x83, 0xe2, 0x67, 0xcc, 0xc5, 0x0f, 0xfb, 0xbf, 0x69, 0x25, 0xfc, 0x80,
- 0x76, 0x6e, 0x01, 0x35, 0x1b, 0x14, 0x5f, 0xb8, 0x08, 0x8e, 0xfc, 0x7e,
- 0xe6, 0xf8, 0x14, 0xe2, 0x44, 0xe2, 0x03, 0x63, 0xc6, 0x8b, 0xc4, 0x95,
- 0xe2, 0xaf, 0x96, 0xfe, 0xd2, 0xf1, 0x57, 0x82, 0x22, 0xe2, 0xdb, 0x2c,
- 0xaf, 0x9f, 0xed, 0x1a, 0x60, 0x7b, 0xe6, 0xa3, 0xda, 0xaf, 0xda, 0x1e,
- 0xd0, 0x71, 0x9f, 0x3d, 0x01, 0x89, 0x27, 0x8d, 0x23, 0x9f, 0x3e, 0xe9,
- 0xf7, 0xea, 0xf1, 0x8f, 0x5a, 0xc6, 0xa1, 0x6b, 0xe7, 0x16, 0xc5, 0x67,
- 0x26, 0x26, 0xb2, 0x7e, 0x1c, 0x6e, 0x10, 0x5a, 0x8e, 0x96, 0xaf, 0x70,
- 0x99, 0x93, 0xb8, 0x44, 0xdc, 0xce, 0x67, 0xbd, 0xe7, 0xa8, 0xa6, 0xc8,
- 0x39, 0xf2, 0x9f, 0x07, 0xed, 0x97, 0xa3, 0x31, 0x4a, 0x10, 0x3b, 0xae,
- 0xcc, 0xfa, 0xf7, 0x03, 0xbe, 0x23, 0x2e, 0x7e, 0xd6, 0xb6, 0xb1, 0xff,
- 0x98, 0x56, 0xec, 0x54, 0xf2, 0xba, 0x58, 0x7e, 0x0b, 0xcb, 0xb7, 0x0b,
- 0xce, 0xdb, 0x73, 0xee, 0x79, 0xd3, 0x71, 0xcb, 0x9f, 0x3b, 0xed, 0x3f,
- 0xda, 0xbf, 0xf9, 0xca, 0xac, 0x5a, 0x5f, 0x7b, 0x9f, 0x73, 0xb8, 0xbf,
- 0xc8, 0x39, 0x84, 0x9c, 0xbf, 0x3c, 0xee, 0xb7, 0x6b, 0x88, 0xf3, 0x5c,
- 0x0f, 0xe2, 0x66, 0xbd, 0xf4, 0x2b, 0xfe, 0xf0, 0x18, 0xe1, 0x5d, 0xbc,
- 0x18, 0x41, 0x7c, 0x1d, 0xd2, 0x5f, 0xb0, 0x1d, 0x2f, 0x7b, 0xce, 0x6b,
- 0x09, 0xf9, 0xb5, 0xc3, 0xc4, 0x7e, 0x1d, 0xdd, 0x58, 0xde, 0xce, 0x78,
- 0xc8, 0xf1, 0x79, 0x99, 0xb5, 0x49, 0xff, 0xe8, 0x9d, 0x53, 0x98, 0x1f,
- 0xdd, 0x43, 0x24, 0x7d, 0xd5, 0xd0, 0xf6, 0x86, 0xd4, 0xdf, 0xc9, 0x41,
- 0x7c, 0x9f, 0x0c, 0xf1, 0xf9, 0x7c, 0xaf, 0x9e, 0xd6, 0x5b, 0xf3, 0x19,
- 0xac, 0xcf, 0xb1, 0x7e, 0x27, 0x82, 0xc4, 0x1f, 0x1d, 0x63, 0xbe, 0xf1,
- 0x11, 0xbf, 0x9d, 0x3f, 0x40, 0x3e, 0xb7, 0xbf, 0x3f, 0x42, 0xe7, 0xdd,
- 0x31, 0x5d, 0x3e, 0xa2, 0xce, 0xe8, 0x29, 0xc5, 0x5f, 0x29, 0xc6, 0xb2,
- 0x4a, 0xd1, 0x2a, 0xd1, 0xbd, 0x17, 0xeb, 0xde, 0x30, 0x91, 0x6f, 0x7a,
- 0xf7, 0x82, 0x7e, 0x88, 0xf9, 0xf5, 0xce, 0xb8, 0xe2, 0x5f, 0x53, 0xe3,
- 0x4c, 0x29, 0x1a, 0x97, 0xf6, 0x28, 0xfb, 0xa5, 0xed, 0x8c, 0xcf, 0xc1,
- 0x46, 0xf0, 0xf7, 0x1d, 0xa2, 0x8d, 0xcf, 0x0c, 0xe4, 0x28, 0x5f, 0x4d,
- 0x0e, 0x5f, 0x52, 0x7e, 0xa9, 0x16, 0xb3, 0xc7, 0x14, 0x0d, 0x89, 0x8e,
- 0x4d, 0xec, 0x97, 0x3d, 0xfe, 0xfc, 0x3c, 0xbf, 0x53, 0x8d, 0x6b, 0x24,
- 0x9f, 0x17, 0xbf, 0x16, 0xc7, 0x39, 0xe4, 0xfa, 0xf5, 0x13, 0x03, 0x76,
- 0xa7, 0x48, 0xff, 0x3d, 0xd1, 0x14, 0x9d, 0xeb, 0x98, 0xe8, 0x25, 0x3c,
- 0x85, 0xac, 0xc1, 0x4b, 0xf8, 0x3e, 0xff, 0x0b, 0x2d, 0x57, 0xe1, 0x61,
- 0x17, 0xdf, 0x9f, 0xc2, 0x95, 0x13, 0xda, 0xc9, 0x71, 0xd0, 0xfb, 0xb6,
- 0xe2, 0xbe, 0xe9, 0x08, 0xa8, 0xf1, 0x3a, 0x39, 0xb6, 0x29, 0x6e, 0x1d,
- 0xdd, 0x6a, 0xbd, 0x4c, 0x02, 0x74, 0x7e, 0x1c, 0x29, 0x5f, 0xcd, 0x47,
- 0xa4, 0x1d, 0xfe, 0x7d, 0x06, 0x11, 0x0f, 0xfb, 0x28, 0xf9, 0xe7, 0xf3,
- 0xf6, 0xad, 0x8c, 0xb6, 0x07, 0xf3, 0xb7, 0x5d, 0x7d, 0x6c, 0xb2, 0xab,
- 0x63, 0x13, 0xf6, 0x9b, 0x75, 0x78, 0x9f, 0x4d, 0xbc, 0xef, 0x31, 0xb5,
- 0x5f, 0x83, 0x47, 0x5f, 0xc5, 0x67, 0x45, 0x6f, 0x91, 0xdc, 0x75, 0xd6,
- 0x77, 0x2e, 0x91, 0x7f, 0xad, 0xa3, 0x53, 0xd8, 0xff, 0xf6, 0xd4, 0x6a,
- 0x7a, 0xd7, 0xb0, 0x9c, 0x75, 0xec, 0xd7, 0xd8, 0x43, 0x8c, 0xdb, 0xea,
- 0x71, 0xca, 0xfb, 0x57, 0xfb, 0x87, 0xe4, 0xdb, 0x0b, 0xd3, 0xab, 0xe9,
- 0x2b, 0x6d, 0x4a, 0x82, 0x3f, 0x65, 0xd0, 0xc1, 0xa8, 0x82, 0x5f, 0xf2,
- 0x71, 0xd3, 0xfa, 0xce, 0x1f, 0xc2, 0x7d, 0x34, 0xe8, 0xe6, 0x0b, 0x25,
- 0xb7, 0x9d, 0xf1, 0x20, 0xe5, 0x05, 0xe0, 0x9f, 0x85, 0x69, 0x9c, 0x9b,
- 0x13, 0x74, 0x3e, 0xbe, 0x68, 0x87, 0x68, 0xff, 0xa8, 0x75, 0x83, 0xef,
- 0xa5, 0xfc, 0xfd, 0x03, 0x79, 0x7d, 0x36, 0x68, 0x2f, 0xe7, 0xe9, 0x1b,
- 0x4c, 0x53, 0xb6, 0x5a, 0x57, 0x2a, 0xf3, 0xad, 0x45, 0xf2, 0x91, 0x57,
- 0x4b, 0x5c, 0x7d, 0x8f, 0xb0, 0x9c, 0x8f, 0x98, 0x0a, 0x96, 0x33, 0xc0,
- 0xeb, 0xe7, 0x7c, 0x72, 0x0c, 0x8f, 0x1c, 0x7f, 0x3e, 0x1a, 0xe3, 0x7b,
- 0xef, 0xbc, 0xb9, 0x52, 0xbd, 0xa4, 0x68, 0xb9, 0x5c, 0x8f, 0x59, 0x7d,
- 0x2f, 0xa4, 0x1a, 0x89, 0xb4, 0x85, 0x0c, 0xb2, 0x77, 0x32, 0x35, 0x02,
- 0x3f, 0x8d, 0xb3, 0x9f, 0x22, 0xf0, 0x53, 0x4d, 0xfe, 0x9e, 0xe4, 0x8d,
- 0xf8, 0xfc, 0xcd, 0x6c, 0xf6, 0x9f, 0xc7, 0xf3, 0xa6, 0x8e, 0x2f, 0x91,
- 0x34, 0xf2, 0x90, 0xbe, 0x3f, 0xf5, 0xbd, 0x72, 0x4b, 0xe7, 0x6d, 0xb9,
- 0x6f, 0x81, 0x3e, 0x41, 0x8a, 0x73, 0x74, 0x9c, 0xf3, 0xd1, 0xd5, 0xa0,
- 0x8e, 0x27, 0xf4, 0x1b, 0xff, 0x8c, 0xfa, 0xe5, 0xef, 0xe5, 0xb0, 0x22,
- 0xcd, 0xb3, 0xc7, 0x88, 0xb6, 0xf4, 0x1d, 0xc7, 0x7c, 0x65, 0xab, 0xd2,
- 0xe7, 0x27, 0x01, 0x9c, 0xd3, 0xb0, 0x98, 0xc9, 0xe0, 0x9e, 0x13, 0x11,
- 0xd2, 0xa3, 0xee, 0x32, 0xe1, 0xc2, 0x8c, 0xa6, 0x32, 0x3e, 0x7f, 0x79,
- 0xec, 0x2e, 0x66, 0xef, 0x84, 0xc4, 0x93, 0xfa, 0x6e, 0xf2, 0x79, 0x95,
- 0x78, 0xb5, 0xf9, 0xbc, 0x3c, 0x4d, 0x7c, 0xf6, 0x22, 0xd9, 0xf9, 0x0d,
- 0x6b, 0x9c, 0xeb, 0xb4, 0x8f, 0x3b, 0xd5, 0xf8, 0x79, 0xfb, 0x75, 0x9c,
- 0x77, 0xfb, 0x75, 0xe4, 0x5b, 0x2b, 0x7c, 0x11, 0x79, 0xb8, 0xf3, 0xa2,
- 0x6f, 0xff, 0x74, 0xc8, 0xd0, 0xe7, 0xe7, 0x7f, 0xf2, 0x9b, 0xfd, 0x5d,
- 0xf6, 0xdb, 0xdd, 0xd5, 0xe3, 0x9a, 0x36, 0xf9, 0x1c, 0xf6, 0xdd, 0x2d,
- 0xb4, 0x57, 0xf9, 0xef, 0x43, 0xf7, 0x1e, 0x0e, 0xed, 0x62, 0x7d, 0x76,
- 0x71, 0x1e, 0xe0, 0xfa, 0x67, 0x7d, 0x50, 0xdf, 0x8b, 0x1a, 0x0f, 0x7c,
- 0x3f, 0x02, 0xa7, 0xd6, 0x28, 0xec, 0x15, 0xaf, 0xf2, 0x39, 0xf8, 0x37,
- 0xd3, 0xd7, 0x18, 0xff, 0x27, 0xb9, 0x3e, 0xd2, 0xf5, 0xdd, 0x3d, 0xcc,
- 0x3b, 0x13, 0x6e, 0x3d, 0xa4, 0xef, 0x1f, 0x35, 0x0e, 0x08, 0x27, 0x52,
- 0x4a, 0xfb, 0x25, 0x7f, 0x07, 0x80, 0x8d, 0x3f, 0x0d, 0x3f, 0xce, 0xb6,
- 0x82, 0xef, 0x0d, 0xf8, 0xc7, 0xd1, 0xfa, 0x2d, 0x36, 0xfa, 0xde, 0x01,
- 0x6d, 0xf0, 0xaf, 0xe9, 0xfa, 0x57, 0xe3, 0x73, 0x89, 0x69, 0xed, 0x66,
- 0xb6, 0xf3, 0xbf, 0xf3, 0xbb, 0xa7, 0x1e, 0x5b, 0xc9, 0xef, 0xb4, 0xbe,
- 0xad, 0xef, 0x2e, 0xe6, 0xcb, 0x76, 0x83, 0x66, 0x76, 0xd3, 0xfc, 0x66,
- 0xe4, 0xdb, 0x70, 0xdb, 0xe9, 0xfb, 0xd4, 0xa7, 0xfa, 0x5d, 0x53, 0xf9,
- 0x25, 0xd0, 0x33, 0x4c, 0x3f, 0xf7, 0x14, 0xe8, 0xb9, 0xa7, 0xfc, 0x79,
- 0xc4, 0x8c, 0xfb, 0xe2, 0xdb, 0x86, 0xf8, 0xbe, 0xe3, 0xc6, 0x77, 0x3d,
- 0xea, 0x03, 0x19, 0xaf, 0x55, 0xe3, 0xe9, 0xc6, 0xe9, 0x7e, 0xf1, 0x7c,
- 0xd8, 0x71, 0x4c, 0xed, 0xc2, 0x3d, 0x37, 0xcc, 0xef, 0xcd, 0x45, 0xf7,
- 0x9e, 0x2a, 0x16, 0xdf, 0xc8, 0xff, 0xe3, 0x4b, 0xf1, 0x3d, 0xb2, 0xa4,
- 0xf3, 0x1f, 0xee, 0x79, 0x5d, 0xd7, 0x0f, 0x79, 0xea, 0x7a, 0xff, 0xbe,
- 0xdf, 0xa2, 0x7a, 0x79, 0x34, 0xe0, 0xe2, 0x82, 0xf8, 0xa7, 0x79, 0x5d,
- 0x19, 0xaf, 0xdb, 0xb7, 0x6c, 0xdd, 0xb5, 0x8c, 0x5a, 0xf7, 0xb7, 0x4f,
- 0x97, 0xf7, 0x25, 0x7c, 0x7a, 0x26, 0x45, 0x1c, 0xf1, 0xc1, 0x7d, 0x61,
- 0x16, 0xe9, 0x63, 0xf8, 0x71, 0xb7, 0x37, 0x8e, 0x7c, 0xa8, 0xdf, 0x79,
- 0xfe, 0xba, 0xfe, 0x8f, 0x9f, 0xae, 0x5c, 0xd7, 0x6b, 0x79, 0x88, 0x5f,
- 0xb7, 0x11, 0x23, 0xbe, 0xeb, 0x43, 0x6a, 0x5d, 0xbf, 0x6b, 0x5f, 0x3b,
- 0xd9, 0x75, 0x99, 0xed, 0xab, 0x63, 0xfb, 0xe4, 0xe7, 0x6d, 0x74, 0x9f,
- 0x58, 0xd7, 0x87, 0xbc, 0xf6, 0xfd, 0x7a, 0x95, 0xfd, 0x1e, 0xf4, 0x1d,
- 0xc1, 0xfb, 0xc6, 0xf5, 0xfe, 0x4a, 0x5e, 0x2d, 0xd7, 0x63, 0x8e, 0xe0,
- 0xe7, 0x54, 0x91, 0xba, 0x46, 0xed, 0xff, 0x7b, 0xe9, 0x00, 0xbe, 0xc7,
- 0xe8, 0x1d, 0x11, 0xb4, 0x2e, 0x67, 0x8a, 0xf9, 0xe5, 0x6b, 0x01, 0xf0,
- 0x15, 0x8b, 0x9b, 0xfa, 0x1e, 0x66, 0x39, 0xc5, 0xec, 0x66, 0x3d, 0x5d,
- 0x3c, 0xf0, 0x3a, 0xe2, 0xeb, 0x63, 0xbe, 0x50, 0x91, 0xbe, 0x04, 0x46,
- 0xb9, 0xad, 0x54, 0x2f, 0x5e, 0x38, 0x39, 0xad, 0xf8, 0x62, 0xee, 0xbb,
- 0xcc, 0xaf, 0xdf, 0xc4, 0x43, 0xf0, 0x23, 0xbd, 0x3f, 0x44, 0xaf, 0xb3,
- 0x92, 0xbf, 0xf0, 0x7e, 0x5a, 0x98, 0xd6, 0xfe, 0xb6, 0xc9, 0x4e, 0xd4,
- 0xd3, 0x17, 0x0a, 0xfc, 0x68, 0x78, 0xfc, 0x08, 0xfe, 0x95, 0x71, 0xef,
- 0x7f, 0x97, 0x03, 0x17, 0xaf, 0x16, 0xc1, 0x3d, 0xf5, 0xf7, 0x1e, 0xd8,
- 0xce, 0x03, 0xad, 0x5e, 0xbb, 0x1a, 0xc4, 0x4c, 0x16, 0xf8, 0xef, 0x62,
- 0x9c, 0xbc, 0xc8, 0x79, 0xf6, 0x7a, 0x54, 0x4d, 0x58, 0xa2, 0xe7, 0x19,
- 0xe4, 0xe9, 0x8a, 0x52, 0xd8, 0xdd, 0xf3, 0x55, 0xed, 0x27, 0xcc, 0xd7,
- 0xc4, 0x50, 0x57, 0x77, 0x45, 0xf0, 0xbe, 0xa8, 0x89, 0x81, 0x56, 0x70,
- 0x9e, 0x9e, 0x71, 0xfb, 0x29, 0xa0, 0xf9, 0xfa, 0x12, 0x7d, 0xa5, 0xdf,
- 0x9a, 0xa8, 0xc3, 0x45, 0x13, 0xd7, 0xcf, 0x94, 0xef, 0x82, 0xe2, 0x60,
- 0x13, 0x70, 0x22, 0xea, 0xfd, 0x79, 0x8a, 0xf3, 0xec, 0xb2, 0x7a, 0x0d,
- 0x7d, 0x99, 0x12, 0x4f, 0x5f, 0x42, 0xef, 0xa7, 0xfd, 0xa8, 0xe5, 0xd2,
- 0x70, 0x85, 0xba, 0x72, 0x91, 0xf3, 0xd8, 0x23, 0xe2, 0x0f, 0x59, 0xd8,
- 0x35, 0x93, 0x2d, 0xc4, 0x95, 0xde, 0x4f, 0xcb, 0x83, 0xde, 0xda, 0x8e,
- 0xbc, 0x7c, 0xec, 0x7f, 0x88, 0xf5, 0xfc, 0x07, 0xf5, 0x33, 0x2b, 0xd8,
- 0x1e, 0x25, 0x17, 0xf3, 0xfb, 0xb8, 0x4f, 0x94, 0x74, 0xc7, 0xfe, 0xfe,
- 0x4e, 0x17, 0xe9, 0xb5, 0x86, 0x71, 0x54, 0xe1, 0xc1, 0x39, 0xf8, 0xd7,
- 0xb6, 0x80, 0x9e, 0x6d, 0xd1, 0x71, 0xd0, 0xf1, 0xd2, 0xf1, 0x41, 0x1c,
- 0x2b, 0xd0, 0x4f, 0xda, 0xd1, 0xf3, 0x04, 0xdd, 0x0f, 0x2d, 0x3d, 0x0b,
- 0xfa, 0xdc, 0x61, 0xfd, 0x81, 0x66, 0xc5, 0xff, 0x9a, 0xf8, 0x13, 0xf7,
- 0x1b, 0xfe, 0xca, 0xb4, 0xb0, 0x6f, 0x82, 0xbe, 0x8b, 0x8c, 0x5b, 0x98,
- 0x03, 0xd2, 0xaa, 0xf3, 0xac, 0xf7, 0x9d, 0xa0, 0xcf, 0xdf, 0xd6, 0x65,
- 0x78, 0xcd, 0xe7, 0x4b, 0x6d, 0x9f, 0xe2, 0x6f, 0x66, 0x1c, 0xca, 0xf7,
- 0xe9, 0x5e, 0xa5, 0x47, 0x5c, 0xde, 0xdb, 0xc8, 0xc7, 0x4e, 0xc4, 0x1b,
- 0x27, 0x89, 0x87, 0x92, 0x88, 0x1a, 0xd6, 0x95, 0x97, 0x90, 0x1d, 0xa7,
- 0xdf, 0xff, 0x80, 0x3e, 0xbf, 0x3d, 0x51, 0x8a, 0xf9, 0xca, 0x67, 0xe2,
- 0xe4, 0x87, 0x73, 0xc0, 0xf1, 0x8f, 0xce, 0x82, 0xbe, 0x25, 0xbe, 0x82,
- 0xf5, 0xe5, 0xa7, 0xe8, 0xfe, 0xb7, 0x2a, 0x19, 0x97, 0x55, 0x38, 0xf7,
- 0x69, 0xd4, 0x0f, 0x4b, 0x4b, 0x22, 0x86, 0xba, 0x4d, 0xdf, 0x03, 0xc0,
- 0x65, 0xc8, 0x13, 0xdf, 0xfb, 0xe1, 0x54, 0x51, 0xbb, 0xf0, 0x9d, 0x64,
- 0x15, 0xe2, 0x55, 0xfb, 0xa3, 0xca, 0x28, 0x8a, 0xcf, 0x36, 0x3f, 0x3e,
- 0x4d, 0xc6, 0xe7, 0x5d, 0xb7, 0x8e, 0x5a, 0x2e, 0x97, 0xde, 0x89, 0x12,
- 0xb7, 0x0f, 0x0b, 0xaf, 0xa0, 0xfb, 0x1a, 0xd4, 0xfe, 0x95, 0xcb, 0xf2,
- 0xeb, 0x06, 0x5f, 0x9c, 0x6f, 0xde, 0xd3, 0x7a, 0x9d, 0x32, 0xbd, 0xdf,
- 0x5b, 0xdc, 0x7b, 0x66, 0x98, 0xfb, 0xfc, 0x39, 0xf4, 0xa3, 0x12, 0xf3,
- 0x69, 0x1a, 0xda, 0xd5, 0xef, 0x52, 0xdf, 0x22, 0x31, 0xcc, 0xf9, 0xf3,
- 0xfd, 0xa0, 0xae, 0xb7, 0x30, 0xbe, 0xc2, 0x79, 0xe3, 0x0e, 0xeb, 0x75,
- 0x80, 0x61, 0x39, 0xdf, 0x48, 0x79, 0x37, 0xa1, 0xeb, 0xb4, 0x61, 0x7e,
- 0x5f, 0xe8, 0x3e, 0xd5, 0x97, 0x83, 0x9c, 0x4f, 0xc9, 0x8f, 0xa1, 0xc4,
- 0xed, 0x29, 0xdd, 0x4f, 0xd0, 0xfd, 0x05, 0xd6, 0x07, 0xfd, 0x30, 0x71,
- 0x30, 0x02, 0x2a, 0x9a, 0xfc, 0xf1, 0x11, 0xae, 0x9d, 0x18, 0x99, 0x05,
- 0xfd, 0x86, 0x08, 0xf7, 0x09, 0x27, 0x58, 0xbf, 0x33, 0xfc, 0xbe, 0x73,
- 0xc8, 0x4f, 0x65, 0xd2, 0x7e, 0xea, 0x5b, 0x25, 0x8e, 0x4d, 0xc3, 0xae,
- 0x01, 0xf7, 0xfd, 0x06, 0x3e, 0xa6, 0xce, 0x9b, 0xdc, 0x2f, 0xe3, 0xbe,
- 0x9a, 0x63, 0x8e, 0xc0, 0x9e, 0x81, 0x1c, 0xc6, 0x8b, 0x78, 0x17, 0x39,
- 0xff, 0xe2, 0x3a, 0xef, 0xf8, 0x49, 0xfd, 0x1e, 0x2c, 0xbe, 0x4e, 0xd7,
- 0x85, 0x83, 0xf4, 0x2e, 0x79, 0x61, 0x92, 0xfb, 0xea, 0xa2, 0x9f, 0xea,
- 0xd1, 0xaf, 0xdb, 0x39, 0x1e, 0xe7, 0xfb, 0x07, 0xfe, 0xbe, 0x81, 0xae,
- 0xbf, 0xe7, 0xd0, 0xff, 0x9c, 0xcc, 0xa5, 0x81, 0x97, 0x64, 0x89, 0x17,
- 0xe7, 0x25, 0x89, 0x4a, 0x8e, 0xdb, 0xda, 0x27, 0x41, 0xcf, 0x3e, 0x89,
- 0x77, 0xf2, 0xc0, 0x2b, 0xec, 0x97, 0x1d, 0x14, 0xa7, 0xed, 0xe8, 0xbf,
- 0x78, 0xeb, 0x50, 0x85, 0x9b, 0x4f, 0x5c, 0x3c, 0xcf, 0x91, 0x5e, 0xb5,
- 0x93, 0x39, 0xe2, 0xab, 0x11, 0x8f, 0xd0, 0xbd, 0x57, 0xed, 0x2c, 0x40,
- 0xcf, 0xc4, 0x04, 0xdb, 0x37, 0xf4, 0x05, 0xd0, 0x57, 0x38, 0xce, 0x3a,
- 0x7e, 0x57, 0xdd, 0x3e, 0x1e, 0xf4, 0xd5, 0xf7, 0xf1, 0xf2, 0xf7, 0x3b,
- 0xc6, 0xd5, 0xad, 0x48, 0x60, 0x7d, 0xc7, 0x8b, 0xf7, 0xa7, 0xfc, 0x78,
- 0x50, 0x78, 0xd1, 0xb8, 0xf4, 0xe2, 0xa8, 0xf0, 0x9c, 0xe5, 0x71, 0xe1,
- 0x34, 0x55, 0x91, 0xbf, 0x70, 0x9f, 0x98, 0x89, 0x89, 0xcc, 0xea, 0x7e,
- 0x7a, 0x13, 0x7e, 0x4a, 0xb0, 0xde, 0x76, 0xff, 0x08, 0xee, 0xa1, 0x31,
- 0x8e, 0xd3, 0x5c, 0x23, 0xd7, 0x11, 0xac, 0xdf, 0xc7, 0xfc, 0xce, 0x40,
- 0x3c, 0x23, 0xf6, 0xe1, 0x69, 0x8e, 0x1f, 0xe3, 0xea, 0x08, 0xdb, 0xfd,
- 0x11, 0xec, 0xb6, 0xb5, 0xdd, 0xfd, 0xae, 0xdd, 0xba, 0x4e, 0xf1, 0xca,
- 0x29, 0x97, 0xb8, 0xa0, 0x7a, 0xc7, 0xbe, 0x4a, 0x79, 0x24, 0xcc, 0x76,
- 0x4a, 0xbe, 0x56, 0xfd, 0xff, 0x8e, 0xf0, 0x57, 0xef, 0x76, 0xef, 0xba,
- 0x52, 0x5e, 0x17, 0x95, 0xeb, 0x30, 0x8f, 0xf3, 0x67, 0xaf, 0xe0, 0x4f,
- 0xe5, 0x37, 0x2d, 0xb7, 0xf0, 0x7c, 0x79, 0xfd, 0x47, 0x95, 0x1d, 0xfd,
- 0x90, 0x57, 0x64, 0x9c, 0xe8, 0x1e, 0xb2, 0xdd, 0xbc, 0x72, 0x87, 0xea,
- 0xc0, 0xe8, 0x85, 0x41, 0xe4, 0x81, 0x0b, 0x83, 0xef, 0x72, 0x1d, 0xce,
- 0x7e, 0xe9, 0xa2, 0xff, 0xaf, 0x92, 0xb1, 0xab, 0xf7, 0xe7, 0x15, 0xbf,
- 0x1e, 0xb5, 0x1e, 0x3d, 0xf4, 0xbe, 0xff, 0x01, 0xfe, 0xf0, 0x11, 0xdc,
- 0xa0, 0x1d, 0x00, 0x00, 0x00 };
+ /* Date: 05/13/2008 13:50 */
+ 0xad, 0x58, 0x4d, 0x6c, 0x54, 0x55, 0x14, 0xbe, 0x7d, 0xf3, 0xdb, 0x99,
+ 0x37, 0x3f, 0xb4, 0xb5, 0xbf, 0x68, 0xa1, 0x95, 0xd2, 0x92, 0x29, 0x94,
+ 0x69, 0x01, 0x95, 0x44, 0x49, 0x31, 0x05, 0x94, 0x84, 0x52, 0x5d, 0x10,
+ 0x37, 0xd0, 0x22, 0xa5, 0x83, 0x2d, 0x69, 0x28, 0x61, 0xc1, 0xc6, 0x09,
+ 0xc5, 0xe2, 0x62, 0x12, 0x2d, 0xb1, 0x14, 0x8c, 0xc1, 0x46, 0x37, 0xc4,
+ 0xb8, 0x19, 0x83, 0x52, 0xd4, 0xc4, 0x84, 0x60, 0x43, 0x70, 0x01, 0x26,
+ 0x9a, 0xe0, 0x42, 0x13, 0xa2, 0x50, 0x0b, 0x36, 0x58, 0x7e, 0x46, 0x17,
+ 0xca, 0x78, 0xef, 0xf9, 0xce, 0x7d, 0x7d, 0x6f, 0x3a, 0xb5, 0x2c, 0xe8,
+ 0xe6, 0xeb, 0xbd, 0xef, 0xdc, 0x73, 0xcf, 0xcf, 0x77, 0xcf, 0x39, 0x6d,
+ 0x54, 0x08, 0xe1, 0x16, 0xc9, 0x74, 0xb5, 0x44, 0x11, 0x32, 0x0a, 0xfc,
+ 0x12, 0xb2, 0x42, 0x78, 0xca, 0xd5, 0x5a, 0x18, 0x82, 0x7f, 0x56, 0x44,
+ 0x09, 0x7e, 0x48, 0xab, 0xef, 0x3e, 0xf1, 0xaa, 0x81, 0xef, 0x6e, 0xa1,
+ 0x30, 0x22, 0x44, 0x52, 0x61, 0x94, 0x71, 0x3d, 0x63, 0x86, 0x31, 0x58,
+ 0x00, 0x6c, 0x66, 0x7c, 0xc0, 0xfb, 0x77, 0x78, 0x7d, 0x93, 0xf1, 0x6f,
+ 0xde, 0x37, 0x19, 0x6f, 0xf3, 0xfe, 0xf3, 0x06, 0x30, 0xc1, 0xfb, 0x3f,
+ 0x4b, 0xd4, 0x76, 0xa9, 0xf5, 0x74, 0x56, 0x24, 0xe5, 0x19, 0x21, 0xc5,
+ 0x1b, 0xf4, 0xbe, 0x49, 0x90, 0x6c, 0x80, 0xdd, 0xaf, 0x2c, 0x51, 0x72,
+ 0xbf, 0xe7, 0x91, 0x53, 0xfb, 0x37, 0xb2, 0xd0, 0x3b, 0xeb, 0xaf, 0xe1,
+ 0x51, 0xe7, 0x96, 0xb6, 0x9c, 0x18, 0xc6, 0xf9, 0x9d, 0x4b, 0xb0, 0xff,
+ 0x54, 0x4c, 0xf9, 0xef, 0x15, 0x49, 0x46, 0xd1, 0xa8, 0xd0, 0x28, 0x48,
+ 0x36, 0xea, 0x40, 0x41, 0xfe, 0x97, 0x61, 0xac, 0x3a, 0x43, 0xd0, 0x1b,
+ 0x70, 0xe8, 0x2d, 0x9d, 0xa3, 0xf7, 0x5a, 0xa1, 0x5d, 0xff, 0x67, 0xac,
+ 0x3f, 0xb0, 0xa0, 0xfe, 0xae, 0x10, 0xb0, 0x38, 0x96, 0xef, 0x9e, 0xc2,
+ 0x05, 0xec, 0xdf, 0xb7, 0xa0, 0xfe, 0xc3, 0x96, 0xfd, 0x3a, 0x6e, 0xfa,
+ 0x3b, 0xb0, 0x1a, 0x62, 0x9f, 0x24, 0x57, 0xe9, 0x78, 0x6a, 0xbf, 0xd9,
+ 0x3e, 0x17, 0x70, 0x43, 0x8c, 0x20, 0xb5, 0x9b, 0x03, 0xdc, 0x56, 0xa7,
+ 0xee, 0x2d, 0x12, 0x6e, 0x43, 0xe9, 0x59, 0xee, 0xf7, 0x9e, 0xc7, 0xfe,
+ 0x8e, 0x08, 0xf0, 0x75, 0x76, 0xe4, 0x46, 0x40, 0x05, 0x26, 0x9b, 0xed,
+ 0x0e, 0xb2, 0x7e, 0xa4, 0x55, 0x24, 0x83, 0x38, 0x3f, 0x61, 0x2a, 0xfb,
+ 0x2e, 0xcb, 0xfc, 0xa9, 0xb5, 0x4b, 0x24, 0x23, 0x4e, 0x3f, 0x3e, 0x14,
+ 0x90, 0x5b, 0xb4, 0x1c, 0xbb, 0xef, 0x76, 0x63, 0x5d, 0xf5, 0x71, 0x94,
+ 0xe4, 0x4f, 0xa6, 0xb5, 0x1f, 0x6a, 0x5f, 0xbe, 0x83, 0x08, 0xf4, 0x88,
+ 0x1a, 0x3f, 0x5d, 0x86, 0x38, 0xc9, 0x4b, 0x1b, 0xb5, 0x3e, 0xfc, 0x9c,
+ 0x58, 0xa6, 0xf9, 0x85, 0x75, 0xb7, 0x97, 0xa0, 0xbc, 0x73, 0x48, 0xd9,
+ 0x1b, 0x11, 0xbb, 0x0c, 0x65, 0x88, 0xc1, 0xfe, 0xb9, 0xfc, 0xe6, 0x17,
+ 0x90, 0xff, 0xa6, 0xda, 0x24, 0xdb, 0xba, 0x9b, 0x71, 0xae, 0x24, 0x0e,
+ 0x1c, 0x89, 0x7b, 0x14, 0xc4, 0xba, 0x07, 0x68, 0xb9, 0xf2, 0xd7, 0xd5,
+ 0x7e, 0x92, 0x4b, 0x36, 0x6a, 0xfe, 0xea, 0xb8, 0x2b, 0x7f, 0xdf, 0xc9,
+ 0x5a, 0xfc, 0xaf, 0x45, 0x7c, 0x6e, 0x2e, 0x53, 0xf2, 0x32, 0x48, 0x35,
+ 0xb8, 0xa7, 0x23, 0x91, 0x8f, 0xff, 0x6f, 0xdb, 0xf8, 0xff, 0x68, 0x79,
+ 0xdc, 0x40, 0xfe, 0x6f, 0xe0, 0x38, 0x2c, 0x61, 0xbe, 0x2c, 0xce, 0xc3,
+ 0x97, 0x08, 0xfd, 0x7e, 0xab, 0x35, 0x4a, 0x71, 0xdc, 0x86, 0xfd, 0xe3,
+ 0x6d, 0xe7, 0x10, 0xef, 0x2d, 0x14, 0x07, 0x11, 0x38, 0xfa, 0x39, 0x4e,
+ 0x75, 0x86, 0xd4, 0xfa, 0xb5, 0x96, 0xee, 0x2f, 0xb1, 0xee, 0x72, 0xa9,
+ 0xf5, 0x0e, 0x73, 0xf7, 0x38, 0xe4, 0x3d, 0x83, 0x51, 0x8a, 0xdf, 0x36,
+ 0xbe, 0x65, 0x8b, 0xab, 0x40, 0x41, 0xca, 0x3b, 0x48, 0x4b, 0x73, 0x82,
+ 0xbe, 0x47, 0xc5, 0xb1, 0x34, 0xbe, 0xef, 0x0f, 0x52, 0x7d, 0x90, 0xfe,
+ 0x91, 0x5c, 0x49, 0xc2, 0x8b, 0xf3, 0xa9, 0x61, 0x3f, 0xf9, 0x3b, 0x75,
+ 0x56, 0xad, 0xb7, 0xc6, 0xa6, 0x20, 0x1f, 0x4b, 0x0c, 0xb1, 0x62, 0x03,
+ 0xf1, 0xbb, 0x65, 0x40, 0x9e, 0xe9, 0x15, 0x70, 0x53, 0xfe, 0x0a, 0x84,
+ 0xd9, 0x06, 0x7c, 0x8b, 0xbe, 0xff, 0x53, 0x90, 0xa2, 0x78, 0x6d, 0x0c,
+ 0xbb, 0xcf, 0xe9, 0xf8, 0x30, 0x46, 0xb4, 0x5f, 0xc0, 0x47, 0xe5, 0xef,
+ 0x90, 0xa9, 0x79, 0xcb, 0x79, 0x6b, 0x98, 0x8f, 0xb7, 0xc0, 0xb6, 0x3a,
+ 0xa0, 0xb7, 0x56, 0xc9, 0x79, 0xf2, 0xf0, 0xd7, 0x99, 0x17, 0xce, 0xab,
+ 0x8d, 0x67, 0x04, 0x92, 0x5f, 0x0e, 0xbe, 0x49, 0x3e, 0x53, 0x5d, 0x92,
+ 0xf1, 0xd4, 0xbc, 0x51, 0x8a, 0x7c, 0xe2, 0x0d, 0xd6, 0x97, 0x60, 0xbf,
+ 0x7a, 0xd9, 0xaf, 0xe9, 0x80, 0x8e, 0xbb, 0xf6, 0x07, 0x78, 0xcc, 0x04,
+ 0xbf, 0x3a, 0x12, 0xda, 0x2f, 0x27, 0x7f, 0xd9, 0x9e, 0xd4, 0xb7, 0x35,
+ 0xf8, 0xa5, 0xaa, 0x16, 0x68, 0xf9, 0x59, 0x47, 0xef, 0x25, 0x5c, 0x36,
+ 0xae, 0xed, 0x50, 0x79, 0xfd, 0x4b, 0xe6, 0x15, 0xf9, 0x39, 0x99, 0xb6,
+ 0xbf, 0xd3, 0xca, 0x3c, 0xef, 0xd4, 0xf9, 0x6e, 0xb4, 0xff, 0xfb, 0x43,
+ 0x54, 0x88, 0x5a, 0xae, 0x4c, 0x3a, 0xdf, 0x05, 0xf8, 0xef, 0xb3, 0x78,
+ 0x54, 0xb2, 0x96, 0xe3, 0xc4, 0x58, 0xba, 0x4e, 0xe9, 0x6b, 0x67, 0xfd,
+ 0x4d, 0xac, 0xdf, 0xb4, 0xbd, 0x4b, 0x65, 0xdf, 0x93, 0xd6, 0x7b, 0xd4,
+ 0xf9, 0x99, 0x7d, 0x97, 0x3a, 0x4e, 0x74, 0x7f, 0xec, 0xca, 0xa4, 0x3a,
+ 0x5f, 0xb5, 0xc0, 0x3b, 0x2d, 0xb6, 0xf4, 0xfd, 0x68, 0xbd, 0x47, 0xf5,
+ 0x3d, 0x28, 0x5e, 0xe0, 0xa5, 0xb3, 0xde, 0xfc, 0x29, 0xeb, 0x0d, 0xf9,
+ 0xe1, 0x37, 0xcf, 0x71, 0x7d, 0x19, 0x50, 0xf7, 0x94, 0xb3, 0xdd, 0xe5,
+ 0xba, 0xce, 0x4b, 0xbb, 0xb9, 0x0e, 0xed, 0xb4, 0xd7, 0x13, 0x8f, 0xad,
+ 0x2e, 0xa8, 0xb5, 0x2b, 0x4f, 0x9f, 0x74, 0xc4, 0x33, 0x29, 0x22, 0x98,
+ 0x03, 0x92, 0x11, 0x25, 0x7f, 0x4f, 0xcc, 0xad, 0x2b, 0xb9, 0xf6, 0x23,
+ 0x1e, 0x9d, 0x46, 0x88, 0xe4, 0xae, 0xf7, 0xab, 0x73, 0xd7, 0xac, 0x3e,
+ 0x8e, 0x3a, 0x73, 0x91, 0xed, 0x5d, 0xcc, 0xf6, 0x4a, 0x7d, 0x8d, 0xc4,
+ 0x53, 0xff, 0xf5, 0x7e, 0xbb, 0xbd, 0x77, 0x1e, 0xce, 0x7f, 0x9f, 0x33,
+ 0xef, 0xfd, 0xdc, 0x6f, 0xb8, 0x4f, 0xfa, 0x77, 0x7f, 0xa5, 0xed, 0xe1,
+ 0x7b, 0x23, 0xfa, 0x7e, 0x93, 0xf2, 0x32, 0x39, 0xa0, 0xce, 0x87, 0x05,
+ 0xd3, 0x44, 0xf4, 0xd5, 0xa3, 0xae, 0x4d, 0xef, 0x81, 0xfd, 0x7d, 0x75,
+ 0xea, 0xfe, 0x16, 0x81, 0x7e, 0xe3, 0x96, 0x21, 0x45, 0x7d, 0xbf, 0x38,
+ 0x9c, 0x2f, 0x8f, 0x5f, 0xb3, 0xdc, 0x38, 0xfb, 0x15, 0x65, 0xbf, 0x36,
+ 0x4b, 0xbf, 0x28, 0xee, 0xfc, 0x3d, 0x9f, 0xdf, 0x6c, 0xa7, 0xd0, 0xfd,
+ 0x9b, 0xcf, 0x91, 0x5c, 0x0f, 0xcb, 0xb9, 0xe7, 0xed, 0xdb, 0x99, 0xe5,
+ 0x54, 0x87, 0x4f, 0x1f, 0xa6, 0x7a, 0x1a, 0xb2, 0xf8, 0xe6, 0xb4, 0x6f,
+ 0xe2, 0x31, 0xc4, 0x51, 0xc9, 0x2d, 0x12, 0x7b, 0xc3, 0xf3, 0xc5, 0xcb,
+ 0xad, 0xb6, 0xc7, 0x66, 0xc6, 0x75, 0xbc, 0x4d, 0xf2, 0x73, 0x72, 0x80,
+ 0xe6, 0xc2, 0x9c, 0x38, 0x1a, 0xb6, 0x38, 0x42, 0x1e, 0xf3, 0x4a, 0xbe,
+ 0xf8, 0xe5, 0xeb, 0x8b, 0x9f, 0x3e, 0xd4, 0x7c, 0x3a, 0xe2, 0xd5, 0xf6,
+ 0x2b, 0x5c, 0x65, 0xe5, 0xf3, 0x00, 0xcf, 0x23, 0x19, 0x93, 0x7e, 0x89,
+ 0x4f, 0xa7, 0x68, 0x69, 0x56, 0x9c, 0x51, 0x72, 0x2b, 0xe2, 0x07, 0xd8,
+ 0xce, 0xcb, 0x2e, 0xf8, 0xd1, 0xb3, 0x07, 0xeb, 0x2b, 0x5c, 0xdf, 0xee,
+ 0x72, 0x9d, 0xda, 0xee, 0x07, 0x4e, 0xd7, 0x93, 0x7f, 0xf1, 0x03, 0xe7,
+ 0xb5, 0x7e, 0xd2, 0x6b, 0x66, 0x38, 0x3e, 0x2f, 0xba, 0xd8, 0xee, 0x1a,
+ 0xca, 0x47, 0xfc, 0x0e, 0xbd, 0x4f, 0xb7, 0x68, 0x5d, 0xaa, 0xb0, 0x42,
+ 0xc6, 0x81, 0xed, 0x59, 0x0f, 0xec, 0xf0, 0x71, 0x5c, 0x1b, 0x72, 0xf3,
+ 0x85, 0x6d, 0x6f, 0x0d, 0x9f, 0xef, 0xc4, 0xda, 0xc7, 0xf5, 0x65, 0x94,
+ 0xed, 0x7a, 0xaf, 0x1e, 0x18, 0x6e, 0x40, 0x7f, 0x9c, 0x34, 0x15, 0x46,
+ 0xe2, 0x03, 0xe3, 0xf0, 0xa7, 0x77, 0x23, 0xfc, 0xbd, 0xc7, 0x71, 0x60,
+ 0x0c, 0x9f, 0x1a, 0xa4, 0xbe, 0x19, 0x1e, 0x42, 0x7f, 0x0d, 0x7b, 0x07,
+ 0xe1, 0x47, 0x6f, 0x06, 0xeb, 0x7b, 0xcf, 0x02, 0x1f, 0x3c, 0x87, 0x73,
+ 0x07, 0x0f, 0x73, 0x7c, 0x36, 0xe6, 0x3f, 0xd7, 0x73, 0x1f, 0x72, 0x7d,
+ 0xf5, 0xd4, 0xe7, 0xc7, 0xb8, 0xef, 0x8a, 0x04, 0xf7, 0xf9, 0x0c, 0xaf,
+ 0xf7, 0x71, 0x1f, 0xb9, 0xcd, 0x7d, 0xb2, 0x37, 0xa7, 0x4f, 0x4e, 0xa1,
+ 0x6e, 0x8e, 0x65, 0x52, 0x6a, 0x43, 0xd6, 0xaf, 0x42, 0xdd, 0x1f, 0x15,
+ 0x06, 0xe2, 0x65, 0x9c, 0xaf, 0x92, 0x35, 0xc0, 0x91, 0x35, 0xe8, 0x6b,
+ 0xbd, 0x87, 0x38, 0x2e, 0x2d, 0x94, 0x9f, 0x95, 0x33, 0xe3, 0x9a, 0x0f,
+ 0x34, 0x3f, 0x3d, 0xd4, 0xbc, 0x43, 0xfd, 0xca, 0x58, 0xf5, 0x76, 0x8a,
+ 0xec, 0xab, 0x1a, 0xcb, 0x90, 0x7c, 0xa5, 0x28, 0x26, 0x7e, 0x55, 0x84,
+ 0x67, 0x60, 0x6f, 0x7c, 0x94, 0xfd, 0xec, 0x7f, 0x06, 0x78, 0x88, 0xf3,
+ 0xac, 0xf3, 0x77, 0x75, 0x9d, 0x49, 0xe7, 0x26, 0x07, 0x60, 0xb7, 0xe6,
+ 0x7d, 0xee, 0x9c, 0xa7, 0xf3, 0x5e, 0xd1, 0x4c, 0x6b, 0xd1, 0x73, 0x50,
+ 0xdd, 0x13, 0x92, 0xf9, 0x52, 0x76, 0xc9, 0x58, 0x70, 0x7f, 0x74, 0xf2,
+ 0x41, 0xf1, 0x45, 0xf3, 0xd2, 0xce, 0x23, 0x3b, 0x4f, 0x9c, 0xfc, 0x08,
+ 0x53, 0x3d, 0x97, 0x8f, 0x97, 0xfa, 0xa7, 0x37, 0x3e, 0x3a, 0xfc, 0xff,
+ 0xf1, 0x3a, 0x85, 0x78, 0xc5, 0xd9, 0x6e, 0x33, 0x41, 0x73, 0xd6, 0x13,
+ 0x62, 0x88, 0xf3, 0x35, 0x55, 0xcf, 0xef, 0xb5, 0x06, 0xf9, 0xea, 0x7f,
+ 0x1a, 0xf6, 0xf4, 0xf3, 0x3b, 0xf9, 0x83, 0xfb, 0x39, 0xf2, 0xec, 0x33,
+ 0xbb, 0xc7, 0x39, 0xaf, 0xcc, 0xb7, 0x7d, 0x1c, 0x87, 0xdb, 0x88, 0x83,
+ 0xa9, 0xe3, 0x90, 0xb0, 0xe2, 0xa0, 0xeb, 0x83, 0x5d, 0x4f, 0x91, 0xe4,
+ 0x0b, 0xd5, 0x19, 0xf3, 0x2a, 0xcd, 0x27, 0x1e, 0xf6, 0x5b, 0xca, 0x35,
+ 0x2b, 0xff, 0xc2, 0xec, 0x5f, 0x48, 0xec, 0x5d, 0x69, 0x3f, 0x17, 0xe4,
+ 0x73, 0x01, 0x79, 0x0e, 0xfb, 0x78, 0x8f, 0xe6, 0x3c, 0xf1, 0x55, 0x71,
+ 0xd4, 0x7a, 0x73, 0xdf, 0x9d, 0x3d, 0x9e, 0x54, 0x51, 0xe9, 0x07, 0x75,
+ 0x46, 0xe6, 0x8d, 0xea, 0x91, 0x69, 0xd5, 0x99, 0xbb, 0x54, 0x7f, 0x03,
+ 0xa7, 0xfb, 0x50, 0x17, 0x4e, 0xf7, 0x9d, 0xe1, 0xfe, 0xc7, 0x71, 0x69,
+ 0xa7, 0xb9, 0x58, 0xc6, 0xae, 0xc6, 0x59, 0x67, 0x9c, 0x76, 0x54, 0xd9,
+ 0xec, 0xd0, 0xf7, 0xce, 0xd7, 0x97, 0x31, 0xaf, 0x6d, 0xa2, 0xbe, 0xec,
+ 0xb7, 0xe6, 0x49, 0x67, 0xbd, 0xf7, 0x3f, 0x72, 0xbd, 0xdf, 0xde, 0x6c,
+ 0xd7, 0x5f, 0x2b, 0x26, 0xd2, 0xd0, 0xdf, 0xce, 0xfd, 0x72, 0x17, 0xbf,
+ 0xdb, 0xeb, 0x81, 0x08, 0xdd, 0xd7, 0xf5, 0x32, 0xf9, 0x27, 0x4a, 0x83,
+ 0xf0, 0xa7, 0x6b, 0x2b, 0xbe, 0x77, 0x85, 0xb0, 0x5f, 0x19, 0xc2, 0xdf,
+ 0x5b, 0xed, 0x3e, 0x93, 0xe4, 0x2b, 0x43, 0xc0, 0x52, 0x7e, 0xef, 0x13,
+ 0xd6, 0x5c, 0x0c, 0x3c, 0xe9, 0xb5, 0xcf, 0x8f, 0x6e, 0x71, 0xc1, 0x8b,
+ 0xf7, 0x2f, 0x1a, 0x30, 0x07, 0xb6, 0xd6, 0x99, 0xf4, 0xbd, 0xa3, 0x01,
+ 0xfd, 0x12, 0xf5, 0x75, 0xf6, 0xef, 0x33, 0x9e, 0x2b, 0x2b, 0x67, 0xe7,
+ 0x67, 0xfb, 0x7c, 0x5d, 0x18, 0x1f, 0xb5, 0xe6, 0x5c, 0x7d, 0x9f, 0xfd,
+ 0xfd, 0x28, 0xbd, 0xb4, 0x94, 0x73, 0xaa, 0x7d, 0xbe, 0x76, 0xe9, 0x79,
+ 0x87, 0xe7, 0xd1, 0x62, 0x71, 0x29, 0x0d, 0xbf, 0x26, 0xd2, 0xf9, 0xde,
+ 0xa1, 0xba, 0x4f, 0xeb, 0x83, 0xdd, 0xda, 0x8f, 0x59, 0xfd, 0xb8, 0x7f,
+ 0x0f, 0xdb, 0xf9, 0x1b, 0xfd, 0x5d, 0x5c, 0xca, 0xfe, 0x28, 0xbd, 0xd8,
+ 0xdf, 0xcc, 0xf3, 0x7e, 0xd2, 0x5a, 0x3b, 0xe7, 0xf4, 0x76, 0xb2, 0xab,
+ 0x88, 0xfb, 0x69, 0xa9, 0xad, 0xdf, 0x43, 0xbe, 0xa4, 0x09, 0x38, 0xd2,
+ 0xa4, 0xf3, 0xa0, 0xf3, 0xa5, 0xf3, 0x83, 0x3c, 0x96, 0xae, 0x26, 0xb1,
+ 0x96, 0xae, 0xd5, 0xf4, 0x60, 0x9b, 0xba, 0x66, 0x9c, 0xff, 0x3f, 0xd8,
+ 0x1e, 0x53, 0xf2, 0x6f, 0x8a, 0xef, 0x63, 0x68, 0x80, 0x3f, 0x31, 0xce,
+ 0xce, 0xc5, 0x9c, 0x00, 0x6b, 0x1e, 0xc1, 0x7d, 0x17, 0x3c, 0xbc, 0xdd,
+ 0xac, 0xe7, 0x46, 0x67, 0xff, 0xfe, 0x90, 0xea, 0xf2, 0xd9, 0x7f, 0x73,
+ 0xe7, 0xce, 0xd9, 0xf9, 0x51, 0xfb, 0xa9, 0xe4, 0x1b, 0x99, 0x8f, 0x7e,
+ 0xd1, 0xba, 0x09, 0x7f, 0x6f, 0x87, 0x7d, 0xe0, 0x7d, 0xd8, 0x67, 0xcf,
+ 0x97, 0xe4, 0x45, 0x21, 0x3d, 0xf0, 0xc5, 0x45, 0x85, 0xe4, 0xcf, 0xf1,
+ 0xcb, 0xdf, 0xd1, 0xe7, 0x8f, 0x46, 0x83, 0xd8, 0x2f, 0x6b, 0x85, 0x7a,
+ 0x37, 0xf1, 0xd6, 0x25, 0x8e, 0x82, 0xd7, 0x1f, 0x8c, 0x00, 0xdf, 0x17,
+ 0x2f, 0x41, 0x4f, 0xd1, 0x11, 0xea, 0x73, 0xfe, 0x32, 0x84, 0x35, 0x35,
+ 0xca, 0x7c, 0x2d, 0x37, 0xe8, 0xff, 0x65, 0x59, 0x11, 0xe2, 0xff, 0xab,
+ 0xf0, 0xbb, 0x03, 0x4f, 0xdd, 0xb6, 0x7c, 0x2f, 0xc4, 0x5b, 0xaa, 0x1f,
+ 0x92, 0x97, 0x38, 0xce, 0xfc, 0xf5, 0xe7, 0xf2, 0x57, 0xc7, 0xa5, 0xdc,
+ 0xc8, 0xcb, 0xd7, 0xb5, 0x4e, 0xbe, 0x7a, 0x99, 0xaf, 0xf7, 0xad, 0xfe,
+ 0x36, 0x57, 0x2f, 0xfe, 0xae, 0xb8, 0xf4, 0xd8, 0xf8, 0x0b, 0xdc, 0x5c,
+ 0xab, 0xee, 0x2f, 0x9b, 0x33, 0x77, 0x56, 0x0b, 0x7b, 0x3d, 0x3a, 0x24,
+ 0xf3, 0xfd, 0x1f, 0xfe, 0xac, 0x5e, 0x92, 0x80, 0x14, 0x00, 0x00, 0x00 };
static u8 bnx2_TPAT_b06FwText[] = {
- 0xbd, 0x59, 0x6f, 0x70, 0x5c, 0xd5, 0x7d, 0x3d, 0x6f, 0xf7, 0xed, 0xee,
- 0x93, 0xb4, 0x92, 0x9e, 0x90, 0x0c, 0xab, 0x56, 0x8d, 0xf6, 0x59, 0x6f,
- 0xa5, 0xc5, 0xab, 0xd8, 0x6f, 0x2d, 0xb9, 0xac, 0x87, 0x37, 0xcd, 0xb3,
- 0x2c, 0x29, 0x8b, 0xec, 0xd8, 0xeb, 0x42, 0x66, 0xe4, 0x09, 0x1d, 0x0b,
- 0x59, 0xd8, 0xc2, 0x18, 0xa2, 0x12, 0x3e, 0xa8, 0x13, 0x4f, 0xbd, 0xe8,
- 0x9f, 0x85, 0xbd, 0xd2, 0x23, 0x02, 0x2c, 0x3b, 0x93, 0x0e, 0x1e, 0xf9,
- 0x8f, 0x18, 0x58, 0x6b, 0xa1, 0xfd, 0x92, 0x69, 0xc3, 0x44, 0x13, 0x1b,
- 0xec, 0x90, 0x38, 0x4e, 0xa7, 0x5f, 0xcc, 0xb4, 0x9d, 0xaa, 0x80, 0x29,
- 0x50, 0x70, 0xdc, 0xce, 0xa4, 0x63, 0x0a, 0xf5, 0xed, 0xb9, 0x6f, 0x57,
- 0x46, 0x38, 0x4e, 0x3f, 0xd6, 0x33, 0x8b, 0x76, 0xef, 0x7b, 0xf7, 0xde,
- 0xdf, 0xbd, 0xbf, 0x73, 0xce, 0xef, 0xdc, 0xcb, 0x6a, 0x1f, 0xca, 0x51,
- 0xfa, 0x57, 0xc9, 0x4f, 0xfb, 0x23, 0x43, 0x4f, 0x6f, 0x58, 0x6b, 0xad,
- 0x95, 0xbf, 0x95, 0x00, 0x54, 0xfc, 0x3f, 0xfe, 0xf3, 0x03, 0xfa, 0x72,
- 0x1c, 0xf2, 0x03, 0xcd, 0x67, 0x2f, 0xae, 0xee, 0x30, 0xa1, 0xf9, 0xed,
- 0x87, 0x5a, 0x76, 0x9b, 0x80, 0x93, 0x4f, 0x44, 0x37, 0xe3, 0x7f, 0x44,
- 0xb6, 0x4e, 0x85, 0x6c, 0xff, 0x23, 0xfb, 0x8b, 0x75, 0x6f, 0xdc, 0x67,
- 0x5c, 0x3f, 0xe1, 0x87, 0xa6, 0xdb, 0x93, 0x9a, 0xde, 0x0c, 0xad, 0x81,
- 0x7d, 0x7e, 0xd4, 0xb2, 0x2b, 0x88, 0xaa, 0xe5, 0xb1, 0x80, 0x93, 0x39,
- 0xc3, 0xda, 0x83, 0x84, 0x7e, 0x8e, 0x0b, 0x72, 0x38, 0xc7, 0x99, 0x3c,
- 0x70, 0x28, 0xa7, 0xe0, 0x2a, 0xc7, 0x1c, 0xcf, 0x6b, 0x58, 0xf2, 0x7b,
- 0xd3, 0xf5, 0x95, 0xd9, 0xc8, 0x98, 0x53, 0x07, 0x45, 0xc8, 0x44, 0xf6,
- 0x0f, 0x6c, 0x33, 0x7e, 0x08, 0xe1, 0xd4, 0x5c, 0x3b, 0x32, 0xab, 0xcf,
- 0x6a, 0xd8, 0xe9, 0x36, 0xf4, 0x69, 0x36, 0xf8, 0x8e, 0x82, 0xd4, 0x7d,
- 0x1a, 0x7a, 0x0b, 0x71, 0x64, 0x0b, 0x59, 0x38, 0x85, 0x31, 0x7e, 0x34,
- 0x84, 0xa6, 0x34, 0x6d, 0xdd, 0xd4, 0xdd, 0xf2, 0x1d, 0x84, 0xa7, 0xae,
- 0x8b, 0x6b, 0x49, 0x1d, 0x6f, 0x6f, 0x14, 0xa2, 0xd2, 0x46, 0xb6, 0xa2,
- 0x3d, 0x0b, 0xbf, 0x6d, 0x58, 0x5b, 0xfc, 0x0a, 0x3a, 0xbf, 0x6e, 0xc6,
- 0xa7, 0x94, 0x07, 0x1f, 0xf4, 0xd9, 0xd0, 0x14, 0x3b, 0xaa, 0x35, 0xe5,
- 0x1b, 0x30, 0x51, 0xd0, 0x71, 0xa8, 0x50, 0x87, 0xb1, 0x02, 0x0e, 0xf8,
- 0x37, 0x04, 0x31, 0xa7, 0xc3, 0xf9, 0x4e, 0xcb, 0x01, 0xec, 0xcb, 0x0d,
- 0x63, 0x77, 0x2e, 0x85, 0xc3, 0x05, 0x19, 0x63, 0x14, 0xa3, 0x05, 0x15,
- 0xc1, 0x29, 0x23, 0xf2, 0x73, 0xdc, 0xe9, 0x99, 0x10, 0x63, 0x56, 0x08,
- 0x23, 0x56, 0x1c, 0xe3, 0xae, 0x8f, 0xeb, 0x0c, 0x61, 0xd4, 0xbc, 0x21,
- 0x06, 0x2c, 0xc3, 0x1a, 0x87, 0x68, 0x3c, 0x6f, 0x19, 0x91, 0x4e, 0x3f,
- 0x9c, 0xef, 0x9b, 0x11, 0x8c, 0x33, 0xf6, 0x31, 0xaf, 0xdf, 0x18, 0x3a,
- 0x6f, 0xf5, 0x73, 0xd8, 0x4f, 0xc7, 0xc4, 0x57, 0xfb, 0x46, 0xc7, 0x91,
- 0x88, 0x4c, 0xc0, 0x87, 0xbe, 0xba, 0x56, 0xf6, 0x6b, 0x8a, 0x4e, 0xc0,
- 0x88, 0x73, 0x9c, 0x6c, 0xb0, 0xdd, 0xe1, 0x18, 0x59, 0xf6, 0x37, 0xa2,
- 0x67, 0x20, 0xc7, 0x6a, 0xe0, 0xef, 0x76, 0xf6, 0x57, 0xe0, 0xb3, 0x63,
- 0xd1, 0x11, 0xf6, 0x39, 0x67, 0xa9, 0x78, 0x93, 0x9f, 0x3e, 0xdd, 0x90,
- 0x99, 0x55, 0x42, 0x6c, 0x3f, 0x04, 0x3e, 0x37, 0x2b, 0x70, 0x22, 0x63,
- 0x61, 0x84, 0xeb, 0xd6, 0xd8, 0x36, 0xc9, 0xb6, 0x80, 0x69, 0x71, 0x7c,
- 0xe8, 0x9d, 0x85, 0x95, 0x98, 0x58, 0xce, 0xcd, 0xef, 0x6b, 0xe7, 0x18,
- 0x6e, 0x31, 0xa7, 0xf2, 0x9d, 0xcd, 0xee, 0x4d, 0xf1, 0x88, 0xba, 0xf2,
- 0xf9, 0xb0, 0xd2, 0xc1, 0x36, 0x47, 0x6d, 0xc0, 0x21, 0x17, 0x5a, 0xd0,
- 0xd4, 0x38, 0x8f, 0x86, 0xf7, 0x72, 0xc3, 0x4a, 0x77, 0xc1, 0x51, 0xba,
- 0xe6, 0x3b, 0x14, 0x67, 0x5e, 0x55, 0x3a, 0x67, 0x65, 0xdc, 0x42, 0x3c,
- 0x6b, 0x29, 0x8c, 0xf9, 0x07, 0x32, 0x5e, 0x27, 0xaa, 0xdc, 0x14, 0x6b,
- 0x62, 0x3e, 0x54, 0x98, 0xdd, 0xca, 0x96, 0x79, 0x21, 0xd2, 0xc9, 0xb4,
- 0xd2, 0x33, 0x0f, 0x2d, 0x6c, 0xdb, 0x5a, 0x6e, 0xea, 0x30, 0xb2, 0xab,
- 0x4c, 0x1c, 0x77, 0xa3, 0xb8, 0x64, 0xf9, 0x70, 0x62, 0x55, 0x19, 0x54,
- 0x53, 0xe1, 0x07, 0xe1, 0xcb, 0x16, 0xd4, 0x2a, 0x7e, 0xbf, 0xb6, 0x43,
- 0xc5, 0x58, 0x7b, 0x8f, 0xd2, 0xc9, 0x3e, 0x01, 0xe6, 0xf9, 0x74, 0x2e,
- 0x8d, 0x30, 0xb1, 0x53, 0x61, 0xc7, 0x22, 0x79, 0xee, 0xcd, 0xdb, 0x56,
- 0x2c, 0xfe, 0xb8, 0xc4, 0x63, 0x8d, 0x11, 0x91, 0x7b, 0x53, 0x69, 0xc7,
- 0xe2, 0x67, 0xb9, 0x0f, 0x7e, 0x53, 0xc5, 0xaf, 0xac, 0x00, 0x16, 0x77,
- 0x58, 0xcc, 0xa9, 0x8e, 0x20, 0xdb, 0xcf, 0x78, 0xed, 0xf2, 0x37, 0xf4,
- 0xae, 0xaf, 0xec, 0x43, 0x71, 0x0f, 0x46, 0xdd, 0x26, 0xc6, 0x5c, 0xdc,
- 0x83, 0xed, 0x5c, 0xef, 0xbf, 0x06, 0xe4, 0xd7, 0xaf, 0xdd, 0x6a, 0xdb,
- 0xc9, 0x38, 0x7d, 0xb6, 0xb9, 0xb8, 0xda, 0x5f, 0x0f, 0xd4, 0xb6, 0xe3,
- 0x30, 0x73, 0xdc, 0x99, 0xbc, 0x1b, 0x59, 0xef, 0x79, 0x9d, 0xbe, 0x65,
- 0xb6, 0x16, 0x7d, 0xab, 0xbc, 0x7d, 0xd3, 0xb7, 0xcd, 0x0a, 0xf1, 0x66,
- 0x32, 0x88, 0xb3, 0xe6, 0x48, 0xa4, 0x12, 0x59, 0xcb, 0xcf, 0x7c, 0x5f,
- 0xe0, 0xfc, 0xf9, 0xa4, 0x1f, 0x27, 0x93, 0x27, 0x90, 0xad, 0x01, 0xe6,
- 0x72, 0x92, 0x57, 0xc6, 0xe2, 0x05, 0xfe, 0xd7, 0x57, 0x90, 0xeb, 0xb3,
- 0xb8, 0x3e, 0x05, 0x67, 0x4c, 0x89, 0x69, 0x4b, 0x6b, 0x26, 0xbf, 0xf6,
- 0x71, 0x3f, 0xeb, 0xdb, 0xc3, 0xc4, 0x27, 0xf0, 0x6e, 0x6e, 0x00, 0x3b,
- 0x8b, 0xb1, 0xe0, 0x46, 0x8e, 0xc2, 0xd2, 0x96, 0xc6, 0x89, 0xe2, 0x6f,
- 0x72, 0x3c, 0xad, 0x75, 0xe4, 0x8c, 0x4c, 0x1a, 0x89, 0x8b, 0x1d, 0x8a,
- 0xec, 0x9f, 0xd6, 0xd6, 0xe4, 0x83, 0x88, 0xd6, 0x16, 0x9f, 0x57, 0xd8,
- 0x5b, 0xb5, 0xc7, 0xa7, 0x14, 0xec, 0x8d, 0xc9, 0x67, 0x5b, 0xb5, 0x96,
- 0x3c, 0xb4, 0x4a, 0x7b, 0x48, 0x3b, 0x3b, 0x65, 0xf4, 0xbd, 0xac, 0x24,
- 0xa2, 0x53, 0x5e, 0x9f, 0x21, 0xad, 0x35, 0x1f, 0xe2, 0x7a, 0xe2, 0xcc,
- 0x09, 0xb4, 0x2a, 0xfb, 0x69, 0xed, 0x57, 0x7c, 0x70, 0xd1, 0xeb, 0xf3,
- 0xb4, 0x16, 0xcf, 0xcb, 0x76, 0xc3, 0x8a, 0x2a, 0x21, 0xdc, 0x9b, 0xd4,
- 0xb0, 0xa6, 0x45, 0x34, 0x76, 0x25, 0x8d, 0xc5, 0x2e, 0x7f, 0x04, 0xc7,
- 0xc9, 0x05, 0xe2, 0xce, 0xf9, 0xc3, 0x96, 0x31, 0x74, 0x15, 0xfc, 0x88,
- 0xd6, 0x38, 0x38, 0xe2, 0x86, 0xf0, 0x33, 0xe2, 0xbf, 0xdb, 0xd2, 0x31,
- 0xe6, 0x1a, 0xf1, 0x5f, 0x20, 0x91, 0x3a, 0xc5, 0x9c, 0x2d, 0x91, 0x03,
- 0x47, 0x0a, 0x4d, 0xf1, 0x53, 0x30, 0x06, 0xbb, 0xc8, 0x01, 0xad, 0x5d,
- 0xc6, 0x00, 0x5d, 0xb5, 0xc9, 0x9d, 0x42, 0x03, 0x72, 0xe4, 0x43, 0x97,
- 0xc7, 0xab, 0x61, 0xa5, 0xb3, 0xf0, 0x4b, 0x6a, 0x6b, 0x37, 0xf1, 0x85,
- 0xea, 0x88, 0x19, 0x44, 0xaa, 0x36, 0x8a, 0xf3, 0xc4, 0x4a, 0xb6, 0xae,
- 0x8c, 0xb9, 0x94, 0xf9, 0x7c, 0x87, 0xcf, 0x7b, 0x94, 0xcd, 0xf3, 0x51,
- 0xfc, 0xcc, 0xfa, 0x42, 0x38, 0x75, 0x95, 0x6c, 0x0b, 0xac, 0x68, 0xd7,
- 0x70, 0xf5, 0x85, 0x72, 0x7c, 0xfc, 0x42, 0x18, 0x9f, 0xbd, 0x40, 0x7e,
- 0xbb, 0x68, 0x2f, 0x87, 0x10, 0xa9, 0x36, 0x21, 0x0a, 0x56, 0x2b, 0xde,
- 0xab, 0x89, 0x45, 0xaf, 0x40, 0x6a, 0xa3, 0xa3, 0xed, 0xce, 0x19, 0x43,
- 0x83, 0x48, 0x38, 0xe7, 0xbc, 0xbd, 0x70, 0xb4, 0xb5, 0xf9, 0xf3, 0x02,
- 0x3b, 0x8a, 0x7b, 0x11, 0xb4, 0x3b, 0xb5, 0xb7, 0x98, 0x9b, 0xcb, 0x5e,
- 0x6e, 0x3a, 0xb5, 0x75, 0xf9, 0xfb, 0xfd, 0x28, 0x2f, 0x3e, 0x53, 0xed,
- 0x8c, 0x36, 0x96, 0x33, 0x7a, 0x27, 0xb9, 0xbe, 0x01, 0xaf, 0x6f, 0x46,
- 0x4b, 0x70, 0xef, 0x97, 0x4a, 0xb9, 0xa9, 0xb4, 0x1f, 0xe2, 0x3e, 0x33,
- 0xf7, 0xde, 0x3e, 0x3e, 0xc4, 0x3d, 0x96, 0xf3, 0x0d, 0xdf, 0x36, 0xdf,
- 0x30, 0xe7, 0x7b, 0x79, 0xc5, 0x7c, 0x07, 0x56, 0xcc, 0x77, 0x60, 0xc5,
- 0x7c, 0x29, 0x72, 0xf5, 0x1f, 0xc4, 0x48, 0x5d, 0x71, 0x6c, 0xd5, 0x1e,
- 0xbc, 0x6d, 0xee, 0x41, 0xce, 0x7d, 0x54, 0x2c, 0x65, 0x8a, 0xe3, 0x54,
- 0xda, 0xfb, 0x57, 0xcc, 0xbd, 0x9f, 0x73, 0x2f, 0x8f, 0xa3, 0x53, 0x8b,
- 0x84, 0xd8, 0x66, 0x09, 0xa1, 0xda, 0xa6, 0xde, 0x89, 0xe6, 0x4c, 0x27,
- 0xb1, 0x53, 0x8e, 0xc4, 0xa2, 0x0f, 0xe6, 0x70, 0xbd, 0x3f, 0x80, 0xa5,
- 0x9a, 0x65, 0x6e, 0x54, 0x96, 0xfe, 0xbe, 0xa4, 0x80, 0x5a, 0xff, 0x6a,
- 0xae, 0x9a, 0x63, 0xc4, 0xf4, 0x01, 0x45, 0x88, 0x73, 0x1b, 0x13, 0x83,
- 0x7e, 0x24, 0xfa, 0xaa, 0x60, 0x12, 0x43, 0x81, 0x12, 0x17, 0x56, 0xf6,
- 0x79, 0xd9, 0xeb, 0x53, 0xf0, 0xfa, 0x08, 0xf1, 0xee, 0x86, 0x0f, 0xc5,
- 0x1b, 0x2d, 0x75, 0xf8, 0x29, 0x39, 0xf9, 0x5a, 0x61, 0x59, 0x57, 0xa4,
- 0x6e, 0xc0, 0x77, 0xce, 0x0a, 0x32, 0xa6, 0x91, 0x7d, 0xc1, 0xaf, 0xf4,
- 0x27, 0x60, 0x4c, 0xd9, 0xe6, 0xc7, 0x2b, 0x49, 0x3c, 0x52, 0x0e, 0xa3,
- 0xf7, 0xb0, 0x92, 0x4d, 0x57, 0xc0, 0x70, 0xd6, 0x28, 0xd9, 0x94, 0x06,
- 0xc9, 0x1b, 0xb5, 0xe9, 0xb4, 0x69, 0x64, 0xaf, 0xf2, 0x65, 0x75, 0xfa,
- 0x4e, 0x31, 0xa8, 0x1c, 0x23, 0x8c, 0x27, 0xdd, 0x0b, 0x58, 0x0c, 0x34,
- 0x50, 0x9f, 0xa5, 0x76, 0x72, 0xe0, 0x05, 0x8d, 0x35, 0x2d, 0x44, 0x22,
- 0xaa, 0x38, 0xe8, 0xfa, 0xce, 0x37, 0x42, 0x20, 0xd8, 0x16, 0xc0, 0x3b,
- 0xe6, 0xa8, 0x55, 0x8f, 0x4d, 0xb8, 0xdc, 0xca, 0x3d, 0x58, 0xa5, 0x22,
- 0x32, 0xb7, 0x72, 0xac, 0x08, 0xc7, 0xfa, 0xb3, 0x10, 0xaa, 0xea, 0xa0,
- 0x36, 0xab, 0xd8, 0xeb, 0x6a, 0x4a, 0x97, 0x2b, 0xb1, 0x6b, 0x46, 0x4e,
- 0xe1, 0x14, 0xb5, 0x82, 0x35, 0xec, 0x8c, 0xaa, 0x6c, 0x99, 0x0d, 0xa1,
- 0x7c, 0xe6, 0x13, 0xf1, 0x18, 0xb5, 0x2f, 0xbd, 0x41, 0x08, 0x33, 0x19,
- 0x82, 0xc6, 0x79, 0x86, 0xc9, 0xe7, 0xea, 0xb6, 0x5a, 0x5c, 0xfb, 0x3a,
- 0xb5, 0xe9, 0xdb, 0x21, 0xf8, 0x67, 0x42, 0x08, 0xce, 0x28, 0x78, 0xa7,
- 0x3d, 0x84, 0xfa, 0x39, 0xf9, 0x5b, 0x41, 0xa3, 0x79, 0x14, 0x07, 0x75,
- 0x3f, 0x63, 0xfc, 0x2b, 0xf4, 0xeb, 0x0d, 0x98, 0xa4, 0x36, 0x3f, 0xea,
- 0x6a, 0xa8, 0x3a, 0x4a, 0x2d, 0xb0, 0x85, 0x38, 0x49, 0xfc, 0x1f, 0x64,
- 0x8c, 0x32, 0xde, 0x0b, 0x56, 0x36, 0x1a, 0x42, 0x00, 0xc1, 0x39, 0x23,
- 0x3d, 0xc9, 0xe8, 0x52, 0x53, 0xaa, 0xb2, 0x7d, 0x96, 0xb5, 0xd7, 0x36,
- 0x7b, 0xeb, 0xfd, 0x42, 0x7c, 0x9a, 0x6c, 0xea, 0x5b, 0xa0, 0x06, 0x8f,
- 0xc4, 0x62, 0x99, 0x7e, 0x05, 0x58, 0x73, 0x96, 0x76, 0x64, 0xe6, 0xbf,
- 0x44, 0x98, 0xe3, 0x1c, 0xd9, 0x20, 0x30, 0x6e, 0x65, 0x23, 0x01, 0x18,
- 0x37, 0x86, 0x50, 0x87, 0x0f, 0x9e, 0x17, 0x42, 0xb4, 0x57, 0xe3, 0x1d,
- 0xcb, 0x18, 0x34, 0xfd, 0x02, 0x3f, 0x4e, 0x66, 0x87, 0x22, 0x30, 0x86,
- 0x7f, 0xad, 0x44, 0xf1, 0xf1, 0x94, 0x91, 0xbe, 0xa8, 0x04, 0x51, 0x39,
- 0x67, 0xea, 0x5b, 0x94, 0x30, 0xca, 0x17, 0xc2, 0x58, 0x7d, 0x36, 0x88,
- 0xc0, 0x4c, 0x18, 0xc1, 0x69, 0xf3, 0xe2, 0x2e, 0x78, 0xe3, 0x2c, 0x0e,
- 0xa1, 0x19, 0xd5, 0xb3, 0x66, 0xf4, 0x5f, 0x20, 0xb1, 0x1d, 0x86, 0xba,
- 0x10, 0x45, 0x7d, 0xc1, 0x44, 0x35, 0xf3, 0x7d, 0xf9, 0xac, 0xcc, 0xb3,
- 0x8e, 0xb0, 0xe9, 0xe3, 0xda, 0x1c, 0x65, 0xab, 0x57, 0x37, 0x3a, 0xf9,
- 0xe9, 0x56, 0x3a, 0xe6, 0xe5, 0x9e, 0x29, 0x28, 0xe3, 0xb3, 0x8b, 0xd6,
- 0x4d, 0xb1, 0x2f, 0x26, 0xeb, 0x44, 0x19, 0x02, 0x76, 0x8f, 0xf2, 0xc0,
- 0x3c, 0x8b, 0x90, 0xa7, 0xef, 0x65, 0x4a, 0xc0, 0x2e, 0x6a, 0xfb, 0x25,
- 0x6a, 0xfb, 0x89, 0x92, 0xb6, 0x57, 0x51, 0xdb, 0x17, 0xfe, 0x4f, 0x6d,
- 0x67, 0xbd, 0x9f, 0xf1, 0xe1, 0xbc, 0x19, 0xc2, 0x71, 0xab, 0x69, 0xb1,
- 0x1e, 0x21, 0x54, 0xb7, 0xe9, 0xa8, 0x5e, 0xb0, 0xf0, 0x1c, 0xf7, 0x16,
- 0x77, 0x15, 0xf5, 0xfd, 0x9b, 0x52, 0xf3, 0x4b, 0x5e, 0xed, 0x71, 0x77,
- 0x59, 0x13, 0xc2, 0xd4, 0x2a, 0x55, 0xe9, 0xa1, 0x9e, 0x3f, 0x90, 0xbc,
- 0x29, 0xe2, 0x31, 0x23, 0x4e, 0xce, 0xde, 0x38, 0x89, 0xa2, 0x46, 0xc4,
- 0xa8, 0x97, 0x4b, 0xb5, 0x71, 0x1c, 0x73, 0x65, 0x4d, 0xeb, 0x64, 0x4d,
- 0x53, 0x30, 0x12, 0x2b, 0x6a, 0xc4, 0xea, 0xbc, 0x6c, 0xd7, 0x51, 0x4f,
- 0x9d, 0x5c, 0xd7, 0x16, 0xc1, 0x31, 0x6a, 0xa4, 0x4b, 0x9f, 0xb3, 0x9d,
- 0xe3, 0x6d, 0x9b, 0x35, 0xb2, 0xdb, 0x99, 0x9f, 0xf3, 0xc4, 0xc5, 0x14,
- 0xab, 0xc3, 0x89, 0x1a, 0x6a, 0x67, 0x73, 0x08, 0x13, 0xd4, 0xcb, 0xf3,
- 0xf4, 0x10, 0x2f, 0xb1, 0xdf, 0xb8, 0x6b, 0x44, 0x5f, 0x22, 0xaf, 0xc7,
- 0x4b, 0x9a, 0xf9, 0x12, 0x7d, 0xc3, 0x38, 0xf3, 0xf4, 0x53, 0x3e, 0x7b,
- 0xcd, 0x35, 0x1c, 0xe9, 0x1f, 0xfc, 0x9e, 0x7f, 0x30, 0xe2, 0x7e, 0x45,
- 0x7a, 0x88, 0x08, 0xde, 0x68, 0x91, 0x58, 0x24, 0xc6, 0x6f, 0xe9, 0xa7,
- 0xaa, 0x7c, 0x6b, 0xf6, 0xba, 0xc8, 0xc7, 0xca, 0x55, 0xc9, 0xbf, 0xb1,
- 0xa4, 0xc4, 0x93, 0x10, 0x65, 0x76, 0x98, 0x5e, 0xcb, 0x8c, 0x7f, 0x84,
- 0x18, 0x71, 0x1b, 0xe1, 0xb3, 0x30, 0xfc, 0x67, 0xb7, 0xa8, 0x9e, 0x8f,
- 0x5d, 0x90, 0x7e, 0x8b, 0x79, 0x9a, 0x32, 0x7b, 0xa7, 0x94, 0x58, 0x66,
- 0x40, 0x91, 0xcf, 0x75, 0x94, 0x9f, 0x5d, 0x22, 0x77, 0x23, 0xe4, 0x6e,
- 0x1d, 0x5e, 0xbf, 0x8d, 0xbf, 0xd4, 0x55, 0xdf, 0x00, 0xf9, 0x9b, 0xad,
- 0x1b, 0xe9, 0xf7, 0x7f, 0x85, 0x7b, 0x87, 0x24, 0x7f, 0xd9, 0xe6, 0xc7,
- 0xb3, 0x49, 0xec, 0x2c, 0x83, 0x91, 0x79, 0x4c, 0xc9, 0x3a, 0xe4, 0x71,
- 0xaa, 0x4c, 0xc9, 0xd2, 0x31, 0x7d, 0xc9, 0xdf, 0x37, 0xf9, 0xb6, 0x9f,
- 0xfc, 0xed, 0xab, 0xbb, 0x9d, 0xbf, 0x47, 0x38, 0x86, 0x8a, 0x27, 0xdc,
- 0xe3, 0x98, 0x0b, 0x04, 0x11, 0x99, 0x09, 0x20, 0x34, 0xa3, 0xa2, 0x92,
- 0x5c, 0x09, 0xdb, 0xd9, 0x78, 0x08, 0x46, 0xfa, 0x35, 0x44, 0x90, 0x98,
- 0xd2, 0xf0, 0xe7, 0x2d, 0x01, 0x9c, 0x89, 0x19, 0x99, 0xfd, 0x4a, 0x84,
- 0x58, 0x1f, 0x61, 0x44, 0x46, 0x34, 0xea, 0x2b, 0xf2, 0x35, 0xd0, 0x1c,
- 0x84, 0x36, 0x23, 0xb9, 0x2e, 0x0e, 0xfa, 0xec, 0x6c, 0x54, 0x23, 0x46,
- 0x7f, 0x40, 0x6c, 0x5c, 0x99, 0x12, 0x62, 0x73, 0xbb, 0x79, 0xf1, 0x3d,
- 0xbf, 0x41, 0xdd, 0x53, 0x89, 0xd3, 0xe2, 0xf8, 0x15, 0x33, 0x1a, 0x82,
- 0x47, 0xbd, 0xf1, 0x6f, 0xbc, 0xce, 0x28, 0x3e, 0x75, 0x55, 0x65, 0x2b,
- 0x71, 0x40, 0x6e, 0x45, 0xe6, 0xa9, 0x7d, 0x87, 0x93, 0x46, 0x7a, 0x8b,
- 0xd2, 0xe4, 0x34, 0xf3, 0xbb, 0x2f, 0x19, 0x8b, 0xf6, 0xf3, 0x9d, 0xf7,
- 0x0b, 0x45, 0x0e, 0xd7, 0x9b, 0xbb, 0xf1, 0x17, 0xe4, 0x70, 0x95, 0xf9,
- 0x14, 0x9e, 0xf4, 0xf4, 0x88, 0x38, 0x98, 0x2e, 0x27, 0xb7, 0x1d, 0x65,
- 0x17, 0x71, 0xbf, 0x73, 0x9e, 0xba, 0x32, 0xd3, 0xee, 0x69, 0x51, 0xc8,
- 0xec, 0x54, 0x7a, 0xe7, 0xbb, 0x3d, 0x0f, 0xb5, 0x7d, 0xd6, 0x87, 0xd7,
- 0xad, 0x4d, 0xf4, 0x2b, 0x69, 0x65, 0xfb, 0xbc, 0xc4, 0x7c, 0x8f, 0xf2,
- 0x4d, 0xe2, 0x3f, 0x7a, 0x97, 0x8a, 0x39, 0x6b, 0x93, 0x12, 0xf4, 0xf0,
- 0x1f, 0x80, 0x93, 0x29, 0x62, 0xdf, 0x6f, 0xc7, 0xac, 0x73, 0x2b, 0xb0,
- 0xdf, 0x7d, 0x07, 0x5f, 0x23, 0xf5, 0x03, 0x45, 0x2d, 0xd7, 0x3b, 0x99,
- 0xaf, 0x67, 0x4a, 0x18, 0x7f, 0x92, 0xed, 0x81, 0x19, 0x68, 0xe5, 0xc4,
- 0x71, 0xcf, 0x54, 0x18, 0xd3, 0x1e, 0x56, 0x04, 0x5e, 0x65, 0x4d, 0xc8,
- 0x27, 0x0d, 0x6b, 0xbf, 0x62, 0xa4, 0xbb, 0x95, 0x44, 0x76, 0x4d, 0xa9,
- 0x1e, 0xde, 0xcb, 0x9a, 0x86, 0xbb, 0xa8, 0x0b, 0x16, 0xb4, 0x10, 0xf1,
- 0xfd, 0x6f, 0xac, 0x4f, 0xff, 0x51, 0xaa, 0x87, 0xc9, 0x7c, 0x39, 0xaa,
- 0x5b, 0xa8, 0xef, 0xc4, 0x73, 0x97, 0xc4, 0x33, 0x3d, 0xc4, 0x18, 0xeb,
- 0xff, 0x4e, 0xe2, 0x79, 0x75, 0x9b, 0x91, 0xed, 0xa4, 0x77, 0xf6, 0xad,
- 0x8f, 0x10, 0xab, 0x71, 0xfa, 0xd5, 0x31, 0x74, 0x70, 0xae, 0xf4, 0xac,
- 0x11, 0xe9, 0x20, 0x07, 0x54, 0xf6, 0x79, 0x89, 0x7d, 0x96, 0x6a, 0xa5,
- 0xaf, 0x0e, 0xe1, 0x59, 0xf6, 0x31, 0x93, 0x8e, 0xa7, 0x15, 0x92, 0x03,
- 0x13, 0x48, 0x64, 0x24, 0x07, 0x9c, 0x55, 0xad, 0xf4, 0xf8, 0x92, 0x03,
- 0xc4, 0xa0, 0x4b, 0x0c, 0x16, 0x79, 0x30, 0x28, 0x79, 0x50, 0x45, 0x0f,
- 0xb1, 0x40, 0x0f, 0x51, 0x61, 0x47, 0xc9, 0x01, 0xc9, 0x89, 0xa2, 0x8f,
- 0xe8, 0x2c, 0xf1, 0x60, 0x8b, 0x37, 0x9f, 0x4a, 0xed, 0x0b, 0xa3, 0x69,
- 0xda, 0xd0, 0x55, 0xe5, 0x3f, 0xc5, 0x2e, 0xd3, 0x5c, 0xdc, 0x4b, 0x2f,
- 0xf0, 0x59, 0x5b, 0x8c, 0x79, 0x0f, 0x63, 0xdd, 0x42, 0x79, 0x40, 0xe2,
- 0xbc, 0x7e, 0x3a, 0x8c, 0xea, 0x69, 0xc9, 0x83, 0xec, 0x24, 0xf5, 0x6f,
- 0xc8, 0xf2, 0xfd, 0x13, 0xf1, 0x1f, 0x25, 0x2e, 0x54, 0xa5, 0x8b, 0x63,
- 0x54, 0xcd, 0xe8, 0x68, 0x9d, 0x36, 0x06, 0x17, 0x70, 0x4d, 0xbc, 0x1a,
- 0x33, 0x33, 0x87, 0x98, 0xff, 0x3d, 0xc9, 0x18, 0xf7, 0x4a, 0xc7, 0xbd,
- 0xb7, 0xc6, 0xf0, 0x38, 0xe1, 0xf4, 0x5b, 0xe1, 0x92, 0xaf, 0xd6, 0xd0,
- 0xef, 0x02, 0x7b, 0x5c, 0x1a, 0x5b, 0xd3, 0xb7, 0x36, 0x88, 0xeb, 0x38,
- 0x49, 0xf4, 0x0f, 0xe8, 0x0e, 0xf3, 0x1f, 0xc2, 0xde, 0xd2, 0x3b, 0x45,
- 0xbf, 0xfd, 0xe3, 0xd2, 0x79, 0xf2, 0x17, 0xfe, 0xe2, 0xdf, 0xbf, 0x55,
- 0x97, 0xcf, 0x97, 0xfd, 0xc4, 0xe0, 0x66, 0x62, 0xb0, 0x9b, 0x39, 0xda,
- 0x6b, 0x91, 0xdf, 0xcc, 0x67, 0x56, 0x0d, 0x51, 0x0f, 0x9b, 0xfa, 0x2a,
- 0xa9, 0x6b, 0x87, 0xa9, 0x51, 0x3f, 0x37, 0xcb, 0xe9, 0xb7, 0x1d, 0xfa,
- 0xed, 0x0e, 0x6a, 0x68, 0x27, 0xf5, 0x53, 0x62, 0x2b, 0x4d, 0x1c, 0x69,
- 0x4a, 0x9a, 0x1e, 0x36, 0x90, 0xa4, 0xd7, 0xae, 0x5b, 0xf6, 0xda, 0x32,
- 0x4e, 0xe9, 0xaf, 0x8d, 0xb8, 0x2c, 0xb5, 0x4f, 0x32, 0x0f, 0x8b, 0x35,
- 0x9b, 0xa0, 0xda, 0x9b, 0x14, 0xd5, 0x96, 0xe7, 0x09, 0x15, 0xdf, 0xa5,
- 0xd6, 0x2e, 0xed, 0x90, 0xe7, 0x0a, 0xae, 0x8b, 0x6d, 0x11, 0x33, 0x16,
- 0x3d, 0x4e, 0x5c, 0x1d, 0xfb, 0x9d, 0x73, 0x46, 0x11, 0x6f, 0xa3, 0xae,
- 0x7a, 0xcb, 0x33, 0x4b, 0x7d, 0xd8, 0x74, 0x0b, 0x6f, 0x1a, 0x9e, 0x68,
- 0x89, 0x12, 0x8f, 0x12, 0x6b, 0x1a, 0xf2, 0x2f, 0x96, 0xe3, 0xd5, 0x17,
- 0xc3, 0x78, 0xe5, 0x45, 0x21, 0xc6, 0x93, 0xe0, 0x69, 0x46, 0x6a, 0xec,
- 0x46, 0xbc, 0xac, 0xc7, 0xa2, 0xcf, 0x7a, 0x9e, 0xd5, 0xa1, 0x67, 0x35,
- 0x06, 0x2f, 0xe0, 0x26, 0xf5, 0x4b, 0x72, 0x3a, 0x41, 0xbe, 0x15, 0xb1,
- 0xe8, 0x79, 0xdb, 0x1a, 0x0d, 0x57, 0x88, 0xbf, 0x6a, 0xe2, 0xef, 0x37,
- 0xd4, 0xdd, 0x6b, 0x25, 0xdd, 0x5d, 0x9b, 0x27, 0x1f, 0xdb, 0x42, 0xe8,
- 0x96, 0x6b, 0x21, 0x0e, 0x47, 0x6f, 0xe1, 0x50, 0x88, 0x0f, 0xb8, 0xe7,
- 0x17, 0x2c, 0x23, 0xbe, 0x99, 0x78, 0x9c, 0xb3, 0x0c, 0xa7, 0x83, 0xde,
- 0x75, 0xd4, 0xc3, 0x24, 0xf5, 0x37, 0x26, 0x71, 0x49, 0x1c, 0x32, 0x27,
- 0x87, 0xd9, 0xe7, 0x3c, 0xfb, 0x4c, 0x94, 0xbc, 0xeb, 0xdb, 0x48, 0xa4,
- 0xa5, 0x77, 0x8d, 0x12, 0x83, 0x87, 0x3d, 0xef, 0x2a, 0xbd, 0xaa, 0xf4,
- 0xa9, 0x32, 0xce, 0x76, 0x2f, 0xce, 0xae, 0x5b, 0x38, 0xa4, 0x86, 0xd5,
- 0x48, 0xfc, 0x7d, 0x03, 0x13, 0xcf, 0x57, 0xa1, 0xda, 0xbc, 0x07, 0x97,
- 0x33, 0xdf, 0x50, 0x23, 0x26, 0xf4, 0x7a, 0xbb, 0x88, 0xc7, 0x9d, 0x85,
- 0x14, 0x5c, 0xf7, 0x2d, 0xe1, 0xd6, 0x19, 0xce, 0x05, 0xcf, 0x7f, 0x0e,
- 0xb2, 0xd6, 0xdc, 0x14, 0xbe, 0x98, 0x71, 0xb1, 0x9f, 0x1e, 0xac, 0xc9,
- 0x5f, 0xf4, 0x72, 0x1b, 0xf3, 0xbf, 0x14, 0xa8, 0x2d, 0xae, 0x53, 0xa5,
- 0x7f, 0x1b, 0x23, 0xe7, 0xc6, 0xcd, 0xa2, 0x97, 0x8b, 0xe5, 0xaf, 0x06,
- 0xa4, 0xa6, 0xfb, 0xda, 0xe4, 0xb8, 0x69, 0x6a, 0xc8, 0xf2, 0xd8, 0x5f,
- 0xea, 0xf2, 0x18, 0x31, 0x38, 0x2a, 0x7d, 0x15, 0x7d, 0x09, 0xcf, 0xe5,
- 0x2b, 0x34, 0x75, 0xd8, 0x0f, 0x53, 0xb6, 0x39, 0xca, 0x03, 0x5c, 0x83,
- 0x66, 0x0e, 0x2b, 0x69, 0x9e, 0x3b, 0x0f, 0x11, 0x5f, 0xdd, 0xac, 0xc3,
- 0x57, 0xad, 0x66, 0x72, 0x98, 0xf5, 0x89, 0xb5, 0xf8, 0xb0, 0xb9, 0x7c,
- 0x7e, 0x93, 0x35, 0x99, 0x35, 0xcc, 0xad, 0x64, 0xfd, 0xee, 0x61, 0xcd,
- 0xe6, 0x28, 0xcc, 0xe9, 0x67, 0x31, 0xd1, 0xb8, 0xb6, 0xcd, 0x18, 0xdc,
- 0xe6, 0x0f, 0x21, 0x47, 0xbc, 0x1f, 0x63, 0x1d, 0x72, 0xb9, 0xa7, 0xd3,
- 0x05, 0x23, 0x95, 0xc5, 0x18, 0xb6, 0x71, 0x4f, 0x79, 0xde, 0x71, 0xfe,
- 0x2e, 0x56, 0x3c, 0x0f, 0xef, 0x65, 0x7d, 0x9b, 0x2c, 0x71, 0xfb, 0x43,
- 0x24, 0x2c, 0xc9, 0xed, 0x45, 0xd6, 0xb7, 0x49, 0x8f, 0xdb, 0x46, 0x4a,
- 0xf2, 0xb9, 0xac, 0x54, 0xd7, 0x3e, 0x82, 0xe4, 0xf0, 0xed, 0x35, 0x4d,
- 0xe2, 0xd9, 0x0e, 0x4a, 0x1f, 0xeb, 0xba, 0xb2, 0x26, 0xc9, 0x5a, 0xb4,
- 0x5c, 0x97, 0x34, 0x79, 0x77, 0x90, 0x69, 0x9c, 0x3a, 0x28, 0x7c, 0xc5,
- 0xfb, 0x87, 0x8b, 0xef, 0xfa, 0xc3, 0xa9, 0xd4, 0x7d, 0xc8, 0x44, 0xce,
- 0x6a, 0xd8, 0xe1, 0x36, 0xf4, 0x85, 0x6c, 0xf0, 0x1d, 0x05, 0xd6, 0x1f,
- 0x6b, 0xc8, 0xdc, 0x76, 0xff, 0xf0, 0x41, 0x4e, 0xd3, 0xaa, 0xa7, 0xee,
- 0x96, 0xef, 0xe0, 0x93, 0xdc, 0x1d, 0xef, 0x1f, 0xd2, 0xbf, 0xef, 0xfe,
- 0xe1, 0x59, 0xf2, 0x63, 0xa2, 0x78, 0xff, 0xe0, 0x7c, 0xa7, 0xc5, 0x8f,
- 0xb9, 0x3a, 0x1c, 0x78, 0xaf, 0x5d, 0xc5, 0xd5, 0x9c, 0x11, 0x79, 0x19,
- 0x07, 0x30, 0xe0, 0xdd, 0x35, 0xf0, 0xcc, 0x6f, 0x0f, 0xe1, 0xd7, 0xed,
- 0xf2, 0xae, 0x21, 0x25, 0xd7, 0x38, 0xc9, 0xe5, 0x43, 0xa3, 0xde, 0x6c,
- 0x61, 0x2d, 0xd8, 0xb7, 0x51, 0xc1, 0x03, 0xc9, 0x7b, 0x3c, 0x6c, 0x4f,
- 0x16, 0x8c, 0x74, 0x94, 0xcf, 0xd6, 0x4d, 0xc9, 0x1a, 0xf9, 0x30, 0xcf,
- 0x86, 0xd0, 0x1a, 0xed, 0x5e, 0x4d, 0xb8, 0x4d, 0x91, 0x0f, 0x15, 0xc3,
- 0x39, 0x09, 0x79, 0x1f, 0x90, 0xb8, 0xe8, 0x57, 0x8c, 0xc5, 0x77, 0xfd,
- 0x46, 0xaa, 0xde, 0xc3, 0xcc, 0xc3, 0x3c, 0xa7, 0xc9, 0xbf, 0xbd, 0xf2,
- 0x8c, 0x87, 0x6d, 0x1c, 0xf3, 0xd2, 0x46, 0x79, 0xee, 0xfc, 0x54, 0x64,
- 0x57, 0x19, 0xce, 0x92, 0xa2, 0x31, 0x37, 0xa0, 0x3e, 0x49, 0x0d, 0x7f,
- 0x98, 0x1a, 0x2e, 0xcf, 0x08, 0xbd, 0x3c, 0x23, 0x34, 0x2d, 0xc6, 0xfd,
- 0x46, 0xe6, 0x06, 0xf5, 0x8e, 0x63, 0xf6, 0xf5, 0x2a, 0x46, 0xef, 0x02,
- 0xf5, 0x7f, 0xbf, 0x52, 0x1c, 0x73, 0x4d, 0x69, 0xcc, 0x7b, 0xf3, 0x9a,
- 0xb2, 0xd9, 0x05, 0x75, 0x07, 0xd1, 0x3d, 0x16, 0xb5, 0xa3, 0x50, 0x4e,
- 0x8e, 0x99, 0x72, 0xcd, 0x8c, 0xad, 0x95, 0xb1, 0x29, 0xf8, 0xb0, 0x45,
- 0xbe, 0xdb, 0x2a, 0xe3, 0x70, 0x2a, 0xec, 0x14, 0xb5, 0xf7, 0xb9, 0x60,
- 0x49, 0xbf, 0x7c, 0xfd, 0xd6, 0x2a, 0x38, 0x75, 0xa8, 0x0e, 0x98, 0xb5,
- 0x18, 0xd7, 0x51, 0x19, 0x36, 0x9b, 0x91, 0xd3, 0x83, 0xe8, 0xb7, 0x7e,
- 0x2b, 0xa8, 0x93, 0x7c, 0x1f, 0x78, 0xec, 0x79, 0x9e, 0xd7, 0xcd, 0xeb,
- 0x88, 0x25, 0x9f, 0xc6, 0x19, 0x7d, 0x08, 0xe5, 0xac, 0xa5, 0xaf, 0x78,
- 0x7a, 0x62, 0x13, 0xcf, 0x0a, 0x31, 0x64, 0xcb, 0x5a, 0x77, 0xdb, 0xd8,
- 0xf2, 0xfe, 0xe1, 0x7d, 0x91, 0x2d, 0x8e, 0xe1, 0xec, 0xb1, 0x32, 0x8c,
- 0xeb, 0x4b, 0xdd, 0xdd, 0x47, 0xdd, 0xa5, 0xb7, 0xfc, 0x5a, 0x39, 0x75,
- 0x77, 0xb7, 0xf5, 0x6d, 0x3c, 0x46, 0x8e, 0x57, 0x98, 0x9f, 0x88, 0xc7,
- 0xeb, 0xe4, 0x98, 0xd4, 0xd7, 0xaa, 0x95, 0xe3, 0xff, 0x33, 0xc7, 0x94,
- 0x73, 0xc8, 0x7a, 0x78, 0x59, 0x48, 0x6f, 0x56, 0x61, 0x0f, 0x2b, 0xdb,
- 0xc8, 0xa9, 0x45, 0x96, 0xde, 0xef, 0x92, 0x4f, 0x4b, 0xcc, 0x4f, 0xe3,
- 0x1d, 0xf8, 0xd4, 0x48, 0x3e, 0xed, 0x5a, 0xc1, 0xa7, 0xe3, 0xe4, 0x53,
- 0x2f, 0xf9, 0xd4, 0xd2, 0xf6, 0x27, 0xd4, 0x15, 0x21, 0x82, 0x6d, 0x37,
- 0xc5, 0x9b, 0x9e, 0xff, 0x95, 0x9e, 0x37, 0xad, 0x74, 0xcd, 0x4b, 0x7d,
- 0xaa, 0xa4, 0x27, 0xee, 0xa1, 0x1f, 0x06, 0x06, 0xc8, 0xa7, 0xc7, 0x4d,
- 0xd1, 0xb8, 0x2f, 0x69, 0xa4, 0x16, 0xe9, 0x6b, 0x7a, 0xc8, 0xa9, 0xb7,
- 0xc8, 0xa9, 0xb1, 0x42, 0x51, 0xa7, 0x0e, 0x73, 0xdd, 0xf7, 0x53, 0xa7,
- 0x7a, 0x0a, 0x52, 0xdb, 0x1c, 0xe2, 0x3f, 0x84, 0x4f, 0xc9, 0xa9, 0xf9,
- 0xa4, 0xa7, 0x53, 0xd6, 0x6f, 0x90, 0x18, 0x3a, 0x2f, 0xf9, 0x44, 0x9d,
- 0x72, 0x0b, 0x4d, 0xd6, 0x79, 0xae, 0x69, 0xd2, 0x35, 0x6e, 0x74, 0x93,
- 0x53, 0x81, 0x76, 0xe3, 0xe2, 0x55, 0x62, 0x37, 0x14, 0x83, 0x1e, 0xb1,
- 0xe5, 0x9a, 0x58, 0x63, 0x59, 0x27, 0x8f, 0x13, 0xff, 0xdd, 0xd4, 0x8c,
- 0xde, 0x82, 0x8d, 0x43, 0x85, 0x95, 0x7b, 0xca, 0x3a, 0x74, 0xc7, 0x7d,
- 0x19, 0x0d, 0xdd, 0xb9, 0x9d, 0xf5, 0xea, 0x8e, 0xed, 0x92, 0xaf, 0x7a,
- 0x48, 0xf2, 0x75, 0xd4, 0xfd, 0x61, 0xe0, 0xce, 0xef, 0xc8, 0xfb, 0x33,
- 0x21, 0x4e, 0x5b, 0xf2, 0xfe, 0x41, 0xfa, 0x1e, 0xfa, 0x68, 0x4b, 0xde,
- 0xa1, 0x75, 0x44, 0x55, 0x18, 0x91, 0x47, 0xf1, 0xb9, 0xc8, 0xd6, 0x39,
- 0xf1, 0x80, 0x57, 0x23, 0x0d, 0xbd, 0x8f, 0xb5, 0x6e, 0xb1, 0x74, 0xce,
- 0x9b, 0xcb, 0x09, 0xf1, 0x16, 0xeb, 0xd4, 0x69, 0x9e, 0xe9, 0x46, 0xf2,
- 0x9f, 0x8b, 0xc5, 0x3a, 0x15, 0x63, 0xe6, 0xad, 0xfb, 0x48, 0x4f, 0xc7,
- 0x4e, 0xf2, 0xd9, 0x44, 0x7e, 0xb9, 0x46, 0x51, 0x33, 0x4d, 0x21, 0x76,
- 0x9b, 0xff, 0x2d, 0xfa, 0xbf, 0xf2, 0xae, 0x10, 0xd3, 0x8c, 0xe1, 0x8a,
- 0x85, 0x03, 0x01, 0xc4, 0xfa, 0x6e, 0xb0, 0xae, 0x5f, 0xda, 0x68, 0x64,
- 0xf2, 0x4a, 0xa2, 0x77, 0xab, 0x22, 0xbd, 0x9e, 0xaf, 0xb3, 0x8c, 0xef,
- 0xb4, 0xd0, 0x1b, 0x7d, 0xc8, 0x0c, 0x06, 0xf9, 0xfd, 0x4d, 0xcb, 0xa0,
- 0x7f, 0x16, 0xa2, 0x3f, 0x25, 0xc7, 0x10, 0xa2, 0xc3, 0x92, 0xe7, 0x80,
- 0x31, 0x9e, 0x03, 0xb2, 0xa2, 0xc2, 0xbc, 0x42, 0x6d, 0x32, 0x32, 0x63,
- 0x8a, 0xc9, 0xbe, 0x51, 0x78, 0x3a, 0xcb, 0x67, 0xda, 0x54, 0x04, 0x7f,
- 0xed, 0xf9, 0xe7, 0x28, 0x35, 0xab, 0x01, 0x7f, 0xe3, 0xe9, 0x96, 0x8a,
- 0x3d, 0xcf, 0x1b, 0x29, 0x55, 0x39, 0x88, 0xf7, 0x2d, 0x43, 0xff, 0x21,
- 0xe3, 0xa6, 0xd6, 0x3c, 0xb7, 0x19, 0x51, 0x70, 0x8e, 0x6c, 0x9f, 0xbf,
- 0x46, 0xd1, 0x58, 0x3b, 0xbe, 0xdf, 0x22, 0x6b, 0xf7, 0x10, 0xba, 0x9b,
- 0xf7, 0xf3, 0xa3, 0xa2, 0x76, 0x46, 0x55, 0x76, 0xd0, 0x93, 0x54, 0xcf,
- 0x54, 0x63, 0xef, 0x7a, 0x21, 0xd6, 0xae, 0x77, 0xc0, 0x33, 0x5f, 0xfc,
- 0x02, 0x6b, 0xd0, 0x89, 0x1a, 0x23, 0x0d, 0xfc, 0x04, 0x3b, 0xe9, 0x65,
- 0x53, 0x6d, 0x39, 0xe0, 0x1e, 0xb9, 0xc6, 0x9f, 0x60, 0xb3, 0xf4, 0xc0,
- 0x56, 0xb5, 0xf4, 0x5b, 0x1e, 0x7e, 0x8b, 0x77, 0x48, 0x4c, 0xf5, 0xd1,
- 0xac, 0x28, 0x37, 0x8d, 0xbe, 0x79, 0xd6, 0xdb, 0x4b, 0xb1, 0xbb, 0xf5,
- 0x6f, 0xcd, 0x4b, 0x0f, 0x6c, 0x46, 0xb7, 0x28, 0x82, 0xb9, 0x78, 0x86,
- 0xb9, 0x88, 0x39, 0x61, 0x5a, 0x86, 0x6a, 0x3b, 0xe6, 0x54, 0x2b, 0xc3,
- 0xca, 0x83, 0xe4, 0x43, 0x5f, 0xb0, 0x9c, 0x1e, 0xc2, 0xa1, 0x7f, 0xf0,
- 0xa1, 0xf2, 0xa8, 0xf4, 0x14, 0x21, 0x6a, 0x4d, 0x53, 0x2f, 0x4f, 0x17,
- 0xd8, 0x97, 0x94, 0xfe, 0x83, 0x58, 0x3f, 0x7a, 0x53, 0x6c, 0xa6, 0xc7,
- 0xdd, 0x5c, 0xf2, 0xb8, 0xbb, 0x66, 0xd3, 0xf4, 0xc0, 0x9a, 0x22, 0xef,
- 0xd3, 0x52, 0x6d, 0x3c, 0x94, 0x3e, 0x28, 0x7d, 0x88, 0x5c, 0x83, 0x8e,
- 0x6b, 0x49, 0x89, 0x5d, 0x1d, 0xa3, 0xed, 0x46, 0x24, 0x0b, 0x79, 0x7f,
- 0x73, 0xbb, 0xbf, 0x80, 0x9e, 0xfe, 0x1d, 0xcf, 0x01, 0x7d, 0x07, 0x63,
- 0x31, 0x82, 0x42, 0xd4, 0x26, 0xfd, 0xe8, 0xf3, 0xce, 0x73, 0x11, 0x3d,
- 0x4d, 0xde, 0x5f, 0xa4, 0x4f, 0xf0, 0xf3, 0xdc, 0x7c, 0x90, 0x58, 0xfa,
- 0xac, 0x65, 0xe4, 0x58, 0x3d, 0xb2, 0x93, 0xb5, 0x30, 0xac, 0xfb, 0xa9,
- 0xab, 0x57, 0x72, 0x0f, 0xb2, 0x9e, 0xfb, 0xda, 0x23, 0x3c, 0x03, 0x34,
- 0xce, 0x64, 0x45, 0x3d, 0xfd, 0xe0, 0x37, 0x78, 0xee, 0xad, 0x69, 0x8b,
- 0xd3, 0x6f, 0x2f, 0xef, 0x95, 0x0f, 0x4f, 0x59, 0x26, 0x1c, 0xef, 0x77,
- 0x58, 0xef, 0x9a, 0xbd, 0x29, 0xe6, 0xcc, 0xbb, 0xf5, 0x8e, 0x62, 0x5c,
- 0x6a, 0x99, 0x6d, 0xa1, 0x65, 0x03, 0xcf, 0x8e, 0x77, 0x88, 0xa9, 0x47,
- 0x7a, 0x9f, 0x40, 0xb1, 0xdf, 0x9f, 0xce, 0x36, 0xe8, 0xdb, 0x59, 0xef,
- 0x16, 0x89, 0x95, 0x5d, 0xeb, 0x2d, 0x19, 0xcb, 0xa2, 0x8c, 0x85, 0xfe,
- 0xd2, 0xb9, 0xdf, 0x47, 0x5f, 0x92, 0x04, 0xaa, 0xcf, 0x3e, 0x45, 0x5e,
- 0xf9, 0x5a, 0xab, 0x91, 0x1d, 0x62, 0x8c, 0xc7, 0xfe, 0x91, 0x5b, 0x33,
- 0x30, 0x8d, 0x01, 0x1f, 0xfb, 0x4c, 0x59, 0xc0, 0x13, 0x0b, 0x3c, 0x97,
- 0x4e, 0xc7, 0xe8, 0xcb, 0xe9, 0x23, 0x17, 0x34, 0x3c, 0x3a, 0x5b, 0x8e,
- 0xef, 0xcd, 0x86, 0xb1, 0x6f, 0xd6, 0xbb, 0xd7, 0xda, 0x5a, 0xcb, 0xf7,
- 0x3a, 0x92, 0x42, 0xcc, 0x5b, 0xeb, 0xf1, 0x1e, 0x3d, 0xd4, 0x6a, 0xc5,
- 0x87, 0xc8, 0x51, 0xe8, 0x3a, 0x71, 0x53, 0xd3, 0xf2, 0x3d, 0x26, 0x58,
- 0x08, 0x73, 0xbd, 0xd4, 0xc9, 0x67, 0xbc, 0xef, 0x63, 0xf4, 0x8f, 0x19,
- 0x89, 0x41, 0x97, 0x18, 0x74, 0x89, 0xc9, 0x5b, 0x9e, 0x5a, 0x62, 0x39,
- 0x4e, 0x1f, 0xfd, 0xb4, 0x28, 0x62, 0xe3, 0x0b, 0x71, 0xda, 0x7c, 0x95,
- 0xfc, 0x55, 0xa9, 0xa1, 0xc0, 0xdf, 0xe7, 0x22, 0xfa, 0x8e, 0x82, 0xcc,
- 0xff, 0x5f, 0x96, 0xf2, 0xbf, 0x18, 0x2a, 0xea, 0x85, 0xe1, 0xcc, 0xa3,
- 0x01, 0xd3, 0x6e, 0x83, 0xbe, 0xd5, 0x1d, 0x19, 0xd6, 0x90, 0x8d, 0x56,
- 0xc3, 0x18, 0x9c, 0x86, 0xaf, 0x35, 0x0c, 0xb9, 0x76, 0x20, 0xef, 0xad,
- 0x51, 0x88, 0x09, 0xea, 0x9b, 0xcc, 0xc1, 0xbf, 0xe7, 0xd0, 0xea, 0x63,
- 0x3e, 0x1c, 0xc6, 0xbe, 0x8f, 0x7b, 0xf0, 0x71, 0x5e, 0xde, 0x73, 0xc6,
- 0xd2, 0x5d, 0xb8, 0xee, 0x8d, 0xf9, 0x51, 0x3e, 0x85, 0x23, 0xee, 0x25,
- 0x71, 0xa4, 0xae, 0xa8, 0xf1, 0x69, 0x9e, 0x8f, 0xaa, 0x8f, 0x96, 0xbc,
- 0x10, 0x39, 0x5c, 0xc9, 0xf5, 0x5e, 0x4b, 0x7a, 0xde, 0x9f, 0x35, 0x72,
- 0x50, 0x3b, 0x6d, 0x6e, 0xe4, 0xda, 0x6e, 0x8a, 0x89, 0x58, 0xb3, 0x56,
- 0x8c, 0x29, 0xa1, 0x9f, 0x42, 0x19, 0xb1, 0x2b, 0xcf, 0x48, 0x52, 0x3f,
- 0xe4, 0x6f, 0x9e, 0x4f, 0x54, 0x27, 0xe2, 0xe7, 0xba, 0x9c, 0x87, 0x64,
- 0x5b, 0xa8, 0xe4, 0x57, 0x97, 0xbd, 0x48, 0x07, 0x9f, 0x49, 0x2f, 0xf2,
- 0xb9, 0xe8, 0xab, 0xeb, 0xb8, 0xa5, 0x39, 0x59, 0xbe, 0x31, 0xee, 0xca,
- 0xfb, 0xab, 0x16, 0x3a, 0x62, 0x05, 0xe7, 0x18, 0xf9, 0xa9, 0xd6, 0x98,
- 0x3e, 0xca, 0xf1, 0x1c, 0x5d, 0x27, 0x97, 0x0f, 0xd2, 0x2f, 0xf3, 0x9d,
- 0x42, 0x0b, 0xfb, 0x48, 0x2d, 0xdb, 0xc1, 0xb5, 0xfe, 0xb6, 0x59, 0x62,
- 0x7b, 0xd4, 0x7d, 0xc3, 0xa7, 0x9a, 0x72, 0x9d, 0x89, 0xd4, 0x28, 0xe3,
- 0x59, 0xd2, 0xa5, 0xb7, 0x76, 0xa8, 0x6d, 0x09, 0xaf, 0x7f, 0x56, 0x95,
- 0x71, 0x78, 0xf1, 0xb0, 0x4d, 0x6a, 0x96, 0x91, 0x39, 0x87, 0x84, 0x33,
- 0x20, 0xcd, 0xc1, 0x2a, 0x19, 0x43, 0x53, 0x64, 0x80, 0xf1, 0x9c, 0xa8,
- 0xf3, 0xf4, 0x90, 0xcf, 0x38, 0x9f, 0xeb, 0xdb, 0x5a, 0x0e, 0x81, 0xd5,
- 0x49, 0xef, 0xdc, 0x5f, 0xfa, 0x7f, 0x18, 0x2a, 0x7d, 0x88, 0xc4, 0xe2,
- 0xff, 0x02, 0xc7, 0x2a, 0x26, 0xcf, 0x94, 0x1a, 0x00, 0x00, 0x00 };
+ 0xbd, 0x59, 0x6d, 0x70, 0x5b, 0x55, 0x7a, 0x7e, 0xae, 0x74, 0x25, 0x5d,
+ 0xdb, 0xb2, 0x75, 0x8d, 0x95, 0x20, 0xb7, 0x2e, 0xd6, 0x8d, 0xaf, 0x6c,
+ 0x11, 0xb9, 0xe1, 0x2a, 0x36, 0x45, 0x19, 0xee, 0x94, 0x1b, 0x7f, 0x21,
+ 0x92, 0x10, 0x94, 0x42, 0x5b, 0x67, 0x96, 0x19, 0x4c, 0xe2, 0x4d, 0x4c,
+ 0x08, 0x6c, 0xba, 0xcb, 0x4c, 0xdd, 0xd9, 0x4c, 0x23, 0xfc, 0x15, 0x93,
+ 0xc8, 0x16, 0x6b, 0x20, 0x26, 0x3b, 0x3b, 0x43, 0xc6, 0xf9, 0x70, 0x0a,
+ 0x72, 0x14, 0xda, 0x3f, 0x3b, 0xd3, 0x65, 0xf0, 0x6c, 0x12, 0x12, 0x58,
+ 0xd8, 0xb4, 0xd3, 0x3f, 0xc9, 0xf4, 0xc7, 0x7a, 0x21, 0xa1, 0x81, 0x42,
+ 0x36, 0xed, 0x0c, 0x9d, 0x50, 0x68, 0x4e, 0x9f, 0x73, 0x25, 0x07, 0x13,
+ 0xb2, 0xfd, 0xd9, 0xcc, 0x08, 0x4b, 0xe7, 0xde, 0x73, 0xce, 0x7b, 0xce,
+ 0xfb, 0x3c, 0xcf, 0xfb, 0x9c, 0xc3, 0x0a, 0x05, 0x95, 0x28, 0xff, 0xab,
+ 0xe6, 0xa7, 0xfd, 0xc9, 0x5d, 0xcf, 0xad, 0x5e, 0xd5, 0xbe, 0x8a, 0x5f,
+ 0x57, 0x2b, 0xcb, 0x55, 0x15, 0xff, 0x8f, 0xff, 0xbc, 0x80, 0xbe, 0x18,
+ 0x87, 0xfc, 0x40, 0xf3, 0xd8, 0xf3, 0x77, 0x75, 0x98, 0xd0, 0xbc, 0xf6,
+ 0x63, 0x4d, 0x5b, 0x4d, 0xc0, 0x29, 0x24, 0xa2, 0x9d, 0xf8, 0x1f, 0x91,
+ 0x0d, 0xab, 0x90, 0xed, 0x7f, 0x64, 0x7f, 0x7d, 0xcf, 0x5b, 0xf7, 0x19,
+ 0xd7, 0x0e, 0x79, 0xa1, 0xe9, 0xf6, 0xb8, 0xaa, 0x37, 0x43, 0x6b, 0x60,
+ 0x9f, 0x9f, 0xb5, 0xf4, 0xfb, 0x50, 0xb3, 0x38, 0x16, 0x70, 0x38, 0x67,
+ 0x58, 0xdb, 0x90, 0xd0, 0x4f, 0x41, 0x85, 0xc3, 0x39, 0x8e, 0x15, 0x80,
+ 0xbd, 0x39, 0x05, 0x97, 0x39, 0xe6, 0x68, 0x41, 0xc3, 0x82, 0xd7, 0x9d,
+ 0xae, 0xaf, 0xc2, 0x46, 0xc6, 0x9c, 0xd8, 0x23, 0x02, 0x26, 0xb2, 0x7f,
+ 0x60, 0x9b, 0xf1, 0xbd, 0x08, 0xa6, 0x66, 0xda, 0x91, 0x59, 0x31, 0xa7,
+ 0x61, 0x73, 0xbe, 0xa1, 0x4f, 0xb3, 0xc1, 0x77, 0x14, 0xa4, 0xee, 0xd3,
+ 0xd0, 0x5b, 0x8c, 0x23, 0x5b, 0xcc, 0xc2, 0x29, 0x8e, 0xf0, 0xa3, 0x21,
+ 0x30, 0xa1, 0x69, 0xf7, 0x4c, 0x2c, 0x97, 0xef, 0x20, 0x38, 0x71, 0x4d,
+ 0x5c, 0x4d, 0xea, 0x78, 0x6f, 0x8d, 0x10, 0xd5, 0x36, 0xb2, 0x55, 0xed,
+ 0x59, 0x78, 0x6d, 0xc3, 0x5a, 0xef, 0x55, 0xd0, 0xf5, 0xc7, 0x66, 0x7c,
+ 0x42, 0x79, 0xf4, 0x51, 0x8f, 0x0d, 0x4d, 0xb1, 0xa3, 0x6a, 0x53, 0xa1,
+ 0x01, 0x63, 0x45, 0x1d, 0x7b, 0x8b, 0x61, 0x8c, 0x14, 0xb1, 0xdb, 0x7b,
+ 0xaf, 0x1f, 0x33, 0x3a, 0x9c, 0xef, 0xb5, 0xec, 0xc6, 0x8e, 0xdc, 0x20,
+ 0xb6, 0xe6, 0x52, 0xd8, 0x57, 0x94, 0x31, 0x46, 0x31, 0x5c, 0x54, 0xe1,
+ 0x9f, 0x30, 0x22, 0xef, 0xe2, 0x76, 0xcf, 0x84, 0x18, 0xb1, 0x02, 0x18,
+ 0xb2, 0xe2, 0x18, 0xcd, 0x7b, 0xb8, 0xce, 0x00, 0x86, 0xcd, 0xeb, 0xa2,
+ 0xdf, 0x32, 0xac, 0x51, 0x88, 0xc6, 0xd3, 0x96, 0x11, 0xe9, 0xf2, 0xc2,
+ 0xf9, 0xb1, 0x19, 0xc1, 0x28, 0x63, 0x1f, 0x71, 0xfb, 0x8d, 0xa0, 0xeb,
+ 0x66, 0x3f, 0x87, 0xfd, 0x74, 0x8c, 0x7d, 0xbb, 0x6f, 0x74, 0x14, 0x89,
+ 0xc8, 0x18, 0x3c, 0xe8, 0x0b, 0xb7, 0xb2, 0x5f, 0x53, 0x74, 0x0c, 0x46,
+ 0x9c, 0xe3, 0x64, 0xfd, 0xed, 0x0e, 0xc7, 0xc8, 0xb2, 0xbf, 0x11, 0x3d,
+ 0x06, 0x39, 0x56, 0x03, 0x7f, 0xb7, 0xb3, 0xbf, 0x02, 0x8f, 0x1d, 0x8b,
+ 0x0e, 0xb1, 0xcf, 0x29, 0x4b, 0xc5, 0x19, 0x7e, 0xfa, 0x74, 0x43, 0x66,
+ 0x56, 0x09, 0xb0, 0x7d, 0x2f, 0xf8, 0xdc, 0xac, 0xc2, 0xa1, 0x8c, 0x85,
+ 0x21, 0xae, 0x5b, 0x63, 0xdb, 0x38, 0xdb, 0x7c, 0xa6, 0xc5, 0xf1, 0xa1,
+ 0x77, 0x15, 0x97, 0x62, 0x62, 0x31, 0x37, 0xbf, 0xaf, 0x9d, 0x63, 0xe4,
+ 0x4b, 0x39, 0x95, 0xef, 0x74, 0xe6, 0x6f, 0x88, 0x27, 0xd5, 0xa5, 0xcf,
+ 0x07, 0x95, 0x0e, 0xb6, 0x39, 0x6a, 0x03, 0xf6, 0xe6, 0xa1, 0xf9, 0x4d,
+ 0x8d, 0xf3, 0x68, 0xf8, 0x28, 0x37, 0xa8, 0xf4, 0x14, 0x1d, 0xa5, 0x7b,
+ 0xb6, 0x43, 0x71, 0x66, 0x55, 0xa5, 0x6b, 0x5a, 0xc6, 0x2d, 0xc4, 0x0b,
+ 0x96, 0xc2, 0x98, 0x7f, 0x22, 0xe3, 0x75, 0xa2, 0xca, 0x0d, 0xb1, 0x32,
+ 0xe6, 0x41, 0x95, 0xd9, 0xa3, 0xac, 0x9f, 0x15, 0x22, 0x9d, 0x4c, 0x2b,
+ 0xeb, 0x66, 0xa1, 0x05, 0x6d, 0x5b, 0xcd, 0x4d, 0xec, 0x43, 0x76, 0x99,
+ 0x89, 0x83, 0xf9, 0x28, 0x3e, 0xb0, 0x3c, 0x38, 0xb4, 0xac, 0x02, 0xaa,
+ 0xa9, 0xf0, 0x83, 0xe0, 0x79, 0x0b, 0x6a, 0x0d, 0xbf, 0x5f, 0xdd, 0xa4,
+ 0x62, 0xa4, 0x7d, 0x9d, 0xd2, 0xc5, 0x3e, 0x3e, 0xe6, 0xf9, 0x68, 0x2e,
+ 0x8d, 0x20, 0xb1, 0x53, 0x65, 0xc7, 0x22, 0x05, 0xee, 0xcd, 0x7b, 0x56,
+ 0x2c, 0xfe, 0xb4, 0xc4, 0x63, 0xad, 0x11, 0x91, 0x7b, 0x53, 0x6d, 0xc7,
+ 0xe2, 0x73, 0xdc, 0x07, 0xaf, 0xa9, 0xe2, 0xd7, 0x96, 0x0f, 0xf3, 0x9b,
+ 0x2c, 0xe6, 0x54, 0x87, 0x9f, 0xed, 0xc7, 0xdc, 0x76, 0xf9, 0x1b, 0x7a,
+ 0xf7, 0xb7, 0xf6, 0xa1, 0xb4, 0x07, 0xc3, 0xf9, 0x26, 0xc6, 0x5c, 0xda,
+ 0x83, 0x47, 0xb8, 0xde, 0xdf, 0xfa, 0xe4, 0xd7, 0xbb, 0x6e, 0xb6, 0x6d,
+ 0x66, 0x9c, 0x1e, 0xdb, 0x9c, 0x5f, 0xe1, 0xad, 0x07, 0xea, 0xda, 0xb1,
+ 0x8f, 0x39, 0xee, 0x4a, 0x2e, 0x47, 0xd6, 0x7d, 0x1e, 0xd6, 0xd7, 0x4f,
+ 0xd7, 0xa1, 0x6f, 0x99, 0xbb, 0x6f, 0xfa, 0xc6, 0x69, 0x21, 0xce, 0x24,
+ 0xfd, 0x98, 0x33, 0x87, 0x22, 0xd5, 0xc8, 0x5a, 0x5e, 0xe6, 0xfb, 0x2c,
+ 0xe7, 0x2f, 0x24, 0xbd, 0x38, 0x9c, 0x3c, 0x84, 0x6c, 0x2d, 0x30, 0x93,
+ 0x93, 0xbc, 0x32, 0xe6, 0xcf, 0xf2, 0xbf, 0x9e, 0xa2, 0x5c, 0x9f, 0xc5,
+ 0xf5, 0x29, 0x38, 0x66, 0x4a, 0x4c, 0x5b, 0x6a, 0x33, 0xf9, 0xb5, 0x83,
+ 0xfb, 0x59, 0xdf, 0x1e, 0x24, 0x3e, 0x81, 0x0f, 0x73, 0xfd, 0xd8, 0x5c,
+ 0x8a, 0x05, 0xd7, 0x73, 0x50, 0x7c, 0x6d, 0x69, 0x1c, 0x2a, 0xfd, 0x26,
+ 0xc7, 0xd3, 0x6a, 0x47, 0xce, 0xc8, 0xa4, 0x91, 0x38, 0xd7, 0xa1, 0xc8,
+ 0xfe, 0x69, 0x75, 0x65, 0xc1, 0x8f, 0x68, 0x5d, 0xe9, 0x79, 0x95, 0xbd,
+ 0x41, 0x7d, 0x7a, 0x42, 0xc1, 0xf6, 0x98, 0x7c, 0xb6, 0x41, 0x6d, 0x29,
+ 0x40, 0xab, 0xb6, 0x77, 0xa9, 0x73, 0x13, 0x46, 0xdf, 0x71, 0x25, 0x11,
+ 0x9d, 0x70, 0xfb, 0xec, 0x52, 0x5b, 0x0b, 0x01, 0xae, 0x27, 0xce, 0x9c,
+ 0x40, 0xab, 0xb1, 0x9f, 0x53, 0x7f, 0xcd, 0x07, 0xe7, 0xdc, 0x3e, 0xcf,
+ 0xa9, 0xf1, 0x82, 0x6c, 0x37, 0xac, 0xa8, 0x12, 0xc0, 0xdd, 0x49, 0x0d,
+ 0x2b, 0x5b, 0x44, 0x63, 0x77, 0xd2, 0x98, 0xef, 0xf6, 0x46, 0x70, 0x90,
+ 0x5c, 0x20, 0xee, 0x9c, 0x3f, 0x6c, 0x19, 0x41, 0x77, 0xd1, 0x8b, 0x68,
+ 0xad, 0x83, 0xfd, 0xf9, 0x00, 0x7e, 0x49, 0xfc, 0xf7, 0x58, 0x3a, 0x46,
+ 0xf2, 0x46, 0xfc, 0x57, 0x48, 0xa4, 0x8e, 0x30, 0x67, 0x0b, 0xe4, 0xc0,
+ 0xfe, 0x62, 0x53, 0xfc, 0x08, 0x8c, 0x81, 0x6e, 0x72, 0x40, 0x6b, 0x97,
+ 0x31, 0x40, 0x57, 0x6d, 0x72, 0xa7, 0xd8, 0x80, 0x1c, 0xf9, 0xd0, 0xed,
+ 0xf2, 0x6a, 0x50, 0xe9, 0x2a, 0xbe, 0x4f, 0x6d, 0xed, 0x21, 0xbe, 0x10,
+ 0x8a, 0x98, 0x7e, 0xa4, 0xea, 0xa2, 0x38, 0x4d, 0xac, 0x64, 0xc3, 0x15,
+ 0xcc, 0xa5, 0xcc, 0xe7, 0x45, 0x3e, 0x5f, 0xa7, 0x74, 0xce, 0x46, 0xf1,
+ 0x4b, 0xeb, 0x6b, 0xe1, 0x84, 0xab, 0xd9, 0xe6, 0x5b, 0xd2, 0xae, 0xe1,
+ 0xf2, 0xcb, 0x95, 0xf8, 0xf4, 0xe5, 0x20, 0xbe, 0x7c, 0x99, 0xfc, 0xce,
+ 0xa3, 0xbd, 0x12, 0x42, 0xa4, 0xda, 0x84, 0x28, 0x5a, 0xad, 0xf8, 0xa8,
+ 0x36, 0x16, 0xbd, 0x00, 0xa9, 0x8d, 0x8e, 0xba, 0x35, 0x67, 0xec, 0x1a,
+ 0x40, 0xc2, 0x39, 0xe5, 0xee, 0x85, 0xa3, 0xae, 0x2a, 0x9c, 0x16, 0xd8,
+ 0x54, 0xda, 0x0b, 0xbf, 0xdd, 0xa5, 0xbe, 0xc3, 0xdc, 0x9c, 0x77, 0x73,
+ 0xd3, 0xa5, 0xde, 0x53, 0xb8, 0xdf, 0x83, 0xca, 0xd2, 0x33, 0xd5, 0xce,
+ 0xa8, 0x23, 0x39, 0xa3, 0x77, 0x9c, 0xeb, 0xeb, 0x77, 0xfb, 0x66, 0xd4,
+ 0x04, 0xf7, 0x7e, 0xa1, 0x9c, 0x9b, 0x6a, 0xfb, 0x31, 0xee, 0x33, 0x73,
+ 0xef, 0xee, 0xe3, 0x63, 0xdc, 0x63, 0x39, 0xdf, 0xe0, 0x2d, 0xf3, 0x0d,
+ 0x72, 0xbe, 0xe3, 0x4b, 0xe6, 0xdb, 0xbd, 0x64, 0xbe, 0xdd, 0x4b, 0xe6,
+ 0x4b, 0x91, 0xab, 0xff, 0x22, 0x86, 0xc2, 0xa5, 0xb1, 0x55, 0x7b, 0xe0,
+ 0x96, 0xb9, 0x07, 0x38, 0xf7, 0x01, 0xb1, 0x90, 0x29, 0x8d, 0x53, 0x6d,
+ 0xef, 0x5c, 0x32, 0xf7, 0x4e, 0xce, 0xbd, 0x38, 0x8e, 0x4e, 0x2d, 0x12,
+ 0x62, 0xa3, 0x25, 0x84, 0x6a, 0x9b, 0x7a, 0x17, 0x9a, 0x33, 0x5d, 0xc4,
+ 0x4e, 0x25, 0x12, 0xf3, 0x1e, 0x98, 0x83, 0xf5, 0x5e, 0x1f, 0x16, 0x6a,
+ 0x17, 0xb9, 0x51, 0x5d, 0xfe, 0xfb, 0x9a, 0x02, 0x6a, 0xfd, 0x1b, 0xb9,
+ 0x10, 0xc7, 0x88, 0xe9, 0xfd, 0x8a, 0x10, 0xa7, 0xd6, 0x24, 0x06, 0xbc,
+ 0x48, 0xf4, 0xd5, 0xc0, 0x24, 0x86, 0x7c, 0x65, 0x2e, 0x2c, 0xed, 0x73,
+ 0xdc, 0xed, 0x53, 0x74, 0xfb, 0x08, 0xf1, 0xe1, 0xbd, 0x57, 0xc4, 0x5b,
+ 0x2d, 0x61, 0xbc, 0x4d, 0x4e, 0x9e, 0x2c, 0x2e, 0xea, 0x8a, 0xd4, 0x0d,
+ 0x78, 0x4e, 0x59, 0x7e, 0xc6, 0x34, 0xb4, 0xc3, 0xff, 0xad, 0xfe, 0x04,
+ 0x8c, 0x29, 0xdb, 0xbc, 0x78, 0x3d, 0x89, 0x27, 0x2b, 0x61, 0xf4, 0xee,
+ 0x53, 0xb2, 0xe9, 0x2a, 0x18, 0xce, 0x4a, 0x25, 0x9b, 0xd2, 0x20, 0x79,
+ 0xa3, 0x36, 0x1e, 0x35, 0x8d, 0xec, 0x65, 0xbe, 0xac, 0x4e, 0xde, 0x2e,
+ 0x06, 0x95, 0x63, 0x04, 0xf1, 0x6c, 0xfe, 0x7d, 0xcc, 0xfb, 0xa4, 0x86,
+ 0x49, 0xed, 0xe4, 0xc0, 0x27, 0xa4, 0x86, 0x05, 0x48, 0x44, 0x15, 0x7b,
+ 0xf2, 0x9e, 0xd3, 0x8d, 0x10, 0xf0, 0xb7, 0xf9, 0x70, 0xd1, 0x1c, 0xb6,
+ 0xea, 0xb1, 0x16, 0xe7, 0x5b, 0xb9, 0x07, 0xcb, 0x54, 0x44, 0x66, 0x96,
+ 0x8e, 0x15, 0xe1, 0x58, 0x11, 0x7c, 0x92, 0x13, 0xa2, 0xd2, 0x36, 0xe2,
+ 0x0b, 0x30, 0x19, 0x47, 0x04, 0x57, 0x0a, 0x5b, 0xfc, 0xa8, 0x09, 0x43,
+ 0x6d, 0x56, 0xb1, 0x3d, 0xaf, 0x29, 0xdd, 0x79, 0xe8, 0x5e, 0xdb, 0x8c,
+ 0x1e, 0xc6, 0x51, 0xc6, 0xc3, 0xba, 0x76, 0x4c, 0x55, 0x36, 0x4e, 0x07,
+ 0x50, 0x3d, 0xf5, 0x99, 0x78, 0x9f, 0x7a, 0xf8, 0xc6, 0xbd, 0xac, 0x17,
+ 0xc9, 0x00, 0xaa, 0xdc, 0xb9, 0x85, 0xf8, 0xb8, 0xad, 0x0e, 0x17, 0x39,
+ 0x5f, 0xf4, 0x2f, 0x03, 0xf0, 0x4e, 0x05, 0xe0, 0x9b, 0x52, 0x30, 0xd3,
+ 0x1e, 0x80, 0x67, 0x46, 0xfe, 0x56, 0x10, 0x30, 0xa7, 0xb1, 0x5d, 0x6f,
+ 0xc0, 0x78, 0x9e, 0x45, 0xda, 0xfc, 0x19, 0x06, 0xdc, 0xef, 0x2a, 0x9e,
+ 0xca, 0x6b, 0x08, 0x1d, 0x10, 0xa2, 0xd1, 0x16, 0x22, 0x96, 0xf4, 0x60,
+ 0xd6, 0x1c, 0x8e, 0x06, 0xb8, 0x8e, 0x61, 0x4b, 0x6a, 0x8e, 0x0f, 0xea,
+ 0x8c, 0x91, 0x39, 0xc7, 0xa8, 0x37, 0x4f, 0xa8, 0x4a, 0xef, 0xf4, 0x1e,
+ 0xc1, 0x98, 0xfa, 0x1e, 0xf0, 0x0a, 0x51, 0xd3, 0xd6, 0x34, 0x70, 0x9e,
+ 0xda, 0x3c, 0x13, 0x8b, 0xf5, 0x0e, 0x29, 0xc0, 0xfa, 0x39, 0x1f, 0xfc,
+ 0x53, 0xff, 0xc5, 0x3a, 0x2b, 0x44, 0xe1, 0x5e, 0x81, 0x77, 0xad, 0x6c,
+ 0xbc, 0x02, 0x46, 0xea, 0x24, 0xc2, 0xb8, 0xf4, 0xa2, 0x10, 0xdb, 0xdb,
+ 0x43, 0x78, 0xcd, 0x32, 0x76, 0x7d, 0xec, 0x15, 0xb8, 0x98, 0xcc, 0x0e,
+ 0xd6, 0x53, 0xb7, 0xae, 0x29, 0x51, 0x54, 0xe5, 0x8d, 0xcc, 0x15, 0x85,
+ 0x4b, 0x9f, 0x31, 0xf5, 0x9d, 0x4a, 0x10, 0x55, 0x27, 0x82, 0xe8, 0x98,
+ 0xf3, 0xa3, 0x62, 0x2a, 0x08, 0xef, 0xa4, 0x79, 0xfd, 0x41, 0xb8, 0xe3,
+ 0x58, 0x27, 0xd1, 0x8c, 0x8b, 0x2f, 0x1b, 0xf3, 0xc7, 0x89, 0x93, 0xed,
+ 0x88, 0xe2, 0x37, 0x05, 0x13, 0x17, 0x0b, 0x41, 0xa8, 0x27, 0x74, 0xd4,
+ 0xbb, 0xf5, 0x4e, 0x47, 0xb5, 0xe9, 0x61, 0x5e, 0x1c, 0xe5, 0x61, 0xb7,
+ 0x9e, 0x74, 0xf1, 0xd3, 0xa3, 0x74, 0xb0, 0xae, 0x6c, 0x98, 0x26, 0x95,
+ 0xf9, 0xec, 0x9c, 0x75, 0x43, 0xec, 0x8f, 0xa5, 0x59, 0x47, 0x2a, 0xe0,
+ 0xb3, 0xd7, 0xb1, 0x8e, 0xb0, 0x38, 0xb9, 0xba, 0x5f, 0xa1, 0xf8, 0xec,
+ 0xef, 0x6a, 0x7e, 0x88, 0x9a, 0x5f, 0xfc, 0x3f, 0x35, 0x5f, 0x85, 0x3a,
+ 0xe5, 0xc1, 0x98, 0x19, 0xc0, 0x6f, 0xac, 0xa6, 0x73, 0x8d, 0x08, 0x20,
+ 0xd5, 0xa6, 0x23, 0x72, 0xc2, 0xc2, 0x8b, 0xdc, 0x5b, 0xdc, 0x71, 0x6b,
+ 0x3d, 0x04, 0x76, 0x92, 0x53, 0x15, 0xd4, 0x86, 0xbb, 0x27, 0x82, 0xd4,
+ 0x29, 0x55, 0x59, 0x4f, 0x9d, 0xdf, 0x91, 0xbc, 0x21, 0xd2, 0x31, 0x23,
+ 0x1e, 0x57, 0x12, 0xa9, 0xbf, 0x43, 0x49, 0x3b, 0x62, 0xd4, 0xd1, 0x05,
+ 0x7d, 0x91, 0x83, 0x5d, 0x2e, 0x07, 0x67, 0x62, 0x25, 0xed, 0x58, 0x51,
+ 0x28, 0xf1, 0xef, 0x01, 0xea, 0xe7, 0xf5, 0xb6, 0x92, 0x76, 0xbe, 0x4a,
+ 0xff, 0xd3, 0xcb, 0xf1, 0x1e, 0x99, 0x36, 0xb2, 0xbd, 0xcc, 0xcf, 0x25,
+ 0x62, 0x63, 0x92, 0x19, 0x9c, 0xaf, 0xa5, 0xa6, 0x36, 0x07, 0x18, 0xe3,
+ 0x75, 0x71, 0x9a, 0xde, 0x62, 0x98, 0xfd, 0x46, 0xf3, 0x46, 0x74, 0x98,
+ 0x7c, 0x1f, 0x2d, 0x6b, 0xe9, 0x30, 0xfd, 0xc4, 0x28, 0xf3, 0xf4, 0x36,
+ 0x9f, 0x9d, 0xcc, 0x1b, 0xe9, 0x2e, 0x57, 0x53, 0xa5, 0xaf, 0x90, 0x31,
+ 0x49, 0x6f, 0x11, 0xc1, 0x5b, 0x2d, 0x52, 0x5f, 0x1b, 0xa8, 0xaf, 0x8b,
+ 0xba, 0x2a, 0xf1, 0x70, 0x4d, 0x84, 0x5a, 0x42, 0x5e, 0xc9, 0xcb, 0x4b,
+ 0x49, 0x21, 0xaa, 0xec, 0x20, 0x2a, 0x27, 0xcc, 0xf4, 0x7a, 0x25, 0x16,
+ 0x31, 0x95, 0xbb, 0xd8, 0xce, 0x1c, 0xce, 0x6d, 0xf2, 0xba, 0xde, 0xf6,
+ 0x84, 0x10, 0x21, 0x5b, 0x47, 0xcd, 0x84, 0x49, 0xdc, 0xc4, 0xfa, 0x8e,
+ 0xb8, 0xcf, 0x75, 0x04, 0xe7, 0x16, 0xc8, 0xe7, 0x08, 0xf9, 0x1c, 0xc6,
+ 0x9b, 0xb7, 0x70, 0x9a, 0x5a, 0xeb, 0xe9, 0x27, 0xa7, 0xb3, 0xe1, 0xa1,
+ 0x2d, 0xde, 0x6f, 0xf1, 0x71, 0xbf, 0xe4, 0x34, 0xdb, 0xbc, 0x78, 0x21,
+ 0x89, 0xcd, 0xc4, 0x47, 0xe6, 0x29, 0x25, 0xeb, 0x90, 0xdb, 0xa9, 0x0a,
+ 0x25, 0x4b, 0x17, 0xf5, 0x0d, 0xa7, 0xcf, 0xf0, 0x6d, 0x2f, 0x39, 0xdd,
+ 0x17, 0xbe, 0x95, 0xd3, 0x2c, 0xbe, 0xcc, 0xf7, 0x33, 0xf9, 0x83, 0x98,
+ 0xf1, 0xf9, 0x11, 0x99, 0xf2, 0x21, 0x30, 0xa5, 0x92, 0x5f, 0x0a, 0xfd,
+ 0x41, 0x36, 0x1e, 0x80, 0x91, 0x3e, 0x89, 0x08, 0x12, 0x13, 0x1a, 0xfe,
+ 0xaa, 0xc5, 0x87, 0x63, 0x31, 0x23, 0xb3, 0x93, 0x3c, 0x5d, 0x39, 0x37,
+ 0xc4, 0x88, 0x8c, 0x68, 0xd4, 0x53, 0xe2, 0xab, 0xaf, 0xd9, 0x0f, 0x6d,
+ 0xca, 0xe5, 0xe0, 0x1e, 0x8f, 0x9d, 0x8d, 0x6a, 0x30, 0x76, 0xfd, 0x84,
+ 0xb8, 0xb8, 0x30, 0x21, 0x44, 0x67, 0xbb, 0x79, 0xee, 0x23, 0xaf, 0x41,
+ 0x2d, 0x54, 0x71, 0x7e, 0xae, 0x34, 0x7e, 0xd5, 0x94, 0x06, 0xff, 0x01,
+ 0x77, 0xfc, 0xeb, 0x6f, 0x32, 0x8a, 0xcf, 0xf3, 0x12, 0x9f, 0x42, 0x04,
+ 0x6c, 0x33, 0x32, 0x4b, 0x3d, 0xdc, 0x97, 0x34, 0xb8, 0x7f, 0x4d, 0x4e,
+ 0x33, 0xbf, 0x7b, 0x92, 0xb1, 0xe8, 0x16, 0xbe, 0x73, 0xa9, 0x58, 0xe2,
+ 0x70, 0xbd, 0xb9, 0x15, 0x7f, 0xa3, 0x7b, 0x51, 0x63, 0xfe, 0x10, 0xcf,
+ 0xba, 0x1a, 0x45, 0xec, 0x4f, 0x56, 0xa2, 0x91, 0x98, 0x7f, 0x82, 0x98,
+ 0xdf, 0x3c, 0x4b, 0xad, 0x99, 0x6a, 0x67, 0x7e, 0x25, 0xdf, 0xbb, 0x94,
+ 0xde, 0xd9, 0x1e, 0xd7, 0x57, 0x3d, 0x32, 0xed, 0xc1, 0x9b, 0xd6, 0x5a,
+ 0x7a, 0x98, 0xb4, 0xf2, 0xc8, 0xac, 0xc4, 0xfb, 0x3a, 0xe5, 0x41, 0x62,
+ 0x3f, 0x7a, 0x87, 0x8a, 0x19, 0x6b, 0xad, 0xe2, 0x77, 0xb1, 0xef, 0x83,
+ 0x93, 0x29, 0xe1, 0xde, 0x6b, 0xc7, 0xac, 0x53, 0x4b, 0x70, 0xdf, 0x73,
+ 0x1b, 0xaf, 0x23, 0xb5, 0x03, 0x25, 0x7d, 0xd7, 0xbb, 0x98, 0xaf, 0xe7,
+ 0xcb, 0xf8, 0x7e, 0x96, 0xed, 0xbe, 0x29, 0x68, 0x95, 0xc4, 0xf0, 0x3a,
+ 0x62, 0x7c, 0x92, 0x38, 0x79, 0x78, 0x5a, 0xe0, 0x0d, 0xd6, 0x89, 0x42,
+ 0xd2, 0xb0, 0x76, 0x2a, 0x46, 0xba, 0x47, 0x49, 0x64, 0x57, 0x96, 0x6b,
+ 0xe4, 0xdd, 0xac, 0x73, 0xb8, 0x43, 0xe0, 0xe7, 0x16, 0xb4, 0x00, 0xb1,
+ 0xfd, 0x6f, 0xac, 0x59, 0xff, 0x51, 0xae, 0x91, 0xc9, 0x42, 0x25, 0x42,
+ 0x2d, 0xd4, 0x7c, 0x62, 0xb9, 0x9b, 0x58, 0x3e, 0x44, 0x3e, 0x8c, 0xd0,
+ 0x13, 0x6c, 0x26, 0x96, 0x57, 0xb4, 0x19, 0xd9, 0x2e, 0xfa, 0x69, 0xcf,
+ 0xea, 0x08, 0x71, 0x1a, 0xa7, 0x87, 0x1d, 0x41, 0x07, 0xe7, 0x4a, 0x4f,
+ 0x1b, 0x91, 0x0e, 0xe2, 0x5f, 0x65, 0x9f, 0xd7, 0xd8, 0x67, 0xa1, 0x4e,
+ 0x7a, 0xed, 0x00, 0x5e, 0x60, 0x1f, 0x33, 0xe9, 0xb8, 0x3a, 0x21, 0xf1,
+ 0x3f, 0x86, 0x44, 0x46, 0xe2, 0xdf, 0x59, 0xd6, 0x4a, 0xdf, 0x2f, 0xf1,
+ 0x4f, 0x0c, 0xe6, 0x89, 0xc1, 0x12, 0x07, 0x06, 0x24, 0x07, 0x6a, 0xe8,
+ 0x2b, 0x4e, 0xd0, 0x57, 0x54, 0xd9, 0x51, 0xe2, 0x5f, 0xf2, 0xa1, 0xe4,
+ 0x2d, 0xba, 0xca, 0x1c, 0x58, 0xef, 0xce, 0x27, 0x35, 0x20, 0x88, 0xa6,
+ 0x49, 0x43, 0x57, 0x95, 0xff, 0x14, 0x4f, 0x98, 0xe6, 0xfc, 0x76, 0xfa,
+ 0x83, 0x2f, 0xdb, 0x62, 0xcc, 0x7b, 0x10, 0xf7, 0x9c, 0x08, 0xa9, 0x12,
+ 0xe7, 0xf5, 0x93, 0x41, 0x84, 0x26, 0x25, 0x0f, 0xb2, 0xe3, 0x11, 0x62,
+ 0xc4, 0xf2, 0xfc, 0x96, 0xf8, 0x8f, 0x12, 0x17, 0xaa, 0xd2, 0xcd, 0x31,
+ 0x6a, 0xa6, 0x74, 0xb4, 0x4e, 0x1a, 0x03, 0x27, 0x70, 0x55, 0xbc, 0x11,
+ 0x33, 0x33, 0x7b, 0x99, 0xff, 0x6d, 0xc9, 0x18, 0xf7, 0x4a, 0xc7, 0xdd,
+ 0x37, 0xc7, 0x70, 0x39, 0xe1, 0x6c, 0xb1, 0x82, 0x65, 0xaf, 0xad, 0x61,
+ 0x4b, 0x1e, 0xd8, 0x96, 0xa7, 0xd9, 0x35, 0x3d, 0xab, 0xfc, 0xb8, 0x86,
+ 0xc3, 0x44, 0x7f, 0xbf, 0xee, 0x30, 0xff, 0x01, 0xea, 0x7d, 0xe9, 0x9d,
+ 0x92, 0x07, 0xff, 0x79, 0xf9, 0x8c, 0xf9, 0x2b, 0x4f, 0xe9, 0xef, 0xdb,
+ 0xde, 0xc5, 0x33, 0xe7, 0x16, 0x62, 0xb0, 0x93, 0x18, 0xec, 0x61, 0x8e,
+ 0xb6, 0x5b, 0xe4, 0x36, 0xf3, 0x99, 0x55, 0x03, 0xf4, 0xd4, 0x4d, 0x7d,
+ 0xd5, 0xd4, 0xb4, 0x7d, 0xd4, 0xa7, 0x77, 0xcd, 0x4a, 0x7a, 0x70, 0x87,
+ 0xda, 0xd9, 0x41, 0xdd, 0xec, 0x52, 0x1e, 0x72, 0xb1, 0x95, 0x26, 0x8e,
+ 0x34, 0x25, 0x4d, 0x5f, 0xeb, 0x63, 0xed, 0x38, 0x14, 0x5e, 0xf4, 0xdf,
+ 0x32, 0x4e, 0xe9, 0xb9, 0x8d, 0xb8, 0x2c, 0xbf, 0xcf, 0xba, 0x3a, 0xb4,
+ 0x16, 0xaa, 0xbd, 0x56, 0x51, 0x6d, 0x79, 0xc6, 0x50, 0xf1, 0x03, 0xea,
+ 0xec, 0xc2, 0x26, 0x79, 0xd6, 0xe0, 0xba, 0xd8, 0x16, 0x31, 0x63, 0xd1,
+ 0x83, 0xc4, 0xd5, 0xab, 0xdf, 0x39, 0x7b, 0x94, 0xf0, 0x36, 0x9c, 0x57,
+ 0x6f, 0xfa, 0x68, 0xa9, 0x0f, 0x6b, 0x6f, 0xe2, 0x4d, 0xc3, 0x33, 0x2d,
+ 0x51, 0xe2, 0x51, 0x62, 0x4d, 0x43, 0xe1, 0x95, 0x4a, 0xbc, 0xf1, 0x4a,
+ 0x10, 0xaf, 0xbf, 0x22, 0xc4, 0x68, 0x12, 0x3c, 0xe1, 0x08, 0xf1, 0x50,
+ 0x72, 0x0d, 0x8e, 0xeb, 0xb1, 0xe8, 0x0b, 0xae, 0x8f, 0x75, 0xe8, 0x63,
+ 0x8d, 0x81, 0xb3, 0xb8, 0x21, 0x0a, 0x2e, 0xa7, 0x13, 0xe4, 0x5b, 0x09,
+ 0x8b, 0xae, 0xdf, 0xad, 0xd5, 0x70, 0x81, 0xf8, 0x0b, 0x11, 0x7f, 0xbf,
+ 0xa3, 0xe6, 0x5e, 0x2d, 0x6b, 0xee, 0xaa, 0x02, 0xf9, 0xd8, 0x16, 0x40,
+ 0x8f, 0x5c, 0x0b, 0x71, 0x38, 0x7c, 0x13, 0x87, 0xac, 0xbd, 0xdc, 0xf3,
+ 0xb3, 0x96, 0x11, 0xef, 0x24, 0x1e, 0x67, 0x2c, 0xc3, 0xe9, 0xa0, 0x9f,
+ 0x1d, 0x76, 0x31, 0x49, 0xed, 0x8d, 0x49, 0x5c, 0x12, 0x87, 0xcc, 0xc9,
+ 0x3e, 0xf6, 0x39, 0xcd, 0x3e, 0x63, 0x65, 0x3f, 0xfb, 0x1e, 0x12, 0x69,
+ 0xe9, 0x67, 0xa3, 0xc4, 0xe0, 0x3e, 0xd7, 0xcf, 0x4a, 0xff, 0x2a, 0xbd,
+ 0xab, 0x8c, 0xb3, 0xdd, 0x8d, 0xb3, 0xfb, 0x26, 0x0e, 0xa9, 0x61, 0xb5,
+ 0x12, 0x7f, 0x0f, 0x60, 0xec, 0xa5, 0x1a, 0x84, 0xcc, 0x3b, 0x71, 0x3e,
+ 0xf3, 0x80, 0x1a, 0x31, 0xa1, 0xd7, 0xdb, 0x25, 0x3c, 0x6e, 0x2e, 0xa6,
+ 0x90, 0xcf, 0xbf, 0x23, 0xf2, 0x61, 0xc3, 0x39, 0xeb, 0x7a, 0xd2, 0x01,
+ 0x7a, 0xc4, 0x1b, 0xc2, 0x13, 0x33, 0xce, 0x6d, 0xa1, 0x2f, 0x6b, 0xf2,
+ 0x96, 0xfc, 0xdd, 0x9a, 0xc2, 0xfb, 0x02, 0x75, 0xa5, 0x75, 0xaa, 0xf4,
+ 0x74, 0x23, 0xe4, 0xdc, 0xa8, 0x59, 0xf2, 0x77, 0xb1, 0xc2, 0xa7, 0xaa,
+ 0xd4, 0x73, 0x4f, 0x9b, 0x1c, 0x37, 0x4d, 0x0d, 0x59, 0x1c, 0xfb, 0x1b,
+ 0x5d, 0x1e, 0x21, 0x06, 0x87, 0xa5, 0xd7, 0xa2, 0x2f, 0xe1, 0x59, 0x7d,
+ 0x89, 0xa6, 0xee, 0xf6, 0xc2, 0x94, 0x6d, 0x8e, 0xf2, 0x10, 0xd7, 0xa0,
+ 0x99, 0x83, 0x4a, 0x9a, 0xb5, 0x79, 0x2f, 0xf1, 0xd5, 0xc3, 0x1a, 0x7c,
+ 0xd9, 0x6a, 0x26, 0x87, 0x05, 0xeb, 0xd0, 0x0d, 0xb1, 0xcf, 0x5c, 0x3c,
+ 0xd3, 0xc9, 0xf3, 0x5c, 0x9c, 0x71, 0x57, 0xb3, 0x76, 0xaf, 0x63, 0xbd,
+ 0xe6, 0x69, 0x91, 0x39, 0xfd, 0x32, 0x26, 0x1a, 0x57, 0xb5, 0x19, 0x03,
+ 0x1b, 0xbd, 0x01, 0xe4, 0x88, 0xf7, 0x57, 0x59, 0x83, 0xf2, 0xdc, 0xd3,
+ 0xc9, 0xa2, 0x91, 0xca, 0x62, 0x04, 0x1b, 0xb9, 0xa7, 0x3c, 0x03, 0x39,
+ 0xff, 0x18, 0x2b, 0x9d, 0x91, 0xb7, 0xb3, 0xb6, 0x8d, 0x97, 0xb9, 0x7d,
+ 0x05, 0x09, 0x4b, 0x72, 0x7b, 0x9e, 0xb5, 0x6d, 0xdc, 0xe5, 0xb6, 0x91,
+ 0x92, 0x7c, 0xae, 0x28, 0xd7, 0xb4, 0x4f, 0x20, 0x39, 0x7c, 0x6b, 0x3d,
+ 0x93, 0x78, 0x5e, 0xeb, 0x93, 0xde, 0x36, 0x9f, 0x97, 0x35, 0x49, 0xd6,
+ 0xa2, 0xc5, 0xba, 0xa4, 0xc9, 0xfb, 0x84, 0x4c, 0xe3, 0xc4, 0x1e, 0xe1,
+ 0x29, 0xdd, 0x49, 0x9c, 0xfb, 0xd0, 0x1b, 0x4c, 0xa5, 0xee, 0x43, 0x26,
+ 0x32, 0xa7, 0x61, 0x53, 0xbe, 0xa1, 0x2f, 0x60, 0x83, 0xef, 0x28, 0xb0,
+ 0xfe, 0x44, 0x43, 0xe6, 0x96, 0x3b, 0x89, 0x8f, 0x73, 0x9a, 0x16, 0x9a,
+ 0x58, 0x2e, 0xdf, 0xc1, 0x67, 0xb9, 0xdb, 0xde, 0x49, 0xa4, 0x7f, 0xdf,
+ 0x9d, 0xc4, 0x0b, 0xe4, 0xc7, 0x58, 0xe9, 0x4e, 0xc2, 0xf9, 0x5e, 0x8b,
+ 0x17, 0x33, 0x61, 0xec, 0xfe, 0xa8, 0x5d, 0xc5, 0xe5, 0x9c, 0x11, 0x39,
+ 0x8e, 0xdd, 0xe8, 0x77, 0xef, 0x1f, 0x90, 0xf5, 0xdb, 0xbb, 0xf0, 0x4f,
+ 0xed, 0xf2, 0xfe, 0x21, 0x25, 0xd7, 0x38, 0xce, 0xe5, 0x43, 0xa3, 0xde,
+ 0xac, 0x67, 0x2d, 0xd8, 0xb1, 0x46, 0xc1, 0x43, 0xc9, 0x3b, 0x5d, 0x6c,
+ 0x8f, 0x17, 0x8d, 0x74, 0x94, 0xcf, 0xee, 0x99, 0x90, 0x35, 0xf2, 0x71,
+ 0x9e, 0x17, 0xa1, 0x35, 0xda, 0xbd, 0xaa, 0xc8, 0x37, 0x45, 0xae, 0x28,
+ 0x86, 0x73, 0x18, 0xf2, 0x8e, 0x20, 0x71, 0xce, 0xab, 0x18, 0xf3, 0x1f,
+ 0x7a, 0x8d, 0x54, 0xbd, 0x8b, 0x99, 0xc7, 0x79, 0x76, 0x93, 0x7f, 0x7b,
+ 0xe5, 0xb9, 0x0f, 0x1b, 0x39, 0xe6, 0x07, 0x6b, 0xe4, 0x59, 0xf4, 0x73,
+ 0x91, 0x5d, 0x66, 0x38, 0x0b, 0x8a, 0xc6, 0xdc, 0x80, 0xfa, 0x24, 0x35,
+ 0xfc, 0x71, 0x6a, 0xb8, 0xf4, 0x2c, 0xbd, 0xf4, 0x2c, 0x4d, 0xf3, 0x71,
+ 0xaf, 0x91, 0xb9, 0x4e, 0xbd, 0xe3, 0x98, 0x7d, 0xbd, 0x8a, 0xd1, 0x7b,
+ 0x82, 0xfa, 0xbf, 0x53, 0x29, 0x8d, 0xb9, 0xb2, 0x3c, 0xe6, 0xdd, 0x05,
+ 0x4d, 0xe9, 0xcc, 0x83, 0xba, 0x83, 0xe8, 0x36, 0x8b, 0xda, 0x51, 0xac,
+ 0x24, 0xc7, 0x4c, 0xb9, 0x66, 0xc6, 0xd6, 0xca, 0xd8, 0x14, 0x5c, 0x69,
+ 0x91, 0xef, 0xb6, 0xca, 0x38, 0x9c, 0x2a, 0x3b, 0x45, 0xed, 0x7d, 0xc5,
+ 0x57, 0xd6, 0x2f, 0xcf, 0x16, 0x6b, 0x19, 0x9c, 0x30, 0x42, 0x3e, 0xb3,
+ 0x0e, 0xa3, 0xb4, 0x81, 0x41, 0xb3, 0x19, 0x39, 0xdd, 0x8f, 0x2d, 0xd6,
+ 0x17, 0x82, 0x3a, 0xc9, 0xf7, 0x81, 0xa7, 0x5e, 0xe2, 0x19, 0xde, 0xbc,
+ 0x86, 0x58, 0xf2, 0x39, 0x1c, 0xd3, 0x77, 0xd1, 0x0f, 0x6e, 0xc5, 0xeb,
+ 0xae, 0x9e, 0xd8, 0xc4, 0xb3, 0x42, 0x0c, 0xd9, 0xb2, 0xd6, 0xdd, 0x32,
+ 0xb6, 0xbc, 0x93, 0xb8, 0x24, 0xb2, 0xa5, 0x31, 0x9c, 0x6d, 0x56, 0x86,
+ 0x71, 0x7d, 0xa3, 0xbb, 0x3b, 0xa8, 0xbb, 0x15, 0xa6, 0xe7, 0xae, 0x4a,
+ 0xea, 0xee, 0x56, 0xeb, 0xcf, 0xf1, 0x14, 0x39, 0x5e, 0x65, 0x7e, 0x26,
+ 0x9e, 0x0e, 0xcb, 0x31, 0xa9, 0xaf, 0x35, 0x4b, 0xc7, 0xff, 0x90, 0x63,
+ 0xca, 0x39, 0x64, 0x3d, 0x3c, 0x2f, 0x0e, 0xd5, 0xca, 0x31, 0x07, 0x95,
+ 0x8d, 0xe4, 0xd4, 0x3c, 0x4b, 0xef, 0x0f, 0xc8, 0xa7, 0x05, 0xe6, 0xa7,
+ 0xf1, 0x36, 0x7c, 0x6a, 0x24, 0x9f, 0x9e, 0x58, 0xc2, 0xa7, 0x83, 0x79,
+ 0xe9, 0xbd, 0x14, 0xb4, 0xb4, 0xfd, 0x29, 0x75, 0x45, 0x08, 0x7f, 0xdb,
+ 0x0d, 0x71, 0xc6, 0xf5, 0xbe, 0xd2, 0xef, 0xa6, 0x95, 0xee, 0x59, 0xa9,
+ 0x4f, 0xd5, 0x08, 0x92, 0x4f, 0x1b, 0xc8, 0xa7, 0x7e, 0xf2, 0xe9, 0x69,
+ 0x53, 0x34, 0xee, 0x48, 0x1a, 0xa9, 0x79, 0xfa, 0x9a, 0x75, 0xe4, 0xd4,
+ 0x3b, 0xe4, 0xd4, 0x48, 0xb1, 0xa4, 0x53, 0xfb, 0xb8, 0xee, 0xfb, 0xa9,
+ 0x53, 0xeb, 0x8a, 0x52, 0xdb, 0x1c, 0xe2, 0x3f, 0x80, 0xcf, 0xc9, 0xa9,
+ 0xd9, 0xa4, 0xab, 0x53, 0xd6, 0xef, 0x90, 0xd8, 0x75, 0x5a, 0xf2, 0x89,
+ 0x3a, 0x95, 0x2f, 0x36, 0x59, 0xa7, 0xb9, 0xa6, 0xf1, 0xbc, 0x71, 0xbd,
+ 0x87, 0x9c, 0xf2, 0xb5, 0x1b, 0xe7, 0x2e, 0x13, 0xbb, 0x81, 0x18, 0xf4,
+ 0x88, 0x2d, 0xd7, 0xc4, 0x1a, 0xcb, 0x3a, 0x79, 0x90, 0xf8, 0xef, 0xa1,
+ 0x66, 0xf4, 0x16, 0x6d, 0xec, 0x2d, 0x2e, 0xdd, 0x53, 0xd6, 0xa1, 0xdb,
+ 0xee, 0xcb, 0xb8, 0xff, 0xf6, 0xed, 0xac, 0x57, 0xb7, 0x6d, 0x97, 0x7c,
+ 0x5d, 0xe6, 0x97, 0x7c, 0x1d, 0xce, 0xbf, 0xa6, 0xde, 0xfe, 0x1d, 0x79,
+ 0xa7, 0x26, 0xc4, 0x51, 0x4b, 0xde, 0x49, 0x48, 0xdf, 0xa3, 0x60, 0xc8,
+ 0x92, 0xf7, 0x6a, 0x1d, 0x51, 0x15, 0x46, 0xe4, 0xfb, 0xf8, 0x4a, 0x64,
+ 0xc3, 0x4e, 0xdc, 0xe7, 0xd6, 0x48, 0x43, 0xef, 0x63, 0xad, 0x9b, 0x2f,
+ 0x9f, 0xfd, 0x66, 0x78, 0x3e, 0x7b, 0x87, 0x75, 0xea, 0x28, 0xcf, 0x79,
+ 0x43, 0x85, 0xaf, 0xc4, 0x7c, 0x58, 0xc5, 0x88, 0x79, 0xf3, 0x8e, 0xd2,
+ 0xd5, 0xb1, 0xc3, 0x7c, 0x36, 0x56, 0x58, 0xac, 0x51, 0xd4, 0x4c, 0x53,
+ 0x88, 0xad, 0xe6, 0x7f, 0x8b, 0x2d, 0xdf, 0x7a, 0x57, 0x88, 0x49, 0xc6,
+ 0x70, 0xc1, 0xc2, 0x6e, 0x1f, 0x62, 0x7d, 0xd7, 0x59, 0xd7, 0x3f, 0x58,
+ 0x63, 0x64, 0x0a, 0x4a, 0xa2, 0x77, 0x83, 0x22, 0xbd, 0x9e, 0xa7, 0xab,
+ 0x82, 0xef, 0xb4, 0xd0, 0x1b, 0x5d, 0x61, 0x06, 0xfd, 0xfc, 0x7e, 0xc6,
+ 0x32, 0x22, 0x47, 0xf8, 0x77, 0x4b, 0x4a, 0x8e, 0x21, 0x44, 0x87, 0x25,
+ 0xef, 0xbb, 0x46, 0xd4, 0xdc, 0x44, 0x56, 0x54, 0x99, 0x17, 0xa8, 0x4d,
+ 0x46, 0x66, 0x44, 0x91, 0x3e, 0x3b, 0x0a, 0x57, 0x67, 0xf9, 0x4c, 0x9b,
+ 0x88, 0xe0, 0xef, 0x5d, 0xff, 0x1c, 0xa5, 0x66, 0x35, 0xe0, 0x1f, 0x5c,
+ 0xdd, 0x52, 0xb1, 0xed, 0x25, 0x23, 0xa5, 0x2a, 0x7b, 0x70, 0xc9, 0x32,
+ 0xf4, 0x9f, 0x32, 0x6e, 0x6a, 0xcd, 0x8b, 0x9d, 0x3c, 0x3f, 0x71, 0x8e,
+ 0x6c, 0x9f, 0xb7, 0x56, 0xd1, 0x58, 0x3b, 0x7e, 0xdc, 0x22, 0x6b, 0xf7,
+ 0x2e, 0xf4, 0x34, 0xef, 0xe4, 0x47, 0x45, 0xdd, 0x94, 0xaa, 0x6c, 0xa2,
+ 0x27, 0x09, 0x4d, 0x85, 0xb0, 0x7d, 0xb5, 0x10, 0xab, 0x56, 0x3b, 0xf8,
+ 0x3c, 0xd9, 0x14, 0x3f, 0xcb, 0x1a, 0x74, 0xa8, 0xd6, 0x48, 0x03, 0xbf,
+ 0xc0, 0x66, 0x7a, 0xd9, 0x54, 0x5b, 0x0e, 0xb8, 0x53, 0xae, 0xf1, 0x17,
+ 0xe8, 0x94, 0x1e, 0xd8, 0x0a, 0x49, 0xbf, 0xe5, 0xe2, 0xb7, 0x74, 0xaf,
+ 0xc4, 0xd4, 0x1d, 0xc8, 0x8a, 0x4a, 0xd3, 0xe8, 0x9b, 0x65, 0xbd, 0xfd,
+ 0x20, 0xb6, 0x5c, 0x7f, 0x78, 0x56, 0x7a, 0x60, 0x33, 0xba, 0x5e, 0x11,
+ 0xcc, 0xc5, 0xf3, 0xcc, 0x45, 0xcc, 0x09, 0xd2, 0x32, 0xf0, 0xac, 0xe5,
+ 0x84, 0x94, 0x41, 0xe5, 0x51, 0xf2, 0xa1, 0xcf, 0x5f, 0x49, 0x0f, 0xe1,
+ 0xd0, 0x3f, 0x78, 0x50, 0x7d, 0x40, 0x7a, 0x8a, 0x00, 0xb5, 0xa6, 0xa9,
+ 0x37, 0xc8, 0xfc, 0xec, 0x48, 0x4a, 0xff, 0x41, 0xac, 0x1f, 0xb8, 0x21,
+ 0x3a, 0xe9, 0x71, 0x3b, 0xcb, 0x1e, 0xf7, 0x89, 0xe9, 0x34, 0x3d, 0xb0,
+ 0xa6, 0xc8, 0x3b, 0xb6, 0x54, 0x1b, 0x0f, 0xa4, 0x8f, 0x4a, 0x1f, 0x22,
+ 0xd7, 0xa0, 0xe3, 0x6a, 0x52, 0x62, 0x57, 0xc7, 0x70, 0xbb, 0x11, 0xc9,
+ 0x42, 0xde, 0xe9, 0xdc, 0xea, 0x2f, 0xa0, 0xa7, 0xbf, 0xe3, 0x39, 0xa0,
+ 0x6f, 0x62, 0x2c, 0x86, 0x5f, 0x88, 0xba, 0xa4, 0x17, 0x7d, 0xee, 0x59,
+ 0x2e, 0xa2, 0xa7, 0xc9, 0xfb, 0x73, 0xf4, 0x09, 0x5e, 0x9e, 0x99, 0xf7,
+ 0x10, 0x4b, 0x5f, 0xb6, 0x0c, 0xbd, 0x5a, 0x8f, 0xec, 0x78, 0x1d, 0xcf,
+ 0xa8, 0xf7, 0x53, 0x57, 0x2f, 0xe4, 0x1e, 0x65, 0x3d, 0xf7, 0xb4, 0x47,
+ 0x78, 0x06, 0x68, 0x9c, 0xca, 0x8a, 0x7a, 0xfa, 0x41, 0x9e, 0x97, 0x51,
+ 0xdb, 0x16, 0xa7, 0xdf, 0x5e, 0xdc, 0x2b, 0x0f, 0x7e, 0x68, 0x99, 0x70,
+ 0xdc, 0xdf, 0x41, 0xbd, 0x7b, 0x9a, 0xe7, 0x68, 0x73, 0xb9, 0xde, 0x51,
+ 0x8a, 0x4b, 0xad, 0xb0, 0x2d, 0xb4, 0xdc, 0x0b, 0xfd, 0xc1, 0xdb, 0xc4,
+ 0xb4, 0x4e, 0x7a, 0x1f, 0x5f, 0xa9, 0xdf, 0x9f, 0x4d, 0x37, 0xe8, 0x8f,
+ 0xb0, 0xde, 0xcd, 0x13, 0x2b, 0x4f, 0xac, 0xb6, 0x64, 0x2c, 0xf3, 0x32,
+ 0x16, 0xfa, 0x4b, 0xe7, 0x7e, 0x0f, 0x7d, 0x49, 0x12, 0x08, 0xcd, 0xfd,
+ 0x35, 0x79, 0xe5, 0x69, 0x0d, 0x21, 0xbb, 0x8b, 0x31, 0xbe, 0xfa, 0xaf,
+ 0xdc, 0x9a, 0xfe, 0x49, 0xf4, 0x7b, 0xd8, 0x67, 0xc2, 0x02, 0x9e, 0x39,
+ 0x01, 0x3c, 0x3d, 0x19, 0xa3, 0x2f, 0xa7, 0x8f, 0x3c, 0xa1, 0xe1, 0xfb,
+ 0xd3, 0x95, 0xf8, 0xd1, 0x74, 0x10, 0x3b, 0xa6, 0xdd, 0xbb, 0xae, 0x0d,
+ 0x75, 0x7c, 0xaf, 0x83, 0x67, 0xbb, 0x59, 0x6b, 0x35, 0x3e, 0xa2, 0x87,
+ 0x5a, 0xa1, 0x78, 0x10, 0x39, 0x00, 0x5d, 0x27, 0x6e, 0x6a, 0x5b, 0x7e,
+ 0x44, 0x2e, 0x0b, 0x61, 0xae, 0x96, 0x3a, 0xf9, 0xbc, 0xfb, 0x7d, 0x84,
+ 0xfe, 0x31, 0x23, 0x31, 0x98, 0x27, 0x06, 0xf3, 0xc4, 0xe4, 0x4d, 0x4f,
+ 0x2d, 0xb1, 0x1c, 0xa7, 0x8f, 0x7e, 0x4e, 0x94, 0xb0, 0xf1, 0xb5, 0x38,
+ 0x6a, 0x9e, 0x24, 0x7f, 0x55, 0x6a, 0x28, 0xf0, 0xcf, 0xb9, 0x88, 0xbe,
+ 0xa9, 0x28, 0xf3, 0xff, 0xb7, 0xe5, 0xfc, 0x9f, 0xf1, 0x97, 0xf4, 0xc2,
+ 0x70, 0x66, 0xd1, 0x80, 0xc9, 0x7c, 0x83, 0xbe, 0x21, 0x3f, 0x34, 0xa8,
+ 0x21, 0x1b, 0x0d, 0xc1, 0x18, 0x98, 0x84, 0xa7, 0x35, 0x08, 0xb9, 0x76,
+ 0xa0, 0xe0, 0xae, 0x51, 0x88, 0x31, 0xea, 0x9b, 0xcc, 0xc1, 0xbf, 0xe7,
+ 0xd0, 0xea, 0x61, 0x3e, 0x1c, 0xc8, 0xb3, 0x35, 0xf0, 0x69, 0x41, 0xde,
+ 0x7d, 0xc6, 0xd2, 0xdd, 0xf8, 0xc2, 0x1d, 0xf3, 0x93, 0x42, 0x0a, 0xfb,
+ 0xf3, 0x1f, 0x88, 0xfd, 0xe1, 0x92, 0xc6, 0xa7, 0x79, 0x3e, 0x0a, 0x1d,
+ 0x28, 0x7b, 0x21, 0x72, 0xb8, 0x9a, 0xeb, 0xbd, 0x9a, 0x74, 0xbd, 0x3f,
+ 0x6b, 0xe4, 0x80, 0x7a, 0xd4, 0x64, 0xb1, 0xab, 0xb9, 0x21, 0xc6, 0x62,
+ 0x89, 0x40, 0x29, 0xa6, 0x84, 0x7e, 0x04, 0x15, 0xc4, 0xae, 0x3c, 0x23,
+ 0x49, 0xfd, 0x90, 0xbf, 0x79, 0x3e, 0x51, 0x9d, 0x88, 0x97, 0xeb, 0x72,
+ 0x1e, 0x93, 0x6d, 0x81, 0xb2, 0x5f, 0x5d, 0xf4, 0x22, 0x1d, 0x7c, 0x26,
+ 0xbd, 0xc8, 0x57, 0xa2, 0x2f, 0xdc, 0x71, 0x53, 0x73, 0xb2, 0x7c, 0x63,
+ 0x34, 0x2f, 0xef, 0xb4, 0x5a, 0xe8, 0x88, 0x15, 0x9c, 0x62, 0xe4, 0x47,
+ 0x5a, 0x63, 0xfa, 0x30, 0xc7, 0x73, 0x74, 0x9d, 0x5c, 0xde, 0x43, 0xbf,
+ 0xcc, 0x77, 0x8a, 0x2d, 0xec, 0x23, 0xb5, 0xec, 0x2f, 0xb8, 0xd6, 0x2f,
+ 0x9a, 0x25, 0xb6, 0x87, 0xf3, 0x6f, 0x79, 0x54, 0x53, 0xae, 0x33, 0x91,
+ 0x1a, 0x66, 0x3c, 0x0b, 0xba, 0xf4, 0xd6, 0x0e, 0xb5, 0x2d, 0xe1, 0xf6,
+ 0xcf, 0xaa, 0x32, 0x0e, 0x37, 0x1e, 0xb6, 0x49, 0xcd, 0x32, 0x32, 0xa7,
+ 0x90, 0x70, 0xfa, 0xa5, 0x39, 0x58, 0x26, 0x63, 0x68, 0x8a, 0xf4, 0x33,
+ 0x9e, 0x43, 0x61, 0x57, 0x0f, 0xf9, 0x8c, 0xf3, 0xe5, 0x3d, 0x1b, 0x2a,
+ 0x21, 0xb0, 0x22, 0xe9, 0x9e, 0xf9, 0xcb, 0xff, 0x5f, 0x43, 0xa5, 0x0f,
+ 0x91, 0x58, 0xfc, 0x5f, 0x69, 0xd7, 0x8a, 0xc0, 0xa8, 0x1a, 0x00, 0x00,
+ 0x00 };
static const u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
static struct fw_info bnx2_tpat_fw_06 = {
- /* Firmware version: 4.0.5 */
+ /* Firmware version: 4.4.22 */
.ver_major = 0x4,
- .ver_minor = 0x0,
- .ver_fix = 0x5,
+ .ver_minor = 0x4,
+ .ver_fix = 0x16,
- .start_addr = 0x08000888,
+ .start_addr = 0x08000488,
- .text_addr = 0x08000800,
- .text_len = 0x1a90,
+ .text_addr = 0x08000400,
+ .text_len = 0x1aa4,
.text_index = 0x0,
.gz_text = bnx2_TPAT_b06FwText,
.gz_text_len = sizeof(bnx2_TPAT_b06FwText),
@@ -3686,11 +3639,11 @@ static struct fw_info bnx2_tpat_fw_06 = {
.data_index = 0x0,
.data = bnx2_TPAT_b06FwData,
- .sbss_addr = 0x080022c0,
+ .sbss_addr = 0x08001ec0,
.sbss_len = 0x44,
.sbss_index = 0x0,
- .bss_addr = 0x08002304,
+ .bss_addr = 0x08001f04,
.bss_len = 0x450,
.bss_index = 0x0,
@@ -3717,862 +3670,862 @@ static const struct cpu_reg cpu_reg_tpat = {
};
static u8 bnx2_TXP_b06FwText[] = {
- 0xad, 0x7b, 0x7f, 0x70, 0x9b, 0x75, 0x7a, 0xe7, 0xe7, 0xd5, 0x0f, 0x5b,
- 0xb2, 0x65, 0x59, 0x0e, 0x4a, 0x90, 0x77, 0xbd, 0x8d, 0x5e, 0xf4, 0xca,
- 0x16, 0xd8, 0x49, 0x5e, 0x25, 0xce, 0xc6, 0x59, 0xab, 0x44, 0x75, 0x1c,
- 0xdb, 0x71, 0x1c, 0x30, 0xc1, 0xdd, 0x3a, 0x3d, 0xae, 0xf1, 0x25, 0x26,
- 0x31, 0x10, 0xc0, 0xe9, 0xa6, 0x7b, 0x62, 0x8f, 0xd6, 0xc2, 0x76, 0x82,
- 0x43, 0x64, 0xbf, 0xce, 0x2a, 0x59, 0x87, 0x4e, 0x67, 0xd6, 0x60, 0x07,
- 0x07, 0x56, 0x8e, 0x60, 0xdb, 0x6b, 0xbb, 0x73, 0xbb, 0x83, 0x8e, 0x40,
- 0xf0, 0x72, 0x01, 0xb6, 0xfd, 0xa3, 0x47, 0x6f, 0xee, 0xda, 0xcc, 0x02,
- 0x59, 0xa0, 0x4b, 0xa0, 0x3b, 0x7b, 0x53, 0x67, 0x0b, 0xbc, 0xf7, 0x79,
- 0xde, 0x57, 0x4a, 0xb2, 0x94, 0x4e, 0x67, 0x3a, 0xe7, 0x19, 0x8f, 0xac,
- 0xf7, 0xc7, 0xf3, 0x7d, 0x7e, 0x3f, 0x9f, 0xe7, 0xf9, 0x7e, 0x5d, 0x0f,
- 0x54, 0xa0, 0xf8, 0x53, 0xc5, 0xdf, 0xe6, 0xe1, 0xd4, 0xe1, 0x8d, 0x6b,
- 0xf5, 0xb5, 0xd6, 0x05, 0x37, 0x5c, 0x72, 0xf3, 0xab, 0x0a, 0x30, 0xf0,
- 0x01, 0xfe, 0x5d, 0x3f, 0x5f, 0xf9, 0xf7, 0xbd, 0x66, 0xfd, 0x38, 0x81,
- 0x40, 0x89, 0x2f, 0xf9, 0x85, 0xc7, 0x91, 0x40, 0x6b, 0x9b, 0x06, 0x8f,
- 0x33, 0xf1, 0x67, 0x89, 0x7d, 0x1a, 0x90, 0xcc, 0x35, 0x86, 0xb7, 0xe2,
- 0x53, 0x33, 0x1d, 0x74, 0x41, 0xae, 0x7f, 0x25, 0xf1, 0xc9, 0xc8, 0x8f,
- 0x36, 0xa9, 0x1f, 0xcf, 0x3a, 0xe1, 0x09, 0x24, 0x4e, 0x23, 0x50, 0x0f,
- 0x4f, 0x1d, 0xdf, 0xf9, 0x93, 0x86, 0x6a, 0x27, 0xfc, 0x25, 0x5a, 0x2d,
- 0x18, 0x33, 0x90, 0xf6, 0x24, 0x86, 0x51, 0xbe, 0x11, 0x78, 0x37, 0x13,
- 0xd5, 0xc7, 0x80, 0x69, 0x47, 0x22, 0x1a, 0x7e, 0x09, 0x3a, 0x8e, 0xe4,
- 0xc3, 0x68, 0xe7, 0xef, 0x76, 0xe3, 0x33, 0x33, 0xec, 0x46, 0xda, 0xc9,
- 0xe7, 0xf6, 0x36, 0x03, 0xdb, 0x32, 0x3a, 0x8e, 0x1a, 0xf0, 0xd4, 0x26,
- 0x1e, 0xc5, 0x66, 0x7e, 0xfa, 0x13, 0x29, 0xbc, 0x31, 0x19, 0x09, 0x3f,
- 0x03, 0xb5, 0x5f, 0x73, 0xaa, 0x29, 0xa0, 0x71, 0x68, 0x50, 0x51, 0x07,
- 0xde, 0x54, 0xd4, 0xde, 0x49, 0x05, 0x1e, 0x85, 0xcf, 0x35, 0xe6, 0xe4,
- 0x33, 0x85, 0xdb, 0x72, 0x1e, 0x5c, 0x72, 0xca, 0xfa, 0xbf, 0x49, 0x7d,
- 0x2b, 0x70, 0x69, 0x2d, 0x18, 0x27, 0x0f, 0xee, 0x84, 0x82, 0xa7, 0x9b,
- 0xa3, 0xa1, 0x51, 0xc8, 0xfd, 0x30, 0xb6, 0xe6, 0xe5, 0x53, 0xa5, 0xd4,
- 0xa6, 0x39, 0xae, 0x9b, 0xe6, 0x19, 0xbd, 0x1c, 0xe9, 0x80, 0x1a, 0x02,
- 0x14, 0x8c, 0xea, 0x0e, 0x24, 0x03, 0x6d, 0x61, 0x17, 0xd4, 0xd0, 0xbd,
- 0xf8, 0x67, 0xca, 0x9c, 0x8c, 0xb9, 0x61, 0x3f, 0x3f, 0x80, 0x72, 0x14,
- 0x02, 0xb6, 0xd6, 0x9e, 0xce, 0x98, 0xe6, 0x05, 0xcd, 0x85, 0x33, 0xd4,
- 0xcf, 0x68, 0xee, 0x9f, 0xcd, 0x02, 0x75, 0x33, 0xae, 0x95, 0xd6, 0xf7,
- 0x60, 0x36, 0x60, 0x9a, 0x73, 0xbc, 0x77, 0x34, 0x57, 0xd2, 0xb3, 0x69,
- 0x3a, 0x34, 0xd3, 0xdc, 0xa7, 0xfd, 0xca, 0xdc, 0xfb, 0x6b, 0xcf, 0x9a,
- 0xe6, 0x13, 0xfa, 0x4d, 0x38, 0x9b, 0x6d, 0x57, 0xba, 0x17, 0x56, 0xf9,
- 0xb7, 0xcf, 0x98, 0xb8, 0xa0, 0x23, 0xe0, 0x48, 0x74, 0x28, 0xdb, 0x17,
- 0xba, 0x94, 0x6d, 0xf9, 0x5d, 0x4a, 0xc7, 0xdc, 0xef, 0x2a, 0x5d, 0x0b,
- 0x03, 0x4a, 0x67, 0x3e, 0x84, 0x79, 0x23, 0x88, 0x39, 0xa3, 0x5f, 0x69,
- 0x5f, 0xe8, 0x53, 0x6c, 0x39, 0x52, 0x4a, 0x5b, 0xbe, 0x44, 0xeb, 0xba,
- 0x1e, 0xb7, 0x67, 0x12, 0x98, 0x30, 0xca, 0xb9, 0xce, 0xb2, 0xf9, 0xa3,
- 0x86, 0x65, 0xca, 0xa9, 0xe3, 0x58, 0xfe, 0x09, 0xec, 0x9c, 0x31, 0xcd,
- 0x5c, 0x1c, 0xc8, 0xe5, 0x81, 0xef, 0x19, 0x91, 0xde, 0x21, 0xc5, 0x34,
- 0x3b, 0xa3, 0xe6, 0xea, 0xcb, 0x7a, 0x63, 0xec, 0x65, 0xfc, 0x93, 0x39,
- 0x1b, 0x44, 0xda, 0x47, 0x1a, 0xc7, 0x69, 0xb3, 0xfb, 0x27, 0xe1, 0x29,
- 0x4f, 0x8c, 0xe3, 0x67, 0x19, 0x78, 0xca, 0x12, 0x69, 0x5c, 0xc8, 0x8c,
- 0x06, 0x3c, 0x88, 0x84, 0xb6, 0x2b, 0xe9, 0x94, 0x03, 0xea, 0xf0, 0xdb,
- 0x50, 0xc3, 0xb4, 0xc7, 0xd2, 0x79, 0x45, 0x2d, 0xbc, 0x0c, 0x35, 0xf9,
- 0x2b, 0x45, 0xed, 0xaa, 0x75, 0x22, 0xe9, 0x88, 0x7a, 0xf0, 0xa3, 0x06,
- 0xb1, 0xc9, 0x38, 0xd6, 0x5a, 0xb6, 0x49, 0xe3, 0xd6, 0x6b, 0xb6, 0x49,
- 0x60, 0x94, 0x7c, 0x1d, 0x25, 0x5f, 0xaf, 0xe8, 0x6a, 0xe8, 0x69, 0x98,
- 0xab, 0x07, 0x75, 0xb9, 0x97, 0xc0, 0x78, 0xde, 0x0c, 0xfb, 0x13, 0x97,
- 0xc8, 0x2f, 0xd2, 0x5f, 0x4a, 0x78, 0xd2, 0xd5, 0x89, 0x4f, 0xcd, 0xd7,
- 0x37, 0x86, 0xf0, 0x62, 0x3e, 0x88, 0x17, 0xf2, 0x01, 0x3c, 0x9f, 0x6f,
- 0x87, 0x91, 0x87, 0x7f, 0x67, 0xfe, 0x8b, 0xfc, 0xd8, 0x84, 0x8f, 0xcf,
- 0x93, 0x6f, 0xff, 0x8e, 0xbc, 0x6b, 0xa0, 0x2c, 0x81, 0xde, 0x1f, 0x67,
- 0x46, 0xcc, 0x0a, 0x0d, 0x03, 0x35, 0x09, 0x2d, 0x79, 0x9b, 0xe2, 0x6b,
- 0xa1, 0x1f, 0xf6, 0xbe, 0x9a, 0x6b, 0x71, 0x69, 0x53, 0x5e, 0xb8, 0xa9,
- 0xff, 0x6d, 0x79, 0xd3, 0x1c, 0xd3, 0x0f, 0xad, 0xdb, 0xdb, 0xf2, 0xa7,
- 0x85, 0x5e, 0xad, 0x07, 0xe9, 0xfc, 0x20, 0xe0, 0x4f, 0xf0, 0x93, 0xa1,
- 0xb8, 0xab, 0xa9, 0x3d, 0x7c, 0xee, 0x41, 0x97, 0xed, 0xcf, 0xe4, 0x81,
- 0x7a, 0x7f, 0xc1, 0x20, 0x0f, 0xc6, 0xb4, 0x1f, 0x15, 0x61, 0xca, 0xf7,
- 0x13, 0xf2, 0x19, 0xc3, 0xf7, 0xf3, 0x1a, 0x79, 0x6b, 0x22, 0x8f, 0x61,
- 0xf2, 0xe7, 0xc1, 0xde, 0xac, 0x3a, 0x9d, 0x86, 0x3a, 0x31, 0x8b, 0x35,
- 0x48, 0x06, 0x03, 0xf4, 0xc1, 0x3f, 0x86, 0x4d, 0xa3, 0x07, 0x53, 0x06,
- 0xd6, 0x07, 0x12, 0xb4, 0x6f, 0x1c, 0x8f, 0x96, 0x21, 0x3a, 0xf0, 0xb1,
- 0xa2, 0xe0, 0xf5, 0x68, 0x0f, 0x26, 0x29, 0x4f, 0x4f, 0xce, 0x8b, 0x07,
- 0xb2, 0x15, 0xb8, 0x2f, 0x6b, 0xe2, 0xfe, 0x38, 0x12, 0x15, 0x94, 0x27,
- 0x16, 0x8f, 0x86, 0xdf, 0x83, 0x0b, 0xed, 0xb9, 0x1e, 0xc6, 0xd2, 0x56,
- 0x24, 0xcb, 0x3c, 0xd8, 0x9a, 0xf3, 0x31, 0x1e, 0x93, 0x38, 0x3d, 0xe3,
- 0x81, 0x7b, 0x83, 0x03, 0xb3, 0xc1, 0x32, 0xc4, 0xea, 0x1d, 0xfc, 0x0d,
- 0xfa, 0xdb, 0x66, 0xea, 0xfc, 0xdb, 0x0c, 0x17, 0x0e, 0x18, 0x0e, 0x8c,
- 0x64, 0x4d, 0xb3, 0x5d, 0x37, 0x71, 0x75, 0x43, 0x00, 0x3f, 0xa0, 0xfe,
- 0x0e, 0x19, 0x21, 0x9c, 0xcd, 0x3f, 0x4e, 0x5e, 0x82, 0x36, 0xbf, 0x06,
- 0x79, 0x37, 0xc8, 0xbb, 0x41, 0xbe, 0x0d, 0xe1, 0xf3, 0x3c, 0x63, 0x46,
- 0xa7, 0x5c, 0x5e, 0xf2, 0x50, 0x89, 0x21, 0xf2, 0x11, 0x89, 0x9b, 0x70,
- 0xc4, 0xd5, 0xf4, 0x5e, 0x26, 0xaf, 0xd5, 0xf5, 0xa6, 0xf9, 0xf1, 0x06,
- 0x91, 0x85, 0x36, 0x77, 0xf4, 0x48, 0x8c, 0xfe, 0x56, 0x15, 0xe3, 0xea,
- 0x6f, 0xa9, 0xb7, 0x27, 0xf3, 0x5e, 0xa4, 0xb2, 0x96, 0xdf, 0x1e, 0x2e,
- 0x23, 0xdf, 0xc2, 0x57, 0x5e, 0x8b, 0x32, 0x46, 0xa3, 0xfd, 0x8c, 0x51,
- 0xec, 0x20, 0xcf, 0xf7, 0x1b, 0xd1, 0x96, 0x5d, 0x8a, 0x0b, 0x9d, 0xb9,
- 0xa0, 0xbf, 0xfd, 0x06, 0x3e, 0x29, 0xaf, 0xc4, 0x20, 0x65, 0x0d, 0x90,
- 0xbf, 0x20, 0xf6, 0x91, 0xcf, 0x17, 0x8a, 0x7c, 0xce, 0xe5, 0x65, 0xad,
- 0xcf, 0xf3, 0x5a, 0xe2, 0x13, 0xe9, 0x15, 0x89, 0xa0, 0x82, 0x0a, 0x1f,
- 0x76, 0xe5, 0xde, 0xa2, 0x2d, 0xea, 0xf0, 0xa7, 0xb4, 0xc1, 0x8b, 0x8c,
- 0x91, 0xef, 0x5f, 0xf3, 0x17, 0xb1, 0xc7, 0x63, 0xb4, 0x83, 0x7a, 0x3a,
- 0x0d, 0x1f, 0x06, 0xf2, 0x49, 0x1c, 0x99, 0x41, 0x72, 0x5e, 0x3f, 0xce,
- 0x78, 0x5f, 0x05, 0xa7, 0x56, 0x9e, 0x0c, 0x68, 0x15, 0xd8, 0x37, 0x17,
- 0xc4, 0x70, 0xbe, 0x0d, 0x46, 0x36, 0x88, 0x83, 0xf4, 0xcd, 0x2b, 0xf1,
- 0xe4, 0xfd, 0x7e, 0x08, 0xef, 0x41, 0x3c, 0xc0, 0x77, 0x9e, 0x98, 0x09,
- 0x62, 0x88, 0x3a, 0xda, 0x1e, 0x8f, 0xb6, 0x78, 0x79, 0xed, 0x00, 0xaf,
- 0x1d, 0xa5, 0xfe, 0xcf, 0xeb, 0x93, 0x18, 0xe8, 0x55, 0x63, 0x40, 0x10,
- 0xfb, 0x0d, 0x04, 0xe8, 0xc2, 0x8f, 0x31, 0xbf, 0xc5, 0xce, 0xf3, 0xfb,
- 0xbd, 0xf9, 0x0a, 0xca, 0xe9, 0x47, 0x48, 0xfb, 0xc4, 0x74, 0x37, 0x9b,
- 0xe6, 0x77, 0xf5, 0xe8, 0xd2, 0x4f, 0x9d, 0x2e, 0x3c, 0x92, 0x77, 0x20,
- 0x35, 0x57, 0x81, 0xdf, 0xcf, 0xba, 0x70, 0x57, 0x7d, 0x05, 0x0e, 0xcd,
- 0x25, 0x31, 0x36, 0x53, 0x81, 0xc1, 0x2c, 0x56, 0xef, 0xd7, 0xc7, 0x6a,
- 0xca, 0xa0, 0x2e, 0xb7, 0x23, 0x86, 0xab, 0xb4, 0xc3, 0x23, 0x73, 0x3e,
- 0x7f, 0xff, 0x4c, 0x00, 0xa9, 0x05, 0x2f, 0x9f, 0x77, 0xf0, 0xf9, 0x72,
- 0xe8, 0xeb, 0x23, 0xa9, 0x00, 0x84, 0xc7, 0x4a, 0x3c, 0x34, 0xe7, 0xc5,
- 0x83, 0xd9, 0x00, 0x0e, 0xce, 0x34, 0x63, 0xda, 0x48, 0xe2, 0x18, 0x73,
- 0xc7, 0xf7, 0xe2, 0x6a, 0xef, 0x41, 0x45, 0x4d, 0x6e, 0x53, 0x92, 0x68,
- 0x88, 0xbb, 0x71, 0x89, 0x79, 0xc8, 0x1d, 0x6f, 0x6c, 0x79, 0x9e, 0xb9,
- 0xa1, 0x2c, 0x11, 0xe4, 0x77, 0x75, 0x82, 0x31, 0x9b, 0x74, 0x3b, 0x36,
- 0x00, 0x2b, 0x25, 0x7e, 0x83, 0xfe, 0x6e, 0x23, 0xe0, 0xef, 0xce, 0xd7,
- 0xf9, 0xb7, 0x1b, 0x21, 0xff, 0x76, 0xc6, 0xd7, 0x36, 0xf1, 0x47, 0xc3,
- 0x83, 0xe3, 0xf1, 0x4f, 0xcd, 0x81, 0x1a, 0x2b, 0x9f, 0xf9, 0x77, 0xce,
- 0xa8, 0xe9, 0x59, 0xa8, 0x3a, 0xab, 0x01, 0x26, 0x17, 0x5c, 0xb4, 0x9f,
- 0x82, 0x1a, 0xad, 0x99, 0x79, 0x3c, 0x80, 0x87, 0x98, 0x53, 0xfe, 0x9a,
- 0x39, 0x65, 0x70, 0x2a, 0x12, 0x98, 0x86, 0x97, 0xfa, 0x06, 0xf6, 0x9e,
- 0x0b, 0xd2, 0xe6, 0x5d, 0x78, 0x9c, 0x7c, 0x6d, 0xdf, 0x18, 0xc4, 0x7d,
- 0xf9, 0x80, 0xbf, 0x8b, 0xf6, 0x7b, 0x2f, 0x17, 0xf2, 0x6f, 0xa5, 0x2d,
- 0xdf, 0xce, 0xa9, 0xe1, 0x02, 0xfe, 0xaf, 0xf8, 0x53, 0x0c, 0x0e, 0x60,
- 0xff, 0x94, 0x1b, 0x85, 0xa0, 0xac, 0x45, 0x9d, 0x1b, 0x2f, 0x9a, 0x3e,
- 0x4d, 0x3b, 0x7d, 0x90, 0xba, 0xfe, 0x46, 0xde, 0x87, 0x07, 0x0d, 0x35,
- 0xf6, 0x7d, 0xc5, 0x47, 0x9d, 0x7a, 0xa8, 0x07, 0x26, 0x98, 0x55, 0xf2,
- 0x5c, 0x1c, 0xe1, 0x55, 0x76, 0xae, 0x3d, 0x34, 0x27, 0x7e, 0x42, 0xdb,
- 0x1b, 0xf4, 0x01, 0xfa, 0xcf, 0xf7, 0xaf, 0xc5, 0xaa, 0x1a, 0x48, 0x5b,
- 0xb9, 0x3b, 0x46, 0x7f, 0xb1, 0x75, 0x74, 0x62, 0x46, 0xf4, 0xa0, 0x4e,
- 0xc3, 0x91, 0xc4, 0xba, 0xf5, 0x7f, 0x6d, 0x5e, 0x5a, 0x29, 0xfa, 0x08,
- 0x60, 0x84, 0x3a, 0x3c, 0x6d, 0x98, 0xe6, 0xd5, 0x0d, 0x1f, 0x9a, 0x2d,
- 0x37, 0x8b, 0x5e, 0x44, 0xd6, 0x1f, 0x28, 0x52, 0x47, 0x6a, 0x34, 0xff,
- 0xff, 0x07, 0x5f, 0xf9, 0xa6, 0x39, 0x60, 0xc9, 0x27, 0xfe, 0xe2, 0xa2,
- 0x2f, 0x3e, 0x4e, 0xda, 0x0e, 0x0c, 0x90, 0xde, 0xc3, 0x86, 0xf9, 0x51,
- 0x6d, 0xe2, 0x33, 0xb3, 0x65, 0x93, 0x36, 0xbc, 0xac, 0xfc, 0x4f, 0x5e,
- 0x0f, 0xe2, 0xa1, 0x7c, 0x0b, 0x75, 0xd7, 0x8e, 0x27, 0xa8, 0xc3, 0xa3,
- 0x86, 0xe4, 0xc4, 0x10, 0xfd, 0xb9, 0x8e, 0xfe, 0xed, 0x52, 0xb6, 0x19,
- 0x39, 0x6c, 0x9f, 0x4c, 0xa3, 0x93, 0xfe, 0xbe, 0x94, 0x89, 0xb4, 0x3c,
- 0x0b, 0x35, 0x4d, 0x19, 0xfc, 0x5d, 0xd4, 0x71, 0xbb, 0xa1, 0x76, 0x89,
- 0x4d, 0xdb, 0x99, 0x97, 0x5e, 0xca, 0x84, 0xfc, 0x6d, 0x79, 0xd1, 0x77,
- 0x9d, 0x7f, 0x6b, 0xfe, 0xab, 0xb4, 0xbd, 0x82, 0xcd, 0x6b, 0x3c, 0xcc,
- 0x33, 0x77, 0xc1, 0xb6, 0xab, 0x6d, 0xbb, 0xd7, 0xe3, 0x8d, 0x03, 0x1f,
- 0x32, 0x3f, 0xa5, 0x57, 0xda, 0xd7, 0x52, 0xbc, 0x56, 0xbd, 0x01, 0xfe,
- 0x3b, 0xe9, 0x07, 0x7b, 0xe8, 0x07, 0x57, 0x37, 0x7c, 0x6a, 0x86, 0x6f,
- 0xb2, 0xfd, 0xa0, 0x6d, 0xc6, 0xe5, 0xef, 0xa0, 0x9e, 0xb6, 0xe9, 0x0a,
- 0xe6, 0xf4, 0x0c, 0x06, 0xae, 0x61, 0x87, 0xe4, 0xec, 0x59, 0x3d, 0xc9,
- 0x3c, 0xf2, 0x9b, 0x70, 0xd5, 0x60, 0xf6, 0x59, 0xfd, 0x71, 0x84, 0x6d,
- 0xdf, 0xc1, 0xc1, 0xac, 0x17, 0xe9, 0xbb, 0x02, 0x98, 0x6f, 0x08, 0xe0,
- 0x61, 0xd2, 0xbe, 0x12, 0x6f, 0x1c, 0x7a, 0x83, 0x3a, 0x98, 0xad, 0x91,
- 0x6b, 0x49, 0xfc, 0xa5, 0xfe, 0x28, 0x70, 0x93, 0xbd, 0xf6, 0x82, 0xc4,
- 0xe8, 0x42, 0x33, 0x8e, 0xe6, 0xfb, 0x15, 0x3b, 0x6f, 0xaa, 0x5d, 0x49,
- 0xfc, 0xc4, 0x94, 0x5c, 0xba, 0x60, 0x30, 0xc7, 0x51, 0x1f, 0xe3, 0xf4,
- 0xa3, 0xd1, 0x5c, 0x9d, 0xbf, 0x93, 0x7e, 0xf4, 0x78, 0x4e, 0x64, 0x8a,
- 0xea, 0xba, 0xb3, 0x96, 0xb5, 0x99, 0xfa, 0x31, 0xac, 0x9a, 0x5f, 0x1d,
- 0xd0, 0x8e, 0x61, 0xda, 0xe2, 0x2d, 0xa5, 0xf4, 0x13, 0x63, 0x30, 0x64,
- 0xaa, 0xcb, 0xb5, 0x43, 0x78, 0xdc, 0xba, 0x16, 0xf4, 0xef, 0x9e, 0x49,
- 0x3a, 0x1c, 0x1a, 0x02, 0x95, 0x89, 0x76, 0x65, 0x37, 0xeb, 0x6e, 0xc7,
- 0x4c, 0x87, 0xd2, 0xb1, 0x20, 0x31, 0xd0, 0xa5, 0x6c, 0x67, 0xcd, 0x4d,
- 0xb2, 0xe6, 0x26, 0x59, 0x73, 0x93, 0xe4, 0x23, 0xc9, 0x5a, 0xdb, 0x96,
- 0x4f, 0x29, 0x3b, 0x44, 0xff, 0xf4, 0xaf, 0xe7, 0x0d, 0x1b, 0x47, 0x30,
- 0x07, 0xf9, 0x3b, 0xf3, 0x6b, 0x1d, 0x36, 0xb6, 0x4b, 0x29, 0x45, 0x2c,
- 0xe3, 0xa9, 0xd0, 0x58, 0xcb, 0x8c, 0x94, 0xd2, 0xcd, 0x7a, 0xdb, 0x6f,
- 0xe9, 0x32, 0x32, 0xfc, 0x0e, 0xeb, 0xec, 0xeb, 0xac, 0xb3, 0xb9, 0x38,
- 0xe3, 0x6a, 0xcd, 0x55, 0x73, 0x60, 0xa5, 0x5d, 0x13, 0xc6, 0xc8, 0xef,
- 0x77, 0x69, 0xb3, 0x02, 0x6b, 0x69, 0xbb, 0x53, 0xc1, 0x7e, 0x0d, 0xd5,
- 0xb5, 0xcc, 0xa9, 0x47, 0xf3, 0xac, 0x03, 0x7a, 0xa4, 0xe5, 0x7d, 0x2a,
- 0xf6, 0xa8, 0xe6, 0xc6, 0xd5, 0x9b, 0x08, 0x76, 0xb4, 0x36, 0x1c, 0xcf,
- 0x96, 0x63, 0x28, 0x9e, 0x5c, 0xe1, 0x21, 0x56, 0xe9, 0x6a, 0xc6, 0xa3,
- 0x5c, 0x5a, 0x09, 0x25, 0xa2, 0xf4, 0x1b, 0x24, 0xa7, 0x58, 0x27, 0x26,
- 0x8d, 0xaf, 0x22, 0xc7, 0x7a, 0x3a, 0xaf, 0xbb, 0xf0, 0x7a, 0x6e, 0x2d,
- 0xf3, 0x5c, 0x54, 0xf7, 0x29, 0x15, 0x8c, 0xdf, 0x04, 0x32, 0x86, 0xe4,
- 0x27, 0xd3, 0x9c, 0x17, 0x1e, 0xa2, 0xd1, 0xe4, 0x28, 0x24, 0x67, 0x99,
- 0xab, 0xef, 0x8d, 0x97, 0x61, 0x73, 0xd4, 0x8f, 0xd5, 0xda, 0x80, 0xd2,
- 0x95, 0x8f, 0xea, 0xe7, 0xf1, 0xbb, 0xca, 0x9e, 0x85, 0x04, 0x63, 0xbb,
- 0x9f, 0xba, 0xa9, 0xc0, 0xa5, 0xa0, 0xf0, 0x88, 0x6a, 0xb7, 0xe6, 0xc0,
- 0xbb, 0x77, 0x2b, 0x08, 0x68, 0x49, 0x5c, 0x68, 0x0e, 0xd0, 0xaf, 0xba,
- 0x88, 0x31, 0xc2, 0x70, 0x2e, 0x86, 0xfc, 0x3b, 0x68, 0x8b, 0xca, 0xc5,
- 0x3a, 0xda, 0x87, 0xbe, 0x47, 0x1d, 0xb6, 0x51, 0x87, 0xdd, 0x73, 0x08,
- 0x54, 0x24, 0xfa, 0x94, 0x8e, 0x7c, 0xbb, 0xd2, 0x9e, 0x57, 0xa9, 0x27,
- 0xd1, 0xc9, 0x37, 0x89, 0x95, 0xc4, 0x57, 0x4a, 0xb6, 0x14, 0x7f, 0xbd,
- 0xd1, 0x9e, 0xfd, 0x0e, 0x89, 0xb9, 0xcd, 0x6b, 0x12, 0x8c, 0x47, 0x07,
- 0xf9, 0x12, 0x1e, 0x3c, 0xa8, 0x6e, 0x30, 0x57, 0x5f, 0x89, 0x33, 0x79,
- 0x56, 0x24, 0x30, 0x95, 0xef, 0xa1, 0x5d, 0x36, 0x14, 0xfd, 0x2b, 0xe0,
- 0xdf, 0x36, 0xd3, 0xae, 0x6c, 0x5b, 0x58, 0xe1, 0xef, 0xa5, 0x0d, 0x7b,
- 0x17, 0x42, 0x42, 0x97, 0xeb, 0x8b, 0x6d, 0x93, 0x70, 0x68, 0xff, 0x9a,
- 0x2d, 0xbf, 0x41, 0x5a, 0x62, 0x4f, 0x6f, 0xc9, 0x4f, 0xfd, 0x7b, 0x66,
- 0x92, 0x78, 0x77, 0x83, 0x9b, 0x35, 0xb5, 0x84, 0x29, 0xaa, 0x8a, 0x9f,
- 0xa7, 0x1d, 0xd0, 0x52, 0x4a, 0x97, 0xf8, 0x91, 0xdb, 0x5e, 0xf3, 0xce,
- 0x19, 0xb8, 0x09, 0x15, 0xc2, 0x4e, 0x62, 0xba, 0x0f, 0xe3, 0xd1, 0x81,
- 0x73, 0x4a, 0x8f, 0xd2, 0x93, 0x97, 0x1a, 0x6c, 0xfb, 0x54, 0x1b, 0x7d,
- 0xaa, 0x9d, 0xfc, 0xb4, 0xd3, 0xa7, 0xba, 0xc9, 0x4f, 0xb7, 0xe5, 0x53,
- 0xe2, 0x9b, 0xbf, 0xce, 0xcb, 0xd6, 0xfc, 0x1e, 0x4b, 0x2f, 0x3b, 0xf8,
- 0x6e, 0x17, 0xe5, 0xe8, 0xe2, 0x7b, 0x7b, 0xf8, 0xde, 0x9e, 0x85, 0xff,
- 0x2d, 0xfc, 0x51, 0x16, 0x3b, 0xf6, 0xaf, 0xd7, 0x34, 0xc9, 0x01, 0xaf,
- 0x15, 0x31, 0x05, 0xd2, 0x8e, 0x84, 0xe4, 0x88, 0x61, 0xf4, 0x36, 0xc3,
- 0xb3, 0x22, 0xf1, 0x93, 0xd6, 0x5d, 0xf5, 0xcc, 0x67, 0xcc, 0xa7, 0x9e,
- 0x29, 0x62, 0x69, 0xe6, 0xe8, 0xf9, 0x16, 0x05, 0x63, 0xfa, 0xcd, 0x8c,
- 0x53, 0x1d, 0x13, 0x79, 0xb5, 0x2b, 0xcc, 0x7b, 0x4d, 0x93, 0x82, 0xf1,
- 0x0f, 0xa2, 0x8d, 0xb8, 0x2e, 0x94, 0x18, 0x42, 0xc8, 0x88, 0x84, 0x26,
- 0x14, 0x75, 0x68, 0x2b, 0xd4, 0x25, 0xd6, 0x86, 0xd4, 0x9c, 0xa2, 0x0e,
- 0xd7, 0x3a, 0xd5, 0xe4, 0x9b, 0x16, 0xbe, 0x3e, 0x88, 0x35, 0x16, 0x86,
- 0x1b, 0x42, 0x8c, 0x58, 0x76, 0x07, 0x69, 0x1e, 0xd8, 0xac, 0xe0, 0xb2,
- 0xfe, 0x21, 0xed, 0xa8, 0x26, 0xd3, 0x8a, 0x8e, 0x0c, 0xf3, 0x44, 0x68,
- 0x4a, 0xb0, 0xfa, 0x41, 0x62, 0x75, 0x78, 0x7c, 0x7c, 0x36, 0x33, 0x19,
- 0x49, 0x79, 0x9c, 0x6a, 0x8c, 0x38, 0x3d, 0x49, 0x9a, 0x7a, 0x9e, 0xf8,
- 0x9d, 0x6b, 0x84, 0xf7, 0x17, 0x69, 0x46, 0x8b, 0x34, 0xb5, 0x1c, 0x18,
- 0x37, 0x13, 0xe8, 0x8c, 0xb2, 0x56, 0x30, 0xe7, 0x1d, 0x93, 0x9e, 0x80,
- 0xf4, 0xca, 0xa7, 0x74, 0x7e, 0x4f, 0x29, 0xbb, 0x25, 0xa6, 0xca, 0x6d,
- 0x2b, 0x54, 0x73, 0x8d, 0xaa, 0xc4, 0x61, 0x2c, 0x5a, 0x6b, 0x0c, 0xcb,
- 0x1a, 0xc3, 0x3f, 0x53, 0xd4, 0xd8, 0x39, 0x45, 0x72, 0x75, 0x63, 0xff,
- 0x39, 0xc6, 0xd0, 0x51, 0x45, 0x6d, 0x39, 0x4e, 0xf1, 0xbd, 0x9a, 0xd0,
- 0x3f, 0x5c, 0x5c, 0x67, 0x18, 0x0d, 0x39, 0xc6, 0x67, 0xde, 0xa3, 0x6c,
- 0xcd, 0xb6, 0x61, 0x6c, 0xae, 0x0d, 0xa3, 0x59, 0x05, 0x7b, 0xf4, 0x95,
- 0xb8, 0x74, 0xb3, 0xd5, 0xa7, 0x54, 0xad, 0xd6, 0x6a, 0x31, 0x12, 0x40,
- 0xb5, 0x43, 0xfb, 0x0a, 0xf6, 0x16, 0x31, 0x7e, 0xe7, 0x89, 0x5e, 0xe6,
- 0x7d, 0x13, 0xef, 0x33, 0x96, 0x22, 0x35, 0x48, 0xba, 0x13, 0x2d, 0xc4,
- 0xe3, 0x75, 0x4e, 0x3b, 0xde, 0xff, 0xc9, 0x63, 0xdb, 0x40, 0xf4, 0xff,
- 0xf9, 0x7b, 0x6d, 0x78, 0x32, 0x5b, 0x86, 0x96, 0x0d, 0xb8, 0x2b, 0x84,
- 0x2a, 0x07, 0x6b, 0xdc, 0x5b, 0xbb, 0x94, 0x14, 0xef, 0x59, 0xcf, 0x7a,
- 0xbe, 0x9c, 0xe8, 0x4d, 0xfc, 0x97, 0x06, 0xb9, 0x6e, 0xe5, 0x8d, 0x1b,
- 0xae, 0x0f, 0x7f, 0xc1, 0x75, 0x05, 0xcf, 0x31, 0x91, 0x7d, 0x8f, 0x35,
- 0x25, 0x97, 0x31, 0xe1, 0x4c, 0xb8, 0x30, 0x34, 0x19, 0xc6, 0xc1, 0xc5,
- 0x20, 0x16, 0x33, 0xea, 0xc0, 0x25, 0xf6, 0x0f, 0x7b, 0x9b, 0x35, 0x3c,
- 0xb8, 0x18, 0xc2, 0x42, 0x06, 0xa6, 0x37, 0xa1, 0x15, 0xbc, 0x4a, 0x0c,
- 0x07, 0x16, 0xeb, 0x70, 0x2e, 0xa3, 0x2d, 0x8d, 0x2a, 0xd1, 0x54, 0x2d,
- 0x71, 0xc7, 0xc3, 0x8b, 0x4d, 0x78, 0x68, 0xd1, 0xc3, 0x77, 0x4c, 0x74,
- 0xc7, 0xeb, 0xf8, 0xbc, 0x03, 0xcf, 0x9e, 0x34, 0x4d, 0xc1, 0x5d, 0x43,
- 0x8b, 0xc0, 0xc2, 0x34, 0x6b, 0xd1, 0x19, 0xd6, 0xa5, 0xa7, 0x80, 0x03,
- 0x4f, 0x39, 0x30, 0x37, 0x6d, 0x62, 0xaf, 0x3e, 0x5a, 0xeb, 0xa0, 0xc3,
- 0x0f, 0xb0, 0x6e, 0xb8, 0x59, 0x03, 0xef, 0x0d, 0xd8, 0xf9, 0xfc, 0x12,
- 0xf3, 0xd4, 0xfd, 0x4f, 0xc5, 0xf0, 0x56, 0x26, 0x8d, 0x6e, 0xe2, 0xf3,
- 0x14, 0x79, 0x79, 0x33, 0xc3, 0x3a, 0xb6, 0xa8, 0xe3, 0x8d, 0x8c, 0x87,
- 0xeb, 0x34, 0xe1, 0xe5, 0x8c, 0x3c, 0x23, 0xcf, 0xfa, 0x30, 0x48, 0x5e,
- 0x5e, 0xcf, 0x84, 0xb8, 0x66, 0x10, 0x3f, 0xe6, 0x73, 0xf7, 0x2d, 0x6a,
- 0xac, 0x5b, 0x1e, 0xae, 0x1b, 0xc6, 0xab, 0x19, 0x1f, 0x79, 0x0d, 0xb2,
- 0x56, 0x0d, 0x62, 0x2c, 0xd3, 0xb8, 0xb4, 0x95, 0x89, 0xda, 0xae, 0x35,
- 0x72, 0xed, 0x1d, 0xb3, 0xc7, 0x8a, 0x45, 0x59, 0xa7, 0xb4, 0xee, 0x20,
- 0x46, 0x33, 0x6f, 0x38, 0x4b, 0xfd, 0xf4, 0x73, 0xd3, 0xcb, 0x16, 0xf6,
- 0x7b, 0xd6, 0xe0, 0xdf, 0x73, 0xc0, 0x39, 0x23, 0x6d, 0x56, 0x27, 0x88,
- 0x75, 0x59, 0xa3, 0x7e, 0xba, 0xb1, 0x89, 0xeb, 0x6a, 0x03, 0x2f, 0x29,
- 0xd2, 0xef, 0xb8, 0x10, 0x7e, 0x4a, 0xf4, 0x45, 0xcc, 0xbc, 0x00, 0xfc,
- 0x25, 0xf1, 0x67, 0xc3, 0xa4, 0x2a, 0x7e, 0xdf, 0x4f, 0x5c, 0xd3, 0x5b,
- 0x40, 0x7d, 0xec, 0x41, 0x8c, 0x98, 0x65, 0xc4, 0xe7, 0xd5, 0xc4, 0xb5,
- 0x8b, 0x4d, 0xac, 0x53, 0x1b, 0x4d, 0xf3, 0x6f, 0x9b, 0x61, 0x3a, 0x12,
- 0x9a, 0x5e, 0xeb, 0x2c, 0x7c, 0xa5, 0x0a, 0xda, 0x92, 0x5f, 0xd1, 0x0a,
- 0x3f, 0x45, 0x74, 0xf8, 0x3c, 0x44, 0xaf, 0xc0, 0xda, 0x45, 0x17, 0xd6,
- 0x51, 0x9e, 0x6d, 0x93, 0x5c, 0x9b, 0xf8, 0x24, 0x4a, 0x99, 0x76, 0x4e,
- 0x12, 0x73, 0x69, 0x3e, 0xac, 0xa1, 0x8e, 0x87, 0x4e, 0x99, 0x66, 0x39,
- 0x75, 0xdc, 0x40, 0xfb, 0xec, 0x3f, 0x61, 0xe2, 0x25, 0xfd, 0x25, 0xea,
- 0x54, 0x21, 0x6e, 0x6c, 0xe6, 0x3b, 0x41, 0x3e, 0xef, 0xc1, 0x81, 0x49,
- 0xe9, 0x97, 0xea, 0xf8, 0xcc, 0x45, 0x1c, 0xcf, 0xc4, 0xd0, 0x44, 0xfd,
- 0x85, 0x49, 0xb3, 0x91, 0xef, 0x84, 0x49, 0x2f, 0xbc, 0xf8, 0x35, 0x6c,
- 0x3f, 0xa5, 0x40, 0x8b, 0x8a, 0x0e, 0xbe, 0x86, 0xf6, 0x33, 0x5f, 0x94,
- 0x13, 0x98, 0xa5, 0xa6, 0xd5, 0x89, 0x02, 0xf1, 0x77, 0x55, 0x62, 0x04,
- 0xac, 0xdf, 0x78, 0x73, 0x56, 0xc1, 0xd4, 0x34, 0xfb, 0xbd, 0x8d, 0x30,
- 0x2b, 0x28, 0xd3, 0x1b, 0xb3, 0xbf, 0x81, 0x67, 0x4e, 0x52, 0x0f, 0x4f,
- 0x07, 0xf1, 0xbd, 0x8c, 0x0b, 0xb7, 0x4e, 0x09, 0xa6, 0xd3, 0x62, 0x07,
- 0x15, 0xe9, 0x8f, 0xa4, 0x6f, 0x89, 0x86, 0xdd, 0x8a, 0x03, 0xf5, 0xcf,
- 0xb8, 0xa0, 0x9d, 0x0b, 0xc3, 0x5d, 0xef, 0x81, 0x56, 0xff, 0xfb, 0xcc,
- 0x35, 0x0e, 0x94, 0xb1, 0x97, 0xed, 0xfc, 0x76, 0x8c, 0xd7, 0x82, 0xbc,
- 0x86, 0xdf, 0x28, 0x87, 0x73, 0x95, 0x93, 0x35, 0xbc, 0x4c, 0x23, 0x1e,
- 0x73, 0x99, 0xa6, 0x93, 0xb5, 0x61, 0xf7, 0x77, 0x4c, 0x33, 0xb2, 0x41,
- 0x9e, 0x0f, 0x20, 0x72, 0x4e, 0xe3, 0x73, 0x76, 0xbd, 0xbc, 0x8e, 0xc7,
- 0x9c, 0xf4, 0x23, 0x89, 0x55, 0xd6, 0x7b, 0xab, 0x87, 0xb2, 0x71, 0xfb,
- 0x0b, 0x79, 0xc1, 0x36, 0x61, 0x4b, 0x86, 0xb3, 0xd3, 0x0a, 0x73, 0x76,
- 0x82, 0xcf, 0x6e, 0x81, 0x33, 0xae, 0x4e, 0xa4, 0xe9, 0x07, 0x7b, 0x03,
- 0x2d, 0x78, 0xce, 0x70, 0xa3, 0x52, 0x5b, 0x85, 0x07, 0x7a, 0x03, 0x78,
- 0x8e, 0x7d, 0x01, 0x6d, 0x16, 0x2b, 0x80, 0x8d, 0xb4, 0x9f, 0xf4, 0x1c,
- 0x3f, 0x84, 0xf6, 0x6d, 0x07, 0xf3, 0x9c, 0xd3, 0xca, 0x73, 0x65, 0xf5,
- 0x40, 0x21, 0xe7, 0xc2, 0x05, 0xcd, 0xc6, 0x84, 0x2f, 0x58, 0x35, 0x5b,
- 0x0d, 0x14, 0xae, 0x61, 0x41, 0xb5, 0x25, 0xa9, 0x90, 0x19, 0xbf, 0xe8,
- 0xae, 0xdf, 0x65, 0xfb, 0xd2, 0xdf, 0x38, 0xa5, 0xe7, 0xb8, 0xfe, 0xbd,
- 0x02, 0x8e, 0x84, 0x1a, 0x6a, 0x73, 0xc2, 0xe3, 0x4a, 0x0c, 0xb5, 0x8e,
- 0x6b, 0x5f, 0xba, 0x81, 0xf7, 0x26, 0x8c, 0xe5, 0xaf, 0xf7, 0xda, 0x5d,
- 0x19, 0xcb, 0x87, 0xba, 0x44, 0xf7, 0x4f, 0xe8, 0x92, 0x67, 0x53, 0x4a,
- 0x3b, 0xf3, 0x56, 0xda, 0x85, 0x74, 0x15, 0x9f, 0xa1, 0xfe, 0x71, 0x74,
- 0x52, 0xe8, 0x1c, 0xc6, 0x78, 0x46, 0x66, 0x1b, 0xc3, 0xd8, 0x6c, 0x44,
- 0x62, 0x4b, 0xec, 0xa1, 0x8f, 0x40, 0xe6, 0x10, 0x8d, 0x85, 0x57, 0x14,
- 0x35, 0x75, 0x8b, 0x53, 0x1d, 0x5a, 0x56, 0xec, 0xbc, 0xb5, 0xb6, 0x98,
- 0xb7, 0xd6, 0xe4, 0x56, 0xf9, 0x7b, 0x58, 0x0f, 0x7a, 0x16, 0x4a, 0xf5,
- 0xa1, 0x47, 0xe9, 0xb4, 0x6a, 0x6b, 0xbf, 0xb2, 0x63, 0xc1, 0xa3, 0x74,
- 0x64, 0x3d, 0x78, 0x85, 0x58, 0x6c, 0xb6, 0x0f, 0x81, 0x5b, 0x37, 0xc2,
- 0xbb, 0x23, 0xdb, 0x8b, 0x72, 0x4d, 0x7a, 0xc8, 0x72, 0x74, 0x5a, 0x75,
- 0xad, 0xce, 0xdf, 0xc3, 0xfa, 0xd3, 0x93, 0xef, 0x63, 0xfe, 0x43, 0xc0,
- 0x9b, 0xb0, 0x67, 0x06, 0x92, 0x0b, 0xef, 0xe0, 0xbb, 0x4b, 0xf1, 0x15,
- 0x80, 0x5d, 0xff, 0x94, 0x7e, 0xf6, 0x12, 0xd5, 0x1b, 0x14, 0x5c, 0xba,
- 0xcb, 0x03, 0xd2, 0x62, 0xcf, 0x7f, 0xb1, 0xf5, 0xc2, 0x74, 0xaf, 0xd2,
- 0x31, 0x37, 0xef, 0xdd, 0x66, 0xc8, 0x2c, 0x62, 0xd6, 0xdb, 0x4e, 0x1e,
- 0xda, 0x17, 0x9e, 0xf6, 0x6e, 0x25, 0x4f, 0x5b, 0x17, 0x3e, 0x4f, 0x53,
- 0xea, 0xca, 0x44, 0x6b, 0x1b, 0x63, 0x7b, 0xb7, 0xfe, 0x91, 0x19, 0xfe,
- 0x1d, 0xa1, 0xb3, 0x58, 0xd4, 0x67, 0x92, 0x7c, 0x05, 0x3d, 0x9d, 0xf9,
- 0x80, 0x27, 0x99, 0x6f, 0xf7, 0xb6, 0x19, 0xbd, 0xde, 0xad, 0x46, 0x9f,
- 0xb7, 0xdd, 0xb8, 0x87, 0xb4, 0x7b, 0xbc, 0x1d, 0x06, 0xe3, 0x3a, 0xdf,
- 0x47, 0xbd, 0xf6, 0x62, 0x3c, 0x7f, 0x0f, 0xb1, 0x87, 0xd0, 0x1c, 0x20,
- 0x0e, 0xf2, 0x52, 0xc6, 0x11, 0xca, 0x58, 0x08, 0xb9, 0x91, 0x54, 0xdd,
- 0xd4, 0xd7, 0x98, 0x65, 0xc7, 0x09, 0x6b, 0x16, 0x55, 0x91, 0x98, 0x6c,
- 0xed, 0x3e, 0xc1, 0x7c, 0x9f, 0x38, 0xda, 0x7a, 0xeb, 0x29, 0xd4, 0xb8,
- 0x13, 0xd2, 0x3b, 0xb3, 0x1f, 0x8e, 0x46, 0xf5, 0xf7, 0x10, 0x0d, 0xbd,
- 0xc2, 0x67, 0x47, 0xe9, 0xbb, 0x63, 0xd6, 0xfc, 0x81, 0x06, 0xc9, 0x35,
- 0xa1, 0xdb, 0xf0, 0x78, 0x77, 0xb2, 0x37, 0xf3, 0x27, 0xd4, 0x96, 0x3b,
- 0x9c, 0x32, 0x0f, 0x29, 0xfc, 0x96, 0x0f, 0x4d, 0xe8, 0xca, 0x7b, 0x28,
- 0xd7, 0x97, 0xf0, 0x0f, 0x27, 0x59, 0xd7, 0x20, 0x7e, 0x68, 0x9a, 0xf7,
- 0xb1, 0xaf, 0x39, 0x96, 0xab, 0xc3, 0x65, 0xcb, 0xc6, 0x2e, 0x1c, 0xcd,
- 0x85, 0xf1, 0x0e, 0xe5, 0x73, 0x2d, 0xd6, 0xe2, 0xed, 0x69, 0x27, 0xf6,
- 0xe9, 0xb7, 0x17, 0xeb, 0x85, 0x03, 0xf7, 0xc6, 0x0e, 0x11, 0x3b, 0x38,
- 0x50, 0x4d, 0xfc, 0xf6, 0xb0, 0x75, 0xcd, 0xc9, 0xfe, 0xef, 0xb7, 0x91,
- 0xb2, 0xeb, 0x09, 0x79, 0x7c, 0x94, 0x3c, 0x36, 0x7b, 0xb7, 0x66, 0x55,
- 0xef, 0x9d, 0x59, 0x78, 0xdc, 0x89, 0xd1, 0xd6, 0x33, 0x27, 0x4d, 0x0c,
- 0xea, 0xb7, 0xe1, 0xca, 0xc9, 0xd1, 0x21, 0x17, 0xfd, 0xe7, 0xe7, 0xf1,
- 0x7e, 0x18, 0x33, 0xb8, 0x40, 0xe4, 0x71, 0xd1, 0xc7, 0xdc, 0xde, 0x10,
- 0x8f, 0x06, 0x58, 0x8b, 0xf5, 0x05, 0xc6, 0x66, 0x07, 0xd4, 0x21, 0xd6,
- 0xe4, 0xa4, 0x33, 0x11, 0x1d, 0x18, 0x23, 0x78, 0xac, 0x22, 0x3f, 0x5e,
- 0xe6, 0x6e, 0xdf, 0x62, 0xd8, 0xbb, 0x9b, 0xf5, 0x26, 0xc4, 0xfe, 0xce,
- 0x1b, 0xc5, 0xed, 0xb5, 0x88, 0xc6, 0x96, 0x29, 0xb7, 0x7b, 0xb1, 0xc9,
- 0x7b, 0x07, 0xeb, 0xc7, 0xe5, 0xa8, 0x39, 0xf2, 0x92, 0xee, 0x83, 0x7f,
- 0x51, 0xa7, 0xbe, 0xfb, 0x31, 0xba, 0xc0, 0x96, 0x2b, 0xca, 0x9e, 0x7f,
- 0xb1, 0xc5, 0xbb, 0x93, 0xb1, 0x59, 0x45, 0x13, 0x35, 0x2e, 0x26, 0xbd,
- 0xd2, 0xf3, 0x35, 0x2d, 0x6e, 0x22, 0x7f, 0xe2, 0xa3, 0x99, 0xd6, 0xcd,
- 0xf4, 0x87, 0xf0, 0x22, 0x3a, 0x99, 0xe6, 0x5e, 0x26, 0xcd, 0xfe, 0x10,
- 0x31, 0xec, 0x81, 0x8d, 0x3e, 0xe6, 0x29, 0xd1, 0x25, 0xf5, 0x98, 0x2f,
- 0xc9, 0x24, 0x75, 0xf9, 0x68, 0xeb, 0xe2, 0x29, 0xa9, 0xcb, 0xa9, 0xd6,
- 0xcc, 0x29, 0x0d, 0xef, 0xb0, 0xb6, 0xac, 0x8d, 0xab, 0xfa, 0x39, 0x25,
- 0x12, 0xba, 0x48, 0x59, 0x5c, 0xf8, 0x85, 0xb9, 0x57, 0x8b, 0x16, 0x6e,
- 0x61, 0x3c, 0x55, 0x33, 0x37, 0x86, 0x98, 0xf3, 0xab, 0x17, 0xa9, 0x98,
- 0x45, 0xa7, 0x1b, 0x15, 0x21, 0x78, 0xa2, 0x1a, 0xde, 0x3d, 0x19, 0xa3,
- 0x1e, 0xae, 0xd1, 0x3c, 0x48, 0xa8, 0x35, 0xc8, 0x52, 0xf8, 0xd8, 0x33,
- 0xf4, 0xc5, 0x71, 0xae, 0x5b, 0xb6, 0x28, 0x3c, 0xcb, 0xf3, 0x41, 0x3e,
- 0x7f, 0x7d, 0xed, 0x6a, 0xae, 0xfd, 0xd1, 0x29, 0xf1, 0xd7, 0x54, 0xeb,
- 0x85, 0x93, 0xf6, 0xda, 0xd1, 0x78, 0x0c, 0x1f, 0x9e, 0x54, 0x87, 0xdf,
- 0x55, 0x22, 0x03, 0x17, 0x14, 0x59, 0x1f, 0x75, 0x55, 0xb8, 0x62, 0x8e,
- 0x46, 0xa3, 0xa9, 0xbd, 0xa4, 0xd9, 0xb2, 0x89, 0xfa, 0xb7, 0xf8, 0xa0,
- 0xcf, 0x33, 0xcf, 0xba, 0xc9, 0x8f, 0xcd, 0x4b, 0x1d, 0x69, 0x9f, 0x2c,
- 0xf6, 0x6a, 0xec, 0x53, 0xaf, 0xf3, 0x13, 0xa4, 0x1e, 0x3c, 0xbb, 0x9b,
- 0x7d, 0xa8, 0xb5, 0x9e, 0x0b, 0xf0, 0x39, 0xd1, 0xc3, 0x2f, 0x15, 0x87,
- 0xf6, 0x1e, 0xf3, 0x98, 0xe4, 0x92, 0x20, 0x73, 0xd8, 0x3d, 0xd2, 0xd3,
- 0xa6, 0xd3, 0xf4, 0x77, 0x37, 0xfd, 0x7d, 0x9b, 0xf8, 0xb4, 0x41, 0x9f,
- 0x36, 0xe8, 0xd3, 0x86, 0x1a, 0x1a, 0x46, 0x24, 0x30, 0x48, 0xbb, 0x25,
- 0x43, 0xe2, 0xeb, 0x7d, 0xd8, 0xc7, 0xdf, 0xfd, 0xbc, 0x7f, 0x94, 0x7d,
- 0x2e, 0x56, 0xc8, 0x9a, 0x87, 0xd1, 0x6e, 0x3c, 0x86, 0xa1, 0x2c, 0x7e,
- 0xe5, 0x6d, 0x2e, 0x47, 0xf9, 0x1a, 0xe9, 0xe1, 0xd5, 0xc0, 0x31, 0x3c,
- 0xc6, 0x3e, 0xea, 0x97, 0x4a, 0xa5, 0xe6, 0xea, 0x3d, 0xae, 0xa8, 0x81,
- 0x76, 0xf6, 0xc3, 0x7b, 0xf3, 0xf7, 0xd0, 0xbe, 0x91, 0xa1, 0x57, 0x14,
- 0xf6, 0x52, 0xb5, 0x5c, 0x9b, 0xb1, 0x74, 0x27, 0xd7, 0x31, 0x84, 0x0f,
- 0x2b, 0xdf, 0xfe, 0x1e, 0x44, 0xb7, 0x3f, 0x6a, 0x18, 0xe4, 0xfa, 0x36,
- 0x1f, 0xa3, 0xec, 0x29, 0x07, 0x19, 0x63, 0xfb, 0xac, 0xf8, 0xea, 0x23,
- 0x8d, 0xeb, 0x79, 0x6c, 0x6b, 0x46, 0x6a, 0xa9, 0x89, 0xc7, 0x75, 0x13,
- 0xcf, 0xf2, 0x77, 0x89, 0xb9, 0x6c, 0xec, 0x86, 0x5c, 0xe6, 0xe0, 0x73,
- 0xbb, 0xf9, 0x5c, 0x0b, 0x53, 0xe7, 0xc2, 0x9c, 0xcc, 0x06, 0x0f, 0xcb,
- 0x6c, 0x10, 0x39, 0x43, 0x74, 0x3f, 0x8c, 0x0b, 0x99, 0x48, 0xca, 0xe9,
- 0x34, 0x47, 0x18, 0x57, 0x4b, 0x1f, 0xd1, 0x77, 0x5f, 0xdf, 0xa8, 0xf6,
- 0x52, 0x87, 0xb1, 0x49, 0x45, 0x0d, 0xbd, 0x86, 0x42, 0xa7, 0x07, 0x8d,
- 0xe1, 0x75, 0xce, 0x68, 0xe0, 0x2c, 0xd4, 0xc2, 0x20, 0x25, 0x7d, 0x3a,
- 0x6f, 0xe7, 0xba, 0xcd, 0xc5, 0x5c, 0xd7, 0x92, 0xab, 0x50, 0xee, 0xcc,
- 0xb2, 0x3e, 0xcf, 0x99, 0x69, 0x3f, 0xeb, 0x55, 0x7e, 0x4e, 0x68, 0x8f,
- 0xa0, 0x31, 0x2e, 0xb4, 0xb4, 0xae, 0x49, 0x05, 0x5f, 0xaf, 0x44, 0x94,
- 0xb5, 0x0a, 0x7a, 0xb9, 0x96, 0x36, 0x59, 0x93, 0x02, 0xee, 0x84, 0xd4,
- 0xce, 0x1e, 0xf6, 0x2d, 0x7d, 0xcc, 0x8b, 0x82, 0xa9, 0x65, 0x5e, 0x6a,
- 0xe7, 0xa3, 0x6d, 0x79, 0xb1, 0x8b, 0xd8, 0x44, 0x6c, 0x73, 0x18, 0x07,
- 0xac, 0x79, 0xb4, 0x89, 0x69, 0x5d, 0x72, 0x83, 0xd8, 0xe9, 0x30, 0xf6,
- 0xe7, 0xdd, 0xb8, 0x97, 0x79, 0x70, 0xbe, 0x99, 0xba, 0xf2, 0xbb, 0x31,
- 0x38, 0x77, 0x3b, 0xf6, 0x65, 0x65, 0x9e, 0xe0, 0xa6, 0xfd, 0x92, 0xc4,
- 0x40, 0xcc, 0x3a, 0xc4, 0x3f, 0x65, 0x5a, 0x49, 0xa7, 0x42, 0x5b, 0x74,
- 0x5a, 0xfa, 0xbe, 0xe0, 0xb6, 0x75, 0x6c, 0xcf, 0x2d, 0x9d, 0x09, 0x59,
- 0xab, 0x34, 0xb3, 0xb4, 0xf5, 0xda, 0x99, 0x91, 0x35, 0x4d, 0x9c, 0xd5,
- 0x6d, 0x4c, 0x5b, 0xd2, 0x67, 0x88, 0x32, 0xd7, 0x6c, 0x02, 0xd6, 0xdd,
- 0x80, 0x6b, 0x2b, 0x78, 0xad, 0xfb, 0x3a, 0xae, 0xed, 0x17, 0xec, 0x4c,
- 0x5c, 0xdb, 0xb5, 0x83, 0xb8, 0xb6, 0x5e, 0x29, 0x61, 0x5a, 0x99, 0x59,
- 0x94, 0x70, 0x6d, 0x75, 0x31, 0x7f, 0x1f, 0xc6, 0x5e, 0x62, 0x9e, 0xda,
- 0xfa, 0x11, 0x78, 0xd6, 0x3b, 0x3e, 0x73, 0x60, 0x84, 0xbd, 0x4c, 0x19,
- 0xb0, 0xd2, 0xc4, 0x2d, 0x1b, 0xd2, 0x66, 0xb9, 0x56, 0x1f, 0x2e, 0x77,
- 0xc8, 0x4c, 0x3a, 0x9a, 0x1e, 0x63, 0x9e, 0x71, 0xac, 0x57, 0xd3, 0x49,
- 0x78, 0x02, 0x35, 0xda, 0x3d, 0xc5, 0x5e, 0x22, 0xe4, 0xd9, 0x4e, 0x4c,
- 0x14, 0x8d, 0x7f, 0x6a, 0xce, 0x06, 0x85, 0x46, 0xa1, 0xe0, 0x41, 0xf2,
- 0x11, 0x0f, 0x6b, 0xd4, 0xb2, 0x32, 0x81, 0xd7, 0xa3, 0x21, 0xcf, 0xce,
- 0x7c, 0xda, 0xdb, 0xdd, 0x70, 0x0b, 0x7a, 0x4e, 0x49, 0x3d, 0x0a, 0x63,
- 0xc7, 0xa9, 0x76, 0xd6, 0x20, 0x0d, 0x1d, 0x93, 0x5d, 0xec, 0xf1, 0x7a,
- 0x95, 0xde, 0x39, 0xd1, 0xa1, 0xd8, 0x40, 0x0d, 0x84, 0x1d, 0x37, 0xce,
- 0x4c, 0x4b, 0xfd, 0xf2, 0x7b, 0x96, 0x7f, 0x8d, 0xeb, 0x01, 0xea, 0xe7,
- 0xaa, 0x1b, 0x7e, 0x13, 0x67, 0x74, 0xf1, 0x4b, 0x7e, 0x37, 0x92, 0xd8,
- 0xd6, 0x3c, 0x6d, 0xba, 0x34, 0x99, 0x7d, 0x87, 0x2c, 0x9b, 0x6e, 0x65,
- 0x9d, 0x6b, 0x9f, 0xeb, 0xa3, 0x1d, 0x4b, 0x73, 0xee, 0x1b, 0xed, 0xb9,
- 0xc5, 0xbb, 0x8d, 0x39, 0x8f, 0x3d, 0xbc, 0xc7, 0xc3, 0x3c, 0xea, 0x39,
- 0x65, 0x62, 0x4e, 0x7f, 0xcb, 0x7c, 0x5c, 0x73, 0xd1, 0x6e, 0x5f, 0x65,
- 0x4e, 0x16, 0xcc, 0x92, 0xf0, 0xde, 0x31, 0xe3, 0x72, 0x54, 0x25, 0xd0,
- 0x5c, 0x46, 0x7f, 0xbc, 0x18, 0xb7, 0xe7, 0x91, 0xc7, 0x73, 0xb7, 0x7b,
- 0xbb, 0xb3, 0xec, 0x33, 0xd8, 0x07, 0xdb, 0xbd, 0xdf, 0x57, 0xbd, 0x7b,
- 0xb2, 0x4e, 0xa5, 0x36, 0x01, 0x67, 0xcb, 0x26, 0x13, 0x1f, 0x6f, 0x88,
- 0xa6, 0x42, 0x0e, 0xe6, 0x4f, 0xd2, 0x32, 0x72, 0xcd, 0xde, 0x7e, 0xe6,
- 0xeb, 0x9d, 0x59, 0xba, 0x01, 0x7d, 0xc7, 0xbf, 0x61, 0x74, 0xc0, 0x0f,
- 0x99, 0xb3, 0xe1, 0xeb, 0x8c, 0xd8, 0x20, 0xfd, 0x31, 0xd4, 0xa6, 0x44,
- 0x97, 0x87, 0x10, 0x5d, 0xfa, 0xd8, 0xf9, 0x96, 0xf9, 0x64, 0x6e, 0x13,
- 0x9f, 0xef, 0x62, 0x2e, 0x4d, 0x32, 0xb7, 0x8e, 0xa6, 0xdc, 0x90, 0x77,
- 0xd4, 0xfe, 0x37, 0x95, 0x08, 0xe3, 0x00, 0xbf, 0xc3, 0xe7, 0x03, 0x1d,
- 0xcc, 0xa3, 0x73, 0x7a, 0x34, 0xb9, 0x15, 0xe9, 0xae, 0x6a, 0xa8, 0x7a,
- 0x83, 0x22, 0x73, 0x31, 0xb1, 0x43, 0x0c, 0x3f, 0xe1, 0x9a, 0x2e, 0x4d,
- 0xf4, 0xb8, 0x85, 0xbe, 0x48, 0x6c, 0xe0, 0xf8, 0xbc, 0xdf, 0xfd, 0x5e,
- 0x19, 0x2a, 0x56, 0x50, 0xb6, 0x9f, 0x58, 0x39, 0xc7, 0xab, 0x69, 0xf8,
- 0xaf, 0xc4, 0x4e, 0x7f, 0x96, 0x97, 0xf9, 0x67, 0x09, 0x0f, 0x8a, 0x6f,
- 0x64, 0x5a, 0x6f, 0x9d, 0x8d, 0x15, 0xe7, 0xa1, 0x1e, 0x6f, 0xd7, 0x8c,
- 0x89, 0xac, 0xee, 0x87, 0xf4, 0xff, 0xe5, 0xf1, 0x02, 0xd1, 0x41, 0x13,
- 0x3a, 0x78, 0xbd, 0x7d, 0xa6, 0x52, 0x69, 0xcf, 0x9a, 0xf8, 0x33, 0x5d,
- 0x4d, 0xb7, 0x39, 0x19, 0xef, 0xba, 0x7a, 0x16, 0xf8, 0x19, 0x71, 0x94,
- 0xf8, 0x98, 0x0b, 0x3e, 0xcd, 0xa6, 0xd5, 0x34, 0x7b, 0x3b, 0xb1, 0x85,
- 0xc4, 0x9f, 0x73, 0x6d, 0x05, 0x9a, 0x95, 0x59, 0x97, 0xe8, 0xad, 0x0b,
- 0xc9, 0x7c, 0xa5, 0xb2, 0x8b, 0xba, 0xbc, 0x73, 0xbd, 0x17, 0x97, 0x2c,
- 0x5d, 0xde, 0x4e, 0x5d, 0xe2, 0x8d, 0xd5, 0x70, 0x5e, 0xa8, 0x05, 0xc1,
- 0x44, 0xb9, 0x1a, 0x1e, 0x70, 0x88, 0x4d, 0x18, 0x27, 0x82, 0xd5, 0x50,
- 0xc9, 0x7a, 0x9e, 0x24, 0x0e, 0x26, 0x6e, 0x0c, 0xf4, 0xe1, 0xdb, 0xcc,
- 0x4b, 0x8f, 0xd3, 0x6f, 0x7f, 0xa1, 0x35, 0xa1, 0xe2, 0x3b, 0xcd, 0xb4,
- 0xe9, 0x26, 0xef, 0xf6, 0x6c, 0x3f, 0x9e, 0x58, 0x30, 0xf1, 0x0c, 0x63,
- 0xa6, 0x21, 0x9e, 0x0e, 0x94, 0xb3, 0xaf, 0x63, 0xed, 0x5b, 0x3e, 0x61,
- 0xf9, 0xfc, 0x68, 0xeb, 0x96, 0xf9, 0x10, 0x9c, 0xdf, 0xb6, 0xf6, 0x7e,
- 0x5a, 0xc3, 0xf3, 0xd6, 0xde, 0x0f, 0x3f, 0x4d, 0x0c, 0xeb, 0x6a, 0xf2,
- 0x63, 0x67, 0x05, 0x2a, 0xa3, 0xa6, 0x39, 0x1c, 0xb7, 0xf6, 0x1f, 0x5a,
- 0x63, 0xd6, 0xfd, 0xa3, 0xfc, 0x2c, 0xcd, 0xae, 0xff, 0x46, 0x30, 0x63,
- 0x38, 0x49, 0xf9, 0x77, 0x10, 0x07, 0xf4, 0x13, 0x07, 0xd4, 0x26, 0xd4,
- 0xe4, 0x6e, 0xa7, 0xcc, 0x69, 0x0a, 0x87, 0xaa, 0x79, 0xfd, 0x8e, 0x22,
- 0x0e, 0xa8, 0x3a, 0x25, 0xb3, 0x3f, 0x62, 0x45, 0xd8, 0x7b, 0x26, 0x3d,
- 0xc4, 0x01, 0x15, 0x93, 0x2e, 0x74, 0x13, 0x03, 0xb8, 0x89, 0xd9, 0xb7,
- 0xe5, 0x6a, 0xe1, 0x3d, 0xe1, 0x44, 0x24, 0xfe, 0x23, 0x1c, 0xa2, 0xbf,
- 0x1d, 0x8a, 0x79, 0x94, 0xf0, 0x2a, 0x07, 0x75, 0xf6, 0x2b, 0x1c, 0x0c,
- 0x38, 0x51, 0xa5, 0xbd, 0x86, 0x07, 0xbf, 0xa0, 0xf6, 0xf7, 0x67, 0x25,
- 0xce, 0x47, 0x5b, 0xbb, 0x4f, 0xd9, 0xb5, 0xdf, 0x77, 0x6a, 0x74, 0x59,
- 0x6a, 0x7f, 0xed, 0x86, 0x7e, 0x9c, 0x9e, 0xc1, 0x37, 0x57, 0x13, 0x64,
- 0xd6, 0x72, 0xcd, 0xfa, 0x78, 0x94, 0x3d, 0xb8, 0x3a, 0xd4, 0xa1, 0x44,
- 0x27, 0xaa, 0x98, 0x0f, 0x4e, 0xb3, 0xf6, 0x7b, 0x12, 0xd1, 0x40, 0xcc,
- 0x81, 0x1e, 0x37, 0x6d, 0xf3, 0x3e, 0xfb, 0xf1, 0x9f, 0xe6, 0xc2, 0xa4,
- 0x59, 0x06, 0x17, 0x6b, 0xff, 0xfb, 0x1a, 0x3e, 0x73, 0xd2, 0x0f, 0xdf,
- 0x71, 0x7a, 0x70, 0x35, 0x67, 0xd7, 0xfe, 0xea, 0x06, 0x73, 0xe4, 0x72,
- 0xdc, 0x87, 0x2b, 0x39, 0x9d, 0xfe, 0xd8, 0x8f, 0xa3, 0xac, 0xfd, 0x97,
- 0xb5, 0x00, 0x3e, 0xcc, 0xb5, 0xd0, 0x47, 0x83, 0xf8, 0x39, 0x71, 0xf2,
- 0x7a, 0xd6, 0xfe, 0xbb, 0xe8, 0x5f, 0x71, 0xd6, 0xfe, 0x36, 0x0b, 0x97,
- 0x64, 0x5a, 0xcf, 0x4c, 0x5b, 0xb5, 0xbf, 0xc1, 0xc1, 0xba, 0xe9, 0x46,
- 0x74, 0x99, 0x39, 0xc3, 0xfc, 0xc5, 0x26, 0x1f, 0x9f, 0xa5, 0xde, 0xf2,
- 0x1b, 0x30, 0x6b, 0xd5, 0xaa, 0x2d, 0xde, 0x5d, 0x5c, 0x7b, 0xa5, 0x15,
- 0x73, 0x26, 0x76, 0xac, 0xff, 0x6b, 0xfc, 0x41, 0x8d, 0x83, 0x3e, 0x99,
- 0xf0, 0xde, 0xc9, 0xb8, 0xf3, 0x27, 0x4a, 0xb3, 0x91, 0x18, 0xd7, 0xb9,
- 0xdd, 0x7b, 0x17, 0xfd, 0xe4, 0x96, 0xf5, 0xcc, 0x2a, 0x01, 0x3b, 0xe6,
- 0xda, 0x19, 0x73, 0x21, 0xc6, 0xdc, 0x6a, 0xc6, 0xdc, 0x93, 0x7a, 0x34,
- 0xb6, 0x85, 0xf8, 0xec, 0x95, 0x9c, 0xc4, 0x5d, 0x33, 0xe9, 0xaa, 0x94,
- 0x6b, 0x74, 0x40, 0xe2, 0x67, 0xc7, 0xfa, 0xd1, 0xb3, 0x95, 0x10, 0x5d,
- 0xe1, 0xb3, 0x95, 0xc4, 0x22, 0xcc, 0x52, 0x4b, 0xcb, 0xce, 0x68, 0xea,
- 0x36, 0x67, 0x74, 0xf8, 0x3d, 0xe5, 0x2d, 0xf3, 0x0d, 0xc6, 0xdc, 0x4e,
- 0xc6, 0xdc, 0x2e, 0xc6, 0x5c, 0x9b, 0x61, 0xe2, 0x85, 0xb8, 0xda, 0xdf,
- 0xe4, 0x88, 0xe8, 0x6d, 0x0e, 0xac, 0xae, 0x64, 0x09, 0xf1, 0x22, 0xda,
- 0xf5, 0x07, 0xe4, 0x7f, 0x49, 0x8f, 0xf6, 0xc6, 0x14, 0x89, 0xb3, 0x30,
- 0x3e, 0xa0, 0xdc, 0xe5, 0xc5, 0x38, 0x3b, 0x30, 0x77, 0xbe, 0xe8, 0x1b,
- 0x25, 0xd9, 0x9d, 0x78, 0x5e, 0x67, 0x5e, 0x5d, 0x21, 0xbe, 0xdb, 0x87,
- 0x09, 0xea, 0xd1, 0x1b, 0xed, 0xc3, 0x31, 0xd6, 0xcd, 0xfb, 0x58, 0xaf,
- 0xef, 0x37, 0x22, 0x2d, 0xdb, 0xd9, 0x27, 0x5d, 0x0a, 0xa9, 0xe1, 0xb0,
- 0xd2, 0x87, 0x41, 0xfa, 0xf0, 0x20, 0xeb, 0x4b, 0x9b, 0xf1, 0x4b, 0xa5,
- 0x83, 0x98, 0x62, 0x7f, 0x5e, 0xde, 0x53, 0x63, 0x69, 0xc7, 0x10, 0x06,
- 0x16, 0x24, 0xcf, 0x21, 0x70, 0x53, 0xa2, 0x0f, 0x53, 0x46, 0x19, 0xfa,
- 0x9a, 0x7b, 0x94, 0x3b, 0xf2, 0x32, 0xa7, 0x63, 0x6c, 0x1a, 0x8c, 0x5d,
- 0x8b, 0x5f, 0x05, 0xb9, 0x68, 0x0f, 0x32, 0x12, 0xab, 0xc6, 0x2e, 0xe5,
- 0xae, 0x39, 0x89, 0xf7, 0x3e, 0xa5, 0x4f, 0xe2, 0xd9, 0x48, 0x29, 0x77,
- 0x4b, 0x7c, 0x5b, 0xb3, 0x6d, 0xc9, 0x01, 0xb2, 0xf7, 0x71, 0x3b, 0xf1,
- 0x1e, 0x18, 0x5f, 0xce, 0xef, 0x84, 0x18, 0x83, 0x6d, 0x65, 0x0e, 0xfa,
- 0x69, 0x84, 0xb6, 0x73, 0xa0, 0x5d, 0xff, 0xb2, 0x99, 0x0e, 0x0c, 0x30,
- 0xa6, 0xfa, 0x70, 0xd4, 0x08, 0x99, 0x97, 0x2d, 0x1c, 0x53, 0xca, 0xf1,
- 0x5b, 0x58, 0xeb, 0x56, 0xc1, 0xa3, 0x49, 0x7d, 0xf7, 0x21, 0x56, 0xe3,
- 0x41, 0x85, 0x26, 0xb5, 0x27, 0xd3, 0xba, 0x78, 0x42, 0x91, 0x3e, 0xa5,
- 0x18, 0xeb, 0x5b, 0xf0, 0x00, 0x73, 0xc2, 0xbe, 0xf8, 0xbd, 0xb8, 0x3f,
- 0x50, 0x01, 0x3f, 0xf5, 0xf4, 0x50, 0xc0, 0xc7, 0x5c, 0xfb, 0x7b, 0x45,
- 0x3a, 0x7f, 0x51, 0x56, 0xec, 0xbf, 0xaf, 0x61, 0xb0, 0x5a, 0xc6, 0xd8,
- 0xe6, 0x19, 0x99, 0x27, 0xa5, 0x5a, 0x43, 0x33, 0x1a, 0xfc, 0xec, 0x7b,
- 0xb7, 0xc4, 0xd5, 0xd4, 0x16, 0x67, 0x44, 0x7a, 0x9a, 0x8c, 0x9f, 0xf8,
- 0x2f, 0x17, 0x8d, 0xf6, 0x36, 0x89, 0x8e, 0xb5, 0x10, 0x3a, 0xa9, 0xa7,
- 0xee, 0x5c, 0x90, 0x31, 0xe4, 0x28, 0x17, 0x2c, 0x95, 0xcc, 0x5d, 0xa7,
- 0x15, 0x22, 0xad, 0xd0, 0x8c, 0xe0, 0xba, 0x14, 0x71, 0x9d, 0xc6, 0x38,
- 0x34, 0xcd, 0xcd, 0xc4, 0x73, 0xbe, 0x53, 0x32, 0x97, 0x8a, 0x4c, 0x10,
- 0x03, 0x37, 0x11, 0x1f, 0xf7, 0xd1, 0xab, 0xcd, 0x5b, 0xea, 0xa3, 0x7a,
- 0x9b, 0x82, 0xc7, 0xe6, 0x9b, 0xe1, 0x71, 0x92, 0xe6, 0x3b, 0xb9, 0x00,
- 0x2e, 0xe7, 0x42, 0x78, 0x9b, 0xb4, 0x2f, 0x59, 0xb4, 0xeb, 0xf0, 0xb3,
- 0x62, 0x0e, 0x8b, 0x33, 0x87, 0x6d, 0xcd, 0x2a, 0xf4, 0xd7, 0x30, 0x46,
- 0xf4, 0xbf, 0xfa, 0xec, 0xd2, 0xcd, 0x1e, 0xea, 0x4d, 0x64, 0x71, 0xf1,
- 0x73, 0x1c, 0x0f, 0x59, 0x39, 0xfb, 0xb5, 0xcf, 0x66, 0x6b, 0x68, 0x2b,
- 0xea, 0xbe, 0xba, 0xf8, 0xde, 0xba, 0xd9, 0x3f, 0x2f, 0xca, 0xdb, 0x53,
- 0xb4, 0x35, 0x71, 0x9b, 0x71, 0x9e, 0xd7, 0x04, 0x47, 0x69, 0x70, 0x9c,
- 0x8a, 0xa1, 0xec, 0xd4, 0x35, 0xfe, 0x35, 0x89, 0x19, 0x56, 0xde, 0xc7,
- 0xbe, 0x4b, 0x9e, 0x1e, 0x21, 0x5e, 0x34, 0xc9, 0xd3, 0x55, 0x8b, 0x97,
- 0x20, 0x79, 0xf9, 0xe4, 0xb3, 0x12, 0xb6, 0x0c, 0x5d, 0x7b, 0x27, 0x40,
- 0x7d, 0xe0, 0xd1, 0x10, 0xf5, 0x79, 0x65, 0xa3, 0x3c, 0xe7, 0xc3, 0x1d,
- 0xb9, 0x44, 0xb9, 0xe4, 0x79, 0xaf, 0xb6, 0x05, 0x7b, 0xe7, 0x3e, 0xaf,
- 0xf7, 0x20, 0x6d, 0x11, 0xa0, 0xf1, 0xe4, 0xde, 0x17, 0xd5, 0xd4, 0x3f,
- 0x42, 0x8a, 0x3d, 0xd3, 0x23, 0xd9, 0x34, 0x1e, 0xca, 0x7e, 0xcb, 0xda,
- 0xcb, 0x5b, 0xb7, 0x01, 0xfb, 0x49, 0xff, 0x60, 0x35, 0xe3, 0xe8, 0x7f,
- 0xc4, 0xa3, 0x82, 0xa5, 0x76, 0x55, 0x42, 0xea, 0x6e, 0xb4, 0xe5, 0x36,
- 0xc5, 0x44, 0x59, 0x1c, 0xc3, 0xed, 0xcd, 0xd1, 0xd8, 0x65, 0x3c, 0x66,
- 0xca, 0x5c, 0xdc, 0x59, 0xac, 0xc1, 0xc4, 0xaf, 0x4a, 0x3b, 0xeb, 0x70,
- 0x5b, 0x11, 0x53, 0x6d, 0xcd, 0xbf, 0xf5, 0xb9, 0xd9, 0x83, 0xf4, 0xed,
- 0x52, 0x7b, 0xbc, 0x4a, 0x1b, 0xd7, 0x39, 0xca, 0x9c, 0xfd, 0xbc, 0xfe,
- 0x52, 0x88, 0x95, 0x19, 0xae, 0xf5, 0x0a, 0x0e, 0x11, 0x3f, 0xa5, 0x83,
- 0x26, 0x76, 0xf1, 0xf3, 0x00, 0x71, 0xd6, 0xbb, 0x7a, 0x15, 0x66, 0x03,
- 0x01, 0x62, 0x4b, 0xe6, 0x60, 0xc7, 0xdf, 0x49, 0x4d, 0x88, 0x85, 0x1d,
- 0xb2, 0x57, 0xff, 0x6f, 0xed, 0xdf, 0xac, 0x27, 0x96, 0x11, 0xd9, 0xbd,
- 0x0a, 0x73, 0x68, 0x0c, 0xc4, 0x37, 0x7b, 0xf5, 0x42, 0xd8, 0x81, 0xe4,
- 0x55, 0x07, 0xd4, 0xd3, 0xef, 0xb0, 0x1f, 0x7c, 0xa4, 0x5e, 0x3d, 0xdd,
- 0xea, 0xd4, 0x90, 0x9a, 0xf2, 0xe0, 0xe1, 0xa9, 0x0e, 0x54, 0x5b, 0x73,
- 0xa4, 0x71, 0xda, 0xcc, 0xc1, 0x3e, 0x6c, 0xf4, 0x53, 0x17, 0xfb, 0xb1,
- 0xab, 0x1b, 0x1e, 0x45, 0x8b, 0x75, 0x7d, 0x0c, 0xfb, 0xb3, 0x5e, 0xa5,
- 0x3b, 0xeb, 0x42, 0xc7, 0x5d, 0x8f, 0xc2, 0xbd, 0x7e, 0x80, 0x7c, 0xc9,
- 0x75, 0xf9, 0xfb, 0x6e, 0xf6, 0x71, 0xc2, 0x5f, 0x19, 0xc2, 0xab, 0xc8,
- 0xdb, 0x7a, 0x0d, 0x23, 0x53, 0x2e, 0x65, 0xb7, 0xf1, 0x37, 0xe6, 0x55,
- 0x6b, 0x6f, 0x48, 0xae, 0x55, 0xc8, 0x99, 0x01, 0x3e, 0x23, 0x39, 0x67,
- 0x10, 0x59, 0xc6, 0xf6, 0xdd, 0xd6, 0xfb, 0xa7, 0xca, 0x6c, 0x99, 0x92,
- 0xec, 0x6f, 0xdb, 0xe9, 0x1f, 0xf2, 0x4c, 0x5b, 0xf1, 0xda, 0x76, 0x8f,
- 0x7d, 0x2e, 0x41, 0xec, 0x3e, 0x88, 0x5b, 0x69, 0x84, 0xfa, 0xa8, 0xf8,
- 0xd8, 0x20, 0xea, 0x73, 0x4c, 0xa8, 0xab, 0x6c, 0x7e, 0x1f, 0x34, 0x0a,
- 0xec, 0x4d, 0x35, 0xe6, 0x4d, 0xea, 0x6e, 0xa5, 0xbc, 0x4f, 0x47, 0xfd,
- 0xb5, 0xf7, 0x4b, 0xf5, 0x54, 0x70, 0xe9, 0x17, 0xdd, 0xff, 0x4d, 0xc8,
- 0x3d, 0x97, 0xf6, 0x87, 0x8c, 0xe3, 0x68, 0x6f, 0xa5, 0x43, 0xfc, 0xe7,
- 0x0f, 0x71, 0xff, 0x1c, 0x1b, 0xd7, 0x0a, 0xa1, 0x4f, 0xdc, 0x6b, 0xb8,
- 0x94, 0x2e, 0xe6, 0x9f, 0x03, 0x53, 0x8e, 0x3b, 0xca, 0xf0, 0xe7, 0x66,
- 0xf9, 0xca, 0x11, 0xd4, 0xc7, 0xc7, 0xf8, 0xbc, 0x82, 0x76, 0x62, 0xc8,
- 0x27, 0xf4, 0xad, 0xe8, 0xa8, 0x91, 0x1c, 0xf0, 0xbc, 0x39, 0xd8, 0x27,
- 0x3a, 0x54, 0xb0, 0x8d, 0xd7, 0x5f, 0xa0, 0x7d, 0x9f, 0xd6, 0x5d, 0xa8,
- 0x5f, 0x21, 0x33, 0x41, 0x75, 0x3a, 0x89, 0x3d, 0x1e, 0x7b, 0x8f, 0x2c,
- 0x6d, 0x56, 0x6b, 0xda, 0xf0, 0x9d, 0x8e, 0xfa, 0xe9, 0x37, 0xe9, 0x4f,
- 0x6d, 0xeb, 0x6f, 0xbc, 0x57, 0xd2, 0x89, 0x8e, 0xd0, 0xfa, 0xe7, 0x4c,
- 0xdc, 0x34, 0x8a, 0xc0, 0xfa, 0x1b, 0xed, 0x5f, 0xe2, 0xfb, 0x30, 0x63,
- 0x10, 0xe9, 0xea, 0x84, 0xcc, 0x89, 0xa2, 0xa4, 0x73, 0x18, 0xbf, 0x9f,
- 0x1f, 0xc3, 0xa1, 0xac, 0xc8, 0xb9, 0x60, 0xf9, 0xb6, 0xb6, 0xfe, 0xba,
- 0x6c, 0x0f, 0x66, 0xa3, 0x03, 0x55, 0x45, 0xd9, 0x0e, 0xb2, 0x1f, 0xa9,
- 0x64, 0x8e, 0x7d, 0x80, 0x3a, 0x1d, 0xb6, 0x74, 0xda, 0x07, 0x3d, 0x77,
- 0x9d, 0xee, 0x10, 0xe9, 0x7a, 0x13, 0xa2, 0x37, 0xd9, 0x97, 0x63, 0x2f,
- 0x40, 0xba, 0xfb, 0x6e, 0xa0, 0x3b, 0xa8, 0x5f, 0xa7, 0xbb, 0x37, 0x1b,
- 0x3d, 0xed, 0x28, 0xd2, 0xfd, 0xc6, 0x5c, 0x89, 0x46, 0x1a, 0x3b, 0xd7,
- 0xa7, 0x91, 0xdb, 0x7c, 0xd0, 0x3c, 0x68, 0xe9, 0xe3, 0xfb, 0xd6, 0xf5,
- 0x6d, 0xf5, 0x12, 0x0f, 0xfc, 0x33, 0xa1, 0x59, 0x67, 0x00, 0x6c, 0x1c,
- 0x76, 0x63, 0x7c, 0xa8, 0x6f, 0x75, 0x3b, 0x93, 0x8c, 0xe3, 0xa0, 0x67,
- 0xfb, 0xe7, 0x66, 0x1f, 0x1d, 0xec, 0xd7, 0x3a, 0x8d, 0x1e, 0x6f, 0x97,
- 0xe1, 0x21, 0x06, 0xab, 0x54, 0xb6, 0x65, 0x65, 0x06, 0x22, 0xb1, 0x5c,
- 0xc4, 0xc5, 0x79, 0xe9, 0x0b, 0xef, 0x61, 0xcf, 0xb0, 0x81, 0xf6, 0x1d,
- 0xc0, 0x44, 0x7e, 0x40, 0x49, 0x06, 0xb9, 0x8e, 0x21, 0x75, 0x05, 0xac,
- 0x79, 0xbd, 0xa8, 0xa4, 0x2f, 0x05, 0x13, 0xd3, 0x89, 0x93, 0xf5, 0x26,
- 0x88, 0x51, 0x3c, 0x2b, 0x12, 0xb3, 0x89, 0x5d, 0xf5, 0x4e, 0x1c, 0xb7,
- 0xb0, 0x98, 0x3a, 0xcb, 0xdf, 0x69, 0x89, 0x99, 0x3b, 0xb3, 0x52, 0xc7,
- 0x08, 0x27, 0xb5, 0x11, 0xfc, 0x63, 0xbc, 0x30, 0x5c, 0x83, 0xe4, 0x7d,
- 0x35, 0x90, 0x1e, 0x63, 0x02, 0x7f, 0xa9, 0x85, 0x3c, 0xfd, 0x79, 0x97,
- 0xd2, 0x6d, 0xcc, 0x7b, 0x77, 0x18, 0x7e, 0xf8, 0xd8, 0xbf, 0xf5, 0x38,
- 0x23, 0xec, 0x39, 0xac, 0x19, 0x7d, 0xeb, 0xad, 0xb9, 0x7e, 0x6f, 0xbb,
- 0x61, 0xe7, 0xc2, 0x5b, 0x66, 0x3d, 0xde, 0x8e, 0x99, 0x48, 0x68, 0xc2,
- 0xc2, 0x62, 0x07, 0x5b, 0x23, 0x39, 0xd3, 0x7c, 0x55, 0x2f, 0x5c, 0x2d,
- 0xb7, 0xbe, 0x4f, 0xb7, 0xc6, 0x72, 0x4d, 0xd8, 0x43, 0xfc, 0xd4, 0x36,
- 0xd3, 0x04, 0x7d, 0x06, 0x38, 0x31, 0x15, 0xc2, 0xba, 0xac, 0x7a, 0x3a,
- 0xe5, 0xec, 0xc7, 0xf4, 0x42, 0x17, 0xb2, 0x79, 0xef, 0x72, 0xd8, 0x41,
- 0x8c, 0x1d, 0x77, 0xe0, 0x0e, 0x7d, 0x83, 0x52, 0xb0, 0x62, 0x5a, 0xc1,
- 0xdd, 0xfa, 0x2e, 0x65, 0xc0, 0xc2, 0x14, 0xf3, 0xc4, 0x22, 0x0a, 0x6e,
- 0xb2, 0x72, 0xef, 0xc9, 0xd6, 0x38, 0xf1, 0xf7, 0x1d, 0x59, 0xa9, 0xef,
- 0x26, 0x2e, 0xc6, 0xa9, 0x97, 0x78, 0xba, 0xdf, 0xcd, 0x7e, 0xe8, 0xa0,
- 0xa2, 0xf6, 0xea, 0x8a, 0x8d, 0xf1, 0x6e, 0x9b, 0xb7, 0x71, 0xe1, 0xad,
- 0xf3, 0xcd, 0x5e, 0xc9, 0x41, 0xed, 0xba, 0x1a, 0x72, 0x39, 0x02, 0x18,
- 0xb6, 0x68, 0xa4, 0x5b, 0xf5, 0xf9, 0x32, 0xac, 0xd6, 0xfa, 0x70, 0xda,
- 0x92, 0x61, 0xa2, 0x75, 0x0b, 0xb1, 0xf6, 0x93, 0x46, 0x3f, 0x7b, 0x65,
- 0xd9, 0x37, 0x8d, 0xc4, 0x5a, 0x9c, 0x6d, 0xc4, 0xb3, 0x91, 0xf0, 0xb2,
- 0x92, 0x54, 0xd2, 0xae, 0xc6, 0xe4, 0x3c, 0x58, 0x51, 0x6a, 0xec, 0xfa,
- 0x26, 0x32, 0x46, 0x89, 0xb3, 0xda, 0xa6, 0xbc, 0xcb, 0x49, 0xd8, 0x73,
- 0x9e, 0x4e, 0xfd, 0xff, 0xe0, 0x52, 0x50, 0x9d, 0x48, 0x92, 0xef, 0x0e,
- 0xe6, 0xdd, 0x42, 0x9f, 0x8b, 0xf7, 0x65, 0xbe, 0x37, 0xdc, 0x3a, 0x9e,
- 0x41, 0xc1, 0x99, 0x90, 0x1e, 0x0b, 0xfe, 0xde, 0x3c, 0x64, 0xd6, 0xc4,
- 0x3e, 0xe3, 0x53, 0xb3, 0xb4, 0xc7, 0xd4, 0x33, 0x63, 0xef, 0x9f, 0x65,
- 0x16, 0x5c, 0xfe, 0x1d, 0x46, 0x33, 0x8e, 0xe7, 0x5d, 0x37, 0xd0, 0x8e,
- 0x4e, 0xdc, 0xe2, 0x70, 0x20, 0xba, 0xfe, 0x6e, 0xa5, 0xb8, 0x07, 0xc5,
- 0x3c, 0x91, 0xb2, 0x6a, 0x62, 0x19, 0xe5, 0xbc, 0x70, 0x52, 0xd6, 0xf8,
- 0x56, 0xeb, 0xf8, 0x49, 0xa9, 0x91, 0xc3, 0xad, 0x21, 0x43, 0xed, 0x95,
- 0x9e, 0xb0, 0x9a, 0x7a, 0xfa, 0x68, 0x52, 0x6a, 0xf0, 0x14, 0x6b, 0xb0,
- 0xba, 0xdc, 0xae, 0x48, 0x1d, 0x53, 0x63, 0x5e, 0xa7, 0x03, 0x57, 0x1a,
- 0xd4, 0xfe, 0x1f, 0x40, 0x1d, 0xb0, 0xe7, 0x8a, 0x8f, 0xb6, 0x36, 0x16,
- 0xf1, 0xf0, 0x6d, 0xf3, 0x83, 0x72, 0xee, 0xc4, 0xd2, 0x71, 0x53, 0x4e,
- 0xb0, 0xb1, 0x69, 0xbe, 0x1c, 0xef, 0x21, 0x6e, 0x10, 0x6c, 0x2c, 0xd7,
- 0x27, 0x5b, 0x1b, 0x66, 0x3d, 0xe4, 0x4d, 0xc1, 0x7b, 0x5a, 0x0f, 0x7d,
- 0xaf, 0xc4, 0xa3, 0x8d, 0x9b, 0xb7, 0x13, 0x37, 0x3b, 0x13, 0x6a, 0xcb,
- 0x56, 0xe2, 0x66, 0x8d, 0xfd, 0x84, 0x0b, 0x7d, 0x78, 0xc2, 0xb0, 0x7b,
- 0x0a, 0xc1, 0xce, 0xe6, 0x49, 0x35, 0x29, 0xb8, 0xf9, 0xea, 0x06, 0x60,
- 0x37, 0x71, 0xf3, 0x72, 0xc6, 0x85, 0x7e, 0xe2, 0xe6, 0x8f, 0x98, 0x82,
- 0xee, 0x24, 0x6e, 0xbe, 0x42, 0x8c, 0x75, 0x3e, 0xfe, 0x73, 0x7c, 0xa3,
- 0x38, 0x3b, 0xdb, 0x4b, 0xec, 0x9c, 0x0c, 0xde, 0x88, 0x9d, 0xff, 0xe2,
- 0x5f, 0x60, 0xe7, 0x3d, 0xc4, 0x84, 0x3d, 0x59, 0xd9, 0x67, 0x1a, 0x6d,
- 0x7d, 0xe3, 0x94, 0x9c, 0x6d, 0xb9, 0x0d, 0xef, 0x9e, 0x1c, 0x1d, 0x22,
- 0x56, 0xc6, 0x58, 0xbc, 0x1f, 0x99, 0x19, 0xac, 0x22, 0x2e, 0x78, 0xd9,
- 0xc9, 0x75, 0xd7, 0xc5, 0x55, 0xfd, 0x4d, 0x25, 0xda, 0xd5, 0x8f, 0x28,
- 0xfb, 0x66, 0x75, 0x99, 0x26, 0x4c, 0xba, 0x12, 0xc4, 0xc6, 0xac, 0x81,
- 0xab, 0x89, 0x9d, 0xab, 0x16, 0x81, 0xda, 0x45, 0x1b, 0x3b, 0xcb, 0xdc,
- 0xac, 0x2a, 0x8a, 0x3f, 0x22, 0x76, 0x66, 0xaf, 0xcb, 0x50, 0x5b, 0x6c,
- 0x62, 0x8c, 0x2a, 0x38, 0x1a, 0xf5, 0xa1, 0x67, 0x8a, 0xb8, 0xc7, 0x9a,
- 0x9b, 0x99, 0x23, 0x3f, 0xd6, 0xfb, 0x71, 0x6c, 0xc1, 0x9e, 0x9b, 0x75,
- 0x12, 0xbf, 0xb9, 0xa2, 0x41, 0x94, 0x2f, 0xba, 0xf0, 0x1c, 0xf1, 0xf3,
- 0x36, 0xda, 0xf9, 0x0c, 0xf1, 0xf3, 0x9e, 0x1b, 0x66, 0x67, 0xb3, 0x8b,
- 0x78, 0x95, 0x58, 0xbe, 0xae, 0x16, 0x51, 0x99, 0x8b, 0x98, 0x57, 0x36,
- 0xfa, 0x70, 0xce, 0xc2, 0xcf, 0xde, 0xe5, 0xb4, 0x62, 0xcb, 0x56, 0x46,
- 0x5b, 0x88, 0x5d, 0x1d, 0xb4, 0x6b, 0xdb, 0x49, 0xb5, 0xeb, 0x25, 0xea,
- 0xa2, 0x31, 0x7a, 0xde, 0xb2, 0xc7, 0x60, 0x5c, 0x66, 0x2c, 0x43, 0xad,
- 0x72, 0xfe, 0xaa, 0x82, 0xf6, 0xee, 0x9e, 0x8c, 0x24, 0x3f, 0x80, 0x1d,
- 0x93, 0xb1, 0x5c, 0x59, 0xb1, 0x1e, 0xca, 0xbd, 0x09, 0xde, 0x4b, 0xa2,
- 0x6b, 0xa3, 0xed, 0xdf, 0xb1, 0xdc, 0x71, 0x62, 0x57, 0xd9, 0x5b, 0x0d,
- 0xf8, 0x3b, 0x8d, 0x2e, 0x4c, 0x1b, 0x61, 0x94, 0x9f, 0x2b, 0xee, 0xd1,
- 0x9e, 0x93, 0x33, 0x7b, 0x8f, 0xb6, 0x06, 0xbe, 0x53, 0xc2, 0x84, 0x49,
- 0xe2, 0xbb, 0xa0, 0xe7, 0x8e, 0xbc, 0xe0, 0xc5, 0x5e, 0x1c, 0x33, 0xd4,
- 0xd0, 0x4f, 0x18, 0x13, 0xf7, 0xc9, 0xfe, 0xfc, 0x0d, 0x33, 0xaa, 0x87,
- 0x79, 0xcf, 0xf8, 0xdc, 0x8c, 0x2a, 0x95, 0xc5, 0xaf, 0x9c, 0xcd, 0xe5,
- 0x70, 0xac, 0x93, 0x19, 0x89, 0x1a, 0x1a, 0xc3, 0x63, 0xc4, 0x1c, 0xbf,
- 0x54, 0x7c, 0x9a, 0x6b, 0xa8, 0xc9, 0xa9, 0x86, 0xe6, 0x15, 0x1f, 0xdf,
- 0xbd, 0x87, 0xf9, 0xed, 0x1e, 0xfa, 0x46, 0x64, 0xb9, 0x42, 0x71, 0xe2,
- 0xd2, 0x97, 0x2d, 0x3c, 0xea, 0xed, 0xe5, 0xb5, 0xe9, 0x7c, 0x09, 0xd7,
- 0xf4, 0x09, 0xaf, 0xe8, 0x9c, 0xb2, 0x73, 0x88, 0x96, 0xf3, 0x2e, 0x5f,
- 0x82, 0x2d, 0x5b, 0x25, 0x65, 0x7d, 0x60, 0x32, 0x60, 0x0e, 0xac, 0x94,
- 0x18, 0xd6, 0xb0, 0xd3, 0x10, 0xff, 0x1a, 0x24, 0x9f, 0x7d, 0x38, 0x62,
- 0xac, 0x66, 0xef, 0x26, 0xf3, 0xd2, 0x26, 0x62, 0xeb, 0x5e, 0xd6, 0x60,
- 0xd3, 0x4c, 0xe9, 0x69, 0xb3, 0x69, 0x93, 0xa6, 0xe7, 0x94, 0x42, 0x4d,
- 0x88, 0xf8, 0x66, 0x3d, 0x6b, 0x77, 0x5b, 0xbe, 0x09, 0x6f, 0x9e, 0xd1,
- 0xe8, 0x9b, 0xed, 0xc4, 0xef, 0xbd, 0xb8, 0x97, 0xf2, 0x7c, 0x23, 0xff,
- 0x4d, 0x24, 0xbf, 0xee, 0xc2, 0xc4, 0x54, 0x12, 0x5b, 0xd6, 0x8f, 0xe0,
- 0xd2, 0xef, 0x78, 0x98, 0xab, 0x7c, 0x78, 0x72, 0x4a, 0xf2, 0x6b, 0x09,
- 0x6f, 0xdf, 0x88, 0x45, 0x3c, 0x08, 0x5b, 0x38, 0xe4, 0x8b, 0xef, 0xd9,
- 0x18, 0xc5, 0xcb, 0x5e, 0xb8, 0xf4, 0x3e, 0xf3, 0xd0, 0xfa, 0x7f, 0x81,
- 0x67, 0x88, 0x5b, 0x88, 0x05, 0x2a, 0x62, 0xd6, 0xf9, 0xb8, 0x12, 0xde,
- 0x75, 0xd1, 0x07, 0x24, 0xa6, 0x57, 0x33, 0xd6, 0x4d, 0x62, 0xe7, 0xe5,
- 0xe2, 0xfc, 0xf2, 0xed, 0x93, 0xea, 0xd2, 0x11, 0x44, 0x88, 0xa1, 0x31,
- 0x28, 0xd8, 0xcd, 0x49, 0xbc, 0x7b, 0x25, 0x1a, 0xd5, 0xcf, 0x11, 0xef,
- 0x8e, 0xd2, 0xd6, 0x2e, 0x4d, 0x7c, 0x33, 0x80, 0xb2, 0xc5, 0x10, 0x7d,
- 0x52, 0xe6, 0x97, 0x7f, 0xe5, 0xb5, 0xe7, 0x97, 0x32, 0x33, 0x97, 0xf3,
- 0x23, 0xe8, 0x28, 0x63, 0xef, 0x56, 0xae, 0xa4, 0x99, 0x93, 0x67, 0xbd,
- 0xbb, 0x99, 0xdf, 0xfb, 0x8d, 0xa0, 0x7f, 0x77, 0x3e, 0xc0, 0xdf, 0x3a,
- 0x7f, 0x7f, 0x7e, 0x07, 0x9f, 0x0f, 0xf1, 0x33, 0x8c, 0x6c, 0x2e, 0x52,
- 0x21, 0xcd, 0x40, 0x36, 0x67, 0xe7, 0xbc, 0x70, 0xee, 0x90, 0x57, 0xb0,
- 0x66, 0xdb, 0x94, 0xfd, 0x5d, 0xbb, 0xe1, 0xfb, 0xe7, 0x31, 0xbf, 0x9b,
- 0x7c, 0x9f, 0x39, 0xa9, 0xe1, 0xa3, 0x93, 0x16, 0xe6, 0x2f, 0x10, 0xf3,
- 0x0f, 0xbb, 0x9d, 0x82, 0x35, 0x7f, 0x61, 0x9e, 0x8f, 0x46, 0x07, 0xe6,
- 0xe8, 0x07, 0x3d, 0xa4, 0xeb, 0xd0, 0x82, 0x16, 0xbf, 0x36, 0x9f, 0xf6,
- 0xcc, 0xf7, 0xf2, 0xc9, 0x18, 0xde, 0xb9, 0x3e, 0x63, 0xfd, 0xa4, 0xcc,
- 0x9a, 0x15, 0xe3, 0xb1, 0x77, 0x37, 0xc1, 0xd3, 0xc2, 0x7e, 0xd3, 0xcd,
- 0xe7, 0x43, 0xd6, 0xf3, 0x32, 0xf3, 0xbd, 0x8e, 0x9d, 0x3f, 0xba, 0xfe,
- 0xce, 0x61, 0x76, 0x6a, 0x9e, 0xf3, 0x8c, 0x2d, 0xa7, 0xf5, 0x9c, 0xcc,
- 0x65, 0xbd, 0xcb, 0xb0, 0xe2, 0x6b, 0x88, 0x32, 0x89, 0x7d, 0x0f, 0x99,
- 0xb6, 0xdf, 0x06, 0xfd, 0x3b, 0x19, 0x0f, 0xdf, 0xa6, 0x7d, 0x76, 0x9e,
- 0xab, 0xf3, 0xdf, 0x6d, 0xec, 0xb2, 0x64, 0xbe, 0xfb, 0x9c, 0xd4, 0x24,
- 0xb9, 0xff, 0x40, 0x85, 0x60, 0xef, 0x27, 0x59, 0xb3, 0x46, 0x0d, 0xd9,
- 0x03, 0x80, 0xe2, 0x4a, 0x1c, 0x41, 0xe7, 0x74, 0x18, 0x6f, 0xeb, 0xde,
- 0xe2, 0x59, 0x17, 0x89, 0xc9, 0x69, 0xc6, 0x64, 0x10, 0x63, 0x46, 0x24,
- 0xfc, 0x36, 0xf1, 0x69, 0x9a, 0x0c, 0x1f, 0xcb, 0x3a, 0xf1, 0x36, 0x31,
- 0x23, 0x14, 0xfb, 0xac, 0xa8, 0xfd, 0x6e, 0xe9, 0xef, 0x4a, 0x84, 0x6b,
- 0x22, 0x2d, 0x07, 0x50, 0x87, 0x0c, 0x73, 0xbe, 0x57, 0xfb, 0x21, 0x8e,
- 0x9f, 0x70, 0xe0, 0x7e, 0xf6, 0x7d, 0xc9, 0xbb, 0x74, 0x7e, 0x6f, 0x1c,
- 0x7a, 0x1f, 0xff, 0x68, 0xce, 0xca, 0x79, 0x2c, 0x45, 0xce, 0x7c, 0x7c,
- 0x62, 0xd6, 0x6a, 0x5a, 0xe1, 0x07, 0xd0, 0x52, 0x57, 0xd1, 0x38, 0xbc,
- 0x8c, 0x0f, 0xcc, 0x02, 0xef, 0xbd, 0xc7, 0xf8, 0x79, 0x49, 0x8f, 0x84,
- 0x1c, 0x14, 0xa6, 0x10, 0x74, 0xe2, 0x3e, 0x5d, 0xe6, 0x29, 0xea, 0xf0,
- 0xb3, 0x50, 0x87, 0x2e, 0x28, 0x72, 0x86, 0xe7, 0x92, 0x99, 0xae, 0x91,
- 0x75, 0x15, 0xac, 0x5b, 0xd3, 0xd8, 0x55, 0x06, 0xb5, 0xc5, 0xad, 0x68,
- 0xfa, 0xfb, 0xca, 0xff, 0x32, 0x0b, 0xc1, 0x4f, 0xcc, 0x77, 0xb4, 0x12,
- 0x5d, 0x35, 0xec, 0x71, 0x96, 0x78, 0xab, 0xc3, 0x71, 0x43, 0xf6, 0xf1,
- 0x7e, 0x88, 0xfb, 0x4f, 0xb8, 0xd0, 0x1e, 0xff, 0xb9, 0x99, 0x0e, 0x0a,
- 0xcd, 0x50, 0x25, 0x2a, 0x84, 0xbe, 0x3d, 0xdb, 0x7e, 0x31, 0x0f, 0xa5,
- 0xc3, 0x10, 0xbc, 0x2c, 0x7e, 0x3a, 0x0d, 0xd3, 0x90, 0x99, 0xa2, 0x89,
- 0x3b, 0xe3, 0x23, 0x78, 0x2f, 0x9e, 0xfc, 0x4f, 0x1e, 0xa8, 0x4b, 0x97,
- 0x9d, 0x6a, 0xa1, 0xc9, 0x19, 0x56, 0xbc, 0x0d, 0xda, 0x70, 0x83, 0x55,
- 0x6f, 0x2e, 0xb2, 0x77, 0xf2, 0x31, 0xb7, 0x48, 0x8f, 0x39, 0x8d, 0xc5,
- 0xc9, 0x34, 0x5c, 0xc4, 0x76, 0xa3, 0xcd, 0x6a, 0xff, 0x33, 0x8a, 0x1a,
- 0x3a, 0xa8, 0x84, 0x95, 0x7b, 0xb5, 0x14, 0x9e, 0xd3, 0xa3, 0xc9, 0x36,
- 0xa5, 0xce, 0xd3, 0x95, 0x2f, 0xd1, 0x6e, 0x27, 0x56, 0x51, 0x0b, 0x97,
- 0x9d, 0xe5, 0xa8, 0xdd, 0xa0, 0x75, 0x95, 0x3b, 0xd5, 0xd4, 0xd7, 0x18,
- 0x5f, 0xdb, 0xf3, 0x05, 0xef, 0xfb, 0x51, 0x07, 0xd6, 0x5a, 0xfb, 0x0d,
- 0x99, 0xe2, 0xbc, 0x74, 0x1a, 0xdd, 0x93, 0xe6, 0x96, 0x8b, 0x71, 0x35,
- 0xf4, 0x8c, 0x92, 0xde, 0xed, 0x23, 0xa6, 0x79, 0x00, 0x5a, 0x78, 0x81,
- 0x75, 0xaa, 0x3d, 0xef, 0xc0, 0x2d, 0xa7, 0x84, 0x66, 0x86, 0x34, 0x8f,
- 0xa0, 0xfc, 0x84, 0xb9, 0x65, 0xb7, 0xae, 0xa6, 0x2e, 0x3b, 0xd3, 0xff,
- 0xbd, 0x96, 0x7a, 0xeb, 0x50, 0x64, 0xbf, 0x6d, 0x84, 0xb8, 0x62, 0x44,
- 0xce, 0xcd, 0xc5, 0xfe, 0x98, 0x98, 0xe2, 0x5b, 0xf4, 0x55, 0x67, 0xc2,
- 0x4f, 0x3e, 0xd5, 0xd8, 0x1c, 0x64, 0xce, 0x1e, 0xc6, 0x65, 0x3d, 0xed,
- 0xed, 0x6c, 0x88, 0x11, 0x9b, 0x85, 0x58, 0x07, 0xc3, 0x38, 0x46, 0x8c,
- 0x77, 0x24, 0x5f, 0x86, 0x42, 0x40, 0x23, 0x36, 0xeb, 0x85, 0x63, 0xd2,
- 0xa7, 0xcc, 0x67, 0x22, 0x7a, 0x3b, 0xfe, 0x33, 0x0a, 0x21, 0x71, 0x91,
- 0x23, 0xf0, 0x9d, 0xf8, 0x7b, 0xb3, 0x4a, 0xd3, 0x5a, 0x26, 0x15, 0xae,
- 0xfb, 0x54, 0x88, 0x3a, 0xe6, 0x7b, 0x72, 0xbe, 0xc5, 0xe8, 0xc1, 0xbd,
- 0x93, 0x41, 0xbe, 0x5f, 0x85, 0x75, 0x27, 0xc2, 0xb8, 0x12, 0xbf, 0x19,
- 0x85, 0x1a, 0x1b, 0x03, 0x79, 0x35, 0xfa, 0x11, 0xfb, 0xac, 0x34, 0x7b,
- 0x4a, 0xd9, 0x63, 0x3a, 0x62, 0x48, 0x7f, 0xee, 0xe2, 0x77, 0x1f, 0x7f,
- 0x45, 0x9f, 0xdf, 0x2a, 0x62, 0x9d, 0xa9, 0xd6, 0xf0, 0xfc, 0xcf, 0x2b,
- 0xec, 0x79, 0x5a, 0x98, 0xcf, 0x05, 0xac, 0x19, 0xe1, 0x28, 0x69, 0x9e,
- 0x9d, 0x96, 0xbe, 0xad, 0x6d, 0xb3, 0xa7, 0xb8, 0x4f, 0xff, 0x53, 0xdd,
- 0x81, 0x2d, 0xec, 0xed, 0x43, 0x9a, 0xd4, 0xcb, 0x51, 0xb5, 0x16, 0x9b,
- 0x71, 0x3a, 0xc0, 0x26, 0x5c, 0xfb, 0x0f, 0x98, 0x08, 0xc4, 0x98, 0xf3,
- 0x35, 0xbc, 0x9b, 0xf9, 0x32, 0xfb, 0x9d, 0x3a, 0x39, 0xe3, 0x83, 0x5b,
- 0x4e, 0xb8, 0xb9, 0xe6, 0x16, 0xe2, 0x9a, 0x4e, 0xbc, 0x16, 0xb0, 0x7b,
- 0x8d, 0xa3, 0xbc, 0x3e, 0x3e, 0xe7, 0x23, 0x16, 0xf5, 0xf0, 0xf7, 0x46,
- 0xde, 0xbe, 0x88, 0x27, 0x91, 0xe5, 0xdf, 0xe2, 0xc9, 0x43, 0x3c, 0xa0,
- 0xe1, 0x6a, 0xe6, 0x65, 0x5c, 0x21, 0xed, 0xf4, 0x9c, 0x4d, 0x73, 0x2a,
- 0x2f, 0x74, 0x65, 0xbd, 0x48, 0xaa, 0xd6, 0x29, 0xf4, 0x7d, 0x72, 0xde,
- 0xf7, 0xdf, 0xb9, 0x06, 0x91, 0xdd, 0x09, 0xf6, 0xc7, 0x7a, 0x03, 0xda,
- 0x03, 0xb4, 0x97, 0x21, 0x6b, 0xa8, 0xec, 0x45, 0xe5, 0xdd, 0x10, 0xd6,
- 0x4e, 0x9a, 0x23, 0xa1, 0x84, 0x5c, 0x37, 0xcd, 0xea, 0x4d, 0x5a, 0xe8,
- 0x4d, 0xc5, 0xc5, 0x5a, 0xe7, 0xa2, 0x0e, 0xc6, 0x71, 0x36, 0xd3, 0xb8,
- 0xf4, 0x1e, 0xb1, 0x53, 0x98, 0xbd, 0xde, 0x25, 0xe7, 0x38, 0xe6, 0x33,
- 0x0b, 0x95, 0x32, 0x23, 0x18, 0xcf, 0xfb, 0x94, 0xb9, 0xcc, 0x91, 0x4a,
- 0xc9, 0x45, 0x63, 0xf4, 0x85, 0xa6, 0x49, 0xe1, 0xd5, 0x1c, 0xa9, 0x22,
- 0x9d, 0x63, 0xa4, 0x33, 0xb7, 0x51, 0xeb, 0x1f, 0x53, 0x44, 0x67, 0x3e,
- 0xe2, 0xba, 0x8b, 0x32, 0x3f, 0xa3, 0xde, 0xfe, 0x94, 0xcf, 0x8b, 0xde,
- 0x82, 0x78, 0xad, 0x48, 0xe7, 0x89, 0xfc, 0x12, 0xe6, 0x32, 0x1f, 0x58,
- 0x7f, 0x8f, 0xe5, 0x63, 0xac, 0x7d, 0x83, 0xc8, 0x31, 0x9f, 0x4c, 0x66,
- 0x1a, 0xfb, 0x27, 0xc9, 0x87, 0x7d, 0x36, 0x6f, 0x10, 0x4f, 0x17, 0x9f,
- 0x19, 0xe5, 0xbb, 0xa3, 0xd7, 0xfe, 0x16, 0x1d, 0xd9, 0xfb, 0xff, 0xf6,
- 0x1e, 0x43, 0x39, 0x6d, 0x67, 0xf7, 0xe1, 0x47, 0x0d, 0xb7, 0xcc, 0xc3,
- 0xf1, 0xf2, 0xf4, 0x16, 0x8c, 0xe9, 0x7f, 0x8e, 0xbd, 0x94, 0x7b, 0x9c,
- 0xfa, 0x3c, 0x61, 0x58, 0xfb, 0xfc, 0x72, 0xfe, 0x8b, 0xb9, 0xfa, 0x60,
- 0xeb, 0x19, 0x62, 0xb1, 0xe3, 0x8c, 0x99, 0xfd, 0xf1, 0xc6, 0xde, 0x57,
- 0xe8, 0x77, 0xc9, 0xdf, 0x96, 0xbd, 0x74, 0x60, 0x32, 0xfb, 0x0d, 0xcc,
- 0xd6, 0x34, 0x2e, 0x3f, 0xcf, 0x9c, 0x70, 0x9a, 0x79, 0xca, 0xc5, 0x9c,
- 0x50, 0x9d, 0x25, 0x86, 0x64, 0x9e, 0x2a, 0x30, 0x4f, 0xb9, 0xb4, 0xc6,
- 0xa5, 0x79, 0xfc, 0x15, 0xf5, 0x22, 0xfc, 0x45, 0x62, 0xf3, 0x90, 0x67,
- 0xed, 0xf9, 0xab, 0x36, 0x3f, 0x84, 0x4b, 0x37, 0xdb, 0x33, 0x34, 0x27,
- 0x6b, 0xf6, 0xbe, 0x4c, 0x63, 0x60, 0x4c, 0x68, 0xf7, 0xa9, 0xa1, 0x34,
- 0x6d, 0x35, 0x61, 0x61, 0xef, 0x61, 0xf6, 0x0b, 0x72, 0xde, 0xab, 0x0a,
- 0x2e, 0xfa, 0xfe, 0x98, 0x2e, 0xe7, 0x20, 0x42, 0xfe, 0xed, 0xb4, 0xe1,
- 0x98, 0xd1, 0xd8, 0x12, 0x51, 0x76, 0xe3, 0x52, 0x31, 0xc7, 0xda, 0x58,
- 0x5a, 0xed, 0x3f, 0x86, 0xc6, 0xde, 0x07, 0xf0, 0x75, 0x24, 0x6b, 0x1a,
- 0x07, 0xa6, 0x11, 0xd1, 0xef, 0x83, 0x9c, 0x1b, 0xb5, 0x69, 0xd5, 0xe7,
- 0x9c, 0xc4, 0x23, 0x9f, 0x98, 0xab, 0xb5, 0x27, 0x30, 0x4d, 0xcc, 0xd8,
- 0xb0, 0x5e, 0x5b, 0xfa, 0x6e, 0xf1, 0x9e, 0xbd, 0xa7, 0x24, 0xfe, 0xe2,
- 0xa1, 0x0e, 0xca, 0xe1, 0x5a, 0x51, 0xc7, 0x35, 0xa8, 0x0b, 0xeb, 0x4c,
- 0xf1, 0x45, 0x1c, 0xa2, 0xbf, 0x4d, 0xe7, 0x15, 0xe8, 0xf5, 0x17, 0x31,
- 0x2c, 0xb5, 0x89, 0xef, 0xb4, 0x65, 0x7c, 0xc4, 0x29, 0x21, 0x94, 0x6b,
- 0x91, 0xf0, 0x28, 0xe5, 0x6b, 0x63, 0x2e, 0x1f, 0x67, 0x0e, 0x49, 0x07,
- 0x7c, 0xd6, 0x39, 0xd7, 0x72, 0x2d, 0x64, 0xfd, 0x6f, 0x82, 0xf4, 0x41,
- 0x0d, 0xb3, 0xb2, 0x9f, 0x7d, 0x04, 0x17, 0xa7, 0x0b, 0x38, 0x1e, 0x4f,
- 0xe2, 0x40, 0x4d, 0x00, 0x93, 0xc6, 0x4a, 0x6b, 0x6e, 0x20, 0xfd, 0x56,
- 0x77, 0xf6, 0xb0, 0x35, 0x8b, 0xdc, 0x16, 0x77, 0xd4, 0xcb, 0x79, 0x8f,
- 0x39, 0xf6, 0x5d, 0xd3, 0xfa, 0x08, 0x0e, 0xe9, 0xdf, 0x82, 0xbe, 0x42,
- 0x72, 0xe7, 0x18, 0xce, 0xcf, 0x4a, 0x0d, 0x9b, 0x68, 0xbd, 0x75, 0x52,
- 0xf4, 0xe3, 0x20, 0xe6, 0xf5, 0xa0, 0xc9, 0xc2, 0x70, 0xaf, 0xb7, 0xae,
- 0x99, 0xb5, 0xb1, 0x5c, 0x53, 0x4e, 0xce, 0x66, 0x57, 0xc1, 0x4f, 0x7d,
- 0x5d, 0x88, 0xbb, 0x99, 0x73, 0x44, 0x9f, 0x72, 0x16, 0xd0, 0x96, 0x33,
- 0x96, 0x53, 0x30, 0xd6, 0x7c, 0xe3, 0x5e, 0x8b, 0xfc, 0x9f, 0xc2, 0xb5,
- 0xf3, 0x89, 0xc5, 0xd9, 0xf8, 0x1f, 0x9b, 0x97, 0x6e, 0x12, 0xb9, 0x5b,
- 0x7d, 0xcc, 0xe9, 0xe1, 0xd9, 0x6b, 0xfa, 0x15, 0x9d, 0x9e, 0x93, 0x9a,
- 0x61, 0xe9, 0xdc, 0x9e, 0xb7, 0xa9, 0xc3, 0xef, 0x28, 0x8d, 0xac, 0x27,
- 0xf4, 0xab, 0x1a, 0xfa, 0x5b, 0x13, 0x06, 0x56, 0x27, 0x5c, 0x7d, 0x57,
- 0x8d, 0x2d, 0x68, 0xd9, 0xf0, 0xae, 0x89, 0x9b, 0xdb, 0xe0, 0xd4, 0xe4,
- 0xfa, 0xac, 0x99, 0x0c, 0xc8, 0xdf, 0x4f, 0xfa, 0xa4, 0x96, 0xbf, 0x68,
- 0x14, 0xcc, 0x35, 0x2b, 0x6d, 0x6c, 0xf8, 0xf7, 0x19, 0xd9, 0x07, 0x4b,
- 0x9b, 0xec, 0xb5, 0x97, 0xde, 0x76, 0x1e, 0xc6, 0xdf, 0xe6, 0x8e, 0xe0,
- 0xad, 0x69, 0x17, 0x71, 0xa6, 0xc8, 0xb2, 0x05, 0xd5, 0x1b, 0xa2, 0xc9,
- 0x77, 0x99, 0x17, 0x97, 0x66, 0x4b, 0x7e, 0xf1, 0x7a, 0xeb, 0xda, 0x59,
- 0x85, 0xb4, 0xaa, 0x50, 0x46, 0x39, 0x7f, 0xac, 0x3b, 0x11, 0x2e, 0x62,
- 0x5b, 0x27, 0xf9, 0xdc, 0x97, 0xb1, 0x31, 0x6f, 0x24, 0x37, 0xed, 0xb3,
- 0xe7, 0x5f, 0x3e, 0xe6, 0xd1, 0x71, 0x4c, 0x64, 0x1a, 0x63, 0xef, 0xc9,
- 0x79, 0x1e, 0xf6, 0x62, 0x97, 0x30, 0x8e, 0x13, 0x99, 0x52, 0x0e, 0x0d,
- 0xc9, 0x39, 0xd8, 0x58, 0xd8, 0x61, 0xe7, 0xc8, 0xb0, 0x43, 0x4d, 0xf3,
- 0xd7, 0x27, 0xd8, 0x60, 0x34, 0x1f, 0x09, 0x95, 0xc3, 0x89, 0xfd, 0xba,
- 0xed, 0x1f, 0xf5, 0xf3, 0x6e, 0x84, 0x57, 0x48, 0x5d, 0x96, 0x9a, 0xec,
- 0x62, 0x4d, 0x5e, 0x89, 0xe4, 0x4a, 0x17, 0x5e, 0xd7, 0x44, 0x1f, 0x53,
- 0x25, 0x7d, 0xe8, 0xe7, 0xf0, 0x90, 0x59, 0xe8, 0x15, 0x5f, 0x72, 0xe3,
- 0x48, 0xd3, 0x9c, 0x39, 0x1b, 0x14, 0xd9, 0x9d, 0x38, 0xcd, 0xfc, 0x8a,
- 0x9b, 0x23, 0xa1, 0xd3, 0xac, 0xd9, 0x63, 0x5a, 0xc9, 0xc7, 0xff, 0x63,
- 0x91, 0x4f, 0xad, 0x7f, 0x01, 0x47, 0xf8, 0x77, 0x7d, 0xe8, 0x80, 0x62,
- 0xaf, 0xb7, 0x66, 0xfe, 0x43, 0x5f, 0x69, 0x76, 0x2a, 0xcf, 0x86, 0x73,
- 0xa7, 0xf9, 0x5d, 0x68, 0xf9, 0xe8, 0x9f, 0xe5, 0x18, 0x08, 0xca, 0x79,
- 0x10, 0xd1, 0x8b, 0xec, 0x3f, 0x82, 0xfa, 0x30, 0xf1, 0x32, 0xf5, 0x71,
- 0xe4, 0xda, 0xd9, 0x2b, 0x3b, 0x7f, 0x55, 0xf0, 0xfa, 0xf6, 0xf8, 0x4b,
- 0x9b, 0xbd, 0xf8, 0x95, 0x79, 0x29, 0x18, 0x62, 0x4e, 0x10, 0x9b, 0xa6,
- 0x2c, 0x1c, 0xe9, 0x24, 0x3e, 0xd9, 0x67, 0x9f, 0x33, 0x69, 0x95, 0xff,
- 0xa1, 0x29, 0xca, 0x51, 0x18, 0x24, 0xce, 0x5e, 0xcc, 0x58, 0x67, 0xfb,
- 0x06, 0xde, 0x54, 0x22, 0xcc, 0x35, 0x5f, 0xc2, 0x40, 0xad, 0xd0, 0x0b,
- 0xf8, 0x77, 0xce, 0xc4, 0xa8, 0x83, 0x3a, 0xa1, 0x6b, 0x3e, 0xc3, 0x6e,
- 0xee, 0xc8, 0xa4, 0xd0, 0x07, 0xc6, 0x26, 0x23, 0x43, 0x3f, 0x06, 0x36,
- 0x57, 0x41, 0x4d, 0x2d, 0x14, 0xff, 0xdf, 0xe3, 0x67, 0x8a, 0xd0, 0x12,
- 0x3a, 0x2e, 0x18, 0xcc, 0x71, 0x53, 0x8b, 0x15, 0xd4, 0x9d, 0xda, 0xfb,
- 0x3d, 0xa5, 0x02, 0x4f, 0x3c, 0x15, 0x23, 0xef, 0x2b, 0xfc, 0xdb, 0x67,
- 0x3c, 0xf0, 0x9e, 0xa9, 0x62, 0xcd, 0xf5, 0xe0, 0x72, 0x33, 0xed, 0xfa,
- 0x54, 0x89, 0x77, 0x6b, 0x9f, 0x14, 0x8f, 0x67, 0xc3, 0x30, 0xe8, 0xb3,
- 0x8b, 0x86, 0xec, 0x17, 0x7b, 0xac, 0xfc, 0xb9, 0xb4, 0xb1, 0xce, 0xda,
- 0xaf, 0x7a, 0x3e, 0xaf, 0x85, 0xce, 0x2a, 0x55, 0xf8, 0xe0, 0x44, 0xe1,
- 0xe6, 0x72, 0x98, 0x2f, 0xae, 0x4e, 0x44, 0xfb, 0xf7, 0xd2, 0xe7, 0xd7,
- 0xae, 0x09, 0xb2, 0x97, 0x61, 0x4f, 0xb9, 0x49, 0xfa, 0xdf, 0x69, 0xf6,
- 0xbf, 0xa5, 0xbd, 0x7f, 0x6d, 0xe8, 0x11, 0x25, 0xdd, 0xe9, 0x87, 0xf9,
- 0x51, 0x79, 0xc2, 0xfc, 0xd8, 0x9d, 0x88, 0xf2, 0x7d, 0xd9, 0xdf, 0x33,
- 0xcd, 0x9f, 0x36, 0x9b, 0x66, 0xae, 0x39, 0xd2, 0x1f, 0x70, 0x06, 0x70,
- 0xa6, 0x41, 0xf6, 0x04, 0x1d, 0xf8, 0x20, 0xaa, 0x85, 0xf6, 0x42, 0xf6,
- 0xe8, 0x99, 0xe3, 0x57, 0xca, 0xf9, 0xc4, 0x3a, 0x7f, 0x97, 0xb1, 0x02,
- 0xcf, 0x2d, 0x6c, 0xc2, 0x80, 0x1b, 0xd6, 0xf9, 0x19, 0x53, 0xc7, 0x9b,
- 0xab, 0x21, 0x75, 0x3b, 0xda, 0xf2, 0x08, 0x82, 0x58, 0xc8, 0x1f, 0xc1,
- 0xc3, 0x27, 0x64, 0xaf, 0x71, 0xb2, 0xd5, 0x73, 0xc2, 0xfc, 0xfb, 0x50,
- 0xa2, 0xc0, 0xbc, 0x68, 0x9a, 0x15, 0x9b, 0x1a, 0x43, 0x2c, 0x47, 0xc4,
- 0x18, 0x69, 0xc1, 0xee, 0x43, 0x1f, 0xa0, 0x06, 0x67, 0xe7, 0x92, 0x37,
- 0xb3, 0x97, 0xec, 0x7a, 0x5a, 0x09, 0xe0, 0x07, 0x94, 0xf1, 0xd9, 0xbc,
- 0xe0, 0x14, 0xa3, 0xb5, 0xfb, 0xc4, 0x2a, 0xbc, 0xb8, 0x10, 0xc4, 0x59,
- 0x43, 0x23, 0x4e, 0x82, 0x52, 0x99, 0x30, 0xab, 0xab, 0xc9, 0x6b, 0xa5,
- 0xd3, 0x89, 0xce, 0xb8, 0xf4, 0x87, 0xda, 0x90, 0x4f, 0xc1, 0xaa, 0x72,
- 0x68, 0xcb, 0x0f, 0x01, 0xc3, 0x5e, 0xf6, 0xab, 0x4f, 0x2b, 0xd1, 0xfe,
- 0xf7, 0x9d, 0x41, 0xfc, 0x80, 0xf9, 0xe7, 0x7b, 0x79, 0x39, 0x5b, 0xc5,
- 0x1c, 0x33, 0x17, 0xa6, 0xad, 0x3c, 0x70, 0xd4, 0x57, 0xe1, 0x28, 0xe3,
- 0xe5, 0x65, 0xbd, 0x8c, 0x39, 0x4a, 0xce, 0x5a, 0x49, 0x7e, 0x7f, 0x54,
- 0xce, 0x94, 0x98, 0xcf, 0x6b, 0x76, 0xbf, 0xaf, 0xcf, 0xdf, 0x78, 0x5e,
- 0x39, 0xc0, 0xbc, 0xde, 0xd8, 0x1b, 0x52, 0x5e, 0x35, 0x93, 0xbf, 0xad,
- 0x50, 0xce, 0x07, 0xab, 0x50, 0x61, 0xc9, 0x8a, 0xd1, 0x6c, 0xa9, 0xa6,
- 0x54, 0x4b, 0x2f, 0xd7, 0x9b, 0x2e, 0xfa, 0x60, 0x25, 0x63, 0xfd, 0x18,
- 0x6b, 0x74, 0xf9, 0x09, 0xa9, 0x25, 0xec, 0x5f, 0x94, 0x2d, 0xc4, 0xc2,
- 0x82, 0x1b, 0x3c, 0x78, 0x20, 0xa0, 0xb6, 0xc8, 0x99, 0xed, 0x67, 0xf3,
- 0x1d, 0x2e, 0x39, 0x3b, 0xf5, 0x5c, 0x5e, 0x6a, 0xb9, 0xe4, 0x82, 0xd2,
- 0x7a, 0x21, 0xd4, 0x4e, 0x8a, 0x8d, 0x86, 0x5b, 0x3f, 0x9a, 0xf4, 0xc9,
- 0xf9, 0xfa, 0x11, 0x07, 0x7b, 0x6d, 0xcf, 0xa4, 0x69, 0xee, 0x69, 0xd6,
- 0x86, 0xb6, 0x38, 0x65, 0x6f, 0x39, 0x32, 0x70, 0x4e, 0x51, 0x5b, 0x26,
- 0x94, 0x1b, 0xe9, 0xfc, 0xb7, 0x2a, 0x89, 0x91, 0x34, 0xe5, 0x7c, 0xdc,
- 0x92, 0x69, 0x8a, 0x32, 0x95, 0xce, 0x16, 0x55, 0xe1, 0xf2, 0x34, 0x34,
- 0x46, 0x2d, 0xce, 0xeb, 0x4c, 0x4e, 0x81, 0x68, 0xb2, 0x1d, 0xe2, 0xff,
- 0xea, 0x80, 0x60, 0xa8, 0x4a, 0xe6, 0xe4, 0xb9, 0x69, 0xa9, 0x31, 0x8a,
- 0xe0, 0x93, 0x34, 0xd7, 0xc6, 0x95, 0x8d, 0xc0, 0xab, 0x93, 0xf6, 0xde,
- 0x7b, 0xf1, 0x2c, 0xb8, 0x75, 0xe6, 0xe1, 0x11, 0xeb, 0x2c, 0x83, 0xd0,
- 0x3f, 0x8c, 0x33, 0x19, 0xc1, 0x94, 0xc3, 0xc4, 0x94, 0x91, 0x14, 0xf1,
- 0x66, 0x4b, 0xde, 0x3e, 0x97, 0xa5, 0x7f, 0x44, 0x9f, 0x7f, 0x9a, 0x58,
- 0xf5, 0x28, 0xec, 0xbd, 0xf7, 0x86, 0xe2, 0x59, 0x85, 0x48, 0xae, 0x4b,
- 0xd9, 0x91, 0x97, 0x18, 0x9b, 0x66, 0x8c, 0xb5, 0x2b, 0xdb, 0x17, 0x3a,
- 0x94, 0xee, 0x85, 0x1e, 0x65, 0x77, 0x5e, 0x7a, 0xd6, 0xc9, 0xd6, 0x07,
- 0x4e, 0xec, 0x52, 0x76, 0xcc, 0xf5, 0x29, 0xc4, 0xb4, 0x01, 0x4f, 0xa2,
- 0x5f, 0xe9, 0x59, 0xb0, 0xe7, 0xe7, 0x5d, 0xec, 0xbb, 0x76, 0x18, 0xa5,
- 0x7e, 0x5e, 0xfe, 0xdf, 0x2b, 0x28, 0xff, 0x5b, 0x31, 0xb0, 0x4d, 0x31,
- 0xcd, 0xdb, 0xe2, 0x7f, 0x27, 0xf6, 0x30, 0x9f, 0x8d, 0xb3, 0x36, 0x1a,
- 0x55, 0x18, 0x64, 0xdf, 0x31, 0xaa, 0xdf, 0x5a, 0xdc, 0x2f, 0x13, 0x99,
- 0xe4, 0x3c, 0x85, 0xf8, 0x2b, 0xd2, 0xe5, 0xe4, 0xe1, 0x1f, 0xc8, 0xff,
- 0x81, 0xa2, 0x5c, 0x3d, 0x72, 0xa6, 0xc0, 0x7d, 0xfd, 0xbc, 0xd9, 0xf1,
- 0xc9, 0xeb, 0x72, 0x31, 0xd7, 0x63, 0x9c, 0xf8, 0xf4, 0x80, 0xa2, 0xa6,
- 0x9e, 0xb1, 0xe5, 0x5a, 0xba, 0xcc, 0x18, 0x1e, 0xb5, 0x62, 0xd8, 0x96,
- 0x6b, 0x5d, 0x51, 0xae, 0xb5, 0xb9, 0x2e, 0xeb, 0x1c, 0x17, 0xf1, 0x7a,
- 0xeb, 0xe2, 0xa4, 0x9c, 0x37, 0x93, 0xd9, 0xa5, 0xc8, 0x26, 0x72, 0x9c,
- 0x30, 0x2b, 0xb4, 0x1e, 0x65, 0xa7, 0x75, 0xfe, 0x4c, 0xce, 0x7e, 0xc9,
- 0x5e, 0x7f, 0x49, 0x2e, 0xa9, 0xe3, 0x2b, 0xfc, 0x1d, 0x33, 0x72, 0x1e,
- 0xdb, 0x34, 0x5f, 0xd3, 0x83, 0x7e, 0x91, 0xe5, 0xac, 0x2e, 0xb2, 0xc8,
- 0xb9, 0x92, 0x92, 0x3c, 0x5f, 0x2b, 0xca, 0x23, 0xb6, 0xba, 0x6e, 0xa7,
- 0xd2, 0xff, 0x09, 0xbe, 0x9d, 0xb1, 0xcf, 0x9c, 0x94, 0xe4, 0xf1, 0x27,
- 0x84, 0xff, 0x8b, 0xad, 0xe3, 0xd3, 0xc3, 0x78, 0x95, 0xf7, 0x7f, 0x9e,
- 0x29, 0xc9, 0xe5, 0xc4, 0xfc, 0x5c, 0xe9, 0x2c, 0x1d, 0x5b, 0x4a, 0x23,
- 0xa2, 0x8f, 0xd1, 0x8f, 0x6c, 0xf9, 0xe4, 0x2c, 0x5d, 0x63, 0xe1, 0xb2,
- 0x35, 0xf7, 0x8a, 0x26, 0xd9, 0x2f, 0xe3, 0x6c, 0xfe, 0xd7, 0xed, 0xd7,
- 0x94, 0xab, 0x60, 0x8f, 0x2c, 0xb4, 0x5f, 0x27, 0x6d, 0x39, 0x73, 0xa2,
- 0xe0, 0x99, 0x39, 0x60, 0xce, 0xe0, 0xb2, 0x89, 0x11, 0x3c, 0xa9, 0x9b,
- 0xe6, 0xd3, 0xcd, 0x9a, 0x9c, 0x15, 0xba, 0x50, 0x6b, 0xcd, 0x85, 0xa0,
- 0x57, 0x69, 0xb2, 0x77, 0x27, 0xe7, 0x4d, 0xfa, 0xa8, 0x03, 0x91, 0x5d,
- 0x7c, 0xa0, 0x64, 0x7b, 0x39, 0x07, 0x97, 0xa6, 0x7e, 0x44, 0x37, 0xa5,
- 0xf3, 0x70, 0x32, 0x73, 0xb9, 0x51, 0x27, 0x5d, 0x96, 0x4e, 0x9e, 0xd5,
- 0xc5, 0x5f, 0x99, 0x7d, 0xe8, 0xab, 0xf3, 0xc4, 0x0f, 0x63, 0xba, 0xdb,
- 0xc2, 0x6a, 0x47, 0x89, 0x4f, 0x26, 0x18, 0x3b, 0x8f, 0x1b, 0x4b, 0x58,
- 0xca, 0xbd, 0x8c, 0x57, 0xaf, 0xfd, 0xcf, 0x9c, 0xf8, 0x8b, 0xde, 0xd2,
- 0x6d, 0x9d, 0x79, 0xfa, 0xa4, 0xe5, 0xd6, 0xa8, 0xe4, 0xa1, 0x1f, 0x36,
- 0xc9, 0x19, 0xa8, 0xf2, 0x44, 0xe0, 0x6b, 0xb2, 0xbf, 0x55, 0x96, 0x98,
- 0xfd, 0xea, 0x05, 0x4d, 0x74, 0xa3, 0x35, 0x9f, 0xd1, 0x44, 0xae, 0x1e,
- 0x7d, 0xdc, 0xfa, 0x1f, 0xce, 0x96, 0x4d, 0xfb, 0x34, 0x89, 0x1d, 0xdf,
- 0xc6, 0x36, 0x2b, 0x27, 0x9c, 0x4e, 0xdc, 0x66, 0xe9, 0xe0, 0x64, 0xe2,
- 0x56, 0xeb, 0x73, 0x3a, 0x11, 0xb3, 0x3e, 0xff, 0x24, 0x61, 0xeb, 0x26,
- 0x97, 0xa8, 0xb7, 0x3e, 0xe7, 0x13, 0xf6, 0xd9, 0xe9, 0xd9, 0x84, 0x66,
- 0x7d, 0x3e, 0x9f, 0x88, 0x58, 0x9f, 0x67, 0x13, 0xb7, 0x5c, 0xe7, 0x8b,
- 0x3f, 0xff, 0x0f, 0x4c, 0xd3, 0x85, 0x76, 0xdc, 0x3a, 0x00, 0x00, 0x00 };
+ 0xad, 0x7b, 0x0d, 0x70, 0x94, 0xf7, 0x79, 0xe7, 0xef, 0xbf, 0x1f, 0xd2,
+ 0xae, 0xb4, 0x5a, 0xad, 0xf0, 0x82, 0x57, 0x89, 0x52, 0xf6, 0xf5, 0xbe,
+ 0x2b, 0x2d, 0x96, 0x80, 0x77, 0x41, 0x04, 0x11, 0x6d, 0xcd, 0x56, 0x08,
+ 0x21, 0x40, 0xd8, 0x32, 0x56, 0x92, 0x25, 0xc7, 0xd4, 0x2a, 0xc8, 0x20,
+ 0xdb, 0x18, 0x8b, 0x86, 0xe6, 0xe4, 0xd6, 0xad, 0xd6, 0x92, 0xc0, 0x60,
+ 0x56, 0xbc, 0x22, 0x82, 0x08, 0x77, 0xee, 0x26, 0xb2, 0x25, 0x2c, 0xec,
+ 0xac, 0x58, 0x3b, 0xbd, 0xeb, 0xc5, 0x33, 0xc9, 0x58, 0x67, 0x6c, 0x4c,
+ 0x72, 0xfe, 0xc8, 0x75, 0x3a, 0x3d, 0xf7, 0xe6, 0xee, 0xca, 0xf8, 0x83,
+ 0xd8, 0x6e, 0x8c, 0xdd, 0x4c, 0x3a, 0x27, 0x52, 0xdb, 0xef, 0xfd, 0x9e,
+ 0xf7, 0xdd, 0x05, 0xe2, 0xba, 0xd3, 0x99, 0xce, 0x69, 0x66, 0x67, 0xa5,
+ 0xf7, 0xe3, 0xf9, 0x3f, 0xdf, 0xcf, 0xef, 0x79, 0xfe, 0x7f, 0xd5, 0x03,
+ 0x15, 0x28, 0xfe, 0x54, 0xf1, 0xd3, 0x3c, 0x30, 0x78, 0x70, 0xd5, 0x8a,
+ 0xe6, 0x15, 0xf6, 0x05, 0x97, 0xc7, 0x23, 0x37, 0xbf, 0xaa, 0x80, 0xde,
+ 0x0f, 0xf0, 0x6f, 0xfa, 0xf9, 0xca, 0xbf, 0xed, 0x35, 0xfb, 0xc7, 0x0d,
+ 0x84, 0x4a, 0x7c, 0xc9, 0x07, 0x3e, 0x57, 0xea, 0xd2, 0xd7, 0xda, 0x74,
+ 0xf8, 0xdc, 0xa9, 0x93, 0xa9, 0xdd, 0x3a, 0x90, 0xce, 0x37, 0x46, 0x37,
+ 0xe0, 0x53, 0x2b, 0x1b, 0xf6, 0x40, 0xae, 0x7f, 0x25, 0xf5, 0xc9, 0xd0,
+ 0x4f, 0xd6, 0x6a, 0x1f, 0x4f, 0xb9, 0xe1, 0x0b, 0xa5, 0x4e, 0x23, 0x54,
+ 0x0f, 0x5f, 0x1d, 0xdf, 0xf9, 0x0f, 0x0d, 0xd5, 0x6e, 0x04, 0x4b, 0xb4,
+ 0x5a, 0x30, 0x62, 0x22, 0xeb, 0x4b, 0x0d, 0xa0, 0x7c, 0x0d, 0xf0, 0x6e,
+ 0x2e, 0x6e, 0x8c, 0x00, 0xe3, 0xae, 0x54, 0x3c, 0xfa, 0x22, 0x0c, 0x1c,
+ 0x2a, 0x44, 0xd1, 0xce, 0xcf, 0x66, 0xf3, 0x33, 0x2b, 0xea, 0x45, 0xd6,
+ 0xcd, 0xe7, 0x76, 0x35, 0x03, 0x1b, 0x73, 0x06, 0x0e, 0x9b, 0xf0, 0xd5,
+ 0xa6, 0x1e, 0xc6, 0x3a, 0x7e, 0x07, 0x53, 0x83, 0x78, 0x7d, 0x2c, 0x16,
+ 0x7d, 0x0a, 0x5a, 0x46, 0x77, 0x6b, 0x83, 0x40, 0x63, 0x7f, 0x9f, 0xd2,
+ 0x7a, 0xdf, 0x50, 0x5a, 0xf7, 0x98, 0x82, 0x4f, 0xf1, 0xb9, 0xc6, 0xbc,
+ 0x7c, 0x0f, 0xe2, 0xd6, 0xbc, 0x0f, 0x97, 0xdc, 0xb2, 0xfe, 0xef, 0x52,
+ 0xdf, 0x0a, 0x1e, 0xbd, 0x05, 0xa3, 0xe4, 0xc1, 0x9b, 0x52, 0x78, 0xb2,
+ 0x39, 0x1e, 0x19, 0x86, 0xdc, 0x8f, 0x62, 0x43, 0x41, 0xbe, 0x35, 0x4a,
+ 0x6d, 0x59, 0xa3, 0x86, 0x65, 0x9d, 0x31, 0xca, 0x91, 0x0d, 0x69, 0x11,
+ 0x40, 0x61, 0xd8, 0x70, 0x21, 0x1d, 0x6a, 0x8b, 0x7a, 0xa0, 0x45, 0xee,
+ 0xc1, 0x3f, 0x51, 0xe6, 0x74, 0xc2, 0x0b, 0xe7, 0xf9, 0x5e, 0x94, 0x63,
+ 0x3e, 0xe4, 0x68, 0xed, 0xc9, 0x9c, 0x65, 0x5d, 0xd0, 0x3d, 0x38, 0x43,
+ 0xfd, 0x0c, 0xe7, 0xff, 0xc9, 0x9a, 0xa7, 0x6e, 0x46, 0xf5, 0xd2, 0xfa,
+ 0x3e, 0x4c, 0x85, 0x2c, 0x6b, 0x9a, 0xf7, 0x0e, 0xe7, 0x4b, 0x7a, 0xb6,
+ 0x2c, 0x97, 0x6e, 0x59, 0xbb, 0xf5, 0xdf, 0x58, 0xbb, 0x7e, 0xeb, 0x59,
+ 0xcb, 0x7a, 0xcc, 0xb8, 0x09, 0x67, 0x27, 0xda, 0xd5, 0x96, 0xd9, 0x25,
+ 0xc1, 0xcd, 0x93, 0x16, 0x2e, 0x18, 0x08, 0xb9, 0x52, 0x1d, 0x6a, 0xf3,
+ 0x6c, 0xa7, 0xda, 0x58, 0xd8, 0xae, 0x3a, 0xa6, 0xbf, 0xa5, 0x3a, 0x67,
+ 0x7b, 0xd5, 0xa6, 0x42, 0x04, 0x33, 0x66, 0x18, 0xd3, 0x66, 0x46, 0xb5,
+ 0xcf, 0xf6, 0x28, 0x47, 0x8e, 0x41, 0xd5, 0x56, 0x28, 0xd1, 0xba, 0xae,
+ 0xc7, 0xcd, 0xb9, 0x14, 0x8e, 0x98, 0xe5, 0x5c, 0x67, 0xc1, 0xfa, 0x49,
+ 0xc3, 0x02, 0xe5, 0x34, 0x70, 0xb4, 0xf0, 0x18, 0xb6, 0x4d, 0x5a, 0x56,
+ 0x3e, 0x09, 0xe4, 0x0b, 0xc0, 0x0f, 0xcc, 0x58, 0x77, 0xbf, 0xb2, 0xac,
+ 0x4d, 0x71, 0x6b, 0xe9, 0x65, 0xa3, 0x31, 0xf1, 0x12, 0xfe, 0xaf, 0x35,
+ 0x15, 0x46, 0x36, 0x40, 0x1a, 0xc7, 0x68, 0xb3, 0xfb, 0xc6, 0xe0, 0x2b,
+ 0x4f, 0x8d, 0xe2, 0x17, 0x39, 0xf8, 0xca, 0x52, 0x59, 0x5c, 0xc8, 0x0d,
+ 0x87, 0x7c, 0x88, 0x45, 0x36, 0xab, 0xec, 0xa0, 0x0b, 0xda, 0xc0, 0xdb,
+ 0xd0, 0xa2, 0xb4, 0xc7, 0xc5, 0xf3, 0x4a, 0x9b, 0x7f, 0x09, 0x5a, 0xfa,
+ 0x37, 0x4a, 0xeb, 0xac, 0x75, 0x23, 0xed, 0x8a, 0xfb, 0xf0, 0x93, 0x06,
+ 0xb1, 0xc9, 0x28, 0x56, 0xd8, 0xb6, 0xc9, 0x62, 0xd9, 0x35, 0xdb, 0xa4,
+ 0x30, 0x4c, 0xbe, 0x0e, 0x93, 0xaf, 0x97, 0x0d, 0x2d, 0xf2, 0x24, 0xac,
+ 0xa5, 0x7d, 0x86, 0xdc, 0x4b, 0x61, 0xb4, 0x60, 0x45, 0x83, 0xa9, 0x4b,
+ 0xe4, 0x17, 0xd9, 0x2f, 0xa5, 0x7c, 0xd9, 0xea, 0xd4, 0xa7, 0xd6, 0x6b,
+ 0x6b, 0x22, 0x78, 0xa1, 0x10, 0xc6, 0x73, 0x85, 0x10, 0x9e, 0x2d, 0xb4,
+ 0xc3, 0x2c, 0x20, 0xb8, 0xad, 0xf0, 0x45, 0x7e, 0x6c, 0x21, 0xc0, 0xe7,
+ 0xc9, 0x77, 0x70, 0x6b, 0xc1, 0xd3, 0x5b, 0x96, 0x42, 0xf7, 0x4f, 0x73,
+ 0x43, 0x56, 0x85, 0x8e, 0xde, 0x9a, 0x94, 0x9e, 0xbe, 0x55, 0x05, 0x5a,
+ 0xe8, 0x87, 0xdd, 0xaf, 0xe4, 0x5b, 0x3c, 0xfa, 0x71, 0x3f, 0xbc, 0xd4,
+ 0xff, 0xc6, 0x82, 0x65, 0x8d, 0x18, 0x07, 0x56, 0xee, 0x6a, 0xf9, 0x8b,
+ 0xf9, 0x6e, 0xbd, 0x0b, 0xd9, 0x42, 0x1f, 0x10, 0x4c, 0xf1, 0x9b, 0xa1,
+ 0xb8, 0xbd, 0xa9, 0x3d, 0x7a, 0xee, 0x01, 0x8f, 0xe3, 0xcf, 0xe4, 0x81,
+ 0x7a, 0x7f, 0xce, 0x24, 0x0f, 0xe6, 0xe1, 0x20, 0x2a, 0xa2, 0x94, 0xef,
+ 0xe7, 0xe4, 0x33, 0x81, 0x1f, 0x16, 0x74, 0xf2, 0xd6, 0x44, 0x1e, 0xa3,
+ 0xe4, 0xcf, 0x87, 0x5d, 0x13, 0xda, 0x78, 0x16, 0xda, 0x91, 0x29, 0x2c,
+ 0x47, 0x3a, 0x1c, 0xa2, 0x0f, 0xfe, 0x39, 0x1c, 0x1a, 0x5d, 0x38, 0x6e,
+ 0x62, 0x55, 0x28, 0x45, 0xfb, 0x26, 0xf1, 0x70, 0x19, 0xe2, 0xbd, 0x1f,
+ 0x2b, 0x85, 0xd7, 0xe2, 0x5d, 0x18, 0xa3, 0x3c, 0x5d, 0x79, 0x3f, 0xee,
+ 0x9f, 0xa8, 0xc0, 0xbd, 0x13, 0x16, 0xee, 0x4b, 0x22, 0x55, 0x41, 0x79,
+ 0x12, 0xc9, 0x78, 0xf4, 0x3d, 0x78, 0xd0, 0x9e, 0xef, 0x62, 0x2c, 0x6d,
+ 0x40, 0xba, 0xcc, 0x87, 0x0d, 0xf9, 0x00, 0xe3, 0x31, 0x8d, 0xd3, 0x93,
+ 0x3e, 0x78, 0x57, 0xbb, 0x30, 0x15, 0x2e, 0x43, 0xa2, 0xde, 0xc5, 0x4f,
+ 0x38, 0xd8, 0x36, 0x59, 0x17, 0xdc, 0x68, 0x7a, 0xb0, 0xd7, 0x74, 0x61,
+ 0x68, 0xc2, 0xb2, 0xda, 0x0d, 0x0b, 0x57, 0x57, 0x87, 0xf0, 0x3c, 0xf5,
+ 0x77, 0xc0, 0x8c, 0xe0, 0x6c, 0xe1, 0x51, 0xf2, 0x12, 0x76, 0xf8, 0x35,
+ 0xc9, 0xbb, 0x49, 0xde, 0x4d, 0xf2, 0x6d, 0x0a, 0x9f, 0xe7, 0x19, 0x33,
+ 0x06, 0xe5, 0xf2, 0x93, 0x87, 0x4a, 0xf4, 0x93, 0x8f, 0x58, 0xd2, 0x82,
+ 0x2b, 0xa9, 0x65, 0x77, 0x31, 0x79, 0x2d, 0xad, 0xb7, 0xac, 0x8f, 0x57,
+ 0x8b, 0x2c, 0xb4, 0xb9, 0xab, 0x4b, 0x62, 0xf4, 0xf7, 0xaa, 0x18, 0x57,
+ 0x7f, 0x4b, 0xbd, 0x3d, 0x5e, 0xf0, 0x63, 0x70, 0xc2, 0xf6, 0xdb, 0x83,
+ 0x65, 0xe4, 0x5b, 0xf8, 0x2a, 0xe8, 0x71, 0xc6, 0x68, 0x3c, 0xc3, 0x18,
+ 0xc5, 0x56, 0xf2, 0x7c, 0x9f, 0x19, 0x6f, 0xd9, 0xae, 0x3c, 0xd8, 0x94,
+ 0x0f, 0x07, 0xdb, 0x6f, 0xe0, 0x93, 0xf2, 0x4a, 0x0c, 0x52, 0xd6, 0x10,
+ 0xf9, 0x0b, 0x63, 0x37, 0xf9, 0x7c, 0xae, 0xc8, 0xe7, 0x74, 0x41, 0xd6,
+ 0xfa, 0x3c, 0xaf, 0x25, 0x3e, 0x91, 0x5d, 0x94, 0x0a, 0x2b, 0x54, 0x04,
+ 0xb0, 0x3d, 0xff, 0x26, 0x6d, 0x51, 0x87, 0xbf, 0xa0, 0x0d, 0x5e, 0x60,
+ 0x8c, 0xfc, 0xf0, 0x9a, 0xbf, 0x88, 0x3d, 0x1e, 0xa1, 0x1d, 0xb4, 0xd3,
+ 0x59, 0x04, 0xd0, 0x5b, 0x48, 0xe3, 0xd0, 0x24, 0xd2, 0x33, 0xc6, 0x31,
+ 0xc6, 0xfb, 0x12, 0xb8, 0xf5, 0xf2, 0x74, 0x48, 0xaf, 0xc0, 0xee, 0xe9,
+ 0x30, 0x06, 0x0a, 0x6d, 0x30, 0x27, 0xc2, 0xd8, 0x47, 0xdf, 0xbc, 0x92,
+ 0x4c, 0xdf, 0x17, 0x84, 0xf0, 0x1e, 0xc6, 0xfd, 0x7c, 0xe7, 0xb1, 0xc9,
+ 0x30, 0xfa, 0xa9, 0xa3, 0xcd, 0xc9, 0x78, 0x8b, 0x9f, 0xd7, 0xf6, 0xf2,
+ 0xda, 0x61, 0xea, 0xff, 0xbc, 0x31, 0x86, 0xde, 0x6e, 0x2d, 0x01, 0x84,
+ 0xb1, 0xc7, 0x44, 0x88, 0x2e, 0xfc, 0x08, 0xf3, 0x5b, 0xe2, 0x3c, 0xff,
+ 0xbe, 0xa7, 0x50, 0x41, 0x39, 0x83, 0x88, 0xe8, 0x9f, 0x58, 0xde, 0x66,
+ 0xcb, 0xfa, 0xbe, 0x11, 0xbf, 0xf8, 0x96, 0xdb, 0x83, 0x87, 0x0a, 0x2e,
+ 0x0c, 0x4e, 0x57, 0xe0, 0x0f, 0x27, 0x3c, 0xb8, 0xb3, 0xbe, 0x02, 0x07,
+ 0xa6, 0xd3, 0x18, 0x99, 0xac, 0x40, 0xdf, 0x04, 0x96, 0xee, 0x31, 0x46,
+ 0x6a, 0xca, 0xa0, 0x2d, 0xb4, 0x23, 0x81, 0xab, 0xb4, 0xc3, 0x43, 0xd3,
+ 0x81, 0x60, 0x66, 0x32, 0x84, 0xc1, 0x59, 0x3f, 0x9f, 0x77, 0xf1, 0xf9,
+ 0x72, 0x18, 0xab, 0x62, 0x83, 0x21, 0x08, 0x8f, 0x95, 0xd8, 0x3f, 0xed,
+ 0xc7, 0x03, 0x13, 0x21, 0xec, 0x9b, 0x6c, 0xc6, 0xb8, 0x99, 0xc6, 0x51,
+ 0xe6, 0x8e, 0x1f, 0x24, 0xb5, 0xee, 0x7d, 0x4a, 0x4b, 0x6f, 0x54, 0x69,
+ 0x34, 0x24, 0xbd, 0xb8, 0xc4, 0x3c, 0xe4, 0x4d, 0x36, 0xb6, 0x3c, 0xcb,
+ 0xdc, 0x50, 0x96, 0x0a, 0xf3, 0x6f, 0xed, 0x08, 0x63, 0x36, 0xed, 0x75,
+ 0xad, 0x06, 0x16, 0x4b, 0xfc, 0x86, 0x83, 0x5b, 0xcc, 0x50, 0x70, 0x4b,
+ 0xa1, 0x2e, 0xb8, 0xd9, 0x8c, 0x04, 0x37, 0x33, 0xbe, 0x36, 0x8a, 0x3f,
+ 0x9a, 0x3e, 0x1c, 0x4b, 0x7e, 0x6a, 0xf5, 0xd6, 0xd8, 0xf9, 0x2c, 0xb8,
+ 0x6d, 0x52, 0xcb, 0x4e, 0x41, 0x33, 0x58, 0x0d, 0x30, 0x36, 0xeb, 0xa1,
+ 0xfd, 0x14, 0x6a, 0xf4, 0x66, 0xe6, 0xf1, 0x10, 0xf6, 0x33, 0xa7, 0xfc,
+ 0x15, 0x73, 0x4a, 0xdf, 0xf1, 0x58, 0x68, 0x1c, 0x7e, 0xea, 0x1b, 0xd8,
+ 0x75, 0x2e, 0x4c, 0x9b, 0x77, 0xe2, 0x51, 0xf2, 0xb5, 0x79, 0x4d, 0x18,
+ 0xf7, 0x16, 0x42, 0xc1, 0x4e, 0xda, 0xef, 0xbd, 0x7c, 0x24, 0xb8, 0x81,
+ 0xb6, 0x7c, 0x3b, 0xaf, 0x45, 0xe7, 0xf1, 0x8f, 0xe2, 0x4f, 0x09, 0xb8,
+ 0x80, 0x3d, 0xc7, 0xbd, 0x98, 0x0f, 0xcb, 0x5a, 0xd4, 0xb9, 0xf9, 0x82,
+ 0x15, 0xd0, 0xf5, 0xd3, 0xfb, 0xa8, 0xeb, 0x6f, 0x17, 0x02, 0x78, 0xc0,
+ 0xd4, 0x12, 0x3f, 0x54, 0x01, 0xea, 0xd4, 0x47, 0x3d, 0x30, 0xc1, 0x2c,
+ 0x91, 0xe7, 0x92, 0x88, 0x2e, 0x71, 0x72, 0xed, 0x81, 0x69, 0xf1, 0x13,
+ 0xda, 0xde, 0xa4, 0x0f, 0xd0, 0x7f, 0x7e, 0x78, 0x2d, 0x56, 0xb5, 0x50,
+ 0xd6, 0xce, 0xdd, 0x09, 0xfa, 0x8b, 0xa3, 0xa3, 0x13, 0x93, 0xa2, 0x07,
+ 0x6d, 0x1c, 0xae, 0x34, 0x56, 0xae, 0xfa, 0x2b, 0xeb, 0xd2, 0x62, 0xd1,
+ 0x47, 0x08, 0x43, 0xd4, 0xe1, 0x69, 0xd3, 0xb2, 0xae, 0xae, 0xfe, 0xd0,
+ 0x6a, 0xb9, 0x59, 0xf4, 0x22, 0xb2, 0x3e, 0xaf, 0xa4, 0x8e, 0xd4, 0xe8,
+ 0xc1, 0xff, 0x0f, 0xbe, 0xf2, 0x1d, 0xab, 0xd7, 0x96, 0x4f, 0xfc, 0xc5,
+ 0x43, 0x5f, 0x7c, 0x94, 0xb4, 0x5d, 0xe8, 0x25, 0xbd, 0x07, 0x4d, 0xeb,
+ 0xa3, 0xda, 0xd4, 0x67, 0x56, 0xcb, 0x5a, 0x7d, 0x60, 0x41, 0xfd, 0x0f,
+ 0x5e, 0x0f, 0x63, 0x7f, 0xa1, 0x85, 0xba, 0x6b, 0xc7, 0x63, 0xd4, 0xe1,
+ 0x61, 0x53, 0x72, 0x62, 0x84, 0xfe, 0x5c, 0x47, 0xff, 0xf6, 0xa8, 0x8d,
+ 0x66, 0x1e, 0x9b, 0xc7, 0xb2, 0xd8, 0x44, 0x7f, 0xbf, 0x98, 0x8b, 0xb5,
+ 0x3c, 0x0d, 0x2d, 0x4b, 0x19, 0x82, 0x9d, 0xd4, 0x71, 0xbb, 0xa9, 0x75,
+ 0x8a, 0x4d, 0xdb, 0x99, 0x97, 0x5e, 0xcc, 0x45, 0x82, 0x6d, 0x05, 0xd1,
+ 0x77, 0x5d, 0x70, 0x43, 0xe1, 0xab, 0xb4, 0xbd, 0xc2, 0xba, 0xe5, 0x3e,
+ 0xe6, 0x99, 0x3b, 0xe1, 0xd8, 0xd5, 0xb1, 0xdd, 0x6b, 0xc9, 0xc6, 0xde,
+ 0x0f, 0x99, 0x9f, 0xb2, 0x8b, 0x9d, 0x6b, 0x83, 0xbc, 0x56, 0xbd, 0x1a,
+ 0xc1, 0x3b, 0xe8, 0x07, 0x77, 0xd3, 0x0f, 0xae, 0xae, 0xfe, 0xd4, 0x8a,
+ 0xde, 0xe4, 0xf8, 0x41, 0xdb, 0xa4, 0x27, 0xd8, 0x41, 0x3d, 0x6d, 0x34,
+ 0x14, 0xa6, 0x8d, 0x1c, 0x7a, 0xaf, 0x61, 0x87, 0xf4, 0xd4, 0x59, 0x23,
+ 0xcd, 0x3c, 0xf2, 0xbb, 0xf0, 0xd4, 0x60, 0xea, 0x69, 0xe3, 0x51, 0x44,
+ 0x1d, 0xdf, 0xc1, 0xbe, 0x09, 0x3f, 0xb2, 0x77, 0x86, 0x30, 0xd3, 0x10,
+ 0xc2, 0x83, 0xa4, 0x7d, 0x25, 0xd9, 0xd8, 0xff, 0x3a, 0x75, 0x30, 0x55,
+ 0x23, 0xd7, 0xd2, 0xf8, 0x91, 0xf1, 0x30, 0x70, 0x93, 0xb3, 0xf6, 0xac,
+ 0xc4, 0xe8, 0x6c, 0x33, 0x0e, 0x17, 0x32, 0xca, 0xc9, 0x9b, 0x5a, 0x67,
+ 0x1a, 0x3f, 0xb7, 0x24, 0x97, 0xce, 0x9a, 0xcc, 0x71, 0xd4, 0xc7, 0x28,
+ 0xfd, 0x68, 0x38, 0x5f, 0x17, 0xdc, 0x44, 0x3f, 0x7a, 0x34, 0x2f, 0x32,
+ 0xc5, 0x0d, 0xc3, 0x5d, 0xcb, 0xda, 0x4c, 0xfd, 0x98, 0x76, 0xcd, 0xaf,
+ 0x0e, 0xe9, 0x47, 0x31, 0x6e, 0xf3, 0x36, 0xa8, 0x32, 0xc4, 0x18, 0x0c,
+ 0x99, 0xea, 0x72, 0xfd, 0x00, 0x1e, 0xb5, 0xaf, 0x85, 0x83, 0x3b, 0x26,
+ 0xd3, 0x2e, 0x97, 0x8e, 0x50, 0x65, 0xaa, 0x5d, 0xed, 0x60, 0xdd, 0xed,
+ 0x98, 0xec, 0x50, 0x1d, 0xb3, 0x12, 0x03, 0x9d, 0x6a, 0x33, 0x6b, 0x6e,
+ 0x9a, 0x35, 0x37, 0xcd, 0x9a, 0x9b, 0x26, 0x1f, 0x69, 0xd6, 0xda, 0xb6,
+ 0xc2, 0xa0, 0xda, 0x2a, 0xfa, 0xa7, 0x7f, 0x3d, 0x6b, 0x3a, 0x38, 0x82,
+ 0x39, 0x28, 0xb8, 0xa9, 0xb0, 0xc2, 0xe5, 0x60, 0xbb, 0x41, 0x55, 0xc4,
+ 0x32, 0xbe, 0x0a, 0x9d, 0xb5, 0xcc, 0x1c, 0x54, 0x5b, 0x58, 0x6f, 0x33,
+ 0xb6, 0x2e, 0x63, 0x03, 0xef, 0xb0, 0xce, 0xbe, 0xc6, 0x3a, 0x9b, 0x4f,
+ 0x32, 0xae, 0x96, 0x5f, 0xb5, 0x7a, 0x17, 0x3b, 0x35, 0x61, 0x84, 0xfc,
+ 0x7e, 0x9f, 0x36, 0x9b, 0x67, 0x2d, 0x6d, 0x77, 0x2b, 0xec, 0xd1, 0x51,
+ 0x5d, 0xcb, 0x9c, 0x7a, 0xb8, 0xc0, 0x3a, 0x60, 0xc4, 0x5a, 0xde, 0xa7,
+ 0x62, 0x0f, 0xeb, 0x5e, 0x5c, 0xbd, 0x89, 0x60, 0x47, 0x6f, 0xc3, 0xb1,
+ 0x89, 0x72, 0xf4, 0x27, 0xd3, 0x8b, 0x7c, 0xc4, 0x2a, 0x9d, 0xcd, 0x78,
+ 0x98, 0x4b, 0xab, 0x48, 0x2a, 0x4e, 0xbf, 0x41, 0xfa, 0x38, 0xeb, 0xc4,
+ 0x98, 0xf9, 0x55, 0xe4, 0x59, 0x4f, 0x67, 0x0c, 0x0f, 0x5e, 0xcb, 0xaf,
+ 0x60, 0x9e, 0x8b, 0x1b, 0x01, 0x55, 0xc1, 0xf8, 0x4d, 0x21, 0x67, 0x4a,
+ 0x7e, 0xb2, 0xac, 0x19, 0xe1, 0x21, 0x1e, 0x4f, 0x0f, 0x43, 0x72, 0x96,
+ 0xb5, 0xf4, 0x9e, 0x64, 0x19, 0xd6, 0xc5, 0x83, 0x58, 0xaa, 0xf7, 0xaa,
+ 0xce, 0x42, 0xdc, 0x38, 0x8f, 0x6f, 0xa9, 0xbb, 0x67, 0x53, 0x8c, 0xed,
+ 0x0c, 0x75, 0x53, 0x81, 0x4b, 0x61, 0xe1, 0x11, 0xd5, 0x5e, 0xdd, 0x85,
+ 0x77, 0xef, 0x52, 0x08, 0xe9, 0x69, 0x5c, 0x68, 0x0e, 0xd1, 0xaf, 0x3a,
+ 0x89, 0x31, 0xa2, 0x70, 0xcf, 0x45, 0x82, 0x5b, 0x69, 0x8b, 0xca, 0xb9,
+ 0x3a, 0xda, 0x87, 0xbe, 0x47, 0x1d, 0xb6, 0x51, 0x87, 0x5b, 0xa6, 0x11,
+ 0xaa, 0x48, 0xf5, 0xa8, 0x8e, 0x42, 0xbb, 0x6a, 0x2f, 0x68, 0xd4, 0x93,
+ 0xe8, 0xe4, 0x3b, 0xc4, 0x4a, 0xe2, 0x2b, 0x25, 0x5b, 0x8a, 0xbf, 0xde,
+ 0x68, 0xcf, 0x8c, 0x4b, 0x62, 0x6e, 0xdd, 0xf2, 0x14, 0xe3, 0xd1, 0x45,
+ 0xbe, 0x84, 0x07, 0x1f, 0xaa, 0x1b, 0xac, 0xa5, 0x57, 0x92, 0x4c, 0x9e,
+ 0x15, 0x29, 0x1c, 0x2f, 0x74, 0xd1, 0x2e, 0xab, 0x8b, 0xfe, 0x15, 0x0a,
+ 0x6e, 0x9c, 0x6c, 0x57, 0x1b, 0x67, 0x17, 0x05, 0xbb, 0x69, 0xc3, 0xee,
+ 0xd9, 0x88, 0xd0, 0xe5, 0xfa, 0x62, 0xdb, 0x34, 0x5c, 0xfa, 0xbf, 0x64,
+ 0xcb, 0x6f, 0x93, 0x96, 0xd8, 0xd3, 0x5f, 0xf2, 0xd3, 0xe0, 0xdd, 0x93,
+ 0x69, 0xbc, 0xbb, 0xda, 0xcb, 0x9a, 0x5a, 0xc2, 0x14, 0x55, 0xc5, 0xef,
+ 0xd3, 0x2e, 0xe8, 0x83, 0xaa, 0x53, 0xfc, 0xc8, 0xeb, 0xac, 0x79, 0xc7,
+ 0x24, 0xbc, 0x84, 0x0a, 0x51, 0x37, 0x31, 0xdd, 0x87, 0xc9, 0x78, 0xef,
+ 0x39, 0xd5, 0xa5, 0xba, 0x0a, 0x52, 0x83, 0x1d, 0x9f, 0x6a, 0xa3, 0x4f,
+ 0xb5, 0x93, 0x9f, 0x76, 0xfa, 0xd4, 0x16, 0xf2, 0xb3, 0xc5, 0xf6, 0x29,
+ 0xf1, 0xcd, 0xdf, 0xe6, 0x65, 0x43, 0xe1, 0x6e, 0x5b, 0x2f, 0x5b, 0xf9,
+ 0x6e, 0x27, 0xe5, 0xe8, 0xe4, 0x7b, 0x77, 0xf3, 0xbd, 0xbb, 0x67, 0xff,
+ 0x97, 0xf0, 0x47, 0x59, 0x9c, 0xd8, 0xbf, 0x5e, 0xd3, 0x24, 0x07, 0xfc,
+ 0xac, 0x88, 0x29, 0x90, 0x75, 0xa5, 0x24, 0x47, 0x0c, 0xa0, 0xbb, 0x19,
+ 0xbe, 0x45, 0xa9, 0x67, 0x5b, 0xb7, 0xd7, 0x33, 0x9f, 0x31, 0x9f, 0xfa,
+ 0x8e, 0x13, 0x4b, 0x33, 0x47, 0xcf, 0xb4, 0x28, 0x8c, 0x18, 0x37, 0x33,
+ 0x4e, 0x0d, 0x1c, 0x29, 0x68, 0x9d, 0x51, 0xde, 0x6b, 0x1a, 0x13, 0x8c,
+ 0xbf, 0x0f, 0x6d, 0xc4, 0x75, 0x91, 0x54, 0x3f, 0x22, 0x66, 0x2c, 0x72,
+ 0x44, 0x69, 0xfd, 0x1b, 0xa0, 0x5d, 0x64, 0x6d, 0x18, 0x9c, 0x56, 0xda,
+ 0x40, 0xad, 0x5b, 0x4b, 0xbf, 0x61, 0xe3, 0xeb, 0x7d, 0x58, 0x6e, 0x63,
+ 0xb8, 0x7e, 0x24, 0x88, 0x65, 0xb7, 0x92, 0xe6, 0xde, 0x75, 0x0a, 0x97,
+ 0x8d, 0x0f, 0x69, 0x47, 0x2d, 0x9d, 0x55, 0x06, 0x72, 0xcc, 0x13, 0x91,
+ 0xe3, 0x82, 0xd5, 0xf7, 0x11, 0xab, 0xc3, 0x17, 0xe0, 0xb3, 0xb9, 0xb1,
+ 0xd8, 0xa0, 0xcf, 0xad, 0x25, 0x88, 0xd3, 0xd3, 0xa4, 0x69, 0x14, 0x88,
+ 0xdf, 0xb9, 0x46, 0x74, 0x4f, 0x91, 0x66, 0xbc, 0x48, 0x53, 0xcf, 0x83,
+ 0x71, 0x73, 0x04, 0x9b, 0xe2, 0xac, 0x15, 0xcc, 0x79, 0x47, 0xa5, 0x27,
+ 0x20, 0xbd, 0xf2, 0xe3, 0x06, 0xff, 0x1e, 0x54, 0x3b, 0x24, 0xa6, 0xca,
+ 0x1d, 0x2b, 0x54, 0x73, 0x8d, 0xaa, 0xd4, 0x41, 0xcc, 0xd9, 0x6b, 0x0c,
+ 0xc8, 0x1a, 0x03, 0xbf, 0x50, 0x5a, 0xe2, 0x9c, 0x92, 0x5c, 0xdd, 0x98,
+ 0x39, 0xc7, 0x18, 0x3a, 0xac, 0xb4, 0x96, 0x63, 0x14, 0xdf, 0xaf, 0x0b,
+ 0xfd, 0x83, 0xc5, 0x75, 0x06, 0xd0, 0x90, 0x67, 0x7c, 0x16, 0x7c, 0x6a,
+ 0xc3, 0x44, 0x1b, 0x46, 0xa6, 0xdb, 0x30, 0x3c, 0xa1, 0x70, 0xb7, 0xb1,
+ 0x18, 0x97, 0x6e, 0xb6, 0xfb, 0x94, 0xaa, 0xa5, 0x7a, 0x2d, 0x86, 0x42,
+ 0xa8, 0x76, 0xe9, 0x5f, 0xc1, 0xae, 0x22, 0xc6, 0xdf, 0x74, 0xa2, 0x9b,
+ 0x79, 0xdf, 0xc2, 0xfb, 0x8c, 0xa5, 0x58, 0x0d, 0xd2, 0xde, 0x54, 0x0b,
+ 0xf1, 0x78, 0x9d, 0xdb, 0x89, 0xf7, 0x0f, 0x7d, 0x8e, 0x0d, 0x44, 0xff,
+ 0x9f, 0xbf, 0xd7, 0x86, 0xc7, 0x27, 0xca, 0xd0, 0xb2, 0x1a, 0x77, 0x46,
+ 0x50, 0xe5, 0x62, 0x8d, 0x7b, 0x73, 0xbb, 0x1a, 0xe4, 0x3d, 0xfb, 0x59,
+ 0xdf, 0x97, 0x53, 0x46, 0xea, 0x4f, 0x1a, 0xe4, 0xba, 0x9d, 0x37, 0x6e,
+ 0xb8, 0xde, 0xfd, 0x05, 0xd7, 0x15, 0x9e, 0x61, 0x22, 0xfb, 0x01, 0x6b,
+ 0x4a, 0x3e, 0x67, 0xc1, 0x9d, 0xf2, 0xa0, 0x7f, 0x2c, 0x8a, 0x7d, 0x73,
+ 0x61, 0xcc, 0xe5, 0xb4, 0xde, 0x4b, 0xec, 0x1f, 0x76, 0x35, 0xeb, 0x78,
+ 0x60, 0x2e, 0x82, 0xd9, 0x1c, 0x2c, 0x7f, 0x4a, 0x9f, 0xf7, 0xab, 0x04,
+ 0xf6, 0xce, 0xd5, 0xe1, 0x5c, 0x4e, 0xbf, 0x38, 0xac, 0xe2, 0x83, 0xb5,
+ 0xc4, 0x1d, 0x0f, 0xce, 0x35, 0x61, 0xff, 0x9c, 0x8f, 0xef, 0x58, 0xd8,
+ 0x92, 0xac, 0xe3, 0xf3, 0x2e, 0x3c, 0x7d, 0xd2, 0xb2, 0x04, 0x77, 0xf5,
+ 0xcf, 0x01, 0xb3, 0xe3, 0xac, 0x45, 0x67, 0x58, 0x97, 0x9e, 0x00, 0xf6,
+ 0x3e, 0xe1, 0xc2, 0xf4, 0xb8, 0x85, 0x5d, 0xc6, 0x70, 0xad, 0x8b, 0x0e,
+ 0xdf, 0xcb, 0xba, 0xe1, 0x65, 0x0d, 0xbc, 0x27, 0xe4, 0xe4, 0xf3, 0x4b,
+ 0xcc, 0x53, 0xf7, 0x3d, 0x91, 0xc0, 0x9b, 0xb9, 0x2c, 0xb6, 0x10, 0x9f,
+ 0x0f, 0x92, 0x97, 0x37, 0x72, 0xac, 0x63, 0x73, 0x06, 0x5e, 0xcf, 0xf9,
+ 0xb8, 0x4e, 0x13, 0x5e, 0xca, 0xc9, 0x33, 0xf2, 0x6c, 0x00, 0x7d, 0xe4,
+ 0xe5, 0xb5, 0x5c, 0x84, 0x6b, 0x86, 0xf1, 0x53, 0x3e, 0x77, 0xef, 0x9c,
+ 0xce, 0xba, 0xe5, 0xe3, 0xba, 0x51, 0xbc, 0x92, 0x0b, 0x90, 0xd7, 0x30,
+ 0x6b, 0x55, 0x1f, 0x46, 0x72, 0x8d, 0x17, 0x37, 0x30, 0x51, 0x3b, 0xb5,
+ 0x46, 0xae, 0xbd, 0x63, 0x75, 0xd9, 0xb1, 0x28, 0xeb, 0x94, 0xd6, 0xed,
+ 0xc3, 0x70, 0xee, 0x75, 0x77, 0xa9, 0x9f, 0x7e, 0x66, 0x7c, 0xc1, 0xc6,
+ 0x7e, 0x4f, 0x9b, 0xfc, 0x7d, 0x1a, 0x38, 0x67, 0x66, 0xad, 0xea, 0x14,
+ 0xb1, 0x2e, 0x6b, 0xd4, 0x5b, 0x6b, 0x9a, 0xb8, 0xae, 0xde, 0xfb, 0xa2,
+ 0x92, 0x7e, 0xc7, 0x83, 0xe8, 0x13, 0xa2, 0x2f, 0x62, 0xe6, 0x59, 0xe0,
+ 0x47, 0xc4, 0x9f, 0x0d, 0x63, 0x9a, 0xf8, 0x7d, 0x86, 0xb8, 0xa6, 0x7b,
+ 0x1e, 0xf5, 0x89, 0x07, 0x30, 0x64, 0x95, 0x11, 0x9f, 0x57, 0x13, 0xd7,
+ 0xce, 0x35, 0xb1, 0x4e, 0xad, 0xb1, 0xac, 0xbf, 0x6d, 0x86, 0xe5, 0x4a,
+ 0xe9, 0x46, 0xad, 0x7b, 0xfe, 0x2b, 0x55, 0xd0, 0x2f, 0x06, 0x95, 0x3e,
+ 0xff, 0x16, 0xe2, 0x03, 0xe7, 0x21, 0x7a, 0x05, 0x56, 0xcc, 0x79, 0xb0,
+ 0x92, 0xf2, 0x6c, 0x1c, 0xe3, 0xda, 0xc4, 0x27, 0x71, 0xca, 0xb4, 0x6d,
+ 0x8c, 0x98, 0x4b, 0x0f, 0x60, 0x39, 0x75, 0xdc, 0x7f, 0xca, 0xb2, 0xca,
+ 0xa9, 0xe3, 0x06, 0xda, 0x67, 0xcf, 0x09, 0x0b, 0x2f, 0x1a, 0x2f, 0x52,
+ 0xa7, 0x8a, 0xb8, 0xb1, 0x99, 0xef, 0x84, 0xf9, 0xbc, 0x0f, 0x7b, 0xc7,
+ 0xa4, 0x5f, 0xaa, 0xe3, 0x33, 0xaf, 0xe2, 0x58, 0x2e, 0x81, 0x26, 0xea,
+ 0x2f, 0x4a, 0x9a, 0x8d, 0x7c, 0x27, 0x4a, 0x7a, 0xd1, 0xb9, 0xaf, 0x61,
+ 0xf3, 0x29, 0x05, 0x3d, 0x2e, 0x3a, 0xf8, 0x1a, 0xda, 0xcf, 0x7c, 0x51,
+ 0x4e, 0x60, 0x96, 0x1a, 0xd7, 0x8e, 0xcc, 0x13, 0x7f, 0x57, 0xa5, 0x86,
+ 0xc0, 0xfa, 0x8d, 0x37, 0xa6, 0x14, 0x8e, 0x8f, 0xb3, 0xdf, 0x5b, 0x03,
+ 0xab, 0x82, 0x32, 0xbd, 0x3e, 0xf5, 0x3b, 0x78, 0xea, 0x24, 0xf5, 0xf0,
+ 0x64, 0x18, 0x3f, 0xc8, 0x79, 0xb0, 0xec, 0xb8, 0x60, 0x3a, 0x3d, 0xb1,
+ 0x4f, 0x49, 0x7f, 0x24, 0x7d, 0x4b, 0x3c, 0xea, 0x55, 0x2e, 0xd4, 0x3f,
+ 0xe5, 0x81, 0x7e, 0x2e, 0x0a, 0x6f, 0xbd, 0x0f, 0x7a, 0xfd, 0x1f, 0x32,
+ 0xd7, 0xb8, 0x50, 0xc6, 0x5e, 0x76, 0xd3, 0x77, 0x13, 0xbc, 0x16, 0xe6,
+ 0x35, 0xfc, 0x4e, 0x39, 0xdc, 0x4b, 0xdc, 0xac, 0xe1, 0x65, 0x3a, 0xf1,
+ 0x98, 0xc7, 0xb2, 0xdc, 0xac, 0x0d, 0x3b, 0xbe, 0x67, 0x59, 0xb1, 0xd5,
+ 0xf2, 0x7c, 0x08, 0xb1, 0x73, 0x3a, 0x9f, 0x73, 0xea, 0xe5, 0x75, 0x3c,
+ 0xe6, 0xa6, 0x1f, 0x49, 0xac, 0xb2, 0xde, 0xdb, 0x3d, 0x94, 0x83, 0xdb,
+ 0x9f, 0x2b, 0x08, 0xb6, 0x89, 0xda, 0x32, 0x9c, 0x1d, 0x57, 0xcc, 0xd9,
+ 0x29, 0x3e, 0xbb, 0x1e, 0xee, 0xa4, 0x76, 0x24, 0x4b, 0x3f, 0xd8, 0x15,
+ 0x6a, 0xc1, 0x33, 0xa6, 0x17, 0x95, 0xfa, 0x12, 0xdc, 0xdf, 0x1d, 0xc2,
+ 0x33, 0xec, 0x0b, 0x68, 0xb3, 0xc4, 0x3c, 0xd8, 0x48, 0x07, 0x49, 0xcf,
+ 0xf5, 0x63, 0xe8, 0xdf, 0x75, 0x31, 0xcf, 0xb9, 0xed, 0x3c, 0x57, 0x56,
+ 0x0f, 0xcc, 0xe7, 0x3d, 0xb8, 0xa0, 0x3b, 0x98, 0xf0, 0x39, 0xbb, 0x66,
+ 0x6b, 0xa1, 0xf9, 0x6b, 0x58, 0x50, 0x6b, 0x49, 0x2b, 0x32, 0x13, 0x14,
+ 0xdd, 0x65, 0x3c, 0x8e, 0x2f, 0xfd, 0x8d, 0x5b, 0x7a, 0x8e, 0xeb, 0x7f,
+ 0x57, 0xc0, 0x95, 0xd2, 0x22, 0x6d, 0x6e, 0xf8, 0x3c, 0xa9, 0xce, 0xd6,
+ 0x51, 0xfd, 0x4b, 0x37, 0xf0, 0xde, 0x84, 0x91, 0xc2, 0xf5, 0x5e, 0xbb,
+ 0x33, 0x67, 0xfb, 0x50, 0xa7, 0xe8, 0xfe, 0x31, 0x43, 0xf2, 0xec, 0xa0,
+ 0x6a, 0x67, 0xde, 0xca, 0x7a, 0x90, 0xad, 0xe2, 0x33, 0xd4, 0x3f, 0x0e,
+ 0x8f, 0x09, 0x9d, 0x83, 0x18, 0xcd, 0xc9, 0x6c, 0x63, 0x00, 0xeb, 0xcc,
+ 0x58, 0xe2, 0x22, 0x7b, 0xe8, 0x43, 0x90, 0x39, 0x44, 0xe3, 0xfc, 0xcb,
+ 0x4a, 0x1b, 0xbc, 0xc5, 0xad, 0xf5, 0x2f, 0x28, 0x27, 0x6f, 0xad, 0x28,
+ 0xe6, 0xad, 0xe5, 0xf9, 0x25, 0xc1, 0x2e, 0xd6, 0x83, 0xae, 0xd9, 0x52,
+ 0x7d, 0xe8, 0x52, 0x9b, 0xec, 0xda, 0x9a, 0x51, 0x5b, 0x67, 0x7d, 0xaa,
+ 0x63, 0xc2, 0x87, 0x97, 0x89, 0xc5, 0xa6, 0x7a, 0x10, 0x5a, 0xb6, 0x06,
+ 0xfe, 0xad, 0x13, 0xdd, 0x28, 0xd7, 0xa5, 0x87, 0x2c, 0xc7, 0x26, 0xbb,
+ 0xae, 0xd5, 0x05, 0xbb, 0x58, 0x7f, 0xba, 0x0a, 0x3d, 0xcc, 0x7f, 0x08,
+ 0xf9, 0x53, 0xce, 0xcc, 0x40, 0x72, 0xe1, 0xed, 0x7c, 0xf7, 0x62, 0x72,
+ 0x11, 0xe0, 0xd4, 0x3f, 0x95, 0x61, 0x2f, 0x51, 0xbd, 0x5a, 0xe1, 0xd2,
+ 0x9d, 0x3e, 0x90, 0x16, 0x7b, 0xfe, 0x7c, 0xeb, 0x85, 0xf1, 0x6e, 0xd5,
+ 0x31, 0x3d, 0xe3, 0xdf, 0x68, 0xca, 0x2c, 0x62, 0xca, 0xdf, 0x4e, 0x1e,
+ 0xda, 0x67, 0x9f, 0xf4, 0x6f, 0x20, 0x4f, 0x1b, 0x66, 0x3f, 0x4f, 0x53,
+ 0xea, 0x4a, 0x7f, 0x6b, 0x1b, 0x63, 0x7b, 0x87, 0xf1, 0x91, 0x15, 0xfd,
+ 0xa6, 0xd0, 0x99, 0x2b, 0xea, 0x33, 0x4d, 0xbe, 0xc2, 0xbe, 0x4d, 0x85,
+ 0x90, 0x2f, 0x5d, 0x68, 0xf7, 0xb7, 0x99, 0xdd, 0xfe, 0x0d, 0x66, 0x8f,
+ 0xbf, 0xdd, 0xdc, 0x49, 0xda, 0x5d, 0xfe, 0x0e, 0x93, 0x71, 0x5d, 0xe8,
+ 0xa1, 0x5e, 0xbb, 0x31, 0x5a, 0xd8, 0x49, 0xec, 0x21, 0x34, 0x7b, 0x89,
+ 0x83, 0xfc, 0x94, 0x71, 0x88, 0x32, 0xce, 0x47, 0xbc, 0x48, 0x6b, 0x5e,
+ 0xea, 0x6b, 0xc4, 0xb6, 0xe3, 0x11, 0x7b, 0x16, 0x55, 0x91, 0x7a, 0xa0,
+ 0x75, 0xcb, 0x09, 0xe6, 0xfb, 0xd4, 0x9e, 0xd6, 0x65, 0xa7, 0x50, 0xe3,
+ 0x4d, 0x49, 0xef, 0xcc, 0x7e, 0x38, 0x1e, 0x37, 0xde, 0x43, 0x3c, 0xf2,
+ 0x32, 0x9f, 0x1d, 0xa6, 0xef, 0x8e, 0xd8, 0xf3, 0x07, 0x1a, 0x24, 0xdf,
+ 0x84, 0x2d, 0xa6, 0xcf, 0xbf, 0x8d, 0xbd, 0x59, 0x30, 0xa5, 0xb5, 0xdc,
+ 0xee, 0x96, 0x79, 0xc8, 0xfc, 0xef, 0x05, 0xd0, 0x84, 0xce, 0x82, 0x8f,
+ 0x72, 0x7d, 0x09, 0x7f, 0x7f, 0x92, 0x75, 0x0d, 0xe2, 0x87, 0x96, 0x75,
+ 0x2f, 0xfb, 0x9a, 0xa3, 0xf9, 0x3a, 0x5c, 0xb6, 0x6d, 0xec, 0xc1, 0xe1,
+ 0x7c, 0x14, 0xef, 0x50, 0x3e, 0xcf, 0x5c, 0x2d, 0xde, 0x1e, 0x77, 0x63,
+ 0xb7, 0x71, 0x5b, 0xb1, 0x5e, 0xb8, 0x70, 0x4f, 0xe2, 0x00, 0xb1, 0x83,
+ 0x0b, 0xd5, 0xc4, 0x6f, 0x0f, 0xda, 0xd7, 0xdc, 0xec, 0xff, 0xbe, 0x8e,
+ 0x41, 0xa7, 0x9e, 0x90, 0xc7, 0x9d, 0xe4, 0xb1, 0xd9, 0xbf, 0x61, 0x42,
+ 0xf3, 0xdf, 0x31, 0x01, 0x9f, 0x37, 0xb5, 0xab, 0xf5, 0xcc, 0x49, 0x0b,
+ 0x7d, 0xc6, 0xad, 0xb8, 0x72, 0x72, 0xb8, 0xdf, 0x43, 0xff, 0xf9, 0x65,
+ 0x32, 0x03, 0x73, 0x12, 0x17, 0x88, 0x3c, 0x5e, 0x0d, 0x30, 0xb7, 0x37,
+ 0x24, 0xe3, 0x21, 0xd6, 0x62, 0x63, 0x96, 0xb1, 0xd9, 0x01, 0xad, 0x9f,
+ 0x35, 0x39, 0xed, 0x4e, 0xc5, 0x7b, 0x47, 0x08, 0x1e, 0xab, 0xc8, 0x8f,
+ 0x9f, 0xb9, 0x3b, 0x30, 0x17, 0xf5, 0xef, 0x60, 0xbd, 0x89, 0xb0, 0xbf,
+ 0xf3, 0xc7, 0x71, 0x5b, 0x2d, 0xe2, 0x89, 0x05, 0xca, 0xed, 0x9d, 0x6b,
+ 0xf2, 0xdf, 0xce, 0xfa, 0x71, 0x39, 0x6e, 0x0d, 0xbd, 0x68, 0x04, 0x10,
+ 0x9c, 0x33, 0xa8, 0xef, 0x0c, 0x86, 0x67, 0xd9, 0x72, 0xc5, 0xd9, 0xf3,
+ 0xcf, 0xb5, 0xf8, 0xb7, 0x31, 0x36, 0xab, 0x68, 0xa2, 0xc6, 0xb9, 0xb4,
+ 0x5f, 0x7a, 0xbe, 0xa6, 0xb9, 0xb5, 0xe4, 0x4f, 0x7c, 0x74, 0x5f, 0xeb,
+ 0x3a, 0xfa, 0x43, 0x74, 0x0e, 0x9b, 0x98, 0xe6, 0x5e, 0x22, 0xcd, 0x4c,
+ 0x84, 0x18, 0x76, 0xef, 0x9a, 0x00, 0xf3, 0x94, 0xe8, 0x92, 0x7a, 0x2c,
+ 0x94, 0x64, 0x92, 0xba, 0xbc, 0xa7, 0x75, 0xee, 0x94, 0xd4, 0xe5, 0x4c,
+ 0x6b, 0xee, 0x94, 0x8e, 0x77, 0x58, 0x5b, 0x56, 0x24, 0x35, 0xe3, 0x9c,
+ 0x8a, 0x45, 0x5e, 0xa5, 0x2c, 0x1e, 0xfc, 0xca, 0xda, 0xa5, 0xc7, 0xe7,
+ 0x6f, 0x61, 0x3c, 0x55, 0x33, 0x37, 0x46, 0x98, 0xf3, 0xab, 0xe7, 0xa8,
+ 0x98, 0x39, 0xb7, 0x17, 0x15, 0x11, 0xf8, 0xe2, 0x3a, 0xde, 0x3d, 0x99,
+ 0xa0, 0x1e, 0xae, 0xd1, 0xdc, 0x47, 0xa8, 0xd5, 0xc7, 0x52, 0xf8, 0xc8,
+ 0x53, 0xf4, 0xc5, 0x51, 0xae, 0x5b, 0x36, 0x27, 0x3c, 0xcb, 0xf3, 0x61,
+ 0x3e, 0x7f, 0x7d, 0xed, 0x6a, 0xae, 0xfd, 0xd1, 0x29, 0xf1, 0xd7, 0x4c,
+ 0xeb, 0x85, 0x93, 0xce, 0xda, 0xf1, 0x64, 0x02, 0x1f, 0x9e, 0xd4, 0x06,
+ 0xde, 0x55, 0xb1, 0xde, 0x0b, 0x4a, 0xd6, 0x47, 0x5d, 0x15, 0xae, 0x58,
+ 0xc3, 0xf1, 0xf8, 0xe0, 0x2e, 0xd2, 0x6c, 0x59, 0x4b, 0xfd, 0xdb, 0x7c,
+ 0xd0, 0xe7, 0x99, 0x67, 0xbd, 0xe4, 0xc7, 0xe1, 0xa5, 0x8e, 0xb4, 0x4f,
+ 0x16, 0x7b, 0x35, 0xf6, 0xa9, 0xd7, 0xf9, 0x09, 0x53, 0x0f, 0xbe, 0x1d,
+ 0xcd, 0x01, 0xd4, 0xda, 0xcf, 0x85, 0xf8, 0x9c, 0xe8, 0xe1, 0xd7, 0xca,
+ 0xa5, 0xbf, 0xc7, 0x3c, 0x26, 0xb9, 0x24, 0xcc, 0x1c, 0xb6, 0x53, 0x7a,
+ 0xda, 0x6c, 0x96, 0xfe, 0xee, 0xa5, 0xbf, 0x6f, 0x14, 0x9f, 0x36, 0xe9,
+ 0xd3, 0x26, 0x7d, 0xda, 0xd4, 0x22, 0x03, 0x88, 0x85, 0xfa, 0x68, 0xb7,
+ 0x74, 0x44, 0x7c, 0xbd, 0x07, 0xbb, 0xf9, 0xd9, 0xc3, 0xfb, 0x87, 0xd9,
+ 0xe7, 0x62, 0x91, 0xac, 0x79, 0x10, 0xed, 0xe6, 0x23, 0xe8, 0x9f, 0xc0,
+ 0x6f, 0xfc, 0xcd, 0xe5, 0x28, 0x5f, 0x2e, 0x3d, 0xbc, 0x16, 0x3a, 0x8a,
+ 0x47, 0xd8, 0x47, 0xfd, 0x5a, 0x55, 0xea, 0x9e, 0xee, 0x63, 0x4a, 0x0b,
+ 0xb5, 0xb3, 0x1f, 0xde, 0x55, 0xd8, 0x49, 0xfb, 0xc6, 0xfa, 0x5f, 0x56,
+ 0xec, 0xa5, 0x6a, 0xb9, 0x36, 0x63, 0xe9, 0x0e, 0xae, 0x63, 0x0a, 0x1f,
+ 0x76, 0xbe, 0xfd, 0x7d, 0x88, 0x6e, 0x7f, 0xd2, 0xd0, 0xc7, 0xf5, 0x1d,
+ 0x3e, 0x86, 0xd9, 0x53, 0xf6, 0x31, 0xc6, 0x76, 0xdb, 0xf1, 0xd5, 0x43,
+ 0x1a, 0xd7, 0xf3, 0xd8, 0x86, 0x9c, 0xd4, 0x52, 0x0b, 0x8f, 0x1a, 0x16,
+ 0x9e, 0xe6, 0xe7, 0x22, 0x73, 0xd9, 0xc8, 0x0d, 0xb9, 0xcc, 0xc5, 0xe7,
+ 0x76, 0xf0, 0xb9, 0x16, 0xa6, 0xce, 0xd9, 0x69, 0x99, 0x0d, 0x1e, 0x94,
+ 0xd9, 0x20, 0xf2, 0xa6, 0xe8, 0x7e, 0x00, 0x17, 0x72, 0xb1, 0x41, 0xb7,
+ 0xdb, 0x1a, 0x62, 0x5c, 0x5d, 0xfc, 0x88, 0xbe, 0xfb, 0xda, 0x1a, 0xad,
+ 0x9b, 0x3a, 0x4c, 0x8c, 0x29, 0x2d, 0xf2, 0x33, 0xcc, 0x6f, 0xf2, 0xa1,
+ 0x31, 0xba, 0xd2, 0x1d, 0x0f, 0x9d, 0x85, 0x36, 0xdf, 0x47, 0x49, 0x9f,
+ 0x2c, 0x38, 0xb9, 0x6e, 0x5d, 0x31, 0xd7, 0xb5, 0xe4, 0x2b, 0xd4, 0x1d,
+ 0x13, 0xac, 0xcf, 0xd3, 0x56, 0x36, 0xc8, 0x7a, 0x55, 0x98, 0x16, 0xda,
+ 0x43, 0x68, 0x4c, 0x0a, 0x2d, 0xbd, 0x73, 0x4c, 0xe1, 0x1b, 0x95, 0x88,
+ 0xb3, 0x56, 0xc1, 0x28, 0xd7, 0xb3, 0x16, 0x6b, 0x52, 0xc8, 0x9b, 0x92,
+ 0xda, 0xd9, 0xc5, 0xbe, 0xa5, 0x87, 0x79, 0x51, 0x30, 0xb5, 0xcc, 0x4b,
+ 0x9d, 0x7c, 0xb4, 0xb1, 0x20, 0x76, 0x11, 0x9b, 0x88, 0x6d, 0x0e, 0xe2,
+ 0x1e, 0x53, 0x7a, 0x7f, 0x0b, 0xe3, 0x46, 0x3c, 0xfa, 0x14, 0xc4, 0x4e,
+ 0x07, 0xa9, 0x0b, 0x2f, 0x76, 0x33, 0x0f, 0xee, 0x6a, 0xa6, 0xae, 0x82,
+ 0x5e, 0xec, 0xb2, 0x67, 0x09, 0x25, 0xfd, 0x79, 0x69, 0x43, 0xc5, 0x1a,
+ 0x37, 0xeb, 0x75, 0xf4, 0xe8, 0xcc, 0x26, 0xdd, 0x29, 0xa1, 0x57, 0x9a,
+ 0x4b, 0x3a, 0xba, 0xdb, 0x94, 0x13, 0xba, 0x16, 0xce, 0x1a, 0x0e, 0x6e,
+ 0x2d, 0xe9, 0x2c, 0x42, 0xb9, 0x6a, 0xd6, 0x02, 0x2b, 0x6f, 0xc0, 0xae,
+ 0x15, 0xbc, 0xb6, 0xe5, 0x3a, 0x76, 0xcd, 0x08, 0x3e, 0x26, 0x76, 0xed,
+ 0xdc, 0x4a, 0xec, 0x5a, 0xaf, 0x4a, 0xb8, 0x55, 0xe6, 0x12, 0x25, 0xec,
+ 0x5a, 0x5d, 0xcc, 0xd1, 0x07, 0xb1, 0x8b, 0xb8, 0xa6, 0xb6, 0x7e, 0x08,
+ 0xbe, 0x55, 0xae, 0xcf, 0x5c, 0x18, 0x62, 0xbf, 0x52, 0x06, 0x2c, 0xb6,
+ 0x70, 0xcb, 0xea, 0xac, 0x55, 0xae, 0xd7, 0x47, 0xcb, 0x5d, 0x32, 0x77,
+ 0x8e, 0x67, 0x47, 0x98, 0x4b, 0x5c, 0xab, 0xb4, 0x6c, 0x1a, 0xbe, 0x50,
+ 0x8d, 0xbe, 0xb3, 0xd8, 0x2f, 0x44, 0x7c, 0x9b, 0x89, 0x7b, 0xe2, 0xc9,
+ 0x4f, 0xad, 0xa9, 0xb0, 0xd0, 0x98, 0x9f, 0xf7, 0x21, 0xfd, 0x90, 0x8f,
+ 0x75, 0x68, 0x41, 0x1d, 0xc1, 0x6b, 0xf1, 0x88, 0x6f, 0x5b, 0x21, 0xeb,
+ 0xdf, 0xd2, 0x70, 0x0b, 0xba, 0x4e, 0x49, 0xcd, 0x89, 0x62, 0xeb, 0xa9,
+ 0x76, 0xd6, 0x19, 0x1d, 0x1d, 0x63, 0x9d, 0xec, 0xe3, 0xba, 0x55, 0xf7,
+ 0xb4, 0xe8, 0x49, 0xf4, 0xac, 0x85, 0xa2, 0xae, 0x1b, 0xe7, 0xa2, 0xa5,
+ 0x9e, 0xf8, 0x3d, 0xdb, 0x87, 0x46, 0x8d, 0x10, 0xf5, 0xf3, 0x2b, 0x2f,
+ 0x82, 0x16, 0xce, 0x18, 0xe2, 0x7b, 0xfc, 0xdb, 0x4c, 0x63, 0x63, 0xf3,
+ 0xb8, 0xe5, 0xd1, 0x65, 0xbe, 0x1d, 0xb1, 0xed, 0xb6, 0x81, 0xb5, 0xac,
+ 0x7d, 0xba, 0x87, 0xb6, 0x2a, 0xcd, 0xb2, 0x6f, 0xb4, 0xd9, 0x7a, 0xff,
+ 0x46, 0xe6, 0x35, 0xf6, 0xe9, 0x3e, 0x1f, 0x73, 0xa5, 0xef, 0x94, 0x85,
+ 0x69, 0xe3, 0x4d, 0xeb, 0x51, 0xdd, 0x43, 0xbb, 0x7c, 0x95, 0x79, 0x57,
+ 0x70, 0x49, 0xca, 0x7f, 0xfb, 0xa4, 0xc7, 0x55, 0x95, 0x42, 0x73, 0x19,
+ 0x7d, 0xee, 0xd5, 0xa4, 0x33, 0x73, 0x3c, 0x96, 0xbf, 0xcd, 0xbf, 0x65,
+ 0x82, 0xbd, 0x04, 0x7b, 0x5d, 0xa7, 0xbf, 0xfb, 0xaa, 0xff, 0xee, 0x09,
+ 0xb7, 0xaa, 0x4d, 0xc1, 0xdd, 0xb2, 0xd6, 0xc2, 0xc7, 0xab, 0xe3, 0x83,
+ 0x11, 0x17, 0x73, 0x24, 0x69, 0x99, 0xf9, 0x66, 0x7f, 0x86, 0x39, 0x79,
+ 0xdb, 0x04, 0xd2, 0x32, 0x9f, 0x0d, 0xae, 0x1e, 0xee, 0x0d, 0x42, 0x66,
+ 0x69, 0xf8, 0x06, 0xa3, 0x32, 0x4c, 0x9f, 0x8b, 0xb4, 0xa9, 0xf8, 0x42,
+ 0x3f, 0xe2, 0x17, 0x3f, 0x76, 0xbf, 0x69, 0x3d, 0x9e, 0x5f, 0xcb, 0xe7,
+ 0x3b, 0x99, 0x2f, 0xd3, 0xcc, 0x9f, 0xc3, 0x83, 0x5e, 0xc8, 0x3b, 0x5a,
+ 0xe6, 0x0d, 0x15, 0xa3, 0xaf, 0xe3, 0x9b, 0x7c, 0x3e, 0xd4, 0xc1, 0x5c,
+ 0x39, 0x6d, 0xc4, 0xd3, 0x1b, 0x90, 0xed, 0xac, 0x86, 0x66, 0x34, 0x28,
+ 0x99, 0x7d, 0x89, 0x1d, 0x12, 0xf8, 0x39, 0xd7, 0xf4, 0xe8, 0xa2, 0xc7,
+ 0xf5, 0xe8, 0x9b, 0x66, 0xfd, 0xbf, 0xe6, 0x6f, 0xa2, 0x03, 0xd1, 0xcb,
+ 0x37, 0xcb, 0x50, 0xb1, 0x88, 0xb2, 0xfd, 0xdc, 0xce, 0x2b, 0x7e, 0x5d,
+ 0xc7, 0x7f, 0x26, 0x3e, 0xfa, 0x4f, 0x05, 0x99, 0x71, 0x96, 0x30, 0x9f,
+ 0xdd, 0x47, 0xb5, 0x2e, 0x9b, 0x4a, 0x14, 0x67, 0x9e, 0x3e, 0x7f, 0xe7,
+ 0xa4, 0x85, 0x93, 0x46, 0x10, 0xd2, 0xe3, 0x97, 0x27, 0xe7, 0x89, 0x00,
+ 0x9a, 0xd0, 0xc1, 0xeb, 0xed, 0x93, 0x95, 0xaa, 0x7d, 0xc2, 0xc2, 0x5f,
+ 0x18, 0x5a, 0xb6, 0xcd, 0xcd, 0x98, 0x36, 0xb4, 0xb3, 0xc0, 0x3b, 0xc4,
+ 0x4a, 0xe2, 0x63, 0x1e, 0x04, 0x74, 0x87, 0x56, 0xd3, 0xd4, 0x6d, 0xc4,
+ 0x0f, 0x12, 0x63, 0xee, 0x15, 0x15, 0x48, 0xaa, 0x29, 0x8f, 0xe8, 0xad,
+ 0x13, 0xe9, 0x42, 0xa5, 0xda, 0x4e, 0x5d, 0xde, 0xb1, 0xaa, 0x0c, 0x97,
+ 0x6c, 0x5d, 0xde, 0x46, 0x5d, 0xe2, 0xf5, 0xa5, 0x70, 0x5f, 0xa8, 0x45,
+ 0xa7, 0x82, 0xdd, 0x9f, 0x55, 0xb2, 0x4e, 0xa7, 0x89, 0x6f, 0x89, 0x07,
+ 0x43, 0x3d, 0xf8, 0x2e, 0xf3, 0xcd, 0xa3, 0xf4, 0xd5, 0x5f, 0xe9, 0x4d,
+ 0xa8, 0xf8, 0x5e, 0x33, 0xed, 0xb8, 0xd6, 0xbf, 0x79, 0x22, 0x83, 0xc7,
+ 0x66, 0x2d, 0x3c, 0xc5, 0x38, 0x69, 0x48, 0x66, 0x43, 0xe5, 0xec, 0xd7,
+ 0x58, 0xd3, 0x16, 0x4e, 0xd8, 0x7e, 0xbe, 0xab, 0x75, 0xfd, 0x4c, 0x04,
+ 0xee, 0xef, 0xca, 0xef, 0x3b, 0x5b, 0xa3, 0x33, 0xf2, 0x9d, 0xe1, 0xb7,
+ 0x85, 0x01, 0x43, 0x4b, 0x7f, 0xec, 0xae, 0x40, 0x65, 0xdc, 0xb2, 0x06,
+ 0x92, 0x72, 0xbd, 0xaf, 0x35, 0x61, 0xdf, 0xdf, 0xc3, 0xef, 0xd2, 0x4c,
+ 0xfa, 0x6f, 0x04, 0x0b, 0x46, 0xd3, 0x94, 0x79, 0x2b, 0xeb, 0x7b, 0x86,
+ 0xf5, 0xbd, 0x36, 0xa5, 0xa5, 0x77, 0xb8, 0x65, 0xfe, 0x32, 0x7f, 0xa0,
+ 0x9a, 0xd7, 0x6f, 0x2f, 0xd6, 0xf7, 0xaa, 0x53, 0x32, 0xd3, 0x23, 0x06,
+ 0x84, 0xb3, 0x17, 0xd2, 0xc5, 0xfa, 0x5e, 0x31, 0xe6, 0xc1, 0x16, 0xd6,
+ 0x76, 0x2f, 0xb1, 0xf8, 0xc6, 0x7c, 0x2d, 0xfc, 0x27, 0xdc, 0x88, 0x25,
+ 0x7f, 0x82, 0x03, 0xf4, 0xb1, 0x03, 0x09, 0xb7, 0x8a, 0x2e, 0x71, 0x51,
+ 0x4f, 0xff, 0x88, 0x7d, 0x21, 0x37, 0xaa, 0xf4, 0x9f, 0xe1, 0x81, 0x2f,
+ 0xa8, 0xe9, 0x99, 0x09, 0x89, 0xed, 0x5d, 0xad, 0x5b, 0x4e, 0x39, 0x35,
+ 0x3d, 0x70, 0x6a, 0x78, 0x41, 0x6a, 0x7a, 0xed, 0xea, 0x0c, 0x4e, 0x4f,
+ 0xe2, 0x3b, 0x4b, 0x09, 0x1e, 0x6b, 0xb9, 0x66, 0x7d, 0x32, 0xce, 0xde,
+ 0x5a, 0xeb, 0xef, 0x50, 0xf1, 0x23, 0x55, 0xcc, 0x01, 0xa7, 0x59, 0xd3,
+ 0x7d, 0xa9, 0x78, 0x28, 0xe1, 0x42, 0x97, 0x97, 0xf6, 0x78, 0x9f, 0x7d,
+ 0xf6, 0x5b, 0xf9, 0x28, 0x69, 0x96, 0xc1, 0xc3, 0x9a, 0xfe, 0xbe, 0x8e,
+ 0xcf, 0xdc, 0xf4, 0xbd, 0x77, 0xdc, 0x3e, 0x5c, 0xcd, 0x3b, 0x35, 0xbd,
+ 0xba, 0xc1, 0x1a, 0xba, 0x9c, 0x0c, 0xe0, 0x4a, 0xde, 0xa0, 0x0f, 0x66,
+ 0x70, 0x98, 0x35, 0xfd, 0xb2, 0x1e, 0xc2, 0x87, 0xf9, 0x16, 0xfa, 0x65,
+ 0x18, 0xbf, 0x24, 0xfe, 0x5d, 0xc5, 0x9a, 0x7e, 0x27, 0x7d, 0x2a, 0xc9,
+ 0x9a, 0xde, 0x66, 0xe3, 0x8d, 0x7d, 0xad, 0x67, 0xc6, 0xed, 0x9a, 0xde,
+ 0xe0, 0x62, 0x3d, 0xf4, 0x22, 0xbe, 0xc0, 0x3c, 0x61, 0xfd, 0x6a, 0x6d,
+ 0x80, 0xcf, 0x52, 0x6f, 0x85, 0xd5, 0x98, 0xb2, 0x6b, 0xd0, 0x7a, 0xff,
+ 0x76, 0xae, 0xbd, 0xd8, 0x8e, 0x33, 0x0b, 0x5b, 0x57, 0xbd, 0x86, 0x3f,
+ 0xaa, 0x71, 0xd1, 0x0f, 0x53, 0xfe, 0x3b, 0x18, 0x6b, 0xc1, 0x54, 0x69,
+ 0xe6, 0x91, 0xe0, 0x3a, 0xb7, 0xf9, 0xef, 0xa4, 0x6f, 0xdc, 0xb2, 0x8a,
+ 0x99, 0x24, 0xe4, 0xc4, 0x59, 0x3b, 0xe3, 0x2c, 0xc2, 0x38, 0x5b, 0xca,
+ 0x38, 0x7b, 0xdc, 0x88, 0x27, 0xd6, 0x13, 0x77, 0xbd, 0x9c, 0x97, 0x58,
+ 0x6b, 0x26, 0x5d, 0x8d, 0x72, 0x0d, 0xf7, 0x4a, 0xcc, 0x6c, 0x5d, 0x35,
+ 0x7c, 0xb6, 0x12, 0xa2, 0x2b, 0x7c, 0xb6, 0x98, 0x18, 0x83, 0x99, 0xe9,
+ 0xe2, 0x82, 0x3b, 0x3e, 0x78, 0xab, 0x3b, 0x3e, 0xf0, 0x9e, 0x7a, 0xd3,
+ 0x7a, 0x9d, 0x71, 0xb6, 0x8d, 0x71, 0xb6, 0x9d, 0x71, 0xd6, 0x66, 0x5a,
+ 0x78, 0x2e, 0xa9, 0x65, 0x9a, 0x5c, 0x31, 0xa3, 0xcd, 0x85, 0xa5, 0x95,
+ 0x2c, 0x0d, 0x7e, 0xc4, 0x3b, 0xff, 0x88, 0xfc, 0x5f, 0x34, 0xe2, 0xdd,
+ 0x09, 0x25, 0xb1, 0x15, 0xc5, 0x07, 0x94, 0xbb, 0xbc, 0x18, 0x5b, 0x7b,
+ 0xa7, 0xcf, 0x17, 0x7d, 0xa3, 0x24, 0xbb, 0x1b, 0xcf, 0x1a, 0xcc, 0xa5,
+ 0x8b, 0xb4, 0x68, 0xd6, 0xd5, 0x83, 0x23, 0xd4, 0xa3, 0x3f, 0xde, 0x83,
+ 0xa3, 0xac, 0x87, 0xf7, 0xb2, 0x0e, 0xdf, 0x67, 0xc6, 0x5a, 0x36, 0xb3,
+ 0xff, 0xb9, 0x14, 0xd1, 0xa2, 0x51, 0xd5, 0x83, 0x3e, 0xfa, 0x70, 0x1f,
+ 0xeb, 0x46, 0x9b, 0xf9, 0x6b, 0xd5, 0x41, 0xac, 0xb0, 0xa7, 0x20, 0xef,
+ 0x69, 0x89, 0x5e, 0x57, 0x3f, 0x7a, 0x67, 0x25, 0xb7, 0x21, 0x74, 0x53,
+ 0xaa, 0x07, 0xc7, 0xcd, 0x32, 0xf4, 0x34, 0x77, 0xa9, 0xdb, 0x0b, 0x32,
+ 0x7f, 0x63, 0x3c, 0x9a, 0x8c, 0x57, 0x9b, 0x5f, 0x85, 0x7c, 0xbc, 0x0b,
+ 0x39, 0x89, 0x4f, 0x73, 0xbb, 0xba, 0x73, 0x5a, 0x62, 0xbc, 0x47, 0xf5,
+ 0x48, 0x0c, 0x9b, 0x83, 0xea, 0x2e, 0x89, 0x69, 0x7b, 0x66, 0x2d, 0x71,
+ 0x2f, 0x7b, 0x1a, 0xb7, 0x11, 0xc7, 0x81, 0x31, 0xe5, 0xfe, 0x5e, 0x84,
+ 0x71, 0xd7, 0x56, 0xe6, 0xa2, 0x9f, 0xc6, 0x68, 0x3b, 0x17, 0xda, 0x8d,
+ 0xdf, 0xb1, 0xb2, 0xa1, 0x5e, 0xc6, 0x54, 0x0f, 0x0e, 0x9b, 0x5f, 0xb6,
+ 0x2e, 0xdb, 0xf8, 0xa4, 0x94, 0xd7, 0xd7, 0xe3, 0x9e, 0x89, 0x25, 0xf0,
+ 0xe9, 0x52, 0xb7, 0x03, 0x48, 0xd4, 0xf8, 0x50, 0xa1, 0x4b, 0xbd, 0xd9,
+ 0xd7, 0x3a, 0x77, 0x42, 0x49, 0xff, 0x51, 0x8c, 0xef, 0xf5, 0xb8, 0x9f,
+ 0x79, 0x60, 0x77, 0xf2, 0x1e, 0xdc, 0x17, 0xaa, 0x40, 0x90, 0x7a, 0xda,
+ 0x1f, 0x0a, 0x30, 0xbf, 0xfe, 0x7e, 0x91, 0xce, 0xb3, 0x65, 0xc5, 0xbe,
+ 0xfa, 0x1a, 0xb6, 0xaa, 0x65, 0x8c, 0xad, 0x9b, 0x94, 0x39, 0x51, 0xa6,
+ 0x35, 0x32, 0xa9, 0x23, 0xc8, 0x7e, 0x76, 0x7d, 0x52, 0x1b, 0x5c, 0xef,
+ 0x8e, 0x49, 0xaf, 0x92, 0x0b, 0x12, 0xd7, 0xe5, 0xe3, 0xf1, 0xee, 0x26,
+ 0xd1, 0xb1, 0x1e, 0xc1, 0x26, 0xea, 0x69, 0x4b, 0x3e, 0xcc, 0x18, 0x5a,
+ 0x28, 0x13, 0x8c, 0x94, 0xce, 0x5f, 0xa7, 0x15, 0x21, 0xad, 0xc8, 0xa4,
+ 0xe0, 0xb5, 0x0c, 0xf1, 0x9a, 0xce, 0x38, 0xb4, 0xac, 0x75, 0xc4, 0x69,
+ 0x81, 0x53, 0x32, 0x6f, 0x8a, 0x1d, 0x21, 0xb6, 0x6d, 0x22, 0xee, 0xed,
+ 0xa1, 0x57, 0x5b, 0xb7, 0xd4, 0xc7, 0x8d, 0x36, 0x85, 0x47, 0x66, 0x9a,
+ 0xe1, 0x73, 0x93, 0xe6, 0x3b, 0xf9, 0x10, 0x2e, 0xe7, 0x23, 0x78, 0x9b,
+ 0xb4, 0x2f, 0xd9, 0xb4, 0xeb, 0xf0, 0x8b, 0x62, 0xde, 0x4a, 0x32, 0x6f,
+ 0x6d, 0x98, 0x50, 0xf4, 0xd7, 0x28, 0x86, 0x8c, 0xbf, 0xfe, 0xec, 0xd2,
+ 0xcd, 0x3e, 0xea, 0x4d, 0x64, 0xf1, 0xf0, 0x7b, 0x14, 0xfb, 0xed, 0x3c,
+ 0xfd, 0xda, 0x67, 0x53, 0x35, 0xb4, 0x15, 0x75, 0x5f, 0x5d, 0x7c, 0x6f,
+ 0xe5, 0x54, 0xa1, 0x28, 0xaf, 0x0e, 0xd7, 0xa9, 0x04, 0xca, 0x4e, 0x5d,
+ 0xe3, 0x55, 0x97, 0xf8, 0x60, 0x65, 0x7d, 0xe4, 0xfb, 0x5c, 0xff, 0x21,
+ 0x62, 0x3e, 0x8b, 0xeb, 0x5f, 0xb5, 0xd7, 0x0d, 0x73, 0x5d, 0x75, 0x0d,
+ 0x1f, 0x46, 0xae, 0xbd, 0x13, 0xa2, 0xec, 0x78, 0x38, 0x42, 0xdd, 0x5d,
+ 0x59, 0x23, 0xcf, 0x05, 0x70, 0x7b, 0x7e, 0x55, 0xb9, 0xe4, 0x71, 0x3f,
+ 0xfb, 0x01, 0xc7, 0x97, 0x88, 0xf7, 0xcc, 0xe7, 0x79, 0x4f, 0xf0, 0xd7,
+ 0x7a, 0x62, 0x8d, 0xcf, 0xeb, 0x3d, 0x4c, 0x5b, 0x94, 0xd1, 0x78, 0x72,
+ 0xef, 0x8b, 0xea, 0xe8, 0x9f, 0x61, 0x90, 0xbd, 0xd0, 0x43, 0x13, 0x59,
+ 0xec, 0x9f, 0xf8, 0x63, 0x7b, 0x8f, 0x6e, 0xe5, 0x6a, 0xec, 0xe1, 0x9a,
+ 0xfb, 0xaa, 0x19, 0x47, 0xff, 0x2d, 0x19, 0x17, 0x8c, 0xb4, 0xbd, 0x12,
+ 0x52, 0x6b, 0xe3, 0x2d, 0xb7, 0x2a, 0x0b, 0x65, 0x49, 0x0c, 0xb4, 0x37,
+ 0xc7, 0x13, 0x97, 0xf1, 0x88, 0x25, 0xf3, 0x6e, 0x77, 0xb1, 0xee, 0x12,
+ 0x97, 0xaa, 0x76, 0xd6, 0xde, 0xb6, 0x22, 0x56, 0xda, 0x50, 0x78, 0xf3,
+ 0x73, 0x33, 0x05, 0xe9, 0xc7, 0xa5, 0xde, 0xf8, 0x55, 0x1b, 0xd7, 0x39,
+ 0xcc, 0x9c, 0xfd, 0xac, 0xf1, 0x62, 0x84, 0xd5, 0x18, 0x9e, 0x55, 0x0a,
+ 0x07, 0x0c, 0x2f, 0xb2, 0x61, 0x0b, 0xdb, 0xf9, 0xbd, 0x97, 0xf8, 0xe9,
+ 0x5d, 0xa3, 0x0a, 0x53, 0xa1, 0x10, 0x31, 0x23, 0x73, 0xb0, 0xeb, 0xff,
+ 0x78, 0x65, 0x5f, 0x27, 0xea, 0x92, 0x3d, 0xf8, 0x7f, 0x6d, 0x5f, 0x66,
+ 0x15, 0xf1, 0x8b, 0xc8, 0xee, 0x57, 0xcc, 0xa1, 0x09, 0x10, 0xd3, 0xec,
+ 0x32, 0xe6, 0xa3, 0x2e, 0xa4, 0xaf, 0xba, 0xa0, 0x9d, 0x7e, 0x87, 0x7d,
+ 0xde, 0x43, 0xf5, 0xda, 0xe9, 0x56, 0xb7, 0x8e, 0xc1, 0xe3, 0x3e, 0x3c,
+ 0x78, 0xbc, 0x03, 0xd5, 0xf6, 0x7c, 0x68, 0x94, 0x3a, 0x75, 0xb1, 0xbf,
+ 0x1a, 0xfe, 0xd4, 0xc3, 0x3e, 0xeb, 0xea, 0xea, 0x87, 0xd1, 0x62, 0x5f,
+ 0x1f, 0xc1, 0x9e, 0x09, 0xbf, 0xda, 0x32, 0xe1, 0x41, 0xc7, 0x9d, 0x0f,
+ 0xc3, 0xbb, 0xaa, 0x97, 0x7c, 0xc9, 0x75, 0xf9, 0xfd, 0x2e, 0xf6, 0x67,
+ 0xc2, 0x5f, 0x19, 0xa2, 0x4b, 0xc8, 0xdb, 0x2a, 0x1d, 0x43, 0xc7, 0x3d,
+ 0x6a, 0x87, 0xf9, 0x37, 0xd6, 0x55, 0x7b, 0xcf, 0x47, 0xae, 0x55, 0xc8,
+ 0x59, 0x00, 0x3e, 0x23, 0x39, 0xa7, 0x0f, 0x13, 0x8c, 0xed, 0xbb, 0xec,
+ 0xf7, 0x8f, 0x97, 0x39, 0x32, 0xa5, 0xd9, 0xb7, 0xb6, 0xd3, 0x7e, 0xf2,
+ 0x4c, 0x6b, 0xf1, 0xda, 0x7a, 0x9f, 0x73, 0xde, 0x40, 0x7c, 0xa1, 0x0f,
+ 0xcb, 0x68, 0x84, 0xfa, 0xb8, 0x5d, 0xa7, 0x50, 0x9f, 0x67, 0x42, 0x5d,
+ 0xe2, 0xf0, 0xfb, 0x80, 0x39, 0xcf, 0x9e, 0x53, 0x67, 0xde, 0xa4, 0xee,
+ 0x16, 0xcb, 0xfb, 0x55, 0xbe, 0xdf, 0x7e, 0x5f, 0xf2, 0x2d, 0xb1, 0x66,
+ 0x50, 0x30, 0xe7, 0x17, 0xdd, 0xff, 0x5d, 0xc8, 0x3d, 0x8f, 0xfe, 0xa7,
+ 0x8c, 0xe3, 0x78, 0x77, 0xa5, 0x4b, 0xfc, 0xe7, 0x4f, 0x71, 0xdf, 0xf4,
+ 0x30, 0xef, 0x0b, 0xfd, 0x83, 0xec, 0x25, 0x3c, 0xaa, 0x93, 0xf9, 0x67,
+ 0xef, 0x71, 0xd7, 0xed, 0x65, 0xf8, 0x4b, 0xab, 0x7c, 0xf1, 0x10, 0xea,
+ 0x93, 0x23, 0x7c, 0x5e, 0xa1, 0x9d, 0xb8, 0xf1, 0x31, 0x63, 0x03, 0x3a,
+ 0x6a, 0x24, 0x07, 0x3c, 0x6b, 0xf5, 0xf5, 0x88, 0x0e, 0x15, 0x36, 0xf2,
+ 0xfa, 0x73, 0xb4, 0xef, 0x93, 0x86, 0x07, 0xf5, 0x8b, 0x64, 0xd6, 0xa7,
+ 0x8d, 0xa7, 0xf1, 0x75, 0x9f, 0xb3, 0xf7, 0x95, 0xb5, 0xaa, 0x75, 0x7d,
+ 0xe0, 0x0e, 0x57, 0xfd, 0xf8, 0x1b, 0xf4, 0xa7, 0xb6, 0x55, 0x37, 0xde,
+ 0x2b, 0xe9, 0xc4, 0x40, 0x64, 0xd5, 0x33, 0x16, 0x6e, 0x1a, 0x46, 0x68,
+ 0xd5, 0x8d, 0xf6, 0x2f, 0xf1, 0x7d, 0x90, 0x31, 0x88, 0x6c, 0x75, 0x4a,
+ 0xe6, 0x3f, 0x71, 0xd2, 0x39, 0x88, 0x3f, 0x2c, 0x8c, 0xe0, 0xc0, 0x44,
+ 0x11, 0x5b, 0xd3, 0xb7, 0xf5, 0x55, 0xd7, 0x65, 0x7b, 0x60, 0x22, 0xde,
+ 0x5b, 0x55, 0x94, 0x6d, 0x1f, 0xfb, 0x8c, 0x4a, 0xe6, 0xd8, 0xfb, 0xa9,
+ 0xd3, 0x01, 0x5b, 0xa7, 0x3d, 0x30, 0xf2, 0xd7, 0xe9, 0xf6, 0x93, 0xae,
+ 0x3f, 0x25, 0x7a, 0x93, 0xfd, 0xb6, 0x83, 0xd8, 0x4b, 0xba, 0xbb, 0x6f,
+ 0xa0, 0xdb, 0x67, 0x5c, 0xa7, 0xbb, 0x6b, 0x22, 0x7e, 0xda, 0x55, 0xa4,
+ 0xfb, 0xed, 0xe9, 0x12, 0x8d, 0x2c, 0xb6, 0xad, 0xca, 0x22, 0xbf, 0x6e,
+ 0x9f, 0xb5, 0xcf, 0xd6, 0xc7, 0x59, 0xfb, 0xfa, 0xc6, 0x7a, 0x89, 0x07,
+ 0xfe, 0x9a, 0xd2, 0xed, 0xbd, 0x7d, 0x07, 0x7b, 0xdd, 0x18, 0x1f, 0xda,
+ 0x9b, 0x5b, 0xdc, 0x69, 0xc6, 0x76, 0xd8, 0xb7, 0xf9, 0x73, 0x33, 0x8d,
+ 0x0e, 0xf6, 0x61, 0x9b, 0xcc, 0x2e, 0x7f, 0xa7, 0xe9, 0x23, 0xee, 0xaa,
+ 0x54, 0x1b, 0x27, 0x64, 0xb6, 0x21, 0xb1, 0x5c, 0xc4, 0xc2, 0x05, 0xe9,
+ 0xf7, 0x76, 0xb2, 0x4f, 0x58, 0x46, 0xfb, 0xf6, 0xe2, 0x48, 0xa1, 0x57,
+ 0xa5, 0xc3, 0x5c, 0xc7, 0x94, 0xba, 0x02, 0xd6, 0xbc, 0x6e, 0x54, 0xd2,
+ 0x97, 0xc2, 0xa9, 0x81, 0xd4, 0xc9, 0x7a, 0x0b, 0xc4, 0x28, 0xbe, 0x45,
+ 0xa9, 0x6c, 0x6a, 0x7b, 0xbd, 0x1b, 0xc7, 0x6c, 0xfc, 0xa5, 0x4d, 0xf1,
+ 0x33, 0x2e, 0x31, 0x73, 0xc7, 0x84, 0xd4, 0x31, 0x42, 0x48, 0x7d, 0x08,
+ 0xff, 0x90, 0x9c, 0x1f, 0xa8, 0x41, 0xfa, 0xde, 0x1a, 0x48, 0x5f, 0x71,
+ 0x04, 0x3f, 0xd2, 0x23, 0xbe, 0x4c, 0xc1, 0xa3, 0xb6, 0x98, 0x33, 0xfe,
+ 0xad, 0x66, 0x10, 0x01, 0xf6, 0x65, 0x5d, 0xee, 0x18, 0xfb, 0x0c, 0xd1,
+ 0x63, 0x67, 0xeb, 0xb2, 0x7c, 0xc6, 0xdf, 0x6e, 0x3a, 0xb9, 0xf0, 0x96,
+ 0x29, 0x9f, 0xbf, 0x63, 0x32, 0x16, 0x39, 0x62, 0x63, 0xb1, 0xae, 0xd6,
+ 0x58, 0xde, 0xb2, 0x5e, 0x31, 0xe6, 0xaf, 0x96, 0x3b, 0x3d, 0x48, 0x6b,
+ 0x22, 0xdf, 0x84, 0xbb, 0x89, 0x9f, 0xda, 0x26, 0x9b, 0x60, 0x4c, 0x02,
+ 0x27, 0x8e, 0x47, 0xb0, 0x72, 0x42, 0x3b, 0x3d, 0xe8, 0xce, 0x60, 0x7c,
+ 0xb6, 0x13, 0x13, 0x05, 0xff, 0x42, 0xd4, 0x45, 0x5c, 0x9d, 0x74, 0xe1,
+ 0x76, 0x63, 0xb5, 0x9a, 0xb7, 0x63, 0x5a, 0xe1, 0x2e, 0x63, 0xbb, 0xea,
+ 0xb5, 0x31, 0xc5, 0x0c, 0xb1, 0x88, 0xc2, 0x4d, 0xce, 0x5c, 0xbe, 0x35,
+ 0x49, 0xcc, 0x7d, 0xfb, 0x84, 0xd4, 0x77, 0x0b, 0xaf, 0x26, 0xa9, 0x97,
+ 0x64, 0x36, 0xe3, 0x65, 0x0f, 0xb4, 0x4f, 0x69, 0xdd, 0x86, 0x72, 0x30,
+ 0xde, 0xad, 0x33, 0x0e, 0x2e, 0x5c, 0x36, 0xd3, 0xec, 0x97, 0x1c, 0xd4,
+ 0x6e, 0x68, 0x11, 0x8f, 0x2b, 0x84, 0x01, 0x9b, 0x46, 0x6f, 0xab, 0x31,
+ 0x53, 0x86, 0xa5, 0x7a, 0x0f, 0x4e, 0xdb, 0x32, 0xf4, 0xb7, 0xae, 0x27,
+ 0xbe, 0x7e, 0xdc, 0xcc, 0xb0, 0x07, 0x96, 0xfd, 0xd0, 0x58, 0xa2, 0xc5,
+ 0xdd, 0x46, 0x0c, 0x1b, 0x8b, 0x2e, 0xa8, 0xb4, 0xca, 0x7a, 0x1a, 0xd3,
+ 0x33, 0x60, 0x45, 0xa9, 0x71, 0xea, 0x9b, 0xc8, 0x18, 0x27, 0xce, 0x6a,
+ 0x3b, 0xee, 0x5f, 0x48, 0xc3, 0x99, 0xdf, 0x6c, 0x32, 0xfe, 0x37, 0x2e,
+ 0x85, 0xb5, 0x23, 0x69, 0xf2, 0xdd, 0xc1, 0xbc, 0x3b, 0xdf, 0xe3, 0xe1,
+ 0x7d, 0x99, 0xdb, 0x75, 0xb7, 0x8e, 0xe6, 0x30, 0xef, 0x4e, 0x49, 0x5f,
+ 0x85, 0x60, 0x77, 0x01, 0x32, 0x43, 0x62, 0x6f, 0xf1, 0xa9, 0x55, 0xda,
+ 0x3b, 0xea, 0x9a, 0x74, 0xf6, 0xc5, 0x72, 0xb3, 0x9e, 0xe0, 0x56, 0xb3,
+ 0x19, 0xc7, 0x0a, 0x9e, 0x1b, 0x68, 0xc7, 0x8f, 0xdc, 0xe2, 0x72, 0x21,
+ 0xbe, 0xea, 0x2e, 0x55, 0xdc, 0x5b, 0x62, 0x9e, 0xc8, 0xd8, 0x35, 0xb1,
+ 0x8c, 0x72, 0x5e, 0x38, 0x29, 0x6b, 0x7c, 0xab, 0x75, 0xf4, 0xa4, 0xd4,
+ 0xc8, 0xee, 0xd6, 0x88, 0xa9, 0x75, 0x4b, 0x1f, 0x58, 0x4d, 0x3d, 0x7d,
+ 0x34, 0x26, 0x35, 0x78, 0x3f, 0x6b, 0xb0, 0xb6, 0xd0, 0xae, 0xa4, 0x8e,
+ 0x69, 0x09, 0xbf, 0xdb, 0x85, 0x2b, 0x0d, 0x5a, 0xe6, 0x79, 0x68, 0xbd,
+ 0xce, 0xbc, 0x70, 0x67, 0x6b, 0x63, 0x11, 0x0f, 0xdf, 0x3a, 0xd3, 0x27,
+ 0xe7, 0x49, 0x6c, 0x1d, 0x37, 0xe5, 0x05, 0x1b, 0x5b, 0xd6, 0x4b, 0xc9,
+ 0x2e, 0xe2, 0x06, 0xc1, 0xc6, 0x72, 0xfd, 0x81, 0xd6, 0x86, 0x29, 0x1f,
+ 0x79, 0x53, 0x78, 0x8f, 0x75, 0xe9, 0x48, 0xa1, 0xc4, 0xa3, 0x83, 0x9b,
+ 0x37, 0x13, 0x37, 0xbb, 0x53, 0x5a, 0xcb, 0x06, 0xe2, 0x66, 0x9d, 0x3d,
+ 0x84, 0x07, 0x3d, 0x78, 0xcc, 0x74, 0xfa, 0x08, 0xc1, 0xce, 0xd6, 0x49,
+ 0x2d, 0x2d, 0xb8, 0xf9, 0xea, 0x6a, 0x60, 0x07, 0x71, 0xf3, 0x42, 0xce,
+ 0x83, 0x0c, 0x71, 0xf3, 0x47, 0x39, 0x1f, 0xee, 0x20, 0x6e, 0xbe, 0x42,
+ 0x8c, 0x75, 0x3e, 0xf9, 0x4b, 0x7c, 0xbb, 0x38, 0x13, 0xdb, 0x95, 0xf0,
+ 0xd1, 0xb7, 0x05, 0x3b, 0xff, 0xa6, 0x88, 0x9d, 0xff, 0xcb, 0x3f, 0xc3,
+ 0xce, 0x77, 0x13, 0x13, 0x76, 0x4d, 0xc8, 0xfe, 0xd1, 0xae, 0xd6, 0xd7,
+ 0x4f, 0xc9, 0x99, 0x95, 0x5b, 0xf1, 0xee, 0xc9, 0xe1, 0x7e, 0x62, 0x65,
+ 0x8c, 0x24, 0x33, 0xc8, 0x4d, 0x62, 0x09, 0x71, 0xc1, 0x4b, 0x6e, 0xae,
+ 0xbb, 0x32, 0xa9, 0x19, 0x6f, 0xa8, 0x78, 0x67, 0x06, 0x71, 0xf6, 0xca,
+ 0xda, 0x02, 0x4d, 0x98, 0xf6, 0xa4, 0x88, 0x8d, 0x59, 0x03, 0x97, 0x12,
+ 0x3b, 0x57, 0xcd, 0x01, 0xb5, 0x73, 0x0e, 0x76, 0x96, 0x79, 0x58, 0x55,
+ 0x1c, 0x7f, 0x46, 0xec, 0xcc, 0xfe, 0x96, 0xa1, 0x36, 0xd7, 0xc4, 0x18,
+ 0x55, 0x38, 0x1c, 0x0f, 0xa0, 0xeb, 0x38, 0x71, 0x8f, 0x3d, 0x0f, 0xb3,
+ 0x86, 0x7e, 0x6a, 0x64, 0x70, 0x74, 0xd6, 0x99, 0x87, 0x6d, 0x22, 0x7e,
+ 0xf3, 0xc4, 0xc3, 0x28, 0x9f, 0xf3, 0xe0, 0x19, 0xe2, 0xe7, 0x8d, 0xb4,
+ 0xf3, 0x19, 0xe2, 0xe7, 0xbb, 0x6f, 0x98, 0x89, 0x4d, 0xcd, 0xe1, 0x15,
+ 0x62, 0xf9, 0xba, 0x5a, 0xc4, 0x65, 0xde, 0x61, 0x5d, 0x59, 0x13, 0xc0,
+ 0x39, 0x1b, 0x3f, 0xfb, 0x17, 0xb2, 0xca, 0x91, 0xad, 0x8c, 0xb6, 0x10,
+ 0xbb, 0xba, 0x68, 0xd7, 0xb6, 0x93, 0x5a, 0xe7, 0x8b, 0xd4, 0x45, 0x63,
+ 0xfc, 0xbc, 0x6d, 0x8f, 0xbe, 0xa4, 0xcc, 0x4e, 0x3a, 0x5b, 0xe5, 0x5c,
+ 0x55, 0x05, 0xed, 0xbd, 0x65, 0x2c, 0x96, 0xfe, 0x00, 0x4e, 0x4c, 0x26,
+ 0xf2, 0x65, 0xc5, 0x7a, 0x28, 0xf7, 0xfa, 0x79, 0x2f, 0x8d, 0xce, 0x35,
+ 0x8e, 0x7f, 0x27, 0xf2, 0xc7, 0x88, 0x5d, 0x65, 0xcf, 0x34, 0x14, 0xdc,
+ 0x64, 0x76, 0x62, 0xdc, 0x8c, 0xa2, 0xfc, 0x5c, 0x71, 0xef, 0xf5, 0x9c,
+ 0x9c, 0xc5, 0xdb, 0xd9, 0x1a, 0xfa, 0x5e, 0x09, 0x13, 0xa6, 0x89, 0xef,
+ 0xc2, 0xbe, 0xdb, 0x0b, 0x82, 0x17, 0xbb, 0x71, 0xd4, 0xd4, 0x22, 0x3f,
+ 0x67, 0x4c, 0xdc, 0x2b, 0xfb, 0xee, 0x37, 0xcc, 0x9e, 0x1e, 0xe4, 0x3d,
+ 0xf3, 0x73, 0xb3, 0xa7, 0xc1, 0x09, 0xfc, 0xc6, 0xdd, 0x5c, 0x0e, 0xd7,
+ 0x4a, 0x2f, 0x31, 0xbd, 0x16, 0x19, 0xc1, 0x23, 0xc4, 0x1c, 0xbf, 0x56,
+ 0x01, 0xdd, 0xd3, 0xdf, 0xe4, 0xd6, 0x22, 0x33, 0x2a, 0xc0, 0x77, 0x77,
+ 0x32, 0xbf, 0xed, 0xa4, 0x6f, 0xc4, 0x16, 0x2a, 0x94, 0x1b, 0x97, 0xbe,
+ 0x6c, 0xe3, 0x51, 0x7f, 0x37, 0xaf, 0x8d, 0x17, 0x4a, 0xb8, 0xa6, 0x47,
+ 0x78, 0xc5, 0xa6, 0xe3, 0x4e, 0x0e, 0xd1, 0xf3, 0xfe, 0x85, 0x4b, 0x70,
+ 0x64, 0xab, 0xa4, 0xac, 0xf7, 0x8f, 0x85, 0xac, 0xde, 0xc5, 0x12, 0xc3,
+ 0x3a, 0xb6, 0x99, 0xe2, 0x5f, 0x7d, 0xe4, 0xb3, 0x07, 0x87, 0xcc, 0xa5,
+ 0xec, 0xdd, 0x64, 0x0e, 0xda, 0x44, 0x6c, 0xdd, 0xcd, 0x1a, 0x6c, 0x59,
+ 0x83, 0x46, 0xd6, 0x6a, 0x5a, 0xab, 0x1b, 0x79, 0x35, 0x5f, 0x13, 0x21,
+ 0xbe, 0x59, 0xc5, 0xda, 0xdd, 0x56, 0x68, 0xc2, 0x1b, 0x67, 0x74, 0xfa,
+ 0x66, 0x3b, 0xf1, 0x7b, 0x37, 0xee, 0xa1, 0x3c, 0xdf, 0x2e, 0x7c, 0x07,
+ 0xe9, 0x6f, 0x78, 0x70, 0xe4, 0x78, 0x1a, 0xeb, 0x57, 0x0d, 0xe1, 0xd2,
+ 0x37, 0x7d, 0xcc, 0x55, 0x01, 0x3c, 0x7e, 0x5c, 0xf2, 0x6b, 0x09, 0x6f,
+ 0xdf, 0x88, 0x45, 0x7c, 0x88, 0xda, 0x38, 0xe4, 0x8b, 0xef, 0x39, 0x18,
+ 0xc5, 0xcf, 0xfe, 0xb7, 0xf4, 0x3e, 0xf3, 0xd0, 0xaa, 0x7f, 0x86, 0x67,
+ 0x88, 0x5b, 0x88, 0x05, 0x2a, 0x12, 0xf6, 0xb9, 0xb7, 0x12, 0xde, 0xf5,
+ 0xd0, 0x07, 0x24, 0xa6, 0x97, 0x32, 0xd6, 0x2d, 0x62, 0xe7, 0x85, 0xe2,
+ 0x5c, 0xf2, 0xed, 0x93, 0xda, 0xc5, 0x43, 0x88, 0x11, 0x43, 0xa3, 0x4f,
+ 0xb0, 0x9b, 0x9b, 0x78, 0xf7, 0x4a, 0x3c, 0x6e, 0x9c, 0x23, 0xde, 0x1d,
+ 0xa6, 0xad, 0x3d, 0xba, 0xf8, 0x66, 0x08, 0x65, 0x73, 0x11, 0xfa, 0xa4,
+ 0xcc, 0x25, 0x5f, 0xf1, 0x3b, 0x73, 0x49, 0x99, 0x85, 0xcb, 0xb9, 0x10,
+ 0x74, 0x94, 0xb1, 0x77, 0x2b, 0x57, 0x59, 0xe6, 0xe4, 0x29, 0xff, 0x0e,
+ 0xe6, 0xf7, 0x8c, 0x19, 0x0e, 0xee, 0x28, 0x84, 0xf8, 0xa9, 0x0b, 0x66,
+ 0x0a, 0xbf, 0xc7, 0xe7, 0x23, 0xfc, 0x8e, 0x62, 0x22, 0x5f, 0x5b, 0x21,
+ 0xcd, 0xc0, 0x44, 0xde, 0xc9, 0x79, 0xd1, 0xfc, 0x5e, 0xbf, 0x60, 0xcd,
+ 0xb6, 0xe3, 0xce, 0xdf, 0xfa, 0x0d, 0x7f, 0x7f, 0x1e, 0xf3, 0x7b, 0xc9,
+ 0xf7, 0x99, 0x93, 0x3a, 0x3e, 0x3a, 0x69, 0x63, 0xfe, 0x79, 0x62, 0xfe,
+ 0x01, 0xaf, 0x5b, 0xb0, 0xe6, 0xaf, 0xac, 0xf3, 0xf1, 0x78, 0xef, 0x34,
+ 0xfd, 0xa0, 0x8b, 0x74, 0x5d, 0x7a, 0xd8, 0xe6, 0xd7, 0xe1, 0xd3, 0x99,
+ 0xe5, 0x5e, 0x3e, 0x99, 0xc0, 0x3b, 0xd7, 0x67, 0xa7, 0x9f, 0x94, 0xd9,
+ 0x33, 0x60, 0x3c, 0xf2, 0xee, 0x5a, 0xf8, 0x5a, 0xd8, 0x6f, 0x7a, 0xf9,
+ 0x7c, 0xc4, 0x7e, 0x5e, 0x66, 0xb9, 0x9f, 0x7c, 0x56, 0xc2, 0xd3, 0x1f,
+ 0x5d, 0x7f, 0xe7, 0x20, 0x3b, 0x35, 0xdf, 0x79, 0xc6, 0x96, 0xdb, 0x7e,
+ 0x4e, 0xe6, 0xad, 0xfe, 0x05, 0xd8, 0xf1, 0xf5, 0xfb, 0x94, 0x49, 0xec,
+ 0x7b, 0xc0, 0x72, 0xfc, 0x36, 0x1c, 0xdc, 0xc6, 0x78, 0xf8, 0x2e, 0xed,
+ 0xb3, 0xed, 0x5c, 0x5d, 0xf0, 0x2e, 0xb3, 0xd3, 0x96, 0xf9, 0xae, 0x73,
+ 0x52, 0x93, 0xe4, 0xfe, 0x1f, 0x54, 0x08, 0x1e, 0x7f, 0x9c, 0x35, 0x6b,
+ 0xd8, 0x94, 0xd9, 0x3e, 0x94, 0x27, 0x75, 0x08, 0x9b, 0xc6, 0xa3, 0x78,
+ 0xdb, 0xf0, 0x17, 0xcf, 0xb0, 0x48, 0x4c, 0x0e, 0x30, 0x26, 0xc3, 0x18,
+ 0x31, 0x63, 0xd1, 0xb7, 0x89, 0x4f, 0xb3, 0x64, 0xf8, 0xe8, 0x84, 0x1b,
+ 0x6f, 0x13, 0x33, 0x42, 0x39, 0x67, 0x40, 0x9d, 0x77, 0x4b, 0xbf, 0x57,
+ 0x22, 0x5a, 0x13, 0x6b, 0xd9, 0x8b, 0x3a, 0xe4, 0x98, 0xf3, 0xfd, 0xfa,
+ 0x8f, 0x71, 0xec, 0x84, 0x0b, 0xf7, 0xb1, 0xef, 0x4b, 0xdf, 0x69, 0xf0,
+ 0xef, 0xc6, 0xfe, 0xf7, 0xf1, 0x0f, 0xd6, 0x94, 0x9c, 0xb3, 0x52, 0x72,
+ 0x96, 0xe3, 0x13, 0xab, 0x56, 0xd7, 0xe7, 0x9f, 0x87, 0x3e, 0x78, 0x15,
+ 0x8d, 0x03, 0x0b, 0xf8, 0xc0, 0x9a, 0xe7, 0xbd, 0xf7, 0x18, 0x3f, 0x2f,
+ 0x1a, 0xb1, 0x88, 0x8b, 0xc2, 0xcc, 0x87, 0xdd, 0xb8, 0xd7, 0x90, 0x7d,
+ 0x26, 0x6d, 0xe0, 0x69, 0x68, 0xfd, 0x17, 0x94, 0x9c, 0xcd, 0xb9, 0x64,
+ 0x65, 0x6b, 0x64, 0x5d, 0x85, 0x95, 0xcb, 0x1b, 0x3b, 0xcb, 0xa0, 0xb5,
+ 0x78, 0x95, 0x6e, 0xbc, 0xaf, 0xfe, 0xa7, 0x35, 0x1f, 0xfe, 0xc4, 0x7a,
+ 0x47, 0x2f, 0xd1, 0xd5, 0xa2, 0x3e, 0x77, 0x89, 0xb7, 0x3a, 0x1c, 0x33,
+ 0x65, 0x7f, 0xee, 0xc7, 0xb8, 0xef, 0x84, 0x07, 0xed, 0xc9, 0x5f, 0x5a,
+ 0xd9, 0xb0, 0xd0, 0x0c, 0x56, 0xa2, 0x42, 0xe8, 0x3b, 0x33, 0xeb, 0x17,
+ 0x0a, 0x50, 0x1d, 0xa6, 0xe0, 0x65, 0xf1, 0xd3, 0x71, 0x58, 0xa6, 0xcc,
+ 0x11, 0x2d, 0xdc, 0x91, 0x1c, 0xc2, 0x7b, 0xc9, 0xf4, 0x1f, 0xf8, 0xa0,
+ 0x5d, 0xbc, 0xec, 0xd6, 0xe6, 0x9b, 0xdc, 0x51, 0xe5, 0x6f, 0xd0, 0x07,
+ 0x1a, 0xec, 0x7a, 0x93, 0x67, 0xef, 0x14, 0x60, 0x6e, 0x91, 0x1e, 0x73,
+ 0x1c, 0x73, 0x63, 0x59, 0x78, 0x88, 0xed, 0x86, 0x9b, 0xb5, 0xcc, 0x53,
+ 0x4a, 0x8b, 0xec, 0x53, 0x51, 0x75, 0x8f, 0x3e, 0x88, 0x67, 0x8c, 0x78,
+ 0xba, 0x4d, 0xd5, 0xf9, 0x3a, 0x0b, 0x25, 0xda, 0xed, 0xc4, 0x2a, 0xda,
+ 0xfc, 0x65, 0x77, 0x39, 0x6a, 0x57, 0xeb, 0x9d, 0xe5, 0x6e, 0x6d, 0xf0,
+ 0x6b, 0x8c, 0xaf, 0xcd, 0x85, 0x79, 0xff, 0xfb, 0x71, 0x17, 0x56, 0xd8,
+ 0xfb, 0x08, 0xb9, 0xe2, 0x8c, 0x74, 0x1c, 0x5b, 0xc6, 0xac, 0xf5, 0xaf,
+ 0x26, 0xb5, 0xc8, 0x53, 0x2a, 0xbb, 0x23, 0x40, 0x4c, 0x73, 0x3f, 0xf4,
+ 0xe8, 0x2c, 0xeb, 0x54, 0x7b, 0xc1, 0x85, 0x5b, 0x4e, 0x09, 0xcd, 0x1c,
+ 0x69, 0x1e, 0x42, 0xf9, 0x09, 0x6b, 0xfd, 0x0e, 0x43, 0x1b, 0xbc, 0xec,
+ 0xce, 0xfe, 0xd7, 0x5a, 0xea, 0xad, 0x43, 0xc9, 0x3e, 0xda, 0x10, 0x71,
+ 0xc5, 0x90, 0x9c, 0x87, 0x4b, 0xfc, 0x39, 0x31, 0xc5, 0x1f, 0xd3, 0x57,
+ 0xdd, 0xa9, 0x20, 0xf9, 0xd4, 0x12, 0xd3, 0x90, 0xf9, 0x79, 0x14, 0x97,
+ 0x8d, 0xac, 0x7f, 0x53, 0x43, 0x82, 0xd8, 0x2c, 0xc2, 0x3a, 0x18, 0xc5,
+ 0x51, 0x62, 0xbc, 0x43, 0x6c, 0x09, 0xe7, 0x43, 0x3a, 0xb1, 0x59, 0x37,
+ 0x5c, 0x63, 0x01, 0x35, 0x93, 0x8b, 0x19, 0xed, 0xf8, 0xf7, 0x98, 0x8f,
+ 0x88, 0x8b, 0x1c, 0x42, 0xe0, 0xc4, 0xdf, 0x59, 0x55, 0xba, 0xde, 0x32,
+ 0xa6, 0xb8, 0xee, 0x13, 0x11, 0xea, 0x98, 0xef, 0xc9, 0xb9, 0x15, 0xb3,
+ 0x0b, 0xf7, 0x8c, 0x85, 0xf9, 0x7e, 0x15, 0x56, 0x9e, 0x88, 0xe2, 0x4a,
+ 0xf2, 0x66, 0xcc, 0xd7, 0x38, 0x18, 0xc8, 0xaf, 0xd3, 0x8f, 0xd8, 0x67,
+ 0x65, 0x0b, 0xba, 0xbd, 0x77, 0x74, 0xc8, 0x94, 0xfe, 0xdc, 0xc3, 0xbf,
+ 0x03, 0xfc, 0x88, 0x3e, 0xbf, 0x55, 0xc4, 0x3a, 0xfb, 0x5b, 0xa3, 0x33,
+ 0x6f, 0x55, 0xd8, 0x7b, 0x9a, 0x88, 0xf2, 0xb9, 0x90, 0x3d, 0x17, 0x1c,
+ 0x26, 0xcd, 0xb3, 0xe3, 0xd2, 0xb7, 0xb5, 0xad, 0xf3, 0x15, 0xf7, 0xdf,
+ 0xdf, 0x32, 0x5c, 0x58, 0xcf, 0xde, 0x3e, 0xa2, 0x4b, 0xbd, 0x1c, 0xd6,
+ 0x6a, 0xb1, 0x0e, 0xa7, 0x43, 0x6c, 0xc2, 0xf5, 0x7f, 0x87, 0x23, 0xa1,
+ 0x04, 0x73, 0xbe, 0x8e, 0x77, 0x73, 0x5f, 0x66, 0xbf, 0x53, 0x27, 0x67,
+ 0x77, 0x70, 0xcb, 0x09, 0x2f, 0xd7, 0x5c, 0x4f, 0x5c, 0xb3, 0x09, 0x3f,
+ 0x0b, 0x39, 0xbd, 0xc6, 0x61, 0x5e, 0x1f, 0x9d, 0x0e, 0x10, 0x8b, 0xfa,
+ 0xf8, 0xb9, 0x91, 0xb7, 0x2f, 0xe2, 0x49, 0x64, 0xf9, 0xd7, 0x78, 0xf2,
+ 0x11, 0x0f, 0xe8, 0xb8, 0x9a, 0x7b, 0x09, 0x57, 0x48, 0x3b, 0x3b, 0xed,
+ 0xd0, 0x3c, 0x5e, 0x10, 0xba, 0xb2, 0x5e, 0x6c, 0xb0, 0xd6, 0x2d, 0xf4,
+ 0x03, 0x72, 0x8e, 0xf7, 0xdf, 0xb8, 0x06, 0x91, 0xdd, 0x09, 0xf6, 0xc7,
+ 0x46, 0x03, 0xda, 0x43, 0xb4, 0x97, 0x29, 0x6b, 0x68, 0xec, 0x45, 0xe5,
+ 0xdd, 0x08, 0x56, 0x8c, 0x59, 0x43, 0x91, 0x94, 0x5c, 0xb7, 0xac, 0xea,
+ 0xb5, 0x7a, 0xe4, 0x0d, 0xe5, 0x61, 0xad, 0xf3, 0x50, 0x07, 0xa3, 0x38,
+ 0x9b, 0x6b, 0xbc, 0xf8, 0x1e, 0xb1, 0x53, 0x94, 0xbd, 0xde, 0x25, 0xf7,
+ 0x28, 0x66, 0x72, 0xff, 0xb1, 0x52, 0x66, 0x04, 0xa3, 0x85, 0x80, 0x9a,
+ 0xce, 0xfd, 0x49, 0xa5, 0xe4, 0xa2, 0x11, 0xfa, 0x42, 0xd3, 0x98, 0xf0,
+ 0x6a, 0x0d, 0x55, 0x91, 0xce, 0x51, 0xd2, 0x99, 0x5e, 0xa3, 0x67, 0x46,
+ 0x94, 0xe8, 0x2c, 0x40, 0x5c, 0xf7, 0xaa, 0xcc, 0xcf, 0xa8, 0xb7, 0xa7,
+ 0xf9, 0xbc, 0xe8, 0x2d, 0x8c, 0x9f, 0x15, 0xe9, 0x3c, 0x56, 0xb8, 0x88,
+ 0xe9, 0xdc, 0x25, 0xfb, 0xf7, 0x91, 0x42, 0x82, 0xb5, 0xaf, 0x0f, 0x79,
+ 0xe6, 0x93, 0xb1, 0x5c, 0x63, 0x66, 0x8c, 0x7c, 0x38, 0x67, 0xee, 0xfa,
+ 0xf0, 0x64, 0xf1, 0x99, 0x61, 0xbe, 0x3b, 0x7c, 0xed, 0x77, 0xd1, 0x91,
+ 0xb3, 0xaf, 0xef, 0xec, 0x2b, 0x94, 0xd3, 0x76, 0x4e, 0x1f, 0x7e, 0xd8,
+ 0xf4, 0xca, 0x0c, 0x1c, 0x2f, 0x8d, 0xaf, 0xc7, 0x88, 0xf1, 0x97, 0xd8,
+ 0x45, 0xb9, 0x47, 0xa9, 0xcf, 0x13, 0xa6, 0xbd, 0x7f, 0x2f, 0xe7, 0xba,
+ 0x98, 0xab, 0xbb, 0x5a, 0xcf, 0x10, 0x8b, 0x1d, 0x63, 0xcc, 0xec, 0x49,
+ 0x36, 0x76, 0xbf, 0x4c, 0xbf, 0x4b, 0x7f, 0x5d, 0xf6, 0xc8, 0x81, 0xb1,
+ 0x89, 0x6f, 0x63, 0xaa, 0xa6, 0x71, 0xe1, 0x59, 0xe6, 0x84, 0xd3, 0xcc,
+ 0x53, 0x1e, 0xe6, 0x84, 0xea, 0x09, 0x62, 0x48, 0xe6, 0xa9, 0x79, 0xe6,
+ 0x29, 0x8f, 0xde, 0x78, 0x71, 0x06, 0xff, 0x9d, 0x7a, 0x11, 0xfe, 0x62,
+ 0x89, 0x19, 0xc8, 0xb3, 0xce, 0xfc, 0x55, 0x9f, 0xe9, 0xc7, 0xa5, 0x9b,
+ 0x9d, 0x19, 0x9a, 0x9b, 0x35, 0x7b, 0x77, 0xae, 0x31, 0x34, 0x22, 0xb4,
+ 0x7b, 0xb4, 0x48, 0x96, 0xb6, 0x3a, 0x62, 0x63, 0xef, 0x6e, 0xf6, 0x0b,
+ 0x72, 0x8e, 0xab, 0x0a, 0x1e, 0xfa, 0xfe, 0x88, 0x21, 0xe7, 0x1b, 0x22,
+ 0xc1, 0xcd, 0xb4, 0xe1, 0x88, 0xd9, 0xd8, 0x12, 0x53, 0x3b, 0x70, 0xa9,
+ 0x98, 0x63, 0x1d, 0x2c, 0xad, 0x65, 0x8e, 0xa2, 0xb1, 0xfb, 0x7e, 0x7c,
+ 0x03, 0xe9, 0x9a, 0xc6, 0xde, 0x71, 0xc4, 0x8c, 0x7b, 0x21, 0xe7, 0x41,
+ 0x1d, 0x5a, 0xf5, 0x79, 0x37, 0xf1, 0xc8, 0x27, 0xd6, 0x52, 0xfd, 0x31,
+ 0x8c, 0x13, 0x33, 0x36, 0xac, 0xd2, 0x2f, 0x7e, 0xbf, 0x78, 0xcf, 0xd9,
+ 0x2b, 0x12, 0x7f, 0xf1, 0x51, 0x07, 0xe5, 0xf0, 0x2c, 0xaa, 0xe3, 0x1a,
+ 0xd4, 0x85, 0x7d, 0x56, 0xf8, 0x55, 0x1c, 0xa0, 0xbf, 0x8d, 0x17, 0x14,
+ 0x8c, 0xfa, 0x57, 0x31, 0x20, 0xb5, 0x89, 0xef, 0xb4, 0xe5, 0x02, 0xc4,
+ 0x29, 0x11, 0x94, 0xeb, 0xb1, 0xe8, 0x30, 0xe5, 0x6b, 0x63, 0x2e, 0x1f,
+ 0x65, 0x0e, 0xc9, 0x86, 0x02, 0xf6, 0xf9, 0xd5, 0x72, 0x3d, 0x62, 0xff,
+ 0xcf, 0x81, 0xf4, 0x41, 0x0d, 0x53, 0xb2, 0x4f, 0x7d, 0x08, 0xaf, 0x8e,
+ 0xcf, 0xe3, 0x58, 0x32, 0x8d, 0xbd, 0x35, 0x21, 0x8c, 0x99, 0x8b, 0xed,
+ 0xb9, 0x81, 0xf4, 0x5b, 0x5b, 0x26, 0x0e, 0xda, 0xb3, 0xc8, 0x8d, 0x49,
+ 0x57, 0xbd, 0x9c, 0xe3, 0x98, 0x66, 0xdf, 0x35, 0x6e, 0x0c, 0xe1, 0x80,
+ 0xf1, 0xc7, 0x30, 0x16, 0x49, 0xee, 0x1c, 0xc1, 0xf9, 0x29, 0xa9, 0x61,
+ 0xfd, 0xad, 0xcb, 0xc6, 0x44, 0x3f, 0x2e, 0x62, 0x5e, 0x1f, 0x9a, 0x6c,
+ 0x0c, 0x37, 0xd7, 0xba, 0x7c, 0xca, 0xc1, 0x72, 0x4d, 0x79, 0x39, 0x73,
+ 0x5d, 0x85, 0x20, 0xf5, 0x75, 0x21, 0xe9, 0x65, 0xce, 0x11, 0x7d, 0xca,
+ 0x19, 0x3f, 0x47, 0xce, 0x44, 0x5e, 0x61, 0xa4, 0xf9, 0xc6, 0xfd, 0x15,
+ 0xf9, 0xff, 0x83, 0x6b, 0xe7, 0x0e, 0x8b, 0xb3, 0xf1, 0x3f, 0xb7, 0x2e,
+ 0xdd, 0x24, 0x72, 0x27, 0x03, 0xcc, 0xe9, 0xd1, 0xa9, 0x6b, 0xfa, 0x15,
+ 0x9d, 0x9e, 0x93, 0x9a, 0x61, 0xeb, 0xdc, 0x99, 0xb7, 0x69, 0x03, 0xef,
+ 0xa8, 0x46, 0xd6, 0x13, 0xfa, 0x55, 0x0d, 0xfd, 0xad, 0x09, 0xbd, 0x4b,
+ 0x53, 0x9e, 0x9e, 0xab, 0xe6, 0x7a, 0xb4, 0xac, 0x7e, 0xd7, 0xc2, 0xcd,
+ 0x6d, 0x70, 0xeb, 0x72, 0x7d, 0xca, 0x4a, 0x87, 0xe4, 0x77, 0x33, 0x20,
+ 0xb5, 0xfc, 0x05, 0x73, 0xde, 0x5a, 0xbe, 0xd8, 0xc1, 0x86, 0x7f, 0x97,
+ 0x93, 0xbd, 0xaf, 0xac, 0xc5, 0x5e, 0xfb, 0xe2, 0xdb, 0xee, 0x83, 0xf8,
+ 0xdb, 0xfc, 0x21, 0xbc, 0x39, 0xee, 0x21, 0xce, 0x14, 0x59, 0xd6, 0xa3,
+ 0x7a, 0x75, 0x3c, 0xfd, 0x2e, 0xf3, 0xe2, 0xc5, 0xa9, 0x92, 0x5f, 0xcc,
+ 0xb5, 0xae, 0x98, 0x52, 0xa4, 0x55, 0x85, 0x32, 0xca, 0xf9, 0x53, 0xc3,
+ 0x8d, 0x68, 0x11, 0xdb, 0xba, 0xc9, 0xe7, 0xee, 0x9c, 0x83, 0x79, 0x63,
+ 0xf9, 0xc3, 0x01, 0x67, 0xfe, 0x15, 0x60, 0x1e, 0x1d, 0xc5, 0x91, 0x5c,
+ 0x63, 0xe2, 0x3d, 0x39, 0xa7, 0xc3, 0x5e, 0xec, 0x12, 0x46, 0x71, 0x22,
+ 0x57, 0xca, 0xa1, 0x11, 0x39, 0xdf, 0x9a, 0x88, 0xba, 0x9c, 0x1c, 0x19,
+ 0x75, 0x69, 0xd9, 0xa8, 0xeb, 0xe6, 0x80, 0x60, 0x83, 0xe1, 0x42, 0x2c,
+ 0x52, 0x0e, 0x37, 0xf6, 0x18, 0x8e, 0x7f, 0xd4, 0xcf, 0x78, 0x11, 0x5d,
+ 0x24, 0x75, 0x59, 0x6a, 0xb2, 0x87, 0x35, 0x79, 0x31, 0xd2, 0x8b, 0x3d,
+ 0x78, 0x4d, 0x17, 0x7d, 0xec, 0x2f, 0xe9, 0xc3, 0x38, 0x87, 0xfd, 0xd6,
+ 0x7c, 0xb7, 0xf8, 0x92, 0x17, 0x87, 0x9a, 0xa6, 0xad, 0xa9, 0xb0, 0xc8,
+ 0xee, 0xc6, 0x69, 0xe6, 0x57, 0xdc, 0x1c, 0x8b, 0x9c, 0x66, 0xcd, 0x1e,
+ 0xd1, 0x4b, 0x3e, 0x7e, 0x57, 0x91, 0x4f, 0x3d, 0x33, 0x8b, 0x3f, 0xe1,
+ 0xef, 0xf5, 0x91, 0xbd, 0xca, 0x59, 0x6f, 0xf9, 0xcc, 0xdb, 0x81, 0xd2,
+ 0xec, 0x54, 0x9e, 0x8d, 0xe6, 0x09, 0x3a, 0x2b, 0x84, 0x56, 0x80, 0xfe,
+ 0x59, 0x8e, 0xde, 0xb0, 0x9c, 0xf3, 0x10, 0xbd, 0xc8, 0x9e, 0x22, 0xa8,
+ 0x0f, 0x0b, 0x2f, 0x51, 0x1f, 0x87, 0xae, 0x9d, 0xa9, 0x72, 0xf2, 0x57,
+ 0x05, 0xaf, 0x6f, 0x4e, 0xbe, 0xb8, 0xce, 0x8f, 0xdf, 0x58, 0x97, 0xc2,
+ 0x11, 0xe6, 0x04, 0xb1, 0x69, 0xc6, 0xc6, 0x91, 0x6e, 0xe2, 0x93, 0xdd,
+ 0xf6, 0xf9, 0x11, 0xc6, 0x81, 0x79, 0x4d, 0x8e, 0xf9, 0x3e, 0xe2, 0xec,
+ 0xb9, 0x9c, 0x7d, 0x66, 0xaf, 0xf7, 0x0d, 0x15, 0x63, 0xae, 0xf9, 0x12,
+ 0x7a, 0x6b, 0x85, 0x5e, 0x28, 0xb8, 0x6d, 0x32, 0x41, 0x1d, 0xd4, 0x09,
+ 0x5d, 0xeb, 0x29, 0x76, 0x73, 0x87, 0xc6, 0x84, 0x3e, 0x30, 0x32, 0x16,
+ 0xeb, 0xff, 0x29, 0xb0, 0xae, 0x0a, 0xda, 0xe0, 0x6c, 0xf1, 0xff, 0x38,
+ 0x7e, 0xa1, 0x84, 0x96, 0xd0, 0xf1, 0xc0, 0x64, 0x8e, 0x3b, 0x3e, 0x57,
+ 0x41, 0xdd, 0x69, 0xdd, 0x3f, 0x50, 0x15, 0x78, 0xec, 0x89, 0x04, 0x79,
+ 0x5f, 0x14, 0xdc, 0x3c, 0xe9, 0x83, 0xff, 0x4c, 0x15, 0x6b, 0xae, 0x0f,
+ 0x97, 0x9b, 0x69, 0xd7, 0x27, 0x4a, 0xbc, 0xdb, 0x7b, 0xa3, 0x78, 0x74,
+ 0x22, 0x0a, 0x93, 0x3e, 0x3b, 0x67, 0xca, 0x3e, 0xb0, 0xcf, 0xce, 0x9f,
+ 0x17, 0xd7, 0xd4, 0xd9, 0x7b, 0x54, 0xcf, 0x16, 0xf4, 0xc8, 0x59, 0x55,
+ 0x85, 0x0f, 0x4e, 0xcc, 0xdf, 0x5c, 0x0e, 0xeb, 0x85, 0xa5, 0xa9, 0x78,
+ 0x66, 0x17, 0x7d, 0x7e, 0xc5, 0xf2, 0x30, 0x7b, 0x19, 0xf6, 0x94, 0x6b,
+ 0xa5, 0xff, 0x1d, 0x60, 0xff, 0x5b, 0xda, 0xd3, 0xd7, 0xfb, 0x1f, 0x52,
+ 0xd9, 0x4d, 0x41, 0x58, 0x1f, 0x95, 0xa7, 0xac, 0x8f, 0xbd, 0xa9, 0x38,
+ 0xdf, 0x97, 0x3d, 0x3d, 0xcb, 0x7a, 0xab, 0xd9, 0xb2, 0xf2, 0xcd, 0xb1,
+ 0x4c, 0xc8, 0x1d, 0xc2, 0x99, 0x06, 0xd9, 0x07, 0x74, 0xe1, 0x83, 0xb8,
+ 0x1e, 0xd9, 0x05, 0xd9, 0x7b, 0x67, 0x8e, 0x5f, 0x2c, 0xe7, 0x0e, 0xeb,
+ 0x82, 0x9d, 0xe6, 0x22, 0x3c, 0x33, 0xbb, 0x16, 0xbd, 0x5e, 0xd8, 0xe7,
+ 0x62, 0x2c, 0x03, 0x6f, 0x2c, 0x85, 0xd4, 0xed, 0x78, 0xcb, 0x43, 0x08,
+ 0x63, 0xb6, 0x70, 0x08, 0x0f, 0x9e, 0x90, 0xfd, 0xc5, 0x07, 0x5a, 0x7d,
+ 0x27, 0xac, 0xbf, 0x8b, 0xa4, 0xe6, 0x99, 0x17, 0x2d, 0xab, 0x62, 0x6d,
+ 0x63, 0x84, 0xe5, 0x88, 0x18, 0xa3, 0x57, 0xb0, 0x7b, 0xff, 0x07, 0xa8,
+ 0xc1, 0xd9, 0xe9, 0xf4, 0xcd, 0xec, 0x25, 0x3b, 0x9f, 0x54, 0x21, 0x3c,
+ 0x4f, 0x19, 0x9f, 0x2e, 0x08, 0x4e, 0x79, 0xb0, 0x75, 0xcb, 0x89, 0x25,
+ 0x78, 0x61, 0x36, 0x8c, 0xb3, 0xa6, 0x4e, 0x9c, 0x04, 0x55, 0x99, 0xb2,
+ 0xaa, 0xab, 0xc9, 0x6b, 0xa5, 0xdb, 0x8d, 0x4d, 0x49, 0xe9, 0x0f, 0xf5,
+ 0xfe, 0x80, 0xc2, 0x92, 0x72, 0xe8, 0x0b, 0xfb, 0x81, 0x01, 0x3f, 0xfb,
+ 0xd5, 0x27, 0x55, 0x3c, 0xf3, 0xbe, 0x3b, 0x8c, 0xe7, 0x99, 0x7f, 0x7e,
+ 0x50, 0x90, 0x33, 0x53, 0xcc, 0x31, 0xd3, 0x51, 0xda, 0xca, 0x07, 0x57,
+ 0x7d, 0x15, 0x0e, 0x33, 0x5e, 0x5e, 0x32, 0xca, 0x98, 0xa3, 0xe4, 0x0c,
+ 0x95, 0xe4, 0xf7, 0x9d, 0x72, 0x56, 0xc4, 0x7a, 0x56, 0x77, 0xfa, 0x7d,
+ 0x63, 0xe6, 0xc6, 0x73, 0xc8, 0x21, 0xe6, 0xf5, 0xc6, 0xee, 0x88, 0x7a,
+ 0xc5, 0x4a, 0x7f, 0x5d, 0x51, 0xce, 0xdd, 0x55, 0xa8, 0xb0, 0x65, 0xc5,
+ 0xf0, 0x44, 0xa9, 0xa6, 0x54, 0x4b, 0x2f, 0xd7, 0x9d, 0x2d, 0xfa, 0x60,
+ 0x25, 0x63, 0xfd, 0x28, 0x6b, 0x74, 0xf9, 0x09, 0xa9, 0x25, 0xec, 0x5f,
+ 0xd4, 0x7a, 0x62, 0x61, 0xc1, 0x0d, 0x3e, 0xdc, 0x1f, 0xd2, 0x5a, 0xe4,
+ 0x2c, 0xf6, 0xd3, 0x85, 0x0e, 0x8f, 0x9c, 0x89, 0x7a, 0xa6, 0x20, 0xb5,
+ 0x5c, 0x72, 0x41, 0x69, 0xbd, 0x08, 0x6a, 0xc7, 0xc4, 0x46, 0xdd, 0xad,
+ 0x1f, 0x8d, 0x05, 0xe4, 0xdc, 0xfc, 0x90, 0x8b, 0xbd, 0xb6, 0x6f, 0xcc,
+ 0xb2, 0xee, 0x6e, 0xd6, 0xfb, 0xd7, 0xbb, 0x65, 0x3f, 0x39, 0xd6, 0x7b,
+ 0x4e, 0x69, 0x2d, 0x47, 0xd4, 0x8d, 0x74, 0x9e, 0xab, 0x92, 0x18, 0xc9,
+ 0x52, 0xce, 0x47, 0x6d, 0x99, 0xf6, 0x53, 0xa6, 0xd2, 0x99, 0xa1, 0x2a,
+ 0x5c, 0x1e, 0x87, 0xce, 0xa8, 0xc5, 0x79, 0x83, 0xc9, 0x29, 0x14, 0x4f,
+ 0xb7, 0x43, 0xfc, 0x5f, 0xeb, 0x15, 0x0c, 0x55, 0xc9, 0x9c, 0x3c, 0x3d,
+ 0x2e, 0x35, 0x46, 0x09, 0x3e, 0xc9, 0x56, 0xa7, 0x06, 0x70, 0x65, 0x0d,
+ 0xf0, 0xca, 0x98, 0xb3, 0xdf, 0x5e, 0x3c, 0xe3, 0x6d, 0x9f, 0x65, 0x78,
+ 0xc8, 0x3e, 0xa3, 0x20, 0xf4, 0x0f, 0xe2, 0x4c, 0x4e, 0x30, 0xe5, 0x00,
+ 0x31, 0x65, 0x6c, 0x90, 0x78, 0xb3, 0xa5, 0xe0, 0x9c, 0xb7, 0x32, 0x3e,
+ 0xa2, 0xcf, 0x3f, 0x49, 0xac, 0x7a, 0x18, 0xce, 0x7e, 0x7b, 0x43, 0xf1,
+ 0x0c, 0x42, 0x2c, 0xdf, 0xa9, 0xb6, 0x16, 0xec, 0x33, 0x5a, 0x8c, 0xb1,
+ 0x76, 0xb5, 0x79, 0xb6, 0x43, 0x6d, 0x99, 0xed, 0x52, 0x3b, 0x0a, 0xd2,
+ 0xb3, 0x3e, 0xd0, 0x7a, 0xff, 0x89, 0xed, 0x6a, 0xeb, 0x74, 0x8f, 0x22,
+ 0xa6, 0x0d, 0xf9, 0x52, 0x19, 0xd5, 0x35, 0xeb, 0xcc, 0xcf, 0x3b, 0xd9,
+ 0x77, 0x6d, 0x35, 0x4b, 0xfd, 0xbc, 0xfc, 0x1f, 0x57, 0x58, 0xfe, 0x67,
+ 0xa2, 0x77, 0xa3, 0xb2, 0xac, 0x5b, 0x93, 0x7f, 0x2d, 0xf6, 0xb0, 0x9e,
+ 0x4e, 0xb2, 0x36, 0x9a, 0x55, 0xe8, 0x63, 0xdf, 0x31, 0x6c, 0x2c, 0x2b,
+ 0xee, 0x97, 0x89, 0x4c, 0x72, 0x4e, 0x42, 0xfc, 0x15, 0x59, 0xf6, 0x20,
+ 0xf8, 0x7b, 0xf2, 0xbf, 0xb7, 0x28, 0x57, 0x97, 0x9c, 0x23, 0xf0, 0x5e,
+ 0x3f, 0x47, 0x76, 0x6c, 0xec, 0xba, 0x5c, 0x1e, 0x5e, 0x1b, 0x25, 0x3e,
+ 0xdd, 0xab, 0xb4, 0xc1, 0xa7, 0x1c, 0xb9, 0x2e, 0x5e, 0x66, 0x0c, 0x0f,
+ 0xdb, 0x31, 0xec, 0xc8, 0xb5, 0xb2, 0x28, 0xd7, 0x8a, 0x7c, 0xa7, 0x7d,
+ 0x3e, 0x8b, 0x74, 0x5a, 0xe7, 0xc6, 0xe4, 0x1c, 0x99, 0xcc, 0x2e, 0x45,
+ 0x36, 0x91, 0xe3, 0x84, 0x55, 0xa1, 0x77, 0xa9, 0x6d, 0xf6, 0xb9, 0x32,
+ 0x39, 0xd3, 0x25, 0xfb, 0xfb, 0x25, 0xb9, 0xa4, 0x8e, 0x2f, 0x0a, 0x76,
+ 0x4c, 0xca, 0x39, 0x6b, 0xcb, 0xfa, 0x99, 0x51, 0x11, 0x14, 0x59, 0xce,
+ 0x1a, 0x22, 0x8b, 0x9c, 0x17, 0x29, 0xc9, 0xf3, 0xb5, 0xa2, 0x3c, 0x62,
+ 0xab, 0xeb, 0x76, 0x2a, 0xfd, 0xff, 0xdf, 0xdb, 0x39, 0xe7, 0x2c, 0x49,
+ 0x49, 0x9e, 0x60, 0x4a, 0xf8, 0xcf, 0xb7, 0x8e, 0x8e, 0x0f, 0xe0, 0x15,
+ 0xde, 0xff, 0x65, 0xae, 0x24, 0x97, 0x1b, 0x33, 0xd3, 0xa5, 0x33, 0x72,
+ 0x6c, 0x29, 0xcd, 0x98, 0x31, 0x42, 0x3f, 0x72, 0xe4, 0x93, 0x33, 0x72,
+ 0x8d, 0xf3, 0x97, 0xed, 0xb9, 0x57, 0x3c, 0xcd, 0x7e, 0x19, 0x67, 0x0b,
+ 0xbf, 0x6d, 0xbf, 0xa6, 0x7c, 0x05, 0x7b, 0x64, 0xa1, 0x3d, 0x47, 0xda,
+ 0x72, 0x96, 0x44, 0xe1, 0xa9, 0x69, 0x60, 0xda, 0xe4, 0xb2, 0xa9, 0x21,
+ 0x3c, 0x6e, 0x58, 0xd6, 0x93, 0xcd, 0xba, 0x9c, 0x01, 0xba, 0x50, 0x6b,
+ 0xcf, 0x85, 0x60, 0x54, 0xe9, 0xb2, 0x77, 0x27, 0xe7, 0x48, 0x7a, 0xa8,
+ 0x03, 0x91, 0x5d, 0x7c, 0xa0, 0x64, 0x7b, 0x39, 0xdf, 0x96, 0xa5, 0x7e,
+ 0x44, 0x37, 0xa5, 0x73, 0x6e, 0x32, 0x73, 0xb9, 0x51, 0x27, 0xb7, 0xd9,
+ 0x3a, 0x79, 0xda, 0x10, 0x7f, 0x65, 0xf6, 0xa1, 0xaf, 0xce, 0x10, 0x3f,
+ 0x8c, 0x18, 0x5e, 0x1b, 0xab, 0x1d, 0x26, 0x3e, 0x39, 0xc2, 0xd8, 0x79,
+ 0xd4, 0xbc, 0x88, 0x8b, 0xf9, 0x97, 0xf0, 0xca, 0xb5, 0xff, 0x85, 0x13,
+ 0x7f, 0xf1, 0xb5, 0x6c, 0xb1, 0xcf, 0x32, 0xfd, 0x75, 0xcb, 0xb2, 0xb8,
+ 0xe4, 0xa1, 0x93, 0x4d, 0x72, 0xb6, 0xa9, 0x3c, 0xf5, 0xde, 0x3a, 0xd9,
+ 0xdf, 0x2a, 0x4b, 0x0d, 0x7e, 0xf5, 0x82, 0x2e, 0xba, 0xf9, 0x64, 0xf5,
+ 0x19, 0x5d, 0xe4, 0xd2, 0x8d, 0x51, 0xfb, 0x7f, 0x33, 0x43, 0x6b, 0x77,
+ 0xeb, 0x12, 0x3b, 0xef, 0x34, 0xb7, 0xd9, 0x39, 0x61, 0x30, 0x75, 0xab,
+ 0xad, 0x83, 0x83, 0xa9, 0x65, 0x8e, 0x2e, 0x52, 0x09, 0xfb, 0xfb, 0xe1,
+ 0x94, 0xa3, 0x9b, 0x5c, 0xaa, 0xde, 0xfe, 0x1e, 0x4d, 0x39, 0x67, 0xa2,
+ 0xb3, 0x29, 0xdd, 0xfe, 0x1e, 0x4f, 0xc5, 0xec, 0xef, 0x23, 0xa9, 0x5b,
+ 0xae, 0xf3, 0xc5, 0x9f, 0xff, 0x07, 0xd8, 0xc4, 0xd3, 0xb4, 0xb4, 0x3a,
+ 0x00, 0x00, 0x00 };
static const u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
static const u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
static struct fw_info bnx2_txp_fw_06 = {
- /* Firmware version: 4.0.5 */
+ /* Firmware version: 4.4.2 */
.ver_major = 0x4,
- .ver_minor = 0x0,
- .ver_fix = 0x5,
+ .ver_minor = 0x4,
+ .ver_fix = 0x2,
.start_addr = 0x08000098,
.text_addr = 0x08000000,
- .text_len = 0x3ad8,
+ .text_len = 0x3ab0,
.text_index = 0x0,
.gz_text = bnx2_TXP_b06FwText,
.gz_text_len = sizeof(bnx2_TXP_b06FwText),
@@ -4582,11 +4535,11 @@ static struct fw_info bnx2_txp_fw_06 = {
.data_index = 0x0,
.data = bnx2_TXP_b06FwData,
- .sbss_addr = 0x08003b00,
+ .sbss_addr = 0x08003ae0,
.sbss_len = 0x68,
.sbss_index = 0x0,
- .bss_addr = 0x08003b68,
+ .bss_addr = 0x08003b48,
.bss_len = 0x14c,
.bss_index = 0x0,
@@ -4611,3 +4564,4 @@ static const struct cpu_reg cpu_reg_txp = {
.spad_base = BNX2_TXP_SCRATCH,
.mips_view_base = 0x8000000,
};
+
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index a14dba1afcc..fd705d1295a 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -151,6 +151,8 @@ struct sw_rx_page {
#define PAGES_PER_SGE_SHIFT 0
#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
+#define BCM_RX_ETH_PAYLOAD_ALIGN 64
+
/* SGE ring related macros */
#define NUM_RX_SGE_PAGES 2
#define RX_SGE_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
@@ -750,8 +752,7 @@ struct bnx2x {
u32 rx_csum;
u32 rx_offset;
- u32 rx_buf_use_size; /* useable size */
- u32 rx_buf_size; /* with alignment */
+ u32 rx_buf_size;
#define ETH_OVREHEAD (ETH_HLEN + 8) /* 8 for CRC + VLAN */
#define ETH_MIN_PACKET_SIZE 60
#define ETH_MAX_PACKET_SIZE 1500
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 82deea0a63f..fce745148ff 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -59,8 +59,8 @@
#include "bnx2x.h"
#include "bnx2x_init.h"
-#define DRV_MODULE_VERSION "1.45.20"
-#define DRV_MODULE_RELDATE "2008/08/25"
+#define DRV_MODULE_VERSION "1.45.22"
+#define DRV_MODULE_RELDATE "2008/09/09"
#define BNX2X_BC_VER 0x040200
/* Time in jiffies before concluding the transmitter is hung */
@@ -649,15 +649,16 @@ static void bnx2x_int_disable(struct bnx2x *bp)
BNX2X_ERR("BUG! proper val not read from IGU!\n");
}
-static void bnx2x_int_disable_sync(struct bnx2x *bp)
+static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
{
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
int i;
/* disable interrupt handling */
atomic_inc(&bp->intr_sem);
- /* prevent the HW from sending interrupts */
- bnx2x_int_disable(bp);
+ if (disable_hw)
+ /* prevent the HW from sending interrupts */
+ bnx2x_int_disable(bp);
/* make sure all ISRs are done */
if (msix) {
@@ -1027,7 +1028,7 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
if (unlikely(skb == NULL))
return -ENOMEM;
- mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
+ mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_size,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
dev_kfree_skb(skb);
@@ -1169,7 +1170,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
/* move empty skb from pool to prod and map it */
prod_rx_buf->skb = fp->tpa_pool[queue].skb;
mapping = pci_map_single(bp->pdev, fp->tpa_pool[queue].skb->data,
- bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+ bp->rx_buf_size, PCI_DMA_FROMDEVICE);
pci_unmap_addr_set(prod_rx_buf, mapping, mapping);
/* move partial skb from cons to pool (don't unmap yet) */
@@ -1276,7 +1277,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
pool entry status to BNX2X_TPA_STOP even if new skb allocation
fails. */
pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping),
- bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+ bp->rx_buf_size, PCI_DMA_FROMDEVICE);
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
@@ -1520,7 +1521,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
} else if (bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0) {
pci_unmap_single(bp->pdev,
pci_unmap_addr(rx_buf, mapping),
- bp->rx_buf_use_size,
+ bp->rx_buf_size,
PCI_DMA_FROMDEVICE);
skb_reserve(skb, pad);
skb_put(skb, len);
@@ -4229,7 +4230,7 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
if (fp->tpa_state[i] == BNX2X_TPA_START)
pci_unmap_single(bp->pdev,
pci_unmap_addr(rx_buf, mapping),
- bp->rx_buf_use_size,
+ bp->rx_buf_size,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
@@ -4245,15 +4246,14 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
u16 ring_prod, cqe_ring_prod;
int i, j;
- bp->rx_buf_use_size = bp->dev->mtu;
- bp->rx_buf_use_size += bp->rx_offset + ETH_OVREHEAD;
- bp->rx_buf_size = bp->rx_buf_use_size + 64;
+ bp->rx_buf_size = bp->dev->mtu;
+ bp->rx_buf_size += bp->rx_offset + ETH_OVREHEAD +
+ BCM_RX_ETH_PAYLOAD_ALIGN;
if (bp->flags & TPA_ENABLE_FLAG) {
DP(NETIF_MSG_IFUP,
- "rx_buf_use_size %d rx_buf_size %d effective_mtu %d\n",
- bp->rx_buf_use_size, bp->rx_buf_size,
- bp->dev->mtu + ETH_OVREHEAD);
+ "rx_buf_size %d effective_mtu %d\n",
+ bp->rx_buf_size, bp->dev->mtu + ETH_OVREHEAD);
for_each_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
@@ -4462,9 +4462,10 @@ static void bnx2x_init_context(struct bnx2x *bp)
context->ustorm_st_context.common.status_block_id = sb_id;
context->ustorm_st_context.common.flags =
USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT;
- context->ustorm_st_context.common.mc_alignment_size = 64;
+ context->ustorm_st_context.common.mc_alignment_size =
+ BCM_RX_ETH_PAYLOAD_ALIGN;
context->ustorm_st_context.common.bd_buff_size =
- bp->rx_buf_use_size;
+ bp->rx_buf_size;
context->ustorm_st_context.common.bd_page_base_hi =
U64_HI(fp->rx_desc_mapping);
context->ustorm_st_context.common.bd_page_base_lo =
@@ -4717,7 +4718,7 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
}
/* Init CQ ring mapping and aggregation size */
- max_agg_size = min((u32)(bp->rx_buf_use_size +
+ max_agg_size = min((u32)(bp->rx_buf_size +
8*BCM_PAGE_SIZE*PAGES_PER_SGE),
(u32)0xffff);
for_each_queue(bp, i) {
@@ -5940,7 +5941,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
pci_unmap_single(bp->pdev,
pci_unmap_addr(rx_buf, mapping),
- bp->rx_buf_use_size,
+ bp->rx_buf_size,
PCI_DMA_FROMDEVICE);
rx_buf->skb = NULL;
@@ -6086,9 +6087,9 @@ static void bnx2x_netif_start(struct bnx2x *bp)
}
}
-static void bnx2x_netif_stop(struct bnx2x *bp)
+static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{
- bnx2x_int_disable_sync(bp);
+ bnx2x_int_disable_sync(bp, disable_hw);
if (netif_running(bp->dev)) {
bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
@@ -6475,7 +6476,7 @@ load_rings_free:
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
load_int_disable:
- bnx2x_int_disable_sync(bp);
+ bnx2x_int_disable_sync(bp, 1);
/* Release IRQs */
bnx2x_free_irq(bp);
load_error:
@@ -6650,7 +6651,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
- bnx2x_netif_stop(bp);
+ bnx2x_netif_stop(bp, 1);
if (!netif_running(bp->dev))
bnx2x_napi_disable(bp);
del_timer_sync(&bp->timer);
@@ -8791,7 +8792,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
if (!netif_running(bp->dev))
return BNX2X_LOOPBACK_FAILED;
- bnx2x_netif_stop(bp);
+ bnx2x_netif_stop(bp, 1);
if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) {
DP(NETIF_MSG_PROBE, "MAC loopback failed\n");
@@ -10346,6 +10347,74 @@ static int bnx2x_resume(struct pci_dev *pdev)
return rc;
}
+static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
+{
+ int i;
+
+ bp->state = BNX2X_STATE_ERROR;
+
+ bp->rx_mode = BNX2X_RX_MODE_NONE;
+
+ bnx2x_netif_stop(bp, 0);
+
+ del_timer_sync(&bp->timer);
+ bp->stats_state = STATS_STATE_DISABLED;
+ DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
+
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+
+ if (CHIP_IS_E1(bp)) {
+ struct mac_configuration_cmd *config =
+ bnx2x_sp(bp, mcast_config);
+
+ for (i = 0; i < config->hdr.length_6b; i++)
+ CAM_INVALIDATE(config->config_table[i]);
+ }
+
+ /* Free SKBs, SGEs, TPA pool and driver internals */
+ bnx2x_free_skbs(bp);
+ for_each_queue(bp, i)
+ bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
+ bnx2x_free_mem(bp);
+
+ bp->state = BNX2X_STATE_CLOSED;
+
+ netif_carrier_off(bp->dev);
+
+ return 0;
+}
+
+static void bnx2x_eeh_recover(struct bnx2x *bp)
+{
+ u32 val;
+
+ mutex_init(&bp->port.phy_mutex);
+
+ bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
+ bp->link_params.shmem_base = bp->common.shmem_base;
+ BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
+
+ if (!bp->common.shmem_base ||
+ (bp->common.shmem_base < 0xA0000) ||
+ (bp->common.shmem_base >= 0xC0000)) {
+ BNX2X_DEV_INFO("MCP not active\n");
+ bp->flags |= NO_MCP_FLAG;
+ return;
+ }
+
+ val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
+ if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+ != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
+ BNX2X_ERR("BAD MCP validity signature\n");
+
+ if (!BP_NOMCP(bp)) {
+ bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FUNC(bp)].drv_mb_header)
+ & DRV_MSG_SEQ_NUMBER_MASK);
+ BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+ }
+}
+
/**
* bnx2x_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
@@ -10365,7 +10434,7 @@ static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev,
netif_device_detach(dev);
if (netif_running(dev))
- bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+ bnx2x_eeh_nic_unload(bp);
pci_disable_device(pdev);
@@ -10420,8 +10489,10 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
rtnl_lock();
+ bnx2x_eeh_recover(bp);
+
if (netif_running(dev))
- bnx2x_nic_load(bp, LOAD_OPEN);
+ bnx2x_nic_load(bp, LOAD_NORMAL);
netif_device_attach(dev);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index b211486a0ca..ade5f3f6693 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -38,6 +38,7 @@
#include <linux/in.h>
#include <net/ipx.h>
#include <net/arp.h>
+#include <net/ipv6.h>
#include <asm/byteorder.h>
#include "bonding.h"
#include "bond_alb.h"
@@ -81,6 +82,7 @@
#define RLB_PROMISC_TIMEOUT 10*ALB_TIMER_TICKS_PER_SEC
static const u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+static const u8 mac_v6_allmcast[ETH_ALEN] = {0x33,0x33,0x00,0x00,0x00,0x01};
static const int alb_delta_in_ticks = HZ / ALB_TIMER_TICKS_PER_SEC;
#pragma pack(1)
@@ -710,7 +712,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
struct arp_pkt *arp = arp_pkt(skb);
struct slave *tx_slave = NULL;
- if (arp->op_code == __constant_htons(ARPOP_REPLY)) {
+ if (arp->op_code == htons(ARPOP_REPLY)) {
/* the arp must be sent on the selected
* rx channel
*/
@@ -719,7 +721,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
}
dprintk("Server sent ARP Reply packet\n");
- } else if (arp->op_code == __constant_htons(ARPOP_REQUEST)) {
+ } else if (arp->op_code == htons(ARPOP_REQUEST)) {
/* Create an entry in the rx_hashtbl for this client as a
* place holder.
* When the arp reply is received the entry will be updated
@@ -1290,6 +1292,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
u32 hash_index = 0;
const u8 *hash_start = NULL;
int res = 1;
+ struct ipv6hdr *ip6hdr;
skb_reset_mac_header(skb);
eth_data = eth_hdr(skb);
@@ -1319,11 +1322,32 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
}
break;
case ETH_P_IPV6:
+ /* IPv6 doesn't really use broadcast mac address, but leave
+ * that here just in case.
+ */
if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) {
do_tx_balance = 0;
break;
}
+ /* IPv6 uses all-nodes multicast as an equivalent to
+ * broadcasts in IPv4.
+ */
+ if (memcmp(eth_data->h_dest, mac_v6_allmcast, ETH_ALEN) == 0) {
+ do_tx_balance = 0;
+ break;
+ }
+
+ /* Additianally, DAD probes should not be tx-balanced as that
+ * will lead to false positives for duplicate addresses and
+ * prevent address configuration from working.
+ */
+ ip6hdr = ipv6_hdr(skb);
+ if (ipv6_addr_any(&ip6hdr->saddr)) {
+ do_tx_balance = 0;
+ break;
+ }
+
hash_start = (char *)&(ipv6_hdr(skb)->daddr);
hash_size = sizeof(ipv6_hdr(skb)->daddr);
break;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c792138511e..8e2be24f3fe 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3702,7 +3702,7 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
struct ethhdr *data = (struct ethhdr *)skb->data;
struct iphdr *iph = ip_hdr(skb);
- if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ if (skb->protocol == htons(ETH_P_IP)) {
return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
(data->h_dest[5] ^ bond_dev->dev_addr[5])) % count;
}
@@ -3723,8 +3723,8 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
__be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
int layer4_xor = 0;
- if (skb->protocol == __constant_htons(ETH_P_IP)) {
- if (!(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) &&
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP)) {
layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
@@ -4493,6 +4493,12 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
static const struct ethtool_ops bond_ethtool_ops = {
.get_drvinfo = bond_ethtool_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .get_tso = ethtool_op_get_tso,
+ .get_ufo = ethtool_op_get_ufo,
+ .get_flags = ethtool_op_get_flags,
};
/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index fb730ec0396..ffb668dd6d3 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -32,7 +32,7 @@
#ifdef BONDING_DEBUG
#define dprintk(fmt, args...) \
printk(KERN_DEBUG \
- DRV_NAME ": %s() %d: " fmt, __FUNCTION__, __LINE__ , ## args )
+ DRV_NAME ": %s() %d: " fmt, __func__, __LINE__ , ## args )
#else
#define dprintk(fmt, args...)
#endif /* BONDING_DEBUG */
@@ -333,5 +333,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_register_arp(struct bonding *);
void bond_unregister_arp(struct bonding *);
+/* exported from bond_main.c */
+extern struct list_head bond_dev_list;
+extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl bond_mode_tbl[];
+extern struct bond_parm_tbl xmit_hashtype_tbl[];
+extern struct bond_parm_tbl arp_validate_tbl[];
+extern struct bond_parm_tbl fail_over_mac_tbl[];
+
#endif /* _LINUX_BONDING_H */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index f1936d51b45..86909cfb14d 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -74,6 +74,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/mm.h>
@@ -91,6 +92,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/mutex.h>
+#include <linux/firmware.h>
#include <net/checksum.h>
@@ -197,6 +199,7 @@ static int link_mode;
MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("sun/cassini.bin");
module_param(cassini_debug, int, 0);
MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
module_param(link_mode, int, 0);
@@ -812,9 +815,44 @@ static int cas_reset_mii_phy(struct cas *cp)
return (limit <= 0);
}
+static int cas_saturn_firmware_init(struct cas *cp)
+{
+ const struct firmware *fw;
+ const char fw_name[] = "sun/cassini.bin";
+ int err;
+
+ if (PHY_NS_DP83065 != cp->phy_id)
+ return 0;
+
+ err = request_firmware(&fw, fw_name, &cp->pdev->dev);
+ if (err) {
+ printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n",
+ fw_name);
+ return err;
+ }
+ if (fw->size < 2) {
+ printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n",
+ fw->size, fw_name);
+ err = -EINVAL;
+ goto out;
+ }
+ cp->fw_load_addr= fw->data[1] << 8 | fw->data[0];
+ cp->fw_size = fw->size - 2;
+ cp->fw_data = vmalloc(cp->fw_size);
+ if (!cp->fw_data) {
+ err = -ENOMEM;
+ printk(KERN_ERR "cassini: \"%s\" Failed %d\n", fw_name, err);
+ goto out;
+ }
+ memcpy(cp->fw_data, &fw->data[2], cp->fw_size);
+out:
+ release_firmware(fw);
+ return err;
+}
+
static void cas_saturn_firmware_load(struct cas *cp)
{
- cas_saturn_patch_t *patch = cas_saturn_patch;
+ int i;
cas_phy_powerdown(cp);
@@ -833,11 +871,9 @@ static void cas_saturn_firmware_load(struct cas *cp)
/* download new firmware */
cas_phy_write(cp, DP83065_MII_MEM, 0x1);
- cas_phy_write(cp, DP83065_MII_REGE, patch->addr);
- while (patch->addr) {
- cas_phy_write(cp, DP83065_MII_REGD, patch->val);
- patch++;
- }
+ cas_phy_write(cp, DP83065_MII_REGE, cp->fw_load_addr);
+ for (i = 0; i < cp->fw_size; i++)
+ cas_phy_write(cp, DP83065_MII_REGD, cp->fw_data[i]);
/* enable firmware */
cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
@@ -2182,7 +2218,7 @@ static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words,
* do any additional locking here. stick the buffer
* at the end.
*/
- __skb_insert(skb, flow->prev, (struct sk_buff *) flow, flow);
+ __skb_queue_tail(flow, skb);
if (words[0] & RX_COMP1_RELEASE_FLOW) {
while ((skb = __skb_dequeue(flow))) {
cas_skb_release(skb);
@@ -5108,6 +5144,9 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
cas_reset(cp, 0);
if (cas_check_invariants(cp))
goto err_out_iounmap;
+ if (cp->cas_flags & CAS_FLAG_SATURN)
+ if (cas_saturn_firmware_init(cp))
+ goto err_out_iounmap;
cp->init_block = (struct cas_init_block *)
pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
@@ -5217,6 +5256,9 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
cp = netdev_priv(dev);
unregister_netdev(dev);
+ if (cp->fw_data)
+ vfree(cp->fw_data);
+
mutex_lock(&cp->pm_mutex);
flush_scheduled_work();
if (cp->hw_running)
diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
index 552af89ca1c..fd17a002b45 100644
--- a/drivers/net/cassini.h
+++ b/drivers/net/cassini.h
@@ -2514,1523 +2514,6 @@ static cas_hp_inst_t cas_prog_null[] = { {NULL} };
#define CAS_HP_FIRMWARE cas_prog_null
#endif
-/* firmware patch for NS_DP83065 */
-typedef struct cas_saturn_patch {
- u16 addr;
- u16 val;
-} cas_saturn_patch_t;
-
-#if 1
-cas_saturn_patch_t cas_saturn_patch[] = {
-{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009},
-{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000},
-{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000},
-{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff},
-{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025},
-{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f},
-{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026},
-{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011},
-{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d},
-{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086},
-{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f},
-{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3},
-{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047},
-{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a},
-{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047},
-{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033},
-{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f},
-{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084},
-{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004},
-{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096},
-{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c},
-{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027},
-{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084},
-{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047},
-{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a},
-{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047},
-{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054},
-{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f},
-{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084},
-{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004},
-{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6},
-{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084},
-{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003},
-{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025},
-{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6},
-{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f},
-{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7},
-{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f},
-{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec},
-{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa},
-{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7},
-{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082},
-{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001},
-{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046},
-{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081},
-{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a},
-{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020},
-{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027},
-{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084},
-{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7},
-{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084},
-{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047},
-{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a},
-{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047},
-{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad},
-{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082},
-{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001},
-{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084},
-{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041},
-{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026},
-{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023},
-{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027},
-{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed},
-{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083},
-{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042},
-{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e},
-{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084},
-{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003},
-{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df},
-{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6},
-{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f},
-{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7},
-{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f},
-{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec},
-{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa},
-{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011},
-{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd},
-{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce},
-{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff},
-{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096},
-{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c},
-{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027},
-{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049},
-{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091},
-{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6},
-{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085},
-{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c},
-{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1},
-{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f},
-{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025},
-{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016},
-{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052},
-{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e},
-{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7},
-{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6},
-{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4},
-{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083},
-{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001},
-{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046},
-{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081},
-{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a},
-{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd},
-{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025},
-{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084},
-{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084},
-{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018},
-{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019},
-{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004},
-{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e},
-{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b},
-{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007},
-{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027},
-{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081},
-{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b},
-{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007},
-{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027},
-{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e},
-{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd},
-{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086},
-{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049},
-{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012},
-{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071},
-{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f},
-{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084},
-{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008},
-{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6},
-{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4},
-{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006},
-{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025},
-{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016},
-{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e},
-{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd},
-{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026},
-{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082},
-{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001},
-{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084},
-{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f},
-{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec},
-{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa},
-{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7},
-{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f},
-{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd},
-{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce},
-{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff},
-{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096},
-{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c},
-{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026},
-{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012},
-{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f},
-{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027},
-{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023},
-{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027},
-{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084},
-{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051},
-{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091},
-{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e},
-{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce},
-{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff},
-{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e},
-{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd},
-{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c},
-{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce},
-{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff},
-{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e},
-{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096},
-{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c},
-{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026},
-{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024},
-{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026},
-{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018},
-{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019},
-{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001},
-{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009},
-{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020},
-{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081},
-{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015},
-{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044},
-{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1},
-{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f},
-{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044},
-{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029},
-{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025},
-{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f},
-{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047},
-{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a},
-{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047},
-{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034},
-{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011},
-{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084},
-{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002},
-{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e},
-{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096},
-{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc},
-{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097},
-{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1},
-{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086},
-{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012},
-{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7},
-{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010},
-{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd},
-{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031},
-{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e},
-{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6},
-{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f},
-{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7},
-{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f},
-{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec},
-{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa},
-{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008},
-{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5},
-{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002},
-{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6},
-{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4},
-{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084},
-{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001},
-{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046},
-{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081},
-{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003},
-{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f},
-{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd},
-{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025},
-{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085},
-{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044},
-{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026},
-{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012},
-{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001},
-{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010},
-{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd},
-{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce},
-{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff},
-{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e},
-{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096},
-{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003},
-{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026},
-{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012},
-{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003},
-{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027},
-{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085},
-{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044},
-{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026},
-{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012},
-{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001},
-{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010},
-{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce},
-{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff},
-{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e},
-{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6},
-{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a},
-{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010},
-{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085},
-{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8},
-{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000},
-{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084},
-{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001},
-{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085},
-{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046},
-{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081},
-{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009},
-{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030},
-{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081},
-{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f},
-{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044},
-{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b},
-{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029},
-{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026},
-{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011},
-{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022},
-{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6},
-{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba},
-{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084},
-{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d},
-{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085},
-{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005},
-{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e},
-{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca},
-{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022},
-{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000},
-{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018},
-{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000},
-{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046},
-{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085},
-{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002},
-{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085},
-{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001},
-{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f},
-{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004},
-{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004},
-{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7},
-{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086},
-{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012},
-{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007},
-{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006},
-{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d},
-{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070},
-{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba},
-{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7},
-{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001},
-{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001},
-{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6},
-{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084},
-{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002},
-{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004},
-{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001},
-{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001},
-{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4},
-{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7},
-{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6},
-{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084},
-{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008},
-{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6},
-{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081},
-{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008},
-{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7},
-{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e},
-{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086},
-{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040},
-{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e},
-{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7},
-{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f},
-{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082},
-{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f},
-{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f},
-{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f},
-{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f},
-{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f},
-{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f},
-{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f},
-{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f},
-{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f},
-{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f},
-{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f},
-{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f},
-{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f},
-{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012},
-{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010},
-{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004},
-{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7},
-{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7},
-{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7},
-{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7},
-{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086},
-{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012},
-{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012},
-{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7},
-{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004},
-{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004},
-{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001},
-{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001},
-{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008},
-{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081},
-{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b},
-{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce},
-{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd},
-{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e},
-{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081},
-{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b},
-{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce},
-{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd},
-{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e},
-{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081},
-{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b},
-{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce},
-{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd},
-{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e},
-{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081},
-{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b},
-{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce},
-{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd},
-{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e},
-{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081},
-{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b},
-{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce},
-{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd},
-{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e},
-{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081},
-{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b},
-{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce},
-{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd},
-{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e},
-{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081},
-{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b},
-{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce},
-{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd},
-{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e},
-{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081},
-{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008},
-{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce},
-{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd},
-{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6},
-{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081},
-{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003},
-{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047},
-{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009},
-{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081},
-{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006},
-{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009},
-{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe},
-{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006},
-{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081},
-{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008},
-{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7},
-{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e},
-{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6},
-{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026},
-{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f},
-{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7},
-{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e},
-{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6},
-{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084},
-{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f},
-{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b},
-{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012},
-{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012},
-{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc},
-{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009},
-{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe},
-{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070},
-{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f},
-{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c},
-{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f},
-{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084},
-{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f},
-{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c},
-{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f},
-{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1},
-{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003},
-{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040},
-{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f},
-{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027},
-{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b},
-{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081},
-{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b},
-{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027},
-{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087},
-{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f},
-{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002},
-{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a},
-{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7},
-{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086},
-{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f},
-{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012},
-{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075},
-{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7},
-{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020},
-{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f},
-{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002},
-{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071},
-{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047},
-{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097},
-{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089},
-{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f},
-{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089},
-{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f},
-{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089},
-{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f},
-{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089},
-{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f},
-{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089},
-{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7},
-{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7},
-{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6},
-{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027},
-{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f},
-{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f},
-{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f},
-{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d},
-{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078},
-{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c},
-{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6},
-{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027},
-{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f},
-{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f},
-{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f},
-{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b},
-{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d},
-{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075},
-{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c},
-{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a},
-{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027},
-{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f},
-{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f},
-{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c},
-{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083},
-{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075},
-{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078},
-{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b},
-{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc},
-{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d},
-{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000},
-{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070},
-{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072},
-{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e},
-{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6},
-{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026},
-{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce},
-{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd},
-{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e},
-{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6},
-{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026},
-{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce},
-{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd},
-{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e},
-{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6},
-{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026},
-{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce},
-{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd},
-{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e},
-{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086},
-{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040},
-{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x0000},
-{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075},
-{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e},
-{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012},
-{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8},
-{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012},
-{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f},
-{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007},
-{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048},
-{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6},
-{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4},
-{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7},
-{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6},
-{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081},
-{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf},
-{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005},
-{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b},
-{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005},
-{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6},
-{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd},
-{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086},
-{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f},
-{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089},
-{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002},
-{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077},
-{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094},
-{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6},
-{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd},
-{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce},
-{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6},
-{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001},
-{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081},
-{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003},
-{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066},
-{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8},
-{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084},
-{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b},
-{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079},
-{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008},
-{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e},
-{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6},
-{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a},
-{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012},
-{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012},
-{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb},
-{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7},
-{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6},
-{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036},
-{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c},
-{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7},
-{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086},
-{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012},
-{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012},
-{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001},
-{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001},
-{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe},
-{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004},
-{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004},
-{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba},
-{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7},
-{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086},
-{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012},
-{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012},
-{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7},
-{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6},
-{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084},
-{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008},
-{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c},
-{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026},
-{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076},
-{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e},
-{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e},
-{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6},
-{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081},
-{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c},
-{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7},
-{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d},
-{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb},
-{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004},
-{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7},
-{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce},
-{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6},
-{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081},
-{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005},
-{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6},
-{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6},
-{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084},
-{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012},
-{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083},
-{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c},
-{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000},
-{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006},
-{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b},
-{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083},
-{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041},
-{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e},
-{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7},
-{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086},
-{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f},
-{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012},
-{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f},
-{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c},
-{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7},
-{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086},
-{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a},
-{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012},
-{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009},
-{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c},
-{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d},
-{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c},
-{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e},
-{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027},
-{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020},
-{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e},
-{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c},
-{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba},
-{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7},
-{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6},
-{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048},
-{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d},
-{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021},
-{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004},
-{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7},
-{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd},
-{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f},
-{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000},
-{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000},
-{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008},
-{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5},
-{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c},
-{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba},
-{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7},
-{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6},
-{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084},
-{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001},
-{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006},
-{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7},
-{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036},
-{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7},
-{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032},
-{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026},
-{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f},
-{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089},
-{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001},
-{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1},
-{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c},
-{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027},
-{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f},
-{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005},
-{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080},
-{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080},
-{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7},
-{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6},
-{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005},
-{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f},
-{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f},
-{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4},
-{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b},
-{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007},
-{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f},
-{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000},
-{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000},
-{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000},
-{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6},
-{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6},
-{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7},
-{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001},
-{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018},
-{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018},
-{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7},
-{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6},
-{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007},
-{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4},
-{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054},
-{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7},
-{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a},
-{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039},
-{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084},
-{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022},
-{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7},
-{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6},
-{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7},
-{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6},
-{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4},
-{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f},
-{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072},
-{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072},
-{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071},
-{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027},
-{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001},
-{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081},
-{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024},
-{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070},
-{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096},
-{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080},
-{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064},
-{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070},
-{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096},
-{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010},
-{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064},
-{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070},
-{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096},
-{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020},
-{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064},
-{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070},
-{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096},
-{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040},
-{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074},
-{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074},
-{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078},
-{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6},
-{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085},
-{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af},
-{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4},
-{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6},
-{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081},
-{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036},
-{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026},
-{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022},
-{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044},
-{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022},
-{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020},
-{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081},
-{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d},
-{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084},
-{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044},
-{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022},
-{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020},
-{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081},
-{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f},
-{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084},
-{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044},
-{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6},
-{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f},
-{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022},
-{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c},
-{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006},
-{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed},
-{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007},
-{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9},
-{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006},
-{0x8aca, 0x0039}, { 0x0, 0x0 }
-};
-#else
-cas_saturn_patch_t cas_saturn_patch[] = {
-{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009},
-{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000},
-{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000},
-{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff},
-{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025},
-{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f},
-{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026},
-{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011},
-{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d},
-{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086},
-{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f},
-{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3},
-{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047},
-{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a},
-{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047},
-{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033},
-{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f},
-{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084},
-{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004},
-{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096},
-{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c},
-{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027},
-{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084},
-{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047},
-{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a},
-{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047},
-{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054},
-{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f},
-{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084},
-{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004},
-{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6},
-{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084},
-{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003},
-{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025},
-{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6},
-{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f},
-{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7},
-{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f},
-{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec},
-{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa},
-{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7},
-{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082},
-{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001},
-{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046},
-{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081},
-{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a},
-{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020},
-{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027},
-{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084},
-{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7},
-{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084},
-{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047},
-{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a},
-{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047},
-{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad},
-{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082},
-{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001},
-{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084},
-{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041},
-{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026},
-{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023},
-{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027},
-{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed},
-{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083},
-{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042},
-{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e},
-{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084},
-{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003},
-{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df},
-{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6},
-{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f},
-{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7},
-{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f},
-{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec},
-{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa},
-{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011},
-{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd},
-{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce},
-{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff},
-{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096},
-{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c},
-{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027},
-{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049},
-{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091},
-{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6},
-{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085},
-{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c},
-{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1},
-{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f},
-{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025},
-{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016},
-{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052},
-{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e},
-{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7},
-{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6},
-{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4},
-{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083},
-{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001},
-{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046},
-{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081},
-{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a},
-{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd},
-{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025},
-{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084},
-{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084},
-{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018},
-{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019},
-{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004},
-{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e},
-{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b},
-{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007},
-{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027},
-{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081},
-{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b},
-{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007},
-{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027},
-{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e},
-{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd},
-{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086},
-{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049},
-{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012},
-{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071},
-{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f},
-{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084},
-{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008},
-{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6},
-{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4},
-{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006},
-{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025},
-{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016},
-{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e},
-{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd},
-{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026},
-{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082},
-{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001},
-{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084},
-{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f},
-{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec},
-{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa},
-{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7},
-{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f},
-{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd},
-{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce},
-{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff},
-{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096},
-{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c},
-{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026},
-{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012},
-{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f},
-{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027},
-{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023},
-{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027},
-{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084},
-{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051},
-{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091},
-{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e},
-{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce},
-{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff},
-{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e},
-{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd},
-{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c},
-{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce},
-{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff},
-{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e},
-{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096},
-{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c},
-{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026},
-{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024},
-{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026},
-{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018},
-{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019},
-{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001},
-{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009},
-{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020},
-{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081},
-{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015},
-{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044},
-{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1},
-{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f},
-{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044},
-{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029},
-{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025},
-{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f},
-{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047},
-{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a},
-{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047},
-{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034},
-{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011},
-{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084},
-{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002},
-{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e},
-{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096},
-{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc},
-{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097},
-{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1},
-{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086},
-{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012},
-{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7},
-{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010},
-{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd},
-{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031},
-{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e},
-{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6},
-{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f},
-{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7},
-{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f},
-{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec},
-{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa},
-{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008},
-{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5},
-{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002},
-{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6},
-{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4},
-{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084},
-{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001},
-{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046},
-{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081},
-{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003},
-{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f},
-{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd},
-{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025},
-{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085},
-{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044},
-{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026},
-{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012},
-{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001},
-{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010},
-{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd},
-{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce},
-{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff},
-{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e},
-{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096},
-{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003},
-{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026},
-{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012},
-{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003},
-{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027},
-{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085},
-{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044},
-{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026},
-{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012},
-{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001},
-{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010},
-{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce},
-{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff},
-{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e},
-{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6},
-{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a},
-{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010},
-{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085},
-{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8},
-{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000},
-{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084},
-{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001},
-{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085},
-{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046},
-{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081},
-{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009},
-{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030},
-{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081},
-{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f},
-{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044},
-{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b},
-{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029},
-{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026},
-{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011},
-{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022},
-{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6},
-{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba},
-{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084},
-{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d},
-{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085},
-{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005},
-{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e},
-{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca},
-{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022},
-{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000},
-{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018},
-{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000},
-{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046},
-{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085},
-{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002},
-{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085},
-{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001},
-{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f},
-{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004},
-{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004},
-{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7},
-{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086},
-{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012},
-{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007},
-{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006},
-{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d},
-{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070},
-{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba},
-{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7},
-{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001},
-{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001},
-{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6},
-{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084},
-{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002},
-{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004},
-{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001},
-{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001},
-{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4},
-{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7},
-{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6},
-{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084},
-{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008},
-{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6},
-{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081},
-{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008},
-{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7},
-{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e},
-{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086},
-{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040},
-{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e},
-{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7},
-{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f},
-{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082},
-{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f},
-{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f},
-{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f},
-{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f},
-{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f},
-{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f},
-{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f},
-{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f},
-{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f},
-{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f},
-{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f},
-{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f},
-{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f},
-{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012},
-{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010},
-{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004},
-{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7},
-{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7},
-{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7},
-{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7},
-{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086},
-{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012},
-{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012},
-{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7},
-{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004},
-{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004},
-{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001},
-{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001},
-{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008},
-{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081},
-{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b},
-{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce},
-{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd},
-{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e},
-{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081},
-{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b},
-{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce},
-{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd},
-{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e},
-{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081},
-{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b},
-{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce},
-{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd},
-{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e},
-{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081},
-{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b},
-{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce},
-{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd},
-{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e},
-{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081},
-{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b},
-{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce},
-{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd},
-{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e},
-{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081},
-{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b},
-{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce},
-{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd},
-{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e},
-{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081},
-{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b},
-{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce},
-{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd},
-{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e},
-{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081},
-{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008},
-{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce},
-{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd},
-{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6},
-{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081},
-{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003},
-{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047},
-{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009},
-{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081},
-{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006},
-{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009},
-{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe},
-{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006},
-{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081},
-{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008},
-{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7},
-{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e},
-{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6},
-{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026},
-{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f},
-{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7},
-{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e},
-{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6},
-{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084},
-{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f},
-{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b},
-{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012},
-{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012},
-{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc},
-{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009},
-{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe},
-{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070},
-{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f},
-{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c},
-{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f},
-{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084},
-{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f},
-{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c},
-{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f},
-{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1},
-{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003},
-{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040},
-{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f},
-{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027},
-{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b},
-{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081},
-{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b},
-{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027},
-{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087},
-{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f},
-{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002},
-{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a},
-{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7},
-{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086},
-{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f},
-{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012},
-{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075},
-{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7},
-{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020},
-{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f},
-{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002},
-{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071},
-{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047},
-{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097},
-{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089},
-{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f},
-{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089},
-{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f},
-{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089},
-{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f},
-{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089},
-{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f},
-{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089},
-{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7},
-{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7},
-{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6},
-{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027},
-{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f},
-{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f},
-{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f},
-{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d},
-{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078},
-{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c},
-{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6},
-{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027},
-{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f},
-{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f},
-{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f},
-{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b},
-{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d},
-{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075},
-{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c},
-{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a},
-{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027},
-{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f},
-{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f},
-{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c},
-{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083},
-{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075},
-{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078},
-{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b},
-{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc},
-{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d},
-{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000},
-{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070},
-{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072},
-{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e},
-{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6},
-{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026},
-{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce},
-{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd},
-{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e},
-{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6},
-{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026},
-{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce},
-{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd},
-{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e},
-{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6},
-{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026},
-{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce},
-{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd},
-{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e},
-{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086},
-{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040},
-{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x006e},
-{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075},
-{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e},
-{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012},
-{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8},
-{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012},
-{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f},
-{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007},
-{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048},
-{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6},
-{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4},
-{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7},
-{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6},
-{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081},
-{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf},
-{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005},
-{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b},
-{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005},
-{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6},
-{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd},
-{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086},
-{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f},
-{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089},
-{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002},
-{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077},
-{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094},
-{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6},
-{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd},
-{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce},
-{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6},
-{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001},
-{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081},
-{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003},
-{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066},
-{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8},
-{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084},
-{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b},
-{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079},
-{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008},
-{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e},
-{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6},
-{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a},
-{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012},
-{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012},
-{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb},
-{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7},
-{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6},
-{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036},
-{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c},
-{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7},
-{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086},
-{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012},
-{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012},
-{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001},
-{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001},
-{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe},
-{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004},
-{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004},
-{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba},
-{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7},
-{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086},
-{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012},
-{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012},
-{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7},
-{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6},
-{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084},
-{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008},
-{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c},
-{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026},
-{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076},
-{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e},
-{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e},
-{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6},
-{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081},
-{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c},
-{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7},
-{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d},
-{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb},
-{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004},
-{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7},
-{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce},
-{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6},
-{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081},
-{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005},
-{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6},
-{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6},
-{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084},
-{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012},
-{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083},
-{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c},
-{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000},
-{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006},
-{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b},
-{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083},
-{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041},
-{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e},
-{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7},
-{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086},
-{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f},
-{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012},
-{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f},
-{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c},
-{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7},
-{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086},
-{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a},
-{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012},
-{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009},
-{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c},
-{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d},
-{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c},
-{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e},
-{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027},
-{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020},
-{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e},
-{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c},
-{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba},
-{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7},
-{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6},
-{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048},
-{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d},
-{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021},
-{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004},
-{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7},
-{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd},
-{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f},
-{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000},
-{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000},
-{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008},
-{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5},
-{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c},
-{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba},
-{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7},
-{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6},
-{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084},
-{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001},
-{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006},
-{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7},
-{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036},
-{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7},
-{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032},
-{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026},
-{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f},
-{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089},
-{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001},
-{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1},
-{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c},
-{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027},
-{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f},
-{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005},
-{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080},
-{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080},
-{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7},
-{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6},
-{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005},
-{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f},
-{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f},
-{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4},
-{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b},
-{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007},
-{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f},
-{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000},
-{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000},
-{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000},
-{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6},
-{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6},
-{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7},
-{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001},
-{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018},
-{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018},
-{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7},
-{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6},
-{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007},
-{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4},
-{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054},
-{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7},
-{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a},
-{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039},
-{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084},
-{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022},
-{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7},
-{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6},
-{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7},
-{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6},
-{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4},
-{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f},
-{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072},
-{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072},
-{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071},
-{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027},
-{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001},
-{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081},
-{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024},
-{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070},
-{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096},
-{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080},
-{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064},
-{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070},
-{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096},
-{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010},
-{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064},
-{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070},
-{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096},
-{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020},
-{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064},
-{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070},
-{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096},
-{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040},
-{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074},
-{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074},
-{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078},
-{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6},
-{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085},
-{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af},
-{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4},
-{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6},
-{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081},
-{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036},
-{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026},
-{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022},
-{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044},
-{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022},
-{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020},
-{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081},
-{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d},
-{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084},
-{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044},
-{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022},
-{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020},
-{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081},
-{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f},
-{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084},
-{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044},
-{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6},
-{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f},
-{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022},
-{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c},
-{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006},
-{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed},
-{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007},
-{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9},
-{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006},
-{0x8aca, 0x0039}, { 0x0, 0x0 }
-};
-#endif
-
-
/* phy types */
#define CAS_PHY_UNKNOWN 0x00
#define CAS_PHY_SERDES 0x01
@@ -4389,6 +2872,11 @@ struct cas {
dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
struct pci_dev *pdev;
struct net_device *dev;
+
+ /* Firmware Info */
+ u16 fw_load_addr;
+ u32 fw_size;
+ u8 *fw_data;
};
#define TX_DESC_NEXT(r, x) (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1))
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index ec6b0af3d46..017a5361b98 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -302,13 +302,7 @@ static int cpmac_mdio_reset(struct mii_bus *bus)
static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, };
-static struct mii_bus cpmac_mii = {
- .name = "cpmac-mii",
- .read = cpmac_mdio_read,
- .write = cpmac_mdio_write,
- .reset = cpmac_mdio_reset,
- .irq = mii_irqs,
-};
+static struct mii_bus *cpmac_mii;
static int cpmac_config(struct net_device *dev, struct ifmap *map)
{
@@ -1116,7 +1110,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
if (!(pdata->phy_mask & (1 << phy_id)))
continue;
- if (!cpmac_mii.phy_map[phy_id])
+ if (!cpmac_mii->phy_map[phy_id])
continue;
break;
}
@@ -1168,7 +1162,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
- priv->phy = phy_connect(dev, cpmac_mii.phy_map[phy_id]->dev.bus_id,
+ priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id,
&cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
if (IS_ERR(priv->phy)) {
if (netif_msg_drv(priv))
@@ -1216,11 +1210,22 @@ int __devinit cpmac_init(void)
u32 mask;
int i, res;
- cpmac_mii.priv = ioremap(AR7_REGS_MDIO, 256);
+ cpmac_mii = mdiobus_alloc();
+ if (cpmac_mii == NULL)
+ return -ENOMEM;
+
+ cpmac_mii->name = "cpmac-mii";
+ cpmac_mii->read = cpmac_mdio_read;
+ cpmac_mii->write = cpmac_mdio_write;
+ cpmac_mii->reset = cpmac_mdio_reset;
+ cpmac_mii->irq = mii_irqs;
+
+ cpmac_mii->priv = ioremap(AR7_REGS_MDIO, 256);
- if (!cpmac_mii.priv) {
+ if (!cpmac_mii->priv) {
printk(KERN_ERR "Can't ioremap mdio registers\n");
- return -ENXIO;
+ res = -ENXIO;
+ goto fail_alloc;
}
#warning FIXME: unhardcode gpio&reset bits
@@ -1230,10 +1235,10 @@ int __devinit cpmac_init(void)
ar7_device_reset(AR7_RESET_BIT_CPMAC_HI);
ar7_device_reset(AR7_RESET_BIT_EPHY);
- cpmac_mii.reset(&cpmac_mii);
+ cpmac_mii->reset(cpmac_mii);
for (i = 0; i < 300000; i++)
- if ((mask = cpmac_read(cpmac_mii.priv, CPMAC_MDIO_ALIVE)))
+ if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE)))
break;
else
cpu_relax();
@@ -1244,10 +1249,10 @@ int __devinit cpmac_init(void)
mask = 0;
}
- cpmac_mii.phy_mask = ~(mask | 0x80000000);
- snprintf(cpmac_mii.id, MII_BUS_ID_SIZE, "0");
+ cpmac_mii->phy_mask = ~(mask | 0x80000000);
+ snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "0");
- res = mdiobus_register(&cpmac_mii);
+ res = mdiobus_register(cpmac_mii);
if (res)
goto fail_mii;
@@ -1258,10 +1263,13 @@ int __devinit cpmac_init(void)
return 0;
fail_cpmac:
- mdiobus_unregister(&cpmac_mii);
+ mdiobus_unregister(cpmac_mii);
fail_mii:
- iounmap(cpmac_mii.priv);
+ iounmap(cpmac_mii->priv);
+
+fail_alloc:
+ mdiobus_free(cpmac_mii);
return res;
}
@@ -1269,8 +1277,9 @@ fail_mii:
void __devexit cpmac_exit(void)
{
platform_driver_unregister(&cpmac_driver);
- mdiobus_unregister(&cpmac_mii);
- iounmap(cpmac_mii.priv);
+ mdiobus_unregister(cpmac_mii);
+ mdiobus_free(cpmac_mii);
+ iounmap(cpmac_mii->priv);
}
module_init(cpmac_init);
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index ea6144a9565..7107620f615 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -36,8 +36,7 @@
Alan Cox : Removed 1.2 support, added 2.1 extra counters.
- Andrew Morton : andrewm@uow.edu.au
- : Kernel 2.3.48
+ Andrew Morton : Kernel 2.3.48
: Handle kmalloc() failures
: Other resource allocation fixes
: Add SMP locks
@@ -49,7 +48,7 @@
: Fixed an out-of-mem bug in dma_rx()
: Updated Documentation/networking/cs89x0.txt
- Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre1
+ Andrew Morton : Kernel 2.3.99-pre1
: Use skb_reserve to longword align IP header (two places)
: Remove a delay loop from dma_rx()
: Replace '100' with HZ
@@ -57,11 +56,11 @@
: Added 'cs89x0_dma=N' kernel boot option
: Correctly initialise lp->lock in non-module compile
- Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1
+ Andrew Morton : Kernel 2.3.99-pre4-1
: MOD_INC/DEC race fix (see
: http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
- Andrew Morton : andrewm@uow.edu.au / Kernel 2.4.0-test7-pre2
+ Andrew Morton : Kernel 2.4.0-test7-pre2
: Enhanced EEPROM support to cover more devices,
: abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
: (Jason Gunthorpe <jgg@ualberta.ca>)
@@ -156,7 +155,7 @@
#include "cs89x0.h"
static char version[] __initdata =
-"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
+"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n";
#define DRV_NAME "cs89x0"
@@ -194,6 +193,12 @@ static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
static unsigned int netcard_portlist[] __used __initdata = {CIRRUS_DEFAULT_BASE, 0};
static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
+#elif defined(CONFIG_MACH_MX31ADS)
+#include <mach/board-mx31ads.h>
+static unsigned int netcard_portlist[] __used __initdata = {
+ PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0
+};
+static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0};
#else
static unsigned int netcard_portlist[] __used __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -802,7 +807,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
} else {
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
-#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
+#ifdef CONFIG_CS89x0_NONISA_IRQ
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -1029,6 +1034,7 @@ skip_this_frame:
void __init reset_chip(struct net_device *dev)
{
+#if !defined(CONFIG_MACH_MX31ADS)
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
struct net_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
@@ -1057,6 +1063,7 @@ void __init reset_chip(struct net_device *dev)
reset_start_time = jiffies;
while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
;
+#endif /* !CONFIG_MACH_MX31ADS */
}
@@ -1304,7 +1311,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
+#ifndef CONFIG_CS89x0_NONISA_IRQ
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
@@ -1397,9 +1404,7 @@ net_open(struct net_device *dev)
release_dma:
#if ALLOW_DMA
free_dma(dev->dma);
-#endif
release_irq:
-#if ALLOW_DMA
release_dma_buff(lp);
#endif
writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
@@ -1871,7 +1876,7 @@ MODULE_PARM_DESC(dmasize , "(ignored)");
MODULE_PARM_DESC(use_dma , "(ignored)");
#endif
-MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>");
+MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 271140433b0..bc8e2413abd 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -54,7 +54,6 @@ struct port_info {
struct adapter *adapter;
struct vlan_group *vlan_grp;
struct sge_qset *qs;
- const struct port_type_info *port_type;
u8 port_id;
u8 rx_csum_offload;
u8 nqsets;
@@ -124,8 +123,7 @@ struct sge_rspq { /* state for an SGE response queue */
dma_addr_t phys_addr; /* physical address of the ring */
unsigned int cntxt_id; /* SGE context id for the response q */
spinlock_t lock; /* guards response processing */
- struct sk_buff *rx_head; /* offload packet receive queue head */
- struct sk_buff *rx_tail; /* offload packet receive queue tail */
+ struct sk_buff_head rx_queue; /* offload packet receive queue */
struct sk_buff *pg_skb; /* used to build frag list in napi handler */
unsigned long offload_pkts;
@@ -241,6 +239,7 @@ struct adapter {
unsigned int check_task_cnt;
struct delayed_work adap_check_task;
struct work_struct ext_intr_handler_task;
+ struct work_struct fatal_error_handler_task;
struct dentry *debugfs_root;
@@ -282,9 +281,11 @@ int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb);
void t3_os_ext_intr_handler(struct adapter *adapter);
void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status,
int speed, int duplex, int fc);
+void t3_os_phymod_changed(struct adapter *adap, int port_id);
void t3_sge_start(struct adapter *adap);
void t3_sge_stop(struct adapter *adap);
+void t3_stop_sge_timers(struct adapter *adap);
void t3_free_sge_resources(struct adapter *adap);
void t3_sge_err_intr_handler(struct adapter *adapter);
irq_handler_t t3_intr_handler(struct adapter *adap, int polling);
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index ee140e63ddc..5c3c05da4d9 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -33,17 +33,57 @@
#include "regs.h"
enum {
+ PMD_RSD = 10, /* PMA/PMD receive signal detect register */
+ PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */
+ PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */
+ XS_LN_STAT = 24 /* XS lane status register */
+};
+
+enum {
AEL100X_TX_DISABLE = 9,
AEL100X_TX_CONFIG1 = 0xc002,
AEL1002_PWR_DOWN_HI = 0xc011,
AEL1002_PWR_DOWN_LO = 0xc012,
AEL1002_XFI_EQL = 0xc015,
AEL1002_LB_EN = 0xc017,
+ AEL_OPT_SETTINGS = 0xc017,
+ AEL_I2C_CTRL = 0xc30a,
+ AEL_I2C_DATA = 0xc30b,
+ AEL_I2C_STAT = 0xc30c,
+ AEL2005_GPIO_CTRL = 0xc214,
+ AEL2005_GPIO_STAT = 0xc215,
+};
+
+enum { edc_none, edc_sr, edc_twinax };
- LASI_CTRL = 0x9002,
- LASI_STAT = 0x9005
+/* PHY module I2C device address */
+#define MODULE_DEV_ADDR 0xa0
+
+#define AEL2005_MODDET_IRQ 4
+
+struct reg_val {
+ unsigned short mmd_addr;
+ unsigned short reg_addr;
+ unsigned short clear_bits;
+ unsigned short set_bits;
};
+static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
+{
+ int err;
+
+ for (err = 0; rv->mmd_addr && !err; rv++) {
+ if (rv->clear_bits == 0xffff)
+ err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
+ rv->set_bits);
+ else
+ err = t3_mdio_change_bits(phy, rv->mmd_addr,
+ rv->reg_addr, rv->clear_bits,
+ rv->set_bits);
+ }
+ return err;
+}
+
static void ael100x_txon(struct cphy *phy)
{
int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
@@ -84,23 +124,23 @@ static int ael1002_intr_noop(struct cphy *phy)
return 0;
}
-static int ael100x_get_link_status(struct cphy *phy, int *link_ok,
- int *speed, int *duplex, int *fc)
+/*
+ * Get link status for a 10GBASE-R device.
+ */
+static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
+ int *duplex, int *fc)
{
if (link_ok) {
- unsigned int status;
- int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status);
-
- /*
- * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
- * once more to get the current link state.
- */
- if (!err && !(status & BMSR_LSTATUS))
- err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR,
- &status);
+ unsigned int stat0, stat1, stat2;
+ int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
+
+ if (!err)
+ err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
+ if (!err)
+ err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
if (err)
return err;
- *link_ok = !!(status & BMSR_LSTATUS);
+ *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
}
if (speed)
*speed = SPEED_10000;
@@ -115,15 +155,18 @@ static struct cphy_ops ael1002_ops = {
.intr_disable = ael1002_intr_noop,
.intr_clear = ael1002_intr_noop,
.intr_handler = ael1002_intr_noop,
- .get_link_status = ael100x_get_link_status,
+ .get_link_status = get_link_status_r,
.power_down = ael1002_power_down,
};
-void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops)
+int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops);
+ cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
+ "10GBASE-R");
ael100x_txon(phy);
+ return 0;
}
static int ael1006_reset(struct cphy *phy, int wait)
@@ -131,72 +174,985 @@ static int ael1006_reset(struct cphy *phy, int wait)
return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
}
-static int ael1006_intr_enable(struct cphy *phy)
+static int ael1006_power_down(struct cphy *phy, int enable)
{
- return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
+ return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
+ BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
}
-static int ael1006_intr_disable(struct cphy *phy)
+static struct cphy_ops ael1006_ops = {
+ .reset = ael1006_reset,
+ .intr_enable = t3_phy_lasi_intr_enable,
+ .intr_disable = t3_phy_lasi_intr_disable,
+ .intr_clear = t3_phy_lasi_intr_clear,
+ .intr_handler = t3_phy_lasi_intr_handler,
+ .get_link_status = get_link_status_r,
+ .power_down = ael1006_power_down,
+};
+
+int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
- return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
+ cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
+ "10GBASE-SR");
+ ael100x_txon(phy);
+ return 0;
}
-static int ael1006_intr_clear(struct cphy *phy)
+static int ael2005_setup_sr_edc(struct cphy *phy)
{
- u32 val;
+ static struct reg_val regs[] = {
+ { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
+ { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
+ { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
+ { 0, 0, 0, 0 }
+ };
+ static u16 sr_edc[] = {
+ 0xcc00, 0x2ff4,
+ 0xcc01, 0x3cd4,
+ 0xcc02, 0x2015,
+ 0xcc03, 0x3105,
+ 0xcc04, 0x6524,
+ 0xcc05, 0x27ff,
+ 0xcc06, 0x300f,
+ 0xcc07, 0x2c8b,
+ 0xcc08, 0x300b,
+ 0xcc09, 0x4009,
+ 0xcc0a, 0x400e,
+ 0xcc0b, 0x2f72,
+ 0xcc0c, 0x3002,
+ 0xcc0d, 0x1002,
+ 0xcc0e, 0x2172,
+ 0xcc0f, 0x3012,
+ 0xcc10, 0x1002,
+ 0xcc11, 0x25d2,
+ 0xcc12, 0x3012,
+ 0xcc13, 0x1002,
+ 0xcc14, 0xd01e,
+ 0xcc15, 0x27d2,
+ 0xcc16, 0x3012,
+ 0xcc17, 0x1002,
+ 0xcc18, 0x2004,
+ 0xcc19, 0x3c84,
+ 0xcc1a, 0x6436,
+ 0xcc1b, 0x2007,
+ 0xcc1c, 0x3f87,
+ 0xcc1d, 0x8676,
+ 0xcc1e, 0x40b7,
+ 0xcc1f, 0xa746,
+ 0xcc20, 0x4047,
+ 0xcc21, 0x5673,
+ 0xcc22, 0x2982,
+ 0xcc23, 0x3002,
+ 0xcc24, 0x13d2,
+ 0xcc25, 0x8bbd,
+ 0xcc26, 0x2862,
+ 0xcc27, 0x3012,
+ 0xcc28, 0x1002,
+ 0xcc29, 0x2092,
+ 0xcc2a, 0x3012,
+ 0xcc2b, 0x1002,
+ 0xcc2c, 0x5cc3,
+ 0xcc2d, 0x314,
+ 0xcc2e, 0x2942,
+ 0xcc2f, 0x3002,
+ 0xcc30, 0x1002,
+ 0xcc31, 0xd019,
+ 0xcc32, 0x2032,
+ 0xcc33, 0x3012,
+ 0xcc34, 0x1002,
+ 0xcc35, 0x2a04,
+ 0xcc36, 0x3c74,
+ 0xcc37, 0x6435,
+ 0xcc38, 0x2fa4,
+ 0xcc39, 0x3cd4,
+ 0xcc3a, 0x6624,
+ 0xcc3b, 0x5563,
+ 0xcc3c, 0x2d42,
+ 0xcc3d, 0x3002,
+ 0xcc3e, 0x13d2,
+ 0xcc3f, 0x464d,
+ 0xcc40, 0x2862,
+ 0xcc41, 0x3012,
+ 0xcc42, 0x1002,
+ 0xcc43, 0x2032,
+ 0xcc44, 0x3012,
+ 0xcc45, 0x1002,
+ 0xcc46, 0x2fb4,
+ 0xcc47, 0x3cd4,
+ 0xcc48, 0x6624,
+ 0xcc49, 0x5563,
+ 0xcc4a, 0x2d42,
+ 0xcc4b, 0x3002,
+ 0xcc4c, 0x13d2,
+ 0xcc4d, 0x2ed2,
+ 0xcc4e, 0x3002,
+ 0xcc4f, 0x1002,
+ 0xcc50, 0x2fd2,
+ 0xcc51, 0x3002,
+ 0xcc52, 0x1002,
+ 0xcc53, 0x004,
+ 0xcc54, 0x2942,
+ 0xcc55, 0x3002,
+ 0xcc56, 0x1002,
+ 0xcc57, 0x2092,
+ 0xcc58, 0x3012,
+ 0xcc59, 0x1002,
+ 0xcc5a, 0x5cc3,
+ 0xcc5b, 0x317,
+ 0xcc5c, 0x2f72,
+ 0xcc5d, 0x3002,
+ 0xcc5e, 0x1002,
+ 0xcc5f, 0x2942,
+ 0xcc60, 0x3002,
+ 0xcc61, 0x1002,
+ 0xcc62, 0x22cd,
+ 0xcc63, 0x301d,
+ 0xcc64, 0x2862,
+ 0xcc65, 0x3012,
+ 0xcc66, 0x1002,
+ 0xcc67, 0x2ed2,
+ 0xcc68, 0x3002,
+ 0xcc69, 0x1002,
+ 0xcc6a, 0x2d72,
+ 0xcc6b, 0x3002,
+ 0xcc6c, 0x1002,
+ 0xcc6d, 0x628f,
+ 0xcc6e, 0x2112,
+ 0xcc6f, 0x3012,
+ 0xcc70, 0x1002,
+ 0xcc71, 0x5aa3,
+ 0xcc72, 0x2dc2,
+ 0xcc73, 0x3002,
+ 0xcc74, 0x1312,
+ 0xcc75, 0x6f72,
+ 0xcc76, 0x1002,
+ 0xcc77, 0x2807,
+ 0xcc78, 0x31a7,
+ 0xcc79, 0x20c4,
+ 0xcc7a, 0x3c24,
+ 0xcc7b, 0x6724,
+ 0xcc7c, 0x1002,
+ 0xcc7d, 0x2807,
+ 0xcc7e, 0x3187,
+ 0xcc7f, 0x20c4,
+ 0xcc80, 0x3c24,
+ 0xcc81, 0x6724,
+ 0xcc82, 0x1002,
+ 0xcc83, 0x2514,
+ 0xcc84, 0x3c64,
+ 0xcc85, 0x6436,
+ 0xcc86, 0xdff4,
+ 0xcc87, 0x6436,
+ 0xcc88, 0x1002,
+ 0xcc89, 0x40a4,
+ 0xcc8a, 0x643c,
+ 0xcc8b, 0x4016,
+ 0xcc8c, 0x8c6c,
+ 0xcc8d, 0x2b24,
+ 0xcc8e, 0x3c24,
+ 0xcc8f, 0x6435,
+ 0xcc90, 0x1002,
+ 0xcc91, 0x2b24,
+ 0xcc92, 0x3c24,
+ 0xcc93, 0x643a,
+ 0xcc94, 0x4025,
+ 0xcc95, 0x8a5a,
+ 0xcc96, 0x1002,
+ 0xcc97, 0x2731,
+ 0xcc98, 0x3011,
+ 0xcc99, 0x1001,
+ 0xcc9a, 0xc7a0,
+ 0xcc9b, 0x100,
+ 0xcc9c, 0xc502,
+ 0xcc9d, 0x53ac,
+ 0xcc9e, 0xc503,
+ 0xcc9f, 0xd5d5,
+ 0xcca0, 0xc600,
+ 0xcca1, 0x2a6d,
+ 0xcca2, 0xc601,
+ 0xcca3, 0x2a4c,
+ 0xcca4, 0xc602,
+ 0xcca5, 0x111,
+ 0xcca6, 0xc60c,
+ 0xcca7, 0x5900,
+ 0xcca8, 0xc710,
+ 0xcca9, 0x700,
+ 0xccaa, 0xc718,
+ 0xccab, 0x700,
+ 0xccac, 0xc720,
+ 0xccad, 0x4700,
+ 0xccae, 0xc801,
+ 0xccaf, 0x7f50,
+ 0xccb0, 0xc802,
+ 0xccb1, 0x7760,
+ 0xccb2, 0xc803,
+ 0xccb3, 0x7fce,
+ 0xccb4, 0xc804,
+ 0xccb5, 0x5700,
+ 0xccb6, 0xc805,
+ 0xccb7, 0x5f11,
+ 0xccb8, 0xc806,
+ 0xccb9, 0x4751,
+ 0xccba, 0xc807,
+ 0xccbb, 0x57e1,
+ 0xccbc, 0xc808,
+ 0xccbd, 0x2700,
+ 0xccbe, 0xc809,
+ 0xccbf, 0x000,
+ 0xccc0, 0xc821,
+ 0xccc1, 0x002,
+ 0xccc2, 0xc822,
+ 0xccc3, 0x014,
+ 0xccc4, 0xc832,
+ 0xccc5, 0x1186,
+ 0xccc6, 0xc847,
+ 0xccc7, 0x1e02,
+ 0xccc8, 0xc013,
+ 0xccc9, 0xf341,
+ 0xccca, 0xc01a,
+ 0xcccb, 0x446,
+ 0xcccc, 0xc024,
+ 0xcccd, 0x1000,
+ 0xccce, 0xc025,
+ 0xcccf, 0xa00,
+ 0xccd0, 0xc026,
+ 0xccd1, 0xc0c,
+ 0xccd2, 0xc027,
+ 0xccd3, 0xc0c,
+ 0xccd4, 0xc029,
+ 0xccd5, 0x0a0,
+ 0xccd6, 0xc030,
+ 0xccd7, 0xa00,
+ 0xccd8, 0xc03c,
+ 0xccd9, 0x01c,
+ 0xccda, 0xc005,
+ 0xccdb, 0x7a06,
+ 0xccdc, 0x000,
+ 0xccdd, 0x2731,
+ 0xccde, 0x3011,
+ 0xccdf, 0x1001,
+ 0xcce0, 0xc620,
+ 0xcce1, 0x000,
+ 0xcce2, 0xc621,
+ 0xcce3, 0x03f,
+ 0xcce4, 0xc622,
+ 0xcce5, 0x000,
+ 0xcce6, 0xc623,
+ 0xcce7, 0x000,
+ 0xcce8, 0xc624,
+ 0xcce9, 0x000,
+ 0xccea, 0xc625,
+ 0xcceb, 0x000,
+ 0xccec, 0xc627,
+ 0xcced, 0x000,
+ 0xccee, 0xc628,
+ 0xccef, 0x000,
+ 0xccf0, 0xc62c,
+ 0xccf1, 0x000,
+ 0xccf2, 0x000,
+ 0xccf3, 0x2806,
+ 0xccf4, 0x3cb6,
+ 0xccf5, 0xc161,
+ 0xccf6, 0x6134,
+ 0xccf7, 0x6135,
+ 0xccf8, 0x5443,
+ 0xccf9, 0x303,
+ 0xccfa, 0x6524,
+ 0xccfb, 0x00b,
+ 0xccfc, 0x1002,
+ 0xccfd, 0x2104,
+ 0xccfe, 0x3c24,
+ 0xccff, 0x2105,
+ 0xcd00, 0x3805,
+ 0xcd01, 0x6524,
+ 0xcd02, 0xdff4,
+ 0xcd03, 0x4005,
+ 0xcd04, 0x6524,
+ 0xcd05, 0x1002,
+ 0xcd06, 0x5dd3,
+ 0xcd07, 0x306,
+ 0xcd08, 0x2ff7,
+ 0xcd09, 0x38f7,
+ 0xcd0a, 0x60b7,
+ 0xcd0b, 0xdffd,
+ 0xcd0c, 0x00a,
+ 0xcd0d, 0x1002,
+ 0xcd0e, 0
+ };
+ int i, err;
+
+ err = set_phy_regs(phy, regs);
+ if (err)
+ return err;
- return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
+ msleep(50);
+
+ for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
+ err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
+ sr_edc[i + 1]);
+ if (!err)
+ phy->priv = edc_sr;
+ return err;
}
-static int ael1006_intr_handler(struct cphy *phy)
+static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
{
- unsigned int status;
- int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
+ static struct reg_val regs[] = {
+ { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
+ { 0, 0, 0, 0 }
+ };
+ static struct reg_val preemphasis[] = {
+ { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
+ { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
+ { 0, 0, 0, 0 }
+ };
+ static u16 twinax_edc[] = {
+ 0xcc00, 0x4009,
+ 0xcc01, 0x27ff,
+ 0xcc02, 0x300f,
+ 0xcc03, 0x40aa,
+ 0xcc04, 0x401c,
+ 0xcc05, 0x401e,
+ 0xcc06, 0x2ff4,
+ 0xcc07, 0x3cd4,
+ 0xcc08, 0x2035,
+ 0xcc09, 0x3145,
+ 0xcc0a, 0x6524,
+ 0xcc0b, 0x26a2,
+ 0xcc0c, 0x3012,
+ 0xcc0d, 0x1002,
+ 0xcc0e, 0x29c2,
+ 0xcc0f, 0x3002,
+ 0xcc10, 0x1002,
+ 0xcc11, 0x2072,
+ 0xcc12, 0x3012,
+ 0xcc13, 0x1002,
+ 0xcc14, 0x22cd,
+ 0xcc15, 0x301d,
+ 0xcc16, 0x2e52,
+ 0xcc17, 0x3012,
+ 0xcc18, 0x1002,
+ 0xcc19, 0x28e2,
+ 0xcc1a, 0x3002,
+ 0xcc1b, 0x1002,
+ 0xcc1c, 0x628f,
+ 0xcc1d, 0x2ac2,
+ 0xcc1e, 0x3012,
+ 0xcc1f, 0x1002,
+ 0xcc20, 0x5553,
+ 0xcc21, 0x2ae2,
+ 0xcc22, 0x3002,
+ 0xcc23, 0x1302,
+ 0xcc24, 0x401e,
+ 0xcc25, 0x2be2,
+ 0xcc26, 0x3012,
+ 0xcc27, 0x1002,
+ 0xcc28, 0x2da2,
+ 0xcc29, 0x3012,
+ 0xcc2a, 0x1002,
+ 0xcc2b, 0x2ba2,
+ 0xcc2c, 0x3002,
+ 0xcc2d, 0x1002,
+ 0xcc2e, 0x5ee3,
+ 0xcc2f, 0x305,
+ 0xcc30, 0x400e,
+ 0xcc31, 0x2bc2,
+ 0xcc32, 0x3002,
+ 0xcc33, 0x1002,
+ 0xcc34, 0x2b82,
+ 0xcc35, 0x3012,
+ 0xcc36, 0x1002,
+ 0xcc37, 0x5663,
+ 0xcc38, 0x302,
+ 0xcc39, 0x401e,
+ 0xcc3a, 0x6f72,
+ 0xcc3b, 0x1002,
+ 0xcc3c, 0x628f,
+ 0xcc3d, 0x2be2,
+ 0xcc3e, 0x3012,
+ 0xcc3f, 0x1002,
+ 0xcc40, 0x22cd,
+ 0xcc41, 0x301d,
+ 0xcc42, 0x2e52,
+ 0xcc43, 0x3012,
+ 0xcc44, 0x1002,
+ 0xcc45, 0x2522,
+ 0xcc46, 0x3012,
+ 0xcc47, 0x1002,
+ 0xcc48, 0x2da2,
+ 0xcc49, 0x3012,
+ 0xcc4a, 0x1002,
+ 0xcc4b, 0x2ca2,
+ 0xcc4c, 0x3012,
+ 0xcc4d, 0x1002,
+ 0xcc4e, 0x2fa4,
+ 0xcc4f, 0x3cd4,
+ 0xcc50, 0x6624,
+ 0xcc51, 0x410b,
+ 0xcc52, 0x56b3,
+ 0xcc53, 0x3c4,
+ 0xcc54, 0x2fb2,
+ 0xcc55, 0x3002,
+ 0xcc56, 0x1002,
+ 0xcc57, 0x220b,
+ 0xcc58, 0x303b,
+ 0xcc59, 0x56b3,
+ 0xcc5a, 0x3c3,
+ 0xcc5b, 0x866b,
+ 0xcc5c, 0x400c,
+ 0xcc5d, 0x23a2,
+ 0xcc5e, 0x3012,
+ 0xcc5f, 0x1002,
+ 0xcc60, 0x2da2,
+ 0xcc61, 0x3012,
+ 0xcc62, 0x1002,
+ 0xcc63, 0x2ca2,
+ 0xcc64, 0x3012,
+ 0xcc65, 0x1002,
+ 0xcc66, 0x2fb4,
+ 0xcc67, 0x3cd4,
+ 0xcc68, 0x6624,
+ 0xcc69, 0x56b3,
+ 0xcc6a, 0x3c3,
+ 0xcc6b, 0x866b,
+ 0xcc6c, 0x401c,
+ 0xcc6d, 0x2205,
+ 0xcc6e, 0x3035,
+ 0xcc6f, 0x5b53,
+ 0xcc70, 0x2c52,
+ 0xcc71, 0x3002,
+ 0xcc72, 0x13c2,
+ 0xcc73, 0x5cc3,
+ 0xcc74, 0x317,
+ 0xcc75, 0x2522,
+ 0xcc76, 0x3012,
+ 0xcc77, 0x1002,
+ 0xcc78, 0x2da2,
+ 0xcc79, 0x3012,
+ 0xcc7a, 0x1002,
+ 0xcc7b, 0x2b82,
+ 0xcc7c, 0x3012,
+ 0xcc7d, 0x1002,
+ 0xcc7e, 0x5663,
+ 0xcc7f, 0x303,
+ 0xcc80, 0x401e,
+ 0xcc81, 0x004,
+ 0xcc82, 0x2c42,
+ 0xcc83, 0x3012,
+ 0xcc84, 0x1002,
+ 0xcc85, 0x6f72,
+ 0xcc86, 0x1002,
+ 0xcc87, 0x628f,
+ 0xcc88, 0x2304,
+ 0xcc89, 0x3c84,
+ 0xcc8a, 0x6436,
+ 0xcc8b, 0xdff4,
+ 0xcc8c, 0x6436,
+ 0xcc8d, 0x2ff5,
+ 0xcc8e, 0x3005,
+ 0xcc8f, 0x8656,
+ 0xcc90, 0xdfba,
+ 0xcc91, 0x56a3,
+ 0xcc92, 0xd05a,
+ 0xcc93, 0x21c2,
+ 0xcc94, 0x3012,
+ 0xcc95, 0x1392,
+ 0xcc96, 0xd05a,
+ 0xcc97, 0x56a3,
+ 0xcc98, 0xdfba,
+ 0xcc99, 0x383,
+ 0xcc9a, 0x6f72,
+ 0xcc9b, 0x1002,
+ 0xcc9c, 0x28c5,
+ 0xcc9d, 0x3005,
+ 0xcc9e, 0x4178,
+ 0xcc9f, 0x5653,
+ 0xcca0, 0x384,
+ 0xcca1, 0x22b2,
+ 0xcca2, 0x3012,
+ 0xcca3, 0x1002,
+ 0xcca4, 0x2be5,
+ 0xcca5, 0x3005,
+ 0xcca6, 0x41e8,
+ 0xcca7, 0x5653,
+ 0xcca8, 0x382,
+ 0xcca9, 0x002,
+ 0xccaa, 0x4258,
+ 0xccab, 0x2474,
+ 0xccac, 0x3c84,
+ 0xccad, 0x6437,
+ 0xccae, 0xdff4,
+ 0xccaf, 0x6437,
+ 0xccb0, 0x2ff5,
+ 0xccb1, 0x3c05,
+ 0xccb2, 0x8757,
+ 0xccb3, 0xb888,
+ 0xccb4, 0x9787,
+ 0xccb5, 0xdff4,
+ 0xccb6, 0x6724,
+ 0xccb7, 0x866a,
+ 0xccb8, 0x6f72,
+ 0xccb9, 0x1002,
+ 0xccba, 0x2d01,
+ 0xccbb, 0x3011,
+ 0xccbc, 0x1001,
+ 0xccbd, 0xc620,
+ 0xccbe, 0x14e5,
+ 0xccbf, 0xc621,
+ 0xccc0, 0xc53d,
+ 0xccc1, 0xc622,
+ 0xccc2, 0x3cbe,
+ 0xccc3, 0xc623,
+ 0xccc4, 0x4452,
+ 0xccc5, 0xc624,
+ 0xccc6, 0xc5c5,
+ 0xccc7, 0xc625,
+ 0xccc8, 0xe01e,
+ 0xccc9, 0xc627,
+ 0xccca, 0x000,
+ 0xcccb, 0xc628,
+ 0xcccc, 0x000,
+ 0xcccd, 0xc62b,
+ 0xccce, 0x000,
+ 0xcccf, 0xc62c,
+ 0xccd0, 0x000,
+ 0xccd1, 0x000,
+ 0xccd2, 0x2d01,
+ 0xccd3, 0x3011,
+ 0xccd4, 0x1001,
+ 0xccd5, 0xc620,
+ 0xccd6, 0x000,
+ 0xccd7, 0xc621,
+ 0xccd8, 0x000,
+ 0xccd9, 0xc622,
+ 0xccda, 0x0ce,
+ 0xccdb, 0xc623,
+ 0xccdc, 0x07f,
+ 0xccdd, 0xc624,
+ 0xccde, 0x032,
+ 0xccdf, 0xc625,
+ 0xcce0, 0x000,
+ 0xcce1, 0xc627,
+ 0xcce2, 0x000,
+ 0xcce3, 0xc628,
+ 0xcce4, 0x000,
+ 0xcce5, 0xc62b,
+ 0xcce6, 0x000,
+ 0xcce7, 0xc62c,
+ 0xcce8, 0x000,
+ 0xcce9, 0x000,
+ 0xccea, 0x2d01,
+ 0xcceb, 0x3011,
+ 0xccec, 0x1001,
+ 0xcced, 0xc502,
+ 0xccee, 0x609f,
+ 0xccef, 0xc600,
+ 0xccf0, 0x2a6e,
+ 0xccf1, 0xc601,
+ 0xccf2, 0x2a2c,
+ 0xccf3, 0xc60c,
+ 0xccf4, 0x5400,
+ 0xccf5, 0xc710,
+ 0xccf6, 0x700,
+ 0xccf7, 0xc718,
+ 0xccf8, 0x700,
+ 0xccf9, 0xc720,
+ 0xccfa, 0x4700,
+ 0xccfb, 0xc728,
+ 0xccfc, 0x700,
+ 0xccfd, 0xc729,
+ 0xccfe, 0x1207,
+ 0xccff, 0xc801,
+ 0xcd00, 0x7f50,
+ 0xcd01, 0xc802,
+ 0xcd02, 0x7760,
+ 0xcd03, 0xc803,
+ 0xcd04, 0x7fce,
+ 0xcd05, 0xc804,
+ 0xcd06, 0x520e,
+ 0xcd07, 0xc805,
+ 0xcd08, 0x5c11,
+ 0xcd09, 0xc806,
+ 0xcd0a, 0x3c51,
+ 0xcd0b, 0xc807,
+ 0xcd0c, 0x4061,
+ 0xcd0d, 0xc808,
+ 0xcd0e, 0x49c1,
+ 0xcd0f, 0xc809,
+ 0xcd10, 0x3840,
+ 0xcd11, 0xc80a,
+ 0xcd12, 0x000,
+ 0xcd13, 0xc821,
+ 0xcd14, 0x002,
+ 0xcd15, 0xc822,
+ 0xcd16, 0x046,
+ 0xcd17, 0xc844,
+ 0xcd18, 0x182f,
+ 0xcd19, 0xc013,
+ 0xcd1a, 0xf341,
+ 0xcd1b, 0xc01a,
+ 0xcd1c, 0x446,
+ 0xcd1d, 0xc024,
+ 0xcd1e, 0x1000,
+ 0xcd1f, 0xc025,
+ 0xcd20, 0xa00,
+ 0xcd21, 0xc026,
+ 0xcd22, 0xc0c,
+ 0xcd23, 0xc027,
+ 0xcd24, 0xc0c,
+ 0xcd25, 0xc029,
+ 0xcd26, 0x0a0,
+ 0xcd27, 0xc030,
+ 0xcd28, 0xa00,
+ 0xcd29, 0xc03c,
+ 0xcd2a, 0x01c,
+ 0xcd2b, 0x000,
+ 0xcd2c, 0x2b84,
+ 0xcd2d, 0x3c74,
+ 0xcd2e, 0x6435,
+ 0xcd2f, 0xdff4,
+ 0xcd30, 0x6435,
+ 0xcd31, 0x2806,
+ 0xcd32, 0x3006,
+ 0xcd33, 0x8565,
+ 0xcd34, 0x2b24,
+ 0xcd35, 0x3c24,
+ 0xcd36, 0x6436,
+ 0xcd37, 0x1002,
+ 0xcd38, 0x2b24,
+ 0xcd39, 0x3c24,
+ 0xcd3a, 0x6436,
+ 0xcd3b, 0x4045,
+ 0xcd3c, 0x8656,
+ 0xcd3d, 0x1002,
+ 0xcd3e, 0x2807,
+ 0xcd3f, 0x31a7,
+ 0xcd40, 0x20c4,
+ 0xcd41, 0x3c24,
+ 0xcd42, 0x6724,
+ 0xcd43, 0x1002,
+ 0xcd44, 0x2807,
+ 0xcd45, 0x3187,
+ 0xcd46, 0x20c4,
+ 0xcd47, 0x3c24,
+ 0xcd48, 0x6724,
+ 0xcd49, 0x1002,
+ 0xcd4a, 0x2514,
+ 0xcd4b, 0x3c64,
+ 0xcd4c, 0x6436,
+ 0xcd4d, 0xdff4,
+ 0xcd4e, 0x6436,
+ 0xcd4f, 0x1002,
+ 0xcd50, 0x2806,
+ 0xcd51, 0x3cb6,
+ 0xcd52, 0xc161,
+ 0xcd53, 0x6134,
+ 0xcd54, 0x6135,
+ 0xcd55, 0x5443,
+ 0xcd56, 0x303,
+ 0xcd57, 0x6524,
+ 0xcd58, 0x00b,
+ 0xcd59, 0x1002,
+ 0xcd5a, 0xd019,
+ 0xcd5b, 0x2104,
+ 0xcd5c, 0x3c24,
+ 0xcd5d, 0x2105,
+ 0xcd5e, 0x3805,
+ 0xcd5f, 0x6524,
+ 0xcd60, 0xdff4,
+ 0xcd61, 0x4005,
+ 0xcd62, 0x6524,
+ 0xcd63, 0x2e8d,
+ 0xcd64, 0x303d,
+ 0xcd65, 0x5dd3,
+ 0xcd66, 0x306,
+ 0xcd67, 0x2ff7,
+ 0xcd68, 0x38f7,
+ 0xcd69, 0x60b7,
+ 0xcd6a, 0xdffd,
+ 0xcd6b, 0x00a,
+ 0xcd6c, 0x1002,
+ 0xcd6d, 0
+ };
+ int i, err;
+ err = set_phy_regs(phy, regs);
+ if (!err && modtype == phy_modtype_twinax_long)
+ err = set_phy_regs(phy, preemphasis);
if (err)
return err;
- return (status & 1) ? cphy_cause_link_change : 0;
+
+ msleep(50);
+
+ for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
+ err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
+ twinax_edc[i + 1]);
+ if (!err)
+ phy->priv = edc_twinax;
+ return err;
}
-static int ael1006_power_down(struct cphy *phy, int enable)
+static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
{
- return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
- BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
+ int i, err;
+ unsigned int stat, data;
+
+ err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
+ (dev_addr << 8) | (1 << 8) | word_addr);
+ if (err)
+ return err;
+
+ for (i = 0; i < 5; i++) {
+ msleep(1);
+ err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
+ if (err)
+ return err;
+ if ((stat & 3) == 1) {
+ err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
+ &data);
+ if (err)
+ return err;
+ return data >> 8;
+ }
+ }
+ CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
+ phy->addr, word_addr);
+ return -ETIMEDOUT;
}
-static struct cphy_ops ael1006_ops = {
- .reset = ael1006_reset,
- .intr_enable = ael1006_intr_enable,
- .intr_disable = ael1006_intr_disable,
- .intr_clear = ael1006_intr_clear,
- .intr_handler = ael1006_intr_handler,
- .get_link_status = ael100x_get_link_status,
- .power_down = ael1006_power_down,
+static int get_module_type(struct cphy *phy, int delay_ms)
+{
+ int v;
+ unsigned int stat;
+
+ v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
+ if (v)
+ return v;
+
+ if (stat & (1 << 8)) /* module absent */
+ return phy_modtype_none;
+
+ if (delay_ms)
+ msleep(delay_ms);
+
+ /* see SFF-8472 for below */
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
+ if (v < 0)
+ return v;
+
+ if (v == 0x10)
+ return phy_modtype_sr;
+ if (v == 0x20)
+ return phy_modtype_lr;
+ if (v == 0x40)
+ return phy_modtype_lrm;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
+ if (v < 0)
+ return v;
+ if (v != 4)
+ goto unknown;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
+ if (v < 0)
+ return v;
+
+ if (v & 0x80) {
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
+ if (v < 0)
+ return v;
+ return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
+ }
+unknown:
+ return phy_modtype_unknown;
+}
+
+static int ael2005_intr_enable(struct cphy *phy)
+{
+ int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
+ return err ? err : t3_phy_lasi_intr_enable(phy);
+}
+
+static int ael2005_intr_disable(struct cphy *phy)
+{
+ int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
+ return err ? err : t3_phy_lasi_intr_disable(phy);
+}
+
+static int ael2005_intr_clear(struct cphy *phy)
+{
+ int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
+ return err ? err : t3_phy_lasi_intr_clear(phy);
+}
+
+static int ael2005_reset(struct cphy *phy, int wait)
+{
+ static struct reg_val regs0[] = {
+ { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
+ { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
+ { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
+ { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
+ { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
+ { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
+ { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
+ { 0, 0, 0, 0 }
+ };
+ static struct reg_val regs1[] = {
+ { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
+ { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ int err, lasi_ctrl;
+
+ err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
+ if (err)
+ return err;
+
+ err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
+ if (err)
+ return err;
+
+ msleep(125);
+ phy->priv = edc_none;
+ err = set_phy_regs(phy, regs0);
+ if (err)
+ return err;
+
+ msleep(50);
+
+ err = get_module_type(phy, 0);
+ if (err < 0)
+ return err;
+ phy->modtype = err;
+
+ if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
+ err = ael2005_setup_twinax_edc(phy, err);
+ else
+ err = ael2005_setup_sr_edc(phy);
+ if (err)
+ return err;
+
+ err = set_phy_regs(phy, regs1);
+ if (err)
+ return err;
+
+ /* reset wipes out interrupts, reenable them if they were on */
+ if (lasi_ctrl & 1)
+ err = ael2005_intr_enable(phy);
+ return err;
+}
+
+static int ael2005_intr_handler(struct cphy *phy)
+{
+ unsigned int stat;
+ int ret, edc_needed, cause = 0;
+
+ ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
+ if (ret)
+ return ret;
+
+ if (stat & AEL2005_MODDET_IRQ) {
+ ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
+ 0xd00);
+ if (ret)
+ return ret;
+
+ /* modules have max 300 ms init time after hot plug */
+ ret = get_module_type(phy, 300);
+ if (ret < 0)
+ return ret;
+
+ phy->modtype = ret;
+ if (ret == phy_modtype_none)
+ edc_needed = phy->priv; /* on unplug retain EDC */
+ else if (ret == phy_modtype_twinax ||
+ ret == phy_modtype_twinax_long)
+ edc_needed = edc_twinax;
+ else
+ edc_needed = edc_sr;
+
+ if (edc_needed != phy->priv) {
+ ret = ael2005_reset(phy, 0);
+ return ret ? ret : cphy_cause_module_change;
+ }
+ cause = cphy_cause_module_change;
+ }
+
+ ret = t3_phy_lasi_intr_handler(phy);
+ if (ret < 0)
+ return ret;
+
+ ret |= cause;
+ return ret ? ret : cphy_cause_link_change;
+}
+
+static struct cphy_ops ael2005_ops = {
+ .reset = ael2005_reset,
+ .intr_enable = ael2005_intr_enable,
+ .intr_disable = ael2005_intr_disable,
+ .intr_clear = ael2005_intr_clear,
+ .intr_handler = ael2005_intr_handler,
+ .get_link_status = get_link_status_r,
+ .power_down = ael1002_power_down,
};
-void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops)
+int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops);
- ael100x_txon(phy);
+ cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
+ SUPPORTED_IRQ, "10GBASE-R");
+ msleep(125);
+ return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
+ 1 << 5);
+}
+
+/*
+ * Get link status for a 10GBASE-X device.
+ */
+static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
+ int *duplex, int *fc)
+{
+ if (link_ok) {
+ unsigned int stat0, stat1, stat2;
+ int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
+
+ if (!err)
+ err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
+ if (!err)
+ err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
+ if (err)
+ return err;
+ *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
+ }
+ if (speed)
+ *speed = SPEED_10000;
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ return 0;
}
static struct cphy_ops qt2045_ops = {
.reset = ael1006_reset,
- .intr_enable = ael1006_intr_enable,
- .intr_disable = ael1006_intr_disable,
- .intr_clear = ael1006_intr_clear,
- .intr_handler = ael1006_intr_handler,
- .get_link_status = ael100x_get_link_status,
+ .intr_enable = t3_phy_lasi_intr_enable,
+ .intr_disable = t3_phy_lasi_intr_disable,
+ .intr_clear = t3_phy_lasi_intr_clear,
+ .intr_handler = t3_phy_lasi_intr_handler,
+ .get_link_status = get_link_status_x,
.power_down = ael1006_power_down,
};
-void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops)
+int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
unsigned int stat;
- cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops);
+ cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
+ "10GBASE-CX4");
/*
* Some cards where the PHY is supposed to be at address 0 actually
@@ -205,6 +1161,7 @@ void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
stat == 0xffff)
phy->addr = 1;
+ return 0;
}
static int xaui_direct_reset(struct cphy *phy, int wait)
@@ -250,8 +1207,11 @@ static struct cphy_ops xaui_direct_ops = {
.power_down = xaui_direct_power_down,
};
-void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops)
+int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);
+ cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
+ SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
+ "10GBASE-CX4");
+ return 0;
}
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 9ecf8a6dc97..e312d315a42 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -193,22 +193,13 @@ struct mdio_ops {
struct adapter_info {
unsigned char nports; /* # of ports */
unsigned char phy_base_addr; /* MDIO PHY base address */
- unsigned char mdien;
- unsigned char mdiinv;
unsigned int gpio_out; /* GPIO output settings */
- unsigned int gpio_intr; /* GPIO IRQ enable mask */
+ unsigned char gpio_intr[MAX_NPORTS]; /* GPIO PHY IRQ pins */
unsigned long caps; /* adapter capabilities */
const struct mdio_ops *mdio_ops; /* MDIO operations */
const char *desc; /* product description */
};
-struct port_type_info {
- void (*phy_prep)(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *ops);
- unsigned int caps;
- const char *desc;
-};
-
struct mc5_stats {
unsigned long parity_err;
unsigned long active_rgn_full;
@@ -358,6 +349,7 @@ struct qset_params { /* SGE queue set parameters */
unsigned int jumbo_size; /* # of entries in jumbo free list */
unsigned int txq_size[SGE_TXQ_PER_SET]; /* Tx queue sizes */
unsigned int cong_thres; /* FL congestion threshold */
+ unsigned int vector; /* Interrupt (line or vector) number */
};
struct sge_params {
@@ -525,12 +517,25 @@ enum {
MAC_RXFIFO_SIZE = 32768
};
-/* IEEE 802.3ae specified MDIO devices */
+/* IEEE 802.3 specified MDIO devices */
enum {
MDIO_DEV_PMA_PMD = 1,
MDIO_DEV_WIS = 2,
MDIO_DEV_PCS = 3,
- MDIO_DEV_XGXS = 4
+ MDIO_DEV_XGXS = 4,
+ MDIO_DEV_ANEG = 7,
+ MDIO_DEV_VEND1 = 30,
+ MDIO_DEV_VEND2 = 31
+};
+
+/* LASI control and status registers */
+enum {
+ RX_ALARM_CTRL = 0x9000,
+ TX_ALARM_CTRL = 0x9001,
+ LASI_CTRL = 0x9002,
+ RX_ALARM_STAT = 0x9003,
+ TX_ALARM_STAT = 0x9004,
+ LASI_STAT = 0x9005
};
/* PHY loopback direction */
@@ -542,12 +547,23 @@ enum {
/* PHY interrupt types */
enum {
cphy_cause_link_change = 1,
- cphy_cause_fifo_error = 2
+ cphy_cause_fifo_error = 2,
+ cphy_cause_module_change = 4,
+};
+
+/* PHY module types */
+enum {
+ phy_modtype_none,
+ phy_modtype_sr,
+ phy_modtype_lr,
+ phy_modtype_lrm,
+ phy_modtype_twinax,
+ phy_modtype_twinax_long,
+ phy_modtype_unknown
};
/* PHY operations */
struct cphy_ops {
- void (*destroy)(struct cphy *phy);
int (*reset)(struct cphy *phy, int wait);
int (*intr_enable)(struct cphy *phy);
@@ -568,8 +584,12 @@ struct cphy_ops {
/* A PHY instance */
struct cphy {
- int addr; /* PHY address */
+ u8 addr; /* PHY address */
+ u8 modtype; /* PHY module type */
+ short priv; /* scratch pad */
+ unsigned int caps; /* PHY capabilities */
struct adapter *adapter; /* associated adapter */
+ const char *desc; /* PHY description */
unsigned long fifo_errors; /* FIFO over/under-flows */
const struct cphy_ops *ops; /* PHY operations */
int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr,
@@ -594,10 +614,13 @@ static inline int mdio_write(struct cphy *phy, int mmd, int reg,
/* Convenience initializer */
static inline void cphy_init(struct cphy *phy, struct adapter *adapter,
int phy_addr, struct cphy_ops *phy_ops,
- const struct mdio_ops *mdio_ops)
+ const struct mdio_ops *mdio_ops,
+ unsigned int caps, const char *desc)
{
- phy->adapter = adapter;
phy->addr = phy_addr;
+ phy->caps = caps;
+ phy->adapter = adapter;
+ phy->desc = desc;
phy->ops = phy_ops;
if (mdio_ops) {
phy->mdio_read = mdio_ops->read;
@@ -668,7 +691,12 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
unsigned int set);
int t3_phy_reset(struct cphy *phy, int mmd, int wait);
int t3_phy_advertise(struct cphy *phy, unsigned int advert);
+int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert);
int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex);
+int t3_phy_lasi_intr_enable(struct cphy *phy);
+int t3_phy_lasi_intr_disable(struct cphy *phy);
+int t3_phy_lasi_intr_clear(struct cphy *phy);
+int t3_phy_lasi_intr_handler(struct cphy *phy);
void t3_intr_enable(struct adapter *adapter);
void t3_intr_disable(struct adapter *adapter);
@@ -698,6 +726,7 @@ int t3_check_fw_version(struct adapter *adapter, int *must_load);
int t3_init_hw(struct adapter *adapter, u32 fw_params);
void mac_prep(struct cmac *mac, struct adapter *adapter, int index);
void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
+int t3_reset_adapter(struct adapter *adapter);
int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
int reset);
int t3_replay_prep_adapter(struct adapter *adapter);
@@ -774,14 +803,16 @@ int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]);
int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
unsigned int credits);
-void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops);
-void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops);
-void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops);
-void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
- const struct mdio_ops *mdio_ops);
-void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
+ const struct mdio_ops *mdio_ops);
+int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops);
#endif /* __CHELSIO_COMMON_H */
diff --git a/drivers/net/cxgb3/cxgb3_ctl_defs.h b/drivers/net/cxgb3/cxgb3_ctl_defs.h
index 6ad92405d9a..1d8d46eb3c9 100644
--- a/drivers/net/cxgb3/cxgb3_ctl_defs.h
+++ b/drivers/net/cxgb3/cxgb3_ctl_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h
index 45e92164c26..47e53769af5 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/cxgb3/cxgb3_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/cxgb3_ioctl.h b/drivers/net/cxgb3/cxgb3_ioctl.h
index 68200a14065..b19e4376ba7 100644
--- a/drivers/net/cxgb3/cxgb3_ioctl.h
+++ b/drivers/net/cxgb3/cxgb3_ioctl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -92,6 +92,8 @@ struct ch_qset_params {
int32_t polling;
int32_t lro;
int32_t cong_thres;
+ int32_t vector;
+ int32_t qnum;
};
struct ch_pktsched_params {
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 5447f3e60f0..1ace41a13ac 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -208,6 +208,31 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
}
}
+/**
+ * t3_os_phymod_changed - handle PHY module changes
+ * @phy: the PHY reporting the module change
+ * @mod_type: new module type
+ *
+ * This is the OS-dependent handler for PHY module changes. It is
+ * invoked when a PHY module is removed or inserted for any OS-specific
+ * processing.
+ */
+void t3_os_phymod_changed(struct adapter *adap, int port_id)
+{
+ static const char *mod_str[] = {
+ NULL, "SR", "LR", "LRM", "TWINAX", "TWINAX", "unknown"
+ };
+
+ const struct net_device *dev = adap->port[port_id];
+ const struct port_info *pi = netdev_priv(dev);
+
+ if (pi->phy.modtype == phy_modtype_none)
+ printk(KERN_INFO "%s: PHY module unplugged\n", dev->name);
+ else
+ printk(KERN_INFO "%s: %s PHY module inserted\n", dev->name,
+ mod_str[pi->phy.modtype]);
+}
+
static void cxgb_set_rxmode(struct net_device *dev)
{
struct t3_rx_mode rm;
@@ -274,10 +299,10 @@ static void name_msix_vecs(struct adapter *adap)
for (i = 0; i < pi->nqsets; i++, msi_idx++) {
snprintf(adap->msix_info[msi_idx].desc, n,
- "%s (queue %d)", d->name, i);
+ "%s-%d", d->name, pi->first_qset + i);
adap->msix_info[msi_idx].desc[n] = 0;
}
- }
+ }
}
static int request_msix_data_irqs(struct adapter *adap)
@@ -306,6 +331,22 @@ static int request_msix_data_irqs(struct adapter *adap)
return 0;
}
+static void free_irq_resources(struct adapter *adapter)
+{
+ if (adapter->flags & USING_MSIX) {
+ int i, n = 0;
+
+ free_irq(adapter->msix_info[0].vec, adapter);
+ for_each_port(adapter, i)
+ n += adap2pinfo(adapter, i)->nqsets;
+
+ for (i = 0; i < n; ++i)
+ free_irq(adapter->msix_info[i + 1].vec,
+ &adapter->sge.qs[i]);
+ } else
+ free_irq(adapter->pdev->irq, adapter);
+}
+
static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
unsigned long n)
{
@@ -473,12 +514,16 @@ static int setup_sge_qsets(struct adapter *adap)
struct port_info *pi = netdev_priv(dev);
pi->qs = &adap->sge.qs[pi->first_qset];
- for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
+ for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
+ ++j, ++qset_idx) {
+ if (!pi->rx_csum_offload)
+ adap->params.sge.qset[qset_idx].lro = 0;
err = t3_sge_alloc_qset(adap, qset_idx, 1,
(adap->flags & USING_MSIX) ? qset_idx + 1 :
irq_idx,
&adap->params.sge.qset[qset_idx], ntxq, dev);
if (err) {
+ t3_stop_sge_timers(adap);
t3_free_sge_resources(adap);
return err;
}
@@ -739,11 +784,12 @@ static void init_port_mtus(struct adapter *adapter)
t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus);
}
-static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
+static int send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
int hi, int port)
{
struct sk_buff *skb;
struct mngt_pktsched_wr *req;
+ int ret;
skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req));
@@ -754,20 +800,28 @@ static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
req->min = lo;
req->max = hi;
req->binding = port;
- t3_mgmt_tx(adap, skb);
+ ret = t3_mgmt_tx(adap, skb);
+
+ return ret;
}
-static void bind_qsets(struct adapter *adap)
+static int bind_qsets(struct adapter *adap)
{
- int i, j;
+ int i, j, err = 0;
for_each_port(adap, i) {
const struct port_info *pi = adap2pinfo(adap, i);
- for (j = 0; j < pi->nqsets; ++j)
- send_pktsched_cmd(adap, 1, pi->first_qset + j, -1,
- -1, i);
+ for (j = 0; j < pi->nqsets; ++j) {
+ int ret = send_pktsched_cmd(adap, 1,
+ pi->first_qset + j, -1,
+ -1, i);
+ if (ret)
+ err = ret;
+ }
}
+
+ return err;
}
#define FW_FNAME "t3fw-%d.%d.%d.bin"
@@ -891,6 +945,13 @@ static int cxgb_up(struct adapter *adap)
goto out;
}
+ /*
+ * Clear interrupts now to catch errors if t3_init_hw fails.
+ * We clear them again later as initialization may trigger
+ * conditions that can interrupt.
+ */
+ t3_intr_clear(adap);
+
err = t3_init_hw(adap, 0);
if (err)
goto out;
@@ -946,9 +1007,16 @@ static int cxgb_up(struct adapter *adap)
t3_write_reg(adap, A_TP_INT_ENABLE, 0x7fbfffff);
}
- if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
- bind_qsets(adap);
- adap->flags |= QUEUES_BOUND;
+ if (!(adap->flags & QUEUES_BOUND)) {
+ err = bind_qsets(adap);
+ if (err) {
+ CH_ERR(adap, "failed to bind qsets, err %d\n", err);
+ t3_intr_disable(adap);
+ free_irq_resources(adap);
+ goto out;
+ }
+ adap->flags |= QUEUES_BOUND;
+ }
out:
return err;
@@ -967,19 +1035,7 @@ static void cxgb_down(struct adapter *adapter)
t3_intr_disable(adapter);
spin_unlock_irq(&adapter->work_lock);
- if (adapter->flags & USING_MSIX) {
- int i, n = 0;
-
- free_irq(adapter->msix_info[0].vec, adapter);
- for_each_port(adapter, i)
- n += adap2pinfo(adapter, i)->nqsets;
-
- for (i = 0; i < n; ++i)
- free_irq(adapter->msix_info[i + 1].vec,
- &adapter->sge.qs[i]);
- } else
- free_irq(adapter->pdev->irq, adapter);
-
+ free_irq_resources(adapter);
flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */
quiesce_rx(adapter);
}
@@ -1100,9 +1156,9 @@ static int cxgb_close(struct net_device *dev)
netif_carrier_off(dev);
t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
- spin_lock(&adapter->work_lock); /* sync with update task */
+ spin_lock_irq(&adapter->work_lock); /* sync with update task */
clear_bit(pi->port_id, &adapter->open_device_map);
- spin_unlock(&adapter->work_lock);
+ spin_unlock_irq(&adapter->work_lock);
if (!(adapter->open_device_map & PORT_MASK))
cancel_rearming_delayed_workqueue(cxgb3_wq,
@@ -1284,8 +1340,8 @@ static unsigned long collect_sge_port_stats(struct adapter *adapter,
int i;
unsigned long tot = 0;
- for (i = 0; i < p->nqsets; ++i)
- tot += adapter->sge.qs[i + p->first_qset].port_stats[idx];
+ for (i = p->first_qset; i < p->first_qset + p->nqsets; ++i)
+ tot += adapter->sge.qs[i].port_stats[idx];
return tot;
}
@@ -1485,11 +1541,22 @@ static int speed_duplex_to_caps(int speed, int duplex)
static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
+ int cap;
struct port_info *p = netdev_priv(dev);
struct link_config *lc = &p->link_config;
- if (!(lc->supported & SUPPORTED_Autoneg))
- return -EOPNOTSUPP; /* can't change speed/duplex */
+ if (!(lc->supported & SUPPORTED_Autoneg)) {
+ /*
+ * PHY offers a single speed/duplex. See if that's what's
+ * being requested.
+ */
+ if (cmd->autoneg == AUTONEG_DISABLE) {
+ cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
+ if (lc->supported & cap)
+ return 0;
+ }
+ return -EINVAL;
+ }
if (cmd->autoneg == AUTONEG_DISABLE) {
int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
@@ -1568,8 +1635,10 @@ static int set_rx_csum(struct net_device *dev, u32 data)
struct adapter *adap = p->adapter;
int i;
- for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
+ for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
+ adap->params.sge.qset[i].lro = 0;
adap->sge.qs[i].lro_enabled = 0;
+ }
}
return 0;
}
@@ -1775,6 +1844,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
int i;
struct qset_params *q;
struct ch_qset_params t;
+ int q1 = pi->first_qset;
+ int nqsets = pi->nqsets;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -1797,6 +1868,16 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
|| !in_range(t.rspq_size, MIN_RSPQ_ENTRIES,
MAX_RSPQ_ENTRIES))
return -EINVAL;
+
+ if ((adapter->flags & FULL_INIT_DONE) && t.lro > 0)
+ for_each_port(adapter, i) {
+ pi = adap2pinfo(adapter, i);
+ if (t.qset_idx >= pi->first_qset &&
+ t.qset_idx < pi->first_qset + pi->nqsets &&
+ !pi->rx_csum_offload)
+ return -EINVAL;
+ }
+
if ((adapter->flags & FULL_INIT_DONE) &&
(t.rspq_size >= 0 || t.fl_size[0] >= 0 ||
t.fl_size[1] >= 0 || t.txq_size[0] >= 0 ||
@@ -1804,6 +1885,20 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
t.polling >= 0 || t.cong_thres >= 0))
return -EBUSY;
+ /* Allow setting of any available qset when offload enabled */
+ if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
+ q1 = 0;
+ for_each_port(adapter, i) {
+ pi = adap2pinfo(adapter, i);
+ nqsets += pi->first_qset + pi->nqsets;
+ }
+ }
+
+ if (t.qset_idx < q1)
+ return -EINVAL;
+ if (t.qset_idx > q1 + nqsets - 1)
+ return -EINVAL;
+
q = &adapter->params.sge.qset[t.qset_idx];
if (t.rspq_size >= 0)
@@ -1853,13 +1948,26 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
case CHELSIO_GET_QSET_PARAMS:{
struct qset_params *q;
struct ch_qset_params t;
+ int q1 = pi->first_qset;
+ int nqsets = pi->nqsets;
+ int i;
if (copy_from_user(&t, useraddr, sizeof(t)))
return -EFAULT;
- if (t.qset_idx >= SGE_QSETS)
+
+ /* Display qsets for all ports when offload enabled */
+ if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
+ q1 = 0;
+ for_each_port(adapter, i) {
+ pi = adap2pinfo(adapter, i);
+ nqsets = pi->first_qset + pi->nqsets;
+ }
+ }
+
+ if (t.qset_idx >= nqsets)
return -EINVAL;
- q = &adapter->params.sge.qset[t.qset_idx];
+ q = &adapter->params.sge.qset[q1 + t.qset_idx];
t.rspq_size = q->rspq_size;
t.txq_size[0] = q->txq_size[0];
t.txq_size[1] = q->txq_size[1];
@@ -1870,6 +1978,12 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
t.lro = q->lro;
t.intr_lat = q->coalesce_usecs;
t.cong_thres = q->cong_thres;
+ t.qnum = q1;
+
+ if (adapter->flags & USING_MSIX)
+ t.vector = adapter->msix_info[q1 + t.qset_idx + 1].vec;
+ else
+ t.vector = adapter->pdev->irq;
if (copy_to_user(useraddr, &t, sizeof(t)))
return -EFAULT;
@@ -2117,7 +2231,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
mmd = data->phy_id >> 8;
if (!mmd)
mmd = MDIO_DEV_PCS;
- else if (mmd > MDIO_DEV_XGXS)
+ else if (mmd > MDIO_DEV_VEND2)
return -EINVAL;
ret =
@@ -2143,7 +2257,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
mmd = data->phy_id >> 8;
if (!mmd)
mmd = MDIO_DEV_PCS;
- else if (mmd > MDIO_DEV_XGXS)
+ else if (mmd > MDIO_DEV_VEND2)
return -EINVAL;
ret =
@@ -2215,8 +2329,8 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
{
int i;
- for (i = 0; i < p->nqsets; i++) {
- struct sge_rspq *q = &adap->sge.qs[i + p->first_qset].rspq;
+ for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
+ struct sge_rspq *q = &adap->sge.qs[i].rspq;
spin_lock_irq(&q->lock);
spin_unlock_irq(&q->lock);
@@ -2290,7 +2404,7 @@ static void check_link_status(struct adapter *adapter)
struct net_device *dev = adapter->port[i];
struct port_info *p = netdev_priv(dev);
- if (!(p->port_type->caps & SUPPORTED_IRQ) && netif_running(dev))
+ if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev))
t3_link_changed(adapter, i);
}
}
@@ -2355,10 +2469,10 @@ static void t3_adap_check_task(struct work_struct *work)
check_t3b2_mac(adapter);
/* Schedule the next check update if any port is active. */
- spin_lock(&adapter->work_lock);
+ spin_lock_irq(&adapter->work_lock);
if (adapter->open_device_map & PORT_MASK)
schedule_chk_task(adapter);
- spin_unlock(&adapter->work_lock);
+ spin_unlock_irq(&adapter->work_lock);
}
/*
@@ -2403,6 +2517,96 @@ void t3_os_ext_intr_handler(struct adapter *adapter)
spin_unlock(&adapter->work_lock);
}
+static int t3_adapter_error(struct adapter *adapter, int reset)
+{
+ int i, ret = 0;
+
+ /* Stop all ports */
+ for_each_port(adapter, i) {
+ struct net_device *netdev = adapter->port[i];
+
+ if (netif_running(netdev))
+ cxgb_close(netdev);
+ }
+
+ if (is_offload(adapter) &&
+ test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
+ offload_close(&adapter->tdev);
+
+ /* Stop SGE timers */
+ t3_stop_sge_timers(adapter);
+
+ adapter->flags &= ~FULL_INIT_DONE;
+
+ if (reset)
+ ret = t3_reset_adapter(adapter);
+
+ pci_disable_device(adapter->pdev);
+
+ return ret;
+}
+
+static int t3_reenable_adapter(struct adapter *adapter)
+{
+ if (pci_enable_device(adapter->pdev)) {
+ dev_err(&adapter->pdev->dev,
+ "Cannot re-enable PCI device after reset.\n");
+ goto err;
+ }
+ pci_set_master(adapter->pdev);
+ pci_restore_state(adapter->pdev);
+
+ /* Free sge resources */
+ t3_free_sge_resources(adapter);
+
+ if (t3_replay_prep_adapter(adapter))
+ goto err;
+
+ return 0;
+err:
+ return -1;
+}
+
+static void t3_resume_ports(struct adapter *adapter)
+{
+ int i;
+
+ /* Restart the ports */
+ for_each_port(adapter, i) {
+ struct net_device *netdev = adapter->port[i];
+
+ if (netif_running(netdev)) {
+ if (cxgb_open(netdev)) {
+ dev_err(&adapter->pdev->dev,
+ "can't bring device back up"
+ " after reset\n");
+ continue;
+ }
+ }
+ }
+}
+
+/*
+ * processes a fatal error.
+ * Bring the ports down, reset the chip, bring the ports back up.
+ */
+static void fatal_error_task(struct work_struct *work)
+{
+ struct adapter *adapter = container_of(work, struct adapter,
+ fatal_error_handler_task);
+ int err = 0;
+
+ rtnl_lock();
+ err = t3_adapter_error(adapter, 1);
+ if (!err)
+ err = t3_reenable_adapter(adapter);
+ if (!err)
+ t3_resume_ports(adapter);
+
+ CH_ALERT(adapter, "adapter reset %s\n", err ? "failed" : "succeeded");
+ rtnl_unlock();
+}
+
void t3_fatal_err(struct adapter *adapter)
{
unsigned int fw_status[4];
@@ -2413,7 +2617,11 @@ void t3_fatal_err(struct adapter *adapter)
t3_write_reg(adapter, A_XGM_RX_CTRL, 0);
t3_write_reg(adapter, XGM_REG(A_XGM_TX_CTRL, 1), 0);
t3_write_reg(adapter, XGM_REG(A_XGM_RX_CTRL, 1), 0);
+
+ spin_lock(&adapter->work_lock);
t3_intr_disable(adapter);
+ queue_work(cxgb3_wq, &adapter->fatal_error_handler_task);
+ spin_unlock(&adapter->work_lock);
}
CH_ALERT(adapter, "encountered fatal error, operation suspended\n");
if (!t3_cim_ctl_blk_read(adapter, 0xa0, 4, fw_status))
@@ -2435,23 +2643,9 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct adapter *adapter = pci_get_drvdata(pdev);
- int i;
-
- /* Stop all ports */
- for_each_port(adapter, i) {
- struct net_device *netdev = adapter->port[i];
-
- if (netif_running(netdev))
- cxgb_close(netdev);
- }
-
- if (is_offload(adapter) &&
- test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
- offload_close(&adapter->tdev);
-
- adapter->flags &= ~FULL_INIT_DONE;
+ int ret;
- pci_disable_device(pdev);
+ ret = t3_adapter_error(adapter, 0);
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
@@ -2467,22 +2661,9 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
{
struct adapter *adapter = pci_get_drvdata(pdev);
- if (pci_enable_device(pdev)) {
- dev_err(&pdev->dev,
- "Cannot re-enable PCI device after reset.\n");
- goto err;
- }
- pci_set_master(pdev);
- pci_restore_state(pdev);
-
- /* Free sge resources */
- t3_free_sge_resources(adapter);
-
- if (t3_replay_prep_adapter(adapter))
- goto err;
+ if (!t3_reenable_adapter(adapter))
+ return PCI_ERS_RESULT_RECOVERED;
- return PCI_ERS_RESULT_RECOVERED;
-err:
return PCI_ERS_RESULT_DISCONNECT;
}
@@ -2496,22 +2677,8 @@ err:
static void t3_io_resume(struct pci_dev *pdev)
{
struct adapter *adapter = pci_get_drvdata(pdev);
- int i;
- /* Restart the ports */
- for_each_port(adapter, i) {
- struct net_device *netdev = adapter->port[i];
-
- if (netif_running(netdev)) {
- if (cxgb_open(netdev)) {
- dev_err(&pdev->dev,
- "can't bring device back up"
- " after reset\n");
- continue;
- }
- netif_device_attach(netdev);
- }
- }
+ t3_resume_ports(adapter);
}
static struct pci_error_handlers t3_err_handler = {
@@ -2520,6 +2687,42 @@ static struct pci_error_handlers t3_err_handler = {
.resume = t3_io_resume,
};
+/*
+ * Set the number of qsets based on the number of CPUs and the number of ports,
+ * not to exceed the number of available qsets, assuming there are enough qsets
+ * per port in HW.
+ */
+static void set_nqsets(struct adapter *adap)
+{
+ int i, j = 0;
+ int num_cpus = num_online_cpus();
+ int hwports = adap->params.nports;
+ int nqsets = SGE_QSETS;
+
+ if (adap->params.rev > 0) {
+ if (hwports == 2 &&
+ (hwports * nqsets > SGE_QSETS ||
+ num_cpus >= nqsets / hwports))
+ nqsets /= hwports;
+ if (nqsets > num_cpus)
+ nqsets = num_cpus;
+ if (nqsets < 1 || hwports == 4)
+ nqsets = 1;
+ } else
+ nqsets = 1;
+
+ for_each_port(adap, i) {
+ struct port_info *pi = adap2pinfo(adap, i);
+
+ pi->first_qset = j;
+ pi->nqsets = nqsets;
+ j = pi->first_qset + nqsets;
+
+ dev_info(&adap->pdev->dev,
+ "Port %d using %d queue sets.\n", i, nqsets);
+ }
+}
+
static int __devinit cxgb_enable_msix(struct adapter *adap)
{
struct msix_entry entries[SGE_QSETS + 1];
@@ -2564,7 +2767,7 @@ static void __devinit print_port_info(struct adapter *adap,
if (!test_bit(i, &adap->registered_device_map))
continue;
printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n",
- dev->name, ai->desc, pi->port_type->desc,
+ dev->name, ai->desc, pi->phy.desc,
is_offload(adap) ? "R" : "", adap->params.rev, buf,
(adap->flags & USING_MSIX) ? " MSI-X" :
(adap->flags & USING_MSI) ? " MSI" : "");
@@ -2660,6 +2863,7 @@ static int __devinit init_one(struct pci_dev *pdev,
INIT_LIST_HEAD(&adapter->adapter_list);
INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
+ INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
for (i = 0; i < ai->nports; ++i) {
@@ -2677,9 +2881,6 @@ static int __devinit init_one(struct pci_dev *pdev,
pi = netdev_priv(netdev);
pi->adapter = adapter;
pi->rx_csum_offload = 1;
- pi->nqsets = 1;
- pi->first_qset = i;
- pi->activity = 0;
pi->port_id = i;
netif_carrier_off(netdev);
netdev->irq = pdev->irq;
@@ -2756,6 +2957,8 @@ static int __devinit init_one(struct pci_dev *pdev,
else if (msi > 0 && pci_enable_msi(pdev) == 0)
adapter->flags |= USING_MSI;
+ set_nqsets(adapter);
+
err = sysfs_create_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
@@ -2801,6 +3004,7 @@ static void __devexit remove_one(struct pci_dev *pdev)
if (test_bit(i, &adapter->registered_device_map))
unregister_netdev(adapter->port[i]);
+ t3_stop_sge_timers(adapter);
t3_free_sge_resources(adapter);
cxgb_disable_msi(adapter);
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c5b3de1bb45..265aa8a15af 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -1018,7 +1018,7 @@ static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e)
skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
if (!skb) {
- printk(KERN_ERR "%s: cannot allocate skb!\n", __FUNCTION__);
+ printk(KERN_ERR "%s: cannot allocate skb!\n", __func__);
return;
}
skb->priority = CPL_PRIORITY_CONTROL;
@@ -1049,14 +1049,14 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
return;
if (!is_offloading(newdev)) {
printk(KERN_WARNING "%s: Redirect to non-offload "
- "device ignored.\n", __FUNCTION__);
+ "device ignored.\n", __func__);
return;
}
tdev = dev2t3cdev(olddev);
BUG_ON(!tdev);
if (tdev != dev2t3cdev(newdev)) {
printk(KERN_WARNING "%s: Redirect to different "
- "offload device ignored.\n", __FUNCTION__);
+ "offload device ignored.\n", __func__);
return;
}
@@ -1064,7 +1064,7 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
e = t3_l2t_get(tdev, new->neighbour, newdev);
if (!e) {
printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
- __FUNCTION__);
+ __func__);
return;
}
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h
index 7a379138b5a..d514e5019df 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/cxgb3/cxgb3_offload.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/firmware_exports.h b/drivers/net/cxgb3/firmware_exports.h
index b75ddd8777f..0d9b0e6dccf 100644
--- a/drivers/net/cxgb3/firmware_exports.h
+++ b/drivers/net/cxgb3/firmware_exports.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
index 825e510bd9e..4407ac9bb55 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/cxgb3/l2t.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -86,6 +86,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb,
struct l2t_entry *e)
{
struct cpl_l2t_write_req *req;
+ struct sk_buff *tmp;
if (!skb) {
skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
@@ -103,13 +104,11 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb,
memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
skb->priority = CPL_PRIORITY_CONTROL;
cxgb3_ofld_send(dev, skb);
- while (e->arpq_head) {
- skb = e->arpq_head;
- e->arpq_head = skb->next;
- skb->next = NULL;
+
+ skb_queue_walk_safe(&e->arpq, skb, tmp) {
+ __skb_unlink(skb, &e->arpq);
cxgb3_ofld_send(dev, skb);
}
- e->arpq_tail = NULL;
e->state = L2T_STATE_VALID;
return 0;
@@ -121,12 +120,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb,
*/
static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb)
{
- skb->next = NULL;
- if (e->arpq_head)
- e->arpq_tail->next = skb;
- else
- e->arpq_head = skb;
- e->arpq_tail = skb;
+ __skb_queue_tail(&e->arpq, skb);
}
int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
@@ -167,7 +161,7 @@ again:
break;
spin_lock_bh(&e->lock);
- if (e->arpq_head)
+ if (!skb_queue_empty(&e->arpq))
setup_l2e_send_pending(dev, skb, e);
else /* we lost the race */
__kfree_skb(skb);
@@ -357,14 +351,14 @@ EXPORT_SYMBOL(t3_l2t_get);
* XXX: maybe we should abandon the latter behavior and just require a failure
* handler.
*/
-static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq)
+static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff_head *arpq)
{
- while (arpq) {
- struct sk_buff *skb = arpq;
+ struct sk_buff *skb, *tmp;
+
+ skb_queue_walk_safe(arpq, skb, tmp) {
struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
- arpq = skb->next;
- skb->next = NULL;
+ __skb_unlink(skb, arpq);
if (cb->arp_failure_handler)
cb->arp_failure_handler(dev, skb);
else
@@ -378,8 +372,8 @@ static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq)
*/
void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh)
{
+ struct sk_buff_head arpq;
struct l2t_entry *e;
- struct sk_buff *arpq = NULL;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) neigh->primary_key;
int ifidx = neigh->dev->ifindex;
@@ -395,6 +389,8 @@ void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh)
return;
found:
+ __skb_queue_head_init(&arpq);
+
read_unlock(&d->lock);
if (atomic_read(&e->refcnt)) {
if (neigh != e->neigh)
@@ -402,8 +398,7 @@ found:
if (e->state == L2T_STATE_RESOLVING) {
if (neigh->nud_state & NUD_FAILED) {
- arpq = e->arpq_head;
- e->arpq_head = e->arpq_tail = NULL;
+ skb_queue_splice_init(&e->arpq, &arpq);
} else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
setup_l2e_send_pending(dev, NULL, e);
} else {
@@ -415,8 +410,8 @@ found:
}
spin_unlock_bh(&e->lock);
- if (arpq)
- handle_failed_resolution(dev, arpq);
+ if (!skb_queue_empty(&arpq))
+ handle_failed_resolution(dev, &arpq);
}
struct l2t_data *t3_init_l2t(unsigned int l2t_capacity)
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h
index d79001336cf..fd3eb07e3f4 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/cxgb3/l2t.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -64,8 +64,7 @@ struct l2t_entry {
struct neighbour *neigh; /* associated neighbour */
struct l2t_entry *first; /* start of hash chain */
struct l2t_entry *next; /* next l2t_entry on chain */
- struct sk_buff *arpq_head; /* queue of packets awaiting resolution */
- struct sk_buff *arpq_tail;
+ struct sk_buff_head arpq; /* queue of packets awaiting resolution */
spinlock_t lock;
atomic_t refcnt; /* entry reference count */
u8 dmac[6]; /* neighbour's MAC address */
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
index 4c4d6e877ea..3b5517b8fbd 100644
--- a/drivers/net/cxgb3/mc5.c
+++ b/drivers/net/cxgb3/mc5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 4bda27c551c..a035d5c2444 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -573,6 +573,10 @@
#define V_GPIO10(x) ((x) << S_GPIO10)
#define F_GPIO10 V_GPIO10(1U)
+#define S_GPIO9 9
+#define V_GPIO9(x) ((x) << S_GPIO9)
+#define F_GPIO9 V_GPIO9(1U)
+
#define S_GPIO7 7
#define V_GPIO7(x) ((x) << S_GPIO7)
#define F_GPIO7 V_GPIO7(1U)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 1b0861d73ab..c6480be0bc1 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -351,7 +351,8 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
if (q->use_pages) {
- put_page(d->pg_chunk.page);
+ if (d->pg_chunk.page)
+ put_page(d->pg_chunk.page);
d->pg_chunk.page = NULL;
} else {
kfree_skb(d->skb);
@@ -583,7 +584,7 @@ static void t3_reset_qset(struct sge_qset *q)
memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET);
memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
q->txq_stopped = 0;
- memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer));
+ q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
kfree(q->lro_frag_tbl);
q->lro_nfrags = q->lro_frag_len = 0;
}
@@ -603,9 +604,6 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
int i;
struct pci_dev *pdev = adapter->pdev;
- if (q->tx_reclaim_timer.function)
- del_timer_sync(&q->tx_reclaim_timer);
-
for (i = 0; i < SGE_RXQ_PER_SET; ++i)
if (q->fl[i].desc) {
spin_lock_irq(&adapter->sge.reg_lock);
@@ -1704,16 +1702,15 @@ int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb)
*/
static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb)
{
- skb->next = skb->prev = NULL;
- if (q->rx_tail)
- q->rx_tail->next = skb;
- else {
+ int was_empty = skb_queue_empty(&q->rx_queue);
+
+ __skb_queue_tail(&q->rx_queue, skb);
+
+ if (was_empty) {
struct sge_qset *qs = rspq_to_qset(q);
napi_schedule(&qs->napi);
- q->rx_head = skb;
}
- q->rx_tail = skb;
}
/**
@@ -1754,26 +1751,29 @@ static int ofld_poll(struct napi_struct *napi, int budget)
int work_done = 0;
while (work_done < budget) {
- struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE];
+ struct sk_buff *skb, *tmp, *skbs[RX_BUNDLE_SIZE];
+ struct sk_buff_head queue;
int ngathered;
spin_lock_irq(&q->lock);
- head = q->rx_head;
- if (!head) {
+ __skb_queue_head_init(&queue);
+ skb_queue_splice_init(&q->rx_queue, &queue);
+ if (skb_queue_empty(&queue)) {
napi_complete(napi);
spin_unlock_irq(&q->lock);
return work_done;
}
-
- tail = q->rx_tail;
- q->rx_head = q->rx_tail = NULL;
spin_unlock_irq(&q->lock);
- for (ngathered = 0; work_done < budget && head; work_done++) {
- prefetch(head->data);
- skbs[ngathered] = head;
- head = head->next;
- skbs[ngathered]->next = NULL;
+ ngathered = 0;
+ skb_queue_walk_safe(&queue, skb, tmp) {
+ if (work_done >= budget)
+ break;
+ work_done++;
+
+ __skb_unlink(skb, &queue);
+ prefetch(skb->data);
+ skbs[ngathered] = skb;
if (++ngathered == RX_BUNDLE_SIZE) {
q->offload_bundles++;
adapter->tdev.recv(&adapter->tdev, skbs,
@@ -1781,12 +1781,10 @@ static int ofld_poll(struct napi_struct *napi, int budget)
ngathered = 0;
}
}
- if (head) { /* splice remaining packets back onto Rx queue */
+ if (!skb_queue_empty(&queue)) {
+ /* splice remaining packets back onto Rx queue */
spin_lock_irq(&q->lock);
- tail->next = q->rx_head;
- if (!q->rx_head)
- q->rx_tail = tail;
- q->rx_head = head;
+ skb_queue_splice(&queue, &q->rx_queue);
spin_unlock_irq(&q->lock);
}
deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered);
@@ -1937,38 +1935,6 @@ static inline int lro_frame_ok(const struct cpl_rx_pkt *p)
eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2);
}
-#define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\
- TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\
- TCP_FLAG_SYN | TCP_FLAG_FIN)
-#define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)
-
-/**
- * lro_segment_ok - check if a TCP segment is eligible for LRO
- * @tcph: the TCP header of the packet
- *
- * Returns true if a TCP packet is eligible for LRO. This requires that
- * the packet have only the ACK flag set and no TCP options besides
- * time stamps.
- */
-static inline int lro_segment_ok(const struct tcphdr *tcph)
-{
- int optlen;
-
- if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK))
- return 0;
-
- optlen = (tcph->doff << 2) - sizeof(*tcph);
- if (optlen) {
- const u32 *opt = (const u32 *)(tcph + 1);
-
- if (optlen != TCPOLEN_TSTAMP_ALIGNED ||
- *opt != htonl(TSTAMP_WORD) || !opt[2])
- return 0;
- }
- return 1;
-}
-
static int t3_get_lro_header(void **eh, void **iph, void **tcph,
u64 *hdr_flags, void *priv)
{
@@ -1981,9 +1947,6 @@ static int t3_get_lro_header(void **eh, void **iph, void **tcph,
*iph = (struct iphdr *)((struct ethhdr *)*eh + 1);
*tcph = (struct tcphdr *)((struct iphdr *)*iph + 1);
- if (!lro_segment_ok(*tcph))
- return -1;
-
*hdr_flags = LRO_IPV4 | LRO_TCP;
return 0;
}
@@ -2878,9 +2841,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
struct net_lro_mgr *lro_mgr = &q->lro_mgr;
init_qset_cntxt(q, id);
- init_timer(&q->tx_reclaim_timer);
- q->tx_reclaim_timer.data = (unsigned long)q;
- q->tx_reclaim_timer.function = sge_timer_cb;
+ setup_timer(&q->tx_reclaim_timer, sge_timer_cb, (unsigned long)q);
q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size,
sizeof(struct rx_desc),
@@ -2934,6 +2895,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->rspq.gen = 1;
q->rspq.size = p->rspq_size;
spin_lock_init(&q->rspq.lock);
+ skb_queue_head_init(&q->rspq.rx_queue);
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
@@ -3043,6 +3005,24 @@ err:
}
/**
+ * t3_stop_sge_timers - stop SGE timer call backs
+ * @adap: the adapter
+ *
+ * Stops each SGE queue set's timer call back
+ */
+void t3_stop_sge_timers(struct adapter *adap)
+{
+ int i;
+
+ for (i = 0; i < SGE_QSETS; ++i) {
+ struct sge_qset *q = &adap->sge.qs[i];
+
+ if (q->tx_reclaim_timer.function)
+ del_timer_sync(&q->tx_reclaim_timer);
+ }
+}
+
+/**
* t3_free_sge_resources - free SGE resources
* @adap: the adapter
*
diff --git a/drivers/net/cxgb3/t3_cpl.h b/drivers/net/cxgb3/t3_cpl.h
index 917970ed24a..852c399a8b0 100644
--- a/drivers/net/cxgb3/t3_cpl.h
+++ b/drivers/net/cxgb3/t3_cpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 04c0e90119a..968f64be374 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -194,21 +194,18 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
static void mi1_init(struct adapter *adap, const struct adapter_info *ai)
{
u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1;
- u32 val = F_PREEN | V_MDIINV(ai->mdiinv) | V_MDIEN(ai->mdien) |
- V_CLKDIV(clkdiv);
+ u32 val = F_PREEN | V_CLKDIV(clkdiv);
- if (!(ai->caps & SUPPORTED_10000baseT_Full))
- val |= V_ST(1);
t3_write_reg(adap, A_MI1_CFG, val);
}
-#define MDIO_ATTEMPTS 10
+#define MDIO_ATTEMPTS 20
/*
- * MI1 read/write operations for direct-addressed PHYs.
+ * MI1 read/write operations for clause 22 PHYs.
*/
-static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr,
- int reg_addr, unsigned int *valp)
+static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *valp)
{
int ret;
u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
@@ -217,16 +214,17 @@ static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr,
return -EINVAL;
mutex_lock(&adapter->mdio_lock);
+ t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
if (!ret)
*valp = t3_read_reg(adapter, A_MI1_DATA);
mutex_unlock(&adapter->mdio_lock);
return ret;
}
-static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
+static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
int reg_addr, unsigned int val)
{
int ret;
@@ -236,37 +234,51 @@ static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
return -EINVAL;
mutex_lock(&adapter->mdio_lock);
+ t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_DATA, val);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
mutex_unlock(&adapter->mdio_lock);
return ret;
}
static const struct mdio_ops mi1_mdio_ops = {
- mi1_read,
- mi1_write
+ t3_mi1_read,
+ t3_mi1_write
};
/*
+ * Performs the address cycle for clause 45 PHYs.
+ * Must be called with the MDIO_LOCK held.
+ */
+static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr,
+ int reg_addr)
+{
+ u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr);
+
+ t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0);
+ t3_write_reg(adapter, A_MI1_ADDR, addr);
+ t3_write_reg(adapter, A_MI1_DATA, reg_addr);
+ t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
+ return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
+ MDIO_ATTEMPTS, 10);
+}
+
+/*
* MI1 read/write operations for indirect-addressed PHYs.
*/
static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr,
int reg_addr, unsigned int *valp)
{
int ret;
- u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr);
mutex_lock(&adapter->mdio_lock);
- t3_write_reg(adapter, A_MI1_ADDR, addr);
- t3_write_reg(adapter, A_MI1_DATA, reg_addr);
- t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
if (!ret) {
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3));
ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
- MDIO_ATTEMPTS, 20);
+ MDIO_ATTEMPTS, 10);
if (!ret)
*valp = t3_read_reg(adapter, A_MI1_DATA);
}
@@ -278,18 +290,14 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr,
int reg_addr, unsigned int val)
{
int ret;
- u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr);
mutex_lock(&adapter->mdio_lock);
- t3_write_reg(adapter, A_MI1_ADDR, addr);
- t3_write_reg(adapter, A_MI1_DATA, reg_addr);
- t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
if (!ret) {
t3_write_reg(adapter, A_MI1_DATA, val);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
- MDIO_ATTEMPTS, 20);
+ MDIO_ATTEMPTS, 10);
}
mutex_unlock(&adapter->mdio_lock);
return ret;
@@ -400,6 +408,29 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert)
}
/**
+ * t3_phy_advertise_fiber - set fiber PHY advertisement register
+ * @phy: the PHY to operate on
+ * @advert: bitmap of capabilities the PHY should advertise
+ *
+ * Sets a fiber PHY's advertisement register to advertise the
+ * requested capabilities.
+ */
+int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert)
+{
+ unsigned int val = 0;
+
+ if (advert & ADVERTISED_1000baseT_Half)
+ val |= ADVERTISE_1000XHALF;
+ if (advert & ADVERTISED_1000baseT_Full)
+ val |= ADVERTISE_1000XFULL;
+ if (advert & ADVERTISED_Pause)
+ val |= ADVERTISE_1000XPAUSE;
+ if (advert & ADVERTISED_Asym_Pause)
+ val |= ADVERTISE_1000XPSE_ASYM;
+ return mdio_write(phy, 0, MII_ADVERTISE, val);
+}
+
+/**
* t3_set_phy_speed_duplex - force PHY speed and duplex
* @phy: the PHY to operate on
* @speed: requested PHY speed
@@ -434,27 +465,52 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
return mdio_write(phy, 0, MII_BMCR, ctl);
}
+int t3_phy_lasi_intr_enable(struct cphy *phy)
+{
+ return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
+}
+
+int t3_phy_lasi_intr_disable(struct cphy *phy)
+{
+ return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
+}
+
+int t3_phy_lasi_intr_clear(struct cphy *phy)
+{
+ u32 val;
+
+ return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
+}
+
+int t3_phy_lasi_intr_handler(struct cphy *phy)
+{
+ unsigned int status;
+ int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
+
+ if (err)
+ return err;
+ return (status & 1) ? cphy_cause_link_change : 0;
+}
+
static const struct adapter_info t3_adap_info[] = {
- {2, 0, 0, 0,
+ {2, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
- F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
- 0,
+ F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
&mi1_mdio_ops, "Chelsio PE9000"},
- {2, 0, 0, 0,
+ {2, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
- F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
- 0,
+ F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
&mi1_mdio_ops, "Chelsio T302"},
- {1, 0, 0, 0,
+ {1, 0,
F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
- 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
+ { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T310"},
- {2, 0, 0, 0,
+ {2, 0,
F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
- F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
- SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
+ F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
+ { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T320"},
};
@@ -467,29 +523,23 @@ const struct adapter_info *t3_get_adapter_info(unsigned int id)
return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL;
}
-#define CAPS_1G (SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | \
- SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII)
-#define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI)
+struct port_type_info {
+ int (*phy_prep)(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *ops);
+};
static const struct port_type_info port_types[] = {
- {NULL},
- {t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE,
- "10GBASE-XR"},
- {t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ,
- "10/100/1000BASE-T"},
- {NULL, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ,
- "10/100/1000BASE-T"},
- {t3_xaui_direct_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"},
- {NULL, CAPS_10G, "10GBASE-KX4"},
- {t3_qt2045_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"},
- {t3_ael1006_phy_prep, CAPS_10G | SUPPORTED_FIBRE,
- "10GBASE-SR"},
- {NULL, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"},
+ { NULL },
+ { t3_ael1002_phy_prep },
+ { t3_vsc8211_phy_prep },
+ { NULL},
+ { t3_xaui_direct_phy_prep },
+ { t3_ael2005_phy_prep },
+ { t3_qt2045_phy_prep },
+ { t3_ael1006_phy_prep },
+ { NULL },
};
-#undef CAPS_1G
-#undef CAPS_10G
-
#define VPD_ENTRY(name, len) \
u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]
@@ -1132,6 +1182,15 @@ void t3_link_changed(struct adapter *adapter, int port_id)
phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
+ if (lc->requested_fc & PAUSE_AUTONEG)
+ fc &= lc->requested_fc;
+ else
+ fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+
+ if (link_ok == lc->link_ok && speed == lc->speed &&
+ duplex == lc->duplex && fc == lc->fc)
+ return; /* nothing changed */
+
if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
uses_xaui(adapter)) {
if (link_ok)
@@ -1142,10 +1201,6 @@ void t3_link_changed(struct adapter *adapter, int port_id)
lc->link_ok = link_ok;
lc->speed = speed < 0 ? SPEED_INVALID : speed;
lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
- if (lc->requested_fc & PAUSE_AUTONEG)
- fc &= lc->requested_fc;
- else
- fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
/* Set MAC speed, duplex, and flow control to match PHY. */
@@ -1191,7 +1246,6 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
fc);
/* Also disables autoneg */
phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
- phy->ops->reset(phy, 0);
} else
phy->ops->autoneg_enable(phy);
} else {
@@ -1221,7 +1275,7 @@ struct intr_info {
unsigned int mask; /* bits to check in interrupt status */
const char *msg; /* message to print or NULL */
short stat_idx; /* stat counter to increment or -1 */
- unsigned short fatal:1; /* whether the condition reported is fatal */
+ unsigned short fatal; /* whether the condition reported is fatal */
};
/**
@@ -1682,25 +1736,23 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx)
*/
int t3_phy_intr_handler(struct adapter *adapter)
{
- u32 mask, gpi = adapter_info(adapter)->gpio_intr;
u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
for_each_port(adapter, i) {
struct port_info *p = adap2pinfo(adapter, i);
- mask = gpi - (gpi & (gpi - 1));
- gpi -= mask;
-
- if (!(p->port_type->caps & SUPPORTED_IRQ))
+ if (!(p->phy.caps & SUPPORTED_IRQ))
continue;
- if (cause & mask) {
+ if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) {
int phy_cause = p->phy.ops->intr_handler(&p->phy);
if (phy_cause & cphy_cause_link_change)
t3_link_changed(adapter, i);
if (phy_cause & cphy_cause_fifo_error)
p->phy.fifo_errors++;
+ if (phy_cause & cphy_cause_module_change)
+ t3_os_phymod_changed(adapter, i);
}
}
@@ -1763,6 +1815,17 @@ int t3_slow_intr_handler(struct adapter *adapter)
return 1;
}
+static unsigned int calc_gpio_intr(struct adapter *adap)
+{
+ unsigned int i, gpi_intr = 0;
+
+ for_each_port(adap, i)
+ if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) &&
+ adapter_info(adap)->gpio_intr[i])
+ gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i];
+ return gpi_intr;
+}
+
/**
* t3_intr_enable - enable interrupts
* @adapter: the adapter whose interrupts should be enabled
@@ -1805,10 +1868,8 @@ void t3_intr_enable(struct adapter *adapter)
t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK);
}
- t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW,
- adapter_info(adapter)->gpio_intr);
- t3_write_reg(adapter, A_T3DBG_INT_ENABLE,
- adapter_info(adapter)->gpio_intr);
+ t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter));
+
if (is_pcie(adapter))
t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK);
else
@@ -3329,6 +3390,8 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
init_hw_for_avail_ports(adapter, adapter->params.nports);
t3_sge_init(adapter, &adapter->params.sge);
+ t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter));
+
t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params);
t3_write_reg(adapter, A_CIM_BOOT_CFG,
V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2));
@@ -3488,7 +3551,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
* Older PCIe cards lose their config space during reset, PCI-X
* ones don't.
*/
-static int t3_reset_adapter(struct adapter *adapter)
+int t3_reset_adapter(struct adapter *adapter)
{
int i, save_and_restore_pcie =
adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
@@ -3556,7 +3619,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
int reset)
{
int ret;
- unsigned int i, j = 0;
+ unsigned int i, j = -1;
get_pci_mode(adapter, &adapter->params.pci);
@@ -3620,16 +3683,18 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
for_each_port(adapter, i) {
u8 hw_addr[6];
+ const struct port_type_info *pti;
struct port_info *p = adap2pinfo(adapter, i);
- while (!adapter->params.vpd.port_type[j])
- ++j;
+ while (!adapter->params.vpd.port_type[++j])
+ ;
- p->port_type = &port_types[adapter->params.vpd.port_type[j]];
- p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
- ai->mdio_ops);
+ pti = &port_types[adapter->params.vpd.port_type[j]];
+ ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
+ ai->mdio_ops);
+ if (ret)
+ return ret;
mac_prep(&p->mac, adapter, j);
- ++j;
/*
* The VPD EEPROM stores the base Ethernet address for the
@@ -3643,9 +3708,9 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
ETH_ALEN);
memcpy(adapter->port[i]->perm_addr, hw_addr,
ETH_ALEN);
- init_link_config(&p->link_config, p->port_type->caps);
+ init_link_config(&p->link_config, p->phy.caps);
p->phy.ops->power_down(&p->phy, 1);
- if (!(p->port_type->caps & SUPPORTED_IRQ))
+ if (!(p->phy.caps & SUPPORTED_IRQ))
adapter->params.linkpoll_period = 10;
}
@@ -3661,7 +3726,7 @@ void t3_led_ready(struct adapter *adapter)
int t3_replay_prep_adapter(struct adapter *adapter)
{
const struct adapter_info *ai = adapter->params.info;
- unsigned int i, j = 0;
+ unsigned int i, j = -1;
int ret;
early_hw_init(adapter, ai);
@@ -3670,15 +3735,17 @@ int t3_replay_prep_adapter(struct adapter *adapter)
return ret;
for_each_port(adapter, i) {
+ const struct port_type_info *pti;
struct port_info *p = adap2pinfo(adapter, i);
- while (!adapter->params.vpd.port_type[j])
- ++j;
- p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
- ai->mdio_ops);
+ while (!adapter->params.vpd.port_type[++j])
+ ;
+ pti = &port_types[adapter->params.vpd.port_type[j]];
+ ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL);
+ if (ret)
+ return ret;
p->phy.ops->power_down(&p->phy, 1);
- ++j;
}
return 0;
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index 0a21cfbd2b2..be55e9ae74d 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 Chelsio Communications. All rights reserved.
+ * Copyright (C) 2006-2008 Chelsio Communications. All rights reserved.
*
* 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
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index 29db711303b..bb8698a8675 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -35,7 +35,7 @@
#define DRV_DESC "Chelsio T3 Network Driver"
#define DRV_NAME "cxgb3"
/* Driver version */
-#define DRV_VERSION "1.0-ko"
+#define DRV_VERSION "1.1.0-ko"
/* Firmware version */
#define FW_VERSION_MAJOR 7
diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/cxgb3/vsc8211.c
index eee4285b31b..33f956bd6b5 100644
--- a/drivers/net/cxgb3/vsc8211.c
+++ b/drivers/net/cxgb3/vsc8211.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
*
* 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
@@ -33,28 +33,40 @@
/* VSC8211 PHY specific registers. */
enum {
+ VSC8211_SIGDET_CTRL = 19,
+ VSC8211_EXT_CTRL = 23,
VSC8211_INTR_ENABLE = 25,
VSC8211_INTR_STATUS = 26,
+ VSC8211_LED_CTRL = 27,
VSC8211_AUX_CTRL_STAT = 28,
+ VSC8211_EXT_PAGE_AXS = 31,
};
enum {
VSC_INTR_RX_ERR = 1 << 0,
- VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
- VSC_INTR_CABLE = 1 << 2, /* cable impairment */
- VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
- VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
- VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
- VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
- VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
- VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
- VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
- VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
- VSC_INTR_LINK_CHG = 1 << 13, /* link change */
- VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
+ VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
+ VSC_INTR_CABLE = 1 << 2, /* cable impairment */
+ VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
+ VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
+ VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
+ VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
+ VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
+ VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
+ VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
+ VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
+ VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */
+ VSC_INTR_LINK_CHG = 1 << 13, /* link change */
+ VSC_INTR_SPD_CHG = 1 << 14, /* speed change */
+ VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
+};
+
+enum {
+ VSC_CTRL_CLAUSE37_VIEW = 1 << 4, /* Switch to Clause 37 view */
+ VSC_CTRL_MEDIA_MODE_HI = 0xf000 /* High part of media mode select */
};
#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
+ VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \
VSC_INTR_NEG_DONE)
#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
VSC_INTR_ENABLE)
@@ -184,6 +196,112 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok,
return 0;
}
+static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok,
+ int *speed, int *duplex, int *fc)
+{
+ unsigned int bmcr, status, lpa, adv;
+ int err, sp = -1, dplx = -1, pause = 0;
+
+ err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
+ if (!err)
+ err = mdio_read(cphy, 0, MII_BMSR, &status);
+ if (err)
+ return err;
+
+ if (link_ok) {
+ /*
+ * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
+ * once more to get the current link state.
+ */
+ if (!(status & BMSR_LSTATUS))
+ err = mdio_read(cphy, 0, MII_BMSR, &status);
+ if (err)
+ return err;
+ *link_ok = (status & BMSR_LSTATUS) != 0;
+ }
+ if (!(bmcr & BMCR_ANENABLE)) {
+ dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+ if (bmcr & BMCR_SPEED1000)
+ sp = SPEED_1000;
+ else if (bmcr & BMCR_SPEED100)
+ sp = SPEED_100;
+ else
+ sp = SPEED_10;
+ } else if (status & BMSR_ANEGCOMPLETE) {
+ err = mdio_read(cphy, 0, MII_LPA, &lpa);
+ if (!err)
+ err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
+ if (err)
+ return err;
+
+ if (adv & lpa & ADVERTISE_1000XFULL) {
+ dplx = DUPLEX_FULL;
+ sp = SPEED_1000;
+ } else if (adv & lpa & ADVERTISE_1000XHALF) {
+ dplx = DUPLEX_HALF;
+ sp = SPEED_1000;
+ }
+
+ if (fc && dplx == DUPLEX_FULL) {
+ if (lpa & adv & ADVERTISE_1000XPAUSE)
+ pause = PAUSE_RX | PAUSE_TX;
+ else if ((lpa & ADVERTISE_1000XPAUSE) &&
+ (adv & lpa & ADVERTISE_1000XPSE_ASYM))
+ pause = PAUSE_TX;
+ else if ((lpa & ADVERTISE_1000XPSE_ASYM) &&
+ (adv & ADVERTISE_1000XPAUSE))
+ pause = PAUSE_RX;
+ }
+ }
+ if (speed)
+ *speed = sp;
+ if (duplex)
+ *duplex = dplx;
+ if (fc)
+ *fc = pause;
+ return 0;
+}
+
+/*
+ * Enable/disable auto MDI/MDI-X in forced link speed mode.
+ */
+static int vsc8211_set_automdi(struct cphy *phy, int enable)
+{
+ int err;
+
+ err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, 18, 0x12);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, 16, 0x87fa);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex)
+{
+ int err;
+
+ err = t3_set_phy_speed_duplex(phy, speed, duplex);
+ if (!err)
+ err = vsc8211_set_automdi(phy, 1);
+ return err;
+}
+
static int vsc8211_power_down(struct cphy *cphy, int enable)
{
return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
@@ -221,8 +339,66 @@ static struct cphy_ops vsc8211_ops = {
.power_down = vsc8211_power_down,
};
-void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
- int phy_addr, const struct mdio_ops *mdio_ops)
+static struct cphy_ops vsc8211_fiber_ops = {
+ .reset = vsc8211_reset,
+ .intr_enable = vsc8211_intr_enable,
+ .intr_disable = vsc8211_intr_disable,
+ .intr_clear = vsc8211_intr_clear,
+ .intr_handler = vsc8211_intr_handler,
+ .autoneg_enable = vsc8211_autoneg_enable,
+ .autoneg_restart = vsc8211_autoneg_restart,
+ .advertise = t3_phy_advertise_fiber,
+ .set_speed_duplex = t3_set_phy_speed_duplex,
+ .get_link_status = vsc8211_get_link_status_fiber,
+ .power_down = vsc8211_power_down,
+};
+
+int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
+ int phy_addr, const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops);
+ int err;
+ unsigned int val;
+
+ cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops,
+ SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
+ SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
+ msleep(20); /* PHY needs ~10ms to start responding to MDIO */
+
+ err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val);
+ if (err)
+ return err;
+ if (val & VSC_CTRL_MEDIA_MODE_HI) {
+ /* copper interface, just need to configure the LEDs */
+ return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100);
+ }
+
+ phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
+ SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ;
+ phy->desc = "1000BASE-X";
+ phy->ops = &vsc8211_fiber_ops;
+
+ err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0);
+ if (err)
+ return err;
+
+ err = mdio_write(phy, 0, VSC8211_EXT_CTRL,
+ val | VSC_CTRL_CLAUSE37_VIEW);
+ if (err)
+ return err;
+
+ err = vsc8211_reset(phy, 0);
+ if (err)
+ return err;
+
+ udelay(5); /* delay after reset before next SMI */
+ return 0;
}
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index ffdc0a1892b..9d7786937aa 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
*
* 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
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 453115acaad..3d69fae781c 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -191,7 +191,7 @@ MODULE_PARM_DESC(use_io, "Force use of i/o access mode");
#define DPRINTK(nlevel, klevel, fmt, args...) \
(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
- __FUNCTION__ , ## args))
+ __func__ , ## args))
#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
@@ -2738,9 +2738,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->flags |= wol_magic;
/* ack any pending wake events, disable PME */
- err = pci_enable_wake(pdev, 0, 0);
- if (err)
- DPRINTK(PROBE, ERR, "Error clearing wake event\n");
+ pci_pme_active(pdev, false);
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 19e317eaf5b..62f62970f97 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -155,8 +155,6 @@ do { \
#endif
#define E1000_MNG_VLAN_NONE (-1)
-/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
@@ -168,14 +166,6 @@ struct e1000_buffer {
u16 next_to_watch;
};
-struct e1000_ps_page {
- struct page *ps_page[PS_PAGE_BUFFERS];
-};
-
-struct e1000_ps_page_dma {
- u64 ps_page_dma[PS_PAGE_BUFFERS];
-};
-
struct e1000_tx_ring {
/* pointer to the descriptor ring memory */
void *desc;
@@ -213,9 +203,6 @@ struct e1000_rx_ring {
unsigned int next_to_clean;
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
- /* arrays of page information for packet split */
- struct e1000_ps_page *ps_page;
- struct e1000_ps_page_dma *ps_page_dma;
/* cpu for rx queue */
int cpu;
@@ -228,8 +215,6 @@ struct e1000_rx_ring {
((((R)->next_to_clean > (R)->next_to_use) \
? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
-#define E1000_RX_DESC_PS(R, i) \
- (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
#define E1000_RX_DESC_EXT(R, i) \
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
@@ -311,10 +296,8 @@ struct e1000_adapter {
u32 rx_int_delay;
u32 rx_abs_int_delay;
bool rx_csum;
- unsigned int rx_ps_pages;
u32 gorcl;
u64 gorcl_old;
- u16 rx_ps_bsize0;
/* OS defined structs */
struct net_device *netdev;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 9d6edf3e73f..d04eef53571 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -144,6 +144,8 @@ static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
+static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
/* IGP cable length table */
static const
@@ -168,6 +170,8 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
104, 109, 114, 118, 121, 124};
+static DEFINE_SPINLOCK(e1000_eeprom_lock);
+
/******************************************************************************
* Set the phy type member in the hw struct.
*
@@ -4904,6 +4908,15 @@ static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
*****************************************************************************/
s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
+ s32 ret;
+ spin_lock(&e1000_eeprom_lock);
+ ret = e1000_do_read_eeprom(hw, offset, words, data);
+ spin_unlock(&e1000_eeprom_lock);
+ return ret;
+}
+
+static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 i = 0;
@@ -5236,6 +5249,16 @@ s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
*****************************************************************************/
s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
+ s32 ret;
+ spin_lock(&e1000_eeprom_lock);
+ ret = e1000_do_write_eeprom(hw, offset, words, data);
+ spin_unlock(&e1000_eeprom_lock);
+ return ret;
+}
+
+
+static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
s32 status = 0;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ad6da7b67e5..fac82152e4c 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -137,15 +137,9 @@ static int e1000_clean(struct napi_struct *napi, int budget);
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int cleaned_count);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -1053,6 +1047,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_LLTX;
+ netdev->vlan_features |= NETIF_F_TSO;
+ netdev->vlan_features |= NETIF_F_TSO6;
+ netdev->vlan_features |= NETIF_F_HW_CSUM;
+ netdev->vlan_features |= NETIF_F_SG;
+
adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
/* initialize eeprom parameters */
@@ -1331,7 +1330,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
hw->max_frame_size = netdev->mtu +
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -1815,26 +1813,6 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
}
memset(rxdr->buffer_info, 0, size);
- rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct e1000_ps_page),
- GFP_KERNEL);
- if (!rxdr->ps_page) {
- vfree(rxdr->buffer_info);
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the receive descriptor ring\n");
- return -ENOMEM;
- }
-
- rxdr->ps_page_dma = kcalloc(rxdr->count,
- sizeof(struct e1000_ps_page_dma),
- GFP_KERNEL);
- if (!rxdr->ps_page_dma) {
- vfree(rxdr->buffer_info);
- kfree(rxdr->ps_page);
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the receive descriptor ring\n");
- return -ENOMEM;
- }
-
if (hw->mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
@@ -1852,8 +1830,6 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
"Unable to allocate memory for the receive descriptor ring\n");
setup_rx_desc_die:
vfree(rxdr->buffer_info);
- kfree(rxdr->ps_page);
- kfree(rxdr->ps_page_dma);
return -ENOMEM;
}
@@ -1932,11 +1908,7 @@ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
static void e1000_setup_rctl(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- u32 rctl, rfctl;
- u32 psrctl = 0;
-#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
- u32 pages = 0;
-#endif
+ u32 rctl;
rctl = er32(RCTL);
@@ -1988,55 +1960,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
-#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
- /* 82571 and greater support packet-split where the protocol
- * header is placed in skb->data and the packet data is
- * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
- * In the case of a non-split, skb->data is linearly filled,
- * followed by the page buffers. Therefore, skb->data is
- * sized to hold the largest protocol header.
- */
- /* allocations using alloc_page take too long for regular MTU
- * so only enable packet split for jumbo frames */
- pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if ((hw->mac_type >= e1000_82571) && (pages <= 3) &&
- PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE))
- adapter->rx_ps_pages = pages;
- else
- adapter->rx_ps_pages = 0;
-#endif
- if (adapter->rx_ps_pages) {
- /* Configure extra packet-split registers */
- rfctl = er32(RFCTL);
- rfctl |= E1000_RFCTL_EXTEN;
- /* disable packet split support for IPv6 extension headers,
- * because some malformed IPv6 headers can hang the RX */
- rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
- E1000_RFCTL_NEW_IPV6_EXT_DIS);
-
- ew32(RFCTL, rfctl);
-
- rctl |= E1000_RCTL_DTYP_PS;
-
- psrctl |= adapter->rx_ps_bsize0 >>
- E1000_PSRCTL_BSIZE0_SHIFT;
-
- switch (adapter->rx_ps_pages) {
- case 3:
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE3_SHIFT;
- case 2:
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE2_SHIFT;
- case 1:
- psrctl |= PAGE_SIZE >>
- E1000_PSRCTL_BSIZE1_SHIFT;
- break;
- }
-
- ew32(PSRCTL, psrctl);
- }
-
ew32(RCTL, rctl);
}
@@ -2053,18 +1976,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 rdlen, rctl, rxcsum, ctrl_ext;
- if (adapter->rx_ps_pages) {
- /* this is a 32 byte descriptor */
- rdlen = adapter->rx_ring[0].count *
- sizeof(union e1000_rx_desc_packet_split);
- adapter->clean_rx = e1000_clean_rx_irq_ps;
- adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
- } else {
- rdlen = adapter->rx_ring[0].count *
- sizeof(struct e1000_rx_desc);
- adapter->clean_rx = e1000_clean_rx_irq;
- adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
- }
+ rdlen = adapter->rx_ring[0].count *
+ sizeof(struct e1000_rx_desc);
+ adapter->clean_rx = e1000_clean_rx_irq;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
/* disable receives while setting up the descriptors */
rctl = er32(RCTL);
@@ -2109,28 +2024,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
rxcsum = er32(RXCSUM);
- if (adapter->rx_csum) {
+ if (adapter->rx_csum)
rxcsum |= E1000_RXCSUM_TUOFL;
-
- /* Enable 82571 IPv4 payload checksum for UDP fragments
- * Must be used in conjunction with packet-split. */
- if ((hw->mac_type >= e1000_82571) &&
- (adapter->rx_ps_pages)) {
- rxcsum |= E1000_RXCSUM_IPPCSE;
- }
- } else {
- rxcsum &= ~E1000_RXCSUM_TUOFL;
+ else
/* don't need to clear IPPCSE as it defaults to 0 */
- }
+ rxcsum &= ~E1000_RXCSUM_TUOFL;
ew32(RXCSUM, rxcsum);
}
- /* enable early receives on 82573, only takes effect if using > 2048
- * byte total frame size. for example only for jumbo frames */
-#define E1000_ERT_2048 0x100
- if (hw->mac_type == e1000_82573)
- ew32(ERT, E1000_ERT_2048);
-
/* Enable Receives */
ew32(RCTL, rctl);
}
@@ -2256,10 +2157,6 @@ static void e1000_free_rx_resources(struct e1000_adapter *adapter,
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
- kfree(rx_ring->ps_page);
- rx_ring->ps_page = NULL;
- kfree(rx_ring->ps_page_dma);
- rx_ring->ps_page_dma = NULL;
pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -2292,11 +2189,9 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
{
struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
- struct e1000_ps_page *ps_page;
- struct e1000_ps_page_dma *ps_page_dma;
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
- unsigned int i, j;
+ unsigned int i;
/* Free all the Rx ring sk_buffs */
for (i = 0; i < rx_ring->count; i++) {
@@ -2310,25 +2205,10 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
}
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
- for (j = 0; j < adapter->rx_ps_pages; j++) {
- if (!ps_page->ps_page[j]) break;
- pci_unmap_page(pdev,
- ps_page_dma->ps_page_dma[j],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- ps_page_dma->ps_page_dma[j] = 0;
- put_page(ps_page->ps_page[j]);
- ps_page->ps_page[j] = NULL;
- }
}
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
- size = sizeof(struct e1000_ps_page) * rx_ring->count;
- memset(rx_ring->ps_page, 0, size);
- size = sizeof(struct e1000_ps_page_dma) * rx_ring->count;
- memset(rx_ring->ps_page_dma, 0, size);
/* Zero out the descriptor ring */
@@ -2998,32 +2878,49 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info;
unsigned int i;
u8 css;
+ u32 cmd_len = E1000_TXD_CMD_DEXT;
- if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
- css = skb_transport_offset(skb);
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return false;
- i = tx_ring->next_to_use;
- buffer_info = &tx_ring->buffer_info[i];
- context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ cmd_len |= E1000_TXD_CMD_TCP;
+ break;
+ case __constant_htons(ETH_P_IPV6):
+ /* XXX not handling all IPV6 headers */
+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+ cmd_len |= E1000_TXD_CMD_TCP;
+ break;
+ default:
+ if (unlikely(net_ratelimit()))
+ DPRINTK(DRV, WARNING,
+ "checksum_partial proto=%x!\n", skb->protocol);
+ break;
+ }
- context_desc->lower_setup.ip_config = 0;
- context_desc->upper_setup.tcp_fields.tucss = css;
- context_desc->upper_setup.tcp_fields.tucso =
- css + skb->csum_offset;
- context_desc->upper_setup.tcp_fields.tucse = 0;
- context_desc->tcp_seg_setup.data = 0;
- context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ css = skb_transport_offset(skb);
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
+ i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
- if (unlikely(++i == tx_ring->count)) i = 0;
- tx_ring->next_to_use = i;
+ context_desc->lower_setup.ip_config = 0;
+ context_desc->upper_setup.tcp_fields.tucss = css;
+ context_desc->upper_setup.tcp_fields.tucso =
+ css + skb->csum_offset;
+ context_desc->upper_setup.tcp_fields.tucse = 0;
+ context_desc->tcp_seg_setup.data = 0;
+ context_desc->cmd_and_length = cpu_to_le32(cmd_len);
- return true;
- }
+ buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
- return false;
+ if (unlikely(++i == tx_ring->count)) i = 0;
+ tx_ring->next_to_use = i;
+
+ return true;
}
#define E1000_MAX_TXD_PWR 12
@@ -4235,181 +4132,6 @@ next_desc:
}
/**
- * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
- * @adapter: board private structure
- **/
-
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
-{
- union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
- struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
- struct e1000_buffer *buffer_info, *next_buffer;
- struct e1000_ps_page *ps_page;
- struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb;
- unsigned int i, j;
- u32 length, staterr;
- int cleaned_count = 0;
- bool cleaned = false;
- unsigned int total_rx_bytes=0, total_rx_packets=0;
-
- i = rx_ring->next_to_clean;
- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
- buffer_info = &rx_ring->buffer_info[i];
-
- while (staterr & E1000_RXD_STAT_DD) {
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
-
- if (unlikely(*work_done >= work_to_do))
- break;
- (*work_done)++;
-
- skb = buffer_info->skb;
-
- /* in the packet split case this is header only */
- prefetch(skb->data - NET_IP_ALIGN);
-
- if (++i == rx_ring->count) i = 0;
- next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
- prefetch(next_rxd);
-
- next_buffer = &rx_ring->buffer_info[i];
-
- cleaned = true;
- cleaned_count++;
- pci_unmap_single(pdev, buffer_info->dma,
- buffer_info->length,
- PCI_DMA_FROMDEVICE);
-
- if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
- E1000_DBG("%s: Packet Split buffers didn't pick up"
- " the full packet\n", netdev->name);
- dev_kfree_skb_irq(skb);
- goto next_desc;
- }
-
- if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
- dev_kfree_skb_irq(skb);
- goto next_desc;
- }
-
- length = le16_to_cpu(rx_desc->wb.middle.length0);
-
- if (unlikely(!length)) {
- E1000_DBG("%s: Last part of the packet spanning"
- " multiple descriptors\n", netdev->name);
- dev_kfree_skb_irq(skb);
- goto next_desc;
- }
-
- /* Good Receive */
- skb_put(skb, length);
-
- {
- /* this looks ugly, but it seems compiler issues make it
- more efficient than reusing j */
- int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
-
- /* page alloc/put takes too long and effects small packet
- * throughput, so unsplit small packets and save the alloc/put*/
- if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) {
- u8 *vaddr;
- /* there is no documentation about how to call
- * kmap_atomic, so we can't hold the mapping
- * very long */
- pci_dma_sync_single_for_cpu(pdev,
- ps_page_dma->ps_page_dma[0],
- PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- vaddr = kmap_atomic(ps_page->ps_page[0],
- KM_SKB_DATA_SOFTIRQ);
- memcpy(skb_tail_pointer(skb), vaddr, l1);
- kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
- pci_dma_sync_single_for_device(pdev,
- ps_page_dma->ps_page_dma[0],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- /* remove the CRC */
- l1 -= 4;
- skb_put(skb, l1);
- goto copydone;
- } /* if */
- }
-
- for (j = 0; j < adapter->rx_ps_pages; j++) {
- length = le16_to_cpu(rx_desc->wb.upper.length[j]);
- if (!length)
- break;
- pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- ps_page_dma->ps_page_dma[j] = 0;
- skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0,
- length);
- ps_page->ps_page[j] = NULL;
- skb->len += length;
- skb->data_len += length;
- skb->truesize += length;
- }
-
- /* strip the ethernet crc, problem is we're using pages now so
- * this whole operation can get a little cpu intensive */
- pskb_trim(skb, skb->len - 4);
-
-copydone:
- total_rx_bytes += skb->len;
- total_rx_packets++;
-
- e1000_rx_checksum(adapter, staterr,
- le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
- skb->protocol = eth_type_trans(skb, netdev);
-
- if (likely(rx_desc->wb.upper.header_status &
- cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
- adapter->rx_hdr_split++;
-
- if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan));
- } else {
- netif_receive_skb(skb);
- }
-
- netdev->last_rx = jiffies;
-
-next_desc:
- rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
- buffer_info->skb = NULL;
-
- /* return some buffers to hardware, one at a time is too slow */
- if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
- cleaned_count = 0;
- }
-
- /* use prefetched values */
- rx_desc = next_rxd;
- buffer_info = next_buffer;
-
- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
- }
- rx_ring->next_to_clean = i;
-
- cleaned_count = E1000_DESC_UNUSED(rx_ring);
- if (cleaned_count)
- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
-
- adapter->total_rx_packets += total_rx_packets;
- adapter->total_rx_bytes += total_rx_bytes;
- adapter->net_stats.rx_bytes += total_rx_bytes;
- adapter->net_stats.rx_packets += total_rx_packets;
- return cleaned;
-}
-
-/**
* e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
* @adapter: address of board private structure
**/
@@ -4521,104 +4243,6 @@ map_skb:
}
/**
- * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split
- * @adapter: address of board private structure
- **/
-
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count)
-{
- struct e1000_hw *hw = &adapter->hw;
- struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
- union e1000_rx_desc_packet_split *rx_desc;
- struct e1000_buffer *buffer_info;
- struct e1000_ps_page *ps_page;
- struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb;
- unsigned int i, j;
-
- i = rx_ring->next_to_use;
- buffer_info = &rx_ring->buffer_info[i];
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
-
- while (cleaned_count--) {
- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
-
- for (j = 0; j < PS_PAGE_BUFFERS; j++) {
- if (j < adapter->rx_ps_pages) {
- if (likely(!ps_page->ps_page[j])) {
- ps_page->ps_page[j] =
- alloc_page(GFP_ATOMIC);
- if (unlikely(!ps_page->ps_page[j])) {
- adapter->alloc_rx_buff_failed++;
- goto no_buffers;
- }
- ps_page_dma->ps_page_dma[j] =
- pci_map_page(pdev,
- ps_page->ps_page[j],
- 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- }
- /* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases
- * this info.
- */
- rx_desc->read.buffer_addr[j+1] =
- cpu_to_le64(ps_page_dma->ps_page_dma[j]);
- } else
- rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0);
- }
-
- skb = netdev_alloc_skb(netdev,
- adapter->rx_ps_bsize0 + NET_IP_ALIGN);
-
- if (unlikely(!skb)) {
- adapter->alloc_rx_buff_failed++;
- break;
- }
-
- /* Make buffer alignment 2 beyond a 16 byte boundary
- * this will result in a 16 byte aligned IP header after
- * the 14 byte MAC header is removed
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
- buffer_info->skb = skb;
- buffer_info->length = adapter->rx_ps_bsize0;
- buffer_info->dma = pci_map_single(pdev, skb->data,
- adapter->rx_ps_bsize0,
- PCI_DMA_FROMDEVICE);
-
- rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
-
- if (unlikely(++i == rx_ring->count)) i = 0;
- buffer_info = &rx_ring->buffer_info[i];
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
- }
-
-no_buffers:
- if (likely(rx_ring->next_to_use != i)) {
- rx_ring->next_to_use = i;
- if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
-
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- /* Hardware increments by 16 bytes, but packet split
- * descriptors are 32 bytes...so we increment tail
- * twice as much.
- */
- writel(i<<1, hw->hw_addr + rx_ring->rdt);
- }
-}
-
-/**
* e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
* @adapter:
**/
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 462351ca2c8..b2c910c52df 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -38,6 +38,7 @@
* 82573V Gigabit Ethernet Controller (Copper)
* 82573E Gigabit Ethernet Controller (Copper)
* 82573L Gigabit Ethernet Controller
+ * 82574L Gigabit Network Connection
*/
#include <linux/netdevice.h>
@@ -54,6 +55,8 @@
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
+#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
+
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
@@ -63,6 +66,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
static s32 e1000_setup_link_82571(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
+static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
+static s32 e1000_led_on_82574(struct e1000_hw *hw);
/**
* e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -92,6 +97,9 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
case e1000_82573:
phy->type = e1000_phy_m88;
break;
+ case e1000_82574:
+ phy->type = e1000_phy_bm;
+ break;
default:
return -E1000_ERR_PHY;
break;
@@ -111,6 +119,10 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
if (phy->id != M88E1111_I_PHY_ID)
return -E1000_ERR_PHY;
break;
+ case e1000_82574:
+ if (phy->id != BME1000_E_PHY_ID_R2)
+ return -E1000_ERR_PHY;
+ break;
default:
return -E1000_ERR_PHY;
break;
@@ -150,6 +162,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82573:
+ case e1000_82574:
if (((eecd >> 15) & 0x3) == 0x3) {
nvm->type = e1000_nvm_flash_hw;
nvm->word_size = 2048;
@@ -245,6 +258,17 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
break;
}
+ switch (hw->mac.type) {
+ case e1000_82574:
+ func->check_mng_mode = e1000_check_mng_mode_82574;
+ func->led_on = e1000_led_on_82574;
+ break;
+ default:
+ func->check_mng_mode = e1000e_check_mng_mode_generic;
+ func->led_on = e1000e_led_on_generic;
+ break;
+ }
+
return 0;
}
@@ -330,6 +354,8 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_id = 0;
switch (hw->mac.type) {
case e1000_82571:
@@ -345,6 +371,20 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
case e1000_82573:
return e1000e_get_phy_id(hw);
break;
+ case e1000_82574:
+ ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
+ if (ret_val)
+ return ret_val;
+
+ phy->id = (u32)(phy_id << 16);
+ udelay(20);
+ ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
+ if (ret_val)
+ return ret_val;
+
+ phy->id |= (u32)(phy_id);
+ phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
+ break;
default:
return -E1000_ERR_PHY;
break;
@@ -421,7 +461,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- if (hw->mac.type != e1000_82573)
+ if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
ret_val = e1000e_acquire_nvm(hw);
if (ret_val)
@@ -461,6 +501,7 @@ static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
switch (hw->mac.type) {
case e1000_82573:
+ case e1000_82574:
ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
break;
case e1000_82571:
@@ -735,7 +776,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset.
*/
- if (hw->mac.type == e1000_82573) {
+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
@@ -776,7 +817,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Need to wait for Phy configuration completion before accessing
* NVM and Phy.
*/
- if (hw->mac.type == e1000_82573)
+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
msleep(25);
/* Clear any pending interrupt events. */
@@ -843,7 +884,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
ew32(TXDCTL(0), reg_data);
/* ...for both queues. */
- if (mac->type != e1000_82573) {
+ if (mac->type != e1000_82573 && mac->type != e1000_82574) {
reg_data = er32(TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB |
@@ -918,19 +959,28 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
}
/* Device Control */
- if (hw->mac.type == e1000_82573) {
+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = er32(CTRL);
reg &= ~(1 << 29);
ew32(CTRL, reg);
}
/* Extended Device Control */
- if (hw->mac.type == e1000_82573) {
+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = er32(CTRL_EXT);
reg &= ~(1 << 23);
reg |= (1 << 22);
ew32(CTRL_EXT, reg);
}
+
+ /* PCI-Ex Control Register */
+ if (hw->mac.type == e1000_82574) {
+ reg = er32(GCR);
+ reg |= (1 << 22);
+ ew32(GCR, reg);
+ }
+
+ return;
}
/**
@@ -947,7 +997,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
u32 vfta_offset = 0;
u32 vfta_bit_in_reg = 0;
- if (hw->mac.type == e1000_82573) {
+ if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
if (hw->mng_cookie.vlan_id != 0) {
/*
* The VFTA is a 4096b bit-field, each identifying
@@ -976,6 +1026,48 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
}
/**
+ * e1000_check_mng_mode_82574 - Check manageability is enabled
+ * @hw: pointer to the HW structure
+ *
+ * Reads the NVM Initialization Control Word 2 and returns true
+ * (>0) if any manageability is enabled, else false (0).
+ **/
+static bool e1000_check_mng_mode_82574(struct e1000_hw *hw)
+{
+ u16 data;
+
+ e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+ return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0;
+}
+
+/**
+ * e1000_led_on_82574 - Turn LED on
+ * @hw: pointer to the HW structure
+ *
+ * Turn LED on.
+ **/
+static s32 e1000_led_on_82574(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ u32 i;
+
+ ctrl = hw->mac.ledctl_mode2;
+ if (!(E1000_STATUS_LU & er32(STATUS))) {
+ /*
+ * If no link, then turn LED on by setting the invert bit
+ * for each LED that's "on" (0x0E) in ledctl_mode2.
+ */
+ for (i = 0; i < 4; i++)
+ if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+ E1000_LEDCTL_MODE_LED_ON)
+ ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
+ }
+ ew32(LEDCTL, ctrl);
+
+ return 0;
+}
+
+/**
* e1000_update_mc_addr_list_82571 - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
@@ -1018,7 +1110,8 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
* the default flow control setting, so we explicitly
* set it to full.
*/
- if (hw->mac.type == e1000_82573)
+ if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
+ hw->fc.type == e1000_fc_default)
hw->fc.type = e1000_fc_full;
return e1000e_setup_link(hw);
@@ -1045,6 +1138,7 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
switch (hw->phy.type) {
case e1000_phy_m88:
+ case e1000_phy_bm:
ret_val = e1000e_copper_link_setup_m88(hw);
break;
case e1000_phy_igp_2:
@@ -1114,11 +1208,10 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
return ret_val;
}
- if (hw->mac.type == e1000_82573 &&
+ if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
*data == ID_LED_RESERVED_F746)
*data = ID_LED_DEFAULT_82573;
- else if (*data == ID_LED_RESERVED_0000 ||
- *data == ID_LED_RESERVED_FFFF)
+ else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
*data = ID_LED_DEFAULT;
return 0;
@@ -1265,13 +1358,13 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
}
static struct e1000_mac_operations e82571_mac_ops = {
- .mng_mode_enab = E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT,
+ /* .check_mng_mode: mac type dependent */
/* .check_for_link: media type dependent */
.cleanup_led = e1000e_cleanup_led_generic,
.clear_hw_cntrs = e1000_clear_hw_cntrs_82571,
.get_bus_info = e1000e_get_bus_info_pcie,
/* .get_link_up_info: media type dependent */
- .led_on = e1000e_led_on_generic,
+ /* .led_on: mac type dependent */
.led_off = e1000e_led_off_generic,
.update_mc_addr_list = e1000_update_mc_addr_list_82571,
.reset_hw = e1000_reset_hw_82571,
@@ -1312,6 +1405,22 @@ static struct e1000_phy_operations e82_phy_ops_m88 = {
.write_phy_reg = e1000e_write_phy_reg_m88,
};
+static struct e1000_phy_operations e82_phy_ops_bm = {
+ .acquire_phy = e1000_get_hw_semaphore_82571,
+ .check_reset_block = e1000e_check_reset_block_generic,
+ .commit_phy = e1000e_phy_sw_reset,
+ .force_speed_duplex = e1000e_phy_force_speed_duplex_m88,
+ .get_cfg_done = e1000e_get_cfg_done,
+ .get_cable_length = e1000e_get_cable_length_m88,
+ .get_phy_info = e1000e_get_phy_info_m88,
+ .read_phy_reg = e1000e_read_phy_reg_bm2,
+ .release_phy = e1000_put_hw_semaphore_82571,
+ .reset_phy = e1000e_phy_hw_reset_generic,
+ .set_d0_lplu_state = e1000_set_d0_lplu_state_82571,
+ .set_d3_lplu_state = e1000e_set_d3_lplu_state,
+ .write_phy_reg = e1000e_write_phy_reg_bm2,
+};
+
static struct e1000_nvm_operations e82571_nvm_ops = {
.acquire_nvm = e1000_acquire_nvm_82571,
.read_nvm = e1000e_read_nvm_eerd,
@@ -1375,3 +1484,21 @@ struct e1000_info e1000_82573_info = {
.nvm_ops = &e82571_nvm_ops,
};
+struct e1000_info e1000_82574_info = {
+ .mac = e1000_82574,
+ .flags = FLAG_HAS_HW_VLAN_FILTER
+ | FLAG_HAS_MSIX
+ | FLAG_HAS_JUMBO_FRAMES
+ | FLAG_HAS_WOL
+ | FLAG_APME_IN_CTRL3
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_SMART_POWER_DOWN
+ | FLAG_HAS_AMT
+ | FLAG_HAS_CTRLEXT_ON_LOAD,
+ .pba = 20,
+ .get_variants = e1000_get_variants_82571,
+ .mac_ops = &e82571_mac_ops,
+ .phy_ops = &e82_phy_ops_bm,
+ .nvm_ops = &e82571_nvm_ops,
+};
+
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 14b0e6cd3b8..48f79ecb82a 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -71,9 +71,11 @@
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
+#define E1000_CTRL_EXT_EIAME 0x01000000
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
+#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
/* Receive Descriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
@@ -299,6 +301,7 @@
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
/* Header split receive */
+#define E1000_RFCTL_ACK_DIS 0x00001000
#define E1000_RFCTL_EXTEN 0x00008000
#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
@@ -363,6 +366,11 @@
#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
+#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
+#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
+#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
+#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
/*
* This defines the bits that are set in the Interrupt Mask
@@ -386,6 +394,11 @@
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
+#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
+#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
+#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
+#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
+#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */
/* Interrupt Cause Set */
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
@@ -505,6 +518,7 @@
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
/* 1000BASE-T Control Register */
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
@@ -540,6 +554,7 @@
#define E1000_EECD_DO 0x00000008 /* NVM Data Out */
#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
+#define E1000_EECD_PRES 0x00000100 /* NVM Present */
#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
/* NVM Addressing bits based on type (0-small, 1-large) */
#define E1000_EECD_ADDR_BITS 0x00000400
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index ac4e506b4f8..c55de1c027a 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -62,6 +62,11 @@ struct e1000_info;
e_printk(KERN_NOTICE, adapter, format, ## arg)
+/* Interrupt modes, as used by the IntMode paramter */
+#define E1000E_INT_MODE_LEGACY 0
+#define E1000E_INT_MODE_MSI 1
+#define E1000E_INT_MODE_MSIX 2
+
/* Tx/Rx descriptor defines */
#define E1000_DEFAULT_TXD 256
#define E1000_MAX_TXD 4096
@@ -95,9 +100,11 @@ enum e1000_boards {
board_82571,
board_82572,
board_82573,
+ board_82574,
board_80003es2lan,
board_ich8lan,
board_ich9lan,
+ board_ich10lan,
};
struct e1000_queue_stats {
@@ -146,6 +153,12 @@ struct e1000_ring {
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
+ char name[IFNAMSIZ + 5];
+ u32 ims_val;
+ u32 itr_val;
+ u16 itr_register;
+ int set_itr;
+
struct sk_buff *rx_skb_top;
struct e1000_queue_stats stats;
@@ -257,7 +270,6 @@ struct e1000_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct net_device_stats net_stats;
- spinlock_t stats_lock; /* prevent concurrent stats updates */
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
@@ -274,6 +286,9 @@ struct e1000_adapter {
u32 test_icr;
u32 msg_enable;
+ struct msix_entry *msix_entries;
+ int int_mode;
+ u32 eiac_mask;
u32 eeprom_wol;
u32 wol;
@@ -284,6 +299,8 @@ struct e1000_adapter {
unsigned long led_status;
unsigned int flags;
+ struct work_struct downshift_task;
+ struct work_struct update_phy_task;
};
struct e1000_info {
@@ -305,7 +322,9 @@ struct e1000_info {
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
+#define FLAG_READ_ONLY_NVM (1 << 8)
#define FLAG_IS_ICH (1 << 9)
+#define FLAG_HAS_MSIX (1 << 10)
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
#define FLAG_IS_QUAD_PORT_A (1 << 12)
#define FLAG_IS_QUAD_PORT (1 << 13)
@@ -364,6 +383,8 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
+extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
extern unsigned int copybreak;
@@ -372,8 +393,10 @@ extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw);
extern struct e1000_info e1000_82571_info;
extern struct e1000_info e1000_82572_info;
extern struct e1000_info e1000_82573_info;
+extern struct e1000_info e1000_82574_info;
extern struct e1000_info e1000_ich8_info;
extern struct e1000_info e1000_ich9_info;
+extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_es2_info;
extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
@@ -385,6 +408,7 @@ extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);
extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw);
extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state);
+extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);
extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
bool state);
extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
@@ -446,10 +470,13 @@ extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw);
extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw);
extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
@@ -520,7 +547,12 @@ static inline s32 e1000_get_phy_info(struct e1000_hw *hw)
return hw->phy.ops.get_phy_info(hw);
}
-extern bool e1000e_check_mng_mode(struct e1000_hw *hw);
+static inline s32 e1000e_check_mng_mode(struct e1000_hw *hw)
+{
+ return hw->mac.ops.check_mng_mode(hw);
+}
+
+extern bool e1000e_check_mng_mode_generic(struct e1000_hw *hw);
extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw);
extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index dc552d7d6fa..da9c09c248e 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -1247,7 +1247,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
}
static struct e1000_mac_operations es2_mac_ops = {
- .mng_mode_enab = E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT,
+ .check_mng_mode = e1000e_check_mng_mode_generic,
/* check_for_link dependent on media type */
.cleanup_led = e1000e_cleanup_led_generic,
.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan,
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index e21c9e0f373..70c11c811a0 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -432,6 +432,10 @@ static void e1000_get_regs(struct net_device *netdev,
regs_buff[11] = er32(TIDV);
regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */
+
+ /* ethtool doesn't use anything past this point, so all this
+ * code is likely legacy junk for apps that may or may not
+ * exist */
if (hw->phy.type == e1000_phy_m88) {
e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
regs_buff[13] = (u32)phy_data; /* cable length */
@@ -447,7 +451,7 @@ static void e1000_get_regs(struct net_device *netdev,
regs_buff[22] = adapter->phy_stats.receive_errors;
regs_buff[23] = regs_buff[13]; /* mdix mode */
}
- regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
+ regs_buff[21] = 0; /* was idle_errors */
e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (u32)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
@@ -529,6 +533,9 @@ static int e1000_set_eeprom(struct net_device *netdev,
if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
return -EFAULT;
+ if (adapter->flags & FLAG_READ_ONLY_NVM)
+ return -EINVAL;
+
max_len = hw->nvm.word_size * 2;
first_word = eeprom->offset >> 1;
@@ -568,6 +575,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
* and flush shadow RAM for 82573 controllers
*/
if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) ||
+ (hw->mac.type == e1000_82574) ||
(hw->mac.type == e1000_82573)))
e1000e_update_nvm_checksum(hw);
@@ -779,8 +787,10 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
toggle = 0x7FFFF3FF;
break;
case e1000_82573:
+ case e1000_82574:
case e1000_ich8lan:
case e1000_ich9lan:
+ case e1000_ich10lan:
toggle = 0x7FFFF033;
break;
default:
@@ -833,7 +843,9 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
for (i = 0; i < mac->rar_entry_count; i++)
REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
- 0x8003FFFF, 0xFFFFFFFF);
+ ((mac->type == e1000_ich10lan) ?
+ 0x8007FFFF : 0x8003FFFF),
+ 0xFFFFFFFF);
for (i = 0; i < mac->mta_reg_count; i++)
REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
@@ -884,10 +896,18 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
u32 shared_int = 1;
u32 irq = adapter->pdev->irq;
int i;
+ int ret_val = 0;
+ int int_mode = E1000E_INT_MODE_LEGACY;
*data = 0;
- /* NOTE: we don't test MSI interrupts here, yet */
+ /* NOTE: we don't test MSI/MSI-X interrupts here, yet */
+ if (adapter->int_mode == E1000E_INT_MODE_MSIX) {
+ int_mode = adapter->int_mode;
+ e1000e_reset_interrupt_capability(adapter);
+ adapter->int_mode = E1000E_INT_MODE_LEGACY;
+ e1000e_set_interrupt_capability(adapter);
+ }
/* Hook up test interrupt handler just for this test */
if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
netdev)) {
@@ -895,7 +915,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
} else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
netdev->name, netdev)) {
*data = 1;
- return -1;
+ ret_val = -1;
+ goto out;
}
e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared"));
@@ -905,12 +926,23 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
/* Test each interrupt */
for (i = 0; i < 10; i++) {
- if ((adapter->flags & FLAG_IS_ICH) && (i == 8))
- continue;
-
/* Interrupt to test */
mask = 1 << i;
+ if (adapter->flags & FLAG_IS_ICH) {
+ switch (mask) {
+ case E1000_ICR_RXSEQ:
+ continue;
+ case 0x00000100:
+ if (adapter->hw.mac.type == e1000_ich8lan ||
+ adapter->hw.mac.type == e1000_ich9lan)
+ continue;
+ break;
+ default:
+ break;
+ }
+ }
+
if (!shared_int) {
/*
* Disable the interrupt to be reported in
@@ -974,7 +1006,14 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
/* Unhook test interrupt handler */
free_irq(irq, netdev);
- return *data;
+out:
+ if (int_mode == E1000E_INT_MODE_MSIX) {
+ e1000e_reset_interrupt_capability(adapter);
+ adapter->int_mode = int_mode;
+ e1000e_set_interrupt_capability(adapter);
+ }
+
+ return ret_val;
}
static void e1000_free_desc_rings(struct e1000_adapter *adapter)
@@ -1755,11 +1794,13 @@ static void e1000_led_blink_callback(unsigned long data)
static int e1000_phys_id(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
if (!data)
data = INT_MAX;
- if (adapter->hw.phy.type == e1000_phy_ife) {
+ if ((hw->phy.type == e1000_phy_ife) ||
+ (hw->mac.type == e1000_82574)) {
if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function =
@@ -1769,16 +1810,16 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- e1e_wphy(&adapter->hw,
- IFE_PHY_SPECIAL_CONTROL_LED, 0);
+ if (hw->phy.type == e1000_phy_ife)
+ e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
} else {
- e1000e_blink_led(&adapter->hw);
+ e1000e_blink_led(hw);
msleep_interruptible(data * 1000);
}
- adapter->hw.mac.ops.led_off(&adapter->hw);
+ hw->mac.ops.led_off(hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
- adapter->hw.mac.ops.cleanup_led(&adapter->hw);
+ hw->mac.ops.cleanup_led(hw);
return 0;
}
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 74f263acb17..f66ed37a7f7 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -65,7 +65,11 @@ enum e1e_registers {
E1000_ICS = 0x000C8, /* Interrupt Cause Set - WO */
E1000_IMS = 0x000D0, /* Interrupt Mask Set - RW */
E1000_IMC = 0x000D8, /* Interrupt Mask Clear - WO */
+ E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */
E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */
+ E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */
+ E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */
+#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2))
E1000_RCTL = 0x00100, /* Rx Control - RW */
E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */
E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */
@@ -332,6 +336,7 @@ enum e1e_registers {
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A
+#define E1000_DEV_ID_82574L 0x10D3
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
@@ -346,6 +351,7 @@ enum e1e_registers {
#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
#define E1000_DEV_ID_ICH8_IGP_M 0x104D
#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD
+#define E1000_DEV_ID_ICH9_BM 0x10E5
#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5
#define E1000_DEV_ID_ICH9_IGP_M 0x10BF
#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB
@@ -356,6 +362,10 @@ enum e1e_registers {
#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC
#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD
#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF
+
+#define E1000_REVISION_4 4
#define E1000_FUNC_1 1
@@ -363,9 +373,11 @@ enum e1000_mac_type {
e1000_82571,
e1000_82572,
e1000_82573,
+ e1000_82574,
e1000_80003es2lan,
e1000_ich8lan,
e1000_ich9lan,
+ e1000_ich10lan,
};
enum e1000_media_type {
@@ -696,8 +708,7 @@ struct e1000_host_mng_command_info {
/* Function pointers and static data for the MAC. */
struct e1000_mac_operations {
- u32 mng_mode_enab;
-
+ bool (*check_mng_mode)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
s32 (*cleanup_led)(struct e1000_hw *);
void (*clear_hw_cntrs)(struct e1000_hw *);
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 9e38452a738..523b9716a54 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -43,7 +43,9 @@
* 82567LM-2 Gigabit Network Connection
* 82567LF-2 Gigabit Network Connection
* 82567V-2 Gigabit Network Connection
- * 82562GT-3 10/100 Network Connection
+ * 82567LF-3 Gigabit Network Connection
+ * 82567LM-3 Gigabit Network Connection
+ * 82567LM-4 Gigabit Network Connection
*/
#include <linux/netdevice.h>
@@ -58,6 +60,7 @@
#define ICH_FLASH_HSFCTL 0x0006
#define ICH_FLASH_FADDR 0x0008
#define ICH_FLASH_FDATA0 0x0010
+#define ICH_FLASH_PR0 0x0074
#define ICH_FLASH_READ_COMMAND_TIMEOUT 500
#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500
@@ -150,6 +153,19 @@ union ich8_hws_flash_regacc {
u16 regval;
};
+/* ICH Flash Protected Region */
+union ich8_flash_protected_range {
+ struct ich8_pr {
+ u32 base:13; /* 0:12 Protected Range Base */
+ u32 reserved1:2; /* 13:14 Reserved */
+ u32 rpe:1; /* 15 Read Protection Enable */
+ u32 limit:13; /* 16:28 Protected Range Limit */
+ u32 reserved2:2; /* 29:30 Reserved */
+ u32 wpe:1; /* 31 Write Protection Enable */
+ } range;
+ u32 regval;
+};
+
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
@@ -157,12 +173,15 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw);
static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
u32 offset, u8 byte);
+static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
+ u8 *data);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
u16 *data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
u8 size, u16 *data);
static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
+static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
@@ -366,6 +385,9 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
return 0;
}
+static DEFINE_MUTEX(nvm_mutex);
+static pid_t nvm_owner = -1;
+
/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
* @hw: pointer to the HW structure
@@ -379,6 +401,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
u32 extcnf_ctrl;
u32 timeout = PHY_CFG_TIMEOUT;
+ might_sleep();
+
+ if (!mutex_trylock(&nvm_mutex)) {
+ WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n",
+ nvm_owner);
+ mutex_lock(&nvm_mutex);
+ }
+ nvm_owner = current->pid;
+
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
@@ -393,6 +424,10 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
if (!timeout) {
hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ nvm_owner = -1;
+ mutex_unlock(&nvm_mutex);
return -E1000_ERR_CONFIG;
}
@@ -414,6 +449,25 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+ nvm_owner = -1;
+ mutex_unlock(&nvm_mutex);
+}
+
+/**
+ * e1000_check_mng_mode_ich8lan - Checks management mode
+ * @hw: pointer to the HW structure
+ *
+ * This checks if the adapter has manageability enabled.
+ * This is a function pointer entry point only called by read/write
+ * routines for the PHY and NVM parts.
+ **/
+static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
+{
+ u32 fwsm = er32(FWSM);
+
+ return (fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
}
/**
@@ -897,6 +951,56 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
}
/**
+ * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1
+ * @hw: pointer to the HW structure
+ * @bank: pointer to the variable that returns the active bank
+ *
+ * Reads signature byte from the NVM using the flash access registers.
+ **/
+static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ /* flash bank size is in words */
+ u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
+ u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
+ u8 bank_high_byte = 0;
+
+ if (hw->mac.type != e1000_ich10lan) {
+ if (er32(EECD) & E1000_EECD_SEC1VAL)
+ *bank = 1;
+ else
+ *bank = 0;
+ } else {
+ /*
+ * Make sure the signature for bank 0 is valid,
+ * if not check for bank1
+ */
+ e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
+ if ((bank_high_byte & 0xC0) == 0x80) {
+ *bank = 0;
+ } else {
+ /*
+ * find if segment 1 is valid by verifying
+ * bit 15:14 = 10b in word 0x13
+ */
+ e1000_read_flash_byte_ich8lan(hw,
+ act_offset + bank1_offset,
+ &bank_high_byte);
+
+ /* bank1 has a valid signature equivalent to SEC1V */
+ if ((bank_high_byte & 0xC0) == 0x80) {
+ *bank = 1;
+ } else {
+ hw_dbg(hw, "ERROR: EEPROM not present\n");
+ return -E1000_ERR_NVM;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
* e1000_read_nvm_ich8lan - Read word(s) from the NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the word(s) to read.
@@ -912,6 +1016,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 act_offset;
s32 ret_val;
+ u32 bank = 0;
u16 i, word;
if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
@@ -924,10 +1029,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
if (ret_val)
return ret_val;
- /* Start with the bank offset, then add the relative offset. */
- act_offset = (er32(EECD) & E1000_EECD_SEC1VAL)
- ? nvm->flash_bank_size
- : 0;
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val)
+ return ret_val;
+
+ act_offset = (bank) ? nvm->flash_bank_size : 0;
act_offset += offset;
for (i = 0; i < words; i++) {
@@ -1075,6 +1181,29 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
}
/**
+ * e1000_read_flash_byte_ich8lan - Read byte from flash
+ * @hw: pointer to the HW structure
+ * @offset: The offset of the byte to read.
+ * @data: Pointer to a byte to store the value read.
+ *
+ * Reads a single byte from the NVM using the flash access registers.
+ **/
+static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
+ u8 *data)
+{
+ s32 ret_val;
+ u16 word = 0;
+
+ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
+ if (ret_val)
+ return ret_val;
+
+ *data = (u8)word;
+
+ return 0;
+}
+
+/**
* e1000_read_flash_data_ich8lan - Read byte or word from NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the byte or word to read.
@@ -1205,7 +1334,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- u32 i, act_offset, new_bank_offset, old_bank_offset;
+ u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
s32 ret_val;
u16 data;
@@ -1225,7 +1354,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* write to bank 0 etc. We also need to erase the segment that
* is going to be written
*/
- if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val)
+ return ret_val;
+
+ if (bank == 0) {
new_bank_offset = nvm->flash_bank_size;
old_bank_offset = 0;
e1000_erase_flash_bank_ich8lan(hw, 1);
@@ -1284,6 +1417,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* programming failed.
*/
if (ret_val) {
+ /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
hw_dbg(hw, "Flash commit failed.\n");
e1000_release_swflag_ich8lan(hw);
return ret_val;
@@ -1374,6 +1508,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only
+ * @hw: pointer to the HW structure
+ *
+ * To prevent malicious write/erase of the NVM, set it to be read-only
+ * so that the hardware ignores all write/erase cycles of the NVM via
+ * the flash control registers. The shadow-ram copy of the NVM will
+ * still be updated, however any updates to this copy will not stick
+ * across driver reloads.
+ **/
+void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
+{
+ union ich8_flash_protected_range pr0;
+ union ich8_hws_flash_status hsfsts;
+ u32 gfpreg;
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ return;
+
+ gfpreg = er32flash(ICH_FLASH_GFPREG);
+
+ /* Write-protect GbE Sector of NVM */
+ pr0.regval = er32flash(ICH_FLASH_PR0);
+ pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK;
+ pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK);
+ pr0.range.wpe = true;
+ ew32flash(ICH_FLASH_PR0, pr0.regval);
+
+ /*
+ * Lock down a subset of GbE Flash Control Registers, e.g.
+ * PR0 to prevent the write-protection from being lifted.
+ * Once FLOCKDN is set, the registers protected by it cannot
+ * be written until FLOCKDN is cleared by a hardware reset.
+ */
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+ hsfsts.hsf_status.flockdn = true;
+ ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+
+ e1000_release_swflag_ich8lan(hw);
+}
+
+/**
* e1000_write_flash_data_ich8lan - Writes bytes to the NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the byte/word to read.
@@ -1720,6 +1897,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(20);
+ /* release the swflag because it is not reset by hardware reset */
+ e1000_release_swflag_ich8lan(hw);
+
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
/*
@@ -2189,13 +2369,14 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
* to a lower speed.
*
- * Should only be called for ICH9 devices.
+ * Should only be called for ICH9 and ICH10 devices.
**/
void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
{
u32 phy_ctrl;
- if (hw->mac.type == e1000_ich9lan) {
+ if ((hw->mac.type == e1000_ich10lan) ||
+ (hw->mac.type == e1000_ich9lan)) {
phy_ctrl = er32(PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
E1000_PHY_CTRL_GBE_DISABLE;
@@ -2253,6 +2434,39 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000_get_cfg_done_ich8lan - Read config done bit
+ * @hw: pointer to the HW structure
+ *
+ * Read the management control register for the config done bit for
+ * completion status. NOTE: silicon which is EEPROM-less will fail trying
+ * to read the config done bit, so an error is *ONLY* logged and returns
+ * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon
+ * would not be able to be reset or change link.
+ **/
+static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
+{
+ u32 bank = 0;
+
+ e1000e_get_cfg_done(hw);
+
+ /* If EEPROM is not marked present, init the IGP 3 PHY manually */
+ if (hw->mac.type != e1000_ich10lan) {
+ if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
+ (hw->phy.type == e1000_phy_igp_3)) {
+ e1000e_phy_init_script_igp3(hw);
+ }
+ } else {
+ if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
+ /* Maybe we should do a basic PHY config */
+ hw_dbg(hw, "EEPROM not present\n");
+ return -E1000_ERR_CONFIG;
+ }
+ }
+
+ return 0;
+}
+
+/**
* e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
* @hw: pointer to the HW structure
*
@@ -2282,7 +2496,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
}
static struct e1000_mac_operations ich8_mac_ops = {
- .mng_mode_enab = E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT,
+ .check_mng_mode = e1000_check_mng_mode_ich8lan,
.check_for_link = e1000e_check_for_copper_link,
.cleanup_led = e1000_cleanup_led_ich8lan,
.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan,
@@ -2302,7 +2516,7 @@ static struct e1000_phy_operations ich8_phy_ops = {
.check_reset_block = e1000_check_reset_block_ich8lan,
.commit_phy = NULL,
.force_speed_duplex = e1000_phy_force_speed_duplex_ich8lan,
- .get_cfg_done = e1000e_get_cfg_done,
+ .get_cfg_done = e1000_get_cfg_done_ich8lan,
.get_cable_length = e1000e_get_cable_length_igp_2,
.get_phy_info = e1000_get_phy_info_ich8lan,
.read_phy_reg = e1000e_read_phy_reg_igp,
@@ -2357,3 +2571,20 @@ struct e1000_info e1000_ich9_info = {
.nvm_ops = &ich8_nvm_ops,
};
+struct e1000_info e1000_ich10_info = {
+ .mac = e1000_ich10lan,
+ .flags = FLAG_HAS_JUMBO_FRAMES
+ | FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+ | FLAG_HAS_AMT
+ | FLAG_HAS_ERT
+ | FLAG_HAS_FLASH
+ | FLAG_APME_IN_WUC,
+ .pba = 10,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+};
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index f1f4e9dfd0a..089578f6855 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -2012,6 +2012,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
}
msleep(10);
+ nvm->ops.release_nvm(hw);
return 0;
}
@@ -2222,17 +2223,18 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
}
/**
- * e1000e_check_mng_mode - check management mode
+ * e1000e_check_mng_mode_generic - check management mode
* @hw: pointer to the HW structure
*
* Reads the firmware semaphore register and returns true (>0) if
* manageability is enabled, else false (0).
**/
-bool e1000e_check_mng_mode(struct e1000_hw *hw)
+bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
{
u32 fwsm = er32(FWSM);
- return (fwsm & E1000_FWSM_MODE_MASK) == hw->mac.ops.mng_mode_enab;
+ return (fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
}
/**
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index d266510c8a9..abd492b7336 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -47,7 +47,7 @@
#include "e1000.h"
-#define DRV_VERSION "0.3.3.3-k2"
+#define DRV_VERSION "0.3.3.3-k6"
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -55,9 +55,11 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_82571] = &e1000_82571_info,
[board_82572] = &e1000_82572_info,
[board_82573] = &e1000_82573_info,
+ [board_82574] = &e1000_82574_info,
[board_80003es2lan] = &e1000_es2_info,
[board_ich8lan] = &e1000_ich8_info,
[board_ich9lan] = &e1000_ich9_info,
+ [board_ich10lan] = &e1000_ich10_info,
};
#ifdef DEBUG
@@ -1115,6 +1117,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
writel(0, adapter->hw.hw_addr + rx_ring->tail);
}
+static void e1000e_downshift_workaround(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter, downshift_task);
+
+ e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
+}
+
/**
* e1000_intr_msi - Interrupt Handler
* @irq: interrupt number
@@ -1139,7 +1149,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
- e1000e_gig_downshift_workaround_ich8lan(hw);
+ schedule_work(&adapter->downshift_task);
/*
* 80003ES2LAN workaround-- For packet buffer work-around on
@@ -1179,8 +1189,8 @@ static irqreturn_t e1000_intr(int irq, void *data)
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-
u32 rctl, icr = er32(ICR);
+
if (!icr)
return IRQ_NONE; /* Not our interrupt */
@@ -1205,7 +1215,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
- e1000e_gig_downshift_workaround_ich8lan(hw);
+ schedule_work(&adapter->downshift_task);
/*
* 80003ES2LAN workaround--
@@ -1236,6 +1246,263 @@ static irqreturn_t e1000_intr(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t e1000_msix_other(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 icr = er32(ICR);
+
+ if (!(icr & E1000_ICR_INT_ASSERTED)) {
+ ew32(IMS, E1000_IMS_OTHER);
+ return IRQ_NONE;
+ }
+
+ if (icr & adapter->eiac_mask)
+ ew32(ICS, (icr & adapter->eiac_mask));
+
+ if (icr & E1000_ICR_OTHER) {
+ if (!(icr & E1000_ICR_LSC))
+ goto no_link_interrupt;
+ hw->mac.get_link_status = 1;
+ /* guard against interrupt when we're going down */
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+ mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ }
+
+no_link_interrupt:
+ ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
+
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t e1000_intr_msix_tx(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_ring *tx_ring = adapter->tx_ring;
+
+
+ adapter->total_tx_bytes = 0;
+ adapter->total_tx_packets = 0;
+
+ if (!e1000_clean_tx_irq(adapter))
+ /* Ring was not completely cleaned, so fire another interrupt */
+ ew32(ICS, tx_ring->ims_val);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t e1000_intr_msix_rx(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ /* Write the ITR value calculated at the end of the
+ * previous interrupt.
+ */
+ if (adapter->rx_ring->set_itr) {
+ writel(1000000000 / (adapter->rx_ring->itr_val * 256),
+ adapter->hw.hw_addr + adapter->rx_ring->itr_register);
+ adapter->rx_ring->set_itr = 0;
+ }
+
+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+ __netif_rx_schedule(netdev, &adapter->napi);
+ }
+ return IRQ_HANDLED;
+}
+
+/**
+ * e1000_configure_msix - Configure MSI-X hardware
+ *
+ * e1000_configure_msix sets up the hardware to properly
+ * generate MSI-X interrupts.
+ **/
+static void e1000_configure_msix(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_ring *rx_ring = adapter->rx_ring;
+ struct e1000_ring *tx_ring = adapter->tx_ring;
+ int vector = 0;
+ u32 ctrl_ext, ivar = 0;
+
+ adapter->eiac_mask = 0;
+
+ /* Workaround issue with spurious interrupts on 82574 in MSI-X mode */
+ if (hw->mac.type == e1000_82574) {
+ u32 rfctl = er32(RFCTL);
+ rfctl |= E1000_RFCTL_ACK_DIS;
+ ew32(RFCTL, rfctl);
+ }
+
+#define E1000_IVAR_INT_ALLOC_VALID 0x8
+ /* Configure Rx vector */
+ rx_ring->ims_val = E1000_IMS_RXQ0;
+ adapter->eiac_mask |= rx_ring->ims_val;
+ if (rx_ring->itr_val)
+ writel(1000000000 / (rx_ring->itr_val * 256),
+ hw->hw_addr + rx_ring->itr_register);
+ else
+ writel(1, hw->hw_addr + rx_ring->itr_register);
+ ivar = E1000_IVAR_INT_ALLOC_VALID | vector;
+
+ /* Configure Tx vector */
+ tx_ring->ims_val = E1000_IMS_TXQ0;
+ vector++;
+ if (tx_ring->itr_val)
+ writel(1000000000 / (tx_ring->itr_val * 256),
+ hw->hw_addr + tx_ring->itr_register);
+ else
+ writel(1, hw->hw_addr + tx_ring->itr_register);
+ adapter->eiac_mask |= tx_ring->ims_val;
+ ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8);
+
+ /* set vector for Other Causes, e.g. link changes */
+ vector++;
+ ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16);
+ if (rx_ring->itr_val)
+ writel(1000000000 / (rx_ring->itr_val * 256),
+ hw->hw_addr + E1000_EITR_82574(vector));
+ else
+ writel(1, hw->hw_addr + E1000_EITR_82574(vector));
+
+ /* Cause Tx interrupts on every write back */
+ ivar |= (1 << 31);
+
+ ew32(IVAR, ivar);
+
+ /* enable MSI-X PBA support */
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_PBA_CLR;
+
+ /* Auto-Mask Other interrupts upon ICR read */
+#define E1000_EIAC_MASK_82574 0x01F00000
+ ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER);
+ ctrl_ext |= E1000_CTRL_EXT_EIAME;
+ ew32(CTRL_EXT, ctrl_ext);
+ e1e_flush();
+}
+
+void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter)
+{
+ if (adapter->msix_entries) {
+ pci_disable_msix(adapter->pdev);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+ } else if (adapter->flags & FLAG_MSI_ENABLED) {
+ pci_disable_msi(adapter->pdev);
+ adapter->flags &= ~FLAG_MSI_ENABLED;
+ }
+
+ return;
+}
+
+/**
+ * e1000e_set_interrupt_capability - set MSI or MSI-X if supported
+ *
+ * Attempt to configure interrupts using the best available
+ * capabilities of the hardware and kernel.
+ **/
+void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
+{
+ int err;
+ int numvecs, i;
+
+
+ switch (adapter->int_mode) {
+ case E1000E_INT_MODE_MSIX:
+ if (adapter->flags & FLAG_HAS_MSIX) {
+ numvecs = 3; /* RxQ0, TxQ0 and other */
+ adapter->msix_entries = kcalloc(numvecs,
+ sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (adapter->msix_entries) {
+ for (i = 0; i < numvecs; i++)
+ adapter->msix_entries[i].entry = i;
+
+ err = pci_enable_msix(adapter->pdev,
+ adapter->msix_entries,
+ numvecs);
+ if (err == 0)
+ return;
+ }
+ /* MSI-X failed, so fall through and try MSI */
+ e_err("Failed to initialize MSI-X interrupts. "
+ "Falling back to MSI interrupts.\n");
+ e1000e_reset_interrupt_capability(adapter);
+ }
+ adapter->int_mode = E1000E_INT_MODE_MSI;
+ /* Fall through */
+ case E1000E_INT_MODE_MSI:
+ if (!pci_enable_msi(adapter->pdev)) {
+ adapter->flags |= FLAG_MSI_ENABLED;
+ } else {
+ adapter->int_mode = E1000E_INT_MODE_LEGACY;
+ e_err("Failed to initialize MSI interrupts. Falling "
+ "back to legacy interrupts.\n");
+ }
+ /* Fall through */
+ case E1000E_INT_MODE_LEGACY:
+ /* Don't do anything; this is the system default */
+ break;
+ }
+
+ return;
+}
+
+/**
+ * e1000_request_msix - Initialize MSI-X interrupts
+ *
+ * e1000_request_msix allocates MSI-X vectors and requests interrupts from the
+ * kernel.
+ **/
+static int e1000_request_msix(struct e1000_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0, vector = 0;
+
+ if (strlen(netdev->name) < (IFNAMSIZ - 5))
+ sprintf(adapter->rx_ring->name, "%s-rx0", netdev->name);
+ else
+ memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
+ err = request_irq(adapter->msix_entries[vector].vector,
+ &e1000_intr_msix_rx, 0, adapter->rx_ring->name,
+ netdev);
+ if (err)
+ goto out;
+ adapter->rx_ring->itr_register = E1000_EITR_82574(vector);
+ adapter->rx_ring->itr_val = adapter->itr;
+ vector++;
+
+ if (strlen(netdev->name) < (IFNAMSIZ - 5))
+ sprintf(adapter->tx_ring->name, "%s-tx0", netdev->name);
+ else
+ memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
+ err = request_irq(adapter->msix_entries[vector].vector,
+ &e1000_intr_msix_tx, 0, adapter->tx_ring->name,
+ netdev);
+ if (err)
+ goto out;
+ adapter->tx_ring->itr_register = E1000_EITR_82574(vector);
+ adapter->tx_ring->itr_val = adapter->itr;
+ vector++;
+
+ err = request_irq(adapter->msix_entries[vector].vector,
+ &e1000_msix_other, 0, netdev->name, netdev);
+ if (err)
+ goto out;
+
+ e1000_configure_msix(adapter);
+ return 0;
+out:
+ return err;
+}
+
/**
* e1000_request_irq - initialize interrupts
*
@@ -1245,29 +1512,33 @@ static irqreturn_t e1000_intr(int irq, void *data)
static int e1000_request_irq(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int irq_flags = IRQF_SHARED;
int err;
- if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) {
- err = pci_enable_msi(adapter->pdev);
- if (!err) {
- adapter->flags |= FLAG_MSI_ENABLED;
- irq_flags = 0;
- }
+ if (adapter->msix_entries) {
+ err = e1000_request_msix(adapter);
+ if (!err)
+ return err;
+ /* fall back to MSI */
+ e1000e_reset_interrupt_capability(adapter);
+ adapter->int_mode = E1000E_INT_MODE_MSI;
+ e1000e_set_interrupt_capability(adapter);
}
+ if (adapter->flags & FLAG_MSI_ENABLED) {
+ err = request_irq(adapter->pdev->irq, &e1000_intr_msi, 0,
+ netdev->name, netdev);
+ if (!err)
+ return err;
- err = request_irq(adapter->pdev->irq,
- ((adapter->flags & FLAG_MSI_ENABLED) ?
- &e1000_intr_msi : &e1000_intr),
- irq_flags, netdev->name, netdev);
- if (err) {
- if (adapter->flags & FLAG_MSI_ENABLED) {
- pci_disable_msi(adapter->pdev);
- adapter->flags &= ~FLAG_MSI_ENABLED;
- }
- e_err("Unable to allocate interrupt, Error: %d\n", err);
+ /* fall back to legacy interrupt */
+ e1000e_reset_interrupt_capability(adapter);
+ adapter->int_mode = E1000E_INT_MODE_LEGACY;
}
+ err = request_irq(adapter->pdev->irq, &e1000_intr, IRQF_SHARED,
+ netdev->name, netdev);
+ if (err)
+ e_err("Unable to allocate interrupt, Error: %d\n", err);
+
return err;
}
@@ -1275,11 +1546,21 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- free_irq(adapter->pdev->irq, netdev);
- if (adapter->flags & FLAG_MSI_ENABLED) {
- pci_disable_msi(adapter->pdev);
- adapter->flags &= ~FLAG_MSI_ENABLED;
+ if (adapter->msix_entries) {
+ int vector = 0;
+
+ free_irq(adapter->msix_entries[vector].vector, netdev);
+ vector++;
+
+ free_irq(adapter->msix_entries[vector].vector, netdev);
+ vector++;
+
+ /* Other Causes interrupt vector */
+ free_irq(adapter->msix_entries[vector].vector, netdev);
+ return;
}
+
+ free_irq(adapter->pdev->irq, netdev);
}
/**
@@ -1290,6 +1571,8 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
ew32(IMC, ~0);
+ if (adapter->msix_entries)
+ ew32(EIAC_82574, 0);
e1e_flush();
synchronize_irq(adapter->pdev->irq);
}
@@ -1301,7 +1584,12 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- ew32(IMS, IMS_ENABLE_MASK);
+ if (adapter->msix_entries) {
+ ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
+ ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
+ } else {
+ ew32(IMS, IMS_ENABLE_MASK);
+ }
e1e_flush();
}
@@ -1551,9 +1839,8 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter)
* traffic pattern. Constants in this function were computed
* based on theoretical maximum wire speed and thresholds were set based
* on testing data as well as attempting to minimize response time
- * while increasing bulk throughput.
- * this functionality is controlled by the InterruptThrottleRate module
- * parameter (see e1000_param.c)
+ * while increasing bulk throughput. This functionality is controlled
+ * by the InterruptThrottleRate module parameter.
**/
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
u16 itr_setting, int packets,
@@ -1661,11 +1948,37 @@ set_itr_now:
min(adapter->itr + (new_itr >> 2), new_itr) :
new_itr;
adapter->itr = new_itr;
- ew32(ITR, 1000000000 / (new_itr * 256));
+ adapter->rx_ring->itr_val = new_itr;
+ if (adapter->msix_entries)
+ adapter->rx_ring->set_itr = 1;
+ else
+ ew32(ITR, 1000000000 / (new_itr * 256));
}
}
/**
+ * e1000_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ **/
+static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
+{
+ adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ if (!adapter->tx_ring)
+ goto err;
+
+ adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ if (!adapter->rx_ring)
+ goto err;
+
+ return 0;
+err:
+ e_err("Unable to allocate memory for queues\n");
+ kfree(adapter->rx_ring);
+ kfree(adapter->tx_ring);
+ return -ENOMEM;
+}
+
+/**
* e1000_clean - NAPI Rx polling callback
* @napi: struct associated with this polling callback
* @budget: amount of packets driver is allowed to process this poll
@@ -1673,12 +1986,17 @@ set_itr_now:
static int e1000_clean(struct napi_struct *napi, int budget)
{
struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *poll_dev = adapter->netdev;
int tx_cleaned = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */
adapter = poll_dev->priv;
+ if (adapter->msix_entries &&
+ !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
+ goto clean_rx;
+
/*
* e1000_clean is called per-cpu. This lock protects
* tx_ring from being cleaned by multiple cpus
@@ -1690,6 +2008,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
spin_unlock(&adapter->tx_queue_lock);
}
+clean_rx:
adapter->clean_rx(adapter, &work_done, budget);
if (tx_cleaned)
@@ -1700,7 +2019,10 @@ static int e1000_clean(struct napi_struct *napi, int budget)
if (adapter->itr_setting & 3)
e1000_set_itr(adapter);
netif_rx_complete(poll_dev, napi);
- e1000_irq_enable(adapter);
+ if (adapter->msix_entries)
+ ew32(IMS, adapter->rx_ring->ims_val);
+ else
+ e1000_irq_enable(adapter);
}
return work_done;
@@ -2496,6 +2818,8 @@ int e1000e_up(struct e1000_adapter *adapter)
clear_bit(__E1000_DOWN, &adapter->state);
napi_enable(&adapter->napi);
+ if (adapter->msix_entries)
+ e1000_configure_msix(adapter);
e1000_irq_enable(adapter);
/* fire a link change interrupt to start the watchdog */
@@ -2579,29 +2903,18 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
- adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
- if (!adapter->tx_ring)
- goto err;
+ e1000e_set_interrupt_capability(adapter);
- adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
- if (!adapter->rx_ring)
- goto err;
+ if (e1000_alloc_queues(adapter))
+ return -ENOMEM;
spin_lock_init(&adapter->tx_queue_lock);
/* Explicitly disable IRQ since the NIC can be in any state. */
e1000_irq_disable(adapter);
- spin_lock_init(&adapter->stats_lock);
-
set_bit(__E1000_DOWN, &adapter->state);
return 0;
-
-err:
- e_err("Unable to allocate memory for queues\n");
- kfree(adapter->rx_ring);
- kfree(adapter->tx_ring);
- return -ENOMEM;
}
/**
@@ -2643,6 +2956,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
/* free the real vector and request a test handler */
e1000_free_irq(adapter);
+ e1000e_reset_interrupt_capability(adapter);
/* Assume that the test fails, if it succeeds then the test
* MSI irq handler will unset this flag */
@@ -2673,6 +2987,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
rmb();
if (adapter->flags & FLAG_MSI_TEST_FAILED) {
+ adapter->int_mode = E1000E_INT_MODE_LEGACY;
err = -EIO;
e_info("MSI interrupt test failed!\n");
}
@@ -2686,7 +3001,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
/* okay so the test worked, restore settings */
e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name);
msi_test_failed:
- /* restore the original vector, even if it failed */
+ e1000e_set_interrupt_capability(adapter);
e1000_request_irq(adapter);
return err;
}
@@ -2796,7 +3111,7 @@ static int e1000_open(struct net_device *netdev)
* ignore e1000e MSI messages, which means we need to test our MSI
* interrupt now
*/
- {
+ if (adapter->int_mode != E1000E_INT_MODE_LEGACY) {
err = e1000_test_msi(adapter);
if (err) {
e_err("Interrupt allocation failed\n");
@@ -2912,6 +3227,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
return 0;
}
+/**
+ * e1000e_update_phy_task - work thread to update phy
+ * @work: pointer to our work struct
+ *
+ * this worker thread exists because we must acquire a
+ * semaphore to read the phy, which we could msleep while
+ * waiting for it, and we can't msleep in a timer.
+ **/
+static void e1000e_update_phy_task(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter, update_phy_task);
+ e1000_get_phy_info(&adapter->hw);
+}
+
/*
* Need to wait a few seconds after link up to get diagnostic information from
* the phy
@@ -2919,7 +3249,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
static void e1000_update_phy_info(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- e1000_get_phy_info(&adapter->hw);
+ schedule_work(&adapter->update_phy_task);
}
/**
@@ -2930,10 +3260,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
- unsigned long irq_flags;
- u16 phy_tmp;
-
-#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
/*
* Prevent stats update while adapter is being reset, or if the pci
@@ -2944,14 +3270,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
if (pci_channel_offline(pdev))
return;
- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
-
- /*
- * these counters are modified from e1000_adjust_tbi_stats,
- * called from the interrupt context, so they must only
- * be written while holding adapter->stats_lock
- */
-
adapter->stats.crcerrs += er32(CRCERRS);
adapter->stats.gprc += er32(GPRC);
adapter->stats.gorc += er32(GORCL);
@@ -2988,7 +3306,8 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
adapter->stats.algnerrc += er32(ALGNERRC);
adapter->stats.rxerrc += er32(RXERRC);
- adapter->stats.tncrs += er32(TNCRS);
+ if (hw->mac.type != e1000_82574)
+ adapter->stats.tncrs += er32(TNCRS);
adapter->stats.cexterr += er32(CEXTERR);
adapter->stats.tsctc += er32(TSCTC);
adapter->stats.tsctfc += er32(TSCTFC);
@@ -3022,21 +3341,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
/* Tx Dropped needs to be maintained elsewhere */
- /* Phy Stats */
- if (hw->phy.media_type == e1000_media_type_copper) {
- if ((adapter->link_speed == SPEED_1000) &&
- (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) {
- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
- adapter->phy_stats.idle_errors += phy_tmp;
- }
- }
-
/* Management Stats */
adapter->stats.mgptc += er32(MGTPTC);
adapter->stats.mgprc += er32(MGTPRC);
adapter->stats.mgpdc += er32(MGTPDC);
-
- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
}
/**
@@ -3048,10 +3356,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct e1000_phy_regs *phy = &adapter->phy_regs;
int ret_val;
- unsigned long irq_flags;
-
-
- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
if ((er32(STATUS) & E1000_STATUS_LU) &&
(adapter->hw.phy.media_type == e1000_media_type_copper)) {
@@ -3082,8 +3386,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
phy->stat1000 = 0;
phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
}
-
- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
}
static void e1000_print_link_info(struct e1000_adapter *adapter)
@@ -3201,6 +3503,27 @@ static void e1000_watchdog_task(struct work_struct *work)
&adapter->link_duplex);
e1000_print_link_info(adapter);
/*
+ * On supported PHYs, check for duplex mismatch only
+ * if link has autonegotiated at 10/100 half
+ */
+ if ((hw->phy.type == e1000_phy_igp_3 ||
+ hw->phy.type == e1000_phy_bm) &&
+ (hw->mac.autoneg == true) &&
+ (adapter->link_speed == SPEED_10 ||
+ adapter->link_speed == SPEED_100) &&
+ (adapter->link_duplex == HALF_DUPLEX)) {
+ u16 autoneg_exp;
+
+ e1e_rphy(hw, PHY_AUTONEG_EXP, &autoneg_exp);
+
+ if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS))
+ e_info("Autonegotiated half duplex but"
+ " link partner cannot autoneg. "
+ " Try forcing full duplex if "
+ "link gets many collisions.\n");
+ }
+
+ /*
* tweak tx_queue_len according to speed/duplex
* and adjust the timeout factor
*/
@@ -3315,7 +3638,10 @@ link_up:
}
/* Cause software interrupt to ensure Rx ring is cleaned */
- ew32(ICS, E1000_ICS_RXDMT0);
+ if (adapter->msix_entries)
+ ew32(ICS, adapter->rx_ring->ims_val);
+ else
+ ew32(ICS, E1000_ICS_RXDMT0);
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = 1;
@@ -3423,34 +3749,50 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
struct e1000_buffer *buffer_info;
unsigned int i;
u8 css;
+ u32 cmd_len = E1000_TXD_CMD_DEXT;
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- css = skb_transport_offset(skb);
-
- i = tx_ring->next_to_use;
- buffer_info = &tx_ring->buffer_info[i];
- context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
-
- context_desc->lower_setup.ip_config = 0;
- context_desc->upper_setup.tcp_fields.tucss = css;
- context_desc->upper_setup.tcp_fields.tucso =
- css + skb->csum_offset;
- context_desc->upper_setup.tcp_fields.tucse = 0;
- context_desc->tcp_seg_setup.data = 0;
- context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ cmd_len |= E1000_TXD_CMD_TCP;
+ break;
+ case __constant_htons(ETH_P_IPV6):
+ /* XXX not handling all IPV6 headers */
+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+ cmd_len |= E1000_TXD_CMD_TCP;
+ break;
+ default:
+ if (unlikely(net_ratelimit()))
+ e_warn("checksum_partial proto=%x!\n", skb->protocol);
+ break;
+ }
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
+ css = skb_transport_offset(skb);
- return 1;
- }
+ i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+
+ context_desc->lower_setup.ip_config = 0;
+ context_desc->upper_setup.tcp_fields.tucss = css;
+ context_desc->upper_setup.tcp_fields.tucso =
+ css + skb->csum_offset;
+ context_desc->upper_setup.tcp_fields.tucse = 0;
+ context_desc->tcp_seg_setup.data = 0;
+ context_desc->cmd_and_length = cpu_to_le32(cmd_len);
+
+ buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
+
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+ tx_ring->next_to_use = i;
- return 0;
+ return 1;
}
#define E1000_MAX_PER_TXD 8192
@@ -4032,6 +4374,7 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
e1000e_down(adapter);
e1000_free_irq(adapter);
}
+ e1000e_reset_interrupt_capability(adapter);
retval = pci_save_state(pdev);
if (retval)
@@ -4158,6 +4501,7 @@ static int e1000_resume(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
+ e1000e_set_interrupt_capability(adapter);
if (netif_running(netdev)) {
err = e1000_request_irq(adapter);
if (err)
@@ -4335,13 +4679,15 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf);
if (!(le16_to_cpu(buf) & (1 << 0))) {
/* Deep Smart Power Down (DSPD) */
- e_warn("Warning: detected DSPD enabled in EEPROM\n");
+ dev_warn(&adapter->pdev->dev,
+ "Warning: detected DSPD enabled in EEPROM\n");
}
ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf);
if (le16_to_cpu(buf) & (3 << 2)) {
/* ASPM enable */
- e_warn("Warning: detected ASPM enabled in EEPROM\n");
+ dev_warn(&adapter->pdev->dev,
+ "Warning: detected ASPM enabled in EEPROM\n");
}
}
@@ -4467,6 +4813,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->bd_number = cards_found++;
+ e1000e_check_options(adapter);
+
/* setup adapter struct */
err = e1000_sw_init(adapter);
if (err)
@@ -4482,6 +4830,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (err)
goto err_hw_init;
+ if ((adapter->flags & FLAG_IS_ICH) &&
+ (adapter->flags & FLAG_READ_ONLY_NVM))
+ e1000e_write_protect_nvm_ich8lan(&adapter->hw);
+
hw->mac.ops.get_bus_info(&adapter->hw);
adapter->hw.phy.autoneg_wait_to_complete = 0;
@@ -4572,8 +4924,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, e1000_reset_task);
INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
-
- e1000e_check_options(adapter);
+ INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
+ INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
/* Initialize link parameters. User can change them with ethtool */
adapter->hw.mac.autoneg = 1;
@@ -4704,6 +5056,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
if (!e1000_check_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
+ e1000e_reset_interrupt_capability(adapter);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
@@ -4745,6 +5098,8 @@ static struct pci_device_id e1000_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 },
+
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT),
board_80003es2lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT),
@@ -4767,6 +5122,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_AMT), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_C), board_ich9lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_BM), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan },
@@ -4775,6 +5131,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
+
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index ed912e023a7..77a3d7207a5 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -114,6 +114,15 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define DEFAULT_ITR 3
#define MAX_ITR 100000
#define MIN_ITR 100
+/* IntMode (Interrupt Mode)
+ *
+ * Valid Range: 0 - 2
+ *
+ * Default Value: 2 (MSI-X)
+ */
+E1000_PARAM(IntMode, "Interrupt Mode");
+#define MAX_INTMODE 2
+#define MIN_INTMODE 0
/*
* Enable Smart Power Down of the PHY
@@ -133,6 +142,15 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
*/
E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
+/*
+ * Write Protect NVM
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+
struct e1000_option {
enum { enable_option, range_option, list_option } type;
const char *name;
@@ -352,6 +370,24 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
adapter->itr = 20000;
}
}
+ { /* Interrupt Mode */
+ struct e1000_option opt = {
+ .type = range_option,
+ .name = "Interrupt Mode",
+ .err = "defaulting to 2 (MSI-X)",
+ .def = E1000E_INT_MODE_MSIX,
+ .arg = { .r = { .min = MIN_INTMODE,
+ .max = MAX_INTMODE } }
+ };
+
+ if (num_IntMode > bd) {
+ unsigned int int_mode = IntMode[bd];
+ e1000_validate_option(&int_mode, &opt, adapter);
+ adapter->int_mode = int_mode;
+ } else {
+ adapter->int_mode = opt.def;
+ }
+ }
{ /* Smart Power Down */
const struct e1000_option opt = {
.type = enable_option,
@@ -388,4 +424,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
opt.def);
}
}
+ { /* Write-protect NVM */
+ const struct e1000_option opt = {
+ .type = enable_option,
+ .name = "Write-protect NVM",
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
+ };
+
+ if (adapter->flags & FLAG_IS_ICH) {
+ if (num_WriteProtectNVM > bd) {
+ unsigned int write_protect_nvm = WriteProtectNVM[bd];
+ e1000_validate_option(&write_protect_nvm, &opt,
+ adapter);
+ if (write_protect_nvm)
+ adapter->flags |= FLAG_READ_ONLY_NVM;
+ } else {
+ if (opt.def)
+ adapter->flags |= FLAG_READ_ONLY_NVM;
+ }
+ }
+ }
}
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index b133dcf0e95..6cd333ae61d 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -476,7 +476,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) {
+ if ((phy->type == e1000_phy_m88) &&
+ (phy->revision < E1000_REVISION_4) &&
+ (phy->id != BME1000_E_PHY_ID_R2)) {
/*
* Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock.
@@ -504,6 +506,18 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
return ret_val;
}
+ if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
+ /* Set PHY page 0, register 29 to 0x0003 */
+ ret_val = e1e_wphy(hw, 29, 0x0003);
+ if (ret_val)
+ return ret_val;
+
+ /* Set PHY page 0, register 30 to 0x0000 */
+ ret_val = e1e_wphy(hw, 30, 0x0000);
+ if (ret_val)
+ return ret_val;
+ }
+
/* Commit the changes. */
ret_val = e1000e_commit_phy(hw);
if (ret_val)
@@ -1720,6 +1734,91 @@ s32 e1000e_get_cfg_done(struct e1000_hw *hw)
return 0;
}
+/**
+ * e1000e_phy_init_script_igp3 - Inits the IGP3 PHY
+ * @hw: pointer to the HW structure
+ *
+ * Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
+ **/
+s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
+{
+ hw_dbg(hw, "Running IGP 3 PHY init script\n");
+
+ /* PHY init IGP 3 */
+ /* Enable rise/fall, 10-mode work in class-A */
+ e1e_wphy(hw, 0x2F5B, 0x9018);
+ /* Remove all caps from Replica path filter */
+ e1e_wphy(hw, 0x2F52, 0x0000);
+ /* Bias trimming for ADC, AFE and Driver (Default) */
+ e1e_wphy(hw, 0x2FB1, 0x8B24);
+ /* Increase Hybrid poly bias */
+ e1e_wphy(hw, 0x2FB2, 0xF8F0);
+ /* Add 4% to Tx amplitude in Gig mode */
+ e1e_wphy(hw, 0x2010, 0x10B0);
+ /* Disable trimming (TTT) */
+ e1e_wphy(hw, 0x2011, 0x0000);
+ /* Poly DC correction to 94.6% + 2% for all channels */
+ e1e_wphy(hw, 0x20DD, 0x249A);
+ /* ABS DC correction to 95.9% */
+ e1e_wphy(hw, 0x20DE, 0x00D3);
+ /* BG temp curve trim */
+ e1e_wphy(hw, 0x28B4, 0x04CE);
+ /* Increasing ADC OPAMP stage 1 currents to max */
+ e1e_wphy(hw, 0x2F70, 0x29E4);
+ /* Force 1000 ( required for enabling PHY regs configuration) */
+ e1e_wphy(hw, 0x0000, 0x0140);
+ /* Set upd_freq to 6 */
+ e1e_wphy(hw, 0x1F30, 0x1606);
+ /* Disable NPDFE */
+ e1e_wphy(hw, 0x1F31, 0xB814);
+ /* Disable adaptive fixed FFE (Default) */
+ e1e_wphy(hw, 0x1F35, 0x002A);
+ /* Enable FFE hysteresis */
+ e1e_wphy(hw, 0x1F3E, 0x0067);
+ /* Fixed FFE for short cable lengths */
+ e1e_wphy(hw, 0x1F54, 0x0065);
+ /* Fixed FFE for medium cable lengths */
+ e1e_wphy(hw, 0x1F55, 0x002A);
+ /* Fixed FFE for long cable lengths */
+ e1e_wphy(hw, 0x1F56, 0x002A);
+ /* Enable Adaptive Clip Threshold */
+ e1e_wphy(hw, 0x1F72, 0x3FB0);
+ /* AHT reset limit to 1 */
+ e1e_wphy(hw, 0x1F76, 0xC0FF);
+ /* Set AHT master delay to 127 msec */
+ e1e_wphy(hw, 0x1F77, 0x1DEC);
+ /* Set scan bits for AHT */
+ e1e_wphy(hw, 0x1F78, 0xF9EF);
+ /* Set AHT Preset bits */
+ e1e_wphy(hw, 0x1F79, 0x0210);
+ /* Change integ_factor of channel A to 3 */
+ e1e_wphy(hw, 0x1895, 0x0003);
+ /* Change prop_factor of channels BCD to 8 */
+ e1e_wphy(hw, 0x1796, 0x0008);
+ /* Change cg_icount + enable integbp for channels BCD */
+ e1e_wphy(hw, 0x1798, 0xD008);
+ /*
+ * Change cg_icount + enable integbp + change prop_factor_master
+ * to 8 for channel A
+ */
+ e1e_wphy(hw, 0x1898, 0xD918);
+ /* Disable AHT in Slave mode on channel A */
+ e1e_wphy(hw, 0x187A, 0x0800);
+ /*
+ * Enable LPLU and disable AN to 1000 in non-D0a states,
+ * Enable SPD+B2B
+ */
+ e1e_wphy(hw, 0x0019, 0x008D);
+ /* Enable restart AN on an1000_dis change */
+ e1e_wphy(hw, 0x001B, 0x2080);
+ /* Enable wh_fifo read clock in 10/100 modes */
+ e1e_wphy(hw, 0x0014, 0x0045);
+ /* Restart AN, Speed selection is 1000 */
+ e1e_wphy(hw, 0x0000, 0x1340);
+
+ return 0;
+}
+
/* Internal function pointers */
/**
@@ -1969,6 +2068,99 @@ out:
}
/**
+ * e1000e_read_phy_reg_bm2 - Read BM PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore, if necessary, then reads the PHY register at offset
+ * and storing the retrieved information in data. Release any acquired
+ * semaphores before exiting.
+ **/
+s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ s32 ret_val;
+ u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+
+ /* Page 800 works differently than the rest so it has its own func */
+ if (page == BM_WUC_PAGE) {
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+ true);
+ return ret_val;
+ }
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy.addr = 1;
+
+ if (offset > MAX_PHY_MULTI_PAGE_REG) {
+
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+ page);
+
+ if (ret_val) {
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+ }
+ }
+
+ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+ data);
+ hw->phy.ops.release_phy(hw);
+
+ return ret_val;
+}
+
+/**
+ * e1000e_write_phy_reg_bm2 - Write BM PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ s32 ret_val;
+ u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+
+ /* Page 800 works differently than the rest so it has its own func */
+ if (page == BM_WUC_PAGE) {
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+ false);
+ return ret_val;
+ }
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy.addr = 1;
+
+ if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
+ page);
+
+ if (ret_val) {
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+ }
+ }
+
+ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+ data);
+
+ hw->phy.ops.release_phy(hw);
+
+ return ret_val;
+}
+
+/**
* e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 795c594a4b7..b751c1b96cf 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -8,7 +8,7 @@
*
* Many modifications, and currently maintained, by
* Philip Blundell <philb@gnu.org>
- * Added the Compaq LTE Alan Cox <alan@redhat.com>
+ * Added the Compaq LTE Alan Cox <alan@lxorguk.ukuu.org.uk>
* Added MCA support Adam Fritzler
*
* Note - this driver is experimental still - it has problems on faster
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index e01926b7b5b..5524271eedc 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,13 +40,13 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0092"
+#define DRV_VERSION "EHEA_0093"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
#define DLPAR_MEM_ADD 2
#define DLPAR_MEM_REM 4
-#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD)
+#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM)
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 156eb6320b4..2a33a613d9e 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -535,7 +535,7 @@ u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr)
cb_logaddr, /* R5 */
0, 0, 0, 0, 0); /* R6-R10 */
#ifdef DEBUG
- ehea_dmp(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
+ ehea_dump(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
#endif
return hret;
}
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 140f05baafd..db8a9257e68 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -595,7 +595,8 @@ static int ehea_create_busmap_callback(unsigned long pfn,
end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
mr_len = *(unsigned long *)arg;
- ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
+ if (!ehea_bmap)
+ ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
if (!ehea_bmap)
return -ENOMEM;
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index aa0bf6e1c69..e1b441effbb 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -110,7 +110,7 @@ spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
}
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
return ret;
}
@@ -131,7 +131,7 @@ static int spi_write_buf(struct enc28j60_net *priv, int len,
ret = spi_write(priv->spi, priv->spi_transfer_buf, len + 1);
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
}
return ret;
}
@@ -156,7 +156,7 @@ static u8 spi_read_op(struct enc28j60_net *priv, u8 op,
ret = spi_write_then_read(priv->spi, tx_buf, 1, rx_buf, slen);
if (ret)
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
else
val = rx_buf[slen - 1];
@@ -176,14 +176,14 @@ static int spi_write_op(struct enc28j60_net *priv, u8 op,
ret = spi_write(priv->spi, priv->spi_transfer_buf, 2);
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
return ret;
}
static void enc28j60_soft_reset(struct enc28j60_net *priv)
{
if (netif_msg_hw(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
spi_write_op(priv, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
/* Errata workaround #1, CLKRDY check is unreliable,
@@ -357,7 +357,7 @@ static void enc28j60_mem_read(struct enc28j60_net *priv,
reg = nolock_regw_read(priv, ERDPTL);
if (reg != addr)
printk(KERN_DEBUG DRV_NAME ": %s() error writing ERDPT "
- "(0x%04x - 0x%04x)\n", __FUNCTION__, reg, addr);
+ "(0x%04x - 0x%04x)\n", __func__, reg, addr);
}
#endif
spi_read_buf(priv, len, data);
@@ -380,7 +380,7 @@ enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data)
if (reg != TXSTART_INIT)
printk(KERN_DEBUG DRV_NAME
": %s() ERWPT:0x%04x != 0x%04x\n",
- __FUNCTION__, reg, TXSTART_INIT);
+ __func__, reg, TXSTART_INIT);
}
#endif
/* Set the TXND pointer to correspond to the packet size given */
@@ -390,13 +390,13 @@ enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data)
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME
": %s() after control byte ERWPT:0x%04x\n",
- __FUNCTION__, nolock_regw_read(priv, EWRPTL));
+ __func__, nolock_regw_read(priv, EWRPTL));
/* copy the packet into the transmit buffer */
spi_write_buf(priv, len, data);
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME
": %s() after write packet ERWPT:0x%04x, len=%d\n",
- __FUNCTION__, nolock_regw_read(priv, EWRPTL), len);
+ __func__, nolock_regw_read(priv, EWRPTL), len);
mutex_unlock(&priv->lock);
}
@@ -495,7 +495,7 @@ static int enc28j60_set_hw_macaddr(struct net_device *ndev)
if (netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME
": %s() Hardware must be disabled to set "
- "Mac address\n", __FUNCTION__);
+ "Mac address\n", __func__);
ret = -EBUSY;
}
mutex_unlock(&priv->lock);
@@ -575,7 +575,7 @@ static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
if (start > 0x1FFF || end > 0x1FFF || start > end) {
if (netif_msg_drv(priv))
printk(KERN_ERR DRV_NAME ": %s(%d, %d) RXFIFO "
- "bad parameters!\n", __FUNCTION__, start, end);
+ "bad parameters!\n", __func__, start, end);
return;
}
/* set receive buffer start + end */
@@ -591,7 +591,7 @@ static void nolock_txfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
if (start > 0x1FFF || end > 0x1FFF || start > end) {
if (netif_msg_drv(priv))
printk(KERN_ERR DRV_NAME ": %s(%d, %d) TXFIFO "
- "bad parameters!\n", __FUNCTION__, start, end);
+ "bad parameters!\n", __func__, start, end);
return;
}
/* set transmit buffer start + end */
@@ -630,7 +630,7 @@ static int enc28j60_hw_init(struct enc28j60_net *priv)
u8 reg;
if (netif_msg_drv(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() - %s\n", __FUNCTION__,
+ printk(KERN_DEBUG DRV_NAME ": %s() - %s\n", __func__,
priv->full_duplex ? "FullDuplex" : "HalfDuplex");
mutex_lock(&priv->lock);
@@ -661,7 +661,7 @@ static int enc28j60_hw_init(struct enc28j60_net *priv)
if (reg == 0x00 || reg == 0xff) {
if (netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() Invalid RevId %d\n",
- __FUNCTION__, reg);
+ __func__, reg);
return 0;
}
@@ -724,7 +724,7 @@ static void enc28j60_hw_enable(struct enc28j60_net *priv)
/* enable interrupts */
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME ": %s() enabling interrupts.\n",
- __FUNCTION__);
+ __func__);
enc28j60_phy_write(priv, PHIE, PHIE_PGEIE | PHIE_PLNKIE);
@@ -888,7 +888,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
if (netif_msg_rx_err(priv))
dev_err(&ndev->dev,
"%s() Invalid packet address!! 0x%04x\n",
- __FUNCTION__, priv->next_pk_ptr);
+ __func__, priv->next_pk_ptr);
/* packet address corrupted: reset RX logic */
mutex_lock(&priv->lock);
nolock_reg_bfclr(priv, ECON1, ECON1_RXEN);
@@ -917,7 +917,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
rxstat |= rsv[4];
if (netif_msg_rx_status(priv))
- enc28j60_dump_rsv(priv, __FUNCTION__, next_packet, len, rxstat);
+ enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat);
if (!RSV_GETBIT(rxstat, RSV_RXOK)) {
if (netif_msg_rx_err(priv))
@@ -941,7 +941,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
enc28j60_mem_read(priv, priv->next_pk_ptr + sizeof(rsv),
len, skb_put(skb, len));
if (netif_msg_pktdata(priv))
- dump_packet(__FUNCTION__, skb->len, skb->data);
+ dump_packet(__func__, skb->len, skb->data);
skb->protocol = eth_type_trans(skb, ndev);
/* update statistics */
ndev->stats.rx_packets++;
@@ -958,7 +958,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
erxrdpt = erxrdpt_workaround(next_packet, RXSTART_INIT, RXEND_INIT);
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT:0x%04x\n",
- __FUNCTION__, erxrdpt);
+ __func__, erxrdpt);
mutex_lock(&priv->lock);
nolock_regw_write(priv, ERXRDPTL, erxrdpt);
@@ -968,7 +968,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
reg = nolock_regw_read(priv, ERXRDPTL);
if (reg != erxrdpt)
printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT verify "
- "error (0x%04x - 0x%04x)\n", __FUNCTION__,
+ "error (0x%04x - 0x%04x)\n", __func__,
reg, erxrdpt);
}
#endif
@@ -1006,7 +1006,7 @@ static int enc28j60_get_free_rxfifo(struct enc28j60_net *priv)
mutex_unlock(&priv->lock);
if (netif_msg_rx_status(priv))
printk(KERN_DEBUG DRV_NAME ": %s() free_space = %d\n",
- __FUNCTION__, free_space);
+ __func__, free_space);
return free_space;
}
@@ -1022,7 +1022,7 @@ static void enc28j60_check_link_status(struct net_device *ndev)
reg = enc28j60_phy_read(priv, PHSTAT2);
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME ": %s() PHSTAT1: %04x, "
- "PHSTAT2: %04x\n", __FUNCTION__,
+ "PHSTAT2: %04x\n", __func__,
enc28j60_phy_read(priv, PHSTAT1), reg);
duplex = reg & PHSTAT2_DPXSTAT;
@@ -1095,7 +1095,7 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
int intflags, loop;
if (netif_msg_intr(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
/* disable further interrupts */
locked_reg_bfclr(priv, EIE, EIE_INTIE);
@@ -1198,7 +1198,7 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
/* re-enable interrupts */
locked_reg_bfset(priv, EIE, EIE_INTIE);
if (netif_msg_intr(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __func__);
}
/*
@@ -1213,7 +1213,7 @@ static void enc28j60_hw_tx(struct enc28j60_net *priv)
": Tx Packet Len:%d\n", priv->tx_skb->len);
if (netif_msg_pktdata(priv))
- dump_packet(__FUNCTION__,
+ dump_packet(__func__,
priv->tx_skb->len, priv->tx_skb->data);
enc28j60_packet_write(priv, priv->tx_skb->len, priv->tx_skb->data);
@@ -1254,7 +1254,7 @@ static int enc28j60_send_packet(struct sk_buff *skb, struct net_device *dev)
struct enc28j60_net *priv = netdev_priv(dev);
if (netif_msg_tx_queued(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
/* If some error occurs while trying to transmit this
* packet, you should return '1' from this function.
@@ -1325,7 +1325,7 @@ static int enc28j60_net_open(struct net_device *dev)
struct enc28j60_net *priv = netdev_priv(dev);
if (netif_msg_drv(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
if (!is_valid_ether_addr(dev->dev_addr)) {
if (netif_msg_ifup(priv)) {
@@ -1363,7 +1363,7 @@ static int enc28j60_net_close(struct net_device *dev)
struct enc28j60_net *priv = netdev_priv(dev);
if (netif_msg_drv(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__);
+ printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
enc28j60_hw_disable(priv);
enc28j60_lowpower(priv, true);
diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile
new file mode 100644
index 00000000000..391c3bce5b7
--- /dev/null
+++ b/drivers/net/enic/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_ENIC) := enic.o
+
+enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
+ enic_res.o vnic_dev.o vnic_rq.o
+
diff --git a/drivers/net/enic/cq_desc.h b/drivers/net/enic/cq_desc.h
new file mode 100644
index 00000000000..c036a8bfd04
--- /dev/null
+++ b/drivers/net/enic/cq_desc.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _CQ_DESC_H_
+#define _CQ_DESC_H_
+
+/*
+ * Completion queue descriptor types
+ */
+enum cq_desc_types {
+ CQ_DESC_TYPE_WQ_ENET = 0,
+ CQ_DESC_TYPE_DESC_COPY = 1,
+ CQ_DESC_TYPE_WQ_EXCH = 2,
+ CQ_DESC_TYPE_RQ_ENET = 3,
+ CQ_DESC_TYPE_RQ_FCP = 4,
+};
+
+/* Completion queue descriptor: 16B
+ *
+ * All completion queues have this basic layout. The
+ * type_specfic area is unique for each completion
+ * queue type.
+ */
+struct cq_desc {
+ __le16 completed_index;
+ __le16 q_number;
+ u8 type_specfic[11];
+ u8 type_color;
+};
+
+#define CQ_DESC_TYPE_BITS 7
+#define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1)
+#define CQ_DESC_COLOR_MASK 1
+#define CQ_DESC_Q_NUM_BITS 10
+#define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1)
+#define CQ_DESC_COMP_NDX_BITS 12
+#define CQ_DESC_COMP_NDX_MASK ((1 << CQ_DESC_COMP_NDX_BITS) - 1)
+
+static inline void cq_desc_dec(const struct cq_desc *desc_arg,
+ u8 *type, u8 *color, u16 *q_number, u16 *completed_index)
+{
+ const struct cq_desc *desc = desc_arg;
+ const u8 type_color = desc->type_color;
+
+ *color = (type_color >> CQ_DESC_TYPE_BITS) & CQ_DESC_COLOR_MASK;
+
+ /*
+ * Make sure color bit is read from desc *before* other fields
+ * are read from desc. Hardware guarantees color bit is last
+ * bit (byte) written. Adding the rmb() prevents the compiler
+ * and/or CPU from reordering the reads which would potentially
+ * result in reading stale values.
+ */
+
+ rmb();
+
+ *type = type_color & CQ_DESC_TYPE_MASK;
+ *q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK;
+ *completed_index = le16_to_cpu(desc->completed_index) &
+ CQ_DESC_COMP_NDX_MASK;
+}
+
+#endif /* _CQ_DESC_H_ */
diff --git a/drivers/net/enic/cq_enet_desc.h b/drivers/net/enic/cq_enet_desc.h
new file mode 100644
index 00000000000..03dce9ed612
--- /dev/null
+++ b/drivers/net/enic/cq_enet_desc.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _CQ_ENET_DESC_H_
+#define _CQ_ENET_DESC_H_
+
+#include "cq_desc.h"
+
+/* Ethernet completion queue descriptor: 16B */
+struct cq_enet_wq_desc {
+ __le16 completed_index;
+ __le16 q_number;
+ u8 reserved[11];
+ u8 type_color;
+};
+
+static inline void cq_enet_wq_desc_dec(struct cq_enet_wq_desc *desc,
+ u8 *type, u8 *color, u16 *q_number, u16 *completed_index)
+{
+ cq_desc_dec((struct cq_desc *)desc, type,
+ color, q_number, completed_index);
+}
+
+/* Completion queue descriptor: Ethernet receive queue, 16B */
+struct cq_enet_rq_desc {
+ __le16 completed_index_flags;
+ __le16 q_number_rss_type_flags;
+ __le32 rss_hash;
+ __le16 bytes_written_flags;
+ __le16 vlan;
+ __le16 checksum_fcoe;
+ u8 flags;
+ u8 type_color;
+};
+
+#define CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT (0x1 << 12)
+#define CQ_ENET_RQ_DESC_FLAGS_FCOE (0x1 << 13)
+#define CQ_ENET_RQ_DESC_FLAGS_EOP (0x1 << 14)
+#define CQ_ENET_RQ_DESC_FLAGS_SOP (0x1 << 15)
+
+#define CQ_ENET_RQ_DESC_RSS_TYPE_BITS 4
+#define CQ_ENET_RQ_DESC_RSS_TYPE_MASK \
+ ((1 << CQ_ENET_RQ_DESC_RSS_TYPE_BITS) - 1)
+#define CQ_ENET_RQ_DESC_RSS_TYPE_NONE 0
+#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 1
+#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 2
+#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 3
+#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 4
+#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX 5
+#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX 6
+
+#define CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC (0x1 << 14)
+
+#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS 14
+#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK \
+ ((1 << CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS) - 1)
+#define CQ_ENET_RQ_DESC_FLAGS_TRUNCATED (0x1 << 14)
+#define CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED (0x1 << 15)
+
+#define CQ_ENET_RQ_DESC_FCOE_SOF_BITS 4
+#define CQ_ENET_RQ_DESC_FCOE_SOF_MASK \
+ ((1 << CQ_ENET_RQ_DESC_FCOE_SOF_BITS) - 1)
+#define CQ_ENET_RQ_DESC_FCOE_EOF_BITS 8
+#define CQ_ENET_RQ_DESC_FCOE_EOF_MASK \
+ ((1 << CQ_ENET_RQ_DESC_FCOE_EOF_BITS) - 1)
+#define CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT 8
+
+#define CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK (0x1 << 0)
+#define CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK (0x1 << 0)
+#define CQ_ENET_RQ_DESC_FLAGS_UDP (0x1 << 1)
+#define CQ_ENET_RQ_DESC_FCOE_ENC_ERROR (0x1 << 1)
+#define CQ_ENET_RQ_DESC_FLAGS_TCP (0x1 << 2)
+#define CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK (0x1 << 3)
+#define CQ_ENET_RQ_DESC_FLAGS_IPV6 (0x1 << 4)
+#define CQ_ENET_RQ_DESC_FLAGS_IPV4 (0x1 << 5)
+#define CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT (0x1 << 6)
+#define CQ_ENET_RQ_DESC_FLAGS_FCS_OK (0x1 << 7)
+
+static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc,
+ u8 *type, u8 *color, u16 *q_number, u16 *completed_index,
+ u8 *ingress_port, u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type,
+ u8 *csum_not_calc, u32 *rss_hash, u16 *bytes_written, u8 *packet_error,
+ u8 *vlan_stripped, u16 *vlan, u16 *checksum, u8 *fcoe_sof,
+ u8 *fcoe_fc_crc_ok, u8 *fcoe_enc_error, u8 *fcoe_eof,
+ u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok,
+ u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok)
+{
+ u16 completed_index_flags = le16_to_cpu(desc->completed_index_flags);
+ u16 q_number_rss_type_flags =
+ le16_to_cpu(desc->q_number_rss_type_flags);
+ u16 bytes_written_flags = le16_to_cpu(desc->bytes_written_flags);
+
+ cq_desc_dec((struct cq_desc *)desc, type,
+ color, q_number, completed_index);
+
+ *ingress_port = (completed_index_flags &
+ CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0;
+ *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ?
+ 1 : 0;
+ *eop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_EOP) ?
+ 1 : 0;
+ *sop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_SOP) ?
+ 1 : 0;
+
+ *rss_type = (u8)((q_number_rss_type_flags >> CQ_DESC_Q_NUM_BITS) &
+ CQ_ENET_RQ_DESC_RSS_TYPE_MASK);
+ *csum_not_calc = (q_number_rss_type_flags &
+ CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ? 1 : 0;
+
+ *rss_hash = le32_to_cpu(desc->rss_hash);
+
+ *bytes_written = bytes_written_flags &
+ CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
+ *packet_error = (bytes_written_flags &
+ CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ? 1 : 0;
+ *vlan_stripped = (bytes_written_flags &
+ CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) ? 1 : 0;
+
+ *vlan = le16_to_cpu(desc->vlan);
+
+ if (*fcoe) {
+ *fcoe_sof = (u8)(le16_to_cpu(desc->checksum_fcoe) &
+ CQ_ENET_RQ_DESC_FCOE_SOF_MASK);
+ *fcoe_fc_crc_ok = (desc->flags &
+ CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK) ? 1 : 0;
+ *fcoe_enc_error = (desc->flags &
+ CQ_ENET_RQ_DESC_FCOE_ENC_ERROR) ? 1 : 0;
+ *fcoe_eof = (u8)((desc->checksum_fcoe >>
+ CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT) &
+ CQ_ENET_RQ_DESC_FCOE_EOF_MASK);
+ *checksum = 0;
+ } else {
+ *fcoe_sof = 0;
+ *fcoe_fc_crc_ok = 0;
+ *fcoe_enc_error = 0;
+ *fcoe_eof = 0;
+ *checksum = le16_to_cpu(desc->checksum_fcoe);
+ }
+
+ *tcp_udp_csum_ok =
+ (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ? 1 : 0;
+ *udp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_UDP) ? 1 : 0;
+ *tcp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP) ? 1 : 0;
+ *ipv4_csum_ok =
+ (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ? 1 : 0;
+ *ipv6 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV6) ? 1 : 0;
+ *ipv4 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4) ? 1 : 0;
+ *ipv4_fragment =
+ (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT) ? 1 : 0;
+ *fcs_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ? 1 : 0;
+}
+
+#endif /* _CQ_ENET_DESC_H_ */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
new file mode 100644
index 00000000000..7f677e89a78
--- /dev/null
+++ b/drivers/net/enic/enic.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _ENIC_H_
+#define _ENIC_H_
+
+#include <linux/inet_lro.h>
+
+#include "vnic_enet.h"
+#include "vnic_dev.h"
+#include "vnic_wq.h"
+#include "vnic_rq.h"
+#include "vnic_cq.h"
+#include "vnic_intr.h"
+#include "vnic_stats.h"
+#include "vnic_rss.h"
+
+#define DRV_NAME "enic"
+#define DRV_DESCRIPTION "Cisco 10G Ethernet Driver"
+#define DRV_VERSION "0.0.1-18163.472-k1"
+#define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc"
+#define PFX DRV_NAME ": "
+
+#define ENIC_LRO_MAX_DESC 8
+#define ENIC_LRO_MAX_AGGR 64
+
+enum enic_cq_index {
+ ENIC_CQ_RQ,
+ ENIC_CQ_WQ,
+ ENIC_CQ_MAX,
+};
+
+enum enic_intx_intr_index {
+ ENIC_INTX_WQ_RQ,
+ ENIC_INTX_ERR,
+ ENIC_INTX_NOTIFY,
+ ENIC_INTX_MAX,
+};
+
+enum enic_msix_intr_index {
+ ENIC_MSIX_RQ,
+ ENIC_MSIX_WQ,
+ ENIC_MSIX_ERR,
+ ENIC_MSIX_NOTIFY,
+ ENIC_MSIX_MAX,
+};
+
+struct enic_msix_entry {
+ int requested;
+ char devname[IFNAMSIZ];
+ irqreturn_t (*isr)(int, void *);
+ void *devid;
+};
+
+/* Per-instance private data structure */
+struct enic {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct vnic_enet_config config;
+ struct vnic_dev_bar bar0;
+ struct vnic_dev *vdev;
+ struct timer_list notify_timer;
+ struct work_struct reset;
+ struct msix_entry msix_entry[ENIC_MSIX_MAX];
+ struct enic_msix_entry msix[ENIC_MSIX_MAX];
+ u32 msg_enable;
+ spinlock_t devcmd_lock;
+ u8 mac_addr[ETH_ALEN];
+ u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
+ unsigned int mc_count;
+ int csum_rx_enabled;
+ u32 port_mtu;
+
+ /* work queue cache line section */
+ ____cacheline_aligned struct vnic_wq wq[1];
+ spinlock_t wq_lock[1];
+ unsigned int wq_count;
+ struct vlan_group *vlan_group;
+
+ /* receive queue cache line section */
+ ____cacheline_aligned struct vnic_rq rq[1];
+ unsigned int rq_count;
+ int (*rq_alloc_buf)(struct vnic_rq *rq);
+ struct napi_struct napi;
+ struct net_lro_mgr lro_mgr;
+ struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC];
+
+ /* interrupt resource cache line section */
+ ____cacheline_aligned struct vnic_intr intr[ENIC_MSIX_MAX];
+ unsigned int intr_count;
+ u32 __iomem *legacy_pba; /* memory-mapped */
+
+ /* completion queue cache line section */
+ ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
+ unsigned int cq_count;
+};
+
+#endif /* _ENIC_H_ */
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
new file mode 100644
index 00000000000..180e968dc54
--- /dev/null
+++ b/drivers/net/enic/enic_main.c
@@ -0,0 +1,1935 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/ethtool.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <net/ip6_checksum.h>
+
+#include "cq_enet_desc.h"
+#include "vnic_dev.h"
+#include "vnic_intr.h"
+#include "vnic_stats.h"
+#include "enic_res.h"
+#include "enic.h"
+
+#define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ)
+
+/* Supported devices */
+static struct pci_device_id enic_id_table[] = {
+ { PCI_VDEVICE(CISCO, 0x0043) },
+ { 0, } /* end of table */
+};
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("Scott Feldman <scofeldm@cisco.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DEVICE_TABLE(pci, enic_id_table);
+
+struct enic_stat {
+ char name[ETH_GSTRING_LEN];
+ unsigned int offset;
+};
+
+#define ENIC_TX_STAT(stat) \
+ { .name = #stat, .offset = offsetof(struct vnic_tx_stats, stat) / 8 }
+#define ENIC_RX_STAT(stat) \
+ { .name = #stat, .offset = offsetof(struct vnic_rx_stats, stat) / 8 }
+
+static const struct enic_stat enic_tx_stats[] = {
+ ENIC_TX_STAT(tx_frames_ok),
+ ENIC_TX_STAT(tx_unicast_frames_ok),
+ ENIC_TX_STAT(tx_multicast_frames_ok),
+ ENIC_TX_STAT(tx_broadcast_frames_ok),
+ ENIC_TX_STAT(tx_bytes_ok),
+ ENIC_TX_STAT(tx_unicast_bytes_ok),
+ ENIC_TX_STAT(tx_multicast_bytes_ok),
+ ENIC_TX_STAT(tx_broadcast_bytes_ok),
+ ENIC_TX_STAT(tx_drops),
+ ENIC_TX_STAT(tx_errors),
+ ENIC_TX_STAT(tx_tso),
+};
+
+static const struct enic_stat enic_rx_stats[] = {
+ ENIC_RX_STAT(rx_frames_ok),
+ ENIC_RX_STAT(rx_frames_total),
+ ENIC_RX_STAT(rx_unicast_frames_ok),
+ ENIC_RX_STAT(rx_multicast_frames_ok),
+ ENIC_RX_STAT(rx_broadcast_frames_ok),
+ ENIC_RX_STAT(rx_bytes_ok),
+ ENIC_RX_STAT(rx_unicast_bytes_ok),
+ ENIC_RX_STAT(rx_multicast_bytes_ok),
+ ENIC_RX_STAT(rx_broadcast_bytes_ok),
+ ENIC_RX_STAT(rx_drop),
+ ENIC_RX_STAT(rx_no_bufs),
+ ENIC_RX_STAT(rx_errors),
+ ENIC_RX_STAT(rx_rss),
+ ENIC_RX_STAT(rx_crc_errors),
+ ENIC_RX_STAT(rx_frames_64),
+ ENIC_RX_STAT(rx_frames_127),
+ ENIC_RX_STAT(rx_frames_255),
+ ENIC_RX_STAT(rx_frames_511),
+ ENIC_RX_STAT(rx_frames_1023),
+ ENIC_RX_STAT(rx_frames_1518),
+ ENIC_RX_STAT(rx_frames_to_max),
+};
+
+static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
+static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
+
+static int enic_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+ ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+ ecmd->port = PORT_FIBRE;
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ if (netif_carrier_ok(netdev)) {
+ ecmd->speed = vnic_dev_port_speed(enic->vdev);
+ ecmd->duplex = DUPLEX_FULL;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ return 0;
+}
+
+static void enic_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_devcmd_fw_info *fw_info;
+
+ spin_lock(&enic->devcmd_lock);
+ vnic_dev_fw_info(enic->vdev, &fw_info);
+ spin_unlock(&enic->devcmd_lock);
+
+ strncpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+ strncpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
+ strncpy(drvinfo->fw_version, fw_info->fw_version,
+ sizeof(drvinfo->fw_version));
+ strncpy(drvinfo->bus_info, pci_name(enic->pdev),
+ sizeof(drvinfo->bus_info));
+}
+
+static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+ unsigned int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < enic_n_tx_stats; i++) {
+ memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
+ data += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < enic_n_rx_stats; i++) {
+ memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
+ data += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+}
+
+static int enic_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return enic_n_tx_stats + enic_n_rx_stats;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void enic_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_stats *vstats;
+ unsigned int i;
+
+ spin_lock(&enic->devcmd_lock);
+ vnic_dev_stats_dump(enic->vdev, &vstats);
+ spin_unlock(&enic->devcmd_lock);
+
+ for (i = 0; i < enic_n_tx_stats; i++)
+ *(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].offset];
+ for (i = 0; i < enic_n_rx_stats; i++)
+ *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset];
+}
+
+static u32 enic_get_rx_csum(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ return enic->csum_rx_enabled;
+}
+
+static int enic_set_rx_csum(struct net_device *netdev, u32 data)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ if (data && !ENIC_SETTING(enic, RXCSUM))
+ return -EINVAL;
+
+ enic->csum_rx_enabled = !!data;
+
+ return 0;
+}
+
+static int enic_set_tx_csum(struct net_device *netdev, u32 data)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ if (data && !ENIC_SETTING(enic, TXCSUM))
+ return -EINVAL;
+
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
+static int enic_set_tso(struct net_device *netdev, u32 data)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ if (data && !ENIC_SETTING(enic, TSO))
+ return -EINVAL;
+
+ if (data)
+ netdev->features |=
+ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+ else
+ netdev->features &=
+ ~(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN);
+
+ return 0;
+}
+
+static u32 enic_get_msglevel(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ return enic->msg_enable;
+}
+
+static void enic_set_msglevel(struct net_device *netdev, u32 value)
+{
+ struct enic *enic = netdev_priv(netdev);
+ enic->msg_enable = value;
+}
+
+static struct ethtool_ops enic_ethtool_ops = {
+ .get_settings = enic_get_settings,
+ .get_drvinfo = enic_get_drvinfo,
+ .get_msglevel = enic_get_msglevel,
+ .set_msglevel = enic_set_msglevel,
+ .get_link = ethtool_op_get_link,
+ .get_strings = enic_get_strings,
+ .get_sset_count = enic_get_sset_count,
+ .get_ethtool_stats = enic_get_ethtool_stats,
+ .get_rx_csum = enic_get_rx_csum,
+ .set_rx_csum = enic_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = enic_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = enic_set_tso,
+};
+
+static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
+{
+ struct enic *enic = vnic_dev_priv(wq->vdev);
+
+ if (buf->sop)
+ pci_unmap_single(enic->pdev, buf->dma_addr,
+ buf->len, PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(enic->pdev, buf->dma_addr,
+ buf->len, PCI_DMA_TODEVICE);
+
+ if (buf->os_buf)
+ dev_kfree_skb_any(buf->os_buf);
+}
+
+static void enic_wq_free_buf(struct vnic_wq *wq,
+ struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque)
+{
+ enic_free_wq_buf(wq, buf);
+}
+
+static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
+ u8 type, u16 q_number, u16 completed_index, void *opaque)
+{
+ struct enic *enic = vnic_dev_priv(vdev);
+
+ spin_lock(&enic->wq_lock[q_number]);
+
+ vnic_wq_service(&enic->wq[q_number], cq_desc,
+ completed_index, enic_wq_free_buf,
+ opaque);
+
+ if (netif_queue_stopped(enic->netdev) &&
+ vnic_wq_desc_avail(&enic->wq[q_number]) >= MAX_SKB_FRAGS + 1)
+ netif_wake_queue(enic->netdev);
+
+ spin_unlock(&enic->wq_lock[q_number]);
+
+ return 0;
+}
+
+static void enic_log_q_error(struct enic *enic)
+{
+ unsigned int i;
+ u32 error_status;
+
+ for (i = 0; i < enic->wq_count; i++) {
+ error_status = vnic_wq_error_status(&enic->wq[i]);
+ if (error_status)
+ printk(KERN_ERR PFX "%s: WQ[%d] error_status %d\n",
+ enic->netdev->name, i, error_status);
+ }
+
+ for (i = 0; i < enic->rq_count; i++) {
+ error_status = vnic_rq_error_status(&enic->rq[i]);
+ if (error_status)
+ printk(KERN_ERR PFX "%s: RQ[%d] error_status %d\n",
+ enic->netdev->name, i, error_status);
+ }
+}
+
+static void enic_link_check(struct enic *enic)
+{
+ int link_status = vnic_dev_link_status(enic->vdev);
+ int carrier_ok = netif_carrier_ok(enic->netdev);
+
+ if (link_status && !carrier_ok) {
+ printk(KERN_INFO PFX "%s: Link UP\n", enic->netdev->name);
+ netif_carrier_on(enic->netdev);
+ } else if (!link_status && carrier_ok) {
+ printk(KERN_INFO PFX "%s: Link DOWN\n", enic->netdev->name);
+ netif_carrier_off(enic->netdev);
+ }
+}
+
+static void enic_mtu_check(struct enic *enic)
+{
+ u32 mtu = vnic_dev_mtu(enic->vdev);
+
+ if (mtu != enic->port_mtu) {
+ if (mtu < enic->netdev->mtu)
+ printk(KERN_WARNING PFX
+ "%s: interface MTU (%d) set higher "
+ "than switch port MTU (%d)\n",
+ enic->netdev->name, enic->netdev->mtu, mtu);
+ enic->port_mtu = mtu;
+ }
+}
+
+static void enic_msglvl_check(struct enic *enic)
+{
+ u32 msg_enable = vnic_dev_msg_lvl(enic->vdev);
+
+ if (msg_enable != enic->msg_enable) {
+ printk(KERN_INFO PFX "%s: msg lvl changed from 0x%x to 0x%x\n",
+ enic->netdev->name, enic->msg_enable, msg_enable);
+ enic->msg_enable = msg_enable;
+ }
+}
+
+static void enic_notify_check(struct enic *enic)
+{
+ enic_msglvl_check(enic);
+ enic_mtu_check(enic);
+ enic_link_check(enic);
+}
+
+#define ENIC_TEST_INTR(pba, i) (pba & (1 << i))
+
+static irqreturn_t enic_isr_legacy(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct enic *enic = netdev_priv(netdev);
+ u32 pba;
+
+ vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]);
+
+ pba = vnic_intr_legacy_pba(enic->legacy_pba);
+ if (!pba) {
+ vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ return IRQ_NONE; /* not our interrupt */
+ }
+
+ if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY))
+ enic_notify_check(enic);
+
+ if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) {
+ enic_log_q_error(enic);
+ /* schedule recovery from WQ/RQ error */
+ schedule_work(&enic->reset);
+ return IRQ_HANDLED;
+ }
+
+ if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) {
+ if (netif_rx_schedule_prep(netdev, &enic->napi))
+ __netif_rx_schedule(netdev, &enic->napi);
+ } else {
+ vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t enic_isr_msi(int irq, void *data)
+{
+ struct enic *enic = data;
+
+ /* With MSI, there is no sharing of interrupts, so this is
+ * our interrupt and there is no need to ack it. The device
+ * is not providing per-vector masking, so the OS will not
+ * write to PCI config space to mask/unmask the interrupt.
+ * We're using mask_on_assertion for MSI, so the device
+ * automatically masks the interrupt when the interrupt is
+ * generated. Later, when exiting polling, the interrupt
+ * will be unmasked (see enic_poll).
+ *
+ * Also, the device uses the same PCIe Traffic Class (TC)
+ * for Memory Write data and MSI, so there are no ordering
+ * issues; the MSI will always arrive at the Root Complex
+ * _after_ corresponding Memory Writes (i.e. descriptor
+ * writes).
+ */
+
+ netif_rx_schedule(enic->netdev, &enic->napi);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t enic_isr_msix_rq(int irq, void *data)
+{
+ struct enic *enic = data;
+
+ /* schedule NAPI polling for RQ cleanup */
+ netif_rx_schedule(enic->netdev, &enic->napi);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t enic_isr_msix_wq(int irq, void *data)
+{
+ struct enic *enic = data;
+ unsigned int wq_work_to_do = -1; /* no limit */
+ unsigned int wq_work_done;
+
+ wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+ wq_work_to_do, enic_wq_service, NULL);
+
+ vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ],
+ wq_work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t enic_isr_msix_err(int irq, void *data)
+{
+ struct enic *enic = data;
+
+ enic_log_q_error(enic);
+
+ /* schedule recovery from WQ/RQ error */
+ schedule_work(&enic->reset);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t enic_isr_msix_notify(int irq, void *data)
+{
+ struct enic *enic = data;
+
+ enic_notify_check(enic);
+ vnic_intr_unmask(&enic->intr[ENIC_MSIX_NOTIFY]);
+
+ return IRQ_HANDLED;
+}
+
+static inline void enic_queue_wq_skb_cont(struct enic *enic,
+ struct vnic_wq *wq, struct sk_buff *skb,
+ unsigned int len_left)
+{
+ skb_frag_t *frag;
+
+ /* Queue additional data fragments */
+ for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
+ len_left -= frag->size;
+ enic_queue_wq_desc_cont(wq, skb,
+ pci_map_page(enic->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE),
+ frag->size,
+ (len_left == 0)); /* EOP? */
+ }
+}
+
+static inline void enic_queue_wq_skb_vlan(struct enic *enic,
+ struct vnic_wq *wq, struct sk_buff *skb,
+ int vlan_tag_insert, unsigned int vlan_tag)
+{
+ unsigned int head_len = skb_headlen(skb);
+ unsigned int len_left = skb->len - head_len;
+ int eop = (len_left == 0);
+
+ /* Queue the main skb fragment */
+ enic_queue_wq_desc(wq, skb,
+ pci_map_single(enic->pdev, skb->data,
+ head_len, PCI_DMA_TODEVICE),
+ head_len,
+ vlan_tag_insert, vlan_tag,
+ eop);
+
+ if (!eop)
+ enic_queue_wq_skb_cont(enic, wq, skb, len_left);
+}
+
+static inline void enic_queue_wq_skb_csum_l4(struct enic *enic,
+ struct vnic_wq *wq, struct sk_buff *skb,
+ int vlan_tag_insert, unsigned int vlan_tag)
+{
+ unsigned int head_len = skb_headlen(skb);
+ unsigned int len_left = skb->len - head_len;
+ unsigned int hdr_len = skb_transport_offset(skb);
+ unsigned int csum_offset = hdr_len + skb->csum_offset;
+ int eop = (len_left == 0);
+
+ /* Queue the main skb fragment */
+ enic_queue_wq_desc_csum_l4(wq, skb,
+ pci_map_single(enic->pdev, skb->data,
+ head_len, PCI_DMA_TODEVICE),
+ head_len,
+ csum_offset,
+ hdr_len,
+ vlan_tag_insert, vlan_tag,
+ eop);
+
+ if (!eop)
+ enic_queue_wq_skb_cont(enic, wq, skb, len_left);
+}
+
+static inline void enic_queue_wq_skb_tso(struct enic *enic,
+ struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss,
+ int vlan_tag_insert, unsigned int vlan_tag)
+{
+ unsigned int head_len = skb_headlen(skb);
+ unsigned int len_left = skb->len - head_len;
+ unsigned int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ int eop = (len_left == 0);
+
+ /* Preload TCP csum field with IP pseudo hdr calculated
+ * with IP length set to zero. HW will later add in length
+ * to each TCP segment resulting from the TSO.
+ */
+
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ ip_hdr(skb)->check = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
+ } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
+ }
+
+ /* Queue the main skb fragment */
+ enic_queue_wq_desc_tso(wq, skb,
+ pci_map_single(enic->pdev, skb->data,
+ head_len, PCI_DMA_TODEVICE),
+ head_len,
+ mss, hdr_len,
+ vlan_tag_insert, vlan_tag,
+ eop);
+
+ if (!eop)
+ enic_queue_wq_skb_cont(enic, wq, skb, len_left);
+}
+
+static inline void enic_queue_wq_skb(struct enic *enic,
+ struct vnic_wq *wq, struct sk_buff *skb)
+{
+ unsigned int mss = skb_shinfo(skb)->gso_size;
+ unsigned int vlan_tag = 0;
+ int vlan_tag_insert = 0;
+
+ if (enic->vlan_group && vlan_tx_tag_present(skb)) {
+ /* VLAN tag from trunking driver */
+ vlan_tag_insert = 1;
+ vlan_tag = vlan_tx_tag_get(skb);
+ }
+
+ if (mss)
+ enic_queue_wq_skb_tso(enic, wq, skb, mss,
+ vlan_tag_insert, vlan_tag);
+ else if (skb->ip_summed == CHECKSUM_PARTIAL)
+ enic_queue_wq_skb_csum_l4(enic, wq, skb,
+ vlan_tag_insert, vlan_tag);
+ else
+ enic_queue_wq_skb_vlan(enic, wq, skb,
+ vlan_tag_insert, vlan_tag);
+}
+
+/* netif_tx_lock held, process context with BHs disabled */
+static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_wq *wq = &enic->wq[0];
+ unsigned long flags;
+
+ if (skb->len <= 0) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ /* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs,
+ * which is very likely. In the off chance it's going to take
+ * more than * ENIC_NON_TSO_MAX_DESC, linearize the skb.
+ */
+
+ if (skb_shinfo(skb)->gso_size == 0 &&
+ skb_shinfo(skb)->nr_frags + 1 > ENIC_NON_TSO_MAX_DESC &&
+ skb_linearize(skb)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ spin_lock_irqsave(&enic->wq_lock[0], flags);
+
+ if (vnic_wq_desc_avail(wq) < skb_shinfo(skb)->nr_frags + 1) {
+ netif_stop_queue(netdev);
+ /* This is a hard error, log it */
+ printk(KERN_ERR PFX "%s: BUG! Tx ring full when "
+ "queue awake!\n", netdev->name);
+ spin_unlock_irqrestore(&enic->wq_lock[0], flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ enic_queue_wq_skb(enic, wq, skb);
+
+ if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + 1)
+ netif_stop_queue(netdev);
+
+ netdev->trans_start = jiffies;
+
+ spin_unlock_irqrestore(&enic->wq_lock[0], flags);
+
+ return NETDEV_TX_OK;
+}
+
+/* dev_base_lock rwlock held, nominally process context */
+static struct net_device_stats *enic_get_stats(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct net_device_stats *net_stats = &netdev->stats;
+ struct vnic_stats *stats;
+
+ spin_lock(&enic->devcmd_lock);
+ vnic_dev_stats_dump(enic->vdev, &stats);
+ spin_unlock(&enic->devcmd_lock);
+
+ net_stats->tx_packets = stats->tx.tx_frames_ok;
+ net_stats->tx_bytes = stats->tx.tx_bytes_ok;
+ net_stats->tx_errors = stats->tx.tx_errors;
+ net_stats->tx_dropped = stats->tx.tx_drops;
+
+ net_stats->rx_packets = stats->rx.rx_frames_ok;
+ net_stats->rx_bytes = stats->rx.rx_bytes_ok;
+ net_stats->rx_errors = stats->rx.rx_errors;
+ net_stats->multicast = stats->rx.rx_multicast_frames_ok;
+ net_stats->rx_crc_errors = stats->rx.rx_crc_errors;
+ net_stats->rx_dropped = stats->rx.rx_no_bufs;
+
+ return net_stats;
+}
+
+static void enic_reset_mcaddrs(struct enic *enic)
+{
+ enic->mc_count = 0;
+}
+
+static int enic_set_mac_addr(struct net_device *netdev, char *addr)
+{
+ if (!is_valid_ether_addr(addr))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, addr, netdev->addr_len);
+
+ return 0;
+}
+
+/* netif_tx_lock held, BHs disabled */
+static void enic_set_multicast_list(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct dev_mc_list *list = netdev->mc_list;
+ int directed = 1;
+ int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0;
+ int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0;
+ int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0;
+ int allmulti = (netdev->flags & IFF_ALLMULTI) ||
+ (netdev->mc_count > ENIC_MULTICAST_PERFECT_FILTERS);
+ u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
+ unsigned int mc_count = netdev->mc_count;
+ unsigned int i, j;
+
+ if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS)
+ mc_count = ENIC_MULTICAST_PERFECT_FILTERS;
+
+ spin_lock(&enic->devcmd_lock);
+
+ vnic_dev_packet_filter(enic->vdev, directed,
+ multicast, broadcast, promisc, allmulti);
+
+ /* Is there an easier way? Trying to minimize to
+ * calls to add/del multicast addrs. We keep the
+ * addrs from the last call in enic->mc_addr and
+ * look for changes to add/del.
+ */
+
+ for (i = 0; list && i < mc_count; i++) {
+ memcpy(mc_addr[i], list->dmi_addr, ETH_ALEN);
+ list = list->next;
+ }
+
+ for (i = 0; i < enic->mc_count; i++) {
+ for (j = 0; j < mc_count; j++)
+ if (compare_ether_addr(enic->mc_addr[i],
+ mc_addr[j]) == 0)
+ break;
+ if (j == mc_count)
+ enic_del_multicast_addr(enic, enic->mc_addr[i]);
+ }
+
+ for (i = 0; i < mc_count; i++) {
+ for (j = 0; j < enic->mc_count; j++)
+ if (compare_ether_addr(mc_addr[i],
+ enic->mc_addr[j]) == 0)
+ break;
+ if (j == enic->mc_count)
+ enic_add_multicast_addr(enic, mc_addr[i]);
+ }
+
+ /* Save the list to compare against next time
+ */
+
+ for (i = 0; i < mc_count; i++)
+ memcpy(enic->mc_addr[i], mc_addr[i], ETH_ALEN);
+
+ enic->mc_count = mc_count;
+
+ spin_unlock(&enic->devcmd_lock);
+}
+
+/* rtnl lock is held */
+static void enic_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *vlan_group)
+{
+ struct enic *enic = netdev_priv(netdev);
+ enic->vlan_group = vlan_group;
+}
+
+/* rtnl lock is held */
+static void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ spin_lock(&enic->devcmd_lock);
+ enic_add_vlan(enic, vid);
+ spin_unlock(&enic->devcmd_lock);
+}
+
+/* rtnl lock is held */
+static void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+ struct enic *enic = netdev_priv(netdev);
+
+ spin_lock(&enic->devcmd_lock);
+ enic_del_vlan(enic, vid);
+ spin_unlock(&enic->devcmd_lock);
+}
+
+/* netif_tx_lock held, BHs disabled */
+static void enic_tx_timeout(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ schedule_work(&enic->reset);
+}
+
+static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
+{
+ struct enic *enic = vnic_dev_priv(rq->vdev);
+
+ if (!buf->os_buf)
+ return;
+
+ pci_unmap_single(enic->pdev, buf->dma_addr,
+ buf->len, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb_any(buf->os_buf);
+}
+
+static inline struct sk_buff *enic_rq_alloc_skb(unsigned int size)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(size + NET_IP_ALIGN);
+
+ if (skb)
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ return skb;
+}
+
+static int enic_rq_alloc_buf(struct vnic_rq *rq)
+{
+ struct enic *enic = vnic_dev_priv(rq->vdev);
+ struct sk_buff *skb;
+ unsigned int len = enic->netdev->mtu + ETH_HLEN;
+ unsigned int os_buf_index = 0;
+ dma_addr_t dma_addr;
+
+ skb = enic_rq_alloc_skb(len);
+ if (!skb)
+ return -ENOMEM;
+
+ dma_addr = pci_map_single(enic->pdev, skb->data,
+ len, PCI_DMA_FROMDEVICE);
+
+ enic_queue_rq_desc(rq, skb, os_buf_index,
+ dma_addr, len);
+
+ return 0;
+}
+
+static int enic_get_skb_header(struct sk_buff *skb, void **iphdr,
+ void **tcph, u64 *hdr_flags, void *priv)
+{
+ struct cq_enet_rq_desc *cq_desc = priv;
+ unsigned int ip_len;
+ struct iphdr *iph;
+
+ u8 type, color, eop, sop, ingress_port, vlan_stripped;
+ u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
+ u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
+ u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc;
+ u8 packet_error;
+ u16 q_number, completed_index, bytes_written, vlan, checksum;
+ u32 rss_hash;
+
+ cq_enet_rq_desc_dec(cq_desc,
+ &type, &color, &q_number, &completed_index,
+ &ingress_port, &fcoe, &eop, &sop, &rss_type,
+ &csum_not_calc, &rss_hash, &bytes_written,
+ &packet_error, &vlan_stripped, &vlan, &checksum,
+ &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error,
+ &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp,
+ &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
+ &fcs_ok);
+
+ if (!(ipv4 && tcp && !ipv4_fragment))
+ return -1;
+
+ skb_reset_network_header(skb);
+ iph = ip_hdr(skb);
+
+ ip_len = ip_hdrlen(skb);
+ skb_set_transport_header(skb, ip_len);
+
+ /* check if ip header and tcp header are complete */
+ if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
+ return -1;
+
+ *hdr_flags = LRO_IPV4 | LRO_TCP;
+ *tcph = tcp_hdr(skb);
+ *iphdr = iph;
+
+ return 0;
+}
+
+static void enic_rq_indicate_buf(struct vnic_rq *rq,
+ struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
+ int skipped, void *opaque)
+{
+ struct enic *enic = vnic_dev_priv(rq->vdev);
+ struct sk_buff *skb;
+
+ u8 type, color, eop, sop, ingress_port, vlan_stripped;
+ u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
+ u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
+ u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc;
+ u8 packet_error;
+ u16 q_number, completed_index, bytes_written, vlan, checksum;
+ u32 rss_hash;
+
+ if (skipped)
+ return;
+
+ skb = buf->os_buf;
+ prefetch(skb->data - NET_IP_ALIGN);
+ pci_unmap_single(enic->pdev, buf->dma_addr,
+ buf->len, PCI_DMA_FROMDEVICE);
+
+ cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
+ &type, &color, &q_number, &completed_index,
+ &ingress_port, &fcoe, &eop, &sop, &rss_type,
+ &csum_not_calc, &rss_hash, &bytes_written,
+ &packet_error, &vlan_stripped, &vlan, &checksum,
+ &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error,
+ &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp,
+ &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
+ &fcs_ok);
+
+ if (packet_error) {
+
+ if (bytes_written > 0 && !fcs_ok) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX
+ "%s: packet error: bad FCS\n",
+ enic->netdev->name);
+ }
+
+ dev_kfree_skb_any(skb);
+
+ return;
+ }
+
+ if (eop && bytes_written > 0) {
+
+ /* Good receive
+ */
+
+ skb_put(skb, bytes_written);
+ skb->protocol = eth_type_trans(skb, enic->netdev);
+
+ if (enic->csum_rx_enabled && !csum_not_calc) {
+ skb->csum = htons(checksum);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+
+ skb->dev = enic->netdev;
+ enic->netdev->last_rx = jiffies;
+
+ if (enic->vlan_group && vlan_stripped) {
+
+ if (ENIC_SETTING(enic, LRO) && ipv4)
+ lro_vlan_hwaccel_receive_skb(&enic->lro_mgr,
+ skb, enic->vlan_group,
+ vlan, cq_desc);
+ else
+ vlan_hwaccel_receive_skb(skb,
+ enic->vlan_group, vlan);
+
+ } else {
+
+ if (ENIC_SETTING(enic, LRO) && ipv4)
+ lro_receive_skb(&enic->lro_mgr, skb, cq_desc);
+ else
+ netif_receive_skb(skb);
+
+ }
+
+ } else {
+
+ /* Buffer overflow
+ */
+
+ dev_kfree_skb_any(skb);
+ }
+}
+
+static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
+ u8 type, u16 q_number, u16 completed_index, void *opaque)
+{
+ struct enic *enic = vnic_dev_priv(vdev);
+
+ vnic_rq_service(&enic->rq[q_number], cq_desc,
+ completed_index, VNIC_RQ_RETURN_DESC,
+ enic_rq_indicate_buf, opaque);
+
+ return 0;
+}
+
+static void enic_rq_drop_buf(struct vnic_rq *rq,
+ struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
+ int skipped, void *opaque)
+{
+ struct enic *enic = vnic_dev_priv(rq->vdev);
+ struct sk_buff *skb = buf->os_buf;
+
+ if (skipped)
+ return;
+
+ pci_unmap_single(enic->pdev, buf->dma_addr,
+ buf->len, PCI_DMA_FROMDEVICE);
+
+ dev_kfree_skb_any(skb);
+}
+
+static int enic_rq_service_drop(struct vnic_dev *vdev, struct cq_desc *cq_desc,
+ u8 type, u16 q_number, u16 completed_index, void *opaque)
+{
+ struct enic *enic = vnic_dev_priv(vdev);
+
+ vnic_rq_service(&enic->rq[q_number], cq_desc,
+ completed_index, VNIC_RQ_RETURN_DESC,
+ enic_rq_drop_buf, opaque);
+
+ return 0;
+}
+
+static int enic_poll(struct napi_struct *napi, int budget)
+{
+ struct enic *enic = container_of(napi, struct enic, napi);
+ struct net_device *netdev = enic->netdev;
+ unsigned int rq_work_to_do = budget;
+ unsigned int wq_work_to_do = -1; /* no limit */
+ unsigned int work_done, rq_work_done, wq_work_done;
+
+ /* Service RQ (first) and WQ
+ */
+
+ rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+ rq_work_to_do, enic_rq_service, NULL);
+
+ wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+ wq_work_to_do, enic_wq_service, NULL);
+
+ /* Accumulate intr event credits for this polling
+ * cycle. An intr event is the completion of a
+ * a WQ or RQ packet.
+ */
+
+ work_done = rq_work_done + wq_work_done;
+
+ if (work_done > 0)
+ vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ],
+ work_done,
+ 0 /* don't unmask intr */,
+ 0 /* don't reset intr timer */);
+
+ if (rq_work_done > 0) {
+
+ /* Replenish RQ
+ */
+
+ vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+
+ } else {
+
+ /* If no work done, flush all LROs and exit polling
+ */
+
+ if (ENIC_SETTING(enic, LRO))
+ lro_flush_all(&enic->lro_mgr);
+
+ netif_rx_complete(netdev, napi);
+ vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
+ }
+
+ return rq_work_done;
+}
+
+static int enic_poll_msix(struct napi_struct *napi, int budget)
+{
+ struct enic *enic = container_of(napi, struct enic, napi);
+ struct net_device *netdev = enic->netdev;
+ unsigned int work_to_do = budget;
+ unsigned int work_done;
+
+ /* Service RQ
+ */
+
+ work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+ work_to_do, enic_rq_service, NULL);
+
+ if (work_done > 0) {
+
+ /* Replenish RQ
+ */
+
+ vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+
+ /* Accumulate intr event credits for this polling
+ * cycle. An intr event is the completion of a
+ * a WQ or RQ packet.
+ */
+
+ vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ],
+ work_done,
+ 0 /* don't unmask intr */,
+ 0 /* don't reset intr timer */);
+ } else {
+
+ /* If no work done, flush all LROs and exit polling
+ */
+
+ if (ENIC_SETTING(enic, LRO))
+ lro_flush_all(&enic->lro_mgr);
+
+ netif_rx_complete(netdev, napi);
+ vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
+ }
+
+ return work_done;
+}
+
+static void enic_notify_timer(unsigned long data)
+{
+ struct enic *enic = (struct enic *)data;
+
+ enic_notify_check(enic);
+
+ mod_timer(&enic->notify_timer,
+ round_jiffies(jiffies + ENIC_NOTIFY_TIMER_PERIOD));
+}
+
+static void enic_free_intr(struct enic *enic)
+{
+ struct net_device *netdev = enic->netdev;
+ unsigned int i;
+
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ free_irq(enic->pdev->irq, netdev);
+ break;
+ case VNIC_DEV_INTR_MODE_MSI:
+ free_irq(enic->pdev->irq, enic);
+ break;
+ case VNIC_DEV_INTR_MODE_MSIX:
+ for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
+ if (enic->msix[i].requested)
+ free_irq(enic->msix_entry[i].vector,
+ enic->msix[i].devid);
+ break;
+ default:
+ break;
+ }
+}
+
+static int enic_request_intr(struct enic *enic)
+{
+ struct net_device *netdev = enic->netdev;
+ unsigned int i;
+ int err = 0;
+
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+
+ case VNIC_DEV_INTR_MODE_INTX:
+
+ err = request_irq(enic->pdev->irq, enic_isr_legacy,
+ IRQF_SHARED, netdev->name, netdev);
+ break;
+
+ case VNIC_DEV_INTR_MODE_MSI:
+
+ err = request_irq(enic->pdev->irq, enic_isr_msi,
+ 0, netdev->name, enic);
+ break;
+
+ case VNIC_DEV_INTR_MODE_MSIX:
+
+ sprintf(enic->msix[ENIC_MSIX_RQ].devname,
+ "%.11s-rx-0", netdev->name);
+ enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq;
+ enic->msix[ENIC_MSIX_RQ].devid = enic;
+
+ sprintf(enic->msix[ENIC_MSIX_WQ].devname,
+ "%.11s-tx-0", netdev->name);
+ enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq;
+ enic->msix[ENIC_MSIX_WQ].devid = enic;
+
+ sprintf(enic->msix[ENIC_MSIX_ERR].devname,
+ "%.11s-err", netdev->name);
+ enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err;
+ enic->msix[ENIC_MSIX_ERR].devid = enic;
+
+ sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname,
+ "%.11s-notify", netdev->name);
+ enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify;
+ enic->msix[ENIC_MSIX_NOTIFY].devid = enic;
+
+ for (i = 0; i < ARRAY_SIZE(enic->msix); i++) {
+ err = request_irq(enic->msix_entry[i].vector,
+ enic->msix[i].isr, 0,
+ enic->msix[i].devname,
+ enic->msix[i].devid);
+ if (err) {
+ enic_free_intr(enic);
+ break;
+ }
+ enic->msix[i].requested = 1;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+static int enic_notify_set(struct enic *enic)
+{
+ int err;
+
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY);
+ break;
+ case VNIC_DEV_INTR_MODE_MSIX:
+ err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY);
+ break;
+ default:
+ err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
+ break;
+ }
+
+ return err;
+}
+
+static void enic_notify_timer_start(struct enic *enic)
+{
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_MSI:
+ mod_timer(&enic->notify_timer, jiffies);
+ break;
+ default:
+ /* Using intr for notification for INTx/MSI-X */
+ break;
+ };
+}
+
+/* rtnl lock is held, process context */
+static int enic_open(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int i;
+ int err;
+
+ err = enic_request_intr(enic);
+ if (err) {
+ printk(KERN_ERR PFX "%s: Unable to request irq.\n",
+ netdev->name);
+ return err;
+ }
+
+ err = enic_notify_set(enic);
+ if (err) {
+ printk(KERN_ERR PFX
+ "%s: Failed to alloc notify buffer, aborting.\n",
+ netdev->name);
+ goto err_out_free_intr;
+ }
+
+ for (i = 0; i < enic->rq_count; i++) {
+ err = vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf);
+ if (err) {
+ printk(KERN_ERR PFX
+ "%s: Unable to alloc receive buffers.\n",
+ netdev->name);
+ goto err_out_notify_unset;
+ }
+ }
+
+ for (i = 0; i < enic->wq_count; i++)
+ vnic_wq_enable(&enic->wq[i]);
+ for (i = 0; i < enic->rq_count; i++)
+ vnic_rq_enable(&enic->rq[i]);
+
+ enic_add_station_addr(enic);
+ enic_set_multicast_list(netdev);
+
+ netif_wake_queue(netdev);
+ napi_enable(&enic->napi);
+ vnic_dev_enable(enic->vdev);
+
+ for (i = 0; i < enic->intr_count; i++)
+ vnic_intr_unmask(&enic->intr[i]);
+
+ enic_notify_timer_start(enic);
+
+ return 0;
+
+err_out_notify_unset:
+ vnic_dev_notify_unset(enic->vdev);
+err_out_free_intr:
+ enic_free_intr(enic);
+
+ return err;
+}
+
+/* rtnl lock is held, process context */
+static int enic_stop(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int i;
+ int err;
+
+ del_timer_sync(&enic->notify_timer);
+
+ vnic_dev_disable(enic->vdev);
+ napi_disable(&enic->napi);
+ netif_stop_queue(netdev);
+
+ for (i = 0; i < enic->intr_count; i++)
+ vnic_intr_mask(&enic->intr[i]);
+
+ for (i = 0; i < enic->wq_count; i++) {
+ err = vnic_wq_disable(&enic->wq[i]);
+ if (err)
+ return err;
+ }
+ for (i = 0; i < enic->rq_count; i++) {
+ err = vnic_rq_disable(&enic->rq[i]);
+ if (err)
+ return err;
+ }
+
+ vnic_dev_notify_unset(enic->vdev);
+ enic_free_intr(enic);
+
+ (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+ -1, enic_rq_service_drop, NULL);
+ (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+ -1, enic_wq_service, NULL);
+
+ for (i = 0; i < enic->wq_count; i++)
+ vnic_wq_clean(&enic->wq[i], enic_free_wq_buf);
+ for (i = 0; i < enic->rq_count; i++)
+ vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
+ for (i = 0; i < enic->cq_count; i++)
+ vnic_cq_clean(&enic->cq[i]);
+ for (i = 0; i < enic->intr_count; i++)
+ vnic_intr_clean(&enic->intr[i]);
+
+ return 0;
+}
+
+static int enic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct enic *enic = netdev_priv(netdev);
+ int running = netif_running(netdev);
+
+ if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
+ return -EINVAL;
+
+ if (running)
+ enic_stop(netdev);
+
+ netdev->mtu = new_mtu;
+
+ if (netdev->mtu > enic->port_mtu)
+ printk(KERN_WARNING PFX
+ "%s: interface MTU (%d) set higher "
+ "than port MTU (%d)\n",
+ netdev->name, netdev->mtu, enic->port_mtu);
+
+ if (running)
+ enic_open(netdev);
+
+ return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void enic_poll_controller(struct net_device *netdev)
+{
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_dev *vdev = enic->vdev;
+
+ switch (vnic_dev_get_intr_mode(vdev)) {
+ case VNIC_DEV_INTR_MODE_MSIX:
+ enic_isr_msix_rq(enic->pdev->irq, enic);
+ enic_isr_msix_wq(enic->pdev->irq, enic);
+ break;
+ case VNIC_DEV_INTR_MODE_MSI:
+ enic_isr_msi(enic->pdev->irq, enic);
+ break;
+ case VNIC_DEV_INTR_MODE_INTX:
+ enic_isr_legacy(enic->pdev->irq, netdev);
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+static int enic_dev_wait(struct vnic_dev *vdev,
+ int (*start)(struct vnic_dev *, int),
+ int (*finished)(struct vnic_dev *, int *),
+ int arg)
+{
+ unsigned long time;
+ int done;
+ int err;
+
+ BUG_ON(in_interrupt());
+
+ err = start(vdev, arg);
+ if (err)
+ return err;
+
+ /* Wait for func to complete...2 seconds max
+ */
+
+ time = jiffies + (HZ * 2);
+ do {
+
+ err = finished(vdev, &done);
+ if (err)
+ return err;
+
+ if (done)
+ return 0;
+
+ schedule_timeout_uninterruptible(HZ / 10);
+
+ } while (time_after(time, jiffies));
+
+ return -ETIMEDOUT;
+}
+
+static int enic_dev_open(struct enic *enic)
+{
+ int err;
+
+ err = enic_dev_wait(enic->vdev, vnic_dev_open,
+ vnic_dev_open_done, 0);
+ if (err)
+ printk(KERN_ERR PFX
+ "vNIC device open failed, err %d.\n", err);
+
+ return err;
+}
+
+static int enic_dev_soft_reset(struct enic *enic)
+{
+ int err;
+
+ err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset,
+ vnic_dev_soft_reset_done, 0);
+ if (err)
+ printk(KERN_ERR PFX
+ "vNIC soft reset failed, err %d.\n", err);
+
+ return err;
+}
+
+static void enic_reset(struct work_struct *work)
+{
+ struct enic *enic = container_of(work, struct enic, reset);
+
+ if (!netif_running(enic->netdev))
+ return;
+
+ rtnl_lock();
+
+ spin_lock(&enic->devcmd_lock);
+ vnic_dev_hang_notify(enic->vdev);
+ spin_unlock(&enic->devcmd_lock);
+
+ enic_stop(enic->netdev);
+ enic_dev_soft_reset(enic);
+ enic_reset_mcaddrs(enic);
+ enic_init_vnic_resources(enic);
+ enic_open(enic->netdev);
+
+ rtnl_unlock();
+}
+
+static int enic_set_intr_mode(struct enic *enic)
+{
+ unsigned int n = ARRAY_SIZE(enic->rq);
+ unsigned int m = ARRAY_SIZE(enic->wq);
+ unsigned int i;
+
+ /* Set interrupt mode (INTx, MSI, MSI-X) depending
+ * system capabilities.
+ *
+ * Try MSI-X first
+ *
+ * We need n RQs, m WQs, n+m CQs, and n+m+2 INTRs
+ * (the second to last INTR is used for WQ/RQ errors)
+ * (the last INTR is used for notifications)
+ */
+
+ BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2);
+ for (i = 0; i < n + m + 2; i++)
+ enic->msix_entry[i].entry = i;
+
+ if (enic->config.intr_mode < 1 &&
+ enic->rq_count >= n &&
+ enic->wq_count >= m &&
+ enic->cq_count >= n + m &&
+ enic->intr_count >= n + m + 2 &&
+ !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
+
+ enic->rq_count = n;
+ enic->wq_count = m;
+ enic->cq_count = n + m;
+ enic->intr_count = n + m + 2;
+
+ vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX);
+
+ return 0;
+ }
+
+ /* Next try MSI
+ *
+ * We need 1 RQ, 1 WQ, 2 CQs, and 1 INTR
+ */
+
+ if (enic->config.intr_mode < 2 &&
+ enic->rq_count >= 1 &&
+ enic->wq_count >= 1 &&
+ enic->cq_count >= 2 &&
+ enic->intr_count >= 1 &&
+ !pci_enable_msi(enic->pdev)) {
+
+ enic->rq_count = 1;
+ enic->wq_count = 1;
+ enic->cq_count = 2;
+ enic->intr_count = 1;
+
+ vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSI);
+
+ return 0;
+ }
+
+ /* Next try INTx
+ *
+ * We need 1 RQ, 1 WQ, 2 CQs, and 3 INTRs
+ * (the first INTR is used for WQ/RQ)
+ * (the second INTR is used for WQ/RQ errors)
+ * (the last INTR is used for notifications)
+ */
+
+ if (enic->config.intr_mode < 3 &&
+ enic->rq_count >= 1 &&
+ enic->wq_count >= 1 &&
+ enic->cq_count >= 2 &&
+ enic->intr_count >= 3) {
+
+ enic->rq_count = 1;
+ enic->wq_count = 1;
+ enic->cq_count = 2;
+ enic->intr_count = 3;
+
+ vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_INTX);
+
+ return 0;
+ }
+
+ vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
+
+ return -EINVAL;
+}
+
+static void enic_clear_intr_mode(struct enic *enic)
+{
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_MSIX:
+ pci_disable_msix(enic->pdev);
+ break;
+ case VNIC_DEV_INTR_MODE_MSI:
+ pci_disable_msi(enic->pdev);
+ break;
+ default:
+ break;
+ }
+
+ vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
+}
+
+static void enic_iounmap(struct enic *enic)
+{
+ if (enic->bar0.vaddr)
+ iounmap(enic->bar0.vaddr);
+}
+
+static int __devinit enic_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct enic *enic;
+ int using_dac = 0;
+ unsigned int i;
+ int err;
+
+ const u8 rss_default_cpu = 0;
+ const u8 rss_hash_type = 0;
+ const u8 rss_hash_bits = 0;
+ const u8 rss_base_cpu = 0;
+ const u8 rss_enable = 0;
+ const u8 tso_ipid_split_en = 0;
+ const u8 ig_vlan_strip_en = 1;
+
+ /* Allocate net device structure and initialize. Private
+ * instance data is initialized to zero.
+ */
+
+ netdev = alloc_etherdev(sizeof(struct enic));
+ if (!netdev) {
+ printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ return -ENOMEM;
+ }
+
+ pci_set_drvdata(pdev, netdev);
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ enic = netdev_priv(netdev);
+ enic->netdev = netdev;
+ enic->pdev = pdev;
+
+ /* Setup PCI resources
+ */
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Cannot enable PCI device, aborting.\n");
+ goto err_out_free_netdev;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Cannot request PCI regions, aborting.\n");
+ goto err_out_disable_device;
+ }
+
+ pci_set_master(pdev);
+
+ /* Query PCI controller on system for DMA addressing
+ * limitation for the device. Try 40-bit first, and
+ * fail to 32-bit.
+ */
+
+ err = pci_set_dma_mask(pdev, DMA_40BIT_MASK);
+ if (err) {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX
+ "No usable DMA configuration, aborting.\n");
+ goto err_out_release_regions;
+ }
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Unable to obtain 32-bit DMA "
+ "for consistent allocations, aborting.\n");
+ goto err_out_release_regions;
+ }
+ } else {
+ err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Unable to obtain 40-bit DMA "
+ "for consistent allocations, aborting.\n");
+ goto err_out_release_regions;
+ }
+ using_dac = 1;
+ }
+
+ /* Map vNIC resources from BAR0
+ */
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX
+ "BAR0 not memory-map'able, aborting.\n");
+ err = -ENODEV;
+ goto err_out_release_regions;
+ }
+
+ enic->bar0.vaddr = pci_iomap(pdev, 0, enic->bar0.len);
+ enic->bar0.bus_addr = pci_resource_start(pdev, 0);
+ enic->bar0.len = pci_resource_len(pdev, 0);
+
+ if (!enic->bar0.vaddr) {
+ printk(KERN_ERR PFX
+ "Cannot memory-map BAR0 res hdr, aborting.\n");
+ err = -ENODEV;
+ goto err_out_release_regions;
+ }
+
+ /* Register vNIC device
+ */
+
+ enic->vdev = vnic_dev_register(NULL, enic, pdev, &enic->bar0);
+ if (!enic->vdev) {
+ printk(KERN_ERR PFX
+ "vNIC registration failed, aborting.\n");
+ err = -ENODEV;
+ goto err_out_iounmap;
+ }
+
+ /* Issue device open to get device in known state
+ */
+
+ err = enic_dev_open(enic);
+ if (err) {
+ printk(KERN_ERR PFX
+ "vNIC dev open failed, aborting.\n");
+ goto err_out_vnic_unregister;
+ }
+
+ /* Issue device init to initialize the vnic-to-switch link.
+ * We'll start with carrier off and wait for link UP
+ * notification later to turn on carrier. We don't need
+ * to wait here for the vnic-to-switch link initialization
+ * to complete; link UP notification is the indication that
+ * the process is complete.
+ */
+
+ netif_carrier_off(netdev);
+
+ err = vnic_dev_init(enic->vdev, 0);
+ if (err) {
+ printk(KERN_ERR PFX
+ "vNIC dev init failed, aborting.\n");
+ goto err_out_dev_close;
+ }
+
+ /* Get vNIC configuration
+ */
+
+ err = enic_get_vnic_config(enic);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Get vNIC configuration failed, aborting.\n");
+ goto err_out_dev_close;
+ }
+
+ /* Get available resource counts
+ */
+
+ enic_get_res_counts(enic);
+
+ /* Set interrupt mode based on resource counts and system
+ * capabilities
+ */
+
+ err = enic_set_intr_mode(enic);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Failed to set intr mode, aborting.\n");
+ goto err_out_dev_close;
+ }
+
+ /* Allocate and configure vNIC resources
+ */
+
+ err = enic_alloc_vnic_resources(enic);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Failed to alloc vNIC resources, aborting.\n");
+ goto err_out_free_vnic_resources;
+ }
+
+ enic_init_vnic_resources(enic);
+
+ /* Enable VLAN tag stripping. RSS not enabled (yet).
+ */
+
+ err = enic_set_nic_cfg(enic,
+ rss_default_cpu, rss_hash_type,
+ rss_hash_bits, rss_base_cpu,
+ rss_enable, tso_ipid_split_en,
+ ig_vlan_strip_en);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Failed to config nic, aborting.\n");
+ goto err_out_free_vnic_resources;
+ }
+
+ /* Setup notification timer, HW reset task, and locks
+ */
+
+ init_timer(&enic->notify_timer);
+ enic->notify_timer.function = enic_notify_timer;
+ enic->notify_timer.data = (unsigned long)enic;
+
+ INIT_WORK(&enic->reset, enic_reset);
+
+ for (i = 0; i < enic->wq_count; i++)
+ spin_lock_init(&enic->wq_lock[i]);
+
+ spin_lock_init(&enic->devcmd_lock);
+
+ /* Register net device
+ */
+
+ enic->port_mtu = enic->config.mtu;
+ (void)enic_change_mtu(netdev, enic->port_mtu);
+
+ err = enic_set_mac_addr(netdev, enic->mac_addr);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Invalid MAC address, aborting.\n");
+ goto err_out_free_vnic_resources;
+ }
+
+ netdev->open = enic_open;
+ netdev->stop = enic_stop;
+ netdev->hard_start_xmit = enic_hard_start_xmit;
+ netdev->get_stats = enic_get_stats;
+ netdev->set_multicast_list = enic_set_multicast_list;
+ netdev->change_mtu = enic_change_mtu;
+ netdev->vlan_rx_register = enic_vlan_rx_register;
+ netdev->vlan_rx_add_vid = enic_vlan_rx_add_vid;
+ netdev->vlan_rx_kill_vid = enic_vlan_rx_kill_vid;
+ netdev->tx_timeout = enic_tx_timeout;
+ netdev->watchdog_timeo = 2 * HZ;
+ netdev->ethtool_ops = &enic_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = enic_poll_controller;
+#endif
+
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ default:
+ netif_napi_add(netdev, &enic->napi, enic_poll, 64);
+ break;
+ case VNIC_DEV_INTR_MODE_MSIX:
+ netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64);
+ break;
+ }
+
+ netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ if (ENIC_SETTING(enic, TXCSUM))
+ netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ if (ENIC_SETTING(enic, TSO))
+ netdev->features |= NETIF_F_TSO |
+ NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+ if (using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+
+ enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM);
+
+ if (ENIC_SETTING(enic, LRO)) {
+ enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR;
+ enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC;
+ enic->lro_mgr.lro_arr = enic->lro_desc;
+ enic->lro_mgr.get_skb_header = enic_get_skb_header;
+ enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
+ enic->lro_mgr.dev = netdev;
+ enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE;
+ enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+ }
+
+ err = register_netdev(netdev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Cannot register net device, aborting.\n");
+ goto err_out_free_vnic_resources;
+ }
+
+ return 0;
+
+err_out_free_vnic_resources:
+ enic_free_vnic_resources(enic);
+err_out_dev_close:
+ vnic_dev_close(enic->vdev);
+err_out_vnic_unregister:
+ enic_clear_intr_mode(enic);
+ vnic_dev_unregister(enic->vdev);
+err_out_iounmap:
+ enic_iounmap(enic);
+err_out_release_regions:
+ pci_release_regions(pdev);
+err_out_disable_device:
+ pci_disable_device(pdev);
+err_out_free_netdev:
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+
+ return err;
+}
+
+static void __devexit enic_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+
+ if (netdev) {
+ struct enic *enic = netdev_priv(netdev);
+
+ flush_scheduled_work();
+ unregister_netdev(netdev);
+ enic_free_vnic_resources(enic);
+ vnic_dev_close(enic->vdev);
+ enic_clear_intr_mode(enic);
+ vnic_dev_unregister(enic->vdev);
+ enic_iounmap(enic);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+ }
+}
+
+static struct pci_driver enic_driver = {
+ .name = DRV_NAME,
+ .id_table = enic_id_table,
+ .probe = enic_probe,
+ .remove = __devexit_p(enic_remove),
+};
+
+static int __init enic_init_module(void)
+{
+ printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION);
+
+ return pci_register_driver(&enic_driver);
+}
+
+static void __exit enic_cleanup_module(void)
+{
+ pci_unregister_driver(&enic_driver);
+}
+
+module_init(enic_init_module);
+module_exit(enic_cleanup_module);
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
new file mode 100644
index 00000000000..95184b9108e
--- /dev/null
+++ b/drivers/net/enic/enic_res.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+#include "wq_enet_desc.h"
+#include "rq_enet_desc.h"
+#include "cq_enet_desc.h"
+#include "vnic_resource.h"
+#include "vnic_enet.h"
+#include "vnic_dev.h"
+#include "vnic_wq.h"
+#include "vnic_rq.h"
+#include "vnic_cq.h"
+#include "vnic_intr.h"
+#include "vnic_stats.h"
+#include "vnic_nic.h"
+#include "vnic_rss.h"
+#include "enic_res.h"
+#include "enic.h"
+
+int enic_get_vnic_config(struct enic *enic)
+{
+ struct vnic_enet_config *c = &enic->config;
+ int err;
+
+ err = vnic_dev_mac_addr(enic->vdev, enic->mac_addr);
+ if (err) {
+ printk(KERN_ERR PFX "Error getting MAC addr, %d\n", err);
+ return err;
+ }
+
+#define GET_CONFIG(m) \
+ do { \
+ err = vnic_dev_spec(enic->vdev, \
+ offsetof(struct vnic_enet_config, m), \
+ sizeof(c->m), &c->m); \
+ if (err) { \
+ printk(KERN_ERR PFX \
+ "Error getting %s, %d\n", #m, err); \
+ return err; \
+ } \
+ } while (0)
+
+ GET_CONFIG(flags);
+ GET_CONFIG(wq_desc_count);
+ GET_CONFIG(rq_desc_count);
+ GET_CONFIG(mtu);
+ GET_CONFIG(intr_timer);
+ GET_CONFIG(intr_timer_type);
+ GET_CONFIG(intr_mode);
+
+ c->wq_desc_count =
+ min_t(u32, ENIC_MAX_WQ_DESCS,
+ max_t(u32, ENIC_MIN_WQ_DESCS,
+ c->wq_desc_count));
+ c->wq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */
+
+ c->rq_desc_count =
+ min_t(u32, ENIC_MAX_RQ_DESCS,
+ max_t(u32, ENIC_MIN_RQ_DESCS,
+ c->rq_desc_count));
+ c->rq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */
+
+ if (c->mtu == 0)
+ c->mtu = 1500;
+ c->mtu = min_t(u16, ENIC_MAX_MTU,
+ max_t(u16, ENIC_MIN_MTU,
+ c->mtu));
+
+ c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
+
+ printk(KERN_INFO PFX "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
+ "wq/rq %d/%d\n",
+ enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
+ enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
+ c->wq_desc_count, c->rq_desc_count);
+ printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d "
+ "intr timer %d\n",
+ c->mtu, ENIC_SETTING(enic, TXCSUM),
+ ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO),
+ ENIC_SETTING(enic, LRO), c->intr_timer);
+
+ return 0;
+}
+
+void enic_add_station_addr(struct enic *enic)
+{
+ vnic_dev_add_addr(enic->vdev, enic->mac_addr);
+}
+
+void enic_add_multicast_addr(struct enic *enic, u8 *addr)
+{
+ vnic_dev_add_addr(enic->vdev, addr);
+}
+
+void enic_del_multicast_addr(struct enic *enic, u8 *addr)
+{
+ vnic_dev_del_addr(enic->vdev, addr);
+}
+
+void enic_add_vlan(struct enic *enic, u16 vlanid)
+{
+ u64 a0 = vlanid, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait);
+ if (err)
+ printk(KERN_ERR PFX "Can't add vlan id, %d\n", err);
+}
+
+void enic_del_vlan(struct enic *enic, u16 vlanid)
+{
+ u64 a0 = vlanid, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait);
+ if (err)
+ printk(KERN_ERR PFX "Can't delete vlan id, %d\n", err);
+}
+
+int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
+ u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
+ u8 ig_vlan_strip_en)
+{
+ u64 a0, a1;
+ u32 nic_cfg;
+ int wait = 1000;
+
+ vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
+ rss_hash_type, rss_hash_bits, rss_base_cpu,
+ rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
+
+ a0 = nic_cfg;
+ a1 = 0;
+
+ return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
+}
+
+void enic_free_vnic_resources(struct enic *enic)
+{
+ unsigned int i;
+
+ for (i = 0; i < enic->wq_count; i++)
+ vnic_wq_free(&enic->wq[i]);
+ for (i = 0; i < enic->rq_count; i++)
+ vnic_rq_free(&enic->rq[i]);
+ for (i = 0; i < enic->cq_count; i++)
+ vnic_cq_free(&enic->cq[i]);
+ for (i = 0; i < enic->intr_count; i++)
+ vnic_intr_free(&enic->intr[i]);
+}
+
+void enic_get_res_counts(struct enic *enic)
+{
+ enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
+ enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
+ enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
+ enic->intr_count = vnic_dev_get_res_count(enic->vdev,
+ RES_TYPE_INTR_CTRL);
+
+ printk(KERN_INFO PFX "vNIC resources avail: "
+ "wq %d rq %d cq %d intr %d\n",
+ enic->wq_count, enic->rq_count,
+ enic->cq_count, enic->intr_count);
+}
+
+void enic_init_vnic_resources(struct enic *enic)
+{
+ enum vnic_dev_intr_mode intr_mode;
+ unsigned int mask_on_assertion;
+ unsigned int interrupt_offset;
+ unsigned int error_interrupt_enable;
+ unsigned int error_interrupt_offset;
+ unsigned int cq_index;
+ unsigned int i;
+
+ intr_mode = vnic_dev_get_intr_mode(enic->vdev);
+
+ /* Init RQ/WQ resources.
+ *
+ * RQ[0 - n-1] point to CQ[0 - n-1]
+ * WQ[0 - m-1] point to CQ[n - n+m-1]
+ *
+ * Error interrupt is not enabled for MSI.
+ */
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ case VNIC_DEV_INTR_MODE_MSIX:
+ error_interrupt_enable = 1;
+ error_interrupt_offset = enic->intr_count - 2;
+ break;
+ default:
+ error_interrupt_enable = 0;
+ error_interrupt_offset = 0;
+ break;
+ }
+
+ for (i = 0; i < enic->rq_count; i++) {
+ cq_index = i;
+ vnic_rq_init(&enic->rq[i],
+ cq_index,
+ error_interrupt_enable,
+ error_interrupt_offset);
+ }
+
+ for (i = 0; i < enic->wq_count; i++) {
+ cq_index = enic->rq_count + i;
+ vnic_wq_init(&enic->wq[i],
+ cq_index,
+ error_interrupt_enable,
+ error_interrupt_offset);
+ }
+
+ /* Init CQ resources
+ *
+ * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI
+ * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X
+ */
+
+ for (i = 0; i < enic->cq_count; i++) {
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_MSIX:
+ interrupt_offset = i;
+ break;
+ default:
+ interrupt_offset = 0;
+ break;
+ }
+
+ vnic_cq_init(&enic->cq[i],
+ 0 /* flow_control_enable */,
+ 1 /* color_enable */,
+ 0 /* cq_head */,
+ 0 /* cq_tail */,
+ 1 /* cq_tail_color */,
+ 1 /* interrupt_enable */,
+ 1 /* cq_entry_enable */,
+ 0 /* cq_message_enable */,
+ interrupt_offset,
+ 0 /* cq_message_addr */);
+ }
+
+ /* Init INTR resources
+ *
+ * mask_on_assertion is not used for INTx due to the level-
+ * triggered nature of INTx
+ */
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_MSI:
+ case VNIC_DEV_INTR_MODE_MSIX:
+ mask_on_assertion = 1;
+ break;
+ default:
+ mask_on_assertion = 0;
+ break;
+ }
+
+ for (i = 0; i < enic->intr_count; i++) {
+ vnic_intr_init(&enic->intr[i],
+ enic->config.intr_timer,
+ enic->config.intr_timer_type,
+ mask_on_assertion);
+ }
+
+ /* Clear LIF stats
+ */
+
+ vnic_dev_stats_clear(enic->vdev);
+}
+
+int enic_alloc_vnic_resources(struct enic *enic)
+{
+ enum vnic_dev_intr_mode intr_mode;
+ unsigned int i;
+ int err;
+
+ intr_mode = vnic_dev_get_intr_mode(enic->vdev);
+
+ printk(KERN_INFO PFX "vNIC resources used: "
+ "wq %d rq %d cq %d intr %d intr mode %s\n",
+ enic->wq_count, enic->rq_count,
+ enic->cq_count, enic->intr_count,
+ intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
+ intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
+ intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" :
+ "unknown"
+ );
+
+ /* Allocate queue resources
+ */
+
+ for (i = 0; i < enic->wq_count; i++) {
+ err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i,
+ enic->config.wq_desc_count,
+ sizeof(struct wq_enet_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ for (i = 0; i < enic->rq_count; i++) {
+ err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i,
+ enic->config.rq_desc_count,
+ sizeof(struct rq_enet_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ for (i = 0; i < enic->cq_count; i++) {
+ if (i < enic->rq_count)
+ err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
+ enic->config.rq_desc_count,
+ sizeof(struct cq_enet_rq_desc));
+ else
+ err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
+ enic->config.wq_desc_count,
+ sizeof(struct cq_enet_wq_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ for (i = 0; i < enic->intr_count; i++) {
+ err = vnic_intr_alloc(enic->vdev, &enic->intr[i], i);
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* Hook remaining resource
+ */
+
+ enic->legacy_pba = vnic_dev_get_res(enic->vdev,
+ RES_TYPE_INTR_PBA_LEGACY, 0);
+ if (!enic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
+ printk(KERN_ERR PFX "Failed to hook legacy pba resource\n");
+ err = -ENODEV;
+ goto err_out_cleanup;
+ }
+
+ return 0;
+
+err_out_cleanup:
+ enic_free_vnic_resources(enic);
+
+ return err;
+}
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
new file mode 100644
index 00000000000..68534a29b7a
--- /dev/null
+++ b/drivers/net/enic/enic_res.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _ENIC_RES_H_
+#define _ENIC_RES_H_
+
+#include "wq_enet_desc.h"
+#include "rq_enet_desc.h"
+#include "vnic_wq.h"
+#include "vnic_rq.h"
+
+#define ENIC_MIN_WQ_DESCS 64
+#define ENIC_MAX_WQ_DESCS 4096
+#define ENIC_MIN_RQ_DESCS 64
+#define ENIC_MAX_RQ_DESCS 4096
+
+#define ENIC_MIN_MTU 576 /* minimum for IPv4 */
+#define ENIC_MAX_MTU 9000
+
+#define ENIC_MULTICAST_PERFECT_FILTERS 32
+
+#define ENIC_NON_TSO_MAX_DESC 16
+
+#define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0)
+
+static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr, unsigned int len,
+ unsigned int mss_or_csum_offset, unsigned int hdr_len,
+ int vlan_tag_insert, unsigned int vlan_tag,
+ int offload_mode, int cq_entry, int sop, int eop)
+{
+ struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
+
+ wq_enet_desc_enc(desc,
+ (u64)dma_addr | VNIC_PADDR_TARGET,
+ (u16)len,
+ (u16)mss_or_csum_offset,
+ (u16)hdr_len, (u8)offload_mode,
+ (u8)eop, (u8)cq_entry,
+ 0, /* fcoe_encap */
+ (u8)vlan_tag_insert,
+ (u16)vlan_tag,
+ 0 /* loopback */);
+
+ wmb();
+
+ vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
+}
+
+static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr, unsigned int len, int eop)
+{
+ enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
+ 0, 0, 0, 0, 0,
+ eop, 0 /* !SOP */, eop);
+}
+
+static inline void enic_queue_wq_desc(struct vnic_wq *wq, void *os_buf,
+ dma_addr_t dma_addr, unsigned int len, int vlan_tag_insert,
+ unsigned int vlan_tag, int eop)
+{
+ enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
+ 0, 0, vlan_tag_insert, vlan_tag,
+ WQ_ENET_OFFLOAD_MODE_CSUM,
+ eop, 1 /* SOP */, eop);
+}
+
+static inline void enic_queue_wq_desc_csum(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr, unsigned int len,
+ int ip_csum, int tcpudp_csum, int vlan_tag_insert,
+ unsigned int vlan_tag, int eop)
+{
+ enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
+ (ip_csum ? 1 : 0) + (tcpudp_csum ? 2 : 0),
+ 0, vlan_tag_insert, vlan_tag,
+ WQ_ENET_OFFLOAD_MODE_CSUM,
+ eop, 1 /* SOP */, eop);
+}
+
+static inline void enic_queue_wq_desc_csum_l4(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr, unsigned int len,
+ unsigned int csum_offset, unsigned int hdr_len,
+ int vlan_tag_insert, unsigned int vlan_tag, int eop)
+{
+ enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
+ csum_offset, hdr_len, vlan_tag_insert, vlan_tag,
+ WQ_ENET_OFFLOAD_MODE_CSUM_L4,
+ eop, 1 /* SOP */, eop);
+}
+
+static inline void enic_queue_wq_desc_tso(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr, unsigned int len,
+ unsigned int mss, unsigned int hdr_len, int vlan_tag_insert,
+ unsigned int vlan_tag, int eop)
+{
+ enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
+ mss, hdr_len, vlan_tag_insert, vlan_tag,
+ WQ_ENET_OFFLOAD_MODE_TSO,
+ eop, 1 /* SOP */, eop);
+}
+
+static inline void enic_queue_rq_desc(struct vnic_rq *rq,
+ void *os_buf, unsigned int os_buf_index,
+ dma_addr_t dma_addr, unsigned int len)
+{
+ struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
+ u8 type = os_buf_index ?
+ RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
+
+ rq_enet_desc_enc(desc,
+ (u64)dma_addr | VNIC_PADDR_TARGET,
+ type, (u16)len);
+
+ wmb();
+
+ vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
+}
+
+struct enic;
+
+int enic_get_vnic_config(struct enic *);
+void enic_add_station_addr(struct enic *enic);
+void enic_add_multicast_addr(struct enic *enic, u8 *addr);
+void enic_del_multicast_addr(struct enic *enic, u8 *addr);
+void enic_add_vlan(struct enic *enic, u16 vlanid);
+void enic_del_vlan(struct enic *enic, u16 vlanid);
+int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
+ u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
+ u8 ig_vlan_strip_en);
+void enic_get_res_counts(struct enic *enic);
+void enic_init_vnic_resources(struct enic *enic);
+int enic_alloc_vnic_resources(struct enic *);
+void enic_free_vnic_resources(struct enic *);
+
+#endif /* _ENIC_RES_H_ */
diff --git a/drivers/net/enic/rq_enet_desc.h b/drivers/net/enic/rq_enet_desc.h
new file mode 100644
index 00000000000..a06e649010c
--- /dev/null
+++ b/drivers/net/enic/rq_enet_desc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _RQ_ENET_DESC_H_
+#define _RQ_ENET_DESC_H_
+
+/* Ethernet receive queue descriptor: 16B */
+struct rq_enet_desc {
+ __le64 address;
+ __le16 length_type;
+ u8 reserved[6];
+};
+
+enum rq_enet_type_types {
+ RQ_ENET_TYPE_ONLY_SOP = 0,
+ RQ_ENET_TYPE_NOT_SOP = 1,
+ RQ_ENET_TYPE_RESV2 = 2,
+ RQ_ENET_TYPE_RESV3 = 3,
+};
+
+#define RQ_ENET_ADDR_BITS 64
+#define RQ_ENET_LEN_BITS 14
+#define RQ_ENET_LEN_MASK ((1 << RQ_ENET_LEN_BITS) - 1)
+#define RQ_ENET_TYPE_BITS 2
+#define RQ_ENET_TYPE_MASK ((1 << RQ_ENET_TYPE_BITS) - 1)
+
+static inline void rq_enet_desc_enc(struct rq_enet_desc *desc,
+ u64 address, u8 type, u16 length)
+{
+ desc->address = cpu_to_le64(address);
+ desc->length_type = cpu_to_le16((length & RQ_ENET_LEN_MASK) |
+ ((type & RQ_ENET_TYPE_MASK) << RQ_ENET_LEN_BITS));
+}
+
+static inline void rq_enet_desc_dec(struct rq_enet_desc *desc,
+ u64 *address, u8 *type, u16 *length)
+{
+ *address = le64_to_cpu(desc->address);
+ *length = le16_to_cpu(desc->length_type) & RQ_ENET_LEN_MASK;
+ *type = (u8)((le16_to_cpu(desc->length_type) >> RQ_ENET_LEN_BITS) &
+ RQ_ENET_TYPE_MASK);
+}
+
+#endif /* _RQ_ENET_DESC_H_ */
diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/enic/vnic_cq.c
new file mode 100644
index 00000000000..020ae6c3f3d
--- /dev/null
+++ b/drivers/net/enic/vnic_cq.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include "vnic_dev.h"
+#include "vnic_cq.h"
+
+void vnic_cq_free(struct vnic_cq *cq)
+{
+ vnic_dev_free_desc_ring(cq->vdev, &cq->ring);
+
+ cq->ctrl = NULL;
+}
+
+int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ int err;
+
+ cq->index = index;
+ cq->vdev = vdev;
+
+ cq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_CQ, index);
+ if (!cq->ctrl) {
+ printk(KERN_ERR "Failed to hook CQ[%d] resource\n", index);
+ return -EINVAL;
+ }
+
+ err = vnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
+ unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
+ unsigned int cq_tail_color, unsigned int interrupt_enable,
+ unsigned int cq_entry_enable, unsigned int cq_message_enable,
+ unsigned int interrupt_offset, u64 cq_message_addr)
+{
+ u64 paddr;
+
+ paddr = (u64)cq->ring.base_addr | VNIC_PADDR_TARGET;
+ writeq(paddr, &cq->ctrl->ring_base);
+ iowrite32(cq->ring.desc_count, &cq->ctrl->ring_size);
+ iowrite32(flow_control_enable, &cq->ctrl->flow_control_enable);
+ iowrite32(color_enable, &cq->ctrl->color_enable);
+ iowrite32(cq_head, &cq->ctrl->cq_head);
+ iowrite32(cq_tail, &cq->ctrl->cq_tail);
+ iowrite32(cq_tail_color, &cq->ctrl->cq_tail_color);
+ iowrite32(interrupt_enable, &cq->ctrl->interrupt_enable);
+ iowrite32(cq_entry_enable, &cq->ctrl->cq_entry_enable);
+ iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable);
+ iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset);
+ writeq(cq_message_addr, &cq->ctrl->cq_message_addr);
+}
+
+void vnic_cq_clean(struct vnic_cq *cq)
+{
+ cq->to_clean = 0;
+ cq->last_color = 0;
+
+ iowrite32(0, &cq->ctrl->cq_head);
+ iowrite32(0, &cq->ctrl->cq_tail);
+ iowrite32(1, &cq->ctrl->cq_tail_color);
+
+ vnic_dev_clear_desc_ring(&cq->ring);
+}
diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/enic/vnic_cq.h
new file mode 100644
index 00000000000..114763cbc2f
--- /dev/null
+++ b/drivers/net/enic/vnic_cq.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_CQ_H_
+#define _VNIC_CQ_H_
+
+#include "cq_desc.h"
+#include "vnic_dev.h"
+
+/* Completion queue control */
+struct vnic_cq_ctrl {
+ u64 ring_base; /* 0x00 */
+ u32 ring_size; /* 0x08 */
+ u32 pad0;
+ u32 flow_control_enable; /* 0x10 */
+ u32 pad1;
+ u32 color_enable; /* 0x18 */
+ u32 pad2;
+ u32 cq_head; /* 0x20 */
+ u32 pad3;
+ u32 cq_tail; /* 0x28 */
+ u32 pad4;
+ u32 cq_tail_color; /* 0x30 */
+ u32 pad5;
+ u32 interrupt_enable; /* 0x38 */
+ u32 pad6;
+ u32 cq_entry_enable; /* 0x40 */
+ u32 pad7;
+ u32 cq_message_enable; /* 0x48 */
+ u32 pad8;
+ u32 interrupt_offset; /* 0x50 */
+ u32 pad9;
+ u64 cq_message_addr; /* 0x58 */
+ u32 pad10;
+};
+
+struct vnic_cq {
+ unsigned int index;
+ struct vnic_dev *vdev;
+ struct vnic_cq_ctrl __iomem *ctrl; /* memory-mapped */
+ struct vnic_dev_ring ring;
+ unsigned int to_clean;
+ unsigned int last_color;
+};
+
+static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
+ unsigned int work_to_do,
+ int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc,
+ u8 type, u16 q_number, u16 completed_index, void *opaque),
+ void *opaque)
+{
+ struct cq_desc *cq_desc;
+ unsigned int work_done = 0;
+ u16 q_number, completed_index;
+ u8 type, color;
+
+ cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
+ cq->ring.desc_size * cq->to_clean);
+ cq_desc_dec(cq_desc, &type, &color,
+ &q_number, &completed_index);
+
+ while (color != cq->last_color) {
+
+ if ((*q_service)(cq->vdev, cq_desc, type,
+ q_number, completed_index, opaque))
+ break;
+
+ cq->to_clean++;
+ if (cq->to_clean == cq->ring.desc_count) {
+ cq->to_clean = 0;
+ cq->last_color = cq->last_color ? 0 : 1;
+ }
+
+ cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
+ cq->ring.desc_size * cq->to_clean);
+ cq_desc_dec(cq_desc, &type, &color,
+ &q_number, &completed_index);
+
+ work_done++;
+ if (work_done >= work_to_do)
+ break;
+ }
+
+ return work_done;
+}
+
+void vnic_cq_free(struct vnic_cq *cq);
+int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size);
+void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
+ unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
+ unsigned int cq_tail_color, unsigned int interrupt_enable,
+ unsigned int cq_entry_enable, unsigned int message_enable,
+ unsigned int interrupt_offset, u64 message_addr);
+void vnic_cq_clean(struct vnic_cq *cq);
+
+#endif /* _VNIC_CQ_H_ */
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
new file mode 100644
index 00000000000..4d104f5c30f
--- /dev/null
+++ b/drivers/net/enic/vnic_dev.c
@@ -0,0 +1,674 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/if_ether.h>
+
+#include "vnic_resource.h"
+#include "vnic_devcmd.h"
+#include "vnic_dev.h"
+#include "vnic_stats.h"
+
+struct vnic_res {
+ void __iomem *vaddr;
+ unsigned int count;
+};
+
+struct vnic_dev {
+ void *priv;
+ struct pci_dev *pdev;
+ struct vnic_res res[RES_TYPE_MAX];
+ enum vnic_dev_intr_mode intr_mode;
+ struct vnic_devcmd __iomem *devcmd;
+ struct vnic_devcmd_notify *notify;
+ struct vnic_devcmd_notify notify_copy;
+ dma_addr_t notify_pa;
+ u32 *linkstatus;
+ dma_addr_t linkstatus_pa;
+ struct vnic_stats *stats;
+ dma_addr_t stats_pa;
+ struct vnic_devcmd_fw_info *fw_info;
+ dma_addr_t fw_info_pa;
+};
+
+#define VNIC_MAX_RES_HDR_SIZE \
+ (sizeof(struct vnic_resource_header) + \
+ sizeof(struct vnic_resource) * RES_TYPE_MAX)
+#define VNIC_RES_STRIDE 128
+
+void *vnic_dev_priv(struct vnic_dev *vdev)
+{
+ return vdev->priv;
+}
+
+static int vnic_dev_discover_res(struct vnic_dev *vdev,
+ struct vnic_dev_bar *bar)
+{
+ struct vnic_resource_header __iomem *rh;
+ struct vnic_resource __iomem *r;
+ u8 type;
+
+ if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
+ printk(KERN_ERR "vNIC BAR0 res hdr length error\n");
+ return -EINVAL;
+ }
+
+ rh = bar->vaddr;
+ if (!rh) {
+ printk(KERN_ERR "vNIC BAR0 res hdr not mem-mapped\n");
+ return -EINVAL;
+ }
+
+ if (ioread32(&rh->magic) != VNIC_RES_MAGIC ||
+ ioread32(&rh->version) != VNIC_RES_VERSION) {
+ printk(KERN_ERR "vNIC BAR0 res magic/version error "
+ "exp (%lx/%lx) curr (%x/%x)\n",
+ VNIC_RES_MAGIC, VNIC_RES_VERSION,
+ ioread32(&rh->magic), ioread32(&rh->version));
+ return -EINVAL;
+ }
+
+ r = (struct vnic_resource __iomem *)(rh + 1);
+
+ while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
+
+ u8 bar_num = ioread8(&r->bar);
+ u32 bar_offset = ioread32(&r->bar_offset);
+ u32 count = ioread32(&r->count);
+ u32 len;
+
+ r++;
+
+ if (bar_num != 0) /* only mapping in BAR0 resources */
+ continue;
+
+ switch (type) {
+ case RES_TYPE_WQ:
+ case RES_TYPE_RQ:
+ case RES_TYPE_CQ:
+ case RES_TYPE_INTR_CTRL:
+ /* each count is stride bytes long */
+ len = count * VNIC_RES_STRIDE;
+ if (len + bar_offset > bar->len) {
+ printk(KERN_ERR "vNIC BAR0 resource %d "
+ "out-of-bounds, offset 0x%x + "
+ "size 0x%x > bar len 0x%lx\n",
+ type, bar_offset,
+ len,
+ bar->len);
+ return -EINVAL;
+ }
+ break;
+ case RES_TYPE_INTR_PBA_LEGACY:
+ case RES_TYPE_DEVCMD:
+ len = count;
+ break;
+ default:
+ continue;
+ }
+
+ vdev->res[type].count = count;
+ vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
+ }
+
+ return 0;
+}
+
+unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
+ enum vnic_res_type type)
+{
+ return vdev->res[type].count;
+}
+
+void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
+ unsigned int index)
+{
+ if (!vdev->res[type].vaddr)
+ return NULL;
+
+ switch (type) {
+ case RES_TYPE_WQ:
+ case RES_TYPE_RQ:
+ case RES_TYPE_CQ:
+ case RES_TYPE_INTR_CTRL:
+ return (char __iomem *)vdev->res[type].vaddr +
+ index * VNIC_RES_STRIDE;
+ default:
+ return (char __iomem *)vdev->res[type].vaddr;
+ }
+}
+
+unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ /* The base address of the desc rings must be 512 byte aligned.
+ * Descriptor count is aligned to groups of 32 descriptors. A
+ * count of 0 means the maximum 4096 descriptors. Descriptor
+ * size is aligned to 16 bytes.
+ */
+
+ unsigned int count_align = 32;
+ unsigned int desc_align = 16;
+
+ ring->base_align = 512;
+
+ if (desc_count == 0)
+ desc_count = 4096;
+
+ ring->desc_count = ALIGN(desc_count, count_align);
+
+ ring->desc_size = ALIGN(desc_size, desc_align);
+
+ ring->size = ring->desc_count * ring->desc_size;
+ ring->size_unaligned = ring->size + ring->base_align;
+
+ return ring->size_unaligned;
+}
+
+void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
+{
+ memset(ring->descs, 0, ring->size);
+}
+
+int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ vnic_dev_desc_ring_size(ring, desc_count, desc_size);
+
+ ring->descs_unaligned = pci_alloc_consistent(vdev->pdev,
+ ring->size_unaligned,
+ &ring->base_addr_unaligned);
+
+ if (!ring->descs_unaligned) {
+ printk(KERN_ERR
+ "Failed to allocate ring (size=%d), aborting\n",
+ (int)ring->size);
+ return -ENOMEM;
+ }
+
+ ring->base_addr = ALIGN(ring->base_addr_unaligned,
+ ring->base_align);
+ ring->descs = (u8 *)ring->descs_unaligned +
+ (ring->base_addr - ring->base_addr_unaligned);
+
+ vnic_dev_clear_desc_ring(ring);
+
+ ring->desc_avail = ring->desc_count - 1;
+
+ return 0;
+}
+
+void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
+{
+ if (ring->descs) {
+ pci_free_consistent(vdev->pdev,
+ ring->size_unaligned,
+ ring->descs_unaligned,
+ ring->base_addr_unaligned);
+ ring->descs = NULL;
+ }
+}
+
+int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
+ u64 *a0, u64 *a1, int wait)
+{
+ struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
+ int delay;
+ u32 status;
+ int dev_cmd_err[] = {
+ /* convert from fw's version of error.h to host's version */
+ 0, /* ERR_SUCCESS */
+ EINVAL, /* ERR_EINVAL */
+ EFAULT, /* ERR_EFAULT */
+ EPERM, /* ERR_EPERM */
+ EBUSY, /* ERR_EBUSY */
+ };
+ int err;
+
+ status = ioread32(&devcmd->status);
+ if (status & STAT_BUSY) {
+ printk(KERN_ERR "Busy devcmd %d\n", _CMD_N(cmd));
+ return -EBUSY;
+ }
+
+ if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
+ writeq(*a0, &devcmd->args[0]);
+ writeq(*a1, &devcmd->args[1]);
+ wmb();
+ }
+
+ iowrite32(cmd, &devcmd->cmd);
+
+ if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
+ return 0;
+
+ for (delay = 0; delay < wait; delay++) {
+
+ udelay(100);
+
+ status = ioread32(&devcmd->status);
+ if (!(status & STAT_BUSY)) {
+
+ if (status & STAT_ERROR) {
+ err = dev_cmd_err[(int)readq(&devcmd->args[0])];
+ printk(KERN_ERR "Error %d devcmd %d\n",
+ err, _CMD_N(cmd));
+ return -err;
+ }
+
+ if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
+ rmb();
+ *a0 = readq(&devcmd->args[0]);
+ *a1 = readq(&devcmd->args[1]);
+ }
+
+ return 0;
+ }
+ }
+
+ printk(KERN_ERR "Timedout devcmd %d\n", _CMD_N(cmd));
+ return -ETIMEDOUT;
+}
+
+int vnic_dev_fw_info(struct vnic_dev *vdev,
+ struct vnic_devcmd_fw_info **fw_info)
+{
+ u64 a0, a1 = 0;
+ int wait = 1000;
+ int err = 0;
+
+ if (!vdev->fw_info) {
+ vdev->fw_info = pci_alloc_consistent(vdev->pdev,
+ sizeof(struct vnic_devcmd_fw_info),
+ &vdev->fw_info_pa);
+ if (!vdev->fw_info)
+ return -ENOMEM;
+
+ a0 = vdev->fw_info_pa;
+
+ /* only get fw_info once and cache it */
+ err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
+ }
+
+ *fw_info = vdev->fw_info;
+
+ return err;
+}
+
+int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
+ void *value)
+{
+ u64 a0, a1;
+ int wait = 1000;
+ int err;
+
+ a0 = offset;
+ a1 = size;
+
+ err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
+
+ switch (size) {
+ case 1: *(u8 *)value = (u8)a0; break;
+ case 2: *(u16 *)value = (u16)a0; break;
+ case 4: *(u32 *)value = (u32)a0; break;
+ case 8: *(u64 *)value = a0; break;
+ default: BUG(); break;
+ }
+
+ return err;
+}
+
+int vnic_dev_stats_clear(struct vnic_dev *vdev)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
+}
+
+int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
+{
+ u64 a0, a1;
+ int wait = 1000;
+
+ if (!vdev->stats) {
+ vdev->stats = pci_alloc_consistent(vdev->pdev,
+ sizeof(struct vnic_stats), &vdev->stats_pa);
+ if (!vdev->stats)
+ return -ENOMEM;
+ }
+
+ *stats = vdev->stats;
+ a0 = vdev->stats_pa;
+ a1 = sizeof(struct vnic_stats);
+
+ return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
+}
+
+int vnic_dev_close(struct vnic_dev *vdev)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
+}
+
+int vnic_dev_enable(struct vnic_dev *vdev)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
+}
+
+int vnic_dev_disable(struct vnic_dev *vdev)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
+}
+
+int vnic_dev_open(struct vnic_dev *vdev, int arg)
+{
+ u64 a0 = (u32)arg, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
+}
+
+int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ *done = 0;
+
+ err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
+ if (err)
+ return err;
+
+ *done = (a0 == 0);
+
+ return 0;
+}
+
+int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
+{
+ u64 a0 = (u32)arg, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
+}
+
+int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ *done = 0;
+
+ err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait);
+ if (err)
+ return err;
+
+ *done = (a0 == 0);
+
+ return 0;
+}
+
+int vnic_dev_hang_notify(struct vnic_dev *vdev)
+{
+ u64 a0, a1;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
+}
+
+int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
+{
+ u64 a0, a1;
+ int wait = 1000;
+ int err, i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac_addr[i] = 0;
+
+ err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+ if (err)
+ return err;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac_addr[i] = ((u8 *)&a0)[i];
+
+ return 0;
+}
+
+void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
+ int broadcast, int promisc, int allmulti)
+{
+ u64 a0, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
+ (multicast ? CMD_PFILTER_MULTICAST : 0) |
+ (broadcast ? CMD_PFILTER_BROADCAST : 0) |
+ (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
+ (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
+
+ err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait);
+ if (err)
+ printk(KERN_ERR "Can't set packet filter\n");
+}
+
+void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ int err;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ ((u8 *)&a0)[i] = addr[i];
+
+ err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+ if (err)
+ printk(KERN_ERR
+ "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
+ err);
+}
+
+void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
+{
+ u64 a0 = 0, a1 = 0;
+ int wait = 1000;
+ int err;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ ((u8 *)&a0)[i] = addr[i];
+
+ err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
+ if (err)
+ printk(KERN_ERR
+ "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
+ err);
+}
+
+int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
+{
+ u64 a0, a1;
+ int wait = 1000;
+
+ if (!vdev->notify) {
+ vdev->notify = pci_alloc_consistent(vdev->pdev,
+ sizeof(struct vnic_devcmd_notify),
+ &vdev->notify_pa);
+ if (!vdev->notify)
+ return -ENOMEM;
+ }
+
+ a0 = vdev->notify_pa;
+ a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
+ a1 += sizeof(struct vnic_devcmd_notify);
+
+ return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
+}
+
+void vnic_dev_notify_unset(struct vnic_dev *vdev)
+{
+ u64 a0, a1;
+ int wait = 1000;
+
+ a0 = 0; /* paddr = 0 to unset notify buffer */
+ a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */
+ a1 += sizeof(struct vnic_devcmd_notify);
+
+ vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
+}
+
+static int vnic_dev_notify_ready(struct vnic_dev *vdev)
+{
+ u32 *words;
+ unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
+ unsigned int i;
+ u32 csum;
+
+ if (!vdev->notify)
+ return 0;
+
+ do {
+ csum = 0;
+ memcpy(&vdev->notify_copy, vdev->notify,
+ sizeof(struct vnic_devcmd_notify));
+ words = (u32 *)&vdev->notify_copy;
+ for (i = 1; i < nwords; i++)
+ csum += words[i];
+ } while (csum != words[0]);
+
+ return 1;
+}
+
+int vnic_dev_init(struct vnic_dev *vdev, int arg)
+{
+ u64 a0 = (u32)arg, a1 = 0;
+ int wait = 1000;
+ return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
+}
+
+int vnic_dev_link_status(struct vnic_dev *vdev)
+{
+ if (vdev->linkstatus)
+ return *vdev->linkstatus;
+
+ if (!vnic_dev_notify_ready(vdev))
+ return 0;
+
+ return vdev->notify_copy.link_state;
+}
+
+u32 vnic_dev_port_speed(struct vnic_dev *vdev)
+{
+ if (!vnic_dev_notify_ready(vdev))
+ return 0;
+
+ return vdev->notify_copy.port_speed;
+}
+
+u32 vnic_dev_msg_lvl(struct vnic_dev *vdev)
+{
+ if (!vnic_dev_notify_ready(vdev))
+ return 0;
+
+ return vdev->notify_copy.msglvl;
+}
+
+u32 vnic_dev_mtu(struct vnic_dev *vdev)
+{
+ if (!vnic_dev_notify_ready(vdev))
+ return 0;
+
+ return vdev->notify_copy.mtu;
+}
+
+void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
+ enum vnic_dev_intr_mode intr_mode)
+{
+ vdev->intr_mode = intr_mode;
+}
+
+enum vnic_dev_intr_mode vnic_dev_get_intr_mode(
+ struct vnic_dev *vdev)
+{
+ return vdev->intr_mode;
+}
+
+void vnic_dev_unregister(struct vnic_dev *vdev)
+{
+ if (vdev) {
+ if (vdev->notify)
+ pci_free_consistent(vdev->pdev,
+ sizeof(struct vnic_devcmd_notify),
+ vdev->notify,
+ vdev->notify_pa);
+ if (vdev->linkstatus)
+ pci_free_consistent(vdev->pdev,
+ sizeof(u32),
+ vdev->linkstatus,
+ vdev->linkstatus_pa);
+ if (vdev->stats)
+ pci_free_consistent(vdev->pdev,
+ sizeof(struct vnic_dev),
+ vdev->stats, vdev->stats_pa);
+ if (vdev->fw_info)
+ pci_free_consistent(vdev->pdev,
+ sizeof(struct vnic_devcmd_fw_info),
+ vdev->fw_info, vdev->fw_info_pa);
+ kfree(vdev);
+ }
+}
+
+struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
+ void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar)
+{
+ if (!vdev) {
+ vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC);
+ if (!vdev)
+ return NULL;
+ }
+
+ vdev->priv = priv;
+ vdev->pdev = pdev;
+
+ if (vnic_dev_discover_res(vdev, bar))
+ goto err_out;
+
+ vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
+ if (!vdev->devcmd)
+ goto err_out;
+
+ return vdev;
+
+err_out:
+ vnic_dev_unregister(vdev);
+ return NULL;
+}
+
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
new file mode 100644
index 00000000000..b9dc1821c80
--- /dev/null
+++ b/drivers/net/enic/vnic_dev.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_DEV_H_
+#define _VNIC_DEV_H_
+
+#include "vnic_resource.h"
+#include "vnic_devcmd.h"
+
+#ifndef VNIC_PADDR_TARGET
+#define VNIC_PADDR_TARGET 0x0000000000000000ULL
+#endif
+
+#ifndef readq
+static inline u64 readq(void __iomem *reg)
+{
+ return (((u64)readl(reg + 0x4UL) << 32) |
+ (u64)readl(reg));
+}
+
+static inline void writeq(u64 val, void __iomem *reg)
+{
+ writel(val & 0xffffffff, reg);
+ writel(val >> 32, reg + 0x4UL);
+}
+#endif
+
+enum vnic_dev_intr_mode {
+ VNIC_DEV_INTR_MODE_UNKNOWN,
+ VNIC_DEV_INTR_MODE_INTX,
+ VNIC_DEV_INTR_MODE_MSI,
+ VNIC_DEV_INTR_MODE_MSIX,
+};
+
+struct vnic_dev_bar {
+ void __iomem *vaddr;
+ dma_addr_t bus_addr;
+ unsigned long len;
+};
+
+struct vnic_dev_ring {
+ void *descs;
+ size_t size;
+ dma_addr_t base_addr;
+ size_t base_align;
+ void *descs_unaligned;
+ size_t size_unaligned;
+ dma_addr_t base_addr_unaligned;
+ unsigned int desc_size;
+ unsigned int desc_count;
+ unsigned int desc_avail;
+};
+
+struct vnic_dev;
+struct vnic_stats;
+
+void *vnic_dev_priv(struct vnic_dev *vdev);
+unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
+ enum vnic_res_type type);
+void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
+ unsigned int index);
+unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
+ unsigned int desc_count, unsigned int desc_size);
+void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring);
+int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
+ unsigned int desc_count, unsigned int desc_size);
+void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
+ struct vnic_dev_ring *ring);
+int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
+ u64 *a0, u64 *a1, int wait);
+int vnic_dev_fw_info(struct vnic_dev *vdev,
+ struct vnic_devcmd_fw_info **fw_info);
+int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
+ void *value);
+int vnic_dev_stats_clear(struct vnic_dev *vdev);
+int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
+int vnic_dev_hang_notify(struct vnic_dev *vdev);
+void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
+ int broadcast, int promisc, int allmulti);
+void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
+void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
+int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
+int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
+void vnic_dev_notify_unset(struct vnic_dev *vdev);
+int vnic_dev_link_status(struct vnic_dev *vdev);
+u32 vnic_dev_port_speed(struct vnic_dev *vdev);
+u32 vnic_dev_msg_lvl(struct vnic_dev *vdev);
+u32 vnic_dev_mtu(struct vnic_dev *vdev);
+int vnic_dev_close(struct vnic_dev *vdev);
+int vnic_dev_enable(struct vnic_dev *vdev);
+int vnic_dev_disable(struct vnic_dev *vdev);
+int vnic_dev_open(struct vnic_dev *vdev, int arg);
+int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
+int vnic_dev_init(struct vnic_dev *vdev, int arg);
+int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
+int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
+void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
+ enum vnic_dev_intr_mode intr_mode);
+enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
+void vnic_dev_unregister(struct vnic_dev *vdev);
+struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
+ void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar);
+
+#endif /* _VNIC_DEV_H_ */
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
new file mode 100644
index 00000000000..d8617a3373b
--- /dev/null
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_DEVCMD_H_
+#define _VNIC_DEVCMD_H_
+
+#define _CMD_NBITS 14
+#define _CMD_VTYPEBITS 10
+#define _CMD_FLAGSBITS 6
+#define _CMD_DIRBITS 2
+
+#define _CMD_NMASK ((1 << _CMD_NBITS)-1)
+#define _CMD_VTYPEMASK ((1 << _CMD_VTYPEBITS)-1)
+#define _CMD_FLAGSMASK ((1 << _CMD_FLAGSBITS)-1)
+#define _CMD_DIRMASK ((1 << _CMD_DIRBITS)-1)
+
+#define _CMD_NSHIFT 0
+#define _CMD_VTYPESHIFT (_CMD_NSHIFT+_CMD_NBITS)
+#define _CMD_FLAGSSHIFT (_CMD_VTYPESHIFT+_CMD_VTYPEBITS)
+#define _CMD_DIRSHIFT (_CMD_FLAGSSHIFT+_CMD_FLAGSBITS)
+
+/*
+ * Direction bits (from host perspective).
+ */
+#define _CMD_DIR_NONE 0U
+#define _CMD_DIR_WRITE 1U
+#define _CMD_DIR_READ 2U
+#define _CMD_DIR_RW (_CMD_DIR_WRITE | _CMD_DIR_READ)
+
+/*
+ * Flag bits.
+ */
+#define _CMD_FLAGS_NONE 0U
+#define _CMD_FLAGS_NOWAIT 1U
+
+/*
+ * vNIC type bits.
+ */
+#define _CMD_VTYPE_NONE 0U
+#define _CMD_VTYPE_ENET 1U
+#define _CMD_VTYPE_FC 2U
+#define _CMD_VTYPE_SCSI 4U
+#define _CMD_VTYPE_ALL (_CMD_VTYPE_ENET | _CMD_VTYPE_FC | _CMD_VTYPE_SCSI)
+
+/*
+ * Used to create cmds..
+*/
+#define _CMDCF(dir, flags, vtype, nr) \
+ (((dir) << _CMD_DIRSHIFT) | \
+ ((flags) << _CMD_FLAGSSHIFT) | \
+ ((vtype) << _CMD_VTYPESHIFT) | \
+ ((nr) << _CMD_NSHIFT))
+#define _CMDC(dir, vtype, nr) _CMDCF(dir, 0, vtype, nr)
+#define _CMDCNW(dir, vtype, nr) _CMDCF(dir, _CMD_FLAGS_NOWAIT, vtype, nr)
+
+/*
+ * Used to decode cmds..
+*/
+#define _CMD_DIR(cmd) (((cmd) >> _CMD_DIRSHIFT) & _CMD_DIRMASK)
+#define _CMD_FLAGS(cmd) (((cmd) >> _CMD_FLAGSSHIFT) & _CMD_FLAGSMASK)
+#define _CMD_VTYPE(cmd) (((cmd) >> _CMD_VTYPESHIFT) & _CMD_VTYPEMASK)
+#define _CMD_N(cmd) (((cmd) >> _CMD_NSHIFT) & _CMD_NMASK)
+
+enum vnic_devcmd_cmd {
+ CMD_NONE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0),
+
+ /* mcpu fw info in mem: (u64)a0=paddr to struct vnic_devcmd_fw_info */
+ CMD_MCPU_FW_INFO = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1),
+
+ /* dev-specific block member:
+ * in: (u16)a0=offset,(u8)a1=size
+ * out: a0=value */
+ CMD_DEV_SPEC = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 2),
+
+ /* stats clear */
+ CMD_STATS_CLEAR = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 3),
+
+ /* stats dump in mem: (u64)a0=paddr to stats area,
+ * (u16)a1=sizeof stats area */
+ CMD_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 4),
+
+ /* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */
+ CMD_PACKET_FILTER = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7),
+
+ /* hang detection notification */
+ CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8),
+
+ /* MAC address in (u48)a0 */
+ CMD_MAC_ADDR = _CMDC(_CMD_DIR_READ,
+ _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9),
+
+ /* disable/enable promisc mode: (u8)a0=0/1 */
+/***** XXX DEPRECATED *****/
+ CMD_PROMISC_MODE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 10),
+
+ /* disable/enable all-multi mode: (u8)a0=0/1 */
+/***** XXX DEPRECATED *****/
+ CMD_ALLMULTI_MODE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 11),
+
+ /* add addr from (u48)a0 */
+ CMD_ADDR_ADD = _CMDCNW(_CMD_DIR_WRITE,
+ _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 12),
+
+ /* del addr from (u48)a0 */
+ CMD_ADDR_DEL = _CMDCNW(_CMD_DIR_WRITE,
+ _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 13),
+
+ /* add VLAN id in (u16)a0 */
+ CMD_VLAN_ADD = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 14),
+
+ /* del VLAN id in (u16)a0 */
+ CMD_VLAN_DEL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 15),
+
+ /* nic_cfg in (u32)a0 */
+ CMD_NIC_CFG = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16),
+
+ /* union vnic_rss_key in mem: (u64)a0=paddr, (u16)a1=len */
+ CMD_RSS_KEY = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 17),
+
+ /* union vnic_rss_cpu in mem: (u64)a0=paddr, (u16)a1=len */
+ CMD_RSS_CPU = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 18),
+
+ /* initiate softreset */
+ CMD_SOFT_RESET = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 19),
+
+ /* softreset status:
+ * out: a0=0 reset complete, a0=1 reset in progress */
+ CMD_SOFT_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 20),
+
+ /* set struct vnic_devcmd_notify buffer in mem:
+ * in:
+ * (u64)a0=paddr to notify (set paddr=0 to unset)
+ * (u32)a1 & 0x00000000ffffffff=sizeof(struct vnic_devcmd_notify)
+ * (u16)a1 & 0x0000ffff00000000=intr num (-1 for no intr)
+ * out:
+ * (u32)a1 = effective size
+ */
+ CMD_NOTIFY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 21),
+
+ /* UNDI API: (u64)a0=paddr to s_PXENV_UNDI_ struct,
+ * (u8)a1=PXENV_UNDI_xxx */
+ CMD_UNDI = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 22),
+
+ /* initiate open sequence (u32)a0=flags (see CMD_OPENF_*) */
+ CMD_OPEN = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 23),
+
+ /* open status:
+ * out: a0=0 open complete, a0=1 open in progress */
+ CMD_OPEN_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 24),
+
+ /* close vnic */
+ CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
+
+ /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
+ CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
+
+ /* variant of CMD_INIT, with provisioning info
+ * (u64)a0=paddr of vnic_devcmd_provinfo
+ * (u32)a1=sizeof provision info */
+ CMD_INIT_PROV_INFO = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 27),
+
+ /* enable virtual link */
+ CMD_ENABLE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28),
+
+ /* disable virtual link */
+ CMD_DISABLE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29),
+
+ /* stats dump all vnics on uplink in mem: (u64)a0=paddr (u32)a1=uif */
+ CMD_STATS_DUMP_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 30),
+
+ /* init status:
+ * out: a0=0 init complete, a0=1 init in progress
+ * if a0=0, a1=errno */
+ CMD_INIT_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31),
+
+ /* INT13 API: (u64)a0=paddr to vnic_int13_params struct
+ * (u8)a1=INT13_CMD_xxx */
+ CMD_INT13 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32),
+
+ /* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */
+ CMD_LOGICAL_UPLINK = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 33),
+
+ /* undo initialize of virtual link */
+ CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
+};
+
+/* flags for CMD_OPEN */
+#define CMD_OPENF_OPROM 0x1 /* open coming from option rom */
+
+/* flags for CMD_INIT */
+#define CMD_INITF_DEFAULT_MAC 0x1 /* init with default mac addr */
+
+/* flags for CMD_PACKET_FILTER */
+#define CMD_PFILTER_DIRECTED 0x01
+#define CMD_PFILTER_MULTICAST 0x02
+#define CMD_PFILTER_BROADCAST 0x04
+#define CMD_PFILTER_PROMISCUOUS 0x08
+#define CMD_PFILTER_ALL_MULTICAST 0x10
+
+enum vnic_devcmd_status {
+ STAT_NONE = 0,
+ STAT_BUSY = 1 << 0, /* cmd in progress */
+ STAT_ERROR = 1 << 1, /* last cmd caused error (code in a0) */
+};
+
+enum vnic_devcmd_error {
+ ERR_SUCCESS = 0,
+ ERR_EINVAL = 1,
+ ERR_EFAULT = 2,
+ ERR_EPERM = 3,
+ ERR_EBUSY = 4,
+ ERR_ECMDUNKNOWN = 5,
+ ERR_EBADSTATE = 6,
+ ERR_ENOMEM = 7,
+ ERR_ETIMEDOUT = 8,
+ ERR_ELINKDOWN = 9,
+};
+
+struct vnic_devcmd_fw_info {
+ char fw_version[32];
+ char fw_build[32];
+ char hw_version[32];
+ char hw_serial_number[32];
+};
+
+struct vnic_devcmd_notify {
+ u32 csum; /* checksum over following words */
+
+ u32 link_state; /* link up == 1 */
+ u32 port_speed; /* effective port speed (rate limit) */
+ u32 mtu; /* MTU */
+ u32 msglvl; /* requested driver msg lvl */
+ u32 uif; /* uplink interface */
+ u32 status; /* status bits (see VNIC_STF_*) */
+ u32 error; /* error code (see ERR_*) for first ERR */
+};
+#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */
+
+struct vnic_devcmd_provinfo {
+ u8 oui[3];
+ u8 type;
+ u8 data[0];
+};
+
+/*
+ * Writing cmd register causes STAT_BUSY to get set in status register.
+ * When cmd completes, STAT_BUSY will be cleared.
+ *
+ * If cmd completed successfully STAT_ERROR will be clear
+ * and args registers contain cmd-specific results.
+ *
+ * If cmd error, STAT_ERROR will be set and args[0] contains error code.
+ *
+ * status register is read-only. While STAT_BUSY is set,
+ * all other register contents are read-only.
+ */
+
+/* Make sizeof(vnic_devcmd) a power-of-2 for I/O BAR. */
+#define VNIC_DEVCMD_NARGS 15
+struct vnic_devcmd {
+ u32 status; /* RO */
+ u32 cmd; /* RW */
+ u64 args[VNIC_DEVCMD_NARGS]; /* RW cmd args (little-endian) */
+};
+
+#endif /* _VNIC_DEVCMD_H_ */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
new file mode 100644
index 00000000000..6332ac9391b
--- /dev/null
+++ b/drivers/net/enic/vnic_enet.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_ENIC_H_
+#define _VNIC_ENIC_H_
+
+/* Device-specific region: enet configuration */
+struct vnic_enet_config {
+ u32 flags;
+ u32 wq_desc_count;
+ u32 rq_desc_count;
+ u16 mtu;
+ u16 intr_timer;
+ u8 intr_timer_type;
+ u8 intr_mode;
+ char devname[16];
+};
+
+#define VENETF_TSO 0x1 /* TSO enabled */
+#define VENETF_LRO 0x2 /* LRO enabled */
+#define VENETF_RXCSUM 0x4 /* RX csum enabled */
+#define VENETF_TXCSUM 0x8 /* TX csum enabled */
+#define VENETF_RSS 0x10 /* RSS enabled */
+#define VENETF_RSSHASH_IPV4 0x20 /* Hash on IPv4 fields */
+#define VENETF_RSSHASH_TCPIPV4 0x40 /* Hash on TCP + IPv4 fields */
+#define VENETF_RSSHASH_IPV6 0x80 /* Hash on IPv6 fields */
+#define VENETF_RSSHASH_TCPIPV6 0x100 /* Hash on TCP + IPv6 fields */
+#define VENETF_RSSHASH_IPV6_EX 0x200 /* Hash on IPv6 extended fields */
+#define VENETF_RSSHASH_TCPIPV6_EX 0x400 /* Hash on TCP + IPv6 ext. fields */
+
+#endif /* _VNIC_ENIC_H_ */
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
new file mode 100644
index 00000000000..ddc38f8f465
--- /dev/null
+++ b/drivers/net/enic/vnic_intr.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "vnic_dev.h"
+#include "vnic_intr.h"
+
+void vnic_intr_free(struct vnic_intr *intr)
+{
+ intr->ctrl = NULL;
+}
+
+int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
+ unsigned int index)
+{
+ intr->index = index;
+ intr->vdev = vdev;
+
+ intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index);
+ if (!intr->ctrl) {
+ printk(KERN_ERR "Failed to hook INTR[%d].ctrl resource\n",
+ index);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+ unsigned int coalescing_type, unsigned int mask_on_assertion)
+{
+ iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer);
+ iowrite32(coalescing_type, &intr->ctrl->coalescing_type);
+ iowrite32(mask_on_assertion, &intr->ctrl->mask_on_assertion);
+ iowrite32(0, &intr->ctrl->int_credits);
+}
+
+void vnic_intr_clean(struct vnic_intr *intr)
+{
+ iowrite32(0, &intr->ctrl->int_credits);
+}
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
new file mode 100644
index 00000000000..ccc408116af
--- /dev/null
+++ b/drivers/net/enic/vnic_intr.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_INTR_H_
+#define _VNIC_INTR_H_
+
+#include <linux/pci.h>
+
+#include "vnic_dev.h"
+
+#define VNIC_INTR_TIMER_MAX 0xffff
+
+#define VNIC_INTR_TIMER_TYPE_ABS 0
+#define VNIC_INTR_TIMER_TYPE_QUIET 1
+
+/* Interrupt control */
+struct vnic_intr_ctrl {
+ u32 coalescing_timer; /* 0x00 */
+ u32 pad0;
+ u32 coalescing_value; /* 0x08 */
+ u32 pad1;
+ u32 coalescing_type; /* 0x10 */
+ u32 pad2;
+ u32 mask_on_assertion; /* 0x18 */
+ u32 pad3;
+ u32 mask; /* 0x20 */
+ u32 pad4;
+ u32 int_credits; /* 0x28 */
+ u32 pad5;
+ u32 int_credit_return; /* 0x30 */
+ u32 pad6;
+};
+
+struct vnic_intr {
+ unsigned int index;
+ struct vnic_dev *vdev;
+ struct vnic_intr_ctrl __iomem *ctrl; /* memory-mapped */
+};
+
+static inline void vnic_intr_unmask(struct vnic_intr *intr)
+{
+ iowrite32(0, &intr->ctrl->mask);
+}
+
+static inline void vnic_intr_mask(struct vnic_intr *intr)
+{
+ iowrite32(1, &intr->ctrl->mask);
+}
+
+static inline void vnic_intr_return_credits(struct vnic_intr *intr,
+ unsigned int credits, int unmask, int reset_timer)
+{
+#define VNIC_INTR_UNMASK_SHIFT 16
+#define VNIC_INTR_RESET_TIMER_SHIFT 17
+
+ u32 int_credit_return = (credits & 0xffff) |
+ (unmask ? (1 << VNIC_INTR_UNMASK_SHIFT) : 0) |
+ (reset_timer ? (1 << VNIC_INTR_RESET_TIMER_SHIFT) : 0);
+
+ iowrite32(int_credit_return, &intr->ctrl->int_credit_return);
+}
+
+static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
+{
+ /* get and ack interrupt in one read (clear-and-ack-on-read) */
+ return ioread32(legacy_pba);
+}
+
+void vnic_intr_free(struct vnic_intr *intr);
+int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
+ unsigned int index);
+void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+ unsigned int coalescing_type, unsigned int mask_on_assertion);
+void vnic_intr_clean(struct vnic_intr *intr);
+
+#endif /* _VNIC_INTR_H_ */
diff --git a/drivers/net/enic/vnic_nic.h b/drivers/net/enic/vnic_nic.h
new file mode 100644
index 00000000000..dadf26fae69
--- /dev/null
+++ b/drivers/net/enic/vnic_nic.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_NIC_H_
+#define _VNIC_NIC_H_
+
+#define NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD 0xffUL
+#define NIC_CFG_RSS_DEFAULT_CPU_SHIFT 0
+#define NIC_CFG_RSS_HASH_TYPE (0xffUL << 8)
+#define NIC_CFG_RSS_HASH_TYPE_MASK_FIELD 0xffUL
+#define NIC_CFG_RSS_HASH_TYPE_SHIFT 8
+#define NIC_CFG_RSS_HASH_BITS (7UL << 16)
+#define NIC_CFG_RSS_HASH_BITS_MASK_FIELD 7UL
+#define NIC_CFG_RSS_HASH_BITS_SHIFT 16
+#define NIC_CFG_RSS_BASE_CPU (7UL << 19)
+#define NIC_CFG_RSS_BASE_CPU_MASK_FIELD 7UL
+#define NIC_CFG_RSS_BASE_CPU_SHIFT 19
+#define NIC_CFG_RSS_ENABLE (1UL << 22)
+#define NIC_CFG_RSS_ENABLE_MASK_FIELD 1UL
+#define NIC_CFG_RSS_ENABLE_SHIFT 22
+#define NIC_CFG_TSO_IPID_SPLIT_EN (1UL << 23)
+#define NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD 1UL
+#define NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT 23
+#define NIC_CFG_IG_VLAN_STRIP_EN (1UL << 24)
+#define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD 1UL
+#define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT 24
+
+static inline void vnic_set_nic_cfg(u32 *nic_cfg,
+ u8 rss_default_cpu, u8 rss_hash_type,
+ u8 rss_hash_bits, u8 rss_base_cpu,
+ u8 rss_enable, u8 tso_ipid_split_en,
+ u8 ig_vlan_strip_en)
+{
+ *nic_cfg = (rss_default_cpu & NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD) |
+ ((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_MASK_FIELD)
+ << NIC_CFG_RSS_HASH_TYPE_SHIFT) |
+ ((rss_hash_bits & NIC_CFG_RSS_HASH_BITS_MASK_FIELD)
+ << NIC_CFG_RSS_HASH_BITS_SHIFT) |
+ ((rss_base_cpu & NIC_CFG_RSS_BASE_CPU_MASK_FIELD)
+ << NIC_CFG_RSS_BASE_CPU_SHIFT) |
+ ((rss_enable & NIC_CFG_RSS_ENABLE_MASK_FIELD)
+ << NIC_CFG_RSS_ENABLE_SHIFT) |
+ ((tso_ipid_split_en & NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD)
+ << NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT) |
+ ((ig_vlan_strip_en & NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD)
+ << NIC_CFG_IG_VLAN_STRIP_EN_SHIFT);
+}
+
+#endif /* _VNIC_NIC_H_ */
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h
new file mode 100644
index 00000000000..144d2812f08
--- /dev/null
+++ b/drivers/net/enic/vnic_resource.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_RESOURCE_H_
+#define _VNIC_RESOURCE_H_
+
+#define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */
+#define VNIC_RES_VERSION 0x00000000L
+
+/* vNIC resource types */
+enum vnic_res_type {
+ RES_TYPE_EOL, /* End-of-list */
+ RES_TYPE_WQ, /* Work queues */
+ RES_TYPE_RQ, /* Receive queues */
+ RES_TYPE_CQ, /* Completion queues */
+ RES_TYPE_RSVD1,
+ RES_TYPE_NIC_CFG, /* Enet NIC config registers */
+ RES_TYPE_RSVD2,
+ RES_TYPE_RSVD3,
+ RES_TYPE_RSVD4,
+ RES_TYPE_RSVD5,
+ RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */
+ RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */
+ RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */
+ RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status, r2c */
+ RES_TYPE_RSVD6,
+ RES_TYPE_RSVD7,
+ RES_TYPE_DEVCMD, /* Device command region */
+ RES_TYPE_PASS_THRU_PAGE, /* Pass-thru page */
+
+ RES_TYPE_MAX, /* Count of resource types */
+};
+
+struct vnic_resource_header {
+ u32 magic;
+ u32 version;
+};
+
+struct vnic_resource {
+ u8 type;
+ u8 bar;
+ u8 pad[2];
+ u32 bar_offset;
+ u32 count;
+};
+
+#endif /* _VNIC_RESOURCE_H_ */
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c
new file mode 100644
index 00000000000..9365e63e821
--- /dev/null
+++ b/drivers/net/enic/vnic_rq.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "vnic_dev.h"
+#include "vnic_rq.h"
+
+static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
+{
+ struct vnic_rq_buf *buf;
+ struct vnic_dev *vdev;
+ unsigned int i, j, count = rq->ring.desc_count;
+ unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
+
+ vdev = rq->vdev;
+
+ for (i = 0; i < blks; i++) {
+ rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ, GFP_ATOMIC);
+ if (!rq->bufs[i]) {
+ printk(KERN_ERR "Failed to alloc rq_bufs\n");
+ return -ENOMEM;
+ }
+ }
+
+ for (i = 0; i < blks; i++) {
+ buf = rq->bufs[i];
+ for (j = 0; j < VNIC_RQ_BUF_BLK_ENTRIES; j++) {
+ buf->index = i * VNIC_RQ_BUF_BLK_ENTRIES + j;
+ buf->desc = (u8 *)rq->ring.descs +
+ rq->ring.desc_size * buf->index;
+ if (buf->index + 1 == count) {
+ buf->next = rq->bufs[0];
+ break;
+ } else if (j + 1 == VNIC_RQ_BUF_BLK_ENTRIES) {
+ buf->next = rq->bufs[i + 1];
+ } else {
+ buf->next = buf + 1;
+ buf++;
+ }
+ }
+ }
+
+ rq->to_use = rq->to_clean = rq->bufs[0];
+ rq->buf_index = 0;
+
+ return 0;
+}
+
+void vnic_rq_free(struct vnic_rq *rq)
+{
+ struct vnic_dev *vdev;
+ unsigned int i;
+
+ vdev = rq->vdev;
+
+ vnic_dev_free_desc_ring(vdev, &rq->ring);
+
+ for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) {
+ kfree(rq->bufs[i]);
+ rq->bufs[i] = NULL;
+ }
+
+ rq->ctrl = NULL;
+}
+
+int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ int err;
+
+ rq->index = index;
+ rq->vdev = vdev;
+
+ rq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_RQ, index);
+ if (!rq->ctrl) {
+ printk(KERN_ERR "Failed to hook RQ[%d] resource\n", index);
+ return -EINVAL;
+ }
+
+ vnic_rq_disable(rq);
+
+ err = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size);
+ if (err)
+ return err;
+
+ err = vnic_rq_alloc_bufs(rq);
+ if (err) {
+ vnic_rq_free(rq);
+ return err;
+ }
+
+ return 0;
+}
+
+void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
+ unsigned int error_interrupt_enable,
+ unsigned int error_interrupt_offset)
+{
+ u64 paddr;
+ u32 fetch_index;
+
+ paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET;
+ writeq(paddr, &rq->ctrl->ring_base);
+ iowrite32(rq->ring.desc_count, &rq->ctrl->ring_size);
+ iowrite32(cq_index, &rq->ctrl->cq_index);
+ iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable);
+ iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset);
+ iowrite32(0, &rq->ctrl->dropped_packet_count);
+ iowrite32(0, &rq->ctrl->error_status);
+
+ /* Use current fetch_index as the ring starting point */
+ fetch_index = ioread32(&rq->ctrl->fetch_index);
+ rq->to_use = rq->to_clean =
+ &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES]
+ [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES];
+ iowrite32(fetch_index, &rq->ctrl->posted_index);
+
+ rq->buf_index = 0;
+}
+
+unsigned int vnic_rq_error_status(struct vnic_rq *rq)
+{
+ return ioread32(&rq->ctrl->error_status);
+}
+
+void vnic_rq_enable(struct vnic_rq *rq)
+{
+ iowrite32(1, &rq->ctrl->enable);
+}
+
+int vnic_rq_disable(struct vnic_rq *rq)
+{
+ unsigned int wait;
+
+ iowrite32(0, &rq->ctrl->enable);
+
+ /* Wait for HW to ACK disable request */
+ for (wait = 0; wait < 100; wait++) {
+ if (!(ioread32(&rq->ctrl->running)))
+ return 0;
+ udelay(1);
+ }
+
+ printk(KERN_ERR "Failed to disable RQ[%d]\n", rq->index);
+
+ return -ETIMEDOUT;
+}
+
+void vnic_rq_clean(struct vnic_rq *rq,
+ void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf))
+{
+ struct vnic_rq_buf *buf;
+ u32 fetch_index;
+
+ BUG_ON(ioread32(&rq->ctrl->enable));
+
+ buf = rq->to_clean;
+
+ while (vnic_rq_desc_used(rq) > 0) {
+
+ (*buf_clean)(rq, buf);
+
+ buf = rq->to_clean = buf->next;
+ rq->ring.desc_avail++;
+ }
+
+ /* Use current fetch_index as the ring starting point */
+ fetch_index = ioread32(&rq->ctrl->fetch_index);
+ rq->to_use = rq->to_clean =
+ &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES]
+ [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES];
+ iowrite32(fetch_index, &rq->ctrl->posted_index);
+
+ rq->buf_index = 0;
+
+ vnic_dev_clear_desc_ring(&rq->ring);
+}
+
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
new file mode 100644
index 00000000000..82bfca67cc4
--- /dev/null
+++ b/drivers/net/enic/vnic_rq.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_RQ_H_
+#define _VNIC_RQ_H_
+
+#include <linux/pci.h>
+
+#include "vnic_dev.h"
+#include "vnic_cq.h"
+
+/* Receive queue control */
+struct vnic_rq_ctrl {
+ u64 ring_base; /* 0x00 */
+ u32 ring_size; /* 0x08 */
+ u32 pad0;
+ u32 posted_index; /* 0x10 */
+ u32 pad1;
+ u32 cq_index; /* 0x18 */
+ u32 pad2;
+ u32 enable; /* 0x20 */
+ u32 pad3;
+ u32 running; /* 0x28 */
+ u32 pad4;
+ u32 fetch_index; /* 0x30 */
+ u32 pad5;
+ u32 error_interrupt_enable; /* 0x38 */
+ u32 pad6;
+ u32 error_interrupt_offset; /* 0x40 */
+ u32 pad7;
+ u32 error_status; /* 0x48 */
+ u32 pad8;
+ u32 dropped_packet_count; /* 0x50 */
+ u32 pad9;
+ u32 dropped_packet_count_rc; /* 0x58 */
+ u32 pad10;
+};
+
+/* Break the vnic_rq_buf allocations into blocks of 64 entries */
+#define VNIC_RQ_BUF_BLK_ENTRIES 64
+#define VNIC_RQ_BUF_BLK_SZ \
+ (VNIC_RQ_BUF_BLK_ENTRIES * sizeof(struct vnic_rq_buf))
+#define VNIC_RQ_BUF_BLKS_NEEDED(entries) \
+ DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES)
+#define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096)
+
+struct vnic_rq_buf {
+ struct vnic_rq_buf *next;
+ dma_addr_t dma_addr;
+ void *os_buf;
+ unsigned int os_buf_index;
+ unsigned int len;
+ unsigned int index;
+ void *desc;
+};
+
+struct vnic_rq {
+ unsigned int index;
+ struct vnic_dev *vdev;
+ struct vnic_rq_ctrl __iomem *ctrl; /* memory-mapped */
+ struct vnic_dev_ring ring;
+ struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX];
+ struct vnic_rq_buf *to_use;
+ struct vnic_rq_buf *to_clean;
+ void *os_buf_head;
+ unsigned int buf_index;
+ unsigned int pkts_outstanding;
+};
+
+static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
+{
+ /* how many does SW own? */
+ return rq->ring.desc_avail;
+}
+
+static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq)
+{
+ /* how many does HW own? */
+ return rq->ring.desc_count - rq->ring.desc_avail - 1;
+}
+
+static inline void *vnic_rq_next_desc(struct vnic_rq *rq)
+{
+ return rq->to_use->desc;
+}
+
+static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
+{
+ return rq->to_use->index;
+}
+
+static inline unsigned int vnic_rq_next_buf_index(struct vnic_rq *rq)
+{
+ return rq->buf_index++;
+}
+
+static inline void vnic_rq_post(struct vnic_rq *rq,
+ void *os_buf, unsigned int os_buf_index,
+ dma_addr_t dma_addr, unsigned int len)
+{
+ struct vnic_rq_buf *buf = rq->to_use;
+
+ buf->os_buf = os_buf;
+ buf->os_buf_index = os_buf_index;
+ buf->dma_addr = dma_addr;
+ buf->len = len;
+
+ buf = buf->next;
+ rq->to_use = buf;
+ rq->ring.desc_avail--;
+
+ /* Move the posted_index every nth descriptor
+ */
+
+#ifndef VNIC_RQ_RETURN_RATE
+#define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */
+#endif
+
+ if ((buf->index & VNIC_RQ_RETURN_RATE) == 0)
+ iowrite32(buf->index, &rq->ctrl->posted_index);
+}
+
+static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
+{
+ rq->ring.desc_avail += count;
+}
+
+enum desc_return_options {
+ VNIC_RQ_RETURN_DESC,
+ VNIC_RQ_DEFER_RETURN_DESC,
+};
+
+static inline void vnic_rq_service(struct vnic_rq *rq,
+ struct cq_desc *cq_desc, u16 completed_index,
+ int desc_return, void (*buf_service)(struct vnic_rq *rq,
+ struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
+ int skipped, void *opaque), void *opaque)
+{
+ struct vnic_rq_buf *buf;
+ int skipped;
+
+ buf = rq->to_clean;
+ while (1) {
+
+ skipped = (buf->index != completed_index);
+
+ (*buf_service)(rq, cq_desc, buf, skipped, opaque);
+
+ if (desc_return == VNIC_RQ_RETURN_DESC)
+ rq->ring.desc_avail++;
+
+ rq->to_clean = buf->next;
+
+ if (!skipped)
+ break;
+
+ buf = rq->to_clean;
+ }
+}
+
+static inline int vnic_rq_fill(struct vnic_rq *rq,
+ int (*buf_fill)(struct vnic_rq *rq))
+{
+ int err;
+
+ while (vnic_rq_desc_avail(rq) > 1) {
+
+ err = (*buf_fill)(rq);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+void vnic_rq_free(struct vnic_rq *rq);
+int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size);
+void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
+ unsigned int error_interrupt_enable,
+ unsigned int error_interrupt_offset);
+unsigned int vnic_rq_error_status(struct vnic_rq *rq);
+void vnic_rq_enable(struct vnic_rq *rq);
+int vnic_rq_disable(struct vnic_rq *rq);
+void vnic_rq_clean(struct vnic_rq *rq,
+ void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf));
+
+#endif /* _VNIC_RQ_H_ */
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h
new file mode 100644
index 00000000000..e325d65d7c3
--- /dev/null
+++ b/drivers/net/enic/vnic_rss.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ */
+
+#ifndef _VNIC_RSS_H_
+#define _VNIC_RSS_H_
+
+/* RSS key array */
+union vnic_rss_key {
+ struct {
+ u8 b[10];
+ u8 b_pad[6];
+ } key[4];
+ u64 raw[8];
+};
+
+/* RSS cpu array */
+union vnic_rss_cpu {
+ struct {
+ u8 b[4] ;
+ u8 b_pad[4];
+ } cpu[32];
+ u64 raw[32];
+};
+
+void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key);
+void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
+void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key);
+void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
+
+#endif /* _VNIC_RSS_H_ */
diff --git a/drivers/net/enic/vnic_stats.h b/drivers/net/enic/vnic_stats.h
new file mode 100644
index 00000000000..9ff9614d89b
--- /dev/null
+++ b/drivers/net/enic/vnic_stats.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_STATS_H_
+#define _VNIC_STATS_H_
+
+/* Tx statistics */
+struct vnic_tx_stats {
+ u64 tx_frames_ok;
+ u64 tx_unicast_frames_ok;
+ u64 tx_multicast_frames_ok;
+ u64 tx_broadcast_frames_ok;
+ u64 tx_bytes_ok;
+ u64 tx_unicast_bytes_ok;
+ u64 tx_multicast_bytes_ok;
+ u64 tx_broadcast_bytes_ok;
+ u64 tx_drops;
+ u64 tx_errors;
+ u64 tx_tso;
+ u64 rsvd[16];
+};
+
+/* Rx statistics */
+struct vnic_rx_stats {
+ u64 rx_frames_ok;
+ u64 rx_frames_total;
+ u64 rx_unicast_frames_ok;
+ u64 rx_multicast_frames_ok;
+ u64 rx_broadcast_frames_ok;
+ u64 rx_bytes_ok;
+ u64 rx_unicast_bytes_ok;
+ u64 rx_multicast_bytes_ok;
+ u64 rx_broadcast_bytes_ok;
+ u64 rx_drop;
+ u64 rx_no_bufs;
+ u64 rx_errors;
+ u64 rx_rss;
+ u64 rx_crc_errors;
+ u64 rx_frames_64;
+ u64 rx_frames_127;
+ u64 rx_frames_255;
+ u64 rx_frames_511;
+ u64 rx_frames_1023;
+ u64 rx_frames_1518;
+ u64 rx_frames_to_max;
+ u64 rsvd[16];
+};
+
+struct vnic_stats {
+ struct vnic_tx_stats tx;
+ struct vnic_rx_stats rx;
+};
+
+#endif /* _VNIC_STATS_H_ */
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c
new file mode 100644
index 00000000000..a576d04708e
--- /dev/null
+++ b/drivers/net/enic/vnic_wq.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "vnic_dev.h"
+#include "vnic_wq.h"
+
+static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
+{
+ struct vnic_wq_buf *buf;
+ struct vnic_dev *vdev;
+ unsigned int i, j, count = wq->ring.desc_count;
+ unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
+
+ vdev = wq->vdev;
+
+ for (i = 0; i < blks; i++) {
+ wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ, GFP_ATOMIC);
+ if (!wq->bufs[i]) {
+ printk(KERN_ERR "Failed to alloc wq_bufs\n");
+ return -ENOMEM;
+ }
+ }
+
+ for (i = 0; i < blks; i++) {
+ buf = wq->bufs[i];
+ for (j = 0; j < VNIC_WQ_BUF_BLK_ENTRIES; j++) {
+ buf->index = i * VNIC_WQ_BUF_BLK_ENTRIES + j;
+ buf->desc = (u8 *)wq->ring.descs +
+ wq->ring.desc_size * buf->index;
+ if (buf->index + 1 == count) {
+ buf->next = wq->bufs[0];
+ break;
+ } else if (j + 1 == VNIC_WQ_BUF_BLK_ENTRIES) {
+ buf->next = wq->bufs[i + 1];
+ } else {
+ buf->next = buf + 1;
+ buf++;
+ }
+ }
+ }
+
+ wq->to_use = wq->to_clean = wq->bufs[0];
+
+ return 0;
+}
+
+void vnic_wq_free(struct vnic_wq *wq)
+{
+ struct vnic_dev *vdev;
+ unsigned int i;
+
+ vdev = wq->vdev;
+
+ vnic_dev_free_desc_ring(vdev, &wq->ring);
+
+ for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {
+ kfree(wq->bufs[i]);
+ wq->bufs[i] = NULL;
+ }
+
+ wq->ctrl = NULL;
+}
+
+int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ int err;
+
+ wq->index = index;
+ wq->vdev = vdev;
+
+ wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index);
+ if (!wq->ctrl) {
+ printk(KERN_ERR "Failed to hook WQ[%d] resource\n", index);
+ return -EINVAL;
+ }
+
+ vnic_wq_disable(wq);
+
+ err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
+ if (err)
+ return err;
+
+ err = vnic_wq_alloc_bufs(wq);
+ if (err) {
+ vnic_wq_free(wq);
+ return err;
+ }
+
+ return 0;
+}
+
+void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
+ unsigned int error_interrupt_enable,
+ unsigned int error_interrupt_offset)
+{
+ u64 paddr;
+
+ paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;
+ writeq(paddr, &wq->ctrl->ring_base);
+ iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size);
+ iowrite32(0, &wq->ctrl->fetch_index);
+ iowrite32(0, &wq->ctrl->posted_index);
+ iowrite32(cq_index, &wq->ctrl->cq_index);
+ iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);
+ iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);
+ iowrite32(0, &wq->ctrl->error_status);
+}
+
+unsigned int vnic_wq_error_status(struct vnic_wq *wq)
+{
+ return ioread32(&wq->ctrl->error_status);
+}
+
+void vnic_wq_enable(struct vnic_wq *wq)
+{
+ iowrite32(1, &wq->ctrl->enable);
+}
+
+int vnic_wq_disable(struct vnic_wq *wq)
+{
+ unsigned int wait;
+
+ iowrite32(0, &wq->ctrl->enable);
+
+ /* Wait for HW to ACK disable request */
+ for (wait = 0; wait < 100; wait++) {
+ if (!(ioread32(&wq->ctrl->running)))
+ return 0;
+ udelay(1);
+ }
+
+ printk(KERN_ERR "Failed to disable WQ[%d]\n", wq->index);
+
+ return -ETIMEDOUT;
+}
+
+void vnic_wq_clean(struct vnic_wq *wq,
+ void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf))
+{
+ struct vnic_wq_buf *buf;
+
+ BUG_ON(ioread32(&wq->ctrl->enable));
+
+ buf = wq->to_clean;
+
+ while (vnic_wq_desc_used(wq) > 0) {
+
+ (*buf_clean)(wq, buf);
+
+ buf = wq->to_clean = buf->next;
+ wq->ring.desc_avail++;
+ }
+
+ wq->to_use = wq->to_clean = wq->bufs[0];
+
+ iowrite32(0, &wq->ctrl->fetch_index);
+ iowrite32(0, &wq->ctrl->posted_index);
+ iowrite32(0, &wq->ctrl->error_status);
+
+ vnic_dev_clear_desc_ring(&wq->ring);
+}
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h
new file mode 100644
index 00000000000..7081828d8a4
--- /dev/null
+++ b/drivers/net/enic/vnic_wq.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _VNIC_WQ_H_
+#define _VNIC_WQ_H_
+
+#include <linux/pci.h>
+
+#include "vnic_dev.h"
+#include "vnic_cq.h"
+
+/* Work queue control */
+struct vnic_wq_ctrl {
+ u64 ring_base; /* 0x00 */
+ u32 ring_size; /* 0x08 */
+ u32 pad0;
+ u32 posted_index; /* 0x10 */
+ u32 pad1;
+ u32 cq_index; /* 0x18 */
+ u32 pad2;
+ u32 enable; /* 0x20 */
+ u32 pad3;
+ u32 running; /* 0x28 */
+ u32 pad4;
+ u32 fetch_index; /* 0x30 */
+ u32 pad5;
+ u32 dca_value; /* 0x38 */
+ u32 pad6;
+ u32 error_interrupt_enable; /* 0x40 */
+ u32 pad7;
+ u32 error_interrupt_offset; /* 0x48 */
+ u32 pad8;
+ u32 error_status; /* 0x50 */
+ u32 pad9;
+};
+
+struct vnic_wq_buf {
+ struct vnic_wq_buf *next;
+ dma_addr_t dma_addr;
+ void *os_buf;
+ unsigned int len;
+ unsigned int index;
+ int sop;
+ void *desc;
+};
+
+/* Break the vnic_wq_buf allocations into blocks of 64 entries */
+#define VNIC_WQ_BUF_BLK_ENTRIES 64
+#define VNIC_WQ_BUF_BLK_SZ \
+ (VNIC_WQ_BUF_BLK_ENTRIES * sizeof(struct vnic_wq_buf))
+#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \
+ DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES)
+#define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096)
+
+struct vnic_wq {
+ unsigned int index;
+ struct vnic_dev *vdev;
+ struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */
+ struct vnic_dev_ring ring;
+ struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX];
+ struct vnic_wq_buf *to_use;
+ struct vnic_wq_buf *to_clean;
+ unsigned int pkts_outstanding;
+};
+
+static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq)
+{
+ /* how many does SW own? */
+ return wq->ring.desc_avail;
+}
+
+static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq)
+{
+ /* how many does HW own? */
+ return wq->ring.desc_count - wq->ring.desc_avail - 1;
+}
+
+static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
+{
+ return wq->to_use->desc;
+}
+
+static inline void vnic_wq_post(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr,
+ unsigned int len, int sop, int eop)
+{
+ struct vnic_wq_buf *buf = wq->to_use;
+
+ buf->sop = sop;
+ buf->os_buf = eop ? os_buf : NULL;
+ buf->dma_addr = dma_addr;
+ buf->len = len;
+
+ buf = buf->next;
+ if (eop)
+ iowrite32(buf->index, &wq->ctrl->posted_index);
+ wq->to_use = buf;
+
+ wq->ring.desc_avail--;
+}
+
+static inline void vnic_wq_service(struct vnic_wq *wq,
+ struct cq_desc *cq_desc, u16 completed_index,
+ void (*buf_service)(struct vnic_wq *wq,
+ struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque),
+ void *opaque)
+{
+ struct vnic_wq_buf *buf;
+
+ buf = wq->to_clean;
+ while (1) {
+
+ (*buf_service)(wq, cq_desc, buf, opaque);
+
+ wq->ring.desc_avail++;
+
+ wq->to_clean = buf->next;
+
+ if (buf->index == completed_index)
+ break;
+
+ buf = wq->to_clean;
+ }
+}
+
+void vnic_wq_free(struct vnic_wq *wq);
+int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
+ unsigned int desc_count, unsigned int desc_size);
+void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
+ unsigned int error_interrupt_enable,
+ unsigned int error_interrupt_offset);
+unsigned int vnic_wq_error_status(struct vnic_wq *wq);
+void vnic_wq_enable(struct vnic_wq *wq);
+int vnic_wq_disable(struct vnic_wq *wq);
+void vnic_wq_clean(struct vnic_wq *wq,
+ void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf));
+
+#endif /* _VNIC_WQ_H_ */
diff --git a/drivers/net/enic/wq_enet_desc.h b/drivers/net/enic/wq_enet_desc.h
new file mode 100644
index 00000000000..483596c2d8b
--- /dev/null
+++ b/drivers/net/enic/wq_enet_desc.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _WQ_ENET_DESC_H_
+#define _WQ_ENET_DESC_H_
+
+/* Ethernet work queue descriptor: 16B */
+struct wq_enet_desc {
+ __le64 address;
+ __le16 length;
+ __le16 mss_loopback;
+ __le16 header_length_flags;
+ __le16 vlan_tag;
+};
+
+#define WQ_ENET_ADDR_BITS 64
+#define WQ_ENET_LEN_BITS 14
+#define WQ_ENET_LEN_MASK ((1 << WQ_ENET_LEN_BITS) - 1)
+#define WQ_ENET_MSS_BITS 14
+#define WQ_ENET_MSS_MASK ((1 << WQ_ENET_MSS_BITS) - 1)
+#define WQ_ENET_MSS_SHIFT 2
+#define WQ_ENET_LOOPBACK_SHIFT 1
+#define WQ_ENET_HDRLEN_BITS 10
+#define WQ_ENET_HDRLEN_MASK ((1 << WQ_ENET_HDRLEN_BITS) - 1)
+#define WQ_ENET_FLAGS_OM_BITS 2
+#define WQ_ENET_FLAGS_OM_MASK ((1 << WQ_ENET_FLAGS_OM_BITS) - 1)
+#define WQ_ENET_FLAGS_EOP_SHIFT 12
+#define WQ_ENET_FLAGS_CQ_ENTRY_SHIFT 13
+#define WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT 14
+#define WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT 15
+
+#define WQ_ENET_OFFLOAD_MODE_CSUM 0
+#define WQ_ENET_OFFLOAD_MODE_RESERVED 1
+#define WQ_ENET_OFFLOAD_MODE_CSUM_L4 2
+#define WQ_ENET_OFFLOAD_MODE_TSO 3
+
+static inline void wq_enet_desc_enc(struct wq_enet_desc *desc,
+ u64 address, u16 length, u16 mss, u16 header_length,
+ u8 offload_mode, u8 eop, u8 cq_entry, u8 fcoe_encap,
+ u8 vlan_tag_insert, u16 vlan_tag, u8 loopback)
+{
+ desc->address = cpu_to_le64(address);
+ desc->length = cpu_to_le16(length & WQ_ENET_LEN_MASK);
+ desc->mss_loopback = cpu_to_le16((mss & WQ_ENET_MSS_MASK) <<
+ WQ_ENET_MSS_SHIFT | (loopback & 1) << WQ_ENET_LOOPBACK_SHIFT);
+ desc->header_length_flags = cpu_to_le16(
+ (header_length & WQ_ENET_HDRLEN_MASK) |
+ (offload_mode & WQ_ENET_FLAGS_OM_MASK) << WQ_ENET_HDRLEN_BITS |
+ (eop & 1) << WQ_ENET_FLAGS_EOP_SHIFT |
+ (cq_entry & 1) << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT |
+ (fcoe_encap & 1) << WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT |
+ (vlan_tag_insert & 1) << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT);
+ desc->vlan_tag = cpu_to_le16(vlan_tag);
+}
+
+static inline void wq_enet_desc_dec(struct wq_enet_desc *desc,
+ u64 *address, u16 *length, u16 *mss, u16 *header_length,
+ u8 *offload_mode, u8 *eop, u8 *cq_entry, u8 *fcoe_encap,
+ u8 *vlan_tag_insert, u16 *vlan_tag, u8 *loopback)
+{
+ *address = le64_to_cpu(desc->address);
+ *length = le16_to_cpu(desc->length) & WQ_ENET_LEN_MASK;
+ *mss = (le16_to_cpu(desc->mss_loopback) >> WQ_ENET_MSS_SHIFT) &
+ WQ_ENET_MSS_MASK;
+ *loopback = (u8)((le16_to_cpu(desc->mss_loopback) >>
+ WQ_ENET_LOOPBACK_SHIFT) & 1);
+ *header_length = le16_to_cpu(desc->header_length_flags) &
+ WQ_ENET_HDRLEN_MASK;
+ *offload_mode = (u8)((le16_to_cpu(desc->header_length_flags) >>
+ WQ_ENET_HDRLEN_BITS) & WQ_ENET_FLAGS_OM_MASK);
+ *eop = (u8)((le16_to_cpu(desc->header_length_flags) >>
+ WQ_ENET_FLAGS_EOP_SHIFT) & 1);
+ *cq_entry = (u8)((le16_to_cpu(desc->header_length_flags) >>
+ WQ_ENET_FLAGS_CQ_ENTRY_SHIFT) & 1);
+ *fcoe_encap = (u8)((le16_to_cpu(desc->header_length_flags) >>
+ WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT) & 1);
+ *vlan_tag_insert = (u8)((le16_to_cpu(desc->header_length_flags) >>
+ WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT) & 1);
+ *vlan_tag = le16_to_cpu(desc->vlan_tag);
+}
+
+#endif /* _WQ_ENET_DESC_H_ */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 3c1364de2b6..b455ae931f7 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -431,7 +431,7 @@ static void getlinktype(struct net_device *dev);
static void getlinkstatus(struct net_device *dev);
static void netdev_timer(unsigned long data);
static void reset_timer(unsigned long data);
-static void tx_timeout(struct net_device *dev);
+static void fealnx_tx_timeout(struct net_device *dev);
static void init_ring(struct net_device *dev);
static int start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t intr_handler(int irq, void *dev_instance);
@@ -658,7 +658,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &mii_ioctl;
dev->ethtool_ops = &netdev_ethtool_ops;
- dev->tx_timeout = &tx_timeout;
+ dev->tx_timeout = &fealnx_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
err = register_netdev(dev);
@@ -1198,7 +1198,7 @@ static void reset_timer(unsigned long data)
}
-static void tx_timeout(struct net_device *dev)
+static void fealnx_tx_timeout(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->mem;
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
index f5634447276..08e18bcb970 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -83,7 +83,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
int err;
int i;
- bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ bus = mdiobus_alloc();
if (bus == NULL)
return -ENOMEM;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -127,7 +127,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
bus->priv = priv;
- bus->dev = dev;
+ bus->parent = dev;
dev_set_drvdata(dev, bus);
/* set MII speed */
@@ -150,7 +150,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
irq_dispose_mapping(bus->irq[i]);
kfree(bus->irq);
kfree(priv);
- kfree(bus);
+ mdiobus_free(bus);
return err;
}
@@ -171,7 +171,7 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of)
irq_dispose_mapping(bus->irq[i]);
kfree(priv);
kfree(bus->irq);
- kfree(bus);
+ mdiobus_free(bus);
return 0;
}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 331b86b01fa..cc7328b1552 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -337,7 +337,7 @@ enum {
NvRegMSIXIrqStatus = 0x3f0,
NvRegPowerState2 = 0x600,
-#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11
+#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15
#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
#define NVREG_POWERSTATE2_PHY_RESET 0x0004
};
@@ -5643,6 +5643,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+ printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n");
}
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
@@ -5890,14 +5891,12 @@ static void nv_restore_phy(struct net_device *dev)
}
}
-static void __devexit nv_remove(struct pci_dev *pci_dev)
+static void nv_restore_mac_addr(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
- unregister_netdev(dev);
-
/* special op: write back the misordered MAC address - otherwise
* the next nv_probe would see a wrong address.
*/
@@ -5905,6 +5904,15 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
writel(np->orig_mac[1], base + NvRegMacAddrB);
writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
base + NvRegTransmitPoll);
+}
+
+static void __devexit nv_remove(struct pci_dev *pci_dev)
+{
+ struct net_device *dev = pci_get_drvdata(pci_dev);
+
+ unregister_netdev(dev);
+
+ nv_restore_mac_addr(pci_dev);
/* restore any phy related changes */
nv_restore_phy(dev);
@@ -5975,10 +5983,14 @@ static void nv_shutdown(struct pci_dev *pdev)
if (netif_running(dev))
nv_close(dev);
- pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
- pci_enable_wake(pdev, PCI_D3cold, np->wolenabled);
+ nv_restore_mac_addr(pdev);
+
pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
+ if (system_state == SYSTEM_POWER_OFF) {
+ if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
+ pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
}
#else
#define nv_suspend NULL
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 9d461825bf4..cb51c1fb033 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -664,23 +664,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static int fs_request_irq(struct net_device *dev, int irq, const char *name,
- irq_handler_t irqf)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- (*fep->ops->pre_request_irq)(dev, irq);
- return request_irq(irq, irqf, IRQF_SHARED, name, dev);
-}
-
-static void fs_free_irq(struct net_device *dev, int irq)
-{
- struct fs_enet_private *fep = netdev_priv(dev);
-
- free_irq(irq, dev);
- (*fep->ops->post_free_irq)(dev, irq);
-}
-
static void fs_timeout(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -800,7 +783,8 @@ static int fs_enet_open(struct net_device *dev)
napi_enable(&fep->napi);
/* Install our interrupt handler. */
- r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
+ r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
+ "fs_enet-mac", dev);
if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate FS_ENET IRQ!", dev->name);
@@ -842,7 +826,7 @@ static int fs_enet_close(struct net_device *dev)
/* release any irqs */
phy_disconnect(fep->phydev);
fep->phydev = NULL;
- fs_free_irq(dev, fep->interrupt);
+ free_irq(fep->interrupt, dev);
return 0;
}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index db46d2e7232..85a4bab7f63 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -34,8 +34,6 @@ struct fs_ops {
void (*adjust_link)(struct net_device *dev);
void (*restart)(struct net_device *dev);
void (*stop)(struct net_device *dev);
- void (*pre_request_irq)(struct net_device *dev, int irq);
- void (*post_free_irq)(struct net_device *dev, int irq);
void (*napi_clear_rx_event)(struct net_device *dev);
void (*napi_enable_rx)(struct net_device *dev);
void (*napi_disable_rx)(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 1c7ef812a8e..22e5a847a58 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -421,16 +421,6 @@ static void stop(struct net_device *dev)
fs_cleanup_bds(dev);
}
-static void pre_request_irq(struct net_device *dev, int irq)
-{
- /* nothing */
-}
-
-static void post_free_irq(struct net_device *dev, int irq)
-{
- /* nothing */
-}
-
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -540,8 +530,6 @@ const struct fs_ops fs_fcc_ops = {
.set_multicast_list = set_multicast_list,
.restart = restart,
.stop = stop,
- .pre_request_irq = pre_request_irq,
- .post_free_irq = post_free_irq,
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 0a7d1c5c652..14e575313c8 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -313,11 +313,7 @@ static void restart(struct net_device *dev)
* Clear any outstanding interrupt.
*/
FW(fecp, ievent, 0xffc0);
-#ifndef CONFIG_PPC_MERGE
- FW(fecp, ivec, (fep->interrupt / 2) << 29);
-#else
FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
-#endif
/*
* adjust to speed (only for DUET & RMII)
@@ -413,30 +409,6 @@ static void stop(struct net_device *dev)
}
}
-static void pre_request_irq(struct net_device *dev, int irq)
-{
-#ifndef CONFIG_PPC_MERGE
- immap_t *immap = fs_enet_immap;
- u32 siel;
-
- /* SIU interrupt */
- if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) {
-
- siel = in_be32(&immap->im_siu_conf.sc_siel);
- if ((irq & 1) == 0)
- siel |= (0x80000000 >> irq);
- else
- siel &= ~(0x80000000 >> (irq & ~1));
- out_be32(&immap->im_siu_conf.sc_siel, siel);
- }
-#endif
-}
-
-static void post_free_irq(struct net_device *dev, int irq)
-{
- /* nothing */
-}
-
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -529,8 +501,6 @@ const struct fs_ops fs_fec_ops = {
.set_multicast_list = set_multicast_list,
.restart = restart,
.stop = stop,
- .pre_request_irq = pre_request_irq,
- .post_free_irq = post_free_irq,
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 22f50dd8b27..008cdd9cc53 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -377,30 +377,6 @@ static void stop(struct net_device *dev)
fs_cleanup_bds(dev);
}
-static void pre_request_irq(struct net_device *dev, int irq)
-{
-#ifndef CONFIG_PPC_MERGE
- immap_t *immap = fs_enet_immap;
- u32 siel;
-
- /* SIU interrupt */
- if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) {
-
- siel = in_be32(&immap->im_siu_conf.sc_siel);
- if ((irq & 1) == 0)
- siel |= (0x80000000 >> irq);
- else
- siel &= ~(0x80000000 >> (irq & ~1));
- out_be32(&immap->im_siu_conf.sc_siel, siel);
- }
-#endif
-}
-
-static void post_free_irq(struct net_device *dev, int irq)
-{
- /* nothing */
-}
-
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -494,8 +470,6 @@ const struct fs_ops fs_scc_ops = {
.set_multicast_list = set_multicast_list,
.restart = restart,
.stop = stop,
- .pre_request_irq = pre_request_irq,
- .post_free_irq = post_free_irq,
.napi_clear_rx_event = napi_clear_rx_event,
.napi_enable_rx = napi_enable_rx,
.napi_disable_rx = napi_disable_rx,
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index be4b72f4f49..49b6645d7e0 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -203,7 +203,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
if (!strcmp(np->type, "ethernet-phy"))
add_phy(new_bus, np);
- new_bus->dev = &ofdev->dev;
+ new_bus->parent = &ofdev->dev;
dev_set_drvdata(&ofdev->dev, new_bus);
ret = mdiobus_register(new_bus);
@@ -218,9 +218,9 @@ out_free_irqs:
out_unmap_regs:
iounmap(bitbang->dir);
out_free_bus:
- kfree(new_bus);
-out_free_priv:
free_mdio_bitbang(new_bus);
+out_free_priv:
+ kfree(bitbang);
out:
return ret;
}
@@ -231,12 +231,11 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
struct bb_info *bitbang = bus->priv;
mdiobus_unregister(bus);
- free_mdio_bitbang(bus);
dev_set_drvdata(&ofdev->dev, NULL);
kfree(bus->irq);
+ free_mdio_bitbang(bus);
iounmap(bitbang->dir);
kfree(bitbang);
- kfree(bus);
return 0;
}
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 695f74cc439..28077cc1b94 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -128,7 +128,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
struct fec_info *fec;
int ret = -ENOMEM, i;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ new_bus = mdiobus_alloc();
if (!new_bus)
goto out;
@@ -172,7 +172,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
if (!strcmp(np->type, "ethernet-phy"))
add_phy(new_bus, np);
- new_bus->dev = &ofdev->dev;
+ new_bus->parent = &ofdev->dev;
dev_set_drvdata(&ofdev->dev, new_bus);
ret = mdiobus_register(new_bus);
@@ -190,7 +190,7 @@ out_res:
out_fec:
kfree(fec);
out_mii:
- kfree(new_bus);
+ mdiobus_free(new_bus);
out:
return ret;
}
@@ -205,7 +205,7 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
kfree(bus->irq);
iounmap(fec->fecp);
kfree(fec);
- kfree(bus);
+ mdiobus_free(bus);
return 0;
}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 4320a983a58..b5bb7ae2817 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -339,6 +339,9 @@ static int gfar_probe(struct platform_device *pdev)
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
+ /* Carrier starts down, phylib will bring it up */
+ netif_carrier_off(dev);
+
err = register_netdev(dev);
if (err) {
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index ebcfb27a904..bf73eea9801 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -136,12 +136,12 @@ static int gfar_mdio_reset(struct mii_bus *bus)
/* Wait until the bus is free */
while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) &&
- timeout--)
+ --timeout)
cpu_relax();
mutex_unlock(&bus->mdio_lock);
- if(timeout <= 0) {
+ if(timeout == 0) {
printk(KERN_ERR "%s: The MII Bus is stuck!\n",
bus->name);
return -EBUSY;
@@ -164,8 +164,7 @@ static int gfar_mdio_probe(struct device *dev)
if (NULL == dev)
return -EINVAL;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
+ new_bus = mdiobus_alloc();
if (NULL == new_bus)
return -ENOMEM;
@@ -196,7 +195,7 @@ static int gfar_mdio_probe(struct device *dev)
new_bus->irq = pdata->irq;
- new_bus->dev = dev;
+ new_bus->parent = dev;
dev_set_drvdata(dev, new_bus);
/*
@@ -211,19 +210,21 @@ static int gfar_mdio_probe(struct device *dev)
gfar_write(&enet_regs->tbipa, 0);
for (i = PHY_MAX_ADDR; i > 0; i--) {
u32 phy_id;
- int r;
- r = get_phy_id(new_bus, i, &phy_id);
- if (r)
- return r;
+ err = get_phy_id(new_bus, i, &phy_id);
+ if (err)
+ goto bus_register_fail;
if (phy_id == 0xffffffff)
break;
}
/* The bus is full. We don't support using 31 PHYs, sorry */
- if (i == 0)
- return -EBUSY;
+ if (i == 0) {
+ err = -EBUSY;
+
+ goto bus_register_fail;
+ }
gfar_write(&enet_regs->tbipa, i);
@@ -240,7 +241,7 @@ static int gfar_mdio_probe(struct device *dev)
bus_register_fail:
iounmap(regs);
reg_map_fail:
- kfree(new_bus);
+ mdiobus_free(new_bus);
return err;
}
@@ -256,7 +257,7 @@ static int gfar_mdio_remove(struct device *dev)
iounmap((void __iomem *)bus->priv);
bus->priv = NULL;
- kfree(bus);
+ mdiobus_free(bus);
return 0;
}
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 8239939554b..fbbd3e660c2 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -139,7 +139,7 @@ static int __init do_hpp_probe(struct net_device *dev)
#ifndef MODULE
struct net_device * __init hp_plus_probe(int unit)
{
- struct net_device *dev = alloc_ei_netdev();
+ struct net_device *dev = alloc_eip_netdev();
int err;
if (!dev)
@@ -284,7 +284,7 @@ hpp_open(struct net_device *dev)
int option_reg;
int retval;
- if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) {
+ if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
return retval;
}
@@ -302,7 +302,7 @@ hpp_open(struct net_device *dev)
/* Select the operational page. */
outw(Perf_Page, ioaddr + HP_PAGING);
- ei_open(dev);
+ eip_open(dev);
return 0;
}
@@ -313,7 +313,7 @@ hpp_close(struct net_device *dev)
int option_reg = inw(ioaddr + HPP_OPTION);
free_irq(dev->irq, dev);
- ei_close(dev);
+ eip_close(dev);
outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
ioaddr + HPP_OPTION);
diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
index 70a3272ee99..78a1628c989 100644
--- a/drivers/net/ibm_newemac/Kconfig
+++ b/drivers/net/ibm_newemac/Kconfig
@@ -1,6 +1,6 @@
config IBM_NEW_EMAC
tristate "IBM EMAC Ethernet support"
- depends on PPC_DCR && PPC_MERGE
+ depends on PPC_DCR
select CRC32
help
This driver supports the IBM EMAC family of Ethernet controllers
@@ -62,3 +62,15 @@ config IBM_NEW_EMAC_TAH
config IBM_NEW_EMAC_EMAC4
bool
default n
+
+config IBM_NEW_EMAC_NO_FLOW_CTRL
+ bool
+ default n
+
+config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+ bool
+ default n
+
+config IBM_NEW_EMAC_MAL_COMMON_ERR
+ bool
+ default n
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index ccd9d9058f6..efcf21c9f5c 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -130,6 +130,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev,
const char *error)
{
if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
+ EMAC_FTR_460EX_PHY_CLK_FIX |
EMAC_FTR_440EP_PHY_CLK_FIX))
DBG(dev, "%s" NL, error);
else if (net_ratelimit())
@@ -201,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
{
return phy_mode == PHY_MODE_GMII ||
phy_mode == PHY_MODE_RGMII ||
+ phy_mode == PHY_MODE_SGMII ||
phy_mode == PHY_MODE_TBI ||
phy_mode == PHY_MODE_RTBI;
}
static inline int emac_phy_gpcs(int phy_mode)
{
- return phy_mode == PHY_MODE_TBI ||
+ return phy_mode == PHY_MODE_SGMII ||
+ phy_mode == PHY_MODE_TBI ||
phy_mode == PHY_MODE_RTBI;
}
@@ -351,10 +354,24 @@ static int emac_reset(struct emac_instance *dev)
emac_tx_disable(dev);
}
+#ifdef CONFIG_PPC_DCR_NATIVE
+ /* Enable internal clock source */
+ if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
+ dcri_clrset(SDR0, SDR0_ETH_CFG,
+ 0, SDR0_ETH_CFG_ECS << dev->cell_index);
+#endif
+
out_be32(&p->mr0, EMAC_MR0_SRST);
while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
--n;
+#ifdef CONFIG_PPC_DCR_NATIVE
+ /* Enable external clock source */
+ if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
+ dcri_clrset(SDR0, SDR0_ETH_CFG,
+ SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+#endif
+
if (n) {
dev->reset_failed = 0;
return 0;
@@ -547,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
switch (dev->phy.speed) {
case SPEED_1000:
if (emac_phy_gpcs(dev->phy.mode)) {
- mr1 |= EMAC_MR1_MF_1000GPCS |
- EMAC_MR1_MF_IPPA(dev->phy.address);
+ mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
+ (dev->phy.gpcs_address != 0xffffffff) ?
+ dev->phy.gpcs_address : dev->phy.address);
/* Put some arbitrary OUI, Manuf & Rev IDs so we can
* identify this GPCS PHY later.
@@ -660,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
out_be32(&p->iser, r);
/* We need to take GPCS PHY out of isolate mode after EMAC reset */
- if (emac_phy_gpcs(dev->phy.mode))
- emac_mii_reset_phy(&dev->phy);
+ if (emac_phy_gpcs(dev->phy.mode)) {
+ if (dev->phy.gpcs_address != 0xffffffff)
+ emac_mii_reset_gpcs(&dev->phy);
+ else
+ emac_mii_reset_phy(&dev->phy);
+ }
return 0;
}
@@ -866,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
struct emac_instance *dev = netdev_priv(ndev);
int res;
- res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev,
+ res = __emac_mdio_read((dev->mdio_instance &&
+ dev->phy.gpcs_address != id) ?
+ dev->mdio_instance : dev,
(u8) id, (u8) reg);
return res;
}
@@ -875,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
{
struct emac_instance *dev = netdev_priv(ndev);
- __emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev,
+ __emac_mdio_write((dev->mdio_instance &&
+ dev->phy.gpcs_address != id) ?
+ dev->mdio_instance : dev,
(u8) id, (u8) reg, (u16) val);
}
@@ -2367,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
* XXX I probably should move these settings to the dev tree
*/
dev->phy.address = -1;
- dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
+ dev->phy.features = SUPPORTED_MII;
+ if (emac_phy_supports_gige(dev->phy_mode))
+ dev->phy.features |= SUPPORTED_1000baseT_Full;
+ else
+ dev->phy.features |= SUPPORTED_100baseT_Full;
dev->phy.pause = 1;
return 0;
@@ -2406,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
* Note that the busy_phy_map is currently global
* while it should probably be per-ASIC...
*/
- dev->phy.address = dev->cell_index;
+ dev->phy.gpcs_address = dev->gpcs_address;
+ if (dev->phy.gpcs_address == 0xffffffff)
+ dev->phy.address = dev->cell_index;
}
emac_configure(dev);
@@ -2516,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
dev->phy_address = 0xffffffff;
if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
dev->phy_map = 0xffffffff;
+ if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
+ dev->gpcs_address = 0xffffffff;
if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
return -ENXIO;
if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
@@ -2559,6 +2593,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
/* Check EMAC version */
if (of_device_is_compatible(np, "ibm,emac4sync")) {
dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
+ if (of_device_is_compatible(np, "ibm,emac-460ex") ||
+ of_device_is_compatible(np, "ibm,emac-460gt"))
+ dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX;
} else if (of_device_is_compatible(np, "ibm,emac4")) {
dev->features |= EMAC_FTR_EMAC4;
if (of_device_is_compatible(np, "ibm,emac-440gx"))
@@ -2567,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
if (of_device_is_compatible(np, "ibm,emac-440ep") ||
of_device_is_compatible(np, "ibm,emac-440gr"))
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+ if (of_device_is_compatible(np, "ibm,emac-405ez"))
+ dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
}
/* Fixup some feature bits based on the device tree */
@@ -2824,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+ if (dev->phy_mode == PHY_MODE_SGMII)
+ printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
+
if (dev->phy.address >= 0)
printk("%s: found %s PHY (0x%02x)\n", ndev->name,
dev->phy.def->name, dev->phy.address);
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 6545e69d12c..18d56c6c423 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -190,6 +190,9 @@ struct emac_instance {
struct delayed_work link_work;
int link_polling;
+ /* GPCS PHY infos */
+ u32 gpcs_address;
+
/* Shared MDIO if any */
u32 mdio_ph;
struct of_device *mdio_dev;
@@ -317,6 +320,10 @@ struct emac_instance {
* The 405EX and 460EX contain the EMAC4SYNC core
*/
#define EMAC_FTR_EMAC4SYNC 0x00000200
+/*
+ * Set if we need phy clock workaround for 460ex or 460gt
+ */
+#define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
/* Right now, we don't quite handle the always/possible masks on the
@@ -341,6 +348,10 @@ enum {
#ifdef CONFIG_IBM_NEW_EMAC_RGMII
EMAC_FTR_HAS_RGMII |
#endif
+#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+ EMAC_FTR_NO_FLOW_CONTROL_40x |
+#endif
+ EMAC_FTR_460EX_PHY_CLK_FIX |
EMAC_FTR_440EP_PHY_CLK_FIX,
};
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 10c267b2b96..1839d3f154a 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include "core.h"
+#include <asm/dcr-regs.h>
static int mal_count;
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_TXEOBISR, r);
+ if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+ mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+
return IRQ_HANDLED;
}
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_RXEOBISR, r);
+ if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+ mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+
return IRQ_HANDLED;
}
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
return IRQ_HANDLED;
}
+static irqreturn_t mal_int(int irq, void *dev_instance)
+{
+ struct mal_instance *mal = dev_instance;
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+ if (esr & MAL_ESR_EVB) {
+ /* descriptor error */
+ if (esr & MAL_ESR_DE) {
+ if (esr & MAL_ESR_CIDT)
+ return mal_rxde(irq, dev_instance);
+ else
+ return mal_txde(irq, dev_instance);
+ } else { /* SERR */
+ return mal_serr(irq, dev_instance);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
{
/* Spinlock-type semantics: only one caller disable poll at a time */
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
unsigned int dcr_base;
const u32 *prop;
u32 cfg;
+ unsigned long irqflags;
+ irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
if (!mal) {
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
goto fail;
}
+ if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
+ mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
+ MAL_FTR_COMMON_ERR_INT);
+
mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
- mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
- mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+
+ if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+ mal->txde_irq = mal->rxde_irq = mal->serr_irq;
+ } else {
+ mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
+ mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+ }
+
if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
mal->rxde_irq == NO_IRQ) {
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
sizeof(struct mal_descriptor) *
mal_rx_bd_offset(mal, i));
- err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal);
+ if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+ irqflags = IRQF_SHARED;
+ hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
+ } else {
+ irqflags = 0;
+ hdlr_serr = mal_serr;
+ hdlr_txde = mal_txde;
+ hdlr_rxde = mal_rxde;
+ }
+
+ err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
if (err)
goto fail2;
- err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal);
+ err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
if (err)
goto fail3;
err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
if (err)
goto fail4;
- err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
+ err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
if (err)
goto fail5;
err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index eaa7262dc07..2f0a8736084 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -102,7 +102,7 @@
/* MAL V1 IER bits */
#define MAL1_IER_NWE 0x00000008
#define MAL1_IER_SOC_EVENTS MAL1_IER_NWE
-#define MAL1_IER_EVENTS (MAL1_IER_SOC_EVENTS | MAL_IER_OTE | \
+#define MAL1_IER_EVENTS (MAL1_IER_SOC_EVENTS | MAL_IER_DE | \
MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
/* MAL V2 IER bits */
@@ -110,7 +110,7 @@
#define MAL2_IER_PRE 0x00000040
#define MAL2_IER_PWE 0x00000020
#define MAL2_IER_SOC_EVENTS (MAL2_IER_PT | MAL2_IER_PRE | MAL2_IER_PWE)
-#define MAL2_IER_EVENTS (MAL2_IER_SOC_EVENTS | MAL_IER_OTE | \
+#define MAL2_IER_EVENTS (MAL2_IER_SOC_EVENTS | MAL_IER_DE | \
MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
@@ -213,6 +213,8 @@ struct mal_instance {
struct of_device *ofdev;
int index;
spinlock_t lock;
+
+ unsigned int features;
};
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
@@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
dcr_write(mal->dcr_host, reg, val);
}
+/* Features of various MAL implementations */
+
+/* Set if you have interrupt coalescing and you have to clear the SDR
+ * register for TXEOB and RXEOB interrupts to work
+ */
+#define MAL_FTR_CLEAR_ICINTSTAT 0x00000001
+
+/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
+ * interrupt
+ */
+#define MAL_FTR_COMMON_ERR_INT 0x00000002
+
+enum {
+ MAL_FTRS_ALWAYS = 0,
+
+ MAL_FTRS_POSSIBLE =
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+ MAL_FTR_CLEAR_ICINTSTAT |
+#endif
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
+ MAL_FTR_COMMON_ERR_INT |
+#endif
+ 0,
+};
+
+static inline int mal_has_feature(struct mal_instance *dev,
+ unsigned long feature)
+{
+ return (MAL_FTRS_ALWAYS & feature) ||
+ (MAL_FTRS_POSSIBLE & dev->features & feature);
+}
+
/* Register MAL devices */
int mal_init(void);
void mal_exit(void);
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index 37bfeea8788..c40cd8df221 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
phy->mdio_write(phy->dev, phy->address, reg, val);
}
+static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
+{
+ return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
+}
+
+static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
+{
+ phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
+}
+
int emac_mii_reset_phy(struct mii_phy *phy)
{
int val;
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
return limit <= 0;
}
+int emac_mii_reset_gpcs(struct mii_phy *phy)
+{
+ int val;
+ int limit = 10000;
+
+ val = gpcs_phy_read(phy, MII_BMCR);
+ val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
+ val |= BMCR_RESET;
+ gpcs_phy_write(phy, MII_BMCR, val);
+
+ udelay(300);
+
+ while (limit--) {
+ val = gpcs_phy_read(phy, MII_BMCR);
+ if (val >= 0 && (val & BMCR_RESET) == 0)
+ break;
+ udelay(10);
+ }
+ if ((val & BMCR_ISOLATE) && limit > 0)
+ gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
+
+ if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
+ /* Configure GPCS interface to recommended setting for SGMII */
+ gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
+ gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
+ gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */
+ }
+
+ return limit <= 0;
+}
+
static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
{
int ctl, adv;
@@ -321,7 +362,7 @@ static struct mii_phy_def bcm5248_phy_def = {
static int m88e1111_init(struct mii_phy *phy)
{
- pr_debug("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__);
+ pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__);
phy_write(phy, 0x14, 0x0ce3);
phy_write(phy, 0x18, 0x4101);
phy_write(phy, 0x09, 0x0e00);
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
return 0;
}
+static int m88e1112_init(struct mii_phy *phy)
+{
+ /*
+ * Marvell 88E1112 PHY needs to have the SGMII MAC
+ * interace (page 2) properly configured to
+ * communicate with the 460EX/GT GPCS interface.
+ */
+
+ u16 reg_short;
+
+ pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
+
+ /* Set access to Page 2 */
+ phy_write(phy, 0x16, 0x0002);
+
+ phy_write(phy, 0x00, 0x0040); /* 1Gbps */
+ reg_short = (u16)(phy_read(phy, 0x1a));
+ reg_short |= 0x8000; /* bypass Auto-Negotiation */
+ phy_write(phy, 0x1a, reg_short);
+ emac_mii_reset_phy(phy); /* reset MAC interface */
+
+ /* Reset access to Page 0 */
+ phy_write(phy, 0x16, 0x0000);
+
+ return 0;
+}
+
static int et1011c_init(struct mii_phy *phy)
{
u16 reg_short;
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
.ops = &m88e1111_phy_ops,
};
+static struct mii_phy_ops m88e1112_phy_ops = {
+ .init = m88e1112_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def m88e1112_phy_def = {
+ .phy_id = 0x01410C90,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "Marvell 88E1112 Ethernet",
+ .ops = &m88e1112_phy_ops,
+};
+
static struct mii_phy_def *mii_phy_table[] = {
&et1011c_phy_def,
&cis8201_phy_def,
&bcm5248_phy_def,
&m88e1111_phy_def,
+ &m88e1112_phy_def,
&genmii_phy_def,
NULL
};
diff --git a/drivers/net/ibm_newemac/phy.h b/drivers/net/ibm_newemac/phy.h
index 1b65c81f655..5d2bf4cbe50 100644
--- a/drivers/net/ibm_newemac/phy.h
+++ b/drivers/net/ibm_newemac/phy.h
@@ -57,6 +57,7 @@ struct mii_phy {
or determined automaticaly */
int address; /* PHY address */
int mode; /* PHY mode */
+ int gpcs_address; /* GPCS PHY address */
/* 1: autoneg enabled, 0: disabled */
int autoneg;
@@ -81,5 +82,6 @@ struct mii_phy {
*/
int emac_mii_phy_probe(struct mii_phy *phy, int address);
int emac_mii_reset_phy(struct mii_phy *phy);
+int emac_mii_reset_gpcs(struct mii_phy *phy);
#endif /* __IBM_NEWEMAC_PHY_H */
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 95e3464068d..f02764725a2 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -71,7 +71,7 @@ History:
June 1st, 2000
corrected version codes, added support for the latest 2.3 changes
Oct 28th, 2002
- cleaned up for the 2.5 tree <alan@redhat.com>
+ cleaned up for the 2.5 tree <alan@lxorguk.ukuu.org.uk>
*************************************************************************/
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 634c4c9d87b..93d02efa9a0 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -3563,10 +3563,6 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget)
struct net_device *netdev = adapter->netdev;
int work_done = 0;
- /* Keep link state information with original netdev */
- if (!netif_carrier_ok(netdev))
- goto quit_polling;
-
#ifdef CONFIG_DCA
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_rx_dca(rx_ring);
@@ -3576,7 +3572,6 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget)
/* If not enough Rx work done, exit the polling mode */
if ((work_done == 0) || !netif_running(netdev)) {
-quit_polling:
netif_rx_complete(netdev, napi);
if (adapter->itr_setting & 3) {
@@ -3617,16 +3612,14 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
unsigned int i;
u32 head, oldhead;
unsigned int count = 0;
- bool cleaned = false;
- bool retval = true;
unsigned int total_bytes = 0, total_packets = 0;
+ bool retval = true;
rmb();
head = get_head(tx_ring);
i = tx_ring->next_to_clean;
while (1) {
while (i != head) {
- cleaned = true;
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
skb = buffer_info->skb;
@@ -3643,7 +3636,6 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
}
igb_unmap_and_free_tx_resource(adapter, buffer_info);
- tx_desc->upper.data = 0;
i++;
if (i == tx_ring->count)
@@ -3665,7 +3657,7 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
done_cleaning:
tx_ring->next_to_clean = i;
- if (unlikely(cleaned &&
+ if (unlikely(count &&
netif_carrier_ok(netdev) &&
IGB_DESC_UNUSED(tx_ring) >= IGB_TX_QUEUE_WAKE)) {
/* Make sure that anybody stopping the queue after this
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 73fe83be34f..e1429fc6d05 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -540,7 +540,8 @@ static int kingsun_probe(struct usb_interface *intf,
if (ret != 0)
goto free_mem;
- info("IrDA: Registered KingSun/DonShine device %s", net->name);
+ dev_info(&net->dev, "IrDA: Registered KingSun/DonShine device %s\n",
+ net->name);
usb_set_intfdata(intf, kingsun);
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
index 8c257a51341..2482d61662a 100644
--- a/drivers/net/irda/ks959-sir.c
+++ b/drivers/net/irda/ks959-sir.c
@@ -801,7 +801,8 @@ static int ks959_probe(struct usb_interface *intf,
if (ret != 0)
goto free_mem;
- info("IrDA: Registered KingSun KS-959 device %s", net->name);
+ dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
+ net->name);
usb_set_intfdata(intf, kingsun);
diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c
index d01a28593ce..1e0de93fd61 100644
--- a/drivers/net/irda/ksdazzle-sir.c
+++ b/drivers/net/irda/ksdazzle-sir.c
@@ -705,7 +705,8 @@ static int ksdazzle_probe(struct usb_interface *intf,
if (ret != 0)
goto free_mem;
- info("IrDA: Registered KingSun/Dazzle device %s", net->name);
+ dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n",
+ net->name);
usb_set_intfdata(intf, kingsun);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 4aa61a1a3d5..c5b02b66f75 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -572,8 +572,8 @@ static void pxa_irda_startup(struct pxa_irda *si)
ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
/* configure DMAC */
- DRCMR17 = si->rxdma | DRCMR_MAPVLD;
- DRCMR18 = si->txdma | DRCMR_MAPVLD;
+ DRCMR(17) = si->rxdma | DRCMR_MAPVLD;
+ DRCMR(18) = si->txdma | DRCMR_MAPVLD;
/* force SIR reinitialization */
si->speed = 4000000;
@@ -602,8 +602,8 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
/* disable the STUART or FICP clocks */
pxa_irda_disable_clk(si);
- DRCMR17 = 0;
- DRCMR18 = 0;
+ DRCMR(17) = 0;
+ DRCMR(18) = 0;
local_irq_restore(flags);
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c
index 36030241f7a..2a9930e6e2a 100644
--- a/drivers/net/irda/sir_dongle.c
+++ b/drivers/net/irda/sir_dongle.c
@@ -67,9 +67,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
const struct dongle_driver *drv = NULL;
int err = -EINVAL;
-#ifdef CONFIG_KMOD
request_module("irda-dongle-%d", type);
-#endif
if (dev->dongle_drv != NULL)
return -EBUSY;
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 05196378274..3575804fd7c 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -506,7 +506,7 @@ static int change_speed(struct stir_cb *stir, unsigned speed)
goto found;
}
- warn("%s: invalid speed %d", stir->netdev->name, speed);
+ dev_warn(&stir->netdev->dev, "invalid speed %d\n", speed);
return -EINVAL;
found:
@@ -598,8 +598,8 @@ static int fifo_txwait(struct stir_cb *stir, int space)
err = read_reg(stir, REG_FIFOCTL, stir->fifo_status,
FIFO_REGS_SIZE);
if (unlikely(err != FIFO_REGS_SIZE)) {
- warn("%s: FIFO register read error: %d",
- stir->netdev->name, err);
+ dev_warn(&stir->netdev->dev,
+ "FIFO register read error: %d\n", err);
return err;
}
@@ -783,8 +783,9 @@ static int stir_transmit_thread(void *arg)
if (unlikely(receive_start(stir))) {
if (net_ratelimit())
- info("%s: receive usb submit failed",
- stir->netdev->name);
+ dev_info(&dev->dev,
+ "%s: receive usb submit failed\n",
+ stir->netdev->name);
stir->receiving = 0;
msleep(10);
continue;
@@ -836,8 +837,8 @@ static void stir_rcv_irq(struct urb *urb)
/* in case of error, the kernel thread will restart us */
if (err) {
- warn("%s: usb receive submit error: %d",
- stir->netdev->name, err);
+ dev_warn(&stir->netdev->dev, "usb receive submit error: %d\n",
+ err);
stir->receiving = 0;
wake_up_process(stir->thread);
}
@@ -1073,7 +1074,8 @@ static int stir_probe(struct usb_interface *intf,
if (ret != 0)
goto err_out2;
- info("IrDA: Registered SigmaTel device %s", net->name);
+ dev_info(&intf->dev, "IrDA: Registered SigmaTel device %s\n",
+ net->name);
usb_set_intfdata(intf, stir);
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 18f4b3a96ae..9c926d205de 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -165,7 +165,7 @@ static void vlsi_proc_pdev(struct seq_file *seq, struct pci_dev *pdev)
unsigned iobase = pci_resource_start(pdev, 0);
unsigned i;
- seq_printf(seq, "\n%s (vid/did: %04x/%04x)\n",
+ seq_printf(seq, "\n%s (vid/did: [%04x:%04x])\n",
pci_name(pdev), (int)pdev->vendor, (int)pdev->device);
seq_printf(seq, "pci-power-state: %u\n", (unsigned) pdev->current_state);
seq_printf(seq, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n",
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 804698fc6a8..d85717e3022 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -85,7 +85,7 @@ struct ixgb_adapter;
#define DPRINTK(nlevel, klevel, fmt, args...) \
(void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
- __FUNCTION__ , ## args))
+ __func__ , ## args))
/* TX/RX descriptor defines */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index aa75385cd6c..be3c7dc96f6 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -977,15 +977,17 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if (buffer_info->skb) {
-
+ if (buffer_info->dma) {
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+ buffer_info->length = 0;
+ }
+ if (buffer_info->skb) {
dev_kfree_skb(buffer_info->skb);
-
buffer_info->skb = NULL;
}
}
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 956914a5028..e116d340dcc 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -37,17 +36,15 @@
#include "ixgbe_type.h"
#include "ixgbe_common.h"
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
#include <linux/dca.h>
#endif
-#define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
-
#define PFX "ixgbe: "
#define DPRINTK(nlevel, klevel, fmt, args...) \
((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
- __FUNCTION__ , ## args)))
+ __func__ , ## args)))
/* TX/RX descriptor defines */
#define IXGBE_DEFAULT_TXD 1024
@@ -58,23 +55,14 @@
#define IXGBE_MAX_RXD 4096
#define IXGBE_MIN_RXD 64
-#define IXGBE_DEFAULT_RXQ 1
-#define IXGBE_MAX_RXQ 1
-#define IXGBE_MIN_RXQ 1
-
-#define IXGBE_DEFAULT_ITR_RX_USECS 125 /* 8k irqs/sec */
-#define IXGBE_DEFAULT_ITR_TX_USECS 250 /* 4k irqs/sec */
-#define IXGBE_MIN_ITR_USECS 100 /* 500k irqs/sec */
-#define IXGBE_MAX_ITR_USECS 10000 /* 100 irqs/sec */
-
/* flow control */
#define IXGBE_DEFAULT_FCRTL 0x10000
-#define IXGBE_MIN_FCRTL 0
+#define IXGBE_MIN_FCRTL 0x40
#define IXGBE_MAX_FCRTL 0x7FF80
#define IXGBE_DEFAULT_FCRTH 0x20000
-#define IXGBE_MIN_FCRTH 0
+#define IXGBE_MIN_FCRTH 0x600
#define IXGBE_MAX_FCRTH 0x7FFF0
-#define IXGBE_DEFAULT_FCPAUSE 0x6800 /* may be too long */
+#define IXGBE_DEFAULT_FCPAUSE 0xFFFF
#define IXGBE_MIN_FCPAUSE 0
#define IXGBE_MAX_FCPAUSE 0xFFFF
@@ -88,9 +76,6 @@
#define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
-/* How many Tx Descriptors do we need to call netif_wake_queue? */
-#define IXGBE_TX_QUEUE_WAKE 16
-
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */
@@ -119,6 +104,7 @@ struct ixgbe_rx_buffer {
dma_addr_t dma;
struct page *page;
dma_addr_t page_dma;
+ unsigned int page_offset;
};
struct ixgbe_queue_stats {
@@ -150,22 +136,20 @@ struct ixgbe_ring {
* offset associated with this ring, which is different
* for DCE and RSS modes */
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
/* cpu for tx queue */
int cpu;
#endif
struct net_lro_mgr lro_mgr;
bool lro_used;
struct ixgbe_queue_stats stats;
- u8 v_idx; /* maps directly to the index for this ring in the hardware
- * vector array, can also be used for finding the bit in EICR
- * and friends that represents the vector for this ring */
+ u16 v_idx; /* maps directly to the index for this ring in the hardware
+ * vector array, can also be used for finding the bit in EICR
+ * and friends that represents the vector for this ring */
- u32 eims_value;
- u16 itr_register;
- char name[IFNAMSIZ + 5];
u16 work_limit; /* max work per interrupt */
+ u16 rx_buf_len;
};
#define RING_F_VMDQ 1
@@ -190,8 +174,8 @@ struct ixgbe_q_vector {
DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
u8 rxr_count; /* Rx ring count assigned to this vector */
u8 txr_count; /* Tx ring count assigned to this vector */
- u8 tx_eitr;
- u8 rx_eitr;
+ u8 tx_itr;
+ u8 rx_itr;
u32 eitr;
};
@@ -228,7 +212,6 @@ struct ixgbe_adapter {
struct timer_list watchdog_timer;
struct vlan_group *vlgrp;
u16 bd_number;
- u16 rx_buf_len;
struct work_struct reset_task;
struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
@@ -240,7 +223,9 @@ struct ixgbe_adapter {
/* TX */
struct ixgbe_ring *tx_ring; /* One per active queue */
+ int num_tx_queues;
u64 restart_queue;
+ u64 hw_csum_tx_good;
u64 lsc_int;
u64 hw_tso_ctxt;
u64 hw_tso6_ctxt;
@@ -249,12 +234,10 @@ struct ixgbe_adapter {
/* RX */
struct ixgbe_ring *rx_ring; /* One per active queue */
- u64 hw_csum_tx_good;
+ int num_rx_queues;
u64 hw_csum_rx_error;
u64 hw_csum_rx_good;
u64 non_eop_descs;
- int num_tx_queues;
- int num_rx_queues;
int num_msix_vectors;
struct ixgbe_ring_feature ring_feature[3];
struct msix_entry *msix_entries;
@@ -267,15 +250,28 @@ struct ixgbe_adapter {
* thus the additional *_CAPABLE flags.
*/
u32 flags;
-#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1 << 0)
-#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1)
-#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 2)
-#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3)
-#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4)
-#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 5)
-#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 6)
-#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 7)
-#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 8)
+#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1)
+#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1)
+#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2)
+#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3)
+#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 4)
+#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 6)
+#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 7)
+#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 8)
+#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 9)
+#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 10)
+#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 11)
+#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 12)
+#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 13)
+#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 16)
+#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17)
+#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18)
+#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
+#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
+#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23)
+
+/* default to trying for four seconds */
+#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
/* OS defined structs */
struct net_device *netdev;
@@ -288,14 +284,21 @@ struct ixgbe_adapter {
struct ixgbe_hw_stats stats;
/* Interrupt Throttle Rate */
- u32 rx_eitr;
- u32 tx_eitr;
+ u32 eitr_param;
unsigned long state;
u64 tx_busy;
u64 lro_aggregated;
u64 lro_flushed;
u64 lro_no_desc;
+ unsigned int tx_ring_count;
+ unsigned int rx_ring_count;
+
+ u32 link_speed;
+ bool link_up;
+ unsigned long link_check_timeout;
+
+ struct work_struct watchdog_task;
};
enum ixbge_state_t {
@@ -317,11 +320,11 @@ extern int ixgbe_up(struct ixgbe_adapter *adapter);
extern void ixgbe_down(struct ixgbe_adapter *adapter);
extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
extern void ixgbe_reset(struct ixgbe_adapter *adapter);
-extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
-extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rxdr);
-extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *txdr);
+extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index f96358b641a..7cddcfba809 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -36,67 +35,62 @@
#define IXGBE_82598_MAX_TX_QUEUES 32
#define IXGBE_82598_MAX_RX_QUEUES 64
#define IXGBE_82598_RAR_ENTRIES 16
+#define IXGBE_82598_MC_TBL_SIZE 128
+#define IXGBE_82598_VFT_TBL_SIZE 128
-static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed,
- bool *autoneg);
-static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw,
- u32 *speed, bool *autoneg);
-static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
- bool *link_up);
-static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed,
- bool autoneg,
- bool autoneg_wait_to_complete);
+static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg);
static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed,
- bool autoneg,
- bool autoneg_wait_to_complete);
-static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
-
+static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete);
+/**
+ */
static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
{
- hw->mac.num_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
- hw->mac.num_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
- hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES;
-
- /* PHY ops are filled in by default properly for Fiber only */
- if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) {
- hw->mac.ops.setup_link = &ixgbe_setup_copper_link_82598;
- hw->mac.ops.setup_link_speed = &ixgbe_setup_copper_link_speed_82598;
- hw->mac.ops.get_link_settings =
- &ixgbe_get_copper_link_settings_82598;
-
- /* Call PHY identify routine to get the phy type */
- ixgbe_identify_phy(hw);
-
- switch (hw->phy.type) {
- case ixgbe_phy_tn:
- hw->phy.ops.setup_link = &ixgbe_setup_tnx_phy_link;
- hw->phy.ops.check_link = &ixgbe_check_tnx_phy_link;
- hw->phy.ops.setup_link_speed =
- &ixgbe_setup_tnx_phy_link_speed;
- break;
- default:
- break;
- }
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+
+ /* Call PHY identify routine to get the phy type */
+ ixgbe_identify_phy_generic(hw);
+
+ /* PHY Init */
+ switch (phy->type) {
+ default:
+ break;
}
+ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
+ mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
+ mac->ops.setup_link_speed =
+ &ixgbe_setup_copper_link_speed_82598;
+ mac->ops.get_link_capabilities =
+ &ixgbe_get_copper_link_capabilities_82598;
+ }
+
+ mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
+ mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
+ mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
+ mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
+ mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
+
return 0;
}
/**
- * ixgbe_get_link_settings_82598 - Determines default link settings
+ * ixgbe_get_link_capabilities_82598 - Determines link capabilities
* @hw: pointer to hardware structure
* @speed: pointer to link speed
* @autoneg: boolean auto-negotiation value
*
- * Determines the default link settings by reading the AUTOC register.
+ * Determines the link capabilities by reading the AUTOC register.
**/
-static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed,
- bool *autoneg)
+static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
{
s32 status = 0;
s32 autoc_reg;
@@ -145,15 +139,16 @@ static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed,
}
/**
- * ixgbe_get_copper_link_settings_82598 - Determines default link settings
+ * ixgbe_get_copper_link_capabilities_82598 - Determines link capabilities
* @hw: pointer to hardware structure
* @speed: pointer to link speed
* @autoneg: boolean auto-negotiation value
*
- * Determines the default link settings by reading the AUTOC register.
+ * Determines the link capabilities by reading the AUTOC register.
**/
-static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw,
- u32 *speed, bool *autoneg)
+s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
{
s32 status = IXGBE_ERR_LINK_SETUP;
u16 speed_ability;
@@ -161,9 +156,9 @@ static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw,
*speed = 0;
*autoneg = true;
- status = ixgbe_read_phy_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &speed_ability);
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &speed_ability);
if (status == 0) {
if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
@@ -191,11 +186,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
+ case IXGBE_DEV_ID_82598EB_XF_LR:
media_type = ixgbe_media_type_fiber;
break;
- case IXGBE_DEV_ID_82598AT_DUAL_PORT:
- media_type = ixgbe_media_type_copper;
- break;
default:
media_type = ixgbe_media_type_unknown;
break;
@@ -205,6 +198,122 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_setup_fc_82598 - Configure flow control settings
+ * @hw: pointer to hardware structure
+ * @packetbuf_num: packet buffer number (0-7)
+ *
+ * Configures the flow control settings based on SW configuration. This
+ * function is used for 802.3x flow control configuration only.
+ **/
+s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
+{
+ u32 frctl_reg;
+ u32 rmcs_reg;
+
+ if (packetbuf_num < 0 || packetbuf_num > 7) {
+ hw_dbg(hw, "Invalid packet buffer number [%d], expected range is"
+ " 0-7\n", packetbuf_num);
+ }
+
+ frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
+
+ rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
+ rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
+
+ /*
+ * 10 gig parts do not have a word in the EEPROM to determine the
+ * default flow control setting, so we explicitly set it to full.
+ */
+ if (hw->fc.type == ixgbe_fc_default)
+ hw->fc.type = ixgbe_fc_full;
+
+ /*
+ * We want to save off the original Flow Control configuration just in
+ * case we get disconnected and then reconnected into a different hub
+ * or switch with different Flow Control capabilities.
+ */
+ hw->fc.original_type = hw->fc.type;
+
+ /*
+ * The possible values of the "flow_control" parameter are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames but not
+ * send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but we do not
+ * support receiving pause frames)
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.type) {
+ case ixgbe_fc_none:
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled,
+ * and Tx Flow control is disabled.
+ */
+ frctl_reg |= IXGBE_FCTRL_RFCE;
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is disabled,
+ * by a software over-ride.
+ */
+ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
+ break;
+ case ixgbe_fc_full:
+ /*
+ * Flow control (both Rx and Tx) is enabled by a software
+ * over-ride.
+ */
+ frctl_reg |= IXGBE_FCTRL_RFCE;
+ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
+ break;
+ default:
+ /* We should never get here. The value should be 0-3. */
+ hw_dbg(hw, "Flow control param set incorrectly\n");
+ break;
+ }
+
+ /* Enable 802.3x based flow control settings. */
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg);
+ IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
+
+ /*
+ * Check for invalid software configuration, zeros are completely
+ * invalid for all parameters used past this point, and if we enable
+ * flow control with zero water marks, we blast flow control packets.
+ */
+ if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
+ hw_dbg(hw, "Flow control structure initialized incorrectly\n");
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
+ }
+
+ /*
+ * We need to set up the Receive Threshold high and low water
+ * marks as well as (optionally) enabling the transmission of
+ * XON frames.
+ */
+ if (hw->fc.type & ixgbe_fc_tx_pause) {
+ if (hw->fc.send_xon) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
+ (hw->fc.low_water | IXGBE_FCRTL_XONE));
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
+ hw->fc.low_water);
+ }
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
+ (hw->fc.high_water)|IXGBE_FCRTH_FCEN);
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+
+ return 0;
+}
+
+/**
* ixgbe_setup_mac_link_82598 - Configures MAC link settings
* @hw: pointer to hardware structure
*
@@ -248,8 +357,7 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
}
if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
- hw_dbg(hw,
- "Autonegotiation did not complete.\n");
+ hw_dbg(hw, "Autonegotiation did not complete.\n");
}
}
}
@@ -259,8 +367,8 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
* case we get disconnected and then reconnected into a different hub
* or switch with different Flow Control capabilities.
*/
- hw->fc.type = hw->fc.original_type;
- ixgbe_setup_fc(hw, 0);
+ hw->fc.original_type = hw->fc.type;
+ ixgbe_setup_fc_82598(hw, 0);
/* Add delay to filter out noises during initial link setup */
msleep(50);
@@ -273,20 +381,35 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
* @hw: pointer to hardware structure
* @speed: pointer to link speed
* @link_up: true is link is up, false otherwise
+ * @link_up_wait_to_complete: bool used to wait for link up or not
*
* Reads the links register to determine if link is up and the current speed
**/
-static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
- bool *link_up)
+static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed, bool *link_up,
+ bool link_up_wait_to_complete)
{
u32 links_reg;
+ u32 i;
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
-
- if (links_reg & IXGBE_LINKS_UP)
- *link_up = true;
- else
- *link_up = false;
+ if (link_up_wait_to_complete) {
+ for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ if (links_reg & IXGBE_LINKS_UP) {
+ *link_up = true;
+ break;
+ } else {
+ *link_up = false;
+ }
+ msleep(100);
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ }
+ } else {
+ if (links_reg & IXGBE_LINKS_UP)
+ *link_up = true;
+ else
+ *link_up = false;
+ }
if (links_reg & IXGBE_LINKS_SPEED)
*speed = IXGBE_LINK_SPEED_10GB_FULL;
@@ -296,6 +419,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
return 0;
}
+
/**
* ixgbe_setup_mac_link_speed_82598 - Set MAC link speed
* @hw: pointer to hardware structure
@@ -306,18 +430,18 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
* Set the link speed in the AUTOC register and restarts link.
**/
static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
- u32 speed, bool autoneg,
- bool autoneg_wait_to_complete)
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete)
{
s32 status = 0;
/* If speed is 10G, then check for CX4 or XAUI. */
if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
- (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4)))
+ (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) {
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
- else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg))
+ } else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) {
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
- else if (autoneg) {
+ } else if (autoneg) {
/* BX mode - Autonegotiate 1G */
if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD))
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN;
@@ -336,7 +460,7 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
* ixgbe_hw This will write the AUTOC register based on the new
* stored values
*/
- hw->mac.ops.setup_link(hw);
+ ixgbe_setup_mac_link_82598(hw);
}
return status;
@@ -354,18 +478,17 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
**/
static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw)
{
- s32 status = 0;
+ s32 status;
/* Restart autonegotiation on PHY */
- if (hw->phy.ops.setup_link)
- status = hw->phy.ops.setup_link(hw);
+ status = hw->phy.ops.setup_link(hw);
- /* Set MAC to KX/KX4 autoneg, which defaultis to Parallel detection */
+ /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */
hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX);
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN;
/* Set up MAC */
- hw->mac.ops.setup_link(hw);
+ ixgbe_setup_mac_link_82598(hw);
return status;
}
@@ -379,23 +502,23 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw)
*
* Sets the link speed in the AUTOC register in the MAC and restarts link.
**/
-static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed,
- bool autoneg,
- bool autoneg_wait_to_complete)
+static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete)
{
- s32 status = 0;
+ s32 status;
/* Setup the PHY according to input speed */
- if (hw->phy.ops.setup_link_speed)
- status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
- autoneg_wait_to_complete);
+ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
+ autoneg_wait_to_complete);
/* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */
hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX);
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN;
/* Set up MAC */
- hw->mac.ops.setup_link(hw);
+ ixgbe_setup_mac_link_82598(hw);
return status;
}
@@ -404,7 +527,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed,
* ixgbe_reset_hw_82598 - Performs hardware reset
* @hw: pointer to hardware structure
*
- * Resets the hardware by reseting the transmit and receive units, masks and
+ * Resets the hardware by resetting the transmit and receive units, masks and
* clears all interrupts, performing a PHY reset, and performing a link (MAC)
* reset.
**/
@@ -418,35 +541,44 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
u8 analog_val;
/* Call adapter stop to disable tx/rx and clear interrupts */
- ixgbe_stop_adapter(hw);
+ hw->mac.ops.stop_adapter(hw);
/*
- * Power up the Atlas TX lanes if they are currently powered down.
- * Atlas TX lanes are powered down for MAC loopback tests, but
+ * Power up the Atlas Tx lanes if they are currently powered down.
+ * Atlas Tx lanes are powered down for MAC loopback tests, but
* they are not automatically restored on reset.
*/
- ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
+ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) {
- /* Enable TX Atlas so packets can be transmitted again */
- ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
+ /* Enable Tx Atlas so packets can be transmitted again */
+ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
+ &analog_val);
analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN;
- ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val);
+ hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
+ analog_val);
- ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val);
+ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
+ &analog_val);
analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
- ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val);
+ hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
+ analog_val);
- ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val);
+ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
+ &analog_val);
analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
- ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val);
+ hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
+ analog_val);
- ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val);
+ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
+ &analog_val);
analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
- ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val);
+ hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
+ analog_val);
}
/* Reset PHY */
- ixgbe_reset_phy(hw);
+ if (hw->phy.reset_disable == false)
+ hw->phy.ops.reset(hw);
/*
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
@@ -499,29 +631,311 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
} else {
hw->mac.link_attach_type =
- (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE);
+ (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE);
hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK);
hw->mac.link_settings_loaded = true;
}
/* Store the permanent mac address */
- ixgbe_get_mac_addr(hw, hw->mac.perm_addr);
+ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
return status;
}
+/**
+ * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to associate with a VMDq index
+ * @vmdq: VMDq set index
+ **/
+s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 rar_high;
+
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+ rar_high &= ~IXGBE_RAH_VIND_MASK;
+ rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
+ return 0;
+}
+
+/**
+ * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to associate with a VMDq index
+ * @vmdq: VMDq clear index (not used in 82598, but elsewhere)
+ **/
+static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 rar_high;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ if (rar < rar_entries) {
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+ if (rar_high & IXGBE_RAH_VIND_MASK) {
+ rar_high &= ~IXGBE_RAH_VIND_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
+ }
+ } else {
+ hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_set_vfta_82598 - Set VLAN filter table
+ * @hw: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFTA
+ * @vlan_on: boolean flag to turn on/off VLAN in VFTA
+ *
+ * Turn on/off specified VLAN in the VLAN filter table.
+ **/
+s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on)
+{
+ u32 regindex;
+ u32 bitindex;
+ u32 bits;
+ u32 vftabyte;
+
+ if (vlan > 4095)
+ return IXGBE_ERR_PARAM;
+
+ /* Determine 32-bit word position in array */
+ regindex = (vlan >> 5) & 0x7F; /* upper seven bits */
+
+ /* Determine the location of the (VMD) queue index */
+ vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
+ bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */
+
+ /* Set the nibble for VMD queue index */
+ bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex));
+ bits &= (~(0x0F << bitindex));
+ bits |= (vind << bitindex);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits);
+
+ /* Determine the location of the bit for this VLAN id */
+ bitindex = vlan & 0x1F; /* lower five bits */
+
+ bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
+ if (vlan_on)
+ /* Turn on this VLAN id */
+ bits |= (1 << bitindex);
+ else
+ /* Turn off this VLAN id */
+ bits &= ~(1 << bitindex);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
+
+ return 0;
+}
+
+/**
+ * ixgbe_clear_vfta_82598 - Clear VLAN filter table
+ * @hw: pointer to hardware structure
+ *
+ * Clears the VLAN filer table, and the VMDq index associated with the filter
+ **/
+static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw)
+{
+ u32 offset;
+ u32 vlanbyte;
+
+ for (offset = 0; offset < hw->mac.vft_size; offset++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
+
+ for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
+ for (offset = 0; offset < hw->mac.vft_size; offset++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
+ 0);
+
+ return 0;
+}
+
+/**
+ * ixgbe_blink_led_start_82598 - Blink LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to blink
+ **/
+static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index)
+{
+ ixgbe_link_speed speed = 0;
+ bool link_up = 0;
+ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ /*
+ * Link must be up to auto-blink the LEDs on the 82598EB MAC;
+ * force it if link is down.
+ */
+ hw->mac.ops.check_link(hw, &speed, &link_up, false);
+
+ if (!link_up) {
+ autoc_reg |= IXGBE_AUTOC_FLU;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+ msleep(10);
+ }
+
+ led_reg &= ~IXGBE_LED_MODE_MASK(index);
+ led_reg |= IXGBE_LED_BLINK(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return 0;
+}
+
+/**
+ * ixgbe_blink_led_stop_82598 - Stop blinking LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to stop blinking
+ **/
+static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index)
+{
+ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ autoc_reg &= ~IXGBE_AUTOC_FLU;
+ autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+
+ led_reg &= ~IXGBE_LED_MODE_MASK(index);
+ led_reg &= ~IXGBE_LED_BLINK(index);
+ led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return 0;
+}
+
+/**
+ * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register
+ * @hw: pointer to hardware structure
+ * @reg: analog register to read
+ * @val: read value
+ *
+ * Performs read operation to Atlas analog register specified.
+ **/
+s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
+{
+ u32 atlas_ctl;
+
+ IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL,
+ IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(10);
+ atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
+ *val = (u8)atlas_ctl;
+
+ return 0;
+}
+
+/**
+ * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register
+ * @hw: pointer to hardware structure
+ * @reg: atlas register to write
+ * @val: value to write
+ *
+ * Performs write operation to Atlas analog register specified.
+ **/
+s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
+{
+ u32 atlas_ctl;
+
+ atlas_ctl = (reg << 8) | val;
+ IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(10);
+
+ return 0;
+}
+
+/**
+ * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
+ * @hw: pointer to hardware structure
+ *
+ * Determines physical layer capabilities of the current configuration.
+ **/
+s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
+{
+ s32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82598EB_CX4:
+ case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
+ break;
+ case IXGBE_DEV_ID_82598AF_DUAL_PORT:
+ case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+ break;
+ case IXGBE_DEV_ID_82598EB_XF_LR:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ break;
+
+ default:
+ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ break;
+ }
+
+ return physical_layer;
+}
+
static struct ixgbe_mac_operations mac_ops_82598 = {
- .reset = &ixgbe_reset_hw_82598,
+ .init_hw = &ixgbe_init_hw_generic,
+ .reset_hw = &ixgbe_reset_hw_82598,
+ .start_hw = &ixgbe_start_hw_generic,
+ .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic,
.get_media_type = &ixgbe_get_media_type_82598,
+ .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
+ .get_mac_addr = &ixgbe_get_mac_addr_generic,
+ .stop_adapter = &ixgbe_stop_adapter_generic,
+ .read_analog_reg8 = &ixgbe_read_analog_reg8_82598,
+ .write_analog_reg8 = &ixgbe_write_analog_reg8_82598,
.setup_link = &ixgbe_setup_mac_link_82598,
- .check_link = &ixgbe_check_mac_link_82598,
.setup_link_speed = &ixgbe_setup_mac_link_speed_82598,
- .get_link_settings = &ixgbe_get_link_settings_82598,
+ .check_link = &ixgbe_check_mac_link_82598,
+ .get_link_capabilities = &ixgbe_get_link_capabilities_82598,
+ .led_on = &ixgbe_led_on_generic,
+ .led_off = &ixgbe_led_off_generic,
+ .blink_led_start = &ixgbe_blink_led_start_82598,
+ .blink_led_stop = &ixgbe_blink_led_stop_82598,
+ .set_rar = &ixgbe_set_rar_generic,
+ .clear_rar = &ixgbe_clear_rar_generic,
+ .set_vmdq = &ixgbe_set_vmdq_82598,
+ .clear_vmdq = &ixgbe_clear_vmdq_82598,
+ .init_rx_addrs = &ixgbe_init_rx_addrs_generic,
+ .update_uc_addr_list = &ixgbe_update_uc_addr_list_generic,
+ .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic,
+ .enable_mc = &ixgbe_enable_mc_generic,
+ .disable_mc = &ixgbe_disable_mc_generic,
+ .clear_vfta = &ixgbe_clear_vfta_82598,
+ .set_vfta = &ixgbe_set_vfta_82598,
+ .setup_fc = &ixgbe_setup_fc_82598,
+};
+
+static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
+ .init_params = &ixgbe_init_eeprom_params_generic,
+ .read = &ixgbe_read_eeprom_generic,
+ .validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
+ .update_checksum = &ixgbe_update_eeprom_checksum_generic,
+};
+
+static struct ixgbe_phy_operations phy_ops_82598 = {
+ .identify = &ixgbe_identify_phy_generic,
+ /* .identify_sfp = &ixgbe_identify_sfp_module_generic, */
+ .reset = &ixgbe_reset_phy_generic,
+ .read_reg = &ixgbe_read_phy_reg_generic,
+ .write_reg = &ixgbe_write_phy_reg_generic,
+ .setup_link = &ixgbe_setup_phy_link_generic,
+ .setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
};
struct ixgbe_info ixgbe_82598_info = {
.mac = ixgbe_mac_82598EB,
.get_invariants = &ixgbe_get_invariants_82598,
.mac_ops = &mac_ops_82598,
+ .eeprom_ops = &eeprom_ops_82598,
+ .phy_ops = &phy_ops_82598,
};
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 7fd6aeb1b02..f67c68404bb 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -33,20 +32,28 @@
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
-static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw);
-
static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw);
+static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
+static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
+static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
+static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
+ u16 count);
+static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
+static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
+static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
+static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
-static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
-static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);
+static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
+static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
+static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
/**
- * ixgbe_start_hw - Prepare hardware for TX/RX
+ * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
*
* Starts the hardware by filling the bus info structure and media type, clears
@@ -54,7 +61,7 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
* table, VLAN filter table, calls routine to set up link and flow control
* settings, and leaves transmit and receive units disabled and uninitialized
**/
-s32 ixgbe_start_hw(struct ixgbe_hw *hw)
+s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
{
u32 ctrl_ext;
@@ -62,22 +69,22 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw)
hw->phy.media_type = hw->mac.ops.get_media_type(hw);
/* Identify the PHY */
- ixgbe_identify_phy(hw);
+ hw->phy.ops.identify(hw);
/*
* Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table
*/
- ixgbe_init_rx_addrs(hw);
+ hw->mac.ops.init_rx_addrs(hw);
/* Clear the VLAN filter table */
- ixgbe_clear_vfta(hw);
+ hw->mac.ops.clear_vfta(hw);
/* Set up link */
hw->mac.ops.setup_link(hw);
/* Clear statistics registers */
- ixgbe_clear_hw_cntrs(hw);
+ hw->mac.ops.clear_hw_cntrs(hw);
/* Set No Snoop Disable */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
@@ -92,34 +99,34 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw)
}
/**
- * ixgbe_init_hw - Generic hardware initialization
+ * ixgbe_init_hw_generic - Generic hardware initialization
* @hw: pointer to hardware structure
*
- * Initialize the hardware by reseting the hardware, filling the bus info
+ * Initialize the hardware by resetting the hardware, filling the bus info
* structure and media type, clears all on chip counters, initializes receive
* address registers, multicast table, VLAN filter table, calls routine to set
* up link and flow control settings, and leaves transmit and receive units
* disabled and uninitialized
**/
-s32 ixgbe_init_hw(struct ixgbe_hw *hw)
+s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
{
/* Reset the hardware */
- hw->mac.ops.reset(hw);
+ hw->mac.ops.reset_hw(hw);
/* Start the HW */
- ixgbe_start_hw(hw);
+ hw->mac.ops.start_hw(hw);
return 0;
}
/**
- * ixgbe_clear_hw_cntrs - Generic clear hardware counters
+ * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
* @hw: pointer to hardware structure
*
* Clears all hardware statistics counters by reading them from the hardware
* Statistics counters are clear on read.
**/
-static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
+s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
{
u16 i = 0;
@@ -191,7 +198,36 @@ static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
}
/**
- * ixgbe_get_mac_addr - Generic get MAC address
+ * ixgbe_read_pba_num_generic - Reads part number from EEPROM
+ * @hw: pointer to hardware structure
+ * @pba_num: stores the part number from the EEPROM
+ *
+ * Reads the part number from the EEPROM.
+ **/
+s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
+{
+ s32 ret_val;
+ u16 data;
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
+ if (ret_val) {
+ hw_dbg(hw, "NVM Read Error\n");
+ return ret_val;
+ }
+ *pba_num = (u32)(data << 16);
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
+ if (ret_val) {
+ hw_dbg(hw, "NVM Read Error\n");
+ return ret_val;
+ }
+ *pba_num |= data;
+
+ return 0;
+}
+
+/**
+ * ixgbe_get_mac_addr_generic - Generic get MAC address
* @hw: pointer to hardware structure
* @mac_addr: Adapter MAC address
*
@@ -199,7 +235,7 @@ static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
* A reset of the adapter must be performed prior to calling this function
* in order for the MAC address to have been loaded from the EEPROM into RAR0
**/
-s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr)
+s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
{
u32 rar_high;
u32 rar_low;
@@ -217,30 +253,8 @@ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr)
return 0;
}
-s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num)
-{
- s32 ret_val;
- u16 data;
-
- ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM0_PTR, &data);
- if (ret_val) {
- hw_dbg(hw, "NVM Read Error\n");
- return ret_val;
- }
- *part_num = (u32)(data << 16);
-
- ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM1_PTR, &data);
- if (ret_val) {
- hw_dbg(hw, "NVM Read Error\n");
- return ret_val;
- }
- *part_num |= data;
-
- return 0;
-}
-
/**
- * ixgbe_stop_adapter - Generic stop TX/RX units
+ * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
* @hw: pointer to hardware structure
*
* Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
@@ -248,7 +262,7 @@ s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num)
* the shared code and drivers to determine if the adapter is in a stopped
* state and should not touch the hardware.
**/
-s32 ixgbe_stop_adapter(struct ixgbe_hw *hw)
+s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
{
u32 number_of_queues;
u32 reg_val;
@@ -264,6 +278,7 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw)
reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
reg_val &= ~(IXGBE_RXCTRL_RXEN);
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
+ IXGBE_WRITE_FLUSH(hw);
msleep(2);
/* Clear interrupt mask to stop from interrupts being generated */
@@ -273,7 +288,7 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw)
IXGBE_READ_REG(hw, IXGBE_EICR);
/* Disable the transmit unit. Each queue must be disabled. */
- number_of_queues = hw->mac.num_tx_queues;
+ number_of_queues = hw->mac.max_tx_queues;
for (i = 0; i < number_of_queues; i++) {
reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
if (reg_val & IXGBE_TXDCTL_ENABLE) {
@@ -282,15 +297,22 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw)
}
}
+ /*
+ * Prevent the PCI-E bus from from hanging by disabling PCI-E master
+ * access and verify no pending requests
+ */
+ if (ixgbe_disable_pcie_master(hw) != 0)
+ hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
+
return 0;
}
/**
- * ixgbe_led_on - Turns on the software controllable LEDs.
+ * ixgbe_led_on_generic - Turns on the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn on
**/
-s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index)
+s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
{
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
@@ -304,11 +326,11 @@ s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index)
}
/**
- * ixgbe_led_off - Turns off the software controllable LEDs.
+ * ixgbe_led_off_generic - Turns off the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn off
**/
-s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index)
+s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
{
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
@@ -321,15 +343,14 @@ s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index)
return 0;
}
-
/**
- * ixgbe_init_eeprom - Initialize EEPROM params
+ * ixgbe_init_eeprom_params_generic - Initialize EEPROM params
* @hw: pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
* ixgbe_hw struct in order to set up EEPROM access.
**/
-s32 ixgbe_init_eeprom(struct ixgbe_hw *hw)
+s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
{
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
u32 eec;
@@ -337,6 +358,9 @@ s32 ixgbe_init_eeprom(struct ixgbe_hw *hw)
if (eeprom->type == ixgbe_eeprom_uninitialized) {
eeprom->type = ixgbe_eeprom_none;
+ /* Set default semaphore delay to 10ms which is a well
+ * tested value */
+ eeprom->semaphore_delay = 10;
/*
* Check for EEPROM present first.
@@ -369,18 +393,85 @@ s32 ixgbe_init_eeprom(struct ixgbe_hw *hw)
}
/**
- * ixgbe_read_eeprom - Read EEPROM word using EERD
+ * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be read
+ * @data: read 16 bit value from EEPROM
+ *
+ * Reads 16 bit value from EEPROM through bit-bang method
+ **/
+s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 *data)
+{
+ s32 status;
+ u16 word_in;
+ u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
+
+ hw->eeprom.ops.init_params(hw);
+
+ if (offset >= hw->eeprom.word_size) {
+ status = IXGBE_ERR_EEPROM;
+ goto out;
+ }
+
+ /* Prepare the EEPROM for reading */
+ status = ixgbe_acquire_eeprom(hw);
+
+ if (status == 0) {
+ if (ixgbe_ready_eeprom(hw) != 0) {
+ ixgbe_release_eeprom(hw);
+ status = IXGBE_ERR_EEPROM;
+ }
+ }
+
+ if (status == 0) {
+ ixgbe_standby_eeprom(hw);
+
+ /*
+ * Some SPI eeproms use the 8th address bit embedded in the
+ * opcode
+ */
+ if ((hw->eeprom.address_bits == 8) && (offset >= 128))
+ read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+
+ /* Send the READ command (opcode + addr) */
+ ixgbe_shift_out_eeprom_bits(hw, read_opcode,
+ IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
+ hw->eeprom.address_bits);
+
+ /* Read the data. */
+ word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
+ *data = (word_in >> 8) | (word_in << 8);
+
+ /* End this read operation */
+ ixgbe_release_eeprom(hw);
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_read_eeprom_generic - Read EEPROM word using EERD
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
**/
-s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data)
+s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
u32 eerd;
s32 status;
+ hw->eeprom.ops.init_params(hw);
+
+ if (offset >= hw->eeprom.word_size) {
+ status = IXGBE_ERR_EEPROM;
+ goto out;
+ }
+
eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) +
IXGBE_EEPROM_READ_REG_START;
@@ -389,10 +480,11 @@ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data)
if (status == 0)
*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
- IXGBE_EEPROM_READ_REG_DATA);
+ IXGBE_EEPROM_READ_REG_DATA);
else
hw_dbg(hw, "Eeprom read timed out\n");
+out:
return status;
}
@@ -420,6 +512,58 @@ static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
+ * @hw: pointer to hardware structure
+ *
+ * Prepares EEPROM for access using bit-bang method. This function should
+ * be called before issuing a command to the EEPROM.
+ **/
+static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u32 eec;
+ u32 i;
+
+ if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
+ status = IXGBE_ERR_SWFW_SYNC;
+
+ if (status == 0) {
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ /* Request EEPROM Access */
+ eec |= IXGBE_EEC_REQ;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+
+ for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ if (eec & IXGBE_EEC_GNT)
+ break;
+ udelay(5);
+ }
+
+ /* Release if grant not acquired */
+ if (!(eec & IXGBE_EEC_GNT)) {
+ eec &= ~IXGBE_EEC_REQ;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ hw_dbg(hw, "Could not acquire EEPROM grant\n");
+
+ ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ status = IXGBE_ERR_EEPROM;
+ }
+ }
+
+ /* Setup EEPROM for Read/Write */
+ if (status == 0) {
+ /* Clear CS and SK */
+ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+ }
+ return status;
+}
+
+/**
* ixgbe_get_eeprom_semaphore - Get hardware semaphore
* @hw: pointer to hardware structure
*
@@ -475,7 +619,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
*/
if (i >= timeout) {
hw_dbg(hw, "Driver can't access the Eeprom - Semaphore "
- "not granted.\n");
+ "not granted.\n");
ixgbe_release_eeprom_semaphore(hw);
status = IXGBE_ERR_EEPROM;
}
@@ -503,6 +647,217 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_ready_eeprom - Polls for EEPROM ready
+ * @hw: pointer to hardware structure
+ **/
+static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u16 i;
+ u8 spi_stat_reg;
+
+ /*
+ * Read "Status Register" repeatedly until the LSB is cleared. The
+ * EEPROM will signal that the command has been completed by clearing
+ * bit 0 of the internal status register. If it's not cleared within
+ * 5 milliseconds, then error out.
+ */
+ for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
+ ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
+ IXGBE_EEPROM_OPCODE_BITS);
+ spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
+ if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
+ break;
+
+ udelay(5);
+ ixgbe_standby_eeprom(hw);
+ };
+
+ /*
+ * On some parts, SPI write time could vary from 0-20mSec on 3.3V
+ * devices (and only 0-5mSec on 5V devices)
+ */
+ if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
+ hw_dbg(hw, "SPI EEPROM Status error\n");
+ status = IXGBE_ERR_EEPROM;
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
+ * @hw: pointer to hardware structure
+ **/
+static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
+{
+ u32 eec;
+
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ /* Toggle CS to flush commands */
+ eec |= IXGBE_EEC_CS;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+ eec &= ~IXGBE_EEC_CS;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+}
+
+/**
+ * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
+ * @hw: pointer to hardware structure
+ * @data: data to send to the EEPROM
+ * @count: number of bits to shift out
+ **/
+static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
+ u16 count)
+{
+ u32 eec;
+ u32 mask;
+ u32 i;
+
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ /*
+ * Mask is used to shift "count" bits of "data" out to the EEPROM
+ * one bit at a time. Determine the starting bit based on count
+ */
+ mask = 0x01 << (count - 1);
+
+ for (i = 0; i < count; i++) {
+ /*
+ * A "1" is shifted out to the EEPROM by setting bit "DI" to a
+ * "1", and then raising and then lowering the clock (the SK
+ * bit controls the clock input to the EEPROM). A "0" is
+ * shifted out to the EEPROM by setting "DI" to "0" and then
+ * raising and then lowering the clock.
+ */
+ if (data & mask)
+ eec |= IXGBE_EEC_DI;
+ else
+ eec &= ~IXGBE_EEC_DI;
+
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+
+ udelay(1);
+
+ ixgbe_raise_eeprom_clk(hw, &eec);
+ ixgbe_lower_eeprom_clk(hw, &eec);
+
+ /*
+ * Shift mask to signify next bit of data to shift in to the
+ * EEPROM
+ */
+ mask = mask >> 1;
+ };
+
+ /* We leave the "DI" bit set to "0" when we leave this routine. */
+ eec &= ~IXGBE_EEC_DI;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+}
+
+/**
+ * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
+ * @hw: pointer to hardware structure
+ **/
+static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
+{
+ u32 eec;
+ u32 i;
+ u16 data = 0;
+
+ /*
+ * In order to read a register from the EEPROM, we need to shift
+ * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
+ * the clock input to the EEPROM (setting the SK bit), and then reading
+ * the value of the "DO" bit. During this "shifting in" process the
+ * "DI" bit should always be clear.
+ */
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
+
+ for (i = 0; i < count; i++) {
+ data = data << 1;
+ ixgbe_raise_eeprom_clk(hw, &eec);
+
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ eec &= ~(IXGBE_EEC_DI);
+ if (eec & IXGBE_EEC_DO)
+ data |= 1;
+
+ ixgbe_lower_eeprom_clk(hw, &eec);
+ }
+
+ return data;
+}
+
+/**
+ * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
+ * @hw: pointer to hardware structure
+ * @eec: EEC register's current value
+ **/
+static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
+{
+ /*
+ * Raise the clock input to the EEPROM
+ * (setting the SK bit), then delay
+ */
+ *eec = *eec | IXGBE_EEC_SK;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+}
+
+/**
+ * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
+ * @hw: pointer to hardware structure
+ * @eecd: EECD's current value
+ **/
+static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
+{
+ /*
+ * Lower the clock input to the EEPROM (clearing the SK bit), then
+ * delay
+ */
+ *eec = *eec & ~IXGBE_EEC_SK;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+}
+
+/**
+ * ixgbe_release_eeprom - Release EEPROM, release semaphores
+ * @hw: pointer to hardware structure
+ **/
+static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
+{
+ u32 eec;
+
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ eec |= IXGBE_EEC_CS; /* Pull CS high */
+ eec &= ~IXGBE_EEC_SK; /* Lower SCK */
+
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+
+ udelay(1);
+
+ /* Stop requesting EEPROM access */
+ eec &= ~IXGBE_EEC_REQ;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+
+ ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+}
+
+/**
* ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
* @hw: pointer to hardware structure
**/
@@ -517,7 +872,7 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
/* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
- if (ixgbe_read_eeprom(hw, i, &word) != 0) {
+ if (hw->eeprom.ops.read(hw, i, &word) != 0) {
hw_dbg(hw, "EEPROM read failed\n");
break;
}
@@ -526,15 +881,15 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
/* Include all data from pointers except for the fw pointer */
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
- ixgbe_read_eeprom(hw, i, &pointer);
+ hw->eeprom.ops.read(hw, i, &pointer);
/* Make sure the pointer seems valid */
if (pointer != 0xFFFF && pointer != 0) {
- ixgbe_read_eeprom(hw, pointer, &length);
+ hw->eeprom.ops.read(hw, pointer, &length);
if (length != 0xFFFF && length != 0) {
for (j = pointer+1; j <= pointer+length; j++) {
- ixgbe_read_eeprom(hw, j, &word);
+ hw->eeprom.ops.read(hw, j, &word);
checksum += word;
}
}
@@ -547,14 +902,15 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
}
/**
- * ixgbe_validate_eeprom_checksum - Validate EEPROM checksum
+ * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum_val: calculated checksum
*
* Performs checksum calculation and validates the EEPROM checksum. If the
* caller does not need checksum_val, the value can be NULL.
**/
-s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val)
+s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
+ u16 *checksum_val)
{
s32 status;
u16 checksum;
@@ -565,12 +921,12 @@ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val)
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
- status = ixgbe_read_eeprom(hw, 0, &checksum);
+ status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status == 0) {
checksum = ixgbe_calc_eeprom_checksum(hw);
- ixgbe_read_eeprom(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
+ hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
/*
* Verify read checksum from EEPROM is the same as
@@ -590,6 +946,33 @@ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val)
}
/**
+ * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
+ * @hw: pointer to hardware structure
+ **/
+s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u16 checksum;
+
+ /*
+ * Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ status = hw->eeprom.ops.read(hw, 0, &checksum);
+
+ if (status == 0) {
+ checksum = ixgbe_calc_eeprom_checksum(hw);
+ status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
+ checksum);
+ } else {
+ hw_dbg(hw, "EEPROM read failed\n");
+ }
+
+ return status;
+}
+
+/**
* ixgbe_validate_mac_addr - Validate MAC address
* @mac_addr: pointer to MAC address.
*
@@ -607,61 +990,140 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr)
status = IXGBE_ERR_INVALID_MAC_ADDR;
/* Reject the zero address */
else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
- mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
+ mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
status = IXGBE_ERR_INVALID_MAC_ADDR;
return status;
}
/**
- * ixgbe_set_rar - Set RX address register
+ * ixgbe_set_rar_generic - Set Rx address register
* @hw: pointer to hardware structure
- * @addr: Address to put into receive address register
* @index: Receive address register to write
- * @vind: Vind to set RAR to
+ * @addr: Address to put into receive address register
+ * @vmdq: VMDq "set" or "pool" index
* @enable_addr: set flag that address is active
*
* Puts an ethernet address into a receive address register.
**/
-s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind,
- u32 enable_addr)
+s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
+ u32 enable_addr)
{
u32 rar_low, rar_high;
+ u32 rar_entries = hw->mac.num_rar_entries;
- /*
- * HW expects these in little endian so we reverse the byte order from
- * network order (big endian) to little endian
- */
- rar_low = ((u32)addr[0] |
- ((u32)addr[1] << 8) |
- ((u32)addr[2] << 16) |
- ((u32)addr[3] << 24));
+ /* setup VMDq pool selection before this RAR gets enabled */
+ hw->mac.ops.set_vmdq(hw, index, vmdq);
- rar_high = ((u32)addr[4] |
- ((u32)addr[5] << 8) |
- ((vind << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK));
+ /* Make sure we are using a valid rar index range */
+ if (index < rar_entries) {
+ /*
+ * HW expects these in little endian so we reverse the byte
+ * order from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[0] |
+ ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) |
+ ((u32)addr[3] << 24));
+ /*
+ * Some parts put the VMDq setting in the extra RAH bits,
+ * so save everything except the lower 16 bits that hold part
+ * of the address and the address valid bit.
+ */
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+ rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
- if (enable_addr != 0)
- rar_high |= IXGBE_RAH_AV;
+ if (enable_addr != 0)
+ rar_high |= IXGBE_RAH_AV;
- IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+ } else {
+ hw_dbg(hw, "RAR index %d is out of range.\n", index);
+ }
return 0;
}
/**
- * ixgbe_init_rx_addrs - Initializes receive address filters.
+ * ixgbe_clear_rar_generic - Remove Rx address register
+ * @hw: pointer to hardware structure
+ * @index: Receive address register to write
+ *
+ * Clears an ethernet address from a receive address register.
+ **/
+s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
+{
+ u32 rar_high;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ /* Make sure we are using a valid rar index range */
+ if (index < rar_entries) {
+ /*
+ * Some parts put the VMDq setting in the extra RAH bits,
+ * so save everything except the lower 16 bits that hold part
+ * of the address and the address valid bit.
+ */
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+ } else {
+ hw_dbg(hw, "RAR index %d is out of range.\n", index);
+ }
+
+ /* clear VMDq pool/queue selection for this RAR */
+ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
+
+ return 0;
+}
+
+/**
+ * ixgbe_enable_rar - Enable Rx address register
+ * @hw: pointer to hardware structure
+ * @index: index into the RAR table
+ *
+ * Enables the select receive address register.
+ **/
+static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
+{
+ u32 rar_high;
+
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high |= IXGBE_RAH_AV;
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+}
+
+/**
+ * ixgbe_disable_rar - Disable Rx address register
+ * @hw: pointer to hardware structure
+ * @index: index into the RAR table
+ *
+ * Disables the select receive address register.
+ **/
+static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
+{
+ u32 rar_high;
+
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high &= (~IXGBE_RAH_AV);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+}
+
+/**
+ * ixgbe_init_rx_addrs_generic - Initializes receive address filters.
* @hw: pointer to hardware structure
*
* Places the MAC address in receive address register 0 and clears the rest
- * of the receive addresss registers. Clears the multicast table. Assumes
+ * of the receive address registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
**/
-static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
+s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
{
u32 i;
- u32 rar_entries = hw->mac.num_rx_addrs;
+ u32 rar_entries = hw->mac.num_rar_entries;
/*
* If the current mac address is valid, assume it is a software override
@@ -671,29 +1133,30 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
if (ixgbe_validate_mac_addr(hw->mac.addr) ==
IXGBE_ERR_INVALID_MAC_ADDR) {
/* Get the MAC address from the RAR0 for later reference */
- ixgbe_get_mac_addr(hw, hw->mac.addr);
+ hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
- hw->mac.addr[0], hw->mac.addr[1],
- hw->mac.addr[2]);
+ hw->mac.addr[0], hw->mac.addr[1],
+ hw->mac.addr[2]);
hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
- hw->mac.addr[4], hw->mac.addr[5]);
+ hw->mac.addr[4], hw->mac.addr[5]);
} else {
/* Setup the receive address. */
hw_dbg(hw, "Overriding MAC Address in RAR[0]\n");
hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ",
- hw->mac.addr[0], hw->mac.addr[1],
- hw->mac.addr[2]);
+ hw->mac.addr[0], hw->mac.addr[1],
+ hw->mac.addr[2]);
hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
- hw->mac.addr[4], hw->mac.addr[5]);
+ hw->mac.addr[4], hw->mac.addr[5]);
- ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
}
+ hw->addr_ctrl.overflow_promisc = 0;
hw->addr_ctrl.rar_used_count = 1;
/* Zero out the other receive addresses. */
- hw_dbg(hw, "Clearing RAR[1-15]\n");
+ hw_dbg(hw, "Clearing RAR[1-%d]\n", rar_entries - 1);
for (i = 1; i < rar_entries; i++) {
IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
@@ -705,9 +1168,113 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
hw_dbg(hw, " Clearing MTA\n");
- for (i = 0; i < IXGBE_MC_TBL_SIZE; i++)
+ for (i = 0; i < hw->mac.mcft_size; i++)
IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
+ if (hw->mac.ops.init_uta_tables)
+ hw->mac.ops.init_uta_tables(hw);
+
+ return 0;
+}
+
+/**
+ * ixgbe_add_uc_addr - Adds a secondary unicast address.
+ * @hw: pointer to hardware structure
+ * @addr: new address
+ *
+ * Adds it to unused receive address register or goes into promiscuous mode.
+ **/
+static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
+{
+ u32 rar_entries = hw->mac.num_rar_entries;
+ u32 rar;
+
+ hw_dbg(hw, " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ /*
+ * Place this address in the RAR if there is room,
+ * else put the controller into promiscuous mode
+ */
+ if (hw->addr_ctrl.rar_used_count < rar_entries) {
+ rar = hw->addr_ctrl.rar_used_count -
+ hw->addr_ctrl.mc_addr_in_rar_count;
+ hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+ hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar);
+ hw->addr_ctrl.rar_used_count++;
+ } else {
+ hw->addr_ctrl.overflow_promisc++;
+ }
+
+ hw_dbg(hw, "ixgbe_add_uc_addr Complete\n");
+}
+
+/**
+ * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
+ * @hw: pointer to hardware structure
+ * @addr_list: the list of new addresses
+ * @addr_count: number of addresses
+ * @next: iterator function to walk the address list
+ *
+ * The given list replaces any existing list. Clears the secondary addrs from
+ * receive address registers. Uses unused receive address registers for the
+ * first secondary addresses, and falls back to promiscuous mode as needed.
+ *
+ * Drivers using secondary unicast addresses must set user_set_promisc when
+ * manually putting the device into promiscuous mode.
+ **/
+s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
+ u32 addr_count, ixgbe_mc_addr_itr next)
+{
+ u8 *addr;
+ u32 i;
+ u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
+ u32 uc_addr_in_use;
+ u32 fctrl;
+ u32 vmdq;
+
+ /*
+ * Clear accounting of old secondary address list,
+ * don't count RAR[0]
+ */
+ uc_addr_in_use = hw->addr_ctrl.rar_used_count -
+ hw->addr_ctrl.mc_addr_in_rar_count - 1;
+ hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
+ hw->addr_ctrl.overflow_promisc = 0;
+
+ /* Zero out the other receive addresses */
+ hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use);
+ for (i = 1; i <= uc_addr_in_use; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+ }
+
+ /* Add the new addresses */
+ for (i = 0; i < addr_count; i++) {
+ hw_dbg(hw, " Adding the secondary addresses:\n");
+ addr = next(hw, &addr_list, &vmdq);
+ ixgbe_add_uc_addr(hw, addr, vmdq);
+ }
+
+ if (hw->addr_ctrl.overflow_promisc) {
+ /* enable promisc if not already in overflow or set by user */
+ if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
+ hw_dbg(hw, " Entering address overflow promisc mode\n");
+ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ fctrl |= IXGBE_FCTRL_UPE;
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+ }
+ } else {
+ /* only disable if set by overflow, not by user */
+ if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
+ hw_dbg(hw, " Leaving address overflow promisc mode\n");
+ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ fctrl &= ~IXGBE_FCTRL_UPE;
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+ }
+ }
+
+ hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n");
return 0;
}
@@ -720,7 +1287,7 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
* bit-vector to set in the multicast table. The hardware uses 12 bits, from
* incoming rx multicast addresses, to determine the bit-vector to check in
* the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
- * by the MO field of the MCSTCTRL. The MO field is set during initalization
+ * by the MO field of the MCSTCTRL. The MO field is set during initialization
* to mc_filter_type.
**/
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
@@ -728,19 +1295,19 @@ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
u32 vector = 0;
switch (hw->mac.mc_filter_type) {
- case 0: /* use bits [47:36] of the address */
+ case 0: /* use bits [47:36] of the address */
vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
break;
- case 1: /* use bits [46:35] of the address */
+ case 1: /* use bits [46:35] of the address */
vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
break;
- case 2: /* use bits [45:34] of the address */
+ case 2: /* use bits [45:34] of the address */
vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
break;
- case 3: /* use bits [43:32] of the address */
+ case 3: /* use bits [43:32] of the address */
vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
break;
- default: /* Invalid mc_filter_type */
+ default: /* Invalid mc_filter_type */
hw_dbg(hw, "MC filter type param set incorrectly\n");
break;
}
@@ -794,21 +1361,22 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
**/
static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
{
- u32 rar_entries = hw->mac.num_rx_addrs;
+ u32 rar_entries = hw->mac.num_rar_entries;
+ u32 rar;
hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
- mc_addr[0], mc_addr[1], mc_addr[2],
- mc_addr[3], mc_addr[4], mc_addr[5]);
+ mc_addr[0], mc_addr[1], mc_addr[2],
+ mc_addr[3], mc_addr[4], mc_addr[5]);
/*
* Place this multicast address in the RAR if there is room,
* else put it in the MTA
*/
if (hw->addr_ctrl.rar_used_count < rar_entries) {
- ixgbe_set_rar(hw, hw->addr_ctrl.rar_used_count,
- mc_addr, 0, IXGBE_RAH_AV);
- hw_dbg(hw, "Added a multicast address to RAR[%d]\n",
- hw->addr_ctrl.rar_used_count);
+ /* use RAR from the end up for multicast */
+ rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1;
+ hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV);
+ hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar);
hw->addr_ctrl.rar_used_count++;
hw->addr_ctrl.mc_addr_in_rar_count++;
} else {
@@ -819,22 +1387,23 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
}
/**
- * ixgbe_update_mc_addr_list - Updates MAC list of multicast addresses
+ * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
* @hw: pointer to hardware structure
* @mc_addr_list: the list of new multicast addresses
* @mc_addr_count: number of addresses
- * @pad: number of bytes between addresses in the list
+ * @next: iterator function to walk the multicast address list
*
* The given list replaces any existing list. Clears the MC addrs from receive
- * address registers and the multicast table. Uses unsed receive address
+ * address registers and the multicast table. Uses unused receive address
* registers for the first multicast addresses, and hashes the rest into the
* multicast table.
**/
-s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
- u32 mc_addr_count, u32 pad)
+s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
+ u32 mc_addr_count, ixgbe_mc_addr_itr next)
{
u32 i;
- u32 rar_entries = hw->mac.num_rx_addrs;
+ u32 rar_entries = hw->mac.num_rar_entries;
+ u32 vmdq;
/*
* Set the new number of MC addresses that we are being requested to
@@ -846,7 +1415,8 @@ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
hw->addr_ctrl.mta_in_use = 0;
/* Zero out the other receive addresses. */
- hw_dbg(hw, "Clearing RAR[1-15]\n");
+ hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count,
+ rar_entries - 1);
for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) {
IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
@@ -854,186 +1424,67 @@ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
/* Clear the MTA */
hw_dbg(hw, " Clearing MTA\n");
- for (i = 0; i < IXGBE_MC_TBL_SIZE; i++)
+ for (i = 0; i < hw->mac.mcft_size; i++)
IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
/* Add the new addresses */
for (i = 0; i < mc_addr_count; i++) {
hw_dbg(hw, " Adding the multicast addresses:\n");
- ixgbe_add_mc_addr(hw, mc_addr_list +
- (i * (IXGBE_ETH_LENGTH_OF_ADDRESS + pad)));
+ ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq));
}
/* Enable mta */
if (hw->addr_ctrl.mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
- IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
+ IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
- hw_dbg(hw, "ixgbe_update_mc_addr_list Complete\n");
+ hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n");
return 0;
}
/**
- * ixgbe_clear_vfta - Clear VLAN filter table
+ * ixgbe_enable_mc_generic - Enable multicast address in RAR
* @hw: pointer to hardware structure
*
- * Clears the VLAN filer table, and the VMDq index associated with the filter
+ * Enables multicast address in RAR and the use of the multicast hash table.
**/
-static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw)
+s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
{
- u32 offset;
- u32 vlanbyte;
-
- for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++)
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
-
- for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
- for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++)
- IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
- 0);
+ u32 i;
+ u32 rar_entries = hw->mac.num_rar_entries;
+ struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
- return 0;
-}
+ if (a->mc_addr_in_rar_count > 0)
+ for (i = (rar_entries - a->mc_addr_in_rar_count);
+ i < rar_entries; i++)
+ ixgbe_enable_rar(hw, i);
-/**
- * ixgbe_set_vfta - Set VLAN filter table
- * @hw: pointer to hardware structure
- * @vlan: VLAN id to write to VLAN filter
- * @vind: VMDq output index that maps queue to VLAN id in VFTA
- * @vlan_on: boolean flag to turn on/off VLAN in VFTA
- *
- * Turn on/off specified VLAN in the VLAN filter table.
- **/
-s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on)
-{
- u32 VftaIndex;
- u32 BitOffset;
- u32 VftaReg;
- u32 VftaByte;
-
- /* Determine 32-bit word position in array */
- VftaIndex = (vlan >> 5) & 0x7F; /* upper seven bits */
-
- /* Determine the location of the (VMD) queue index */
- VftaByte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
- BitOffset = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */
-
- /* Set the nibble for VMD queue index */
- VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex));
- VftaReg &= (~(0x0F << BitOffset));
- VftaReg |= (vind << BitOffset);
- IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg);
-
- /* Determine the location of the bit for this VLAN id */
- BitOffset = vlan & 0x1F; /* lower five bits */
-
- VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex));
- if (vlan_on)
- /* Turn on this VLAN id */
- VftaReg |= (1 << BitOffset);
- else
- /* Turn off this VLAN id */
- VftaReg &= ~(1 << BitOffset);
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg);
+ if (a->mta_in_use > 0)
+ IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
+ hw->mac.mc_filter_type);
return 0;
}
/**
- * ixgbe_setup_fc - Configure flow control settings
+ * ixgbe_disable_mc_generic - Disable multicast address in RAR
* @hw: pointer to hardware structure
- * @packetbuf_num: packet buffer number (0-7)
*
- * Configures the flow control settings based on SW configuration.
- * This function is used for 802.3x flow control configuration only.
+ * Disables multicast address in RAR and the use of the multicast hash table.
**/
-s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
{
- u32 frctl_reg;
- u32 rmcs_reg;
-
- if (packetbuf_num < 0 || packetbuf_num > 7)
- hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
- "is 0-7\n", packetbuf_num);
-
- frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
- frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
-
- rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
- rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
-
- /*
- * We want to save off the original Flow Control configuration just in
- * case we get disconnected and then reconnected into a different hub
- * or switch with different Flow Control capabilities.
- */
- hw->fc.type = hw->fc.original_type;
-
- /*
- * The possible values of the "flow_control" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames but not
- * send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but we do not
- * support receiving pause frames)
- * 3: Both Rx and TX flow control (symmetric) are enabled.
- * other: Invalid.
- */
- switch (hw->fc.type) {
- case ixgbe_fc_none:
- break;
- case ixgbe_fc_rx_pause:
- /*
- * RX Flow control is enabled,
- * and TX Flow control is disabled.
- */
- frctl_reg |= IXGBE_FCTRL_RFCE;
- break;
- case ixgbe_fc_tx_pause:
- /*
- * TX Flow control is enabled, and RX Flow control is disabled,
- * by a software over-ride.
- */
- rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
- break;
- case ixgbe_fc_full:
- /*
- * Flow control (both RX and TX) is enabled by a software
- * over-ride.
- */
- frctl_reg |= IXGBE_FCTRL_RFCE;
- rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
- break;
- default:
- /* We should never get here. The value should be 0-3. */
- hw_dbg(hw, "Flow control param set incorrectly\n");
- break;
- }
-
- /* Enable 802.3x based flow control settings. */
- IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg);
- IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
+ u32 i;
+ u32 rar_entries = hw->mac.num_rar_entries;
+ struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
- /*
- * We need to set up the Receive Threshold high and low water
- * marks as well as (optionally) enabling the transmission of
- * XON frames.
- */
- if (hw->fc.type & ixgbe_fc_tx_pause) {
- if (hw->fc.send_xon) {
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
- (hw->fc.low_water | IXGBE_FCRTL_XONE));
- } else {
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
- hw->fc.low_water);
- }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
- (hw->fc.high_water)|IXGBE_FCRTH_FCEN);
- }
+ if (a->mc_addr_in_rar_count > 0)
+ for (i = (rar_entries - a->mc_addr_in_rar_count);
+ i < rar_entries; i++)
+ ixgbe_disable_rar(hw, i);
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+ if (a->mta_in_use > 0)
+ IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
return 0;
}
@@ -1049,13 +1500,24 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
**/
s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
{
- u32 ctrl;
- s32 i;
+ u32 i;
+ u32 reg_val;
+ u32 number_of_queues;
s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- ctrl |= IXGBE_CTRL_GIO_DIS;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
+ /* Disable the receive unit by stopping each queue */
+ number_of_queues = hw->mac.max_rx_queues;
+ for (i = 0; i < number_of_queues; i++) {
+ reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+ if (reg_val & IXGBE_RXDCTL_ENABLE) {
+ reg_val &= ~IXGBE_RXDCTL_ENABLE;
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
+ }
+ }
+
+ reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ reg_val |= IXGBE_CTRL_GIO_DIS;
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
@@ -1070,11 +1532,11 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
/**
- * ixgbe_acquire_swfw_sync - Aquire SWFW semaphore
+ * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
* @hw: pointer to hardware structure
- * @mask: Mask to specify wich semaphore to acquire
+ * @mask: Mask to specify which semaphore to acquire
*
- * Aquires the SWFW semaphore throught the GSSR register for the specified
+ * Acquires the SWFW semaphore thought the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
**/
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -1116,9 +1578,9 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
/**
* ixgbe_release_swfw_sync - Release SWFW semaphore
* @hw: pointer to hardware structure
- * @mask: Mask to specify wich semaphore to release
+ * @mask: Mask to specify which semaphore to release
*
- * Releases the SWFW semaphore throught the GSSR register for the specified
+ * Releases the SWFW semaphore thought the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
**/
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -1135,45 +1597,3 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
ixgbe_release_eeprom_semaphore(hw);
}
-/**
- * ixgbe_read_analog_reg8 - Reads 8 bit Atlas analog register
- * @hw: pointer to hardware structure
- * @reg: analog register to read
- * @val: read value
- *
- * Performs write operation to analog register specified.
- **/
-s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val)
-{
- u32 atlas_ctl;
-
- IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL,
- IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
- IXGBE_WRITE_FLUSH(hw);
- udelay(10);
- atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
- *val = (u8)atlas_ctl;
-
- return 0;
-}
-
-/**
- * ixgbe_write_analog_reg8 - Writes 8 bit Atlas analog register
- * @hw: pointer to hardware structure
- * @reg: atlas register to write
- * @val: value to write
- *
- * Performs write operation to Atlas analog register specified.
- **/
-s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val)
-{
- u32 atlas_ctl;
-
- atlas_ctl = (reg << 8) | val;
- IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
- IXGBE_WRITE_FLUSH(hw);
- udelay(10);
-
- return 0;
-}
-
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index de6ddd5d04a..192f8d01291 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -31,34 +30,45 @@
#include "ixgbe_type.h"
-s32 ixgbe_init_hw(struct ixgbe_hw *hw);
-s32 ixgbe_start_hw(struct ixgbe_hw *hw);
-s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr);
-s32 ixgbe_stop_adapter(struct ixgbe_hw *hw);
-s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num);
+s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
+s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
+s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
+s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw);
+s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num);
+s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr);
+s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw);
+s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw);
+
+s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
+
+s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
+s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
+s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 *data);
+s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
+ u16 *checksum_val);
+s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
+
+s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
+ u32 enable_addr);
+s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw);
+s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
+ u32 mc_addr_count,
+ ixgbe_mc_addr_itr func);
+s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
+ u32 addr_count, ixgbe_mc_addr_itr func);
+s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
+s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
-s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index);
-s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index);
-
-s32 ixgbe_init_eeprom(struct ixgbe_hw *hw);
-s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data);
-s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val);
-
-s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind,
- u32 enable_addr);
-s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
- u32 mc_addr_count, u32 pad);
-s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
-
-s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packtetbuf_num);
-
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
-s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val);
-s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);
+s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val);
+s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val);
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 3efe5dda10a..81a9c4b8672 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -48,7 +47,7 @@ struct ixgbe_stats {
};
#define IXGBE_STAT(m) sizeof(((struct ixgbe_adapter *)0)->m), \
- offsetof(struct ixgbe_adapter, m)
+ offsetof(struct ixgbe_adapter, m)
static struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_packets", IXGBE_STAT(net_stats.rx_packets)},
{"tx_packets", IXGBE_STAT(net_stats.tx_packets)},
@@ -95,14 +94,15 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
};
#define IXGBE_QUEUE_STATS_LEN \
- ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \
- ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \
- (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
-#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
+ ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \
+ ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \
+ (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
+#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
+#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
static int ixgbe_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+ struct ethtool_cmd *ecmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -114,7 +114,7 @@ static int ixgbe_get_settings(struct net_device *netdev,
ecmd->transceiver = XCVR_EXTERNAL;
if (hw->phy.media_type == ixgbe_media_type_copper) {
ecmd->supported |= (SUPPORTED_1000baseT_Full |
- SUPPORTED_TP | SUPPORTED_Autoneg);
+ SUPPORTED_TP | SUPPORTED_Autoneg);
ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg);
if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
@@ -126,14 +126,15 @@ static int ixgbe_get_settings(struct net_device *netdev,
} else {
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising = (ADVERTISED_10000baseT_Full |
- ADVERTISED_FIBRE);
+ ADVERTISED_FIBRE);
ecmd->port = PORT_FIBRE;
+ ecmd->autoneg = AUTONEG_DISABLE;
}
- adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up);
+ hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
if (link_up) {
ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
- SPEED_10000 : SPEED_1000;
+ SPEED_10000 : SPEED_1000;
ecmd->duplex = DUPLEX_FULL;
} else {
ecmd->speed = -1;
@@ -144,7 +145,7 @@ static int ixgbe_get_settings(struct net_device *netdev,
}
static int ixgbe_set_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+ struct ethtool_cmd *ecmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -164,7 +165,7 @@ static int ixgbe_set_settings(struct net_device *netdev,
}
static void ixgbe_get_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+ struct ethtool_pauseparam *pause)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -182,7 +183,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
}
static int ixgbe_set_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+ struct ethtool_pauseparam *pause)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -233,15 +234,15 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
static u32 ixgbe_get_tx_csum(struct net_device *netdev)
{
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ return (netdev->features & NETIF_F_IP_CSUM) != 0;
}
static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
{
if (data)
- netdev->features |= NETIF_F_HW_CSUM;
+ netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
else
- netdev->features &= ~NETIF_F_HW_CSUM;
+ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
return 0;
}
@@ -281,7 +282,7 @@ static int ixgbe_get_regs_len(struct net_device *netdev)
#define IXGBE_GET_STAT(_A_, _R_) _A_->stats._R_
static void ixgbe_get_regs(struct net_device *netdev,
- struct ethtool_regs *regs, void *p)
+ struct ethtool_regs *regs, void *p)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -315,7 +316,9 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC);
/* Interrupt */
- regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICR);
+ /* don't read EICR because it can clear interrupt causes, instead
+ * read EICS which is a shadow but doesn't clear EICR */
+ regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICS);
regs_buff[19] = IXGBE_READ_REG(hw, IXGBE_EICS);
regs_buff[20] = IXGBE_READ_REG(hw, IXGBE_EIMS);
regs_buff[21] = IXGBE_READ_REG(hw, IXGBE_EIMC);
@@ -325,7 +328,7 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[25] = IXGBE_READ_REG(hw, IXGBE_IVAR(0));
regs_buff[26] = IXGBE_READ_REG(hw, IXGBE_MSIXT);
regs_buff[27] = IXGBE_READ_REG(hw, IXGBE_MSIXPBA);
- regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL);
+ regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL(0));
regs_buff[29] = IXGBE_READ_REG(hw, IXGBE_GPIE);
/* Flow Control */
@@ -371,7 +374,7 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[482 + i] = IXGBE_READ_REG(hw, IXGBE_RAL(i));
for (i = 0; i < 16; i++)
regs_buff[498 + i] = IXGBE_READ_REG(hw, IXGBE_RAH(i));
- regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE);
+ regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0));
regs_buff[515] = IXGBE_READ_REG(hw, IXGBE_FCTRL);
regs_buff[516] = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
regs_buff[517] = IXGBE_READ_REG(hw, IXGBE_MCSTCTRL);
@@ -419,7 +422,6 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM);
regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT);
- /* DCE */
regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS);
regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS);
regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS);
@@ -539,21 +541,17 @@ static void ixgbe_get_regs(struct net_device *netdev,
/* Diagnostic */
regs_buff[1071] = IXGBE_READ_REG(hw, IXGBE_RDSTATCTL);
for (i = 0; i < 8; i++)
- regs_buff[1072] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i));
+ regs_buff[1072 + i] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i));
regs_buff[1080] = IXGBE_READ_REG(hw, IXGBE_RDHMPN);
- regs_buff[1081] = IXGBE_READ_REG(hw, IXGBE_RIC_DW0);
- regs_buff[1082] = IXGBE_READ_REG(hw, IXGBE_RIC_DW1);
- regs_buff[1083] = IXGBE_READ_REG(hw, IXGBE_RIC_DW2);
- regs_buff[1084] = IXGBE_READ_REG(hw, IXGBE_RIC_DW3);
+ for (i = 0; i < 4; i++)
+ regs_buff[1081 + i] = IXGBE_READ_REG(hw, IXGBE_RIC_DW(i));
regs_buff[1085] = IXGBE_READ_REG(hw, IXGBE_RDPROBE);
regs_buff[1086] = IXGBE_READ_REG(hw, IXGBE_TDSTATCTL);
for (i = 0; i < 8; i++)
- regs_buff[1087] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i));
+ regs_buff[1087 + i] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i));
regs_buff[1095] = IXGBE_READ_REG(hw, IXGBE_TDHMPN);
- regs_buff[1096] = IXGBE_READ_REG(hw, IXGBE_TIC_DW0);
- regs_buff[1097] = IXGBE_READ_REG(hw, IXGBE_TIC_DW1);
- regs_buff[1098] = IXGBE_READ_REG(hw, IXGBE_TIC_DW2);
- regs_buff[1099] = IXGBE_READ_REG(hw, IXGBE_TIC_DW3);
+ for (i = 0; i < 4; i++)
+ regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i));
regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE);
regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL);
regs_buff[1102] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA0);
@@ -566,7 +564,7 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[1109] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA2);
regs_buff[1110] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA3);
for (i = 0; i < 8; i++)
- regs_buff[1111] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i));
+ regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i));
regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL);
regs_buff[1120] = IXGBE_READ_REG(hw, IXGBE_MDFTC1);
regs_buff[1121] = IXGBE_READ_REG(hw, IXGBE_MDFTC2);
@@ -585,7 +583,7 @@ static int ixgbe_get_eeprom_len(struct net_device *netdev)
}
static int ixgbe_get_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *eeprom, u8 *bytes)
+ struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
@@ -608,8 +606,8 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
return -ENOMEM;
for (i = 0; i < eeprom_len; i++) {
- if ((ret_val = ixgbe_read_eeprom(hw, first_word + i,
- &eeprom_buff[i])))
+ if ((ret_val = hw->eeprom.ops.read(hw, first_word + i,
+ &eeprom_buff[i])))
break;
}
@@ -624,7 +622,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
}
static void ixgbe_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+ struct ethtool_drvinfo *drvinfo)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -637,7 +635,7 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
}
static void ixgbe_get_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+ struct ethtool_ringparam *ring)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *tx_ring = adapter->tx_ring;
@@ -654,15 +652,12 @@ static void ixgbe_get_ringparam(struct net_device *netdev,
}
static int ixgbe_set_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+ struct ethtool_ringparam *ring)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_tx_buffer *old_buf;
- struct ixgbe_rx_buffer *old_rx_buf;
- void *old_desc;
+ struct ixgbe_ring *temp_ring;
int i, err;
- u32 new_rx_count, new_tx_count, old_size;
- dma_addr_t old_dma;
+ u32 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
@@ -681,6 +676,15 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
return 0;
}
+ if (adapter->num_tx_queues > adapter->num_rx_queues)
+ temp_ring = vmalloc(adapter->num_tx_queues *
+ sizeof(struct ixgbe_ring));
+ else
+ temp_ring = vmalloc(adapter->num_rx_queues *
+ sizeof(struct ixgbe_ring));
+ if (!temp_ring)
+ return -ENOMEM;
+
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
msleep(1);
@@ -693,66 +697,61 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
* to the tx and rx ring structs.
*/
if (new_tx_count != adapter->tx_ring->count) {
+ memcpy(temp_ring, adapter->tx_ring,
+ adapter->num_tx_queues * sizeof(struct ixgbe_ring));
+
for (i = 0; i < adapter->num_tx_queues; i++) {
- /* Save existing descriptor ring */
- old_buf = adapter->tx_ring[i].tx_buffer_info;
- old_desc = adapter->tx_ring[i].desc;
- old_size = adapter->tx_ring[i].size;
- old_dma = adapter->tx_ring[i].dma;
- /* Try to allocate a new one */
- adapter->tx_ring[i].tx_buffer_info = NULL;
- adapter->tx_ring[i].desc = NULL;
- adapter->tx_ring[i].count = new_tx_count;
- err = ixgbe_setup_tx_resources(adapter,
- &adapter->tx_ring[i]);
+ temp_ring[i].count = new_tx_count;
+ err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]);
if (err) {
- /* Restore the old one so at least
- the adapter still works, even if
- we failed the request */
- adapter->tx_ring[i].tx_buffer_info = old_buf;
- adapter->tx_ring[i].desc = old_desc;
- adapter->tx_ring[i].size = old_size;
- adapter->tx_ring[i].dma = old_dma;
+ while (i) {
+ i--;
+ ixgbe_free_tx_resources(adapter,
+ &temp_ring[i]);
+ }
goto err_setup;
}
- /* Free the old buffer manually */
- vfree(old_buf);
- pci_free_consistent(adapter->pdev, old_size,
- old_desc, old_dma);
}
+
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]);
+
+ memcpy(adapter->tx_ring, temp_ring,
+ adapter->num_tx_queues * sizeof(struct ixgbe_ring));
+
+ adapter->tx_ring_count = new_tx_count;
}
if (new_rx_count != adapter->rx_ring->count) {
- for (i = 0; i < adapter->num_rx_queues; i++) {
+ memcpy(temp_ring, adapter->rx_ring,
+ adapter->num_rx_queues * sizeof(struct ixgbe_ring));
- old_rx_buf = adapter->rx_ring[i].rx_buffer_info;
- old_desc = adapter->rx_ring[i].desc;
- old_size = adapter->rx_ring[i].size;
- old_dma = adapter->rx_ring[i].dma;
-
- adapter->rx_ring[i].rx_buffer_info = NULL;
- adapter->rx_ring[i].desc = NULL;
- adapter->rx_ring[i].dma = 0;
- adapter->rx_ring[i].count = new_rx_count;
- err = ixgbe_setup_rx_resources(adapter,
- &adapter->rx_ring[i]);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ temp_ring[i].count = new_rx_count;
+ err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);
if (err) {
- adapter->rx_ring[i].rx_buffer_info = old_rx_buf;
- adapter->rx_ring[i].desc = old_desc;
- adapter->rx_ring[i].size = old_size;
- adapter->rx_ring[i].dma = old_dma;
+ while (i) {
+ i--;
+ ixgbe_free_rx_resources(adapter,
+ &temp_ring[i]);
+ }
goto err_setup;
}
-
- vfree(old_rx_buf);
- pci_free_consistent(adapter->pdev, old_size, old_desc,
- old_dma);
}
+
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]);
+
+ memcpy(adapter->rx_ring, temp_ring,
+ adapter->num_rx_queues * sizeof(struct ixgbe_ring));
+
+ adapter->rx_ring_count = new_rx_count;
}
+ /* success! */
err = 0;
err_setup:
- if (netif_running(adapter->netdev))
+ if (netif_running(netdev))
ixgbe_up(adapter);
clear_bit(__IXGBE_RESETTING, &adapter->state);
@@ -770,7 +769,7 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
}
static void ixgbe_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, u64 *data)
+ struct ethtool_stats *stats, u64 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
u64 *queue_stat;
@@ -778,12 +777,20 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
int j, k;
int i;
u64 aggregated = 0, flushed = 0, no_desc = 0;
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated;
+ flushed += adapter->rx_ring[i].lro_mgr.stats.flushed;
+ no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc;
+ }
+ adapter->lro_aggregated = aggregated;
+ adapter->lro_flushed = flushed;
+ adapter->lro_no_desc = no_desc;
ixgbe_update_stats(adapter);
for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
char *p = (char *)adapter + ixgbe_gstrings_stats[i].stat_offset;
data[i] = (ixgbe_gstrings_stats[i].sizeof_stat ==
- sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
for (j = 0; j < adapter->num_tx_queues; j++) {
queue_stat = (u64 *)&adapter->tx_ring[j].stats;
@@ -792,24 +799,18 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
i += k;
}
for (j = 0; j < adapter->num_rx_queues; j++) {
- aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated;
- flushed += adapter->rx_ring[j].lro_mgr.stats.flushed;
- no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc;
queue_stat = (u64 *)&adapter->rx_ring[j].stats;
for (k = 0; k < stat_count; k++)
data[i + k] = queue_stat[k];
i += k;
}
- adapter->lro_aggregated = aggregated;
- adapter->lro_flushed = flushed;
- adapter->lro_no_desc = no_desc;
}
static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
- u8 *data)
+ u8 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- u8 *p = data;
+ char *p = (char *)data;
int i;
switch (stringset) {
@@ -831,14 +832,14 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
sprintf(p, "rx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
}
-/* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
+ /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
break;
}
}
static void ixgbe_get_wol(struct net_device *netdev,
- struct ethtool_wolinfo *wol)
+ struct ethtool_wolinfo *wol)
{
wol->supported = 0;
wol->wolopts = 0;
@@ -859,16 +860,17 @@ static int ixgbe_nway_reset(struct net_device *netdev)
static int ixgbe_phys_id(struct net_device *netdev, u32 data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- u32 led_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_LEDCTL);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
u32 i;
if (!data || data > 300)
data = 300;
for (i = 0; i < (data * 1000); i += 400) {
- ixgbe_led_on(&adapter->hw, IXGBE_LED_ON);
+ hw->mac.ops.led_on(hw, IXGBE_LED_ON);
msleep_interruptible(200);
- ixgbe_led_off(&adapter->hw, IXGBE_LED_ON);
+ hw->mac.ops.led_off(hw, IXGBE_LED_ON);
msleep_interruptible(200);
}
@@ -879,67 +881,75 @@ static int ixgbe_phys_id(struct net_device *netdev, u32 data)
}
static int ixgbe_get_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec)
+ struct ethtool_coalesce *ec)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
- ec->rx_coalesce_usecs = adapter->rx_eitr;
- else
- ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr;
-
- if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS)
- ec->tx_coalesce_usecs = adapter->tx_eitr;
- else
- ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr;
-
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
+
+ /* only valid if in constant ITR mode */
+ switch (adapter->itr_setting) {
+ case 0:
+ /* throttling disabled */
+ ec->rx_coalesce_usecs = 0;
+ break;
+ case 1:
+ /* dynamic ITR mode */
+ ec->rx_coalesce_usecs = 1;
+ break;
+ default:
+ /* fixed interrupt rate mode */
+ ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
+ break;
+ }
return 0;
}
static int ixgbe_set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec)
+ struct ethtool_coalesce *ec)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
-
- if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
- ((ec->rx_coalesce_usecs != 0) &&
- (ec->rx_coalesce_usecs != 1) &&
- (ec->rx_coalesce_usecs != 3) &&
- (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
- return -EINVAL;
- if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
- ((ec->tx_coalesce_usecs != 0) &&
- (ec->tx_coalesce_usecs != 1) &&
- (ec->tx_coalesce_usecs != 3) &&
- (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
- return -EINVAL;
-
- /* convert to rate of irq's per second */
- if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
- adapter->rx_eitr = ec->rx_coalesce_usecs;
- else
- adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
-
- if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
- adapter->tx_eitr = ec->rx_coalesce_usecs;
- else
- adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
+ struct ixgbe_hw *hw = &adapter->hw;
+ int i;
if (ec->tx_max_coalesced_frames_irq)
- adapter->tx_ring[0].work_limit =
- ec->tx_max_coalesced_frames_irq;
+ adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
+
+ if (ec->rx_coalesce_usecs > 1) {
+ /* store the value in ints/second */
+ adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
+
+ /* static value of interrupt rate */
+ adapter->itr_setting = adapter->eitr_param;
+ /* clear the lower bit */
+ adapter->itr_setting &= ~1;
+ } else if (ec->rx_coalesce_usecs == 1) {
+ /* 1 means dynamic mode */
+ adapter->eitr_param = 20000;
+ adapter->itr_setting = 1;
+ } else {
+ /* any other value means disable eitr, which is best
+ * served by setting the interrupt rate very high */
+ adapter->eitr_param = 3000000;
+ adapter->itr_setting = 0;
+ }
- if (netif_running(netdev)) {
- ixgbe_down(adapter);
- ixgbe_up(adapter);
+ for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
+ struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+ if (q_vector->txr_count && !q_vector->rxr_count)
+ q_vector->eitr = (adapter->eitr_param >> 1);
+ else
+ /* rx only or mixed */
+ q_vector->eitr = adapter->eitr_param;
+ IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
+ EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
}
return 0;
}
-static struct ethtool_ops ixgbe_ethtool_ops = {
+static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
.get_drvinfo = ixgbe_get_drvinfo,
@@ -966,7 +976,7 @@ static struct ethtool_ops ixgbe_ethtool_ops = {
.set_tso = ixgbe_set_tso,
.get_strings = ixgbe_get_strings,
.phys_id = ixgbe_phys_id,
- .get_sset_count = ixgbe_get_sset_count,
+ .get_sset_count = ixgbe_get_sset_count,
.get_ethtool_stats = ixgbe_get_ethtool_stats,
.get_coalesce = ixgbe_get_coalesce,
.set_coalesce = ixgbe_set_coalesce,
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 53f41b649f0..7548fb7360d 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -46,15 +45,14 @@
char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
- "Intel(R) 10 Gigabit PCI Express Network Driver";
+ "Intel(R) 10 Gigabit PCI Express Network Driver";
-#define DRV_VERSION "1.3.18-k4"
+#define DRV_VERSION "1.3.30-k2"
const char ixgbe_driver_version[] = DRV_VERSION;
-static const char ixgbe_copyright[] =
- "Copyright (c) 1999-2007 Intel Corporation.";
+static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation.";
static const struct ixgbe_info *ixgbe_info_tbl[] = {
- [board_82598] = &ixgbe_82598_info,
+ [board_82598] = &ixgbe_82598_info,
};
/* ixgbe_pci_tbl - PCI Device ID Table
@@ -74,15 +72,17 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR),
+ board_82598 },
/* required last entry */
{0, }
};
MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
- void *p);
+ void *p);
static struct notifier_block dca_notifier = {
.notifier_call = ixgbe_notify_dca,
.next = NULL,
@@ -104,7 +104,7 @@ static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
/* Let firmware take over control of h/w */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
- ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
+ ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
}
static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
@@ -114,24 +114,11 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
/* Let firmware know the driver has taken over */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
- ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
+ ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
}
-#ifdef DEBUG
-/**
- * ixgbe_get_hw_dev_name - return device name string
- * used by hardware layer to print debugging information
- **/
-char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw)
-{
- struct ixgbe_adapter *adapter = hw->back;
- struct net_device *netdev = adapter->netdev;
- return netdev->name;
-}
-#endif
-
static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry,
- u8 msix_vector)
+ u8 msix_vector)
{
u32 ivar, index;
@@ -144,13 +131,12 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry,
}
static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
- struct ixgbe_tx_buffer
- *tx_buffer_info)
+ struct ixgbe_tx_buffer
+ *tx_buffer_info)
{
if (tx_buffer_info->dma) {
- pci_unmap_page(adapter->pdev,
- tx_buffer_info->dma,
- tx_buffer_info->length, PCI_DMA_TODEVICE);
+ pci_unmap_page(adapter->pdev, tx_buffer_info->dma,
+ tx_buffer_info->length, PCI_DMA_TODEVICE);
tx_buffer_info->dma = 0;
}
if (tx_buffer_info->skb) {
@@ -161,107 +147,120 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
}
static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- unsigned int eop,
- union ixgbe_adv_tx_desc *eop_desc)
+ struct ixgbe_ring *tx_ring,
+ unsigned int eop)
{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 head, tail;
+
/* Detect a transmit hang in hardware, this serializes the
- * check with the clearing of time_stamp and movement of i */
+ * check with the clearing of time_stamp and movement of eop */
+ head = IXGBE_READ_REG(hw, tx_ring->head);
+ tail = IXGBE_READ_REG(hw, tx_ring->tail);
adapter->detect_tx_hung = false;
- if (tx_ring->tx_buffer_info[eop].dma &&
+ if ((head != tail) &&
+ tx_ring->tx_buffer_info[eop].time_stamp &&
time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) &&
!(IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)) {
/* detected Tx unit hang */
+ union ixgbe_adv_tx_desc *tx_desc;
+ tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
- " TDH <%x>\n"
- " TDT <%x>\n"
+ " Tx Queue <%d>\n"
+ " TDH, TDT <%x>, <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"tx_buffer_info[next_to_clean]\n"
" time_stamp <%lx>\n"
- " next_to_watch <%x>\n"
- " jiffies <%lx>\n"
- " next_to_watch.status <%x>\n",
- readl(adapter->hw.hw_addr + tx_ring->head),
- readl(adapter->hw.hw_addr + tx_ring->tail),
- tx_ring->next_to_use,
- tx_ring->next_to_clean,
- tx_ring->tx_buffer_info[eop].time_stamp,
- eop, jiffies, eop_desc->wb.status);
+ " jiffies <%lx>\n",
+ tx_ring->queue_index,
+ head, tail,
+ tx_ring->next_to_use, eop,
+ tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
return true;
}
return false;
}
-#define IXGBE_MAX_TXD_PWR 14
-#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
+#define IXGBE_MAX_TXD_PWR 14
+#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
(((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
- MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
+ MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
+
+#define GET_TX_HEAD_FROM_RING(ring) (\
+ *(volatile u32 *) \
+ ((union ixgbe_adv_tx_desc *)(ring)->desc + (ring)->count))
+static void ixgbe_tx_timeout(struct net_device *netdev);
/**
* ixgbe_clean_tx_irq - Reclaim resources after transmit completes
* @adapter: board private structure
+ * @tx_ring: tx ring to clean
**/
static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
- struct net_device *netdev = adapter->netdev;
- union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
+ union ixgbe_adv_tx_desc *tx_desc;
struct ixgbe_tx_buffer *tx_buffer_info;
- unsigned int i, eop;
- bool cleaned = false;
- unsigned int total_tx_bytes = 0, total_tx_packets = 0;
+ struct net_device *netdev = adapter->netdev;
+ struct sk_buff *skb;
+ unsigned int i;
+ u32 head, oldhead;
+ unsigned int count = 0;
+ unsigned int total_bytes = 0, total_packets = 0;
+ rmb();
+ head = GET_TX_HEAD_FROM_RING(tx_ring);
+ head = le32_to_cpu(head);
i = tx_ring->next_to_clean;
- eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
- while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) {
- cleaned = false;
- while (!cleaned) {
+ while (1) {
+ while (i != head) {
tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
tx_buffer_info = &tx_ring->tx_buffer_info[i];
- cleaned = (i == eop);
+ skb = tx_buffer_info->skb;
- tx_ring->stats.bytes += tx_buffer_info->length;
- if (cleaned) {
- struct sk_buff *skb = tx_buffer_info->skb;
+ if (skb) {
unsigned int segs, bytecount;
+
+ /* gso_segs is currently only valid for tcp */
segs = skb_shinfo(skb)->gso_segs ?: 1;
/* multiply data chunks by size of headers */
bytecount = ((segs - 1) * skb_headlen(skb)) +
- skb->len;
- total_tx_packets += segs;
- total_tx_bytes += bytecount;
+ skb->len;
+ total_packets += segs;
+ total_bytes += bytecount;
}
+
ixgbe_unmap_and_free_tx_resource(adapter,
- tx_buffer_info);
- tx_desc->wb.status = 0;
+ tx_buffer_info);
i++;
if (i == tx_ring->count)
i = 0;
- }
-
- tx_ring->stats.packets++;
-
- eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
-
- /* weight of a sort for tx, avoid endless transmit cleanup */
- if (total_tx_packets >= tx_ring->work_limit)
- break;
- }
+ count++;
+ if (count == tx_ring->count)
+ goto done_cleaning;
+ }
+ oldhead = head;
+ rmb();
+ head = GET_TX_HEAD_FROM_RING(tx_ring);
+ head = le32_to_cpu(head);
+ if (head == oldhead)
+ goto done_cleaning;
+ } /* while (1) */
+
+done_cleaning:
tx_ring->next_to_clean = i;
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
- if (total_tx_packets && netif_carrier_ok(netdev) &&
- (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
+ if (unlikely(count && netif_carrier_ok(netdev) &&
+ (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
*/
@@ -269,59 +268,68 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
!test_bit(__IXGBE_DOWN, &adapter->state)) {
netif_wake_subqueue(netdev, tx_ring->queue_index);
- adapter->restart_queue++;
+ ++adapter->restart_queue;
}
}
- if (adapter->detect_tx_hung)
- if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
- netif_stop_subqueue(netdev, tx_ring->queue_index);
-
- if (total_tx_packets >= tx_ring->work_limit)
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
+ if (adapter->detect_tx_hung) {
+ if (ixgbe_check_tx_hang(adapter, tx_ring, i)) {
+ /* schedule immediate reset if we believe we hung */
+ DPRINTK(PROBE, INFO,
+ "tx hang %d detected, resetting adapter\n",
+ adapter->tx_timeout_count + 1);
+ ixgbe_tx_timeout(adapter->netdev);
+ }
+ }
- tx_ring->total_bytes += total_tx_bytes;
- tx_ring->total_packets += total_tx_packets;
- adapter->net_stats.tx_bytes += total_tx_bytes;
- adapter->net_stats.tx_packets += total_tx_packets;
- cleaned = total_tx_packets ? true : false;
- return cleaned;
+ /* re-arm the interrupt */
+ if ((total_packets >= tx_ring->work_limit) ||
+ (count == tx_ring->count))
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx);
+
+ tx_ring->total_bytes += total_bytes;
+ tx_ring->total_packets += total_packets;
+ tx_ring->stats.bytes += total_bytes;
+ tx_ring->stats.packets += total_packets;
+ adapter->net_stats.tx_bytes += total_bytes;
+ adapter->net_stats.tx_packets += total_packets;
+ return (total_packets ? true : false);
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rxr)
+ struct ixgbe_ring *rx_ring)
{
u32 rxctrl;
int cpu = get_cpu();
- int q = rxr - adapter->rx_ring;
+ int q = rx_ring - adapter->rx_ring;
- if (rxr->cpu != cpu) {
+ if (rx_ring->cpu != cpu) {
rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
- rxctrl |= dca_get_tag(cpu);
+ rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
- rxr->cpu = cpu;
+ rx_ring->cpu = cpu;
}
put_cpu();
}
static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *txr)
+ struct ixgbe_ring *tx_ring)
{
u32 txctrl;
int cpu = get_cpu();
- int q = txr - adapter->tx_ring;
+ int q = tx_ring - adapter->tx_ring;
- if (txr->cpu != cpu) {
+ if (tx_ring->cpu != cpu) {
txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
- txctrl |= dca_get_tag(cpu);
+ txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl);
- txr->cpu = cpu;
+ tx_ring->cpu = cpu;
}
put_cpu();
}
@@ -351,11 +359,14 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
switch (event) {
case DCA_PROVIDER_ADD:
- adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
+ /* if we're already enabled, don't do it again */
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+ break;
/* Always use CB2 mode, difference is masked
* in the CB driver. */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
if (dca_add_requester(dev) == 0) {
+ adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
ixgbe_setup_dca(adapter);
break;
}
@@ -372,7 +383,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
return 0;
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_IXGBE_DCA */
/**
* ixgbe_receive_skb - Send a completed packet up the stack
* @adapter: board private structure
@@ -382,8 +393,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
* @rx_desc: rx descriptor
**/
static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
- struct sk_buff *skb, u8 status,
- struct ixgbe_ring *ring,
+ struct sk_buff *skb, u8 status,
+ struct ixgbe_ring *ring,
union ixgbe_adv_rx_desc *rx_desc)
{
bool is_vlan = (status & IXGBE_RXD_STAT_VP);
@@ -420,14 +431,12 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
* @skb: skb currently being received and modified
**/
static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
- u32 status_err,
- struct sk_buff *skb)
+ u32 status_err, struct sk_buff *skb)
{
skb->ip_summed = CHECKSUM_NONE;
- /* Ignore Checksum bit is set, or rx csum disabled */
- if ((status_err & IXGBE_RXD_STAT_IXSM) ||
- !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
+ /* Rx csum disabled */
+ if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
return;
/* if IP and error */
@@ -455,37 +464,44 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
* @adapter: address of board private structure
**/
static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring,
- int cleaned_count)
+ struct ixgbe_ring *rx_ring,
+ int cleaned_count)
{
- struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union ixgbe_adv_rx_desc *rx_desc;
- struct ixgbe_rx_buffer *rx_buffer_info;
- struct sk_buff *skb;
+ struct ixgbe_rx_buffer *bi;
unsigned int i;
- unsigned int bufsz = adapter->rx_buf_len + NET_IP_ALIGN;
+ unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN;
i = rx_ring->next_to_use;
- rx_buffer_info = &rx_ring->rx_buffer_info[i];
+ bi = &rx_ring->rx_buffer_info[i];
while (cleaned_count--) {
rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
- if (!rx_buffer_info->page &&
- (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) {
- rx_buffer_info->page = alloc_page(GFP_ATOMIC);
- if (!rx_buffer_info->page) {
- adapter->alloc_rx_page_failed++;
- goto no_buffers;
+ if (!bi->page_dma &&
+ (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) {
+ if (!bi->page) {
+ bi->page = alloc_page(GFP_ATOMIC);
+ if (!bi->page) {
+ adapter->alloc_rx_page_failed++;
+ goto no_buffers;
+ }
+ bi->page_offset = 0;
+ } else {
+ /* use a half page if we're re-using */
+ bi->page_offset ^= (PAGE_SIZE / 2);
}
- rx_buffer_info->page_dma =
- pci_map_page(pdev, rx_buffer_info->page,
- 0, PAGE_SIZE, PCI_DMA_FROMDEVICE);
+
+ bi->page_dma = pci_map_page(pdev, bi->page,
+ bi->page_offset,
+ (PAGE_SIZE / 2),
+ PCI_DMA_FROMDEVICE);
}
- if (!rx_buffer_info->skb) {
- skb = netdev_alloc_skb(netdev, bufsz);
+ if (!bi->skb) {
+ struct sk_buff *skb = netdev_alloc_skb(adapter->netdev,
+ bufsz);
if (!skb) {
adapter->alloc_rx_buff_failed++;
@@ -499,28 +515,25 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
*/
skb_reserve(skb, NET_IP_ALIGN);
- rx_buffer_info->skb = skb;
- rx_buffer_info->dma = pci_map_single(pdev, skb->data,
- bufsz,
- PCI_DMA_FROMDEVICE);
+ bi->skb = skb;
+ bi->dma = pci_map_single(pdev, skb->data, bufsz,
+ PCI_DMA_FROMDEVICE);
}
/* Refresh the desc even if buffer_addrs didn't change because
* each write-back erases this info. */
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- rx_desc->read.pkt_addr =
- cpu_to_le64(rx_buffer_info->page_dma);
- rx_desc->read.hdr_addr =
- cpu_to_le64(rx_buffer_info->dma);
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+ rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
} else {
- rx_desc->read.pkt_addr =
- cpu_to_le64(rx_buffer_info->dma);
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
}
i++;
if (i == rx_ring->count)
i = 0;
- rx_buffer_info = &rx_ring->rx_buffer_info[i];
+ bi = &rx_ring->rx_buffer_info[i];
}
+
no_buffers:
if (rx_ring->next_to_use != i) {
rx_ring->next_to_use = i;
@@ -538,46 +551,54 @@ no_buffers:
}
}
+static inline u16 ixgbe_get_hdr_info(union ixgbe_adv_rx_desc *rx_desc)
+{
+ return rx_desc->wb.lower.lo_dword.hs_rss.hdr_info;
+}
+
+static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc)
+{
+ return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+}
+
static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring,
- int *work_done, int work_to_do)
+ struct ixgbe_ring *rx_ring,
+ int *work_done, int work_to_do)
{
- struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
struct sk_buff *skb;
unsigned int i;
- u32 upper_len, len, staterr;
+ u32 len, staterr;
u16 hdr_info;
bool cleaned = false;
int cleaned_count = 0;
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
i = rx_ring->next_to_clean;
- upper_len = 0;
rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
rx_buffer_info = &rx_ring->rx_buffer_info[i];
while (staterr & IXGBE_RXD_STAT_DD) {
+ u32 upper_len = 0;
if (*work_done >= work_to_do)
break;
(*work_done)++;
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- hdr_info =
- le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info);
- len =
- ((hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
- IXGBE_RXDADV_HDRBUFLEN_SHIFT);
+ hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
+ len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
+ IXGBE_RXDADV_HDRBUFLEN_SHIFT;
if (hdr_info & IXGBE_RXDADV_SPH)
adapter->rx_hdr_split++;
if (len > IXGBE_RX_HDR_SIZE)
len = IXGBE_RX_HDR_SIZE;
upper_len = le16_to_cpu(rx_desc->wb.upper.length);
- } else
+ } else {
len = le16_to_cpu(rx_desc->wb.upper.length);
+ }
cleaned = true;
skb = rx_buffer_info->skb;
@@ -586,18 +607,25 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
if (len && !skb_shinfo(skb)->nr_frags) {
pci_unmap_single(pdev, rx_buffer_info->dma,
- adapter->rx_buf_len + NET_IP_ALIGN,
- PCI_DMA_FROMDEVICE);
+ rx_ring->rx_buf_len + NET_IP_ALIGN,
+ PCI_DMA_FROMDEVICE);
skb_put(skb, len);
}
if (upper_len) {
pci_unmap_page(pdev, rx_buffer_info->page_dma,
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
rx_buffer_info->page_dma = 0;
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
- rx_buffer_info->page, 0, upper_len);
- rx_buffer_info->page = NULL;
+ rx_buffer_info->page,
+ rx_buffer_info->page_offset,
+ upper_len);
+
+ if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
+ (page_count(rx_buffer_info->page) != 1))
+ rx_buffer_info->page = NULL;
+ else
+ get_page(rx_buffer_info->page);
skb->len += upper_len;
skb->data_len += upper_len;
@@ -620,6 +648,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
rx_buffer_info->skb = next_buffer->skb;
rx_buffer_info->dma = next_buffer->dma;
next_buffer->skb = skb;
+ next_buffer->dma = 0;
adapter->non_eop_descs++;
goto next_desc;
}
@@ -635,9 +664,9 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
total_rx_bytes += skb->len;
total_rx_packets++;
- skb->protocol = eth_type_trans(skb, netdev);
+ skb->protocol = eth_type_trans(skb, adapter->netdev);
ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
- netdev->last_rx = jiffies;
+ adapter->netdev->last_rx = jiffies;
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -666,9 +695,6 @@ next_desc:
if (cleaned_count)
ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
- adapter->net_stats.rx_bytes += total_rx_bytes;
- adapter->net_stats.rx_packets += total_rx_packets;
-
rx_ring->total_packets += total_rx_packets;
rx_ring->total_bytes += total_rx_bytes;
adapter->net_stats.rx_bytes += total_rx_bytes;
@@ -700,43 +726,43 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vector = &adapter->q_vector[v_idx];
/* XXX for_each_bit(...) */
r_idx = find_first_bit(q_vector->rxr_idx,
- adapter->num_rx_queues);
+ adapter->num_rx_queues);
for (i = 0; i < q_vector->rxr_count; i++) {
j = adapter->rx_ring[r_idx].reg_idx;
ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(j), v_idx);
r_idx = find_next_bit(q_vector->rxr_idx,
- adapter->num_rx_queues,
- r_idx + 1);
+ adapter->num_rx_queues,
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->txr_idx,
- adapter->num_tx_queues);
+ adapter->num_tx_queues);
for (i = 0; i < q_vector->txr_count; i++) {
j = adapter->tx_ring[r_idx].reg_idx;
ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(j), v_idx);
r_idx = find_next_bit(q_vector->txr_idx,
- adapter->num_tx_queues,
- r_idx + 1);
+ adapter->num_tx_queues,
+ r_idx + 1);
}
- /* if this is a tx only vector use half the irq (tx) rate */
+ /* if this is a tx only vector halve the interrupt rate */
if (q_vector->txr_count && !q_vector->rxr_count)
- q_vector->eitr = adapter->tx_eitr;
+ q_vector->eitr = (adapter->eitr_param >> 1);
else
- /* rx only or mixed */
- q_vector->eitr = adapter->rx_eitr;
+ /* rx only */
+ q_vector->eitr = adapter->eitr_param;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
- EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
+ EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
}
ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
- /* set up to autoclear timer, lsc, and the vectors */
+ /* set up to autoclear timer, and the vectors */
mask = IXGBE_EIMS_ENABLE_MASK;
- mask &= ~IXGBE_EIMS_OTHER;
+ mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
}
@@ -766,8 +792,8 @@ enum latency_range {
* parameter (see ixgbe_param.c)
**/
static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
- u32 eitr, u8 itr_setting,
- int packets, int bytes)
+ u32 eitr, u8 itr_setting,
+ int packets, int bytes)
{
unsigned int retval = itr_setting;
u32 timepassed_us;
@@ -814,40 +840,40 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
u32 new_itr;
u8 current_itr, ret_itr;
int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
- sizeof(struct ixgbe_q_vector);
+ sizeof(struct ixgbe_q_vector);
struct ixgbe_ring *rx_ring, *tx_ring;
r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
for (i = 0; i < q_vector->txr_count; i++) {
tx_ring = &(adapter->tx_ring[r_idx]);
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->tx_eitr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
+ q_vector->tx_itr,
+ tx_ring->total_packets,
+ tx_ring->total_bytes);
/* if the result for this queue would decrease interrupt
* rate for this vector then use that result */
- q_vector->tx_eitr = ((q_vector->tx_eitr > ret_itr) ?
- q_vector->tx_eitr - 1 : ret_itr);
+ q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
+ q_vector->tx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
for (i = 0; i < q_vector->rxr_count; i++) {
rx_ring = &(adapter->rx_ring[r_idx]);
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->rx_eitr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
+ q_vector->rx_itr,
+ rx_ring->total_packets,
+ rx_ring->total_bytes);
/* if the result for this queue would decrease interrupt
* rate for this vector then use that result */
- q_vector->rx_eitr = ((q_vector->rx_eitr > ret_itr) ?
- q_vector->rx_eitr - 1 : ret_itr);
+ q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
+ q_vector->rx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
+ r_idx + 1);
}
- current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
+ current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
@@ -871,13 +897,27 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
/* must write high and low 16 bits to reset counter */
DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx,
- itr_reg);
+ itr_reg);
IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16);
}
return;
}
+
+static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ adapter->lsc_int++;
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
+ adapter->link_check_timeout = jiffies;
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
+ schedule_work(&adapter->watchdog_task);
+ }
+}
+
static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
{
struct net_device *netdev = data;
@@ -885,11 +925,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
- if (eicr & IXGBE_EICR_LSC) {
- adapter->lsc_int++;
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer, jiffies);
- }
+ if (eicr & IXGBE_EICR_LSC)
+ ixgbe_check_lsc(adapter);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
@@ -901,7 +938,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
{
struct ixgbe_q_vector *q_vector = data;
struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *txr;
+ struct ixgbe_ring *tx_ring;
int i, r_idx;
if (!q_vector->txr_count)
@@ -909,16 +946,16 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
for (i = 0; i < q_vector->txr_count; i++) {
- txr = &(adapter->tx_ring[r_idx]);
-#ifdef CONFIG_DCA
+ tx_ring = &(adapter->tx_ring[r_idx]);
+#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_tx_dca(adapter, txr);
+ ixgbe_update_tx_dca(adapter, tx_ring);
#endif
- txr->total_bytes = 0;
- txr->total_packets = 0;
- ixgbe_clean_tx_irq(adapter, txr);
+ tx_ring->total_bytes = 0;
+ tx_ring->total_packets = 0;
+ ixgbe_clean_tx_irq(adapter, tx_ring);
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
return IRQ_HANDLED;
@@ -933,18 +970,26 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
{
struct ixgbe_q_vector *q_vector = data;
struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *rxr;
+ struct ixgbe_ring *rx_ring;
int r_idx;
+ int i;
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ for (i = 0; i < q_vector->rxr_count; i++) {
+ rx_ring = &(adapter->rx_ring[r_idx]);
+ rx_ring->total_bytes = 0;
+ rx_ring->total_packets = 0;
+ r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+ r_idx + 1);
+ }
+
if (!q_vector->rxr_count)
return IRQ_HANDLED;
- rxr = &(adapter->rx_ring[r_idx]);
+ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ rx_ring = &(adapter->rx_ring[r_idx]);
/* disable interrupts on this vector only */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->v_idx);
- rxr->total_bytes = 0;
- rxr->total_packets = 0;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx);
netif_rx_schedule(adapter->netdev, &q_vector->napi);
return IRQ_HANDLED;
@@ -963,39 +1008,90 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
* @napi: napi struct with our devices info in it
* @budget: amount of work driver is allowed to do this pass, in packets
*
+ * This function is optimized for cleaning one queue only on a single
+ * q_vector!!!
**/
static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
+ container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *rxr;
+ struct ixgbe_ring *rx_ring = NULL;
int work_done = 0;
long r_idx;
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
- rxr = &(adapter->rx_ring[r_idx]);
-#ifdef CONFIG_DCA
+ rx_ring = &(adapter->rx_ring[r_idx]);
+#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_rx_dca(adapter, rxr);
+ ixgbe_update_rx_dca(adapter, rx_ring);
#endif
- ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
+ ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget);
/* If all Rx work done, exit the polling mode */
if (work_done < budget) {
netif_rx_complete(adapter->netdev, napi);
- if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
+ if (adapter->itr_setting & 3)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->v_idx);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx);
}
return work_done;
}
+/**
+ * ixgbe_clean_rxonly_many - msix (aka one shot) rx clean routine
+ * @napi: napi struct with our devices info in it
+ * @budget: amount of work driver is allowed to do this pass, in packets
+ *
+ * This function will clean more than one rx queue associated with a
+ * q_vector.
+ **/
+static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
+{
+ struct ixgbe_q_vector *q_vector =
+ container_of(napi, struct ixgbe_q_vector, napi);
+ struct ixgbe_adapter *adapter = q_vector->adapter;
+ struct ixgbe_ring *rx_ring = NULL;
+ int work_done = 0, i;
+ long r_idx;
+ u16 enable_mask = 0;
+
+ /* attempt to distribute budget to each queue fairly, but don't allow
+ * the budget to go below 1 because we'll exit polling */
+ budget /= (q_vector->rxr_count ?: 1);
+ budget = max(budget, 1);
+ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ for (i = 0; i < q_vector->rxr_count; i++) {
+ rx_ring = &(adapter->rx_ring[r_idx]);
+#ifdef CONFIG_IXGBE_DCA
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+ ixgbe_update_rx_dca(adapter, rx_ring);
+#endif
+ ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget);
+ enable_mask |= rx_ring->v_idx;
+ r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+ r_idx + 1);
+ }
+
+ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+ rx_ring = &(adapter->rx_ring[r_idx]);
+ /* If all Rx work done, exit the polling mode */
+ if (work_done < budget) {
+ netif_rx_complete(adapter->netdev, napi);
+ if (adapter->itr_setting & 3)
+ ixgbe_set_itr_msix(q_vector);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask);
+ return 0;
+ }
+
+ return work_done;
+}
static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
- int r_idx)
+ int r_idx)
{
a->q_vector[v_idx].adapter = a;
set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
@@ -1004,7 +1100,7 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
}
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
- int r_idx)
+ int r_idx)
{
a->q_vector[v_idx].adapter = a;
set_bit(r_idx, a->q_vector[v_idx].txr_idx);
@@ -1024,7 +1120,7 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
* mapping configurations in here.
**/
static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
- int vectors)
+ int vectors)
{
int v_start = 0;
int rxr_idx = 0, txr_idx = 0;
@@ -1101,28 +1197,28 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
goto out;
#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
- (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
- &ixgbe_msix_clean_many)
+ (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
+ &ixgbe_msix_clean_many)
for (vector = 0; vector < q_vectors; vector++) {
handler = SET_HANDLER(&adapter->q_vector[vector]);
sprintf(adapter->name[vector], "%s:v%d-%s",
- netdev->name, vector,
- (handler == &ixgbe_msix_clean_rx) ? "Rx" :
- ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
+ netdev->name, vector,
+ (handler == &ixgbe_msix_clean_rx) ? "Rx" :
+ ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
err = request_irq(adapter->msix_entries[vector].vector,
- handler, 0, adapter->name[vector],
- &(adapter->q_vector[vector]));
+ handler, 0, adapter->name[vector],
+ &(adapter->q_vector[vector]));
if (err) {
DPRINTK(PROBE, ERR,
- "request_irq failed for MSIX interrupt "
- "Error: %d\n", err);
+ "request_irq failed for MSIX interrupt "
+ "Error: %d\n", err);
goto free_queue_irqs;
}
}
sprintf(adapter->name[vector], "%s:lsc", netdev->name);
err = request_irq(adapter->msix_entries[vector].vector,
- &ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+ &ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
if (err) {
DPRINTK(PROBE, ERR,
"request_irq for msix_lsc failed: %d\n", err);
@@ -1134,7 +1230,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
free_queue_irqs:
for (i = vector - 1; i >= 0; i--)
free_irq(adapter->msix_entries[--vector].vector,
- &(adapter->q_vector[i]));
+ &(adapter->q_vector[i]));
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
@@ -1152,16 +1248,16 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
- q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr,
- q_vector->tx_eitr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
- q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr,
- q_vector->rx_eitr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
+ q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
+ q_vector->tx_itr,
+ tx_ring->total_packets,
+ tx_ring->total_bytes);
+ q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
+ q_vector->rx_itr,
+ rx_ring->total_packets,
+ rx_ring->total_bytes);
- current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
+ current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
@@ -1206,19 +1302,19 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
-
/* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read
* therefore no explict interrupt disable is necessary */
eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
- if (!eicr)
+ if (!eicr) {
+ /* shared interrupt alert!
+ * make sure interrupts are enabled because the read will
+ * have disabled interrupts due to EIAM */
+ ixgbe_irq_enable(adapter);
return IRQ_NONE; /* Not our interrupt */
-
- if (eicr & IXGBE_EICR_LSC) {
- adapter->lsc_int++;
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- mod_timer(&adapter->watchdog_timer, jiffies);
}
+ if (eicr & IXGBE_EICR_LSC)
+ ixgbe_check_lsc(adapter);
if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
adapter->tx_ring[0].total_packets = 0;
@@ -1261,10 +1357,10 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
err = request_irq(adapter->pdev->irq, &ixgbe_intr, 0,
- netdev->name, netdev);
+ netdev->name, netdev);
} else {
err = request_irq(adapter->pdev->irq, &ixgbe_intr, IRQF_SHARED,
- netdev->name, netdev);
+ netdev->name, netdev);
}
if (err)
@@ -1288,7 +1384,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
i--;
for (; i >= 0; i--) {
free_irq(adapter->msix_entries[i].vector,
- &(adapter->q_vector[i]));
+ &(adapter->q_vector[i]));
}
ixgbe_reset_q_vectors(adapter);
@@ -1335,7 +1431,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
- EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
+ EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);
ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0);
@@ -1347,26 +1443,31 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_configure_tx - Configure 8254x Transmit Unit after Reset
+ * ixgbe_configure_tx - Configure 8259x Transmit Unit after Reset
* @adapter: board private structure
*
* Configure the Tx unit of the MAC after a reset.
**/
static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
{
- u64 tdba;
+ u64 tdba, tdwba;
struct ixgbe_hw *hw = &adapter->hw;
u32 i, j, tdlen, txctrl;
/* Setup the HW Tx Head and Tail descriptor pointers */
for (i = 0; i < adapter->num_tx_queues; i++) {
- j = adapter->tx_ring[i].reg_idx;
- tdba = adapter->tx_ring[i].dma;
- tdlen = adapter->tx_ring[i].count *
- sizeof(union ixgbe_adv_tx_desc);
+ struct ixgbe_ring *ring = &adapter->tx_ring[i];
+ j = ring->reg_idx;
+ tdba = ring->dma;
+ tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc);
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
- (tdba & DMA_32BIT_MASK));
+ (tdba & DMA_32BIT_MASK));
IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
+ tdwba = ring->dma +
+ (ring->count * sizeof(union ixgbe_adv_tx_desc));
+ tdwba |= IXGBE_TDWBAL_HEAD_WB_ENABLE;
+ IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(j), tdwba & DMA_32BIT_MASK);
+ IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(j), (tdwba >> 32));
IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
@@ -1375,20 +1476,66 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
/* Disable Tx Head Writeback RO bit, since this hoses
* bookkeeping if things aren't delivered in order.
*/
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
}
}
-#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
- (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
+#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
+
+static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
+{
+ struct ixgbe_ring *rx_ring;
+ u32 srrctl;
+ int queue0;
+ unsigned long mask;
+
+ /* program one srrctl register per VMDq index */
+ if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) {
+ long shift, len;
+ mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask;
+ len = sizeof(adapter->ring_feature[RING_F_VMDQ].mask) * 8;
+ shift = find_first_bit(&mask, len);
+ queue0 = index & mask;
+ index = (index & mask) >> shift;
+ /* program one srrctl per RSS queue since RDRXCTL.MVMEN is enabled */
+ } else {
+ mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask;
+ queue0 = index & mask;
+ index = index & mask;
+ }
+
+ rx_ring = &adapter->rx_ring[queue0];
+
+ srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index));
+
+ srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
+ srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+
+ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ srrctl |= IXGBE_RXBUFFER_2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ srrctl |= ((IXGBE_RX_HDR_SIZE <<
+ IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+ IXGBE_SRRCTL_BSIZEHDR_MASK);
+ } else {
+ srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
+
+ if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE)
+ srrctl |= IXGBE_RXBUFFER_2048 >>
+ IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+ else
+ srrctl |= rx_ring->rx_buf_len >>
+ IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+ }
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
+}
-#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
/**
* ixgbe_get_skb_hdr - helper function for LRO header processing
* @skb: pointer to sk_buff to be added to LRO packet
- * @iphdr: pointer to tcp header structure
+ * @iphdr: pointer to ip header structure
* @tcph: pointer to tcp header structure
* @hdr_flags: pointer to header flags
* @priv: private data
@@ -1399,8 +1546,8 @@ static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
union ixgbe_adv_rx_desc *rx_desc = priv;
/* Verify that this is a valid IPv4 TCP packet */
- if (!(rx_desc->wb.lower.lo_dword.pkt_info &
- (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)))
+ if (!((ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_IPV4) &&
+ (ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_TCP)))
return -1;
/* Set network headers */
@@ -1412,8 +1559,11 @@ static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
return 0;
}
+#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+ (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
+
/**
- * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset
+ * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
* @adapter: board private structure
*
* Configure the Rx unit of the MAC after a reset.
@@ -1426,25 +1576,26 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
int i, j;
u32 rdlen, rxctrl, rxcsum;
- u32 random[10];
+ static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
+ 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
+ 0x6A3E67EA, 0x14364D17, 0x3BED200D};
u32 fctrl, hlreg0;
u32 pages;
- u32 reta = 0, mrqc, srrctl;
+ u32 reta = 0, mrqc;
+ u32 rdrxctl;
+ int rx_buf_len;
/* Decide whether to use packet split mode or not */
- if (netdev->mtu > ETH_DATA_LEN)
- adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
- else
- adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
+ adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
/* Set the RX buffer length according to the mode */
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- adapter->rx_buf_len = IXGBE_RX_HDR_SIZE;
+ rx_buf_len = IXGBE_RX_HDR_SIZE;
} else {
if (netdev->mtu <= ETH_DATA_LEN)
- adapter->rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
else
- adapter->rx_buf_len = ALIGN(max_frame, 1024);
+ rx_buf_len = ALIGN(max_frame, 1024);
}
fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
@@ -1461,28 +1612,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(0));
- srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
- srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
-
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- srrctl |= PAGE_SIZE >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
- srrctl |= ((IXGBE_RX_HDR_SIZE <<
- IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
- IXGBE_SRRCTL_BSIZEHDR_MASK);
- } else {
- srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
-
- if (adapter->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE)
- srrctl |=
- IXGBE_RXBUFFER_2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- else
- srrctl |=
- adapter->rx_buf_len >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- }
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(0), srrctl);
-
rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc);
/* disable receives while setting up the descriptors */
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
@@ -1492,25 +1621,43 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
* the Base and Length of the Rx Descriptor Ring */
for (i = 0; i < adapter->num_rx_queues; i++) {
rdba = adapter->rx_ring[i].dma;
- IXGBE_WRITE_REG(hw, IXGBE_RDBAL(i), (rdba & DMA_32BIT_MASK));
- IXGBE_WRITE_REG(hw, IXGBE_RDBAH(i), (rdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_RDLEN(i), rdlen);
- IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0);
- adapter->rx_ring[i].head = IXGBE_RDH(i);
- adapter->rx_ring[i].tail = IXGBE_RDT(i);
- }
-
- /* Intitial LRO Settings */
- adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
- adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
- adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
- adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
- if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
- adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
- adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
- adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
- adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+ j = adapter->rx_ring[i].reg_idx;
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_32BIT_MASK));
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
+ IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
+ adapter->rx_ring[i].head = IXGBE_RDH(j);
+ adapter->rx_ring[i].tail = IXGBE_RDT(j);
+ adapter->rx_ring[i].rx_buf_len = rx_buf_len;
+ /* Intitial LRO Settings */
+ adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
+ adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
+ adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
+ adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+ adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
+ adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
+ adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
+ adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+
+ ixgbe_configure_srrctl(adapter, j);
+ }
+
+ /*
+ * For VMDq support of different descriptor types or
+ * buffer sizes through the use of multiple SRRCTL
+ * registers, RDRXCTL.MVMEN must be set to 1
+ *
+ * also, the manual doesn't mention it clearly but DCA hints
+ * will only use queue 0's tags unless this bit is set. Side
+ * effects of setting this bit are only that SRRCTL must be
+ * fully programmed [0..15]
+ */
+ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ rdrxctl |= IXGBE_RDRXCTL_MVMEN;
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
/* Fill out redirection table */
@@ -1525,22 +1672,20 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
}
/* Fill out hash function seeds */
- /* XXX use a random constant here to glue certain flows */
- get_random_bytes(&random[0], 40);
for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random[i]);
+ IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
mrqc = IXGBE_MRQC_RSSEN
/* Perform hash on these packet types */
- | IXGBE_MRQC_RSS_FIELD_IPV4
- | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV4_UDP
- | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV6_EX
- | IXGBE_MRQC_RSS_FIELD_IPV6
- | IXGBE_MRQC_RSS_FIELD_IPV6_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
- | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
+ | IXGBE_MRQC_RSS_FIELD_IPV4
+ | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
+ | IXGBE_MRQC_RSS_FIELD_IPV4_UDP
+ | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP
+ | IXGBE_MRQC_RSS_FIELD_IPV6_EX
+ | IXGBE_MRQC_RSS_FIELD_IPV6
+ | IXGBE_MRQC_RSS_FIELD_IPV6_TCP
+ | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
+ | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
@@ -1562,7 +1707,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
}
static void ixgbe_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+ struct vlan_group *grp)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
u32 ctrl;
@@ -1586,14 +1731,16 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
/* add VID to filter table */
- ixgbe_set_vfta(&adapter->hw, vid, 0, true);
+ hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true);
}
static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_disable(adapter);
@@ -1604,7 +1751,7 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
ixgbe_irq_enable(adapter);
/* remove VID from filter table */
- ixgbe_set_vfta(&adapter->hw, vid, 0, false);
+ hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false);
}
static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
@@ -1621,23 +1768,37 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
}
}
+static u8 *ixgbe_addr_list_itr(struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq)
+{
+ struct dev_mc_list *mc_ptr;
+ u8 *addr = *mc_addr_ptr;
+ *vmdq = 0;
+
+ mc_ptr = container_of(addr, struct dev_mc_list, dmi_addr[0]);
+ if (mc_ptr->next)
+ *mc_addr_ptr = mc_ptr->next->dmi_addr;
+ else
+ *mc_addr_ptr = NULL;
+
+ return addr;
+}
+
/**
- * ixgbe_set_multi - Multicast and Promiscuous mode set
+ * ixgbe_set_rx_mode - Unicast, Multicast and Promiscuous mode set
* @netdev: network interface device structure
*
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated. This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
+ * The set_rx_method entry point is called whenever the unicast/multicast
+ * address list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper unicast, multicast and
+ * promiscuous mode.
**/
-static void ixgbe_set_multi(struct net_device *netdev)
+static void ixgbe_set_rx_mode(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- struct dev_mc_list *mc_ptr;
- u8 *mta_list;
u32 fctrl, vlnctrl;
- int i;
+ u8 *addr_list = NULL;
+ int addr_count = 0;
/* Check for Promiscuous and All Multicast modes */
@@ -1645,6 +1806,7 @@ static void ixgbe_set_multi(struct net_device *netdev)
vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
if (netdev->flags & IFF_PROMISC) {
+ hw->addr_ctrl.user_set_promisc = 1;
fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
vlnctrl &= ~IXGBE_VLNCTRL_VFE;
} else {
@@ -1655,33 +1817,25 @@ static void ixgbe_set_multi(struct net_device *netdev)
fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
}
vlnctrl |= IXGBE_VLNCTRL_VFE;
+ hw->addr_ctrl.user_set_promisc = 0;
}
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
- if (netdev->mc_count) {
- mta_list = kcalloc(netdev->mc_count, ETH_ALEN, GFP_ATOMIC);
- if (!mta_list)
- return;
-
- /* Shared function expects packed array of only addresses. */
- mc_ptr = netdev->mc_list;
-
- for (i = 0; i < netdev->mc_count; i++) {
- if (!mc_ptr)
- break;
- memcpy(mta_list + (i * ETH_ALEN), mc_ptr->dmi_addr,
- ETH_ALEN);
- mc_ptr = mc_ptr->next;
- }
-
- ixgbe_update_mc_addr_list(hw, mta_list, i, 0);
- kfree(mta_list);
- } else {
- ixgbe_update_mc_addr_list(hw, NULL, 0, 0);
- }
-
+ /* reprogram secondary unicast list */
+ addr_count = netdev->uc_count;
+ if (addr_count)
+ addr_list = netdev->uc_list->dmi_addr;
+ hw->mac.ops.update_uc_addr_list(hw, addr_list, addr_count,
+ ixgbe_addr_list_itr);
+
+ /* reprogram multicast list */
+ addr_count = netdev->mc_count;
+ if (addr_count)
+ addr_list = netdev->mc_list->dmi_addr;
+ hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count,
+ ixgbe_addr_list_itr);
}
static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
@@ -1695,10 +1849,16 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
q_vectors = 1;
for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+ struct napi_struct *napi;
q_vector = &adapter->q_vector[q_idx];
if (!q_vector->rxr_count)
continue;
- napi_enable(&q_vector->napi);
+ napi = &q_vector->napi;
+ if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) &&
+ (q_vector->rxr_count > 1))
+ napi->poll = &ixgbe_clean_rxonly_many;
+
+ napi_enable(napi);
}
}
@@ -1725,7 +1885,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int i;
- ixgbe_set_multi(netdev);
+ ixgbe_set_rx_mode(netdev);
ixgbe_restore_vlan(adapter);
@@ -1733,7 +1893,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
ixgbe_configure_rx(adapter);
for (i = 0; i < adapter->num_rx_queues; i++)
ixgbe_alloc_rx_buffers(adapter, &adapter->rx_ring[i],
- (adapter->rx_ring[i].count - 1));
+ (adapter->rx_ring[i].count - 1));
}
static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
@@ -1751,7 +1911,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
(adapter->flags & IXGBE_FLAG_MSI_ENABLED)) {
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME |
- IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
+ IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
} else {
/* MSI only */
gpie = 0;
@@ -1778,6 +1938,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) {
j = adapter->tx_ring[i].reg_idx;
txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+ /* enable WTHRESH=8 descriptors, to encourage burst writeback */
+ txdctl |= (8 << 16);
txdctl |= IXGBE_TXDCTL_ENABLE;
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
}
@@ -1812,6 +1974,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
/* bring the link up in the watchdog, this could race with our first
* link up interrupt but shouldn't be a problem */
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
+ adapter->link_check_timeout = jiffies;
mod_timer(&adapter->watchdog_timer, jiffies);
return 0;
}
@@ -1836,50 +2000,14 @@ int ixgbe_up(struct ixgbe_adapter *adapter)
void ixgbe_reset(struct ixgbe_adapter *adapter)
{
- if (ixgbe_init_hw(&adapter->hw))
- DPRINTK(PROBE, ERR, "Hardware Error\n");
+ struct ixgbe_hw *hw = &adapter->hw;
+ if (hw->mac.ops.init_hw(hw))
+ dev_err(&adapter->pdev->dev, "Hardware Error\n");
/* reprogram the RAR[0] in case user changed it. */
- ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
-
-}
-
-#ifdef CONFIG_PM
-static int ixgbe_resume(struct pci_dev *pdev)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- u32 err;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- err = pci_enable_device(pdev);
- if (err) {
- printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \
- "suspend\n");
- return err;
- }
- pci_set_master(pdev);
-
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
-
- if (netif_running(netdev)) {
- err = ixgbe_request_irq(adapter);
- if (err)
- return err;
- }
-
- ixgbe_reset(adapter);
-
- if (netif_running(netdev))
- ixgbe_up(adapter);
-
- netif_device_attach(netdev);
+ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
- return 0;
}
-#endif
/**
* ixgbe_clean_rx_ring - Free Rx Buffers per Queue
@@ -1887,7 +2015,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
* @rx_ring: ring to free buffers from
**/
static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
@@ -1901,8 +2029,8 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
rx_buffer_info = &rx_ring->rx_buffer_info[i];
if (rx_buffer_info->dma) {
pci_unmap_single(pdev, rx_buffer_info->dma,
- adapter->rx_buf_len,
- PCI_DMA_FROMDEVICE);
+ rx_ring->rx_buf_len,
+ PCI_DMA_FROMDEVICE);
rx_buffer_info->dma = 0;
}
if (rx_buffer_info->skb) {
@@ -1911,12 +2039,12 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
}
if (!rx_buffer_info->page)
continue;
- pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2,
+ PCI_DMA_FROMDEVICE);
rx_buffer_info->page_dma = 0;
-
put_page(rx_buffer_info->page);
rx_buffer_info->page = NULL;
+ rx_buffer_info->page_offset = 0;
}
size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
@@ -1938,7 +2066,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
* @tx_ring: ring to be cleaned
**/
static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned long size;
@@ -1991,75 +2119,64 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
void ixgbe_down(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct ixgbe_hw *hw = &adapter->hw;
u32 rxctrl;
+ u32 txdctl;
+ int i, j;
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
/* disable receives */
- rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL,
- rxctrl & ~IXGBE_RXCTRL_RXEN);
+ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
netif_tx_disable(netdev);
- /* disable transmits in the hardware */
-
- /* flush both disables */
- IXGBE_WRITE_FLUSH(&adapter->hw);
+ IXGBE_WRITE_FLUSH(hw);
msleep(10);
+ netif_tx_stop_all_queues(netdev);
+
ixgbe_irq_disable(adapter);
ixgbe_napi_disable_all(adapter);
+
del_timer_sync(&adapter->watchdog_timer);
+ cancel_work_sync(&adapter->watchdog_task);
+
+ /* disable transmits in the hardware now that interrupts are off */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ j = adapter->tx_ring[i].reg_idx;
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j),
+ (txdctl & ~IXGBE_TXDCTL_ENABLE));
+ }
netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
+#ifdef CONFIG_IXGBE_DCA
+ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
+ adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
+ dca_remove_requester(&adapter->pdev->dev);
+ }
+
+#endif
if (!pci_channel_offline(adapter->pdev))
ixgbe_reset(adapter);
ixgbe_clean_all_tx_rings(adapter);
ixgbe_clean_all_rx_rings(adapter);
-}
-
-static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_PM
- int retval = 0;
-#endif
-
- netif_device_detach(netdev);
-
- if (netif_running(netdev)) {
- ixgbe_down(adapter);
- ixgbe_free_irq(adapter);
+#ifdef CONFIG_IXGBE_DCA
+ /* since we reset the hardware DCA settings were cleared */
+ if (dca_add_requester(&adapter->pdev->dev) == 0) {
+ adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
+ /* always use CB2 mode, difference is masked
+ * in the CB driver */
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
+ ixgbe_setup_dca(adapter);
}
-
-#ifdef CONFIG_PM
- retval = pci_save_state(pdev);
- if (retval)
- return retval;
#endif
-
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
-
- ixgbe_release_hw_control(adapter);
-
- pci_disable_device(pdev);
-
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
- return 0;
-}
-
-static void ixgbe_shutdown(struct pci_dev *pdev)
-{
- ixgbe_suspend(pdev, PMSG_SUSPEND);
}
/**
@@ -2072,11 +2189,11 @@ static void ixgbe_shutdown(struct pci_dev *pdev)
static int ixgbe_poll(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector = container_of(napi,
- struct ixgbe_q_vector, napi);
+ struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
- int tx_cleaned = 0, work_done = 0;
+ int tx_cleaned, work_done = 0;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
ixgbe_update_tx_dca(adapter, adapter->tx_ring);
ixgbe_update_rx_dca(adapter, adapter->rx_ring);
@@ -2092,12 +2209,11 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
netif_rx_complete(adapter->netdev, napi);
- if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
+ if (adapter->itr_setting & 3)
ixgbe_set_itr(adapter);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable(adapter);
}
-
return work_done;
}
@@ -2123,8 +2239,48 @@ static void ixgbe_reset_task(struct work_struct *work)
ixgbe_reinit_locked(adapter);
}
+static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
+{
+ int nrq = 1, ntq = 1;
+ int feature_mask = 0, rss_i, rss_m;
+
+ /* Number of supported queues */
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82598EB:
+ rss_i = adapter->ring_feature[RING_F_RSS].indices;
+ rss_m = 0;
+ feature_mask |= IXGBE_FLAG_RSS_ENABLED;
+
+ switch (adapter->flags & feature_mask) {
+ case (IXGBE_FLAG_RSS_ENABLED):
+ rss_m = 0xF;
+ nrq = rss_i;
+ ntq = rss_i;
+ break;
+ case 0:
+ default:
+ rss_i = 0;
+ rss_m = 0;
+ nrq = 1;
+ ntq = 1;
+ break;
+ }
+
+ adapter->ring_feature[RING_F_RSS].indices = rss_i;
+ adapter->ring_feature[RING_F_RSS].mask = rss_m;
+ break;
+ default:
+ nrq = 1;
+ ntq = 1;
+ break;
+ }
+
+ adapter->num_rx_queues = nrq;
+ adapter->num_tx_queues = ntq;
+}
+
static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
- int vectors)
+ int vectors)
{
int err, vector_threshold;
@@ -2143,7 +2299,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
*/
while (vectors >= vector_threshold) {
err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
- vectors);
+ vectors);
if (!err) /* Success in acquiring all requested vectors. */
break;
else if (err < 0)
@@ -2162,54 +2318,13 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- adapter->num_tx_queues = 1;
- adapter->num_rx_queues = 1;
+ ixgbe_set_num_queues(adapter);
} else {
adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
adapter->num_msix_vectors = vectors;
}
}
-static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
-{
- int nrq, ntq;
- int feature_mask = 0, rss_i, rss_m;
-
- /* Number of supported queues */
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- rss_i = adapter->ring_feature[RING_F_RSS].indices;
- rss_m = 0;
- feature_mask |= IXGBE_FLAG_RSS_ENABLED;
-
- switch (adapter->flags & feature_mask) {
- case (IXGBE_FLAG_RSS_ENABLED):
- rss_m = 0xF;
- nrq = rss_i;
- ntq = rss_i;
- break;
- case 0:
- default:
- rss_i = 0;
- rss_m = 0;
- nrq = 1;
- ntq = 1;
- break;
- }
-
- adapter->ring_feature[RING_F_RSS].indices = rss_i;
- adapter->ring_feature[RING_F_RSS].mask = rss_m;
- break;
- default:
- nrq = 1;
- ntq = 1;
- break;
- }
-
- adapter->num_rx_queues = nrq;
- adapter->num_tx_queues = ntq;
-}
-
/**
* ixgbe_cache_ring_register - Descriptor ring to register mapping
* @adapter: board private structure to initialize
@@ -2219,9 +2334,6 @@ static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
**/
static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
{
- /* TODO: Remove all uses of the indices in the cases where multiple
- * features are OR'd together, if the feature set makes sense.
- */
int feature_mask = 0, rss_i;
int i, txr_idx, rxr_idx;
@@ -2262,21 +2374,22 @@ static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
int i;
adapter->tx_ring = kcalloc(adapter->num_tx_queues,
- sizeof(struct ixgbe_ring), GFP_KERNEL);
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!adapter->tx_ring)
goto err_tx_ring_allocation;
adapter->rx_ring = kcalloc(adapter->num_rx_queues,
- sizeof(struct ixgbe_ring), GFP_KERNEL);
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!adapter->rx_ring)
goto err_rx_ring_allocation;
for (i = 0; i < adapter->num_tx_queues; i++) {
- adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
+ adapter->tx_ring[i].count = adapter->tx_ring_count;
adapter->tx_ring[i].queue_index = i;
}
+
for (i = 0; i < adapter->num_rx_queues; i++) {
- adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD;
+ adapter->rx_ring[i].count = adapter->rx_ring_count;
adapter->rx_ring[i].queue_index = i;
}
@@ -2298,7 +2411,7 @@ err_tx_ring_allocation:
* capabilities of the hardware and the kernel.
**/
static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
- *adapter)
+ *adapter)
{
int err = 0;
int vector, v_budget;
@@ -2310,7 +2423,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
* (roughly) twice the number of vectors as there are CPU's.
*/
v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
- (int)(num_online_cpus() * 2)) + NON_Q_VECTORS;
+ (int)(num_online_cpus() * 2)) + NON_Q_VECTORS;
/*
* At the same time, hardware can only support a maximum of
@@ -2324,7 +2437,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
/* A failure in MSI-X entry allocation isn't fatal, but it does
* mean we disable MSI-X capabilities of the adapter. */
adapter->msix_entries = kcalloc(v_budget,
- sizeof(struct msix_entry), GFP_KERNEL);
+ sizeof(struct msix_entry), GFP_KERNEL);
if (!adapter->msix_entries) {
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
ixgbe_set_num_queues(adapter);
@@ -2333,7 +2446,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
err = ixgbe_alloc_queues(adapter);
if (err) {
DPRINTK(PROBE, ERR, "Unable to allocate memory "
- "for queues\n");
+ "for queues\n");
goto out;
}
@@ -2354,7 +2467,7 @@ try_msi:
adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
} else {
DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
- "falling back to legacy. Error: %d\n", err);
+ "falling back to legacy. Error: %d\n", err);
/* reset err */
err = 0;
}
@@ -2410,9 +2523,9 @@ static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
}
DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
- "Tx Queue count = %u\n",
- (adapter->num_rx_queues > 1) ? "Enabled" :
- "Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
+ "Tx Queue count = %u\n",
+ (adapter->num_rx_queues > 1) ? "Enabled" :
+ "Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
set_bit(__IXGBE_DOWN, &adapter->state);
@@ -2439,33 +2552,44 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
unsigned int rss;
+ /* PCI config space info */
+
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->revision_id = pdev->revision;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_device_id = pdev->subsystem_device;
+
/* Set capability flags */
rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
- /* Enable Dynamic interrupt throttling by default */
- adapter->rx_eitr = 1;
- adapter->tx_eitr = 1;
-
/* default flow control settings */
- hw->fc.original_type = ixgbe_fc_full;
- hw->fc.type = ixgbe_fc_full;
+ hw->fc.original_type = ixgbe_fc_none;
+ hw->fc.type = ixgbe_fc_none;
+ hw->fc.high_water = IXGBE_DEFAULT_FCRTH;
+ hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
+ hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
+ hw->fc.send_xon = true;
/* select 10G link by default */
hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
- if (hw->mac.ops.reset(hw)) {
- dev_err(&pdev->dev, "HW Init failed\n");
- return -EIO;
- }
- if (hw->mac.ops.setup_link_speed(hw, IXGBE_LINK_SPEED_10GB_FULL, true,
- false)) {
- dev_err(&pdev->dev, "Link Speed setup failed\n");
- return -EIO;
- }
+
+ /* enable itr by default in dynamic mode */
+ adapter->itr_setting = 1;
+ adapter->eitr_param = 20000;
+
+ /* set defaults for eitr in MegaBytes */
+ adapter->eitr_low = 10;
+ adapter->eitr_high = 20;
+
+ /* set default ring sizes */
+ adapter->tx_ring_count = IXGBE_DEFAULT_TXD;
+ adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
/* initialize eeprom parameters */
- if (ixgbe_init_eeprom(hw)) {
+ if (ixgbe_init_eeprom_params_generic(hw)) {
dev_err(&pdev->dev, "EEPROM initialization failed\n");
return -EIO;
}
@@ -2481,105 +2605,157 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
/**
* ixgbe_setup_tx_resources - allocate Tx resources (Descriptors)
* @adapter: board private structure
- * @txdr: tx descriptor ring (for a specific queue) to setup
+ * @tx_ring: tx descriptor ring (for a specific queue) to setup
*
* Return 0 on success, negative on failure
**/
int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *txdr)
+ struct ixgbe_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
int size;
- size = sizeof(struct ixgbe_tx_buffer) * txdr->count;
- txdr->tx_buffer_info = vmalloc(size);
- if (!txdr->tx_buffer_info) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the transmit descriptor ring\n");
- return -ENOMEM;
- }
- memset(txdr->tx_buffer_info, 0, size);
+ size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
+ tx_ring->tx_buffer_info = vmalloc(size);
+ if (!tx_ring->tx_buffer_info)
+ goto err;
+ memset(tx_ring->tx_buffer_info, 0, size);
/* round up to nearest 4K */
- txdr->size = txdr->count * sizeof(union ixgbe_adv_tx_desc);
- txdr->size = ALIGN(txdr->size, 4096);
+ tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc) +
+ sizeof(u32);
+ tx_ring->size = ALIGN(tx_ring->size, 4096);
- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if (!txdr->desc) {
- vfree(txdr->tx_buffer_info);
- DPRINTK(PROBE, ERR,
- "Memory allocation failed for the tx desc ring\n");
- return -ENOMEM;
- }
-
- txdr->next_to_use = 0;
- txdr->next_to_clean = 0;
- txdr->work_limit = txdr->count;
+ tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
+ &tx_ring->dma);
+ if (!tx_ring->desc)
+ goto err;
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+ tx_ring->work_limit = tx_ring->count;
return 0;
+
+err:
+ vfree(tx_ring->tx_buffer_info);
+ tx_ring->tx_buffer_info = NULL;
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit "
+ "descriptor ring\n");
+ return -ENOMEM;
+}
+
+/**
+ * ixgbe_setup_all_tx_resources - allocate all queues Tx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+ if (!err)
+ continue;
+ DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i);
+ break;
+ }
+
+ return err;
}
/**
* ixgbe_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: board private structure
- * @rxdr: rx descriptor ring (for a specific queue) to setup
+ * @rx_ring: rx descriptor ring (for a specific queue) to setup
*
* Returns 0 on success, negative on failure
**/
int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rxdr)
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
- rxdr->lro_mgr.lro_arr = vmalloc(size);
- if (!rxdr->lro_mgr.lro_arr)
+ rx_ring->lro_mgr.lro_arr = vmalloc(size);
+ if (!rx_ring->lro_mgr.lro_arr)
return -ENOMEM;
- memset(rxdr->lro_mgr.lro_arr, 0, size);
+ memset(rx_ring->lro_mgr.lro_arr, 0, size);
- size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
- rxdr->rx_buffer_info = vmalloc(size);
- if (!rxdr->rx_buffer_info) {
+ size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
+ rx_ring->rx_buffer_info = vmalloc(size);
+ if (!rx_ring->rx_buffer_info) {
DPRINTK(PROBE, ERR,
- "vmalloc allocation failed for the rx desc ring\n");
+ "vmalloc allocation failed for the rx desc ring\n");
goto alloc_failed;
}
- memset(rxdr->rx_buffer_info, 0, size);
+ memset(rx_ring->rx_buffer_info, 0, size);
/* Round up to nearest 4K */
- rxdr->size = rxdr->count * sizeof(union ixgbe_adv_rx_desc);
- rxdr->size = ALIGN(rxdr->size, 4096);
+ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
+ rx_ring->size = ALIGN(rx_ring->size, 4096);
- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+ rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, &rx_ring->dma);
- if (!rxdr->desc) {
+ if (!rx_ring->desc) {
DPRINTK(PROBE, ERR,
- "Memory allocation failed for the rx desc ring\n");
- vfree(rxdr->rx_buffer_info);
+ "Memory allocation failed for the rx desc ring\n");
+ vfree(rx_ring->rx_buffer_info);
goto alloc_failed;
}
- rxdr->next_to_clean = 0;
- rxdr->next_to_use = 0;
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
return 0;
alloc_failed:
- vfree(rxdr->lro_mgr.lro_arr);
- rxdr->lro_mgr.lro_arr = NULL;
+ vfree(rx_ring->lro_mgr.lro_arr);
+ rx_ring->lro_mgr.lro_arr = NULL;
return -ENOMEM;
}
/**
+ * ixgbe_setup_all_rx_resources - allocate all queues Rx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+ if (!err)
+ continue;
+ DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i);
+ break;
+ }
+
+ return err;
+}
+
+/**
* ixgbe_free_tx_resources - Free Tx Resources per Queue
* @adapter: board private structure
* @tx_ring: Tx descriptor ring for a specific queue
*
* Free all transmit software resources
**/
-static void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2614,8 +2790,8 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter)
*
* Free all receive software resources
**/
-static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2647,59 +2823,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_setup_all_tx_resources - allocate all queues Tx resources
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]);
- if (err) {
- DPRINTK(PROBE, ERR,
- "Allocation for Tx Queue %u failed\n", i);
- break;
- }
- }
-
- return err;
-}
-
-/**
- * ixgbe_setup_all_rx_resources - allocate all queues Rx resources
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-
-static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]);
- if (err) {
- DPRINTK(PROBE, ERR,
- "Allocation for Rx Queue %u failed\n", i);
- break;
- }
- }
-
- return err;
-}
-
-/**
* ixgbe_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
* @new_mtu: new value for maximum frame size
@@ -2711,12 +2834,12 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
struct ixgbe_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- if ((max_frame < (ETH_ZLEN + ETH_FCS_LEN)) ||
- (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
+ /* MTU < 68 is an error and causes problems on some kernels */
+ if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
return -EINVAL;
DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
- netdev->mtu, new_mtu);
+ netdev->mtu, new_mtu);
/* must set new MTU before calling down or up */
netdev->mtu = new_mtu;
@@ -2811,6 +2934,135 @@ static int ixgbe_close(struct net_device *netdev)
}
/**
+ * ixgbe_napi_add_all - prep napi structs for use
+ * @adapter: private struct
+ * helper function to napi_add each possible q_vector->napi
+ */
+static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
+{
+ int q_idx, q_vectors;
+ int (*poll)(struct napi_struct *, int);
+
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ poll = &ixgbe_clean_rxonly;
+ /* Only enable as many vectors as we have rx queues. */
+ q_vectors = adapter->num_rx_queues;
+ } else {
+ poll = &ixgbe_poll;
+ /* only one q_vector for legacy modes */
+ q_vectors = 1;
+ }
+
+ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+ struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
+ netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
+ }
+}
+
+static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
+{
+ int q_idx;
+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+ /* legacy and MSI only use one vector */
+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
+ q_vectors = 1;
+
+ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+ struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
+ if (!q_vector->rxr_count)
+ continue;
+ netif_napi_del(&q_vector->napi);
+ }
+}
+
+#ifdef CONFIG_PM
+static int ixgbe_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "ixgbe: Cannot enable PCI device from "
+ "suspend\n");
+ return err;
+ }
+ pci_set_master(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ err = ixgbe_init_interrupt_scheme(adapter);
+ if (err) {
+ printk(KERN_ERR "ixgbe: Cannot initialize interrupts for "
+ "device\n");
+ return err;
+ }
+
+ ixgbe_napi_add_all(adapter);
+ ixgbe_reset(adapter);
+
+ if (netif_running(netdev)) {
+ err = ixgbe_open(adapter->netdev);
+ if (err)
+ return err;
+ }
+
+ netif_device_attach(netdev);
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+#ifdef CONFIG_PM
+ int retval = 0;
+#endif
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev)) {
+ ixgbe_down(adapter);
+ ixgbe_free_irq(adapter);
+ ixgbe_free_all_tx_resources(adapter);
+ ixgbe_free_all_rx_resources(adapter);
+ }
+ ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_napi_del_all(adapter);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+
+#ifdef CONFIG_PM
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+#endif
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ ixgbe_release_hw_control(adapter);
+
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static void ixgbe_shutdown(struct pci_dev *pdev)
+{
+ ixgbe_suspend(pdev, PMSG_SUSPEND);
+}
+
+/**
* ixgbe_update_stats - Update the board statistics counters.
* @adapter: board private structure
**/
@@ -2883,7 +3135,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
/* Rx Errors */
adapter->net_stats.rx_errors = adapter->stats.crcerrs +
- adapter->stats.rlec;
+ adapter->stats.rlec;
adapter->net_stats.rx_dropped = 0;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
@@ -2897,27 +3149,74 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
static void ixgbe_watchdog(unsigned long data)
{
struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
- struct net_device *netdev = adapter->netdev;
- bool link_up;
- u32 link_speed = 0;
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ /* Do the watchdog outside of interrupt context due to the lovely
+ * delays that some of the newer hardware requires */
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ /* Cause software interrupt to ensure rx rings are cleaned */
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ u32 eics =
+ (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
+ IXGBE_WRITE_REG(hw, IXGBE_EICS, eics);
+ } else {
+ /* For legacy and MSI interrupts don't set any bits that
+ * are enabled for EIAM, because this operation would
+ * set *both* EIMS and EICS for any bit in EIAM */
+ IXGBE_WRITE_REG(hw, IXGBE_EICS,
+ (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
+ }
+ /* Reset the timer */
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 2 * HZ));
+ }
- adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
+ schedule_work(&adapter->watchdog_task);
+}
+
+/**
+ * ixgbe_watchdog_task - worker thread to bring link up
+ * @work: pointer to work_struct containing our data
+ **/
+static void ixgbe_watchdog_task(struct work_struct *work)
+{
+ struct ixgbe_adapter *adapter = container_of(work,
+ struct ixgbe_adapter,
+ watchdog_task);
+ struct net_device *netdev = adapter->netdev;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 link_speed = adapter->link_speed;
+ bool link_up = adapter->link_up;
+
+ adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
+
+ if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
+ hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
+ if (link_up ||
+ time_after(jiffies, (adapter->link_check_timeout +
+ IXGBE_TRY_LINK_TIMEOUT))) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
+ adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
+ }
+ adapter->link_up = link_up;
+ adapter->link_speed = link_speed;
+ }
if (link_up) {
if (!netif_carrier_ok(netdev)) {
- u32 frctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
- u32 rmcs = IXGBE_READ_REG(&adapter->hw, IXGBE_RMCS);
+ u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
#define FLOW_RX (frctl & IXGBE_FCTRL_RFCE)
#define FLOW_TX (rmcs & IXGBE_RMCS_TFCE_802_3X)
DPRINTK(LINK, INFO, "NIC Link is Up %s, "
- "Flow Control: %s\n",
- (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
- "10 Gbps" :
- (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
- "1 Gbps" : "unknown speed")),
- ((FLOW_RX && FLOW_TX) ? "RX/TX" :
- (FLOW_RX ? "RX" :
- (FLOW_TX ? "TX" : "None"))));
+ "Flow Control: %s\n",
+ (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
+ "10 Gbps" :
+ (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
+ "1 Gbps" : "unknown speed")),
+ ((FLOW_RX && FLOW_TX) ? "RX/TX" :
+ (FLOW_RX ? "RX" :
+ (FLOW_TX ? "TX" : "None"))));
netif_carrier_on(netdev);
netif_tx_wake_all_queues(netdev);
@@ -2926,6 +3225,8 @@ static void ixgbe_watchdog(unsigned long data)
adapter->detect_tx_hung = true;
}
} else {
+ adapter->link_up = false;
+ adapter->link_speed = 0;
if (netif_carrier_ok(netdev)) {
DPRINTK(LINK, INFO, "NIC Link is Down\n");
netif_carrier_off(netdev);
@@ -2934,36 +3235,19 @@ static void ixgbe_watchdog(unsigned long data)
}
ixgbe_update_stats(adapter);
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
- /* Cause software interrupt to ensure rx rings are cleaned */
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- u32 eics =
- (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics);
- } else {
- /* for legacy and MSI interrupts don't set any bits that
- * are enabled for EIAM, because this operation would
- * set *both* EIMS and EICS for any bit in EIAM */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
- (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
- }
- /* Reset the timer */
- mod_timer(&adapter->watchdog_timer,
- round_jiffies(jiffies + 2 * HZ));
- }
+ adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
}
static int ixgbe_tso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
- u32 tx_flags, u8 *hdr_len)
+ struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+ u32 tx_flags, u8 *hdr_len)
{
struct ixgbe_adv_tx_context_desc *context_desc;
unsigned int i;
int err;
struct ixgbe_tx_buffer *tx_buffer_info;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
- u32 mss_l4len_idx = 0, l4len;
+ u32 vlan_macip_lens = 0, type_tucmd_mlhl;
+ u32 mss_l4len_idx, l4len;
if (skb_is_gso(skb)) {
if (skb_header_cloned(skb)) {
@@ -2979,16 +3263,16 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
iph->tot_len = 0;
iph->check = 0;
tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
adapter->hw_tso_ctxt++;
} else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
ipv6_hdr(skb)->payload_len = 0;
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
adapter->hw_tso6_ctxt++;
}
@@ -3002,7 +3286,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
vlan_macip_lens |=
(tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
vlan_macip_lens |= ((skb_network_offset(skb)) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
+ IXGBE_ADVTXD_MACLEN_SHIFT);
*hdr_len += skb_network_offset(skb);
vlan_macip_lens |=
(skb_transport_header(skb) - skb_network_header(skb));
@@ -3012,8 +3296,8 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
context_desc->seqnum_seed = 0;
/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
- type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
+ type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
+ IXGBE_ADVTXD_DTYP_CTXT);
if (skb->protocol == htons(ETH_P_IP))
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
@@ -3021,9 +3305,11 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
/* MSS L4LEN IDX */
- mss_l4len_idx |=
+ mss_l4len_idx =
(skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT);
mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT);
+ /* use index 1 for TSO */
+ mss_l4len_idx |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
tx_buffer_info->time_stamp = jiffies;
@@ -3040,8 +3326,8 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
}
static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags)
+ struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags)
{
struct ixgbe_adv_tx_context_desc *context_desc;
unsigned int i;
@@ -3058,16 +3344,16 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
vlan_macip_lens |=
(tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
vlan_macip_lens |= (skb_network_offset(skb) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
+ IXGBE_ADVTXD_MACLEN_SHIFT);
if (skb->ip_summed == CHECKSUM_PARTIAL)
vlan_macip_lens |= (skb_transport_header(skb) -
- skb_network_header(skb));
+ skb_network_header(skb));
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
context_desc->seqnum_seed = 0;
type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
+ IXGBE_ADVTXD_DTYP_CTXT);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
switch (skb->protocol) {
@@ -3075,16 +3361,14 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
if (ip_hdr(skb)->protocol == IPPROTO_TCP)
type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ IXGBE_ADVTXD_TUCMD_L4T_TCP;
break;
-
case __constant_htons(ETH_P_IPV6):
/* XXX what about other V6 headers?? */
if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ IXGBE_ADVTXD_TUCMD_L4T_TCP;
break;
-
default:
if (unlikely(net_ratelimit())) {
DPRINTK(PROBE, WARNING,
@@ -3096,10 +3380,12 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
}
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
+ /* use index zero for tx checksum offload */
context_desc->mss_l4len_idx = 0;
tx_buffer_info->time_stamp = jiffies;
tx_buffer_info->next_to_watch = i;
+
adapter->hw_csum_tx_good++;
i++;
if (i == tx_ring->count)
@@ -3108,12 +3394,13 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
return true;
}
+
return false;
}
static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, unsigned int first)
+ struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb, unsigned int first)
{
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned int len = skb->len;
@@ -3131,8 +3418,8 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
tx_buffer_info->length = size;
tx_buffer_info->dma = pci_map_single(adapter->pdev,
- skb->data + offset,
- size, PCI_DMA_TODEVICE);
+ skb->data + offset,
+ size, PCI_DMA_TODEVICE);
tx_buffer_info->time_stamp = jiffies;
tx_buffer_info->next_to_watch = i;
@@ -3157,9 +3444,10 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
tx_buffer_info->length = size;
tx_buffer_info->dma = pci_map_page(adapter->pdev,
- frag->page,
- offset,
- size, PCI_DMA_TODEVICE);
+ frag->page,
+ offset,
+ size,
+ PCI_DMA_TODEVICE);
tx_buffer_info->time_stamp = jiffies;
tx_buffer_info->next_to_watch = i;
@@ -3182,8 +3470,8 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
}
static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- int tx_flags, int count, u32 paylen, u8 hdr_len)
+ struct ixgbe_ring *tx_ring,
+ int tx_flags, int count, u32 paylen, u8 hdr_len)
{
union ixgbe_adv_tx_desc *tx_desc = NULL;
struct ixgbe_tx_buffer *tx_buffer_info;
@@ -3202,15 +3490,17 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
+ /* use index 1 context for tso */
+ olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
if (tx_flags & IXGBE_TX_FLAGS_IPV4)
olinfo_status |= IXGBE_TXD_POPTS_IXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
} else if (tx_flags & IXGBE_TX_FLAGS_CSUM)
olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);
@@ -3220,9 +3510,8 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma);
tx_desc->read.cmd_type_len =
- cpu_to_le32(cmd_type_len | tx_buffer_info->length);
+ cpu_to_le32(cmd_type_len | tx_buffer_info->length);
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
-
i++;
if (i == tx_ring->count)
i = 0;
@@ -3243,7 +3532,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
}
static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
- struct ixgbe_ring *tx_ring, int size)
+ struct ixgbe_ring *tx_ring, int size)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -3259,61 +3548,52 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
return -EBUSY;
/* A reprieve! - use start_queue because it doesn't call schedule */
- netif_wake_subqueue(netdev, tx_ring->queue_index);
+ netif_start_subqueue(netdev, tx_ring->queue_index);
++adapter->restart_queue;
return 0;
}
static int ixgbe_maybe_stop_tx(struct net_device *netdev,
- struct ixgbe_ring *tx_ring, int size)
+ struct ixgbe_ring *tx_ring, int size)
{
if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
return 0;
return __ixgbe_maybe_stop_tx(netdev, tx_ring, size);
}
-
static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *tx_ring;
- unsigned int len = skb->len;
unsigned int first;
unsigned int tx_flags = 0;
u8 hdr_len = 0;
int r_idx = 0, tso;
- unsigned int mss = 0;
int count = 0;
unsigned int f;
- unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
- len -= skb->data_len;
+
r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping;
tx_ring = &adapter->tx_ring[r_idx];
-
- if (skb->len <= 0) {
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
+ if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ tx_flags |= vlan_tx_tag_get(skb);
+ tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= IXGBE_TX_FLAGS_VLAN;
}
- mss = skb_shinfo(skb)->gso_size;
-
- if (mss)
- count++;
- else if (skb->ip_summed == CHECKSUM_PARTIAL)
+ /* three things can cause us to need a context descriptor */
+ if (skb_is_gso(skb) ||
+ (skb->ip_summed == CHECKSUM_PARTIAL) ||
+ (tx_flags & IXGBE_TX_FLAGS_VLAN))
count++;
- count += TXD_USE_COUNT(len);
- for (f = 0; f < nr_frags; f++)
+ count += TXD_USE_COUNT(skb_headlen(skb));
+ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) {
adapter->tx_busy++;
return NETDEV_TX_BUSY;
}
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
- tx_flags |= IXGBE_TX_FLAGS_VLAN;
- tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT);
- }
if (skb->protocol == htons(ETH_P_IP))
tx_flags |= IXGBE_TX_FLAGS_IPV4;
@@ -3327,12 +3607,12 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (tso)
tx_flags |= IXGBE_TX_FLAGS_TSO;
else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
- (skb->ip_summed == CHECKSUM_PARTIAL))
+ (skb->ip_summed == CHECKSUM_PARTIAL))
tx_flags |= IXGBE_TX_FLAGS_CSUM;
ixgbe_tx_queue(adapter, tx_ring, tx_flags,
- ixgbe_tx_map(adapter, tx_ring, skb, first),
- skb->len, hdr_len);
+ ixgbe_tx_map(adapter, tx_ring, skb, first),
+ skb->len, hdr_len);
netdev->trans_start = jiffies;
@@ -3366,15 +3646,16 @@ static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev)
static int ixgbe_set_mac(struct net_device *netdev, void *p)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len);
+ memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
- ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
+ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
return 0;
}
@@ -3398,28 +3679,19 @@ static void ixgbe_netpoll(struct net_device *netdev)
#endif
/**
- * ixgbe_napi_add_all - prep napi structs for use
- * @adapter: private struct
- * helper function to napi_add each possible q_vector->napi
- */
-static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
+ * ixgbe_link_config - set up initial link with default speed and duplex
+ * @hw: pointer to private hardware struct
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int ixgbe_link_config(struct ixgbe_hw *hw)
{
- int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
- int (*poll)(struct napi_struct *, int);
+ u32 autoneg = IXGBE_LINK_SPEED_10GB_FULL;
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- poll = &ixgbe_clean_rxonly;
- } else {
- poll = &ixgbe_poll;
- /* only one q_vector for legacy modes */
- q_vectors = 1;
- }
+ /* must always autoneg for both 1G and 10G link */
+ hw->mac.autoneg = true;
- for (i = 0; i < q_vectors; i++) {
- struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
- netif_napi_add(adapter->netdev, &q_vector->napi,
- (*poll), 64);
- }
+ return hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
}
/**
@@ -3434,17 +3706,16 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
* and a hardware reset occur.
**/
static int __devinit ixgbe_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
struct net_device *netdev;
struct ixgbe_adapter *adapter = NULL;
struct ixgbe_hw *hw;
const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
- unsigned long mmio_start, mmio_len;
static int cards_found;
int i, err, pci_using_dac;
u16 link_status, link_speed, link_width;
- u32 part_num;
+ u32 part_num, eec;
err = pci_enable_device(pdev);
if (err)
@@ -3459,7 +3730,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
dev_err(&pdev->dev, "No usable DMA "
- "configuration, aborting\n");
+ "configuration, aborting\n");
goto err_dma;
}
}
@@ -3492,10 +3763,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
hw->back = adapter;
adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
- mmio_start = pci_resource_start(pdev, 0);
- mmio_len = pci_resource_len(pdev, 0);
-
- hw->hw_addr = ioremap(mmio_start, mmio_len);
+ hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
if (!hw->hw_addr) {
err = -EIO;
goto err_ioremap;
@@ -3510,7 +3779,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->stop = &ixgbe_close;
netdev->hard_start_xmit = &ixgbe_xmit_frame;
netdev->get_stats = &ixgbe_get_stats;
- netdev->set_multicast_list = &ixgbe_set_multi;
+ netdev->set_rx_mode = &ixgbe_set_rx_mode;
+ netdev->set_multicast_list = &ixgbe_set_rx_mode;
netdev->set_mac_address = &ixgbe_set_mac;
netdev->change_mtu = &ixgbe_change_mtu;
ixgbe_set_ethtool_ops(netdev);
@@ -3524,22 +3794,23 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
#endif
strcpy(netdev->name, pci_name(pdev));
- netdev->mem_start = mmio_start;
- netdev->mem_end = mmio_start + mmio_len;
-
adapter->bd_number = cards_found;
- /* PCI config space info */
- hw->vendor_id = pdev->vendor;
- hw->device_id = pdev->device;
- hw->revision_id = pdev->revision;
- hw->subsystem_vendor_id = pdev->subsystem_vendor;
- hw->subsystem_device_id = pdev->subsystem_device;
-
/* Setup hw api */
memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
hw->mac.type = ii->mac;
+ /* EEPROM */
+ memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops));
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ /* If EEPROM is valid (bit 8 = 1), use default otherwise use bit bang */
+ if (!(eec & (1 << 8)))
+ hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic;
+
+ /* PHY */
+ memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops));
+ /* phy->sfp_type = ixgbe_sfp_type_unknown; */
+
err = ii->get_invariants(hw);
if (err)
goto err_hw_init;
@@ -3549,26 +3820,34 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (err)
goto err_sw_init;
+ /* reset_hw fills in the perm_addr as well */
+ err = hw->mac.ops.reset_hw(hw);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err);
+ goto err_sw_init;
+ }
+
netdev->features = NETIF_F_SG |
- NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_RX |
- NETIF_F_HW_VLAN_FILTER;
+ NETIF_F_IP_CSUM |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_LRO;
+ netdev->features |= NETIF_F_IPV6_CSUM;
netdev->features |= NETIF_F_TSO;
netdev->features |= NETIF_F_TSO6;
+ netdev->features |= NETIF_F_LRO;
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
- netdev->vlan_features |= NETIF_F_HW_CSUM;
+ netdev->vlan_features |= NETIF_F_IP_CSUM;
netdev->vlan_features |= NETIF_F_SG;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* make sure the EEPROM is good */
- if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
+ if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -3577,7 +3856,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len);
memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len);
- if (ixgbe_validate_mac_addr(netdev->dev_addr)) {
+ if (ixgbe_validate_mac_addr(netdev->perm_addr)) {
+ dev_err(&pdev->dev, "invalid MAC address\n");
err = -EIO;
goto err_eeprom;
}
@@ -3587,13 +3867,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
adapter->watchdog_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
-
- /* initialize default flow control settings */
- hw->fc.original_type = ixgbe_fc_full;
- hw->fc.type = ixgbe_fc_full;
- hw->fc.high_water = IXGBE_DEFAULT_FCRTH;
- hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
- hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
+ INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task);
err = ixgbe_init_interrupt_scheme(adapter);
if (err)
@@ -3604,32 +3878,39 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
link_speed = link_status & IXGBE_PCI_LINK_SPEED;
link_width = link_status & IXGBE_PCI_LINK_WIDTH;
dev_info(&pdev->dev, "(PCI Express:%s:%s) "
- "%02x:%02x:%02x:%02x:%02x:%02x\n",
- ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" :
- (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" :
- "Unknown"),
- ((link_width == IXGBE_PCI_LINK_WIDTH_8) ? "Width x8" :
- (link_width == IXGBE_PCI_LINK_WIDTH_4) ? "Width x4" :
- (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" :
- (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" :
- "Unknown"),
- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
- ixgbe_read_part_num(hw, &part_num);
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" :
+ (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" :
+ "Unknown"),
+ ((link_width == IXGBE_PCI_LINK_WIDTH_8) ? "Width x8" :
+ (link_width == IXGBE_PCI_LINK_WIDTH_4) ? "Width x4" :
+ (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" :
+ (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" :
+ "Unknown"),
+ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
+ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+ ixgbe_read_pba_num_generic(hw, &part_num);
dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
- hw->mac.type, hw->phy.type,
- (part_num >> 8), (part_num & 0xff));
+ hw->mac.type, hw->phy.type,
+ (part_num >> 8), (part_num & 0xff));
if (link_width <= IXGBE_PCI_LINK_WIDTH_4) {
dev_warn(&pdev->dev, "PCI-Express bandwidth available for "
- "this card is not sufficient for optimal "
- "performance.\n");
+ "this card is not sufficient for optimal "
+ "performance.\n");
dev_warn(&pdev->dev, "For optimal performance a x8 "
- "PCI-Express slot is required.\n");
+ "PCI-Express slot is required.\n");
}
/* reset the hardware with the new settings */
- ixgbe_start_hw(hw);
+ hw->mac.ops.start_hw(hw);
+
+ /* link_config depends on start_hw being called at least once */
+ err = ixgbe_link_config(hw);
+ if (err) {
+ dev_err(&pdev->dev, "setup_link_speed FAILED %d\n", err);
+ goto err_register;
+ }
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
@@ -3641,7 +3922,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (err)
goto err_register;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
if (dca_add_requester(&pdev->dev) == 0) {
adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
/* always use CB2 mode, difference is masked
@@ -3691,7 +3972,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
flush_scheduled_work();
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
dca_remove_requester(&pdev->dev);
@@ -3709,6 +3990,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
DPRINTK(PROBE, INFO, "complete\n");
+ ixgbe_napi_del_all(adapter);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
@@ -3726,7 +4008,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
* this device has been detected.
*/
static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
+ pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbe_adapter *adapter = netdev->priv;
@@ -3737,7 +4019,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
ixgbe_down(adapter);
pci_disable_device(pdev);
- /* Request a slot slot reset. */
+ /* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
}
@@ -3754,7 +4036,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
if (pci_enable_device(pdev)) {
DPRINTK(PROBE, ERR,
- "Cannot re-enable PCI device after reset.\n");
+ "Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
pci_set_master(pdev);
@@ -3788,7 +4070,6 @@ static void ixgbe_io_resume(struct pci_dev *pdev)
}
netif_device_attach(netdev);
-
}
static struct pci_error_handlers ixgbe_err_handler = {
@@ -3824,13 +4105,14 @@ static int __init ixgbe_init_module(void)
printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
dca_register_notify(&dca_notifier);
-
#endif
+
ret = pci_register_driver(&ixgbe_driver);
return ret;
}
+
module_init(ixgbe_init_module);
/**
@@ -3841,24 +4123,24 @@ module_init(ixgbe_init_module);
**/
static void __exit ixgbe_exit_module(void)
{
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
dca_unregister_notify(&dca_notifier);
#endif
pci_unregister_driver(&ixgbe_driver);
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_IXGBE_DCA
static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
- void *p)
+ void *p)
{
int ret_val;
ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
- __ixgbe_notify_dca);
+ __ixgbe_notify_dca);
return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_IXGBE_DCA */
module_exit(ixgbe_exit_module);
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 8002931ae82..764035a8c9a 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -33,32 +32,36 @@
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
+static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
-static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
-static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
- u32 device_type, u16 phy_data);
/**
- * ixgbe_identify_phy - Get physical layer module
+ * ixgbe_identify_phy_generic - Get physical layer module
* @hw: pointer to hardware structure
*
* Determines the physical layer module found on the current adapter.
**/
-s32 ixgbe_identify_phy(struct ixgbe_hw *hw)
+s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 phy_addr;
- for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
- if (ixgbe_validate_phy_addr(hw, phy_addr)) {
- hw->phy.addr = phy_addr;
- ixgbe_get_phy_id(hw);
- hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
- status = 0;
- break;
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
+ if (ixgbe_validate_phy_addr(hw, phy_addr)) {
+ hw->phy.addr = phy_addr;
+ ixgbe_get_phy_id(hw);
+ hw->phy.type =
+ ixgbe_get_phy_type_from_id(hw->phy.id);
+ status = 0;
+ break;
+ }
}
+ } else {
+ status = 0;
}
+
return status;
}
@@ -73,10 +76,8 @@ static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr)
bool valid = false;
hw->phy.addr = phy_addr;
- ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_PHY_ID_HIGH,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &phy_id);
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id);
if (phy_id != 0xFFFF && phy_id != 0x0)
valid = true;
@@ -95,21 +96,18 @@ static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
u16 phy_id_high = 0;
u16 phy_id_low = 0;
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_PHY_ID_HIGH,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &phy_id_high);
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &phy_id_high);
if (status == 0) {
hw->phy.id = (u32)(phy_id_high << 16);
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_PHY_ID_LOW,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &phy_id_low);
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &phy_id_low);
hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
}
-
return status;
}
@@ -123,9 +121,6 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
enum ixgbe_phy_type phy_type;
switch (phy_id) {
- case TN1010_PHY_ID:
- phy_type = ixgbe_phy_tn;
- break;
case QT2022_PHY_ID:
phy_type = ixgbe_phy_qt;
break;
@@ -138,32 +133,31 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
}
/**
- * ixgbe_reset_phy - Performs a PHY reset
+ * ixgbe_reset_phy_generic - Performs a PHY reset
* @hw: pointer to hardware structure
**/
-s32 ixgbe_reset_phy(struct ixgbe_hw *hw)
+s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
{
/*
* Perform soft PHY reset to the PHY_XS.
* This will cause a soft reset to the PHY
*/
- return ixgbe_write_phy_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
- IXGBE_MDIO_PHY_XS_DEV_TYPE,
- IXGBE_MDIO_PHY_XS_RESET);
+ return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE,
+ IXGBE_MDIO_PHY_XS_RESET);
}
/**
- * ixgbe_read_phy_reg - Reads a value from a specified PHY register
+ * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register
* @hw: pointer to hardware structure
* @reg_addr: 32 bit address of PHY register to read
* @phy_data: Pointer to read data from PHY register
**/
-s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
- u32 device_type, u16 *phy_data)
+s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 *phy_data)
{
u32 command;
u32 i;
- u32 timeout = 10;
u32 data;
s32 status = 0;
u16 gssr;
@@ -179,9 +173,9 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
if (status == 0) {
/* Setup and write the address cycle command */
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
- (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
- (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
+ (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -190,7 +184,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* The MDI Command bit will clear when the operation is
* complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
udelay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -210,9 +204,9 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* command
*/
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
- (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
- (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
+ (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -221,7 +215,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* completed. The MDI Command bit will clear when the
* operation is complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
udelay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -231,8 +225,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
- hw_dbg(hw,
- "PHY read command didn't complete\n");
+ hw_dbg(hw, "PHY read command didn't complete\n");
status = IXGBE_ERR_PHY;
} else {
/*
@@ -247,22 +240,22 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
ixgbe_release_swfw_sync(hw, gssr);
}
+
return status;
}
/**
- * ixgbe_write_phy_reg - Writes a value to specified PHY register
+ * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register
* @hw: pointer to hardware structure
* @reg_addr: 32 bit PHY register to write
* @device_type: 5 bit device type
* @phy_data: Data to write to the PHY register
**/
-static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
- u32 device_type, u16 phy_data)
+s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 phy_data)
{
u32 command;
u32 i;
- u32 timeout = 10;
s32 status = 0;
u16 gssr;
@@ -280,9 +273,9 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
/* Setup and write the address cycle command */
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
- (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
- (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
+ (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -291,19 +284,19 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* The MDI Command bit will clear when the operation is
* complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
udelay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
- if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
- hw_dbg(hw, "PHY address cmd didn't complete\n");
+ if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
break;
- }
}
- if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
+ if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+ hw_dbg(hw, "PHY address cmd didn't complete\n");
status = IXGBE_ERR_PHY;
+ }
if (status == 0) {
/*
@@ -311,9 +304,9 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* command
*/
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
- (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
- (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
+ (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -322,20 +315,19 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
* completed. The MDI Command bit will clear when the
* operation is complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
udelay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
- if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
- hw_dbg(hw, "PHY write command did not "
- "complete.\n");
+ if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
break;
- }
}
- if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
+ if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
+ hw_dbg(hw, "PHY address cmd didn't complete\n");
status = IXGBE_ERR_PHY;
+ }
}
ixgbe_release_swfw_sync(hw, gssr);
@@ -345,67 +337,54 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
}
/**
- * ixgbe_setup_tnx_phy_link - Set and restart autoneg
+ * ixgbe_setup_phy_link_generic - Set and restart autoneg
* @hw: pointer to hardware structure
*
* Restart autonegotiation and PHY and waits for completion.
**/
-s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw)
+s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_NOT_IMPLEMENTED;
u32 time_out;
u32 max_time_out = 10;
- u16 autoneg_speed_selection_register = 0x10;
- u16 autoneg_restart_mask = 0x0200;
- u16 autoneg_complete_mask = 0x0020;
- u16 autoneg_reg = 0;
+ u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
/*
* Set advertisement settings in PHY based on autoneg_advertised
* settings. If autoneg_advertised = 0, then advertise default values
- * txn devices cannot be "forced" to a autoneg 10G and fail. But can
+ * tnx devices cannot be "forced" to a autoneg 10G and fail. But can
* for a 1G.
*/
- ixgbe_read_phy_reg(hw,
- autoneg_speed_selection_register,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */
else
autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */
- ixgbe_write_phy_reg(hw,
- autoneg_speed_selection_register,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
-
+ hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
/* Restart PHY autonegotiation and wait for completion */
- ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_CONTROL,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
- autoneg_reg |= autoneg_restart_mask;
+ autoneg_reg |= IXGBE_MII_RESTART;
- ixgbe_write_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_CONTROL,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
+ hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
/* Wait for autonegotiation to finish */
for (time_out = 0; time_out < max_time_out; time_out++) {
udelay(10);
/* Restart PHY autonegotiation and wait for completion */
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
- autoneg_reg &= autoneg_complete_mask;
- if (autoneg_reg == autoneg_complete_mask) {
+ autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
+ if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
status = 0;
break;
}
@@ -418,64 +397,17 @@ s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw)
}
/**
- * ixgbe_check_tnx_phy_link - Determine link and speed status
- * @hw: pointer to hardware structure
- *
- * Reads the VS1 register to determine if link is up and the current speed for
- * the PHY.
- **/
-s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, u32 *speed,
- bool *link_up)
-{
- s32 status = 0;
- u32 time_out;
- u32 max_time_out = 10;
- u16 phy_link = 0;
- u16 phy_speed = 0;
- u16 phy_data = 0;
-
- /* Initialize speed and link to default case */
- *link_up = false;
- *speed = IXGBE_LINK_SPEED_10GB_FULL;
-
- /*
- * Check current speed and link status of the PHY register.
- * This is a vendor specific register and may have to
- * be changed for other copper PHYs.
- */
- for (time_out = 0; time_out < max_time_out; time_out++) {
- udelay(10);
- if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
- *link_up = true;
- if (phy_speed ==
- IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
- *speed = IXGBE_LINK_SPEED_1GB_FULL;
- break;
- } else {
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- &phy_data);
- phy_link = phy_data &
- IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
- phy_speed = phy_data &
- IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
- }
- }
-
- return status;
-}
-
-/**
- * ixgbe_setup_tnx_phy_link_speed - Sets the auto advertised capabilities
+ * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: true if autonegotiation enabled
**/
-s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed,
- bool autoneg,
- bool autoneg_wait_to_complete)
+s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete)
{
+
/*
* Clear autoneg_advertised and set new values based on input link
* speed.
@@ -484,11 +416,13 @@ s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed,
if (speed & IXGBE_LINK_SPEED_10GB_FULL)
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
if (speed & IXGBE_LINK_SPEED_1GB_FULL)
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
/* Setup link based on the new speed settings */
- ixgbe_setup_tnx_phy_link(hw);
+ hw->phy.ops.setup_link(hw);
return 0;
}
+
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h
index aa3ea72e678..9bfe3f2b1d8 100644
--- a/drivers/net/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ixgbe/ixgbe_phy.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -30,20 +29,52 @@
#define _IXGBE_PHY_H_
#include "ixgbe_type.h"
+#define IXGBE_I2C_EEPROM_DEV_ADDR 0xA0
-s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw);
-s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, u32 *speed, bool *link_up);
-s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, u32 speed, bool autoneg,
- bool autoneg_wait_to_complete);
-s32 ixgbe_identify_phy(struct ixgbe_hw *hw);
-s32 ixgbe_reset_phy(struct ixgbe_hw *hw);
-s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr,
- u32 device_type, u16 *phy_data);
-
-/* PHY specific */
-s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw);
-s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, u32 *speed, bool *link_up);
-s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, bool autoneg,
- bool autoneg_wait_to_complete);
+/* EEPROM byte offsets */
+#define IXGBE_SFF_IDENTIFIER 0x0
+#define IXGBE_SFF_IDENTIFIER_SFP 0x3
+#define IXGBE_SFF_VENDOR_OUI_BYTE0 0x25
+#define IXGBE_SFF_VENDOR_OUI_BYTE1 0x26
+#define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27
+#define IXGBE_SFF_1GBE_COMP_CODES 0x6
+#define IXGBE_SFF_10GBE_COMP_CODES 0x3
+#define IXGBE_SFF_TRANSMISSION_MEDIA 0x9
+
+/* Bitmasks */
+#define IXGBE_SFF_TWIN_AX_CAPABLE 0x80
+#define IXGBE_SFF_1GBASESX_CAPABLE 0x1
+#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
+#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
+#define IXGBE_I2C_EEPROM_READ_MASK 0x100
+#define IXGBE_I2C_EEPROM_STATUS_MASK 0x3
+#define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0
+#define IXGBE_I2C_EEPROM_STATUS_PASS 0x1
+#define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2
+#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3
+
+/* Bit-shift macros */
+#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 12
+#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 8
+#define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 4
+
+/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
+#define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600
+#define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500
+#define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00
+
+
+s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
+s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
+s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw);
+s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 *phy_data);
+s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 phy_data);
+s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw);
+s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete);
#endif /* _IXGBE_PHY_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index c0282a223df..c6f8fa1c4e5 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2007 Intel Corporation.
+ Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,6 @@
the file called "COPYING".
Contact Information:
- Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -37,9 +36,9 @@
/* Device IDs */
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
-#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
+#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
/* General Registers */
#define IXGBE_CTRL 0x00000
@@ -70,11 +69,11 @@
#define IXGBE_EIMC 0x00888
#define IXGBE_EIAC 0x00810
#define IXGBE_EIAM 0x00890
-#define IXGBE_EITR(_i) (0x00820 + ((_i) * 4)) /* 0x820-0x86c */
-#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */
+#define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : (0x012300 + ((_i) * 4)))
+#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */
#define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */
#define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */
-#define IXGBE_PBACL 0x11068
+#define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4)))
#define IXGBE_GPIE 0x00898
/* Flow Control Registers */
@@ -86,20 +85,33 @@
#define IXGBE_TFCS 0x0CE00
/* Receive DMA Registers */
-#define IXGBE_RDBAL(_i) (0x01000 + ((_i) * 0x40)) /* 64 of each (0-63)*/
-#define IXGBE_RDBAH(_i) (0x01004 + ((_i) * 0x40))
-#define IXGBE_RDLEN(_i) (0x01008 + ((_i) * 0x40))
-#define IXGBE_RDH(_i) (0x01010 + ((_i) * 0x40))
-#define IXGBE_RDT(_i) (0x01018 + ((_i) * 0x40))
-#define IXGBE_RXDCTL(_i) (0x01028 + ((_i) * 0x40))
-#define IXGBE_RSCCTL(_i) (0x0102C + ((_i) * 0x40))
-#define IXGBE_SRRCTL(_i) (0x02100 + ((_i) * 4))
- /* array of 16 (0x02100-0x0213C) */
-#define IXGBE_DCA_RXCTRL(_i) (0x02200 + ((_i) * 4))
- /* array of 16 (0x02200-0x0223C) */
-#define IXGBE_RDRXCTL 0x02F00
+#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : (0x0D000 + ((_i - 64) * 0x40)))
+#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : (0x0D004 + ((_i - 64) * 0x40)))
+#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : (0x0D008 + ((_i - 64) * 0x40)))
+#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : (0x0D010 + ((_i - 64) * 0x40)))
+#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : (0x0D018 + ((_i - 64) * 0x40)))
+#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : (0x0D028 + ((_i - 64) * 0x40)))
+/*
+ * Split and Replication Receive Control Registers
+ * 00-15 : 0x02100 + n*4
+ * 16-64 : 0x01014 + n*0x40
+ * 64-127: 0x0D014 + (n-64)*0x40
+ */
+#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
+ (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
+ (0x0D014 + ((_i - 64) * 0x40))))
+/*
+ * Rx DCA Control Register:
+ * 00-15 : 0x02200 + n*4
+ * 16-64 : 0x0100C + n*0x40
+ * 64-127: 0x0D00C + (n-64)*0x40
+ */
+#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
+ (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
+ (0x0D00C + ((_i - 64) * 0x40))))
+#define IXGBE_RDRXCTL 0x02F00
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
- /* 8 of these 0x03C00 - 0x03C1C */
+ /* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_RXCTRL 0x03000
#define IXGBE_DROPEN 0x03D04
#define IXGBE_RXPBSIZE_SHIFT 10
@@ -107,29 +119,32 @@
/* Receive Registers */
#define IXGBE_RXCSUM 0x05000
#define IXGBE_RFCTL 0x05008
+#define IXGBE_DRECCCTL 0x02F08
+#define IXGBE_DRECCCTL_DISABLE 0
+/* Multicast Table Array - 128 entries */
#define IXGBE_MTA(_i) (0x05200 + ((_i) * 4))
- /* Multicast Table Array - 128 entries */
-#define IXGBE_RAL(_i) (0x05400 + ((_i) * 8)) /* 16 of these (0-15) */
-#define IXGBE_RAH(_i) (0x05404 + ((_i) * 8)) /* 16 of these (0-15) */
-#define IXGBE_PSRTYPE 0x05480
- /* 0x5480-0x54BC Packet split receive type */
+#define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x0A200 + ((_i) * 8)))
+#define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x0A204 + ((_i) * 8)))
+/* Packet split receive type */
+#define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : (0x0EA00 + ((_i) * 4)))
+/* array of 4096 1-bit vlan filters */
#define IXGBE_VFTA(_i) (0x0A000 + ((_i) * 4))
- /* array of 4096 1-bit vlan filters */
+/*array of 4096 4-bit vlan vmdq indices */
#define IXGBE_VFTAVIND(_j, _i) (0x0A200 + ((_j) * 0x200) + ((_i) * 4))
- /*array of 4096 4-bit vlan vmdq indicies */
#define IXGBE_FCTRL 0x05080
#define IXGBE_VLNCTRL 0x05088
#define IXGBE_MCSTCTRL 0x05090
#define IXGBE_MRQC 0x05818
-#define IXGBE_VMD_CTL 0x0581C
#define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIRVP 0x05AC0
+#define IXGBE_VMD_CTL 0x0581C
#define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */
#define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */
+
/* Transmit DMA registers */
-#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40))/* 32 of these (0-31)*/
+#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/
#define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40))
#define IXGBE_TDLEN(_i) (0x06008 + ((_i) * 0x40))
#define IXGBE_TDH(_i) (0x06010 + ((_i) * 0x40))
@@ -138,11 +153,10 @@
#define IXGBE_TDWBAL(_i) (0x06038 + ((_i) * 0x40))
#define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40))
#define IXGBE_DTXCTL 0x07E00
-#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4))
- /* there are 16 of these (0-15) */
+
+#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
#define IXGBE_TIPG 0x0CB00
-#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) *0x04))
- /* there are 8 of these */
+#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) * 4)) /* 8 of these */
#define IXGBE_MNGTXMAP 0x0CD10
#define IXGBE_TIPG_FIBER_DEFAULT 3
#define IXGBE_TXPBSIZE_SHIFT 10
@@ -154,6 +168,7 @@
#define IXGBE_IPAV 0x05838
#define IXGBE_IP4AT 0x05840 /* IPv4 table 0x5840-0x5858 */
#define IXGBE_IP6AT 0x05880 /* IPv6 table 0x5880-0x588F */
+
#define IXGBE_WUPL 0x05900
#define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */
#define IXGBE_FHFT 0x09000 /* Flex host filter table 9000-93FC */
@@ -170,6 +185,8 @@
#define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */
+
+
/* Stats registers */
#define IXGBE_CRCERRS 0x04000
#define IXGBE_ILLERRC 0x04004
@@ -224,7 +241,7 @@
#define IXGBE_XEC 0x04120
#define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4)) /* 16 of these */
-#define IXGBE_TQSMR(_i) (0x07300 + ((_i) * 4)) /* 8 of these */
+#define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : (0x08600 + ((_i) * 4)))
#define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
@@ -275,23 +292,17 @@
#define IXGBE_DCA_CTRL 0x11074
/* Diagnostic Registers */
-#define IXGBE_RDSTATCTL 0x02C20
-#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */
-#define IXGBE_RDHMPN 0x02F08
-#define IXGBE_RIC_DW0 0x02F10
-#define IXGBE_RIC_DW1 0x02F14
-#define IXGBE_RIC_DW2 0x02F18
-#define IXGBE_RIC_DW3 0x02F1C
-#define IXGBE_RDPROBE 0x02F20
-#define IXGBE_TDSTATCTL 0x07C20
-#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */
-#define IXGBE_TDHMPN 0x07F08
-#define IXGBE_TIC_DW0 0x07F10
-#define IXGBE_TIC_DW1 0x07F14
-#define IXGBE_TIC_DW2 0x07F18
-#define IXGBE_TIC_DW3 0x07F1C
-#define IXGBE_TDPROBE 0x07F20
-#define IXGBE_TXBUFCTRL 0x0C600
+#define IXGBE_RDSTATCTL 0x02C20
+#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */
+#define IXGBE_RDHMPN 0x02F08
+#define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4))
+#define IXGBE_RDPROBE 0x02F20
+#define IXGBE_TDSTATCTL 0x07C20
+#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */
+#define IXGBE_TDHMPN 0x07F08
+#define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4))
+#define IXGBE_TDPROBE 0x07F20
+#define IXGBE_TXBUFCTRL 0x0C600
#define IXGBE_TXBUFDATA0 0x0C610
#define IXGBE_TXBUFDATA1 0x0C614
#define IXGBE_TXBUFDATA2 0x0C618
@@ -356,12 +367,10 @@
#define IXGBE_ANLP2 0x042B4
#define IXGBE_ATLASCTL 0x04800
-/* RSCCTL Bit Masks */
-#define IXGBE_RSCCTL_RSCEN 0x01
-#define IXGBE_RSCCTL_MAXDESC_1 0x00
-#define IXGBE_RSCCTL_MAXDESC_4 0x04
-#define IXGBE_RSCCTL_MAXDESC_8 0x08
-#define IXGBE_RSCCTL_MAXDESC_16 0x0C
+/* RDRXCTL Bit Masks */
+#define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min Threshold Size */
+#define IXGBE_RDRXCTL_MVMEN 0x00000020
+#define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */
/* CTRL Bit Masks */
#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
@@ -394,7 +403,7 @@
#define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
-#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */
+#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
#define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */
/* MSCA Bit Masks */
@@ -418,10 +427,10 @@
#define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress enable */
/* MSRWD bit masks */
-#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF
-#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0
-#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000
-#define IXGBE_MSRWD_READ_DATA_SHIFT 16
+#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF
+#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0
+#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000
+#define IXGBE_MSRWD_READ_DATA_SHIFT 16
/* Atlas registers */
#define IXGBE_ATLAS_PDN_LPBK 0x24
@@ -436,6 +445,7 @@
#define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0
#define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0
+
/* Device Type definitions for new protocol MDIO commands */
#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
#define IXGBE_MDIO_PCS_DEV_TYPE 0x3
@@ -443,6 +453,8 @@
#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
+#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
+
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */
@@ -456,23 +468,39 @@
#define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */
#define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/
#define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/
-#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Abilty Reg */
+#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */
#define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */
#define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */
+#define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Address Reg */
+#define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */
+#define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */
+
+/* MII clause 22/28 definitions */
+#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800
+
+#define IXGBE_MII_SPEED_SELECTION_REG 0x10
+#define IXGBE_MII_RESTART 0x200
+#define IXGBE_MII_AUTONEG_COMPLETE 0x20
+#define IXGBE_MII_AUTONEG_REG 0x0
+
#define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0
#define IXGBE_MAX_PHY_ADDR 32
/* PHY IDs*/
-#define TN1010_PHY_ID 0x00A19410
#define QT2022_PHY_ID 0x0043A400
+/* PHY Types */
+#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
+
/* General purpose Interrupt Enable */
-#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */
-#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */
-#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
-#define IXGBE_GPIE_EIAME 0x40000000
-#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
+#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */
+#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */
+#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */
+#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */
+#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
+#define IXGBE_GPIE_EIAME 0x40000000
+#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
/* Transmit Flow Control status */
#define IXGBE_TFCS_TXOFF 0x00000001
@@ -533,7 +561,7 @@
#define IXGBE_PAP_TXPAUSECNT_MASK 0x0000FFFF /* Pause counter mask */
/* RMCS Bit Masks */
-#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recylce Mode enable */
+#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recycle Mode enable */
/* Receive Arbitration Control: 0 Round Robin, 1 DFP */
#define IXGBE_RMCS_RAC 0x00000004
#define IXGBE_RMCS_DFP IXGBE_RMCS_RAC /* Deficit Fixed Priority ena */
@@ -541,12 +569,15 @@
#define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority flow control ena */
#define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */
+
/* Interrupt register bitmasks */
/* Extended Interrupt Cause Read */
#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */
#define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */
-#define IXGBE_EICR_MNG 0x00400000 /* Managability Event Interrupt */
+#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
+#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
+#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */
#define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */
#define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
@@ -554,11 +585,12 @@
/* Extended Interrupt Cause Set */
#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
-#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
-#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
-#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
-#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
-#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */
+#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
+#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
+#define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
+#define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
+#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */
#define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
#define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */
@@ -566,7 +598,9 @@
#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
-#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
+#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
+#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
#define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */
#define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
#define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */
@@ -575,18 +609,20 @@
#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
#define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
-#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
-#define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Error */
+#define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
+#define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
+#define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */
#define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
#define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */
-#define IXGBE_EIMS_ENABLE_MASK (\
- IXGBE_EIMS_RTX_QUEUE | \
- IXGBE_EIMS_LSC | \
- IXGBE_EIMS_TCP_TIMER | \
- IXGBE_EIMS_OTHER)
+#define IXGBE_EIMS_ENABLE_MASK ( \
+ IXGBE_EIMS_RTX_QUEUE | \
+ IXGBE_EIMS_LSC | \
+ IXGBE_EIMS_TCP_TIMER | \
+ IXGBE_EIMS_OTHER)
-/* Immediate Interrupt RX (A.K.A. Low Latency Interrupt) */
+/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
#define IXGBE_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */
#define IXGBE_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */
#define IXGBE_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
@@ -623,6 +659,7 @@
#define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */
#define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */
+
#define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */
/* STATUS Bit Masks */
@@ -670,16 +707,16 @@
#define IXGBE_AUTOC_AN_RESTART 0x00001000
#define IXGBE_AUTOC_FLU 0x00000001
#define IXGBE_AUTOC_LMS_SHIFT 13
-#define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT)
-#define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
-
-#define IXGBE_AUTOC_1G_PMA_PMD 0x00000200
-#define IXGBE_AUTOC_10G_PMA_PMD 0x00000180
+#define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
+
+#define IXGBE_AUTOC_1G_PMA_PMD 0x00000200
+#define IXGBE_AUTOC_10G_PMA_PMD 0x00000180
#define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7
#define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9
#define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
@@ -705,6 +742,7 @@
#define IXGBE_LINKS_TL_FAULT 0x00001000
#define IXGBE_LINKS_SIGNAL 0x00000F00
+#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
/* SW Semaphore Register bitmasks */
@@ -759,6 +797,11 @@
#define IXGBE_PBANUM0_PTR 0x15
#define IXGBE_PBANUM1_PTR 0x16
+/* Legacy EEPROM word offsets */
+#define IXGBE_ISCSI_BOOT_CAPS 0x0033
+#define IXGBE_ISCSI_SETUP_PORT_0 0x0030
+#define IXGBE_ISCSI_SETUP_PORT_1 0x0034
+
/* EEPROM Commands - SPI */
#define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */
#define IXGBE_EEPROM_STATUS_RDY_SPI 0x01
@@ -766,7 +809,7 @@
#define IXGBE_EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
#define IXGBE_EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = addr bit-8 */
#define IXGBE_EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Ena latch */
-/* EEPROM reset Write Enbale latch */
+/* EEPROM reset Write Enable latch */
#define IXGBE_EEPROM_WRDI_OPCODE_SPI 0x04
#define IXGBE_EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status reg */
#define IXGBE_EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status reg */
@@ -805,26 +848,20 @@
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
-/* PHY Types */
-#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
-
/* Check whether address is multicast. This is little-endian specific check.*/
#define IXGBE_IS_MULTICAST(Address) \
- (bool)(((u8 *)(Address))[0] & ((u8)0x01))
+ (bool)(((u8 *)(Address))[0] & ((u8)0x01))
/* Check whether an address is broadcast. */
#define IXGBE_IS_BROADCAST(Address) \
- ((((u8 *)(Address))[0] == ((u8)0xff)) && \
- (((u8 *)(Address))[1] == ((u8)0xff)))
+ ((((u8 *)(Address))[0] == ((u8)0xff)) && \
+ (((u8 *)(Address))[1] == ((u8)0xff)))
/* RAH */
#define IXGBE_RAH_VIND_MASK 0x003C0000
#define IXGBE_RAH_VIND_SHIFT 18
#define IXGBE_RAH_AV 0x80000000
-
-/* Filters */
-#define IXGBE_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
-#define IXGBE_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+#define IXGBE_CLEAR_VMDQ_ALL 0xFFFFFFFF
/* Header split receive */
#define IXGBE_RFCTL_ISCSI_DIS 0x00000001
@@ -853,7 +890,7 @@
#define IXGBE_MAX_FRAME_SZ 0x40040000
#define IXGBE_TDWBAL_HEAD_WB_ENABLE 0x1 /* Tx head write-back enable */
-#define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq. # write-back enable */
+#define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq# write-back enable */
/* Receive Config masks */
#define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */
@@ -866,7 +903,7 @@
#define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */
#define IXGBE_FCTRL_PMCF 0x00001000 /* Pass MAC Control Frames */
#define IXGBE_FCTRL_DPF 0x00002000 /* Discard Pause Frame */
-/* Receive Priority Flow Control Enbale */
+/* Receive Priority Flow Control Enable */
#define IXGBE_FCTRL_RPFCE 0x00004000
#define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */
@@ -896,9 +933,8 @@
/* Receive Descriptor bit definitions */
#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */
#define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */
-#define IXGBE_RXD_STAT_IXSM 0x04 /* Ignore checksum */
#define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
-#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
+#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
#define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */
#define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
#define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */
@@ -914,7 +950,7 @@
#define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */
#define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */
#define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */
-#define IXGBE_RXDADV_HBO 0x00800000
+#define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */
#define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */
#define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */
#define IXGBE_RXDADV_ERR_PE 0x08000000 /* Packet Error */
@@ -928,15 +964,17 @@
#define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */
#define IXGBE_RXD_CFI_SHIFT 12
+
/* SRRCTL bit definitions */
-#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
-#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F
-#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00
-#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000
+#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
+#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F
+#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00
+#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
+#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000
#define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000
#define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
@@ -970,21 +1008,20 @@
#define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
#define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
#define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
-
/* Masks to determine if packets should be dropped due to frame errors */
-#define IXGBE_RXD_ERR_FRAME_ERR_MASK (\
- IXGBE_RXD_ERR_CE | \
- IXGBE_RXD_ERR_LE | \
- IXGBE_RXD_ERR_PE | \
- IXGBE_RXD_ERR_OSE | \
- IXGBE_RXD_ERR_USE)
-
-#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK (\
- IXGBE_RXDADV_ERR_CE | \
- IXGBE_RXDADV_ERR_LE | \
- IXGBE_RXDADV_ERR_PE | \
- IXGBE_RXDADV_ERR_OSE | \
- IXGBE_RXDADV_ERR_USE)
+#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \
+ IXGBE_RXD_ERR_CE | \
+ IXGBE_RXD_ERR_LE | \
+ IXGBE_RXD_ERR_PE | \
+ IXGBE_RXD_ERR_OSE | \
+ IXGBE_RXD_ERR_USE)
+
+#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \
+ IXGBE_RXDADV_ERR_CE | \
+ IXGBE_RXDADV_ERR_LE | \
+ IXGBE_RXDADV_ERR_PE | \
+ IXGBE_RXDADV_ERR_OSE | \
+ IXGBE_RXDADV_ERR_USE)
/* Multicast bit mask */
#define IXGBE_MCSTCTRL_MFE 0x4
@@ -1000,6 +1037,7 @@
#define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */
#define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT
+
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
u64 buffer_addr; /* Address of the descriptor's data buffer */
@@ -1007,15 +1045,15 @@ struct ixgbe_legacy_tx_desc {
__le32 data;
struct {
__le16 length; /* Data buffer length */
- u8 cso; /* Checksum offset */
- u8 cmd; /* Descriptor control */
+ u8 cso; /* Checksum offset */
+ u8 cmd; /* Descriptor control */
} flags;
} lower;
union {
__le32 data;
struct {
- u8 status; /* Descriptor status */
- u8 css; /* Checksum start */
+ u8 status; /* Descriptor status */
+ u8 css; /* Checksum start */
__le16 vlan;
} fields;
} upper;
@@ -1024,7 +1062,7 @@ struct ixgbe_legacy_tx_desc {
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
- __le64 buffer_addr; /* Address of descriptor's data buf */
+ __le64 buffer_addr; /* Address of descriptor's data buf */
__le32 cmd_type_len;
__le32 olinfo_status;
} read;
@@ -1039,9 +1077,9 @@ union ixgbe_adv_tx_desc {
struct ixgbe_legacy_rx_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
__le16 length; /* Length of data DMAed into data buffer */
- u16 csum; /* Packet checksum */
- u8 status; /* Descriptor status */
- u8 errors; /* Descriptor Errors */
+ __le16 csum; /* Packet checksum */
+ u8 status; /* Descriptor status */
+ u8 errors; /* Descriptor Errors */
__le16 vlan;
};
@@ -1053,15 +1091,18 @@ union ixgbe_adv_rx_desc {
} read;
struct {
struct {
- struct {
- __le16 pkt_info; /* RSS type, Packet type */
- __le16 hdr_info; /* Split Header, header len */
+ union {
+ __le32 data;
+ struct {
+ __le16 pkt_info; /* RSS, Pkt type */
+ __le16 hdr_info; /* Splithdr, hdrlen */
+ } hs_rss;
} lo_dword;
union {
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
- u16 csum; /* Packet Checksum */
+ __le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
@@ -1082,49 +1123,69 @@ struct ixgbe_adv_tx_context_desc {
};
/* Adv Transmit Descriptor Config Masks */
-#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buffer length(bytes) */
+#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */
#define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */
#define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Desc */
#define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */
#define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */
-#define IXGBE_ADVTXD_DCMD_RDMA 0x04000000 /* RDMA */
#define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */
-#define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
+#define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
#define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext (1=Adv) */
#define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE /* VLAN pkt enable */
#define IXGBE_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD /* Descriptor Done */
-#define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */
+#define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED pres in WB */
#define IXGBE_ADVTXD_STAT_RSV 0x0000000C /* STA Reserved */
#define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
+#define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */
#define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */
#define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \
- IXGBE_ADVTXD_POPTS_SHIFT)
+ IXGBE_ADVTXD_POPTS_SHIFT)
#define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \
- IXGBE_ADVTXD_POPTS_SHIFT)
-#define IXGBE_ADVTXD_POPTS_EOM 0x00000400 /* Enable L bit-RDMA DDP hdr */
-#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
-#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
-#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
-#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/
-#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */
-#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
-#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
-#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
-#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
-#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
-#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
-#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
-#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */
-#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
-#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
-
+ IXGBE_ADVTXD_POPTS_SHIFT)
+#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
+#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
+#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
+#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU */
+#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */
+#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
+#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
+#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
+#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
+#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
+#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
+#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
+#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
+#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /*Req requires Markers and CRC*/
+#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
+#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
+
+/* Autonegotiation advertised speeds */
+typedef u32 ixgbe_autoneg_advertised;
/* Link speed */
+typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_UNKNOWN 0
#define IXGBE_LINK_SPEED_100_FULL 0x0008
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
+#define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \
+ IXGBE_LINK_SPEED_10GB_FULL)
+
+/* Physical layer type */
+typedef u32 ixgbe_physical_layer;
+#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0
+#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001
+#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002
+#define IXGBE_PHYSICAL_LAYER_100BASE_T 0x0004
+#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020
+#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080
+#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100
+#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200
+#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400
enum ixgbe_eeprom_type {
@@ -1141,16 +1202,38 @@ enum ixgbe_mac_type {
enum ixgbe_phy_type {
ixgbe_phy_unknown = 0,
- ixgbe_phy_tn,
ixgbe_phy_qt,
- ixgbe_phy_xaui
+ ixgbe_phy_xaui,
+ ixgbe_phy_tw_tyco,
+ ixgbe_phy_tw_unknown,
+ ixgbe_phy_sfp_avago,
+ ixgbe_phy_sfp_ftl,
+ ixgbe_phy_sfp_unknown,
+ ixgbe_phy_generic
+};
+
+/*
+ * SFP+ module type IDs:
+ *
+ * ID Module Type
+ * =============
+ * 0 SFP_DA_CU
+ * 1 SFP_SR
+ * 2 SFP_LR
+ */
+enum ixgbe_sfp_type {
+ ixgbe_sfp_type_da_cu = 0,
+ ixgbe_sfp_type_sr = 1,
+ ixgbe_sfp_type_lr = 2,
+ ixgbe_sfp_type_unknown = 0xFFFF
};
enum ixgbe_media_type {
ixgbe_media_type_unknown = 0,
ixgbe_media_type_fiber,
ixgbe_media_type_copper,
- ixgbe_media_type_backplane
+ ixgbe_media_type_backplane,
+ ixgbe_media_type_virtual
};
/* Flow Control Settings */
@@ -1167,6 +1250,8 @@ struct ixgbe_addr_filter_info {
u32 rar_used_count;
u32 mc_addr_in_rar_count;
u32 mta_in_use;
+ u32 overflow_promisc;
+ bool user_set_promisc;
};
/* Flow control parameters */
@@ -1242,57 +1327,118 @@ struct ixgbe_hw_stats {
/* forward declaration */
struct ixgbe_hw;
+/* iterator type for walking multicast address lists */
+typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr,
+ u32 *vmdq);
+
+/* Function pointer table */
+struct ixgbe_eeprom_operations {
+ s32 (*init_params)(struct ixgbe_hw *);
+ s32 (*read)(struct ixgbe_hw *, u16, u16 *);
+ s32 (*write)(struct ixgbe_hw *, u16, u16);
+ s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
+ s32 (*update_checksum)(struct ixgbe_hw *);
+};
+
struct ixgbe_mac_operations {
- s32 (*reset)(struct ixgbe_hw *);
+ s32 (*init_hw)(struct ixgbe_hw *);
+ s32 (*reset_hw)(struct ixgbe_hw *);
+ s32 (*start_hw)(struct ixgbe_hw *);
+ s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
+ s32 (*get_supported_physical_layer)(struct ixgbe_hw *);
+ s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
+ s32 (*stop_adapter)(struct ixgbe_hw *);
+ s32 (*get_bus_info)(struct ixgbe_hw *);
+ s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*);
+ s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8);
+
+ /* Link */
s32 (*setup_link)(struct ixgbe_hw *);
- s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *);
- s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool);
- s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *);
+ s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
+ bool);
+ s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
+ s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
+ bool *);
+
+ /* LED */
+ s32 (*led_on)(struct ixgbe_hw *, u32);
+ s32 (*led_off)(struct ixgbe_hw *, u32);
+ s32 (*blink_led_start)(struct ixgbe_hw *, u32);
+ s32 (*blink_led_stop)(struct ixgbe_hw *, u32);
+
+ /* RAR, Multicast, VLAN */
+ s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
+ s32 (*clear_rar)(struct ixgbe_hw *, u32);
+ s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32);
+ s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32);
+ s32 (*init_rx_addrs)(struct ixgbe_hw *);
+ s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32,
+ ixgbe_mc_addr_itr);
+ s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32,
+ ixgbe_mc_addr_itr);
+ s32 (*enable_mc)(struct ixgbe_hw *);
+ s32 (*disable_mc)(struct ixgbe_hw *);
+ s32 (*clear_vfta)(struct ixgbe_hw *);
+ s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
+ s32 (*init_uta_tables)(struct ixgbe_hw *);
+
+ /* Flow Control */
+ s32 (*setup_fc)(struct ixgbe_hw *, s32);
};
struct ixgbe_phy_operations {
+ s32 (*identify)(struct ixgbe_hw *);
+ s32 (*identify_sfp)(struct ixgbe_hw *);
+ s32 (*reset)(struct ixgbe_hw *);
+ s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *);
+ s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16);
s32 (*setup_link)(struct ixgbe_hw *);
- s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *);
- s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool);
-};
-
-struct ixgbe_mac_info {
- struct ixgbe_mac_operations ops;
- enum ixgbe_mac_type type;
- u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
- u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
- s32 mc_filter_type;
- u32 num_rx_queues;
- u32 num_tx_queues;
- u32 num_rx_addrs;
- u32 link_attach_type;
- u32 link_mode_select;
- bool link_settings_loaded;
+ s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
+ bool);
+ s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *);
+ s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8);
+ s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
+ s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
};
struct ixgbe_eeprom_info {
- enum ixgbe_eeprom_type type;
- u16 word_size;
- u16 address_bits;
+ struct ixgbe_eeprom_operations ops;
+ enum ixgbe_eeprom_type type;
+ u32 semaphore_delay;
+ u16 word_size;
+ u16 address_bits;
};
-struct ixgbe_phy_info {
- struct ixgbe_phy_operations ops;
-
- enum ixgbe_phy_type type;
- u32 addr;
- u32 id;
- u32 revision;
- enum ixgbe_media_type media_type;
- u32 autoneg_advertised;
- bool autoneg_wait_to_complete;
+struct ixgbe_mac_info {
+ struct ixgbe_mac_operations ops;
+ enum ixgbe_mac_type type;
+ u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
+ u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
+ s32 mc_filter_type;
+ u32 mcft_size;
+ u32 vft_size;
+ u32 num_rar_entries;
+ u32 max_tx_queues;
+ u32 max_rx_queues;
+ u32 link_attach_type;
+ u32 link_mode_select;
+ bool link_settings_loaded;
+ bool autoneg;
+ bool autoneg_failed;
};
-struct ixgbe_info {
- enum ixgbe_mac_type mac;
- s32 (*get_invariants)(struct ixgbe_hw *);
- struct ixgbe_mac_operations *mac_ops;
+struct ixgbe_phy_info {
+ struct ixgbe_phy_operations ops;
+ enum ixgbe_phy_type type;
+ u32 addr;
+ u32 id;
+ enum ixgbe_sfp_type sfp_type;
+ u32 revision;
+ enum ixgbe_media_type media_type;
+ bool reset_disable;
+ ixgbe_autoneg_advertised autoneg_advertised;
+ bool autoneg_wait_to_complete;
};
struct ixgbe_hw {
@@ -1311,6 +1457,15 @@ struct ixgbe_hw {
bool adapter_stopped;
};
+struct ixgbe_info {
+ enum ixgbe_mac_type mac;
+ s32 (*get_invariants)(struct ixgbe_hw *);
+ struct ixgbe_mac_operations *mac_ops;
+ struct ixgbe_eeprom_operations *eeprom_ops;
+ struct ixgbe_phy_operations *phy_ops;
+};
+
+
/* Error Codes */
#define IXGBE_ERR_EEPROM -1
#define IXGBE_ERR_EEPROM_CHECKSUM -2
@@ -1329,6 +1484,8 @@ struct ixgbe_hw {
#define IXGBE_ERR_RESET_FAILED -15
#define IXGBE_ERR_SWFW_SYNC -16
#define IXGBE_ERR_PHY_ADDR_INVALID -17
+#define IXGBE_ERR_I2C -18
+#define IXGBE_ERR_SFP_NOT_SUPPORTED -19
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
new file mode 100644
index 00000000000..81c6cdc3851
--- /dev/null
+++ b/drivers/net/jme.c
@@ -0,0 +1,3038 @@
+/*
+ * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver
+ *
+ * Copyright 2008 JMicron Technology Corporation
+ * http://www.jmicron.com/
+ *
+ * Author: Guo-Fu Tseng <cooldavid@cooldavid.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.
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_vlan.h>
+#include <net/ip6_checksum.h>
+#include "jme.h"
+
+static int force_pseudohp = -1;
+static int no_pseudohp = -1;
+static int no_extplug = -1;
+module_param(force_pseudohp, int, 0);
+MODULE_PARM_DESC(force_pseudohp,
+ "Enable pseudo hot-plug feature manually by driver instead of BIOS.");
+module_param(no_pseudohp, int, 0);
+MODULE_PARM_DESC(no_pseudohp, "Disable pseudo hot-plug feature.");
+module_param(no_extplug, int, 0);
+MODULE_PARM_DESC(no_extplug,
+ "Do not use external plug signal for pseudo hot-plug.");
+
+static int
+jme_mdio_read(struct net_device *netdev, int phy, int reg)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int i, val, again = (reg == MII_BMSR) ? 1 : 0;
+
+read_again:
+ jwrite32(jme, JME_SMI, SMI_OP_REQ |
+ smi_phy_addr(phy) |
+ smi_reg_addr(reg));
+
+ wmb();
+ for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) {
+ udelay(20);
+ val = jread32(jme, JME_SMI);
+ if ((val & SMI_OP_REQ) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ jeprintk(jme->pdev, "phy(%d) read timeout : %d\n", phy, reg);
+ return 0;
+ }
+
+ if (again--)
+ goto read_again;
+
+ return (val & SMI_DATA_MASK) >> SMI_DATA_SHIFT;
+}
+
+static void
+jme_mdio_write(struct net_device *netdev,
+ int phy, int reg, int val)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int i;
+
+ jwrite32(jme, JME_SMI, SMI_OP_WRITE | SMI_OP_REQ |
+ ((val << SMI_DATA_SHIFT) & SMI_DATA_MASK) |
+ smi_phy_addr(phy) | smi_reg_addr(reg));
+
+ wmb();
+ for (i = JME_PHY_TIMEOUT * 50 ; i > 0 ; --i) {
+ udelay(20);
+ if ((jread32(jme, JME_SMI) & SMI_OP_REQ) == 0)
+ break;
+ }
+
+ if (i == 0)
+ jeprintk(jme->pdev, "phy(%d) write timeout : %d\n", phy, reg);
+
+ return;
+}
+
+static inline void
+jme_reset_phy_processor(struct jme_adapter *jme)
+{
+ u32 val;
+
+ jme_mdio_write(jme->dev,
+ jme->mii_if.phy_id,
+ MII_ADVERTISE, ADVERTISE_ALL |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+
+ if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250)
+ jme_mdio_write(jme->dev,
+ jme->mii_if.phy_id,
+ MII_CTRL1000,
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+
+ val = jme_mdio_read(jme->dev,
+ jme->mii_if.phy_id,
+ MII_BMCR);
+
+ jme_mdio_write(jme->dev,
+ jme->mii_if.phy_id,
+ MII_BMCR, val | BMCR_RESET);
+
+ return;
+}
+
+static void
+jme_setup_wakeup_frame(struct jme_adapter *jme,
+ u32 *mask, u32 crc, int fnr)
+{
+ int i;
+
+ /*
+ * Setup CRC pattern
+ */
+ jwrite32(jme, JME_WFOI, WFOI_CRC_SEL | (fnr & WFOI_FRAME_SEL));
+ wmb();
+ jwrite32(jme, JME_WFODP, crc);
+ wmb();
+
+ /*
+ * Setup Mask
+ */
+ for (i = 0 ; i < WAKEUP_FRAME_MASK_DWNR ; ++i) {
+ jwrite32(jme, JME_WFOI,
+ ((i << WFOI_MASK_SHIFT) & WFOI_MASK_SEL) |
+ (fnr & WFOI_FRAME_SEL));
+ wmb();
+ jwrite32(jme, JME_WFODP, mask[i]);
+ wmb();
+ }
+}
+
+static inline void
+jme_reset_mac_processor(struct jme_adapter *jme)
+{
+ u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
+ u32 crc = 0xCDCDCDCD;
+ u32 gpreg0;
+ int i;
+
+ jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST);
+ udelay(2);
+ jwrite32(jme, JME_GHC, jme->reg_ghc);
+
+ jwrite32(jme, JME_RXDBA_LO, 0x00000000);
+ jwrite32(jme, JME_RXDBA_HI, 0x00000000);
+ jwrite32(jme, JME_RXQDC, 0x00000000);
+ jwrite32(jme, JME_RXNDA, 0x00000000);
+ jwrite32(jme, JME_TXDBA_LO, 0x00000000);
+ jwrite32(jme, JME_TXDBA_HI, 0x00000000);
+ jwrite32(jme, JME_TXQDC, 0x00000000);
+ jwrite32(jme, JME_TXNDA, 0x00000000);
+
+ jwrite32(jme, JME_RXMCHT_LO, 0x00000000);
+ jwrite32(jme, JME_RXMCHT_HI, 0x00000000);
+ for (i = 0 ; i < WAKEUP_FRAME_NR ; ++i)
+ jme_setup_wakeup_frame(jme, mask, crc, i);
+ if (jme->fpgaver)
+ gpreg0 = GPREG0_DEFAULT | GPREG0_LNKINTPOLL;
+ else
+ gpreg0 = GPREG0_DEFAULT;
+ jwrite32(jme, JME_GPREG0, gpreg0);
+ jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
+}
+
+static inline void
+jme_reset_ghc_speed(struct jme_adapter *jme)
+{
+ jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX);
+ jwrite32(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_clear_pm(struct jme_adapter *jme)
+{
+ jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
+ pci_set_power_state(jme->pdev, PCI_D0);
+ pci_enable_wake(jme->pdev, PCI_D0, false);
+}
+
+static int
+jme_reload_eeprom(struct jme_adapter *jme)
+{
+ u32 val;
+ int i;
+
+ val = jread32(jme, JME_SMBCSR);
+
+ if (val & SMBCSR_EEPROMD) {
+ val |= SMBCSR_CNACK;
+ jwrite32(jme, JME_SMBCSR, val);
+ val |= SMBCSR_RELOAD;
+ jwrite32(jme, JME_SMBCSR, val);
+ mdelay(12);
+
+ for (i = JME_EEPROM_RELOAD_TIMEOUT; i > 0; --i) {
+ mdelay(1);
+ if ((jread32(jme, JME_SMBCSR) & SMBCSR_RELOAD) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ jeprintk(jme->pdev, "eeprom reload timeout\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static void
+jme_load_macaddr(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ unsigned char macaddr[6];
+ u32 val;
+
+ spin_lock_bh(&jme->macaddr_lock);
+ val = jread32(jme, JME_RXUMA_LO);
+ macaddr[0] = (val >> 0) & 0xFF;
+ macaddr[1] = (val >> 8) & 0xFF;
+ macaddr[2] = (val >> 16) & 0xFF;
+ macaddr[3] = (val >> 24) & 0xFF;
+ val = jread32(jme, JME_RXUMA_HI);
+ macaddr[4] = (val >> 0) & 0xFF;
+ macaddr[5] = (val >> 8) & 0xFF;
+ memcpy(netdev->dev_addr, macaddr, 6);
+ spin_unlock_bh(&jme->macaddr_lock);
+}
+
+static inline void
+jme_set_rx_pcc(struct jme_adapter *jme, int p)
+{
+ switch (p) {
+ case PCC_OFF:
+ jwrite32(jme, JME_PCCRX0,
+ ((PCC_OFF_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) |
+ ((PCC_OFF_CNT << PCCRX_SHIFT) & PCCRX_MASK));
+ break;
+ case PCC_P1:
+ jwrite32(jme, JME_PCCRX0,
+ ((PCC_P1_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) |
+ ((PCC_P1_CNT << PCCRX_SHIFT) & PCCRX_MASK));
+ break;
+ case PCC_P2:
+ jwrite32(jme, JME_PCCRX0,
+ ((PCC_P2_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) |
+ ((PCC_P2_CNT << PCCRX_SHIFT) & PCCRX_MASK));
+ break;
+ case PCC_P3:
+ jwrite32(jme, JME_PCCRX0,
+ ((PCC_P3_TO << PCCRXTO_SHIFT) & PCCRXTO_MASK) |
+ ((PCC_P3_CNT << PCCRX_SHIFT) & PCCRX_MASK));
+ break;
+ default:
+ break;
+ }
+ wmb();
+
+ if (!(test_bit(JME_FLAG_POLL, &jme->flags)))
+ msg_rx_status(jme, "Switched to PCC_P%d\n", p);
+}
+
+static void
+jme_start_irq(struct jme_adapter *jme)
+{
+ register struct dynpcc_info *dpi = &(jme->dpi);
+
+ jme_set_rx_pcc(jme, PCC_P1);
+ dpi->cur = PCC_P1;
+ dpi->attempt = PCC_P1;
+ dpi->cnt = 0;
+
+ jwrite32(jme, JME_PCCTX,
+ ((PCC_TX_TO << PCCTXTO_SHIFT) & PCCTXTO_MASK) |
+ ((PCC_TX_CNT << PCCTX_SHIFT) & PCCTX_MASK) |
+ PCCTXQ0_EN
+ );
+
+ /*
+ * Enable Interrupts
+ */
+ jwrite32(jme, JME_IENS, INTR_ENABLE);
+}
+
+static inline void
+jme_stop_irq(struct jme_adapter *jme)
+{
+ /*
+ * Disable Interrupts
+ */
+ jwrite32f(jme, JME_IENC, INTR_ENABLE);
+}
+
+static inline void
+jme_enable_shadow(struct jme_adapter *jme)
+{
+ jwrite32(jme,
+ JME_SHBA_LO,
+ ((u32)jme->shadow_dma & ~((u32)0x1F)) | SHBA_POSTEN);
+}
+
+static inline void
+jme_disable_shadow(struct jme_adapter *jme)
+{
+ jwrite32(jme, JME_SHBA_LO, 0x0);
+}
+
+static u32
+jme_linkstat_from_phy(struct jme_adapter *jme)
+{
+ u32 phylink, bmsr;
+
+ phylink = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 17);
+ bmsr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMSR);
+ if (bmsr & BMSR_ANCOMP)
+ phylink |= PHY_LINK_AUTONEG_COMPLETE;
+
+ return phylink;
+}
+
+static inline void
+jme_set_phyfifoa(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004);
+}
+
+static inline void
+jme_set_phyfifob(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000);
+}
+
+static int
+jme_check_link(struct net_device *netdev, int testonly)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1;
+ char linkmsg[64];
+ int rc = 0;
+
+ linkmsg[0] = '\0';
+
+ if (jme->fpgaver)
+ phylink = jme_linkstat_from_phy(jme);
+ else
+ phylink = jread32(jme, JME_PHY_LINK);
+
+ if (phylink & PHY_LINK_UP) {
+ if (!(phylink & PHY_LINK_AUTONEG_COMPLETE)) {
+ /*
+ * If we did not enable AN
+ * Speed/Duplex Info should be obtained from SMI
+ */
+ phylink = PHY_LINK_UP;
+
+ bmcr = jme_mdio_read(jme->dev,
+ jme->mii_if.phy_id,
+ MII_BMCR);
+
+ phylink |= ((bmcr & BMCR_SPEED1000) &&
+ (bmcr & BMCR_SPEED100) == 0) ?
+ PHY_LINK_SPEED_1000M :
+ (bmcr & BMCR_SPEED100) ?
+ PHY_LINK_SPEED_100M :
+ PHY_LINK_SPEED_10M;
+
+ phylink |= (bmcr & BMCR_FULLDPLX) ?
+ PHY_LINK_DUPLEX : 0;
+
+ strcat(linkmsg, "Forced: ");
+ } else {
+ /*
+ * Keep polling for speed/duplex resolve complete
+ */
+ while (!(phylink & PHY_LINK_SPEEDDPU_RESOLVED) &&
+ --cnt) {
+
+ udelay(1);
+
+ if (jme->fpgaver)
+ phylink = jme_linkstat_from_phy(jme);
+ else
+ phylink = jread32(jme, JME_PHY_LINK);
+ }
+ if (!cnt)
+ jeprintk(jme->pdev,
+ "Waiting speed resolve timeout.\n");
+
+ strcat(linkmsg, "ANed: ");
+ }
+
+ if (jme->phylink == phylink) {
+ rc = 1;
+ goto out;
+ }
+ if (testonly)
+ goto out;
+
+ jme->phylink = phylink;
+
+ ghc = jme->reg_ghc & ~(GHC_SPEED_10M |
+ GHC_SPEED_100M |
+ GHC_SPEED_1000M |
+ GHC_DPX);
+ switch (phylink & PHY_LINK_SPEED_MASK) {
+ case PHY_LINK_SPEED_10M:
+ ghc |= GHC_SPEED_10M;
+ strcat(linkmsg, "10 Mbps, ");
+ break;
+ case PHY_LINK_SPEED_100M:
+ ghc |= GHC_SPEED_100M;
+ strcat(linkmsg, "100 Mbps, ");
+ break;
+ case PHY_LINK_SPEED_1000M:
+ ghc |= GHC_SPEED_1000M;
+ strcat(linkmsg, "1000 Mbps, ");
+ break;
+ default:
+ break;
+ }
+
+ if (phylink & PHY_LINK_DUPLEX) {
+ jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT);
+ ghc |= GHC_DPX;
+ } else {
+ jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT |
+ TXMCS_BACKOFF |
+ TXMCS_CARRIERSENSE |
+ TXMCS_COLLISION);
+ jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN |
+ ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
+ TXTRHD_TXREN |
+ ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
+ }
+ strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
+ "Full-Duplex, " :
+ "Half-Duplex, ");
+
+ if (phylink & PHY_LINK_MDI_STAT)
+ strcat(linkmsg, "MDI-X");
+ else
+ strcat(linkmsg, "MDI");
+
+ gpreg1 = GPREG1_DEFAULT;
+ if (is_buggy250(jme->pdev->device, jme->chiprev)) {
+ if (!(phylink & PHY_LINK_DUPLEX))
+ gpreg1 |= GPREG1_HALFMODEPATCH;
+ switch (phylink & PHY_LINK_SPEED_MASK) {
+ case PHY_LINK_SPEED_10M:
+ jme_set_phyfifoa(jme);
+ gpreg1 |= GPREG1_RSSPATCH;
+ break;
+ case PHY_LINK_SPEED_100M:
+ jme_set_phyfifob(jme);
+ gpreg1 |= GPREG1_RSSPATCH;
+ break;
+ case PHY_LINK_SPEED_1000M:
+ jme_set_phyfifoa(jme);
+ break;
+ default:
+ break;
+ }
+ }
+ jwrite32(jme, JME_GPREG1, gpreg1);
+
+ jme->reg_ghc = ghc;
+ jwrite32(jme, JME_GHC, ghc);
+
+ msg_link(jme, "Link is up at %s.\n", linkmsg);
+ netif_carrier_on(netdev);
+ } else {
+ if (testonly)
+ goto out;
+
+ msg_link(jme, "Link is down.\n");
+ jme->phylink = 0;
+ netif_carrier_off(netdev);
+ }
+
+out:
+ return rc;
+}
+
+static int
+jme_setup_tx_resources(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = &(jme->txring[0]);
+
+ txring->alloc = dma_alloc_coherent(&(jme->pdev->dev),
+ TX_RING_ALLOC_SIZE(jme->tx_ring_size),
+ &(txring->dmaalloc),
+ GFP_ATOMIC);
+
+ if (!txring->alloc) {
+ txring->desc = NULL;
+ txring->dmaalloc = 0;
+ txring->dma = 0;
+ return -ENOMEM;
+ }
+
+ /*
+ * 16 Bytes align
+ */
+ txring->desc = (void *)ALIGN((unsigned long)(txring->alloc),
+ RING_DESC_ALIGN);
+ txring->dma = ALIGN(txring->dmaalloc, RING_DESC_ALIGN);
+ txring->next_to_use = 0;
+ atomic_set(&txring->next_to_clean, 0);
+ atomic_set(&txring->nr_free, jme->tx_ring_size);
+
+ /*
+ * Initialize Transmit Descriptors
+ */
+ memset(txring->alloc, 0, TX_RING_ALLOC_SIZE(jme->tx_ring_size));
+ memset(txring->bufinf, 0,
+ sizeof(struct jme_buffer_info) * jme->tx_ring_size);
+
+ return 0;
+}
+
+static void
+jme_free_tx_resources(struct jme_adapter *jme)
+{
+ int i;
+ struct jme_ring *txring = &(jme->txring[0]);
+ struct jme_buffer_info *txbi = txring->bufinf;
+
+ if (txring->alloc) {
+ for (i = 0 ; i < jme->tx_ring_size ; ++i) {
+ txbi = txring->bufinf + i;
+ if (txbi->skb) {
+ dev_kfree_skb(txbi->skb);
+ txbi->skb = NULL;
+ }
+ txbi->mapping = 0;
+ txbi->len = 0;
+ txbi->nr_desc = 0;
+ txbi->start_xmit = 0;
+ }
+
+ dma_free_coherent(&(jme->pdev->dev),
+ TX_RING_ALLOC_SIZE(jme->tx_ring_size),
+ txring->alloc,
+ txring->dmaalloc);
+
+ txring->alloc = NULL;
+ txring->desc = NULL;
+ txring->dmaalloc = 0;
+ txring->dma = 0;
+ }
+ txring->next_to_use = 0;
+ atomic_set(&txring->next_to_clean, 0);
+ atomic_set(&txring->nr_free, 0);
+
+}
+
+static inline void
+jme_enable_tx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Select Queue 0
+ */
+ jwrite32(jme, JME_TXCS, TXCS_DEFAULT | TXCS_SELECT_QUEUE0);
+ wmb();
+
+ /*
+ * Setup TX Queue 0 DMA Bass Address
+ */
+ jwrite32(jme, JME_TXDBA_LO, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_TXDBA_HI, (__u64)(jme->txring[0].dma) >> 32);
+ jwrite32(jme, JME_TXNDA, (__u64)jme->txring[0].dma & 0xFFFFFFFFUL);
+
+ /*
+ * Setup TX Descptor Count
+ */
+ jwrite32(jme, JME_TXQDC, jme->tx_ring_size);
+
+ /*
+ * Enable TX Engine
+ */
+ wmb();
+ jwrite32(jme, JME_TXCS, jme->reg_txcs |
+ TXCS_SELECT_QUEUE0 |
+ TXCS_ENABLE);
+
+}
+
+static inline void
+jme_restart_tx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Restart TX Engine
+ */
+ jwrite32(jme, JME_TXCS, jme->reg_txcs |
+ TXCS_SELECT_QUEUE0 |
+ TXCS_ENABLE);
+}
+
+static inline void
+jme_disable_tx_engine(struct jme_adapter *jme)
+{
+ int i;
+ u32 val;
+
+ /*
+ * Disable TX Engine
+ */
+ jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0);
+ wmb();
+
+ val = jread32(jme, JME_TXCS);
+ for (i = JME_TX_DISABLE_TIMEOUT ; (val & TXCS_ENABLE) && i > 0 ; --i) {
+ mdelay(1);
+ val = jread32(jme, JME_TXCS);
+ rmb();
+ }
+
+ if (!i)
+ jeprintk(jme->pdev, "Disable TX engine timeout.\n");
+}
+
+static void
+jme_set_clean_rxdesc(struct jme_adapter *jme, int i)
+{
+ struct jme_ring *rxring = jme->rxring;
+ register struct rxdesc *rxdesc = rxring->desc;
+ struct jme_buffer_info *rxbi = rxring->bufinf;
+ rxdesc += i;
+ rxbi += i;
+
+ rxdesc->dw[0] = 0;
+ rxdesc->dw[1] = 0;
+ rxdesc->desc1.bufaddrh = cpu_to_le32((__u64)rxbi->mapping >> 32);
+ rxdesc->desc1.bufaddrl = cpu_to_le32(
+ (__u64)rxbi->mapping & 0xFFFFFFFFUL);
+ rxdesc->desc1.datalen = cpu_to_le16(rxbi->len);
+ if (jme->dev->features & NETIF_F_HIGHDMA)
+ rxdesc->desc1.flags = RXFLAG_64BIT;
+ wmb();
+ rxdesc->desc1.flags |= RXFLAG_OWN | RXFLAG_INT;
+}
+
+static int
+jme_make_new_rx_buf(struct jme_adapter *jme, int i)
+{
+ struct jme_ring *rxring = &(jme->rxring[0]);
+ struct jme_buffer_info *rxbi = rxring->bufinf + i;
+ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb(jme->dev,
+ jme->dev->mtu + RX_EXTRA_LEN);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ rxbi->skb = skb;
+ rxbi->len = skb_tailroom(skb);
+ rxbi->mapping = pci_map_page(jme->pdev,
+ virt_to_page(skb->data),
+ offset_in_page(skb->data),
+ rxbi->len,
+ PCI_DMA_FROMDEVICE);
+
+ return 0;
+}
+
+static void
+jme_free_rx_buf(struct jme_adapter *jme, int i)
+{
+ struct jme_ring *rxring = &(jme->rxring[0]);
+ struct jme_buffer_info *rxbi = rxring->bufinf;
+ rxbi += i;
+
+ if (rxbi->skb) {
+ pci_unmap_page(jme->pdev,
+ rxbi->mapping,
+ rxbi->len,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxbi->skb);
+ rxbi->skb = NULL;
+ rxbi->mapping = 0;
+ rxbi->len = 0;
+ }
+}
+
+static void
+jme_free_rx_resources(struct jme_adapter *jme)
+{
+ int i;
+ struct jme_ring *rxring = &(jme->rxring[0]);
+
+ if (rxring->alloc) {
+ for (i = 0 ; i < jme->rx_ring_size ; ++i)
+ jme_free_rx_buf(jme, i);
+
+ dma_free_coherent(&(jme->pdev->dev),
+ RX_RING_ALLOC_SIZE(jme->rx_ring_size),
+ rxring->alloc,
+ rxring->dmaalloc);
+ rxring->alloc = NULL;
+ rxring->desc = NULL;
+ rxring->dmaalloc = 0;
+ rxring->dma = 0;
+ }
+ rxring->next_to_use = 0;
+ atomic_set(&rxring->next_to_clean, 0);
+}
+
+static int
+jme_setup_rx_resources(struct jme_adapter *jme)
+{
+ int i;
+ struct jme_ring *rxring = &(jme->rxring[0]);
+
+ rxring->alloc = dma_alloc_coherent(&(jme->pdev->dev),
+ RX_RING_ALLOC_SIZE(jme->rx_ring_size),
+ &(rxring->dmaalloc),
+ GFP_ATOMIC);
+ if (!rxring->alloc) {
+ rxring->desc = NULL;
+ rxring->dmaalloc = 0;
+ rxring->dma = 0;
+ return -ENOMEM;
+ }
+
+ /*
+ * 16 Bytes align
+ */
+ rxring->desc = (void *)ALIGN((unsigned long)(rxring->alloc),
+ RING_DESC_ALIGN);
+ rxring->dma = ALIGN(rxring->dmaalloc, RING_DESC_ALIGN);
+ rxring->next_to_use = 0;
+ atomic_set(&rxring->next_to_clean, 0);
+
+ /*
+ * Initiallize Receive Descriptors
+ */
+ for (i = 0 ; i < jme->rx_ring_size ; ++i) {
+ if (unlikely(jme_make_new_rx_buf(jme, i))) {
+ jme_free_rx_resources(jme);
+ return -ENOMEM;
+ }
+
+ jme_set_clean_rxdesc(jme, i);
+ }
+
+ return 0;
+}
+
+static inline void
+jme_enable_rx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Select Queue 0
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0);
+ wmb();
+
+ /*
+ * Setup RX DMA Bass Address
+ */
+ jwrite32(jme, JME_RXDBA_LO, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_RXDBA_HI, (__u64)(jme->rxring[0].dma) >> 32);
+ jwrite32(jme, JME_RXNDA, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL);
+
+ /*
+ * Setup RX Descriptor Count
+ */
+ jwrite32(jme, JME_RXQDC, jme->rx_ring_size);
+
+ /*
+ * Setup Unicast Filter
+ */
+ jme_set_multi(jme->dev);
+
+ /*
+ * Enable RX Engine
+ */
+ wmb();
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0 |
+ RXCS_ENABLE |
+ RXCS_QST);
+}
+
+static inline void
+jme_restart_rx_engine(struct jme_adapter *jme)
+{
+ /*
+ * Start RX Engine
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+ RXCS_QUEUESEL_Q0 |
+ RXCS_ENABLE |
+ RXCS_QST);
+}
+
+static inline void
+jme_disable_rx_engine(struct jme_adapter *jme)
+{
+ int i;
+ u32 val;
+
+ /*
+ * Disable RX Engine
+ */
+ jwrite32(jme, JME_RXCS, jme->reg_rxcs);
+ wmb();
+
+ val = jread32(jme, JME_RXCS);
+ for (i = JME_RX_DISABLE_TIMEOUT ; (val & RXCS_ENABLE) && i > 0 ; --i) {
+ mdelay(1);
+ val = jread32(jme, JME_RXCS);
+ rmb();
+ }
+
+ if (!i)
+ jeprintk(jme->pdev, "Disable RX engine timeout.\n");
+
+}
+
+static int
+jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
+{
+ if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4)))
+ return false;
+
+ if (unlikely(!(flags & RXWBFLAG_MF) &&
+ (flags & RXWBFLAG_TCPON) && !(flags & RXWBFLAG_TCPCS))) {
+ msg_rx_err(jme, "TCP Checksum error.\n");
+ goto out_sumerr;
+ }
+
+ if (unlikely(!(flags & RXWBFLAG_MF) &&
+ (flags & RXWBFLAG_UDPON) && !(flags & RXWBFLAG_UDPCS))) {
+ msg_rx_err(jme, "UDP Checksum error.\n");
+ goto out_sumerr;
+ }
+
+ if (unlikely((flags & RXWBFLAG_IPV4) && !(flags & RXWBFLAG_IPCS))) {
+ msg_rx_err(jme, "IPv4 Checksum error.\n");
+ goto out_sumerr;
+ }
+
+ return true;
+
+out_sumerr:
+ return false;
+}
+
+static void
+jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
+{
+ struct jme_ring *rxring = &(jme->rxring[0]);
+ struct rxdesc *rxdesc = rxring->desc;
+ struct jme_buffer_info *rxbi = rxring->bufinf;
+ struct sk_buff *skb;
+ int framesize;
+
+ rxdesc += idx;
+ rxbi += idx;
+
+ skb = rxbi->skb;
+ pci_dma_sync_single_for_cpu(jme->pdev,
+ rxbi->mapping,
+ rxbi->len,
+ PCI_DMA_FROMDEVICE);
+
+ if (unlikely(jme_make_new_rx_buf(jme, idx))) {
+ pci_dma_sync_single_for_device(jme->pdev,
+ rxbi->mapping,
+ rxbi->len,
+ PCI_DMA_FROMDEVICE);
+
+ ++(NET_STAT(jme).rx_dropped);
+ } else {
+ framesize = le16_to_cpu(rxdesc->descwb.framesize)
+ - RX_PREPAD_SIZE;
+
+ skb_reserve(skb, RX_PREPAD_SIZE);
+ skb_put(skb, framesize);
+ skb->protocol = eth_type_trans(skb, jme->dev);
+
+ if (jme_rxsum_ok(jme, rxdesc->descwb.flags))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (rxdesc->descwb.flags & RXWBFLAG_TAGON) {
+ if (jme->vlgrp) {
+ jme->jme_vlan_rx(skb, jme->vlgrp,
+ le32_to_cpu(rxdesc->descwb.vlan));
+ NET_STAT(jme).rx_bytes += 4;
+ }
+ } else {
+ jme->jme_rx(skb);
+ }
+
+ if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) ==
+ RXWBFLAG_DEST_MUL)
+ ++(NET_STAT(jme).multicast);
+
+ jme->dev->last_rx = jiffies;
+ NET_STAT(jme).rx_bytes += framesize;
+ ++(NET_STAT(jme).rx_packets);
+ }
+
+ jme_set_clean_rxdesc(jme, idx);
+
+}
+
+static int
+jme_process_receive(struct jme_adapter *jme, int limit)
+{
+ struct jme_ring *rxring = &(jme->rxring[0]);
+ struct rxdesc *rxdesc = rxring->desc;
+ int i, j, ccnt, desccnt, mask = jme->rx_ring_mask;
+
+ if (unlikely(!atomic_dec_and_test(&jme->rx_cleaning)))
+ goto out_inc;
+
+ if (unlikely(atomic_read(&jme->link_changing) != 1))
+ goto out_inc;
+
+ if (unlikely(!netif_carrier_ok(jme->dev)))
+ goto out_inc;
+
+ i = atomic_read(&rxring->next_to_clean);
+ while (limit-- > 0) {
+ rxdesc = rxring->desc;
+ rxdesc += i;
+
+ if ((rxdesc->descwb.flags & RXWBFLAG_OWN) ||
+ !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL))
+ goto out;
+
+ desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT;
+
+ if (unlikely(desccnt > 1 ||
+ rxdesc->descwb.errstat & RXWBERR_ALLERR)) {
+
+ if (rxdesc->descwb.errstat & RXWBERR_CRCERR)
+ ++(NET_STAT(jme).rx_crc_errors);
+ else if (rxdesc->descwb.errstat & RXWBERR_OVERUN)
+ ++(NET_STAT(jme).rx_fifo_errors);
+ else
+ ++(NET_STAT(jme).rx_errors);
+
+ if (desccnt > 1)
+ limit -= desccnt - 1;
+
+ for (j = i, ccnt = desccnt ; ccnt-- ; ) {
+ jme_set_clean_rxdesc(jme, j);
+ j = (j + 1) & (mask);
+ }
+
+ } else {
+ jme_alloc_and_feed_skb(jme, i);
+ }
+
+ i = (i + desccnt) & (mask);
+ }
+
+out:
+ atomic_set(&rxring->next_to_clean, i);
+
+out_inc:
+ atomic_inc(&jme->rx_cleaning);
+
+ return limit > 0 ? limit : 0;
+
+}
+
+static void
+jme_attempt_pcc(struct dynpcc_info *dpi, int atmp)
+{
+ if (likely(atmp == dpi->cur)) {
+ dpi->cnt = 0;
+ return;
+ }
+
+ if (dpi->attempt == atmp) {
+ ++(dpi->cnt);
+ } else {
+ dpi->attempt = atmp;
+ dpi->cnt = 0;
+ }
+
+}
+
+static void
+jme_dynamic_pcc(struct jme_adapter *jme)
+{
+ register struct dynpcc_info *dpi = &(jme->dpi);
+
+ if ((NET_STAT(jme).rx_bytes - dpi->last_bytes) > PCC_P3_THRESHOLD)
+ jme_attempt_pcc(dpi, PCC_P3);
+ else if ((NET_STAT(jme).rx_packets - dpi->last_pkts) > PCC_P2_THRESHOLD
+ || dpi->intr_cnt > PCC_INTR_THRESHOLD)
+ jme_attempt_pcc(dpi, PCC_P2);
+ else
+ jme_attempt_pcc(dpi, PCC_P1);
+
+ if (unlikely(dpi->attempt != dpi->cur && dpi->cnt > 5)) {
+ if (dpi->attempt < dpi->cur)
+ tasklet_schedule(&jme->rxclean_task);
+ jme_set_rx_pcc(jme, dpi->attempt);
+ dpi->cur = dpi->attempt;
+ dpi->cnt = 0;
+ }
+}
+
+static void
+jme_start_pcc_timer(struct jme_adapter *jme)
+{
+ struct dynpcc_info *dpi = &(jme->dpi);
+ dpi->last_bytes = NET_STAT(jme).rx_bytes;
+ dpi->last_pkts = NET_STAT(jme).rx_packets;
+ dpi->intr_cnt = 0;
+ jwrite32(jme, JME_TMCSR,
+ TMCSR_EN | ((0xFFFFFF - PCC_INTERVAL_US) & TMCSR_CNT));
+}
+
+static inline void
+jme_stop_pcc_timer(struct jme_adapter *jme)
+{
+ jwrite32(jme, JME_TMCSR, 0);
+}
+
+static void
+jme_shutdown_nic(struct jme_adapter *jme)
+{
+ u32 phylink;
+
+ phylink = jme_linkstat_from_phy(jme);
+
+ if (!(phylink & PHY_LINK_UP)) {
+ /*
+ * Disable all interrupt before issue timer
+ */
+ jme_stop_irq(jme);
+ jwrite32(jme, JME_TIMER2, TMCSR_EN | 0xFFFFFE);
+ }
+}
+
+static void
+jme_pcc_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)arg;
+ struct net_device *netdev = jme->dev;
+
+ if (unlikely(test_bit(JME_FLAG_SHUTDOWN, &jme->flags))) {
+ jme_shutdown_nic(jme);
+ return;
+ }
+
+ if (unlikely(!netif_carrier_ok(netdev) ||
+ (atomic_read(&jme->link_changing) != 1)
+ )) {
+ jme_stop_pcc_timer(jme);
+ return;
+ }
+
+ if (!(test_bit(JME_FLAG_POLL, &jme->flags)))
+ jme_dynamic_pcc(jme);
+
+ jme_start_pcc_timer(jme);
+}
+
+static inline void
+jme_polling_mode(struct jme_adapter *jme)
+{
+ jme_set_rx_pcc(jme, PCC_OFF);
+}
+
+static inline void
+jme_interrupt_mode(struct jme_adapter *jme)
+{
+ jme_set_rx_pcc(jme, PCC_P1);
+}
+
+static inline int
+jme_pseudo_hotplug_enabled(struct jme_adapter *jme)
+{
+ u32 apmc;
+ apmc = jread32(jme, JME_APMC);
+ return apmc & JME_APMC_PSEUDO_HP_EN;
+}
+
+static void
+jme_start_shutdown_timer(struct jme_adapter *jme)
+{
+ u32 apmc;
+
+ apmc = jread32(jme, JME_APMC) | JME_APMC_PCIE_SD_EN;
+ apmc &= ~JME_APMC_EPIEN_CTRL;
+ if (!no_extplug) {
+ jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_EN);
+ wmb();
+ }
+ jwrite32f(jme, JME_APMC, apmc);
+
+ jwrite32f(jme, JME_TIMER2, 0);
+ set_bit(JME_FLAG_SHUTDOWN, &jme->flags);
+ jwrite32(jme, JME_TMCSR,
+ TMCSR_EN | ((0xFFFFFF - APMC_PHP_SHUTDOWN_DELAY) & TMCSR_CNT));
+}
+
+static void
+jme_stop_shutdown_timer(struct jme_adapter *jme)
+{
+ u32 apmc;
+
+ jwrite32f(jme, JME_TMCSR, 0);
+ jwrite32f(jme, JME_TIMER2, 0);
+ clear_bit(JME_FLAG_SHUTDOWN, &jme->flags);
+
+ apmc = jread32(jme, JME_APMC);
+ apmc &= ~(JME_APMC_PCIE_SD_EN | JME_APMC_EPIEN_CTRL);
+ jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_DIS);
+ wmb();
+ jwrite32f(jme, JME_APMC, apmc);
+}
+
+static void
+jme_link_change_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)arg;
+ struct net_device *netdev = jme->dev;
+ int rc;
+
+ while (!atomic_dec_and_test(&jme->link_changing)) {
+ atomic_inc(&jme->link_changing);
+ msg_intr(jme, "Get link change lock failed.\n");
+ while (atomic_read(&jme->link_changing) != 1)
+ msg_intr(jme, "Waiting link change lock.\n");
+ }
+
+ if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu)
+ goto out;
+
+ jme->old_mtu = netdev->mtu;
+ netif_stop_queue(netdev);
+ if (jme_pseudo_hotplug_enabled(jme))
+ jme_stop_shutdown_timer(jme);
+
+ jme_stop_pcc_timer(jme);
+ tasklet_disable(&jme->txclean_task);
+ tasklet_disable(&jme->rxclean_task);
+ tasklet_disable(&jme->rxempty_task);
+
+ if (netif_carrier_ok(netdev)) {
+ jme_reset_ghc_speed(jme);
+ jme_disable_rx_engine(jme);
+ jme_disable_tx_engine(jme);
+ jme_reset_mac_processor(jme);
+ jme_free_rx_resources(jme);
+ jme_free_tx_resources(jme);
+
+ if (test_bit(JME_FLAG_POLL, &jme->flags))
+ jme_polling_mode(jme);
+
+ netif_carrier_off(netdev);
+ }
+
+ jme_check_link(netdev, 0);
+ if (netif_carrier_ok(netdev)) {
+ rc = jme_setup_rx_resources(jme);
+ if (rc) {
+ jeprintk(jme->pdev, "Allocating resources for RX error"
+ ", Device STOPPED!\n");
+ goto out_enable_tasklet;
+ }
+
+ rc = jme_setup_tx_resources(jme);
+ if (rc) {
+ jeprintk(jme->pdev, "Allocating resources for TX error"
+ ", Device STOPPED!\n");
+ goto err_out_free_rx_resources;
+ }
+
+ jme_enable_rx_engine(jme);
+ jme_enable_tx_engine(jme);
+
+ netif_start_queue(netdev);
+
+ if (test_bit(JME_FLAG_POLL, &jme->flags))
+ jme_interrupt_mode(jme);
+
+ jme_start_pcc_timer(jme);
+ } else if (jme_pseudo_hotplug_enabled(jme)) {
+ jme_start_shutdown_timer(jme);
+ }
+
+ goto out_enable_tasklet;
+
+err_out_free_rx_resources:
+ jme_free_rx_resources(jme);
+out_enable_tasklet:
+ tasklet_enable(&jme->txclean_task);
+ tasklet_hi_enable(&jme->rxclean_task);
+ tasklet_hi_enable(&jme->rxempty_task);
+out:
+ atomic_inc(&jme->link_changing);
+}
+
+static void
+jme_rx_clean_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)arg;
+ struct dynpcc_info *dpi = &(jme->dpi);
+
+ jme_process_receive(jme, jme->rx_ring_size);
+ ++(dpi->intr_cnt);
+
+}
+
+static int
+jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget))
+{
+ struct jme_adapter *jme = jme_napi_priv(holder);
+ struct net_device *netdev = jme->dev;
+ int rest;
+
+ rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget));
+
+ while (atomic_read(&jme->rx_empty) > 0) {
+ atomic_dec(&jme->rx_empty);
+ ++(NET_STAT(jme).rx_dropped);
+ jme_restart_rx_engine(jme);
+ }
+ atomic_inc(&jme->rx_empty);
+
+ if (rest) {
+ JME_RX_COMPLETE(netdev, holder);
+ jme_interrupt_mode(jme);
+ }
+
+ JME_NAPI_WEIGHT_SET(budget, rest);
+ return JME_NAPI_WEIGHT_VAL(budget) - rest;
+}
+
+static void
+jme_rx_empty_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)arg;
+
+ if (unlikely(atomic_read(&jme->link_changing) != 1))
+ return;
+
+ if (unlikely(!netif_carrier_ok(jme->dev)))
+ return;
+
+ msg_rx_status(jme, "RX Queue Full!\n");
+
+ jme_rx_clean_tasklet(arg);
+
+ while (atomic_read(&jme->rx_empty) > 0) {
+ atomic_dec(&jme->rx_empty);
+ ++(NET_STAT(jme).rx_dropped);
+ jme_restart_rx_engine(jme);
+ }
+ atomic_inc(&jme->rx_empty);
+}
+
+static void
+jme_wake_queue_if_stopped(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = jme->txring;
+
+ smp_wmb();
+ if (unlikely(netif_queue_stopped(jme->dev) &&
+ atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) {
+ msg_tx_done(jme, "TX Queue Waked.\n");
+ netif_wake_queue(jme->dev);
+ }
+
+}
+
+static void
+jme_tx_clean_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)arg;
+ struct jme_ring *txring = &(jme->txring[0]);
+ struct txdesc *txdesc = txring->desc;
+ struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi;
+ int i, j, cnt = 0, max, err, mask;
+
+ tx_dbg(jme, "Into txclean.\n");
+
+ if (unlikely(!atomic_dec_and_test(&jme->tx_cleaning)))
+ goto out;
+
+ if (unlikely(atomic_read(&jme->link_changing) != 1))
+ goto out;
+
+ if (unlikely(!netif_carrier_ok(jme->dev)))
+ goto out;
+
+ max = jme->tx_ring_size - atomic_read(&txring->nr_free);
+ mask = jme->tx_ring_mask;
+
+ for (i = atomic_read(&txring->next_to_clean) ; cnt < max ; ) {
+
+ ctxbi = txbi + i;
+
+ if (likely(ctxbi->skb &&
+ !(txdesc[i].descwb.flags & TXWBFLAG_OWN))) {
+
+ tx_dbg(jme, "txclean: %d+%d@%lu\n",
+ i, ctxbi->nr_desc, jiffies);
+
+ err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR;
+
+ for (j = 1 ; j < ctxbi->nr_desc ; ++j) {
+ ttxbi = txbi + ((i + j) & (mask));
+ txdesc[(i + j) & (mask)].dw[0] = 0;
+
+ pci_unmap_page(jme->pdev,
+ ttxbi->mapping,
+ ttxbi->len,
+ PCI_DMA_TODEVICE);
+
+ ttxbi->mapping = 0;
+ ttxbi->len = 0;
+ }
+
+ dev_kfree_skb(ctxbi->skb);
+
+ cnt += ctxbi->nr_desc;
+
+ if (unlikely(err)) {
+ ++(NET_STAT(jme).tx_carrier_errors);
+ } else {
+ ++(NET_STAT(jme).tx_packets);
+ NET_STAT(jme).tx_bytes += ctxbi->len;
+ }
+
+ ctxbi->skb = NULL;
+ ctxbi->len = 0;
+ ctxbi->start_xmit = 0;
+
+ } else {
+ break;
+ }
+
+ i = (i + ctxbi->nr_desc) & mask;
+
+ ctxbi->nr_desc = 0;
+ }
+
+ tx_dbg(jme, "txclean: done %d@%lu.\n", i, jiffies);
+ atomic_set(&txring->next_to_clean, i);
+ atomic_add(cnt, &txring->nr_free);
+
+ jme_wake_queue_if_stopped(jme);
+
+out:
+ atomic_inc(&jme->tx_cleaning);
+}
+
+static void
+jme_intr_msi(struct jme_adapter *jme, u32 intrstat)
+{
+ /*
+ * Disable interrupt
+ */
+ jwrite32f(jme, JME_IENC, INTR_ENABLE);
+
+ if (intrstat & (INTR_LINKCH | INTR_SWINTR)) {
+ /*
+ * Link change event is critical
+ * all other events are ignored
+ */
+ jwrite32(jme, JME_IEVE, intrstat);
+ tasklet_schedule(&jme->linkch_task);
+ goto out_reenable;
+ }
+
+ if (intrstat & INTR_TMINTR) {
+ jwrite32(jme, JME_IEVE, INTR_TMINTR);
+ tasklet_schedule(&jme->pcc_task);
+ }
+
+ if (intrstat & (INTR_PCCTXTO | INTR_PCCTX)) {
+ jwrite32(jme, JME_IEVE, INTR_PCCTXTO | INTR_PCCTX | INTR_TX0);
+ tasklet_schedule(&jme->txclean_task);
+ }
+
+ if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) {
+ jwrite32(jme, JME_IEVE, (intrstat & (INTR_PCCRX0TO |
+ INTR_PCCRX0 |
+ INTR_RX0EMP)) |
+ INTR_RX0);
+ }
+
+ if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+ if (intrstat & INTR_RX0EMP)
+ atomic_inc(&jme->rx_empty);
+
+ if ((intrstat & (INTR_PCCRX0TO | INTR_PCCRX0 | INTR_RX0EMP))) {
+ if (likely(JME_RX_SCHEDULE_PREP(jme))) {
+ jme_polling_mode(jme);
+ JME_RX_SCHEDULE(jme);
+ }
+ }
+ } else {
+ if (intrstat & INTR_RX0EMP) {
+ atomic_inc(&jme->rx_empty);
+ tasklet_hi_schedule(&jme->rxempty_task);
+ } else if (intrstat & (INTR_PCCRX0TO | INTR_PCCRX0)) {
+ tasklet_hi_schedule(&jme->rxclean_task);
+ }
+ }
+
+out_reenable:
+ /*
+ * Re-enable interrupt
+ */
+ jwrite32f(jme, JME_IENS, INTR_ENABLE);
+}
+
+static irqreturn_t
+jme_intr(int irq, void *dev_id)
+{
+ struct net_device *netdev = dev_id;
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 intrstat;
+
+ intrstat = jread32(jme, JME_IEVE);
+
+ /*
+ * Check if it's really an interrupt for us
+ */
+ if (unlikely((intrstat & INTR_ENABLE) == 0))
+ return IRQ_NONE;
+
+ /*
+ * Check if the device still exist
+ */
+ if (unlikely(intrstat == ~((typeof(intrstat))0)))
+ return IRQ_NONE;
+
+ jme_intr_msi(jme, intrstat);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+jme_msi(int irq, void *dev_id)
+{
+ struct net_device *netdev = dev_id;
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 intrstat;
+
+ pci_dma_sync_single_for_cpu(jme->pdev,
+ jme->shadow_dma,
+ sizeof(u32) * SHADOW_REG_NR,
+ PCI_DMA_FROMDEVICE);
+ intrstat = jme->shadow_regs[SHADOW_IEVE];
+ jme->shadow_regs[SHADOW_IEVE] = 0;
+
+ jme_intr_msi(jme, intrstat);
+
+ return IRQ_HANDLED;
+}
+
+static void
+jme_reset_link(struct jme_adapter *jme)
+{
+ jwrite32(jme, JME_TMCSR, TMCSR_SWIT);
+}
+
+static void
+jme_restart_an(struct jme_adapter *jme)
+{
+ u32 bmcr;
+
+ spin_lock_bh(&jme->phy_lock);
+ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+ spin_unlock_bh(&jme->phy_lock);
+}
+
+static int
+jme_request_irq(struct jme_adapter *jme)
+{
+ int rc;
+ struct net_device *netdev = jme->dev;
+ irq_handler_t handler = jme_intr;
+ int irq_flags = IRQF_SHARED;
+
+ if (!pci_enable_msi(jme->pdev)) {
+ set_bit(JME_FLAG_MSI, &jme->flags);
+ handler = jme_msi;
+ irq_flags = 0;
+ }
+
+ rc = request_irq(jme->pdev->irq, handler, irq_flags, netdev->name,
+ netdev);
+ if (rc) {
+ jeprintk(jme->pdev,
+ "Unable to request %s interrupt (return: %d)\n",
+ test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx",
+ rc);
+
+ if (test_bit(JME_FLAG_MSI, &jme->flags)) {
+ pci_disable_msi(jme->pdev);
+ clear_bit(JME_FLAG_MSI, &jme->flags);
+ }
+ } else {
+ netdev->irq = jme->pdev->irq;
+ }
+
+ return rc;
+}
+
+static void
+jme_free_irq(struct jme_adapter *jme)
+{
+ free_irq(jme->pdev->irq, jme->dev);
+ if (test_bit(JME_FLAG_MSI, &jme->flags)) {
+ pci_disable_msi(jme->pdev);
+ clear_bit(JME_FLAG_MSI, &jme->flags);
+ jme->dev->irq = jme->pdev->irq;
+ }
+}
+
+static int
+jme_open(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int rc;
+
+ jme_clear_pm(jme);
+ JME_NAPI_ENABLE(jme);
+
+ tasklet_enable(&jme->txclean_task);
+ tasklet_hi_enable(&jme->rxclean_task);
+ tasklet_hi_enable(&jme->rxempty_task);
+
+ rc = jme_request_irq(jme);
+ if (rc)
+ goto err_out;
+
+ jme_enable_shadow(jme);
+ jme_start_irq(jme);
+
+ if (test_bit(JME_FLAG_SSET, &jme->flags))
+ jme_set_settings(netdev, &jme->old_ecmd);
+ else
+ jme_reset_phy_processor(jme);
+
+ jme_reset_link(jme);
+
+ return 0;
+
+err_out:
+ netif_stop_queue(netdev);
+ netif_carrier_off(netdev);
+ return rc;
+}
+
+#ifdef CONFIG_PM
+static void
+jme_set_100m_half(struct jme_adapter *jme)
+{
+ u32 bmcr, tmp;
+
+ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
+ BMCR_SPEED1000 | BMCR_FULLDPLX);
+ tmp |= BMCR_SPEED100;
+
+ if (bmcr != tmp)
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, tmp);
+
+ if (jme->fpgaver)
+ jwrite32(jme, JME_GHC, GHC_SPEED_100M | GHC_LINK_POLL);
+ else
+ jwrite32(jme, JME_GHC, GHC_SPEED_100M);
+}
+
+#define JME_WAIT_LINK_TIME 2000 /* 2000ms */
+static void
+jme_wait_link(struct jme_adapter *jme)
+{
+ u32 phylink, to = JME_WAIT_LINK_TIME;
+
+ mdelay(1000);
+ phylink = jme_linkstat_from_phy(jme);
+ while (!(phylink & PHY_LINK_UP) && (to -= 10) > 0) {
+ mdelay(10);
+ phylink = jme_linkstat_from_phy(jme);
+ }
+}
+#endif
+
+static inline void
+jme_phy_off(struct jme_adapter *jme)
+{
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
+}
+
+static int
+jme_close(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ netif_stop_queue(netdev);
+ netif_carrier_off(netdev);
+
+ jme_stop_irq(jme);
+ jme_disable_shadow(jme);
+ jme_free_irq(jme);
+
+ JME_NAPI_DISABLE(jme);
+
+ tasklet_kill(&jme->linkch_task);
+ tasklet_kill(&jme->txclean_task);
+ tasklet_kill(&jme->rxclean_task);
+ tasklet_kill(&jme->rxempty_task);
+
+ jme_reset_ghc_speed(jme);
+ jme_disable_rx_engine(jme);
+ jme_disable_tx_engine(jme);
+ jme_reset_mac_processor(jme);
+ jme_free_rx_resources(jme);
+ jme_free_tx_resources(jme);
+ jme->phylink = 0;
+ jme_phy_off(jme);
+
+ return 0;
+}
+
+static int
+jme_alloc_txdesc(struct jme_adapter *jme,
+ struct sk_buff *skb)
+{
+ struct jme_ring *txring = jme->txring;
+ int idx, nr_alloc, mask = jme->tx_ring_mask;
+
+ idx = txring->next_to_use;
+ nr_alloc = skb_shinfo(skb)->nr_frags + 2;
+
+ if (unlikely(atomic_read(&txring->nr_free) < nr_alloc))
+ return -1;
+
+ atomic_sub(nr_alloc, &txring->nr_free);
+
+ txring->next_to_use = (txring->next_to_use + nr_alloc) & mask;
+
+ return idx;
+}
+
+static void
+jme_fill_tx_map(struct pci_dev *pdev,
+ struct txdesc *txdesc,
+ struct jme_buffer_info *txbi,
+ struct page *page,
+ u32 page_offset,
+ u32 len,
+ u8 hidma)
+{
+ dma_addr_t dmaaddr;
+
+ dmaaddr = pci_map_page(pdev,
+ page,
+ page_offset,
+ len,
+ PCI_DMA_TODEVICE);
+
+ pci_dma_sync_single_for_device(pdev,
+ dmaaddr,
+ len,
+ PCI_DMA_TODEVICE);
+
+ txdesc->dw[0] = 0;
+ txdesc->dw[1] = 0;
+ txdesc->desc2.flags = TXFLAG_OWN;
+ txdesc->desc2.flags |= (hidma) ? TXFLAG_64BIT : 0;
+ txdesc->desc2.datalen = cpu_to_le16(len);
+ txdesc->desc2.bufaddrh = cpu_to_le32((__u64)dmaaddr >> 32);
+ txdesc->desc2.bufaddrl = cpu_to_le32(
+ (__u64)dmaaddr & 0xFFFFFFFFUL);
+
+ txbi->mapping = dmaaddr;
+ txbi->len = len;
+}
+
+static void
+jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
+{
+ struct jme_ring *txring = jme->txring;
+ struct txdesc *txdesc = txring->desc, *ctxdesc;
+ struct jme_buffer_info *txbi = txring->bufinf, *ctxbi;
+ u8 hidma = jme->dev->features & NETIF_F_HIGHDMA;
+ int i, nr_frags = skb_shinfo(skb)->nr_frags;
+ int mask = jme->tx_ring_mask;
+ struct skb_frag_struct *frag;
+ u32 len;
+
+ for (i = 0 ; i < nr_frags ; ++i) {
+ frag = &skb_shinfo(skb)->frags[i];
+ ctxdesc = txdesc + ((idx + i + 2) & (mask));
+ ctxbi = txbi + ((idx + i + 2) & (mask));
+
+ jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, frag->page,
+ frag->page_offset, frag->size, hidma);
+ }
+
+ len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len;
+ ctxdesc = txdesc + ((idx + 1) & (mask));
+ ctxbi = txbi + ((idx + 1) & (mask));
+ jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data),
+ offset_in_page(skb->data), len, hidma);
+
+}
+
+static int
+jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb)
+{
+ if (unlikely(skb_shinfo(skb)->gso_size &&
+ skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) {
+ dev_kfree_skb(skb);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+jme_tx_tso(struct sk_buff *skb,
+ u16 *mss, u8 *flags)
+{
+ *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT;
+ if (*mss) {
+ *flags |= TXFLAG_LSEN;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+
+ iph->check = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
+ } else {
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ip6h->saddr,
+ &ip6h->daddr, 0,
+ IPPROTO_TCP,
+ 0);
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags)
+{
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 ip_proto;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ ip_proto = ip_hdr(skb)->protocol;
+ break;
+ case htons(ETH_P_IPV6):
+ ip_proto = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ ip_proto = 0;
+ break;
+ }
+
+ switch (ip_proto) {
+ case IPPROTO_TCP:
+ *flags |= TXFLAG_TCPCS;
+ break;
+ case IPPROTO_UDP:
+ *flags |= TXFLAG_UDPCS;
+ break;
+ default:
+ msg_tx_err(jme, "Error upper layer protocol.\n");
+ break;
+ }
+ }
+}
+
+static inline void
+jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags)
+{
+ if (vlan_tx_tag_present(skb)) {
+ *flags |= TXFLAG_TAGON;
+ *vlan = vlan_tx_tag_get(skb);
+ }
+}
+
+static int
+jme_fill_first_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
+{
+ struct jme_ring *txring = jme->txring;
+ struct txdesc *txdesc;
+ struct jme_buffer_info *txbi;
+ u8 flags;
+
+ txdesc = (struct txdesc *)txring->desc + idx;
+ txbi = txring->bufinf + idx;
+
+ txdesc->dw[0] = 0;
+ txdesc->dw[1] = 0;
+ txdesc->dw[2] = 0;
+ txdesc->dw[3] = 0;
+ txdesc->desc1.pktsize = cpu_to_le16(skb->len);
+ /*
+ * Set OWN bit at final.
+ * When kernel transmit faster than NIC.
+ * And NIC trying to send this descriptor before we tell
+ * it to start sending this TX queue.
+ * Other fields are already filled correctly.
+ */
+ wmb();
+ flags = TXFLAG_OWN | TXFLAG_INT;
+ /*
+ * Set checksum flags while not tso
+ */
+ if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags))
+ jme_tx_csum(jme, skb, &flags);
+ jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags);
+ txdesc->desc1.flags = flags;
+ /*
+ * Set tx buffer info after telling NIC to send
+ * For better tx_clean timing
+ */
+ wmb();
+ txbi->nr_desc = skb_shinfo(skb)->nr_frags + 2;
+ txbi->skb = skb;
+ txbi->len = skb->len;
+ txbi->start_xmit = jiffies;
+ if (!txbi->start_xmit)
+ txbi->start_xmit = (0UL-1);
+
+ return 0;
+}
+
+static void
+jme_stop_queue_if_full(struct jme_adapter *jme)
+{
+ struct jme_ring *txring = jme->txring;
+ struct jme_buffer_info *txbi = txring->bufinf;
+ int idx = atomic_read(&txring->next_to_clean);
+
+ txbi += idx;
+
+ smp_wmb();
+ if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) {
+ netif_stop_queue(jme->dev);
+ msg_tx_queued(jme, "TX Queue Paused.\n");
+ smp_wmb();
+ if (atomic_read(&txring->nr_free)
+ >= (jme->tx_wake_threshold)) {
+ netif_wake_queue(jme->dev);
+ msg_tx_queued(jme, "TX Queue Fast Waked.\n");
+ }
+ }
+
+ if (unlikely(txbi->start_xmit &&
+ (jiffies - txbi->start_xmit) >= TX_TIMEOUT &&
+ txbi->skb)) {
+ netif_stop_queue(jme->dev);
+ msg_tx_queued(jme, "TX Queue Stopped %d@%lu.\n", idx, jiffies);
+ }
+}
+
+/*
+ * This function is already protected by netif_tx_lock()
+ */
+
+static int
+jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int idx;
+
+ if (unlikely(jme_expand_header(jme, skb))) {
+ ++(NET_STAT(jme).tx_dropped);
+ return NETDEV_TX_OK;
+ }
+
+ idx = jme_alloc_txdesc(jme, skb);
+
+ if (unlikely(idx < 0)) {
+ netif_stop_queue(netdev);
+ msg_tx_err(jme, "BUG! Tx ring full when queue awake!\n");
+
+ return NETDEV_TX_BUSY;
+ }
+
+ jme_map_tx_skb(jme, skb, idx);
+ jme_fill_first_tx_desc(jme, skb, idx);
+
+ jwrite32(jme, JME_TXCS, jme->reg_txcs |
+ TXCS_SELECT_QUEUE0 |
+ TXCS_QUEUE0S |
+ TXCS_ENABLE);
+ netdev->trans_start = jiffies;
+
+ tx_dbg(jme, "xmit: %d+%d@%lu\n", idx,
+ skb_shinfo(skb)->nr_frags + 2,
+ jiffies);
+ jme_stop_queue_if_full(jme);
+
+ return NETDEV_TX_OK;
+}
+
+static int
+jme_set_macaddr(struct net_device *netdev, void *p)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+ u32 val;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ spin_lock_bh(&jme->macaddr_lock);
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+ val = (addr->sa_data[3] & 0xff) << 24 |
+ (addr->sa_data[2] & 0xff) << 16 |
+ (addr->sa_data[1] & 0xff) << 8 |
+ (addr->sa_data[0] & 0xff);
+ jwrite32(jme, JME_RXUMA_LO, val);
+ val = (addr->sa_data[5] & 0xff) << 8 |
+ (addr->sa_data[4] & 0xff);
+ jwrite32(jme, JME_RXUMA_HI, val);
+ spin_unlock_bh(&jme->macaddr_lock);
+
+ return 0;
+}
+
+static void
+jme_set_multi(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 mc_hash[2] = {};
+ int i;
+
+ spin_lock_bh(&jme->rxmcs_lock);
+
+ jme->reg_rxmcs |= RXMCS_BRDFRAME | RXMCS_UNIFRAME;
+
+ if (netdev->flags & IFF_PROMISC) {
+ jme->reg_rxmcs |= RXMCS_ALLFRAME;
+ } else if (netdev->flags & IFF_ALLMULTI) {
+ jme->reg_rxmcs |= RXMCS_ALLMULFRAME;
+ } else if (netdev->flags & IFF_MULTICAST) {
+ struct dev_mc_list *mclist;
+ int bit_nr;
+
+ jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED;
+ for (i = 0, mclist = netdev->mc_list;
+ mclist && i < netdev->mc_count;
+ ++i, mclist = mclist->next) {
+
+ bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F;
+ mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F);
+ }
+
+ jwrite32(jme, JME_RXMCHT_LO, mc_hash[0]);
+ jwrite32(jme, JME_RXMCHT_HI, mc_hash[1]);
+ }
+
+ wmb();
+ jwrite32(jme, JME_RXMCS, jme->reg_rxmcs);
+
+ spin_unlock_bh(&jme->rxmcs_lock);
+}
+
+static int
+jme_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if (new_mtu == jme->old_mtu)
+ return 0;
+
+ if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
+ ((new_mtu) < IPV6_MIN_MTU))
+ return -EINVAL;
+
+ if (new_mtu > 4000) {
+ jme->reg_rxcs &= ~RXCS_FIFOTHNP;
+ jme->reg_rxcs |= RXCS_FIFOTHNP_64QW;
+ jme_restart_rx_engine(jme);
+ } else {
+ jme->reg_rxcs &= ~RXCS_FIFOTHNP;
+ jme->reg_rxcs |= RXCS_FIFOTHNP_128QW;
+ jme_restart_rx_engine(jme);
+ }
+
+ if (new_mtu > 1900) {
+ netdev->features &= ~(NETIF_F_HW_CSUM |
+ NETIF_F_TSO |
+ NETIF_F_TSO6);
+ } else {
+ if (test_bit(JME_FLAG_TXCSUM, &jme->flags))
+ netdev->features |= NETIF_F_HW_CSUM;
+ if (test_bit(JME_FLAG_TSO, &jme->flags))
+ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+ }
+
+ netdev->mtu = new_mtu;
+ jme_reset_link(jme);
+
+ return 0;
+}
+
+static void
+jme_tx_timeout(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ jme->phylink = 0;
+ jme_reset_phy_processor(jme);
+ if (test_bit(JME_FLAG_SSET, &jme->flags))
+ jme_set_settings(netdev, &jme->old_ecmd);
+
+ /*
+ * Force to Reset the link again
+ */
+ jme_reset_link(jme);
+}
+
+static void
+jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ jme->vlgrp = grp;
+}
+
+static void
+jme_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(jme->pdev));
+}
+
+static int
+jme_get_regs_len(struct net_device *netdev)
+{
+ return JME_REG_LEN;
+}
+
+static void
+mmapio_memcpy(struct jme_adapter *jme, u32 *p, u32 reg, int len)
+{
+ int i;
+
+ for (i = 0 ; i < len ; i += 4)
+ p[i >> 2] = jread32(jme, reg + i);
+}
+
+static void
+mdio_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr)
+{
+ int i;
+ u16 *p16 = (u16 *)p;
+
+ for (i = 0 ; i < reg_nr ; ++i)
+ p16[i] = jme_mdio_read(jme->dev, jme->mii_if.phy_id, i);
+}
+
+static void
+jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 *p32 = (u32 *)p;
+
+ memset(p, 0xFF, JME_REG_LEN);
+
+ regs->version = 1;
+ mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_PHY, JME_PHY_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_MISC, JME_MISC_LEN);
+
+ p32 += 0x100 >> 2;
+ mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN);
+
+ p32 += 0x100 >> 2;
+ mdio_memcpy(jme, p32, JME_PHY_REG_NR);
+}
+
+static int
+jme_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ ecmd->tx_coalesce_usecs = PCC_TX_TO;
+ ecmd->tx_max_coalesced_frames = PCC_TX_CNT;
+
+ if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+ ecmd->use_adaptive_rx_coalesce = false;
+ ecmd->rx_coalesce_usecs = 0;
+ ecmd->rx_max_coalesced_frames = 0;
+ return 0;
+ }
+
+ ecmd->use_adaptive_rx_coalesce = true;
+
+ switch (jme->dpi.cur) {
+ case PCC_P1:
+ ecmd->rx_coalesce_usecs = PCC_P1_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P1_CNT;
+ break;
+ case PCC_P2:
+ ecmd->rx_coalesce_usecs = PCC_P2_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P2_CNT;
+ break;
+ case PCC_P3:
+ ecmd->rx_coalesce_usecs = PCC_P3_TO;
+ ecmd->rx_max_coalesced_frames = PCC_P3_CNT;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ struct dynpcc_info *dpi = &(jme->dpi);
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ if (ecmd->use_adaptive_rx_coalesce
+ && test_bit(JME_FLAG_POLL, &jme->flags)) {
+ clear_bit(JME_FLAG_POLL, &jme->flags);
+ jme->jme_rx = netif_rx;
+ jme->jme_vlan_rx = vlan_hwaccel_rx;
+ dpi->cur = PCC_P1;
+ dpi->attempt = PCC_P1;
+ dpi->cnt = 0;
+ jme_set_rx_pcc(jme, PCC_P1);
+ jme_interrupt_mode(jme);
+ } else if (!(ecmd->use_adaptive_rx_coalesce)
+ && !(test_bit(JME_FLAG_POLL, &jme->flags))) {
+ set_bit(JME_FLAG_POLL, &jme->flags);
+ jme->jme_rx = netif_receive_skb;
+ jme->jme_vlan_rx = vlan_hwaccel_receive_skb;
+ jme_interrupt_mode(jme);
+ }
+
+ return 0;
+}
+
+static void
+jme_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 val;
+
+ ecmd->tx_pause = (jme->reg_txpfc & TXPFC_PF_EN) != 0;
+ ecmd->rx_pause = (jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0;
+
+ spin_lock_bh(&jme->phy_lock);
+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ spin_unlock_bh(&jme->phy_lock);
+
+ ecmd->autoneg =
+ (val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0;
+}
+
+static int
+jme_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 val;
+
+ if (((jme->reg_txpfc & TXPFC_PF_EN) != 0) ^
+ (ecmd->tx_pause != 0)) {
+
+ if (ecmd->tx_pause)
+ jme->reg_txpfc |= TXPFC_PF_EN;
+ else
+ jme->reg_txpfc &= ~TXPFC_PF_EN;
+
+ jwrite32(jme, JME_TXPFC, jme->reg_txpfc);
+ }
+
+ spin_lock_bh(&jme->rxmcs_lock);
+ if (((jme->reg_rxmcs & RXMCS_FLOWCTRL) != 0) ^
+ (ecmd->rx_pause != 0)) {
+
+ if (ecmd->rx_pause)
+ jme->reg_rxmcs |= RXMCS_FLOWCTRL;
+ else
+ jme->reg_rxmcs &= ~RXMCS_FLOWCTRL;
+
+ jwrite32(jme, JME_RXMCS, jme->reg_rxmcs);
+ }
+ spin_unlock_bh(&jme->rxmcs_lock);
+
+ spin_lock_bh(&jme->phy_lock);
+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ if (((val & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) != 0) ^
+ (ecmd->autoneg != 0)) {
+
+ if (ecmd->autoneg)
+ val |= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ else
+ val &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+ MII_ADVERTISE, val);
+ }
+ spin_unlock_bh(&jme->phy_lock);
+
+ return 0;
+}
+
+static void
+jme_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC | WAKE_PHY;
+
+ wol->wolopts = 0;
+
+ if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
+ wol->wolopts |= WAKE_PHY;
+
+ if (jme->reg_pmcs & PMCS_MFEN)
+ wol->wolopts |= WAKE_MAGIC;
+
+}
+
+static int
+jme_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_MAGICSECURE |
+ WAKE_UCAST |
+ WAKE_MCAST |
+ WAKE_BCAST |
+ WAKE_ARP))
+ return -EOPNOTSUPP;
+
+ jme->reg_pmcs = 0;
+
+ if (wol->wolopts & WAKE_PHY)
+ jme->reg_pmcs |= PMCS_LFEN | PMCS_LREN;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ jme->reg_pmcs |= PMCS_MFEN;
+
+ jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+
+ return 0;
+}
+
+static int
+jme_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int rc;
+
+ spin_lock_bh(&jme->phy_lock);
+ rc = mii_ethtool_gset(&(jme->mii_if), ecmd);
+ spin_unlock_bh(&jme->phy_lock);
+ return rc;
+}
+
+static int
+jme_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int rc, fdc = 0;
+
+ if (ecmd->speed == SPEED_1000 && ecmd->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ if (jme->mii_if.force_media &&
+ ecmd->autoneg != AUTONEG_ENABLE &&
+ (jme->mii_if.full_duplex != ecmd->duplex))
+ fdc = 1;
+
+ spin_lock_bh(&jme->phy_lock);
+ rc = mii_ethtool_sset(&(jme->mii_if), ecmd);
+ spin_unlock_bh(&jme->phy_lock);
+
+ if (!rc && fdc)
+ jme_reset_link(jme);
+
+ if (!rc) {
+ set_bit(JME_FLAG_SSET, &jme->flags);
+ jme->old_ecmd = *ecmd;
+ }
+
+ return rc;
+}
+
+static u32
+jme_get_link(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ return jread32(jme, JME_PHY_LINK) & PHY_LINK_UP;
+}
+
+static u32
+jme_get_msglevel(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ return jme->msg_enable;
+}
+
+static void
+jme_set_msglevel(struct net_device *netdev, u32 value)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ jme->msg_enable = value;
+}
+
+static u32
+jme_get_rx_csum(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ return jme->reg_rxmcs & RXMCS_CHECKSUM;
+}
+
+static int
+jme_set_rx_csum(struct net_device *netdev, u32 on)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ spin_lock_bh(&jme->rxmcs_lock);
+ if (on)
+ jme->reg_rxmcs |= RXMCS_CHECKSUM;
+ else
+ jme->reg_rxmcs &= ~RXMCS_CHECKSUM;
+ jwrite32(jme, JME_RXMCS, jme->reg_rxmcs);
+ spin_unlock_bh(&jme->rxmcs_lock);
+
+ return 0;
+}
+
+static int
+jme_set_tx_csum(struct net_device *netdev, u32 on)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if (on) {
+ set_bit(JME_FLAG_TXCSUM, &jme->flags);
+ if (netdev->mtu <= 1900)
+ netdev->features |= NETIF_F_HW_CSUM;
+ } else {
+ clear_bit(JME_FLAG_TXCSUM, &jme->flags);
+ netdev->features &= ~NETIF_F_HW_CSUM;
+ }
+
+ return 0;
+}
+
+static int
+jme_set_tso(struct net_device *netdev, u32 on)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ if (on) {
+ set_bit(JME_FLAG_TSO, &jme->flags);
+ if (netdev->mtu <= 1900)
+ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+ } else {
+ clear_bit(JME_FLAG_TSO, &jme->flags);
+ netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+ }
+
+ return 0;
+}
+
+static int
+jme_nway_reset(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ jme_restart_an(jme);
+ return 0;
+}
+
+static u8
+jme_smb_read(struct jme_adapter *jme, unsigned int addr)
+{
+ u32 val;
+ int to;
+
+ val = jread32(jme, JME_SMBCSR);
+ to = JME_SMB_BUSY_TIMEOUT;
+ while ((val & SMBCSR_BUSY) && --to) {
+ msleep(1);
+ val = jread32(jme, JME_SMBCSR);
+ }
+ if (!to) {
+ msg_hw(jme, "SMB Bus Busy.\n");
+ return 0xFF;
+ }
+
+ jwrite32(jme, JME_SMBINTF,
+ ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) |
+ SMBINTF_HWRWN_READ |
+ SMBINTF_HWCMD);
+
+ val = jread32(jme, JME_SMBINTF);
+ to = JME_SMB_BUSY_TIMEOUT;
+ while ((val & SMBINTF_HWCMD) && --to) {
+ msleep(1);
+ val = jread32(jme, JME_SMBINTF);
+ }
+ if (!to) {
+ msg_hw(jme, "SMB Bus Busy.\n");
+ return 0xFF;
+ }
+
+ return (val & SMBINTF_HWDATR) >> SMBINTF_HWDATR_SHIFT;
+}
+
+static void
+jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data)
+{
+ u32 val;
+ int to;
+
+ val = jread32(jme, JME_SMBCSR);
+ to = JME_SMB_BUSY_TIMEOUT;
+ while ((val & SMBCSR_BUSY) && --to) {
+ msleep(1);
+ val = jread32(jme, JME_SMBCSR);
+ }
+ if (!to) {
+ msg_hw(jme, "SMB Bus Busy.\n");
+ return;
+ }
+
+ jwrite32(jme, JME_SMBINTF,
+ ((data << SMBINTF_HWDATW_SHIFT) & SMBINTF_HWDATW) |
+ ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) |
+ SMBINTF_HWRWN_WRITE |
+ SMBINTF_HWCMD);
+
+ val = jread32(jme, JME_SMBINTF);
+ to = JME_SMB_BUSY_TIMEOUT;
+ while ((val & SMBINTF_HWCMD) && --to) {
+ msleep(1);
+ val = jread32(jme, JME_SMBINTF);
+ }
+ if (!to) {
+ msg_hw(jme, "SMB Bus Busy.\n");
+ return;
+ }
+
+ mdelay(2);
+}
+
+static int
+jme_get_eeprom_len(struct net_device *netdev)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ u32 val;
+ val = jread32(jme, JME_SMBCSR);
+ return (val & SMBCSR_EEPROMD) ? JME_SMB_LEN : 0;
+}
+
+static int
+jme_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int i, offset = eeprom->offset, len = eeprom->len;
+
+ /*
+ * ethtool will check the boundary for us
+ */
+ eeprom->magic = JME_EEPROM_MAGIC;
+ for (i = 0 ; i < len ; ++i)
+ data[i] = jme_smb_read(jme, i + offset);
+
+ return 0;
+}
+
+static int
+jme_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct jme_adapter *jme = netdev_priv(netdev);
+ int i, offset = eeprom->offset, len = eeprom->len;
+
+ if (eeprom->magic != JME_EEPROM_MAGIC)
+ return -EINVAL;
+
+ /*
+ * ethtool will check the boundary for us
+ */
+ for (i = 0 ; i < len ; ++i)
+ jme_smb_write(jme, i + offset, data[i]);
+
+ return 0;
+}
+
+static const struct ethtool_ops jme_ethtool_ops = {
+ .get_drvinfo = jme_get_drvinfo,
+ .get_regs_len = jme_get_regs_len,
+ .get_regs = jme_get_regs,
+ .get_coalesce = jme_get_coalesce,
+ .set_coalesce = jme_set_coalesce,
+ .get_pauseparam = jme_get_pauseparam,
+ .set_pauseparam = jme_set_pauseparam,
+ .get_wol = jme_get_wol,
+ .set_wol = jme_set_wol,
+ .get_settings = jme_get_settings,
+ .set_settings = jme_set_settings,
+ .get_link = jme_get_link,
+ .get_msglevel = jme_get_msglevel,
+ .set_msglevel = jme_set_msglevel,
+ .get_rx_csum = jme_get_rx_csum,
+ .set_rx_csum = jme_set_rx_csum,
+ .set_tx_csum = jme_set_tx_csum,
+ .set_tso = jme_set_tso,
+ .set_sg = ethtool_op_set_sg,
+ .nway_reset = jme_nway_reset,
+ .get_eeprom_len = jme_get_eeprom_len,
+ .get_eeprom = jme_get_eeprom,
+ .set_eeprom = jme_set_eeprom,
+};
+
+static int
+jme_pci_dma64(struct pci_dev *pdev)
+{
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ return 1;
+
+ if (!pci_set_dma_mask(pdev, DMA_40BIT_MASK))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK))
+ return 1;
+
+ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
+ return 0;
+
+ return -1;
+}
+
+static inline void
+jme_phy_init(struct jme_adapter *jme)
+{
+ u16 reg26;
+
+ reg26 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, 26);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, 26, reg26 | 0x1000);
+}
+
+static inline void
+jme_check_hw_ver(struct jme_adapter *jme)
+{
+ u32 chipmode;
+
+ chipmode = jread32(jme, JME_CHIPMODE);
+
+ jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT;
+ jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT;
+}
+
+static int __devinit
+jme_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc = 0, using_dac, i;
+ struct net_device *netdev;
+ struct jme_adapter *jme;
+ u16 bmcr, bmsr;
+ u32 apmc;
+
+ /*
+ * set up PCI device basics
+ */
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ jeprintk(pdev, "Cannot enable PCI device.\n");
+ goto err_out;
+ }
+
+ using_dac = jme_pci_dma64(pdev);
+ if (using_dac < 0) {
+ jeprintk(pdev, "Cannot set PCI DMA Mask.\n");
+ rc = -EIO;
+ goto err_out_disable_pdev;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ jeprintk(pdev, "No PCI resource region found.\n");
+ rc = -ENOMEM;
+ goto err_out_disable_pdev;
+ }
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc) {
+ jeprintk(pdev, "Cannot obtain PCI resource region.\n");
+ goto err_out_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ /*
+ * alloc and init net device
+ */
+ netdev = alloc_etherdev(sizeof(*jme));
+ if (!netdev) {
+ jeprintk(pdev, "Cannot allocate netdev structure.\n");
+ rc = -ENOMEM;
+ goto err_out_release_regions;
+ }
+ netdev->open = jme_open;
+ netdev->stop = jme_close;
+ netdev->hard_start_xmit = jme_start_xmit;
+ netdev->set_mac_address = jme_set_macaddr;
+ netdev->set_multicast_list = jme_set_multi;
+ netdev->change_mtu = jme_change_mtu;
+ netdev->ethtool_ops = &jme_ethtool_ops;
+ netdev->tx_timeout = jme_tx_timeout;
+ netdev->watchdog_timeo = TX_TIMEOUT;
+ netdev->vlan_rx_register = jme_vlan_rx_register;
+ NETDEV_GET_STATS(netdev, &jme_get_stats);
+ netdev->features = NETIF_F_HW_CSUM |
+ NETIF_F_SG |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX;
+ if (using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ pci_set_drvdata(pdev, netdev);
+
+ /*
+ * init adapter info
+ */
+ jme = netdev_priv(netdev);
+ jme->pdev = pdev;
+ jme->dev = netdev;
+ jme->jme_rx = netif_rx;
+ jme->jme_vlan_rx = vlan_hwaccel_rx;
+ jme->old_mtu = netdev->mtu = 1500;
+ jme->phylink = 0;
+ jme->tx_ring_size = 1 << 10;
+ jme->tx_ring_mask = jme->tx_ring_size - 1;
+ jme->tx_wake_threshold = 1 << 9;
+ jme->rx_ring_size = 1 << 9;
+ jme->rx_ring_mask = jme->rx_ring_size - 1;
+ jme->msg_enable = JME_DEF_MSG_ENABLE;
+ jme->regs = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!(jme->regs)) {
+ jeprintk(pdev, "Mapping PCI resource region error.\n");
+ rc = -ENOMEM;
+ goto err_out_free_netdev;
+ }
+ jme->shadow_regs = pci_alloc_consistent(pdev,
+ sizeof(u32) * SHADOW_REG_NR,
+ &(jme->shadow_dma));
+ if (!(jme->shadow_regs)) {
+ jeprintk(pdev, "Allocating shadow register mapping error.\n");
+ rc = -ENOMEM;
+ goto err_out_unmap;
+ }
+
+ if (no_pseudohp) {
+ apmc = jread32(jme, JME_APMC) & ~JME_APMC_PSEUDO_HP_EN;
+ jwrite32(jme, JME_APMC, apmc);
+ } else if (force_pseudohp) {
+ apmc = jread32(jme, JME_APMC) | JME_APMC_PSEUDO_HP_EN;
+ jwrite32(jme, JME_APMC, apmc);
+ }
+
+ NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, jme->rx_ring_size >> 2)
+
+ spin_lock_init(&jme->phy_lock);
+ spin_lock_init(&jme->macaddr_lock);
+ spin_lock_init(&jme->rxmcs_lock);
+
+ atomic_set(&jme->link_changing, 1);
+ atomic_set(&jme->rx_cleaning, 1);
+ atomic_set(&jme->tx_cleaning, 1);
+ atomic_set(&jme->rx_empty, 1);
+
+ tasklet_init(&jme->pcc_task,
+ &jme_pcc_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->linkch_task,
+ &jme_link_change_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->txclean_task,
+ &jme_tx_clean_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->rxclean_task,
+ &jme_rx_clean_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->rxempty_task,
+ &jme_rx_empty_tasklet,
+ (unsigned long) jme);
+ tasklet_disable_nosync(&jme->txclean_task);
+ tasklet_disable_nosync(&jme->rxclean_task);
+ tasklet_disable_nosync(&jme->rxempty_task);
+ jme->dpi.cur = PCC_P1;
+
+ jme->reg_ghc = 0;
+ jme->reg_rxcs = RXCS_DEFAULT;
+ jme->reg_rxmcs = RXMCS_DEFAULT;
+ jme->reg_txpfc = 0;
+ jme->reg_pmcs = PMCS_MFEN;
+ set_bit(JME_FLAG_TXCSUM, &jme->flags);
+ set_bit(JME_FLAG_TSO, &jme->flags);
+
+ /*
+ * Get Max Read Req Size from PCI Config Space
+ */
+ pci_read_config_byte(pdev, PCI_DCSR_MRRS, &jme->mrrs);
+ jme->mrrs &= PCI_DCSR_MRRS_MASK;
+ switch (jme->mrrs) {
+ case MRRS_128B:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_128B;
+ break;
+ case MRRS_256B:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_256B;
+ break;
+ default:
+ jme->reg_txcs = TXCS_DEFAULT | TXCS_DMASIZE_512B;
+ break;
+ };
+
+ /*
+ * Must check before reset_mac_processor
+ */
+ jme_check_hw_ver(jme);
+ jme->mii_if.dev = netdev;
+ if (jme->fpgaver) {
+ jme->mii_if.phy_id = 0;
+ for (i = 1 ; i < 32 ; ++i) {
+ bmcr = jme_mdio_read(netdev, i, MII_BMCR);
+ bmsr = jme_mdio_read(netdev, i, MII_BMSR);
+ if (bmcr != 0xFFFFU && (bmcr != 0 || bmsr != 0)) {
+ jme->mii_if.phy_id = i;
+ break;
+ }
+ }
+
+ if (!jme->mii_if.phy_id) {
+ rc = -EIO;
+ jeprintk(pdev, "Can not find phy_id.\n");
+ goto err_out_free_shadow;
+ }
+
+ jme->reg_ghc |= GHC_LINK_POLL;
+ } else {
+ jme->mii_if.phy_id = 1;
+ }
+ if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250)
+ jme->mii_if.supports_gmii = true;
+ else
+ jme->mii_if.supports_gmii = false;
+ jme->mii_if.mdio_read = jme_mdio_read;
+ jme->mii_if.mdio_write = jme_mdio_write;
+
+ jme_clear_pm(jme);
+ jme_set_phyfifoa(jme);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->rev);
+ if (!jme->fpgaver)
+ jme_phy_init(jme);
+ jme_phy_off(jme);
+
+ /*
+ * Reset MAC processor and reload EEPROM for MAC Address
+ */
+ jme_reset_mac_processor(jme);
+ rc = jme_reload_eeprom(jme);
+ if (rc) {
+ jeprintk(pdev,
+ "Reload eeprom for reading MAC Address error.\n");
+ goto err_out_free_shadow;
+ }
+ jme_load_macaddr(netdev);
+
+ /*
+ * Tell stack that we are not ready to work until open()
+ */
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ /*
+ * Register netdev
+ */
+ rc = register_netdev(netdev);
+ if (rc) {
+ jeprintk(pdev, "Cannot register net device.\n");
+ goto err_out_free_shadow;
+ }
+
+ msg_probe(jme,
+ "JMC250 gigabit%s ver:%x rev:%x "
+ "macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (jme->fpgaver != 0) ? " (FPGA)" : "",
+ (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
+ jme->rev,
+ netdev->dev_addr[0],
+ netdev->dev_addr[1],
+ netdev->dev_addr[2],
+ netdev->dev_addr[3],
+ netdev->dev_addr[4],
+ netdev->dev_addr[5]);
+
+ return 0;
+
+err_out_free_shadow:
+ pci_free_consistent(pdev,
+ sizeof(u32) * SHADOW_REG_NR,
+ jme->shadow_regs,
+ jme->shadow_dma);
+err_out_unmap:
+ iounmap(jme->regs);
+err_out_free_netdev:
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+err_out_release_regions:
+ pci_release_regions(pdev);
+err_out_disable_pdev:
+ pci_disable_device(pdev);
+err_out:
+ return rc;
+}
+
+static void __devexit
+jme_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+ pci_free_consistent(pdev,
+ sizeof(u32) * SHADOW_REG_NR,
+ jme->shadow_regs,
+ jme->shadow_dma);
+ iounmap(jme->regs);
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(netdev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+}
+
+#ifdef CONFIG_PM
+static int
+jme_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ atomic_dec(&jme->link_changing);
+
+ netif_device_detach(netdev);
+ netif_stop_queue(netdev);
+ jme_stop_irq(jme);
+
+ tasklet_disable(&jme->txclean_task);
+ tasklet_disable(&jme->rxclean_task);
+ tasklet_disable(&jme->rxempty_task);
+
+ jme_disable_shadow(jme);
+
+ if (netif_carrier_ok(netdev)) {
+ if (test_bit(JME_FLAG_POLL, &jme->flags))
+ jme_polling_mode(jme);
+
+ jme_stop_pcc_timer(jme);
+ jme_reset_ghc_speed(jme);
+ jme_disable_rx_engine(jme);
+ jme_disable_tx_engine(jme);
+ jme_reset_mac_processor(jme);
+ jme_free_rx_resources(jme);
+ jme_free_tx_resources(jme);
+ netif_carrier_off(netdev);
+ jme->phylink = 0;
+ }
+
+ tasklet_enable(&jme->txclean_task);
+ tasklet_hi_enable(&jme->rxclean_task);
+ tasklet_hi_enable(&jme->rxempty_task);
+
+ pci_save_state(pdev);
+ if (jme->reg_pmcs) {
+ jme_set_100m_half(jme);
+
+ if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
+ jme_wait_link(jme);
+
+ jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+
+ pci_enable_wake(pdev, PCI_D3cold, true);
+ } else {
+ jme_phy_off(jme);
+ }
+ pci_set_power_state(pdev, PCI_D3cold);
+
+ return 0;
+}
+
+static int
+jme_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct jme_adapter *jme = netdev_priv(netdev);
+
+ jme_clear_pm(jme);
+ pci_restore_state(pdev);
+
+ if (test_bit(JME_FLAG_SSET, &jme->flags))
+ jme_set_settings(netdev, &jme->old_ecmd);
+ else
+ jme_reset_phy_processor(jme);
+
+ jme_enable_shadow(jme);
+ jme_start_irq(jme);
+ netif_device_attach(netdev);
+
+ atomic_inc(&jme->link_changing);
+
+ jme_reset_link(jme);
+
+ return 0;
+}
+#endif
+
+static struct pci_device_id jme_pci_tbl[] = {
+ { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) },
+ { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) },
+ { }
+};
+
+static struct pci_driver jme_driver = {
+ .name = DRV_NAME,
+ .id_table = jme_pci_tbl,
+ .probe = jme_init_one,
+ .remove = __devexit_p(jme_remove_one),
+#ifdef CONFIG_PM
+ .suspend = jme_suspend,
+ .resume = jme_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init
+jme_init_module(void)
+{
+ printk(KERN_INFO PFX "JMicron JMC250 gigabit ethernet "
+ "driver version %s\n", DRV_VERSION);
+ return pci_register_driver(&jme_driver);
+}
+
+static void __exit
+jme_cleanup_module(void)
+{
+ pci_unregister_driver(&jme_driver);
+}
+
+module_init(jme_init_module);
+module_exit(jme_cleanup_module);
+
+MODULE_AUTHOR("Guo-Fu Tseng <cooldavid@cooldavid.org>");
+MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
+
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
new file mode 100644
index 00000000000..f863aee6648
--- /dev/null
+++ b/drivers/net/jme.h
@@ -0,0 +1,1229 @@
+/*
+ * JMicron JMC2x0 series PCIe Ethernet Linux Device Driver
+ *
+ * Copyright 2008 JMicron Technology Corporation
+ * http://www.jmicron.com/
+ *
+ * Author: Guo-Fu Tseng <cooldavid@cooldavid.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.
+ *
+ * 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 __JME_H_INCLUDED__
+#define __JME_H_INCLUDEE__
+
+#define DRV_NAME "jme"
+#define DRV_VERSION "1.0.3"
+#define PFX DRV_NAME ": "
+
+#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
+#define PCI_DEVICE_ID_JMICRON_JMC260 0x0260
+
+/*
+ * Message related definitions
+ */
+#define JME_DEF_MSG_ENABLE \
+ (NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR | \
+ NETIF_MSG_HW)
+
+#define jeprintk(pdev, fmt, args...) \
+ printk(KERN_ERR PFX fmt, ## args)
+
+#ifdef TX_DEBUG
+#define tx_dbg(priv, fmt, args...) \
+ printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ## args)
+#else
+#define tx_dbg(priv, fmt, args...)
+#endif
+
+#define jme_msg(msglvl, type, priv, fmt, args...) \
+ if (netif_msg_##type(priv)) \
+ printk(msglvl "%s: " fmt, (priv)->dev->name, ## args)
+
+#define msg_probe(priv, fmt, args...) \
+ jme_msg(KERN_INFO, probe, priv, fmt, ## args)
+
+#define msg_link(priv, fmt, args...) \
+ jme_msg(KERN_INFO, link, priv, fmt, ## args)
+
+#define msg_intr(priv, fmt, args...) \
+ jme_msg(KERN_INFO, intr, priv, fmt, ## args)
+
+#define msg_rx_err(priv, fmt, args...) \
+ jme_msg(KERN_ERR, rx_err, priv, fmt, ## args)
+
+#define msg_rx_status(priv, fmt, args...) \
+ jme_msg(KERN_INFO, rx_status, priv, fmt, ## args)
+
+#define msg_tx_err(priv, fmt, args...) \
+ jme_msg(KERN_ERR, tx_err, priv, fmt, ## args)
+
+#define msg_tx_done(priv, fmt, args...) \
+ jme_msg(KERN_INFO, tx_done, priv, fmt, ## args)
+
+#define msg_tx_queued(priv, fmt, args...) \
+ jme_msg(KERN_INFO, tx_queued, priv, fmt, ## args)
+
+#define msg_hw(priv, fmt, args...) \
+ jme_msg(KERN_ERR, hw, priv, fmt, ## args)
+
+/*
+ * Extra PCI Configuration space interface
+ */
+#define PCI_DCSR_MRRS 0x59
+#define PCI_DCSR_MRRS_MASK 0x70
+
+enum pci_dcsr_mrrs_vals {
+ MRRS_128B = 0x00,
+ MRRS_256B = 0x10,
+ MRRS_512B = 0x20,
+ MRRS_1024B = 0x30,
+ MRRS_2048B = 0x40,
+ MRRS_4096B = 0x50,
+};
+
+#define PCI_SPI 0xB0
+
+enum pci_spi_bits {
+ SPI_EN = 0x10,
+ SPI_MISO = 0x08,
+ SPI_MOSI = 0x04,
+ SPI_SCLK = 0x02,
+ SPI_CS = 0x01,
+};
+
+struct jme_spi_op {
+ void __user *uwbuf;
+ void __user *urbuf;
+ __u8 wn; /* Number of write actions */
+ __u8 rn; /* Number of read actions */
+ __u8 bitn; /* Number of bits per action */
+ __u8 spd; /* The maxim acceptable speed of controller, in MHz.*/
+ __u8 mode; /* CPOL, CPHA, and Duplex mode of SPI */
+
+ /* Internal use only */
+ u8 *kwbuf;
+ u8 *krbuf;
+ u8 sr;
+ u16 halfclk; /* Half of clock cycle calculated from spd, in ns */
+};
+
+enum jme_spi_op_bits {
+ SPI_MODE_CPHA = 0x01,
+ SPI_MODE_CPOL = 0x02,
+ SPI_MODE_DUP = 0x80,
+};
+
+#define HALF_US 500 /* 500 ns */
+#define JMESPIIOCTL SIOCDEVPRIVATE
+
+/*
+ * Dynamic(adaptive)/Static PCC values
+ */
+enum dynamic_pcc_values {
+ PCC_OFF = 0,
+ PCC_P1 = 1,
+ PCC_P2 = 2,
+ PCC_P3 = 3,
+
+ PCC_OFF_TO = 0,
+ PCC_P1_TO = 1,
+ PCC_P2_TO = 64,
+ PCC_P3_TO = 128,
+
+ PCC_OFF_CNT = 0,
+ PCC_P1_CNT = 1,
+ PCC_P2_CNT = 16,
+ PCC_P3_CNT = 32,
+};
+struct dynpcc_info {
+ unsigned long last_bytes;
+ unsigned long last_pkts;
+ unsigned long intr_cnt;
+ unsigned char cur;
+ unsigned char attempt;
+ unsigned char cnt;
+};
+#define PCC_INTERVAL_US 100000
+#define PCC_INTERVAL (HZ / (1000000 / PCC_INTERVAL_US))
+#define PCC_P3_THRESHOLD (2 * 1024 * 1024)
+#define PCC_P2_THRESHOLD 800
+#define PCC_INTR_THRESHOLD 800
+#define PCC_TX_TO 1000
+#define PCC_TX_CNT 8
+
+/*
+ * TX/RX Descriptors
+ *
+ * TX/RX Ring DESC Count Must be multiple of 16 and <= 1024
+ */
+#define RING_DESC_ALIGN 16 /* Descriptor alignment */
+#define TX_DESC_SIZE 16
+#define TX_RING_NR 8
+#define TX_RING_ALLOC_SIZE(s) ((s * TX_DESC_SIZE) + RING_DESC_ALIGN)
+
+struct txdesc {
+ union {
+ __u8 all[16];
+ __le32 dw[4];
+ struct {
+ /* DW0 */
+ __le16 vlan;
+ __u8 rsv1;
+ __u8 flags;
+
+ /* DW1 */
+ __le16 datalen;
+ __le16 mss;
+
+ /* DW2 */
+ __le16 pktsize;
+ __le16 rsv2;
+
+ /* DW3 */
+ __le32 bufaddr;
+ } desc1;
+ struct {
+ /* DW0 */
+ __le16 rsv1;
+ __u8 rsv2;
+ __u8 flags;
+
+ /* DW1 */
+ __le16 datalen;
+ __le16 rsv3;
+
+ /* DW2 */
+ __le32 bufaddrh;
+
+ /* DW3 */
+ __le32 bufaddrl;
+ } desc2;
+ struct {
+ /* DW0 */
+ __u8 ehdrsz;
+ __u8 rsv1;
+ __u8 rsv2;
+ __u8 flags;
+
+ /* DW1 */
+ __le16 trycnt;
+ __le16 segcnt;
+
+ /* DW2 */
+ __le16 pktsz;
+ __le16 rsv3;
+
+ /* DW3 */
+ __le32 bufaddrl;
+ } descwb;
+ };
+};
+
+enum jme_txdesc_flags_bits {
+ TXFLAG_OWN = 0x80,
+ TXFLAG_INT = 0x40,
+ TXFLAG_64BIT = 0x20,
+ TXFLAG_TCPCS = 0x10,
+ TXFLAG_UDPCS = 0x08,
+ TXFLAG_IPCS = 0x04,
+ TXFLAG_LSEN = 0x02,
+ TXFLAG_TAGON = 0x01,
+};
+
+#define TXDESC_MSS_SHIFT 2
+enum jme_rxdescwb_flags_bits {
+ TXWBFLAG_OWN = 0x80,
+ TXWBFLAG_INT = 0x40,
+ TXWBFLAG_TMOUT = 0x20,
+ TXWBFLAG_TRYOUT = 0x10,
+ TXWBFLAG_COL = 0x08,
+
+ TXWBFLAG_ALLERR = TXWBFLAG_TMOUT |
+ TXWBFLAG_TRYOUT |
+ TXWBFLAG_COL,
+};
+
+#define RX_DESC_SIZE 16
+#define RX_RING_NR 4
+#define RX_RING_ALLOC_SIZE(s) ((s * RX_DESC_SIZE) + RING_DESC_ALIGN)
+#define RX_BUF_DMA_ALIGN 8
+#define RX_PREPAD_SIZE 10
+#define ETH_CRC_LEN 2
+#define RX_VLANHDR_LEN 2
+#define RX_EXTRA_LEN (RX_PREPAD_SIZE + \
+ ETH_HLEN + \
+ ETH_CRC_LEN + \
+ RX_VLANHDR_LEN + \
+ RX_BUF_DMA_ALIGN)
+
+struct rxdesc {
+ union {
+ __u8 all[16];
+ __le32 dw[4];
+ struct {
+ /* DW0 */
+ __le16 rsv2;
+ __u8 rsv1;
+ __u8 flags;
+
+ /* DW1 */
+ __le16 datalen;
+ __le16 wbcpl;
+
+ /* DW2 */
+ __le32 bufaddrh;
+
+ /* DW3 */
+ __le32 bufaddrl;
+ } desc1;
+ struct {
+ /* DW0 */
+ __le16 vlan;
+ __le16 flags;
+
+ /* DW1 */
+ __le16 framesize;
+ __u8 errstat;
+ __u8 desccnt;
+
+ /* DW2 */
+ __le32 rsshash;
+
+ /* DW3 */
+ __u8 hashfun;
+ __u8 hashtype;
+ __le16 resrv;
+ } descwb;
+ };
+};
+
+enum jme_rxdesc_flags_bits {
+ RXFLAG_OWN = 0x80,
+ RXFLAG_INT = 0x40,
+ RXFLAG_64BIT = 0x20,
+};
+
+enum jme_rxwbdesc_flags_bits {
+ RXWBFLAG_OWN = 0x8000,
+ RXWBFLAG_INT = 0x4000,
+ RXWBFLAG_MF = 0x2000,
+ RXWBFLAG_64BIT = 0x2000,
+ RXWBFLAG_TCPON = 0x1000,
+ RXWBFLAG_UDPON = 0x0800,
+ RXWBFLAG_IPCS = 0x0400,
+ RXWBFLAG_TCPCS = 0x0200,
+ RXWBFLAG_UDPCS = 0x0100,
+ RXWBFLAG_TAGON = 0x0080,
+ RXWBFLAG_IPV4 = 0x0040,
+ RXWBFLAG_IPV6 = 0x0020,
+ RXWBFLAG_PAUSE = 0x0010,
+ RXWBFLAG_MAGIC = 0x0008,
+ RXWBFLAG_WAKEUP = 0x0004,
+ RXWBFLAG_DEST = 0x0003,
+ RXWBFLAG_DEST_UNI = 0x0001,
+ RXWBFLAG_DEST_MUL = 0x0002,
+ RXWBFLAG_DEST_BRO = 0x0003,
+};
+
+enum jme_rxwbdesc_desccnt_mask {
+ RXWBDCNT_WBCPL = 0x80,
+ RXWBDCNT_DCNT = 0x7F,
+};
+
+enum jme_rxwbdesc_errstat_bits {
+ RXWBERR_LIMIT = 0x80,
+ RXWBERR_MIIER = 0x40,
+ RXWBERR_NIBON = 0x20,
+ RXWBERR_COLON = 0x10,
+ RXWBERR_ABORT = 0x08,
+ RXWBERR_SHORT = 0x04,
+ RXWBERR_OVERUN = 0x02,
+ RXWBERR_CRCERR = 0x01,
+ RXWBERR_ALLERR = 0xFF,
+};
+
+/*
+ * Buffer information corresponding to ring descriptors.
+ */
+struct jme_buffer_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ int len;
+ int nr_desc;
+ unsigned long start_xmit;
+};
+
+/*
+ * The structure holding buffer information and ring descriptors all together.
+ */
+#define MAX_RING_DESC_NR 1024
+struct jme_ring {
+ void *alloc; /* pointer to allocated memory */
+ void *desc; /* pointer to ring memory */
+ dma_addr_t dmaalloc; /* phys address of ring alloc */
+ dma_addr_t dma; /* phys address for ring dma */
+
+ /* Buffer information corresponding to each descriptor */
+ struct jme_buffer_info bufinf[MAX_RING_DESC_NR];
+
+ int next_to_use;
+ atomic_t next_to_clean;
+ atomic_t nr_free;
+};
+
+#define NET_STAT(priv) (priv->dev->stats)
+#define NETDEV_GET_STATS(netdev, fun_ptr)
+#define DECLARE_NET_DEVICE_STATS
+
+#define DECLARE_NAPI_STRUCT struct napi_struct napi;
+#define NETIF_NAPI_SET(dev, napis, pollfn, q) \
+ netif_napi_add(dev, napis, pollfn, q);
+#define JME_NAPI_HOLDER(holder) struct napi_struct *holder
+#define JME_NAPI_WEIGHT(w) int w
+#define JME_NAPI_WEIGHT_VAL(w) w
+#define JME_NAPI_WEIGHT_SET(w, r)
+#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev, napis)
+#define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi);
+#define JME_NAPI_DISABLE(priv) \
+ if (!napi_disable_pending(&priv->napi)) \
+ napi_disable(&priv->napi);
+#define JME_RX_SCHEDULE_PREP(priv) \
+ netif_rx_schedule_prep(priv->dev, &priv->napi)
+#define JME_RX_SCHEDULE(priv) \
+ __netif_rx_schedule(priv->dev, &priv->napi);
+
+/*
+ * Jmac Adapter Private data
+ */
+#define SHADOW_REG_NR 8
+struct jme_adapter {
+ struct pci_dev *pdev;
+ struct net_device *dev;
+ void __iomem *regs;
+ dma_addr_t shadow_dma;
+ u32 *shadow_regs;
+ struct mii_if_info mii_if;
+ struct jme_ring rxring[RX_RING_NR];
+ struct jme_ring txring[TX_RING_NR];
+ spinlock_t phy_lock;
+ spinlock_t macaddr_lock;
+ spinlock_t rxmcs_lock;
+ struct tasklet_struct rxempty_task;
+ struct tasklet_struct rxclean_task;
+ struct tasklet_struct txclean_task;
+ struct tasklet_struct linkch_task;
+ struct tasklet_struct pcc_task;
+ unsigned long flags;
+ u32 reg_txcs;
+ u32 reg_txpfc;
+ u32 reg_rxcs;
+ u32 reg_rxmcs;
+ u32 reg_ghc;
+ u32 reg_pmcs;
+ u32 phylink;
+ u32 tx_ring_size;
+ u32 tx_ring_mask;
+ u32 tx_wake_threshold;
+ u32 rx_ring_size;
+ u32 rx_ring_mask;
+ u8 mrrs;
+ unsigned int fpgaver;
+ unsigned int chiprev;
+ u8 rev;
+ u32 msg_enable;
+ struct ethtool_cmd old_ecmd;
+ unsigned int old_mtu;
+ struct vlan_group *vlgrp;
+ struct dynpcc_info dpi;
+ atomic_t intr_sem;
+ atomic_t link_changing;
+ atomic_t tx_cleaning;
+ atomic_t rx_cleaning;
+ atomic_t rx_empty;
+ int (*jme_rx)(struct sk_buff *skb);
+ int (*jme_vlan_rx)(struct sk_buff *skb,
+ struct vlan_group *grp,
+ unsigned short vlan_tag);
+ DECLARE_NAPI_STRUCT
+ DECLARE_NET_DEVICE_STATS
+};
+
+enum shadow_reg_val {
+ SHADOW_IEVE = 0,
+};
+
+enum jme_flags_bits {
+ JME_FLAG_MSI = 1,
+ JME_FLAG_SSET = 2,
+ JME_FLAG_TXCSUM = 3,
+ JME_FLAG_TSO = 4,
+ JME_FLAG_POLL = 5,
+ JME_FLAG_SHUTDOWN = 6,
+};
+
+#define TX_TIMEOUT (5 * HZ)
+#define JME_REG_LEN 0x500
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9216
+
+static inline struct jme_adapter*
+jme_napi_priv(struct napi_struct *napi)
+{
+ struct jme_adapter *jme;
+ jme = container_of(napi, struct jme_adapter, napi);
+ return jme;
+}
+
+/*
+ * MMaped I/O Resters
+ */
+enum jme_iomap_offsets {
+ JME_MAC = 0x0000,
+ JME_PHY = 0x0400,
+ JME_MISC = 0x0800,
+ JME_RSS = 0x0C00,
+};
+
+enum jme_iomap_lens {
+ JME_MAC_LEN = 0x80,
+ JME_PHY_LEN = 0x58,
+ JME_MISC_LEN = 0x98,
+ JME_RSS_LEN = 0xFF,
+};
+
+enum jme_iomap_regs {
+ JME_TXCS = JME_MAC | 0x00, /* Transmit Control and Status */
+ JME_TXDBA_LO = JME_MAC | 0x04, /* Transmit Queue Desc Base Addr */
+ JME_TXDBA_HI = JME_MAC | 0x08, /* Transmit Queue Desc Base Addr */
+ JME_TXQDC = JME_MAC | 0x0C, /* Transmit Queue Desc Count */
+ JME_TXNDA = JME_MAC | 0x10, /* Transmit Queue Next Desc Addr */
+ JME_TXMCS = JME_MAC | 0x14, /* Transmit MAC Control Status */
+ JME_TXPFC = JME_MAC | 0x18, /* Transmit Pause Frame Control */
+ JME_TXTRHD = JME_MAC | 0x1C, /* Transmit Timer/Retry@Half-Dup */
+
+ JME_RXCS = JME_MAC | 0x20, /* Receive Control and Status */
+ JME_RXDBA_LO = JME_MAC | 0x24, /* Receive Queue Desc Base Addr */
+ JME_RXDBA_HI = JME_MAC | 0x28, /* Receive Queue Desc Base Addr */
+ JME_RXQDC = JME_MAC | 0x2C, /* Receive Queue Desc Count */
+ JME_RXNDA = JME_MAC | 0x30, /* Receive Queue Next Desc Addr */
+ JME_RXMCS = JME_MAC | 0x34, /* Receive MAC Control Status */
+ JME_RXUMA_LO = JME_MAC | 0x38, /* Receive Unicast MAC Address */
+ JME_RXUMA_HI = JME_MAC | 0x3C, /* Receive Unicast MAC Address */
+ JME_RXMCHT_LO = JME_MAC | 0x40, /* Recv Multicast Addr HashTable */
+ JME_RXMCHT_HI = JME_MAC | 0x44, /* Recv Multicast Addr HashTable */
+ JME_WFODP = JME_MAC | 0x48, /* Wakeup Frame Output Data Port */
+ JME_WFOI = JME_MAC | 0x4C, /* Wakeup Frame Output Interface */
+
+ JME_SMI = JME_MAC | 0x50, /* Station Management Interface */
+ JME_GHC = JME_MAC | 0x54, /* Global Host Control */
+ JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */
+
+
+ JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */
+ JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
+ JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
+ JME_SMBINTF = JME_PHY | 0x44, /* SMB Interface */
+
+
+ JME_TMCSR = JME_MISC | 0x00, /* Timer Control/Status Register */
+ JME_GPREG0 = JME_MISC | 0x08, /* General purpose REG-0 */
+ JME_GPREG1 = JME_MISC | 0x0C, /* General purpose REG-1 */
+ JME_IEVE = JME_MISC | 0x20, /* Interrupt Event Status */
+ JME_IREQ = JME_MISC | 0x24, /* Intr Req Status(For Debug) */
+ JME_IENS = JME_MISC | 0x28, /* Intr Enable - Setting Port */
+ JME_IENC = JME_MISC | 0x2C, /* Interrupt Enable - Clear Port */
+ JME_PCCRX0 = JME_MISC | 0x30, /* PCC Control for RX Queue 0 */
+ JME_PCCTX = JME_MISC | 0x40, /* PCC Control for TX Queues */
+ JME_CHIPMODE = JME_MISC | 0x44, /* Identify FPGA Version */
+ JME_SHBA_HI = JME_MISC | 0x48, /* Shadow Register Base HI */
+ JME_SHBA_LO = JME_MISC | 0x4C, /* Shadow Register Base LO */
+ JME_TIMER1 = JME_MISC | 0x70, /* Timer1 */
+ JME_TIMER2 = JME_MISC | 0x74, /* Timer2 */
+ JME_APMC = JME_MISC | 0x7C, /* Aggressive Power Mode Control */
+ JME_PCCSRX0 = JME_MISC | 0x80, /* PCC Status of RX0 */
+};
+
+/*
+ * TX Control/Status Bits
+ */
+enum jme_txcs_bits {
+ TXCS_QUEUE7S = 0x00008000,
+ TXCS_QUEUE6S = 0x00004000,
+ TXCS_QUEUE5S = 0x00002000,
+ TXCS_QUEUE4S = 0x00001000,
+ TXCS_QUEUE3S = 0x00000800,
+ TXCS_QUEUE2S = 0x00000400,
+ TXCS_QUEUE1S = 0x00000200,
+ TXCS_QUEUE0S = 0x00000100,
+ TXCS_FIFOTH = 0x000000C0,
+ TXCS_DMASIZE = 0x00000030,
+ TXCS_BURST = 0x00000004,
+ TXCS_ENABLE = 0x00000001,
+};
+
+enum jme_txcs_value {
+ TXCS_FIFOTH_16QW = 0x000000C0,
+ TXCS_FIFOTH_12QW = 0x00000080,
+ TXCS_FIFOTH_8QW = 0x00000040,
+ TXCS_FIFOTH_4QW = 0x00000000,
+
+ TXCS_DMASIZE_64B = 0x00000000,
+ TXCS_DMASIZE_128B = 0x00000010,
+ TXCS_DMASIZE_256B = 0x00000020,
+ TXCS_DMASIZE_512B = 0x00000030,
+
+ TXCS_SELECT_QUEUE0 = 0x00000000,
+ TXCS_SELECT_QUEUE1 = 0x00010000,
+ TXCS_SELECT_QUEUE2 = 0x00020000,
+ TXCS_SELECT_QUEUE3 = 0x00030000,
+ TXCS_SELECT_QUEUE4 = 0x00040000,
+ TXCS_SELECT_QUEUE5 = 0x00050000,
+ TXCS_SELECT_QUEUE6 = 0x00060000,
+ TXCS_SELECT_QUEUE7 = 0x00070000,
+
+ TXCS_DEFAULT = TXCS_FIFOTH_4QW |
+ TXCS_BURST,
+};
+
+#define JME_TX_DISABLE_TIMEOUT 10 /* 10 msec */
+
+/*
+ * TX MAC Control/Status Bits
+ */
+enum jme_txmcs_bit_masks {
+ TXMCS_IFG2 = 0xC0000000,
+ TXMCS_IFG1 = 0x30000000,
+ TXMCS_TTHOLD = 0x00000300,
+ TXMCS_FBURST = 0x00000080,
+ TXMCS_CARRIEREXT = 0x00000040,
+ TXMCS_DEFER = 0x00000020,
+ TXMCS_BACKOFF = 0x00000010,
+ TXMCS_CARRIERSENSE = 0x00000008,
+ TXMCS_COLLISION = 0x00000004,
+ TXMCS_CRC = 0x00000002,
+ TXMCS_PADDING = 0x00000001,
+};
+
+enum jme_txmcs_values {
+ TXMCS_IFG2_6_4 = 0x00000000,
+ TXMCS_IFG2_8_5 = 0x40000000,
+ TXMCS_IFG2_10_6 = 0x80000000,
+ TXMCS_IFG2_12_7 = 0xC0000000,
+
+ TXMCS_IFG1_8_4 = 0x00000000,
+ TXMCS_IFG1_12_6 = 0x10000000,
+ TXMCS_IFG1_16_8 = 0x20000000,
+ TXMCS_IFG1_20_10 = 0x30000000,
+
+ TXMCS_TTHOLD_1_8 = 0x00000000,
+ TXMCS_TTHOLD_1_4 = 0x00000100,
+ TXMCS_TTHOLD_1_2 = 0x00000200,
+ TXMCS_TTHOLD_FULL = 0x00000300,
+
+ TXMCS_DEFAULT = TXMCS_IFG2_8_5 |
+ TXMCS_IFG1_16_8 |
+ TXMCS_TTHOLD_FULL |
+ TXMCS_DEFER |
+ TXMCS_CRC |
+ TXMCS_PADDING,
+};
+
+enum jme_txpfc_bits_masks {
+ TXPFC_VLAN_TAG = 0xFFFF0000,
+ TXPFC_VLAN_EN = 0x00008000,
+ TXPFC_PF_EN = 0x00000001,
+};
+
+enum jme_txtrhd_bits_masks {
+ TXTRHD_TXPEN = 0x80000000,
+ TXTRHD_TXP = 0x7FFFFF00,
+ TXTRHD_TXREN = 0x00000080,
+ TXTRHD_TXRL = 0x0000007F,
+};
+
+enum jme_txtrhd_shifts {
+ TXTRHD_TXP_SHIFT = 8,
+ TXTRHD_TXRL_SHIFT = 0,
+};
+
+/*
+ * RX Control/Status Bits
+ */
+enum jme_rxcs_bit_masks {
+ /* FIFO full threshold for transmitting Tx Pause Packet */
+ RXCS_FIFOTHTP = 0x30000000,
+ /* FIFO threshold for processing next packet */
+ RXCS_FIFOTHNP = 0x0C000000,
+ RXCS_DMAREQSZ = 0x03000000, /* DMA Request Size */
+ RXCS_QUEUESEL = 0x00030000, /* Queue selection */
+ RXCS_RETRYGAP = 0x0000F000, /* RX Desc full retry gap */
+ RXCS_RETRYCNT = 0x00000F00, /* RX Desc full retry counter */
+ RXCS_WAKEUP = 0x00000040, /* Enable receive wakeup packet */
+ RXCS_MAGIC = 0x00000020, /* Enable receive magic packet */
+ RXCS_SHORT = 0x00000010, /* Enable receive short packet */
+ RXCS_ABORT = 0x00000008, /* Enable receive errorr packet */
+ RXCS_QST = 0x00000004, /* Receive queue start */
+ RXCS_SUSPEND = 0x00000002,
+ RXCS_ENABLE = 0x00000001,
+};
+
+enum jme_rxcs_values {
+ RXCS_FIFOTHTP_16T = 0x00000000,
+ RXCS_FIFOTHTP_32T = 0x10000000,
+ RXCS_FIFOTHTP_64T = 0x20000000,
+ RXCS_FIFOTHTP_128T = 0x30000000,
+
+ RXCS_FIFOTHNP_16QW = 0x00000000,
+ RXCS_FIFOTHNP_32QW = 0x04000000,
+ RXCS_FIFOTHNP_64QW = 0x08000000,
+ RXCS_FIFOTHNP_128QW = 0x0C000000,
+
+ RXCS_DMAREQSZ_16B = 0x00000000,
+ RXCS_DMAREQSZ_32B = 0x01000000,
+ RXCS_DMAREQSZ_64B = 0x02000000,
+ RXCS_DMAREQSZ_128B = 0x03000000,
+
+ RXCS_QUEUESEL_Q0 = 0x00000000,
+ RXCS_QUEUESEL_Q1 = 0x00010000,
+ RXCS_QUEUESEL_Q2 = 0x00020000,
+ RXCS_QUEUESEL_Q3 = 0x00030000,
+
+ RXCS_RETRYGAP_256ns = 0x00000000,
+ RXCS_RETRYGAP_512ns = 0x00001000,
+ RXCS_RETRYGAP_1024ns = 0x00002000,
+ RXCS_RETRYGAP_2048ns = 0x00003000,
+ RXCS_RETRYGAP_4096ns = 0x00004000,
+ RXCS_RETRYGAP_8192ns = 0x00005000,
+ RXCS_RETRYGAP_16384ns = 0x00006000,
+ RXCS_RETRYGAP_32768ns = 0x00007000,
+
+ RXCS_RETRYCNT_0 = 0x00000000,
+ RXCS_RETRYCNT_4 = 0x00000100,
+ RXCS_RETRYCNT_8 = 0x00000200,
+ RXCS_RETRYCNT_12 = 0x00000300,
+ RXCS_RETRYCNT_16 = 0x00000400,
+ RXCS_RETRYCNT_20 = 0x00000500,
+ RXCS_RETRYCNT_24 = 0x00000600,
+ RXCS_RETRYCNT_28 = 0x00000700,
+ RXCS_RETRYCNT_32 = 0x00000800,
+ RXCS_RETRYCNT_36 = 0x00000900,
+ RXCS_RETRYCNT_40 = 0x00000A00,
+ RXCS_RETRYCNT_44 = 0x00000B00,
+ RXCS_RETRYCNT_48 = 0x00000C00,
+ RXCS_RETRYCNT_52 = 0x00000D00,
+ RXCS_RETRYCNT_56 = 0x00000E00,
+ RXCS_RETRYCNT_60 = 0x00000F00,
+
+ RXCS_DEFAULT = RXCS_FIFOTHTP_128T |
+ RXCS_FIFOTHNP_128QW |
+ RXCS_DMAREQSZ_128B |
+ RXCS_RETRYGAP_256ns |
+ RXCS_RETRYCNT_32,
+};
+
+#define JME_RX_DISABLE_TIMEOUT 10 /* 10 msec */
+
+/*
+ * RX MAC Control/Status Bits
+ */
+enum jme_rxmcs_bits {
+ RXMCS_ALLFRAME = 0x00000800,
+ RXMCS_BRDFRAME = 0x00000400,
+ RXMCS_MULFRAME = 0x00000200,
+ RXMCS_UNIFRAME = 0x00000100,
+ RXMCS_ALLMULFRAME = 0x00000080,
+ RXMCS_MULFILTERED = 0x00000040,
+ RXMCS_RXCOLLDEC = 0x00000020,
+ RXMCS_FLOWCTRL = 0x00000008,
+ RXMCS_VTAGRM = 0x00000004,
+ RXMCS_PREPAD = 0x00000002,
+ RXMCS_CHECKSUM = 0x00000001,
+
+ RXMCS_DEFAULT = RXMCS_VTAGRM |
+ RXMCS_PREPAD |
+ RXMCS_FLOWCTRL |
+ RXMCS_CHECKSUM,
+};
+
+/*
+ * Wakeup Frame setup interface registers
+ */
+#define WAKEUP_FRAME_NR 8
+#define WAKEUP_FRAME_MASK_DWNR 4
+
+enum jme_wfoi_bit_masks {
+ WFOI_MASK_SEL = 0x00000070,
+ WFOI_CRC_SEL = 0x00000008,
+ WFOI_FRAME_SEL = 0x00000007,
+};
+
+enum jme_wfoi_shifts {
+ WFOI_MASK_SHIFT = 4,
+};
+
+/*
+ * SMI Related definitions
+ */
+enum jme_smi_bit_mask {
+ SMI_DATA_MASK = 0xFFFF0000,
+ SMI_REG_ADDR_MASK = 0x0000F800,
+ SMI_PHY_ADDR_MASK = 0x000007C0,
+ SMI_OP_WRITE = 0x00000020,
+ /* Set to 1, after req done it'll be cleared to 0 */
+ SMI_OP_REQ = 0x00000010,
+ SMI_OP_MDIO = 0x00000008, /* Software assess In/Out */
+ SMI_OP_MDOE = 0x00000004, /* Software Output Enable */
+ SMI_OP_MDC = 0x00000002, /* Software CLK Control */
+ SMI_OP_MDEN = 0x00000001, /* Software access Enable */
+};
+
+enum jme_smi_bit_shift {
+ SMI_DATA_SHIFT = 16,
+ SMI_REG_ADDR_SHIFT = 11,
+ SMI_PHY_ADDR_SHIFT = 6,
+};
+
+static inline u32 smi_reg_addr(int x)
+{
+ return (x << SMI_REG_ADDR_SHIFT) & SMI_REG_ADDR_MASK;
+}
+
+static inline u32 smi_phy_addr(int x)
+{
+ return (x << SMI_PHY_ADDR_SHIFT) & SMI_PHY_ADDR_MASK;
+}
+
+#define JME_PHY_TIMEOUT 100 /* 100 msec */
+#define JME_PHY_REG_NR 32
+
+/*
+ * Global Host Control
+ */
+enum jme_ghc_bit_mask {
+ GHC_SWRST = 0x40000000,
+ GHC_DPX = 0x00000040,
+ GHC_SPEED = 0x00000030,
+ GHC_LINK_POLL = 0x00000001,
+};
+
+enum jme_ghc_speed_val {
+ GHC_SPEED_10M = 0x00000010,
+ GHC_SPEED_100M = 0x00000020,
+ GHC_SPEED_1000M = 0x00000030,
+};
+
+/*
+ * Power management control and status register
+ */
+enum jme_pmcs_bit_masks {
+ PMCS_WF7DET = 0x80000000,
+ PMCS_WF6DET = 0x40000000,
+ PMCS_WF5DET = 0x20000000,
+ PMCS_WF4DET = 0x10000000,
+ PMCS_WF3DET = 0x08000000,
+ PMCS_WF2DET = 0x04000000,
+ PMCS_WF1DET = 0x02000000,
+ PMCS_WF0DET = 0x01000000,
+ PMCS_LFDET = 0x00040000,
+ PMCS_LRDET = 0x00020000,
+ PMCS_MFDET = 0x00010000,
+ PMCS_WF7EN = 0x00008000,
+ PMCS_WF6EN = 0x00004000,
+ PMCS_WF5EN = 0x00002000,
+ PMCS_WF4EN = 0x00001000,
+ PMCS_WF3EN = 0x00000800,
+ PMCS_WF2EN = 0x00000400,
+ PMCS_WF1EN = 0x00000200,
+ PMCS_WF0EN = 0x00000100,
+ PMCS_LFEN = 0x00000004,
+ PMCS_LREN = 0x00000002,
+ PMCS_MFEN = 0x00000001,
+};
+
+/*
+ * Giga PHY Status Registers
+ */
+enum jme_phy_link_bit_mask {
+ PHY_LINK_SPEED_MASK = 0x0000C000,
+ PHY_LINK_DUPLEX = 0x00002000,
+ PHY_LINK_SPEEDDPU_RESOLVED = 0x00000800,
+ PHY_LINK_UP = 0x00000400,
+ PHY_LINK_AUTONEG_COMPLETE = 0x00000200,
+ PHY_LINK_MDI_STAT = 0x00000040,
+};
+
+enum jme_phy_link_speed_val {
+ PHY_LINK_SPEED_10M = 0x00000000,
+ PHY_LINK_SPEED_100M = 0x00004000,
+ PHY_LINK_SPEED_1000M = 0x00008000,
+};
+
+#define JME_SPDRSV_TIMEOUT 500 /* 500 us */
+
+/*
+ * SMB Control and Status
+ */
+enum jme_smbcsr_bit_mask {
+ SMBCSR_CNACK = 0x00020000,
+ SMBCSR_RELOAD = 0x00010000,
+ SMBCSR_EEPROMD = 0x00000020,
+ SMBCSR_INITDONE = 0x00000010,
+ SMBCSR_BUSY = 0x0000000F,
+};
+
+enum jme_smbintf_bit_mask {
+ SMBINTF_HWDATR = 0xFF000000,
+ SMBINTF_HWDATW = 0x00FF0000,
+ SMBINTF_HWADDR = 0x0000FF00,
+ SMBINTF_HWRWN = 0x00000020,
+ SMBINTF_HWCMD = 0x00000010,
+ SMBINTF_FASTM = 0x00000008,
+ SMBINTF_GPIOSCL = 0x00000004,
+ SMBINTF_GPIOSDA = 0x00000002,
+ SMBINTF_GPIOEN = 0x00000001,
+};
+
+enum jme_smbintf_vals {
+ SMBINTF_HWRWN_READ = 0x00000020,
+ SMBINTF_HWRWN_WRITE = 0x00000000,
+};
+
+enum jme_smbintf_shifts {
+ SMBINTF_HWDATR_SHIFT = 24,
+ SMBINTF_HWDATW_SHIFT = 16,
+ SMBINTF_HWADDR_SHIFT = 8,
+};
+
+#define JME_EEPROM_RELOAD_TIMEOUT 2000 /* 2000 msec */
+#define JME_SMB_BUSY_TIMEOUT 20 /* 20 msec */
+#define JME_SMB_LEN 256
+#define JME_EEPROM_MAGIC 0x250
+
+/*
+ * Timer Control/Status Register
+ */
+enum jme_tmcsr_bit_masks {
+ TMCSR_SWIT = 0x80000000,
+ TMCSR_EN = 0x01000000,
+ TMCSR_CNT = 0x00FFFFFF,
+};
+
+/*
+ * General Purpose REG-0
+ */
+enum jme_gpreg0_masks {
+ GPREG0_DISSH = 0xFF000000,
+ GPREG0_PCIRLMT = 0x00300000,
+ GPREG0_PCCNOMUTCLR = 0x00040000,
+ GPREG0_LNKINTPOLL = 0x00001000,
+ GPREG0_PCCTMR = 0x00000300,
+ GPREG0_PHYADDR = 0x0000001F,
+};
+
+enum jme_gpreg0_vals {
+ GPREG0_DISSH_DW7 = 0x80000000,
+ GPREG0_DISSH_DW6 = 0x40000000,
+ GPREG0_DISSH_DW5 = 0x20000000,
+ GPREG0_DISSH_DW4 = 0x10000000,
+ GPREG0_DISSH_DW3 = 0x08000000,
+ GPREG0_DISSH_DW2 = 0x04000000,
+ GPREG0_DISSH_DW1 = 0x02000000,
+ GPREG0_DISSH_DW0 = 0x01000000,
+ GPREG0_DISSH_ALL = 0xFF000000,
+
+ GPREG0_PCIRLMT_8 = 0x00000000,
+ GPREG0_PCIRLMT_6 = 0x00100000,
+ GPREG0_PCIRLMT_5 = 0x00200000,
+ GPREG0_PCIRLMT_4 = 0x00300000,
+
+ GPREG0_PCCTMR_16ns = 0x00000000,
+ GPREG0_PCCTMR_256ns = 0x00000100,
+ GPREG0_PCCTMR_1us = 0x00000200,
+ GPREG0_PCCTMR_1ms = 0x00000300,
+
+ GPREG0_PHYADDR_1 = 0x00000001,
+
+ GPREG0_DEFAULT = GPREG0_PCIRLMT_4 |
+ GPREG0_PCCTMR_1us |
+ GPREG0_PHYADDR_1,
+};
+
+/*
+ * General Purpose REG-1
+ * Note: All theses bits defined here are for
+ * Chip mode revision 0x11 only
+ */
+enum jme_gpreg1_masks {
+ GPREG1_INTRDELAYUNIT = 0x00000018,
+ GPREG1_INTRDELAYENABLE = 0x00000007,
+};
+
+enum jme_gpreg1_vals {
+ GPREG1_RSSPATCH = 0x00000040,
+ GPREG1_HALFMODEPATCH = 0x00000020,
+
+ GPREG1_INTDLYUNIT_16NS = 0x00000000,
+ GPREG1_INTDLYUNIT_256NS = 0x00000008,
+ GPREG1_INTDLYUNIT_1US = 0x00000010,
+ GPREG1_INTDLYUNIT_16US = 0x00000018,
+
+ GPREG1_INTDLYEN_1U = 0x00000001,
+ GPREG1_INTDLYEN_2U = 0x00000002,
+ GPREG1_INTDLYEN_3U = 0x00000003,
+ GPREG1_INTDLYEN_4U = 0x00000004,
+ GPREG1_INTDLYEN_5U = 0x00000005,
+ GPREG1_INTDLYEN_6U = 0x00000006,
+ GPREG1_INTDLYEN_7U = 0x00000007,
+
+ GPREG1_DEFAULT = 0x00000000,
+};
+
+/*
+ * Interrupt Status Bits
+ */
+enum jme_interrupt_bits {
+ INTR_SWINTR = 0x80000000,
+ INTR_TMINTR = 0x40000000,
+ INTR_LINKCH = 0x20000000,
+ INTR_PAUSERCV = 0x10000000,
+ INTR_MAGICRCV = 0x08000000,
+ INTR_WAKERCV = 0x04000000,
+ INTR_PCCRX0TO = 0x02000000,
+ INTR_PCCRX1TO = 0x01000000,
+ INTR_PCCRX2TO = 0x00800000,
+ INTR_PCCRX3TO = 0x00400000,
+ INTR_PCCTXTO = 0x00200000,
+ INTR_PCCRX0 = 0x00100000,
+ INTR_PCCRX1 = 0x00080000,
+ INTR_PCCRX2 = 0x00040000,
+ INTR_PCCRX3 = 0x00020000,
+ INTR_PCCTX = 0x00010000,
+ INTR_RX3EMP = 0x00008000,
+ INTR_RX2EMP = 0x00004000,
+ INTR_RX1EMP = 0x00002000,
+ INTR_RX0EMP = 0x00001000,
+ INTR_RX3 = 0x00000800,
+ INTR_RX2 = 0x00000400,
+ INTR_RX1 = 0x00000200,
+ INTR_RX0 = 0x00000100,
+ INTR_TX7 = 0x00000080,
+ INTR_TX6 = 0x00000040,
+ INTR_TX5 = 0x00000020,
+ INTR_TX4 = 0x00000010,
+ INTR_TX3 = 0x00000008,
+ INTR_TX2 = 0x00000004,
+ INTR_TX1 = 0x00000002,
+ INTR_TX0 = 0x00000001,
+};
+
+static const u32 INTR_ENABLE = INTR_SWINTR |
+ INTR_TMINTR |
+ INTR_LINKCH |
+ INTR_PCCRX0TO |
+ INTR_PCCRX0 |
+ INTR_PCCTXTO |
+ INTR_PCCTX |
+ INTR_RX0EMP;
+
+/*
+ * PCC Control Registers
+ */
+enum jme_pccrx_masks {
+ PCCRXTO_MASK = 0xFFFF0000,
+ PCCRX_MASK = 0x0000FF00,
+};
+
+enum jme_pcctx_masks {
+ PCCTXTO_MASK = 0xFFFF0000,
+ PCCTX_MASK = 0x0000FF00,
+ PCCTX_QS_MASK = 0x000000FF,
+};
+
+enum jme_pccrx_shifts {
+ PCCRXTO_SHIFT = 16,
+ PCCRX_SHIFT = 8,
+};
+
+enum jme_pcctx_shifts {
+ PCCTXTO_SHIFT = 16,
+ PCCTX_SHIFT = 8,
+};
+
+enum jme_pcctx_bits {
+ PCCTXQ0_EN = 0x00000001,
+ PCCTXQ1_EN = 0x00000002,
+ PCCTXQ2_EN = 0x00000004,
+ PCCTXQ3_EN = 0x00000008,
+ PCCTXQ4_EN = 0x00000010,
+ PCCTXQ5_EN = 0x00000020,
+ PCCTXQ6_EN = 0x00000040,
+ PCCTXQ7_EN = 0x00000080,
+};
+
+/*
+ * Chip Mode Register
+ */
+enum jme_chipmode_bit_masks {
+ CM_FPGAVER_MASK = 0xFFFF0000,
+ CM_CHIPREV_MASK = 0x0000FF00,
+ CM_CHIPMODE_MASK = 0x0000000F,
+};
+
+enum jme_chipmode_shifts {
+ CM_FPGAVER_SHIFT = 16,
+ CM_CHIPREV_SHIFT = 8,
+};
+
+/*
+ * Shadow base address register bits
+ */
+enum jme_shadow_base_address_bits {
+ SHBA_POSTEN = 0x1,
+};
+
+/*
+ * Aggressive Power Mode Control
+ */
+enum jme_apmc_bits {
+ JME_APMC_PCIE_SD_EN = 0x40000000,
+ JME_APMC_PSEUDO_HP_EN = 0x20000000,
+ JME_APMC_EPIEN = 0x04000000,
+ JME_APMC_EPIEN_CTRL = 0x03000000,
+};
+
+enum jme_apmc_values {
+ JME_APMC_EPIEN_CTRL_EN = 0x02000000,
+ JME_APMC_EPIEN_CTRL_DIS = 0x01000000,
+};
+
+#define APMC_PHP_SHUTDOWN_DELAY (10 * 1000 * 1000)
+
+#ifdef REG_DEBUG
+static char *MAC_REG_NAME[] = {
+ "JME_TXCS", "JME_TXDBA_LO", "JME_TXDBA_HI", "JME_TXQDC",
+ "JME_TXNDA", "JME_TXMCS", "JME_TXPFC", "JME_TXTRHD",
+ "JME_RXCS", "JME_RXDBA_LO", "JME_RXDBA_HI", "JME_RXQDC",
+ "JME_RXNDA", "JME_RXMCS", "JME_RXUMA_LO", "JME_RXUMA_HI",
+ "JME_RXMCHT_LO", "JME_RXMCHT_HI", "JME_WFODP", "JME_WFOI",
+ "JME_SMI", "JME_GHC", "UNKNOWN", "UNKNOWN",
+ "JME_PMCS"};
+
+static char *PE_REG_NAME[] = {
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "JME_PHY_CS", "UNKNOWN",
+ "JME_PHY_LINK", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "JME_SMBCSR", "JME_SMBINTF"};
+
+static char *MISC_REG_NAME[] = {
+ "JME_TMCSR", "JME_GPIO", "JME_GPREG0", "JME_GPREG1",
+ "JME_IEVE", "JME_IREQ", "JME_IENS", "JME_IENC",
+ "JME_PCCRX0", "JME_PCCRX1", "JME_PCCRX2", "JME_PCCRX3",
+ "JME_PCCTX0", "JME_CHIPMODE", "JME_SHBA_HI", "JME_SHBA_LO",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "JME_TIMER1", "JME_TIMER2", "UNKNOWN", "JME_APMC",
+ "JME_PCCSRX0"};
+
+static inline void reg_dbg(const struct jme_adapter *jme,
+ const char *msg, u32 val, u32 reg)
+{
+ const char *regname;
+ switch (reg & 0xF00) {
+ case 0x000:
+ regname = MAC_REG_NAME[(reg & 0xFF) >> 2];
+ break;
+ case 0x400:
+ regname = PE_REG_NAME[(reg & 0xFF) >> 2];
+ break;
+ case 0x800:
+ regname = MISC_REG_NAME[(reg & 0xFF) >> 2];
+ break;
+ default:
+ regname = PE_REG_NAME[0];
+ }
+ printk(KERN_DEBUG "%s: %-20s %08x@%s\n", jme->dev->name,
+ msg, val, regname);
+}
+#else
+static inline void reg_dbg(const struct jme_adapter *jme,
+ const char *msg, u32 val, u32 reg) {}
+#endif
+
+/*
+ * Read/Write MMaped I/O Registers
+ */
+static inline u32 jread32(struct jme_adapter *jme, u32 reg)
+{
+ return readl(jme->regs + reg);
+}
+
+static inline void jwrite32(struct jme_adapter *jme, u32 reg, u32 val)
+{
+ reg_dbg(jme, "REG WRITE", val, reg);
+ writel(val, jme->regs + reg);
+ reg_dbg(jme, "VAL AFTER WRITE", readl(jme->regs + reg), reg);
+}
+
+static inline void jwrite32f(struct jme_adapter *jme, u32 reg, u32 val)
+{
+ /*
+ * Read after write should cause flush
+ */
+ reg_dbg(jme, "REG WRITE FLUSH", val, reg);
+ writel(val, jme->regs + reg);
+ readl(jme->regs + reg);
+ reg_dbg(jme, "VAL AFTER WRITE", readl(jme->regs + reg), reg);
+}
+
+/*
+ * PHY Regs
+ */
+enum jme_phy_reg17_bit_masks {
+ PREG17_SPEED = 0xC000,
+ PREG17_DUPLEX = 0x2000,
+ PREG17_SPDRSV = 0x0800,
+ PREG17_LNKUP = 0x0400,
+ PREG17_MDI = 0x0040,
+};
+
+enum jme_phy_reg17_vals {
+ PREG17_SPEED_10M = 0x0000,
+ PREG17_SPEED_100M = 0x4000,
+ PREG17_SPEED_1000M = 0x8000,
+};
+
+#define BMSR_ANCOMP 0x0020
+
+/*
+ * Workaround
+ */
+static inline int is_buggy250(unsigned short device, unsigned int chiprev)
+{
+ return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
+}
+
+/*
+ * Function prototypes
+ */
+static int jme_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd);
+static void jme_set_multi(struct net_device *netdev);
+
+#endif
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index 00d59ab2f8a..f80dcc11fe2 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -530,9 +530,9 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void __ei_poll(struct net_device *dev)
{
- disable_irq_lockdep(dev->irq);
+ disable_irq(dev->irq);
__ei_interrupt(dev->irq, dev);
- enable_irq_lockdep(dev->irq);
+ enable_irq(dev->irq);
}
#endif
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 84c77f1f9a5..01f7a31bac7 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -195,8 +195,8 @@ static int macb_mii_probe(struct net_device *dev)
/* find the first phy */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- if (bp->mii_bus.phy_map[phy_addr]) {
- phydev = bp->mii_bus.phy_map[phy_addr];
+ if (bp->mii_bus->phy_map[phy_addr]) {
+ phydev = bp->mii_bus->phy_map[phy_addr];
break;
}
}
@@ -244,30 +244,36 @@ static int macb_mii_init(struct macb *bp)
/* Enable managment port */
macb_writel(bp, NCR, MACB_BIT(MPE));
- bp->mii_bus.name = "MACB_mii_bus";
- bp->mii_bus.read = &macb_mdio_read;
- bp->mii_bus.write = &macb_mdio_write;
- bp->mii_bus.reset = &macb_mdio_reset;
- snprintf(bp->mii_bus.id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
- bp->mii_bus.priv = bp;
- bp->mii_bus.dev = &bp->dev->dev;
+ bp->mii_bus = mdiobus_alloc();
+ if (bp->mii_bus == NULL) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ bp->mii_bus->name = "MACB_mii_bus";
+ bp->mii_bus->read = &macb_mdio_read;
+ bp->mii_bus->write = &macb_mdio_write;
+ bp->mii_bus->reset = &macb_mdio_reset;
+ snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
+ bp->mii_bus->priv = bp;
+ bp->mii_bus->parent = &bp->dev->dev;
pdata = bp->pdev->dev.platform_data;
if (pdata)
- bp->mii_bus.phy_mask = pdata->phy_mask;
+ bp->mii_bus->phy_mask = pdata->phy_mask;
- bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
- if (!bp->mii_bus.irq) {
+ bp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ if (!bp->mii_bus->irq) {
err = -ENOMEM;
- goto err_out;
+ goto err_out_free_mdiobus;
}
for (i = 0; i < PHY_MAX_ADDR; i++)
- bp->mii_bus.irq[i] = PHY_POLL;
+ bp->mii_bus->irq[i] = PHY_POLL;
- platform_set_drvdata(bp->dev, &bp->mii_bus);
+ platform_set_drvdata(bp->dev, bp->mii_bus);
- if (mdiobus_register(&bp->mii_bus))
+ if (mdiobus_register(bp->mii_bus))
goto err_out_free_mdio_irq;
if (macb_mii_probe(bp->dev) != 0) {
@@ -277,9 +283,11 @@ static int macb_mii_init(struct macb *bp)
return 0;
err_out_unregister_bus:
- mdiobus_unregister(&bp->mii_bus);
+ mdiobus_unregister(bp->mii_bus);
err_out_free_mdio_irq:
- kfree(bp->mii_bus.irq);
+ kfree(bp->mii_bus->irq);
+err_out_free_mdiobus:
+ mdiobus_free(bp->mii_bus);
err_out:
return err;
}
@@ -1261,8 +1269,9 @@ static int __exit macb_remove(struct platform_device *pdev)
bp = netdev_priv(dev);
if (bp->phy_dev)
phy_disconnect(bp->phy_dev);
- mdiobus_unregister(&bp->mii_bus);
- kfree(bp->mii_bus.irq);
+ mdiobus_unregister(bp->mii_bus);
+ kfree(bp->mii_bus->irq);
+ mdiobus_free(bp->mii_bus);
unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(bp->regs);
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index 57b85acf0d1..d3212f6db70 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -384,7 +384,7 @@ struct macb {
unsigned int rx_pending, tx_pending;
- struct mii_bus mii_bus;
+ struct mii_bus *mii_bus;
struct phy_device *phy_dev;
unsigned int link;
unsigned int speed;
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 51ad3765e07..85587a6667b 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*
* Copyright (C) 1996 Paul Mackerras.
- * Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ * Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
*
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 0a97c26df6a..a1e22ed1f6e 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -41,7 +41,7 @@
#endif
#if MFE_DEBUG>=1
-#define DPRINTK(str,args...) printk(KERN_DEBUG "meth: %s: " str, __FUNCTION__ , ## args)
+#define DPRINTK(str,args...) printk(KERN_DEBUG "meth: %s: " str, __func__ , ## args)
#define MFE_RX_DEBUG 2
#else
#define DPRINTK(str,args...)
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 6d343efb271..4e7a5faf035 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -203,7 +203,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
out_badirq:
printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
- dev->name, __FUNCTION__, irq);
+ dev->name, __func__, irq);
return ret;
}
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index 096bca54bcf..b411b79d72a 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/bitmap.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 62071d9c4a5..d1dd5b48dbd 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -67,11 +67,10 @@ struct mlx4_mpt_entry {
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
#define MLX4_MPT_FLAG_REGION (1 << 8)
-#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 26)
+#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
+#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
-#define MLX4_MTT_FLAG_PRESENT 1
-
#define MLX4_MPT_STATUS_SW 0xF0
#define MLX4_MPT_STATUS_HW 0x00
@@ -348,7 +347,10 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
/* fast register MR in free state */
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
- mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG);
+ mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG |
+ MLX4_MPT_PD_FLAG_RAE);
+ mpt_entry->mtt_sz = cpu_to_be32((1 << mr->mtt.order) *
+ MLX4_MTT_ENTRY_PER_SEG);
} else {
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 0a18b9e96da..a9c8c08044b 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/etherdevice.h>
@@ -48,30 +49,28 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
#include <linux/mv643xx_eth.h>
#include <asm/io.h>
#include <asm/types.h>
#include <asm/system.h>
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
-static char mv643xx_eth_driver_version[] = "1.3";
+static char mv643xx_eth_driver_version[] = "1.4";
-#define MV643XX_ETH_CHECKSUM_OFFLOAD_TX
-#define MV643XX_ETH_NAPI
-#define MV643XX_ETH_TX_FAST_REFILL
-
-#ifdef MV643XX_ETH_CHECKSUM_OFFLOAD_TX
-#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
-#else
-#define MAX_DESCS_PER_SKB 1
-#endif
/*
* Registers shared between all ports.
*/
#define PHY_ADDR 0x0000
#define SMI_REG 0x0004
+#define SMI_BUSY 0x10000000
+#define SMI_READ_VALID 0x08000000
+#define SMI_OPCODE_READ 0x04000000
+#define SMI_OPCODE_WRITE 0x00000000
+#define ERR_INT_CAUSE 0x0080
+#define ERR_INT_SMI_DONE 0x00000010
+#define ERR_INT_MASK 0x0084
#define WINDOW_BASE(w) (0x0200 + ((w) << 3))
#define WINDOW_SIZE(w) (0x0204 + ((w) << 3))
#define WINDOW_REMAP_HIGH(w) (0x0280 + ((w) << 2))
@@ -104,16 +103,12 @@ static char mv643xx_eth_driver_version[] = "1.3";
#define TX_BW_MTU(p) (0x0458 + ((p) << 10))
#define TX_BW_BURST(p) (0x045c + ((p) << 10))
#define INT_CAUSE(p) (0x0460 + ((p) << 10))
-#define INT_TX_END_0 0x00080000
#define INT_TX_END 0x07f80000
-#define INT_RX 0x0007fbfc
+#define INT_RX 0x000003fc
#define INT_EXT 0x00000002
#define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10))
-#define INT_EXT_LINK 0x00100000
-#define INT_EXT_PHY 0x00010000
-#define INT_EXT_TX_ERROR_0 0x00000100
-#define INT_EXT_TX_0 0x00000001
-#define INT_EXT_TX 0x0000ffff
+#define INT_EXT_LINK_PHY 0x00110000
+#define INT_EXT_TX 0x000000ff
#define INT_MASK(p) (0x0468 + ((p) << 10))
#define INT_MASK_EXT(p) (0x046c + ((p) << 10))
#define TX_FIFO_URGENT_THRESHOLD(p) (0x0474 + ((p) << 10))
@@ -171,8 +166,8 @@ static char mv643xx_eth_driver_version[] = "1.3";
#define FORCE_LINK_PASS (1 << 1)
#define SERIAL_PORT_ENABLE (1 << 0)
-#define DEFAULT_RX_QUEUE_SIZE 400
-#define DEFAULT_TX_QUEUE_SIZE 800
+#define DEFAULT_RX_QUEUE_SIZE 128
+#define DEFAULT_TX_QUEUE_SIZE 256
/*
@@ -249,9 +244,23 @@ struct mv643xx_eth_shared_private {
void __iomem *base;
/*
- * Protects access to SMI_REG, which is shared between ports.
+ * Points at the right SMI instance to use.
+ */
+ struct mv643xx_eth_shared_private *smi;
+
+ /*
+ * Provides access to local SMI interface.
+ */
+ struct mii_bus *smi_bus;
+
+ /*
+ * If we have access to the error interrupt pin (which is
+ * somewhat misnamed as it not only reflects internal errors
+ * but also reflects SMI completion), use that to wait for
+ * SMI access completion instead of polling the SMI busy bit.
*/
- spinlock_t phy_lock;
+ int err_interrupt;
+ wait_queue_head_t smi_busy_wait;
/*
* Per-port MBUS window access register value.
@@ -263,9 +272,13 @@ struct mv643xx_eth_shared_private {
*/
unsigned int t_clk;
int extended_rx_coal_limit;
- int tx_bw_control_moved;
+ int tx_bw_control;
};
+#define TX_BW_CONTROL_ABSENT 0
+#define TX_BW_CONTROL_OLD_LAYOUT 1
+#define TX_BW_CONTROL_NEW_LAYOUT 2
+
/* per-port *****************************************************************/
struct mib_counters {
@@ -314,8 +327,6 @@ struct rx_queue {
dma_addr_t rx_desc_dma;
int rx_desc_area_size;
struct sk_buff **rx_skb;
-
- struct timer_list rx_oom;
};
struct tx_queue {
@@ -330,7 +341,12 @@ struct tx_queue {
struct tx_desc *tx_desc_area;
dma_addr_t tx_desc_dma;
int tx_desc_area_size;
- struct sk_buff **tx_skb;
+
+ struct sk_buff_head tx_skb;
+
+ unsigned long tx_packets;
+ unsigned long tx_bytes;
+ unsigned long tx_dropped;
};
struct mv643xx_eth_private {
@@ -339,14 +355,24 @@ struct mv643xx_eth_private {
struct net_device *dev;
- struct mv643xx_eth_shared_private *shared_smi;
- int phy_addr;
-
- spinlock_t lock;
+ struct phy_device *phy;
+ struct timer_list mib_counters_timer;
+ spinlock_t mib_counters_lock;
struct mib_counters mib_counters;
+
struct work_struct tx_timeout_task;
- struct mii_if_info mii;
+
+ struct napi_struct napi;
+ u8 work_link;
+ u8 work_tx;
+ u8 work_tx_end;
+ u8 work_rx;
+ u8 work_rx_refill;
+ u8 work_rx_oom;
+
+ int skb_size;
+ struct sk_buff_head rx_recycle;
/*
* RX state.
@@ -354,9 +380,8 @@ struct mv643xx_eth_private {
int default_rx_ring_size;
unsigned long rx_desc_sram_addr;
int rx_desc_sram_size;
- u8 rxq_mask;
- int rxq_primary;
- struct napi_struct napi;
+ int rxq_count;
+ struct timer_list rx_oom;
struct rx_queue rxq[8];
/*
@@ -365,12 +390,8 @@ struct mv643xx_eth_private {
int default_tx_ring_size;
unsigned long tx_desc_sram_addr;
int tx_desc_sram_size;
- u8 txq_mask;
- int txq_primary;
+ int txq_count;
struct tx_queue txq[8];
-#ifdef MV643XX_ETH_TX_FAST_REFILL
- int tx_clean_threshold;
-#endif
};
@@ -440,94 +461,21 @@ static void txq_disable(struct tx_queue *txq)
udelay(10);
}
-static void __txq_maybe_wake(struct tx_queue *txq)
+static void txq_maybe_wake(struct tx_queue *txq)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
+ struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index);
- /*
- * netif_{stop,wake}_queue() flow control only applies to
- * the primary queue.
- */
- BUG_ON(txq->index != mp->txq_primary);
-
- if (txq->tx_ring_size - txq->tx_desc_count >= MAX_DESCS_PER_SKB)
- netif_wake_queue(mp->dev);
-}
-
-
-/* rx ***********************************************************************/
-static void txq_reclaim(struct tx_queue *txq, int force);
-
-static void rxq_refill(struct rx_queue *rxq)
-{
- struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
-
- while (rxq->rx_desc_count < rxq->rx_ring_size) {
- int skb_size;
- struct sk_buff *skb;
- int unaligned;
- int rx;
-
- /*
- * Reserve 2+14 bytes for an ethernet header (the
- * hardware automatically prepends 2 bytes of dummy
- * data to each received packet), 16 bytes for up to
- * four VLAN tags, and 4 bytes for the trailing FCS
- * -- 36 bytes total.
- */
- skb_size = mp->dev->mtu + 36;
-
- /*
- * Make sure that the skb size is a multiple of 8
- * bytes, as the lower three bits of the receive
- * descriptor's buffer size field are ignored by
- * the hardware.
- */
- skb_size = (skb_size + 7) & ~7;
-
- skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1);
- if (skb == NULL)
- break;
-
- unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1);
- if (unaligned)
- skb_reserve(skb, dma_get_cache_alignment() - unaligned);
-
- rxq->rx_desc_count++;
- rx = rxq->rx_used_desc;
- rxq->rx_used_desc = (rx + 1) % rxq->rx_ring_size;
-
- rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data,
- skb_size, DMA_FROM_DEVICE);
- rxq->rx_desc_area[rx].buf_size = skb_size;
- rxq->rx_skb[rx] = skb;
- wmb();
- rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA |
- RX_ENABLE_INTERRUPT;
- wmb();
-
- /*
- * The hardware automatically prepends 2 bytes of
- * dummy data to each received packet, so that the
- * IP header ends up 16-byte aligned.
- */
- skb_reserve(skb, 2);
+ if (netif_tx_queue_stopped(nq)) {
+ __netif_tx_lock(nq, smp_processor_id());
+ if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1)
+ netif_tx_wake_queue(nq);
+ __netif_tx_unlock(nq);
}
-
- if (rxq->rx_desc_count != rxq->rx_ring_size)
- mod_timer(&rxq->rx_oom, jiffies + (HZ / 10));
-
- spin_unlock_irqrestore(&mp->lock, flags);
}
-static inline void rxq_refill_timer_wrapper(unsigned long data)
-{
- rxq_refill((struct rx_queue *)data);
-}
+/* rx napi ******************************************************************/
static int rxq_process(struct rx_queue *rxq, int budget)
{
struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
@@ -539,31 +487,31 @@ static int rxq_process(struct rx_queue *rxq, int budget)
struct rx_desc *rx_desc;
unsigned int cmd_sts;
struct sk_buff *skb;
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
+ u16 byte_cnt;
rx_desc = &rxq->rx_desc_area[rxq->rx_curr_desc];
cmd_sts = rx_desc->cmd_sts;
- if (cmd_sts & BUFFER_OWNED_BY_DMA) {
- spin_unlock_irqrestore(&mp->lock, flags);
+ if (cmd_sts & BUFFER_OWNED_BY_DMA)
break;
- }
rmb();
skb = rxq->rx_skb[rxq->rx_curr_desc];
rxq->rx_skb[rxq->rx_curr_desc] = NULL;
- rxq->rx_curr_desc = (rxq->rx_curr_desc + 1) % rxq->rx_ring_size;
-
- spin_unlock_irqrestore(&mp->lock, flags);
+ rxq->rx_curr_desc++;
+ if (rxq->rx_curr_desc == rxq->rx_ring_size)
+ rxq->rx_curr_desc = 0;
- dma_unmap_single(NULL, rx_desc->buf_ptr + 2,
+ dma_unmap_single(NULL, rx_desc->buf_ptr,
rx_desc->buf_size, DMA_FROM_DEVICE);
rxq->rx_desc_count--;
rx++;
+ mp->work_rx_refill |= 1 << rxq->index;
+
+ byte_cnt = rx_desc->byte_cnt;
+
/*
* Update statistics.
*
@@ -573,7 +521,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
* byte CRC at the end of the packet (which we do count).
*/
stats->rx_packets++;
- stats->rx_bytes += rx_desc->byte_cnt - 2;
+ stats->rx_bytes += byte_cnt - 2;
/*
* In case we received a packet without first / last bits
@@ -596,72 +544,84 @@ static int rxq_process(struct rx_queue *rxq, int budget)
if (cmd_sts & ERROR_SUMMARY)
stats->rx_errors++;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
} else {
/*
* The -4 is for the CRC in the trailer of the
* received packet
*/
- skb_put(skb, rx_desc->byte_cnt - 2 - 4);
+ skb_put(skb, byte_cnt - 2 - 4);
- if (cmd_sts & LAYER_4_CHECKSUM_OK) {
+ if (cmd_sts & LAYER_4_CHECKSUM_OK)
skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->csum = htons(
- (cmd_sts & 0x0007fff8) >> 3);
- }
skb->protocol = eth_type_trans(skb, mp->dev);
-#ifdef MV643XX_ETH_NAPI
netif_receive_skb(skb);
-#else
- netif_rx(skb);
-#endif
}
mp->dev->last_rx = jiffies;
}
- rxq_refill(rxq);
+ if (rx < budget)
+ mp->work_rx &= ~(1 << rxq->index);
return rx;
}
-#ifdef MV643XX_ETH_NAPI
-static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
+static int rxq_refill(struct rx_queue *rxq, int budget)
{
- struct mv643xx_eth_private *mp;
- int rx;
- int i;
+ struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
+ int refilled;
- mp = container_of(napi, struct mv643xx_eth_private, napi);
+ refilled = 0;
+ while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) {
+ struct sk_buff *skb;
+ int unaligned;
+ int rx;
+
+ skb = __skb_dequeue(&mp->rx_recycle);
+ if (skb == NULL)
+ skb = dev_alloc_skb(mp->skb_size +
+ dma_get_cache_alignment() - 1);
-#ifdef MV643XX_ETH_TX_FAST_REFILL
- if (++mp->tx_clean_threshold > 5) {
- mp->tx_clean_threshold = 0;
- for (i = 0; i < 8; i++)
- if (mp->txq_mask & (1 << i))
- txq_reclaim(mp->txq + i, 0);
-
- if (netif_carrier_ok(mp->dev)) {
- spin_lock_irq(&mp->lock);
- __txq_maybe_wake(mp->txq + mp->txq_primary);
- spin_unlock_irq(&mp->lock);
+ if (skb == NULL) {
+ mp->work_rx_oom |= 1 << rxq->index;
+ goto oom;
}
- }
-#endif
- rx = 0;
- for (i = 7; rx < budget && i >= 0; i--)
- if (mp->rxq_mask & (1 << i))
- rx += rxq_process(mp->rxq + i, budget - rx);
+ unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1);
+ if (unaligned)
+ skb_reserve(skb, dma_get_cache_alignment() - unaligned);
- if (rx < budget) {
- netif_rx_complete(mp->dev, napi);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
+ refilled++;
+ rxq->rx_desc_count++;
+
+ rx = rxq->rx_used_desc++;
+ if (rxq->rx_used_desc == rxq->rx_ring_size)
+ rxq->rx_used_desc = 0;
+
+ rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data,
+ mp->skb_size, DMA_FROM_DEVICE);
+ rxq->rx_desc_area[rx].buf_size = mp->skb_size;
+ rxq->rx_skb[rx] = skb;
+ wmb();
+ rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA |
+ RX_ENABLE_INTERRUPT;
+ wmb();
+
+ /*
+ * The hardware automatically prepends 2 bytes of
+ * dummy data to each received packet, so that the
+ * IP header ends up 16-byte aligned.
+ */
+ skb_reserve(skb, 2);
}
- return rx;
+ if (refilled < budget)
+ mp->work_rx_refill &= ~(1 << rxq->index);
+
+oom:
+ return refilled;
}
-#endif
/* tx ***********************************************************************/
@@ -684,8 +644,9 @@ static int txq_alloc_desc_index(struct tx_queue *txq)
BUG_ON(txq->tx_desc_count >= txq->tx_ring_size);
- tx_desc_curr = txq->tx_curr_desc;
- txq->tx_curr_desc = (tx_desc_curr + 1) % txq->tx_ring_size;
+ tx_desc_curr = txq->tx_curr_desc++;
+ if (txq->tx_curr_desc == txq->tx_ring_size)
+ txq->tx_curr_desc = 0;
BUG_ON(txq->tx_curr_desc == txq->tx_used_desc);
@@ -714,10 +675,8 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
desc->cmd_sts = BUFFER_OWNED_BY_DMA |
ZERO_PADDING | TX_LAST_DESC |
TX_ENABLE_INTERRUPT;
- txq->tx_skb[tx_index] = skb;
} else {
desc->cmd_sts = BUFFER_OWNED_BY_DMA;
- txq->tx_skb[tx_index] = NULL;
}
desc->l4i_chk = 0;
@@ -734,144 +693,228 @@ static inline __be16 sum16_as_be(__sum16 sum)
return (__force __be16)sum;
}
-static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
+static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int nr_frags = skb_shinfo(skb)->nr_frags;
int tx_index;
struct tx_desc *desc;
u32 cmd_sts;
+ u16 l4i_chk;
int length;
cmd_sts = TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA;
-
- tx_index = txq_alloc_desc_index(txq);
- desc = &txq->tx_desc_area[tx_index];
-
- if (nr_frags) {
- txq_submit_frag_skb(txq, skb);
-
- length = skb_headlen(skb);
- txq->tx_skb[tx_index] = NULL;
- } else {
- cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT;
- length = skb->len;
- txq->tx_skb[tx_index] = skb;
- }
-
- desc->byte_cnt = length;
- desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+ l4i_chk = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- int mac_hdr_len;
+ int tag_bytes;
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
skb->protocol != htons(ETH_P_8021Q));
- cmd_sts |= GEN_TCP_UDP_CHECKSUM |
- GEN_IP_V4_CHECKSUM |
- ip_hdr(skb)->ihl << TX_IHL_SHIFT;
+ tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN;
+ if (unlikely(tag_bytes & ~12)) {
+ if (skb_checksum_help(skb) == 0)
+ goto no_csum;
+ kfree_skb(skb);
+ return 1;
+ }
- mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
- switch (mac_hdr_len - ETH_HLEN) {
- case 0:
- break;
- case 4:
- cmd_sts |= MAC_HDR_EXTRA_4_BYTES;
- break;
- case 8:
- cmd_sts |= MAC_HDR_EXTRA_8_BYTES;
- break;
- case 12:
+ if (tag_bytes & 4)
cmd_sts |= MAC_HDR_EXTRA_4_BYTES;
+ if (tag_bytes & 8)
cmd_sts |= MAC_HDR_EXTRA_8_BYTES;
- break;
- default:
- if (net_ratelimit())
- dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev,
- "mac header length is %d?!\n", mac_hdr_len);
- break;
- }
+
+ cmd_sts |= GEN_TCP_UDP_CHECKSUM |
+ GEN_IP_V4_CHECKSUM |
+ ip_hdr(skb)->ihl << TX_IHL_SHIFT;
switch (ip_hdr(skb)->protocol) {
case IPPROTO_UDP:
cmd_sts |= UDP_FRAME;
- desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check));
+ l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check));
break;
case IPPROTO_TCP:
- desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check));
+ l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check));
break;
default:
BUG();
}
} else {
+no_csum:
/* Errata BTS #50, IHL must be 5 if no HW checksum */
cmd_sts |= 5 << TX_IHL_SHIFT;
- desc->l4i_chk = 0;
}
+ tx_index = txq_alloc_desc_index(txq);
+ desc = &txq->tx_desc_area[tx_index];
+
+ if (nr_frags) {
+ txq_submit_frag_skb(txq, skb);
+ length = skb_headlen(skb);
+ } else {
+ cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT;
+ length = skb->len;
+ }
+
+ desc->l4i_chk = l4i_chk;
+ desc->byte_cnt = length;
+ desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+
+ __skb_queue_tail(&txq->tx_skb, skb);
+
/* ensure all other descriptors are written before first cmd_sts */
wmb();
desc->cmd_sts = cmd_sts;
- /* clear TX_END interrupt status */
- wrl(mp, INT_CAUSE(mp->port_num), ~(INT_TX_END_0 << txq->index));
- rdl(mp, INT_CAUSE(mp->port_num));
+ /* clear TX_END status */
+ mp->work_tx_end &= ~(1 << txq->index);
/* ensure all descriptors are written before poking hardware */
wmb();
txq_enable(txq);
txq->tx_desc_count += nr_frags + 1;
+
+ return 0;
}
static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- struct net_device_stats *stats = &dev->stats;
+ int queue;
struct tx_queue *txq;
- unsigned long flags;
+ struct netdev_queue *nq;
+
+ queue = skb_get_queue_mapping(skb);
+ txq = mp->txq + queue;
+ nq = netdev_get_tx_queue(dev, queue);
if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
- stats->tx_dropped++;
+ txq->tx_dropped++;
dev_printk(KERN_DEBUG, &dev->dev,
"failed to linearize skb with tiny "
"unaligned fragment\n");
return NETDEV_TX_BUSY;
}
- spin_lock_irqsave(&mp->lock, flags);
-
- txq = mp->txq + mp->txq_primary;
-
- if (txq->tx_ring_size - txq->tx_desc_count < MAX_DESCS_PER_SKB) {
- spin_unlock_irqrestore(&mp->lock, flags);
- if (txq->index == mp->txq_primary && net_ratelimit())
- dev_printk(KERN_ERR, &dev->dev,
- "primary tx queue full?!\n");
+ if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) {
+ if (net_ratelimit())
+ dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n");
kfree_skb(skb);
return NETDEV_TX_OK;
}
- txq_submit_skb(txq, skb);
- stats->tx_bytes += skb->len;
- stats->tx_packets++;
- dev->trans_start = jiffies;
-
- if (txq->index == mp->txq_primary) {
+ if (!txq_submit_skb(txq, skb)) {
int entries_left;
+ txq->tx_bytes += skb->len;
+ txq->tx_packets++;
+ dev->trans_start = jiffies;
+
entries_left = txq->tx_ring_size - txq->tx_desc_count;
- if (entries_left < MAX_DESCS_PER_SKB)
- netif_stop_queue(dev);
+ if (entries_left < MAX_SKB_FRAGS + 1)
+ netif_tx_stop_queue(nq);
}
- spin_unlock_irqrestore(&mp->lock, flags);
-
return NETDEV_TX_OK;
}
+/* tx napi ******************************************************************/
+static void txq_kick(struct tx_queue *txq)
+{
+ struct mv643xx_eth_private *mp = txq_to_mp(txq);
+ struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index);
+ u32 hw_desc_ptr;
+ u32 expected_ptr;
+
+ __netif_tx_lock(nq, smp_processor_id());
+
+ if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index))
+ goto out;
+
+ hw_desc_ptr = rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, txq->index));
+ expected_ptr = (u32)txq->tx_desc_dma +
+ txq->tx_curr_desc * sizeof(struct tx_desc);
+
+ if (hw_desc_ptr != expected_ptr)
+ txq_enable(txq);
+
+out:
+ __netif_tx_unlock(nq);
+
+ mp->work_tx_end &= ~(1 << txq->index);
+}
+
+static int txq_reclaim(struct tx_queue *txq, int budget, int force)
+{
+ struct mv643xx_eth_private *mp = txq_to_mp(txq);
+ struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index);
+ int reclaimed;
+
+ __netif_tx_lock(nq, smp_processor_id());
+
+ reclaimed = 0;
+ while (reclaimed < budget && txq->tx_desc_count > 0) {
+ int tx_index;
+ struct tx_desc *desc;
+ u32 cmd_sts;
+ struct sk_buff *skb;
+
+ tx_index = txq->tx_used_desc;
+ desc = &txq->tx_desc_area[tx_index];
+ cmd_sts = desc->cmd_sts;
+
+ if (cmd_sts & BUFFER_OWNED_BY_DMA) {
+ if (!force)
+ break;
+ desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA;
+ }
+
+ txq->tx_used_desc = tx_index + 1;
+ if (txq->tx_used_desc == txq->tx_ring_size)
+ txq->tx_used_desc = 0;
+
+ reclaimed++;
+ txq->tx_desc_count--;
+
+ skb = NULL;
+ if (cmd_sts & TX_LAST_DESC)
+ skb = __skb_dequeue(&txq->tx_skb);
+
+ if (cmd_sts & ERROR_SUMMARY) {
+ dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n");
+ mp->dev->stats.tx_errors++;
+ }
+
+ if (cmd_sts & TX_FIRST_DESC) {
+ dma_unmap_single(NULL, desc->buf_ptr,
+ desc->byte_cnt, DMA_TO_DEVICE);
+ } else {
+ dma_unmap_page(NULL, desc->buf_ptr,
+ desc->byte_cnt, DMA_TO_DEVICE);
+ }
+
+ if (skb != NULL) {
+ if (skb_queue_len(&mp->rx_recycle) <
+ mp->default_rx_ring_size &&
+ skb_recycle_check(skb, mp->skb_size))
+ __skb_queue_head(&mp->rx_recycle, skb);
+ else
+ dev_kfree_skb(skb);
+ }
+ }
+
+ __netif_tx_unlock(nq);
+
+ if (reclaimed < budget)
+ mp->work_tx &= ~(1 << txq->index);
+
+ return reclaimed;
+}
+
+
/* tx rate control **********************************************************/
/*
* Set total maximum TX rate (shared by all TX queues for this port)
@@ -895,14 +938,17 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst)
if (bucket_size > 65535)
bucket_size = 65535;
- if (mp->shared->tx_bw_control_moved) {
- wrl(mp, TX_BW_RATE_MOVED(mp->port_num), token_rate);
- wrl(mp, TX_BW_MTU_MOVED(mp->port_num), mtu);
- wrl(mp, TX_BW_BURST_MOVED(mp->port_num), bucket_size);
- } else {
+ switch (mp->shared->tx_bw_control) {
+ case TX_BW_CONTROL_OLD_LAYOUT:
wrl(mp, TX_BW_RATE(mp->port_num), token_rate);
wrl(mp, TX_BW_MTU(mp->port_num), mtu);
wrl(mp, TX_BW_BURST(mp->port_num), bucket_size);
+ break;
+ case TX_BW_CONTROL_NEW_LAYOUT:
+ wrl(mp, TX_BW_RATE_MOVED(mp->port_num), token_rate);
+ wrl(mp, TX_BW_MTU_MOVED(mp->port_num), mtu);
+ wrl(mp, TX_BW_BURST_MOVED(mp->port_num), bucket_size);
+ break;
}
}
@@ -934,14 +980,21 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)
/*
* Turn on fixed priority mode.
*/
- if (mp->shared->tx_bw_control_moved)
- off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
- else
+ off = 0;
+ switch (mp->shared->tx_bw_control) {
+ case TX_BW_CONTROL_OLD_LAYOUT:
off = TXQ_FIX_PRIO_CONF(mp->port_num);
+ break;
+ case TX_BW_CONTROL_NEW_LAYOUT:
+ off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
+ break;
+ }
- val = rdl(mp, off);
- val |= 1 << txq->index;
- wrl(mp, off, val);
+ if (off) {
+ val = rdl(mp, off);
+ val |= 1 << txq->index;
+ wrl(mp, off, val);
+ }
}
static void txq_set_wrr(struct tx_queue *txq, int weight)
@@ -953,95 +1006,147 @@ static void txq_set_wrr(struct tx_queue *txq, int weight)
/*
* Turn off fixed priority mode.
*/
- if (mp->shared->tx_bw_control_moved)
- off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
- else
+ off = 0;
+ switch (mp->shared->tx_bw_control) {
+ case TX_BW_CONTROL_OLD_LAYOUT:
off = TXQ_FIX_PRIO_CONF(mp->port_num);
+ break;
+ case TX_BW_CONTROL_NEW_LAYOUT:
+ off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
+ break;
+ }
- val = rdl(mp, off);
- val &= ~(1 << txq->index);
- wrl(mp, off, val);
+ if (off) {
+ val = rdl(mp, off);
+ val &= ~(1 << txq->index);
+ wrl(mp, off, val);
- /*
- * Configure WRR weight for this queue.
- */
- off = TXQ_BW_WRR_CONF(mp->port_num, txq->index);
+ /*
+ * Configure WRR weight for this queue.
+ */
+ off = TXQ_BW_WRR_CONF(mp->port_num, txq->index);
- val = rdl(mp, off);
- val = (val & ~0xff) | (weight & 0xff);
- wrl(mp, off, val);
+ val = rdl(mp, off);
+ val = (val & ~0xff) | (weight & 0xff);
+ wrl(mp, off, val);
+ }
}
/* mii management interface *************************************************/
-#define SMI_BUSY 0x10000000
-#define SMI_READ_VALID 0x08000000
-#define SMI_OPCODE_READ 0x04000000
-#define SMI_OPCODE_WRITE 0x00000000
+static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
+{
+ struct mv643xx_eth_shared_private *msp = dev_id;
-static void smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr,
- unsigned int reg, unsigned int *value)
+ if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
+ writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
+ wake_up(&msp->smi_busy_wait);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int smi_is_done(struct mv643xx_eth_shared_private *msp)
{
- void __iomem *smi_reg = mp->shared_smi->base + SMI_REG;
- unsigned long flags;
- int i;
+ return !(readl(msp->base + SMI_REG) & SMI_BUSY);
+}
- /* the SMI register is a shared resource */
- spin_lock_irqsave(&mp->shared_smi->phy_lock, flags);
+static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
+{
+ if (msp->err_interrupt == NO_IRQ) {
+ int i;
- /* wait for the SMI register to become available */
- for (i = 0; readl(smi_reg) & SMI_BUSY; i++) {
- if (i == 1000) {
- printk("%s: PHY busy timeout\n", mp->dev->name);
- goto out;
+ for (i = 0; !smi_is_done(msp); i++) {
+ if (i == 10)
+ return -ETIMEDOUT;
+ msleep(10);
}
- udelay(10);
+
+ return 0;
+ }
+
+ if (!wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
+ msecs_to_jiffies(100)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
+{
+ struct mv643xx_eth_shared_private *msp = bus->priv;
+ void __iomem *smi_reg = msp->base + SMI_REG;
+ int ret;
+
+ if (smi_wait_ready(msp)) {
+ printk("mv643xx_eth: SMI bus busy timeout\n");
+ return -ETIMEDOUT;
}
writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
- /* now wait for the data to be valid */
- for (i = 0; !(readl(smi_reg) & SMI_READ_VALID); i++) {
- if (i == 1000) {
- printk("%s: PHY read timeout\n", mp->dev->name);
- goto out;
- }
- udelay(10);
+ if (smi_wait_ready(msp)) {
+ printk("mv643xx_eth: SMI bus busy timeout\n");
+ return -ETIMEDOUT;
}
- *value = readl(smi_reg) & 0xffff;
-out:
- spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags);
+ ret = readl(smi_reg);
+ if (!(ret & SMI_READ_VALID)) {
+ printk("mv643xx_eth: SMI bus read not valid\n");
+ return -ENODEV;
+ }
+
+ return ret & 0xffff;
}
-static void smi_reg_write(struct mv643xx_eth_private *mp,
- unsigned int addr,
- unsigned int reg, unsigned int value)
+static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
{
- void __iomem *smi_reg = mp->shared_smi->base + SMI_REG;
- unsigned long flags;
- int i;
+ struct mv643xx_eth_shared_private *msp = bus->priv;
+ void __iomem *smi_reg = msp->base + SMI_REG;
- /* the SMI register is a shared resource */
- spin_lock_irqsave(&mp->shared_smi->phy_lock, flags);
-
- /* wait for the SMI register to become available */
- for (i = 0; readl(smi_reg) & SMI_BUSY; i++) {
- if (i == 1000) {
- printk("%s: PHY busy timeout\n", mp->dev->name);
- goto out;
- }
- udelay(10);
+ if (smi_wait_ready(msp)) {
+ printk("mv643xx_eth: SMI bus busy timeout\n");
+ return -ETIMEDOUT;
}
writel(SMI_OPCODE_WRITE | (reg << 21) |
- (addr << 16) | (value & 0xffff), smi_reg);
-out:
- spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags);
+ (addr << 16) | (val & 0xffff), smi_reg);
+
+ if (smi_wait_ready(msp)) {
+ printk("mv643xx_eth: SMI bus busy timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
}
-/* mib counters *************************************************************/
+/* statistics ***************************************************************/
+static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
+{
+ struct mv643xx_eth_private *mp = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ unsigned long tx_packets = 0;
+ unsigned long tx_bytes = 0;
+ unsigned long tx_dropped = 0;
+ int i;
+
+ for (i = 0; i < mp->txq_count; i++) {
+ struct tx_queue *txq = mp->txq + i;
+
+ tx_packets += txq->tx_packets;
+ tx_bytes += txq->tx_bytes;
+ tx_dropped += txq->tx_dropped;
+ }
+
+ stats->tx_packets = tx_packets;
+ stats->tx_bytes = tx_bytes;
+ stats->tx_dropped = tx_dropped;
+
+ return stats;
+}
+
static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset)
{
return rdl(mp, MIB_COUNTERS(mp->port_num) + offset);
@@ -1059,6 +1164,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
{
struct mib_counters *p = &mp->mib_counters;
+ spin_lock(&mp->mib_counters_lock);
p->good_octets_received += mib_read(mp, 0x00);
p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
p->bad_octets_received += mib_read(mp, 0x08);
@@ -1091,6 +1197,16 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->bad_crc_event += mib_read(mp, 0x74);
p->collision += mib_read(mp, 0x78);
p->late_collision += mib_read(mp, 0x7c);
+ spin_unlock(&mp->mib_counters_lock);
+
+ mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
+}
+
+static void mib_counters_timer_wrapper(unsigned long _mp)
+{
+ struct mv643xx_eth_private *mp = (void *)_mp;
+
+ mib_counters_update(mp);
}
@@ -1156,9 +1272,9 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *
struct mv643xx_eth_private *mp = netdev_priv(dev);
int err;
- spin_lock_irq(&mp->lock);
- err = mii_ethtool_gset(&mp->mii, cmd);
- spin_unlock_irq(&mp->lock);
+ err = phy_read_status(mp->phy);
+ if (err == 0)
+ err = phy_ethtool_gset(mp->phy, cmd);
/*
* The MAC does not support 1000baseT_Half.
@@ -1206,18 +1322,13 @@ static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethto
static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- int err;
/*
* The MAC does not support 1000baseT_Half.
*/
cmd->advertising &= ~ADVERTISED_1000baseT_Half;
- spin_lock_irq(&mp->lock);
- err = mii_ethtool_sset(&mp->mii, cmd);
- spin_unlock_irq(&mp->lock);
-
- return err;
+ return phy_ethtool_sset(mp->phy, cmd);
}
static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -1239,7 +1350,7 @@ static int mv643xx_eth_nway_reset(struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- return mii_nway_restart(&mp->mii);
+ return genphy_restart_aneg(mp->phy);
}
static int mv643xx_eth_nway_reset_phyless(struct net_device *dev)
@@ -1249,14 +1360,7 @@ static int mv643xx_eth_nway_reset_phyless(struct net_device *dev)
static u32 mv643xx_eth_get_link(struct net_device *dev)
{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
-
- return mii_link_ok(&mp->mii);
-}
-
-static u32 mv643xx_eth_get_link_phyless(struct net_device *dev)
-{
- return 1;
+ return !!netif_carrier_ok(dev);
}
static void mv643xx_eth_get_strings(struct net_device *dev,
@@ -1277,9 +1381,10 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats,
uint64_t *data)
{
- struct mv643xx_eth_private *mp = dev->priv;
+ struct mv643xx_eth_private *mp = netdev_priv(dev);
int i;
+ mv643xx_eth_get_stats(dev);
mib_counters_update(mp);
for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) {
@@ -1323,7 +1428,7 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = {
.set_settings = mv643xx_eth_set_settings_phyless,
.get_drvinfo = mv643xx_eth_get_drvinfo,
.nway_reset = mv643xx_eth_nway_reset_phyless,
- .get_link = mv643xx_eth_get_link_phyless,
+ .get_link = mv643xx_eth_get_link,
.set_sg = ethtool_op_set_sg,
.get_strings = mv643xx_eth_get_strings,
.get_ethtool_stats = mv643xx_eth_get_ethtool_stats,
@@ -1487,7 +1592,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index)
size = rxq->rx_ring_size * sizeof(struct rx_desc);
- if (index == mp->rxq_primary && size <= mp->rx_desc_sram_size) {
+ if (index == 0 && size <= mp->rx_desc_sram_size) {
rxq->rx_desc_area = ioremap(mp->rx_desc_sram_addr,
mp->rx_desc_sram_size);
rxq->rx_desc_dma = mp->rx_desc_sram_addr;
@@ -1515,20 +1620,21 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index)
rx_desc = (struct rx_desc *)rxq->rx_desc_area;
for (i = 0; i < rxq->rx_ring_size; i++) {
- int nexti = (i + 1) % rxq->rx_ring_size;
+ int nexti;
+
+ nexti = i + 1;
+ if (nexti == rxq->rx_ring_size)
+ nexti = 0;
+
rx_desc[i].next_desc_ptr = rxq->rx_desc_dma +
nexti * sizeof(struct rx_desc);
}
- init_timer(&rxq->rx_oom);
- rxq->rx_oom.data = (unsigned long)rxq;
- rxq->rx_oom.function = rxq_refill_timer_wrapper;
-
return 0;
out_free:
- if (index == mp->rxq_primary && size <= mp->rx_desc_sram_size)
+ if (index == 0 && size <= mp->rx_desc_sram_size)
iounmap(rxq->rx_desc_area);
else
dma_free_coherent(NULL, size,
@@ -1546,8 +1652,6 @@ static void rxq_deinit(struct rx_queue *rxq)
rxq_disable(rxq);
- del_timer_sync(&rxq->rx_oom);
-
for (i = 0; i < rxq->rx_ring_size; i++) {
if (rxq->rx_skb[i]) {
dev_kfree_skb(rxq->rx_skb[i]);
@@ -1561,7 +1665,7 @@ static void rxq_deinit(struct rx_queue *rxq)
rxq->rx_desc_count);
}
- if (rxq->index == mp->rxq_primary &&
+ if (rxq->index == 0 &&
rxq->rx_desc_area_size <= mp->rx_desc_sram_size)
iounmap(rxq->rx_desc_area);
else
@@ -1588,7 +1692,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
size = txq->tx_ring_size * sizeof(struct tx_desc);
- if (index == mp->txq_primary && size <= mp->tx_desc_sram_size) {
+ if (index == 0 && size <= mp->tx_desc_sram_size) {
txq->tx_desc_area = ioremap(mp->tx_desc_sram_addr,
mp->tx_desc_sram_size);
txq->tx_desc_dma = mp->tx_desc_sram_addr;
@@ -1601,120 +1705,97 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
if (txq->tx_desc_area == NULL) {
dev_printk(KERN_ERR, &mp->dev->dev,
"can't allocate tx ring (%d bytes)\n", size);
- goto out;
+ return -ENOMEM;
}
memset(txq->tx_desc_area, 0, size);
txq->tx_desc_area_size = size;
- txq->tx_skb = kmalloc(txq->tx_ring_size * sizeof(*txq->tx_skb),
- GFP_KERNEL);
- if (txq->tx_skb == NULL) {
- dev_printk(KERN_ERR, &mp->dev->dev,
- "can't allocate tx skb ring\n");
- goto out_free;
- }
tx_desc = (struct tx_desc *)txq->tx_desc_area;
for (i = 0; i < txq->tx_ring_size; i++) {
struct tx_desc *txd = tx_desc + i;
- int nexti = (i + 1) % txq->tx_ring_size;
+ int nexti;
+
+ nexti = i + 1;
+ if (nexti == txq->tx_ring_size)
+ nexti = 0;
txd->cmd_sts = 0;
txd->next_desc_ptr = txq->tx_desc_dma +
nexti * sizeof(struct tx_desc);
}
- return 0;
-
-
-out_free:
- if (index == mp->txq_primary && size <= mp->tx_desc_sram_size)
- iounmap(txq->tx_desc_area);
- else
- dma_free_coherent(NULL, size,
- txq->tx_desc_area,
- txq->tx_desc_dma);
+ skb_queue_head_init(&txq->tx_skb);
-out:
- return -ENOMEM;
+ return 0;
}
-static void txq_reclaim(struct tx_queue *txq, int force)
+static void txq_deinit(struct tx_queue *txq)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
- while (txq->tx_desc_count > 0) {
- int tx_index;
- struct tx_desc *desc;
- u32 cmd_sts;
- struct sk_buff *skb;
- dma_addr_t addr;
- int count;
- tx_index = txq->tx_used_desc;
- desc = &txq->tx_desc_area[tx_index];
- cmd_sts = desc->cmd_sts;
+ txq_disable(txq);
+ txq_reclaim(txq, txq->tx_ring_size, 1);
- if (cmd_sts & BUFFER_OWNED_BY_DMA) {
- if (!force)
- break;
- desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA;
- }
+ BUG_ON(txq->tx_used_desc != txq->tx_curr_desc);
- txq->tx_used_desc = (tx_index + 1) % txq->tx_ring_size;
- txq->tx_desc_count--;
+ if (txq->index == 0 &&
+ txq->tx_desc_area_size <= mp->tx_desc_sram_size)
+ iounmap(txq->tx_desc_area);
+ else
+ dma_free_coherent(NULL, txq->tx_desc_area_size,
+ txq->tx_desc_area, txq->tx_desc_dma);
+}
- addr = desc->buf_ptr;
- count = desc->byte_cnt;
- skb = txq->tx_skb[tx_index];
- txq->tx_skb[tx_index] = NULL;
- if (cmd_sts & ERROR_SUMMARY) {
- dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n");
- mp->dev->stats.tx_errors++;
- }
+/* netdev ops and related ***************************************************/
+static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp)
+{
+ u32 int_cause;
+ u32 int_cause_ext;
- /*
- * Drop mp->lock while we free the skb.
- */
- spin_unlock_irqrestore(&mp->lock, flags);
+ int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
+ (INT_TX_END | INT_RX | INT_EXT);
+ if (int_cause == 0)
+ return 0;
- if (cmd_sts & TX_FIRST_DESC)
- dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
- else
- dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE);
+ int_cause_ext = 0;
+ if (int_cause & INT_EXT)
+ int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num));
- if (skb)
- dev_kfree_skb_irq(skb);
+ int_cause &= INT_TX_END | INT_RX;
+ if (int_cause) {
+ wrl(mp, INT_CAUSE(mp->port_num), ~int_cause);
+ mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) &
+ ~(rdl(mp, TXQ_COMMAND(mp->port_num)) & 0xff);
+ mp->work_rx |= (int_cause & INT_RX) >> 2;
+ }
- spin_lock_irqsave(&mp->lock, flags);
+ int_cause_ext &= INT_EXT_LINK_PHY | INT_EXT_TX;
+ if (int_cause_ext) {
+ wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext);
+ if (int_cause_ext & INT_EXT_LINK_PHY)
+ mp->work_link = 1;
+ mp->work_tx |= int_cause_ext & INT_EXT_TX;
}
- spin_unlock_irqrestore(&mp->lock, flags);
+
+ return 1;
}
-static void txq_deinit(struct tx_queue *txq)
+static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
{
- struct mv643xx_eth_private *mp = txq_to_mp(txq);
-
- txq_disable(txq);
- txq_reclaim(txq, 1);
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct mv643xx_eth_private *mp = netdev_priv(dev);
- BUG_ON(txq->tx_used_desc != txq->tx_curr_desc);
+ if (unlikely(!mv643xx_eth_collect_events(mp)))
+ return IRQ_NONE;
- if (txq->index == mp->txq_primary &&
- txq->tx_desc_area_size <= mp->tx_desc_sram_size)
- iounmap(txq->tx_desc_area);
- else
- dma_free_coherent(NULL, txq->tx_desc_area_size,
- txq->tx_desc_area, txq->tx_desc_dma);
+ wrl(mp, INT_MASK(mp->port_num), 0);
+ napi_schedule(&mp->napi);
- kfree(txq->tx_skb);
+ return IRQ_HANDLED;
}
-
-/* netdev ops and related ***************************************************/
static void handle_link_event(struct mv643xx_eth_private *mp)
{
struct net_device *dev = mp->dev;
@@ -1731,15 +1812,12 @@ static void handle_link_event(struct mv643xx_eth_private *mp)
printk(KERN_INFO "%s: link down\n", dev->name);
netif_carrier_off(dev);
- netif_stop_queue(dev);
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < mp->txq_count; i++) {
struct tx_queue *txq = mp->txq + i;
- if (mp->txq_mask & (1 << i)) {
- txq_reclaim(txq, 1);
- txq_reset_hw_ptr(txq);
- }
+ txq_reclaim(txq, txq->tx_ring_size, 1);
+ txq_reset_hw_ptr(txq);
}
}
return;
@@ -1767,119 +1845,93 @@ static void handle_link_event(struct mv643xx_eth_private *mp)
speed, duplex ? "full" : "half",
fc ? "en" : "dis");
- if (!netif_carrier_ok(dev)) {
+ if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
- netif_wake_queue(dev);
- }
}
-static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
+static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
{
- struct net_device *dev = (struct net_device *)dev_id;
- struct mv643xx_eth_private *mp = netdev_priv(dev);
- u32 int_cause;
- u32 int_cause_ext;
-
- int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
- (INT_TX_END | INT_RX | INT_EXT);
- if (int_cause == 0)
- return IRQ_NONE;
-
- int_cause_ext = 0;
- if (int_cause & INT_EXT) {
- int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num))
- & (INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX);
- wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext);
- }
+ struct mv643xx_eth_private *mp;
+ int work_done;
- if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK))
- handle_link_event(mp);
+ mp = container_of(napi, struct mv643xx_eth_private, napi);
- /*
- * RxBuffer or RxError set for any of the 8 queues?
- */
-#ifdef MV643XX_ETH_NAPI
- if (int_cause & INT_RX) {
- wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_RX));
- wrl(mp, INT_MASK(mp->port_num), 0x00000000);
- rdl(mp, INT_MASK(mp->port_num));
+ mp->work_rx_refill |= mp->work_rx_oom;
+ mp->work_rx_oom = 0;
- netif_rx_schedule(dev, &mp->napi);
- }
-#else
- if (int_cause & INT_RX) {
- int i;
+ work_done = 0;
+ while (work_done < budget) {
+ u8 queue_mask;
+ int queue;
+ int work_tbd;
- for (i = 7; i >= 0; i--)
- if (mp->rxq_mask & (1 << i))
- rxq_process(mp->rxq + i, INT_MAX);
- }
-#endif
-
- /*
- * TxBuffer or TxError set for any of the 8 queues?
- */
- if (int_cause_ext & INT_EXT_TX) {
- int i;
+ if (mp->work_link) {
+ mp->work_link = 0;
+ handle_link_event(mp);
+ continue;
+ }
- for (i = 0; i < 8; i++)
- if (mp->txq_mask & (1 << i))
- txq_reclaim(mp->txq + i, 0);
+ queue_mask = mp->work_tx | mp->work_tx_end |
+ mp->work_rx | mp->work_rx_refill;
+ if (!queue_mask) {
+ if (mv643xx_eth_collect_events(mp))
+ continue;
+ break;
+ }
- /*
- * Enough space again in the primary TX queue for a
- * full packet?
- */
- if (netif_carrier_ok(dev)) {
- spin_lock(&mp->lock);
- __txq_maybe_wake(mp->txq + mp->txq_primary);
- spin_unlock(&mp->lock);
+ queue = fls(queue_mask) - 1;
+ queue_mask = 1 << queue;
+
+ work_tbd = budget - work_done;
+ if (work_tbd > 16)
+ work_tbd = 16;
+
+ if (mp->work_tx_end & queue_mask) {
+ txq_kick(mp->txq + queue);
+ } else if (mp->work_tx & queue_mask) {
+ work_done += txq_reclaim(mp->txq + queue, work_tbd, 0);
+ txq_maybe_wake(mp->txq + queue);
+ } else if (mp->work_rx & queue_mask) {
+ work_done += rxq_process(mp->rxq + queue, work_tbd);
+ } else if (mp->work_rx_refill & queue_mask) {
+ work_done += rxq_refill(mp->rxq + queue, work_tbd);
+ } else {
+ BUG();
}
}
- /*
- * Any TxEnd interrupts?
- */
- if (int_cause & INT_TX_END) {
- int i;
-
- wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END));
-
- spin_lock(&mp->lock);
- for (i = 0; i < 8; i++) {
- struct tx_queue *txq = mp->txq + i;
- u32 hw_desc_ptr;
- u32 expected_ptr;
-
- if ((int_cause & (INT_TX_END_0 << i)) == 0)
- continue;
+ if (work_done < budget) {
+ if (mp->work_rx_oom)
+ mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
+ napi_complete(napi);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
+ }
- hw_desc_ptr =
- rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, i));
- expected_ptr = (u32)txq->tx_desc_dma +
- txq->tx_curr_desc * sizeof(struct tx_desc);
+ return work_done;
+}
- if (hw_desc_ptr != expected_ptr)
- txq_enable(txq);
- }
- spin_unlock(&mp->lock);
- }
+static inline void oom_timer_wrapper(unsigned long data)
+{
+ struct mv643xx_eth_private *mp = (void *)data;
- return IRQ_HANDLED;
+ napi_schedule(&mp->napi);
}
static void phy_reset(struct mv643xx_eth_private *mp)
{
- unsigned int data;
+ int data;
+
+ data = phy_read(mp->phy, MII_BMCR);
+ if (data < 0)
+ return;
- smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
data |= BMCR_RESET;
- smi_reg_write(mp, mp->phy_addr, MII_BMCR, data);
+ if (phy_write(mp->phy, MII_BMCR, data) < 0)
+ return;
do {
- udelay(1);
- smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
- } while (data & BMCR_RESET);
+ data = phy_read(mp->phy, MII_BMCR);
+ } while (data >= 0 && data & BMCR_RESET);
}
static void port_start(struct mv643xx_eth_private *mp)
@@ -1890,7 +1942,7 @@ static void port_start(struct mv643xx_eth_private *mp)
/*
* Perform PHY reset, if there is a PHY.
*/
- if (mp->phy_addr != -1) {
+ if (mp->phy != NULL) {
struct ethtool_cmd cmd;
mv643xx_eth_get_settings(mp->dev, &cmd);
@@ -1907,7 +1959,7 @@ static void port_start(struct mv643xx_eth_private *mp)
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
pscr |= DO_NOT_FORCE_LINK_FAIL;
- if (mp->phy_addr == -1)
+ if (mp->phy == NULL)
pscr |= FORCE_LINK_PASS;
wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
@@ -1917,12 +1969,9 @@ static void port_start(struct mv643xx_eth_private *mp)
* Configure TX path and queues.
*/
tx_set_rate(mp, 1000000000, 16777216);
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < mp->txq_count; i++) {
struct tx_queue *txq = mp->txq + i;
- if ((mp->txq_mask & (1 << i)) == 0)
- continue;
-
txq_reset_hw_ptr(txq);
txq_set_rate(txq, 1000000000, 16777216);
txq_set_fixed_prio_mode(txq);
@@ -1935,9 +1984,10 @@ static void port_start(struct mv643xx_eth_private *mp)
/*
* Receive all unmatched unicast, TCP, UDP, BPDU and broadcast
- * frames to RX queue #0.
+ * frames to RX queue #0, and include the pseudo-header when
+ * calculating receive checksums.
*/
- wrl(mp, PORT_CONFIG(mp->port_num), 0x00000000);
+ wrl(mp, PORT_CONFIG(mp->port_num), 0x02000000);
/*
* Treat BPDUs as normal multicasts, and disable partition mode.
@@ -1947,14 +1997,11 @@ static void port_start(struct mv643xx_eth_private *mp)
/*
* Enable the receive queues.
*/
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < mp->rxq_count; i++) {
struct rx_queue *rxq = mp->rxq + i;
int off = RXQ_CURRENT_DESC_PTR(mp->port_num, i);
u32 addr;
- if ((mp->rxq_mask & (1 << i)) == 0)
- continue;
-
addr = (u32)rxq->rx_desc_dma;
addr += rxq->rx_curr_desc * sizeof(struct rx_desc);
wrl(mp, off, addr);
@@ -1993,6 +2040,26 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
wrl(mp, TX_FIFO_URGENT_THRESHOLD(mp->port_num), (coal & 0x3fff) << 4);
}
+static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp)
+{
+ int skb_size;
+
+ /*
+ * Reserve 2+14 bytes for an ethernet header (the hardware
+ * automatically prepends 2 bytes of dummy data to each
+ * received packet), 16 bytes for up to four VLAN tags, and
+ * 4 bytes for the trailing FCS -- 36 bytes total.
+ */
+ skb_size = mp->dev->mtu + 36;
+
+ /*
+ * Make sure that the skb size is a multiple of 8 bytes, as
+ * the lower three bits of the receive descriptor's buffer
+ * size field are ignored by the hardware.
+ */
+ mp->skb_size = (skb_size + 7) & ~7;
+}
+
static int mv643xx_eth_open(struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
@@ -2004,8 +2071,7 @@ static int mv643xx_eth_open(struct net_device *dev)
rdl(mp, INT_CAUSE_EXT(mp->port_num));
err = request_irq(dev->irq, mv643xx_eth_irq,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- dev->name, dev);
+ IRQF_SHARED, dev->name, dev);
if (err) {
dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
return -EAGAIN;
@@ -2013,58 +2079,53 @@ static int mv643xx_eth_open(struct net_device *dev)
init_mac_tables(mp);
- for (i = 0; i < 8; i++) {
- if ((mp->rxq_mask & (1 << i)) == 0)
- continue;
+ mv643xx_eth_recalc_skb_size(mp);
+
+ napi_enable(&mp->napi);
+ skb_queue_head_init(&mp->rx_recycle);
+
+ for (i = 0; i < mp->rxq_count; i++) {
err = rxq_init(mp, i);
if (err) {
while (--i >= 0)
- if (mp->rxq_mask & (1 << i))
- rxq_deinit(mp->rxq + i);
+ rxq_deinit(mp->rxq + i);
goto out;
}
- rxq_refill(mp->rxq + i);
+ rxq_refill(mp->rxq + i, INT_MAX);
}
- for (i = 0; i < 8; i++) {
- if ((mp->txq_mask & (1 << i)) == 0)
- continue;
+ if (mp->work_rx_oom) {
+ mp->rx_oom.expires = jiffies + (HZ / 10);
+ add_timer(&mp->rx_oom);
+ }
+ for (i = 0; i < mp->txq_count; i++) {
err = txq_init(mp, i);
if (err) {
while (--i >= 0)
- if (mp->txq_mask & (1 << i))
- txq_deinit(mp->txq + i);
+ txq_deinit(mp->txq + i);
goto out_free;
}
}
-#ifdef MV643XX_ETH_NAPI
- napi_enable(&mp->napi);
-#endif
-
netif_carrier_off(dev);
- netif_stop_queue(dev);
port_start(mp);
set_rx_coal(mp, 0);
set_tx_coal(mp, 0);
- wrl(mp, INT_MASK_EXT(mp->port_num),
- INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX);
-
+ wrl(mp, INT_MASK_EXT(mp->port_num), INT_EXT_LINK_PHY | INT_EXT_TX);
wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
return 0;
out_free:
- for (i = 0; i < 8; i++)
- if (mp->rxq_mask & (1 << i))
- rxq_deinit(mp->rxq + i);
+ for (i = 0; i < mp->rxq_count; i++)
+ rxq_deinit(mp->rxq + i);
out:
free_irq(dev->irq, dev);
@@ -2076,12 +2137,10 @@ static void port_reset(struct mv643xx_eth_private *mp)
unsigned int data;
int i;
- for (i = 0; i < 8; i++) {
- if (mp->rxq_mask & (1 << i))
- rxq_disable(mp->rxq + i);
- if (mp->txq_mask & (1 << i))
- txq_disable(mp->txq + i);
- }
+ for (i = 0; i < mp->rxq_count; i++)
+ rxq_disable(mp->rxq + i);
+ for (i = 0; i < mp->txq_count; i++)
+ txq_disable(mp->txq + i);
while (1) {
u32 ps = rdl(mp, PORT_STATUS(mp->port_num));
@@ -2107,23 +2166,26 @@ static int mv643xx_eth_stop(struct net_device *dev)
wrl(mp, INT_MASK(mp->port_num), 0x00000000);
rdl(mp, INT_MASK(mp->port_num));
-#ifdef MV643XX_ETH_NAPI
+ del_timer_sync(&mp->mib_counters_timer);
+
napi_disable(&mp->napi);
-#endif
+
+ del_timer_sync(&mp->rx_oom);
+
netif_carrier_off(dev);
- netif_stop_queue(dev);
free_irq(dev->irq, dev);
port_reset(mp);
+ mv643xx_eth_get_stats(dev);
mib_counters_update(mp);
- for (i = 0; i < 8; i++) {
- if (mp->rxq_mask & (1 << i))
- rxq_deinit(mp->rxq + i);
- if (mp->txq_mask & (1 << i))
- txq_deinit(mp->txq + i);
- }
+ skb_queue_purge(&mp->rx_recycle);
+
+ for (i = 0; i < mp->rxq_count; i++)
+ rxq_deinit(mp->rxq + i);
+ for (i = 0; i < mp->txq_count; i++)
+ txq_deinit(mp->txq + i);
return 0;
}
@@ -2132,8 +2194,8 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- if (mp->phy_addr != -1)
- return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL);
+ if (mp->phy != NULL)
+ return phy_mii_ioctl(mp->phy, if_mii(ifr), cmd);
return -EOPNOTSUPP;
}
@@ -2146,6 +2208,7 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
dev->mtu = new_mtu;
+ mv643xx_eth_recalc_skb_size(mp);
tx_set_rate(mp, 1000000000, 16777216);
if (!netif_running(dev))
@@ -2173,12 +2236,10 @@ static void tx_timeout_task(struct work_struct *ugly)
mp = container_of(ugly, struct mv643xx_eth_private, tx_timeout_task);
if (netif_running(mp->dev)) {
- netif_stop_queue(mp->dev);
-
+ netif_tx_stop_all_queues(mp->dev);
port_reset(mp);
port_start(mp);
-
- __txq_maybe_wake(mp->txq + mp->txq_primary);
+ netif_tx_wake_all_queues(mp->dev);
}
}
@@ -2205,22 +2266,6 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
}
#endif
-static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg)
-{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
- int val;
-
- smi_reg_read(mp, addr, reg, &val);
-
- return val;
-}
-
-static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val)
-{
- struct mv643xx_eth_private *mp = netdev_priv(dev);
- smi_reg_write(mp, addr, reg, val);
-}
-
/* platform glue ************************************************************/
static void
@@ -2272,14 +2317,20 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
msp->extended_rx_coal_limit = 0;
/*
- * Check whether the TX rate control registers are in the
- * old or the new place.
+ * Check whether the MAC supports TX rate control, and if
+ * yes, whether its associated registers are in the old or
+ * the new place.
*/
writel(1, msp->base + TX_BW_MTU_MOVED(0));
- if (readl(msp->base + TX_BW_MTU_MOVED(0)) & 1)
- msp->tx_bw_control_moved = 1;
- else
- msp->tx_bw_control_moved = 0;
+ if (readl(msp->base + TX_BW_MTU_MOVED(0)) & 1) {
+ msp->tx_bw_control = TX_BW_CONTROL_NEW_LAYOUT;
+ } else {
+ writel(7, msp->base + TX_BW_RATE(0));
+ if (readl(msp->base + TX_BW_RATE(0)) & 7)
+ msp->tx_bw_control = TX_BW_CONTROL_OLD_LAYOUT;
+ else
+ msp->tx_bw_control = TX_BW_CONTROL_ABSENT;
+ }
}
static int mv643xx_eth_shared_probe(struct platform_device *pdev)
@@ -2309,7 +2360,45 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (msp->base == NULL)
goto out_free;
- spin_lock_init(&msp->phy_lock);
+ /*
+ * Set up and register SMI bus.
+ */
+ if (pd == NULL || pd->shared_smi == NULL) {
+ msp->smi_bus = mdiobus_alloc();
+ if (msp->smi_bus == NULL)
+ goto out_unmap;
+
+ msp->smi_bus->priv = msp;
+ msp->smi_bus->name = "mv643xx_eth smi";
+ msp->smi_bus->read = smi_bus_read;
+ msp->smi_bus->write = smi_bus_write,
+ snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
+ msp->smi_bus->parent = &pdev->dev;
+ msp->smi_bus->phy_mask = 0xffffffff;
+ if (mdiobus_register(msp->smi_bus) < 0)
+ goto out_free_mii_bus;
+ msp->smi = msp;
+ } else {
+ msp->smi = platform_get_drvdata(pd->shared_smi);
+ }
+
+ msp->err_interrupt = NO_IRQ;
+ init_waitqueue_head(&msp->smi_busy_wait);
+
+ /*
+ * Check whether the error interrupt is hooked up.
+ */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res != NULL) {
+ int err;
+
+ err = request_irq(res->start, mv643xx_eth_err_irq,
+ IRQF_SHARED, "mv643xx_eth", msp);
+ if (!err) {
+ writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
+ msp->err_interrupt = res->start;
+ }
+ }
/*
* (Re-)program MBUS remapping windows if we are asked to.
@@ -2327,6 +2416,10 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
return 0;
+out_free_mii_bus:
+ mdiobus_free(msp->smi_bus);
+out_unmap:
+ iounmap(msp->base);
out_free:
kfree(msp);
out:
@@ -2336,7 +2429,14 @@ out:
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
{
struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
+ struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
+ if (pd == NULL || pd->shared_smi == NULL) {
+ mdiobus_free(msp->smi_bus);
+ mdiobus_unregister(msp->smi_bus);
+ }
+ if (msp->err_interrupt != NO_IRQ)
+ free_irq(msp->err_interrupt, msp);
iounmap(msp->base);
kfree(msp);
@@ -2382,33 +2482,13 @@ static void set_params(struct mv643xx_eth_private *mp,
else
uc_addr_get(mp, dev->dev_addr);
- if (pd->phy_addr == -1) {
- mp->shared_smi = NULL;
- mp->phy_addr = -1;
- } else {
- mp->shared_smi = mp->shared;
- if (pd->shared_smi != NULL)
- mp->shared_smi = platform_get_drvdata(pd->shared_smi);
-
- if (pd->force_phy_addr || pd->phy_addr) {
- mp->phy_addr = pd->phy_addr & 0x3f;
- phy_addr_set(mp, mp->phy_addr);
- } else {
- mp->phy_addr = phy_addr_get(mp);
- }
- }
-
mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE;
if (pd->rx_queue_size)
mp->default_rx_ring_size = pd->rx_queue_size;
mp->rx_desc_sram_addr = pd->rx_sram_addr;
mp->rx_desc_sram_size = pd->rx_sram_size;
- if (pd->rx_queue_mask)
- mp->rxq_mask = pd->rx_queue_mask;
- else
- mp->rxq_mask = 0x01;
- mp->rxq_primary = fls(mp->rxq_mask) - 1;
+ mp->rxq_count = pd->rx_queue_count ? : 1;
mp->default_tx_ring_size = DEFAULT_TX_QUEUE_SIZE;
if (pd->tx_queue_size)
@@ -2416,76 +2496,63 @@ static void set_params(struct mv643xx_eth_private *mp,
mp->tx_desc_sram_addr = pd->tx_sram_addr;
mp->tx_desc_sram_size = pd->tx_sram_size;
- if (pd->tx_queue_mask)
- mp->txq_mask = pd->tx_queue_mask;
- else
- mp->txq_mask = 0x01;
- mp->txq_primary = fls(mp->txq_mask) - 1;
+ mp->txq_count = pd->tx_queue_count ? : 1;
}
-static int phy_detect(struct mv643xx_eth_private *mp)
+static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
+ int phy_addr)
{
- unsigned int data;
- unsigned int data2;
+ struct mii_bus *bus = mp->shared->smi->smi_bus;
+ struct phy_device *phydev;
+ int start;
+ int num;
+ int i;
+
+ if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) {
+ start = phy_addr_get(mp) & 0x1f;
+ num = 32;
+ } else {
+ start = phy_addr & 0x1f;
+ num = 1;
+ }
- smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
- smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE);
+ phydev = NULL;
+ for (i = 0; i < num; i++) {
+ int addr = (start + i) & 0x1f;
- smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data2);
- if (((data ^ data2) & BMCR_ANENABLE) == 0)
- return -ENODEV;
+ if (bus->phy_map[addr] == NULL)
+ mdiobus_scan(bus, addr);
- smi_reg_write(mp, mp->phy_addr, MII_BMCR, data);
+ if (phydev == NULL) {
+ phydev = bus->phy_map[addr];
+ if (phydev != NULL)
+ phy_addr_set(mp, addr);
+ }
+ }
- return 0;
+ return phydev;
}
-static int phy_init(struct mv643xx_eth_private *mp,
- struct mv643xx_eth_platform_data *pd)
+static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
{
- struct ethtool_cmd cmd;
- int err;
+ struct phy_device *phy = mp->phy;
- err = phy_detect(mp);
- if (err) {
- dev_printk(KERN_INFO, &mp->dev->dev,
- "no PHY detected at addr %d\n", mp->phy_addr);
- return err;
- }
phy_reset(mp);
- mp->mii.phy_id = mp->phy_addr;
- mp->mii.phy_id_mask = 0x3f;
- mp->mii.reg_num_mask = 0x1f;
- mp->mii.dev = mp->dev;
- mp->mii.mdio_read = mv643xx_eth_mdio_read;
- mp->mii.mdio_write = mv643xx_eth_mdio_write;
-
- mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
-
- memset(&cmd, 0, sizeof(cmd));
-
- cmd.port = PORT_MII;
- cmd.transceiver = XCVR_INTERNAL;
- cmd.phy_address = mp->phy_addr;
- if (pd->speed == 0) {
- cmd.autoneg = AUTONEG_ENABLE;
- cmd.speed = SPEED_100;
- cmd.advertising = ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full;
- if (mp->mii.supports_gmii)
- cmd.advertising |= ADVERTISED_1000baseT_Full;
+ phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII);
+
+ if (speed == 0) {
+ phy->autoneg = AUTONEG_ENABLE;
+ phy->speed = 0;
+ phy->duplex = 0;
+ phy->advertising = phy->supported | ADVERTISED_Autoneg;
} else {
- cmd.autoneg = AUTONEG_DISABLE;
- cmd.speed = pd->speed;
- cmd.duplex = pd->duplex;
+ phy->autoneg = AUTONEG_DISABLE;
+ phy->advertising = 0;
+ phy->speed = speed;
+ phy->duplex = duplex;
}
-
- mv643xx_eth_set_settings(mp->dev, &cmd);
-
- return 0;
+ phy_start_aneg(phy);
}
static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
@@ -2499,7 +2566,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
}
pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
- if (mp->phy_addr == -1) {
+ if (mp->phy == NULL) {
pscr |= DISABLE_AUTO_NEG_SPEED_GMII;
if (speed == SPEED_1000)
pscr |= SET_GMII_SPEED_TO_1000;
@@ -2538,7 +2605,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
return -ENODEV;
}
- dev = alloc_etherdev(sizeof(struct mv643xx_eth_private));
+ dev = alloc_etherdev_mq(sizeof(struct mv643xx_eth_private), 8);
if (!dev)
return -ENOMEM;
@@ -2549,33 +2616,47 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mp->port_num = pd->port_number;
mp->dev = dev;
-#ifdef MV643XX_ETH_NAPI
- netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 64);
-#endif
set_params(mp, pd);
+ dev->real_num_tx_queues = mp->txq_count;
- spin_lock_init(&mp->lock);
-
- mib_counters_clear(mp);
- INIT_WORK(&mp->tx_timeout_task, tx_timeout_task);
-
- if (mp->phy_addr != -1) {
- err = phy_init(mp, pd);
- if (err)
- goto out;
+ if (pd->phy_addr != MV643XX_ETH_PHY_NONE)
+ mp->phy = phy_scan(mp, pd->phy_addr);
+ if (mp->phy != NULL) {
+ phy_init(mp, pd->speed, pd->duplex);
SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
} else {
SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless);
}
+
init_pscr(mp, pd->speed, pd->duplex);
+ mib_counters_clear(mp);
+
+ init_timer(&mp->mib_counters_timer);
+ mp->mib_counters_timer.data = (unsigned long)mp;
+ mp->mib_counters_timer.function = mib_counters_timer_wrapper;
+ mp->mib_counters_timer.expires = jiffies + 30 * HZ;
+ add_timer(&mp->mib_counters_timer);
+
+ spin_lock_init(&mp->mib_counters_lock);
+
+ INIT_WORK(&mp->tx_timeout_task, tx_timeout_task);
+
+ netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 128);
+
+ init_timer(&mp->rx_oom);
+ mp->rx_oom.data = (unsigned long)mp;
+ mp->rx_oom.function = oom_timer_wrapper;
+
+
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
BUG_ON(!res);
dev->irq = res->start;
+ dev->get_stats = mv643xx_eth_get_stats;
dev->hard_start_xmit = mv643xx_eth_xmit;
dev->open = mv643xx_eth_open;
dev->stop = mv643xx_eth_stop;
@@ -2590,14 +2671,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev->watchdog_timeo = 2 * HZ;
dev->base_addr = 0;
-#ifdef MV643XX_ETH_CHECKSUM_OFFLOAD_TX
- /*
- * Zero copy can only work if we use Discovery II memory. Else, we will
- * have to map the buffers to ISA memory which is only 16 MB
- */
dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM;
-#endif
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -2611,16 +2686,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %s\n",
mp->port_num, print_mac(mac, dev->dev_addr));
- if (dev->features & NETIF_F_SG)
- dev_printk(KERN_NOTICE, &dev->dev, "scatter/gather enabled\n");
-
- if (dev->features & NETIF_F_IP_CSUM)
- dev_printk(KERN_NOTICE, &dev->dev, "tx checksum offload\n");
-
-#ifdef MV643XX_ETH_NAPI
- dev_printk(KERN_NOTICE, &dev->dev, "napi enabled\n");
-#endif
-
if (mp->tx_desc_sram_size > 0)
dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n");
@@ -2637,6 +2702,8 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
struct mv643xx_eth_private *mp = platform_get_drvdata(pdev);
unregister_netdev(mp->dev);
+ if (mp->phy != NULL)
+ phy_detach(mp->phy);
flush_scheduled_work();
free_netdev(mp->dev);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index d6524db321a..a9aebad5265 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.3-1.358"
+#define MYRI10GE_VERSION_STR "1.4.3-1.369"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -102,6 +102,8 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
+#define MYRI10GE_MAX_SLICES 32
+
struct myri10ge_rx_buffer_state {
struct page *page;
int page_offset;
@@ -138,6 +140,8 @@ struct myri10ge_rx_buf {
struct myri10ge_tx_buf {
struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */
+ __be32 __iomem *send_go; /* "go" doorbell ptr */
+ __be32 __iomem *send_stop; /* "stop" doorbell ptr */
struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */
char *req_bytes;
struct myri10ge_tx_buffer_state *info;
@@ -149,6 +153,7 @@ struct myri10ge_tx_buf {
int done ____cacheline_aligned; /* transmit slots completed */
int pkt_done; /* packets completed */
int wake_queue;
+ int queue_active;
};
struct myri10ge_rx_done {
@@ -183,7 +188,7 @@ struct myri10ge_slice_state {
dma_addr_t fw_stats_bus;
int watchdog_tx_done;
int watchdog_tx_req;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
int cached_dca_tag;
int cpu;
__be32 __iomem *dca_tag;
@@ -215,7 +220,7 @@ struct myri10ge_priv {
int msi_enabled;
int msix_enabled;
struct msix_entry *msix_vectors;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
int dca_enabled;
#endif
u32 link_state;
@@ -418,6 +423,12 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
return -ENOSYS;
} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {
return -E2BIG;
+ } else if (result == MXGEFW_CMD_ERROR_RANGE &&
+ cmd == MXGEFW_CMD_ENABLE_RSS_QUEUES &&
+ (data->
+ data1 & MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES) !=
+ 0) {
+ return -ERANGE;
} else {
dev_err(&mgp->pdev->dev,
"command %d failed, result = %d\n",
@@ -891,7 +902,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
struct myri10ge_slice_state *ss;
int i, status;
size_t bytes;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
unsigned long dca_tag_off;
#endif
@@ -947,9 +958,24 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
*/
cmd.data0 = mgp->num_slices;
- cmd.data1 = 1; /* use MSI-X */
+ cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+ if (mgp->dev->real_num_tx_queues > 1)
+ cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
&cmd, 0);
+
+ /* Firmware older than 1.4.32 only supports multiple
+ * RX queues, so if we get an error, first retry using a
+ * single TX queue before giving up */
+ if (status != 0 && mgp->dev->real_num_tx_queues > 1) {
+ mgp->dev->real_num_tx_queues = 1;
+ cmd.data0 = mgp->num_slices;
+ cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+ status = myri10ge_send_cmd(mgp,
+ MXGEFW_CMD_ENABLE_RSS_QUEUES,
+ &cmd, 0);
+ }
+
if (status != 0) {
dev_err(&mgp->pdev->dev,
"failed to set number of slices\n");
@@ -986,7 +1012,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
}
put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_DCA_OFFSET, &cmd, 0);
dca_tag_off = cmd.data0;
for (i = 0; i < mgp->num_slices; i++) {
@@ -1025,7 +1051,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
return status;
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
static void
myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag)
{
@@ -1060,8 +1086,9 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp)
}
err = dca_add_requester(&pdev->dev);
if (err) {
- dev_err(&pdev->dev,
- "dca_add_requester() failed, err=%d\n", err);
+ if (err != -ENODEV)
+ dev_err(&pdev->dev,
+ "dca_add_requester() failed, err=%d\n", err);
return;
}
mgp->dca_enabled = 1;
@@ -1316,6 +1343,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
{
struct pci_dev *pdev = ss->mgp->pdev;
struct myri10ge_tx_buf *tx = &ss->tx;
+ struct netdev_queue *dev_queue;
struct sk_buff *skb;
int idx, len;
@@ -1349,11 +1377,31 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
PCI_DMA_TODEVICE);
}
}
+
+ dev_queue = netdev_get_tx_queue(ss->dev, ss - ss->mgp->ss);
+ /*
+ * Make a minimal effort to prevent the NIC from polling an
+ * idle tx queue. If we can't get the lock we leave the queue
+ * active. In this case, either a thread was about to start
+ * using the queue anyway, or we lost a race and the NIC will
+ * waste some of its resources polling an inactive queue for a
+ * while.
+ */
+
+ if ((ss->mgp->dev->real_num_tx_queues > 1) &&
+ __netif_tx_trylock(dev_queue)) {
+ if (tx->req == tx->done) {
+ tx->queue_active = 0;
+ put_be32(htonl(1), tx->send_stop);
+ }
+ __netif_tx_unlock(dev_queue);
+ }
+
/* start the queue if we've stopped it */
- if (netif_queue_stopped(ss->dev)
+ if (netif_tx_queue_stopped(dev_queue)
&& tx->req - tx->done < (tx->mask >> 1)) {
tx->wake_queue++;
- netif_wake_queue(ss->dev);
+ netif_tx_wake_queue(dev_queue);
}
}
@@ -1457,7 +1505,7 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
struct net_device *netdev = ss->mgp->dev;
int work_done;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
if (ss->mgp->dca_enabled)
myri10ge_update_dca(ss);
#endif
@@ -1481,9 +1529,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
u32 send_done_count;
int i;
- /* an interrupt on a non-zero slice is implicitly valid
- * since MSI-X irqs are not shared */
- if (ss != mgp->ss) {
+ /* an interrupt on a non-zero receive-only slice is implicitly
+ * valid since MSI-X irqs are not shared */
+ if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
netif_rx_schedule(ss->dev, &ss->napi);
return (IRQ_HANDLED);
}
@@ -1525,7 +1573,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
barrier();
}
- myri10ge_check_statblock(mgp);
+ /* Only slice 0 updates stats */
+ if (ss == mgp->ss)
+ myri10ge_check_statblock(mgp);
put_be32(htonl(3), ss->irq_claim + 1);
return (IRQ_HANDLED);
@@ -1686,8 +1736,8 @@ static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = {
"tx_boundary", "WC", "irq", "MSI", "MSIX",
"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
"serial_number", "watchdog_resets",
-#ifdef CONFIG_DCA
- "dca_capable", "dca_enabled",
+#ifdef CONFIG_MYRI10GE_DCA
+ "dca_capable_firmware", "dca_device_present",
#endif
"link_changes", "link_up", "dropped_link_overflow",
"dropped_link_error_or_filtered",
@@ -1765,7 +1815,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
data[i++] = (unsigned int)mgp->read_write_dma;
data[i++] = (unsigned int)mgp->serial_number;
data[i++] = (unsigned int)mgp->watchdog_resets;
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
data[i++] = (unsigned int)(mgp->ss[0].dca_tag != NULL);
data[i++] = (unsigned int)(mgp->dca_enabled);
#endif
@@ -1883,6 +1933,7 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
/* ensure req_list entries are aligned to 8 bytes */
ss->tx.req_list = (struct mcp_kreq_ether_send *)
ALIGN((unsigned long)ss->tx.req_bytes, 8);
+ ss->tx.queue_active = 0;
bytes = rx_ring_entries * sizeof(*ss->rx_small.shadow);
ss->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
@@ -2200,11 +2251,14 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
int status;
ss = &mgp->ss[slice];
- cmd.data0 = 0; /* single slice for now */
- status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
- ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)
- (mgp->sram + cmd.data0);
-
+ status = 0;
+ if (slice == 0 || (mgp->dev->real_num_tx_queues > 1)) {
+ cmd.data0 = slice;
+ status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET,
+ &cmd, 0);
+ ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)
+ (mgp->sram + cmd.data0);
+ }
cmd.data0 = slice;
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET,
&cmd, 0);
@@ -2216,6 +2270,10 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
(mgp->sram + cmd.data0);
+ ss->tx.send_go = (__iomem __be32 *)
+ (mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice);
+ ss->tx.send_stop = (__iomem __be32 *)
+ (mgp->sram + MXGEFW_ETH_SEND_STOP + 64 * slice);
return status;
}
@@ -2229,7 +2287,7 @@ static int myri10ge_set_stats(struct myri10ge_priv *mgp, int slice)
ss = &mgp->ss[slice];
cmd.data0 = MYRI10GE_LOWPART_TO_U32(ss->fw_stats_bus);
cmd.data1 = MYRI10GE_HIGHPART_TO_U32(ss->fw_stats_bus);
- cmd.data2 = sizeof(struct mcp_irq_data);
+ cmd.data2 = sizeof(struct mcp_irq_data) | (slice << 16);
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
if (status == -ENOSYS) {
dma_addr_t bus = ss->fw_stats_bus;
@@ -2270,7 +2328,9 @@ static int myri10ge_open(struct net_device *dev)
if (mgp->num_slices > 1) {
cmd.data0 = mgp->num_slices;
- cmd.data1 = 1; /* use MSI-X */
+ cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+ if (mgp->dev->real_num_tx_queues > 1)
+ cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
&cmd, 0);
if (status != 0) {
@@ -2291,6 +2351,7 @@ static int myri10ge_open(struct net_device *dev)
printk(KERN_ERR
"myri10ge: %s: failed to setup rss tables\n",
dev->name);
+ goto abort_with_nothing;
}
/* just enable an identity mapping */
@@ -2361,7 +2422,11 @@ static int myri10ge_open(struct net_device *dev)
status = myri10ge_allocate_rings(ss);
if (status != 0)
goto abort_with_rings;
- if (slice == 0)
+
+ /* only firmware which supports multiple TX queues
+ * supports setting up the tx stats on non-zero
+ * slices */
+ if (slice == 0 || mgp->dev->real_num_tx_queues > 1)
status = myri10ge_set_stats(mgp, slice);
if (status) {
printk(KERN_ERR
@@ -2427,7 +2492,8 @@ static int myri10ge_open(struct net_device *dev)
mgp->running = MYRI10GE_ETH_RUNNING;
mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
add_timer(&mgp->watchdog_timer);
- netif_wake_queue(dev);
+ netif_tx_wake_all_queues(dev);
+
return 0;
abort_with_rings:
@@ -2460,7 +2526,8 @@ static int myri10ge_close(struct net_device *dev)
napi_disable(&mgp->ss[i].napi);
}
netif_carrier_off(dev);
- netif_stop_queue(dev);
+
+ netif_tx_stop_all_queues(dev);
old_down_cnt = mgp->down_cnt;
mb();
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
@@ -2565,18 +2632,21 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
struct mcp_kreq_ether_send *req;
struct myri10ge_tx_buf *tx;
struct skb_frag_struct *frag;
+ struct netdev_queue *netdev_queue;
dma_addr_t bus;
u32 low;
__be32 high_swapped;
unsigned int len;
int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
- u16 pseudo_hdr_offset, cksum_offset;
+ u16 pseudo_hdr_offset, cksum_offset, queue;
int cum_len, seglen, boundary, rdma_count;
u8 flags, odd_flag;
- /* always transmit through slot 0 */
- ss = mgp->ss;
+ queue = skb_get_queue_mapping(skb);
+ ss = &mgp->ss[queue];
+ netdev_queue = netdev_get_tx_queue(mgp->dev, queue);
tx = &ss->tx;
+
again:
req = tx->req_list;
avail = tx->mask - 1 - (tx->req - tx->done);
@@ -2592,7 +2662,7 @@ again:
if ((unlikely(avail < max_segments))) {
/* we are out of transmit resources */
tx->stop_queue++;
- netif_stop_queue(dev);
+ netif_tx_stop_queue(netdev_queue);
return 1;
}
@@ -2785,10 +2855,16 @@ again:
idx = ((count - 1) + tx->req) & tx->mask;
tx->info[idx].last = 1;
myri10ge_submit_req(tx, tx->req_list, count);
+ /* if using multiple tx queues, make sure NIC polls the
+ * current slice */
+ if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) {
+ tx->queue_active = 1;
+ put_be32(htonl(1), tx->send_go);
+ }
tx->pkt_start++;
if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
tx->stop_queue++;
- netif_stop_queue(dev);
+ netif_tx_stop_queue(netdev_queue);
}
dev->trans_start = jiffies;
return 0;
@@ -3366,20 +3442,21 @@ static void myri10ge_watchdog(struct work_struct *work)
for (i = 0; i < mgp->num_slices; i++) {
tx = &mgp->ss[i].tx;
printk(KERN_INFO
- "myri10ge: %s: (%d): %d %d %d %d %d\n",
- mgp->dev->name, i, tx->req, tx->done,
- tx->pkt_start, tx->pkt_done,
+ "myri10ge: %s: (%d): %d %d %d %d %d %d\n",
+ mgp->dev->name, i, tx->queue_active, tx->req,
+ tx->done, tx->pkt_start, tx->pkt_done,
(int)ntohl(mgp->ss[i].fw_stats->
send_done_count));
msleep(2000);
printk(KERN_INFO
- "myri10ge: %s: (%d): %d %d %d %d %d\n",
- mgp->dev->name, i, tx->req, tx->done,
- tx->pkt_start, tx->pkt_done,
+ "myri10ge: %s: (%d): %d %d %d %d %d %d\n",
+ mgp->dev->name, i, tx->queue_active, tx->req,
+ tx->done, tx->pkt_start, tx->pkt_done,
(int)ntohl(mgp->ss[i].fw_stats->
send_done_count));
}
}
+
rtnl_lock();
myri10ge_close(mgp->dev);
status = myri10ge_load_firmware(mgp, 1);
@@ -3434,10 +3511,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
/* nic seems like it might be stuck.. */
if (rx_pause_cnt != mgp->watchdog_pause) {
if (net_ratelimit())
- printk(KERN_WARNING "myri10ge %s:"
+ printk(KERN_WARNING
+ "myri10ge %s slice %d:"
"TX paused, check link partner\n",
- mgp->dev->name);
+ mgp->dev->name, i);
} else {
+ printk(KERN_WARNING
+ "myri10ge %s slice %d stuck:",
+ mgp->dev->name, i);
reset_needed = 1;
}
}
@@ -3652,7 +3733,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int status = -ENXIO;
int dac_enabled;
- netdev = alloc_etherdev(sizeof(*mgp));
+ netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
if (netdev == NULL) {
dev_err(dev, "Could not allocate ethernet device\n");
return -ENOMEM;
@@ -3757,13 +3838,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_err(&pdev->dev, "failed to alloc slice state\n");
goto abort_with_firmware;
}
-
+ netdev->real_num_tx_queues = mgp->num_slices;
status = myri10ge_reset(mgp);
if (status != 0) {
dev_err(&pdev->dev, "failed reset\n");
goto abort_with_slices;
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
myri10ge_setup_dca(mgp);
#endif
pci_set_drvdata(pdev, mgp);
@@ -3781,6 +3862,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->set_multicast_list = myri10ge_set_multicast_list;
netdev->set_mac_address = myri10ge_set_mac_address;
netdev->features = mgp->features;
+
if (dac_enabled)
netdev->features |= NETIF_F_HIGHDMA;
@@ -3866,7 +3948,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
netdev = mgp->dev;
unregister_netdev(netdev);
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
myri10ge_teardown_dca(mgp);
#endif
myri10ge_dummy_rdma(mgp, 0);
@@ -3911,7 +3993,7 @@ static struct pci_driver myri10ge_driver = {
#endif
};
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
static int
myri10ge_notify_dca(struct notifier_block *nb, unsigned long event, void *p)
{
@@ -3936,16 +4018,17 @@ static __init int myri10ge_init_module(void)
printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
MYRI10GE_VERSION_STR);
- if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_SRC_PORT ||
- myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) {
+ if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX) {
printk(KERN_ERR
"%s: Illegal rssh hash type %d, defaulting to source port\n",
myri10ge_driver.name, myri10ge_rss_hash);
myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT;
}
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
dca_register_notify(&myri10ge_dca_notifier);
#endif
+ if (myri10ge_max_slices > MYRI10GE_MAX_SLICES)
+ myri10ge_max_slices = MYRI10GE_MAX_SLICES;
return pci_register_driver(&myri10ge_driver);
}
@@ -3954,7 +4037,7 @@ module_init(myri10ge_init_module);
static __exit void myri10ge_cleanup_module(void)
{
-#ifdef CONFIG_DCA
+#ifdef CONFIG_MYRI10GE_DCA
dca_unregister_notify(&myri10ge_dca_notifier);
#endif
pci_unregister_driver(&myri10ge_driver);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 656a260fc95..3ad7589d6a1 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -1,6 +1,6 @@
/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
*
- * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net)
*/
static char version[] =
@@ -22,6 +22,9 @@ static char version[] =
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <net/dst.h>
#include <net/arp.h>
@@ -33,7 +36,6 @@ static char version[] =
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <asm/idprom.h>
-#include <asm/sbus.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
@@ -243,7 +245,8 @@ static void myri_clean_rings(struct myri_eth *mp)
u32 dma_addr;
dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
+ dma_unmap_single(&mp->myri_op->dev, dma_addr,
+ RX_ALLOC_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb(mp->rx_skbs[i]);
mp->rx_skbs[i] = NULL;
}
@@ -259,7 +262,9 @@ static void myri_clean_rings(struct myri_eth *mp)
u32 dma_addr;
dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3, SBUS_DMA_TODEVICE);
+ dma_unmap_single(&mp->myri_op->dev, dma_addr,
+ (skb->len + 3) & ~3,
+ DMA_TO_DEVICE);
dev_kfree_skb(mp->tx_skbs[i]);
mp->tx_skbs[i] = NULL;
}
@@ -288,7 +293,9 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
skb->dev = dev;
skb_put(skb, RX_ALLOC_SIZE);
- dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
+ dma_addr = dma_map_single(&mp->myri_op->dev,
+ skb->data, RX_ALLOC_SIZE,
+ DMA_FROM_DEVICE);
sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
sbus_writel(i, &rxd[i].ctx);
@@ -344,7 +351,8 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev)
DTX(("SKB[%d] ", entry));
dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len, SBUS_DMA_TODEVICE);
+ dma_unmap_single(&mp->myri_op->dev, dma_addr,
+ skb->len, DMA_TO_DEVICE);
dev_kfree_skb(skb);
mp->tx_skbs[entry] = NULL;
dev->stats.tx_packets++;
@@ -423,9 +431,9 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
/* Check for errors. */
DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
- sbus_dma_sync_single_for_cpu(mp->myri_sdev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
+ dma_sync_single_for_cpu(&mp->myri_op->dev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE, DMA_FROM_DEVICE);
if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
DRX(("ERROR["));
dev->stats.rx_errors++;
@@ -442,10 +450,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
drops++;
DRX(("DROP "));
dev->stats.rx_dropped++;
- sbus_dma_sync_single_for_device(mp->myri_sdev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- SBUS_DMA_FROMDEVICE);
+ dma_sync_single_for_device(&mp->myri_op->dev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE,
+ DMA_FROM_DEVICE);
sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
sbus_writel(index, &rxd->ctx);
sbus_writel(1, &rxd->num_sg);
@@ -464,17 +472,17 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
DRX(("skb_alloc(FAILED) "));
goto drop_it;
}
- sbus_unmap_single(mp->myri_sdev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- SBUS_DMA_FROMDEVICE);
+ dma_unmap_single(&mp->myri_op->dev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE,
+ DMA_FROM_DEVICE);
mp->rx_skbs[index] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, RX_ALLOC_SIZE);
- dma_addr = sbus_map_single(mp->myri_sdev,
- new_skb->data,
- RX_ALLOC_SIZE,
- SBUS_DMA_FROMDEVICE);
+ dma_addr = dma_map_single(&mp->myri_op->dev,
+ new_skb->data,
+ RX_ALLOC_SIZE,
+ DMA_FROM_DEVICE);
sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
sbus_writel(index, &rxd->ctx);
@@ -500,10 +508,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
/* Reuse original ring buffer. */
DRX(("reuse "));
- sbus_dma_sync_single_for_device(mp->myri_sdev,
- sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE,
- SBUS_DMA_FROMDEVICE);
+ dma_sync_single_for_device(&mp->myri_op->dev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE,
+ DMA_FROM_DEVICE);
sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
sbus_writel(index, &rxd->ctx);
sbus_writel(1, &rxd->num_sg);
@@ -652,7 +660,8 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
}
- dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len, SBUS_DMA_TODEVICE);
+ dma_addr = dma_map_single(&mp->myri_op->dev, skb->data,
+ len, DMA_TO_DEVICE);
sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
sbus_writel(len, &txd->myri_gathers[0].len);
sbus_writel(1, &txd->num_sg);
@@ -891,30 +900,30 @@ static const struct header_ops myri_header_ops = {
.cache_update = myri_header_cache_update,
};
-static int __devinit myri_ether_init(struct sbus_dev *sdev)
+static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- static int num;
+ struct device_node *dp = op->node;
static unsigned version_printed;
struct net_device *dev;
- struct myri_eth *mp;
- unsigned char prop_buf[32];
- int i;
DECLARE_MAC_BUF(mac);
+ struct myri_eth *mp;
+ const void *prop;
+ static int num;
+ int i, len;
- DET(("myri_ether_init(%p,%d):\n", sdev, num));
+ DET(("myri_ether_init(%p,%d):\n", op, num));
dev = alloc_etherdev(sizeof(struct myri_eth));
-
if (!dev)
return -ENOMEM;
if (version_printed++ == 0)
printk(version);
- SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
+ SET_NETDEV_DEV(dev, &op->dev);
- mp = (struct myri_eth *) dev->priv;
+ mp = netdev_priv(dev);
spin_lock_init(&mp->irq_lock);
- mp->myri_sdev = sdev;
+ mp->myri_op = op;
/* Clean out skb arrays. */
for (i = 0; i < (RX_RING_SIZE + 1); i++)
@@ -924,55 +933,44 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
mp->tx_skbs[i] = NULL;
/* First check for EEPROM information. */
- i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info",
- (char *)&mp->eeprom, sizeof(struct myri_eeprom));
- DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i));
- if (i == 0 || i == -1) {
+ prop = of_get_property(dp, "myrinet-eeprom-info", &len);
+
+ if (prop)
+ memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom));
+ if (!prop) {
/* No eeprom property, must cook up the values ourselves. */
DET(("No EEPROM: "));
mp->eeprom.bus_type = BUS_TYPE_SBUS;
- mp->eeprom.cpuvers = prom_getintdefault(sdev->prom_node,"cpu_version",0);
- mp->eeprom.cval = prom_getintdefault(sdev->prom_node,"clock_value",0);
- mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0);
- DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers,
- mp->eeprom.cval, mp->eeprom.ramsz));
- if (mp->eeprom.cpuvers == 0) {
- DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3));
+ mp->eeprom.cpuvers =
+ of_getintprop_default(dp, "cpu_version", 0);
+ mp->eeprom.cval =
+ of_getintprop_default(dp, "clock_value", 0);
+ mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0);
+ if (!mp->eeprom.cpuvers)
mp->eeprom.cpuvers = CPUVERS_2_3;
- }
- if (mp->eeprom.cpuvers < CPUVERS_3_0) {
- DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n"));
+ if (mp->eeprom.cpuvers < CPUVERS_3_0)
mp->eeprom.cval = 0;
- }
- if (mp->eeprom.ramsz == 0) {
- DET(("EEPROM: ramsz == 0, setting to 128k\n"));
+ if (!mp->eeprom.ramsz)
mp->eeprom.ramsz = (128 * 1024);
- }
- i = prom_getproperty(sdev->prom_node, "myrinet-board-id",
- &prop_buf[0], 10);
- DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i));
- if ((i != 0) && (i != -1))
- memcpy(&mp->eeprom.id[0], &prop_buf[0], 6);
+
+ prop = of_get_property(dp, "myrinet-board-id", &len);
+ if (prop)
+ memcpy(&mp->eeprom.id[0], prop, 6);
else
set_boardid_from_idprom(mp, num);
- i = prom_getproperty(sdev->prom_node, "fpga_version",
- &mp->eeprom.fvers[0], 32);
- DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i));
- if (i == 0 || i == -1)
+
+ prop = of_get_property(dp, "fpga_version", &len);
+ if (prop)
+ memcpy(&mp->eeprom.fvers[0], prop, 32);
+ else
memset(&mp->eeprom.fvers[0], 0, 32);
if (mp->eeprom.cpuvers == CPUVERS_4_1) {
- DET(("EEPROM: cpuvers CPUVERS_4_1, "));
- if (mp->eeprom.ramsz == (128 * 1024)) {
- DET(("ramsize 128k, setting to 256k, "));
+ if (mp->eeprom.ramsz == (128 * 1024))
mp->eeprom.ramsz = (256 * 1024);
- }
- if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
- DET(("changing cval from %08x to %08x ",
- mp->eeprom.cval, 0x50e450e4));
+ if ((mp->eeprom.cval == 0x40414041) ||
+ (mp->eeprom.cval == 0x90449044))
mp->eeprom.cval = 0x50e450e4;
- }
- DET(("\n"));
}
}
#ifdef DEBUG_DETECT
@@ -991,8 +989,8 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
* XXX only a valid version for PCI cards? Ask feldy...
*/
DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
- mp->regs = sbus_ioremap(&sdev->resource[0], 0,
- mp->reg_size, "MyriCOM Regs");
+ mp->regs = of_ioremap(&op->resource[0], 0,
+ mp->reg_size, "MyriCOM Regs");
if (!mp->regs) {
printk("MyriCOM: Cannot map MyriCOM registers.\n");
goto err;
@@ -1001,13 +999,12 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
mp->lregs = mp->lanai + (0x10000 * 2);
} else {
DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
- mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
- PAGE_SIZE, "MyriCOM Control Regs");
- mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
+ mp->cregs = of_ioremap(&op->resource[0], 0,
+ PAGE_SIZE, "MyriCOM Control Regs");
+ mp->lregs = of_ioremap(&op->resource[0], (256 * 1024),
PAGE_SIZE, "MyriCOM LANAI Regs");
- mp->lanai =
- sbus_ioremap(&sdev->resource[0], (512 * 1024),
- mp->eeprom.ramsz, "MyriCOM SRAM");
+ mp->lanai = of_ioremap(&op->resource[0], (512 * 1024),
+ mp->eeprom.ramsz, "MyriCOM SRAM");
}
DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
mp->cregs, mp->lregs, mp->lanai));
@@ -1039,16 +1036,15 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
myri_reset_on(mp->cregs);
/* Get the supported DVMA burst sizes from our SBUS. */
- mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node,
- "burst-sizes", 0x00);
-
- if (!sbus_can_burst64(sdev))
+ mp->myri_bursts = of_getintprop_default(dp->parent,
+ "burst-sizes", 0x00);
+ if (!sbus_can_burst64())
mp->myri_bursts &= ~(DMA_BURST64);
DET(("MYRI bursts %02x\n", mp->myri_bursts));
/* Encode SBUS interrupt level in second control register. */
- i = prom_getint(sdev->prom_node, "interrupts");
+ i = of_getintprop_default(dp, "interrupts", 0);
if (i == 0)
i = 4;
DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
@@ -1063,7 +1059,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
dev->tx_timeout = &myri_tx_timeout;
dev->watchdog_timeo = 5*HZ;
dev->set_multicast_list = &myri_set_multicast;
- dev->irq = sdev->irqs[0];
+ dev->irq = op->irqs[0];
/* Register interrupt handler now. */
DET(("Requesting MYRIcom IRQ line.\n"));
@@ -1088,7 +1084,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev)
goto err_free_irq;
}
- dev_set_drvdata(&sdev->ofdev.dev, mp);
+ dev_set_drvdata(&op->dev, mp);
num++;
@@ -1105,39 +1101,31 @@ err:
return -ENODEV;
}
-
-static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match)
-{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
-
- return myri_ether_init(sdev);
-}
-
-static int __devexit myri_sbus_remove(struct of_device *dev)
+static int __devexit myri_sbus_remove(struct of_device *op)
{
- struct myri_eth *mp = dev_get_drvdata(&dev->dev);
+ struct myri_eth *mp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = mp->dev;
- unregister_netdevice(net_dev);
+ unregister_netdev(net_dev);
free_irq(net_dev->irq, net_dev);
if (mp->eeprom.cpuvers < CPUVERS_4_0) {
- sbus_iounmap(mp->regs, mp->reg_size);
+ of_iounmap(&op->resource[0], mp->regs, mp->reg_size);
} else {
- sbus_iounmap(mp->cregs, PAGE_SIZE);
- sbus_iounmap(mp->lregs, (256 * 1024));
- sbus_iounmap(mp->lanai, (512 * 1024));
+ of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE);
+ of_iounmap(&op->resource[0], mp->lregs, (256 * 1024));
+ of_iounmap(&op->resource[0], mp->lanai, (512 * 1024));
}
free_netdev(net_dev);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id myri_sbus_match[] = {
+static const struct of_device_id myri_sbus_match[] = {
{
.name = "MYRICOM,mlanai",
},
@@ -1158,7 +1146,7 @@ static struct of_platform_driver myri_sbus_driver = {
static int __init myri_sbus_init(void)
{
- return of_register_driver(&myri_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&myri_sbus_driver, &of_bus_type);
}
static void __exit myri_sbus_exit(void)
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 5d93fcc95d5..ff363e95d9c 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -288,7 +288,7 @@ struct myri_eth {
struct myri_eeprom eeprom; /* Local copy of EEPROM. */
unsigned int reg_size; /* Size of register space. */
unsigned int shmem_base; /* Offset to shared ram. */
- struct sbus_dev *myri_sdev; /* Our SBUS device struct. */
+ struct of_device *myri_op; /* Our OF device struct. */
};
/* We use this to acquire receive skb's that we can DMA directly into. */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index b238ed0e8ac..f7fa3944659 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -612,7 +612,7 @@ static void undo_cable_magic(struct net_device *dev);
static void check_link(struct net_device *dev);
static void netdev_timer(unsigned long data);
static void dump_ring(struct net_device *dev);
-static void tx_timeout(struct net_device *dev);
+static void ns_tx_timeout(struct net_device *dev);
static int alloc_ring(struct net_device *dev);
static void refill_rx(struct net_device *dev);
static void init_ring(struct net_device *dev);
@@ -920,7 +920,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
dev->set_multicast_list = &set_rx_mode;
dev->change_mtu = &natsemi_change_mtu;
dev->do_ioctl = &netdev_ioctl;
- dev->tx_timeout = &tx_timeout;
+ dev->tx_timeout = &ns_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1875,7 +1875,7 @@ static void dump_ring(struct net_device *dev)
}
}
-static void tx_timeout(struct net_device *dev)
+static void ns_tx_timeout(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
@@ -3232,7 +3232,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
* suspend/resume synchronization:
* entry points:
* netdev_open, netdev_close, netdev_ioctl, set_rx_mode, intr_handler,
- * start_tx, tx_timeout
+ * start_tx, ns_tx_timeout
*
* No function accesses the hardware without checking np->hands_off.
* the check occurs under spin_lock_irq(&np->lock);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index fa3ceca4e15..eb681c0d51b 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -64,6 +64,25 @@ static const char version2[] =
/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
#define SUPPORT_NE_BAD_CLONES
+/* 0xbad = bad sig or no reset ack */
+#define BAD 0xbad
+
+#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
+static struct platform_device *pdev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];
+
+#ifdef MODULE
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es),required");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+#endif /* MODULE */
/* Do we perform extra sanity checks on stuff ? */
/* #define NE_SANITY_CHECK */
@@ -74,6 +93,10 @@ static const char version2[] =
/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
/* #define PACKETBUF_MEMSIZE 0x40 */
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
/* Do we need a portlist for the ISA auto-probe ? */
#define NEEDS_PORTLIST
@@ -192,8 +215,13 @@ static int __init do_ne_probe(struct net_device *dev)
#endif
/* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
+ if (base_addr > 0x1ff) { /* Check a single specified location. */
+ int ret = ne_probe1(dev, base_addr);
+ if (ret)
+ printk(KERN_WARNING "ne.c: No NE*000 card found at "
+ "i/o = %#lx\n", base_addr);
+ return ret;
+ }
else if (base_addr != 0) /* Don't probe at all. */
return -ENXIO;
@@ -214,28 +242,6 @@ static int __init do_ne_probe(struct net_device *dev)
return -ENODEV;
}
-#ifndef MODULE
-struct net_device * __init ne_probe(int unit)
-{
- struct net_device *dev = alloc_eip_netdev();
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
-
- err = do_ne_probe(dev);
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-#endif
-
static int __init ne_probe_isapnp(struct net_device *dev)
{
int i;
@@ -329,7 +335,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
with an otherwise unused dev->mem_end value of "0xBAD" will
cause the driver to skip these parts of the probe. */
- bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+ bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
/* Reset card. Who knows what dain-bramaged state it was left in. */
@@ -806,46 +812,95 @@ retry:
static int __init ne_drv_probe(struct platform_device *pdev)
{
struct net_device *dev;
+ int err, this_dev = pdev->id;
struct resource *res;
- int err, irq;
-
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- irq = platform_get_irq(pdev, 0);
- if (!res || irq < 0)
- return -ENODEV;
dev = alloc_eip_netdev();
if (!dev)
return -ENOMEM;
- dev->irq = irq;
- dev->base_addr = res->start;
+
+ /* ne.c doesn't populate resources in platform_device, but
+ * rbtx4927_ne_init and rbtx4938_ne_init do register devices
+ * with resources.
+ */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (res) {
+ dev->base_addr = res->start;
+ dev->irq = platform_get_irq(pdev, 0);
+ } else {
+ if (this_dev < 0 || this_dev >= MAX_NE_CARDS)
+ return -EINVAL;
+ dev->base_addr = io[this_dev];
+ dev->irq = irq[this_dev];
+ dev->mem_end = bad[this_dev];
+ }
err = do_ne_probe(dev);
if (err) {
free_netdev(dev);
return err;
}
platform_set_drvdata(pdev, dev);
+
+ /* Update with any values found by probing, don't update if
+ * resources were specified.
+ */
+ if (!res) {
+ io[this_dev] = dev->base_addr;
+ irq[this_dev] = dev->irq;
+ }
return 0;
}
-static int __exit ne_drv_remove(struct platform_device *pdev)
+static int ne_drv_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
- free_netdev(dev);
+ if (dev) {
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ netif_device_detach(dev);
+ unregister_netdev(dev);
+ if (idev)
+ pnp_device_detach(idev);
+ /* Careful ne_drv_remove can be called twice, once from
+ * the platform_driver.remove and again when the
+ * platform_device is being removed.
+ */
+ ei_status.priv = 0;
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+ free_netdev(dev);
+ platform_set_drvdata(pdev, NULL);
+ }
return 0;
}
+/* Remove unused devices or all if true. */
+static void ne_loop_rm_unreg(int all)
+{
+ int this_dev;
+ struct platform_device *pdev;
+ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+ pdev = pdev_ne[this_dev];
+ /* No network device == unused */
+ if (pdev && (!platform_get_drvdata(pdev) || all)) {
+ ne_drv_remove(pdev);
+ platform_device_unregister(pdev);
+ pdev_ne[this_dev] = NULL;
+ }
+ }
+}
+
#ifdef CONFIG_PM
static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
struct net_device *dev = platform_get_drvdata(pdev);
- if (netif_running(dev))
+ if (netif_running(dev)) {
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
netif_device_detach(dev);
+ if (idev)
+ pnp_stop_dev(idev);
+ }
return 0;
}
@@ -854,6 +909,9 @@ static int ne_drv_resume(struct platform_device *pdev)
struct net_device *dev = platform_get_drvdata(pdev);
if (netif_running(dev)) {
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ if (idev)
+ pnp_start_dev(idev);
ne_reset_8390(dev);
NS8390p_init(dev, 1);
netif_device_attach(dev);
@@ -866,7 +924,7 @@ static int ne_drv_resume(struct platform_device *pdev)
#endif
static struct platform_driver ne_driver = {
- .remove = __exit_p(ne_drv_remove),
+ .remove = ne_drv_remove,
.suspend = ne_drv_suspend,
.resume = ne_drv_resume,
.driver = {
@@ -875,91 +933,96 @@ static struct platform_driver ne_driver = {
},
};
-static int __init ne_init(void)
+static void __init ne_add_devices(void)
{
- return platform_driver_probe(&ne_driver, ne_drv_probe);
-}
+ int this_dev;
+ struct platform_device *pdev;
-static void __exit ne_exit(void)
-{
- platform_driver_unregister(&ne_driver);
+ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+ if (pdev_ne[this_dev])
+ continue;
+ pdev = platform_device_register_simple(
+ DRV_NAME, this_dev, NULL, 0);
+ if (IS_ERR(pdev))
+ continue;
+ pdev_ne[this_dev] = pdev;
+ }
}
#ifdef MODULE
-#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es),required");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
-MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-
-int __init init_module(void)
+int __init init_module()
{
- int this_dev, found = 0;
- int plat_found = !ne_init();
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = alloc_eip_netdev();
- if (!dev)
- break;
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- if (do_ne_probe(dev) == 0) {
- dev_ne[found++] = dev;
- continue;
- }
- free_netdev(dev);
- if (found || plat_found)
- break;
- if (io[this_dev] != 0)
- printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
- else
- printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
- return -ENXIO;
+ int retval;
+ ne_add_devices();
+ retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+ if (retval) {
+ if (io[0] == 0)
+ printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
+ " value(s) for ISA cards.\n");
+ ne_loop_rm_unreg(1);
+ return retval;
}
- if (found || plat_found)
- return 0;
- return -ENODEV;
-}
-static void cleanup_card(struct net_device *dev)
+ /* Unregister unused platform_devices. */
+ ne_loop_rm_unreg(0);
+ return retval;
+}
+#else /* MODULE */
+static int __init ne_init(void)
{
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
+ int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+
+ /* Unregister unused platform_devices. */
+ ne_loop_rm_unreg(0);
+ return retval;
}
+module_init(ne_init);
-void __exit cleanup_module(void)
+struct net_device * __init ne_probe(int unit)
{
int this_dev;
+ struct net_device *dev;
+
+ /* Find an empty slot, that is no net_device and zero io port. */
+ this_dev = 0;
+ while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
+ io[this_dev]) {
+ if (++this_dev == MAX_NE_CARDS)
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Get irq, io from kernel command line */
+ dev = alloc_eip_netdev();
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
- ne_exit();
+ sprintf(dev->name, "eth%d", unit);
+ netdev_boot_setup_check(dev);
+
+ io[this_dev] = dev->base_addr;
+ irq[this_dev] = dev->irq;
+ bad[this_dev] = dev->mem_end;
+
+ free_netdev(dev);
+
+ ne_add_devices();
+
+ /* return the first device found */
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = dev_ne[this_dev];
- if (dev) {
- unregister_netdev(dev);
- cleanup_card(dev);
- free_netdev(dev);
+ if (pdev_ne[this_dev]) {
+ dev = platform_get_drvdata(pdev_ne[this_dev]);
+ if (dev)
+ return dev;
}
}
+
+ return ERR_PTR(-ENODEV);
}
-#else /* MODULE */
-module_init(ne_init);
-module_exit(ne_exit);
#endif /* MODULE */
+
+static void __exit ne_exit(void)
+{
+ platform_driver_unregister(&ne_driver);
+ ne_loop_rm_unreg(1);
+}
+module_exit(ne_exit);
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 3f9af759cb9..b9bed82e1d2 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -189,7 +189,7 @@ netx_eth_interrupt(int irq, void *dev_id)
if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
printk("%s: unexpected status: 0x%08x\n",
- __FUNCTION__, status);
+ __func__, status);
fill_level =
readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 244ab49c433..f8e601c51da 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -742,7 +742,7 @@ extern char netxen_nic_driver_name[];
} while (0)
#else
#define DPRINTK(klevel, fmt, args...) do { \
- printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
+ printk(KERN_##klevel PFX "%s: %s: " fmt, __func__,\
(adapter != NULL && adapter->netdev != NULL) ? \
adapter->netdev->name : NULL, \
## args); } while(0)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 32bb47adbe3..6ef3f0d84bc 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -77,18 +77,18 @@ static irqreturn_t netxen_msi_intr(int irq, void *data);
/* PCI Device ID Table */
#define ENTRY(device) \
- {PCI_DEVICE(0x4040, (device)), \
+ {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \
.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
- ENTRY(0x0001),
- ENTRY(0x0002),
- ENTRY(0x0003),
- ENTRY(0x0004),
- ENTRY(0x0005),
- ENTRY(0x0024),
- ENTRY(0x0025),
- ENTRY(0x0100),
+ ENTRY(PCI_DEVICE_ID_NX2031_10GXSR),
+ ENTRY(PCI_DEVICE_ID_NX2031_10GCX4),
+ ENTRY(PCI_DEVICE_ID_NX2031_4GCU),
+ ENTRY(PCI_DEVICE_ID_NX2031_IMEZ),
+ ENTRY(PCI_DEVICE_ID_NX2031_HMEZ),
+ ENTRY(PCI_DEVICE_ID_NX2031_XG_MGMT),
+ ENTRY(PCI_DEVICE_ID_NX2031_XG_MGMT2),
+ ENTRY(PCI_DEVICE_ID_NX3031),
{0,}
};
@@ -241,7 +241,7 @@ static void netxen_check_options(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_REF_QG:
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
- adapter->msix_supported = 0;
+ adapter->msix_supported = !!use_msi_x;
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
break;
@@ -359,16 +359,6 @@ static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
int i, pos;
struct pci_dev *pdev;
- pdev = pci_get_device(0x1166, 0x0140, NULL);
- if (pdev) {
- pci_dev_put(pdev);
- adapter->hw_read_wx(adapter,
- NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
- chicken |= 0x4000;
- adapter->hw_write_wx(adapter,
- NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
- }
-
pdev = adapter->pdev;
adapter->hw_read_wx(adapter,
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index e4765b713ab..ebc81270290 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -5984,6 +5984,56 @@ static void niu_netif_start(struct niu *np)
niu_enable_interrupts(np, 1);
}
+static void niu_reset_buffers(struct niu *np)
+{
+ int i, j, k, err;
+
+ if (np->rx_rings) {
+ for (i = 0; i < np->num_rx_rings; i++) {
+ struct rx_ring_info *rp = &np->rx_rings[i];
+
+ for (j = 0, k = 0; j < MAX_RBR_RING_SIZE; j++) {
+ struct page *page;
+
+ page = rp->rxhash[j];
+ while (page) {
+ struct page *next =
+ (struct page *) page->mapping;
+ u64 base = page->index;
+ base = base >> RBR_DESCR_ADDR_SHIFT;
+ rp->rbr[k++] = cpu_to_le32(base);
+ page = next;
+ }
+ }
+ for (; k < MAX_RBR_RING_SIZE; k++) {
+ err = niu_rbr_add_page(np, rp, GFP_ATOMIC, k);
+ if (unlikely(err))
+ break;
+ }
+
+ rp->rbr_index = rp->rbr_table_size - 1;
+ rp->rcr_index = 0;
+ rp->rbr_pending = 0;
+ rp->rbr_refill_pending = 0;
+ }
+ }
+ if (np->tx_rings) {
+ for (i = 0; i < np->num_tx_rings; i++) {
+ struct tx_ring_info *rp = &np->tx_rings[i];
+
+ for (j = 0; j < MAX_TX_RING_SIZE; j++) {
+ if (rp->tx_buffs[j].skb)
+ (void) release_tx_packet(np, rp, j);
+ }
+
+ rp->pending = MAX_TX_RING_SIZE;
+ rp->prod = 0;
+ rp->cons = 0;
+ rp->wrap_bit = 0;
+ }
+ }
+}
+
static void niu_reset_task(struct work_struct *work)
{
struct niu *np = container_of(work, struct niu, reset_task);
@@ -6006,6 +6056,12 @@ static void niu_reset_task(struct work_struct *work)
niu_stop_hw(np);
+ spin_unlock_irqrestore(&np->lock, flags);
+
+ niu_reset_buffers(np);
+
+ spin_lock_irqsave(&np->lock, flags);
+
err = niu_init_hw(np);
if (!err) {
np->timer.expires = jiffies + HZ;
@@ -9074,7 +9130,7 @@ static int __devexit niu_of_remove(struct of_device *op)
return 0;
}
-static struct of_device_id niu_match[] = {
+static const struct of_device_id niu_match[] = {
{
.name = "network",
.compatible = "SUNW,niusl",
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 53451c3b2c0..0a575fef29e 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -119,7 +119,7 @@ KERN_INFO " Support available from http://foo.com/bar/baz.html\n";
#ifdef NETDRV_DEBUG
/* note: prints function name for you */
-# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
#else
# define DPRINTK(fmt, args...)
#endif
@@ -130,7 +130,7 @@ KERN_INFO " Support available from http://foo.com/bar/baz.html\n";
# define assert(expr) \
if(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
- #expr,__FILE__,__FUNCTION__,__LINE__); \
+ #expr,__FILE__,__func__,__LINE__); \
}
#endif
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 7112fd5e0e1..08c4dd89607 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -355,9 +355,10 @@ static int tc574_config(struct pcmcia_device *link)
for (i = j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
+ if (i == 0)
+ break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
@@ -377,7 +378,7 @@ static int tc574_config(struct pcmcia_device *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == 0) {
pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(le16_to_cpu(buf[i]));
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 549a6455842..c235cdba69c 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -15,7 +15,7 @@
incorporated herein by reference.
Donald Becker may be reached at becker@scyld.com
- Updated for 2.5.x by Alan Cox <alan@redhat.com>
+ Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
======================================================================*/
@@ -278,9 +278,10 @@ static int tc589_config(struct pcmcia_device *link)
if (multi && (j & 0x80)) continue;
link->io.BasePort1 = j ^ 0x300;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
+ if (i == 0)
+ break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
@@ -295,7 +296,7 @@ static int tc589_config(struct pcmcia_device *link)
/* The 3c589 has an extra EEPROM for configuration info, including
the hardware address. The 3c562 puts the address in the CIS. */
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == 0) {
pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(le16_to_cpu(buf[i]));
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
index e8f55d8ed7a..9b8f793b1cc 100644
--- a/drivers/net/pcmcia/Kconfig
+++ b/drivers/net/pcmcia/Kconfig
@@ -111,7 +111,7 @@ config ARCNET_COM20020_CS
config PCMCIA_IBMTR
tristate "IBM PCMCIA tokenring adapter support"
- depends on IBMTR!=y && TR && !64BIT
+ depends on IBMTR!=y && TR
help
Say Y here if you intend to attach this type of Token Ring PCMCIA
card to your computer. You then also need to say Y to "Token Ring
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 3f682d49a4e..b37a498939a 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -262,7 +262,7 @@ static int try_io_port(struct pcmcia_device *link)
if (link->io.NumPorts2 > 0) {
/* for master/slave multifunction cards */
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
- link->irq.Attributes =
+ link->irq.Attributes =
IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
}
} else {
@@ -276,7 +276,8 @@ static int try_io_port(struct pcmcia_device *link)
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) return ret;
+ if (ret == 0)
+ return ret;
}
return ret;
} else {
@@ -284,59 +285,50 @@ static int try_io_port(struct pcmcia_device *link)
}
}
+static int axnet_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -ENODEV;
+
+ p_dev->conf.ConfigIndex = 0x05;
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return -ENODEV;
+}
+
static int axnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
int i, j, last_ret, last_fn;
- u_short buf[64];
DECLARE_MAC_BUF(mac);
DEBUG(0, "axnet_config(0x%p)\n", link);
- tuple.Attributes = 0;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = 0x05;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
- if (last_ret != CS_SUCCESS) {
+ last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
+ if (last_ret != 0) {
cs_error(link, RequestIO, last_ret);
goto failed;
}
@@ -784,6 +776,7 @@ static struct pcmcia_device_id axnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
+ PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index ea9414c4d90..831090c7562 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -260,21 +260,21 @@ static int com20020_config(struct pcmcia_device *link)
DEBUG(0, "com20020_config(0x%p)\n", link);
DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
- i = !CS_SUCCESS;
+ i = -ENODEV;
if (!link->io.BasePort1)
{
for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
{
link->io.BasePort1 = ioaddr;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
+ if (i == 0)
break;
}
}
else
i = pcmcia_request_io(link, &link->io);
- if (i != CS_SUCCESS)
+ if (i != 0)
{
DEBUG(1,"arcnet: requestIO failed totally!\n");
goto failed;
@@ -287,7 +287,7 @@ static int com20020_config(struct pcmcia_device *link)
link->irq.AssignedIRQ,
link->irq.IRQInfo1, link->irq.IRQInfo2);
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS)
+ if (i != 0)
{
DEBUG(1,"arcnet: requestIRQ failed totally!\n");
goto failed;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index a550c9bd126..69d916daa7b 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -309,7 +309,8 @@ static int mfc_try_io_port(struct pcmcia_device *link)
printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
}
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) return ret;
+ if (ret == 0)
+ return ret;
}
return ret;
}
@@ -325,7 +326,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
link->io.BasePort1 = ioaddr;
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) {
+ if (ret == 0) {
/* calculate ConfigIndex value */
link->conf.ConfigIndex =
((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
@@ -356,12 +357,12 @@ static int fmvj18x_config(struct pcmcia_device *link)
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
- if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == 0) {
/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
link->conf.ConfigIndex = parse.cftable_entry.index;
switch (link->manf_id) {
case MANFID_TDK:
@@ -430,10 +431,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->irq.Attributes =
IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
ret = mfc_try_io_port(link);
- if (ret != CS_SUCCESS) goto cs_failed;
+ if (ret != 0) goto cs_failed;
} else if (cardtype == UNGERMANN) {
ret = ungermann_try_io_port(link);
- if (ret != CS_SUCCESS) goto cs_failed;
+ if (ret != 0) goto cs_failed;
} else {
CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
@@ -565,7 +566,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
i = pcmcia_request_window(&link, &req, &link->win);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestWindow, i);
return -1;
}
@@ -599,7 +600,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
iounmap(base);
j = pcmcia_release_window(link->win);
- if (j != CS_SUCCESS)
+ if (j != 0)
cs_error(link, ReleaseWindow, j);
return (i != 0x200) ? 0 : -1;
@@ -620,7 +621,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
i = pcmcia_request_window(&link, &req, &link->win);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestWindow, i);
return -1;
}
@@ -642,7 +643,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
iounmap(base);
j = pcmcia_release_window(link->win);
- if (j != CS_SUCCESS)
+ if (j != 0)
cs_error(link, ReleaseWindow, j);
return 0;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 4eafa4f42cf..cf3cca4642f 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -238,7 +238,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
/* Try PRIMARY card at 0xA20-0xA23 */
link->io.BasePort1 = 0xA20;
i = pcmcia_request_io(link, &link->io);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
/* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
link->io.BasePort1 = 0xA24;
CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index cfcbea9b7e2..448cd40aeba 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -69,7 +69,7 @@ Driver Notes and Issues
History
-------------------------------------------------------------------------------
Log: nmclan_cs.c,v
- * 2.5.75-ac1 2003/07/11 Alan Cox <alan@redhat.com>
+ * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk>
* Fixed hang on card eject as we probe it
* Cleaned up to use new style locking.
*
@@ -925,7 +925,7 @@ static void mace_tx_timeout(struct net_device *dev)
printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
#if RESET_ON_TIMEOUT
printk("resetting card\n");
- pcmcia_reset_card(link, NULL);
+ pcmcia_reset_card(link->socket);
#else /* #if RESET_ON_TIMEOUT */
printk("NOT resetting card\n");
#endif /* #if RESET_ON_TIMEOUT */
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 2d4c4ad89b8..e40d6301aa7 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -310,7 +310,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
i = pcmcia_request_window(&link, &req, &link->win);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestWindow, i);
return NULL;
}
@@ -333,7 +333,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
iounmap(virt);
j = pcmcia_release_window(link->win);
- if (j != CS_SUCCESS)
+ if (j != 0)
cs_error(link, ReleaseWindow, j);
return (i < NR_INFO) ? hw_info+i : NULL;
} /* get_hwinfo */
@@ -504,7 +504,8 @@ static int try_io_port(struct pcmcia_device *link)
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) return ret;
+ if (ret == 0)
+ return ret;
}
return ret;
} else {
@@ -512,58 +513,53 @@ static int try_io_port(struct pcmcia_device *link)
}
}
+static int pcnet_confcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ int *has_shmem = priv_data;
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -EINVAL;
+
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+
+ *has_shmem = ((cfg->mem.nwin == 1) &&
+ (cfg->mem.win[0].len >= 0x4000));
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return 0;
+}
+
static int pcnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+ int last_ret, last_fn, start_pg, stop_pg, cm_offset;
int has_shmem = 0;
- u_short buf[64];
hw_info_t *local_hw_info;
DECLARE_MAC_BUF(mac);
DEBUG(0, "pcnet_config(0x%p)\n", link);
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = cfg->index;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- has_shmem = ((cfg->mem.nwin == 1) &&
- (cfg->mem.win[0].len >= 0x4000));
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
- if (last_ret != CS_SUCCESS) {
+ last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
+ if (last_ret) {
cs_error(link, RequestIO, last_ret);
goto failed;
}
@@ -1626,6 +1622,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
@@ -1737,7 +1734,6 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
- PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6),
PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
/* too generic! */
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 250eb1954c3..c74d6656d26 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -409,10 +409,13 @@ static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
{
int i;
- if ((i = pcmcia_get_first_tuple(handle, tuple)) != CS_SUCCESS ||
- (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS)
+ i = pcmcia_get_first_tuple(handle, tuple);
+ if (i != 0)
return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
+ i = pcmcia_get_tuple_data(handle, tuple);
+ if (i != 0)
+ return i;
+ return pcmcia_parse_tuple(tuple, parse);
}
static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
@@ -420,10 +423,10 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
{
int i;
- if ((i = pcmcia_get_next_tuple(handle, tuple)) != CS_SUCCESS ||
- (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS)
+ if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 ||
+ (i = pcmcia_get_tuple_data(handle, tuple)) != 0)
return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
+ return pcmcia_parse_tuple(tuple, parse);
}
/*======================================================================
@@ -459,27 +462,36 @@ static int mhz_3288_power(struct pcmcia_device *link)
return 0;
}
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ int k;
+ p_dev->io.BasePort2 = cf->io.win[0].base;
+ for (k = 0; k < 0x400; k += 0x10) {
+ if (k & 0x80)
+ continue;
+ p_dev->io.BasePort1 = k ^ 0x300;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
+}
+
static int mhz_mfc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
struct smc_cfg_mem *cfg_mem;
- tuple_t *tuple;
- cisparse_t *parse;
- cistpl_cftable_entry_t *cf;
- u_char *buf;
win_req_t req;
memreq_t mem;
- int i, k;
+ int i;
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
if (!cfg_mem)
- return CS_OUT_OF_RESOURCE;
-
- tuple = &cfg_mem->tuple;
- parse = &cfg_mem->parse;
- cf = &parse->cftable_entry;
- buf = cfg_mem->buf;
+ return -ENOMEM;
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
@@ -489,27 +501,9 @@ static int mhz_mfc_config(struct pcmcia_device *link)
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts2 = 8;
- tuple->Attributes = tuple->TupleOffset = 0;
- tuple->TupleData = (cisdata_t *)buf;
- tuple->TupleDataMax = 255;
- tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
- i = first_tuple(link, tuple, parse);
/* The Megahertz combo cards have modem-like CIS entries, so
we have to explicitly try a bunch of port combinations. */
- while (i == CS_SUCCESS) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort2 = cf->io.win[0].base;
- for (k = 0; k < 0x400; k += 0x10) {
- if (k & 0x80) continue;
- link->io.BasePort1 = k ^ 0x300;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- if (i == CS_SUCCESS) break;
- i = next_tuple(link, tuple, parse);
- }
- if (i != CS_SUCCESS)
+ if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
goto free_cfg_mem;
dev->base_addr = link->io.BasePort1;
@@ -518,7 +512,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
req.Base = req.Size = 0;
req.AccessSpeed = 0;
i = pcmcia_request_window(&link, &req, &link->win);
- if (i != CS_SUCCESS)
+ if (i != 0)
goto free_cfg_mem;
smc->base = ioremap(req.Base, req.Size);
mem.CardOffset = mem.Page = 0;
@@ -526,14 +520,14 @@ static int mhz_mfc_config(struct pcmcia_device *link)
mem.CardOffset = link->conf.ConfigBase;
i = pcmcia_map_mem_page(link->win, &mem);
- if ((i == CS_SUCCESS)
+ if ((i == 0)
&& (smc->manfid == MANFID_MEGAHERTZ)
&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))
mhz_3288_power(link);
free_cfg_mem:
kfree(cfg_mem);
- return i;
+ return -ENODEV;
}
static int mhz_setup(struct pcmcia_device *link)
@@ -560,12 +554,12 @@ static int mhz_setup(struct pcmcia_device *link)
/* Read the station address from the CIS. It is stored as the last
(fourth) string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
- if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) != 0) {
rc = -1;
goto free_cfg_mem;
}
/* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
- if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+ if (next_tuple(link, tuple, parse) != 0)
first_tuple(link, tuple, parse);
if (parse->version_1.ns > 3) {
station_addr = parse->version_1.str + parse->version_1.ofs[3];
@@ -577,11 +571,11 @@ static int mhz_setup(struct pcmcia_device *link)
/* Another possibility: for the EM3288, in a special tuple */
tuple->DesiredTuple = 0x81;
- if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, tuple) != 0) {
rc = -1;
goto free_cfg_mem;
}
- if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_tuple_data(link, tuple) != 0) {
rc = -1;
goto free_cfg_mem;
}
@@ -660,46 +654,27 @@ static int mot_setup(struct pcmcia_device *link)
/*====================================================================*/
+static int smc_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int smc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- struct smc_cfg_mem *cfg_mem;
- tuple_t *tuple;
- cisparse_t *parse;
- cistpl_cftable_entry_t *cf;
- u_char *buf;
int i;
- cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
- if (!cfg_mem)
- return CS_OUT_OF_RESOURCE;
-
- tuple = &cfg_mem->tuple;
- parse = &cfg_mem->parse;
- cf = &parse->cftable_entry;
- buf = cfg_mem->buf;
-
- tuple->Attributes = tuple->TupleOffset = 0;
- tuple->TupleData = (cisdata_t *)buf;
- tuple->TupleDataMax = 255;
- tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
link->io.NumPorts1 = 16;
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i == CS_SUCCESS) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- i = next_tuple(link, tuple, parse);
- }
- if (i == CS_SUCCESS)
- dev->base_addr = link->io.BasePort1;
+ i = pcmcia_loop_config(link, smc_configcheck, NULL);
+ if (!i)
+ dev->base_addr = link->io.BasePort1;
- kfree(cfg_mem);
return i;
}
@@ -715,7 +690,7 @@ static int smc_setup(struct pcmcia_device *link)
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
if (!cfg_mem)
- return CS_OUT_OF_RESOURCE;
+ return -ENOMEM;
tuple = &cfg_mem->tuple;
parse = &cfg_mem->parse;
@@ -728,12 +703,12 @@ static int smc_setup(struct pcmcia_device *link)
/* Check for a LAN function extension tuple */
tuple->DesiredTuple = CISTPL_FUNCE;
i = first_tuple(link, tuple, parse);
- while (i == CS_SUCCESS) {
+ while (i == 0) {
if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
break;
i = next_tuple(link, tuple, parse);
}
- if (i == CS_SUCCESS) {
+ if (i == 0) {
node_id = (cistpl_lan_node_id_t *)parse->funce.data;
if (node_id->nb == 6) {
for (i = 0; i < 6; i++)
@@ -780,9 +755,10 @@ static int osi_config(struct pcmcia_device *link)
for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j];
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
+ if (i == 0)
+ break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
/* Fallback: turn off hard decode */
link->conf.ConfigIndex = 0x03;
link->io.NumPorts2 = 0;
@@ -815,13 +791,13 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
/* Read the station address from tuple 0x90, subtuple 0x04 */
tuple->DesiredTuple = 0x90;
i = pcmcia_get_first_tuple(link, tuple);
- while (i == CS_SUCCESS) {
+ while (i == 0) {
i = pcmcia_get_tuple_data(link, tuple);
- if ((i != CS_SUCCESS) || (buf[0] == 0x04))
+ if ((i != 0) || (buf[0] == 0x04))
break;
i = pcmcia_get_next_tuple(link, tuple);
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
rc = -1;
goto free_cfg_mem;
}
@@ -959,8 +935,11 @@ static int check_sig(struct pcmcia_device *link)
======================================================================*/
-#define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
+#define CS_EXIT_TEST(ret, svc, label) \
+if (ret != 0) { \
+ cs_error(link, svc, ret); \
+ goto label; \
+}
static int smc91c92_config(struct pcmcia_device *link)
{
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index f6c4698ce73..e1fd585e713 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -353,7 +353,7 @@ typedef struct local_info_t {
* Some more prototypes
*/
static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void do_tx_timeout(struct net_device *dev);
+static void xirc_tx_timeout(struct net_device *dev);
static void xirc2ps_tx_timeout_task(struct work_struct *work);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
@@ -377,7 +377,7 @@ first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 &&
(err = pcmcia_get_tuple_data(handle, tuple)) == 0)
- err = pcmcia_parse_tuple(handle, tuple, parse);
+ err = pcmcia_parse_tuple(tuple, parse);
return err;
}
@@ -388,7 +388,7 @@ next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 &&
(err = pcmcia_get_tuple_data(handle, tuple)) == 0)
- err = pcmcia_parse_tuple(handle, tuple, parse);
+ err = pcmcia_parse_tuple(tuple, parse);
return err;
}
@@ -590,7 +590,7 @@ xirc2ps_probe(struct pcmcia_device *link)
dev->open = &do_open;
dev->stop = &do_stop;
#ifdef HAVE_TX_TIMEOUT
- dev->tx_timeout = do_tx_timeout;
+ dev->tx_timeout = xirc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task);
#endif
@@ -715,6 +715,47 @@ has_ce2_string(struct pcmcia_device * p_dev)
return 0;
}
+static int
+xirc2ps_config_modem(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ unsigned int ioaddr;
+
+ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
+ for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+ p_dev->io.BasePort2 = cf->io.win[0].base;
+ p_dev->io.BasePort1 = ioaddr;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+static int
+xirc2ps_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ int *pass = priv_data;
+
+ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
+ p_dev->io.BasePort2 = cf->io.win[0].base;
+ p_dev->io.BasePort1 = p_dev->io.BasePort2
+ + (*pass ? (cf->index & 0x20 ? -24:8)
+ : (cf->index & 0x20 ? 8:-24));
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
+
+}
+
/****************
* xirc2ps_config() is scheduled to run after a CARD_INSERTION event
* is received, to configure the PCMCIA socket, and to make the
@@ -725,13 +766,12 @@ xirc2ps_config(struct pcmcia_device * link)
{
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
+ unsigned int ioaddr;
tuple_t tuple;
cisparse_t parse;
- unsigned int ioaddr;
int err, i;
u_char buf[64];
cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
DECLARE_MAC_BUF(mac);
local->dingo_ccr = NULL;
@@ -846,19 +886,8 @@ xirc2ps_config(struct pcmcia_device * link)
/* Take the Modem IO port from the CIS and scan for a free
* Ethernet port */
link->io.NumPorts1 = 16; /* no Mako stuff anymore */
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(link, &tuple, &parse); !err;
- err = next_tuple(link, &tuple, &parse)) {
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
- for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
- link->conf.ConfigIndex = cf->index ;
- link->io.BasePort2 = cf->io.win[0].base;
- link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link, &link->io)))
- goto port_found;
- }
- }
- }
+ if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
+ goto port_found;
} else {
link->io.NumPorts1 = 18;
/* We do 2 passes here: The first one uses the regular mapping and
@@ -866,21 +895,9 @@ xirc2ps_config(struct pcmcia_device * link)
* mirrored every 32 bytes. Actually we use a mirrored port for
* the Mako if (on the first pass) the COR bit 5 is set.
*/
- for (pass=0; pass < 2; pass++) {
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(link, &tuple, &parse); !err;
- err = next_tuple(link, &tuple, &parse)){
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){
- link->conf.ConfigIndex = cf->index ;
- link->io.BasePort2 = cf->io.win[0].base;
- link->io.BasePort1 = link->io.BasePort2
- + (pass ? (cf->index & 0x20 ? -24:8)
- : (cf->index & 0x20 ? 8:-24));
- if (!(err=pcmcia_request_io(link, &link->io)))
+ for (pass=0; pass < 2; pass++)
+ if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
goto port_found;
- }
- }
- }
/* if special option:
* try to configure as Ethernet only.
* .... */
@@ -1335,7 +1352,7 @@ xirc2ps_tx_timeout_task(struct work_struct *work)
}
static void
-do_tx_timeout(struct net_device *dev)
+xirc_tx_timeout(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
lp->stats.tx_errors++;
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 4e07956a483..cf24cc34deb 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -24,7 +24,7 @@
struct fixed_mdio_bus {
int irqs[PHY_MAX_ADDR];
- struct mii_bus mii_bus;
+ struct mii_bus *mii_bus;
struct list_head phys;
};
@@ -115,8 +115,7 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
static int fixed_mdio_read(struct mii_bus *bus, int phy_id, int reg_num)
{
- struct fixed_mdio_bus *fmb = container_of(bus, struct fixed_mdio_bus,
- mii_bus);
+ struct fixed_mdio_bus *fmb = bus->priv;
struct fixed_phy *fp;
if (reg_num >= MII_REGS_NUM)
@@ -213,19 +212,28 @@ static int __init fixed_mdio_bus_init(void)
goto err_pdev;
}
- snprintf(fmb->mii_bus.id, MII_BUS_ID_SIZE, "0");
- fmb->mii_bus.name = "Fixed MDIO Bus";
- fmb->mii_bus.dev = &pdev->dev;
- fmb->mii_bus.read = &fixed_mdio_read;
- fmb->mii_bus.write = &fixed_mdio_write;
- fmb->mii_bus.irq = fmb->irqs;
+ fmb->mii_bus = mdiobus_alloc();
+ if (fmb->mii_bus == NULL) {
+ ret = -ENOMEM;
+ goto err_mdiobus_reg;
+ }
- ret = mdiobus_register(&fmb->mii_bus);
+ snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "0");
+ fmb->mii_bus->name = "Fixed MDIO Bus";
+ fmb->mii_bus->priv = fmb;
+ fmb->mii_bus->parent = &pdev->dev;
+ fmb->mii_bus->read = &fixed_mdio_read;
+ fmb->mii_bus->write = &fixed_mdio_write;
+ fmb->mii_bus->irq = fmb->irqs;
+
+ ret = mdiobus_register(fmb->mii_bus);
if (ret)
- goto err_mdiobus_reg;
+ goto err_mdiobus_alloc;
return 0;
+err_mdiobus_alloc:
+ mdiobus_free(fmb->mii_bus);
err_mdiobus_reg:
platform_device_unregister(pdev);
err_pdev:
@@ -238,7 +246,8 @@ static void __exit fixed_mdio_bus_exit(void)
struct fixed_mdio_bus *fmb = &platform_fmb;
struct fixed_phy *fp, *tmp;
- mdiobus_unregister(&fmb->mii_bus);
+ mdiobus_unregister(fmb->mii_bus);
+ mdiobus_free(fmb->mii_bus);
platform_device_unregister(pdev);
list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index c01b78013dd..2576055b350 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -165,7 +165,7 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
{
struct mii_bus *bus;
- bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ bus = mdiobus_alloc();
if (!bus)
return NULL;
@@ -184,7 +184,7 @@ void free_mdio_bitbang(struct mii_bus *bus)
struct mdiobb_ctrl *ctrl = bus->priv;
module_put(ctrl->ops->owner);
- kfree(bus);
+ mdiobus_free(bus);
}
EXPORT_SYMBOL(free_mdio_bitbang);
diff --git a/drivers/net/phy/mdio-ofgpio.c b/drivers/net/phy/mdio-ofgpio.c
index 7edfc0c3483..2ff97754e57 100644
--- a/drivers/net/phy/mdio-ofgpio.c
+++ b/drivers/net/phy/mdio-ofgpio.c
@@ -122,7 +122,7 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
if (!new_bus)
- goto out_free_priv;
+ goto out_free_bitbang;
new_bus->name = "GPIO Bitbanged MII",
@@ -142,7 +142,7 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
if (!strcmp(np->type, "ethernet-phy"))
add_phy(new_bus, np);
- new_bus->dev = &ofdev->dev;
+ new_bus->parent = &ofdev->dev;
dev_set_drvdata(&ofdev->dev, new_bus);
ret = mdiobus_register(new_bus);
@@ -155,9 +155,9 @@ out_free_irqs:
dev_set_drvdata(&ofdev->dev, NULL);
kfree(new_bus->irq);
out_free_bus:
- kfree(new_bus);
-out_free_priv:
free_mdio_bitbang(new_bus);
+out_free_bitbang:
+ kfree(bitbang);
out:
return ret;
}
@@ -168,11 +168,10 @@ static int mdio_ofgpio_remove(struct of_device *ofdev)
struct mdio_gpio_info *bitbang = bus->priv;
mdiobus_unregister(bus);
+ kfree(bus->irq);
free_mdio_bitbang(bus);
dev_set_drvdata(&ofdev->dev, NULL);
- kfree(bus->irq);
kfree(bitbang);
- kfree(bus);
return 0;
}
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 94e0b7ed76f..d0ed1ef284a 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -36,6 +36,43 @@
#include <asm/uaccess.h>
/**
+ * mdiobus_alloc - allocate a mii_bus structure
+ *
+ * Description: called by a bus driver to allocate an mii_bus
+ * structure to fill in.
+ */
+struct mii_bus *mdiobus_alloc(void)
+{
+ struct mii_bus *bus;
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (bus != NULL)
+ bus->state = MDIOBUS_ALLOCATED;
+
+ return bus;
+}
+EXPORT_SYMBOL(mdiobus_alloc);
+
+/**
+ * mdiobus_release - mii_bus device release callback
+ * @d: the target struct device that contains the mii_bus
+ *
+ * Description: called when the last reference to an mii_bus is
+ * dropped, to free the underlying memory.
+ */
+static void mdiobus_release(struct device *d)
+{
+ struct mii_bus *bus = to_mii_bus(d);
+ BUG_ON(bus->state != MDIOBUS_RELEASED);
+ kfree(bus);
+}
+
+static struct class mdio_bus_class = {
+ .name = "mdio_bus",
+ .dev_release = mdiobus_release,
+};
+
+/**
* mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
* @bus: target mii_bus
*
@@ -54,55 +91,36 @@ int mdiobus_register(struct mii_bus *bus)
NULL == bus->write)
return -EINVAL;
- mutex_init(&bus->mdio_lock);
-
- if (bus->reset)
- bus->reset(bus);
-
- for (i = 0; i < PHY_MAX_ADDR; i++) {
- struct phy_device *phydev;
-
- if (bus->phy_mask & (1 << i)) {
- bus->phy_map[i] = NULL;
- continue;
- }
-
- phydev = get_phy_device(bus, i);
+ BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
+ bus->state != MDIOBUS_UNREGISTERED);
- if (IS_ERR(phydev))
- return PTR_ERR(phydev);
+ bus->dev.parent = bus->parent;
+ bus->dev.class = &mdio_bus_class;
+ bus->dev.groups = NULL;
+ memcpy(bus->dev.bus_id, bus->id, MII_BUS_ID_SIZE);
- /* There's a PHY at this address
- * We need to set:
- * 1) IRQ
- * 2) bus_id
- * 3) parent
- * 4) bus
- * 5) mii_bus
- * And, we need to register it */
- if (phydev) {
- phydev->irq = bus->irq[i];
+ err = device_register(&bus->dev);
+ if (err) {
+ printk(KERN_ERR "mii_bus %s failed to register\n", bus->id);
+ return -EINVAL;
+ }
- phydev->dev.parent = bus->dev;
- phydev->dev.bus = &mdio_bus_type;
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i);
+ bus->state = MDIOBUS_REGISTERED;
- phydev->bus = bus;
+ mutex_init(&bus->mdio_lock);
- /* Run all of the fixups for this PHY */
- phy_scan_fixups(phydev);
+ if (bus->reset)
+ bus->reset(bus);
- err = device_register(&phydev->dev);
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ bus->phy_map[i] = NULL;
+ if ((bus->phy_mask & (1 << i)) == 0) {
+ struct phy_device *phydev;
- if (err) {
- printk(KERN_ERR "phy %d failed to register\n",
- i);
- phy_device_free(phydev);
- phydev = NULL;
- }
+ phydev = mdiobus_scan(bus, i);
+ if (IS_ERR(phydev))
+ err = PTR_ERR(phydev);
}
-
- bus->phy_map[i] = phydev;
}
pr_info("%s: probed\n", bus->name);
@@ -115,6 +133,10 @@ void mdiobus_unregister(struct mii_bus *bus)
{
int i;
+ BUG_ON(bus->state != MDIOBUS_REGISTERED);
+ bus->state = MDIOBUS_UNREGISTERED;
+
+ device_unregister(&bus->dev);
for (i = 0; i < PHY_MAX_ADDR; i++) {
if (bus->phy_map[i])
device_unregister(&bus->phy_map[i]->dev);
@@ -123,6 +145,122 @@ void mdiobus_unregister(struct mii_bus *bus)
EXPORT_SYMBOL(mdiobus_unregister);
/**
+ * mdiobus_free - free a struct mii_bus
+ * @bus: mii_bus to free
+ *
+ * This function releases the reference to the underlying device
+ * object in the mii_bus. If this is the last reference, the mii_bus
+ * will be freed.
+ */
+void mdiobus_free(struct mii_bus *bus)
+{
+ /*
+ * For compatibility with error handling in drivers.
+ */
+ if (bus->state == MDIOBUS_ALLOCATED) {
+ kfree(bus);
+ return;
+ }
+
+ BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
+ bus->state = MDIOBUS_RELEASED;
+
+ put_device(&bus->dev);
+}
+EXPORT_SYMBOL(mdiobus_free);
+
+struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
+{
+ struct phy_device *phydev;
+ int err;
+
+ phydev = get_phy_device(bus, addr);
+ if (IS_ERR(phydev) || phydev == NULL)
+ return phydev;
+
+ /* There's a PHY at this address
+ * We need to set:
+ * 1) IRQ
+ * 2) bus_id
+ * 3) parent
+ * 4) bus
+ * 5) mii_bus
+ * And, we need to register it */
+
+ phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
+
+ phydev->dev.parent = bus->parent;
+ phydev->dev.bus = &mdio_bus_type;
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr);
+
+ phydev->bus = bus;
+
+ /* Run all of the fixups for this PHY */
+ phy_scan_fixups(phydev);
+
+ err = device_register(&phydev->dev);
+ if (err) {
+ printk(KERN_ERR "phy %d failed to register\n", addr);
+ phy_device_free(phydev);
+ phydev = NULL;
+ }
+
+ bus->phy_map[addr] = phydev;
+
+ return phydev;
+}
+EXPORT_SYMBOL(mdiobus_scan);
+
+/**
+ * mdiobus_read - Convenience function for reading a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to read
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_read(struct mii_bus *bus, int addr, u16 regnum)
+{
+ int retval;
+
+ BUG_ON(in_interrupt());
+
+ mutex_lock(&bus->mdio_lock);
+ retval = bus->read(bus, addr, regnum);
+ mutex_unlock(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(mdiobus_read);
+
+/**
+ * mdiobus_write - Convenience function for writing a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_write(struct mii_bus *bus, int addr, u16 regnum, u16 val)
+{
+ int err;
+
+ BUG_ON(in_interrupt());
+
+ mutex_lock(&bus->mdio_lock);
+ err = bus->write(bus, addr, regnum, val);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_write);
+
+/**
* mdio_bus_match - determine if given PHY driver supports the given PHY device
* @dev: target PHY device
* @drv: given PHY driver
@@ -174,10 +312,20 @@ EXPORT_SYMBOL(mdio_bus_type);
int __init mdio_bus_init(void)
{
- return bus_register(&mdio_bus_type);
+ int ret;
+
+ ret = class_register(&mdio_bus_class);
+ if (!ret) {
+ ret = bus_register(&mdio_bus_type);
+ if (ret)
+ class_unregister(&mdio_bus_class);
+ }
+
+ return ret;
}
void mdio_bus_exit(void)
{
+ class_unregister(&mdio_bus_class);
bus_unregister(&mdio_bus_type);
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 45cc2914d34..df4e6257d4a 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -58,55 +58,6 @@ EXPORT_SYMBOL(phy_print_status);
/**
- * phy_read - Convenience function for reading a given PHY register
- * @phydev: the phy_device struct
- * @regnum: register number to read
- *
- * NOTE: MUST NOT be called from interrupt context,
- * because the bus read/write functions may wait for an interrupt
- * to conclude the operation.
- */
-int phy_read(struct phy_device *phydev, u16 regnum)
-{
- int retval;
- struct mii_bus *bus = phydev->bus;
-
- BUG_ON(in_interrupt());
-
- mutex_lock(&bus->mdio_lock);
- retval = bus->read(bus, phydev->addr, regnum);
- mutex_unlock(&bus->mdio_lock);
-
- return retval;
-}
-EXPORT_SYMBOL(phy_read);
-
-/**
- * phy_write - Convenience function for writing a given PHY register
- * @phydev: the phy_device struct
- * @regnum: register number to write
- * @val: value to write to @regnum
- *
- * NOTE: MUST NOT be called from interrupt context,
- * because the bus read/write functions may wait for an interrupt
- * to conclude the operation.
- */
-int phy_write(struct phy_device *phydev, u16 regnum, u16 val)
-{
- int err;
- struct mii_bus *bus = phydev->bus;
-
- BUG_ON(in_interrupt());
-
- mutex_lock(&bus->mdio_lock);
- err = bus->write(bus, phydev->addr, regnum, val);
- mutex_unlock(&bus->mdio_lock);
-
- return err;
-}
-EXPORT_SYMBOL(phy_write);
-
-/**
* phy_clear_interrupt - Ack the phy device's interrupt
* @phydev: the phy_device struct
*
@@ -366,7 +317,8 @@ int phy_mii_ioctl(struct phy_device *phydev,
switch (cmd) {
case SIOCGMIIPHY:
mii_data->phy_id = phydev->addr;
- break;
+ /* fall through */
+
case SIOCGMIIREG:
mii_data->val_out = phy_read(phydev, mii_data->reg_num);
break;
@@ -413,7 +365,7 @@ int phy_mii_ioctl(struct phy_device *phydev,
break;
default:
- return -ENOTTY;
+ return -EOPNOTSUPP;
}
return 0;
@@ -728,6 +680,12 @@ static void phy_change(struct work_struct *work)
if (err)
goto irq_enable_err;
+ /* Stop timer and run the state queue now. The work function for
+ * state_queue will start the timer up again.
+ */
+ del_timer(&phydev->phy_timer);
+ schedule_work(&phydev->state_queue);
+
return;
irq_enable_err:
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 16a0e7de588..e11b03b2b25 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -309,11 +309,6 @@ void phy_disconnect(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_disconnect);
-static int phy_compare_id(struct device *dev, void *data)
-{
- return strcmp((char *)data, dev->bus_id) ? 0 : 1;
-}
-
/**
* phy_attach - attach a network device to a particular PHY device
* @dev: network device to attach
@@ -337,8 +332,7 @@ struct phy_device *phy_attach(struct net_device *dev,
/* Search the list of PHY devices on the mdio bus for the
* PHY with the requested name */
- d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
-
+ d = bus_find_device_by_name(bus, NULL, bus_id);
if (d) {
phydev = to_phy_device(d);
} else {
@@ -419,13 +413,14 @@ EXPORT_SYMBOL(phy_detach);
*
* Description: Writes MII_ADVERTISE with the appropriate values,
* after sanitizing the values to make sure we only advertise
- * what is supported.
+ * what is supported. Returns < 0 on error, 0 if the PHY's advertisement
+ * hasn't changed, and > 0 if it has changed.
*/
int genphy_config_advert(struct phy_device *phydev)
{
u32 advertise;
- int adv;
- int err;
+ int oldadv, adv;
+ int err, changed = 0;
/* Only allow advertising what
* this PHY supports */
@@ -433,7 +428,7 @@ int genphy_config_advert(struct phy_device *phydev)
advertise = phydev->advertising;
/* Setup standard advertisement */
- adv = phy_read(phydev, MII_ADVERTISE);
+ oldadv = adv = phy_read(phydev, MII_ADVERTISE);
if (adv < 0)
return adv;
@@ -453,15 +448,18 @@ int genphy_config_advert(struct phy_device *phydev)
if (advertise & ADVERTISED_Asym_Pause)
adv |= ADVERTISE_PAUSE_ASYM;
- err = phy_write(phydev, MII_ADVERTISE, adv);
+ if (adv != oldadv) {
+ err = phy_write(phydev, MII_ADVERTISE, adv);
- if (err < 0)
- return err;
+ if (err < 0)
+ return err;
+ changed = 1;
+ }
/* Configure gigabit if it's supported */
if (phydev->supported & (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full)) {
- adv = phy_read(phydev, MII_CTRL1000);
+ oldadv = adv = phy_read(phydev, MII_CTRL1000);
if (adv < 0)
return adv;
@@ -471,13 +469,17 @@ int genphy_config_advert(struct phy_device *phydev)
adv |= ADVERTISE_1000HALF;
if (advertise & SUPPORTED_1000baseT_Full)
adv |= ADVERTISE_1000FULL;
- err = phy_write(phydev, MII_CTRL1000, adv);
- if (err < 0)
- return err;
+ if (adv != oldadv) {
+ err = phy_write(phydev, MII_CTRL1000, adv);
+
+ if (err < 0)
+ return err;
+ changed = 1;
+ }
}
- return adv;
+ return changed;
}
EXPORT_SYMBOL(genphy_config_advert);
@@ -549,6 +551,7 @@ int genphy_restart_aneg(struct phy_device *phydev)
return ctl;
}
+EXPORT_SYMBOL(genphy_restart_aneg);
/**
@@ -561,19 +564,22 @@ int genphy_restart_aneg(struct phy_device *phydev)
*/
int genphy_config_aneg(struct phy_device *phydev)
{
- int err = 0;
+ int result = 0;
if (AUTONEG_ENABLE == phydev->autoneg) {
- err = genphy_config_advert(phydev);
+ int result = genphy_config_advert(phydev);
- if (err < 0)
- return err;
+ if (result < 0) /* error */
+ return result;
- err = genphy_restart_aneg(phydev);
+ /* Only restart aneg if we are advertising something different
+ * than we were before. */
+ if (result > 0)
+ result = genphy_restart_aneg(phydev);
} else
- err = genphy_setup_forced(phydev);
+ result = genphy_setup_forced(phydev);
- return err;
+ return result;
}
EXPORT_SYMBOL(genphy_config_aneg);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index ddccc074a76..7e857e938ad 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -866,8 +866,8 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
- NULL, "ppp");
+ device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
+ "ppp");
}
out:
@@ -1833,9 +1833,11 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
/* If the queue is getting long, don't wait any longer for packets
before the start of the queue. */
- if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN
- && seq_before(ppp->minseq, ppp->mrq.next->sequence))
- ppp->minseq = ppp->mrq.next->sequence;
+ if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
+ struct sk_buff *skb = skb_peek(&ppp->mrq);
+ if (seq_before(ppp->minseq, skb->sequence))
+ ppp->minseq = skb->sequence;
+ }
/* Pull completed packets off the queue and receive them. */
while ((skb = ppp_mp_reconstruct(ppp)))
@@ -1861,10 +1863,11 @@ ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb)
/* N.B. we don't need to lock the list lock because we have the
ppp unit receive-side lock. */
- for (p = list->next; p != (struct sk_buff *)list; p = p->next)
+ skb_queue_walk(list, p) {
if (seq_before(seq, p->sequence))
break;
- __skb_insert(skb, p->prev, p, list);
+ }
+ __skb_queue_before(list, p, skb);
}
/*
@@ -2124,13 +2127,9 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
|| ccp_option[1] < 2 || ccp_option[1] > data.length)
goto out;
- cp = find_compressor(ccp_option[0]);
-#ifdef CONFIG_KMOD
- if (!cp) {
- request_module("ppp-compress-%d", ccp_option[0]);
- cp = find_compressor(ccp_option[0]);
- }
-#endif /* CONFIG_KMOD */
+ cp = try_then_request_module(
+ find_compressor(ccp_option[0]),
+ "ppp-compress-%d", ccp_option[0]);
if (!cp)
goto out;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index ff175e8f36b..185b1dff10a 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -353,7 +353,7 @@ static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_
spin_lock_bh(&session->reorder_q.lock);
skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
if (PPPOL2TP_SKB_CB(skbp)->ns > ns) {
- __skb_insert(skb, skbp->prev, skbp, &session->reorder_q);
+ __skb_queue_before(&session->reorder_q, skbp, skb);
PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
"%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns,
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index c6898c1fc54..03aecc97fb4 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -115,13 +115,8 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol)
goto out;
rc = -EPROTONOSUPPORT;
-#ifdef CONFIG_KMOD
- if (!pppox_protos[protocol]) {
- char buffer[32];
- sprintf(buffer, "pppox-proto-%d", protocol);
- request_module(buffer);
- }
-#endif
+ if (!pppox_protos[protocol])
+ request_module("pppox-proto-%d", protocol);
if (!pppox_protos[protocol] ||
!try_module_get(pppox_protos[protocol]->owner))
goto out;
diff --git a/drivers/net/qlge/Makefile b/drivers/net/qlge/Makefile
new file mode 100644
index 00000000000..8a197658d76
--- /dev/null
+++ b/drivers/net/qlge/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Qlogic 10GbE PCI Express ethernet driver
+#
+
+obj-$(CONFIG_QLGE) += qlge.o
+
+qlge-objs := qlge_main.o qlge_dbg.o qlge_mpi.o qlge_ethtool.o
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
new file mode 100644
index 00000000000..38116f9d416
--- /dev/null
+++ b/drivers/net/qlge/qlge.h
@@ -0,0 +1,1593 @@
+/*
+ * QLogic QLA41xx NIC HBA Driver
+ * Copyright (c) 2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qlge for copyright and licensing details.
+ */
+#ifndef _QLGE_H_
+#define _QLGE_H_
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+/*
+ * General definitions...
+ */
+#define DRV_NAME "qlge"
+#define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver "
+#define DRV_VERSION "v1.00.00-b3"
+
+#define PFX "qlge: "
+#define QPRINTK(qdev, nlevel, klevel, fmt, args...) \
+ do { \
+ if (!((qdev)->msg_enable & NETIF_MSG_##nlevel)) \
+ ; \
+ else \
+ dev_printk(KERN_##klevel, &((qdev)->pdev->dev), \
+ "%s: " fmt, __func__, ##args); \
+ } while (0)
+
+#define QLGE_VENDOR_ID 0x1077
+#define QLGE_DEVICE_ID1 0x8012
+#define QLGE_DEVICE_ID 0x8000
+
+#define MAX_RX_RINGS 128
+#define MAX_TX_RINGS 128
+
+#define NUM_TX_RING_ENTRIES 256
+#define NUM_RX_RING_ENTRIES 256
+
+#define NUM_SMALL_BUFFERS 512
+#define NUM_LARGE_BUFFERS 512
+
+#define SMALL_BUFFER_SIZE 256
+#define LARGE_BUFFER_SIZE PAGE_SIZE
+#define MAX_SPLIT_SIZE 1023
+#define QLGE_SB_PAD 32
+
+#define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */
+#define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */
+#define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2)
+#define UDELAY_COUNT 3
+#define UDELAY_DELAY 10
+
+
+#define TX_DESC_PER_IOCB 8
+/* The maximum number of frags we handle is based
+ * on PAGE_SIZE...
+ */
+#if (PAGE_SHIFT == 12) || (PAGE_SHIFT == 13) /* 4k & 8k pages */
+#define TX_DESC_PER_OAL ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2)
+#else /* all other page sizes */
+#define TX_DESC_PER_OAL 0
+#endif
+
+#define DB_PAGE_SIZE 4096
+
+/*
+ * Processor Address Register (PROC_ADDR) bit definitions.
+ */
+enum {
+
+ /* Misc. stuff */
+ MAILBOX_COUNT = 16,
+
+ PROC_ADDR_RDY = (1 << 31),
+ PROC_ADDR_R = (1 << 30),
+ PROC_ADDR_ERR = (1 << 29),
+ PROC_ADDR_DA = (1 << 28),
+ PROC_ADDR_FUNC0_MBI = 0x00001180,
+ PROC_ADDR_FUNC0_MBO = (PROC_ADDR_FUNC0_MBI + MAILBOX_COUNT),
+ PROC_ADDR_FUNC0_CTL = 0x000011a1,
+ PROC_ADDR_FUNC2_MBI = 0x00001280,
+ PROC_ADDR_FUNC2_MBO = (PROC_ADDR_FUNC2_MBI + MAILBOX_COUNT),
+ PROC_ADDR_FUNC2_CTL = 0x000012a1,
+ PROC_ADDR_MPI_RISC = 0x00000000,
+ PROC_ADDR_MDE = 0x00010000,
+ PROC_ADDR_REGBLOCK = 0x00020000,
+ PROC_ADDR_RISC_REG = 0x00030000,
+};
+
+/*
+ * System Register (SYS) bit definitions.
+ */
+enum {
+ SYS_EFE = (1 << 0),
+ SYS_FAE = (1 << 1),
+ SYS_MDC = (1 << 2),
+ SYS_DST = (1 << 3),
+ SYS_DWC = (1 << 4),
+ SYS_EVW = (1 << 5),
+ SYS_OMP_DLY_MASK = 0x3f000000,
+ /*
+ * There are no values defined as of edit #15.
+ */
+ SYS_ODI = (1 << 14),
+};
+
+/*
+ * Reset/Failover Register (RST_FO) bit definitions.
+ */
+enum {
+ RST_FO_TFO = (1 << 0),
+ RST_FO_RR_MASK = 0x00060000,
+ RST_FO_RR_CQ_CAM = 0x00000000,
+ RST_FO_RR_DROP = 0x00000001,
+ RST_FO_RR_DQ = 0x00000002,
+ RST_FO_RR_RCV_FUNC_CQ = 0x00000003,
+ RST_FO_FRB = (1 << 12),
+ RST_FO_MOP = (1 << 13),
+ RST_FO_REG = (1 << 14),
+ RST_FO_FR = (1 << 15),
+};
+
+/*
+ * Function Specific Control Register (FSC) bit definitions.
+ */
+enum {
+ FSC_DBRST_MASK = 0x00070000,
+ FSC_DBRST_256 = 0x00000000,
+ FSC_DBRST_512 = 0x00000001,
+ FSC_DBRST_768 = 0x00000002,
+ FSC_DBRST_1024 = 0x00000003,
+ FSC_DBL_MASK = 0x00180000,
+ FSC_DBL_DBRST = 0x00000000,
+ FSC_DBL_MAX_PLD = 0x00000008,
+ FSC_DBL_MAX_BRST = 0x00000010,
+ FSC_DBL_128_BYTES = 0x00000018,
+ FSC_EC = (1 << 5),
+ FSC_EPC_MASK = 0x00c00000,
+ FSC_EPC_INBOUND = (1 << 6),
+ FSC_EPC_OUTBOUND = (1 << 7),
+ FSC_VM_PAGESIZE_MASK = 0x07000000,
+ FSC_VM_PAGE_2K = 0x00000100,
+ FSC_VM_PAGE_4K = 0x00000200,
+ FSC_VM_PAGE_8K = 0x00000300,
+ FSC_VM_PAGE_64K = 0x00000600,
+ FSC_SH = (1 << 11),
+ FSC_DSB = (1 << 12),
+ FSC_STE = (1 << 13),
+ FSC_FE = (1 << 15),
+};
+
+/*
+ * Host Command Status Register (CSR) bit definitions.
+ */
+enum {
+ CSR_ERR_STS_MASK = 0x0000003f,
+ /*
+ * There are no valued defined as of edit #15.
+ */
+ CSR_RR = (1 << 8),
+ CSR_HRI = (1 << 9),
+ CSR_RP = (1 << 10),
+ CSR_CMD_PARM_SHIFT = 22,
+ CSR_CMD_NOP = 0x00000000,
+ CSR_CMD_SET_RST = 0x1000000,
+ CSR_CMD_CLR_RST = 0x20000000,
+ CSR_CMD_SET_PAUSE = 0x30000000,
+ CSR_CMD_CLR_PAUSE = 0x40000000,
+ CSR_CMD_SET_H2R_INT = 0x50000000,
+ CSR_CMD_CLR_H2R_INT = 0x60000000,
+ CSR_CMD_PAR_EN = 0x70000000,
+ CSR_CMD_SET_BAD_PAR = 0x80000000,
+ CSR_CMD_CLR_BAD_PAR = 0x90000000,
+ CSR_CMD_CLR_R2PCI_INT = 0xa0000000,
+};
+
+/*
+ * Configuration Register (CFG) bit definitions.
+ */
+enum {
+ CFG_LRQ = (1 << 0),
+ CFG_DRQ = (1 << 1),
+ CFG_LR = (1 << 2),
+ CFG_DR = (1 << 3),
+ CFG_LE = (1 << 5),
+ CFG_LCQ = (1 << 6),
+ CFG_DCQ = (1 << 7),
+ CFG_Q_SHIFT = 8,
+ CFG_Q_MASK = 0x7f000000,
+};
+
+/*
+ * Status Register (STS) bit definitions.
+ */
+enum {
+ STS_FE = (1 << 0),
+ STS_PI = (1 << 1),
+ STS_PL0 = (1 << 2),
+ STS_PL1 = (1 << 3),
+ STS_PI0 = (1 << 4),
+ STS_PI1 = (1 << 5),
+ STS_FUNC_ID_MASK = 0x000000c0,
+ STS_FUNC_ID_SHIFT = 6,
+ STS_F0E = (1 << 8),
+ STS_F1E = (1 << 9),
+ STS_F2E = (1 << 10),
+ STS_F3E = (1 << 11),
+ STS_NFE = (1 << 12),
+};
+
+/*
+ * Interrupt Enable Register (INTR_EN) bit definitions.
+ */
+enum {
+ INTR_EN_INTR_MASK = 0x007f0000,
+ INTR_EN_TYPE_MASK = 0x03000000,
+ INTR_EN_TYPE_ENABLE = 0x00000100,
+ INTR_EN_TYPE_DISABLE = 0x00000200,
+ INTR_EN_TYPE_READ = 0x00000300,
+ INTR_EN_IHD = (1 << 13),
+ INTR_EN_IHD_MASK = (INTR_EN_IHD << 16),
+ INTR_EN_EI = (1 << 14),
+ INTR_EN_EN = (1 << 15),
+};
+
+/*
+ * Interrupt Mask Register (INTR_MASK) bit definitions.
+ */
+enum {
+ INTR_MASK_PI = (1 << 0),
+ INTR_MASK_HL0 = (1 << 1),
+ INTR_MASK_LH0 = (1 << 2),
+ INTR_MASK_HL1 = (1 << 3),
+ INTR_MASK_LH1 = (1 << 4),
+ INTR_MASK_SE = (1 << 5),
+ INTR_MASK_LSC = (1 << 6),
+ INTR_MASK_MC = (1 << 7),
+ INTR_MASK_LINK_IRQS = INTR_MASK_LSC | INTR_MASK_SE | INTR_MASK_MC,
+};
+
+/*
+ * Register (REV_ID) bit definitions.
+ */
+enum {
+ REV_ID_MASK = 0x0000000f,
+ REV_ID_NICROLL_SHIFT = 0,
+ REV_ID_NICREV_SHIFT = 4,
+ REV_ID_XGROLL_SHIFT = 8,
+ REV_ID_XGREV_SHIFT = 12,
+ REV_ID_CHIPREV_SHIFT = 28,
+};
+
+/*
+ * Force ECC Error Register (FRC_ECC_ERR) bit definitions.
+ */
+enum {
+ FRC_ECC_ERR_VW = (1 << 12),
+ FRC_ECC_ERR_VB = (1 << 13),
+ FRC_ECC_ERR_NI = (1 << 14),
+ FRC_ECC_ERR_NO = (1 << 15),
+ FRC_ECC_PFE_SHIFT = 16,
+ FRC_ECC_ERR_DO = (1 << 18),
+ FRC_ECC_P14 = (1 << 19),
+};
+
+/*
+ * Error Status Register (ERR_STS) bit definitions.
+ */
+enum {
+ ERR_STS_NOF = (1 << 0),
+ ERR_STS_NIF = (1 << 1),
+ ERR_STS_DRP = (1 << 2),
+ ERR_STS_XGP = (1 << 3),
+ ERR_STS_FOU = (1 << 4),
+ ERR_STS_FOC = (1 << 5),
+ ERR_STS_FOF = (1 << 6),
+ ERR_STS_FIU = (1 << 7),
+ ERR_STS_FIC = (1 << 8),
+ ERR_STS_FIF = (1 << 9),
+ ERR_STS_MOF = (1 << 10),
+ ERR_STS_TA = (1 << 11),
+ ERR_STS_MA = (1 << 12),
+ ERR_STS_MPE = (1 << 13),
+ ERR_STS_SCE = (1 << 14),
+ ERR_STS_STE = (1 << 15),
+ ERR_STS_FOW = (1 << 16),
+ ERR_STS_UE = (1 << 17),
+ ERR_STS_MCH = (1 << 26),
+ ERR_STS_LOC_SHIFT = 27,
+};
+
+/*
+ * RAM Debug Address Register (RAM_DBG_ADDR) bit definitions.
+ */
+enum {
+ RAM_DBG_ADDR_FW = (1 << 30),
+ RAM_DBG_ADDR_FR = (1 << 31),
+};
+
+/*
+ * Semaphore Register (SEM) bit definitions.
+ */
+enum {
+ /*
+ * Example:
+ * reg = SEM_XGMAC0_MASK | (SEM_SET << SEM_XGMAC0_SHIFT)
+ */
+ SEM_CLEAR = 0,
+ SEM_SET = 1,
+ SEM_FORCE = 3,
+ SEM_XGMAC0_SHIFT = 0,
+ SEM_XGMAC1_SHIFT = 2,
+ SEM_ICB_SHIFT = 4,
+ SEM_MAC_ADDR_SHIFT = 6,
+ SEM_FLASH_SHIFT = 8,
+ SEM_PROBE_SHIFT = 10,
+ SEM_RT_IDX_SHIFT = 12,
+ SEM_PROC_REG_SHIFT = 14,
+ SEM_XGMAC0_MASK = 0x00030000,
+ SEM_XGMAC1_MASK = 0x000c0000,
+ SEM_ICB_MASK = 0x00300000,
+ SEM_MAC_ADDR_MASK = 0x00c00000,
+ SEM_FLASH_MASK = 0x03000000,
+ SEM_PROBE_MASK = 0x0c000000,
+ SEM_RT_IDX_MASK = 0x30000000,
+ SEM_PROC_REG_MASK = 0xc0000000,
+};
+
+/*
+ * 10G MAC Address Register (XGMAC_ADDR) bit definitions.
+ */
+enum {
+ XGMAC_ADDR_RDY = (1 << 31),
+ XGMAC_ADDR_R = (1 << 30),
+ XGMAC_ADDR_XME = (1 << 29),
+
+ /* XGMAC control registers */
+ PAUSE_SRC_LO = 0x00000100,
+ PAUSE_SRC_HI = 0x00000104,
+ GLOBAL_CFG = 0x00000108,
+ GLOBAL_CFG_RESET = (1 << 0),
+ GLOBAL_CFG_JUMBO = (1 << 6),
+ GLOBAL_CFG_TX_STAT_EN = (1 << 10),
+ GLOBAL_CFG_RX_STAT_EN = (1 << 11),
+ TX_CFG = 0x0000010c,
+ TX_CFG_RESET = (1 << 0),
+ TX_CFG_EN = (1 << 1),
+ TX_CFG_PREAM = (1 << 2),
+ RX_CFG = 0x00000110,
+ RX_CFG_RESET = (1 << 0),
+ RX_CFG_EN = (1 << 1),
+ RX_CFG_PREAM = (1 << 2),
+ FLOW_CTL = 0x0000011c,
+ PAUSE_OPCODE = 0x00000120,
+ PAUSE_TIMER = 0x00000124,
+ PAUSE_FRM_DEST_LO = 0x00000128,
+ PAUSE_FRM_DEST_HI = 0x0000012c,
+ MAC_TX_PARAMS = 0x00000134,
+ MAC_TX_PARAMS_JUMBO = (1 << 31),
+ MAC_TX_PARAMS_SIZE_SHIFT = 16,
+ MAC_RX_PARAMS = 0x00000138,
+ MAC_SYS_INT = 0x00000144,
+ MAC_SYS_INT_MASK = 0x00000148,
+ MAC_MGMT_INT = 0x0000014c,
+ MAC_MGMT_IN_MASK = 0x00000150,
+ EXT_ARB_MODE = 0x000001fc,
+
+ /* XGMAC TX statistics registers */
+ TX_PKTS = 0x00000200,
+ TX_BYTES = 0x00000208,
+ TX_MCAST_PKTS = 0x00000210,
+ TX_BCAST_PKTS = 0x00000218,
+ TX_UCAST_PKTS = 0x00000220,
+ TX_CTL_PKTS = 0x00000228,
+ TX_PAUSE_PKTS = 0x00000230,
+ TX_64_PKT = 0x00000238,
+ TX_65_TO_127_PKT = 0x00000240,
+ TX_128_TO_255_PKT = 0x00000248,
+ TX_256_511_PKT = 0x00000250,
+ TX_512_TO_1023_PKT = 0x00000258,
+ TX_1024_TO_1518_PKT = 0x00000260,
+ TX_1519_TO_MAX_PKT = 0x00000268,
+ TX_UNDERSIZE_PKT = 0x00000270,
+ TX_OVERSIZE_PKT = 0x00000278,
+
+ /* XGMAC statistics control registers */
+ RX_HALF_FULL_DET = 0x000002a0,
+ TX_HALF_FULL_DET = 0x000002a4,
+ RX_OVERFLOW_DET = 0x000002a8,
+ TX_OVERFLOW_DET = 0x000002ac,
+ RX_HALF_FULL_MASK = 0x000002b0,
+ TX_HALF_FULL_MASK = 0x000002b4,
+ RX_OVERFLOW_MASK = 0x000002b8,
+ TX_OVERFLOW_MASK = 0x000002bc,
+ STAT_CNT_CTL = 0x000002c0,
+ STAT_CNT_CTL_CLEAR_TX = (1 << 0),
+ STAT_CNT_CTL_CLEAR_RX = (1 << 1),
+ AUX_RX_HALF_FULL_DET = 0x000002d0,
+ AUX_TX_HALF_FULL_DET = 0x000002d4,
+ AUX_RX_OVERFLOW_DET = 0x000002d8,
+ AUX_TX_OVERFLOW_DET = 0x000002dc,
+ AUX_RX_HALF_FULL_MASK = 0x000002f0,
+ AUX_TX_HALF_FULL_MASK = 0x000002f4,
+ AUX_RX_OVERFLOW_MASK = 0x000002f8,
+ AUX_TX_OVERFLOW_MASK = 0x000002fc,
+
+ /* XGMAC RX statistics registers */
+ RX_BYTES = 0x00000300,
+ RX_BYTES_OK = 0x00000308,
+ RX_PKTS = 0x00000310,
+ RX_PKTS_OK = 0x00000318,
+ RX_BCAST_PKTS = 0x00000320,
+ RX_MCAST_PKTS = 0x00000328,
+ RX_UCAST_PKTS = 0x00000330,
+ RX_UNDERSIZE_PKTS = 0x00000338,
+ RX_OVERSIZE_PKTS = 0x00000340,
+ RX_JABBER_PKTS = 0x00000348,
+ RX_UNDERSIZE_FCERR_PKTS = 0x00000350,
+ RX_DROP_EVENTS = 0x00000358,
+ RX_FCERR_PKTS = 0x00000360,
+ RX_ALIGN_ERR = 0x00000368,
+ RX_SYMBOL_ERR = 0x00000370,
+ RX_MAC_ERR = 0x00000378,
+ RX_CTL_PKTS = 0x00000380,
+ RX_PAUSE_PKTS = 0x00000384,
+ RX_64_PKTS = 0x00000390,
+ RX_65_TO_127_PKTS = 0x00000398,
+ RX_128_255_PKTS = 0x000003a0,
+ RX_256_511_PKTS = 0x000003a8,
+ RX_512_TO_1023_PKTS = 0x000003b0,
+ RX_1024_TO_1518_PKTS = 0x000003b8,
+ RX_1519_TO_MAX_PKTS = 0x000003c0,
+ RX_LEN_ERR_PKTS = 0x000003c8,
+
+ /* XGMAC MDIO control registers */
+ MDIO_TX_DATA = 0x00000400,
+ MDIO_RX_DATA = 0x00000410,
+ MDIO_CMD = 0x00000420,
+ MDIO_PHY_ADDR = 0x00000430,
+ MDIO_PORT = 0x00000440,
+ MDIO_STATUS = 0x00000450,
+
+ /* XGMAC AUX statistics registers */
+};
+
+/*
+ * Enhanced Transmission Schedule Registers (NIC_ETS,CNA_ETS) bit definitions.
+ */
+enum {
+ ETS_QUEUE_SHIFT = 29,
+ ETS_REF = (1 << 26),
+ ETS_RS = (1 << 27),
+ ETS_P = (1 << 28),
+ ETS_FC_COS_SHIFT = 23,
+};
+
+/*
+ * Flash Address Register (FLASH_ADDR) bit definitions.
+ */
+enum {
+ FLASH_ADDR_RDY = (1 << 31),
+ FLASH_ADDR_R = (1 << 30),
+ FLASH_ADDR_ERR = (1 << 29),
+};
+
+/*
+ * Stop CQ Processing Register (CQ_STOP) bit definitions.
+ */
+enum {
+ CQ_STOP_QUEUE_MASK = (0x007f0000),
+ CQ_STOP_TYPE_MASK = (0x03000000),
+ CQ_STOP_TYPE_START = 0x00000100,
+ CQ_STOP_TYPE_STOP = 0x00000200,
+ CQ_STOP_TYPE_READ = 0x00000300,
+ CQ_STOP_EN = (1 << 15),
+};
+
+/*
+ * MAC Protocol Address Index Register (MAC_ADDR_IDX) bit definitions.
+ */
+enum {
+ MAC_ADDR_IDX_SHIFT = 4,
+ MAC_ADDR_TYPE_SHIFT = 16,
+ MAC_ADDR_TYPE_MASK = 0x000f0000,
+ MAC_ADDR_TYPE_CAM_MAC = 0x00000000,
+ MAC_ADDR_TYPE_MULTI_MAC = 0x00010000,
+ MAC_ADDR_TYPE_VLAN = 0x00020000,
+ MAC_ADDR_TYPE_MULTI_FLTR = 0x00030000,
+ MAC_ADDR_TYPE_FC_MAC = 0x00040000,
+ MAC_ADDR_TYPE_MGMT_MAC = 0x00050000,
+ MAC_ADDR_TYPE_MGMT_VLAN = 0x00060000,
+ MAC_ADDR_TYPE_MGMT_V4 = 0x00070000,
+ MAC_ADDR_TYPE_MGMT_V6 = 0x00080000,
+ MAC_ADDR_TYPE_MGMT_TU_DP = 0x00090000,
+ MAC_ADDR_ADR = (1 << 25),
+ MAC_ADDR_RS = (1 << 26),
+ MAC_ADDR_E = (1 << 27),
+ MAC_ADDR_MR = (1 << 30),
+ MAC_ADDR_MW = (1 << 31),
+ MAX_MULTICAST_ENTRIES = 32,
+};
+
+/*
+ * MAC Protocol Address Index Register (SPLT_HDR) bit definitions.
+ */
+enum {
+ SPLT_HDR_EP = (1 << 31),
+};
+
+/*
+ * FCoE Receive Configuration Register (FC_RCV_CFG) bit definitions.
+ */
+enum {
+ FC_RCV_CFG_ECT = (1 << 15),
+ FC_RCV_CFG_DFH = (1 << 20),
+ FC_RCV_CFG_DVF = (1 << 21),
+ FC_RCV_CFG_RCE = (1 << 27),
+ FC_RCV_CFG_RFE = (1 << 28),
+ FC_RCV_CFG_TEE = (1 << 29),
+ FC_RCV_CFG_TCE = (1 << 30),
+ FC_RCV_CFG_TFE = (1 << 31),
+};
+
+/*
+ * NIC Receive Configuration Register (NIC_RCV_CFG) bit definitions.
+ */
+enum {
+ NIC_RCV_CFG_PPE = (1 << 0),
+ NIC_RCV_CFG_VLAN_MASK = 0x00060000,
+ NIC_RCV_CFG_VLAN_ALL = 0x00000000,
+ NIC_RCV_CFG_VLAN_MATCH_ONLY = 0x00000002,
+ NIC_RCV_CFG_VLAN_MATCH_AND_NON = 0x00000004,
+ NIC_RCV_CFG_VLAN_NONE_AND_NON = 0x00000006,
+ NIC_RCV_CFG_RV = (1 << 3),
+ NIC_RCV_CFG_DFQ_MASK = (0x7f000000),
+ NIC_RCV_CFG_DFQ_SHIFT = 8,
+ NIC_RCV_CFG_DFQ = 0, /* HARDCODE default queue to 0. */
+};
+
+/*
+ * Mgmt Receive Configuration Register (MGMT_RCV_CFG) bit definitions.
+ */
+enum {
+ MGMT_RCV_CFG_ARP = (1 << 0),
+ MGMT_RCV_CFG_DHC = (1 << 1),
+ MGMT_RCV_CFG_DHS = (1 << 2),
+ MGMT_RCV_CFG_NP = (1 << 3),
+ MGMT_RCV_CFG_I6N = (1 << 4),
+ MGMT_RCV_CFG_I6R = (1 << 5),
+ MGMT_RCV_CFG_DH6 = (1 << 6),
+ MGMT_RCV_CFG_UD1 = (1 << 7),
+ MGMT_RCV_CFG_UD0 = (1 << 8),
+ MGMT_RCV_CFG_BCT = (1 << 9),
+ MGMT_RCV_CFG_MCT = (1 << 10),
+ MGMT_RCV_CFG_DM = (1 << 11),
+ MGMT_RCV_CFG_RM = (1 << 12),
+ MGMT_RCV_CFG_STL = (1 << 13),
+ MGMT_RCV_CFG_VLAN_MASK = 0xc0000000,
+ MGMT_RCV_CFG_VLAN_ALL = 0x00000000,
+ MGMT_RCV_CFG_VLAN_MATCH_ONLY = 0x00004000,
+ MGMT_RCV_CFG_VLAN_MATCH_AND_NON = 0x00008000,
+ MGMT_RCV_CFG_VLAN_NONE_AND_NON = 0x0000c000,
+};
+
+/*
+ * Routing Index Register (RT_IDX) bit definitions.
+ */
+enum {
+ RT_IDX_IDX_SHIFT = 8,
+ RT_IDX_TYPE_MASK = 0x000f0000,
+ RT_IDX_TYPE_RT = 0x00000000,
+ RT_IDX_TYPE_RT_INV = 0x00010000,
+ RT_IDX_TYPE_NICQ = 0x00020000,
+ RT_IDX_TYPE_NICQ_INV = 0x00030000,
+ RT_IDX_DST_MASK = 0x00700000,
+ RT_IDX_DST_RSS = 0x00000000,
+ RT_IDX_DST_CAM_Q = 0x00100000,
+ RT_IDX_DST_COS_Q = 0x00200000,
+ RT_IDX_DST_DFLT_Q = 0x00300000,
+ RT_IDX_DST_DEST_Q = 0x00400000,
+ RT_IDX_RS = (1 << 26),
+ RT_IDX_E = (1 << 27),
+ RT_IDX_MR = (1 << 30),
+ RT_IDX_MW = (1 << 31),
+
+ /* Nic Queue format - type 2 bits */
+ RT_IDX_BCAST = (1 << 0),
+ RT_IDX_MCAST = (1 << 1),
+ RT_IDX_MCAST_MATCH = (1 << 2),
+ RT_IDX_MCAST_REG_MATCH = (1 << 3),
+ RT_IDX_MCAST_HASH_MATCH = (1 << 4),
+ RT_IDX_FC_MACH = (1 << 5),
+ RT_IDX_ETH_FCOE = (1 << 6),
+ RT_IDX_CAM_HIT = (1 << 7),
+ RT_IDX_CAM_BIT0 = (1 << 8),
+ RT_IDX_CAM_BIT1 = (1 << 9),
+ RT_IDX_VLAN_TAG = (1 << 10),
+ RT_IDX_VLAN_MATCH = (1 << 11),
+ RT_IDX_VLAN_FILTER = (1 << 12),
+ RT_IDX_ETH_SKIP1 = (1 << 13),
+ RT_IDX_ETH_SKIP2 = (1 << 14),
+ RT_IDX_BCAST_MCAST_MATCH = (1 << 15),
+ RT_IDX_802_3 = (1 << 16),
+ RT_IDX_LLDP = (1 << 17),
+ RT_IDX_UNUSED018 = (1 << 18),
+ RT_IDX_UNUSED019 = (1 << 19),
+ RT_IDX_UNUSED20 = (1 << 20),
+ RT_IDX_UNUSED21 = (1 << 21),
+ RT_IDX_ERR = (1 << 22),
+ RT_IDX_VALID = (1 << 23),
+ RT_IDX_TU_CSUM_ERR = (1 << 24),
+ RT_IDX_IP_CSUM_ERR = (1 << 25),
+ RT_IDX_MAC_ERR = (1 << 26),
+ RT_IDX_RSS_TCP6 = (1 << 27),
+ RT_IDX_RSS_TCP4 = (1 << 28),
+ RT_IDX_RSS_IPV6 = (1 << 29),
+ RT_IDX_RSS_IPV4 = (1 << 30),
+ RT_IDX_RSS_MATCH = (1 << 31),
+
+ /* Hierarchy for the NIC Queue Mask */
+ RT_IDX_ALL_ERR_SLOT = 0,
+ RT_IDX_MAC_ERR_SLOT = 0,
+ RT_IDX_IP_CSUM_ERR_SLOT = 1,
+ RT_IDX_TCP_UDP_CSUM_ERR_SLOT = 2,
+ RT_IDX_BCAST_SLOT = 3,
+ RT_IDX_MCAST_MATCH_SLOT = 4,
+ RT_IDX_ALLMULTI_SLOT = 5,
+ RT_IDX_UNUSED6_SLOT = 6,
+ RT_IDX_UNUSED7_SLOT = 7,
+ RT_IDX_RSS_MATCH_SLOT = 8,
+ RT_IDX_RSS_IPV4_SLOT = 8,
+ RT_IDX_RSS_IPV6_SLOT = 9,
+ RT_IDX_RSS_TCP4_SLOT = 10,
+ RT_IDX_RSS_TCP6_SLOT = 11,
+ RT_IDX_CAM_HIT_SLOT = 12,
+ RT_IDX_UNUSED013 = 13,
+ RT_IDX_UNUSED014 = 14,
+ RT_IDX_PROMISCUOUS_SLOT = 15,
+ RT_IDX_MAX_SLOTS = 16,
+};
+
+/*
+ * Control Register Set Map
+ */
+enum {
+ PROC_ADDR = 0, /* Use semaphore */
+ PROC_DATA = 0x04, /* Use semaphore */
+ SYS = 0x08,
+ RST_FO = 0x0c,
+ FSC = 0x10,
+ CSR = 0x14,
+ LED = 0x18,
+ ICB_RID = 0x1c, /* Use semaphore */
+ ICB_L = 0x20, /* Use semaphore */
+ ICB_H = 0x24, /* Use semaphore */
+ CFG = 0x28,
+ BIOS_ADDR = 0x2c,
+ STS = 0x30,
+ INTR_EN = 0x34,
+ INTR_MASK = 0x38,
+ ISR1 = 0x3c,
+ ISR2 = 0x40,
+ ISR3 = 0x44,
+ ISR4 = 0x48,
+ REV_ID = 0x4c,
+ FRC_ECC_ERR = 0x50,
+ ERR_STS = 0x54,
+ RAM_DBG_ADDR = 0x58,
+ RAM_DBG_DATA = 0x5c,
+ ECC_ERR_CNT = 0x60,
+ SEM = 0x64,
+ GPIO_1 = 0x68, /* Use semaphore */
+ GPIO_2 = 0x6c, /* Use semaphore */
+ GPIO_3 = 0x70, /* Use semaphore */
+ RSVD2 = 0x74,
+ XGMAC_ADDR = 0x78, /* Use semaphore */
+ XGMAC_DATA = 0x7c, /* Use semaphore */
+ NIC_ETS = 0x80,
+ CNA_ETS = 0x84,
+ FLASH_ADDR = 0x88, /* Use semaphore */
+ FLASH_DATA = 0x8c, /* Use semaphore */
+ CQ_STOP = 0x90,
+ PAGE_TBL_RID = 0x94,
+ WQ_PAGE_TBL_LO = 0x98,
+ WQ_PAGE_TBL_HI = 0x9c,
+ CQ_PAGE_TBL_LO = 0xa0,
+ CQ_PAGE_TBL_HI = 0xa4,
+ MAC_ADDR_IDX = 0xa8, /* Use semaphore */
+ MAC_ADDR_DATA = 0xac, /* Use semaphore */
+ COS_DFLT_CQ1 = 0xb0,
+ COS_DFLT_CQ2 = 0xb4,
+ ETYPE_SKIP1 = 0xb8,
+ ETYPE_SKIP2 = 0xbc,
+ SPLT_HDR = 0xc0,
+ FC_PAUSE_THRES = 0xc4,
+ NIC_PAUSE_THRES = 0xc8,
+ FC_ETHERTYPE = 0xcc,
+ FC_RCV_CFG = 0xd0,
+ NIC_RCV_CFG = 0xd4,
+ FC_COS_TAGS = 0xd8,
+ NIC_COS_TAGS = 0xdc,
+ MGMT_RCV_CFG = 0xe0,
+ RT_IDX = 0xe4,
+ RT_DATA = 0xe8,
+ RSVD7 = 0xec,
+ XG_SERDES_ADDR = 0xf0,
+ XG_SERDES_DATA = 0xf4,
+ PRB_MX_ADDR = 0xf8, /* Use semaphore */
+ PRB_MX_DATA = 0xfc, /* Use semaphore */
+};
+
+/*
+ * CAM output format.
+ */
+enum {
+ CAM_OUT_ROUTE_FC = 0,
+ CAM_OUT_ROUTE_NIC = 1,
+ CAM_OUT_FUNC_SHIFT = 2,
+ CAM_OUT_RV = (1 << 4),
+ CAM_OUT_SH = (1 << 15),
+ CAM_OUT_CQ_ID_SHIFT = 5,
+};
+
+/*
+ * Mailbox definitions
+ */
+enum {
+ /* Asynchronous Event Notifications */
+ AEN_SYS_ERR = 0x00008002,
+ AEN_LINK_UP = 0x00008011,
+ AEN_LINK_DOWN = 0x00008012,
+ AEN_IDC_CMPLT = 0x00008100,
+ AEN_IDC_REQ = 0x00008101,
+ AEN_FW_INIT_DONE = 0x00008400,
+ AEN_FW_INIT_FAIL = 0x00008401,
+
+ /* Mailbox Command Opcodes. */
+ MB_CMD_NOP = 0x00000000,
+ MB_CMD_EX_FW = 0x00000002,
+ MB_CMD_MB_TEST = 0x00000006,
+ MB_CMD_CSUM_TEST = 0x00000007, /* Verify Checksum */
+ MB_CMD_ABOUT_FW = 0x00000008,
+ MB_CMD_LOAD_RISC_RAM = 0x0000000b,
+ MB_CMD_DUMP_RISC_RAM = 0x0000000c,
+ MB_CMD_WRITE_RAM = 0x0000000d,
+ MB_CMD_READ_RAM = 0x0000000f,
+ MB_CMD_STOP_FW = 0x00000014,
+ MB_CMD_MAKE_SYS_ERR = 0x0000002a,
+ MB_CMD_INIT_FW = 0x00000060,
+ MB_CMD_GET_INIT_CB = 0x00000061,
+ MB_CMD_GET_FW_STATE = 0x00000069,
+ MB_CMD_IDC_REQ = 0x00000100, /* Inter-Driver Communication */
+ MB_CMD_IDC_ACK = 0x00000101, /* Inter-Driver Communication */
+ MB_CMD_SET_WOL_MODE = 0x00000110, /* Wake On Lan */
+ MB_WOL_DISABLE = 0x00000000,
+ MB_WOL_MAGIC_PKT = 0x00000001,
+ MB_WOL_FLTR = 0x00000002,
+ MB_WOL_UCAST = 0x00000004,
+ MB_WOL_MCAST = 0x00000008,
+ MB_WOL_BCAST = 0x00000010,
+ MB_WOL_LINK_UP = 0x00000020,
+ MB_WOL_LINK_DOWN = 0x00000040,
+ MB_CMD_SET_WOL_FLTR = 0x00000111, /* Wake On Lan Filter */
+ MB_CMD_CLEAR_WOL_FLTR = 0x00000112, /* Wake On Lan Filter */
+ MB_CMD_SET_WOL_MAGIC = 0x00000113, /* Wake On Lan Magic Packet */
+ MB_CMD_CLEAR_WOL_MAGIC = 0x00000114, /* Wake On Lan Magic Packet */
+ MB_CMD_PORT_RESET = 0x00000120,
+ MB_CMD_SET_PORT_CFG = 0x00000122,
+ MB_CMD_GET_PORT_CFG = 0x00000123,
+ MB_CMD_SET_ASIC_VOLTS = 0x00000130,
+ MB_CMD_GET_SNS_DATA = 0x00000131, /* Temp and Volt Sense data. */
+
+ /* Mailbox Command Status. */
+ MB_CMD_STS_GOOD = 0x00004000, /* Success. */
+ MB_CMD_STS_INTRMDT = 0x00001000, /* Intermediate Complete. */
+ MB_CMD_STS_ERR = 0x00004005, /* Error. */
+};
+
+struct mbox_params {
+ u32 mbox_in[MAILBOX_COUNT];
+ u32 mbox_out[MAILBOX_COUNT];
+ int in_count;
+ int out_count;
+};
+
+struct flash_params {
+ u8 dev_id_str[4];
+ u16 size;
+ u16 csum;
+ u16 ver;
+ u16 sub_dev_id;
+ u8 mac_addr[6];
+ u16 res;
+};
+
+
+/*
+ * doorbell space for the rx ring context
+ */
+struct rx_doorbell_context {
+ u32 cnsmr_idx; /* 0x00 */
+ u32 valid; /* 0x04 */
+ u32 reserved[4]; /* 0x08-0x14 */
+ u32 lbq_prod_idx; /* 0x18 */
+ u32 sbq_prod_idx; /* 0x1c */
+};
+
+/*
+ * doorbell space for the tx ring context
+ */
+struct tx_doorbell_context {
+ u32 prod_idx; /* 0x00 */
+ u32 valid; /* 0x04 */
+ u32 reserved[4]; /* 0x08-0x14 */
+ u32 lbq_prod_idx; /* 0x18 */
+ u32 sbq_prod_idx; /* 0x1c */
+};
+
+/* DATA STRUCTURES SHARED WITH HARDWARE. */
+
+struct bq_element {
+ u32 addr_lo;
+#define BQ_END 0x00000001
+#define BQ_CONT 0x00000002
+#define BQ_MASK 0x00000003
+ u32 addr_hi;
+} __attribute((packed));
+
+struct tx_buf_desc {
+ __le64 addr;
+ __le32 len;
+#define TX_DESC_LEN_MASK 0x000fffff
+#define TX_DESC_C 0x40000000
+#define TX_DESC_E 0x80000000
+} __attribute((packed));
+
+/*
+ * IOCB Definitions...
+ */
+
+#define OPCODE_OB_MAC_IOCB 0x01
+#define OPCODE_OB_MAC_TSO_IOCB 0x02
+#define OPCODE_IB_MAC_IOCB 0x20
+#define OPCODE_IB_MPI_IOCB 0x21
+#define OPCODE_IB_AE_IOCB 0x3f
+
+struct ob_mac_iocb_req {
+ u8 opcode;
+ u8 flags1;
+#define OB_MAC_IOCB_REQ_OI 0x01
+#define OB_MAC_IOCB_REQ_I 0x02
+#define OB_MAC_IOCB_REQ_D 0x08
+#define OB_MAC_IOCB_REQ_F 0x10
+ u8 flags2;
+ u8 flags3;
+#define OB_MAC_IOCB_DFP 0x02
+#define OB_MAC_IOCB_V 0x04
+ __le32 reserved1[2];
+ __le16 frame_len;
+#define OB_MAC_IOCB_LEN_MASK 0x3ffff
+ __le16 reserved2;
+ __le32 tid;
+ __le32 txq_idx;
+ __le32 reserved3;
+ __le16 vlan_tci;
+ __le16 reserved4;
+ struct tx_buf_desc tbd[TX_DESC_PER_IOCB];
+} __attribute((packed));
+
+struct ob_mac_iocb_rsp {
+ u8 opcode; /* */
+ u8 flags1; /* */
+#define OB_MAC_IOCB_RSP_OI 0x01 /* */
+#define OB_MAC_IOCB_RSP_I 0x02 /* */
+#define OB_MAC_IOCB_RSP_E 0x08 /* */
+#define OB_MAC_IOCB_RSP_S 0x10 /* too Short */
+#define OB_MAC_IOCB_RSP_L 0x20 /* too Large */
+#define OB_MAC_IOCB_RSP_P 0x40 /* Padded */
+ u8 flags2; /* */
+ u8 flags3; /* */
+#define OB_MAC_IOCB_RSP_B 0x80 /* */
+ __le32 tid;
+ __le32 txq_idx;
+ __le32 reserved[13];
+} __attribute((packed));
+
+struct ob_mac_tso_iocb_req {
+ u8 opcode;
+ u8 flags1;
+#define OB_MAC_TSO_IOCB_OI 0x01
+#define OB_MAC_TSO_IOCB_I 0x02
+#define OB_MAC_TSO_IOCB_D 0x08
+#define OB_MAC_TSO_IOCB_IP4 0x40
+#define OB_MAC_TSO_IOCB_IP6 0x80
+ u8 flags2;
+#define OB_MAC_TSO_IOCB_LSO 0x20
+#define OB_MAC_TSO_IOCB_UC 0x40
+#define OB_MAC_TSO_IOCB_TC 0x80
+ u8 flags3;
+#define OB_MAC_TSO_IOCB_IC 0x01
+#define OB_MAC_TSO_IOCB_DFP 0x02
+#define OB_MAC_TSO_IOCB_V 0x04
+ __le32 reserved1[2];
+ __le32 frame_len;
+ __le32 tid;
+ __le32 txq_idx;
+ __le16 total_hdrs_len;
+ __le16 net_trans_offset;
+#define OB_MAC_TRANSPORT_HDR_SHIFT 6
+ __le16 vlan_tci;
+ __le16 mss;
+ struct tx_buf_desc tbd[TX_DESC_PER_IOCB];
+} __attribute((packed));
+
+struct ob_mac_tso_iocb_rsp {
+ u8 opcode;
+ u8 flags1;
+#define OB_MAC_TSO_IOCB_RSP_OI 0x01
+#define OB_MAC_TSO_IOCB_RSP_I 0x02
+#define OB_MAC_TSO_IOCB_RSP_E 0x08
+#define OB_MAC_TSO_IOCB_RSP_S 0x10
+#define OB_MAC_TSO_IOCB_RSP_L 0x20
+#define OB_MAC_TSO_IOCB_RSP_P 0x40
+ u8 flags2; /* */
+ u8 flags3; /* */
+#define OB_MAC_TSO_IOCB_RSP_B 0x8000
+ __le32 tid;
+ __le32 txq_idx;
+ __le32 reserved2[13];
+} __attribute((packed));
+
+struct ib_mac_iocb_rsp {
+ u8 opcode; /* 0x20 */
+ u8 flags1;
+#define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */
+#define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */
+#define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */
+#define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */
+#define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */
+#define IB_MAC_IOCB_RSP_M_MASK 0x60 /* Multicast info */
+#define IB_MAC_IOCB_RSP_M_NONE 0x00 /* Not mcast frame */
+#define IB_MAC_IOCB_RSP_M_HASH 0x20 /* HASH mcast frame */
+#define IB_MAC_IOCB_RSP_M_REG 0x40 /* Registered mcast frame */
+#define IB_MAC_IOCB_RSP_M_PROM 0x60 /* Promiscuous mcast frame */
+#define IB_MAC_IOCB_RSP_B 0x80 /* Broadcast frame */
+ u8 flags2;
+#define IB_MAC_IOCB_RSP_P 0x01 /* Promiscuous frame */
+#define IB_MAC_IOCB_RSP_V 0x02 /* Vlan tag present */
+#define IB_MAC_IOCB_RSP_ERR_MASK 0x1c /* */
+#define IB_MAC_IOCB_RSP_ERR_CODE_ERR 0x04
+#define IB_MAC_IOCB_RSP_ERR_OVERSIZE 0x08
+#define IB_MAC_IOCB_RSP_ERR_UNDERSIZE 0x10
+#define IB_MAC_IOCB_RSP_ERR_PREAMBLE 0x14
+#define IB_MAC_IOCB_RSP_ERR_FRAME_LEN 0x18
+#define IB_MAC_IOCB_RSP_ERR_CRC 0x1c
+#define IB_MAC_IOCB_RSP_U 0x20 /* UDP packet */
+#define IB_MAC_IOCB_RSP_T 0x40 /* TCP packet */
+#define IB_MAC_IOCB_RSP_FO 0x80 /* Failover port */
+ u8 flags3;
+#define IB_MAC_IOCB_RSP_RSS_MASK 0x07 /* RSS mask */
+#define IB_MAC_IOCB_RSP_M_NONE 0x00 /* No RSS match */
+#define IB_MAC_IOCB_RSP_M_IPV4 0x04 /* IPv4 RSS match */
+#define IB_MAC_IOCB_RSP_M_IPV6 0x02 /* IPv6 RSS match */
+#define IB_MAC_IOCB_RSP_M_TCP_V4 0x05 /* TCP with IPv4 */
+#define IB_MAC_IOCB_RSP_M_TCP_V6 0x03 /* TCP with IPv6 */
+#define IB_MAC_IOCB_RSP_V4 0x08 /* IPV4 */
+#define IB_MAC_IOCB_RSP_V6 0x10 /* IPV6 */
+#define IB_MAC_IOCB_RSP_IH 0x20 /* Split after IP header */
+#define IB_MAC_IOCB_RSP_DS 0x40 /* data is in small buffer */
+#define IB_MAC_IOCB_RSP_DL 0x80 /* data is in large buffer */
+ __le32 data_len; /* */
+ __le32 data_addr_lo; /* */
+ __le32 data_addr_hi; /* */
+ __le32 rss; /* */
+ __le16 vlan_id; /* 12 bits */
+#define IB_MAC_IOCB_RSP_C 0x1000 /* VLAN CFI bit */
+#define IB_MAC_IOCB_RSP_COS_SHIFT 12 /* class of service value */
+
+ __le16 reserved1;
+ __le32 reserved2[6];
+ __le32 flags4;
+#define IB_MAC_IOCB_RSP_HV 0x20000000 /* */
+#define IB_MAC_IOCB_RSP_HS 0x40000000 /* */
+#define IB_MAC_IOCB_RSP_HL 0x80000000 /* */
+ __le32 hdr_len; /* */
+ __le32 hdr_addr_lo; /* */
+ __le32 hdr_addr_hi; /* */
+} __attribute((packed));
+
+struct ib_ae_iocb_rsp {
+ u8 opcode;
+ u8 flags1;
+#define IB_AE_IOCB_RSP_OI 0x01
+#define IB_AE_IOCB_RSP_I 0x02
+ u8 event;
+#define LINK_UP_EVENT 0x00
+#define LINK_DOWN_EVENT 0x01
+#define CAM_LOOKUP_ERR_EVENT 0x06
+#define SOFT_ECC_ERROR_EVENT 0x07
+#define MGMT_ERR_EVENT 0x08
+#define TEN_GIG_MAC_EVENT 0x09
+#define GPI0_H2L_EVENT 0x10
+#define GPI0_L2H_EVENT 0x20
+#define GPI1_H2L_EVENT 0x11
+#define GPI1_L2H_EVENT 0x21
+#define PCI_ERR_ANON_BUF_RD 0x40
+ u8 q_id;
+ __le32 reserved[15];
+} __attribute((packed));
+
+/*
+ * These three structures are for generic
+ * handling of ib and ob iocbs.
+ */
+struct ql_net_rsp_iocb {
+ u8 opcode;
+ u8 flags0;
+ __le16 length;
+ __le32 tid;
+ __le32 reserved[14];
+} __attribute((packed));
+
+struct net_req_iocb {
+ u8 opcode;
+ u8 flags0;
+ __le16 flags1;
+ __le32 tid;
+ __le32 reserved1[30];
+} __attribute((packed));
+
+/*
+ * tx ring initialization control block for chip.
+ * It is defined as:
+ * "Work Queue Initialization Control Block"
+ */
+struct wqicb {
+ __le16 len;
+#define Q_LEN_V (1 << 4)
+#define Q_LEN_CPP_CONT 0x0000
+#define Q_LEN_CPP_16 0x0001
+#define Q_LEN_CPP_32 0x0002
+#define Q_LEN_CPP_64 0x0003
+ __le16 flags;
+#define Q_PRI_SHIFT 1
+#define Q_FLAGS_LC 0x1000
+#define Q_FLAGS_LB 0x2000
+#define Q_FLAGS_LI 0x4000
+#define Q_FLAGS_LO 0x8000
+ __le16 cq_id_rss;
+#define Q_CQ_ID_RSS_RV 0x8000
+ __le16 rid;
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le32 cnsmr_idx_addr_lo;
+ __le32 cnsmr_idx_addr_hi;
+} __attribute((packed));
+
+/*
+ * rx ring initialization control block for chip.
+ * It is defined as:
+ * "Completion Queue Initialization Control Block"
+ */
+struct cqicb {
+ u8 msix_vect;
+ u8 reserved1;
+ u8 reserved2;
+ u8 flags;
+#define FLAGS_LV 0x08
+#define FLAGS_LS 0x10
+#define FLAGS_LL 0x20
+#define FLAGS_LI 0x40
+#define FLAGS_LC 0x80
+ __le16 len;
+#define LEN_V (1 << 4)
+#define LEN_CPP_CONT 0x0000
+#define LEN_CPP_32 0x0001
+#define LEN_CPP_64 0x0002
+#define LEN_CPP_128 0x0003
+ __le16 rid;
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le32 prod_idx_addr_lo;
+ __le32 prod_idx_addr_hi;
+ __le16 pkt_delay;
+ __le16 irq_delay;
+ __le32 lbq_addr_lo;
+ __le32 lbq_addr_hi;
+ __le16 lbq_buf_size;
+ __le16 lbq_len; /* entry count */
+ __le32 sbq_addr_lo;
+ __le32 sbq_addr_hi;
+ __le16 sbq_buf_size;
+ __le16 sbq_len; /* entry count */
+} __attribute((packed));
+
+struct ricb {
+ u8 base_cq;
+#define RSS_L4K 0x80
+ u8 flags;
+#define RSS_L6K 0x01
+#define RSS_LI 0x02
+#define RSS_LB 0x04
+#define RSS_LM 0x08
+#define RSS_RI4 0x10
+#define RSS_RT4 0x20
+#define RSS_RI6 0x40
+#define RSS_RT6 0x80
+ __le16 mask;
+ __le32 hash_cq_id[256];
+ __le32 ipv6_hash_key[10];
+ __le32 ipv4_hash_key[4];
+} __attribute((packed));
+
+/* SOFTWARE/DRIVER DATA STRUCTURES. */
+
+struct oal {
+ struct tx_buf_desc oal[TX_DESC_PER_OAL];
+};
+
+struct map_list {
+ DECLARE_PCI_UNMAP_ADDR(mapaddr);
+ DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+struct tx_ring_desc {
+ struct sk_buff *skb;
+ struct ob_mac_iocb_req *queue_entry;
+ int index;
+ struct oal oal;
+ struct map_list map[MAX_SKB_FRAGS + 1];
+ int map_cnt;
+ struct tx_ring_desc *next;
+};
+
+struct bq_desc {
+ union {
+ struct page *lbq_page;
+ struct sk_buff *skb;
+ } p;
+ struct bq_element *bq;
+ int index;
+ DECLARE_PCI_UNMAP_ADDR(mapaddr);
+ DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+#define QL_TXQ_IDX(qdev, skb) (smp_processor_id()%(qdev->tx_ring_count))
+
+struct tx_ring {
+ /*
+ * queue info.
+ */
+ struct wqicb wqicb; /* structure used to inform chip of new queue */
+ void *wq_base; /* pci_alloc:virtual addr for tx */
+ dma_addr_t wq_base_dma; /* pci_alloc:dma addr for tx */
+ u32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */
+ dma_addr_t cnsmr_idx_sh_reg_dma; /* dma-shadow copy of consumer */
+ u32 wq_size; /* size in bytes of queue area */
+ u32 wq_len; /* number of entries in queue */
+ void __iomem *prod_idx_db_reg; /* doorbell area index reg at offset 0x00 */
+ void __iomem *valid_db_reg; /* doorbell area valid reg at offset 0x04 */
+ u16 prod_idx; /* current value for prod idx */
+ u16 cq_id; /* completion (rx) queue for tx completions */
+ u8 wq_id; /* queue id for this entry */
+ u8 reserved1[3];
+ struct tx_ring_desc *q; /* descriptor list for the queue */
+ spinlock_t lock;
+ atomic_t tx_count; /* counts down for every outstanding IO */
+ atomic_t queue_stopped; /* Turns queue off when full. */
+ struct delayed_work tx_work;
+ struct ql_adapter *qdev;
+};
+
+/*
+ * Type of inbound queue.
+ */
+enum {
+ DEFAULT_Q = 2, /* Handles slow queue and chip/MPI events. */
+ TX_Q = 3, /* Handles outbound completions. */
+ RX_Q = 4, /* Handles inbound completions. */
+};
+
+struct rx_ring {
+ struct cqicb cqicb; /* The chip's completion queue init control block. */
+
+ /* Completion queue elements. */
+ void *cq_base;
+ dma_addr_t cq_base_dma;
+ u32 cq_size;
+ u32 cq_len;
+ u16 cq_id;
+ u32 *prod_idx_sh_reg; /* Shadowed producer register. */
+ dma_addr_t prod_idx_sh_reg_dma;
+ void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
+ u32 cnsmr_idx; /* current sw idx */
+ struct ql_net_rsp_iocb *curr_entry; /* next entry on queue */
+ void __iomem *valid_db_reg; /* PCI doorbell mem area + 0x04 */
+
+ /* Large buffer queue elements. */
+ u32 lbq_len; /* entry count */
+ u32 lbq_size; /* size in bytes of queue */
+ u32 lbq_buf_size;
+ void *lbq_base;
+ dma_addr_t lbq_base_dma;
+ void *lbq_base_indirect;
+ dma_addr_t lbq_base_indirect_dma;
+ struct bq_desc *lbq; /* array of control blocks */
+ void __iomem *lbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x18 */
+ u32 lbq_prod_idx; /* current sw prod idx */
+ u32 lbq_curr_idx; /* next entry we expect */
+ u32 lbq_clean_idx; /* beginning of new descs */
+ u32 lbq_free_cnt; /* free buffer desc cnt */
+
+ /* Small buffer queue elements. */
+ u32 sbq_len; /* entry count */
+ u32 sbq_size; /* size in bytes of queue */
+ u32 sbq_buf_size;
+ void *sbq_base;
+ dma_addr_t sbq_base_dma;
+ void *sbq_base_indirect;
+ dma_addr_t sbq_base_indirect_dma;
+ struct bq_desc *sbq; /* array of control blocks */
+ void __iomem *sbq_prod_idx_db_reg; /* PCI doorbell mem area + 0x1c */
+ u32 sbq_prod_idx; /* current sw prod idx */
+ u32 sbq_curr_idx; /* next entry we expect */
+ u32 sbq_clean_idx; /* beginning of new descs */
+ u32 sbq_free_cnt; /* free buffer desc cnt */
+
+ /* Misc. handler elements. */
+ u32 type; /* Type of queue, tx, rx, or default. */
+ u32 irq; /* Which vector this ring is assigned. */
+ u32 cpu; /* Which CPU this should run on. */
+ char name[IFNAMSIZ + 5];
+ struct napi_struct napi;
+ struct delayed_work rx_work;
+ u8 reserved;
+ struct ql_adapter *qdev;
+};
+
+/*
+ * RSS Initialization Control Block
+ */
+struct hash_id {
+ u8 value[4];
+};
+
+struct nic_stats {
+ /*
+ * These stats come from offset 200h to 278h
+ * in the XGMAC register.
+ */
+ u64 tx_pkts;
+ u64 tx_bytes;
+ u64 tx_mcast_pkts;
+ u64 tx_bcast_pkts;
+ u64 tx_ucast_pkts;
+ u64 tx_ctl_pkts;
+ u64 tx_pause_pkts;
+ u64 tx_64_pkt;
+ u64 tx_65_to_127_pkt;
+ u64 tx_128_to_255_pkt;
+ u64 tx_256_511_pkt;
+ u64 tx_512_to_1023_pkt;
+ u64 tx_1024_to_1518_pkt;
+ u64 tx_1519_to_max_pkt;
+ u64 tx_undersize_pkt;
+ u64 tx_oversize_pkt;
+
+ /*
+ * These stats come from offset 300h to 3C8h
+ * in the XGMAC register.
+ */
+ u64 rx_bytes;
+ u64 rx_bytes_ok;
+ u64 rx_pkts;
+ u64 rx_pkts_ok;
+ u64 rx_bcast_pkts;
+ u64 rx_mcast_pkts;
+ u64 rx_ucast_pkts;
+ u64 rx_undersize_pkts;
+ u64 rx_oversize_pkts;
+ u64 rx_jabber_pkts;
+ u64 rx_undersize_fcerr_pkts;
+ u64 rx_drop_events;
+ u64 rx_fcerr_pkts;
+ u64 rx_align_err;
+ u64 rx_symbol_err;
+ u64 rx_mac_err;
+ u64 rx_ctl_pkts;
+ u64 rx_pause_pkts;
+ u64 rx_64_pkts;
+ u64 rx_65_to_127_pkts;
+ u64 rx_128_255_pkts;
+ u64 rx_256_511_pkts;
+ u64 rx_512_to_1023_pkts;
+ u64 rx_1024_to_1518_pkts;
+ u64 rx_1519_to_max_pkts;
+ u64 rx_len_err_pkts;
+};
+
+/*
+ * intr_context structure is used during initialization
+ * to hook the interrupts. It is also used in a single
+ * irq environment as a context to the ISR.
+ */
+struct intr_context {
+ struct ql_adapter *qdev;
+ u32 intr;
+ u32 hooked;
+ u32 intr_en_mask; /* value/mask used to enable this intr */
+ u32 intr_dis_mask; /* value/mask used to disable this intr */
+ u32 intr_read_mask; /* value/mask used to read this intr */
+ char name[IFNAMSIZ * 2];
+ atomic_t irq_cnt; /* irq_cnt is used in single vector
+ * environment. It's incremented for each
+ * irq handler that is scheduled. When each
+ * handler finishes it decrements irq_cnt and
+ * enables interrupts if it's zero. */
+ irq_handler_t handler;
+};
+
+/* adapter flags definitions. */
+enum {
+ QL_ADAPTER_UP = (1 << 0), /* Adapter has been brought up. */
+ QL_LEGACY_ENABLED = (1 << 3),
+ QL_MSI_ENABLED = (1 << 3),
+ QL_MSIX_ENABLED = (1 << 4),
+ QL_DMA64 = (1 << 5),
+ QL_PROMISCUOUS = (1 << 6),
+ QL_ALLMULTI = (1 << 7),
+};
+
+/* link_status bit definitions */
+enum {
+ LOOPBACK_MASK = 0x00000700,
+ LOOPBACK_PCS = 0x00000100,
+ LOOPBACK_HSS = 0x00000200,
+ LOOPBACK_EXT = 0x00000300,
+ PAUSE_MASK = 0x000000c0,
+ PAUSE_STD = 0x00000040,
+ PAUSE_PRI = 0x00000080,
+ SPEED_MASK = 0x00000038,
+ SPEED_100Mb = 0x00000000,
+ SPEED_1Gb = 0x00000008,
+ SPEED_10Gb = 0x00000010,
+ LINK_TYPE_MASK = 0x00000007,
+ LINK_TYPE_XFI = 0x00000001,
+ LINK_TYPE_XAUI = 0x00000002,
+ LINK_TYPE_XFI_BP = 0x00000003,
+ LINK_TYPE_XAUI_BP = 0x00000004,
+ LINK_TYPE_10GBASET = 0x00000005,
+};
+
+/*
+ * The main Adapter structure definition.
+ * This structure has all fields relevant to the hardware.
+ */
+struct ql_adapter {
+ struct ricb ricb;
+ unsigned long flags;
+ u32 wol;
+
+ struct nic_stats nic_stats;
+
+ struct vlan_group *vlgrp;
+
+ /* PCI Configuration information for this device */
+ struct pci_dev *pdev;
+ struct net_device *ndev; /* Parent NET device */
+
+ /* Hardware information */
+ u32 chip_rev_id;
+ u32 func; /* PCI function for this adapter */
+
+ spinlock_t adapter_lock;
+ spinlock_t hw_lock;
+ spinlock_t stats_lock;
+ spinlock_t legacy_lock; /* used for maintaining legacy intr sync */
+
+ /* PCI Bus Relative Register Addresses */
+ void __iomem *reg_base;
+ void __iomem *doorbell_area;
+ u32 doorbell_area_size;
+
+ u32 msg_enable;
+
+ /* Page for Shadow Registers */
+ void *rx_ring_shadow_reg_area;
+ dma_addr_t rx_ring_shadow_reg_dma;
+ void *tx_ring_shadow_reg_area;
+ dma_addr_t tx_ring_shadow_reg_dma;
+
+ u32 mailbox_in;
+ u32 mailbox_out;
+
+ int tx_ring_size;
+ int rx_ring_size;
+ u32 intr_count;
+ struct msix_entry *msi_x_entry;
+ struct intr_context intr_context[MAX_RX_RINGS];
+
+ int (*legacy_check) (struct ql_adapter *);
+
+ int tx_ring_count; /* One per online CPU. */
+ u32 rss_ring_first_cq_id;/* index of first inbound (rss) rx_ring */
+ u32 rss_ring_count; /* One per online CPU. */
+ /*
+ * rx_ring_count =
+ * one default queue +
+ * (CPU count * outbound completion rx_ring) +
+ * (CPU count * inbound (RSS) completion rx_ring)
+ */
+ int rx_ring_count;
+ int ring_mem_size;
+ void *ring_mem;
+ struct rx_ring *rx_ring;
+ int rx_csum;
+ struct tx_ring *tx_ring;
+ u32 default_rx_queue;
+
+ u16 rx_coalesce_usecs; /* cqicb->int_delay */
+ u16 rx_max_coalesced_frames; /* cqicb->pkt_int_delay */
+ u16 tx_coalesce_usecs; /* cqicb->int_delay */
+ u16 tx_max_coalesced_frames; /* cqicb->pkt_int_delay */
+
+ u32 xg_sem_mask;
+ u32 port_link_up;
+ u32 port_init;
+ u32 link_status;
+
+ struct flash_params flash;
+
+ struct net_device_stats stats;
+ struct workqueue_struct *q_workqueue;
+ struct workqueue_struct *workqueue;
+ struct delayed_work asic_reset_work;
+ struct delayed_work mpi_reset_work;
+ struct delayed_work mpi_work;
+};
+
+/*
+ * Typical Register accessor for memory mapped device.
+ */
+static inline u32 ql_read32(const struct ql_adapter *qdev, int reg)
+{
+ return readl(qdev->reg_base + reg);
+}
+
+/*
+ * Typical Register accessor for memory mapped device.
+ */
+static inline void ql_write32(const struct ql_adapter *qdev, int reg, u32 val)
+{
+ writel(val, qdev->reg_base + reg);
+}
+
+/*
+ * Doorbell Registers:
+ * Doorbell registers are virtual registers in the PCI memory space.
+ * The space is allocated by the chip during PCI initialization. The
+ * device driver finds the doorbell address in BAR 3 in PCI config space.
+ * The registers are used to control outbound and inbound queues. For
+ * example, the producer index for an outbound queue. Each queue uses
+ * 1 4k chunk of memory. The lower half of the space is for outbound
+ * queues. The upper half is for inbound queues.
+ */
+static inline void ql_write_db_reg(u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+ mmiowb();
+}
+
+/*
+ * Shadow Registers:
+ * Outbound queues have a consumer index that is maintained by the chip.
+ * Inbound queues have a producer index that is maintained by the chip.
+ * For lower overhead, these registers are "shadowed" to host memory
+ * which allows the device driver to track the queue progress without
+ * PCI reads. When an entry is placed on an inbound queue, the chip will
+ * update the relevant index register and then copy the value to the
+ * shadow register in host memory.
+ */
+static inline unsigned int ql_read_sh_reg(const volatile void *addr)
+{
+ return *(volatile unsigned int __force *)addr;
+}
+
+extern char qlge_driver_name[];
+extern const char qlge_driver_version[];
+extern const struct ethtool_ops qlge_ethtool_ops;
+
+extern int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask);
+extern void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask);
+extern int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
+extern int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
+ u32 *value);
+extern int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value);
+extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
+ u16 q_id);
+void ql_queue_fw_error(struct ql_adapter *qdev);
+void ql_mpi_work(struct work_struct *work);
+void ql_mpi_reset_work(struct work_struct *work);
+int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit);
+void ql_queue_asic_error(struct ql_adapter *qdev);
+void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
+void ql_set_ethtool_ops(struct net_device *ndev);
+int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data);
+
+#if 1
+#define QL_ALL_DUMP
+#define QL_REG_DUMP
+#define QL_DEV_DUMP
+#define QL_CB_DUMP
+/* #define QL_IB_DUMP */
+/* #define QL_OB_DUMP */
+#endif
+
+#ifdef QL_REG_DUMP
+extern void ql_dump_xgmac_control_regs(struct ql_adapter *qdev);
+extern void ql_dump_routing_entries(struct ql_adapter *qdev);
+extern void ql_dump_regs(struct ql_adapter *qdev);
+#define QL_DUMP_REGS(qdev) ql_dump_regs(qdev)
+#define QL_DUMP_ROUTE(qdev) ql_dump_routing_entries(qdev)
+#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) ql_dump_xgmac_control_regs(qdev)
+#else
+#define QL_DUMP_REGS(qdev)
+#define QL_DUMP_ROUTE(qdev)
+#define QL_DUMP_XGMAC_CONTROL_REGS(qdev)
+#endif
+
+#ifdef QL_STAT_DUMP
+extern void ql_dump_stat(struct ql_adapter *qdev);
+#define QL_DUMP_STAT(qdev) ql_dump_stat(qdev)
+#else
+#define QL_DUMP_STAT(qdev)
+#endif
+
+#ifdef QL_DEV_DUMP
+extern void ql_dump_qdev(struct ql_adapter *qdev);
+#define QL_DUMP_QDEV(qdev) ql_dump_qdev(qdev)
+#else
+#define QL_DUMP_QDEV(qdev)
+#endif
+
+#ifdef QL_CB_DUMP
+extern void ql_dump_wqicb(struct wqicb *wqicb);
+extern void ql_dump_tx_ring(struct tx_ring *tx_ring);
+extern void ql_dump_ricb(struct ricb *ricb);
+extern void ql_dump_cqicb(struct cqicb *cqicb);
+extern void ql_dump_rx_ring(struct rx_ring *rx_ring);
+extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);
+#define QL_DUMP_RICB(ricb) ql_dump_ricb(ricb)
+#define QL_DUMP_WQICB(wqicb) ql_dump_wqicb(wqicb)
+#define QL_DUMP_TX_RING(tx_ring) ql_dump_tx_ring(tx_ring)
+#define QL_DUMP_CQICB(cqicb) ql_dump_cqicb(cqicb)
+#define QL_DUMP_RX_RING(rx_ring) ql_dump_rx_ring(rx_ring)
+#define QL_DUMP_HW_CB(qdev, size, bit, q_id) \
+ ql_dump_hw_cb(qdev, size, bit, q_id)
+#else
+#define QL_DUMP_RICB(ricb)
+#define QL_DUMP_WQICB(wqicb)
+#define QL_DUMP_TX_RING(tx_ring)
+#define QL_DUMP_CQICB(cqicb)
+#define QL_DUMP_RX_RING(rx_ring)
+#define QL_DUMP_HW_CB(qdev, size, bit, q_id)
+#endif
+
+#ifdef QL_OB_DUMP
+extern void ql_dump_tx_desc(struct tx_buf_desc *tbd);
+extern void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb);
+extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);
+#define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb) ql_dump_ob_mac_iocb(ob_mac_iocb)
+#define QL_DUMP_OB_MAC_RSP(ob_mac_rsp) ql_dump_ob_mac_rsp(ob_mac_rsp)
+#else
+#define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb)
+#define QL_DUMP_OB_MAC_RSP(ob_mac_rsp)
+#endif
+
+#ifdef QL_IB_DUMP
+extern void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp);
+#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp) ql_dump_ib_mac_rsp(ib_mac_rsp)
+#else
+#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp)
+#endif
+
+#ifdef QL_ALL_DUMP
+extern void ql_dump_all(struct ql_adapter *qdev);
+#define QL_DUMP_ALL(qdev) ql_dump_all(qdev)
+#else
+#define QL_DUMP_ALL(qdev)
+#endif
+
+#endif /* _QLGE_H_ */
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
new file mode 100644
index 00000000000..47df304a02c
--- /dev/null
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -0,0 +1,858 @@
+#include "qlge.h"
+
+#ifdef QL_REG_DUMP
+static void ql_dump_intr_states(struct ql_adapter *qdev)
+{
+ int i;
+ u32 value;
+ for (i = 0; i < qdev->intr_count; i++) {
+ ql_write32(qdev, INTR_EN, qdev->intr_context[i].intr_read_mask);
+ value = ql_read32(qdev, INTR_EN);
+ printk(KERN_ERR PFX
+ "%s: Interrupt %d is %s.\n",
+ qdev->ndev->name, i,
+ (value & INTR_EN_EN ? "enabled" : "disabled"));
+ }
+}
+
+void ql_dump_xgmac_control_regs(struct ql_adapter *qdev)
+{
+ u32 data;
+ if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) {
+ printk(KERN_ERR "%s: Couldn't get xgmac sem.\n", __func__);
+ return;
+ }
+ ql_read_xgmac_reg(qdev, PAUSE_SRC_LO, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_SRC_LO = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, PAUSE_SRC_HI, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_SRC_HI = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data);
+ printk(KERN_ERR PFX "%s: GLOBAL_CFG = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, TX_CFG, &data);
+ printk(KERN_ERR PFX "%s: TX_CFG = 0x%.08x.\n", qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, RX_CFG, &data);
+ printk(KERN_ERR PFX "%s: RX_CFG = 0x%.08x.\n", qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, FLOW_CTL, &data);
+ printk(KERN_ERR PFX "%s: FLOW_CTL = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, PAUSE_OPCODE, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_OPCODE = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, PAUSE_TIMER, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_TIMER = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, PAUSE_FRM_DEST_LO, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_FRM_DEST_LO = 0x%.08x.\n",
+ qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, PAUSE_FRM_DEST_HI, &data);
+ printk(KERN_ERR PFX "%s: PAUSE_FRM_DEST_HI = 0x%.08x.\n",
+ qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, MAC_TX_PARAMS, &data);
+ printk(KERN_ERR PFX "%s: MAC_TX_PARAMS = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, MAC_RX_PARAMS, &data);
+ printk(KERN_ERR PFX "%s: MAC_RX_PARAMS = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, MAC_SYS_INT, &data);
+ printk(KERN_ERR PFX "%s: MAC_SYS_INT = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, MAC_SYS_INT_MASK, &data);
+ printk(KERN_ERR PFX "%s: MAC_SYS_INT_MASK = 0x%.08x.\n",
+ qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, MAC_MGMT_INT, &data);
+ printk(KERN_ERR PFX "%s: MAC_MGMT_INT = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_read_xgmac_reg(qdev, MAC_MGMT_IN_MASK, &data);
+ printk(KERN_ERR PFX "%s: MAC_MGMT_IN_MASK = 0x%.08x.\n",
+ qdev->ndev->name, data);
+ ql_read_xgmac_reg(qdev, EXT_ARB_MODE, &data);
+ printk(KERN_ERR PFX "%s: EXT_ARB_MODE = 0x%.08x.\n", qdev->ndev->name,
+ data);
+ ql_sem_unlock(qdev, qdev->xg_sem_mask);
+
+}
+
+static void ql_dump_ets_regs(struct ql_adapter *qdev)
+{
+}
+
+static void ql_dump_cam_entries(struct ql_adapter *qdev)
+{
+ int i;
+ u32 value[3];
+ for (i = 0; i < 4; i++) {
+ if (ql_get_mac_addr_reg(qdev, MAC_ADDR_TYPE_CAM_MAC, i, value)) {
+ printk(KERN_ERR PFX
+ "%s: Failed read of mac index register.\n",
+ __func__);
+ return;
+ } else {
+ if (value[0])
+ printk(KERN_ERR PFX
+ "%s: CAM index %d CAM Lookup Lower = 0x%.08x:%.08x, Output = 0x%.08x.\n",
+ qdev->ndev->name, i, value[1], value[0],
+ value[2]);
+ }
+ }
+ for (i = 0; i < 32; i++) {
+ if (ql_get_mac_addr_reg
+ (qdev, MAC_ADDR_TYPE_MULTI_MAC, i, value)) {
+ printk(KERN_ERR PFX
+ "%s: Failed read of mac index register.\n",
+ __func__);
+ return;
+ } else {
+ if (value[0])
+ printk(KERN_ERR PFX
+ "%s: MCAST index %d CAM Lookup Lower = 0x%.08x:%.08x.\n",
+ qdev->ndev->name, i, value[1], value[0]);
+ }
+ }
+}
+
+void ql_dump_routing_entries(struct ql_adapter *qdev)
+{
+ int i;
+ u32 value;
+ for (i = 0; i < 16; i++) {
+ value = 0;
+ if (ql_get_routing_reg(qdev, i, &value)) {
+ printk(KERN_ERR PFX
+ "%s: Failed read of routing index register.\n",
+ __func__);
+ return;
+ } else {
+ if (value)
+ printk(KERN_ERR PFX
+ "%s: Routing Mask %d = 0x%.08x.\n",
+ qdev->ndev->name, i, value);
+ }
+ }
+}
+
+void ql_dump_regs(struct ql_adapter *qdev)
+{
+ printk(KERN_ERR PFX "reg dump for function #%d.\n", qdev->func);
+ printk(KERN_ERR PFX "SYS = 0x%x.\n",
+ ql_read32(qdev, SYS));
+ printk(KERN_ERR PFX "RST_FO = 0x%x.\n",
+ ql_read32(qdev, RST_FO));
+ printk(KERN_ERR PFX "FSC = 0x%x.\n",
+ ql_read32(qdev, FSC));
+ printk(KERN_ERR PFX "CSR = 0x%x.\n",
+ ql_read32(qdev, CSR));
+ printk(KERN_ERR PFX "ICB_RID = 0x%x.\n",
+ ql_read32(qdev, ICB_RID));
+ printk(KERN_ERR PFX "ICB_L = 0x%x.\n",
+ ql_read32(qdev, ICB_L));
+ printk(KERN_ERR PFX "ICB_H = 0x%x.\n",
+ ql_read32(qdev, ICB_H));
+ printk(KERN_ERR PFX "CFG = 0x%x.\n",
+ ql_read32(qdev, CFG));
+ printk(KERN_ERR PFX "BIOS_ADDR = 0x%x.\n",
+ ql_read32(qdev, BIOS_ADDR));
+ printk(KERN_ERR PFX "STS = 0x%x.\n",
+ ql_read32(qdev, STS));
+ printk(KERN_ERR PFX "INTR_EN = 0x%x.\n",
+ ql_read32(qdev, INTR_EN));
+ printk(KERN_ERR PFX "INTR_MASK = 0x%x.\n",
+ ql_read32(qdev, INTR_MASK));
+ printk(KERN_ERR PFX "ISR1 = 0x%x.\n",
+ ql_read32(qdev, ISR1));
+ printk(KERN_ERR PFX "ISR2 = 0x%x.\n",
+ ql_read32(qdev, ISR2));
+ printk(KERN_ERR PFX "ISR3 = 0x%x.\n",
+ ql_read32(qdev, ISR3));
+ printk(KERN_ERR PFX "ISR4 = 0x%x.\n",
+ ql_read32(qdev, ISR4));
+ printk(KERN_ERR PFX "REV_ID = 0x%x.\n",
+ ql_read32(qdev, REV_ID));
+ printk(KERN_ERR PFX "FRC_ECC_ERR = 0x%x.\n",
+ ql_read32(qdev, FRC_ECC_ERR));
+ printk(KERN_ERR PFX "ERR_STS = 0x%x.\n",
+ ql_read32(qdev, ERR_STS));
+ printk(KERN_ERR PFX "RAM_DBG_ADDR = 0x%x.\n",
+ ql_read32(qdev, RAM_DBG_ADDR));
+ printk(KERN_ERR PFX "RAM_DBG_DATA = 0x%x.\n",
+ ql_read32(qdev, RAM_DBG_DATA));
+ printk(KERN_ERR PFX "ECC_ERR_CNT = 0x%x.\n",
+ ql_read32(qdev, ECC_ERR_CNT));
+ printk(KERN_ERR PFX "SEM = 0x%x.\n",
+ ql_read32(qdev, SEM));
+ printk(KERN_ERR PFX "GPIO_1 = 0x%x.\n",
+ ql_read32(qdev, GPIO_1));
+ printk(KERN_ERR PFX "GPIO_2 = 0x%x.\n",
+ ql_read32(qdev, GPIO_2));
+ printk(KERN_ERR PFX "GPIO_3 = 0x%x.\n",
+ ql_read32(qdev, GPIO_3));
+ printk(KERN_ERR PFX "XGMAC_ADDR = 0x%x.\n",
+ ql_read32(qdev, XGMAC_ADDR));
+ printk(KERN_ERR PFX "XGMAC_DATA = 0x%x.\n",
+ ql_read32(qdev, XGMAC_DATA));
+ printk(KERN_ERR PFX "NIC_ETS = 0x%x.\n",
+ ql_read32(qdev, NIC_ETS));
+ printk(KERN_ERR PFX "CNA_ETS = 0x%x.\n",
+ ql_read32(qdev, CNA_ETS));
+ printk(KERN_ERR PFX "FLASH_ADDR = 0x%x.\n",
+ ql_read32(qdev, FLASH_ADDR));
+ printk(KERN_ERR PFX "FLASH_DATA = 0x%x.\n",
+ ql_read32(qdev, FLASH_DATA));
+ printk(KERN_ERR PFX "CQ_STOP = 0x%x.\n",
+ ql_read32(qdev, CQ_STOP));
+ printk(KERN_ERR PFX "PAGE_TBL_RID = 0x%x.\n",
+ ql_read32(qdev, PAGE_TBL_RID));
+ printk(KERN_ERR PFX "WQ_PAGE_TBL_LO = 0x%x.\n",
+ ql_read32(qdev, WQ_PAGE_TBL_LO));
+ printk(KERN_ERR PFX "WQ_PAGE_TBL_HI = 0x%x.\n",
+ ql_read32(qdev, WQ_PAGE_TBL_HI));
+ printk(KERN_ERR PFX "CQ_PAGE_TBL_LO = 0x%x.\n",
+ ql_read32(qdev, CQ_PAGE_TBL_LO));
+ printk(KERN_ERR PFX "CQ_PAGE_TBL_HI = 0x%x.\n",
+ ql_read32(qdev, CQ_PAGE_TBL_HI));
+ printk(KERN_ERR PFX "COS_DFLT_CQ1 = 0x%x.\n",
+ ql_read32(qdev, COS_DFLT_CQ1));
+ printk(KERN_ERR PFX "COS_DFLT_CQ2 = 0x%x.\n",
+ ql_read32(qdev, COS_DFLT_CQ2));
+ printk(KERN_ERR PFX "SPLT_HDR = 0x%x.\n",
+ ql_read32(qdev, SPLT_HDR));
+ printk(KERN_ERR PFX "FC_PAUSE_THRES = 0x%x.\n",
+ ql_read32(qdev, FC_PAUSE_THRES));
+ printk(KERN_ERR PFX "NIC_PAUSE_THRES = 0x%x.\n",
+ ql_read32(qdev, NIC_PAUSE_THRES));
+ printk(KERN_ERR PFX "FC_ETHERTYPE = 0x%x.\n",
+ ql_read32(qdev, FC_ETHERTYPE));
+ printk(KERN_ERR PFX "FC_RCV_CFG = 0x%x.\n",
+ ql_read32(qdev, FC_RCV_CFG));
+ printk(KERN_ERR PFX "NIC_RCV_CFG = 0x%x.\n",
+ ql_read32(qdev, NIC_RCV_CFG));
+ printk(KERN_ERR PFX "FC_COS_TAGS = 0x%x.\n",
+ ql_read32(qdev, FC_COS_TAGS));
+ printk(KERN_ERR PFX "NIC_COS_TAGS = 0x%x.\n",
+ ql_read32(qdev, NIC_COS_TAGS));
+ printk(KERN_ERR PFX "MGMT_RCV_CFG = 0x%x.\n",
+ ql_read32(qdev, MGMT_RCV_CFG));
+ printk(KERN_ERR PFX "XG_SERDES_ADDR = 0x%x.\n",
+ ql_read32(qdev, XG_SERDES_ADDR));
+ printk(KERN_ERR PFX "XG_SERDES_DATA = 0x%x.\n",
+ ql_read32(qdev, XG_SERDES_DATA));
+ printk(KERN_ERR PFX "PRB_MX_ADDR = 0x%x.\n",
+ ql_read32(qdev, PRB_MX_ADDR));
+ printk(KERN_ERR PFX "PRB_MX_DATA = 0x%x.\n",
+ ql_read32(qdev, PRB_MX_DATA));
+ ql_dump_intr_states(qdev);
+ ql_dump_xgmac_control_regs(qdev);
+ ql_dump_ets_regs(qdev);
+ ql_dump_cam_entries(qdev);
+ ql_dump_routing_entries(qdev);
+}
+#endif
+
+#ifdef QL_STAT_DUMP
+void ql_dump_stat(struct ql_adapter *qdev)
+{
+ printk(KERN_ERR "%s: Enter.\n", __func__);
+ printk(KERN_ERR "tx_pkts = %ld\n",
+ (unsigned long)qdev->nic_stats.tx_pkts);
+ printk(KERN_ERR "tx_bytes = %ld\n",
+ (unsigned long)qdev->nic_stats.tx_bytes);
+ printk(KERN_ERR "tx_mcast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_mcast_pkts);
+ printk(KERN_ERR "tx_bcast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_bcast_pkts);
+ printk(KERN_ERR "tx_ucast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_ucast_pkts);
+ printk(KERN_ERR "tx_ctl_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_ctl_pkts);
+ printk(KERN_ERR "tx_pause_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_pause_pkts);
+ printk(KERN_ERR "tx_64_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_64_pkt);
+ printk(KERN_ERR "tx_65_to_127_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_65_to_127_pkt);
+ printk(KERN_ERR "tx_128_to_255_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_128_to_255_pkt);
+ printk(KERN_ERR "tx_256_511_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_256_511_pkt);
+ printk(KERN_ERR "tx_512_to_1023_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_512_to_1023_pkt);
+ printk(KERN_ERR "tx_1024_to_1518_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_1024_to_1518_pkt);
+ printk(KERN_ERR "tx_1519_to_max_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_1519_to_max_pkt);
+ printk(KERN_ERR "tx_undersize_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_undersize_pkt);
+ printk(KERN_ERR "tx_oversize_pkt = %ld.\n",
+ (unsigned long)qdev->nic_stats.tx_oversize_pkt);
+ printk(KERN_ERR "rx_bytes = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_bytes);
+ printk(KERN_ERR "rx_bytes_ok = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_bytes_ok);
+ printk(KERN_ERR "rx_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_pkts);
+ printk(KERN_ERR "rx_pkts_ok = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_pkts_ok);
+ printk(KERN_ERR "rx_bcast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_bcast_pkts);
+ printk(KERN_ERR "rx_mcast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_mcast_pkts);
+ printk(KERN_ERR "rx_ucast_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_ucast_pkts);
+ printk(KERN_ERR "rx_undersize_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_undersize_pkts);
+ printk(KERN_ERR "rx_oversize_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_oversize_pkts);
+ printk(KERN_ERR "rx_jabber_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_jabber_pkts);
+ printk(KERN_ERR "rx_undersize_fcerr_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_undersize_fcerr_pkts);
+ printk(KERN_ERR "rx_drop_events = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_drop_events);
+ printk(KERN_ERR "rx_fcerr_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_fcerr_pkts);
+ printk(KERN_ERR "rx_align_err = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_align_err);
+ printk(KERN_ERR "rx_symbol_err = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_symbol_err);
+ printk(KERN_ERR "rx_mac_err = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_mac_err);
+ printk(KERN_ERR "rx_ctl_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_ctl_pkts);
+ printk(KERN_ERR "rx_pause_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_pause_pkts);
+ printk(KERN_ERR "rx_64_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_64_pkts);
+ printk(KERN_ERR "rx_65_to_127_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_65_to_127_pkts);
+ printk(KERN_ERR "rx_128_255_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_128_255_pkts);
+ printk(KERN_ERR "rx_256_511_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_256_511_pkts);
+ printk(KERN_ERR "rx_512_to_1023_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_512_to_1023_pkts);
+ printk(KERN_ERR "rx_1024_to_1518_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_1024_to_1518_pkts);
+ printk(KERN_ERR "rx_1519_to_max_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_1519_to_max_pkts);
+ printk(KERN_ERR "rx_len_err_pkts = %ld.\n",
+ (unsigned long)qdev->nic_stats.rx_len_err_pkts);
+};
+#endif
+
+#ifdef QL_DEV_DUMP
+void ql_dump_qdev(struct ql_adapter *qdev)
+{
+ int i;
+ printk(KERN_ERR PFX "qdev->flags = %lx.\n",
+ qdev->flags);
+ printk(KERN_ERR PFX "qdev->vlgrp = %p.\n",
+ qdev->vlgrp);
+ printk(KERN_ERR PFX "qdev->pdev = %p.\n",
+ qdev->pdev);
+ printk(KERN_ERR PFX "qdev->ndev = %p.\n",
+ qdev->ndev);
+ printk(KERN_ERR PFX "qdev->chip_rev_id = %d.\n",
+ qdev->chip_rev_id);
+ printk(KERN_ERR PFX "qdev->reg_base = %p.\n",
+ qdev->reg_base);
+ printk(KERN_ERR PFX "qdev->doorbell_area = %p.\n",
+ qdev->doorbell_area);
+ printk(KERN_ERR PFX "qdev->doorbell_area_size = %d.\n",
+ qdev->doorbell_area_size);
+ printk(KERN_ERR PFX "msg_enable = %x.\n",
+ qdev->msg_enable);
+ printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_area = %p.\n",
+ qdev->rx_ring_shadow_reg_area);
+ printk(KERN_ERR PFX "qdev->rx_ring_shadow_reg_dma = %llx.\n",
+ (unsigned long long) qdev->rx_ring_shadow_reg_dma);
+ printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_area = %p.\n",
+ qdev->tx_ring_shadow_reg_area);
+ printk(KERN_ERR PFX "qdev->tx_ring_shadow_reg_dma = %llx.\n",
+ (unsigned long long) qdev->tx_ring_shadow_reg_dma);
+ printk(KERN_ERR PFX "qdev->intr_count = %d.\n",
+ qdev->intr_count);
+ if (qdev->msi_x_entry)
+ for (i = 0; i < qdev->intr_count; i++) {
+ printk(KERN_ERR PFX
+ "msi_x_entry.[%d]vector = %d.\n", i,
+ qdev->msi_x_entry[i].vector);
+ printk(KERN_ERR PFX
+ "msi_x_entry.[%d]entry = %d.\n", i,
+ qdev->msi_x_entry[i].entry);
+ }
+ for (i = 0; i < qdev->intr_count; i++) {
+ printk(KERN_ERR PFX
+ "intr_context[%d].qdev = %p.\n", i,
+ qdev->intr_context[i].qdev);
+ printk(KERN_ERR PFX
+ "intr_context[%d].intr = %d.\n", i,
+ qdev->intr_context[i].intr);
+ printk(KERN_ERR PFX
+ "intr_context[%d].hooked = %d.\n", i,
+ qdev->intr_context[i].hooked);
+ printk(KERN_ERR PFX
+ "intr_context[%d].intr_en_mask = 0x%08x.\n", i,
+ qdev->intr_context[i].intr_en_mask);
+ printk(KERN_ERR PFX
+ "intr_context[%d].intr_dis_mask = 0x%08x.\n", i,
+ qdev->intr_context[i].intr_dis_mask);
+ printk(KERN_ERR PFX
+ "intr_context[%d].intr_read_mask = 0x%08x.\n", i,
+ qdev->intr_context[i].intr_read_mask);
+ }
+ printk(KERN_ERR PFX "qdev->tx_ring_count = %d.\n", qdev->tx_ring_count);
+ printk(KERN_ERR PFX "qdev->rx_ring_count = %d.\n", qdev->rx_ring_count);
+ printk(KERN_ERR PFX "qdev->ring_mem_size = %d.\n", qdev->ring_mem_size);
+ printk(KERN_ERR PFX "qdev->ring_mem = %p.\n", qdev->ring_mem);
+ printk(KERN_ERR PFX "qdev->intr_count = %d.\n", qdev->intr_count);
+ printk(KERN_ERR PFX "qdev->tx_ring = %p.\n",
+ qdev->tx_ring);
+ printk(KERN_ERR PFX "qdev->rss_ring_first_cq_id = %d.\n",
+ qdev->rss_ring_first_cq_id);
+ printk(KERN_ERR PFX "qdev->rss_ring_count = %d.\n",
+ qdev->rss_ring_count);
+ printk(KERN_ERR PFX "qdev->rx_ring = %p.\n", qdev->rx_ring);
+ printk(KERN_ERR PFX "qdev->default_rx_queue = %d.\n",
+ qdev->default_rx_queue);
+ printk(KERN_ERR PFX "qdev->xg_sem_mask = 0x%08x.\n",
+ qdev->xg_sem_mask);
+ printk(KERN_ERR PFX "qdev->port_link_up = 0x%08x.\n",
+ qdev->port_link_up);
+ printk(KERN_ERR PFX "qdev->port_init = 0x%08x.\n",
+ qdev->port_init);
+
+}
+#endif
+
+#ifdef QL_CB_DUMP
+void ql_dump_wqicb(struct wqicb *wqicb)
+{
+ printk(KERN_ERR PFX "Dumping wqicb stuff...\n");
+ printk(KERN_ERR PFX "wqicb->len = 0x%x.\n", le16_to_cpu(wqicb->len));
+ printk(KERN_ERR PFX "wqicb->flags = %x.\n", le16_to_cpu(wqicb->flags));
+ printk(KERN_ERR PFX "wqicb->cq_id_rss = %d.\n",
+ le16_to_cpu(wqicb->cq_id_rss));
+ printk(KERN_ERR PFX "wqicb->rid = 0x%x.\n", le16_to_cpu(wqicb->rid));
+ printk(KERN_ERR PFX "wqicb->wq_addr_lo = 0x%.08x.\n",
+ le32_to_cpu(wqicb->addr_lo));
+ printk(KERN_ERR PFX "wqicb->wq_addr_hi = 0x%.08x.\n",
+ le32_to_cpu(wqicb->addr_hi));
+ printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_lo = 0x%.08x.\n",
+ le32_to_cpu(wqicb->cnsmr_idx_addr_lo));
+ printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_hi = 0x%.08x.\n",
+ le32_to_cpu(wqicb->cnsmr_idx_addr_hi));
+}
+
+void ql_dump_tx_ring(struct tx_ring *tx_ring)
+{
+ if (tx_ring == NULL)
+ return;
+ printk(KERN_ERR PFX
+ "===================== Dumping tx_ring %d ===============.\n",
+ tx_ring->wq_id);
+ printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base);
+ printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n",
+ (unsigned long long) tx_ring->wq_base_dma);
+ printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n",
+ tx_ring->cnsmr_idx_sh_reg);
+ printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n",
+ (unsigned long long) tx_ring->cnsmr_idx_sh_reg_dma);
+ printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size);
+ printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len);
+ printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n",
+ tx_ring->prod_idx_db_reg);
+ printk(KERN_ERR PFX "tx_ring->valid_db_reg = %p.\n",
+ tx_ring->valid_db_reg);
+ printk(KERN_ERR PFX "tx_ring->prod_idx = %d.\n", tx_ring->prod_idx);
+ printk(KERN_ERR PFX "tx_ring->cq_id = %d.\n", tx_ring->cq_id);
+ printk(KERN_ERR PFX "tx_ring->wq_id = %d.\n", tx_ring->wq_id);
+ printk(KERN_ERR PFX "tx_ring->q = %p.\n", tx_ring->q);
+ printk(KERN_ERR PFX "tx_ring->tx_count = %d.\n",
+ atomic_read(&tx_ring->tx_count));
+}
+
+void ql_dump_ricb(struct ricb *ricb)
+{
+ int i;
+ printk(KERN_ERR PFX
+ "===================== Dumping ricb ===============.\n");
+ printk(KERN_ERR PFX "Dumping ricb stuff...\n");
+
+ printk(KERN_ERR PFX "ricb->base_cq = %d.\n", ricb->base_cq & 0x1f);
+ printk(KERN_ERR PFX "ricb->flags = %s%s%s%s%s%s%s%s%s.\n",
+ ricb->base_cq & RSS_L4K ? "RSS_L4K " : "",
+ ricb->flags & RSS_L6K ? "RSS_L6K " : "",
+ ricb->flags & RSS_LI ? "RSS_LI " : "",
+ ricb->flags & RSS_LB ? "RSS_LB " : "",
+ ricb->flags & RSS_LM ? "RSS_LM " : "",
+ ricb->flags & RSS_RI4 ? "RSS_RI4 " : "",
+ ricb->flags & RSS_RT4 ? "RSS_RT4 " : "",
+ ricb->flags & RSS_RI6 ? "RSS_RI6 " : "",
+ ricb->flags & RSS_RT6 ? "RSS_RT6 " : "");
+ printk(KERN_ERR PFX "ricb->mask = 0x%.04x.\n", le16_to_cpu(ricb->mask));
+ for (i = 0; i < 16; i++)
+ printk(KERN_ERR PFX "ricb->hash_cq_id[%d] = 0x%.08x.\n", i,
+ le32_to_cpu(ricb->hash_cq_id[i]));
+ for (i = 0; i < 10; i++)
+ printk(KERN_ERR PFX "ricb->ipv6_hash_key[%d] = 0x%.08x.\n", i,
+ le32_to_cpu(ricb->ipv6_hash_key[i]));
+ for (i = 0; i < 4; i++)
+ printk(KERN_ERR PFX "ricb->ipv4_hash_key[%d] = 0x%.08x.\n", i,
+ le32_to_cpu(ricb->ipv4_hash_key[i]));
+}
+
+void ql_dump_cqicb(struct cqicb *cqicb)
+{
+ printk(KERN_ERR PFX "Dumping cqicb stuff...\n");
+
+ printk(KERN_ERR PFX "cqicb->msix_vect = %d.\n", cqicb->msix_vect);
+ printk(KERN_ERR PFX "cqicb->flags = %x.\n", cqicb->flags);
+ printk(KERN_ERR PFX "cqicb->len = %d.\n", le16_to_cpu(cqicb->len));
+ printk(KERN_ERR PFX "cqicb->addr_lo = %x.\n",
+ le32_to_cpu(cqicb->addr_lo));
+ printk(KERN_ERR PFX "cqicb->addr_hi = %x.\n",
+ le32_to_cpu(cqicb->addr_hi));
+ printk(KERN_ERR PFX "cqicb->prod_idx_addr_lo = %x.\n",
+ le32_to_cpu(cqicb->prod_idx_addr_lo));
+ printk(KERN_ERR PFX "cqicb->prod_idx_addr_hi = %x.\n",
+ le32_to_cpu(cqicb->prod_idx_addr_hi));
+ printk(KERN_ERR PFX "cqicb->pkt_delay = 0x%.04x.\n",
+ le16_to_cpu(cqicb->pkt_delay));
+ printk(KERN_ERR PFX "cqicb->irq_delay = 0x%.04x.\n",
+ le16_to_cpu(cqicb->irq_delay));
+ printk(KERN_ERR PFX "cqicb->lbq_addr_lo = %x.\n",
+ le32_to_cpu(cqicb->lbq_addr_lo));
+ printk(KERN_ERR PFX "cqicb->lbq_addr_hi = %x.\n",
+ le32_to_cpu(cqicb->lbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->lbq_buf_size = 0x%.04x.\n",
+ le16_to_cpu(cqicb->lbq_buf_size));
+ printk(KERN_ERR PFX "cqicb->lbq_len = 0x%.04x.\n",
+ le16_to_cpu(cqicb->lbq_len));
+ printk(KERN_ERR PFX "cqicb->sbq_addr_lo = %x.\n",
+ le32_to_cpu(cqicb->sbq_addr_lo));
+ printk(KERN_ERR PFX "cqicb->sbq_addr_hi = %x.\n",
+ le32_to_cpu(cqicb->sbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->sbq_buf_size = 0x%.04x.\n",
+ le16_to_cpu(cqicb->sbq_buf_size));
+ printk(KERN_ERR PFX "cqicb->sbq_len = 0x%.04x.\n",
+ le16_to_cpu(cqicb->sbq_len));
+}
+
+void ql_dump_rx_ring(struct rx_ring *rx_ring)
+{
+ if (rx_ring == NULL)
+ return;
+ printk(KERN_ERR PFX
+ "===================== Dumping rx_ring %d ===============.\n",
+ rx_ring->cq_id);
+ printk(KERN_ERR PFX "Dumping rx_ring %d, type = %s%s%s.\n",
+ rx_ring->cq_id, rx_ring->type == DEFAULT_Q ? "DEFAULT" : "",
+ rx_ring->type == TX_Q ? "OUTBOUND COMPLETIONS" : "",
+ rx_ring->type == RX_Q ? "INBOUND_COMPLETIONS" : "");
+ printk(KERN_ERR PFX "rx_ring->cqicb = %p.\n", &rx_ring->cqicb);
+ printk(KERN_ERR PFX "rx_ring->cq_base = %p.\n", rx_ring->cq_base);
+ printk(KERN_ERR PFX "rx_ring->cq_base_dma = %llx.\n",
+ (unsigned long long) rx_ring->cq_base_dma);
+ printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size);
+ printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len);
+ printk(KERN_ERR PFX
+ "rx_ring->prod_idx_sh_reg, addr = %p, value = %d.\n",
+ rx_ring->prod_idx_sh_reg,
+ rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0);
+ printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n",
+ (unsigned long long) rx_ring->prod_idx_sh_reg_dma);
+ printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n",
+ rx_ring->cnsmr_idx_db_reg);
+ printk(KERN_ERR PFX "rx_ring->cnsmr_idx = %d.\n", rx_ring->cnsmr_idx);
+ printk(KERN_ERR PFX "rx_ring->curr_entry = %p.\n", rx_ring->curr_entry);
+ printk(KERN_ERR PFX "rx_ring->valid_db_reg = %p.\n",
+ rx_ring->valid_db_reg);
+
+ printk(KERN_ERR PFX "rx_ring->lbq_base = %p.\n", rx_ring->lbq_base);
+ printk(KERN_ERR PFX "rx_ring->lbq_base_dma = %llx.\n",
+ (unsigned long long) rx_ring->lbq_base_dma);
+ printk(KERN_ERR PFX "rx_ring->lbq_base_indirect = %p.\n",
+ rx_ring->lbq_base_indirect);
+ printk(KERN_ERR PFX "rx_ring->lbq_base_indirect_dma = %llx.\n",
+ (unsigned long long) rx_ring->lbq_base_indirect_dma);
+ printk(KERN_ERR PFX "rx_ring->lbq = %p.\n", rx_ring->lbq);
+ printk(KERN_ERR PFX "rx_ring->lbq_len = %d.\n", rx_ring->lbq_len);
+ printk(KERN_ERR PFX "rx_ring->lbq_size = %d.\n", rx_ring->lbq_size);
+ printk(KERN_ERR PFX "rx_ring->lbq_prod_idx_db_reg = %p.\n",
+ rx_ring->lbq_prod_idx_db_reg);
+ printk(KERN_ERR PFX "rx_ring->lbq_prod_idx = %d.\n",
+ rx_ring->lbq_prod_idx);
+ printk(KERN_ERR PFX "rx_ring->lbq_curr_idx = %d.\n",
+ rx_ring->lbq_curr_idx);
+ printk(KERN_ERR PFX "rx_ring->lbq_clean_idx = %d.\n",
+ rx_ring->lbq_clean_idx);
+ printk(KERN_ERR PFX "rx_ring->lbq_free_cnt = %d.\n",
+ rx_ring->lbq_free_cnt);
+ printk(KERN_ERR PFX "rx_ring->lbq_buf_size = %d.\n",
+ rx_ring->lbq_buf_size);
+
+ printk(KERN_ERR PFX "rx_ring->sbq_base = %p.\n", rx_ring->sbq_base);
+ printk(KERN_ERR PFX "rx_ring->sbq_base_dma = %llx.\n",
+ (unsigned long long) rx_ring->sbq_base_dma);
+ printk(KERN_ERR PFX "rx_ring->sbq_base_indirect = %p.\n",
+ rx_ring->sbq_base_indirect);
+ printk(KERN_ERR PFX "rx_ring->sbq_base_indirect_dma = %llx.\n",
+ (unsigned long long) rx_ring->sbq_base_indirect_dma);
+ printk(KERN_ERR PFX "rx_ring->sbq = %p.\n", rx_ring->sbq);
+ printk(KERN_ERR PFX "rx_ring->sbq_len = %d.\n", rx_ring->sbq_len);
+ printk(KERN_ERR PFX "rx_ring->sbq_size = %d.\n", rx_ring->sbq_size);
+ printk(KERN_ERR PFX "rx_ring->sbq_prod_idx_db_reg addr = %p.\n",
+ rx_ring->sbq_prod_idx_db_reg);
+ printk(KERN_ERR PFX "rx_ring->sbq_prod_idx = %d.\n",
+ rx_ring->sbq_prod_idx);
+ printk(KERN_ERR PFX "rx_ring->sbq_curr_idx = %d.\n",
+ rx_ring->sbq_curr_idx);
+ printk(KERN_ERR PFX "rx_ring->sbq_clean_idx = %d.\n",
+ rx_ring->sbq_clean_idx);
+ printk(KERN_ERR PFX "rx_ring->sbq_free_cnt = %d.\n",
+ rx_ring->sbq_free_cnt);
+ printk(KERN_ERR PFX "rx_ring->sbq_buf_size = %d.\n",
+ rx_ring->sbq_buf_size);
+ printk(KERN_ERR PFX "rx_ring->cq_id = %d.\n", rx_ring->cq_id);
+ printk(KERN_ERR PFX "rx_ring->irq = %d.\n", rx_ring->irq);
+ printk(KERN_ERR PFX "rx_ring->cpu = %d.\n", rx_ring->cpu);
+ printk(KERN_ERR PFX "rx_ring->qdev = %p.\n", rx_ring->qdev);
+}
+
+void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id)
+{
+ void *ptr;
+
+ printk(KERN_ERR PFX "%s: Enter.\n", __func__);
+
+ ptr = kmalloc(size, GFP_ATOMIC);
+ if (ptr == NULL) {
+ printk(KERN_ERR PFX "%s: Couldn't allocate a buffer.\n",
+ __func__);
+ return;
+ }
+
+ if (ql_write_cfg(qdev, ptr, size, bit, q_id)) {
+ printk(KERN_ERR "%s: Failed to upload control block!\n",
+ __func__);
+ goto fail_it;
+ }
+ switch (bit) {
+ case CFG_DRQ:
+ ql_dump_wqicb((struct wqicb *)ptr);
+ break;
+ case CFG_DCQ:
+ ql_dump_cqicb((struct cqicb *)ptr);
+ break;
+ case CFG_DR:
+ ql_dump_ricb((struct ricb *)ptr);
+ break;
+ default:
+ printk(KERN_ERR PFX "%s: Invalid bit value = %x.\n",
+ __func__, bit);
+ break;
+ }
+fail_it:
+ kfree(ptr);
+}
+#endif
+
+#ifdef QL_OB_DUMP
+void ql_dump_tx_desc(struct tx_buf_desc *tbd)
+{
+ printk(KERN_ERR PFX "tbd->addr = 0x%llx\n",
+ le64_to_cpu((u64) tbd->addr));
+ printk(KERN_ERR PFX "tbd->len = %d\n",
+ le32_to_cpu(tbd->len & TX_DESC_LEN_MASK));
+ printk(KERN_ERR PFX "tbd->flags = %s %s\n",
+ tbd->len & TX_DESC_C ? "C" : ".",
+ tbd->len & TX_DESC_E ? "E" : ".");
+ tbd++;
+ printk(KERN_ERR PFX "tbd->addr = 0x%llx\n",
+ le64_to_cpu((u64) tbd->addr));
+ printk(KERN_ERR PFX "tbd->len = %d\n",
+ le32_to_cpu(tbd->len & TX_DESC_LEN_MASK));
+ printk(KERN_ERR PFX "tbd->flags = %s %s\n",
+ tbd->len & TX_DESC_C ? "C" : ".",
+ tbd->len & TX_DESC_E ? "E" : ".");
+ tbd++;
+ printk(KERN_ERR PFX "tbd->addr = 0x%llx\n",
+ le64_to_cpu((u64) tbd->addr));
+ printk(KERN_ERR PFX "tbd->len = %d\n",
+ le32_to_cpu(tbd->len & TX_DESC_LEN_MASK));
+ printk(KERN_ERR PFX "tbd->flags = %s %s\n",
+ tbd->len & TX_DESC_C ? "C" : ".",
+ tbd->len & TX_DESC_E ? "E" : ".");
+
+}
+
+void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb)
+{
+ struct ob_mac_tso_iocb_req *ob_mac_tso_iocb =
+ (struct ob_mac_tso_iocb_req *)ob_mac_iocb;
+ struct tx_buf_desc *tbd;
+ u16 frame_len;
+
+ printk(KERN_ERR PFX "%s\n", __func__);
+ printk(KERN_ERR PFX "opcode = %s\n",
+ (ob_mac_iocb->opcode == OPCODE_OB_MAC_IOCB) ? "MAC" : "TSO");
+ printk(KERN_ERR PFX "flags1 = %s %s %s %s %s\n",
+ ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_OI ? "OI" : "",
+ ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_I ? "I" : "",
+ ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_D ? "D" : "",
+ ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP4 ? "IP4" : "",
+ ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP6 ? "IP6" : "");
+ printk(KERN_ERR PFX "flags2 = %s %s %s\n",
+ ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_LSO ? "LSO" : "",
+ ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_UC ? "UC" : "",
+ ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_TC ? "TC" : "");
+ printk(KERN_ERR PFX "flags3 = %s %s %s \n",
+ ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_IC ? "IC" : "",
+ ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_DFP ? "DFP" : "",
+ ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_V ? "V" : "");
+ printk(KERN_ERR PFX "tid = %x\n", ob_mac_iocb->tid);
+ printk(KERN_ERR PFX "txq_idx = %d\n", ob_mac_iocb->txq_idx);
+ printk(KERN_ERR PFX "vlan_tci = %x\n", ob_mac_tso_iocb->vlan_tci);
+ if (ob_mac_iocb->opcode == OPCODE_OB_MAC_TSO_IOCB) {
+ printk(KERN_ERR PFX "frame_len = %d\n",
+ le32_to_cpu(ob_mac_tso_iocb->frame_len));
+ printk(KERN_ERR PFX "mss = %d\n",
+ le16_to_cpu(ob_mac_tso_iocb->mss));
+ printk(KERN_ERR PFX "prot_hdr_len = %d\n",
+ le16_to_cpu(ob_mac_tso_iocb->total_hdrs_len));
+ printk(KERN_ERR PFX "hdr_offset = 0x%.04x\n",
+ le16_to_cpu(ob_mac_tso_iocb->net_trans_offset));
+ frame_len = le32_to_cpu(ob_mac_tso_iocb->frame_len);
+ } else {
+ printk(KERN_ERR PFX "frame_len = %d\n",
+ le16_to_cpu(ob_mac_iocb->frame_len));
+ frame_len = le16_to_cpu(ob_mac_iocb->frame_len);
+ }
+ tbd = &ob_mac_iocb->tbd[0];
+ ql_dump_tx_desc(tbd);
+}
+
+void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp)
+{
+ printk(KERN_ERR PFX "%s\n", __func__);
+ printk(KERN_ERR PFX "opcode = %d\n", ob_mac_rsp->opcode);
+ printk(KERN_ERR PFX "flags = %s %s %s %s %s %s %s\n",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_OI ? "OI" : ".",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_I ? "I" : ".",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_E ? "E" : ".",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_S ? "S" : ".",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_L ? "L" : ".",
+ ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_P ? "P" : ".",
+ ob_mac_rsp->flags2 & OB_MAC_IOCB_RSP_B ? "B" : ".");
+ printk(KERN_ERR PFX "tid = %x\n", ob_mac_rsp->tid);
+}
+#endif
+
+#ifdef QL_IB_DUMP
+void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
+{
+ printk(KERN_ERR PFX "%s\n", __func__);
+ printk(KERN_ERR PFX "opcode = 0x%x\n", ib_mac_rsp->opcode);
+ printk(KERN_ERR PFX "flags1 = %s%s%s%s%s%s\n",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_OI ? "OI " : "",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_I ? "I " : "",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_TE ? "TE " : "",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU ? "NU " : "",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_IE ? "IE " : "",
+ ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_B ? "B " : "");
+
+ if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK)
+ printk(KERN_ERR PFX "%s%s%s Multicast.\n",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_REG ? "Registered" : "",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : "");
+
+ printk(KERN_ERR PFX "flags2 = %s%s%s%s%s\n",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) ? "P " : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? "V " : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) ? "U " : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) ? "T " : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_FO) ? "FO " : "");
+
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK)
+ printk(KERN_ERR PFX "%s%s%s%s%s error.\n",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) ==
+ IB_MAC_IOCB_RSP_ERR_OVERSIZE ? "oversize" : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) ==
+ IB_MAC_IOCB_RSP_ERR_UNDERSIZE ? "undersize" : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) ==
+ IB_MAC_IOCB_RSP_ERR_PREAMBLE ? "preamble" : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) ==
+ IB_MAC_IOCB_RSP_ERR_FRAME_LEN ? "frame length" : "",
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) ==
+ IB_MAC_IOCB_RSP_ERR_CRC ? "CRC" : "");
+
+ printk(KERN_ERR PFX "flags3 = %s%s.\n",
+ ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS ? "DS " : "",
+ ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL ? "DL " : "");
+
+ if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK)
+ printk(KERN_ERR PFX "RSS flags = %s%s%s%s.\n",
+ ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) ==
+ IB_MAC_IOCB_RSP_M_IPV4) ? "IPv4 RSS" : "",
+ ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) ==
+ IB_MAC_IOCB_RSP_M_IPV6) ? "IPv6 RSS " : "",
+ ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) ==
+ IB_MAC_IOCB_RSP_M_TCP_V4) ? "TCP/IPv4 RSS" : "",
+ ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) ==
+ IB_MAC_IOCB_RSP_M_TCP_V6) ? "TCP/IPv6 RSS" : "");
+
+ printk(KERN_ERR PFX "data_len = %d\n",
+ le32_to_cpu(ib_mac_rsp->data_len));
+ printk(KERN_ERR PFX "data_addr_hi = 0x%x\n",
+ le32_to_cpu(ib_mac_rsp->data_addr_hi));
+ printk(KERN_ERR PFX "data_addr_lo = 0x%x\n",
+ le32_to_cpu(ib_mac_rsp->data_addr_lo));
+ if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK)
+ printk(KERN_ERR PFX "rss = %x\n",
+ le32_to_cpu(ib_mac_rsp->rss));
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)
+ printk(KERN_ERR PFX "vlan_id = %x\n",
+ le16_to_cpu(ib_mac_rsp->vlan_id));
+
+ printk(KERN_ERR PFX "flags4 = %s%s%s.\n",
+ le32_to_cpu(ib_mac_rsp->
+ flags4) & IB_MAC_IOCB_RSP_HV ? "HV " : "",
+ le32_to_cpu(ib_mac_rsp->
+ flags4) & IB_MAC_IOCB_RSP_HS ? "HS " : "",
+ le32_to_cpu(ib_mac_rsp->
+ flags4) & IB_MAC_IOCB_RSP_HL ? "HL " : "");
+
+ if (le32_to_cpu(ib_mac_rsp->flags4) & IB_MAC_IOCB_RSP_HV) {
+ printk(KERN_ERR PFX "hdr length = %d.\n",
+ le32_to_cpu(ib_mac_rsp->hdr_len));
+ printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n",
+ le32_to_cpu(ib_mac_rsp->hdr_addr_hi));
+ printk(KERN_ERR PFX "hdr addr_lo = 0x%x.\n",
+ le32_to_cpu(ib_mac_rsp->hdr_addr_lo));
+ }
+}
+#endif
+
+#ifdef QL_ALL_DUMP
+void ql_dump_all(struct ql_adapter *qdev)
+{
+ int i;
+
+ QL_DUMP_REGS(qdev);
+ QL_DUMP_QDEV(qdev);
+ for (i = 0; i < qdev->tx_ring_count; i++) {
+ QL_DUMP_TX_RING(&qdev->tx_ring[i]);
+ QL_DUMP_WQICB((struct wqicb *)&qdev->tx_ring[i]);
+ }
+ for (i = 0; i < qdev->rx_ring_count; i++) {
+ QL_DUMP_RX_RING(&qdev->rx_ring[i]);
+ QL_DUMP_CQICB((struct cqicb *)&qdev->rx_ring[i]);
+ }
+}
+#endif
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
new file mode 100644
index 00000000000..b62fbd4bf00
--- /dev/null
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -0,0 +1,414 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/dmapool.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <linux/version.h>
+
+#include "qlge.h"
+
+static int ql_update_ring_coalescing(struct ql_adapter *qdev)
+{
+ int i, status = 0;
+ struct rx_ring *rx_ring;
+ struct cqicb *cqicb;
+
+ if (!netif_running(qdev->ndev))
+ return status;
+
+ spin_lock(&qdev->hw_lock);
+ /* Skip the default queue, and update the outbound handler
+ * queues if they changed.
+ */
+ cqicb = (struct cqicb *)&qdev->rx_ring[1];
+ if (le16_to_cpu(cqicb->irq_delay) != qdev->tx_coalesce_usecs ||
+ le16_to_cpu(cqicb->pkt_delay) != qdev->tx_max_coalesced_frames) {
+ for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) {
+ rx_ring = &qdev->rx_ring[i];
+ cqicb = (struct cqicb *)rx_ring;
+ cqicb->irq_delay = le16_to_cpu(qdev->tx_coalesce_usecs);
+ cqicb->pkt_delay =
+ le16_to_cpu(qdev->tx_max_coalesced_frames);
+ cqicb->flags = FLAGS_LI;
+ status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+ CFG_LCQ, rx_ring->cq_id);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to load CQICB.\n");
+ goto exit;
+ }
+ }
+ }
+
+ /* Update the inbound (RSS) handler queues if they changed. */
+ cqicb = (struct cqicb *)&qdev->rx_ring[qdev->rss_ring_first_cq_id];
+ if (le16_to_cpu(cqicb->irq_delay) != qdev->rx_coalesce_usecs ||
+ le16_to_cpu(cqicb->pkt_delay) != qdev->rx_max_coalesced_frames) {
+ for (i = qdev->rss_ring_first_cq_id;
+ i <= qdev->rss_ring_first_cq_id + qdev->rss_ring_count;
+ i++) {
+ rx_ring = &qdev->rx_ring[i];
+ cqicb = (struct cqicb *)rx_ring;
+ cqicb->irq_delay = le16_to_cpu(qdev->rx_coalesce_usecs);
+ cqicb->pkt_delay =
+ le16_to_cpu(qdev->rx_max_coalesced_frames);
+ cqicb->flags = FLAGS_LI;
+ status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+ CFG_LCQ, rx_ring->cq_id);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to load CQICB.\n");
+ goto exit;
+ }
+ }
+ }
+exit:
+ spin_unlock(&qdev->hw_lock);
+ return status;
+}
+
+void ql_update_stats(struct ql_adapter *qdev)
+{
+ u32 i;
+ u64 data;
+ u64 *iter = &qdev->nic_stats.tx_pkts;
+
+ spin_lock(&qdev->stats_lock);
+ if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) {
+ QPRINTK(qdev, DRV, ERR,
+ "Couldn't get xgmac sem.\n");
+ goto quit;
+ }
+ /*
+ * Get TX statistics.
+ */
+ for (i = 0x200; i < 0x280; i += 8) {
+ if (ql_read_xgmac_reg64(qdev, i, &data)) {
+ QPRINTK(qdev, DRV, ERR,
+ "Error reading status register 0x%.04x.\n", i);
+ goto end;
+ } else
+ *iter = data;
+ iter++;
+ }
+
+ /*
+ * Get RX statistics.
+ */
+ for (i = 0x300; i < 0x3d0; i += 8) {
+ if (ql_read_xgmac_reg64(qdev, i, &data)) {
+ QPRINTK(qdev, DRV, ERR,
+ "Error reading status register 0x%.04x.\n", i);
+ goto end;
+ } else
+ *iter = data;
+ iter++;
+ }
+
+end:
+ ql_sem_unlock(qdev, qdev->xg_sem_mask);
+quit:
+ spin_unlock(&qdev->stats_lock);
+
+ QL_DUMP_STAT(qdev);
+
+ return;
+}
+
+static char ql_stats_str_arr[][ETH_GSTRING_LEN] = {
+ {"tx_pkts"},
+ {"tx_bytes"},
+ {"tx_mcast_pkts"},
+ {"tx_bcast_pkts"},
+ {"tx_ucast_pkts"},
+ {"tx_ctl_pkts"},
+ {"tx_pause_pkts"},
+ {"tx_64_pkts"},
+ {"tx_65_to_127_pkts"},
+ {"tx_128_to_255_pkts"},
+ {"tx_256_511_pkts"},
+ {"tx_512_to_1023_pkts"},
+ {"tx_1024_to_1518_pkts"},
+ {"tx_1519_to_max_pkts"},
+ {"tx_undersize_pkts"},
+ {"tx_oversize_pkts"},
+ {"rx_bytes"},
+ {"rx_bytes_ok"},
+ {"rx_pkts"},
+ {"rx_pkts_ok"},
+ {"rx_bcast_pkts"},
+ {"rx_mcast_pkts"},
+ {"rx_ucast_pkts"},
+ {"rx_undersize_pkts"},
+ {"rx_oversize_pkts"},
+ {"rx_jabber_pkts"},
+ {"rx_undersize_fcerr_pkts"},
+ {"rx_drop_events"},
+ {"rx_fcerr_pkts"},
+ {"rx_align_err"},
+ {"rx_symbol_err"},
+ {"rx_mac_err"},
+ {"rx_ctl_pkts"},
+ {"rx_pause_pkts"},
+ {"rx_64_pkts"},
+ {"rx_65_to_127_pkts"},
+ {"rx_128_255_pkts"},
+ {"rx_256_511_pkts"},
+ {"rx_512_to_1023_pkts"},
+ {"rx_1024_to_1518_pkts"},
+ {"rx_1519_to_max_pkts"},
+ {"rx_len_err_pkts"},
+};
+
+static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(buf, ql_stats_str_arr, sizeof(ql_stats_str_arr));
+ break;
+ }
+}
+
+static int ql_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(ql_stats_str_arr);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void
+ql_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ struct nic_stats *s = &qdev->nic_stats;
+
+ ql_update_stats(qdev);
+
+ *data++ = s->tx_pkts;
+ *data++ = s->tx_bytes;
+ *data++ = s->tx_mcast_pkts;
+ *data++ = s->tx_bcast_pkts;
+ *data++ = s->tx_ucast_pkts;
+ *data++ = s->tx_ctl_pkts;
+ *data++ = s->tx_pause_pkts;
+ *data++ = s->tx_64_pkt;
+ *data++ = s->tx_65_to_127_pkt;
+ *data++ = s->tx_128_to_255_pkt;
+ *data++ = s->tx_256_511_pkt;
+ *data++ = s->tx_512_to_1023_pkt;
+ *data++ = s->tx_1024_to_1518_pkt;
+ *data++ = s->tx_1519_to_max_pkt;
+ *data++ = s->tx_undersize_pkt;
+ *data++ = s->tx_oversize_pkt;
+ *data++ = s->rx_bytes;
+ *data++ = s->rx_bytes_ok;
+ *data++ = s->rx_pkts;
+ *data++ = s->rx_pkts_ok;
+ *data++ = s->rx_bcast_pkts;
+ *data++ = s->rx_mcast_pkts;
+ *data++ = s->rx_ucast_pkts;
+ *data++ = s->rx_undersize_pkts;
+ *data++ = s->rx_oversize_pkts;
+ *data++ = s->rx_jabber_pkts;
+ *data++ = s->rx_undersize_fcerr_pkts;
+ *data++ = s->rx_drop_events;
+ *data++ = s->rx_fcerr_pkts;
+ *data++ = s->rx_align_err;
+ *data++ = s->rx_symbol_err;
+ *data++ = s->rx_mac_err;
+ *data++ = s->rx_ctl_pkts;
+ *data++ = s->rx_pause_pkts;
+ *data++ = s->rx_64_pkts;
+ *data++ = s->rx_65_to_127_pkts;
+ *data++ = s->rx_128_255_pkts;
+ *data++ = s->rx_256_511_pkts;
+ *data++ = s->rx_512_to_1023_pkts;
+ *data++ = s->rx_1024_to_1518_pkts;
+ *data++ = s->rx_1519_to_max_pkts;
+ *data++ = s->rx_len_err_pkts;
+}
+
+static int ql_get_settings(struct net_device *ndev,
+ struct ethtool_cmd *ecmd)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ ecmd->supported = SUPPORTED_10000baseT_Full;
+ ecmd->advertising = ADVERTISED_10000baseT_Full;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->transceiver = XCVR_EXTERNAL;
+ if ((qdev->link_status & LINK_TYPE_MASK) == LINK_TYPE_10GBASET) {
+ ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
+ ecmd->advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg);
+ ecmd->port = PORT_TP;
+ } else {
+ ecmd->supported |= SUPPORTED_FIBRE;
+ ecmd->advertising |= ADVERTISED_FIBRE;
+ ecmd->port = PORT_FIBRE;
+ }
+
+ ecmd->speed = SPEED_10000;
+ ecmd->duplex = DUPLEX_FULL;
+
+ return 0;
+}
+
+static void ql_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ strncpy(drvinfo->driver, qlge_driver_name, 32);
+ strncpy(drvinfo->version, qlge_driver_version, 32);
+ strncpy(drvinfo->fw_version, "N/A", 32);
+ strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
+ drvinfo->n_stats = 0;
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = 0;
+ drvinfo->eedump_len = 0;
+}
+
+static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+{
+ struct ql_adapter *qdev = netdev_priv(dev);
+
+ c->rx_coalesce_usecs = qdev->rx_coalesce_usecs;
+ c->tx_coalesce_usecs = qdev->tx_coalesce_usecs;
+
+ /* This chip coalesces as follows:
+ * If a packet arrives, hold off interrupts until
+ * cqicb->int_delay expires, but if no other packets arrive don't
+ * wait longer than cqicb->pkt_int_delay. But ethtool doesn't use a
+ * timer to coalesce on a frame basis. So, we have to take ethtool's
+ * max_coalesced_frames value and convert it to a delay in microseconds.
+ * We do this by using a basic thoughput of 1,000,000 frames per
+ * second @ (1024 bytes). This means one frame per usec. So it's a
+ * simple one to one ratio.
+ */
+ c->rx_max_coalesced_frames = qdev->rx_max_coalesced_frames;
+ c->tx_max_coalesced_frames = qdev->tx_max_coalesced_frames;
+
+ return 0;
+}
+
+static int ql_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *c)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ /* Validate user parameters. */
+ if (c->rx_coalesce_usecs > qdev->rx_ring_size / 2)
+ return -EINVAL;
+ /* Don't wait more than 10 usec. */
+ if (c->rx_max_coalesced_frames > MAX_INTER_FRAME_WAIT)
+ return -EINVAL;
+ if (c->tx_coalesce_usecs > qdev->tx_ring_size / 2)
+ return -EINVAL;
+ if (c->tx_max_coalesced_frames > MAX_INTER_FRAME_WAIT)
+ return -EINVAL;
+
+ /* Verify a change took place before updating the hardware. */
+ if (qdev->rx_coalesce_usecs == c->rx_coalesce_usecs &&
+ qdev->tx_coalesce_usecs == c->tx_coalesce_usecs &&
+ qdev->rx_max_coalesced_frames == c->rx_max_coalesced_frames &&
+ qdev->tx_max_coalesced_frames == c->tx_max_coalesced_frames)
+ return 0;
+
+ qdev->rx_coalesce_usecs = c->rx_coalesce_usecs;
+ qdev->tx_coalesce_usecs = c->tx_coalesce_usecs;
+ qdev->rx_max_coalesced_frames = c->rx_max_coalesced_frames;
+ qdev->tx_max_coalesced_frames = c->tx_max_coalesced_frames;
+
+ return ql_update_ring_coalescing(qdev);
+}
+
+static u32 ql_get_rx_csum(struct net_device *netdev)
+{
+ struct ql_adapter *qdev = netdev_priv(netdev);
+ return qdev->rx_csum;
+}
+
+static int ql_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+ struct ql_adapter *qdev = netdev_priv(netdev);
+ qdev->rx_csum = data;
+ return 0;
+}
+
+static int ql_set_tso(struct net_device *ndev, uint32_t data)
+{
+
+ if (data) {
+ ndev->features |= NETIF_F_TSO;
+ ndev->features |= NETIF_F_TSO6;
+ } else {
+ ndev->features &= ~NETIF_F_TSO;
+ ndev->features &= ~NETIF_F_TSO6;
+ }
+ return 0;
+}
+
+static u32 ql_get_msglevel(struct net_device *ndev)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ return qdev->msg_enable;
+}
+
+static void ql_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ qdev->msg_enable = value;
+}
+
+const struct ethtool_ops qlge_ethtool_ops = {
+ .get_settings = ql_get_settings,
+ .get_drvinfo = ql_get_drvinfo,
+ .get_msglevel = ql_get_msglevel,
+ .set_msglevel = ql_set_msglevel,
+ .get_link = ethtool_op_get_link,
+ .get_rx_csum = ql_get_rx_csum,
+ .set_rx_csum = ql_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ql_set_tso,
+ .get_coalesce = ql_get_coalesce,
+ .set_coalesce = ql_set_coalesce,
+ .get_sset_count = ql_get_sset_count,
+ .get_strings = ql_get_strings,
+ .get_ethtool_stats = ql_get_ethtool_stats,
+};
+
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
new file mode 100644
index 00000000000..4b2caa6b7ac
--- /dev/null
+++ b/drivers/net/qlge/qlge_main.c
@@ -0,0 +1,3956 @@
+/*
+ * QLogic qlge NIC HBA Driver
+ * Copyright (c) 2003-2008 QLogic Corporation
+ * See LICENSE.qlge for copyright and licensing details.
+ * Author: Linux qlge network device driver by
+ * Ron Mercer <ron.mercer@qlogic.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/dmapool.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <net/ip6_checksum.h>
+
+#include "qlge.h"
+
+char qlge_driver_name[] = DRV_NAME;
+const char qlge_driver_version[] = DRV_VERSION;
+
+MODULE_AUTHOR("Ron Mercer <ron.mercer@qlogic.com>");
+MODULE_DESCRIPTION(DRV_STRING " ");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static const u32 default_msg =
+ NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK |
+/* NETIF_MSG_TIMER | */
+ NETIF_MSG_IFDOWN |
+ NETIF_MSG_IFUP |
+ NETIF_MSG_RX_ERR |
+ NETIF_MSG_TX_ERR |
+ NETIF_MSG_TX_QUEUED |
+ NETIF_MSG_INTR | NETIF_MSG_TX_DONE | NETIF_MSG_RX_STATUS |
+/* NETIF_MSG_PKTDATA | */
+ NETIF_MSG_HW | NETIF_MSG_WOL | 0;
+
+static int debug = 0x00007fff; /* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+#define MSIX_IRQ 0
+#define MSI_IRQ 1
+#define LEG_IRQ 2
+static int irq_type = MSIX_IRQ;
+module_param(irq_type, int, MSIX_IRQ);
+MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");
+
+static struct pci_device_id qlge_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID1)},
+ /* required last entry */
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, qlge_pci_tbl);
+
+/* This hardware semaphore causes exclusive access to
+ * resources shared between the NIC driver, MPI firmware,
+ * FCOE firmware and the FC driver.
+ */
+static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask)
+{
+ u32 sem_bits = 0;
+
+ switch (sem_mask) {
+ case SEM_XGMAC0_MASK:
+ sem_bits = SEM_SET << SEM_XGMAC0_SHIFT;
+ break;
+ case SEM_XGMAC1_MASK:
+ sem_bits = SEM_SET << SEM_XGMAC1_SHIFT;
+ break;
+ case SEM_ICB_MASK:
+ sem_bits = SEM_SET << SEM_ICB_SHIFT;
+ break;
+ case SEM_MAC_ADDR_MASK:
+ sem_bits = SEM_SET << SEM_MAC_ADDR_SHIFT;
+ break;
+ case SEM_FLASH_MASK:
+ sem_bits = SEM_SET << SEM_FLASH_SHIFT;
+ break;
+ case SEM_PROBE_MASK:
+ sem_bits = SEM_SET << SEM_PROBE_SHIFT;
+ break;
+ case SEM_RT_IDX_MASK:
+ sem_bits = SEM_SET << SEM_RT_IDX_SHIFT;
+ break;
+ case SEM_PROC_REG_MASK:
+ sem_bits = SEM_SET << SEM_PROC_REG_SHIFT;
+ break;
+ default:
+ QPRINTK(qdev, PROBE, ALERT, "Bad Semaphore mask!.\n");
+ return -EINVAL;
+ }
+
+ ql_write32(qdev, SEM, sem_bits | sem_mask);
+ return !(ql_read32(qdev, SEM) & sem_bits);
+}
+
+int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask)
+{
+ unsigned int seconds = 3;
+ do {
+ if (!ql_sem_trylock(qdev, sem_mask))
+ return 0;
+ ssleep(1);
+ } while (--seconds);
+ return -ETIMEDOUT;
+}
+
+void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask)
+{
+ ql_write32(qdev, SEM, sem_mask);
+ ql_read32(qdev, SEM); /* flush */
+}
+
+/* This function waits for a specific bit to come ready
+ * in a given register. It is used mostly by the initialize
+ * process, but is also used in kernel thread API such as
+ * netdev->set_multi, netdev->set_mac_address, netdev->vlan_rx_add_vid.
+ */
+int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit)
+{
+ u32 temp;
+ int count = UDELAY_COUNT;
+
+ while (count) {
+ temp = ql_read32(qdev, reg);
+
+ /* check for errors */
+ if (temp & err_bit) {
+ QPRINTK(qdev, PROBE, ALERT,
+ "register 0x%.08x access error, value = 0x%.08x!.\n",
+ reg, temp);
+ return -EIO;
+ } else if (temp & bit)
+ return 0;
+ udelay(UDELAY_DELAY);
+ count--;
+ }
+ QPRINTK(qdev, PROBE, ALERT,
+ "Timed out waiting for reg %x to come ready.\n", reg);
+ return -ETIMEDOUT;
+}
+
+/* The CFG register is used to download TX and RX control blocks
+ * to the chip. This function waits for an operation to complete.
+ */
+static int ql_wait_cfg(struct ql_adapter *qdev, u32 bit)
+{
+ int count = UDELAY_COUNT;
+ u32 temp;
+
+ while (count) {
+ temp = ql_read32(qdev, CFG);
+ if (temp & CFG_LE)
+ return -EIO;
+ if (!(temp & bit))
+ return 0;
+ udelay(UDELAY_DELAY);
+ count--;
+ }
+ return -ETIMEDOUT;
+}
+
+
+/* Used to issue init control blocks to hw. Maps control block,
+ * sets address, triggers download, waits for completion.
+ */
+int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
+ u16 q_id)
+{
+ u64 map;
+ int status = 0;
+ int direction;
+ u32 mask;
+ u32 value;
+
+ direction =
+ (bit & (CFG_LRQ | CFG_LR | CFG_LCQ)) ? PCI_DMA_TODEVICE :
+ PCI_DMA_FROMDEVICE;
+
+ map = pci_map_single(qdev->pdev, ptr, size, direction);
+ if (pci_dma_mapping_error(qdev->pdev, map)) {
+ QPRINTK(qdev, IFUP, ERR, "Couldn't map DMA area.\n");
+ return -ENOMEM;
+ }
+
+ status = ql_wait_cfg(qdev, bit);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Timed out waiting for CFG to come ready.\n");
+ goto exit;
+ }
+
+ status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
+ if (status)
+ goto exit;
+ ql_write32(qdev, ICB_L, (u32) map);
+ ql_write32(qdev, ICB_H, (u32) (map >> 32));
+ ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */
+
+ mask = CFG_Q_MASK | (bit << 16);
+ value = bit | (q_id << CFG_Q_SHIFT);
+ ql_write32(qdev, CFG, (mask | value));
+
+ /*
+ * Wait for the bit to clear after signaling hw.
+ */
+ status = ql_wait_cfg(qdev, bit);
+exit:
+ pci_unmap_single(qdev->pdev, map, size, direction);
+ return status;
+}
+
+/* Get a specific MAC address from the CAM. Used for debug and reg dump. */
+int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
+ u32 *value)
+{
+ u32 offset = 0;
+ int status;
+
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return status;
+ switch (type) {
+ case MAC_ADDR_TYPE_MULTI_MAC:
+ case MAC_ADDR_TYPE_CAM_MAC:
+ {
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ *value++ = ql_read32(qdev, MAC_ADDR_DATA);
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ *value++ = ql_read32(qdev, MAC_ADDR_DATA);
+ if (type == MAC_ADDR_TYPE_CAM_MAC) {
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
+ status =
+ ql_wait_reg_rdy(qdev, MAC_ADDR_IDX,
+ MAC_ADDR_MR, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ *value++ = ql_read32(qdev, MAC_ADDR_DATA);
+ }
+ break;
+ }
+ case MAC_ADDR_TYPE_VLAN:
+ case MAC_ADDR_TYPE_MULTI_FLTR:
+ default:
+ QPRINTK(qdev, IFUP, CRIT,
+ "Address type %d not yet supported.\n", type);
+ status = -EPERM;
+ }
+exit:
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+ return status;
+}
+
+/* Set up a MAC, multicast or VLAN address for the
+ * inbound frame matching.
+ */
+static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
+ u16 index)
+{
+ u32 offset = 0;
+ int status = 0;
+
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return status;
+ switch (type) {
+ case MAC_ADDR_TYPE_MULTI_MAC:
+ case MAC_ADDR_TYPE_CAM_MAC:
+ {
+ u32 cam_output;
+ u32 upper = (addr[0] << 8) | addr[1];
+ u32 lower =
+ (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
+ (addr[5]);
+
+ QPRINTK(qdev, IFUP, INFO,
+ "Adding %s address %02x:%02x:%02x:%02x:%02x:%02x"
+ " at index %d in the CAM.\n",
+ ((type ==
+ MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" :
+ "UNICAST"), addr[0], addr[1], addr[2], addr[3],
+ addr[4], addr[5], index);
+
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ type); /* type */
+ ql_write32(qdev, MAC_ADDR_DATA, lower);
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ type); /* type */
+ ql_write32(qdev, MAC_ADDR_DATA, upper);
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ type); /* type */
+ /* This field should also include the queue id
+ and possibly the function id. Right now we hardcode
+ the route field to NIC core.
+ */
+ if (type == MAC_ADDR_TYPE_CAM_MAC) {
+ cam_output = (CAM_OUT_ROUTE_NIC |
+ (qdev->
+ func << CAM_OUT_FUNC_SHIFT) |
+ (qdev->
+ rss_ring_first_cq_id <<
+ CAM_OUT_CQ_ID_SHIFT));
+ if (qdev->vlgrp)
+ cam_output |= CAM_OUT_RV;
+ /* route to NIC core */
+ ql_write32(qdev, MAC_ADDR_DATA, cam_output);
+ }
+ break;
+ }
+ case MAC_ADDR_TYPE_VLAN:
+ {
+ u32 enable_bit = *((u32 *) &addr[0]);
+ /* For VLAN, the addr actually holds a bit that
+ * either enables or disables the vlan id we are
+ * addressing. It's either MAC_ADDR_E on or off.
+ * That's bit-27 we're talking about.
+ */
+ QPRINTK(qdev, IFUP, INFO, "%s VLAN ID %d %s the CAM.\n",
+ (enable_bit ? "Adding" : "Removing"),
+ index, (enable_bit ? "to" : "from"));
+
+ status =
+ ql_wait_reg_rdy(qdev,
+ MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ if (status)
+ goto exit;
+ ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */
+ (index << MAC_ADDR_IDX_SHIFT) | /* index */
+ type | /* type */
+ enable_bit); /* enable/disable */
+ break;
+ }
+ case MAC_ADDR_TYPE_MULTI_FLTR:
+ default:
+ QPRINTK(qdev, IFUP, CRIT,
+ "Address type %d not yet supported.\n", type);
+ status = -EPERM;
+ }
+exit:
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+ return status;
+}
+
+/* Get a specific frame routing value from the CAM.
+ * Used for debug and reg dump.
+ */
+int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value)
+{
+ int status = 0;
+
+ status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
+ if (status)
+ goto exit;
+
+ status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, RT_IDX_E);
+ if (status)
+ goto exit;
+
+ ql_write32(qdev, RT_IDX,
+ RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT));
+ status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, RT_IDX_E);
+ if (status)
+ goto exit;
+ *value = ql_read32(qdev, RT_DATA);
+exit:
+ ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
+ return status;
+}
+
+/* The NIC function for this chip has 16 routing indexes. Each one can be used
+ * to route different frame types to various inbound queues. We send broadcast/
+ * multicast/error frames to the default queue for slow handling,
+ * and CAM hit/RSS frames to the fast handling queues.
+ */
+static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask,
+ int enable)
+{
+ int status;
+ u32 value = 0;
+
+ status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
+ if (status)
+ return status;
+
+ QPRINTK(qdev, IFUP, DEBUG,
+ "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s mask %s the routing reg.\n",
+ (enable ? "Adding" : "Removing"),
+ ((index == RT_IDX_ALL_ERR_SLOT) ? "MAC ERROR/ALL ERROR" : ""),
+ ((index == RT_IDX_IP_CSUM_ERR_SLOT) ? "IP CSUM ERROR" : ""),
+ ((index ==
+ RT_IDX_TCP_UDP_CSUM_ERR_SLOT) ? "TCP/UDP CSUM ERROR" : ""),
+ ((index == RT_IDX_BCAST_SLOT) ? "BROADCAST" : ""),
+ ((index == RT_IDX_MCAST_MATCH_SLOT) ? "MULTICAST MATCH" : ""),
+ ((index == RT_IDX_ALLMULTI_SLOT) ? "ALL MULTICAST MATCH" : ""),
+ ((index == RT_IDX_UNUSED6_SLOT) ? "UNUSED6" : ""),
+ ((index == RT_IDX_UNUSED7_SLOT) ? "UNUSED7" : ""),
+ ((index == RT_IDX_RSS_MATCH_SLOT) ? "RSS ALL/IPV4 MATCH" : ""),
+ ((index == RT_IDX_RSS_IPV6_SLOT) ? "RSS IPV6" : ""),
+ ((index == RT_IDX_RSS_TCP4_SLOT) ? "RSS TCP4" : ""),
+ ((index == RT_IDX_RSS_TCP6_SLOT) ? "RSS TCP6" : ""),
+ ((index == RT_IDX_CAM_HIT_SLOT) ? "CAM HIT" : ""),
+ ((index == RT_IDX_UNUSED013) ? "UNUSED13" : ""),
+ ((index == RT_IDX_UNUSED014) ? "UNUSED14" : ""),
+ ((index == RT_IDX_PROMISCUOUS_SLOT) ? "PROMISCUOUS" : ""),
+ (enable ? "to" : "from"));
+
+ switch (mask) {
+ case RT_IDX_CAM_HIT:
+ {
+ value = RT_IDX_DST_CAM_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_CAM_HIT_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_VALID: /* Promiscuous Mode frames. */
+ {
+ value = RT_IDX_DST_DFLT_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_PROMISCUOUS_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_ERR: /* Pass up MAC,IP,TCP/UDP error frames. */
+ {
+ value = RT_IDX_DST_DFLT_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_ALL_ERR_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_BCAST: /* Pass up Broadcast frames to default Q. */
+ {
+ value = RT_IDX_DST_DFLT_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_BCAST_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_MCAST: /* Pass up All Multicast frames. */
+ {
+ value = RT_IDX_DST_CAM_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_MCAST_MATCH: /* Pass up matched Multicast frames. */
+ {
+ value = RT_IDX_DST_CAM_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case RT_IDX_RSS_MATCH: /* Pass up matched RSS frames. */
+ {
+ value = RT_IDX_DST_RSS | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (RT_IDX_RSS_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ case 0: /* Clear the E-bit on an entry. */
+ {
+ value = RT_IDX_DST_DFLT_Q | /* dest */
+ RT_IDX_TYPE_NICQ | /* type */
+ (index << RT_IDX_IDX_SHIFT);/* index */
+ break;
+ }
+ default:
+ QPRINTK(qdev, IFUP, ERR, "Mask type %d not yet supported.\n",
+ mask);
+ status = -EPERM;
+ goto exit;
+ }
+
+ if (value) {
+ status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0);
+ if (status)
+ goto exit;
+ value |= (enable ? RT_IDX_E : 0);
+ ql_write32(qdev, RT_IDX, value);
+ ql_write32(qdev, RT_DATA, enable ? mask : 0);
+ }
+exit:
+ ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
+ return status;
+}
+
+static void ql_enable_interrupts(struct ql_adapter *qdev)
+{
+ ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16) | INTR_EN_EI);
+}
+
+static void ql_disable_interrupts(struct ql_adapter *qdev)
+{
+ ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16));
+}
+
+/* If we're running with multiple MSI-X vectors then we enable on the fly.
+ * Otherwise, we may have multiple outstanding workers and don't want to
+ * enable until the last one finishes. In this case, the irq_cnt gets
+ * incremented everytime we queue a worker and decremented everytime
+ * a worker finishes. Once it hits zero we enable the interrupt.
+ */
+void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+{
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
+ ql_write32(qdev, INTR_EN,
+ qdev->intr_context[intr].intr_en_mask);
+ else {
+ if (qdev->legacy_check)
+ spin_lock(&qdev->legacy_lock);
+ if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) {
+ QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n",
+ intr);
+ ql_write32(qdev, INTR_EN,
+ qdev->intr_context[intr].intr_en_mask);
+ } else {
+ QPRINTK(qdev, INTR, ERR,
+ "Skip enable, other queue(s) are active.\n");
+ }
+ if (qdev->legacy_check)
+ spin_unlock(&qdev->legacy_lock);
+ }
+}
+
+static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+{
+ u32 var = 0;
+
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
+ goto exit;
+ else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) {
+ ql_write32(qdev, INTR_EN,
+ qdev->intr_context[intr].intr_dis_mask);
+ var = ql_read32(qdev, STS);
+ }
+ atomic_inc(&qdev->intr_context[intr].irq_cnt);
+exit:
+ return var;
+}
+
+static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
+{
+ int i;
+ for (i = 0; i < qdev->intr_count; i++) {
+ /* The enable call does a atomic_dec_and_test
+ * and enables only if the result is zero.
+ * So we precharge it here.
+ */
+ atomic_set(&qdev->intr_context[i].irq_cnt, 1);
+ ql_enable_completion_interrupt(qdev, i);
+ }
+
+}
+
+int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
+{
+ int status = 0;
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev,
+ FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR);
+ if (status)
+ goto exit;
+ /* set up for reg read */
+ ql_write32(qdev, FLASH_ADDR, FLASH_ADDR_R | offset);
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev,
+ FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR);
+ if (status)
+ goto exit;
+ /* get the data */
+ *data = ql_read32(qdev, FLASH_DATA);
+exit:
+ return status;
+}
+
+static int ql_get_flash_params(struct ql_adapter *qdev)
+{
+ int i;
+ int status;
+ u32 *p = (u32 *)&qdev->flash;
+
+ if (ql_sem_spinlock(qdev, SEM_FLASH_MASK))
+ return -ETIMEDOUT;
+
+ for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) {
+ status = ql_read_flash_word(qdev, i, p);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n");
+ goto exit;
+ }
+
+ }
+exit:
+ ql_sem_unlock(qdev, SEM_FLASH_MASK);
+ return status;
+}
+
+/* xgmac register are located behind the xgmac_addr and xgmac_data
+ * register pair. Each read/write requires us to wait for the ready
+ * bit before reading/writing the data.
+ */
+static int ql_write_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 data)
+{
+ int status;
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev,
+ XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+ if (status)
+ return status;
+ /* write the data to the data reg */
+ ql_write32(qdev, XGMAC_DATA, data);
+ /* trigger the write */
+ ql_write32(qdev, XGMAC_ADDR, reg);
+ return status;
+}
+
+/* xgmac register are located behind the xgmac_addr and xgmac_data
+ * register pair. Each read/write requires us to wait for the ready
+ * bit before reading/writing the data.
+ */
+int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
+{
+ int status = 0;
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev,
+ XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+ if (status)
+ goto exit;
+ /* set up for reg read */
+ ql_write32(qdev, XGMAC_ADDR, reg | XGMAC_ADDR_R);
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev,
+ XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+ if (status)
+ goto exit;
+ /* get the data */
+ *data = ql_read32(qdev, XGMAC_DATA);
+exit:
+ return status;
+}
+
+/* This is used for reading the 64-bit statistics regs. */
+int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data)
+{
+ int status = 0;
+ u32 hi = 0;
+ u32 lo = 0;
+
+ status = ql_read_xgmac_reg(qdev, reg, &lo);
+ if (status)
+ goto exit;
+
+ status = ql_read_xgmac_reg(qdev, reg + 4, &hi);
+ if (status)
+ goto exit;
+
+ *data = (u64) lo | ((u64) hi << 32);
+
+exit:
+ return status;
+}
+
+/* Take the MAC Core out of reset.
+ * Enable statistics counting.
+ * Take the transmitter/receiver out of reset.
+ * This functionality may be done in the MPI firmware at a
+ * later date.
+ */
+static int ql_port_initialize(struct ql_adapter *qdev)
+{
+ int status = 0;
+ u32 data;
+
+ if (ql_sem_trylock(qdev, qdev->xg_sem_mask)) {
+ /* Another function has the semaphore, so
+ * wait for the port init bit to come ready.
+ */
+ QPRINTK(qdev, LINK, INFO,
+ "Another function has the semaphore, so wait for the port init bit to come ready.\n");
+ status = ql_wait_reg_rdy(qdev, STS, qdev->port_init, 0);
+ if (status) {
+ QPRINTK(qdev, LINK, CRIT,
+ "Port initialize timed out.\n");
+ }
+ return status;
+ }
+
+ QPRINTK(qdev, LINK, INFO, "Got xgmac semaphore!.\n");
+ /* Set the core reset. */
+ status = ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data);
+ if (status)
+ goto end;
+ data |= GLOBAL_CFG_RESET;
+ status = ql_write_xgmac_reg(qdev, GLOBAL_CFG, data);
+ if (status)
+ goto end;
+
+ /* Clear the core reset and turn on jumbo for receiver. */
+ data &= ~GLOBAL_CFG_RESET; /* Clear core reset. */
+ data |= GLOBAL_CFG_JUMBO; /* Turn on jumbo. */
+ data |= GLOBAL_CFG_TX_STAT_EN;
+ data |= GLOBAL_CFG_RX_STAT_EN;
+ status = ql_write_xgmac_reg(qdev, GLOBAL_CFG, data);
+ if (status)
+ goto end;
+
+ /* Enable transmitter, and clear it's reset. */
+ status = ql_read_xgmac_reg(qdev, TX_CFG, &data);
+ if (status)
+ goto end;
+ data &= ~TX_CFG_RESET; /* Clear the TX MAC reset. */
+ data |= TX_CFG_EN; /* Enable the transmitter. */
+ status = ql_write_xgmac_reg(qdev, TX_CFG, data);
+ if (status)
+ goto end;
+
+ /* Enable receiver and clear it's reset. */
+ status = ql_read_xgmac_reg(qdev, RX_CFG, &data);
+ if (status)
+ goto end;
+ data &= ~RX_CFG_RESET; /* Clear the RX MAC reset. */
+ data |= RX_CFG_EN; /* Enable the receiver. */
+ status = ql_write_xgmac_reg(qdev, RX_CFG, data);
+ if (status)
+ goto end;
+
+ /* Turn on jumbo. */
+ status =
+ ql_write_xgmac_reg(qdev, MAC_TX_PARAMS, MAC_TX_PARAMS_JUMBO | (0x2580 << 16));
+ if (status)
+ goto end;
+ status =
+ ql_write_xgmac_reg(qdev, MAC_RX_PARAMS, 0x2580);
+ if (status)
+ goto end;
+
+ /* Signal to the world that the port is enabled. */
+ ql_write32(qdev, STS, ((qdev->port_init << 16) | qdev->port_init));
+end:
+ ql_sem_unlock(qdev, qdev->xg_sem_mask);
+ return status;
+}
+
+/* Get the next large buffer. */
+struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
+{
+ struct bq_desc *lbq_desc = &rx_ring->lbq[rx_ring->lbq_curr_idx];
+ rx_ring->lbq_curr_idx++;
+ if (rx_ring->lbq_curr_idx == rx_ring->lbq_len)
+ rx_ring->lbq_curr_idx = 0;
+ rx_ring->lbq_free_cnt++;
+ return lbq_desc;
+}
+
+/* Get the next small buffer. */
+struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
+{
+ struct bq_desc *sbq_desc = &rx_ring->sbq[rx_ring->sbq_curr_idx];
+ rx_ring->sbq_curr_idx++;
+ if (rx_ring->sbq_curr_idx == rx_ring->sbq_len)
+ rx_ring->sbq_curr_idx = 0;
+ rx_ring->sbq_free_cnt++;
+ return sbq_desc;
+}
+
+/* Update an rx ring index. */
+static void ql_update_cq(struct rx_ring *rx_ring)
+{
+ rx_ring->cnsmr_idx++;
+ rx_ring->curr_entry++;
+ if (unlikely(rx_ring->cnsmr_idx == rx_ring->cq_len)) {
+ rx_ring->cnsmr_idx = 0;
+ rx_ring->curr_entry = rx_ring->cq_base;
+ }
+}
+
+static void ql_write_cq_idx(struct rx_ring *rx_ring)
+{
+ ql_write_db_reg(rx_ring->cnsmr_idx, rx_ring->cnsmr_idx_db_reg);
+}
+
+/* Process (refill) a large buffer queue. */
+static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+{
+ int clean_idx = rx_ring->lbq_clean_idx;
+ struct bq_desc *lbq_desc;
+ struct bq_element *bq;
+ u64 map;
+ int i;
+
+ while (rx_ring->lbq_free_cnt > 16) {
+ for (i = 0; i < 16; i++) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "lbq: try cleaning clean_idx = %d.\n",
+ clean_idx);
+ lbq_desc = &rx_ring->lbq[clean_idx];
+ bq = lbq_desc->bq;
+ if (lbq_desc->p.lbq_page == NULL) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "lbq: getting new page for index %d.\n",
+ lbq_desc->index);
+ lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC);
+ if (lbq_desc->p.lbq_page == NULL) {
+ QPRINTK(qdev, RX_STATUS, ERR,
+ "Couldn't get a page.\n");
+ return;
+ }
+ map = pci_map_page(qdev->pdev,
+ lbq_desc->p.lbq_page,
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(qdev->pdev, map)) {
+ QPRINTK(qdev, RX_STATUS, ERR,
+ "PCI mapping failed.\n");
+ return;
+ }
+ pci_unmap_addr_set(lbq_desc, mapaddr, map);
+ pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
+ bq->addr_lo = /*lbq_desc->addr_lo = */
+ cpu_to_le32(map);
+ bq->addr_hi = /*lbq_desc->addr_hi = */
+ cpu_to_le32(map >> 32);
+ }
+ clean_idx++;
+ if (clean_idx == rx_ring->lbq_len)
+ clean_idx = 0;
+ }
+
+ rx_ring->lbq_clean_idx = clean_idx;
+ rx_ring->lbq_prod_idx += 16;
+ if (rx_ring->lbq_prod_idx == rx_ring->lbq_len)
+ rx_ring->lbq_prod_idx = 0;
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "lbq: updating prod idx = %d.\n",
+ rx_ring->lbq_prod_idx);
+ ql_write_db_reg(rx_ring->lbq_prod_idx,
+ rx_ring->lbq_prod_idx_db_reg);
+ rx_ring->lbq_free_cnt -= 16;
+ }
+}
+
+/* Process (refill) a small buffer queue. */
+static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+{
+ int clean_idx = rx_ring->sbq_clean_idx;
+ struct bq_desc *sbq_desc;
+ struct bq_element *bq;
+ u64 map;
+ int i;
+
+ while (rx_ring->sbq_free_cnt > 16) {
+ for (i = 0; i < 16; i++) {
+ sbq_desc = &rx_ring->sbq[clean_idx];
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "sbq: try cleaning clean_idx = %d.\n",
+ clean_idx);
+ bq = sbq_desc->bq;
+ if (sbq_desc->p.skb == NULL) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "sbq: getting new skb for index %d.\n",
+ sbq_desc->index);
+ sbq_desc->p.skb =
+ netdev_alloc_skb(qdev->ndev,
+ rx_ring->sbq_buf_size);
+ if (sbq_desc->p.skb == NULL) {
+ QPRINTK(qdev, PROBE, ERR,
+ "Couldn't get an skb.\n");
+ rx_ring->sbq_clean_idx = clean_idx;
+ return;
+ }
+ skb_reserve(sbq_desc->p.skb, QLGE_SB_PAD);
+ map = pci_map_single(qdev->pdev,
+ sbq_desc->p.skb->data,
+ rx_ring->sbq_buf_size /
+ 2, PCI_DMA_FROMDEVICE);
+ pci_unmap_addr_set(sbq_desc, mapaddr, map);
+ pci_unmap_len_set(sbq_desc, maplen,
+ rx_ring->sbq_buf_size / 2);
+ bq->addr_lo = cpu_to_le32(map);
+ bq->addr_hi = cpu_to_le32(map >> 32);
+ }
+
+ clean_idx++;
+ if (clean_idx == rx_ring->sbq_len)
+ clean_idx = 0;
+ }
+ rx_ring->sbq_clean_idx = clean_idx;
+ rx_ring->sbq_prod_idx += 16;
+ if (rx_ring->sbq_prod_idx == rx_ring->sbq_len)
+ rx_ring->sbq_prod_idx = 0;
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "sbq: updating prod idx = %d.\n",
+ rx_ring->sbq_prod_idx);
+ ql_write_db_reg(rx_ring->sbq_prod_idx,
+ rx_ring->sbq_prod_idx_db_reg);
+
+ rx_ring->sbq_free_cnt -= 16;
+ }
+}
+
+static void ql_update_buffer_queues(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
+{
+ ql_update_sbq(qdev, rx_ring);
+ ql_update_lbq(qdev, rx_ring);
+}
+
+/* Unmaps tx buffers. Can be called from send() if a pci mapping
+ * fails at some stage, or from the interrupt when a tx completes.
+ */
+static void ql_unmap_send(struct ql_adapter *qdev,
+ struct tx_ring_desc *tx_ring_desc, int mapped)
+{
+ int i;
+ for (i = 0; i < mapped; i++) {
+ if (i == 0 || (i == 7 && mapped > 7)) {
+ /*
+ * Unmap the skb->data area, or the
+ * external sglist (AKA the Outbound
+ * Address List (OAL)).
+ * If its the zeroeth element, then it's
+ * the skb->data area. If it's the 7th
+ * element and there is more than 6 frags,
+ * then its an OAL.
+ */
+ if (i == 7) {
+ QPRINTK(qdev, TX_DONE, DEBUG,
+ "unmapping OAL area.\n");
+ }
+ pci_unmap_single(qdev->pdev,
+ pci_unmap_addr(&tx_ring_desc->map[i],
+ mapaddr),
+ pci_unmap_len(&tx_ring_desc->map[i],
+ maplen),
+ PCI_DMA_TODEVICE);
+ } else {
+ QPRINTK(qdev, TX_DONE, DEBUG, "unmapping frag %d.\n",
+ i);
+ pci_unmap_page(qdev->pdev,
+ pci_unmap_addr(&tx_ring_desc->map[i],
+ mapaddr),
+ pci_unmap_len(&tx_ring_desc->map[i],
+ maplen), PCI_DMA_TODEVICE);
+ }
+ }
+
+}
+
+/* Map the buffers for this transmit. This will return
+ * NETDEV_TX_BUSY or NETDEV_TX_OK based on success.
+ */
+static int ql_map_send(struct ql_adapter *qdev,
+ struct ob_mac_iocb_req *mac_iocb_ptr,
+ struct sk_buff *skb, struct tx_ring_desc *tx_ring_desc)
+{
+ int len = skb_headlen(skb);
+ dma_addr_t map;
+ int frag_idx, err, map_idx = 0;
+ struct tx_buf_desc *tbd = mac_iocb_ptr->tbd;
+ int frag_cnt = skb_shinfo(skb)->nr_frags;
+
+ if (frag_cnt) {
+ QPRINTK(qdev, TX_QUEUED, DEBUG, "frag_cnt = %d.\n", frag_cnt);
+ }
+ /*
+ * Map the skb buffer first.
+ */
+ map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+ err = pci_dma_mapping_error(qdev->pdev, map);
+ if (err) {
+ QPRINTK(qdev, TX_QUEUED, ERR,
+ "PCI mapping failed with error: %d\n", err);
+
+ return NETDEV_TX_BUSY;
+ }
+
+ tbd->len = cpu_to_le32(len);
+ tbd->addr = cpu_to_le64(map);
+ pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, map);
+ pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen, len);
+ map_idx++;
+
+ /*
+ * This loop fills the remainder of the 8 address descriptors
+ * in the IOCB. If there are more than 7 fragments, then the
+ * eighth address desc will point to an external list (OAL).
+ * When this happens, the remainder of the frags will be stored
+ * in this list.
+ */
+ for (frag_idx = 0; frag_idx < frag_cnt; frag_idx++, map_idx++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_idx];
+ tbd++;
+ if (frag_idx == 6 && frag_cnt > 7) {
+ /* Let's tack on an sglist.
+ * Our control block will now
+ * look like this:
+ * iocb->seg[0] = skb->data
+ * iocb->seg[1] = frag[0]
+ * iocb->seg[2] = frag[1]
+ * iocb->seg[3] = frag[2]
+ * iocb->seg[4] = frag[3]
+ * iocb->seg[5] = frag[4]
+ * iocb->seg[6] = frag[5]
+ * iocb->seg[7] = ptr to OAL (external sglist)
+ * oal->seg[0] = frag[6]
+ * oal->seg[1] = frag[7]
+ * oal->seg[2] = frag[8]
+ * oal->seg[3] = frag[9]
+ * oal->seg[4] = frag[10]
+ * etc...
+ */
+ /* Tack on the OAL in the eighth segment of IOCB. */
+ map = pci_map_single(qdev->pdev, &tx_ring_desc->oal,
+ sizeof(struct oal),
+ PCI_DMA_TODEVICE);
+ err = pci_dma_mapping_error(qdev->pdev, map);
+ if (err) {
+ QPRINTK(qdev, TX_QUEUED, ERR,
+ "PCI mapping outbound address list with error: %d\n",
+ err);
+ goto map_error;
+ }
+
+ tbd->addr = cpu_to_le64(map);
+ /*
+ * The length is the number of fragments
+ * that remain to be mapped times the length
+ * of our sglist (OAL).
+ */
+ tbd->len =
+ cpu_to_le32((sizeof(struct tx_buf_desc) *
+ (frag_cnt - frag_idx)) | TX_DESC_C);
+ pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr,
+ map);
+ pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen,
+ sizeof(struct oal));
+ tbd = (struct tx_buf_desc *)&tx_ring_desc->oal;
+ map_idx++;
+ }
+
+ map =
+ pci_map_page(qdev->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+
+ err = pci_dma_mapping_error(qdev->pdev, map);
+ if (err) {
+ QPRINTK(qdev, TX_QUEUED, ERR,
+ "PCI mapping frags failed with error: %d.\n",
+ err);
+ goto map_error;
+ }
+
+ tbd->addr = cpu_to_le64(map);
+ tbd->len = cpu_to_le32(frag->size);
+ pci_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, map);
+ pci_unmap_len_set(&tx_ring_desc->map[map_idx], maplen,
+ frag->size);
+
+ }
+ /* Save the number of segments we've mapped. */
+ tx_ring_desc->map_cnt = map_idx;
+ /* Terminate the last segment. */
+ tbd->len = cpu_to_le32(le32_to_cpu(tbd->len) | TX_DESC_E);
+ return NETDEV_TX_OK;
+
+map_error:
+ /*
+ * If the first frag mapping failed, then i will be zero.
+ * This causes the unmap of the skb->data area. Otherwise
+ * we pass in the number of frags that mapped successfully
+ * so they can be umapped.
+ */
+ ql_unmap_send(qdev, tx_ring_desc, map_idx);
+ return NETDEV_TX_BUSY;
+}
+
+void ql_realign_skb(struct sk_buff *skb, int len)
+{
+ void *temp_addr = skb->data;
+
+ /* Undo the skb_reserve(skb,32) we did before
+ * giving to hardware, and realign data on
+ * a 2-byte boundary.
+ */
+ skb->data -= QLGE_SB_PAD - NET_IP_ALIGN;
+ skb->tail -= QLGE_SB_PAD - NET_IP_ALIGN;
+ skb_copy_to_linear_data(skb, temp_addr,
+ (unsigned int)len);
+}
+
+/*
+ * This function builds an skb for the given inbound
+ * completion. It will be rewritten for readability in the near
+ * future, but for not it works well.
+ */
+static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring,
+ struct ib_mac_iocb_rsp *ib_mac_rsp)
+{
+ struct bq_desc *lbq_desc;
+ struct bq_desc *sbq_desc;
+ struct sk_buff *skb = NULL;
+ u32 length = le32_to_cpu(ib_mac_rsp->data_len);
+ u32 hdr_len = le32_to_cpu(ib_mac_rsp->hdr_len);
+
+ /*
+ * Handle the header buffer if present.
+ */
+ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV &&
+ ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) {
+ QPRINTK(qdev, RX_STATUS, DEBUG, "Header of %d bytes in small buffer.\n", hdr_len);
+ /*
+ * Headers fit nicely into a small buffer.
+ */
+ sbq_desc = ql_get_curr_sbuf(rx_ring);
+ pci_unmap_single(qdev->pdev,
+ pci_unmap_addr(sbq_desc, mapaddr),
+ pci_unmap_len(sbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+ skb = sbq_desc->p.skb;
+ ql_realign_skb(skb, hdr_len);
+ skb_put(skb, hdr_len);
+ sbq_desc->p.skb = NULL;
+ }
+
+ /*
+ * Handle the data buffer(s).
+ */
+ if (unlikely(!length)) { /* Is there data too? */
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "No Data buffer in this packet.\n");
+ return skb;
+ }
+
+ if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) {
+ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Headers in small, data of %d bytes in small, combine them.\n", length);
+ /*
+ * Data is less than small buffer size so it's
+ * stuffed in a small buffer.
+ * For this case we append the data
+ * from the "data" small buffer to the "header" small
+ * buffer.
+ */
+ sbq_desc = ql_get_curr_sbuf(rx_ring);
+ pci_dma_sync_single_for_cpu(qdev->pdev,
+ pci_unmap_addr
+ (sbq_desc, mapaddr),
+ pci_unmap_len
+ (sbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb_put(skb, length),
+ sbq_desc->p.skb->data, length);
+ pci_dma_sync_single_for_device(qdev->pdev,
+ pci_unmap_addr
+ (sbq_desc,
+ mapaddr),
+ pci_unmap_len
+ (sbq_desc,
+ maplen),
+ PCI_DMA_FROMDEVICE);
+ } else {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "%d bytes in a single small buffer.\n", length);
+ sbq_desc = ql_get_curr_sbuf(rx_ring);
+ skb = sbq_desc->p.skb;
+ ql_realign_skb(skb, length);
+ skb_put(skb, length);
+ pci_unmap_single(qdev->pdev,
+ pci_unmap_addr(sbq_desc,
+ mapaddr),
+ pci_unmap_len(sbq_desc,
+ maplen),
+ PCI_DMA_FROMDEVICE);
+ sbq_desc->p.skb = NULL;
+ }
+ } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) {
+ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Header in small, %d bytes in large. Chain large to small!\n", length);
+ /*
+ * The data is in a single large buffer. We
+ * chain it to the header buffer's skb and let
+ * it rip.
+ */
+ lbq_desc = ql_get_curr_lbuf(rx_ring);
+ pci_unmap_page(qdev->pdev,
+ pci_unmap_addr(lbq_desc,
+ mapaddr),
+ pci_unmap_len(lbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Chaining page to skb.\n");
+ skb_fill_page_desc(skb, 0, lbq_desc->p.lbq_page,
+ 0, length);
+ skb->len += length;
+ skb->data_len += length;
+ skb->truesize += length;
+ lbq_desc->p.lbq_page = NULL;
+ } else {
+ /*
+ * The headers and data are in a single large buffer. We
+ * copy it to a new skb and let it go. This can happen with
+ * jumbo mtu on a non-TCP/UDP frame.
+ */
+ lbq_desc = ql_get_curr_lbuf(rx_ring);
+ skb = netdev_alloc_skb(qdev->ndev, length);
+ if (skb == NULL) {
+ QPRINTK(qdev, PROBE, DEBUG,
+ "No skb available, drop the packet.\n");
+ return NULL;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length);
+ skb_fill_page_desc(skb, 0, lbq_desc->p.lbq_page,
+ 0, length);
+ skb->len += length;
+ skb->data_len += length;
+ skb->truesize += length;
+ length -= length;
+ lbq_desc->p.lbq_page = NULL;
+ __pskb_pull_tail(skb,
+ (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ?
+ VLAN_ETH_HLEN : ETH_HLEN);
+ }
+ } else {
+ /*
+ * The data is in a chain of large buffers
+ * pointed to by a small buffer. We loop
+ * thru and chain them to the our small header
+ * buffer's skb.
+ * frags: There are 18 max frags and our small
+ * buffer will hold 32 of them. The thing is,
+ * we'll use 3 max for our 9000 byte jumbo
+ * frames. If the MTU goes up we could
+ * eventually be in trouble.
+ */
+ int size, offset, i = 0;
+ struct bq_element *bq, bq_array[8];
+ sbq_desc = ql_get_curr_sbuf(rx_ring);
+ pci_unmap_single(qdev->pdev,
+ pci_unmap_addr(sbq_desc, mapaddr),
+ pci_unmap_len(sbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+ if (!(ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS)) {
+ /*
+ * This is an non TCP/UDP IP frame, so
+ * the headers aren't split into a small
+ * buffer. We have to use the small buffer
+ * that contains our sg list as our skb to
+ * send upstairs. Copy the sg list here to
+ * a local buffer and use it to find the
+ * pages to chain.
+ */
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "%d bytes of headers & data in chain of large.\n", length);
+ skb = sbq_desc->p.skb;
+ bq = &bq_array[0];
+ memcpy(bq, skb->data, sizeof(bq_array));
+ sbq_desc->p.skb = NULL;
+ skb_reserve(skb, NET_IP_ALIGN);
+ } else {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Headers in small, %d bytes of data in chain of large.\n", length);
+ bq = (struct bq_element *)sbq_desc->p.skb->data;
+ }
+ while (length > 0) {
+ lbq_desc = ql_get_curr_lbuf(rx_ring);
+ if ((bq->addr_lo & ~BQ_MASK) != lbq_desc->bq->addr_lo) {
+ QPRINTK(qdev, RX_STATUS, ERR,
+ "Panic!!! bad large buffer address, expected 0x%.08x, got 0x%.08x.\n",
+ lbq_desc->bq->addr_lo, bq->addr_lo);
+ return NULL;
+ }
+ pci_unmap_page(qdev->pdev,
+ pci_unmap_addr(lbq_desc,
+ mapaddr),
+ pci_unmap_len(lbq_desc,
+ maplen),
+ PCI_DMA_FROMDEVICE);
+ size = (length < PAGE_SIZE) ? length : PAGE_SIZE;
+ offset = 0;
+
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Adding page %d to skb for %d bytes.\n",
+ i, size);
+ skb_fill_page_desc(skb, i, lbq_desc->p.lbq_page,
+ offset, size);
+ skb->len += size;
+ skb->data_len += size;
+ skb->truesize += size;
+ length -= size;
+ lbq_desc->p.lbq_page = NULL;
+ bq++;
+ i++;
+ }
+ __pskb_pull_tail(skb, (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ?
+ VLAN_ETH_HLEN : ETH_HLEN);
+ }
+ return skb;
+}
+
+/* Process an inbound completion from an rx ring. */
+static void ql_process_mac_rx_intr(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring,
+ struct ib_mac_iocb_rsp *ib_mac_rsp)
+{
+ struct net_device *ndev = qdev->ndev;
+ struct sk_buff *skb = NULL;
+
+ QL_DUMP_IB_MAC_RSP(ib_mac_rsp);
+
+ skb = ql_build_rx_skb(qdev, rx_ring, ib_mac_rsp);
+ if (unlikely(!skb)) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "No skb available, drop packet.\n");
+ return;
+ }
+
+ prefetch(skb->data);
+ skb->dev = ndev;
+ if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) {
+ QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_REG ? "Registered" : "",
+ (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) ==
+ IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : "");
+ }
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) {
+ QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n");
+ }
+ if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) {
+ QPRINTK(qdev, RX_STATUS, ERR,
+ "Bad checksum for this %s packet.\n",
+ ((ib_mac_rsp->
+ flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP"));
+ skb->ip_summed = CHECKSUM_NONE;
+ } else if (qdev->rx_csum &&
+ ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) ||
+ ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) &&
+ !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) {
+ QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n");
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ qdev->stats.rx_packets++;
+ qdev->stats.rx_bytes += skb->len;
+ skb->protocol = eth_type_trans(skb, ndev);
+ if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Passing a VLAN packet upstream.\n");
+ vlan_hwaccel_rx(skb, qdev->vlgrp,
+ le16_to_cpu(ib_mac_rsp->vlan_id));
+ } else {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Passing a normal packet upstream.\n");
+ netif_rx(skb);
+ }
+ ndev->last_rx = jiffies;
+}
+
+/* Process an outbound completion from an rx ring. */
+static void ql_process_mac_tx_intr(struct ql_adapter *qdev,
+ struct ob_mac_iocb_rsp *mac_rsp)
+{
+ struct tx_ring *tx_ring;
+ struct tx_ring_desc *tx_ring_desc;
+
+ QL_DUMP_OB_MAC_RSP(mac_rsp);
+ tx_ring = &qdev->tx_ring[mac_rsp->txq_idx];
+ tx_ring_desc = &tx_ring->q[mac_rsp->tid];
+ ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt);
+ qdev->stats.tx_bytes += tx_ring_desc->map_cnt;
+ qdev->stats.tx_packets++;
+ dev_kfree_skb(tx_ring_desc->skb);
+ tx_ring_desc->skb = NULL;
+
+ if (unlikely(mac_rsp->flags1 & (OB_MAC_IOCB_RSP_E |
+ OB_MAC_IOCB_RSP_S |
+ OB_MAC_IOCB_RSP_L |
+ OB_MAC_IOCB_RSP_P | OB_MAC_IOCB_RSP_B))) {
+ if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_E) {
+ QPRINTK(qdev, TX_DONE, WARNING,
+ "Total descriptor length did not match transfer length.\n");
+ }
+ if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_S) {
+ QPRINTK(qdev, TX_DONE, WARNING,
+ "Frame too short to be legal, not sent.\n");
+ }
+ if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_L) {
+ QPRINTK(qdev, TX_DONE, WARNING,
+ "Frame too long, but sent anyway.\n");
+ }
+ if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_B) {
+ QPRINTK(qdev, TX_DONE, WARNING,
+ "PCI backplane error. Frame not sent.\n");
+ }
+ }
+ atomic_inc(&tx_ring->tx_count);
+}
+
+/* Fire up a handler to reset the MPI processor. */
+void ql_queue_fw_error(struct ql_adapter *qdev)
+{
+ netif_stop_queue(qdev->ndev);
+ netif_carrier_off(qdev->ndev);
+ queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0);
+}
+
+void ql_queue_asic_error(struct ql_adapter *qdev)
+{
+ netif_stop_queue(qdev->ndev);
+ netif_carrier_off(qdev->ndev);
+ ql_disable_interrupts(qdev);
+ queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0);
+}
+
+static void ql_process_chip_ae_intr(struct ql_adapter *qdev,
+ struct ib_ae_iocb_rsp *ib_ae_rsp)
+{
+ switch (ib_ae_rsp->event) {
+ case MGMT_ERR_EVENT:
+ QPRINTK(qdev, RX_ERR, ERR,
+ "Management Processor Fatal Error.\n");
+ ql_queue_fw_error(qdev);
+ return;
+
+ case CAM_LOOKUP_ERR_EVENT:
+ QPRINTK(qdev, LINK, ERR,
+ "Multiple CAM hits lookup occurred.\n");
+ QPRINTK(qdev, DRV, ERR, "This event shouldn't occur.\n");
+ ql_queue_asic_error(qdev);
+ return;
+
+ case SOFT_ECC_ERROR_EVENT:
+ QPRINTK(qdev, RX_ERR, ERR, "Soft ECC error detected.\n");
+ ql_queue_asic_error(qdev);
+ break;
+
+ case PCI_ERR_ANON_BUF_RD:
+ QPRINTK(qdev, RX_ERR, ERR,
+ "PCI error occurred when reading anonymous buffers from rx_ring %d.\n",
+ ib_ae_rsp->q_id);
+ ql_queue_asic_error(qdev);
+ break;
+
+ default:
+ QPRINTK(qdev, DRV, ERR, "Unexpected event %d.\n",
+ ib_ae_rsp->event);
+ ql_queue_asic_error(qdev);
+ break;
+ }
+}
+
+static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
+{
+ struct ql_adapter *qdev = rx_ring->qdev;
+ u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+ struct ob_mac_iocb_rsp *net_rsp = NULL;
+ int count = 0;
+
+ /* While there are entries in the completion queue. */
+ while (prod != rx_ring->cnsmr_idx) {
+
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id,
+ prod, rx_ring->cnsmr_idx);
+
+ net_rsp = (struct ob_mac_iocb_rsp *)rx_ring->curr_entry;
+ rmb();
+ switch (net_rsp->opcode) {
+
+ case OPCODE_OB_MAC_TSO_IOCB:
+ case OPCODE_OB_MAC_IOCB:
+ ql_process_mac_tx_intr(qdev, net_rsp);
+ break;
+ default:
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Hit default case, not handled! dropping the packet, opcode = %x.\n",
+ net_rsp->opcode);
+ }
+ count++;
+ ql_update_cq(rx_ring);
+ prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+ }
+ ql_write_cq_idx(rx_ring);
+ if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) {
+ struct tx_ring *tx_ring = &qdev->tx_ring[net_rsp->txq_idx];
+ if (atomic_read(&tx_ring->queue_stopped) &&
+ (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4)))
+ /*
+ * The queue got stopped because the tx_ring was full.
+ * Wake it up, because it's now at least 25% empty.
+ */
+ netif_wake_queue(qdev->ndev);
+ }
+
+ return count;
+}
+
+static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
+{
+ struct ql_adapter *qdev = rx_ring->qdev;
+ u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+ struct ql_net_rsp_iocb *net_rsp;
+ int count = 0;
+
+ /* While there are entries in the completion queue. */
+ while (prod != rx_ring->cnsmr_idx) {
+
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id,
+ prod, rx_ring->cnsmr_idx);
+
+ net_rsp = rx_ring->curr_entry;
+ rmb();
+ switch (net_rsp->opcode) {
+ case OPCODE_IB_MAC_IOCB:
+ ql_process_mac_rx_intr(qdev, rx_ring,
+ (struct ib_mac_iocb_rsp *)
+ net_rsp);
+ break;
+
+ case OPCODE_IB_AE_IOCB:
+ ql_process_chip_ae_intr(qdev, (struct ib_ae_iocb_rsp *)
+ net_rsp);
+ break;
+ default:
+ {
+ QPRINTK(qdev, RX_STATUS, DEBUG,
+ "Hit default case, not handled! dropping the packet, opcode = %x.\n",
+ net_rsp->opcode);
+ }
+ }
+ count++;
+ ql_update_cq(rx_ring);
+ prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+ if (count == budget)
+ break;
+ }
+ ql_update_buffer_queues(qdev, rx_ring);
+ ql_write_cq_idx(rx_ring);
+ return count;
+}
+
+static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
+{
+ struct rx_ring *rx_ring = container_of(napi, struct rx_ring, napi);
+ struct ql_adapter *qdev = rx_ring->qdev;
+ int work_done = ql_clean_inbound_rx_ring(rx_ring, budget);
+
+ QPRINTK(qdev, RX_STATUS, DEBUG, "Enter, NAPI POLL cq_id = %d.\n",
+ rx_ring->cq_id);
+
+ if (work_done < budget) {
+ __netif_rx_complete(qdev->ndev, napi);
+ ql_enable_completion_interrupt(qdev, rx_ring->irq);
+ }
+ return work_done;
+}
+
+static void ql_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ qdev->vlgrp = grp;
+ if (grp) {
+ QPRINTK(qdev, IFUP, DEBUG, "Turning on VLAN in NIC_RCV_CFG.\n");
+ ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
+ NIC_RCV_CFG_VLAN_MATCH_AND_NON);
+ } else {
+ QPRINTK(qdev, IFUP, DEBUG,
+ "Turning off VLAN in NIC_RCV_CFG.\n");
+ ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
+ }
+}
+
+static void ql_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ u32 enable_bit = MAC_ADDR_E;
+
+ spin_lock(&qdev->hw_lock);
+ if (ql_set_mac_addr_reg
+ (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n");
+ }
+ spin_unlock(&qdev->hw_lock);
+}
+
+static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ u32 enable_bit = 0;
+
+ spin_lock(&qdev->hw_lock);
+ if (ql_set_mac_addr_reg
+ (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n");
+ }
+ spin_unlock(&qdev->hw_lock);
+
+}
+
+/* Worker thread to process a given rx_ring that is dedicated
+ * to outbound completions.
+ */
+static void ql_tx_clean(struct work_struct *work)
+{
+ struct rx_ring *rx_ring =
+ container_of(work, struct rx_ring, rx_work.work);
+ ql_clean_outbound_rx_ring(rx_ring);
+ ql_enable_completion_interrupt(rx_ring->qdev, rx_ring->irq);
+
+}
+
+/* Worker thread to process a given rx_ring that is dedicated
+ * to inbound completions.
+ */
+static void ql_rx_clean(struct work_struct *work)
+{
+ struct rx_ring *rx_ring =
+ container_of(work, struct rx_ring, rx_work.work);
+ ql_clean_inbound_rx_ring(rx_ring, 64);
+ ql_enable_completion_interrupt(rx_ring->qdev, rx_ring->irq);
+}
+
+/* MSI-X Multiple Vector Interrupt Handler for outbound completions. */
+static irqreturn_t qlge_msix_tx_isr(int irq, void *dev_id)
+{
+ struct rx_ring *rx_ring = dev_id;
+ queue_delayed_work_on(rx_ring->cpu, rx_ring->qdev->q_workqueue,
+ &rx_ring->rx_work, 0);
+ return IRQ_HANDLED;
+}
+
+/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */
+static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id)
+{
+ struct rx_ring *rx_ring = dev_id;
+ struct ql_adapter *qdev = rx_ring->qdev;
+ netif_rx_schedule(qdev->ndev, &rx_ring->napi);
+ return IRQ_HANDLED;
+}
+
+/* We check here to see if we're already handling a legacy
+ * interrupt. If we are, then it must belong to another
+ * chip with which we're sharing the interrupt line.
+ */
+int ql_legacy_check(struct ql_adapter *qdev)
+{
+ int err;
+ spin_lock(&qdev->legacy_lock);
+ err = atomic_read(&qdev->intr_context[0].irq_cnt);
+ spin_unlock(&qdev->legacy_lock);
+ return err;
+}
+
+/* This handles a fatal error, MPI activity, and the default
+ * rx_ring in an MSI-X multiple vector environment.
+ * In MSI/Legacy environment it also process the rest of
+ * the rx_rings.
+ */
+static irqreturn_t qlge_isr(int irq, void *dev_id)
+{
+ struct rx_ring *rx_ring = dev_id;
+ struct ql_adapter *qdev = rx_ring->qdev;
+ struct intr_context *intr_context = &qdev->intr_context[0];
+ u32 var;
+ int i;
+ int work_done = 0;
+
+ if (qdev->legacy_check && qdev->legacy_check(qdev)) {
+ QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n");
+ return IRQ_NONE; /* Not our interrupt */
+ }
+
+ var = ql_read32(qdev, STS);
+
+ /*
+ * Check for fatal error.
+ */
+ if (var & STS_FE) {
+ ql_queue_asic_error(qdev);
+ QPRINTK(qdev, INTR, ERR, "Got fatal error, STS = %x.\n", var);
+ var = ql_read32(qdev, ERR_STS);
+ QPRINTK(qdev, INTR, ERR,
+ "Resetting chip. Error Status Register = 0x%x\n", var);
+ return IRQ_HANDLED;
+ }
+
+ /*
+ * Check MPI processor activity.
+ */
+ if (var & STS_PI) {
+ /*
+ * We've got an async event or mailbox completion.
+ * Handle it and clear the source of the interrupt.
+ */
+ QPRINTK(qdev, INTR, ERR, "Got MPI processor interrupt.\n");
+ ql_disable_completion_interrupt(qdev, intr_context->intr);
+ queue_delayed_work_on(smp_processor_id(), qdev->workqueue,
+ &qdev->mpi_work, 0);
+ work_done++;
+ }
+
+ /*
+ * Check the default queue and wake handler if active.
+ */
+ rx_ring = &qdev->rx_ring[0];
+ if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
+ QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n");
+ ql_disable_completion_interrupt(qdev, intr_context->intr);
+ queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue,
+ &rx_ring->rx_work, 0);
+ work_done++;
+ }
+
+ if (!test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
+ /*
+ * Start the DPC for each active queue.
+ */
+ for (i = 1; i < qdev->rx_ring_count; i++) {
+ rx_ring = &qdev->rx_ring[i];
+ if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) !=
+ rx_ring->cnsmr_idx) {
+ QPRINTK(qdev, INTR, INFO,
+ "Waking handler for rx_ring[%d].\n", i);
+ ql_disable_completion_interrupt(qdev,
+ intr_context->
+ intr);
+ if (i < qdev->rss_ring_first_cq_id)
+ queue_delayed_work_on(rx_ring->cpu,
+ qdev->q_workqueue,
+ &rx_ring->rx_work,
+ 0);
+ else
+ netif_rx_schedule(qdev->ndev,
+ &rx_ring->napi);
+ work_done++;
+ }
+ }
+ }
+ return work_done ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr)
+{
+
+ if (skb_is_gso(skb)) {
+ int err;
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+ return err;
+ }
+
+ mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB;
+ mac_iocb_ptr->flags3 |= OB_MAC_TSO_IOCB_IC;
+ mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len);
+ mac_iocb_ptr->total_hdrs_len =
+ cpu_to_le16(skb_transport_offset(skb) + tcp_hdrlen(skb));
+ mac_iocb_ptr->net_trans_offset =
+ cpu_to_le16(skb_network_offset(skb) |
+ skb_transport_offset(skb)
+ << OB_MAC_TRANSPORT_HDR_SHIFT);
+ mac_iocb_ptr->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_LSO;
+ if (likely(skb->protocol == htons(ETH_P_IP))) {
+ struct iphdr *iph = ip_hdr(skb);
+ iph->check = 0;
+ mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP6;
+ tcp_hdr(skb)->check =
+ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static void ql_hw_csum_setup(struct sk_buff *skb,
+ struct ob_mac_tso_iocb_req *mac_iocb_ptr)
+{
+ int len;
+ struct iphdr *iph = ip_hdr(skb);
+ u16 *check;
+ mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB;
+ mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len);
+ mac_iocb_ptr->net_trans_offset =
+ cpu_to_le16(skb_network_offset(skb) |
+ skb_transport_offset(skb) << OB_MAC_TRANSPORT_HDR_SHIFT);
+
+ mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4;
+ len = (ntohs(iph->tot_len) - (iph->ihl << 2));
+ if (likely(iph->protocol == IPPROTO_TCP)) {
+ check = &(tcp_hdr(skb)->check);
+ mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_TC;
+ mac_iocb_ptr->total_hdrs_len =
+ cpu_to_le16(skb_transport_offset(skb) +
+ (tcp_hdr(skb)->doff << 2));
+ } else {
+ check = &(udp_hdr(skb)->check);
+ mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_UC;
+ mac_iocb_ptr->total_hdrs_len =
+ cpu_to_le16(skb_transport_offset(skb) +
+ sizeof(struct udphdr));
+ }
+ *check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, len, iph->protocol, 0);
+}
+
+static int qlge_send(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct tx_ring_desc *tx_ring_desc;
+ struct ob_mac_iocb_req *mac_iocb_ptr;
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int tso;
+ struct tx_ring *tx_ring;
+ u32 tx_ring_idx = (u32) QL_TXQ_IDX(qdev, skb);
+
+ tx_ring = &qdev->tx_ring[tx_ring_idx];
+
+ if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) {
+ QPRINTK(qdev, TX_QUEUED, INFO,
+ "%s: shutting down tx queue %d du to lack of resources.\n",
+ __func__, tx_ring_idx);
+ netif_stop_queue(ndev);
+ atomic_inc(&tx_ring->queue_stopped);
+ return NETDEV_TX_BUSY;
+ }
+ tx_ring_desc = &tx_ring->q[tx_ring->prod_idx];
+ mac_iocb_ptr = tx_ring_desc->queue_entry;
+ memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr));
+ if (ql_map_send(qdev, mac_iocb_ptr, skb, tx_ring_desc) != NETDEV_TX_OK) {
+ QPRINTK(qdev, TX_QUEUED, ERR, "Could not map the segments.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB;
+ mac_iocb_ptr->tid = tx_ring_desc->index;
+ /* We use the upper 32-bits to store the tx queue for this IO.
+ * When we get the completion we can use it to establish the context.
+ */
+ mac_iocb_ptr->txq_idx = tx_ring_idx;
+ tx_ring_desc->skb = skb;
+
+ mac_iocb_ptr->frame_len = cpu_to_le16((u16) skb->len);
+
+ if (qdev->vlgrp && vlan_tx_tag_present(skb)) {
+ QPRINTK(qdev, TX_QUEUED, DEBUG, "Adding a vlan tag %d.\n",
+ vlan_tx_tag_get(skb));
+ mac_iocb_ptr->flags3 |= OB_MAC_IOCB_V;
+ mac_iocb_ptr->vlan_tci = cpu_to_le16(vlan_tx_tag_get(skb));
+ }
+ tso = ql_tso(skb, (struct ob_mac_tso_iocb_req *)mac_iocb_ptr);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ } else if (unlikely(!tso) && (skb->ip_summed == CHECKSUM_PARTIAL)) {
+ ql_hw_csum_setup(skb,
+ (struct ob_mac_tso_iocb_req *)mac_iocb_ptr);
+ }
+ QL_DUMP_OB_MAC_IOCB(mac_iocb_ptr);
+ tx_ring->prod_idx++;
+ if (tx_ring->prod_idx == tx_ring->wq_len)
+ tx_ring->prod_idx = 0;
+ wmb();
+
+ ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg);
+ ndev->trans_start = jiffies;
+ QPRINTK(qdev, TX_QUEUED, DEBUG, "tx queued, slot %d, len %d\n",
+ tx_ring->prod_idx, skb->len);
+
+ atomic_dec(&tx_ring->tx_count);
+ return NETDEV_TX_OK;
+}
+
+static void ql_free_shadow_space(struct ql_adapter *qdev)
+{
+ if (qdev->rx_ring_shadow_reg_area) {
+ pci_free_consistent(qdev->pdev,
+ PAGE_SIZE,
+ qdev->rx_ring_shadow_reg_area,
+ qdev->rx_ring_shadow_reg_dma);
+ qdev->rx_ring_shadow_reg_area = NULL;
+ }
+ if (qdev->tx_ring_shadow_reg_area) {
+ pci_free_consistent(qdev->pdev,
+ PAGE_SIZE,
+ qdev->tx_ring_shadow_reg_area,
+ qdev->tx_ring_shadow_reg_dma);
+ qdev->tx_ring_shadow_reg_area = NULL;
+ }
+}
+
+static int ql_alloc_shadow_space(struct ql_adapter *qdev)
+{
+ qdev->rx_ring_shadow_reg_area =
+ pci_alloc_consistent(qdev->pdev,
+ PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma);
+ if (qdev->rx_ring_shadow_reg_area == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Allocation of RX shadow space failed.\n");
+ return -ENOMEM;
+ }
+ qdev->tx_ring_shadow_reg_area =
+ pci_alloc_consistent(qdev->pdev, PAGE_SIZE,
+ &qdev->tx_ring_shadow_reg_dma);
+ if (qdev->tx_ring_shadow_reg_area == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Allocation of TX shadow space failed.\n");
+ goto err_wqp_sh_area;
+ }
+ return 0;
+
+err_wqp_sh_area:
+ pci_free_consistent(qdev->pdev,
+ PAGE_SIZE,
+ qdev->rx_ring_shadow_reg_area,
+ qdev->rx_ring_shadow_reg_dma);
+ return -ENOMEM;
+}
+
+static void ql_init_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
+{
+ struct tx_ring_desc *tx_ring_desc;
+ int i;
+ struct ob_mac_iocb_req *mac_iocb_ptr;
+
+ mac_iocb_ptr = tx_ring->wq_base;
+ tx_ring_desc = tx_ring->q;
+ for (i = 0; i < tx_ring->wq_len; i++) {
+ tx_ring_desc->index = i;
+ tx_ring_desc->skb = NULL;
+ tx_ring_desc->queue_entry = mac_iocb_ptr;
+ mac_iocb_ptr++;
+ tx_ring_desc++;
+ }
+ atomic_set(&tx_ring->tx_count, tx_ring->wq_len);
+ atomic_set(&tx_ring->queue_stopped, 0);
+}
+
+static void ql_free_tx_resources(struct ql_adapter *qdev,
+ struct tx_ring *tx_ring)
+{
+ if (tx_ring->wq_base) {
+ pci_free_consistent(qdev->pdev, tx_ring->wq_size,
+ tx_ring->wq_base, tx_ring->wq_base_dma);
+ tx_ring->wq_base = NULL;
+ }
+ kfree(tx_ring->q);
+ tx_ring->q = NULL;
+}
+
+static int ql_alloc_tx_resources(struct ql_adapter *qdev,
+ struct tx_ring *tx_ring)
+{
+ tx_ring->wq_base =
+ pci_alloc_consistent(qdev->pdev, tx_ring->wq_size,
+ &tx_ring->wq_base_dma);
+
+ if ((tx_ring->wq_base == NULL)
+ || tx_ring->wq_base_dma & (tx_ring->wq_size - 1)) {
+ QPRINTK(qdev, IFUP, ERR, "tx_ring alloc failed.\n");
+ return -ENOMEM;
+ }
+ tx_ring->q =
+ kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL);
+ if (tx_ring->q == NULL)
+ goto err;
+
+ return 0;
+err:
+ pci_free_consistent(qdev->pdev, tx_ring->wq_size,
+ tx_ring->wq_base, tx_ring->wq_base_dma);
+ return -ENOMEM;
+}
+
+void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+{
+ int i;
+ struct bq_desc *lbq_desc;
+
+ for (i = 0; i < rx_ring->lbq_len; i++) {
+ lbq_desc = &rx_ring->lbq[i];
+ if (lbq_desc->p.lbq_page) {
+ pci_unmap_page(qdev->pdev,
+ pci_unmap_addr(lbq_desc, mapaddr),
+ pci_unmap_len(lbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+
+ put_page(lbq_desc->p.lbq_page);
+ lbq_desc->p.lbq_page = NULL;
+ }
+ lbq_desc->bq->addr_lo = 0;
+ lbq_desc->bq->addr_hi = 0;
+ }
+}
+
+/*
+ * Allocate and map a page for each element of the lbq.
+ */
+static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
+{
+ int i;
+ struct bq_desc *lbq_desc;
+ u64 map;
+ struct bq_element *bq = rx_ring->lbq_base;
+
+ for (i = 0; i < rx_ring->lbq_len; i++) {
+ lbq_desc = &rx_ring->lbq[i];
+ memset(lbq_desc, 0, sizeof(lbq_desc));
+ lbq_desc->bq = bq;
+ lbq_desc->index = i;
+ lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC);
+ if (unlikely(!lbq_desc->p.lbq_page)) {
+ QPRINTK(qdev, IFUP, ERR, "failed alloc_page().\n");
+ goto mem_error;
+ } else {
+ map = pci_map_page(qdev->pdev,
+ lbq_desc->p.lbq_page,
+ 0, PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(qdev->pdev, map)) {
+ QPRINTK(qdev, IFUP, ERR,
+ "PCI mapping failed.\n");
+ goto mem_error;
+ }
+ pci_unmap_addr_set(lbq_desc, mapaddr, map);
+ pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
+ bq->addr_lo = cpu_to_le32(map);
+ bq->addr_hi = cpu_to_le32(map >> 32);
+ }
+ bq++;
+ }
+ return 0;
+mem_error:
+ ql_free_lbq_buffers(qdev, rx_ring);
+ return -ENOMEM;
+}
+
+void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+{
+ int i;
+ struct bq_desc *sbq_desc;
+
+ for (i = 0; i < rx_ring->sbq_len; i++) {
+ sbq_desc = &rx_ring->sbq[i];
+ if (sbq_desc == NULL) {
+ QPRINTK(qdev, IFUP, ERR, "sbq_desc %d is NULL.\n", i);
+ return;
+ }
+ if (sbq_desc->p.skb) {
+ pci_unmap_single(qdev->pdev,
+ pci_unmap_addr(sbq_desc, mapaddr),
+ pci_unmap_len(sbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(sbq_desc->p.skb);
+ sbq_desc->p.skb = NULL;
+ }
+ if (sbq_desc->bq == NULL) {
+ QPRINTK(qdev, IFUP, ERR, "sbq_desc->bq %d is NULL.\n",
+ i);
+ return;
+ }
+ sbq_desc->bq->addr_lo = 0;
+ sbq_desc->bq->addr_hi = 0;
+ }
+}
+
+/* Allocate and map an skb for each element of the sbq. */
+static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
+{
+ int i;
+ struct bq_desc *sbq_desc;
+ struct sk_buff *skb;
+ u64 map;
+ struct bq_element *bq = rx_ring->sbq_base;
+
+ for (i = 0; i < rx_ring->sbq_len; i++) {
+ sbq_desc = &rx_ring->sbq[i];
+ memset(sbq_desc, 0, sizeof(sbq_desc));
+ sbq_desc->index = i;
+ sbq_desc->bq = bq;
+ skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size);
+ if (unlikely(!skb)) {
+ /* Better luck next round */
+ QPRINTK(qdev, IFUP, ERR,
+ "small buff alloc failed for %d bytes at index %d.\n",
+ rx_ring->sbq_buf_size, i);
+ goto mem_err;
+ }
+ skb_reserve(skb, QLGE_SB_PAD);
+ sbq_desc->p.skb = skb;
+ /*
+ * Map only half the buffer. Because the
+ * other half may get some data copied to it
+ * when the completion arrives.
+ */
+ map = pci_map_single(qdev->pdev,
+ skb->data,
+ rx_ring->sbq_buf_size / 2,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(qdev->pdev, map)) {
+ QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n");
+ goto mem_err;
+ }
+ pci_unmap_addr_set(sbq_desc, mapaddr, map);
+ pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2);
+ bq->addr_lo = /*sbq_desc->addr_lo = */
+ cpu_to_le32(map);
+ bq->addr_hi = /*sbq_desc->addr_hi = */
+ cpu_to_le32(map >> 32);
+ bq++;
+ }
+ return 0;
+mem_err:
+ ql_free_sbq_buffers(qdev, rx_ring);
+ return -ENOMEM;
+}
+
+static void ql_free_rx_resources(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
+{
+ if (rx_ring->sbq_len)
+ ql_free_sbq_buffers(qdev, rx_ring);
+ if (rx_ring->lbq_len)
+ ql_free_lbq_buffers(qdev, rx_ring);
+
+ /* Free the small buffer queue. */
+ if (rx_ring->sbq_base) {
+ pci_free_consistent(qdev->pdev,
+ rx_ring->sbq_size,
+ rx_ring->sbq_base, rx_ring->sbq_base_dma);
+ rx_ring->sbq_base = NULL;
+ }
+
+ /* Free the small buffer queue control blocks. */
+ kfree(rx_ring->sbq);
+ rx_ring->sbq = NULL;
+
+ /* Free the large buffer queue. */
+ if (rx_ring->lbq_base) {
+ pci_free_consistent(qdev->pdev,
+ rx_ring->lbq_size,
+ rx_ring->lbq_base, rx_ring->lbq_base_dma);
+ rx_ring->lbq_base = NULL;
+ }
+
+ /* Free the large buffer queue control blocks. */
+ kfree(rx_ring->lbq);
+ rx_ring->lbq = NULL;
+
+ /* Free the rx queue. */
+ if (rx_ring->cq_base) {
+ pci_free_consistent(qdev->pdev,
+ rx_ring->cq_size,
+ rx_ring->cq_base, rx_ring->cq_base_dma);
+ rx_ring->cq_base = NULL;
+ }
+}
+
+/* Allocate queues and buffers for this completions queue based
+ * on the values in the parameter structure. */
+static int ql_alloc_rx_resources(struct ql_adapter *qdev,
+ struct rx_ring *rx_ring)
+{
+
+ /*
+ * Allocate the completion queue for this rx_ring.
+ */
+ rx_ring->cq_base =
+ pci_alloc_consistent(qdev->pdev, rx_ring->cq_size,
+ &rx_ring->cq_base_dma);
+
+ if (rx_ring->cq_base == NULL) {
+ QPRINTK(qdev, IFUP, ERR, "rx_ring alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ if (rx_ring->sbq_len) {
+ /*
+ * Allocate small buffer queue.
+ */
+ rx_ring->sbq_base =
+ pci_alloc_consistent(qdev->pdev, rx_ring->sbq_size,
+ &rx_ring->sbq_base_dma);
+
+ if (rx_ring->sbq_base == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Small buffer queue allocation failed.\n");
+ goto err_mem;
+ }
+
+ /*
+ * Allocate small buffer queue control blocks.
+ */
+ rx_ring->sbq =
+ kmalloc(rx_ring->sbq_len * sizeof(struct bq_desc),
+ GFP_KERNEL);
+ if (rx_ring->sbq == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Small buffer queue control block allocation failed.\n");
+ goto err_mem;
+ }
+
+ if (ql_alloc_sbq_buffers(qdev, rx_ring)) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Small buffer allocation failed.\n");
+ goto err_mem;
+ }
+ }
+
+ if (rx_ring->lbq_len) {
+ /*
+ * Allocate large buffer queue.
+ */
+ rx_ring->lbq_base =
+ pci_alloc_consistent(qdev->pdev, rx_ring->lbq_size,
+ &rx_ring->lbq_base_dma);
+
+ if (rx_ring->lbq_base == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Large buffer queue allocation failed.\n");
+ goto err_mem;
+ }
+ /*
+ * Allocate large buffer queue control blocks.
+ */
+ rx_ring->lbq =
+ kmalloc(rx_ring->lbq_len * sizeof(struct bq_desc),
+ GFP_KERNEL);
+ if (rx_ring->lbq == NULL) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Large buffer queue control block allocation failed.\n");
+ goto err_mem;
+ }
+
+ /*
+ * Allocate the buffers.
+ */
+ if (ql_alloc_lbq_buffers(qdev, rx_ring)) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Large buffer allocation failed.\n");
+ goto err_mem;
+ }
+ }
+
+ return 0;
+
+err_mem:
+ ql_free_rx_resources(qdev, rx_ring);
+ return -ENOMEM;
+}
+
+static void ql_tx_ring_clean(struct ql_adapter *qdev)
+{
+ struct tx_ring *tx_ring;
+ struct tx_ring_desc *tx_ring_desc;
+ int i, j;
+
+ /*
+ * Loop through all queues and free
+ * any resources.
+ */
+ for (j = 0; j < qdev->tx_ring_count; j++) {
+ tx_ring = &qdev->tx_ring[j];
+ for (i = 0; i < tx_ring->wq_len; i++) {
+ tx_ring_desc = &tx_ring->q[i];
+ if (tx_ring_desc && tx_ring_desc->skb) {
+ QPRINTK(qdev, IFDOWN, ERR,
+ "Freeing lost SKB %p, from queue %d, index %d.\n",
+ tx_ring_desc->skb, j,
+ tx_ring_desc->index);
+ ql_unmap_send(qdev, tx_ring_desc,
+ tx_ring_desc->map_cnt);
+ dev_kfree_skb(tx_ring_desc->skb);
+ tx_ring_desc->skb = NULL;
+ }
+ }
+ }
+}
+
+static void ql_free_ring_cb(struct ql_adapter *qdev)
+{
+ kfree(qdev->ring_mem);
+}
+
+static int ql_alloc_ring_cb(struct ql_adapter *qdev)
+{
+ /* Allocate space for tx/rx ring control blocks. */
+ qdev->ring_mem_size =
+ (qdev->tx_ring_count * sizeof(struct tx_ring)) +
+ (qdev->rx_ring_count * sizeof(struct rx_ring));
+ qdev->ring_mem = kmalloc(qdev->ring_mem_size, GFP_KERNEL);
+ if (qdev->ring_mem == NULL) {
+ return -ENOMEM;
+ } else {
+ qdev->rx_ring = qdev->ring_mem;
+ qdev->tx_ring = qdev->ring_mem +
+ (qdev->rx_ring_count * sizeof(struct rx_ring));
+ }
+ return 0;
+}
+
+static void ql_free_mem_resources(struct ql_adapter *qdev)
+{
+ int i;
+
+ for (i = 0; i < qdev->tx_ring_count; i++)
+ ql_free_tx_resources(qdev, &qdev->tx_ring[i]);
+ for (i = 0; i < qdev->rx_ring_count; i++)
+ ql_free_rx_resources(qdev, &qdev->rx_ring[i]);
+ ql_free_shadow_space(qdev);
+}
+
+static int ql_alloc_mem_resources(struct ql_adapter *qdev)
+{
+ int i;
+
+ /* Allocate space for our shadow registers and such. */
+ if (ql_alloc_shadow_space(qdev))
+ return -ENOMEM;
+
+ for (i = 0; i < qdev->rx_ring_count; i++) {
+ if (ql_alloc_rx_resources(qdev, &qdev->rx_ring[i]) != 0) {
+ QPRINTK(qdev, IFUP, ERR,
+ "RX resource allocation failed.\n");
+ goto err_mem;
+ }
+ }
+ /* Allocate tx queue resources */
+ for (i = 0; i < qdev->tx_ring_count; i++) {
+ if (ql_alloc_tx_resources(qdev, &qdev->tx_ring[i]) != 0) {
+ QPRINTK(qdev, IFUP, ERR,
+ "TX resource allocation failed.\n");
+ goto err_mem;
+ }
+ }
+ return 0;
+
+err_mem:
+ ql_free_mem_resources(qdev);
+ return -ENOMEM;
+}
+
+/* Set up the rx ring control block and pass it to the chip.
+ * The control block is defined as
+ * "Completion Queue Initialization Control Block", or cqicb.
+ */
+static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+{
+ struct cqicb *cqicb = &rx_ring->cqicb;
+ void *shadow_reg = qdev->rx_ring_shadow_reg_area +
+ (rx_ring->cq_id * sizeof(u64) * 4);
+ u64 shadow_reg_dma = qdev->rx_ring_shadow_reg_dma +
+ (rx_ring->cq_id * sizeof(u64) * 4);
+ void __iomem *doorbell_area =
+ qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id));
+ int err = 0;
+ u16 bq_len;
+
+ /* Set up the shadow registers for this ring. */
+ rx_ring->prod_idx_sh_reg = shadow_reg;
+ rx_ring->prod_idx_sh_reg_dma = shadow_reg_dma;
+ shadow_reg += sizeof(u64);
+ shadow_reg_dma += sizeof(u64);
+ rx_ring->lbq_base_indirect = shadow_reg;
+ rx_ring->lbq_base_indirect_dma = shadow_reg_dma;
+ shadow_reg += sizeof(u64);
+ shadow_reg_dma += sizeof(u64);
+ rx_ring->sbq_base_indirect = shadow_reg;
+ rx_ring->sbq_base_indirect_dma = shadow_reg_dma;
+
+ /* PCI doorbell mem area + 0x00 for consumer index register */
+ rx_ring->cnsmr_idx_db_reg = (u32 *) doorbell_area;
+ rx_ring->cnsmr_idx = 0;
+ rx_ring->curr_entry = rx_ring->cq_base;
+
+ /* PCI doorbell mem area + 0x04 for valid register */
+ rx_ring->valid_db_reg = doorbell_area + 0x04;
+
+ /* PCI doorbell mem area + 0x18 for large buffer consumer */
+ rx_ring->lbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x18);
+
+ /* PCI doorbell mem area + 0x1c */
+ rx_ring->sbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x1c);
+
+ memset((void *)cqicb, 0, sizeof(struct cqicb));
+ cqicb->msix_vect = rx_ring->irq;
+
+ cqicb->len = cpu_to_le16(rx_ring->cq_len | LEN_V | LEN_CPP_CONT);
+
+ cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma);
+ cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32);
+
+ cqicb->prod_idx_addr_lo = cpu_to_le32(rx_ring->prod_idx_sh_reg_dma);
+ cqicb->prod_idx_addr_hi =
+ cpu_to_le32((u64) rx_ring->prod_idx_sh_reg_dma >> 32);
+
+ /*
+ * Set up the control block load flags.
+ */
+ cqicb->flags = FLAGS_LC | /* Load queue base address */
+ FLAGS_LV | /* Load MSI-X vector */
+ FLAGS_LI; /* Load irq delay values */
+ if (rx_ring->lbq_len) {
+ cqicb->flags |= FLAGS_LL; /* Load lbq values */
+ *((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma;
+ cqicb->lbq_addr_lo =
+ cpu_to_le32(rx_ring->lbq_base_indirect_dma);
+ cqicb->lbq_addr_hi =
+ cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32);
+ cqicb->lbq_buf_size = cpu_to_le32(rx_ring->lbq_buf_size);
+ bq_len = (u16) rx_ring->lbq_len;
+ cqicb->lbq_len = cpu_to_le16(bq_len);
+ rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16;
+ rx_ring->lbq_curr_idx = 0;
+ rx_ring->lbq_clean_idx = rx_ring->lbq_prod_idx;
+ rx_ring->lbq_free_cnt = 16;
+ }
+ if (rx_ring->sbq_len) {
+ cqicb->flags |= FLAGS_LS; /* Load sbq values */
+ *((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma;
+ cqicb->sbq_addr_lo =
+ cpu_to_le32(rx_ring->sbq_base_indirect_dma);
+ cqicb->sbq_addr_hi =
+ cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32);
+ cqicb->sbq_buf_size =
+ cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8);
+ bq_len = (u16) rx_ring->sbq_len;
+ cqicb->sbq_len = cpu_to_le16(bq_len);
+ rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16;
+ rx_ring->sbq_curr_idx = 0;
+ rx_ring->sbq_clean_idx = rx_ring->sbq_prod_idx;
+ rx_ring->sbq_free_cnt = 16;
+ }
+ switch (rx_ring->type) {
+ case TX_Q:
+ /* If there's only one interrupt, then we use
+ * worker threads to process the outbound
+ * completion handling rx_rings. We do this so
+ * they can be run on multiple CPUs. There is
+ * room to play with this more where we would only
+ * run in a worker if there are more than x number
+ * of outbound completions on the queue and more
+ * than one queue active. Some threshold that
+ * would indicate a benefit in spite of the cost
+ * of a context switch.
+ * If there's more than one interrupt, then the
+ * outbound completions are processed in the ISR.
+ */
+ if (!test_bit(QL_MSIX_ENABLED, &qdev->flags))
+ INIT_DELAYED_WORK(&rx_ring->rx_work, ql_tx_clean);
+ else {
+ /* With all debug warnings on we see a WARN_ON message
+ * when we free the skb in the interrupt context.
+ */
+ INIT_DELAYED_WORK(&rx_ring->rx_work, ql_tx_clean);
+ }
+ cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
+ cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames);
+ break;
+ case DEFAULT_Q:
+ INIT_DELAYED_WORK(&rx_ring->rx_work, ql_rx_clean);
+ cqicb->irq_delay = 0;
+ cqicb->pkt_delay = 0;
+ break;
+ case RX_Q:
+ /* Inbound completion handling rx_rings run in
+ * separate NAPI contexts.
+ */
+ netif_napi_add(qdev->ndev, &rx_ring->napi, ql_napi_poll_msix,
+ 64);
+ cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs);
+ cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames);
+ break;
+ default:
+ QPRINTK(qdev, IFUP, DEBUG, "Invalid rx_ring->type = %d.\n",
+ rx_ring->type);
+ }
+ QPRINTK(qdev, IFUP, INFO, "Initializing rx work queue.\n");
+ err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb),
+ CFG_LCQ, rx_ring->cq_id);
+ if (err) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to load CQICB.\n");
+ return err;
+ }
+ QPRINTK(qdev, IFUP, INFO, "Successfully loaded CQICB.\n");
+ /*
+ * Advance the producer index for the buffer queues.
+ */
+ wmb();
+ if (rx_ring->lbq_len)
+ ql_write_db_reg(rx_ring->lbq_prod_idx,
+ rx_ring->lbq_prod_idx_db_reg);
+ if (rx_ring->sbq_len)
+ ql_write_db_reg(rx_ring->sbq_prod_idx,
+ rx_ring->sbq_prod_idx_db_reg);
+ return err;
+}
+
+static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
+{
+ struct wqicb *wqicb = (struct wqicb *)tx_ring;
+ void __iomem *doorbell_area =
+ qdev->doorbell_area + (DB_PAGE_SIZE * tx_ring->wq_id);
+ void *shadow_reg = qdev->tx_ring_shadow_reg_area +
+ (tx_ring->wq_id * sizeof(u64));
+ u64 shadow_reg_dma = qdev->tx_ring_shadow_reg_dma +
+ (tx_ring->wq_id * sizeof(u64));
+ int err = 0;
+
+ /*
+ * Assign doorbell registers for this tx_ring.
+ */
+ /* TX PCI doorbell mem area for tx producer index */
+ tx_ring->prod_idx_db_reg = (u32 *) doorbell_area;
+ tx_ring->prod_idx = 0;
+ /* TX PCI doorbell mem area + 0x04 */
+ tx_ring->valid_db_reg = doorbell_area + 0x04;
+
+ /*
+ * Assign shadow registers for this tx_ring.
+ */
+ tx_ring->cnsmr_idx_sh_reg = shadow_reg;
+ tx_ring->cnsmr_idx_sh_reg_dma = shadow_reg_dma;
+
+ wqicb->len = cpu_to_le16(tx_ring->wq_len | Q_LEN_V | Q_LEN_CPP_CONT);
+ wqicb->flags = cpu_to_le16(Q_FLAGS_LC |
+ Q_FLAGS_LB | Q_FLAGS_LI | Q_FLAGS_LO);
+ wqicb->cq_id_rss = cpu_to_le16(tx_ring->cq_id);
+ wqicb->rid = 0;
+ wqicb->addr_lo = cpu_to_le32(tx_ring->wq_base_dma);
+ wqicb->addr_hi = cpu_to_le32((u64) tx_ring->wq_base_dma >> 32);
+
+ wqicb->cnsmr_idx_addr_lo = cpu_to_le32(tx_ring->cnsmr_idx_sh_reg_dma);
+ wqicb->cnsmr_idx_addr_hi =
+ cpu_to_le32((u64) tx_ring->cnsmr_idx_sh_reg_dma >> 32);
+
+ ql_init_tx_ring(qdev, tx_ring);
+
+ err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ,
+ (u16) tx_ring->wq_id);
+ if (err) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n");
+ return err;
+ }
+ QPRINTK(qdev, IFUP, INFO, "Successfully loaded WQICB.\n");
+ return err;
+}
+
+static void ql_disable_msix(struct ql_adapter *qdev)
+{
+ if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
+ pci_disable_msix(qdev->pdev);
+ clear_bit(QL_MSIX_ENABLED, &qdev->flags);
+ kfree(qdev->msi_x_entry);
+ qdev->msi_x_entry = NULL;
+ } else if (test_bit(QL_MSI_ENABLED, &qdev->flags)) {
+ pci_disable_msi(qdev->pdev);
+ clear_bit(QL_MSI_ENABLED, &qdev->flags);
+ }
+}
+
+static void ql_enable_msix(struct ql_adapter *qdev)
+{
+ int i;
+
+ qdev->intr_count = 1;
+ /* Get the MSIX vectors. */
+ if (irq_type == MSIX_IRQ) {
+ /* Try to alloc space for the msix struct,
+ * if it fails then go to MSI/legacy.
+ */
+ qdev->msi_x_entry = kcalloc(qdev->rx_ring_count,
+ sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!qdev->msi_x_entry) {
+ irq_type = MSI_IRQ;
+ goto msi;
+ }
+
+ for (i = 0; i < qdev->rx_ring_count; i++)
+ qdev->msi_x_entry[i].entry = i;
+
+ if (!pci_enable_msix
+ (qdev->pdev, qdev->msi_x_entry, qdev->rx_ring_count)) {
+ set_bit(QL_MSIX_ENABLED, &qdev->flags);
+ qdev->intr_count = qdev->rx_ring_count;
+ QPRINTK(qdev, IFUP, INFO,
+ "MSI-X Enabled, got %d vectors.\n",
+ qdev->intr_count);
+ return;
+ } else {
+ kfree(qdev->msi_x_entry);
+ qdev->msi_x_entry = NULL;
+ QPRINTK(qdev, IFUP, WARNING,
+ "MSI-X Enable failed, trying MSI.\n");
+ irq_type = MSI_IRQ;
+ }
+ }
+msi:
+ if (irq_type == MSI_IRQ) {
+ if (!pci_enable_msi(qdev->pdev)) {
+ set_bit(QL_MSI_ENABLED, &qdev->flags);
+ QPRINTK(qdev, IFUP, INFO,
+ "Running with MSI interrupts.\n");
+ return;
+ }
+ }
+ irq_type = LEG_IRQ;
+ spin_lock_init(&qdev->legacy_lock);
+ qdev->legacy_check = ql_legacy_check;
+ QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n");
+}
+
+/*
+ * Here we build the intr_context structures based on
+ * our rx_ring count and intr vector count.
+ * The intr_context structure is used to hook each vector
+ * to possibly different handlers.
+ */
+static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev)
+{
+ int i = 0;
+ struct intr_context *intr_context = &qdev->intr_context[0];
+
+ ql_enable_msix(qdev);
+
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) {
+ /* Each rx_ring has it's
+ * own intr_context since we have separate
+ * vectors for each queue.
+ * This only true when MSI-X is enabled.
+ */
+ for (i = 0; i < qdev->intr_count; i++, intr_context++) {
+ qdev->rx_ring[i].irq = i;
+ intr_context->intr = i;
+ intr_context->qdev = qdev;
+ /*
+ * We set up each vectors enable/disable/read bits so
+ * there's no bit/mask calculations in the critical path.
+ */
+ intr_context->intr_en_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
+ INTR_EN_TYPE_ENABLE | INTR_EN_IHD_MASK | INTR_EN_IHD
+ | i;
+ intr_context->intr_dis_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
+ INTR_EN_TYPE_DISABLE | INTR_EN_IHD_MASK |
+ INTR_EN_IHD | i;
+ intr_context->intr_read_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
+ INTR_EN_TYPE_READ | INTR_EN_IHD_MASK | INTR_EN_IHD |
+ i;
+
+ if (i == 0) {
+ /*
+ * Default queue handles bcast/mcast plus
+ * async events. Needs buffers.
+ */
+ intr_context->handler = qlge_isr;
+ sprintf(intr_context->name, "%s-default-queue",
+ qdev->ndev->name);
+ } else if (i < qdev->rss_ring_first_cq_id) {
+ /*
+ * Outbound queue is for outbound completions only.
+ */
+ intr_context->handler = qlge_msix_tx_isr;
+ sprintf(intr_context->name, "%s-txq-%d",
+ qdev->ndev->name, i);
+ } else {
+ /*
+ * Inbound queues handle unicast frames only.
+ */
+ intr_context->handler = qlge_msix_rx_isr;
+ sprintf(intr_context->name, "%s-rxq-%d",
+ qdev->ndev->name, i);
+ }
+ }
+ } else {
+ /*
+ * All rx_rings use the same intr_context since
+ * there is only one vector.
+ */
+ intr_context->intr = 0;
+ intr_context->qdev = qdev;
+ /*
+ * We set up each vectors enable/disable/read bits so
+ * there's no bit/mask calculations in the critical path.
+ */
+ intr_context->intr_en_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_ENABLE;
+ intr_context->intr_dis_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK |
+ INTR_EN_TYPE_DISABLE;
+ intr_context->intr_read_mask =
+ INTR_EN_TYPE_MASK | INTR_EN_INTR_MASK | INTR_EN_TYPE_READ;
+ /*
+ * Single interrupt means one handler for all rings.
+ */
+ intr_context->handler = qlge_isr;
+ sprintf(intr_context->name, "%s-single_irq", qdev->ndev->name);
+ for (i = 0; i < qdev->rx_ring_count; i++)
+ qdev->rx_ring[i].irq = 0;
+ }
+}
+
+static void ql_free_irq(struct ql_adapter *qdev)
+{
+ int i;
+ struct intr_context *intr_context = &qdev->intr_context[0];
+
+ for (i = 0; i < qdev->intr_count; i++, intr_context++) {
+ if (intr_context->hooked) {
+ if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
+ free_irq(qdev->msi_x_entry[i].vector,
+ &qdev->rx_ring[i]);
+ QPRINTK(qdev, IFDOWN, ERR,
+ "freeing msix interrupt %d.\n", i);
+ } else {
+ free_irq(qdev->pdev->irq, &qdev->rx_ring[0]);
+ QPRINTK(qdev, IFDOWN, ERR,
+ "freeing msi interrupt %d.\n", i);
+ }
+ }
+ }
+ ql_disable_msix(qdev);
+}
+
+static int ql_request_irq(struct ql_adapter *qdev)
+{
+ int i;
+ int status = 0;
+ struct pci_dev *pdev = qdev->pdev;
+ struct intr_context *intr_context = &qdev->intr_context[0];
+
+ ql_resolve_queues_to_irqs(qdev);
+
+ for (i = 0; i < qdev->intr_count; i++, intr_context++) {
+ atomic_set(&intr_context->irq_cnt, 0);
+ if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
+ status = request_irq(qdev->msi_x_entry[i].vector,
+ intr_context->handler,
+ 0,
+ intr_context->name,
+ &qdev->rx_ring[i]);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed request for MSIX interrupt %d.\n",
+ i);
+ goto err_irq;
+ } else {
+ QPRINTK(qdev, IFUP, INFO,
+ "Hooked intr %d, queue type %s%s%s, with name %s.\n",
+ i,
+ qdev->rx_ring[i].type ==
+ DEFAULT_Q ? "DEFAULT_Q" : "",
+ qdev->rx_ring[i].type ==
+ TX_Q ? "TX_Q" : "",
+ qdev->rx_ring[i].type ==
+ RX_Q ? "RX_Q" : "", intr_context->name);
+ }
+ } else {
+ QPRINTK(qdev, IFUP, DEBUG,
+ "trying msi or legacy interrupts.\n");
+ QPRINTK(qdev, IFUP, DEBUG,
+ "%s: irq = %d.\n", __func__, pdev->irq);
+ QPRINTK(qdev, IFUP, DEBUG,
+ "%s: context->name = %s.\n", __func__,
+ intr_context->name);
+ QPRINTK(qdev, IFUP, DEBUG,
+ "%s: dev_id = 0x%p.\n", __func__,
+ &qdev->rx_ring[0]);
+ status =
+ request_irq(pdev->irq, qlge_isr,
+ test_bit(QL_MSI_ENABLED,
+ &qdev->
+ flags) ? 0 : IRQF_SHARED,
+ intr_context->name, &qdev->rx_ring[0]);
+ if (status)
+ goto err_irq;
+
+ QPRINTK(qdev, IFUP, ERR,
+ "Hooked intr %d, queue type %s%s%s, with name %s.\n",
+ i,
+ qdev->rx_ring[0].type ==
+ DEFAULT_Q ? "DEFAULT_Q" : "",
+ qdev->rx_ring[0].type == TX_Q ? "TX_Q" : "",
+ qdev->rx_ring[0].type == RX_Q ? "RX_Q" : "",
+ intr_context->name);
+ }
+ intr_context->hooked = 1;
+ }
+ return status;
+err_irq:
+ QPRINTK(qdev, IFUP, ERR, "Failed to get the interrupts!!!/n");
+ ql_free_irq(qdev);
+ return status;
+}
+
+static int ql_start_rss(struct ql_adapter *qdev)
+{
+ struct ricb *ricb = &qdev->ricb;
+ int status = 0;
+ int i;
+ u8 *hash_id = (u8 *) ricb->hash_cq_id;
+
+ memset((void *)ricb, 0, sizeof(ricb));
+
+ ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K;
+ ricb->flags =
+ (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RI4 | RSS_RI6 | RSS_RT4 |
+ RSS_RT6);
+ ricb->mask = cpu_to_le16(qdev->rss_ring_count - 1);
+
+ /*
+ * Fill out the Indirection Table.
+ */
+ for (i = 0; i < 32; i++)
+ hash_id[i] = i & 1;
+
+ /*
+ * Random values for the IPv6 and IPv4 Hash Keys.
+ */
+ get_random_bytes((void *)&ricb->ipv6_hash_key[0], 40);
+ get_random_bytes((void *)&ricb->ipv4_hash_key[0], 16);
+
+ QPRINTK(qdev, IFUP, INFO, "Initializing RSS.\n");
+
+ status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n");
+ return status;
+ }
+ QPRINTK(qdev, IFUP, INFO, "Successfully loaded RICB.\n");
+ return status;
+}
+
+/* Initialize the frame-to-queue routing. */
+static int ql_route_initialize(struct ql_adapter *qdev)
+{
+ int status = 0;
+ int i;
+
+ /* Clear all the entries in the routing table. */
+ for (i = 0; i < 16; i++) {
+ status = ql_set_routing_reg(qdev, i, 0, 0);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to init routing register for CAM packets.\n");
+ return status;
+ }
+ }
+
+ status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to init routing register for error packets.\n");
+ return status;
+ }
+ status = ql_set_routing_reg(qdev, RT_IDX_BCAST_SLOT, RT_IDX_BCAST, 1);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to init routing register for broadcast packets.\n");
+ return status;
+ }
+ /* If we have more than one inbound queue, then turn on RSS in the
+ * routing block.
+ */
+ if (qdev->rss_ring_count > 1) {
+ status = ql_set_routing_reg(qdev, RT_IDX_RSS_MATCH_SLOT,
+ RT_IDX_RSS_MATCH, 1);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to init routing register for MATCH RSS packets.\n");
+ return status;
+ }
+ }
+
+ status = ql_set_routing_reg(qdev, RT_IDX_CAM_HIT_SLOT,
+ RT_IDX_CAM_HIT, 1);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to init routing register for CAM packets.\n");
+ return status;
+ }
+ return status;
+}
+
+static int ql_adapter_initialize(struct ql_adapter *qdev)
+{
+ u32 value, mask;
+ int i;
+ int status = 0;
+
+ /*
+ * Set up the System register to halt on errors.
+ */
+ value = SYS_EFE | SYS_FAE;
+ mask = value << 16;
+ ql_write32(qdev, SYS, mask | value);
+
+ /* Set the default queue. */
+ value = NIC_RCV_CFG_DFQ;
+ mask = NIC_RCV_CFG_DFQ_MASK;
+ ql_write32(qdev, NIC_RCV_CFG, (mask | value));
+
+ /* Set the MPI interrupt to enabled. */
+ ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
+
+ /* Enable the function, set pagesize, enable error checking. */
+ value = FSC_FE | FSC_EPC_INBOUND | FSC_EPC_OUTBOUND |
+ FSC_EC | FSC_VM_PAGE_4K | FSC_SH;
+
+ /* Set/clear header splitting. */
+ mask = FSC_VM_PAGESIZE_MASK |
+ FSC_DBL_MASK | FSC_DBRST_MASK | (value << 16);
+ ql_write32(qdev, FSC, mask | value);
+
+ ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP |
+ min(SMALL_BUFFER_SIZE, MAX_SPLIT_SIZE));
+
+ /* Start up the rx queues. */
+ for (i = 0; i < qdev->rx_ring_count; i++) {
+ status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to start rx ring[%d].\n", i);
+ return status;
+ }
+ }
+
+ /* If there is more than one inbound completion queue
+ * then download a RICB to configure RSS.
+ */
+ if (qdev->rss_ring_count > 1) {
+ status = ql_start_rss(qdev);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to start RSS.\n");
+ return status;
+ }
+ }
+
+ /* Start up the tx queues. */
+ for (i = 0; i < qdev->tx_ring_count; i++) {
+ status = ql_start_tx_ring(qdev, &qdev->tx_ring[i]);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Failed to start tx ring[%d].\n", i);
+ return status;
+ }
+ }
+
+ status = ql_port_initialize(qdev);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n");
+ return status;
+ }
+
+ status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr,
+ MAC_ADDR_TYPE_CAM_MAC, qdev->func);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
+ return status;
+ }
+
+ status = ql_route_initialize(qdev);
+ if (status) {
+ QPRINTK(qdev, IFUP, ERR, "Failed to init routing table.\n");
+ return status;
+ }
+
+ /* Start NAPI for the RSS queues. */
+ for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) {
+ QPRINTK(qdev, IFUP, INFO, "Enabling NAPI for rx_ring[%d].\n",
+ i);
+ napi_enable(&qdev->rx_ring[i].napi);
+ }
+
+ return status;
+}
+
+/* Issue soft reset to chip. */
+static int ql_adapter_reset(struct ql_adapter *qdev)
+{
+ u32 value;
+ int max_wait_time;
+ int status = 0;
+ int resetCnt = 0;
+
+#define MAX_RESET_CNT 1
+issueReset:
+ resetCnt++;
+ QPRINTK(qdev, IFDOWN, DEBUG, "Issue soft reset to chip.\n");
+ ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR);
+ /* Wait for reset to complete. */
+ max_wait_time = 3;
+ QPRINTK(qdev, IFDOWN, DEBUG, "Wait %d seconds for reset to complete.\n",
+ max_wait_time);
+ do {
+ value = ql_read32(qdev, RST_FO);
+ if ((value & RST_FO_FR) == 0)
+ break;
+
+ ssleep(1);
+ } while ((--max_wait_time));
+ if (value & RST_FO_FR) {
+ QPRINTK(qdev, IFDOWN, ERR,
+ "Stuck in SoftReset: FSC_SR:0x%08x\n", value);
+ if (resetCnt < MAX_RESET_CNT)
+ goto issueReset;
+ }
+ if (max_wait_time == 0) {
+ status = -ETIMEDOUT;
+ QPRINTK(qdev, IFDOWN, ERR,
+ "ETIMEOUT!!! errored out of resetting the chip!\n");
+ }
+
+ return status;
+}
+
+static void ql_display_dev_info(struct net_device *ndev)
+{
+ struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+
+ QPRINTK(qdev, PROBE, INFO,
+ "Function #%d, NIC Roll %d, NIC Rev = %d, "
+ "XG Roll = %d, XG Rev = %d.\n",
+ qdev->func,
+ qdev->chip_rev_id & 0x0000000f,
+ qdev->chip_rev_id >> 4 & 0x0000000f,
+ qdev->chip_rev_id >> 8 & 0x0000000f,
+ qdev->chip_rev_id >> 12 & 0x0000000f);
+ QPRINTK(qdev, PROBE, INFO,
+ "MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->dev_addr[0], ndev->dev_addr[1],
+ ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
+ ndev->dev_addr[5]);
+}
+
+static int ql_adapter_down(struct ql_adapter *qdev)
+{
+ struct net_device *ndev = qdev->ndev;
+ int i, status = 0;
+ struct rx_ring *rx_ring;
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ cancel_delayed_work_sync(&qdev->asic_reset_work);
+ cancel_delayed_work_sync(&qdev->mpi_reset_work);
+ cancel_delayed_work_sync(&qdev->mpi_work);
+
+ /* The default queue at index 0 is always processed in
+ * a workqueue.
+ */
+ cancel_delayed_work_sync(&qdev->rx_ring[0].rx_work);
+
+ /* The rest of the rx_rings are processed in
+ * a workqueue only if it's a single interrupt
+ * environment (MSI/Legacy).
+ */
+ for (i = 1; i > qdev->rx_ring_count; i++) {
+ rx_ring = &qdev->rx_ring[i];
+ /* Only the RSS rings use NAPI on multi irq
+ * environment. Outbound completion processing
+ * is done in interrupt context.
+ */
+ if (i >= qdev->rss_ring_first_cq_id) {
+ napi_disable(&rx_ring->napi);
+ } else {
+ cancel_delayed_work_sync(&rx_ring->rx_work);
+ }
+ }
+
+ clear_bit(QL_ADAPTER_UP, &qdev->flags);
+
+ ql_disable_interrupts(qdev);
+
+ ql_tx_ring_clean(qdev);
+
+ spin_lock(&qdev->hw_lock);
+ status = ql_adapter_reset(qdev);
+ if (status)
+ QPRINTK(qdev, IFDOWN, ERR, "reset(func #%d) FAILED!\n",
+ qdev->func);
+ spin_unlock(&qdev->hw_lock);
+ return status;
+}
+
+static int ql_adapter_up(struct ql_adapter *qdev)
+{
+ int err = 0;
+
+ spin_lock(&qdev->hw_lock);
+ err = ql_adapter_initialize(qdev);
+ if (err) {
+ QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n");
+ spin_unlock(&qdev->hw_lock);
+ goto err_init;
+ }
+ spin_unlock(&qdev->hw_lock);
+ set_bit(QL_ADAPTER_UP, &qdev->flags);
+ ql_enable_interrupts(qdev);
+ ql_enable_all_completion_interrupts(qdev);
+ if ((ql_read32(qdev, STS) & qdev->port_init)) {
+ netif_carrier_on(qdev->ndev);
+ netif_start_queue(qdev->ndev);
+ }
+
+ return 0;
+err_init:
+ ql_adapter_reset(qdev);
+ return err;
+}
+
+static int ql_cycle_adapter(struct ql_adapter *qdev)
+{
+ int status;
+
+ status = ql_adapter_down(qdev);
+ if (status)
+ goto error;
+
+ status = ql_adapter_up(qdev);
+ if (status)
+ goto error;
+
+ return status;
+error:
+ QPRINTK(qdev, IFUP, ALERT,
+ "Driver up/down cycle failed, closing device\n");
+ rtnl_lock();
+ dev_close(qdev->ndev);
+ rtnl_unlock();
+ return status;
+}
+
+static void ql_release_adapter_resources(struct ql_adapter *qdev)
+{
+ ql_free_mem_resources(qdev);
+ ql_free_irq(qdev);
+}
+
+static int ql_get_adapter_resources(struct ql_adapter *qdev)
+{
+ int status = 0;
+
+ if (ql_alloc_mem_resources(qdev)) {
+ QPRINTK(qdev, IFUP, ERR, "Unable to allocate memory.\n");
+ return -ENOMEM;
+ }
+ status = ql_request_irq(qdev);
+ if (status)
+ goto err_irq;
+ return status;
+err_irq:
+ ql_free_mem_resources(qdev);
+ return status;
+}
+
+static int qlge_close(struct net_device *ndev)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ /*
+ * Wait for device to recover from a reset.
+ * (Rarely happens, but possible.)
+ */
+ while (!test_bit(QL_ADAPTER_UP, &qdev->flags))
+ msleep(1);
+ ql_adapter_down(qdev);
+ ql_release_adapter_resources(qdev);
+ ql_free_ring_cb(qdev);
+ return 0;
+}
+
+static int ql_configure_rings(struct ql_adapter *qdev)
+{
+ int i;
+ struct rx_ring *rx_ring;
+ struct tx_ring *tx_ring;
+ int cpu_cnt = num_online_cpus();
+
+ /*
+ * For each processor present we allocate one
+ * rx_ring for outbound completions, and one
+ * rx_ring for inbound completions. Plus there is
+ * always the one default queue. For the CPU
+ * counts we end up with the following rx_rings:
+ * rx_ring count =
+ * one default queue +
+ * (CPU count * outbound completion rx_ring) +
+ * (CPU count * inbound (RSS) completion rx_ring)
+ * To keep it simple we limit the total number of
+ * queues to < 32, so we truncate CPU to 8.
+ * This limitation can be removed when requested.
+ */
+
+ if (cpu_cnt > 8)
+ cpu_cnt = 8;
+
+ /*
+ * rx_ring[0] is always the default queue.
+ */
+ /* Allocate outbound completion ring for each CPU. */
+ qdev->tx_ring_count = cpu_cnt;
+ /* Allocate inbound completion (RSS) ring for each CPU. */
+ qdev->rss_ring_count = cpu_cnt;
+ /* cq_id for the first inbound ring handler. */
+ qdev->rss_ring_first_cq_id = cpu_cnt + 1;
+ /*
+ * qdev->rx_ring_count:
+ * Total number of rx_rings. This includes the one
+ * default queue, a number of outbound completion
+ * handler rx_rings, and the number of inbound
+ * completion handler rx_rings.
+ */
+ qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1;
+
+ if (ql_alloc_ring_cb(qdev))
+ return -ENOMEM;
+
+ for (i = 0; i < qdev->tx_ring_count; i++) {
+ tx_ring = &qdev->tx_ring[i];
+ memset((void *)tx_ring, 0, sizeof(tx_ring));
+ tx_ring->qdev = qdev;
+ tx_ring->wq_id = i;
+ tx_ring->wq_len = qdev->tx_ring_size;
+ tx_ring->wq_size =
+ tx_ring->wq_len * sizeof(struct ob_mac_iocb_req);
+
+ /*
+ * The completion queue ID for the tx rings start
+ * immediately after the default Q ID, which is zero.
+ */
+ tx_ring->cq_id = i + 1;
+ }
+
+ for (i = 0; i < qdev->rx_ring_count; i++) {
+ rx_ring = &qdev->rx_ring[i];
+ memset((void *)rx_ring, 0, sizeof(rx_ring));
+ rx_ring->qdev = qdev;
+ rx_ring->cq_id = i;
+ rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */
+ if (i == 0) { /* Default queue at index 0. */
+ /*
+ * Default queue handles bcast/mcast plus
+ * async events. Needs buffers.
+ */
+ rx_ring->cq_len = qdev->rx_ring_size;
+ rx_ring->cq_size =
+ rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
+ rx_ring->lbq_len = NUM_LARGE_BUFFERS;
+ rx_ring->lbq_size =
+ rx_ring->lbq_len * sizeof(struct bq_element);
+ rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
+ rx_ring->sbq_len = NUM_SMALL_BUFFERS;
+ rx_ring->sbq_size =
+ rx_ring->sbq_len * sizeof(struct bq_element);
+ rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
+ rx_ring->type = DEFAULT_Q;
+ } else if (i < qdev->rss_ring_first_cq_id) {
+ /*
+ * Outbound queue handles outbound completions only.
+ */
+ /* outbound cq is same size as tx_ring it services. */
+ rx_ring->cq_len = qdev->tx_ring_size;
+ rx_ring->cq_size =
+ rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
+ rx_ring->lbq_len = 0;
+ rx_ring->lbq_size = 0;
+ rx_ring->lbq_buf_size = 0;
+ rx_ring->sbq_len = 0;
+ rx_ring->sbq_size = 0;
+ rx_ring->sbq_buf_size = 0;
+ rx_ring->type = TX_Q;
+ } else { /* Inbound completions (RSS) queues */
+ /*
+ * Inbound queues handle unicast frames only.
+ */
+ rx_ring->cq_len = qdev->rx_ring_size;
+ rx_ring->cq_size =
+ rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
+ rx_ring->lbq_len = NUM_LARGE_BUFFERS;
+ rx_ring->lbq_size =
+ rx_ring->lbq_len * sizeof(struct bq_element);
+ rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
+ rx_ring->sbq_len = NUM_SMALL_BUFFERS;
+ rx_ring->sbq_size =
+ rx_ring->sbq_len * sizeof(struct bq_element);
+ rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
+ rx_ring->type = RX_Q;
+ }
+ }
+ return 0;
+}
+
+static int qlge_open(struct net_device *ndev)
+{
+ int err = 0;
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ err = ql_configure_rings(qdev);
+ if (err)
+ return err;
+
+ err = ql_get_adapter_resources(qdev);
+ if (err)
+ goto error_up;
+
+ err = ql_adapter_up(qdev);
+ if (err)
+ goto error_up;
+
+ return err;
+
+error_up:
+ ql_release_adapter_resources(qdev);
+ ql_free_ring_cb(qdev);
+ return err;
+}
+
+static int qlge_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ if (ndev->mtu == 1500 && new_mtu == 9000) {
+ QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n");
+ } else if (ndev->mtu == 9000 && new_mtu == 1500) {
+ QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n");
+ } else if ((ndev->mtu == 1500 && new_mtu == 1500) ||
+ (ndev->mtu == 9000 && new_mtu == 9000)) {
+ return 0;
+ } else
+ return -EINVAL;
+ ndev->mtu = new_mtu;
+ return 0;
+}
+
+static struct net_device_stats *qlge_get_stats(struct net_device
+ *ndev)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ return &qdev->stats;
+}
+
+static void qlge_set_multicast_list(struct net_device *ndev)
+{
+ struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+ struct dev_mc_list *mc_ptr;
+ int i;
+
+ spin_lock(&qdev->hw_lock);
+ /*
+ * Set or clear promiscuous mode if a
+ * transition is taking place.
+ */
+ if (ndev->flags & IFF_PROMISC) {
+ if (!test_bit(QL_PROMISCUOUS, &qdev->flags)) {
+ if (ql_set_routing_reg
+ (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 1)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to set promiscous mode.\n");
+ } else {
+ set_bit(QL_PROMISCUOUS, &qdev->flags);
+ }
+ }
+ } else {
+ if (test_bit(QL_PROMISCUOUS, &qdev->flags)) {
+ if (ql_set_routing_reg
+ (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 0)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to clear promiscous mode.\n");
+ } else {
+ clear_bit(QL_PROMISCUOUS, &qdev->flags);
+ }
+ }
+ }
+
+ /*
+ * Set or clear all multicast mode if a
+ * transition is taking place.
+ */
+ if ((ndev->flags & IFF_ALLMULTI) ||
+ (ndev->mc_count > MAX_MULTICAST_ENTRIES)) {
+ if (!test_bit(QL_ALLMULTI, &qdev->flags)) {
+ if (ql_set_routing_reg
+ (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 1)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to set all-multi mode.\n");
+ } else {
+ set_bit(QL_ALLMULTI, &qdev->flags);
+ }
+ }
+ } else {
+ if (test_bit(QL_ALLMULTI, &qdev->flags)) {
+ if (ql_set_routing_reg
+ (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 0)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to clear all-multi mode.\n");
+ } else {
+ clear_bit(QL_ALLMULTI, &qdev->flags);
+ }
+ }
+ }
+
+ if (ndev->mc_count) {
+ for (i = 0, mc_ptr = ndev->mc_list; mc_ptr;
+ i++, mc_ptr = mc_ptr->next)
+ if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr,
+ MAC_ADDR_TYPE_MULTI_MAC, i)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to loadmulticast address.\n");
+ goto exit;
+ }
+ if (ql_set_routing_reg
+ (qdev, RT_IDX_MCAST_MATCH_SLOT, RT_IDX_MCAST_MATCH, 1)) {
+ QPRINTK(qdev, HW, ERR,
+ "Failed to set multicast match mode.\n");
+ } else {
+ set_bit(QL_ALLMULTI, &qdev->flags);
+ }
+ }
+exit:
+ spin_unlock(&qdev->hw_lock);
+}
+
+static int qlge_set_mac_address(struct net_device *ndev, void *p)
+{
+ struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+ struct sockaddr *addr = p;
+
+ if (netif_running(ndev))
+ return -EBUSY;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+ memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+ spin_lock(&qdev->hw_lock);
+ if (ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr,
+ MAC_ADDR_TYPE_CAM_MAC, qdev->func)) {/* Unicast */
+ QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n");
+ return -1;
+ }
+ spin_unlock(&qdev->hw_lock);
+
+ return 0;
+}
+
+static void qlge_tx_timeout(struct net_device *ndev)
+{
+ struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+ queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0);
+}
+
+static void ql_asic_reset_work(struct work_struct *work)
+{
+ struct ql_adapter *qdev =
+ container_of(work, struct ql_adapter, asic_reset_work.work);
+ ql_cycle_adapter(qdev);
+}
+
+static void ql_get_board_info(struct ql_adapter *qdev)
+{
+ qdev->func =
+ (ql_read32(qdev, STS) & STS_FUNC_ID_MASK) >> STS_FUNC_ID_SHIFT;
+ if (qdev->func) {
+ qdev->xg_sem_mask = SEM_XGMAC1_MASK;
+ qdev->port_link_up = STS_PL1;
+ qdev->port_init = STS_PI1;
+ qdev->mailbox_in = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC2_MBI;
+ qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC2_MBO;
+ } else {
+ qdev->xg_sem_mask = SEM_XGMAC0_MASK;
+ qdev->port_link_up = STS_PL0;
+ qdev->port_init = STS_PI0;
+ qdev->mailbox_in = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBI;
+ qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBO;
+ }
+ qdev->chip_rev_id = ql_read32(qdev, REV_ID);
+}
+
+static void ql_release_all(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ if (qdev->workqueue) {
+ destroy_workqueue(qdev->workqueue);
+ qdev->workqueue = NULL;
+ }
+ if (qdev->q_workqueue) {
+ destroy_workqueue(qdev->q_workqueue);
+ qdev->q_workqueue = NULL;
+ }
+ if (qdev->reg_base)
+ iounmap((void *)qdev->reg_base);
+ if (qdev->doorbell_area)
+ iounmap(qdev->doorbell_area);
+ pci_release_regions(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static int __devinit ql_init_device(struct pci_dev *pdev,
+ struct net_device *ndev, int cards_found)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int pos, err = 0;
+ u16 val16;
+
+ memset((void *)qdev, 0, sizeof(qdev));
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "PCI device enable failed.\n");
+ return err;
+ }
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (pos <= 0) {
+ dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, "
+ "aborting.\n");
+ goto err_out;
+ } else {
+ pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16);
+ val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
+ val16 |= (PCI_EXP_DEVCTL_CERE |
+ PCI_EXP_DEVCTL_NFERE |
+ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
+ pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16);
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(&pdev->dev, "PCI region request failed.\n");
+ goto err_out;
+ }
+
+ pci_set_master(pdev);
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ set_bit(QL_DMA64, &qdev->flags);
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ }
+
+ if (err) {
+ dev_err(&pdev->dev, "No usable DMA configuration.\n");
+ goto err_out;
+ }
+
+ pci_set_drvdata(pdev, ndev);
+ qdev->reg_base =
+ ioremap_nocache(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ if (!qdev->reg_base) {
+ dev_err(&pdev->dev, "Register mapping failed.\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ qdev->doorbell_area_size = pci_resource_len(pdev, 3);
+ qdev->doorbell_area =
+ ioremap_nocache(pci_resource_start(pdev, 3),
+ pci_resource_len(pdev, 3));
+ if (!qdev->doorbell_area) {
+ dev_err(&pdev->dev, "Doorbell register mapping failed.\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ ql_get_board_info(qdev);
+ qdev->ndev = ndev;
+ qdev->pdev = pdev;
+ qdev->msg_enable = netif_msg_init(debug, default_msg);
+ spin_lock_init(&qdev->hw_lock);
+ spin_lock_init(&qdev->stats_lock);
+
+ /* make sure the EEPROM is good */
+ err = ql_get_flash_params(qdev);
+ if (err) {
+ dev_err(&pdev->dev, "Invalid FLASH.\n");
+ goto err_out;
+ }
+
+ if (!is_valid_ether_addr(qdev->flash.mac_addr))
+ goto err_out;
+
+ memcpy(ndev->dev_addr, qdev->flash.mac_addr, ndev->addr_len);
+ memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+ /* Set up the default ring sizes. */
+ qdev->tx_ring_size = NUM_TX_RING_ENTRIES;
+ qdev->rx_ring_size = NUM_RX_RING_ENTRIES;
+
+ /* Set up the coalescing parameters. */
+ qdev->rx_coalesce_usecs = DFLT_COALESCE_WAIT;
+ qdev->tx_coalesce_usecs = DFLT_COALESCE_WAIT;
+ qdev->rx_max_coalesced_frames = DFLT_INTER_FRAME_WAIT;
+ qdev->tx_max_coalesced_frames = DFLT_INTER_FRAME_WAIT;
+
+ /*
+ * Set up the operating parameters.
+ */
+ qdev->rx_csum = 1;
+
+ qdev->q_workqueue = create_workqueue(ndev->name);
+ qdev->workqueue = create_singlethread_workqueue(ndev->name);
+ INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work);
+ INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work);
+ INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
+
+ if (!cards_found) {
+ dev_info(&pdev->dev, "%s\n", DRV_STRING);
+ dev_info(&pdev->dev, "Driver name: %s, Version: %s.\n",
+ DRV_NAME, DRV_VERSION);
+ }
+ return 0;
+err_out:
+ ql_release_all(pdev);
+ pci_disable_device(pdev);
+ return err;
+}
+
+static int __devinit qlge_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_entry)
+{
+ struct net_device *ndev = NULL;
+ struct ql_adapter *qdev = NULL;
+ static int cards_found = 0;
+ int err = 0;
+
+ ndev = alloc_etherdev(sizeof(struct ql_adapter));
+ if (!ndev)
+ return -ENOMEM;
+
+ err = ql_init_device(pdev, ndev, cards_found);
+ if (err < 0) {
+ free_netdev(ndev);
+ return err;
+ }
+
+ qdev = netdev_priv(ndev);
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ ndev->features = (0
+ | NETIF_F_IP_CSUM
+ | NETIF_F_SG
+ | NETIF_F_TSO
+ | NETIF_F_TSO6
+ | NETIF_F_TSO_ECN
+ | NETIF_F_HW_VLAN_TX
+ | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER);
+
+ if (test_bit(QL_DMA64, &qdev->flags))
+ ndev->features |= NETIF_F_HIGHDMA;
+
+ /*
+ * Set up net_device structure.
+ */
+ ndev->tx_queue_len = qdev->tx_ring_size;
+ ndev->irq = pdev->irq;
+ ndev->open = qlge_open;
+ ndev->stop = qlge_close;
+ ndev->hard_start_xmit = qlge_send;
+ SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
+ ndev->change_mtu = qlge_change_mtu;
+ ndev->get_stats = qlge_get_stats;
+ ndev->set_multicast_list = qlge_set_multicast_list;
+ ndev->set_mac_address = qlge_set_mac_address;
+ ndev->tx_timeout = qlge_tx_timeout;
+ ndev->watchdog_timeo = 10 * HZ;
+ ndev->vlan_rx_register = ql_vlan_rx_register;
+ ndev->vlan_rx_add_vid = ql_vlan_rx_add_vid;
+ ndev->vlan_rx_kill_vid = ql_vlan_rx_kill_vid;
+ err = register_netdev(ndev);
+ if (err) {
+ dev_err(&pdev->dev, "net device registration failed.\n");
+ ql_release_all(pdev);
+ pci_disable_device(pdev);
+ return err;
+ }
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ ql_display_dev_info(ndev);
+ cards_found++;
+ return 0;
+}
+
+static void __devexit qlge_remove(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ unregister_netdev(ndev);
+ ql_release_all(pdev);
+ pci_disable_device(pdev);
+ free_netdev(ndev);
+}
+
+/*
+ * This callback is called by the PCI subsystem whenever
+ * a PCI bus error is detected.
+ */
+static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
+ enum pci_channel_state state)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ if (netif_running(ndev))
+ ql_adapter_down(qdev);
+
+ pci_disable_device(pdev);
+
+ /* Request a slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * This callback is called after the PCI buss has been reset.
+ * Basically, this tries to restart the card from scratch.
+ * This is a shortened version of the device probe/discovery code,
+ * it resembles the first-half of the () routine.
+ */
+static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ if (pci_enable_device(pdev)) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ ql_adapter_reset(qdev);
+
+ /* Make sure the EEPROM is good */
+ memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+ if (!is_valid_ether_addr(ndev->perm_addr)) {
+ QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void qlge_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ pci_set_master(pdev);
+
+ if (netif_running(ndev)) {
+ if (ql_adapter_up(qdev)) {
+ QPRINTK(qdev, IFUP, ERR,
+ "Device initialization failed after reset.\n");
+ return;
+ }
+ }
+
+ netif_device_attach(ndev);
+}
+
+static struct pci_error_handlers qlge_err_handler = {
+ .error_detected = qlge_io_error_detected,
+ .slot_reset = qlge_io_slot_reset,
+ .resume = qlge_io_resume,
+};
+
+static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int err;
+
+ netif_device_detach(ndev);
+
+ if (netif_running(ndev)) {
+ err = ql_adapter_down(qdev);
+ if (!err)
+ return err;
+ }
+
+ err = pci_save_state(pdev);
+ if (err)
+ return err;
+
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int qlge_resume(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ QPRINTK(qdev, IFUP, ERR, "Cannot enable PCI device from suspend\n");
+ return err;
+ }
+ pci_set_master(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ if (netif_running(ndev)) {
+ err = ql_adapter_up(qdev);
+ if (err)
+ return err;
+ }
+
+ netif_device_attach(ndev);
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static void qlge_shutdown(struct pci_dev *pdev)
+{
+ qlge_suspend(pdev, PMSG_SUSPEND);
+}
+
+static struct pci_driver qlge_driver = {
+ .name = DRV_NAME,
+ .id_table = qlge_pci_tbl,
+ .probe = qlge_probe,
+ .remove = __devexit_p(qlge_remove),
+#ifdef CONFIG_PM
+ .suspend = qlge_suspend,
+ .resume = qlge_resume,
+#endif
+ .shutdown = qlge_shutdown,
+ .err_handler = &qlge_err_handler
+};
+
+static int __init qlge_init_module(void)
+{
+ return pci_register_driver(&qlge_driver);
+}
+
+static void __exit qlge_exit(void)
+{
+ pci_unregister_driver(&qlge_driver);
+}
+
+module_init(qlge_init_module);
+module_exit(qlge_exit);
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
new file mode 100644
index 00000000000..24fe344bcf1
--- /dev/null
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -0,0 +1,150 @@
+#include "qlge.h"
+
+static int ql_read_mbox_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
+{
+ int status;
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
+ if (status)
+ goto exit;
+ /* set up for reg read */
+ ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R);
+ /* wait for reg to come ready */
+ status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
+ if (status)
+ goto exit;
+ /* get the data */
+ *data = ql_read32(qdev, PROC_DATA);
+exit:
+ return status;
+}
+
+int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
+{
+ int i, status;
+
+ status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK);
+ if (status)
+ return -EBUSY;
+ for (i = 0; i < mbcp->out_count; i++) {
+ status =
+ ql_read_mbox_reg(qdev, qdev->mailbox_out + i,
+ &mbcp->mbox_out[i]);
+ if (status) {
+ QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n");
+ break;
+ }
+ }
+ ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */
+ return status;
+}
+
+static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
+{
+ mbcp->out_count = 2;
+
+ if (ql_get_mb_sts(qdev, mbcp))
+ goto exit;
+
+ qdev->link_status = mbcp->mbox_out[1];
+ QPRINTK(qdev, DRV, ERR, "Link Up.\n");
+ QPRINTK(qdev, DRV, INFO, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
+ if (!netif_carrier_ok(qdev->ndev)) {
+ QPRINTK(qdev, LINK, INFO, "Link is Up.\n");
+ netif_carrier_on(qdev->ndev);
+ netif_wake_queue(qdev->ndev);
+ }
+exit:
+ /* Clear the MPI firmware status. */
+ ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
+}
+
+static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
+{
+ mbcp->out_count = 3;
+
+ if (ql_get_mb_sts(qdev, mbcp)) {
+ QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
+ goto exit;
+ }
+
+ if (netif_carrier_ok(qdev->ndev)) {
+ QPRINTK(qdev, LINK, INFO, "Link is Down.\n");
+ netif_carrier_off(qdev->ndev);
+ netif_stop_queue(qdev->ndev);
+ }
+ QPRINTK(qdev, DRV, ERR, "Link Down.\n");
+ QPRINTK(qdev, DRV, ERR, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
+exit:
+ /* Clear the MPI firmware status. */
+ ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
+}
+
+static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp)
+{
+ mbcp->out_count = 2;
+
+ if (ql_get_mb_sts(qdev, mbcp)) {
+ QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
+ goto exit;
+ }
+ QPRINTK(qdev, DRV, ERR, "Firmware initialized!\n");
+ QPRINTK(qdev, DRV, ERR, "Firmware status = 0x%.08x.\n",
+ mbcp->mbox_out[0]);
+ QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n",
+ mbcp->mbox_out[1]);
+exit:
+ /* Clear the MPI firmware status. */
+ ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
+}
+
+void ql_mpi_work(struct work_struct *work)
+{
+ struct ql_adapter *qdev =
+ container_of(work, struct ql_adapter, mpi_work.work);
+ struct mbox_params mbc;
+ struct mbox_params *mbcp = &mbc;
+ mbcp->out_count = 1;
+
+ while (ql_read32(qdev, STS) & STS_PI) {
+ if (ql_get_mb_sts(qdev, mbcp)) {
+ QPRINTK(qdev, DRV, ERR,
+ "Could not read MPI, resetting ASIC!\n");
+ ql_queue_asic_error(qdev);
+ }
+
+ switch (mbcp->mbox_out[0]) {
+ case AEN_LINK_UP:
+ ql_link_up(qdev, mbcp);
+ break;
+ case AEN_LINK_DOWN:
+ ql_link_down(qdev, mbcp);
+ break;
+ case AEN_FW_INIT_DONE:
+ ql_init_fw_done(qdev, mbcp);
+ break;
+ case MB_CMD_STS_GOOD:
+ break;
+ case AEN_FW_INIT_FAIL:
+ case AEN_SYS_ERR:
+ case MB_CMD_STS_ERR:
+ ql_queue_fw_error(qdev);
+ default:
+ /* Clear the MPI firmware status. */
+ ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
+ break;
+ }
+ }
+ ql_enable_completion_interrupt(qdev, 0);
+}
+
+void ql_mpi_reset_work(struct work_struct *work)
+{
+ struct ql_adapter *qdev =
+ container_of(work, struct ql_adapter, mpi_reset_work.work);
+ QPRINTK(qdev, DRV, ERR,
+ "Enter, qdev = %p..\n", qdev);
+ ql_write32(qdev, CSR, CSR_CMD_SET_RST);
+ msleep(50);
+ ql_write32(qdev, CSR, CSR_CMD_CLR_RST);
+}
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 5d86281d936..34fe7ef8e5e 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -265,7 +265,7 @@ static void r6040_free_txbufs(struct net_device *dev)
le32_to_cpu(lp->tx_insert_ptr->buf),
MAX_BUF_SIZE, PCI_DMA_TODEVICE);
dev_kfree_skb(lp->tx_insert_ptr->skb_ptr);
- lp->rx_insert_ptr->skb_ptr = NULL;
+ lp->tx_insert_ptr->skb_ptr = NULL;
}
lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp;
}
@@ -370,7 +370,7 @@ static void r6040_init_mac_regs(struct net_device *dev)
/* Reset internal state machine */
iowrite16(2, ioaddr + MAC_SM);
iowrite16(0, ioaddr + MAC_SM);
- udelay(5000);
+ mdelay(5);
/* MAC Bus Control Register */
iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
@@ -806,7 +806,7 @@ static void r6040_mac_address(struct net_device *dev)
iowrite16(0x01, ioaddr + MCR1); /* Reset MAC */
iowrite16(2, ioaddr + MAC_SM); /* Reset internal state machine */
iowrite16(0, ioaddr + MAC_SM);
- udelay(5000);
+ mdelay(5);
/* Restore MAC Address */
adrp = (u16 *) dev->dev_addr;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 0f6f9747d25..c821da21d8e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -36,7 +36,7 @@
#define assert(expr) \
if (!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
- #expr,__FILE__,__FUNCTION__,__LINE__); \
+ #expr,__FILE__,__func__,__LINE__); \
}
#define dprintk(fmt, args...) \
do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
@@ -61,6 +61,7 @@ static const int multicast_filter_limit = 32;
/* MAC address length */
#define MAC_ADDR_LEN 6
+#define MAX_READ_REQUEST_SHIFT 12
#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
@@ -95,6 +96,10 @@ enum mac_version {
RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+ RTL_GIGA_MAC_VER_07 = 0x07, // 8102e
+ RTL_GIGA_MAC_VER_08 = 0x08, // 8102e
+ RTL_GIGA_MAC_VER_09 = 0x09, // 8102e
+ RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e
RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be
RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb
@@ -104,7 +109,12 @@ enum mac_version {
RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf
RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP
RTL_GIGA_MAC_VER_19 = 0x13, // 8168C
- RTL_GIGA_MAC_VER_20 = 0x14 // 8168C
+ RTL_GIGA_MAC_VER_20 = 0x14, // 8168C
+ RTL_GIGA_MAC_VER_21 = 0x15, // 8168C
+ RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
+ RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
+ RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
+ RTL_GIGA_MAC_VER_25 = 0x19 // 8168D
};
#define _R(NAME,MAC,MASK) \
@@ -121,6 +131,10 @@ static const struct {
_R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
+ _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E
+ _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E
+ _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -130,7 +144,12 @@ static const struct {
_R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
- _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
+ _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E
};
#undef _R
@@ -196,9 +215,6 @@ enum rtl_registers {
Config5 = 0x56,
MultiIntr = 0x5c,
PHYAR = 0x60,
- TBICSR = 0x64,
- TBI_ANAR = 0x68,
- TBI_LPAR = 0x6a,
PHYstatus = 0x6c,
RxMaxSize = 0xda,
CPlusCmd = 0xe0,
@@ -212,6 +228,32 @@ enum rtl_registers {
FuncForceEvent = 0xfc,
};
+enum rtl8110_registers {
+ TBICSR = 0x64,
+ TBI_ANAR = 0x68,
+ TBI_LPAR = 0x6a,
+};
+
+enum rtl8168_8101_registers {
+ CSIDR = 0x64,
+ CSIAR = 0x68,
+#define CSIAR_FLAG 0x80000000
+#define CSIAR_WRITE_CMD 0x80000000
+#define CSIAR_BYTE_ENABLE 0x0f
+#define CSIAR_BYTE_ENABLE_SHIFT 12
+#define CSIAR_ADDR_MASK 0x0fff
+
+ EPHYAR = 0x80,
+#define EPHYAR_FLAG 0x80000000
+#define EPHYAR_WRITE_CMD 0x80000000
+#define EPHYAR_REG_MASK 0x1f
+#define EPHYAR_REG_SHIFT 16
+#define EPHYAR_DATA_MASK 0xffff
+ DBG_REG = 0xd1,
+#define FIX_NAK_1 (1 << 4)
+#define FIX_NAK_2 (1 << 3)
+};
+
enum rtl_register_content {
/* InterruptStatusBits */
SYSErr = 0x8000,
@@ -265,7 +307,13 @@ enum rtl_register_content {
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/* Config1 register p.24 */
+ LEDS1 = (1 << 7),
+ LEDS0 = (1 << 6),
MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
+ Speed_down = (1 << 4),
+ MEMMAP = (1 << 3),
+ IOMAP = (1 << 2),
+ VPD = (1 << 1),
PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */
@@ -275,6 +323,7 @@ enum rtl_register_content {
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
+ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
/* Config5 register p.27 */
BWF = (1 << 6), /* Accept Broadcast wakeup frame */
@@ -292,7 +341,16 @@ enum rtl_register_content {
TBINwComplete = 0x01000000,
/* CPlusCmd p.31 */
- PktCntrDisable = (1 << 7), // 8168
+ EnableBist = (1 << 15), // 8168 8101
+ Mac_dbgo_oe = (1 << 14), // 8168 8101
+ Normal_mode = (1 << 13), // unused
+ Force_half_dup = (1 << 12), // 8168 8101
+ Force_rxflow_en = (1 << 11), // 8168 8101
+ Force_txflow_en = (1 << 10), // 8168 8101
+ Cxpl_dbg_sel = (1 << 9), // 8168 8101
+ ASF = (1 << 8), // 8168 8101
+ PktCntrDisable = (1 << 7), // 8168 8101
+ Mac_dbgo_sel = 0x001c, // 8168
RxVlan = (1 << 6),
RxChkSum = (1 << 5),
PCIDAC = (1 << 4),
@@ -370,8 +428,9 @@ struct ring_info {
};
enum features {
- RTL_FEATURE_WOL = (1 << 0),
- RTL_FEATURE_MSI = (1 << 1),
+ RTL_FEATURE_WOL = (1 << 0),
+ RTL_FEATURE_MSI = (1 << 1),
+ RTL_FEATURE_GMII = (1 << 2),
};
struct rtl8169_private {
@@ -406,13 +465,16 @@ struct rtl8169_private {
struct vlan_group *vlgrp;
#endif
int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
- void (*get_settings)(struct net_device *, struct ethtool_cmd *);
+ int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *);
void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
+ int pcie_cap;
struct delayed_work task;
unsigned features;
+
+ struct mii_if_info mii;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -482,6 +544,94 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
return value;
}
+static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
+{
+ mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
+}
+
+static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
+ int val)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ mdio_write(ioaddr, location, val);
+}
+
+static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ return mdio_read(ioaddr, location);
+}
+
+static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value)
+{
+ unsigned int i;
+
+ RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
+ (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG))
+ break;
+ udelay(10);
+ }
+}
+
+static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr)
+{
+ u16 value = 0xffff;
+ unsigned int i;
+
+ RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(EPHYAR) & EPHYAR_FLAG) {
+ value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK;
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
+}
+
+static void rtl_csi_write(void __iomem *ioaddr, int addr, int value)
+{
+ unsigned int i;
+
+ RTL_W32(CSIDR, value);
+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
+ break;
+ udelay(10);
+ }
+}
+
+static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
+{
+ u32 value = ~0x00;
+ unsigned int i;
+
+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(CSIAR) & CSIAR_FLAG) {
+ value = RTL_R32(CSIDR);
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
+}
+
static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
{
RTL_W16(IntrMask, 0x0000);
@@ -619,6 +769,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
tp->features |= RTL_FEATURE_WOL;
else
tp->features &= ~RTL_FEATURE_WOL;
+ device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
spin_unlock_irq(&tp->lock);
@@ -705,8 +856,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
}
}
- /* The 8100e/8101e do Fast Ethernet only. */
- if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ /* The 8100e/8101e/8102e do Fast Ethernet only. */
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_07) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_08) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_09) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_10) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
(tp->mac_version == RTL_GIGA_MAC_VER_15) ||
(tp->mac_version == RTL_GIGA_MAC_VER_16)) {
@@ -720,9 +875,13 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
- if ((tp->mac_version == RTL_GIGA_MAC_VER_12) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
- /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
+ (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
+ /*
+ * Wake up the PHY.
+ * Vendor specific (0x1f) and reserved (0x0e) MII registers.
+ */
mdio_write(ioaddr, 0x1f, 0x0000);
mdio_write(ioaddr, 0x0e, 0x0000);
}
@@ -850,7 +1009,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
#endif
-static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
+static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
@@ -867,65 +1026,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->speed = SPEED_1000;
cmd->duplex = DUPLEX_FULL; /* Always set */
+
+ return 0;
}
-static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
+static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
- u8 status;
-
- cmd->supported = SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_TP;
-
- cmd->autoneg = 1;
- cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
-
- if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)
- cmd->advertising |= ADVERTISED_10baseT_Half;
- if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)
- cmd->advertising |= ADVERTISED_10baseT_Full;
- if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)
- cmd->advertising |= ADVERTISED_100baseT_Half;
- if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)
- cmd->advertising |= ADVERTISED_100baseT_Full;
- if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)
- cmd->advertising |= ADVERTISED_1000baseT_Full;
-
- status = RTL_R8(PHYstatus);
-
- if (status & _1000bpsF)
- cmd->speed = SPEED_1000;
- else if (status & _100bps)
- cmd->speed = SPEED_100;
- else if (status & _10bps)
- cmd->speed = SPEED_10;
-
- if (status & TxFlowCtrl)
- cmd->advertising |= ADVERTISED_Asym_Pause;
- if (status & RxFlowCtrl)
- cmd->advertising |= ADVERTISED_Pause;
-
- cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
- DUPLEX_FULL : DUPLEX_HALF;
+
+ return mii_ethtool_gset(&tp->mii, cmd);
}
static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
unsigned long flags;
+ int rc;
spin_lock_irqsave(&tp->lock, flags);
- tp->get_settings(dev, cmd);
+ rc = tp->get_settings(dev, cmd);
spin_unlock_irqrestore(&tp->lock, flags);
- return 0;
+ return rc;
}
static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
@@ -1103,11 +1226,19 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
u32 val;
int mac_version;
} mac_info[] = {
- /* 8168B family. */
- { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ /* 8168D family. */
+ { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 },
+
+ /* 8168C family. */
+ { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
+ { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
{ 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
{ 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
- { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 },
+ { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
+ { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
+ { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
/* 8168B family. */
{ 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
@@ -1116,8 +1247,17 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
{ 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
/* 8101 family. */
+ { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
+ { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
{ 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
+ { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
{ 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
+ { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
+ { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
{ 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
/* FIXME: where did these entries come from ? -- FR */
{ 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
@@ -1228,7 +1368,31 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
-static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168bb_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x10, 0xf41b },
+ { 0x1f, 0x0000 }
+ };
+
+ mdio_write(ioaddr, 0x1f, 0x0001);
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168bef_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x10, 0xf41b },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
{ 0x1f, 0x0000 },
@@ -1241,7 +1405,22 @@ static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
-static void rtl8168c_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x1d, 0x3d98 },
+ { 0x1f, 0x0000 }
+ };
+
+ mdio_write(ioaddr, 0x1f, 0x0000);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
{ 0x1f, 0x0001 },
@@ -1257,25 +1436,157 @@ static void rtl8168c_hw_phy_config(void __iomem *ioaddr)
{ 0x1f, 0x0003 },
{ 0x12, 0xc096 },
{ 0x16, 0x000a },
- { 0x1f, 0x0000 }
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x09, 0x2000 },
+ { 0x09, 0x0000 }
};
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
}
-static void rtl8168cx_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
- { 0x1f, 0x0000 },
+ { 0x1f, 0x0001 },
{ 0x12, 0x2300 },
+ { 0x03, 0x802f },
+ { 0x02, 0x4f02 },
+ { 0x01, 0x0409 },
+ { 0x00, 0xf099 },
+ { 0x04, 0x9800 },
+ { 0x04, 0x9000 },
+ { 0x1d, 0x3d98 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x7eb8 },
+ { 0x06, 0x0761 },
{ 0x1f, 0x0003 },
{ 0x16, 0x0f0a },
- { 0x1f, 0x0000 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x1d, 0x3d98 },
{ 0x1f, 0x0002 },
{ 0x0c, 0x7eb8 },
+ { 0x06, 0x5461 },
+ { 0x1f, 0x0003 },
+ { 0x16, 0x0f0a },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
+{
+ rtl8168c_3_hw_phy_config(ioaddr);
+}
+
+static void rtl8168d_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init_0[] = {
+ { 0x1f, 0x0001 },
+ { 0x09, 0x2770 },
+ { 0x08, 0x04d0 },
+ { 0x0b, 0xad15 },
+ { 0x0c, 0x5bf0 },
+ { 0x1c, 0xf101 },
+ { 0x1f, 0x0003 },
+ { 0x14, 0x94d7 },
+ { 0x12, 0xf4d6 },
+ { 0x09, 0xca0f },
+ { 0x1f, 0x0002 },
+ { 0x0b, 0x0b10 },
+ { 0x0c, 0xd1f7 },
+ { 0x1f, 0x0002 },
+ { 0x06, 0x5461 },
+ { 0x1f, 0x0002 },
+ { 0x05, 0x6662 },
+ { 0x1f, 0x0000 },
+ { 0x14, 0x0060 },
+ { 0x1f, 0x0000 },
+ { 0x0d, 0xf8a0 },
+ { 0x1f, 0x0005 },
+ { 0x05, 0xffc2 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+ if (mdio_read(ioaddr, 0x06) == 0xc400) {
+ struct phy_reg phy_reg_init_1[] = {
+ { 0x1f, 0x0005 },
+ { 0x01, 0x0300 },
+ { 0x1f, 0x0000 },
+ { 0x11, 0x401c },
+ { 0x16, 0x4100 },
+ { 0x1f, 0x0005 },
+ { 0x07, 0x0010 },
+ { 0x05, 0x83dc },
+ { 0x06, 0x087d },
+ { 0x05, 0x8300 },
+ { 0x06, 0x0101 },
+ { 0x06, 0x05f8 },
+ { 0x06, 0xf9fa },
+ { 0x06, 0xfbef },
+ { 0x06, 0x79e2 },
+ { 0x06, 0x835f },
+ { 0x06, 0xe0f8 },
+ { 0x06, 0x9ae1 },
+ { 0x06, 0xf89b },
+ { 0x06, 0xef31 },
+ { 0x06, 0x3b65 },
+ { 0x06, 0xaa07 },
+ { 0x06, 0x81e4 },
+ { 0x06, 0xf89a },
+ { 0x06, 0xe5f8 },
+ { 0x06, 0x9baf },
+ { 0x06, 0x06ae },
+ { 0x05, 0x83dc },
+ { 0x06, 0x8300 },
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init_1,
+ ARRAY_SIZE(phy_reg_init_1));
+ }
+
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0003 },
+ { 0x08, 0x441d },
+ { 0x01, 0x9100 },
{ 0x1f, 0x0000 }
};
+ mdio_write(ioaddr, 0x1f, 0x0000);
+ mdio_patch(ioaddr, 0x11, 1 << 12);
+ mdio_patch(ioaddr, 0x19, 1 << 13);
+
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
@@ -1296,15 +1607,43 @@ static void rtl_hw_phy_config(struct net_device *dev)
case RTL_GIGA_MAC_VER_04:
rtl8169sb_hw_phy_config(ioaddr);
break;
+ case RTL_GIGA_MAC_VER_07:
+ case RTL_GIGA_MAC_VER_08:
+ case RTL_GIGA_MAC_VER_09:
+ rtl8102e_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_11:
+ rtl8168bb_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_12:
+ rtl8168bef_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_17:
+ rtl8168bef_hw_phy_config(ioaddr);
+ break;
case RTL_GIGA_MAC_VER_18:
- rtl8168cp_hw_phy_config(ioaddr);
+ rtl8168cp_1_hw_phy_config(ioaddr);
break;
case RTL_GIGA_MAC_VER_19:
- rtl8168c_hw_phy_config(ioaddr);
+ rtl8168c_1_hw_phy_config(ioaddr);
break;
case RTL_GIGA_MAC_VER_20:
- rtl8168cx_hw_phy_config(ioaddr);
+ rtl8168c_2_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_21:
+ rtl8168c_3_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_22:
+ rtl8168c_4_hw_phy_config(ioaddr);
break;
+ case RTL_GIGA_MAC_VER_23:
+ case RTL_GIGA_MAC_VER_24:
+ rtl8168cp_2_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_25:
+ rtl8168d_hw_phy_config(ioaddr);
+ break;
+
default:
break;
}
@@ -1513,7 +1852,7 @@ static const struct rtl_cfg_info {
unsigned int align;
u16 intr_event;
u16 napi_event;
- unsigned msi;
+ unsigned features;
} rtl_cfg_infos [] = {
[RTL_CFG_0] = {
.hw_start = rtl_hw_start_8169,
@@ -1522,7 +1861,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
- .msi = 0
+ .features = RTL_FEATURE_GMII
},
[RTL_CFG_1] = {
.hw_start = rtl_hw_start_8168,
@@ -1531,7 +1870,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow |
TxErr | TxOK | RxOK | RxErr,
.napi_event = TxErr | TxOK | RxOK | RxOverflow,
- .msi = RTL_FEATURE_MSI
+ .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI
},
[RTL_CFG_2] = {
.hw_start = rtl_hw_start_8101,
@@ -1540,7 +1879,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
- .msi = RTL_FEATURE_MSI
+ .features = RTL_FEATURE_MSI
}
};
@@ -1552,7 +1891,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
u8 cfg2;
cfg2 = RTL_R8(Config2) & ~MSIEnable;
- if (cfg->msi) {
+ if (cfg->features & RTL_FEATURE_MSI) {
if (pci_enable_msi(pdev)) {
dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
} else {
@@ -1572,12 +1911,81 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
}
}
+static int rtl_eeprom_read(struct pci_dev *pdev, int cap, int addr, __le32 *val)
+{
+ int ret, count = 100;
+ u16 status = 0;
+ u32 value;
+
+ ret = pci_write_config_word(pdev, cap + PCI_VPD_ADDR, addr);
+ if (ret < 0)
+ return ret;
+
+ do {
+ udelay(10);
+ ret = pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &status);
+ if (ret < 0)
+ return ret;
+ } while (!(status & PCI_VPD_ADDR_F) && --count);
+
+ if (!(status & PCI_VPD_ADDR_F))
+ return -ETIMEDOUT;
+
+ ret = pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &value);
+ if (ret < 0)
+ return ret;
+
+ *val = cpu_to_le32(value);
+
+ return 0;
+}
+
+static void rtl_init_mac_address(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ struct pci_dev *pdev = tp->pci_dev;
+ u8 cfg1;
+ int vpd_cap;
+ u8 mac[8];
+ DECLARE_MAC_BUF(buf);
+
+ cfg1 = RTL_R8(Config1);
+ if (!(cfg1 & VPD)) {
+ dprintk("VPD access not enabled, enabling\n");
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+ RTL_W8(Config1, cfg1 | VPD);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+ }
+
+ vpd_cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
+ if (!vpd_cap)
+ return;
+
+ /* MAC address is stored in EEPROM at offset 0x0e
+ * Realtek says: "The VPD address does not have to be a DWORD-aligned
+ * address as defined in the PCI 2.2 Specifications, but the VPD data
+ * is always consecutive 4-byte data starting from the VPD address
+ * specified."
+ */
+ if (rtl_eeprom_read(pdev, vpd_cap, 0x000e, (__le32*)&mac[0]) < 0 ||
+ rtl_eeprom_read(pdev, vpd_cap, 0x0012, (__le32*)&mac[4]) < 0) {
+ dprintk("Reading MAC address from EEPROM failed\n");
+ return;
+ }
+
+ dprintk("MAC address found in EEPROM: %s\n", print_mac(buf, mac));
+
+ /* Write MAC address */
+ rtl_rar_set(tp, mac);
+}
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
const unsigned int region = cfg->region;
struct rtl8169_private *tp;
+ struct mii_if_info *mii;
struct net_device *dev;
void __iomem *ioaddr;
unsigned int i;
@@ -1602,6 +2010,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->pci_dev = pdev;
tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
+ mii = &tp->mii;
+ mii->dev = dev;
+ mii->mdio_read = rtl_mdio_read;
+ mii->mdio_write = rtl_mdio_write;
+ mii->phy_id_mask = 0x1f;
+ mii->reg_num_mask = 0x1f;
+ mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
+
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
if (rc < 0) {
@@ -1670,6 +2086,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_res_4;
}
+ tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (!tp->pcie_cap && netif_msg_probe(tp))
+ dev_info(&pdev->dev, "no PCI Express capability\n");
+
/* Unneeded ? Don't mess with Mrs. Murphy. */
rtl8169_irq_mask_and_ack(ioaddr);
@@ -1706,6 +2126,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+ if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
+ tp->features |= RTL_FEATURE_WOL;
+ if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
+ tp->features |= RTL_FEATURE_WOL;
tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -1728,7 +2152,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->do_ioctl = rtl8169_ioctl;
}
- /* Get MAC address. FIXME: read EEPROM */
+ spin_lock_init(&tp->lock);
+
+ tp->mmio_addr = ioaddr;
+
+ rtl_init_mac_address(tp, ioaddr);
+
+ /* Get MAC address */
for (i = 0; i < MAC_ADDR_LEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
@@ -1758,7 +2188,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif
tp->intr_mask = 0xffff;
- tp->mmio_addr = ioaddr;
tp->align = cfg->align;
tp->hw_start = cfg->hw_start;
tp->intr_event = cfg->intr_event;
@@ -1768,8 +2197,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->timer.data = (unsigned long) dev;
tp->timer.function = rtl8169_phy_timer;
- spin_lock_init(&tp->lock);
-
rc = register_netdev(dev);
if (rc < 0)
goto err_out_msi_5;
@@ -1791,6 +2218,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
rtl8169_init_phy(dev, tp);
+ device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
out:
return rc;
@@ -2061,12 +2489,209 @@ static void rtl_hw_start_8169(struct net_device *dev)
RTL_W16(IntrMask, tp->intr_event);
}
+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int cap = tp->pcie_cap;
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+}
+
+static void rtl_csi_access_enable(void __iomem *ioaddr)
+{
+ u32 csi;
+
+ csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff;
+ rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000);
+}
+
+struct ephy_info {
+ unsigned int offset;
+ u16 mask;
+ u16 bits;
+};
+
+static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len)
+{
+ u16 w;
+
+ while (len-- > 0) {
+ w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits;
+ rtl_ephy_write(ioaddr, e->offset, w);
+ e++;
+ }
+}
+
+static void rtl_disable_clock_request(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int cap = tp->pcie_cap;
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl);
+ ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl);
+ }
+}
+
+#define R8168_CPCMD_QUIRK_MASK (\
+ EnableBist | \
+ Mac_dbgo_oe | \
+ Force_half_dup | \
+ Force_rxflow_en | \
+ Force_txflow_en | \
+ Cxpl_dbg_sel | \
+ ASF | \
+ PktCntrDisable | \
+ Mac_dbgo_sel)
+
+static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+
+ rtl_tx_performance_tweak(pdev,
+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_hw_start_8168bb(ioaddr, pdev);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ rtl_disable_clock_request(pdev);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static struct ephy_info e_info_8168cp[] = {
+ { 0x01, 0, 0x0001 },
+ { 0x02, 0x0800, 0x1000 },
+ { 0x03, 0, 0x0042 },
+ { 0x06, 0x0080, 0x0000 },
+ { 0x07, 0, 0x2000 }
+ };
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ /* Magic. */
+ RTL_W8(DBG_REG, 0x20);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static struct ephy_info e_info_8168c_1[] = {
+ { 0x02, 0x0800, 0x1000 },
+ { 0x03, 0, 0x0002 },
+ { 0x06, 0x0080, 0x0000 }
+ };
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
+
+ rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static struct ephy_info e_info_8168c_2[] = {
+ { 0x01, 0, 0x0001 },
+ { 0x03, 0x0400, 0x0220 }
+ };
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_hw_start_8168c_2(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_csi_access_enable(ioaddr);
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_disable_clock_request(pdev);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
static void rtl_hw_start_8168(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
- u8 ctl;
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -2074,17 +2699,10 @@ static void rtl_hw_start_8168(struct net_device *dev)
rtl_set_rx_max_size(ioaddr);
- rtl_set_rx_tx_config_registers(tp);
-
tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
RTL_W16(CPlusCmd, tp->cp_cmd);
- /* Tx performance tweak. */
- pci_read_config_byte(pdev, 0x69, &ctl);
- ctl = (ctl & ~0x70) | 0x50;
- pci_write_config_byte(pdev, 0x69, ctl);
-
RTL_W16(IntrMitigate, 0x5151);
/* Work around for RxFIFO overflow. */
@@ -2095,21 +2713,134 @@ static void rtl_hw_start_8168(struct net_device *dev)
rtl_set_rx_tx_desc_registers(tp, ioaddr);
- RTL_W8(Cfg9346, Cfg9346_Lock);
+ rtl_set_rx_mode(dev);
+
+ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
+ (InterFrameGap << TxInterFrameGapShift));
RTL_R8(IntrMask);
- RTL_W32(RxMissed, 0);
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_11:
+ rtl_hw_start_8168bb(ioaddr, pdev);
+ break;
- rtl_set_rx_mode(dev);
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_17:
+ rtl_hw_start_8168bef(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_18:
+ rtl_hw_start_8168cp_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_19:
+ rtl_hw_start_8168c_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_20:
+ rtl_hw_start_8168c_2(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_21:
+ rtl_hw_start_8168c_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_22:
+ rtl_hw_start_8168c_4(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_23:
+ rtl_hw_start_8168cp_2(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_24:
+ rtl_hw_start_8168cp_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_25:
+ rtl_hw_start_8168d(ioaddr, pdev);
+ break;
+
+ default:
+ printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
+ dev->name, tp->mac_version);
+ break;
+ }
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
RTL_W16(IntrMask, tp->intr_event);
}
+#define R810X_CPCMD_QUIRK_MASK (\
+ EnableBist | \
+ Mac_dbgo_oe | \
+ Force_half_dup | \
+ Force_half_dup | \
+ Force_txflow_en | \
+ Cxpl_dbg_sel | \
+ ASF | \
+ PktCntrDisable | \
+ PCIDAC | \
+ PCIMulRW)
+
+static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static struct ephy_info e_info_8102e_1[] = {
+ { 0x01, 0, 0x6e65 },
+ { 0x02, 0, 0x091f },
+ { 0x03, 0, 0xc2f9 },
+ { 0x06, 0, 0xafb5 },
+ { 0x07, 0, 0x0e00 },
+ { 0x19, 0, 0xec80 },
+ { 0x01, 0, 0x2e65 },
+ { 0x01, 0, 0x6e65 }
+ };
+ u8 cfg1;
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(DBG_REG, FIX_NAK_1);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W8(Config1,
+ LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ cfg1 = RTL_R8(Config1);
+ if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
+ RTL_W8(Config1, cfg1 & ~LEDS0);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
+
+ rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
+}
+
+static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ rtl_hw_start_8102e_2(ioaddr, pdev);
+
+ rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
+}
+
static void rtl_hw_start_8101(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -2118,8 +2849,26 @@ static void rtl_hw_start_8101(struct net_device *dev)
if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_16)) {
- pci_write_config_word(pdev, 0x68, 0x00);
- pci_write_config_word(pdev, 0x69, 0x08);
+ int cap = tp->pcie_cap;
+
+ if (cap) {
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_NOSNOOP_EN);
+ }
+ }
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_07:
+ rtl_hw_start_8102e_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_08:
+ rtl_hw_start_8102e_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_09:
+ rtl_hw_start_8102e_2(ioaddr, pdev);
+ break;
}
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -2143,8 +2892,6 @@ static void rtl_hw_start_8101(struct net_device *dev)
RTL_R8(IntrMask);
- RTL_W32(RxMissed, 0);
-
rtl_set_rx_mode(dev);
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
@@ -2922,6 +3669,17 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
return work_done;
}
+static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (tp->mac_version > RTL_GIGA_MAC_VER_06)
+ return;
+
+ dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
+ RTL_W32(RxMissed, 0);
+}
+
static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -2939,9 +3697,7 @@ core_down:
rtl8169_asic_down(ioaddr);
- /* Update the error counts. */
- dev->stats.rx_missed_errors += RTL_R32(RxMissed);
- RTL_W32(RxMissed, 0);
+ rtl8169_rx_missed(dev, ioaddr);
spin_unlock_irq(&tp->lock);
@@ -3063,8 +3819,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
if (netif_running(dev)) {
spin_lock_irqsave(&tp->lock, flags);
- dev->stats.rx_missed_errors += RTL_R32(RxMissed);
- RTL_W32(RxMissed, 0);
+ rtl8169_rx_missed(dev, ioaddr);
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -3089,8 +3844,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
rtl8169_asic_down(ioaddr);
- dev->stats.rx_missed_errors += RTL_R32(RxMissed);
- RTL_W32(RxMissed, 0);
+ rtl8169_rx_missed(dev, ioaddr);
spin_unlock_irq(&tp->lock);
@@ -3121,6 +3875,11 @@ out:
return 0;
}
+static void rtl_shutdown(struct pci_dev *pdev)
+{
+ rtl8169_suspend(pdev, PMSG_SUSPEND);
+}
+
#endif /* CONFIG_PM */
static struct pci_driver rtl8169_pci_driver = {
@@ -3131,6 +3890,7 @@ static struct pci_driver rtl8169_pci_driver = {
#ifdef CONFIG_PM
.suspend = rtl8169_suspend,
.resume = rtl8169_resume,
+ .shutdown = rtl_shutdown,
#endif
};
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index a2b073097e5..6a1375f9cbb 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -371,9 +371,6 @@ static void s2io_vlan_rx_register(struct net_device *dev,
flags[i]);
}
-/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
-static int vlan_strip_flag;
-
/* Unregister the vlan */
static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
{
@@ -2303,7 +2300,7 @@ static int start_nic(struct s2io_nic *nic)
val64 = readq(&bar0->rx_pa_cfg);
val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
writeq(val64, &bar0->rx_pa_cfg);
- vlan_strip_flag = 0;
+ nic->vlan_strip_flag = 0;
}
/*
@@ -3136,7 +3133,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
if (skb == NULL) {
spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
DBG_PRINT(ERR_DBG, "%s: Null skb ",
- __FUNCTION__);
+ __func__);
DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
return;
}
@@ -3496,7 +3493,7 @@ static void s2io_reset(struct s2io_nic * sp)
unsigned long long mem_alloc_cnt, mem_free_cnt, watchdog_cnt;
DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n",
- __FUNCTION__, sp->dev->name);
+ __func__, sp->dev->name);
/* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
@@ -3518,7 +3515,7 @@ static void s2io_reset(struct s2io_nic * sp)
}
if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) {
- DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__);
+ DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __func__);
}
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd);
@@ -3768,7 +3765,7 @@ static void restore_xmsi_data(struct s2io_nic *nic)
val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6));
writeq(val64, &bar0->xmsi_access);
if (wait_for_msix_trans(nic, msix_index)) {
- DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __func__);
continue;
}
}
@@ -3789,7 +3786,7 @@ static void store_xmsi_data(struct s2io_nic *nic)
val64 = (s2BIT(15) | vBIT(msix_index, 26, 6));
writeq(val64, &bar0->xmsi_access);
if (wait_for_msix_trans(nic, msix_index)) {
- DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __func__);
continue;
}
addr = readq(&bar0->xmsi_address);
@@ -3812,7 +3809,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
GFP_KERNEL);
if (!nic->entries) {
DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \
- __FUNCTION__);
+ __func__);
nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
return -ENOMEM;
}
@@ -3826,7 +3823,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
GFP_KERNEL);
if (!nic->s2io_entries) {
DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n",
- __FUNCTION__);
+ __func__);
nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
kfree(nic->entries);
nic->mac_control.stats_info->sw_stat.mem_freed
@@ -5010,7 +5007,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->rx_pa_cfg);
val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
writeq(val64, &bar0->rx_pa_cfg);
- vlan_strip_flag = 0;
+ sp->vlan_strip_flag = 0;
}
val64 = readq(&bar0->mac_cfg);
@@ -5032,7 +5029,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->rx_pa_cfg);
val64 |= RX_PA_CFG_STRIP_VLAN_TAG;
writeq(val64, &bar0->rx_pa_cfg);
- vlan_strip_flag = 1;
+ sp->vlan_strip_flag = 1;
}
val64 = readq(&bar0->mac_cfg);
@@ -6746,7 +6743,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
ret = s2io_card_up(sp);
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
- __FUNCTION__);
+ __func__);
return ret;
}
s2io_wake_all_tx_queue(sp);
@@ -7530,7 +7527,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
default:
DBG_PRINT(ERR_DBG,
"%s: Samadhana!!\n",
- __FUNCTION__);
+ __func__);
BUG();
}
}
@@ -7781,7 +7778,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
return -ENOMEM;
}
if ((ret = pci_request_regions(pdev, s2io_driver_name))) {
- DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __FUNCTION__, ret);
+ DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __func__, ret);
pci_disable_device(pdev);
return -ENODEV;
}
@@ -7998,7 +7995,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
if (sp->device_type & XFRAME_II_DEVICE) {
mode = s2io_verify_pci_mode(sp);
if (mode < 0) {
- DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "%s: ", __func__);
DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
ret = -EBADSLT;
goto set_swap_failed;
@@ -8175,8 +8172,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
break;
}
if (sp->config.multiq) {
- for (i = 0; i < sp->config.tx_fifo_num; i++)
- mac_control->fifos[i].multiq = config->multiq;
+ for (i = 0; i < sp->config.tx_fifo_num; i++)
+ mac_control->fifos[i].multiq = config->multiq;
DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
dev->name);
} else
@@ -8206,6 +8203,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
/* Initialize device name */
sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
+ if (vlan_tag_strip)
+ sp->vlan_strip_flag = 1;
+ else
+ sp->vlan_strip_flag = 0;
+
/*
* Make Link state as off at this point, when the Link change
* interrupt comes the state will be automatically changed to
@@ -8299,7 +8301,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) {
DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n",
- __FUNCTION__);
+ __func__);
return -1;
}
@@ -8311,7 +8313,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
* If vlan stripping is disabled and the frame is VLAN tagged,
* shift the offset by the VLAN header size bytes.
*/
- if ((!vlan_strip_flag) &&
+ if ((!sp->vlan_strip_flag) &&
(rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
ip_off += HEADER_VLAN_SIZE;
} else {
@@ -8330,7 +8332,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
static int check_for_socket_match(struct lro *lro, struct iphdr *ip,
struct tcphdr *tcp)
{
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__);
if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) ||
(lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest))
return -1;
@@ -8345,7 +8347,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
static void initiate_new_session(struct lro *lro, u8 *l2h,
struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag)
{
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__);
lro->l2h = l2h;
lro->iph = ip;
lro->tcph = tcp;
@@ -8375,7 +8377,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
struct tcphdr *tcp = lro->tcph;
__sum16 nchk;
struct stat_block *statinfo = sp->mac_control.stats_info;
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__);
/* Update L3 header */
ip->tot_len = htons(lro->total_len);
@@ -8403,7 +8405,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
static void aggregate_new_rx(struct lro *lro, struct iphdr *ip,
struct tcphdr *tcp, u32 l4_pyld)
{
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__);
lro->total_len += l4_pyld;
lro->frags_len += l4_pyld;
lro->tcp_next_seq += l4_pyld;
@@ -8427,7 +8429,7 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
{
u8 *ptr;
- DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__);
if (!tcp_pyld_len) {
/* Runt frame or a pure ack */
@@ -8509,7 +8511,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp,
if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) {
DBG_PRINT(INFO_DBG, "%s:Out of order. expected "
- "0x%x, actual 0x%x\n", __FUNCTION__,
+ "0x%x, actual 0x%x\n", __func__,
(*lro)->tcp_next_seq,
ntohl(tcph->seq));
@@ -8549,7 +8551,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp,
if (ret == 0) { /* sessions exceeded */
DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n",
- __FUNCTION__);
+ __func__);
*lro = NULL;
return ret;
}
@@ -8571,7 +8573,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp,
break;
default:
DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n",
- __FUNCTION__);
+ __func__);
break;
}
@@ -8592,7 +8594,7 @@ static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
skb->protocol = eth_type_trans(skb, dev);
if (sp->vlgrp && vlan_tag
- && (vlan_strip_flag)) {
+ && (sp->vlan_strip_flag)) {
/* Queueing the vlan frame to the upper layer */
if (sp->config.napi)
vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 6722a2f7d09..55cb943f23f 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -962,6 +962,7 @@ struct s2io_nic {
int task_flag;
unsigned long long start_time;
struct vlan_group *vlgrp;
+ int vlan_strip_flag;
#define MSIX_FLG 0xA5
int num_entries;
struct msix_entry *entries;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index fe41e4ec21e..2615d46e6e5 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -256,7 +256,7 @@ struct sbmac_softc {
struct net_device *sbm_dev; /* pointer to linux device */
struct napi_struct napi;
struct phy_device *phy_dev; /* the associated PHY device */
- struct mii_bus mii_bus; /* the MII bus */
+ struct mii_bus *mii_bus; /* the MII bus */
int phy_irq[PHY_MAX_ADDR];
spinlock_t sbm_lock; /* spin lock */
int sbm_devflags; /* current device flags */
@@ -2069,9 +2069,10 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance)
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
+ unsigned long flags;
/* lock eth irq */
- spin_lock_irq (&sc->sbm_lock);
+ spin_lock_irqsave(&sc->sbm_lock, flags);
/*
* Put the buffer on the transmit ring. If we
@@ -2081,14 +2082,14 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
/* XXX save skb that we could not send */
netif_stop_queue(dev);
- spin_unlock_irq(&sc->sbm_lock);
+ spin_unlock_irqrestore(&sc->sbm_lock, flags);
return 1;
}
dev->trans_start = jiffies;
- spin_unlock_irq (&sc->sbm_lock);
+ spin_unlock_irqrestore(&sc->sbm_lock, flags);
return 0;
}
@@ -2347,10 +2348,17 @@ static int sbmac_init(struct platform_device *pldev, long long base)
/* This is needed for PASS2 for Rx H/W checksum feature */
sbmac_set_iphdr_offset(sc);
+ sc->mii_bus = mdiobus_alloc();
+ if (sc->mii_bus == NULL) {
+ sbmac_uninitctx(sc);
+ return -ENOMEM;
+ }
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR "%s.%d: unable to register netdev\n",
sbmac_string, idx);
+ mdiobus_free(sc->mii_bus);
sbmac_uninitctx(sc);
return err;
}
@@ -2368,17 +2376,17 @@ static int sbmac_init(struct platform_device *pldev, long long base)
pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %s\n",
dev->name, base, print_mac(mac, eaddr));
- sc->mii_bus.name = sbmac_mdio_string;
- snprintf(sc->mii_bus.id, MII_BUS_ID_SIZE, "%x", idx);
- sc->mii_bus.priv = sc;
- sc->mii_bus.read = sbmac_mii_read;
- sc->mii_bus.write = sbmac_mii_write;
- sc->mii_bus.irq = sc->phy_irq;
+ sc->mii_bus->name = sbmac_mdio_string;
+ snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
+ sc->mii_bus->priv = sc;
+ sc->mii_bus->read = sbmac_mii_read;
+ sc->mii_bus->write = sbmac_mii_write;
+ sc->mii_bus->irq = sc->phy_irq;
for (i = 0; i < PHY_MAX_ADDR; ++i)
- sc->mii_bus.irq[i] = SBMAC_PHY_INT;
+ sc->mii_bus->irq[i] = SBMAC_PHY_INT;
- sc->mii_bus.dev = &pldev->dev;
- dev_set_drvdata(&pldev->dev, &sc->mii_bus);
+ sc->mii_bus->parent = &pldev->dev;
+ dev_set_drvdata(&pldev->dev, sc->mii_bus);
return 0;
}
@@ -2409,7 +2417,7 @@ static int sbmac_open(struct net_device *dev)
/*
* Probe PHY address
*/
- err = mdiobus_register(&sc->mii_bus);
+ err = mdiobus_register(sc->mii_bus);
if (err) {
printk(KERN_ERR "%s: unable to register MDIO bus\n",
dev->name);
@@ -2446,7 +2454,7 @@ static int sbmac_open(struct net_device *dev)
return 0;
out_unregister:
- mdiobus_unregister(&sc->mii_bus);
+ mdiobus_unregister(sc->mii_bus);
out_unirq:
free_irq(dev->irq, dev);
@@ -2462,7 +2470,7 @@ static int sbmac_mii_probe(struct net_device *dev)
int i;
for (i = 0; i < PHY_MAX_ADDR; i++) {
- phy_dev = sc->mii_bus.phy_map[i];
+ phy_dev = sc->mii_bus->phy_map[i];
if (phy_dev)
break;
}
@@ -2568,14 +2576,15 @@ static void sbmac_mii_poll(struct net_device *dev)
static void sbmac_tx_timeout (struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
+ unsigned long flags;
- spin_lock_irq (&sc->sbm_lock);
+ spin_lock_irqsave(&sc->sbm_lock, flags);
dev->trans_start = jiffies;
dev->stats.tx_errors++;
- spin_unlock_irq (&sc->sbm_lock);
+ spin_unlock_irqrestore(&sc->sbm_lock, flags);
printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
}
@@ -2639,7 +2648,7 @@ static int sbmac_close(struct net_device *dev)
phy_disconnect(sc->phy_dev);
sc->phy_dev = NULL;
- mdiobus_unregister(&sc->mii_bus);
+ mdiobus_unregister(sc->mii_bus);
free_irq(dev->irq, dev);
@@ -2748,6 +2757,7 @@ static int __exit sbmac_remove(struct platform_device *pldev)
unregister_netdev(dev);
sbmac_uninitctx(sc);
+ mdiobus_free(sc->mii_bus);
iounmap(sc->sbm_base);
free_netdev(dev);
diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h
index 2c79d27404e..d95c2182801 100644
--- a/drivers/net/sfc/bitfield.h
+++ b/drivers/net/sfc/bitfield.h
@@ -52,9 +52,9 @@
*
* The maximum width mask that can be generated is 64 bits.
*/
-#define EFX_MASK64(field) \
- (EFX_WIDTH(field) == 64 ? ~((u64) 0) : \
- (((((u64) 1) << EFX_WIDTH(field))) - 1))
+#define EFX_MASK64(width) \
+ ((width) == 64 ? ~((u64) 0) : \
+ (((((u64) 1) << (width))) - 1))
/* Mask equal in width to the specified field.
*
@@ -63,9 +63,9 @@
* The maximum width mask that can be generated is 32 bits. Use
* EFX_MASK64 for higher width fields.
*/
-#define EFX_MASK32(field) \
- (EFX_WIDTH(field) == 32 ? ~((u32) 0) : \
- (((((u32) 1) << EFX_WIDTH(field))) - 1))
+#define EFX_MASK32(width) \
+ ((width) == 32 ? ~((u32) 0) : \
+ (((((u32) 1) << (width))) - 1))
/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */
typedef union efx_dword {
@@ -138,44 +138,49 @@ typedef union efx_oword {
EFX_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high)
#define EFX_EXTRACT_OWORD64(oword, low, high) \
- (EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \
- EFX_EXTRACT64((oword).u64[1], 64, 127, low, high))
+ ((EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \
+ EFX_EXTRACT64((oword).u64[1], 64, 127, low, high)) & \
+ EFX_MASK64(high + 1 - low))
#define EFX_EXTRACT_QWORD64(qword, low, high) \
- EFX_EXTRACT64((qword).u64[0], 0, 63, low, high)
+ (EFX_EXTRACT64((qword).u64[0], 0, 63, low, high) & \
+ EFX_MASK64(high + 1 - low))
#define EFX_EXTRACT_OWORD32(oword, low, high) \
- (EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \
- EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \
- EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \
- EFX_EXTRACT32((oword).u32[3], 96, 127, low, high))
+ ((EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \
+ EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \
+ EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \
+ EFX_EXTRACT32((oword).u32[3], 96, 127, low, high)) & \
+ EFX_MASK32(high + 1 - low))
#define EFX_EXTRACT_QWORD32(qword, low, high) \
- (EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \
- EFX_EXTRACT32((qword).u32[1], 32, 63, low, high))
+ ((EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \
+ EFX_EXTRACT32((qword).u32[1], 32, 63, low, high)) & \
+ EFX_MASK32(high + 1 - low))
-#define EFX_EXTRACT_DWORD(dword, low, high) \
- EFX_EXTRACT32((dword).u32[0], 0, 31, low, high)
+#define EFX_EXTRACT_DWORD(dword, low, high) \
+ (EFX_EXTRACT32((dword).u32[0], 0, 31, low, high) & \
+ EFX_MASK32(high + 1 - low))
-#define EFX_OWORD_FIELD64(oword, field) \
- (EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
- & EFX_MASK64(field))
+#define EFX_OWORD_FIELD64(oword, field) \
+ EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field))
-#define EFX_QWORD_FIELD64(qword, field) \
- (EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
- & EFX_MASK64(field))
+#define EFX_QWORD_FIELD64(qword, field) \
+ EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field))
-#define EFX_OWORD_FIELD32(oword, field) \
- (EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
- & EFX_MASK32(field))
+#define EFX_OWORD_FIELD32(oword, field) \
+ EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field))
-#define EFX_QWORD_FIELD32(qword, field) \
- (EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
- & EFX_MASK32(field))
+#define EFX_QWORD_FIELD32(qword, field) \
+ EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field))
-#define EFX_DWORD_FIELD(dword, field) \
- (EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
- & EFX_MASK32(field))
+#define EFX_DWORD_FIELD(dword, field) \
+ EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field))
#define EFX_OWORD_IS_ZERO64(oword) \
(((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0)
@@ -411,69 +416,102 @@ typedef union efx_oword {
* for read-modify-write operations.
*
*/
-
#define EFX_INVERT_OWORD(oword) do { \
(oword).u64[0] = ~((oword).u64[0]); \
(oword).u64[1] = ~((oword).u64[1]); \
} while (0)
-#define EFX_INSERT_FIELD64(...) \
- cpu_to_le64(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
+#define EFX_AND_OWORD(oword, from, mask) \
+ do { \
+ (oword).u64[0] = (from).u64[0] & (mask).u64[0]; \
+ (oword).u64[1] = (from).u64[1] & (mask).u64[1]; \
+ } while (0)
+
+#define EFX_OR_OWORD(oword, from, mask) \
+ do { \
+ (oword).u64[0] = (from).u64[0] | (mask).u64[0]; \
+ (oword).u64[1] = (from).u64[1] | (mask).u64[1]; \
+ } while (0)
-#define EFX_INSERT_FIELD32(...) \
- cpu_to_le32(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
+#define EFX_INSERT64(min, max, low, high, value) \
+ cpu_to_le64(EFX_INSERT_NATIVE(min, max, low, high, value))
-#define EFX_INPLACE_MASK64(min, max, field) \
- EFX_INSERT_FIELD64(min, max, field, EFX_MASK64(field))
+#define EFX_INSERT32(min, max, low, high, value) \
+ cpu_to_le32(EFX_INSERT_NATIVE(min, max, low, high, value))
-#define EFX_INPLACE_MASK32(min, max, field) \
- EFX_INSERT_FIELD32(min, max, field, EFX_MASK32(field))
+#define EFX_INPLACE_MASK64(min, max, low, high) \
+ EFX_INSERT64(min, max, low, high, EFX_MASK64(high + 1 - low))
-#define EFX_SET_OWORD_FIELD64(oword, field, value) do { \
+#define EFX_INPLACE_MASK32(min, max, low, high) \
+ EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low))
+
+#define EFX_SET_OWORD64(oword, low, high, value) do { \
(oword).u64[0] = (((oword).u64[0] \
- & ~EFX_INPLACE_MASK64(0, 63, field)) \
- | EFX_INSERT_FIELD64(0, 63, field, value)); \
+ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \
+ | EFX_INSERT64(0, 63, low, high, value)); \
(oword).u64[1] = (((oword).u64[1] \
- & ~EFX_INPLACE_MASK64(64, 127, field)) \
- | EFX_INSERT_FIELD64(64, 127, field, value)); \
+ & ~EFX_INPLACE_MASK64(64, 127, low, high)) \
+ | EFX_INSERT64(64, 127, low, high, value)); \
} while (0)
-#define EFX_SET_QWORD_FIELD64(qword, field, value) do { \
+#define EFX_SET_QWORD64(qword, low, high, value) do { \
(qword).u64[0] = (((qword).u64[0] \
- & ~EFX_INPLACE_MASK64(0, 63, field)) \
- | EFX_INSERT_FIELD64(0, 63, field, value)); \
+ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \
+ | EFX_INSERT64(0, 63, low, high, value)); \
} while (0)
-#define EFX_SET_OWORD_FIELD32(oword, field, value) do { \
+#define EFX_SET_OWORD32(oword, low, high, value) do { \
(oword).u32[0] = (((oword).u32[0] \
- & ~EFX_INPLACE_MASK32(0, 31, field)) \
- | EFX_INSERT_FIELD32(0, 31, field, value)); \
+ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \
+ | EFX_INSERT32(0, 31, low, high, value)); \
(oword).u32[1] = (((oword).u32[1] \
- & ~EFX_INPLACE_MASK32(32, 63, field)) \
- | EFX_INSERT_FIELD32(32, 63, field, value)); \
+ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \
+ | EFX_INSERT32(32, 63, low, high, value)); \
(oword).u32[2] = (((oword).u32[2] \
- & ~EFX_INPLACE_MASK32(64, 95, field)) \
- | EFX_INSERT_FIELD32(64, 95, field, value)); \
+ & ~EFX_INPLACE_MASK32(64, 95, low, high)) \
+ | EFX_INSERT32(64, 95, low, high, value)); \
(oword).u32[3] = (((oword).u32[3] \
- & ~EFX_INPLACE_MASK32(96, 127, field)) \
- | EFX_INSERT_FIELD32(96, 127, field, value)); \
+ & ~EFX_INPLACE_MASK32(96, 127, low, high)) \
+ | EFX_INSERT32(96, 127, low, high, value)); \
} while (0)
-#define EFX_SET_QWORD_FIELD32(qword, field, value) do { \
+#define EFX_SET_QWORD32(qword, low, high, value) do { \
(qword).u32[0] = (((qword).u32[0] \
- & ~EFX_INPLACE_MASK32(0, 31, field)) \
- | EFX_INSERT_FIELD32(0, 31, field, value)); \
+ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \
+ | EFX_INSERT32(0, 31, low, high, value)); \
(qword).u32[1] = (((qword).u32[1] \
- & ~EFX_INPLACE_MASK32(32, 63, field)) \
- | EFX_INSERT_FIELD32(32, 63, field, value)); \
+ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \
+ | EFX_INSERT32(32, 63, low, high, value)); \
} while (0)
-#define EFX_SET_DWORD_FIELD(dword, field, value) do { \
- (dword).u32[0] = (((dword).u32[0] \
- & ~EFX_INPLACE_MASK32(0, 31, field)) \
- | EFX_INSERT_FIELD32(0, 31, field, value)); \
+#define EFX_SET_DWORD32(dword, low, high, value) do { \
+ (dword).u32[0] = (((dword).u32[0] \
+ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \
+ | EFX_INSERT32(0, 31, low, high, value)); \
} while (0)
+#define EFX_SET_OWORD_FIELD64(oword, field, value) \
+ EFX_SET_OWORD64(oword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field), value)
+
+#define EFX_SET_QWORD_FIELD64(qword, field, value) \
+ EFX_SET_QWORD64(qword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field), value)
+
+#define EFX_SET_OWORD_FIELD32(oword, field, value) \
+ EFX_SET_OWORD32(oword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field), value)
+
+#define EFX_SET_QWORD_FIELD32(qword, field, value) \
+ EFX_SET_QWORD32(qword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field), value)
+
+#define EFX_SET_DWORD_FIELD(dword, field, value) \
+ EFX_SET_DWORD32(dword, EFX_LOW_BIT(field), \
+ EFX_HIGH_BIT(field), value)
+
+
+
#if BITS_PER_LONG == 64
#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD64
#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD64
@@ -502,4 +540,10 @@ typedef union efx_oword {
#define EFX_DMA_TYPE_WIDTH(width) \
(((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
+
+/* Static initialiser */
+#define EFX_OWORD32(a, b, c, d) \
+ { .u32 = { __constant_cpu_to_le32(a), __constant_cpu_to_le32(b), \
+ __constant_cpu_to_le32(c), __constant_cpu_to_le32(d) } }
+
#endif /* EFX_BITFIELD_H */
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c
index d3d3dd0a117..99e60237326 100644
--- a/drivers/net/sfc/boards.c
+++ b/drivers/net/sfc/boards.c
@@ -31,23 +31,23 @@ static void blink_led_timer(unsigned long context)
mod_timer(&bl->timer, jiffies + BLINK_INTERVAL);
}
-static void board_blink(struct efx_nic *efx, int blink)
+static void board_blink(struct efx_nic *efx, bool blink)
{
struct efx_blinker *blinker = &efx->board_info.blinker;
/* The rtnl mutex serialises all ethtool ioctls, so
* nothing special needs doing here. */
if (blink) {
- blinker->resubmit = 1;
- blinker->state = 0;
+ blinker->resubmit = true;
+ blinker->state = false;
setup_timer(&blinker->timer, blink_led_timer,
(unsigned long)efx);
mod_timer(&blinker->timer, jiffies + BLINK_INTERVAL);
} else {
- blinker->resubmit = 0;
+ blinker->resubmit = false;
if (blinker->timer.function)
del_timer_sync(&blinker->timer);
- efx->board_info.set_fault_led(efx, 0);
+ efx->board_info.set_fault_led(efx, false);
}
}
@@ -78,7 +78,7 @@ static int sfe4002_init_leds(struct efx_nic *efx)
return 0;
}
-static void sfe4002_fault_led(struct efx_nic *efx, int state)
+static void sfe4002_fault_led(struct efx_nic *efx, bool state)
{
xfp_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON :
QUAKE_LED_OFF);
diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h
index e5e844359ce..c6e01b64bfb 100644
--- a/drivers/net/sfc/boards.h
+++ b/drivers/net/sfc/boards.h
@@ -21,7 +21,5 @@ enum efx_board_type {
extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
extern int sfe4001_init(struct efx_nic *efx);
-/* Are we putting the PHY into flash config mode */
-extern unsigned int sfe4001_phy_flash_cfg;
#endif
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 45c72eebb3a..06ea71c7e34 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -28,7 +28,6 @@
#include "efx.h"
#include "mdio_10g.h"
#include "falcon.h"
-#include "workarounds.h"
#include "mac.h"
#define EFX_MAX_MTU (9 * 1024)
@@ -52,7 +51,7 @@ static struct workqueue_struct *refill_workqueue;
* This sets the default for new devices. It can be controlled later
* using ethtool.
*/
-static int lro = 1;
+static int lro = true;
module_param(lro, int, 0644);
MODULE_PARM_DESC(lro, "Large receive offload acceleration");
@@ -65,7 +64,7 @@ MODULE_PARM_DESC(lro, "Large receive offload acceleration");
* This is forced to 0 for MSI interrupt mode as the interrupt vector
* is not written
*/
-static unsigned int separate_tx_and_rx_channels = 1;
+static unsigned int separate_tx_and_rx_channels = true;
/* This is the weight assigned to each of the (per-channel) virtual
* NAPI devices.
@@ -81,7 +80,7 @@ unsigned int efx_monitor_interval = 1 * HZ;
/* This controls whether or not the hardware monitor will trigger a
* reset when it detects an error condition.
*/
-static unsigned int monitor_reset = 1;
+static unsigned int monitor_reset = true;
/* This controls whether or not the driver will initialise devices
* with invalid MAC addresses stored in the EEPROM or flash. If true,
@@ -141,8 +140,7 @@ static void efx_fini_channels(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
- if ((efx->state == STATE_RUNNING) || \
- (efx->state == STATE_RESETTING)) \
+ if (efx->state == STATE_RUNNING) \
ASSERT_RTNL(); \
} while (0)
@@ -159,16 +157,18 @@ static void efx_fini_channels(struct efx_nic *efx);
* never be concurrently called more than once on the same channel,
* though different channels may be being processed concurrently.
*/
-static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
+static int efx_process_channel(struct efx_channel *channel, int rx_quota)
{
- int rxdmaqs;
- struct efx_rx_queue *rx_queue;
+ struct efx_nic *efx = channel->efx;
+ int rx_packets;
- if (unlikely(channel->efx->reset_pending != RESET_TYPE_NONE ||
+ if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
!channel->enabled))
- return rx_quota;
+ return 0;
- rxdmaqs = falcon_process_eventq(channel, &rx_quota);
+ rx_packets = falcon_process_eventq(channel, rx_quota);
+ if (rx_packets == 0)
+ return 0;
/* Deliver last RX packet. */
if (channel->rx_pkt) {
@@ -180,16 +180,9 @@ static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
efx_flush_lro(channel);
efx_rx_strategy(channel);
- /* Refill descriptor rings as necessary */
- rx_queue = &channel->efx->rx_queue[0];
- while (rxdmaqs) {
- if (rxdmaqs & 0x01)
- efx_fast_push_rx_descriptors(rx_queue);
- rx_queue++;
- rxdmaqs >>= 1;
- }
+ efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
- return rx_quota;
+ return rx_packets;
}
/* Mark channel as finished processing
@@ -203,7 +196,7 @@ static inline void efx_channel_processed(struct efx_channel *channel)
/* The interrupt handler for this channel may set work_pending
* as soon as we acknowledge the events we've seen. Make sure
* it's cleared before then. */
- channel->work_pending = 0;
+ channel->work_pending = false;
smp_wmb();
falcon_eventq_read_ack(channel);
@@ -219,14 +212,12 @@ static int efx_poll(struct napi_struct *napi, int budget)
struct efx_channel *channel =
container_of(napi, struct efx_channel, napi_str);
struct net_device *napi_dev = channel->napi_dev;
- int unused;
int rx_packets;
EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
channel->channel, raw_smp_processor_id());
- unused = efx_process_channel(channel, budget);
- rx_packets = (budget - unused);
+ rx_packets = efx_process_channel(channel, budget);
if (rx_packets < budget) {
/* There is no race here; although napi_disable() will
@@ -260,7 +251,7 @@ void efx_process_channel_now(struct efx_channel *channel)
falcon_disable_interrupts(efx);
if (efx->legacy_irq)
synchronize_irq(efx->legacy_irq);
- if (channel->has_interrupt && channel->irq)
+ if (channel->irq)
synchronize_irq(channel->irq);
/* Wait for any NAPI processing to complete */
@@ -290,13 +281,13 @@ static int efx_probe_eventq(struct efx_channel *channel)
}
/* Prepare channel's event queue */
-static int efx_init_eventq(struct efx_channel *channel)
+static void efx_init_eventq(struct efx_channel *channel)
{
EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
channel->eventq_read_ptr = 0;
- return falcon_init_eventq(channel);
+ falcon_init_eventq(channel);
}
static void efx_fini_eventq(struct efx_channel *channel)
@@ -362,12 +353,11 @@ static int efx_probe_channel(struct efx_channel *channel)
* to propagate configuration changes (mtu, checksum offload), or
* to clear hardware error conditions
*/
-static int efx_init_channels(struct efx_nic *efx)
+static void efx_init_channels(struct efx_nic *efx)
{
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
struct efx_channel *channel;
- int rc = 0;
/* Calculate the rx buffer allocation parameters required to
* support the current MTU, including padding for header
@@ -382,36 +372,20 @@ static int efx_init_channels(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
- rc = efx_init_eventq(channel);
- if (rc)
- goto err;
+ efx_init_eventq(channel);
- efx_for_each_channel_tx_queue(tx_queue, channel) {
- rc = efx_init_tx_queue(tx_queue);
- if (rc)
- goto err;
- }
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ efx_init_tx_queue(tx_queue);
/* The rx buffer allocation strategy is MTU dependent */
efx_rx_strategy(channel);
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- rc = efx_init_rx_queue(rx_queue);
- if (rc)
- goto err;
- }
+ efx_for_each_channel_rx_queue(rx_queue, channel)
+ efx_init_rx_queue(rx_queue);
WARN_ON(channel->rx_pkt != NULL);
efx_rx_strategy(channel);
}
-
- return 0;
-
- err:
- EFX_ERR(efx, "failed to initialise channel %d\n",
- channel ? channel->channel : -1);
- efx_fini_channels(efx);
- return rc;
}
/* This enables event queue processing and packet transmission.
@@ -432,8 +406,8 @@ static void efx_start_channel(struct efx_channel *channel)
/* The interrupt handler for this channel may set work_pending
* as soon as we enable it. Make sure it's cleared before
* then. Similarly, make sure it sees the enabled flag set. */
- channel->work_pending = 0;
- channel->enabled = 1;
+ channel->work_pending = false;
+ channel->enabled = true;
smp_wmb();
napi_enable(&channel->napi_str);
@@ -456,7 +430,7 @@ static void efx_stop_channel(struct efx_channel *channel)
EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);
- channel->enabled = 0;
+ channel->enabled = false;
napi_disable(&channel->napi_str);
/* Ensure that any worker threads have exited or will be no-ops */
@@ -471,10 +445,17 @@ static void efx_fini_channels(struct efx_nic *efx)
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
+ int rc;
EFX_ASSERT_RESET_SERIALISED(efx);
BUG_ON(efx->port_enabled);
+ rc = falcon_flush_queues(efx);
+ if (rc)
+ EFX_ERR(efx, "failed to flush queues\n");
+ else
+ EFX_LOG(efx, "successfully flushed all queues\n");
+
efx_for_each_channel(channel, efx) {
EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
@@ -482,13 +463,6 @@ static void efx_fini_channels(struct efx_nic *efx)
efx_fini_rx_queue(rx_queue);
efx_for_each_channel_tx_queue(tx_queue, channel)
efx_fini_tx_queue(tx_queue);
- }
-
- /* Do the event queues last so that we can handle flush events
- * for all DMA queues. */
- efx_for_each_channel(channel, efx) {
- EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel);
-
efx_fini_eventq(channel);
}
}
@@ -526,8 +500,6 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
*/
static void efx_link_status_changed(struct efx_nic *efx)
{
- int carrier_ok;
-
/* SFC Bug 5356: A net_dev notifier is registered, so we must ensure
* that no events are triggered between unregister_netdev() and the
* driver unloading. A more general condition is that NETDEV_CHANGE
@@ -535,8 +507,12 @@ static void efx_link_status_changed(struct efx_nic *efx)
if (!netif_running(efx->net_dev))
return;
- carrier_ok = netif_carrier_ok(efx->net_dev) ? 1 : 0;
- if (efx->link_up != carrier_ok) {
+ if (efx->port_inhibited) {
+ netif_carrier_off(efx->net_dev);
+ return;
+ }
+
+ if (efx->link_up != netif_carrier_ok(efx->net_dev)) {
efx->n_link_state_changes++;
if (efx->link_up)
@@ -577,13 +553,19 @@ static void efx_link_status_changed(struct efx_nic *efx)
/* This call reinitialises the MAC to pick up new PHY settings. The
* caller must hold the mac_lock */
-static void __efx_reconfigure_port(struct efx_nic *efx)
+void __efx_reconfigure_port(struct efx_nic *efx)
{
WARN_ON(!mutex_is_locked(&efx->mac_lock));
EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n",
raw_smp_processor_id());
+ /* Serialise the promiscuous flag with efx_set_multicast_list. */
+ if (efx_dev_registered(efx)) {
+ netif_addr_lock_bh(efx->net_dev);
+ netif_addr_unlock_bh(efx->net_dev);
+ }
+
falcon_reconfigure_xmac(efx);
/* Inform kernel of loss/gain of carrier */
@@ -661,7 +643,8 @@ static int efx_init_port(struct efx_nic *efx)
if (rc)
return rc;
- efx->port_initialized = 1;
+ efx->port_initialized = true;
+ efx->stats_enabled = true;
/* Reconfigure port to program MAC registers */
falcon_reconfigure_xmac(efx);
@@ -678,7 +661,7 @@ static void efx_start_port(struct efx_nic *efx)
BUG_ON(efx->port_enabled);
mutex_lock(&efx->mac_lock);
- efx->port_enabled = 1;
+ efx->port_enabled = true;
__efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);
}
@@ -692,7 +675,7 @@ static void efx_stop_port(struct efx_nic *efx)
EFX_LOG(efx, "stop port\n");
mutex_lock(&efx->mac_lock);
- efx->port_enabled = 0;
+ efx->port_enabled = false;
mutex_unlock(&efx->mac_lock);
/* Serialise against efx_set_multicast_list() */
@@ -710,9 +693,9 @@ static void efx_fini_port(struct efx_nic *efx)
return;
falcon_fini_xmac(efx);
- efx->port_initialized = 0;
+ efx->port_initialized = false;
- efx->link_up = 0;
+ efx->link_up = false;
efx_link_status_changed(efx);
}
@@ -797,7 +780,7 @@ static int efx_init_io(struct efx_nic *efx)
return 0;
fail4:
- release_mem_region(efx->membase_phys, efx->type->mem_map_size);
+ pci_release_region(efx->pci_dev, efx->type->mem_bar);
fail3:
efx->membase_phys = 0;
fail2:
@@ -823,53 +806,61 @@ static void efx_fini_io(struct efx_nic *efx)
pci_disable_device(efx->pci_dev);
}
-/* Probe the number and type of interrupts we are able to obtain. */
+/* Get number of RX queues wanted. Return number of online CPU
+ * packages in the expectation that an IRQ balancer will spread
+ * interrupts across them. */
+static int efx_wanted_rx_queues(void)
+{
+ cpumask_t core_mask;
+ int count;
+ int cpu;
+
+ cpus_clear(core_mask);
+ count = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpu_isset(cpu, core_mask)) {
+ ++count;
+ cpus_or(core_mask, core_mask,
+ topology_core_siblings(cpu));
+ }
+ }
+
+ return count;
+}
+
+/* Probe the number and type of interrupts we are able to obtain, and
+ * the resulting numbers of channels and RX queues.
+ */
static void efx_probe_interrupts(struct efx_nic *efx)
{
- int max_channel = efx->type->phys_addr_channels - 1;
- struct msix_entry xentries[EFX_MAX_CHANNELS];
+ int max_channels =
+ min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
int rc, i;
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
- BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
-
- if (rss_cpus == 0) {
- cpumask_t core_mask;
- int cpu;
-
- cpus_clear(core_mask);
- efx->rss_queues = 0;
- for_each_online_cpu(cpu) {
- if (!cpu_isset(cpu, core_mask)) {
- ++efx->rss_queues;
- cpus_or(core_mask, core_mask,
- topology_core_siblings(cpu));
- }
- }
- } else {
- efx->rss_queues = rss_cpus;
- }
+ struct msix_entry xentries[EFX_MAX_CHANNELS];
+ int wanted_ints;
- efx->rss_queues = min(efx->rss_queues, max_channel + 1);
- efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
+ /* We want one RX queue and interrupt per CPU package
+ * (or as specified by the rss_cpus module parameter).
+ * We will need one channel per interrupt.
+ */
+ wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
+ efx->n_rx_queues = min(wanted_ints, max_channels);
- /* Request maximum number of MSI interrupts, and fill out
- * the channel interrupt information the allowed allocation */
- for (i = 0; i < efx->rss_queues; i++)
+ for (i = 0; i < efx->n_rx_queues; i++)
xentries[i].entry = i;
- rc = pci_enable_msix(efx->pci_dev, xentries, efx->rss_queues);
+ rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues);
if (rc > 0) {
- EFX_BUG_ON_PARANOID(rc >= efx->rss_queues);
- efx->rss_queues = rc;
+ EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues);
+ efx->n_rx_queues = rc;
rc = pci_enable_msix(efx->pci_dev, xentries,
- efx->rss_queues);
+ efx->n_rx_queues);
}
if (rc == 0) {
- for (i = 0; i < efx->rss_queues; i++) {
- efx->channel[i].has_interrupt = 1;
+ for (i = 0; i < efx->n_rx_queues; i++)
efx->channel[i].irq = xentries[i].vector;
- }
} else {
/* Fall back to single channel MSI */
efx->interrupt_mode = EFX_INT_MODE_MSI;
@@ -879,11 +870,10 @@ static void efx_probe_interrupts(struct efx_nic *efx)
/* Try single interrupt MSI */
if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
- efx->rss_queues = 1;
+ efx->n_rx_queues = 1;
rc = pci_enable_msi(efx->pci_dev);
if (rc == 0) {
efx->channel[0].irq = efx->pci_dev->irq;
- efx->channel[0].has_interrupt = 1;
} else {
EFX_ERR(efx, "could not enable MSI\n");
efx->interrupt_mode = EFX_INT_MODE_LEGACY;
@@ -892,10 +882,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
/* Assume legacy interrupts */
if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
- efx->rss_queues = 1;
- /* Every channel is interruptible */
- for (i = 0; i < EFX_MAX_CHANNELS; i++)
- efx->channel[i].has_interrupt = 1;
+ efx->n_rx_queues = 1;
efx->legacy_irq = efx->pci_dev->irq;
}
}
@@ -905,7 +892,7 @@ static void efx_remove_interrupts(struct efx_nic *efx)
struct efx_channel *channel;
/* Remove MSI/MSI-X interrupts */
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel(channel, efx)
channel->irq = 0;
pci_disable_msi(efx->pci_dev);
pci_disable_msix(efx->pci_dev);
@@ -914,45 +901,22 @@ static void efx_remove_interrupts(struct efx_nic *efx)
efx->legacy_irq = 0;
}
-/* Select number of used resources
- * Should be called after probe_interrupts()
- */
-static void efx_select_used(struct efx_nic *efx)
+static void efx_set_channels(struct efx_nic *efx)
{
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
- int i;
- /* TX queues. One per port per channel with TX capability
- * (more than one per port won't work on Linux, due to out
- * of order issues... but will be fine on Solaris)
- */
- tx_queue = &efx->tx_queue[0];
-
- /* Perform this for each channel with TX capabilities.
- * At the moment, we only support a single TX queue
- */
- tx_queue->used = 1;
- if ((!EFX_INT_MODE_USE_MSI(efx)) && separate_tx_and_rx_channels)
- tx_queue->channel = &efx->channel[1];
- else
- tx_queue->channel = &efx->channel[0];
- tx_queue->channel->used_flags |= EFX_USED_BY_TX;
- tx_queue++;
-
- /* RX queues. Each has a dedicated channel. */
- for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
- rx_queue = &efx->rx_queue[i];
+ efx_for_each_tx_queue(tx_queue, efx) {
+ if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels)
+ tx_queue->channel = &efx->channel[1];
+ else
+ tx_queue->channel = &efx->channel[0];
+ tx_queue->channel->used_flags |= EFX_USED_BY_TX;
+ }
- if (i < efx->rss_queues) {
- rx_queue->used = 1;
- /* If we allow multiple RX queues per channel
- * we need to decide that here
- */
- rx_queue->channel = &efx->channel[rx_queue->queue];
- rx_queue->channel->used_flags |= EFX_USED_BY_RX;
- rx_queue++;
- }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ rx_queue->channel = &efx->channel[rx_queue->queue];
+ rx_queue->channel->used_flags |= EFX_USED_BY_RX;
}
}
@@ -971,8 +935,7 @@ static int efx_probe_nic(struct efx_nic *efx)
* in MSI-X interrupts. */
efx_probe_interrupts(efx);
- /* Determine number of RX queues and TX queues */
- efx_select_used(efx);
+ efx_set_channels(efx);
/* Initialise the interrupt moderation settings */
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
@@ -1058,7 +1021,8 @@ static void efx_start_all(struct efx_nic *efx)
/* Mark the port as enabled so port reconfigurations can start, then
* restart the transmit interface early so the watchdog timer stops */
efx_start_port(efx);
- efx_wake_queue(efx);
+ if (efx_dev_registered(efx))
+ efx_wake_queue(efx);
efx_for_each_channel(channel, efx)
efx_start_channel(channel);
@@ -1109,7 +1073,7 @@ static void efx_stop_all(struct efx_nic *efx)
falcon_disable_interrupts(efx);
if (efx->legacy_irq)
synchronize_irq(efx->legacy_irq);
- efx_for_each_channel_with_interrupt(channel, efx) {
+ efx_for_each_channel(channel, efx) {
if (channel->irq)
synchronize_irq(channel->irq);
}
@@ -1128,13 +1092,12 @@ static void efx_stop_all(struct efx_nic *efx)
/* Isolate the MAC from the TX and RX engines, so that queue
* flushes will complete in a timely fashion. */
- falcon_deconfigure_mac_wrapper(efx);
falcon_drain_tx_fifo(efx);
/* Stop the kernel transmit interface late, so the watchdog
* timer isn't ticking over the flush */
- efx_stop_queue(efx);
if (efx_dev_registered(efx)) {
+ efx_stop_queue(efx);
netif_tx_lock_bh(efx->net_dev);
netif_tx_unlock_bh(efx->net_dev);
}
@@ -1151,24 +1114,16 @@ static void efx_remove_all(struct efx_nic *efx)
}
/* A convinience function to safely flush all the queues */
-int efx_flush_queues(struct efx_nic *efx)
+void efx_flush_queues(struct efx_nic *efx)
{
- int rc;
-
EFX_ASSERT_RESET_SERIALISED(efx);
efx_stop_all(efx);
efx_fini_channels(efx);
- rc = efx_init_channels(efx);
- if (rc) {
- efx_schedule_reset(efx, RESET_TYPE_DISABLE);
- return rc;
- }
+ efx_init_channels(efx);
efx_start_all(efx);
-
- return 0;
}
/**************************************************************************
@@ -1249,7 +1204,7 @@ static void efx_monitor(struct work_struct *data)
*/
static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
EFX_ASSERT_RESET_SERIALISED(efx);
@@ -1303,10 +1258,10 @@ static void efx_fini_napi(struct efx_nic *efx)
*/
static void efx_netpoll(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel(channel, efx)
efx_schedule_channel(channel);
}
@@ -1321,12 +1276,15 @@ static void efx_netpoll(struct net_device *net_dev)
/* Context: process, rtnl_lock() held. */
static int efx_net_open(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
EFX_ASSERT_RESET_SERIALISED(efx);
EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
raw_smp_processor_id());
+ if (efx->phy_mode & PHY_MODE_SPECIAL)
+ return -EBUSY;
+
efx_start_all(efx);
return 0;
}
@@ -1337,8 +1295,7 @@ static int efx_net_open(struct net_device *net_dev)
*/
static int efx_net_stop(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
- int rc;
+ struct efx_nic *efx = netdev_priv(net_dev);
EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
raw_smp_processor_id());
@@ -1346,9 +1303,7 @@ static int efx_net_stop(struct net_device *net_dev)
/* Stop the device and flush all the channels */
efx_stop_all(efx);
efx_fini_channels(efx);
- rc = efx_init_channels(efx);
- if (rc)
- efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+ efx_init_channels(efx);
return 0;
}
@@ -1356,7 +1311,7 @@ static int efx_net_stop(struct net_device *net_dev)
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct net_device_stats *stats = &net_dev->stats;
@@ -1366,7 +1321,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
*/
if (!spin_trylock(&efx->stats_lock))
return stats;
- if (efx->state == STATE_RUNNING) {
+ if (efx->stats_enabled) {
falcon_update_stats_xmac(efx);
falcon_update_nic_stats(efx);
}
@@ -1403,7 +1358,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
/* Context: netif_tx_lock held, BHs disabled. */
static void efx_watchdog(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
atomic_read(&efx->netif_stop_count), efx->port_enabled,
@@ -1417,7 +1372,7 @@ static void efx_watchdog(struct net_device *net_dev)
/* Context: process, rtnl_lock() held. */
static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
int rc = 0;
EFX_ASSERT_RESET_SERIALISED(efx);
@@ -1431,21 +1386,15 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
efx_fini_channels(efx);
net_dev->mtu = new_mtu;
- rc = efx_init_channels(efx);
- if (rc)
- goto fail;
+ efx_init_channels(efx);
efx_start_all(efx);
return rc;
-
- fail:
- efx_schedule_reset(efx, RESET_TYPE_DISABLE);
- return rc;
}
static int efx_set_mac_address(struct net_device *net_dev, void *data)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct sockaddr *addr = data;
char *new_addr = addr->sa_data;
@@ -1466,26 +1415,19 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
return 0;
}
-/* Context: netif_tx_lock held, BHs disabled. */
+/* Context: netif_addr_lock held, BHs disabled. */
static void efx_set_multicast_list(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct dev_mc_list *mc_list = net_dev->mc_list;
union efx_multicast_hash *mc_hash = &efx->multicast_hash;
- int promiscuous;
+ bool promiscuous = !!(net_dev->flags & IFF_PROMISC);
+ bool changed = (efx->promiscuous != promiscuous);
u32 crc;
int bit;
int i;
- /* Set per-MAC promiscuity flag and reconfigure MAC if necessary */
- promiscuous = (net_dev->flags & IFF_PROMISC) ? 1 : 0;
- if (efx->promiscuous != promiscuous) {
- efx->promiscuous = promiscuous;
- /* Close the window between efx_stop_port() and efx_flush_all()
- * by only queuing work when the port is enabled. */
- if (efx->port_enabled)
- queue_work(efx->workqueue, &efx->reconfigure_work);
- }
+ efx->promiscuous = promiscuous;
/* Build multicast hash table */
if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
@@ -1500,6 +1442,13 @@ static void efx_set_multicast_list(struct net_device *net_dev)
}
}
+ if (!efx->port_enabled)
+ /* Delay pushing settings until efx_start_port() */
+ return;
+
+ if (changed)
+ queue_work(efx->workqueue, &efx->reconfigure_work);
+
/* Create and activate new global multicast hash table */
falcon_set_multicast_hash(efx);
}
@@ -1510,7 +1459,7 @@ static int efx_netdev_event(struct notifier_block *this,
struct net_device *net_dev = ptr;
if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
strcpy(efx->name, net_dev->name);
}
@@ -1568,7 +1517,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
if (!efx->net_dev)
return;
- BUG_ON(efx->net_dev->priv != efx);
+ BUG_ON(netdev_priv(efx->net_dev) != efx);
/* Free up any skbs still remaining. This has to happen before
* we try to unregister the netdev as running their destructors
@@ -1588,49 +1537,60 @@ static void efx_unregister_netdev(struct efx_nic *efx)
*
**************************************************************************/
-/* The final hardware and software finalisation before reset. */
-static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* Tears down the entire software state and most of the hardware state
+ * before reset. */
+void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
int rc;
EFX_ASSERT_RESET_SERIALISED(efx);
+ /* The net_dev->get_stats handler is quite slow, and will fail
+ * if a fetch is pending over reset. Serialise against it. */
+ spin_lock(&efx->stats_lock);
+ efx->stats_enabled = false;
+ spin_unlock(&efx->stats_lock);
+
+ efx_stop_all(efx);
+ mutex_lock(&efx->mac_lock);
+
rc = falcon_xmac_get_settings(efx, ecmd);
- if (rc) {
+ if (rc)
EFX_ERR(efx, "could not back up PHY settings\n");
- goto fail;
- }
efx_fini_channels(efx);
- return 0;
-
- fail:
- return rc;
}
-/* The first part of software initialisation after a hardware reset
- * This function does not handle serialisation with the kernel, it
- * assumes the caller has done this */
-static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* This function will always ensure that the locks acquired in
+ * efx_reset_down() are released. A failure return code indicates
+ * that we were unable to reinitialise the hardware, and the
+ * driver should be disabled. If ok is false, then the rx and tx
+ * engines are not restarted, pending a RESET_DISABLE. */
+int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
{
int rc;
- rc = efx_init_channels(efx);
- if (rc)
- goto fail1;
+ EFX_ASSERT_RESET_SERIALISED(efx);
- /* Restore MAC and PHY settings. */
- rc = falcon_xmac_set_settings(efx, ecmd);
+ rc = falcon_init_nic(efx);
if (rc) {
- EFX_ERR(efx, "could not restore PHY settings\n");
- goto fail2;
+ EFX_ERR(efx, "failed to initialise NIC\n");
+ ok = false;
}
- return 0;
+ if (ok) {
+ efx_init_channels(efx);
- fail2:
- efx_fini_channels(efx);
- fail1:
+ if (falcon_xmac_set_settings(efx, ecmd))
+ EFX_ERR(efx, "could not restore PHY settings\n");
+ }
+
+ mutex_unlock(&efx->mac_lock);
+
+ if (ok) {
+ efx_start_all(efx);
+ efx->stats_enabled = true;
+ }
return rc;
}
@@ -1659,25 +1619,14 @@ static int efx_reset(struct efx_nic *efx)
goto unlock_rtnl;
}
- efx->state = STATE_RESETTING;
EFX_INFO(efx, "resetting (%d)\n", method);
- /* The net_dev->get_stats handler is quite slow, and will fail
- * if a fetch is pending over reset. Serialise against it. */
- spin_lock(&efx->stats_lock);
- spin_unlock(&efx->stats_lock);
-
- efx_stop_all(efx);
- mutex_lock(&efx->mac_lock);
-
- rc = efx_reset_down(efx, &ecmd);
- if (rc)
- goto fail1;
+ efx_reset_down(efx, &ecmd);
rc = falcon_reset_hw(efx, method);
if (rc) {
EFX_ERR(efx, "failed to reset hardware\n");
- goto fail2;
+ goto fail;
}
/* Allow resets to be rescheduled. */
@@ -1689,46 +1638,27 @@ static int efx_reset(struct efx_nic *efx)
* can respond to requests. */
pci_set_master(efx->pci_dev);
- /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
- * case so the driver can talk to external SRAM */
- rc = falcon_init_nic(efx);
- if (rc) {
- EFX_ERR(efx, "failed to initialise NIC\n");
- goto fail3;
- }
-
/* Leave device stopped if necessary */
if (method == RESET_TYPE_DISABLE) {
- /* Reinitialise the device anyway so the driver unload sequence
- * can talk to the external SRAM */
- falcon_init_nic(efx);
rc = -EIO;
- goto fail4;
+ goto fail;
}
- rc = efx_reset_up(efx, &ecmd);
+ rc = efx_reset_up(efx, &ecmd, true);
if (rc)
- goto fail5;
+ goto disable;
- mutex_unlock(&efx->mac_lock);
EFX_LOG(efx, "reset complete\n");
-
- efx->state = STATE_RUNNING;
- efx_start_all(efx);
-
unlock_rtnl:
rtnl_unlock();
return 0;
- fail5:
- fail4:
- fail3:
- fail2:
- fail1:
+ fail:
+ efx_reset_up(efx, &ecmd, false);
+ disable:
EFX_ERR(efx, "has been disabled\n");
efx->state = STATE_DISABLED;
- mutex_unlock(&efx->mac_lock);
rtnl_unlock();
efx_unregister_netdev(efx);
efx_fini_port(efx);
@@ -1801,7 +1731,7 @@ static struct pci_device_id efx_pci_table[] __devinitdata = {
*
* Dummy PHY/MAC/Board operations
*
- * Can be used where the MAC does not implement this operation
+ * Can be used for some unimplemented operations
* Needed so all function pointers are valid and do not have to be tested
* before use
*
@@ -1811,7 +1741,7 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
return 0;
}
void efx_port_dummy_op_void(struct efx_nic *efx) {}
-void efx_port_dummy_op_blink(struct efx_nic *efx, int blink) {}
+void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
static struct efx_phy_operations efx_dummy_phy_operations = {
.init = efx_port_dummy_op_int,
@@ -1819,20 +1749,14 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
.check_hw = efx_port_dummy_op_int,
.fini = efx_port_dummy_op_void,
.clear_interrupt = efx_port_dummy_op_void,
- .reset_xaui = efx_port_dummy_op_void,
};
-/* Dummy board operations */
-static int efx_nic_dummy_op_int(struct efx_nic *nic)
-{
- return 0;
-}
-
static struct efx_board efx_dummy_board_info = {
- .init = efx_nic_dummy_op_int,
- .init_leds = efx_port_dummy_op_int,
- .set_fault_led = efx_port_dummy_op_blink,
- .fini = efx_port_dummy_op_void,
+ .init = efx_port_dummy_op_int,
+ .init_leds = efx_port_dummy_op_int,
+ .set_fault_led = efx_port_dummy_op_blink,
+ .blink = efx_port_dummy_op_blink,
+ .fini = efx_port_dummy_op_void,
};
/**************************************************************************
@@ -1865,7 +1789,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->board_info = efx_dummy_board_info;
efx->net_dev = net_dev;
- efx->rx_checksum_enabled = 1;
+ efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock);
mutex_init(&efx->mac_lock);
@@ -1878,10 +1802,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
channel = &efx->channel[i];
channel->efx = efx;
channel->channel = i;
- channel->evqnum = i;
- channel->work_pending = 0;
+ channel->work_pending = false;
}
- for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
+ for (i = 0; i < EFX_TX_QUEUE_COUNT; i++) {
tx_queue = &efx->tx_queue[i];
tx_queue->efx = efx;
tx_queue->queue = i;
@@ -2056,19 +1979,16 @@ static int efx_pci_probe_main(struct efx_nic *efx)
goto fail5;
}
- rc = efx_init_channels(efx);
- if (rc)
- goto fail6;
+ efx_init_channels(efx);
rc = falcon_init_interrupt(efx);
if (rc)
- goto fail7;
+ goto fail6;
return 0;
- fail7:
- efx_fini_channels(efx);
fail6:
+ efx_fini_channels(efx);
efx_fini_port(efx);
fail5:
fail4:
@@ -2105,7 +2025,10 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
NETIF_F_HIGHDMA | NETIF_F_TSO);
if (lro)
net_dev->features |= NETIF_F_LRO;
- efx = net_dev->priv;
+ /* Mask for features that also apply to VLAN devices */
+ net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
+ NETIF_F_HIGHDMA | NETIF_F_TSO);
+ efx = netdev_priv(net_dev);
pci_set_drvdata(pci_dev, efx);
rc = efx_init_struct(efx, type, pci_dev, net_dev);
if (rc)
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 3b2f69f4a9a..d02937b70ee 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -28,15 +28,21 @@ extern void efx_wake_queue(struct efx_nic *efx);
/* RX */
extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
- unsigned int len, int checksummed, int discard);
+ unsigned int len, bool checksummed, bool discard);
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
/* Channels */
extern void efx_process_channel_now(struct efx_channel *channel);
-extern int efx_flush_queues(struct efx_nic *efx);
+extern void efx_flush_queues(struct efx_nic *efx);
/* Ports */
extern void efx_reconfigure_port(struct efx_nic *efx);
+extern void __efx_reconfigure_port(struct efx_nic *efx);
+
+/* Reset handling */
+extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd,
+ bool ok);
/* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
@@ -50,7 +56,7 @@ extern void efx_hex_dump(const u8 *, unsigned int, const char *);
/* Dummy PHY ops for PHY drivers */
extern int efx_port_dummy_op_int(struct efx_nic *efx);
extern void efx_port_dummy_op_void(struct efx_nic *efx);
-extern void efx_port_dummy_op_blink(struct efx_nic *efx, int blink);
+extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink);
extern unsigned int efx_monitor_interval;
@@ -59,7 +65,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
{
EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n",
channel->channel, raw_smp_processor_id());
- channel->work_pending = 1;
+ channel->work_pending = true;
netif_rx_schedule(channel->napi_dev, &channel->napi_str);
}
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index c53290d08e2..cec15dbb88e 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -52,12 +52,11 @@ extern const char *efx_loopback_mode_names[];
#define LOOPBACK_MASK(_efx) \
(1 << (_efx)->loopback_mode)
-#define LOOPBACK_INTERNAL(_efx) \
- ((LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)) ? 1 : 0)
+#define LOOPBACK_INTERNAL(_efx) \
+ (!!(LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)))
-#define LOOPBACK_OUT_OF(_from, _to, _mask) \
- (((LOOPBACK_MASK(_from) & (_mask)) && \
- ((LOOPBACK_MASK(_to) & (_mask)) == 0)) ? 1 : 0)
+#define LOOPBACK_OUT_OF(_from, _to, _mask) \
+ ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask)))
/*****************************************************************************/
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index e2c75d10161..fa98af58223 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -17,6 +17,7 @@
#include "ethtool.h"
#include "falcon.h"
#include "gmii.h"
+#include "spi.h"
#include "mac.h"
const char *efx_loopback_mode_names[] = {
@@ -32,8 +33,6 @@ const char *efx_loopback_mode_names[] = {
[LOOPBACK_NETWORK] = "NETWORK",
};
-static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable);
-
struct ethtool_string {
char name[ETH_GSTRING_LEN];
};
@@ -173,6 +172,11 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
/* Number of ethtool statistics */
#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
+/* EEPROM range with gPXE configuration */
+#define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
+#define EFX_ETHTOOL_EEPROM_MIN 0x100U
+#define EFX_ETHTOOL_EEPROM_MAX 0x400U
+
/**************************************************************************
*
* Ethtool operations
@@ -183,7 +187,7 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
/* Identify device by flashing LEDs */
static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
efx->board_info.blink(efx, 1);
schedule_timeout_interruptible(seconds * HZ);
@@ -195,7 +199,7 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
int efx_ethtool_get_settings(struct net_device *net_dev,
struct ethtool_cmd *ecmd)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
int rc;
mutex_lock(&efx->mac_lock);
@@ -209,7 +213,7 @@ int efx_ethtool_get_settings(struct net_device *net_dev,
int efx_ethtool_set_settings(struct net_device *net_dev,
struct ethtool_cmd *ecmd)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
int rc;
mutex_lock(&efx->mac_lock);
@@ -224,7 +228,7 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
struct ethtool_drvinfo *info)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
@@ -329,7 +333,10 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
unsigned int n = 0;
enum efx_loopback_mode mode;
- /* Interrupt */
+ efx_fill_test(n++, strings, data, &tests->mii,
+ "core", 0, "mii", NULL);
+ efx_fill_test(n++, strings, data, &tests->nvram,
+ "core", 0, "nvram", NULL);
efx_fill_test(n++, strings, data, &tests->interrupt,
"core", 0, "interrupt", NULL);
@@ -349,16 +356,17 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
"eventq.poll", NULL);
}
- /* PHY presence */
- efx_fill_test(n++, strings, data, &tests->phy_ok,
- EFX_PORT_NAME, "phy_ok", NULL);
+ efx_fill_test(n++, strings, data, &tests->registers,
+ "core", 0, "registers", NULL);
+ efx_fill_test(n++, strings, data, &tests->phy,
+ EFX_PORT_NAME, "phy", NULL);
/* Loopback tests */
efx_fill_test(n++, strings, data, &tests->loopback_speed,
EFX_PORT_NAME, "loopback.speed", NULL);
efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
EFX_PORT_NAME, "loopback.full_duplex", NULL);
- for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
+ for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
if (!(efx->loopback_modes & (1 << mode)))
continue;
n = efx_fill_loopback_test(efx,
@@ -369,22 +377,24 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
return n;
}
-static int efx_ethtool_get_stats_count(struct net_device *net_dev)
+static int efx_ethtool_get_sset_count(struct net_device *net_dev,
+ int string_set)
{
- return EFX_ETHTOOL_NUM_STATS;
-}
-
-static int efx_ethtool_self_test_count(struct net_device *net_dev)
-{
- struct efx_nic *efx = net_dev->priv;
-
- return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
+ switch (string_set) {
+ case ETH_SS_STATS:
+ return EFX_ETHTOOL_NUM_STATS;
+ case ETH_SS_TEST:
+ return efx_ethtool_fill_self_tests(netdev_priv(net_dev),
+ NULL, NULL, NULL);
+ default:
+ return -EINVAL;
+ }
}
static void efx_ethtool_get_strings(struct net_device *net_dev,
u32 string_set, u8 *strings)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct ethtool_string *ethtool_strings =
(struct ethtool_string *)strings;
int i;
@@ -410,7 +420,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
struct ethtool_stats *stats,
u64 *data)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct efx_ethtool_stat *stat;
struct efx_channel *channel;
@@ -442,60 +452,21 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
}
}
-static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
-{
- int rc;
-
- /* Our TSO requires TX checksumming, so force TX checksumming
- * on when TSO is enabled.
- */
- if (enable) {
- rc = efx_ethtool_set_tx_csum(net_dev, 1);
- if (rc)
- return rc;
- }
-
- return ethtool_op_set_tso(net_dev, enable);
-}
-
-static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
-{
- struct efx_nic *efx = net_dev->priv;
- int rc;
-
- rc = ethtool_op_set_tx_csum(net_dev, enable);
- if (rc)
- return rc;
-
- efx_flush_queues(efx);
-
- /* Our TSO requires TX checksumming, so disable TSO when
- * checksumming is disabled
- */
- if (!enable) {
- rc = efx_ethtool_set_tso(net_dev, 0);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
/* No way to stop the hardware doing the checks; we just
* ignore the result.
*/
- efx->rx_checksum_enabled = (enable ? 1 : 0);
+ efx->rx_checksum_enabled = !!enable;
return 0;
}
static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
return efx->rx_checksum_enabled;
}
@@ -503,7 +474,7 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
static void efx_ethtool_self_test(struct net_device *net_dev,
struct ethtool_test *test, u64 *data)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_self_tests efx_tests;
int offline, already_up;
int rc;
@@ -533,15 +504,9 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
goto out;
/* Perform offline tests only if online tests passed */
- if (offline) {
- /* Stop the kernel from sending packets during the test. */
- efx_stop_queue(efx);
- rc = efx_flush_queues(efx);
- if (!rc)
- rc = efx_offline_test(efx, &efx_tests,
- efx->loopback_modes);
- efx_wake_queue(efx);
- }
+ if (offline)
+ rc = efx_offline_test(efx, &efx_tests,
+ efx->loopback_modes);
out:
if (!already_up)
@@ -561,22 +526,65 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
/* Restart autonegotiation */
static int efx_ethtool_nway_reset(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
return mii_nway_restart(&efx->mii);
}
static u32 efx_ethtool_get_link(struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
return efx->link_up;
}
+static int efx_ethtool_get_eeprom_len(struct net_device *net_dev)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_spi_device *spi = efx->spi_eeprom;
+
+ if (!spi)
+ return 0;
+ return min(spi->size, EFX_ETHTOOL_EEPROM_MAX) -
+ min(spi->size, EFX_ETHTOOL_EEPROM_MIN);
+}
+
+static int efx_ethtool_get_eeprom(struct net_device *net_dev,
+ struct ethtool_eeprom *eeprom, u8 *buf)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_spi_device *spi = efx->spi_eeprom;
+ size_t len;
+ int rc;
+
+ rc = falcon_spi_read(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+ eeprom->len, &len, buf);
+ eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
+ eeprom->len = len;
+ return rc;
+}
+
+static int efx_ethtool_set_eeprom(struct net_device *net_dev,
+ struct ethtool_eeprom *eeprom, u8 *buf)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_spi_device *spi = efx->spi_eeprom;
+ size_t len;
+ int rc;
+
+ if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
+ return -EINVAL;
+
+ rc = falcon_spi_write(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+ eeprom->len, &len, buf);
+ eeprom->len = len;
+ return rc;
+}
+
static int efx_ethtool_get_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
struct efx_channel *channel;
@@ -614,7 +622,7 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
static int efx_ethtool_set_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
unsigned tx_usecs, rx_usecs;
@@ -657,7 +665,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
enum efx_fc_type flow_control = efx->flow_control;
int rc;
@@ -680,11 +688,11 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
- pause->rx_pause = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
- pause->tx_pause = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
- pause->autoneg = (efx->flow_control & EFX_FC_AUTO) ? 1 : 0;
+ pause->rx_pause = !!(efx->flow_control & EFX_FC_RX);
+ pause->tx_pause = !!(efx->flow_control & EFX_FC_TX);
+ pause->autoneg = !!(efx->flow_control & EFX_FC_AUTO);
}
@@ -694,6 +702,9 @@ struct ethtool_ops efx_ethtool_ops = {
.get_drvinfo = efx_ethtool_get_drvinfo,
.nway_reset = efx_ethtool_nway_reset,
.get_link = efx_ethtool_get_link,
+ .get_eeprom_len = efx_ethtool_get_eeprom_len,
+ .get_eeprom = efx_ethtool_get_eeprom,
+ .set_eeprom = efx_ethtool_set_eeprom,
.get_coalesce = efx_ethtool_get_coalesce,
.set_coalesce = efx_ethtool_set_coalesce,
.get_pauseparam = efx_ethtool_get_pauseparam,
@@ -701,17 +712,16 @@ struct ethtool_ops efx_ethtool_ops = {
.get_rx_csum = efx_ethtool_get_rx_csum,
.set_rx_csum = efx_ethtool_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = efx_ethtool_set_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
- .set_tso = efx_ethtool_set_tso,
+ .set_tso = ethtool_op_set_tso,
.get_flags = ethtool_op_get_flags,
.set_flags = ethtool_op_set_flags,
- .self_test_count = efx_ethtool_self_test_count,
+ .get_sset_count = efx_ethtool_get_sset_count,
.self_test = efx_ethtool_self_test,
.get_strings = efx_ethtool_get_strings,
.phys_id = efx_ethtool_phys_id,
- .get_stats_count = efx_ethtool_get_stats_count,
.get_ethtool_stats = efx_ethtool_get_stats,
};
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 9138ee5b7b7..31ed1f49de0 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -108,10 +108,10 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
/* Max number of internal errors. After this resets will not be performed */
#define FALCON_MAX_INT_ERRORS 4
-/* Maximum period that we wait for flush events. If the flush event
- * doesn't arrive in this period of time then we check if the queue
- * was disabled anyway. */
-#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */
+/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
+ */
+#define FALCON_FLUSH_INTERVAL 10
+#define FALCON_FLUSH_POLL_COUNT 100
/**************************************************************************
*
@@ -242,7 +242,7 @@ static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
* falcon_alloc_special_buffer()) in Falcon's buffer table, allowing
* it to be used for event queues, descriptor rings etc.
*/
-static int
+static void
falcon_init_special_buffer(struct efx_nic *efx,
struct efx_special_buffer *buffer)
{
@@ -266,8 +266,6 @@ falcon_init_special_buffer(struct efx_nic *efx,
BUF_OWNER_ID_FBUF, 0);
falcon_write_sram(efx, &buf_desc, index);
}
-
- return 0;
}
/* Unmaps a buffer from Falcon and clears the buffer table entries */
@@ -449,16 +447,15 @@ int falcon_probe_tx(struct efx_tx_queue *tx_queue)
sizeof(efx_qword_t));
}
-int falcon_init_tx(struct efx_tx_queue *tx_queue)
+void falcon_init_tx(struct efx_tx_queue *tx_queue)
{
efx_oword_t tx_desc_ptr;
struct efx_nic *efx = tx_queue->efx;
- int rc;
+
+ tx_queue->flushed = false;
/* Pin TX descriptor ring */
- rc = falcon_init_special_buffer(efx, &tx_queue->txd);
- if (rc)
- return rc;
+ falcon_init_special_buffer(efx, &tx_queue->txd);
/* Push TX descriptor ring to card */
EFX_POPULATE_OWORD_10(tx_desc_ptr,
@@ -466,7 +463,7 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue)
TX_ISCSI_DDIG_EN, 0,
TX_ISCSI_HDIG_EN, 0,
TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
- TX_DESCQ_EVQ_ID, tx_queue->channel->evqnum,
+ TX_DESCQ_EVQ_ID, tx_queue->channel->channel,
TX_DESCQ_OWNER_ID, 0,
TX_DESCQ_LABEL, tx_queue->queue,
TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
@@ -474,9 +471,9 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue)
TX_NON_IP_DROP_DIS_B0, 1);
if (falcon_rev(efx) >= FALCON_REV_B0) {
- int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM);
- EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum);
- EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum);
+ int csum = tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM;
+ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, !csum);
+ EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, !csum);
}
falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
@@ -485,73 +482,28 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue)
if (falcon_rev(efx) < FALCON_REV_B0) {
efx_oword_t reg;
- BUG_ON(tx_queue->queue >= 128); /* HW limit */
+ /* Only 128 bits in this register */
+ BUILD_BUG_ON(EFX_TX_QUEUE_COUNT >= 128);
falcon_read(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
- if (efx->net_dev->features & NETIF_F_IP_CSUM)
+ if (tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM)
clear_bit_le(tx_queue->queue, (void *)&reg);
else
set_bit_le(tx_queue->queue, (void *)&reg);
falcon_write(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
}
-
- return 0;
}
-static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
+static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- struct efx_channel *channel = &efx->channel[0];
efx_oword_t tx_flush_descq;
- unsigned int read_ptr, i;
/* Post a flush command */
EFX_POPULATE_OWORD_2(tx_flush_descq,
TX_FLUSH_DESCQ_CMD, 1,
TX_FLUSH_DESCQ, tx_queue->queue);
falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
- msleep(FALCON_FLUSH_TIMEOUT);
-
- if (EFX_WORKAROUND_7803(efx))
- return 0;
-
- /* Look for a flush completed event */
- read_ptr = channel->eventq_read_ptr;
- for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
- efx_qword_t *event = falcon_event(channel, read_ptr);
- int ev_code, ev_sub_code, ev_queue;
- if (!falcon_event_present(event))
- break;
-
- ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
- ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
- ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID);
- if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) &&
- (ev_queue == tx_queue->queue)) {
- EFX_LOG(efx, "tx queue %d flush command succesful\n",
- tx_queue->queue);
- return 0;
- }
-
- read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
- }
-
- if (EFX_WORKAROUND_11557(efx)) {
- efx_oword_t reg;
- int enabled;
-
- falcon_read_table(efx, &reg, efx->type->txd_ptr_tbl_base,
- tx_queue->queue);
- enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN);
- if (!enabled) {
- EFX_LOG(efx, "tx queue %d disabled without a "
- "flush event seen\n", tx_queue->queue);
- return 0;
- }
- }
-
- EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue);
- return -ETIMEDOUT;
}
void falcon_fini_tx(struct efx_tx_queue *tx_queue)
@@ -559,9 +511,8 @@ void falcon_fini_tx(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t tx_desc_ptr;
- /* Stop the hardware using the queue */
- if (falcon_flush_tx_queue(tx_queue))
- EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue);
+ /* The queue should have been flushed */
+ WARN_ON(!tx_queue->flushed);
/* Remove TX descriptor ring from card */
EFX_ZERO_OWORD(tx_desc_ptr);
@@ -638,29 +589,28 @@ int falcon_probe_rx(struct efx_rx_queue *rx_queue)
sizeof(efx_qword_t));
}
-int falcon_init_rx(struct efx_rx_queue *rx_queue)
+void falcon_init_rx(struct efx_rx_queue *rx_queue)
{
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
- int rc;
- int is_b0 = falcon_rev(efx) >= FALCON_REV_B0;
- int iscsi_digest_en = is_b0;
+ bool is_b0 = falcon_rev(efx) >= FALCON_REV_B0;
+ bool iscsi_digest_en = is_b0;
EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
rx_queue->queue, rx_queue->rxd.index,
rx_queue->rxd.index + rx_queue->rxd.entries - 1);
+ rx_queue->flushed = false;
+
/* Pin RX descriptor ring */
- rc = falcon_init_special_buffer(efx, &rx_queue->rxd);
- if (rc)
- return rc;
+ falcon_init_special_buffer(efx, &rx_queue->rxd);
/* Push RX descriptor ring to card */
EFX_POPULATE_OWORD_10(rx_desc_ptr,
RX_ISCSI_DDIG_EN, iscsi_digest_en,
RX_ISCSI_HDIG_EN, iscsi_digest_en,
RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
- RX_DESCQ_EVQ_ID, rx_queue->channel->evqnum,
+ RX_DESCQ_EVQ_ID, rx_queue->channel->channel,
RX_DESCQ_OWNER_ID, 0,
RX_DESCQ_LABEL, rx_queue->queue,
RX_DESCQ_SIZE, FALCON_RXD_RING_ORDER,
@@ -670,14 +620,11 @@ int falcon_init_rx(struct efx_rx_queue *rx_queue)
RX_DESCQ_EN, 1);
falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
rx_queue->queue);
- return 0;
}
-static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
+static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- struct efx_channel *channel = &efx->channel[0];
- unsigned int read_ptr, i;
efx_oword_t rx_flush_descq;
/* Post a flush command */
@@ -685,75 +632,15 @@ static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
RX_FLUSH_DESCQ_CMD, 1,
RX_FLUSH_DESCQ, rx_queue->queue);
falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER);
- msleep(FALCON_FLUSH_TIMEOUT);
-
- if (EFX_WORKAROUND_7803(efx))
- return 0;
-
- /* Look for a flush completed event */
- read_ptr = channel->eventq_read_ptr;
- for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
- efx_qword_t *event = falcon_event(channel, read_ptr);
- int ev_code, ev_sub_code, ev_queue, ev_failed;
- if (!falcon_event_present(event))
- break;
-
- ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
- ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
- ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID);
- ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL);
-
- if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) &&
- (ev_queue == rx_queue->queue)) {
- if (ev_failed) {
- EFX_INFO(efx, "rx queue %d flush command "
- "failed\n", rx_queue->queue);
- return -EAGAIN;
- } else {
- EFX_LOG(efx, "rx queue %d flush command "
- "succesful\n", rx_queue->queue);
- return 0;
- }
- }
-
- read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
- }
-
- if (EFX_WORKAROUND_11557(efx)) {
- efx_oword_t reg;
- int enabled;
-
- falcon_read_table(efx, &reg, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
- enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN);
- if (!enabled) {
- EFX_LOG(efx, "rx queue %d disabled without a "
- "flush event seen\n", rx_queue->queue);
- return 0;
- }
- }
-
- EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue);
- return -ETIMEDOUT;
}
void falcon_fini_rx(struct efx_rx_queue *rx_queue)
{
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
- int i, rc;
- /* Try and flush the rx queue. This may need to be repeated */
- for (i = 0; i < 5; i++) {
- rc = falcon_flush_rx_queue(rx_queue);
- if (rc == -EAGAIN)
- continue;
- break;
- }
- if (rc) {
- EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue);
- efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
- }
+ /* The queue should already have been flushed */
+ WARN_ON(!rx_queue->flushed);
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
@@ -793,7 +680,7 @@ void falcon_eventq_read_ack(struct efx_channel *channel)
EFX_POPULATE_DWORD_1(reg, EVQ_RPTR_DWORD, channel->eventq_read_ptr);
falcon_writel_table(efx, &reg, efx->type->evq_rptr_tbl_base,
- channel->evqnum);
+ channel->channel);
}
/* Use HW to insert a SW defined event */
@@ -802,7 +689,7 @@ void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event)
efx_oword_t drv_ev_reg;
EFX_POPULATE_OWORD_2(drv_ev_reg,
- DRV_EV_QID, channel->evqnum,
+ DRV_EV_QID, channel->channel,
DRV_EV_DATA,
EFX_QWORD_FIELD64(*event, WHOLE_EVENT));
falcon_write(channel->efx, &drv_ev_reg, DRV_EV_REG_KER);
@@ -813,8 +700,8 @@ void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event)
* Falcon batches TX completion events; the message we receive is of
* the form "complete all TX events up to this index".
*/
-static inline void falcon_handle_tx_event(struct efx_channel *channel,
- efx_qword_t *event)
+static void falcon_handle_tx_event(struct efx_channel *channel,
+ efx_qword_t *event)
{
unsigned int tx_ev_desc_ptr;
unsigned int tx_ev_q_label;
@@ -847,39 +734,19 @@ static inline void falcon_handle_tx_event(struct efx_channel *channel,
}
}
-/* Check received packet's destination MAC address. */
-static int check_dest_mac(struct efx_rx_queue *rx_queue,
- const efx_qword_t *event)
-{
- struct efx_rx_buffer *rx_buf;
- struct efx_nic *efx = rx_queue->efx;
- int rx_ev_desc_ptr;
- struct ethhdr *eh;
-
- if (efx->promiscuous)
- return 1;
-
- rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
- rx_buf = efx_rx_buffer(rx_queue, rx_ev_desc_ptr);
- eh = (struct ethhdr *)rx_buf->data;
- if (memcmp(eh->h_dest, efx->net_dev->dev_addr, ETH_ALEN))
- return 0;
- return 1;
-}
-
/* Detect errors included in the rx_evt_pkt_ok bit. */
static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
const efx_qword_t *event,
- unsigned *rx_ev_pkt_ok,
- int *discard, int byte_count)
+ bool *rx_ev_pkt_ok,
+ bool *discard)
{
struct efx_nic *efx = rx_queue->efx;
- unsigned rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
- unsigned rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
- unsigned rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
- unsigned rx_ev_pkt_type, rx_ev_other_err, rx_ev_pause_frm;
- unsigned rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
- int snap, non_ip;
+ bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
+ bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
+ bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
+ bool rx_ev_other_err, rx_ev_pause_frm;
+ bool rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
+ unsigned rx_ev_pkt_type;
rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
@@ -903,41 +770,6 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
- snap = (rx_ev_pkt_type == RX_EV_PKT_TYPE_LLC_DECODE) ||
- (rx_ev_pkt_type == RX_EV_PKT_TYPE_VLAN_LLC_DECODE);
- non_ip = (rx_ev_hdr_type == RX_EV_HDR_TYPE_NON_IP_DECODE);
-
- /* SFC bug 5475/8970: The Falcon XMAC incorrectly calculates the
- * length field of an LLC frame, which sets TOBE_DISC. We could set
- * PASS_LEN_ERR, but we want the MAC to filter out short frames (to
- * protect the RX block).
- *
- * bug5475 - LLC/SNAP: Falcon identifies SNAP packets.
- * bug8970 - LLC/noSNAP: Falcon does not provide an LLC flag.
- * LLC can't encapsulate IP, so by definition
- * these packets are NON_IP.
- *
- * Unicast mismatch will also cause TOBE_DISC, so the driver needs
- * to check this.
- */
- if (EFX_WORKAROUND_5475(efx) && rx_ev_tobe_disc && (snap || non_ip)) {
- /* If all the other flags are zero then we can state the
- * entire packet is ok, which will flag to the kernel not
- * to recalculate checksums.
- */
- if (!(non_ip | rx_ev_other_err | rx_ev_pause_frm))
- *rx_ev_pkt_ok = 1;
-
- rx_ev_tobe_disc = 0;
-
- /* TOBE_DISC is set for unicast mismatch. But given that
- * we can't trust TOBE_DISC here, we must validate the dest
- * MAC address ourselves.
- */
- if (!rx_ev_mcast_pkt && !check_dest_mac(rx_queue, event))
- rx_ev_tobe_disc = 1;
- }
-
/* Count errors that are not in MAC stats. */
if (rx_ev_frm_trunc)
++rx_queue->channel->n_rx_frm_trunc;
@@ -961,7 +793,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
#ifdef EFX_ENABLE_DEBUG
if (rx_ev_other_err) {
EFX_INFO_RL(efx, " RX queue %d unexpected RX event "
- EFX_QWORD_FMT "%s%s%s%s%s%s%s%s%s\n",
+ EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
rx_queue->queue, EFX_QWORD_VAL(*event),
rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
rx_ev_ip_hdr_chksum_err ?
@@ -972,8 +804,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
rx_ev_drib_nib ? " [DRIB_NIB]" : "",
rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
- rx_ev_pause_frm ? " [PAUSE]" : "",
- snap ? " [SNAP/LLC]" : "");
+ rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
@@ -1006,13 +837,13 @@ static void falcon_handle_rx_bad_index(struct efx_rx_queue *rx_queue,
* Also "is multicast" and "matches multicast filter" flags can be used to
* discard non-matching multicast packets.
*/
-static inline int falcon_handle_rx_event(struct efx_channel *channel,
- const efx_qword_t *event)
+static void falcon_handle_rx_event(struct efx_channel *channel,
+ const efx_qword_t *event)
{
- unsigned int rx_ev_q_label, rx_ev_desc_ptr, rx_ev_byte_cnt;
- unsigned int rx_ev_pkt_ok, rx_ev_hdr_type, rx_ev_mcast_pkt;
+ unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
+ unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
unsigned expected_ptr;
- int discard = 0, checksummed;
+ bool rx_ev_pkt_ok, discard = false, checksummed;
struct efx_rx_queue *rx_queue;
struct efx_nic *efx = channel->efx;
@@ -1022,16 +853,14 @@ static inline int falcon_handle_rx_event(struct efx_channel *channel,
rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_JUMBO_CONT));
WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_SOP) != 1);
+ WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL) != channel->channel);
- rx_ev_q_label = EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL);
- rx_queue = &efx->rx_queue[rx_ev_q_label];
+ rx_queue = &efx->rx_queue[channel->channel];
rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
expected_ptr = rx_queue->removed_count & FALCON_RXD_RING_MASK;
- if (unlikely(rx_ev_desc_ptr != expected_ptr)) {
+ if (unlikely(rx_ev_desc_ptr != expected_ptr))
falcon_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
- return rx_ev_q_label;
- }
if (likely(rx_ev_pkt_ok)) {
/* If packet is marked as OK and packet type is TCP/IPv4 or
@@ -1040,8 +869,8 @@ static inline int falcon_handle_rx_event(struct efx_channel *channel,
checksummed = RX_EV_HDR_TYPE_HAS_CHECKSUMS(rx_ev_hdr_type);
} else {
falcon_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok,
- &discard, rx_ev_byte_cnt);
- checksummed = 0;
+ &discard);
+ checksummed = false;
}
/* Detect multicast packets that didn't match the filter */
@@ -1051,14 +880,12 @@ static inline int falcon_handle_rx_event(struct efx_channel *channel,
EFX_QWORD_FIELD(*event, RX_EV_MCAST_HASH_MATCH);
if (unlikely(!rx_ev_mcast_hash_match))
- discard = 1;
+ discard = true;
}
/* Handle received packet */
efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
checksummed, discard);
-
- return rx_ev_q_label;
}
/* Global events are basically PHY events */
@@ -1066,23 +893,23 @@ static void falcon_handle_global_event(struct efx_channel *channel,
efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
- int is_phy_event = 0, handled = 0;
+ bool is_phy_event = false, handled = false;
/* Check for interrupt on either port. Some boards have a
* single PHY wired to the interrupt line for port 1. */
if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
EFX_QWORD_FIELD(*event, XG_PHY_INTR))
- is_phy_event = 1;
+ is_phy_event = true;
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
- EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0))
- is_phy_event = 1;
+ EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0))
+ is_phy_event = true;
if (is_phy_event) {
efx->phy_op->clear_interrupt(efx);
queue_work(efx->workqueue, &efx->reconfigure_work);
- handled = 1;
+ handled = true;
}
if (EFX_QWORD_FIELD_VER(efx, *event, RX_RECOVERY)) {
@@ -1092,7 +919,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
atomic_inc(&efx->rx_reset);
efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
- handled = 1;
+ handled = true;
}
if (!handled)
@@ -1163,13 +990,12 @@ static void falcon_handle_driver_event(struct efx_channel *channel,
}
}
-int falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
+int falcon_process_eventq(struct efx_channel *channel, int rx_quota)
{
unsigned int read_ptr;
efx_qword_t event, *p_event;
int ev_code;
- int rxq;
- int rxdmaqs = 0;
+ int rx_packets = 0;
read_ptr = channel->eventq_read_ptr;
@@ -1191,9 +1017,8 @@ int falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
switch (ev_code) {
case RX_IP_EV_DECODE:
- rxq = falcon_handle_rx_event(channel, &event);
- rxdmaqs |= (1 << rxq);
- (*rx_quota)--;
+ falcon_handle_rx_event(channel, &event);
+ ++rx_packets;
break;
case TX_IP_EV_DECODE:
falcon_handle_tx_event(channel, &event);
@@ -1220,10 +1045,10 @@ int falcon_process_eventq(struct efx_channel *channel, int *rx_quota)
/* Increment read pointer */
read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
- } while (*rx_quota);
+ } while (rx_packets < rx_quota);
channel->eventq_read_ptr = read_ptr;
- return rxdmaqs;
+ return rx_packets;
}
void falcon_set_int_moderation(struct efx_channel *channel)
@@ -1251,7 +1076,7 @@ void falcon_set_int_moderation(struct efx_channel *channel)
TIMER_VAL, 0);
}
falcon_writel_page_locked(efx, &timer_cmd, TIMER_CMD_REG_KER,
- channel->evqnum);
+ channel->channel);
}
@@ -1265,20 +1090,17 @@ int falcon_probe_eventq(struct efx_channel *channel)
return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
}
-int falcon_init_eventq(struct efx_channel *channel)
+void falcon_init_eventq(struct efx_channel *channel)
{
efx_oword_t evq_ptr;
struct efx_nic *efx = channel->efx;
- int rc;
EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
channel->channel, channel->eventq.index,
channel->eventq.index + channel->eventq.entries - 1);
/* Pin event queue buffer */
- rc = falcon_init_special_buffer(efx, &channel->eventq);
- if (rc)
- return rc;
+ falcon_init_special_buffer(efx, &channel->eventq);
/* Fill event queue with all ones (i.e. empty events) */
memset(channel->eventq.addr, 0xff, channel->eventq.len);
@@ -1289,11 +1111,9 @@ int falcon_init_eventq(struct efx_channel *channel)
EVQ_SIZE, FALCON_EVQ_ORDER,
EVQ_BUF_BASE_ID, channel->eventq.index);
falcon_write_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base,
- channel->evqnum);
+ channel->channel);
falcon_set_int_moderation(channel);
-
- return 0;
}
void falcon_fini_eventq(struct efx_channel *channel)
@@ -1304,7 +1124,7 @@ void falcon_fini_eventq(struct efx_channel *channel)
/* Remove event queue from card */
EFX_ZERO_OWORD(eventq_ptr);
falcon_write_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base,
- channel->evqnum);
+ channel->channel);
/* Unpin event queue */
falcon_fini_special_buffer(efx, &channel->eventq);
@@ -1331,6 +1151,121 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
falcon_generate_event(channel, &test_event);
}
+/**************************************************************************
+ *
+ * Flush handling
+ *
+ **************************************************************************/
+
+
+static void falcon_poll_flush_events(struct efx_nic *efx)
+{
+ struct efx_channel *channel = &efx->channel[0];
+ struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue *rx_queue;
+ unsigned int read_ptr, i;
+
+ read_ptr = channel->eventq_read_ptr;
+ for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
+ efx_qword_t *event = falcon_event(channel, read_ptr);
+ int ev_code, ev_sub_code, ev_queue;
+ bool ev_failed;
+ if (!falcon_event_present(event))
+ break;
+
+ ev_code = EFX_QWORD_FIELD(*event, EV_CODE);
+ if (ev_code != DRIVER_EV_DECODE)
+ continue;
+
+ ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
+ switch (ev_sub_code) {
+ case TX_DESCQ_FLS_DONE_EV_DECODE:
+ ev_queue = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_TX_DESCQ_ID);
+ if (ev_queue < EFX_TX_QUEUE_COUNT) {
+ tx_queue = efx->tx_queue + ev_queue;
+ tx_queue->flushed = true;
+ }
+ break;
+ case RX_DESCQ_FLS_DONE_EV_DECODE:
+ ev_queue = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_RX_DESCQ_ID);
+ ev_failed = EFX_QWORD_FIELD(*event,
+ DRIVER_EV_RX_FLUSH_FAIL);
+ if (ev_queue < efx->n_rx_queues) {
+ rx_queue = efx->rx_queue + ev_queue;
+
+ /* retry the rx flush */
+ if (ev_failed)
+ falcon_flush_rx_queue(rx_queue);
+ else
+ rx_queue->flushed = true;
+ }
+ break;
+ }
+
+ read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
+ }
+}
+
+/* Handle tx and rx flushes at the same time, since they run in
+ * parallel in the hardware and there's no reason for us to
+ * serialise them */
+int falcon_flush_queues(struct efx_nic *efx)
+{
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int i;
+ bool outstanding;
+
+ /* Issue flush requests */
+ efx_for_each_tx_queue(tx_queue, efx) {
+ tx_queue->flushed = false;
+ falcon_flush_tx_queue(tx_queue);
+ }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ rx_queue->flushed = false;
+ falcon_flush_rx_queue(rx_queue);
+ }
+
+ /* Poll the evq looking for flush completions. Since we're not pushing
+ * any more rx or tx descriptors at this point, we're in no danger of
+ * overflowing the evq whilst we wait */
+ for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) {
+ msleep(FALCON_FLUSH_INTERVAL);
+ falcon_poll_flush_events(efx);
+
+ /* Check if every queue has been succesfully flushed */
+ outstanding = false;
+ efx_for_each_tx_queue(tx_queue, efx)
+ outstanding |= !tx_queue->flushed;
+ efx_for_each_rx_queue(rx_queue, efx)
+ outstanding |= !rx_queue->flushed;
+ if (!outstanding)
+ return 0;
+ }
+
+ /* Mark the queues as all flushed. We're going to return failure
+ * leading to a reset, or fake up success anyway. "flushed" now
+ * indicates that we tried to flush. */
+ efx_for_each_tx_queue(tx_queue, efx) {
+ if (!tx_queue->flushed)
+ EFX_ERR(efx, "tx queue %d flush command timed out\n",
+ tx_queue->queue);
+ tx_queue->flushed = true;
+ }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ if (!rx_queue->flushed)
+ EFX_ERR(efx, "rx queue %d flush command timed out\n",
+ rx_queue->queue);
+ rx_queue->flushed = true;
+ }
+
+ if (EFX_WORKAROUND_7803(efx))
+ return 0;
+
+ return -ETIMEDOUT;
+}
/**************************************************************************
*
@@ -1371,7 +1306,7 @@ void falcon_enable_interrupts(struct efx_nic *efx)
/* Force processing of all the channels to get the EVQ RPTRs up to
date */
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel(channel, efx)
efx_schedule_channel(channel);
}
@@ -1439,10 +1374,11 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
}
- /* Disable DMA bus mastering on both devices */
+ /* Disable both devices */
pci_disable_device(efx->pci_dev);
if (FALCON_IS_DUAL_FUNC(efx))
pci_disable_device(nic_data->pci_dev2);
+ falcon_disable_interrupts(efx);
if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n");
@@ -1589,7 +1525,7 @@ static void falcon_setup_rss_indir_table(struct efx_nic *efx)
offset < RX_RSS_INDIR_TBL_B0 + 0x800;
offset += 0x10) {
EFX_POPULATE_DWORD_1(dword, RX_RSS_INDIR_ENT_B0,
- i % efx->rss_queues);
+ i % efx->n_rx_queues);
falcon_writel(efx, &dword, offset);
i++;
}
@@ -1621,7 +1557,7 @@ int falcon_init_interrupt(struct efx_nic *efx)
}
/* Hook MSI or MSI-X interrupt */
- efx_for_each_channel_with_interrupt(channel, efx) {
+ efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, falcon_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
efx->name, channel);
@@ -1634,7 +1570,7 @@ int falcon_init_interrupt(struct efx_nic *efx)
return 0;
fail2:
- efx_for_each_channel_with_interrupt(channel, efx)
+ efx_for_each_channel(channel, efx)
free_irq(channel->irq, channel);
fail1:
return rc;
@@ -1646,7 +1582,7 @@ void falcon_fini_interrupt(struct efx_nic *efx)
efx_oword_t reg;
/* Disable MSI/MSI-X interrupts */
- efx_for_each_channel_with_interrupt(channel, efx) {
+ efx_for_each_channel(channel, efx) {
if (channel->irq)
free_irq(channel->irq, channel);
}
@@ -1669,69 +1605,200 @@ void falcon_fini_interrupt(struct efx_nic *efx)
**************************************************************************
*/
-#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
+#define FALCON_SPI_MAX_LEN ((unsigned) sizeof(efx_oword_t))
/* Wait for SPI command completion */
static int falcon_spi_wait(struct efx_nic *efx)
{
+ unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10);
efx_oword_t reg;
- int cmd_en, timer_active;
- int count;
+ bool cmd_en, timer_active;
- count = 0;
- do {
+ for (;;) {
falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
if (!cmd_en && !timer_active)
return 0;
- udelay(10);
- } while (++count < 10000); /* wait upto 100msec */
- EFX_ERR(efx, "timed out waiting for SPI\n");
- return -ETIMEDOUT;
+ if (time_after_eq(jiffies, timeout)) {
+ EFX_ERR(efx, "timed out waiting for SPI\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
}
-static int
-falcon_spi_read(struct efx_nic *efx, int device_id, unsigned int command,
- unsigned int address, unsigned int addr_len,
- void *data, unsigned int len)
+static int falcon_spi_cmd(const struct efx_spi_device *spi,
+ unsigned int command, int address,
+ const void *in, void *out, unsigned int len)
{
+ struct efx_nic *efx = spi->efx;
+ bool addressed = (address >= 0);
+ bool reading = (out != NULL);
efx_oword_t reg;
int rc;
- BUG_ON(len > FALCON_SPI_MAX_LEN);
+ /* Input validation */
+ if (len > FALCON_SPI_MAX_LEN)
+ return -EINVAL;
/* Check SPI not currently being accessed */
rc = falcon_spi_wait(efx);
if (rc)
return rc;
- /* Program address register */
- EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address);
- falcon_write(efx, &reg, EE_SPI_HADR_REG_KER);
+ /* Program address register, if we have an address */
+ if (addressed) {
+ EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address);
+ falcon_write(efx, &reg, EE_SPI_HADR_REG_KER);
+ }
+
+ /* Program data register, if we have data */
+ if (in != NULL) {
+ memcpy(&reg, in, len);
+ falcon_write(efx, &reg, EE_SPI_HDATA_REG_KER);
+ }
- /* Issue read command */
+ /* Issue read/write command */
EFX_POPULATE_OWORD_7(reg,
EE_SPI_HCMD_CMD_EN, 1,
- EE_SPI_HCMD_SF_SEL, device_id,
+ EE_SPI_HCMD_SF_SEL, spi->device_id,
EE_SPI_HCMD_DABCNT, len,
- EE_SPI_HCMD_READ, EE_SPI_READ,
+ EE_SPI_HCMD_READ, reading,
EE_SPI_HCMD_DUBCNT, 0,
- EE_SPI_HCMD_ADBCNT, addr_len,
+ EE_SPI_HCMD_ADBCNT,
+ (addressed ? spi->addr_len : 0),
EE_SPI_HCMD_ENC, command);
falcon_write(efx, &reg, EE_SPI_HCMD_REG_KER);
- /* Wait for read to complete */
+ /* Wait for read/write to complete */
rc = falcon_spi_wait(efx);
if (rc)
return rc;
/* Read data */
- falcon_read(efx, &reg, EE_SPI_HDATA_REG_KER);
- memcpy(data, &reg, len);
+ if (out != NULL) {
+ falcon_read(efx, &reg, EE_SPI_HDATA_REG_KER);
+ memcpy(out, &reg, len);
+ }
+
return 0;
}
+static unsigned int
+falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start)
+{
+ return min(FALCON_SPI_MAX_LEN,
+ (spi->block_size - (start & (spi->block_size - 1))));
+}
+
+static inline u8
+efx_spi_munge_command(const struct efx_spi_device *spi,
+ const u8 command, const unsigned int address)
+{
+ return command | (((address >> 8) & spi->munge_address) << 3);
+}
+
+
+static int falcon_spi_fast_wait(const struct efx_spi_device *spi)
+{
+ u8 status;
+ int i, rc;
+
+ /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
+ for (i = 0; i < 50; i++) {
+ udelay(20);
+
+ rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
+ &status, sizeof(status));
+ if (rc)
+ return rc;
+ if (!(status & SPI_STATUS_NRDY))
+ return 0;
+ }
+ EFX_ERR(spi->efx,
+ "timed out waiting for device %d last status=0x%02x\n",
+ spi->device_id, status);
+ return -ETIMEDOUT;
+}
+
+int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
+ size_t len, size_t *retlen, u8 *buffer)
+{
+ unsigned int command, block_len, pos = 0;
+ int rc = 0;
+
+ while (pos < len) {
+ block_len = min((unsigned int)len - pos,
+ FALCON_SPI_MAX_LEN);
+
+ command = efx_spi_munge_command(spi, SPI_READ, start + pos);
+ rc = falcon_spi_cmd(spi, command, start + pos, NULL,
+ buffer + pos, block_len);
+ if (rc)
+ break;
+ pos += block_len;
+
+ /* Avoid locking up the system */
+ cond_resched();
+ if (signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
+ }
+
+ if (retlen)
+ *retlen = pos;
+ return rc;
+}
+
+int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
+ size_t len, size_t *retlen, const u8 *buffer)
+{
+ u8 verify_buffer[FALCON_SPI_MAX_LEN];
+ unsigned int command, block_len, pos = 0;
+ int rc = 0;
+
+ while (pos < len) {
+ rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+ if (rc)
+ break;
+
+ block_len = min((unsigned int)len - pos,
+ falcon_spi_write_limit(spi, start + pos));
+ command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
+ rc = falcon_spi_cmd(spi, command, start + pos,
+ buffer + pos, NULL, block_len);
+ if (rc)
+ break;
+
+ rc = falcon_spi_fast_wait(spi);
+ if (rc)
+ break;
+
+ command = efx_spi_munge_command(spi, SPI_READ, start + pos);
+ rc = falcon_spi_cmd(spi, command, start + pos,
+ NULL, verify_buffer, block_len);
+ if (memcmp(verify_buffer, buffer + pos, block_len)) {
+ rc = -EIO;
+ break;
+ }
+
+ pos += block_len;
+
+ /* Avoid locking up the system */
+ cond_resched();
+ if (signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
+ }
+
+ if (retlen)
+ *retlen = pos;
+ return rc;
+}
+
/**************************************************************************
*
* MAC wrapper
@@ -1812,7 +1879,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
{
efx_oword_t reg;
int link_speed;
- unsigned int tx_fc;
+ bool tx_fc;
if (efx->link_options & GM_LPA_10000)
link_speed = 0x3;
@@ -1847,7 +1914,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
/* Transmission of pause frames when RX crosses the threshold is
* covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
* Action on receipt of pause frames is controller by XM_DIS_FCNTL */
- tx_fc = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
+ tx_fc = !!(efx->flow_control & EFX_FC_TX);
falcon_read(efx, &reg, RX_CFG_REG_KER);
EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
@@ -1887,8 +1954,10 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
/* Wait for transfer to complete */
for (i = 0; i < 400; i++) {
- if (*(volatile u32 *)dma_done == FALCON_STATS_DONE)
+ if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
+ rmb(); /* Ensure the stats are valid. */
return 0;
+ }
udelay(10);
}
@@ -1951,7 +2020,7 @@ static int falcon_gmii_wait(struct efx_nic *efx)
static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
int addr, int value)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg;
@@ -2019,7 +2088,7 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
* could be read, -1 will be returned. */
static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
{
- struct efx_nic *efx = net_dev->priv;
+ struct efx_nic *efx = netdev_priv(net_dev);
unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg;
int value = -1;
@@ -2120,7 +2189,7 @@ int falcon_probe_port(struct efx_nic *efx)
return rc;
/* Set up GMII structure for PHY */
- efx->mii.supports_gmii = 1;
+ efx->mii.supports_gmii = true;
falcon_init_mdio(&efx->mii);
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
@@ -2168,6 +2237,170 @@ void falcon_set_multicast_hash(struct efx_nic *efx)
falcon_write(efx, &mc_hash->oword[1], MAC_MCAST_HASH_REG1_KER);
}
+
+/**************************************************************************
+ *
+ * Falcon test code
+ *
+ **************************************************************************/
+
+int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
+{
+ struct falcon_nvconfig *nvconfig;
+ struct efx_spi_device *spi;
+ void *region;
+ int rc, magic_num, struct_ver;
+ __le16 *word, *limit;
+ u32 csum;
+
+ region = kmalloc(NVCONFIG_END, GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+ nvconfig = region + NVCONFIG_OFFSET;
+
+ spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
+ rc = falcon_spi_read(spi, 0, NVCONFIG_END, NULL, region);
+ if (rc) {
+ EFX_ERR(efx, "Failed to read %s\n",
+ efx->spi_flash ? "flash" : "EEPROM");
+ rc = -EIO;
+ goto out;
+ }
+
+ magic_num = le16_to_cpu(nvconfig->board_magic_num);
+ struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
+
+ rc = -EINVAL;
+ if (magic_num != NVCONFIG_BOARD_MAGIC_NUM) {
+ EFX_ERR(efx, "NVRAM bad magic 0x%x\n", magic_num);
+ goto out;
+ }
+ if (struct_ver < 2) {
+ EFX_ERR(efx, "NVRAM has ancient version 0x%x\n", struct_ver);
+ goto out;
+ } else if (struct_ver < 4) {
+ word = &nvconfig->board_magic_num;
+ limit = (__le16 *) (nvconfig + 1);
+ } else {
+ word = region;
+ limit = region + NVCONFIG_END;
+ }
+ for (csum = 0; word < limit; ++word)
+ csum += le16_to_cpu(*word);
+
+ if (~csum & 0xffff) {
+ EFX_ERR(efx, "NVRAM has incorrect checksum\n");
+ goto out;
+ }
+
+ rc = 0;
+ if (nvconfig_out)
+ memcpy(nvconfig_out, nvconfig, sizeof(*nvconfig));
+
+ out:
+ kfree(region);
+ return rc;
+}
+
+/* Registers tested in the falcon register test */
+static struct {
+ unsigned address;
+ efx_oword_t mask;
+} efx_test_registers[] = {
+ { ADR_REGION_REG_KER,
+ EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) },
+ { RX_CFG_REG_KER,
+ EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) },
+ { TX_CFG_REG_KER,
+ EFX_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) },
+ { TX_CFG2_REG_KER,
+ EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
+ { MAC0_CTRL_REG_KER,
+ EFX_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) },
+ { SRM_TX_DC_CFG_REG_KER,
+ EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ { RX_DC_CFG_REG_KER,
+ EFX_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) },
+ { RX_DC_PF_WM_REG_KER,
+ EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
+ { DP_CTRL_REG,
+ EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_GLB_CFG_REG,
+ EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_TX_CFG_REG,
+ EFX_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_RX_CFG_REG,
+ EFX_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_RX_PARAM_REG,
+ EFX_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_FC_REG,
+ EFX_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) },
+ { XM_ADR_LO_REG,
+ EFX_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) },
+ { XX_SD_CTL_REG,
+ EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
+};
+
+static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
+ const efx_oword_t *mask)
+{
+ return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) ||
+ ((a->u64[1] ^ b->u64[1]) & mask->u64[1]);
+}
+
+int falcon_test_registers(struct efx_nic *efx)
+{
+ unsigned address = 0, i, j;
+ efx_oword_t mask, imask, original, reg, buf;
+
+ /* Falcon should be in loopback to isolate the XMAC from the PHY */
+ WARN_ON(!LOOPBACK_INTERNAL(efx));
+
+ for (i = 0; i < ARRAY_SIZE(efx_test_registers); ++i) {
+ address = efx_test_registers[i].address;
+ mask = imask = efx_test_registers[i].mask;
+ EFX_INVERT_OWORD(imask);
+
+ falcon_read(efx, &original, address);
+
+ /* bit sweep on and off */
+ for (j = 0; j < 128; j++) {
+ if (!EFX_EXTRACT_OWORD32(mask, j, j))
+ continue;
+
+ /* Test this testable bit can be set in isolation */
+ EFX_AND_OWORD(reg, original, mask);
+ EFX_SET_OWORD32(reg, j, j, 1);
+
+ falcon_write(efx, &reg, address);
+ falcon_read(efx, &buf, address);
+
+ if (efx_masked_compare_oword(&reg, &buf, &mask))
+ goto fail;
+
+ /* Test this testable bit can be cleared in isolation */
+ EFX_OR_OWORD(reg, original, mask);
+ EFX_SET_OWORD32(reg, j, j, 0);
+
+ falcon_write(efx, &reg, address);
+ falcon_read(efx, &buf, address);
+
+ if (efx_masked_compare_oword(&reg, &buf, &mask))
+ goto fail;
+ }
+
+ falcon_write(efx, &original, address);
+ }
+
+ return 0;
+
+fail:
+ EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
+ " at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
+ EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
+ return -EIO;
+}
+
/**************************************************************************
*
* Device reset
@@ -2305,68 +2538,103 @@ static int falcon_reset_sram(struct efx_nic *efx)
return -ETIMEDOUT;
}
+static int falcon_spi_device_init(struct efx_nic *efx,
+ struct efx_spi_device **spi_device_ret,
+ unsigned int device_id, u32 device_type)
+{
+ struct efx_spi_device *spi_device;
+
+ if (device_type != 0) {
+ spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL);
+ if (!spi_device)
+ return -ENOMEM;
+ spi_device->device_id = device_id;
+ spi_device->size =
+ 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE);
+ spi_device->addr_len =
+ SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
+ spi_device->munge_address = (spi_device->size == 1 << 9 &&
+ spi_device->addr_len == 1);
+ spi_device->block_size =
+ 1 << SPI_DEV_TYPE_FIELD(device_type,
+ SPI_DEV_TYPE_BLOCK_SIZE);
+
+ spi_device->efx = efx;
+ } else {
+ spi_device = NULL;
+ }
+
+ kfree(*spi_device_ret);
+ *spi_device_ret = spi_device;
+ return 0;
+}
+
+
+static void falcon_remove_spi_devices(struct efx_nic *efx)
+{
+ kfree(efx->spi_eeprom);
+ efx->spi_eeprom = NULL;
+ kfree(efx->spi_flash);
+ efx->spi_flash = NULL;
+}
+
/* Extract non-volatile configuration */
static int falcon_probe_nvconfig(struct efx_nic *efx)
{
struct falcon_nvconfig *nvconfig;
- efx_oword_t nic_stat;
- int device_id;
- unsigned addr_len;
- size_t offset, len;
- int magic_num, struct_ver, board_rev;
+ int board_rev;
int rc;
- /* Find the boot device. */
- falcon_read(efx, &nic_stat, NIC_STAT_REG);
- if (EFX_OWORD_FIELD(nic_stat, SF_PRST)) {
- device_id = EE_SPI_FLASH;
- addr_len = 3;
- } else if (EFX_OWORD_FIELD(nic_stat, EE_PRST)) {
- device_id = EE_SPI_EEPROM;
- addr_len = 2;
- } else {
- return -ENODEV;
- }
-
nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
+ if (!nvconfig)
+ return -ENOMEM;
- /* Read the whole configuration structure into memory. */
- for (offset = 0; offset < sizeof(*nvconfig); offset += len) {
- len = min(sizeof(*nvconfig) - offset,
- (size_t) FALCON_SPI_MAX_LEN);
- rc = falcon_spi_read(efx, device_id, SPI_READ,
- NVCONFIG_BASE + offset, addr_len,
- (char *)nvconfig + offset, len);
- if (rc)
- goto out;
- }
-
- /* Read the MAC addresses */
- memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
-
- /* Read the board configuration. */
- magic_num = le16_to_cpu(nvconfig->board_magic_num);
- struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
-
- if (magic_num != NVCONFIG_BOARD_MAGIC_NUM || struct_ver < 2) {
- EFX_ERR(efx, "Non volatile memory bad magic=%x ver=%x "
- "therefore using defaults\n", magic_num, struct_ver);
+ rc = falcon_read_nvram(efx, nvconfig);
+ if (rc == -EINVAL) {
+ EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
efx->phy_type = PHY_TYPE_NONE;
efx->mii.phy_id = PHY_ADDR_INVALID;
board_rev = 0;
+ rc = 0;
+ } else if (rc) {
+ goto fail1;
} else {
struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
+ struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
efx->phy_type = v2->port0_phy_type;
efx->mii.phy_id = v2->port0_phy_addr;
board_rev = le16_to_cpu(v2->board_revision);
+
+ if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
+ __le32 fl = v3->spi_device_type[EE_SPI_FLASH];
+ __le32 ee = v3->spi_device_type[EE_SPI_EEPROM];
+ rc = falcon_spi_device_init(efx, &efx->spi_flash,
+ EE_SPI_FLASH,
+ le32_to_cpu(fl));
+ if (rc)
+ goto fail2;
+ rc = falcon_spi_device_init(efx, &efx->spi_eeprom,
+ EE_SPI_EEPROM,
+ le32_to_cpu(ee));
+ if (rc)
+ goto fail2;
+ }
}
+ /* Read the MAC addresses */
+ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
+
EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id);
efx_set_board_info(efx, board_rev);
- out:
+ kfree(nvconfig);
+ return 0;
+
+ fail2:
+ falcon_remove_spi_devices(efx);
+ fail1:
kfree(nvconfig);
return rc;
}
@@ -2417,6 +2685,86 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
return 0;
}
+/* Probe all SPI devices on the NIC */
+static void falcon_probe_spi_devices(struct efx_nic *efx)
+{
+ efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
+ bool has_flash, has_eeprom, boot_is_external;
+
+ falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER);
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+ falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
+
+ has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST);
+ has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST);
+ boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE);
+
+ if (has_flash) {
+ /* Default flash SPI device: Atmel AT25F1024
+ * 128 KB, 24-bit address, 32 KB erase block,
+ * 256 B write block
+ */
+ u32 flash_device_type =
+ (17 << SPI_DEV_TYPE_SIZE_LBN)
+ | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
+ | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
+ | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
+
+ falcon_spi_device_init(efx, &efx->spi_flash,
+ EE_SPI_FLASH, flash_device_type);
+
+ if (!boot_is_external) {
+ /* Disable VPD and set clock dividers to safe
+ * values for initial programming.
+ */
+ EFX_LOG(efx, "Booted from internal ASIC settings;"
+ " setting SPI config\n");
+ EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
+ /* 125 MHz / 7 ~= 20 MHz */
+ EE_SF_CLOCK_DIV, 7,
+ /* 125 MHz / 63 ~= 2 MHz */
+ EE_EE_CLOCK_DIV, 63);
+ falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
+ }
+ }
+
+ if (has_eeprom) {
+ u32 eeprom_device_type;
+
+ /* If it has no flash, it must have a large EEPROM
+ * for chip config; otherwise check whether 9-bit
+ * addressing is used for VPD configuration
+ */
+ if (has_flash &&
+ (!boot_is_external ||
+ EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) {
+ /* Default SPI device: Atmel AT25040 or similar
+ * 512 B, 9-bit address, 8 B write block
+ */
+ eeprom_device_type =
+ (9 << SPI_DEV_TYPE_SIZE_LBN)
+ | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
+ } else {
+ /* "Large" SPI device: Atmel AT25640 or similar
+ * 8 KB, 16-bit address, 32 B write block
+ */
+ eeprom_device_type =
+ (13 << SPI_DEV_TYPE_SIZE_LBN)
+ | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
+ }
+
+ falcon_spi_device_init(efx, &efx->spi_eeprom,
+ EE_SPI_EEPROM, eeprom_device_type);
+ }
+
+ EFX_LOG(efx, "flash is %s, EEPROM is %s\n",
+ (has_flash ? "present" : "absent"),
+ (has_eeprom ? "present" : "absent"));
+}
+
int falcon_probe_nic(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data;
@@ -2424,6 +2772,8 @@ int falcon_probe_nic(struct efx_nic *efx)
/* Allocate storage for hardware specific data */
nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
+ if (!nic_data)
+ return -ENOMEM;
efx->nic_data = nic_data;
/* Determine number of ports etc. */
@@ -2467,6 +2817,8 @@ int falcon_probe_nic(struct efx_nic *efx)
(unsigned long long)efx->irq_status.dma_addr,
efx->irq_status.addr, virt_to_phys(efx->irq_status.addr));
+ falcon_probe_spi_devices(efx);
+
/* Read in the non-volatile configuration */
rc = falcon_probe_nvconfig(efx);
if (rc)
@@ -2486,6 +2838,7 @@ int falcon_probe_nic(struct efx_nic *efx)
return 0;
fail5:
+ falcon_remove_spi_devices(efx);
falcon_free_buffer(efx, &efx->irq_status);
fail4:
fail3:
@@ -2573,19 +2926,14 @@ int falcon_init_nic(struct efx_nic *efx)
EFX_INVERT_OWORD(temp);
falcon_write(efx, &temp, FATAL_INTR_REG_KER);
- /* Set number of RSS queues for receive path. */
- falcon_read(efx, &temp, RX_FILTER_CTL_REG);
- if (falcon_rev(efx) >= FALCON_REV_B0)
- EFX_SET_OWORD_FIELD(temp, NUM_KER, 0);
- else
- EFX_SET_OWORD_FIELD(temp, NUM_KER, efx->rss_queues - 1);
if (EFX_WORKAROUND_7244(efx)) {
+ falcon_read(efx, &temp, RX_FILTER_CTL_REG);
EFX_SET_OWORD_FIELD(temp, UDP_FULL_SRCH_LIMIT, 8);
EFX_SET_OWORD_FIELD(temp, UDP_WILD_SRCH_LIMIT, 8);
EFX_SET_OWORD_FIELD(temp, TCP_FULL_SRCH_LIMIT, 8);
EFX_SET_OWORD_FIELD(temp, TCP_WILD_SRCH_LIMIT, 8);
+ falcon_write(efx, &temp, RX_FILTER_CTL_REG);
}
- falcon_write(efx, &temp, RX_FILTER_CTL_REG);
falcon_setup_rss_indir_table(efx);
@@ -2641,8 +2989,8 @@ int falcon_init_nic(struct efx_nic *efx)
rx_xoff_thresh_bytes : efx->type->rx_xoff_thresh);
EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_MAC_TH, thresh / 256);
/* RX control FIFO thresholds [32 entries] */
- EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_TX_TH, 25);
- EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 20);
+ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_TX_TH, 20);
+ EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 25);
falcon_write(efx, &temp, RX_CFG_REG_KER);
/* Set destination of both TX and RX Flush events */
@@ -2662,6 +3010,7 @@ void falcon_remove_nic(struct efx_nic *efx)
rc = i2c_del_adapter(&efx->i2c_adap);
BUG_ON(rc);
+ falcon_remove_spi_devices(efx);
falcon_free_buffer(efx, &efx->irq_status);
falcon_reset_hw(efx, RESET_TYPE_ALL);
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 492f9bc2884..be025ba7a6c 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -40,24 +40,24 @@ extern struct efx_nic_type falcon_b_nic_type;
/* TX data path */
extern int falcon_probe_tx(struct efx_tx_queue *tx_queue);
-extern int falcon_init_tx(struct efx_tx_queue *tx_queue);
+extern void falcon_init_tx(struct efx_tx_queue *tx_queue);
extern void falcon_fini_tx(struct efx_tx_queue *tx_queue);
extern void falcon_remove_tx(struct efx_tx_queue *tx_queue);
extern void falcon_push_buffers(struct efx_tx_queue *tx_queue);
/* RX data path */
extern int falcon_probe_rx(struct efx_rx_queue *rx_queue);
-extern int falcon_init_rx(struct efx_rx_queue *rx_queue);
+extern void falcon_init_rx(struct efx_rx_queue *rx_queue);
extern void falcon_fini_rx(struct efx_rx_queue *rx_queue);
extern void falcon_remove_rx(struct efx_rx_queue *rx_queue);
extern void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue);
/* Event data path */
extern int falcon_probe_eventq(struct efx_channel *channel);
-extern int falcon_init_eventq(struct efx_channel *channel);
+extern void falcon_init_eventq(struct efx_channel *channel);
extern void falcon_fini_eventq(struct efx_channel *channel);
extern void falcon_remove_eventq(struct efx_channel *channel);
-extern int falcon_process_eventq(struct efx_channel *channel, int *rx_quota);
+extern int falcon_process_eventq(struct efx_channel *channel, int rx_quota);
extern void falcon_eventq_read_ack(struct efx_channel *channel);
/* Ports */
@@ -65,7 +65,7 @@ extern int falcon_probe_port(struct efx_nic *efx);
extern void falcon_remove_port(struct efx_nic *efx);
/* MAC/PHY */
-extern int falcon_xaui_link_ok(struct efx_nic *efx);
+extern bool falcon_xaui_link_ok(struct efx_nic *efx);
extern int falcon_dma_stats(struct efx_nic *efx,
unsigned int done_offset);
extern void falcon_drain_tx_fifo(struct efx_nic *efx);
@@ -86,6 +86,7 @@ extern void falcon_fini_interrupt(struct efx_nic *efx);
extern int falcon_probe_nic(struct efx_nic *efx);
extern int falcon_probe_resources(struct efx_nic *efx);
extern int falcon_init_nic(struct efx_nic *efx);
+extern int falcon_flush_queues(struct efx_nic *efx);
extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
extern void falcon_remove_resources(struct efx_nic *efx);
extern void falcon_remove_nic(struct efx_nic *efx);
@@ -93,6 +94,12 @@ extern void falcon_update_nic_stats(struct efx_nic *efx);
extern void falcon_set_multicast_hash(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
+/* Tests */
+struct falcon_nvconfig;
+extern int falcon_read_nvram(struct efx_nic *efx,
+ struct falcon_nvconfig *nvconfig);
+extern int falcon_test_registers(struct efx_nic *efx);
+
/**************************************************************************
*
* Falcon MAC stats
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 6d003114eea..5d584b0dbb5 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -92,6 +92,17 @@
/* SPI host data register */
#define EE_SPI_HDATA_REG_KER 0x0120
+/* SPI/VPD config register */
+#define EE_VPD_CFG_REG_KER 0x0140
+#define EE_VPD_EN_LBN 0
+#define EE_VPD_EN_WIDTH 1
+#define EE_VPD_EN_AD9_MODE_LBN 1
+#define EE_VPD_EN_AD9_MODE_WIDTH 1
+#define EE_EE_CLOCK_DIV_LBN 112
+#define EE_EE_CLOCK_DIV_WIDTH 7
+#define EE_SF_CLOCK_DIV_LBN 120
+#define EE_SF_CLOCK_DIV_WIDTH 7
+
/* PCIE CORE ACCESS REG */
#define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68
#define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70
@@ -106,7 +117,6 @@
#define SF_PRST_WIDTH 1
#define EE_PRST_LBN 8
#define EE_PRST_WIDTH 1
-/* See pic_mode_t for decoding of this field */
/* These bit definitions are extrapolated from the list of numerical
* values for STRAP_PINS.
*/
@@ -115,6 +125,9 @@
#define STRAP_PCIE_LBN 0
#define STRAP_PCIE_WIDTH 1
+#define BOOTED_USING_NVDEVICE_LBN 3
+#define BOOTED_USING_NVDEVICE_WIDTH 1
+
/* GPIO control register */
#define GPIO_CTL_REG_KER 0x0210
#define GPIO_OUTPUTS_LBN (16)
@@ -479,18 +492,8 @@
#define MAC_MCAST_HASH_REG0_KER 0xca0
#define MAC_MCAST_HASH_REG1_KER 0xcb0
-/* GMAC registers */
-#define FALCON_GMAC_REGBANK 0xe00
-#define FALCON_GMAC_REGBANK_SIZE 0x200
-#define FALCON_GMAC_REG_SIZE 0x10
-
-/* XMAC registers */
-#define FALCON_XMAC_REGBANK 0x1200
-#define FALCON_XMAC_REGBANK_SIZE 0x200
-#define FALCON_XMAC_REG_SIZE 0x10
-
/* XGMAC address register low */
-#define XM_ADR_LO_REG_MAC 0x00
+#define XM_ADR_LO_REG 0x1200
#define XM_ADR_3_LBN 24
#define XM_ADR_3_WIDTH 8
#define XM_ADR_2_LBN 16
@@ -501,14 +504,14 @@
#define XM_ADR_0_WIDTH 8
/* XGMAC address register high */
-#define XM_ADR_HI_REG_MAC 0x01
+#define XM_ADR_HI_REG 0x1210
#define XM_ADR_5_LBN 8
#define XM_ADR_5_WIDTH 8
#define XM_ADR_4_LBN 0
#define XM_ADR_4_WIDTH 8
/* XGMAC global configuration */
-#define XM_GLB_CFG_REG_MAC 0x02
+#define XM_GLB_CFG_REG 0x1220
#define XM_RX_STAT_EN_LBN 11
#define XM_RX_STAT_EN_WIDTH 1
#define XM_TX_STAT_EN_LBN 10
@@ -521,7 +524,7 @@
#define XM_CORE_RST_WIDTH 1
/* XGMAC transmit configuration */
-#define XM_TX_CFG_REG_MAC 0x03
+#define XM_TX_CFG_REG 0x1230
#define XM_IPG_LBN 16
#define XM_IPG_WIDTH 4
#define XM_FCNTL_LBN 10
@@ -536,7 +539,7 @@
#define XM_TXEN_WIDTH 1
/* XGMAC receive configuration */
-#define XM_RX_CFG_REG_MAC 0x04
+#define XM_RX_CFG_REG 0x1240
#define XM_PASS_CRC_ERR_LBN 25
#define XM_PASS_CRC_ERR_WIDTH 1
#define XM_ACPT_ALL_MCAST_LBN 11
@@ -549,7 +552,7 @@
#define XM_RXEN_WIDTH 1
/* XGMAC management interrupt mask register */
-#define XM_MGT_INT_MSK_REG_MAC_B0 0x5
+#define XM_MGT_INT_MSK_REG_B0 0x1250
#define XM_MSK_PRMBLE_ERR_LBN 2
#define XM_MSK_PRMBLE_ERR_WIDTH 1
#define XM_MSK_RMTFLT_LBN 1
@@ -558,29 +561,29 @@
#define XM_MSK_LCLFLT_WIDTH 1
/* XGMAC flow control register */
-#define XM_FC_REG_MAC 0x7
+#define XM_FC_REG 0x1270
#define XM_PAUSE_TIME_LBN 16
#define XM_PAUSE_TIME_WIDTH 16
#define XM_DIS_FCNTL_LBN 0
#define XM_DIS_FCNTL_WIDTH 1
/* XGMAC pause time count register */
-#define XM_PAUSE_TIME_REG_MAC 0x9
+#define XM_PAUSE_TIME_REG 0x1290
/* XGMAC transmit parameter register */
-#define XM_TX_PARAM_REG_MAC 0x0d
+#define XM_TX_PARAM_REG 0x012d0
#define XM_TX_JUMBO_MODE_LBN 31
#define XM_TX_JUMBO_MODE_WIDTH 1
#define XM_MAX_TX_FRM_SIZE_LBN 16
#define XM_MAX_TX_FRM_SIZE_WIDTH 14
/* XGMAC receive parameter register */
-#define XM_RX_PARAM_REG_MAC 0x0e
+#define XM_RX_PARAM_REG 0x12e0
#define XM_MAX_RX_FRM_SIZE_LBN 0
#define XM_MAX_RX_FRM_SIZE_WIDTH 14
/* XGMAC management interrupt status register */
-#define XM_MGT_INT_REG_MAC_B0 0x0f
+#define XM_MGT_INT_REG_B0 0x12f0
#define XM_PRMBLE_ERR 2
#define XM_PRMBLE_WIDTH 1
#define XM_RMTFLT_LBN 1
@@ -589,7 +592,7 @@
#define XM_LCLFLT_WIDTH 1
/* XGXS/XAUI powerdown/reset register */
-#define XX_PWR_RST_REG_MAC 0x10
+#define XX_PWR_RST_REG 0x1300
#define XX_PWRDND_EN_LBN 15
#define XX_PWRDND_EN_WIDTH 1
@@ -619,7 +622,7 @@
#define XX_RST_XX_EN_WIDTH 1
/* XGXS/XAUI powerdown/reset control register */
-#define XX_SD_CTL_REG_MAC 0x11
+#define XX_SD_CTL_REG 0x1310
#define XX_HIDRVD_LBN 15
#define XX_HIDRVD_WIDTH 1
#define XX_LODRVD_LBN 14
@@ -645,7 +648,7 @@
#define XX_LPBKA_LBN 0
#define XX_LPBKA_WIDTH 1
-#define XX_TXDRV_CTL_REG_MAC 0x12
+#define XX_TXDRV_CTL_REG 0x1320
#define XX_DEQD_LBN 28
#define XX_DEQD_WIDTH 4
#define XX_DEQC_LBN 24
@@ -664,7 +667,7 @@
#define XX_DTXA_WIDTH 4
/* XAUI XGXS core status register */
-#define XX_CORE_STAT_REG_MAC 0x16
+#define XX_CORE_STAT_REG 0x1360
#define XX_FORCE_SIG_LBN 24
#define XX_FORCE_SIG_WIDTH 8
#define XX_FORCE_SIG_DECODE_FORCED 0xff
@@ -1127,7 +1130,28 @@ struct falcon_nvconfig_board_v2 {
__le16 board_revision;
} __packed;
-#define NVCONFIG_BASE 0x300
+/* Board configuration v3 extra information */
+struct falcon_nvconfig_board_v3 {
+ __le32 spi_device_type[2];
+} __packed;
+
+/* Bit numbers for spi_device_type */
+#define SPI_DEV_TYPE_SIZE_LBN 0
+#define SPI_DEV_TYPE_SIZE_WIDTH 5
+#define SPI_DEV_TYPE_ADDR_LEN_LBN 6
+#define SPI_DEV_TYPE_ADDR_LEN_WIDTH 2
+#define SPI_DEV_TYPE_ERASE_CMD_LBN 8
+#define SPI_DEV_TYPE_ERASE_CMD_WIDTH 8
+#define SPI_DEV_TYPE_ERASE_SIZE_LBN 16
+#define SPI_DEV_TYPE_ERASE_SIZE_WIDTH 5
+#define SPI_DEV_TYPE_BLOCK_SIZE_LBN 24
+#define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH 5
+#define SPI_DEV_TYPE_FIELD(type, field) \
+ (((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(EFX_WIDTH(field)))
+
+#define NVCONFIG_OFFSET 0x300
+#define NVCONFIG_END 0x400
+
#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
struct falcon_nvconfig {
efx_oword_t ee_vpd_cfg_reg; /* 0x300 */
@@ -1144,6 +1168,8 @@ struct falcon_nvconfig {
__le16 board_struct_ver;
__le16 board_checksum;
struct falcon_nvconfig_board_v2 board_v2;
+ efx_oword_t ee_base_page_reg; /* 0x3B0 */
+ struct falcon_nvconfig_board_v3 board_v3;
} __packed;
#endif /* EFX_FALCON_HWDEFS_H */
diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h
index 6670cdfc41a..c16da3149fa 100644
--- a/drivers/net/sfc/falcon_io.h
+++ b/drivers/net/sfc/falcon_io.h
@@ -13,7 +13,6 @@
#include <linux/io.h>
#include <linux/spinlock.h>
-#include "net_driver.h"
/**************************************************************************
*
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index 55c0d9760be..d4012314dd0 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -23,56 +23,24 @@
/**************************************************************************
*
- * MAC register access
- *
- **************************************************************************/
-
-/* Offset of an XMAC register within Falcon */
-#define FALCON_XMAC_REG(mac_reg) \
- (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE))
-
-void falcon_xmac_writel(struct efx_nic *efx,
- efx_dword_t *value, unsigned int mac_reg)
-{
- efx_oword_t temp;
-
- EFX_POPULATE_OWORD_1(temp, MAC_DATA, EFX_DWORD_FIELD(*value, MAC_DATA));
- falcon_write(efx, &temp, FALCON_XMAC_REG(mac_reg));
-}
-
-void falcon_xmac_readl(struct efx_nic *efx,
- efx_dword_t *value, unsigned int mac_reg)
-{
- efx_oword_t temp;
-
- falcon_read(efx, &temp, FALCON_XMAC_REG(mac_reg));
- EFX_POPULATE_DWORD_1(*value, MAC_DATA, EFX_OWORD_FIELD(temp, MAC_DATA));
-}
-
-/**************************************************************************
- *
* MAC operations
*
*************************************************************************/
static int falcon_reset_xmac(struct efx_nic *efx)
{
- efx_dword_t reg;
+ efx_oword_t reg;
int count;
- EFX_POPULATE_DWORD_1(reg, XM_CORE_RST, 1);
- falcon_xmac_writel(efx, &reg, XM_GLB_CFG_REG_MAC);
+ EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
+ falcon_write(efx, &reg, XM_GLB_CFG_REG);
for (count = 0; count < 10000; count++) { /* wait upto 100ms */
- falcon_xmac_readl(efx, &reg, XM_GLB_CFG_REG_MAC);
- if (EFX_DWORD_FIELD(reg, XM_CORE_RST) == 0)
+ falcon_read(efx, &reg, XM_GLB_CFG_REG);
+ if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
return 0;
udelay(10);
}
- /* This often fails when DSP is disabled, ignore it */
- if (sfe4001_phy_flash_cfg != 0)
- return 0;
-
EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
return -ETIMEDOUT;
}
@@ -80,25 +48,25 @@ static int falcon_reset_xmac(struct efx_nic *efx)
/* Configure the XAUI driver that is an output from Falcon */
static void falcon_setup_xaui(struct efx_nic *efx)
{
- efx_dword_t sdctl, txdrv;
+ efx_oword_t sdctl, txdrv;
/* Move the XAUI into low power, unless there is no PHY, in
* which case the XAUI will have to drive a cable. */
if (efx->phy_type == PHY_TYPE_NONE)
return;
- falcon_xmac_readl(efx, &sdctl, XX_SD_CTL_REG_MAC);
- EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT);
- EFX_SET_DWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT);
- falcon_xmac_writel(efx, &sdctl, XX_SD_CTL_REG_MAC);
-
- EFX_POPULATE_DWORD_8(txdrv,
+ falcon_read(efx, &sdctl, XX_SD_CTL_REG);
+ EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT);
+ EFX_SET_OWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT);
+ falcon_write(efx, &sdctl, XX_SD_CTL_REG);
+
+ EFX_POPULATE_OWORD_8(txdrv,
XX_DEQD, XX_TXDRV_DEQ_DEFAULT,
XX_DEQC, XX_TXDRV_DEQ_DEFAULT,
XX_DEQB, XX_TXDRV_DEQ_DEFAULT,
@@ -107,93 +75,21 @@ static void falcon_setup_xaui(struct efx_nic *efx)
XX_DTXC, XX_TXDRV_DTX_DEFAULT,
XX_DTXB, XX_TXDRV_DTX_DEFAULT,
XX_DTXA, XX_TXDRV_DTX_DEFAULT);
- falcon_xmac_writel(efx, &txdrv, XX_TXDRV_CTL_REG_MAC);
+ falcon_write(efx, &txdrv, XX_TXDRV_CTL_REG);
}
-static void falcon_hold_xaui_in_rst(struct efx_nic *efx)
-{
- efx_dword_t reg;
-
- EFX_ZERO_DWORD(reg);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-}
-
-static int _falcon_reset_xaui_a(struct efx_nic *efx)
-{
- efx_dword_t reg;
-
- falcon_hold_xaui_in_rst(efx);
- falcon_xmac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
-
- /* Follow the RAMBUS XAUI data reset sequencing
- * Channels A and B first: power down, reset PLL, reset, clear
- */
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNA_EN, 0);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNB_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- EFX_SET_DWORD_FIELD(reg, XX_RSTPLLAB_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- EFX_SET_DWORD_FIELD(reg, XX_RESETA_EN, 0);
- EFX_SET_DWORD_FIELD(reg, XX_RESETB_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- /* Channels C and D: power down, reset PLL, reset, clear */
- EFX_SET_DWORD_FIELD(reg, XX_PWRDNC_EN, 0);
- EFX_SET_DWORD_FIELD(reg, XX_PWRDND_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- EFX_SET_DWORD_FIELD(reg, XX_RSTPLLCD_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- EFX_SET_DWORD_FIELD(reg, XX_RESETC_EN, 0);
- EFX_SET_DWORD_FIELD(reg, XX_RESETD_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- /* Setup XAUI */
- falcon_setup_xaui(efx);
- udelay(10);
-
- /* Take XGXS out of reset */
- EFX_ZERO_DWORD(reg);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- return 0;
-}
-
-static int _falcon_reset_xaui_b(struct efx_nic *efx)
+int falcon_reset_xaui(struct efx_nic *efx)
{
- efx_dword_t reg;
+ efx_oword_t reg;
int count;
EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
+ falcon_write(efx, &reg, XX_PWR_RST_REG);
/* Give some time for the link to establish */
for (count = 0; count < 1000; count++) { /* wait upto 10ms */
- falcon_xmac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
- if (EFX_DWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
+ falcon_read(efx, &reg, XX_PWR_RST_REG);
+ if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
falcon_setup_xaui(efx);
return 0;
}
@@ -203,55 +99,41 @@ static int _falcon_reset_xaui_b(struct efx_nic *efx)
return -ETIMEDOUT;
}
-int falcon_reset_xaui(struct efx_nic *efx)
+static bool falcon_xgmii_status(struct efx_nic *efx)
{
- int rc;
-
- if (EFX_WORKAROUND_9388(efx)) {
- falcon_hold_xaui_in_rst(efx);
- efx->phy_op->reset_xaui(efx);
- rc = _falcon_reset_xaui_a(efx);
- } else {
- rc = _falcon_reset_xaui_b(efx);
- }
- return rc;
-}
-
-static int falcon_xgmii_status(struct efx_nic *efx)
-{
- efx_dword_t reg;
+ efx_oword_t reg;
if (falcon_rev(efx) < FALCON_REV_B0)
- return 1;
+ return true;
/* The ISR latches, so clear it and re-read */
- falcon_xmac_readl(efx, &reg, XM_MGT_INT_REG_MAC_B0);
- falcon_xmac_readl(efx, &reg, XM_MGT_INT_REG_MAC_B0);
+ falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
+ falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
- if (EFX_DWORD_FIELD(reg, XM_LCLFLT) ||
- EFX_DWORD_FIELD(reg, XM_RMTFLT)) {
+ if (EFX_OWORD_FIELD(reg, XM_LCLFLT) ||
+ EFX_OWORD_FIELD(reg, XM_RMTFLT)) {
EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg));
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static void falcon_mask_status_intr(struct efx_nic *efx, int enable)
+static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
{
- efx_dword_t reg;
+ efx_oword_t reg;
if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
return;
/* Flush the ISR */
if (enable)
- falcon_xmac_readl(efx, &reg, XM_MGT_INT_REG_MAC_B0);
+ falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
- EFX_POPULATE_DWORD_2(reg,
+ EFX_POPULATE_OWORD_2(reg,
XM_MSK_RMTFLT, !enable,
XM_MSK_LCLFLT, !enable);
- falcon_xmac_writel(efx, &reg, XM_MGT_INT_MSK_REG_MAC_B0);
+ falcon_write(efx, &reg, XM_MGT_INT_MSK_REG_B0);
}
int falcon_init_xmac(struct efx_nic *efx)
@@ -274,7 +156,7 @@ int falcon_init_xmac(struct efx_nic *efx)
if (rc)
goto fail2;
- falcon_mask_status_intr(efx, 1);
+ falcon_mask_status_intr(efx, true);
return 0;
fail2:
@@ -283,34 +165,34 @@ int falcon_init_xmac(struct efx_nic *efx)
return rc;
}
-int falcon_xaui_link_ok(struct efx_nic *efx)
+bool falcon_xaui_link_ok(struct efx_nic *efx)
{
- efx_dword_t reg;
- int align_done, sync_status, link_ok = 0;
+ efx_oword_t reg;
+ bool align_done, link_ok = false;
+ int sync_status;
if (LOOPBACK_INTERNAL(efx))
- return 1;
+ return true;
/* Read link status */
- falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
+ falcon_read(efx, &reg, XX_CORE_STAT_REG);
- align_done = EFX_DWORD_FIELD(reg, XX_ALIGN_DONE);
- sync_status = EFX_DWORD_FIELD(reg, XX_SYNC_STAT);
+ align_done = EFX_OWORD_FIELD(reg, XX_ALIGN_DONE);
+ sync_status = EFX_OWORD_FIELD(reg, XX_SYNC_STAT);
if (align_done && (sync_status == XX_SYNC_STAT_DECODE_SYNCED))
- link_ok = 1;
+ link_ok = true;
/* Clear link status ready for next read */
- EFX_SET_DWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET);
- EFX_SET_DWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET);
- EFX_SET_DWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
- falcon_xmac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
+ EFX_SET_OWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET);
+ EFX_SET_OWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET);
+ EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
+ falcon_write(efx, &reg, XX_CORE_STAT_REG);
/* If the link is up, then check the phy side of the xaui link
* (error conditions from the wire side propoagate back through
* the phy to the xaui side). */
if (efx->link_up && link_ok) {
- int has_phyxs = efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS);
- if (has_phyxs)
+ if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
link_ok = mdio_clause45_phyxgxs_lane_sync(efx);
}
@@ -325,15 +207,15 @@ int falcon_xaui_link_ok(struct efx_nic *efx)
static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
unsigned int max_frame_len;
- efx_dword_t reg;
- int rx_fc = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
+ efx_oword_t reg;
+ bool rx_fc = !!(efx->flow_control & EFX_FC_RX);
/* Configure MAC - cut-thru mode is hard wired on */
EFX_POPULATE_DWORD_3(reg,
XM_RX_JUMBO_MODE, 1,
XM_TX_STAT_EN, 1,
XM_RX_STAT_EN, 1);
- falcon_xmac_writel(efx, &reg, XM_GLB_CFG_REG_MAC);
+ falcon_write(efx, &reg, XM_GLB_CFG_REG);
/* Configure TX */
EFX_POPULATE_DWORD_6(reg,
@@ -343,7 +225,7 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
XM_TXCRC, 1,
XM_FCNTL, 1,
XM_IPG, 0x3);
- falcon_xmac_writel(efx, &reg, XM_TX_CFG_REG_MAC);
+ falcon_write(efx, &reg, XM_TX_CFG_REG);
/* Configure RX */
EFX_POPULATE_DWORD_5(reg,
@@ -352,21 +234,21 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
XM_ACPT_ALL_MCAST, 1,
XM_ACPT_ALL_UCAST, efx->promiscuous,
XM_PASS_CRC_ERR, 1);
- falcon_xmac_writel(efx, &reg, XM_RX_CFG_REG_MAC);
+ falcon_write(efx, &reg, XM_RX_CFG_REG);
/* Set frame length */
max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len);
- falcon_xmac_writel(efx, &reg, XM_RX_PARAM_REG_MAC);
+ falcon_write(efx, &reg, XM_RX_PARAM_REG);
EFX_POPULATE_DWORD_2(reg,
XM_MAX_TX_FRM_SIZE, max_frame_len,
XM_TX_JUMBO_MODE, 1);
- falcon_xmac_writel(efx, &reg, XM_TX_PARAM_REG_MAC);
+ falcon_write(efx, &reg, XM_TX_PARAM_REG);
EFX_POPULATE_DWORD_2(reg,
XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
- XM_DIS_FCNTL, rx_fc ? 0 : 1);
- falcon_xmac_writel(efx, &reg, XM_FC_REG_MAC);
+ XM_DIS_FCNTL, !rx_fc);
+ falcon_write(efx, &reg, XM_FC_REG);
/* Set MAC address */
EFX_POPULATE_DWORD_4(reg,
@@ -374,83 +256,75 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
XM_ADR_1, efx->net_dev->dev_addr[1],
XM_ADR_2, efx->net_dev->dev_addr[2],
XM_ADR_3, efx->net_dev->dev_addr[3]);
- falcon_xmac_writel(efx, &reg, XM_ADR_LO_REG_MAC);
+ falcon_write(efx, &reg, XM_ADR_LO_REG);
EFX_POPULATE_DWORD_2(reg,
XM_ADR_4, efx->net_dev->dev_addr[4],
XM_ADR_5, efx->net_dev->dev_addr[5]);
- falcon_xmac_writel(efx, &reg, XM_ADR_HI_REG_MAC);
+ falcon_write(efx, &reg, XM_ADR_HI_REG);
}
static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
{
- efx_dword_t reg;
- int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0;
- int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0;
- int xgmii_loopback =
- (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0;
+ efx_oword_t reg;
+ bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS);
+ bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI);
+ bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII);
/* XGXS block is flaky and will need to be reset if moving
* into our out of XGMII, XGXS or XAUI loopbacks. */
if (EFX_WORKAROUND_5147(efx)) {
- int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
- int reset_xgxs;
+ bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
+ bool reset_xgxs;
- falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
- old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN);
- old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN);
+ falcon_read(efx, &reg, XX_CORE_STAT_REG);
+ old_xgxs_loopback = EFX_OWORD_FIELD(reg, XX_XGXS_LB_EN);
+ old_xgmii_loopback = EFX_OWORD_FIELD(reg, XX_XGMII_LB_EN);
- falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
- old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA);
+ falcon_read(efx, &reg, XX_SD_CTL_REG);
+ old_xaui_loopback = EFX_OWORD_FIELD(reg, XX_LPBKA);
/* The PHY driver may have turned XAUI off */
reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
(xaui_loopback != old_xaui_loopback) ||
(xgmii_loopback != old_xgmii_loopback));
- if (reset_xgxs) {
- falcon_xmac_readl(efx, &reg, XX_PWR_RST_REG_MAC);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(1);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0);
- EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(1);
- }
+
+ if (reset_xgxs)
+ falcon_reset_xaui(efx);
}
- falcon_xmac_readl(efx, &reg, XX_CORE_STAT_REG_MAC);
- EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG,
+ falcon_read(efx, &reg, XX_CORE_STAT_REG);
+ EFX_SET_OWORD_FIELD(reg, XX_FORCE_SIG,
(xgxs_loopback || xaui_loopback) ?
XX_FORCE_SIG_DECODE_FORCED : 0);
- EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
- EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
- falcon_xmac_writel(efx, &reg, XX_CORE_STAT_REG_MAC);
-
- falcon_xmac_readl(efx, &reg, XX_SD_CTL_REG_MAC);
- EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
- EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
- EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
- EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
- falcon_xmac_writel(efx, &reg, XX_SD_CTL_REG_MAC);
+ EFX_SET_OWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
+ EFX_SET_OWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
+ falcon_write(efx, &reg, XX_CORE_STAT_REG);
+
+ falcon_read(efx, &reg, XX_SD_CTL_REG);
+ EFX_SET_OWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
+ EFX_SET_OWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
+ EFX_SET_OWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
+ EFX_SET_OWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
+ falcon_write(efx, &reg, XX_SD_CTL_REG);
}
/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
* to come back up. Bash it until it comes back up */
-static int falcon_check_xaui_link_up(struct efx_nic *efx)
+static bool falcon_check_xaui_link_up(struct efx_nic *efx)
{
int max_tries, tries;
tries = EFX_WORKAROUND_5147(efx) ? 5 : 1;
max_tries = tries;
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
- (efx->phy_type == PHY_TYPE_NONE))
- return 0;
+ (efx->phy_type == PHY_TYPE_NONE) ||
+ efx_phy_mode_disabled(efx->phy_mode))
+ return false;
while (tries) {
if (falcon_xaui_link_ok(efx))
- return 1;
+ return true;
EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
__func__, tries);
@@ -461,18 +335,22 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx)
EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n",
max_tries);
- return 0;
+ return false;
}
void falcon_reconfigure_xmac(struct efx_nic *efx)
{
- int xaui_link_ok;
+ bool xaui_link_ok;
- falcon_mask_status_intr(efx, 0);
+ falcon_mask_status_intr(efx, false);
falcon_deconfigure_mac_wrapper(efx);
- efx->tx_disabled = LOOPBACK_INTERNAL(efx);
+ /* Reconfigure the PHY, disabling transmit in mac level loopback. */
+ if (LOOPBACK_INTERNAL(efx))
+ efx->phy_mode |= PHY_MODE_TX_DISABLED;
+ else
+ efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
efx->phy_op->reconfigure(efx);
falcon_reconfigure_xgxs_core(efx);
@@ -484,7 +362,7 @@ void falcon_reconfigure_xmac(struct efx_nic *efx)
xaui_link_ok = falcon_check_xaui_link_up(efx);
if (xaui_link_ok && efx->link_up)
- falcon_mask_status_intr(efx, 1);
+ falcon_mask_status_intr(efx, true);
}
void falcon_fini_xmac(struct efx_nic *efx)
@@ -554,21 +432,23 @@ void falcon_update_stats_xmac(struct efx_nic *efx)
/* Update derived statistics */
mac_stats->tx_good_bytes =
- (mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
+ (mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
+ mac_stats->tx_control * 64);
mac_stats->rx_bad_bytes =
- (mac_stats->rx_bytes - mac_stats->rx_good_bytes);
+ (mac_stats->rx_bytes - mac_stats->rx_good_bytes -
+ mac_stats->rx_control * 64);
}
int falcon_check_xmac(struct efx_nic *efx)
{
- unsigned xaui_link_ok;
+ bool xaui_link_ok;
int rc;
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
- (efx->phy_type == PHY_TYPE_NONE))
+ efx_phy_mode_disabled(efx->phy_mode))
return 0;
- falcon_mask_status_intr(efx, 0);
+ falcon_mask_status_intr(efx, false);
xaui_link_ok = falcon_xaui_link_ok(efx);
if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
@@ -579,7 +459,7 @@ int falcon_check_xmac(struct efx_nic *efx)
/* Unmask interrupt if everything was (and still is) ok */
if (xaui_link_ok && efx->link_up)
- falcon_mask_status_intr(efx, 1);
+ falcon_mask_status_intr(efx, true);
return rc;
}
@@ -620,7 +500,7 @@ int falcon_xmac_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control)
{
- int reset;
+ bool reset;
if (flow_control & EFX_FC_AUTO) {
EFX_LOG(efx, "10G does not support flow control "
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
index edd07d4dee1..a31571c6913 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/sfc/mac.h
@@ -13,10 +13,6 @@
#include "net_driver.h"
-extern void falcon_xmac_writel(struct efx_nic *efx,
- efx_dword_t *value, unsigned int mac_reg);
-extern void falcon_xmac_readl(struct efx_nic *efx,
- efx_dword_t *value, unsigned int mac_reg);
extern int falcon_init_xmac(struct efx_nic *efx);
extern void falcon_reconfigure_xmac(struct efx_nic *efx);
extern void falcon_update_stats_xmac(struct efx_nic *efx);
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index c4f540e93b7..003e48dcb2f 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -159,20 +159,21 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
return 0;
}
-int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
+bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
{
int phy_id = efx->mii.phy_id;
int status;
- int ok = 1;
+ bool ok = true;
int mmd = 0;
- int good;
/* If the port is in loopback, then we should only consider a subset
* of mmd's */
if (LOOPBACK_INTERNAL(efx))
- return 1;
+ return true;
else if (efx->loopback_mode == LOOPBACK_NETWORK)
- return 0;
+ return false;
+ else if (efx_phy_mode_disabled(efx->phy_mode))
+ return false;
else if (efx->loopback_mode == LOOPBACK_PHYXS)
mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS |
MDIO_MMDREG_DEVS0_PCS |
@@ -192,8 +193,7 @@ int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
status = mdio_clause45_read(efx, phy_id,
mmd, MDIO_MMDREG_STAT1);
- good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
- ok = ok && good;
+ ok = ok && (status & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
}
mmd_mask = (mmd_mask >> 1);
mmd++;
@@ -208,7 +208,7 @@ void mdio_clause45_transmit_disable(struct efx_nic *efx)
ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
MDIO_MMDREG_TXDIS);
- if (efx->tx_disabled)
+ if (efx->phy_mode & PHY_MODE_TX_DISABLED)
ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
else
ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index cb99f3f4491..19c42eaf7fb 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -199,18 +199,19 @@ static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd)
return (id_hi << 16) | (id_low);
}
-static inline int mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx)
+static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx)
{
- int i, sync, lane_status;
+ int i, lane_status;
+ bool sync;
for (i = 0; i < 2; ++i)
lane_status = mdio_clause45_read(efx, efx->mii.phy_id,
MDIO_MMD_PHYXS,
MDIO_PHYXS_LANE_STATE);
- sync = (lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)) != 0;
+ sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN));
if (!sync)
- EFX_INFO(efx, "XGXS lane status: %x\n", lane_status);
+ EFX_LOG(efx, "XGXS lane status: %x\n", lane_status);
return sync;
}
@@ -230,8 +231,8 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
unsigned int mmd_mask, unsigned int fatal_mask);
/* Check the link status of specified mmds in bit mask */
-extern int mdio_clause45_links_ok(struct efx_nic *efx,
- unsigned int mmd_mask);
+extern bool mdio_clause45_links_ok(struct efx_nic *efx,
+ unsigned int mmd_mask);
/* Generic transmit disable support though PMAPMD */
extern void mdio_clause45_transmit_disable(struct efx_nic *efx);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 219c74a772c..cdb11fad605 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -88,9 +88,12 @@ do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0)
**************************************************************************/
#define EFX_MAX_CHANNELS 32
-#define EFX_MAX_TX_QUEUES 1
#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
+#define EFX_TX_QUEUE_OFFLOAD_CSUM 0
+#define EFX_TX_QUEUE_NO_CSUM 1
+#define EFX_TX_QUEUE_COUNT 2
+
/**
* struct efx_special_buffer - An Efx special buffer
* @addr: CPU base address of the buffer
@@ -127,7 +130,6 @@ struct efx_special_buffer {
* This field is zero when the queue slot is empty.
* @continuation: True if this fragment is not the end of a packet.
* @unmap_single: True if pci_unmap_single should be used.
- * @unmap_addr: DMA address to unmap
* @unmap_len: Length of this fragment to unmap
*/
struct efx_tx_buffer {
@@ -135,9 +137,8 @@ struct efx_tx_buffer {
struct efx_tso_header *tsoh;
dma_addr_t dma_addr;
unsigned short len;
- unsigned char continuation;
- unsigned char unmap_single;
- dma_addr_t unmap_addr;
+ bool continuation;
+ bool unmap_single;
unsigned short unmap_len;
};
@@ -156,13 +157,13 @@ struct efx_tx_buffer {
*
* @efx: The associated Efx NIC
* @queue: DMA queue number
- * @used: Queue is used by net driver
* @channel: The associated channel
* @buffer: The software buffer ring
* @txd: The hardware descriptor ring
+ * @flushed: Used when handling queue flushing
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
- * @stopped: Stopped flag.
+ * @stopped: Stopped count.
* Set if this TX queue is currently stopping its port.
* @insert_count: Current insert pointer
* This is the number of buffers that have been added to the
@@ -188,11 +189,11 @@ struct efx_tx_queue {
/* Members which don't change on the fast path */
struct efx_nic *efx ____cacheline_aligned_in_smp;
int queue;
- int used;
struct efx_channel *channel;
struct efx_nic *nic;
struct efx_tx_buffer *buffer;
struct efx_special_buffer txd;
+ bool flushed;
/* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp;
@@ -232,7 +233,6 @@ struct efx_rx_buffer {
* struct efx_rx_queue - An Efx RX queue
* @efx: The associated Efx NIC
* @queue: DMA queue number
- * @used: Queue is used by net driver
* @channel: The associated channel
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
@@ -262,11 +262,11 @@ struct efx_rx_buffer {
* the remaining space in the allocation.
* @buf_dma_addr: Page's DMA address.
* @buf_data: Page's host address.
+ * @flushed: Use when handling queue flushing
*/
struct efx_rx_queue {
struct efx_nic *efx;
int queue;
- int used;
struct efx_channel *channel;
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
@@ -288,6 +288,7 @@ struct efx_rx_queue {
struct page *buf_page;
dma_addr_t buf_dma_addr;
char *buf_data;
+ bool flushed;
};
/**
@@ -325,12 +326,10 @@ enum efx_rx_alloc_method {
* queue.
*
* @efx: Associated Efx NIC
- * @evqnum: Event queue number
* @channel: Channel instance number
* @used_flags: Channel is used by net driver
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
- * @has_interrupt: Channel has an interrupt
* @irq_moderation: IRQ moderation value (in us)
* @napi_dev: Net device used with NAPI
* @napi_str: NAPI control structure
@@ -357,17 +356,14 @@ enum efx_rx_alloc_method {
*/
struct efx_channel {
struct efx_nic *efx;
- int evqnum;
int channel;
int used_flags;
- int enabled;
+ bool enabled;
int irq;
- unsigned int has_interrupt;
unsigned int irq_moderation;
struct net_device *napi_dev;
struct napi_struct napi_str;
- struct work_struct reset_work;
- int work_pending;
+ bool work_pending;
struct efx_special_buffer eventq;
unsigned int eventq_read_ptr;
unsigned int last_eventq_read_ptr;
@@ -390,7 +386,7 @@ struct efx_channel {
* access with prefetches.
*/
struct efx_rx_buffer *rx_pkt;
- int rx_pkt_csummed;
+ bool rx_pkt_csummed;
};
@@ -403,8 +399,8 @@ struct efx_channel {
*/
struct efx_blinker {
int led_num;
- int state;
- int resubmit;
+ bool state;
+ bool resubmit;
struct timer_list timer;
};
@@ -432,8 +428,8 @@ struct efx_board {
* have a separate init callback that happens later than
* board init. */
int (*init_leds)(struct efx_nic *efx);
- void (*set_fault_led) (struct efx_nic *efx, int state);
- void (*blink) (struct efx_nic *efx, int start);
+ void (*set_fault_led) (struct efx_nic *efx, bool state);
+ void (*blink) (struct efx_nic *efx, bool start);
void (*fini) (struct efx_nic *nic);
struct efx_blinker blinker;
struct i2c_client *hwmon_client, *ioexp_client;
@@ -467,8 +463,7 @@ enum nic_state {
STATE_INIT = 0,
STATE_RUNNING = 1,
STATE_FINI = 2,
- STATE_RESETTING = 3, /* rtnl_lock always held */
- STATE_DISABLED = 4,
+ STATE_DISABLED = 3,
STATE_MAX,
};
@@ -479,7 +474,7 @@ enum nic_state {
* This is the equivalent of NET_IP_ALIGN [which controls the alignment
* of the skb->head for hardware DMA].
*/
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
#define EFX_PAGE_IP_ALIGN 0
#else
#define EFX_PAGE_IP_ALIGN NET_IP_ALIGN
@@ -512,7 +507,6 @@ enum efx_fc_type {
* @clear_interrupt: Clear down interrupt
* @blink: Blink LEDs
* @check_hw: Check hardware
- * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset)
* @mmds: MMD presence mask
* @loopbacks: Supported loopback modes mask
*/
@@ -522,11 +516,28 @@ struct efx_phy_operations {
void (*reconfigure) (struct efx_nic *efx);
void (*clear_interrupt) (struct efx_nic *efx);
int (*check_hw) (struct efx_nic *efx);
- void (*reset_xaui) (struct efx_nic *efx);
+ int (*test) (struct efx_nic *efx);
int mmds;
unsigned loopbacks;
};
+/**
+ * @enum efx_phy_mode - PHY operating mode flags
+ * @PHY_MODE_NORMAL: on and should pass traffic
+ * @PHY_MODE_TX_DISABLED: on with TX disabled
+ * @PHY_MODE_SPECIAL: on but will not pass traffic
+ */
+enum efx_phy_mode {
+ PHY_MODE_NORMAL = 0,
+ PHY_MODE_TX_DISABLED = 1,
+ PHY_MODE_SPECIAL = 8,
+};
+
+static inline bool efx_phy_mode_disabled(enum efx_phy_mode mode)
+{
+ return !!(mode & ~PHY_MODE_TX_DISABLED);
+}
+
/*
* Efx extended statistics
*
@@ -632,7 +643,7 @@ union efx_multicast_hash {
* @tx_queue: TX DMA queues
* @rx_queue: RX DMA queues
* @channel: Channels
- * @rss_queues: Number of RSS queues
+ * @n_rx_queues: Number of RX queues
* @rx_buffer_len: RX buffer length
* @rx_buffer_order: Order (log2) of number of pages for each RX buffer
* @irq_status: Interrupt status buffer
@@ -640,15 +651,20 @@ union efx_multicast_hash {
* This register is written with the SMP processor ID whenever an
* interrupt is handled. It is used by falcon_test_interrupt()
* to verify that an interrupt has occurred.
+ * @spi_flash: SPI flash device
+ * This field will be %NULL if no flash device is present.
+ * @spi_eeprom: SPI EEPROM device
+ * This field will be %NULL if no EEPROM device is present.
* @n_rx_nodesc_drop_cnt: RX no descriptor drop count
* @nic_data: Hardware dependant state
- * @mac_lock: MAC access lock. Protects @port_enabled, efx_monitor() and
- * efx_reconfigure_port()
+ * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
+ * @port_inhibited, efx_monitor() and efx_reconfigure_port()
* @port_enabled: Port enabled indicator.
* Serialises efx_stop_all(), efx_start_all() and efx_monitor() and
* efx_reconfigure_work with kernel interfaces. Safe to read under any
* one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
* be held to modify it.
+ * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
* @port_initialized: Port initialized?
* @net_dev: Operating system network device. Consider holding the rtnl lock
* @rx_checksum_enabled: RX checksumming enabled
@@ -658,14 +674,16 @@ union efx_multicast_hash {
* can provide. Generic code converts these into a standard
* &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics
- * @stats_lock: Statistics update lock
+ * @stats_lock: Statistics update lock. Serialises statistics fetches
+ * @stats_enabled: Temporarily disable statistics fetches.
+ * Serialised by @stats_lock
* @mac_address: Permanent MAC address
* @phy_type: PHY type
* @phy_lock: PHY access lock
* @phy_op: PHY interface
* @phy_data: PHY private data (including PHY-specific stats)
* @mii: PHY interface
- * @tx_disabled: PHY transmitter turned off
+ * @phy_mode: PHY operating mode. Serialised by @mac_lock.
* @link_up: Link status
* @link_options: Link options (MII/GMII format)
* @n_link_state_changes: Number of times the link has changed state
@@ -700,27 +718,31 @@ struct efx_nic {
enum nic_state state;
enum reset_type reset_pending;
- struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
+ struct efx_tx_queue tx_queue[EFX_TX_QUEUE_COUNT];
struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
struct efx_channel channel[EFX_MAX_CHANNELS];
- int rss_queues;
+ int n_rx_queues;
unsigned int rx_buffer_len;
unsigned int rx_buffer_order;
struct efx_buffer irq_status;
volatile signed int last_irq_cpu;
+ struct efx_spi_device *spi_flash;
+ struct efx_spi_device *spi_eeprom;
+
unsigned n_rx_nodesc_drop_cnt;
struct falcon_nic_data *nic_data;
struct mutex mac_lock;
- int port_enabled;
+ bool port_enabled;
+ bool port_inhibited;
- int port_initialized;
+ bool port_initialized;
struct net_device *net_dev;
- int rx_checksum_enabled;
+ bool rx_checksum_enabled;
atomic_t netif_stop_count;
spinlock_t netif_stop_lock;
@@ -728,6 +750,7 @@ struct efx_nic {
struct efx_mac_stats mac_stats;
struct efx_buffer stats_buffer;
spinlock_t stats_lock;
+ bool stats_enabled;
unsigned char mac_address[ETH_ALEN];
@@ -736,13 +759,13 @@ struct efx_nic {
struct efx_phy_operations *phy_op;
void *phy_data;
struct mii_if_info mii;
- unsigned tx_disabled;
+ enum efx_phy_mode phy_mode;
- int link_up;
+ bool link_up;
unsigned int link_options;
unsigned int n_link_state_changes;
- int promiscuous;
+ bool promiscuous;
union efx_multicast_hash multicast_hash;
enum efx_fc_type flow_control;
struct work_struct reconfigure_work;
@@ -829,50 +852,33 @@ struct efx_nic_type {
continue; \
else
-/* Iterate over all used channels with interrupts */
-#define efx_for_each_channel_with_interrupt(_channel, _efx) \
- for (_channel = &_efx->channel[0]; \
- _channel < &_efx->channel[EFX_MAX_CHANNELS]; \
- _channel++) \
- if (!(_channel->used_flags && _channel->has_interrupt)) \
- continue; \
- else
-
/* Iterate over all used TX queues */
#define efx_for_each_tx_queue(_tx_queue, _efx) \
for (_tx_queue = &_efx->tx_queue[0]; \
- _tx_queue < &_efx->tx_queue[EFX_MAX_TX_QUEUES]; \
- _tx_queue++) \
- if (!_tx_queue->used) \
- continue; \
- else
+ _tx_queue < &_efx->tx_queue[EFX_TX_QUEUE_COUNT]; \
+ _tx_queue++)
/* Iterate over all TX queues belonging to a channel */
#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
for (_tx_queue = &_channel->efx->tx_queue[0]; \
- _tx_queue < &_channel->efx->tx_queue[EFX_MAX_TX_QUEUES]; \
+ _tx_queue < &_channel->efx->tx_queue[EFX_TX_QUEUE_COUNT]; \
_tx_queue++) \
- if ((!_tx_queue->used) || \
- (_tx_queue->channel != _channel)) \
+ if (_tx_queue->channel != _channel) \
continue; \
else
/* Iterate over all used RX queues */
#define efx_for_each_rx_queue(_rx_queue, _efx) \
for (_rx_queue = &_efx->rx_queue[0]; \
- _rx_queue < &_efx->rx_queue[EFX_MAX_RX_QUEUES]; \
- _rx_queue++) \
- if (!_rx_queue->used) \
- continue; \
- else
+ _rx_queue < &_efx->rx_queue[_efx->n_rx_queues]; \
+ _rx_queue++)
/* Iterate over all RX queues belonging to a channel */
#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \
- for (_rx_queue = &_channel->efx->rx_queue[0]; \
- _rx_queue < &_channel->efx->rx_queue[EFX_MAX_RX_QUEUES]; \
- _rx_queue++) \
- if ((!_rx_queue->used) || \
- (_rx_queue->channel != _channel)) \
+ for (_rx_queue = &_channel->efx->rx_queue[_channel->channel]; \
+ _rx_queue; \
+ _rx_queue = NULL) \
+ if (_rx_queue->channel != _channel) \
continue; \
else
@@ -886,13 +892,13 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
}
/* Set bit in a little-endian bitfield */
-static inline void set_bit_le(int nr, unsigned char *addr)
+static inline void set_bit_le(unsigned nr, unsigned char *addr)
{
addr[nr / 8] |= (1 << (nr % 8));
}
/* Clear bit in a little-endian bitfield */
-static inline void clear_bit_le(int nr, unsigned char *addr)
+static inline void clear_bit_le(unsigned nr, unsigned char *addr)
{
addr[nr / 8] &= ~(1 << (nr % 8));
}
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 9d02c84e6b2..f746536f4ff 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -15,15 +15,7 @@
*/
extern struct efx_phy_operations falcon_tenxpress_phy_ops;
-enum tenxpress_state {
- TENXPRESS_STATUS_OFF = 0,
- TENXPRESS_STATUS_OTEMP = 1,
- TENXPRESS_STATUS_NORMAL = 2,
-};
-
-extern void tenxpress_set_state(struct efx_nic *efx,
- enum tenxpress_state state);
-extern void tenxpress_phy_blink(struct efx_nic *efx, int blink);
+extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
extern void tenxpress_crc_err(struct efx_nic *efx);
/****************************************************************************
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 0d27dd39bc0..0f805da4ce5 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -212,8 +212,8 @@ void efx_lro_fini(struct net_lro_mgr *lro_mgr)
* and populates a struct efx_rx_buffer with the relevant
* information. Return a negative error code or 0 on success.
*/
-static inline int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf)
+static int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf)
{
struct efx_nic *efx = rx_queue->efx;
struct net_device *net_dev = efx->net_dev;
@@ -252,8 +252,8 @@ static inline int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
* and populates a struct efx_rx_buffer with the relevant
* information. Return a negative error code or 0 on success.
*/
-static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf)
+static int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf)
{
struct efx_nic *efx = rx_queue->efx;
int bytes, space, offset;
@@ -319,8 +319,8 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
* and populates a struct efx_rx_buffer with the relevant
* information.
*/
-static inline int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *new_rx_buf)
+static int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *new_rx_buf)
{
int rc = 0;
@@ -340,8 +340,8 @@ static inline int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
return rc;
}
-static inline void efx_unmap_rx_buffer(struct efx_nic *efx,
- struct efx_rx_buffer *rx_buf)
+static void efx_unmap_rx_buffer(struct efx_nic *efx,
+ struct efx_rx_buffer *rx_buf)
{
if (rx_buf->page) {
EFX_BUG_ON_PARANOID(rx_buf->skb);
@@ -357,8 +357,8 @@ static inline void efx_unmap_rx_buffer(struct efx_nic *efx,
}
}
-static inline void efx_free_rx_buffer(struct efx_nic *efx,
- struct efx_rx_buffer *rx_buf)
+static void efx_free_rx_buffer(struct efx_nic *efx,
+ struct efx_rx_buffer *rx_buf)
{
if (rx_buf->page) {
__free_pages(rx_buf->page, efx->rx_buffer_order);
@@ -369,8 +369,8 @@ static inline void efx_free_rx_buffer(struct efx_nic *efx,
}
}
-static inline void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf)
+static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf)
{
efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
efx_free_rx_buffer(rx_queue->efx, rx_buf);
@@ -506,10 +506,10 @@ void efx_rx_work(struct work_struct *data)
efx_schedule_slow_fill(rx_queue, 1);
}
-static inline void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf,
- int len, int *discard,
- int *leak_packet)
+static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf,
+ int len, bool *discard,
+ bool *leak_packet)
{
struct efx_nic *efx = rx_queue->efx;
unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
@@ -520,7 +520,7 @@ static inline void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
/* The packet must be discarded, but this is only a fatal error
* if the caller indicated it was
*/
- *discard = 1;
+ *discard = true;
if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
EFX_ERR_RL(efx, " RX queue %d seriously overlength "
@@ -546,8 +546,8 @@ static inline void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
* Handles driverlink veto, and passes the fragment up via
* the appropriate LRO method
*/
-static inline void efx_rx_packet_lro(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf)
+static void efx_rx_packet_lro(struct efx_channel *channel,
+ struct efx_rx_buffer *rx_buf)
{
struct net_lro_mgr *lro_mgr = &channel->lro_mgr;
void *priv = channel;
@@ -574,9 +574,9 @@ static inline void efx_rx_packet_lro(struct efx_channel *channel,
}
/* Allocate and construct an SKB around a struct page.*/
-static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
- struct efx_nic *efx,
- int hdr_len)
+static struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
+ struct efx_nic *efx,
+ int hdr_len)
{
struct sk_buff *skb;
@@ -621,11 +621,11 @@ static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf,
}
void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
- unsigned int len, int checksummed, int discard)
+ unsigned int len, bool checksummed, bool discard)
{
struct efx_nic *efx = rx_queue->efx;
struct efx_rx_buffer *rx_buf;
- int leak_packet = 0;
+ bool leak_packet = false;
rx_buf = efx_rx_buffer(rx_queue, index);
EFX_BUG_ON_PARANOID(!rx_buf->data);
@@ -683,11 +683,11 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
/* Handle a received packet. Second half: Touches packet payload. */
void __efx_rx_packet(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf, int checksummed)
+ struct efx_rx_buffer *rx_buf, bool checksummed)
{
struct efx_nic *efx = channel->efx;
struct sk_buff *skb;
- int lro = efx->net_dev->features & NETIF_F_LRO;
+ bool lro = !!(efx->net_dev->features & NETIF_F_LRO);
/* If we're in loopback test, then pass the packet directly to the
* loopback layer, and free the rx_buf here
@@ -789,27 +789,18 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
/* Allocate RX buffers */
rxq_size = (efx->type->rxd_ring_mask + 1) * sizeof(*rx_queue->buffer);
rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
- if (!rx_queue->buffer) {
- rc = -ENOMEM;
- goto fail1;
- }
+ if (!rx_queue->buffer)
+ return -ENOMEM;
rc = falcon_probe_rx(rx_queue);
- if (rc)
- goto fail2;
-
- return 0;
-
- fail2:
- kfree(rx_queue->buffer);
- rx_queue->buffer = NULL;
- fail1:
- rx_queue->used = 0;
-
+ if (rc) {
+ kfree(rx_queue->buffer);
+ rx_queue->buffer = NULL;
+ }
return rc;
}
-int efx_init_rx_queue(struct efx_rx_queue *rx_queue)
+void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
unsigned int max_fill, trigger, limit;
@@ -833,7 +824,7 @@ int efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue->fast_fill_limit = limit;
/* Set up RX descriptor ring */
- return falcon_init_rx(rx_queue);
+ falcon_init_rx(rx_queue);
}
void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
@@ -872,7 +863,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
kfree(rx_queue->buffer);
rx_queue->buffer = NULL;
- rx_queue->used = 0;
}
void efx_flush_lro(struct efx_channel *channel)
diff --git a/drivers/net/sfc/rx.h b/drivers/net/sfc/rx.h
index f35e377bfc5..0e88a9ddc1c 100644
--- a/drivers/net/sfc/rx.h
+++ b/drivers/net/sfc/rx.h
@@ -14,7 +14,7 @@
int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
-int efx_init_rx_queue(struct efx_rx_queue *rx_queue);
+void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx);
@@ -24,6 +24,6 @@ void efx_rx_strategy(struct efx_channel *channel);
void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
void efx_rx_work(struct work_struct *data);
void __efx_rx_packet(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf, int checksummed);
+ struct efx_rx_buffer *rx_buf, bool checksummed);
#endif /* EFX_RX_H */
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 3b2de9fe7f2..362956e3fe1 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -27,6 +27,9 @@
#include "boards.h"
#include "workarounds.h"
#include "mac.h"
+#include "spi.h"
+#include "falcon_io.h"
+#include "mdio_10g.h"
/*
* Loopback test packet structure
@@ -51,7 +54,7 @@ static const char *payload_msg =
"Hello world! This is an Efx loopback test in progress!";
/**
- * efx_selftest_state - persistent state during a selftest
+ * efx_loopback_state - persistent state during a loopback selftest
* @flush: Drop all packets in efx_loopback_rx_packet
* @packet_count: Number of packets being used in this test
* @skbs: An array of skbs transmitted
@@ -59,10 +62,14 @@ static const char *payload_msg =
* @rx_bad: RX bad packet count
* @payload: Payload used in tests
*/
-struct efx_selftest_state {
- int flush;
+struct efx_loopback_state {
+ bool flush;
int packet_count;
struct sk_buff **skbs;
+
+ /* Checksums are being offloaded */
+ bool offload_csum;
+
atomic_t rx_good;
atomic_t rx_bad;
struct efx_loopback_payload payload;
@@ -70,21 +77,65 @@ struct efx_selftest_state {
/**************************************************************************
*
- * Configurable values
+ * MII, NVRAM and register tests
*
**************************************************************************/
-/* Level of loopback testing
- *
- * The maximum packet burst length is 16**(n-1), i.e.
- *
- * - Level 0 : no packets
- * - Level 1 : 1 packet
- * - Level 2 : 17 packets (1 * 1 packet, 1 * 16 packets)
- * - Level 3 : 273 packets (1 * 1 packet, 1 * 16 packet, 1 * 256 packets)
- *
- */
-static unsigned int loopback_test_level = 3;
+static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests)
+{
+ int rc = 0;
+ u16 physid1, physid2;
+ struct mii_if_info *mii = &efx->mii;
+ struct net_device *net_dev = efx->net_dev;
+
+ if (efx->phy_type == PHY_TYPE_NONE)
+ return 0;
+
+ mutex_lock(&efx->mac_lock);
+ tests->mii = -1;
+
+ physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
+ physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
+
+ if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
+ (physid2 == 0x0000) || (physid2 == 0xffff)) {
+ EFX_ERR(efx, "no MII PHY present with ID %d\n",
+ mii->phy_id);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
+ if (rc)
+ goto out;
+
+out:
+ mutex_unlock(&efx->mac_lock);
+ tests->mii = rc ? -1 : 1;
+ return rc;
+}
+
+static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests)
+{
+ int rc;
+
+ rc = falcon_read_nvram(efx, NULL);
+ tests->nvram = rc ? -1 : 1;
+ return rc;
+}
+
+static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
+{
+ int rc;
+
+ /* Not supported on A-series silicon */
+ if (falcon_rev(efx) < FALCON_REV_B0)
+ return 0;
+
+ rc = falcon_test_registers(efx);
+ tests->registers = rc ? -1 : 1;
+ return rc;
+}
/**************************************************************************
*
@@ -107,7 +158,7 @@ static int efx_test_interrupts(struct efx_nic *efx,
/* ACK each interrupting event queue. Receiving an interrupt due to
* traffic before a test event is raised is considered a pass */
- efx_for_each_channel_with_interrupt(channel, efx) {
+ efx_for_each_channel(channel, efx) {
if (channel->work_pending)
efx_process_channel_now(channel);
if (efx->last_irq_cpu >= 0)
@@ -132,41 +183,6 @@ static int efx_test_interrupts(struct efx_nic *efx,
return 0;
}
-/* Test generation and receipt of non-interrupting events */
-static int efx_test_eventq(struct efx_channel *channel,
- struct efx_self_tests *tests)
-{
- unsigned int magic;
-
- /* Channel specific code, limited to 20 bits */
- magic = (0x00010150 + channel->channel);
- EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
- channel->channel, magic);
-
- tests->eventq_dma[channel->channel] = -1;
- tests->eventq_int[channel->channel] = 1; /* fake pass */
- tests->eventq_poll[channel->channel] = 1; /* fake pass */
-
- /* Reset flag and zero magic word */
- channel->efx->last_irq_cpu = -1;
- channel->eventq_magic = 0;
- smp_wmb();
-
- falcon_generate_test_event(channel, magic);
- udelay(1);
-
- efx_process_channel_now(channel);
- if (channel->eventq_magic != magic) {
- EFX_ERR(channel->efx, "channel %d failed to see test event\n",
- channel->channel);
- return -ETIMEDOUT;
- } else {
- tests->eventq_dma[channel->channel] = 1;
- }
-
- return 0;
-}
-
/* Test generation and receipt of interrupting events */
static int efx_test_eventq_irq(struct efx_channel *channel,
struct efx_self_tests *tests)
@@ -230,39 +246,18 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
return 0;
}
-/**************************************************************************
- *
- * PHY testing
- *
- **************************************************************************/
-
-/* Check PHY presence by reading the PHY ID registers */
-static int efx_test_phy(struct efx_nic *efx,
- struct efx_self_tests *tests)
+static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests)
{
- u16 physid1, physid2;
- struct mii_if_info *mii = &efx->mii;
- struct net_device *net_dev = efx->net_dev;
+ int rc;
- if (efx->phy_type == PHY_TYPE_NONE)
+ if (!efx->phy_op->test)
return 0;
- EFX_LOG(efx, "testing PHY presence\n");
- tests->phy_ok = -1;
-
- physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
- physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
-
- if ((physid1 != 0x0000) && (physid1 != 0xffff) &&
- (physid2 != 0x0000) && (physid2 != 0xffff)) {
- EFX_LOG(efx, "found MII PHY %d ID 0x%x:%x\n",
- mii->phy_id, physid1, physid2);
- tests->phy_ok = 1;
- return 0;
- }
-
- EFX_ERR(efx, "no MII PHY present with ID %d\n", mii->phy_id);
- return -ENODEV;
+ mutex_lock(&efx->mac_lock);
+ rc = efx->phy_op->test(efx);
+ mutex_unlock(&efx->mac_lock);
+ tests->phy = rc ? -1 : 1;
+ return rc;
}
/**************************************************************************
@@ -278,7 +273,7 @@ static int efx_test_phy(struct efx_nic *efx,
void efx_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len)
{
- struct efx_selftest_state *state = efx->loopback_selftest;
+ struct efx_loopback_state *state = efx->loopback_selftest;
struct efx_loopback_payload *received;
struct efx_loopback_payload *payload;
@@ -289,11 +284,12 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
return;
payload = &state->payload;
-
+
received = (struct efx_loopback_payload *) buf_ptr;
received->ip.saddr = payload->ip.saddr;
- received->ip.check = payload->ip.check;
-
+ if (state->offload_csum)
+ received->ip.check = payload->ip.check;
+
/* Check that header exists */
if (pkt_len < sizeof(received->header)) {
EFX_ERR(efx, "saw runt RX packet (length %d) in %s loopback "
@@ -362,7 +358,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
/* Initialise an efx_selftest_state for a new iteration */
static void efx_iterate_state(struct efx_nic *efx)
{
- struct efx_selftest_state *state = efx->loopback_selftest;
+ struct efx_loopback_state *state = efx->loopback_selftest;
struct net_device *net_dev = efx->net_dev;
struct efx_loopback_payload *payload = &state->payload;
@@ -395,17 +391,17 @@ static void efx_iterate_state(struct efx_nic *efx)
smp_wmb();
}
-static int efx_tx_loopback(struct efx_tx_queue *tx_queue)
+static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- struct efx_selftest_state *state = efx->loopback_selftest;
+ struct efx_loopback_state *state = efx->loopback_selftest;
struct efx_loopback_payload *payload;
struct sk_buff *skb;
int i, rc;
/* Transmit N copies of buffer */
for (i = 0; i < state->packet_count; i++) {
- /* Allocate an skb, holding an extra reference for
+ /* Allocate an skb, holding an extra reference for
* transmit completion counting */
skb = alloc_skb(sizeof(state->payload), GFP_KERNEL);
if (!skb)
@@ -444,11 +440,25 @@ static int efx_tx_loopback(struct efx_tx_queue *tx_queue)
return 0;
}
-static int efx_rx_loopback(struct efx_tx_queue *tx_queue,
- struct efx_loopback_self_tests *lb_tests)
+static int efx_poll_loopback(struct efx_nic *efx)
+{
+ struct efx_loopback_state *state = efx->loopback_selftest;
+ struct efx_channel *channel;
+
+ /* NAPI polling is not enabled, so process channels
+ * synchronously */
+ efx_for_each_channel(channel, efx) {
+ if (channel->work_pending)
+ efx_process_channel_now(channel);
+ }
+ return atomic_read(&state->rx_good) == state->packet_count;
+}
+
+static int efx_end_loopback(struct efx_tx_queue *tx_queue,
+ struct efx_loopback_self_tests *lb_tests)
{
struct efx_nic *efx = tx_queue->efx;
- struct efx_selftest_state *state = efx->loopback_selftest;
+ struct efx_loopback_state *state = efx->loopback_selftest;
struct sk_buff *skb;
int tx_done = 0, rx_good, rx_bad;
int i, rc = 0;
@@ -507,11 +517,10 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
struct efx_loopback_self_tests *lb_tests)
{
struct efx_nic *efx = tx_queue->efx;
- struct efx_selftest_state *state = efx->loopback_selftest;
- struct efx_channel *channel;
- int i, rc = 0;
+ struct efx_loopback_state *state = efx->loopback_selftest;
+ int i, begin_rc, end_rc;
- for (i = 0; i < loopback_test_level; i++) {
+ for (i = 0; i < 3; i++) {
/* Determine how many packets to send */
state->packet_count = (efx->type->txd_ring_mask + 1) / 3;
state->packet_count = min(1 << (i << 2), state->packet_count);
@@ -519,30 +528,31 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
state->packet_count, GFP_KERNEL);
if (!state->skbs)
return -ENOMEM;
- state->flush = 0;
+ state->flush = false;
EFX_LOG(efx, "TX queue %d testing %s loopback with %d "
"packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
state->packet_count);
efx_iterate_state(efx);
- rc = efx_tx_loopback(tx_queue);
-
- /* NAPI polling is not enabled, so process channels synchronously */
- schedule_timeout_uninterruptible(HZ / 50);
- efx_for_each_channel_with_interrupt(channel, efx) {
- if (channel->work_pending)
- efx_process_channel_now(channel);
+ begin_rc = efx_begin_loopback(tx_queue);
+
+ /* This will normally complete very quickly, but be
+ * prepared to wait up to 100 ms. */
+ msleep(1);
+ if (!efx_poll_loopback(efx)) {
+ msleep(100);
+ efx_poll_loopback(efx);
}
- rc |= efx_rx_loopback(tx_queue, lb_tests);
+ end_rc = efx_end_loopback(tx_queue, lb_tests);
kfree(state->skbs);
- if (rc) {
+ if (begin_rc || end_rc) {
/* Wait a while to ensure there are no packets
* floating around after a failure. */
schedule_timeout_uninterruptible(HZ / 10);
- return rc;
+ return begin_rc ? begin_rc : end_rc;
}
}
@@ -550,49 +560,36 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
"of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
state->packet_count);
- return rc;
+ return 0;
}
-static int efx_test_loopbacks(struct efx_nic *efx,
+static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
struct efx_self_tests *tests,
unsigned int loopback_modes)
{
- struct efx_selftest_state *state = efx->loopback_selftest;
- struct ethtool_cmd ecmd, ecmd_loopback;
+ enum efx_loopback_mode mode;
+ struct efx_loopback_state *state;
struct efx_tx_queue *tx_queue;
- enum efx_loopback_mode old_mode, mode;
- int count, rc = 0, link_up;
-
- rc = efx_ethtool_get_settings(efx->net_dev, &ecmd);
- if (rc) {
- EFX_ERR(efx, "could not get GMII settings\n");
- return rc;
- }
- old_mode = efx->loopback_mode;
-
- /* Disable autonegotiation for the purposes of loopback */
- memcpy(&ecmd_loopback, &ecmd, sizeof(ecmd_loopback));
- if (ecmd_loopback.autoneg == AUTONEG_ENABLE) {
- ecmd_loopback.autoneg = AUTONEG_DISABLE;
- ecmd_loopback.duplex = DUPLEX_FULL;
- ecmd_loopback.speed = SPEED_10000;
- }
+ bool link_up;
+ int count, rc = 0;
- rc = efx_ethtool_set_settings(efx->net_dev, &ecmd_loopback);
- if (rc) {
- EFX_ERR(efx, "could not disable autonegotiation\n");
- goto out;
- }
- tests->loopback_speed = ecmd_loopback.speed;
- tests->loopback_full_duplex = ecmd_loopback.duplex;
+ /* Set the port loopback_selftest member. From this point on
+ * all received packets will be dropped. Mark the state as
+ * "flushing" so all inflight packets are dropped */
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+ BUG_ON(efx->loopback_selftest);
+ state->flush = true;
+ efx->loopback_selftest = state;
/* Test all supported loopback modes */
- for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
+ for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
if (!(loopback_modes & (1 << mode)))
continue;
/* Move the port into the specified loopback mode. */
- state->flush = 1;
+ state->flush = true;
efx->loopback_mode = mode;
efx_reconfigure_port(efx);
@@ -616,7 +613,7 @@ static int efx_test_loopbacks(struct efx_nic *efx,
*/
link_up = efx->link_up;
if (!falcon_xaui_link_ok(efx))
- link_up = 0;
+ link_up = false;
} while ((++count < 20) && !link_up);
@@ -634,18 +631,21 @@ static int efx_test_loopbacks(struct efx_nic *efx,
/* Test every TX queue */
efx_for_each_tx_queue(tx_queue, efx) {
- rc |= efx_test_loopback(tx_queue,
- &tests->loopback[mode]);
+ state->offload_csum = (tx_queue->queue ==
+ EFX_TX_QUEUE_OFFLOAD_CSUM);
+ rc = efx_test_loopback(tx_queue,
+ &tests->loopback[mode]);
if (rc)
goto out;
}
}
out:
- /* Take out of loopback and restore PHY settings */
- state->flush = 1;
- efx->loopback_mode = old_mode;
- efx_ethtool_set_settings(efx->net_dev, &ecmd);
+ /* Remove the flush. The caller will remove the loopback setting */
+ state->flush = true;
+ efx->loopback_selftest = NULL;
+ wmb();
+ kfree(state);
return rc;
}
@@ -661,23 +661,27 @@ static int efx_test_loopbacks(struct efx_nic *efx,
int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
{
struct efx_channel *channel;
- int rc = 0;
+ int rc, rc2 = 0;
+
+ rc = efx_test_mii(efx, tests);
+ if (rc && !rc2)
+ rc2 = rc;
- EFX_LOG(efx, "performing online self-tests\n");
+ rc = efx_test_nvram(efx, tests);
+ if (rc && !rc2)
+ rc2 = rc;
+
+ rc = efx_test_interrupts(efx, tests);
+ if (rc && !rc2)
+ rc2 = rc;
- rc |= efx_test_interrupts(efx, tests);
efx_for_each_channel(channel, efx) {
- if (channel->has_interrupt)
- rc |= efx_test_eventq_irq(channel, tests);
- else
- rc |= efx_test_eventq(channel, tests);
+ rc = efx_test_eventq_irq(channel, tests);
+ if (rc && !rc2)
+ rc2 = rc;
}
- rc |= efx_test_phy(efx, tests);
-
- if (rc)
- EFX_ERR(efx, "failed online self-tests\n");
- return rc;
+ return rc2;
}
/* Offline (i.e. disruptive) testing
@@ -685,35 +689,66 @@ int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
int efx_offline_test(struct efx_nic *efx,
struct efx_self_tests *tests, unsigned int loopback_modes)
{
- struct efx_selftest_state *state;
- int rc = 0;
-
- EFX_LOG(efx, "performing offline self-tests\n");
+ enum efx_loopback_mode loopback_mode = efx->loopback_mode;
+ int phy_mode = efx->phy_mode;
+ struct ethtool_cmd ecmd, ecmd_test;
+ int rc, rc2 = 0;
+
+ /* force the carrier state off so the kernel doesn't transmit during
+ * the loopback test, and the watchdog timeout doesn't fire. Also put
+ * falcon into loopback for the register test.
+ */
+ mutex_lock(&efx->mac_lock);
+ efx->port_inhibited = true;
+ if (efx->loopback_modes)
+ efx->loopback_mode = __ffs(efx->loopback_modes);
+ __efx_reconfigure_port(efx);
+ mutex_unlock(&efx->mac_lock);
+
+ /* free up all consumers of SRAM (including all the queues) */
+ efx_reset_down(efx, &ecmd);
+
+ rc = efx_test_chip(efx, tests);
+ if (rc && !rc2)
+ rc2 = rc;
+
+ /* reset the chip to recover from the register test */
+ rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
+
+ /* Modify the saved ecmd so that when efx_reset_up() restores the phy
+ * state, AN is disabled, and the phy is powered, and out of loopback */
+ memcpy(&ecmd_test, &ecmd, sizeof(ecmd_test));
+ if (ecmd_test.autoneg == AUTONEG_ENABLE) {
+ ecmd_test.autoneg = AUTONEG_DISABLE;
+ ecmd_test.duplex = DUPLEX_FULL;
+ ecmd_test.speed = SPEED_10000;
+ }
+ efx->loopback_mode = LOOPBACK_NONE;
- /* Create a selftest_state structure to hold state for the test */
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (state == NULL) {
- rc = -ENOMEM;
- goto out;
+ rc = efx_reset_up(efx, &ecmd_test, rc == 0);
+ if (rc) {
+ EFX_ERR(efx, "Unable to recover from chip test\n");
+ efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+ return rc;
}
- /* Set the port loopback_selftest member. From this point on
- * all received packets will be dropped. Mark the state as
- * "flushing" so all inflight packets are dropped */
- BUG_ON(efx->loopback_selftest);
- state->flush = 1;
- efx->loopback_selftest = state;
+ tests->loopback_speed = ecmd_test.speed;
+ tests->loopback_full_duplex = ecmd_test.duplex;
- rc = efx_test_loopbacks(efx, tests, loopback_modes);
+ rc = efx_test_phy(efx, tests);
+ if (rc && !rc2)
+ rc2 = rc;
- efx->loopback_selftest = NULL;
- wmb();
- kfree(state);
+ rc = efx_test_loopbacks(efx, ecmd_test, tests, loopback_modes);
+ if (rc && !rc2)
+ rc2 = rc;
- out:
- if (rc)
- EFX_ERR(efx, "failed offline self-tests\n");
+ /* restore the PHY to the previous state */
+ efx->loopback_mode = loopback_mode;
+ efx->phy_mode = phy_mode;
+ efx->port_inhibited = false;
+ efx_ethtool_set_settings(efx->net_dev, &ecmd);
- return rc;
+ return rc2;
}
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h
index f6999c2b622..fc15df15d76 100644
--- a/drivers/net/sfc/selftest.h
+++ b/drivers/net/sfc/selftest.h
@@ -18,8 +18,8 @@
*/
struct efx_loopback_self_tests {
- int tx_sent[EFX_MAX_TX_QUEUES];
- int tx_done[EFX_MAX_TX_QUEUES];
+ int tx_sent[EFX_TX_QUEUE_COUNT];
+ int tx_done[EFX_TX_QUEUE_COUNT];
int rx_good;
int rx_bad;
};
@@ -29,14 +29,19 @@ struct efx_loopback_self_tests {
* indicates failure.
*/
struct efx_self_tests {
+ /* online tests */
+ int mii;
+ int nvram;
int interrupt;
int eventq_dma[EFX_MAX_CHANNELS];
int eventq_int[EFX_MAX_CHANNELS];
int eventq_poll[EFX_MAX_CHANNELS];
- int phy_ok;
+ /* offline tests */
+ int registers;
+ int phy;
int loopback_speed;
int loopback_full_duplex;
- struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX];
+ struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
};
extern void efx_loopback_rx_packet(struct efx_nic *efx,
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index b2784952399..fe4e3fd2233 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -13,11 +13,13 @@
* the PHY
*/
#include <linux/delay.h>
+#include "net_driver.h"
#include "efx.h"
#include "phy.h"
#include "boards.h"
#include "falcon.h"
#include "falcon_hwdefs.h"
+#include "falcon_io.h"
#include "mac.h"
/**************************************************************************
@@ -120,23 +122,144 @@ static void sfe4001_poweroff(struct efx_nic *efx)
i2c_smbus_read_byte_data(hwmon_client, RSL);
}
-static void sfe4001_fini(struct efx_nic *efx)
+static int sfe4001_poweron(struct efx_nic *efx)
{
- EFX_INFO(efx, "%s\n", __func__);
+ struct i2c_client *hwmon_client = efx->board_info.hwmon_client;
+ struct i2c_client *ioexp_client = efx->board_info.ioexp_client;
+ unsigned int i, j;
+ int rc;
+ u8 out;
+
+ /* Clear any previous over-temperature alert */
+ rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
+ if (rc < 0)
+ return rc;
+
+ /* Enable port 0 and port 1 outputs on IO expander */
+ rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00);
+ if (rc)
+ return rc;
+ rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
+ 0xff & ~(1 << P1_SPARE_LBN));
+ if (rc)
+ goto fail_on;
+
+ /* If PHY power is on, turn it all off and wait 1 second to
+ * ensure a full reset.
+ */
+ rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT);
+ if (rc < 0)
+ goto fail_on;
+ out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
+ (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
+ (0 << P0_EN_1V0X_LBN));
+ if (rc != out) {
+ EFX_INFO(efx, "power-cycling PHY\n");
+ rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+ if (rc)
+ goto fail_on;
+ schedule_timeout_uninterruptible(HZ);
+ }
+ for (i = 0; i < 20; ++i) {
+ /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
+ out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
+ (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
+ (1 << P0_X_TRST_LBN));
+ if (efx->phy_mode & PHY_MODE_SPECIAL)
+ out |= 1 << P0_EN_3V3X_LBN;
+
+ rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+ if (rc)
+ goto fail_on;
+ msleep(10);
+
+ /* Turn on 1V power rail */
+ out &= ~(1 << P0_EN_1V0X_LBN);
+ rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+ if (rc)
+ goto fail_on;
+
+ EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i);
+
+ /* In flash config mode, DSP does not turn on AFE, so
+ * just wait 1 second.
+ */
+ if (efx->phy_mode & PHY_MODE_SPECIAL) {
+ schedule_timeout_uninterruptible(HZ);
+ return 0;
+ }
+
+ for (j = 0; j < 10; ++j) {
+ msleep(100);
+
+ /* Check DSP has asserted AFE power line */
+ rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
+ if (rc < 0)
+ goto fail_on;
+ if (rc & (1 << P1_AFE_PWD_LBN))
+ return 0;
+ }
+ }
+
+ EFX_INFO(efx, "timed out waiting for DSP boot\n");
+ rc = -ETIMEDOUT;
+fail_on:
sfe4001_poweroff(efx);
- i2c_unregister_device(efx->board_info.ioexp_client);
- i2c_unregister_device(efx->board_info.hwmon_client);
+ return rc;
}
-/* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected
- * to the FLASH_CFG_1 input on the DSP. We must keep it high at power-
- * up to allow writing the flash (done through MDIO from userland).
+/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
+ * using the 3V3X output of the IO-expander. Allow the user to set
+ * this when the device is stopped, and keep it stopped then.
*/
-unsigned int sfe4001_phy_flash_cfg;
-module_param_named(phy_flash_cfg, sfe4001_phy_flash_cfg, uint, 0444);
-MODULE_PARM_DESC(phy_flash_cfg,
- "Force PHY to enter flash configuration mode");
+
+static ssize_t show_phy_flash_cfg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL));
+}
+
+static ssize_t set_phy_flash_cfg(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ enum efx_phy_mode old_mode, new_mode;
+ int err;
+
+ rtnl_lock();
+ old_mode = efx->phy_mode;
+ if (count == 0 || *buf == '0')
+ new_mode = old_mode & ~PHY_MODE_SPECIAL;
+ else
+ new_mode = PHY_MODE_SPECIAL;
+ if (old_mode == new_mode) {
+ err = 0;
+ } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
+ err = -EBUSY;
+ } else {
+ efx->phy_mode = new_mode;
+ err = sfe4001_poweron(efx);
+ efx_reconfigure_port(efx);
+ }
+ rtnl_unlock();
+
+ return err ? err : count;
+}
+
+static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg);
+
+static void sfe4001_fini(struct efx_nic *efx)
+{
+ EFX_INFO(efx, "%s\n", __func__);
+
+ device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+ sfe4001_poweroff(efx);
+ i2c_unregister_device(efx->board_info.ioexp_client);
+ i2c_unregister_device(efx->board_info.hwmon_client);
+}
/* This board uses an I2C expander to provider power to the PHY, which needs to
* be turned on before the PHY can be used.
@@ -144,41 +267,14 @@ MODULE_PARM_DESC(phy_flash_cfg,
*/
int sfe4001_init(struct efx_nic *efx)
{
- struct i2c_client *hwmon_client, *ioexp_client;
- unsigned int count;
+ struct i2c_client *hwmon_client;
int rc;
- u8 out;
- efx_dword_t reg;
hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647);
if (!hwmon_client)
return -EIO;
efx->board_info.hwmon_client = hwmon_client;
- ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
- if (!ioexp_client) {
- rc = -EIO;
- goto fail_hwmon;
- }
- efx->board_info.ioexp_client = ioexp_client;
-
- /* 10Xpress has fixed-function LED pins, so there is no board-specific
- * blink code. */
- efx->board_info.blink = tenxpress_phy_blink;
-
- /* Ensure that XGXS and XAUI SerDes are held in reset */
- EFX_POPULATE_DWORD_7(reg, XX_PWRDNA_EN, 1,
- XX_PWRDNB_EN, 1,
- XX_RSTPLLAB_EN, 1,
- XX_RESETA_EN, 1,
- XX_RESETB_EN, 1,
- XX_RSTXGXSRX_EN, 1,
- XX_RSTXGXSTX_EN, 1);
- falcon_xmac_writel(efx, &reg, XX_PWR_RST_REG_MAC);
- udelay(10);
-
- efx->board_info.fini = sfe4001_fini;
-
/* Set DSP over-temperature alert threshold */
EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
rc = i2c_smbus_write_byte_data(hwmon_client, WLHO,
@@ -195,78 +291,34 @@ int sfe4001_init(struct efx_nic *efx)
goto fail_ioexp;
}
- /* Clear any previous over-temperature alert */
- rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
- if (rc < 0)
- goto fail_ioexp;
+ efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
+ if (!efx->board_info.ioexp_client) {
+ rc = -EIO;
+ goto fail_hwmon;
+ }
- /* Enable port 0 and port 1 outputs on IO expander */
- rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00);
+ /* 10Xpress has fixed-function LED pins, so there is no board-specific
+ * blink code. */
+ efx->board_info.blink = tenxpress_phy_blink;
+
+ efx->board_info.fini = sfe4001_fini;
+
+ rc = sfe4001_poweron(efx);
if (rc)
goto fail_ioexp;
- rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
- 0xff & ~(1 << P1_SPARE_LBN));
- if (rc)
- goto fail_on;
- /* Turn all power off then wait 1 sec. This ensures PHY is reset */
- out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
- (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
- (0 << P0_EN_1V0X_LBN));
- rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+ rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
if (rc)
goto fail_on;
- schedule_timeout_uninterruptible(HZ);
- count = 0;
- do {
- /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
- out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
- (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
- (1 << P0_X_TRST_LBN));
- if (sfe4001_phy_flash_cfg)
- out |= 1 << P0_EN_3V3X_LBN;
-
- rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
- if (rc)
- goto fail_on;
- msleep(10);
-
- /* Turn on 1V power rail */
- out &= ~(1 << P0_EN_1V0X_LBN);
- rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
- if (rc)
- goto fail_on;
-
- EFX_INFO(efx, "waiting for power (attempt %d)...\n", count);
-
- schedule_timeout_uninterruptible(HZ);
-
- /* Check DSP is powered */
- rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
- if (rc < 0)
- goto fail_on;
- if (rc & (1 << P1_AFE_PWD_LBN))
- goto done;
-
- /* DSP doesn't look powered in flash config mode */
- if (sfe4001_phy_flash_cfg)
- goto done;
- } while (++count < 20);
-
- EFX_INFO(efx, "timed out waiting for power\n");
- rc = -ETIMEDOUT;
- goto fail_on;
-
-done:
EFX_INFO(efx, "PHY is powered on\n");
return 0;
fail_on:
sfe4001_poweroff(efx);
fail_ioexp:
- i2c_unregister_device(ioexp_client);
+ i2c_unregister_device(efx->board_info.ioexp_client);
fail_hwmon:
- i2c_unregister_device(hwmon_client);
+ i2c_unregister_device(hwmon_client);
return rc;
}
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
index 34412f3d41c..feef6194237 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/sfc/spi.h
@@ -19,53 +19,48 @@
*
*************************************************************************/
-/*
- * Commands common to all known devices.
- *
+#define SPI_WRSR 0x01 /* Write status register */
+#define SPI_WRITE 0x02 /* Write data to memory array */
+#define SPI_READ 0x03 /* Read data from memory array */
+#define SPI_WRDI 0x04 /* Reset write enable latch */
+#define SPI_RDSR 0x05 /* Read status register */
+#define SPI_WREN 0x06 /* Set write enable latch */
+
+#define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */
+#define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */
+#define SPI_STATUS_BP1 0x08 /* Block protection bit 1 */
+#define SPI_STATUS_BP0 0x04 /* Block protection bit 0 */
+#define SPI_STATUS_WEN 0x02 /* State of the write enable latch */
+#define SPI_STATUS_NRDY 0x01 /* Device busy flag */
+
+/**
+ * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
+ * @efx: The Efx controller that owns this device
+ * @device_id: Controller's id for the device
+ * @size: Size (in bytes)
+ * @addr_len: Number of address bytes in read/write commands
+ * @munge_address: Flag whether addresses should be munged.
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
+ * use bit 3 of the command byte as address bit A8, rather
+ * than having a two-byte address. If this flag is set, then
+ * commands should be munged in this way.
+ * @block_size: Write block size (in bytes).
+ * Write commands are limited to blocks with this size and alignment.
+ * @read: Read function for the device
+ * @write: Write function for the device
*/
-
-/* Write status register */
-#define SPI_WRSR 0x01
-
-/* Write data to memory array */
-#define SPI_WRITE 0x02
-
-/* Read data from memory array */
-#define SPI_READ 0x03
-
-/* Reset write enable latch */
-#define SPI_WRDI 0x04
-
-/* Read status register */
-#define SPI_RDSR 0x05
-
-/* Set write enable latch */
-#define SPI_WREN 0x06
-
-/* SST: Enable write to status register */
-#define SPI_SST_EWSR 0x50
-
-/*
- * Status register bits. Not all bits are supported on all devices.
- *
- */
-
-/* Write-protect pin enabled */
-#define SPI_STATUS_WPEN 0x80
-
-/* Block protection bit 2 */
-#define SPI_STATUS_BP2 0x10
-
-/* Block protection bit 1 */
-#define SPI_STATUS_BP1 0x08
-
-/* Block protection bit 0 */
-#define SPI_STATUS_BP0 0x04
-
-/* State of the write enable latch */
-#define SPI_STATUS_WEN 0x02
-
-/* Device busy flag */
-#define SPI_STATUS_NRDY 0x01
+struct efx_spi_device {
+ struct efx_nic *efx;
+ int device_id;
+ unsigned int size;
+ unsigned int addr_len;
+ unsigned int munge_address:1;
+ unsigned int block_size;
+};
+
+int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
+ size_t len, size_t *retlen, u8 *buffer);
+int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
+ size_t len, size_t *retlen, const u8 *buffer);
#endif /* EFX_SPI_H */
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index c0146061c32..d507c93d666 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -65,25 +65,10 @@
#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
-/* Self test (BIST) control register */
-#define PMA_PMD_BIST_CTRL_REG (0xc014)
-#define PMA_PMD_BIST_BER_LBN (2) /* Run BER test */
-#define PMA_PMD_BIST_CONT_LBN (1) /* Run continuous BIST until cleared */
-#define PMA_PMD_BIST_SINGLE_LBN (0) /* Run 1 BIST iteration (self clears) */
-/* Self test status register */
-#define PMA_PMD_BIST_STAT_REG (0xc015)
-#define PMA_PMD_BIST_ENX_LBN (3)
-#define PMA_PMD_BIST_PMA_LBN (2)
-#define PMA_PMD_BIST_RXD_LBN (1)
-#define PMA_PMD_BIST_AFE_LBN (0)
-
/* Special Software reset register */
#define PMA_PMD_EXT_CTRL_REG 49152
#define PMA_PMD_EXT_SSR_LBN 15
-#define BIST_MAX_DELAY (1000)
-#define BIST_POLL_DELAY (10)
-
/* Misc register defines */
#define PCS_CLOCK_CTRL_REG 0xd801
#define PLL312_RST_N_LBN 2
@@ -119,27 +104,12 @@ MODULE_PARM_DESC(crc_error_reset_threshold,
"Max number of CRC errors before XAUI reset");
struct tenxpress_phy_data {
- enum tenxpress_state state;
enum efx_loopback_mode loopback_mode;
atomic_t bad_crc_count;
- int tx_disabled;
+ enum efx_phy_mode phy_mode;
int bad_lp_tries;
};
-static int tenxpress_state_is(struct efx_nic *efx, int state)
-{
- struct tenxpress_phy_data *phy_data = efx->phy_data;
- return (phy_data != NULL) && (state == phy_data->state);
-}
-
-void tenxpress_set_state(struct efx_nic *efx,
- enum tenxpress_state state)
-{
- struct tenxpress_phy_data *phy_data = efx->phy_data;
- if (phy_data != NULL)
- phy_data->state = state;
-}
-
void tenxpress_crc_err(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
@@ -176,8 +146,6 @@ static int tenxpress_phy_check(struct efx_nic *efx)
return 0;
}
-static void tenxpress_reset_xaui(struct efx_nic *efx);
-
static int tenxpress_init(struct efx_nic *efx)
{
int rc, reg;
@@ -214,15 +182,12 @@ static int tenxpress_phy_init(struct efx_nic *efx)
if (!phy_data)
return -ENOMEM;
efx->phy_data = phy_data;
+ phy_data->phy_mode = efx->phy_mode;
- tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL);
-
- if (!sfe4001_phy_flash_cfg) {
- rc = mdio_clause45_wait_reset_mmds(efx,
- TENXPRESS_REQUIRED_DEVS);
- if (rc < 0)
- goto fail;
- }
+ rc = mdio_clause45_wait_reset_mmds(efx,
+ TENXPRESS_REQUIRED_DEVS);
+ if (rc < 0)
+ goto fail;
rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
if (rc < 0)
@@ -249,7 +214,10 @@ static int tenxpress_special_reset(struct efx_nic *efx)
{
int rc, reg;
- EFX_TRACE(efx, "%s\n", __func__);
+ /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
+ * a special software reset can glitch the XGMAC sufficiently for stats
+ * requests to fail. Since we don't ofen special_reset, just lock. */
+ spin_lock(&efx->stats_lock);
/* Initiate reset */
reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -258,23 +226,25 @@ static int tenxpress_special_reset(struct efx_nic *efx)
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
PMA_PMD_EXT_CTRL_REG, reg);
- msleep(200);
+ mdelay(200);
/* Wait for the blocks to come out of reset */
rc = mdio_clause45_wait_reset_mmds(efx,
TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
- return rc;
+ goto unlock;
/* Try and reconfigure the device */
rc = tenxpress_init(efx);
if (rc < 0)
- return rc;
+ goto unlock;
- return 0;
+unlock:
+ spin_unlock(&efx->stats_lock);
+ return rc;
}
-static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp)
+static void tenxpress_set_bad_lp(struct efx_nic *efx, bool bad_lp)
{
struct tenxpress_phy_data *pd = efx->phy_data;
int reg;
@@ -311,15 +281,15 @@ static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp)
* into a non-10GBT port and if so warn the user that they won't get
* link any time soon as we are 10GBT only, unless caller specified
* not to do this check (it isn't useful in loopback) */
-static int tenxpress_link_ok(struct efx_nic *efx, int check_lp)
+static bool tenxpress_link_ok(struct efx_nic *efx, bool check_lp)
{
- int ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS);
+ bool ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS);
if (ok) {
- tenxpress_set_bad_lp(efx, 0);
+ tenxpress_set_bad_lp(efx, false);
} else if (check_lp) {
/* Are we plugged into the wrong sort of link? */
- int bad_lp = 0;
+ bool bad_lp = false;
int phy_id = efx->mii.phy_id;
int an_stat = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_AN_STATUS);
@@ -332,7 +302,7 @@ static int tenxpress_link_ok(struct efx_nic *efx, int check_lp)
* bit has the advantage of not clearing when autoneg
* restarts. */
if (!(xphy_stat & (1 << PMA_PMD_XSTAT_FLP_LBN))) {
- tenxpress_set_bad_lp(efx, 0);
+ tenxpress_set_bad_lp(efx, false);
return ok;
}
@@ -367,16 +337,19 @@ static void tenxpress_phyxs_loopback(struct efx_nic *efx)
static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
- int loop_change = LOOPBACK_OUT_OF(phy_data, efx,
- TENXPRESS_LOOPBACKS);
+ bool loop_change = LOOPBACK_OUT_OF(phy_data, efx,
+ TENXPRESS_LOOPBACKS);
- if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL))
+ if (efx->phy_mode & PHY_MODE_SPECIAL) {
+ phy_data->phy_mode = efx->phy_mode;
return;
+ }
/* When coming out of transmit disable, coming out of low power
* mode, or moving out of any PHY internal loopback mode,
* perform a special software reset */
- if ((phy_data->tx_disabled && !efx->tx_disabled) ||
+ if ((efx->phy_mode == PHY_MODE_NORMAL &&
+ phy_data->phy_mode != PHY_MODE_NORMAL) ||
loop_change) {
tenxpress_special_reset(efx);
falcon_reset_xaui(efx);
@@ -386,9 +359,9 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
mdio_clause45_phy_reconfigure(efx);
tenxpress_phyxs_loopback(efx);
- phy_data->tx_disabled = efx->tx_disabled;
phy_data->loopback_mode = efx->loopback_mode;
- efx->link_up = tenxpress_link_ok(efx, 0);
+ phy_data->phy_mode = efx->phy_mode;
+ efx->link_up = tenxpress_link_ok(efx, false);
efx->link_options = GM_LPA_10000FULL;
}
@@ -402,16 +375,14 @@ static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
static int tenxpress_phy_check_hw(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
- int phy_up = tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL);
- int link_ok;
+ bool link_ok;
- link_ok = phy_up && tenxpress_link_ok(efx, 1);
+ link_ok = tenxpress_link_ok(efx, true);
if (link_ok != efx->link_up)
falcon_xmac_sim_phy_event(efx);
- /* Nothing to check if we've already shut down the PHY */
- if (!phy_up)
+ if (phy_data->phy_mode != PHY_MODE_NORMAL)
return 0;
if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
@@ -444,7 +415,7 @@ static void tenxpress_phy_fini(struct efx_nic *efx)
/* Set the RX and TX LEDs and Link LED flashing. The other LEDs
* (which probably aren't wired anyway) are left in AUTO mode */
-void tenxpress_phy_blink(struct efx_nic *efx, int blink)
+void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
{
int reg;
@@ -459,52 +430,10 @@ void tenxpress_phy_blink(struct efx_nic *efx, int blink)
PMA_PMD_LED_OVERR_REG, reg);
}
-static void tenxpress_reset_xaui(struct efx_nic *efx)
+static int tenxpress_phy_test(struct efx_nic *efx)
{
- int phy = efx->mii.phy_id;
- int clk_ctrl, test_select, soft_rst2;
-
- /* Real work is done on clock_ctrl other resets are thought to be
- * optional but make the reset more reliable
- */
-
- /* Read */
- clk_ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
- PCS_CLOCK_CTRL_REG);
- test_select = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
- PCS_TEST_SELECT_REG);
- soft_rst2 = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
- PCS_SOFT_RST2_REG);
-
- /* Put in reset */
- test_select &= ~(1 << CLK312_EN_LBN);
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_TEST_SELECT_REG, test_select);
-
- soft_rst2 &= ~((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_SOFT_RST2_REG, soft_rst2);
-
- clk_ctrl &= ~(1 << PLL312_RST_N_LBN);
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_CLOCK_CTRL_REG, clk_ctrl);
- udelay(10);
-
- /* Remove reset */
- clk_ctrl |= (1 << PLL312_RST_N_LBN);
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_CLOCK_CTRL_REG, clk_ctrl);
- udelay(10);
-
- soft_rst2 |= ((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN));
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_SOFT_RST2_REG, soft_rst2);
- udelay(10);
-
- test_select |= (1 << CLK312_EN_LBN);
- mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
- PCS_TEST_SELECT_REG, test_select);
- udelay(10);
+ /* BIST is automatically run after a special software reset */
+ return tenxpress_special_reset(efx);
}
struct efx_phy_operations falcon_tenxpress_phy_ops = {
@@ -513,7 +442,7 @@ struct efx_phy_operations falcon_tenxpress_phy_ops = {
.check_hw = tenxpress_phy_check_hw,
.fini = tenxpress_phy_fini,
.clear_interrupt = tenxpress_phy_clear_interrupt,
- .reset_xaui = tenxpress_reset_xaui,
+ .test = tenxpress_phy_test,
.mmds = TENXPRESS_REQUIRED_DEVS,
.loopbacks = TENXPRESS_LOOPBACKS,
};
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 5e8374ab28e..da3e9ff339f 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -47,7 +47,7 @@ void efx_stop_queue(struct efx_nic *efx)
* We want to be able to nest calls to netif_stop_queue(), since each
* channel can have an individual stop on the queue.
*/
-inline void efx_wake_queue(struct efx_nic *efx)
+void efx_wake_queue(struct efx_nic *efx)
{
local_bh_disable();
if (atomic_dec_and_lock(&efx->netif_stop_count,
@@ -59,19 +59,21 @@ inline void efx_wake_queue(struct efx_nic *efx)
local_bh_enable();
}
-static inline void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer)
+static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
+ struct efx_tx_buffer *buffer)
{
if (buffer->unmap_len) {
struct pci_dev *pci_dev = tx_queue->efx->pci_dev;
+ dma_addr_t unmap_addr = (buffer->dma_addr + buffer->len -
+ buffer->unmap_len);
if (buffer->unmap_single)
- pci_unmap_single(pci_dev, buffer->unmap_addr,
- buffer->unmap_len, PCI_DMA_TODEVICE);
+ pci_unmap_single(pci_dev, unmap_addr, buffer->unmap_len,
+ PCI_DMA_TODEVICE);
else
- pci_unmap_page(pci_dev, buffer->unmap_addr,
- buffer->unmap_len, PCI_DMA_TODEVICE);
+ pci_unmap_page(pci_dev, unmap_addr, buffer->unmap_len,
+ PCI_DMA_TODEVICE);
buffer->unmap_len = 0;
- buffer->unmap_single = 0;
+ buffer->unmap_single = false;
}
if (buffer->skb) {
@@ -103,13 +105,13 @@ struct efx_tso_header {
};
static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb);
+ struct sk_buff *skb);
static void efx_fini_tso(struct efx_tx_queue *tx_queue);
static void efx_tsoh_heap_free(struct efx_tx_queue *tx_queue,
struct efx_tso_header *tsoh);
-static inline void efx_tsoh_free(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer)
+static void efx_tsoh_free(struct efx_tx_queue *tx_queue,
+ struct efx_tx_buffer *buffer)
{
if (buffer->tsoh) {
if (likely(!buffer->tsoh->unmap_len)) {
@@ -136,8 +138,8 @@ static inline void efx_tsoh_free(struct efx_tx_queue *tx_queue,
* Returns NETDEV_TX_OK or NETDEV_TX_BUSY
* You must hold netif_tx_lock() to call this function.
*/
-static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb)
+static int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb)
{
struct efx_nic *efx = tx_queue->efx;
struct pci_dev *pci_dev = efx->pci_dev;
@@ -148,7 +150,7 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
unsigned int len, unmap_len = 0, fill_level, insert_ptr, misalign;
dma_addr_t dma_addr, unmap_addr = 0;
unsigned int dma_len;
- unsigned unmap_single;
+ bool unmap_single;
int q_space, i = 0;
int rc = NETDEV_TX_OK;
@@ -167,7 +169,7 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
* since this is more efficient on machines with sparse
* memory.
*/
- unmap_single = 1;
+ unmap_single = true;
dma_addr = pci_map_single(pci_dev, skb->data, len, PCI_DMA_TODEVICE);
/* Process all fragments */
@@ -213,7 +215,7 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
EFX_BUG_ON_PARANOID(buffer->tsoh);
EFX_BUG_ON_PARANOID(buffer->skb);
EFX_BUG_ON_PARANOID(buffer->len);
- EFX_BUG_ON_PARANOID(buffer->continuation != 1);
+ EFX_BUG_ON_PARANOID(!buffer->continuation);
EFX_BUG_ON_PARANOID(buffer->unmap_len);
dma_len = (((~dma_addr) & efx->type->tx_dma_mask) + 1);
@@ -233,7 +235,6 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
} while (len);
/* Transfer ownership of the unmapping to the final buffer */
- buffer->unmap_addr = unmap_addr;
buffer->unmap_single = unmap_single;
buffer->unmap_len = unmap_len;
unmap_len = 0;
@@ -247,14 +248,14 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
page_offset = fragment->page_offset;
i++;
/* Map for DMA */
- unmap_single = 0;
+ unmap_single = false;
dma_addr = pci_map_page(pci_dev, page, page_offset, len,
PCI_DMA_TODEVICE);
}
/* Transfer ownership of the skb to the final buffer */
buffer->skb = skb;
- buffer->continuation = 0;
+ buffer->continuation = false;
/* Pass off to hardware */
falcon_push_buffers(tx_queue);
@@ -287,9 +288,14 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
}
/* Free the fragment we were mid-way through pushing */
- if (unmap_len)
- pci_unmap_page(pci_dev, unmap_addr, unmap_len,
- PCI_DMA_TODEVICE);
+ if (unmap_len) {
+ if (unmap_single)
+ pci_unmap_single(pci_dev, unmap_addr, unmap_len,
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(pci_dev, unmap_addr, unmap_len,
+ PCI_DMA_TODEVICE);
+ }
return rc;
}
@@ -299,8 +305,8 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
* This removes packets from the TX queue, up to and including the
* specified index.
*/
-static inline void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
- unsigned int index)
+static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
+ unsigned int index)
{
struct efx_nic *efx = tx_queue->efx;
unsigned int stop_index, read_ptr;
@@ -320,7 +326,7 @@ static inline void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
}
efx_dequeue_buffer(tx_queue, buffer);
- buffer->continuation = 1;
+ buffer->continuation = true;
buffer->len = 0;
++tx_queue->read_count;
@@ -367,8 +373,15 @@ inline int efx_xmit(struct efx_nic *efx,
*/
int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
{
- struct efx_nic *efx = net_dev->priv;
- return efx_xmit(efx, &efx->tx_queue[0], skb);
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_tx_queue *tx_queue;
+
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
+ tx_queue = &efx->tx_queue[EFX_TX_QUEUE_OFFLOAD_CSUM];
+ else
+ tx_queue = &efx->tx_queue[EFX_TX_QUEUE_NO_CSUM];
+
+ return efx_xmit(efx, tx_queue, skb);
}
void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
@@ -412,30 +425,25 @@ int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
/* Allocate software ring */
txq_size = (efx->type->txd_ring_mask + 1) * sizeof(*tx_queue->buffer);
tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
- if (!tx_queue->buffer) {
- rc = -ENOMEM;
- goto fail1;
- }
+ if (!tx_queue->buffer)
+ return -ENOMEM;
for (i = 0; i <= efx->type->txd_ring_mask; ++i)
- tx_queue->buffer[i].continuation = 1;
+ tx_queue->buffer[i].continuation = true;
/* Allocate hardware ring */
rc = falcon_probe_tx(tx_queue);
if (rc)
- goto fail2;
+ goto fail;
return 0;
- fail2:
+ fail:
kfree(tx_queue->buffer);
tx_queue->buffer = NULL;
- fail1:
- tx_queue->used = 0;
-
return rc;
}
-int efx_init_tx_queue(struct efx_tx_queue *tx_queue)
+void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
{
EFX_LOG(tx_queue->efx, "initialising TX queue %d\n", tx_queue->queue);
@@ -446,7 +454,7 @@ int efx_init_tx_queue(struct efx_tx_queue *tx_queue)
BUG_ON(tx_queue->stopped);
/* Set up TX descriptor ring */
- return falcon_init_tx(tx_queue);
+ falcon_init_tx(tx_queue);
}
void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
@@ -461,7 +469,7 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
buffer = &tx_queue->buffer[tx_queue->read_count &
tx_queue->efx->type->txd_ring_mask];
efx_dequeue_buffer(tx_queue, buffer);
- buffer->continuation = 1;
+ buffer->continuation = true;
buffer->len = 0;
++tx_queue->read_count;
@@ -494,7 +502,6 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
kfree(tx_queue->buffer);
tx_queue->buffer = NULL;
- tx_queue->used = 0;
}
@@ -509,7 +516,7 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
/* Number of bytes inserted at the start of a TSO header buffer,
* similar to NET_IP_ALIGN.
*/
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
#define TSOH_OFFSET 0
#else
#define TSOH_OFFSET NET_IP_ALIGN
@@ -533,47 +540,37 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
/**
* struct tso_state - TSO state for an SKB
- * @remaining_len: Bytes of data we've yet to segment
+ * @out_len: Remaining length in current segment
* @seqnum: Current sequence number
+ * @ipv4_id: Current IPv4 ID, host endian
* @packet_space: Remaining space in current packet
- * @ifc: Input fragment cursor.
- * Where we are in the current fragment of the incoming SKB. These
- * values get updated in place when we split a fragment over
- * multiple packets.
- * @p: Parameters.
- * These values are set once at the start of the TSO send and do
- * not get changed as the routine progresses.
+ * @dma_addr: DMA address of current position
+ * @in_len: Remaining length in current SKB fragment
+ * @unmap_len: Length of SKB fragment
+ * @unmap_addr: DMA address of SKB fragment
+ * @unmap_single: DMA single vs page mapping flag
+ * @header_len: Number of bytes of header
+ * @full_packet_size: Number of bytes to put in each outgoing segment
*
* The state used during segmentation. It is put into this data structure
* just to make it easy to pass into inline functions.
*/
struct tso_state {
- unsigned remaining_len;
+ /* Output position */
+ unsigned out_len;
unsigned seqnum;
+ unsigned ipv4_id;
unsigned packet_space;
- struct {
- /* DMA address of current position */
- dma_addr_t dma_addr;
- /* Remaining length */
- unsigned int len;
- /* DMA address and length of the whole fragment */
- unsigned int unmap_len;
- dma_addr_t unmap_addr;
- struct page *page;
- unsigned page_off;
- } ifc;
-
- struct {
- /* The number of bytes of header */
- unsigned int header_length;
-
- /* The number of bytes to put in each outgoing segment. */
- int full_packet_size;
-
- /* Current IPv4 ID, host endian. */
- unsigned ipv4_id;
- } p;
+ /* Input position */
+ dma_addr_t dma_addr;
+ unsigned in_len;
+ unsigned unmap_len;
+ dma_addr_t unmap_addr;
+ bool unmap_single;
+
+ unsigned header_len;
+ int full_packet_size;
};
@@ -581,11 +578,24 @@ struct tso_state {
* Verify that our various assumptions about sk_buffs and the conditions
* under which TSO will be attempted hold true.
*/
-static inline void efx_tso_check_safe(const struct sk_buff *skb)
+static void efx_tso_check_safe(struct sk_buff *skb)
{
- EFX_BUG_ON_PARANOID(skb->protocol != htons(ETH_P_IP));
+ __be16 protocol = skb->protocol;
+
EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto !=
- skb->protocol);
+ protocol);
+ if (protocol == htons(ETH_P_8021Q)) {
+ /* Find the encapsulated protocol; reset network header
+ * and transport header based on that. */
+ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
+ protocol = veh->h_vlan_encapsulated_proto;
+ skb_set_network_header(skb, sizeof(*veh));
+ if (protocol == htons(ETH_P_IP))
+ skb_set_transport_header(skb, sizeof(*veh) +
+ 4 * ip_hdr(skb)->ihl);
+ }
+
+ EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IP));
EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP);
EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data)
+ (tcp_hdr(skb)->doff << 2u)) >
@@ -685,18 +695,14 @@ efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, struct efx_tso_header *tsoh)
* @tx_queue: Efx TX queue
* @dma_addr: DMA address of fragment
* @len: Length of fragment
- * @skb: Only non-null for end of last segment
- * @end_of_packet: True if last fragment in a packet
- * @unmap_addr: DMA address of fragment for unmapping
- * @unmap_len: Only set this in last segment of a fragment
+ * @final_buffer: The final buffer inserted into the queue
*
* Push descriptors onto the TX queue. Return 0 on success or 1 if
* @tx_queue full.
*/
static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
dma_addr_t dma_addr, unsigned len,
- const struct sk_buff *skb, int end_of_packet,
- dma_addr_t unmap_addr, unsigned unmap_len)
+ struct efx_tx_buffer **final_buffer)
{
struct efx_tx_buffer *buffer;
struct efx_nic *efx = tx_queue->efx;
@@ -724,8 +730,10 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
fill_level = (tx_queue->insert_count
- tx_queue->old_read_count);
q_space = efx->type->txd_ring_mask - 1 - fill_level;
- if (unlikely(q_space-- <= 0))
+ if (unlikely(q_space-- <= 0)) {
+ *final_buffer = NULL;
return 1;
+ }
smp_mb();
--tx_queue->stopped;
}
@@ -742,7 +750,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
EFX_BUG_ON_PARANOID(buffer->len);
EFX_BUG_ON_PARANOID(buffer->unmap_len);
EFX_BUG_ON_PARANOID(buffer->skb);
- EFX_BUG_ON_PARANOID(buffer->continuation != 1);
+ EFX_BUG_ON_PARANOID(!buffer->continuation);
EFX_BUG_ON_PARANOID(buffer->tsoh);
buffer->dma_addr = dma_addr;
@@ -765,10 +773,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
EFX_BUG_ON_PARANOID(!len);
buffer->len = len;
- buffer->skb = skb;
- buffer->continuation = !end_of_packet;
- buffer->unmap_addr = unmap_addr;
- buffer->unmap_len = unmap_len;
+ *final_buffer = buffer;
return 0;
}
@@ -780,8 +785,8 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
* a single fragment, and we know it doesn't cross a page boundary. It
* also allows us to not worry about end-of-packet etc.
*/
-static inline void efx_tso_put_header(struct efx_tx_queue *tx_queue,
- struct efx_tso_header *tsoh, unsigned len)
+static void efx_tso_put_header(struct efx_tx_queue *tx_queue,
+ struct efx_tso_header *tsoh, unsigned len)
{
struct efx_tx_buffer *buffer;
@@ -791,7 +796,7 @@ static inline void efx_tso_put_header(struct efx_tx_queue *tx_queue,
EFX_BUG_ON_PARANOID(buffer->len);
EFX_BUG_ON_PARANOID(buffer->unmap_len);
EFX_BUG_ON_PARANOID(buffer->skb);
- EFX_BUG_ON_PARANOID(buffer->continuation != 1);
+ EFX_BUG_ON_PARANOID(!buffer->continuation);
EFX_BUG_ON_PARANOID(buffer->tsoh);
buffer->len = len;
buffer->dma_addr = tsoh->dma_addr;
@@ -805,6 +810,7 @@ static inline void efx_tso_put_header(struct efx_tx_queue *tx_queue,
static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
{
struct efx_tx_buffer *buffer;
+ dma_addr_t unmap_addr;
/* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) {
@@ -814,11 +820,18 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->skb);
buffer->len = 0;
- buffer->continuation = 1;
+ buffer->continuation = true;
if (buffer->unmap_len) {
- pci_unmap_page(tx_queue->efx->pci_dev,
- buffer->unmap_addr,
- buffer->unmap_len, PCI_DMA_TODEVICE);
+ unmap_addr = (buffer->dma_addr + buffer->len -
+ buffer->unmap_len);
+ if (buffer->unmap_single)
+ pci_unmap_single(tx_queue->efx->pci_dev,
+ unmap_addr, buffer->unmap_len,
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(tx_queue->efx->pci_dev,
+ unmap_addr, buffer->unmap_len,
+ PCI_DMA_TODEVICE);
buffer->unmap_len = 0;
}
}
@@ -826,50 +839,57 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
/* Parse the SKB header and initialise state. */
-static inline void tso_start(struct tso_state *st, const struct sk_buff *skb)
+static void tso_start(struct tso_state *st, const struct sk_buff *skb)
{
/* All ethernet/IP/TCP headers combined size is TCP header size
* plus offset of TCP header relative to start of packet.
*/
- st->p.header_length = ((tcp_hdr(skb)->doff << 2u)
- + PTR_DIFF(tcp_hdr(skb), skb->data));
- st->p.full_packet_size = (st->p.header_length
- + skb_shinfo(skb)->gso_size);
+ st->header_len = ((tcp_hdr(skb)->doff << 2u)
+ + PTR_DIFF(tcp_hdr(skb), skb->data));
+ st->full_packet_size = st->header_len + skb_shinfo(skb)->gso_size;
- st->p.ipv4_id = ntohs(ip_hdr(skb)->id);
+ st->ipv4_id = ntohs(ip_hdr(skb)->id);
st->seqnum = ntohl(tcp_hdr(skb)->seq);
EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg);
EFX_BUG_ON_PARANOID(tcp_hdr(skb)->syn);
EFX_BUG_ON_PARANOID(tcp_hdr(skb)->rst);
- st->packet_space = st->p.full_packet_size;
- st->remaining_len = skb->len - st->p.header_length;
+ st->packet_space = st->full_packet_size;
+ st->out_len = skb->len - st->header_len;
+ st->unmap_len = 0;
+ st->unmap_single = false;
}
-
-/**
- * tso_get_fragment - record fragment details and map for DMA
- * @st: TSO state
- * @efx: Efx NIC
- * @data: Pointer to fragment data
- * @len: Length of fragment
- *
- * Record fragment details and map for DMA. Return 0 on success, or
- * -%ENOMEM if DMA mapping fails.
- */
-static inline int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
- int len, struct page *page, int page_off)
+static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
+ skb_frag_t *frag)
{
+ st->unmap_addr = pci_map_page(efx->pci_dev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+ if (likely(!pci_dma_mapping_error(efx->pci_dev, st->unmap_addr))) {
+ st->unmap_single = false;
+ st->unmap_len = frag->size;
+ st->in_len = frag->size;
+ st->dma_addr = st->unmap_addr;
+ return 0;
+ }
+ return -ENOMEM;
+}
- st->ifc.unmap_addr = pci_map_page(efx->pci_dev, page, page_off,
- len, PCI_DMA_TODEVICE);
- if (likely(!pci_dma_mapping_error(efx->pci_dev, st->ifc.unmap_addr))) {
- st->ifc.unmap_len = len;
- st->ifc.len = len;
- st->ifc.dma_addr = st->ifc.unmap_addr;
- st->ifc.page = page;
- st->ifc.page_off = page_off;
+static int tso_get_head_fragment(struct tso_state *st, struct efx_nic *efx,
+ const struct sk_buff *skb)
+{
+ int hl = st->header_len;
+ int len = skb_headlen(skb) - hl;
+
+ st->unmap_addr = pci_map_single(efx->pci_dev, skb->data + hl,
+ len, PCI_DMA_TODEVICE);
+ if (likely(!pci_dma_mapping_error(efx->pci_dev, st->unmap_addr))) {
+ st->unmap_single = true;
+ st->unmap_len = len;
+ st->in_len = len;
+ st->dma_addr = st->unmap_addr;
return 0;
}
return -ENOMEM;
@@ -886,36 +906,45 @@ static inline int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
* of fragment or end-of-packet. Return 0 on success, 1 if not enough
* space in @tx_queue.
*/
-static inline int tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb,
- struct tso_state *st)
+static int tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
+ const struct sk_buff *skb,
+ struct tso_state *st)
{
-
+ struct efx_tx_buffer *buffer;
int n, end_of_packet, rc;
- if (st->ifc.len == 0)
+ if (st->in_len == 0)
return 0;
if (st->packet_space == 0)
return 0;
- EFX_BUG_ON_PARANOID(st->ifc.len <= 0);
+ EFX_BUG_ON_PARANOID(st->in_len <= 0);
EFX_BUG_ON_PARANOID(st->packet_space <= 0);
- n = min(st->ifc.len, st->packet_space);
+ n = min(st->in_len, st->packet_space);
st->packet_space -= n;
- st->remaining_len -= n;
- st->ifc.len -= n;
- st->ifc.page_off += n;
- end_of_packet = st->remaining_len == 0 || st->packet_space == 0;
-
- rc = efx_tx_queue_insert(tx_queue, st->ifc.dma_addr, n,
- st->remaining_len ? NULL : skb,
- end_of_packet, st->ifc.unmap_addr,
- st->ifc.len ? 0 : st->ifc.unmap_len);
-
- st->ifc.dma_addr += n;
+ st->out_len -= n;
+ st->in_len -= n;
+
+ rc = efx_tx_queue_insert(tx_queue, st->dma_addr, n, &buffer);
+ if (likely(rc == 0)) {
+ if (st->out_len == 0)
+ /* Transfer ownership of the skb */
+ buffer->skb = skb;
+
+ end_of_packet = st->out_len == 0 || st->packet_space == 0;
+ buffer->continuation = !end_of_packet;
+
+ if (st->in_len == 0) {
+ /* Transfer ownership of the pci mapping */
+ buffer->unmap_len = st->unmap_len;
+ buffer->unmap_single = st->unmap_single;
+ st->unmap_len = 0;
+ }
+ }
+ st->dma_addr += n;
return rc;
}
@@ -929,9 +958,9 @@ static inline int tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
* Generate a new header and prepare for the new packet. Return 0 on
* success, or -1 if failed to alloc header.
*/
-static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb,
- struct tso_state *st)
+static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
+ const struct sk_buff *skb,
+ struct tso_state *st)
{
struct efx_tso_header *tsoh;
struct iphdr *tsoh_iph;
@@ -940,7 +969,7 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
u8 *header;
/* Allocate a DMA-mapped header buffer. */
- if (likely(TSOH_SIZE(st->p.header_length) <= TSOH_STD_SIZE)) {
+ if (likely(TSOH_SIZE(st->header_len) <= TSOH_STD_SIZE)) {
if (tx_queue->tso_headers_free == NULL) {
if (efx_tsoh_block_alloc(tx_queue))
return -1;
@@ -951,7 +980,7 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
tsoh->unmap_len = 0;
} else {
tx_queue->tso_long_headers++;
- tsoh = efx_tsoh_heap_alloc(tx_queue, st->p.header_length);
+ tsoh = efx_tsoh_heap_alloc(tx_queue, st->header_len);
if (unlikely(!tsoh))
return -1;
}
@@ -961,33 +990,32 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
tsoh_iph = (struct iphdr *)(header + SKB_IPV4_OFF(skb));
/* Copy and update the headers. */
- memcpy(header, skb->data, st->p.header_length);
+ memcpy(header, skb->data, st->header_len);
tsoh_th->seq = htonl(st->seqnum);
st->seqnum += skb_shinfo(skb)->gso_size;
- if (st->remaining_len > skb_shinfo(skb)->gso_size) {
+ if (st->out_len > skb_shinfo(skb)->gso_size) {
/* This packet will not finish the TSO burst. */
- ip_length = st->p.full_packet_size - ETH_HDR_LEN(skb);
+ ip_length = st->full_packet_size - ETH_HDR_LEN(skb);
tsoh_th->fin = 0;
tsoh_th->psh = 0;
} else {
/* This packet will be the last in the TSO burst. */
- ip_length = (st->p.header_length - ETH_HDR_LEN(skb)
- + st->remaining_len);
+ ip_length = st->header_len - ETH_HDR_LEN(skb) + st->out_len;
tsoh_th->fin = tcp_hdr(skb)->fin;
tsoh_th->psh = tcp_hdr(skb)->psh;
}
tsoh_iph->tot_len = htons(ip_length);
/* Linux leaves suitable gaps in the IP ID space for us to fill. */
- tsoh_iph->id = htons(st->p.ipv4_id);
- st->p.ipv4_id++;
+ tsoh_iph->id = htons(st->ipv4_id);
+ st->ipv4_id++;
st->packet_space = skb_shinfo(skb)->gso_size;
++tx_queue->tso_packets;
/* Form a descriptor for this header. */
- efx_tso_put_header(tx_queue, tsoh, st->p.header_length);
+ efx_tso_put_header(tx_queue, tsoh, st->header_len);
return 0;
}
@@ -1005,11 +1033,11 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue,
* %NETDEV_TX_OK or %NETDEV_TX_BUSY.
*/
static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
- const struct sk_buff *skb)
+ struct sk_buff *skb)
{
+ struct efx_nic *efx = tx_queue->efx;
int frag_i, rc, rc2 = NETDEV_TX_OK;
struct tso_state state;
- skb_frag_t *f;
/* Verify TSO is safe - these checks should never fail. */
efx_tso_check_safe(skb);
@@ -1021,29 +1049,16 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
/* Assume that skb header area contains exactly the headers, and
* all payload is in the frag list.
*/
- if (skb_headlen(skb) == state.p.header_length) {
+ if (skb_headlen(skb) == state.header_len) {
/* Grab the first payload fragment. */
EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1);
frag_i = 0;
- f = &skb_shinfo(skb)->frags[frag_i];
- rc = tso_get_fragment(&state, tx_queue->efx,
- f->size, f->page, f->page_offset);
+ rc = tso_get_fragment(&state, efx,
+ skb_shinfo(skb)->frags + frag_i);
if (rc)
goto mem_err;
} else {
- /* It may look like this code fragment assumes that the
- * skb->data portion does not cross a page boundary, but
- * that is not the case. It is guaranteed to be direct
- * mapped memory, and therefore is physically contiguous,
- * and so DMA will work fine. kmap_atomic() on this region
- * will just return the direct mapping, so that will work
- * too.
- */
- int page_off = (unsigned long)skb->data & (PAGE_SIZE - 1);
- int hl = state.p.header_length;
- rc = tso_get_fragment(&state, tx_queue->efx,
- skb_headlen(skb) - hl,
- virt_to_page(skb->data), page_off + hl);
+ rc = tso_get_head_fragment(&state, efx, skb);
if (rc)
goto mem_err;
frag_i = -1;
@@ -1058,13 +1073,12 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
goto stop;
/* Move onto the next fragment? */
- if (state.ifc.len == 0) {
+ if (state.in_len == 0) {
if (++frag_i >= skb_shinfo(skb)->nr_frags)
/* End of payload reached. */
break;
- f = &skb_shinfo(skb)->frags[frag_i];
- rc = tso_get_fragment(&state, tx_queue->efx,
- f->size, f->page, f->page_offset);
+ rc = tso_get_fragment(&state, efx,
+ skb_shinfo(skb)->frags + frag_i);
if (rc)
goto mem_err;
}
@@ -1082,8 +1096,7 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
return NETDEV_TX_OK;
mem_err:
- EFX_ERR(tx_queue->efx, "Out of memory for TSO headers, or PCI mapping"
- " error\n");
+ EFX_ERR(efx, "Out of memory for TSO headers, or PCI mapping error\n");
dev_kfree_skb_any((struct sk_buff *)skb);
goto unwind;
@@ -1092,9 +1105,19 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
/* Stop the queue if it wasn't stopped before. */
if (tx_queue->stopped == 1)
- efx_stop_queue(tx_queue->efx);
+ efx_stop_queue(efx);
unwind:
+ /* Free the DMA mapping we were in the process of writing out */
+ if (state.unmap_len) {
+ if (state.unmap_single)
+ pci_unmap_single(efx->pci_dev, state.unmap_addr,
+ state.unmap_len, PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(efx->pci_dev, state.unmap_addr,
+ state.unmap_len, PCI_DMA_TODEVICE);
+ }
+
efx_enqueue_unwind(tx_queue);
return rc2;
}
diff --git a/drivers/net/sfc/tx.h b/drivers/net/sfc/tx.h
index 1526a73b4b5..5e1cc234e42 100644
--- a/drivers/net/sfc/tx.h
+++ b/drivers/net/sfc/tx.h
@@ -15,7 +15,7 @@
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
-int efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 35ab19c27f8..fa7b49d6928 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -20,14 +20,10 @@
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
-/* SNAP frames have TOBE_DISC set */
-#define EFX_WORKAROUND_5475 EFX_WORKAROUND_ALWAYS
/* RX PCIe double split performance issue */
#define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
/* TX pkt parser problem with <= 16 byte TXes */
#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
-/* XGXS and XAUI reset sequencing in SW */
-#define EFX_WORKAROUND_9388 EFX_WORKAROUND_ALWAYS
/* Low rate CRC errors require XAUI reset */
#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS
/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index f3684ad2888..276151df3a7 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -40,7 +40,7 @@ void xfp_set_led(struct efx_nic *p, int led, int mode)
}
struct xfp_phy_data {
- int tx_disabled;
+ enum efx_phy_mode phy_mode;
};
#define XFP_MAX_RESET_TIME 500
@@ -93,7 +93,7 @@ static int xfp_phy_init(struct efx_nic *efx)
" %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
MDIO_ID_REV(devid));
- phy_data->tx_disabled = efx->tx_disabled;
+ phy_data->phy_mode = efx->phy_mode;
rc = xfp_reset_phy(efx);
@@ -136,13 +136,14 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
struct xfp_phy_data *phy_data = efx->phy_data;
/* Reset the PHY when moving from tx off to tx on */
- if (phy_data->tx_disabled && !efx->tx_disabled)
+ if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) &&
+ (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
xfp_reset_phy(efx);
mdio_clause45_transmit_disable(efx);
mdio_clause45_phy_reconfigure(efx);
- phy_data->tx_disabled = efx->tx_disabled;
+ phy_data->phy_mode = efx->phy_mode;
efx->link_up = xfp_link_ok(efx);
efx->link_options = GM_LPA_10000FULL;
}
@@ -151,7 +152,7 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
static void xfp_phy_fini(struct efx_nic *efx)
{
/* Clobber the LED if it was blinking */
- efx->board_info.blink(efx, 0);
+ efx->board_info.blink(efx, false);
/* Free the context block */
kfree(efx->phy_data);
@@ -164,7 +165,6 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
.check_hw = xfp_phy_check_hw,
.fini = xfp_phy_fini,
.clear_interrupt = xfp_phy_clear_interrupt,
- .reset_xaui = efx_port_dummy_op_void,
.mmds = XFP_REQUIRED_DEVS,
.loopbacks = XFP_LOOPBACKS,
};
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 1c370e6aa64..b39d1cc1ef0 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1140,7 +1140,7 @@ static int sh_mdio_init(struct net_device *ndev, int id)
/* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii";
- mdp->mii_bus->dev = &ndev->dev;
+ mdp->mii_bus->parent = &ndev->dev;
mdp->mii_bus->id[0] = id;
/* PHY IRQ */
@@ -1166,7 +1166,7 @@ out_free_irq:
kfree(mdp->mii_bus->irq);
out_free_bus:
- kfree(mdp->mii_bus);
+ free_mdio_bitbang(mdp->mii_bus);
out_free_bitbang:
kfree(bitbang);
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
index ea85de91823..79e665e0853 100644
--- a/drivers/net/skfp/pmf.c
+++ b/drivers/net/skfp/pmf.c
@@ -44,17 +44,10 @@ static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
int set, int local);
static int port_to_mib(struct s_smc *smc, int p);
-#define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e))
-#define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e))
-
-#define MOFFMS(e) ((int)&(((struct fddi_mib_m *)0)->e))
-#define MOFFMA(e) ((int) (((struct fddi_mib_m *)0)->e))
-
-#define MOFFAS(e) ((int)&(((struct fddi_mib_a *)0)->e))
-#define MOFFAA(e) ((int) (((struct fddi_mib_a *)0)->e))
-
-#define MOFFPS(e) ((int)&(((struct fddi_mib_p *)0)->e))
-#define MOFFPA(e) ((int) (((struct fddi_mib_p *)0)->e))
+#define MOFFSS(e) offsetof(struct fddi_mib, e)
+#define MOFFMS(e) offsetof(struct fddi_mib_m, e)
+#define MOFFAS(e) offsetof(struct fddi_mib_a, e)
+#define MOFFPS(e) offsetof(struct fddi_mib_p, e)
#define AC_G 0x01 /* Get */
@@ -87,8 +80,8 @@ static const struct s_p_tab {
{ SMT_P100D,AC_G, MOFFSS(fddiSMTOpVersionId), "S" } ,
{ SMT_P100E,AC_G, MOFFSS(fddiSMTHiVersionId), "S" } ,
{ SMT_P100F,AC_G, MOFFSS(fddiSMTLoVersionId), "S" } ,
- { SMT_P1010,AC_G, MOFFSA(fddiSMTManufacturerData), "D" } ,
- { SMT_P1011,AC_GR, MOFFSA(fddiSMTUserData), "D" } ,
+ { SMT_P1010,AC_G, MOFFSS(fddiSMTManufacturerData), "D" } ,
+ { SMT_P1011,AC_GR, MOFFSS(fddiSMTUserData), "D" } ,
{ SMT_P1012,AC_G, MOFFSS(fddiSMTMIBVersionId), "S" } ,
/* StationConfigGrp */
@@ -103,7 +96,7 @@ static const struct s_p_tab {
{ SMT_P101D,AC_GR, MOFFSS(fddiSMTTT_Notify), "wS" } ,
{ SMT_P101E,AC_GR, MOFFSS(fddiSMTStatRptPolicy), "bB" } ,
{ SMT_P101F,AC_GR, MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
- { SMT_P1020,AC_G, MOFFSA(fddiSMTPORTIndexes), "II" } ,
+ { SMT_P1020,AC_G, MOFFSS(fddiSMTPORTIndexes), "II" } ,
{ SMT_P1021,AC_G, MOFFSS(fddiSMTMACIndexes), "I" } ,
{ SMT_P1022,AC_G, MOFFSS(fddiSMTBypassPresent), "F" } ,
@@ -117,8 +110,8 @@ static const struct s_p_tab {
/* MIBOperationGrp */
{ SMT_P1032,AC_GROUP } ,
- { SMT_P1033,AC_G, MOFFSA(fddiSMTTimeStamp),"P" } ,
- { SMT_P1034,AC_G, MOFFSA(fddiSMTTransitionTimeStamp),"P" } ,
+ { SMT_P1033,AC_G, MOFFSS(fddiSMTTimeStamp),"P" } ,
+ { SMT_P1034,AC_G, MOFFSS(fddiSMTTransitionTimeStamp),"P" } ,
/* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
{ SMT_P1035,AC_G, MOFFSS(fddiSMTSetCount),"4P" } ,
{ SMT_P1036,AC_G, MOFFSS(fddiSMTLastSetStationId),"8" } ,
@@ -129,7 +122,7 @@ static const struct s_p_tab {
* PRIVATE EXTENSIONS
* only accessible locally to get/set passwd
*/
- { SMT_P10F0,AC_GR, MOFFSA(fddiPRPMFPasswd), "8" } ,
+ { SMT_P10F0,AC_GR, MOFFSS(fddiPRPMFPasswd), "8" } ,
{ SMT_P10F1,AC_GR, MOFFSS(fddiPRPMFStation), "8" } ,
#ifdef ESS
{ SMT_P10F2,AC_GR, MOFFSS(fddiESSPayload), "lL" } ,
@@ -245,7 +238,7 @@ static const struct s_p_tab {
{ SMT_P400E,AC_GR, MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
{ SMT_P400F,AC_G, MOFFPS(fddiPORTMacIndicated), "2" } ,
{ SMT_P4010,AC_G, MOFFPS(fddiPORTCurrentPath), "E" } ,
- { SMT_P4011,AC_GR, MOFFPA(fddiPORTRequestedPaths), "l4" } ,
+ { SMT_P4011,AC_GR, MOFFPS(fddiPORTRequestedPaths), "l4" } ,
{ SMT_P4012,AC_G, MOFFPS(fddiPORTMACPlacement), "S" } ,
{ SMT_P4013,AC_G, MOFFPS(fddiPORTAvailablePaths), "B" } ,
{ SMT_P4016,AC_G, MOFFPS(fddiPORTPMDClass), "E" } ,
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 2e26dced13a..43f4c730be4 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -319,6 +319,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
struct skge_port *skge = netdev_priv(dev);
const struct skge_hw *hw = skge->hw;
u32 supported = skge_supported_modes(hw);
+ int err = 0;
if (ecmd->autoneg == AUTONEG_ENABLE) {
ecmd->advertising = supported;
@@ -367,8 +368,14 @@ 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_phy_reset(skge);
+ if (netif_running(dev)) {
+ skge_down(dev);
+ err = skge_up(dev);
+ if (err) {
+ dev_close(dev);
+ return err;
+ }
+ }
return (0);
}
@@ -494,7 +501,7 @@ static int skge_set_ring_param(struct net_device *dev,
struct ethtool_ringparam *p)
{
struct skge_port *skge = netdev_priv(dev);
- int err;
+ int err = 0;
if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE)
@@ -510,7 +517,7 @@ static int skge_set_ring_param(struct net_device *dev,
dev_close(dev);
}
- return 0;
+ return err;
}
static u32 skge_get_msglevel(struct net_device *netdev)
@@ -593,6 +600,7 @@ static int skge_set_pauseparam(struct net_device *dev,
{
struct skge_port *skge = netdev_priv(dev);
struct ethtool_pauseparam old;
+ int err = 0;
skge_get_pauseparam(dev, &old);
@@ -609,8 +617,14 @@ static int skge_set_pauseparam(struct net_device *dev,
skge->flow_control = FLOW_MODE_NONE;
}
- if (netif_running(dev))
- skge_phy_reset(skge);
+ if (netif_running(dev)) {
+ skge_down(dev);
+ err = skge_up(dev);
+ if (err) {
+ dev_close(dev);
+ return err;
+ }
+ }
return 0;
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index e24b25ca1c6..3813d15e2df 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3034,7 +3034,8 @@ 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 & ~sky2_wol_supported(sky2->hw))
+ if ((wol->wolopts & ~sky2_wol_supported(sky2->hw))
+ || !device_can_wakeup(&hw->pdev->dev))
return -EOPNOTSUPP;
sky2->wol = wol->wolopts;
@@ -3045,6 +3046,8 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
+ device_set_wakeup_enable(&hw->pdev->dev, sky2->wol);
+
if (!netif_running(dev))
sky2_wol_init(sky2);
return 0;
@@ -3732,27 +3735,63 @@ static int sky2_get_eeprom_len(struct net_device *dev)
return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
}
-static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
+static int sky2_vpd_wait(const struct sky2_hw *hw, int cap, u16 busy)
{
- u32 val;
+ unsigned long start = jiffies;
- sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+ while ( (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F) == busy) {
+ /* Can take up to 10.6 ms for write */
+ if (time_after(jiffies, start + HZ/4)) {
+ dev_err(&hw->pdev->dev, PFX "VPD cycle timed out");
+ return -ETIMEDOUT;
+ }
+ mdelay(1);
+ }
- do {
- offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR);
- } while (!(offset & PCI_VPD_ADDR_F));
+ return 0;
+}
+
+static int sky2_vpd_read(struct sky2_hw *hw, int cap, void *data,
+ u16 offset, size_t length)
+{
+ int rc = 0;
+
+ while (length > 0) {
+ u32 val;
+
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+ rc = sky2_vpd_wait(hw, cap, 0);
+ if (rc)
+ break;
+
+ val = sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+
+ memcpy(data, &val, min(sizeof(val), length));
+ offset += sizeof(u32);
+ data += sizeof(u32);
+ length -= sizeof(u32);
+ }
- val = sky2_pci_read32(hw, cap + PCI_VPD_DATA);
- return val;
+ return rc;
}
-static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
+static int sky2_vpd_write(struct sky2_hw *hw, int cap, const void *data,
+ u16 offset, unsigned int length)
{
- sky2_pci_write16(hw, cap + PCI_VPD_DATA, val);
- sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
- do {
- offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR);
- } while (offset & PCI_VPD_ADDR_F);
+ unsigned int i;
+ int rc = 0;
+
+ for (i = 0; i < length; i += sizeof(u32)) {
+ u32 val = *(u32 *)(data + i);
+
+ sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+ sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+
+ rc = sky2_vpd_wait(hw, cap, PCI_VPD_ADDR_F);
+ if (rc)
+ break;
+ }
+ return rc;
}
static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
@@ -3760,24 +3799,13 @@ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
{
struct sky2_port *sky2 = netdev_priv(dev);
int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
- int length = eeprom->len;
- u16 offset = eeprom->offset;
if (!cap)
return -EINVAL;
eeprom->magic = SKY2_EEPROM_MAGIC;
- while (length > 0) {
- u32 val = sky2_vpd_read(sky2->hw, cap, offset);
- int n = min_t(int, length, sizeof(val));
-
- memcpy(data, &val, n);
- length -= n;
- data += n;
- offset += n;
- }
- return 0;
+ return sky2_vpd_read(sky2->hw, cap, data, eeprom->offset, eeprom->len);
}
static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
@@ -3785,8 +3813,6 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
{
struct sky2_port *sky2 = netdev_priv(dev);
int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
- int length = eeprom->len;
- u16 offset = eeprom->offset;
if (!cap)
return -EINVAL;
@@ -3794,21 +3820,11 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
if (eeprom->magic != SKY2_EEPROM_MAGIC)
return -EINVAL;
- while (length > 0) {
- u32 val;
- int n = min_t(int, length, sizeof(val));
-
- if (n < sizeof(val))
- val = sky2_vpd_read(sky2->hw, cap, offset);
- memcpy(&val, data, n);
-
- sky2_vpd_write(sky2->hw, cap, offset, val);
+ /* Partial writes not supported */
+ if ((eeprom->offset & 3) || (eeprom->len & 3))
+ return -EINVAL;
- length -= n;
- data += n;
- offset += n;
- }
- return 0;
+ return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
}
@@ -4166,16 +4182,67 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
return err;
}
-static int __devinit pci_wake_enabled(struct pci_dev *dev)
+/*
+ * Read and parse the first part of Vital Product Data
+ */
+#define VPD_SIZE 128
+#define VPD_MAGIC 0x82
+
+static void __devinit sky2_vpd_info(struct sky2_hw *hw)
{
- int pm = pci_find_capability(dev, PCI_CAP_ID_PM);
- u16 value;
+ int cap = pci_find_capability(hw->pdev, PCI_CAP_ID_VPD);
+ const u8 *p;
+ u8 *vpd_buf = NULL;
+ u16 len;
+ static struct vpd_tag {
+ char tag[2];
+ char *label;
+ } vpd_tags[] = {
+ { "PN", "Part Number" },
+ { "EC", "Engineering Level" },
+ { "MN", "Manufacturer" },
+ };
- if (!pm)
- return 0;
- if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value))
- return 0;
- return value & PCI_PM_CTRL_PME_ENABLE;
+ if (!cap)
+ goto out;
+
+ vpd_buf = kmalloc(VPD_SIZE, GFP_KERNEL);
+ if (!vpd_buf)
+ goto out;
+
+ if (sky2_vpd_read(hw, cap, vpd_buf, 0, VPD_SIZE))
+ goto out;
+
+ if (vpd_buf[0] != VPD_MAGIC)
+ goto out;
+ len = vpd_buf[1];
+ if (len == 0 || len > VPD_SIZE - 4)
+ goto out;
+ p = vpd_buf + 3;
+ dev_info(&hw->pdev->dev, "%.*s\n", len, p);
+ p += len;
+
+ while (p < vpd_buf + VPD_SIZE - 4) {
+ int i;
+
+ if (!memcmp("RW", p, 2)) /* end marker */
+ break;
+
+ len = p[2];
+ if (len > (p - vpd_buf) - 4)
+ break;
+
+ for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) {
+ if (!memcmp(vpd_tags[i].tag, p, 2)) {
+ printk(KERN_DEBUG " %s: %.*s\n",
+ vpd_tags[i].label, len, p + 3);
+ break;
+ }
+ }
+ p += len + 3;
+ }
+out:
+ kfree(vpd_buf);
}
/* This driver supports yukon2 chipset only */
@@ -4238,7 +4305,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
}
}
- wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0;
+ wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
err = -ENOMEM;
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
@@ -4276,13 +4343,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
if (err)
goto err_out_iounmap;
- dev_info(&pdev->dev, "v%s addr 0x%llx irq %d Yukon-2 %s rev %d\n",
- DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0),
- pdev->irq, sky2_name(hw->chip_id, buf1, sizeof(buf1)),
- hw->chip_rev);
+ dev_info(&pdev->dev, "Yukon-2 %s chip revision %d\n",
+ sky2_name(hw->chip_id, buf1, sizeof(buf1)), hw->chip_rev);
sky2_reset(hw);
+ sky2_vpd_info(hw);
+
dev = sky2_init_netdev(hw, 0, using_dac, wol_default);
if (!dev) {
err = -ENOMEM;
@@ -4533,6 +4600,8 @@ static struct pci_driver sky2_driver = {
static int __init sky2_init_module(void)
{
+ pr_info(PFX "driver version " DRV_VERSION "\n");
+
sky2_debug_init();
return pci_register_driver(&sky2_driver);
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index c5871624f97..8aa7460ef0e 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -183,7 +183,7 @@ static void smc911x_reset(struct net_device *dev)
unsigned int reg, timeout=0, resets=1;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
/* Take out of PM setting first */
if ((SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_) == 0) {
@@ -272,7 +272,7 @@ static void smc911x_enable(struct net_device *dev)
unsigned mask, cfg, cr;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
SMC_SET_MAC_ADDR(lp, dev->dev_addr);
@@ -329,7 +329,7 @@ static void smc911x_shutdown(struct net_device *dev)
unsigned cr;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __func__);
/* Disable IRQ's */
SMC_SET_INT_EN(lp, 0);
@@ -348,7 +348,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
struct smc911x_local *lp = netdev_priv(dev);
unsigned int fifo_count, timeout, reg;
- DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __func__);
fifo_count = SMC_GET_RX_FIFO_INF(lp) & 0xFFFF;
if (fifo_count <= 4) {
/* Manually dump the packet data */
@@ -382,7 +382,7 @@ static inline void smc911x_rcv(struct net_device *dev)
unsigned char *data;
DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
status = SMC_GET_RX_STS_FIFO(lp);
DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n",
dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff);
@@ -460,7 +460,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev)
unsigned char *buf;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __func__);
BUG_ON(lp->pending_tx_skb == NULL);
skb = lp->pending_tx_skb;
@@ -524,7 +524,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
BUG_ON(lp->pending_tx_skb != NULL);
@@ -596,7 +596,7 @@ static void smc911x_tx(struct net_device *dev)
unsigned int tx_status;
DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
/* Collect the TX status */
while (((SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
@@ -647,7 +647,7 @@ static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg)
SMC_GET_MII(lp, phyreg, phyaddr, phydata);
DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n",
- __FUNCTION__, phyaddr, phyreg, phydata);
+ __func__, phyaddr, phyreg, phydata);
return phydata;
}
@@ -661,7 +661,7 @@ static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg,
struct smc911x_local *lp = netdev_priv(dev);
DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
- __FUNCTION__, phyaddr, phyreg, phydata);
+ __func__, phyaddr, phyreg, phydata);
SMC_SET_MII(lp, phyreg, phyaddr, phydata);
}
@@ -676,7 +676,7 @@ static void smc911x_phy_detect(struct net_device *dev)
int phyaddr;
unsigned int cfg, id1, id2;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
lp->phy_type = 0;
@@ -685,8 +685,10 @@ static void smc911x_phy_detect(struct net_device *dev)
* PHY#1 to PHY#31, and then PHY#0 last.
*/
switch(lp->version) {
- case 0x115:
- case 0x117:
+ case CHIP_9115:
+ case CHIP_9117:
+ case CHIP_9215:
+ case CHIP_9217:
cfg = SMC_GET_HW_CFG(lp);
if (cfg & HW_CFG_EXT_PHY_DET_) {
cfg &= ~HW_CFG_PHY_CLK_SEL_;
@@ -722,6 +724,9 @@ static void smc911x_phy_detect(struct net_device *dev)
break;
}
}
+ if (phyaddr < 32)
+ /* Found an external PHY */
+ break;
}
default:
/* Internal media only */
@@ -746,7 +751,7 @@ static int smc911x_phy_fixed(struct net_device *dev)
int phyaddr = lp->mii.phy_id;
int bmcr;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
/* Enter Link Disable state */
SMC_GET_PHY_BMCR(lp, phyaddr, bmcr);
@@ -793,7 +798,7 @@ static int smc911x_phy_reset(struct net_device *dev, int phy)
unsigned long flags;
unsigned int reg;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__);
spin_lock_irqsave(&lp->lock, flags);
reg = SMC_GET_PMT_CTRL(lp);
@@ -852,7 +857,7 @@ static void smc911x_phy_check_media(struct net_device *dev, int init)
int phyaddr = lp->mii.phy_id;
unsigned int bmcr, cr;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
/* duplex state has changed */
@@ -892,7 +897,7 @@ static void smc911x_phy_configure(struct work_struct *work)
int status;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__);
/*
* We should not be called if phy_type is zero.
@@ -985,7 +990,7 @@ static void smc911x_phy_interrupt(struct net_device *dev)
int phyaddr = lp->mii.phy_id;
int status;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
if (lp->phy_type == 0)
return;
@@ -1013,7 +1018,7 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id)
unsigned int rx_overrun=0, cr, pkts;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
spin_lock_irqsave(&lp->lock, flags);
@@ -1174,8 +1179,6 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore(&lp->lock, flags);
- DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
-
return IRQ_HANDLED;
}
@@ -1188,7 +1191,7 @@ smc911x_tx_dma_irq(int dma, void *data)
struct sk_buff *skb = lp->current_tx_skb;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name);
/* Clear the DMA interrupt sources */
@@ -1224,7 +1227,7 @@ smc911x_rx_dma_irq(int dma, void *data)
unsigned long flags;
unsigned int pkts;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name);
/* Clear the DMA interrupt sources */
SMC_DMA_ACK_IRQ(dev, dma);
@@ -1272,7 +1275,7 @@ static void smc911x_timeout(struct net_device *dev)
int status, mask;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
spin_lock_irqsave(&lp->lock, flags);
status = SMC_GET_INT(lp);
@@ -1310,7 +1313,7 @@ static void smc911x_set_multicast_list(struct net_device *dev)
unsigned int mcr, update_multicast = 0;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
spin_lock_irqsave(&lp->lock, flags);
SMC_GET_MAC_CR(lp, mcr);
@@ -1412,7 +1415,7 @@ smc911x_open(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
/*
* Check that the address is valid. If its not, refuse
@@ -1420,7 +1423,7 @@ smc911x_open(struct net_device *dev)
* address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
*/
if (!is_valid_ether_addr(dev->dev_addr)) {
- PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
+ PRINTK("%s: no valid ethernet hw addr\n", __func__);
return -EINVAL;
}
@@ -1449,7 +1452,7 @@ static int smc911x_close(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
netif_stop_queue(dev);
netif_carrier_off(dev);
@@ -1483,7 +1486,7 @@ smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
int ret, status;
unsigned long flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
cmd->maxtxpkt = 1;
cmd->maxrxpkt = 1;
@@ -1621,7 +1624,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) {
if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) {
PRINTK("%s: %s timeout waiting for EEPROM to respond\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -EFAULT;
}
mdelay(1);
@@ -1629,7 +1632,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
}
if (timeout == 0) {
PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -ETIMEDOUT;
}
return 0;
@@ -1742,7 +1745,7 @@ static int __init smc911x_findirq(struct net_device *dev)
int timeout = 20;
unsigned long cookie;
- DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
cookie = probe_irq_on();
@@ -1808,7 +1811,7 @@ static int __init smc911x_probe(struct net_device *dev)
const char *version_string;
unsigned long irq_flags;
- DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
/* First, see if the endian word is recognized */
val = SMC_GET_BYTE_TEST(lp);
@@ -2058,7 +2061,7 @@ static int smc911x_drv_probe(struct platform_device *pdev)
unsigned int *addr;
int ret;
- DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
@@ -2129,7 +2132,7 @@ static int smc911x_drv_remove(struct platform_device *pdev)
struct smc911x_local *lp = netdev_priv(ndev);
struct resource *res;
- DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
@@ -2159,7 +2162,7 @@ static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state)
struct net_device *ndev = platform_get_drvdata(dev);
struct smc911x_local *lp = netdev_priv(ndev);
- DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
if (ndev) {
if (netif_running(ndev)) {
netif_device_detach(ndev);
@@ -2177,7 +2180,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
{
struct net_device *ndev = platform_get_drvdata(dev);
- DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+ DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__);
if (ndev) {
struct smc911x_local *lp = netdev_priv(ndev);
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index 2abfc284519..bf6240f23f5 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -666,10 +666,13 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
#define LAN911X_INTERNAL_PHY_ID (0x0007C000)
/* Chip ID values */
-#define CHIP_9115 0x115
-#define CHIP_9116 0x116
-#define CHIP_9117 0x117
-#define CHIP_9118 0x118
+#define CHIP_9115 0x0115
+#define CHIP_9116 0x0116
+#define CHIP_9117 0x0117
+#define CHIP_9118 0x0118
+#define CHIP_9215 0x115A
+#define CHIP_9217 0x117A
+#define CHIP_9218 0x118A
struct chip_id {
u16 id;
@@ -681,6 +684,9 @@ static const struct chip_id chip_ids[] = {
{ CHIP_9116, "LAN9116" },
{ CHIP_9117, "LAN9117" },
{ CHIP_9118, "LAN9118" },
+ { CHIP_9215, "LAN9215" },
+ { CHIP_9217, "LAN9217" },
+ { CHIP_9218, "LAN9218" },
{ 0, NULL },
};
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 24768c10cad..c70870e0fd6 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -270,7 +270,7 @@ static void smc_reset(struct net_device *dev)
unsigned int ctl, cfg;
struct sk_buff *pending_skb;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
/* Disable all interrupts, block TX tasklet */
spin_lock_irq(&lp->lock);
@@ -363,7 +363,7 @@ static void smc_enable(struct net_device *dev)
void __iomem *ioaddr = lp->base;
int mask;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
/* see the header file for options in TCR/RCR DEFAULT */
SMC_SELECT_BANK(lp, 0);
@@ -397,7 +397,7 @@ static void smc_shutdown(struct net_device *dev)
void __iomem *ioaddr = lp->base;
struct sk_buff *pending_skb;
- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+ DBG(2, "%s: %s\n", CARDNAME, __func__);
/* no more interrupts for me */
spin_lock_irq(&lp->lock);
@@ -430,7 +430,7 @@ static inline void smc_rcv(struct net_device *dev)
void __iomem *ioaddr = lp->base;
unsigned int packet_number, status, packet_len;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
packet_number = SMC_GET_RXFIFO(lp);
if (unlikely(packet_number & RXFIFO_REMPTY)) {
@@ -577,7 +577,7 @@ static void smc_hardware_send_pkt(unsigned long data)
unsigned int packet_no, len;
unsigned char *buf;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
if (!smc_special_trylock(&lp->lock)) {
netif_stop_queue(dev);
@@ -662,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
void __iomem *ioaddr = lp->base;
unsigned int numPages, poll_count, status;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
BUG_ON(lp->pending_tx_skb != NULL);
@@ -734,7 +734,7 @@ static void smc_tx(struct net_device *dev)
void __iomem *ioaddr = lp->base;
unsigned int saved_packet, packet_no, tx_status, pkt_len;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
/* If the TX FIFO is empty then nothing to do */
packet_no = SMC_GET_TXFIFO(lp);
@@ -856,7 +856,7 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
- __FUNCTION__, phyaddr, phyreg, phydata);
+ __func__, phyaddr, phyreg, phydata);
SMC_SELECT_BANK(lp, 2);
return phydata;
@@ -883,7 +883,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
- __FUNCTION__, phyaddr, phyreg, phydata);
+ __func__, phyaddr, phyreg, phydata);
SMC_SELECT_BANK(lp, 2);
}
@@ -896,7 +896,7 @@ static void smc_phy_detect(struct net_device *dev)
struct smc_local *lp = netdev_priv(dev);
int phyaddr;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
lp->phy_type = 0;
@@ -935,7 +935,7 @@ static int smc_phy_fixed(struct net_device *dev)
int phyaddr = lp->mii.phy_id;
int bmcr, cfg1;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
/* Enter Link Disable state */
cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG);
@@ -1168,7 +1168,7 @@ static void smc_phy_interrupt(struct net_device *dev)
int phyaddr = lp->mii.phy_id;
int phy18;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
if (lp->phy_type == 0)
return;
@@ -1236,7 +1236,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
int status, mask, timeout, card_stats;
int saved_pointer;
- DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(3, "%s: %s\n", dev->name, __func__);
spin_lock(&lp->lock);
@@ -1358,7 +1358,7 @@ static void smc_timeout(struct net_device *dev)
void __iomem *ioaddr = lp->base;
int status, mask, eph_st, meminfo, fifo;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
spin_lock_irq(&lp->lock);
status = SMC_GET_INT(lp);
@@ -1402,7 +1402,7 @@ static void smc_set_multicast_list(struct net_device *dev)
unsigned char multicast_table[8];
int update_multicast = 0;
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
if (dev->flags & IFF_PROMISC) {
DBG(2, "%s: RCR_PRMS\n", dev->name);
@@ -1505,7 +1505,7 @@ smc_open(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
/*
* Check that the address is valid. If its not, refuse
@@ -1513,14 +1513,16 @@ smc_open(struct net_device *dev)
* address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
*/
if (!is_valid_ether_addr(dev->dev_addr)) {
- PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
+ PRINTK("%s: no valid ethernet hw addr\n", __func__);
return -EINVAL;
}
/* Setup the default Register Modes */
lp->tcr_cur_mode = TCR_DEFAULT;
lp->rcr_cur_mode = RCR_DEFAULT;
- lp->rpc_cur_mode = RPC_DEFAULT;
+ lp->rpc_cur_mode = RPC_DEFAULT |
+ lp->cfg.leda << RPC_LSXA_SHFT |
+ lp->cfg.ledb << RPC_LSXB_SHFT;
/*
* If we are not using a MII interface, we need to
@@ -1557,7 +1559,7 @@ static int smc_close(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ DBG(2, "%s: %s\n", dev->name, __func__);
netif_stop_queue(dev);
netif_carrier_off(dev);
@@ -1700,7 +1702,7 @@ static int __init smc_findirq(struct smc_local *lp)
int timeout = 20;
unsigned long cookie;
- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+ DBG(2, "%s: %s\n", CARDNAME, __func__);
cookie = probe_irq_on();
@@ -1778,7 +1780,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
const char *version_string;
DECLARE_MAC_BUF(mac);
- DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+ DBG(2, "%s: %s\n", CARDNAME, __func__);
/* First, see if the high byte is 0x33 */
val = SMC_CURRENT_BANK(lp);
@@ -1961,7 +1963,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
if (dev->dma != (unsigned char)-1)
printk(" DMA %d", dev->dma);
- printk("%s%s\n", nowait ? " [nowait]" : "",
+ printk("%s%s\n",
+ lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "",
THROTTLE_TX_PKTS ? " [throttle_tx]" : "");
if (!is_valid_ether_addr(dev->dev_addr)) {
@@ -2157,6 +2160,11 @@ static int smc_drv_probe(struct platform_device *pdev)
lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
}
+ if (!lp->cfg.leda && !lp->cfg.ledb) {
+ lp->cfg.leda = RPC_LSA_DEFAULT;
+ lp->cfg.ledb = RPC_LSB_DEFAULT;
+ }
+
ndev->dma = (unsigned char)-1;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 997e7f1d5c6..a07cc9351c6 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -43,7 +43,8 @@
#if defined(CONFIG_ARCH_LUBBOCK) ||\
defined(CONFIG_MACH_MAINSTONE) ||\
defined(CONFIG_MACH_ZYLONITE) ||\
- defined(CONFIG_MACH_LITTLETON)
+ defined(CONFIG_MACH_LITTLETON) ||\
+ defined(CONFIG_ARCH_VIPER)
#include <asm/mach-types.h>
@@ -446,6 +447,8 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define SMC_CAN_USE_32BIT 1
#define SMC_NOWAIT 1
+#define SMC_IO_SHIFT (lp->io_shift)
+
#define SMC_inb(a, r) readb((a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
@@ -778,14 +781,6 @@ smc_pxa_dma_irq(int dma, void *dummy)
#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
-#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
-#define RPC_LED_RES (0x01) // LED = Reserved
-#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
-#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
-#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
-#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
-#define RPC_LED_TX (0x06) // LED = TX packet occurred
-#define RPC_LED_RX (0x07) // LED = RX packet occurred
#ifndef RPC_LSA_DEFAULT
#define RPC_LSA_DEFAULT RPC_LED_100
@@ -794,7 +789,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
#define RPC_LSB_DEFAULT RPC_LED_FD
#endif
-#define RPC_DEFAULT (RPC_ANEG | (RPC_LSA_DEFAULT << RPC_LSXA_SHFT) | (RPC_LSB_DEFAULT << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+#define RPC_DEFAULT (RPC_ANEG | RPC_SPEED | RPC_DPLX)
/* Bank 0 0x0C is reserved */
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 0e4a88d1632..018d0fca942 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1,7 +1,6 @@
-/* $Id: sunbmac.c,v 1.30 2002/01/15 06:48:55 davem Exp $
- * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
+/* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
*
- * Copyright (C) 1997, 1998, 1999, 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1997, 1998, 1999, 2003, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -23,6 +22,9 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/auxio.h>
#include <asm/byteorder.h>
@@ -32,15 +34,14 @@
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/pgtable.h>
-#include <asm/sbus.h>
#include <asm/system.h>
#include "sunbmac.h"
#define DRV_NAME "sunbmac"
-#define DRV_VERSION "2.0"
-#define DRV_RELDATE "11/24/03"
-#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
+#define DRV_VERSION "2.1"
+#define DRV_RELDATE "August 26, 2008"
+#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)"
static char version[] =
DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
@@ -96,8 +97,8 @@ static int qec_global_reset(void __iomem *gregs)
static void qec_init(struct bigmac *bp)
{
+ struct of_device *qec_op = bp->qec_op;
void __iomem *gregs = bp->gregs;
- struct sbus_dev *qec_sdev = bp->qec_sdev;
u8 bsizes = bp->bigmac_bursts;
u32 regval;
@@ -112,13 +113,13 @@ static void qec_init(struct bigmac *bp)
sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE);
/* All of memsize is given to bigmac. */
- sbus_writel(qec_sdev->reg_addrs[1].reg_size,
+ sbus_writel(resource_size(&qec_op->resource[1]),
gregs + GLOB_MSIZE);
/* Half to the transmitter, half to the receiver. */
- sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1,
+ sbus_writel(resource_size(&qec_op->resource[1]) >> 1,
gregs + GLOB_TSIZE);
- sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1,
+ sbus_writel(resource_size(&qec_op->resource[1]) >> 1,
gregs + GLOB_RSIZE);
}
@@ -239,9 +240,10 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
skb_reserve(skb, 34);
bb->be_rxd[i].rx_addr =
- sbus_map_single(bp->bigmac_sdev, skb->data,
- RX_BUF_ALLOC_SIZE - 34,
- SBUS_DMA_FROMDEVICE);
+ dma_map_single(&bp->bigmac_op->dev,
+ skb->data,
+ RX_BUF_ALLOC_SIZE - 34,
+ DMA_FROM_DEVICE);
bb->be_rxd[i].rx_flags =
(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
}
@@ -776,9 +778,9 @@ static void bigmac_tx(struct bigmac *bp)
skb = bp->tx_skbs[elem];
bp->enet_stats.tx_packets++;
bp->enet_stats.tx_bytes += skb->len;
- sbus_unmap_single(bp->bigmac_sdev,
- this->tx_addr, skb->len,
- SBUS_DMA_TODEVICE);
+ dma_unmap_single(&bp->bigmac_op->dev,
+ this->tx_addr, skb->len,
+ DMA_TO_DEVICE);
DTX(("skb(%p) ", skb));
bp->tx_skbs[elem] = NULL;
@@ -831,18 +833,19 @@ static void bigmac_rx(struct bigmac *bp)
drops++;
goto drop_it;
}
- sbus_unmap_single(bp->bigmac_sdev,
- this->rx_addr,
- RX_BUF_ALLOC_SIZE - 34,
- SBUS_DMA_FROMDEVICE);
+ dma_unmap_single(&bp->bigmac_op->dev,
+ this->rx_addr,
+ RX_BUF_ALLOC_SIZE - 34,
+ DMA_FROM_DEVICE);
bp->rx_skbs[elem] = new_skb;
new_skb->dev = bp->dev;
skb_put(new_skb, ETH_FRAME_LEN);
skb_reserve(new_skb, 34);
- this->rx_addr = sbus_map_single(bp->bigmac_sdev,
- new_skb->data,
- RX_BUF_ALLOC_SIZE - 34,
- SBUS_DMA_FROMDEVICE);
+ this->rx_addr =
+ dma_map_single(&bp->bigmac_op->dev,
+ new_skb->data,
+ RX_BUF_ALLOC_SIZE - 34,
+ DMA_FROM_DEVICE);
this->rx_flags =
(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
@@ -857,13 +860,13 @@ static void bigmac_rx(struct bigmac *bp)
}
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
- sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
- this->rx_addr, len,
- SBUS_DMA_FROMDEVICE);
+ dma_sync_single_for_cpu(&bp->bigmac_op->dev,
+ this->rx_addr, len,
+ DMA_FROM_DEVICE);
skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
- sbus_dma_sync_single_for_device(bp->bigmac_sdev,
- this->rx_addr, len,
- SBUS_DMA_FROMDEVICE);
+ dma_sync_single_for_device(&bp->bigmac_op->dev,
+ this->rx_addr, len,
+ DMA_FROM_DEVICE);
/* Reuse original ring buffer. */
this->rx_flags =
@@ -959,7 +962,8 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 mapping;
len = skb->len;
- mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len, SBUS_DMA_TODEVICE);
+ mapping = dma_map_single(&bp->bigmac_op->dev, skb->data,
+ len, DMA_TO_DEVICE);
/* Avoid a race... */
spin_lock_irq(&bp->lock);
@@ -1051,12 +1055,8 @@ static void bigmac_set_multicast(struct net_device *dev)
/* Ethtool support... */
static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct bigmac *bp = dev->priv;
-
strcpy(info->driver, "sunbmac");
strcpy(info->version, "2.0");
- sprintf(info->bus_info, "SBUS:%d",
- bp->qec_sdev->slot);
}
static u32 bigmac_get_link(struct net_device *dev)
@@ -1075,14 +1075,15 @@ static const struct ethtool_ops bigmac_ethtool_ops = {
.get_link = bigmac_get_link,
};
-static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
+static int __devinit bigmac_ether_init(struct of_device *op,
+ struct of_device *qec_op)
{
- struct net_device *dev;
static int version_printed;
- struct bigmac *bp;
+ struct net_device *dev;
u8 bsizes, bsizes_more;
- int i;
DECLARE_MAC_BUF(mac);
+ struct bigmac *bp;
+ int i;
/* Get a new device struct for this interface. */
dev = alloc_etherdev(sizeof(struct bigmac));
@@ -1092,32 +1093,21 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
- dev->base_addr = (long) qec_sdev;
for (i = 0; i < 6; i++)
dev->dev_addr[i] = idprom->id_ethaddr[i];
/* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */
- bp = dev->priv;
- bp->qec_sdev = qec_sdev;
- bp->bigmac_sdev = qec_sdev->child;
+ bp = netdev_priv(dev);
+ bp->qec_op = qec_op;
+ bp->bigmac_op = op;
- SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev);
+ SET_NETDEV_DEV(dev, &op->dev);
spin_lock_init(&bp->lock);
- /* Verify the registers we expect, are actually there. */
- if ((bp->bigmac_sdev->num_registers != 3) ||
- (bp->qec_sdev->num_registers != 2)) {
- printk(KERN_ERR "BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n",
- bp->qec_sdev->num_registers,
- bp->bigmac_sdev->num_registers);
- printk(KERN_ERR "BIGMAC: Would you like that for here or to go?\n");
- goto fail_and_cleanup;
- }
-
/* Map in QEC global control registers. */
- bp->gregs = sbus_ioremap(&bp->qec_sdev->resource[0], 0,
- GLOB_REG_SIZE, "BigMAC QEC GLobal Regs");
+ bp->gregs = of_ioremap(&qec_op->resource[0], 0,
+ GLOB_REG_SIZE, "BigMAC QEC GLobal Regs");
if (!bp->gregs) {
printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n");
goto fail_and_cleanup;
@@ -1134,13 +1124,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
goto fail_and_cleanup;
/* Get supported SBUS burst sizes. */
- bsizes = prom_getintdefault(bp->qec_sdev->prom_node,
- "burst-sizes",
- 0xff);
-
- bsizes_more = prom_getintdefault(bp->qec_sdev->bus->prom_node,
- "burst-sizes",
- 0xff);
+ bsizes = of_getintprop_default(qec_op->node, "burst-sizes", 0xff);
+ bsizes_more = of_getintprop_default(qec_op->node, "burst-sizes", 0xff);
bsizes &= 0xff;
if (bsizes_more != 0xff)
@@ -1154,16 +1139,16 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
qec_init(bp);
/* Map in the BigMAC channel registers. */
- bp->creg = sbus_ioremap(&bp->bigmac_sdev->resource[0], 0,
- CREG_REG_SIZE, "BigMAC QEC Channel Regs");
+ bp->creg = of_ioremap(&op->resource[0], 0,
+ CREG_REG_SIZE, "BigMAC QEC Channel Regs");
if (!bp->creg) {
printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n");
goto fail_and_cleanup;
}
/* Map in the BigMAC control registers. */
- bp->bregs = sbus_ioremap(&bp->bigmac_sdev->resource[1], 0,
- BMAC_REG_SIZE, "BigMAC Primary Regs");
+ bp->bregs = of_ioremap(&op->resource[1], 0,
+ BMAC_REG_SIZE, "BigMAC Primary Regs");
if (!bp->bregs) {
printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n");
goto fail_and_cleanup;
@@ -1172,8 +1157,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
/* Map in the BigMAC transceiver registers, this is how you poke at
* the BigMAC's PHY.
*/
- bp->tregs = sbus_ioremap(&bp->bigmac_sdev->resource[2], 0,
- TCVR_REG_SIZE, "BigMAC Transceiver Regs");
+ bp->tregs = of_ioremap(&op->resource[2], 0,
+ TCVR_REG_SIZE, "BigMAC Transceiver Regs");
if (!bp->tregs) {
printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n");
goto fail_and_cleanup;
@@ -1183,17 +1168,17 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
bigmac_stop(bp);
/* Allocate transmit/receive descriptor DVMA block. */
- bp->bmac_block = sbus_alloc_consistent(bp->bigmac_sdev,
- PAGE_SIZE,
- &bp->bblock_dvma);
+ bp->bmac_block = dma_alloc_coherent(&bp->bigmac_op->dev,
+ PAGE_SIZE,
+ &bp->bblock_dvma, GFP_ATOMIC);
if (bp->bmac_block == NULL || bp->bblock_dvma == 0) {
printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n");
goto fail_and_cleanup;
}
/* Get the board revision of this BigMAC. */
- bp->board_rev = prom_getintdefault(bp->bigmac_sdev->prom_node,
- "board-version", 1);
+ bp->board_rev = of_getintprop_default(bp->bigmac_op->node,
+ "board-version", 1);
/* Init auto-negotiation timer state. */
init_timer(&bp->bigmac_timer);
@@ -1217,7 +1202,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
dev->watchdog_timeo = 5*HZ;
/* Finish net device registration. */
- dev->irq = bp->bigmac_sdev->irqs[0];
+ dev->irq = bp->bigmac_op->irqs[0];
dev->dma = 0;
if (register_netdev(dev)) {
@@ -1225,7 +1210,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
goto fail_and_cleanup;
}
- dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp);
+ dev_set_drvdata(&bp->bigmac_op->dev, bp);
printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n",
dev->name, print_mac(mac, dev->dev_addr));
@@ -1236,66 +1221,67 @@ fail_and_cleanup:
/* Something went wrong, undo whatever we did so far. */
/* Free register mappings if any. */
if (bp->gregs)
- sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
+ of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE);
if (bp->creg)
- sbus_iounmap(bp->creg, CREG_REG_SIZE);
+ of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE);
if (bp->bregs)
- sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
+ of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE);
if (bp->tregs)
- sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
+ of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE);
if (bp->bmac_block)
- sbus_free_consistent(bp->bigmac_sdev,
- PAGE_SIZE,
- bp->bmac_block,
- bp->bblock_dvma);
+ dma_free_coherent(&bp->bigmac_op->dev,
+ PAGE_SIZE,
+ bp->bmac_block,
+ bp->bblock_dvma);
/* This also frees the co-located 'dev->priv' */
free_netdev(dev);
return -ENODEV;
}
-/* QEC can be the parent of either QuadEthernet or
- * a BigMAC. We want the latter.
+/* QEC can be the parent of either QuadEthernet or a BigMAC. We want
+ * the latter.
*/
-static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit bigmac_sbus_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
+ struct device *parent = op->dev.parent;
+ struct of_device *qec_op;
- if (!strcmp(dp->name, "be"))
- sdev = sdev->parent;
+ qec_op = to_of_device(parent);
- return bigmac_ether_init(sdev);
+ return bigmac_ether_init(op, qec_op);
}
-static int __devexit bigmac_sbus_remove(struct of_device *dev)
+static int __devexit bigmac_sbus_remove(struct of_device *op)
{
- struct bigmac *bp = dev_get_drvdata(&dev->dev);
+ struct bigmac *bp = dev_get_drvdata(&op->dev);
+ struct device *parent = op->dev.parent;
struct net_device *net_dev = bp->dev;
+ struct of_device *qec_op;
- unregister_netdevice(net_dev);
+ qec_op = to_of_device(parent);
- sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
- sbus_iounmap(bp->creg, CREG_REG_SIZE);
- sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
- sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
- sbus_free_consistent(bp->bigmac_sdev,
- PAGE_SIZE,
- bp->bmac_block,
- bp->bblock_dvma);
+ unregister_netdev(net_dev);
+
+ of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE);
+ of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE);
+ of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE);
+ of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE);
+ dma_free_coherent(&op->dev,
+ PAGE_SIZE,
+ bp->bmac_block,
+ bp->bblock_dvma);
free_netdev(net_dev);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id bigmac_sbus_match[] = {
- {
- .name = "qec",
- },
+static const struct of_device_id bigmac_sbus_match[] = {
{
.name = "be",
},
@@ -1313,7 +1299,7 @@ static struct of_platform_driver bigmac_sbus_driver = {
static int __init bigmac_init(void)
{
- return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&bigmac_sbus_driver, &of_bus_type);
}
static void __exit bigmac_exit(void)
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index b563d3c2993..8840bc0b840 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -329,8 +329,8 @@ struct bigmac {
unsigned int timer_ticks;
struct net_device_stats enet_stats;
- struct sbus_dev *qec_sdev;
- struct sbus_dev *bigmac_sdev;
+ struct of_device *qec_op;
+ struct of_device *bigmac_op;
struct net_device *dev;
};
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 7d5561b8241..f860ea15039 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -409,6 +409,7 @@ static int change_mtu(struct net_device *dev, int new_mtu);
static int eeprom_read(void __iomem *ioaddr, int location);
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 value);
+static int mdio_wait_link(struct net_device *dev, int wait);
static int netdev_open(struct net_device *dev);
static void check_duplex(struct net_device *dev);
static void netdev_timer(unsigned long data);
@@ -785,6 +786,24 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
return;
}
+static int mdio_wait_link(struct net_device *dev, int wait)
+{
+ int bmsr;
+ int phy_id;
+ struct netdev_private *np;
+
+ np = netdev_priv(dev);
+ phy_id = np->phys[0];
+
+ do {
+ bmsr = mdio_read(dev, phy_id, MII_BMSR);
+ if (bmsr & 0x0004)
+ return 0;
+ mdelay(1);
+ } while (--wait > 0);
+ return -1;
+}
+
static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
@@ -1393,41 +1412,51 @@ static void netdev_error(struct net_device *dev, int intr_status)
int speed;
if (intr_status & LinkChange) {
- if (np->an_enable) {
- mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
- mii_lpa= mdio_read (dev, np->phys[0], MII_LPA);
- mii_advertise &= mii_lpa;
- printk (KERN_INFO "%s: Link changed: ", dev->name);
- if (mii_advertise & ADVERTISE_100FULL) {
- np->speed = 100;
- printk ("100Mbps, full duplex\n");
- } else if (mii_advertise & ADVERTISE_100HALF) {
- np->speed = 100;
- printk ("100Mbps, half duplex\n");
- } else if (mii_advertise & ADVERTISE_10FULL) {
- np->speed = 10;
- printk ("10Mbps, full duplex\n");
- } else if (mii_advertise & ADVERTISE_10HALF) {
- np->speed = 10;
- printk ("10Mbps, half duplex\n");
- } else
- printk ("\n");
+ if (mdio_wait_link(dev, 10) == 0) {
+ printk(KERN_INFO "%s: Link up\n", dev->name);
+ if (np->an_enable) {
+ mii_advertise = mdio_read(dev, np->phys[0],
+ MII_ADVERTISE);
+ mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+ mii_advertise &= mii_lpa;
+ printk(KERN_INFO "%s: Link changed: ",
+ dev->name);
+ if (mii_advertise & ADVERTISE_100FULL) {
+ np->speed = 100;
+ printk("100Mbps, full duplex\n");
+ } else if (mii_advertise & ADVERTISE_100HALF) {
+ np->speed = 100;
+ printk("100Mbps, half duplex\n");
+ } else if (mii_advertise & ADVERTISE_10FULL) {
+ np->speed = 10;
+ printk("10Mbps, full duplex\n");
+ } else if (mii_advertise & ADVERTISE_10HALF) {
+ np->speed = 10;
+ printk("10Mbps, half duplex\n");
+ } else
+ printk("\n");
+ } else {
+ mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR);
+ speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
+ np->speed = speed;
+ printk(KERN_INFO "%s: Link changed: %dMbps ,",
+ dev->name, speed);
+ printk("%s duplex.\n",
+ (mii_ctl & BMCR_FULLDPLX) ?
+ "full" : "half");
+ }
+ check_duplex(dev);
+ if (np->flowctrl && np->mii_if.full_duplex) {
+ iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
+ ioaddr + MulticastFilter1+2);
+ iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
+ ioaddr + MACCtrl0);
+ }
+ netif_carrier_on(dev);
} else {
- mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR);
- speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
- np->speed = speed;
- printk (KERN_INFO "%s: Link changed: %dMbps ,",
- dev->name, speed);
- printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
- "full" : "half");
- }
- check_duplex (dev);
- if (np->flowctrl && np->mii_if.full_duplex) {
- iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
- ioaddr + MulticastFilter1+2);
- iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
- ioaddr + MACCtrl0);
+ printk(KERN_INFO "%s: Link down\n", dev->name);
+ netif_carrier_off(dev);
}
}
if (intr_status & StatsMax) {
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index b79d5f018f7..f1ebeb5f65b 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -3,7 +3,7 @@
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
*
* Copyright (C) 1996, 1998, 1999, 2002, 2003,
- 2006 David S. Miller (davem@davemloft.net)
+ * 2006, 2008 David S. Miller (davem@davemloft.net)
*
* Changes :
* 2000/11/11 Willy Tarreau <willy AT meta-x.org>
@@ -34,6 +34,7 @@
#include <linux/skbuff.h>
#include <linux/mm.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -41,8 +42,9 @@
#include <asm/byteorder.h>
#ifdef CONFIG_SPARC
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/idprom.h>
-#include <asm/sbus.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/prom.h>
@@ -60,8 +62,8 @@
#include "sunhme.h"
#define DRV_NAME "sunhme"
-#define DRV_VERSION "3.00"
-#define DRV_RELDATE "June 23, 2006"
+#define DRV_VERSION "3.10"
+#define DRV_RELDATE "August 26, 2008"
#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)"
static char version[] =
@@ -251,13 +253,13 @@ static u32 pci_hme_read_desc32(hme32 *p)
#define hme_read_desc32(__hp, __p) \
((__hp)->read_desc32(__p))
#define hme_dma_map(__hp, __ptr, __size, __dir) \
- ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size), (__dir)))
+ ((__hp)->dma_map((__hp)->dma_dev, (__ptr), (__size), (__dir)))
#define hme_dma_unmap(__hp, __addr, __size, __dir) \
- ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size), (__dir)))
+ ((__hp)->dma_unmap((__hp)->dma_dev, (__addr), (__size), (__dir)))
#define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \
- ((__hp)->dma_sync_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir)))
+ ((__hp)->dma_sync_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir)))
#define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \
- ((__hp)->dma_sync_for_device((__hp)->happy_dev, (__addr), (__size), (__dir)))
+ ((__hp)->dma_sync_for_device((__hp)->dma_dev, (__addr), (__size), (__dir)))
#else
#ifdef CONFIG_SBUS
/* SBUS only compilation */
@@ -277,13 +279,13 @@ do { (__txd)->tx_addr = (__force hme32)(u32)(__addr); \
} while(0)
#define hme_read_desc32(__hp, __p) ((__force u32)(hme32)*(__p))
#define hme_dma_map(__hp, __ptr, __size, __dir) \
- sbus_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
+ dma_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir))
#define hme_dma_unmap(__hp, __addr, __size, __dir) \
- sbus_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+ dma_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir))
#define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \
- sbus_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir))
+ dma_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir))
#define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \
- sbus_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir))
+ dma_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir))
#else
/* PCI only compilation */
#define hme_write32(__hp, __reg, __val) \
@@ -305,36 +307,17 @@ static inline u32 hme_read_desc32(struct happy_meal *hp, hme32 *p)
return le32_to_cpup((__le32 *)p);
}
#define hme_dma_map(__hp, __ptr, __size, __dir) \
- pci_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
+ pci_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir))
#define hme_dma_unmap(__hp, __addr, __size, __dir) \
- pci_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+ pci_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir))
#define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \
- pci_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir))
+ pci_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir))
#define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \
- pci_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir))
+ pci_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir))
#endif
#endif
-#ifdef SBUS_DMA_BIDIRECTIONAL
-# define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL
-#else
-# define DMA_BIDIRECTIONAL 0
-#endif
-
-#ifdef SBUS_DMA_FROMDEVICE
-# define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE
-#else
-# define DMA_TODEVICE 1
-#endif
-
-#ifdef SBUS_DMA_TODEVICE
-# define DMA_TODEVICE SBUS_DMA_TODEVICE
-#else
-# define DMA_FROMDEVICE 2
-#endif
-
-
/* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */
static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit)
{
@@ -1224,7 +1207,8 @@ static void happy_meal_clean_rings(struct happy_meal *hp)
rxd = &hp->happy_block->happy_meal_rxd[i];
dma_addr = hme_read_desc32(hp, &rxd->rx_addr);
- hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
+ dma_unmap_single(hp->dma_dev, dma_addr,
+ RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
hp->rx_skbs[i] = NULL;
}
@@ -1242,10 +1226,10 @@ static void happy_meal_clean_rings(struct happy_meal *hp)
for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
txd = &hp->happy_block->happy_meal_txd[i];
dma_addr = hme_read_desc32(hp, &txd->tx_addr);
- hme_dma_unmap(hp, dma_addr,
- (hme_read_desc32(hp, &txd->tx_flags)
- & TXFLAG_SIZE),
- DMA_TODEVICE);
+ dma_unmap_single(hp->dma_dev, dma_addr,
+ (hme_read_desc32(hp, &txd->tx_flags)
+ & TXFLAG_SIZE),
+ DMA_TO_DEVICE);
if (frag != skb_shinfo(skb)->nr_frags)
i++;
@@ -1287,7 +1271,8 @@ static void happy_meal_init_rings(struct happy_meal *hp)
skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, &hb->happy_meal_rxd[i],
(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
- hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
+ dma_map_single(hp->dma_dev, skb->data, RX_BUF_ALLOC_SIZE,
+ DMA_FROM_DEVICE));
skb_reserve(skb, RX_OFFSET);
}
@@ -1593,7 +1578,7 @@ static int happy_meal_init(struct happy_meal *hp)
if ((hp->happy_bursts & DMA_BURST64) &&
((hp->happy_flags & HFLAG_PCI) != 0
#ifdef CONFIG_SBUS
- || sbus_can_burst64(hp->happy_dev)
+ || sbus_can_burst64()
#endif
|| 0)) {
u32 gcfg = GREG_CFG_BURST64;
@@ -1603,11 +1588,13 @@ static int happy_meal_init(struct happy_meal *hp)
* do not. -DaveM
*/
#ifdef CONFIG_SBUS
- if ((hp->happy_flags & HFLAG_PCI) == 0 &&
- sbus_can_dma_64bit(hp->happy_dev)) {
- sbus_set_sbus64(hp->happy_dev,
- hp->happy_bursts);
- gcfg |= GREG_CFG_64BIT;
+ if ((hp->happy_flags & HFLAG_PCI) == 0) {
+ struct of_device *op = hp->happy_dev;
+ if (sbus_can_dma_64bit()) {
+ sbus_set_sbus64(&op->dev,
+ hp->happy_bursts);
+ gcfg |= GREG_CFG_64BIT;
+ }
}
#endif
@@ -1966,7 +1953,7 @@ static void happy_meal_tx(struct happy_meal *hp)
dma_len = hme_read_desc32(hp, &this->tx_flags);
dma_len &= TXFLAG_SIZE;
- hme_dma_unmap(hp, dma_addr, dma_len, DMA_TODEVICE);
+ dma_unmap_single(hp->dma_dev, dma_addr, dma_len, DMA_TO_DEVICE);
elem = NEXT_TX(elem);
this = &txbase[elem];
@@ -2044,13 +2031,14 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
drops++;
goto drop_it;
}
- hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
+ dma_unmap_single(hp->dma_dev, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE);
hp->rx_skbs[elem] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
hme_write_rxd(hp, this,
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
- hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
+ dma_map_single(hp->dma_dev, new_skb->data, RX_BUF_ALLOC_SIZE,
+ DMA_FROM_DEVICE));
skb_reserve(new_skb, RX_OFFSET);
/* Trim the original skb for the netif. */
@@ -2065,10 +2053,9 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
- hme_dma_sync_for_cpu(hp, dma_addr, len, DMA_FROMDEVICE);
+ dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
skb_copy_from_linear_data(skb, copy_skb->data, len);
- hme_dma_sync_for_device(hp, dma_addr, len, DMA_FROMDEVICE);
-
+ dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
/* Reuse original ring buffer. */
hme_write_rxd(hp, this,
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
@@ -2300,7 +2287,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 mapping, len;
len = skb->len;
- mapping = hme_dma_map(hp, skb->data, len, DMA_TODEVICE);
+ mapping = dma_map_single(hp->dma_dev, skb->data, len, DMA_TO_DEVICE);
tx_flags |= (TXFLAG_SOP | TXFLAG_EOP);
hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry],
(tx_flags | (len & TXFLAG_SIZE)),
@@ -2314,7 +2301,8 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
* Otherwise we could race with the device.
*/
first_len = skb_headlen(skb);
- first_mapping = hme_dma_map(hp, skb->data, first_len, DMA_TODEVICE);
+ first_mapping = dma_map_single(hp->dma_dev, skb->data, first_len,
+ DMA_TO_DEVICE);
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -2322,10 +2310,9 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 len, mapping, this_txflags;
len = this_frag->size;
- mapping = hme_dma_map(hp,
- ((void *) page_address(this_frag->page) +
- this_frag->page_offset),
- len, DMA_TODEVICE);
+ mapping = dma_map_page(hp->dma_dev, this_frag->page,
+ this_frag->page_offset, len,
+ DMA_TO_DEVICE);
this_txflags = tx_flags;
if (frag == skb_shinfo(skb)->nr_frags - 1)
this_txflags |= TXFLAG_EOP;
@@ -2493,9 +2480,12 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
}
#ifdef CONFIG_SBUS
else {
- struct sbus_dev *sdev = hp->happy_dev;
- sprintf(info->bus_info, "SBUS:%d",
- sdev->slot);
+ const struct linux_prom_registers *regs;
+ struct of_device *op = hp->happy_dev;
+ regs = of_get_property(op->node, "regs", NULL);
+ if (regs)
+ sprintf(info->bus_info, "SBUS:%d",
+ regs->which_io);
}
#endif
}
@@ -2521,63 +2511,21 @@ static const struct ethtool_ops hme_ethtool_ops = {
static int hme_version_printed;
#ifdef CONFIG_SBUS
-void __devinit quattro_get_ranges(struct quattro *qp)
-{
- struct sbus_dev *sdev = qp->quattro_dev;
- int err;
-
- err = prom_getproperty(sdev->prom_node,
- "ranges",
- (char *)&qp->ranges[0],
- sizeof(qp->ranges));
- if (err == 0 || err == -1) {
- qp->nranges = 0;
- return;
- }
- qp->nranges = (err / sizeof(struct linux_prom_ranges));
-}
-
-static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp)
-{
- struct sbus_dev *sdev = hp->happy_dev;
- int rng;
-
- for (rng = 0; rng < qp->nranges; rng++) {
- struct linux_prom_ranges *rngp = &qp->ranges[rng];
- int reg;
-
- for (reg = 0; reg < 5; reg++) {
- if (sdev->reg_addrs[reg].which_io ==
- rngp->ot_child_space)
- break;
- }
- if (reg == 5)
- continue;
-
- sdev->reg_addrs[reg].which_io = rngp->ot_parent_space;
- sdev->reg_addrs[reg].phys_addr += rngp->ot_parent_base;
- }
-}
-
/* Given a happy meal sbus device, find it's quattro parent.
* If none exist, allocate and return a new one.
*
* Return NULL on failure.
*/
-static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev)
+static struct quattro * __devinit quattro_sbus_find(struct of_device *child)
{
- struct sbus_dev *sdev;
+ struct device *parent = child->dev.parent;
+ struct of_device *op;
struct quattro *qp;
- int i;
- for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
- for (i = 0, sdev = qp->quattro_dev;
- (sdev != NULL) && (i < 4);
- sdev = sdev->next, i++) {
- if (sdev == goal_sdev)
- return qp;
- }
- }
+ op = to_of_device(parent);
+ qp = dev_get_drvdata(&op->dev);
+ if (qp)
+ return qp;
qp = kmalloc(sizeof(struct quattro), GFP_KERNEL);
if (qp != NULL) {
@@ -2586,10 +2534,11 @@ static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev)
for (i = 0; i < 4; i++)
qp->happy_meals[i] = NULL;
- qp->quattro_dev = goal_sdev;
+ qp->quattro_dev = child;
qp->next = qfe_sbus_list;
qfe_sbus_list = qp;
- quattro_get_ranges(qp);
+
+ dev_set_drvdata(&op->dev, qp);
}
return qp;
}
@@ -2602,10 +2551,10 @@ static void __init quattro_sbus_register_irqs(void)
struct quattro *qp;
for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
- struct sbus_dev *sdev = qp->quattro_dev;
+ struct of_device *op = qp->quattro_dev;
int err;
- err = request_irq(sdev->irqs[0],
+ err = request_irq(op->irqs[0],
quattro_sbus_interrupt,
IRQF_SHARED, "Quattro",
qp);
@@ -2621,9 +2570,9 @@ static void quattro_sbus_free_irqs(void)
struct quattro *qp;
for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
- struct sbus_dev *sdev = qp->quattro_dev;
+ struct of_device *op = qp->quattro_dev;
- free_irq(sdev->irqs[0], qp);
+ free_irq(op->irqs[0], qp);
}
}
#endif /* CONFIG_SBUS */
@@ -2660,9 +2609,9 @@ static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
-static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe)
+static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
{
- struct device_node *dp = sdev->ofdev.node;
+ struct device_node *dp = op->node, *sbus_dp;
struct quattro *qp = NULL;
struct happy_meal *hp;
struct net_device *dev;
@@ -2671,7 +2620,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
DECLARE_MAC_BUF(mac);
if (is_qfe) {
- qp = quattro_sbus_find(sdev);
+ qp = quattro_sbus_find(op);
if (qp == NULL)
goto err_out;
for (qfe_slot = 0; qfe_slot < 4; qfe_slot++)
@@ -2685,7 +2634,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
dev = alloc_etherdev(sizeof(struct happy_meal));
if (!dev)
goto err_out;
- SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
+ SET_NETDEV_DEV(dev, &op->dev);
if (hme_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -2713,56 +2662,50 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
}
- hp = dev->priv;
+ hp = netdev_priv(dev);
- hp->happy_dev = sdev;
+ hp->happy_dev = op;
+ hp->dma_dev = &op->dev;
spin_lock_init(&hp->happy_lock);
err = -ENODEV;
- if (sdev->num_registers != 5) {
- printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n",
- sdev->num_registers);
- goto err_out_free_netdev;
- }
-
if (qp != NULL) {
hp->qfe_parent = qp;
hp->qfe_ent = qfe_slot;
qp->happy_meals[qfe_slot] = dev;
- quattro_apply_ranges(qp, hp);
}
- hp->gregs = sbus_ioremap(&sdev->resource[0], 0,
- GREG_REG_SIZE, "HME Global Regs");
+ hp->gregs = of_ioremap(&op->resource[0], 0,
+ GREG_REG_SIZE, "HME Global Regs");
if (!hp->gregs) {
printk(KERN_ERR "happymeal: Cannot map global registers.\n");
goto err_out_free_netdev;
}
- hp->etxregs = sbus_ioremap(&sdev->resource[1], 0,
- ETX_REG_SIZE, "HME TX Regs");
+ hp->etxregs = of_ioremap(&op->resource[1], 0,
+ ETX_REG_SIZE, "HME TX Regs");
if (!hp->etxregs) {
printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n");
goto err_out_iounmap;
}
- hp->erxregs = sbus_ioremap(&sdev->resource[2], 0,
- ERX_REG_SIZE, "HME RX Regs");
+ hp->erxregs = of_ioremap(&op->resource[2], 0,
+ ERX_REG_SIZE, "HME RX Regs");
if (!hp->erxregs) {
printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n");
goto err_out_iounmap;
}
- hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0,
- BMAC_REG_SIZE, "HME BIGMAC Regs");
+ hp->bigmacregs = of_ioremap(&op->resource[3], 0,
+ BMAC_REG_SIZE, "HME BIGMAC Regs");
if (!hp->bigmacregs) {
printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n");
goto err_out_iounmap;
}
- hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0,
- TCVR_REG_SIZE, "HME Tranceiver Regs");
+ hp->tcvregs = of_ioremap(&op->resource[4], 0,
+ TCVR_REG_SIZE, "HME Tranceiver Regs");
if (!hp->tcvregs) {
printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n");
goto err_out_iounmap;
@@ -2781,13 +2724,18 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
if (qp != NULL)
hp->happy_flags |= HFLAG_QUATTRO;
+ sbus_dp = to_of_device(op->dev.parent)->node;
+ if (is_qfe)
+ sbus_dp = to_of_device(op->dev.parent->parent)->node;
+
/* Get the supported DVMA burst sizes from our Happy SBUS. */
- hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node,
+ hp->happy_bursts = of_getintprop_default(sbus_dp,
"burst-sizes", 0x00);
- hp->happy_block = sbus_alloc_consistent(hp->happy_dev,
- PAGE_SIZE,
- &hp->hblock_dvma);
+ hp->happy_block = dma_alloc_coherent(hp->dma_dev,
+ PAGE_SIZE,
+ &hp->hblock_dvma,
+ GFP_ATOMIC);
err = -ENOMEM;
if (!hp->happy_block) {
printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n");
@@ -2816,19 +2764,13 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
/* Happy Meal can do it all... */
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
- dev->irq = sdev->irqs[0];
+ dev->irq = op->irqs[0];
#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
- /* Hook up PCI register/dma accessors. */
+ /* Hook up SBUS register/descriptor accessors. */
hp->read_desc32 = sbus_hme_read_desc32;
hp->write_txd = sbus_hme_write_txd;
hp->write_rxd = sbus_hme_write_rxd;
- hp->dma_map = (u32 (*)(void *, void *, long, int))sbus_map_single;
- hp->dma_unmap = (void (*)(void *, u32, long, int))sbus_unmap_single;
- hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int))
- sbus_dma_sync_single_for_cpu;
- hp->dma_sync_for_device = (void (*)(void *, u32, long, int))
- sbus_dma_sync_single_for_device;
hp->read32 = sbus_hme_read32;
hp->write32 = sbus_hme_write32;
#endif
@@ -2843,10 +2785,10 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
if (register_netdev(hp->dev)) {
printk(KERN_ERR "happymeal: Cannot register net device, "
"aborting.\n");
- goto err_out_free_consistent;
+ goto err_out_free_coherent;
}
- dev_set_drvdata(&sdev->ofdev.dev, hp);
+ dev_set_drvdata(&op->dev, hp);
if (qfe_slot != -1)
printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
@@ -2859,23 +2801,23 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
return 0;
-err_out_free_consistent:
- sbus_free_consistent(hp->happy_dev,
- PAGE_SIZE,
- hp->happy_block,
- hp->hblock_dvma);
+err_out_free_coherent:
+ dma_free_coherent(hp->dma_dev,
+ PAGE_SIZE,
+ hp->happy_block,
+ hp->hblock_dvma);
err_out_iounmap:
if (hp->gregs)
- sbus_iounmap(hp->gregs, GREG_REG_SIZE);
+ of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE);
if (hp->etxregs)
- sbus_iounmap(hp->etxregs, ETX_REG_SIZE);
+ of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE);
if (hp->erxregs)
- sbus_iounmap(hp->erxregs, ERX_REG_SIZE);
+ of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE);
if (hp->bigmacregs)
- sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE);
+ of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE);
if (hp->tcvregs)
- sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
+ of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE);
err_out_free_netdev:
free_netdev(dev);
@@ -3035,6 +2977,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
memset(hp, 0, sizeof(*hp));
hp->happy_dev = pdev;
+ hp->dma_dev = &pdev->dev;
spin_lock_init(&hp->happy_lock);
@@ -3121,7 +3064,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
#endif
hp->happy_block = (struct hmeal_init_block *)
- pci_alloc_consistent(pdev, PAGE_SIZE, &hp->hblock_dvma);
+ dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &hp->hblock_dvma, GFP_KERNEL);
err = -ENODEV;
if (!hp->happy_block) {
@@ -3151,16 +3094,10 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
- /* Hook up PCI register/dma accessors. */
+ /* Hook up PCI register/descriptor accessors. */
hp->read_desc32 = pci_hme_read_desc32;
hp->write_txd = pci_hme_write_txd;
hp->write_rxd = pci_hme_write_rxd;
- hp->dma_map = (u32 (*)(void *, void *, long, int))pci_map_single;
- hp->dma_unmap = (void (*)(void *, u32, long, int))pci_unmap_single;
- hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int))
- pci_dma_sync_single_for_cpu;
- hp->dma_sync_for_device = (void (*)(void *, u32, long, int))
- pci_dma_sync_single_for_device;
hp->read32 = pci_hme_read32;
hp->write32 = pci_hme_write32;
#endif
@@ -3231,10 +3168,8 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
unregister_netdev(net_dev);
- pci_free_consistent(hp->happy_dev,
- PAGE_SIZE,
- hp->happy_block,
- hp->hblock_dvma);
+ dma_free_coherent(hp->dma_dev, PAGE_SIZE,
+ hp->happy_block, hp->hblock_dvma);
iounmap(hp->gregs);
pci_release_regions(hp->happy_dev);
@@ -3279,46 +3214,45 @@ static void happy_meal_pci_exit(void)
#endif
#ifdef CONFIG_SBUS
-static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
+ struct device_node *dp = op->node;
const char *model = of_get_property(dp, "model", NULL);
int is_qfe = (match->data != NULL);
if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
is_qfe = 1;
- return happy_meal_sbus_probe_one(sdev, is_qfe);
+ return happy_meal_sbus_probe_one(op, is_qfe);
}
-static int __devexit hme_sbus_remove(struct of_device *dev)
+static int __devexit hme_sbus_remove(struct of_device *op)
{
- struct happy_meal *hp = dev_get_drvdata(&dev->dev);
+ struct happy_meal *hp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = hp->dev;
unregister_netdev(net_dev);
/* XXX qfe parent interrupt... */
- sbus_iounmap(hp->gregs, GREG_REG_SIZE);
- sbus_iounmap(hp->etxregs, ETX_REG_SIZE);
- sbus_iounmap(hp->erxregs, ERX_REG_SIZE);
- sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE);
- sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
- sbus_free_consistent(hp->happy_dev,
- PAGE_SIZE,
- hp->happy_block,
- hp->hblock_dvma);
+ of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE);
+ of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE);
+ of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE);
+ of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE);
+ of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE);
+ dma_free_coherent(hp->dma_dev,
+ PAGE_SIZE,
+ hp->happy_block,
+ hp->hblock_dvma);
free_netdev(net_dev);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id hme_sbus_match[] = {
+static const struct of_device_id hme_sbus_match[] = {
{
.name = "SUNW,hme",
},
@@ -3346,7 +3280,7 @@ static int __init happy_meal_sbus_init(void)
{
int err;
- err = of_register_driver(&hme_sbus_driver, &sbus_bus_type);
+ err = of_register_driver(&hme_sbus_driver, &of_bus_type);
if (!err)
quattro_sbus_register_irqs();
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h
index 4da5539fac7..efd2ca0fcad 100644
--- a/drivers/net/sunhme.h
+++ b/drivers/net/sunhme.h
@@ -405,14 +405,11 @@ struct happy_meal {
u32 (*read_desc32)(hme32 *);
void (*write_txd)(struct happy_meal_txd *, u32, u32);
void (*write_rxd)(struct happy_meal_rxd *, u32, u32);
- u32 (*dma_map)(void *, void *, long, int);
- void (*dma_unmap)(void *, u32, long, int);
- void (*dma_sync_for_cpu)(void *, u32, long, int);
- void (*dma_sync_for_device)(void *, u32, long, int);
#endif
- /* This is either a sbus_dev or a pci_dev. */
+ /* This is either an of_device or a pci_dev. */
void *happy_dev;
+ struct device *dma_dev;
spinlock_t happy_lock;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 4e994f87469..704301a5a7f 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -91,6 +91,9 @@ static char lancestr[] = "LANCE";
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -98,7 +101,6 @@ static char lancestr[] = "LANCE";
#include <asm/pgtable.h>
#include <asm/byteorder.h> /* Used by the checksum routines */
#include <asm/idprom.h>
-#include <asm/sbus.h>
#include <asm/prom.h>
#include <asm/auxio.h> /* For tpe-link-test? setting */
#include <asm/irq.h>
@@ -248,7 +250,7 @@ struct lance_private {
int rx_new, tx_new;
int rx_old, tx_old;
- struct sbus_dma *ledma; /* If set this points to ledma */
+ struct of_device *ledma; /* If set this points to ledma */
char tpe; /* cable-selection is TPE */
char auto_select; /* cable-selection by carrier */
char burst_sizes; /* ledma SBus burst sizes */
@@ -263,7 +265,8 @@ struct lance_private {
char *name;
dma_addr_t init_block_dvma;
struct net_device *dev; /* Backpointer */
- struct sbus_dev *sdev;
+ struct of_device *op;
+ struct of_device *lebuffer;
struct timer_list multicast_timer;
};
@@ -1272,27 +1275,29 @@ static void lance_set_multicast_retry(unsigned long _opaque)
static void lance_free_hwresources(struct lance_private *lp)
{
if (lp->lregs)
- sbus_iounmap(lp->lregs, LANCE_REG_SIZE);
+ of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE);
+ if (lp->dregs) {
+ struct of_device *ledma = lp->ledma;
+
+ of_iounmap(&ledma->resource[0], lp->dregs,
+ resource_size(&ledma->resource[0]));
+ }
if (lp->init_block_iomem) {
- sbus_iounmap(lp->init_block_iomem,
- sizeof(struct lance_init_block));
+ of_iounmap(&lp->lebuffer->resource[0], lp->init_block_iomem,
+ sizeof(struct lance_init_block));
} else if (lp->init_block_mem) {
- sbus_free_consistent(lp->sdev,
- sizeof(struct lance_init_block),
- lp->init_block_mem,
- lp->init_block_dvma);
+ dma_free_coherent(&lp->op->dev,
+ sizeof(struct lance_init_block),
+ lp->init_block_mem,
+ lp->init_block_dvma);
}
}
/* Ethtool support... */
static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct lance_private *lp = netdev_priv(dev);
-
strcpy(info->driver, "sunlance");
strcpy(info->version, "2.02");
- sprintf(info->bus_info, "SBUS:%d",
- lp->sdev->slot);
}
static u32 sparc_lance_get_link(struct net_device *dev)
@@ -1308,16 +1313,16 @@ static const struct ethtool_ops sparc_lance_ethtool_ops = {
.get_link = sparc_lance_get_link,
};
-static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
- struct sbus_dma *ledma,
- struct sbus_dev *lebuffer)
+static int __devinit sparc_lance_probe_one(struct of_device *op,
+ struct of_device *ledma,
+ struct of_device *lebuffer)
{
+ struct device_node *dp = op->node;
static unsigned version_printed;
- struct device_node *dp = sdev->ofdev.node;
- struct net_device *dev;
struct lance_private *lp;
- int i;
+ struct net_device *dev;
DECLARE_MAC_BUF(mac);
+ int i;
dev = alloc_etherdev(sizeof(struct lance_private) + 8);
if (!dev)
@@ -1338,14 +1343,27 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
dev->dev_addr[i] = idprom->id_ethaddr[i];
/* Get the IO region */
- lp->lregs = sbus_ioremap(&sdev->resource[0], 0,
- LANCE_REG_SIZE, lancestr);
+ lp->lregs = of_ioremap(&op->resource[0], 0,
+ LANCE_REG_SIZE, lancestr);
if (!lp->lregs) {
printk(KERN_ERR "SunLance: Cannot map registers.\n");
goto fail;
}
- lp->sdev = sdev;
+ lp->ledma = ledma;
+ if (lp->ledma) {
+ lp->dregs = of_ioremap(&ledma->resource[0], 0,
+ resource_size(&ledma->resource[0]),
+ "ledma");
+ if (!lp->dregs) {
+ printk(KERN_ERR "SunLance: Cannot map "
+ "ledma registers.\n");
+ goto fail;
+ }
+ }
+
+ lp->op = op;
+ lp->lebuffer = lebuffer;
if (lebuffer) {
/* sanity check */
if (lebuffer->resource[0].start & 7) {
@@ -1353,8 +1371,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
goto fail;
}
lp->init_block_iomem =
- sbus_ioremap(&lebuffer->resource[0], 0,
- sizeof(struct lance_init_block), "lebuffer");
+ of_ioremap(&lebuffer->resource[0], 0,
+ sizeof(struct lance_init_block), "lebuffer");
if (!lp->init_block_iomem) {
printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n");
goto fail;
@@ -1366,9 +1384,10 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
lp->tx = lance_tx_pio;
} else {
lp->init_block_mem =
- sbus_alloc_consistent(sdev, sizeof(struct lance_init_block),
- &lp->init_block_dvma);
- if (!lp->init_block_mem || lp->init_block_dvma == 0) {
+ dma_alloc_coherent(&op->dev,
+ sizeof(struct lance_init_block),
+ &lp->init_block_dvma, GFP_ATOMIC);
+ if (!lp->init_block_mem) {
printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n");
goto fail;
}
@@ -1383,13 +1402,13 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
LE_C3_BCON));
lp->name = lancestr;
- lp->ledma = ledma;
lp->burst_sizes = 0;
if (lp->ledma) {
- struct device_node *ledma_dp = ledma->sdev->ofdev.node;
- const char *prop;
+ struct device_node *ledma_dp = ledma->node;
+ struct device_node *sbus_dp;
unsigned int sbmask;
+ const char *prop;
u32 csr;
/* Find burst-size property for ledma */
@@ -1397,7 +1416,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev,
"burst-sizes", 0);
/* ledma may be capable of fast bursts, but sbus may not. */
- sbmask = of_getintprop_default(ledma_dp, "burst-sizes",
+ sbus_dp = ledma_dp->parent;
+ sbmask = of_getintprop_default(sbus_dp, "burst-sizes",
DMA_BURSTBITS);
lp->burst_sizes &= sbmask;
@@ -1435,8 +1455,6 @@ no_link_test:
lp->tpe = 1;
}
- lp->dregs = ledma->regs;
-
/* Reset ledma */
csr = sbus_readl(lp->dregs + DMA_CSR);
sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR);
@@ -1446,7 +1464,7 @@ no_link_test:
lp->dregs = NULL;
lp->dev = dev;
- SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
+ SET_NETDEV_DEV(dev, &op->dev);
dev->open = &lance_open;
dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit;
@@ -1455,9 +1473,7 @@ no_link_test:
dev->set_multicast_list = &lance_set_multicast;
dev->ethtool_ops = &sparc_lance_ethtool_ops;
- dev->irq = sdev->irqs[0];
-
- dev->dma = 0;
+ dev->irq = op->irqs[0];
/* We cannot sleep if the chip is busy during a
* multicast list update event, because such events
@@ -1473,7 +1489,7 @@ no_link_test:
goto fail;
}
- dev_set_drvdata(&sdev->ofdev.dev, lp);
+ dev_set_drvdata(&op->dev, lp);
printk(KERN_INFO "%s: LANCE %s\n",
dev->name, print_mac(mac, dev->dev_addr));
@@ -1486,80 +1502,25 @@ fail:
return -ENODEV;
}
-/* On 4m, find the associated dma for the lance chip */
-static struct sbus_dma * __devinit find_ledma(struct sbus_dev *sdev)
-{
- struct sbus_dma *p;
-
- for_each_dvma(p) {
- if (p->sdev == sdev)
- return p;
- }
- return NULL;
-}
-
-#ifdef CONFIG_SUN4
-
-#include <asm/sun4paddr.h>
-#include <asm/machines.h>
-
-/* Find all the lance cards on the system and initialize them */
-static struct sbus_dev sun4_sdev;
-static int __devinit sparc_lance_init(void)
-{
- if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||
- (idprom->id_machtype == (SM_SUN4|SM_4_470))) {
- memset(&sun4_sdev, 0, sizeof(struct sbus_dev));
- sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
- sun4_sdev.irqs[0] = 6;
- return sparc_lance_probe_one(&sun4_sdev, NULL, NULL);
- }
- return -ENODEV;
-}
-
-static int __exit sunlance_sun4_remove(void)
+static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev);
- struct net_device *net_dev = lp->dev;
-
- unregister_netdev(net_dev);
-
- lance_free_hwresources(lp);
-
- free_netdev(net_dev);
-
- dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL);
-
- return 0;
-}
-
-#else /* !CONFIG_SUN4 */
-
-static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match)
-{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+ struct of_device *parent = to_of_device(op->dev.parent);
+ struct device_node *parent_dp = parent->node;
int err;
- if (sdev->parent) {
- struct of_device *parent = &sdev->parent->ofdev;
-
- if (!strcmp(parent->node->name, "ledma")) {
- struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev));
-
- err = sparc_lance_probe_one(sdev, ledma, NULL);
- } else if (!strcmp(parent->node->name, "lebuffer")) {
- err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev));
- } else
- err = sparc_lance_probe_one(sdev, NULL, NULL);
+ if (!strcmp(parent_dp->name, "ledma")) {
+ err = sparc_lance_probe_one(op, parent, NULL);
+ } else if (!strcmp(parent_dp->name, "lebuffer")) {
+ err = sparc_lance_probe_one(op, NULL, parent);
} else
- err = sparc_lance_probe_one(sdev, NULL, NULL);
+ err = sparc_lance_probe_one(op, NULL, NULL);
return err;
}
-static int __devexit sunlance_sbus_remove(struct of_device *dev)
+static int __devexit sunlance_sbus_remove(struct of_device *op)
{
- struct lance_private *lp = dev_get_drvdata(&dev->dev);
+ struct lance_private *lp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = lp->dev;
unregister_netdev(net_dev);
@@ -1568,12 +1529,12 @@ static int __devexit sunlance_sbus_remove(struct of_device *dev)
free_netdev(net_dev);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id sunlance_sbus_match[] = {
+static const struct of_device_id sunlance_sbus_match[] = {
{
.name = "le",
},
@@ -1593,17 +1554,12 @@ static struct of_platform_driver sunlance_sbus_driver = {
/* Find all the lance cards on the system and initialize them */
static int __init sparc_lance_init(void)
{
- return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&sunlance_sbus_driver, &of_bus_type);
}
-#endif /* !CONFIG_SUN4 */
static void __exit sparc_lance_exit(void)
{
-#ifdef CONFIG_SUN4
- sunlance_sun4_remove();
-#else
of_unregister_driver(&sunlance_sbus_driver);
-#endif
}
module_init(sparc_lance_init);
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index e811331d460..f63644744ff 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -3,7 +3,7 @@
* controller out there can be most efficiently programmed
* if you make it look like a LANCE.
*
- * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996, 1999, 2003, 2006, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -24,13 +24,15 @@
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <asm/idprom.h>
-#include <asm/sbus.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
@@ -40,8 +42,8 @@
#include "sunqe.h"
#define DRV_NAME "sunqe"
-#define DRV_VERSION "4.0"
-#define DRV_RELDATE "June 23, 2006"
+#define DRV_VERSION "4.1"
+#define DRV_RELDATE "August 27, 2008"
#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)"
static char version[] =
@@ -690,12 +692,18 @@ static void qe_set_multicast(struct net_device *dev)
/* Ethtool support... */
static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
+ const struct linux_prom_registers *regs;
struct sunqe *qep = dev->priv;
+ struct of_device *op;
strcpy(info->driver, "sunqe");
strcpy(info->version, "3.0");
- sprintf(info->bus_info, "SBUS:%d",
- qep->qe_sdev->slot);
+
+ op = qep->op;
+ regs = of_get_property(op->node, "reg", NULL);
+ if (regs)
+ sprintf(info->bus_info, "SBUS:%d", regs->which_io);
+
}
static u32 qe_get_link(struct net_device *dev)
@@ -717,11 +725,11 @@ static const struct ethtool_ops qe_ethtool_ops = {
};
/* This is only called once at boot time for each card probed. */
-static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev)
+static void qec_init_once(struct sunqec *qecp, struct of_device *op)
{
u8 bsizes = qecp->qec_bursts;
- if (sbus_can_burst64(qsdev) && (bsizes & DMA_BURST64)) {
+ if (sbus_can_burst64() && (bsizes & DMA_BURST64)) {
sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL);
} else if (bsizes & DMA_BURST32) {
sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL);
@@ -735,15 +743,15 @@ static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev)
sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE);
/* Set the local memsize register, divided up to one piece per QE channel. */
- sbus_writel((qsdev->reg_addrs[1].reg_size >> 2),
+ sbus_writel((resource_size(&op->resource[1]) >> 2),
qecp->gregs + GLOB_MSIZE);
/* Divide up the local QEC memory amongst the 4 QE receiver and
* transmitter FIFOs. Basically it is (total / 2 / num_channels).
*/
- sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1,
+ sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1,
qecp->gregs + GLOB_TSIZE);
- sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1,
+ sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1,
qecp->gregs + GLOB_RSIZE);
}
@@ -767,24 +775,21 @@ static u8 __devinit qec_get_burst(struct device_node *dp)
return bsizes;
}
-static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev)
+static struct sunqec * __devinit get_qec(struct of_device *child)
{
- struct sbus_dev *qec_sdev = child_sdev->parent;
+ struct of_device *op = to_of_device(child->dev.parent);
struct sunqec *qecp;
- for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) {
- if (qecp->qec_sdev == qec_sdev)
- break;
- }
+ qecp = dev_get_drvdata(&op->dev);
if (!qecp) {
qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL);
if (qecp) {
u32 ctrl;
- qecp->qec_sdev = qec_sdev;
- qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0,
- GLOB_REG_SIZE,
- "QEC Global Registers");
+ qecp->op = op;
+ qecp->gregs = of_ioremap(&op->resource[0], 0,
+ GLOB_REG_SIZE,
+ "QEC Global Registers");
if (!qecp->gregs)
goto fail;
@@ -799,16 +804,18 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev)
if (qec_global_reset(qecp->gregs))
goto fail;
- qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node);
+ qecp->qec_bursts = qec_get_burst(op->node);
- qec_init_once(qecp, qec_sdev);
+ qec_init_once(qecp, op);
- if (request_irq(qec_sdev->irqs[0], &qec_interrupt,
+ if (request_irq(op->irqs[0], &qec_interrupt,
IRQF_SHARED, "qec", (void *) qecp)) {
printk(KERN_ERR "qec: Can't register irq.\n");
goto fail;
}
+ dev_set_drvdata(&op->dev, qecp);
+
qecp->next_module = root_qec_dev;
root_qec_dev = qecp;
}
@@ -818,17 +825,17 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev)
fail:
if (qecp->gregs)
- sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
+ of_iounmap(&op->resource[0], qecp->gregs, GLOB_REG_SIZE);
kfree(qecp);
return NULL;
}
-static int __devinit qec_ether_init(struct sbus_dev *sdev)
+static int __devinit qec_ether_init(struct of_device *op)
{
static unsigned version_printed;
struct net_device *dev;
- struct sunqe *qe;
struct sunqec *qecp;
+ struct sunqe *qe;
int i, res;
if (version_printed++ == 0)
@@ -842,49 +849,42 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev)
qe = netdev_priv(dev);
- i = of_getintprop_default(sdev->ofdev.node, "channel#", -1);
- if (i == -1) {
- struct sbus_dev *td = sdev->parent->child;
- i = 0;
- while (td != sdev) {
- td = td->next;
- i++;
- }
- }
+ res = -ENODEV;
+
+ i = of_getintprop_default(op->node, "channel#", -1);
+ if (i == -1)
+ goto fail;
qe->channel = i;
spin_lock_init(&qe->lock);
- res = -ENODEV;
- qecp = get_qec(sdev);
+ qecp = get_qec(op);
if (!qecp)
goto fail;
qecp->qes[qe->channel] = qe;
qe->dev = dev;
qe->parent = qecp;
- qe->qe_sdev = sdev;
+ qe->op = op;
res = -ENOMEM;
- qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0,
- CREG_REG_SIZE, "QEC Channel Registers");
+ qe->qcregs = of_ioremap(&op->resource[0], 0,
+ CREG_REG_SIZE, "QEC Channel Registers");
if (!qe->qcregs) {
printk(KERN_ERR "qe: Cannot map channel registers.\n");
goto fail;
}
- qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0,
- MREGS_REG_SIZE, "QE MACE Registers");
+ qe->mregs = of_ioremap(&op->resource[1], 0,
+ MREGS_REG_SIZE, "QE MACE Registers");
if (!qe->mregs) {
printk(KERN_ERR "qe: Cannot map MACE registers.\n");
goto fail;
}
- qe->qe_block = sbus_alloc_consistent(qe->qe_sdev,
- PAGE_SIZE,
- &qe->qblock_dvma);
- qe->buffers = sbus_alloc_consistent(qe->qe_sdev,
- sizeof(struct sunqe_buffers),
- &qe->buffers_dvma);
+ qe->qe_block = dma_alloc_coherent(&op->dev, PAGE_SIZE,
+ &qe->qblock_dvma, GFP_ATOMIC);
+ qe->buffers = dma_alloc_coherent(&op->dev, sizeof(struct sunqe_buffers),
+ &qe->buffers_dvma, GFP_ATOMIC);
if (qe->qe_block == NULL || qe->qblock_dvma == 0 ||
qe->buffers == NULL || qe->buffers_dvma == 0)
goto fail;
@@ -892,7 +892,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev)
/* Stop this QE. */
qe_stop(qe);
- SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
+ SET_NETDEV_DEV(dev, &op->dev);
dev->open = qe_open;
dev->stop = qe_close;
@@ -900,7 +900,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev)
dev->set_multicast_list = qe_set_multicast;
dev->tx_timeout = qe_tx_timeout;
dev->watchdog_timeo = 5*HZ;
- dev->irq = sdev->irqs[0];
+ dev->irq = op->irqs[0];
dev->dma = 0;
dev->ethtool_ops = &qe_ethtool_ops;
@@ -908,7 +908,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev)
if (res)
goto fail;
- dev_set_drvdata(&sdev->ofdev.dev, qe);
+ dev_set_drvdata(&op->dev, qe);
printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel);
for (i = 0; i < 6; i++)
@@ -922,58 +922,50 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev)
fail:
if (qe->qcregs)
- sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
+ of_iounmap(&op->resource[0], qe->qcregs, CREG_REG_SIZE);
if (qe->mregs)
- sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
+ of_iounmap(&op->resource[1], qe->mregs, MREGS_REG_SIZE);
if (qe->qe_block)
- sbus_free_consistent(qe->qe_sdev,
- PAGE_SIZE,
- qe->qe_block,
- qe->qblock_dvma);
+ dma_free_coherent(&op->dev, PAGE_SIZE,
+ qe->qe_block, qe->qblock_dvma);
if (qe->buffers)
- sbus_free_consistent(qe->qe_sdev,
- sizeof(struct sunqe_buffers),
- qe->buffers,
- qe->buffers_dvma);
+ dma_free_coherent(&op->dev,
+ sizeof(struct sunqe_buffers),
+ qe->buffers,
+ qe->buffers_dvma);
free_netdev(dev);
return res;
}
-static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
-
- return qec_ether_init(sdev);
+ return qec_ether_init(op);
}
-static int __devexit qec_sbus_remove(struct of_device *dev)
+static int __devexit qec_sbus_remove(struct of_device *op)
{
- struct sunqe *qp = dev_get_drvdata(&dev->dev);
+ struct sunqe *qp = dev_get_drvdata(&op->dev);
struct net_device *net_dev = qp->dev;
unregister_netdev(net_dev);
- sbus_iounmap(qp->qcregs, CREG_REG_SIZE);
- sbus_iounmap(qp->mregs, MREGS_REG_SIZE);
- sbus_free_consistent(qp->qe_sdev,
- PAGE_SIZE,
- qp->qe_block,
- qp->qblock_dvma);
- sbus_free_consistent(qp->qe_sdev,
- sizeof(struct sunqe_buffers),
- qp->buffers,
- qp->buffers_dvma);
+ of_iounmap(&op->resource[0], qp->qcregs, CREG_REG_SIZE);
+ of_iounmap(&op->resource[1], qp->mregs, MREGS_REG_SIZE);
+ dma_free_coherent(&op->dev, PAGE_SIZE,
+ qp->qe_block, qp->qblock_dvma);
+ dma_free_coherent(&op->dev, sizeof(struct sunqe_buffers),
+ qp->buffers, qp->buffers_dvma);
free_netdev(net_dev);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id qec_sbus_match[] = {
+static const struct of_device_id qec_sbus_match[] = {
{
.name = "qe",
},
@@ -991,7 +983,7 @@ static struct of_platform_driver qec_sbus_driver = {
static int __init qec_init(void)
{
- return of_register_driver(&qec_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&qec_sbus_driver, &of_bus_type);
}
static void __exit qec_exit(void)
@@ -1000,11 +992,11 @@ static void __exit qec_exit(void)
while (root_qec_dev) {
struct sunqec *next = root_qec_dev->next_module;
+ struct of_device *op = root_qec_dev->op;
- free_irq(root_qec_dev->qec_sdev->irqs[0],
- (void *) root_qec_dev);
- sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE);
-
+ free_irq(op->irqs[0], (void *) root_qec_dev);
+ of_iounmap(&op->resource[0], root_qec_dev->gregs,
+ GLOB_REG_SIZE);
kfree(root_qec_dev);
root_qec_dev = next;
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h
index 347c8ddc159..5813a7b2faa 100644
--- a/drivers/net/sunqe.h
+++ b/drivers/net/sunqe.h
@@ -314,7 +314,7 @@ struct sunqec {
void __iomem *gregs; /* QEC Global Registers */
struct sunqe *qes[4]; /* Each child MACE */
unsigned int qec_bursts; /* Support burst sizes */
- struct sbus_dev *qec_sdev; /* QEC's SBUS device */
+ struct of_device *op; /* QEC's OF device */
struct sunqec *next_module; /* List of all QECs in system */
};
@@ -342,7 +342,7 @@ struct sunqe {
__u32 buffers_dvma; /* DVMA visible address. */
struct sunqec *parent;
u8 mconfig; /* Base MACE mconfig value */
- struct sbus_dev *qe_sdev; /* QE's SBUS device struct */
+ struct of_device *op; /* QE's OF device struct */
struct net_device *dev; /* QE's netdevice struct */
int channel; /* Who am I? */
};
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index 6415ce15c2e..a720065553d 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -1,6 +1,6 @@
/* sunvnet.c: Sun LDOM Virtual Network Driver.
*
- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
*/
#include <linux/module.h>
@@ -1260,7 +1260,7 @@ static int vnet_port_remove(struct vio_dev *vdev)
return 0;
}
-static struct vio_device_id vnet_port_match[] = {
+static const struct vio_device_id vnet_port_match[] = {
{
.type = "vnet-port",
},
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 8487ace9d2e..df20cafff7d 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -424,7 +424,7 @@ struct tc35815_local {
*/
spinlock_t lock;
- struct mii_bus mii_bus;
+ struct mii_bus *mii_bus;
struct phy_device *phy_dev;
int duplex;
int speed;
@@ -704,13 +704,13 @@ static int tc_mii_probe(struct net_device *dev)
/* find the first phy */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- if (lp->mii_bus.phy_map[phy_addr]) {
+ if (lp->mii_bus->phy_map[phy_addr]) {
if (phydev) {
printk(KERN_ERR "%s: multiple PHYs found\n",
dev->name);
return -EINVAL;
}
- phydev = lp->mii_bus.phy_map[phy_addr];
+ phydev = lp->mii_bus->phy_map[phy_addr];
break;
}
}
@@ -762,23 +762,29 @@ static int tc_mii_init(struct net_device *dev)
int err;
int i;
- lp->mii_bus.name = "tc35815_mii_bus";
- lp->mii_bus.read = tc_mdio_read;
- lp->mii_bus.write = tc_mdio_write;
- snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "%x",
- (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn);
- lp->mii_bus.priv = dev;
- lp->mii_bus.dev = &lp->pci_dev->dev;
- lp->mii_bus.irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- if (!lp->mii_bus.irq) {
+ lp->mii_bus = mdiobus_alloc();
+ if (lp->mii_bus == NULL) {
err = -ENOMEM;
goto err_out;
}
+ lp->mii_bus->name = "tc35815_mii_bus";
+ lp->mii_bus->read = tc_mdio_read;
+ lp->mii_bus->write = tc_mdio_write;
+ snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x",
+ (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn);
+ lp->mii_bus->priv = dev;
+ lp->mii_bus->parent = &lp->pci_dev->dev;
+ lp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!lp->mii_bus->irq) {
+ err = -ENOMEM;
+ goto err_out_free_mii_bus;
+ }
+
for (i = 0; i < PHY_MAX_ADDR; i++)
- lp->mii_bus.irq[i] = PHY_POLL;
+ lp->mii_bus->irq[i] = PHY_POLL;
- err = mdiobus_register(&lp->mii_bus);
+ err = mdiobus_register(lp->mii_bus);
if (err)
goto err_out_free_mdio_irq;
err = tc_mii_probe(dev);
@@ -787,9 +793,11 @@ static int tc_mii_init(struct net_device *dev)
return 0;
err_out_unregister_bus:
- mdiobus_unregister(&lp->mii_bus);
+ mdiobus_unregister(lp->mii_bus);
err_out_free_mdio_irq:
- kfree(lp->mii_bus.irq);
+ kfree(lp->mii_bus->irq);
+err_out_free_mii_bus:
+ mdiobus_free(lp->mii_bus);
err_out:
return err;
}
@@ -961,8 +969,9 @@ static void __devexit tc35815_remove_one(struct pci_dev *pdev)
struct tc35815_local *lp = netdev_priv(dev);
phy_disconnect(lp->phy_dev);
- mdiobus_unregister(&lp->mii_bus);
- kfree(lp->mii_bus.irq);
+ mdiobus_unregister(lp->mii_bus);
+ kfree(lp->mii_bus->irq);
+ mdiobus_free(lp->mii_bus);
unregister_netdev(dev);
free_netdev(dev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index 7db48f1cd94..efaf84d9757 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -539,22 +539,22 @@ struct txd_desc {
#define ERR(fmt, args...) printk(KERN_ERR fmt, ## args)
#define DBG2(fmt, args...) \
- printk(KERN_ERR "%s:%-5d: " fmt, __FUNCTION__, __LINE__, ## args)
+ printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args)
#define BDX_ASSERT(x) BUG_ON(x)
#ifdef DEBUG
#define ENTER do { \
- printk(KERN_ERR "%s:%-5d: ENTER\n", __FUNCTION__, __LINE__); \
+ printk(KERN_ERR "%s:%-5d: ENTER\n", __func__, __LINE__); \
} while (0)
#define RET(args...) do { \
- printk(KERN_ERR "%s:%-5d: RETURN\n", __FUNCTION__, __LINE__); \
+ printk(KERN_ERR "%s:%-5d: RETURN\n", __func__, __LINE__); \
return args; } while (0)
#define DBG(fmt, args...) \
- printk(KERN_ERR "%s:%-5d: " fmt, __FUNCTION__, __LINE__, ## args)
+ printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args)
#else
#define ENTER do { } while (0)
#define RET(args...) return args
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 71d2c5cfdad..eb9f8f3638e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -876,7 +876,7 @@ static void tg3_mdio_config(struct tg3 *tp)
{
u32 val;
- if (tp->mdio_bus.phy_map[PHY_ADDR]->interface !=
+ if (tp->mdio_bus->phy_map[PHY_ADDR]->interface !=
PHY_INTERFACE_MODE_RGMII)
return;
@@ -920,9 +920,9 @@ static void tg3_mdio_config(struct tg3 *tp)
static void tg3_mdio_start(struct tg3 *tp)
{
if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
- mutex_lock(&tp->mdio_bus.mdio_lock);
+ mutex_lock(&tp->mdio_bus->mdio_lock);
tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
- mutex_unlock(&tp->mdio_bus.mdio_lock);
+ mutex_unlock(&tp->mdio_bus->mdio_lock);
}
tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL;
@@ -936,9 +936,9 @@ static void tg3_mdio_start(struct tg3 *tp)
static void tg3_mdio_stop(struct tg3 *tp)
{
if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
- mutex_lock(&tp->mdio_bus.mdio_lock);
+ mutex_lock(&tp->mdio_bus->mdio_lock);
tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED;
- mutex_unlock(&tp->mdio_bus.mdio_lock);
+ mutex_unlock(&tp->mdio_bus->mdio_lock);
}
}
@@ -947,7 +947,6 @@ static int tg3_mdio_init(struct tg3 *tp)
int i;
u32 reg;
struct phy_device *phydev;
- struct mii_bus *mdio_bus = &tp->mdio_bus;
tg3_mdio_start(tp);
@@ -955,21 +954,23 @@ static int tg3_mdio_init(struct tg3 *tp)
(tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED))
return 0;
- memset(mdio_bus, 0, sizeof(*mdio_bus));
+ tp->mdio_bus = mdiobus_alloc();
+ if (tp->mdio_bus == NULL)
+ return -ENOMEM;
- mdio_bus->name = "tg3 mdio bus";
- snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%x",
+ tp->mdio_bus->name = "tg3 mdio bus";
+ snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x",
(tp->pdev->bus->number << 8) | tp->pdev->devfn);
- mdio_bus->priv = tp;
- mdio_bus->dev = &tp->pdev->dev;
- mdio_bus->read = &tg3_mdio_read;
- mdio_bus->write = &tg3_mdio_write;
- mdio_bus->reset = &tg3_mdio_reset;
- mdio_bus->phy_mask = ~(1 << PHY_ADDR);
- mdio_bus->irq = &tp->mdio_irq[0];
+ tp->mdio_bus->priv = tp;
+ tp->mdio_bus->parent = &tp->pdev->dev;
+ tp->mdio_bus->read = &tg3_mdio_read;
+ tp->mdio_bus->write = &tg3_mdio_write;
+ tp->mdio_bus->reset = &tg3_mdio_reset;
+ tp->mdio_bus->phy_mask = ~(1 << PHY_ADDR);
+ tp->mdio_bus->irq = &tp->mdio_irq[0];
for (i = 0; i < PHY_MAX_ADDR; i++)
- mdio_bus->irq[i] = PHY_POLL;
+ tp->mdio_bus->irq[i] = PHY_POLL;
/* The bus registration will look for all the PHYs on the mdio bus.
* Unfortunately, it does not ensure the PHY is powered up before
@@ -979,7 +980,7 @@ static int tg3_mdio_init(struct tg3 *tp)
if (tg3_readphy(tp, MII_BMCR, &reg) || (reg & BMCR_PDOWN))
tg3_bmcr_reset(tp);
- i = mdiobus_register(mdio_bus);
+ i = mdiobus_register(tp->mdio_bus);
if (i) {
printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n",
tp->dev->name, i);
@@ -988,7 +989,7 @@ static int tg3_mdio_init(struct tg3 *tp)
tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
- phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
switch (phydev->phy_id) {
case TG3_PHY_ID_BCM50610:
@@ -1014,7 +1015,8 @@ static void tg3_mdio_fini(struct tg3 *tp)
{
if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED;
- mdiobus_unregister(&tp->mdio_bus);
+ mdiobus_unregister(tp->mdio_bus);
+ mdiobus_free(tp->mdio_bus);
tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
}
}
@@ -1220,7 +1222,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
u32 old_tx_mode = tp->tx_mode;
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)
- autoneg = tp->mdio_bus.phy_map[PHY_ADDR]->autoneg;
+ autoneg = tp->mdio_bus->phy_map[PHY_ADDR]->autoneg;
else
autoneg = tp->link_config.autoneg;
@@ -1257,7 +1259,7 @@ static void tg3_adjust_link(struct net_device *dev)
u8 oldflowctrl, linkmesg = 0;
u32 mac_mode, lcl_adv, rmt_adv;
struct tg3 *tp = netdev_priv(dev);
- struct phy_device *phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR];
spin_lock(&tp->lock);
@@ -1334,7 +1336,7 @@ static int tg3_phy_init(struct tg3 *tp)
/* Bring the PHY back to a known state. */
tg3_bmcr_reset(tp);
- phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
/* Attach the MAC to the PHY. */
phydev = phy_connect(tp->dev, phydev->dev.bus_id, tg3_adjust_link,
@@ -1367,7 +1369,7 @@ static void tg3_phy_start(struct tg3 *tp)
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return;
- phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
if (tp->link_config.phy_is_low_power) {
tp->link_config.phy_is_low_power = 0;
@@ -1387,13 +1389,13 @@ static void tg3_phy_stop(struct tg3 *tp)
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return;
- phy_stop(tp->mdio_bus.phy_map[PHY_ADDR]);
+ phy_stop(tp->mdio_bus->phy_map[PHY_ADDR]);
}
static void tg3_phy_fini(struct tg3 *tp)
{
if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) {
- phy_disconnect(tp->mdio_bus.phy_map[PHY_ADDR]);
+ phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED;
}
}
@@ -2049,7 +2051,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
struct phy_device *phydev;
u32 advertising;
- phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
tp->link_config.phy_is_low_power = 1;
@@ -3861,10 +3863,7 @@ static void tg3_tx(struct tg3 *tp)
return;
}
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(ri, mapping),
- skb_headlen(skb),
- PCI_DMA_TODEVICE);
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
ri->skb = NULL;
@@ -3874,12 +3873,6 @@ static void tg3_tx(struct tg3 *tp)
ri = &tp->tx_buffers[sw_idx];
if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
tx_bug = 1;
-
- pci_unmap_page(tp->pdev,
- pci_unmap_addr(ri, mapping),
- skb_shinfo(skb)->frags[i].size,
- PCI_DMA_TODEVICE);
-
sw_idx = NEXT_TX(sw_idx);
}
@@ -4633,12 +4626,16 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
} else {
/* New SKB is guaranteed to be linear. */
entry = *start;
- new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
- PCI_DMA_TODEVICE);
+ ret = skb_dma_map(&tp->pdev->dev, new_skb, DMA_TO_DEVICE);
+ new_addr = skb_shinfo(new_skb)->dma_maps[0];
+
/* Make sure new skb does not cross any 4G boundaries.
* Drop the packet if it does.
*/
- if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ if (ret || tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ if (!ret)
+ skb_dma_unmap(&tp->pdev->dev, new_skb,
+ DMA_TO_DEVICE);
ret = -1;
dev_kfree_skb(new_skb);
new_skb = NULL;
@@ -4652,18 +4649,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
/* Now clean up the sw ring entries. */
i = 0;
while (entry != last_plus_one) {
- int len;
-
- if (i == 0)
- len = skb_headlen(skb);
- else
- len = skb_shinfo(skb)->frags[i-1].size;
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(&tp->tx_buffers[entry], mapping),
- len, PCI_DMA_TODEVICE);
if (i == 0) {
tp->tx_buffers[entry].skb = new_skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr);
} else {
tp->tx_buffers[entry].skb = NULL;
}
@@ -4671,6 +4658,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
i++;
}
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
dev_kfree_skb(skb);
return ret;
@@ -4705,8 +4693,9 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- dma_addr_t mapping;
u32 len, entry, base_flags, mss;
+ struct skb_shared_info *sp;
+ dma_addr_t mapping;
len = skb_headlen(skb);
@@ -4765,11 +4754,16 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
(vlan_tx_tag_get(skb) << 16));
#endif
- /* Queue skb data, a.k.a. the main skb fragment. */
- mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ goto out_unlock;
+ }
+
+ sp = skb_shinfo(skb);
+
+ mapping = sp->dma_maps[0];
tp->tx_buffers[entry].skb = skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len, base_flags,
(skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -4785,13 +4779,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
len = frag->size;
- mapping = pci_map_page(tp->pdev,
- frag->page,
- frag->page_offset,
- len, PCI_DMA_TODEVICE);
-
+ mapping = sp->dma_maps[i + 1];
tp->tx_buffers[entry].skb = NULL;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len,
base_flags, (i == last) | (mss << 1));
@@ -4859,9 +4848,10 @@ tg3_tso_bug_end:
static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- dma_addr_t mapping;
u32 len, entry, base_flags, mss;
+ struct skb_shared_info *sp;
int would_hit_hwbug;
+ dma_addr_t mapping;
len = skb_headlen(skb);
@@ -4942,11 +4932,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
(vlan_tx_tag_get(skb) << 16));
#endif
- /* Queue skb data, a.k.a. the main skb fragment. */
- mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ goto out_unlock;
+ }
+
+ sp = skb_shinfo(skb);
+
+ mapping = sp->dma_maps[0];
tp->tx_buffers[entry].skb = skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
would_hit_hwbug = 0;
@@ -4969,13 +4964,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
len = frag->size;
- mapping = pci_map_page(tp->pdev,
- frag->page,
- frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ mapping = sp->dma_maps[i + 1];
tp->tx_buffers[entry].skb = NULL;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
@@ -5128,7 +5119,6 @@ static void tg3_free_rings(struct tg3 *tp)
for (i = 0; i < TG3_TX_RING_SIZE; ) {
struct tx_ring_info *txp;
struct sk_buff *skb;
- int j;
txp = &tp->tx_buffers[i];
skb = txp->skb;
@@ -5138,22 +5128,11 @@ static void tg3_free_rings(struct tg3 *tp)
continue;
}
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(txp, mapping),
- skb_headlen(skb),
- PCI_DMA_TODEVICE);
- txp->skb = NULL;
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
- i++;
+ txp->skb = NULL;
- for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
- txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
- pci_unmap_page(tp->pdev,
- pci_unmap_addr(txp, mapping),
- skb_shinfo(skb)->frags[j].size,
- PCI_DMA_TODEVICE);
- i++;
- }
+ i += skb_shinfo(skb)->nr_frags + 1;
dev_kfree_skb_any(skb);
}
@@ -8977,7 +8956,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return -EAGAIN;
- return phy_ethtool_gset(tp->mdio_bus.phy_map[PHY_ADDR], cmd);
+ return phy_ethtool_gset(tp->mdio_bus->phy_map[PHY_ADDR], cmd);
}
cmd->supported = (SUPPORTED_Autoneg);
@@ -9018,7 +8997,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return -EAGAIN;
- return phy_ethtool_sset(tp->mdio_bus.phy_map[PHY_ADDR], cmd);
+ return phy_ethtool_sset(tp->mdio_bus->phy_map[PHY_ADDR], cmd);
}
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
@@ -9166,7 +9145,7 @@ static int tg3_nway_reset(struct net_device *dev)
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return -EAGAIN;
- r = phy_start_aneg(tp->mdio_bus.phy_map[PHY_ADDR]);
+ r = phy_start_aneg(tp->mdio_bus->phy_map[PHY_ADDR]);
} else {
u32 bmcr;
@@ -9283,7 +9262,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
u32 newadv;
struct phy_device *phydev;
- phydev = tp->mdio_bus.phy_map[PHY_ADDR];
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
if (epause->rx_pause) {
if (epause->tx_pause)
@@ -10265,7 +10244,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
return -EAGAIN;
- return phy_mii_ioctl(tp->mdio_bus.phy_map[PHY_ADDR], data, cmd);
+ return phy_mii_ioctl(tp->mdio_bus->phy_map[PHY_ADDR], data, cmd);
}
switch(cmd) {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index f5b8cab8d4b..be252abe898 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2197,7 +2197,6 @@ struct ring_info {
struct tx_ring_info {
struct sk_buff *skb;
- DECLARE_PCI_UNMAP_ADDR(mapping)
u32 prev_vlan_tag;
};
@@ -2557,7 +2556,7 @@ struct tg3 {
int msi_cap;
int pcix_cap;
- struct mii_bus mdio_bus;
+ struct mii_bus *mdio_bus;
int mdio_irq[PHY_MAX_ADDR];
/* PHY info */
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ec871f64676..c41d6876136 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -29,7 +29,8 @@
*
* Tigran Aivazian <tigran@sco.com>: TLan_PciProbe() now uses
* new PCI BIOS interface.
- * Alan Cox <alan@redhat.com>: Fixed the out of memory
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>:
+ * Fixed the out of memory
* handling.
*
* Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index fa73e6eed6b..ed50d288e49 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -25,7 +25,7 @@
* To do:
* 1. Multicast support.
*
- * Initial 2.5 cleanup Alan Cox <alan@redhat.com> 2002/10/28
+ * Initial 2.5 cleanup Alan Cox <alan@lxorguk.ukuu.org.uk> 2002/10/28
*/
#include <linux/module.h>
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 43fde99b24a..eb1da6f0b08 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -263,7 +263,7 @@ static inline void tsi108_write_tbi(struct tsi108_prv_data *data,
return;
udelay(10);
}
- printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+ printk(KERN_ERR "%s function time out \n", __func__);
}
static int mii_speed(struct mii_if_info *mii)
@@ -1059,7 +1059,7 @@ static void tsi108_stop_ethernet(struct net_device *dev)
return;
udelay(10);
}
- printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+ printk(KERN_ERR "%s function time out \n", __func__);
}
static void tsi108_reset_ether(struct tsi108_prv_data * data)
@@ -1244,7 +1244,7 @@ static void tsi108_init_phy(struct net_device *dev)
udelay(10);
}
if (i == 0)
- printk(KERN_ERR "%s function time out \n", __FUNCTION__);
+ printk(KERN_ERR "%s function time out \n", __func__);
if (data->phy_type == TSI108_PHY_BCM54XX) {
tsi108_write_mii(data, 0x09, 0x0300);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 9281d06d5aa..124d5d690dd 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1418,7 +1418,6 @@ static int de_close (struct net_device *dev)
de_free_rings(de);
de_adapter_sleep(de);
- pci_disable_device(de->pdev);
return 0;
}
@@ -1689,6 +1688,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
unsigned i;
dw32 (ROMCmd, 0); /* Reset the pointer with a dummy write. */
+ udelay(5);
for (i = 0; i < 6; i++) {
int value, boguscnt = 100000;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 617ef41bdfe..6444cbec0bd 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -832,7 +832,7 @@ struct de4x5_private {
s32 csr14; /* Saved SIA TX/RX Register */
s32 csr15; /* Saved SIA General Register */
int save_cnt; /* Flag if state already saved */
- struct sk_buff *skb; /* Save the (re-ordered) skb's */
+ struct sk_buff_head queue; /* Save the (re-ordered) skb's */
} cache;
struct de4x5_srom srom; /* A copy of the SROM */
int cfrv; /* Card CFRV copy */
@@ -1128,6 +1128,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
printk(" which has an Ethernet PROM CRC error.\n");
return -ENXIO;
} else {
+ skb_queue_head_init(&lp->cache.queue);
lp->cache.gepc = GEP_INIT;
lp->asBit = GEP_SLNK;
lp->asPolarity = GEP_SLNK;
@@ -1487,7 +1488,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
}
} else if (skb->len > 0) {
/* If we already have stuff queued locally, use that first */
- if (lp->cache.skb && !lp->interrupt) {
+ if (!skb_queue_empty(&lp->cache.queue) && !lp->interrupt) {
de4x5_put_cache(dev, skb);
skb = de4x5_get_cache(dev);
}
@@ -1580,7 +1581,7 @@ de4x5_interrupt(int irq, void *dev_id)
/* Load the TX ring with any locally stored packets */
if (!test_and_set_bit(0, (void *)&lp->cache.lock)) {
- while (lp->cache.skb && !netif_queue_stopped(dev) && lp->tx_enable) {
+ while (!skb_queue_empty(&lp->cache.queue) && !netif_queue_stopped(dev) && lp->tx_enable) {
de4x5_queue_pkt(de4x5_get_cache(dev), dev);
}
lp->cache.lock = 0;
@@ -3679,11 +3680,7 @@ de4x5_free_tx_buffs(struct net_device *dev)
}
/* Unload the locally queued packets */
- while (lp->cache.skb) {
- dev_kfree_skb(de4x5_get_cache(dev));
- }
-
- return;
+ __skb_queue_purge(&lp->cache.queue);
}
/*
@@ -3781,43 +3778,24 @@ static void
de4x5_put_cache(struct net_device *dev, struct sk_buff *skb)
{
struct de4x5_private *lp = netdev_priv(dev);
- struct sk_buff *p;
-
- if (lp->cache.skb) {
- for (p=lp->cache.skb; p->next; p=p->next);
- p->next = skb;
- } else {
- lp->cache.skb = skb;
- }
- skb->next = NULL;
- return;
+ __skb_queue_tail(&lp->cache.queue, skb);
}
static void
de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb)
{
struct de4x5_private *lp = netdev_priv(dev);
- struct sk_buff *p = lp->cache.skb;
-
- lp->cache.skb = skb;
- skb->next = p;
- return;
+ __skb_queue_head(&lp->cache.queue, skb);
}
static struct sk_buff *
de4x5_get_cache(struct net_device *dev)
{
struct de4x5_private *lp = netdev_priv(dev);
- struct sk_buff *p = lp->cache.skb;
- if (p) {
- lp->cache.skb = p->next;
- p->next = NULL;
- }
-
- return p;
+ return __skb_dequeue(&lp->cache.queue);
}
/*
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 656200472fa..8e46a513a25 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -23,7 +23,7 @@
Marcelo Tosatti <marcelo@conectiva.com.br> :
Made it compile in 2.3 (device to net_device)
- Alan Cox <alan@redhat.com> :
+ Alan Cox <alan@lxorguk.ukuu.org.uk> :
Cleaned up for kernel merge.
Removed the back compatibility support
Reformatted, fixing spelling etc as I went
@@ -49,7 +49,7 @@
support. Updated PCI resource allocation. Do not
forget to unmap PCI mapped skbs.
- Alan Cox <alan@redhat.com>
+ Alan Cox <alan@lxorguk.ukuu.org.uk>
Added new PCI identifiers provided by Clear Zhang at ALi
for their 1563 ethernet device.
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 8f944e57fd5..c87747bb24c 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -400,7 +400,7 @@ static struct enet_addr_container *get_enet_addr_container(void)
enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL);
if (!enet_addr_cont) {
ugeth_err("%s: No memory for enet_addr_container object.",
- __FUNCTION__);
+ __func__);
return NULL;
}
@@ -427,7 +427,7 @@ static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth,
struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
if (!(paddr_num < NUM_OF_PADDRS)) {
- ugeth_warn("%s: Illegal paddr_num.", __FUNCTION__);
+ ugeth_warn("%s: Illegal paddr_num.", __func__);
return -EINVAL;
}
@@ -447,7 +447,7 @@ static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
if (!(paddr_num < NUM_OF_PADDRS)) {
- ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+ ugeth_warn("%s: Illagel paddr_num.", __func__);
return -EINVAL;
}
@@ -1441,7 +1441,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
u32 upsmr, maccfg2, tbiBaseAddress;
u16 value;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
ug_info = ugeth->ug_info;
ug_regs = ugeth->ug_regs;
@@ -1504,7 +1504,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
if (ret_val != 0) {
if (netif_msg_probe(ugeth))
ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.",
- __FUNCTION__);
+ __func__);
return ret_val;
}
@@ -1744,7 +1744,7 @@ static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
/* check if the UCC number is in range. */
if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
if (netif_msg_probe(ugeth))
- ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+ ugeth_err("%s: ucc_num out of range.", __func__);
return -EINVAL;
}
@@ -1773,7 +1773,7 @@ static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode)
/* check if the UCC number is in range. */
if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
if (netif_msg_probe(ugeth))
- ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+ ugeth_err("%s: ucc_num out of range.", __func__);
return -EINVAL;
}
@@ -2062,7 +2062,7 @@ static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth
ugeth_warn
("%s: multicast address added to paddr will have no "
"effect - is this what you wanted?",
- __FUNCTION__);
+ __func__);
ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */
/* store address in our database */
@@ -2278,7 +2278,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
struct phy_device *phydev = ugeth->phydev;
u32 tempval;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
/* Disable the controller */
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
@@ -2315,7 +2315,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
(uf_info->bd_mem_part == MEM_PART_MURAM))) {
if (netif_msg_probe(ugeth))
ugeth_err("%s: Bad memory partition value.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
@@ -2327,7 +2327,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (netif_msg_probe(ugeth))
ugeth_err
("%s: Rx BD ring length must be multiple of 4, no smaller than 8.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
}
@@ -2338,7 +2338,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (netif_msg_probe(ugeth))
ugeth_err
("%s: Tx BD ring length must be no smaller than 2.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
}
@@ -2349,21 +2349,21 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (netif_msg_probe(ugeth))
ugeth_err
("%s: max_rx_buf_length must be non-zero multiple of 128.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
/* num Tx queues */
if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
if (netif_msg_probe(ugeth))
- ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
+ ugeth_err("%s: number of tx queues too large.", __func__);
return -EINVAL;
}
/* num Rx queues */
if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
if (netif_msg_probe(ugeth))
- ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
+ ugeth_err("%s: number of rx queues too large.", __func__);
return -EINVAL;
}
@@ -2374,7 +2374,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
ugeth_err
("%s: VLAN priority table entry must not be"
" larger than number of Rx queues.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
}
@@ -2386,7 +2386,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
ugeth_err
("%s: IP priority table entry must not be"
" larger than number of Rx queues.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
}
@@ -2394,7 +2394,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (ug_info->cam && !ug_info->ecamptr) {
if (netif_msg_probe(ugeth))
ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
@@ -2404,7 +2404,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (netif_msg_probe(ugeth))
ugeth_err("%s: Number of station addresses greater than 1 "
"not allowed in extended parsing mode.",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
@@ -2418,7 +2418,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
/* Initialize the general fast UCC block. */
if (ucc_fast_init(uf_info, &ugeth->uccf)) {
if (netif_msg_probe(ugeth))
- ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
+ ugeth_err("%s: Failed to init uccf.", __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2448,7 +2448,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
u8 __iomem *endOfRing;
u8 numThreadsRxNumerical, numThreadsTxNumerical;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
uccf = ugeth->uccf;
ug_info = ugeth->ug_info;
uf_info = &ug_info->uf_info;
@@ -2474,7 +2474,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
default:
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Rx threads value.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -EINVAL;
break;
@@ -2499,7 +2499,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
default:
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Tx threads value.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -EINVAL;
break;
@@ -2553,7 +2553,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (ret_val != 0) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: IPGIFG initialization parameter too large.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2571,7 +2571,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (ret_val != 0) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Half Duplex initialization parameter too large.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2626,7 +2626,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate memory for Tx bd rings.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2662,7 +2662,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate memory for Rx bd rings.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2678,7 +2678,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (ugeth->tx_skbuff[j] == NULL) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate tx_skbuff",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2710,7 +2710,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (ugeth->rx_skbuff[j] == NULL) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate rx_skbuff",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2744,7 +2744,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2767,7 +2767,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2797,7 +2797,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2841,7 +2841,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_scheduler.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2892,7 +2892,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_tx_fw_statistics_pram.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2932,7 +2932,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2954,7 +2954,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2978,7 +2978,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for"
- " p_rx_fw_statistics_pram.", __FUNCTION__);
+ " p_rx_fw_statistics_pram.", __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3001,7 +3001,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for"
- " p_rx_irq_coalescing_tbl.", __FUNCTION__);
+ " p_rx_irq_coalescing_tbl.", __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3070,7 +3070,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3147,7 +3147,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (!ug_info->extendedFilteringChainPointer) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Null Extended Filtering Chain Pointer.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -EINVAL;
}
@@ -3161,7 +3161,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for"
- " p_exf_glbl_param.", __FUNCTION__);
+ " p_exf_glbl_param.", __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3209,7 +3209,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate memory for"
- " p_UccInitEnetParamShadows.", __FUNCTION__);
+ " p_UccInitEnetParamShadows.", __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3244,7 +3244,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Invalid largest External Lookup Key Size.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -EINVAL;
}
@@ -3271,7 +3271,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ug_info->riscRx, 1)) != 0) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3287,7 +3287,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ug_info->riscTx, 0)) != 0) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3297,7 +3297,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill Rx bds with buffers.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3309,7 +3309,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err
("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
- __FUNCTION__);
+ __func__);
ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3360,7 +3360,7 @@ static void ucc_geth_timeout(struct net_device *dev)
{
struct ucc_geth_private *ugeth = netdev_priv(dev);
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
dev->stats.tx_errors++;
@@ -3386,7 +3386,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 bd_status;
u8 txQ = 0;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
spin_lock_irq(&ugeth->lock);
@@ -3459,7 +3459,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
u8 *bdBuffer;
struct net_device *dev;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
dev = ugeth->dev;
@@ -3481,7 +3481,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
(bd_status & R_ERRORS_FATAL)) {
if (netif_msg_rx_err(ugeth))
ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
- __FUNCTION__, __LINE__, (u32) skb);
+ __func__, __LINE__, (u32) skb);
if (skb)
dev_kfree_skb_any(skb);
@@ -3507,7 +3507,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
skb = get_new_skb(ugeth, bd);
if (!skb) {
if (netif_msg_rx_err(ugeth))
- ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
+ ugeth_warn("%s: No Rx Data Buffer", __func__);
dev->stats.rx_dropped++;
break;
}
@@ -3613,7 +3613,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
register u32 tx_mask;
u8 i;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
uccf = ugeth->uccf;
ug_info = ugeth->ug_info;
@@ -3683,13 +3683,13 @@ static int ucc_geth_open(struct net_device *dev)
struct ucc_geth_private *ugeth = netdev_priv(dev);
int err;
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
/* Test station address */
if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Multicast address used for station address"
- " - is this what you wanted?", __FUNCTION__);
+ " - is this what you wanted?", __func__);
return -EINVAL;
}
@@ -3772,7 +3772,7 @@ static int ucc_geth_close(struct net_device *dev)
{
struct ucc_geth_private *ugeth = netdev_priv(dev);
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
napi_disable(&ugeth->napi);
@@ -3840,7 +3840,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
};
- ugeth_vdbg("%s: IN", __FUNCTION__);
+ ugeth_vdbg("%s: IN", __func__);
prop = of_get_property(np, "cell-index", NULL);
if (!prop) {
@@ -3857,7 +3857,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
if (ug_info == NULL) {
if (netif_msg_probe(&debug))
ugeth_err("%s: [%d] Missing additional data!",
- __FUNCTION__, ucc_num);
+ __func__, ucc_num);
return -ENODEV;
}
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index 6d9e7ad9fda..c001d261366 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -141,8 +141,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
struct resource res;
int k, err = 0;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
+ new_bus = mdiobus_alloc();
if (NULL == new_bus)
return -ENOMEM;
@@ -187,7 +186,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
new_bus->priv = (void __force *)regs;
- new_bus->dev = device;
+ new_bus->parent = device;
dev_set_drvdata(device, new_bus);
/* Read MII management master from device tree */
@@ -235,7 +234,7 @@ bus_register_fail:
ioremap_fail:
kfree(new_bus->irq);
reg_map_fail:
- kfree(new_bus);
+ mdiobus_free(new_bus);
return err;
}
@@ -251,7 +250,7 @@ static int uec_mdio_remove(struct of_device *ofdev)
iounmap((void __iomem *)bus->priv);
bus->priv = NULL;
- kfree(bus);
+ mdiobus_free(bus);
return 0;
}
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 0973b6e3702..8ee21030e9a 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -188,6 +188,14 @@ config USB_NET_DM9601
This option adds support for Davicom DM9601 based USB 1.1
10/100 Ethernet adapters.
+config USB_NET_SMSC95XX
+ tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
+ depends on USB_USBNET
+ select CRC32
+ help
+ This option adds support for SMSC LAN95XX based USB 2.0
+ 10/100 Ethernet adapters.
+
config USB_NET_GL620A
tristate "GeneSys GL620USB-A based cables"
depends on USB_USBNET
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index 24800c157f9..88a87eeb376 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_HSO) += hso.o
obj-$(CONFIG_USB_NET_AX8817X) += asix.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
+obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
obj-$(CONFIG_USB_NET_NET1080) += net1080.o
obj-$(CONFIG_USB_NET_PLUSB) += plusb.o
@@ -19,6 +20,3 @@ obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 22c17bbacb6..466a89e2444 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -456,7 +456,7 @@ static void catc_tx_timeout(struct net_device *netdev)
{
struct catc *catc = netdev_priv(netdev);
- warn("Transmit timed out.");
+ dev_warn(&netdev->dev, "Transmit timed out.\n");
usb_unlink_urb(catc->tx_urb);
}
@@ -847,7 +847,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
dbg("64k Memory\n");
break;
default:
- warn("Couldn't detect memory size, assuming 32k");
+ dev_warn(&intf->dev,
+ "Couldn't detect memory size, assuming 32k\n");
case 0x87654321:
catc_set_reg(catc, TxBufCount, 4);
catc_set_reg(catc, RxBufCount, 16);
@@ -953,7 +954,8 @@ static int __init catc_init(void)
{
int result = usb_register(&catc_driver);
if (result == 0)
- info(DRIVER_VERSION " " DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return result;
}
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 6e42b5a8c22..1164c52e2c0 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -92,9 +92,6 @@
#define HSO_NET_TX_TIMEOUT (HZ*10)
-/* Serial port defines and structs. */
-#define HSO_SERIAL_FLAG_RX_SENT 0
-
#define HSO_SERIAL_MAGIC 0x48534f31
/* Number of ttys to handle */
@@ -179,6 +176,12 @@ struct hso_net {
unsigned long flags;
};
+enum rx_ctrl_state{
+ RX_IDLE,
+ RX_SENT,
+ RX_PENDING
+};
+
struct hso_serial {
struct hso_device *parent;
int magic;
@@ -205,7 +208,7 @@ struct hso_serial {
struct usb_endpoint_descriptor *in_endp;
struct usb_endpoint_descriptor *out_endp;
- unsigned long flags;
+ enum rx_ctrl_state rx_state;
u8 rts_state;
u8 dtr_state;
unsigned tx_urb_used:1;
@@ -216,6 +219,15 @@ struct hso_serial {
spinlock_t serial_lock;
int (*write_data) (struct hso_serial *serial);
+ /* Hacks required to get flow control
+ * working on the serial receive buffers
+ * so as not to drop characters on the floor.
+ */
+ int curr_rx_urb_idx;
+ u16 curr_rx_urb_offset;
+ u8 rx_urb_filled[MAX_RX_URBS];
+ struct tasklet_struct unthrottle_tasklet;
+ struct work_struct retry_unthrottle_workqueue;
};
struct hso_device {
@@ -271,7 +283,7 @@ struct hso_device {
static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static void ctrl_callback(struct urb *urb);
-static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
+static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
static void hso_kick_transmit(struct hso_serial *serial);
/* Helper functions */
static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int,
@@ -287,6 +299,8 @@ static int hso_start_net_device(struct hso_device *hso_dev);
static void hso_free_shared_int(struct hso_shared_int *shared_int);
static int hso_stop_net_device(struct hso_device *hso_dev);
static void hso_serial_ref_free(struct kref *ref);
+static void hso_std_serial_read_bulk_callback(struct urb *urb);
+static int hso_mux_serial_read(struct hso_serial *serial);
static void async_get_intf(struct work_struct *data);
static void async_put_intf(struct work_struct *data);
static int hso_put_activity(struct hso_device *hso_dev);
@@ -458,6 +472,17 @@ static ssize_t hso_sysfs_show_porttype(struct device *dev,
}
static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL);
+static int hso_urb_to_index(struct hso_serial *serial, struct urb *urb)
+{
+ int idx;
+
+ for (idx = 0; idx < serial->num_rx_urbs; idx++)
+ if (serial->rx_urb[idx] == urb)
+ return idx;
+ dev_err(serial->parent->dev, "hso_urb_to_index failed\n");
+ return -1;
+}
+
/* converts mux value to a port spec value */
static u32 hso_mux_to_port(int mux)
{
@@ -1039,6 +1064,158 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
return;
}
+static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb)
+{
+ int result;
+#ifdef CONFIG_HSO_AUTOPM
+ usb_mark_last_busy(urb->dev);
+#endif
+ /* We are done with this URB, resubmit it. Prep the USB to wait for
+ * another frame */
+ usb_fill_bulk_urb(urb, serial->parent->usb,
+ usb_rcvbulkpipe(serial->parent->usb,
+ serial->in_endp->
+ bEndpointAddress & 0x7F),
+ urb->transfer_buffer, serial->rx_data_length,
+ hso_std_serial_read_bulk_callback, serial);
+ /* Give this to the USB subsystem so it can tell us when more data
+ * arrives. */
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d\n",
+ __func__, result);
+ }
+}
+
+
+
+
+static void put_rxbuf_data_and_resubmit_bulk_urb(struct hso_serial *serial)
+{
+ int count;
+ struct urb *curr_urb;
+
+ while (serial->rx_urb_filled[serial->curr_rx_urb_idx]) {
+ curr_urb = serial->rx_urb[serial->curr_rx_urb_idx];
+ count = put_rxbuf_data(curr_urb, serial);
+ if (count == -1)
+ return;
+ if (count == 0) {
+ serial->curr_rx_urb_idx++;
+ if (serial->curr_rx_urb_idx >= serial->num_rx_urbs)
+ serial->curr_rx_urb_idx = 0;
+ hso_resubmit_rx_bulk_urb(serial, curr_urb);
+ }
+ }
+}
+
+static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial)
+{
+ int count = 0;
+ struct urb *urb;
+
+ urb = serial->rx_urb[0];
+ if (serial->open_count > 0) {
+ count = put_rxbuf_data(urb, serial);
+ if (count == -1)
+ return;
+ }
+ /* Re issue a read as long as we receive data. */
+
+ if (count == 0 && ((urb->actual_length != 0) ||
+ (serial->rx_state == RX_PENDING))) {
+ serial->rx_state = RX_SENT;
+ hso_mux_serial_read(serial);
+ } else
+ serial->rx_state = RX_IDLE;
+}
+
+
+/* read callback for Diag and CS port */
+static void hso_std_serial_read_bulk_callback(struct urb *urb)
+{
+ struct hso_serial *serial = urb->context;
+ int status = urb->status;
+
+ /* sanity check */
+ if (!serial) {
+ D1("serial == NULL");
+ return;
+ } else if (status) {
+ log_usb_status(status, __func__);
+ return;
+ }
+
+ D4("\n--- Got serial_read_bulk callback %02x ---", status);
+ D1("Actual length = %d\n", urb->actual_length);
+ DUMP1(urb->transfer_buffer, urb->actual_length);
+
+ /* Anyone listening? */
+ if (serial->open_count == 0)
+ return;
+
+ if (status == 0) {
+ if (serial->parent->port_spec & HSO_INFO_CRC_BUG) {
+ u32 rest;
+ u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
+ rest =
+ urb->actual_length %
+ serial->in_endp->wMaxPacketSize;
+ if (((rest == 5) || (rest == 6))
+ && !memcmp(((u8 *) urb->transfer_buffer) +
+ urb->actual_length - 4, crc_check, 4)) {
+ urb->actual_length -= 4;
+ }
+ }
+ /* Valid data, handle RX data */
+ spin_lock(&serial->serial_lock);
+ serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
+ put_rxbuf_data_and_resubmit_bulk_urb(serial);
+ spin_unlock(&serial->serial_lock);
+ } else if (status == -ENOENT || status == -ECONNRESET) {
+ /* Unlinked - check for throttled port. */
+ D2("Port %d, successfully unlinked urb", serial->minor);
+ spin_lock(&serial->serial_lock);
+ serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
+ hso_resubmit_rx_bulk_urb(serial, urb);
+ spin_unlock(&serial->serial_lock);
+ } else {
+ D2("Port %d, status = %d for read urb", serial->minor, status);
+ return;
+ }
+}
+
+/*
+ * This needs to be a tasklet otherwise we will
+ * end up recursively calling this function.
+ */
+void hso_unthrottle_tasklet(struct hso_serial *serial)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&serial->serial_lock, flags);
+ if ((serial->parent->port_spec & HSO_INTF_MUX))
+ put_rxbuf_data_and_resubmit_ctrl_urb(serial);
+ else
+ put_rxbuf_data_and_resubmit_bulk_urb(serial);
+ spin_unlock_irqrestore(&serial->serial_lock, flags);
+}
+
+static void hso_unthrottle(struct tty_struct *tty)
+{
+ struct hso_serial *serial = get_serial_by_tty(tty);
+
+ tasklet_hi_schedule(&serial->unthrottle_tasklet);
+}
+
+void hso_unthrottle_workfunc(struct work_struct *work)
+{
+ struct hso_serial *serial =
+ container_of(work, struct hso_serial,
+ retry_unthrottle_workqueue);
+ hso_unthrottle_tasklet(serial);
+}
+
/* open the requested serial port */
static int hso_serial_open(struct tty_struct *tty, struct file *filp)
{
@@ -1064,13 +1241,18 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
tty->driver_data = serial;
serial->tty = tty;
- /* check for port allready opened, if not set the termios */
+ /* check for port already opened, if not set the termios */
serial->open_count++;
if (serial->open_count == 1) {
tty->low_latency = 1;
- serial->flags = 0;
+ serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
+ tasklet_init(&serial->unthrottle_tasklet,
+ (void (*)(unsigned long))hso_unthrottle_tasklet,
+ (unsigned long)serial);
+ INIT_WORK(&serial->retry_unthrottle_workqueue,
+ hso_unthrottle_workfunc);
result = hso_start_serial_device(serial->parent, GFP_KERNEL);
if (result) {
hso_stop_serial_device(serial->parent);
@@ -1117,9 +1299,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
}
if (!usb_gone)
hso_stop_serial_device(serial->parent);
+ tasklet_kill(&serial->unthrottle_tasklet);
+ cancel_work_sync(&serial->retry_unthrottle_workqueue);
}
+
if (!usb_gone)
usb_autopm_put_interface(serial->parent->interface);
+
mutex_unlock(&serial->parent->mutex);
}
@@ -1422,15 +1608,21 @@ static void intr_callback(struct urb *urb)
(1 << i));
if (serial != NULL) {
D1("Pending read interrupt on port %d\n", i);
- if (!test_and_set_bit(HSO_SERIAL_FLAG_RX_SENT,
- &serial->flags)) {
+ spin_lock(&serial->serial_lock);
+ if (serial->rx_state == RX_IDLE) {
/* Setup and send a ctrl req read on
* port i */
- hso_mux_serial_read(serial);
+ if (!serial->rx_urb_filled[0]) {
+ serial->rx_state = RX_SENT;
+ hso_mux_serial_read(serial);
+ } else
+ serial->rx_state = RX_PENDING;
+
} else {
D1("Already pending a read on "
"port %d\n", i);
}
+ spin_unlock(&serial->serial_lock);
}
}
}
@@ -1532,16 +1724,10 @@ static void ctrl_callback(struct urb *urb)
if (req->bRequestType ==
(USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) {
/* response to a read command */
- if (serial->open_count > 0) {
- /* handle RX data the normal way */
- put_rxbuf_data(urb, serial);
- }
-
- /* Re issue a read as long as we receive data. */
- if (urb->actual_length != 0)
- hso_mux_serial_read(serial);
- else
- clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags);
+ serial->rx_urb_filled[0] = 1;
+ spin_lock(&serial->serial_lock);
+ put_rxbuf_data_and_resubmit_ctrl_urb(serial);
+ spin_unlock(&serial->serial_lock);
} else {
hso_put_activity(serial->parent);
if (serial->tty)
@@ -1552,91 +1738,42 @@ static void ctrl_callback(struct urb *urb)
}
/* handle RX data for serial port */
-static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
+static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
{
struct tty_struct *tty = serial->tty;
-
+ int write_length_remaining = 0;
+ int curr_write_len;
/* Sanity check */
if (urb == NULL || serial == NULL) {
D1("serial = NULL");
- return;
+ return -2;
}
/* Push data to tty */
- if (tty && urb->actual_length) {
+ if (tty) {
+ write_length_remaining = urb->actual_length -
+ serial->curr_rx_urb_offset;
D1("data to push to tty");
- tty_insert_flip_string(tty, urb->transfer_buffer,
- urb->actual_length);
- tty_flip_buffer_push(tty);
- }
-}
-
-/* read callback for Diag and CS port */
-static void hso_std_serial_read_bulk_callback(struct urb *urb)
-{
- struct hso_serial *serial = urb->context;
- int result;
- int status = urb->status;
-
- /* sanity check */
- if (!serial) {
- D1("serial == NULL");
- return;
- } else if (status) {
- log_usb_status(status, __func__);
- return;
- }
-
- D4("\n--- Got serial_read_bulk callback %02x ---", status);
- D1("Actual length = %d\n", urb->actual_length);
- DUMP1(urb->transfer_buffer, urb->actual_length);
-
- /* Anyone listening? */
- if (serial->open_count == 0)
- return;
-
- if (status == 0) {
- if (serial->parent->port_spec & HSO_INFO_CRC_BUG) {
- u32 rest;
- u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
- rest =
- urb->actual_length %
- serial->in_endp->wMaxPacketSize;
- if (((rest == 5) || (rest == 6))
- && !memcmp(((u8 *) urb->transfer_buffer) +
- urb->actual_length - 4, crc_check, 4)) {
- urb->actual_length -= 4;
- }
+ while (write_length_remaining) {
+ if (test_bit(TTY_THROTTLED, &tty->flags))
+ return -1;
+ curr_write_len = tty_insert_flip_string
+ (tty, urb->transfer_buffer +
+ serial->curr_rx_urb_offset,
+ write_length_remaining);
+ serial->curr_rx_urb_offset += curr_write_len;
+ write_length_remaining -= curr_write_len;
+ tty_flip_buffer_push(tty);
}
- /* Valid data, handle RX data */
- put_rxbuf_data(urb, serial);
- } else if (status == -ENOENT || status == -ECONNRESET) {
- /* Unlinked - check for throttled port. */
- D2("Port %d, successfully unlinked urb", serial->minor);
- } else {
- D2("Port %d, status = %d for read urb", serial->minor, status);
- return;
}
-
- usb_mark_last_busy(urb->dev);
-
- /* We are done with this URB, resubmit it. Prep the USB to wait for
- * another frame */
- usb_fill_bulk_urb(urb, serial->parent->usb,
- usb_rcvbulkpipe(serial->parent->usb,
- serial->in_endp->
- bEndpointAddress & 0x7F),
- urb->transfer_buffer, serial->rx_data_length,
- hso_std_serial_read_bulk_callback, serial);
- /* Give this to the USB subsystem so it can tell us when more data
- * arrives. */
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d",
- __func__, result);
+ if (write_length_remaining == 0) {
+ serial->curr_rx_urb_offset = 0;
+ serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
}
+ return write_length_remaining;
}
+
/* Base driver functions */
static void hso_log_port(struct hso_device *hso_dev)
@@ -1794,9 +1931,13 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
return -ENODEV;
for (i = 0; i < serial->num_rx_urbs; i++) {
- if (serial->rx_urb[i])
+ if (serial->rx_urb[i]) {
usb_kill_urb(serial->rx_urb[i]);
+ serial->rx_urb_filled[i] = 0;
+ }
}
+ serial->curr_rx_urb_idx = 0;
+ serial->curr_rx_urb_offset = 0;
if (serial->tx_urb)
usb_kill_urb(serial->tx_urb);
@@ -2211,14 +2352,14 @@ static struct hso_device *hso_create_bulk_serial_device(
USB_DIR_IN);
if (!serial->in_endp) {
dev_err(&interface->dev, "Failed to find BULK IN ep\n");
- goto exit;
+ goto exit2;
}
if (!
(serial->out_endp =
hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT))) {
dev_err(&interface->dev, "Failed to find BULK IN ep\n");
- goto exit;
+ goto exit2;
}
serial->write_data = hso_std_serial_write_data;
@@ -2231,9 +2372,10 @@ static struct hso_device *hso_create_bulk_serial_device(
/* done, return it */
return hso_dev;
+
+exit2:
+ hso_serial_common_free(serial);
exit:
- if (hso_dev && serial)
- hso_serial_common_free(serial);
kfree(serial);
hso_free_device(hso_dev);
return NULL;
@@ -2740,6 +2882,7 @@ static const struct tty_operations hso_serial_ops = {
.chars_in_buffer = hso_serial_chars_in_buffer,
.tiocmget = hso_serial_tiocmget,
.tiocmset = hso_serial_tiocmset,
+ .unthrottle = hso_unthrottle
};
static struct usb_driver hso_driver = {
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index d6829db51b4..fdbf3be24fd 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -832,7 +832,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
{
- warn("kaweth failed tx_urb %d", res);
+ dev_warn(&net->dev, "kaweth failed tx_urb %d\n", res);
skip:
kaweth->stats.tx_errors++;
@@ -924,7 +924,7 @@ static void kaweth_tx_timeout(struct net_device *net)
{
struct kaweth_device *kaweth = netdev_priv(net);
- warn("%s: Tx timed out. Resetting.", net->name);
+ dev_warn(&net->dev, "%s: Tx timed out. Resetting.\n", net->name);
kaweth->stats.tx_errors++;
net->trans_start = jiffies;
@@ -1016,10 +1016,10 @@ static int kaweth_probe(
*/
if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) {
- info("Firmware present in device.");
+ dev_info(&intf->dev, "Firmware present in device.\n");
} else {
/* Download the firmware */
- info("Downloading firmware...");
+ dev_info(&intf->dev, "Downloading firmware...\n");
kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
if ((result = kaweth_download_firmware(kaweth,
"kaweth/new_code.bin",
@@ -1061,7 +1061,7 @@ static int kaweth_probe(
}
/* Device will now disappear for a moment... */
- info("Firmware loaded. I'll be back...");
+ dev_info(&intf->dev, "Firmware loaded. I'll be back...\n");
err_fw:
free_page((unsigned long)kaweth->firmware_buf);
free_netdev(netdev);
@@ -1075,10 +1075,10 @@ err_fw:
goto err_free_netdev;
}
- info("Statistics collection: %x", kaweth->configuration.statistics_mask);
- info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
- info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size));
- info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ dev_info(&intf->dev, "Statistics collection: %x\n", kaweth->configuration.statistics_mask);
+ dev_info(&intf->dev, "Multicast filter limit: %x\n", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
+ dev_info(&intf->dev, "MTU: %d\n", le16_to_cpu(kaweth->configuration.segment_size));
+ dev_info(&intf->dev, "Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
(int)kaweth->configuration.hw_addr[0],
(int)kaweth->configuration.hw_addr[1],
(int)kaweth->configuration.hw_addr[2],
@@ -1174,7 +1174,8 @@ err_fw:
goto err_intfdata;
}
- info("kaweth interface created at %s", kaweth->net->name);
+ dev_info(&intf->dev, "kaweth interface created at %s\n",
+ kaweth->net->name);
dbg("Kaweth probe returning.");
@@ -1205,11 +1206,11 @@ static void kaweth_disconnect(struct usb_interface *intf)
struct kaweth_device *kaweth = usb_get_intfdata(intf);
struct net_device *netdev;
- info("Unregistering");
+ dev_info(&intf->dev, "Unregistering\n");
usb_set_intfdata(intf, NULL);
if (!kaweth) {
- warn("unregistering non-existant device");
+ dev_warn(&intf->dev, "unregistering non-existant device\n");
return;
}
netdev = kaweth->net;
@@ -1269,7 +1270,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
// timeout
- warn("usb_control/bulk_msg: timeout");
+ dev_warn(&urb->dev->dev, "usb_control/bulk_msg: timeout\n");
usb_kill_urb(urb); // remove urb safely
status = -ETIMEDOUT;
}
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index ca9d00c1194..b5143509e8b 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -118,7 +118,7 @@ static void mcs7830_async_cmd_callback(struct urb *urb)
if (urb->status < 0)
printk(KERN_DEBUG "%s() failed with %d\n",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
kfree(req);
usb_free_urb(urb);
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index a84ba487c71..38b90e7a7ed 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -117,9 +117,9 @@ static void ctrl_callback(struct urb *urb)
case -ENOENT:
break;
default:
- if (netif_msg_drv(pegasus))
+ if (netif_msg_drv(pegasus) && printk_ratelimit())
dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
wake_up(&pegasus->ctrl_wait);
@@ -136,7 +136,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
if (!buffer) {
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
add_wait_queue(&pegasus->ctrl_wait, &wait);
@@ -166,7 +166,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
set_current_state(TASK_RUNNING);
if (ret == -ENODEV)
netif_device_detach(pegasus->net);
- if (netif_msg_drv(pegasus))
+ if (netif_msg_drv(pegasus) && printk_ratelimit())
dev_err(&pegasus->intf->dev, "%s, status %d\n",
__FUNCTION__, ret);
goto out;
@@ -224,7 +224,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus))
dev_err(&pegasus->intf->dev, "%s, status %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
goto out;
}
@@ -246,7 +246,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
if (!tmp) {
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
memcpy(tmp, &data, 1);
@@ -275,9 +275,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
if (ret == -ENODEV)
netif_device_detach(pegasus->net);
- if (netif_msg_drv(pegasus))
+ if (netif_msg_drv(pegasus) && printk_ratelimit())
dev_err(&pegasus->intf->dev, "%s, status %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
goto out;
}
@@ -310,7 +310,7 @@ static int update_eth_regs_async(pegasus_t * pegasus)
netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus))
dev_err(&pegasus->intf->dev, "%s, status %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
}
return ret;
@@ -341,7 +341,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
}
fail:
if (netif_msg_drv(pegasus))
- dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
+ dev_warn(&pegasus->intf->dev, "%s failed\n", __func__);
return ret;
}
@@ -378,7 +378,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
fail:
if (netif_msg_drv(pegasus))
- dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
+ dev_warn(&pegasus->intf->dev, "%s failed\n", __func__);
return -ETIMEDOUT;
}
@@ -415,7 +415,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
fail:
if (netif_msg_drv(pegasus))
- dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
+ dev_warn(&pegasus->intf->dev, "%s failed\n", __func__);
return -ETIMEDOUT;
}
@@ -463,7 +463,7 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
return ret;
fail:
if (netif_msg_drv(pegasus))
- dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
+ dev_warn(&pegasus->intf->dev, "%s failed\n", __func__);
return -ETIMEDOUT;
}
#endif /* PEGASUS_WRITE_EEPROM */
@@ -1209,8 +1209,7 @@ static void pegasus_set_multicast(struct net_device *net)
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
if (netif_msg_link(pegasus))
pr_info("%s: Promiscuous mode enabled.\n", net->name);
- } else if (net->mc_count ||
- (net->flags & IFF_ALLMULTI)) {
+ } else if (net->mc_count || (net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
if (netif_msg_link(pegasus))
@@ -1220,6 +1219,8 @@ static void pegasus_set_multicast(struct net_device *net)
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
}
+ pegasus->ctrl_urb->status = 0;
+
pegasus->flags |= ETH_REGS_CHANGE;
ctrl_callback(pegasus->ctrl_urb);
}
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index df56a518691..6133401ebc6 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -221,7 +221,7 @@ static void ctrl_callback(struct urb *urb)
case -ENOENT:
break;
default:
- warn("ctrl urb status %d", urb->status);
+ dev_warn(&urb->dev->dev, "ctrl urb status %d\n", urb->status);
}
dev = urb->context;
clear_bit(RX_REG_SET, &dev->flags);
@@ -441,10 +441,10 @@ static void read_bulk_callback(struct urb *urb)
case -ENOENT:
return; /* the urb is in unlink state */
case -ETIME:
- warn("may be reset is needed?..");
+ dev_warn(&urb->dev->dev, "may be reset is needed?..\n");
goto goon;
default:
- warn("Rx status %d", urb->status);
+ dev_warn(&urb->dev->dev, "Rx status %d\n", urb->status);
goto goon;
}
@@ -538,7 +538,8 @@ static void write_bulk_callback(struct urb *urb)
if (!netif_device_present(dev->netdev))
return;
if (urb->status)
- info("%s: Tx status %d", dev->netdev->name, urb->status);
+ dev_info(&urb->dev->dev, "%s: Tx status %d\n",
+ dev->netdev->name, urb->status);
dev->netdev->trans_start = jiffies;
netif_wake_queue(dev->netdev);
}
@@ -561,7 +562,8 @@ static void intr_callback(struct urb *urb)
return;
/* -EPIPE: should clear the halt */
default:
- info("%s: intr status %d", dev->netdev->name, urb->status);
+ dev_info(&urb->dev->dev, "%s: intr status %d\n",
+ dev->netdev->name, urb->status);
goto resubmit;
}
@@ -665,7 +667,7 @@ static int enable_net_traffic(rtl8150_t * dev)
u8 cr, tcr, rcr, msr;
if (!rtl8150_reset(dev)) {
- warn("%s - device reset failed", __FUNCTION__);
+ dev_warn(&dev->udev->dev, "device reset failed\n");
}
/* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */
rcr = 0x9e;
@@ -699,7 +701,7 @@ static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev)
static void rtl8150_tx_timeout(struct net_device *netdev)
{
rtl8150_t *dev = netdev_priv(netdev);
- warn("%s: Tx timeout.", netdev->name);
+ dev_warn(&netdev->dev, "Tx timeout.\n");
usb_unlink_urb(dev->tx_urb);
dev->stats.tx_errors++;
}
@@ -710,12 +712,12 @@ static void rtl8150_set_multicast(struct net_device *netdev)
netif_stop_queue(netdev);
if (netdev->flags & IFF_PROMISC) {
dev->rx_creg |= cpu_to_le16(0x0001);
- info("%s: promiscuous mode", netdev->name);
+ dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name);
} else if (netdev->mc_count ||
(netdev->flags & IFF_ALLMULTI)) {
dev->rx_creg &= cpu_to_le16(0xfffe);
dev->rx_creg |= cpu_to_le16(0x0002);
- info("%s: allmulti set", netdev->name);
+ dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name);
} else {
/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
dev->rx_creg &= cpu_to_le16(0x00fc);
@@ -740,7 +742,7 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if (res == -ENODEV)
netif_device_detach(dev->netdev);
else {
- warn("failed tx_urb %d\n", res);
+ dev_warn(&netdev->dev, "failed tx_urb %d\n", res);
dev->stats.tx_errors++;
netif_start_queue(netdev);
}
@@ -783,7 +785,7 @@ static int rtl8150_open(struct net_device *netdev)
if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
if (res == -ENODEV)
netif_device_detach(dev->netdev);
- warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
+ dev_warn(&netdev->dev, "rx_urb submit failed: %d\n", res);
return res;
}
usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
@@ -792,7 +794,7 @@ static int rtl8150_open(struct net_device *netdev)
if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
if (res == -ENODEV)
netif_device_detach(dev->netdev);
- warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
+ dev_warn(&netdev->dev, "intr_urb submit failed: %d\n", res);
usb_kill_urb(dev->rx_urb);
return res;
}
@@ -947,7 +949,7 @@ static int rtl8150_probe(struct usb_interface *intf,
goto out2;
}
- info("%s: rtl8150 is detected", netdev->name);
+ dev_info(&intf->dev, "%s: rtl8150 is detected\n", netdev->name);
return 0;
@@ -984,7 +986,8 @@ static void rtl8150_disconnect(struct usb_interface *intf)
static int __init usb_rtl8150_init(void)
{
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return usb_register(&rtl8150_driver);
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
new file mode 100644
index 00000000000..51e2f5d7d14
--- /dev/null
+++ b/drivers/net/usb/smsc95xx.c
@@ -0,0 +1,1225 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007-2008 SMSC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+#include "smsc95xx.h"
+
+#define SMSC_CHIPNAME "smsc95xx"
+#define SMSC_DRIVER_VERSION "1.0.3"
+#define HS_USB_PKT_SIZE (512)
+#define FS_USB_PKT_SIZE (64)
+#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
+#define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE)
+#define DEFAULT_BULK_IN_DELAY (0x00002000)
+#define MAX_SINGLE_PACKET_SIZE (2048)
+#define LAN95XX_EEPROM_MAGIC (0x9500)
+#define EEPROM_MAC_OFFSET (0x01)
+#define DEFAULT_RX_CSUM_ENABLE (true)
+#define SMSC95XX_INTERNAL_PHY_ID (1)
+#define SMSC95XX_TX_OVERHEAD (8)
+#define FLOW_CTRL_TX (1)
+#define FLOW_CTRL_RX (2)
+
+struct smsc95xx_priv {
+ u32 mac_cr;
+ spinlock_t mac_cr_lock;
+ bool use_rx_csum;
+};
+
+struct usb_context {
+ struct usb_ctrlrequest req;
+ struct completion notify;
+ struct usbnet *dev;
+};
+
+int turbo_mode = true;
+module_param(turbo_mode, bool, 0644);
+MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+
+static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
+{
+ u32 *buf = kmalloc(4, GFP_KERNEL);
+ int ret;
+
+ BUG_ON(!dev);
+
+ if (!buf)
+ return -ENOMEM;
+
+ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ USB_VENDOR_REQUEST_READ_REGISTER,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+
+ if (unlikely(ret < 0))
+ devwarn(dev, "Failed to read register index 0x%08x", index);
+
+ le32_to_cpus(buf);
+ *data = *buf;
+ kfree(buf);
+
+ return ret;
+}
+
+static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data)
+{
+ u32 *buf = kmalloc(4, GFP_KERNEL);
+ int ret;
+
+ BUG_ON(!dev);
+
+ if (!buf)
+ return -ENOMEM;
+
+ *buf = data;
+ cpu_to_le32s(buf);
+
+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_VENDOR_REQUEST_WRITE_REGISTER,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+
+ if (unlikely(ret < 0))
+ devwarn(dev, "Failed to write register index 0x%08x", index);
+
+ kfree(buf);
+
+ return ret;
+}
+
+/* Loop until the read is completed with timeout
+ * called with phy_mutex held */
+static int smsc95xx_phy_wait_not_busy(struct usbnet *dev)
+{
+ unsigned long start_time = jiffies;
+ u32 val;
+
+ do {
+ smsc95xx_read_reg(dev, MII_ADDR, &val);
+ if (!(val & MII_BUSY_))
+ return 0;
+ } while (!time_after(jiffies, start_time + HZ));
+
+ return -EIO;
+}
+
+static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u32 val, addr;
+
+ mutex_lock(&dev->phy_mutex);
+
+ /* confirm MII not busy */
+ if (smsc95xx_phy_wait_not_busy(dev)) {
+ devwarn(dev, "MII is busy in smsc95xx_mdio_read");
+ mutex_unlock(&dev->phy_mutex);
+ return -EIO;
+ }
+
+ /* set the address, index & direction (read from PHY) */
+ phy_id &= dev->mii.phy_id_mask;
+ idx &= dev->mii.reg_num_mask;
+ addr = (phy_id << 11) | (idx << 6) | MII_READ_;
+ smsc95xx_write_reg(dev, MII_ADDR, addr);
+
+ if (smsc95xx_phy_wait_not_busy(dev)) {
+ devwarn(dev, "Timed out reading MII reg %02X", idx);
+ mutex_unlock(&dev->phy_mutex);
+ return -EIO;
+ }
+
+ smsc95xx_read_reg(dev, MII_DATA, &val);
+
+ mutex_unlock(&dev->phy_mutex);
+
+ return (u16)(val & 0xFFFF);
+}
+
+static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+ int regval)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u32 val, addr;
+
+ mutex_lock(&dev->phy_mutex);
+
+ /* confirm MII not busy */
+ if (smsc95xx_phy_wait_not_busy(dev)) {
+ devwarn(dev, "MII is busy in smsc95xx_mdio_write");
+ mutex_unlock(&dev->phy_mutex);
+ return;
+ }
+
+ val = regval;
+ smsc95xx_write_reg(dev, MII_DATA, val);
+
+ /* set the address, index & direction (write to PHY) */
+ phy_id &= dev->mii.phy_id_mask;
+ idx &= dev->mii.reg_num_mask;
+ addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
+ smsc95xx_write_reg(dev, MII_ADDR, addr);
+
+ if (smsc95xx_phy_wait_not_busy(dev))
+ devwarn(dev, "Timed out writing MII reg %02X", idx);
+
+ mutex_unlock(&dev->phy_mutex);
+}
+
+static int smsc95xx_wait_eeprom(struct usbnet *dev)
+{
+ unsigned long start_time = jiffies;
+ u32 val;
+
+ do {
+ smsc95xx_read_reg(dev, E2P_CMD, &val);
+ if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
+ break;
+ udelay(40);
+ } while (!time_after(jiffies, start_time + HZ));
+
+ if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) {
+ devwarn(dev, "EEPROM read operation timeout");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
+{
+ unsigned long start_time = jiffies;
+ u32 val;
+
+ do {
+ smsc95xx_read_reg(dev, E2P_CMD, &val);
+
+ if (!(val & E2P_CMD_LOADED_)) {
+ devwarn(dev, "No EEPROM present");
+ return -EIO;
+ }
+
+ if (!(val & E2P_CMD_BUSY_))
+ return 0;
+
+ udelay(40);
+ } while (!time_after(jiffies, start_time + HZ));
+
+ devwarn(dev, "EEPROM is busy");
+ return -EIO;
+}
+
+static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
+ u8 *data)
+{
+ u32 val;
+ int i, ret;
+
+ BUG_ON(!dev);
+ BUG_ON(!data);
+
+ ret = smsc95xx_eeprom_confirm_not_busy(dev);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < length; i++) {
+ val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
+ smsc95xx_write_reg(dev, E2P_CMD, val);
+
+ ret = smsc95xx_wait_eeprom(dev);
+ if (ret < 0)
+ return ret;
+
+ smsc95xx_read_reg(dev, E2P_DATA, &val);
+
+ data[i] = val & 0xFF;
+ offset++;
+ }
+
+ return 0;
+}
+
+static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
+ u8 *data)
+{
+ u32 val;
+ int i, ret;
+
+ BUG_ON(!dev);
+ BUG_ON(!data);
+
+ ret = smsc95xx_eeprom_confirm_not_busy(dev);
+ if (ret)
+ return ret;
+
+ /* Issue write/erase enable command */
+ val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
+ smsc95xx_write_reg(dev, E2P_CMD, val);
+
+ ret = smsc95xx_wait_eeprom(dev);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < length; i++) {
+
+ /* Fill data register */
+ val = data[i];
+ smsc95xx_write_reg(dev, E2P_DATA, val);
+
+ /* Send "write" command */
+ val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
+ smsc95xx_write_reg(dev, E2P_CMD, val);
+
+ ret = smsc95xx_wait_eeprom(dev);
+ if (ret < 0)
+ return ret;
+
+ offset++;
+ }
+
+ return 0;
+}
+
+static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_context *usb_context = urb->context;
+ struct usbnet *dev = usb_context->dev;
+
+ if (urb->status < 0)
+ devwarn(dev, "async callback failed with %d", urb->status);
+
+ complete(&usb_context->notify);
+
+ kfree(usb_context);
+ usb_free_urb(urb);
+}
+
+static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data)
+{
+ struct usb_context *usb_context;
+ int status;
+ struct urb *urb;
+ const u16 size = 4;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ devwarn(dev, "Error allocating URB");
+ return -ENOMEM;
+ }
+
+ usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC);
+ if (usb_context == NULL) {
+ devwarn(dev, "Error allocating control msg");
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ usb_context->req.bRequestType =
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+ usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER;
+ usb_context->req.wValue = 00;
+ usb_context->req.wIndex = cpu_to_le16(index);
+ usb_context->req.wLength = cpu_to_le16(size);
+ init_completion(&usb_context->notify);
+
+ usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ (void *)&usb_context->req, data, size,
+ (usb_complete_t)smsc95xx_async_cmd_callback,
+ (void *)usb_context);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status < 0) {
+ devwarn(dev, "Error submitting control msg, sts=%d", status);
+ kfree(usb_context);
+ usb_free_urb(urb);
+ }
+
+ return status;
+}
+
+/* returns hash bit number for given MAC address
+ * example:
+ * 01 00 5E 00 00 01 -> returns bit number 31 */
+static unsigned int smsc95xx_hash(char addr[ETH_ALEN])
+{
+ return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
+}
+
+static void smsc95xx_set_multicast(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u32 hash_hi = 0;
+ u32 hash_lo = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+
+ if (dev->net->flags & IFF_PROMISC) {
+ if (netif_msg_drv(dev))
+ devdbg(dev, "promiscuous mode enabled");
+ pdata->mac_cr |= MAC_CR_PRMS_;
+ pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+ } else if (dev->net->flags & IFF_ALLMULTI) {
+ if (netif_msg_drv(dev))
+ devdbg(dev, "receive all multicast enabled");
+ pdata->mac_cr |= MAC_CR_MCPAS_;
+ pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_);
+ } else if (dev->net->mc_count > 0) {
+ struct dev_mc_list *mc_list = dev->net->mc_list;
+ int count = 0;
+
+ pdata->mac_cr |= MAC_CR_HPFILT_;
+ pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+ while (mc_list) {
+ count++;
+ if (mc_list->dmi_addrlen == ETH_ALEN) {
+ u32 bitnum = smsc95xx_hash(mc_list->dmi_addr);
+ u32 mask = 0x01 << (bitnum & 0x1F);
+ if (bitnum & 0x20)
+ hash_hi |= mask;
+ else
+ hash_lo |= mask;
+ } else {
+ devwarn(dev, "dmi_addrlen != 6");
+ }
+ mc_list = mc_list->next;
+ }
+
+ if (count != ((u32)dev->net->mc_count))
+ devwarn(dev, "mc_count != dev->mc_count");
+
+ if (netif_msg_drv(dev))
+ devdbg(dev, "HASHH=0x%08X, HASHL=0x%08X", hash_hi,
+ hash_lo);
+ } else {
+ if (netif_msg_drv(dev))
+ devdbg(dev, "receive own packets only");
+ pdata->mac_cr &=
+ ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+ }
+
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ /* Initiate async writes, as we can't wait for completion here */
+ smsc95xx_write_reg_async(dev, HASHH, &hash_hi);
+ smsc95xx_write_reg_async(dev, HASHL, &hash_lo);
+ smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
+}
+
+static u8 smsc95xx_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv)
+{
+ u8 cap = 0;
+
+ if (lcladv & ADVERTISE_PAUSE_CAP) {
+ if (lcladv & ADVERTISE_PAUSE_ASYM) {
+ if (rmtadv & LPA_PAUSE_CAP)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ else if (rmtadv & LPA_PAUSE_ASYM)
+ cap = FLOW_CTRL_RX;
+ } else {
+ if (rmtadv & LPA_PAUSE_CAP)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+ if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+ cap = FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
+ u16 lcladv, u16 rmtadv)
+{
+ u32 flow, afc_cfg = 0;
+
+ int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
+ if (ret < 0) {
+ devwarn(dev, "error reading AFC_CFG");
+ return;
+ }
+
+ if (duplex == DUPLEX_FULL) {
+ u8 cap = smsc95xx_resolve_flowctrl_fulldplx(lcladv, rmtadv);
+
+ if (cap & FLOW_CTRL_RX)
+ flow = 0xFFFF0002;
+ else
+ flow = 0;
+
+ if (cap & FLOW_CTRL_TX)
+ afc_cfg |= 0xF;
+ else
+ afc_cfg &= ~0xF;
+
+ if (netif_msg_link(dev))
+ devdbg(dev, "rx pause %s, tx pause %s",
+ (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+ (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+ } else {
+ if (netif_msg_link(dev))
+ devdbg(dev, "half duplex");
+ flow = 0;
+ afc_cfg |= 0xF;
+ }
+
+ smsc95xx_write_reg(dev, FLOW, flow);
+ smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
+}
+
+static int smsc95xx_link_reset(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ struct mii_if_info *mii = &dev->mii;
+ struct ethtool_cmd ecmd;
+ unsigned long flags;
+ u16 lcladv, rmtadv;
+ u32 intdata;
+
+ /* clear interrupt status */
+ smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
+ intdata = 0xFFFFFFFF;
+ smsc95xx_write_reg(dev, INT_STS, intdata);
+
+ mii_check_media(mii, 1, 1);
+ mii_ethtool_gset(&dev->mii, &ecmd);
+ lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
+ rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
+
+ if (netif_msg_link(dev))
+ devdbg(dev, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x",
+ ecmd.speed, ecmd.duplex, lcladv, rmtadv);
+
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+ if (ecmd.duplex != DUPLEX_FULL) {
+ pdata->mac_cr &= ~MAC_CR_FDPX_;
+ pdata->mac_cr |= MAC_CR_RCVOWN_;
+ } else {
+ pdata->mac_cr &= ~MAC_CR_RCVOWN_;
+ pdata->mac_cr |= MAC_CR_FDPX_;
+ }
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+
+ smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
+
+ return 0;
+}
+
+static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+{
+ u32 intdata;
+
+ if (urb->actual_length != 4) {
+ devwarn(dev, "unexpected urb length %d", urb->actual_length);
+ return;
+ }
+
+ memcpy(&intdata, urb->transfer_buffer, 4);
+ le32_to_cpus(&intdata);
+
+ if (netif_msg_link(dev))
+ devdbg(dev, "intdata: 0x%08X", intdata);
+
+ if (intdata & INT_ENP_PHY_INT_)
+ usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+ else
+ devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata);
+}
+
+/* Enable or disable Rx checksum offload engine */
+static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable)
+{
+ u32 read_buf;
+ int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read COE_CR: %d", ret);
+ return ret;
+ }
+
+ if (enable)
+ read_buf |= Rx_COE_EN_;
+ else
+ read_buf &= ~Rx_COE_EN_;
+
+ ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write COE_CR: %d", ret);
+ return ret;
+ }
+
+ if (netif_msg_hw(dev))
+ devdbg(dev, "COE_CR = 0x%08x", read_buf);
+ return 0;
+}
+
+static int smsc95xx_ethtool_get_eeprom_len(struct net_device *net)
+{
+ return MAX_EEPROM_SIZE;
+}
+
+static int smsc95xx_ethtool_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+
+ ee->magic = LAN95XX_EEPROM_MAGIC;
+
+ return smsc95xx_read_eeprom(dev, ee->offset, ee->len, data);
+}
+
+static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+
+ if (ee->magic != LAN95XX_EEPROM_MAGIC) {
+ devwarn(dev, "EEPROM: magic value mismatch, magic = 0x%x",
+ ee->magic);
+ return -EINVAL;
+ }
+
+ return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data);
+}
+
+static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ return pdata->use_rx_csum;
+}
+
+static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ pdata->use_rx_csum = !!val;
+
+ return smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+}
+
+static struct ethtool_ops smsc95xx_ethtool_ops = {
+ .get_link = usbnet_get_link,
+ .nway_reset = usbnet_nway_reset,
+ .get_drvinfo = usbnet_get_drvinfo,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_settings = usbnet_get_settings,
+ .set_settings = usbnet_set_settings,
+ .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
+ .get_eeprom = smsc95xx_ethtool_get_eeprom,
+ .set_eeprom = smsc95xx_ethtool_set_eeprom,
+ .get_rx_csum = smsc95xx_ethtool_get_rx_csum,
+ .set_rx_csum = smsc95xx_ethtool_set_rx_csum,
+};
+
+static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static void smsc95xx_init_mac_address(struct usbnet *dev)
+{
+ /* try reading mac address from EEPROM */
+ if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+ dev->net->dev_addr) == 0) {
+ if (is_valid_ether_addr(dev->net->dev_addr)) {
+ /* eeprom values are valid so use them */
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "MAC address read from EEPROM");
+ return;
+ }
+ }
+
+ /* no eeprom, or eeprom values are invalid. generate random MAC */
+ random_ether_addr(dev->net->dev_addr);
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "MAC address set to random_ether_addr");
+}
+
+static int smsc95xx_set_mac_address(struct usbnet *dev)
+{
+ u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
+ dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
+ u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
+ int ret;
+
+ ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write ADDRL: %d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write ADDRH: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* starts the TX path */
+static void smsc95xx_start_tx_path(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ unsigned long flags;
+ u32 reg_val;
+
+ /* Enable Tx at MAC */
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+ pdata->mac_cr |= MAC_CR_TXEN_;
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+
+ /* Enable Tx at SCSRs */
+ reg_val = TX_CFG_ON_;
+ smsc95xx_write_reg(dev, TX_CFG, reg_val);
+}
+
+/* Starts the Receive path */
+static void smsc95xx_start_rx_path(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+ pdata->mac_cr |= MAC_CR_RXEN_;
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+}
+
+static int smsc95xx_phy_initialize(struct usbnet *dev)
+{
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = smsc95xx_mdio_read;
+ dev->mii.mdio_write = smsc95xx_mdio_write;
+ dev->mii.phy_id_mask = 0x1f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID;
+
+ smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+
+ /* read to clear */
+ smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+
+ smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
+ PHY_INT_MASK_DEFAULT_);
+ mii_nway_restart(&dev->mii);
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "phy initialised succesfully");
+ return 0;
+}
+
+static int smsc95xx_reset(struct usbnet *dev)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ u32 read_buf, write_buf, burst_cap;
+ int ret = 0, timeout;
+ DECLARE_MAC_BUF(mac);
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "entering smsc95xx_reset");
+
+ write_buf = HW_CFG_LRST_;
+ ret = smsc95xx_write_reg(dev, HW_CFG, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write HW_CFG_LRST_ bit in HW_CFG "
+ "register, ret = %d", ret);
+ return ret;
+ }
+
+ timeout = 0;
+ do {
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read HW_CFG: %d", ret);
+ return ret;
+ }
+ msleep(10);
+ timeout++;
+ } while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
+
+ if (timeout >= 100) {
+ devwarn(dev, "timeout waiting for completion of Lite Reset");
+ return ret;
+ }
+
+ write_buf = PM_CTL_PHY_RST_;
+ ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write PM_CTRL: %d", ret);
+ return ret;
+ }
+
+ timeout = 0;
+ do {
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read PM_CTRL: %d", ret);
+ return ret;
+ }
+ msleep(10);
+ timeout++;
+ } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
+
+ if (timeout >= 100) {
+ devwarn(dev, "timeout waiting for PHY Reset");
+ return ret;
+ }
+
+ smsc95xx_init_mac_address(dev);
+
+ ret = smsc95xx_set_mac_address(dev);
+ if (ret < 0)
+ return ret;
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "MAC Address: %s",
+ print_mac(mac, dev->net->dev_addr));
+
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read HW_CFG: %d", ret);
+ return ret;
+ }
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from HW_CFG : 0x%08x", read_buf);
+
+ read_buf |= HW_CFG_BIR_;
+
+ ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write HW_CFG_BIR_ bit in HW_CFG "
+ "register, ret = %d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read HW_CFG: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from HW_CFG after writing "
+ "HW_CFG_BIR_: 0x%08x", read_buf);
+
+ if (!turbo_mode) {
+ burst_cap = 0;
+ dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
+ } else if (dev->udev->speed == USB_SPEED_HIGH) {
+ burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
+ dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
+ } else {
+ burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
+ dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
+ }
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "rx_urb_size=%ld", (ulong)dev->rx_urb_size);
+
+ ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write BURST_CAP: %d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read BURST_CAP: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from BURST_CAP after writing: 0x%08x",
+ read_buf);
+
+ read_buf = DEFAULT_BULK_IN_DELAY;
+ ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "ret = %d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read BULK_IN_DLY: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from BULK_IN_DLY after writing: "
+ "0x%08x", read_buf);
+
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read HW_CFG: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from HW_CFG: 0x%08x", read_buf);
+
+ if (turbo_mode)
+ read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
+
+ read_buf &= ~HW_CFG_RXDOFF_;
+
+ /* set Rx data offset=2, Make IP header aligns on word boundary. */
+ read_buf |= NET_IP_ALIGN << 9;
+
+ ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write HW_CFG register, ret=%d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read HW_CFG: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "Read Value from HW_CFG after writing: 0x%08x",
+ read_buf);
+
+ write_buf = 0xFFFFFFFF;
+ ret = smsc95xx_write_reg(dev, INT_STS, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write INT_STS register, ret=%d", ret);
+ return ret;
+ }
+
+ ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read ID_REV: %d", ret);
+ return ret;
+ }
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "ID_REV = 0x%08x", read_buf);
+
+ /* Init Tx */
+ write_buf = 0;
+ ret = smsc95xx_write_reg(dev, FLOW, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write FLOW: %d", ret);
+ return ret;
+ }
+
+ read_buf = AFC_CFG_DEFAULT;
+ ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write AFC_CFG: %d", ret);
+ return ret;
+ }
+
+ /* Don't need mac_cr_lock during initialisation */
+ ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read MAC_CR: %d", ret);
+ return ret;
+ }
+
+ /* Init Rx */
+ /* Set Vlan */
+ write_buf = (u32)ETH_P_8021Q;
+ ret = smsc95xx_write_reg(dev, VLAN1, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write VAN1: %d", ret);
+ return ret;
+ }
+
+ /* Enable or disable Rx checksum offload engine */
+ ret = smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+ if (ret < 0) {
+ devwarn(dev, "Failed to set Rx csum offload: %d", ret);
+ return ret;
+ }
+
+ smsc95xx_set_multicast(dev->net);
+
+ if (smsc95xx_phy_initialize(dev) < 0)
+ return -EIO;
+
+ ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to read INT_EP_CTL: %d", ret);
+ return ret;
+ }
+
+ /* enable PHY interrupts */
+ read_buf |= INT_EP_CTL_PHY_INT_;
+
+ ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write INT_EP_CTL: %d", ret);
+ return ret;
+ }
+
+ smsc95xx_start_tx_path(dev);
+ smsc95xx_start_rx_path(dev);
+
+ if (netif_msg_ifup(dev))
+ devdbg(dev, "smsc95xx_reset, return 0");
+ return 0;
+}
+
+static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct smsc95xx_priv *pdata = NULL;
+ int ret;
+
+ printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
+
+ ret = usbnet_get_endpoints(dev, intf);
+ if (ret < 0) {
+ devwarn(dev, "usbnet_get_endpoints failed: %d", ret);
+ return ret;
+ }
+
+ dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
+ GFP_KERNEL);
+
+ pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ if (!pdata) {
+ devwarn(dev, "Unable to allocate struct smsc95xx_priv");
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&pdata->mac_cr_lock);
+
+ pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
+
+ /* Init all registers */
+ ret = smsc95xx_reset(dev);
+
+ dev->net->do_ioctl = smsc95xx_ioctl;
+ dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
+ dev->net->set_multicast_list = smsc95xx_set_multicast;
+ dev->net->flags |= IFF_MULTICAST;
+ dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD;
+ return 0;
+}
+
+static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ if (pdata) {
+ if (netif_msg_ifdown(dev))
+ devdbg(dev, "free pdata");
+ kfree(pdata);
+ pdata = NULL;
+ dev->data[0] = 0;
+ }
+}
+
+static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
+{
+ skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb_trim(skb, skb->len - 2);
+}
+
+static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ while (skb->len > 0) {
+ u32 header, align_count;
+ struct sk_buff *ax_skb;
+ unsigned char *packet;
+ u16 size;
+
+ memcpy(&header, skb->data, sizeof(header));
+ le32_to_cpus(&header);
+ skb_pull(skb, 4 + NET_IP_ALIGN);
+ packet = skb->data;
+
+ /* get the packet length */
+ size = (u16)((header & RX_STS_FL_) >> 16);
+ align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
+
+ if (unlikely(header & RX_STS_ES_)) {
+ if (netif_msg_rx_err(dev))
+ devdbg(dev, "Error header=0x%08x", header);
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+
+ if (header & RX_STS_CRC_) {
+ dev->stats.rx_crc_errors++;
+ } else {
+ if (header & (RX_STS_TL_ | RX_STS_RF_))
+ dev->stats.rx_frame_errors++;
+
+ if ((header & RX_STS_LE_) &&
+ (!(header & RX_STS_FT_)))
+ dev->stats.rx_length_errors++;
+ }
+ } else {
+ /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
+ if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+ if (netif_msg_rx_err(dev))
+ devdbg(dev, "size err header=0x%08x",
+ header);
+ return 0;
+ }
+
+ /* last frame in this batch */
+ if (skb->len == size) {
+ if (pdata->use_rx_csum)
+ smsc95xx_rx_csum_offload(skb);
+
+ skb->truesize = size + sizeof(struct sk_buff);
+
+ return 1;
+ }
+
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!ax_skb)) {
+ devwarn(dev, "Error allocating skb");
+ return 0;
+ }
+
+ ax_skb->len = size;
+ ax_skb->data = packet;
+ skb_set_tail_pointer(ax_skb, size);
+
+ if (pdata->use_rx_csum)
+ smsc95xx_rx_csum_offload(ax_skb);
+
+ ax_skb->truesize = size + sizeof(struct sk_buff);
+
+ usbnet_skb_return(dev, ax_skb);
+ }
+
+ skb_pull(skb, size);
+
+ /* padding bytes before the next frame starts */
+ if (skb->len)
+ skb_pull(skb, align_count);
+ }
+
+ if (unlikely(skb->len < 0)) {
+ devwarn(dev, "invalid rx length<0 %d", skb->len);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
+ struct sk_buff *skb, gfp_t flags)
+{
+ u32 tx_cmd_a, tx_cmd_b;
+
+ if (skb_headroom(skb) < SMSC95XX_TX_OVERHEAD) {
+ struct sk_buff *skb2 = skb_copy_expand(skb,
+ SMSC95XX_TX_OVERHEAD, 0, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ skb_push(skb, 4);
+ tx_cmd_b = (u32)(skb->len - 4);
+ cpu_to_le32s(&tx_cmd_b);
+ memcpy(skb->data, &tx_cmd_b, 4);
+
+ skb_push(skb, 4);
+ tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
+ TX_CMD_A_LAST_SEG_;
+ cpu_to_le32s(&tx_cmd_a);
+ memcpy(skb->data, &tx_cmd_a, 4);
+
+ return skb;
+}
+
+static const struct driver_info smsc95xx_info = {
+ .description = "smsc95xx USB 2.0 Ethernet",
+ .bind = smsc95xx_bind,
+ .unbind = smsc95xx_unbind,
+ .link_reset = smsc95xx_link_reset,
+ .reset = smsc95xx_reset,
+ .rx_fixup = smsc95xx_rx_fixup,
+ .tx_fixup = smsc95xx_tx_fixup,
+ .status = smsc95xx_status,
+ .flags = FLAG_ETHER,
+};
+
+static const struct usb_device_id products[] = {
+ {
+ /* SMSC9500 USB Ethernet Device */
+ USB_DEVICE(0x0424, 0x9500),
+ .driver_info = (unsigned long) &smsc95xx_info,
+ },
+ { }, /* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver smsc95xx_driver = {
+ .name = "smsc95xx",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disconnect = usbnet_disconnect,
+};
+
+static int __init smsc95xx_init(void)
+{
+ return usb_register(&smsc95xx_driver);
+}
+module_init(smsc95xx_init);
+
+static void __exit smsc95xx_exit(void)
+{
+ usb_deregister(&smsc95xx_driver);
+}
+module_exit(smsc95xx_exit);
+
+MODULE_AUTHOR("Nancy Lin");
+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
+MODULE_DESCRIPTION("SMSC95XX USB 2.0 Ethernet Devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h
new file mode 100644
index 00000000000..66b5c84f302
--- /dev/null
+++ b/drivers/net/usb/smsc95xx.h
@@ -0,0 +1,253 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007-2008 SMSC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *****************************************************************************/
+
+#ifndef _SMSC95XX_H
+#define _SMSC95XX_H
+
+/* Tx command words */
+#define TX_CMD_A_DATA_OFFSET_ (0x001F0000)
+#define TX_CMD_A_FIRST_SEG_ (0x00002000)
+#define TX_CMD_A_LAST_SEG_ (0x00001000)
+#define TX_CMD_A_BUF_SIZE_ (0x000007FF)
+
+#define TX_CMD_B_CSUM_ENABLE (0x00004000)
+#define TX_CMD_B_ADD_CRC_DISABLE_ (0x00002000)
+#define TX_CMD_B_DISABLE_PADDING_ (0x00001000)
+#define TX_CMD_B_PKT_BYTE_LENGTH_ (0x000007FF)
+
+/* Rx status word */
+#define RX_STS_FF_ (0x40000000) /* Filter Fail */
+#define RX_STS_FL_ (0x3FFF0000) /* Frame Length */
+#define RX_STS_ES_ (0x00008000) /* Error Summary */
+#define RX_STS_BF_ (0x00002000) /* Broadcast Frame */
+#define RX_STS_LE_ (0x00001000) /* Length Error */
+#define RX_STS_RF_ (0x00000800) /* Runt Frame */
+#define RX_STS_MF_ (0x00000400) /* Multicast Frame */
+#define RX_STS_TL_ (0x00000080) /* Frame too long */
+#define RX_STS_CS_ (0x00000040) /* Collision Seen */
+#define RX_STS_FT_ (0x00000020) /* Frame Type */
+#define RX_STS_RW_ (0x00000010) /* Receive Watchdog */
+#define RX_STS_ME_ (0x00000008) /* Mii Error */
+#define RX_STS_DB_ (0x00000004) /* Dribbling */
+#define RX_STS_CRC_ (0x00000002) /* CRC Error */
+
+/* SCSRs */
+#define ID_REV (0x00)
+#define ID_REV_CHIP_ID_MASK_ (0xFFFF0000)
+#define ID_REV_CHIP_REV_MASK_ (0x0000FFFF)
+#define ID_REV_CHIP_ID_9500_ (0x9500)
+
+#define INT_STS (0x08)
+#define INT_STS_TX_STOP_ (0x00020000)
+#define INT_STS_RX_STOP_ (0x00010000)
+#define INT_STS_PHY_INT_ (0x00008000)
+#define INT_STS_TXE_ (0x00004000)
+#define INT_STS_TDFU_ (0x00002000)
+#define INT_STS_TDFO_ (0x00001000)
+#define INT_STS_RXDF_ (0x00000800)
+#define INT_STS_GPIOS_ (0x000007FF)
+
+#define RX_CFG (0x0C)
+#define RX_FIFO_FLUSH_ (0x00000001)
+
+#define TX_CFG (0x10)
+#define TX_CFG_ON_ (0x00000004)
+#define TX_CFG_STOP_ (0x00000002)
+#define TX_CFG_FIFO_FLUSH_ (0x00000001)
+
+#define HW_CFG (0x14)
+#define HW_CFG_BIR_ (0x00001000)
+#define HW_CFG_LEDB_ (0x00000800)
+#define HW_CFG_RXDOFF_ (0x00000600)
+#define HW_CFG_DRP_ (0x00000040)
+#define HW_CFG_MEF_ (0x00000020)
+#define HW_CFG_LRST_ (0x00000008)
+#define HW_CFG_PSEL_ (0x00000004)
+#define HW_CFG_BCE_ (0x00000002)
+#define HW_CFG_SRST_ (0x00000001)
+
+#define PM_CTRL (0x20)
+#define PM_CTL_DEV_RDY_ (0x00000080)
+#define PM_CTL_SUS_MODE_ (0x00000060)
+#define PM_CTL_SUS_MODE_0 (0x00000000)
+#define PM_CTL_SUS_MODE_1 (0x00000020)
+#define PM_CTL_SUS_MODE_2 (0x00000060)
+#define PM_CTL_PHY_RST_ (0x00000010)
+#define PM_CTL_WOL_EN_ (0x00000008)
+#define PM_CTL_ED_EN_ (0x00000004)
+#define PM_CTL_WUPS_ (0x00000003)
+#define PM_CTL_WUPS_NO_ (0x00000000)
+#define PM_CTL_WUPS_ED_ (0x00000001)
+#define PM_CTL_WUPS_WOL_ (0x00000002)
+#define PM_CTL_WUPS_MULTI_ (0x00000003)
+
+#define LED_GPIO_CFG (0x24)
+
+#define GPIO_CFG (0x28)
+
+#define AFC_CFG (0x2C)
+
+/* Hi watermark = 15.5Kb (~10 mtu pkts) */
+/* low watermark = 3k (~2 mtu pkts) */
+/* backpressure duration = ~ 350us */
+/* Apply FC on any frame. */
+#define AFC_CFG_DEFAULT (0x00F830A1)
+
+#define E2P_CMD (0x30)
+#define E2P_CMD_BUSY_ (0x80000000)
+#define E2P_CMD_MASK_ (0x70000000)
+#define E2P_CMD_READ_ (0x00000000)
+#define E2P_CMD_EWDS_ (0x10000000)
+#define E2P_CMD_EWEN_ (0x20000000)
+#define E2P_CMD_WRITE_ (0x30000000)
+#define E2P_CMD_WRAL_ (0x40000000)
+#define E2P_CMD_ERASE_ (0x50000000)
+#define E2P_CMD_ERAL_ (0x60000000)
+#define E2P_CMD_RELOAD_ (0x70000000)
+#define E2P_CMD_TIMEOUT_ (0x00000400)
+#define E2P_CMD_LOADED_ (0x00000200)
+#define E2P_CMD_ADDR_ (0x000001FF)
+
+#define MAX_EEPROM_SIZE (512)
+
+#define E2P_DATA (0x34)
+#define E2P_DATA_MASK_ (0x000000FF)
+
+#define BURST_CAP (0x38)
+
+#define GPIO_WAKE (0x64)
+
+#define INT_EP_CTL (0x68)
+#define INT_EP_CTL_INTEP_ (0x80000000)
+#define INT_EP_CTL_MACRTO_ (0x00080000)
+#define INT_EP_CTL_TX_STOP_ (0x00020000)
+#define INT_EP_CTL_RX_STOP_ (0x00010000)
+#define INT_EP_CTL_PHY_INT_ (0x00008000)
+#define INT_EP_CTL_TXE_ (0x00004000)
+#define INT_EP_CTL_TDFU_ (0x00002000)
+#define INT_EP_CTL_TDFO_ (0x00001000)
+#define INT_EP_CTL_RXDF_ (0x00000800)
+#define INT_EP_CTL_GPIOS_ (0x000007FF)
+
+#define BULK_IN_DLY (0x6C)
+
+/* MAC CSRs */
+#define MAC_CR (0x100)
+#define MAC_CR_RXALL_ (0x80000000)
+#define MAC_CR_RCVOWN_ (0x00800000)
+#define MAC_CR_LOOPBK_ (0x00200000)
+#define MAC_CR_FDPX_ (0x00100000)
+#define MAC_CR_MCPAS_ (0x00080000)
+#define MAC_CR_PRMS_ (0x00040000)
+#define MAC_CR_INVFILT_ (0x00020000)
+#define MAC_CR_PASSBAD_ (0x00010000)
+#define MAC_CR_HFILT_ (0x00008000)
+#define MAC_CR_HPFILT_ (0x00002000)
+#define MAC_CR_LCOLL_ (0x00001000)
+#define MAC_CR_BCAST_ (0x00000800)
+#define MAC_CR_DISRTY_ (0x00000400)
+#define MAC_CR_PADSTR_ (0x00000100)
+#define MAC_CR_BOLMT_MASK (0x000000C0)
+#define MAC_CR_DFCHK_ (0x00000020)
+#define MAC_CR_TXEN_ (0x00000008)
+#define MAC_CR_RXEN_ (0x00000004)
+
+#define ADDRH (0x104)
+
+#define ADDRL (0x108)
+
+#define HASHH (0x10C)
+
+#define HASHL (0x110)
+
+#define MII_ADDR (0x114)
+#define MII_WRITE_ (0x02)
+#define MII_BUSY_ (0x01)
+#define MII_READ_ (0x00) /* ~of MII Write bit */
+
+#define MII_DATA (0x118)
+
+#define FLOW (0x11C)
+#define FLOW_FCPT_ (0xFFFF0000)
+#define FLOW_FCPASS_ (0x00000004)
+#define FLOW_FCEN_ (0x00000002)
+#define FLOW_FCBSY_ (0x00000001)
+
+#define VLAN1 (0x120)
+
+#define VLAN2 (0x124)
+
+#define WUFF (0x128)
+
+#define WUCSR (0x12C)
+
+#define COE_CR (0x130)
+#define Tx_COE_EN_ (0x00010000)
+#define Rx_COE_MODE_ (0x00000002)
+#define Rx_COE_EN_ (0x00000001)
+
+/* Vendor-specific PHY Definitions */
+
+/* Mode Control/Status Register */
+#define PHY_MODE_CTRL_STS (17)
+#define MODE_CTRL_STS_EDPWRDOWN_ ((u16)0x2000)
+#define MODE_CTRL_STS_ENERGYON_ ((u16)0x0002)
+
+#define SPECIAL_CTRL_STS (27)
+#define SPECIAL_CTRL_STS_OVRRD_AMDIX_ ((u16)0x8000)
+#define SPECIAL_CTRL_STS_AMDIX_ENABLE_ ((u16)0x4000)
+#define SPECIAL_CTRL_STS_AMDIX_STATE_ ((u16)0x2000)
+
+#define PHY_INT_SRC (29)
+#define PHY_INT_SRC_ENERGY_ON_ ((u16)0x0080)
+#define PHY_INT_SRC_ANEG_COMP_ ((u16)0x0040)
+#define PHY_INT_SRC_REMOTE_FAULT_ ((u16)0x0020)
+#define PHY_INT_SRC_LINK_DOWN_ ((u16)0x0010)
+
+#define PHY_INT_MASK (30)
+#define PHY_INT_MASK_ENERGY_ON_ ((u16)0x0080)
+#define PHY_INT_MASK_ANEG_COMP_ ((u16)0x0040)
+#define PHY_INT_MASK_REMOTE_FAULT_ ((u16)0x0020)
+#define PHY_INT_MASK_LINK_DOWN_ ((u16)0x0010)
+#define PHY_INT_MASK_DEFAULT_ (PHY_INT_MASK_ANEG_COMP_ | \
+ PHY_INT_MASK_LINK_DOWN_)
+
+#define PHY_SPECIAL (31)
+#define PHY_SPECIAL_SPD_ ((u16)0x001C)
+#define PHY_SPECIAL_SPD_10HALF_ ((u16)0x0004)
+#define PHY_SPECIAL_SPD_10FULL_ ((u16)0x0014)
+#define PHY_SPECIAL_SPD_100HALF_ ((u16)0x0008)
+#define PHY_SPECIAL_SPD_100FULL_ ((u16)0x0018)
+
+/* USB Vendor Requests */
+#define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0
+#define USB_VENDOR_REQUEST_READ_REGISTER 0xA1
+#define USB_VENDOR_REQUEST_GET_STATS 0xA2
+
+/* Interrupt Endpoint status word bitfields */
+#define INT_ENP_TX_STOP_ ((u32)BIT(17))
+#define INT_ENP_RX_STOP_ ((u32)BIT(16))
+#define INT_ENP_PHY_INT_ ((u32)BIT(15))
+#define INT_ENP_TXE_ ((u32)BIT(14))
+#define INT_ENP_TDFU_ ((u32)BIT(13))
+#define INT_ENP_TDFO_ ((u32)BIT(12))
+#define INT_ENP_RXDF_ ((u32)BIT(11))
+
+#endif /* _SMSC95XX_H */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 8463efb9e0b..02d25c74399 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -512,14 +512,13 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
int count = 0;
spin_lock_irqsave (&q->lock, flags);
- for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) {
+ skb_queue_walk_safe(q, skb, skbnext) {
struct skb_data *entry;
struct urb *urb;
int retval;
entry = (struct skb_data *) skb->cb;
urb = entry->urb;
- skbnext = skb->next;
// during some PM-driven resume scenarios,
// these (async) unlinks complete immediately
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 96dff04334b..5b7870080c5 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -914,7 +914,7 @@ static void alloc_rbufs(struct net_device *dev)
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz);
+ struct sk_buff *skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
rp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
@@ -1473,8 +1473,8 @@ static int rhine_rx(struct net_device *dev, int limit)
/* Check if the packet is long enough to accept without
copying to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
- skb_reserve(skb, 2); /* 16 byte align the IP header */
+ (skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN)) != NULL) {
+ skb_reserve(skb, NET_IP_ALIGN); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(rp->pdev,
rp->rx_skbuff_dma[entry],
rp->rx_buf_sz,
@@ -1518,7 +1518,7 @@ static int rhine_rx(struct net_device *dev, int limit)
struct sk_buff *skb;
entry = rp->dirty_rx % RX_RING_SIZE;
if (rp->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(rp->rx_buf_sz);
+ skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
rp->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 007c1297006..2dced383bcf 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -12,7 +12,7 @@
* Scatter gather
* More testing
*
- * The changes are (c) Copyright 2004, Red Hat Inc. <alan@redhat.com>
+ * The changes are (c) Copyright 2004, Red Hat Inc. <alan@lxorguk.ukuu.org.uk>
* Additional fixes and clean up: Francois Romieu
*
* This source has not been verified for use in safety critical systems.
@@ -1272,7 +1272,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
continue;
pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
PCI_DMA_FROMDEVICE);
- rd_info->skb_dma = (dma_addr_t) NULL;
+ rd_info->skb_dma = 0;
dev_kfree_skb(rd_info->skb);
rd_info->skb = NULL;
@@ -1333,7 +1333,7 @@ static void velocity_free_td_ring_entry(struct velocity_info *vptr,
if (td_info->skb_dma[i]) {
pci_unmap_single(vptr->pdev, td_info->skb_dma[i],
td_info->skb->len, PCI_DMA_TODEVICE);
- td_info->skb_dma[i] = (dma_addr_t) NULL;
+ td_info->skb_dma[i] = 0;
}
}
dev_kfree_skb(td_info->skb);
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 1b95b04c925..29a33090d3d 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -1381,7 +1381,7 @@ enum velocity_msg_level {
#define ASSERT(x) { \
if (!(x)) { \
printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\
- __FUNCTION__, __LINE__);\
+ __func__, __LINE__);\
BUG(); \
}\
}
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 2ae2ec40015..21efd99b929 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE
config PC300
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
- depends on HDLC && PCI
+ depends on HDLC && PCI && BROKEN
---help---
Driver for the Cyclades-PC300 synchronous communication boards.
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index f14051556c8..7f97f8d08c3 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -388,8 +388,8 @@ static int __init cosa_init(void)
goto out_chrdev;
}
for (i = 0; i < nr_cards; i++)
- device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
- NULL, "cosa%d", i);
+ device_create(cosa_class, NULL, MKDEV(cosa_major, i), NULL,
+ "cosa%d", i);
err = 0;
goto out;
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index d14e6678dee..a5ddc6c8963 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -407,7 +407,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
if (cfm->version != CFM_VERSION) {
printk(KERN_ERR "%s:%s: firmware format %u rejected! "
"Expecting %u.\n",
- modname, __FUNCTION__, cfm->version, CFM_VERSION);
+ modname, __func__, cfm->version, CFM_VERSION);
return -EINVAL;
}
@@ -420,7 +420,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
*/
if (cksum != cfm->checksum) {
printk(KERN_ERR "%s:%s: firmware corrupted!\n",
- modname, __FUNCTION__);
+ modname, __func__);
printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
len - (int)sizeof(struct cycx_firmware) - 1,
cfm->info.codesize);
@@ -432,7 +432,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
/* If everything is ok, set reset, data and code pointers */
img_hdr = (struct cycx_fw_header *)&cfm->image;
#ifdef FIRMWARE_DEBUG
- printk(KERN_INFO "%s:%s: image sizes\n", __FUNCTION__, modname);
+ printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname);
printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
printk(KERN_INFO " data=%lu\n", img_hdr->data_size);
printk(KERN_INFO " code=%lu\n", img_hdr->code_size);
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index d3b28b01b9f..5a7303dc096 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -874,7 +874,7 @@ static void cycx_x25_irq_connect(struct cycx_device *card,
nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
- __FUNCTION__, lcn, loc, rem);
+ __func__, lcn, loc, rem);
dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
if (!dev) {
@@ -902,7 +902,7 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
- card->devname, __FUNCTION__, lcn, key);
+ card->devname, __func__, lcn, key);
dev = cycx_x25_get_dev_by_lcn(wandev, -key);
if (!dev) {
@@ -929,7 +929,7 @@ static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
- card->devname, __FUNCTION__, lcn);
+ card->devname, __func__, lcn);
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (!dev) {
/* Invalid channel, discard packet */
@@ -950,7 +950,7 @@ static void cycx_x25_irq_disconnect(struct cycx_device *card,
u8 lcn;
cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
- dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn);
+ dprintk(1, KERN_INFO "%s:lcn=%d\n", __func__, lcn);
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (dev) {
@@ -1381,7 +1381,7 @@ static void cycx_x25_chan_timer(unsigned long d)
cycx_x25_chan_disconnect(dev);
else
printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
- chan->card->devname, __FUNCTION__, dev->name);
+ chan->card->devname, __func__, dev->name);
}
/* Set logical channel state. */
@@ -1485,7 +1485,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "%s: out of memory\n", __FUNCTION__);
+ printk(KERN_ERR "%s: out of memory\n", __func__);
return;
}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index f5d55ad0226..5f1ccb2b08b 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -647,7 +647,7 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
skb = dpriv->rx_skbuff[dpriv->rx_current++%RX_RING_SIZE];
if (!skb) {
- printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __FUNCTION__);
+ printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __func__);
goto refill;
}
pkt_len = TO_SIZE(le32_to_cpu(rx_fd->state2));
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 8b7e5d2e2ac..cbcbf6f0414 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -163,15 +163,17 @@ static void x25_close(struct net_device *dev)
static int x25_rx(struct sk_buff *skb)
{
+ struct net_device *dev = skb->dev;
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
- skb->dev->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return NET_RX_DROP;
}
- if (lapb_data_received(skb->dev, skb) == LAPB_OK)
+ if (lapb_data_received(dev, skb) == LAPB_OK)
return NET_RX_SUCCESS;
- skb->dev->stats.rx_errors++;
+ dev->stats.rx_errors++;
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index f80640f5a74..d7bb63e616b 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -122,7 +122,6 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
* Most functions mess with the structure
* Disable interrupts while we do the polling
*/
- spin_lock_irqsave(&sc->lmc_lock, flags);
switch (cmd) {
/*
@@ -152,6 +151,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
+ spin_lock_irqsave(&sc->lmc_lock, flags);
sc->lmc_media->set_status (sc, &ctl);
if(ctl.crc_length != sc->ictl.crc_length) {
@@ -161,6 +161,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
else
sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE;
}
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
ret = 0;
break;
@@ -187,15 +188,18 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break; /* no change */
}
+ spin_lock_irqsave(&sc->lmc_lock, flags);
lmc_proto_close(sc);
sc->if_type = new_type;
lmc_proto_attach(sc);
ret = lmc_proto_open(sc);
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
break;
}
case LMCIOCGETXINFO: /*fold01*/
+ spin_lock_irqsave(&sc->lmc_lock, flags);
sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;
sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;
@@ -208,6 +212,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ;
sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);
sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
sc->lmc_xinfo.Magic1 = 0xDEADBEEF;
@@ -220,6 +225,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
case LMCIOCGETLMCSTATS:
+ spin_lock_irqsave(&sc->lmc_lock, flags);
if (sc->lmc_cardtype == LMC_CARDTYPE_T1) {
lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_LSB);
sc->extra_stats.framingBitErrorCount +=
@@ -243,6 +249,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
sc->extra_stats.severelyErroredFrameCount +=
regVal & T1FRAMER_SEF_MASK;
}
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
if (copy_to_user(ifr->ifr_data, &sc->lmc_device->stats,
sizeof(sc->lmc_device->stats)) ||
copy_to_user(ifr->ifr_data + sizeof(sc->lmc_device->stats),
@@ -258,12 +265,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
+ spin_lock_irqsave(&sc->lmc_lock, flags);
memset(&sc->lmc_device->stats, 0, sizeof(sc->lmc_device->stats));
memset(&sc->extra_stats, 0, sizeof(sc->extra_stats));
sc->extra_stats.check = STATCHECK;
sc->extra_stats.version_size = (DRIVER_VERSION << 16) +
sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats);
sc->extra_stats.lmc_cardtype = sc->lmc_cardtype;
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
ret = 0;
break;
@@ -282,8 +291,10 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
ret = -EFAULT;
break;
}
+ spin_lock_irqsave(&sc->lmc_lock, flags);
sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);
sc->ictl.circuit_type = ctl.circuit_type;
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
ret = 0;
break;
@@ -294,12 +305,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
+ spin_lock_irqsave(&sc->lmc_lock, flags);
/* Reset driver and bring back to current state */
printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
lmc_running_reset (dev);
printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
ret = 0;
break;
@@ -338,14 +351,15 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
*/
netif_stop_queue(dev);
- if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) {
+ if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) {
ret = -EFAULT;
break;
- }
+ }
switch(xc.command){
case lmc_xilinx_reset: /*fold02*/
{
u16 mii;
+ spin_lock_irqsave(&sc->lmc_lock, flags);
mii = lmc_mii_readreg (sc, 0, 16);
/*
@@ -404,6 +418,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
lmc_led_off(sc, LMC_DS3_LED2);
}
}
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
@@ -416,6 +431,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
{
u16 mii;
int timeout = 500000;
+ spin_lock_irqsave(&sc->lmc_lock, flags);
mii = lmc_mii_readreg (sc, 0, 16);
/*
@@ -451,13 +467,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
*/
while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
(timeout-- > 0))
- ;
+ cpu_relax();
/*
* stop driving Xilinx-related signals
*/
lmc_gpio_mkinput(sc, 0xff);
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
ret = 0x0;
@@ -493,6 +510,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data);
+ spin_lock_irqsave(&sc->lmc_lock, flags);
lmc_gpio_mkinput(sc, 0xff);
/*
@@ -545,7 +563,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
*/
while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
(timeout-- > 0))
- ;
+ cpu_relax();
printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout);
@@ -588,6 +606,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+ spin_unlock_irqrestore(&sc->lmc_lock, flags);
kfree(data);
@@ -611,8 +630,6 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
break;
}
- spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/
-
lmc_trace(dev, "lmc_ioctl out");
return ret;
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 4518d0aa248..4917a94943b 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -548,7 +548,7 @@ static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
{
st_cpc_tty_area *cpc_tty;
- CPC_TTY_DBG("%s: set:%x clear:%x\n", __FUNCTION__, set, clear);
+ CPC_TTY_DBG("%s: set:%x clear:%x\n", __func__, set, clear);
if (!tty || !tty->driver_data ) {
CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 6596cd0742b..f972fef87c9 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -856,7 +856,7 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev )
len = SBNI_MIN_LEN;
nl->tx_buf_p = skb;
- nl->tx_frameno = (len + nl->maxframe - 1) / nl->maxframe;
+ nl->tx_frameno = DIV_ROUND_UP(len, nl->maxframe);
nl->framelen = len < nl->maxframe ? len : nl->maxframe;
outb( inb( dev->base_addr + CSR0 ) | TR_REQ, dev->base_addr + CSR0 );
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 243bd8d918f..ccd9cd35ecb 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -18,7 +18,8 @@
* DMA now uses get_free_page as kmalloc buffers may span a 64K
* boundary.
*
- * Modified for SMP safety and SMP locking by Alan Cox <alan@redhat.com>
+ * Modified for SMP safety and SMP locking by Alan Cox
+ * <alan@lxorguk.ukuu.org.uk>
*
* Performance
*
diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h
index 4f372396c51..85b3e785d48 100644
--- a/drivers/net/wan/z85230.h
+++ b/drivers/net/wan/z85230.h
@@ -2,7 +2,7 @@
* Description of Z8530 Z85C30 and Z85230 communications chips
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ * Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
*/
#ifndef _Z8530_H
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 9931b5ab59c..45bdf0b339b 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -300,6 +300,19 @@ config LIBERTAS_DEBUG
---help---
Debugging support.
+config LIBERTAS_THINFIRM
+ tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
+ depends on WLAN_80211 && MAC80211
+ select FW_LOADER
+ ---help---
+ A library for Marvell Libertas 8xxx devices using thinfirm.
+
+config LIBERTAS_THINFIRM_USB
+ tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
+ depends on LIBERTAS_THINFIRM && USB
+ ---help---
+ A driver for Marvell Libertas 8388 USB devices using thinfirm.
+
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
@@ -322,6 +335,9 @@ config HERMES
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
select WIRELESS_EXT
+ select FW_LOADER
+ select CRYPTO
+ select CRYPTO_MICHAEL_MIC
---help---
A driver for 802.11b wireless cards based on the "Hermes" or
Intersil HFA384x (Prism 2) MAC controller. This includes the vast
@@ -411,7 +427,6 @@ config PCMCIA_HERMES
config PCMCIA_SPECTRUM
tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
depends on PCMCIA && HERMES
- select FW_LOADER
---help---
This is a driver for 802.11b cards using RAM-loadable Symbol
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 59aa89ec6e8..59d2d805f60 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
-obj-$(CONFIG_HERMES) += orinoco.o hermes.o
+obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
@@ -48,6 +48,8 @@ obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS) += libertas/
+obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
+
rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 3333d4596b8..b2c050b6889 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -765,11 +765,11 @@ static void adm8211_update_mode(struct ieee80211_hw *dev)
priv->soft_rx_crc = 0;
switch (priv->mode) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA);
priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR;
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
priv->nar &= ~ADM8211_NAR_PR;
priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR;
@@ -777,7 +777,7 @@ static void adm8211_update_mode(struct ieee80211_hw *dev)
if (priv->pdev->revision >= ADM8211_REV_BA)
priv->soft_rx_crc = 1;
break;
- case IEEE80211_IF_TYPE_MNTR:
+ case NL80211_IFTYPE_MONITOR:
priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST);
priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR;
break;
@@ -1410,11 +1410,11 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@@ -1437,7 +1437,7 @@ static void adm8211_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
}
static int adm8211_init_rings(struct ieee80211_hw *dev)
@@ -1556,7 +1556,7 @@ static int adm8211_start(struct ieee80211_hw *dev)
ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE |
ADM8211_IER_RCIE | ADM8211_IER_TCIE |
ADM8211_IER_TDUIE | ADM8211_IER_GPTIE);
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
adm8211_update_mode(dev);
ADM8211_CSR_WRITE(RDR, 0);
@@ -1571,7 +1571,7 @@ static void adm8211_stop(struct ieee80211_hw *dev)
{
struct adm8211_priv *priv = dev->priv;
- priv->mode = IEEE80211_IF_TYPE_INVALID;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
priv->nar = 0;
ADM8211_CSR_WRITE(NAR, 0);
ADM8211_CSR_WRITE(IER, 0);
@@ -1884,6 +1884,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
dev->channel_change_time = 1000;
dev->max_signal = 100; /* FIXME: find better value */
@@ -1895,7 +1896,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
priv->tx_power = 0x40;
priv->lpf_cutoff = 0xFF;
priv->lnags_threshold = 0xFF;
- priv->mode = IEEE80211_IF_TYPE_INVALID;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
/* Power-on issue. EEPROM won't read correctly without */
if (pdev->revision >= ADM8211_REV_BA) {
@@ -1985,7 +1986,7 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct adm8211_priv *priv = dev->priv;
- if (priv->mode != IEEE80211_IF_TYPE_INVALID) {
+ if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
ieee80211_stop_queues(dev);
adm8211_stop(dev);
}
@@ -2003,7 +2004,7 @@ static int adm8211_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- if (priv->mode != IEEE80211_IF_TYPE_INVALID) {
+ if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
adm8211_start(dev);
ieee80211_wake_queues(dev);
}
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index b5cd850a4a5..370133e492d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1915,7 +1915,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
struct airo_info *ai = dev->priv;
if (!skb) {
- airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
+ airo_print_err(dev->name, "%s: skb == NULL!",__func__);
return 0;
}
npacks = skb_queue_len (&ai->txq);
@@ -1964,7 +1964,7 @@ static int mpi_send_packet (struct net_device *dev)
if ((skb = skb_dequeue(&ai->txq)) == NULL) {
airo_print_err(dev->name,
"%s: Dequeue'd zero in send_packet()",
- __FUNCTION__);
+ __func__);
return 0;
}
@@ -2115,7 +2115,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
u32 *fids = priv->fids;
if ( skb == NULL ) {
- airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
+ airo_print_err(dev->name, "%s: skb == NULL!", __func__);
return 0;
}
@@ -2186,7 +2186,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
}
if ( skb == NULL ) {
- airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
+ airo_print_err(dev->name, "%s: skb == NULL!", __func__);
return 0;
}
@@ -4127,7 +4127,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
airo_print_err(ai->dev->name,
"%s: MAC should be disabled (rid=%04x)",
- __FUNCTION__, rid);
+ __func__, rid);
memset(&cmd, 0, sizeof(cmd));
memset(&rsp, 0, sizeof(rsp));
@@ -4142,7 +4142,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
&ai->config_desc.rid_desc, sizeof(Rid));
if (len < 4 || len > 2047) {
- airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
+ airo_print_err(ai->dev->name, "%s: len=%d", __func__, len);
rc = -1;
} else {
memcpy((char *)ai->config_desc.virtual_host_addr,
@@ -4151,9 +4151,9 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
rc = issuecommand(ai, &cmd, &rsp);
if ((rc & 0xff00) != 0) {
airo_print_err(ai->dev->name, "%s: Write rid Error %d",
- __FUNCTION__, rc);
+ __func__, rc);
airo_print_err(ai->dev->name, "%s: Cmd=%04x",
- __FUNCTION__, cmd.cmd);
+ __func__, cmd.cmd);
}
if ((rsp.status & 0x7f00))
@@ -7107,7 +7107,7 @@ static int airo_get_aplist(struct net_device *dev,
*/
static int airo_set_scan(struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ struct iw_point *dwrq,
char *extra)
{
struct airo_info *ai = dev->priv;
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index f12355398fe..27696c20f4c 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -147,7 +147,7 @@ static int airo_probe(struct pcmcia_device *p_dev)
DEBUG(0, "airo_attach()\n");
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;
@@ -206,126 +206,123 @@ static void airo_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int airo_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ win_req_t *req = priv_data;
+
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+ /* Do we need to allocate an interrupt? */
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+ return -ENODEV;
+
+ /*
+ Now set up a common memory window, if needed. There is room
+ in the struct pcmcia_device structure for one memory window handle,
+ but if the base addresses need to be saved, or if multiple
+ windows are needed, the info should go in the private data
+ structure for this device.
+
+ Note that the memory window base is a physical address, and
+ needs to be mapped to virtual space with ioremap() before it
+ is used.
+ */
+ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+ cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+ memreq_t map;
+ req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+ req->Base = mem->win[0].host_addr;
+ req->Size = mem->win[0].len;
+ req->AccessSpeed = 0;
+ if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0)
+ return -ENODEV;
+ map.Page = 0;
+ map.CardOffset = mem->win[0].card_addr;
+ if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+ return -ENODEV;
+ }
+ /* If we got this far, we're cool! */
+ return 0;
+}
+
+
static int airo_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
+ win_req_t *req;
int last_fn, last_ret;
- u_char buf[64];
- win_req_t req;
- memreq_t map;
dev = link->priv;
DEBUG(0, "airo_config(0x%p)\n", link);
+ req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ /*
+ * In this loop, we scan the CIS for configuration table
+ * entries, each of which describes a valid card
+ * configuration, including voltage, IO window, memory window,
+ * and interrupt settings.
+ *
+ * We make no assumptions about the card to be configured: we
+ * use just the information available in the CIS. In an ideal
+ * world, this would work for any PCMCIA card, but it requires
+ * a complete and accurate CIS. In practice, a driver usually
+ * "knows" most of these things without consulting the CIS,
+ * and most client drivers will only use the CIS to fill in
+ * implementation-defined details.
+ */
+ last_ret = pcmcia_loop_config(link, airo_cs_config_check, req);
+ if (last_ret)
+ goto failed;
+
/*
- In this loop, we scan the CIS for configuration table entries,
- each of which describes a valid card configuration, including
- voltage, IO window, memory window, and interrupt settings.
-
- We make no assumptions about the card to be configured: we use
- just the information available in the CIS. In an ideal world,
- this would work for any PCMCIA card, but it requires a complete
- and accurate CIS. In practice, a driver usually "knows" most of
- these things without consulting the CIS, and most client drivers
- will only use the CIS to fill in implementation-defined details.
+ Allocate an interrupt line. Note that this does not assign a
+ handler to the interrupt, unless the 'Handler' member of the
+ irq structure is initialized.
*/
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t dflt = { 0 };
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- if (cfg->index == 0) goto next_entry;
- link->conf.ConfigIndex = cfg->index;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
-
- /*
- Now set up a common memory window, if needed. There is room
- in the struct pcmcia_device structure for one memory window handle,
- but if the base addresses need to be saved, or if multiple
- windows are needed, the info should go in the private data
- structure for this device.
-
- Note that the memory window base is a physical address, and
- needs to be mapped to virtual space with ioremap() before it
- is used.
- */
- if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
- cistpl_mem_t *mem =
- (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- req.Base = mem->win[0].host_addr;
- req.Size = mem->win[0].len;
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link, &req, &link->win) != 0)
- goto next_entry;
- map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
- goto next_entry;
- }
- /* If we got this far, we're cool! */
- break;
-
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
-
- /*
- Allocate an interrupt line. Note that this does not assign a
- handler to the interrupt, unless the 'Handler' member of the
- irq structure is initialized.
- */
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -362,14 +359,17 @@ static int airo_config(struct pcmcia_device *link)
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
if (link->win)
- printk(", mem 0x%06lx-0x%06lx", req.Base,
- req.Base+req.Size-1);
+ printk(", mem 0x%06lx-0x%06lx", req->Base,
+ req->Base+req->Size-1);
printk("\n");
+ kfree(req);
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
+ failed:
airo_release(link);
+ kfree(req);
return -ENODEV;
} /* airo_config */
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 6f7eb9f5922..ce03a2e865f 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -180,7 +180,8 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
}
/* Allocate space for private device-specific data */
- dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
+ dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
+ airport_hard_reset, NULL);
if (! dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
return -ENODEV;
diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile
index 564ecd0c5d4..719cfaef708 100644
--- a/drivers/net/wireless/ath5k/Makefile
+++ b/drivers/net/wireless/ath5k/Makefile
@@ -1,6 +1,14 @@
-ath5k-y += base.o
-ath5k-y += hw.o
+ath5k-y += caps.o
ath5k-y += initvals.o
+ath5k-y += eeprom.o
+ath5k-y += gpio.o
+ath5k-y += desc.o
+ath5k-y += dma.o
+ath5k-y += qcu.o
+ath5k-y += pcu.o
ath5k-y += phy.o
+ath5k-y += reset.o
+ath5k-y += attach.o
+ath5k-y += base.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
obj-$(CONFIG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 9102eea3c8b..53ea439aff4 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -18,18 +18,23 @@
#ifndef _ATH5K_H
#define _ATH5K_H
-/* Set this to 1 to disable regulatory domain restrictions for channel tests.
- * WARNING: This is for debuging only and has side effects (eg. scan takes too
- * long and results timeouts). It's also illegal to tune to some of the
- * supported frequencies in some countries, so use this at your own risk,
- * you've been warned. */
+/* TODO: Clean up channel debuging -doesn't work anyway- and start
+ * working on reg. control code using all available eeprom information
+ * -rev. engineering needed- */
#define CHAN_DEBUG 0
#include <linux/io.h>
#include <linux/types.h>
#include <net/mac80211.h>
-#include "hw.h"
+/* RX/TX descriptor hw structs
+ * TODO: Driver part should only see sw structs */
+#include "desc.h"
+
+/* EEPROM structs/offsets
+ * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
+ * and clean up common bits, then introduce set/get functions in eeprom.c */
+#include "eeprom.h"
/* PCI IDs */
#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
@@ -87,7 +92,92 @@
ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
/*
+ * AR5K REGISTER ACCESS
+ */
+
+/* Some macros to read/write fields */
+
+/* First shift, then mask */
+#define AR5K_REG_SM(_val, _flags) \
+ (((_val) << _flags##_S) & (_flags))
+
+/* First mask, then shift */
+#define AR5K_REG_MS(_val, _flags) \
+ (((_val) & (_flags)) >> _flags##_S)
+
+/* Some registers can hold multiple values of interest. For this
+ * reason when we want to write to these registers we must first
+ * retrieve the values which we do not want to clear (lets call this
+ * old_data) and then set the register with this and our new_value:
+ * ( old_data | new_value) */
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
+ (((_val) << _flags##_S) & (_flags)), _reg)
+
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
+ (_mask)) | (_flags), _reg)
+
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
+
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
+
+/* Access to PHY registers */
+#define AR5K_PHY_READ(ah, _reg) \
+ ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_PHY_WRITE(ah, _reg, _val) \
+ ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
+
+/* Access QCU registers per queue */
+#define AR5K_REG_READ_Q(ah, _reg, _queue) \
+ (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
+
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
+ ath5k_hw_reg_write(ah, (1 << _queue), _reg)
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
+ _reg |= 1 << _queue; \
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
+ _reg &= ~(1 << _queue); \
+} while (0)
+
+/* Used while writing initvals */
+#define AR5K_REG_WAIT(_i) do { \
+ if (_i % 64) \
+ udelay(1); \
+} while (0)
+
+/* Register dumps are done per operation mode */
+#define AR5K_INI_RFGAIN_5GHZ 0
+#define AR5K_INI_RFGAIN_2GHZ 1
+
+/* TODO: Clean this up */
+#define AR5K_INI_VAL_11A 0
+#define AR5K_INI_VAL_11A_TURBO 1
+#define AR5K_INI_VAL_11B 2
+#define AR5K_INI_VAL_11G 3
+#define AR5K_INI_VAL_11G_TURBO 4
+#define AR5K_INI_VAL_XR 0
+#define AR5K_INI_VAL_MAX 5
+
+#define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+#define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+
+/* Used for BSSID etc manipulation */
+#define AR5K_LOW_ID(_a)( \
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
+)
+
+#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
+
+/*
* Some tuneable values (these should be changeable by the user)
+ * TODO: Make use of them and add more options OR use debug/configfs
*/
#define AR5K_TUNE_DMA_BEACON_RESP 2
#define AR5K_TUNE_SW_BEACON_RESP 10
@@ -98,13 +188,13 @@
#define AR5K_TUNE_REGISTER_TIMEOUT 20000
/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
* be the max value. */
-#define AR5K_TUNE_RSSI_THRES 129
+#define AR5K_TUNE_RSSI_THRES 129
/* This must be set when setting the RSSI threshold otherwise it can
* prevent a reset. If AR5K_RSSI_THR is read after writing to it
* the BMISS_THRES will be seen as 0, seems harware doesn't keep
* track of it. Max value depends on harware. For AR5210 this is just 7.
* For AR5211+ this seems to be up to 255. */
-#define AR5K_TUNE_BMISS_THRES 7
+#define AR5K_TUNE_BMISS_THRES 7
#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
#define AR5K_TUNE_BEACON_INTERVAL 100
#define AR5K_TUNE_AIFS 2
@@ -123,6 +213,55 @@
#define AR5K_TUNE_ANT_DIVERSITY true
#define AR5K_TUNE_HWTXTRIES 4
+#define AR5K_INIT_CARR_SENSE_EN 1
+
+/*Swap RX/TX Descriptor for big endian archs*/
+#if defined(__BIG_ENDIAN)
+#define AR5K_INIT_CFG ( \
+ AR5K_CFG_SWTD | AR5K_CFG_SWRD \
+)
+#else
+#define AR5K_INIT_CFG 0x00000000
+#endif
+
+/* Initial values */
+#define AR5K_INIT_TX_LATENCY 502
+#define AR5K_INIT_USEC 39
+#define AR5K_INIT_USEC_TURBO 79
+#define AR5K_INIT_USEC_32 31
+#define AR5K_INIT_SLOT_TIME 396
+#define AR5K_INIT_SLOT_TIME_TURBO 480
+#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
+#define AR5K_INIT_PROG_IFS 920
+#define AR5K_INIT_PROG_IFS_TURBO 960
+#define AR5K_INIT_EIFS 3440
+#define AR5K_INIT_EIFS_TURBO 6880
+#define AR5K_INIT_SIFS 560
+#define AR5K_INIT_SIFS_TURBO 480
+#define AR5K_INIT_SH_RETRY 10
+#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+#define AR5K_INIT_SSH_RETRY 32
+#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
+#define AR5K_INIT_TX_RETRY 10
+
+#define AR5K_INIT_TRANSMIT_LATENCY ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC) \
+)
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC_TURBO) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
+ (AR5K_INIT_PROG_IFS) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
+ (AR5K_INIT_PROG_IFS_TURBO) \
+)
+
/* token to use for aifs, cwmin, cwmax in MadWiFi */
#define AR5K_TXQ_USEDEFAULT ((u32) -1)
@@ -142,7 +281,9 @@ enum ath5k_radio {
AR5K_RF5112 = 2,
AR5K_RF2413 = 3,
AR5K_RF5413 = 4,
- AR5K_RF2425 = 5,
+ AR5K_RF2316 = 5,
+ AR5K_RF2317 = 6,
+ AR5K_RF2425 = 7,
};
/*
@@ -150,7 +291,7 @@ enum ath5k_radio {
*/
enum ath5k_srev_type {
- AR5K_VERSION_VER,
+ AR5K_VERSION_MAC,
AR5K_VERSION_RAD,
};
@@ -162,23 +303,24 @@ struct ath5k_srev_name {
#define AR5K_SREV_UNKNOWN 0xffff
-#define AR5K_SREV_VER_AR5210 0x00
-#define AR5K_SREV_VER_AR5311 0x10
-#define AR5K_SREV_VER_AR5311A 0x20
-#define AR5K_SREV_VER_AR5311B 0x30
-#define AR5K_SREV_VER_AR5211 0x40
-#define AR5K_SREV_VER_AR5212 0x50
-#define AR5K_SREV_VER_AR5213 0x55
-#define AR5K_SREV_VER_AR5213A 0x59
-#define AR5K_SREV_VER_AR2413 0x78
-#define AR5K_SREV_VER_AR2414 0x79
-#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */
-#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */
-#define AR5K_SREV_VER_AR5413 0xa4
-#define AR5K_SREV_VER_AR5414 0xa5
-#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */
-#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */
-#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */
+#define AR5K_SREV_AR5210 0x00 /* Crete */
+#define AR5K_SREV_AR5311 0x10 /* Maui 1 */
+#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */
+#define AR5K_SREV_AR5311B 0x30 /* Spirit */
+#define AR5K_SREV_AR5211 0x40 /* Oahu */
+#define AR5K_SREV_AR5212 0x50 /* Venice */
+#define AR5K_SREV_AR5213 0x55 /* ??? */
+#define AR5K_SREV_AR5213A 0x59 /* Hainan */
+#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
+#define AR5K_SREV_AR2414 0x70 /* Griffin */
+#define AR5K_SREV_AR5424 0x90 /* Condor */
+#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
+#define AR5K_SREV_AR5414 0xa0 /* Eagle */
+#define AR5K_SREV_AR2415 0xb0 /* Cobra */
+#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
+#define AR5K_SREV_AR5418 0xca /* PCI-E */
+#define AR5K_SREV_AR2425 0xe0 /* Swan */
+#define AR5K_SREV_AR2417 0xf0 /* Nala */
#define AR5K_SREV_RAD_5110 0x00
#define AR5K_SREV_RAD_5111 0x10
@@ -190,13 +332,22 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_2112 0x40
#define AR5K_SREV_RAD_2112A 0x45
#define AR5K_SREV_RAD_2112B 0x46
-#define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */
-#define AR5K_SREV_RAD_SC1 0x60 /* Found on 5413/5414 */
-#define AR5K_SREV_RAD_SC2 0xa0 /* Found on 2424-5/5424 */
-#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
+#define AR5K_SREV_RAD_2413 0x50
+#define AR5K_SREV_RAD_5413 0x60
+#define AR5K_SREV_RAD_2316 0x70
+#define AR5K_SREV_RAD_2317 0x80
+#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
+#define AR5K_SREV_RAD_2425 0xa2
+#define AR5K_SREV_RAD_5133 0xc0
+
+#define AR5K_SREV_PHY_5211 0x30
+#define AR5K_SREV_PHY_5212 0x41
+#define AR5K_SREV_PHY_2112B 0x43
+#define AR5K_SREV_PHY_2413 0x45
+#define AR5K_SREV_PHY_5413 0x61
+#define AR5K_SREV_PHY_2425 0x70
/* IEEE defs */
-
#define IEEE80211_MAX_LEN 2500
/* TODO add support to mac80211 for vendor-specific rates and modes */
@@ -268,27 +419,21 @@ enum ath5k_driver_mode {
AR5K_MODE_MAX = 5
};
-/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
-#define AR5K_SET_SHORT_PREAMBLE 0x04
-
-#define HAS_SHPREAMBLE(_ix) \
- (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
-#define SHPREAMBLE_FLAG(_ix) \
- (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
-
/****************\
TX DEFINITIONS
\****************/
/*
- * TX Status
+ * TX Status descriptor
*/
struct ath5k_tx_status {
u16 ts_seqnum;
u16 ts_tstamp;
u8 ts_status;
- u8 ts_rate;
+ u8 ts_rate[4];
+ u8 ts_retry[4];
+ u8 ts_final_idx;
s8 ts_rssi;
u8 ts_shortretry;
u8 ts_longretry;
@@ -354,7 +499,6 @@ enum ath5k_tx_queue_id {
AR5K_TX_QUEUE_ID_XR_DATA = 9,
};
-
/*
* Flags to set hw queue's parameters...
*/
@@ -387,7 +531,8 @@ struct ath5k_txq_info {
/*
* Transmit packet types.
- * These are not fully used inside OpenHAL yet
+ * used on tx control descriptor
+ * TODO: Use them inside base.c corectly
*/
enum ath5k_pkt_type {
AR5K_PKT_TYPE_NORMAL = 0,
@@ -430,7 +575,7 @@ enum ath5k_dmasize {
\****************/
/*
- * RX Status
+ * RX Status descriptor
*/
struct ath5k_rx_status {
u16 rs_datalen;
@@ -494,34 +639,59 @@ struct ath5k_beacon_state {
#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+/*******************************\
+ GAIN OPTIMIZATION DEFINITIONS
+\*******************************/
+
+enum ath5k_rfgain {
+ AR5K_RFGAIN_INACTIVE = 0,
+ AR5K_RFGAIN_READ_REQUESTED,
+ AR5K_RFGAIN_NEED_CHANGE,
+};
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
+#define AR5K_GAIN_CCK_PROBE_CORR 5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
+#define AR5K_GAIN_STEP_COUNT 10
+#define AR5K_GAIN_PARAM_TX_CLIP 0
+#define AR5K_GAIN_PARAM_PD_90 1
+#define AR5K_GAIN_PARAM_PD_84 2
+#define AR5K_GAIN_PARAM_GAIN_SEL 3
+#define AR5K_GAIN_PARAM_MIX_ORN 0
+#define AR5K_GAIN_PARAM_PD_138 1
+#define AR5K_GAIN_PARAM_PD_137 2
+#define AR5K_GAIN_PARAM_PD_136 3
+#define AR5K_GAIN_PARAM_PD_132 4
+#define AR5K_GAIN_PARAM_PD_131 5
+#define AR5K_GAIN_PARAM_PD_130 6
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ath5k_gain_opt_step {
+ s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+ s32 gos_gain;
+};
+
+struct ath5k_gain {
+ u32 g_step_idx;
+ u32 g_current;
+ u32 g_target;
+ u32 g_low;
+ u32 g_high;
+ u32 g_f_corr;
+ u32 g_active;
+ const struct ath5k_gain_opt_step *g_step;
+};
+
+
/********************\
COMMON DEFINITIONS
\********************/
-/*
- * Atheros hardware descriptor
- * This is read and written to by the hardware
- */
-struct ath5k_desc {
- u32 ds_link; /* physical address of the next descriptor */
- u32 ds_data; /* physical address of data buffer (skb) */
-
- union {
- struct ath5k_hw_5210_tx_desc ds_tx5210;
- struct ath5k_hw_5212_tx_desc ds_tx5212;
- struct ath5k_hw_all_rx_desc ds_rx;
- } ud;
-} __packed;
-
-#define AR5K_RXDESC_INTREQ 0x0020
-
-#define AR5K_TXDESC_CLRDMASK 0x0001
-#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
-#define AR5K_TXDESC_RTSENA 0x0004
-#define AR5K_TXDESC_CTSENA 0x0008
-#define AR5K_TXDESC_INTREQ 0x0010
-#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
-
#define AR5K_SLOT_TIME_9 396
#define AR5K_SLOT_TIME_20 880
#define AR5K_SLOT_TIME_MAX 0xffff
@@ -553,167 +723,79 @@ struct ath5k_desc {
#define CHANNEL_MODES CHANNEL_ALL
/*
- * Used internaly in OpenHAL (ar5211.c/ar5212.c
- * for reset_tx_queue). Also see struct struct ieee80211_channel.
+ * Used internaly for reset_tx_queue).
+ * Also see struct struct ieee80211_channel.
*/
#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
/*
- * The following structure will be used to map 2GHz channels to
+ * The following structure is used to map 2GHz channels to
* 5GHz Atheros channels.
+ * TODO: Clean up
*/
struct ath5k_athchan_2ghz {
u32 a2_flags;
u16 a2_athchan;
};
-/*
- * Rate definitions
- * TODO: Clean them up or move them on mac80211 -most of these infos are
- * used by the rate control algorytm on MadWiFi.
- */
-/* Max number of rates on the rate table and what it seems
- * Atheros hardware supports */
-#define AR5K_MAX_RATES 32
+/******************\
+ RATE DEFINITIONS
+\******************/
/**
- * struct ath5k_rate - rate structure
- * @valid: is this a valid rate for rate control (remove)
- * @modulation: respective mac80211 modulation
- * @rate_kbps: rate in kbit/s
- * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
- * &struct ath5k_rx_status.rs_rate and on TX on
- * &struct ath5k_tx_status.ts_rate. Seems the ar5xxx harware supports
- * up to 32 rates, indexed by 1-32. This means we really only need
- * 6 bits for the rate_code.
- * @dot11_rate: respective IEEE-802.11 rate value
- * @control_rate: index of rate assumed to be used to send control frames.
- * This can be used to set override the value on the rate duration
- * registers. This is only useful if we can override in the harware at
- * what rate we want to send control frames at. Note that IEEE-802.11
- * Ch. 9.6 (after IEEE 802.11g changes) defines the rate at which we
- * should send ACK/CTS, if we change this value we can be breaking
- * the spec.
+ * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
*
- * This structure is used to get the RX rate or set the TX rate on the
+ * The rate code is used to get the RX rate or set the TX rate on the
* hardware descriptors. It is also used for internal modulation control
* and settings.
*
- * On RX after the &struct ath5k_desc is parsed by the appropriate
- * ah_proc_rx_desc() the respective hardware rate value is set in
- * &struct ath5k_rx_status.rs_rate. On TX the desired rate is set in
- * &struct ath5k_tx_status.ts_rate which is later used to setup the
- * &struct ath5k_desc correctly. This is the hardware rate map we are
- * aware of:
+ * This is the hardware rate map we are aware of:
*
- * rate_code 1 2 3 4 5 6 7 8
+ * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
* rate_kbps 3000 1000 ? ? ? 2000 500 48000
*
- * rate_code 9 10 11 12 13 14 15 16
+ * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
* rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
*
* rate_code 17 18 19 20 21 22 23 24
* rate_kbps ? ? ? ? ? ? ? 11000
*
* rate_code 25 26 27 28 29 30 31 32
- * rate_kbps 5500 2000 1000 ? ? ? ? ?
+ * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
*
+ * "S" indicates CCK rates with short preamble.
+ *
+ * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
+ * lowest 4 bits, so they are the same as below with a 0xF mask.
+ * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
+ * We handle this in ath5k_setup_bands().
*/
-struct ath5k_rate {
- u8 valid;
- u32 modulation;
- u16 rate_kbps;
- u8 rate_code;
- u8 dot11_rate;
- u8 control_rate;
-};
-
-/* XXX: GRR all this stuff to get leds blinking ??? (check out setcurmode) */
-struct ath5k_rate_table {
- u16 rate_count;
- u8 rate_code_to_index[AR5K_MAX_RATES]; /* Back-mapping */
- struct ath5k_rate rates[AR5K_MAX_RATES];
-};
-
-/*
- * Rate tables...
- * TODO: CLEAN THIS !!!
- */
-#define AR5K_RATES_11A { 8, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
- 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255 }, { \
- { 1, 0, 6000, 11, 140, 0 }, \
- { 1, 0, 9000, 15, 18, 0 }, \
- { 1, 0, 12000, 10, 152, 2 }, \
- { 1, 0, 18000, 14, 36, 2 }, \
- { 1, 0, 24000, 9, 176, 4 }, \
- { 1, 0, 36000, 13, 72, 4 }, \
- { 1, 0, 48000, 8, 96, 4 }, \
- { 1, 0, 54000, 12, 108, 4 } } \
-}
-
-#define AR5K_RATES_11B { 4, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
- 3, 2, 1, 0, 255, 255, 255, 255 }, { \
- { 1, 0, 1000, 27, 130, 0 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \
-}
-
-#define AR5K_RATES_11G { 12, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
- 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
- 3, 2, 1, 0, 255, 255, 255, 255 }, { \
- { 1, 0, 1000, 27, 2, 0 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \
- { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \
- { 0, 0, 6000, 11, 12, 4 }, \
- { 0, 0, 9000, 15, 18, 4 }, \
- { 1, 0, 12000, 10, 24, 6 }, \
- { 1, 0, 18000, 14, 36, 6 }, \
- { 1, 0, 24000, 9, 48, 8 }, \
- { 1, 0, 36000, 13, 72, 8 }, \
- { 1, 0, 48000, 8, 96, 8 }, \
- { 1, 0, 54000, 12, 108, 8 } } \
-}
-
-#define AR5K_RATES_TURBO { 8, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
- 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255 }, { \
- { 1, MODULATION_TURBO, 6000, 11, 140, 0 }, \
- { 1, MODULATION_TURBO, 9000, 15, 18, 0 }, \
- { 1, MODULATION_TURBO, 12000, 10, 152, 2 }, \
- { 1, MODULATION_TURBO, 18000, 14, 36, 2 }, \
- { 1, MODULATION_TURBO, 24000, 9, 176, 4 }, \
- { 1, MODULATION_TURBO, 36000, 13, 72, 4 }, \
- { 1, MODULATION_TURBO, 48000, 8, 96, 4 }, \
- { 1, MODULATION_TURBO, 54000, 12, 108, 4 } } \
-}
+#define AR5K_MAX_RATES 32
-#define AR5K_RATES_XR { 12, { \
- 255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \
- 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255 }, { \
- { 1, MODULATION_XR, 500, 7, 129, 0 }, \
- { 1, MODULATION_XR, 1000, 2, 139, 1 }, \
- { 1, MODULATION_XR, 2000, 6, 150, 2 }, \
- { 1, MODULATION_XR, 3000, 1, 150, 3 }, \
- { 1, 0, 6000, 11, 140, 4 }, \
- { 1, 0, 9000, 15, 18, 4 }, \
- { 1, 0, 12000, 10, 152, 6 }, \
- { 1, 0, 18000, 14, 36, 6 }, \
- { 1, 0, 24000, 9, 176, 8 }, \
- { 1, 0, 36000, 13, 72, 8 }, \
- { 1, 0, 48000, 8, 96, 8 }, \
- { 1, 0, 54000, 12, 108, 8 } } \
-}
+/* B */
+#define ATH5K_RATE_CODE_1M 0x1B
+#define ATH5K_RATE_CODE_2M 0x1A
+#define ATH5K_RATE_CODE_5_5M 0x19
+#define ATH5K_RATE_CODE_11M 0x18
+/* A and G */
+#define ATH5K_RATE_CODE_6M 0x0B
+#define ATH5K_RATE_CODE_9M 0x0F
+#define ATH5K_RATE_CODE_12M 0x0A
+#define ATH5K_RATE_CODE_18M 0x0E
+#define ATH5K_RATE_CODE_24M 0x09
+#define ATH5K_RATE_CODE_36M 0x0D
+#define ATH5K_RATE_CODE_48M 0x08
+#define ATH5K_RATE_CODE_54M 0x0C
+/* XR */
+#define ATH5K_RATE_CODE_XR_500K 0x07
+#define ATH5K_RATE_CODE_XR_1M 0x02
+#define ATH5K_RATE_CODE_XR_2M 0x06
+#define ATH5K_RATE_CODE_XR_3M 0x01
+
+/* adding this flag to rate_code enables short preamble */
+#define AR5K_SET_SHORT_PREAMBLE 0x04
/*
* Crypto definitions
@@ -735,7 +817,6 @@ struct ath5k_rate_table {
return (false); \
} while (0)
-
enum ath5k_ant_setting {
AR5K_ANT_VARIABLE = 0, /* variable by programming */
AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
@@ -846,7 +927,8 @@ enum ath5k_power_mode {
/*
* These match net80211 definitions (not used in
- * d80211).
+ * mac80211).
+ * TODO: Clean this up
*/
#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/
#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/
@@ -862,7 +944,8 @@ enum ath5k_power_mode {
/*
* Chipset capabilities -see ath5k_hw_get_capability-
* get_capability function is not yet fully implemented
- * in OpenHAL so most of these don't work yet...
+ * in ath5k so most of these don't work yet...
+ * TODO: Implement these & merge with _TUNE_ stuff above
*/
enum ath5k_capability_type {
AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
@@ -931,6 +1014,7 @@ struct ath5k_capabilities {
#define AR5K_MAX_GPIO 10
#define AR5K_MAX_RF_BANKS 8
+/* TODO: Clean up and merge with ath5k_softc */
struct ath5k_hw {
u32 ah_magic;
@@ -939,7 +1023,7 @@ struct ath5k_hw {
enum ath5k_int ah_imr;
- enum ieee80211_if_types ah_op_mode;
+ enum nl80211_iftype ah_op_mode;
enum ath5k_power_mode ah_power_mode;
struct ieee80211_channel ah_current_channel;
bool ah_turbo;
@@ -1023,11 +1107,13 @@ struct ath5k_hw {
/*
* Function pointers
*/
+ int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags);
int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int);
- int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int);
int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
@@ -1040,33 +1126,38 @@ struct ath5k_hw {
* Prototypes
*/
-/* General Functions */
-extern int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set);
/* Attach/Detach Functions */
extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
-extern const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, unsigned int mode);
extern void ath5k_hw_detach(struct ath5k_hw *ah);
+
/* Reset Functions */
-extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel);
+extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
/* Power management functions */
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
+
/* DMA Related Functions */
-extern void ath5k_hw_start_rx(struct ath5k_hw *ah);
+extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
-extern u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah);
-extern void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr);
-extern int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
-extern u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue);
-extern int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr);
+extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
+ u32 phys_addr);
extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
/* Interrupt handling */
extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
-extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
+extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum
+ath5k_int new_mask);
extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
+
/* EEPROM access functions */
-extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
+extern int ath5k_eeprom_init(struct ath5k_hw *ah);
+extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+
/* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
/* BSSID Functions */
@@ -1076,14 +1167,14 @@ extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc
extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
/* Receive start/stop functions */
extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
-extern void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah);
+extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
/* RX Filter functions */
extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
-extern int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index);
+extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
-/* Beacon related functions */
+/* Beacon control functions */
extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
@@ -1105,61 +1196,129 @@ extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
+
/* Queue Control Unit, DFS Control Unit Functions */
-extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info);
-extern int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info);
extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
+ const struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
+ enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info);
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
-extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
-extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+
/* Hardware Descriptor Functions */
-extern int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags);
+extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
+
/* GPIO Functions */
extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
-extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+
/* Misc functions */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
-
+extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
/* Initial register settings functions */
extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
+
/* Initialize RF */
extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode);
extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq);
extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah);
extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah);
-
-
/* PHY/RF channel functions */
extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
/* PHY calibration */
extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
-extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
/* Misc PHY functions */
extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
-extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* TX power setup */
extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower);
extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
+/*
+ * Functions used internaly
+ */
+/*
+ * Translate usec to hw clock units
+ */
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+{
+ return turbo ? (usec * 80) : (usec * 40);
+}
+
+/*
+ * Translate hw clock units to usec
+ */
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+{
+ return turbo ? (clock / 80) : (clock / 40);
+}
+
+/*
+ * Read from a register
+ */
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
return ioread32(ah->ah_iobase + reg);
}
+/*
+ * Write to a register
+ */
static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
{
iowrite32(val, ah->ah_iobase + reg);
}
+#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
+/*
+ * Check if a register write has been completed
+ */
+static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
+ u32 val, bool is_set)
+{
+ int i;
+ u32 data;
+
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ data = ath5k_hw_reg_read(ah, reg);
+ if (is_set && (data & flag))
+ break;
+ else if ((data & flag) == val)
+ break;
+ udelay(15);
+ }
+
+ return (i <= 0) ? -EAGAIN : 0;
+}
+#endif
+
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
+{
+ u32 retval = 0, bit, i;
+
+ for (i = 0; i < bits; i++) {
+ bit = (val >> i) & 1;
+ retval = (retval << 1) | bit;
+ }
+
+ return retval;
+}
+
#endif
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c
new file mode 100644
index 00000000000..51d569883cd
--- /dev/null
+++ b/drivers/net/wireless/ath5k/attach.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* Attach/Detach Functions and helpers *
+\*************************************/
+
+#include <linux/pci.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/**
+ * ath5k_hw_post - Power On Self Test helper function
+ *
+ * @ah: The &struct ath5k_hw
+ */
+static int ath5k_hw_post(struct ath5k_hw *ah)
+{
+
+ int i, c;
+ u16 cur_reg;
+ u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
+ u32 var_pattern;
+ u32 static_pattern[4] = {
+ 0x55555555, 0xaaaaaaaa,
+ 0x66666666, 0x99999999
+ };
+ u32 init_val;
+ u32 cur_val;
+
+ for (c = 0; c < 2; c++) {
+
+ cur_reg = regs[c];
+
+ /* Save previous value */
+ init_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ for (i = 0; i < 256; i++) {
+ var_pattern = i << 16 | i;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x0039080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ for (i = 0; i < 4; i++) {
+ var_pattern = static_pattern[i];
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x003b080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ /* Restore previous value */
+ ath5k_hw_reg_write(ah, init_val, cur_reg);
+
+ }
+
+ return 0;
+
+}
+
+/**
+ * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ *
+ * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @mac_version: The mac version id (check out ath5k.h) based on pci id
+ *
+ * Check if the device is supported, perform a POST and initialize the needed
+ * structs. Returns -ENOMEM if we don't have memory for the needed structs,
+ * -ENODEV if the device is not supported or prints an error msg if something
+ * else went wrong.
+ */
+struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+{
+ struct ath5k_hw *ah;
+ struct pci_dev *pdev = sc->pdev;
+ u8 mac[ETH_ALEN];
+ int ret;
+ u32 srev;
+
+ /*If we passed the test malloc a ath5k_hw struct*/
+ ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+ if (ah == NULL) {
+ ret = -ENOMEM;
+ ATH5K_ERR(sc, "out of memory\n");
+ goto err;
+ }
+
+ ah->ah_sc = sc;
+ ah->ah_iobase = sc->iobase;
+
+ /*
+ * HW information
+ */
+ ah->ah_op_mode = NL80211_IFTYPE_STATION;
+ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+ ah->ah_turbo = false;
+ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+ ah->ah_imr = 0;
+ ah->ah_atim_window = 0;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+ ah->ah_software_retry = false;
+ ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
+
+ /*
+ * Set the mac version based on the pci id
+ */
+ ah->ah_version = mac_version;
+
+ /*Fill the ath5k_hw struct with the needed functions*/
+ ret = ath5k_hw_init_desc_functions(ah);
+ if (ret)
+ goto err_free;
+
+ /* Bring device out of sleep and reset it's units */
+ ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
+ if (ret)
+ goto err_free;
+
+ /* Get MAC, PHY and RADIO revisions */
+ srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ ah->ah_mac_srev = srev;
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
+ 0xffffffff;
+ ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_5GHZ);
+ ah->ah_phy = AR5K_PHY(0);
+
+ /* Try to identify radio chip based on it's srev */
+ switch (ah->ah_radio_5ghz_revision & 0xf0) {
+ case AR5K_SREV_RAD_5111:
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = false;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
+ break;
+ case AR5K_SREV_RAD_5112:
+ case AR5K_SREV_RAD_2112:
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = false;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
+ break;
+ case AR5K_SREV_RAD_2413:
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
+ break;
+ case AR5K_SREV_RAD_5413:
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
+ break;
+ case AR5K_SREV_RAD_2316:
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
+ break;
+ case AR5K_SREV_RAD_2317:
+ ah->ah_radio = AR5K_RF2317;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2317;
+ break;
+ case AR5K_SREV_RAD_5424:
+ if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
+ ah->ah_mac_version == AR5K_SREV_AR2417){
+ ah->ah_radio = AR5K_RF2425;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
+ } else {
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = true;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
+ }
+ break;
+ default:
+ /* Identify radio based on mac/phy srev */
+ if (ah->ah_version == AR5K_AR5210) {
+ ah->ah_radio = AR5K_RF5110;
+ ah->ah_single_chip = false;
+ } else if (ah->ah_version == AR5K_AR5211) {
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = false;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
+ ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+ ah->ah_radio = AR5K_RF2425;
+ ah->ah_single_chip = true;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
+ } else if (srev == AR5K_SREV_AR5213A &&
+ ah->ah_phy_revision == AR5K_SREV_PHY_2112B) {
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = false;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2112B;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = true;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = true;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = true;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
+ } else {
+ ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+ }
+
+
+ /* Return on unsuported chips (unsupported eeprom etc) */
+ if ((srev >= AR5K_SREV_AR5416) &&
+ (srev < AR5K_SREV_AR2425)) {
+ ATH5K_ERR(sc, "Device not yet supported.\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ /*
+ * Write PCI-E power save settings
+ */
+ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
+ ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
+ /* Shut off RX when elecidle is asserted */
+ ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
+ /* TODO: EEPROM work */
+ ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
+ /* Shut off PLL and CLKREQ active in L1 */
+ ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
+ /* Preserce other settings */
+ ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
+ /* Reset SERDES to load new settings */
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
+ mdelay(1);
+ }
+
+ /*
+ * POST
+ */
+ ret = ath5k_hw_post(ah);
+ if (ret)
+ goto err_free;
+
+ /* Enable pci core retry fix on Hainan (5213A) and later chips */
+ if (srev >= AR5K_SREV_AR5213A)
+ ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
+
+ /*
+ * Get card capabilities, calibration values etc
+ * TODO: EEPROM work
+ */
+ ret = ath5k_eeprom_init(ah);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to init EEPROM\n");
+ goto err_free;
+ }
+
+ /* Get misc capabilities */
+ ret = ath5k_hw_set_capabilities(ah);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ /* Set MAC address */
+ ret = ath5k_eeprom_read_mac(ah, mac);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ ath5k_hw_set_lladdr(ah, mac);
+ /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_set_rfgain_opt(ah);
+
+ return ah;
+err_free:
+ kfree(ah);
+err:
+ return ERR_PTR(ret);
+}
+
+/**
+ * ath5k_hw_detach - Free the ath5k_hw struct
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_detach(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+
+ if (ah->ah_rf_banks != NULL)
+ kfree(ah->ah_rf_banks);
+
+ /* assume interrupts are down */
+ kfree(ah);
+}
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 0676c6d8438..9b95c4049b3 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -72,7 +72,7 @@ MODULE_AUTHOR("Nick Kossifidis");
MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.5.0 (EXPERIMENTAL)");
+MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
/* Known PCI ids */
@@ -93,45 +93,94 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
{ PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
- { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/
+ { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
/* Known SREVs */
static struct ath5k_srev_name srev_names[] = {
- { "5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210 },
- { "5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311 },
- { "5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A },
- { "5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B },
- { "5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211 },
- { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
- { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
- { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
- { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 },
- { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 },
- { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
- { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
- { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
- { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 },
- { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 },
- { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 },
- { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 },
- { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN },
+ { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
+ { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
+ { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
+ { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B },
+ { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 },
+ { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 },
+ { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 },
+ { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A },
+ { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 },
+ { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 },
+ { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 },
+ { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 },
+ { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 },
+ { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 },
+ { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 },
+ { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
+ { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
+ { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
+ { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
+ { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A },
{ "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
{ "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
{ "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
+ { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B },
{ "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
{ "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
- { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 },
- { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
- { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
+ { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
+ { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
+ { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
+ { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
};
+static struct ieee80211_rate ath5k_rates[] = {
+ { .bitrate = 10,
+ .hw_value = ATH5K_RATE_CODE_1M, },
+ { .bitrate = 20,
+ .hw_value = ATH5K_RATE_CODE_2M,
+ .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55,
+ .hw_value = ATH5K_RATE_CODE_5_5M,
+ .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110,
+ .hw_value = ATH5K_RATE_CODE_11M,
+ .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 60,
+ .hw_value = ATH5K_RATE_CODE_6M,
+ .flags = 0 },
+ { .bitrate = 90,
+ .hw_value = ATH5K_RATE_CODE_9M,
+ .flags = 0 },
+ { .bitrate = 120,
+ .hw_value = ATH5K_RATE_CODE_12M,
+ .flags = 0 },
+ { .bitrate = 180,
+ .hw_value = ATH5K_RATE_CODE_18M,
+ .flags = 0 },
+ { .bitrate = 240,
+ .hw_value = ATH5K_RATE_CODE_24M,
+ .flags = 0 },
+ { .bitrate = 360,
+ .hw_value = ATH5K_RATE_CODE_36M,
+ .flags = 0 },
+ { .bitrate = 480,
+ .hw_value = ATH5K_RATE_CODE_48M,
+ .flags = 0 },
+ { .bitrate = 540,
+ .hw_value = ATH5K_RATE_CODE_54M,
+ .flags = 0 },
+ /* XR missing */
+};
+
/*
* Prototypes - PCI stack related functions
*/
@@ -162,7 +211,8 @@ static struct pci_driver ath5k_pci_driver = {
* Prototypes - MAC 802.11 stack related functions
*/
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int ath5k_reset(struct ieee80211_hw *hw);
+static int ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel);
+static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
static void ath5k_stop(struct ieee80211_hw *hw);
static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -218,20 +268,16 @@ static void ath5k_detach(struct pci_dev *pdev,
struct ieee80211_hw *hw);
/* Channel/mode setup */
static inline short ath5k_ieee2mhz(short chan);
-static unsigned int ath5k_copy_rates(struct ieee80211_rate *rates,
- const struct ath5k_rate_table *rt,
- unsigned int max);
static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
struct ieee80211_channel *channels,
unsigned int mode,
unsigned int max);
-static int ath5k_getchannels(struct ieee80211_hw *hw);
+static int ath5k_setup_bands(struct ieee80211_hw *hw);
static int ath5k_chan_set(struct ath5k_softc *sc,
struct ieee80211_channel *chan);
static void ath5k_setcurmode(struct ath5k_softc *sc,
unsigned int mode);
static void ath5k_mode_setup(struct ath5k_softc *sc);
-static void ath5k_set_total_hw_rates(struct ath5k_softc *sc);
/* Descriptor setup */
static int ath5k_desc_alloc(struct ath5k_softc *sc,
@@ -351,7 +397,11 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
if (srev_names[i].sr_type != type)
continue;
- if ((val & 0xff) < srev_names[i + 1].sr_val) {
+
+ if ((val & 0xf0) == srev_names[i].sr_val)
+ name = srev_names[i].sr_name;
+
+ if ((val & 0xff) == srev_names[i].sr_val) {
name = srev_names[i].sr_name;
break;
}
@@ -446,6 +496,12 @@ ath5k_pci_probe(struct pci_dev *pdev,
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
hw->extra_tx_headroom = 2;
hw->channel_change_time = 5000;
sc = hw->priv;
@@ -462,7 +518,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
sc->iobase = mem; /* So we can unmap it on detach */
sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
- sc->opmode = IEEE80211_IF_TYPE_STA;
+ sc->opmode = NL80211_IFTYPE_STATION;
mutex_init(&sc->lock);
spin_lock_init(&sc->rxbuflock);
spin_lock_init(&sc->txbuflock);
@@ -485,13 +541,19 @@ ath5k_pci_probe(struct pci_dev *pdev,
goto err_irq;
}
+ /* set up multi-rate retry capabilities */
+ if (sc->ah->ah_version == AR5K_AR5212) {
+ hw->max_altrates = 3;
+ hw->max_altrate_tries = 11;
+ }
+
/* Finish private driver data initialization */
ret = ath5k_attach(pdev, hw);
if (ret)
goto err_ah;
ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_VER,sc->ah->ah_mac_srev),
+ ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
sc->ah->ah_mac_srev,
sc->ah->ah_phy_revision);
@@ -646,7 +708,6 @@ err_no_irq:
#endif /* CONFIG_PM */
-
/***********************\
* Driver Initialization *
\***********************/
@@ -669,7 +730,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
* return false w/o doing anything. MAC's that do
* support it will return true w/o doing anything.
*/
- ret = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
+ ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
if (ret < 0)
goto err;
if (ret > 0)
@@ -688,15 +749,12 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
* on settings like the phy mode and regulatory
* domain restrictions.
*/
- ret = ath5k_getchannels(hw);
+ ret = ath5k_setup_bands(hw);
if (ret) {
ATH5K_ERR(sc, "can't get channels\n");
goto err;
}
- /* Set *_rates so we can map hw rate index */
- ath5k_set_total_hw_rates(sc);
-
/* NB: setup here so ath5k_rate_update is happy */
if (test_bit(AR5K_MODE_11A, ah->ah_modes))
ath5k_setcurmode(sc, AR5K_MODE_11A);
@@ -813,27 +871,6 @@ ath5k_ieee2mhz(short chan)
}
static unsigned int
-ath5k_copy_rates(struct ieee80211_rate *rates,
- const struct ath5k_rate_table *rt,
- unsigned int max)
-{
- unsigned int i, count;
-
- if (rt == NULL)
- return 0;
-
- for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
- rates[count].bitrate = rt->rates[i].rate_kbps / 100;
- rates[count].hw_value = rt->rates[i].rate_code;
- rates[count].flags = rt->rates[i].modulation;
- count++;
- max--;
- }
-
- return count;
-}
-
-static unsigned int
ath5k_copy_channels(struct ath5k_hw *ah,
struct ieee80211_channel *channels,
unsigned int mode,
@@ -895,74 +932,97 @@ ath5k_copy_channels(struct ath5k_hw *ah,
return count;
}
+static void
+ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
+{
+ u8 i;
+
+ for (i = 0; i < AR5K_MAX_RATES; i++)
+ sc->rate_idx[b->band][i] = -1;
+
+ for (i = 0; i < b->n_bitrates; i++) {
+ sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
+ if (b->bitrates[i].hw_value_short)
+ sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
+ }
+}
+
static int
-ath5k_getchannels(struct ieee80211_hw *hw)
+ath5k_setup_bands(struct ieee80211_hw *hw)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
- struct ieee80211_supported_band *sbands = sc->sbands;
- const struct ath5k_rate_table *hw_rates;
- unsigned int max_r, max_c, count_r, count_c;
- int mode2g = AR5K_MODE_11G;
+ struct ieee80211_supported_band *sband;
+ int max_c, count_c = 0;
+ int i;
BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
-
- max_r = ARRAY_SIZE(sc->rates);
max_c = ARRAY_SIZE(sc->channels);
- count_r = count_c = 0;
/* 2GHz band */
- if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
- mode2g = AR5K_MODE_11B;
- if (!test_bit(AR5K_MODE_11B,
- sc->ah->ah_capabilities.cap_mode))
- mode2g = -1;
- }
+ sband = &sc->sbands[IEEE80211_BAND_2GHZ];
+ sband->band = IEEE80211_BAND_2GHZ;
+ sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
- if (mode2g > 0) {
- struct ieee80211_supported_band *sband =
- &sbands[IEEE80211_BAND_2GHZ];
+ if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
+ /* G mode */
+ memcpy(sband->bitrates, &ath5k_rates[0],
+ sizeof(struct ieee80211_rate) * 12);
+ sband->n_bitrates = 12;
- sband->bitrates = sc->rates;
sband->channels = sc->channels;
-
- sband->band = IEEE80211_BAND_2GHZ;
sband->n_channels = ath5k_copy_channels(ah, sband->channels,
- mode2g, max_c);
-
- hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
- sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
- hw_rates, max_r);
+ AR5K_MODE_11G, max_c);
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
count_c = sband->n_channels;
- count_r = sband->n_bitrates;
+ max_c -= count_c;
+ } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
+ /* B mode */
+ memcpy(sband->bitrates, &ath5k_rates[0],
+ sizeof(struct ieee80211_rate) * 4);
+ sband->n_bitrates = 4;
+
+ /* 5211 only supports B rates and uses 4bit rate codes
+ * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B)
+ * fix them up here:
+ */
+ if (ah->ah_version == AR5K_AR5211) {
+ for (i = 0; i < 4; i++) {
+ sband->bitrates[i].hw_value =
+ sband->bitrates[i].hw_value & 0xF;
+ sband->bitrates[i].hw_value_short =
+ sband->bitrates[i].hw_value_short & 0xF;
+ }
+ }
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
+ sband->channels = sc->channels;
+ sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+ AR5K_MODE_11B, max_c);
- max_r -= count_r;
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
+ count_c = sband->n_channels;
max_c -= count_c;
-
}
+ ath5k_setup_rate_idx(sc, sband);
- /* 5GHz band */
-
+ /* 5GHz band, A mode */
if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
- struct ieee80211_supported_band *sband =
- &sbands[IEEE80211_BAND_5GHZ];
+ sband = &sc->sbands[IEEE80211_BAND_5GHZ];
+ sband->band = IEEE80211_BAND_5GHZ;
+ sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
- sband->bitrates = &sc->rates[count_r];
- sband->channels = &sc->channels[count_c];
+ memcpy(sband->bitrates, &ath5k_rates[4],
+ sizeof(struct ieee80211_rate) * 8);
+ sband->n_bitrates = 8;
- sband->band = IEEE80211_BAND_5GHZ;
+ sband->channels = &sc->channels[count_c];
sband->n_channels = ath5k_copy_channels(ah, sband->channels,
AR5K_MODE_11A, max_c);
- hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A);
- sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
- hw_rates, max_r);
-
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
}
+ ath5k_setup_rate_idx(sc, sband);
ath5k_debug_dump_bands(sc);
@@ -978,9 +1038,6 @@ ath5k_getchannels(struct ieee80211_hw *hw)
static int
ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
{
- struct ath5k_hw *ah = sc->ah;
- int ret;
-
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
sc->curchan->center_freq, chan->center_freq);
@@ -996,41 +1053,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- ath5k_hw_set_intr(ah, 0); /* disable interrupts */
- ath5k_txq_cleanup(sc); /* clear pending tx frames */
- ath5k_rx_stop(sc); /* turn off frame recv */
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
- if (ret) {
- ATH5K_ERR(sc, "%s: unable to reset channel "
- "(%u Mhz)\n", __func__, chan->center_freq);
- return ret;
- }
-
- ath5k_hw_set_txpower_limit(sc->ah, 0);
-
- /*
- * Re-enable rx framework.
- */
- ret = ath5k_rx_start(sc);
- if (ret) {
- ATH5K_ERR(sc, "%s: unable to restart recv logic\n",
- __func__);
- return ret;
- }
-
- /*
- * Change channels and update the h/w rate map
- * if we're switching; e.g. 11a to 11b/g.
- *
- * XXX needed?
- */
-/* ath5k_chan_change(sc, chan); */
-
- ath5k_beacon_config(sc);
- /*
- * Re-enable interrupts.
- */
- ath5k_hw_set_intr(ah, sc->imask);
+ return ath5k_reset(sc, true, true);
}
return 0;
@@ -1068,75 +1091,13 @@ ath5k_mode_setup(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
}
-/*
- * Match the hw provided rate index (through descriptors)
- * to an index for sc->curband->bitrates, so it can be used
- * by the stack.
- *
- * This one is a little bit tricky but i think i'm right
- * about this...
- *
- * We have 4 rate tables in the following order:
- * XR (4 rates)
- * 802.11a (8 rates)
- * 802.11b (4 rates)
- * 802.11g (12 rates)
- * that make the hw rate table.
- *
- * Lets take a 5211 for example that supports a and b modes only.
- * First comes the 802.11a table and then 802.11b (total 12 rates).
- * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit),
- * if it returns 2 it points to the second 802.11a rate etc.
- *
- * Same goes for 5212 who has xr/a/b/g support (total 28 rates).
- * First comes the XR table, then 802.11a, 802.11b and 802.11g.
- * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc
- */
-static void
-ath5k_set_total_hw_rates(struct ath5k_softc *sc) {
-
- struct ath5k_hw *ah = sc->ah;
-
- if (test_bit(AR5K_MODE_11A, ah->ah_modes))
- sc->a_rates = 8;
-
- if (test_bit(AR5K_MODE_11B, ah->ah_modes))
- sc->b_rates = 4;
-
- if (test_bit(AR5K_MODE_11G, ah->ah_modes))
- sc->g_rates = 12;
-
- /* XXX: Need to see what what happens when
- xr disable bits in eeprom are set */
- if (ah->ah_version >= AR5K_AR5212)
- sc->xr_rates = 4;
-
-}
-
static inline int
-ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) {
-
- int mac80211_rix;
-
- if(sc->curband->band == IEEE80211_BAND_2GHZ) {
- /* We setup a g ratetable for both b/g modes */
- mac80211_rix =
- hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates;
- } else {
- mac80211_rix = hw_rix - sc->xr_rates;
- }
-
- /* Something went wrong, fallback to basic rate for this band */
- if ((mac80211_rix >= sc->curband->n_bitrates) ||
- (mac80211_rix <= 0 ))
- mac80211_rix = 1;
-
- return mac80211_rix;
+ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
+{
+ WARN_ON(hw_rix < 0 || hw_rix > AR5K_MAX_RATES);
+ return sc->rate_idx[sc->curband->band][hw_rix];
}
-
-
-
/***************\
* Buffers setup *
\***************/
@@ -1199,7 +1160,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds = bf->desc;
ds->ds_link = bf->daddr; /* link to self */
ds->ds_data = bf->skbaddr;
- ath5k_hw_setup_rx_desc(ah, ds,
+ ah->ah_setup_rx_desc(ah, ds,
skb_tailroom(skb), /* buffer size */
0);
@@ -1218,7 +1179,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
- int ret;
+ struct ieee80211_rate *rate;
+ unsigned int mrr_rate[3], mrr_tries[3];
+ int i, ret;
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
@@ -1233,7 +1196,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
if (info->control.hw_key) {
keyidx = info->control.hw_key->hw_key_idx;
- pktlen += info->control.icv_len;
+ pktlen += info->control.hw_key->icv_len;
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
@@ -1243,6 +1206,22 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
if (ret)
goto err_unmap;
+ memset(mrr_rate, 0, sizeof(mrr_rate));
+ memset(mrr_tries, 0, sizeof(mrr_tries));
+ for (i = 0; i < 3; i++) {
+ rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+ if (!rate)
+ break;
+
+ mrr_rate[i] = rate->hw_value;
+ mrr_tries[i] = info->control.retries[i].limit;
+ }
+
+ ah->ah_setup_mrr_tx_desc(ah, ds,
+ mrr_rate[0], mrr_tries[0],
+ mrr_rate[1], mrr_tries[1],
+ mrr_rate[2], mrr_tries[2]);
+
ds->ds_link = 0;
ds->ds_data = bf->skbaddr;
@@ -1250,12 +1229,12 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
list_add_tail(&bf->list, &txq->q);
sc->tx_stats[txq->qnum].len++;
if (txq->link == NULL) /* is this first packet? */
- ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr);
+ ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
else /* no, so only link it */
*txq->link = bf->daddr;
txq->link = &ds->ds_link;
- ath5k_hw_tx_start(ah, txq->qnum);
+ ath5k_hw_start_tx_dma(ah, txq->qnum);
mmiowb();
spin_unlock_bh(&txq->lock);
@@ -1433,7 +1412,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
if (ret)
return ret;
- if (sc->opmode == IEEE80211_IF_TYPE_AP) {
+ if (sc->opmode == NL80211_IFTYPE_AP ||
+ sc->opmode == NL80211_IFTYPE_MESH_POINT) {
/*
* Always burst out beacon and CAB traffic
* (aifs = cwmin = cwmax = 0)
@@ -1441,7 +1421,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_aifs = 0;
qi.tqi_cw_min = 0;
qi.tqi_cw_max = 0;
- } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/*
* Adhoc mode; backoff between 0 and (2 * cw_min).
*/
@@ -1454,7 +1434,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
- ret = ath5k_hw_setup_tx_queueprops(ah, sc->bhalq, &qi);
+ ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
if (ret) {
ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
"hardware queue!\n", __func__);
@@ -1503,14 +1483,14 @@ ath5k_txq_cleanup(struct ath5k_softc *sc)
/* don't touch the hardware if marked invalid */
ath5k_hw_stop_tx_dma(ah, sc->bhalq);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
- ath5k_hw_get_tx_buf(ah, sc->bhalq));
+ ath5k_hw_get_txdp(ah, sc->bhalq));
for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
if (sc->txqs[i].setup) {
ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
"link %p\n",
sc->txqs[i].qnum,
- ath5k_hw_get_tx_buf(ah,
+ ath5k_hw_get_txdp(ah,
sc->txqs[i].qnum),
sc->txqs[i].link);
}
@@ -1570,8 +1550,8 @@ ath5k_rx_start(struct ath5k_softc *sc)
bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
spin_unlock_bh(&sc->rxbuflock);
- ath5k_hw_put_rx_buf(ah, bf->daddr);
- ath5k_hw_start_rx(ah); /* enable recv descriptors */
+ ath5k_hw_set_rxdp(ah, bf->daddr);
+ ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
ath5k_mode_setup(sc); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
@@ -1588,7 +1568,7 @@ ath5k_rx_stop(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
- ath5k_hw_stop_pcu_recv(ah); /* disable PCU */
+ ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
@@ -1602,7 +1582,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
struct sk_buff *skb, struct ath5k_rx_status *rs)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
- unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
+ unsigned int keyix, hlen;
if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
rs->rs_keyix != AR5K_RXKEYIX_INVALID)
@@ -1611,6 +1591,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
/* Apparently when a default key is used to decrypt the packet
the hw does not set the index used to decrypt. In such cases
get the index from the packet. */
+ hlen = ieee80211_hdrlen(hdr->frame_control);
if (ieee80211_has_protected(hdr->frame_control) &&
!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
skb->len >= hlen + 4) {
@@ -1768,7 +1749,7 @@ ath5k_tasklet_rx(unsigned long data)
/* let crypto-error packets fall through in MNTR */
if ((rs.rs_status &
~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
- sc->opmode != IEEE80211_IF_TYPE_MNTR)
+ sc->opmode != NL80211_IFTYPE_MONITOR)
goto next;
}
accept:
@@ -1824,10 +1805,14 @@ accept:
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
+ if (rxs.rate_idx >= 0 && rs.rs_rate ==
+ sc->curband->bitrates[rxs.rate_idx].hw_value_short)
+ rxs.flag |= RX_FLAG_SHORTPRE;
+
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
/* check beacons in IBSS mode */
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+ if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, &rxs);
__ieee80211_rx(sc->hw, skb, &rxs);
@@ -1853,7 +1838,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
struct ath5k_desc *ds;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
- int ret;
+ int i, ret;
spin_lock(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
@@ -1875,7 +1860,25 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
PCI_DMA_TODEVICE);
- info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
+ memset(&info->status, 0, sizeof(info->status));
+ info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
+ ts.ts_rate[ts.ts_final_idx]);
+ info->status.retry_count = ts.ts_longretry;
+
+ for (i = 0; i < 4; i++) {
+ struct ieee80211_tx_altrate *r =
+ &info->status.retries[i];
+
+ if (ts.ts_rate[i]) {
+ r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
+ r->limit = ts.ts_retry[i];
+ } else {
+ r->rate_idx = -1;
+ r->limit = 0;
+ }
+ }
+
+ info->status.excessive_retries = 0;
if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
if (ts.ts_status & AR5K_TXERR_XRETRY)
@@ -1942,7 +1945,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds = bf->desc;
flags = AR5K_TXDESC_NOACK;
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) {
+ if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
ds->ds_link = bf->daddr; /* self-linked */
flags |= AR5K_TXDESC_VEOL;
/*
@@ -1991,8 +1994,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
- if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
- sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
+ if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+ sc->opmode == NL80211_IFTYPE_MONITOR)) {
ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
return;
}
@@ -2032,8 +2035,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
/* NB: hw still stops DMA, so proceed */
}
- ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
- ath5k_hw_tx_start(ah, sc->bhalq);
+ ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
+ ath5k_hw_start_tx_dma(ah, sc->bhalq);
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
@@ -2162,13 +2165,13 @@ ath5k_beacon_config(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
- ath5k_hw_set_intr(ah, 0);
+ ath5k_hw_set_imr(ah, 0);
sc->bmisscount = 0;
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
- if (sc->opmode == IEEE80211_IF_TYPE_STA) {
+ if (sc->opmode == NL80211_IFTYPE_STATION) {
sc->imask |= AR5K_INT_BMISS;
- } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@@ -2188,7 +2191,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
}
/* TODO else AP */
- ath5k_hw_set_intr(ah, sc->imask);
+ ath5k_hw_set_imr(ah, sc->imask);
}
@@ -2220,36 +2223,13 @@ ath5k_init(struct ath5k_softc *sc)
*/
sc->curchan = sc->hw->conf.channel;
sc->curband = &sc->sbands[sc->curchan->band];
- ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
- if (ret) {
- ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
- goto done;
- }
- /*
- * This is needed only to setup initial state
- * but it's best done after a reset.
- */
- ath5k_hw_set_txpower_limit(sc->ah, 0);
-
- /*
- * Setup the hardware after reset: the key cache
- * is filled as needed and the receive engine is
- * set going. Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- ret = ath5k_rx_start(sc);
- if (ret)
- goto done;
-
- /*
- * Enable interrupts.
- */
sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
AR5K_INT_MIB;
+ ret = ath5k_reset(sc, false, false);
+ if (ret)
+ goto done;
- ath5k_hw_set_intr(sc->ah, sc->imask);
/* Set ack to be sent at low bit-rates */
ath5k_hw_set_ack_bitrate_high(sc->ah, false);
@@ -2290,7 +2270,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
if (!test_bit(ATH_STAT_INVALID, sc->status)) {
ath5k_led_off(sc);
- ath5k_hw_set_intr(ah, 0);
+ ath5k_hw_set_imr(ah, 0);
synchronize_irq(sc->pdev->irq);
}
ath5k_txq_cleanup(sc);
@@ -2396,7 +2376,7 @@ ath5k_intr(int irq, void *dev_id)
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(ah);
sc->nexttbtt += sc->bintval;
@@ -2451,7 +2431,7 @@ ath5k_tasklet_reset(unsigned long data)
{
struct ath5k_softc *sc = (void *)data;
- ath5k_reset(sc->hw);
+ ath5k_reset_wake(sc);
}
/*
@@ -2474,7 +2454,7 @@ ath5k_calibrate(unsigned long data)
* to load new gain values.
*/
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
- ath5k_reset(sc->hw);
+ ath5k_reset_wake(sc);
}
if (ath5k_hw_phy_calibrate(ah, sc->curchan))
ATH5K_ERR(sc, "calibration of channel %u failed\n",
@@ -2626,7 +2606,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ath5k_debug_dump_skb(sc, skb, "TX ", 1);
- if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
+ if (sc->opmode == NL80211_IFTYPE_MONITOR)
ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
/*
@@ -2675,48 +2655,67 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
static int
-ath5k_reset(struct ieee80211_hw *hw)
+ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel)
{
- struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
- ath5k_hw_set_intr(ah, 0);
- ath5k_txq_cleanup(sc);
- ath5k_rx_stop(sc);
-
+ if (stop) {
+ ath5k_hw_set_imr(ah, 0);
+ ath5k_txq_cleanup(sc);
+ ath5k_rx_stop(sc);
+ }
ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
- if (unlikely(ret)) {
+ if (ret) {
ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
goto err;
}
+
+ /*
+ * This is needed only to setup initial state
+ * but it's best done after a reset.
+ */
ath5k_hw_set_txpower_limit(sc->ah, 0);
ret = ath5k_rx_start(sc);
- if (unlikely(ret)) {
+ if (ret) {
ATH5K_ERR(sc, "can't start recv logic\n");
goto err;
}
+
/*
- * We may be doing a reset in response to an ioctl
- * that changes the channel so update any state that
- * might change as a result.
+ * Change channels and update the h/w rate map if we're switching;
+ * e.g. 11a to 11b/g.
+ *
+ * We may be doing a reset in response to an ioctl that changes the
+ * channel so update any state that might change as a result.
*
* XXX needed?
*/
/* ath5k_chan_change(sc, c); */
- ath5k_beacon_config(sc);
- /* intrs are started by ath5k_beacon_config */
- ieee80211_wake_queues(hw);
+ ath5k_beacon_config(sc);
+ /* intrs are enabled by ath5k_beacon_config */
return 0;
err:
return ret;
}
+static int
+ath5k_reset_wake(struct ath5k_softc *sc)
+{
+ int ret;
+
+ ret = ath5k_reset(sc, true, true);
+ if (!ret)
+ ieee80211_wake_queues(sc->hw);
+
+ return ret;
+}
+
static int ath5k_start(struct ieee80211_hw *hw)
{
return ath5k_init(hw->priv);
@@ -2742,9 +2741,9 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
sc->vif = conf->vif;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- case IEEE80211_IF_TYPE_MNTR:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MONITOR:
sc->opmode = conf->type;
break;
default:
@@ -2815,7 +2814,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (conf->changed & IEEE80211_IFCC_BEACON &&
- vif->type == IEEE80211_IF_TYPE_IBSS) {
+ vif->type == NL80211_IFTYPE_ADHOC) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon) {
ret = -ENOMEM;
@@ -2827,7 +2826,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_unlock(&sc->lock);
- return ath5k_reset(hw);
+ return ath5k_reset_wake(sc);
unlock:
mutex_unlock(&sc->lock);
return ret;
@@ -2934,16 +2933,17 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
- if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
+ if (sc->opmode == NL80211_IFTYPE_MONITOR)
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
- if (sc->opmode != IEEE80211_IF_TYPE_STA)
+ if (sc->opmode != NL80211_IFTYPE_STATION)
rfilt |= AR5K_RX_FILTER_PROBEREQ;
- if (sc->opmode != IEEE80211_IF_TYPE_AP &&
+ if (sc->opmode != NL80211_IFTYPE_AP &&
+ sc->opmode != NL80211_IFTYPE_MESH_POINT &&
test_bit(ATH_STAT_PROMISC, sc->status))
rfilt |= AR5K_RX_FILTER_PROM;
- if (sc->opmode == IEEE80211_IF_TYPE_STA ||
- sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ if (sc->opmode == NL80211_IFTYPE_STATION ||
+ sc->opmode == NL80211_IFTYPE_ADHOC) {
rfilt |= AR5K_RX_FILTER_BEACON;
}
@@ -3048,7 +3048,7 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
* in IBSS mode we need to update the beacon timers too.
* this will also reset the TSF if we call it with 0
*/
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+ if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_beacon_update_timers(sc, 0);
else
ath5k_hw_reset_tsf(sc->ah);
@@ -3063,7 +3063,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
ath5k_debug_dump_skb(sc, skb, "BC ", 1);
- if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
+ if (sc->opmode != NL80211_IFTYPE_ADHOC) {
ret = -EIO;
goto end;
}
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
index 7ec2f377d5c..9d0b728928e 100644
--- a/drivers/net/wireless/ath5k/base.h
+++ b/drivers/net/wireless/ath5k/base.h
@@ -111,17 +111,13 @@ struct ath5k_softc {
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels[ATH_CHAN_MAX];
- struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS];
- enum ieee80211_if_types opmode;
+ struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+ enum nl80211_iftype opmode;
struct ath5k_hw *ah; /* Atheros HW */
struct ieee80211_supported_band *curband;
- u8 a_rates;
- u8 b_rates;
- u8 g_rates;
- u8 xr_rates;
-
#ifdef CONFIG_ATH5K_DEBUG
struct ath5k_dbg_info debug; /* debug info */
#endif /* CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath5k/caps.c
new file mode 100644
index 00000000000..150f5ed204a
--- /dev/null
+++ b/drivers/net/wireless/ath5k/caps.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/**************\
+* Capabilities *
+\**************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Fill the capabilities struct
+ * TODO: Merge this with EEPROM code when we are done with it
+ */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
+{
+ u16 ee_header;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Capabilities stored in the EEPROM */
+ ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Set radio capabilities
+ * (The AR5110 only supports the middle 5GHz band)
+ */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
+ ah->ah_capabilities.cap_range.range_2ghz_min = 0;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+ /* Set supported modes */
+ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
+ __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
+ } else {
+ /*
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+ * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX current ieee80211 implementation because the IEEE
+ * XXX channel mapping does not support negative channel
+ * XXX numbers (2312MHz is channel -19). Of course, this
+ * XXX doesn't matter because these channels are out of range
+ * XXX but some regulation domains like MKK (Japan) will
+ * XXX support frequencies somewhere around 4.8GHz.
+ */
+
+ /*
+ * Set radio capabilities
+ */
+
+ if (AR5K_EEPROM_HDR_11A(ee_header)) {
+ /* 4920 */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+ /* Set supported modes */
+ __set_bit(AR5K_MODE_11A,
+ ah->ah_capabilities.cap_mode);
+ __set_bit(AR5K_MODE_11A_TURBO,
+ ah->ah_capabilities.cap_mode);
+ if (ah->ah_version == AR5K_AR5212)
+ __set_bit(AR5K_MODE_11G_TURBO,
+ ah->ah_capabilities.cap_mode);
+ }
+
+ /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
+ * connected */
+ if (AR5K_EEPROM_HDR_11B(ee_header) ||
+ AR5K_EEPROM_HDR_11G(ee_header)) {
+ /* 2312 */
+ ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+ if (AR5K_EEPROM_HDR_11B(ee_header))
+ __set_bit(AR5K_MODE_11B,
+ ah->ah_capabilities.cap_mode);
+
+ if (AR5K_EEPROM_HDR_11G(ee_header))
+ __set_bit(AR5K_MODE_11G,
+ ah->ah_capabilities.cap_mode);
+ }
+ }
+
+ /* GPIO */
+ ah->ah_gpio_npins = AR5K_NUM_GPIO;
+
+ /* Set number of supported TX queues */
+ if (ah->ah_version == AR5K_AR5210)
+ ah->ah_capabilities.cap_queues.q_tx_num =
+ AR5K_NUM_TX_QUEUES_NOQCU;
+ else
+ ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
+
+ return 0;
+}
+
+/* Main function used by the driver part to check caps */
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
+ enum ath5k_capability_type cap_type,
+ u32 capability, u32 *result)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ switch (cap_type) {
+ case AR5K_CAP_NUM_TXQUEUES:
+ if (result) {
+ if (ah->ah_version == AR5K_AR5210)
+ *result = AR5K_NUM_TX_QUEUES_NOQCU;
+ else
+ *result = AR5K_NUM_TX_QUEUES;
+ goto yes;
+ }
+ case AR5K_CAP_VEOL:
+ goto yes;
+ case AR5K_CAP_COMPRESSION:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_BURST:
+ goto yes;
+ case AR5K_CAP_TPC:
+ goto yes;
+ case AR5K_CAP_BSSIDMASK:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_XR:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ default:
+ goto no;
+ }
+
+no:
+ return -EINVAL;
+yes:
+ return 0;
+}
+
+/*
+ * TODO: Following functions should be part of a new function
+ * set_capability
+ */
+
+int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
+ u16 assoc_id)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+ return 0;
+ }
+
+ return -EIO;
+}
+
+int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+ return 0;
+ }
+
+ return -EIO;
+}
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 6fa6c8e04ff..8f92d670f61 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -58,8 +58,8 @@
* THE POSSIBILITY OF SUCH DAMAGES.
*/
-#include "debug.h"
#include "base.h"
+#include "debug.h"
static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
@@ -525,7 +525,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
return;
printk(KERN_DEBUG "rx queue %x, link %p\n",
- ath5k_hw_get_rx_buf(ah), sc->rxlink);
+ ath5k_hw_get_rxdp(ah), sc->rxlink);
spin_lock_bh(&sc->rxbuflock);
list_for_each_entry(bf, &sc->rxbuf, list) {
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c
new file mode 100644
index 00000000000..dd1374052ba
--- /dev/null
+++ b/drivers/net/wireless/ath5k/desc.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/******************************\
+ Hardware Descriptor Functions
+\******************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * TX Descriptors
+ */
+
+/*
+ * Initialize the 2-word tx control descriptor on 5210/5211
+ */
+static int
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
+ unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
+ unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate, unsigned int rtscts_duration)
+{
+ u32 frame_type;
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (unlikely(tx_tries0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ if (unlikely(tx_rate0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ /* remove padding we might have added before */
+ frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
+
+ if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ if (type == AR5K_PKT_TYPE_BEACON)
+ pkt_len = roundup(pkt_len, 4);
+
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+ /*
+ * Verify and set header length
+ * XXX: I only found that on 5210 code, does it work on 5211 ?
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ return -EINVAL;
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ }
+
+ /*Diferences between 5210-5211*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (type) {
+ case AR5K_PKT_TYPE_BEACON:
+ case AR5K_PKT_TYPE_PROBE_RESP:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
+ case AR5K_PKT_TYPE_PIFS:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
+ default:
+ frame_type = type /*<< 2 ?*/;
+ }
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+ } else {
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ AR5K_REG_SM(antenna_mode,
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ }
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+ tx_ctl->tx_control_0 |=
+ AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(key_index,
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+
+ /*
+ * RTS/CTS Duration [5210 ?]
+ */
+ if ((ah->ah_version == AR5K_AR5210) &&
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+ tx_ctl->tx_control_1 |= rtscts_duration &
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+ return 0;
+}
+
+/*
+ * Initialize the 4-word tx control descriptor on 5212
+ */
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
+ enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
+ unsigned int tx_tries0, unsigned int key_index,
+ unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate,
+ unsigned int rtscts_duration)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ ATH5K_TRACE(ah->ah_sc);
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (unlikely(tx_tries0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ if (unlikely(tx_rate0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ /* remove padding we might have added before */
+ frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
+
+ if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ if (type == AR5K_PKT_TYPE_BEACON)
+ pkt_len = roundup(pkt_len, 4);
+
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(0, CTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+ tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
+ AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+
+ /*
+ * RTS/CTS
+ */
+ if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
+ if ((flags & AR5K_TXDESC_RTSENA) &&
+ (flags & AR5K_TXDESC_CTSENA))
+ return -EINVAL;
+ tx_ctl->tx_control_2 |= rtscts_duration &
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize a 4-word multi rate retry tx control descriptor on 5212
+ */
+static int
+ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
+ u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+
+ /*
+ * Rates can be 0 as long as the retry count is 0 too.
+ * A zero rate and nonzero retry count will put the HW into a mode where
+ * it continously sends noise on the channel, so it is important to
+ * avoid this.
+ */
+ if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
+ (tx_rate2 == 0 && tx_tries2 != 0) ||
+ (tx_rate3 == 0 && tx_tries3 != 0))) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (ah->ah_version == AR5K_AR5212) {
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+#define _XTX_TRIES(_n) \
+ if (tx_tries##_n) { \
+ tx_ctl->tx_control_2 |= \
+ AR5K_REG_SM(tx_tries##_n, \
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
+ tx_ctl->tx_control_3 |= \
+ AR5K_REG_SM(tx_rate##_n, \
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
+ }
+
+ _XTX_TRIES(1);
+ _XTX_TRIES(2);
+ _XTX_TRIES(3);
+
+#undef _XTX_TRIES
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* no mrr support for cards older than 5212 */
+static int
+ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
+ u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
+{
+ return 0;
+}
+
+/*
+ * Proccess the tx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+ tx_status = &desc->ud.ds_tx5210.tx_stat;
+
+ /* No frame has been send or error */
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ /*TODO: ts->ts_virtcol + test*/
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = 1;
+ ts->ts_status = 0;
+ ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ ts->ts_retry[0] = ts->ts_longretry;
+ ts->ts_final_idx = 0;
+
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess a tx status descriptor on 5212
+ */
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ tx_status = &desc->ud.ds_tx5212.tx_stat;
+
+ /* No frame has been send or error */
+ if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = (tx_status->tx_status_1 &
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+ ts->ts_status = 0;
+
+ ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
+
+ /* The longretry counter has the number of un-acked retries
+ * for the final rate. To get the total number of retries
+ * we have to add the retry counters for the other rates
+ * as well
+ */
+ ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+ switch (ts->ts_final_idx) {
+ case 3:
+ ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+
+ ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+ ts->ts_longretry += ts->ts_retry[2];
+ /* fall through */
+ case 2:
+ ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+
+ ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+ ts->ts_longretry += ts->ts_retry[1];
+ /* fall through */
+ case 1:
+ ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+
+ ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+ ts->ts_longretry += ts->ts_retry[0];
+ /* fall through */
+ case 0:
+ ts->ts_rate[0] = tx_ctl->tx_control_3 &
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ break;
+ }
+
+ /* TX error */
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * RX Descriptors
+ */
+
+/*
+ * Initialize an rx control descriptor
+ */
+static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags)
+{
+ struct ath5k_hw_rx_ctl *rx_ctl;
+
+ ATH5K_TRACE(ah->ah_sc);
+ rx_ctl = &desc->ud.ds_rx.rx_ctl;
+
+ /*
+ * Clear the descriptor
+ * If we don't clean the status descriptor,
+ * while scanning we get too many results,
+ * most of them virtual, after some secs
+ * of scanning system hangs. M.F.
+ */
+ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+
+ /* Setup descriptor */
+ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+ if (unlikely(rx_ctl->rx_control_1 != size))
+ return -EINVAL;
+
+ if (flags & AR5K_RXDESC_INTREQ)
+ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* No frame received / not ready */
+ if (unlikely(!(rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_DONE)))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ rs->rs_more = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_MORE;
+ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+
+ /*
+ * Key table status
+ */
+ if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
+ else
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
+ rs->rs_status |= AR5K_RXERR_FIFO;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5212
+ */
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+ struct ath5k_hw_rx_error *rx_err;
+
+ ATH5K_TRACE(ah->ah_sc);
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* Overlay on error */
+ rx_err = &desc->ud.ds_rx.u.rx_err;
+
+ /* No frame received / not ready */
+ if (unlikely(!(rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_DONE)))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ rs->rs_more = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_MORE;
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+
+ /*
+ * Key table status
+ */
+ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
+ else
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+ rs->rs_status |= AR5K_RXERR_MIC;
+ }
+
+ return 0;
+}
+
+/*
+ * Init function pointers inside ath5k_hw struct
+ */
+int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
+{
+
+ if (ah->ah_version != AR5K_AR5210 &&
+ ah->ah_version != AR5K_AR5211 &&
+ ah->ah_version != AR5K_AR5212)
+ return -ENOTSUPP;
+
+ /* XXX: What is this magic value and where is it used ? */
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
+ else if (ah->ah_version == AR5K_AR5211)
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
+ ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
+ } else {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
+ ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
+ }
+
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+ else if (ah->ah_version <= AR5K_AR5211)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/desc.h
index 64fca8dcb38..56158c804e3 100644
--- a/drivers/net/wireless/ath5k/hw.h
+++ b/drivers/net/wireless/ath5k/desc.h
@@ -1,8 +1,6 @@
/*
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
- * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,159 +13,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
*/
-#include <linux/delay.h>
-
-/*
- * Gain settings
- */
-
-enum ath5k_rfgain {
- AR5K_RFGAIN_INACTIVE = 0,
- AR5K_RFGAIN_READ_REQUESTED,
- AR5K_RFGAIN_NEED_CHANGE,
-};
-
-#define AR5K_GAIN_CRN_FIX_BITS_5111 4
-#define AR5K_GAIN_CRN_FIX_BITS_5112 7
-#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
-#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
-#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
-#define AR5K_GAIN_CCK_PROBE_CORR 5
-#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
-#define AR5K_GAIN_STEP_COUNT 10
-#define AR5K_GAIN_PARAM_TX_CLIP 0
-#define AR5K_GAIN_PARAM_PD_90 1
-#define AR5K_GAIN_PARAM_PD_84 2
-#define AR5K_GAIN_PARAM_GAIN_SEL 3
-#define AR5K_GAIN_PARAM_MIX_ORN 0
-#define AR5K_GAIN_PARAM_PD_138 1
-#define AR5K_GAIN_PARAM_PD_137 2
-#define AR5K_GAIN_PARAM_PD_136 3
-#define AR5K_GAIN_PARAM_PD_132 4
-#define AR5K_GAIN_PARAM_PD_131 5
-#define AR5K_GAIN_PARAM_PD_130 6
-#define AR5K_GAIN_CHECK_ADJUST(_g) \
- ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
-
-struct ath5k_gain_opt_step {
- s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
- s32 gos_gain;
-};
-
-struct ath5k_gain {
- u32 g_step_idx;
- u32 g_current;
- u32 g_target;
- u32 g_low;
- u32 g_high;
- u32 g_f_corr;
- u32 g_active;
- const struct ath5k_gain_opt_step *g_step;
-};
-
-
-/*
- * HW SPECIFIC STRUCTS
- */
-
-/* Some EEPROM defines */
-#define AR5K_EEPROM_EEP_SCALE 100
-#define AR5K_EEPROM_EEP_DELTA 10
-#define AR5K_EEPROM_N_MODES 3
-#define AR5K_EEPROM_N_5GHZ_CHAN 10
-#define AR5K_EEPROM_N_2GHZ_CHAN 3
-#define AR5K_EEPROM_MAX_CHAN 10
-#define AR5K_EEPROM_N_PCDAC 11
-#define AR5K_EEPROM_N_TEST_FREQ 8
-#define AR5K_EEPROM_N_EDGES 8
-#define AR5K_EEPROM_N_INTERCEPTS 11
-#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
-#define AR5K_EEPROM_PCDAC_M 0x3f
-#define AR5K_EEPROM_PCDAC_START 1
-#define AR5K_EEPROM_PCDAC_STOP 63
-#define AR5K_EEPROM_PCDAC_STEP 1
-#define AR5K_EEPROM_NON_EDGE_M 0x40
-#define AR5K_EEPROM_CHANNEL_POWER 8
-#define AR5K_EEPROM_N_OBDB 4
-#define AR5K_EEPROM_OBDB_DIS 0xffff
-#define AR5K_EEPROM_CHANNEL_DIS 0xff
-#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
-#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
-#define AR5K_EEPROM_MAX_CTLS 32
-#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
-#define AR5K_EEPROM_N_XPD0_POINTS 4
-#define AR5K_EEPROM_N_XPD3_POINTS 3
-#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
-#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
-#define AR5K_EEPROM_POWER_M 0x3f
-#define AR5K_EEPROM_POWER_MIN 0
-#define AR5K_EEPROM_POWER_MAX 3150
-#define AR5K_EEPROM_POWER_STEP 50
-#define AR5K_EEPROM_POWER_TABLE_SIZE 64
-#define AR5K_EEPROM_N_POWER_LOC_11B 4
-#define AR5K_EEPROM_N_POWER_LOC_11G 6
-#define AR5K_EEPROM_I_GAIN 10
-#define AR5K_EEPROM_CCK_OFDM_DELTA 15
-#define AR5K_EEPROM_N_IQ_CAL 2
-
-/* Struct to hold EEPROM calibration data */
-struct ath5k_eeprom_info {
- u16 ee_magic;
- u16 ee_protect;
- u16 ee_regdomain;
- u16 ee_version;
- u16 ee_header;
- u16 ee_ant_gain;
- u16 ee_misc0;
- u16 ee_misc1;
- u16 ee_cck_ofdm_gain_delta;
- u16 ee_cck_ofdm_power_delta;
- u16 ee_scaled_cck_delta;
-
- /* Used for tx thermal adjustment (eeprom_init, rfregs) */
- u16 ee_tx_clip;
- u16 ee_pwd_84;
- u16 ee_pwd_90;
- u16 ee_gain_select;
-
- /* RF Calibration settings (reset, rfregs) */
- u16 ee_i_cal[AR5K_EEPROM_N_MODES];
- u16 ee_q_cal[AR5K_EEPROM_N_MODES];
- u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
- u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
- u16 ee_xr_power[AR5K_EEPROM_N_MODES];
- u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
- u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
- u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
- u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
- u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
- u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
- u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
- u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
- u16 ee_thr_62[AR5K_EEPROM_N_MODES];
- u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
- u16 ee_xpd[AR5K_EEPROM_N_MODES];
- u16 ee_x_gain[AR5K_EEPROM_N_MODES];
- u16 ee_i_gain[AR5K_EEPROM_N_MODES];
- u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
-
- /* Unused */
- u16 ee_false_detect[AR5K_EEPROM_N_MODES];
- u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
- u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
-
- /* Conformance test limits (Unused) */
- u16 ee_ctls;
- u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
-
- /* Noise Floor Calibration settings */
- s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
- s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
- s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
-};
-
/*
* Internal RX/TX descriptor structures
* (rX: reserved fields possibily used by future versions of the ar5k chipset)
@@ -178,14 +26,15 @@ struct ath5k_eeprom_info {
*/
struct ath5k_hw_rx_ctl {
u32 rx_control_0; /* RX control word 0 */
+ u32 rx_control_1; /* RX control word 1 */
+} __packed;
+/* RX control word 0 field/sflags */
#define AR5K_DESC_RX_CTL0 0x00000000
- u32 rx_control_1; /* RX control word 1 */
-
+/* RX control word 1 fields/flags */
#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
-} __packed;
/*
* common hardware RX status descriptor
@@ -197,6 +46,7 @@ struct ath5k_hw_rx_status {
} __packed;
/* 5210/5211 */
+/* RX status word 0 fields/flags */
#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
@@ -205,6 +55,8 @@ struct ath5k_hw_rx_status {
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
+
+/* RX status word 1 fields/flags */
#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
@@ -220,6 +72,7 @@ struct ath5k_hw_rx_status {
#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
/* 5212 */
+/* RX status word 0 fields/flags */
#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
@@ -229,6 +82,8 @@ struct ath5k_hw_rx_status {
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
+
+/* RX status word 1 fields/flags */
#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
@@ -246,16 +101,18 @@ struct ath5k_hw_rx_status {
* common hardware RX error descriptor
*/
struct ath5k_hw_rx_error {
- u32 rx_error_0; /* RX error word 0 */
+ u32 rx_error_0; /* RX status word 0 */
+ u32 rx_error_1; /* RX status word 1 */
+} __packed;
+/* RX error word 0 fields/flags */
#define AR5K_RX_DESC_ERROR0 0x00000000
- u32 rx_error_1; /* RX error word 1 */
-
+/* RX error word 1 fields/flags */
#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
-} __packed;
+/* PHY Error codes */
#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
@@ -270,7 +127,10 @@ struct ath5k_hw_rx_error {
*/
struct ath5k_hw_2w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */
+ u32 tx_control_1; /* TX control word 1 */
+} __packed;
+/* TX control word 0 fields/flags */
#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
@@ -284,29 +144,34 @@ struct ath5k_hw_2w_tx_ctl {
#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
-#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT (ah->ah_version == AR5K_AR5210 ? \
- AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
- AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+
#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
- u32 tx_control_1; /* TX control word 1 */
-
+/* TX control word 1 fields/flags */
#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
-#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX (ah->ah_version == AR5K_AR5210 ? \
- AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
- AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+
#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
-} __packed;
+/* Frame types */
#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
@@ -378,7 +243,10 @@ struct ath5k_hw_4w_tx_ctl {
*/
struct ath5k_hw_tx_status {
u32 tx_status_0; /* TX status word 0 */
+ u32 tx_status_1; /* TX status word 1 */
+} __packed;
+/* TX status word 0 fields/flags */
#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
@@ -400,8 +268,7 @@ struct ath5k_hw_tx_status {
#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
- u32 tx_status_1; /* TX status word 1 */
-
+/* TX status word 1 fields/flags */
#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
@@ -411,8 +278,6 @@ struct ath5k_hw_tx_status {
#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
-} __packed;
-
/*
* 5210/5211 hardware TX descriptor
@@ -441,176 +306,27 @@ struct ath5k_hw_all_rx_desc {
} u;
} __packed;
-
/*
- * AR5K REGISTER ACCESS
+ * Atheros hardware descriptor
+ * This is read and written to by the hardware
*/
+struct ath5k_desc {
+ u32 ds_link; /* physical address of the next descriptor */
+ u32 ds_data; /* physical address of data buffer (skb) */
-/*Swap RX/TX Descriptor for big endian archs*/
-#if defined(__BIG_ENDIAN)
-#define AR5K_INIT_CFG ( \
- AR5K_CFG_SWTD | AR5K_CFG_SWRD \
-)
-#else
-#define AR5K_INIT_CFG 0x00000000
-#endif
-
-/*#define AR5K_REG_READ(_reg) ath5k_hw_reg_read(ah, _reg)
-
-#define AR5K_REG_WRITE(_reg, _val) ath5k_hw_reg_write(ah, _val, _reg)*/
-
-#define AR5K_REG_SM(_val, _flags) \
- (((_val) << _flags##_S) & (_flags))
-
-#define AR5K_REG_MS(_val, _flags) \
- (((_val) & (_flags)) >> _flags##_S)
-
-/* Some registers can hold multiple values of interest. For this
- * reason when we want to write to these registers we must first
- * retrieve the values which we do not want to clear (lets call this
- * old_data) and then set the register with this and our new_value:
- * ( old_data | new_value) */
-#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
- ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
- (((_val) << _flags##_S) & (_flags)), _reg)
-
-#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
- ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
- (_mask)) | (_flags), _reg)
-
-#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
- ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
-
-#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
- ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
-
-#define AR5K_PHY_WRITE(ah, _reg, _val) \
- ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
-
-#define AR5K_PHY_READ(ah, _reg) \
- ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
-
-#define AR5K_REG_WAIT(_i) do { \
- if (_i % 64) \
- udelay(1); \
-} while (0)
-
-#define AR5K_EEPROM_READ(_o, _v) do { \
- if ((ret = ath5k_hw_eeprom_read(ah, (_o), &(_v))) != 0) \
- return (ret); \
-} while (0)
-
-#define AR5K_EEPROM_READ_HDR(_o, _v) \
- AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
-
-/* Read status of selected queue */
-#define AR5K_REG_READ_Q(ah, _reg, _queue) \
- (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
-
-#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
- ath5k_hw_reg_write(ah, (1 << _queue), _reg)
-
-#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
- _reg |= 1 << _queue; \
-} while (0)
-
-#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
- _reg &= ~(1 << _queue); \
-} while (0)
-
-#define AR5K_LOW_ID(_a)( \
-(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
-)
-
-#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
-
-/*
- * Initial register values
- */
-
-/*
- * Common initial register values
- */
-#define AR5K_INIT_MODE CHANNEL_B
-
-#define AR5K_INIT_TX_LATENCY 502
-#define AR5K_INIT_USEC 39
-#define AR5K_INIT_USEC_TURBO 79
-#define AR5K_INIT_USEC_32 31
-#define AR5K_INIT_CARR_SENSE_EN 1
-#define AR5K_INIT_PROG_IFS 920
-#define AR5K_INIT_PROG_IFS_TURBO 960
-#define AR5K_INIT_EIFS 3440
-#define AR5K_INIT_EIFS_TURBO 6880
-#define AR5K_INIT_SLOT_TIME 396
-#define AR5K_INIT_SLOT_TIME_TURBO 480
-#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
-#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
-#define AR5K_INIT_SIFS 560
-#define AR5K_INIT_SIFS_TURBO 480
-#define AR5K_INIT_SH_RETRY 10
-#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
-#define AR5K_INIT_SSH_RETRY 32
-#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
-#define AR5K_INIT_TX_RETRY 10
-#define AR5K_INIT_TOPS 8
-#define AR5K_INIT_RXNOFRM 8
-#define AR5K_INIT_RPGTO 0
-#define AR5K_INIT_TXNOFRM 0
-#define AR5K_INIT_BEACON_PERIOD 65535
-#define AR5K_INIT_TIM_OFFSET 0
-#define AR5K_INIT_BEACON_EN 0
-#define AR5K_INIT_RESET_TSF 0
-
-#define AR5K_INIT_TRANSMIT_LATENCY ( \
- (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
- (AR5K_INIT_USEC) \
-)
-#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
- (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
- (AR5K_INIT_USEC_TURBO) \
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
- (AR5K_INIT_PROG_IFS) \
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
- (AR5K_INIT_PROG_IFS_TURBO) \
-)
-#define AR5K_INIT_BEACON_CONTROL ( \
- (AR5K_INIT_RESET_TSF << 24) | (AR5K_INIT_BEACON_EN << 23) | \
- (AR5K_INIT_TIM_OFFSET << 16) | (AR5K_INIT_BEACON_PERIOD) \
-)
-
-/*
- * Non-common initial register values which have to be loaded into the
- * card at boot time and after each reset.
- */
-
-/* Register dumps are done per operation mode */
-#define AR5K_INI_RFGAIN_5GHZ 0
-#define AR5K_INI_RFGAIN_2GHZ 1
-
-#define AR5K_INI_VAL_11A 0
-#define AR5K_INI_VAL_11A_TURBO 1
-#define AR5K_INI_VAL_11B 2
-#define AR5K_INI_VAL_11G 3
-#define AR5K_INI_VAL_11G_TURBO 4
-#define AR5K_INI_VAL_XR 0
-#define AR5K_INI_VAL_MAX 5
-
-#define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
-#define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+ union {
+ struct ath5k_hw_5210_tx_desc ds_tx5210;
+ struct ath5k_hw_5212_tx_desc ds_tx5212;
+ struct ath5k_hw_all_rx_desc ds_rx;
+ } ud;
+} __packed;
-static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
-{
- u32 retval = 0, bit, i;
+#define AR5K_RXDESC_INTREQ 0x0020
- for (i = 0; i < bits; i++) {
- bit = (val >> i) & 1;
- retval = (retval << 1) | bit;
- }
+#define AR5K_TXDESC_CLRDMASK 0x0001
+#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
+#define AR5K_TXDESC_RTSENA 0x0004
+#define AR5K_TXDESC_CTSENA 0x0008
+#define AR5K_TXDESC_INTREQ 0x0010
+#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
- return retval;
-}
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c
new file mode 100644
index 00000000000..7adceb2c7fa
--- /dev/null
+++ b/drivers/net/wireless/ath5k/dma.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* DMA and interrupt masking functions *
+\*************************************/
+
+/*
+ * dma.c - DMA and interrupt masking functions
+ *
+ * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
+ * handle queue setup for 5210 chipset (rest are handled on qcu.c).
+ * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * status registers (ISR).
+ *
+ * TODO: Handle SISR on 5211+ and introduce a function to return the queue
+ * number that resulted the interrupt.
+ */
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*********\
+* Receive *
+\*********/
+
+/**
+ * ath5k_hw_start_rx_dma - Start DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+}
+
+/**
+ * ath5k_hw_stop_rx_dma - Stop DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+{
+ unsigned int i;
+
+ ATH5K_TRACE(ah->ah_sc);
+ ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
+
+ /*
+ * It may take some time to disable the DMA receive unit
+ */
+ for (i = 1000; i > 0 &&
+ (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
+ i--)
+ udelay(10);
+
+ return i ? 0 : -EBUSY;
+}
+
+/**
+ * ath5k_hw_get_rxdp - Get RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * XXX: Is RXDP read and clear ?
+ */
+u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_RXDP);
+}
+
+/**
+ * ath5k_hw_set_rxdp - Set RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ * @phys_addr: RX descriptor address
+ *
+ * XXX: Should we check if rx is enabled before setting rxdp ?
+ */
+void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+}
+
+
+/**********\
+* Transmit *
+\**********/
+
+/**
+ * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Start DMA transmit for a specific queue and since 5210 doesn't have
+ * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
+ * queue for normal data and one queue for beacons). For queue setup
+ * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
+ * of range or if queue is already disabled.
+ *
+ * NOTE: Must be called after setting up tx control descriptor for that
+ * queue (see below).
+ */
+int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 tx_queue;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /*
+ * Set the queue by type on 5210
+ */
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+ AR5K_BSR);
+ break;
+ case AR5K_TX_QUEUE_CAB:
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
+ AR5K_BCR_BDMAE, AR5K_BSR);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Start queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /* Return if queue is disabled */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
+ return -EIO;
+
+ /* Start queue */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
+ }
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Stop DMA transmit on a specific hw queue and drain queue so we don't
+ * have any pending frames. Returns -EBUSY if we still have pending frames,
+ * -EINVAL if queue number is out of range.
+ *
+ */
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ unsigned int i = 40;
+ u32 tx_queue, pending;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /*
+ * Set by queue type
+ */
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ /* XXX Fix me... */
+ tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, 0, AR5K_BSR);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Stop queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /*
+ * Schedule TX disable and wait until queue is empty
+ */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
+
+ /*Check for pending frames*/
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ /* For 2413+ order PCU to drop packets using
+ * QUIET mechanism */
+ if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
+ pending){
+ /* Set periodicity and duration */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
+ AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
+ AR5K_QUIET_CTL2);
+
+ /* Enable quiet period for current TSF */
+ ath5k_hw_reg_write(ah,
+ AR5K_QUIET_CTL1_QT_EN |
+ AR5K_REG_SM(ath5k_hw_reg_read(ah,
+ AR5K_TSF_L32_5211) >> 10,
+ AR5K_QUIET_CTL1_NEXT_QT_TSF),
+ AR5K_QUIET_CTL1);
+
+ /* Force channel idle high */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+
+ /* Wait a while and disable mechanism */
+ udelay(200);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
+ AR5K_QUIET_CTL1_QT_EN);
+
+ /* Re-check for pending frames */
+ i = 40;
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+ }
+
+ /* Clear register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
+ if (pending)
+ return -EBUSY;
+ }
+
+ /* TODO: Check for success on 5210 else return error */
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Get TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and use tx queue type since we only have 2 queues.
+ * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just read the corresponding TXDP register.
+ *
+ * XXX: Is TXDP read and clear ?
+ */
+u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
+{
+ u16 tx_reg;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /*
+ * Get the transmit queue descriptor pointer from the selected queue
+ */
+ /*5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_reg = AR5K_NOQCU_TXDP0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ tx_reg = AR5K_NOQCU_TXDP1;
+ break;
+ default:
+ return 0xffffffff;
+ }
+ } else {
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ return ath5k_hw_reg_read(ah, tx_reg);
+}
+
+/**
+ * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Set TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and we use tx queue type since we only have 2 queues
+ * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just set the corresponding TXDP register.
+ * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
+ * active.
+ */
+int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
+{
+ u16 tx_reg;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /*
+ * Set the transmit queue descriptor pointer register by type
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_reg = AR5K_NOQCU_TXDP0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ tx_reg = AR5K_NOQCU_TXDP1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ /*
+ * Set the transmit queue descriptor pointer for
+ * the selected queue on QCU for 5211+
+ * (this won't work if the queue is still active)
+ */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ return -EIO;
+
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ /* Set descriptor pointer */
+ ath5k_hw_reg_write(ah, phys_addr, tx_reg);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_update_tx_triglevel - Update tx trigger level
+ *
+ * @ah: The &struct ath5k_hw
+ * @increase: Flag to force increase of trigger level
+ *
+ * This function increases/decreases the tx trigger level for the tx fifo
+ * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
+ * the buffer and transmits it's data. Lowering this results sending small
+ * frames more quickly but can lead to tx underruns, raising it a lot can
+ * result other problems (i think bmiss is related). Right now we start with
+ * the lowest possible (64Bytes) and if we get tx underrun we increase it using
+ * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ *
+ * XXX: Link this with tx DMA size ?
+ * XXX: Use it to save interrupts ?
+ * TODO: Needs testing, i think it's related to bmiss...
+ */
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
+{
+ u32 trigger_level, imr;
+ int ret = -EIO;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Disable interrupts by setting the mask
+ */
+ imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
+
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ AR5K_TXCFG_TXFULL);
+
+ if (!increase) {
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ goto done;
+ } else
+ trigger_level +=
+ ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+ /*
+ * Update trigger level on success
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_TXFULL, trigger_level);
+
+ ret = 0;
+
+done:
+ /*
+ * Restore interrupt mask
+ */
+ ath5k_hw_set_imr(ah, imr);
+
+ return ret;
+}
+
+/*******************\
+* Interrupt masking *
+\*******************/
+
+/**
+ * ath5k_hw_is_intr_pending - Check if we have pending interrupts
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Check if we have pending interrupts to process. Returns 1 if we
+ * have pending interrupts and 0 if we haven't.
+ */
+bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
+}
+
+/**
+ * ath5k_hw_get_isr - Get interrupt status
+ *
+ * @ah: The @struct ath5k_hw
+ * @interrupt_mask: Driver's interrupt mask used to filter out
+ * interrupts in sw.
+ *
+ * This function is used inside our interrupt handler to determine the reason
+ * for the interrupt by reading Primary Interrupt Status Register. Returns an
+ * abstract interrupt status mask which is mostly ISR with some uncommon bits
+ * being mapped on some standard non hw-specific positions
+ * (check out &ath5k_int).
+ *
+ * NOTE: We use read-and-clear register, so after this function is called ISR
+ * is zeroed.
+ *
+ * XXX: Why filter interrupts in sw with interrupt_mask ? No benefit at all
+ * plus it can be misleading (one might thing that we save interrupts this way)
+ */
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
+{
+ u32 data;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Read interrupt status from the Interrupt Status register
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_ISR);
+ if (unlikely(data == AR5K_INT_NOCARD)) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ } else {
+ /*
+ * Read interrupt status from the Read-And-Clear
+ * shadow register.
+ * Note: PISR/SISR Not available on 5210
+ */
+ data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+ }
+
+ /*
+ * Get abstract interrupt mask (driver-compatible)
+ */
+ *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
+
+ if (unlikely(data == AR5K_INT_NOCARD))
+ return -ENODEV;
+
+ if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
+ *interrupt_mask |= AR5K_INT_RX;
+
+ if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
+ | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
+ *interrupt_mask |= AR5K_INT_TX;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*HIU = Host Interface Unit (PCI etc)*/
+ if (unlikely(data & (AR5K_ISR_HIUERR)))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*Beacon Not Ready*/
+ if (unlikely(data & (AR5K_ISR_BNR)))
+ *interrupt_mask |= AR5K_INT_BNR;
+ }
+
+ /*
+ * XXX: BMISS interrupts may occur after association.
+ * I found this on 5210 code but it needs testing. If this is
+ * true we should disable them before assoc and re-enable them
+ * after a successfull assoc + some jiffies.
+ */
+#if 0
+ interrupt_mask &= ~AR5K_INT_BMISS;
+#endif
+
+ /*
+ * In case we didn't handle anything,
+ * print the register value.
+ */
+ if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
+ ATH5K_PRINTF("0x%08x\n", data);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_imr - Set interrupt mask
+ *
+ * @ah: The &struct ath5k_hw
+ * @new_mask: The new interrupt mask to be set
+ *
+ * Set the interrupt mask in hw to save interrupts. We do that by mapping
+ * ath5k_int bits to hw-specific bits to remove abstraction and writing
+ * Interrupt Mask Register.
+ */
+enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
+{
+ enum ath5k_int old_mask, int_mask;
+
+ /*
+ * Disable card interrupts to prevent any race conditions
+ * (they will be re-enabled afterwards).
+ */
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+
+ old_mask = ah->ah_imr;
+
+ /*
+ * Add additional, chipset-dependent interrupt mask flags
+ * and write them to the IMR (interrupt mask register).
+ */
+ int_mask = new_mask & AR5K_INT_COMMON;
+
+ if (new_mask & AR5K_INT_RX)
+ int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
+ AR5K_IMR_RXDESC;
+
+ if (new_mask & AR5K_INT_TX)
+ int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
+ AR5K_IMR_TXURN;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ if (new_mask & AR5K_INT_FATAL) {
+ int_mask |= AR5K_IMR_HIUERR;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
+ AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
+ }
+ }
+
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+
+ /* Store new interrupt mask */
+ ah->ah_imr = new_mask;
+
+ /* ..re-enable interrupts */
+ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+
+ return old_mask;
+}
+
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
new file mode 100644
index 00000000000..a883839b6a9
--- /dev/null
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* EEPROM access functions and helpers *
+\*************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Read from eeprom
+ */
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+{
+ u32 status, timeout;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Initialize EEPROM access
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_READ);
+ }
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
+ if (status & AR5K_EEPROM_STAT_RDERR)
+ return -EIO;
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+ 0xffff);
+ return 0;
+ }
+ udelay(15);
+ }
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Translate binary channel representation in EEPROM to frequency
+ */
+static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
+ unsigned int mode)
+{
+ u16 val;
+
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
+ return bin;
+
+ if (mode == AR5K_EEPROM_MODE_11A) {
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = (5 * bin) + 4800;
+ else
+ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
+ (bin * 10) + 5100;
+ } else {
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = bin + 2300;
+ else
+ val = bin + 2400;
+ }
+
+ return val;
+}
+
+/*
+ * Read antenna infos from eeprom
+ */
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret, i = 0;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
+ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ /* Get antenna modes */
+ ah->ah_antenna[mode][0] =
+ (ee->ee_ant_control[mode][0] << 4) | 0x1;
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
+ (ee->ee_ant_control[mode][3] << 12) |
+ (ee->ee_ant_control[mode][4] << 18) |
+ (ee->ee_ant_control[mode][5] << 24);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
+ (ee->ee_ant_control[mode][8] << 12) |
+ (ee->ee_ant_control[mode][9] << 18) |
+ (ee->ee_ant_control[mode][10] << 24);
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read supported modes from eeprom
+ */
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+ ee->ee_thr_62[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
+
+ if ((val & 0xff) & 0x80)
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+ else
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_noise_floor_thr[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
+ ee->ee_xpd[mode] = val & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ ee->ee_xr_power[mode] = val & 0x3f;
+ else {
+ ee->ee_ob[mode][0] = val & 0x7;
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+ } else {
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+ if (mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+ mode == AR5K_EEPROM_MODE_11A) {
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
+ mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+int ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ unsigned int mode, i;
+ int ret;
+ u32 offset;
+ u16 val;
+
+ /* Initial TX thermal adjustment values */
+ ee->ee_tx_clip = 4;
+ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
+ ee->ee_gain_select = 1;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return 0;
+
+#ifdef notyet
+ /*
+ * Validate the checksum of the EEPROM date. There are some
+ * devices with invalid EEPROMs.
+ */
+ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
+ cksum ^= val;
+ }
+ if (cksum != AR5K_EEPROM_INFO_CKSUM) {
+ ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+ return -EIO;
+ }
+#endif
+
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+ ee_ant_gain);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ /*
+ * Get conformance test limit values
+ */
+ offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
+
+ for (i = 0; i < ee->ee_ctls; i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ /*
+ * Get values for 802.11a (5GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11A;
+
+ ee->ee_turbo_max_power[mode] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ }
+
+ /*
+ * Get values for 802.11b (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11B;
+ offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ /*
+ * Get values for 802.11g (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11G;
+ offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ }
+
+ /*
+ * Read 5GHz EEPROM channels
+ */
+
+ return 0;
+}
+
+/*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN];
+ u32 total, offset;
+ u16 data;
+ int octet, ret;
+
+ memset(mac, 0, ETH_ALEN);
+ memset(mac_d, 0, ETH_ALEN);
+
+ ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
+ if (ret)
+ return ret;
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ ret = ath5k_hw_eeprom_read(ah, offset, &data);
+ if (ret)
+ return ret;
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h
new file mode 100644
index 00000000000..a468ecfbb18
--- /dev/null
+++ b/drivers/net/wireless/ath5k/eeprom.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
+ */
+#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
+#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
+#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
+#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
+
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
+#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO_CKSUM 0xffff
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
+#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
+#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_3 0x4003
+#define AR5K_EEPROM_VERSION_4_4 0x4004
+#define AR5K_EEPROM_VERSION_4_5 0x4005
+#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
+#define AR5K_EEPROM_VERSION_4_7 0x4007
+
+#define AR5K_EEPROM_MODE_11A 0
+#define AR5K_EEPROM_MODE_11B 1
+#define AR5K_EEPROM_MODE_11G 2
+
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
+
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
+
+/* calibration settings */
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
+
+/* [3.1 - 3.3] */
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 0x00c4
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+#define AR5K_EEPROM_MISC1 0x00c5
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE 100
+#define AR5K_EEPROM_EEP_DELTA 10
+#define AR5K_EEPROM_N_MODES 3
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_TEST_FREQ 8
+#define AR5K_EEPROM_N_EDGES 8
+#define AR5K_EEPROM_N_INTERCEPTS 11
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M 0x3f
+#define AR5K_EEPROM_PCDAC_START 1
+#define AR5K_EEPROM_PCDAC_STOP 63
+#define AR5K_EEPROM_PCDAC_STEP 1
+#define AR5K_EEPROM_NON_EDGE_M 0x40
+#define AR5K_EEPROM_CHANNEL_POWER 8
+#define AR5K_EEPROM_N_OBDB 4
+#define AR5K_EEPROM_OBDB_DIS 0xffff
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS 32
+#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
+#define AR5K_EEPROM_N_XPD0_POINTS 4
+#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
+#define AR5K_EEPROM_POWER_M 0x3f
+#define AR5K_EEPROM_POWER_MIN 0
+#define AR5K_EEPROM_POWER_MAX 3150
+#define AR5K_EEPROM_POWER_STEP 50
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
+#define AR5K_EEPROM_I_GAIN 10
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
+#define AR5K_EEPROM_N_IQ_CAL 2
+
+#define AR5K_EEPROM_READ(_o, _v) do { \
+ ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \
+ if (ret) \
+ return ret; \
+} while (0)
+
+#define AR5K_EEPROM_READ_HDR(_o, _v) \
+ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
+
+/* Struct to hold EEPROM calibration data */
+struct ath5k_eeprom_info {
+ u16 ee_magic;
+ u16 ee_protect;
+ u16 ee_regdomain;
+ u16 ee_version;
+ u16 ee_header;
+ u16 ee_ant_gain;
+ u16 ee_misc0;
+ u16 ee_misc1;
+ u16 ee_cck_ofdm_gain_delta;
+ u16 ee_cck_ofdm_power_delta;
+ u16 ee_scaled_cck_delta;
+
+ /* Used for tx thermal adjustment (eeprom_init, rfregs) */
+ u16 ee_tx_clip;
+ u16 ee_pwd_84;
+ u16 ee_pwd_90;
+ u16 ee_gain_select;
+
+ /* RF Calibration settings (reset, rfregs) */
+ u16 ee_i_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_q_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
+ u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+ u16 ee_xr_power[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+ u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_thr_62[AR5K_EEPROM_N_MODES];
+ u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_xpd[AR5K_EEPROM_N_MODES];
+ u16 ee_x_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_i_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+
+ /* Unused */
+ u16 ee_false_detect[AR5K_EEPROM_N_MODES];
+ u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
+ u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
+
+ /* Conformance test limits (Unused) */
+ u16 ee_ctls;
+ u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
+
+ /* Noise Floor Calibration settings */
+ s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+};
diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath5k/gpio.c
new file mode 100644
index 00000000000..b77205adc18
--- /dev/null
+++ b/drivers/net/wireless/ath5k/gpio.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/****************\
+ GPIO Functions
+\****************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Set led state
+ */
+void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
+{
+ u32 led;
+ /*5210 has different led mode handling*/
+ u32 led_5210;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*Reset led status*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
+
+ /*
+ * Some blinking values, define at your wish
+ */
+ switch (state) {
+ case AR5K_LED_SCAN:
+ case AR5K_LED_AUTH:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
+ led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
+ break;
+
+ case AR5K_LED_INIT:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
+ led_5210 = AR5K_PCICFG_LED_PEND;
+ break;
+
+ case AR5K_LED_ASSOC:
+ case AR5K_LED_RUN:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
+ led_5210 = AR5K_PCICFG_LED_ASSOC;
+ break;
+
+ default:
+ led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
+ led_5210 = AR5K_PCICFG_LED_PEND;
+ break;
+ }
+
+ /*Write new status to the register*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
+}
+
+/*
+ * Set GPIO inputs
+ */
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Set GPIO outputs
+ */
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Get GPIO state
+ */
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return 0xffffffff;
+
+ /* GPIO input magic */
+ return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
+ 0x1;
+}
+
+/*
+ * Set GPIO state
+ */
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
+{
+ u32 data;
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ /* GPIO output magic */
+ data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ data &= ~(1 << gpio);
+ data |= (val & 1) << gpio;
+
+ ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
+
+ return 0;
+}
+
+/*
+ * Initialize the GPIO interrupt (RFKill switch)
+ */
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ u32 interrupt_level)
+{
+ u32 data;
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return;
+
+ /*
+ * Set the GPIO interrupt
+ */
+ data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
+ ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
+ AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
+ (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
+
+ ath5k_hw_reg_write(ah, interrupt_level ? data :
+ (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
+
+ ah->ah_imr |= AR5K_IMR_GPIO;
+
+ /* Enable GPIO interrupts */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
+}
+
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
deleted file mode 100644
index ad1a5b422c8..00000000000
--- a/drivers/net/wireless/ath5k/hw.c
+++ /dev/null
@@ -1,4529 +0,0 @@
-/*
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
- * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
- * Copyright (c) 2007 Pavel Roskin <proski@gnu.org>
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * HW related functions for Atheros Wireless LAN devices.
- */
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "reg.h"
-#include "base.h"
-#include "debug.h"
-
-/* Rate tables */
-static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A;
-static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B;
-static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G;
-static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO;
-static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR;
-
-/* Prototypes */
-static int ath5k_hw_nic_reset(struct ath5k_hw *, u32);
-static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool);
-static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
- unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int);
-static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int);
-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
- struct ath5k_tx_status *);
-static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
- unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int);
-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
- struct ath5k_tx_status *);
-static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
- struct ath5k_rx_status *);
-static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
- struct ath5k_rx_status *);
-static int ath5k_hw_get_capabilities(struct ath5k_hw *);
-
-static int ath5k_eeprom_init(struct ath5k_hw *);
-static int ath5k_eeprom_read_mac(struct ath5k_hw *, u8 *);
-
-static int ath5k_hw_enable_pspoll(struct ath5k_hw *, u8 *, u16);
-static int ath5k_hw_disable_pspoll(struct ath5k_hw *);
-
-/*
- * Enable to overwrite the country code (use "00" for debug)
- */
-#if 0
-#define COUNTRYCODE "00"
-#endif
-
-/*******************\
- General Functions
-\*******************/
-
-/*
- * Functions used internaly
- */
-
-static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
-{
- return turbo ? (usec * 80) : (usec * 40);
-}
-
-static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
-{
- return turbo ? (clock / 80) : (clock / 40);
-}
-
-/*
- * Check if a register write has been completed
- */
-int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
- bool is_set)
-{
- int i;
- u32 data;
-
- for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
- data = ath5k_hw_reg_read(ah, reg);
- if (is_set && (data & flag))
- break;
- else if ((data & flag) == val)
- break;
- udelay(15);
- }
-
- return (i <= 0) ? -EAGAIN : 0;
-}
-
-
-/***************************************\
- Attach/Detach Functions
-\***************************************/
-
-/*
- * Power On Self Test helper function
- */
-static int ath5k_hw_post(struct ath5k_hw *ah)
-{
-
- int i, c;
- u16 cur_reg;
- u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
- u32 var_pattern;
- u32 static_pattern[4] = {
- 0x55555555, 0xaaaaaaaa,
- 0x66666666, 0x99999999
- };
- u32 init_val;
- u32 cur_val;
-
- for (c = 0; c < 2; c++) {
-
- cur_reg = regs[c];
-
- /* Save previous value */
- init_val = ath5k_hw_reg_read(ah, cur_reg);
-
- for (i = 0; i < 256; i++) {
- var_pattern = i << 16 | i;
- ath5k_hw_reg_write(ah, var_pattern, cur_reg);
- cur_val = ath5k_hw_reg_read(ah, cur_reg);
-
- if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
- return -EAGAIN;
- }
-
- /* Found on ndiswrapper dumps */
- var_pattern = 0x0039080f;
- ath5k_hw_reg_write(ah, var_pattern, cur_reg);
- }
-
- for (i = 0; i < 4; i++) {
- var_pattern = static_pattern[i];
- ath5k_hw_reg_write(ah, var_pattern, cur_reg);
- cur_val = ath5k_hw_reg_read(ah, cur_reg);
-
- if (cur_val != var_pattern) {
- ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
- return -EAGAIN;
- }
-
- /* Found on ndiswrapper dumps */
- var_pattern = 0x003b080f;
- ath5k_hw_reg_write(ah, var_pattern, cur_reg);
- }
-
- /* Restore previous value */
- ath5k_hw_reg_write(ah, init_val, cur_reg);
-
- }
-
- return 0;
-
-}
-
-/*
- * Check if the device is supported and initialize the needed structs
- */
-struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
-{
- struct ath5k_hw *ah;
- struct pci_dev *pdev = sc->pdev;
- u8 mac[ETH_ALEN];
- int ret;
- u32 srev;
-
- /*If we passed the test malloc a ath5k_hw struct*/
- ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
- if (ah == NULL) {
- ret = -ENOMEM;
- ATH5K_ERR(sc, "out of memory\n");
- goto err;
- }
-
- ah->ah_sc = sc;
- ah->ah_iobase = sc->iobase;
-
- /*
- * HW information
- */
-
- ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
- ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
- ah->ah_turbo = false;
- ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
- ah->ah_imr = 0;
- ah->ah_atim_window = 0;
- ah->ah_aifs = AR5K_TUNE_AIFS;
- ah->ah_cw_min = AR5K_TUNE_CWMIN;
- ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
- ah->ah_software_retry = false;
- ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
-
- /*
- * Set the mac revision based on the pci id
- */
- ah->ah_version = mac_version;
-
- /*Fill the ath5k_hw struct with the needed functions*/
- if (ah->ah_version == AR5K_AR5212)
- ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
- else if (ah->ah_version == AR5K_AR5211)
- ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
-
- if (ah->ah_version == AR5K_AR5212) {
- ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
- ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
- ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
- } else {
- ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
- ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
- ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
- }
-
- if (ah->ah_version == AR5K_AR5212)
- ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
- else if (ah->ah_version <= AR5K_AR5211)
- ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
-
- /* Bring device out of sleep and reset it's units */
- ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
- if (ret)
- goto err_free;
-
- /* Get MAC, PHY and RADIO revisions */
- srev = ath5k_hw_reg_read(ah, AR5K_SREV);
- ah->ah_mac_srev = srev;
- ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
- ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
- ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
- 0xffffffff;
- ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_5GHZ);
-
- if (ah->ah_version == AR5K_AR5210)
- ah->ah_radio_2ghz_revision = 0;
- else
- ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
-
- /* Return on unsuported chips (unsupported eeprom etc) */
- if ((srev >= AR5K_SREV_VER_AR5416) &&
- (srev < AR5K_SREV_VER_AR2425)) {
- ATH5K_ERR(sc, "Device not yet supported.\n");
- ret = -ENODEV;
- goto err_free;
- } else if (srev == AR5K_SREV_VER_AR2425) {
- ATH5K_WARN(sc, "Support for RF2425 is under development.\n");
- }
-
- /* Identify single chip solutions */
- if (((srev <= AR5K_SREV_VER_AR5414) &&
- (srev >= AR5K_SREV_VER_AR2413)) ||
- (srev == AR5K_SREV_VER_AR2425)) {
- ah->ah_single_chip = true;
- } else {
- ah->ah_single_chip = false;
- }
-
- /* Single chip radio */
- if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision)
- ah->ah_radio_2ghz_revision = 0;
-
- /* Identify the radio chip*/
- if (ah->ah_version == AR5K_AR5210) {
- ah->ah_radio = AR5K_RF5110;
- /*
- * Register returns 0x0/0x04 for radio revision
- * so ath5k_hw_radio_revision doesn't parse the value
- * correctly. For now we are based on mac's srev to
- * identify RF2425 radio.
- */
- } else if (srev == AR5K_SREV_VER_AR2425) {
- ah->ah_radio = AR5K_RF2425;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
- ah->ah_radio = AR5K_RF5111;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
- ah->ah_radio = AR5K_RF5112;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
- ah->ah_radio = AR5K_RF2413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
- ah->ah_radio = AR5K_RF5413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
- /* AR5424 */
- if (srev >= AR5K_SREV_VER_AR5424) {
- ah->ah_radio = AR5K_RF5413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
- /* AR2424 */
- } else {
- ah->ah_radio = AR5K_RF2413; /* For testing */
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
- }
- }
- ah->ah_phy = AR5K_PHY(0);
-
- /*
- * Write PCI-E power save settings
- */
- if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
- ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
- ath5k_hw_reg_write(ah, 0x24924924, 0x4080);
- ath5k_hw_reg_write(ah, 0x28000039, 0x4080);
- ath5k_hw_reg_write(ah, 0x53160824, 0x4080);
- ath5k_hw_reg_write(ah, 0xe5980579, 0x4080);
- ath5k_hw_reg_write(ah, 0x001defff, 0x4080);
- ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080);
- ath5k_hw_reg_write(ah, 0xbe105554, 0x4080);
- ath5k_hw_reg_write(ah, 0x000e3007, 0x4080);
- ath5k_hw_reg_write(ah, 0x00000000, 0x4084);
- }
-
- /*
- * POST
- */
- ret = ath5k_hw_post(ah);
- if (ret)
- goto err_free;
-
- /* Write AR5K_PCICFG_UNK on 2112B and later chips */
- if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B ||
- srev > AR5K_SREV_VER_AR2413) {
- ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG);
- }
-
- /*
- * Get card capabilities, values, ...
- */
- ret = ath5k_eeprom_init(ah);
- if (ret) {
- ATH5K_ERR(sc, "unable to init EEPROM\n");
- goto err_free;
- }
-
- /* Get misc capabilities */
- ret = ath5k_hw_get_capabilities(ah);
- if (ret) {
- ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
- sc->pdev->device);
- goto err_free;
- }
-
- /* Get MAC address */
- ret = ath5k_eeprom_read_mac(ah, mac);
- if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
- sc->pdev->device);
- goto err_free;
- }
-
- ath5k_hw_set_lladdr(ah, mac);
- /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
- memset(ah->ah_bssid, 0xff, ETH_ALEN);
- ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
- ath5k_hw_set_opmode(ah);
-
- ath5k_hw_set_rfgain_opt(ah);
-
- return ah;
-err_free:
- kfree(ah);
-err:
- return ERR_PTR(ret);
-}
-
-/*
- * Bring up MAC + PHY Chips
- */
-static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
-{
- struct pci_dev *pdev = ah->ah_sc->pdev;
- u32 turbo, mode, clock, bus_flags;
- int ret;
-
- turbo = 0;
- mode = 0;
- clock = 0;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /* Wakeup the device */
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
- return ret;
- }
-
- if (ah->ah_version != AR5K_AR5210) {
- /*
- * Get channel mode flags
- */
-
- if (ah->ah_radio >= AR5K_RF5112) {
- mode = AR5K_PHY_MODE_RAD_RF5112;
- clock = AR5K_PHY_PLL_RF5112;
- } else {
- mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
- clock = AR5K_PHY_PLL_RF5111; /*Zero*/
- }
-
- if (flags & CHANNEL_2GHZ) {
- mode |= AR5K_PHY_MODE_FREQ_2GHZ;
- clock |= AR5K_PHY_PLL_44MHZ;
-
- if (flags & CHANNEL_CCK) {
- mode |= AR5K_PHY_MODE_MOD_CCK;
- } else if (flags & CHANNEL_OFDM) {
- /* XXX Dynamic OFDM/CCK is not supported by the
- * AR5211 so we set MOD_OFDM for plain g (no
- * CCK headers) operation. We need to test
- * this, 5211 might support ofdm-only g after
- * all, there are also initial register values
- * in the code for g mode (see initvals.c). */
- if (ah->ah_version == AR5K_AR5211)
- mode |= AR5K_PHY_MODE_MOD_OFDM;
- else
- mode |= AR5K_PHY_MODE_MOD_DYN;
- } else {
- ATH5K_ERR(ah->ah_sc,
- "invalid radio modulation mode\n");
- return -EINVAL;
- }
- } else if (flags & CHANNEL_5GHZ) {
- mode |= AR5K_PHY_MODE_FREQ_5GHZ;
- clock |= AR5K_PHY_PLL_40MHZ;
-
- if (flags & CHANNEL_OFDM)
- mode |= AR5K_PHY_MODE_MOD_OFDM;
- else {
- ATH5K_ERR(ah->ah_sc,
- "invalid radio modulation mode\n");
- return -EINVAL;
- }
- } else {
- ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
- return -EINVAL;
- }
-
- if (flags & CHANNEL_TURBO)
- turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
- } else { /* Reset the device */
-
- /* ...enable Atheros turbo mode if requested */
- if (flags & CHANNEL_TURBO)
- ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
- AR5K_PHY_TURBO);
- }
-
- /* reseting PCI on PCI-E cards results card to hang
- * and always return 0xffff... so we ingore that flag
- * for PCI-E cards */
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-
- /* Reset chipset */
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_BASEBAND | bus_flags);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
- return -EIO;
- }
-
- if (ah->ah_version == AR5K_AR5210)
- udelay(2300);
-
- /* ...wakeup again!*/
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
- return ret;
- }
-
- /* ...final warm reset */
- if (ath5k_hw_nic_reset(ah, 0)) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
- return -EIO;
- }
-
- if (ah->ah_version != AR5K_AR5210) {
- /* ...set the PHY operating mode */
- ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
- udelay(300);
-
- ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
- ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
- }
-
- return 0;
-}
-
-/*
- * Get the rate table for a specific operation mode
- */
-const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
- unsigned int mode)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- if (!test_bit(mode, ah->ah_capabilities.cap_mode))
- return NULL;
-
- /* Get rate tables */
- switch (mode) {
- case AR5K_MODE_11A:
- return &ath5k_rt_11a;
- case AR5K_MODE_11A_TURBO:
- return &ath5k_rt_turbo;
- case AR5K_MODE_11B:
- return &ath5k_rt_11b;
- case AR5K_MODE_11G:
- return &ath5k_rt_11g;
- case AR5K_MODE_11G_TURBO:
- return &ath5k_rt_xr;
- }
-
- return NULL;
-}
-
-/*
- * Free the ath5k_hw struct
- */
-void ath5k_hw_detach(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
-
- if (ah->ah_rf_banks != NULL)
- kfree(ah->ah_rf_banks);
-
- /* assume interrupts are down */
- kfree(ah);
-}
-
-/****************************\
- Reset function and helpers
-\****************************/
-
-/**
- * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
- *
- * @ah: the &struct ath5k_hw
- * @channel: the currently set channel upon reset
- *
- * Write the OFDM timings for the AR5212 upon reset. This is a helper for
- * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
- * depending on the bandwidth of the channel.
- *
- */
-static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
- struct ieee80211_channel *channel)
-{
- /* Get exponent and mantissa and set it */
- u32 coef_scaled, coef_exp, coef_man,
- ds_coef_exp, ds_coef_man, clock;
-
- if (!(ah->ah_version == AR5K_AR5212) ||
- !(channel->hw_value & CHANNEL_OFDM))
- BUG();
-
- /* Seems there are two PLLs, one for baseband sampling and one
- * for tuning. Tuning basebands are 40 MHz or 80MHz when in
- * turbo. */
- clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
- coef_scaled = ((5 * (clock << 24)) / 2) /
- channel->center_freq;
-
- for (coef_exp = 31; coef_exp > 0; coef_exp--)
- if ((coef_scaled >> coef_exp) & 0x1)
- break;
-
- if (!coef_exp)
- return -EINVAL;
-
- coef_exp = 14 - (coef_exp - 24);
- coef_man = coef_scaled +
- (1 << (24 - coef_exp - 1));
- ds_coef_man = coef_man >> (24 - coef_exp);
- ds_coef_exp = coef_exp - 16;
-
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
- AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
- AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
-
- return 0;
-}
-
-/**
- * ath5k_hw_write_rate_duration - set rate duration during hw resets
- *
- * @ah: the &struct ath5k_hw
- * @mode: one of enum ath5k_driver_mode
- *
- * Write the rate duration table for the current mode upon hw reset. This
- * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
- * an ACK timeout for the hardware for the current mode for each rate. The
- * rates which are capable of short preamble (802.11b rates 2Mbps, 5.5Mbps,
- * and 11Mbps) have another register for the short preamble ACK timeout
- * calculation.
- *
- */
-static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
- unsigned int mode)
-{
- struct ath5k_softc *sc = ah->ah_sc;
- const struct ath5k_rate_table *rt;
- struct ieee80211_rate srate = {};
- unsigned int i;
-
- /* Get rate table for the current operating mode */
- rt = ath5k_hw_get_rate_table(ah, mode);
-
- /* Write rate duration table */
- for (i = 0; i < rt->rate_count; i++) {
- const struct ath5k_rate *rate, *control_rate;
-
- u32 reg;
- u16 tx_time;
-
- rate = &rt->rates[i];
- control_rate = &rt->rates[rate->control_rate];
-
- /* Set ACK timeout */
- reg = AR5K_RATE_DUR(rate->rate_code);
-
- srate.bitrate = control_rate->rate_kbps/100;
-
- /* An ACK frame consists of 10 bytes. If you add the FCS,
- * which ieee80211_generic_frame_duration() adds,
- * its 14 bytes. Note we use the control rate and not the
- * actual rate for this rate. See mac80211 tx.c
- * ieee80211_duration() for a brief description of
- * what rate we should choose to TX ACKs. */
- tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
- sc->vif, 10, &srate));
-
- ath5k_hw_reg_write(ah, tx_time, reg);
-
- if (!HAS_SHPREAMBLE(i))
- continue;
-
- /*
- * We're not distinguishing short preamble here,
- * This is true, all we'll get is a longer value here
- * which is not necessarilly bad. We could use
- * export ieee80211_frame_duration() but that needs to be
- * fixed first to be properly used by mac802111 drivers:
- *
- * - remove erp stuff and let the routine figure ofdm
- * erp rates
- * - remove passing argument ieee80211_local as
- * drivers don't have access to it
- * - move drivers using ieee80211_generic_frame_duration()
- * to this
- */
- ath5k_hw_reg_write(ah, tx_time,
- reg + (AR5K_SET_SHORT_PREAMBLE << 2));
- }
-}
-
-/*
- * Main reset function
- */
-int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
- struct ieee80211_channel *channel, bool change_channel)
-{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- struct pci_dev *pdev = ah->ah_sc->pdev;
- u32 data, s_seq, s_ant, s_led[3], dma_size;
- unsigned int i, mode, freq, ee_mode, ant[2];
- int ret;
-
- ATH5K_TRACE(ah->ah_sc);
-
- s_seq = 0;
- s_ant = 0;
- ee_mode = 0;
- freq = 0;
- mode = 0;
-
- /*
- * Save some registers before a reset
- */
- /*DCU/Antenna selection not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
- if (change_channel) {
- /* Seq number for queue 0 -do this for all queues ? */
- s_seq = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DFS_SEQNUM(0));
- /*Default antenna*/
- s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
- }
- }
-
- /*GPIOs*/
- s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
- s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
- s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
- if (change_channel && ah->ah_rf_banks != NULL)
- ath5k_hw_get_rf_gain(ah);
-
-
- /*Wakeup the device*/
- ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
- if (ret)
- return ret;
-
- /*
- * Initialize operating mode
- */
- ah->ah_op_mode = op_mode;
-
- /*
- * 5111/5112 Settings
- * 5210 only comes with RF5110
- */
- if (ah->ah_version != AR5K_AR5210) {
- if (ah->ah_radio != AR5K_RF5111 &&
- ah->ah_radio != AR5K_RF5112 &&
- ah->ah_radio != AR5K_RF5413 &&
- ah->ah_radio != AR5K_RF2413 &&
- ah->ah_radio != AR5K_RF2425) {
- ATH5K_ERR(ah->ah_sc,
- "invalid phy radio: %u\n", ah->ah_radio);
- return -EINVAL;
- }
-
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- mode = AR5K_MODE_11A;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- case CHANNEL_G:
- mode = AR5K_MODE_11G;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
- break;
- case CHANNEL_B:
- mode = AR5K_MODE_11B;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11B;
- break;
- case CHANNEL_T:
- mode = AR5K_MODE_11A_TURBO;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- /*Is this ok on 5211 too ?*/
- case CHANNEL_TG:
- mode = AR5K_MODE_11G_TURBO;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
- break;
- case CHANNEL_XR:
- if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
- "XR mode not available on 5211");
- return -EINVAL;
- }
- mode = AR5K_MODE_XR;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- default:
- ATH5K_ERR(ah->ah_sc,
- "invalid channel: %d\n", channel->center_freq);
- return -EINVAL;
- }
-
- /* PHY access enable */
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-
- }
-
- ret = ath5k_hw_write_initvals(ah, mode, change_channel);
- if (ret)
- return ret;
-
- /*
- * 5211/5212 Specific
- */
- if (ah->ah_version != AR5K_AR5210) {
- /*
- * Write initial RF gain settings
- * This should work for both 5111/5112
- */
- ret = ath5k_hw_rfgain(ah, freq);
- if (ret)
- return ret;
-
- mdelay(1);
-
- /*
- * Write some more initial register settings
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0x0002a002, 0x982c);
-
- if (channel->hw_value == CHANNEL_G)
- if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
- ath5k_hw_reg_write(ah, 0x00f80d80,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
- ath5k_hw_reg_write(ah, 0x00380140,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
- ath5k_hw_reg_write(ah, 0x00fc0ec0,
- 0x994c);
- else /* 2425 */
- ath5k_hw_reg_write(ah, 0x00fc0fc0,
- 0x994c);
- else
- ath5k_hw_reg_write(ah, 0x00000000, 0x994c);
-
- /* Some bits are disabled here, we know nothing about
- * register 0xa228 yet, most of the times this ends up
- * with a value 0x9b5 -haven't seen any dump with
- * a different value- */
- /* Got this from decompiling binary HAL */
- data = ath5k_hw_reg_read(ah, 0xa228);
- data &= 0xfffffdff;
- ath5k_hw_reg_write(ah, data, 0xa228);
-
- data = ath5k_hw_reg_read(ah, 0xa228);
- data &= 0xfffe03ff;
- ath5k_hw_reg_write(ah, data, 0xa228);
- data = 0;
-
- /* Just write 0x9b5 ? */
- /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */
- ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
- ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
- ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
- }
-
- /* Fix for first revision of the RF5112 RF chipset */
- if (ah->ah_radio >= AR5K_RF5112 &&
- ah->ah_radio_5ghz_revision <
- AR5K_SREV_RAD_5112A) {
- ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
- AR5K_PHY_CCKTXCTL);
- if (channel->hw_value & CHANNEL_5GHZ)
- data = 0xffb81020;
- else
- data = 0xffb80d20;
- ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
- data = 0;
- }
-
- /*
- * Set TX power (FIXME)
- */
- ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER);
- if (ret)
- return ret;
-
- /* Write rate duration table only on AR5212 and if
- * virtual interface has already been brought up
- * XXX: rethink this after new mode changes to
- * mac80211 are integrated */
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->vif != NULL)
- ath5k_hw_write_rate_duration(ah, mode);
-
- /*
- * Write RF registers
- */
- ret = ath5k_hw_rfregs(ah, channel, mode);
- if (ret)
- return ret;
-
- /*
- * Configure additional registers
- */
-
- /* Write OFDM timings on 5212*/
- if (ah->ah_version == AR5K_AR5212 &&
- channel->hw_value & CHANNEL_OFDM) {
- ret = ath5k_hw_write_ofdm_timings(ah, channel);
- if (ret)
- return ret;
- }
-
- /*Enable/disable 802.11b mode on 5111
- (enable 2111 frequency converter + CCK)*/
- if (ah->ah_radio == AR5K_RF5111) {
- if (mode == AR5K_MODE_11B)
- AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_B_MODE);
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_B_MODE);
- }
-
- /*
- * Set channel and calibrate the PHY
- */
- ret = ath5k_hw_channel(ah, channel);
- if (ret)
- return ret;
-
- /* Set antenna mode */
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL,
- ah->ah_antenna[ee_mode][0], 0xfffffc06);
-
- /*
- * In case a fixed antenna was set as default
- * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
- * registers.
- */
- if (s_ant != 0){
- if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
- ant[0] = ant[1] = AR5K_ANT_FIXED_A;
- else /* 2 - Aux */
- ant[0] = ant[1] = AR5K_ANT_FIXED_B;
- } else {
- ant[0] = AR5K_ANT_FIXED_A;
- ant[1] = AR5K_ANT_FIXED_B;
- }
-
- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
- AR5K_PHY_ANT_SWITCH_TABLE_0);
- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
- AR5K_PHY_ANT_SWITCH_TABLE_1);
-
- /* Commit values from EEPROM */
- if (ah->ah_radio == AR5K_RF5111)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
- AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
-
- ath5k_hw_reg_write(ah,
- AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
- AR5K_PHY_NFTHRES);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING,
- (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
- 0xffffc07f);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
- (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
- 0xfffc0fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
- (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
- ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
- 0xffff0000);
-
- ath5k_hw_reg_write(ah,
- (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
- (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
- (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
- (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3,
- ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF,
- (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01);
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CORR_ENABLE |
- (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
- ee->ee_q_cal[ee_mode]);
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
- AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
- ee->ee_margin_tx_rx[ee_mode]);
-
- } else {
- mdelay(1);
- /* Disable phy and wait */
- ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
- mdelay(1);
- }
-
- /*
- * Restore saved values
- */
- /*DCU/Antenna selection not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
- ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
- ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
- }
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
- ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
- ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
-
- /*
- * Misc
- */
- /* XXX: add ah->aid once mac80211 gives this to us */
- ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
-
- ath5k_hw_set_opmode(ah);
- /*PISR/SISR Not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
- /* If we later allow tuning for this, store into sc structure */
- data = AR5K_TUNE_RSSI_THRES |
- AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
- ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
- }
-
- /*
- * Set Rx/Tx DMA Configuration
- *
- * Set maximum DMA size (512) except for PCI-E cards since
- * it causes rx overruns and tx errors (tested on 5424 but since
- * rx overruns also occur on 5416/5418 with madwifi we set 128
- * for all PCI-E cards to be safe).
- *
- * In dumps this is 128 for allchips.
- *
- * XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
- * guess we can tweak it and see how it goes ;-)
- */
- dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
- if (ah->ah_version != AR5K_AR5210) {
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_SDMAMR, dma_size);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
- AR5K_RXCFG_SDMAMW, dma_size);
- }
-
- /*
- * Enable the PHY and wait until completion
- */
- ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-
- /*
- * On 5211+ read activation -> rx delay
- * and use it.
- */
- if (ah->ah_version != AR5K_AR5210) {
- data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
- AR5K_PHY_RX_DELAY_M;
- data = (channel->hw_value & CHANNEL_CCK) ?
- ((data << 2) / 22) : (data / 10);
-
- udelay(100 + (2 * data));
- data = 0;
- } else {
- mdelay(1);
- }
-
- /*
- * Perform ADC test (?)
- */
- data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
- ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
- for (i = 0; i <= 20; i++) {
- if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
- break;
- udelay(200);
- }
- ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1);
- data = 0;
-
- /*
- * Start automatic gain calibration
- *
- * During AGC calibration RX path is re-routed to
- * a signal detector so we don't receive anything.
- *
- * This method is used to calibrate some static offsets
- * used together with on-the fly I/Q calibration (the
- * one performed via ath5k_hw_phy_calibrate), that doesn't
- * interrupt rx path.
- *
- * If we are in a noisy environment AGC calibration may time
- * out.
- */
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL);
-
- /* At the same time start I/Q calibration for QAM constellation
- * -no need for CCK- */
- ah->ah_calibration = false;
- if (!(mode == AR5K_MODE_11B)) {
- ah->ah_calibration = true;
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_RUN);
- }
-
- /* Wait for gain calibration to finish (we check for I/Q calibration
- * during ath5k_phy_calibrate) */
- if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL, 0, false)) {
- ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
- channel->center_freq);
- return -EAGAIN;
- }
-
- /*
- * Start noise floor calibration
- *
- * If we run NF calibration before AGC, it always times out.
- * Binary HAL starts NF and AGC calibration at the same time
- * and only waits for AGC to finish. I believe that's wrong because
- * during NF calibration, rx path is also routed to a detector, so if
- * it doesn't finish we won't have RX.
- *
- * XXX: Find an interval that's OK for all cards...
- */
- ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
- if (ret)
- return ret;
-
- /*
- * Reset queues and start beacon timers at the end of the reset routine
- */
- for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
- /*No QCU on 5210*/
- if (ah->ah_version != AR5K_AR5210)
- AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
-
- ret = ath5k_hw_reset_tx_queue(ah, i);
- if (ret) {
- ATH5K_ERR(ah->ah_sc,
- "failed to reset TX queue #%d\n", i);
- return ret;
- }
- }
-
- /* Pre-enable interrupts on 5211/5212*/
- if (ah->ah_version != AR5K_AR5210)
- ath5k_hw_set_intr(ah, AR5K_INT_RX | AR5K_INT_TX |
- AR5K_INT_FATAL);
-
- /*
- * Set RF kill flags if supported by the device (read from the EEPROM)
- * Disable gpio_intr for now since it results system hang.
- * TODO: Handle this in ath5k_intr
- */
-#if 0
- if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
- ath5k_hw_set_gpio_input(ah, 0);
- ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
- if (ah->ah_gpio[0] == 0)
- ath5k_hw_set_gpio_intr(ah, 0, 1);
- else
- ath5k_hw_set_gpio_intr(ah, 0, 0);
- }
-#endif
-
- /*
- * Set the 32MHz reference clock on 5212 phy clock sleep register
- *
- * TODO: Find out how to switch to external 32Khz clock to save power
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
- ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
- ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
-
- data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ;
- data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ?
- 0x00000f80 : 0x00001380 ;
- ath5k_hw_reg_write(ah, data, AR5K_USEC_5211);
- data = 0;
- }
-
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
- ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
- ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
- if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
- ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
- }
-
- /*
- * Disable beacons and reset the register
- */
- AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
- AR5K_BEACON_RESET_TSF);
-
- return 0;
-}
-
-/*
- * Reset chipset
- */
-static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
-{
- int ret;
- u32 mask = val ? val : ~0U;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /* Read-and-clear RX Descriptor Pointer*/
- ath5k_hw_reg_read(ah, AR5K_RXDP);
-
- /*
- * Reset the device and wait until success
- */
- ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
-
- /* Wait at least 128 PCI clocks */
- udelay(15);
-
- if (ah->ah_version == AR5K_AR5210) {
- val &= AR5K_RESET_CTL_CHIP;
- mask &= AR5K_RESET_CTL_CHIP;
- } else {
- val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
- mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
- }
-
- ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
-
- /*
- * Reset configuration register (for hw byte-swap). Note that this
- * is only set for big endian. We do the necessary magic in
- * AR5K_INIT_CFG.
- */
- if ((val & AR5K_RESET_CTL_PCU) == 0)
- ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
-
- return ret;
-}
-
-/*
- * Power management functions
- */
-
-/*
- * Sleep control
- */
-int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
- bool set_chip, u16 sleep_duration)
-{
- unsigned int i;
- u32 staid, data;
-
- ATH5K_TRACE(ah->ah_sc);
- staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
-
- switch (mode) {
- case AR5K_PM_AUTO:
- staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
- /* fallthrough */
- case AR5K_PM_NETWORK_SLEEP:
- if (set_chip)
- ath5k_hw_reg_write(ah,
- AR5K_SLEEP_CTL_SLE_ALLOW |
- sleep_duration,
- AR5K_SLEEP_CTL);
-
- staid |= AR5K_STA_ID1_PWR_SV;
- break;
-
- case AR5K_PM_FULL_SLEEP:
- if (set_chip)
- ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
- AR5K_SLEEP_CTL);
-
- staid |= AR5K_STA_ID1_PWR_SV;
- break;
-
- case AR5K_PM_AWAKE:
-
- staid &= ~AR5K_STA_ID1_PWR_SV;
-
- if (!set_chip)
- goto commit;
-
- /* Preserve sleep duration */
- data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
- if( data & 0xffc00000 ){
- data = 0;
- } else {
- data = data & 0xfffcffff;
- }
-
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
- udelay(15);
-
- for (i = 50; i > 0; i--) {
- /* Check if the chip did wake up */
- if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
- AR5K_PCICFG_SPWR_DN) == 0)
- break;
-
- /* Wait a bit and retry */
- udelay(200);
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
- }
-
- /* Fail if the chip didn't wake up */
- if (i <= 0)
- return -EIO;
-
- break;
-
- default:
- return -EINVAL;
- }
-
-commit:
- ah->ah_power_mode = mode;
- ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
-
- return 0;
-}
-
-/***********************\
- DMA Related Functions
-\***********************/
-
-/*
- * Receive functions
- */
-
-/*
- * Start DMA receive
- */
-void ath5k_hw_start_rx(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
- ath5k_hw_reg_read(ah, AR5K_CR);
-}
-
-/*
- * Stop DMA receive
- */
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
-{
- unsigned int i;
-
- ATH5K_TRACE(ah->ah_sc);
- ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
-
- /*
- * It may take some time to disable the DMA receive unit
- */
- for (i = 2000; i > 0 &&
- (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
- i--)
- udelay(10);
-
- return i ? 0 : -EBUSY;
-}
-
-/*
- * Get the address of the RX Descriptor
- */
-u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah)
-{
- return ath5k_hw_reg_read(ah, AR5K_RXDP);
-}
-
-/*
- * Set the address of the RX Descriptor
- */
-void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- /*TODO:Shouldn't we check if RX is enabled first ?*/
- ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
-}
-
-/*
- * Transmit functions
- */
-
-/*
- * Start DMA transmit for a specific queue
- * (see also QCU/DCU functions)
- */
-int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue)
-{
- u32 tx_queue;
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /* Return if queue is declared inactive */
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return -EIO;
-
- if (ah->ah_version == AR5K_AR5210) {
- tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
-
- /*
- * Set the queue by type on 5210
- */
- switch (ah->ah_txq[queue].tqi_type) {
- case AR5K_TX_QUEUE_DATA:
- tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
- break;
- case AR5K_TX_QUEUE_BEACON:
- tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
- ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
- AR5K_BSR);
- break;
- case AR5K_TX_QUEUE_CAB:
- tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
- ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
- AR5K_BCR_BDMAE, AR5K_BSR);
- break;
- default:
- return -EINVAL;
- }
- /* Start queue */
- ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
- ath5k_hw_reg_read(ah, AR5K_CR);
- } else {
- /* Return if queue is disabled */
- if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
- return -EIO;
-
- /* Start queue */
- AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
- }
-
- return 0;
-}
-
-/*
- * Stop DMA transmit for a specific queue
- * (see also QCU/DCU functions)
- */
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
-{
- unsigned int i = 100;
- u32 tx_queue, pending;
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /* Return if queue is declared inactive */
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return -EIO;
-
- if (ah->ah_version == AR5K_AR5210) {
- tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
-
- /*
- * Set by queue type
- */
- switch (ah->ah_txq[queue].tqi_type) {
- case AR5K_TX_QUEUE_DATA:
- tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
- break;
- case AR5K_TX_QUEUE_BEACON:
- case AR5K_TX_QUEUE_CAB:
- /* XXX Fix me... */
- tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
- ath5k_hw_reg_write(ah, 0, AR5K_BSR);
- break;
- default:
- return -EINVAL;
- }
-
- /* Stop queue */
- ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
- ath5k_hw_reg_read(ah, AR5K_CR);
- } else {
- /*
- * Schedule TX disable and wait until queue is empty
- */
- AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
-
- /*Check for pending frames*/
- do {
- pending = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_STATUS(queue)) &
- AR5K_QCU_STS_FRMPENDCNT;
- udelay(100);
- } while (--i && pending);
-
- /* Clear register */
- ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
- if (pending)
- return -EBUSY;
- }
-
- /* TODO: Check for success else return error */
- return 0;
-}
-
-/*
- * Get the address of the TX Descriptor for a specific queue
- * (see also QCU/DCU functions)
- */
-u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue)
-{
- u16 tx_reg;
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /*
- * Get the transmit queue descriptor pointer from the selected queue
- */
- /*5210 doesn't have QCU*/
- if (ah->ah_version == AR5K_AR5210) {
- switch (ah->ah_txq[queue].tqi_type) {
- case AR5K_TX_QUEUE_DATA:
- tx_reg = AR5K_NOQCU_TXDP0;
- break;
- case AR5K_TX_QUEUE_BEACON:
- case AR5K_TX_QUEUE_CAB:
- tx_reg = AR5K_NOQCU_TXDP1;
- break;
- default:
- return 0xffffffff;
- }
- } else {
- tx_reg = AR5K_QUEUE_TXDP(queue);
- }
-
- return ath5k_hw_reg_read(ah, tx_reg);
-}
-
-/*
- * Set the address of the TX Descriptor for a specific queue
- * (see also QCU/DCU functions)
- */
-int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
-{
- u16 tx_reg;
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /*
- * Set the transmit queue descriptor pointer register by type
- * on 5210
- */
- if (ah->ah_version == AR5K_AR5210) {
- switch (ah->ah_txq[queue].tqi_type) {
- case AR5K_TX_QUEUE_DATA:
- tx_reg = AR5K_NOQCU_TXDP0;
- break;
- case AR5K_TX_QUEUE_BEACON:
- case AR5K_TX_QUEUE_CAB:
- tx_reg = AR5K_NOQCU_TXDP1;
- break;
- default:
- return -EINVAL;
- }
- } else {
- /*
- * Set the transmit queue descriptor pointer for
- * the selected queue on QCU for 5211+
- * (this won't work if the queue is still active)
- */
- if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
- return -EIO;
-
- tx_reg = AR5K_QUEUE_TXDP(queue);
- }
-
- /* Set descriptor pointer */
- ath5k_hw_reg_write(ah, phys_addr, tx_reg);
-
- return 0;
-}
-
-/*
- * Update tx trigger level
- */
-int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
-{
- u32 trigger_level, imr;
- int ret = -EIO;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /*
- * Disable interrupts by setting the mask
- */
- imr = ath5k_hw_set_intr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
-
- /*TODO: Boundary check on trigger_level*/
- trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
- AR5K_TXCFG_TXFULL);
-
- if (!increase) {
- if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
- goto done;
- } else
- trigger_level +=
- ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
-
- /*
- * Update trigger level on success
- */
- if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
- else
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_TXFULL, trigger_level);
-
- ret = 0;
-
-done:
- /*
- * Restore interrupt mask
- */
- ath5k_hw_set_intr(ah, imr);
-
- return ret;
-}
-
-/*
- * Interrupt handling
- */
-
-/*
- * Check if we have pending interrupts
- */
-bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_reg_read(ah, AR5K_INTPEND);
-}
-
-/*
- * Get interrupt mask (ISR)
- */
-int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
-{
- u32 data;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /*
- * Read interrupt status from the Interrupt Status register
- * on 5210
- */
- if (ah->ah_version == AR5K_AR5210) {
- data = ath5k_hw_reg_read(ah, AR5K_ISR);
- if (unlikely(data == AR5K_INT_NOCARD)) {
- *interrupt_mask = data;
- return -ENODEV;
- }
- } else {
- /*
- * Read interrupt status from the Read-And-Clear shadow register
- * Note: PISR/SISR Not available on 5210
- */
- data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
- }
-
- /*
- * Get abstract interrupt mask (driver-compatible)
- */
- *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
-
- if (unlikely(data == AR5K_INT_NOCARD))
- return -ENODEV;
-
- if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
- *interrupt_mask |= AR5K_INT_RX;
-
- if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
- | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
- *interrupt_mask |= AR5K_INT_TX;
-
- if (ah->ah_version != AR5K_AR5210) {
- /*HIU = Host Interface Unit (PCI etc)*/
- if (unlikely(data & (AR5K_ISR_HIUERR)))
- *interrupt_mask |= AR5K_INT_FATAL;
-
- /*Beacon Not Ready*/
- if (unlikely(data & (AR5K_ISR_BNR)))
- *interrupt_mask |= AR5K_INT_BNR;
- }
-
- /*
- * XXX: BMISS interrupts may occur after association.
- * I found this on 5210 code but it needs testing. If this is
- * true we should disable them before assoc and re-enable them
- * after a successfull assoc + some jiffies.
- */
-#if 0
- interrupt_mask &= ~AR5K_INT_BMISS;
-#endif
-
- /*
- * In case we didn't handle anything,
- * print the register value.
- */
- if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
- ATH5K_PRINTF("0x%08x\n", data);
-
- return 0;
-}
-
-/*
- * Set interrupt mask
- */
-enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask)
-{
- enum ath5k_int old_mask, int_mask;
-
- /*
- * Disable card interrupts to prevent any race conditions
- * (they will be re-enabled afterwards).
- */
- ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
- ath5k_hw_reg_read(ah, AR5K_IER);
-
- old_mask = ah->ah_imr;
-
- /*
- * Add additional, chipset-dependent interrupt mask flags
- * and write them to the IMR (interrupt mask register).
- */
- int_mask = new_mask & AR5K_INT_COMMON;
-
- if (new_mask & AR5K_INT_RX)
- int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
- AR5K_IMR_RXDESC;
-
- if (new_mask & AR5K_INT_TX)
- int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
- AR5K_IMR_TXURN;
-
- if (ah->ah_version != AR5K_AR5210) {
- if (new_mask & AR5K_INT_FATAL) {
- int_mask |= AR5K_IMR_HIUERR;
- AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
- AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
- }
- }
-
- ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
-
- /* Store new interrupt mask */
- ah->ah_imr = new_mask;
-
- /* ..re-enable interrupts */
- ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
- ath5k_hw_reg_read(ah, AR5K_IER);
-
- return old_mask;
-}
-
-
-/*************************\
- EEPROM access functions
-\*************************/
-
-/*
- * Read from eeprom
- */
-static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
-{
- u32 status, timeout;
-
- ATH5K_TRACE(ah->ah_sc);
- /*
- * Initialize EEPROM access
- */
- if (ah->ah_version == AR5K_AR5210) {
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
- (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
- } else {
- ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
- AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
- AR5K_EEPROM_CMD_READ);
- }
-
- for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
- status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
- if (status & AR5K_EEPROM_STAT_RDDONE) {
- if (status & AR5K_EEPROM_STAT_RDERR)
- return -EIO;
- *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
- 0xffff);
- return 0;
- }
- udelay(15);
- }
-
- return -ETIMEDOUT;
-}
-
-/*
- * Write to eeprom - currently disabled, use at your own risk
- */
-#if 0
-static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
-{
-
- u32 status, timeout;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /*
- * Initialize eeprom access
- */
-
- if (ah->ah_version == AR5K_AR5210) {
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
- } else {
- AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
- AR5K_EEPROM_CMD_RESET);
- }
-
- /*
- * Write data to data register
- */
-
- if (ah->ah_version == AR5K_AR5210) {
- ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset));
- } else {
- ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
- ath5k_hw_reg_write(ah, data, AR5K_EEPROM_DATA);
- AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
- AR5K_EEPROM_CMD_WRITE);
- }
-
- /*
- * Check status
- */
-
- for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
- status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
- if (status & AR5K_EEPROM_STAT_WRDONE) {
- if (status & AR5K_EEPROM_STAT_WRERR)
- return EIO;
- return 0;
- }
- udelay(15);
- }
-
- ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
- return -EIO;
-}
-#endif
-
-/*
- * Translate binary channel representation in EEPROM to frequency
- */
-static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, unsigned int mode)
-{
- u16 val;
-
- if (bin == AR5K_EEPROM_CHANNEL_DIS)
- return bin;
-
- if (mode == AR5K_EEPROM_MODE_11A) {
- if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
- val = (5 * bin) + 4800;
- else
- val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
- (bin * 10) + 5100;
- } else {
- if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
- val = bin + 2300;
- else
- val = bin + 2400;
- }
-
- return val;
-}
-
-/*
- * Read antenna infos from eeprom
- */
-static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
- unsigned int mode)
-{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 o = *offset;
- u16 val;
- int ret, i = 0;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
- ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
- ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
- ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
- ee->ee_ant_control[mode][i++] = val & 0x3f;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
- ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
- ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
- ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
- ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
- ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
- ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
- ee->ee_ant_control[mode][i++] = val & 0x3f;
-
- /* Get antenna modes */
- ah->ah_antenna[mode][0] =
- (ee->ee_ant_control[mode][0] << 4) | 0x1;
- ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
- ee->ee_ant_control[mode][1] |
- (ee->ee_ant_control[mode][2] << 6) |
- (ee->ee_ant_control[mode][3] << 12) |
- (ee->ee_ant_control[mode][4] << 18) |
- (ee->ee_ant_control[mode][5] << 24);
- ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
- ee->ee_ant_control[mode][6] |
- (ee->ee_ant_control[mode][7] << 6) |
- (ee->ee_ant_control[mode][8] << 12) |
- (ee->ee_ant_control[mode][9] << 18) |
- (ee->ee_ant_control[mode][10] << 24);
-
- /* return new offset */
- *offset = o;
-
- return 0;
-}
-
-/*
- * Read supported modes from eeprom
- */
-static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
- unsigned int mode)
-{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 o = *offset;
- u16 val;
- int ret;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
- ee->ee_thr_62[mode] = val & 0xff;
-
- if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
- ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
- ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
-
- if ((val & 0xff) & 0x80)
- ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
- else
- ee->ee_noise_floor_thr[mode] = val & 0xff;
-
- if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
- ee->ee_noise_floor_thr[mode] =
- mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
- ee->ee_x_gain[mode] = (val >> 1) & 0xf;
- ee->ee_xpd[mode] = val & 0x1;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
- ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
- AR5K_EEPROM_READ(o++, val);
- ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
-
- if (mode == AR5K_EEPROM_MODE_11A)
- ee->ee_xr_power[mode] = val & 0x3f;
- else {
- ee->ee_ob[mode][0] = val & 0x7;
- ee->ee_db[mode][0] = (val >> 3) & 0x7;
- }
- }
-
- if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
- ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
- ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
- } else {
- ee->ee_i_gain[mode] = (val >> 13) & 0x7;
-
- AR5K_EEPROM_READ(o++, val);
- ee->ee_i_gain[mode] |= (val << 3) & 0x38;
-
- if (mode == AR5K_EEPROM_MODE_11G)
- ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
- }
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
- mode == AR5K_EEPROM_MODE_11A) {
- ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
- ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
- }
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
- mode == AR5K_EEPROM_MODE_11G)
- ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
-
- /* return new offset */
- *offset = o;
-
- return 0;
-}
-
-/*
- * Initialize eeprom & capabilities structs
- */
-static int ath5k_eeprom_init(struct ath5k_hw *ah)
-{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- unsigned int mode, i;
- int ret;
- u32 offset;
- u16 val;
-
- /* Initial TX thermal adjustment values */
- ee->ee_tx_clip = 4;
- ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
- ee->ee_gain_select = 1;
-
- /*
- * Read values from EEPROM and store them in the capability structure
- */
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
-
- /* Return if we have an old EEPROM */
- if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
- return 0;
-
-#ifdef notyet
- /*
- * Validate the checksum of the EEPROM date. There are some
- * devices with invalid EEPROMs.
- */
- for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
- AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
- cksum ^= val;
- }
- if (cksum != AR5K_EEPROM_INFO_CKSUM) {
- ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
- return -EIO;
- }
-#endif
-
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
- ee_ant_gain);
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
- }
-
- if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
- AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
- ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
- ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
-
- AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
- ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
- ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
- }
-
- /*
- * Get conformance test limit values
- */
- offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
- ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
-
- for (i = 0; i < ee->ee_ctls; i++) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_ctl[i] = (val >> 8) & 0xff;
- ee->ee_ctl[i + 1] = val & 0xff;
- }
-
- /*
- * Get values for 802.11a (5GHz)
- */
- mode = AR5K_EEPROM_MODE_11A;
-
- ee->ee_turbo_max_power[mode] =
- AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
-
- offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
-
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][3] = (val >> 5) & 0x7;
- ee->ee_db[mode][3] = (val >> 2) & 0x7;
- ee->ee_ob[mode][2] = (val << 1) & 0x7;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
- ee->ee_db[mode][2] = (val >> 12) & 0x7;
- ee->ee_ob[mode][1] = (val >> 9) & 0x7;
- ee->ee_db[mode][1] = (val >> 6) & 0x7;
- ee->ee_ob[mode][0] = (val >> 3) & 0x7;
- ee->ee_db[mode][0] = val & 0x7;
-
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_margin_tx_rx[mode] = val & 0x3f;
- }
-
- /*
- * Get values for 802.11b (2.4GHz)
- */
- mode = AR5K_EEPROM_MODE_11B;
- offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
-
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][1] = (val >> 4) & 0x7;
- ee->ee_db[mode][1] = val & 0x7;
-
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][0] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
- ee->ee_cal_pier[mode][1] =
- ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][2] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
- }
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
-
- /*
- * Get values for 802.11g (2.4GHz)
- */
- mode = AR5K_EEPROM_MODE_11G;
- offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
-
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][1] = (val >> 4) & 0x7;
- ee->ee_db[mode][1] = val & 0x7;
-
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][0] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
- ee->ee_cal_pier[mode][1] =
- ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_turbo_max_power[mode] = val & 0x7f;
- ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][2] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
- ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_cck_ofdm_gain_delta = val & 0xff;
- }
- }
-
- /*
- * Read 5GHz EEPROM channels
- */
-
- return 0;
-}
-
-/*
- * Read the MAC address from eeprom
- */
-static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
- u8 mac_d[ETH_ALEN];
- u32 total, offset;
- u16 data;
- int octet, ret;
-
- memset(mac, 0, ETH_ALEN);
- memset(mac_d, 0, ETH_ALEN);
-
- ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
- if (ret)
- return ret;
-
- for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
- ret = ath5k_hw_eeprom_read(ah, offset, &data);
- if (ret)
- return ret;
-
- total += data;
- mac_d[octet + 1] = data & 0xff;
- mac_d[octet] = data >> 8;
- octet += 2;
- }
-
- memcpy(mac, mac_d, ETH_ALEN);
-
- if (!total || total == 3 * 0xffff)
- return -EINVAL;
-
- return 0;
-}
-
-/*
- * Fill the capabilities struct
- */
-static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
-{
- u16 ee_header;
-
- ATH5K_TRACE(ah->ah_sc);
- /* Capabilities stored in the EEPROM */
- ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
-
- if (ah->ah_version == AR5K_AR5210) {
- /*
- * Set radio capabilities
- * (The AR5110 only supports the middle 5GHz band)
- */
- ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
- ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
- ah->ah_capabilities.cap_range.range_2ghz_min = 0;
- ah->ah_capabilities.cap_range.range_2ghz_max = 0;
-
- /* Set supported modes */
- __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
- __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
- } else {
- /*
- * XXX The tranceiver supports frequencies from 4920 to 6100GHz
- * XXX and from 2312 to 2732GHz. There are problems with the
- * XXX current ieee80211 implementation because the IEEE
- * XXX channel mapping does not support negative channel
- * XXX numbers (2312MHz is channel -19). Of course, this
- * XXX doesn't matter because these channels are out of range
- * XXX but some regulation domains like MKK (Japan) will
- * XXX support frequencies somewhere around 4.8GHz.
- */
-
- /*
- * Set radio capabilities
- */
-
- if (AR5K_EEPROM_HDR_11A(ee_header)) {
- ah->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */
- ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
-
- /* Set supported modes */
- __set_bit(AR5K_MODE_11A,
- ah->ah_capabilities.cap_mode);
- __set_bit(AR5K_MODE_11A_TURBO,
- ah->ah_capabilities.cap_mode);
- if (ah->ah_version == AR5K_AR5212)
- __set_bit(AR5K_MODE_11G_TURBO,
- ah->ah_capabilities.cap_mode);
- }
-
- /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
- * connected */
- if (AR5K_EEPROM_HDR_11B(ee_header) ||
- AR5K_EEPROM_HDR_11G(ee_header)) {
- ah->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */
- ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
-
- if (AR5K_EEPROM_HDR_11B(ee_header))
- __set_bit(AR5K_MODE_11B,
- ah->ah_capabilities.cap_mode);
-
- if (AR5K_EEPROM_HDR_11G(ee_header))
- __set_bit(AR5K_MODE_11G,
- ah->ah_capabilities.cap_mode);
- }
- }
-
- /* GPIO */
- ah->ah_gpio_npins = AR5K_NUM_GPIO;
-
- /* Set number of supported TX queues */
- if (ah->ah_version == AR5K_AR5210)
- ah->ah_capabilities.cap_queues.q_tx_num =
- AR5K_NUM_TX_QUEUES_NOQCU;
- else
- ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
-
- return 0;
-}
-
-/*********************************\
- Protocol Control Unit Functions
-\*********************************/
-
-/*
- * Set Operation mode
- */
-int ath5k_hw_set_opmode(struct ath5k_hw *ah)
-{
- u32 pcu_reg, beacon_reg, low_id, high_id;
-
- pcu_reg = 0;
- beacon_reg = 0;
-
- ATH5K_TRACE(ah->ah_sc);
-
- switch (ah->ah_op_mode) {
- case IEEE80211_IF_TYPE_IBSS:
- pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
- beacon_reg |= AR5K_BCR_ADHOC;
- break;
-
- case IEEE80211_IF_TYPE_AP:
- pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
- beacon_reg |= AR5K_BCR_AP;
- break;
-
- case IEEE80211_IF_TYPE_STA:
- pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_PWR_SV : 0);
- case IEEE80211_IF_TYPE_MNTR:
- pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
- break;
-
- default:
- return -EINVAL;
- }
-
- /*
- * Set PCU registers
- */
- low_id = AR5K_LOW_ID(ah->ah_sta_id);
- high_id = AR5K_HIGH_ID(ah->ah_sta_id);
- ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
- ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
-
- /*
- * Set Beacon Control Register on 5210
- */
- if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
-
- return 0;
-}
-
-/*
- * BSSID Functions
- */
-
-/*
- * Get station id
- */
-void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
-{
- ATH5K_TRACE(ah->ah_sc);
- memcpy(mac, ah->ah_sta_id, ETH_ALEN);
-}
-
-/*
- * Set station id
- */
-int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
-{
- u32 low_id, high_id;
-
- ATH5K_TRACE(ah->ah_sc);
- /* Set new station ID */
- memcpy(ah->ah_sta_id, mac, ETH_ALEN);
-
- low_id = AR5K_LOW_ID(mac);
- high_id = AR5K_HIGH_ID(mac);
-
- ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
- ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
-
- return 0;
-}
-
-/*
- * Set BSSID
- */
-void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
-{
- u32 low_id, high_id;
- u16 tim_offset = 0;
-
- /*
- * Set simple BSSID mask on 5212
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
- }
-
- /*
- * Set BSSID which triggers the "SME Join" operation
- */
- low_id = AR5K_LOW_ID(bssid);
- high_id = AR5K_HIGH_ID(bssid);
- ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
- ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
- AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
-
- if (assoc_id == 0) {
- ath5k_hw_disable_pspoll(ah);
- return;
- }
-
- AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
- tim_offset ? tim_offset + 4 : 0);
-
- ath5k_hw_enable_pspoll(ah, NULL, 0);
-}
-/**
- * ath5k_hw_set_bssid_mask - set common bits we should listen to
- *
- * The bssid_mask is a utility used by AR5212 hardware to inform the hardware
- * which bits of the interface's MAC address should be looked at when trying
- * to decide which packets to ACK. In station mode every bit matters. In AP
- * mode with a single BSS every bit matters as well. In AP mode with
- * multiple BSSes not every bit matters.
- *
- * @ah: the &struct ath5k_hw
- * @mask: the bssid_mask, a u8 array of size ETH_ALEN
- *
- * Note that this is a simple filter and *does* not filter out all
- * relevant frames. Some non-relevant frames will get through, probability
- * jocks are welcomed to compute.
- *
- * When handling multiple BSSes (or VAPs) you can get the BSSID mask by
- * computing the set of:
- *
- * ~ ( MAC XOR BSSID )
- *
- * When you do this you are essentially computing the common bits. Later it
- * is assumed the harware will "and" (&) the BSSID mask with the MAC address
- * to obtain the relevant bits which should match on the destination frame.
- *
- * Simple example: on your card you have have two BSSes you have created with
- * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
- * There is another BSSID-03 but you are not part of it. For simplicity's sake,
- * assuming only 4 bits for a mac address and for BSSIDs you can then have:
- *
- * \
- * MAC: 0001 |
- * BSSID-01: 0100 | --> Belongs to us
- * BSSID-02: 1001 |
- * /
- * -------------------
- * BSSID-03: 0110 | --> External
- * -------------------
- *
- * Our bssid_mask would then be:
- *
- * On loop iteration for BSSID-01:
- * ~(0001 ^ 0100) -> ~(0101)
- * -> 1010
- * bssid_mask = 1010
- *
- * On loop iteration for BSSID-02:
- * bssid_mask &= ~(0001 ^ 1001)
- * bssid_mask = (1010) & ~(0001 ^ 1001)
- * bssid_mask = (1010) & ~(1001)
- * bssid_mask = (1010) & (0110)
- * bssid_mask = 0010
- *
- * A bssid_mask of 0010 means "only pay attention to the second least
- * significant bit". This is because its the only bit common
- * amongst the MAC and all BSSIDs we support. To findout what the real
- * common bit is we can simply "&" the bssid_mask now with any BSSID we have
- * or our MAC address (we assume the hardware uses the MAC address).
- *
- * Now, suppose there's an incoming frame for BSSID-03:
- *
- * IFRAME-01: 0110
- *
- * An easy eye-inspeciton of this already should tell you that this frame
- * will not pass our check. This is beacuse the bssid_mask tells the
- * hardware to only look at the second least significant bit and the
- * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
- * as 1, which does not match 0.
- *
- * So with IFRAME-01 we *assume* the hardware will do:
- *
- * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
- * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
- * --> allow = (0010) == 0000 ? 1 : 0;
- * --> allow = 0
- *
- * Lets now test a frame that should work:
- *
- * IFRAME-02: 0001 (we should allow)
- *
- * allow = (0001 & 1010) == 1010
- *
- * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
- * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
- * --> allow = (0010) == (0010)
- * --> allow = 1
- *
- * Other examples:
- *
- * IFRAME-03: 0100 --> allowed
- * IFRAME-04: 1001 --> allowed
- * IFRAME-05: 1101 --> allowed but its not for us!!!
- *
- */
-int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
-{
- u32 low_id, high_id;
- ATH5K_TRACE(ah->ah_sc);
-
- if (ah->ah_version == AR5K_AR5212) {
- low_id = AR5K_LOW_ID(mask);
- high_id = AR5K_HIGH_ID(mask);
-
- ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
- ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
-
- return 0;
- }
-
- return -EIO;
-}
-
-/*
- * Receive start/stop functions
- */
-
-/*
- * Start receive on PCU
- */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-
- /* TODO: ANI Support */
-}
-
-/*
- * Stop receive on PCU
- */
-void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-
- /* TODO: ANI Support */
-}
-
-/*
- * RX Filter functions
- */
-
-/*
- * Set multicast filter
- */
-void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
-{
- ATH5K_TRACE(ah->ah_sc);
- /* Set the multicat filter */
- ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
- ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
-}
-
-/*
- * Set multicast filter by index
- */
-int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index)
-{
-
- ATH5K_TRACE(ah->ah_sc);
- if (index >= 64)
- return -EINVAL;
- else if (index >= 32)
- AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
- (1 << (index - 32)));
- else
- AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
-
- return 0;
-}
-
-/*
- * Clear Multicast filter by index
- */
-int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
-{
-
- ATH5K_TRACE(ah->ah_sc);
- if (index >= 64)
- return -EINVAL;
- else if (index >= 32)
- AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
- (1 << (index - 32)));
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
-
- return 0;
-}
-
-/*
- * Get current rx filter
- */
-u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
-{
- u32 data, filter = 0;
-
- ATH5K_TRACE(ah->ah_sc);
- filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
-
- /*Radar detection for 5212*/
- if (ah->ah_version == AR5K_AR5212) {
- data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
-
- if (data & AR5K_PHY_ERR_FIL_RADAR)
- filter |= AR5K_RX_FILTER_RADARERR;
- if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
- filter |= AR5K_RX_FILTER_PHYERR;
- }
-
- return filter;
-}
-
-/*
- * Set rx filter
- */
-void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
-{
- u32 data = 0;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /* Set PHY error filter register on 5212*/
- if (ah->ah_version == AR5K_AR5212) {
- if (filter & AR5K_RX_FILTER_RADARERR)
- data |= AR5K_PHY_ERR_FIL_RADAR;
- if (filter & AR5K_RX_FILTER_PHYERR)
- data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
- }
-
- /*
- * The AR5210 uses promiscous mode to detect radar activity
- */
- if (ah->ah_version == AR5K_AR5210 &&
- (filter & AR5K_RX_FILTER_RADARERR)) {
- filter &= ~AR5K_RX_FILTER_RADARERR;
- filter |= AR5K_RX_FILTER_PROM;
- }
-
- /*Zero length DMA*/
- if (data)
- AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
-
- /*Write RX Filter register*/
- ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
-
- /*Write PHY error filter register on 5212*/
- if (ah->ah_version == AR5K_AR5212)
- ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
-
-}
-
-/*
- * Beacon related functions
- */
-
-/*
- * Get a 32bit TSF
- */
-u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
-}
-
-/*
- * Get the full 64bit TSF
- */
-u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
-{
- u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
- ATH5K_TRACE(ah->ah_sc);
-
- return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
-}
-
-/*
- * Force a TSF reset
- */
-void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF);
-}
-
-/*
- * Initialize beacon timers
- */
-void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
-{
- u32 timer1, timer2, timer3;
-
- ATH5K_TRACE(ah->ah_sc);
- /*
- * Set the additional timers by mode
- */
- switch (ah->ah_op_mode) {
- case IEEE80211_IF_TYPE_STA:
- if (ah->ah_version == AR5K_AR5210) {
- timer1 = 0xffffffff;
- timer2 = 0xffffffff;
- } else {
- timer1 = 0x0000ffff;
- timer2 = 0x0007ffff;
- }
- break;
-
- default:
- timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
- timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
- }
-
- timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
-
- /*
- * Set the beacon register and enable all timers.
- * (next beacon, DMA beacon, software beacon, ATIM window time)
- */
- ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
- ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
- ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
- ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
-
- ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
- AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
- AR5K_BEACON);
-}
-
-#if 0
-/*
- * Set beacon timers
- */
-int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
- const struct ath5k_beacon_state *state)
-{
- u32 cfp_period, next_cfp, dtim, interval, next_beacon;
-
- /*
- * TODO: should be changed through *state
- * review struct ath5k_beacon_state struct
- *
- * XXX: These are used for cfp period bellow, are they
- * ok ? Is it O.K. for tsf here to be 0 or should we use
- * get_tsf ?
- */
- u32 dtim_count = 0; /* XXX */
- u32 cfp_count = 0; /* XXX */
- u32 tsf = 0; /* XXX */
-
- ATH5K_TRACE(ah->ah_sc);
- /* Return on an invalid beacon state */
- if (state->bs_interval < 1)
- return -EINVAL;
-
- interval = state->bs_interval;
- dtim = state->bs_dtim_period;
-
- /*
- * PCF support?
- */
- if (state->bs_cfp_period > 0) {
- /*
- * Enable PCF mode and set the CFP
- * (Contention Free Period) and timer registers
- */
- cfp_period = state->bs_cfp_period * state->bs_dtim_period *
- state->bs_interval;
- next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
- state->bs_interval;
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
- AR5K_STA_ID1_DEFAULT_ANTENNA |
- AR5K_STA_ID1_PCF);
- ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
- ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
- AR5K_CFP_DUR);
- ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
- next_cfp)) << 3, AR5K_TIMER2);
- } else {
- /* Disable PCF mode */
- AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
- AR5K_STA_ID1_DEFAULT_ANTENNA |
- AR5K_STA_ID1_PCF);
- }
-
- /*
- * Enable the beacon timer register
- */
- ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
-
- /*
- * Start the beacon timers
- */
- ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &~
- (AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
- AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
- AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
- AR5K_BEACON_PERIOD), AR5K_BEACON);
-
- /*
- * Write new beacon miss threshold, if it appears to be valid
- * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
- * and return if its not in range. We can test this by reading value and
- * setting value to a largest value and seeing which values register.
- */
-
- AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
- state->bs_bmiss_threshold);
-
- /*
- * Set sleep control register
- * XXX: Didn't find this in 5210 code but since this register
- * exists also in ar5k's 5210 headers i leave it as common code.
- */
- AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
- (state->bs_sleep_duration - 3) << 3);
-
- /*
- * Set enhanced sleep registers on 5212
- */
- if (ah->ah_version == AR5K_AR5212) {
- if (state->bs_sleep_duration > state->bs_interval &&
- roundup(state->bs_sleep_duration, interval) ==
- state->bs_sleep_duration)
- interval = state->bs_sleep_duration;
-
- if (state->bs_sleep_duration > dtim && (dtim == 0 ||
- roundup(state->bs_sleep_duration, dtim) ==
- state->bs_sleep_duration))
- dtim = state->bs_sleep_duration;
-
- if (interval > dtim)
- return -EINVAL;
-
- next_beacon = interval == dtim ? state->bs_next_dtim :
- state->bs_next_beacon;
-
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
- AR5K_SLEEP0_NEXT_DTIM) |
- AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
- AR5K_SLEEP0_ENH_SLEEP_EN |
- AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
-
- ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
- AR5K_SLEEP1_NEXT_TIM) |
- AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
-
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
- AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
- }
-
- return 0;
-}
-
-/*
- * Reset beacon timers
- */
-void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- /*
- * Disable beacon timer
- */
- ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
-
- /*
- * Disable some beacon register values
- */
- AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
- AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
- ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
-}
-
-/*
- * Wait for beacon queue to finish
- */
-int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
-{
- unsigned int i;
- int ret;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /* 5210 doesn't have QCU*/
- if (ah->ah_version == AR5K_AR5210) {
- /*
- * Wait for beaconn queue to finish by checking
- * Control Register and Beacon Status Register.
- */
- for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
- if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
- ||
- !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
- break;
- udelay(10);
- }
-
- /* Timeout... */
- if (i <= 0) {
- /*
- * Re-schedule the beacon queue
- */
- ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
- ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
- AR5K_BCR);
-
- return -EIO;
- }
- ret = 0;
- } else {
- /*5211/5212*/
- ret = ath5k_hw_register_timeout(ah,
- AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
- AR5K_QCU_STS_FRMPENDCNT, 0, false);
-
- if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
- return -EIO;
- }
-
- return ret;
-}
-#endif
-
-/*
- * Update mib counters (statistics)
- */
-void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
- struct ieee80211_low_level_stats *stats)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- /* Read-And-Clear */
- stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
- stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
- stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
- stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
-
- /* XXX: Should we use this to track beacon count ?
- * -we read it anyway to clear the register */
- ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
-
- /* Reset profile count registers on 5212*/
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
- }
-}
-
-/** ath5k_hw_set_ack_bitrate - set bitrate for ACKs
- *
- * @ah: the &struct ath5k_hw
- * @high: determines if to use low bit rate or now
- */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
-{
- if (ah->ah_version != AR5K_AR5212)
- return;
- else {
- u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
- if (high)
- AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
- }
-}
-
-
-/*
- * ACK/CTS Timeouts
- */
-
-/*
- * Set ACK timeout on PCU
- */
-int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
- ah->ah_turbo) <= timeout)
- return -EINVAL;
-
- AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
- ath5k_hw_htoclock(timeout, ah->ah_turbo));
-
- return 0;
-}
-
-/*
- * Read the ACK timeout from PCU
- */
-unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
- AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
-}
-
-/*
- * Set CTS timeout on PCU
- */
-int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
- ah->ah_turbo) <= timeout)
- return -EINVAL;
-
- AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
- ath5k_hw_htoclock(timeout, ah->ah_turbo));
-
- return 0;
-}
-
-/*
- * Read CTS timeout from PCU
- */
-unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
- AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
-}
-
-/*
- * Key table (WEP) functions
- */
-
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
-{
- unsigned int i;
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
- for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
- ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
-
- /*
- * Set NULL encryption on AR5212+
- *
- * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
- * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
- *
- * Note2: Windows driver (ndiswrapper) sets this to
- * 0x00000714 instead of 0x00000007
- */
- if (ah->ah_version > AR5K_AR5211)
- ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
- AR5K_KEYTABLE_TYPE(entry));
-
- return 0;
-}
-
-int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
-{
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
- /* Check the validation flag at the end of the entry */
- return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
- AR5K_KEYTABLE_VALID;
-}
-
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
- const struct ieee80211_key_conf *key, const u8 *mac)
-{
- unsigned int i;
- __le32 key_v[5] = {};
- u32 keytype;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /* key->keylen comes in from mac80211 in bytes */
-
- if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
- return -EOPNOTSUPP;
-
- switch (key->keylen) {
- /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
- case 40 / 8:
- memcpy(&key_v[0], key->key, 5);
- keytype = AR5K_KEYTABLE_TYPE_40;
- break;
-
- /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
- case 104 / 8:
- memcpy(&key_v[0], &key->key[0], 6);
- memcpy(&key_v[2], &key->key[6], 6);
- memcpy(&key_v[4], &key->key[12], 1);
- keytype = AR5K_KEYTABLE_TYPE_104;
- break;
- /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
- case 128 / 8:
- memcpy(&key_v[0], &key->key[0], 6);
- memcpy(&key_v[2], &key->key[6], 6);
- memcpy(&key_v[4], &key->key[12], 4);
- keytype = AR5K_KEYTABLE_TYPE_128;
- break;
-
- default:
- return -EINVAL; /* shouldn't happen */
- }
-
- for (i = 0; i < ARRAY_SIZE(key_v); i++)
- ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
- AR5K_KEYTABLE_OFF(entry, i));
-
- ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
-
- return ath5k_hw_set_key_lladdr(ah, entry, mac);
-}
-
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
-{
- u32 low_id, high_id;
-
- ATH5K_TRACE(ah->ah_sc);
- /* Invalid entry (key table overflow) */
- AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
- /* MAC may be NULL if it's a broadcast key. In this case no need to
- * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
- if (unlikely(mac == NULL)) {
- low_id = 0xffffffff;
- high_id = 0xffff | AR5K_KEYTABLE_VALID;
- } else {
- low_id = AR5K_LOW_ID(mac);
- high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
- }
-
- ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
- ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
-
- return 0;
-}
-
-
-/********************************************\
-Queue Control Unit, DFS Control Unit Functions
-\********************************************/
-
-/*
- * Initialize a transmit queue
- */
-int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
- struct ath5k_txq_info *queue_info)
-{
- unsigned int queue;
- int ret;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /*
- * Get queue by type
- */
- /*5210 only has 2 queues*/
- if (ah->ah_version == AR5K_AR5210) {
- switch (queue_type) {
- case AR5K_TX_QUEUE_DATA:
- queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
- break;
- case AR5K_TX_QUEUE_BEACON:
- case AR5K_TX_QUEUE_CAB:
- queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
- break;
- default:
- return -EINVAL;
- }
- } else {
- switch (queue_type) {
- case AR5K_TX_QUEUE_DATA:
- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
- ah->ah_txq[queue].tqi_type !=
- AR5K_TX_QUEUE_INACTIVE; queue++) {
-
- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
- return -EINVAL;
- }
- break;
- case AR5K_TX_QUEUE_UAPSD:
- queue = AR5K_TX_QUEUE_ID_UAPSD;
- break;
- case AR5K_TX_QUEUE_BEACON:
- queue = AR5K_TX_QUEUE_ID_BEACON;
- break;
- case AR5K_TX_QUEUE_CAB:
- queue = AR5K_TX_QUEUE_ID_CAB;
- break;
- case AR5K_TX_QUEUE_XR_DATA:
- if (ah->ah_version != AR5K_AR5212)
- ATH5K_ERR(ah->ah_sc,
- "XR data queues only supported in"
- " 5212!\n");
- queue = AR5K_TX_QUEUE_ID_XR_DATA;
- break;
- default:
- return -EINVAL;
- }
- }
-
- /*
- * Setup internal queue structure
- */
- memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
- ah->ah_txq[queue].tqi_type = queue_type;
-
- if (queue_info != NULL) {
- queue_info->tqi_type = queue_type;
- ret = ath5k_hw_setup_tx_queueprops(ah, queue, queue_info);
- if (ret)
- return ret;
- }
- /*
- * We use ah_txq_status to hold a temp value for
- * the Secondary interrupt mask registers on 5211+
- * check out ath5k_hw_reset_tx_queue
- */
- AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
-
- return queue;
-}
-
-/*
- * Setup a transmit queue
- */
-int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue,
- const struct ath5k_txq_info *queue_info)
-{
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return -EIO;
-
- memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
-
- /*XXX: Is this supported on 5210 ?*/
- if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
- ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
- (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
- queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
- ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
-
- return 0;
-}
-
-/*
- * Get properties for a specific transmit queue
- */
-int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
- struct ath5k_txq_info *queue_info)
-{
- ATH5K_TRACE(ah->ah_sc);
- memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
- return 0;
-}
-
-/*
- * Set a transmit queue inactive
- */
-void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
- return;
-
- /* This queue will be skipped in further operations */
- ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
- /*For SIMR setup*/
- AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
-}
-
-/*
- * Set DFS params for a transmit queue
- */
-int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
- u32 cw_min, cw_max, retry_lg, retry_sh;
- struct ath5k_txq_info *tq = &ah->ah_txq[queue];
-
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- tq = &ah->ah_txq[queue];
-
- if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return 0;
-
- if (ah->ah_version == AR5K_AR5210) {
- /* Only handle data queues, others will be ignored */
- if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
- return 0;
-
- /* Set Slot time */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
- AR5K_SLOT_TIME);
- /* Set ACK_CTS timeout */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
- AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
- /* Set Transmit Latency */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_TRANSMIT_LATENCY_TURBO :
- AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
- /* Set IFS0 */
- if (ah->ah_turbo)
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME_TURBO) <<
- AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
- AR5K_IFS0);
- else
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
- AR5K_INIT_SIFS, AR5K_IFS0);
-
- /* Set IFS1 */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
- AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
- /* Set AR5K_PHY_SETTLING */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
- | 0x38 :
- (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
- | 0x1C,
- AR5K_PHY_SETTLING);
- /* Set Frame Control Register */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
- AR5K_PHY_TURBO_SHORT | 0x2020) :
- (AR5K_PHY_FRAME_CTL_INI | 0x1020),
- AR5K_PHY_FRAME_CTL_5210);
- }
-
- /*
- * Calculate cwmin/max by channel mode
- */
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
- ah->ah_aifs = AR5K_TUNE_AIFS;
- /*XR is only supported on 5212*/
- if (IS_CHAN_XR(ah->ah_current_channel) &&
- ah->ah_version == AR5K_AR5212) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
- ah->ah_aifs = AR5K_TUNE_AIFS_XR;
- /*B mode is not supported on 5210*/
- } else if (IS_CHAN_B(ah->ah_current_channel) &&
- ah->ah_version != AR5K_AR5210) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
- ah->ah_aifs = AR5K_TUNE_AIFS_11B;
- }
-
- cw_min = 1;
- while (cw_min < ah->ah_cw_min)
- cw_min = (cw_min << 1) | 1;
-
- cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
- ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
- cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
- ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
-
- /*
- * Calculate and set retry limits
- */
- if (ah->ah_software_retry) {
- /* XXX Need to test this */
- retry_lg = ah->ah_limit_tx_retries;
- retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
- AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
- } else {
- retry_lg = AR5K_INIT_LG_RETRY;
- retry_sh = AR5K_INIT_SH_RETRY;
- }
-
- /*No QCU/DCU [5210]*/
- if (ah->ah_version == AR5K_AR5210) {
- ath5k_hw_reg_write(ah,
- (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
- | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
- AR5K_NODCU_RETRY_LMT_SLG_RETRY)
- | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
- AR5K_NODCU_RETRY_LMT_SSH_RETRY)
- | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
- | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
- AR5K_NODCU_RETRY_LMT);
- } else {
- /*QCU/DCU [5211+]*/
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
- AR5K_DCU_RETRY_LMT_SLG_RETRY) |
- AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
- AR5K_DCU_RETRY_LMT_SSH_RETRY) |
- AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
- AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
- AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
-
- /*===Rest is also for QCU/DCU only [5211+]===*/
-
- /*
- * Set initial content window (cw_min/cw_max)
- * and arbitrated interframe space (aifs)...
- */
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
- AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
- AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
- AR5K_DCU_LCL_IFS_AIFS),
- AR5K_QUEUE_DFS_LOCAL_IFS(queue));
-
- /*
- * Set misc registers
- */
- ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
- AR5K_QUEUE_MISC(queue));
-
- if (tq->tqi_cbr_period) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
- AR5K_QCU_CBRCFG_INTVAL) |
- AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
- AR5K_QCU_CBRCFG_ORN_THRES),
- AR5K_QUEUE_CBRCFG(queue));
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_CBR);
- if (tq->tqi_cbr_overflow_limit)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_CBR_THRES_ENABLE);
- }
-
- if (tq->tqi_ready_time)
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
- AR5K_QCU_RDYTIMECFG_INTVAL) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
-
- if (tq->tqi_burst_time) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
- AR5K_DCU_CHAN_TIME_DUR) |
- AR5K_DCU_CHAN_TIME_ENABLE,
- AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_RDY_VEOL_POLICY);
- }
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
- AR5K_QUEUE_DFS_MISC(queue));
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
- AR5K_QUEUE_DFS_MISC(queue));
-
- /*
- * Set registers by queue type
- */
- switch (tq->tqi_type) {
- case AR5K_TX_QUEUE_BEACON:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_DBA_GT |
- AR5K_QCU_MISC_CBREXP_BCN |
- AR5K_QCU_MISC_BCN_ENABLE);
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
- AR5K_DCU_MISC_ARBLOCK_CTL_S) |
- AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
- AR5K_DCU_MISC_BCN_ENABLE);
-
- ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
- (AR5K_TUNE_SW_BEACON_RESP -
- AR5K_TUNE_DMA_BEACON_RESP) -
- AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
- break;
-
- case AR5K_TX_QUEUE_CAB:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_DBA_GT |
- AR5K_QCU_MISC_CBREXP |
- AR5K_QCU_MISC_CBREXP_BCN);
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
- AR5K_DCU_MISC_ARBLOCK_CTL_S));
- break;
-
- case AR5K_TX_QUEUE_UAPSD:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_CBREXP);
- break;
-
- case AR5K_TX_QUEUE_DATA:
- default:
- break;
- }
-
- /*
- * Enable interrupts for this tx queue
- * in the secondary interrupt mask registers
- */
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
-
-
- /* Update secondary interrupt mask registers */
- ah->ah_txq_imr_txok &= ah->ah_txq_status;
- ah->ah_txq_imr_txerr &= ah->ah_txq_status;
- ah->ah_txq_imr_txurn &= ah->ah_txq_status;
- ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
- ah->ah_txq_imr_txeol &= ah->ah_txq_status;
-
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
- AR5K_SIMR0_QCU_TXOK) |
- AR5K_REG_SM(ah->ah_txq_imr_txdesc,
- AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
- AR5K_SIMR1_QCU_TXERR) |
- AR5K_REG_SM(ah->ah_txq_imr_txeol,
- AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
- AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
- }
-
- return 0;
-}
-
-/*
- * Get number of pending frames
- * for a specific queue [5211+]
- */
-u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) {
- ATH5K_TRACE(ah->ah_sc);
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /* Return if queue is declared inactive */
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return false;
-
- /* XXX: How about AR5K_CFG_TXCNT ? */
- if (ah->ah_version == AR5K_AR5210)
- return false;
-
- return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
-}
-
-/*
- * Set slot time
- */
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
- return -EINVAL;
-
- if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
- ah->ah_turbo), AR5K_SLOT_TIME);
- else
- ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
-
- return 0;
-}
-
-/*
- * Get slot time
- */
-unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (ah->ah_version == AR5K_AR5210)
- return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
- AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
- else
- return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
-}
-
-
-/******************************\
- Hardware Descriptor Functions
-\******************************/
-
-/*
- * TX Descriptor
- */
-
-/*
- * Initialize the 2-word tx descriptor on 5210/5211
- */
-static int
-ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
- unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
- unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
- unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
- unsigned int rtscts_rate, unsigned int rtscts_duration)
-{
- u32 frame_type;
- struct ath5k_hw_2w_tx_ctl *tx_ctl;
- unsigned int frame_len;
-
- tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
-
- /*
- * Validate input
- * - Zero retries don't make sense.
- * - A zero rate will put the HW into a mode where it continously sends
- * noise on the channel, so it is important to avoid this.
- */
- if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
- WARN_ON(1);
- return -EINVAL;
- }
- if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
- WARN_ON(1);
- return -EINVAL;
- }
-
- /* Clear descriptor */
- memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
-
- /* Setup control descriptor */
-
- /* Verify and set frame length */
-
- /* remove padding we might have added before */
- frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
-
- if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
- return -EINVAL;
-
- tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
-
- /* Verify and set buffer length */
-
- /* NB: beacon's BufLen must be a multiple of 4 bytes */
- if(type == AR5K_PKT_TYPE_BEACON)
- pkt_len = roundup(pkt_len, 4);
-
- if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
- return -EINVAL;
-
- tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
-
- /*
- * Verify and set header length
- * XXX: I only found that on 5210 code, does it work on 5211 ?
- */
- if (ah->ah_version == AR5K_AR5210) {
- if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
- return -EINVAL;
- tx_ctl->tx_control_0 |=
- AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
- }
-
- /*Diferences between 5210-5211*/
- if (ah->ah_version == AR5K_AR5210) {
- switch (type) {
- case AR5K_PKT_TYPE_BEACON:
- case AR5K_PKT_TYPE_PROBE_RESP:
- frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
- case AR5K_PKT_TYPE_PIFS:
- frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
- default:
- frame_type = type /*<< 2 ?*/;
- }
-
- tx_ctl->tx_control_0 |=
- AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
- AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
- } else {
- tx_ctl->tx_control_0 |=
- AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
- AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
- tx_ctl->tx_control_1 |=
- AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
- }
-#define _TX_FLAGS(_c, _flag) \
- if (flags & AR5K_TXDESC_##_flag) \
- tx_ctl->tx_control_##_c |= \
- AR5K_2W_TX_DESC_CTL##_c##_##_flag
-
- _TX_FLAGS(0, CLRDMASK);
- _TX_FLAGS(0, VEOL);
- _TX_FLAGS(0, INTREQ);
- _TX_FLAGS(0, RTSENA);
- _TX_FLAGS(1, NOACK);
-
-#undef _TX_FLAGS
-
- /*
- * WEP crap
- */
- if (key_index != AR5K_TXKEYIX_INVALID) {
- tx_ctl->tx_control_0 |=
- AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
- tx_ctl->tx_control_1 |=
- AR5K_REG_SM(key_index,
- AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
- }
-
- /*
- * RTS/CTS Duration [5210 ?]
- */
- if ((ah->ah_version == AR5K_AR5210) &&
- (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
- tx_ctl->tx_control_1 |= rtscts_duration &
- AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
-
- return 0;
-}
-
-/*
- * Initialize the 4-word tx descriptor on 5212
- */
-static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
- struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
- enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
- unsigned int tx_tries0, unsigned int key_index,
- unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
- unsigned int rtscts_duration)
-{
- struct ath5k_hw_4w_tx_ctl *tx_ctl;
- unsigned int frame_len;
-
- ATH5K_TRACE(ah->ah_sc);
- tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
- /*
- * Validate input
- * - Zero retries don't make sense.
- * - A zero rate will put the HW into a mode where it continously sends
- * noise on the channel, so it is important to avoid this.
- */
- if (unlikely(tx_tries0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero retries\n");
- WARN_ON(1);
- return -EINVAL;
- }
- if (unlikely(tx_rate0 == 0)) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
- WARN_ON(1);
- return -EINVAL;
- }
-
- /* Clear descriptor */
- memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
-
- /* Setup control descriptor */
-
- /* Verify and set frame length */
-
- /* remove padding we might have added before */
- frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
-
- if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
- return -EINVAL;
-
- tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
-
- /* Verify and set buffer length */
-
- /* NB: beacon's BufLen must be a multiple of 4 bytes */
- if(type == AR5K_PKT_TYPE_BEACON)
- pkt_len = roundup(pkt_len, 4);
-
- if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
- return -EINVAL;
-
- tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
-
- tx_ctl->tx_control_0 |=
- AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
- AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
- tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
- AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
- tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
- tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-
-#define _TX_FLAGS(_c, _flag) \
- if (flags & AR5K_TXDESC_##_flag) \
- tx_ctl->tx_control_##_c |= \
- AR5K_4W_TX_DESC_CTL##_c##_##_flag
-
- _TX_FLAGS(0, CLRDMASK);
- _TX_FLAGS(0, VEOL);
- _TX_FLAGS(0, INTREQ);
- _TX_FLAGS(0, RTSENA);
- _TX_FLAGS(0, CTSENA);
- _TX_FLAGS(1, NOACK);
-
-#undef _TX_FLAGS
-
- /*
- * WEP crap
- */
- if (key_index != AR5K_TXKEYIX_INVALID) {
- tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
- tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
- AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
- }
-
- /*
- * RTS/CTS
- */
- if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
- if ((flags & AR5K_TXDESC_RTSENA) &&
- (flags & AR5K_TXDESC_CTSENA))
- return -EINVAL;
- tx_ctl->tx_control_2 |= rtscts_duration &
- AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
- tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
- AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
- }
-
- return 0;
-}
-
-/*
- * Initialize a 4-word multirate tx descriptor on 5212
- */
-static int
-ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
- unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
- unsigned int tx_rate3, u_int tx_tries3)
-{
- struct ath5k_hw_4w_tx_ctl *tx_ctl;
-
- /*
- * Rates can be 0 as long as the retry count is 0 too.
- * A zero rate and nonzero retry count will put the HW into a mode where
- * it continously sends noise on the channel, so it is important to
- * avoid this.
- */
- if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
- (tx_rate2 == 0 && tx_tries2 != 0) ||
- (tx_rate3 == 0 && tx_tries3 != 0))) {
- ATH5K_ERR(ah->ah_sc, "zero rate\n");
- WARN_ON(1);
- return -EINVAL;
- }
-
- if (ah->ah_version == AR5K_AR5212) {
- tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
-#define _XTX_TRIES(_n) \
- if (tx_tries##_n) { \
- tx_ctl->tx_control_2 |= \
- AR5K_REG_SM(tx_tries##_n, \
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
- tx_ctl->tx_control_3 |= \
- AR5K_REG_SM(tx_rate##_n, \
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
- }
-
- _XTX_TRIES(1);
- _XTX_TRIES(2);
- _XTX_TRIES(3);
-
-#undef _XTX_TRIES
-
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Proccess the tx status descriptor on 5210/5211
- */
-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc, struct ath5k_tx_status *ts)
-{
- struct ath5k_hw_2w_tx_ctl *tx_ctl;
- struct ath5k_hw_tx_status *tx_status;
-
- ATH5K_TRACE(ah->ah_sc);
-
- tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
- tx_status = &desc->ud.ds_tx5210.tx_stat;
-
- /* No frame has been send or error */
- if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
- return -EINPROGRESS;
-
- /*
- * Get descriptor status
- */
- ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
- ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
- ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
- /*TODO: ts->ts_virtcol + test*/
- ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_SEQ_NUM);
- ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
- ts->ts_antenna = 1;
- ts->ts_status = 0;
- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
- AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
-
- if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
- if (tx_status->tx_status_0 &
- AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
- ts->ts_status |= AR5K_TXERR_XRETRY;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
- ts->ts_status |= AR5K_TXERR_FIFO;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
- ts->ts_status |= AR5K_TXERR_FILT;
- }
-
- return 0;
-}
-
-/*
- * Proccess a tx descriptor on 5212
- */
-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc, struct ath5k_tx_status *ts)
-{
- struct ath5k_hw_4w_tx_ctl *tx_ctl;
- struct ath5k_hw_tx_status *tx_status;
-
- ATH5K_TRACE(ah->ah_sc);
-
- tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
- tx_status = &desc->ud.ds_tx5212.tx_stat;
-
- /* No frame has been send or error */
- if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
- return -EINPROGRESS;
-
- /*
- * Get descriptor status
- */
- ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
- ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
- ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
- ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_SEQ_NUM);
- ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
- ts->ts_antenna = (tx_status->tx_status_1 &
- AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
- ts->ts_status = 0;
-
- switch (AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
- case 0:
- ts->ts_rate = tx_ctl->tx_control_3 &
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
- break;
- case 1:
- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
- break;
- case 2:
- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
- break;
- case 3:
- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
- break;
- }
-
- if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
- if (tx_status->tx_status_0 &
- AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
- ts->ts_status |= AR5K_TXERR_XRETRY;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
- ts->ts_status |= AR5K_TXERR_FIFO;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
- ts->ts_status |= AR5K_TXERR_FILT;
- }
-
- return 0;
-}
-
-/*
- * RX Descriptor
- */
-
-/*
- * Initialize an rx descriptor
- */
-int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
- u32 size, unsigned int flags)
-{
- struct ath5k_hw_rx_ctl *rx_ctl;
-
- ATH5K_TRACE(ah->ah_sc);
- rx_ctl = &desc->ud.ds_rx.rx_ctl;
-
- /*
- * Clear the descriptor
- * If we don't clean the status descriptor,
- * while scanning we get too many results,
- * most of them virtual, after some secs
- * of scanning system hangs. M.F.
- */
- memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
-
- /* Setup descriptor */
- rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
- if (unlikely(rx_ctl->rx_control_1 != size))
- return -EINVAL;
-
- if (flags & AR5K_RXDESC_INTREQ)
- rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
-
- return 0;
-}
-
-/*
- * Proccess the rx status descriptor on 5210/5211
- */
-static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc, struct ath5k_rx_status *rs)
-{
- struct ath5k_hw_rx_status *rx_status;
-
- rx_status = &desc->ud.ds_rx.u.rx_stat;
-
- /* No frame received / not ready */
- if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
- == 0))
- return -EINPROGRESS;
-
- /*
- * Frame receive status
- */
- rs->rs_datalen = rx_status->rx_status_0 &
- AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
- rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
- rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
- rs->rs_antenna = rx_status->rx_status_0 &
- AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
- rs->rs_more = rx_status->rx_status_0 &
- AR5K_5210_RX_DESC_STATUS0_MORE;
- /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
- rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
- rs->rs_status = 0;
- rs->rs_phyerr = 0;
-
- /*
- * Key table status
- */
- if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
- rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
- else
- rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
- /*
- * Receive/descriptor errors
- */
- if ((rx_status->rx_status_1 &
- AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
- if (rx_status->rx_status_1 &
- AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
- rs->rs_status |= AR5K_RXERR_CRC;
-
- if (rx_status->rx_status_1 &
- AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
- rs->rs_status |= AR5K_RXERR_FIFO;
-
- if (rx_status->rx_status_1 &
- AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
- rs->rs_status |= AR5K_RXERR_PHY;
- rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
- }
-
- if (rx_status->rx_status_1 &
- AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
- rs->rs_status |= AR5K_RXERR_DECRYPT;
- }
-
- return 0;
-}
-
-/*
- * Proccess the rx status descriptor on 5212
- */
-static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc, struct ath5k_rx_status *rs)
-{
- struct ath5k_hw_rx_status *rx_status;
- struct ath5k_hw_rx_error *rx_err;
-
- ATH5K_TRACE(ah->ah_sc);
- rx_status = &desc->ud.ds_rx.u.rx_stat;
-
- /* Overlay on error */
- rx_err = &desc->ud.ds_rx.u.rx_err;
-
- /* No frame received / not ready */
- if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
- == 0))
- return -EINPROGRESS;
-
- /*
- * Frame receive status
- */
- rs->rs_datalen = rx_status->rx_status_0 &
- AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
- rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
- rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
- rs->rs_antenna = rx_status->rx_status_0 &
- AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
- rs->rs_more = rx_status->rx_status_0 &
- AR5K_5212_RX_DESC_STATUS0_MORE;
- rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
- rs->rs_status = 0;
- rs->rs_phyerr = 0;
-
- /*
- * Key table status
- */
- if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
- rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
- else
- rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
- /*
- * Receive/descriptor errors
- */
- if ((rx_status->rx_status_1 &
- AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
- if (rx_status->rx_status_1 &
- AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
- rs->rs_status |= AR5K_RXERR_CRC;
-
- if (rx_status->rx_status_1 &
- AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
- rs->rs_status |= AR5K_RXERR_PHY;
- rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
- AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
- }
-
- if (rx_status->rx_status_1 &
- AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
- rs->rs_status |= AR5K_RXERR_DECRYPT;
-
- if (rx_status->rx_status_1 &
- AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
- rs->rs_status |= AR5K_RXERR_MIC;
- }
-
- return 0;
-}
-
-
-/****************\
- GPIO Functions
-\****************/
-
-/*
- * Set led state
- */
-void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
-{
- u32 led;
- /*5210 has different led mode handling*/
- u32 led_5210;
-
- ATH5K_TRACE(ah->ah_sc);
-
- /*Reset led status*/
- if (ah->ah_version != AR5K_AR5210)
- AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED);
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
-
- /*
- * Some blinking values, define at your wish
- */
- switch (state) {
- case AR5K_LED_SCAN:
- case AR5K_LED_AUTH:
- led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
- led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
- break;
-
- case AR5K_LED_INIT:
- led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
- led_5210 = AR5K_PCICFG_LED_PEND;
- break;
-
- case AR5K_LED_ASSOC:
- case AR5K_LED_RUN:
- led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
- led_5210 = AR5K_PCICFG_LED_ASSOC;
- break;
-
- default:
- led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
- led_5210 = AR5K_PCICFG_LED_PEND;
- break;
- }
-
- /*Write new status to the register*/
- if (ah->ah_version != AR5K_AR5210)
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
- else
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
-}
-
-/*
- * Set GPIO outputs
- */
-int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (gpio > AR5K_NUM_GPIO)
- return -EINVAL;
-
- ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
- AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
-
- return 0;
-}
-
-/*
- * Set GPIO inputs
- */
-int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (gpio > AR5K_NUM_GPIO)
- return -EINVAL;
-
- ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
- AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
-
- return 0;
-}
-
-/*
- * Get GPIO state
- */
-u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
-{
- ATH5K_TRACE(ah->ah_sc);
- if (gpio > AR5K_NUM_GPIO)
- return 0xffffffff;
-
- /* GPIO input magic */
- return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
- 0x1;
-}
-
-/*
- * Set GPIO state
- */
-int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
-{
- u32 data;
- ATH5K_TRACE(ah->ah_sc);
-
- if (gpio > AR5K_NUM_GPIO)
- return -EINVAL;
-
- /* GPIO output magic */
- data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
- data &= ~(1 << gpio);
- data |= (val & 1) << gpio;
-
- ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
-
- return 0;
-}
-
-/*
- * Initialize the GPIO interrupt (RFKill switch)
- */
-void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
- u32 interrupt_level)
-{
- u32 data;
-
- ATH5K_TRACE(ah->ah_sc);
- if (gpio > AR5K_NUM_GPIO)
- return;
-
- /*
- * Set the GPIO interrupt
- */
- data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
- ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
- AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
- (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
-
- ath5k_hw_reg_write(ah, interrupt_level ? data :
- (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
-
- ah->ah_imr |= AR5K_IMR_GPIO;
-
- /* Enable GPIO interrupts */
- AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
-}
-
-
-
-
-/****************\
- Misc functions
-\****************/
-
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
- enum ath5k_capability_type cap_type,
- u32 capability, u32 *result)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- switch (cap_type) {
- case AR5K_CAP_NUM_TXQUEUES:
- if (result) {
- if (ah->ah_version == AR5K_AR5210)
- *result = AR5K_NUM_TX_QUEUES_NOQCU;
- else
- *result = AR5K_NUM_TX_QUEUES;
- goto yes;
- }
- case AR5K_CAP_VEOL:
- goto yes;
- case AR5K_CAP_COMPRESSION:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_BURST:
- goto yes;
- case AR5K_CAP_TPC:
- goto yes;
- case AR5K_CAP_BSSIDMASK:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- case AR5K_CAP_XR:
- if (ah->ah_version == AR5K_AR5212)
- goto yes;
- else
- goto no;
- default:
- goto no;
- }
-
-no:
- return -EINVAL;
-yes:
- return 0;
-}
-
-static int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
- u16 assoc_id)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- if (ah->ah_version == AR5K_AR5210) {
- AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
- AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
- return 0;
- }
-
- return -EIO;
-}
-
-static int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
-{
- ATH5K_TRACE(ah->ah_sc);
-
- if (ah->ah_version == AR5K_AR5210) {
- AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
- AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
- return 0;
- }
-
- return -EIO;
-}
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
index 2806b21bf90..ea2e1a20b49 100644
--- a/drivers/net/wireless/ath5k/initvals.c
+++ b/drivers/net/wireless/ath5k/initvals.c
@@ -1,9 +1,9 @@
/*
* Initial register settings functions
*
- * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,13 +20,9 @@
*/
#include "ath5k.h"
-#include "base.h"
#include "reg.h"
-
-/*
- * MAC/PHY REGISTERS
- */
-
+#include "debug.h"
+#include "base.h"
/*
* Mode-independent initial register writes
@@ -65,10 +61,10 @@ static const struct ath5k_ini ar5210_ini[] = {
{ AR5K_TXCFG, AR5K_DMASIZE_128B },
{ AR5K_RXCFG, AR5K_DMASIZE_128B },
{ AR5K_CFG, AR5K_INIT_CFG },
- { AR5K_TOPS, AR5K_INIT_TOPS },
- { AR5K_RXNOFRM, AR5K_INIT_RXNOFRM },
- { AR5K_RPGTO, AR5K_INIT_RPGTO },
- { AR5K_TXNOFRM, AR5K_INIT_TXNOFRM },
+ { AR5K_TOPS, 8 },
+ { AR5K_RXNOFRM, 8 },
+ { AR5K_RPGTO, 0 },
+ { AR5K_TXNOFRM, 0 },
{ AR5K_SFR, 0 },
{ AR5K_MIBC, 0 },
{ AR5K_MISC, 0 },
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
new file mode 100644
index 00000000000..a47df9a24aa
--- /dev/null
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -0,0 +1,1014 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*********************************\
+* Protocol Control Unit Functions *
+\*********************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*******************\
+* Generic functions *
+\*******************/
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Initialize PCU for the various operating modes (AP/STA etc)
+ *
+ * NOTE: ah->ah_op_mode must be set before calling this.
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
+{
+ u32 pcu_reg, beacon_reg, low_id, high_id;
+
+ pcu_reg = 0;
+ beacon_reg = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ switch (ah->ah_op_mode) {
+ case NL80211_IFTYPE_ADHOC:
+ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ beacon_reg |= AR5K_BCR_ADHOC;
+ break;
+
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ beacon_reg |= AR5K_BCR_AP;
+ break;
+
+ case NL80211_IFTYPE_STATION:
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_PWR_SV : 0);
+ case NL80211_IFTYPE_MONITOR:
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * Set PCU registers
+ */
+ low_id = AR5K_LOW_ID(ah->ah_sta_id);
+ high_id = AR5K_HIGH_ID(ah->ah_sta_id);
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ /*
+ * Set Beacon Control Register on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_update - Update mib counters (mac layer statistics)
+ *
+ * @ah: The &struct ath5k_hw
+ * @stats: The &struct ieee80211_low_level_stats we use to track
+ * statistics on the driver
+ *
+ * Reads MIB counters from PCU and updates sw statistics. Must be
+ * called after a MIB interrupt.
+ */
+void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
+ struct ieee80211_low_level_stats *stats)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Read-And-Clear */
+ stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
+ stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
+ stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
+ stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
+
+ /* XXX: Should we use this to track beacon count ?
+ * -we read it anyway to clear the register */
+ ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
+
+ /* Reset profile count registers on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
+ }
+}
+
+/**
+ * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ *
+ * @ah: The &struct ath5k_hw
+ * @high: Flag to determine if we want to use high transmition rate
+ * for ACKs or not
+ *
+ * If high flag is set, we tell hw to use a set of control rates based on
+ * the current transmition rate (check out control_rates array inside reset.c).
+ * If not hw just uses the lowest rate available for the current modulation
+ * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
+ */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
+{
+ if (ah->ah_version != AR5K_AR5212)
+ return;
+ else {
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+ if (high)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ }
+}
+
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
+/**
+ * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+
+/****************\
+* BSSID handling *
+\****************/
+
+/**
+ * ath5k_hw_get_lladdr - Get station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Initialize ah->ah_sta_id using the mac address provided
+ * (just a memcpy).
+ *
+ * TODO: Remove it once we merge ath5k_softc and ath5k_hw
+ */
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ memcpy(mac, ah->ah_sta_id, ETH_ALEN);
+}
+
+/**
+ * ath5k_hw_set_lladdr - Set station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Set station id on hw using the provided mac address
+ */
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
+{
+ u32 low_id, high_id;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Set new station ID */
+ memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_associd - Set BSSID for association
+ *
+ * @ah: The &struct ath5k_hw
+ * @bssid: BSSID
+ * @assoc_id: Assoc id
+ *
+ * Sets the BSSID which trigers the "SME Join" operation
+ */
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+{
+ u32 low_id, high_id;
+ u16 tim_offset = 0;
+
+ /*
+ * Set simple BSSID mask on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
+ }
+
+ /*
+ * Set BSSID which triggers the "SME Join" operation
+ */
+ low_id = AR5K_LOW_ID(bssid);
+ high_id = AR5K_HIGH_ID(bssid);
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
+ ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
+ AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
+
+ if (assoc_id == 0) {
+ ath5k_hw_disable_pspoll(ah);
+ return;
+ }
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
+ tim_offset ? tim_offset + 4 : 0);
+
+ ath5k_hw_enable_pspoll(ah, NULL, 0);
+}
+
+/**
+ * ath5k_hw_set_bssid_mask - filter out bssids we listen
+ *
+ * @ah: the &struct ath5k_hw
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
+ *
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode and AP mode with a single
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
+ * accept frames for all BSSes and so we tweak some bits of our mac address
+ * in order to have multiple BSSes.
+ *
+ * NOTE: This is a simple filter and does *not* filter out all
+ * relevant frames. Some frames that are not for us might get ACKed from us
+ * by PCU because they just match the mask.
+ *
+ * When handling multiple BSSes you can get the BSSID mask by computing the
+ * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
+ *
+ * When you do this you are essentially computing the common bits of all your
+ * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
+ * the MAC address to obtain the relevant bits and compare the result with
+ * (frame's BSSID & mask) to see if they match.
+ */
+/*
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ * \
+ * MAC: 0001 |
+ * BSSID-01: 0100 | --> Belongs to us
+ * BSSID-02: 1001 |
+ * /
+ * -------------------
+ * BSSID-03: 0110 | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ * On loop iteration for BSSID-01:
+ * ~(0001 ^ 0100) -> ~(0101)
+ * -> 1010
+ * bssid_mask = 1010
+ *
+ * On loop iteration for BSSID-02:
+ * bssid_mask &= ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(1001)
+ * bssid_mask = (1010) & (0110)
+ * bssid_mask = 0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01: 0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is beacuse the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ * --> allow = (0010) == 0000 ? 1 : 0;
+ * --> allow = 0
+ *
+ * Lets now test a frame that should work:
+ *
+ * IFRAME-02: 0001 (we should allow)
+ *
+ * allow = (0001 & 1010) == 1010
+ *
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
+ * --> allow = (0010) == (0010)
+ * --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03: 0100 --> allowed
+ * IFRAME-04: 1001 --> allowed
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
+ *
+ */
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
+{
+ u32 low_id, high_id;
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ low_id = AR5K_LOW_ID(mask);
+ high_id = AR5K_HIGH_ID(mask);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
+
+ return 0;
+ }
+
+ return -EIO;
+}
+
+
+/************\
+* RX Control *
+\************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ * TODO: Init ANI here
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ *
+ * TODO: Detach ANI here
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter
+ */
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /* Set the multicat filter */
+ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
+ ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
+}
+
+/*
+ * Set multicast filter by index
+ */
+int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
+{
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (index >= 64)
+ return -EINVAL;
+ else if (index >= 32)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
+ (1 << (index - 32)));
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+ return 0;
+}
+
+/*
+ * Clear Multicast filter by index
+ */
+int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
+{
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (index >= 64)
+ return -EINVAL;
+ else if (index >= 32)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
+ (1 << (index - 32)));
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_rx_filter - Get current rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the RX filter by reading rx filter and
+ * phy error filter registers. RX filter is used
+ * to set the allowed frame types that PCU will accept
+ * and pass to the driver. For a list of frame types
+ * check out reg.h.
+ */
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
+{
+ u32 data, filter = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+ filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
+
+ /*Radar detection for 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
+
+ if (data & AR5K_PHY_ERR_FIL_RADAR)
+ filter |= AR5K_RX_FILTER_RADARERR;
+ if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
+ filter |= AR5K_RX_FILTER_PHYERR;
+ }
+
+ return filter;
+}
+
+/**
+ * ath5k_hw_set_rx_filter - Set rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ * @filter: RX filter mask (see reg.h)
+ *
+ * Sets RX filter register and also handles PHY error filter
+ * register on 5212 and newer chips so that we have proper PHY
+ * error reporting.
+ */
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
+{
+ u32 data = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Set PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ if (filter & AR5K_RX_FILTER_RADARERR)
+ data |= AR5K_PHY_ERR_FIL_RADAR;
+ if (filter & AR5K_RX_FILTER_PHYERR)
+ data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
+ }
+
+ /*
+ * The AR5210 uses promiscous mode to detect radar activity
+ */
+ if (ah->ah_version == AR5K_AR5210 &&
+ (filter & AR5K_RX_FILTER_RADARERR)) {
+ filter &= ~AR5K_RX_FILTER_RADARERR;
+ filter |= AR5K_RX_FILTER_PROM;
+ }
+
+ /*Zero length DMA*/
+ if (data)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+
+ /*Write RX Filter register*/
+ ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
+
+ /*Write PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
+
+}
+
+
+/****************\
+* Beacon control *
+\****************/
+
+/**
+ * ath5k_hw_get_tsf32 - Get a 32bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns lower 32 bits of current TSF
+ */
+u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+}
+
+/**
+ * ath5k_hw_get_tsf64 - Get the full 64bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the current TSF
+ */
+u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
+{
+ u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ ATH5K_TRACE(ah->ah_sc);
+
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
+}
+
+/**
+ * ath5k_hw_reset_tsf - Force a TSF reset
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Forces a TSF reset on PCU
+ */
+void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
+{
+ u32 val;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
+
+ /*
+ * Each write to the RESET_TSF bit toggles a hardware internal
+ * signal to reset TSF, but if left high it will cause a TSF reset
+ * on the next chip reset as well. Thus we always write the value
+ * twice to clear the signal.
+ */
+ ath5k_hw_reg_write(ah, val, AR5K_BEACON);
+ ath5k_hw_reg_write(ah, val, AR5K_BEACON);
+}
+
+/*
+ * Initialize beacon timers
+ */
+void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
+{
+ u32 timer1, timer2, timer3;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Set the additional timers by mode
+ */
+ switch (ah->ah_op_mode) {
+ case NL80211_IFTYPE_STATION:
+ if (ah->ah_version == AR5K_AR5210) {
+ timer1 = 0xffffffff;
+ timer2 = 0xffffffff;
+ } else {
+ timer1 = 0x0000ffff;
+ timer2 = 0x0007ffff;
+ }
+ break;
+
+ default:
+ timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
+ timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
+ }
+
+ timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
+
+ /*
+ * Set the beacon register and enable all timers.
+ * (next beacon, DMA beacon, software beacon, ATIM window time)
+ */
+ ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+ ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
+ ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
+ ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
+
+ ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
+ AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
+ AR5K_BEACON);
+}
+
+#if 0
+/*
+ * Set beacon timers
+ */
+int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
+ const struct ath5k_beacon_state *state)
+{
+ u32 cfp_period, next_cfp, dtim, interval, next_beacon;
+
+ /*
+ * TODO: should be changed through *state
+ * review struct ath5k_beacon_state struct
+ *
+ * XXX: These are used for cfp period bellow, are they
+ * ok ? Is it O.K. for tsf here to be 0 or should we use
+ * get_tsf ?
+ */
+ u32 dtim_count = 0; /* XXX */
+ u32 cfp_count = 0; /* XXX */
+ u32 tsf = 0; /* XXX */
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Return on an invalid beacon state */
+ if (state->bs_interval < 1)
+ return -EINVAL;
+
+ interval = state->bs_interval;
+ dtim = state->bs_dtim_period;
+
+ /*
+ * PCF support?
+ */
+ if (state->bs_cfp_period > 0) {
+ /*
+ * Enable PCF mode and set the CFP
+ * (Contention Free Period) and timer registers
+ */
+ cfp_period = state->bs_cfp_period * state->bs_dtim_period *
+ state->bs_interval;
+ next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
+ state->bs_interval;
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_PCF);
+ ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
+ ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
+ AR5K_CFP_DUR);
+ ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
+ next_cfp)) << 3, AR5K_TIMER2);
+ } else {
+ /* Disable PCF mode */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_PCF);
+ }
+
+ /*
+ * Enable the beacon timer register
+ */
+ ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
+
+ /*
+ * Start the beacon timers
+ */
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
+ ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
+ AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
+ AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
+ AR5K_BEACON_PERIOD), AR5K_BEACON);
+
+ /*
+ * Write new beacon miss threshold, if it appears to be valid
+ * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
+ * and return if its not in range. We can test this by reading value and
+ * setting value to a largest value and seeing which values register.
+ */
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
+ state->bs_bmiss_threshold);
+
+ /*
+ * Set sleep control register
+ * XXX: Didn't find this in 5210 code but since this register
+ * exists also in ar5k's 5210 headers i leave it as common code.
+ */
+ AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
+ (state->bs_sleep_duration - 3) << 3);
+
+ /*
+ * Set enhanced sleep registers on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ if (state->bs_sleep_duration > state->bs_interval &&
+ roundup(state->bs_sleep_duration, interval) ==
+ state->bs_sleep_duration)
+ interval = state->bs_sleep_duration;
+
+ if (state->bs_sleep_duration > dtim && (dtim == 0 ||
+ roundup(state->bs_sleep_duration, dtim) ==
+ state->bs_sleep_duration))
+ dtim = state->bs_sleep_duration;
+
+ if (interval > dtim)
+ return -EINVAL;
+
+ next_beacon = interval == dtim ? state->bs_next_dtim :
+ state->bs_next_beacon;
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
+ AR5K_SLEEP0_NEXT_DTIM) |
+ AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
+ AR5K_SLEEP0_ENH_SLEEP_EN |
+ AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
+ AR5K_SLEEP1_NEXT_TIM) |
+ AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
+ AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
+ }
+
+ return 0;
+}
+
+/*
+ * Reset beacon timers
+ */
+void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Disable beacon timer
+ */
+ ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+
+ /*
+ * Disable some beacon register values
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
+ ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
+}
+
+/*
+ * Wait for beacon queue to finish
+ */
+int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
+{
+ unsigned int i;
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* 5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Wait for beaconn queue to finish by checking
+ * Control Register and Beacon Status Register.
+ */
+ for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
+ ||
+ !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
+ break;
+ udelay(10);
+ }
+
+ /* Timeout... */
+ if (i <= 0) {
+ /*
+ * Re-schedule the beacon queue
+ */
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+ AR5K_BCR);
+
+ return -EIO;
+ }
+ ret = 0;
+ } else {
+ /*5211/5212*/
+ ret = ath5k_hw_register_timeout(ah,
+ AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
+ AR5K_QCU_STS_FRMPENDCNT, 0, false);
+
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
+ return -EIO;
+ }
+
+ return ret;
+}
+#endif
+
+
+/*********************\
+* Key table functions *
+\*********************/
+
+/*
+ * Reset a key entry on the table
+ */
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+{
+ unsigned int i;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+ /*
+ * Set NULL encryption on AR5212+
+ *
+ * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
+ * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
+ *
+ * Note2: Windows driver (ndiswrapper) sets this to
+ * 0x00000714 instead of 0x00000007
+ */
+ if (ah->ah_version > AR5K_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(entry));
+
+ return 0;
+}
+
+/*
+ * Check if a table entry is valid
+ */
+int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ /* Check the validation flag at the end of the entry */
+ return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
+ AR5K_KEYTABLE_VALID;
+}
+
+/*
+ * Set a key entry on the table
+ */
+int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
+ const struct ieee80211_key_conf *key, const u8 *mac)
+{
+ unsigned int i;
+ __le32 key_v[5] = {};
+ u32 keytype;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* key->keylen comes in from mac80211 in bytes */
+
+ if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
+ return -EOPNOTSUPP;
+
+ switch (key->keylen) {
+ /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
+ case 40 / 8:
+ memcpy(&key_v[0], key->key, 5);
+ keytype = AR5K_KEYTABLE_TYPE_40;
+ break;
+
+ /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
+ case 104 / 8:
+ memcpy(&key_v[0], &key->key[0], 6);
+ memcpy(&key_v[2], &key->key[6], 6);
+ memcpy(&key_v[4], &key->key[12], 1);
+ keytype = AR5K_KEYTABLE_TYPE_104;
+ break;
+ /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
+ case 128 / 8:
+ memcpy(&key_v[0], &key->key[0], 6);
+ memcpy(&key_v[2], &key->key[6], 6);
+ memcpy(&key_v[4], &key->key[12], 4);
+ keytype = AR5K_KEYTABLE_TYPE_128;
+ break;
+
+ default:
+ return -EINVAL; /* shouldn't happen */
+ }
+
+ for (i = 0; i < ARRAY_SIZE(key_v); i++)
+ ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+ AR5K_KEYTABLE_OFF(entry, i));
+
+ ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
+
+ return ath5k_hw_set_key_lladdr(ah, entry, mac);
+}
+
+int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
+{
+ u32 low_id, high_id;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Invalid entry (key table overflow) */
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ /* MAC may be NULL if it's a broadcast key. In this case no need to
+ * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
+ if (unlikely(mac == NULL)) {
+ low_id = 0xffffffff;
+ high_id = 0xffff | AR5K_KEYTABLE_VALID;
+ } else {
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
+ }
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
+ ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
index fa0d47faf57..e43f6563e61 100644
--- a/drivers/net/wireless/ath5k/phy.c
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -1,9 +1,9 @@
/*
* PHY functions
*
- * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +19,8 @@
*
*/
+#define _ATH5K_PHY
+
#include <linux/delay.h>
#include "ath5k.h"
@@ -2122,7 +2124,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
- udelay(2300);
+ mdelay(2);
/*
* Set the channel (with AGC turned off)
@@ -2501,3 +2503,5 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power)
return ath5k_hw_txpower(ah, channel, power);
}
+
+#undef _ATH5K_PHY
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c
new file mode 100644
index 00000000000..01bf09176d2
--- /dev/null
+++ b/drivers/net/wireless/ath5k/qcu.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/********************************************\
+Queue Control Unit, DFS Control Unit Functions
+\********************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Get properties for a transmit queue
+ */
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
+ struct ath5k_txq_info *queue_info)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
+ return 0;
+}
+
+/*
+ * Set properties for a transmit queue
+ */
+int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
+ const struct ath5k_txq_info *queue_info)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+
+ /*XXX: Is this supported on 5210 ?*/
+ if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
+ (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
+ queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+
+ return 0;
+}
+
+/*
+ * Initialize a transmit queue
+ */
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info)
+{
+ unsigned int queue;
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Get queue by type
+ */
+ /*5210 only has 2 queues*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (queue_type) {
+ case AR5K_TX_QUEUE_DATA:
+ queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (queue_type) {
+ case AR5K_TX_QUEUE_DATA:
+ for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
+ ah->ah_txq[queue].tqi_type !=
+ AR5K_TX_QUEUE_INACTIVE; queue++) {
+
+ if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
+ return -EINVAL;
+ }
+ break;
+ case AR5K_TX_QUEUE_UAPSD:
+ queue = AR5K_TX_QUEUE_ID_UAPSD;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ queue = AR5K_TX_QUEUE_ID_BEACON;
+ break;
+ case AR5K_TX_QUEUE_CAB:
+ queue = AR5K_TX_QUEUE_ID_CAB;
+ break;
+ case AR5K_TX_QUEUE_XR_DATA:
+ if (ah->ah_version != AR5K_AR5212)
+ ATH5K_ERR(ah->ah_sc,
+ "XR data queues only supported in"
+ " 5212!\n");
+ queue = AR5K_TX_QUEUE_ID_XR_DATA;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Setup internal queue structure
+ */
+ memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
+ ah->ah_txq[queue].tqi_type = queue_type;
+
+ if (queue_info != NULL) {
+ queue_info->tqi_type = queue_type;
+ ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * We use ah_txq_status to hold a temp value for
+ * the Secondary interrupt mask registers on 5211+
+ * check out ath5k_hw_reset_tx_queue
+ */
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
+
+ return queue;
+}
+
+/*
+ * Get number of pending frames
+ * for a specific queue [5211+]
+ */
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return false;
+
+ /* XXX: How about AR5K_CFG_TXCNT ? */
+ if (ah->ah_version == AR5K_AR5210)
+ return false;
+
+ return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
+ return;
+
+ /* This queue will be skipped in further operations */
+ ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
+ /*For SIMR setup*/
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
+}
+
+/*
+ * Set DFS properties for a transmit queue on DCU
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 cw_min, cw_max, retry_lg, retry_sh;
+ struct ath5k_txq_info *tq = &ah->ah_txq[queue];
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ tq = &ah->ah_txq[queue];
+
+ if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return 0;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Only handle data queues, others will be ignored */
+ if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
+ return 0;
+
+ /* Set Slot time */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ AR5K_SLOT_TIME);
+ /* Set ACK_CTS timeout */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ /* Set Transmit Latency */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+
+ /* Set IFS0 */
+ if (ah->ah_turbo) {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME_TURBO) <<
+ AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
+ AR5K_IFS0);
+ } else {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ AR5K_INIT_SIFS, AR5K_IFS0);
+ }
+
+ /* Set IFS1 */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ /* Set AR5K_PHY_SETTLING */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x38 :
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x1C,
+ AR5K_PHY_SETTLING);
+ /* Set Frame Control Register */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
+
+ /*
+ * Calculate cwmin/max by channel mode
+ */
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ /*XR is only supported on 5212*/
+ if (IS_CHAN_XR(ah->ah_current_channel) &&
+ ah->ah_version == AR5K_AR5212) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
+ ah->ah_aifs = AR5K_TUNE_AIFS_XR;
+ /*B mode is not supported on 5210*/
+ } else if (IS_CHAN_B(ah->ah_current_channel) &&
+ ah->ah_version != AR5K_AR5210) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
+ ah->ah_aifs = AR5K_TUNE_AIFS_11B;
+ }
+
+ cw_min = 1;
+ while (cw_min < ah->ah_cw_min)
+ cw_min = (cw_min << 1) | 1;
+
+ cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
+ ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
+ cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
+ ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
+
+ /*
+ * Calculate and set retry limits
+ */
+ if (ah->ah_software_retry) {
+ /* XXX Need to test this */
+ retry_lg = ah->ah_limit_tx_retries;
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+ AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
+ } else {
+ retry_lg = AR5K_INIT_LG_RETRY;
+ retry_sh = AR5K_INIT_SH_RETRY;
+ }
+
+ /*No QCU/DCU [5210]*/
+ if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_reg_write(ah,
+ (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+ | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+ | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
+ | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+ AR5K_NODCU_RETRY_LMT);
+ } else {
+ /*QCU/DCU [5211+]*/
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_DCU_RETRY_LMT_SLG_RETRY) |
+ AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_DCU_RETRY_LMT_SSH_RETRY) |
+ AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
+ AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+ AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+
+ /*===Rest is also for QCU/DCU only [5211+]===*/
+
+ /*
+ * Set initial content window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
+ AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set misc registers
+ */
+ ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
+ AR5K_QUEUE_MISC(queue));
+
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+ if (tq->tqi_cbr_overflow_limit)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBR_THRES_ENABLE);
+ }
+
+ if (tq->tqi_ready_time)
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+ if (tq->tqi_flags
+ & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_RDY_VEOL_POLICY);
+ }
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ /*
+ * Set registers by queue type
+ */
+ switch (tq->tqi_type) {
+ case AR5K_TX_QUEUE_BEACON:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP_BCN_DIS |
+ AR5K_QCU_MISC_BCN_ENABLE);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S) |
+ AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
+ AR5K_DCU_MISC_BCN_ENABLE);
+
+ ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
+ (AR5K_TUNE_SW_BEACON_RESP -
+ AR5K_TUNE_DMA_BEACON_RESP) -
+ AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+ break;
+
+ case AR5K_TX_QUEUE_CAB:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP_DIS |
+ AR5K_QCU_MISC_CBREXP_BCN_DIS);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S));
+ break;
+
+ case AR5K_TX_QUEUE_UAPSD:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBREXP_DIS);
+ break;
+
+ case AR5K_TX_QUEUE_DATA:
+ default:
+ break;
+ }
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+
+ /* Update secondary interrupt mask registers */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
+ }
+
+ return 0;
+}
+
+/*
+ * Get slot time from DCU
+ */
+unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ah->ah_version == AR5K_AR5210)
+ return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
+ AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
+ else
+ return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
+}
+
+/*
+ * Set slot time on DCU
+ */
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
+ return -EINVAL;
+
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+ ah->ah_turbo), AR5K_SLOT_TIME);
+ else
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index 7562bf173d3..e557fe178bb 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2007 Michael Taylor <mike.taylor@apprion.com>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,6 +29,10 @@
* http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
*
* 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
+ *
+ * This file also contains register values found on a memory dump of
+ * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
+ * released by Atheros and on various debug messages found on the net.
*/
@@ -295,7 +299,7 @@
#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */
#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
-#define AR5K_ISR_BRSSI 0x00020000
+#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
@@ -303,46 +307,56 @@
#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */
-#define AR5K_ISR_TIM 0x00800000 /* [5210] */
-#define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */
-#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/
-#define AR5K_ISR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
-#define AR5K_ISR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
-#define AR5K_ISR_QTRIG 0x08000000 /* [5211+] */
+#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
+#define AR5K_ISR_TIM 0x00800000 /* [5211+] */
+#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */
+#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */
+#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */
+#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
/*
* Secondary status registers [5211+] (0 - 4)
*
- * I guess from the names that these give the status for each
- * queue, that's why only masks are defined here, haven't got
- * any info about them (couldn't find them anywhere in ar5k code).
+ * These give the status for each QCU, only QCUs 0-9 are
+ * represented.
*/
#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SISR0_QCU_TXOK_S 0
#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SISR0_QCU_TXDESC_S 16
#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SISR1_QCU_TXERR_S 0
#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SISR1_QCU_TXEOL_S 16
#define AR5K_SISR2 0x008c /* Register Address [5211+] */
#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SISR2_QCU_TXURN_S 0
#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */
#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */
-#define AR5K_SISR2_DPERR 0x00400000 /* Det par Error (?) */
+#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */
#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */
#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */
#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SISR3_QCBORN_S 0
#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SISR3_QCBRURN_S 16
#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SISR4_QTRIG_S 0
/*
* Shadow read-and-clear interrupt status registers [5211+]
@@ -379,7 +393,7 @@
#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */
#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
-#define AR5K_IMR_BRSSI 0x00020000
+#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
@@ -387,12 +401,14 @@
#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */
+#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
-#define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */
+#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
-#define AR5K_IMR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
-#define AR5K_IMR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
-#define AR5K_IMR_QTRIG 0x08000000 /* [5211+] */
+#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */
+#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */
+#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
/*
* Secondary interrupt mask registers [5211+] (0 - 4)
@@ -414,13 +430,14 @@
#define AR5K_SIMR2_QCU_TXURN_S 0
#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */
#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */
-#define AR5K_SIMR2_DPERR 0x00400000 /* Det par Error (?) */
+#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */
#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */
#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */
#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
@@ -586,15 +603,15 @@
#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
-#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */
-#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */
-#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */
+#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
+#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */
+#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */
#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
-#define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */
-#define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */
+#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */
+#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */
#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */
-#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled */
-#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME enalbed */
+#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */
+#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */
#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */
#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */
#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */
@@ -663,6 +680,7 @@
#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
#define AR5K_DCU_LCL_IFS_AIFS_S 20
+#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */
#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
/*
@@ -691,11 +709,7 @@
/*
* DCU misc registers [5211+]
*
- * For some of the registers i couldn't find in the code
- * (only backoff stuff is there realy) i tried to match the
- * names with 802.11e parameters etc, so i guess VIRTCOL here
- * means Virtual Collision and HCFPOLL means Hybrid Coordination
- * factor Poll (CF- Poll). Arbiter lockout control controls the
+ * Note: Arbiter lockout control controls the
* behaviour on low priority queues when we have multiple queues
* with pending frames. Intra-frame lockout means we wait until
* the queue's current frame transmits (with post frame backoff and bursting)
@@ -705,15 +719,20 @@
* No lockout means there is no special handling.
*/
#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
-#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff threshold */
+#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */
+#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series
+ station RTS/data failure count
+ reset policy (?) */
+#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series
+ CW reset policy */
+#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */
#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */
#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */
#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */
#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
-#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
-#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1
-#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2
+#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
+#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1
#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */
#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
@@ -768,8 +787,9 @@
#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
-#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFC cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */
#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */
#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */
@@ -820,8 +840,6 @@
#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
-#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \
- AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY)
/*
* Sleep control register
@@ -833,9 +851,11 @@
#define AR5K_SLEEP_CTL_SLE_S 16
#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
-#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000
+#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */
#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
-/* more bits */
+#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */
+#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */
+#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */
/*
* Interrupt pending register
@@ -851,27 +871,28 @@
/*
* PCI configuration register
+ * TODO: Fix LED stuff
*/
#define AR5K_PCICFG 0x4010 /* Register Address */
#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
-#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock (?) */
+#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */
#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
#define AR5K_PCICFG_EESIZE_S 3
#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
-#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */
+#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */
#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
-#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */
-#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */
+#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */
+#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */
#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
-#define AR5K_PCICFG_UNK 0x00001000 /* Passed on some parts durring attach (?) */
-#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts (?) */
+#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */
+#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/
#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
@@ -884,7 +905,8 @@
#define AR5K_PCICFG_LEDSTATE \
(AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
-#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate (field) */
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24
/*
* "General Purpose Input/Output" (GPIO) control register
@@ -906,8 +928,8 @@
#define AR5K_GPIOCR 0x4014 /* Register Address */
#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
-#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is off (?) */
-#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is on */
+#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */
+#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */
#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
@@ -925,7 +947,6 @@
#define AR5K_GPIODI 0x401c
#define AR5K_GPIODI_M 0x0000002f
-
/*
* Silicon revision register
*/
@@ -935,7 +956,59 @@
#define AR5K_SREV_VER 0x000000ff /* Mask for version */
#define AR5K_SREV_VER_S 4
+/*
+ * TXE write posting register
+ */
+#define AR5K_TXEPOST 0x4028
+
+/*
+ * QCU sleep mask
+ */
+#define AR5K_QCU_SLEEP_MASK 0x402c
+
+/* 0x4068 is compression buffer configuration
+ * register on 5414 and pm configuration register
+ * on 5424 and newer pci-e chips. */
+
+/*
+ * Compression buffer configuration
+ * register (enable/disable) [5414]
+ */
+#define AR5K_5414_CBCFG 0x4068
+#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */
+
+/*
+ * PCI-E Power managment configuration
+ * and status register [5424+]
+ */
+#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */
+/* Only 5424 */
+#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1
+ when d2_sleep_en is asserted */
+#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */
+#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */
+#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes
+ down */
+/* Wake On Wireless */
+#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */
+#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */
+#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */
+#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080
+#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100
+#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200
+#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400
+
+/*
+ * PCI-E Workaround enable register
+ */
+#define AR5K_PCIE_WAEN 0x407c
+/*
+ * PCI-E Serializer/Desirializer
+ * registers
+ */
+#define AR5K_PCIE_SERDES 0x4080
+#define AR5K_PCIE_SERDES_RESET 0x4084
/*====EEPROM REGISTERS====*/
@@ -977,98 +1050,6 @@
#define AR5K_EEPROM_BASE 0x6000
/*
- * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
- */
-#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
-#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
-#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
-#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
-#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
-
-#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
-#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
-#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
-#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
-#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
-#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
-#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
-#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
-#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
-#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
-#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
-#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
-#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
-#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
-#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
-#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
-#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
-#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
-#define AR5K_EEPROM_INFO_CKSUM 0xffff
-#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
-
-#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
-#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
-#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
-#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
-#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_3 0x4003
-#define AR5K_EEPROM_VERSION_4_4 0x4004
-#define AR5K_EEPROM_VERSION_4_5 0x4005
-#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
-#define AR5K_EEPROM_VERSION_4_7 0x4007
-
-#define AR5K_EEPROM_MODE_11A 0
-#define AR5K_EEPROM_MODE_11B 1
-#define AR5K_EEPROM_MODE_11G 2
-
-#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
-#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
-#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
-#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
-#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
-#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
-#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
-
-#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
-#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
-#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
-#define AR5K_EEPROM_RFKILL_POLARITY_S 1
-
-/* Newer EEPROMs are using a different offset */
-#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
- (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
-
-#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
-#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
-#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
-
-/* calibration settings */
-#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
-#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
-#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
-#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
-
-/* [3.1 - 3.3] */
-#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
-#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
-
-/* Misc values available since EEPROM 4.0 */
-#define AR5K_EEPROM_MISC0 0x00c4
-#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
-#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
-#define AR5K_EEPROM_MISC1 0x00c5
-#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
-
-/*
* EEPROM data register
*/
#define AR5K_EEPROM_DATA_5211 0x6004
@@ -1100,14 +1081,28 @@
* EEPROM config register
*/
#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */
-#define AR5K_EEPROM_CFG_SIZE_OVR 0x00000001
+#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */
+#define AR5K_EEPROM_CFG_SIZE_AUTO 0
+#define AR5K_EEPROM_CFG_SIZE_4KBIT 1
+#define AR5K_EEPROM_CFG_SIZE_8KBIT 2
+#define AR5K_EEPROM_CFG_SIZE_16KBIT 3
#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */
#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */
-#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protectio key */
+#define AR5K_EEPROM_CFG_CLK_RATE_S 3
+#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0
+#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1
+#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2
+#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */
+#define AR5K_EEPROM_CFG_PROT_KEY_S 8
#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */
/*
+ * TODO: Wake On Wireless registers
+ * Range 0x7000 - 0x7ce0
+ */
+
+/*
* Protocol Control Unit (PCU) registers
*/
/*
@@ -1139,11 +1134,13 @@
#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */
#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */
-#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */
-#define AR5K_STA_ID1_SELF_GEN_SECTORE 0x04000000 /* Self generate sectore (?) */
+#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */
+#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */
#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */
-#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Keysearch mode (?) */
+#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */
#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */
+#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */
+#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */
/*
* First BSSID register (MAC address, lower 32bits)
@@ -1402,16 +1399,16 @@
#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
-#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
-#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
-#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Enable scrambler seed */
-#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200
#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
@@ -1420,12 +1417,15 @@
#define AR5K_DIAG_SW_SCRAM_SEED_S 10
#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
-#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000
+#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
-#define AR5K_DIAG_SW_OBSPT_M 0x000c0000
+#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
#define AR5K_DIAG_SW_OBSPT_S 18
-/* more bits */
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
/*
* TSF (clock) register (lower 32 bits)
@@ -1636,16 +1636,16 @@
*
* XXX: PCDAC steps (0.5dbm) or DBM ?
*
- * XXX: Mask changes for newer chips to 7f
- * like tx power table ?
*/
#define AR5K_TXPC 0x80e8 /* Register Address */
-#define AR5K_TXPC_ACK_M 0x0000003f /* Mask for ACK tx power */
+#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */
#define AR5K_TXPC_ACK_S 0
-#define AR5K_TXPC_CTS_M 0x00003f00 /* Mask for CTS tx power */
+#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */
#define AR5K_TXPC_CTS_S 8
-#define AR5K_TXPC_CHIRP_M 0x003f0000 /* Mask for CHIRP tx power */
-#define AR5K_TXPC_CHIRP_S 22
+#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */
+#define AR5K_TXPC_CHIRP_S 16
+#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */
+#define AR5K_TXPC_DOPPLER_S 24
/*
* Profile count registers
@@ -1656,14 +1656,19 @@
#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */
/*
- * Quiet (period) control registers (?)
+ * Quiet period control registers
*/
#define AR5K_QUIET_CTL1 0x80fc /* Register Address */
-#define AR5K_QUIET_CTL1_NEXT_QT 0x0000ffff /* Mask for next quiet (period?) (?) */
-#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet (period?) */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0
+#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */
+#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */
+
#define AR5K_QUIET_CTL2 0x8100 /* Register Address */
-#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period (?) */
-#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet duration (?) */
+#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */
+#define AR5K_QUIET_CTL2_QT_PER_S 0
+#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */
+#define AR5K_QUIET_CTL2_QT_DUR_S 16
/*
* TSF parameter register
@@ -1673,12 +1678,15 @@
#define AR5K_TSF_PARM_INC_S 0
/*
- * QoS register (?)
+ * QoS NOACK policy
*/
-#define AR5K_QOS 0x8108 /* Register Address */
-#define AR5K_QOS_NOACK_2BIT_VALUES 0x00000000 /* (field) */
-#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000020 /* (field) */
-#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000080 /* (field) */
+#define AR5K_QOS_NOACK 0x8108 /* Register Address */
+#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */
+#define AR5K_QOS_NOACK_2BIT_VALUES_S 0
+#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
+#define AR5K_QOS_NOACK_BIT_OFFSET_S 4
+#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */
+#define AR5K_QOS_NOACK_BYTE_OFFSET_S 8
/*
* PHY error filter register
@@ -1702,29 +1710,15 @@
/*
* MIC QoS control register (?)
*/
-#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */
-#define AR5K_MIC_QOS_CTL_0 0x00000001 /* MIC QoS control 0 (?) */
-#define AR5K_MIC_QOS_CTL_1 0x00000004 /* MIC QoS control 1 (?) */
-#define AR5K_MIC_QOS_CTL_2 0x00000010 /* MIC QoS control 2 (?) */
-#define AR5K_MIC_QOS_CTL_3 0x00000040 /* MIC QoS control 3 (?) */
-#define AR5K_MIC_QOS_CTL_4 0x00000100 /* MIC QoS control 4 (?) */
-#define AR5K_MIC_QOS_CTL_5 0x00000400 /* MIC QoS control 5 (?) */
-#define AR5K_MIC_QOS_CTL_6 0x00001000 /* MIC QoS control 6 (?) */
-#define AR5K_MIC_QOS_CTL_7 0x00004000 /* MIC QoS control 7 (?) */
-#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */
+#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */
+#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2))
+#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */
/*
* MIC QoS select register (?)
*/
-#define AR5K_MIC_QOS_SEL 0x811c
-#define AR5K_MIC_QOS_SEL_0 0x00000001
-#define AR5K_MIC_QOS_SEL_1 0x00000010
-#define AR5K_MIC_QOS_SEL_2 0x00000100
-#define AR5K_MIC_QOS_SEL_3 0x00001000
-#define AR5K_MIC_QOS_SEL_4 0x00010000
-#define AR5K_MIC_QOS_SEL_5 0x00100000
-#define AR5K_MIC_QOS_SEL_6 0x01000000
-#define AR5K_MIC_QOS_SEL_7 0x10000000
+#define AR5K_MIC_QOS_SEL 0x811c
+#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4))
/*
* Misc mode control register (?)
@@ -1759,6 +1753,11 @@
#define AR5K_TSF_THRES 0x813c
/*
+ * TODO: Wake On Wireless registers
+ * Range: 0x8147 - 0x818c
+ */
+
+/*
* Rate -> ACK SIFS mapping table (32 entries)
*/
#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */
@@ -1873,7 +1872,8 @@
*/
#define AR5K_PHY_TURBO 0x9804 /* Register Address */
#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */
-#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Short mode (20Mhz channels) (?) */
+#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */
+#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */
/*
* PHY agility command register
@@ -1883,6 +1883,11 @@
#define AR5K_PHY_TST1 0x9808
#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/
#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC_S 1
+#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */
+#define AR5K_PHY_TST1_TXSRC_ALT_S 7
+
/*
* PHY timing register 3 [5112+]
@@ -1907,15 +1912,23 @@
/*
* PHY RF control registers
- * (i think these are delay times,
- * these calibration values exist
- * in EEPROM)
*/
#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */
-#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* Mask for TX frame to TX d(esc?) start */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0
#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* Mask for TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 0
+
+#define AR5K_PHY_ADC_CTL 0x982c
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0
+#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000
+#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000
+#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16
#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */
#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */
@@ -1937,35 +1950,43 @@
* PHY settling register
*/
#define AR5K_PHY_SETTLING 0x9844 /* Register Address */
-#define AR5K_PHY_SETTLING_AGC 0x0000007f /* Mask for AGC settling time */
-#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Mask for Switch settlig time */
+#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
+#define AR5K_PHY_SETTLING_AGC_S 0
+#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
+#define AR5K_PHY_SETTLINK_SWITCH_S 7
/*
* PHY Gain registers
*/
#define AR5K_PHY_GAIN 0x9848 /* Register Address */
-#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* Mask for TX-RX Attenuation */
+#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */
+#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12
+#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000
+#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18
#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */
#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */
/*
- * Desired size register
+ * Desired ADC/PGA size register
* (for more infos read ANI patent)
*/
#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */
-#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* Mask for ADC desired size */
-#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* Mask for PGA desired size */
-#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Mask for Total desired size (?) */
+#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */
+#define AR5K_PHY_DESIRED_SIZE_ADC_S 0
+#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */
+#define AR5K_PHY_DESIRED_SIZE_PGA_S 8
+#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */
+#define AR5K_PHY_DESIRED_SIZE_TOT_S 20
/*
* PHY signal register
* (for more infos read ANI patent)
*/
#define AR5K_PHY_SIG 0x9858 /* Register Address */
-#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* Mask for FIRSTEP */
+#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */
#define AR5K_PHY_SIG_FIRSTEP_S 12
-#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* Mask for FIPWR */
+#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */
#define AR5K_PHY_SIG_FIRPWR_S 18
/*
@@ -1973,9 +1994,9 @@
* (for more infos read ANI patent)
*/
#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */
-#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* Mask for AGC Coarse low */
+#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */
#define AR5K_PHY_AGCCOARSE_LO_S 7
-#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* Mask for AGC Coarse high */
+#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */
#define AR5K_PHY_AGCCOARSE_HI_S 15
/*
@@ -1984,6 +2005,8 @@
#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
+#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
+#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
/*
* PHY noise floor status register
@@ -1994,7 +2017,10 @@
#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
-#define AR5K_PHY_NF_THRESH62 0x00001000 /* Thresh62 -check ANI patent- (field) */
+#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
+#define AR5K_PHY_NF_THRESH62_S 12
+#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
+#define AR5K_PHY_NF_MINCCA_PWR_S 19
/*
* PHY ADC saturation register [5110]
@@ -2034,24 +2060,31 @@
*/
#define AR5K_PHY_SCR 0x9870
#define AR5K_PHY_SCR_32MHZ 0x0000001f
+
#define AR5K_PHY_SLMT 0x9874
#define AR5K_PHY_SLMT_32MHZ 0x0000007f
+
#define AR5K_PHY_SCAL 0x9878
#define AR5K_PHY_SCAL_32MHZ 0x0000000e
+
/*
* PHY PLL (Phase Locked Loop) control register
*/
#define AR5K_PHY_PLL 0x987c
-#define AR5K_PHY_PLL_20MHZ 0x13 /* For half rate (?) [5111+] */
-#define AR5K_PHY_PLL_40MHZ_5211 0x18 /* For 802.11a */
+#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */
+/* 40MHz -> 5GHz band */
+#define AR5K_PHY_PLL_40MHZ_5211 0x00000018
#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
+#define AR5K_PHY_PLL_40MHZ_5413 0x00000004
#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
-#define AR5K_PHY_PLL_44MHZ_5211 0x19 /* For 802.11b/g */
+/* 44MHz -> 2.4GHz band */
+#define AR5K_PHY_PLL_44MHZ_5211 0x00000019
#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
+
#define AR5K_PHY_PLL_RF5111 0x00000000
#define AR5K_PHY_PLL_RF5112 0x00000040
#define AR5K_PHY_PLL_HALF_RATE 0x00000100
@@ -2118,6 +2151,19 @@
#define AR5K_PHY_RFSTG_DISABLE 0x00000021
/*
+ * BIN masks (?)
+ */
+#define AR5K_PHY_BIN_MASK_1 0x9900
+#define AR5K_PHY_BIN_MASK_2 0x9904
+#define AR5K_PHY_BIN_MASK_3 0x9908
+
+#define AR5K_PHY_BIN_MASK_CTL 0x990c
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0
+#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000
+#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24
+
+/*
* PHY Antenna control register
*/
#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */
@@ -2164,6 +2210,7 @@
#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
@@ -2210,7 +2257,6 @@
#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
-
/*
* PHY TX rate power registers [5112+]
*/
@@ -2232,6 +2278,8 @@
#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */
#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */
+#define AR5K_PHY_FRAME_CTL_EMU 0x80000000
+#define AR5K_PHY_FRAME_CTL_EMU_S 31
/*---[5110/5111]---*/
#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */
#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */
@@ -2250,48 +2298,36 @@
* PHY radar detection register [5111+]
*/
#define AR5K_PHY_RADAR 0x9954
-
-/* Radar enable ........ ........ ........ .......1 */
#define AR5K_PHY_RADAR_ENABLE 0x00000001
-#define AR5K_PHY_RADAR_DISABLE 0x00000000
-#define AR5K_PHY_RADAR_ENABLE_S 0
-
-/* This is the value found on the card .1.111.1 .1.1.... 111....1 1...1...
-at power on. */
-#define AR5K_PHY_RADAR_PWONDEF_AR5213 0x5d50e188
-
-/* This is the value found on the card .1.1.111 ..11...1 .1...1.1 1...11.1
-after DFS is enabled */
-#define AR5K_PHY_RADAR_ENABLED_AR5213 0x5731458d
-
-/* Finite Impulse Response (FIR) filter .1111111 ........ ........ ........
- * power out threshold.
- * 7-bits, standard power range {0..127} in 1/2 dBm units. */
-#define AR5K_PHY_RADAR_FIRPWROUTTHR 0x7f000000
-#define AR5K_PHY_RADAR_FIRPWROUTTHR_S 24
-
-/* Radar RSSI/SNR threshold. ........ 111111.. ........ ........
- * 6-bits, dBm range {0..63} in dBm units. */
-#define AR5K_PHY_RADAR_RADARRSSITHR 0x00fc0000
-#define AR5K_PHY_RADAR_RADARRSSITHR_S 18
-
-/* Pulse height threshold ........ ......11 1111.... ........
- * 6-bits, dBm range {0..63} in dBm units. */
-#define AR5K_PHY_RADAR_PULSEHEIGHTTHR 0x0003f000
-#define AR5K_PHY_RADAR_PULSEHEIGHTTHR_S 12
-
-/* Pulse RSSI/SNR threshold ........ ........ ....1111 11......
- * 6-bits, dBm range {0..63} in dBm units. */
-#define AR5K_PHY_RADAR_PULSERSSITHR 0x00000fc0
-#define AR5K_PHY_RADAR_PULSERSSITHR_S 6
-
-/* Inband threshold ........ ........ ........ ..11111.
- * 5-bits, units unknown {0..31} (? MHz ?) */
-#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e
+#define AR5K_PHY_RADAR_DISABLE 0x00000000
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
+ 5-bits, units unknown {0..31}
+ (? MHz ?) */
#define AR5K_PHY_RADAR_INBANDTHR_S 1
+#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PRSSI_THR_S 6
+
+#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
+
+#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_RSSI_THR_S 18
+
+#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response
+ filter power out threshold.
+ 7-bits, standard power range
+ {0..127} in 1/2 dBm units. */
+#define AR5K_PHY_RADAR_FIRPWR_THRS 24
+
/*
- * PHY antenna switch table registers [5110]
+ * PHY antenna switch table registers
*/
#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
@@ -2302,25 +2338,65 @@ after DFS is enabled */
#define AR5K_PHY_NFTHRES 0x9968
/*
- * PHY clock sleep registers [5112+]
+ * Sigma Delta register (?) [5213]
*/
-#define AR5K_PHY_SCLOCK 0x99f0
-#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
-#define AR5K_PHY_SDELAY 0x99f4
-#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
-#define AR5K_PHY_SPENDING 0x99f8
-#define AR5K_PHY_SPENDING_14 0x00000014
-#define AR5K_PHY_SPENDING_18 0x00000018
-#define AR5K_PHY_SPENDING_RF5111 0x00000018
-#define AR5K_PHY_SPENDING_RF5112 0x00000014
-/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */
-/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */
-#define AR5K_PHY_SPENDING_RF5413 0x00000014
-#define AR5K_PHY_SPENDING_RF2413 0x00000014
-#define AR5K_PHY_SPENDING_RF2425 0x00000018
+#define AR5K_PHY_SIGMA_DELTA 0x996C
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8
+#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
+#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+/*
+ * RF restart register [5112+] (?)
+ */
+#define AR5K_PHY_RESTART 0x9970 /* restart */
+#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */
+#define AR5K_PHY_RESTART_DIV_GC_S 18
+
+/*
+ * RF Bus access request register (for synth-oly channel switching)
+ */
+#define AR5K_PHY_RFBUS_REQ 0x997C
+#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
+
+/*
+ * Spur mitigation masks (?)
+ */
+#define AR5K_PHY_TIMING_7 0x9980
+#define AR5K_PHY_TIMING_8 0x9984
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0
+
+#define AR5K_PHY_BIN_MASK2_1 0x9988
+#define AR5K_PHY_BIN_MASK2_2 0x998c
+#define AR5K_PHY_BIN_MASK2_3 0x9990
+
+#define AR5K_PHY_BIN_MASK2_4 0x9994
+#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR_PHY_TIMING_9 0x9998
+#define AR_PHY_TIMING_10 0x999c
+#define AR_PHY_TIMING_10_PILOT_MASK_2 0x000fffff
+#define AR_PHY_TIMING_10_PILOT_MASK_2_S 0
+
+/*
+ * Spur mitigation control
+ */
+#define AR_PHY_TIMING_11 0x99a0 /* Register address */
+#define AR_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */
+#define AR_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0
+#define AR_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */
+#define AR_PHY_TIMING_11_SPUR_FREQ_SD_S 20
+#define AR_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */
+#define AR_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */
/*
- * Misc PHY/radio registers [5110 - 5111]
+ * Gain tables
*/
#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
@@ -2340,9 +2416,10 @@ after DFS is enabled */
#define AR5K_PHY_CURRENT_RSSI 0x9c1c
/*
- * PHY RF Bus grant register (?)
+ * PHY RF Bus grant register
*/
#define AR5K_PHY_RFBUS_GRANT 0x9c20
+#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001
/*
* PHY ADC test register
@@ -2386,6 +2463,31 @@ after DFS is enabled */
#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008
/*
+ * Heavy clip enable register
+ */
+#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0
+
+/*
+ * PHY clock sleep registers [5112+]
+ */
+#define AR5K_PHY_SCLOCK 0x99f0
+#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
+#define AR5K_PHY_SDELAY 0x99f4
+#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
+#define AR5K_PHY_SPENDING 0x99f8
+#define AR5K_PHY_SPENDING_14 0x00000014
+#define AR5K_PHY_SPENDING_18 0x00000018
+#define AR5K_PHY_SPENDING_RF5111 0x00000018
+#define AR5K_PHY_SPENDING_RF5112 0x00000014
+/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */
+/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */
+#define AR5K_PHY_SPENDING_RF5413 0x00000018
+#define AR5K_PHY_SPENDING_RF2413 0x00000018
+#define AR5K_PHY_SPENDING_RF2316 0x00000018
+#define AR5K_PHY_SPENDING_RF2317 0x00000018
+#define AR5K_PHY_SPENDING_RF2425 0x00000014
+
+/*
* PHY PAPD I (power?) table (?)
* (92! entries)
*/
@@ -2436,10 +2538,47 @@ after DFS is enabled */
#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f
#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0
+/* Same address is used for antenna diversity activation */
+#define AR5K_PHY_FAST_ANT_DIV 0xa208
+#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000
+
/*
* PHY 2GHz gain register [5111+]
*/
-#define AR5K_PHY_GAIN_2GHZ 0xa20c
-#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
+#define AR5K_PHY_GAIN_2GHZ 0xa20c
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
-#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
+#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
+
+#define AR5K_PHY_CCK_RX_CTL_4 0xa21c
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19
+
+#define AR5K_PHY_DAG_CCK_CTL 0xa228
+#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10
+
+#define AR5K_PHY_FAST_ADC 0xa24c
+
+#define AR5K_PHY_BLUETOOTH 0xa254
+
+/*
+ * Transmit Power Control register
+ * [2413+]
+ */
+#define AR5K_PHY_TPC_RG1 0xa258
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14
+
+#define AR5K_PHY_TPC_RG5 0xa26C
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
new file mode 100644
index 00000000000..8f1886834e6
--- /dev/null
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#define _ATH5K_RESET
+
+/*****************************\
+ Reset functions and helpers
+\*****************************/
+
+#include <linux/pci.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+#include "debug.h"
+
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the OFDM timings for the AR5212 upon reset. This is a helper for
+ * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
+ * depending on the bandwidth of the channel.
+ *
+ */
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ /* Get exponent and mantissa and set it */
+ u32 coef_scaled, coef_exp, coef_man,
+ ds_coef_exp, ds_coef_man, clock;
+
+ if (!(ah->ah_version == AR5K_AR5212) ||
+ !(channel->hw_value & CHANNEL_OFDM))
+ BUG();
+
+ /* Seems there are two PLLs, one for baseband sampling and one
+ * for tuning. Tuning basebands are 40 MHz or 80MHz when in
+ * turbo. */
+ clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
+ coef_scaled = ((5 * (clock << 24)) / 2) /
+ channel->center_freq;
+
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ if ((coef_scaled >> coef_exp) & 0x1)
+ break;
+
+ if (!coef_exp)
+ return -EINVAL;
+
+ coef_exp = 14 - (coef_exp - 24);
+ coef_man = coef_scaled +
+ (1 << (24 - coef_exp - 1));
+ ds_coef_man = coef_man >> (24 - coef_exp);
+ ds_coef_exp = coef_exp - 16;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+ return 0;
+}
+
+
+/*
+ * index into rates for control rates, we can set it up like this because
+ * this is only used for AR5212 and we know it supports G mode
+ */
+static int control_rates[] =
+ { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
+
+/**
+ * ath5k_hw_write_rate_duration - set rate duration during hw resets
+ *
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for
+ * the hardware for the current mode for each rate. The rates which are capable
+ * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another
+ * register for the short preamble ACK timeout calculation.
+ */
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ unsigned int mode)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct ieee80211_rate *rate;
+ unsigned int i;
+
+ /* Write rate duration table */
+ for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
+ u32 reg;
+ u16 tx_time;
+
+ rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
+
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(rate->hw_value);
+
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * which ieee80211_generic_frame_duration() adds,
+ * its 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+ tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
+ sc->vif, 10, rate));
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+ if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
+ continue;
+
+ /*
+ * We're not distinguishing short preamble here,
+ * This is true, all we'll get is a longer value here
+ * which is not necessarilly bad. We could use
+ * export ieee80211_frame_duration() but that needs to be
+ * fixed first to be properly used by mac802111 drivers:
+ *
+ * - remove erp stuff and let the routine figure ofdm
+ * erp rates
+ * - remove passing argument ieee80211_local as
+ * drivers don't have access to it
+ * - move drivers using ieee80211_generic_frame_duration()
+ * to this
+ */
+ ath5k_hw_reg_write(ah, tx_time,
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+ }
+}
+
+/*
+ * Reset chipset
+ */
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
+{
+ int ret;
+ u32 mask = val ? val : ~0U;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Read-and-clear RX Descriptor Pointer*/
+ ath5k_hw_reg_read(ah, AR5K_RXDP);
+
+ /*
+ * Reset the device and wait until success
+ */
+ ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
+
+ /* Wait at least 128 PCI clocks */
+ udelay(15);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ } else {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ }
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
+
+ /*
+ * Reset configuration register (for hw byte-swap). Note that this
+ * is only set for big endian. We do the necessary magic in
+ * AR5K_INIT_CFG.
+ */
+ if ((val & AR5K_RESET_CTL_PCU) == 0)
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+ return ret;
+}
+
+/*
+ * Sleep control
+ */
+int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ bool set_chip, u16 sleep_duration)
+{
+ unsigned int i;
+ u32 staid, data;
+
+ ATH5K_TRACE(ah->ah_sc);
+ staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+
+ switch (mode) {
+ case AR5K_PM_AUTO:
+ staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+ /* fallthrough */
+ case AR5K_PM_NETWORK_SLEEP:
+ if (set_chip)
+ ath5k_hw_reg_write(ah,
+ AR5K_SLEEP_CTL_SLE_ALLOW |
+ sleep_duration,
+ AR5K_SLEEP_CTL);
+
+ staid |= AR5K_STA_ID1_PWR_SV;
+ break;
+
+ case AR5K_PM_FULL_SLEEP:
+ if (set_chip)
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
+ AR5K_SLEEP_CTL);
+
+ staid |= AR5K_STA_ID1_PWR_SV;
+ break;
+
+ case AR5K_PM_AWAKE:
+
+ staid &= ~AR5K_STA_ID1_PWR_SV;
+
+ if (!set_chip)
+ goto commit;
+
+ /* Preserve sleep duration */
+ data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+ if (data & 0xffc00000)
+ data = 0;
+ else
+ data = data & 0xfffcffff;
+
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(15);
+
+ for (i = 50; i > 0; i--) {
+ /* Check if the chip did wake up */
+ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_SPWR_DN) == 0)
+ break;
+
+ /* Wait a bit and retry */
+ udelay(200);
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ }
+
+ /* Fail if the chip didn't wake up */
+ if (i <= 0)
+ return -EIO;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+commit:
+ ah->ah_power_mode = mode;
+ ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/*
+ * Bring up MAC + PHY Chips
+ */
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+{
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 turbo, mode, clock, bus_flags;
+ int ret;
+
+ turbo = 0;
+ mode = 0;
+ clock = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Wakeup the device */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Get channel mode flags
+ */
+
+ if (ah->ah_radio >= AR5K_RF5112) {
+ mode = AR5K_PHY_MODE_RAD_RF5112;
+ clock = AR5K_PHY_PLL_RF5112;
+ } else {
+ mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
+ clock = AR5K_PHY_PLL_RF5111; /*Zero*/
+ }
+
+ if (flags & CHANNEL_2GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+ clock |= AR5K_PHY_PLL_44MHZ;
+
+ if (flags & CHANNEL_CCK) {
+ mode |= AR5K_PHY_MODE_MOD_CCK;
+ } else if (flags & CHANNEL_OFDM) {
+ /* XXX Dynamic OFDM/CCK is not supported by the
+ * AR5211 so we set MOD_OFDM for plain g (no
+ * CCK headers) operation. We need to test
+ * this, 5211 might support ofdm-only g after
+ * all, there are also initial register values
+ * in the code for g mode (see initvals.c). */
+ if (ah->ah_version == AR5K_AR5211)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else
+ mode |= AR5K_PHY_MODE_MOD_DYN;
+ } else {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else if (flags & CHANNEL_5GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+ clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (flags & CHANNEL_OFDM)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else {
+ ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+ return -EINVAL;
+ }
+
+ if (flags & CHANNEL_TURBO)
+ turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+ } else { /* Reset the device */
+
+ /* ...enable Atheros turbo mode if requested */
+ if (flags & CHANNEL_TURBO)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
+ AR5K_PHY_TURBO);
+ }
+
+ /* reseting PCI on PCI-E cards results card to hang
+ * and always return 0xffff... so we ingore that flag
+ * for PCI-E cards */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ /* Reset chipset */
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ return ret;
+ }
+
+ /* ...final warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /* ...set the PHY operating mode */
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+
+ ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
+ ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
+ }
+
+ return 0;
+}
+
+/*
+ * Main reset function
+ */
+int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ struct ieee80211_channel *channel, bool change_channel)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 data, s_seq, s_ant, s_led[3], dma_size;
+ unsigned int i, mode, freq, ee_mode, ant[2];
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ s_seq = 0;
+ s_ant = 0;
+ ee_mode = 0;
+ freq = 0;
+ mode = 0;
+
+ /*
+ * Save some registers before a reset
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ if (change_channel) {
+ /* Seq number for queue 0 -do this for all queues ? */
+ s_seq = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DFS_SEQNUM(0));
+ /*Default antenna*/
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+ }
+ }
+
+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_get_rf_gain(ah);
+
+
+ /*Wakeup the device*/
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Initialize operating mode
+ */
+ ah->ah_op_mode = op_mode;
+
+ /*
+ * 5111/5112 Settings
+ * 5210 only comes with RF5110
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ if (ah->ah_radio != AR5K_RF5111 &&
+ ah->ah_radio != AR5K_RF5112 &&
+ ah->ah_radio != AR5K_RF5413 &&
+ ah->ah_radio != AR5K_RF2413 &&
+ ah->ah_radio != AR5K_RF2425) {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid phy radio: %u\n", ah->ah_radio);
+ return -EINVAL;
+ }
+
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ mode = AR5K_MODE_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_G:
+ mode = AR5K_MODE_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_B:
+ mode = AR5K_MODE_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ break;
+ case CHANNEL_T:
+ mode = AR5K_MODE_11A_TURBO;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ /*Is this ok on 5211 too ?*/
+ case CHANNEL_TG:
+ mode = AR5K_MODE_11G_TURBO;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "XR mode not available on 5211");
+ return -EINVAL;
+ }
+ mode = AR5K_MODE_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ ATH5K_ERR(ah->ah_sc,
+ "invalid channel: %d\n", channel->center_freq);
+ return -EINVAL;
+ }
+
+ /* PHY access enable */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ }
+
+ ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+ if (ret)
+ return ret;
+
+ /*
+ * 5211/5212 Specific
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Write initial RF gain settings
+ * This should work for both 5111/5112
+ */
+ ret = ath5k_hw_rfgain(ah, freq);
+ if (ret)
+ return ret;
+
+ mdelay(1);
+
+ /*
+ * Write some more initial register settings
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0x0002a002, 0x982c);
+
+ if (channel->hw_value == CHANNEL_G)
+ if (ah->ah_mac_srev < AR5K_SREV_AR2413)
+ ath5k_hw_reg_write(ah, 0x00f80d80,
+ 0x994c);
+ else if (ah->ah_mac_srev < AR5K_SREV_AR5424)
+ ath5k_hw_reg_write(ah, 0x00380140,
+ 0x994c);
+ else if (ah->ah_mac_srev < AR5K_SREV_AR2425)
+ ath5k_hw_reg_write(ah, 0x00fc0ec0,
+ 0x994c);
+ else /* 2425 */
+ ath5k_hw_reg_write(ah, 0x00fc0fc0,
+ 0x994c);
+ else
+ ath5k_hw_reg_write(ah, 0x00000000, 0x994c);
+
+ /* Some bits are disabled here, we know nothing about
+ * register 0xa228 yet, most of the times this ends up
+ * with a value 0x9b5 -haven't seen any dump with
+ * a different value- */
+ /* Got this from decompiling binary HAL */
+ data = ath5k_hw_reg_read(ah, 0xa228);
+ data &= 0xfffffdff;
+ ath5k_hw_reg_write(ah, data, 0xa228);
+
+ data = ath5k_hw_reg_read(ah, 0xa228);
+ data &= 0xfffe03ff;
+ ath5k_hw_reg_write(ah, data, 0xa228);
+ data = 0;
+
+ /* Just write 0x9b5 ? */
+ /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */
+ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+ ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
+ ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio >= AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ data = 0;
+ }
+
+ /*
+ * Set TX power (FIXME)
+ */
+ ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER);
+ if (ret)
+ return ret;
+
+ /* Write rate duration table only on AR5212 and if
+ * virtual interface has already been brought up
+ * XXX: rethink this after new mode changes to
+ * mac80211 are integrated */
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_sc->vif != NULL)
+ ath5k_hw_write_rate_duration(ah, mode);
+
+ /*
+ * Write RF registers
+ */
+ ret = ath5k_hw_rfregs(ah, channel, mode);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure additional registers
+ */
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+ channel->hw_value & CHANNEL_OFDM) {
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+ }
+
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+ if (mode == AR5K_MODE_11B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ }
+
+ /*
+ * Set channel and calibrate the PHY
+ */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;
+
+ /* Set antenna mode */
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL,
+ ah->ah_antenna[ee_mode][0], 0xfffffc06);
+
+ /*
+ * In case a fixed antenna was set as default
+ * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
+ * registers.
+ */
+ if (s_ant != 0) {
+ if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_A;
+ else /* 2 - Aux */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_B;
+ } else {
+ ant[0] = AR5K_ANT_FIXED_A;
+ ant[1] = AR5K_ANT_FIXED_B;
+ }
+
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Commit values from EEPROM */
+ if (ah->ah_radio == AR5K_RF5111)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
+ AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY_NFTHRES);
+
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING,
+ (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
+ 0xffffc07f);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
+ (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
+ 0xfffc0fff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
+ ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
+ 0xffff0000);
+
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3,
+ ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF,
+ (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+
+ } else {
+ mdelay(1);
+ /* Disable phy and wait */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+ mdelay(1);
+ }
+
+ /*
+ * Restore saved values
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
+ ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
+ }
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+ ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
+ ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
+
+ /*
+ * Misc
+ */
+ /* XXX: add ah->aid once mac80211 gives this to us */
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+
+ ath5k_hw_set_opmode(ah);
+ /*PISR/SISR Not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+ /* If we later allow tuning for this, store into sc structure */
+ data = AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
+ ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
+ }
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set maximum DMA size (512) except for PCI-E cards since
+ * it causes rx overruns and tx errors (tested on 5424 but since
+ * rx overruns also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * In dumps this is 128 for allchips.
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, dma_size);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, dma_size);
+ }
+
+ /*
+ * Enable the PHY and wait until completion
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+ /*
+ * On 5211+ read activation -> rx delay
+ * and use it.
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+ data = (channel->hw_value & CHANNEL_CCK) ?
+ ((data << 2) / 22) : (data / 10);
+
+ udelay(100 + (2 * data));
+ data = 0;
+ } else {
+ mdelay(1);
+ }
+
+ /*
+ * Perform ADC test (?)
+ */
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+ ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+ for (i = 0; i <= 20; i++) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+ break;
+ udelay(200);
+ }
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1);
+ data = 0;
+
+ /*
+ * Start automatic gain calibration
+ *
+ * During AGC calibration RX path is re-routed to
+ * a signal detector so we don't receive anything.
+ *
+ * This method is used to calibrate some static offsets
+ * used together with on-the fly I/Q calibration (the
+ * one performed via ath5k_hw_phy_calibrate), that doesn't
+ * interrupt rx path.
+ *
+ * If we are in a noisy environment AGC calibration may time
+ * out.
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL);
+
+ /* At the same time start I/Q calibration for QAM constellation
+ * -no need for CCK- */
+ ah->ah_calibration = false;
+ if (!(mode == AR5K_MODE_11B)) {
+ ah->ah_calibration = true;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_RUN);
+ }
+
+ /* Wait for gain calibration to finish (we check for I/Q calibration
+ * during ath5k_phy_calibrate) */
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, false)) {
+ ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+ channel->center_freq);
+ return -EAGAIN;
+ }
+
+ /*
+ * Start noise floor calibration
+ *
+ * If we run NF calibration before AGC, it always times out.
+ * Binary HAL starts NF and AGC calibration at the same time
+ * and only waits for AGC to finish. I believe that's wrong because
+ * during NF calibration, rx path is also routed to a detector, so if
+ * it doesn't finish we won't have RX.
+ *
+ * XXX: Find an interval that's OK for all cards...
+ */
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ if (ret)
+ return ret;
+
+ /*
+ * Reset queues and start beacon timers at the end of the reset routine
+ */
+ for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+ /*No QCU on 5210*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
+
+ ret = ath5k_hw_reset_tx_queue(ah, i);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "failed to reset TX queue #%d\n", i);
+ return ret;
+ }
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_set_imr(ah, AR5K_INT_RX | AR5K_INT_TX |
+ AR5K_INT_FATAL);
+
+ /*
+ * Set RF kill flags if supported by the device (read from the EEPROM)
+ * Disable gpio_intr for now since it results system hang.
+ * TODO: Handle this in ath5k_intr
+ */
+#if 0
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
+ ath5k_hw_set_gpio_input(ah, 0);
+ ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
+ if (ah->ah_gpio[0] == 0)
+ ath5k_hw_set_gpio_intr(ah, 0, 1);
+ else
+ ath5k_hw_set_gpio_intr(ah, 0, 0);
+ }
+#endif
+
+ /*
+ * Set the 32MHz reference clock on 5212 phy clock sleep register
+ *
+ * TODO: Find out how to switch to external 32Khz clock to save power
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+ ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
+
+ data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ;
+ data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ?
+ 0x00000f80 : 0x00001380 ;
+ ath5k_hw_reg_write(ah, data, AR5K_USEC_5211);
+ data = 0;
+ }
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
+ ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
+ ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413)
+ ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
+ }
+
+ /*
+ * Disable beacons and reset the register
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
+ AR5K_BEACON_RESET_TSF);
+
+ return 0;
+}
+
+#undef _ATH5K_RESET
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig
index 9e19dcceb3a..80a69243041 100644
--- a/drivers/net/wireless/ath9k/Kconfig
+++ b/drivers/net/wireless/ath9k/Kconfig
@@ -1,6 +1,9 @@
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
+ select MAC80211_LEDS
+ select LEDS_CLASS
+ select NEW_LEDS
---help---
This module adds support for wireless adapters based on
Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index d1b0fbae5a3..accace5f7ef 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -144,6 +144,7 @@ struct ath_desc {
#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
#define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
+#define ATH9K_TXDESC_CAB 0x0400
#define ATH9K_RXDESC_INTREQ 0x0020
@@ -564,8 +565,6 @@ enum ath9k_cipher {
#define CTL_5GHT40 8
#define AR_EEPROM_MAC(i) (0x1d+(i))
-#define EEP_SCALE 100
-#define EEP_DELTA 10
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
@@ -606,9 +605,6 @@ struct ath9k_country_entry {
#define REG_CLR_BIT(_a, _r, _f) \
REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
-#define ATH9K_COMP_BUF_MAX_SIZE 9216
-#define ATH9K_COMP_BUF_ALIGN_SIZE 512
-
#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
#define INIT_AIFS 2
@@ -632,12 +628,6 @@ struct ath9k_country_entry {
(IEEE80211_WEP_IVLEN + \
IEEE80211_WEP_KIDLEN + \
IEEE80211_WEP_CRCLEN))
-#define IEEE80211_MAX_LEN (2300 + FCS_LEN + \
- (IEEE80211_WEP_IVLEN + \
- IEEE80211_WEP_KIDLEN + \
- IEEE80211_WEP_CRCLEN))
-
-#define MAX_REG_ADD_COUNT 129
#define MAX_RATE_POWER 63
enum ath9k_power_mode {
@@ -707,13 +697,6 @@ enum phytype {
};
#define PHY_CCK PHY_DS
-enum start_adhoc_option {
- START_ADHOC_NO_11A,
- START_ADHOC_PER_11D,
- START_ADHOC_IN_11A,
- START_ADHOC_IN_11B,
-};
-
enum ath9k_tp_scale {
ATH9K_TP_SCALE_MAX = 0,
ATH9K_TP_SCALE_50,
@@ -769,14 +752,11 @@ struct ath9k_node_stats {
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
-enum ath9k_gpio_output_mux_type {
- ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT,
- ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
- ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
- ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
- ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
- ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES
-};
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
enum {
ATH9K_RESET_POWER_ON,
@@ -790,19 +770,20 @@ struct ath_hal {
u32 ah_magic;
u16 ah_devid;
u16 ah_subvendorid;
- struct ath_softc *ah_sc;
- void __iomem *ah_sh;
- u16 ah_countryCode;
u32 ah_macVersion;
u16 ah_macRev;
u16 ah_phyRev;
u16 ah_analog5GhzRev;
u16 ah_analog2GhzRev;
- u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE];
- u32 ah_flags;
+
+ void __iomem *ah_sh;
+ struct ath_softc *ah_sc;
enum ath9k_opmode ah_opmode;
struct ath9k_ops_config ah_config;
struct ath9k_hw_capabilities ah_caps;
+
+ u16 ah_countryCode;
+ u32 ah_flags;
int16_t ah_powerLimit;
u16 ah_maxPowerLevel;
u32 ah_tpScale;
@@ -812,15 +793,17 @@ struct ath_hal {
u16 ah_currentRD5G;
u16 ah_currentRD2G;
char ah_iso[4];
- enum start_adhoc_option ah_adHocMode;
- bool ah_commonMode;
+
struct ath9k_channel ah_channels[150];
- u32 ah_nchan;
struct ath9k_channel *ah_curchan;
- u16 ah_rfsilent;
- bool ah_rfkillEnabled;
+ u32 ah_nchan;
+
bool ah_isPciExpress;
u16 ah_txTrigLevel;
+ u16 ah_rfsilent;
+ u32 ah_rfkill_gpio;
+ u32 ah_rfkill_polarity;
+
#ifndef ATH_NF_PER_CHAN
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
#endif
@@ -853,7 +836,7 @@ bool ath9k_regd_init_channels(struct ath_hal *ah,
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
enum ath9k_int ints);
-bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
+bool ath9k_hw_reset(struct ath_hal *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode,
u8 txchainmask, u8 rxchainmask,
@@ -871,7 +854,7 @@ bool ath9k_hw_calibrate(struct ath_hal *ah,
u8 rxchainmask,
bool longcal,
bool *isCalDone);
-int16_t ath9k_hw_getchan_noise(struct ath_hal *ah,
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
struct ath9k_channel *chan);
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
u16 assocId);
@@ -1018,4 +1001,9 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah,
bool ath9k_get_channel_edges(struct ath_hal *ah,
u16 flags, u16 *low,
u16 *high);
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+ u32 ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
#endif
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index caf569401a3..9e15c30bbc0 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -16,7 +16,6 @@
/* Implementation of beacon processing. */
-#include <asm/unaligned.h>
#include "core.h"
/*
@@ -26,14 +25,13 @@
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
* settings and channel width min/max
*/
-
static int ath_beaconq_config(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
struct ath9k_tx_queue_info qi;
ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi);
- if (sc->sc_opmode == ATH9K_M_HOSTAP) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
/* Always burst out beacon and CAB traffic. */
qi.tqi_aifs = 1;
qi.tqi_cwmin = 0;
@@ -63,19 +61,18 @@ static int ath_beaconq_config(struct ath_softc *sc)
* up all required antenna switch parameters, rate codes, and channel flags.
* Beacons are always sent out at the lowest rate, and are not retried.
*/
-
static void ath_beacon_setup(struct ath_softc *sc,
- struct ath_vap *avp, struct ath_buf *bf)
+ struct ath_vap *avp, struct ath_buf *bf)
{
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
- int flags, antenna;
+ struct ath9k_11n_rate_series series[4];
const struct ath9k_rate_table *rt;
+ int flags, antenna;
u8 rix, rate;
int ctsrate = 0;
int ctsduration = 0;
- struct ath9k_11n_rate_series series[4];
DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n",
__func__, skb, skb->len);
@@ -85,7 +82,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
flags = ATH9K_TXDESC_NOACK;
- if (sc->sc_opmode == ATH9K_M_IBSS &&
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
ds->ds_link = bf->bf_daddr; /* self-linked */
flags |= ATH9K_TXDESC_VEOL;
@@ -111,27 +108,28 @@ static void ath_beacon_setup(struct ath_softc *sc,
rix = 0;
rt = sc->sc_currates;
rate = rt->info[rix].rateCode;
- if (sc->sc_flags & ATH_PREAMBLE_SHORT)
+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
rate |= rt->info[rix].shortPreamble;
- ath9k_hw_set11n_txdesc(ah, ds
- , skb->len + FCS_LEN /* frame length */
- , ATH9K_PKT_TYPE_BEACON /* Atheros packet type */
- , avp->av_btxctl.txpower /* txpower XXX */
- , ATH9K_TXKEYIX_INVALID /* no encryption */
- , ATH9K_KEY_TYPE_CLEAR /* no encryption */
- , flags /* no ack, veol for beacons */
+ ath9k_hw_set11n_txdesc(ah, ds,
+ skb->len + FCS_LEN, /* frame length */
+ ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
+ avp->av_btxctl.txpower, /* txpower XXX */
+ ATH9K_TXKEYIX_INVALID, /* no encryption */
+ ATH9K_KEY_TYPE_CLEAR, /* no encryption */
+ flags /* no ack,
+ veol for beacons */
);
/* NB: beacon's BufLen must be a multiple of 4 bytes */
- ath9k_hw_filltxdesc(ah, ds
- , roundup(skb->len, 4) /* buffer length */
- , true /* first segment */
- , true /* last segment */
- , ds /* first descriptor */
+ ath9k_hw_filltxdesc(ah, ds,
+ roundup(skb->len, 4), /* buffer length */
+ true, /* first segment */
+ true, /* last segment */
+ ds /* first descriptor */
);
- memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
+ memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
series[0].Tries = 1;
series[0].Rate = rate;
series[0].ChSel = sc->sc_tx_chainmask;
@@ -140,55 +138,6 @@ static void ath_beacon_setup(struct ath_softc *sc,
ctsrate, ctsduration, series, 4, 0);
}
-/* Move everything from the vap's mcast queue to the hardware cab queue.
- * Caller must hold mcasq lock and cabq lock
- * XXX MORE_DATA bit?
- */
-static void empty_mcastq_into_cabq(struct ath_hal *ah,
- struct ath_txq *mcastq, struct ath_txq *cabq)
-{
- struct ath_buf *bfmcast;
-
- BUG_ON(list_empty(&mcastq->axq_q));
-
- bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list);
-
- /* link the descriptors */
- if (!cabq->axq_link)
- ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr);
- else
- *cabq->axq_link = bfmcast->bf_daddr;
-
- /* append the private vap mcast list to the cabq */
-
- cabq->axq_depth += mcastq->axq_depth;
- cabq->axq_totalqueued += mcastq->axq_totalqueued;
- cabq->axq_linkbuf = mcastq->axq_linkbuf;
- cabq->axq_link = mcastq->axq_link;
- list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q);
- mcastq->axq_depth = 0;
- mcastq->axq_totalqueued = 0;
- mcastq->axq_linkbuf = NULL;
- mcastq->axq_link = NULL;
-}
-
-/* This is only run at DTIM. We move everything from the vap's mcast queue
- * to the hardware cab queue. Caller must hold the mcastq lock. */
-static void trigger_mcastq(struct ath_hal *ah,
- struct ath_txq *mcastq, struct ath_txq *cabq)
-{
- spin_lock_bh(&cabq->axq_lock);
-
- if (!list_empty(&mcastq->axq_q))
- empty_mcastq_into_cabq(ah, mcastq, cabq);
-
- /* cabq is gated by beacon so it is safe to start here */
- if (!list_empty(&cabq->axq_q))
- ath9k_hw_txstart(ah, cabq->axq_qnum);
-
- spin_unlock_bh(&cabq->axq_lock);
-}
-
/*
* Generate beacon frame and queue cab data for a vap.
*
@@ -199,57 +148,56 @@ static void trigger_mcastq(struct ath_hal *ah,
*/
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
{
- struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
- int cabq_depth;
- int mcastq_depth;
- int is_beacon_dtim = 0;
- unsigned int curlen;
struct ath_txq *cabq;
- struct ath_txq *mcastq;
+ struct ieee80211_tx_info *info;
+ int cabq_depth;
+
avp = sc->sc_vaps[if_id];
+ ASSERT(avp);
- mcastq = &avp->av_mcastq;
cabq = sc->sc_cabq;
- ASSERT(avp);
-
if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
__func__, avp, avp->av_bcbuf);
return NULL;
}
+
bf = avp->av_bcbuf;
- skb = (struct sk_buff *) bf->bf_mpdu;
+ skb = (struct sk_buff *)bf->bf_mpdu;
+ if (skb) {
+ pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_TODEVICE);
+ }
- /*
- * Update dynamic beacon contents. If this returns
- * non-zero then we need to remap the memory because
- * the beacon frame changed size (probably because
- * of the TIM bitmap).
- */
- curlen = skb->len;
-
- /* XXX: spin_lock_bh should not be used here, but sparse bitches
- * otherwise. We should fix sparse :) */
- spin_lock_bh(&mcastq->axq_lock);
- mcastq_depth = avp->av_mcastq.axq_depth;
-
- if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) ==
- 1) {
- ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
- bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
- } else {
- pci_dma_sync_single_for_cpu(sc->pdev,
- bf->bf_buf_addr,
- skb_tailroom(skb),
- PCI_DMA_TODEVICE);
+ skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+ bf->bf_mpdu = skb;
+ if (skb == NULL)
+ return NULL;
+
+ info = IEEE80211_SKB_CB(skb);
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+ /*
+ * TODO: make sure the seq# gets assigned properly (vs. other
+ * TX frames)
+ */
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ sc->seq_no += 0x10;
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
}
+ bf->bf_buf_addr = bf->bf_dmacontext =
+ pci_map_single(sc->pdev, skb->data,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_TODEVICE);
+
+ skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+
/*
* if the CABQ traffic from previous DTIM is pending and the current
* beacon is also a DTIM.
@@ -262,9 +210,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
cabq_depth = cabq->axq_depth;
spin_unlock_bh(&cabq->axq_lock);
- is_beacon_dtim = avp->av_boff.bo_tim[4] & 1;
-
- if (mcastq_depth && is_beacon_dtim && cabq_depth) {
+ if (skb && cabq_depth) {
/*
* Unlock the cabq lock as ath_tx_draintxq acquires
* the lock again which is a common function and that
@@ -284,10 +230,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* Enable the CAB queue before the beacon queue to
* insure cab frames are triggered by this beacon.
*/
- if (is_beacon_dtim)
- trigger_mcastq(ah, mcastq, cabq);
+ while (skb) {
+ ath_tx_cabq(sc, skb);
+ skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+ }
- spin_unlock_bh(&mcastq->axq_lock);
return bf;
}
@@ -295,7 +242,6 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* Startup beacon transmission for adhoc mode when they are sent entirely
* by the hardware using the self-linked descriptor + veol trick.
*/
-
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
@@ -332,12 +278,11 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
* min/max, and enable aifs). The info structure does not need to be
* persistant.
*/
-
int ath_beaconq_setup(struct ath_hal *ah)
{
struct ath9k_tx_queue_info qi;
- memzero(&qi, sizeof(qi));
+ memset(&qi, 0, sizeof(qi));
qi.tqi_aifs = 1;
qi.tqi_cwmin = 0;
qi.tqi_cwmax = 0;
@@ -353,29 +298,27 @@ int ath_beaconq_setup(struct ath_hal *ah)
* the ATH interface. This routine also calculates the beacon "slot" for
* staggared beacons in the mBSSID case.
*/
-
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
struct ath_vap *avp;
- struct ieee80211_hdr *wh;
+ struct ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
+ __le64 tstamp;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
- /*
- * Allocate beacon state for hostap/ibss. We know
- * a buffer is available.
- */
+ /* Allocate beacon state for hostap/ibss. We know
+ * a buffer is available. */
avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
- struct ath_buf, list);
+ struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
- if (sc->sc_opmode == ATH9K_M_HOSTAP ||
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
int slot;
/*
@@ -408,17 +351,16 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
skb = (struct sk_buff *)bf->bf_mpdu;
- ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
+ pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
}
/*
- * NB: the beacon data buffer must be 32-bit aligned;
- * we assume the wbuf routines will return us something
- * with this alignment (perhaps should assert).
- * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and
+ * NB: the beacon data buffer must be 32-bit aligned.
+ * FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble
*/
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
@@ -428,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
return -ENOMEM;
}
+ tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+ sc->bc_tstamp = le64_to_cpu(tstamp);
+
/*
* Calculate a TSF adjustment factor required for
* staggered beacons. Note that we assume the format
@@ -439,9 +384,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
__le64 val;
int intval;
- /* FIXME: Use default value for now: Sujith */
-
- intval = ATH_DEFAULT_BINTVAL;
+ intval = sc->hw->conf.beacon_int ?
+ sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
/*
* The beacon interval is in TU's; the TSF in usecs.
@@ -462,12 +406,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
__func__, "stagger",
avp->av_bslot, intval, (unsigned long long)tsfadjust);
- wh = (struct ieee80211_hdr *)skb->data;
- memcpy(&wh[1], &val, sizeof(val));
+ hdr = (struct ieee80211_hdr *)skb->data;
+ memcpy(&hdr[1], &val, sizeof(val));
}
- bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
+ bf->bf_buf_addr = bf->bf_dmacontext =
+ pci_map_single(sc->pdev, skb->data,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_TODEVICE);
bf->bf_mpdu = skb;
return 0;
@@ -477,9 +423,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
* Reclaim beacon resources and return buffer to the pool.
*
* Checks the VAP to put the beacon frame buffer back to the ATH object
- * queue, and de-allocates any wbuf frames that were sent as CAB traffic.
+ * queue, and de-allocates any skbs that were sent as CAB traffic.
*/
-
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
{
if (avp->av_bcbuf != NULL) {
@@ -493,8 +438,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
- ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
+ pci_unmap_single(sc->pdev, bf->bf_dmacontext,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
}
@@ -505,44 +451,14 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
}
/*
- * Reclaim beacon resources and return buffer to the pool.
- *
- * This function will free any wbuf frames that are still attached to the
- * beacon buffers in the ATH object. Note that this does not de-allocate
- * any wbuf objects that are in the transmit queue and have not yet returned
- * to the ATH object.
-*/
-
-void ath_beacon_free(struct ath_softc *sc)
-{
- struct ath_buf *bf;
-
- list_for_each_entry(bf, &sc->sc_bbuf, list) {
- if (bf->bf_mpdu != NULL) {
- struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu;
- ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
- dev_kfree_skb_any(skb);
- bf->bf_mpdu = NULL;
- }
- }
-}
-
-/*
* Tasklet for Sending Beacons
*
* Transmit one or more beacon frames at SWBA. Dynamic updates to the frame
* contents are done as needed and the slot time is also adjusted based on
* current state.
- *
- * This tasklet is not scheduled, it's called in ISR context.
*/
-
void ath9k_beacon_tasklet(unsigned long data)
{
-#define TSF_TO_TU(_h,_l) \
- ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
-
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf = NULL;
@@ -555,7 +471,7 @@ void ath9k_beacon_tasklet(unsigned long data)
u32 tsftu;
u16 intval;
- if (sc->sc_noreset) {
+ if (sc->sc_flags & SC_OP_NO_RESET) {
show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
&rx_clear,
&rx_frame,
@@ -568,6 +484,8 @@ void ath9k_beacon_tasklet(unsigned long data)
* and wait for the next. Missed beacons indicate
* a problem and should not occur. If we miss too
* many consecutive beacons reset the device.
+ *
+ * FIXME: Clean up this mess !!
*/
if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
sc->sc_bmisscount++;
@@ -577,25 +495,22 @@ void ath9k_beacon_tasklet(unsigned long data)
* (in that layer).
*/
if (sc->sc_bmisscount < BSTUCK_THRESH) {
- if (sc->sc_noreset) {
+ if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc, ATH_DBG_BEACON,
"%s: missed %u consecutive beacons\n",
__func__, sc->sc_bmisscount);
if (show_cycles) {
/*
- * Display cycle counter stats
- * from HW to aide in debug of
- * stickiness.
+ * Display cycle counter stats from HW
+ * to aide in debug of stickiness.
*/
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: busy times: rx_clear=%d, "
"rx_frame=%d, tx_frame=%d\n",
__func__, rx_clear, rx_frame,
tx_frame);
} else {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: unable to obtain "
"busy times\n", __func__);
}
@@ -605,10 +520,9 @@ void ath9k_beacon_tasklet(unsigned long data)
__func__, sc->sc_bmisscount);
}
} else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
- if (sc->sc_noreset) {
+ if (sc->sc_flags & SC_OP_NO_RESET) {
if (sc->sc_bmisscount == BSTUCK_THRESH) {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: beacon is officially "
"stuck\n", __func__);
ath9k_hw_dmaRegDump(ah);
@@ -620,13 +534,12 @@ void ath9k_beacon_tasklet(unsigned long data)
ath_bstuck_process(sc);
}
}
-
return;
}
+
if (sc->sc_bmisscount != 0) {
- if (sc->sc_noreset) {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ if (sc->sc_flags & SC_OP_NO_RESET) {
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: resume beacon xmit after %u misses\n",
__func__, sc->sc_bmisscount);
} else {
@@ -643,17 +556,19 @@ void ath9k_beacon_tasklet(unsigned long data)
* on the tsf to safeguard against missing an swba.
*/
- /* FIXME: Use default value for now - Sujith */
- intval = ATH_DEFAULT_BINTVAL;
+ intval = sc->hw->conf.beacon_int ?
+ sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
+
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
- __func__, slot, (unsigned long long) tsf, tsftu,
- intval, if_id);
+ "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
+ __func__, slot, (unsigned long long)tsf, tsftu,
+ intval, if_id);
+
bfaddr = 0;
if (if_id != ATH_IF_ID_ANY) {
bf = ath_beacon_generate(sc, if_id);
@@ -704,22 +619,20 @@ void ath9k_beacon_tasklet(unsigned long data)
sc->ast_be_xmit += bc; /* XXX per-vap? */
}
-#undef TSF_TO_TU
}
/*
* Tasklet for Beacon Stuck processing
*
* Processing for Beacon Stuck.
- * Basically calls the ath_internal_reset function to reset the chip.
+ * Basically resets the chip.
*/
-
void ath_bstuck_process(struct ath_softc *sc)
{
DPRINTF(sc, ATH_DBG_BEACON,
"%s: stuck beacon; resetting (bmiss count %u)\n",
__func__, sc->sc_bmisscount);
- ath_internal_reset(sc);
+ ath_reset(sc, false);
}
/*
@@ -737,40 +650,32 @@ void ath_bstuck_process(struct ath_softc *sc)
* interrupt when we stop seeing beacons from the AP
* we've associated with.
*/
-
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
-#define TSF_TO_TU(_h,_l) \
- ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
struct ath_hal *ah = sc->sc_ah;
- u32 nexttbtt, intval;
struct ath_beacon_config conf;
enum ath9k_opmode av_opmode;
+ u32 nexttbtt, intval;
if (if_id != ATH_IF_ID_ANY)
av_opmode = sc->sc_vaps[if_id]->av_opmode;
else
- av_opmode = sc->sc_opmode;
+ av_opmode = sc->sc_ah->ah_opmode;
- memzero(&conf, sizeof(struct ath_beacon_config));
+ memset(&conf, 0, sizeof(struct ath_beacon_config));
- /* FIXME: Use default values for now - Sujith */
- /* Query beacon configuration first */
- /*
- * Protocol stack doesn't support dynamic beacon configuration,
- * use default configurations.
- */
- conf.beacon_interval = ATH_DEFAULT_BINTVAL;
+ conf.beacon_interval = sc->hw->conf.beacon_int ?
+ sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
conf.listen_interval = 1;
conf.dtim_period = conf.beacon_interval;
conf.dtim_count = 1;
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
/* extract tstamp from last beacon and convert to TU */
- nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4),
- get_unaligned_le32(conf.u.last_tstamp));
+ nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp);
+
/* XXX conditionalize multi-bss support? */
- if (sc->sc_opmode == ATH9K_M_HOSTAP) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
/*
* For multi-bss ap support beacons are either staggered
* evenly over N slots or burst together. For the former
@@ -784,14 +689,16 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
}
- if (nexttbtt == 0) /* e.g. for ap mode */
+ if (nexttbtt == 0) /* e.g. for ap mode */
nexttbtt = intval;
- else if (intval) /* NB: can be 0 for monitor mode */
+ else if (intval) /* NB: can be 0 for monitor mode */
nexttbtt = roundup(nexttbtt, intval);
+
DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
__func__, nexttbtt, intval, conf.beacon_interval);
+
/* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
- if (sc->sc_opmode == ATH9K_M_STA) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
struct ath9k_beacon_state bs;
u64 tsf;
u32 tsftu;
@@ -803,19 +710,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* last beacon we received (which may be none).
*/
dtimperiod = conf.dtim_period;
- if (dtimperiod <= 0) /* NB: 0 if not known */
+ if (dtimperiod <= 0) /* NB: 0 if not known */
dtimperiod = 1;
dtimcount = conf.dtim_count;
- if (dtimcount >= dtimperiod) /* NB: sanity check */
- dtimcount = 0; /* XXX? */
- cfpperiod = 1; /* NB: no PCF support yet */
+ if (dtimcount >= dtimperiod) /* NB: sanity check */
+ dtimcount = 0;
+ cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
sleepduration = conf.listen_interval * intval;
if (sleepduration <= 0)
sleepduration = intval;
-#define FUDGE 2
+#define FUDGE 2
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
@@ -831,7 +738,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
}
} while (nexttbtt < tsftu);
#undef FUDGE
- memzero(&bs, sizeof(bs));
+ memset(&bs, 0, sizeof(bs));
bs.bs_intval = intval;
bs.bs_nexttbtt = nexttbtt;
bs.bs_dtimperiod = dtimperiod*intval;
@@ -839,6 +746,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
bs.bs_cfpmaxduration = 0;
+
/*
* Calculate the number of consecutive beacons to miss
* before taking a BMISS interrupt. The configuration
@@ -847,9 +755,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* result to at most 15 beacons.
*/
if (sleepduration > intval) {
- bs.bs_bmissthreshold =
- conf.listen_interval *
- ATH_DEFAULT_BMISS_LIMIT / 2;
+ bs.bs_bmissthreshold = conf.listen_interval *
+ ATH_DEFAULT_BMISS_LIMIT / 2;
} else {
bs.bs_bmissthreshold =
DIV_ROUND_UP(conf.bmiss_timeout, intval);
@@ -869,8 +776,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* XXX fixed at 100ms
*/
- bs.bs_sleepduration =
- roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+ bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100),
+ sleepduration);
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
@@ -886,19 +793,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
"cfp:period %u "
"maxdur %u "
"next %u "
- "timoffset %u\n"
- , __func__
- , (unsigned long long)tsf, tsftu
- , bs.bs_intval
- , bs.bs_nexttbtt
- , bs.bs_dtimperiod
- , bs.bs_nextdtim
- , bs.bs_bmissthreshold
- , bs.bs_sleepduration
- , bs.bs_cfpperiod
- , bs.bs_cfpmaxduration
- , bs.bs_cfpnext
- , bs.bs_timoffset
+ "timoffset %u\n",
+ __func__,
+ (unsigned long long)tsf, tsftu,
+ bs.bs_intval,
+ bs.bs_nexttbtt,
+ bs.bs_dtimperiod,
+ bs.bs_nextdtim,
+ bs.bs_bmissthreshold,
+ bs.bs_sleepduration,
+ bs.bs_cfpperiod,
+ bs.bs_cfpmaxduration,
+ bs.bs_cfpnext,
+ bs.bs_timoffset
);
ath9k_hw_set_interrupts(ah, 0);
@@ -911,12 +818,12 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
ath9k_hw_set_interrupts(ah, 0);
if (nexttbtt == intval)
intval |= ATH9K_BEACON_RESET_TSF;
- if (sc->sc_opmode == ATH9K_M_IBSS) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
/*
* Pull nexttbtt forward to reflect the current
- * TSF .
+ * TSF
*/
-#define FUDGE 2
+#define FUDGE 2
if (!(intval & ATH9K_BEACON_RESET_TSF)) {
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU((u32)(tsf>>32),
@@ -943,7 +850,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
sc->sc_imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
- } else if (sc->sc_opmode == ATH9K_M_HOSTAP) {
+ } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
/*
* In AP mode we enable the beacon timers and
* SWBA interrupts to prepare beacon frames.
@@ -959,11 +866,10 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* When using a self-linked beacon descriptor in
* ibss mode load it once here.
*/
- if (sc->sc_opmode == ATH9K_M_IBSS &&
+ if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
ath_beacon_start_adhoc(sc, 0);
}
-#undef TSF_TO_TU
}
/* Function to collect beacon rssi data and resync beacon if necessary */
@@ -975,5 +881,5 @@ void ath_beacon_sync(struct ath_softc *sc, int if_id)
* beacon frame we just received.
*/
ath_beacon_config(sc, if_id);
- sc->sc_beacons = 1;
+ sc->sc_flags |= SC_OP_BEACONS;
}
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index f6c45288d0e..c5033f6f42a 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -21,9 +21,6 @@
static int ath_outdoor; /* enable outdoor use */
-static const u8 ath_bcast_mac[ETH_ALEN] =
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
static u32 ath_chainmask_sel_up_rssi_thres =
ATH_CHAINMASK_SEL_UP_RSSI_THRES;
static u32 ath_chainmask_sel_down_rssi_thres =
@@ -54,10 +51,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
* Set current operating mode
*
* This function initializes and fills the rate table in the ATH object based
- * on the operating mode. The blink rates are also set up here, although
- * they have been superceeded by the ath_led module.
+ * on the operating mode.
*/
-
static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
{
const struct ath9k_rate_table *rt;
@@ -70,7 +65,7 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
for (i = 0; i < rt->rateCount; i++)
sc->sc_rixmap[rt->info[i].rateCode] = (u8) i;
- memzero(sc->sc_hwmap, sizeof(sc->sc_hwmap));
+ memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
for (i = 0; i < 256; i++) {
u8 ix = rt->rateCodeToIndex[i];
@@ -235,7 +230,7 @@ static int ath_setup_channels(struct ath_softc *sc)
* Determine mode from channel flags
*
* This routine will provide the enumerated WIRELESSS_MODE value based
- * on the settings of the channel flags. If ho valid set of flags
+ * on the settings of the channel flags. If no valid set of flags
* exist, the lowest mode (11b) is selected.
*/
@@ -260,7 +255,8 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
else if (chan->chanmode == CHANNEL_G_HT40MINUS)
return ATH9K_MODE_11NG_HT40MINUS;
- /* NB: should not get here */
+ WARN_ON(1); /* should not get here */
+
return ATH9K_MODE_11B;
}
@@ -275,14 +271,12 @@ static int ath_stop(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n",
- __func__, sc->sc_invalid);
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
+ __func__, sc->sc_flags & SC_OP_INVALID);
/*
* Shutdown the hardware and driver:
* stop output from above
- * reset 802.11 state machine
- * (sends station deassoc/deauth frames)
* turn off timers
* disable interrupts
* clear transmit machinery
@@ -294,10 +288,8 @@ static int ath_stop(struct ath_softc *sc)
* hardware is gone (invalid).
*/
- if (!sc->sc_invalid)
- ath9k_hw_set_interrupts(ah, 0);
ath_draintxq(sc, false);
- if (!sc->sc_invalid) {
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
@@ -307,56 +299,6 @@ static int ath_stop(struct ath_softc *sc)
}
/*
- * Start Scan
- *
- * This function is called when starting a channel scan. It will perform
- * power save wakeup processing, set the filter for the scan, and get the
- * chip ready to send broadcast packets out during the scan.
-*/
-
-void ath_scan_start(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- u32 rfilt;
- u32 now = (u32) jiffies_to_msecs(get_timestamp());
-
- sc->sc_scanning = 1;
- rfilt = ath_calcrxfilter(sc);
- ath9k_hw_setrxfilter(ah, rfilt);
- ath9k_hw_write_associd(ah, ath_bcast_mac, 0);
-
- /* Restore previous power management state. */
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n",
- now / 1000, now % 1000, __func__, rfilt);
-}
-
-/*
- * Scan End
- *
- * This routine is called by the upper layer when the scan is completed. This
- * will set the filters back to normal operating mode, set the BSSID to the
- * correct value, and restore the power save state.
-*/
-
-void ath_scan_end(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- u32 rfilt;
- u32 now = (u32) jiffies_to_msecs(get_timestamp());
-
- sc->sc_scanning = 0;
- /* Request for a full reset due to rx packet filter changes */
- sc->sc_full_reset = 1;
- rfilt = ath_calcrxfilter(sc);
- ath9k_hw_setrxfilter(ah, rfilt);
- ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n",
- now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid);
-}
-
-/*
* Set the current channel
*
* Set/change channels. If the channel is really being changed, it's done
@@ -367,25 +309,23 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
{
struct ath_hal *ah = sc->sc_ah;
bool fastcc = true, stopped;
- enum ath9k_ht_macmode ht_macmode;
- if (sc->sc_invalid) /* if the device is invalid or removed */
+ if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */
return -EIO;
DPRINTF(sc, ATH_DBG_CONFIG,
"%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
__func__,
- ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel,
- sc->sc_curchan.channelFlags),
- sc->sc_curchan.channel,
+ ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
+ sc->sc_ah->ah_curchan->channelFlags),
+ sc->sc_ah->ah_curchan->channel,
ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
hchan->channel, hchan->channelFlags);
- ht_macmode = ath_cwm_macmode(sc);
-
- if (hchan->channel != sc->sc_curchan.channel ||
- hchan->channelFlags != sc->sc_curchan.channelFlags ||
- sc->sc_update_chainmask || sc->sc_full_reset) {
+ if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
+ hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
+ (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
+ (sc->sc_flags & SC_OP_FULL_RESET)) {
int status;
/*
* This is only performed if the channel settings have
@@ -404,15 +344,16 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
* to flush data frames already in queue because of
* changing channel. */
- if (!stopped || sc->sc_full_reset)
+ if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
fastcc = false;
spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan,
- ht_macmode, sc->sc_tx_chainmask,
- sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing,
- fastcc, &status)) {
+ if (!ath9k_hw_reset(ah, hchan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask,
+ sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing,
+ fastcc, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: unable to reset channel %u (%uMhz) "
"flags 0x%x hal status %u\n", __func__,
@@ -424,9 +365,8 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
}
spin_unlock_bh(&sc->sc_resetlock);
- sc->sc_curchan = *hchan;
- sc->sc_update_chainmask = 0;
- sc->sc_full_reset = 0;
+ sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
+ sc->sc_flags &= ~SC_OP_FULL_RESET;
/* Re-enable rx framework */
if (ath_startrecv(sc) != 0) {
@@ -477,7 +417,7 @@ static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an)
{
struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
- memzero(cm, sizeof(struct ath_chainmask_sel));
+ memset(cm, 0, sizeof(struct ath_chainmask_sel));
cm->cur_tx_mask = sc->sc_tx_chainmask;
cm->cur_rx_mask = sc->sc_rx_chainmask;
@@ -537,7 +477,7 @@ int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an)
void ath_update_chainmask(struct ath_softc *sc, int is_ht)
{
- sc->sc_update_chainmask = 1;
+ sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
if (is_ht) {
sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
@@ -550,66 +490,126 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht)
__func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask);
}
-/******************/
-/* VAP management */
-/******************/
+/*******/
+/* ANI */
+/*******/
/*
- * VAP in Listen mode
- *
- * This routine brings the VAP out of the down state into a "listen" state
- * where it waits for association requests. This is used in AP and AdHoc
- * modes.
-*/
+ * This routine performs the periodic noise floor calibration function
+ * that is used to adjust and optimize the chip performance. This
+ * takes environmental changes (location, temperature) into account.
+ * When the task is complete, it reschedules itself depending on the
+ * appropriate interval that was calculated.
+ */
-int ath_vap_listen(struct ath_softc *sc, int if_id)
+static void ath_ani_calibrate(unsigned long data)
{
- struct ath_hal *ah = sc->sc_ah;
- struct ath_vap *avp;
- u32 rfilt = 0;
- DECLARE_MAC_BUF(mac);
+ struct ath_softc *sc;
+ struct ath_hal *ah;
+ bool longcal = false;
+ bool shortcal = false;
+ bool aniflag = false;
+ unsigned int timestamp = jiffies_to_msecs(jiffies);
+ u32 cal_interval;
- avp = sc->sc_vaps[if_id];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
- __func__, if_id);
- return -EINVAL;
- }
+ sc = (struct ath_softc *)data;
+ ah = sc->sc_ah;
-#ifdef CONFIG_SLOW_ANT_DIV
- ath_slow_ant_div_stop(&sc->sc_antdiv);
-#endif
+ /*
+ * don't calibrate when we're scanning.
+ * we are most likely not on our home channel.
+ */
+ if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
+ return;
- /* update ratectrl about the new state */
- ath_rate_newstate(sc, avp);
+ /* Long calibration runs independently of short calibration. */
+ if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
+ longcal = true;
+ DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n",
+ __func__, jiffies);
+ sc->sc_ani.sc_longcal_timer = timestamp;
+ }
- rfilt = ath_calcrxfilter(sc);
- ath9k_hw_setrxfilter(ah, rfilt);
+ /* Short calibration applies only while sc_caldone is false */
+ if (!sc->sc_ani.sc_caldone) {
+ if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
+ ATH_SHORT_CALINTERVAL) {
+ shortcal = true;
+ DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n",
+ __func__, jiffies);
+ sc->sc_ani.sc_shortcal_timer = timestamp;
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ } else {
+ if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
+ ATH_RESTART_CALINTERVAL) {
+ ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
+ &sc->sc_ani.sc_caldone);
+ if (sc->sc_ani.sc_caldone)
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ }
- if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) {
- memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN);
- ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
- } else
- sc->sc_curaid = 0;
+ /* Verify whether we must check ANI */
+ if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
+ ATH_ANI_POLLINTERVAL) {
+ aniflag = true;
+ sc->sc_ani.sc_checkani_timer = timestamp;
+ }
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: RX filter 0x%x bssid %s aid 0x%x\n",
- __func__, rfilt, print_mac(mac,
- sc->sc_curbssid), sc->sc_curaid);
+ /* Skip all processing if there's nothing to do. */
+ if (longcal || shortcal || aniflag) {
+ /* Call ANI routine if necessary */
+ if (aniflag)
+ ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
+ ah->ah_curchan);
+
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ bool iscaldone = false;
+
+ if (ath9k_hw_calibrate(ah, ah->ah_curchan,
+ sc->sc_rx_chainmask, longcal,
+ &iscaldone)) {
+ if (longcal)
+ sc->sc_ani.sc_noise_floor =
+ ath9k_hw_getchan_noise(ah,
+ ah->ah_curchan);
+
+ DPRINTF(sc, ATH_DBG_ANI,
+ "%s: calibrate chan %u/%x nf: %d\n",
+ __func__,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags,
+ sc->sc_ani.sc_noise_floor);
+ } else {
+ DPRINTF(sc, ATH_DBG_ANY,
+ "%s: calibrate chan %u/%x failed\n",
+ __func__,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags);
+ }
+ sc->sc_ani.sc_caldone = iscaldone;
+ }
+ }
/*
- * XXXX
- * Disable BMISS interrupt when we're not associated
- */
- ath9k_hw_set_interrupts(ah,
- sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
- sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
- /* need to reconfigure the beacons when it moves to RUN */
- sc->sc_beacons = 0;
+ * Set timer interval based on previous results.
+ * The interval must be the shortest necessary to satisfy ANI,
+ * short calibration and long calibration.
+ */
- return 0;
+ cal_interval = ATH_ANI_POLLINTERVAL;
+ if (!sc->sc_ani.sc_caldone)
+ cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
+
+ mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
}
+/******************/
+/* VAP management */
+/******************/
+
int ath_vap_attach(struct ath_softc *sc,
int if_id,
struct ieee80211_vif *if_data,
@@ -642,21 +642,19 @@ int ath_vap_attach(struct ath_softc *sc,
if (avp == NULL)
return -ENOMEM;
- memzero(avp, sizeof(struct ath_vap));
+ memset(avp, 0, sizeof(struct ath_vap));
avp->av_if_data = if_data;
/* Set the VAP opmode */
avp->av_opmode = opmode;
avp->av_bslot = -1;
- INIT_LIST_HEAD(&avp->av_mcastq.axq_q);
- INIT_LIST_HEAD(&avp->av_mcastq.axq_acq);
- spin_lock_init(&avp->av_mcastq.axq_lock);
- ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
+ if (opmode == ATH9K_M_HOSTAP)
+ ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_vaps[if_id] = avp;
sc->sc_nvaps++;
/* Set the device opmode */
- sc->sc_opmode = opmode;
+ sc->sc_ah->ah_opmode = opmode;
/* default VAP configuration */
avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
@@ -689,9 +687,6 @@ int ath_vap_detach(struct ath_softc *sc, int if_id)
ath_stoprecv(sc); /* stop recv side */
ath_flushrecv(sc); /* flush recv queue */
- /* Reclaim any pending mcast bufs on the vap. */
- ath_tx_draintxq(sc, &avp->av_mcastq, false);
-
kfree(avp);
sc->sc_vaps[if_id] = NULL;
sc->sc_nvaps--;
@@ -728,9 +723,9 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
struct ath_hal *ah = sc->sc_ah;
int status;
int error = 0;
- enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode);
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
+ __func__, sc->sc_ah->ah_opmode);
/*
* Stop anything previously setup. This is safe
@@ -752,16 +747,16 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- sc->sc_curchan = *initial_chan;
spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode,
- sc->sc_tx_chainmask, sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing, false, &status)) {
+ if (!ath9k_hw_reset(ah, initial_chan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, false, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: unable to reset hardware; hal status %u "
"(freq %u flags 0x%x)\n", __func__, status,
- sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
+ initial_chan->channel, initial_chan->channelFlags);
error = -EIO;
spin_unlock_bh(&sc->sc_resetlock);
goto done;
@@ -802,7 +797,8 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
* Note we only do this (at the moment) for station mode.
*/
if (ath9k_hw_phycounters(ah) &&
- ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS)))
+ ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
+ (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
sc->sc_imask |= ATH9K_INT_MIB;
/*
* Some hardware processes the TIM IE and fires an
@@ -811,7 +807,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
* enable the TIM interrupt when operating as station.
*/
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
- (sc->sc_opmode == ATH9K_M_STA) &&
+ (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
!sc->sc_config.swBeaconProcess)
sc->sc_imask |= ATH9K_INT_TIM;
/*
@@ -823,34 +819,34 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
/* XXX: we must make sure h/w is ready and clear invalid flag
* before turning on interrupt. */
- sc->sc_invalid = 0;
+ sc->sc_flags &= ~SC_OP_INVALID;
done:
return error;
}
-/*
- * Reset the hardware w/o losing operational state. This is
- * basically a more efficient way of doing ath_stop, ath_init,
- * followed by state transitions to the current 802.11
- * operational state. Used to recover from errors rx overrun
- * and to reset the hardware when rf gain settings must be reset.
- */
-
-static int ath_reset_start(struct ath_softc *sc, u32 flag)
+int ath_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hal *ah = sc->sc_ah;
+ int status;
+ int error = 0;
ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
- ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */
- ath_stoprecv(sc); /* stop recv side */
- ath_flushrecv(sc); /* flush recv queue */
+ ath_draintxq(sc, retry_tx); /* stop xmit */
+ ath_stoprecv(sc); /* stop recv */
+ ath_flushrecv(sc); /* flush recv queue */
- return 0;
-}
-
-static int ath_reset_end(struct ath_softc *sc, u32 flag)
-{
- struct ath_hal *ah = sc->sc_ah;
+ /* Reset chip */
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, false, &status)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: unable to reset hardware; hal status %u\n",
+ __func__, status);
+ error = -EIO;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0) /* restart recv */
DPRINTF(sc, ATH_DBG_FATAL,
@@ -861,16 +857,17 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag)
* that changes the channel so update any state that
* might change as a result.
*/
- ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan));
+ ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
- ath_update_txpow(sc); /* update tx power state */
+ ath_update_txpow(sc);
- if (sc->sc_beacons)
+ if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
+
ath9k_hw_set_interrupts(ah, sc->sc_imask);
/* Restart the txq */
- if (flag & RESET_RETRY_TXQ) {
+ if (retry_tx) {
int i;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
@@ -880,28 +877,6 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag)
}
}
}
- return 0;
-}
-
-int ath_reset(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- int status;
- int error = 0;
- enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
-
- /* NB: indicate channel change so we do a full reset */
- spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan,
- ht_macmode,
- sc->sc_tx_chainmask, sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing, false, &status)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset hardware; hal status %u\n",
- __func__, status);
- error = -EIO;
- }
- spin_unlock_bh(&sc->sc_resetlock);
return error;
}
@@ -911,7 +886,7 @@ int ath_suspend(struct ath_softc *sc)
struct ath_hal *ah = sc->sc_ah;
/* No I/O if device has been surprise removed */
- if (sc->sc_invalid)
+ if (sc->sc_flags & SC_OP_INVALID)
return -EIO;
/* Shut off the interrupt before setting sc->sc_invalid to '1' */
@@ -919,7 +894,7 @@ int ath_suspend(struct ath_softc *sc)
/* XXX: we must make sure h/w will not generate any interrupt
* before setting the invalid flag. */
- sc->sc_invalid = 1;
+ sc->sc_flags |= SC_OP_INVALID;
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
@@ -940,7 +915,7 @@ irqreturn_t ath_isr(int irq, void *dev)
bool sched = false;
do {
- if (sc->sc_invalid) {
+ if (sc->sc_flags & SC_OP_INVALID) {
/*
* The hardware is not ready/present, don't
* touch anything. Note this can happen early
@@ -1050,7 +1025,7 @@ static void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_FATAL) {
/* need a chip reset */
- ath_internal_reset(sc);
+ ath_reset(sc, false);
return;
} else {
@@ -1093,10 +1068,9 @@ int ath_init(u16 devid, struct ath_softc *sc)
int status;
int error = 0, i;
int csz = 0;
- u32 rd;
/* XXX: hardware will not be ready until ath_open() being called */
- sc->sc_invalid = 1;
+ sc->sc_flags |= SC_OP_INVALID;
sc->sc_debug = DBG_DEFAULT;
DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
@@ -1126,8 +1100,9 @@ int ath_init(u16 devid, struct ath_softc *sc)
}
sc->sc_ah = ah;
- /* Get the chipset-specific aggr limit. */
- sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit;
+ /* Initializes the noise floor to a reasonable default value.
+ * Later on this will be updated during ANI processing. */
+ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
/* Get the hardware key cache size. */
sc->sc_keymax = ah->ah_caps.keycache_size;
@@ -1162,14 +1137,12 @@ int ath_init(u16 devid, struct ath_softc *sc)
* is resposible for filtering this list based on settings
* like the phy mode.
*/
- rd = ah->ah_currentRD;
-
error = ath_setup_channels(sc);
if (error)
goto bad;
/* default to STA mode */
- sc->sc_opmode = ATH9K_M_MONITOR;
+ sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
/* Setup rate tables */
@@ -1238,9 +1211,11 @@ int ath_init(u16 devid, struct ath_softc *sc)
goto bad2;
}
+ setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
sc->sc_rc = ath_rate_attach(ah);
if (sc->sc_rc == NULL) {
- error = EIO;
+ error = -EIO;
goto bad2;
}
@@ -1280,20 +1255,13 @@ int ath_init(u16 devid, struct ath_softc *sc)
/* 11n Capabilities */
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
- sc->sc_txaggr = 1;
- sc->sc_rxaggr = 1;
+ sc->sc_flags |= SC_OP_TXAGGR;
+ sc->sc_flags |= SC_OP_RXAGGR;
}
sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
- /* Configuration for rx chain detection */
- sc->sc_rxchaindetect_ref = 0;
- sc->sc_rxchaindetect_thresh5GHz = 35;
- sc->sc_rxchaindetect_thresh2GHz = 35;
- sc->sc_rxchaindetect_delta5GHz = 30;
- sc->sc_rxchaindetect_delta2GHz = 30;
-
ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
sc->sc_defant = ath9k_hw_getdefantenna(ah);
@@ -1336,8 +1304,10 @@ void ath_deinit(struct ath_softc *sc)
DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
+ tasklet_kill(&sc->intr_tq);
+ tasklet_kill(&sc->bcon_tasklet);
ath_stop(sc);
- if (!sc->sc_invalid)
+ if (!(sc->sc_flags & SC_OP_INVALID))
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
ath_rate_detach(sc->sc_rc);
/* cleanup tx queues */
@@ -1364,7 +1334,7 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
if (an == NULL)
return NULL;
- memzero(an, sizeof(*an));
+ memset(an, 0, sizeof(*an));
an->an_sc = sc;
memcpy(an->an_addr, addr, ETH_ALEN);
@@ -1464,9 +1434,9 @@ void ath_newassoc(struct ath_softc *sc,
/* if station reassociates, tear down the aggregation state. */
if (!isnew) {
for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
- if (sc->sc_txaggr)
+ if (sc->sc_flags & SC_OP_TXAGGR)
ath_tx_aggr_teardown(sc, an, tidno);
- if (sc->sc_rxaggr)
+ if (sc->sc_flags & SC_OP_RXAGGR)
ath_rx_aggr_teardown(sc, an, tidno);
}
}
@@ -1751,7 +1721,7 @@ int ath_descdma_setup(struct ath_softc *sc,
error = -ENOMEM;
goto fail2;
}
- memzero(bf, bsize);
+ memset(bf, 0, bsize);
dd->dd_bufptr = bf;
INIT_LIST_HEAD(head);
@@ -1783,7 +1753,7 @@ fail2:
pci_free_consistent(sc->pdev,
dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
fail:
- memzero(dd, sizeof(*dd));
+ memset(dd, 0, sizeof(*dd));
return error;
#undef ATH_DESC_4KB_BOUND_CHECK
#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
@@ -1808,20 +1778,13 @@ void ath_descdma_cleanup(struct ath_softc *sc,
INIT_LIST_HEAD(head);
kfree(dd->dd_bufptr);
- memzero(dd, sizeof(*dd));
+ memset(dd, 0, sizeof(*dd));
}
/*************/
/* Utilities */
/*************/
-void ath_internal_reset(struct ath_softc *sc)
-{
- ath_reset_start(sc, 0);
- ath_reset(sc);
- ath_reset_end(sc, 0);
-}
-
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
{
int qnum;
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index 673b3d81133..cb3e61e57c4 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -39,6 +39,8 @@
#include <linux/scatterlist.h>
#include <asm/page.h>
#include <net/mac80211.h>
+#include <linux/leds.h>
+#include <linux/rfkill.h>
#include "ath9k.h"
#include "rc.h"
@@ -79,11 +81,8 @@ struct ath_node;
} \
} while (0)
-/* XXX: remove */
-#define memzero(_buf, _len) memset(_buf, 0, _len)
-
-#define get_dma_mem_context(var, field) (&((var)->field))
-#define copy_dma_mem_context(dst, src) (*dst = *src)
+#define TSF_TO_TU(_h,_l) \
+ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
#define ATH9K_BH_STATUS_INTACT 0
#define ATH9K_BH_STATUS_CHANGE 1
@@ -95,6 +94,8 @@ static inline unsigned long get_timestamp(void)
return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
}
+static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
/*************/
/* Debugging */
/*************/
@@ -175,42 +176,38 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht);
/* Descriptor Management */
/*************************/
-/* Number of descriptors per buffer. The only case where we see skbuff
-chains is due to FF aggregation in the driver. */
-#define ATH_TXDESC 1
-/* if there's more fragment for this MSDU */
-#define ATH_BF_MORE_MPDU 1
#define ATH_TXBUF_RESET(_bf) do { \
(_bf)->bf_status = 0; \
(_bf)->bf_lastbf = NULL; \
(_bf)->bf_lastfrm = NULL; \
(_bf)->bf_next = NULL; \
- memzero(&((_bf)->bf_state), \
+ memset(&((_bf)->bf_state), 0, \
sizeof(struct ath_buf_state)); \
} while (0)
+enum buffer_type {
+ BUF_DATA = BIT(0),
+ BUF_AGGR = BIT(1),
+ BUF_AMPDU = BIT(2),
+ BUF_HT = BIT(3),
+ BUF_RETRY = BIT(4),
+ BUF_XRETRY = BIT(5),
+ BUF_SHORT_PREAMBLE = BIT(6),
+ BUF_BAR = BIT(7),
+ BUF_PSPOLL = BIT(8),
+ BUF_AGGR_BURST = BIT(9),
+ BUF_CALC_AIRTIME = BIT(10),
+};
+
struct ath_buf_state {
- int bfs_nframes; /* # frames in aggregate */
- u16 bfs_al; /* length of aggregate */
- u16 bfs_frmlen; /* length of frame */
- int bfs_seqno; /* sequence number */
- int bfs_tidno; /* tid of this frame */
- int bfs_retries; /* current retries */
+ int bfs_nframes; /* # frames in aggregate */
+ u16 bfs_al; /* length of aggregate */
+ u16 bfs_frmlen; /* length of frame */
+ int bfs_seqno; /* sequence number */
+ int bfs_tidno; /* tid of this frame */
+ int bfs_retries; /* current retries */
struct ath_rc_series bfs_rcs[4]; /* rate series */
- u8 bfs_isdata:1; /* is a data frame/aggregate */
- u8 bfs_isaggr:1; /* is an aggregate */
- u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */
- u8 bfs_ht:1; /* is an HT frame */
- u8 bfs_isretried:1; /* is retried */
- u8 bfs_isxretried:1; /* is excessive retried */
- u8 bfs_shpreamble:1; /* is short preamble */
- u8 bfs_isbar:1; /* is a BAR */
- u8 bfs_ispspoll:1; /* is a PS-Poll */
- u8 bfs_aggrburst:1; /* is a aggr burst */
- u8 bfs_calcairtime:1; /* requests airtime be calculated
- when set for tx frame */
- int bfs_rifsburst_elem; /* RIFS burst/bar */
- int bfs_nrifsubframes; /* # of elements in burst */
+ u32 bf_type; /* BUF_* (enum buffer_type) */
/* key type use to encrypt this frame */
enum ath9k_key_type bfs_keytype;
};
@@ -222,26 +219,22 @@ struct ath_buf_state {
#define bf_seqno bf_state.bfs_seqno
#define bf_tidno bf_state.bfs_tidno
#define bf_rcs bf_state.bfs_rcs
-#define bf_isdata bf_state.bfs_isdata
-#define bf_isaggr bf_state.bfs_isaggr
-#define bf_isampdu bf_state.bfs_isampdu
-#define bf_ht bf_state.bfs_ht
-#define bf_isretried bf_state.bfs_isretried
-#define bf_isxretried bf_state.bfs_isxretried
-#define bf_shpreamble bf_state.bfs_shpreamble
-#define bf_rifsburst_elem bf_state.bfs_rifsburst_elem
-#define bf_nrifsubframes bf_state.bfs_nrifsubframes
#define bf_keytype bf_state.bfs_keytype
-#define bf_isbar bf_state.bfs_isbar
-#define bf_ispspoll bf_state.bfs_ispspoll
-#define bf_aggrburst bf_state.bfs_aggrburst
-#define bf_calcairtime bf_state.bfs_calcairtime
+#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA)
+#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
+#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT)
+#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
+#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
+#define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE)
+#define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR)
+#define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL)
+#define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST)
/*
* Abstraction of a contiguous buffer to transmit/receive. There is only
* a single hw descriptor encapsulated here.
*/
-
struct ath_buf {
struct list_head list;
struct list_head *last;
@@ -316,7 +309,7 @@ void ath_descdma_cleanup(struct ath_softc *sc,
#define ATH_RX_TIMEOUT 40 /* 40 milliseconds */
#define WME_NUM_TID 16
#define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */
-#define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */
+#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */
enum ATH_RX_TYPE {
ATH_RX_NON_CONSUMED = 0,
@@ -391,10 +384,10 @@ int ath_rx_input(struct ath_softc *sc,
struct sk_buff *skb,
struct ath_recv_status *rx_status,
enum ATH_RX_TYPE *status);
-int ath__rx_indicate(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- u16 keyix);
+int _ath_rx_indicate(struct ath_softc *sc,
+ struct sk_buff *skb,
+ struct ath_recv_status *status,
+ u16 keyix);
int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
struct ath_recv_status *status);
@@ -402,8 +395,7 @@ int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
/* TX */
/******/
-#define ATH_FRAG_PER_MSDU 1
-#define ATH_TXBUF (512/ATH_FRAG_PER_MSDU)
+#define ATH_TXBUF 512
/* max number of transmit attempts (tries) */
#define ATH_TXMAXTRY 13
/* max number of 11n transmit attempts (tries) */
@@ -522,7 +514,6 @@ struct ath_tx_control {
u32 keyix;
int min_rate;
int mcast_rate;
- u16 nextfraglen;
struct ath_softc *dev;
dma_addr_t dmacontext;
};
@@ -557,10 +548,10 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype);
void ath_draintxq(struct ath_softc *sc, bool retry_tx);
void ath_tx_draintxq(struct ath_softc *sc,
- struct ath_txq *txq, bool retry_tx);
+ struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc,
- struct ath_node *an, bool bh_flag);
+ struct ath_node *an, bool bh_flag);
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_init(struct ath_softc *sc, int nbufs);
@@ -575,6 +566,7 @@ u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
struct ath_xmit_status *tx_status, struct ath_node *an);
+void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
/**********************/
/* Node / Aggregation */
@@ -585,7 +577,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
/* indicates the node is 80211 power save */
#define ATH_NODE_PWRSAVE 0x2
-#define ADDBA_TIMEOUT 200 /* 200 milliseconds */
#define ADDBA_EXCHANGE_ATTEMPTS 10
#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
@@ -705,9 +696,6 @@ struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
#define ATH_BCBUF 4 /* number of beacon buffers */
#define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */
#define ATH_DEFAULT_BMISS_LIMIT 10
-#define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */
-#define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */
-#define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
/* beacon configuration */
@@ -724,30 +712,16 @@ struct ath_beacon_config {
} u; /* last received beacon/probe response timestamp of this BSS. */
};
-/* offsets in a beacon frame for
- * quick acess of beacon content by low-level driver */
-struct ath_beacon_offset {
- u8 *bo_tim; /* start of atim/dtim */
-};
-
void ath9k_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, int if_id);
int ath_beaconq_setup(struct ath_hal *ah);
int ath_beacon_alloc(struct ath_softc *sc, int if_id);
void ath_bstuck_process(struct ath_softc *sc);
-void ath_beacon_tasklet(struct ath_softc *sc, int *needmark);
-void ath_beacon_free(struct ath_softc *sc);
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
void ath_beacon_sync(struct ath_softc *sc, int if_id);
-void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi);
void ath_get_beaconconfig(struct ath_softc *sc,
int if_id,
struct ath_beacon_config *conf);
-int ath_update_beacon(struct ath_softc *sc,
- int if_id,
- struct ath_beacon_offset *bo,
- struct sk_buff *skb,
- int mcast);
/********/
/* VAPs */
/********/
@@ -774,10 +748,8 @@ struct ath_vap {
struct ieee80211_vif *av_if_data;
enum ath9k_opmode av_opmode; /* VAP operational mode */
struct ath_buf *av_bcbuf; /* beacon buffer */
- struct ath_beacon_offset av_boff; /* dynamic update state */
struct ath_tx_control av_btxctl; /* txctl information for beacon */
int av_bslot; /* beacon slot index */
- struct ath_txq av_mcastq; /* multicast transmit queue */
struct ath_vap_config av_config;/* vap configuration parameters*/
struct ath_rate_node *rc_node;
};
@@ -788,8 +760,7 @@ int ath_vap_attach(struct ath_softc *sc,
enum ath9k_opmode opmode);
int ath_vap_detach(struct ath_softc *sc, int if_id);
int ath_vap_config(struct ath_softc *sc,
- int if_id, struct ath_vap_config *if_config);
-int ath_vap_listen(struct ath_softc *sc, int if_id);
+ int if_id, struct ath_vap_config *if_config);
/*********************/
/* Antenna diversity */
@@ -829,6 +800,58 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv,
struct ath_rx_status *rx_stats);
void ath_setdefantenna(void *sc, u32 antenna);
+/*******/
+/* ANI */
+/*******/
+
+/* ANI values for STA only.
+ FIXME: Add appropriate values for AP later */
+
+#define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */
+#define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */
+#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */
+#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */
+
+struct ath_ani {
+ bool sc_caldone;
+ int16_t sc_noise_floor;
+ unsigned int sc_longcal_timer;
+ unsigned int sc_shortcal_timer;
+ unsigned int sc_resetcal_timer;
+ unsigned int sc_checkani_timer;
+ struct timer_list timer;
+};
+
+/********************/
+/* LED Control */
+/********************/
+
+#define ATH_LED_PIN 1
+
+enum ath_led_type {
+ ATH_LED_RADIO,
+ ATH_LED_ASSOC,
+ ATH_LED_TX,
+ ATH_LED_RX
+};
+
+struct ath_led {
+ struct ath_softc *sc;
+ struct led_classdev led_cdev;
+ enum ath_led_type led_type;
+ char name[32];
+ bool registered;
+};
+
+/* Rfkill */
+#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
+
+struct ath_rfkill {
+ struct rfkill *rfkill;
+ struct delayed_work rfkill_poll;
+ char rfkill_name[32];
+};
+
/********************/
/* Main driver core */
/********************/
@@ -841,11 +864,7 @@ void ath_setdefantenna(void *sc, u32 antenna);
#define ATH_DEFAULT_NOISE_FLOOR -95
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
-#define ATH_PREAMBLE_SHORT (1<<0)
-#define ATH_PROTECT_ENABLE (1<<1)
#define ATH_MAX_SW_RETRIES 10
-/* Num farmes difference in tx to flip default recv */
-#define ATH_ANTENNA_DIFF 2
#define ATH_CHAN_MAX 255
#define IEEE80211_WEP_NKID 4 /* number of key ids */
#define IEEE80211_RATE_VAL 0x7f
@@ -859,9 +878,7 @@ void ath_setdefantenna(void *sc, u32 antenna);
*/
#define ATH_KEYMAX 128 /* max key cache size we handle */
-#define RESET_RETRY_TXQ 0x00000001
#define ATH_IF_ID_ANY 0xff
-
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
#define RSSI_LPF_THRESHOLD -20
@@ -907,60 +924,64 @@ struct ath_ht_info {
u8 ext_chan_offset;
};
+#define SC_OP_INVALID BIT(0)
+#define SC_OP_BEACONS BIT(1)
+#define SC_OP_RXAGGR BIT(2)
+#define SC_OP_TXAGGR BIT(3)
+#define SC_OP_CHAINMASK_UPDATE BIT(4)
+#define SC_OP_FULL_RESET BIT(5)
+#define SC_OP_NO_RESET BIT(6)
+#define SC_OP_PREAMBLE_SHORT BIT(7)
+#define SC_OP_PROTECT_ENABLE BIT(8)
+#define SC_OP_RXFLUSH BIT(9)
+#define SC_OP_LED_ASSOCIATED BIT(10)
+#define SC_OP_RFKILL_REGISTERED BIT(11)
+#define SC_OP_RFKILL_SW_BLOCKED BIT(12)
+#define SC_OP_RFKILL_HW_BLOCKED BIT(13)
+
struct ath_softc {
struct ieee80211_hw *hw;
struct pci_dev *pdev;
- void __iomem *mem;
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
- struct ath_config sc_config; /* load-time parameters */
- int sc_debug;
+ struct ath_config sc_config;
struct ath_hal *sc_ah;
- struct ath_rate_softc *sc_rc; /* tx rate control support */
+ struct ath_rate_softc *sc_rc;
+ void __iomem *mem;
+
+ u8 sc_curbssid[ETH_ALEN];
+ u8 sc_myaddr[ETH_ALEN];
+ u8 sc_bssidmask[ETH_ALEN];
+
+ int sc_debug;
u32 sc_intrstatus;
- enum ath9k_opmode sc_opmode; /* current operating mode */
-
- u8 sc_invalid; /* being detached */
- u8 sc_beacons; /* beacons running */
- u8 sc_scanning; /* scanning active */
- u8 sc_txaggr; /* enable 11n tx aggregation */
- u8 sc_rxaggr; /* enable 11n rx aggregation */
- u8 sc_update_chainmask; /* change chain mask */
- u8 sc_full_reset; /* force full reset */
- enum wireless_mode sc_curmode; /* current phy mode */
+ u32 sc_flags; /* SC_OP_* */
+ unsigned int rx_filter;
u16 sc_curtxpow;
u16 sc_curaid;
- u8 sc_curbssid[ETH_ALEN];
- u8 sc_myaddr[ETH_ALEN];
+ u16 sc_cachelsz;
+ int sc_slotupdate; /* slot to next advance fsm */
+ int sc_slottime;
+ int sc_bslot[ATH_BCBUF];
+ u8 sc_tx_chainmask;
+ u8 sc_rx_chainmask;
+ enum ath9k_int sc_imask;
+ enum wireless_mode sc_curmode; /* current phy mode */
enum PROT_MODE sc_protmode;
- u8 sc_mcastantenna;
- u8 sc_txantenna; /* data tx antenna (fixed or auto) */
+
u8 sc_nbcnvaps; /* # of vaps sending beacons */
u16 sc_nvaps; /* # of active virtual ap's */
struct ath_vap *sc_vaps[ATH_BCBUF];
- enum ath9k_int sc_imask;
- u8 sc_bssidmask[ETH_ALEN];
+
+ u8 sc_mcastantenna;
u8 sc_defant; /* current default antenna */
u8 sc_rxotherant; /* rx's on non-default antenna */
- u16 sc_cachelsz;
- int sc_slotupdate; /* slot to next advance fsm */
- int sc_slottime;
- u8 sc_noreset;
- int sc_bslot[ATH_BCBUF];
+
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
struct list_head node_list;
struct ath_ht_info sc_ht_info;
- int16_t sc_noise_floor; /* signal noise floor in dBm */
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
- u8 sc_tx_chainmask;
- u8 sc_rx_chainmask;
- u8 sc_rxchaindetect_ref;
- u8 sc_rxchaindetect_thresh5GHz;
- u8 sc_rxchaindetect_thresh2GHz;
- u8 sc_rxchaindetect_delta5GHz;
- u8 sc_rxchaindetect_delta2GHz;
- u32 sc_rtsaggrlimit; /* Chipset specific aggr limit */
- u32 sc_flags;
+
#ifdef CONFIG_SLOW_ANT_DIV
struct ath_antdiv sc_antdiv;
#endif
@@ -974,15 +995,12 @@ struct ath_softc {
u32 sc_keymax; /* size of key cache */
DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */
u8 sc_splitmic; /* split TKIP MIC keys */
- int sc_keytype;
/* RX */
struct list_head sc_rxbuf;
struct ath_descdma sc_rxdma;
int sc_rxbufsize; /* rx size based on mtu */
u32 *sc_rxlink; /* link ptr in last RX desc */
- u32 sc_rxflush; /* rx flush in progress */
- u64 sc_lastrx; /* tsf of last rx'd frame */
/* TX */
struct list_head sc_txbuf;
@@ -991,7 +1009,7 @@ struct ath_softc {
u32 sc_txqsetup;
u32 sc_txintrperiod; /* tx interrupt batching */
int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */
- u32 sc_ant_tx[8]; /* recent tx frames/antenna */
+ u16 seq_no; /* TX sequence number */
/* Beacon */
struct ath9k_tx_queue_info sc_beacon_qi;
@@ -1001,6 +1019,7 @@ struct ath_softc {
u32 sc_bhalq;
u32 sc_bmisscount;
u32 ast_be_xmit; /* beacons transmitted */
+ u64 bc_tstamp;
/* Rate */
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
@@ -1015,7 +1034,6 @@ struct ath_softc {
/* Channel, Band */
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
- struct ath9k_channel sc_curchan;
/* Locks */
spinlock_t sc_rxflushlock;
@@ -1023,6 +1041,18 @@ struct ath_softc {
spinlock_t sc_txbuflock;
spinlock_t sc_resetlock;
spinlock_t node_lock;
+
+ /* LEDs */
+ struct ath_led radio_led;
+ struct ath_led assoc_led;
+ struct ath_led tx_led;
+ struct ath_led rx_led;
+
+ /* Rfkill */
+ struct ath_rfkill rf_kill;
+
+ /* ANI */
+ struct ath_ani sc_ani;
};
int ath_init(u16 devid, struct ath_softc *sc);
@@ -1030,14 +1060,8 @@ void ath_deinit(struct ath_softc *sc);
int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
int ath_suspend(struct ath_softc *sc);
irqreturn_t ath_isr(int irq, void *dev);
-int ath_reset(struct ath_softc *sc);
-void ath_scan_start(struct ath_softc *sc);
-void ath_scan_end(struct ath_softc *sc);
+int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
-void ath_setup_rate(struct ath_softc *sc,
- enum wireless_mode wMode,
- enum RATE_TYPE type,
- const struct ath9k_rate_table *rt);
/*********************/
/* Utility Functions */
@@ -1056,17 +1080,5 @@ int ath_cabq_update(struct ath_softc *);
void ath_get_currentCountry(struct ath_softc *sc,
struct ath9k_country_entry *ctry);
u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
-void ath_internal_reset(struct ath_softc *sc);
-u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc);
-dma_addr_t ath_skb_map_single(struct ath_softc *sc,
- struct sk_buff *skb,
- int direction,
- dma_addr_t *pa);
-void ath_skb_unmap_single(struct ath_softc *sc,
- struct sk_buff *skb,
- int direction,
- dma_addr_t *pa);
-void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]);
-enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc);
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index a17eb130f57..98bc25c9b3c 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -85,29 +85,6 @@ static const struct hal_percal_data adc_init_dc_cal = {
ath9k_hw_adc_dccal_calibrate
};
-static const struct ath_hal ar5416hal = {
- AR5416_MAGIC,
- 0,
- 0,
- NULL,
- NULL,
- CTRY_DEFAULT,
- 0,
- 0,
- 0,
- 0,
- 0,
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- },
-};
-
static struct ath9k_rate_table ar5416_11a_table = {
8,
{0},
@@ -352,7 +329,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
ah->ah_config.ofdm_trig_high = 500;
ah->ah_config.cck_trig_high = 200;
ah->ah_config.cck_trig_low = 100;
- ah->ah_config.enable_ani = 0;
+ ah->ah_config.enable_ani = 1;
ah->ah_config.noise_immunity_level = 4;
ah->ah_config.ofdm_weaksignal_det = 1;
ah->ah_config.cck_weaksignal_thr = 0;
@@ -371,7 +348,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
ah->ah_config.intr_mitigation = 0;
}
-static inline void ath9k_hw_override_ini(struct ath_hal *ah,
+static void ath9k_hw_override_ini(struct ath_hal *ah,
struct ath9k_channel *chan)
{
if (!AR_SREV_5416_V20_OR_LATER(ah)
@@ -381,8 +358,8 @@ static inline void ath9k_hw_override_ini(struct ath_hal *ah,
REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
}
-static inline void ath9k_hw_init_bb(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static void ath9k_hw_init_bb(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
u32 synthDelay;
@@ -397,8 +374,8 @@ static inline void ath9k_hw_init_bb(struct ath_hal *ah,
udelay(synthDelay + BASE_ACTIVATE_DELAY);
}
-static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
- enum ath9k_opmode opmode)
+static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
+ enum ath9k_opmode opmode)
{
struct ath_hal_5416 *ahp = AH5416(ah);
@@ -428,7 +405,7 @@ static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
}
}
-static inline void ath9k_hw_init_qos(struct ath_hal *ah)
+static void ath9k_hw_init_qos(struct ath_hal *ah)
{
REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
@@ -523,7 +500,7 @@ static inline bool ath9k_hw_nvram_read(struct ath_hal *ah,
return ath9k_hw_eeprom_read(ah, off, data);
}
-static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
+static bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
struct ar5416_eeprom *eep = &ahp->ah_eeprom;
@@ -790,7 +767,7 @@ ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
return true;
}
-static inline int ath9k_hw_check_eeprom(struct ath_hal *ah)
+static int ath9k_hw_check_eeprom(struct ath_hal *ah)
{
u32 sum = 0, el;
u16 *eepdata;
@@ -1196,11 +1173,12 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
ah = &ahp->ah;
- memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal));
-
ah->ah_sc = sc;
ah->ah_sh = mem;
+ ah->ah_magic = AR5416_MAGIC;
+ ah->ah_countryCode = CTRY_DEFAULT;
+
ah->ah_devid = devid;
ah->ah_subvendorid = 0;
@@ -1294,7 +1272,7 @@ u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
}
}
-static inline int ath9k_hw_get_radiorev(struct ath_hal *ah)
+static int ath9k_hw_get_radiorev(struct ath_hal *ah)
{
u32 val;
int i;
@@ -1307,7 +1285,7 @@ static inline int ath9k_hw_get_radiorev(struct ath_hal *ah)
return ath9k_hw_reverse_bits(val, 8);
}
-static inline int ath9k_hw_init_macaddr(struct ath_hal *ah)
+static int ath9k_hw_init_macaddr(struct ath_hal *ah)
{
u32 sum;
int i;
@@ -1389,7 +1367,7 @@ static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah,
return spur_val;
}
-static inline int ath9k_hw_rfattach(struct ath_hal *ah)
+static int ath9k_hw_rfattach(struct ath_hal *ah)
{
bool rfStatus = false;
int ecode = 0;
@@ -1434,8 +1412,8 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah)
return 0;
}
-static inline void ath9k_hw_init_pll(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static void ath9k_hw_init_pll(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
u32 pll;
@@ -1553,7 +1531,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
}
}
-static inline void
+static void
ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
{
u32 rfMode = 0;
@@ -1623,7 +1601,7 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
return true;
}
-static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
+static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
{
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT);
@@ -1664,7 +1642,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hal *ah,
}
}
-static inline
+static
struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
struct ath9k_channel *chan)
{
@@ -2098,7 +2076,7 @@ static void ath9k_hw_ani_attach(struct ath_hal *ah)
ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
}
-static inline void ath9k_hw_ani_setup(struct ath_hal *ah)
+static void ath9k_hw_ani_setup(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
int i;
@@ -2548,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah)
}
}
+/*
+ * Process a MIB interrupt. We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
void ath9k_hw_procmibevent(struct ath_hal *ah,
const struct ath9k_node_stats *stats)
{
@@ -2555,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
u32 phyCnt1, phyCnt2;
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
-
+ /* Reset these counters regardless */
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+ /* Clear the mib counters and save them in the stats */
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
ahp->ah_stats.ast_nodestats = *stats;
if (!DO_ANI(ah))
return;
+ /* NB: these are not reset-on-read */
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
@@ -2574,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
struct ar5416AniState *aniState = ahp->ah_curani;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
ahp->ah_stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
@@ -2584,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
+ /*
+ * NB: figure out which counter triggered. If both
+ * trigger we'll only deal with one as the processing
+ * clobbers the error counter so the trigger threshold
+ * check will never be true.
+ */
if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
ath9k_hw_ani_ofdm_err_trigger(ah);
if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
ath9k_hw_ani_cck_err_trigger(ah);
-
+ /* NB: always restart to insure the h/w counters are reset */
ath9k_ani_restart(ah);
}
}
@@ -2822,32 +2814,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
}
}
-static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
- enum ath9k_gpio_output_mux_type
- halSignalType)
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+ u32 ah_signal_type)
{
- u32 ah_signal_type;
u32 gpio_shift;
- static u32 MuxSignalConversionTable[] = {
-
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
-
- AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
-
- AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
-
- AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
-
- AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
- };
-
- if ((halSignalType >= 0)
- && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable)))
- ah_signal_type = MuxSignalConversionTable[halSignalType];
- else
- return false;
-
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
gpio_shift = 2 * gpio;
@@ -2856,19 +2827,46 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
(AR_GPIO_OE_OUT_DRV << gpio_shift));
-
- return true;
}
-static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio,
- u32 val)
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
{
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
AR_GPIO_BIT(gpio));
- return true;
}
-static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
+/*
+ * Configure GPIO Input lines
+ */
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
+{
+ u32 gpio_shift;
+
+ ASSERT(gpio < ah->ah_caps.num_gpio_pins);
+
+ gpio_shift = gpio << 1;
+
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+#ifdef CONFIG_RFKILL
+static void ath9k_enable_rfkill(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+
+ REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
+ AR_GPIO_INPUT_MUX2_RFSILENT);
+
+ ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
+ REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+}
+#endif
+
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
{
if (gpio >= ah->ah_caps.num_gpio_pins)
return 0xffffffff;
@@ -2883,7 +2881,7 @@ static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
}
}
-static inline int ath9k_hw_post_attach(struct ath_hal *ah)
+static int ath9k_hw_post_attach(struct ath_hal *ah)
{
int ecode;
@@ -3081,17 +3079,17 @@ static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
+#ifdef CONFIG_RFKILL
ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
- ahp->ah_gpioSelect =
+ ah->ah_rfkill_gpio =
MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
- ahp->ah_polarity =
+ ah->ah_rfkill_polarity =
MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
- ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true,
- NULL);
pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
}
+#endif
if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
(ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
@@ -3595,7 +3593,7 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin,
return true;
}
-static inline void
+static void
ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
struct ath9k_channel *chan,
struct cal_data_per_freq *pRawDataSet,
@@ -3777,7 +3775,7 @@ ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
return;
}
-static inline bool
+static bool
ath9k_hw_set_power_cal_table(struct ath_hal *ah,
struct ar5416_eeprom *pEepData,
struct ath9k_channel *chan,
@@ -3980,7 +3978,7 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
}
}
-static inline void
+static void
ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
struct ath9k_channel *chan,
struct cal_target_power_leg *powInfo,
@@ -4046,7 +4044,7 @@ ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
}
}
-static inline void
+static void
ath9k_hw_get_target_powers(struct ath_hal *ah,
struct ath9k_channel *chan,
struct cal_target_power_ht *powInfo,
@@ -4113,7 +4111,7 @@ ath9k_hw_get_target_powers(struct ath_hal *ah,
}
}
-static inline u16
+static u16
ath9k_hw_get_max_edge_power(u16 freq,
struct cal_ctl_edges *pRdEdgesPower,
bool is2GHz)
@@ -4143,7 +4141,7 @@ ath9k_hw_get_max_edge_power(u16 freq,
return twiceMaxEdgePower;
}
-static inline bool
+static bool
ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
struct ar5416_eeprom *pEepData,
struct ath9k_channel *chan,
@@ -5122,7 +5120,7 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
-static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah)
+static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
int rx_chainmask, tx_chainmask;
@@ -5326,7 +5324,7 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
}
}
-static inline void ath9k_hw_init_user_settings(struct ath_hal *ah)
+static void ath9k_hw_init_user_settings(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
@@ -5345,7 +5343,7 @@ static inline void ath9k_hw_init_user_settings(struct ath_hal *ah)
ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
}
-static inline int
+static int
ath9k_hw_process_ini(struct ath_hal *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode)
@@ -5476,7 +5474,7 @@ ath9k_hw_process_ini(struct ath_hal *ah,
return 0;
}
-static inline void ath9k_hw_setup_calibration(struct ath_hal *ah,
+static void ath9k_hw_setup_calibration(struct ath_hal *ah,
struct hal_cal_list *currCal)
{
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
@@ -5512,8 +5510,8 @@ static inline void ath9k_hw_setup_calibration(struct ath_hal *ah,
AR_PHY_TIMING_CTRL4_DO_CAL);
}
-static inline void ath9k_hw_reset_calibration(struct ath_hal *ah,
- struct hal_cal_list *currCal)
+static void ath9k_hw_reset_calibration(struct ath_hal *ah,
+ struct hal_cal_list *currCal)
{
struct ath_hal_5416 *ahp = AH5416(ah);
int i;
@@ -5532,7 +5530,7 @@ static inline void ath9k_hw_reset_calibration(struct ath_hal *ah,
ahp->ah_CalSamples = 0;
}
-static inline void
+static void
ath9k_hw_per_calibration(struct ath_hal *ah,
struct ath9k_channel *ichan,
u8 rxchainmask,
@@ -5622,7 +5620,7 @@ static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah,
return true;
}
-static inline bool
+static bool
ath9k_hw_channel_change(struct ath_hal *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode)
@@ -5799,8 +5797,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
return retval;
}
-static inline bool ath9k_hw_init_cal(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static bool ath9k_hw_init_cal(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
struct ath_hal_5416 *ahp = AH5416(ah);
struct ath9k_channel *ichan =
@@ -5861,7 +5859,7 @@ static inline bool ath9k_hw_init_cal(struct ath_hal *ah,
}
-bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
+bool ath9k_hw_reset(struct ath_hal *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode,
u8 txchainmask, u8 rxchainmask,
@@ -5869,7 +5867,6 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
bool bChannelChange,
int *status)
{
-#define FAIL(_code) do { ecode = _code; goto bad; } while (0)
u32 saveLedState;
struct ath_hal_5416 *ahp = AH5416(ah);
struct ath9k_channel *curchan = ah->ah_curchan;
@@ -5891,11 +5888,14 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
"%s: invalid channel %u/0x%x; no mapping\n",
__func__, chan->channel, chan->channelFlags);
- FAIL(-EINVAL);
+ ecode = -EINVAL;
+ goto bad;
}
- if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
- return false;
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+ ecode = -EIO;
+ goto bad;
+ }
if (curchan)
ath9k_hw_getnf(ah, curchan);
@@ -5932,7 +5932,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
if (!ath9k_hw_chip_reset(ah, chan)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n",
__func__);
- FAIL(-EIO);
+ ecode = -EINVAL;
+ goto bad;
}
if (AR_SREV_9280(ah)) {
@@ -5945,12 +5946,14 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
else
ath9k_hw_set_gpio(ah, 9, 1);
}
- ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
}
ecode = ath9k_hw_process_ini(ah, chan, macmode);
- if (ecode != 0)
+ if (ecode != 0) {
+ ecode = -EINVAL;
goto bad;
+ }
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
ath9k_hw_set_delta_slope(ah, chan);
@@ -5963,7 +5966,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"%s: error setting board options\n", __func__);
- FAIL(-EIO);
+ ecode = -EIO;
+ goto bad;
}
ath9k_hw_decrease_chain_power(ah, chan);
@@ -5975,7 +5979,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
| (ah->ah_config.
ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
| ahp->ah_staId1Defaults);
- ath9k_hw_set_operating_mode(ah, opmode);
+ ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
@@ -5991,11 +5995,15 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
- FAIL(-EIO);
+ if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
+ ecode = -EIO;
+ goto bad;
+ }
} else {
- if (!(ath9k_hw_set_channel(ah, chan)))
- FAIL(-EIO);
+ if (!(ath9k_hw_set_channel(ah, chan))) {
+ ecode = -EIO;
+ goto bad;
+ }
}
for (i = 0; i < AR_NUM_DCU; i++)
@@ -6005,13 +6013,15 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
for (i = 0; i < ah->ah_caps.total_queues; i++)
ath9k_hw_resettxqueue(ah, i);
- ath9k_hw_init_interrupt_masks(ah, opmode);
+ ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
ath9k_hw_init_qos(ah);
+#ifdef CONFIG_RFKILL
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ ath9k_enable_rfkill(ah);
+#endif
ath9k_hw_init_user_settings(ah);
- ah->ah_opmode = opmode;
-
REG_WRITE(ah, AR_STA_ID1,
REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
@@ -6027,8 +6037,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
ath9k_hw_init_bb(ah, chan);
- if (!ath9k_hw_init_cal(ah, chan))
- FAIL(-ENODEV);
+ if (!ath9k_hw_init_cal(ah, chan)){
+ ecode = -EIO;;
+ goto bad;
+ }
rx_chainmask = ahp->ah_rxchainmask;
if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
@@ -6064,7 +6076,6 @@ bad:
if (status)
*status = ecode;
return false;
-#undef FAIL
}
bool ath9k_hw_phy_disable(struct ath_hal *ah)
@@ -6539,31 +6550,6 @@ ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
return true;
}
-#ifdef CONFIG_ATH9K_RFKILL
-static void ath9k_enable_rfkill(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
- AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-
- REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
- AR_GPIO_INPUT_MUX2_RFSILENT);
-
- ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect);
- REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-
- if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) {
-
- ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
- !ahp->ah_gpioBit);
- } else {
- ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
- ahp->ah_gpioBit);
- }
-}
-#endif
-
void
ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
u16 assocId)
@@ -7285,15 +7271,15 @@ ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
}
break;
case ATH9K_CIPHER_WEP:
- if (k->kv_len < 40 / NBBY) {
+ if (k->kv_len < LEN_WEP40) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
"%s: WEP key length %u too small\n",
__func__, k->kv_len);
return false;
}
- if (k->kv_len <= 40 / NBBY)
+ if (k->kv_len <= LEN_WEP40)
keyType = AR_KEYTABLE_TYPE_40;
- else if (k->kv_len <= 104 / NBBY)
+ else if (k->kv_len <= LEN_WEP104)
keyType = AR_KEYTABLE_TYPE_104;
else
keyType = AR_KEYTABLE_TYPE_128;
@@ -7313,7 +7299,7 @@ ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
- if (k->kv_len <= 104 / NBBY)
+ if (k->kv_len <= LEN_WEP104)
key4 &= 0xff;
if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
@@ -7678,8 +7664,7 @@ bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
REG_WRITE(ah, AR_DRETRY_LIMIT(q),
SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
| SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
- | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
- );
+ | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
REG_WRITE(ah, AR_DMISC(q),
@@ -8324,15 +8309,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid,
*error = -ENXIO;
break;
}
- if (ah != NULL) {
- ah->ah_devid = ah->ah_devid;
- ah->ah_subvendorid = ah->ah_subvendorid;
- ah->ah_macVersion = ah->ah_macVersion;
- ah->ah_macRev = ah->ah_macRev;
- ah->ah_phyRev = ah->ah_phyRev;
- ah->ah_analog5GhzRev = ah->ah_analog5GhzRev;
- ah->ah_analog2GhzRev = ah->ah_analog2GhzRev;
- }
+
return ah;
}
@@ -8439,23 +8416,48 @@ u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
}
}
-int16_t
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW -60
+
+/* AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values */
+static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
+{
+ if (nf > ATH9K_NF_TOO_LOW) {
+ DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+ "%s: noise floor value detected (%d) is "
+ "lower than what we think is a "
+ "reasonable value (%d)\n",
+ __func__, nf, ATH9K_NF_TOO_LOW);
+ return false;
+ }
+ return true;
+}
+
+s16
ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
{
struct ath9k_channel *ichan;
+ s16 nf;
ichan = ath9k_regd_check_channel(ah, chan);
if (ichan == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
"%s: invalid channel %u/0x%x; no mapping\n",
__func__, chan->channel, chan->channelFlags);
- return 0;
+ return ATH_DEFAULT_NOISE_FLOOR;
}
if (ichan->rawNoiseFloor == 0) {
enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
- return NOISE_FLOOR[mode];
+ nf = NOISE_FLOOR[mode];
} else
- return ichan->rawNoiseFloor;
+ nf = ichan->rawNoiseFloor;
+
+ if (!ath9k_hw_nf_in_range(ah, nf))
+ nf = ATH_DEFAULT_NOISE_FLOOR;
+
+ return nf;
}
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h
index ae680f21ba7..2113818ee93 100644
--- a/drivers/net/wireless/ath9k/hw.h
+++ b/drivers/net/wireless/ath9k/hw.h
@@ -314,14 +314,11 @@ struct ar5416_desc {
#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \
MS(ads->ds_rxstatus0, AR_RxRate) : \
(ads->ds_rxstatus3 >> 2) & 0xFF)
-#define RXSTATUS_DUPLICATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \
- MS(ads->ds_rxstatus3, AR_Parallel40) : \
- (ads->ds_rxstatus3 >> 10) & 0x1)
-#define set11nTries(_series, _index) \
+#define set11nTries(_series, _index) \
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
-#define set11nRate(_series, _index) \
+#define set11nRate(_series, _index) \
(SM((_series)[_index].Rate, AR_XmitRate##_index))
#define set11nPktDurRTSCTS(_series, _index) \
@@ -330,11 +327,11 @@ struct ar5416_desc {
AR_RTSCTSQual##_index : 0))
#define set11nRateFlags(_series, _index) \
- (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
- AR_2040_##_index : 0) \
- |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
- AR_GI##_index : 0) \
- |SM((_series)[_index].ChSel, AR_ChainSel##_index))
+ (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
+ AR_2040_##_index : 0) \
+ |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
+ AR_GI##_index : 0) \
+ |SM((_series)[_index].ChSel, AR_ChainSel##_index))
#define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100)
@@ -346,9 +343,6 @@ struct ar5416_desc {
#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
-#define NUM_CORNER_FIX_BITS_2133 7
-#define CCK_OFDM_GAIN_DELTA 15
-
struct ar5416AniState {
struct ath9k_channel c;
u8 noiseImmunityLevel;
@@ -377,11 +371,8 @@ struct ar5416AniState {
};
#define HAL_PROCESS_ANI 0x00000001
-#define HAL_RADAR_EN 0x80000000
-#define HAL_AR_EN 0x40000000
-
#define DO_ANI(ah) \
- ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI))
+ ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI))
struct ar5416Stats {
u32 ast_ani_niup;
@@ -425,7 +416,6 @@ struct ar5416Stats {
#define AR5416_EEP_MINOR_VER_7 0x7
#define AR5416_EEP_MINOR_VER_9 0x9
-#define AR5416_EEP_START_LOC 256
#define AR5416_NUM_5G_CAL_PIERS 8
#define AR5416_NUM_2G_CAL_PIERS 4
#define AR5416_NUM_5G_20_TARGET_POWERS 8
@@ -441,25 +431,10 @@ struct ar5416Stats {
#define AR5416_EEPROM_MODAL_SPURS 5
#define AR5416_MAX_RATE_POWER 63
#define AR5416_NUM_PDADC_VALUES 128
-#define AR5416_NUM_RATES 16
#define AR5416_BCHAN_UNUSED 0xFF
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
-#define AR5416_EEPMISC_BIG_ENDIAN 0x01
#define AR5416_MAX_CHAINS 3
-#define AR5416_ANT_16S 25
-
-#define AR5416_NUM_ANT_CHAIN_FIELDS 7
-#define AR5416_NUM_ANT_COMMON_FIELDS 4
-#define AR5416_SIZE_ANT_CHAIN_FIELD 3
-#define AR5416_SIZE_ANT_COMMON_FIELD 4
-#define AR5416_ANT_CHAIN_MASK 0x7
-#define AR5416_ANT_COMMON_MASK 0xf
-#define AR5416_CHAIN_0_IDX 0
-#define AR5416_CHAIN_1_IDX 1
-#define AR5416_CHAIN_2_IDX 2
-
#define AR5416_PWR_TABLE_OFFSET -5
-#define AR5416_LEGACY_CHAINMASK 1
enum eeprom_param {
EEP_NFTHRESH_5,
@@ -633,7 +608,7 @@ struct ar5416IniArray {
};
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
- (iniarray)->ia_array = (u32 *)(array); \
+ (iniarray)->ia_array = (u32 *)(array); \
(iniarray)->ia_rows = (rows); \
(iniarray)->ia_columns = (columns); \
} while (0)
@@ -641,16 +616,16 @@ struct ar5416IniArray {
#define INI_RA(iniarray, row, column) \
(((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
-#define INIT_CAL(_perCal) do { \
- (_perCal)->calState = CAL_WAITING; \
- (_perCal)->calNext = NULL; \
+#define INIT_CAL(_perCal) do { \
+ (_perCal)->calState = CAL_WAITING; \
+ (_perCal)->calNext = NULL; \
} while (0)
#define INSERT_CAL(_ahp, _perCal) \
do { \
if ((_ahp)->ah_cal_list_last == NULL) { \
- (_ahp)->ah_cal_list = \
- (_ahp)->ah_cal_list_last = (_perCal); \
+ (_ahp)->ah_cal_list = \
+ (_ahp)->ah_cal_list_last = (_perCal); \
((_ahp)->ah_cal_list_last)->calNext = (_perCal); \
} else { \
((_ahp)->ah_cal_list_last)->calNext = (_perCal); \
@@ -696,25 +671,29 @@ struct hal_cal_list {
struct ath_hal_5416 {
struct ath_hal ah;
struct ar5416_eeprom ah_eeprom;
+ struct ar5416Stats ah_stats;
+ struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
+ void __iomem *ah_cal_mem;
+
u8 ah_macaddr[ETH_ALEN];
u8 ah_bssid[ETH_ALEN];
u8 ah_bssidmask[ETH_ALEN];
u16 ah_assocId;
+
int16_t ah_curchanRadIndex;
u32 ah_maskReg;
- struct ar5416Stats ah_stats;
- u32 ah_txDescMask;
u32 ah_txOkInterruptMask;
u32 ah_txErrInterruptMask;
u32 ah_txDescInterruptMask;
u32 ah_txEolInterruptMask;
u32 ah_txUrnInterruptMask;
- struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
- enum ath9k_power_mode ah_powerMode;
bool ah_chipFullSleep;
u32 ah_atimWindow;
- enum ath9k_ant_setting ah_diversityControl;
u16 ah_antennaSwitchSwap;
+ enum ath9k_power_mode ah_powerMode;
+ enum ath9k_ant_setting ah_diversityControl;
+
+ /* Calibration */
enum hal_cal_types ah_suppCals;
struct hal_cal_list ah_iqCalData;
struct hal_cal_list ah_adcGainCalData;
@@ -751,16 +730,16 @@ struct ath_hal_5416 {
int32_t sign[AR5416_MAX_CHAINS];
} ah_Meas3;
u16 ah_CalSamples;
- u32 ah_tx6PowerInHalfDbm;
+
u32 ah_staId1Defaults;
u32 ah_miscMode;
- bool ah_tpcEnabled;
- u32 ah_beaconInterval;
enum {
AUTO_32KHZ,
USE_32KHZ,
DONT_USE_32KHZ,
} ah_enable32kHzClock;
+
+ /* RF */
u32 *ah_analogBank0Data;
u32 *ah_analogBank1Data;
u32 *ah_analogBank2Data;
@@ -770,8 +749,9 @@ struct ath_hal_5416 {
u32 *ah_analogBank7Data;
u32 *ah_addac5416_21;
u32 *ah_bank6Temp;
- u32 ah_ofdmTxPower;
+
int16_t ah_txPowerIndexOffset;
+ u32 ah_beaconInterval;
u32 ah_slottime;
u32 ah_acktimeout;
u32 ah_ctstimeout;
@@ -780,7 +760,8 @@ struct ath_hal_5416 {
u32 ah_gpioSelect;
u32 ah_polarity;
u32 ah_gpioBit;
- bool ah_eepEnabled;
+
+ /* ANI */
u32 ah_procPhyErr;
bool ah_hasHwPhyCounters;
u32 ah_aniPeriod;
@@ -790,18 +771,14 @@ struct ath_hal_5416 {
int ah_coarseHigh[5];
int ah_coarseLow[5];
int ah_firpwr[5];
- u16 ah_ratesArray[16];
+ enum ath9k_ani_cmd ah_ani_function;
+
u32 ah_intrTxqs;
bool ah_intrMitigation;
- u32 ah_cycleCount;
- u32 ah_ctlBusy;
- u32 ah_extBusy;
enum ath9k_ht_extprotspacing ah_extprotspacing;
u8 ah_txchainmask;
u8 ah_rxchainmask;
- int ah_hwp;
- void __iomem *ah_cal_mem;
- enum ath9k_ani_cmd ah_ani_function;
+
struct ar5416IniArray ah_iniModes;
struct ar5416IniArray ah_iniCommon;
struct ar5416IniArray ah_iniBank0;
@@ -820,10 +797,6 @@ struct ath_hal_5416 {
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
-#define IS_5416_EMU(ah) \
- ((ah->ah_devid == AR5416_DEVID_EMU) || \
- (ah->ah_devid == AR5416_DEVID_EMU_PCIE))
-
#define ar5416RfDetach(ah) do { \
if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \
AH5416(ah)->ah_rfHal.rfDetach(ah); \
@@ -841,8 +814,8 @@ struct ath_hal_5416 {
#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \
int r; \
for (r = 0; r < ((iniarray)->ia_rows); r++) { \
- REG_WRITE(ah, INI_RA((iniarray), (r), 0), \
- INI_RA((iniarray), r, (column))); \
+ REG_WRITE(ah, INI_RA((iniarray), (r), 0), \
+ INI_RA((iniarray), r, (column))); \
DO_DELAY(regWr); \
} \
} while (0)
@@ -852,30 +825,21 @@ struct ath_hal_5416 {
#define COEF_SCALE_S 24
#define HT40_CHANNEL_CENTER_SHIFT 10
-#define ar5416CheckOpMode(_opmode) \
- ((_opmode == ATH9K_M_STA) || (_opmode == ATH9K_M_IBSS) || \
- (_opmode == ATH9K_M_HOSTAP) || (_opmode == ATH9K_M_MONITOR))
-
#define AR5416_EEPROM_MAGIC_OFFSET 0x0
#define AR5416_EEPROM_S 2
#define AR5416_EEPROM_OFFSET 0x2000
-#define AR5416_EEPROM_START_ADDR \
+#define AR5416_EEPROM_START_ADDR \
(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
#define AR5416_EEPROM_MAX 0xae0
-#define ar5416_get_eep_ver(_ahp) \
+#define ar5416_get_eep_ver(_ahp) \
(((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF)
-#define ar5416_get_eep_rev(_ahp) \
+#define ar5416_get_eep_rev(_ahp) \
(((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF)
-#define ar5416_get_ntxchains(_txchainmask) \
+#define ar5416_get_ntxchains(_txchainmask) \
(((_txchainmask >> 2) & 1) + \
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
-#define IS_EEP_MINOR_V3(_ahp) \
- (ath9k_hw_get_eeprom((_ahp), EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_3)
-
-#define FIXED_CCA_THRESHOLD 15
-
#ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5
#else
@@ -910,8 +874,6 @@ struct ath_hal_5416 {
#define AR_GPIOD_MASK 0x00001FFF
#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
-#define MAX_ANALOG_START 319
-
#define HAL_EP_RND(x, mul) \
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
#define BEACON_RSSI(ahp) \
@@ -923,8 +885,6 @@ struct ath_hal_5416 {
#define AH_TIMEOUT 100000
#define AH_TIME_QUANTUM 10
-#define IS(_c, _f) (((_c)->channelFlags & _f) || 0)
-
#define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 200000
@@ -964,6 +924,6 @@ struct ath_hal_5416 {
#define OFDM_SYMBOL_TIME_QUARTER 16
u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
- enum eeprom_param param);
+ enum eeprom_param param);
#endif
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 2888778040e..f05f584ab7b 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -22,8 +22,6 @@
#define ATH_PCI_VERSION "0.1"
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
-#define IEEE80211_ACTION_CAT_HT 7
-#define IEEE80211_ACTION_HT_TXCHWIDTH 0
static char *dev_info = "ath9k";
@@ -142,7 +140,7 @@ static int ath_key_config(struct ath_softc *sc,
struct ath9k_keyval hk;
const u8 *mac = NULL;
int ret = 0;
- enum ieee80211_if_types opmode;
+ enum nl80211_iftype opmode;
memset(&hk, 0, sizeof(hk));
@@ -181,14 +179,14 @@ static int ath_key_config(struct ath_softc *sc,
*/
if (is_broadcast_ether_addr(addr)) {
switch (opmode) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
/* default key: could be group WPA key
* or could be static WEP key */
mac = NULL;
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
break;
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
break;
default:
ASSERT(0);
@@ -206,36 +204,30 @@ static int ath_key_config(struct ath_softc *sc,
if (!ret)
return -EIO;
- sc->sc_keytype = hk.kv_type;
return 0;
}
static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
{
-#define ATH_MAX_NUM_KEYS 4
int freeslot;
- freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0;
+ freeslot = (key->keyidx >= 4) ? 1 : 0;
ath_key_reset(sc, key->keyidx, freeslot);
-#undef ATH_MAX_NUM_KEYS
}
static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
{
-/* Until mac80211 includes these fields */
-
-#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
-#define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
-#define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
+#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
+#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
ht_info->ht_supported = 1;
ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
- |(u16)IEEE80211_HT_CAP_MIMO_PS
+ |(u16)IEEE80211_HT_CAP_SM_PS
|(u16)IEEE80211_HT_CAP_SGI_40
|(u16)IEEE80211_HT_CAP_DSSSCCK40;
- ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536;
- ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8;
+ ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
+ ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
/* setup supported mcs set */
memset(ht_info->supp_mcs_set, 0, 16);
ht_info->supp_mcs_set[0] = 0xff;
@@ -282,10 +274,12 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
rx_status->mactime = status->tsf;
rx_status->band = curchan->band;
rx_status->freq = curchan->center_freq;
- rx_status->noise = ATH_DEFAULT_NOISE_FLOOR;
+ rx_status->noise = sc->sc_ani.sc_noise_floor;
rx_status->signal = rx_status->noise + status->rssi;
rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
rx_status->antenna = status->antenna;
+
+ /* XXX Fix me, 64 cannot be the max rssi value, rigure it out */
rx_status->qual = status->rssi * 100 / 64;
if (status->flags & ATH_RX_MIC_ERROR)
@@ -331,6 +325,698 @@ static u8 parse_mpdudensity(u8 mpdudensity)
}
}
+static void ath9k_ht_conf(struct ath_softc *sc,
+ struct ieee80211_bss_conf *bss_conf)
+{
+#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
+ struct ath_ht_info *ht_info = &sc->sc_ht_info;
+
+ if (bss_conf->assoc_ht) {
+ ht_info->ext_chan_offset =
+ bss_conf->ht_bss_conf->bss_cap &
+ IEEE80211_HT_IE_CHA_SEC_OFFSET;
+
+ if (!(bss_conf->ht_conf->cap &
+ IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
+ (bss_conf->ht_bss_conf->bss_cap &
+ IEEE80211_HT_IE_CHA_WIDTH))
+ ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
+ else
+ ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
+
+ ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
+ ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+ bss_conf->ht_conf->ampdu_factor);
+ ht_info->mpdudensity =
+ parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
+
+ }
+
+#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
+}
+
+static void ath9k_bss_assoc_info(struct ath_softc *sc,
+ struct ieee80211_bss_conf *bss_conf)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ath_vap *avp;
+ int pos;
+ DECLARE_MAC_BUF(mac);
+
+ if (bss_conf->assoc) {
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
+ __func__,
+ bss_conf->aid);
+
+ avp = sc->sc_vaps[0];
+ if (avp == NULL) {
+ DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
+ __func__);
+ return;
+ }
+
+ /* New association, store aid */
+ if (avp->av_opmode == ATH9K_M_STA) {
+ sc->sc_curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
+ sc->sc_curaid);
+ }
+
+ /* Configure the beacon */
+ ath_beacon_config(sc, 0);
+ sc->sc_flags |= SC_OP_BEACONS;
+
+ /* Reset rssi stats */
+ sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
+
+ /* Update chainmask */
+ ath_update_chainmask(sc, bss_conf->assoc_ht);
+
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "%s: bssid %s aid 0x%x\n",
+ __func__,
+ print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
+ __func__,
+ curchan->center_freq);
+
+ pos = ath_get_channel(sc, curchan);
+ if (pos == -1) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: Invalid channel\n", __func__);
+ return;
+ }
+
+ if (hw->conf.ht_conf.ht_supported)
+ sc->sc_ah->ah_channels[pos].chanmode =
+ ath_get_extchanmode(sc, curchan);
+ else
+ sc->sc_ah->ah_channels[pos].chanmode =
+ (curchan->band == IEEE80211_BAND_2GHZ) ?
+ CHANNEL_G : CHANNEL_A;
+
+ /* set h/w channel */
+ if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: Unable to set channel\n",
+ __func__);
+
+ ath_rate_newstate(sc, avp);
+ /* Update ratectrl about the new state */
+ ath_rc_node_update(hw, avp->rc_node);
+
+ /* Start ANI */
+ mod_timer(&sc->sc_ani.timer,
+ jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+
+ } else {
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "%s: Bss Info DISSOC\n", __func__);
+ sc->sc_curaid = 0;
+ }
+}
+
+void ath_get_beaconconfig(struct ath_softc *sc,
+ int if_id,
+ struct ath_beacon_config *conf)
+{
+ struct ieee80211_hw *hw = sc->hw;
+
+ /* fill in beacon config data */
+
+ conf->beacon_interval = hw->conf.beacon_int;
+ conf->listen_interval = 100;
+ conf->dtim_count = 1;
+ conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
+}
+
+void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ struct ath_xmit_status *tx_status, struct ath_node *an)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+ DPRINTF(sc, ATH_DBG_XMIT,
+ "%s: TX complete: skb: %p\n", __func__, skb);
+
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
+ tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
+ /* free driver's private data area of tx_info */
+ if (tx_info->driver_data[0] != NULL)
+ kfree(tx_info->driver_data[0]);
+ tx_info->driver_data[0] = NULL;
+ }
+
+ if (tx_status->flags & ATH_TX_BAR) {
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+ tx_status->flags &= ~ATH_TX_BAR;
+ }
+
+ if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
+ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+ /* Frame was not ACKed, but an ACK was expected */
+ tx_info->status.excessive_retries = 1;
+ }
+ } else {
+ /* Frame was ACKed */
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ }
+
+ tx_info->status.retry_count = tx_status->retries;
+
+ ieee80211_tx_status(hw, skb);
+ if (an)
+ ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
+}
+
+int _ath_rx_indicate(struct ath_softc *sc,
+ struct sk_buff *skb,
+ struct ath_recv_status *status,
+ u16 keyix)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_node *an = NULL;
+ struct ieee80211_rx_status rx_status;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ int padsize;
+ enum ATH_RX_TYPE st;
+
+ /* see if any padding is done by the hw and remove it */
+ if (hdrlen & 3) {
+ padsize = hdrlen % 4;
+ memmove(skb->data + padsize, skb->data, hdrlen);
+ skb_pull(skb, padsize);
+ }
+
+ /* Prepare rx status */
+ ath9k_rx_prepare(sc, skb, status, &rx_status);
+
+ if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
+ !(status->flags & ATH_RX_DECRYPT_ERROR)) {
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+ } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
+ && !(status->flags & ATH_RX_DECRYPT_ERROR)
+ && skb->len >= hdrlen + 4) {
+ keyix = skb->data[hdrlen + 3] >> 6;
+
+ if (test_bit(keyix, sc->sc_keymap))
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+ }
+
+ spin_lock_bh(&sc->node_lock);
+ an = ath_node_find(sc, hdr->addr2);
+ spin_unlock_bh(&sc->node_lock);
+
+ if (an) {
+ ath_rx_input(sc, an,
+ hw->conf.ht_conf.ht_supported,
+ skb, status, &st);
+ }
+ if (!an || (st != ATH_RX_CONSUMED))
+ __ieee80211_rx(hw, skb, &rx_status);
+
+ return 0;
+}
+
+int ath_rx_subframe(struct ath_node *an,
+ struct sk_buff *skb,
+ struct ath_recv_status *status)
+{
+ struct ath_softc *sc = an->an_sc;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_rx_status rx_status;
+
+ /* Prepare rx status */
+ ath9k_rx_prepare(sc, skb, status, &rx_status);
+ if (!(status->flags & ATH_RX_DECRYPT_ERROR))
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+
+ __ieee80211_rx(hw, skb, &rx_status);
+
+ return 0;
+}
+
+/********************************/
+/* LED functions */
+/********************************/
+
+static void ath_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+ struct ath_softc *sc = led->sc;
+
+ switch (brightness) {
+ case LED_OFF:
+ if (led->led_type == ATH_LED_ASSOC ||
+ led->led_type == ATH_LED_RADIO)
+ sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
+ (led->led_type == ATH_LED_RADIO) ? 1 :
+ !!(sc->sc_flags & SC_OP_LED_ASSOCIATED));
+ break;
+ case LED_FULL:
+ if (led->led_type == ATH_LED_ASSOC)
+ sc->sc_flags |= SC_OP_LED_ASSOCIATED;
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
+ char *trigger)
+{
+ int ret;
+
+ led->sc = sc;
+ led->led_cdev.name = led->name;
+ led->led_cdev.default_trigger = trigger;
+ led->led_cdev.brightness_set = ath_led_brightness;
+
+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
+ if (ret)
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Failed to register led:%s", led->name);
+ else
+ led->registered = 1;
+ return ret;
+}
+
+static void ath_unregister_led(struct ath_led *led)
+{
+ if (led->registered) {
+ led_classdev_unregister(&led->led_cdev);
+ led->registered = 0;
+ }
+}
+
+static void ath_deinit_leds(struct ath_softc *sc)
+{
+ ath_unregister_led(&sc->assoc_led);
+ sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+ ath_unregister_led(&sc->tx_led);
+ ath_unregister_led(&sc->rx_led);
+ ath_unregister_led(&sc->radio_led);
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+}
+
+static void ath_init_leds(struct ath_softc *sc)
+{
+ char *trigger;
+ int ret;
+
+ /* Configure gpio 1 for output */
+ ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ /* LED off, active low */
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+ trigger = ieee80211_get_radio_led_name(sc->hw);
+ snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
+ "ath9k-%s:radio", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->radio_led, trigger);
+ sc->radio_led.led_type = ATH_LED_RADIO;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_assoc_led_name(sc->hw);
+ snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
+ "ath9k-%s:assoc", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->assoc_led, trigger);
+ sc->assoc_led.led_type = ATH_LED_ASSOC;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_tx_led_name(sc->hw);
+ snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
+ "ath9k-%s:tx", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->tx_led, trigger);
+ sc->tx_led.led_type = ATH_LED_TX;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_rx_led_name(sc->hw);
+ snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
+ "ath9k-%s:rx", wiphy_name(sc->hw->wiphy));
+ ret = ath_register_led(sc, &sc->rx_led, trigger);
+ sc->rx_led.led_type = ATH_LED_RX;
+ if (ret)
+ goto fail;
+
+ return;
+
+fail:
+ ath_deinit_leds(sc);
+}
+
+#ifdef CONFIG_RFKILL
+/*******************/
+/* Rfkill */
+/*******************/
+
+static void ath_radio_enable(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int status;
+
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(ah, ah->ah_curchan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask,
+ sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing,
+ false, &status)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n", __func__,
+ ath9k_hw_mhz2ieee(ah,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags),
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags, status);
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ ath_update_txpow(sc);
+ if (ath_startrecv(sc) != 0) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: unable to restart recv logic\n", __func__);
+ return;
+ }
+
+ if (sc->sc_flags & SC_OP_BEACONS)
+ ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
+
+ /* Re-Enable interrupts */
+ ath9k_hw_set_interrupts(ah, sc->sc_imask);
+
+ /* Enable LED */
+ ath9k_hw_cfg_output(ah, ATH_LED_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
+
+ ieee80211_wake_queues(sc->hw);
+}
+
+static void ath_radio_disable(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int status;
+
+
+ ieee80211_stop_queues(sc->hw);
+
+ /* Disable LED */
+ ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
+ ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
+
+ /* Disable interrupts */
+ ath9k_hw_set_interrupts(ah, 0);
+
+ ath_draintxq(sc, false); /* clear pending tx frames */
+ ath_stoprecv(sc); /* turn off frame recv */
+ ath_flushrecv(sc); /* flush recv queue */
+
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(ah, ah->ah_curchan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask,
+ sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing,
+ false, &status)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n", __func__,
+ ath9k_hw_mhz2ieee(ah,
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags),
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags, status);
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ ath9k_hw_phy_disable(ah);
+ ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+}
+
+static bool ath_is_rfkill_set(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+
+ return ath9k_hw_gpio_get(ah, ah->ah_rfkill_gpio) ==
+ ah->ah_rfkill_polarity;
+}
+
+/* h/w rfkill poll function */
+static void ath_rfkill_poll(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ rf_kill.rfkill_poll.work);
+ bool radio_on;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return;
+
+ radio_on = !ath_is_rfkill_set(sc);
+
+ /*
+ * enable/disable radio only when there is a
+ * state change in RF switch
+ */
+ if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
+ enum rfkill_state state;
+
+ if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
+ state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
+ : RFKILL_STATE_HARD_BLOCKED;
+ } else if (radio_on) {
+ ath_radio_enable(sc);
+ state = RFKILL_STATE_UNBLOCKED;
+ } else {
+ ath_radio_disable(sc);
+ state = RFKILL_STATE_HARD_BLOCKED;
+ }
+
+ if (state == RFKILL_STATE_HARD_BLOCKED)
+ sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
+ else
+ sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
+
+ rfkill_force_state(sc->rf_kill.rfkill, state);
+ }
+
+ queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
+ msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
+}
+
+/* s/w rfkill handler */
+static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
+{
+ struct ath_softc *sc = data;
+
+ switch (state) {
+ case RFKILL_STATE_SOFT_BLOCKED:
+ if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
+ SC_OP_RFKILL_SW_BLOCKED)))
+ ath_radio_disable(sc);
+ sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
+ return 0;
+ case RFKILL_STATE_UNBLOCKED:
+ if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
+ sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
+ if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
+ DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
+ "radio as it is disabled by h/w \n");
+ return -EPERM;
+ }
+ ath_radio_enable(sc);
+ }
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Init s/w rfkill */
+static int ath_init_sw_rfkill(struct ath_softc *sc)
+{
+ sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
+ RFKILL_TYPE_WLAN);
+ if (!sc->rf_kill.rfkill) {
+ DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
+ return -ENOMEM;
+ }
+
+ snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
+ "ath9k-%s:rfkill", wiphy_name(sc->hw->wiphy));
+ sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
+ sc->rf_kill.rfkill->data = sc;
+ sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
+ sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
+ sc->rf_kill.rfkill->user_claim_unsupported = 1;
+
+ return 0;
+}
+
+/* Deinitialize rfkill */
+static void ath_deinit_rfkill(struct ath_softc *sc)
+{
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
+
+ if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
+ rfkill_unregister(sc->rf_kill.rfkill);
+ sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
+ sc->rf_kill.rfkill = NULL;
+ }
+}
+#endif /* CONFIG_RFKILL */
+
+static int ath_detach(struct ath_softc *sc)
+{
+ struct ieee80211_hw *hw = sc->hw;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
+
+ /* Deinit LED control */
+ ath_deinit_leds(sc);
+
+#ifdef CONFIG_RFKILL
+ /* deinit rfkill */
+ ath_deinit_rfkill(sc);
+#endif
+
+ /* Unregister hw */
+
+ ieee80211_unregister_hw(hw);
+
+ /* unregister Rate control */
+ ath_rate_control_unregister();
+
+ /* tx/rx cleanup */
+
+ ath_rx_cleanup(sc);
+ ath_tx_cleanup(sc);
+
+ /* Deinit */
+
+ ath_deinit(sc);
+
+ return 0;
+}
+
+static int ath_attach(u16 devid,
+ struct ath_softc *sc)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ int error = 0;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
+
+ error = ath_init(devid, sc);
+ if (error != 0)
+ return error;
+
+ /* Init nodes */
+
+ INIT_LIST_HEAD(&sc->node_list);
+ spin_lock_init(&sc->node_lock);
+
+ /* get mac address from hardware and set in mac80211 */
+
+ SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
+
+ /* setup channels and rates */
+
+ sc->sbands[IEEE80211_BAND_2GHZ].channels =
+ sc->channels[IEEE80211_BAND_2GHZ];
+ sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
+ sc->rates[IEEE80211_BAND_2GHZ];
+ sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
+ /* Setup HT capabilities for 2.4Ghz*/
+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
+
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &sc->sbands[IEEE80211_BAND_2GHZ];
+
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
+ sc->sbands[IEEE80211_BAND_5GHZ].channels =
+ sc->channels[IEEE80211_BAND_5GHZ];
+ sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+ sc->rates[IEEE80211_BAND_5GHZ];
+ sc->sbands[IEEE80211_BAND_5GHZ].band =
+ IEEE80211_BAND_5GHZ;
+
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
+ /* Setup HT capabilities for 5Ghz*/
+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
+
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &sc->sbands[IEEE80211_BAND_5GHZ];
+ }
+
+ /* FIXME: Have to figure out proper hw init values later */
+
+ hw->queues = 4;
+ hw->ampdu_queues = 1;
+
+ /* Register rate control */
+ hw->rate_control_algorithm = "ath9k_rate_control";
+ error = ath_rate_control_register();
+ if (error != 0) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: Unable to register rate control "
+ "algorithm:%d\n", __func__, error);
+ ath_rate_control_unregister();
+ goto bad;
+ }
+
+ error = ieee80211_register_hw(hw);
+ if (error != 0) {
+ ath_rate_control_unregister();
+ goto bad;
+ }
+
+ /* Initialize LED control */
+ ath_init_leds(sc);
+
+#ifdef CONFIG_RFKILL
+ /* Initialze h/w Rfkill */
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
+
+ /* Initialize s/w rfkill */
+ if (ath_init_sw_rfkill(sc))
+ goto detach;
+#endif
+
+ /* initialize tx/rx engine */
+
+ error = ath_tx_init(sc, ATH_TXBUF);
+ if (error != 0)
+ goto detach;
+
+ error = ath_rx_init(sc, ATH_RXBUF);
+ if (error != 0)
+ goto detach;
+
+ return 0;
+detach:
+ ath_detach(sc);
+bad:
+ return error;
+}
+
static int ath9k_start(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
@@ -359,6 +1045,33 @@ static int ath9k_start(struct ieee80211_hw *hw)
return error;
}
+#ifdef CONFIG_RFKILL
+ /* Start rfkill polling */
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ queue_delayed_work(sc->hw->workqueue,
+ &sc->rf_kill.rfkill_poll, 0);
+
+ if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
+ if (rfkill_register(sc->rf_kill.rfkill)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to register rfkill\n");
+ rfkill_free(sc->rf_kill.rfkill);
+
+ /* Deinitialize the device */
+ if (sc->pdev->irq)
+ free_irq(sc->pdev->irq, sc);
+ ath_detach(sc);
+ pci_iounmap(sc->pdev, sc->mem);
+ pci_release_region(sc->pdev, 0);
+ pci_disable_device(sc->pdev);
+ ieee80211_free_hw(hw);
+ return -EIO;
+ } else {
+ sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
+ }
+ }
+#endif
+
ieee80211_wake_queues(hw);
return 0;
}
@@ -368,6 +1081,20 @@ static int ath9k_tx(struct ieee80211_hw *hw,
{
struct ath_softc *sc = hw->priv;
int hdrlen, padsize;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ /*
+ * As a temporary workaround, assign seq# here; this will likely need
+ * to be cleaned up to work better with Beacon transmission and virtual
+ * BSSes.
+ */
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ sc->seq_no += 0x10;
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+ }
/* Add the padding after the header if this is not already done */
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
@@ -406,6 +1133,11 @@ static void ath9k_stop(struct ieee80211_hw *hw)
"%s: Device is no longer present\n", __func__);
ieee80211_stop_queues(hw);
+
+#ifdef CONFIG_RFKILL
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
+#endif
}
static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -420,16 +1152,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
return -ENOBUFS;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
ic_opmode = ATH9K_M_STA;
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
ic_opmode = ATH9K_M_IBSS;
break;
+ case NL80211_IFTYPE_AP:
+ ic_opmode = ATH9K_M_HOSTAP;
+ break;
default:
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Only STA and IBSS are supported currently\n",
- __func__);
+ "%s: Interface type %d not yet supported\n",
+ __func__, conf->type);
return -EOPNOTSUPP;
}
@@ -445,6 +1180,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
return error;
}
+ if (conf->type == NL80211_IFTYPE_AP) {
+ /* TODO: is this a suitable place to start ANI for AP mode? */
+ /* Start ANI */
+ mod_timer(&sc->sc_ani.timer,
+ jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+ }
+
return 0;
}
@@ -467,12 +1209,15 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
#ifdef CONFIG_SLOW_ANT_DIV
ath_slow_ant_div_stop(&sc->sc_antdiv);
#endif
+ /* Stop ANI */
+ del_timer_sync(&sc->sc_ani.timer);
/* Update ratectrl */
ath_rate_newstate(sc, avp);
/* Reclaim beacon resources */
- if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
+ sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
ath_beacon_return(sc, avp);
}
@@ -480,7 +1225,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
/* Set interrupt mask */
sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
- sc->sc_beacons = 0;
+ sc->sc_flags &= ~SC_OP_BEACONS;
error = ath_vap_detach(sc, 0);
if (error)
@@ -529,6 +1274,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
struct ieee80211_if_conf *conf)
{
struct ath_softc *sc = hw->priv;
+ struct ath_hal *ah = sc->sc_ah;
struct ath_vap *avp;
u32 rfilt = 0;
int error, i;
@@ -541,18 +1287,25 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
return -EINVAL;
}
+ /* TODO: Need to decide which hw opmode to use for multi-interface
+ * cases */
+ if (vif->type == NL80211_IFTYPE_AP &&
+ ah->ah_opmode != ATH9K_M_HOSTAP) {
+ ah->ah_opmode = ATH9K_M_HOSTAP;
+ ath9k_hw_setopmode(ah);
+ ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
+ /* Request full reset to get hw opmode changed properly */
+ sc->sc_flags |= SC_OP_FULL_RESET;
+ }
+
if ((conf->changed & IEEE80211_IFCC_BSSID) &&
!is_zero_ether_addr(conf->bssid)) {
switch (vif->type) {
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
/* Update ratectrl about the new state */
ath_rate_newstate(sc, avp);
- /* Set rx filter */
- rfilt = ath_calcrxfilter(sc);
- ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
-
/* Set BSSID */
memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
sc->sc_curaid = 0;
@@ -585,7 +1338,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
/* need to reconfigure the beacon */
- sc->sc_beacons = 0;
+ sc->sc_flags &= ~SC_OP_BEACONS ;
break;
default:
@@ -594,7 +1347,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
}
if ((conf->changed & IEEE80211_IFCC_BEACON) &&
- (vif->type == IEEE80211_IF_TYPE_IBSS)) {
+ ((vif->type == NL80211_IFTYPE_ADHOC) ||
+ (vif->type == NL80211_IFTYPE_AP))) {
/*
* Allocate and setup the beacon frame.
*
@@ -613,7 +1367,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
}
/* Check for WLAN_CAPABILITY_PRIVACY ? */
- if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) {
+ if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
for (i = 0; i < IEEE80211_WEP_NKID; i++)
if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
ath9k_hw_keysetmac(sc->sc_ah,
@@ -622,7 +1376,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
}
/* Only legacy IBSS for now */
- if (vif->type == IEEE80211_IF_TYPE_IBSS)
+ if (vif->type == NL80211_IFTYPE_ADHOC)
ath_update_chainmask(sc, 0);
return 0;
@@ -636,8 +1390,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
FIF_BCN_PRBRESP_PROMISC | \
FIF_FCSFAIL)
-/* Accept unicast, bcast and mcast frames */
-
+/* FIXME: sc->sc_full_reset ? */
static void ath9k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
@@ -645,22 +1398,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
struct dev_mc_list *mclist)
{
struct ath_softc *sc = hw->priv;
+ u32 rfilt;
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
+ sc->rx_filter = *total_flags;
+ rfilt = ath_calcrxfilter(sc);
+ ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
+
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
- ath_scan_start(sc);
- else
- ath_scan_end(sc);
+ ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
}
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n",
+ __func__, sc->rx_filter);
}
static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
- const u8 *addr)
+ struct ieee80211_sta *sta)
{
struct ath_softc *sc = hw->priv;
struct ath_node *an;
@@ -668,19 +1427,18 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&sc->node_lock, flags);
- an = ath_node_find(sc, (u8 *) addr);
+ an = ath_node_find(sc, sta->addr);
spin_unlock_irqrestore(&sc->node_lock, flags);
switch (cmd) {
case STA_NOTIFY_ADD:
spin_lock_irqsave(&sc->node_lock, flags);
if (!an) {
- ath_node_attach(sc, (u8 *)addr, 0);
+ ath_node_attach(sc, sta->addr, 0);
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
- __func__,
- print_mac(mac, addr));
+ __func__, print_mac(mac, sta->addr));
} else {
- ath_node_get(sc, (u8 *)addr);
+ ath_node_get(sc, sta->addr);
}
spin_unlock_irqrestore(&sc->node_lock, flags);
break;
@@ -693,7 +1451,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
__func__,
- print_mac(mac, addr));
+ print_mac(mac, sta->addr));
}
break;
default:
@@ -756,13 +1514,13 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
key->hw_key_idx = key->keyidx;
/* push IV and Michael MIC generation to stack */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ if (key->alg == ALG_TKIP)
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
}
break;
case DISABLE_KEY:
ath_key_delete(sc, key);
clear_bit(key->keyidx, sc->sc_keymap);
- sc->sc_keytype = ATH9K_CIPHER_CLR;
break;
default:
ret = -EINVAL;
@@ -771,117 +1529,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
return ret;
}
-static void ath9k_ht_conf(struct ath_softc *sc,
- struct ieee80211_bss_conf *bss_conf)
-{
-#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
- struct ath_ht_info *ht_info = &sc->sc_ht_info;
-
- if (bss_conf->assoc_ht) {
- ht_info->ext_chan_offset =
- bss_conf->ht_bss_conf->bss_cap &
- IEEE80211_HT_IE_CHA_SEC_OFFSET;
-
- if (!(bss_conf->ht_conf->cap &
- IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
- (bss_conf->ht_bss_conf->bss_cap &
- IEEE80211_HT_IE_CHA_WIDTH))
- ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
- else
- ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
-
- ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
- ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
- bss_conf->ht_conf->ampdu_factor);
- ht_info->mpdudensity =
- parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
-
- }
-
-#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
-}
-
-static void ath9k_bss_assoc_info(struct ath_softc *sc,
- struct ieee80211_bss_conf *bss_conf)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_channel *curchan = hw->conf.channel;
- struct ath_vap *avp;
- int pos;
- DECLARE_MAC_BUF(mac);
-
- if (bss_conf->assoc) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
- __func__,
- bss_conf->aid);
-
- avp = sc->sc_vaps[0];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
- __func__);
- return;
- }
-
- /* New association, store aid */
- if (avp->av_opmode == ATH9K_M_STA) {
- sc->sc_curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
- sc->sc_curaid);
- }
-
- /* Configure the beacon */
- ath_beacon_config(sc, 0);
- sc->sc_beacons = 1;
-
- /* Reset rssi stats */
- sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
-
- /* Update chainmask */
- ath_update_chainmask(sc, bss_conf->assoc_ht);
-
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: bssid %s aid 0x%x\n",
- __func__,
- print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
- __func__,
- curchan->center_freq);
-
- pos = ath_get_channel(sc, curchan);
- if (pos == -1) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Invalid channel\n", __func__);
- return;
- }
-
- if (hw->conf.ht_conf.ht_supported)
- sc->sc_ah->ah_channels[pos].chanmode =
- ath_get_extchanmode(sc, curchan);
- else
- sc->sc_ah->ah_channels[pos].chanmode =
- (curchan->band == IEEE80211_BAND_2GHZ) ?
- CHANNEL_G : CHANNEL_A;
-
- /* set h/w channel */
- if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to set channel\n",
- __func__);
-
- ath_rate_newstate(sc, avp);
- /* Update ratectrl about the new state */
- ath_rc_node_update(hw, avp->rc_node);
- } else {
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Bss Info DISSOC\n", __func__);
- sc->sc_curaid = 0;
- }
-}
-
static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -894,9 +1541,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
__func__,
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
- sc->sc_flags |= ATH_PREAMBLE_SHORT;
+ sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
else
- sc->sc_flags &= ~ATH_PREAMBLE_SHORT;
+ sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
@@ -905,9 +1552,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->use_cts_prot);
if (bss_conf->use_cts_prot &&
hw->conf.channel->band != IEEE80211_BAND_5GHZ)
- sc->sc_flags |= ATH_PROTECT_ENABLE;
+ sc->sc_flags |= SC_OP_PROTECT_ENABLE;
else
- sc->sc_flags &= ~ATH_PROTECT_ENABLE;
+ sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
}
if (changed & BSS_CHANGED_HT) {
@@ -946,45 +1593,44 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw)
static int ath9k_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
- const u8 *addr,
- u16 tid,
- u16 *ssn)
+ struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
{
struct ath_softc *sc = hw->priv;
int ret = 0;
switch (action) {
case IEEE80211_AMPDU_RX_START:
- ret = ath_rx_aggr_start(sc, addr, tid, ssn);
+ ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to start RX aggregation\n",
__func__);
break;
case IEEE80211_AMPDU_RX_STOP:
- ret = ath_rx_aggr_stop(sc, addr, tid);
+ ret = ath_rx_aggr_stop(sc, sta->addr, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to stop RX aggregation\n",
__func__);
break;
case IEEE80211_AMPDU_TX_START:
- ret = ath_tx_aggr_start(sc, addr, tid, ssn);
+ ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to start TX aggregation\n",
__func__);
else
- ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
+ ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- ret = ath_tx_aggr_stop(sc, addr, tid);
+ ret = ath_tx_aggr_stop(sc, sta->addr, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Unable to stop TX aggregation\n",
__func__);
- ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
+ ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
default:
DPRINTF(sc, ATH_DBG_FATAL,
@@ -994,6 +1640,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
return ret;
}
+static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value)
+{
+ return -EOPNOTSUPP;
+}
+
static struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -1018,255 +1669,10 @@ static struct ieee80211_ops ath9k_ops = {
.get_tsf = ath9k_get_tsf,
.reset_tsf = ath9k_reset_tsf,
.tx_last_beacon = NULL,
- .ampdu_action = ath9k_ampdu_action
+ .ampdu_action = ath9k_ampdu_action,
+ .set_frag_threshold = ath9k_no_fragmentation,
};
-void ath_get_beaconconfig(struct ath_softc *sc,
- int if_id,
- struct ath_beacon_config *conf)
-{
- struct ieee80211_hw *hw = sc->hw;
-
- /* fill in beacon config data */
-
- conf->beacon_interval = hw->conf.beacon_int;
- conf->listen_interval = 100;
- conf->dtim_count = 1;
- conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
-}
-
-int ath_update_beacon(struct ath_softc *sc,
- int if_id,
- struct ath_beacon_offset *bo,
- struct sk_buff *skb,
- int mcast)
-{
- return 0;
-}
-
-void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_xmit_status *tx_status, struct ath_node *an)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
- DPRINTF(sc, ATH_DBG_XMIT,
- "%s: TX complete: skb: %p\n", __func__, skb);
-
- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
- tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
- /* free driver's private data area of tx_info */
- if (tx_info->driver_data[0] != NULL)
- kfree(tx_info->driver_data[0]);
- tx_info->driver_data[0] = NULL;
- }
-
- if (tx_status->flags & ATH_TX_BAR) {
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
- tx_status->flags &= ~ATH_TX_BAR;
- }
- if (tx_status->flags)
- tx_info->status.excessive_retries = 1;
-
- tx_info->status.retry_count = tx_status->retries;
-
- ieee80211_tx_status(hw, skb);
- if (an)
- ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
-}
-
-int ath__rx_indicate(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- u16 keyix)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ath_node *an = NULL;
- struct ieee80211_rx_status rx_status;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- int padsize;
- enum ATH_RX_TYPE st;
-
- /* see if any padding is done by the hw and remove it */
- if (hdrlen & 3) {
- padsize = hdrlen % 4;
- memmove(skb->data + padsize, skb->data, hdrlen);
- skb_pull(skb, padsize);
- }
-
- /* remove FCS before passing up to protocol stack */
- skb_trim(skb, (skb->len - FCS_LEN));
-
- /* Prepare rx status */
- ath9k_rx_prepare(sc, skb, status, &rx_status);
-
- if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
- !(status->flags & ATH_RX_DECRYPT_ERROR)) {
- rx_status.flag |= RX_FLAG_DECRYPTED;
- } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
- && !(status->flags & ATH_RX_DECRYPT_ERROR)
- && skb->len >= hdrlen + 4) {
- keyix = skb->data[hdrlen + 3] >> 6;
-
- if (test_bit(keyix, sc->sc_keymap))
- rx_status.flag |= RX_FLAG_DECRYPTED;
- }
-
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, hdr->addr2);
- spin_unlock_bh(&sc->node_lock);
-
- if (an) {
- ath_rx_input(sc, an,
- hw->conf.ht_conf.ht_supported,
- skb, status, &st);
- }
- if (!an || (st != ATH_RX_CONSUMED))
- __ieee80211_rx(hw, skb, &rx_status);
-
- return 0;
-}
-
-int ath_rx_subframe(struct ath_node *an,
- struct sk_buff *skb,
- struct ath_recv_status *status)
-{
- struct ath_softc *sc = an->an_sc;
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_rx_status rx_status;
-
- /* Prepare rx status */
- ath9k_rx_prepare(sc, skb, status, &rx_status);
- if (!(status->flags & ATH_RX_DECRYPT_ERROR))
- rx_status.flag |= RX_FLAG_DECRYPTED;
-
- __ieee80211_rx(hw, skb, &rx_status);
-
- return 0;
-}
-
-enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
-{
- return sc->sc_ht_info.tx_chan_width;
-}
-
-static int ath_detach(struct ath_softc *sc)
-{
- struct ieee80211_hw *hw = sc->hw;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
-
- /* Unregister hw */
-
- ieee80211_unregister_hw(hw);
-
- /* unregister Rate control */
- ath_rate_control_unregister();
-
- /* tx/rx cleanup */
-
- ath_rx_cleanup(sc);
- ath_tx_cleanup(sc);
-
- /* Deinit */
-
- ath_deinit(sc);
-
- return 0;
-}
-
-static int ath_attach(u16 devid,
- struct ath_softc *sc)
-{
- struct ieee80211_hw *hw = sc->hw;
- int error = 0;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
-
- error = ath_init(devid, sc);
- if (error != 0)
- return error;
-
- /* Init nodes */
-
- INIT_LIST_HEAD(&sc->node_list);
- spin_lock_init(&sc->node_lock);
-
- /* get mac address from hardware and set in mac80211 */
-
- SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
-
- /* setup channels and rates */
-
- sc->sbands[IEEE80211_BAND_2GHZ].channels =
- sc->channels[IEEE80211_BAND_2GHZ];
- sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
- sc->rates[IEEE80211_BAND_2GHZ];
- sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
-
- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
- /* Setup HT capabilities for 2.4Ghz*/
- setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
-
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
- &sc->sbands[IEEE80211_BAND_2GHZ];
-
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_5GHZ].channels =
- sc->channels[IEEE80211_BAND_5GHZ];
- sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
- sc->rates[IEEE80211_BAND_5GHZ];
- sc->sbands[IEEE80211_BAND_5GHZ].band =
- IEEE80211_BAND_5GHZ;
-
- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
- /* Setup HT capabilities for 5Ghz*/
- setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
-
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &sc->sbands[IEEE80211_BAND_5GHZ];
- }
-
- /* FIXME: Have to figure out proper hw init values later */
-
- hw->queues = 4;
- hw->ampdu_queues = 1;
-
- /* Register rate control */
- hw->rate_control_algorithm = "ath9k_rate_control";
- error = ath_rate_control_register();
- if (error != 0) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to register rate control "
- "algorithm:%d\n", __func__, error);
- ath_rate_control_unregister();
- goto bad;
- }
-
- error = ieee80211_register_hw(hw);
- if (error != 0) {
- ath_rate_control_unregister();
- goto bad;
- }
-
- /* initialize tx/rx engine */
-
- error = ath_tx_init(sc, ATH_TXBUF);
- if (error != 0)
- goto bad1;
-
- error = ath_rx_init(sc, ATH_RXBUF);
- if (error != 0)
- goto bad1;
-
- return 0;
-bad1:
- ath_detach(sc);
-bad:
- return error;
-}
-
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
void __iomem *mem;
@@ -1340,9 +1746,16 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto bad2;
}
- hw->flags = IEEE80211_HW_SIGNAL_DBM |
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
@@ -1390,10 +1803,17 @@ static void ath_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
+ enum ath9k_int status;
- if (pdev->irq)
+ if (pdev->irq) {
+ ath9k_hw_set_interrupts(sc->sc_ah, 0);
+ /* clear the ISR */
+ ath9k_hw_getisr(sc->sc_ah, &status);
+ sc->sc_flags |= SC_OP_INVALID;
free_irq(pdev->irq, sc);
+ }
ath_detach(sc);
+
pci_iounmap(pdev, sc->mem);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
@@ -1404,6 +1824,16 @@ static void ath_pci_remove(struct pci_dev *pdev)
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath_softc *sc = hw->priv;
+
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+#ifdef CONFIG_RFKILL
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
+#endif
+
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, 3);
@@ -1413,6 +1843,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int ath_pci_resume(struct pci_dev *pdev)
{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath_softc *sc = hw->priv;
u32 val;
int err;
@@ -1429,6 +1861,21 @@ static int ath_pci_resume(struct pci_dev *pdev)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ /* Enable LED */
+ ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+#ifdef CONFIG_RFKILL
+ /*
+ * check the h/w rfkill state on resume
+ * and start the rfkill poll timer
+ */
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ queue_delayed_work(sc->hw->workqueue,
+ &sc->rf_kill.rfkill_poll, 0);
+#endif
+
return 0;
}
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h
index 0cd399a5344..14702344448 100644
--- a/drivers/net/wireless/ath9k/phy.h
+++ b/drivers/net/wireless/ath9k/phy.h
@@ -18,19 +18,19 @@
#define PHY_H
bool ath9k_hw_ar9280_set_channel(struct ath_hal *ah,
- struct ath9k_channel
- *chan);
+ struct ath9k_channel
+ *chan);
bool ath9k_hw_set_channel(struct ath_hal *ah,
- struct ath9k_channel *chan);
+ struct ath9k_channel *chan);
void ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex,
u32 freqIndex, int regWrites);
bool ath9k_hw_set_rf_regs(struct ath_hal *ah,
- struct ath9k_channel *chan,
- u16 modesIndex);
+ struct ath9k_channel *chan,
+ u16 modesIndex);
void ath9k_hw_decrease_chain_power(struct ath_hal *ah,
struct ath9k_channel *chan);
bool ath9k_hw_init_rf(struct ath_hal *ah,
- int *status);
+ int *status);
#define AR_PHY_BASE 0x9800
#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index 73c460ad355..cca2fc5b076 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -20,6 +20,7 @@
*/
#include "core.h"
+/* FIXME: remove this include! */
#include "../net/mac80211/rate.h"
static u32 tx_triglevel_max;
@@ -653,8 +654,8 @@ ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv,
rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv);
for (i = 0; i < rate_table->rate_cnt; i++) {
valid = (ath_rc_priv->single_stream ?
- rate_table->info[i].valid_single_stream :
- rate_table->info[i].valid);
+ rate_table->info[i].valid_single_stream :
+ rate_table->info[i].valid);
if (valid == TRUE) {
u32 phy = rate_table->info[i].phy;
u8 valid_rate_count = 0;
@@ -740,14 +741,14 @@ ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv,
for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy;
u32 valid = (ath_rc_priv->single_stream ?
- rate_table->info[j].valid_single_stream :
- rate_table->info[j].valid);
+ rate_table->info[j].valid_single_stream :
+ rate_table->info[j].valid);
if (((((struct ath_rateset *)
- mcs_set)->rs_rates[i] & 0x7F) !=
- (rate_table->info[j].dot11rate & 0x7F)) ||
- !WLAN_RC_PHY_HT(phy) ||
- !WLAN_RC_PHY_HT_VALID(valid, capflag))
+ mcs_set)->rs_rates[i] & 0x7F) !=
+ (rate_table->info[j].dot11rate & 0x7F)) ||
+ !WLAN_RC_PHY_HT(phy) ||
+ !WLAN_RC_PHY_HT_VALID(valid, capflag))
continue;
if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
@@ -847,9 +848,9 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp)
/* For half and quarter rate channles use different
* rate tables
*/
- if (sc->sc_curchan.channelFlags & CHANNEL_HALF)
+ if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF)
ar5416_sethalf_ratetable(asc);
- else if (sc->sc_curchan.channelFlags & CHANNEL_QUARTER)
+ else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER)
ar5416_setquarter_ratetable(asc);
else /* full rate */
ar5416_setfull_ratetable(asc);
@@ -866,10 +867,10 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp)
}
static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- int probe_allowed, int *is_probing,
- int is_retry)
+ struct ath_rate_node *ath_rc_priv,
+ const struct ath_rate_table *rate_table,
+ int probe_allowed, int *is_probing,
+ int is_retry)
{
u32 dt, best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
@@ -997,8 +998,8 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
rate = rate_ctrl->rate_table_size - 1;
ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
- (rate_table->info[rate].valid_single_stream &&
- ath_rc_priv->single_stream));
+ (rate_table->info[rate].valid_single_stream &&
+ ath_rc_priv->single_stream));
return rate;
}
@@ -1023,10 +1024,10 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table ,
}
static u8 ath_rc_rate_getidx(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- u8 rix, u16 stepdown,
- u16 min_rate)
+ struct ath_rate_node *ath_rc_priv,
+ const struct ath_rate_table *rate_table,
+ u8 rix, u16 stepdown,
+ u16 min_rate)
{
u32 j;
u8 nextindex;
@@ -1066,8 +1067,8 @@ static void ath_rc_ratefind(struct ath_softc *sc,
rate_table =
(struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode];
rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table,
- (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
- is_probe, is_retry);
+ (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
+ is_probe, is_retry);
nrix = rix;
if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) {
@@ -1099,13 +1100,13 @@ static void ath_rc_ratefind(struct ath_softc *sc,
try_num = ((i + 1) == num_rates) ?
num_tries - (try_per_rate * i) : try_per_rate ;
min_rate = (((i + 1) == num_rates) &&
- (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
+ (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
- rate_table, nrix, 1, min_rate);
+ rate_table, nrix, 1, min_rate);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table,
- &series[i], try_num, nrix, TRUE);
+ &series[i], try_num, nrix, TRUE);
}
/*
@@ -1124,13 +1125,13 @@ static void ath_rc_ratefind(struct ath_softc *sc,
* above conditions.
*/
if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
- (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
- (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
+ (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
+ (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
if (i == 4 &&
((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
- (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
+ (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
series[3].rix = series[2].rix;
series[3].flags = series[2].flags;
series[3].max_4ms_framelen = series[2].max_4ms_framelen;
@@ -1141,18 +1142,19 @@ static void ath_rc_ratefind(struct ath_softc *sc,
/*
* Return the Tx rate series.
*/
-void ath_rate_findrate(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- int num_tries,
- int num_rates,
- unsigned int rcflag,
- struct ath_rc_series series[],
- int *is_probe,
- int is_retry)
+static void ath_rate_findrate(struct ath_softc *sc,
+ struct ath_rate_node *ath_rc_priv,
+ int num_tries,
+ int num_rates,
+ unsigned int rcflag,
+ struct ath_rc_series series[],
+ int *is_probe,
+ int is_retry)
{
struct ath_vap *avp = ath_rc_priv->avp;
- DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
+ DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+
if (!num_rates || !num_tries)
return;
@@ -1174,9 +1176,8 @@ void ath_rate_findrate(struct ath_softc *sc,
unsigned int mcs;
u8 series_rix = 0;
- series[idx].tries =
- IEEE80211_RATE_IDX_ENTRY(
- avp->av_config.av_fixed_retryset, idx);
+ series[idx].tries = IEEE80211_RATE_IDX_ENTRY(
+ avp->av_config.av_fixed_retryset, idx);
mcs = IEEE80211_RATE_IDX_ENTRY(
avp->av_config.av_fixed_rateset, idx);
@@ -1228,7 +1229,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
u32 now_msec = jiffies_to_msecs(jiffies);
int state_change = FALSE, rate, count;
u8 last_per;
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
+ struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
struct ath_rate_table *rate_table =
(struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode];
@@ -1272,14 +1273,14 @@ static void ath_rc_update_ht(struct ath_softc *sc,
} else {
/* xretries == 2 */
count = sizeof(nretry_to_per_lookup) /
- sizeof(nretry_to_per_lookup[0]);
+ sizeof(nretry_to_per_lookup[0]);
if (retries >= count)
retries = count - 1;
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
rate_ctrl->state[tx_rate].per =
(u8)(rate_ctrl->state[tx_rate].per -
- (rate_ctrl->state[tx_rate].per >> 3) +
- ((100) >> 3));
+ (rate_ctrl->state[tx_rate].per >> 3) +
+ ((100) >> 3));
}
/* xretries == 1 or 2 */
@@ -1295,8 +1296,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
if (retries >= count)
retries = count - 1;
if (info_priv->n_bad_frames) {
- /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
- /*
+ /* new_PER = 7/8*old_PER + 1/8*(currentPER)
* Assuming that n_frames is not 0. The current PER
* from the retries is 100 * retries / (retries+1),
* since the first retries attempts failed, and the
@@ -1386,7 +1386,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* rssi_ack values.
*/
if (tx_rate == rate_ctrl->rate_max_phy &&
- rate_ctrl->hw_maxretry_pktcnt < 255) {
+ rate_ctrl->hw_maxretry_pktcnt < 255) {
rate_ctrl->hw_maxretry_pktcnt++;
}
@@ -1418,7 +1418,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
/* Now reduce the current
* rssi threshold. */
if ((rssi_ackAvg < rssi_thres + 2) &&
- (rssi_thres > rssi_ack_vmin)) {
+ (rssi_thres > rssi_ack_vmin)) {
rate_ctrl->state[tx_rate].
rssi_thres--;
}
@@ -1436,10 +1436,10 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* a while (except if we are probing).
*/
if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 &&
- rate_table->info[tx_rate].ratekbps <=
- rate_table->info[rate_ctrl->rate_max_phy].ratekbps) {
+ rate_table->info[tx_rate].ratekbps <=
+ rate_table->info[rate_ctrl->rate_max_phy].ratekbps) {
ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl,
- (u8) tx_rate, &rate_ctrl->rate_max_phy);
+ (u8) tx_rate, &rate_ctrl->rate_max_phy);
/* Don't probe for a little while. */
rate_ctrl->probe_time = now_msec;
@@ -1460,43 +1460,43 @@ static void ath_rc_update_ht(struct ath_softc *sc,
break;
if (rate_ctrl->state[rate].rssi_thres +
- rate_table->info[rate].rssi_ack_deltamin >
- rate_ctrl->state[rate+1].rssi_thres) {
+ rate_table->info[rate].rssi_ack_deltamin >
+ rate_ctrl->state[rate+1].rssi_thres) {
rate_ctrl->state[rate+1].rssi_thres =
rate_ctrl->state[rate].
- rssi_thres +
+ rssi_thres +
rate_table->info[rate].
- rssi_ack_deltamin;
+ rssi_ack_deltamin;
}
}
/* Make sure the rates below this have lower rssi thresholds. */
for (rate = tx_rate - 1; rate >= 0; rate--) {
if (rate_table->info[rate].phy !=
- rate_table->info[tx_rate].phy)
+ rate_table->info[tx_rate].phy)
break;
if (rate_ctrl->state[rate].rssi_thres +
- rate_table->info[rate].rssi_ack_deltamin >
- rate_ctrl->state[rate+1].rssi_thres) {
+ rate_table->info[rate].rssi_ack_deltamin >
+ rate_ctrl->state[rate+1].rssi_thres) {
if (rate_ctrl->state[rate+1].rssi_thres <
- rate_table->info[rate].
- rssi_ack_deltamin)
+ rate_table->info[rate].
+ rssi_ack_deltamin)
rate_ctrl->state[rate].rssi_thres = 0;
else {
rate_ctrl->state[rate].rssi_thres =
rate_ctrl->state[rate+1].
- rssi_thres -
- rate_table->info[rate].
- rssi_ack_deltamin;
+ rssi_thres -
+ rate_table->info[rate].
+ rssi_ack_deltamin;
}
if (rate_ctrl->state[rate].rssi_thres <
- rate_table->info[rate].
- rssi_ack_validmin) {
+ rate_table->info[rate].
+ rssi_ack_validmin) {
rate_ctrl->state[rate].rssi_thres =
rate_table->info[rate].
- rssi_ack_validmin;
+ rssi_ack_validmin;
}
}
}
@@ -1507,11 +1507,11 @@ static void ath_rc_update_ht(struct ath_softc *sc,
if (rate_ctrl->state[tx_rate].per < last_per) {
for (rate = tx_rate - 1; rate >= 0; rate--) {
if (rate_table->info[rate].phy !=
- rate_table->info[tx_rate].phy)
+ rate_table->info[tx_rate].phy)
break;
if (rate_ctrl->state[rate].per >
- rate_ctrl->state[rate+1].per) {
+ rate_ctrl->state[rate+1].per) {
rate_ctrl->state[rate].per =
rate_ctrl->state[rate+1].per;
}
@@ -1528,11 +1528,11 @@ static void ath_rc_update_ht(struct ath_softc *sc,
/* Every so often, we reduce the thresholds and
* PER (different for CCK and OFDM). */
if (now_msec - rate_ctrl->rssi_down_time >=
- rate_table->rssi_reduce_interval) {
+ rate_table->rssi_reduce_interval) {
for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) {
if (rate_ctrl->state[rate].rssi_thres >
- rate_table->info[rate].rssi_ack_validmin)
+ rate_table->info[rate].rssi_ack_validmin)
rate_ctrl->state[rate].rssi_thres -= 1;
}
rate_ctrl->rssi_down_time = now_msec;
@@ -1541,7 +1541,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
/* Every so often, we reduce the thresholds
* and PER (different for CCK and OFDM). */
if (now_msec - rate_ctrl->per_down_time >=
- rate_table->rssi_reduce_interval) {
+ rate_table->rssi_reduce_interval) {
for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) {
rate_ctrl->state[rate].per =
7 * rate_ctrl->state[rate].per / 8;
@@ -1560,7 +1560,7 @@ static void ath_rc_update(struct ath_softc *sc,
struct ath_tx_info_priv *info_priv, int final_ts_idx,
int xretries, int long_retry)
{
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
+ struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
struct ath_rate_table *rate_table;
struct ath_tx_ratectrl *rate_ctrl;
struct ath_rc_series rcs[4];
@@ -1637,7 +1637,6 @@ static void ath_rc_update(struct ath_softc *sc,
xretries, long_retry);
}
-
/*
* Process a tx descriptor for a completed transmit (success or failure).
*/
@@ -1651,13 +1650,13 @@ static void ath_rate_tx_complete(struct ath_softc *sc,
struct ath_vap *avp;
avp = rc_priv->avp;
- if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE)
- || info_priv->tx.ts_status & ATH9K_TXERR_FILT)
+ if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) ||
+ (info_priv->tx.ts_status & ATH9K_TXERR_FILT))
return;
if (info_priv->tx.ts_rssi > 0) {
ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
- info_priv->tx.ts_rssi);
+ info_priv->tx.ts_rssi);
}
/*
@@ -1682,7 +1681,6 @@ static void ath_rate_tx_complete(struct ath_softc *sc,
info_priv->tx.ts_longretry);
}
-
/*
* Update the SIB's rate control information
*
@@ -1701,8 +1699,8 @@ static void ath_rc_sib_update(struct ath_softc *sc,
struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
struct ath_rateset *rateset = negotiated_rates;
u8 *ht_mcs = (u8 *)negotiated_htrates;
- struct ath_tx_ratectrl *rate_ctrl = (struct ath_tx_ratectrl *)
- (ath_rc_priv);
+ struct ath_tx_ratectrl *rate_ctrl =
+ (struct ath_tx_ratectrl *)ath_rc_priv;
u8 i, j, k, hi = 0, hthi = 0;
rate_table = (struct ath_rate_table *)
@@ -1815,19 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv)
}
-static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta)
+static void ath_setup_rates(struct ath_softc *sc,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
+ struct ath_rate_node *rc_priv)
{
- struct ieee80211_supported_band *sband;
- struct ieee80211_hw *hw = local_to_hw(local);
- struct ath_softc *sc = hw->priv;
- struct ath_rate_node *rc_priv = sta->rate_ctrl_priv;
int i, j = 0;
- DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+
for (i = 0; i < sband->n_bitrates; i++) {
- if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) {
+ if (sta->supp_rates[sband->band] & BIT(i)) {
rc_priv->neg_rates.rs_rates[j]
= (sband->bitrates[i].bitrate * 2) / 10;
j++;
@@ -1854,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
}
/* Rate Control callbacks */
-static void ath_tx_status(void *priv, struct net_device *dev,
+static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
struct ath_softc *sc = priv;
struct ath_tx_info_priv *tx_info_priv;
struct ath_node *an;
- struct sta_info *sta;
- struct ieee80211_local *local;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
__le16 fc;
- local = hw_to_local(sc->hw);
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
@@ -1875,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev,
an = ath_node_find(sc, hdr->addr1);
spin_unlock_bh(&sc->node_lock);
- sta = sta_info_get(local, hdr->addr1);
- if (!an || !sta || !ieee80211_is_data(fc)) {
+ if (!an || !priv_sta || !ieee80211_is_data(fc)) {
if (tx_info->driver_data[0] != NULL) {
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
@@ -1884,37 +1878,40 @@ static void ath_tx_status(void *priv, struct net_device *dev,
return;
}
if (tx_info->driver_data[0] != NULL) {
- ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv);
+ ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
}
}
static void ath_tx_aggr_resp(struct ath_softc *sc,
- struct sta_info *sta,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
struct ath_node *an,
u8 tidno)
{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_local *local;
struct ath_atx_tid *txtid;
- struct ieee80211_supported_band *sband;
u16 buffersize = 0;
int state;
- DECLARE_MAC_BUF(mac);
+ struct sta_info *si;
- if (!sc->sc_txaggr)
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
return;
txtid = ATH_AN_2_TID(an, tidno);
if (!txtid->paused)
return;
- local = hw_to_local(sc->hw);
- sband = hw->wiphy->bands[hw->conf.channel->band];
+ /*
+ * XXX: This is entirely busted, we aren't supposed to
+ * access the sta from here because it's internal
+ * to mac80211, and looking at the state without
+ * locking is wrong too.
+ */
+ si = container_of(sta, struct sta_info, sta);
buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */
- state = sta->ampdu_mlme.tid_state_tx[tidno];
+ state = si->ampdu_mlme.tid_state_tx[tidno];
if (state & HT_ADDBA_RECEIVED_MSK) {
txtid->addba_exchangecomplete = 1;
@@ -1930,21 +1927,18 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
}
}
-static void ath_get_rate(void *priv, struct net_device *dev,
- struct ieee80211_supported_band *sband,
- struct sk_buff *skb,
- struct rate_selection *sel)
+static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
+ struct sk_buff *skb, struct rate_selection *sel)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- struct ath_softc *sc = (struct ath_softc *)priv;
+ struct ath_softc *sc = priv;
struct ieee80211_hw *hw = sc->hw;
struct ath_tx_info_priv *tx_info_priv;
- struct ath_rate_node *ath_rc_priv;
+ struct ath_rate_node *ath_rc_priv = priv_sta;
struct ath_node *an;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- int is_probe, chk, ret;
+ int is_probe = FALSE, chk, ret;
s8 lowest_idx;
__le16 fc = hdr->frame_control;
u8 *qc, tid;
@@ -1957,18 +1951,15 @@ static void ath_get_rate(void *priv, struct net_device *dev,
ASSERT(tx_info->driver_data[0] != NULL);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- sta = sta_info_get(local, hdr->addr1);
- lowest_idx = rate_lowest_index(local, sband, sta);
+ lowest_idx = rate_lowest_index(sband, sta);
tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
/* lowest rate for management and multicast/broadcast frames */
if (!ieee80211_is_data(fc) ||
- is_multicast_ether_addr(hdr->addr1) || !sta) {
+ is_multicast_ether_addr(hdr->addr1) || !sta) {
sel->rate_idx = lowest_idx;
return;
}
- ath_rc_priv = sta->rate_ctrl_priv;
-
/* Find tx rate for unicast frames */
ath_rate_findrate(sc, ath_rc_priv,
ATH_11N_TXMAXTRY, 4,
@@ -1977,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
&is_probe,
false);
if (is_probe)
- sel->probe_idx = ((struct ath_tx_ratectrl *)
- sta->rate_ctrl_priv)->probe_rate;
+ sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
/* Ratecontrol sometimes returns invalid rate index */
if (tx_info_priv->rcs[0].rix != 0xff)
@@ -2022,38 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev,
__func__,
print_mac(mac, hdr->addr1));
} else if (chk == AGGR_EXCHANGE_PROGRESS)
- ath_tx_aggr_resp(sc, sta, an, tid);
+ ath_tx_aggr_resp(sc, sband, sta, an, tid);
}
}
}
-static void ath_rate_init(void *priv, void *priv_sta,
- struct ieee80211_local *local,
- struct sta_info *sta)
+static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta)
{
- struct ieee80211_supported_band *sband;
- struct ieee80211_hw *hw = local_to_hw(local);
- struct ieee80211_conf *conf = &local->hw.conf;
- struct ath_softc *sc = hw->priv;
+ struct ath_softc *sc = priv;
+ struct ath_rate_node *ath_rc_priv = priv_sta;
int i, j = 0;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- sta->txrate_idx = rate_lowest_index(local, sband, sta);
-
- ath_setup_rates(local, sta);
- if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
+ ath_setup_rates(sc, sband, sta, ath_rc_priv);
+ if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
for (i = 0; i < MCS_SET_SIZE; i++) {
- if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
- ((struct ath_rate_node *)
- priv_sta)->neg_ht_rates.rs_rates[j++] = i;
+ if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
+ ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX)
break;
}
- ((struct ath_rate_node *)priv_sta)->neg_ht_rates.rs_nrates = j;
+ ath_rc_priv->neg_ht_rates.rs_nrates = j;
}
- ath_rc_node_update(hw, priv_sta);
+ ath_rc_node_update(sc->hw, priv_sta);
}
static void ath_rate_clear(void *priv)
@@ -2061,13 +2044,12 @@ static void ath_rate_clear(void *priv)
return;
}
-static void *ath_rate_alloc(struct ieee80211_local *local)
+static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
- struct ieee80211_hw *hw = local_to_hw(local);
struct ath_softc *sc = hw->priv;
- DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
- return local->hw.priv;
+ DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+ return hw->priv;
}
static void ath_rate_free(void *priv)
@@ -2075,24 +2057,28 @@ static void ath_rate_free(void *priv)
return;
}
-static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
+static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct ath_softc *sc = priv;
struct ath_vap *avp = sc->sc_vaps[0];
struct ath_rate_node *rate_priv;
- DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
+ DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+
rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
if (!rate_priv) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s:Unable to allocate"
- "private rate control structure", __func__);
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "%s: Unable to allocate private rc structure\n",
+ __func__);
return NULL;
}
ath_rc_sib_init(rate_priv);
+
return rate_priv;
}
-static void ath_rate_free_sta(void *priv, void *priv_sta)
+static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
+ void *priv_sta)
{
struct ath_rate_node *rate_priv = priv_sta;
struct ath_softc *sc = priv;
@@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = {
.alloc = ath_rate_alloc,
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
- .free_sta = ath_rate_free_sta
+ .free_sta = ath_rate_free_sta,
};
int ath_rate_control_register(void)
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h
index 71aef9c7523..b95b41508b9 100644
--- a/drivers/net/wireless/ath9k/rc.h
+++ b/drivers/net/wireless/ath9k/rc.h
@@ -71,9 +71,6 @@ enum ieee80211_fixed_rate_mode {
*/
#define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8)))
-#define SHORT_PRE 1
-#define LONG_PRE 0
-
#define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS
#define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS
#define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI
@@ -102,18 +99,18 @@ enum {
WLAN_RC_PHY_MAX
};
-#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
- || (_phy == WLAN_RC_PHY_HT_40_DS) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
- || (_phy == WLAN_RC_PHY_HT_40_DS) \
- || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
+ || (_phy == WLAN_RC_PHY_HT_40_DS) \
+ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
+ || (_phy == WLAN_RC_PHY_HT_40_DS) \
+ || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
@@ -135,56 +132,59 @@ enum {
#define WLAN_RC_SGI_FLAG (0x04)
#define WLAN_RC_HT_FLAG (0x08)
-/* Index into the rate table */
-#define INIT_RATE_MAX_20 23
-#define INIT_RATE_MAX_40 40
-
#define RATE_TABLE_SIZE 64
-/* XXX: Convert to kdoc */
+/**
+ * struct ath_rate_table - Rate Control table
+ * @valid: valid for use in rate control
+ * @valid_single_stream: valid for use in rate control for
+ * single stream operation
+ * @phy: CCK/OFDM
+ * @ratekbps: rate in Kbits per second
+ * @user_ratekbps: user rate in Kbits per second
+ * @ratecode: rate that goes into HW descriptors
+ * @short_preamble: Mask for enabling short preamble in ratecode for CCK
+ * @dot11rate: value that goes into supported
+ * rates info element of MLME
+ * @ctrl_rate: Index of next lower basic rate, used for duration computation
+ * @max_4ms_framelen: maximum frame length(bytes) for tx duration
+ * @probe_interval: interval for rate control to probe for other rates
+ * @rssi_reduce_interval: interval for rate control to reduce rssi
+ * @initial_ratemax: initial ratemax value used in ath_rc_sib_update()
+ */
struct ath_rate_table {
int rate_cnt;
struct {
- int valid; /* Valid for use in rate control */
- int valid_single_stream;/* Valid for use in rate control
- for single stream operation */
- u8 phy; /* CCK/OFDM/TURBO/XR */
- u32 ratekbps; /* Rate in Kbits per second */
- u32 user_ratekbps; /* User rate in KBits per second */
- u8 ratecode; /* rate that goes into
- hw descriptors */
- u8 short_preamble; /* Mask for enabling short preamble
- in rate code for CCK */
- u8 dot11rate; /* Value that goes into supported
- rates info element of MLME */
- u8 ctrl_rate; /* Index of next lower basic rate,
- used for duration computation */
- int8_t rssi_ack_validmin; /* Rate control related */
- int8_t rssi_ack_deltamin; /* Rate control related */
- u8 base_index; /* base rate index */
- u8 cw40index; /* 40cap rate index */
- u8 sgi_index; /* shortgi rate index */
- u8 ht_index; /* shortgi rate index */
- u32 max_4ms_framelen; /* Maximum frame length(bytes)
- for 4ms tx duration */
+ int valid;
+ int valid_single_stream;
+ u8 phy;
+ u32 ratekbps;
+ u32 user_ratekbps;
+ u8 ratecode;
+ u8 short_preamble;
+ u8 dot11rate;
+ u8 ctrl_rate;
+ int8_t rssi_ack_validmin;
+ int8_t rssi_ack_deltamin;
+ u8 base_index;
+ u8 cw40index;
+ u8 sgi_index;
+ u8 ht_index;
+ u32 max_4ms_framelen;
} info[RATE_TABLE_SIZE];
- u32 probe_interval; /* interval for ratectrl to
- probe for other rates */
- u32 rssi_reduce_interval; /* interval for ratectrl
- to reduce RSSI */
- u8 initial_ratemax; /* the initial ratemax value used
- in ath_rc_sib_update() */
+ u32 probe_interval;
+ u32 rssi_reduce_interval;
+ u8 initial_ratemax;
};
#define ATH_RC_PROBE_ALLOWED 0x00000001
#define ATH_RC_MINRATE_LASTRATE 0x00000002
-#define ATH_RC_SHORT_PREAMBLE 0x00000004
struct ath_rc_series {
- u8 rix;
- u8 tries;
- u8 flags;
- u32 max_4ms_framelen;
+ u8 rix;
+ u8 tries;
+ u8 flags;
+ u32 max_4ms_framelen;
};
/* rcs_flags definition */
@@ -201,42 +201,56 @@ struct ath_rc_series {
#define MAX_TX_RATE_PHY 48
struct ath_tx_ratectrl_state {
- int8_t rssi_thres; /* required rssi for this rate (dB) */
- u8 per; /* recent estimate of packet error rate (%) */
+ int8_t rssi_thres; /* required rssi for this rate (dB) */
+ u8 per; /* recent estimate of packet error rate (%) */
};
+/**
+ * struct ath_tx_ratectrl - TX Rate control Information
+ * @state: RC state
+ * @rssi_last: last ACK rssi
+ * @rssi_last_lookup: last ACK rssi used for lookup
+ * @rssi_last_prev: previous last ACK rssi
+ * @rssi_last_prev2: 2nd previous last ACK rssi
+ * @rssi_sum_cnt: count of rssi_sum for averaging
+ * @rssi_sum_rate: rate that we are averaging
+ * @rssi_sum: running sum of rssi for averaging
+ * @probe_rate: rate we are probing at
+ * @rssi_time: msec timestamp for last ack rssi
+ * @rssi_down_time: msec timestamp for last down step
+ * @probe_time: msec timestamp for last probe
+ * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
+ * @max_valid_rate: maximum number of valid rate
+ * @per_down_time: msec timestamp for last PER down step
+ * @valid_phy_ratecnt: valid rate count
+ * @rate_max_phy: phy index for the max rate
+ * @probe_interval: interval for ratectrl to probe for other rates
+ */
struct ath_tx_ratectrl {
- struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; /* state */
- int8_t rssi_last; /* last ack rssi */
- int8_t rssi_last_lookup; /* last ack rssi used for lookup */
- int8_t rssi_last_prev; /* previous last ack rssi */
- int8_t rssi_last_prev2; /* 2nd previous last ack rssi */
- int32_t rssi_sum_cnt; /* count of rssi_sum for averaging */
- int32_t rssi_sum_rate; /* rate that we are averaging */
- int32_t rssi_sum; /* running sum of rssi for averaging */
- u32 valid_txrate_mask; /* mask of valid rates */
- u8 rate_table_size; /* rate table size */
- u8 rate_max; /* max rate that has recently worked */
- u8 probe_rate; /* rate we are probing at */
- u32 rssi_time; /* msec timestamp for last ack rssi */
- u32 rssi_down_time; /* msec timestamp for last down step */
- u32 probe_time; /* msec timestamp for last probe */
- u8 hw_maxretry_pktcnt; /* num packets since we got
- HW max retry error */
- u8 max_valid_rate; /* maximum number of valid rate */
- u8 valid_rate_index[MAX_TX_RATE_TBL]; /* valid rate index */
- u32 per_down_time; /* msec timstamp for last
- PER down step */
+ struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL];
+ int8_t rssi_last;
+ int8_t rssi_last_lookup;
+ int8_t rssi_last_prev;
+ int8_t rssi_last_prev2;
+ int32_t rssi_sum_cnt;
+ int32_t rssi_sum_rate;
+ int32_t rssi_sum;
+ u8 rate_table_size;
+ u8 probe_rate;
+ u32 rssi_time;
+ u32 rssi_down_time;
+ u32 probe_time;
+ u8 hw_maxretry_pktcnt;
+ u8 max_valid_rate;
+ u8 valid_rate_index[MAX_TX_RATE_TBL];
+ u32 per_down_time;
/* 11n state */
- u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; /* valid rate count */
- u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL];
- u8 rc_phy_mode;
- u8 rate_max_phy; /* Phy index for the max rate */
- u32 rate_max_lastused; /* msec timstamp of when we
- last used rateMaxPhy */
- u32 probe_interval; /* interval for ratectrl to probe
- for other rates */
+ u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
+ u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL];
+ u8 rc_phy_mode;
+ u8 rate_max_phy;
+ u32 probe_interval;
};
struct ath_rateset {
@@ -248,29 +262,32 @@ struct ath_rateset {
struct ath_rate_softc {
/* phy tables that contain rate control data */
const void *hw_rate_table[ATH9K_MODE_MAX];
- int fixedrix; /* -1 or index of fixed rate */
+
+ /* -1 or index of fixed rate */
+ int fixedrix;
};
/* per-node state */
struct ath_rate_node {
- struct ath_tx_ratectrl tx_ratectrl; /* rate control state proper */
- u32 prev_data_rix; /* rate idx of last data frame */
+ struct ath_tx_ratectrl tx_ratectrl;
- /* map of rate ix -> negotiated rate set ix */
- u8 rixmap[MAX_TX_RATE_TBL];
+ /* rate idx of last data frame */
+ u32 prev_data_rix;
- /* map of ht rate ix -> negotiated rate set ix */
- u8 ht_rixmap[MAX_TX_RATE_TBL];
+ /* ht capabilities */
+ u8 ht_cap;
- u8 ht_cap; /* ht capabilities */
- u8 ant_tx; /* current transmit antenna */
+ /* When TRUE, only single stream Tx possible */
+ u8 single_stream;
- u8 single_stream; /* When TRUE, only single
- stream Tx possible */
- struct ath_rateset neg_rates; /* Negotiated rates */
- struct ath_rateset neg_ht_rates; /* Negotiated HT rates */
- struct ath_rate_softc *asc; /* back pointer to atheros softc */
- struct ath_vap *avp; /* back pointer to vap */
+ /* Negotiated rates */
+ struct ath_rateset neg_rates;
+
+ /* Negotiated HT rates */
+ struct ath_rateset neg_ht_rates;
+
+ struct ath_rate_softc *asc;
+ struct ath_vap *avp;
};
/* Driver data of ieee80211_tx_info */
@@ -297,17 +314,10 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv);
void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp);
/*
- * Return the tx rate series.
- */
-void ath_rate_findrate(struct ath_softc *sc, struct ath_rate_node *ath_rc_priv,
- int num_tries, int num_rates,
- unsigned int rcflag, struct ath_rc_series[],
- int *is_probe, int isretry);
-/*
* Return rate index for given Dot11 Rate.
*/
u8 ath_rate_findrateix(struct ath_softc *sc,
- u8 dot11_rate);
+ u8 dot11_rate);
/* Routines to register/unregister rate control algorithm */
int ath_rate_control_register(void);
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 2fe806175c0..4983402af55 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -184,7 +184,7 @@ static int ath_ampdu_input(struct ath_softc *sc,
tid = qc[0] & 0xf;
}
- if (sc->sc_opmode == ATH9K_M_STA) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
/* Drop the frame not belonging to me. */
if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) {
dev_kfree_skb(skb);
@@ -360,8 +360,9 @@ static void ath_rx_flush_tid(struct ath_softc *sc,
struct ath_arx_tid *rxtid, int drop)
{
struct ath_rxbuf *rxbuf;
+ unsigned long flag;
- spin_lock_bh(&rxtid->tidlock);
+ spin_lock_irqsave(&rxtid->tidlock, flag);
while (rxtid->baw_head != rxtid->baw_tail) {
rxbuf = rxtid->rxbuf + rxtid->baw_head;
if (!rxbuf->rx_wbuf) {
@@ -382,7 +383,7 @@ static void ath_rx_flush_tid(struct ath_softc *sc,
INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
}
- spin_unlock_bh(&rxtid->tidlock);
+ spin_unlock_irqrestore(&rxtid->tidlock, flag);
}
static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
@@ -448,17 +449,16 @@ static int ath_rx_indicate(struct ath_softc *sc,
int type;
/* indicate frame to the stack, which will free the old skb. */
- type = ath__rx_indicate(sc, skb, status, keyix);
+ type = _ath_rx_indicate(sc, skb, status, keyix);
/* allocate a new skb and queue it to for H/W processing */
nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
if (nskb != NULL) {
bf->bf_mpdu = nskb;
- bf->bf_buf_addr = ath_skb_map_single(sc,
- nskb,
- PCI_DMA_FROMDEVICE,
- /* XXX: Remove get_dma_mem_context() */
- get_dma_mem_context(bf, bf_dmacontext));
+ bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data,
+ skb_end_pointer(nskb) - nskb->head,
+ PCI_DMA_FROMDEVICE);
+ bf->bf_dmacontext = bf->bf_buf_addr;
ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf;
/* queue the new wbuf to H/W */
@@ -504,7 +504,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
do {
spin_lock_init(&sc->sc_rxflushlock);
- sc->sc_rxflush = 0;
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->sc_rxbuflock);
/*
@@ -541,9 +541,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
}
bf->bf_mpdu = skb;
- bf->bf_buf_addr =
- ath_skb_map_single(sc, skb, PCI_DMA_FROMDEVICE,
- get_dma_mem_context(bf, bf_dmacontext));
+ bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
+ skb_end_pointer(skb) - skb->head,
+ PCI_DMA_FROMDEVICE);
+ bf->bf_dmacontext = bf->bf_buf_addr;
ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
}
sc->sc_rxlink = NULL;
@@ -597,6 +598,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
u32 ath_calcrxfilter(struct ath_softc *sc)
{
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
+
u32 rfilt;
rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
@@ -604,25 +606,29 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
- if (sc->sc_opmode != ATH9K_M_STA)
+ if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/* Can't set HOSTAP into promiscous mode */
- if (sc->sc_opmode == ATH9K_M_MONITOR) {
+ if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
+ (sc->rx_filter & FIF_PROMISC_IN_BSS)) ||
+ (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
rfilt |= ATH9K_RX_FILTER_PROM;
/* ??? To prevent from sending ACK */
rfilt &= ~ATH9K_RX_FILTER_UCAST;
}
- if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS ||
- sc->sc_scanning)
+ if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
+ (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) ||
+ (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))
rfilt |= ATH9K_RX_FILTER_BEACON;
/* If in HOSTAP mode, want to enable reception of PSPOLL frames
& beacon frames */
- if (sc->sc_opmode == ATH9K_M_HOSTAP)
+ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
return rfilt;
+
#undef RX_FILTER_PRESERVE
}
@@ -702,11 +708,11 @@ void ath_flushrecv(struct ath_softc *sc)
* progress (see references to sc_rxflush)
*/
spin_lock_bh(&sc->sc_rxflushlock);
- sc->sc_rxflush = 1;
+ sc->sc_flags |= SC_OP_RXFLUSH;
ath_rx_tasklet(sc, 1);
- sc->sc_rxflush = 0;
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_unlock_bh(&sc->sc_rxflushlock);
}
@@ -719,7 +725,7 @@ int ath_rx_input(struct ath_softc *sc,
struct ath_recv_status *rx_status,
enum ATH_RX_TYPE *status)
{
- if (is_ampdu && sc->sc_rxaggr) {
+ if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) {
*status = ATH_RX_CONSUMED;
return ath_ampdu_input(sc, an, skb, rx_status);
} else {
@@ -750,7 +756,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
do {
/* If handling rx interrupt and flush is in progress => exit */
- if (sc->sc_rxflush && (flush == 0))
+ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
break;
spin_lock_bh(&sc->sc_rxbuflock);
@@ -886,7 +892,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
- memzero(&rx_status, sizeof(struct ath_recv_status));
+ memset(&rx_status, 0, sizeof(struct ath_recv_status));
if (ds->ds_rxstat.rs_more) {
/*
@@ -900,7 +906,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* Enable this if you want to see
* error frames in Monitor mode.
*/
- if (sc->sc_opmode != ATH9K_M_MONITOR)
+ if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
goto rx_next;
#endif
/* fall thru for monitor mode handling... */
@@ -945,7 +951,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
- if (sc->sc_opmode == ATH9K_M_MONITOR) {
+ if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
if (ds->ds_rxstat.rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_CRC))
@@ -993,20 +999,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
rx_status.flags |= ATH_RX_SHORT_GI;
}
- /* sc->sc_noise_floor is only available when the station
+ /* sc_noise_floor is only available when the station
attaches to an AP, so we use a default value
if we are not yet attached. */
-
- /* XXX we should use either sc->sc_noise_floor or
- * ath_hal_getChanNoise(ah, &sc->sc_curchan)
- * to calculate the noise floor.
- * However, the value returned by ath_hal_getChanNoise
- * seems to be incorrect (-31dBm on the last test),
- * so we will use a hard-coded value until we
- * figure out what is going on.
- */
rx_status.abs_rssi =
- ds->ds_rxstat.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
+ ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor;
pci_dma_sync_single_for_cpu(sc->pdev,
bf->bf_buf_addr,
@@ -1089,7 +1086,7 @@ rx_next:
"%s: Reset rx chain mask. "
"Do internal reset\n", __func__);
ASSERT(flush == 0);
- ath_internal_reset(sc);
+ ath_reset(sc, false);
}
return 0;
@@ -1127,7 +1124,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
rxtid = &an->an_aggr.rx.tid[tid];
spin_lock_bh(&rxtid->tidlock);
- if (sc->sc_rxaggr) {
+ if (sc->sc_flags & SC_OP_RXAGGR) {
/* Allow aggregation reception
* Adjust rx BA window size. Peer might indicate a
* zero buffer size for a _dont_care_ condition.
@@ -1160,7 +1157,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
} else {
/* Ensure the memory is zeroed out (all internal
* pointers are null) */
- memzero(rxtid->rxbuf, ATH_TID_MAX_BUFS *
+ memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS *
sizeof(struct ath_rxbuf));
DPRINTF(sc, ATH_DBG_AGGR,
"%s: Allocated @%p\n", __func__, rxtid->rxbuf);
@@ -1227,7 +1224,7 @@ void ath_rx_aggr_teardown(struct ath_softc *sc,
void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
{
- if (sc->sc_rxaggr) {
+ if (sc->sc_flags & SC_OP_RXAGGR) {
struct ath_arx_tid *rxtid;
int tidno;
@@ -1259,7 +1256,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
{
- if (sc->sc_rxaggr) {
+ if (sc->sc_flags & SC_OP_RXAGGR) {
struct ath_arx_tid *rxtid;
int tidno, i;
@@ -1292,27 +1289,3 @@ void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
{
ath_rx_node_cleanup(sc, an);
}
-
-dma_addr_t ath_skb_map_single(struct ath_softc *sc,
- struct sk_buff *skb,
- int direction,
- dma_addr_t *pa)
-{
- /*
- * NB: do NOT use skb->len, which is 0 on initialization.
- * Use skb's entire data area instead.
- */
- *pa = pci_map_single(sc->pdev, skb->data,
- skb_end_pointer(skb) - skb->head, direction);
- return *pa;
-}
-
-void ath_skb_unmap_single(struct ath_softc *sc,
- struct sk_buff *skb,
- int direction,
- dma_addr_t *pa)
-{
- /* Unmap skb's entire data area */
- pci_unmap_single(sc->pdev, *pa,
- skb_end_pointer(skb) - skb->head, direction);
-}
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h
index 42b0890a468..60617ae6620 100644
--- a/drivers/net/wireless/ath9k/reg.h
+++ b/drivers/net/wireless/ath9k/reg.h
@@ -899,12 +899,6 @@ enum {
#define AR_GPIO_OUTPUT_MUX2 0x4064
#define AR_GPIO_OUTPUT_MUX3 0x4068
-#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
-#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
-#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
-#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
-#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
-
#define AR_INPUT_STATE 0x406c
#define AR_EEPROM_STATUS_DATA 0x407c
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 157f830ee6b..3a4757942b3 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -60,79 +60,6 @@ static u32 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
/*
- * Insert a chain of ath_buf (descriptors) on a multicast txq
- * but do NOT start tx DMA on this queue.
- * NB: must be called with txq lock held
- */
-
-static void ath_tx_mcastqaddbuf(struct ath_softc *sc,
- struct ath_txq *txq,
- struct list_head *head)
-{
- struct ath_hal *ah = sc->sc_ah;
- struct ath_buf *bf;
-
- if (list_empty(head))
- return;
-
- /*
- * Insert the frame on the outbound list and
- * pass it on to the hardware.
- */
- bf = list_first_entry(head, struct ath_buf, list);
-
- /*
- * The CAB queue is started from the SWBA handler since
- * frames only go out on DTIM and to avoid possible races.
- */
- ath9k_hw_set_interrupts(ah, 0);
-
- /*
- * If there is anything in the mcastq, we want to set
- * the "more data" bit in the last item in the queue to
- * indicate that there is "more data". It makes sense to add
- * it here since you are *always* going to have
- * more data when adding to this queue, no matter where
- * you call from.
- */
-
- if (txq->axq_depth) {
- struct ath_buf *lbf;
- struct ieee80211_hdr *hdr;
-
- /*
- * Add the "more data flag" to the last frame
- */
-
- lbf = list_entry(txq->axq_q.prev, struct ath_buf, list);
- hdr = (struct ieee80211_hdr *)
- ((struct sk_buff *)(lbf->bf_mpdu))->data;
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- }
-
- /*
- * Now, concat the frame onto the queue
- */
- list_splice_tail_init(head, &txq->axq_q);
- txq->axq_depth++;
- txq->axq_totalqueued++;
- txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
-
- DPRINTF(sc, ATH_DBG_QUEUE,
- "%s: txq depth = %d\n", __func__, txq->axq_depth);
- if (txq->axq_link != NULL) {
- *txq->axq_link = bf->bf_daddr;
- DPRINTF(sc, ATH_DBG_XMIT,
- "%s: link[%u](%p)=%llx (%p)\n",
- __func__,
- txq->axq_qnum, txq->axq_link,
- ito64(bf->bf_daddr), bf->bf_desc);
- }
- txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
- ath9k_hw_set_interrupts(ah, sc->sc_imask);
-}
-
-/*
* Insert a chain of ath_buf (descriptors) on a txq and
* assume the descriptors are already chained together by caller.
* NB: must be called with txq lock held
@@ -277,8 +204,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
__le16 fc;
u8 *qc;
- memset(txctl, 0, sizeof(struct ath_tx_control));
-
txctl->dev = sc;
hdr = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
@@ -302,7 +227,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
}
txctl->if_id = 0;
- txctl->nextfraglen = 0;
txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3);
txctl->txpower = MAX_RATE_POWER; /* FIXME */
@@ -313,13 +237,13 @@ static int ath_tx_prepare(struct ath_softc *sc,
if (tx_info->control.hw_key) {
txctl->keyix = tx_info->control.hw_key->hw_key_idx;
- txctl->frmlen += tx_info->control.icv_len;
+ txctl->frmlen += tx_info->control.hw_key->icv_len;
- if (sc->sc_keytype == ATH9K_CIPHER_WEP)
+ if (tx_info->control.hw_key->alg == ALG_WEP)
txctl->keytype = ATH9K_KEY_TYPE_WEP;
- else if (sc->sc_keytype == ATH9K_CIPHER_TKIP)
+ else if (tx_info->control.hw_key->alg == ALG_TKIP)
txctl->keytype = ATH9K_KEY_TYPE_TKIP;
- else if (sc->sc_keytype == ATH9K_CIPHER_AES_CCM)
+ else if (tx_info->control.hw_key->alg == ALG_CCMP)
txctl->keytype = ATH9K_KEY_TYPE_AES;
}
@@ -329,12 +253,18 @@ static int ath_tx_prepare(struct ath_softc *sc,
/* Fill qnum */
- txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
- txq = &sc->sc_txq[txctl->qnum];
+ if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) {
+ txctl->qnum = 0;
+ txq = sc->sc_cabq;
+ } else {
+ txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+ txq = &sc->sc_txq[txctl->qnum];
+ }
spin_lock_bh(&txq->axq_lock);
/* Try to avoid running out of descriptors */
- if (txq->axq_depth >= (ATH_TXBUF - 20)) {
+ if (txq->axq_depth >= (ATH_TXBUF - 20) &&
+ !(txctl->flags & ATH9K_TXDESC_CAB)) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: TX queue: %d is full, depth: %d\n",
__func__,
@@ -354,12 +284,12 @@ static int ath_tx_prepare(struct ath_softc *sc,
/* Fill flags */
- txctl->flags = ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+ txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
- tx_info->flags |= ATH9K_TXDESC_NOACK;
+ txctl->flags |= ATH9K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
- tx_info->flags |= ATH9K_TXDESC_RTSENA;
+ txctl->flags |= ATH9K_TXDESC_RTSENA;
/*
* Setup for rate calculations.
@@ -392,7 +322,7 @@ static int ath_tx_prepare(struct ath_softc *sc,
* incremented by the fragmentation routine.
*/
if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) &&
- txctl->ht && sc->sc_txaggr) {
+ txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
struct ath_atx_tid *tid;
tid = ATH_AN_2_TID(txctl->an, txctl->tidno);
@@ -413,50 +343,18 @@ static int ath_tx_prepare(struct ath_softc *sc,
}
rix = rcs[0].rix;
- /*
- * Calculate duration. This logically belongs in the 802.11
- * layer but it lacks sufficient information to calculate it.
- */
- if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) {
- u16 dur;
+ if (ieee80211_has_morefrags(fc) ||
+ (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
/*
- * XXX not right with fragmentation.
- */
- if (sc->sc_flags & ATH_PREAMBLE_SHORT)
- dur = rt->info[rix].spAckDuration;
- else
- dur = rt->info[rix].lpAckDuration;
-
- if (le16_to_cpu(hdr->frame_control) &
- IEEE80211_FCTL_MOREFRAGS) {
- dur += dur; /* Add additional 'SIFS + ACK' */
-
- /*
- ** Compute size of next fragment in order to compute
- ** durations needed to update NAV.
- ** The last fragment uses the ACK duration only.
- ** Add time for next fragment.
- */
- dur += ath9k_hw_computetxtime(sc->sc_ah, rt,
- txctl->nextfraglen,
- rix, sc->sc_flags & ATH_PREAMBLE_SHORT);
- }
-
- if (ieee80211_has_morefrags(fc) ||
- (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
- /*
- ** Force hardware to use computed duration for next
- ** fragment by disabling multi-rate retry, which
- ** updates duration based on the multi-rate
- ** duration table.
- */
- rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
- rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
- /* reset tries but keep rate index */
- rcs[0].tries = ATH_TXMAXTRY;
- }
-
- hdr->duration_id = cpu_to_le16(dur);
+ ** Force hardware to use computed duration for next
+ ** fragment by disabling multi-rate retry, which
+ ** updates duration based on the multi-rate
+ ** duration table.
+ */
+ rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
+ rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
+ /* reset tries but keep rate index */
+ rcs[0].tries = ATH_TXMAXTRY;
}
/*
@@ -484,12 +382,8 @@ static int ath_tx_prepare(struct ath_softc *sc,
if (is_multicast_ether_addr(hdr->addr1)) {
antenna = sc->sc_mcastantenna + 1;
sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1;
- } else
- antenna = sc->sc_txantenna;
+ }
-#ifdef USE_LEGACY_HAL
- txctl->antenna = antenna;
-#endif
return 0;
}
@@ -502,7 +396,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
{
struct sk_buff *skb = bf->bf_mpdu;
struct ath_xmit_status tx_status;
- dma_addr_t *pa;
/*
* Set retry information.
@@ -518,13 +411,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
if (!txok) {
tx_status.flags |= ATH_TX_ERROR;
- if (bf->bf_isxretried)
+ if (bf_isxretried(bf))
tx_status.flags |= ATH_TX_XRETRY;
}
/* Unmap this frame */
- pa = get_dma_mem_context(bf, bf_dmacontext);
pci_unmap_single(sc->pdev,
- *pa,
+ bf->bf_dmacontext,
skb->len,
PCI_DMA_TODEVICE);
/* complete this frame */
@@ -629,7 +521,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc,
if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
return 0;
- isaggr = bf->bf_isaggr;
+ isaggr = bf_isaggr(bf);
if (isaggr) {
seq_st = ATH_DS_BA_SEQ(ds);
memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
@@ -651,7 +543,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
- bf->bf_isretried = 1;
+ bf->bf_state.bf_type |= BUF_RETRY;
bf->bf_retries++;
skb = bf->bf_mpdu;
@@ -698,7 +590,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc,
u8 rc;
int streams, pktlen;
- pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen;
+ pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
rc = rt->info[rix].rateCode;
/*
@@ -742,7 +634,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
int i, flags, rtsctsena = 0, dynamic_mimops = 0;
u32 ctsduration = 0;
u8 rix = 0, cix, ctsrate = 0;
- u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit;
+ u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit;
struct ath_node *an = (struct ath_node *) bf->bf_node;
/*
@@ -781,7 +673,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* let rate series flags determine which rates will actually
* use RTS.
*/
- if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf->bf_isdata) {
+ if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
BUG_ON(!an);
/*
* 802.11g protection not needed, use our default behavior
@@ -793,7 +685,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* and the second aggregate should have any protection at all.
*/
if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) {
- if (!bf->bf_aggrburst) {
+ if (!bf_isaggrburst(bf)) {
flags = ATH9K_TXDESC_RTSENA;
dynamic_mimops = 1;
} else {
@@ -806,7 +698,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* Set protection if aggregate protection on
*/
if (sc->sc_config.ath_aggr_prot &&
- (!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) {
+ (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
flags = ATH9K_TXDESC_RTSENA;
cix = rt->info[sc->sc_protrix].controlRate;
rtsctsena = 1;
@@ -815,7 +707,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
/*
* For AR5416 - RTS cannot be followed by a frame larger than 8K.
*/
- if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) {
+ if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) {
/*
* Ensure that in the case of SM Dynamic power save
* while we are bursting the second aggregate the
@@ -832,12 +724,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
/* NB: cix is set above where RTS/CTS is enabled */
BUG_ON(cix == 0xff);
ctsrate = rt->info[cix].rateCode |
- (bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0);
+ (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
/*
* Setup HAL rate series
*/
- memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
+ memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
for (i = 0; i < 4; i++) {
if (!bf->bf_rcs[i].tries)
@@ -846,7 +738,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
rix = bf->bf_rcs[i].rix;
series[i].Rate = rt->info[rix].rateCode |
- (bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0);
+ (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0);
series[i].Tries = bf->bf_rcs[i].tries;
@@ -862,7 +754,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
sc, rix, bf,
(bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
(bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
- bf->bf_shpreamble);
+ bf_isshpreamble(bf));
if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) &&
(bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) {
@@ -875,7 +767,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
*/
series[i].ChSel = sc->sc_tx_chainmask;
} else {
- if (bf->bf_ht)
+ if (bf_isht(bf))
series[i].ChSel =
ath_chainmask_sel_logic(sc, an);
else
@@ -908,7 +800,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* use the precalculated ACK durations.
*/
if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */
- ctsduration += bf->bf_shpreamble ?
+ ctsduration += bf_isshpreamble(bf) ?
rt->info[cix].spAckDuration :
rt->info[cix].lpAckDuration;
}
@@ -916,7 +808,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
ctsduration += series[0].PktDuration;
if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
- ctsduration += bf->bf_shpreamble ?
+ ctsduration += bf_isshpreamble(bf) ?
rt->info[rix].spAckDuration :
rt->info[rix].lpAckDuration;
}
@@ -925,17 +817,17 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* Disable multi-rate retry when using RTS/CTS by clearing
* series 1, 2 and 3.
*/
- memzero(&series[1], sizeof(struct ath9k_11n_rate_series) * 3);
+ memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3);
}
/*
* set dur_update_en for l-sig computation except for PS-Poll frames
*/
ath9k_hw_set11n_ratescenario(ah, ds, lastds,
- !bf->bf_ispspoll,
- ctsrate,
- ctsduration,
- series, 4, flags);
+ !bf_ispspoll(bf),
+ ctsrate,
+ ctsduration,
+ series, 4, flags);
if (sc->sc_config.ath_aggr_prot && flags)
ath9k_hw_set11n_burstduration(ah, ds, 8192);
}
@@ -958,7 +850,7 @@ static int ath_tx_send_normal(struct ath_softc *sc,
BUG_ON(list_empty(bf_head));
bf = list_first_entry(bf_head, struct ath_buf, list);
- bf->bf_isampdu = 0; /* regular HT frame */
+ bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */
skb = (struct sk_buff *)bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
@@ -998,7 +890,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
while (!list_empty(&tid->buf_q)) {
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- ASSERT(!bf->bf_isretried);
+ ASSERT(!bf_isretried(bf));
list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
ath_tx_send_normal(sc, txq, tid, &bf_head);
}
@@ -1025,7 +917,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
- isaggr = bf->bf_isaggr;
+ isaggr = bf_isaggr(bf);
if (isaggr) {
if (txok) {
if (ATH_DS_TX_BA(ds)) {
@@ -1038,7 +930,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
ATH_DS_BA_BITMAP(ds),
WME_BA_BMP_SIZE >> 3);
} else {
- memzero(ba, WME_BA_BMP_SIZE >> 3);
+ memset(ba, 0, WME_BA_BMP_SIZE >> 3);
/*
* AR5416 can become deaf/mute when BA
@@ -1047,11 +939,11 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
* when perform internal reset in this routine.
* Only enable reset in STA mode for now.
*/
- if (sc->sc_opmode == ATH9K_M_STA)
+ if (sc->sc_ah->ah_opmode == ATH9K_M_STA)
needreset = 1;
}
} else {
- memzero(ba, WME_BA_BMP_SIZE >> 3);
+ memset(ba, 0, WME_BA_BMP_SIZE >> 3);
}
}
@@ -1075,7 +967,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
ath_tx_set_retry(sc, bf);
txpending = 1;
} else {
- bf->bf_isxretried = 1;
+ bf->bf_state.bf_type |= BUF_XRETRY;
txfail = 1;
sendbar = 1;
}
@@ -1175,11 +1067,8 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
tbf->bf_lastfrm->bf_desc);
/* copy the DMA context */
- copy_dma_mem_context(
- get_dma_mem_context(tbf,
- bf_dmacontext),
- get_dma_mem_context(bf_last,
- bf_dmacontext));
+ tbf->bf_dmacontext =
+ bf_last->bf_dmacontext;
}
list_add_tail(&tbf->list, &bf_head);
} else {
@@ -1188,7 +1077,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
* software retry
*/
ath9k_hw_cleartxdesc(sc->sc_ah,
- bf->bf_lastfrm->bf_desc);
+ bf->bf_lastfrm->bf_desc);
}
/*
@@ -1242,7 +1131,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
}
if (needreset)
- ath_internal_reset(sc);
+ ath_reset(sc, false);
return;
}
@@ -1331,7 +1220,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_depth--;
- if (bf->bf_isaggr)
+ if (bf_isaggr(bf))
txq->axq_aggr_depth--;
txok = (ds->ds_txstat.ts_status == 0);
@@ -1345,14 +1234,14 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
spin_unlock_bh(&sc->sc_txbuflock);
}
- if (!bf->bf_isampdu) {
+ if (!bf_isampdu(bf)) {
/*
* This frame is sent out as a single frame.
* Use hardware retry status for this frame.
*/
bf->bf_retries = ds->ds_txstat.ts_longretry;
if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_isxretried = 1;
+ bf->bf_state.bf_type |= BUF_XRETRY;
nbad = 0;
} else {
nbad = ath_tx_num_badfrms(sc, bf, txok);
@@ -1368,7 +1257,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (ds->ds_txstat.ts_status == 0)
nacked++;
- if (bf->bf_isdata) {
+ if (bf_isdata(bf)) {
if (isrifs)
tmp_ds = bf->bf_rifslast->bf_desc;
else
@@ -1384,7 +1273,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
/*
* Complete this transmit unit
*/
- if (bf->bf_isampdu)
+ if (bf_isampdu(bf))
ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok);
else
ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
@@ -1406,7 +1295,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
/*
* schedule any pending packets if aggregation is enabled
*/
- if (sc->sc_txaggr)
+ if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
@@ -1430,10 +1319,9 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
struct ath_hal *ah = sc->sc_ah;
int i;
int npend = 0;
- enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
/* XXX return value */
- if (!sc->sc_invalid) {
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
ath_tx_stopdma(sc, &sc->sc_txq[i]);
@@ -1454,10 +1342,11 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
"%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, sc->sc_opmode,
- &sc->sc_curchan, ht_macmode,
- sc->sc_tx_chainmask, sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing, true, &status)) {
+ if (!ath9k_hw_reset(ah,
+ sc->sc_ah->ah_curchan,
+ sc->sc_ht_info.tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, true, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: unable to reset hardware; hal status %u\n",
@@ -1481,7 +1370,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc,
{
int index, cindex;
- if (bf->bf_isretried)
+ if (bf_isretried(bf))
return;
index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
@@ -1516,7 +1405,7 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
BUG_ON(list_empty(bf_head));
bf = list_first_entry(bf_head, struct ath_buf, list);
- bf->bf_isampdu = 1;
+ bf->bf_state.bf_type |= BUF_AMPDU;
bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */
bf->bf_tidno = txctl->tidno;
@@ -1860,7 +1749,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
if (bf->bf_nframes == 1) {
ASSERT(bf->bf_lastfrm == bf_last);
- bf->bf_isaggr = 0;
+ bf->bf_state.bf_type &= ~BUF_AGGR;
/*
* clear aggr bits for every descriptor
* XXX TODO: is there a way to optimize it?
@@ -1877,7 +1766,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
/*
* setup first desc with rate and aggr info
*/
- bf->bf_isaggr = 1;
+ bf->bf_state.bf_type |= BUF_AGGR;
ath_buf_set_rate(sc, bf);
ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
@@ -1925,7 +1814,7 @@ static void ath_tid_drain(struct ath_softc *sc,
list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
/* update baw for software retried frame */
- if (bf->bf_isretried)
+ if (bf_isretried(bf))
ath_tx_update_baw(sc, tid, bf->bf_seqno);
/*
@@ -1990,13 +1879,18 @@ static int ath_tx_start_dma(struct ath_softc *sc,
struct list_head bf_head;
struct ath_desc *ds;
struct ath_hal *ah = sc->sc_ah;
- struct ath_txq *txq = &sc->sc_txq[txctl->qnum];
+ struct ath_txq *txq;
struct ath_tx_info_priv *tx_info_priv;
struct ath_rc_series *rcs;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
__le16 fc = hdr->frame_control;
+ if (unlikely(txctl->flags & ATH9K_TXDESC_CAB))
+ txq = sc->sc_cabq;
+ else
+ txq = &sc->sc_txq[txctl->qnum];
+
/* For each sglist entry, allocate an ath_buf for DMA */
INIT_LIST_HEAD(&bf_head);
spin_lock_bh(&sc->sc_txbuflock);
@@ -2014,11 +1908,21 @@ static int ath_tx_start_dma(struct ath_softc *sc,
/* set up this buffer */
ATH_TXBUF_RESET(bf);
bf->bf_frmlen = txctl->frmlen;
- bf->bf_isdata = ieee80211_is_data(fc);
- bf->bf_isbar = ieee80211_is_back_req(fc);
- bf->bf_ispspoll = ieee80211_is_pspoll(fc);
+
+ ieee80211_is_data(fc) ?
+ (bf->bf_state.bf_type |= BUF_DATA) :
+ (bf->bf_state.bf_type &= ~BUF_DATA);
+ ieee80211_is_back_req(fc) ?
+ (bf->bf_state.bf_type |= BUF_BAR) :
+ (bf->bf_state.bf_type &= ~BUF_BAR);
+ ieee80211_is_pspoll(fc) ?
+ (bf->bf_state.bf_type |= BUF_PSPOLL) :
+ (bf->bf_state.bf_type &= ~BUF_PSPOLL);
+ (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ?
+ (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) :
+ (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE);
+
bf->bf_flags = txctl->flags;
- bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT;
bf->bf_keytype = txctl->keytype;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
rcs = tx_info_priv->rcs;
@@ -2038,8 +1942,7 @@ static int ath_tx_start_dma(struct ath_softc *sc,
/*
* Save the DMA context in the first ath_buf
*/
- copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext),
- get_dma_mem_context(txctl, dmacontext));
+ bf->bf_dmacontext = txctl->dmacontext;
/*
* Formulate first tx descriptor with tx controls.
@@ -2060,11 +1963,13 @@ static int ath_tx_start_dma(struct ath_softc *sc,
ds); /* first descriptor */
bf->bf_lastfrm = bf;
- bf->bf_ht = txctl->ht;
+ (txctl->ht) ?
+ (bf->bf_state.bf_type |= BUF_HT) :
+ (bf->bf_state.bf_type &= ~BUF_HT);
spin_lock_bh(&txq->axq_lock);
- if (txctl->ht && sc->sc_txaggr) {
+ if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno);
if (ath_aggr_query(sc, an, txctl->tidno)) {
/*
@@ -2090,27 +1995,7 @@ static int ath_tx_start_dma(struct ath_softc *sc,
bf->bf_tidno = txctl->tidno;
}
- if (is_multicast_ether_addr(hdr->addr1)) {
- struct ath_vap *avp = sc->sc_vaps[txctl->if_id];
-
- /*
- * When servicing one or more stations in power-save
- * mode (or) if there is some mcast data waiting on
- * mcast queue (to prevent out of order delivery of
- * mcast,bcast packets) multicast frames must be
- * buffered until after the beacon. We use the private
- * mcast queue for that.
- */
- /* XXX? more bit in 802.11 frame header */
- spin_lock_bh(&avp->av_mcastq.axq_lock);
- if (txctl->ps || avp->av_mcastq.axq_depth)
- ath_tx_mcastqaddbuf(sc,
- &avp->av_mcastq, &bf_head);
- else
- ath_tx_txqaddbuf(sc, txq, &bf_head);
- spin_unlock_bh(&avp->av_mcastq.axq_lock);
- } else
- ath_tx_txqaddbuf(sc, txq, &bf_head);
+ ath_tx_txqaddbuf(sc, txq, &bf_head);
}
spin_unlock_bh(&txq->axq_lock);
return 0;
@@ -2118,30 +2003,31 @@ static int ath_tx_start_dma(struct ath_softc *sc,
static void xmit_map_sg(struct ath_softc *sc,
struct sk_buff *skb,
- dma_addr_t *pa,
struct ath_tx_control *txctl)
{
struct ath_xmit_status tx_status;
struct ath_atx_tid *tid;
struct scatterlist sg;
- *pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+ txctl->dmacontext = pci_map_single(sc->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
/* setup S/G list */
memset(&sg, 0, sizeof(struct scatterlist));
- sg_dma_address(&sg) = *pa;
+ sg_dma_address(&sg) = txctl->dmacontext;
sg_dma_len(&sg) = skb->len;
if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) {
/*
* We have to do drop frame here.
*/
- pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE);
+ pci_unmap_single(sc->pdev, txctl->dmacontext,
+ skb->len, PCI_DMA_TODEVICE);
tx_status.retries = 0;
tx_status.flags = ATH_TX_ERROR;
- if (txctl->ht && sc->sc_txaggr) {
+ if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
/* Reclaim the seqno. */
tid = ATH_AN_2_TID((struct ath_node *)
txctl->an, txctl->tidno);
@@ -2162,7 +2048,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
/* Setup tx descriptors */
error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
- "tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC);
+ "tx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: failed to allocate tx descriptors: %d\n",
@@ -2212,7 +2098,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
struct ath9k_tx_queue_info qi;
int qnum;
- memzero(&qi, sizeof(qi));
+ memset(&qi, 0, sizeof(qi));
qi.tqi_subtype = subtype;
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
@@ -2403,6 +2289,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
struct ath_tx_control txctl;
int error = 0;
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
error = ath_tx_prepare(sc, skb, &txctl);
if (error == 0)
/*
@@ -2410,9 +2297,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
* ath_tx_start_dma() will be called either synchronously
* or asynchrounsly once DMA is complete.
*/
- xmit_map_sg(sc, skb,
- get_dma_mem_context(&txctl, dmacontext),
- &txctl);
+ xmit_map_sg(sc, skb, &txctl);
else
ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
@@ -2424,8 +2309,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
void ath_tx_tasklet(struct ath_softc *sc)
{
- u64 tsf = ath9k_hw_gettsf64(sc->sc_ah);
- int i, nacked = 0;
+ int i;
u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
@@ -2435,10 +2319,8 @@ void ath_tx_tasklet(struct ath_softc *sc)
*/
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
- nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
+ ath_tx_processq(sc, &sc->sc_txq[i]);
}
- if (nacked)
- sc->sc_lastrx = tsf;
}
void ath_tx_draintxq(struct ath_softc *sc,
@@ -2486,14 +2368,14 @@ void ath_tx_draintxq(struct ath_softc *sc,
spin_unlock_bh(&txq->axq_lock);
- if (bf->bf_isampdu)
+ if (bf_isampdu(bf))
ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0);
else
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
}
/* flush any pending frames if aggregation is enabled */
- if (sc->sc_txaggr) {
+ if (sc->sc_flags & SC_OP_TXAGGR) {
if (!retry_tx) {
spin_lock_bh(&txq->axq_lock);
ath_txq_drain_pending_buffers(sc, txq,
@@ -2509,7 +2391,7 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx)
{
/* stop beacon queue. The beacon will be freed when
* we go to INIT state */
- if (!sc->sc_invalid) {
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
(void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__,
ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq));
@@ -2536,7 +2418,7 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
struct ath_atx_tid *txtid;
DECLARE_MAC_BUF(mac);
- if (!sc->sc_txaggr)
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
return AGGR_NOT_REQUIRED;
/* ADDBA exchange must be completed before sending aggregates */
@@ -2583,7 +2465,7 @@ int ath_tx_aggr_start(struct ath_softc *sc,
return -1;
}
- if (sc->sc_txaggr) {
+ if (sc->sc_flags & SC_OP_TXAGGR) {
txtid = ATH_AN_2_TID(an, tid);
txtid->addba_exchangeinprogress = 1;
ath_tx_pause_tid(sc, txtid);
@@ -2647,7 +2529,7 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
spin_lock_bh(&txq->axq_lock);
while (!list_empty(&txtid->buf_q)) {
bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
- if (!bf->bf_isretried) {
+ if (!bf_isretried(bf)) {
/*
* NB: it's based on the assumption that
* software retried frame will always stay
@@ -2743,7 +2625,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
{
- if (sc->sc_txaggr) {
+ if (sc->sc_flags & SC_OP_TXAGGR) {
struct ath_atx_tid *tid;
struct ath_atx_ac *ac;
int tidno, acno;
@@ -2855,7 +2737,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
{
- if (sc->sc_txaggr) {
+ if (sc->sc_flags & SC_OP_TXAGGR) {
struct ath_atx_tid *tid;
int tidno, i;
@@ -2869,3 +2751,57 @@ void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
}
}
}
+
+void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
+{
+ int hdrlen, padsize;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ath_tx_control txctl;
+
+ /*
+ * As a temporary workaround, assign seq# here; this will likely need
+ * to be cleaned up to work better with Beacon transmission and virtual
+ * BSSes.
+ */
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ sc->seq_no += 0x10;
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+ }
+
+ /* Add the padding after the header if this is not already done */
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ if (hdrlen & 3) {
+ padsize = hdrlen % 4;
+ if (skb_headroom(skb) < padsize) {
+ DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding "
+ "failed\n", __func__);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ skb_push(skb, padsize);
+ memmove(skb->data, skb->data + padsize, hdrlen);
+ }
+
+ DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n",
+ __func__,
+ skb);
+
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
+ txctl.flags = ATH9K_TXDESC_CAB;
+ if (ath_tx_prepare(sc, skb, &txctl) == 0) {
+ /*
+ * Start DMA mapping.
+ * ath_tx_start_dma() will be called either synchronously
+ * or asynchrounsly once DMA is complete.
+ */
+ xmit_map_sg(sc, skb, &txctl);
+ } else {
+ ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
+ DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
+ dev_kfree_skb_any(skb);
+ }
+}
+
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index bd65c485098..ecb02bdaab5 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2258,7 +2258,7 @@ static int atmel_get_freq(struct net_device *dev,
static int atmel_set_scan(struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ struct iw_point *dwrq,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 12617cd0b78..77406245dc7 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -158,7 +158,7 @@ static int atmel_probe(struct pcmcia_device *p_dev)
DEBUG(0, "atmel_attach()\n");
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;
@@ -224,13 +224,58 @@ static int card_present(void *arg)
return 0;
}
+static int atmel_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+ /* Do we need to allocate an interrupt? */
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int atmel_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
int last_fn, last_ret;
- u_char buf[64];
struct pcmcia_device_id *did;
dev = link->priv;
@@ -238,11 +283,6 @@ static int atmel_config(struct pcmcia_device *link)
DEBUG(0, "atmel_config(0x%p)\n", link);
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
@@ -255,66 +295,8 @@ static int atmel_config(struct pcmcia_device *link)
these things without consulting the CIS, and most client drivers
will only use the CIS to fill in implementation-defined details.
*/
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t dflt = { 0 };
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- if (cfg->index == 0) goto next_entry;
- link->conf.ConfigIndex = cfg->index;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
-
- /* If we got this far, we're cool! */
- break;
-
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
+ if (pcmcia_loop_config(link, atmel_config_check, NULL))
+ goto failed;
/*
Allocate an interrupt line. Note that this does not assign a
@@ -360,6 +342,7 @@ static int atmel_config(struct pcmcia_device *link)
cs_failed:
cs_error(link, last_fn, last_ret);
+ failed:
atmel_release(link);
return -ENODEV;
}
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 1fa043d1802..1f81d36f87c 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -80,6 +80,18 @@ config B43_NPHY
SAY N.
+config B43_PHY_LP
+ bool "IEEE 802.11g LP-PHY support (BROKEN)"
+ depends on B43 && EXPERIMENTAL && BROKEN
+ ---help---
+ Support for the LP-PHY.
+ The LP-PHY is an IEEE 802.11g based PHY built into some notebooks
+ and embedded devices.
+
+ THIS IS BROKEN AND DOES NOT WORK YET.
+
+ SAY N.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 8c52b0b9862..14a02b3aea5 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,8 +1,11 @@
b43-y += main.o
b43-y += tables.o
b43-$(CONFIG_B43_NPHY) += tables_nphy.o
-b43-y += phy.o
-b43-$(CONFIG_B43_NPHY) += nphy.o
+b43-y += phy_common.o
+b43-y += phy_g.o
+b43-y += phy_a.o
+b43-$(CONFIG_B43_NPHY) += phy_n.o
+b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index edcdfa36645..427b8203e3f 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -12,7 +12,7 @@
#include "leds.h"
#include "rfkill.h"
#include "lo.h"
-#include "phy.h"
+#include "phy_common.h"
/* The unique identifier of the firmware that's officially supported by
@@ -173,6 +173,11 @@ enum {
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
+/* TSSI information */
+#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
+#define B43_SHM_SH_TSSI_OFDM_A 0x0068 /* TSSI for last 4 OFDM frames (32bit) */
+#define B43_SHM_SH_TSSI_OFDM_G 0x0070 /* TSSI for last 4 OFDM frames (32bit) */
+#define B43_TSSI_MAX 0x7F /* Max value for one TSSI value */
/* SHM_SHARED TX FIFO variables */
#define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */
#define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */
@@ -508,122 +513,6 @@ struct b43_iv {
} __attribute__((__packed__));
-struct b43_phy {
- /* Band support flags. */
- bool supports_2ghz;
- bool supports_5ghz;
-
- /* GMODE bit enabled? */
- bool gmode;
-
- /* Analog Type */
- u8 analog;
- /* B43_PHYTYPE_ */
- u8 type;
- /* PHY revision number. */
- u8 rev;
-
- /* Radio versioning */
- u16 radio_manuf; /* Radio manufacturer */
- u16 radio_ver; /* Radio version */
- u8 radio_rev; /* Radio revision */
-
- bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
-
- /* ACI (adjacent channel interference) flags. */
- bool aci_enable;
- bool aci_wlan_automatic;
- bool aci_hw_rssi;
-
- /* Radio switched on/off */
- bool radio_on;
- struct {
- /* Values saved when turning the radio off.
- * They are needed when turning it on again. */
- bool valid;
- u16 rfover;
- u16 rfoverval;
- } radio_off_context;
-
- u16 minlowsig[2];
- u16 minlowsigpos[2];
-
- /* TSSI to dBm table in use */
- const s8 *tssi2dbm;
- /* Target idle TSSI */
- int tgt_idle_tssi;
- /* Current idle TSSI */
- int cur_idle_tssi;
-
- /* LocalOscillator control values. */
- struct b43_txpower_lo_control *lo_control;
- /* Values from b43_calc_loopback_gain() */
- s16 max_lb_gain; /* Maximum Loopback gain in hdB */
- s16 trsw_rx_gain; /* TRSW RX gain in hdB */
- s16 lna_lod_gain; /* LNA lod */
- s16 lna_gain; /* LNA */
- s16 pga_gain; /* PGA */
-
- /* Desired TX power level (in dBm).
- * This is set by the user and adjusted in b43_phy_xmitpower(). */
- u8 power_level;
- /* A-PHY TX Power control value. */
- u16 txpwr_offset;
-
- /* Current TX power level attenuation control values */
- struct b43_bbatt bbatt;
- struct b43_rfatt rfatt;
- u8 tx_control; /* B43_TXCTL_XXX */
-
- /* Hardware Power Control enabled? */
- bool hardware_power_control;
-
- /* Current Interference Mitigation mode */
- int interfmode;
- /* Stack of saved values from the Interference Mitigation code.
- * Each value in the stack is layed out as follows:
- * bit 0-11: offset
- * bit 12-15: register ID
- * bit 16-32: value
- * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
- */
-#define B43_INTERFSTACK_SIZE 26
- u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
-
- /* Saved values from the NRSSI Slope calculation */
- s16 nrssi[2];
- s32 nrssislope;
- /* In memory nrssi lookup table. */
- s8 nrssi_lt[64];
-
- /* current channel */
- u8 channel;
-
- u16 lofcal;
-
- u16 initval; //FIXME rename?
-
- /* PHY TX errors counter. */
- atomic_t txerr_cnt;
-
- /* The device does address auto increment for the OFDM tables.
- * We cache the previously used address here and omit the address
- * write on the next table access, if possible. */
- u16 ofdmtab_addr; /* The address currently set in hardware. */
- enum { /* The last data flow direction. */
- B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
- B43_OFDMTAB_DIRECTION_READ,
- B43_OFDMTAB_DIRECTION_WRITE,
- } ofdmtab_addr_direction;
-
-#if B43_DEBUG
- /* Manual TX-power control enabled? */
- bool manual_txpower_control;
- /* PHY registers locked by b43_phy_lock()? */
- bool phy_locked;
-#endif /* B43_DEBUG */
-};
-
/* Data structures for DMA transmission, per 80211 core. */
struct b43_dma {
struct b43_dmaring *tx_ring_AC_BK; /* Background */
@@ -680,7 +569,7 @@ struct b43_key {
#define B43_QOS_VOICE B43_QOS_PARAMS(3)
/* QOS parameter hardware data structure offsets. */
-#define B43_NR_QOSPARAMS 22
+#define B43_NR_QOSPARAMS 16
enum {
B43_QOSPARAM_TXOP = 0,
B43_QOSPARAM_CWMIN,
@@ -696,8 +585,6 @@ enum {
struct b43_qos_params {
/* The QOS parameters */
struct ieee80211_tx_queue_params p;
- /* Does this need to get uploaded to hardware? */
- bool need_hw_update;
};
struct b43_wldev;
@@ -759,11 +646,13 @@ struct b43_wl {
bool beacon_templates_virgin; /* Never wrote the templates? */
struct work_struct beacon_update_trigger;
- /* The current QOS parameters for the 4 queues.
- * This is protected by the irq_lock. */
+ /* The current QOS parameters for the 4 queues. */
struct b43_qos_params qos_params[4];
- /* Workqueue for updating QOS parameters in hardware. */
- struct work_struct qos_update_work;
+
+ /* Work for adjustment of the transmission power.
+ * This is scheduled when we determine that the actual TX output
+ * power doesn't match what we want. */
+ struct work_struct txpower_adjust_work;
};
/* In-memory representation of a cached microcode file. */
@@ -908,6 +797,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
return (wl->operating && wl->if_type == type);
}
+/**
+ * b43_current_band - Returns the currently used band.
+ * Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ.
+ */
+static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
+{
+ return wl->hw->conf.channel->band;
+}
+
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
{
return ssb_read16(dev->dev, offset);
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 29851bc1101..06a01da8016 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -443,76 +443,6 @@ out_unlock:
return count;
}
-static ssize_t txpower_g_read_file(struct b43_wldev *dev,
- char *buf, size_t bufsize)
-{
- ssize_t count = 0;
-
- if (dev->phy.type != B43_PHYTYPE_G) {
- fappend("Device is not a G-PHY\n");
- goto out;
- }
- fappend("Control: %s\n", dev->phy.manual_txpower_control ?
- "MANUAL" : "AUTOMATIC");
- fappend("Baseband attenuation: %u\n", dev->phy.bbatt.att);
- fappend("Radio attenuation: %u\n", dev->phy.rfatt.att);
- fappend("TX Mixer Gain: %s\n",
- (dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF");
- fappend("PA Gain 2dB: %s\n",
- (dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF");
- fappend("PA Gain 3dB: %s\n",
- (dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF");
- fappend("\n\n");
- fappend("You can write to this file:\n");
- fappend("Writing \"auto\" enables automatic txpower control.\n");
- fappend
- ("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" "
- "enables manual txpower control.\n");
- fappend("Example: 5 4 0 0 1\n");
- fappend("Enables manual control with Baseband attenuation 5, "
- "Radio attenuation 4, No TX Mixer Gain, "
- "No PA Gain 2dB, With PA Gain 3dB.\n");
-out:
- return count;
-}
-
-static int txpower_g_write_file(struct b43_wldev *dev,
- const char *buf, size_t count)
-{
- if (dev->phy.type != B43_PHYTYPE_G)
- return -ENODEV;
- if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) {
- /* Automatic control */
- dev->phy.manual_txpower_control = 0;
- b43_phy_xmitpower(dev);
- } else {
- int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0;
- /* Manual control */
- if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt,
- &txmix, &pa2db, &pa3db) != 5)
- return -EINVAL;
- b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
- dev->phy.manual_txpower_control = 1;
- dev->phy.bbatt.att = bbatt;
- dev->phy.rfatt.att = rfatt;
- dev->phy.tx_control = 0;
- if (txmix)
- dev->phy.tx_control |= B43_TXCTL_TXMIX;
- if (pa2db)
- dev->phy.tx_control |= B43_TXCTL_PA2DB;
- if (pa3db)
- dev->phy.tx_control |= B43_TXCTL_PA3DB;
- b43_phy_lock(dev);
- b43_radio_lock(dev);
- b43_set_txpower_g(dev, &dev->phy.bbatt,
- &dev->phy.rfatt, dev->phy.tx_control);
- b43_radio_unlock(dev);
- b43_phy_unlock(dev);
- }
-
- return 0;
-}
-
/* wl->irq_lock is locked */
static int restart_write_file(struct b43_wldev *dev,
const char *buf, size_t count)
@@ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
err = -ENODEV;
goto out;
}
- lo = phy->lo_control;
+ lo = phy->g->lo_control;
fappend("-- Local Oscillator calibration data --\n\n");
fappend("HW-power-control enabled: %d\n",
dev->phy.hardware_power_control);
@@ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
list_for_each_entry(cal, &lo->calib_list, list) {
bool active;
- active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
- b43_compare_rfatt(&cal->rfatt, &phy->rfatt));
+ active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
+ b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
"(expires in %lu sec)%s\n",
cal->bbatt.att,
@@ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
-B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);
B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
@@ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
ADD_FILE(mmio32write, 0200);
ADD_FILE(tsf, 0600);
ADD_FILE(txstat, 0400);
- ADD_FILE(txpower_g, 0600);
ADD_FILE(restart, 0200);
ADD_FILE(loctls, 0400);
@@ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
debugfs_remove(e->file_mmio32write.dentry);
debugfs_remove(e->file_tsf.dentry);
debugfs_remove(e->file_txstat.dentry);
- debugfs_remove(e->file_txpower_g.dentry);
debugfs_remove(e->file_restart.dentry);
debugfs_remove(e->file_loctls.dentry);
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 9c854d6aae3..6a18a147046 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -29,7 +29,7 @@
#include "b43.h"
#include "lo.h"
-#include "phy.h"
+#include "phy_g.h"
#include "main.h"
#include <linux/delay.h>
@@ -174,7 +174,8 @@ static u16 lo_txctl_register_table(struct b43_wldev *dev,
static void lo_measure_txctl_values(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
u16 reg, mask;
u16 trsw_rx, pga;
u16 radio_pctl_reg;
@@ -195,7 +196,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
int lb_gain; /* Loopback gain (in dB) */
trsw_rx = 0;
- lb_gain = phy->max_lb_gain / 2;
+ lb_gain = gphy->max_lb_gain / 2;
if (lb_gain > 10) {
radio_pctl_reg = 0;
pga = abs(10 - lb_gain) / 6;
@@ -226,7 +227,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
}
b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
& 0xFFF0) | radio_pctl_reg);
- b43_phy_set_baseband_attenuation(dev, 2);
+ b43_gphy_set_baseband_attenuation(dev, 2);
reg = lo_txctl_register_table(dev, &mask, NULL);
mask = ~mask;
@@ -277,7 +278,8 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
static void lo_read_power_vector(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
int i;
u64 tmp;
u64 power_vector = 0;
@@ -298,6 +300,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
s16 max_rx_gain, int use_trsw_rx)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
u16 tmp;
if (max_rx_gain < 0)
@@ -308,7 +311,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
int trsw_rx_gain;
if (use_trsw_rx) {
- trsw_rx_gain = phy->trsw_rx_gain / 2;
+ trsw_rx_gain = gphy->trsw_rx_gain / 2;
if (max_rx_gain >= trsw_rx_gain) {
trsw_rx_gain = max_rx_gain - trsw_rx_gain;
trsw_rx = 0x20;
@@ -316,38 +319,38 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
} else
trsw_rx_gain = max_rx_gain;
if (trsw_rx_gain < 9) {
- phy->lna_lod_gain = 0;
+ gphy->lna_lod_gain = 0;
} else {
- phy->lna_lod_gain = 1;
+ gphy->lna_lod_gain = 1;
trsw_rx_gain -= 8;
}
trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D);
- phy->pga_gain = trsw_rx_gain / 3;
- if (phy->pga_gain >= 5) {
- phy->pga_gain -= 5;
- phy->lna_gain = 2;
+ gphy->pga_gain = trsw_rx_gain / 3;
+ if (gphy->pga_gain >= 5) {
+ gphy->pga_gain -= 5;
+ gphy->lna_gain = 2;
} else
- phy->lna_gain = 0;
+ gphy->lna_gain = 0;
} else {
- phy->lna_gain = 0;
- phy->trsw_rx_gain = 0x20;
+ gphy->lna_gain = 0;
+ gphy->trsw_rx_gain = 0x20;
if (max_rx_gain >= 0x14) {
- phy->lna_lod_gain = 1;
- phy->pga_gain = 2;
+ gphy->lna_lod_gain = 1;
+ gphy->pga_gain = 2;
} else if (max_rx_gain >= 0x12) {
- phy->lna_lod_gain = 1;
- phy->pga_gain = 1;
+ gphy->lna_lod_gain = 1;
+ gphy->pga_gain = 1;
} else if (max_rx_gain >= 0xF) {
- phy->lna_lod_gain = 1;
- phy->pga_gain = 0;
+ gphy->lna_lod_gain = 1;
+ gphy->pga_gain = 0;
} else {
- phy->lna_lod_gain = 0;
- phy->pga_gain = 0;
+ gphy->lna_lod_gain = 0;
+ gphy->pga_gain = 0;
}
}
tmp = b43_radio_read16(dev, 0x7A);
- if (phy->lna_lod_gain == 0)
+ if (gphy->lna_lod_gain == 0)
tmp &= ~0x0008;
else
tmp |= 0x0008;
@@ -392,10 +395,11 @@ static void lo_measure_setup(struct b43_wldev *dev,
{
struct ssb_sprom *sprom = &dev->dev->bus->sprom;
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
u16 tmp;
- if (b43_has_hardware_pctl(phy)) {
+ if (b43_has_hardware_pctl(dev)) {
sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01));
sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL);
@@ -496,7 +500,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
if (phy->rev >= 2)
b43_dummy_transmission(dev);
- b43_radio_selectchannel(dev, 6, 0);
+ b43_gphy_channel_switch(dev, 6, 0);
b43_radio_read16(dev, 0x51); /* dummy read */
if (phy->type == B43_PHYTYPE_G)
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0);
@@ -520,18 +524,19 @@ static void lo_measure_restore(struct b43_wldev *dev,
struct lo_g_saved_values *sav)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
u16 tmp;
if (phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
- tmp = (phy->pga_gain << 8);
+ tmp = (gphy->pga_gain << 8);
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0);
udelay(5);
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2);
udelay(2);
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3);
} else {
- tmp = (phy->pga_gain | 0xEFA0);
+ tmp = (gphy->pga_gain | 0xEFA0);
b43_phy_write(dev, B43_PHY_PGACTL, tmp);
}
if (phy->type == B43_PHYTYPE_G) {
@@ -572,7 +577,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E);
b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0);
}
- if (b43_has_hardware_pctl(phy)) {
+ if (b43_has_hardware_pctl(dev)) {
tmp = (sav->phy_lo_mask & 0xBFFF);
b43_phy_write(dev, B43_PHY_LO_MASK, tmp);
b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01);
@@ -580,7 +585,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14);
b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
}
- b43_radio_selectchannel(dev, sav->old_channel, 1);
+ b43_gphy_channel_switch(dev, sav->old_channel, 1);
}
struct b43_lo_g_statemachine {
@@ -597,6 +602,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
struct b43_lo_g_statemachine *d)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
struct b43_loctl test_loctl;
struct b43_loctl orig_loctl;
struct b43_loctl prev_loctl = {
@@ -646,9 +652,9 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
test_loctl.q != prev_loctl.q) &&
(abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) {
b43_lo_write(dev, &test_loctl);
- feedth = lo_measure_feedthrough(dev, phy->lna_gain,
- phy->pga_gain,
- phy->trsw_rx_gain);
+ feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+ gphy->pga_gain,
+ gphy->trsw_rx_gain);
if (feedth < d->lowest_feedth) {
memcpy(probe_loctl, &test_loctl,
sizeof(struct b43_loctl));
@@ -677,6 +683,7 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
int *max_rx_gain)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
struct b43_lo_g_statemachine d;
u16 feedth;
int found_lower;
@@ -693,17 +700,17 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
max_repeat = 4;
do {
b43_lo_write(dev, &d.min_loctl);
- feedth = lo_measure_feedthrough(dev, phy->lna_gain,
- phy->pga_gain,
- phy->trsw_rx_gain);
+ feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+ gphy->pga_gain,
+ gphy->trsw_rx_gain);
if (feedth < 0x258) {
if (feedth >= 0x12C)
*max_rx_gain += 6;
else
*max_rx_gain += 3;
- feedth = lo_measure_feedthrough(dev, phy->lna_gain,
- phy->pga_gain,
- phy->trsw_rx_gain);
+ feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+ gphy->pga_gain,
+ gphy->trsw_rx_gain);
}
d.lowest_feedth = feedth;
@@ -752,6 +759,7 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
const struct b43_rfatt *rfatt)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
struct b43_loctl loctl = {
.i = 0,
.q = 0,
@@ -782,11 +790,11 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
if (rfatt->with_padmix)
max_rx_gain -= pad_mix_gain;
if (has_loopback_gain(phy))
- max_rx_gain += phy->max_lb_gain;
+ max_rx_gain += gphy->max_lb_gain;
lo_measure_gain_values(dev, max_rx_gain,
has_loopback_gain(phy));
- b43_phy_set_baseband_attenuation(dev, bbatt->att);
+ b43_gphy_set_baseband_attenuation(dev, bbatt->att);
lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
lo_measure_restore(dev, &saved_regs);
@@ -820,7 +828,7 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
const struct b43_bbatt *bbatt,
const struct b43_rfatt *rfatt)
{
- struct b43_txpower_lo_control *lo = dev->phy.lo_control;
+ struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
struct b43_lo_calib *c;
c = b43_find_lo_calib(lo, bbatt, rfatt);
@@ -839,7 +847,8 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
int i;
int rf_offset, bb_offset;
const struct b43_rfatt *rfatt;
@@ -917,14 +926,14 @@ static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf)
void b43_lo_g_adjust(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
struct b43_lo_calib *cal;
struct b43_rfatt rf;
- memcpy(&rf, &phy->rfatt, sizeof(rf));
+ memcpy(&rf, &gphy->rfatt, sizeof(rf));
b43_lo_fixup_rfatt(&rf);
- cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf);
+ cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf);
if (!cal)
return;
b43_lo_write(dev, &cal->ctl);
@@ -952,7 +961,8 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev,
void b43_lo_g_maintanance_work(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
unsigned long now;
unsigned long expire;
struct b43_lo_calib *cal, *tmp;
@@ -962,7 +972,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
if (!lo)
return;
now = jiffies;
- hwpctl = b43_has_hardware_pctl(phy);
+ hwpctl = b43_has_hardware_pctl(dev);
if (hwpctl) {
/* Read the power vector and update it, if needed. */
@@ -983,8 +993,8 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
if (!time_before(cal->calib_time, expire))
continue;
/* This item expired. */
- if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
- b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) {
+ if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) &&
+ b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) {
B43_WARN_ON(current_item_expired);
current_item_expired = 1;
}
@@ -1002,7 +1012,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
/* Recalibrate currently used LO setting. */
if (b43_debug(dev, B43_DBG_LO))
b43dbg(dev->wl, "LO: Recalibrating current LO setting\n");
- cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt);
+ cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt);
if (cal) {
list_add(&cal->list, &lo->calib_list);
b43_lo_write(dev, &cal->ctl);
@@ -1013,7 +1023,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
void b43_lo_g_cleanup(struct b43_wldev *dev)
{
- struct b43_txpower_lo_control *lo = dev->phy.lo_control;
+ struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
struct b43_lo_calib *cal, *tmp;
if (!lo)
@@ -1027,9 +1037,7 @@ void b43_lo_g_cleanup(struct b43_wldev *dev)
/* LO Initialization */
void b43_lo_g_init(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
-
- if (b43_has_hardware_pctl(phy)) {
+ if (b43_has_hardware_pctl(dev)) {
lo_read_power_vector(dev);
b43_gphy_dc_lt_init(dev, 1);
}
diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h
index 1da321cabc1..3b27e20eff8 100644
--- a/drivers/net/wireless/b43/lo.h
+++ b/drivers/net/wireless/b43/lo.h
@@ -1,7 +1,9 @@
#ifndef B43_LO_H_
#define B43_LO_H_
-#include "phy.h"
+/* G-PHY Local Oscillator */
+
+#include "phy_g.h"
struct b43_wldev;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 7205a936ec7..14c44df584d 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -44,8 +44,9 @@
#include "b43.h"
#include "main.h"
#include "debugfs.h"
-#include "phy.h"
-#include "nphy.h"
+#include "phy_common.h"
+#include "phy_g.h"
+#include "phy_n.h"
#include "dma.h"
#include "pio.h"
#include "sysfs.h"
@@ -814,7 +815,7 @@ void b43_dummy_transmission(struct b43_wldev *dev)
break;
udelay(10);
}
- for (i = 0x00; i < 0x0A; i++) {
+ for (i = 0x00; i < 0x19; i++) {
value = b43_read16(dev, 0x0690);
if (!(value & 0x0100))
break;
@@ -1051,23 +1052,6 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
}
-/* Turn the Analog ON/OFF */
-static void b43_switch_analog(struct b43_wldev *dev, int on)
-{
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- case B43_PHYTYPE_G:
- b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
- break;
- case B43_PHYTYPE_N:
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
- on ? 0 : 0x7FFF);
- break;
- default:
- B43_WARN_ON(1);
- }
-}
-
void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
{
u32 tmslow;
@@ -1090,8 +1074,12 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
msleep(1);
- /* Turn Analog ON */
- b43_switch_analog(dev, 1);
+ /* Turn Analog ON, but only if we already know the PHY-type.
+ * This protects against very early setup where we don't know the
+ * PHY-type, yet. wireless_core_reset will be called once again later,
+ * when we know the PHY-type. */
+ if (dev->phy.ops)
+ dev->phy.ops->switch_analog(dev, 1);
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
@@ -1174,6 +1162,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
{
/* Top half of Link Quality calculation. */
+ if (dev->phy.type != B43_PHYTYPE_G)
+ return;
if (dev->noisecalc.calculation_running)
return;
dev->noisecalc.calculation_running = 1;
@@ -1184,7 +1174,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
static void handle_irq_noise(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *phy = dev->phy.g;
u16 tmp;
u8 noise[4];
u8 i, j;
@@ -1192,6 +1182,9 @@ static void handle_irq_noise(struct b43_wldev *dev)
/* Bottom half of Link Quality calculation. */
+ if (dev->phy.type != B43_PHYTYPE_G)
+ return;
+
/* Possible race condition: It might be possible that the user
* changed to a different channel in the meantime since we
* started the calculation. We ignore that fact, since it's
@@ -1251,13 +1244,13 @@ generate_new:
static void handle_irq_tbtt_indication(struct b43_wldev *dev)
{
- if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
+ if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
///TODO: PS TBTT
} else {
if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
b43_power_saving_ctl_bits(dev, 0);
}
- if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+ if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
dev->dfq_valid = 1;
}
@@ -1606,8 +1599,8 @@ static void handle_irq_beacon(struct b43_wldev *dev)
struct b43_wl *wl = dev->wl;
u32 cmd, beacon0_valid, beacon1_valid;
- if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) &&
- !b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
+ if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
+ !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
return;
/* This is the bottom half of the asynchronous beacon update. */
@@ -2575,10 +2568,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
ctl &= ~B43_MACCTL_BEACPROMISC;
ctl |= B43_MACCTL_INFRA;
- if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
- b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
+ if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
ctl |= B43_MACCTL_AP;
- else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
+ else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
ctl &= ~B43_MACCTL_INFRA;
if (wl->filter_flags & FIF_CONTROL)
@@ -2688,9 +2681,8 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
/* This is the opposite of b43_chip_init() */
static void b43_chip_exit(struct b43_wldev *dev)
{
- b43_radio_turn_off(dev, 1);
+ b43_phy_exit(dev);
b43_gpio_cleanup(dev);
- b43_lo_g_cleanup(dev);
/* firmware is released later */
}
@@ -2700,7 +2692,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
static int b43_chip_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- int err, tmp;
+ int err;
u32 value32, macctl;
u16 value16;
@@ -2725,19 +2717,20 @@ static int b43_chip_init(struct b43_wldev *dev)
err = b43_upload_initvals(dev);
if (err)
goto err_gpio_clean;
- b43_radio_turn_on(dev);
- b43_write16(dev, 0x03E6, 0x0000);
+ /* Turn the Analog on and initialize the PHY. */
+ phy->ops->switch_analog(dev, 1);
err = b43_phy_init(dev);
if (err)
- goto err_radio_off;
+ goto err_gpio_clean;
- /* Select initial Interference Mitigation. */
- tmp = phy->interfmode;
- phy->interfmode = B43_INTERFMODE_NONE;
- b43_radio_set_interference_mitigation(dev, tmp);
+ /* Disable Interference Mitigation. */
+ if (phy->ops->interf_mitigation)
+ phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
- b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+ /* Select the antennae */
+ if (phy->ops->set_rx_antenna)
+ phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
if (phy->type == B43_PHYTYPE_B) {
@@ -2790,8 +2783,6 @@ static int b43_chip_init(struct b43_wldev *dev)
out:
return err;
-err_radio_off:
- b43_radio_turn_off(dev, 1);
err_gpio_clean:
b43_gpio_cleanup(dev);
return err;
@@ -2799,25 +2790,13 @@ err_gpio_clean:
static void b43_periodic_every60sec(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+ const struct b43_phy_operations *ops = dev->phy.ops;
- if (phy->type != B43_PHYTYPE_G)
- return;
- if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
- b43_mac_suspend(dev);
- b43_calc_nrssi_slope(dev);
- if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
- u8 old_chan = phy->channel;
-
- /* VCO Calibration */
- if (old_chan >= 8)
- b43_radio_selectchannel(dev, 1, 0);
- else
- b43_radio_selectchannel(dev, 13, 0);
- b43_radio_selectchannel(dev, old_chan, 0);
- }
- b43_mac_enable(dev);
- }
+ if (ops->pwork_60sec)
+ ops->pwork_60sec(dev);
+
+ /* Force check the TX power emission now. */
+ b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME);
}
static void b43_periodic_every30sec(struct b43_wldev *dev)
@@ -2845,32 +2824,8 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
}
}
- if (phy->type == B43_PHYTYPE_G) {
- //TODO: update_aci_moving_average
- if (phy->aci_enable && phy->aci_wlan_automatic) {
- b43_mac_suspend(dev);
- if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) {
- if (0 /*TODO: bunch of conditions */ ) {
- b43_radio_set_interference_mitigation
- (dev, B43_INTERFMODE_MANUALWLAN);
- }
- } else if (1 /*TODO*/) {
- /*
- if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) {
- b43_radio_set_interference_mitigation(dev,
- B43_INTERFMODE_NONE);
- }
- */
- }
- b43_mac_enable(dev);
- } else if (phy->interfmode == B43_INTERFMODE_NONWLAN &&
- phy->rev == 1) {
- //TODO: implement rev1 workaround
- }
- }
- b43_phy_xmitpower(dev); //FIXME: unless scanning?
- b43_lo_g_maintanance_work(dev);
- //TODO for APHY (temperature?)
+ if (phy->ops->pwork_15sec)
+ phy->ops->pwork_15sec(dev);
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
wmb();
@@ -3104,36 +3059,31 @@ static void b43_qos_params_upload(struct b43_wldev *dev,
}
}
-/* Update the QOS parameters in hardware. */
-static void b43_qos_update(struct b43_wldev *dev)
+/* Mapping of mac80211 queue numbers to b43 QoS SHM offsets. */
+static const u16 b43_qos_shm_offsets[] = {
+ /* [mac80211-queue-nr] = SHM_OFFSET, */
+ [0] = B43_QOS_VOICE,
+ [1] = B43_QOS_VIDEO,
+ [2] = B43_QOS_BESTEFFORT,
+ [3] = B43_QOS_BACKGROUND,
+};
+
+/* Update all QOS parameters in hardware. */
+static void b43_qos_upload_all(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
struct b43_qos_params *params;
- unsigned long flags;
unsigned int i;
- /* Mapping of mac80211 queues to b43 SHM offsets. */
- static const u16 qos_shm_offsets[] = {
- [0] = B43_QOS_VOICE,
- [1] = B43_QOS_VIDEO,
- [2] = B43_QOS_BESTEFFORT,
- [3] = B43_QOS_BACKGROUND,
- };
- BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
+ BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+ ARRAY_SIZE(wl->qos_params));
b43_mac_suspend(dev);
- spin_lock_irqsave(&wl->irq_lock, flags);
-
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
params = &(wl->qos_params[i]);
- if (params->need_hw_update) {
- b43_qos_params_upload(dev, &(params->p),
- qos_shm_offsets[i]);
- params->need_hw_update = 0;
- }
+ b43_qos_params_upload(dev, &(params->p),
+ b43_qos_shm_offsets[i]);
}
-
- spin_unlock_irqrestore(&wl->irq_lock, flags);
b43_mac_enable(dev);
}
@@ -3142,25 +3092,50 @@ static void b43_qos_clear(struct b43_wl *wl)
struct b43_qos_params *params;
unsigned int i;
+ /* Initialize QoS parameters to sane defaults. */
+
+ BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+ ARRAY_SIZE(wl->qos_params));
+
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
params = &(wl->qos_params[i]);
- memset(&(params->p), 0, sizeof(params->p));
- params->p.aifs = -1;
- params->need_hw_update = 1;
+ switch (b43_qos_shm_offsets[i]) {
+ case B43_QOS_VOICE:
+ params->p.txop = 0;
+ params->p.aifs = 2;
+ params->p.cw_min = 0x0001;
+ params->p.cw_max = 0x0001;
+ break;
+ case B43_QOS_VIDEO:
+ params->p.txop = 0;
+ params->p.aifs = 2;
+ params->p.cw_min = 0x0001;
+ params->p.cw_max = 0x0001;
+ break;
+ case B43_QOS_BESTEFFORT:
+ params->p.txop = 0;
+ params->p.aifs = 3;
+ params->p.cw_min = 0x0001;
+ params->p.cw_max = 0x03FF;
+ break;
+ case B43_QOS_BACKGROUND:
+ params->p.txop = 0;
+ params->p.aifs = 7;
+ params->p.cw_min = 0x0001;
+ params->p.cw_max = 0x03FF;
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
}
}
/* Initialize the core's QOS capabilities */
static void b43_qos_init(struct b43_wldev *dev)
{
- struct b43_wl *wl = dev->wl;
- unsigned int i;
-
/* Upload the current QOS parameters. */
- for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
- wl->qos_params[i].need_hw_update = 1;
- b43_qos_update(dev);
+ b43_qos_upload_all(dev);
/* Enable QOS support. */
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
@@ -3169,25 +3144,13 @@ static void b43_qos_init(struct b43_wldev *dev)
| B43_MMIO_IFSCTL_USE_EDCF);
}
-static void b43_qos_update_work(struct work_struct *work)
-{
- struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
- struct b43_wldev *dev;
-
- mutex_lock(&wl->mutex);
- dev = wl->current_dev;
- if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
- b43_qos_update(dev);
- mutex_unlock(&wl->mutex);
-}
-
static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
const struct ieee80211_tx_queue_params *params)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- unsigned long flags;
+ struct b43_wldev *dev;
unsigned int queue = (unsigned int)_queue;
- struct b43_qos_params *p;
+ int err = -ENODEV;
if (queue >= ARRAY_SIZE(wl->qos_params)) {
/* Queue not available or don't support setting
@@ -3195,16 +3158,25 @@ static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
* confuse mac80211. */
return 0;
}
+ BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+ ARRAY_SIZE(wl->qos_params));
- spin_lock_irqsave(&wl->irq_lock, flags);
- p = &(wl->qos_params[queue]);
- memcpy(&(p->p), params, sizeof(p->p));
- p->need_hw_update = 1;
- spin_unlock_irqrestore(&wl->irq_lock, flags);
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED)))
+ goto out_unlock;
- queue_work(hw->workqueue, &wl->qos_update_work);
+ memcpy(&(wl->qos_params[queue].p), params, sizeof(*params));
+ b43_mac_suspend(dev);
+ b43_qos_params_upload(dev, &(wl->qos_params[queue].p),
+ b43_qos_shm_offsets[queue]);
+ b43_mac_enable(dev);
+ err = 0;
- return 0;
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
}
static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
@@ -3401,7 +3373,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
if (conf->channel->hw_value != phy->channel)
- b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ b43_switch_channel(dev, conf->channel->hw_value);
/* Enable/Disable ShortSlot timing. */
if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
@@ -3417,26 +3389,30 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
- if (conf->power_level != phy->power_level) {
- phy->power_level = conf->power_level;
- b43_phy_xmitpower(dev);
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ if (conf->power_level != phy->desired_txpower) {
+ phy->desired_txpower = conf->power_level;
+ b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
+ B43_TXPWR_IGNORE_TSSI);
}
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
}
/* Antennas for RX and management frame TX. */
antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
b43_mgmtframe_txantenna(dev, antenna);
antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
- b43_set_rx_antenna(dev, antenna);
+ if (phy->ops->set_rx_antenna)
+ phy->ops->set_rx_antenna(dev, antenna);
/* Update templates for AP/mesh mode. */
- if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
- b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
+ if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
b43_set_beacon_int(dev, conf->beacon_int);
if (!!conf->radio_enabled != phy->radio_on) {
if (conf->radio_enabled) {
- b43_radio_turn_on(dev);
+ b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
b43info(dev->wl, "Radio turned on by software\n");
if (!dev->radio_hw_enable) {
b43info(dev->wl, "The hardware RF-kill button "
@@ -3444,7 +3420,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
"Press the button to turn it on.\n");
}
} else {
- b43_radio_turn_off(dev, 0);
+ b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
b43info(dev->wl, "Radio turned off by software\n");
}
}
@@ -3619,14 +3595,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
else
memset(wl->bssid, 0, ETH_ALEN);
if (b43_status(dev) >= B43_STAT_INITIALIZED) {
- if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
- b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) {
+ if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
B43_WARN_ON(vif->type != wl->if_type);
if (conf->changed & IEEE80211_IFCC_SSID)
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
- } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
+ } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
}
@@ -3818,48 +3794,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
static void setup_struct_phy_for_init(struct b43_wldev *dev,
struct b43_phy *phy)
{
- struct b43_txpower_lo_control *lo;
- int i;
-
- memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
- memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
-
- phy->aci_enable = 0;
- phy->aci_wlan_automatic = 0;
- phy->aci_hw_rssi = 0;
-
- phy->radio_off_context.valid = 0;
-
- lo = phy->lo_control;
- if (lo) {
- memset(lo, 0, sizeof(*(phy->lo_control)));
- lo->tx_bias = 0xFF;
- INIT_LIST_HEAD(&lo->calib_list);
- }
- phy->max_lb_gain = 0;
- phy->trsw_rx_gain = 0;
- phy->txpwr_offset = 0;
-
- /* NRSSI */
- phy->nrssislope = 0;
- for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
- phy->nrssi[i] = -1000;
- for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
- phy->nrssi_lt[i] = i;
-
- phy->lofcal = 0xFFFF;
- phy->initval = 0xFFFF;
-
- phy->interfmode = B43_INTERFMODE_NONE;
- phy->channel = 0xFF;
-
phy->hardware_power_control = !!modparam_hwpctl;
-
+ phy->next_txpwr_check_time = jiffies;
/* PHY TX errors counter. */
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
-
- /* OFDM-table address caching. */
- phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
}
static void setup_struct_wldev_for_init(struct b43_wldev *dev)
@@ -3965,7 +3903,7 @@ static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
pu_delay = 3700;
else
pu_delay = 1050;
- if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
+ if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
pu_delay = 500;
if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
pu_delay = max(pu_delay, (u16)2400);
@@ -3979,7 +3917,7 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
u16 pretbtt;
/* The time value is in microseconds. */
- if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) {
+ if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) {
pretbtt = 2;
} else {
if (dev->phy.type == B43_PHYTYPE_A)
@@ -3995,7 +3933,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
/* Locking: wl->mutex */
static void b43_wireless_core_exit(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
u32 macctl;
B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
@@ -4016,12 +3953,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
b43_dma_free(dev);
b43_pio_free(dev);
b43_chip_exit(dev);
- b43_radio_turn_off(dev, 1);
- b43_switch_analog(dev, 0);
- if (phy->dyn_tssi_tbl)
- kfree(phy->tssi2dbm);
- kfree(phy->lo_control);
- phy->lo_control = NULL;
+ dev->phy.ops->switch_analog(dev, 0);
if (dev->wl->current_beacon) {
dev_kfree_skb_any(dev->wl->current_beacon);
dev->wl->current_beacon = NULL;
@@ -4052,29 +3984,23 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_wireless_core_reset(dev, tmp);
}
- if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) {
- phy->lo_control =
- kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL);
- if (!phy->lo_control) {
- err = -ENOMEM;
- goto err_busdown;
- }
- }
+ /* Reset all data structures. */
setup_struct_wldev_for_init(dev);
-
- err = b43_phy_init_tssi2dbm_table(dev);
- if (err)
- goto err_kfree_lo_control;
+ phy->ops->prepare_structs(dev);
/* Enable IRQ routing to this device. */
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev);
- b43_phy_early_init(dev);
+ if (phy->ops->prepare_hardware) {
+ err = phy->ops->prepare_hardware(dev);
+ if (err)
+ goto err_busdown;
+ }
err = b43_chip_init(dev);
if (err)
- goto err_kfree_tssitbl;
+ goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
hf = b43_hf_read(dev);
@@ -4140,15 +4066,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
out:
return err;
- err_chip_exit:
+err_chip_exit:
b43_chip_exit(dev);
- err_kfree_tssitbl:
- if (phy->dyn_tssi_tbl)
- kfree(phy->tssi2dbm);
- err_kfree_lo_control:
- kfree(phy->lo_control);
- phy->lo_control = NULL;
- err_busdown:
+err_busdown:
ssb_bus_may_powerdown(bus);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
return err;
@@ -4164,11 +4084,11 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
- if (conf->type != IEEE80211_IF_TYPE_AP &&
- conf->type != IEEE80211_IF_TYPE_MESH_POINT &&
- conf->type != IEEE80211_IF_TYPE_STA &&
- conf->type != IEEE80211_IF_TYPE_WDS &&
- conf->type != IEEE80211_IF_TYPE_IBSS)
+ if (conf->type != NL80211_IFTYPE_AP &&
+ conf->type != NL80211_IFTYPE_MESH_POINT &&
+ conf->type != NL80211_IFTYPE_STATION &&
+ conf->type != NL80211_IFTYPE_WDS &&
+ conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
@@ -4283,7 +4203,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
struct b43_wldev *dev = wl->current_dev;
b43_rfkill_exit(dev);
- cancel_work_sync(&(wl->qos_update_work));
cancel_work_sync(&(wl->beacon_update_trigger));
mutex_lock(&wl->mutex);
@@ -4291,6 +4210,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
b43_wireless_core_stop(dev);
b43_wireless_core_exit(dev);
mutex_unlock(&wl->mutex);
+
+ cancel_work_sync(&(wl->txpower_adjust_work));
}
static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
@@ -4313,7 +4234,8 @@ out_unlock:
return err;
}
-static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
+static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, bool set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
@@ -4328,7 +4250,7 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
static void b43_op_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
- const u8 *addr)
+ struct ieee80211_sta *sta)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -4422,6 +4344,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
/* We release firmware that late to not be required to re-request
* is all the time when we reinit the core. */
b43_release_firmware(dev);
+ b43_phy_free(dev);
}
static int b43_wireless_core_attach(struct b43_wldev *dev)
@@ -4495,30 +4418,35 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
}
}
+ err = b43_phy_allocate(dev);
+ if (err)
+ goto err_powerdown;
+
dev->phy.gmode = have_2ghz_phy;
tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
err = b43_validate_chipaccess(dev);
if (err)
- goto err_powerdown;
+ goto err_phy_free;
err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
if (err)
- goto err_powerdown;
+ goto err_phy_free;
/* Now set some default "current_dev" */
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43_chip_reset);
- b43_radio_turn_off(dev, 1);
- b43_switch_analog(dev, 0);
+ dev->phy.ops->switch_analog(dev, 0);
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(bus);
out:
return err;
+err_phy_free:
+ b43_phy_free(dev);
err_powerdown:
ssb_bus_may_powerdown(bus);
return err;
@@ -4615,9 +4543,11 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
pdev = bus->host_pci;
if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) ||
+ IS_PDEV(pdev, BROADCOM, 0x4320, HP, 0x12f8) ||
IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) ||
- IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013))
+ IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) ||
+ IS_PDEV(pdev, BROADCOM, 0x4320, MOTOROLA, 0x7010))
bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
}
}
@@ -4650,7 +4580,15 @@ static int b43_wireless_init(struct ssb_device *dev)
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
hw->queues = b43_modparam_qos ? 4 : 1;
+ hw->max_altrates = 1;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
@@ -4667,8 +4605,8 @@ static int b43_wireless_init(struct ssb_device *dev)
spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
INIT_LIST_HEAD(&wl->devlist);
- INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
+ INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
ssb_set_devtypedata(dev, wl);
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index b8aa16307f7..3cfc30307a2 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -82,13 +82,13 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
tuple.TupleOffset = 0;
res = pcmcia_get_first_tuple(dev, &tuple);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_kfree_ssb;
res = pcmcia_get_tuple_data(dev, &tuple);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_kfree_ssb;
- res = pcmcia_parse_tuple(dev, &tuple, &parse);
- if (res != CS_SUCCESS)
+ res = pcmcia_parse_tuple(&tuple, &parse);
+ if (res != 0)
goto err_kfree_ssb;
dev->conf.ConfigBase = parse.config.base;
@@ -107,13 +107,13 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
win.Size = SSB_CORE_SIZE;
win.AccessSpeed = 250;
res = pcmcia_request_window(&dev, &win, &dev->win);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_kfree_ssb;
mem.CardOffset = 0;
mem.Page = 0;
res = pcmcia_map_mem_page(dev->win, &mem);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_disable;
dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
@@ -121,11 +121,11 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
dev->irq.Handler = NULL; /* The handler is registered later. */
dev->irq.Instance = NULL;
res = pcmcia_request_irq(dev, &dev->irq);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_disable;
res = pcmcia_request_configuration(dev, &dev->conf);
- if (res != CS_SUCCESS)
+ if (res != 0)
goto err_disable;
err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h
deleted file mode 100644
index 4aab1090352..00000000000
--- a/drivers/net/wireless/b43/phy.h
+++ /dev/null
@@ -1,340 +0,0 @@
-#ifndef B43_PHY_H_
-#define B43_PHY_H_
-
-#include <linux/types.h>
-
-struct b43_wldev;
-struct b43_phy;
-
-/*** PHY Registers ***/
-
-/* Routing */
-#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
-#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
-#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
-#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
-#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
-
-/* CCK (B-PHY) registers. */
-#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
-/* N-PHY registers. */
-#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
-/* N-PHY BMODE registers. */
-#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
-/* OFDM (A-PHY) registers. */
-#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
-/* Extended G-PHY registers. */
-#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
-
-/* OFDM (A) PHY Registers */
-#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
-#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
-#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
-#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
-#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
-#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
-#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
-#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
-#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
-#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
-#define B43_PHY_CRS0_EN 0x4000
-#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
-#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
-#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
-#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
-#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
-#define B43_PHY_LMS B43_PHY_OFDM(0x55)
-#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
-#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
-#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
-#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
-#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
-#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
-#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
-#define B43_PHY_OTABLENR_SHIFT 10
-#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
-#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
-#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
-#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
-#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
-#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
-#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
-#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
-#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
-#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
-#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
-#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
-#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
-#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
-#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
-#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
-#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
-#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
-#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
-#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
-#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
-#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
-#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
-#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
-#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
-#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
-#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
-#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
-#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
-
-/* CCK (B) PHY Registers */
-#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
-#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
-#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
-#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
-#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
-#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
-#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
-#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
-#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
-#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
-#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
-#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
-#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
-#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
-
-/* Extended G-PHY Registers */
-#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
-#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
-#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
-#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
-#define B43_PHY_GTABNR_SHIFT 10
-#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
-#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
-#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
-#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
-#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
-#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
-#define B43_PHY_RFOVERVAL_LNA 0x7000
-#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
-#define B43_PHY_RFOVERVAL_PGA 0x0F00
-#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
-#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
-#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
-#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
-#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
-#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
-#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
-#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
-
-/*** OFDM table numbers ***/
-#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
-#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
-#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
-#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
-#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
-#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
-#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
-#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
-#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
-#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
-#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
-#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
-#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
-#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
-#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
-#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
-#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
-#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
-#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
-#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
-#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
-#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
-#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
-#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
-#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
-#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
-#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
-#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
-#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
-#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
-#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
-#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
-
-u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
-void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
- u16 offset, u16 value);
-u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
-void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
- u16 offset, u32 value);
-
-/*** G-PHY table numbers */
-#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
-#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
-#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
-#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
-
-u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); //TODO implement
-void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); //TODO implement
-
-#define B43_DEFAULT_CHANNEL_A 36
-#define B43_DEFAULT_CHANNEL_BG 6
-
-enum {
- B43_ANTENNA0, /* Antenna 0 */
- B43_ANTENNA1, /* Antenna 0 */
- B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
- B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
- B43_ANTENNA2,
- B43_ANTENNA3 = 8,
-
- B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
- B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
-};
-
-enum {
- B43_INTERFMODE_NONE,
- B43_INTERFMODE_NONWLAN,
- B43_INTERFMODE_MANUALWLAN,
- B43_INTERFMODE_AUTOWLAN,
-};
-
-/* Masks for the different PHY versioning registers. */
-#define B43_PHYVER_ANALOG 0xF000
-#define B43_PHYVER_ANALOG_SHIFT 12
-#define B43_PHYVER_TYPE 0x0F00
-#define B43_PHYVER_TYPE_SHIFT 8
-#define B43_PHYVER_VERSION 0x00FF
-
-void b43_phy_lock(struct b43_wldev *dev);
-void b43_phy_unlock(struct b43_wldev *dev);
-
-
-/* Read a value from a PHY register */
-u16 b43_phy_read(struct b43_wldev *dev, u16 offset);
-/* Write a value to a PHY register */
-void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val);
-/* Mask a PHY register with a mask */
-void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
-/* OR a PHY register with a bitmap */
-void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
-/* Mask and OR a PHY register with a mask and bitmap */
-void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
-
-
-int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev);
-
-void b43_phy_early_init(struct b43_wldev *dev);
-int b43_phy_init(struct b43_wldev *dev);
-
-void b43_set_rx_antenna(struct b43_wldev *dev, int antenna);
-
-void b43_phy_xmitpower(struct b43_wldev *dev);
-
-/* Returns the boolean whether the board has HardwarePowerControl */
-bool b43_has_hardware_pctl(struct b43_phy *phy);
-/* Returns the boolean whether "TX Magnification" is enabled. */
-#define has_tx_magnification(phy) \
- (((phy)->rev >= 2) && \
- ((phy)->radio_ver == 0x2050) && \
- ((phy)->radio_rev == 8))
-/* Card uses the loopback gain stuff */
-#define has_loopback_gain(phy) \
- (((phy)->rev > 1) || ((phy)->gmode))
-
-/* Radio Attenuation (RF Attenuation) */
-struct b43_rfatt {
- u8 att; /* Attenuation value */
- bool with_padmix; /* Flag, PAD Mixer enabled. */
-};
-struct b43_rfatt_list {
- /* Attenuation values list */
- const struct b43_rfatt *list;
- u8 len;
- /* Minimum/Maximum attenuation values */
- u8 min_val;
- u8 max_val;
-};
-
-/* Returns true, if the values are the same. */
-static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
- const struct b43_rfatt *b)
-{
- return ((a->att == b->att) &&
- (a->with_padmix == b->with_padmix));
-}
-
-/* Baseband Attenuation */
-struct b43_bbatt {
- u8 att; /* Attenuation value */
-};
-struct b43_bbatt_list {
- /* Attenuation values list */
- const struct b43_bbatt *list;
- u8 len;
- /* Minimum/Maximum attenuation values */
- u8 min_val;
- u8 max_val;
-};
-
-/* Returns true, if the values are the same. */
-static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
- const struct b43_bbatt *b)
-{
- return (a->att == b->att);
-}
-
-/* tx_control bits. */
-#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
-#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
-#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
-
-/* Write BasebandAttenuation value to the device. */
-void b43_phy_set_baseband_attenuation(struct b43_wldev *dev,
- u16 baseband_attenuation);
-
-extern const u8 b43_radio_channel_codes_bg[];
-
-void b43_radio_lock(struct b43_wldev *dev);
-void b43_radio_unlock(struct b43_wldev *dev);
-
-
-/* Read a value from a 16bit radio register */
-u16 b43_radio_read16(struct b43_wldev *dev, u16 offset);
-/* Write a value to a 16bit radio register */
-void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val);
-/* Mask a 16bit radio register with a mask */
-void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
-/* OR a 16bit radio register with a bitmap */
-void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
-/* Mask and OR a PHY register with a mask and bitmap */
-void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
-
-
-u16 b43_radio_init2050(struct b43_wldev *dev);
-void b43_radio_init2060(struct b43_wldev *dev);
-
-void b43_radio_turn_on(struct b43_wldev *dev);
-void b43_radio_turn_off(struct b43_wldev *dev, bool force);
-
-int b43_radio_selectchannel(struct b43_wldev *dev, u8 channel,
- int synthetic_pu_workaround);
-
-u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel);
-u8 b43_radio_aci_scan(struct b43_wldev *dev);
-
-int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode);
-
-void b43_calc_nrssi_slope(struct b43_wldev *dev);
-void b43_calc_nrssi_threshold(struct b43_wldev *dev);
-s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset);
-void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val);
-void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val);
-void b43_nrssi_mem_update(struct b43_wldev *dev);
-
-void b43_radio_set_tx_iq(struct b43_wldev *dev);
-u16 b43_radio_calibrationvalue(struct b43_wldev *dev);
-
-void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
- int *_bbatt, int *_rfatt);
-
-void b43_set_txpower_g(struct b43_wldev *dev,
- const struct b43_bbatt *bbatt,
- const struct b43_rfatt *rfatt, u8 tx_control);
-
-#endif /* B43_PHY_H_ */
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
new file mode 100644
index 00000000000..0f1a84c9de6
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -0,0 +1,643 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11a PHY driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+ Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
+ Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "phy_a.h"
+#include "phy_common.h"
+#include "wa.h"
+#include "tables.h"
+#include "main.h"
+
+
+/* Get the freq, as it has to be written to the device. */
+static inline u16 channel2freq_a(u8 channel)
+{
+ B43_WARN_ON(channel > 200);
+
+ return (5000 + 5 * channel);
+}
+
+static inline u16 freq_r3A_value(u16 frequency)
+{
+ u16 value;
+
+ if (frequency < 5091)
+ value = 0x0040;
+ else if (frequency < 5321)
+ value = 0x0000;
+ else if (frequency < 5806)
+ value = 0x0080;
+ else
+ value = 0x0040;
+
+ return value;
+}
+
+#if 0
+/* This function converts a TSSI value to dBm in Q5.2 */
+static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_a *aphy = phy->a;
+ s8 dbm = 0;
+ s32 tmp;
+
+ tmp = (aphy->tgt_idle_tssi - aphy->cur_idle_tssi + tssi);
+ tmp += 0x80;
+ tmp = clamp_val(tmp, 0x00, 0xFF);
+ dbm = aphy->tssi2dbm[tmp];
+ //TODO: There's a FIXME on the specs
+
+ return dbm;
+}
+#endif
+
+void b43_radio_set_tx_iq(struct b43_wldev *dev)
+{
+ static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
+ static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
+ u16 tmp = b43_radio_read16(dev, 0x001E);
+ int i, j;
+
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 5; j++) {
+ if (tmp == (data_high[i] << 4 | data_low[j])) {
+ b43_phy_write(dev, 0x0069,
+ (i - j) << 8 | 0x00C0);
+ return;
+ }
+ }
+ }
+}
+
+static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
+{
+ u16 freq, r8, tmp;
+
+ freq = channel2freq_a(channel);
+
+ r8 = b43_radio_read16(dev, 0x0008);
+ b43_write16(dev, 0x03F0, freq);
+ b43_radio_write16(dev, 0x0008, r8);
+
+ //TODO: write max channel TX power? to Radio 0x2D
+ tmp = b43_radio_read16(dev, 0x002E);
+ tmp &= 0x0080;
+ //TODO: OR tmp with the Power out estimation for this channel?
+ b43_radio_write16(dev, 0x002E, tmp);
+
+ if (freq >= 4920 && freq <= 5500) {
+ /*
+ * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
+ * = (freq * 0.025862069
+ */
+ r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+ }
+ b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
+ b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
+ b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
+ b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022)
+ & 0x000F) | (r8 << 4));
+ b43_radio_write16(dev, 0x002A, (r8 << 4));
+ b43_radio_write16(dev, 0x002B, (r8 << 4));
+ b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008)
+ & 0x00F0) | (r8 << 4));
+ b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029)
+ & 0xFF0F) | 0x00B0);
+ b43_radio_write16(dev, 0x0035, 0x00AA);
+ b43_radio_write16(dev, 0x0036, 0x0085);
+ b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A)
+ & 0xFF20) |
+ freq_r3A_value(freq));
+ b43_radio_write16(dev, 0x003D,
+ b43_radio_read16(dev, 0x003D) & 0x00FF);
+ b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081)
+ & 0xFF7F) | 0x0080);
+ b43_radio_write16(dev, 0x0035,
+ b43_radio_read16(dev, 0x0035) & 0xFFEF);
+ b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035)
+ & 0xFFEF) | 0x0010);
+ b43_radio_set_tx_iq(dev);
+ //TODO: TSSI2dbm workaround
+//FIXME b43_phy_xmitpower(dev);
+}
+
+void b43_radio_init2060(struct b43_wldev *dev)
+{
+ b43_radio_write16(dev, 0x0004, 0x00C0);
+ b43_radio_write16(dev, 0x0005, 0x0008);
+ b43_radio_write16(dev, 0x0009, 0x0040);
+ b43_radio_write16(dev, 0x0005, 0x00AA);
+ b43_radio_write16(dev, 0x0032, 0x008F);
+ b43_radio_write16(dev, 0x0006, 0x008F);
+ b43_radio_write16(dev, 0x0034, 0x008F);
+ b43_radio_write16(dev, 0x002C, 0x0007);
+ b43_radio_write16(dev, 0x0082, 0x0080);
+ b43_radio_write16(dev, 0x0080, 0x0000);
+ b43_radio_write16(dev, 0x003F, 0x00DA);
+ b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
+ b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010);
+ b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
+ b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
+ msleep(1); /* delay 400usec */
+
+ b43_radio_write16(dev, 0x0081,
+ (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
+ msleep(1); /* delay 400usec */
+
+ b43_radio_write16(dev, 0x0005,
+ (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
+ b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010);
+ b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
+ b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040);
+ b43_radio_write16(dev, 0x0081,
+ (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
+ b43_radio_write16(dev, 0x0005,
+ (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
+ b43_phy_write(dev, 0x0063, 0xDDC6);
+ b43_phy_write(dev, 0x0069, 0x07BE);
+ b43_phy_write(dev, 0x006A, 0x0000);
+
+ aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev));
+
+ msleep(1);
+}
+
+static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
+{
+ int i;
+
+ if (dev->phy.rev < 3) {
+ if (enable)
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, 0xFFF8);
+ }
+ else
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
+ }
+ } else {
+ if (enable)
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, 0x0820);
+ else
+ for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
+ }
+}
+
+static void b43_phy_ww(struct b43_wldev *dev)
+{
+ u16 b, curr_s, best_s = 0xFFFF;
+ int i;
+
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000);
+ b43_phy_write(dev, B43_PHY_OFDM(0x82),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300);
+ b43_radio_write16(dev, 0x0009,
+ b43_radio_read16(dev, 0x0009) | 0x0080);
+ b43_radio_write16(dev, 0x0012,
+ (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002);
+ b43_wa_initgains(dev);
+ b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
+ b = b43_phy_read(dev, B43_PHY_PWRDOWN);
+ b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
+ b43_radio_write16(dev, 0x0004,
+ b43_radio_read16(dev, 0x0004) | 0x0004);
+ for (i = 0x10; i <= 0x20; i++) {
+ b43_radio_write16(dev, 0x0013, i);
+ curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
+ if (!curr_s) {
+ best_s = 0x0000;
+ break;
+ } else if (curr_s >= 0x0080)
+ curr_s = 0x0100 - curr_s;
+ if (curr_s < best_s)
+ best_s = curr_s;
+ }
+ b43_phy_write(dev, B43_PHY_PWRDOWN, b);
+ b43_radio_write16(dev, 0x0004,
+ b43_radio_read16(dev, 0x0004) & 0xFFFB);
+ b43_radio_write16(dev, 0x0013, best_s);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
+ b43_phy_write(dev, B43_PHY_OFDM(0xBB),
+ (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053);
+ b43_phy_write(dev, B43_PHY_OFDM61,
+ (b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120);
+ b43_phy_write(dev, B43_PHY_OFDM(0x13),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000);
+ b43_phy_write(dev, B43_PHY_OFDM(0x14),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
+ for (i = 0; i < 6; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
+ b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
+}
+
+static void hardware_pctl_init_aphy(struct b43_wldev *dev)
+{
+ //TODO
+}
+
+void b43_phy_inita(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ struct b43_phy *phy = &dev->phy;
+
+ /* This lowlevel A-PHY init is also called from G-PHY init.
+ * So we must not access phy->a, if called from G-PHY code.
+ */
+ B43_WARN_ON((phy->type != B43_PHYTYPE_A) &&
+ (phy->type != B43_PHYTYPE_G));
+
+ might_sleep();
+
+ if (phy->rev >= 6) {
+ if (phy->type == B43_PHYTYPE_A)
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000);
+ if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+ b43_phy_write(dev, B43_PHY_ENCORE,
+ b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010);
+ else
+ b43_phy_write(dev, B43_PHY_ENCORE,
+ b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010);
+ }
+
+ b43_wa_all(dev);
+
+ if (phy->type == B43_PHYTYPE_A) {
+ if (phy->gmode && (phy->rev < 3))
+ b43_phy_write(dev, 0x0034,
+ b43_phy_read(dev, 0x0034) | 0x0001);
+ b43_phy_rssiagc(dev, 0);
+
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
+
+ b43_radio_init2060(dev);
+
+ if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
+ ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
+ (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ ; //TODO: A PHY LO
+ }
+
+ if (phy->rev >= 3)
+ b43_phy_ww(dev);
+
+ hardware_pctl_init_aphy(dev);
+
+ //TODO: radar detection
+ }
+
+ if ((phy->type == B43_PHYTYPE_G) &&
+ (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ b43_phy_write(dev, B43_PHY_OFDM(0x6E),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x6E))
+ & 0xE000) | 0x3CF);
+ }
+}
+
+/* Initialise the TSSI->dBm lookup table */
+static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_a *aphy = phy->a;
+ s16 pab0, pab1, pab2;
+
+ pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
+ pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
+ pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
+
+ if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+ pab0 != -1 && pab1 != -1 && pab2 != -1) {
+ /* The pabX values are set in SPROM. Use them. */
+ if ((s8) dev->dev->bus->sprom.itssi_a != 0 &&
+ (s8) dev->dev->bus->sprom.itssi_a != -1)
+ aphy->tgt_idle_tssi =
+ (s8) (dev->dev->bus->sprom.itssi_a);
+ else
+ aphy->tgt_idle_tssi = 62;
+ aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
+ pab1, pab2);
+ if (!aphy->tssi2dbm)
+ return -ENOMEM;
+ } else {
+ /* pabX values not set in SPROM,
+ * but APHY needs a generated table. */
+ aphy->tssi2dbm = NULL;
+ b43err(dev->wl, "Could not generate tssi2dBm "
+ "table (wrong SPROM info)!\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int b43_aphy_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_a *aphy;
+ int err;
+
+ aphy = kzalloc(sizeof(*aphy), GFP_KERNEL);
+ if (!aphy)
+ return -ENOMEM;
+ dev->phy.a = aphy;
+
+ err = b43_aphy_init_tssi2dbm_table(dev);
+ if (err)
+ goto err_free_aphy;
+
+ return 0;
+
+err_free_aphy:
+ kfree(aphy);
+ dev->phy.a = NULL;
+
+ return err;
+}
+
+static void b43_aphy_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_a *aphy = phy->a;
+ const void *tssi2dbm;
+ int tgt_idle_tssi;
+
+ /* tssi2dbm table is constant, so it is initialized at alloc time.
+ * Save a copy of the pointer. */
+ tssi2dbm = aphy->tssi2dbm;
+ tgt_idle_tssi = aphy->tgt_idle_tssi;
+
+ /* Zero out the whole PHY structure. */
+ memset(aphy, 0, sizeof(*aphy));
+
+ aphy->tssi2dbm = tssi2dbm;
+ aphy->tgt_idle_tssi = tgt_idle_tssi;
+
+ //TODO init struct b43_phy_a
+
+}
+
+static void b43_aphy_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_a *aphy = phy->a;
+
+ kfree(aphy->tssi2dbm);
+ aphy->tssi2dbm = NULL;
+
+ kfree(aphy);
+ dev->phy.a = NULL;
+}
+
+static int b43_aphy_op_init(struct b43_wldev *dev)
+{
+ b43_phy_inita(dev);
+
+ return 0;
+}
+
+static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
+{
+ /* OFDM registers are base-registers for the A-PHY. */
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
+ offset &= ~B43_PHYROUTE;
+ offset |= B43_PHYROUTE_BASE;
+ }
+
+#if B43_DEBUG
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
+ /* Ext-G registers are only available on G-PHYs */
+ b43err(dev->wl, "Invalid EXT-G PHY access at "
+ "0x%04X on A-PHY\n", offset);
+ dump_stack();
+ }
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
+ /* N-BMODE registers are only available on N-PHYs */
+ b43err(dev->wl, "Invalid N-BMODE PHY access at "
+ "0x%04X on A-PHY\n", offset);
+ dump_stack();
+ }
+#endif /* B43_DEBUG */
+
+ return offset;
+}
+
+static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
+{
+ reg = adjust_phyreg(dev, reg);
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ reg = adjust_phyreg(dev, reg);
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+ /* A-PHY needs 0x40 for read access */
+ reg |= 0x40;
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
+{
+ return (dev->phy.rev >= 5);
+}
+
+static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
+ enum rfkill_state state)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (state == RFKILL_STATE_UNBLOCKED) {
+ if (phy->radio_on)
+ return;
+ b43_radio_write16(dev, 0x0004, 0x00C0);
+ b43_radio_write16(dev, 0x0005, 0x0008);
+ b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) & 0xFFF7);
+ b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) & 0xFFF7);
+ b43_radio_init2060(dev);
+ } else {
+ b43_radio_write16(dev, 0x0004, 0x00FF);
+ b43_radio_write16(dev, 0x0005, 0x00FB);
+ b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008);
+ b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
+ }
+}
+
+static int b43_aphy_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ if (new_channel > 200)
+ return -EINVAL;
+ aphy_channel_switch(dev, new_channel);
+
+ return 0;
+}
+
+static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev)
+{
+ return 36; /* Default to channel 36 */
+}
+
+static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{//TODO
+ struct b43_phy *phy = &dev->phy;
+ u64 hf;
+ u16 tmp;
+ int autodiv = 0;
+
+ if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
+ autodiv = 1;
+
+ hf = b43_hf_read(dev);
+ hf &= ~B43_HF_ANTDIVHELP;
+ b43_hf_write(dev, hf);
+
+ tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
+ tmp &= ~B43_PHY_BBANDCFG_RXANT;
+ tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
+ << B43_PHY_BBANDCFG_RXANT_SHIFT;
+ b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
+
+ if (autodiv) {
+ tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
+ if (antenna == B43_ANTENNA_AUTO0)
+ tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
+ else
+ tmp |= B43_PHY_ANTDWELL_AUTODIV1;
+ b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
+ }
+ if (phy->rev < 3) {
+ tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
+ tmp = (tmp & 0xFF00) | 0x24;
+ b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
+ } else {
+ tmp = b43_phy_read(dev, B43_PHY_OFDM61);
+ tmp |= 0x10;
+ b43_phy_write(dev, B43_PHY_OFDM61, tmp);
+ if (phy->analog == 3) {
+ b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
+ 0x1D);
+ b43_phy_write(dev, B43_PHY_ADIVRELATED,
+ 8);
+ } else {
+ b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
+ 0x3A);
+ tmp =
+ b43_phy_read(dev,
+ B43_PHY_ADIVRELATED);
+ tmp = (tmp & 0xFF00) | 8;
+ b43_phy_write(dev, B43_PHY_ADIVRELATED,
+ tmp);
+ }
+ }
+
+ hf |= B43_HF_ANTDIVHELP;
+ b43_hf_write(dev, hf);
+}
+
+static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)
+{//TODO
+}
+
+static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev,
+ bool ignore_tssi)
+{//TODO
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev)
+{//TODO
+}
+
+static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
+{//TODO
+}
+
+const struct b43_phy_operations b43_phyops_a = {
+ .allocate = b43_aphy_op_allocate,
+ .free = b43_aphy_op_free,
+ .prepare_structs = b43_aphy_op_prepare_structs,
+ .init = b43_aphy_op_init,
+ .phy_read = b43_aphy_op_read,
+ .phy_write = b43_aphy_op_write,
+ .radio_read = b43_aphy_op_radio_read,
+ .radio_write = b43_aphy_op_radio_write,
+ .supports_hwpctl = b43_aphy_op_supports_hwpctl,
+ .software_rfkill = b43_aphy_op_software_rfkill,
+ .switch_analog = b43_phyop_switch_analog_generic,
+ .switch_channel = b43_aphy_op_switch_channel,
+ .get_default_chan = b43_aphy_op_get_default_chan,
+ .set_rx_antenna = b43_aphy_op_set_rx_antenna,
+ .recalc_txpower = b43_aphy_op_recalc_txpower,
+ .adjust_txpower = b43_aphy_op_adjust_txpower,
+ .pwork_15sec = b43_aphy_op_pwork_15sec,
+ .pwork_60sec = b43_aphy_op_pwork_60sec,
+};
diff --git a/drivers/net/wireless/b43/phy_a.h b/drivers/net/wireless/b43/phy_a.h
new file mode 100644
index 00000000000..5cfaab7b16e
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_a.h
@@ -0,0 +1,130 @@
+#ifndef LINUX_B43_PHY_A_H_
+#define LINUX_B43_PHY_A_H_
+
+#include "phy_common.h"
+
+
+/* OFDM (A) PHY Registers */
+#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
+#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
+#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
+#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
+#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
+#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
+#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
+#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
+#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
+#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
+#define B43_PHY_CRS0_EN 0x4000
+#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
+#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
+#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
+#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
+#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
+#define B43_PHY_LMS B43_PHY_OFDM(0x55)
+#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
+#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
+#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
+#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
+#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
+#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
+#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
+#define B43_PHY_OTABLENR_SHIFT 10
+#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
+#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
+#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
+#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
+#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
+#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
+#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
+#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
+#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
+#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
+#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
+#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
+#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
+#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
+#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
+#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
+#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
+#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
+#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
+#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
+#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
+#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
+#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
+#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
+#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
+#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
+#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
+#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
+#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
+
+/*** OFDM table numbers ***/
+#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
+#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
+#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
+#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
+#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
+#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
+#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
+#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
+#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
+#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
+#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
+#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
+#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
+#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
+#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
+#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
+#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
+#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
+#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
+#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
+#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
+#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
+#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
+#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
+#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
+#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
+#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
+#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
+#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
+#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
+#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
+#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
+
+u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
+ u16 offset, u16 value);
+u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
+ u16 offset, u32 value);
+
+
+struct b43_phy_a {
+ /* Pointer to the table used to convert a
+ * TSSI value to dBm-Q5.2 */
+ const s8 *tssi2dbm;
+ /* Target idle TSSI */
+ int tgt_idle_tssi;
+ /* Current idle TSSI */
+ int cur_idle_tssi;//FIXME value currently not set
+
+ /* A-PHY TX Power control value. */
+ u16 txpwr_offset;
+
+ //TODO lots of missing stuff
+};
+
+/**
+ * b43_phy_inita - Lowlevel A-PHY init routine.
+ * This is _only_ used by the G-PHY code.
+ */
+void b43_phy_inita(struct b43_wldev *dev);
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_a;
+
+#endif /* LINUX_B43_PHY_A_H_ */
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
new file mode 100644
index 00000000000..af37abccccb
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -0,0 +1,381 @@
+/*
+
+ Broadcom B43 wireless driver
+ Common PHY routines
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+ Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
+ Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "phy_common.h"
+#include "phy_g.h"
+#include "phy_a.h"
+#include "phy_n.h"
+#include "phy_lp.h"
+#include "b43.h"
+#include "main.h"
+
+
+int b43_phy_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &(dev->phy);
+ int err;
+
+ phy->ops = NULL;
+
+ switch (phy->type) {
+ case B43_PHYTYPE_A:
+ phy->ops = &b43_phyops_a;
+ break;
+ case B43_PHYTYPE_G:
+ phy->ops = &b43_phyops_g;
+ break;
+ case B43_PHYTYPE_N:
+#ifdef CONFIG_B43_NPHY
+ phy->ops = &b43_phyops_n;
+#endif
+ break;
+ case B43_PHYTYPE_LP:
+#ifdef CONFIG_B43_PHY_LP
+ phy->ops = &b43_phyops_lp;
+#endif
+ break;
+ }
+ if (B43_WARN_ON(!phy->ops))
+ return -ENODEV;
+
+ err = phy->ops->allocate(dev);
+ if (err)
+ phy->ops = NULL;
+
+ return err;
+}
+
+void b43_phy_free(struct b43_wldev *dev)
+{
+ dev->phy.ops->free(dev);
+ dev->phy.ops = NULL;
+}
+
+int b43_phy_init(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ const struct b43_phy_operations *ops = phy->ops;
+ int err;
+
+ phy->channel = ops->get_default_chan(dev);
+
+ ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
+ err = ops->init(dev);
+ if (err) {
+ b43err(dev->wl, "PHY init failed\n");
+ goto err_block_rf;
+ }
+ /* Make sure to switch hardware and firmware (SHM) to
+ * the default channel. */
+ err = b43_switch_channel(dev, ops->get_default_chan(dev));
+ if (err) {
+ b43err(dev->wl, "PHY init: Channel switch to default failed\n");
+ goto err_phy_exit;
+ }
+
+ return 0;
+
+err_phy_exit:
+ if (ops->exit)
+ ops->exit(dev);
+err_block_rf:
+ ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
+
+ return err;
+}
+
+void b43_phy_exit(struct b43_wldev *dev)
+{
+ const struct b43_phy_operations *ops = dev->phy.ops;
+
+ ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
+ if (ops->exit)
+ ops->exit(dev);
+}
+
+bool b43_has_hardware_pctl(struct b43_wldev *dev)
+{
+ if (!dev->phy.hardware_power_control)
+ return 0;
+ if (!dev->phy.ops->supports_hwpctl)
+ return 0;
+ return dev->phy.ops->supports_hwpctl(dev);
+}
+
+void b43_radio_lock(struct b43_wldev *dev)
+{
+ u32 macctl;
+
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
+ macctl |= B43_MACCTL_RADIOLOCK;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ /* Commit the write and wait for the device
+ * to exit any radio register access. */
+ b43_read32(dev, B43_MMIO_MACCTL);
+ udelay(10);
+}
+
+void b43_radio_unlock(struct b43_wldev *dev)
+{
+ u32 macctl;
+
+ /* Commit any write */
+ b43_read16(dev, B43_MMIO_PHY_VER);
+ /* unlock */
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
+ macctl &= ~B43_MACCTL_RADIOLOCK;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
+}
+
+void b43_phy_lock(struct b43_wldev *dev)
+{
+#if B43_DEBUG
+ B43_WARN_ON(dev->phy.phy_locked);
+ dev->phy.phy_locked = 1;
+#endif
+ B43_WARN_ON(dev->dev->id.revision < 3);
+
+ if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
+ b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+}
+
+void b43_phy_unlock(struct b43_wldev *dev)
+{
+#if B43_DEBUG
+ B43_WARN_ON(!dev->phy.phy_locked);
+ dev->phy.phy_locked = 0;
+#endif
+ B43_WARN_ON(dev->dev->id.revision < 3);
+
+ if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
+ b43_power_saving_ctl_bits(dev, 0);
+}
+
+u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ return dev->phy.ops->radio_read(dev, reg);
+}
+
+void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ dev->phy.ops->radio_write(dev, reg, value);
+}
+
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+ b43_radio_write16(dev, offset,
+ b43_radio_read16(dev, offset) & mask);
+}
+
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+ b43_radio_write16(dev, offset,
+ b43_radio_read16(dev, offset) | set);
+}
+
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+ b43_radio_write16(dev, offset,
+ (b43_radio_read16(dev, offset) & mask) | set);
+}
+
+u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
+{
+ return dev->phy.ops->phy_read(dev, reg);
+}
+
+void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ dev->phy.ops->phy_write(dev, reg, value);
+}
+
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+ b43_phy_write(dev, offset,
+ b43_phy_read(dev, offset) & mask);
+}
+
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+ b43_phy_write(dev, offset,
+ b43_phy_read(dev, offset) | set);
+}
+
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+ b43_phy_write(dev, offset,
+ (b43_phy_read(dev, offset) & mask) | set);
+}
+
+int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
+{
+ struct b43_phy *phy = &(dev->phy);
+ u16 channelcookie, savedcookie;
+ int err;
+
+ if (new_channel == B43_DEFAULT_CHANNEL)
+ new_channel = phy->ops->get_default_chan(dev);
+
+ /* First we set the channel radio code to prevent the
+ * firmware from sending ghost packets.
+ */
+ channelcookie = new_channel;
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ channelcookie |= 0x100;
+ //FIXME set 40Mhz flag if required
+ savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
+
+ /* Now try to switch the PHY hardware channel. */
+ err = phy->ops->switch_channel(dev, new_channel);
+ if (err)
+ goto err_restore_cookie;
+
+ dev->phy.channel = new_channel;
+ /* Wait for the radio to tune to the channel and stabilize. */
+ msleep(8);
+
+ return 0;
+
+err_restore_cookie:
+ b43_shm_write16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_CHAN, savedcookie);
+
+ return err;
+}
+
+void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (state == RFKILL_STATE_HARD_BLOCKED) {
+ /* We cannot hardware-block the device */
+ state = RFKILL_STATE_SOFT_BLOCKED;
+ }
+
+ phy->ops->software_rfkill(dev, state);
+ phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
+}
+
+/**
+ * b43_phy_txpower_adjust_work - TX power workqueue.
+ *
+ * Workqueue for updating the TX power parameters in hardware.
+ */
+void b43_phy_txpower_adjust_work(struct work_struct *work)
+{
+ struct b43_wl *wl = container_of(work, struct b43_wl,
+ txpower_adjust_work);
+ struct b43_wldev *dev;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+
+ if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
+ dev->phy.ops->adjust_txpower(dev);
+
+ mutex_unlock(&wl->mutex);
+}
+
+/* Called with wl->irq_lock locked */
+void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
+{
+ struct b43_phy *phy = &dev->phy;
+ unsigned long now = jiffies;
+ enum b43_txpwr_result result;
+
+ if (!(flags & B43_TXPWR_IGNORE_TIME)) {
+ /* Check if it's time for a TXpower check. */
+ if (time_before(now, phy->next_txpwr_check_time))
+ return; /* Not yet */
+ }
+ /* The next check will be needed in two seconds, or later. */
+ phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
+
+ if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
+ return; /* No software txpower adjustment needed */
+
+ result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
+ if (result == B43_TXPWR_RES_DONE)
+ return; /* We are done. */
+ B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
+ B43_WARN_ON(phy->ops->adjust_txpower == NULL);
+
+ /* We must adjust the transmission power in hardware.
+ * Schedule b43_phy_txpower_adjust_work(). */
+ queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
+}
+
+int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
+{
+ const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
+ unsigned int a, b, c, d;
+ unsigned int average;
+ u32 tmp;
+
+ tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
+ a = tmp & 0xFF;
+ b = (tmp >> 8) & 0xFF;
+ c = (tmp >> 16) & 0xFF;
+ d = (tmp >> 24) & 0xFF;
+ if (a == 0 || a == B43_TSSI_MAX ||
+ b == 0 || b == B43_TSSI_MAX ||
+ c == 0 || c == B43_TSSI_MAX ||
+ d == 0 || d == B43_TSSI_MAX)
+ return -ENOENT;
+ /* The values are OK. Clear them. */
+ tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
+ (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
+ b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);
+
+ if (is_ofdm) {
+ a = (a + 32) & 0x3F;
+ b = (b + 32) & 0x3F;
+ c = (c + 32) & 0x3F;
+ d = (d + 32) & 0x3F;
+ }
+
+ /* Get the average of the values with 0.5 added to each value. */
+ average = (a + b + c + d + 2) / 4;
+ if (is_ofdm) {
+ /* Adjust for CCK-boost */
+ if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
+ & B43_HF_CCKBOOST)
+ average = (average >= 13) ? (average - 13) : 0;
+ }
+
+ return average;
+}
+
+void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
+{
+ b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
+}
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
new file mode 100644
index 00000000000..c9f5430d1d7
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -0,0 +1,413 @@
+#ifndef LINUX_B43_PHY_COMMON_H_
+#define LINUX_B43_PHY_COMMON_H_
+
+#include <linux/rfkill.h>
+
+struct b43_wldev;
+
+
+/* PHY register routing bits */
+#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
+#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
+#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
+#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
+#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
+
+/* CCK (B-PHY) registers. */
+#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
+/* N-PHY registers. */
+#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
+/* N-PHY BMODE registers. */
+#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
+/* OFDM (A-PHY) registers. */
+#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
+/* Extended G-PHY registers. */
+#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
+
+
+/* Masks for the PHY versioning registers. */
+#define B43_PHYVER_ANALOG 0xF000
+#define B43_PHYVER_ANALOG_SHIFT 12
+#define B43_PHYVER_TYPE 0x0F00
+#define B43_PHYVER_TYPE_SHIFT 8
+#define B43_PHYVER_VERSION 0x00FF
+
+/**
+ * enum b43_interference_mitigation - Interference Mitigation mode
+ *
+ * @B43_INTERFMODE_NONE: Disabled
+ * @B43_INTERFMODE_NONWLAN: Non-WLAN Interference Mitigation
+ * @B43_INTERFMODE_MANUALWLAN: WLAN Interference Mitigation
+ * @B43_INTERFMODE_AUTOWLAN: Automatic WLAN Interference Mitigation
+ */
+enum b43_interference_mitigation {
+ B43_INTERFMODE_NONE,
+ B43_INTERFMODE_NONWLAN,
+ B43_INTERFMODE_MANUALWLAN,
+ B43_INTERFMODE_AUTOWLAN,
+};
+
+/* Antenna identifiers */
+enum {
+ B43_ANTENNA0, /* Antenna 0 */
+ B43_ANTENNA1, /* Antenna 0 */
+ B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
+ B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
+ B43_ANTENNA2,
+ B43_ANTENNA3 = 8,
+
+ B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
+ B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
+};
+
+/**
+ * enum b43_txpwr_result - Return value for the recalc_txpower PHY op.
+ *
+ * @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed.
+ * @B43_TXPWR_RES_DONE: No more work to do. Everything is done.
+ */
+enum b43_txpwr_result {
+ B43_TXPWR_RES_NEED_ADJUST,
+ B43_TXPWR_RES_DONE,
+};
+
+/**
+ * struct b43_phy_operations - Function pointers for PHY ops.
+ *
+ * @allocate: Allocate and initialise the PHY data structures.
+ * Must not be NULL.
+ * @free: Destroy and free the PHY data structures.
+ * Must not be NULL.
+ *
+ * @prepare_structs: Prepare the PHY data structures.
+ * The data structures allocated in @allocate are
+ * initialized here.
+ * Must not be NULL.
+ * @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to
+ * do some early early PHY hardware init.
+ * Can be NULL, if not required.
+ * @init: Initialize the PHY.
+ * Must not be NULL.
+ * @exit: Shutdown the PHY.
+ * Can be NULL, if not required.
+ *
+ * @phy_read: Read from a PHY register.
+ * Must not be NULL.
+ * @phy_write: Write to a PHY register.
+ * Must not be NULL.
+ * @radio_read: Read from a Radio register.
+ * Must not be NULL.
+ * @radio_write: Write to a Radio register.
+ * Must not be NULL.
+ *
+ * @supports_hwpctl: Returns a boolean whether Hardware Power Control
+ * is supported or not.
+ * If NULL, hwpctl is assumed to be never supported.
+ * @software_rfkill: Turn the radio ON or OFF.
+ * Possible state values are
+ * RFKILL_STATE_SOFT_BLOCKED or
+ * RFKILL_STATE_UNBLOCKED
+ * Must not be NULL.
+ * @switch_analog: Turn the Analog on/off.
+ * Must not be NULL.
+ * @switch_channel: Switch the radio to another channel.
+ * Must not be NULL.
+ * @get_default_chan: Just returns the default channel number.
+ * Must not be NULL.
+ * @set_rx_antenna: Set the antenna used for RX.
+ * Can be NULL, if not supported.
+ * @interf_mitigation: Switch the Interference Mitigation mode.
+ * Can be NULL, if not supported.
+ *
+ * @recalc_txpower: Recalculate the transmission power parameters.
+ * This callback has to recalculate the TX power settings,
+ * but does not need to write them to the hardware, yet.
+ * Returns enum b43_txpwr_result to indicate whether the hardware
+ * needs to be adjusted.
+ * If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower
+ * will be called later.
+ * If the parameter "ignore_tssi" is true, the TSSI values should
+ * be ignored and a recalculation of the power settings should be
+ * done even if the TSSI values did not change.
+ * This callback is called with wl->irq_lock held and must not sleep.
+ * Must not be NULL.
+ * @adjust_txpower: Write the previously calculated TX power settings
+ * (from @recalc_txpower) to the hardware.
+ * This function may sleep.
+ * Can be NULL, if (and ONLY if) @recalc_txpower _always_
+ * returns B43_TXPWR_RES_DONE.
+ *
+ * @pwork_15sec: Periodic work. Called every 15 seconds.
+ * Can be NULL, if not required.
+ * @pwork_60sec: Periodic work. Called every 60 seconds.
+ * Can be NULL, if not required.
+ */
+struct b43_phy_operations {
+ /* Initialisation */
+ int (*allocate)(struct b43_wldev *dev);
+ void (*free)(struct b43_wldev *dev);
+ void (*prepare_structs)(struct b43_wldev *dev);
+ int (*prepare_hardware)(struct b43_wldev *dev);
+ int (*init)(struct b43_wldev *dev);
+ void (*exit)(struct b43_wldev *dev);
+
+ /* Register access */
+ u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
+ void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
+ u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
+ void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
+
+ /* Radio */
+ bool (*supports_hwpctl)(struct b43_wldev *dev);
+ void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state);
+ void (*switch_analog)(struct b43_wldev *dev, bool on);
+ int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
+ unsigned int (*get_default_chan)(struct b43_wldev *dev);
+ void (*set_rx_antenna)(struct b43_wldev *dev, int antenna);
+ int (*interf_mitigation)(struct b43_wldev *dev,
+ enum b43_interference_mitigation new_mode);
+
+ /* Transmission power adjustment */
+ enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev,
+ bool ignore_tssi);
+ void (*adjust_txpower)(struct b43_wldev *dev);
+
+ /* Misc */
+ void (*pwork_15sec)(struct b43_wldev *dev);
+ void (*pwork_60sec)(struct b43_wldev *dev);
+};
+
+struct b43_phy_a;
+struct b43_phy_g;
+struct b43_phy_n;
+struct b43_phy_lp;
+
+struct b43_phy {
+ /* Hardware operation callbacks. */
+ const struct b43_phy_operations *ops;
+
+ /* Most hardware context information is stored in the standard-
+ * specific data structures pointed to by the pointers below.
+ * Only one of them is valid (the currently enabled PHY). */
+#ifdef CONFIG_B43_DEBUG
+ /* No union for debug build to force NULL derefs in buggy code. */
+ struct {
+#else
+ union {
+#endif
+ /* A-PHY specific information */
+ struct b43_phy_a *a;
+ /* G-PHY specific information */
+ struct b43_phy_g *g;
+ /* N-PHY specific information */
+ struct b43_phy_n *n;
+ /* LP-PHY specific information */
+ struct b43_phy_lp *lp;
+ };
+
+ /* Band support flags. */
+ bool supports_2ghz;
+ bool supports_5ghz;
+
+ /* GMODE bit enabled? */
+ bool gmode;
+
+ /* Analog Type */
+ u8 analog;
+ /* B43_PHYTYPE_ */
+ u8 type;
+ /* PHY revision number. */
+ u8 rev;
+
+ /* Radio versioning */
+ u16 radio_manuf; /* Radio manufacturer */
+ u16 radio_ver; /* Radio version */
+ u8 radio_rev; /* Radio revision */
+
+ /* Software state of the radio */
+ bool radio_on;
+
+ /* Desired TX power level (in dBm).
+ * This is set by the user and adjusted in b43_phy_xmitpower(). */
+ int desired_txpower;
+
+ /* Hardware Power Control enabled? */
+ bool hardware_power_control;
+
+ /* The time (in absolute jiffies) when the next TX power output
+ * check is needed. */
+ unsigned long next_txpwr_check_time;
+
+ /* current channel */
+ unsigned int channel;
+
+ /* PHY TX errors counter. */
+ atomic_t txerr_cnt;
+
+#ifdef CONFIG_B43_DEBUG
+ /* PHY registers locked by b43_phy_lock()? */
+ bool phy_locked;
+#endif /* B43_DEBUG */
+};
+
+
+/**
+ * b43_phy_allocate - Allocate PHY structs
+ * Allocate the PHY data structures, based on the current dev->phy.type
+ */
+int b43_phy_allocate(struct b43_wldev *dev);
+
+/**
+ * b43_phy_free - Free PHY structs
+ */
+void b43_phy_free(struct b43_wldev *dev);
+
+/**
+ * b43_phy_init - Initialise the PHY
+ */
+int b43_phy_init(struct b43_wldev *dev);
+
+/**
+ * b43_phy_exit - Cleanup PHY
+ */
+void b43_phy_exit(struct b43_wldev *dev);
+
+/**
+ * b43_has_hardware_pctl - Hardware Power Control supported?
+ * Returns a boolean, whether hardware power control is supported.
+ */
+bool b43_has_hardware_pctl(struct b43_wldev *dev);
+
+/**
+ * b43_phy_read - 16bit PHY register read access
+ */
+u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
+
+/**
+ * b43_phy_write - 16bit PHY register write access
+ */
+void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
+
+/**
+ * b43_phy_mask - Mask a PHY register with a mask
+ */
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+
+/**
+ * b43_phy_set - OR a PHY register with a bitmap
+ */
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
+
+/**
+ * b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap
+ */
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
+/**
+ * b43_radio_read - 16bit Radio register read access
+ */
+u16 b43_radio_read(struct b43_wldev *dev, u16 reg);
+#define b43_radio_read16 b43_radio_read /* DEPRECATED */
+
+/**
+ * b43_radio_write - 16bit Radio register write access
+ */
+void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value);
+#define b43_radio_write16 b43_radio_write /* DEPRECATED */
+
+/**
+ * b43_radio_mask - Mask a 16bit radio register with a mask
+ */
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+
+/**
+ * b43_radio_set - OR a 16bit radio register with a bitmap
+ */
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
+
+/**
+ * b43_radio_maskset - Mask and OR a radio register with a mask and bitmap
+ */
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
+/**
+ * b43_radio_lock - Lock firmware radio register access
+ */
+void b43_radio_lock(struct b43_wldev *dev);
+
+/**
+ * b43_radio_unlock - Unlock firmware radio register access
+ */
+void b43_radio_unlock(struct b43_wldev *dev);
+
+/**
+ * b43_phy_lock - Lock firmware PHY register access
+ */
+void b43_phy_lock(struct b43_wldev *dev);
+
+/**
+ * b43_phy_unlock - Unlock firmware PHY register access
+ */
+void b43_phy_unlock(struct b43_wldev *dev);
+
+/**
+ * b43_switch_channel - Switch to another channel
+ */
+int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
+/**
+ * B43_DEFAULT_CHANNEL - Switch to the default channel.
+ */
+#define B43_DEFAULT_CHANNEL UINT_MAX
+
+/**
+ * b43_software_rfkill - Turn the radio ON or OFF in software.
+ */
+void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);
+
+/**
+ * b43_phy_txpower_check - Check TX power output.
+ *
+ * Compare the current TX power output to the desired power emission
+ * and schedule an adjustment in case it mismatches.
+ * Requires wl->irq_lock locked.
+ *
+ * @flags: OR'ed enum b43_phy_txpower_check_flags flags.
+ * See the docs below.
+ */
+void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags);
+/**
+ * enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check()
+ *
+ * @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo
+ * the check now.
+ * @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average
+ * TSSI did not change.
+ */
+enum b43_phy_txpower_check_flags {
+ B43_TXPWR_IGNORE_TIME = (1 << 0),
+ B43_TXPWR_IGNORE_TSSI = (1 << 1),
+};
+
+struct work_struct;
+void b43_phy_txpower_adjust_work(struct work_struct *work);
+
+/**
+ * b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM.
+ *
+ * @shm_offset: The SHM address to read the values from.
+ *
+ * Returns the average of the 4 TSSI values, or a negative error code.
+ */
+int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
+
+/**
+ * b43_phy_switch_analog_generic - Generic PHY operation for switching the Analog.
+ *
+ * It does the switching based on the PHY0 core register.
+ * Do _not_ call this directly. Only use it as a switch_analog callback
+ * for struct b43_phy_operations.
+ */
+void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
+
+
+#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy_g.c
index 305d4cd6fd0..232181f6333 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -1,10 +1,11 @@
/*
Broadcom B43 wireless driver
+ IEEE 802.11g PHY driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -25,38 +26,14 @@
*/
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/types.h>
-#include <linux/bitrev.h>
-
#include "b43.h"
-#include "phy.h"
-#include "nphy.h"
-#include "main.h"
-#include "tables.h"
+#include "phy_g.h"
+#include "phy_common.h"
#include "lo.h"
-#include "wa.h"
-
-
-static const s8 b43_tssi2dbm_b_table[] = {
- 0x4D, 0x4C, 0x4B, 0x4A,
- 0x4A, 0x49, 0x48, 0x47,
- 0x47, 0x46, 0x45, 0x45,
- 0x44, 0x43, 0x42, 0x42,
- 0x41, 0x40, 0x3F, 0x3E,
- 0x3D, 0x3C, 0x3B, 0x3A,
- 0x39, 0x38, 0x37, 0x36,
- 0x35, 0x34, 0x32, 0x31,
- 0x30, 0x2F, 0x2D, 0x2C,
- 0x2B, 0x29, 0x28, 0x26,
- 0x25, 0x23, 0x21, 0x1F,
- 0x1D, 0x1A, 0x17, 0x14,
- 0x10, 0x0C, 0x06, 0x00,
- -7, -7, -7, -7,
- -7, -7, -7, -7,
- -7, -7, -7, -7,
-};
+#include "main.h"
+
+#include <linux/bitrev.h>
+
static const s8 b43_tssi2dbm_g_table[] = {
77, 77, 77, 76,
@@ -84,8 +61,20 @@ const u8 b43_radio_channel_codes_bg[] = {
72, 84,
};
+
+static void b43_calc_nrssi_threshold(struct b43_wldev *dev);
+
+
#define bitrev4(tmp) (bitrev8(tmp) >> 4)
-static void b43_phy_initg(struct b43_wldev *dev);
+
+
+/* Get the freq, as it has to be written to the device. */
+static inline u16 channel2freq_bg(u8 channel)
+{
+ B43_WARN_ON(!(channel >= 1 && channel <= 14));
+
+ return b43_radio_channel_codes_bg[channel - 1];
+}
static void generate_rfatt_list(struct b43_wldev *dev,
struct b43_rfatt_list *list)
@@ -130,7 +119,7 @@ static void generate_rfatt_list(struct b43_wldev *dev,
{.att = 9,.with_padmix = 1,},
};
- if (!b43_has_hardware_pctl(phy)) {
+ if (!b43_has_hardware_pctl(dev)) {
/* Software pctl */
list->list = rfatt_0;
list->len = ARRAY_SIZE(rfatt_0);
@@ -174,140 +163,55 @@ static void generate_bbatt_list(struct b43_wldev *dev,
list->max_val = 8;
}
-bool b43_has_hardware_pctl(struct b43_phy *phy)
-{
- if (!phy->hardware_power_control)
- return 0;
- switch (phy->type) {
- case B43_PHYTYPE_A:
- if (phy->rev >= 5)
- return 1;
- break;
- case B43_PHYTYPE_G:
- if (phy->rev >= 6)
- return 1;
- break;
- default:
- B43_WARN_ON(1);
- }
- return 0;
-}
-
static void b43_shm_clear_tssi(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0068, 0x7F7F);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x006a, 0x7F7F);
- break;
- case B43_PHYTYPE_B:
- case B43_PHYTYPE_G:
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);
- break;
- }
-}
-
-/* Lock the PHY registers against concurrent access from the microcode.
- * This lock is nonrecursive. */
-void b43_phy_lock(struct b43_wldev *dev)
-{
-#if B43_DEBUG
- B43_WARN_ON(dev->phy.phy_locked);
- dev->phy.phy_locked = 1;
-#endif
- B43_WARN_ON(dev->dev->id.revision < 3);
-
- if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
- b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+ b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);
+ b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);
+ b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);
+ b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);
}
-void b43_phy_unlock(struct b43_wldev *dev)
+/* Synthetic PU workaround */
+static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel)
{
-#if B43_DEBUG
- B43_WARN_ON(!dev->phy.phy_locked);
- dev->phy.phy_locked = 0;
-#endif
- B43_WARN_ON(dev->dev->id.revision < 3);
+ struct b43_phy *phy = &dev->phy;
- if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
- b43_power_saving_ctl_bits(dev, 0);
-}
+ might_sleep();
-/* Different PHYs require different register routing flags.
- * This adjusts (and does sanity checks on) the routing flags.
- */
-static inline u16 adjust_phyreg_for_phytype(struct b43_phy *phy,
- u16 offset, struct b43_wldev *dev)
-{
- if (phy->type == B43_PHYTYPE_A) {
- /* OFDM registers are base-registers for the A-PHY. */
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
- offset &= ~B43_PHYROUTE;
- offset |= B43_PHYROUTE_BASE;
- }
+ if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {
+ /* We do not need the workaround. */
+ return;
}
-#if B43_DEBUG
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
- /* Ext-G registers are only available on G-PHYs */
- if (phy->type != B43_PHYTYPE_G) {
- b43err(dev->wl, "Invalid EXT-G PHY access at "
- "0x%04X on PHY type %u\n", offset, phy->type);
- dump_stack();
- }
- }
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
- /* N-BMODE registers are only available on N-PHYs */
- if (phy->type != B43_PHYTYPE_N) {
- b43err(dev->wl, "Invalid N-BMODE PHY access at "
- "0x%04X on PHY type %u\n", offset, phy->type);
- dump_stack();
- }
+ if (channel <= 10) {
+ b43_write16(dev, B43_MMIO_CHANNEL,
+ channel2freq_bg(channel + 4));
+ } else {
+ b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1));
}
-#endif /* B43_DEBUG */
-
- return offset;
-}
-
-u16 b43_phy_read(struct b43_wldev * dev, u16 offset)
-{
- struct b43_phy *phy = &dev->phy;
-
- offset = adjust_phyreg_for_phytype(phy, offset, dev);
- b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);
- return b43_read16(dev, B43_MMIO_PHY_DATA);
+ msleep(1);
+ b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
}
-void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val)
+/* Set the baseband attenuation value on chip. */
+void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
+ u16 baseband_attenuation)
{
struct b43_phy *phy = &dev->phy;
- offset = adjust_phyreg_for_phytype(phy, offset, dev);
- b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);
- b43_write16(dev, B43_MMIO_PHY_DATA, val);
-}
-
-void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
-{
- b43_phy_write(dev, offset,
- b43_phy_read(dev, offset) & mask);
-}
-
-void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
-{
- b43_phy_write(dev, offset,
- b43_phy_read(dev, offset) | set);
-}
-
-void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
-{
- b43_phy_write(dev, offset,
- (b43_phy_read(dev, offset) & mask) | set);
+ if (phy->analog == 0) {
+ b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0)
+ & 0xFFF0) |
+ baseband_attenuation);
+ } else if (phy->analog > 1) {
+ b43_phy_write(dev, B43_PHY_DACCTL,
+ (b43_phy_read(dev, B43_PHY_DACCTL)
+ & 0xFFC3) | (baseband_attenuation << 2));
+ } else {
+ b43_phy_write(dev, B43_PHY_DACCTL,
+ (b43_phy_read(dev, B43_PHY_DACCTL)
+ & 0xFF87) | (baseband_attenuation << 3));
+ }
}
/* Adjust the transmission power output (G-PHY) */
@@ -316,7 +220,8 @@ void b43_set_txpower_g(struct b43_wldev *dev,
const struct b43_rfatt *rfatt, u8 tx_control)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
u16 bb, rf;
u16 tx_bias, tx_magn;
@@ -327,11 +232,12 @@ void b43_set_txpower_g(struct b43_wldev *dev,
if (unlikely(tx_bias == 0xFF))
tx_bias = 0;
- /* Save the values for later */
- phy->tx_control = tx_control;
- memcpy(&phy->rfatt, rfatt, sizeof(*rfatt));
- phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);
- memcpy(&phy->bbatt, bbatt, sizeof(*bbatt));
+ /* Save the values for later. Use memmove, because it's valid
+ * to pass &gphy->rfatt as rfatt pointer argument. Same for bbatt. */
+ gphy->tx_control = tx_control;
+ memmove(&gphy->rfatt, rfatt, sizeof(*rfatt));
+ gphy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);
+ memmove(&gphy->bbatt, bbatt, sizeof(*bbatt));
if (b43_debug(dev, B43_DBG_XMITPOWER)) {
b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), "
@@ -340,7 +246,7 @@ void b43_set_txpower_g(struct b43_wldev *dev,
bb, rf, tx_control, tx_bias, tx_magn);
}
- b43_phy_set_baseband_attenuation(dev, bb);
+ b43_gphy_set_baseband_attenuation(dev, bb);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf);
if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
b43_radio_write16(dev, 0x43,
@@ -358,179 +264,23 @@ void b43_set_txpower_g(struct b43_wldev *dev,
b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52)
& 0xFFF0) | (tx_bias & 0x000F));
}
- if (phy->type == B43_PHYTYPE_G)
- b43_lo_g_adjust(dev);
-}
-
-static void default_baseband_attenuation(struct b43_wldev *dev,
- struct b43_bbatt *bb)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
- bb->att = 0;
- else
- bb->att = 2;
-}
-
-static void default_radio_attenuation(struct b43_wldev *dev,
- struct b43_rfatt *rf)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
-
- rf->with_padmix = 0;
-
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BCM4309G) {
- if (bus->boardinfo.rev < 0x43) {
- rf->att = 2;
- return;
- } else if (bus->boardinfo.rev < 0x51) {
- rf->att = 3;
- return;
- }
- }
-
- if (phy->type == B43_PHYTYPE_A) {
- rf->att = 0x60;
- return;
- }
-
- switch (phy->radio_ver) {
- case 0x2053:
- switch (phy->radio_rev) {
- case 1:
- rf->att = 6;
- return;
- }
- break;
- case 0x2050:
- switch (phy->radio_rev) {
- case 0:
- rf->att = 5;
- return;
- case 1:
- if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
- rf->att = 3;
- else if (bus->boardinfo.vendor ==
- SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
- SSB_BOARD_BU4306)
- rf->att = 3;
- else
- rf->att = 1;
- } else {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
- rf->att = 7;
- else
- rf->att = 6;
- }
- return;
- case 2:
- if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
- rf->att = 3;
- else if (bus->boardinfo.vendor ==
- SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
- SSB_BOARD_BU4306)
- rf->att = 5;
- else if (bus->chip_id == 0x4320)
- rf->att = 4;
- else
- rf->att = 3;
- } else
- rf->att = 6;
- return;
- case 3:
- rf->att = 5;
- return;
- case 4:
- case 5:
- rf->att = 1;
- return;
- case 6:
- case 7:
- rf->att = 5;
- return;
- case 8:
- rf->att = 0xA;
- rf->with_padmix = 1;
- return;
- case 9:
- default:
- rf->att = 5;
- return;
- }
- }
- rf->att = 5;
-}
-
-static u16 default_tx_control(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (phy->radio_ver != 0x2050)
- return 0;
- if (phy->radio_rev == 1)
- return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX;
- if (phy->radio_rev < 6)
- return B43_TXCTL_PA2DB;
- if (phy->radio_rev == 8)
- return B43_TXCTL_TXMIX;
- return 0;
-}
-
-/* This func is called "PHY calibrate" in the specs... */
-void b43_phy_early_init(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
-
- default_baseband_attenuation(dev, &phy->bbatt);
- default_radio_attenuation(dev, &phy->rfatt);
- phy->tx_control = (default_tx_control(dev) << 4);
-
- /* Commit previous writes */
- b43_read32(dev, B43_MMIO_MACCTL);
-
- if (phy->type == B43_PHYTYPE_B || phy->type == B43_PHYTYPE_G) {
- generate_rfatt_list(dev, &lo->rfatt_list);
- generate_bbatt_list(dev, &lo->bbatt_list);
- }
- if (phy->type == B43_PHYTYPE_G && phy->rev == 1) {
- /* Workaround: Temporarly disable gmode through the early init
- * phase, as the gmode stuff is not needed for phy rev 1 */
- phy->gmode = 0;
- b43_wireless_core_reset(dev, 0);
- b43_phy_initg(dev);
- phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
- }
+ b43_lo_g_adjust(dev);
}
/* GPHY_TSSI_Power_Lookup_Table_Init */
static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
int i;
u16 value;
for (i = 0; i < 32; i++)
- b43_ofdmtab_write16(dev, 0x3C20, i, phy->tssi2dbm[i]);
+ b43_ofdmtab_write16(dev, 0x3C20, i, gphy->tssi2dbm[i]);
for (i = 32; i < 64; i++)
- b43_ofdmtab_write16(dev, 0x3C00, i - 32, phy->tssi2dbm[i]);
+ b43_ofdmtab_write16(dev, 0x3C00, i - 32, gphy->tssi2dbm[i]);
for (i = 0; i < 64; i += 2) {
- value = (u16) phy->tssi2dbm[i];
- value |= ((u16) phy->tssi2dbm[i + 1]) << 8;
+ value = (u16) gphy->tssi2dbm[i];
+ value |= ((u16) gphy->tssi2dbm[i + 1]) << 8;
b43_phy_write(dev, 0x380 + (i / 2), value);
}
}
@@ -539,7 +289,8 @@ static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev)
static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- struct b43_txpower_lo_control *lo = phy->lo_control;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
u16 nr_written = 0;
u16 tmp;
u8 rf, bb;
@@ -561,1509 +312,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
}
}
-static void hardware_pctl_init_aphy(struct b43_wldev *dev)
-{
- //TODO
-}
-
-static void hardware_pctl_init_gphy(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
-
- b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0)
- | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
- b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00)
- | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
- b43_gphy_tssi_power_lt_init(dev);
- b43_gphy_gain_lt_init(dev);
- b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF);
- b43_phy_write(dev, 0x0014, 0x0000);
-
- B43_WARN_ON(phy->rev < 6);
- b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
- | 0x0800);
- b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
- & 0xFEFF);
- b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801)
- & 0xFFBF);
-
- b43_gphy_dc_lt_init(dev, 1);
-}
-
-/* HardwarePowerControl init for A and G PHY */
-static void b43_hardware_pctl_init(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (!b43_has_hardware_pctl(phy)) {
- /* No hardware power control */
- b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL);
- return;
- }
- /* Init the hwpctl related hardware */
- switch (phy->type) {
- case B43_PHYTYPE_A:
- hardware_pctl_init_aphy(dev);
- break;
- case B43_PHYTYPE_G:
- hardware_pctl_init_gphy(dev);
- break;
- default:
- B43_WARN_ON(1);
- }
- /* Enable hardware pctl in firmware. */
- b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);
-}
-
-static void b43_hardware_pctl_early_init(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (!b43_has_hardware_pctl(phy)) {
- b43_phy_write(dev, 0x047A, 0xC111);
- return;
- }
-
- b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF);
- b43_phy_write(dev, 0x002F, 0x0202);
- b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002);
- b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000);
- if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
- b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
- & 0xFF0F) | 0x0010);
- b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
- | 0x8000);
- b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
- & 0xFFC0) | 0x0010);
- b43_phy_write(dev, 0x002E, 0xC07F);
- b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
- | 0x0400);
- } else {
- b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
- | 0x0200);
- b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
- | 0x0400);
- b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
- & 0x7FFF);
- b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F)
- & 0xFFFE);
- b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
- & 0xFFC0) | 0x0010);
- b43_phy_write(dev, 0x002E, 0xC07F);
- b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
- & 0xFF0F) | 0x0010);
- }
-}
-
-/* Intialize B/G PHY power control
- * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
- */
-static void b43_phy_init_pctl(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
- struct b43_rfatt old_rfatt;
- struct b43_bbatt old_bbatt;
- u8 old_tx_control = 0;
-
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
- return;
-
- b43_phy_write(dev, 0x0028, 0x8018);
-
- /* This does something with the Analog... */
- b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0)
- & 0xFFDF);
-
- if (phy->type == B43_PHYTYPE_G && !phy->gmode)
- return;
- b43_hardware_pctl_early_init(dev);
- if (phy->cur_idle_tssi == 0) {
- if (phy->radio_ver == 0x2050 && phy->analog == 0) {
- b43_radio_write16(dev, 0x0076,
- (b43_radio_read16(dev, 0x0076)
- & 0x00F7) | 0x0084);
- } else {
- struct b43_rfatt rfatt;
- struct b43_bbatt bbatt;
-
- memcpy(&old_rfatt, &phy->rfatt, sizeof(old_rfatt));
- memcpy(&old_bbatt, &phy->bbatt, sizeof(old_bbatt));
- old_tx_control = phy->tx_control;
-
- bbatt.att = 11;
- if (phy->radio_rev == 8) {
- rfatt.att = 15;
- rfatt.with_padmix = 1;
- } else {
- rfatt.att = 9;
- rfatt.with_padmix = 0;
- }
- b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
- }
- b43_dummy_transmission(dev);
- phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
- if (B43_DEBUG) {
- /* Current-Idle-TSSI sanity check. */
- if (abs(phy->cur_idle_tssi - phy->tgt_idle_tssi) >= 20) {
- b43dbg(dev->wl,
- "!WARNING! Idle-TSSI phy->cur_idle_tssi "
- "measuring failed. (cur=%d, tgt=%d). Disabling TX power "
- "adjustment.\n", phy->cur_idle_tssi,
- phy->tgt_idle_tssi);
- phy->cur_idle_tssi = 0;
- }
- }
- if (phy->radio_ver == 0x2050 && phy->analog == 0) {
- b43_radio_write16(dev, 0x0076,
- b43_radio_read16(dev, 0x0076)
- & 0xFF7B);
- } else {
- b43_set_txpower_g(dev, &old_bbatt,
- &old_rfatt, old_tx_control);
- }
- }
- b43_hardware_pctl_init(dev);
- b43_shm_clear_tssi(dev);
-}
-
-static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
-{
- int i;
-
- if (dev->phy.rev < 3) {
- if (enable)
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, 0xFFF8);
- }
- else
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
- }
- } else {
- if (enable)
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, 0x0820);
- else
- for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
- }
-}
-
-static void b43_phy_ww(struct b43_wldev *dev)
-{
- u16 b, curr_s, best_s = 0xFFFF;
- int i;
-
- b43_phy_write(dev, B43_PHY_CRS0,
- b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN);
- b43_phy_write(dev, B43_PHY_OFDM(0x1B),
- b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000);
- b43_phy_write(dev, B43_PHY_OFDM(0x82),
- (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300);
- b43_radio_write16(dev, 0x0009,
- b43_radio_read16(dev, 0x0009) | 0x0080);
- b43_radio_write16(dev, 0x0012,
- (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002);
- b43_wa_initgains(dev);
- b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
- b = b43_phy_read(dev, B43_PHY_PWRDOWN);
- b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
- b43_radio_write16(dev, 0x0004,
- b43_radio_read16(dev, 0x0004) | 0x0004);
- for (i = 0x10; i <= 0x20; i++) {
- b43_radio_write16(dev, 0x0013, i);
- curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
- if (!curr_s) {
- best_s = 0x0000;
- break;
- } else if (curr_s >= 0x0080)
- curr_s = 0x0100 - curr_s;
- if (curr_s < best_s)
- best_s = curr_s;
- }
- b43_phy_write(dev, B43_PHY_PWRDOWN, b);
- b43_radio_write16(dev, 0x0004,
- b43_radio_read16(dev, 0x0004) & 0xFFFB);
- b43_radio_write16(dev, 0x0013, best_s);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
- b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
- b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
- b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
- b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
- b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
- b43_phy_write(dev, B43_PHY_OFDM(0xBB),
- (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053);
- b43_phy_write(dev, B43_PHY_OFDM61,
- (b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120);
- b43_phy_write(dev, B43_PHY_OFDM(0x13),
- (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000);
- b43_phy_write(dev, B43_PHY_OFDM(0x14),
- (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
- for (i = 0; i < 6; i++)
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
- b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
- b43_phy_write(dev, B43_PHY_CRS0,
- b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
-}
-
-/* Initialize APHY. This is also called for the GPHY in some cases. */
-static void b43_phy_inita(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
-
- might_sleep();
-
- if (phy->rev >= 6) {
- if (phy->type == B43_PHYTYPE_A)
- b43_phy_write(dev, B43_PHY_OFDM(0x1B),
- b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000);
- if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
- b43_phy_write(dev, B43_PHY_ENCORE,
- b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010);
- else
- b43_phy_write(dev, B43_PHY_ENCORE,
- b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010);
- }
-
- b43_wa_all(dev);
-
- if (phy->type == B43_PHYTYPE_A) {
- if (phy->gmode && (phy->rev < 3))
- b43_phy_write(dev, 0x0034,
- b43_phy_read(dev, 0x0034) | 0x0001);
- b43_phy_rssiagc(dev, 0);
-
- b43_phy_write(dev, B43_PHY_CRS0,
- b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
-
- b43_radio_init2060(dev);
-
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
- ; //TODO: A PHY LO
- }
-
- if (phy->rev >= 3)
- b43_phy_ww(dev);
-
- hardware_pctl_init_aphy(dev);
-
- //TODO: radar detection
- }
-
- if ((phy->type == B43_PHYTYPE_G) &&
- (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
- b43_phy_write(dev, B43_PHY_OFDM(0x6E),
- (b43_phy_read(dev, B43_PHY_OFDM(0x6E))
- & 0xE000) | 0x3CF);
- }
-}
-
-static void b43_phy_initb5(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
- u16 offset, value;
- u8 old_channel;
-
- if (phy->analog == 1) {
- b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A)
- | 0x0050);
- }
- if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type != SSB_BOARD_BU4306)) {
- value = 0x2120;
- for (offset = 0x00A8; offset < 0x00C7; offset++) {
- b43_phy_write(dev, offset, value);
- value += 0x202;
- }
- }
- b43_phy_write(dev, 0x0035, (b43_phy_read(dev, 0x0035) & 0xF0FF)
- | 0x0700);
- if (phy->radio_ver == 0x2050)
- b43_phy_write(dev, 0x0038, 0x0667);
-
- if (phy->gmode || phy->rev >= 2) {
- if (phy->radio_ver == 0x2050) {
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A)
- | 0x0020);
- b43_radio_write16(dev, 0x0051,
- b43_radio_read16(dev, 0x0051)
- | 0x0004);
- }
- b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000);
-
- b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
- b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
-
- b43_phy_write(dev, 0x001C, 0x186A);
-
- b43_phy_write(dev, 0x0013,
- (b43_phy_read(dev, 0x0013) & 0x00FF) | 0x1900);
- b43_phy_write(dev, 0x0035,
- (b43_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064);
- b43_phy_write(dev, 0x005D,
- (b43_phy_read(dev, 0x005D) & 0xFF80) | 0x000A);
- }
-
- if (dev->bad_frames_preempt) {
- b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
- b43_phy_read(dev,
- B43_PHY_RADIO_BITFIELD) | (1 << 11));
- }
-
- if (phy->analog == 1) {
- b43_phy_write(dev, 0x0026, 0xCE00);
- b43_phy_write(dev, 0x0021, 0x3763);
- b43_phy_write(dev, 0x0022, 0x1BC3);
- b43_phy_write(dev, 0x0023, 0x06F9);
- b43_phy_write(dev, 0x0024, 0x037E);
- } else
- b43_phy_write(dev, 0x0026, 0xCC00);
- b43_phy_write(dev, 0x0030, 0x00C6);
- b43_write16(dev, 0x03EC, 0x3F22);
-
- if (phy->analog == 1)
- b43_phy_write(dev, 0x0020, 0x3E1C);
- else
- b43_phy_write(dev, 0x0020, 0x301C);
-
- if (phy->analog == 0)
- b43_write16(dev, 0x03E4, 0x3000);
-
- old_channel = phy->channel;
- /* Force to channel 7, even if not supported. */
- b43_radio_selectchannel(dev, 7, 0);
-
- if (phy->radio_ver != 0x2050) {
- b43_radio_write16(dev, 0x0075, 0x0080);
- b43_radio_write16(dev, 0x0079, 0x0081);
- }
-
- b43_radio_write16(dev, 0x0050, 0x0020);
- b43_radio_write16(dev, 0x0050, 0x0023);
-
- if (phy->radio_ver == 0x2050) {
- b43_radio_write16(dev, 0x0050, 0x0020);
- b43_radio_write16(dev, 0x005A, 0x0070);
- }
-
- b43_radio_write16(dev, 0x005B, 0x007B);
- b43_radio_write16(dev, 0x005C, 0x00B0);
-
- b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0007);
-
- b43_radio_selectchannel(dev, old_channel, 0);
-
- b43_phy_write(dev, 0x0014, 0x0080);
- b43_phy_write(dev, 0x0032, 0x00CA);
- b43_phy_write(dev, 0x002A, 0x88A3);
-
- b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
-
- if (phy->radio_ver == 0x2050)
- b43_radio_write16(dev, 0x005D, 0x000D);
-
- b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);
-}
-
-static void b43_phy_initb6(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- u16 offset, val;
- u8 old_channel;
-
- b43_phy_write(dev, 0x003E, 0x817A);
- b43_radio_write16(dev, 0x007A,
- (b43_radio_read16(dev, 0x007A) | 0x0058));
- if (phy->radio_rev == 4 || phy->radio_rev == 5) {
- b43_radio_write16(dev, 0x51, 0x37);
- b43_radio_write16(dev, 0x52, 0x70);
- b43_radio_write16(dev, 0x53, 0xB3);
- b43_radio_write16(dev, 0x54, 0x9B);
- b43_radio_write16(dev, 0x5A, 0x88);
- b43_radio_write16(dev, 0x5B, 0x88);
- b43_radio_write16(dev, 0x5D, 0x88);
- b43_radio_write16(dev, 0x5E, 0x88);
- b43_radio_write16(dev, 0x7D, 0x88);
- b43_hf_write(dev, b43_hf_read(dev)
- | B43_HF_TSSIRPSMW);
- }
- B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */
- if (phy->radio_rev == 8) {
- b43_radio_write16(dev, 0x51, 0);
- b43_radio_write16(dev, 0x52, 0x40);
- b43_radio_write16(dev, 0x53, 0xB7);
- b43_radio_write16(dev, 0x54, 0x98);
- b43_radio_write16(dev, 0x5A, 0x88);
- b43_radio_write16(dev, 0x5B, 0x6B);
- b43_radio_write16(dev, 0x5C, 0x0F);
- if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
- b43_radio_write16(dev, 0x5D, 0xFA);
- b43_radio_write16(dev, 0x5E, 0xD8);
- } else {
- b43_radio_write16(dev, 0x5D, 0xF5);
- b43_radio_write16(dev, 0x5E, 0xB8);
- }
- b43_radio_write16(dev, 0x0073, 0x0003);
- b43_radio_write16(dev, 0x007D, 0x00A8);
- b43_radio_write16(dev, 0x007C, 0x0001);
- b43_radio_write16(dev, 0x007E, 0x0008);
- }
- val = 0x1E1F;
- for (offset = 0x0088; offset < 0x0098; offset++) {
- b43_phy_write(dev, offset, val);
- val -= 0x0202;
- }
- val = 0x3E3F;
- for (offset = 0x0098; offset < 0x00A8; offset++) {
- b43_phy_write(dev, offset, val);
- val -= 0x0202;
- }
- val = 0x2120;
- for (offset = 0x00A8; offset < 0x00C8; offset++) {
- b43_phy_write(dev, offset, (val & 0x3F3F));
- val += 0x0202;
- }
- if (phy->type == B43_PHYTYPE_G) {
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) | 0x0020);
- b43_radio_write16(dev, 0x0051,
- b43_radio_read16(dev, 0x0051) | 0x0004);
- b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
- b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
- b43_phy_write(dev, 0x5B, 0);
- b43_phy_write(dev, 0x5C, 0);
- }
-
- old_channel = phy->channel;
- if (old_channel >= 8)
- b43_radio_selectchannel(dev, 1, 0);
- else
- b43_radio_selectchannel(dev, 13, 0);
-
- b43_radio_write16(dev, 0x0050, 0x0020);
- b43_radio_write16(dev, 0x0050, 0x0023);
- udelay(40);
- if (phy->radio_rev < 6 || phy->radio_rev == 8) {
- b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C)
- | 0x0002));
- b43_radio_write16(dev, 0x50, 0x20);
- }
- if (phy->radio_rev <= 2) {
- b43_radio_write16(dev, 0x7C, 0x20);
- b43_radio_write16(dev, 0x5A, 0x70);
- b43_radio_write16(dev, 0x5B, 0x7B);
- b43_radio_write16(dev, 0x5C, 0xB0);
- }
- b43_radio_write16(dev, 0x007A,
- (b43_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007);
-
- b43_radio_selectchannel(dev, old_channel, 0);
-
- b43_phy_write(dev, 0x0014, 0x0200);
- if (phy->radio_rev >= 6)
- b43_phy_write(dev, 0x2A, 0x88C2);
- else
- b43_phy_write(dev, 0x2A, 0x8AC0);
- b43_phy_write(dev, 0x0038, 0x0668);
- b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
- if (phy->radio_rev <= 5) {
- b43_phy_write(dev, 0x5D, (b43_phy_read(dev, 0x5D)
- & 0xFF80) | 0x0003);
- }
- if (phy->radio_rev <= 2)
- b43_radio_write16(dev, 0x005D, 0x000D);
-
- if (phy->analog == 4) {
- b43_write16(dev, 0x3E4, 9);
- b43_phy_write(dev, 0x61, b43_phy_read(dev, 0x61)
- & 0x0FFF);
- } else {
- b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0)
- | 0x0004);
- }
- if (phy->type == B43_PHYTYPE_B)
- B43_WARN_ON(1);
- else if (phy->type == B43_PHYTYPE_G)
- b43_write16(dev, 0x03E6, 0x0);
-}
-
-static void b43_calc_loopback_gain(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- u16 backup_phy[16] = { 0 };
- u16 backup_radio[3];
- u16 backup_bband;
- u16 i, j, loop_i_max;
- u16 trsw_rx;
- u16 loop1_outer_done, loop1_inner_done;
-
- backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0);
- backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
- backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER);
- backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL);
- if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
- backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);
- backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
- }
- backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A));
- backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59));
- backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58));
- backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A));
- backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03));
- backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);
- backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);
- backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B));
- backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);
- backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
- backup_bband = phy->bbatt.att;
- backup_radio[0] = b43_radio_read16(dev, 0x52);
- backup_radio[1] = b43_radio_read16(dev, 0x43);
- backup_radio[2] = b43_radio_read16(dev, 0x7A);
-
- b43_phy_write(dev, B43_PHY_CRS0,
- b43_phy_read(dev, B43_PHY_CRS0) & 0x3FFF);
- b43_phy_write(dev, B43_PHY_CCKBBANDCFG,
- b43_phy_read(dev, B43_PHY_CCKBBANDCFG) | 0x8000);
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER) | 0x0002);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFD);
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER) | 0x0001);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFE);
- if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
- b43_phy_write(dev, B43_PHY_ANALOGOVER,
- b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0001);
- b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
- b43_phy_read(dev,
- B43_PHY_ANALOGOVERVAL) & 0xFFFE);
- b43_phy_write(dev, B43_PHY_ANALOGOVER,
- b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0002);
- b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
- b43_phy_read(dev,
- B43_PHY_ANALOGOVERVAL) & 0xFFFD);
- }
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER) | 0x000C);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL) | 0x000C);
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER) | 0x0030);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- (b43_phy_read(dev, B43_PHY_RFOVERVAL)
- & 0xFFCF) | 0x10);
-
- b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780);
- b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
- b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
-
- b43_phy_write(dev, B43_PHY_CCK(0x0A),
- b43_phy_read(dev, B43_PHY_CCK(0x0A)) | 0x2000);
- if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
- b43_phy_write(dev, B43_PHY_ANALOGOVER,
- b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004);
- b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
- b43_phy_read(dev,
- B43_PHY_ANALOGOVERVAL) & 0xFFFB);
- }
- b43_phy_write(dev, B43_PHY_CCK(0x03),
- (b43_phy_read(dev, B43_PHY_CCK(0x03))
- & 0xFF9F) | 0x40);
-
- if (phy->radio_rev == 8) {
- b43_radio_write16(dev, 0x43, 0x000F);
- } else {
- b43_radio_write16(dev, 0x52, 0);
- b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
- & 0xFFF0) | 0x9);
- }
- b43_phy_set_baseband_attenuation(dev, 11);
-
- if (phy->rev >= 3)
- b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
- else
- b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
- b43_phy_write(dev, B43_PHY_LO_CTL, 0);
-
- b43_phy_write(dev, B43_PHY_CCK(0x2B),
- (b43_phy_read(dev, B43_PHY_CCK(0x2B))
- & 0xFFC0) | 0x01);
- b43_phy_write(dev, B43_PHY_CCK(0x2B),
- (b43_phy_read(dev, B43_PHY_CCK(0x2B))
- & 0xC0FF) | 0x800);
-
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER) | 0x0100);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF);
-
- if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
- if (phy->rev >= 7) {
- b43_phy_write(dev, B43_PHY_RFOVER,
- b43_phy_read(dev, B43_PHY_RFOVER)
- | 0x0800);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL)
- | 0x8000);
- }
- }
- b43_radio_write16(dev, 0x7A, b43_radio_read16(dev, 0x7A)
- & 0x00F7);
-
- j = 0;
- loop_i_max = (phy->radio_rev == 8) ? 15 : 9;
- for (i = 0; i < loop_i_max; i++) {
- for (j = 0; j < 16; j++) {
- b43_radio_write16(dev, 0x43, i);
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- (b43_phy_read(dev, B43_PHY_RFOVERVAL)
- & 0xF0FF) | (j << 8));
- b43_phy_write(dev, B43_PHY_PGACTL,
- (b43_phy_read(dev, B43_PHY_PGACTL)
- & 0x0FFF) | 0xA000);
- b43_phy_write(dev, B43_PHY_PGACTL,
- b43_phy_read(dev, B43_PHY_PGACTL)
- | 0xF000);
- udelay(20);
- if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
- goto exit_loop1;
- }
- }
- exit_loop1:
- loop1_outer_done = i;
- loop1_inner_done = j;
- if (j >= 8) {
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- b43_phy_read(dev, B43_PHY_RFOVERVAL)
- | 0x30);
- trsw_rx = 0x1B;
- for (j = j - 8; j < 16; j++) {
- b43_phy_write(dev, B43_PHY_RFOVERVAL,
- (b43_phy_read(dev, B43_PHY_RFOVERVAL)
- & 0xF0FF) | (j << 8));
- b43_phy_write(dev, B43_PHY_PGACTL,
- (b43_phy_read(dev, B43_PHY_PGACTL)
- & 0x0FFF) | 0xA000);
- b43_phy_write(dev, B43_PHY_PGACTL,
- b43_phy_read(dev, B43_PHY_PGACTL)
- | 0xF000);
- udelay(20);
- trsw_rx -= 3;
- if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
- goto exit_loop2;
- }
- } else
- trsw_rx = 0x18;
- exit_loop2:
-
- if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
- b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);
- b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);
- }
- b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]);
- b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]);
- b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]);
- b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]);
- b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]);
- b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);
- b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);
- b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]);
- b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);
-
- b43_phy_set_baseband_attenuation(dev, backup_bband);
-
- b43_radio_write16(dev, 0x52, backup_radio[0]);
- b43_radio_write16(dev, 0x43, backup_radio[1]);
- b43_radio_write16(dev, 0x7A, backup_radio[2]);
-
- b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003);
- udelay(10);
- b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]);
- b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]);
- b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]);
- b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]);
-
- phy->max_lb_gain =
- ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
- phy->trsw_rx_gain = trsw_rx * 2;
-}
-
-static void b43_phy_initg(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- u16 tmp;
-
- if (phy->rev == 1)
- b43_phy_initb5(dev);
- else
- b43_phy_initb6(dev);
-
- if (phy->rev >= 2 || phy->gmode)
- b43_phy_inita(dev);
-
- if (phy->rev >= 2) {
- b43_phy_write(dev, B43_PHY_ANALOGOVER, 0);
- b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0);
- }
- if (phy->rev == 2) {
- b43_phy_write(dev, B43_PHY_RFOVER, 0);
- b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
- }
- if (phy->rev > 5) {
- b43_phy_write(dev, B43_PHY_RFOVER, 0x400);
- b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
- }
- if (phy->gmode || phy->rev >= 2) {
- tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM);
- tmp &= B43_PHYVER_VERSION;
- if (tmp == 3 || tmp == 5) {
- b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816);
- b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006);
- }
- if (tmp == 5) {
- b43_phy_write(dev, B43_PHY_OFDM(0xCC),
- (b43_phy_read(dev, B43_PHY_OFDM(0xCC))
- & 0x00FF) | 0x1F00);
- }
- }
- if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
- b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78);
- if (phy->radio_rev == 8) {
- b43_phy_write(dev, B43_PHY_EXTG(0x01),
- b43_phy_read(dev, B43_PHY_EXTG(0x01))
- | 0x80);
- b43_phy_write(dev, B43_PHY_OFDM(0x3E),
- b43_phy_read(dev, B43_PHY_OFDM(0x3E))
- | 0x4);
- }
- if (has_loopback_gain(phy))
- b43_calc_loopback_gain(dev);
-
- if (phy->radio_rev != 8) {
- if (phy->initval == 0xFFFF)
- phy->initval = b43_radio_init2050(dev);
- else
- b43_radio_write16(dev, 0x0078, phy->initval);
- }
- b43_lo_g_init(dev);
- if (has_tx_magnification(phy)) {
- b43_radio_write16(dev, 0x52,
- (b43_radio_read16(dev, 0x52) & 0xFF00)
- | phy->lo_control->tx_bias | phy->
- lo_control->tx_magn);
- } else {
- b43_radio_write16(dev, 0x52,
- (b43_radio_read16(dev, 0x52) & 0xFFF0)
- | phy->lo_control->tx_bias);
- }
- if (phy->rev >= 6) {
- b43_phy_write(dev, B43_PHY_CCK(0x36),
- (b43_phy_read(dev, B43_PHY_CCK(0x36))
- & 0x0FFF) | (phy->lo_control->
- tx_bias << 12));
- }
- if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
- b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
- else
- b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
- if (phy->rev < 2)
- b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
- else
- b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
- if (phy->gmode || phy->rev >= 2) {
- b43_lo_g_adjust(dev);
- b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
- }
-
- if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
- /* The specs state to update the NRSSI LT with
- * the value 0x7FFFFFFF here. I think that is some weird
- * compiler optimization in the original driver.
- * Essentially, what we do here is resetting all NRSSI LT
- * entries to -32 (see the clamp_val() in nrssi_hw_update())
- */
- b43_nrssi_hw_update(dev, 0xFFFF); //FIXME?
- b43_calc_nrssi_threshold(dev);
- } else if (phy->gmode || phy->rev >= 2) {
- if (phy->nrssi[0] == -1000) {
- B43_WARN_ON(phy->nrssi[1] != -1000);
- b43_calc_nrssi_slope(dev);
- } else
- b43_calc_nrssi_threshold(dev);
- }
- if (phy->radio_rev == 8)
- b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230);
- b43_phy_init_pctl(dev);
- /* FIXME: The spec says in the following if, the 0 should be replaced
- 'if OFDM may not be used in the current locale'
- but OFDM is legal everywhere */
- if ((dev->dev->bus->chip_id == 0x4306
- && dev->dev->bus->chip_package == 2) || 0) {
- b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
- & 0xBFFF);
- b43_phy_write(dev, B43_PHY_OFDM(0xC3),
- b43_phy_read(dev, B43_PHY_OFDM(0xC3))
- & 0x7FFF);
- }
-}
-
-/* Set the baseband attenuation value on chip. */
-void b43_phy_set_baseband_attenuation(struct b43_wldev *dev,
- u16 baseband_attenuation)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (phy->analog == 0) {
- b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0)
- & 0xFFF0) |
- baseband_attenuation);
- } else if (phy->analog > 1) {
- b43_phy_write(dev, B43_PHY_DACCTL,
- (b43_phy_read(dev, B43_PHY_DACCTL)
- & 0xFFC3) | (baseband_attenuation << 2));
- } else {
- b43_phy_write(dev, B43_PHY_DACCTL,
- (b43_phy_read(dev, B43_PHY_DACCTL)
- & 0xFF87) | (baseband_attenuation << 3));
- }
-}
-
-/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
- * This function converts a TSSI value to dBm in Q5.2
- */
-static s8 b43_phy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
-{
- struct b43_phy *phy = &dev->phy;
- s8 dbm = 0;
- s32 tmp;
-
- tmp = (phy->tgt_idle_tssi - phy->cur_idle_tssi + tssi);
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- tmp += 0x80;
- tmp = clamp_val(tmp, 0x00, 0xFF);
- dbm = phy->tssi2dbm[tmp];
- //TODO: There's a FIXME on the specs
- break;
- case B43_PHYTYPE_B:
- case B43_PHYTYPE_G:
- tmp = clamp_val(tmp, 0x00, 0x3F);
- dbm = phy->tssi2dbm[tmp];
- break;
- default:
- B43_WARN_ON(1);
- }
-
- return dbm;
-}
-
-void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
- int *_bbatt, int *_rfatt)
-{
- int rfatt = *_rfatt;
- int bbatt = *_bbatt;
- struct b43_txpower_lo_control *lo = dev->phy.lo_control;
-
- /* Get baseband and radio attenuation values into their permitted ranges.
- * Radio attenuation affects power level 4 times as much as baseband. */
-
- /* Range constants */
- const int rf_min = lo->rfatt_list.min_val;
- const int rf_max = lo->rfatt_list.max_val;
- const int bb_min = lo->bbatt_list.min_val;
- const int bb_max = lo->bbatt_list.max_val;
-
- while (1) {
- if (rfatt > rf_max && bbatt > bb_max - 4)
- break; /* Can not get it into ranges */
- if (rfatt < rf_min && bbatt < bb_min + 4)
- break; /* Can not get it into ranges */
- if (bbatt > bb_max && rfatt > rf_max - 1)
- break; /* Can not get it into ranges */
- if (bbatt < bb_min && rfatt < rf_min + 1)
- break; /* Can not get it into ranges */
-
- if (bbatt > bb_max) {
- bbatt -= 4;
- rfatt += 1;
- continue;
- }
- if (bbatt < bb_min) {
- bbatt += 4;
- rfatt -= 1;
- continue;
- }
- if (rfatt > rf_max) {
- rfatt -= 1;
- bbatt += 4;
- continue;
- }
- if (rfatt < rf_min) {
- rfatt += 1;
- bbatt -= 4;
- continue;
- }
- break;
- }
-
- *_rfatt = clamp_val(rfatt, rf_min, rf_max);
- *_bbatt = clamp_val(bbatt, bb_min, bb_max);
-}
-
-/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
-void b43_phy_xmitpower(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
-
- if (phy->cur_idle_tssi == 0)
- return;
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
- return;
-#ifdef CONFIG_B43_DEBUG
- if (phy->manual_txpower_control)
- return;
-#endif
-
- switch (phy->type) {
- case B43_PHYTYPE_A:{
-
- //TODO: Nothing for A PHYs yet :-/
-
- break;
- }
- case B43_PHYTYPE_B:
- case B43_PHYTYPE_G:{
- u16 tmp;
- s8 v0, v1, v2, v3;
- s8 average;
- int max_pwr;
- int desired_pwr, estimated_pwr, pwr_adjust;
- int rfatt_delta, bbatt_delta;
- int rfatt, bbatt;
- u8 tx_control;
-
- tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x0058);
- v0 = (s8) (tmp & 0x00FF);
- v1 = (s8) ((tmp & 0xFF00) >> 8);
- tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x005A);
- v2 = (s8) (tmp & 0x00FF);
- v3 = (s8) ((tmp & 0xFF00) >> 8);
- tmp = 0;
-
- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F
- || v3 == 0x7F) {
- tmp =
- b43_shm_read16(dev, B43_SHM_SHARED, 0x0070);
- v0 = (s8) (tmp & 0x00FF);
- v1 = (s8) ((tmp & 0xFF00) >> 8);
- tmp =
- b43_shm_read16(dev, B43_SHM_SHARED, 0x0072);
- v2 = (s8) (tmp & 0x00FF);
- v3 = (s8) ((tmp & 0xFF00) >> 8);
- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F
- || v3 == 0x7F)
- return;
- v0 = (v0 + 0x20) & 0x3F;
- v1 = (v1 + 0x20) & 0x3F;
- v2 = (v2 + 0x20) & 0x3F;
- v3 = (v3 + 0x20) & 0x3F;
- tmp = 1;
- }
- b43_shm_clear_tssi(dev);
-
- average = (v0 + v1 + v2 + v3 + 2) / 4;
-
- if (tmp
- && (b43_shm_read16(dev, B43_SHM_SHARED, 0x005E) &
- 0x8))
- average -= 13;
-
- estimated_pwr =
- b43_phy_estimate_power_out(dev, average);
-
- max_pwr = dev->dev->bus->sprom.maxpwr_bg;
- if ((dev->dev->bus->sprom.boardflags_lo
- & B43_BFL_PACTRL) && (phy->type == B43_PHYTYPE_G))
- max_pwr -= 0x3;
- if (unlikely(max_pwr <= 0)) {
- b43warn(dev->wl,
- "Invalid max-TX-power value in SPROM.\n");
- max_pwr = 60; /* fake it */
- dev->dev->bus->sprom.maxpwr_bg = max_pwr;
- }
-
- /*TODO:
- max_pwr = min(REG - dev->dev->bus->sprom.antennagain_bgphy - 0x6, max_pwr)
- where REG is the max power as per the regulatory domain
- */
-
- /* Get desired power (in Q5.2) */
- desired_pwr = INT_TO_Q52(phy->power_level);
- /* And limit it. max_pwr already is Q5.2 */
- desired_pwr = clamp_val(desired_pwr, 0, max_pwr);
- if (b43_debug(dev, B43_DBG_XMITPOWER)) {
- b43dbg(dev->wl,
- "Current TX power output: " Q52_FMT
- " dBm, " "Desired TX power output: "
- Q52_FMT " dBm\n", Q52_ARG(estimated_pwr),
- Q52_ARG(desired_pwr));
- }
-
- /* Calculate the adjustment delta. */
- pwr_adjust = desired_pwr - estimated_pwr;
-
- /* RF attenuation delta. */
- rfatt_delta = ((pwr_adjust + 7) / 8);
- /* Lower attenuation => Bigger power output. Negate it. */
- rfatt_delta = -rfatt_delta;
-
- /* Baseband attenuation delta. */
- bbatt_delta = pwr_adjust / 2;
- /* Lower attenuation => Bigger power output. Negate it. */
- bbatt_delta = -bbatt_delta;
- /* RF att affects power level 4 times as much as
- * Baseband attennuation. Subtract it. */
- bbatt_delta -= 4 * rfatt_delta;
-
- /* So do we finally need to adjust something? */
- if ((rfatt_delta == 0) && (bbatt_delta == 0))
- return;
-
- /* Calculate the new attenuation values. */
- bbatt = phy->bbatt.att;
- bbatt += bbatt_delta;
- rfatt = phy->rfatt.att;
- rfatt += rfatt_delta;
-
- b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
- tx_control = phy->tx_control;
- if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
- if (rfatt <= 1) {
- if (tx_control == 0) {
- tx_control =
- B43_TXCTL_PA2DB |
- B43_TXCTL_TXMIX;
- rfatt += 2;
- bbatt += 2;
- } else if (dev->dev->bus->sprom.
- boardflags_lo &
- B43_BFL_PACTRL) {
- bbatt += 4 * (rfatt - 2);
- rfatt = 2;
- }
- } else if (rfatt > 4 && tx_control) {
- tx_control = 0;
- if (bbatt < 3) {
- rfatt -= 3;
- bbatt += 2;
- } else {
- rfatt -= 2;
- bbatt -= 2;
- }
- }
- }
- /* Save the control values */
- phy->tx_control = tx_control;
- b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
- phy->rfatt.att = rfatt;
- phy->bbatt.att = bbatt;
-
- /* Adjust the hardware */
- b43_phy_lock(dev);
- b43_radio_lock(dev);
- b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt,
- phy->tx_control);
- b43_radio_unlock(dev);
- b43_phy_unlock(dev);
- break;
- }
- case B43_PHYTYPE_N:
- b43_nphy_xmitpower(dev);
- break;
- default:
- B43_WARN_ON(1);
- }
-}
-
-static inline s32 b43_tssi2dbm_ad(s32 num, s32 den)
-{
- if (num < 0)
- return num / den;
- else
- return (num + den / 2) / den;
-}
-
-static inline
- s8 b43_tssi2dbm_entry(s8 entry[], u8 index, s16 pab0, s16 pab1, s16 pab2)
-{
- s32 m1, m2, f = 256, q, delta;
- s8 i = 0;
-
- m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
- m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1);
- do {
- if (i > 15)
- return -EINVAL;
- q = b43_tssi2dbm_ad(f * 4096 -
- b43_tssi2dbm_ad(m2 * f, 16) * f, 2048);
- delta = abs(q - f);
- f = q;
- i++;
- } while (delta >= 2);
- entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
- return 0;
-}
-
-/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
-int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- s16 pab0, pab1, pab2;
- u8 idx;
- s8 *dyn_tssi2dbm;
-
- if (phy->type == B43_PHYTYPE_A) {
- pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
- pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
- pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
- } else {
- pab0 = (s16) (dev->dev->bus->sprom.pa0b0);
- pab1 = (s16) (dev->dev->bus->sprom.pa0b1);
- pab2 = (s16) (dev->dev->bus->sprom.pa0b2);
- }
-
- if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
- phy->tgt_idle_tssi = 0x34;
- phy->tssi2dbm = b43_tssi2dbm_b_table;
- return 0;
- }
-
- if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
- pab0 != -1 && pab1 != -1 && pab2 != -1) {
- /* The pabX values are set in SPROM. Use them. */
- if (phy->type == B43_PHYTYPE_A) {
- if ((s8) dev->dev->bus->sprom.itssi_a != 0 &&
- (s8) dev->dev->bus->sprom.itssi_a != -1)
- phy->tgt_idle_tssi =
- (s8) (dev->dev->bus->sprom.itssi_a);
- else
- phy->tgt_idle_tssi = 62;
- } else {
- if ((s8) dev->dev->bus->sprom.itssi_bg != 0 &&
- (s8) dev->dev->bus->sprom.itssi_bg != -1)
- phy->tgt_idle_tssi =
- (s8) (dev->dev->bus->sprom.itssi_bg);
- else
- phy->tgt_idle_tssi = 62;
- }
- dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
- if (dyn_tssi2dbm == NULL) {
- b43err(dev->wl, "Could not allocate memory "
- "for tssi2dbm table\n");
- return -ENOMEM;
- }
- for (idx = 0; idx < 64; idx++)
- if (b43_tssi2dbm_entry
- (dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
- phy->tssi2dbm = NULL;
- b43err(dev->wl, "Could not generate "
- "tssi2dBm table\n");
- kfree(dyn_tssi2dbm);
- return -ENODEV;
- }
- phy->tssi2dbm = dyn_tssi2dbm;
- phy->dyn_tssi_tbl = 1;
- } else {
- /* pabX values not set in SPROM. */
- switch (phy->type) {
- case B43_PHYTYPE_A:
- /* APHY needs a generated table. */
- phy->tssi2dbm = NULL;
- b43err(dev->wl, "Could not generate tssi2dBm "
- "table (wrong SPROM info)!\n");
- return -ENODEV;
- case B43_PHYTYPE_B:
- phy->tgt_idle_tssi = 0x34;
- phy->tssi2dbm = b43_tssi2dbm_b_table;
- break;
- case B43_PHYTYPE_G:
- phy->tgt_idle_tssi = 0x34;
- phy->tssi2dbm = b43_tssi2dbm_g_table;
- break;
- }
- }
-
- return 0;
-}
-
-int b43_phy_init(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- bool unsupported = 0;
- int err = 0;
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- if (phy->rev == 2 || phy->rev == 3)
- b43_phy_inita(dev);
- else
- unsupported = 1;
- break;
- case B43_PHYTYPE_G:
- b43_phy_initg(dev);
- break;
- case B43_PHYTYPE_N:
- err = b43_phy_initn(dev);
- break;
- default:
- unsupported = 1;
- }
- if (unsupported)
- b43err(dev->wl, "Unknown PHYTYPE found\n");
-
- return err;
-}
-
-void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
-{
- struct b43_phy *phy = &dev->phy;
- u64 hf;
- u16 tmp;
- int autodiv = 0;
-
- if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
- autodiv = 1;
-
- hf = b43_hf_read(dev);
- hf &= ~B43_HF_ANTDIVHELP;
- b43_hf_write(dev, hf);
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- case B43_PHYTYPE_G:
- tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
- tmp &= ~B43_PHY_BBANDCFG_RXANT;
- tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
- << B43_PHY_BBANDCFG_RXANT_SHIFT;
- b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
-
- if (autodiv) {
- tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
- if (antenna == B43_ANTENNA_AUTO0)
- tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
- else
- tmp |= B43_PHY_ANTDWELL_AUTODIV1;
- b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
- }
- if (phy->type == B43_PHYTYPE_G) {
- tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);
- if (autodiv)
- tmp |= B43_PHY_ANTWRSETT_ARXDIV;
- else
- tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;
- b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);
- if (phy->rev >= 2) {
- tmp = b43_phy_read(dev, B43_PHY_OFDM61);
- tmp |= B43_PHY_OFDM61_10;
- b43_phy_write(dev, B43_PHY_OFDM61, tmp);
-
- tmp =
- b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK);
- tmp = (tmp & 0xFF00) | 0x15;
- b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK,
- tmp);
-
- if (phy->rev == 2) {
- b43_phy_write(dev, B43_PHY_ADIVRELATED,
- 8);
- } else {
- tmp =
- b43_phy_read(dev,
- B43_PHY_ADIVRELATED);
- tmp = (tmp & 0xFF00) | 8;
- b43_phy_write(dev, B43_PHY_ADIVRELATED,
- tmp);
- }
- }
- if (phy->rev >= 6)
- b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);
- } else {
- if (phy->rev < 3) {
- tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
- tmp = (tmp & 0xFF00) | 0x24;
- b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
- } else {
- tmp = b43_phy_read(dev, B43_PHY_OFDM61);
- tmp |= 0x10;
- b43_phy_write(dev, B43_PHY_OFDM61, tmp);
- if (phy->analog == 3) {
- b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
- 0x1D);
- b43_phy_write(dev, B43_PHY_ADIVRELATED,
- 8);
- } else {
- b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
- 0x3A);
- tmp =
- b43_phy_read(dev,
- B43_PHY_ADIVRELATED);
- tmp = (tmp & 0xFF00) | 8;
- b43_phy_write(dev, B43_PHY_ADIVRELATED,
- tmp);
- }
- }
- }
- break;
- case B43_PHYTYPE_B:
- tmp = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
- tmp &= ~B43_PHY_BBANDCFG_RXANT;
- tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
- << B43_PHY_BBANDCFG_RXANT_SHIFT;
- b43_phy_write(dev, B43_PHY_CCKBBANDCFG, tmp);
- break;
- case B43_PHYTYPE_N:
- b43_nphy_set_rxantenna(dev, antenna);
- break;
- default:
- B43_WARN_ON(1);
- }
-
- hf |= B43_HF_ANTDIVHELP;
- b43_hf_write(dev, hf);
-}
-
-/* Get the freq, as it has to be written to the device. */
-static inline u16 channel2freq_bg(u8 channel)
-{
- B43_WARN_ON(!(channel >= 1 && channel <= 14));
-
- return b43_radio_channel_codes_bg[channel - 1];
-}
-
-/* Get the freq, as it has to be written to the device. */
-static inline u16 channel2freq_a(u8 channel)
-{
- B43_WARN_ON(channel > 200);
-
- return (5000 + 5 * channel);
-}
-
-void b43_radio_lock(struct b43_wldev *dev)
-{
- u32 macctl;
-
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
- macctl |= B43_MACCTL_RADIOLOCK;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
- /* Commit the write and wait for the device
- * to exit any radio register access. */
- b43_read32(dev, B43_MMIO_MACCTL);
- udelay(10);
-}
-
-void b43_radio_unlock(struct b43_wldev *dev)
-{
- u32 macctl;
-
- /* Commit any write */
- b43_read16(dev, B43_MMIO_PHY_VER);
- /* unlock */
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
- macctl &= ~B43_MACCTL_RADIOLOCK;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
-}
-
-u16 b43_radio_read16(struct b43_wldev *dev, u16 offset)
-{
- struct b43_phy *phy = &dev->phy;
-
- /* Offset 1 is a 32-bit register. */
- B43_WARN_ON(offset == 1);
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- offset |= 0x40;
- break;
- case B43_PHYTYPE_B:
- if (phy->radio_ver == 0x2053) {
- if (offset < 0x70)
- offset += 0x80;
- else if (offset < 0x80)
- offset += 0x70;
- } else if (phy->radio_ver == 0x2050) {
- offset |= 0x80;
- } else
- B43_WARN_ON(1);
- break;
- case B43_PHYTYPE_G:
- offset |= 0x80;
- break;
- case B43_PHYTYPE_N:
- offset |= 0x100;
- break;
- case B43_PHYTYPE_LP:
- /* No adjustment required. */
- break;
- default:
- B43_WARN_ON(1);
- }
-
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
- return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-}
-
-void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val)
-{
- /* Offset 1 is a 32-bit register. */
- B43_WARN_ON(offset == 1);
-
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
- b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, val);
-}
-
-void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
-{
- b43_radio_write16(dev, offset,
- b43_radio_read16(dev, offset) & mask);
-}
-
-void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
-{
- b43_radio_write16(dev, offset,
- b43_radio_read16(dev, offset) | set);
-}
-
-void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
-{
- b43_radio_write16(dev, offset,
- (b43_radio_read16(dev, offset) & mask) | set);
-}
-
static void b43_set_all_gains(struct b43_wldev *dev,
s16 first, s16 second, s16 third)
{
@@ -2134,108 +382,10 @@ static void b43_set_original_gains(struct b43_wldev *dev)
b43_dummy_transmission(dev);
}
-/* Synthetic PU workaround */
-static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel)
-{
- struct b43_phy *phy = &dev->phy;
-
- might_sleep();
-
- if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {
- /* We do not need the workaround. */
- return;
- }
-
- if (channel <= 10) {
- b43_write16(dev, B43_MMIO_CHANNEL,
- channel2freq_bg(channel + 4));
- } else {
- b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1));
- }
- msleep(1);
- b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
-}
-
-u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel)
-{
- struct b43_phy *phy = &dev->phy;
- u8 ret = 0;
- u16 saved, rssi, temp;
- int i, j = 0;
-
- saved = b43_phy_read(dev, 0x0403);
- b43_radio_selectchannel(dev, channel, 0);
- b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
- if (phy->aci_hw_rssi)
- rssi = b43_phy_read(dev, 0x048A) & 0x3F;
- else
- rssi = saved & 0x3F;
- /* clamp temp to signed 5bit */
- if (rssi > 32)
- rssi -= 64;
- for (i = 0; i < 100; i++) {
- temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F;
- if (temp > 32)
- temp -= 64;
- if (temp < rssi)
- j++;
- if (j >= 20)
- ret = 1;
- }
- b43_phy_write(dev, 0x0403, saved);
-
- return ret;
-}
-
-u8 b43_radio_aci_scan(struct b43_wldev * dev)
-{
- struct b43_phy *phy = &dev->phy;
- u8 ret[13];
- unsigned int channel = phy->channel;
- unsigned int i, j, start, end;
-
- if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))
- return 0;
-
- b43_phy_lock(dev);
- b43_radio_lock(dev);
- b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
- b43_phy_write(dev, B43_PHY_G_CRS,
- b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
- b43_set_all_gains(dev, 3, 8, 1);
-
- start = (channel - 5 > 0) ? channel - 5 : 1;
- end = (channel + 5 < 14) ? channel + 5 : 13;
-
- for (i = start; i <= end; i++) {
- if (abs(channel - i) > 2)
- ret[i - 1] = b43_radio_aci_detect(dev, i);
- }
- b43_radio_selectchannel(dev, channel, 0);
- b43_phy_write(dev, 0x0802,
- (b43_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003);
- b43_phy_write(dev, 0x0403, b43_phy_read(dev, 0x0403) & 0xFFF8);
- b43_phy_write(dev, B43_PHY_G_CRS,
- b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
- b43_set_original_gains(dev);
- for (i = 0; i < 13; i++) {
- if (!ret[i])
- continue;
- end = (i + 5 < 13) ? i + 5 : 13;
- for (j = i; j < end; j++)
- ret[j] = 1;
- }
- b43_radio_unlock(dev);
- b43_phy_unlock(dev);
-
- return ret[channel - 1];
-}
-
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
{
b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
- mmiowb();
b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);
}
@@ -2267,17 +417,17 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
void b43_nrssi_mem_update(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
s16 i, delta;
s32 tmp;
- delta = 0x1F - phy->nrssi[0];
+ delta = 0x1F - gphy->nrssi[0];
for (i = 0; i < 64; i++) {
- tmp = (i - delta) * phy->nrssislope;
+ tmp = (i - delta) * gphy->nrssislope;
tmp /= 0x10000;
tmp += 0x3A;
tmp = clamp_val(tmp, 0, 0x3F);
- phy->nrssi_lt[i] = tmp;
+ gphy->nrssi_lt[i] = tmp;
}
}
@@ -2442,347 +592,230 @@ static void b43_calc_nrssi_offset(struct b43_wldev *dev)
void b43_calc_nrssi_slope(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
u16 backup[18] = { 0 };
u16 tmp;
s16 nrssi0, nrssi1;
- switch (phy->type) {
- case B43_PHYTYPE_B:
- backup[0] = b43_radio_read16(dev, 0x007A);
- backup[1] = b43_radio_read16(dev, 0x0052);
- backup[2] = b43_radio_read16(dev, 0x0043);
- backup[3] = b43_phy_read(dev, 0x0030);
- backup[4] = b43_phy_read(dev, 0x0026);
- backup[5] = b43_phy_read(dev, 0x0015);
- backup[6] = b43_phy_read(dev, 0x002A);
- backup[7] = b43_phy_read(dev, 0x0020);
- backup[8] = b43_phy_read(dev, 0x005A);
- backup[9] = b43_phy_read(dev, 0x0059);
- backup[10] = b43_phy_read(dev, 0x0058);
- backup[11] = b43_read16(dev, 0x03E2);
- backup[12] = b43_read16(dev, 0x03E6);
- backup[13] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
-
- tmp = b43_radio_read16(dev, 0x007A);
- tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
- b43_radio_write16(dev, 0x007A, tmp);
- b43_phy_write(dev, 0x0030, 0x00FF);
- b43_write16(dev, 0x03EC, 0x7F7F);
- b43_phy_write(dev, 0x0026, 0x0000);
- b43_phy_write(dev, 0x0015, b43_phy_read(dev, 0x0015) | 0x0020);
- b43_phy_write(dev, 0x002A, 0x08A3);
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) | 0x0080);
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- nrssi0 = (s16) b43_phy_read(dev, 0x0027);
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) & 0x007F);
- if (phy->rev >= 2) {
- b43_write16(dev, 0x03E6, 0x0040);
- } else if (phy->rev == 0) {
- b43_write16(dev, 0x03E6, 0x0122);
- } else {
- b43_write16(dev, B43_MMIO_CHANNEL_EXT,
- b43_read16(dev,
- B43_MMIO_CHANNEL_EXT) & 0x2000);
- }
- b43_phy_write(dev, 0x0020, 0x3F3F);
- b43_phy_write(dev, 0x0015, 0xF330);
- b43_radio_write16(dev, 0x005A, 0x0060);
- b43_radio_write16(dev, 0x0043,
- b43_radio_read16(dev, 0x0043) & 0x00F0);
- b43_phy_write(dev, 0x005A, 0x0480);
- b43_phy_write(dev, 0x0059, 0x0810);
- b43_phy_write(dev, 0x0058, 0x000D);
- udelay(20);
-
- nrssi1 = (s16) b43_phy_read(dev, 0x0027);
- b43_phy_write(dev, 0x0030, backup[3]);
- b43_radio_write16(dev, 0x007A, backup[0]);
- b43_write16(dev, 0x03E2, backup[11]);
- b43_phy_write(dev, 0x0026, backup[4]);
- b43_phy_write(dev, 0x0015, backup[5]);
- b43_phy_write(dev, 0x002A, backup[6]);
- b43_synth_pu_workaround(dev, phy->channel);
- if (phy->rev != 0)
- b43_write16(dev, 0x03F4, backup[13]);
-
- b43_phy_write(dev, 0x0020, backup[7]);
- b43_phy_write(dev, 0x005A, backup[8]);
- b43_phy_write(dev, 0x0059, backup[9]);
- b43_phy_write(dev, 0x0058, backup[10]);
- b43_radio_write16(dev, 0x0052, backup[1]);
- b43_radio_write16(dev, 0x0043, backup[2]);
-
- if (nrssi0 == nrssi1)
- phy->nrssislope = 0x00010000;
- else
- phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
-
- if (nrssi0 <= -4) {
- phy->nrssi[0] = nrssi0;
- phy->nrssi[1] = nrssi1;
- }
- break;
- case B43_PHYTYPE_G:
- if (phy->radio_rev >= 9)
- return;
- if (phy->radio_rev == 8)
- b43_calc_nrssi_offset(dev);
+ if (phy->radio_rev >= 9)
+ return;
+ if (phy->radio_rev == 8)
+ b43_calc_nrssi_offset(dev);
- b43_phy_write(dev, B43_PHY_G_CRS,
- b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
- b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
- backup[7] = b43_read16(dev, 0x03E2);
- b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000);
- backup[0] = b43_radio_read16(dev, 0x007A);
- backup[1] = b43_radio_read16(dev, 0x0052);
- backup[2] = b43_radio_read16(dev, 0x0043);
- backup[3] = b43_phy_read(dev, 0x0015);
- backup[4] = b43_phy_read(dev, 0x005A);
- backup[5] = b43_phy_read(dev, 0x0059);
- backup[6] = b43_phy_read(dev, 0x0058);
- backup[8] = b43_read16(dev, 0x03E6);
- backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
- if (phy->rev >= 3) {
- backup[10] = b43_phy_read(dev, 0x002E);
- backup[11] = b43_phy_read(dev, 0x002F);
- backup[12] = b43_phy_read(dev, 0x080F);
- backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL);
- backup[14] = b43_phy_read(dev, 0x0801);
- backup[15] = b43_phy_read(dev, 0x0060);
- backup[16] = b43_phy_read(dev, 0x0014);
- backup[17] = b43_phy_read(dev, 0x0478);
- b43_phy_write(dev, 0x002E, 0);
- b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0);
- switch (phy->rev) {
- case 4:
- case 6:
- case 7:
- b43_phy_write(dev, 0x0478,
- b43_phy_read(dev, 0x0478)
- | 0x0100);
- b43_phy_write(dev, 0x0801,
- b43_phy_read(dev, 0x0801)
- | 0x0040);
- break;
- case 3:
- case 5:
- b43_phy_write(dev, 0x0801,
- b43_phy_read(dev, 0x0801)
- & 0xFFBF);
- break;
- }
- b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060)
+ b43_phy_write(dev, B43_PHY_G_CRS,
+ b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
+ b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
+ backup[7] = b43_read16(dev, 0x03E2);
+ b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000);
+ backup[0] = b43_radio_read16(dev, 0x007A);
+ backup[1] = b43_radio_read16(dev, 0x0052);
+ backup[2] = b43_radio_read16(dev, 0x0043);
+ backup[3] = b43_phy_read(dev, 0x0015);
+ backup[4] = b43_phy_read(dev, 0x005A);
+ backup[5] = b43_phy_read(dev, 0x0059);
+ backup[6] = b43_phy_read(dev, 0x0058);
+ backup[8] = b43_read16(dev, 0x03E6);
+ backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
+ if (phy->rev >= 3) {
+ backup[10] = b43_phy_read(dev, 0x002E);
+ backup[11] = b43_phy_read(dev, 0x002F);
+ backup[12] = b43_phy_read(dev, 0x080F);
+ backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL);
+ backup[14] = b43_phy_read(dev, 0x0801);
+ backup[15] = b43_phy_read(dev, 0x0060);
+ backup[16] = b43_phy_read(dev, 0x0014);
+ backup[17] = b43_phy_read(dev, 0x0478);
+ b43_phy_write(dev, 0x002E, 0);
+ b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0);
+ switch (phy->rev) {
+ case 4:
+ case 6:
+ case 7:
+ b43_phy_write(dev, 0x0478,
+ b43_phy_read(dev, 0x0478)
+ | 0x0100);
+ b43_phy_write(dev, 0x0801,
+ b43_phy_read(dev, 0x0801)
| 0x0040);
- b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014)
- | 0x0200);
- }
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) | 0x0070);
- b43_set_all_gains(dev, 0, 8, 0);
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) & 0x00F7);
- if (phy->rev >= 2) {
- b43_phy_write(dev, 0x0811,
- (b43_phy_read(dev, 0x0811) & 0xFFCF) |
- 0x0030);
- b43_phy_write(dev, 0x0812,
- (b43_phy_read(dev, 0x0812) & 0xFFCF) |
- 0x0010);
+ break;
+ case 3:
+ case 5:
+ b43_phy_write(dev, 0x0801,
+ b43_phy_read(dev, 0x0801)
+ & 0xFFBF);
+ break;
}
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) | 0x0080);
- udelay(20);
+ b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060)
+ | 0x0040);
+ b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014)
+ | 0x0200);
+ }
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) | 0x0070);
+ b43_set_all_gains(dev, 0, 8, 0);
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) & 0x00F7);
+ if (phy->rev >= 2) {
+ b43_phy_write(dev, 0x0811,
+ (b43_phy_read(dev, 0x0811) & 0xFFCF) |
+ 0x0030);
+ b43_phy_write(dev, 0x0812,
+ (b43_phy_read(dev, 0x0812) & 0xFFCF) |
+ 0x0010);
+ }
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) | 0x0080);
+ udelay(20);
- nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
- if (nrssi0 >= 0x0020)
- nrssi0 -= 0x0040;
+ nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+ if (nrssi0 >= 0x0020)
+ nrssi0 -= 0x0040;
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) & 0x007F);
- if (phy->rev >= 2) {
- b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003)
- & 0xFF9F) | 0x0040);
- }
-
- b43_write16(dev, B43_MMIO_CHANNEL_EXT,
- b43_read16(dev, B43_MMIO_CHANNEL_EXT)
- | 0x2000);
- b43_radio_write16(dev, 0x007A,
- b43_radio_read16(dev, 0x007A) | 0x000F);
- b43_phy_write(dev, 0x0015, 0xF330);
- if (phy->rev >= 2) {
- b43_phy_write(dev, 0x0812,
- (b43_phy_read(dev, 0x0812) & 0xFFCF) |
- 0x0020);
- b43_phy_write(dev, 0x0811,
- (b43_phy_read(dev, 0x0811) & 0xFFCF) |
- 0x0020);
- }
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) & 0x007F);
+ if (phy->rev >= 2) {
+ b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003)
+ & 0xFF9F) | 0x0040);
+ }
- b43_set_all_gains(dev, 3, 0, 1);
- if (phy->radio_rev == 8) {
- b43_radio_write16(dev, 0x0043, 0x001F);
- } else {
- tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F;
- b43_radio_write16(dev, 0x0052, tmp | 0x0060);
- tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0;
- b43_radio_write16(dev, 0x0043, tmp | 0x0009);
- }
- b43_phy_write(dev, 0x005A, 0x0480);
- b43_phy_write(dev, 0x0059, 0x0810);
- b43_phy_write(dev, 0x0058, 0x000D);
- udelay(20);
- nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
- if (nrssi1 >= 0x0020)
- nrssi1 -= 0x0040;
- if (nrssi0 == nrssi1)
- phy->nrssislope = 0x00010000;
- else
- phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
- if (nrssi0 >= -4) {
- phy->nrssi[0] = nrssi1;
- phy->nrssi[1] = nrssi0;
- }
- if (phy->rev >= 3) {
- b43_phy_write(dev, 0x002E, backup[10]);
- b43_phy_write(dev, 0x002F, backup[11]);
- b43_phy_write(dev, 0x080F, backup[12]);
- b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]);
- }
- if (phy->rev >= 2) {
- b43_phy_write(dev, 0x0812,
- b43_phy_read(dev, 0x0812) & 0xFFCF);
- b43_phy_write(dev, 0x0811,
- b43_phy_read(dev, 0x0811) & 0xFFCF);
- }
+ b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+ b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+ | 0x2000);
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) | 0x000F);
+ b43_phy_write(dev, 0x0015, 0xF330);
+ if (phy->rev >= 2) {
+ b43_phy_write(dev, 0x0812,
+ (b43_phy_read(dev, 0x0812) & 0xFFCF) |
+ 0x0020);
+ b43_phy_write(dev, 0x0811,
+ (b43_phy_read(dev, 0x0811) & 0xFFCF) |
+ 0x0020);
+ }
- b43_radio_write16(dev, 0x007A, backup[0]);
- b43_radio_write16(dev, 0x0052, backup[1]);
- b43_radio_write16(dev, 0x0043, backup[2]);
- b43_write16(dev, 0x03E2, backup[7]);
- b43_write16(dev, 0x03E6, backup[8]);
- b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]);
- b43_phy_write(dev, 0x0015, backup[3]);
- b43_phy_write(dev, 0x005A, backup[4]);
- b43_phy_write(dev, 0x0059, backup[5]);
- b43_phy_write(dev, 0x0058, backup[6]);
- b43_synth_pu_workaround(dev, phy->channel);
- b43_phy_write(dev, 0x0802,
- b43_phy_read(dev, 0x0802) | (0x0001 | 0x0002));
- b43_set_original_gains(dev);
- b43_phy_write(dev, B43_PHY_G_CRS,
- b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
- if (phy->rev >= 3) {
- b43_phy_write(dev, 0x0801, backup[14]);
- b43_phy_write(dev, 0x0060, backup[15]);
- b43_phy_write(dev, 0x0014, backup[16]);
- b43_phy_write(dev, 0x0478, backup[17]);
- }
- b43_nrssi_mem_update(dev);
- b43_calc_nrssi_threshold(dev);
- break;
- default:
- B43_WARN_ON(1);
+ b43_set_all_gains(dev, 3, 0, 1);
+ if (phy->radio_rev == 8) {
+ b43_radio_write16(dev, 0x0043, 0x001F);
+ } else {
+ tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F;
+ b43_radio_write16(dev, 0x0052, tmp | 0x0060);
+ tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0;
+ b43_radio_write16(dev, 0x0043, tmp | 0x0009);
+ }
+ b43_phy_write(dev, 0x005A, 0x0480);
+ b43_phy_write(dev, 0x0059, 0x0810);
+ b43_phy_write(dev, 0x0058, 0x000D);
+ udelay(20);
+ nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+ if (nrssi1 >= 0x0020)
+ nrssi1 -= 0x0040;
+ if (nrssi0 == nrssi1)
+ gphy->nrssislope = 0x00010000;
+ else
+ gphy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+ if (nrssi0 >= -4) {
+ gphy->nrssi[0] = nrssi1;
+ gphy->nrssi[1] = nrssi0;
+ }
+ if (phy->rev >= 3) {
+ b43_phy_write(dev, 0x002E, backup[10]);
+ b43_phy_write(dev, 0x002F, backup[11]);
+ b43_phy_write(dev, 0x080F, backup[12]);
+ b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]);
}
+ if (phy->rev >= 2) {
+ b43_phy_write(dev, 0x0812,
+ b43_phy_read(dev, 0x0812) & 0xFFCF);
+ b43_phy_write(dev, 0x0811,
+ b43_phy_read(dev, 0x0811) & 0xFFCF);
+ }
+
+ b43_radio_write16(dev, 0x007A, backup[0]);
+ b43_radio_write16(dev, 0x0052, backup[1]);
+ b43_radio_write16(dev, 0x0043, backup[2]);
+ b43_write16(dev, 0x03E2, backup[7]);
+ b43_write16(dev, 0x03E6, backup[8]);
+ b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]);
+ b43_phy_write(dev, 0x0015, backup[3]);
+ b43_phy_write(dev, 0x005A, backup[4]);
+ b43_phy_write(dev, 0x0059, backup[5]);
+ b43_phy_write(dev, 0x0058, backup[6]);
+ b43_synth_pu_workaround(dev, phy->channel);
+ b43_phy_write(dev, 0x0802,
+ b43_phy_read(dev, 0x0802) | (0x0001 | 0x0002));
+ b43_set_original_gains(dev);
+ b43_phy_write(dev, B43_PHY_G_CRS,
+ b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
+ if (phy->rev >= 3) {
+ b43_phy_write(dev, 0x0801, backup[14]);
+ b43_phy_write(dev, 0x0060, backup[15]);
+ b43_phy_write(dev, 0x0014, backup[16]);
+ b43_phy_write(dev, 0x0478, backup[17]);
+ }
+ b43_nrssi_mem_update(dev);
+ b43_calc_nrssi_threshold(dev);
}
-void b43_calc_nrssi_threshold(struct b43_wldev *dev)
+static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- s32 threshold;
+ struct b43_phy_g *gphy = phy->g;
s32 a, b;
s16 tmp16;
u16 tmp_u16;
- switch (phy->type) {
- case B43_PHYTYPE_B:{
- if (phy->radio_ver != 0x2050)
- return;
- if (!
- (dev->dev->bus->sprom.
- boardflags_lo & B43_BFL_RSSI))
- return;
-
- if (phy->radio_rev >= 6) {
- threshold =
- (phy->nrssi[1] - phy->nrssi[0]) * 32;
- threshold += 20 * (phy->nrssi[0] + 1);
- threshold /= 40;
- } else
- threshold = phy->nrssi[1] - 5;
-
- threshold = clamp_val(threshold, 0, 0x3E);
- b43_phy_read(dev, 0x0020); /* dummy read */
- b43_phy_write(dev, 0x0020,
- (((u16) threshold) << 8) | 0x001C);
-
- if (phy->radio_rev >= 6) {
- b43_phy_write(dev, 0x0087, 0x0E0D);
- b43_phy_write(dev, 0x0086, 0x0C0B);
- b43_phy_write(dev, 0x0085, 0x0A09);
- b43_phy_write(dev, 0x0084, 0x0808);
- b43_phy_write(dev, 0x0083, 0x0808);
- b43_phy_write(dev, 0x0082, 0x0604);
- b43_phy_write(dev, 0x0081, 0x0302);
- b43_phy_write(dev, 0x0080, 0x0100);
- }
- break;
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+ if (!phy->gmode ||
+ !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ tmp16 = b43_nrssi_hw_read(dev, 0x20);
+ if (tmp16 >= 0x20)
+ tmp16 -= 0x40;
+ if (tmp16 < 3) {
+ b43_phy_write(dev, 0x048A,
+ (b43_phy_read(dev, 0x048A)
+ & 0xF000) | 0x09EB);
+ } else {
+ b43_phy_write(dev, 0x048A,
+ (b43_phy_read(dev, 0x048A)
+ & 0xF000) | 0x0AED);
}
- case B43_PHYTYPE_G:
- if (!phy->gmode ||
- !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
- tmp16 = b43_nrssi_hw_read(dev, 0x20);
- if (tmp16 >= 0x20)
- tmp16 -= 0x40;
- if (tmp16 < 3) {
- b43_phy_write(dev, 0x048A,
- (b43_phy_read(dev, 0x048A)
- & 0xF000) | 0x09EB);
- } else {
- b43_phy_write(dev, 0x048A,
- (b43_phy_read(dev, 0x048A)
- & 0xF000) | 0x0AED);
- }
+ } else {
+ if (gphy->interfmode == B43_INTERFMODE_NONWLAN) {
+ a = 0xE;
+ b = 0xA;
+ } else if (!gphy->aci_wlan_automatic && gphy->aci_enable) {
+ a = 0x13;
+ b = 0x12;
} else {
- if (phy->interfmode == B43_INTERFMODE_NONWLAN) {
- a = 0xE;
- b = 0xA;
- } else if (!phy->aci_wlan_automatic && phy->aci_enable) {
- a = 0x13;
- b = 0x12;
- } else {
- a = 0xE;
- b = 0x11;
- }
-
- a = a * (phy->nrssi[1] - phy->nrssi[0]);
- a += (phy->nrssi[0] << 6);
- if (a < 32)
- a += 31;
- else
- a += 32;
- a = a >> 6;
- a = clamp_val(a, -31, 31);
-
- b = b * (phy->nrssi[1] - phy->nrssi[0]);
- b += (phy->nrssi[0] << 6);
- if (b < 32)
- b += 31;
- else
- b += 32;
- b = b >> 6;
- b = clamp_val(b, -31, 31);
-
- tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;
- tmp_u16 |= ((u32) b & 0x0000003F);
- tmp_u16 |= (((u32) a & 0x0000003F) << 6);
- b43_phy_write(dev, 0x048A, tmp_u16);
+ a = 0xE;
+ b = 0x11;
}
- break;
- default:
- B43_WARN_ON(1);
+
+ a = a * (gphy->nrssi[1] - gphy->nrssi[0]);
+ a += (gphy->nrssi[0] << 6);
+ if (a < 32)
+ a += 31;
+ else
+ a += 32;
+ a = a >> 6;
+ a = clamp_val(a, -31, 31);
+
+ b = b * (gphy->nrssi[1] - gphy->nrssi[0]);
+ b += (gphy->nrssi[0] << 6);
+ if (b < 32)
+ b += 31;
+ else
+ b += 32;
+ b = b >> 6;
+ b = clamp_val(b, -31, 31);
+
+ tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;
+ tmp_u16 |= ((u32) b & 0x0000003F);
+ tmp_u16 |= (((u32) a & 0x0000003F) << 6);
+ b43_phy_write(dev, 0x048A, tmp_u16);
}
}
@@ -2860,9 +893,10 @@ static void
b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
u16 tmp, flipped;
size_t stackidx = 0;
- u32 *stack = phy->interfstack;
+ u32 *stack = gphy->interfstack;
switch (mode) {
case B43_INTERFMODE_NONWLAN:
@@ -2928,7 +962,7 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
if (b43_phy_read(dev, 0x0033) & 0x0800)
break;
- phy->aci_enable = 1;
+ gphy->aci_enable = 1;
phy_stacksave(B43_PHY_RADIO_BITFIELD);
phy_stacksave(B43_PHY_G_CRS);
@@ -3064,7 +1098,8 @@ static void
b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
{
struct b43_phy *phy = &dev->phy;
- u32 *stack = phy->interfstack;
+ struct b43_phy_g *gphy = phy->g;
+ u32 *stack = gphy->interfstack;
switch (mode) {
case B43_INTERFMODE_NONWLAN:
@@ -3103,7 +1138,7 @@ b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
if (!(b43_phy_read(dev, 0x0033) & 0x0800))
break;
- phy->aci_enable = 0;
+ gphy->aci_enable = 0;
phy_stackrestore(B43_PHY_RADIO_BITFIELD);
phy_stackrestore(B43_PHY_G_CRS);
@@ -3153,47 +1188,6 @@ b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
#undef ofdmtab_stacksave
#undef ofdmtab_stackrestore
-int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode)
-{
- struct b43_phy *phy = &dev->phy;
- int currentmode;
-
- if ((phy->type != B43_PHYTYPE_G) || (phy->rev == 0) || (!phy->gmode))
- return -ENODEV;
-
- phy->aci_wlan_automatic = 0;
- switch (mode) {
- case B43_INTERFMODE_AUTOWLAN:
- phy->aci_wlan_automatic = 1;
- if (phy->aci_enable)
- mode = B43_INTERFMODE_MANUALWLAN;
- else
- mode = B43_INTERFMODE_NONE;
- break;
- case B43_INTERFMODE_NONE:
- case B43_INTERFMODE_NONWLAN:
- case B43_INTERFMODE_MANUALWLAN:
- break;
- default:
- return -EINVAL;
- }
-
- currentmode = phy->interfmode;
- if (currentmode == mode)
- return 0;
- if (currentmode != B43_INTERFMODE_NONE)
- b43_radio_interference_mitigation_disable(dev, currentmode);
-
- if (mode == B43_INTERFMODE_NONE) {
- phy->aci_enable = 0;
- phy->aci_hw_rssi = 0;
- } else
- b43_radio_interference_mitigation_enable(dev, mode);
- phy->interfmode = mode;
-
- return 0;
-}
-
static u16 b43_radio_core_calibration_value(struct b43_wldev *dev)
{
u16 reg, index, ret;
@@ -3219,13 +1213,14 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
u16 phy_register, unsigned int lpd)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
if (!phy->gmode)
return 0;
if (has_loopback_gain(phy)) {
- int max_lb_gain = phy->max_lb_gain;
+ int max_lb_gain = gphy->max_lb_gain;
u16 extlna;
u16 i;
@@ -3606,301 +1601,1682 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
return ret;
}
-void b43_radio_init2060(struct b43_wldev *dev)
+static void b43_phy_initb5(struct b43_wldev *dev)
{
- int err;
+ struct ssb_bus *bus = dev->dev->bus;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ u16 offset, value;
+ u8 old_channel;
- b43_radio_write16(dev, 0x0004, 0x00C0);
- b43_radio_write16(dev, 0x0005, 0x0008);
- b43_radio_write16(dev, 0x0009, 0x0040);
- b43_radio_write16(dev, 0x0005, 0x00AA);
- b43_radio_write16(dev, 0x0032, 0x008F);
- b43_radio_write16(dev, 0x0006, 0x008F);
- b43_radio_write16(dev, 0x0034, 0x008F);
- b43_radio_write16(dev, 0x002C, 0x0007);
- b43_radio_write16(dev, 0x0082, 0x0080);
- b43_radio_write16(dev, 0x0080, 0x0000);
- b43_radio_write16(dev, 0x003F, 0x00DA);
- b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
- b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010);
- b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
- b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
- msleep(1); /* delay 400usec */
-
- b43_radio_write16(dev, 0x0081,
- (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
- msleep(1); /* delay 400usec */
-
- b43_radio_write16(dev, 0x0005,
- (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
- b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010);
- b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
- b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040);
- b43_radio_write16(dev, 0x0081,
- (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
- b43_radio_write16(dev, 0x0005,
- (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
- b43_phy_write(dev, 0x0063, 0xDDC6);
- b43_phy_write(dev, 0x0069, 0x07BE);
- b43_phy_write(dev, 0x006A, 0x0000);
-
- err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_A, 0);
- B43_WARN_ON(err);
+ if (phy->analog == 1) {
+ b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A)
+ | 0x0050);
+ }
+ if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
+ (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+ value = 0x2120;
+ for (offset = 0x00A8; offset < 0x00C7; offset++) {
+ b43_phy_write(dev, offset, value);
+ value += 0x202;
+ }
+ }
+ b43_phy_write(dev, 0x0035, (b43_phy_read(dev, 0x0035) & 0xF0FF)
+ | 0x0700);
+ if (phy->radio_ver == 0x2050)
+ b43_phy_write(dev, 0x0038, 0x0667);
- msleep(1);
+ if (phy->gmode || phy->rev >= 2) {
+ if (phy->radio_ver == 0x2050) {
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A)
+ | 0x0020);
+ b43_radio_write16(dev, 0x0051,
+ b43_radio_read16(dev, 0x0051)
+ | 0x0004);
+ }
+ b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000);
+
+ b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
+ b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
+
+ b43_phy_write(dev, 0x001C, 0x186A);
+
+ b43_phy_write(dev, 0x0013,
+ (b43_phy_read(dev, 0x0013) & 0x00FF) | 0x1900);
+ b43_phy_write(dev, 0x0035,
+ (b43_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064);
+ b43_phy_write(dev, 0x005D,
+ (b43_phy_read(dev, 0x005D) & 0xFF80) | 0x000A);
+ }
+
+ if (dev->bad_frames_preempt) {
+ b43_phy_write(dev, B43_PHY_RADIO_BITFIELD,
+ b43_phy_read(dev,
+ B43_PHY_RADIO_BITFIELD) | (1 << 11));
+ }
+
+ if (phy->analog == 1) {
+ b43_phy_write(dev, 0x0026, 0xCE00);
+ b43_phy_write(dev, 0x0021, 0x3763);
+ b43_phy_write(dev, 0x0022, 0x1BC3);
+ b43_phy_write(dev, 0x0023, 0x06F9);
+ b43_phy_write(dev, 0x0024, 0x037E);
+ } else
+ b43_phy_write(dev, 0x0026, 0xCC00);
+ b43_phy_write(dev, 0x0030, 0x00C6);
+ b43_write16(dev, 0x03EC, 0x3F22);
+
+ if (phy->analog == 1)
+ b43_phy_write(dev, 0x0020, 0x3E1C);
+ else
+ b43_phy_write(dev, 0x0020, 0x301C);
+
+ if (phy->analog == 0)
+ b43_write16(dev, 0x03E4, 0x3000);
+
+ old_channel = phy->channel;
+ /* Force to channel 7, even if not supported. */
+ b43_gphy_channel_switch(dev, 7, 0);
+
+ if (phy->radio_ver != 0x2050) {
+ b43_radio_write16(dev, 0x0075, 0x0080);
+ b43_radio_write16(dev, 0x0079, 0x0081);
+ }
+
+ b43_radio_write16(dev, 0x0050, 0x0020);
+ b43_radio_write16(dev, 0x0050, 0x0023);
+
+ if (phy->radio_ver == 0x2050) {
+ b43_radio_write16(dev, 0x0050, 0x0020);
+ b43_radio_write16(dev, 0x005A, 0x0070);
+ }
+
+ b43_radio_write16(dev, 0x005B, 0x007B);
+ b43_radio_write16(dev, 0x005C, 0x00B0);
+
+ b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0007);
+
+ b43_gphy_channel_switch(dev, old_channel, 0);
+
+ b43_phy_write(dev, 0x0014, 0x0080);
+ b43_phy_write(dev, 0x0032, 0x00CA);
+ b43_phy_write(dev, 0x002A, 0x88A3);
+
+ b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);
+
+ if (phy->radio_ver == 0x2050)
+ b43_radio_write16(dev, 0x005D, 0x000D);
+
+ b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);
}
-static inline u16 freq_r3A_value(u16 frequency)
+static void b43_phy_initb6(struct b43_wldev *dev)
{
- u16 value;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ u16 offset, val;
+ u8 old_channel;
+
+ b43_phy_write(dev, 0x003E, 0x817A);
+ b43_radio_write16(dev, 0x007A,
+ (b43_radio_read16(dev, 0x007A) | 0x0058));
+ if (phy->radio_rev == 4 || phy->radio_rev == 5) {
+ b43_radio_write16(dev, 0x51, 0x37);
+ b43_radio_write16(dev, 0x52, 0x70);
+ b43_radio_write16(dev, 0x53, 0xB3);
+ b43_radio_write16(dev, 0x54, 0x9B);
+ b43_radio_write16(dev, 0x5A, 0x88);
+ b43_radio_write16(dev, 0x5B, 0x88);
+ b43_radio_write16(dev, 0x5D, 0x88);
+ b43_radio_write16(dev, 0x5E, 0x88);
+ b43_radio_write16(dev, 0x7D, 0x88);
+ b43_hf_write(dev, b43_hf_read(dev)
+ | B43_HF_TSSIRPSMW);
+ }
+ B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */
+ if (phy->radio_rev == 8) {
+ b43_radio_write16(dev, 0x51, 0);
+ b43_radio_write16(dev, 0x52, 0x40);
+ b43_radio_write16(dev, 0x53, 0xB7);
+ b43_radio_write16(dev, 0x54, 0x98);
+ b43_radio_write16(dev, 0x5A, 0x88);
+ b43_radio_write16(dev, 0x5B, 0x6B);
+ b43_radio_write16(dev, 0x5C, 0x0F);
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+ b43_radio_write16(dev, 0x5D, 0xFA);
+ b43_radio_write16(dev, 0x5E, 0xD8);
+ } else {
+ b43_radio_write16(dev, 0x5D, 0xF5);
+ b43_radio_write16(dev, 0x5E, 0xB8);
+ }
+ b43_radio_write16(dev, 0x0073, 0x0003);
+ b43_radio_write16(dev, 0x007D, 0x00A8);
+ b43_radio_write16(dev, 0x007C, 0x0001);
+ b43_radio_write16(dev, 0x007E, 0x0008);
+ }
+ val = 0x1E1F;
+ for (offset = 0x0088; offset < 0x0098; offset++) {
+ b43_phy_write(dev, offset, val);
+ val -= 0x0202;
+ }
+ val = 0x3E3F;
+ for (offset = 0x0098; offset < 0x00A8; offset++) {
+ b43_phy_write(dev, offset, val);
+ val -= 0x0202;
+ }
+ val = 0x2120;
+ for (offset = 0x00A8; offset < 0x00C8; offset++) {
+ b43_phy_write(dev, offset, (val & 0x3F3F));
+ val += 0x0202;
+ }
+ if (phy->type == B43_PHYTYPE_G) {
+ b43_radio_write16(dev, 0x007A,
+ b43_radio_read16(dev, 0x007A) | 0x0020);
+ b43_radio_write16(dev, 0x0051,
+ b43_radio_read16(dev, 0x0051) | 0x0004);
+ b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100);
+ b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000);
+ b43_phy_write(dev, 0x5B, 0);
+ b43_phy_write(dev, 0x5C, 0);
+ }
+
+ old_channel = phy->channel;
+ if (old_channel >= 8)
+ b43_gphy_channel_switch(dev, 1, 0);
+ else
+ b43_gphy_channel_switch(dev, 13, 0);
+
+ b43_radio_write16(dev, 0x0050, 0x0020);
+ b43_radio_write16(dev, 0x0050, 0x0023);
+ udelay(40);
+ if (phy->radio_rev < 6 || phy->radio_rev == 8) {
+ b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C)
+ | 0x0002));
+ b43_radio_write16(dev, 0x50, 0x20);
+ }
+ if (phy->radio_rev <= 2) {
+ b43_radio_write16(dev, 0x7C, 0x20);
+ b43_radio_write16(dev, 0x5A, 0x70);
+ b43_radio_write16(dev, 0x5B, 0x7B);
+ b43_radio_write16(dev, 0x5C, 0xB0);
+ }
+ b43_radio_write16(dev, 0x007A,
+ (b43_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007);
+
+ b43_gphy_channel_switch(dev, old_channel, 0);
- if (frequency < 5091)
- value = 0x0040;
- else if (frequency < 5321)
- value = 0x0000;
- else if (frequency < 5806)
- value = 0x0080;
+ b43_phy_write(dev, 0x0014, 0x0200);
+ if (phy->radio_rev >= 6)
+ b43_phy_write(dev, 0x2A, 0x88C2);
else
- value = 0x0040;
+ b43_phy_write(dev, 0x2A, 0x8AC0);
+ b43_phy_write(dev, 0x0038, 0x0668);
+ b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);
+ if (phy->radio_rev <= 5) {
+ b43_phy_write(dev, 0x5D, (b43_phy_read(dev, 0x5D)
+ & 0xFF80) | 0x0003);
+ }
+ if (phy->radio_rev <= 2)
+ b43_radio_write16(dev, 0x005D, 0x000D);
- return value;
+ if (phy->analog == 4) {
+ b43_write16(dev, 0x3E4, 9);
+ b43_phy_write(dev, 0x61, b43_phy_read(dev, 0x61)
+ & 0x0FFF);
+ } else {
+ b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0)
+ | 0x0004);
+ }
+ if (phy->type == B43_PHYTYPE_B)
+ B43_WARN_ON(1);
+ else if (phy->type == B43_PHYTYPE_G)
+ b43_write16(dev, 0x03E6, 0x0);
}
-void b43_radio_set_tx_iq(struct b43_wldev *dev)
+static void b43_calc_loopback_gain(struct b43_wldev *dev)
{
- static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
- static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
- u16 tmp = b43_radio_read16(dev, 0x001E);
- int i, j;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ u16 backup_phy[16] = { 0 };
+ u16 backup_radio[3];
+ u16 backup_bband;
+ u16 i, j, loop_i_max;
+ u16 trsw_rx;
+ u16 loop1_outer_done, loop1_inner_done;
- for (i = 0; i < 5; i++) {
- for (j = 0; j < 5; j++) {
- if (tmp == (data_high[i] << 4 | data_low[j])) {
- b43_phy_write(dev, 0x0069,
- (i - j) << 8 | 0x00C0);
- return;
+ backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0);
+ backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
+ backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER);
+ backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+ if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
+ backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);
+ backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
+ }
+ backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A));
+ backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59));
+ backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58));
+ backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A));
+ backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03));
+ backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);
+ backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);
+ backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B));
+ backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);
+ backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
+ backup_bband = gphy->bbatt.att;
+ backup_radio[0] = b43_radio_read16(dev, 0x52);
+ backup_radio[1] = b43_radio_read16(dev, 0x43);
+ backup_radio[2] = b43_radio_read16(dev, 0x7A);
+
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) & 0x3FFF);
+ b43_phy_write(dev, B43_PHY_CCKBBANDCFG,
+ b43_phy_read(dev, B43_PHY_CCKBBANDCFG) | 0x8000);
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER) | 0x0002);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFD);
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER) | 0x0001);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFE);
+ if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
+ b43_phy_write(dev, B43_PHY_ANALOGOVER,
+ b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0001);
+ b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
+ b43_phy_read(dev,
+ B43_PHY_ANALOGOVERVAL) & 0xFFFE);
+ b43_phy_write(dev, B43_PHY_ANALOGOVER,
+ b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0002);
+ b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
+ b43_phy_read(dev,
+ B43_PHY_ANALOGOVERVAL) & 0xFFFD);
+ }
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER) | 0x000C);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL) | 0x000C);
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER) | 0x0030);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ (b43_phy_read(dev, B43_PHY_RFOVERVAL)
+ & 0xFFCF) | 0x10);
+
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
+
+ b43_phy_write(dev, B43_PHY_CCK(0x0A),
+ b43_phy_read(dev, B43_PHY_CCK(0x0A)) | 0x2000);
+ if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
+ b43_phy_write(dev, B43_PHY_ANALOGOVER,
+ b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004);
+ b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
+ b43_phy_read(dev,
+ B43_PHY_ANALOGOVERVAL) & 0xFFFB);
+ }
+ b43_phy_write(dev, B43_PHY_CCK(0x03),
+ (b43_phy_read(dev, B43_PHY_CCK(0x03))
+ & 0xFF9F) | 0x40);
+
+ if (phy->radio_rev == 8) {
+ b43_radio_write16(dev, 0x43, 0x000F);
+ } else {
+ b43_radio_write16(dev, 0x52, 0);
+ b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
+ & 0xFFF0) | 0x9);
+ }
+ b43_gphy_set_baseband_attenuation(dev, 11);
+
+ if (phy->rev >= 3)
+ b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
+ else
+ b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
+ b43_phy_write(dev, B43_PHY_LO_CTL, 0);
+
+ b43_phy_write(dev, B43_PHY_CCK(0x2B),
+ (b43_phy_read(dev, B43_PHY_CCK(0x2B))
+ & 0xFFC0) | 0x01);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B),
+ (b43_phy_read(dev, B43_PHY_CCK(0x2B))
+ & 0xC0FF) | 0x800);
+
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER) | 0x0100);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF);
+
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+ if (phy->rev >= 7) {
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ b43_phy_read(dev, B43_PHY_RFOVER)
+ | 0x0800);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL)
+ | 0x8000);
+ }
+ }
+ b43_radio_write16(dev, 0x7A, b43_radio_read16(dev, 0x7A)
+ & 0x00F7);
+
+ j = 0;
+ loop_i_max = (phy->radio_rev == 8) ? 15 : 9;
+ for (i = 0; i < loop_i_max; i++) {
+ for (j = 0; j < 16; j++) {
+ b43_radio_write16(dev, 0x43, i);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ (b43_phy_read(dev, B43_PHY_RFOVERVAL)
+ & 0xF0FF) | (j << 8));
+ b43_phy_write(dev, B43_PHY_PGACTL,
+ (b43_phy_read(dev, B43_PHY_PGACTL)
+ & 0x0FFF) | 0xA000);
+ b43_phy_write(dev, B43_PHY_PGACTL,
+ b43_phy_read(dev, B43_PHY_PGACTL)
+ | 0xF000);
+ udelay(20);
+ if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
+ goto exit_loop1;
+ }
+ }
+ exit_loop1:
+ loop1_outer_done = i;
+ loop1_inner_done = j;
+ if (j >= 8) {
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ b43_phy_read(dev, B43_PHY_RFOVERVAL)
+ | 0x30);
+ trsw_rx = 0x1B;
+ for (j = j - 8; j < 16; j++) {
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ (b43_phy_read(dev, B43_PHY_RFOVERVAL)
+ & 0xF0FF) | (j << 8));
+ b43_phy_write(dev, B43_PHY_PGACTL,
+ (b43_phy_read(dev, B43_PHY_PGACTL)
+ & 0x0FFF) | 0xA000);
+ b43_phy_write(dev, B43_PHY_PGACTL,
+ b43_phy_read(dev, B43_PHY_PGACTL)
+ | 0xF000);
+ udelay(20);
+ trsw_rx -= 3;
+ if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
+ goto exit_loop2;
+ }
+ } else
+ trsw_rx = 0x18;
+ exit_loop2:
+
+ if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
+ b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);
+ b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);
+ }
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]);
+ b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]);
+ b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]);
+ b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);
+ b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]);
+ b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);
+
+ b43_gphy_set_baseband_attenuation(dev, backup_bband);
+
+ b43_radio_write16(dev, 0x52, backup_radio[0]);
+ b43_radio_write16(dev, 0x43, backup_radio[1]);
+ b43_radio_write16(dev, 0x7A, backup_radio[2]);
+
+ b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003);
+ udelay(10);
+ b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]);
+ b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]);
+ b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]);
+
+ gphy->max_lb_gain =
+ ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
+ gphy->trsw_rx_gain = trsw_rx * 2;
+}
+
+static void b43_hardware_pctl_early_init(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (!b43_has_hardware_pctl(dev)) {
+ b43_phy_write(dev, 0x047A, 0xC111);
+ return;
+ }
+
+ b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF);
+ b43_phy_write(dev, 0x002F, 0x0202);
+ b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002);
+ b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000);
+ if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
+ b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
+ & 0xFF0F) | 0x0010);
+ b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
+ | 0x8000);
+ b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
+ & 0xFFC0) | 0x0010);
+ b43_phy_write(dev, 0x002E, 0xC07F);
+ b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
+ | 0x0400);
+ } else {
+ b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
+ | 0x0200);
+ b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036)
+ | 0x0400);
+ b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D)
+ & 0x7FFF);
+ b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F)
+ & 0xFFFE);
+ b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E)
+ & 0xFFC0) | 0x0010);
+ b43_phy_write(dev, 0x002E, 0xC07F);
+ b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A)
+ & 0xFF0F) | 0x0010);
+ }
+}
+
+/* Hardware power control for G-PHY */
+static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+
+ if (!b43_has_hardware_pctl(dev)) {
+ /* No hardware power control */
+ b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL);
+ return;
+ }
+
+ b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0)
+ | (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));
+ b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00)
+ | (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));
+ b43_gphy_tssi_power_lt_init(dev);
+ b43_gphy_gain_lt_init(dev);
+ b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF);
+ b43_phy_write(dev, 0x0014, 0x0000);
+
+ B43_WARN_ON(phy->rev < 6);
+ b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
+ | 0x0800);
+ b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478)
+ & 0xFEFF);
+ b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801)
+ & 0xFFBF);
+
+ b43_gphy_dc_lt_init(dev, 1);
+
+ /* Enable hardware pctl in firmware. */
+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);
+}
+
+/* Intialize B/G PHY power control */
+static void b43_phy_init_pctl(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_rfatt old_rfatt;
+ struct b43_bbatt old_bbatt;
+ u8 old_tx_control = 0;
+
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+ if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
+ (bus->boardinfo.type == SSB_BOARD_BU4306))
+ return;
+
+ b43_phy_write(dev, 0x0028, 0x8018);
+
+ /* This does something with the Analog... */
+ b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0)
+ & 0xFFDF);
+
+ if (!phy->gmode)
+ return;
+ b43_hardware_pctl_early_init(dev);
+ if (gphy->cur_idle_tssi == 0) {
+ if (phy->radio_ver == 0x2050 && phy->analog == 0) {
+ b43_radio_write16(dev, 0x0076,
+ (b43_radio_read16(dev, 0x0076)
+ & 0x00F7) | 0x0084);
+ } else {
+ struct b43_rfatt rfatt;
+ struct b43_bbatt bbatt;
+
+ memcpy(&old_rfatt, &gphy->rfatt, sizeof(old_rfatt));
+ memcpy(&old_bbatt, &gphy->bbatt, sizeof(old_bbatt));
+ old_tx_control = gphy->tx_control;
+
+ bbatt.att = 11;
+ if (phy->radio_rev == 8) {
+ rfatt.att = 15;
+ rfatt.with_padmix = 1;
+ } else {
+ rfatt.att = 9;
+ rfatt.with_padmix = 0;
}
+ b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
+ }
+ b43_dummy_transmission(dev);
+ gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
+ if (B43_DEBUG) {
+ /* Current-Idle-TSSI sanity check. */
+ if (abs(gphy->cur_idle_tssi - gphy->tgt_idle_tssi) >= 20) {
+ b43dbg(dev->wl,
+ "!WARNING! Idle-TSSI phy->cur_idle_tssi "
+ "measuring failed. (cur=%d, tgt=%d). Disabling TX power "
+ "adjustment.\n", gphy->cur_idle_tssi,
+ gphy->tgt_idle_tssi);
+ gphy->cur_idle_tssi = 0;
+ }
+ }
+ if (phy->radio_ver == 0x2050 && phy->analog == 0) {
+ b43_radio_write16(dev, 0x0076,
+ b43_radio_read16(dev, 0x0076)
+ & 0xFF7B);
+ } else {
+ b43_set_txpower_g(dev, &old_bbatt,
+ &old_rfatt, old_tx_control);
}
}
+ b43_hardware_pctl_init_gphy(dev);
+ b43_shm_clear_tssi(dev);
}
-int b43_radio_selectchannel(struct b43_wldev *dev,
- u8 channel, int synthetic_pu_workaround)
+static void b43_phy_initg(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- u16 r8, tmp;
- u16 freq;
- u16 channelcookie, savedcookie;
- int err = 0;
-
- if (channel == 0xFF) {
- switch (phy->type) {
- case B43_PHYTYPE_A:
- channel = B43_DEFAULT_CHANNEL_A;
- break;
- case B43_PHYTYPE_B:
- case B43_PHYTYPE_G:
- channel = B43_DEFAULT_CHANNEL_BG;
- break;
- case B43_PHYTYPE_N:
- //FIXME check if we are on 2.4GHz or 5GHz and set a default channel.
- channel = 1;
- break;
- default:
- B43_WARN_ON(1);
+ struct b43_phy_g *gphy = phy->g;
+ u16 tmp;
+
+ if (phy->rev == 1)
+ b43_phy_initb5(dev);
+ else
+ b43_phy_initb6(dev);
+
+ if (phy->rev >= 2 || phy->gmode)
+ b43_phy_inita(dev);
+
+ if (phy->rev >= 2) {
+ b43_phy_write(dev, B43_PHY_ANALOGOVER, 0);
+ b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0);
+ }
+ if (phy->rev == 2) {
+ b43_phy_write(dev, B43_PHY_RFOVER, 0);
+ b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
+ }
+ if (phy->rev > 5) {
+ b43_phy_write(dev, B43_PHY_RFOVER, 0x400);
+ b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
+ }
+ if (phy->gmode || phy->rev >= 2) {
+ tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM);
+ tmp &= B43_PHYVER_VERSION;
+ if (tmp == 3 || tmp == 5) {
+ b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816);
+ b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006);
}
+ if (tmp == 5) {
+ b43_phy_write(dev, B43_PHY_OFDM(0xCC),
+ (b43_phy_read(dev, B43_PHY_OFDM(0xCC))
+ & 0x00FF) | 0x1F00);
+ }
+ }
+ if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
+ b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78);
+ if (phy->radio_rev == 8) {
+ b43_phy_write(dev, B43_PHY_EXTG(0x01),
+ b43_phy_read(dev, B43_PHY_EXTG(0x01))
+ | 0x80);
+ b43_phy_write(dev, B43_PHY_OFDM(0x3E),
+ b43_phy_read(dev, B43_PHY_OFDM(0x3E))
+ | 0x4);
+ }
+ if (has_loopback_gain(phy))
+ b43_calc_loopback_gain(dev);
+
+ if (phy->radio_rev != 8) {
+ if (gphy->initval == 0xFFFF)
+ gphy->initval = b43_radio_init2050(dev);
+ else
+ b43_radio_write16(dev, 0x0078, gphy->initval);
+ }
+ b43_lo_g_init(dev);
+ if (has_tx_magnification(phy)) {
+ b43_radio_write16(dev, 0x52,
+ (b43_radio_read16(dev, 0x52) & 0xFF00)
+ | gphy->lo_control->tx_bias | gphy->
+ lo_control->tx_magn);
+ } else {
+ b43_radio_write16(dev, 0x52,
+ (b43_radio_read16(dev, 0x52) & 0xFFF0)
+ | gphy->lo_control->tx_bias);
+ }
+ if (phy->rev >= 6) {
+ b43_phy_write(dev, B43_PHY_CCK(0x36),
+ (b43_phy_read(dev, B43_PHY_CCK(0x36))
+ & 0x0FFF) | (gphy->lo_control->
+ tx_bias << 12));
+ }
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
+ else
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
+ if (phy->rev < 2)
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
+ else
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
+ if (phy->gmode || phy->rev >= 2) {
+ b43_lo_g_adjust(dev);
+ b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- /* First we set the channel radio code to prevent the
- * firmware from sending ghost packets.
- */
- channelcookie = channel;
- if (0 /*FIXME on 5Ghz */)
- channelcookie |= 0x100;
- //FIXME set 40Mhz flag if required
- savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
-
- switch (phy->type) {
- case B43_PHYTYPE_A:
- if (channel > 200) {
- err = -EINVAL;
- goto out;
+ if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ /* The specs state to update the NRSSI LT with
+ * the value 0x7FFFFFFF here. I think that is some weird
+ * compiler optimization in the original driver.
+ * Essentially, what we do here is resetting all NRSSI LT
+ * entries to -32 (see the clamp_val() in nrssi_hw_update())
+ */
+ b43_nrssi_hw_update(dev, 0xFFFF); //FIXME?
+ b43_calc_nrssi_threshold(dev);
+ } else if (phy->gmode || phy->rev >= 2) {
+ if (gphy->nrssi[0] == -1000) {
+ B43_WARN_ON(gphy->nrssi[1] != -1000);
+ b43_calc_nrssi_slope(dev);
+ } else
+ b43_calc_nrssi_threshold(dev);
+ }
+ if (phy->radio_rev == 8)
+ b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230);
+ b43_phy_init_pctl(dev);
+ /* FIXME: The spec says in the following if, the 0 should be replaced
+ 'if OFDM may not be used in the current locale'
+ but OFDM is legal everywhere */
+ if ((dev->dev->bus->chip_id == 0x4306
+ && dev->dev->bus->chip_package == 2) || 0) {
+ b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0)
+ & 0xBFFF);
+ b43_phy_write(dev, B43_PHY_OFDM(0xC3),
+ b43_phy_read(dev, B43_PHY_OFDM(0xC3))
+ & 0x7FFF);
+ }
+}
+
+void b43_gphy_channel_switch(struct b43_wldev *dev,
+ unsigned int channel,
+ bool synthetic_pu_workaround)
+{
+ if (synthetic_pu_workaround)
+ b43_synth_pu_workaround(dev, channel);
+
+ b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
+
+ if (channel == 14) {
+ if (dev->dev->bus->sprom.country_code ==
+ SSB_SPROM1CCODE_JAPAN)
+ b43_hf_write(dev,
+ b43_hf_read(dev) & ~B43_HF_ACPR);
+ else
+ b43_hf_write(dev,
+ b43_hf_read(dev) | B43_HF_ACPR);
+ b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+ b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+ | (1 << 11));
+ } else {
+ b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+ b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+ & 0xF7BF);
+ }
+}
+
+static void default_baseband_attenuation(struct b43_wldev *dev,
+ struct b43_bbatt *bb)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
+ bb->att = 0;
+ else
+ bb->att = 2;
+}
+
+static void default_radio_attenuation(struct b43_wldev *dev,
+ struct b43_rfatt *rf)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ struct b43_phy *phy = &dev->phy;
+
+ rf->with_padmix = 0;
+
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
+ bus->boardinfo.type == SSB_BOARD_BCM4309G) {
+ if (bus->boardinfo.rev < 0x43) {
+ rf->att = 2;
+ return;
+ } else if (bus->boardinfo.rev < 0x51) {
+ rf->att = 3;
+ return;
}
- freq = channel2freq_a(channel);
-
- r8 = b43_radio_read16(dev, 0x0008);
- b43_write16(dev, 0x03F0, freq);
- b43_radio_write16(dev, 0x0008, r8);
-
- //TODO: write max channel TX power? to Radio 0x2D
- tmp = b43_radio_read16(dev, 0x002E);
- tmp &= 0x0080;
- //TODO: OR tmp with the Power out estimation for this channel?
- b43_radio_write16(dev, 0x002E, tmp);
-
- if (freq >= 4920 && freq <= 5500) {
- /*
- * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
- * = (freq * 0.025862069
- */
- r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+ }
+
+ if (phy->type == B43_PHYTYPE_A) {
+ rf->att = 0x60;
+ return;
+ }
+
+ switch (phy->radio_ver) {
+ case 0x2053:
+ switch (phy->radio_rev) {
+ case 1:
+ rf->att = 6;
+ return;
}
- b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
- b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
- b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
- b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022)
- & 0x000F) | (r8 << 4));
- b43_radio_write16(dev, 0x002A, (r8 << 4));
- b43_radio_write16(dev, 0x002B, (r8 << 4));
- b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008)
- & 0x00F0) | (r8 << 4));
- b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029)
- & 0xFF0F) | 0x00B0);
- b43_radio_write16(dev, 0x0035, 0x00AA);
- b43_radio_write16(dev, 0x0036, 0x0085);
- b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A)
- & 0xFF20) |
- freq_r3A_value(freq));
- b43_radio_write16(dev, 0x003D,
- b43_radio_read16(dev, 0x003D) & 0x00FF);
- b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081)
- & 0xFF7F) | 0x0080);
- b43_radio_write16(dev, 0x0035,
- b43_radio_read16(dev, 0x0035) & 0xFFEF);
- b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035)
- & 0xFFEF) | 0x0010);
- b43_radio_set_tx_iq(dev);
- //TODO: TSSI2dbm workaround
- b43_phy_xmitpower(dev); //FIXME correct?
break;
- case B43_PHYTYPE_G:
- if ((channel < 1) || (channel > 14)) {
- err = -EINVAL;
- goto out;
+ case 0x2050:
+ switch (phy->radio_rev) {
+ case 0:
+ rf->att = 5;
+ return;
+ case 1:
+ if (phy->type == B43_PHYTYPE_G) {
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
+ && bus->boardinfo.type == SSB_BOARD_BCM4309G
+ && bus->boardinfo.rev >= 30)
+ rf->att = 3;
+ else if (bus->boardinfo.vendor ==
+ SSB_BOARDVENDOR_BCM
+ && bus->boardinfo.type ==
+ SSB_BOARD_BU4306)
+ rf->att = 3;
+ else
+ rf->att = 1;
+ } else {
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
+ && bus->boardinfo.type == SSB_BOARD_BCM4309G
+ && bus->boardinfo.rev >= 30)
+ rf->att = 7;
+ else
+ rf->att = 6;
+ }
+ return;
+ case 2:
+ if (phy->type == B43_PHYTYPE_G) {
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
+ && bus->boardinfo.type == SSB_BOARD_BCM4309G
+ && bus->boardinfo.rev >= 30)
+ rf->att = 3;
+ else if (bus->boardinfo.vendor ==
+ SSB_BOARDVENDOR_BCM
+ && bus->boardinfo.type ==
+ SSB_BOARD_BU4306)
+ rf->att = 5;
+ else if (bus->chip_id == 0x4320)
+ rf->att = 4;
+ else
+ rf->att = 3;
+ } else
+ rf->att = 6;
+ return;
+ case 3:
+ rf->att = 5;
+ return;
+ case 4:
+ case 5:
+ rf->att = 1;
+ return;
+ case 6:
+ case 7:
+ rf->att = 5;
+ return;
+ case 8:
+ rf->att = 0xA;
+ rf->with_padmix = 1;
+ return;
+ case 9:
+ default:
+ rf->att = 5;
+ return;
}
+ }
+ rf->att = 5;
+}
- if (synthetic_pu_workaround)
- b43_synth_pu_workaround(dev, channel);
+static u16 default_tx_control(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
- b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
+ if (phy->radio_ver != 0x2050)
+ return 0;
+ if (phy->radio_rev == 1)
+ return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX;
+ if (phy->radio_rev < 6)
+ return B43_TXCTL_PA2DB;
+ if (phy->radio_rev == 8)
+ return B43_TXCTL_TXMIX;
+ return 0;
+}
- if (channel == 14) {
- if (dev->dev->bus->sprom.country_code ==
- SSB_SPROM1CCODE_JAPAN)
- b43_hf_write(dev,
- b43_hf_read(dev) & ~B43_HF_ACPR);
- else
- b43_hf_write(dev,
- b43_hf_read(dev) | B43_HF_ACPR);
- b43_write16(dev, B43_MMIO_CHANNEL_EXT,
- b43_read16(dev, B43_MMIO_CHANNEL_EXT)
- | (1 << 11));
- } else {
- b43_write16(dev, B43_MMIO_CHANNEL_EXT,
- b43_read16(dev, B43_MMIO_CHANNEL_EXT)
- & 0xF7BF);
+static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ u8 ret = 0;
+ u16 saved, rssi, temp;
+ int i, j = 0;
+
+ saved = b43_phy_read(dev, 0x0403);
+ b43_switch_channel(dev, channel);
+ b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
+ if (gphy->aci_hw_rssi)
+ rssi = b43_phy_read(dev, 0x048A) & 0x3F;
+ else
+ rssi = saved & 0x3F;
+ /* clamp temp to signed 5bit */
+ if (rssi > 32)
+ rssi -= 64;
+ for (i = 0; i < 100; i++) {
+ temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F;
+ if (temp > 32)
+ temp -= 64;
+ if (temp < rssi)
+ j++;
+ if (j >= 20)
+ ret = 1;
+ }
+ b43_phy_write(dev, 0x0403, saved);
+
+ return ret;
+}
+
+static u8 b43_gphy_aci_scan(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ u8 ret[13];
+ unsigned int channel = phy->channel;
+ unsigned int i, j, start, end;
+
+ if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))
+ return 0;
+
+ b43_phy_lock(dev);
+ b43_radio_lock(dev);
+ b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
+ b43_phy_write(dev, B43_PHY_G_CRS,
+ b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF);
+ b43_set_all_gains(dev, 3, 8, 1);
+
+ start = (channel - 5 > 0) ? channel - 5 : 1;
+ end = (channel + 5 < 14) ? channel + 5 : 13;
+
+ for (i = start; i <= end; i++) {
+ if (abs(channel - i) > 2)
+ ret[i - 1] = b43_gphy_aci_detect(dev, i);
+ }
+ b43_switch_channel(dev, channel);
+ b43_phy_write(dev, 0x0802,
+ (b43_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003);
+ b43_phy_write(dev, 0x0403, b43_phy_read(dev, 0x0403) & 0xFFF8);
+ b43_phy_write(dev, B43_PHY_G_CRS,
+ b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000);
+ b43_set_original_gains(dev);
+ for (i = 0; i < 13; i++) {
+ if (!ret[i])
+ continue;
+ end = (i + 5 < 13) ? i + 5 : 13;
+ for (j = i; j < end; j++)
+ ret[j] = 1;
+ }
+ b43_radio_unlock(dev);
+ b43_phy_unlock(dev);
+
+ return ret[channel - 1];
+}
+
+static s32 b43_tssi2dbm_ad(s32 num, s32 den)
+{
+ if (num < 0)
+ return num / den;
+ else
+ return (num + den / 2) / den;
+}
+
+static s8 b43_tssi2dbm_entry(s8 entry[], u8 index,
+ s16 pab0, s16 pab1, s16 pab2)
+{
+ s32 m1, m2, f = 256, q, delta;
+ s8 i = 0;
+
+ m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+ m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+ do {
+ if (i > 15)
+ return -EINVAL;
+ q = b43_tssi2dbm_ad(f * 4096 -
+ b43_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+ delta = abs(q - f);
+ f = q;
+ i++;
+ } while (delta >= 2);
+ entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+ return 0;
+}
+
+u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,
+ s16 pab0, s16 pab1, s16 pab2)
+{
+ unsigned int i;
+ u8 *tab;
+ int err;
+
+ tab = kmalloc(64, GFP_KERNEL);
+ if (!tab) {
+ b43err(dev->wl, "Could not allocate memory "
+ "for tssi2dbm table\n");
+ return NULL;
+ }
+ for (i = 0; i < 64; i++) {
+ err = b43_tssi2dbm_entry(tab, i, pab0, pab1, pab2);
+ if (err) {
+ b43err(dev->wl, "Could not generate "
+ "tssi2dBm table\n");
+ kfree(tab);
+ return NULL;
}
- break;
- case B43_PHYTYPE_N:
- err = b43_nphy_selectchannel(dev, channel);
- if (err)
- goto out;
- break;
- default:
- B43_WARN_ON(1);
}
- phy->channel = channel;
- /* Wait for the radio to tune to the channel and stabilize. */
- msleep(8);
-out:
- if (err) {
- b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_CHAN, savedcookie);
+ return tab;
+}
+
+/* Initialise the TSSI->dBm lookup table */
+static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ s16 pab0, pab1, pab2;
+
+ pab0 = (s16) (dev->dev->bus->sprom.pa0b0);
+ pab1 = (s16) (dev->dev->bus->sprom.pa0b1);
+ pab2 = (s16) (dev->dev->bus->sprom.pa0b2);
+
+ B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) &&
+ (phy->radio_ver != 0x2050)); /* Not supported anymore */
+
+ gphy->dyn_tssi_tbl = 0;
+
+ if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+ pab0 != -1 && pab1 != -1 && pab2 != -1) {
+ /* The pabX values are set in SPROM. Use them. */
+ if ((s8) dev->dev->bus->sprom.itssi_bg != 0 &&
+ (s8) dev->dev->bus->sprom.itssi_bg != -1) {
+ gphy->tgt_idle_tssi =
+ (s8) (dev->dev->bus->sprom.itssi_bg);
+ } else
+ gphy->tgt_idle_tssi = 62;
+ gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
+ pab1, pab2);
+ if (!gphy->tssi2dbm)
+ return -ENOMEM;
+ gphy->dyn_tssi_tbl = 1;
+ } else {
+ /* pabX values not set in SPROM. */
+ gphy->tgt_idle_tssi = 52;
+ gphy->tssi2dbm = b43_tssi2dbm_g_table;
}
+
+ return 0;
+}
+
+static int b43_gphy_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_g *gphy;
+ struct b43_txpower_lo_control *lo;
+ int err;
+
+ gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);
+ if (!gphy) {
+ err = -ENOMEM;
+ goto error;
+ }
+ dev->phy.g = gphy;
+
+ lo = kzalloc(sizeof(*lo), GFP_KERNEL);
+ if (!lo) {
+ err = -ENOMEM;
+ goto err_free_gphy;
+ }
+ gphy->lo_control = lo;
+
+ err = b43_gphy_init_tssi2dbm_table(dev);
+ if (err)
+ goto err_free_lo;
+
+ return 0;
+
+err_free_lo:
+ kfree(lo);
+err_free_gphy:
+ kfree(gphy);
+error:
return err;
}
-void b43_radio_turn_on(struct b43_wldev *dev)
+static void b43_gphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- int err;
- u8 channel;
+ struct b43_phy_g *gphy = phy->g;
+ const void *tssi2dbm;
+ int tgt_idle_tssi;
+ struct b43_txpower_lo_control *lo;
+ unsigned int i;
+
+ /* tssi2dbm table is constant, so it is initialized at alloc time.
+ * Save a copy of the pointer. */
+ tssi2dbm = gphy->tssi2dbm;
+ tgt_idle_tssi = gphy->tgt_idle_tssi;
+ /* Save the LO pointer. */
+ lo = gphy->lo_control;
+
+ /* Zero out the whole PHY structure. */
+ memset(gphy, 0, sizeof(*gphy));
+
+ /* Restore pointers. */
+ gphy->tssi2dbm = tssi2dbm;
+ gphy->tgt_idle_tssi = tgt_idle_tssi;
+ gphy->lo_control = lo;
+
+ memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig));
+
+ /* NRSSI */
+ for (i = 0; i < ARRAY_SIZE(gphy->nrssi); i++)
+ gphy->nrssi[i] = -1000;
+ for (i = 0; i < ARRAY_SIZE(gphy->nrssi_lt); i++)
+ gphy->nrssi_lt[i] = i;
+
+ gphy->lofcal = 0xFFFF;
+ gphy->initval = 0xFFFF;
+
+ gphy->interfmode = B43_INTERFMODE_NONE;
+
+ /* OFDM-table address caching. */
+ gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
+
+ gphy->average_tssi = 0xFF;
+
+ /* Local Osciallator structure */
+ lo->tx_bias = 0xFF;
+ INIT_LIST_HEAD(&lo->calib_list);
+}
+
+static void b43_gphy_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+
+ kfree(gphy->lo_control);
+
+ if (gphy->dyn_tssi_tbl)
+ kfree(gphy->tssi2dbm);
+ gphy->dyn_tssi_tbl = 0;
+ gphy->tssi2dbm = NULL;
+
+ kfree(gphy);
+ dev->phy.g = NULL;
+}
+
+static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ struct b43_txpower_lo_control *lo = gphy->lo_control;
+
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+ default_baseband_attenuation(dev, &gphy->bbatt);
+ default_radio_attenuation(dev, &gphy->rfatt);
+ gphy->tx_control = (default_tx_control(dev) << 4);
+ generate_rfatt_list(dev, &lo->rfatt_list);
+ generate_bbatt_list(dev, &lo->bbatt_list);
+
+ /* Commit previous writes */
+ b43_read32(dev, B43_MMIO_MACCTL);
+
+ if (phy->rev == 1) {
+ /* Workaround: Temporarly disable gmode through the early init
+ * phase, as the gmode stuff is not needed for phy rev 1 */
+ phy->gmode = 0;
+ b43_wireless_core_reset(dev, 0);
+ b43_phy_initg(dev);
+ phy->gmode = 1;
+ b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ }
+
+ return 0;
+}
+
+static int b43_gphy_op_init(struct b43_wldev *dev)
+{
+ b43_phy_initg(dev);
+
+ return 0;
+}
+
+static void b43_gphy_op_exit(struct b43_wldev *dev)
+{
+ b43_lo_g_cleanup(dev);
+}
+
+static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+ /* G-PHY needs 0x80 for read access. */
+ reg |= 0x80;
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev)
+{
+ return (dev->phy.rev >= 6);
+}
+
+static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
+ enum rfkill_state state)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ unsigned int channel;
might_sleep();
- if (phy->radio_on)
- return;
+ if (state == RFKILL_STATE_UNBLOCKED) {
+ /* Turn radio ON */
+ if (phy->radio_on)
+ return;
- switch (phy->type) {
- case B43_PHYTYPE_A:
- b43_radio_write16(dev, 0x0004, 0x00C0);
- b43_radio_write16(dev, 0x0005, 0x0008);
- b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) & 0xFFF7);
- b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) & 0xFFF7);
- b43_radio_init2060(dev);
- break;
- case B43_PHYTYPE_B:
- case B43_PHYTYPE_G:
b43_phy_write(dev, 0x0015, 0x8000);
b43_phy_write(dev, 0x0015, 0xCC00);
b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
- if (phy->radio_off_context.valid) {
+ if (gphy->radio_off_context.valid) {
/* Restore the RFover values. */
b43_phy_write(dev, B43_PHY_RFOVER,
- phy->radio_off_context.rfover);
+ gphy->radio_off_context.rfover);
b43_phy_write(dev, B43_PHY_RFOVERVAL,
- phy->radio_off_context.rfoverval);
- phy->radio_off_context.valid = 0;
+ gphy->radio_off_context.rfoverval);
+ gphy->radio_off_context.valid = 0;
}
channel = phy->channel;
- err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1);
- err |= b43_radio_selectchannel(dev, channel, 0);
- B43_WARN_ON(err);
- break;
- case B43_PHYTYPE_N:
- b43_nphy_radio_turn_on(dev);
- break;
- default:
- B43_WARN_ON(1);
+ b43_gphy_channel_switch(dev, 6, 1);
+ b43_gphy_channel_switch(dev, channel, 0);
+ } else {
+ /* Turn radio OFF */
+ u16 rfover, rfoverval;
+
+ rfover = b43_phy_read(dev, B43_PHY_RFOVER);
+ rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+ gphy->radio_off_context.rfover = rfover;
+ gphy->radio_off_context.rfoverval = rfoverval;
+ gphy->radio_off_context.valid = 1;
+ b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
}
- phy->radio_on = 1;
}
-void b43_radio_turn_off(struct b43_wldev *dev, bool force)
+static int b43_gphy_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ if ((new_channel < 1) || (new_channel > 14))
+ return -EINVAL;
+ b43_gphy_channel_switch(dev, new_channel, 0);
+
+ return 0;
+}
+
+static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev)
+{
+ return 1; /* Default to channel 1 */
+}
+
+static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{
struct b43_phy *phy = &dev->phy;
+ u64 hf;
+ u16 tmp;
+ int autodiv = 0;
- if (!phy->radio_on && !force)
- return;
+ if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
+ autodiv = 1;
+
+ hf = b43_hf_read(dev);
+ hf &= ~B43_HF_ANTDIVHELP;
+ b43_hf_write(dev, hf);
+
+ tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
+ tmp &= ~B43_PHY_BBANDCFG_RXANT;
+ tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
+ << B43_PHY_BBANDCFG_RXANT_SHIFT;
+ b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
+
+ if (autodiv) {
+ tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
+ if (antenna == B43_ANTENNA_AUTO0)
+ tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
+ else
+ tmp |= B43_PHY_ANTDWELL_AUTODIV1;
+ b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
+ }
+ tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);
+ if (autodiv)
+ tmp |= B43_PHY_ANTWRSETT_ARXDIV;
+ else
+ tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;
+ b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);
+ if (phy->rev >= 2) {
+ tmp = b43_phy_read(dev, B43_PHY_OFDM61);
+ tmp |= B43_PHY_OFDM61_10;
+ b43_phy_write(dev, B43_PHY_OFDM61, tmp);
+
+ tmp =
+ b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK);
+ tmp = (tmp & 0xFF00) | 0x15;
+ b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK,
+ tmp);
+
+ if (phy->rev == 2) {
+ b43_phy_write(dev, B43_PHY_ADIVRELATED,
+ 8);
+ } else {
+ tmp =
+ b43_phy_read(dev,
+ B43_PHY_ADIVRELATED);
+ tmp = (tmp & 0xFF00) | 8;
+ b43_phy_write(dev, B43_PHY_ADIVRELATED,
+ tmp);
+ }
+ }
+ if (phy->rev >= 6)
+ b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);
+
+ hf |= B43_HF_ANTDIVHELP;
+ b43_hf_write(dev, hf);
+}
- switch (phy->type) {
- case B43_PHYTYPE_N:
- b43_nphy_radio_turn_off(dev);
+static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,
+ enum b43_interference_mitigation mode)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ int currentmode;
+
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+ if ((phy->rev == 0) || (!phy->gmode))
+ return -ENODEV;
+
+ gphy->aci_wlan_automatic = 0;
+ switch (mode) {
+ case B43_INTERFMODE_AUTOWLAN:
+ gphy->aci_wlan_automatic = 1;
+ if (gphy->aci_enable)
+ mode = B43_INTERFMODE_MANUALWLAN;
+ else
+ mode = B43_INTERFMODE_NONE;
break;
- case B43_PHYTYPE_A:
- b43_radio_write16(dev, 0x0004, 0x00FF);
- b43_radio_write16(dev, 0x0005, 0x00FB);
- b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008);
- b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
+ case B43_INTERFMODE_NONE:
+ case B43_INTERFMODE_NONWLAN:
+ case B43_INTERFMODE_MANUALWLAN:
break;
- case B43_PHYTYPE_G: {
- u16 rfover, rfoverval;
+ default:
+ return -EINVAL;
+ }
- rfover = b43_phy_read(dev, B43_PHY_RFOVER);
- rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
- if (!force) {
- phy->radio_off_context.rfover = rfover;
- phy->radio_off_context.rfoverval = rfoverval;
- phy->radio_off_context.valid = 1;
+ currentmode = gphy->interfmode;
+ if (currentmode == mode)
+ return 0;
+ if (currentmode != B43_INTERFMODE_NONE)
+ b43_radio_interference_mitigation_disable(dev, currentmode);
+
+ if (mode == B43_INTERFMODE_NONE) {
+ gphy->aci_enable = 0;
+ gphy->aci_hw_rssi = 0;
+ } else
+ b43_radio_interference_mitigation_enable(dev, mode);
+ gphy->interfmode = mode;
+
+ return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+ * This function converts a TSSI value to dBm in Q5.2
+ */
+static s8 b43_gphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
+{
+ struct b43_phy_g *gphy = dev->phy.g;
+ s8 dbm;
+ s32 tmp;
+
+ tmp = (gphy->tgt_idle_tssi - gphy->cur_idle_tssi + tssi);
+ tmp = clamp_val(tmp, 0x00, 0x3F);
+ dbm = gphy->tssi2dbm[tmp];
+
+ return dbm;
+}
+
+static void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
+ int *_bbatt, int *_rfatt)
+{
+ int rfatt = *_rfatt;
+ int bbatt = *_bbatt;
+ struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
+
+ /* Get baseband and radio attenuation values into their permitted ranges.
+ * Radio attenuation affects power level 4 times as much as baseband. */
+
+ /* Range constants */
+ const int rf_min = lo->rfatt_list.min_val;
+ const int rf_max = lo->rfatt_list.max_val;
+ const int bb_min = lo->bbatt_list.min_val;
+ const int bb_max = lo->bbatt_list.max_val;
+
+ while (1) {
+ if (rfatt > rf_max && bbatt > bb_max - 4)
+ break; /* Can not get it into ranges */
+ if (rfatt < rf_min && bbatt < bb_min + 4)
+ break; /* Can not get it into ranges */
+ if (bbatt > bb_max && rfatt > rf_max - 1)
+ break; /* Can not get it into ranges */
+ if (bbatt < bb_min && rfatt < rf_min + 1)
+ break; /* Can not get it into ranges */
+
+ if (bbatt > bb_max) {
+ bbatt -= 4;
+ rfatt += 1;
+ continue;
+ }
+ if (bbatt < bb_min) {
+ bbatt += 4;
+ rfatt -= 1;
+ continue;
+ }
+ if (rfatt > rf_max) {
+ rfatt -= 1;
+ bbatt += 4;
+ continue;
+ }
+ if (rfatt < rf_min) {
+ rfatt += 1;
+ bbatt -= 4;
+ continue;
}
- b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
- b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
break;
}
- default:
- B43_WARN_ON(1);
+
+ *_rfatt = clamp_val(rfatt, rf_min, rf_max);
+ *_bbatt = clamp_val(bbatt, bb_min, bb_max);
+}
+
+static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ int rfatt, bbatt;
+ u8 tx_control;
+
+ spin_lock_irq(&dev->wl->irq_lock);
+
+ /* Calculate the new attenuation values. */
+ bbatt = gphy->bbatt.att;
+ bbatt += gphy->bbatt_delta;
+ rfatt = gphy->rfatt.att;
+ rfatt += gphy->rfatt_delta;
+
+ b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
+ tx_control = gphy->tx_control;
+ if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
+ if (rfatt <= 1) {
+ if (tx_control == 0) {
+ tx_control =
+ B43_TXCTL_PA2DB |
+ B43_TXCTL_TXMIX;
+ rfatt += 2;
+ bbatt += 2;
+ } else if (dev->dev->bus->sprom.
+ boardflags_lo &
+ B43_BFL_PACTRL) {
+ bbatt += 4 * (rfatt - 2);
+ rfatt = 2;
+ }
+ } else if (rfatt > 4 && tx_control) {
+ tx_control = 0;
+ if (bbatt < 3) {
+ rfatt -= 3;
+ bbatt += 2;
+ } else {
+ rfatt -= 2;
+ bbatt -= 2;
+ }
+ }
}
- phy->radio_on = 0;
+ /* Save the control values */
+ gphy->tx_control = tx_control;
+ b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
+ gphy->rfatt.att = rfatt;
+ gphy->bbatt.att = bbatt;
+
+ /* We drop the lock early, so we can sleep during hardware
+ * adjustment. Possible races with op_recalc_txpower are harmless,
+ * as we will be called once again in case we raced. */
+ spin_unlock_irq(&dev->wl->irq_lock);
+
+ if (b43_debug(dev, B43_DBG_XMITPOWER))
+ b43dbg(dev->wl, "Adjusting TX power\n");
+
+ /* Adjust the hardware */
+ b43_phy_lock(dev);
+ b43_radio_lock(dev);
+ b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt,
+ gphy->tx_control);
+ b43_radio_unlock(dev);
+ b43_phy_unlock(dev);
}
+
+static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
+ bool ignore_tssi)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+ unsigned int average_tssi;
+ int cck_result, ofdm_result;
+ int estimated_pwr, desired_pwr, pwr_adjust;
+ int rfatt_delta, bbatt_delta;
+ unsigned int max_pwr;
+
+ /* First get the average TSSI */
+ cck_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_CCK);
+ ofdm_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_OFDM_G);
+ if ((cck_result < 0) && (ofdm_result < 0)) {
+ /* No TSSI information available */
+ if (!ignore_tssi)
+ goto no_adjustment_needed;
+ cck_result = 0;
+ ofdm_result = 0;
+ }
+ if (cck_result < 0)
+ average_tssi = ofdm_result;
+ else if (ofdm_result < 0)
+ average_tssi = cck_result;
+ else
+ average_tssi = (cck_result + ofdm_result) / 2;
+ /* Merge the average with the stored value. */
+ if (likely(gphy->average_tssi != 0xFF))
+ average_tssi = (average_tssi + gphy->average_tssi) / 2;
+ gphy->average_tssi = average_tssi;
+ B43_WARN_ON(average_tssi >= B43_TSSI_MAX);
+
+ /* Estimate the TX power emission based on the TSSI */
+ estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
+
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+ max_pwr = dev->dev->bus->sprom.maxpwr_bg;
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ max_pwr -= 3; /* minus 0.75 */
+ if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
+ b43warn(dev->wl,
+ "Invalid max-TX-power value in SPROM.\n");
+ max_pwr = INT_TO_Q52(20); /* fake it */
+ dev->dev->bus->sprom.maxpwr_bg = max_pwr;
+ }
+
+ /* Get desired power (in Q5.2) */
+ if (phy->desired_txpower < 0)
+ desired_pwr = INT_TO_Q52(0);
+ else
+ desired_pwr = INT_TO_Q52(phy->desired_txpower);
+ /* And limit it. max_pwr already is Q5.2 */
+ desired_pwr = clamp_val(desired_pwr, 0, max_pwr);
+ if (b43_debug(dev, B43_DBG_XMITPOWER)) {
+ b43dbg(dev->wl,
+ "[TX power] current = " Q52_FMT
+ " dBm, desired = " Q52_FMT
+ " dBm, max = " Q52_FMT "\n",
+ Q52_ARG(estimated_pwr),
+ Q52_ARG(desired_pwr),
+ Q52_ARG(max_pwr));
+ }
+
+ /* Calculate the adjustment delta. */
+ pwr_adjust = desired_pwr - estimated_pwr;
+ if (pwr_adjust == 0)
+ goto no_adjustment_needed;
+
+ /* RF attenuation delta. */
+ rfatt_delta = ((pwr_adjust + 7) / 8);
+ /* Lower attenuation => Bigger power output. Negate it. */
+ rfatt_delta = -rfatt_delta;
+
+ /* Baseband attenuation delta. */
+ bbatt_delta = pwr_adjust / 2;
+ /* Lower attenuation => Bigger power output. Negate it. */
+ bbatt_delta = -bbatt_delta;
+ /* RF att affects power level 4 times as much as
+ * Baseband attennuation. Subtract it. */
+ bbatt_delta -= 4 * rfatt_delta;
+
+ if (b43_debug(dev, B43_DBG_XMITPOWER)) {
+ int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust;
+ b43dbg(dev->wl,
+ "[TX power deltas] %s" Q52_FMT " dBm => "
+ "bbatt-delta = %d, rfatt-delta = %d\n",
+ (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm),
+ bbatt_delta, rfatt_delta);
+ }
+ /* So do we finally need to adjust something in hardware? */
+ if ((rfatt_delta == 0) && (bbatt_delta == 0))
+ goto no_adjustment_needed;
+
+ /* Save the deltas for later when we adjust the power. */
+ gphy->bbatt_delta = bbatt_delta;
+ gphy->rfatt_delta = rfatt_delta;
+
+ /* We need to adjust the TX power on the device. */
+ return B43_TXPWR_RES_NEED_ADJUST;
+
+no_adjustment_needed:
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
+
+ //TODO: update_aci_moving_average
+ if (gphy->aci_enable && gphy->aci_wlan_automatic) {
+ b43_mac_suspend(dev);
+ if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
+ if (0 /*TODO: bunch of conditions */ ) {
+ phy->ops->interf_mitigation(dev,
+ B43_INTERFMODE_MANUALWLAN);
+ }
+ } else if (0 /*TODO*/) {
+ if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
+ phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
+ }
+ b43_mac_enable(dev);
+ } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
+ phy->rev == 1) {
+ //TODO: implement rev1 workaround
+ }
+ b43_lo_g_maintanance_work(dev);
+}
+
+static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+ return;
+
+ b43_mac_suspend(dev);
+ b43_calc_nrssi_slope(dev);
+ if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
+ u8 old_chan = phy->channel;
+
+ /* VCO Calibration */
+ if (old_chan >= 8)
+ b43_switch_channel(dev, 1);
+ else
+ b43_switch_channel(dev, 13);
+ b43_switch_channel(dev, old_chan);
+ }
+ b43_mac_enable(dev);
+}
+
+const struct b43_phy_operations b43_phyops_g = {
+ .allocate = b43_gphy_op_allocate,
+ .free = b43_gphy_op_free,
+ .prepare_structs = b43_gphy_op_prepare_structs,
+ .prepare_hardware = b43_gphy_op_prepare_hardware,
+ .init = b43_gphy_op_init,
+ .exit = b43_gphy_op_exit,
+ .phy_read = b43_gphy_op_read,
+ .phy_write = b43_gphy_op_write,
+ .radio_read = b43_gphy_op_radio_read,
+ .radio_write = b43_gphy_op_radio_write,
+ .supports_hwpctl = b43_gphy_op_supports_hwpctl,
+ .software_rfkill = b43_gphy_op_software_rfkill,
+ .switch_analog = b43_phyop_switch_analog_generic,
+ .switch_channel = b43_gphy_op_switch_channel,
+ .get_default_chan = b43_gphy_op_get_default_chan,
+ .set_rx_antenna = b43_gphy_op_set_rx_antenna,
+ .interf_mitigation = b43_gphy_op_interf_mitigation,
+ .recalc_txpower = b43_gphy_op_recalc_txpower,
+ .adjust_txpower = b43_gphy_op_adjust_txpower,
+ .pwork_15sec = b43_gphy_op_pwork_15sec,
+ .pwork_60sec = b43_gphy_op_pwork_60sec,
+};
diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h
new file mode 100644
index 00000000000..718947fd41a
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_g.h
@@ -0,0 +1,209 @@
+#ifndef LINUX_B43_PHY_G_H_
+#define LINUX_B43_PHY_G_H_
+
+/* OFDM PHY registers are defined in the A-PHY header. */
+#include "phy_a.h"
+
+/* CCK (B) PHY Registers */
+#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
+#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
+#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
+#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
+#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
+#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
+#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
+#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
+#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
+#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
+#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
+#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
+#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
+#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
+
+/* Extended G-PHY Registers */
+#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
+#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
+#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
+#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
+#define B43_PHY_GTABNR_SHIFT 10
+#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
+#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
+#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
+#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
+#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
+#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
+#define B43_PHY_RFOVERVAL_LNA 0x7000
+#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
+#define B43_PHY_RFOVERVAL_PGA 0x0F00
+#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
+#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
+#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
+#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
+#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
+#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
+#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
+#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
+
+
+/*** G-PHY table numbers */
+#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
+#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
+#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
+#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
+
+u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value);
+
+
+/* Returns the boolean whether "TX Magnification" is enabled. */
+#define has_tx_magnification(phy) \
+ (((phy)->rev >= 2) && \
+ ((phy)->radio_ver == 0x2050) && \
+ ((phy)->radio_rev == 8))
+/* Card uses the loopback gain stuff */
+#define has_loopback_gain(phy) \
+ (((phy)->rev > 1) || ((phy)->gmode))
+
+/* Radio Attenuation (RF Attenuation) */
+struct b43_rfatt {
+ u8 att; /* Attenuation value */
+ bool with_padmix; /* Flag, PAD Mixer enabled. */
+};
+struct b43_rfatt_list {
+ /* Attenuation values list */
+ const struct b43_rfatt *list;
+ u8 len;
+ /* Minimum/Maximum attenuation values */
+ u8 min_val;
+ u8 max_val;
+};
+
+/* Returns true, if the values are the same. */
+static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
+ const struct b43_rfatt *b)
+{
+ return ((a->att == b->att) &&
+ (a->with_padmix == b->with_padmix));
+}
+
+/* Baseband Attenuation */
+struct b43_bbatt {
+ u8 att; /* Attenuation value */
+};
+struct b43_bbatt_list {
+ /* Attenuation values list */
+ const struct b43_bbatt *list;
+ u8 len;
+ /* Minimum/Maximum attenuation values */
+ u8 min_val;
+ u8 max_val;
+};
+
+/* Returns true, if the values are the same. */
+static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
+ const struct b43_bbatt *b)
+{
+ return (a->att == b->att);
+}
+
+/* tx_control bits. */
+#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
+#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
+#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
+
+struct b43_txpower_lo_control;
+
+struct b43_phy_g {
+ /* ACI (adjacent channel interference) flags. */
+ bool aci_enable;
+ bool aci_wlan_automatic;
+ bool aci_hw_rssi;
+
+ /* Radio switched on/off */
+ bool radio_on;
+ struct {
+ /* Values saved when turning the radio off.
+ * They are needed when turning it on again. */
+ bool valid;
+ u16 rfover;
+ u16 rfoverval;
+ } radio_off_context;
+
+ u16 minlowsig[2];
+ u16 minlowsigpos[2];
+
+ /* Pointer to the table used to convert a
+ * TSSI value to dBm-Q5.2 */
+ const s8 *tssi2dbm;
+ /* tssi2dbm is kmalloc()ed. Only used for free()ing. */
+ bool dyn_tssi_tbl;
+ /* Target idle TSSI */
+ int tgt_idle_tssi;
+ /* Current idle TSSI */
+ int cur_idle_tssi;
+ /* The current average TSSI.
+ * Needs irq_lock, as it's updated in the IRQ path. */
+ u8 average_tssi;
+ /* Current TX power level attenuation control values */
+ struct b43_bbatt bbatt;
+ struct b43_rfatt rfatt;
+ u8 tx_control; /* B43_TXCTL_XXX */
+ /* The calculated attenuation deltas that are used later
+ * when adjusting the actual power output. */
+ int bbatt_delta;
+ int rfatt_delta;
+
+ /* LocalOscillator control values. */
+ struct b43_txpower_lo_control *lo_control;
+ /* Values from b43_calc_loopback_gain() */
+ s16 max_lb_gain; /* Maximum Loopback gain in hdB */
+ s16 trsw_rx_gain; /* TRSW RX gain in hdB */
+ s16 lna_lod_gain; /* LNA lod */
+ s16 lna_gain; /* LNA */
+ s16 pga_gain; /* PGA */
+
+ /* Current Interference Mitigation mode */
+ int interfmode;
+ /* Stack of saved values from the Interference Mitigation code.
+ * Each value in the stack is layed out as follows:
+ * bit 0-11: offset
+ * bit 12-15: register ID
+ * bit 16-32: value
+ * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+ */
+#define B43_INTERFSTACK_SIZE 26
+ u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
+
+ /* Saved values from the NRSSI Slope calculation */
+ s16 nrssi[2];
+ s32 nrssislope;
+ /* In memory nrssi lookup table. */
+ s8 nrssi_lt[64];
+
+ u16 lofcal;
+
+ u16 initval; //FIXME rename?
+
+ /* The device does address auto increment for the OFDM tables.
+ * We cache the previously used address here and omit the address
+ * write on the next table access, if possible. */
+ u16 ofdmtab_addr; /* The address currently set in hardware. */
+ enum { /* The last data flow direction. */
+ B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
+ B43_OFDMTAB_DIRECTION_READ,
+ B43_OFDMTAB_DIRECTION_WRITE,
+ } ofdmtab_addr_direction;
+};
+
+void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
+ u16 baseband_attenuation);
+void b43_gphy_channel_switch(struct b43_wldev *dev,
+ unsigned int channel,
+ bool synthetic_pu_workaround);
+u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,
+ s16 pab0, s16 pab1, s16 pab2);
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_g;
+
+#endif /* LINUX_B43_PHY_G_H_ */
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
new file mode 100644
index 00000000000..c5d9dc3667c
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -0,0 +1,155 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11g LP-PHY driver
+
+ Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "phy_lp.h"
+#include "phy_common.h"
+
+
+static int b43_lpphy_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy;
+
+ lpphy = kzalloc(sizeof(*lpphy), GFP_KERNEL);
+ if (!lpphy)
+ return -ENOMEM;
+ dev->phy.lp = lpphy;
+
+ return 0;
+}
+
+static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_lp *lpphy = phy->lp;
+
+ memset(lpphy, 0, sizeof(*lpphy));
+
+ //TODO
+}
+
+static void b43_lpphy_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+
+ kfree(lpphy);
+ dev->phy.lp = NULL;
+}
+
+static int b43_lpphy_op_init(struct b43_wldev *dev)
+{
+ //TODO
+
+ return 0;
+}
+
+static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+ /* LP-PHY needs a special bit set for read access */
+ if (dev->phy.rev < 2) {
+ if (reg != 0x4001)
+ reg |= 0x100;
+ } else
+ reg |= 0x200;
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
+ enum rfkill_state state)
+{
+ //TODO
+}
+
+static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ //TODO
+ return 0;
+}
+
+static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
+{
+ return 1; /* Default to channel 1 */
+}
+
+static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{
+ //TODO
+}
+
+static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
+{
+ //TODO
+}
+
+static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
+ bool ignore_tssi)
+{
+ //TODO
+ return B43_TXPWR_RES_DONE;
+}
+
+
+const struct b43_phy_operations b43_phyops_lp = {
+ .allocate = b43_lpphy_op_allocate,
+ .free = b43_lpphy_op_free,
+ .prepare_structs = b43_lpphy_op_prepare_structs,
+ .init = b43_lpphy_op_init,
+ .phy_read = b43_lpphy_op_read,
+ .phy_write = b43_lpphy_op_write,
+ .radio_read = b43_lpphy_op_radio_read,
+ .radio_write = b43_lpphy_op_radio_write,
+ .software_rfkill = b43_lpphy_op_software_rfkill,
+ .switch_analog = b43_phyop_switch_analog_generic,
+ .switch_channel = b43_lpphy_op_switch_channel,
+ .get_default_chan = b43_lpphy_op_get_default_chan,
+ .set_rx_antenna = b43_lpphy_op_set_rx_antenna,
+ .recalc_txpower = b43_lpphy_op_recalc_txpower,
+ .adjust_txpower = b43_lpphy_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
new file mode 100644
index 00000000000..b0b5357abf9
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -0,0 +1,540 @@
+#ifndef LINUX_B43_PHY_LP_H_
+#define LINUX_B43_PHY_LP_H_
+
+/* Definitions for the LP-PHY */
+
+
+
+
+#define B43_LP_RADIO(radio_reg) (radio_reg)
+#define B43_LP_NORTH(radio_reg) B43_LP_RADIO(radio_reg)
+#define B43_LP_SOUTH(radio_reg) B43_LP_RADIO((radio_reg) | 0x4000)
+
+
+/*** Broadcom 2062 NORTH radio registers ***/
+#define B2062_N_COMM1 B43_LP_NORTH(0x000) /* Common 01 (north) */
+#define B2062_N_COMM2 B43_LP_NORTH(0x002) /* Common 02 (north) */
+#define B2062_N_COMM3 B43_LP_NORTH(0x003) /* Common 03 (north) */
+#define B2062_N_COMM4 B43_LP_NORTH(0x004) /* Common 04 (north) */
+#define B2062_N_COMM5 B43_LP_NORTH(0x005) /* Common 05 (north) */
+#define B2062_N_COMM6 B43_LP_NORTH(0x006) /* Common 06 (north) */
+#define B2062_N_COMM7 B43_LP_NORTH(0x007) /* Common 07 (north) */
+#define B2062_N_COMM8 B43_LP_NORTH(0x008) /* Common 08 (north) */
+#define B2062_N_COMM9 B43_LP_NORTH(0x009) /* Common 09 (north) */
+#define B2062_N_COMM10 B43_LP_NORTH(0x00A) /* Common 10 (north) */
+#define B2062_N_COMM11 B43_LP_NORTH(0x00B) /* Common 11 (north) */
+#define B2062_N_COMM12 B43_LP_NORTH(0x00C) /* Common 12 (north) */
+#define B2062_N_COMM13 B43_LP_NORTH(0x00D) /* Common 13 (north) */
+#define B2062_N_COMM14 B43_LP_NORTH(0x00E) /* Common 14 (north) */
+#define B2062_N_COMM15 B43_LP_NORTH(0x00F) /* Common 15 (north) */
+#define B2062_N_PDN_CTL0 B43_LP_NORTH(0x010) /* PDN Control 0 (north) */
+#define B2062_N_PDN_CTL1 B43_LP_NORTH(0x011) /* PDN Control 1 (north) */
+#define B2062_N_PDN_CTL2 B43_LP_NORTH(0x012) /* PDN Control 2 (north) */
+#define B2062_N_PDN_CTL3 B43_LP_NORTH(0x013) /* PDN Control 3 (north) */
+#define B2062_N_PDN_CTL4 B43_LP_NORTH(0x014) /* PDN Control 4 (north) */
+#define B2062_N_GEN_CTL0 B43_LP_NORTH(0x015) /* GEN Control 0 (north) */
+#define B2062_N_IQ_CALIB B43_LP_NORTH(0x016) /* IQ Calibration (north) */
+#define B2062_N_LGENC B43_LP_NORTH(0x017) /* LGENC (north) */
+#define B2062_N_LGENA_LPF B43_LP_NORTH(0x018) /* LGENA LPF (north) */
+#define B2062_N_LGENA_BIAS0 B43_LP_NORTH(0x019) /* LGENA Bias 0 (north) */
+#define B2062_N_LGNEA_BIAS1 B43_LP_NORTH(0x01A) /* LGNEA Bias 1 (north) */
+#define B2062_N_LGENA_CTL0 B43_LP_NORTH(0x01B) /* LGENA Control 0 (north) */
+#define B2062_N_LGENA_CTL1 B43_LP_NORTH(0x01C) /* LGENA Control 1 (north) */
+#define B2062_N_LGENA_CTL2 B43_LP_NORTH(0x01D) /* LGENA Control 2 (north) */
+#define B2062_N_LGENA_TUNE0 B43_LP_NORTH(0x01E) /* LGENA Tune 0 (north) */
+#define B2062_N_LGENA_TUNE1 B43_LP_NORTH(0x01F) /* LGENA Tune 1 (north) */
+#define B2062_N_LGENA_TUNE2 B43_LP_NORTH(0x020) /* LGENA Tune 2 (north) */
+#define B2062_N_LGENA_TUNE3 B43_LP_NORTH(0x021) /* LGENA Tune 3 (north) */
+#define B2062_N_LGENA_CTL3 B43_LP_NORTH(0x022) /* LGENA Control 3 (north) */
+#define B2062_N_LGENA_CTL4 B43_LP_NORTH(0x023) /* LGENA Control 4 (north) */
+#define B2062_N_LGENA_CTL5 B43_LP_NORTH(0x024) /* LGENA Control 5 (north) */
+#define B2062_N_LGENA_CTL6 B43_LP_NORTH(0x025) /* LGENA Control 6 (north) */
+#define B2062_N_LGENA_CTL7 B43_LP_NORTH(0x026) /* LGENA Control 7 (north) */
+#define B2062_N_RXA_CTL0 B43_LP_NORTH(0x027) /* RXA Control 0 (north) */
+#define B2062_N_RXA_CTL1 B43_LP_NORTH(0x028) /* RXA Control 1 (north) */
+#define B2062_N_RXA_CTL2 B43_LP_NORTH(0x029) /* RXA Control 2 (north) */
+#define B2062_N_RXA_CTL3 B43_LP_NORTH(0x02A) /* RXA Control 3 (north) */
+#define B2062_N_RXA_CTL4 B43_LP_NORTH(0x02B) /* RXA Control 4 (north) */
+#define B2062_N_RXA_CTL5 B43_LP_NORTH(0x02C) /* RXA Control 5 (north) */
+#define B2062_N_RXA_CTL6 B43_LP_NORTH(0x02D) /* RXA Control 6 (north) */
+#define B2062_N_RXA_CTL7 B43_LP_NORTH(0x02E) /* RXA Control 7 (north) */
+#define B2062_N_RXBB_CTL0 B43_LP_NORTH(0x02F) /* RXBB Control 0 (north) */
+#define B2062_N_RXBB_CTL1 B43_LP_NORTH(0x030) /* RXBB Control 1 (north) */
+#define B2062_N_RXBB_CTL2 B43_LP_NORTH(0x031) /* RXBB Control 2 (north) */
+#define B2062_N_RXBB_GAIN0 B43_LP_NORTH(0x032) /* RXBB Gain 0 (north) */
+#define B2062_N_RXBB_GAIN1 B43_LP_NORTH(0x033) /* RXBB Gain 1 (north) */
+#define B2062_N_RXBB_GAIN2 B43_LP_NORTH(0x034) /* RXBB Gain 2 (north) */
+#define B2062_N_RXBB_GAIN3 B43_LP_NORTH(0x035) /* RXBB Gain 3 (north) */
+#define B2062_N_RXBB_RSSI0 B43_LP_NORTH(0x036) /* RXBB RSSI 0 (north) */
+#define B2062_N_RXBB_RSSI1 B43_LP_NORTH(0x037) /* RXBB RSSI 1 (north) */
+#define B2062_N_RXBB_CALIB0 B43_LP_NORTH(0x038) /* RXBB Calibration0 (north) */
+#define B2062_N_RXBB_CALIB1 B43_LP_NORTH(0x039) /* RXBB Calibration1 (north) */
+#define B2062_N_RXBB_CALIB2 B43_LP_NORTH(0x03A) /* RXBB Calibration2 (north) */
+#define B2062_N_RXBB_BIAS0 B43_LP_NORTH(0x03B) /* RXBB Bias 0 (north) */
+#define B2062_N_RXBB_BIAS1 B43_LP_NORTH(0x03C) /* RXBB Bias 1 (north) */
+#define B2062_N_RXBB_BIAS2 B43_LP_NORTH(0x03D) /* RXBB Bias 2 (north) */
+#define B2062_N_RXBB_BIAS3 B43_LP_NORTH(0x03E) /* RXBB Bias 3 (north) */
+#define B2062_N_RXBB_BIAS4 B43_LP_NORTH(0x03F) /* RXBB Bias 4 (north) */
+#define B2062_N_RXBB_BIAS5 B43_LP_NORTH(0x040) /* RXBB Bias 5 (north) */
+#define B2062_N_RXBB_RSSI2 B43_LP_NORTH(0x041) /* RXBB RSSI 2 (north) */
+#define B2062_N_RXBB_RSSI3 B43_LP_NORTH(0x042) /* RXBB RSSI 3 (north) */
+#define B2062_N_RXBB_RSSI4 B43_LP_NORTH(0x043) /* RXBB RSSI 4 (north) */
+#define B2062_N_RXBB_RSSI5 B43_LP_NORTH(0x044) /* RXBB RSSI 5 (north) */
+#define B2062_N_TX_CTL0 B43_LP_NORTH(0x045) /* TX Control 0 (north) */
+#define B2062_N_TX_CTL1 B43_LP_NORTH(0x046) /* TX Control 1 (north) */
+#define B2062_N_TX_CTL2 B43_LP_NORTH(0x047) /* TX Control 2 (north) */
+#define B2062_N_TX_CTL3 B43_LP_NORTH(0x048) /* TX Control 3 (north) */
+#define B2062_N_TX_CTL4 B43_LP_NORTH(0x049) /* TX Control 4 (north) */
+#define B2062_N_TX_CTL5 B43_LP_NORTH(0x04A) /* TX Control 5 (north) */
+#define B2062_N_TX_CTL6 B43_LP_NORTH(0x04B) /* TX Control 6 (north) */
+#define B2062_N_TX_CTL7 B43_LP_NORTH(0x04C) /* TX Control 7 (north) */
+#define B2062_N_TX_CTL8 B43_LP_NORTH(0x04D) /* TX Control 8 (north) */
+#define B2062_N_TX_CTL9 B43_LP_NORTH(0x04E) /* TX Control 9 (north) */
+#define B2062_N_TX_CTL_A B43_LP_NORTH(0x04F) /* TX Control A (north) */
+#define B2062_N_TX_GC2G B43_LP_NORTH(0x050) /* TX GC2G (north) */
+#define B2062_N_TX_GC5G B43_LP_NORTH(0x051) /* TX GC5G (north) */
+#define B2062_N_TX_TUNE B43_LP_NORTH(0x052) /* TX Tune (north) */
+#define B2062_N_TX_PAD B43_LP_NORTH(0x053) /* TX PAD (north) */
+#define B2062_N_TX_PGA B43_LP_NORTH(0x054) /* TX PGA (north) */
+#define B2062_N_TX_PADAUX B43_LP_NORTH(0x055) /* TX PADAUX (north) */
+#define B2062_N_TX_PGAAUX B43_LP_NORTH(0x056) /* TX PGAAUX (north) */
+#define B2062_N_TSSI_CTL0 B43_LP_NORTH(0x057) /* TSSI Control 0 (north) */
+#define B2062_N_TSSI_CTL1 B43_LP_NORTH(0x058) /* TSSI Control 1 (north) */
+#define B2062_N_TSSI_CTL2 B43_LP_NORTH(0x059) /* TSSI Control 2 (north) */
+#define B2062_N_IQ_CALIB_CTL0 B43_LP_NORTH(0x05A) /* IQ Calibration Control 0 (north) */
+#define B2062_N_IQ_CALIB_CTL1 B43_LP_NORTH(0x05B) /* IQ Calibration Control 1 (north) */
+#define B2062_N_IQ_CALIB_CTL2 B43_LP_NORTH(0x05C) /* IQ Calibration Control 2 (north) */
+#define B2062_N_CALIB_TS B43_LP_NORTH(0x05D) /* Calibration TS (north) */
+#define B2062_N_CALIB_CTL0 B43_LP_NORTH(0x05E) /* Calibration Control 0 (north) */
+#define B2062_N_CALIB_CTL1 B43_LP_NORTH(0x05F) /* Calibration Control 1 (north) */
+#define B2062_N_CALIB_CTL2 B43_LP_NORTH(0x060) /* Calibration Control 2 (north) */
+#define B2062_N_CALIB_CTL3 B43_LP_NORTH(0x061) /* Calibration Control 3 (north) */
+#define B2062_N_CALIB_CTL4 B43_LP_NORTH(0x062) /* Calibration Control 4 (north) */
+#define B2062_N_CALIB_DBG0 B43_LP_NORTH(0x063) /* Calibration Debug 0 (north) */
+#define B2062_N_CALIB_DBG1 B43_LP_NORTH(0x064) /* Calibration Debug 1 (north) */
+#define B2062_N_CALIB_DBG2 B43_LP_NORTH(0x065) /* Calibration Debug 2 (north) */
+#define B2062_N_CALIB_DBG3 B43_LP_NORTH(0x066) /* Calibration Debug 3 (north) */
+#define B2062_N_PSENSE_CTL0 B43_LP_NORTH(0x069) /* PSENSE Control 0 (north) */
+#define B2062_N_PSENSE_CTL1 B43_LP_NORTH(0x06A) /* PSENSE Control 1 (north) */
+#define B2062_N_PSENSE_CTL2 B43_LP_NORTH(0x06B) /* PSENSE Control 2 (north) */
+#define B2062_N_TEST_BUF0 B43_LP_NORTH(0x06C) /* TEST BUF0 (north) */
+
+/*** Broadcom 2062 SOUTH radio registers ***/
+#define B2062_S_COMM1 B43_LP_SOUTH(0x000) /* Common 01 (south) */
+#define B2062_S_RADIO_ID_CODE B43_LP_SOUTH(0x001) /* Radio ID code (south) */
+#define B2062_S_COMM2 B43_LP_SOUTH(0x002) /* Common 02 (south) */
+#define B2062_S_COMM3 B43_LP_SOUTH(0x003) /* Common 03 (south) */
+#define B2062_S_COMM4 B43_LP_SOUTH(0x004) /* Common 04 (south) */
+#define B2062_S_COMM5 B43_LP_SOUTH(0x005) /* Common 05 (south) */
+#define B2062_S_COMM6 B43_LP_SOUTH(0x006) /* Common 06 (south) */
+#define B2062_S_COMM7 B43_LP_SOUTH(0x007) /* Common 07 (south) */
+#define B2062_S_COMM8 B43_LP_SOUTH(0x008) /* Common 08 (south) */
+#define B2062_S_COMM9 B43_LP_SOUTH(0x009) /* Common 09 (south) */
+#define B2062_S_COMM10 B43_LP_SOUTH(0x00A) /* Common 10 (south) */
+#define B2062_S_COMM11 B43_LP_SOUTH(0x00B) /* Common 11 (south) */
+#define B2062_S_COMM12 B43_LP_SOUTH(0x00C) /* Common 12 (south) */
+#define B2062_S_COMM13 B43_LP_SOUTH(0x00D) /* Common 13 (south) */
+#define B2062_S_COMM14 B43_LP_SOUTH(0x00E) /* Common 14 (south) */
+#define B2062_S_COMM15 B43_LP_SOUTH(0x00F) /* Common 15 (south) */
+#define B2062_S_PDS_CTL0 B43_LP_SOUTH(0x010) /* PDS Control 0 (south) */
+#define B2062_S_PDS_CTL1 B43_LP_SOUTH(0x011) /* PDS Control 1 (south) */
+#define B2062_S_PDS_CTL2 B43_LP_SOUTH(0x012) /* PDS Control 2 (south) */
+#define B2062_S_PDS_CTL3 B43_LP_SOUTH(0x013) /* PDS Control 3 (south) */
+#define B2062_S_BG_CTL0 B43_LP_SOUTH(0x014) /* BG Control 0 (south) */
+#define B2062_S_BG_CTL1 B43_LP_SOUTH(0x015) /* BG Control 1 (south) */
+#define B2062_S_BG_CTL2 B43_LP_SOUTH(0x016) /* BG Control 2 (south) */
+#define B2062_S_LGENG_CTL0 B43_LP_SOUTH(0x017) /* LGENG Control 00 (south) */
+#define B2062_S_LGENG_CTL1 B43_LP_SOUTH(0x018) /* LGENG Control 01 (south) */
+#define B2062_S_LGENG_CTL2 B43_LP_SOUTH(0x019) /* LGENG Control 02 (south) */
+#define B2062_S_LGENG_CTL3 B43_LP_SOUTH(0x01A) /* LGENG Control 03 (south) */
+#define B2062_S_LGENG_CTL4 B43_LP_SOUTH(0x01B) /* LGENG Control 04 (south) */
+#define B2062_S_LGENG_CTL5 B43_LP_SOUTH(0x01C) /* LGENG Control 05 (south) */
+#define B2062_S_LGENG_CTL6 B43_LP_SOUTH(0x01D) /* LGENG Control 06 (south) */
+#define B2062_S_LGENG_CTL7 B43_LP_SOUTH(0x01E) /* LGENG Control 07 (south) */
+#define B2062_S_LGENG_CTL8 B43_LP_SOUTH(0x01F) /* LGENG Control 08 (south) */
+#define B2062_S_LGENG_CTL9 B43_LP_SOUTH(0x020) /* LGENG Control 09 (south) */
+#define B2062_S_LGENG_CTL10 B43_LP_SOUTH(0x021) /* LGENG Control 10 (south) */
+#define B2062_S_LGENG_CTL11 B43_LP_SOUTH(0x022) /* LGENG Control 11 (south) */
+#define B2062_S_REFPLL_CTL0 B43_LP_SOUTH(0x023) /* REFPLL Control 00 (south) */
+#define B2062_S_REFPLL_CTL1 B43_LP_SOUTH(0x024) /* REFPLL Control 01 (south) */
+#define B2062_S_REFPLL_CTL2 B43_LP_SOUTH(0x025) /* REFPLL Control 02 (south) */
+#define B2062_S_REFPLL_CTL3 B43_LP_SOUTH(0x026) /* REFPLL Control 03 (south) */
+#define B2062_S_REFPLL_CTL4 B43_LP_SOUTH(0x027) /* REFPLL Control 04 (south) */
+#define B2062_S_REFPLL_CTL5 B43_LP_SOUTH(0x028) /* REFPLL Control 05 (south) */
+#define B2062_S_REFPLL_CTL6 B43_LP_SOUTH(0x029) /* REFPLL Control 06 (south) */
+#define B2062_S_REFPLL_CTL7 B43_LP_SOUTH(0x02A) /* REFPLL Control 07 (south) */
+#define B2062_S_REFPLL_CTL8 B43_LP_SOUTH(0x02B) /* REFPLL Control 08 (south) */
+#define B2062_S_REFPLL_CTL9 B43_LP_SOUTH(0x02C) /* REFPLL Control 09 (south) */
+#define B2062_S_REFPLL_CTL10 B43_LP_SOUTH(0x02D) /* REFPLL Control 10 (south) */
+#define B2062_S_REFPLL_CTL11 B43_LP_SOUTH(0x02E) /* REFPLL Control 11 (south) */
+#define B2062_S_REFPLL_CTL12 B43_LP_SOUTH(0x02F) /* REFPLL Control 12 (south) */
+#define B2062_S_REFPLL_CTL13 B43_LP_SOUTH(0x030) /* REFPLL Control 13 (south) */
+#define B2062_S_REFPLL_CTL14 B43_LP_SOUTH(0x031) /* REFPLL Control 14 (south) */
+#define B2062_S_REFPLL_CTL15 B43_LP_SOUTH(0x032) /* REFPLL Control 15 (south) */
+#define B2062_S_REFPLL_CTL16 B43_LP_SOUTH(0x033) /* REFPLL Control 16 (south) */
+#define B2062_S_RFPLL_CTL0 B43_LP_SOUTH(0x034) /* RFPLL Control 00 (south) */
+#define B2062_S_RFPLL_CTL1 B43_LP_SOUTH(0x035) /* RFPLL Control 01 (south) */
+#define B2062_S_RFPLL_CTL2 B43_LP_SOUTH(0x036) /* RFPLL Control 02 (south) */
+#define B2062_S_RFPLL_CTL3 B43_LP_SOUTH(0x037) /* RFPLL Control 03 (south) */
+#define B2062_S_RFPLL_CTL4 B43_LP_SOUTH(0x038) /* RFPLL Control 04 (south) */
+#define B2062_S_RFPLL_CTL5 B43_LP_SOUTH(0x039) /* RFPLL Control 05 (south) */
+#define B2062_S_RFPLL_CTL6 B43_LP_SOUTH(0x03A) /* RFPLL Control 06 (south) */
+#define B2062_S_RFPLL_CTL7 B43_LP_SOUTH(0x03B) /* RFPLL Control 07 (south) */
+#define B2062_S_RFPLL_CTL8 B43_LP_SOUTH(0x03C) /* RFPLL Control 08 (south) */
+#define B2062_S_RFPLL_CTL9 B43_LP_SOUTH(0x03D) /* RFPLL Control 09 (south) */
+#define B2062_S_RFPLL_CTL10 B43_LP_SOUTH(0x03E) /* RFPLL Control 10 (south) */
+#define B2062_S_RFPLL_CTL11 B43_LP_SOUTH(0x03F) /* RFPLL Control 11 (south) */
+#define B2062_S_RFPLL_CTL12 B43_LP_SOUTH(0x040) /* RFPLL Control 12 (south) */
+#define B2062_S_RFPLL_CTL13 B43_LP_SOUTH(0x041) /* RFPLL Control 13 (south) */
+#define B2062_S_RFPLL_CTL14 B43_LP_SOUTH(0x042) /* RFPLL Control 14 (south) */
+#define B2062_S_RFPLL_CTL15 B43_LP_SOUTH(0x043) /* RFPLL Control 15 (south) */
+#define B2062_S_RFPLL_CTL16 B43_LP_SOUTH(0x044) /* RFPLL Control 16 (south) */
+#define B2062_S_RFPLL_CTL17 B43_LP_SOUTH(0x045) /* RFPLL Control 17 (south) */
+#define B2062_S_RFPLL_CTL18 B43_LP_SOUTH(0x046) /* RFPLL Control 18 (south) */
+#define B2062_S_RFPLL_CTL19 B43_LP_SOUTH(0x047) /* RFPLL Control 19 (south) */
+#define B2062_S_RFPLL_CTL20 B43_LP_SOUTH(0x048) /* RFPLL Control 20 (south) */
+#define B2062_S_RFPLL_CTL21 B43_LP_SOUTH(0x049) /* RFPLL Control 21 (south) */
+#define B2062_S_RFPLL_CTL22 B43_LP_SOUTH(0x04A) /* RFPLL Control 22 (south) */
+#define B2062_S_RFPLL_CTL23 B43_LP_SOUTH(0x04B) /* RFPLL Control 23 (south) */
+#define B2062_S_RFPLL_CTL24 B43_LP_SOUTH(0x04C) /* RFPLL Control 24 (south) */
+#define B2062_S_RFPLL_CTL25 B43_LP_SOUTH(0x04D) /* RFPLL Control 25 (south) */
+#define B2062_S_RFPLL_CTL26 B43_LP_SOUTH(0x04E) /* RFPLL Control 26 (south) */
+#define B2062_S_RFPLL_CTL27 B43_LP_SOUTH(0x04F) /* RFPLL Control 27 (south) */
+#define B2062_S_RFPLL_CTL28 B43_LP_SOUTH(0x050) /* RFPLL Control 28 (south) */
+#define B2062_S_RFPLL_CTL29 B43_LP_SOUTH(0x051) /* RFPLL Control 29 (south) */
+#define B2062_S_RFPLL_CTL30 B43_LP_SOUTH(0x052) /* RFPLL Control 30 (south) */
+#define B2062_S_RFPLL_CTL31 B43_LP_SOUTH(0x053) /* RFPLL Control 31 (south) */
+#define B2062_S_RFPLL_CTL32 B43_LP_SOUTH(0x054) /* RFPLL Control 32 (south) */
+#define B2062_S_RFPLL_CTL33 B43_LP_SOUTH(0x055) /* RFPLL Control 33 (south) */
+#define B2062_S_RFPLL_CTL34 B43_LP_SOUTH(0x056) /* RFPLL Control 34 (south) */
+#define B2062_S_RXG_CNT0 B43_LP_SOUTH(0x057) /* RXG Counter 00 (south) */
+#define B2062_S_RXG_CNT1 B43_LP_SOUTH(0x058) /* RXG Counter 01 (south) */
+#define B2062_S_RXG_CNT2 B43_LP_SOUTH(0x059) /* RXG Counter 02 (south) */
+#define B2062_S_RXG_CNT3 B43_LP_SOUTH(0x05A) /* RXG Counter 03 (south) */
+#define B2062_S_RXG_CNT4 B43_LP_SOUTH(0x05B) /* RXG Counter 04 (south) */
+#define B2062_S_RXG_CNT5 B43_LP_SOUTH(0x05C) /* RXG Counter 05 (south) */
+#define B2062_S_RXG_CNT6 B43_LP_SOUTH(0x05D) /* RXG Counter 06 (south) */
+#define B2062_S_RXG_CNT7 B43_LP_SOUTH(0x05E) /* RXG Counter 07 (south) */
+#define B2062_S_RXG_CNT8 B43_LP_SOUTH(0x05F) /* RXG Counter 08 (south) */
+#define B2062_S_RXG_CNT9 B43_LP_SOUTH(0x060) /* RXG Counter 09 (south) */
+#define B2062_S_RXG_CNT10 B43_LP_SOUTH(0x061) /* RXG Counter 10 (south) */
+#define B2062_S_RXG_CNT11 B43_LP_SOUTH(0x062) /* RXG Counter 11 (south) */
+#define B2062_S_RXG_CNT12 B43_LP_SOUTH(0x063) /* RXG Counter 12 (south) */
+#define B2062_S_RXG_CNT13 B43_LP_SOUTH(0x064) /* RXG Counter 13 (south) */
+#define B2062_S_RXG_CNT14 B43_LP_SOUTH(0x065) /* RXG Counter 14 (south) */
+#define B2062_S_RXG_CNT15 B43_LP_SOUTH(0x066) /* RXG Counter 15 (south) */
+#define B2062_S_RXG_CNT16 B43_LP_SOUTH(0x067) /* RXG Counter 16 (south) */
+#define B2062_S_RXG_CNT17 B43_LP_SOUTH(0x068) /* RXG Counter 17 (south) */
+
+
+
+/*** Broadcom 2063 radio registers ***/
+#define B2063_RADIO_ID_CODE B43_LP_RADIO(0x001) /* Radio ID code */
+#define B2063_COMM1 B43_LP_RADIO(0x000) /* Common 01 */
+#define B2063_COMM2 B43_LP_RADIO(0x002) /* Common 02 */
+#define B2063_COMM3 B43_LP_RADIO(0x003) /* Common 03 */
+#define B2063_COMM4 B43_LP_RADIO(0x004) /* Common 04 */
+#define B2063_COMM5 B43_LP_RADIO(0x005) /* Common 05 */
+#define B2063_COMM6 B43_LP_RADIO(0x006) /* Common 06 */
+#define B2063_COMM7 B43_LP_RADIO(0x007) /* Common 07 */
+#define B2063_COMM8 B43_LP_RADIO(0x008) /* Common 08 */
+#define B2063_COMM9 B43_LP_RADIO(0x009) /* Common 09 */
+#define B2063_COMM10 B43_LP_RADIO(0x00A) /* Common 10 */
+#define B2063_COMM11 B43_LP_RADIO(0x00B) /* Common 11 */
+#define B2063_COMM12 B43_LP_RADIO(0x00C) /* Common 12 */
+#define B2063_COMM13 B43_LP_RADIO(0x00D) /* Common 13 */
+#define B2063_COMM14 B43_LP_RADIO(0x00E) /* Common 14 */
+#define B2063_COMM15 B43_LP_RADIO(0x00F) /* Common 15 */
+#define B2063_COMM16 B43_LP_RADIO(0x010) /* Common 16 */
+#define B2063_COMM17 B43_LP_RADIO(0x011) /* Common 17 */
+#define B2063_COMM18 B43_LP_RADIO(0x012) /* Common 18 */
+#define B2063_COMM19 B43_LP_RADIO(0x013) /* Common 19 */
+#define B2063_COMM20 B43_LP_RADIO(0x014) /* Common 20 */
+#define B2063_COMM21 B43_LP_RADIO(0x015) /* Common 21 */
+#define B2063_COMM22 B43_LP_RADIO(0x016) /* Common 22 */
+#define B2063_COMM23 B43_LP_RADIO(0x017) /* Common 23 */
+#define B2063_COMM24 B43_LP_RADIO(0x018) /* Common 24 */
+#define B2063_PWR_SWITCH_CTL B43_LP_RADIO(0x019) /* POWER SWITCH Control */
+#define B2063_PLL_SP1 B43_LP_RADIO(0x01A) /* PLL SP 1 */
+#define B2063_PLL_SP2 B43_LP_RADIO(0x01B) /* PLL SP 2 */
+#define B2063_LOGEN_SP1 B43_LP_RADIO(0x01C) /* LOGEN SP 1 */
+#define B2063_LOGEN_SP2 B43_LP_RADIO(0x01D) /* LOGEN SP 2 */
+#define B2063_LOGEN_SP3 B43_LP_RADIO(0x01E) /* LOGEN SP 3 */
+#define B2063_LOGEN_SP4 B43_LP_RADIO(0x01F) /* LOGEN SP 4 */
+#define B2063_LOGEN_SP5 B43_LP_RADIO(0x020) /* LOGEN SP 5 */
+#define B2063_G_RX_SP1 B43_LP_RADIO(0x021) /* G RX SP 1 */
+#define B2063_G_RX_SP2 B43_LP_RADIO(0x022) /* G RX SP 2 */
+#define B2063_G_RX_SP3 B43_LP_RADIO(0x023) /* G RX SP 3 */
+#define B2063_G_RX_SP4 B43_LP_RADIO(0x024) /* G RX SP 4 */
+#define B2063_G_RX_SP5 B43_LP_RADIO(0x025) /* G RX SP 5 */
+#define B2063_G_RX_SP6 B43_LP_RADIO(0x026) /* G RX SP 6 */
+#define B2063_G_RX_SP7 B43_LP_RADIO(0x027) /* G RX SP 7 */
+#define B2063_G_RX_SP8 B43_LP_RADIO(0x028) /* G RX SP 8 */
+#define B2063_G_RX_SP9 B43_LP_RADIO(0x029) /* G RX SP 9 */
+#define B2063_G_RX_SP10 B43_LP_RADIO(0x02A) /* G RX SP 10 */
+#define B2063_G_RX_SP11 B43_LP_RADIO(0x02B) /* G RX SP 11 */
+#define B2063_A_RX_SP1 B43_LP_RADIO(0x02C) /* A RX SP 1 */
+#define B2063_A_RX_SP2 B43_LP_RADIO(0x02D) /* A RX SP 2 */
+#define B2063_A_RX_SP3 B43_LP_RADIO(0x02E) /* A RX SP 3 */
+#define B2063_A_RX_SP4 B43_LP_RADIO(0x02F) /* A RX SP 4 */
+#define B2063_A_RX_SP5 B43_LP_RADIO(0x030) /* A RX SP 5 */
+#define B2063_A_RX_SP6 B43_LP_RADIO(0x031) /* A RX SP 6 */
+#define B2063_A_RX_SP7 B43_LP_RADIO(0x032) /* A RX SP 7 */
+#define B2063_RX_BB_SP1 B43_LP_RADIO(0x033) /* RX BB SP 1 */
+#define B2063_RX_BB_SP2 B43_LP_RADIO(0x034) /* RX BB SP 2 */
+#define B2063_RX_BB_SP3 B43_LP_RADIO(0x035) /* RX BB SP 3 */
+#define B2063_RX_BB_SP4 B43_LP_RADIO(0x036) /* RX BB SP 4 */
+#define B2063_RX_BB_SP5 B43_LP_RADIO(0x037) /* RX BB SP 5 */
+#define B2063_RX_BB_SP6 B43_LP_RADIO(0x038) /* RX BB SP 6 */
+#define B2063_RX_BB_SP7 B43_LP_RADIO(0x039) /* RX BB SP 7 */
+#define B2063_RX_BB_SP8 B43_LP_RADIO(0x03A) /* RX BB SP 8 */
+#define B2063_TX_RF_SP1 B43_LP_RADIO(0x03B) /* TX RF SP 1 */
+#define B2063_TX_RF_SP2 B43_LP_RADIO(0x03C) /* TX RF SP 2 */
+#define B2063_TX_RF_SP3 B43_LP_RADIO(0x03D) /* TX RF SP 3 */
+#define B2063_TX_RF_SP4 B43_LP_RADIO(0x03E) /* TX RF SP 4 */
+#define B2063_TX_RF_SP5 B43_LP_RADIO(0x03F) /* TX RF SP 5 */
+#define B2063_TX_RF_SP6 B43_LP_RADIO(0x040) /* TX RF SP 6 */
+#define B2063_TX_RF_SP7 B43_LP_RADIO(0x041) /* TX RF SP 7 */
+#define B2063_TX_RF_SP8 B43_LP_RADIO(0x042) /* TX RF SP 8 */
+#define B2063_TX_RF_SP9 B43_LP_RADIO(0x043) /* TX RF SP 9 */
+#define B2063_TX_RF_SP10 B43_LP_RADIO(0x044) /* TX RF SP 10 */
+#define B2063_TX_RF_SP11 B43_LP_RADIO(0x045) /* TX RF SP 11 */
+#define B2063_TX_RF_SP12 B43_LP_RADIO(0x046) /* TX RF SP 12 */
+#define B2063_TX_RF_SP13 B43_LP_RADIO(0x047) /* TX RF SP 13 */
+#define B2063_TX_RF_SP14 B43_LP_RADIO(0x048) /* TX RF SP 14 */
+#define B2063_TX_RF_SP15 B43_LP_RADIO(0x049) /* TX RF SP 15 */
+#define B2063_TX_RF_SP16 B43_LP_RADIO(0x04A) /* TX RF SP 16 */
+#define B2063_TX_RF_SP17 B43_LP_RADIO(0x04B) /* TX RF SP 17 */
+#define B2063_PA_SP1 B43_LP_RADIO(0x04C) /* PA SP 1 */
+#define B2063_PA_SP2 B43_LP_RADIO(0x04D) /* PA SP 2 */
+#define B2063_PA_SP3 B43_LP_RADIO(0x04E) /* PA SP 3 */
+#define B2063_PA_SP4 B43_LP_RADIO(0x04F) /* PA SP 4 */
+#define B2063_PA_SP5 B43_LP_RADIO(0x050) /* PA SP 5 */
+#define B2063_PA_SP6 B43_LP_RADIO(0x051) /* PA SP 6 */
+#define B2063_PA_SP7 B43_LP_RADIO(0x052) /* PA SP 7 */
+#define B2063_TX_BB_SP1 B43_LP_RADIO(0x053) /* TX BB SP 1 */
+#define B2063_TX_BB_SP2 B43_LP_RADIO(0x054) /* TX BB SP 2 */
+#define B2063_TX_BB_SP3 B43_LP_RADIO(0x055) /* TX BB SP 3 */
+#define B2063_REG_SP1 B43_LP_RADIO(0x056) /* REG SP 1 */
+#define B2063_BANDGAP_CTL1 B43_LP_RADIO(0x057) /* BANDGAP Control 1 */
+#define B2063_BANDGAP_CTL2 B43_LP_RADIO(0x058) /* BANDGAP Control 2 */
+#define B2063_LPO_CTL1 B43_LP_RADIO(0x059) /* LPO Control 1 */
+#define B2063_RC_CALIB_CTL1 B43_LP_RADIO(0x05A) /* RC Calibration Control 1 */
+#define B2063_RC_CALIB_CTL2 B43_LP_RADIO(0x05B) /* RC Calibration Control 2 */
+#define B2063_RC_CALIB_CTL3 B43_LP_RADIO(0x05C) /* RC Calibration Control 3 */
+#define B2063_RC_CALIB_CTL4 B43_LP_RADIO(0x05D) /* RC Calibration Control 4 */
+#define B2063_RC_CALIB_CTL5 B43_LP_RADIO(0x05E) /* RC Calibration Control 5 */
+#define B2063_RC_CALIB_CTL6 B43_LP_RADIO(0x05F) /* RC Calibration Control 6 */
+#define B2063_RC_CALIB_CTL7 B43_LP_RADIO(0x060) /* RC Calibration Control 7 */
+#define B2063_RC_CALIB_CTL8 B43_LP_RADIO(0x061) /* RC Calibration Control 8 */
+#define B2063_RC_CALIB_CTL9 B43_LP_RADIO(0x062) /* RC Calibration Control 9 */
+#define B2063_RC_CALIB_CTL10 B43_LP_RADIO(0x063) /* RC Calibration Control 10 */
+#define B2063_PLL_JTAG_CALNRST B43_LP_RADIO(0x064) /* PLL JTAG CALNRST */
+#define B2063_PLL_JTAG_IN_PLL1 B43_LP_RADIO(0x065) /* PLL JTAG IN PLL 1 */
+#define B2063_PLL_JTAG_IN_PLL2 B43_LP_RADIO(0x066) /* PLL JTAG IN PLL 2 */
+#define B2063_PLL_JTAG_PLL_CP1 B43_LP_RADIO(0x067) /* PLL JTAG PLL CP 1 */
+#define B2063_PLL_JTAG_PLL_CP2 B43_LP_RADIO(0x068) /* PLL JTAG PLL CP 2 */
+#define B2063_PLL_JTAG_PLL_CP3 B43_LP_RADIO(0x069) /* PLL JTAG PLL CP 3 */
+#define B2063_PLL_JTAG_PLL_CP4 B43_LP_RADIO(0x06A) /* PLL JTAG PLL CP 4 */
+#define B2063_PLL_JTAG_PLL_CTL1 B43_LP_RADIO(0x06B) /* PLL JTAG PLL Control 1 */
+#define B2063_PLL_JTAG_PLL_LF1 B43_LP_RADIO(0x06C) /* PLL JTAG PLL LF 1 */
+#define B2063_PLL_JTAG_PLL_LF2 B43_LP_RADIO(0x06D) /* PLL JTAG PLL LF 2 */
+#define B2063_PLL_JTAG_PLL_LF3 B43_LP_RADIO(0x06E) /* PLL JTAG PLL LF 3 */
+#define B2063_PLL_JTAG_PLL_LF4 B43_LP_RADIO(0x06F) /* PLL JTAG PLL LF 4 */
+#define B2063_PLL_JTAG_PLL_SG1 B43_LP_RADIO(0x070) /* PLL JTAG PLL SG 1 */
+#define B2063_PLL_JTAG_PLL_SG2 B43_LP_RADIO(0x071) /* PLL JTAG PLL SG 2 */
+#define B2063_PLL_JTAG_PLL_SG3 B43_LP_RADIO(0x072) /* PLL JTAG PLL SG 3 */
+#define B2063_PLL_JTAG_PLL_SG4 B43_LP_RADIO(0x073) /* PLL JTAG PLL SG 4 */
+#define B2063_PLL_JTAG_PLL_SG5 B43_LP_RADIO(0x074) /* PLL JTAG PLL SG 5 */
+#define B2063_PLL_JTAG_PLL_VCO1 B43_LP_RADIO(0x075) /* PLL JTAG PLL VCO 1 */
+#define B2063_PLL_JTAG_PLL_VCO2 B43_LP_RADIO(0x076) /* PLL JTAG PLL VCO 2 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB1 B43_LP_RADIO(0x077) /* PLL JTAG PLL VCO Calibration 1 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB2 B43_LP_RADIO(0x078) /* PLL JTAG PLL VCO Calibration 2 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB3 B43_LP_RADIO(0x079) /* PLL JTAG PLL VCO Calibration 3 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB4 B43_LP_RADIO(0x07A) /* PLL JTAG PLL VCO Calibration 4 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB5 B43_LP_RADIO(0x07B) /* PLL JTAG PLL VCO Calibration 5 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB6 B43_LP_RADIO(0x07C) /* PLL JTAG PLL VCO Calibration 6 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB7 B43_LP_RADIO(0x07D) /* PLL JTAG PLL VCO Calibration 7 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB8 B43_LP_RADIO(0x07E) /* PLL JTAG PLL VCO Calibration 8 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB9 B43_LP_RADIO(0x07F) /* PLL JTAG PLL VCO Calibration 9 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB10 B43_LP_RADIO(0x080) /* PLL JTAG PLL VCO Calibration 10 */
+#define B2063_PLL_JTAG_PLL_XTAL_12 B43_LP_RADIO(0x081) /* PLL JTAG PLL XTAL 1 2 */
+#define B2063_PLL_JTAG_PLL_XTAL3 B43_LP_RADIO(0x082) /* PLL JTAG PLL XTAL 3 */
+#define B2063_LOGEN_ACL1 B43_LP_RADIO(0x083) /* LOGEN ACL 1 */
+#define B2063_LOGEN_ACL2 B43_LP_RADIO(0x084) /* LOGEN ACL 2 */
+#define B2063_LOGEN_ACL3 B43_LP_RADIO(0x085) /* LOGEN ACL 3 */
+#define B2063_LOGEN_ACL4 B43_LP_RADIO(0x086) /* LOGEN ACL 4 */
+#define B2063_LOGEN_ACL5 B43_LP_RADIO(0x087) /* LOGEN ACL 5 */
+#define B2063_LO_CALIB_INPUTS B43_LP_RADIO(0x088) /* LO Calibration INPUTS */
+#define B2063_LO_CALIB_CTL1 B43_LP_RADIO(0x089) /* LO Calibration Control 1 */
+#define B2063_LO_CALIB_CTL2 B43_LP_RADIO(0x08A) /* LO Calibration Control 2 */
+#define B2063_LO_CALIB_CTL3 B43_LP_RADIO(0x08B) /* LO Calibration Control 3 */
+#define B2063_LO_CALIB_WAITCNT B43_LP_RADIO(0x08C) /* LO Calibration WAITCNT */
+#define B2063_LO_CALIB_OVR1 B43_LP_RADIO(0x08D) /* LO Calibration OVR 1 */
+#define B2063_LO_CALIB_OVR2 B43_LP_RADIO(0x08E) /* LO Calibration OVR 2 */
+#define B2063_LO_CALIB_OVAL1 B43_LP_RADIO(0x08F) /* LO Calibration OVAL 1 */
+#define B2063_LO_CALIB_OVAL2 B43_LP_RADIO(0x090) /* LO Calibration OVAL 2 */
+#define B2063_LO_CALIB_OVAL3 B43_LP_RADIO(0x091) /* LO Calibration OVAL 3 */
+#define B2063_LO_CALIB_OVAL4 B43_LP_RADIO(0x092) /* LO Calibration OVAL 4 */
+#define B2063_LO_CALIB_OVAL5 B43_LP_RADIO(0x093) /* LO Calibration OVAL 5 */
+#define B2063_LO_CALIB_OVAL6 B43_LP_RADIO(0x094) /* LO Calibration OVAL 6 */
+#define B2063_LO_CALIB_OVAL7 B43_LP_RADIO(0x095) /* LO Calibration OVAL 7 */
+#define B2063_LO_CALIB_CALVLD1 B43_LP_RADIO(0x096) /* LO Calibration CALVLD 1 */
+#define B2063_LO_CALIB_CALVLD2 B43_LP_RADIO(0x097) /* LO Calibration CALVLD 2 */
+#define B2063_LO_CALIB_CVAL1 B43_LP_RADIO(0x098) /* LO Calibration CVAL 1 */
+#define B2063_LO_CALIB_CVAL2 B43_LP_RADIO(0x099) /* LO Calibration CVAL 2 */
+#define B2063_LO_CALIB_CVAL3 B43_LP_RADIO(0x09A) /* LO Calibration CVAL 3 */
+#define B2063_LO_CALIB_CVAL4 B43_LP_RADIO(0x09B) /* LO Calibration CVAL 4 */
+#define B2063_LO_CALIB_CVAL5 B43_LP_RADIO(0x09C) /* LO Calibration CVAL 5 */
+#define B2063_LO_CALIB_CVAL6 B43_LP_RADIO(0x09D) /* LO Calibration CVAL 6 */
+#define B2063_LO_CALIB_CVAL7 B43_LP_RADIO(0x09E) /* LO Calibration CVAL 7 */
+#define B2063_LOGEN_CALIB_EN B43_LP_RADIO(0x09F) /* LOGEN Calibration EN */
+#define B2063_LOGEN_PEAKDET1 B43_LP_RADIO(0x0A0) /* LOGEN PEAKDET 1 */
+#define B2063_LOGEN_RCCR1 B43_LP_RADIO(0x0A1) /* LOGEN RCCR 1 */
+#define B2063_LOGEN_VCOBUF1 B43_LP_RADIO(0x0A2) /* LOGEN VCOBUF 1 */
+#define B2063_LOGEN_MIXER1 B43_LP_RADIO(0x0A3) /* LOGEN MIXER 1 */
+#define B2063_LOGEN_MIXER2 B43_LP_RADIO(0x0A4) /* LOGEN MIXER 2 */
+#define B2063_LOGEN_BUF1 B43_LP_RADIO(0x0A5) /* LOGEN BUF 1 */
+#define B2063_LOGEN_BUF2 B43_LP_RADIO(0x0A6) /* LOGEN BUF 2 */
+#define B2063_LOGEN_DIV1 B43_LP_RADIO(0x0A7) /* LOGEN DIV 1 */
+#define B2063_LOGEN_DIV2 B43_LP_RADIO(0x0A8) /* LOGEN DIV 2 */
+#define B2063_LOGEN_DIV3 B43_LP_RADIO(0x0A9) /* LOGEN DIV 3 */
+#define B2063_LOGEN_CBUFRX1 B43_LP_RADIO(0x0AA) /* LOGEN CBUFRX 1 */
+#define B2063_LOGEN_CBUFRX2 B43_LP_RADIO(0x0AB) /* LOGEN CBUFRX 2 */
+#define B2063_LOGEN_CBUFTX1 B43_LP_RADIO(0x0AC) /* LOGEN CBUFTX 1 */
+#define B2063_LOGEN_CBUFTX2 B43_LP_RADIO(0x0AD) /* LOGEN CBUFTX 2 */
+#define B2063_LOGEN_IDAC1 B43_LP_RADIO(0x0AE) /* LOGEN IDAC 1 */
+#define B2063_LOGEN_SPARE1 B43_LP_RADIO(0x0AF) /* LOGEN SPARE 1 */
+#define B2063_LOGEN_SPARE2 B43_LP_RADIO(0x0B0) /* LOGEN SPARE 2 */
+#define B2063_LOGEN_SPARE3 B43_LP_RADIO(0x0B1) /* LOGEN SPARE 3 */
+#define B2063_G_RX_1ST1 B43_LP_RADIO(0x0B2) /* G RX 1ST 1 */
+#define B2063_G_RX_1ST2 B43_LP_RADIO(0x0B3) /* G RX 1ST 2 */
+#define B2063_G_RX_1ST3 B43_LP_RADIO(0x0B4) /* G RX 1ST 3 */
+#define B2063_G_RX_2ND1 B43_LP_RADIO(0x0B5) /* G RX 2ND 1 */
+#define B2063_G_RX_2ND2 B43_LP_RADIO(0x0B6) /* G RX 2ND 2 */
+#define B2063_G_RX_2ND3 B43_LP_RADIO(0x0B7) /* G RX 2ND 3 */
+#define B2063_G_RX_2ND4 B43_LP_RADIO(0x0B8) /* G RX 2ND 4 */
+#define B2063_G_RX_2ND5 B43_LP_RADIO(0x0B9) /* G RX 2ND 5 */
+#define B2063_G_RX_2ND6 B43_LP_RADIO(0x0BA) /* G RX 2ND 6 */
+#define B2063_G_RX_2ND7 B43_LP_RADIO(0x0BB) /* G RX 2ND 7 */
+#define B2063_G_RX_2ND8 B43_LP_RADIO(0x0BC) /* G RX 2ND 8 */
+#define B2063_G_RX_PS1 B43_LP_RADIO(0x0BD) /* G RX PS 1 */
+#define B2063_G_RX_PS2 B43_LP_RADIO(0x0BE) /* G RX PS 2 */
+#define B2063_G_RX_PS3 B43_LP_RADIO(0x0BF) /* G RX PS 3 */
+#define B2063_G_RX_PS4 B43_LP_RADIO(0x0C0) /* G RX PS 4 */
+#define B2063_G_RX_PS5 B43_LP_RADIO(0x0C1) /* G RX PS 5 */
+#define B2063_G_RX_MIX1 B43_LP_RADIO(0x0C2) /* G RX MIX 1 */
+#define B2063_G_RX_MIX2 B43_LP_RADIO(0x0C3) /* G RX MIX 2 */
+#define B2063_G_RX_MIX3 B43_LP_RADIO(0x0C4) /* G RX MIX 3 */
+#define B2063_G_RX_MIX4 B43_LP_RADIO(0x0C5) /* G RX MIX 4 */
+#define B2063_G_RX_MIX5 B43_LP_RADIO(0x0C6) /* G RX MIX 5 */
+#define B2063_G_RX_MIX6 B43_LP_RADIO(0x0C7) /* G RX MIX 6 */
+#define B2063_G_RX_MIX7 B43_LP_RADIO(0x0C8) /* G RX MIX 7 */
+#define B2063_G_RX_MIX8 B43_LP_RADIO(0x0C9) /* G RX MIX 8 */
+#define B2063_G_RX_PDET1 B43_LP_RADIO(0x0CA) /* G RX PDET 1 */
+#define B2063_G_RX_SPARES1 B43_LP_RADIO(0x0CB) /* G RX SPARES 1 */
+#define B2063_G_RX_SPARES2 B43_LP_RADIO(0x0CC) /* G RX SPARES 2 */
+#define B2063_G_RX_SPARES3 B43_LP_RADIO(0x0CD) /* G RX SPARES 3 */
+#define B2063_A_RX_1ST1 B43_LP_RADIO(0x0CE) /* A RX 1ST 1 */
+#define B2063_A_RX_1ST2 B43_LP_RADIO(0x0CF) /* A RX 1ST 2 */
+#define B2063_A_RX_1ST3 B43_LP_RADIO(0x0D0) /* A RX 1ST 3 */
+#define B2063_A_RX_1ST4 B43_LP_RADIO(0x0D1) /* A RX 1ST 4 */
+#define B2063_A_RX_1ST5 B43_LP_RADIO(0x0D2) /* A RX 1ST 5 */
+#define B2063_A_RX_2ND1 B43_LP_RADIO(0x0D3) /* A RX 2ND 1 */
+#define B2063_A_RX_2ND2 B43_LP_RADIO(0x0D4) /* A RX 2ND 2 */
+#define B2063_A_RX_2ND3 B43_LP_RADIO(0x0D5) /* A RX 2ND 3 */
+#define B2063_A_RX_2ND4 B43_LP_RADIO(0x0D6) /* A RX 2ND 4 */
+#define B2063_A_RX_2ND5 B43_LP_RADIO(0x0D7) /* A RX 2ND 5 */
+#define B2063_A_RX_2ND6 B43_LP_RADIO(0x0D8) /* A RX 2ND 6 */
+#define B2063_A_RX_2ND7 B43_LP_RADIO(0x0D9) /* A RX 2ND 7 */
+#define B2063_A_RX_PS1 B43_LP_RADIO(0x0DA) /* A RX PS 1 */
+#define B2063_A_RX_PS2 B43_LP_RADIO(0x0DB) /* A RX PS 2 */
+#define B2063_A_RX_PS3 B43_LP_RADIO(0x0DC) /* A RX PS 3 */
+#define B2063_A_RX_PS4 B43_LP_RADIO(0x0DD) /* A RX PS 4 */
+#define B2063_A_RX_PS5 B43_LP_RADIO(0x0DE) /* A RX PS 5 */
+#define B2063_A_RX_PS6 B43_LP_RADIO(0x0DF) /* A RX PS 6 */
+#define B2063_A_RX_MIX1 B43_LP_RADIO(0x0E0) /* A RX MIX 1 */
+#define B2063_A_RX_MIX2 B43_LP_RADIO(0x0E1) /* A RX MIX 2 */
+#define B2063_A_RX_MIX3 B43_LP_RADIO(0x0E2) /* A RX MIX 3 */
+#define B2063_A_RX_MIX4 B43_LP_RADIO(0x0E3) /* A RX MIX 4 */
+#define B2063_A_RX_MIX5 B43_LP_RADIO(0x0E4) /* A RX MIX 5 */
+#define B2063_A_RX_MIX6 B43_LP_RADIO(0x0E5) /* A RX MIX 6 */
+#define B2063_A_RX_MIX7 B43_LP_RADIO(0x0E6) /* A RX MIX 7 */
+#define B2063_A_RX_MIX8 B43_LP_RADIO(0x0E7) /* A RX MIX 8 */
+#define B2063_A_RX_PWRDET1 B43_LP_RADIO(0x0E8) /* A RX PWRDET 1 */
+#define B2063_A_RX_SPARE1 B43_LP_RADIO(0x0E9) /* A RX SPARE 1 */
+#define B2063_A_RX_SPARE2 B43_LP_RADIO(0x0EA) /* A RX SPARE 2 */
+#define B2063_A_RX_SPARE3 B43_LP_RADIO(0x0EB) /* A RX SPARE 3 */
+#define B2063_RX_TIA_CTL1 B43_LP_RADIO(0x0EC) /* RX TIA Control 1 */
+#define B2063_RX_TIA_CTL2 B43_LP_RADIO(0x0ED) /* RX TIA Control 2 */
+#define B2063_RX_TIA_CTL3 B43_LP_RADIO(0x0EE) /* RX TIA Control 3 */
+#define B2063_RX_TIA_CTL4 B43_LP_RADIO(0x0EF) /* RX TIA Control 4 */
+#define B2063_RX_TIA_CTL5 B43_LP_RADIO(0x0F0) /* RX TIA Control 5 */
+#define B2063_RX_TIA_CTL6 B43_LP_RADIO(0x0F1) /* RX TIA Control 6 */
+#define B2063_RX_BB_CTL1 B43_LP_RADIO(0x0F2) /* RX BB Control 1 */
+#define B2063_RX_BB_CTL2 B43_LP_RADIO(0x0F3) /* RX BB Control 2 */
+#define B2063_RX_BB_CTL3 B43_LP_RADIO(0x0F4) /* RX BB Control 3 */
+#define B2063_RX_BB_CTL4 B43_LP_RADIO(0x0F5) /* RX BB Control 4 */
+#define B2063_RX_BB_CTL5 B43_LP_RADIO(0x0F6) /* RX BB Control 5 */
+#define B2063_RX_BB_CTL6 B43_LP_RADIO(0x0F7) /* RX BB Control 6 */
+#define B2063_RX_BB_CTL7 B43_LP_RADIO(0x0F8) /* RX BB Control 7 */
+#define B2063_RX_BB_CTL8 B43_LP_RADIO(0x0F9) /* RX BB Control 8 */
+#define B2063_RX_BB_CTL9 B43_LP_RADIO(0x0FA) /* RX BB Control 9 */
+#define B2063_TX_RF_CTL1 B43_LP_RADIO(0x0FB) /* TX RF Control 1 */
+#define B2063_TX_RF_IDAC_LO_RF_I B43_LP_RADIO(0x0FC) /* TX RF IDAC LO RF I */
+#define B2063_TX_RF_IDAC_LO_RF_Q B43_LP_RADIO(0x0FD) /* TX RF IDAC LO RF Q */
+#define B2063_TX_RF_IDAC_LO_BB_I B43_LP_RADIO(0x0FE) /* TX RF IDAC LO BB I */
+#define B2063_TX_RF_IDAC_LO_BB_Q B43_LP_RADIO(0x0FF) /* TX RF IDAC LO BB Q */
+#define B2063_TX_RF_CTL2 B43_LP_RADIO(0x100) /* TX RF Control 2 */
+#define B2063_TX_RF_CTL3 B43_LP_RADIO(0x101) /* TX RF Control 3 */
+#define B2063_TX_RF_CTL4 B43_LP_RADIO(0x102) /* TX RF Control 4 */
+#define B2063_TX_RF_CTL5 B43_LP_RADIO(0x103) /* TX RF Control 5 */
+#define B2063_TX_RF_CTL6 B43_LP_RADIO(0x104) /* TX RF Control 6 */
+#define B2063_TX_RF_CTL7 B43_LP_RADIO(0x105) /* TX RF Control 7 */
+#define B2063_TX_RF_CTL8 B43_LP_RADIO(0x106) /* TX RF Control 8 */
+#define B2063_TX_RF_CTL9 B43_LP_RADIO(0x107) /* TX RF Control 9 */
+#define B2063_TX_RF_CTL10 B43_LP_RADIO(0x108) /* TX RF Control 10 */
+#define B2063_TX_RF_CTL14 B43_LP_RADIO(0x109) /* TX RF Control 14 */
+#define B2063_TX_RF_CTL15 B43_LP_RADIO(0x10A) /* TX RF Control 15 */
+#define B2063_PA_CTL1 B43_LP_RADIO(0x10B) /* PA Control 1 */
+#define B2063_PA_CTL2 B43_LP_RADIO(0x10C) /* PA Control 2 */
+#define B2063_PA_CTL3 B43_LP_RADIO(0x10D) /* PA Control 3 */
+#define B2063_PA_CTL4 B43_LP_RADIO(0x10E) /* PA Control 4 */
+#define B2063_PA_CTL5 B43_LP_RADIO(0x10F) /* PA Control 5 */
+#define B2063_PA_CTL6 B43_LP_RADIO(0x110) /* PA Control 6 */
+#define B2063_PA_CTL7 B43_LP_RADIO(0x111) /* PA Control 7 */
+#define B2063_PA_CTL8 B43_LP_RADIO(0x112) /* PA Control 8 */
+#define B2063_PA_CTL9 B43_LP_RADIO(0x113) /* PA Control 9 */
+#define B2063_PA_CTL10 B43_LP_RADIO(0x114) /* PA Control 10 */
+#define B2063_PA_CTL11 B43_LP_RADIO(0x115) /* PA Control 11 */
+#define B2063_PA_CTL12 B43_LP_RADIO(0x116) /* PA Control 12 */
+#define B2063_PA_CTL13 B43_LP_RADIO(0x117) /* PA Control 13 */
+#define B2063_TX_BB_CTL1 B43_LP_RADIO(0x118) /* TX BB Control 1 */
+#define B2063_TX_BB_CTL2 B43_LP_RADIO(0x119) /* TX BB Control 2 */
+#define B2063_TX_BB_CTL3 B43_LP_RADIO(0x11A) /* TX BB Control 3 */
+#define B2063_TX_BB_CTL4 B43_LP_RADIO(0x11B) /* TX BB Control 4 */
+#define B2063_GPIO_CTL1 B43_LP_RADIO(0x11C) /* GPIO Control 1 */
+#define B2063_VREG_CTL1 B43_LP_RADIO(0x11D) /* VREG Control 1 */
+#define B2063_AMUX_CTL1 B43_LP_RADIO(0x11E) /* AMUX Control 1 */
+#define B2063_IQ_CALIB_GVAR B43_LP_RADIO(0x11F) /* IQ Calibration GVAR */
+#define B2063_IQ_CALIB_CTL1 B43_LP_RADIO(0x120) /* IQ Calibration Control 1 */
+#define B2063_IQ_CALIB_CTL2 B43_LP_RADIO(0x121) /* IQ Calibration Control 2 */
+#define B2063_TEMPSENSE_CTL1 B43_LP_RADIO(0x122) /* TEMPSENSE Control 1 */
+#define B2063_TEMPSENSE_CTL2 B43_LP_RADIO(0x123) /* TEMPSENSE Control 2 */
+#define B2063_TX_RX_LOOPBACK1 B43_LP_RADIO(0x124) /* TX/RX LOOPBACK 1 */
+#define B2063_TX_RX_LOOPBACK2 B43_LP_RADIO(0x125) /* TX/RX LOOPBACK 2 */
+#define B2063_EXT_TSSI_CTL1 B43_LP_RADIO(0x126) /* EXT TSSI Control 1 */
+#define B2063_EXT_TSSI_CTL2 B43_LP_RADIO(0x127) /* EXT TSSI Control 2 */
+#define B2063_AFE_CTL B43_LP_RADIO(0x128) /* AFE Control */
+
+
+
+struct b43_phy_lp {
+ //TODO
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lp;
+
+#endif /* LINUX_B43_PHY_LP_H_ */
diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/phy_n.c
index 644eed993be..8bcfda5f3f0 100644
--- a/drivers/net/wireless/b43/nphy.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -26,7 +26,7 @@
#include <linux/types.h>
#include "b43.h"
-#include "nphy.h"
+#include "phy_n.h"
#include "tables_nphy.h"
@@ -34,10 +34,16 @@ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
}
-void b43_nphy_xmitpower(struct b43_wldev *dev)
+static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
{//TODO
}
+static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
+ bool ignore_tssi)
+{//TODO
+ return B43_TXPWR_RES_DONE;
+}
+
static void b43_chantab_radio_upload(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e)
{
@@ -81,9 +87,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
//TODO
}
-/* Tune the hardware to a new channel. Don't call this directly.
- * Use b43_radio_selectchannel() */
-int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
+/* Tune the hardware to a new channel. */
+static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
{
const struct b43_nphy_channeltab_entry *tabent;
@@ -162,7 +167,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
msleep(1);
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
msleep(1);
- b43_radio_selectchannel(dev, dev->phy.channel, 0);
+ nphy_channel_switch(dev, dev->phy.channel);
b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
@@ -484,3 +489,140 @@ int b43_phy_initn(struct b43_wldev *dev)
b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
return 0;
}
+
+static int b43_nphy_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_n *nphy;
+
+ nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
+ if (!nphy)
+ return -ENOMEM;
+ dev->phy.n = nphy;
+
+ return 0;
+}
+
+static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
+
+ memset(nphy, 0, sizeof(*nphy));
+
+ //TODO init struct b43_phy_n
+}
+
+static void b43_nphy_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
+
+ kfree(nphy);
+ phy->n = NULL;
+}
+
+static int b43_nphy_op_init(struct b43_wldev *dev)
+{
+ return b43_phy_initn(dev);
+}
+
+static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
+{
+#if B43_DEBUG
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
+ /* OFDM registers are onnly available on A/G-PHYs */
+ b43err(dev->wl, "Invalid OFDM PHY access at "
+ "0x%04X on N-PHY\n", offset);
+ dump_stack();
+ }
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
+ /* Ext-G registers are only available on G-PHYs */
+ b43err(dev->wl, "Invalid EXT-G PHY access at "
+ "0x%04X on N-PHY\n", offset);
+ dump_stack();
+ }
+#endif /* B43_DEBUG */
+}
+
+static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
+{
+ check_phyreg(dev, reg);
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ check_phyreg(dev, reg);
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+ /* N-PHY needs 0x100 for read access */
+ reg |= 0x100;
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
+ enum rfkill_state state)
+{//TODO
+}
+
+static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
+ on ? 0 : 0x7FFF);
+}
+
+static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if ((new_channel < 1) || (new_channel > 14))
+ return -EINVAL;
+ } else {
+ if (new_channel > 200)
+ return -EINVAL;
+ }
+
+ return nphy_channel_switch(dev, new_channel);
+}
+
+static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ return 1;
+ return 36;
+}
+
+const struct b43_phy_operations b43_phyops_n = {
+ .allocate = b43_nphy_op_allocate,
+ .free = b43_nphy_op_free,
+ .prepare_structs = b43_nphy_op_prepare_structs,
+ .init = b43_nphy_op_init,
+ .phy_read = b43_nphy_op_read,
+ .phy_write = b43_nphy_op_write,
+ .radio_read = b43_nphy_op_radio_read,
+ .radio_write = b43_nphy_op_radio_write,
+ .software_rfkill = b43_nphy_op_software_rfkill,
+ .switch_analog = b43_nphy_op_switch_analog,
+ .switch_channel = b43_nphy_op_switch_channel,
+ .get_default_chan = b43_nphy_op_get_default_chan,
+ .recalc_txpower = b43_nphy_op_recalc_txpower,
+ .adjust_txpower = b43_nphy_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/phy_n.h
index faf46b9cbf1..1749aef4147 100644
--- a/drivers/net/wireless/b43/nphy.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -1,7 +1,7 @@
#ifndef B43_NPHY_H_
#define B43_NPHY_H_
-#include "phy.h"
+#include "phy_common.h"
/* N-PHY registers. */
@@ -919,54 +919,12 @@
struct b43_wldev;
+struct b43_phy_n {
+ //TODO lots of missing stuff
+};
-#ifdef CONFIG_B43_NPHY
-/* N-PHY support enabled */
-int b43_phy_initn(struct b43_wldev *dev);
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_n;
-void b43_nphy_radio_turn_on(struct b43_wldev *dev);
-void b43_nphy_radio_turn_off(struct b43_wldev *dev);
-
-int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
-
-void b43_nphy_xmitpower(struct b43_wldev *dev);
-void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
-
-
-#else /* CONFIG_B43_NPHY */
-/* N-PHY support disabled */
-
-
-static inline
-int b43_phy_initn(struct b43_wldev *dev)
-{
- return -EOPNOTSUPP;
-}
-
-static inline
-void b43_nphy_radio_turn_on(struct b43_wldev *dev)
-{
-}
-static inline
-void b43_nphy_radio_turn_off(struct b43_wldev *dev)
-{
-}
-
-static inline
-int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
-{
- return -ENOSYS;
-}
-
-static inline
-void b43_nphy_xmitpower(struct b43_wldev *dev)
-{
-}
-static inline
-void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
-{
-}
-
-#endif /* CONFIG_B43_NPHY */
#endif /* B43_NPHY_H_ */
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index fec5645944a..713753781f4 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -24,6 +24,7 @@
#include "rfkill.h"
#include "b43.h"
+#include "phy_common.h"
#include <linux/kmod.h>
@@ -43,23 +44,6 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
return 0;
}
-/* Update the rfkill state */
-static void b43_rfkill_update_state(struct b43_wldev *dev)
-{
- struct b43_rfkill *rfk = &(dev->wl->rfkill);
-
- if (!dev->radio_hw_enable) {
- rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
- return;
- }
-
- if (!dev->phy.radio_on)
- rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
- else
- rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
-
-}
-
/* The poll callback for the hardware button. */
static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
{
@@ -77,7 +61,6 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
- b43_rfkill_update_state(dev);
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
}
@@ -114,11 +97,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
goto out_unlock;
}
if (!dev->phy.radio_on)
- b43_radio_turn_on(dev);
+ b43_software_rfkill(dev, state);
break;
case RFKILL_STATE_SOFT_BLOCKED:
if (dev->phy.radio_on)
- b43_radio_turn_off(dev, 0);
+ b43_software_rfkill(dev, state);
break;
default:
b43warn(wl, "Received unexpected rfkill state %d.\n", state);
@@ -187,6 +170,11 @@ void b43_rfkill_init(struct b43_wldev *dev)
"The built-in radio LED will not work.\n");
#endif /* CONFIG_RFKILL_INPUT */
+#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
+ b43warn(wl, "The rfkill-input subsystem is not available. "
+ "The built-in radio LED will not work.\n");
+#endif
+
err = input_register_polled_device(rfk->poll_dev);
if (err)
goto err_unreg_rfk;
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 275095b8cbe..5adaa3692d7 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -29,7 +29,7 @@
#include "b43.h"
#include "sysfs.h"
#include "main.h"
-#include "phy.h"
+#include "phy_common.h"
#define GENERIC_FILESIZE 64
@@ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev,
mutex_lock(&wldev->wl->mutex);
- switch (wldev->phy.interfmode) {
+ if (wldev->phy.type != B43_PHYTYPE_G) {
+ mutex_unlock(&wldev->wl->mutex);
+ return -ENOSYS;
+ }
+
+ switch (wldev->phy.g->interfmode) {
case B43_INTERFMODE_NONE:
count =
snprintf(buf, PAGE_SIZE,
@@ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
mutex_lock(&wldev->wl->mutex);
spin_lock_irqsave(&wldev->wl->irq_lock, flags);
- err = b43_radio_set_interference_mitigation(wldev, mode);
- if (err) {
- b43err(wldev->wl, "Interference Mitigation not "
- "supported by device\n");
- }
+ if (wldev->phy.ops->interf_mitigation) {
+ err = wldev->phy.ops->interf_mitigation(wldev, mode);
+ if (err) {
+ b43err(wldev->wl, "Interference Mitigation not "
+ "supported by device\n");
+ }
+ } else
+ err = -ENOSYS;
+
mmiowb();
spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
mutex_unlock(&wldev->wl->mutex);
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 3f5ea06bf13..1ef9a6463ec 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -27,7 +27,8 @@
#include "b43.h"
#include "tables.h"
-#include "phy.h"
+#include "phy_g.h"
+
const u32 b43_tab_rotor[] = {
0xFEB93FFD, 0xFEC63FFD, /* 0 */
@@ -377,17 +378,17 @@ static inline void assert_sizes(void)
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
- if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
- (addr - 1 != phy->ofdmtab_addr)) {
+ if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+ (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
- phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+ gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
}
- phy->ofdmtab_addr = addr;
+ gphy->ofdmtab_addr = addr;
return b43_phy_read(dev, B43_PHY_OTABLEI);
@@ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
u16 offset, u16 value)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
- if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
- (addr - 1 != phy->ofdmtab_addr)) {
+ if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+ (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
- phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+ gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
}
- phy->ofdmtab_addr = addr;
+ gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value);
}
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
u32 ret;
u16 addr;
addr = table + offset;
- if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
- (addr - 1 != phy->ofdmtab_addr)) {
+ if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+ (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
- phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+ gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
}
- phy->ofdmtab_addr = addr;
+ gphy->ofdmtab_addr = addr;
ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
ret <<= 16;
ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
@@ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
u16 offset, u32 value)
{
- struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = dev->phy.g;
u16 addr;
addr = table + offset;
- if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
- (addr - 1 != phy->ofdmtab_addr)) {
+ if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+ (addr - 1 != gphy->ofdmtab_addr)) {
/* The hardware has a different address in memory. Update it. */
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
- phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+ gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
}
- phy->ofdmtab_addr = addr;
+ gphy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value);
b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 2aa57551786..4e233631554 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -24,8 +24,8 @@
#include "b43.h"
#include "tables_nphy.h"
-#include "phy.h"
-#include "nphy.h"
+#include "phy_common.h"
+#include "phy_n.h"
struct b2055_inittab_entry {
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
index daa94211f83..0c0fb15abb9 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -27,7 +27,7 @@
#include "b43.h"
#include "main.h"
#include "tables.h"
-#include "phy.h"
+#include "phy_common.h"
#include "wa.h"
static void b43_wa_papd(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 9dda8169f7c..2fabcf8f047 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -28,7 +28,7 @@
*/
#include "xmit.h"
-#include "phy.h"
+#include "phy_common.h"
#include "dma.h"
#include "pio.h"
@@ -208,7 +208,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
rate_ofdm = b43_is_ofdm_rate(rate);
- fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate;
+ fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
rate_fb = fbrate->hw_value;
rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
@@ -252,7 +252,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
}
/* Hardware appends ICV. */
- plcp_fragment_len += info->control.icv_len;
+ plcp_fragment_len += info->control.hw_key->icv_len;
key_idx = b43_kidx_to_fw(dev, key_idx);
mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
@@ -260,7 +260,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
B43_TXH_MAC_KEYALG;
wlhdr_len = ieee80211_hdrlen(fctl);
- iv_len = min((size_t) info->control.iv_len,
+ iv_len = min((size_t) info->control.hw_key->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
@@ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
int adjust_2053, int adjust_2050)
{
struct b43_phy *phy = &dev->phy;
+ struct b43_phy_g *gphy = phy->g;
s32 tmp;
switch (phy->radio_ver) {
@@ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
- tmp = phy->nrssi_lt[in_rssi];
+ B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+ tmp = gphy->nrssi_lt[in_rssi];
tmp = 31 - tmp;
tmp *= -131;
tmp /= 128;
@@ -678,6 +680,8 @@ void b43_handle_txstatus(struct b43_wldev *dev,
b43_pio_handle_txstatus(dev, status);
else
b43_dma_handle_txstatus(dev, status);
+
+ b43_phy_txpower_check(dev, 0);
}
/* Fill out the mac80211 TXstatus report based on the b43-specific
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1cb77db5c29..c66d57560e7 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -888,13 +888,13 @@ generate_new:
static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
{
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
/* TODO: PS TBTT */
} else {
if (1/*FIXME: the last PSpoll frame was sent successfully */)
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
dev->dfq_valid = 1;
}
@@ -1201,7 +1201,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
struct b43legacy_wl *wl = dev->wl;
u32 cmd;
- if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
return;
/* This is the bottom half of the asynchronous beacon update. */
@@ -1936,9 +1936,9 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
ctl &= ~B43legacy_MACCTL_BEACPROMISC;
ctl |= B43legacy_MACCTL_INFRA;
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
ctl |= B43legacy_MACCTL_AP;
- else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
+ else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))
ctl &= ~B43legacy_MACCTL_INFRA;
if (wl->filter_flags & FIF_CONTROL)
@@ -2646,7 +2646,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
b43legacy_mgmtframe_txantenna(dev, antenna_tx);
/* Update templates for AP mode. */
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
b43legacy_set_beacon_int(dev, conf->beacon_int);
@@ -2733,12 +2733,12 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
else
memset(wl->bssid, 0, ETH_ALEN);
if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
- B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
+ if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
+ B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
- } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
+ } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
}
@@ -3020,7 +3020,7 @@ static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
bool idle) {
u16 pu_delay = 1050;
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
pu_delay = 500;
if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
pu_delay = max(pu_delay, (u16)2400);
@@ -3035,7 +3035,7 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
u16 pretbtt;
/* The time value is in microseconds. */
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
pretbtt = 2;
else
pretbtt = 250;
@@ -3259,10 +3259,10 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
- if (conf->type != IEEE80211_IF_TYPE_AP &&
- conf->type != IEEE80211_IF_TYPE_STA &&
- conf->type != IEEE80211_IF_TYPE_WDS &&
- conf->type != IEEE80211_IF_TYPE_IBSS)
+ if (conf->type != NL80211_IFTYPE_AP &&
+ conf->type != NL80211_IFTYPE_STATION &&
+ conf->type != NL80211_IFTYPE_WDS &&
+ conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
@@ -3403,7 +3403,7 @@ out_unlock:
}
static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
- int aid, int set)
+ struct ieee80211_sta *sta, bool set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
@@ -3704,7 +3704,13 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_ADHOC);
hw->queues = 1; /* FIXME: hardware has more queues */
+ hw->max_altrates = 1;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 768cccb9b1b..4c9442b16f3 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -103,7 +103,7 @@ void b43legacy_phy_lock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_suspend(dev);
} else {
- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, 1);
}
}
@@ -118,7 +118,7 @@ void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_enable(dev);
} else {
- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
}
@@ -595,12 +595,14 @@ static void b43legacy_phy_initb5(struct b43legacy_wldev *dev)
0x0035) & 0xFFC0) | 0x0064);
b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
0x005D) & 0xFF80) | 0x000A);
+ b43legacy_phy_write(dev, 0x5B, 0x0000);
+ b43legacy_phy_write(dev, 0x5C, 0x0000);
}
if (dev->bad_frames_preempt)
b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
b43legacy_phy_read(dev,
- B43legacy_PHY_RADIO_BITFIELD) | (1 << 11));
+ B43legacy_PHY_RADIO_BITFIELD) | (1 << 12));
if (phy->analog == 1) {
b43legacy_phy_write(dev, 0x0026, 0xCE00);
@@ -753,7 +755,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_radio_write16(dev, 0x0050, 0x0020);
}
if (phy->radio_rev <= 2) {
- b43legacy_radio_write16(dev, 0x007C, 0x0020);
+ b43legacy_radio_write16(dev, 0x0050, 0x0020);
b43legacy_radio_write16(dev, 0x005A, 0x0070);
b43legacy_radio_write16(dev, 0x005B, 0x007B);
b43legacy_radio_write16(dev, 0x005C, 0x00B0);
@@ -771,7 +773,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x002A, 0x8AC0);
b43legacy_phy_write(dev, 0x0038, 0x0668);
b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
- if (phy->radio_rev <= 5)
+ if (phy->radio_rev == 4 || phy->radio_rev == 5)
b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
0x005D) & 0xFF80) | 0x0003);
if (phy->radio_rev <= 2)
@@ -1010,7 +1012,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_initb5(dev);
else
b43legacy_phy_initb6(dev);
- if (phy->rev >= 2 || phy->gmode)
+ if (phy->rev >= 2 && phy->gmode)
b43legacy_phy_inita(dev);
if (phy->rev >= 2) {
@@ -1025,18 +1027,22 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0811, 0x0400);
b43legacy_phy_write(dev, 0x0015, 0x00C0);
}
- if (phy->rev >= 2 || phy->gmode) {
+ if (phy->gmode) {
tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF;
- if (tmp == 3 || tmp == 5) {
+ if (tmp == 3) {
+ b43legacy_phy_write(dev, 0x04C2, 0x1816);
+ b43legacy_phy_write(dev, 0x04C3, 0x8606);
+ }
+ if (tmp == 4 || tmp == 5) {
b43legacy_phy_write(dev, 0x04C2, 0x1816);
b43legacy_phy_write(dev, 0x04C3, 0x8006);
- if (tmp == 5)
- b43legacy_phy_write(dev, 0x04CC,
- (b43legacy_phy_read(dev,
- 0x04CC) & 0x00FF) |
- 0x1F00);
+ b43legacy_phy_write(dev, 0x04CC,
+ (b43legacy_phy_read(dev,
+ 0x04CC) & 0x00FF) |
+ 0x1F00);
}
- b43legacy_phy_write(dev, 0x047E, 0x0078);
+ if (phy->rev >= 2)
+ b43legacy_phy_write(dev, 0x047E, 0x0078);
}
if (phy->radio_rev == 8) {
b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801)
@@ -1078,7 +1084,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
else
b43legacy_phy_write(dev, 0x002F, 0x0202);
}
- if (phy->gmode || phy->rev >= 2) {
+ if (phy->gmode) {
b43legacy_phy_lo_adjust(dev, 0);
b43legacy_phy_write(dev, 0x080F, 0x8078);
}
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 476add97e97..b32bf6a94f1 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -44,23 +44,6 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
return 0;
}
-/* Update the rfkill state */
-static void b43legacy_rfkill_update_state(struct b43legacy_wldev *dev)
-{
- struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
-
- if (!dev->radio_hw_enable) {
- rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
- return;
- }
-
- if (!dev->phy.radio_on)
- rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
- else
- rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
-
-}
-
/* The poll callback for the hardware button. */
static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
{
@@ -78,7 +61,6 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
- b43legacy_rfkill_update_state(dev);
b43legacyinfo(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
}
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 68e1f8c7872..65e83378160 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -193,7 +193,6 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
{
const struct ieee80211_hdr *wlhdr;
int use_encryption = !!info->control.hw_key;
- u16 fctl;
u8 rate;
struct ieee80211_rate *rate_fb;
int rate_ofdm;
@@ -204,7 +203,6 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
struct ieee80211_rate *tx_rate;
wlhdr = (const struct ieee80211_hdr *)fragment_data;
- fctl = le16_to_cpu(wlhdr->frame_control);
memset(txhdr, 0, sizeof(*txhdr));
@@ -212,7 +210,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
rate = tx_rate->hw_value;
rate_ofdm = b43legacy_is_ofdm_rate(rate);
- rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate;
+ rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
txhdr->mac_frame_ctl = wlhdr->frame_control;
@@ -245,7 +243,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
if (key->enabled) {
/* Hardware appends ICV. */
- plcp_fragment_len += info->control.icv_len;
+ plcp_fragment_len += info->control.hw_key->icv_len;
key_idx = b43legacy_kidx_to_fw(dev, key_idx);
mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
@@ -253,8 +251,8 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
mac_ctl |= (key->algorithm <<
B43legacy_TX4_MAC_KEYALG_SHIFT) &
B43legacy_TX4_MAC_KEYALG;
- wlhdr_len = ieee80211_get_hdrlen(fctl);
- iv_len = min((size_t)info->control.iv_len,
+ wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
+ iv_len = min((size_t)info->control.hw_key->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
} else {
@@ -626,7 +624,7 @@ void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
tmp = hw->count;
status.frame_count = (tmp >> 4);
status.rts_count = (tmp & 0x0F);
- tmp = hw->flags;
+ tmp = hw->flags << 1;
status.supp_reason = ((tmp & 0x1C) >> 2);
status.pm_indicated = !!(tmp & 0x80);
status.intermediate = !!(tmp & 0x40);
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 29d39105f5b..bfa375369df 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -87,7 +87,8 @@ MODULE_LICENSE("Dual MPL/GPL");
Callable from any context.
*/
-static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
+static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
+ u16 param1, u16 param2)
{
int k = CMD_BUSY_TIMEOUT;
u16 reg;
@@ -103,8 +104,8 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
return -EBUSY;
}
- hermes_write_regn(hw, PARAM2, 0);
- hermes_write_regn(hw, PARAM1, 0);
+ hermes_write_regn(hw, PARAM2, param2);
+ hermes_write_regn(hw, PARAM1, param1);
hermes_write_regn(hw, PARAM0, param0);
hermes_write_regn(hw, CMD, cmd);
@@ -115,16 +116,72 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
* Function definitions
*/
+/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
+int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+ u16 parm0, u16 parm1, u16 parm2,
+ struct hermes_response *resp)
+{
+ int err = 0;
+ int k;
+ u16 status, reg;
+
+ err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
+ if (err)
+ return err;
+
+ reg = hermes_read_regn(hw, EVSTAT);
+ k = CMD_INIT_TIMEOUT;
+ while ((!(reg & HERMES_EV_CMD)) && k) {
+ k--;
+ udelay(10);
+ reg = hermes_read_regn(hw, EVSTAT);
+ }
+
+ hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
+
+ if (!hermes_present(hw)) {
+ DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
+ hw->iobase);
+ err = -ENODEV;
+ goto out;
+ }
+
+ if (!(reg & HERMES_EV_CMD)) {
+ printk(KERN_ERR "hermes @ %p: "
+ "Timeout waiting for card to reset (reg=0x%04x)!\n",
+ hw->iobase, reg);
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ status = hermes_read_regn(hw, STATUS);
+ if (resp) {
+ resp->status = status;
+ resp->resp0 = hermes_read_regn(hw, RESP0);
+ resp->resp1 = hermes_read_regn(hw, RESP1);
+ resp->resp2 = hermes_read_regn(hw, RESP2);
+ }
+
+ hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
+
+ if (status & HERMES_STATUS_RESULT)
+ err = -EIO;
+out:
+ return err;
+}
+EXPORT_SYMBOL(hermes_doicmd_wait);
+
void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
{
hw->iobase = address;
hw->reg_spacing = reg_spacing;
hw->inten = 0x0;
}
+EXPORT_SYMBOL(hermes_struct_init);
int hermes_init(hermes_t *hw)
{
- u16 status, reg;
+ u16 reg;
int err = 0;
int k;
@@ -162,45 +219,11 @@ int hermes_init(hermes_t *hw)
/* We don't use hermes_docmd_wait here, because the reset wipes
the magic constant in SWSUPPORT0 away, and it gets confused */
- err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0);
- if (err)
- return err;
-
- reg = hermes_read_regn(hw, EVSTAT);
- k = CMD_INIT_TIMEOUT;
- while ( (! (reg & HERMES_EV_CMD)) && k) {
- k--;
- udelay(10);
- reg = hermes_read_regn(hw, EVSTAT);
- }
-
- hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
-
- if (! hermes_present(hw)) {
- DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
- hw->iobase);
- err = -ENODEV;
- goto out;
- }
-
- if (! (reg & HERMES_EV_CMD)) {
- printk(KERN_ERR "hermes @ %p: "
- "Timeout waiting for card to reset (reg=0x%04x)!\n",
- hw->iobase, reg);
- err = -ETIMEDOUT;
- goto out;
- }
+ err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
- status = hermes_read_regn(hw, STATUS);
-
- hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
-
- if (status & HERMES_STATUS_RESULT)
- err = -EIO;
-
- out:
return err;
}
+EXPORT_SYMBOL(hermes_init);
/* Issue a command to the chip, and (busy!) wait for it to
* complete.
@@ -216,7 +239,7 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
u16 reg;
u16 status;
- err = hermes_issue_cmd(hw, cmd, parm0);
+ err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
if (err) {
if (! hermes_present(hw)) {
if (net_ratelimit())
@@ -271,6 +294,7 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
out:
return err;
}
+EXPORT_SYMBOL(hermes_docmd_wait);
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
{
@@ -313,7 +337,7 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
return 0;
}
-
+EXPORT_SYMBOL(hermes_allocate);
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
*
@@ -397,6 +421,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
out:
return err;
}
+EXPORT_SYMBOL(hermes_bap_pread);
/* Write a block of data to the chip's buffer, via the
* BAP. Synchronization/serialization is the caller's problem.
@@ -422,6 +447,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
out:
return err;
}
+EXPORT_SYMBOL(hermes_bap_pwrite);
/* Read a Length-Type-Value record from the card.
*
@@ -463,7 +489,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
if (rtype != rid)
printk(KERN_WARNING "hermes @ %p: %s(): "
"rid (0x%04x) does not match type (0x%04x)\n",
- hw->iobase, __FUNCTION__, rid, rtype);
+ hw->iobase, __func__, rid, rtype);
if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
printk(KERN_WARNING "hermes @ %p: "
"Truncating LTV record from %d to %d bytes. "
@@ -475,6 +501,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
return 0;
}
+EXPORT_SYMBOL(hermes_read_ltv);
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
u16 length, const void *value)
@@ -497,20 +524,11 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
hermes_write_bytes(hw, dreg, value, count << 1);
- err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
+ err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
rid, NULL);
return err;
}
-
-EXPORT_SYMBOL(hermes_struct_init);
-EXPORT_SYMBOL(hermes_init);
-EXPORT_SYMBOL(hermes_docmd_wait);
-EXPORT_SYMBOL(hermes_allocate);
-
-EXPORT_SYMBOL(hermes_bap_pread);
-EXPORT_SYMBOL(hermes_bap_pwrite);
-EXPORT_SYMBOL(hermes_read_ltv);
EXPORT_SYMBOL(hermes_write_ltv);
static int __init init_hermes(void)
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 8e3f0e3edb5..8b13c8fef3d 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -179,17 +179,23 @@
#define HERMES_802_11_OFFSET (14)
#define HERMES_802_3_OFFSET (14+32)
#define HERMES_802_2_OFFSET (14+32+14)
+#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
#define HERMES_RXSTAT_ERR (0x0003)
#define HERMES_RXSTAT_BADCRC (0x0001)
#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
+#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */
#define HERMES_RXSTAT_MACPORT (0x0700)
#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
+#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */
#define HERMES_RXSTAT_MSGTYPE (0xE000)
#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
+/* Shift amount for key ID in RXSTAT and TXCTRL */
+#define HERMES_MIC_KEY_ID_SHIFT 11
+
struct hermes_tx_descriptor {
__le16 status;
__le16 reserved1;
@@ -208,6 +214,8 @@ struct hermes_tx_descriptor {
#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */
#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */
#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */
+#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */
+#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */
#define HERMES_TXCTRL_ALT_RTRY (0x0020)
/* Inquiry constants and data types */
@@ -302,6 +310,40 @@ union hermes_scan_info {
struct symbol_scan_apinfo s;
};
+/* Extended scan struct for HERMES_INQ_CHANNELINFO.
+ * wl_lkm calls this an ACS scan (Automatic Channel Select).
+ * Keep out of union hermes_scan_info because it is much bigger than
+ * the older scan structures. */
+struct agere_ext_scan_info {
+ __le16 reserved0;
+
+ u8 noise;
+ u8 level;
+ u8 rx_flow;
+ u8 rate;
+ __le16 reserved1[2];
+
+ __le16 frame_control;
+ __le16 dur_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ __le16 sequence;
+ u8 addr4[ETH_ALEN];
+
+ __le16 data_length;
+
+ /* Next 3 fields do not get filled in. */
+ u8 daddr[ETH_ALEN];
+ u8 saddr[ETH_ALEN];
+ __le16 len_type;
+
+ __le64 timestamp;
+ __le16 beacon_interval;
+ __le16 capabilities;
+ u8 data[316];
+} __attribute__ ((packed));
+
#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
#define HERMES_LINKSTATUS_CONNECTED (0x0001)
#define HERMES_LINKSTATUS_DISCONNECTED (0x0002)
@@ -353,6 +395,9 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
int hermes_init(hermes_t *hw);
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
struct hermes_response *resp);
+int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+ u16 parm0, u16 parm1, u16 parm2,
+ struct hermes_response *resp);
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
diff --git a/drivers/net/wireless/hermes_dld.c b/drivers/net/wireless/hermes_dld.c
new file mode 100644
index 00000000000..d8c626e61a3
--- /dev/null
+++ b/drivers/net/wireless/hermes_dld.c
@@ -0,0 +1,730 @@
+/*
+ * Hermes download helper driver.
+ *
+ * This could be entirely merged into hermes.c.
+ *
+ * I'm keeping it separate to minimise the amount of merging between
+ * kernel upgrades. It also means the memory overhead for drivers that
+ * don't need firmware download low.
+ *
+ * This driver:
+ * - is capable of writing to the volatile area of the hermes device
+ * - is currently not capable of writing to non-volatile areas
+ * - provide helpers to identify and update plugin data
+ * - is not capable of interpreting a fw image directly. That is up to
+ * the main card driver.
+ * - deals with Hermes I devices. It can probably be modified to deal
+ * with Hermes II devices
+ *
+ * Copyright (C) 2007, David Kilroy
+ *
+ * Plug data code slightly modified from spectrum_cs driver
+ * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
+ * Portions based on information in wl_lkm_718 Agere driver
+ * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "hermes.h"
+#include "hermes_dld.h"
+
+MODULE_DESCRIPTION("Download helper for Lucent Hermes chipset");
+MODULE_AUTHOR("David Kilroy <kilroyd@gmail.com>");
+MODULE_LICENSE("Dual MPL/GPL");
+
+#define PFX "hermes_dld: "
+
+/*
+ * AUX port access. To unlock the AUX port write the access keys to the
+ * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
+ * register. Then read it and make sure it's HERMES_AUX_ENABLED.
+ */
+#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
+#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
+#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
+#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
+
+#define HERMES_AUX_PW0 0xFE01
+#define HERMES_AUX_PW1 0xDC23
+#define HERMES_AUX_PW2 0xBA45
+
+/* HERMES_CMD_DOWNLD */
+#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
+
+/* End markers used in dblocks */
+#define PDI_END 0x00000000 /* End of PDA */
+#define BLOCK_END 0xFFFFFFFF /* Last image block */
+#define TEXT_END 0x1A /* End of text header */
+
+/*
+ * PDA == Production Data Area
+ *
+ * In principle, the max. size of the PDA is is 4096 words. Currently,
+ * however, only about 500 bytes of this area are used.
+ *
+ * Some USB implementations can't handle sizes in excess of 1016. Note
+ * that PDA is not actually used in those USB environments, but may be
+ * retrieved by common code.
+ */
+#define MAX_PDA_SIZE 1000
+
+/* Limit the amout we try to download in a single shot.
+ * Size is in bytes.
+ */
+#define MAX_DL_SIZE 1024
+#define LIMIT_PROGRAM_SIZE 0
+
+/*
+ * The following structures have little-endian fields denoted by
+ * the leading underscore. Don't access them directly - use inline
+ * functions defined below.
+ */
+
+/*
+ * The binary image to be downloaded consists of series of data blocks.
+ * Each block has the following structure.
+ */
+struct dblock {
+ __le32 addr; /* adapter address where to write the block */
+ __le16 len; /* length of the data only, in bytes */
+ char data[0]; /* data to be written */
+} __attribute__ ((packed));
+
+/*
+ * Plug Data References are located in in the image after the last data
+ * block. They refer to areas in the adapter memory where the plug data
+ * items with matching ID should be written.
+ */
+struct pdr {
+ __le32 id; /* record ID */
+ __le32 addr; /* adapter address where to write the data */
+ __le32 len; /* expected length of the data, in bytes */
+ char next[0]; /* next PDR starts here */
+} __attribute__ ((packed));
+
+/*
+ * Plug Data Items are located in the EEPROM read from the adapter by
+ * primary firmware. They refer to the device-specific data that should
+ * be plugged into the secondary firmware.
+ */
+struct pdi {
+ __le16 len; /* length of ID and data, in words */
+ __le16 id; /* record ID */
+ char data[0]; /* plug data */
+} __attribute__ ((packed));
+
+/*** FW data block access functions ***/
+
+static inline u32
+dblock_addr(const struct dblock *blk)
+{
+ return le32_to_cpu(blk->addr);
+}
+
+static inline u32
+dblock_len(const struct dblock *blk)
+{
+ return le16_to_cpu(blk->len);
+}
+
+/*** PDR Access functions ***/
+
+static inline u32
+pdr_id(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->id);
+}
+
+static inline u32
+pdr_addr(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->addr);
+}
+
+static inline u32
+pdr_len(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->len);
+}
+
+/*** PDI Access functions ***/
+
+static inline u32
+pdi_id(const struct pdi *pdi)
+{
+ return le16_to_cpu(pdi->id);
+}
+
+/* Return length of the data only, in bytes */
+static inline u32
+pdi_len(const struct pdi *pdi)
+{
+ return 2 * (le16_to_cpu(pdi->len) - 1);
+}
+
+/*** Hermes AUX control ***/
+
+static inline void
+hermes_aux_setaddr(hermes_t *hw, u32 addr)
+{
+ hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
+ hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
+}
+
+static inline int
+hermes_aux_control(hermes_t *hw, int enabled)
+{
+ int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
+ int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
+ int i;
+
+ /* Already open? */
+ if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
+ return 0;
+
+ hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
+ hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
+ hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
+ hermes_write_reg(hw, HERMES_CONTROL, action);
+
+ for (i = 0; i < 20; i++) {
+ udelay(10);
+ if (hermes_read_reg(hw, HERMES_CONTROL) ==
+ desired_state)
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+/*** Plug Data Functions ***/
+
+/*
+ * Scan PDR for the record with the specified RECORD_ID.
+ * If it's not found, return NULL.
+ */
+static struct pdr *
+hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
+{
+ struct pdr *pdr = first_pdr;
+ void *end = (void *)first_pdr + MAX_PDA_SIZE;
+
+ while (((void *)pdr < end) &&
+ (pdr_id(pdr) != PDI_END)) {
+ /*
+ * PDR area is currently not terminated by PDI_END.
+ * It's followed by CRC records, which have the type
+ * field where PDR has length. The type can be 0 or 1.
+ */
+ if (pdr_len(pdr) < 2)
+ return NULL;
+
+ /* If the record ID matches, we are done */
+ if (pdr_id(pdr) == record_id)
+ return pdr;
+
+ pdr = (struct pdr *) pdr->next;
+ }
+ return NULL;
+}
+
+/* Scan production data items for a particular entry */
+static struct pdi *
+hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
+{
+ struct pdi *pdi = first_pdi;
+
+ while (pdi_id(pdi) != PDI_END) {
+
+ /* If the record ID matches, we are done */
+ if (pdi_id(pdi) == record_id)
+ return pdi;
+
+ pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
+ }
+ return NULL;
+}
+
+/* Process one Plug Data Item - find corresponding PDR and plug it */
+static int
+hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi)
+{
+ struct pdr *pdr;
+
+ /* Find the PDR corresponding to this PDI */
+ pdr = hermes_find_pdr(first_pdr, pdi_id(pdi));
+
+ /* No match is found, safe to ignore */
+ if (!pdr)
+ return 0;
+
+ /* Lengths of the data in PDI and PDR must match */
+ if (pdi_len(pdi) != pdr_len(pdr))
+ return -EINVAL;
+
+ /* do the actual plugging */
+ hermes_aux_setaddr(hw, pdr_addr(pdr));
+ hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
+
+ return 0;
+}
+
+/* Read PDA from the adapter */
+int hermes_read_pda(hermes_t *hw,
+ __le16 *pda,
+ u32 pda_addr,
+ u16 pda_len,
+ int use_eeprom) /* can we get this into hw? */
+{
+ int ret;
+ u16 pda_size;
+ u16 data_len = pda_len;
+ __le16 *data = pda;
+
+ if (use_eeprom) {
+ /* PDA of spectrum symbol is in eeprom */
+
+ /* Issue command to read EEPROM */
+ ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
+ if (ret)
+ return ret;
+ } else {
+ /* wl_lkm does not include PDA size in the PDA area.
+ * We will pad the information into pda, so other routines
+ * don't have to be modified */
+ pda[0] = cpu_to_le16(pda_len - 2);
+ /* Includes CFG_PROD_DATA but not itself */
+ pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
+ data_len = pda_len - 4;
+ data = pda + 2;
+ }
+
+ /* Open auxiliary port */
+ ret = hermes_aux_control(hw, 1);
+ printk(KERN_DEBUG PFX "AUX enable returned %d\n", ret);
+ if (ret)
+ return ret;
+
+ /* read PDA from EEPROM */
+ hermes_aux_setaddr(hw, pda_addr);
+ hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
+
+ /* Close aux port */
+ ret = hermes_aux_control(hw, 0);
+ printk(KERN_DEBUG PFX "AUX disable returned %d\n", ret);
+
+ /* Check PDA length */
+ pda_size = le16_to_cpu(pda[0]);
+ printk(KERN_DEBUG PFX "Actual PDA length %d, Max allowed %d\n",
+ pda_size, pda_len);
+ if (pda_size > pda_len)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(hermes_read_pda);
+
+/* Parse PDA and write the records into the adapter
+ *
+ * Attempt to write every records that is in the specified pda
+ * which also has a valid production data record for the firmware.
+ */
+int hermes_apply_pda(hermes_t *hw,
+ const char *first_pdr,
+ const __le16 *pda)
+{
+ int ret;
+ const struct pdi *pdi;
+ struct pdr *pdr;
+
+ pdr = (struct pdr *) first_pdr;
+
+ /* Go through every PDI and plug them into the adapter */
+ pdi = (const struct pdi *) (pda + 2);
+ while (pdi_id(pdi) != PDI_END) {
+ ret = hermes_plug_pdi(hw, pdr, pdi);
+ if (ret)
+ return ret;
+
+ /* Increment to the next PDI */
+ pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)];
+ }
+ return 0;
+}
+EXPORT_SYMBOL(hermes_apply_pda);
+
+/* Identify the total number of bytes in all blocks
+ * including the header data.
+ */
+size_t
+hermes_blocks_length(const char *first_block)
+{
+ const struct dblock *blk = (const struct dblock *) first_block;
+ int total_len = 0;
+ int len;
+
+ /* Skip all blocks to locate Plug Data References
+ * (Spectrum CS) */
+ while (dblock_addr(blk) != BLOCK_END) {
+ len = dblock_len(blk);
+ total_len += sizeof(*blk) + len;
+ blk = (struct dblock *) &blk->data[len];
+ }
+
+ return total_len;
+}
+EXPORT_SYMBOL(hermes_blocks_length);
+
+/*** Hermes programming ***/
+
+/* About to start programming data (Hermes I)
+ * offset is the entry point
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+int hermesi_program_init(hermes_t *hw, u32 offset)
+{
+ int err;
+
+ /* Disable interrupts?*/
+ /*hw->inten = 0x0;*/
+ /*hermes_write_regn(hw, INTEN, 0);*/
+ /*hermes_set_irqmask(hw, 0);*/
+
+ /* Acknowledge any outstanding command */
+ hermes_write_regn(hw, EVACK, 0xFFFF);
+
+ /* Using doicmd_wait rather than docmd_wait */
+ err = hermes_doicmd_wait(hw,
+ 0x0100 | HERMES_CMD_INIT,
+ 0, 0, 0, NULL);
+ if (err)
+ return err;
+
+ err = hermes_doicmd_wait(hw,
+ 0x0000 | HERMES_CMD_INIT,
+ 0, 0, 0, NULL);
+ if (err)
+ return err;
+
+ err = hermes_aux_control(hw, 1);
+ printk(KERN_DEBUG PFX "AUX enable returned %d\n", err);
+
+ if (err)
+ return err;
+
+ printk(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
+ err = hermes_doicmd_wait(hw,
+ HERMES_PROGRAM_ENABLE_VOLATILE,
+ offset & 0xFFFFu,
+ offset >> 16,
+ 0,
+ NULL);
+ printk(KERN_DEBUG PFX "PROGRAM_ENABLE returned %d\n",
+ err);
+
+ return err;
+}
+EXPORT_SYMBOL(hermesi_program_init);
+
+/* Done programming data (Hermes I)
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+int hermesi_program_end(hermes_t *hw)
+{
+ struct hermes_response resp;
+ int rc = 0;
+ int err;
+
+ rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
+
+ printk(KERN_DEBUG PFX "PROGRAM_DISABLE returned %d, "
+ "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
+ rc, resp.resp0, resp.resp1, resp.resp2);
+
+ if ((rc == 0) &&
+ ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
+ rc = -EIO;
+
+ err = hermes_aux_control(hw, 0);
+ printk(KERN_DEBUG PFX "AUX disable returned %d\n", err);
+
+ /* Acknowledge any outstanding command */
+ hermes_write_regn(hw, EVACK, 0xFFFF);
+
+ /* Reinitialise, ignoring return */
+ (void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
+ 0, 0, 0, NULL);
+
+ return rc ? rc : err;
+}
+EXPORT_SYMBOL(hermesi_program_end);
+
+/* Program the data blocks */
+int hermes_program(hermes_t *hw, const char *first_block, const char *end)
+{
+ const struct dblock *blk;
+ u32 blkaddr;
+ u32 blklen;
+#if LIMIT_PROGRAM_SIZE
+ u32 addr;
+ u32 len;
+#endif
+
+ blk = (const struct dblock *) first_block;
+
+ if ((const char *) blk > (end - sizeof(*blk)))
+ return -EIO;
+
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+
+ while ((blkaddr != BLOCK_END) &&
+ (((const char *) blk + blklen) <= end)) {
+ printk(KERN_DEBUG PFX
+ "Programming block of length %d to address 0x%08x\n",
+ blklen, blkaddr);
+
+#if !LIMIT_PROGRAM_SIZE
+ /* wl_lkm driver splits this into writes of 2000 bytes */
+ hermes_aux_setaddr(hw, blkaddr);
+ hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
+ blklen);
+#else
+ len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
+ addr = blkaddr;
+
+ while (addr < (blkaddr + blklen)) {
+ printk(KERN_DEBUG PFX
+ "Programming subblock of length %d "
+ "to address 0x%08x. Data @ %p\n",
+ len, addr, &blk->data[addr - blkaddr]);
+
+ hermes_aux_setaddr(hw, addr);
+ hermes_write_bytes(hw, HERMES_AUXDATA,
+ &blk->data[addr - blkaddr],
+ len);
+
+ addr += len;
+ len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
+ (blkaddr + blklen - addr) : MAX_DL_SIZE;
+ }
+#endif
+ blk = (const struct dblock *) &blk->data[blklen];
+
+ if ((const char *) blk > (end - sizeof(*blk)))
+ return -EIO;
+
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(hermes_program);
+
+static int __init init_hermes_dld(void)
+{
+ return 0;
+}
+
+static void __exit exit_hermes_dld(void)
+{
+}
+
+module_init(init_hermes_dld);
+module_exit(exit_hermes_dld);
+
+/*** Default plugging data for Hermes I ***/
+/* Values from wl_lkm_718/hcf/dhf.c */
+
+#define DEFINE_DEFAULT_PDR(pid, length, data) \
+static const struct { \
+ __le16 len; \
+ __le16 id; \
+ u8 val[length]; \
+} __attribute__ ((packed)) default_pdr_data_##pid = { \
+ __constant_cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
+ sizeof(__le16)) - 1), \
+ __constant_cpu_to_le16(pid), \
+ data \
+}
+
+#define DEFAULT_PDR(pid) default_pdr_data_##pid
+
+/* HWIF Compatiblity */
+DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
+
+/* PPPPSign */
+DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
+
+/* PPPPProf */
+DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
+
+/* Antenna diversity */
+DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
+
+/* Modem VCO band Set-up */
+DEFINE_DEFAULT_PDR(0x0160, 28,
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00");
+
+/* Modem Rx Gain Table Values */
+DEFINE_DEFAULT_PDR(0x0161, 256,
+ "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+ "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+ "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+ "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+ "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
+ "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
+ "\x3B\x01\x3A\01\x3A\x01\x39\x01"
+ "\x39\x01\x38\01\x38\x01\x37\x01"
+ "\x37\x01\x36\01\x36\x01\x35\x01"
+ "\x35\x01\x34\01\x34\x01\x33\x01"
+ "\x33\x01\x32\x01\x32\x01\x31\x01"
+ "\x31\x01\x30\x01\x30\x01\x7B\x01"
+ "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
+ "\x79\x01\x78\x01\x78\x01\x77\x01"
+ "\x77\x01\x76\x01\x76\x01\x75\x01"
+ "\x75\x01\x74\x01\x74\x01\x73\x01"
+ "\x73\x01\x72\x01\x72\x01\x71\x01"
+ "\x71\x01\x70\x01\x70\x01\x68\x01"
+ "\x68\x01\x67\x01\x67\x01\x66\x01"
+ "\x66\x01\x65\x01\x65\x01\x57\x01"
+ "\x57\x01\x56\x01\x56\x01\x55\x01"
+ "\x55\x01\x54\x01\x54\x01\x53\x01"
+ "\x53\x01\x52\x01\x52\x01\x51\x01"
+ "\x51\x01\x50\x01\x50\x01\x48\x01"
+ "\x48\x01\x47\x01\x47\x01\x46\x01"
+ "\x46\x01\x45\x01\x45\x01\x44\x01"
+ "\x44\x01\x43\x01\x43\x01\x42\x01"
+ "\x42\x01\x41\x01\x41\x01\x40\x01"
+ "\x40\x01\x40\x01\x40\x01\x40\x01"
+ "\x40\x01\x40\x01\x40\x01\x40\x01"
+ "\x40\x01\x40\x01\x40\x01\x40\x01"
+ "\x40\x01\x40\x01\x40\x01\x40\x01");
+
+/* Write PDA according to certain rules.
+ *
+ * For every production data record, look for a previous setting in
+ * the pda, and use that.
+ *
+ * For certain records, use defaults if they are not found in pda.
+ */
+int hermes_apply_pda_with_defaults(hermes_t *hw,
+ const char *first_pdr,
+ const __le16 *pda)
+{
+ const struct pdr *pdr = (const struct pdr *) first_pdr;
+ struct pdi *first_pdi = (struct pdi *) &pda[2];
+ struct pdi *pdi;
+ struct pdi *default_pdi = NULL;
+ struct pdi *outdoor_pdi;
+ void *end = (void *)first_pdr + MAX_PDA_SIZE;
+ int record_id;
+
+ while (((void *)pdr < end) &&
+ (pdr_id(pdr) != PDI_END)) {
+ /*
+ * For spectrum_cs firmwares,
+ * PDR area is currently not terminated by PDI_END.
+ * It's followed by CRC records, which have the type
+ * field where PDR has length. The type can be 0 or 1.
+ */
+ if (pdr_len(pdr) < 2)
+ break;
+ record_id = pdr_id(pdr);
+
+ pdi = hermes_find_pdi(first_pdi, record_id);
+ if (pdi)
+ printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
+ record_id, pdi);
+
+ switch (record_id) {
+ case 0x110: /* Modem REFDAC values */
+ case 0x120: /* Modem VGDAC values */
+ outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1);
+ default_pdi = NULL;
+ if (outdoor_pdi) {
+ pdi = outdoor_pdi;
+ printk(KERN_DEBUG PFX
+ "Using outdoor record 0x%04x at %p\n",
+ record_id + 1, pdi);
+ }
+ break;
+ case 0x5: /* HWIF Compatiblity */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
+ break;
+ case 0x108: /* PPPPSign */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
+ break;
+ case 0x109: /* PPPPProf */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
+ break;
+ case 0x150: /* Antenna diversity */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
+ break;
+ case 0x160: /* Modem VCO band Set-up */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
+ break;
+ case 0x161: /* Modem Rx Gain Table Values */
+ default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
+ break;
+ default:
+ default_pdi = NULL;
+ break;
+ }
+ if (!pdi && default_pdi) {
+ /* Use default */
+ pdi = default_pdi;
+ printk(KERN_DEBUG PFX
+ "Using default record 0x%04x at %p\n",
+ record_id, pdi);
+ }
+
+ if (pdi) {
+ /* Lengths of the data in PDI and PDR must match */
+ if (pdi_len(pdi) == pdr_len(pdr)) {
+ /* do the actual plugging */
+ hermes_aux_setaddr(hw, pdr_addr(pdr));
+ hermes_write_bytes(hw, HERMES_AUXDATA,
+ pdi->data, pdi_len(pdi));
+ }
+ }
+
+ pdr++;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(hermes_apply_pda_with_defaults);
diff --git a/drivers/net/wireless/hermes_dld.h b/drivers/net/wireless/hermes_dld.h
new file mode 100644
index 00000000000..6fcb2627799
--- /dev/null
+++ b/drivers/net/wireless/hermes_dld.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007, David Kilroy
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+#ifndef _HERMES_DLD_H
+#define _HERMES_DLD_H
+
+#include "hermes.h"
+
+int hermesi_program_init(hermes_t *hw, u32 offset);
+int hermesi_program_end(hermes_t *hw);
+int hermes_program(hermes_t *hw, const char *first_block, const char *end);
+
+int hermes_read_pda(hermes_t *hw,
+ __le16 *pda,
+ u32 pda_addr,
+ u16 pda_len,
+ int use_eeprom);
+int hermes_apply_pda(hermes_t *hw,
+ const char *first_pdr,
+ const __le16 *pda);
+int hermes_apply_pda_with_defaults(hermes_t *hw,
+ const char *first_pdr,
+ const __le16 *pda);
+
+size_t hermes_blocks_length(const char *first_block);
+
+#endif /* _HERMES_DLD_H */
diff --git a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/hermes_rid.h
index 4f46b4809e5..42eb67dea1d 100644
--- a/drivers/net/wireless/hermes_rid.h
+++ b/drivers/net/wireless/hermes_rid.h
@@ -30,6 +30,7 @@
#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20
#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21
#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21
+#define HERMES_RID_CNFDROPUNENCRYPTED 0xFC22
#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23
#define HERMES_RID_CNFDEFAULTKEY0 0xFC24
#define HERMES_RID_CNFDEFAULTKEY1 0xFC25
@@ -85,6 +86,16 @@
#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2
#define HERMES_RID_CNFBASICRATES 0xFCB3
#define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4
+#define HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE 0xFCB4
+#define HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE 0xFCB5
+#define HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE 0xFCB6
+#define HERMES_RID_CNFADDMAPPEDTKIPKEY_AGERE 0xFCB7
+#define HERMES_RID_CNFREMMAPPEDTKIPKEY_AGERE 0xFCB8
+#define HERMES_RID_CNFSETWPACAPABILITIES_AGERE 0xFCB9
+#define HERMES_RID_CNFCACHEDPMKADDRESS 0xFCBA
+#define HERMES_RID_CNFREMOVEPMKADDRESS 0xFCBB
+#define HERMES_RID_CNFSCANCHANNELS2GHZ 0xFCC2
+#define HERMES_RID_CNFDISASSOCIATE 0xFCC8
#define HERMES_RID_CNFTICKTIME 0xFCE0
#define HERMES_RID_CNFSCANREQUEST 0xFCE1
#define HERMES_RID_CNFJOINREQUEST 0xFCE2
@@ -137,6 +148,12 @@
#define HERMES_RID_CURRENTTXRATE6 0xFD85
#define HERMES_RID_OWNMACADDR 0xFD86
#define HERMES_RID_SCANRESULTSTABLE 0xFD88
+#define HERMES_RID_CURRENT_COUNTRY_INFO 0xFD89
+#define HERMES_RID_CURRENT_WPA_IE 0xFD8A
+#define HERMES_RID_CURRENT_TKIP_IV 0xFD8B
+#define HERMES_RID_CURRENT_ASSOC_REQ_INFO 0xFD8C
+#define HERMES_RID_CURRENT_ASSOC_RESP_INFO 0xFD8D
+#define HERMES_RID_TXQUEUEEMPTY 0xFD91
#define HERMES_RID_PHYTYPE 0xFDC0
#define HERMES_RID_CURRENTCHANNEL 0xFDC1
#define HERMES_RID_CURRENTPOWERSTATE 0xFDC2
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 3b4e55cf33c..63374027735 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -234,7 +234,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
" res=%d\n", res);
}
@@ -246,7 +246,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
" res=%d\n", res);
}
@@ -305,7 +305,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
- pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
+ pcmcia_parse_tuple(&tuple, parse) ||
parse->longlink_mfc.nfn < 2) {
/* No multi-function links found */
ret = -ENODEV;
@@ -322,7 +322,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
reg.Value = COR_SOFT_RESET;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
dev->name, res);
goto done;
@@ -339,7 +339,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
dev->name, res);
goto done;
@@ -374,7 +374,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Value = 0;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
res);
return;
@@ -386,7 +386,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Value |= COR_SOFT_RESET;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
res);
return;
@@ -399,7 +399,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Value |= COR_IREQ_ENA;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
res);
return;
@@ -433,7 +433,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Value = 0;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
"(%d)\n", res);
return;
@@ -446,7 +446,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Value |= COR_SOFT_RESET;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
"(%d)\n", res);
return;
@@ -460,7 +460,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Offset = CISREG_CCSR;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
"(%d)\n", res);
return;
@@ -472,7 +472,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Value = old_cor & ~COR_SOFT_RESET;
res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
- if (res != CS_SUCCESS) {
+ if (res != 0) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
"(%d)\n", res);
return;
@@ -532,145 +532,118 @@ static void prism2_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-#define CFG_CHECK2(fn, retf) \
-do { int _ret = (retf); \
-if (_ret != 0) { \
- PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \
- cs_error(link, fn, _ret); \
- goto next_entry; \
-} \
-} while (0)
-
/* run after a CARD_INSERTION event is received to configure the PCMCIA
* socket and make the device available to the system */
+
+static int prism2_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
+ "(default 0x%02X)\n", cfg->index, dflt->index);
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !ignore_cis_vcc) {
+ PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
+ " this entry\n");
+ return -ENODEV;
+ }
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !ignore_cis_vcc) {
+ PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
+ "- skipping this entry\n");
+ return -ENODEV;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+ else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) {
+ /* At least Compaq WL200 does not have IRQInfo1 set,
+ * but it does not work without interrupts.. */
+ printk(KERN_WARNING "Config has no IRQ info, but trying to "
+ "enable IRQ anyway..\n");
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+ }
+
+ /* IO window settings */
+ PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
+ "dflt->io.nwin=%d\n",
+ cfg->io.nwin, dflt->io.nwin);
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
+ "io.base=0x%04x, len=%d\n", io->flags,
+ io->win[0].base, io->win[0].len);
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags &
+ CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int prism2_config(struct pcmcia_device *link)
{
struct net_device *dev;
struct hostap_interface *iface;
local_info_t *local;
int ret = 1;
- tuple_t tuple;
- cisparse_t *parse;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- cistpl_cftable_entry_t dflt = { 0 };
struct hostap_cs_priv *hw_priv;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
- parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
- if (parse == NULL || hw_priv == NULL) {
+ if (hw_priv == NULL) {
ret = -ENOMEM;
goto failed;
}
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
/* Look for an appropriate configuration table entry in the CIS */
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- for (;;) {
- cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
- CFG_CHECK2(GetTupleData,
- pcmcia_get_tuple_data(link, &tuple));
- CFG_CHECK2(ParseTuple,
- pcmcia_parse_tuple(link, &tuple, parse));
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- dflt = *cfg;
- if (cfg->index == 0)
- goto next_entry;
- link->conf.ConfigIndex = cfg->index;
- PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
- "(default 0x%02X)\n", cfg->index, dflt.index);
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
- 10000 && !ignore_cis_vcc) {
- PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
- " this entry\n");
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
- 10000 && !ignore_cis_vcc) {
- PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
- "- skipping this entry\n");
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
- else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) {
- /* At least Compaq WL200 does not have IRQInfo1 set,
- * but it does not work without interrupts.. */
- printk("Config has no IRQ info, but trying to enable "
- "IRQ anyway..\n");
- link->conf.Attributes |= CONF_ENABLE_IRQ;
- }
-
- /* IO window settings */
- PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
- "dflt.io.nwin=%d\n",
- cfg->io.nwin, dflt.io.nwin);
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
- "io.base=0x%04x, len=%d\n", io->flags,
- io->win[0].base, io->win[0].len);
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = io->flags &
- CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
- CFG_CHECK2(RequestIO,
- pcmcia_request_io(link, &link->io));
-
- /* This configuration table entry is OK */
- break;
-
- next_entry:
- CS_CHECK(GetNextTuple,
- pcmcia_get_next_tuple(link, &tuple));
+ last_ret = pcmcia_loop_config(link, prism2_config_check, NULL);
+ if (last_ret) {
+ if (!ignore_cis_vcc)
+ printk(KERN_ERR "GetNextTuple(): No matching "
+ "CIS configuration. Maybe you need the "
+ "ignore_cis_vcc=1 parameter.\n");
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
/* Need to allocate net_device before requesting IRQ handler */
@@ -738,14 +711,12 @@ static int prism2_config(struct pcmcia_device *link)
if (ret == 0 && local->ddev)
strcpy(hw_priv->node.dev_name, local->ddev->name);
}
- kfree(parse);
return ret;
cs_failed:
cs_error(link, last_fn, last_ret);
failed:
- kfree(parse);
kfree(hw_priv);
prism2_release((u_long)link);
return ret;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 19a401c4a0d..bca74811bc7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -211,7 +211,7 @@ static u32 ipw2100_debug_level = IPW_DL_NONE;
do { \
if (ipw2100_debug_level & (level)) { \
printk(KERN_DEBUG "ipw2100: %c %s ", \
- in_interrupt() ? 'I' : 'U', __FUNCTION__); \
+ in_interrupt() ? 'I' : 'U', __func__); \
printk(message); \
} \
} while (0)
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index d4ab28b73b3..0bad1ec3e7e 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1394,13 +1394,13 @@ BIT_ARG16(x)
#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)
+ in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
#ifdef CONFIG_IPW2200_DEBUG
#define IPW_LL_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)
+ in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
#else
#define IPW_LL_DEBUG(level, fmt, args...) do {} while (0)
#endif /* CONFIG_IPW2200_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
index f1d002f7b79..33016fb5e9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
@@ -34,12 +34,12 @@ extern u32 iwl3945_debug_level;
#define IWL_DEBUG(level, fmt, args...) \
do { if (iwl3945_debug_level & (level)) \
printk(KERN_ERR DRV_NAME": %c %s " fmt, \
- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+ in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
#define IWL_DEBUG_LIMIT(level, fmt, args...) \
do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
printk(KERN_ERR DRV_NAME": %c %s " fmt, \
- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+ in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
index 0b947511461..b3fe48de3ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
@@ -59,7 +59,7 @@
*
*/
-#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
+#define _iwl3945_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs))
#ifdef CONFIG_IWL3945_DEBUG
static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
u32 ofs, u32 val)
@@ -73,14 +73,14 @@ static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *
#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
#endif
-#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs))
+#define _iwl3945_read32(priv, ofs) ioread32((priv)->hw_base + (ofs))
#ifdef CONFIG_IWL3945_DEBUG
static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
{
IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
return _iwl3945_read32(priv, ofs);
}
-#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs)
+#define iwl3945_read32(priv, ofs)__iwl3945_read32(__FILE__, __LINE__, priv, ofs)
#else
#define iwl3945_read32(p, o) _iwl3945_read32(p, o)
#endif
@@ -153,28 +153,10 @@ static inline void __iwl3945_clear_bit(const char *f, u32 l,
static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv)
{
int ret;
- u32 gp_ctl;
-
#ifdef CONFIG_IWL3945_DEBUG
if (atomic_read(&priv->restrict_refcnt))
return 0;
#endif
- if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status)) {
- IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
- "wakes up NIC\n");
-
- /* 10 msec allows time for NIC to complete its data save */
- gp_ctl = _iwl3945_read32(priv, CSR_GP_CNTRL);
- if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
- IWL_DEBUG_RF_KILL("Wait for complete power-down, "
- "gpctl = 0x%08x\n", gp_ctl);
- mdelay(10);
- } else
- IWL_DEBUG_RF_KILL("power-down complete, "
- "gpctl = 0x%08x\n", gp_ctl);
- }
-
/* this bit wakes up the NIC */
_iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
ret = _iwl3945_poll_bit(priv, CSR_GP_CNTRL,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 10c64bdb314..6fc5e7361f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -36,8 +36,6 @@
#include <linux/workqueue.h>
-#include "../net/mac80211/rate.h"
-
#include "iwl-3945.h"
#define RS_NAME "iwl-3945-rs"
@@ -65,6 +63,9 @@ struct iwl3945_rs_sta {
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
+
+ /* used to be in sta_info */
+ int last_txrate_idx;
};
static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = {
@@ -316,9 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
}
}
-static void rs_rate_init(void *priv_rate, void *priv_sta,
- struct ieee80211_local *local, struct sta_info *sta)
+static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta)
{
+ struct iwl3945_rs_sta *rs_sta = priv_sta;
int i;
IWL_DEBUG_RATE("enter\n");
@@ -329,24 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* after assoc.. */
for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
- if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
- sta->txrate_idx = i;
+ if (sta->supp_rates[sband->band] & (1 << i)) {
+ rs_sta->last_txrate_idx = i;
break;
}
}
- sta->last_txrate_idx = sta->txrate_idx;
-
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
- if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
- sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ if (sband->band == IEEE80211_BAND_5GHZ)
+ rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
IWL_DEBUG_RATE("leave\n");
}
-static void *rs_alloc(struct ieee80211_local *local)
+static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
- return local->hw.priv;
+ return hw->priv;
}
/* rate scale requires free function to be implemented */
@@ -354,17 +354,24 @@ static void rs_free(void *priv)
{
return;
}
+
static void rs_clear(void *priv)
{
return;
}
-static void *rs_alloc_sta(void *priv, gfp_t gfp)
+static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
+ struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
int i;
+ /*
+ * XXX: If it's using sta->drv_priv anyway, it might
+ * as well just put all the information there.
+ */
+
IWL_DEBUG_RATE("enter\n");
rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
@@ -373,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp)
return NULL;
}
+ psta->rs_sta = rs_sta;
+
spin_lock_init(&rs_sta->lock);
rs_sta->start_rate = IWL_RATE_INVALID;
@@ -398,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp)
return rs_sta;
}
-static void rs_free_sta(void *priv, void *priv_sta)
+static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
+ void *priv_sta)
{
+ struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
struct iwl3945_rs_sta *rs_sta = priv_sta;
+ psta->rs_sta = NULL;
+
IWL_DEBUG_RATE("enter\n");
del_timer_sync(&rs_sta->rate_scale_flush);
kfree(rs_sta);
@@ -443,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
* NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
* the hardware for each rate.
*/
-static void rs_tx_status(void *priv_rate,
- struct net_device *dev,
+static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
u8 retries, current_count;
int scale_rate_index, first_index, last_index;
unsigned long flags;
- struct sta_info *sta;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iwl3945_rs_sta *rs_sta;
- struct ieee80211_supported_band *sband;
+ struct iwl3945_rs_sta *rs_sta = priv_sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
-
retries = info->status.retry_count;
first_index = sband->bitrates[info->tx_rate_idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
@@ -470,17 +476,11 @@ static void rs_tx_status(void *priv_rate,
return;
}
- rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
- if (!sta || !sta->rate_ctrl_priv) {
- rcu_read_unlock();
+ if (!priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
return;
}
- rs_sta = (void *)sta->rate_ctrl_priv;
-
rs_sta->tx_packets++;
scale_rate_index = first_index;
@@ -547,8 +547,6 @@ static void rs_tx_status(void *priv_rate,
spin_unlock_irqrestore(&rs_sta->lock, flags);
- rcu_read_unlock();
-
IWL_DEBUG_RATE("leave\n");
return;
@@ -632,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
* rate table and must reference the driver allocated rate table
*
*/
-static void rs_get_rate(void *priv_rate, struct net_device *dev,
- struct ieee80211_supported_band *sband,
- struct sk_buff *skb,
- struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
+ struct sk_buff *skb, struct rate_selection *sel)
{
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
int index;
- struct iwl3945_rs_sta *rs_sta;
+ struct iwl3945_rs_sta *rs_sta = priv_sta;
struct iwl3945_rate_scale_data *window = NULL;
int current_tpt = IWL_INV_TPT;
int low_tpt = IWL_INV_TPT;
@@ -649,40 +646,31 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
u32 fail_count;
s8 scale_action = 0;
unsigned long flags;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct sta_info *sta;
u16 fc, rate_mask;
- struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RATE("enter\n");
- rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
+ !sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- sel->rate_idx = rate_lowest_index(local, sband, sta);
- rcu_read_unlock();
+ sel->rate_idx = rate_lowest_index(sband, sta);
return;
}
rate_mask = sta->supp_rates[sband->band];
- index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
+ index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
- rs_sta = (void *)sta->rate_ctrl_priv;
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!rs_sta->ibss_sta_added) {
u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
@@ -803,17 +791,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
out:
- sta->last_txrate_idx = index;
+ rs_sta->last_txrate_idx = index;
if (sband->band == IEEE80211_BAND_5GHZ)
- sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+ sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
else
- sta->txrate_idx = sta->last_txrate_idx;
-
- rcu_read_unlock();
+ sel->rate_idx = rs_sta->last_txrate_idx;
IWL_DEBUG_RATE("leave: %d\n", index);
-
- sel->rate_idx = sta->txrate_idx;
}
static struct rate_control_ops rs_ops = {
@@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = {
.free_sta = rs_free_sta,
};
-int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
-{
- struct ieee80211_local *local = hw_to_local(hw);
- struct iwl3945_priv *priv = hw->priv;
- struct iwl3945_rs_sta *rs_sta;
- struct sta_info *sta;
- unsigned long flags;
- int count = 0, i;
- u32 samples = 0, success = 0, good = 0;
- unsigned long now = jiffies;
- u32 max_time = 0;
-
- rcu_read_lock();
-
- sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
- if (!sta || !sta->rate_ctrl_priv) {
- if (sta)
- IWL_DEBUG_RATE("leave - no private rate data!\n");
- else
- IWL_DEBUG_RATE("leave - no station!\n");
- rcu_read_unlock();
- return sprintf(buf, "station %d not found\n", sta_id);
- }
-
- rs_sta = (void *)sta->rate_ctrl_priv;
- spin_lock_irqsave(&rs_sta->lock, flags);
- i = IWL_RATE_54M_INDEX;
- while (1) {
- u64 mask;
- int j;
-
- count +=
- sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2);
-
- mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
- for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
- buf[count++] =
- (rs_sta->win[i].data & mask) ? '1' : '0';
-
- samples += rs_sta->win[i].counter;
- good += rs_sta->win[i].success_counter;
- success += rs_sta->win[i].success_counter *
- iwl3945_rates[i].ieee;
-
- if (rs_sta->win[i].stamp) {
- int delta =
- jiffies_to_msecs(now - rs_sta->win[i].stamp);
-
- if (delta > max_time)
- max_time = delta;
-
- count += sprintf(&buf[count], "%5dms\n", delta);
- } else
- buf[count++] = '\n';
-
- j = iwl3945_get_prev_ieee_rate(i);
- if (j == i)
- break;
- i = j;
- }
- spin_unlock_irqrestore(&rs_sta->lock, flags);
- rcu_read_unlock();
-
- /* Display the average rate of all samples taken.
- *
- * NOTE: We multiple # of samples by 2 since the IEEE measurement
- * added from iwl3945_rates is actually 2X the rate */
- if (samples)
- count += sprintf(
- &buf[count],
- "\nAverage rate is %3d.%02dMbs over last %4dms\n"
- "%3d%% success (%d good packets over %d tries)\n",
- success / (2 * samples), (success * 5 / samples) % 10,
- max_time, good * 100 / samples, good, samples);
- else
- count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");
-
- return count;
-}
-
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
struct iwl3945_priv *priv = hw->priv;
s32 rssi = 0;
unsigned long flags;
- struct ieee80211_local *local = hw_to_local(hw);
struct iwl3945_rs_sta *rs_sta;
- struct sta_info *sta;
+ struct ieee80211_sta *sta;
+ struct iwl3945_sta_priv *psta;
IWL_DEBUG_RATE("enter\n");
- if (!local->rate_ctrl->ops->name ||
- strcmp(local->rate_ctrl->ops->name, RS_NAME)) {
- IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n");
- IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n");
- return;
- }
-
rcu_read_lock();
- sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
- if (!sta || !sta->rate_ctrl_priv) {
+ sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
+ psta = (void *) sta->drv_priv;
+ if (!sta || !psta) {
IWL_DEBUG_RATE("leave - no private rate data!\n");
rcu_read_unlock();
return;
}
- rs_sta = (void *)sta->rate_ctrl_priv;
+ rs_sta = psta->rs_sta;
spin_lock_irqsave(&rs_sta->lock, flags);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
index f085d330bdc..98b17ae6ef2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
@@ -176,15 +176,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
}
/**
- * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation
- *
- * NOTE: This is provided as a quick mechanism for a user to visualize
- * the performance of the rate control algorithm and is not meant to be
- * parsed software.
- */
-extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
-
-/**
* iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
*
* The specific throughput table used is based on the type of network
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 3f51f363534..7ca5627cc07 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -520,10 +520,10 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
+ case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr3, priv->bssid);
- case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
+ case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr2, priv->bssid);
default:
@@ -531,99 +531,6 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
}
}
-static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
- struct sk_buff *skb,
- struct iwl3945_rx_frame_hdr *rx_hdr,
- struct ieee80211_rx_status *stats)
-{
- /* First cache any information we need before we overwrite
- * the information provided in the skb from the hardware */
- s8 signal = stats->signal;
- s8 noise = 0;
- int rate = stats->rate_idx;
- u64 tsf = stats->mactime;
- __le16 phy_flags_hw = rx_hdr->phy_flags, antenna;
-
- struct iwl3945_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- __le64 rt_tsf; /* TSF */
- u8 rt_flags; /* radiotap packet flags */
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channelMHz; /* channel in MHz */
- __le16 rt_chbitmask; /* channel bitfield */
- s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
- s8 rt_dbmnoise;
- u8 rt_antenna; /* antenna number */
- } __attribute__ ((packed)) *iwl3945_rt;
-
- if (skb_headroom(skb) < sizeof(*iwl3945_rt)) {
- if (net_ratelimit())
- printk(KERN_ERR "not enough headroom [%d] for "
- "radiotap head [%zd]\n",
- skb_headroom(skb), sizeof(*iwl3945_rt));
- return;
- }
-
- /* put radiotap header in front of 802.11 header and data */
- iwl3945_rt = (void *)skb_push(skb, sizeof(*iwl3945_rt));
-
- /* initialise radiotap header */
- iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- iwl3945_rt->rt_hdr.it_pad = 0;
-
- /* total header + data */
- put_unaligned_le16(sizeof(*iwl3945_rt), &iwl3945_rt->rt_hdr.it_len);
-
- /* Indicate all the fields we add to the radiotap header */
- put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) |
- (1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
- (1 << IEEE80211_RADIOTAP_ANTENNA),
- &iwl3945_rt->rt_hdr.it_present);
-
- /* Zero the flags, we'll add to them as we go */
- iwl3945_rt->rt_flags = 0;
-
- put_unaligned_le64(tsf, &iwl3945_rt->rt_tsf);
-
- iwl3945_rt->rt_dbmsignal = signal;
- iwl3945_rt->rt_dbmnoise = noise;
-
- /* Convert the channel frequency and set the flags */
- put_unaligned_le16(stats->freq, &iwl3945_rt->rt_channelMHz);
- if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
- put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
- &iwl3945_rt->rt_chbitmask);
- else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
- put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
- &iwl3945_rt->rt_chbitmask);
- else /* 802.11g */
- put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
- &iwl3945_rt->rt_chbitmask);
-
- if (rate == -1)
- iwl3945_rt->rt_rate = 0;
- else {
- if (stats->band == IEEE80211_BAND_5GHZ)
- rate += IWL_FIRST_OFDM_RATE;
-
- iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
- }
-
- /* antenna number */
- antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
- iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
-
- /* set the preamble flag if we have it */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
- iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
- stats->flag |= RX_FLAG_RADIOTAP;
-}
-
static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb,
struct ieee80211_rx_status *stats)
@@ -657,9 +564,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
iwl3945_set_decrypted_flag(priv, rxb->skb,
le32_to_cpu(rx_end->status), stats);
- if (priv->add_radiotap)
- iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
-
#ifdef CONFIG_IWL3945_LEDS
if (ieee80211_is_data(hdr->frame_control))
priv->rxtxpackets += len;
@@ -684,7 +588,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
u8 network_packet;
- rx_status.antenna = 0;
rx_status.flag = 0;
rx_status.mactime = le64_to_cpu(rx_end->timestamp);
rx_status.freq =
@@ -696,6 +599,13 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+ rx_status.antenna = le16_to_cpu(rx_hdr->phy_flags &
+ RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+ /* set the preamble flag if appropriate */
+ if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+ rx_status.flag |= RX_FLAG_SHORTPRE;
+
if ((unlikely(rx_stats->phy_count > 20))) {
IWL_DEBUG_DROP
("dsp size out of range [0,20]: "
@@ -771,100 +681,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
priv->last_rx_noise = rx_status.noise;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
- return;
- }
-
- switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
- case IEEE80211_FTYPE_MGMT:
- switch (le16_to_cpu(header->frame_control) &
- IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_RESP:
- case IEEE80211_STYPE_BEACON:{
- /* If this is a beacon or probe response for
- * our network then cache the beacon
- * timestamp */
- if ((((priv->iw_mode == IEEE80211_IF_TYPE_STA)
- && !compare_ether_addr(header->addr2,
- priv->bssid)) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
- && !compare_ether_addr(header->addr3,
- priv->bssid)))) {
- struct ieee80211_mgmt *mgmt =
- (struct ieee80211_mgmt *)header;
- __le32 *pos;
- pos = (__le32 *)&mgmt->u.beacon.
- timestamp;
- priv->timestamp0 = le32_to_cpu(pos[0]);
- priv->timestamp1 = le32_to_cpu(pos[1]);
- priv->beacon_int = le16_to_cpu(
- mgmt->u.beacon.beacon_int);
- if (priv->call_post_assoc_from_beacon &&
- (priv->iw_mode ==
- IEEE80211_IF_TYPE_STA))
- queue_work(priv->workqueue,
- &priv->post_associate.work);
-
- priv->call_post_assoc_from_beacon = 0;
- }
-
- break;
- }
-
- case IEEE80211_STYPE_ACTION:
- /* TODO: Parse 802.11h frames for CSA... */
- break;
-
- /*
- * TODO: Use the new callback function from
- * mac80211 instead of sniffing these packets.
- */
- case IEEE80211_STYPE_ASSOC_RESP:
- case IEEE80211_STYPE_REASSOC_RESP:{
- struct ieee80211_mgmt *mgnt =
- (struct ieee80211_mgmt *)header;
-
- /* We have just associated, give some
- * time for the 4-way handshake if
- * any. Don't start scan too early. */
- priv->next_scan_jiffies = jiffies +
- IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-
- priv->assoc_id = (~((1 << 15) | (1 << 14)) &
- le16_to_cpu(mgnt->u.
- assoc_resp.aid));
- priv->assoc_capability =
- le16_to_cpu(mgnt->u.assoc_resp.capab_info);
- if (priv->beacon_int)
- queue_work(priv->workqueue,
- &priv->post_associate.work);
- else
- priv->call_post_assoc_from_beacon = 1;
- break;
- }
-
- case IEEE80211_STYPE_PROBE_REQ:{
- DECLARE_MAC_BUF(mac1);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
- IWL_DEBUG_DROP
- ("Dropping (non network): %s"
- ", %s, %s\n",
- print_mac(mac1, header->addr1),
- print_mac(mac2, header->addr2),
- print_mac(mac3, header->addr3));
- return;
- }
- }
-
- case IEEE80211_FTYPE_DATA:
- /* fall through */
- default:
- iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
- break;
- }
+ iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
}
int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr,
@@ -990,7 +807,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
priv->stations[sta_id].current_rate.rate_n_flags = rate;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
(sta_id != priv->hw_setting.bcast_sta_id) &&
(sta_id != IWL_MULTICAST_ID))
priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index fa81ba1af3d..bdd32475b99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
extern int iwl3945_param_hwcrypto;
extern int iwl3945_param_queues_num;
+struct iwl3945_sta_priv {
+ struct iwl3945_rs_sta *rs_sta;
+};
+
enum iwl3945_antenna {
IWL_ANTENNA_DIVERSITY,
IWL_ANTENNA_MAIN,
@@ -707,7 +711,6 @@ struct iwl3945_priv {
enum ieee80211_band band;
int alloc_rxb_skb;
- bool add_radiotap;
void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb);
@@ -852,7 +855,7 @@ struct iwl3945_priv {
/* eeprom */
struct iwl3945_eeprom eeprom;
- enum ieee80211_if_types iw_mode;
+ enum nl80211_iftype iw_mode;
struct sk_buff *ibss_beacon;
@@ -895,7 +898,6 @@ struct iwl3945_priv {
struct delayed_work thermal_periodic;
struct delayed_work gather_stats;
struct delayed_work scan_check;
- struct delayed_work post_associate;
#define IWL_DEFAULT_TX_POWER 0x0F
s8 user_txpower_limit;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index fce950f4163..f4793a60944 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -98,16 +98,17 @@
#define IWL_RSSI_OFFSET 44
-#include "iwl-commands.h"
/* PCI registers */
-#define PCI_LINK_CTRL 0x0F0 /* 1 byte */
-#define PCI_POWER_SOURCE 0x0C8
-#define PCI_REG_WUM8 0x0E8
+#define PCI_CFG_RETRY_TIMEOUT 0x041
+#define PCI_CFG_POWER_SOURCE 0x0C8
+#define PCI_REG_WUM8 0x0E8
+#define PCI_CFG_LINK_CTRL 0x0F0
/* PCI register values */
-#define PCI_LINK_VAL_L0S_EN 0x01
-#define PCI_LINK_VAL_L1_EN 0x02
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02
+#define PCI_CFG_CMD_REG_INT_DIS_MSK 0x04
#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
#define TFD_QUEUE_SIZE_MAX (256)
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index e2581229d8b..9838de5f436 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -399,7 +399,7 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
unsigned long flags;
u32 val;
u16 radio_cfg;
- u8 val_link;
+ u16 link;
spin_lock_irqsave(&priv->lock, flags);
@@ -410,10 +410,10 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
val & ~(1 << 11));
}
- pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link);
+ pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &link);
/* L1 is enabled by BIOS */
- if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN)
+ if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
/* diable L0S disabled L1A enabled */
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
else
@@ -474,8 +474,8 @@ static void iwl4965_apm_stop(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
udelay(10);
-
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ /* clear "init complete" move adapter D0A* --> D0U state */
+ iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1607,8 +1607,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
return ret;
}
-
-int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+#ifdef IEEE80211_CONF_CHANNEL_SWITCH
+static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
{
int rc;
u8 band = 0;
@@ -1648,6 +1648,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
return rc;
}
+#endif
static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 17d4f31c593..c479ee211c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -129,6 +129,13 @@ struct iwl5000_shared {
__le32 padding2;
} __attribute__ ((packed));
+/* calibrations defined for 5000 */
+/* defines the order in which results should be sent to the runtime uCode */
+enum iwl5000_calib {
+ IWL5000_CALIB_LO,
+ IWL5000_CALIB_TX_IQ,
+ IWL5000_CALIB_TX_IQ_PERD,
+};
#endif /* __iwl_5000_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index cbc01a00eaf..5155b8a760a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -145,7 +145,8 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
udelay(10);
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ /* clear "init complete" move adapter D0A* --> D0U state */
+ iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -208,14 +209,14 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
u16 radio_cfg;
- u8 val_link;
+ u16 link;
spin_lock_irqsave(&priv->lock, flags);
- pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link);
+ pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &link);
/* L1 is enabled by BIOS */
- if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN)
+ if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
/* diable L0S disabled L1A enabled */
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
else
@@ -444,48 +445,6 @@ static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
sizeof(cal_cmd), &cal_cmd);
}
-static int iwl5000_send_calib_results(struct iwl_priv *priv)
-{
- int ret = 0;
-
- struct iwl_host_cmd hcmd = {
- .id = REPLY_PHY_CALIBRATION_CMD,
- .meta.flags = CMD_SIZE_HUGE,
- };
-
- if (priv->calib_results.lo_res) {
- hcmd.len = priv->calib_results.lo_res_len;
- hcmd.data = priv->calib_results.lo_res;
- ret = iwl_send_cmd_sync(priv, &hcmd);
-
- if (ret)
- goto err;
- }
-
- if (priv->calib_results.tx_iq_res) {
- hcmd.len = priv->calib_results.tx_iq_res_len;
- hcmd.data = priv->calib_results.tx_iq_res;
- ret = iwl_send_cmd_sync(priv, &hcmd);
-
- if (ret)
- goto err;
- }
-
- if (priv->calib_results.tx_iq_perd_res) {
- hcmd.len = priv->calib_results.tx_iq_perd_res_len;
- hcmd.data = priv->calib_results.tx_iq_perd_res;
- ret = iwl_send_cmd_sync(priv, &hcmd);
-
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- IWL_ERROR("Error %d\n", ret);
- return ret;
-}
-
static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
{
struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
@@ -510,33 +469,30 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
-
- iwl_free_calib_results(priv);
+ int index;
/* reduce the size of the length field itself */
len -= 4;
+ /* Define the order in which the results will be sent to the runtime
+ * uCode. iwl_send_calib_results sends them in a row according to their
+ * index. We sort them here */
switch (hdr->op_code) {
case IWL5000_PHY_CALIBRATE_LO_CMD:
- priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC);
- priv->calib_results.lo_res_len = len;
- memcpy(priv->calib_results.lo_res, pkt->u.raw, len);
+ index = IWL5000_CALIB_LO;
break;
case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
- priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC);
- priv->calib_results.tx_iq_res_len = len;
- memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len);
+ index = IWL5000_CALIB_TX_IQ;
break;
case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
- priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC);
- priv->calib_results.tx_iq_perd_res_len = len;
- memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len);
+ index = IWL5000_CALIB_TX_IQ_PERD;
break;
default:
IWL_ERROR("Unknown calibration notification %d\n",
hdr->op_code);
return;
}
+ iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
}
static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
@@ -577,14 +533,11 @@ static int iwl5000_load_section(struct iwl_priv *priv,
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
- /* FIME: write the MSB of the phy_addr in CTRL1
- * iwl_write_direct32(priv,
- IWL_FH_TFDIB_CTRL1_REG(IWL_FH_SRVC_CHNL),
- ((phy_addr & MSB_MSK)
- << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_count);
- */
iwl_write_direct32(priv,
- FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), byte_cnt);
+ FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
+ (iwl_get_dma_hi_address(phy_addr)
+ << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
+
iwl_write_direct32(priv,
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
@@ -834,7 +787,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
iwl5000_send_Xtal_calib(priv);
if (priv->ucode_type == UCODE_RT)
- iwl5000_send_calib_results(priv);
+ iwl_send_calib_results(priv);
return 0;
}
@@ -880,12 +833,12 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_5100:
case CSR_HW_REV_TYPE_5300:
- /* 5X00 wants in Celsius */
+ case CSR_HW_REV_TYPE_5350:
+ /* 5X00 and 5350 wants in Celsius */
priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
break;
case CSR_HW_REV_TYPE_5150:
- case CSR_HW_REV_TYPE_5350:
- /* 5X50 wants in Kelvin */
+ /* 5150 wants in Kelvin */
priv->hw_params.ct_kill_threshold =
CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
break;
@@ -1616,6 +1569,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
.mod_params = &iwl50_mod_params,
};
+MODULE_FIRMWARE("iwlwifi-5000" IWL5000_UCODE_API ".ucode");
+
module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable50,
"manually disable the 50XX radio (default 0 [radio on])");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 754fef5b592..e2a58e47703 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -35,8 +35,6 @@
#include <linux/workqueue.h>
-#include "../net/mac80211/rate.h"
-
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
@@ -163,12 +161,15 @@ struct iwl_lq_sta {
u32 dbg_fixed_rate;
#endif
struct iwl_priv *drv;
+
+ /* used to be in sta_info */
+ int last_txrate_idx;
};
static void rs_rate_scale_perform(struct iwl_priv *priv,
- struct net_device *dev,
struct ieee80211_hdr *hdr,
- struct sta_info *sta);
+ struct ieee80211_sta *sta,
+ struct iwl_lq_sta *lq_sta);
static void rs_fill_link_cmd(const struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
@@ -354,17 +355,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
- struct sta_info *sta)
+ struct ieee80211_sta *sta)
{
- unsigned long state;
DECLARE_MAC_BUF(mac);
- spin_lock_bh(&sta->lock);
- state = sta->ampdu_mlme.tid_state_tx[tid];
- spin_unlock_bh(&sta->lock);
-
- if (state == HT_AGG_STATE_IDLE &&
- rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
+ if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
print_mac(mac, sta->addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
@@ -373,7 +368,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
struct iwl_lq_sta *lq_data,
- struct sta_info *sta)
+ struct ieee80211_sta *sta)
{
if ((tid < TID_MAX_LOAD_COUNT))
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
@@ -436,7 +431,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
/* Shift bitmap by one frame (throw away oldest history),
* OR in "1", and increment "success" if this
* frame was successful. */
- window->data <<= 1;;
+ window->data <<= 1;
if (successes > 0) {
window->success_counter++;
window->data |= 0x1;
@@ -773,7 +768,8 @@ out:
/*
* mac80211 sends us Tx status
*/
-static void rs_tx_status(void *priv_rate, struct net_device *dev,
+static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
int status;
@@ -781,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
int rs_index, index = 0;
struct iwl_lq_sta *lq_sta;
struct iwl_link_quality_cmd *table;
- struct sta_info *sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hw *hw = local_to_hw(local);
+ struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+ struct ieee80211_hw *hw = priv->hw;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_rate_scale_data *window = NULL;
struct iwl_rate_scale_data *search_win = NULL;
@@ -811,17 +805,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
if (retries > 15)
retries = 15;
- rcu_read_lock();
+ lq_sta = (struct iwl_lq_sta *)priv_sta;
- sta = sta_info_get(local, hdr->addr1);
-
- if (!sta || !sta->rate_ctrl_priv)
- goto out;
-
-
- lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added)
goto out;
@@ -965,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
}
/* See if there's a better rate or modulation mode to try. */
- rs_rate_scale_perform(priv, dev, hdr, sta);
+ rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
- rcu_read_unlock();
return;
}
@@ -1128,6 +1113,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
/* Higher rate not available, use the original */
} else {
+ new_rate = rate;
break;
}
}
@@ -1142,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
static int rs_switch_to_mimo2(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@@ -1153,7 +1139,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
!sta->ht_info.ht_supported)
return -1;
- if (priv->current_ht_config.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)
+ if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+ == WLAN_HT_CAP_SM_PS_STATIC)
return -1;
/* Need both Tx chains/antennas to support MIMO */
@@ -1209,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
static int rs_switch_to_siso(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@@ -1269,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
static int rs_move_legacy_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta,
+ struct ieee80211_sta *sta,
int index)
{
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1280,15 +1267,23 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+ u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret = 0;
for (; ;) {
switch (tbl->action) {
- case IWL_LEGACY_SWITCH_ANTENNA:
+ case IWL_LEGACY_SWITCH_ANTENNA1:
+ case IWL_LEGACY_SWITCH_ANTENNA2:
IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n");
lq_sta->action_counter++;
+ if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
+ tx_chains_num <= 1) ||
+ (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
+ tx_chains_num <= 2))
+ break;
+
/* Don't change antenna if success has been great */
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break;
@@ -1298,7 +1293,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
if (rs_toggle_antenna(valid_tx_ant,
&search_tbl->current_rate, search_tbl)) {
- lq_sta->search_better_tbl = 1;
+ rs_set_expected_tpt_table(lq_sta, search_tbl);
goto out;
}
break;
@@ -1311,43 +1306,54 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
search_tbl, index);
if (!ret) {
- lq_sta->search_better_tbl = 1;
lq_sta->action_counter = 0;
goto out;
}
break;
- case IWL_LEGACY_SWITCH_MIMO2:
+ case IWL_LEGACY_SWITCH_MIMO2_AB:
+ case IWL_LEGACY_SWITCH_MIMO2_AC:
+ case IWL_LEGACY_SWITCH_MIMO2_BC:
IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n");
/* Set up search table to try MIMO */
memcpy(search_tbl, tbl, sz);
search_tbl->is_SGI = 0;
- search_tbl->ant_type = ANT_AB;/*FIXME:RS*/
- /*FIXME:RS:need to check ant validity*/
+
+ if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB)
+ search_tbl->ant_type = ANT_AB;
+ else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
+ search_tbl->ant_type = ANT_AC;
+ else
+ search_tbl->ant_type = ANT_BC;
+
+ if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+ break;
+
ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
search_tbl, index);
if (!ret) {
- lq_sta->search_better_tbl = 1;
lq_sta->action_counter = 0;
goto out;
}
break;
}
tbl->action++;
- if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
- tbl->action = IWL_LEGACY_SWITCH_ANTENNA;
+ if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
if (tbl->action == start_action)
break;
}
+ search_tbl->lq_type = LQ_NONE;
return 0;
- out:
+out:
+ lq_sta->search_better_tbl = 1;
tbl->action++;
- if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
- tbl->action = IWL_LEGACY_SWITCH_ANTENNA;
+ if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
return 0;
}
@@ -1358,7 +1364,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
static int rs_move_siso_to_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta, int index)
+ struct ieee80211_sta *sta, int index)
{
u8 is_green = lq_sta->is_green;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1369,34 +1375,51 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+ u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret;
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
- case IWL_SISO_SWITCH_ANTENNA:
+ case IWL_SISO_SWITCH_ANTENNA1:
+ case IWL_SISO_SWITCH_ANTENNA2:
IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n");
+
+ if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
+ tx_chains_num <= 1) ||
+ (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
+ tx_chains_num <= 2))
+ break;
+
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break;
memcpy(search_tbl, tbl, sz);
if (rs_toggle_antenna(valid_tx_ant,
- &search_tbl->current_rate, search_tbl)) {
- lq_sta->search_better_tbl = 1;
+ &search_tbl->current_rate, search_tbl))
goto out;
- }
break;
- case IWL_SISO_SWITCH_MIMO2:
+ case IWL_SISO_SWITCH_MIMO2_AB:
+ case IWL_SISO_SWITCH_MIMO2_AC:
+ case IWL_SISO_SWITCH_MIMO2_BC:
IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n");
memcpy(search_tbl, tbl, sz);
search_tbl->is_SGI = 0;
- search_tbl->ant_type = ANT_AB; /*FIXME:RS*/
+
+ if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB)
+ search_tbl->ant_type = ANT_AB;
+ else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
+ search_tbl->ant_type = ANT_AC;
+ else
+ search_tbl->ant_type = ANT_BC;
+
+ if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+ break;
+
ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
search_tbl, index);
- if (!ret) {
- lq_sta->search_better_tbl = 1;
+ if (!ret)
goto out;
- }
break;
case IWL_SISO_SWITCH_GI:
if (!tbl->is_fat &&
@@ -1426,22 +1449,23 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
}
search_tbl->current_rate = rate_n_flags_from_tbl(
search_tbl, index, is_green);
- lq_sta->search_better_tbl = 1;
goto out;
}
tbl->action++;
if (tbl->action > IWL_SISO_SWITCH_GI)
- tbl->action = IWL_SISO_SWITCH_ANTENNA;
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
if (tbl->action == start_action)
break;
}
+ search_tbl->lq_type = LQ_NONE;
return 0;
out:
+ lq_sta->search_better_tbl = 1;
tbl->action++;
if (tbl->action > IWL_SISO_SWITCH_GI)
- tbl->action = IWL_SISO_SWITCH_ANTENNA;
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
return 0;
}
@@ -1451,43 +1475,64 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
static int rs_move_mimo_to_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
- struct sta_info *sta, int index)
+ struct ieee80211_sta *sta, int index)
{
s8 is_green = lq_sta->is_green;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
struct iwl_scale_tbl_info *search_tbl =
&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ struct iwl_rate_scale_data *window = &(tbl->win[index]);
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
- /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/
+ u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+ u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret;
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
- case IWL_MIMO_SWITCH_ANTENNA_A:
- case IWL_MIMO_SWITCH_ANTENNA_B:
+ case IWL_MIMO2_SWITCH_ANTENNA1:
+ case IWL_MIMO2_SWITCH_ANTENNA2:
+ IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n");
+
+ if (tx_chains_num <= 2)
+ break;
+
+ if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+ break;
+
+ memcpy(search_tbl, tbl, sz);
+ if (rs_toggle_antenna(valid_tx_ant,
+ &search_tbl->current_rate, search_tbl))
+ goto out;
+ break;
+ case IWL_MIMO2_SWITCH_SISO_A:
+ case IWL_MIMO2_SWITCH_SISO_B:
+ case IWL_MIMO2_SWITCH_SISO_C:
IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n");
/* Set up new search table for SISO */
memcpy(search_tbl, tbl, sz);
- /*FIXME:RS:need to check ant validity + C*/
- if (tbl->action == IWL_MIMO_SWITCH_ANTENNA_A)
+ if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
search_tbl->ant_type = ANT_A;
- else
+ else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
search_tbl->ant_type = ANT_B;
+ else
+ search_tbl->ant_type = ANT_C;
+
+ if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+ break;
ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
search_tbl, index);
- if (!ret) {
- lq_sta->search_better_tbl = 1;
+ if (!ret)
goto out;
- }
+
break;
- case IWL_MIMO_SWITCH_GI:
+ case IWL_MIMO2_SWITCH_GI:
if (!tbl->is_fat &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_20MHZ))
@@ -1516,23 +1561,23 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
}
search_tbl->current_rate = rate_n_flags_from_tbl(
search_tbl, index, is_green);
- lq_sta->search_better_tbl = 1;
goto out;
}
tbl->action++;
- if (tbl->action > IWL_MIMO_SWITCH_GI)
- tbl->action = IWL_MIMO_SWITCH_ANTENNA_A;
+ if (tbl->action > IWL_MIMO2_SWITCH_GI)
+ tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
if (tbl->action == start_action)
break;
}
-
+ search_tbl->lq_type = LQ_NONE;
return 0;
out:
+ lq_sta->search_better_tbl = 1;
tbl->action++;
- if (tbl->action > IWL_MIMO_SWITCH_GI)
- tbl->action = IWL_MIMO_SWITCH_ANTENNA_A;
+ if (tbl->action > IWL_MIMO2_SWITCH_GI)
+ tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
return 0;
}
@@ -1623,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
* Do rate scaling and search for new modulation mode.
*/
static void rs_rate_scale_perform(struct iwl_priv *priv,
- struct net_device *dev,
struct ieee80211_hdr *hdr,
- struct sta_info *sta)
+ struct ieee80211_sta *sta,
+ struct iwl_lq_sta *lq_sta)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hw *hw = local_to_hw(local);
+ struct ieee80211_hw *hw = priv->hw;
struct ieee80211_conf *conf = &hw->conf;
int low = IWL_RATE_INVALID;
int high = IWL_RATE_INVALID;
@@ -1643,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
__le16 fc;
u16 rate_mask;
u8 update_lq = 0;
- struct iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl, *tbl1;
u16 rate_scale_index_msk = 0;
u32 rate;
@@ -1664,10 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
return;
}
- if (!sta || !sta->rate_ctrl_priv)
+ if (!sta || !lq_sta)
return;
- lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
+ lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr);
@@ -1685,7 +1728,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
is_green = lq_sta->is_green;
/* current tx rate */
- index = sta->last_txrate_idx;
+ index = lq_sta->last_txrate_idx;
IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
tbl->lq_type);
@@ -1746,19 +1789,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
rs_stay_in_table(lq_sta);
goto out;
+ }
/* Else we have enough samples; calculate estimate of
* actual average throughput */
- } else {
- /*FIXME:RS remove this else if we don't get this error*/
- if (window->average_tpt != ((window->success_ratio *
- tbl->expected_tpt[index] + 64) / 128)) {
- IWL_ERROR("expected_tpt should have been calculated"
- " by now\n");
- window->average_tpt = ((window->success_ratio *
- tbl->expected_tpt[index] + 64) / 128);
- }
- }
+
+ BUG_ON(window->average_tpt != ((window->success_ratio *
+ tbl->expected_tpt[index] + 64) / 128));
/* If we are searching for better modulation mode, check success. */
if (lq_sta->search_better_tbl) {
@@ -1768,7 +1805,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
* continuing to use the setup that we've been trying. */
if (window->average_tpt > lq_sta->last_tpt) {
- IWL_DEBUG_RATE("LQ: SWITCHING TO CURRENT TABLE "
+ IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE "
"suc=%d cur-tpt=%d old-tpt=%d\n",
window->success_ratio,
window->average_tpt,
@@ -2004,15 +2041,7 @@ lq_update:
out:
tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green);
i = index;
- sta->last_txrate_idx = i;
-
- /* sta->txrate_idx is an index to A mode rates which start
- * at IWL_FIRST_OFDM_RATE
- */
- if (lq_sta->band == IEEE80211_BAND_5GHZ)
- sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
- else
- sta->txrate_idx = i;
+ lq_sta->last_txrate_idx = i;
return;
}
@@ -2020,9 +2049,9 @@ out:
static void rs_initialize_lq(struct iwl_priv *priv,
struct ieee80211_conf *conf,
- struct sta_info *sta)
+ struct ieee80211_sta *sta,
+ struct iwl_lq_sta *lq_sta)
{
- struct iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl;
int rate_idx;
int i;
@@ -2031,14 +2060,13 @@ static void rs_initialize_lq(struct iwl_priv *priv,
u8 active_tbl = 0;
u8 valid_tx_ant;
- if (!sta || !sta->rate_ctrl_priv)
+ if (!sta || !lq_sta)
goto out;
- lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
- i = sta->last_txrate_idx;
+ i = lq_sta->last_txrate_idx;
if ((lq_sta->lq.sta_id == 0xff) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+ (priv->iw_mode == NL80211_IFTYPE_ADHOC))
goto out;
valid_tx_ant = priv->hw_params.valid_tx_ant;
@@ -2075,40 +2103,33 @@ static void rs_initialize_lq(struct iwl_priv *priv,
return;
}
-static void rs_get_rate(void *priv_rate, struct net_device *dev,
- struct ieee80211_supported_band *sband,
- struct sk_buff *skb,
- struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
+ struct sk_buff *skb, struct rate_selection *sel)
{
int i;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_conf *conf = &local->hw.conf;
+ struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+ struct ieee80211_conf *conf = &priv->hw->conf;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct sta_info *sta;
__le16 fc;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
struct iwl_lq_sta *lq_sta;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
- rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = hdr->frame_control;
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
- sel->rate_idx = rate_lowest_index(local, sband, sta);
- goto out;
+ !sta || !priv_sta) {
+ sel->rate_idx = rate_lowest_index(sband, sta);
+ return;
}
- lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
- i = sta->last_txrate_idx;
+ lq_sta = (struct iwl_lq_sta *)priv_sta;
+ i = lq_sta->last_txrate_idx;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added) {
u8 sta_id = iwl_find_station(priv, hdr->addr1);
DECLARE_MAC_BUF(mac);
@@ -2123,23 +2144,22 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
lq_sta->lq.sta_id = sta_id;
lq_sta->lq.rs_table[0].rate_n_flags = 0;
lq_sta->ibss_sta_added = 1;
- rs_initialize_lq(priv, conf, sta);
+ rs_initialize_lq(priv, conf, sta, lq_sta);
}
}
if ((i < 0) || (i > IWL_RATE_COUNT)) {
- sel->rate_idx = rate_lowest_index(local, sband, sta);
- goto out;
+ sel->rate_idx = rate_lowest_index(sband, sta);
+ return;
}
if (sband->band == IEEE80211_BAND_5GHZ)
i -= IWL_FIRST_OFDM_RATE;
sel->rate_idx = i;
-out:
- rcu_read_unlock();
}
-static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
+static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
+ gfp_t gfp)
{
struct iwl_lq_sta *lq_sta;
struct iwl_priv *priv;
@@ -2162,33 +2182,28 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
return lq_sta;
}
-static void rs_rate_init(void *priv_rate, void *priv_sta,
- struct ieee80211_local *local,
- struct sta_info *sta)
+static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta)
{
int i, j;
- struct ieee80211_conf *conf = &local->hw.conf;
- struct ieee80211_supported_band *sband;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+ struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl_lq_sta *lq_sta = priv_sta;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
- sta->txrate_idx = 3;
for (j = 0; j < LQ_SIZE; j++)
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
- IWL_DEBUG_RATE("LQ: *** rate scale global init ***\n");
+ IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n");
/* TODO: what is a good starting rate for STA? About middle? Maybe not
* the lowest or the highest rate.. Could consider using RSSI from
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
lq_sta->ibss_sta_added = 0;
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->addr);
DECLARE_MAC_BUF(mac);
@@ -2211,15 +2226,14 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
}
/* Find highest tx rate supported by hardware and destination station */
+ lq_sta->last_txrate_idx = 3;
for (i = 0; i < sband->n_bitrates; i++)
if (sta->supp_rates[sband->band] & BIT(i))
- sta->txrate_idx = i;
+ lq_sta->last_txrate_idx = i;
- sta->last_txrate_idx = sta->txrate_idx;
- /* WTF is with this bogus comment? A doesn't have cck rates */
- /* For MODE_IEEE80211A, cck rates are at end of rate table */
- if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
- sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ /* For MODE_IEEE80211A, skip over cck rates in global rate table */
+ if (sband->band == IEEE80211_BAND_5GHZ)
+ lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_dup = 0;
lq_sta->is_green = rs_use_green(priv, conf);
@@ -2259,7 +2273,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
lq_sta->drv = priv;
- rs_initialize_lq(priv, conf, sta);
+ rs_initialize_lq(priv, conf, sta, lq_sta);
}
static void rs_fill_link_cmd(const struct iwl_priv *priv,
@@ -2381,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
}
-static void *rs_alloc(struct ieee80211_local *local)
+static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
- return local->hw.priv;
+ return hw->priv;
}
/* rate scale requires free function to be implemented */
static void rs_free(void *priv_rate)
@@ -2404,12 +2418,12 @@ static void rs_clear(void *priv_rate)
#endif /* CONFIG_IWLWIFI_DEBUG */
}
-static void rs_free_sta(void *priv_rate, void *priv_sta)
+static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
+ void *priv_sta)
{
struct iwl_lq_sta *lq_sta = priv_sta;
- struct iwl_priv *priv;
+ struct iwl_priv *priv __maybe_unused = priv_r;
- priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE("enter\n");
kfree(lq_sta);
IWL_DEBUG_RATE("leave\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index 84d4d1e3375..d148d73635e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -206,21 +206,28 @@ enum {
#define IWL_RATE_DECREASE_TH 1920 /* 15% */
/* possible actions when in legacy mode */
-#define IWL_LEGACY_SWITCH_ANTENNA 0
-#define IWL_LEGACY_SWITCH_SISO 1
-#define IWL_LEGACY_SWITCH_MIMO2 2
+#define IWL_LEGACY_SWITCH_ANTENNA1 0
+#define IWL_LEGACY_SWITCH_ANTENNA2 1
+#define IWL_LEGACY_SWITCH_SISO 2
+#define IWL_LEGACY_SWITCH_MIMO2_AB 3
+#define IWL_LEGACY_SWITCH_MIMO2_AC 4
+#define IWL_LEGACY_SWITCH_MIMO2_BC 5
/* possible actions when in siso mode */
-#define IWL_SISO_SWITCH_ANTENNA 0
-#define IWL_SISO_SWITCH_MIMO2 1
-#define IWL_SISO_SWITCH_GI 2
+#define IWL_SISO_SWITCH_ANTENNA1 0
+#define IWL_SISO_SWITCH_ANTENNA2 1
+#define IWL_SISO_SWITCH_MIMO2_AB 2
+#define IWL_SISO_SWITCH_MIMO2_AC 3
+#define IWL_SISO_SWITCH_MIMO2_BC 4
+#define IWL_SISO_SWITCH_GI 5
/* possible actions when in mimo mode */
-#define IWL_MIMO_SWITCH_ANTENNA_A 0
-#define IWL_MIMO_SWITCH_ANTENNA_B 1
-#define IWL_MIMO_SWITCH_GI 2
-
-/*FIXME:RS:separate MIMO2/3 transitions*/
+#define IWL_MIMO2_SWITCH_ANTENNA1 0
+#define IWL_MIMO2_SWITCH_ANTENNA2 1
+#define IWL_MIMO2_SWITCH_SISO_A 2
+#define IWL_MIMO2_SWITCH_SISO_B 3
+#define IWL_MIMO2_SWITCH_SISO_C 4
+#define IWL_MIMO2_SWITCH_GI 5
/*FIXME:RS:add posible acctions for MIMO3*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 061ffba9c88..24a1aeb6448 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -181,14 +181,14 @@ static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
}
/**
- * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
* @priv: staging_rxon is compared to active_rxon
*
* If the RXON structure is changing enough to require a new tune,
* or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
* a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
*/
-static int iwl4965_full_rxon_required(struct iwl_priv *priv)
+static int iwl_full_rxon_required(struct iwl_priv *priv)
{
/* These items are only settable from the full RXON command */
@@ -207,7 +207,6 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
(priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
- (priv->staging_rxon.rx_chain != priv->active_rxon.rx_chain) ||
(priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
return 1;
@@ -263,7 +262,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
/* If we don't need to send a full RXON, we can use
* iwl4965_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
- if (!iwl4965_full_rxon_required(priv)) {
+ if (!iwl_full_rxon_required(priv)) {
ret = iwl_send_rxon_assoc(priv);
if (ret) {
IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
@@ -338,7 +337,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
if (new_assoc) {
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
ret = iwl_rxon_add_station(priv,
priv->active_rxon.bssid_addr, 1);
if (ret == IWL_INVALID_STATION) {
@@ -449,8 +448,8 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
const u8 *dest, int left)
{
if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
- (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
+ ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
+ (priv->iw_mode != NL80211_IFTYPE_AP)))
return 0;
if (priv->ibss_beacon->len > left)
@@ -486,7 +485,7 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
return IWL_RATE_6M_PLCP;
}
-unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate)
{
struct iwl_tx_beacon_cmd *tx_beacon_cmd;
@@ -565,8 +564,6 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
if (!iwl_conf->is_ht)
return;
- priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
-
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
@@ -587,8 +584,8 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
iwl_conf->supported_chan_width = 0;
}
- iwl_conf->tx_mimo_ps_mode =
- (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+ iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
+
memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
iwl_conf->control_channel = ht_bss_conf->primary_channel;
@@ -675,7 +672,7 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
beacon_int = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
if (beacon_int == 0) {
priv->rxon_timing.beacon_interval = cpu_to_le16(100);
priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
@@ -724,7 +721,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
@@ -743,23 +740,23 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
- case IEEE80211_IF_TYPE_MNTR:
+ case NL80211_IFTYPE_MONITOR:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
@@ -788,7 +785,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
* in some case A channels are all non IBSS
* in this case force B/G channel
*/
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!(is_channel_ibss(ch_info)))
ch_info = &priv->channel_info[0];
@@ -1185,7 +1182,7 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
}
@@ -1273,7 +1270,7 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
if (src == IWL_PWR_SRC_VAUX) {
u32 val;
- ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
+ ret = pci_read_config_dword(priv->pci_dev, PCI_CFG_POWER_SOURCE,
&val);
if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
@@ -2190,7 +2187,10 @@ static void __iwl4965_down(struct iwl_priv *priv)
udelay(5);
/* FIXME: apm_ops.suspend(priv) */
- priv->cfg->ops->lib->apm_ops.reset(priv);
+ if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+ priv->cfg->ops->lib->apm_ops.stop(priv);
+ else
+ priv->cfg->ops->lib->apm_ops.reset(priv);
priv->cfg->ops->lib->free_shared_mem(priv);
exit:
@@ -2388,7 +2388,7 @@ static void iwl4965_bg_set_monitor(struct work_struct *work)
mutex_lock(&priv->mutex);
- ret = iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR);
+ ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR);
if (ret) {
if (ret == -EAGAIN)
@@ -2469,7 +2469,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
DECLARE_MAC_BUF(mac);
unsigned long flags;
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@@ -2486,6 +2486,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
if (!priv->vif || !priv->is_open)
return;
+ iwl_power_cancel_timeout(priv);
iwl_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -2503,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- if (priv->current_ht_config.is_ht)
- iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
iwl_set_rxon_chain(priv);
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
@@ -2523,7 +2523,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
@@ -2531,10 +2531,10 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
iwl4965_commit_rxon(priv);
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
/* assume default assoc id */
priv->assoc_id = 1;
@@ -2550,44 +2550,23 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
break;
}
- /* Enable Rx differential gain and sensitivity calibrations */
- iwl_chain_noise_reset(priv);
- priv->start_calib = 1;
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->assoc_station_added = 1;
spin_lock_irqsave(&priv->lock, flags);
iwl_activate_qos(priv, 0);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_power_update_mode(priv, 0);
- /* we have just associated, don't start scan too early */
- priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
-}
-
-static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
-
-static void iwl_bg_scan_completed(struct work_struct *work)
-{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, scan_completed);
-
- IWL_DEBUG_SCAN("SCAN complete scan\n");
+ /* the chain noise calibration will enabled PM upon completion
+ * If chain noise has already been run, then we need to enable
+ * power management here */
+ if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+ iwl_power_enable_management(priv);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (test_bit(STATUS_CONF_PENDING, &priv->status))
- iwl4965_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
-
- ieee80211_scan_completed(priv->hw);
+ /* Enable Rx differential gain and sensitivity calibrations */
+ iwl_chain_noise_reset(priv);
+ priv->start_calib = 1;
- /* Since setting the TXPOWER may have been deferred while
- * performing the scan, fire one off */
- mutex_lock(&priv->mutex);
- iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
- mutex_unlock(&priv->mutex);
}
/*****************************************************************************
@@ -2602,6 +2581,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
int ret;
+ u16 pci_cmd;
IWL_DEBUG_MAC80211("enter\n");
@@ -2612,6 +2592,13 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
pci_restore_state(priv->pci_dev);
pci_enable_msi(priv->pci_dev);
+ /* enable interrupts if needed: hw bug w/a */
+ pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
+ if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+ pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
+ }
+
ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
DRV_NAME, priv);
if (ret) {
@@ -2720,12 +2707,6 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
IWL_DEBUG_MACDUMP("enter\n");
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- IWL_DEBUG_MAC80211("leave - monitor\n");
- dev_kfree_skb_any(skb);
- return 0;
- }
-
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
@@ -2790,8 +2771,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
- priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
goto out;
@@ -2809,7 +2788,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211("leave - scanning\n");
- set_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
return 0;
}
@@ -2822,7 +2800,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
goto out;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
!is_channel_ibss(ch_info)) {
IWL_ERROR("channel %d in band %d not IBSS channel\n",
conf->channel->hw_value, conf->channel->band);
@@ -2843,7 +2821,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
)
priv->staging_rxon.flags = 0;
- iwl_set_rxon_channel(priv, conf->channel->band, channel);
+ iwl_set_rxon_channel(priv, conf->channel);
iwl_set_flags_for_band(priv, conf->channel->band);
@@ -2872,6 +2850,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
goto out;
}
+ if (conf->flags & IEEE80211_CONF_PS)
+ ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3);
+ else
+ ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM);
+ if (ret)
+ IWL_DEBUG_MAC80211("Error setting power level\n");
+
IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n",
priv->tx_power_user_lmt, conf->power_level);
@@ -2888,7 +2873,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
IWL_DEBUG_MAC80211("leave\n");
out:
- clear_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
return ret;
}
@@ -2937,7 +2921,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
@@ -2976,7 +2960,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
return 0;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
@@ -2986,7 +2970,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
return rc;
}
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
@@ -3009,7 +2993,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
!(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
*/
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
@@ -3044,11 +3028,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
* to verify) - jpk */
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl4965_config_ap(priv);
else {
rc = iwl4965_commit_rxon(priv);
- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
+ if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
iwl_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
}
@@ -3084,7 +3068,7 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- IEEE80211_IF_TYPE_MNTR,
+ NL80211_IFTYPE_MONITOR,
changed_flags, *total_flags);
/* queue work 'cuz mac80211 is holding a lock which
* prevents us from issuing (synchronous) f/w cmds */
@@ -3165,6 +3149,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
priv->power_data.dtim_period = bss_conf->dtim_period;
priv->timestamp = bss_conf->timestamp;
priv->assoc_capability = bss_conf->assoc_capability;
+
+ /* we have just associated, don't start scan too early
+ * leave time for EAPOL exchange to complete
+ */
priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
mutex_lock(&priv->mutex);
@@ -3181,11 +3169,11 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
}
-static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
{
- int rc = 0;
unsigned long flags;
struct iwl_priv *priv = hw->priv;
+ int ret;
IWL_DEBUG_MAC80211("enter\n");
@@ -3193,41 +3181,47 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
- rc = -EIO;
+ ret = -EIO;
IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
goto out_unlock;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */
- rc = -EIO;
+ if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
+ ret = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
}
- /* we don't schedule scan within next_scan_jiffies period */
+ /* We don't schedule scan within next_scan_jiffies period.
+ * Avoid scanning during possible EAPOL exchange, return
+ * success immediately.
+ */
if (priv->next_scan_jiffies &&
- time_after(priv->next_scan_jiffies, jiffies)) {
- rc = -EAGAIN;
+ time_after(priv->next_scan_jiffies, jiffies)) {
+ IWL_DEBUG_SCAN("scan rejected: within next scan period\n");
+ queue_work(priv->workqueue, &priv->scan_completed);
+ ret = 0;
goto out_unlock;
}
+
/* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
- IWL_DELAY_NEXT_SCAN, jiffies)) {
- rc = -EAGAIN;
+ if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
+ time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
+ IWL_DEBUG_SCAN("scan rejected: within previous scan period\n");
+ queue_work(priv->workqueue, &priv->scan_completed);
+ ret = 0;
goto out_unlock;
}
- if (len) {
- IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
- iwl_escape_essid(ssid, len), (int)len);
+ if (ssid_len) {
priv->one_direct_scan = 1;
- priv->direct_ssid_len = (u8)
- min((u8) len, (u8) IW_ESSID_MAX_SIZE);
+ priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE);
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
- } else
+ } else {
priv->one_direct_scan = 0;
+ }
- rc = iwl_scan_initiate(priv);
+ ret = iwl_scan_initiate(priv);
IWL_DEBUG_MAC80211("leave\n");
@@ -3235,7 +3229,7 @@ out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex);
- return rc;
+ return ret;
}
static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -3324,7 +3318,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* in 1X mode.
* In legacy wep mode, we use another host command to the uCode */
if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
- priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ priv->iw_mode != NL80211_IFTYPE_AP) {
if (cmd == SET_KEY)
is_default_wep_key = !priv->key_mapping_key;
else
@@ -3395,7 +3389,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
priv->qos_data.qos_active = 1;
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl_activate_qos(priv, 1);
else if (priv->assoc_id && iwl_is_associated(priv))
iwl_activate_qos(priv, 0);
@@ -3408,13 +3402,13 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
- const u8 *addr, u16 tid, u16 *ssn)
+ struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
- print_mac(mac, addr), tid);
+ print_mac(mac, sta->addr), tid);
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
@@ -3422,16 +3416,16 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
- return iwl_rx_agg_start(priv, addr, tid, *ssn);
+ return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
- return iwl_rx_agg_stop(priv, addr, tid);
+ return iwl_rx_agg_stop(priv, sta->addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
- return iwl_tx_agg_start(priv, addr, tid, ssn);
+ return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT("stop Tx\n");
- return iwl_tx_agg_stop(priv, addr, tid);
+ return iwl_tx_agg_stop(priv, sta->addr, tid);
default:
IWL_DEBUG_HT("unknown\n");
return -EINVAL;
@@ -3513,7 +3507,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
priv->beacon_int = priv->hw->conf.beacon_int;
priv->timestamp = 0;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ if ((priv->iw_mode == NL80211_IFTYPE_STATION))
priv->beacon_int = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3527,7 +3521,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode != NL80211_IFTYPE_AP) {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
@@ -3536,7 +3530,17 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
iwl_power_update_mode(priv, 0);
/* Per mac80211.h: This is only used in IBSS mode... */
- if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+
+ /* switch to CAM during association period.
+ * the ucode will block any association/authentication
+ * frome during assiciation period if it can not hear
+ * the AP because of PM. the timer enable PM back is
+ * association do not complete
+ */
+ if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN |
+ IEEE80211_CHAN_RADAR))
+ iwl_power_disable_management(priv, 3000);
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
@@ -3565,7 +3569,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
return -EIO;
}
- if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
mutex_unlock(&priv->mutex);
return -EIO;
@@ -3580,7 +3584,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
priv->assoc_id = 0;
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
- priv->timestamp = le64_to_cpu(timestamp) + (priv->beacon_int * 1000);
+ priv->timestamp = le64_to_cpu(timestamp);
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3622,11 +3626,11 @@ static ssize_t store_debug_level(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = d->driver_data;
- char *p = (char *)buf;
- u32 val;
+ unsigned long val;
+ int ret;
- val = simple_strtoul(p, &p, 0);
- if (p == buf)
+ ret = strict_strtoul(buf, 0, &val);
+ if (ret)
printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf);
else
@@ -3698,11 +3702,11 @@ static ssize_t store_tx_power(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- char *p = (char *)buf;
- u32 val;
+ unsigned long val;
+ int ret;
- val = simple_strtoul(p, &p, 10);
- if (p == buf)
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
printk(KERN_INFO DRV_NAME
": %s is not in decimal form.\n", buf);
else
@@ -3726,7 +3730,12 @@ static ssize_t store_flags(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- u32 flags = simple_strtoul(buf, NULL, 0);
+ unsigned long val;
+ u32 flags;
+ int ret = strict_strtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+ flags = (u32)val;
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
@@ -3734,8 +3743,7 @@ static ssize_t store_flags(struct device *d,
if (iwl_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
- IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
- flags);
+ IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags);
priv->staging_rxon.flags = cpu_to_le32(flags);
iwl4965_commit_rxon(priv);
}
@@ -3761,7 +3769,12 @@ static ssize_t store_filter_flags(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- u32 filter_flags = simple_strtoul(buf, NULL, 0);
+ unsigned long val;
+ u32 filter_flags;
+ int ret = strict_strtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+ filter_flags = (u32)val;
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
@@ -3862,10 +3875,12 @@ static ssize_t store_retry_rate(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ long val;
+ int ret = strict_strtol(buf, 10, &val);
+ if (!ret)
+ return ret;
- priv->retry_rate = simple_strtoul(buf, NULL, 0);
- if (priv->retry_rate <= 0)
- priv->retry_rate = 1;
+ priv->retry_rate = (val > 0) ? val : 1;
return count;
}
@@ -3886,9 +3901,9 @@ static ssize_t store_power_level(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
int ret;
- int mode;
+ unsigned long mode;
+
- mode = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (!iwl_is_ready(priv)) {
@@ -3896,6 +3911,10 @@ static ssize_t store_power_level(struct device *d,
goto out;
}
+ ret = strict_strtoul(buf, 10, &mode);
+ if (ret)
+ goto out;
+
ret = iwl_power_set_user_mode(priv, mode);
if (ret) {
IWL_DEBUG_MAC80211("failed setting power mode.\n");
@@ -4072,9 +4091,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
- /* FIXME : remove when resolved PENDING */
- INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
iwl_setup_scan_deferred_work(priv);
+ iwl_setup_power_deferred_work(priv);
if (priv->cfg->ops->lib->setup_deferred_work)
priv->cfg->ops->lib->setup_deferred_work(priv);
@@ -4094,6 +4112,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
+ cancel_delayed_work_sync(&priv->set_power_save);
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->beacon_update);
del_timer_sync(&priv->statistics_periodic);
@@ -4142,7 +4161,7 @@ static struct ieee80211_ops iwl4965_hw_ops = {
.reset_tsf = iwl4965_mac_reset_tsf,
.bss_info_changed = iwl4965_bss_info_changed,
.ampdu_action = iwl4965_mac_ampdu_action,
- .hw_scan = iwl4965_mac_hw_scan
+ .hw_scan = iwl_mac_hw_scan
};
static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -4196,13 +4215,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_set_master(pdev);
- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
if (err) {
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
/* both attempts failed: */
if (err) {
printk(KERN_WARNING "%s: No suitable DMA available.\n",
@@ -4217,9 +4236,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_set_drvdata(pdev, priv);
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, 0x41, 0x00);
/***********************
* 3. Read REV register
@@ -4239,6 +4255,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
": Detected Intel Wireless WiFi Link %s REV=0x%X\n",
priv->cfg->name, priv->hw_rev);
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
/* amp init */
err = priv->cfg->ops->lib->apm_ops.init(priv);
if (err < 0) {
@@ -4364,15 +4384,18 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
iwl_dbgfs_unregister(priv);
sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ /* ieee80211_unregister_hw call wil cause iwl4965_mac_stop to
+ * to be called and iwl4965_down since we are removing the device
+ * we need to set STATUS_EXIT_PENDING bit.
+ */
+ set_bit(STATUS_EXIT_PENDING, &priv->status);
if (priv->mac80211_registered) {
ieee80211_unregister_hw(priv->hw);
priv->mac80211_registered = 0;
+ } else {
+ iwl4965_down(priv);
}
- set_bit(STATUS_EXIT_PENDING, &priv->status);
-
- iwl4965_down(priv);
-
/* make sure we flush any pending irq or
* tasklet for the driver
*/
@@ -4470,7 +4493,10 @@ static struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
{IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
{IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
- {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
+/* 5350 WiFi/WiMax */
+ {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
+ {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
+ {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
#endif /* CONFIG_IWL5000 */
{0}
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index ef49440bd7f..72fbf47229d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -66,6 +66,66 @@
#include "iwl-core.h"
#include "iwl-calib.h"
+/*****************************************************************************
+ * INIT calibrations framework
+ *****************************************************************************/
+
+ int iwl_send_calib_results(struct iwl_priv *priv)
+{
+ int ret = 0;
+ int i = 0;
+
+ struct iwl_host_cmd hcmd = {
+ .id = REPLY_PHY_CALIBRATION_CMD,
+ .meta.flags = CMD_SIZE_HUGE,
+ };
+
+ for (i = 0; i < IWL_CALIB_MAX; i++)
+ if (priv->calib_results[i].buf) {
+ hcmd.len = priv->calib_results[i].buf_len;
+ hcmd.data = priv->calib_results[i].buf;
+ ret = iwl_send_cmd_sync(priv, &hcmd);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ IWL_ERROR("Error %d iteration %d\n", ret, i);
+ return ret;
+}
+EXPORT_SYMBOL(iwl_send_calib_results);
+
+int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
+{
+ if (res->buf_len != len) {
+ kfree(res->buf);
+ res->buf = kzalloc(len, GFP_ATOMIC);
+ }
+ if (unlikely(res->buf == NULL))
+ return -ENOMEM;
+
+ res->buf_len = len;
+ memcpy(res->buf, buf, len);
+ return 0;
+}
+EXPORT_SYMBOL(iwl_calib_set);
+
+void iwl_calib_free_results(struct iwl_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < IWL_CALIB_MAX; i++) {
+ kfree(priv->calib_results[i].buf);
+ priv->calib_results[i].buf = NULL;
+ priv->calib_results[i].buf_len = 0;
+ }
+}
+
+/*****************************************************************************
+ * RUNTIME calibrations framework
+ *****************************************************************************/
+
/* "false alarms" are signals that our DSP tries to lock onto,
* but then determines that they are either noise, or transmissions
* from a distant wireless network (also "noise", really) that get
@@ -748,13 +808,11 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
}
}
+ /* Save for use within RXON, TX, SCAN commands, etc. */
+ priv->chain_noise_data.active_chains = active_chains;
IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n",
active_chains);
- /* Save for use within RXON, TX, SCAN commands, etc. */
- /*priv->valid_antenna = active_chains;*/
- /*FIXME: should be reflected in RX chains in RXON */
-
/* Analyze noise for rx balance */
average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS);
average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS);
@@ -779,6 +837,15 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
priv->cfg->ops->utils->gain_computation(priv, average_noise,
min_average_noise_antenna_i, min_average_noise);
+
+ /* Some power changes may have been made during the calibration.
+ * Update and commit the RXON
+ */
+ if (priv->cfg->ops->lib->update_chain_flags)
+ priv->cfg->ops->lib->update_chain_flags(priv);
+
+ data->state = IWL_CHAIN_NOISE_DONE;
+ iwl_power_enable_management(priv);
}
EXPORT_SYMBOL(iwl_chain_noise_calibration);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 28b5b09996e..8d04e966ad4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -163,6 +163,13 @@ enum {
/* iwl_cmd_header flags value */
#define IWL_CMD_FAILED_MSK 0x40
+#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s) ((s) & 0xff)
+#define INDEX_TO_SEQ(i) ((i) & 0xff)
+#define SEQ_HUGE_FRAME __constant_cpu_to_le16(0x4000)
+#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+
/**
* struct iwl_cmd_header
*
@@ -171,7 +178,7 @@ enum {
*/
struct iwl_cmd_header {
u8 cmd; /* Command ID: REPLY_RXON, etc. */
- u8 flags; /* IWL_CMD_* */
+ u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
/*
* The driver sets up the sequence number to values of its chosing.
* uCode does not use this value, but passes it back to the driver
@@ -187,11 +194,12 @@ struct iwl_cmd_header {
*
* The Linux driver uses the following format:
*
- * 0:7 index/position within Tx queue
- * 8:13 Tx queue selection
- * 14:14 driver sets this to indicate command is in the 'huge'
- * storage at the end of the command buffers, i.e. scan cmd
- * 15:15 uCode sets this in uCode-originated response/notification
+ * 0:7 tfd index - position within TX queue
+ * 8:12 TX queue id
+ * 13 reserved
+ * 14 huge - driver sets this to indicate command is in the
+ * 'huge' storage at the end of the command buffers
+ * 15 unsolicited RX or uCode-originated notification
*/
__le16 sequence;
@@ -2026,8 +2034,8 @@ struct iwl4965_spectrum_notification {
* bit 2 - '0' PM have to walk up every DTIM
* '1' PM could sleep over DTIM till listen Interval.
* PCI power managed
- * bit 3 - '0' (PCI_LINK_CTRL & 0x1)
- * '1' !(PCI_LINK_CTRL & 0x1)
+ * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
+ * '1' !(PCI_CFG_LINK_CTRL & 0x1)
* Force sleep Modes
* bit 31/30- '00' use both mac/xtal sleeps
* '01' force Mac sleep
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c72f72579be..4c312c55f90 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -306,14 +306,14 @@ void iwl_reset_qos(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
- } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
@@ -399,8 +399,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
- ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
- (IWL_MIMO_PS_NONE << 2));
+ ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS &
+ (WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.fat_channel & BIT(band)) {
@@ -592,12 +592,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}
-static u8 is_single_rx_stream(struct iwl_priv *priv)
+static bool is_single_rx_stream(struct iwl_priv *priv)
{
return !priv->current_ht_config.is_ht ||
((priv->current_ht_config.supp_mcs_set[1] == 0) &&
- (priv->current_ht_config.supp_mcs_set[2] == 0)) ||
- priv->ps_mode == IWL_MIMO_PS_STATIC;
+ (priv->current_ht_config.supp_mcs_set[2] == 0));
}
static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -647,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
u32 val;
- if (!ht_info->is_ht)
+ if (!ht_info->is_ht) {
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
+ RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+ RXON_FLG_FAT_PROT_MSK |
+ RXON_FLG_HT_PROT_MSK);
return;
+ }
/* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
if (iwl_is_fat_tx_allowed(priv, NULL))
@@ -698,39 +703,63 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
}
EXPORT_SYMBOL(iwl_set_rxon_ht);
-/*
- * Determine how many receiver/antenna chains to use.
+#define IWL_NUM_RX_CHAINS_MULTIPLE 3
+#define IWL_NUM_RX_CHAINS_SINGLE 2
+#define IWL_NUM_IDLE_CHAINS_DUAL 2
+#define IWL_NUM_IDLE_CHAINS_SINGLE 1
+
+/* Determine how many receiver/antenna chains to use.
* More provides better reception via diversity. Fewer saves power.
* MIMO (dual stream) requires at least 2, but works better with 3.
* This does not determine *which* chains to use, just how many.
*/
-static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
- u8 *idle_state, u8 *rx_state)
+static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
{
- u8 is_single = is_single_rx_stream(priv);
- u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1;
+ bool is_single = is_single_rx_stream(priv);
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
/* # of Rx chains to use when expecting MIMO. */
- if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC)))
- *rx_state = 2;
+ if (is_single || (!is_cam && (priv->current_ht_config.sm_ps ==
+ WLAN_HT_CAP_SM_PS_STATIC)))
+ return IWL_NUM_RX_CHAINS_SINGLE;
else
- *rx_state = 3;
+ return IWL_NUM_RX_CHAINS_MULTIPLE;
+}
+static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+ int idle_cnt;
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
/* # Rx chains when idling and maybe trying to save power */
- switch (priv->ps_mode) {
- case IWL_MIMO_PS_STATIC:
- case IWL_MIMO_PS_DYNAMIC:
- *idle_state = (is_cam) ? 2 : 1;
+ switch (priv->current_ht_config.sm_ps) {
+ case WLAN_HT_CAP_SM_PS_STATIC:
+ case WLAN_HT_CAP_SM_PS_DYNAMIC:
+ idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
+ IWL_NUM_IDLE_CHAINS_SINGLE;
break;
- case IWL_MIMO_PS_NONE:
- *idle_state = (is_cam) ? *rx_state : 1;
+ case WLAN_HT_CAP_SM_PS_DISABLED:
+ idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
break;
+ case WLAN_HT_CAP_SM_PS_INVALID:
default:
- *idle_state = 1;
+ IWL_ERROR("invalide mimo ps mode %d\n",
+ priv->current_ht_config.sm_ps);
+ WARN_ON(1);
+ idle_cnt = -1;
break;
}
+ return idle_cnt;
+}
- return 0;
+/* up to 4 chains */
+static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
+{
+ u8 res;
+ res = (chain_bitmap & BIT(0)) >> 0;
+ res += (chain_bitmap & BIT(1)) >> 1;
+ res += (chain_bitmap & BIT(2)) >> 2;
+ res += (chain_bitmap & BIT(4)) >> 4;
+ return res;
}
/**
@@ -741,39 +770,59 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
*/
void iwl_set_rxon_chain(struct iwl_priv *priv)
{
- u8 is_single = is_single_rx_stream(priv);
- u8 idle_state, rx_state;
-
- priv->staging_rxon.rx_chain = 0;
- rx_state = idle_state = 3;
+ bool is_single = is_single_rx_stream(priv);
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+ u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
+ u32 active_chains;
+ u16 rx_chain;
/* Tell uCode which antennas are actually connected.
* Before first association, we assume all antennas are connected.
* Just after first association, iwl_chain_noise_calibration()
* checks which antennas actually *are* connected. */
- priv->staging_rxon.rx_chain |=
- cpu_to_le16(priv->hw_params.valid_rx_ant <<
- RXON_RX_CHAIN_VALID_POS);
+ if (priv->chain_noise_data.active_chains)
+ active_chains = priv->chain_noise_data.active_chains;
+ else
+ active_chains = priv->hw_params.valid_rx_ant;
+
+ rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
/* How many receivers should we use? */
- iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state);
- priv->staging_rxon.rx_chain |=
- cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS);
- priv->staging_rxon.rx_chain |=
- cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS);
-
- if (!is_single && (rx_state >= 2) &&
- !test_bit(STATUS_POWER_PMI, &priv->status))
+ active_rx_cnt = iwl_get_active_rx_chain_count(priv);
+ idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+
+ /* correct rx chain count according hw settings
+ * and chain noise calibration
+ */
+ valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
+ if (valid_rx_cnt < active_rx_cnt)
+ active_rx_cnt = valid_rx_cnt;
+
+ if (valid_rx_cnt < idle_rx_cnt)
+ idle_rx_cnt = valid_rx_cnt;
+
+ rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+ rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
+
+ priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
+
+ if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
else
priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
- IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
+ IWL_DEBUG_ASSOC("rx_chain=0x%X active=%d idle=%d\n",
+ priv->staging_rxon.rx_chain,
+ active_rx_cnt, idle_rx_cnt);
+
+ WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+ active_rx_cnt < idle_rx_cnt);
}
EXPORT_SYMBOL(iwl_set_rxon_chain);
/**
- * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
+ * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
* @channel: Any channel valid for the requested phymode
@@ -782,10 +831,11 @@ EXPORT_SYMBOL(iwl_set_rxon_chain);
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the phymode
*/
-int iwl_set_rxon_channel(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel)
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
{
+ enum ieee80211_band band = ch->band;
+ u16 channel = ieee80211_frequency_to_channel(ch->center_freq);
+
if (!iwl_get_channel_info(priv, band, channel)) {
IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
channel, band);
@@ -819,6 +869,10 @@ int iwl_setup_mac(struct iwl_priv *priv)
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
/* queues to support 11n aggregation */
@@ -876,7 +930,6 @@ int iwl_init_drv(struct iwl_priv *priv)
spin_lock_init(&priv->power_data.lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
- spin_lock_init(&priv->lq_mngr.lock);
INIT_LIST_HEAD(&priv->free_frames);
@@ -890,10 +943,10 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
- priv->iw_mode = IEEE80211_IF_TYPE_STA;
+ priv->iw_mode = NL80211_IFTYPE_STATION;
priv->use_ant_b_for_management_frame = 1; /* start with ant B */
- priv->ps_mode = IWL_MIMO_PS_NONE;
+ priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
/* Choose which receivers/antennas to use */
iwl_set_rxon_chain(priv);
@@ -907,8 +960,6 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
- iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
-
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
@@ -935,22 +986,6 @@ err:
}
EXPORT_SYMBOL(iwl_init_drv);
-void iwl_free_calib_results(struct iwl_priv *priv)
-{
- kfree(priv->calib_results.lo_res);
- priv->calib_results.lo_res = NULL;
- priv->calib_results.lo_res_len = 0;
-
- kfree(priv->calib_results.tx_iq_res);
- priv->calib_results.tx_iq_res = NULL;
- priv->calib_results.tx_iq_res_len = 0;
-
- kfree(priv->calib_results.tx_iq_perd_res);
- priv->calib_results.tx_iq_perd_res = NULL;
- priv->calib_results.tx_iq_perd_res_len = 0;
-}
-EXPORT_SYMBOL(iwl_free_calib_results);
-
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
int ret = 0;
@@ -978,10 +1013,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
}
EXPORT_SYMBOL(iwl_set_tx_power);
-
void iwl_uninit_drv(struct iwl_priv *priv)
{
- iwl_free_calib_results(priv);
+ iwl_calib_free_results(priv);
iwlcore_free_geos(priv);
iwl_free_channel_map(priv);
kfree(priv->scan);
@@ -1135,7 +1169,6 @@ int iwl_verify_ucode(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_verify_ucode);
-
static const char *desc_lookup(int i)
{
switch (i) {
@@ -1216,9 +1249,9 @@ EXPORT_SYMBOL(iwl_dump_nic_error_log);
/**
* iwl_print_event_log - Dump error event log to syslog
*
- * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
+ * NOTE: Must be called with iwl_grab_nic_access() already obtained!
*/
-void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
u32 num_events, u32 mode)
{
u32 i;
@@ -1259,8 +1292,6 @@ void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
}
}
}
-EXPORT_SYMBOL(iwl_print_event_log);
-
void iwl_dump_nic_event_log(struct iwl_priv *priv)
{
@@ -1376,7 +1407,7 @@ void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
iwl_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode != NL80211_IFTYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 64f139e9744..288b6a800e0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -184,14 +184,10 @@ struct iwl_cfg {
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_ops *hw_ops);
void iwl_hw_detect(struct iwl_priv *priv);
-
void iwl_clear_stations_table(struct iwl_priv *priv);
-void iwl_free_calib_results(struct iwl_priv *priv);
void iwl_reset_qos(struct iwl_priv *priv);
void iwl_set_rxon_chain(struct iwl_priv *priv);
-int iwl_set_rxon_channel(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel);
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
struct ieee80211_ht_info *sta_ht_inf);
@@ -218,7 +214,6 @@ void iwl_rx_replenish(struct iwl_priv *priv);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn);
int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
-/* FIXME: remove when TX is moved to iwl core */
int iwl_rx_queue_restock(struct iwl_priv *priv);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_rx_allocate(struct iwl_priv *priv);
@@ -237,11 +232,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
******************************************************/
int iwl_txq_ctx_reset(struct iwl_priv *priv);
int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
-/* FIXME: remove when free Tx is fully merged into iwlcore */
-int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
- dma_addr_t addr, u16 len);
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
@@ -256,6 +247,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
* RF -Kill - here and not in iwl-rfkill.h to be available when
* RF-kill subsystem is not compiled.
****************************************************/
+void iwl_rf_kill(struct iwl_priv *priv);
void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
@@ -286,11 +278,17 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
-const char *iwl_escape_essid(const char *essid, u8 essid_len);
int iwl_scan_initiate(struct iwl_priv *priv);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
+/*******************************************************************************
+ * Calibrations - implemented in iwl-calib.c
+ ******************************************************************************/
+int iwl_send_calib_results(struct iwl_priv *priv);
+int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
+void iwl_calib_free_results(struct iwl_priv *priv);
+
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
@@ -312,8 +310,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
/*****************************************************
* Error Handling Debugging
******************************************************/
-void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode);
void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv);
@@ -337,8 +333,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv);
#define STATUS_SCAN_HW 15
#define STATUS_POWER_PMI 16
#define STATUS_FW_ERROR 17
-#define STATUS_CONF_PENDING 18
-#define STATUS_MODE_PENDING 19
+#define STATUS_MODE_PENDING 18
static inline int iwl_is_ready(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 52629fbd835..662edf4f8d2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -64,7 +64,7 @@
#define CSR_BASE (0x000)
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
-#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
+#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index d2daa174df2..e548d67f87f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -110,11 +110,12 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
*
*/
-#define IWL_DL_INFO (1 << 0)
-#define IWL_DL_MAC80211 (1 << 1)
-#define IWL_DL_HOST_COMMAND (1 << 2)
-#define IWL_DL_STATE (1 << 3)
+#define IWL_DL_INFO (1 << 0)
+#define IWL_DL_MAC80211 (1 << 1)
+#define IWL_DL_HCMD (1 << 2)
+#define IWL_DL_STATE (1 << 3)
#define IWL_DL_MACDUMP (1 << 4)
+#define IWL_DL_HCMD_DUMP (1 << 5)
#define IWL_DL_RADIO (1 << 7)
#define IWL_DL_POWER (1 << 8)
#define IWL_DL_TEMP (1 << 9)
@@ -162,7 +163,8 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
-#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
+#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a)
+#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a)
#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c19db438306..c018121085e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -225,12 +225,6 @@ struct iwl_frame {
struct list_head list;
};
-#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
-#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
-#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
-#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
-#define SEQ_HUGE_FRAME (0x4000)
-#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
@@ -412,7 +406,7 @@ struct iwl_ht_info {
/* self configuration data */
u8 is_ht;
u8 supported_chan_width;
- u16 tx_mimo_ps_mode;
+ u8 sm_ps;
u8 is_green_field;
u8 sgf; /* HT_SHORT_GI_* short guard interval */
u8 max_amsdu_size;
@@ -571,50 +565,31 @@ struct iwl_hw_params {
#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
-
/******************************************************************************
*
- * Functions implemented in iwl-base.c which are forward declared here
- * for use by iwl-*.c
+ * Functions implemented in core module which are forward declared here
+ * for use by iwl-[4-5].c
*
- *****************************************************************************/
-struct iwl_addsta_cmd;
-extern int iwl_send_add_sta(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags);
-u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
- u8 flags, struct ieee80211_ht_info *ht_info);
-extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left);
-extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
-int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
-extern int iwl4965_set_power(struct iwl_priv *priv, void *cmd);
-
-extern const u8 iwl_bcast_addr[ETH_ALEN];
-
-/******************************************************************************
- *
- * Functions implemented in iwl-[34]*.c which are forward declared here
- * for use by iwl-base.c
- *
- * NOTE: The implementation of these functions are hardware specific
- * which is why they are in the hardware specific files (vs. iwl-base.c)
+ * NOTE: The implementation of these functions are not hardware specific
+ * which is why they are in the core module files.
*
* Naming convention --
- * iwl4965_ <-- Its part of iwlwifi (should be changed to iwl4965_)
- * iwl4965_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwl_ <-- Is part of iwlwifi
* iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
* iwl4965_bg_ <-- Called from work queue context
* iwl4965_mac_ <-- mac80211 callback
*
****************************************************************************/
+struct iwl_addsta_cmd;
+extern int iwl_send_add_sta(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *sta, u8 flags);
+extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ int is_ap, u8 flags, struct ieee80211_ht_info *ht_info);
+extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
+extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
+extern const u8 iwl_bcast_addr[ETH_ALEN];
extern int iwl_rxq_stop(struct iwl_priv *priv);
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
-extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl_frame *frame, u8 rate);
-extern void iwl4965_disable_events(struct iwl_priv *priv);
-
-extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
extern int iwl_queue_space(const struct iwl_queue *q);
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
@@ -637,12 +612,6 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
struct iwl_priv;
-/*
- * Forward declare iwl-4965.c functions for iwl-base.c
- */
-extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
-int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
- u8 tid, int txq_id);
/* Structures, enum, and defines specific to the 4965 */
@@ -657,11 +626,6 @@ struct iwl_kw {
#define IWL_CHANNEL_WIDTH_20MHZ 0
#define IWL_CHANNEL_WIDTH_40MHZ 1
-#define IWL_MIMO_PS_STATIC 0
-#define IWL_MIMO_PS_NONE 3
-#define IWL_MIMO_PS_DYNAMIC 1
-#define IWL_MIMO_PS_INVALID 2
-
#define IWL_OPERATION_MODE_AUTO 0
#define IWL_OPERATION_MODE_HT_ONLY 1
#define IWL_OPERATION_MODE_MIXED 2
@@ -672,18 +636,6 @@ struct iwl_kw {
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
-struct iwl4965_lq_mngr {
- spinlock_t lock;
- s32 max_window_size;
- s32 *expected_tpt;
- u8 *next_higher_rate;
- u8 *next_lower_rate;
- unsigned long stamp;
- unsigned long stamp_last;
- u32 flush_time;
- u32 tx_packets;
-};
-
/* Sensitivity and chain noise calibration */
#define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
#define INITIALIZATION_VALUE 0xFFFF
@@ -728,8 +680,9 @@ enum iwl4965_false_alarm_state {
enum iwl4965_chain_noise_state {
IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */
- IWL_CHAIN_NOISE_ACCUMULATE = 1,
- IWL_CHAIN_NOISE_CALIBRATED = 2,
+ IWL_CHAIN_NOISE_ACCUMULATE,
+ IWL_CHAIN_NOISE_CALIBRATED,
+ IWL_CHAIN_NOISE_DONE,
};
enum iwl4965_calib_enabled_state {
@@ -746,13 +699,10 @@ struct statistics_general_data {
u32 beacon_energy_c;
};
-struct iwl_calib_results {
- void *tx_iq_res;
- void *tx_iq_perd_res;
- void *lo_res;
- u32 tx_iq_res_len;
- u32 tx_iq_perd_res_len;
- u32 lo_res_len;
+/* Opaque calibration results */
+struct iwl_calib_result {
+ void *buf;
+ size_t buf_len;
};
enum ucode_type {
@@ -790,17 +740,18 @@ struct iwl_sensitivity_data {
/* Chain noise (differential Rx gain) calib data */
struct iwl_chain_noise_data {
- u8 state;
- u16 beacon_count;
+ u32 active_chains;
u32 chain_noise_a;
u32 chain_noise_b;
u32 chain_noise_c;
u32 chain_signal_a;
u32 chain_signal_b;
u32 chain_signal_c;
+ u16 beacon_count;
u8 disconn_array[NUM_RX_CHAINS];
u8 delta_gain_code[NUM_RX_CHAINS];
u8 radio_write;
+ u8 state;
};
#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
@@ -814,6 +765,7 @@ enum {
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
+#define IWL_CALIB_MAX 3
struct iwl_priv {
@@ -829,7 +781,6 @@ struct iwl_priv {
enum ieee80211_band band;
int alloc_rxb_skb;
- bool add_radiotap;
void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
@@ -858,7 +809,7 @@ struct iwl_priv {
s32 last_temperature;
/* init calibration results */
- struct iwl_calib_results calib_results;
+ struct iwl_calib_result calib_results[IWL_CALIB_MAX];
/* Scan related variables */
unsigned long last_scan_jiffies;
@@ -940,9 +891,6 @@ struct iwl_priv {
u8 last_phy_res[100];
/* Rate scaling data */
- struct iwl4965_lq_mngr lq_mngr;
-
- /* Rate scaling data */
s8 data_retry_limit;
u8 retry_rate;
@@ -1006,7 +954,7 @@ struct iwl_priv {
u8 *eeprom;
struct iwl_eeprom_calib_info *calib_info;
- enum ieee80211_if_types iw_mode;
+ enum nl80211_iftype iw_mode;
struct sk_buff *ibss_beacon;
@@ -1026,7 +974,6 @@ struct iwl_priv {
* hardware */
u16 assoc_id;
u16 assoc_capability;
- u8 ps_mode;
struct iwl_qos_info qos_data;
@@ -1048,6 +995,7 @@ struct iwl_priv {
struct tasklet_struct irq_tasklet;
+ struct delayed_work set_power_save;
struct delayed_work init_alive_start;
struct delayed_work alive_start;
struct delayed_work scan_check;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 944642450d3..a72efdf6d1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -247,8 +247,8 @@
#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
-#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20)
-#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_BITSHIFT (4)
+#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20)
+#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4)
#define RX_RB_TIMEOUT (0x10)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
@@ -260,8 +260,9 @@
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000)
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
+#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
/**
@@ -287,6 +288,7 @@
#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
+#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
/**
* Transmit DMA Channel Control/Status Registers (TCSR)
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 2eb03eea190..8300f3d00a0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -120,8 +120,18 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
return 1;
}
- IWL_DEBUG_HC("back from %s (0x%08X)\n",
- get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+#ifdef CONFIG_IWLWIFI_DEBUG
+ switch (cmd->hdr.cmd) {
+ case REPLY_TX_LINK_QUALITY_CMD:
+ case SENSITIVITY_CMD:
+ IWL_DEBUG_HC_DUMP("back from %s (0x%08X)\n",
+ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+ break;
+ default:
+ IWL_DEBUG_HC("back from %s (0x%08X)\n",
+ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+ }
+#endif
/* Let iwl_tx_complete free the response skb */
return 1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 5bc3df432d2..9740fcc1805 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -61,7 +61,7 @@
*
*/
-#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
+#define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs))
#ifdef CONFIG_IWLWIFI_DEBUG
static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
u32 ofs, u32 val)
@@ -75,7 +75,7 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val)
#endif
-#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs))
+#define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs))
#ifdef CONFIG_IWLWIFI_DEBUG
static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
{
@@ -155,28 +155,10 @@ static inline void __iwl_clear_bit(const char *f, u32 l,
static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
{
int ret;
- u32 gp_ctl;
-
#ifdef CONFIG_IWLWIFI_DEBUG
if (atomic_read(&priv->restrict_refcnt))
return 0;
#endif
- if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status)) {
- IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
- "wakes up NIC\n");
-
- /* 10 msec allows time for NIC to complete its data save */
- gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
- if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
- IWL_DEBUG_RF_KILL("Wait for complete power-down, "
- "gpctl = 0x%08x\n", gp_ctl);
- mdelay(10);
- } else
- IWL_DEBUG_RF_KILL("power-down complete, "
- "gpctl = 0x%08x\n", gp_ctl);
- }
-
/* this bit wakes up the NIC */
_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index a099c9e30e5..60a03d2d2d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -152,9 +152,10 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
/* initialize to default */
static int iwl_power_init_handle(struct iwl_priv *priv)
{
- int ret = 0, i;
struct iwl_power_mgr *pow_data;
int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
+ struct iwl_powertable_cmd *cmd;
+ int i;
u16 pci_pm;
IWL_DEBUG_POWER("Initialize power \n");
@@ -167,25 +168,19 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
- ret = pci_read_config_word(priv->pci_dev,
- PCI_LINK_CTRL, &pci_pm);
- if (ret != 0)
- return 0;
- else {
- struct iwl_powertable_cmd *cmd;
+ pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &pci_pm);
- IWL_DEBUG_POWER("adjust power command flags\n");
+ IWL_DEBUG_POWER("adjust power command flags\n");
- for (i = 0; i < IWL_POWER_MAX; i++) {
- cmd = &pow_data->pwr_range_0[i].cmd;
+ for (i = 0; i < IWL_POWER_MAX; i++) {
+ cmd = &pow_data->pwr_range_0[i].cmd;
- if (pci_pm & 0x1)
- cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
- else
- cmd->flags |= IWL_POWER_PCI_PM_MSK;
- }
+ if (pci_pm & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
+ cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
+ else
+ cmd->flags |= IWL_POWER_PCI_PM_MSK;
}
- return ret;
+ return 0;
}
/* adjust power command according to dtim period and power level*/
@@ -255,17 +250,26 @@ static int iwl_update_power_command(struct iwl_priv *priv,
/*
- * calucaute the final power mode index
+ * compute the final power mode index
*/
-int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
+int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
struct iwl_power_mgr *setting = &(priv->power_data);
int ret = 0;
u16 uninitialized_var(final_mode);
- /* If on battery, set to 3,
- * if plugged into AC power, set to CAM ("continuously aware mode"),
- * else user level */
+ /* Don't update the RX chain when chain noise calibration is running */
+ if (priv->chain_noise_data.state != IWL_CHAIN_NOISE_DONE &&
+ priv->chain_noise_data.state != IWL_CHAIN_NOISE_ALIVE) {
+ IWL_DEBUG_POWER("Cannot update the power, chain noise "
+ "calibration running: %d\n",
+ priv->chain_noise_data.state);
+ return -EAGAIN;
+ }
+
+ /* If on battery, set to 3,
+ * if plugged into AC power, set to CAM ("continuously aware mode"),
+ * else user level */
switch (setting->system_power_setting) {
case IWL_POWER_SYS_AUTO:
@@ -286,11 +290,11 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
final_mode = setting->critical_power_setting;
/* driver only support CAM for non STA network */
- if (priv->iw_mode != IEEE80211_IF_TYPE_STA)
+ if (priv->iw_mode != NL80211_IFTYPE_STATION)
final_mode = IWL_POWER_MODE_CAM;
if (!iwl_is_rfkill(priv) && !setting->power_disabled &&
- ((setting->power_mode != final_mode) || refresh)) {
+ ((setting->power_mode != final_mode) || force)) {
struct iwl_powertable_cmd cmd;
if (final_mode != IWL_POWER_MODE_CAM)
@@ -324,7 +328,7 @@ EXPORT_SYMBOL(iwl_power_update_mode);
* this will be usefull for rate scale to disable PM during heavy
* Tx/Rx activities
*/
-int iwl_power_disable_management(struct iwl_priv *priv)
+int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
{
u16 prev_mode;
int ret = 0;
@@ -337,6 +341,11 @@ int iwl_power_disable_management(struct iwl_priv *priv)
ret = iwl_power_update_mode(priv, 0);
priv->power_data.power_disabled = 1;
priv->power_data.user_power_setting = prev_mode;
+ cancel_delayed_work(&priv->set_power_save);
+ if (ms)
+ queue_delayed_work(priv->workqueue, &priv->set_power_save,
+ msecs_to_jiffies(ms));
+
return ret;
}
@@ -359,35 +368,26 @@ EXPORT_SYMBOL(iwl_power_enable_management);
/* set user_power_setting */
int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
{
- int ret = 0;
-
if (mode > IWL_POWER_LIMIT)
return -EINVAL;
priv->power_data.user_power_setting = mode;
- ret = iwl_power_update_mode(priv, 0);
-
- return ret;
+ return iwl_power_update_mode(priv, 0);
}
EXPORT_SYMBOL(iwl_power_set_user_mode);
-
/* set system_power_setting. This should be set by over all
* PM application.
*/
int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
{
- int ret = 0;
-
if (mode > IWL_POWER_LIMIT)
return -EINVAL;
priv->power_data.system_power_setting = mode;
- ret = iwl_power_update_mode(priv, 0);
-
- return ret;
+ return iwl_power_update_mode(priv, 0);
}
EXPORT_SYMBOL(iwl_power_set_system_mode);
@@ -431,3 +431,35 @@ int iwl_power_temperature_change(struct iwl_priv *priv)
return ret;
}
EXPORT_SYMBOL(iwl_power_temperature_change);
+
+static void iwl_bg_set_power_save(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work,
+ struct iwl_priv, set_power_save.work);
+ IWL_DEBUG(IWL_DL_STATE, "update power\n");
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ mutex_lock(&priv->mutex);
+
+ /* on starting association we disable power managment
+ * until association, if association failed then this
+ * timer will expire and enable PM again.
+ */
+ if (!iwl_is_associated(priv))
+ iwl_power_enable_management(priv);
+
+ mutex_unlock(&priv->mutex);
+}
+void iwl_setup_power_deferred_work(struct iwl_priv *priv)
+{
+ INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save);
+}
+EXPORT_SYMBOL(iwl_setup_power_deferred_work);
+
+void iwl_power_cancel_timeout(struct iwl_priv *priv)
+{
+ cancel_delayed_work(&priv->set_power_save);
+}
+EXPORT_SYMBOL(iwl_power_cancel_timeout);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index abcbbf96a84..df484a90ae6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -72,14 +72,16 @@ struct iwl_power_mgr {
/* final power level that used to calculate final power command */
u8 power_mode;
u8 user_power_setting; /* set by user through mac80211 or sysfs */
- u8 system_power_setting; /* set by kernel syatem tools */
+ u8 system_power_setting; /* set by kernel system tools */
u8 critical_power_setting; /* set if driver over heated */
u8 is_battery_active; /* DC/AC power */
u8 power_disabled; /* flag to disable using power saving level */
};
-int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh);
-int iwl_power_disable_management(struct iwl_priv *priv);
+void iwl_setup_power_deferred_work(struct iwl_priv *priv);
+void iwl_power_cancel_timeout(struct iwl_priv *priv);
+int iwl_power_update_mode(struct iwl_priv *priv, bool force);
+int iwl_power_disable_management(struct iwl_priv *priv, u32 ms);
int iwl_power_enable_management(struct iwl_priv *priv);
int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index f3f6ea49fdd..7cde9d76ff5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -376,7 +376,9 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
{
int ret;
unsigned long flags;
- unsigned int rb_size;
+ u32 rb_size;
+ const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+ const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */
spin_lock_irqsave(&priv->lock, flags);
ret = iwl_grab_nic_access(priv);
@@ -398,26 +400,32 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
/* Tell device where to find RBD circular buffer in DRAM */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- rxq->dma_addr >> 8);
+ (u32)(rxq->dma_addr >> 8));
/* Tell device where in DRAM to update its Rx status */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
(priv->shared_phys + priv->rb_closed_offset) >> 4);
- /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
+ /* Enable Rx DMA
+ * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set becuase of HW bug in
+ * the credit mechanism in 5000 HW RX FIFO
+ * Direct rx interrupts to hosts
+ * Rx buffer size 4 or 8k
+ * RB timeout 0x10
+ * 256 RBDs
+ */
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+ FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- rb_size |
- /* 0x10 << 4 | */
- (RX_QUEUE_SIZE_LOG <<
- FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
-
- /*
- * iwl_write32(priv,CSR_INT_COAL_REG,0);
- */
+ rb_size|
+ (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+ (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
iwl_release_nic_access(priv);
+
+ iwl_write32(priv, CSR_INT_COALESCING, 0x40);
+
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
@@ -789,107 +797,6 @@ static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
}
#endif
-static void iwl_add_radiotap(struct iwl_priv *priv,
- struct sk_buff *skb,
- struct iwl_rx_phy_res *rx_start,
- struct ieee80211_rx_status *stats,
- u32 ampdu_status)
-{
- s8 signal = stats->signal;
- s8 noise = 0;
- int rate = stats->rate_idx;
- u64 tsf = stats->mactime;
- __le16 antenna;
- __le16 phy_flags_hw = rx_start->phy_flags;
- struct iwl4965_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- __le64 rt_tsf; /* TSF */
- u8 rt_flags; /* radiotap packet flags */
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channelMHz; /* channel in MHz */
- __le16 rt_chbitmask; /* channel bitfield */
- s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
- s8 rt_dbmnoise;
- u8 rt_antenna; /* antenna number */
- } __attribute__ ((packed)) *iwl4965_rt;
-
- /* TODO: We won't have enough headroom for HT frames. Fix it later. */
- if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
- if (net_ratelimit())
- printk(KERN_ERR "not enough headroom [%d] for "
- "radiotap head [%zd]\n",
- skb_headroom(skb), sizeof(*iwl4965_rt));
- return;
- }
-
- /* put radiotap header in front of 802.11 header and data */
- iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
-
- /* initialise radiotap header */
- iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- iwl4965_rt->rt_hdr.it_pad = 0;
-
- /* total header + data */
- put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len);
-
- /* Indicate all the fields we add to the radiotap header */
- put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) |
- (1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
- (1 << IEEE80211_RADIOTAP_ANTENNA),
- &(iwl4965_rt->rt_hdr.it_present));
-
- /* Zero the flags, we'll add to them as we go */
- iwl4965_rt->rt_flags = 0;
-
- put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf);
-
- iwl4965_rt->rt_dbmsignal = signal;
- iwl4965_rt->rt_dbmnoise = noise;
-
- /* Convert the channel frequency and set the flags */
- put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz);
- if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
- put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
- &iwl4965_rt->rt_chbitmask);
- else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
- put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
- &iwl4965_rt->rt_chbitmask);
- else /* 802.11g */
- put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
- &iwl4965_rt->rt_chbitmask);
-
- if (rate == -1)
- iwl4965_rt->rt_rate = 0;
- else
- iwl4965_rt->rt_rate = iwl_rates[rate].ieee;
-
- /*
- * "antenna number"
- *
- * It seems that the antenna field in the phy flags value
- * is actually a bitfield. This is undefined by radiotap,
- * it wants an actual antenna number but I always get "7"
- * for most legacy frames I receive indicating that the
- * same frame was received on all three RX chains.
- *
- * I think this field should be removed in favour of a
- * new 802.11n radiotap field "RX chains" that is defined
- * as a bitmask.
- */
- antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
- iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
-
- /* set the preamble flag if appropriate */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
- iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
- stats->flag |= RX_FLAG_RADIOTAP;
-}
-
static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
{
/* 0 - mgmt, 1 - cnt, 2 - data */
@@ -1074,9 +981,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
- if (priv->add_radiotap)
- iwl_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
-
iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
priv->alloc_rxb_skb--;
@@ -1130,10 +1034,10 @@ static int iwl_is_network_packet(struct iwl_priv *priv,
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
+ case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr3, priv->bssid);
- case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
+ case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr2, priv->bssid);
default:
@@ -1171,9 +1075,11 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
- rx_status.antenna = 0;
rx_status.flag = 0;
- rx_status.flag |= RX_FLAG_TSFT;
+
+ /* TSF isn't reliable. In order to allow smooth user experience,
+ * this W/A doesn't propagate it to the mac80211 */
+ /*rx_status.flag |= RX_FLAG_TSFT;*/
if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
@@ -1250,8 +1156,28 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.signal, rx_status.noise, rx_status.signal,
(unsigned long long)rx_status.mactime);
+ /*
+ * "antenna number"
+ *
+ * It seems that the antenna field in the phy flags value
+ * is actually a bitfield. This is undefined by radiotap,
+ * it wants an actual antenna number but I always get "7"
+ * for most legacy frames I receive indicating that the
+ * same frame was received on all three RX chains.
+ *
+ * I think this field should be removed in favour of a
+ * new 802.11n radiotap field "RX chains" that is defined
+ * as a bitmask.
+ */
+ rx_status.antenna = le16_to_cpu(rx_start->phy_flags &
+ RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+ /* set the preamble flag if appropriate */
+ if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+ rx_status.flag |= RX_FLAG_SHORTPRE;
+
/* Take shortcut when only in monitor mode */
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
iwl_pass_packet_to_mac80211(priv, include_phy,
rxb, &rx_status);
return;
@@ -1268,7 +1194,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
switch (fc & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_MGMT:
case IEEE80211_FTYPE_DATA:
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
header->addr2);
/* fall through */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 9bb6adb28b7..3b0bee331a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -88,7 +88,7 @@ static int iwl_is_empty_essid(const char *essid, int essid_len)
-const char *iwl_escape_essid(const char *essid, u8 essid_len)
+static const char *iwl_escape_essid(const char *essid, u8 essid_len)
{
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
const char *s = essid;
@@ -111,7 +111,6 @@ const char *iwl_escape_essid(const char *essid, u8 essid_len)
*d = '\0';
return escaped;
}
-EXPORT_SYMBOL(iwl_escape_essid);
/**
* iwl_scan_cancel - Cancel any currently executing HW scan
@@ -421,7 +420,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
else
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
- if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes)
+ if (n_probes)
scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
scan_ch->active_dwell = cpu_to_le16(active_dwell);
@@ -464,11 +463,6 @@ void iwl_init_scan_params(struct iwl_priv *priv)
int iwl_scan_initiate(struct iwl_priv *priv)
{
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
- IWL_ERROR("APs don't scan.\n");
- return 0;
- }
-
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
@@ -480,8 +474,7 @@ int iwl_scan_initiate(struct iwl_priv *priv)
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN("Scan request while abort pending. "
- "Queuing.\n");
+ IWL_DEBUG_SCAN("Scan request while abort pending\n");
return -EAGAIN;
}
@@ -710,7 +703,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
u16 cmd_len;
enum ieee80211_band band;
u8 n_probes = 2;
- u8 rx_chain = 0x7; /* bitmap: ABC chains */
+ u8 rx_chain = priv->hw_params.valid_rx_ant;
conf = ieee80211_get_hw_conf(priv->hw);
@@ -850,7 +843,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
/* Force use of chains B and C (0x6) for scan Rx for 4965
* Avoid A (0x1) because of its off-channel reception on A-band.
- * MIMO is not used here, but value is required */
+ */
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
rx_chain = 0x6;
} else {
@@ -858,6 +851,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
+ /* MIMO is not used here, but value is required */
scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
(rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) |
@@ -869,7 +863,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
scan->tx_cmd.len = cpu_to_le16(cmd_len);
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
@@ -922,10 +916,29 @@ static void iwl_bg_abort_scan(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
+static void iwl_bg_scan_completed(struct work_struct *work)
+{
+ struct iwl_priv *priv =
+ container_of(work, struct iwl_priv, scan_completed);
+
+ IWL_DEBUG_SCAN("SCAN complete scan\n");
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ ieee80211_scan_completed(priv->hw);
+
+ /* Since setting the TXPOWER may have been deferred while
+ * performing the scan, fire one off */
+ mutex_lock(&priv->mutex);
+ iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+ mutex_unlock(&priv->mutex);
+}
+
+
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
{
- /* FIXME: move here when resolved PENDING
- * INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); */
+ INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 6283a3a707f..61797f3f8d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -47,8 +47,8 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
unsigned long flags;
DECLARE_MAC_BUF(mac);
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) ||
- (priv->iw_mode == IEEE80211_IF_TYPE_AP))
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
+ (priv->iw_mode == NL80211_IFTYPE_AP))
start = IWL_STA_ID;
if (is_broadcast_ether_addr(addr))
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(iwl_find_station);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
{
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
return IWL_AP_ID;
} else {
u8 *da = ieee80211_get_DA(hdr);
@@ -191,20 +191,20 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
if (!sta_ht_inf || !sta_ht_inf->ht_supported)
goto done;
- mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2;
+ mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
sta_flags = priv->stations[index].sta.station_flags;
sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
switch (mimo_ps_mode) {
- case WLAN_HT_CAP_MIMO_PS_STATIC:
+ case WLAN_HT_CAP_SM_PS_STATIC:
sta_flags |= STA_FLG_MIMO_DIS_MSK;
break;
- case WLAN_HT_CAP_MIMO_PS_DYNAMIC:
+ case WLAN_HT_CAP_SM_PS_DYNAMIC:
sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
break;
- case WLAN_HT_CAP_MIMO_PS_DISABLED:
+ case WLAN_HT_CAP_SM_PS_DISABLED:
break;
default:
IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode);
@@ -286,7 +286,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
/* BCAST station and IBSS stations do not work in HT mode */
if (sta_id != priv->hw_params.bcast_sta_id &&
- priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
+ priv->iw_mode != NL80211_IFTYPE_ADHOC)
iwl_set_ht_add_station(priv, sta_id, ht_info);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
@@ -817,7 +817,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
};
if ((lq->sta_id == 0xFF) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+ (priv->iw_mode == NL80211_IFTYPE_ADHOC))
return -EINVAL;
if (lq->sta_id == 0xFF)
@@ -904,7 +904,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
if ((is_ap) &&
(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ (priv->iw_mode == NL80211_IFTYPE_STATION))
sta_id = iwl_add_station_flags(priv, addr, is_ap,
0, cur_ht_config);
else
@@ -938,11 +938,11 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If we are a client station in a BSS network, use the special
* AP station entry (that's the only station we communicate with) */
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@@ -950,7 +950,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@@ -968,6 +968,11 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_params.bcast_sta_id;
+ /* If we are in monitor mode, use BCAST. This is required for
+ * packet injection. */
+ case NL80211_IFTYPE_MONITOR:
+ return priv->hw_params.bcast_sta_id;
+
default:
IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
return priv->hw_params.bcast_sta_id;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index d82823b5c8a..907a53ebc6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -63,7 +63,7 @@ static const u16 default_tid_to_tx_fifo[] = {
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
-int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+static int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
@@ -115,10 +115,8 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
}
return 0;
}
-EXPORT_SYMBOL(iwl_hw_txq_free_tfd);
-
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
dma_addr_t addr, u16 len)
{
int index, is_odd;
@@ -126,7 +124,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
/* Each TFD can point to a maximum 20 Tx buffers */
- if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) {
+ if (num_tbs >= MAX_NUM_OF_TBS) {
IWL_ERROR("Error can not send more than %d chunks\n",
MAX_NUM_OF_TBS);
return -EINVAL;
@@ -151,7 +149,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
return 0;
}
-EXPORT_SYMBOL(iwl_hw_txq_attach_buf_to_tfd);
/**
* iwl_txq_update_write_ptr - Send new write index to hardware
@@ -402,12 +399,11 @@ static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
/**
* iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
*/
-static int iwl_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
+static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id)
{
int i, len;
- int rc = 0;
+ int ret;
/*
* Alloc buffer array for commands (Tx or other types of commands).
@@ -426,19 +422,16 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
continue;
}
- txq->cmd[i] = kmalloc(len, GFP_KERNEL | GFP_DMA);
+ txq->cmd[i] = kmalloc(len, GFP_KERNEL);
if (!txq->cmd[i])
- return -ENOMEM;
+ goto err;
}
/* Alloc driver data array and TFD circular buffer */
- rc = iwl_tx_queue_alloc(priv, txq, txq_id);
- if (rc) {
- for (i = 0; i < slots_num; i++)
- kfree(txq->cmd[i]);
+ ret = iwl_tx_queue_alloc(priv, txq, txq_id);
+ if (ret)
+ goto err;
- return -ENOMEM;
- }
txq->need_update = 0;
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
@@ -452,6 +445,17 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
iwl_hw_tx_queue_init(priv, txq);
return 0;
+err:
+ for (i = 0; i < slots_num; i++) {
+ kfree(txq->cmd[i]);
+ txq->cmd[i] = NULL;
+ }
+
+ if (txq_id == IWL_CMD_QUEUE_NUM) {
+ kfree(txq->cmd[slots_num]);
+ txq->cmd[slots_num] = NULL;
+ }
+ return -ENOMEM;
}
/**
* iwl_hw_txq_ctx_free - Free TXQ Context
@@ -471,7 +475,6 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
-
/**
* iwl_txq_ctx_reset - Reset TX queue context
* Destroys all DMA structures and initialise them again
@@ -538,6 +541,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
error_kw:
return ret;
}
+
/**
* iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
*/
@@ -789,11 +793,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
goto drop_unlock;
}
- if (!priv->vif) {
- IWL_DEBUG_DROP("Dropping - !priv->vif\n");
- goto drop_unlock;
- }
-
if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) ==
IWL_INVALID_RATE) {
IWL_ERROR("ERROR: No TX rate available.\n");
@@ -815,16 +814,18 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* drop all data frame if we are not associated */
if (ieee80211_is_data(fc) &&
- (!iwl_is_associated(priv) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
- !priv->assoc_station_added)) {
+ (priv->iw_mode != NL80211_IFTYPE_MONITOR ||
+ !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
+ (!iwl_is_associated(priv) ||
+ ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
+ !priv->assoc_station_added)) {
IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
goto drop_unlock;
}
spin_unlock_irqrestore(&priv->lock, flags);
- hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc));
+ hdr_len = ieee80211_hdrlen(fc);
/* Find (or create) index into station table for destination station */
sta_id = iwl_get_sta_id(priv, hdr);
@@ -842,7 +843,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
txq_id = swq_id;
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & 0xf;
+ tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
seq_number = priv->stations[sta_id].tid[tid].seq_number;
seq_number &= IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = hdr->seq_ctrl &
@@ -1057,7 +1058,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
INDEX_TO_SEQ(q->write_ptr));
if (out_cmd->meta.flags & CMD_SIZE_HUGE)
- out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
+ out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
len = (idx == TFD_CMD_SLOTS) ?
IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
phys_addr = pci_map_single(priv->pci_dev, out_cmd, len,
@@ -1065,12 +1066,26 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
phys_addr += offsetof(struct iwl_cmd, hdr);
iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
- IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
- "%d bytes at %d[%d]:%d\n",
- get_cmd_string(out_cmd->hdr.cmd),
- out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
-
+#ifdef CONFIG_IWLWIFI_DEBUG
+ switch (out_cmd->hdr.cmd) {
+ case REPLY_TX_LINK_QUALITY_CMD:
+ case SENSITIVITY_CMD:
+ IWL_DEBUG_HC_DUMP("Sending command %s (#%x), seq: 0x%04X, "
+ "%d bytes at %d[%d]:%d\n",
+ get_cmd_string(out_cmd->hdr.cmd),
+ out_cmd->hdr.cmd,
+ le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+ q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
+ break;
+ default:
+ IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
+ "%d bytes at %d[%d]:%d\n",
+ get_cmd_string(out_cmd->hdr.cmd),
+ out_cmd->hdr.cmd,
+ le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+ q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
+ }
+#endif
txq->need_update = 1;
/* Set up entry in queue's byte count circular buffer */
@@ -1178,17 +1193,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
- int huge = sequence & SEQ_HUGE_FRAME;
int cmd_index;
+ bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
struct iwl_cmd *cmd;
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
- if (txq_id != IWL_CMD_QUEUE_NUM)
- IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
- txq_id, pkt->hdr.cmd);
- BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
+ if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
+ "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd))
+ return;
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index b775d5bab66..d15a2c99795 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1160,7 +1160,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
if (iwl3945_is_associated(priv) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ (priv->iw_mode == NL80211_IFTYPE_STATION))
if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
== IWL_INVALID_STATION) {
IWL_ERROR("Error adding AP address for transmit.\n");
@@ -1447,8 +1447,8 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
{
if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
- (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
+ ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
+ (priv->iw_mode != NL80211_IFTYPE_AP)))
return 0;
if (priv->ibss_beacon->len > left)
@@ -1746,14 +1746,14 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
- } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
@@ -2120,7 +2120,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
beacon_int = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
if (beacon_int == 0) {
priv->rxon_timing.beacon_interval = cpu_to_le16(100);
priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
@@ -2156,7 +2156,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
@@ -2218,7 +2218,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
@@ -2237,23 +2237,23 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
- case IEEE80211_IF_TYPE_MNTR:
+ case NL80211_IFTYPE_MONITOR:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
@@ -2282,7 +2282,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
* in some case A channels are all non IBSS
* in this case force B/G channel
*/
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!(is_channel_ibss(ch_info)))
ch_info = &priv->channel_info[0];
@@ -2302,7 +2302,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
{
- if (mode == IEEE80211_IF_TYPE_IBSS) {
+ if (mode == NL80211_IFTYPE_ADHOC) {
const struct iwl3945_channel_info *ch_info;
ch_info = iwl3945_get_channel_info(priv,
@@ -2469,11 +2469,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If we are a client station in a BSS network, use the special
* AP station entry (that's the only station we communicate with) */
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@@ -2481,7 +2481,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
- case IEEE80211_IF_TYPE_IBSS: {
+ case NL80211_IFTYPE_ADHOC: {
DECLARE_MAC_BUF(mac);
/* Create new station table entry */
@@ -2502,7 +2502,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
}
/* If we are in monitor mode, use BCAST. This is required for
* packet injection. */
- case IEEE80211_IF_TYPE_MNTR:
+ case NL80211_IFTYPE_MONITOR:
return priv->hw_setting.bcast_sta_id;
default:
@@ -2565,16 +2565,16 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
/* drop all data frame if we are not associated */
if (ieee80211_is_data(fc) &&
- (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */
+ (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
(!iwl3945_is_associated(priv) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) {
+ ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
goto drop_unlock;
}
spin_unlock_irqrestore(&priv->lock, flags);
- hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc));
+ hdr_len = ieee80211_hdrlen(fc);
/* Find (or create) index into station table for destination station */
sta_id = iwl3945_get_sta_id(priv, hdr);
@@ -2590,7 +2590,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & 0xf;
+ tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
seq_number = priv->stations[sta_id].tid[tid].seq_number &
IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = cpu_to_le16(seq_number) |
@@ -2709,7 +2709,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
sizeof(out_cmd->cmd.tx));
iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
- ieee80211_get_hdrlen(le16_to_cpu(fc)));
+ ieee80211_hdrlen(fc));
/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -2806,7 +2806,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
if (disable_radio) {
iwl3945_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode != NL80211_IFTYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
@@ -3161,7 +3161,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
}
@@ -4782,8 +4782,11 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
* sending probe req. This should be set long enough to hear probe responses
* from more than one AP. */
-#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */
-#define IWL_ACTIVE_DWELL_TIME_52 (10)
+#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */
+#define IWL_ACTIVE_DWELL_TIME_52 (20)
+
+#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
/* For faster active scanning, scan will move to the next channel if fewer than
* PLCP_QUIET_THRESH packets are heard on this channel within
@@ -4792,7 +4795,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
* no other traffic).
* Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */
-#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */
+#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */
/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
* Must be set longer than active dwell time.
@@ -4802,19 +4805,23 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
+#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+
static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
- enum ieee80211_band band)
+ enum ieee80211_band band,
+ u8 n_probes)
{
if (band == IEEE80211_BAND_5GHZ)
- return IWL_ACTIVE_DWELL_TIME_52;
+ return IWL_ACTIVE_DWELL_TIME_52 +
+ IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
else
- return IWL_ACTIVE_DWELL_TIME_24;
+ return IWL_ACTIVE_DWELL_TIME_24 +
+ IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
}
static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
enum ieee80211_band band)
{
- u16 active = iwl3945_get_active_dwell_time(priv, band);
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
@@ -4829,15 +4836,12 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
}
- if (passive <= active)
- passive = active + 1;
-
return passive;
}
static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
enum ieee80211_band band,
- u8 is_active, u8 direct_mask,
+ u8 is_active, u8 n_probes,
struct iwl3945_scan_channel *scan_ch)
{
const struct ieee80211_channel *channels = NULL;
@@ -4853,9 +4857,12 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
channels = sband->channels;
- active_dwell = iwl3945_get_active_dwell_time(priv, band);
+ active_dwell = iwl3945_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
+ if (passive_dwell <= active_dwell)
+ passive_dwell = active_dwell + 1;
+
for (i = 0, added = 0; i < sband->n_channels; i++) {
if (channels[i].flags & IEEE80211_CHAN_DISABLED)
continue;
@@ -4875,8 +4882,8 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
else
scan_ch->type = 1; /* active */
- if (scan_ch->type & 1)
- scan_ch->type |= (direct_mask << 1);
+ if ((scan_ch->type & 1) && n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
@@ -6052,7 +6059,7 @@ static void iwl3945_bg_set_monitor(struct work_struct *work)
if (!iwl3945_is_ready(priv))
IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
else
- if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
+ if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0)
IWL_ERROR("iwl3945_set_mode() failed\n");
mutex_unlock(&priv->mutex);
@@ -6093,7 +6100,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
int rc = 0;
struct iwl3945_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
- u8 direct_mask;
+ u8 n_probes = 2;
enum ieee80211_band band;
conf = ieee80211_get_hw_conf(priv->hw);
@@ -6201,7 +6208,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
- direct_mask = 1;
+ n_probes++;
} else if (!iwl3945_is_associated(priv) && priv->essid_len) {
IWL_DEBUG_SCAN
("Kicking off one direct scan for '%s' when not associated\n",
@@ -6209,11 +6216,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->essid_len;
memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- direct_mask = 1;
- } else {
+ n_probes++;
+ } else
IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
- direct_mask = 0;
- }
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
@@ -6243,21 +6248,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
- if (direct_mask)
- scan->channel_count =
- iwl3945_get_channels_for_scan(
- priv, band, 1, /* active */
- direct_mask,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
- else
- scan->channel_count =
- iwl3945_get_channels_for_scan(
- priv, band, 0, /* passive */
- direct_mask,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+ scan->channel_count =
+ iwl3945_get_channels_for_scan(priv, band, 1, /* active */
+ n_probes,
+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
scan->channel_count * sizeof(struct iwl3945_scan_channel);
@@ -6320,16 +6317,13 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
#define IWL_DELAY_NEXT_SCAN (HZ*2)
-static void iwl3945_bg_post_associate(struct work_struct *data)
+static void iwl3945_post_associate(struct iwl3945_priv *priv)
{
- struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv,
- post_associate.work);
-
int rc = 0;
struct ieee80211_conf *conf = NULL;
DECLARE_MAC_BUF(mac);
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@@ -6342,12 +6336,9 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- mutex_lock(&priv->mutex);
-
- if (!priv->vif || !priv->is_open) {
- mutex_unlock(&priv->mutex);
+ if (!priv->vif || !priv->is_open)
return;
- }
+
iwl3945_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -6381,7 +6372,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
@@ -6389,11 +6380,11 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
iwl3945_commit_rxon(priv);
switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
break;
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_ADHOC:
/* clear out the station table */
iwl3945_clear_stations_table(priv);
@@ -6419,7 +6410,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
- mutex_unlock(&priv->mutex);
}
static void iwl3945_bg_abort_scan(struct work_struct *work)
@@ -6567,7 +6557,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
*/
mutex_lock(&priv->mutex);
iwl3945_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
mutex_unlock(&priv->mutex);
}
@@ -6650,8 +6639,6 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
- priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
if (!iwl3945_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n");
ret = -EIO;
@@ -6767,7 +6754,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
@@ -6804,7 +6791,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
}
/* handle this temporarily here */
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
@@ -6816,7 +6803,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
/* XXX: this MUST use conf->mac_addr */
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
@@ -6839,7 +6826,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
!(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
*/
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
@@ -6874,11 +6861,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
* to verify) - jpk */
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl3945_config_ap(priv);
else {
rc = iwl3945_commit_rxon(priv);
- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
+ if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
iwl3945_add_station(priv,
priv->active_rxon.bssid_addr, 1, 0);
}
@@ -6914,7 +6901,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- IEEE80211_IF_TYPE_MNTR,
+ NL80211_IFTYPE_MONITOR,
changed_flags, *total_flags);
/* queue work 'cuz mac80211 is holding a lock which
* prevents us from issuing (synchronous) f/w cmds */
@@ -6935,7 +6922,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
if (iwl3945_is_ready_rf(priv)) {
iwl3945_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl3945_commit_rxon(priv);
}
@@ -6950,6 +6936,63 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211("leave\n");
}
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
+static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
+{
+ struct iwl3945_priv *priv = hw->priv;
+
+ IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
+
+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+ IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
+ bss_conf->use_short_preamble);
+ if (bss_conf->use_short_preamble)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ else
+ priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ }
+
+ if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+ IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
+ if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+ priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+ else
+ priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+ }
+
+ if (changes & BSS_CHANGED_ASSOC) {
+ IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
+ /* This should never happen as this function should
+ * never be called from interrupt context. */
+ if (WARN_ON_ONCE(in_interrupt()))
+ return;
+ if (bss_conf->assoc) {
+ priv->assoc_id = bss_conf->aid;
+ priv->beacon_int = bss_conf->beacon_int;
+ priv->timestamp0 = bss_conf->timestamp & 0xFFFFFFFF;
+ priv->timestamp1 = (bss_conf->timestamp >> 32) &
+ 0xFFFFFFFF;
+ priv->assoc_capability = bss_conf->assoc_capability;
+ priv->next_scan_jiffies = jiffies +
+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+ mutex_lock(&priv->mutex);
+ iwl3945_post_associate(priv);
+ mutex_unlock(&priv->mutex);
+ } else {
+ priv->assoc_id = 0;
+ IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
+ }
+ } else if (changes && iwl3945_is_associated(priv) && priv->assoc_id) {
+ IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
+ iwl3945_send_rxon_assoc(priv);
+ }
+
+}
+
static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
{
int rc = 0;
@@ -6967,7 +7010,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */
+ if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
rc = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
@@ -7109,7 +7152,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl3945_activate_qos(priv, 1);
else if (priv->assoc_id && iwl3945_is_associated(priv))
iwl3945_activate_qos(priv, 0);
@@ -7182,8 +7225,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
iwl3945_reset_qos(priv);
- cancel_delayed_work(&priv->post_associate);
-
spin_lock_irqsave(&priv->lock, flags);
priv->assoc_id = 0;
priv->assoc_capability = 0;
@@ -7198,7 +7239,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
priv->beacon_int = priv->hw->conf.beacon_int;
priv->timestamp1 = 0;
priv->timestamp0 = 0;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ if ((priv->iw_mode == NL80211_IFTYPE_STATION))
priv->beacon_int = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -7212,14 +7253,14 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ if (priv->iw_mode != NL80211_IFTYPE_AP) {
iwl3945_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl3945_commit_rxon(priv);
}
/* Per mac80211.h: This is only used in IBSS mode... */
- if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
@@ -7248,7 +7289,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
return -EIO;
}
- if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
mutex_unlock(&priv->mutex);
return -EIO;
@@ -7268,7 +7309,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
iwl3945_reset_qos(priv);
- queue_work(priv->workqueue, &priv->post_associate.work);
+ iwl3945_post_associate(priv);
mutex_unlock(&priv->mutex);
@@ -7329,15 +7370,6 @@ static ssize_t show_temperature(struct device *d,
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-static ssize_t show_rs_window(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct iwl3945_priv *priv = d->driver_data;
- return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID);
-}
-static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
-
static ssize_t show_tx_power(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -7767,7 +7799,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor);
- INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
@@ -7785,7 +7816,6 @@ static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv)
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
- cancel_delayed_work(&priv->post_associate);
cancel_work_sync(&priv->beacon_update);
}
@@ -7801,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
#endif
&dev_attr_power_level.attr,
&dev_attr_retry_rate.attr,
- &dev_attr_rs_window.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
&dev_attr_temperature.attr,
@@ -7830,6 +7859,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.conf_tx = iwl3945_mac_conf_tx,
.get_tsf = iwl3945_mac_get_tsf,
.reset_tsf = iwl3945_mac_reset_tsf,
+ .bss_info_changed = iwl3945_bss_info_changed,
.hw_scan = iwl3945_mac_hw_scan
};
@@ -7868,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
SET_IEEE80211_DEV(hw, &pdev->dev);
hw->rate_control_algorithm = "iwl-3945-rs";
+ hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
@@ -7890,6 +7921,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
/* 4 EDCA QOS priorities */
hw->queues = 4;
@@ -7951,7 +7987,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
IWL_DEBUG_INFO("Radio disabled.\n");
}
- priv->iw_mode = IEEE80211_IF_TYPE_STA;
+ priv->iw_mode = NL80211_IFTYPE_STATION;
printk(KERN_INFO DRV_NAME
": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
@@ -8331,6 +8367,8 @@ static void __exit iwl3945_exit(void)
iwl3945_rate_control_unregister();
}
+MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode");
+
module_param_named(antenna, iwl3945_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
module_param_named(disable, iwl3945_param_disable, int, 0444);
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index a267d6e65f0..92be60415d0 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -8,6 +8,7 @@
#include "scan.h"
#include "cmd.h"
+static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp);
static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -20,12 +21,88 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
#define CAPINFO_MASK (~(0xda00))
+/**
+ * @brief This function finds common rates between rates and card rates.
+ *
+ * It will fill common rates in rates as output if found.
+ *
+ * NOTE: Setting the MSB of the basic rates need to be taken
+ * care, either before or after calling this function
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param rates the buffer which keeps input and output
+ * @param rates_size the size of rate1 buffer; new size of buffer on return
+ *
+ * @return 0 on success, or -1 on error
+ */
+static int get_common_rates(struct lbs_private *priv,
+ u8 *rates,
+ u16 *rates_size)
+{
+ u8 *card_rates = lbs_bg_rates;
+ size_t num_card_rates = sizeof(lbs_bg_rates);
+ int ret = 0, i, j;
+ u8 tmp[30];
+ size_t tmp_size = 0;
+
+ /* For each rate in card_rates that exists in rate1, copy to tmp */
+ for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
+ for (j = 0; rates[j] && (j < *rates_size); j++) {
+ if (rates[j] == card_rates[i])
+ tmp[tmp_size++] = card_rates[i];
+ }
+ }
+
+ lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
+ lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
+ lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
+ lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
+
+ if (!priv->enablehwauto) {
+ for (i = 0; i < tmp_size; i++) {
+ if (tmp[i] == priv->cur_rate)
+ goto done;
+ }
+ lbs_pr_alert("Previously set fixed data rate %#x isn't "
+ "compatible with the network.\n", priv->cur_rate);
+ ret = -1;
+ goto done;
+ }
+ ret = 0;
+
+done:
+ memset(rates, 0, *rates_size);
+ *rates_size = min_t(int, tmp_size, *rates_size);
+ memcpy(rates, tmp, *rates_size);
+ return ret;
+}
+
+
+/**
+ * @brief Sets the MSB on basic rates as the firmware requires
+ *
+ * Scan through an array and set the MSB for basic data rates.
+ *
+ * @param rates buffer of data rates
+ * @param len size of buffer
+ */
+static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (rates[i] == 0x02 || rates[i] == 0x04 ||
+ rates[i] == 0x0b || rates[i] == 0x16)
+ rates[i] |= 0x80;
+ }
+}
+
/**
* @brief Associate to a specific BSS discovered in a scan
*
* @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to the BSS descriptor to associate with.
+ * @param assoc_req The association request describing the BSS to associate with
*
* @return 0-success, otherwise fail
*/
@@ -33,29 +110,29 @@ static int lbs_associate(struct lbs_private *priv,
struct assoc_request *assoc_req)
{
int ret;
+ u8 preamble = RADIO_PREAMBLE_LONG;
lbs_deb_enter(LBS_DEB_ASSOC);
ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
0, CMD_OPTION_WAITFORRSP,
0, assoc_req->bss.bssid);
-
if (ret)
- goto done;
+ goto out;
- /* set preamble to firmware */
+ /* Use short preamble only when both the BSS and firmware support it */
if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
(assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- else
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+ preamble = RADIO_PREAMBLE_SHORT;
- lbs_set_radio_control(priv);
+ ret = lbs_set_radio(priv, preamble, 1);
+ if (ret)
+ goto out;
ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-done:
+out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -64,17 +141,22 @@ done:
* @brief Join an adhoc network found in a previous scan
*
* @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
- * to attempt to join
+ * @param assoc_req The association request describing the BSS to join
*
- * @return 0--success, -1--fail
+ * @return 0 on success, error on failure
*/
-static int lbs_join_adhoc_network(struct lbs_private *priv,
+static int lbs_adhoc_join(struct lbs_private *priv,
struct assoc_request *assoc_req)
{
+ struct cmd_ds_802_11_ad_hoc_join cmd;
struct bss_descriptor *bss = &assoc_req->bss;
+ u8 preamble = RADIO_PREAMBLE_LONG;
+ DECLARE_MAC_BUF(mac);
+ u16 ratesize = 0;
int ret = 0;
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
lbs_deb_join("current SSID '%s', ssid length %u\n",
escape_essid(priv->curbssparams.ssid,
priv->curbssparams.ssid_len),
@@ -106,29 +188,106 @@ static int lbs_join_adhoc_network(struct lbs_private *priv,
goto out;
}
- /* Use shortpreamble only when both creator and card supports
- short preamble */
- if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
- !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
- lbs_deb_join("AdhocJoin: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- } else {
+ /* Use short preamble only when both the BSS and firmware support it */
+ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
+ (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
lbs_deb_join("AdhocJoin: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+ preamble = RADIO_PREAMBLE_SHORT;
}
- lbs_set_radio_control(priv);
+ ret = lbs_set_radio(priv, preamble, 1);
+ if (ret)
+ goto out;
lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
priv->adhoccreate = 0;
+ priv->curbssparams.channel = bss->channel;
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
- 0, CMD_OPTION_WAITFORRSP,
- OID_802_11_SSID, assoc_req);
+ /* Build the join command */
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+ cmd.bss.type = CMD_BSS_TYPE_IBSS;
+ cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
+
+ memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
+ memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
+
+ memcpy(&cmd.bss.phyparamset, &bss->phyparamset,
+ sizeof(union ieeetypes_phyparamset));
+
+ memcpy(&cmd.bss.ssparamset, &bss->ssparamset,
+ sizeof(union IEEEtypes_ssparamset));
+
+ cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
+ lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+ bss->capability, CAPINFO_MASK);
+
+ /* information on BSSID descriptor passed to FW */
+ lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
+ print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
+
+ /* Only v8 and below support setting these */
+ if (priv->fwrelease < 0x09000000) {
+ /* failtimeout */
+ cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
+ /* probedelay */
+ cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+ }
+
+ /* Copy Data rates from the rates recorded in scan response */
+ memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
+ ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
+ memcpy(cmd.bss.rates, bss->rates, ratesize);
+ if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
+ lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
+ ret = -1;
+ goto out;
+ }
+
+ /* Copy the ad-hoc creation rates into Current BSS state structure */
+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+ memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
+
+ /* Set MSB on basic rates as the firmware requires, but _after_
+ * copying to current bss rates.
+ */
+ lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
+
+ cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
+
+ if (assoc_req->secinfo.wep_enabled) {
+ u16 tmp = le16_to_cpu(cmd.bss.capability);
+ tmp |= WLAN_CAPABILITY_PRIVACY;
+ cmd.bss.capability = cpu_to_le16(tmp);
+ }
+
+ if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
+ __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
+
+ /* wake up first */
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
+ CMD_ACT_SET, 0, 0,
+ &local_ps_mode);
+ if (ret) {
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
+ if (ret == 0)
+ ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
out:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -136,39 +295,131 @@ out:
* @brief Start an Adhoc Network
*
* @param priv A pointer to struct lbs_private structure
- * @param adhocssid The ssid of the Adhoc Network
- * @return 0--success, -1--fail
+ * @param assoc_req The association request describing the BSS to start
+ *
+ * @return 0 on success, error on failure
*/
-static int lbs_start_adhoc_network(struct lbs_private *priv,
+static int lbs_adhoc_start(struct lbs_private *priv,
struct assoc_request *assoc_req)
{
+ struct cmd_ds_802_11_ad_hoc_start cmd;
+ u8 preamble = RADIO_PREAMBLE_LONG;
+ size_t ratesize = 0;
+ u16 tmpcap = 0;
int ret = 0;
- priv->adhoccreate = 1;
+ lbs_deb_enter(LBS_DEB_ASSOC);
if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
- lbs_deb_join("AdhocStart: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- } else {
- lbs_deb_join("AdhocStart: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+ lbs_deb_join("ADHOC_START: Will use short preamble\n");
+ preamble = RADIO_PREAMBLE_SHORT;
}
- lbs_set_radio_control(priv);
+ ret = lbs_set_radio(priv, preamble, 1);
+ if (ret)
+ goto out;
- lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
- lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
+ /* Build the start command */
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+ memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
+
+ lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ assoc_req->ssid_len);
+
+ cmd.bsstype = CMD_BSS_TYPE_IBSS;
+
+ if (priv->beacon_period == 0)
+ priv->beacon_period = MRVDRV_BEACON_INTERVAL;
+ cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
+
+ WARN_ON(!assoc_req->channel);
+
+ /* set Physical parameter set */
+ cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
+ cmd.phyparamset.dsparamset.len = 1;
+ cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
+
+ /* set IBSS parameter set */
+ cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
+ cmd.ssparamset.ibssparamset.len = 2;
+ cmd.ssparamset.ibssparamset.atimwindow = 0;
+
+ /* set capability info */
+ tmpcap = WLAN_CAPABILITY_IBSS;
+ if (assoc_req->secinfo.wep_enabled) {
+ lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n");
+ tmpcap |= WLAN_CAPABILITY_PRIVACY;
+ } else
+ lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n");
+
+ cmd.capability = cpu_to_le16(tmpcap);
+
+ /* Only v8 and below support setting probe delay */
+ if (priv->fwrelease < 0x09000000)
+ cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+
+ ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
+ memcpy(cmd.rates, lbs_bg_rates, ratesize);
+
+ /* Copy the ad-hoc creating rates into Current BSS state structure */
+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+ memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
+ /* Set MSB on basic rates as the firmware requires, but _after_
+ * copying to current bss rates.
+ */
+ lbs_set_basic_rate_flags(cmd.rates, ratesize);
+
+ lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
+ cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
+
+ if (lbs_create_dnld_countryinfo_11d(priv)) {
+ lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
+ ret = -1;
+ goto out;
+ }
+
+ lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
+ assoc_req->channel, assoc_req->band);
+
+ priv->adhoccreate = 1;
+ priv->mode = IW_MODE_ADHOC;
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
+ if (ret == 0)
+ ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-int lbs_stop_adhoc_network(struct lbs_private *priv)
+/**
+ * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @return 0 on success, or an error
+ */
+int lbs_adhoc_stop(struct lbs_private *priv)
{
- return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+ struct cmd_ds_802_11_ad_hoc_stop cmd;
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_JOIN);
+
+ memset(&cmd, 0, sizeof (cmd));
+ cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
+
+ /* Clean up everything even if there was an error */
+ lbs_mac_event_disconnected(priv);
+
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+ return ret;
}
static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
@@ -480,14 +731,14 @@ static int assoc_helper_essid(struct lbs_private *priv,
if (bss != NULL) {
lbs_deb_assoc("SSID found, will join\n");
memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- lbs_join_adhoc_network(priv, assoc_req);
+ lbs_adhoc_join(priv, assoc_req);
} else {
/* else send START command */
lbs_deb_assoc("SSID not found, creating adhoc network\n");
memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
IW_ESSID_MAX_SIZE);
assoc_req->bss.ssid_len = assoc_req->ssid_len;
- lbs_start_adhoc_network(priv, assoc_req);
+ lbs_adhoc_start(priv, assoc_req);
}
}
@@ -520,7 +771,7 @@ static int assoc_helper_bssid(struct lbs_private *priv,
ret = lbs_associate(priv, assoc_req);
lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
} else if (assoc_req->mode == IW_MODE_ADHOC) {
- lbs_join_adhoc_network(priv, assoc_req);
+ lbs_adhoc_join(priv, assoc_req);
}
out:
@@ -572,11 +823,7 @@ static int assoc_helper_mode(struct lbs_private *priv,
}
priv->mode = assoc_req->mode;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- 0, CMD_OPTION_WAITFORRSP,
- OID_802_11_INFRASTRUCTURE_MODE,
- /* Shoot me now */ (void *) (size_t) assoc_req->mode);
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
done:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1029,7 +1276,9 @@ void lbs_association_worker(struct work_struct *work)
*/
if (priv->mode == IW_MODE_INFRA) {
if (should_deauth_infrastructure(priv, assoc_req)) {
- ret = lbs_send_deauthentication(priv);
+ ret = lbs_cmd_80211_deauthenticate(priv,
+ priv->curbssparams.bssid,
+ WLAN_REASON_DEAUTH_LEAVING);
if (ret) {
lbs_deb_assoc("Deauthentication due to new "
"configuration request failed: %d\n",
@@ -1038,7 +1287,7 @@ void lbs_association_worker(struct work_struct *work)
}
} else if (priv->mode == IW_MODE_ADHOC) {
if (should_stop_adhoc(priv, assoc_req)) {
- ret = lbs_stop_adhoc_network(priv);
+ ret = lbs_adhoc_stop(priv);
if (ret) {
lbs_deb_assoc("Teardown of AdHoc network due to "
"new configuration request failed: %d\n",
@@ -1214,94 +1463,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
/**
- * @brief This function finds common rates between rate1 and card rates.
- *
- * It will fill common rates in rate1 as output if found.
- *
- * NOTE: Setting the MSB of the basic rates need to be taken
- * care, either before or after calling this function
- *
- * @param priv A pointer to struct lbs_private structure
- * @param rate1 the buffer which keeps input and output
- * @param rate1_size the size of rate1 buffer; new size of buffer on return
- *
- * @return 0 or -1
- */
-static int get_common_rates(struct lbs_private *priv,
- u8 *rates,
- u16 *rates_size)
-{
- u8 *card_rates = lbs_bg_rates;
- size_t num_card_rates = sizeof(lbs_bg_rates);
- int ret = 0, i, j;
- u8 tmp[30];
- size_t tmp_size = 0;
-
- /* For each rate in card_rates that exists in rate1, copy to tmp */
- for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
- for (j = 0; rates[j] && (j < *rates_size); j++) {
- if (rates[j] == card_rates[i])
- tmp[tmp_size++] = card_rates[i];
- }
- }
-
- lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
- lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
- lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
-
- if (!priv->enablehwauto) {
- for (i = 0; i < tmp_size; i++) {
- if (tmp[i] == priv->cur_rate)
- goto done;
- }
- lbs_pr_alert("Previously set fixed data rate %#x isn't "
- "compatible with the network.\n", priv->cur_rate);
- ret = -1;
- goto done;
- }
- ret = 0;
-
-done:
- memset(rates, 0, *rates_size);
- *rates_size = min_t(int, tmp_size, *rates_size);
- memcpy(rates, tmp, *rates_size);
- return ret;
-}
-
-
-/**
- * @brief Sets the MSB on basic rates as the firmware requires
- *
- * Scan through an array and set the MSB for basic data rates.
- *
- * @param rates buffer of data rates
- * @param len size of buffer
- */
-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (rates[i] == 0x02 || rates[i] == 0x04 ||
- rates[i] == 0x0b || rates[i] == 0x16)
- rates[i] |= 0x80;
- }
-}
-
-/**
- * @brief Send Deauthentication Request
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0--success, -1--fail
- */
-int lbs_send_deauthentication(struct lbs_private *priv)
-{
- return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-}
-
-/**
* @brief This function prepares command of authenticate.
*
* @param priv A pointer to struct lbs_private structure
@@ -1353,26 +1514,37 @@ out:
return ret;
}
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
+/**
+ * @brief Deauthenticate from a specific BSS
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param bssid The specific BSS to deauthenticate from
+ * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
+ u16 reason)
{
- struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
+ struct cmd_ds_802_11_deauthenticate cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_JOIN);
- cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
- S_DS_GEN);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
+ cmd.reasoncode = cpu_to_le16(reason);
- /* set AP MAC address */
- memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
- /* Reason code 3 = Station is leaving */
-#define REASON_CODE_STA_LEAVING 3
- dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
+ /* Clean up everything even if there was an error; can't assume that
+ * we're still authenticated to the AP after trying to deauth.
+ */
+ lbs_mac_event_disconnected(priv);
lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
+ return ret;
}
int lbs_cmd_80211_associate(struct lbs_private *priv,
@@ -1489,231 +1661,6 @@ done:
return ret;
}
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
- int ret = 0;
- int cmdappendsize = 0;
- struct assoc_request *assoc_req = pdata_buf;
- u16 tmpcap = 0;
- size_t ratesize = 0;
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- if (!priv) {
- ret = -1;
- goto done;
- }
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
-
- /*
- * Fill in the parameters for 2 data structures:
- * 1. cmd_ds_802_11_ad_hoc_start command
- * 2. priv->scantable[i]
- *
- * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
- * probe delay, and cap info.
- *
- * Firmware will fill up beacon period, DTIM, Basic rates
- * and operational rates.
- */
-
- memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
- memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
-
- lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
- assoc_req->ssid_len);
-
- /* set the BSS type */
- adhs->bsstype = CMD_BSS_TYPE_IBSS;
- priv->mode = IW_MODE_ADHOC;
- if (priv->beacon_period == 0)
- priv->beacon_period = MRVDRV_BEACON_INTERVAL;
- adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
-
- /* set Physical param set */
-#define DS_PARA_IE_ID 3
-#define DS_PARA_IE_LEN 1
-
- adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
- adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
-
- WARN_ON(!assoc_req->channel);
-
- lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
- assoc_req->channel);
-
- adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
-
- /* set IBSS param set */
-#define IBSS_PARA_IE_ID 6
-#define IBSS_PARA_IE_LEN 2
-
- adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
- adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
- adhs->ssparamset.ibssparamset.atimwindow = 0;
-
- /* set capability info */
- tmpcap = WLAN_CAPABILITY_IBSS;
- if (assoc_req->secinfo.wep_enabled) {
- lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
- "setting privacy on\n");
- tmpcap |= WLAN_CAPABILITY_PRIVACY;
- } else {
- lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
- "setting privacy off\n");
- }
- adhs->capability = cpu_to_le16(tmpcap);
-
- /* probedelay */
- adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- memset(adhs->rates, 0, sizeof(adhs->rates));
- ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
- memcpy(adhs->rates, lbs_bg_rates, ratesize);
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(adhs->rates, ratesize);
-
- lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
- adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
-
- lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
-
- if (lbs_create_dnld_countryinfo_11d(priv)) {
- lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
- S_DS_GEN + cmdappendsize);
-
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
-{
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
- cmd->size = cpu_to_le16(S_DS_GEN);
-
- return 0;
-}
-
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
- struct assoc_request *assoc_req = pdata_buf;
- struct bss_descriptor *bss = &assoc_req->bss;
- int cmdappendsize = 0;
- int ret = 0;
- u16 ratesize = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
-
- join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
- join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
-
- memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
- memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
-
- memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
- sizeof(union ieeetypes_phyparamset));
-
- memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
- sizeof(union IEEEtypes_ssparamset));
-
- join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
- lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
- bss->capability, CAPINFO_MASK);
-
- /* information on BSSID descriptor passed to FW */
- lbs_deb_join(
- "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
- print_mac(mac, join_cmd->bss.bssid),
- join_cmd->bss.ssid);
-
- /* failtimeout */
- join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
-
- /* probedelay */
- join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- priv->curbssparams.channel = bss->channel;
-
- /* Copy Data rates from the rates recorded in scan response */
- memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
- ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
- memcpy(join_cmd->bss.rates, bss->rates, ratesize);
- if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
- lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
- ret = -1;
- goto done;
- }
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
-
- join_cmd->bss.ssparamset.ibssparamset.atimwindow =
- cpu_to_le16(bss->atimwindow);
-
- if (assoc_req->secinfo.wep_enabled) {
- u16 tmp = le16_to_cpu(join_cmd->bss.capability);
- tmp |= WLAN_CAPABILITY_PRIVACY;
- join_cmd->bss.capability = cpu_to_le16(tmp);
- }
-
- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
- /* wake up first */
- __le32 Localpsmode;
-
- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_PS_MODE,
- CMD_ACT_SET,
- 0, 0, &Localpsmode);
-
- if (ret) {
- ret = -1;
- goto done;
- }
- }
-
- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
- S_DS_GEN + cmdappendsize);
-
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
@@ -1815,34 +1762,19 @@ done:
return ret;
}
-int lbs_ret_80211_disassociate(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *resp)
+static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
{
int ret = 0;
u16 command = le16_to_cpu(resp->command);
u16 result = le16_to_cpu(resp->result);
- struct cmd_ds_802_11_ad_hoc_result *padhocresult;
+ struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
union iwreq_data wrqu;
struct bss_descriptor *bss;
DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_JOIN);
- padhocresult = &resp->params.result;
-
- lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
- lbs_deb_join("ADHOC_RESP: command = %x\n", command);
- lbs_deb_join("ADHOC_RESP: result = %x\n", result);
+ adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp;
if (!priv->in_progress_assoc_req) {
lbs_deb_join("ADHOC_RESP: no in-progress association "
@@ -1856,26 +1788,19 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
* Join result code 0 --> SUCCESS
*/
if (result) {
- lbs_deb_join("ADHOC_RESP: failed\n");
+ lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
if (priv->connect_status == LBS_CONNECTED)
lbs_mac_event_disconnected(priv);
ret = -1;
goto done;
}
- /*
- * Now the join cmd should be successful
- * If BSSID has changed use SSID to compare instead of BSSID
- */
- lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
- escape_essid(bss->ssid, bss->ssid_len));
-
/* Send a Media Connected event, according to the Spec */
priv->connect_status = LBS_CONNECTED;
if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
/* Update the created network descriptor with the new BSSID */
- memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
+ memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN);
}
/* Set the BSSID from the joined/started descriptor */
@@ -1894,22 +1819,13 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
- lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
- print_mac(mac, padhocresult->bssid));
+ lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
+ escape_essid(bss->ssid, bss->ssid_len),
+ print_mac(mac, priv->curbssparams.bssid),
+ priv->curbssparams.channel);
done:
lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index c516fbe518f..8b7336dd02a 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -12,28 +12,18 @@ struct cmd_ds_command;
int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
+
+int lbs_adhoc_stop(struct lbs_private *priv);
+
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd);
+ u8 bssid[ETH_ALEN], u16 reason);
int lbs_cmd_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
-int lbs_ret_80211_disassociate(struct lbs_private *priv);
int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int lbs_stop_adhoc_network(struct lbs_private *priv);
-
-int lbs_send_deauthentication(struct lbs_private *priv);
-
#endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 75427e61898..297696de2da 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -480,181 +480,166 @@ int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
return ret;
}
-static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
-{
- struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd->command = cpu_to_le16(CMD_802_11_RESET);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
- reset->action = cpu_to_le16(cmd_action);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- int cmd_action,
- int cmd_oid, void *pdata_buf)
+/**
+ * @brief Set an SNMP MIB value
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param oid The OID to set in the firmware
+ * @param val Value to set the OID to
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
{
- struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
- u8 ucTemp;
+ struct cmd_ds_802_11_snmp_mib cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_CMD);
- lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
-
- cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
- cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
-
- switch (cmd_oid) {
- case OID_802_11_INFRASTRUCTURE_MODE:
- {
- u8 mode = (u8) (size_t) pdata_buf;
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
- if (mode == IW_MODE_ADHOC) {
- ucTemp = SNMP_MIB_VALUE_ADHOC;
- } else {
- /* Infra and Auto modes */
- ucTemp = SNMP_MIB_VALUE_INFRA;
- }
-
- memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
+ memset(&cmd, 0, sizeof (cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.oid = cpu_to_le16((u16) oid);
+ switch (oid) {
+ case SNMP_MIB_OID_BSS_TYPE:
+ cmd.bufsize = cpu_to_le16(sizeof(u8));
+ cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
break;
+ case SNMP_MIB_OID_11D_ENABLE:
+ case SNMP_MIB_OID_FRAG_THRESHOLD:
+ case SNMP_MIB_OID_RTS_THRESHOLD:
+ case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
+ case SNMP_MIB_OID_LONG_RETRY_LIMIT:
+ cmd.bufsize = cpu_to_le16(sizeof(u16));
+ *((__le16 *)(&cmd.value)) = cpu_to_le16(val);
+ break;
+ default:
+ lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
+ ret = -EINVAL;
+ goto out;
}
- case OID_802_11D_ENABLE:
- {
- u32 ulTemp;
-
- pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
-
- if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *(u32 *)pdata_buf;
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) ulTemp);
- }
- break;
- }
-
- case OID_802_11_FRAGMENTATION_THRESHOLD:
- {
- u32 ulTemp;
-
- pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
-
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *((u32 *) pdata_buf);
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) ulTemp);
+ lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
+ le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
- }
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
- break;
- }
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
- case OID_802_11_RTS_THRESHOLD:
- {
+/**
+ * @brief Get an SNMP MIB value
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param oid The OID to retrieve from the firmware
+ * @param out_val Location for the returned value
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
+{
+ struct cmd_ds_802_11_snmp_mib cmd;
+ int ret;
- u32 ulTemp;
- pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
+ lbs_deb_enter(LBS_DEB_CMD);
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *((u32 *)pdata_buf);
- *(__le16 *)(pSNMPMIB->value) =
- cpu_to_le16((u16) ulTemp);
+ memset(&cmd, 0, sizeof (cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_GET);
+ cmd.oid = cpu_to_le16(oid);
- }
- break;
- }
- case OID_802_11_TX_RETRYCOUNT:
- pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
-
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) priv->txretrycount);
- }
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
+ if (ret)
+ goto out;
+ switch (le16_to_cpu(cmd.bufsize)) {
+ case sizeof(u8):
+ if (oid == SNMP_MIB_OID_BSS_TYPE) {
+ if (cmd.value[0] == 2)
+ *out_val = IW_MODE_ADHOC;
+ else
+ *out_val = IW_MODE_INFRA;
+ } else
+ *out_val = cmd.value[0];
+ break;
+ case sizeof(u16):
+ *out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
break;
default:
+ lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
+ oid, le16_to_cpu(cmd.bufsize));
break;
}
- lbs_deb_cmd(
- "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
- le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
- le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
-
- lbs_deb_cmd(
- "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
- le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
- le16_to_cpu(pSNMPMIB->bufsize),
- le16_to_cpu(*(__le16 *) pSNMPMIB->value));
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
-static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+/**
+ * @brief Get the min, max, and current TX power
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param curlevel Current power level in dBm
+ * @param minlevel Minimum supported power level in dBm (optional)
+ * @param maxlevel Maximum supported power level in dBm (optional)
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
+ s16 *maxlevel)
{
-
- struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
+ struct cmd_ds_802_11_rf_tx_power cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->size =
- cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
- prtp->action = cpu_to_le16(cmd_action);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_GET);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
+ if (ret == 0) {
+ *curlevel = le16_to_cpu(cmd.curlevel);
+ if (minlevel)
+ *minlevel = le16_to_cpu(cmd.minlevel);
+ if (maxlevel)
+ *maxlevel = le16_to_cpu(cmd.maxlevel);
+ }
- lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
- le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
- le16_to_cpu(prtp->action));
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
+}
- switch (cmd_action) {
- case CMD_ACT_TX_POWER_OPT_GET:
- prtp->action = cpu_to_le16(CMD_ACT_GET);
- prtp->currentlevel = 0;
- break;
+/**
+ * @brief Set the TX power
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param dbm The desired power level in dBm
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
+{
+ struct cmd_ds_802_11_rf_tx_power cmd;
+ int ret;
- case CMD_ACT_TX_POWER_OPT_SET_HIGH:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
- break;
+ lbs_deb_enter(LBS_DEB_CMD);
- case CMD_ACT_TX_POWER_OPT_SET_MID:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
- break;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.curlevel = cpu_to_le16(dbm);
- case CMD_ACT_TX_POWER_OPT_SET_LOW:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
- break;
- }
+ lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ return ret;
}
static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
@@ -838,7 +823,9 @@ int lbs_update_channel(struct lbs_private *priv)
int lbs_set_channel(struct lbs_private *priv, u8 channel)
{
struct cmd_ds_802_11_rf_channel cmd;
+#ifdef DEBUG
u8 old_channel = priv->curbssparams.channel;
+#endif
int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
@@ -1033,9 +1020,9 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
return ret;
}
-int lbs_mesh_config_send(struct lbs_private *priv,
- struct cmd_ds_mesh_config *cmd,
- uint16_t action, uint16_t type)
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
{
int ret;
@@ -1054,6 +1041,19 @@ int lbs_mesh_config_send(struct lbs_private *priv,
return ret;
}
+int lbs_mesh_config_send(struct lbs_private *priv,
+ struct cmd_ds_mesh_config *cmd,
+ uint16_t action, uint16_t type)
+{
+ int ret;
+
+ if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+ return -EOPNOTSUPP;
+
+ ret = __lbs_mesh_config_send(priv, cmd, action, type);
+ return ret;
+}
+
/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
* START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
* are all handled by preparing a struct cmd_ds_mesh_config and passing it to
@@ -1095,7 +1095,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
action, priv->mesh_tlv, chan,
escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
- return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+ return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
}
static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
@@ -1256,41 +1256,47 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
priv->cur_cmd = NULL;
}
-int lbs_set_radio_control(struct lbs_private *priv)
+int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
{
- int ret = 0;
struct cmd_ds_802_11_radio_control cmd;
+ int ret = -EINVAL;
lbs_deb_enter(LBS_DEB_CMD);
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
- switch (priv->preamble) {
- case CMD_TYPE_SHORT_PREAMBLE:
- cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
- break;
-
- case CMD_TYPE_LONG_PREAMBLE:
- cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
- break;
+ /* Only v8 and below support setting the preamble */
+ if (priv->fwrelease < 0x09000000) {
+ switch (preamble) {
+ case RADIO_PREAMBLE_SHORT:
+ if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
+ goto out;
+ /* Fall through */
+ case RADIO_PREAMBLE_AUTO:
+ case RADIO_PREAMBLE_LONG:
+ cmd.control = cpu_to_le16(preamble);
+ break;
+ default:
+ goto out;
+ }
+ }
- case CMD_TYPE_AUTO_PREAMBLE:
- default:
- cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
- break;
+ if (radio_on)
+ cmd.control |= cpu_to_le16(0x1);
+ else {
+ cmd.control &= cpu_to_le16(~0x1);
+ priv->txpower_cur = 0;
}
- if (priv->radioon)
- cmd.control |= cpu_to_le16(TURN_ON_RF);
- else
- cmd.control &= cpu_to_le16(~TURN_ON_RF);
+ lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
+ radio_on ? "ON" : "OFF", preamble);
- lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
- priv->preamble);
+ priv->radio_on = radio_on;
ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
+out:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1380,55 +1386,25 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
break;
- case CMD_802_11_DEAUTHENTICATE:
- ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
- break;
-
- case CMD_802_11_AD_HOC_START:
- ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
- break;
-
- case CMD_802_11_RESET:
- ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
- break;
-
case CMD_802_11_AUTHENTICATE:
ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
break;
- case CMD_802_11_SNMP_MIB:
- ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
- cmd_action, cmd_oid, pdata_buf);
- break;
-
case CMD_MAC_REG_ACCESS:
case CMD_BBP_REG_ACCESS:
case CMD_RF_REG_ACCESS:
ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
break;
- case CMD_802_11_RF_TX_POWER:
- ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
- cmd_action, pdata_buf);
- break;
-
case CMD_802_11_MONITOR_MODE:
ret = lbs_cmd_802_11_monitor_mode(cmdptr,
cmd_action, pdata_buf);
break;
- case CMD_802_11_AD_HOC_JOIN:
- ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
- break;
-
case CMD_802_11_RSSI:
ret = lbs_cmd_802_11_rssi(priv, cmdptr);
break;
- case CMD_802_11_AD_HOC_STOP:
- ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
- break;
-
case CMD_802_11_SET_AFC:
case CMD_802_11_GET_AFC:
@@ -1953,6 +1929,70 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
}
+/**
+ * @brief Configures the transmission power control functionality.
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param enable Transmission power control enable
+ * @param p0 Power level when link quality is good (dBm).
+ * @param p1 Power level when link quality is fair (dBm).
+ * @param p2 Power level when link quality is poor (dBm).
+ * @param usesnr Use Signal to Noise Ratio in TPC
+ *
+ * @return 0 on success
+ */
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+ int8_t p2, int usesnr)
+{
+ struct cmd_ds_802_11_tpc_cfg cmd;
+ int ret;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.enable = !!enable;
+ cmd.usesnr = !!usesnr;
+ cmd.P0 = p0;
+ cmd.P1 = p1;
+ cmd.P2 = p2;
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
+
+ return ret;
+}
+
+/**
+ * @brief Configures the power adaptation settings.
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param enable Power adaptation enable
+ * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm).
+ * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
+ * @param p2 Power level for 48 and 54 Mbps (dBm).
+ *
+ * @return 0 on Success
+ */
+
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+ int8_t p1, int8_t p2)
+{
+ struct cmd_ds_802_11_pa_cfg cmd;
+ int ret;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.enable = !!enable;
+ cmd.P0 = p0;
+ cmd.P1 = p1;
+ cmd.P2 = p2;
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
+
+ return ret;
+}
+
+
static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index a53b51f8bdb..36be4c9703e 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -26,6 +26,18 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg);
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+ int8_t p1, int8_t p2);
+
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+ int8_t p2, int usesnr);
+
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+ int8_t p1, int8_t p2);
+
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+ int8_t p2, int usesnr);
+
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *resp);
@@ -61,4 +73,14 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
+int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
+ s16 *maxlevel);
+int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
+
+int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
+
+int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
+
+int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
+
#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 24de3c3cf87..bcf2a9756fb 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -146,63 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
return ret;
}
-static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
- u16 oid = le16_to_cpu(smib->oid);
- u16 querytype = le16_to_cpu(smib->querytype);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
- querytype);
- lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
-
- if (querytype == CMD_ACT_GET) {
- switch (oid) {
- case FRAGTHRESH_I:
- priv->fragthsd =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
- priv->fragthsd);
- break;
- case RTSTHRESH_I:
- priv->rtsthsd =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
- priv->rtsthsd);
- break;
- case SHORT_RETRYLIM_I:
- priv->txretrycount =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
- priv->rtsthsd);
- break;
- default:
- break;
- }
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
-
- lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
static int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
@@ -273,24 +216,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_80211_associate(priv, resp);
break;
- case CMD_RET(CMD_802_11_DISASSOCIATE):
- case CMD_RET(CMD_802_11_DEAUTHENTICATE):
- ret = lbs_ret_80211_disassociate(priv);
- break;
-
- case CMD_RET(CMD_802_11_AD_HOC_START):
- case CMD_RET(CMD_802_11_AD_HOC_JOIN):
- ret = lbs_ret_80211_ad_hoc_start(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_SNMP_MIB):
- ret = lbs_ret_802_11_snmp_mib(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_RF_TX_POWER):
- ret = lbs_ret_802_11_rf_tx_power(priv, resp);
- break;
-
case CMD_RET(CMD_802_11_SET_AFC):
case CMD_RET(CMD_802_11_GET_AFC):
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -300,7 +225,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
break;
- case CMD_RET(CMD_802_11_RESET):
case CMD_RET(CMD_802_11_AUTHENTICATE):
case CMD_RET(CMD_802_11_BEACON_STOP):
break;
@@ -309,10 +233,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_802_11_rssi(priv, resp);
break;
- case CMD_RET(CMD_802_11_AD_HOC_STOP):
- ret = lbs_ret_80211_ad_hoc_stop(priv);
- break;
-
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
ret = lbs_ret_802_11d_domain_info(resp);
break;
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index a8ac974daca..1a8888ccead 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -34,7 +34,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
-int lbs_set_radio_control(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 12e687550bc..076a636e8f6 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -189,6 +189,14 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MRVDRV_CMD_UPLD_RDY 0x0008
#define MRVDRV_CARDEVENT 0x0010
+/* Automatic TX control default levels */
+#define POW_ADAPT_DEFAULT_P0 13
+#define POW_ADAPT_DEFAULT_P1 15
+#define POW_ADAPT_DEFAULT_P2 18
+#define TPC_DEFAULT_P0 5
+#define TPC_DEFAULT_P1 10
+#define TPC_DEFAULT_P2 13
+
/** TxPD status */
/* Station firmware use TxPD status field to report final Tx transmit
@@ -243,6 +251,9 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define CMD_F_HOSTCMD (1 << 0)
#define FW_CAPINFO_WPA (1 << 0)
+#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13)
+#define FW_CAPINFO_BOOT2_UPGRADE (1<<14)
+#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15)
#define KEY_LEN_WPA_AES 16
#define KEY_LEN_WPA_TKIP 32
@@ -316,7 +327,8 @@ enum PS_STATE {
enum DNLD_STATE {
DNLD_RES_RECEIVED,
DNLD_DATA_SENT,
- DNLD_CMD_SENT
+ DNLD_CMD_SENT,
+ DNLD_BOOTCMD_SENT,
};
/** LBS_MEDIA_STATE */
@@ -339,27 +351,6 @@ enum mv_ms_type {
MVMS_EVENT
};
-/** SNMP_MIB_INDEX_e */
-enum SNMP_MIB_INDEX_e {
- DESIRED_BSSTYPE_I = 0,
- OP_RATESET_I,
- BCNPERIOD_I,
- DTIMPERIOD_I,
- ASSOCRSP_TIMEOUT_I,
- RTSTHRESH_I,
- SHORT_RETRYLIM_I,
- LONG_RETRYLIM_I,
- FRAGTHRESH_I,
- DOT11D_I,
- DOT11H_I,
- MANUFID_I,
- PRODID_I,
- MANUF_OUI_I,
- MANUF_NAME_I,
- MANUF_PRODNAME_I,
- MANUF_PRODVER_I,
-};
-
/** KEY_TYPE_ID */
enum KEY_TYPE_ID {
KEY_TYPE_ID_WEP = 0,
@@ -374,12 +365,6 @@ enum KEY_INFO_WPA {
KEY_INFO_WPA_ENABLED = 0x04
};
-/** SNMP_MIB_VALUE_e */
-enum SNMP_MIB_VALUE_e {
- SNMP_MIB_VALUE_INFRA = 1,
- SNMP_MIB_VALUE_ADHOC
-};
-
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f5bb40c54d8..f6f3753da30 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -58,6 +58,7 @@ struct lbs_802_11_security {
u8 WPA2enabled;
u8 wep_enabled;
u8 auth_mode;
+ u32 key_mgmt;
};
/** Current Basic Service Set State Structure */
@@ -240,9 +241,6 @@ struct lbs_private {
uint16_t enablehwauto;
uint16_t ratebitmap;
- u32 fragthsd;
- u32 rtsthsd;
-
u8 txretrycount;
/** Tx-related variables (for single packet tx) */
@@ -253,7 +251,9 @@ struct lbs_private {
u32 connect_status;
u32 mesh_connect_status;
u16 regioncode;
- u16 txpowerlevel;
+ s16 txpower_cur;
+ s16 txpower_min;
+ s16 txpower_max;
/** POWER MANAGEMENT AND PnP SUPPORT */
u8 surpriseremoved;
@@ -291,8 +291,7 @@ struct lbs_private {
u16 nextSNRNF;
u16 numSNRNF;
- u8 radioon;
- u32 preamble;
+ u8 radio_on;
/** data rate stuff */
u8 cur_rate;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c92e41b4faf..5004d7679c0 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -9,17 +9,6 @@
#define DEFAULT_AD_HOC_CHANNEL 6
#define DEFAULT_AD_HOC_CHANNEL_A 36
-/** IEEE 802.11 oids */
-#define OID_802_11_SSID 0x00008002
-#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
-#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
-#define OID_802_11_RTS_THRESHOLD 0x0000800A
-#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
-#define OID_802_11_SUPPORTED_RATES 0x0000800E
-#define OID_802_11_STATISTICS 0x00008012
-#define OID_802_11_TX_RETRYCOUNT 0x0000801D
-#define OID_802_11D_ENABLE 0x00008020
-
#define CMD_OPTION_WAITFORRSP 0x0002
/** Host command IDs */
@@ -61,7 +50,6 @@
#define CMD_RF_REG_MAP 0x0023
#define CMD_802_11_DEAUTHENTICATE 0x0024
#define CMD_802_11_REASSOCIATE 0x0025
-#define CMD_802_11_DISASSOCIATE 0x0026
#define CMD_MAC_CONTROL 0x0028
#define CMD_802_11_AD_HOC_START 0x002b
#define CMD_802_11_AD_HOC_JOIN 0x002c
@@ -84,6 +72,7 @@
#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
#define CMD_802_11_SLEEP_PERIOD 0x0068
#define CMD_802_11_TPC_CFG 0x0072
+#define CMD_802_11_PA_CFG 0x0073
#define CMD_802_11_FW_WAKE_METHOD 0x0074
#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
@@ -153,11 +142,6 @@
#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
-/* Define action or option for CMD_802_11_RADIO_CONTROL */
-#define CMD_TYPE_AUTO_PREAMBLE 0x0001
-#define CMD_TYPE_SHORT_PREAMBLE 0x0002
-#define CMD_TYPE_LONG_PREAMBLE 0x0003
-
/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
#define CMD_SUBSCRIBE_SNR_LOW 0x0002
@@ -166,28 +150,14 @@
#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
-#define TURN_ON_RF 0x01
-#define RADIO_ON 0x01
-#define RADIO_OFF 0x00
-
-#define SET_AUTO_PREAMBLE 0x05
-#define SET_SHORT_PREAMBLE 0x03
-#define SET_LONG_PREAMBLE 0x01
+#define RADIO_PREAMBLE_LONG 0x00
+#define RADIO_PREAMBLE_SHORT 0x02
+#define RADIO_PREAMBLE_AUTO 0x04
/* Define action or option for CMD_802_11_RF_CHANNEL */
#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
-/* Define action or option for CMD_802_11_RF_TX_POWER */
-#define CMD_ACT_TX_POWER_OPT_GET 0x0000
-#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
-#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
-#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
-
-#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
-#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
-#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
-
/* Define action or option for CMD_802_11_DATA_RATE */
#define CMD_ACT_SET_TX_AUTO 0x0000
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
@@ -210,6 +180,19 @@
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
#define CMD_WAKE_METHOD_GPIO 0x0002
+/* Object IDs for CMD_802_11_SNMP_MIB */
+#define SNMP_MIB_OID_BSS_TYPE 0x0000
+#define SNMP_MIB_OID_OP_RATE_SET 0x0001
+#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */
+#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */
+#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */
+#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005
+#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006
+#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007
+#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008
+#define SNMP_MIB_OID_11D_ENABLE 0x0009
+#define SNMP_MIB_OID_11H_ENABLE 0x000A
+
/* Define action or option for CMD_BT_ACCESS */
enum cmd_bt_access_opts {
/* The bt commands start at 5 instead of 1 because the old dft commands
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 913b480211a..d9f9a12a739 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -151,10 +151,6 @@ struct cmd_ds_get_hw_spec {
__le32 fwcapinfo;
} __attribute__ ((packed));
-struct cmd_ds_802_11_reset {
- __le16 action;
-};
-
struct cmd_ds_802_11_subscribe_event {
struct cmd_header hdr;
@@ -232,7 +228,9 @@ struct cmd_ds_802_11_authenticate {
};
struct cmd_ds_802_11_deauthenticate {
- u8 macaddr[6];
+ struct cmd_header hdr;
+
+ u8 macaddr[ETH_ALEN];
__le16 reasoncode;
};
@@ -251,20 +249,10 @@ struct cmd_ds_802_11_associate {
#endif
} __attribute__ ((packed));
-struct cmd_ds_802_11_disassociate {
- u8 destmacaddr[6];
- __le16 reasoncode;
-};
-
struct cmd_ds_802_11_associate_rsp {
struct ieeetypes_assocrsp assocRsp;
};
-struct cmd_ds_802_11_ad_hoc_result {
- u8 pad[3];
- u8 bssid[ETH_ALEN];
-};
-
struct cmd_ds_802_11_set_wep {
struct cmd_header hdr;
@@ -309,7 +297,9 @@ struct cmd_ds_802_11_get_stat {
};
struct cmd_ds_802_11_snmp_mib {
- __le16 querytype;
+ struct cmd_header hdr;
+
+ __le16 action;
__le16 oid;
__le16 bufsize;
u8 value[128];
@@ -435,8 +425,12 @@ struct cmd_ds_802_11_mac_address {
};
struct cmd_ds_802_11_rf_tx_power {
+ struct cmd_header hdr;
+
__le16 action;
- __le16 currentlevel;
+ __le16 curlevel;
+ s8 maxlevel;
+ s8 minlevel;
};
struct cmd_ds_802_11_rf_antenna {
@@ -507,10 +501,12 @@ struct cmd_ds_802_11_rate_adapt_rateset {
};
struct cmd_ds_802_11_ad_hoc_start {
+ struct cmd_header hdr;
+
u8 ssid[IW_ESSID_MAX_SIZE];
u8 bsstype;
__le16 beaconperiod;
- u8 dtimperiod;
+ u8 dtimperiod; /* Reserved on v9 and later */
union IEEEtypes_ssparamset ssparamset;
union ieeetypes_phyparamset phyparamset;
__le16 probedelay;
@@ -519,9 +515,16 @@ struct cmd_ds_802_11_ad_hoc_start {
u8 tlv_memory_size_pad[100];
} __attribute__ ((packed));
+struct cmd_ds_802_11_ad_hoc_result {
+ struct cmd_header hdr;
+
+ u8 pad[3];
+ u8 bssid[ETH_ALEN];
+};
+
struct adhoc_bssdesc {
- u8 bssid[6];
- u8 ssid[32];
+ u8 bssid[ETH_ALEN];
+ u8 ssid[IW_ESSID_MAX_SIZE];
u8 type;
__le16 beaconperiod;
u8 dtimperiod;
@@ -539,10 +542,15 @@ struct adhoc_bssdesc {
} __attribute__ ((packed));
struct cmd_ds_802_11_ad_hoc_join {
+ struct cmd_header hdr;
+
struct adhoc_bssdesc bss;
- __le16 failtimeout;
- __le16 probedelay;
+ __le16 failtimeout; /* Reserved on v9 and later */
+ __le16 probedelay; /* Reserved on v9 and later */
+} __attribute__ ((packed));
+struct cmd_ds_802_11_ad_hoc_stop {
+ struct cmd_header hdr;
} __attribute__ ((packed));
struct cmd_ds_802_11_enable_rsn {
@@ -597,14 +605,28 @@ struct cmd_ds_802_11_eeprom_access {
} __attribute__ ((packed));
struct cmd_ds_802_11_tpc_cfg {
+ struct cmd_header hdr;
+
__le16 action;
- u8 enable;
- s8 P0;
- s8 P1;
- s8 P2;
- u8 usesnr;
+ uint8_t enable;
+ int8_t P0;
+ int8_t P1;
+ int8_t P2;
+ uint8_t usesnr;
} __attribute__ ((packed));
+
+struct cmd_ds_802_11_pa_cfg {
+ struct cmd_header hdr;
+
+ __le16 action;
+ uint8_t enable;
+ int8_t P0;
+ int8_t P1;
+ int8_t P2;
+} __attribute__ ((packed));
+
+
struct cmd_ds_802_11_led_ctrl {
__le16 action;
__le16 numled;
@@ -693,21 +715,13 @@ struct cmd_ds_command {
union {
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_associate associate;
- struct cmd_ds_802_11_deauthenticate deauth;
- struct cmd_ds_802_11_ad_hoc_start ads;
- struct cmd_ds_802_11_reset reset;
- struct cmd_ds_802_11_ad_hoc_result result;
struct cmd_ds_802_11_authenticate auth;
struct cmd_ds_802_11_get_stat gstat;
struct cmd_ds_802_3_get_stat gstat_8023;
- struct cmd_ds_802_11_snmp_mib smib;
- struct cmd_ds_802_11_rf_tx_power txp;
struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_monitor_mode monitor;
- struct cmd_ds_802_11_ad_hoc_join adj;
struct cmd_ds_802_11_rssi rssi;
struct cmd_ds_802_11_rssi_rsp rssirsp;
- struct cmd_ds_802_11_disassociate dassociate;
struct cmd_ds_mac_reg_access macreg;
struct cmd_ds_bbp_reg_access bbpreg;
struct cmd_ds_rf_reg_access rfreg;
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 04d7a251e3f..842a08d1f10 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -595,7 +595,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)
if (ret < 0) {
lbs_pr_err("can't download helper at 0x%x, ret %d\n",
sent, ret);
- goto done;
+ goto err_release;
}
if (count == 0)
@@ -604,9 +604,8 @@ static int if_cs_prog_helper(struct if_cs_card *card)
sent += count;
}
+err_release:
release_firmware(fw);
- ret = 0;
-
done:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
@@ -676,14 +675,8 @@ static int if_cs_prog_real(struct if_cs_card *card)
}
ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
- if (ret < 0) {
+ if (ret < 0)
lbs_pr_err("firmware download failed\n");
- goto err_release;
- }
-
- ret = 0;
- goto done;
-
err_release:
release_firmware(fw);
@@ -720,7 +713,7 @@ static int if_cs_host_to_card(struct lbs_private *priv,
ret = if_cs_send_cmd(priv, buf, nb);
break;
default:
- lbs_pr_err("%s: unsupported type %d\n", __FUNCTION__, type);
+ lbs_pr_err("%s: unsupported type %d\n", __func__, type);
}
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
@@ -798,7 +791,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 ||
(ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 ||
- (ret = pcmcia_parse_tuple(p_dev, &tuple, &parse)) != 0)
+ (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
{
lbs_pr_err("error in pcmcia_get_first_tuple etc\n");
goto out1;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 632c291404a..cafbccb7414 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -39,7 +39,10 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int __if_usb_prog_firmware(struct if_usb_card *cardp,
+ const char *fwname, int cmd);
+static int if_usb_prog_firmware(struct if_usb_card *cardp,
+ const char *fwname, int cmd);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
@@ -48,6 +51,62 @@ static void if_usb_free(struct if_usb_card *cardp);
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
static int if_usb_reset_device(struct if_usb_card *cardp);
+/* sysfs hooks */
+
+/**
+ * Set function to write firmware to device's persistent memory
+ */
+static ssize_t if_usb_firmware_set(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct if_usb_card *cardp = priv->card;
+ char fwname[FIRMWARE_NAME_MAX];
+ int ret;
+
+ sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
+ ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_FW);
+ if (ret == 0)
+ return count;
+
+ return ret;
+}
+
+/**
+ * lbs_flash_fw attribute to be exported per ethX interface through sysfs
+ * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to
+ * the device's persistent memory:
+ * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw
+ */
+static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
+
+/**
+ * Set function to write firmware to device's persistent memory
+ */
+static ssize_t if_usb_boot2_set(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct if_usb_card *cardp = priv->card;
+ char fwname[FIRMWARE_NAME_MAX];
+ int ret;
+
+ sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
+ ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_BOOT2);
+ if (ret == 0)
+ return count;
+
+ return ret;
+}
+
+/**
+ * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs
+ * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware
+ * to the device's persistent memory:
+ * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2
+ */
+static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set);
+
/**
* @brief call back function to handle the status of the URB
* @param urb pointer to urb structure
@@ -66,10 +125,10 @@ static void if_usb_write_bulk_callback(struct urb *urb)
lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
urb->actual_length);
- /* Used for both firmware TX and regular TX. priv isn't
- * valid at firmware load time.
+ /* Boot commands such as UPDATE_FW and UPDATE_BOOT2 are not
+ * passed up to the lbs level.
*/
- if (priv)
+ if (priv && priv->dnld_sent != DNLD_BOOTCMD_SENT)
lbs_host_to_card_done(priv);
} else {
/* print the failure status number for debug */
@@ -231,7 +290,7 @@ static int if_usb_probe(struct usb_interface *intf,
}
/* Upload firmware */
- if (if_usb_prog_firmware(cardp)) {
+ if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) {
lbs_deb_usbd(&udev->dev, "FW upload failed\n");
goto err_prog_firmware;
}
@@ -260,6 +319,12 @@ static int if_usb_probe(struct usb_interface *intf,
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
+ if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw))
+ lbs_pr_err("cannot register lbs_flash_fw attribute\n");
+
+ if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
+ lbs_pr_err("cannot register lbs_flash_boot2 attribute\n");
+
return 0;
err_start_card:
@@ -285,6 +350,9 @@ static void if_usb_disconnect(struct usb_interface *intf)
lbs_deb_enter(LBS_DEB_MAIN);
+ device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2);
+ device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw);
+
cardp->surprise_removed = 1;
if (priv) {
@@ -371,11 +439,10 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
cmd->command = cpu_to_le16(CMD_802_11_RESET);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_header));
cmd->result = cpu_to_le16(0);
cmd->seqnum = cpu_to_le16(0x5a5a);
- cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT);
- usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
+ usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
msleep(100);
ret = usb_reset_device(cardp->udev);
@@ -510,7 +577,7 @@ static void if_usb_receive_fwload(struct urb *urb)
if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(cardp);
- cardp->bootcmdresp = 1;
+ cardp->bootcmdresp = BOOT_CMD_RESP_OK;
lbs_deb_usbd(&cardp->udev->dev,
"Received valid boot command response\n");
return;
@@ -526,7 +593,9 @@ static void if_usb_receive_fwload(struct urb *urb)
lbs_pr_info("boot cmd response wrong magic number (0x%x)\n",
le32_to_cpu(bootcmdresp.magic));
}
- } else if (bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
+ } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) &&
+ (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) &&
+ (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) {
lbs_pr_info("boot cmd response cmd_tag error (%d)\n",
bootcmdresp.cmd);
} else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
@@ -564,8 +633,8 @@ static void if_usb_receive_fwload(struct urb *urb)
kfree_skb(skb);
- /* reschedule timer for 200ms hence */
- mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
+ /* Give device 5s to either write firmware to its RAM or eeprom */
+ mod_timer(&cardp->fw_timeout, jiffies + (HZ*5));
if (cardp->fwfinalblk) {
cardp->fwdnldover = 1;
@@ -809,7 +878,54 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
}
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
+/**
+* @brief This function programs the firmware subject to cmd
+*
+* @param cardp the if_usb_card descriptor
+* fwname firmware or boot2 image file name
+* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW,
+* or BOOT_CMD_UPDATE_BOOT2.
+* @return 0 or error code
+*/
+static int if_usb_prog_firmware(struct if_usb_card *cardp,
+ const char *fwname, int cmd)
+{
+ struct lbs_private *priv = cardp->priv;
+ unsigned long flags, caps;
+ int ret;
+
+ caps = priv->fwcapinfo;
+ if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) ||
+ ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE)))
+ return -EOPNOTSUPP;
+
+ /* Ensure main thread is idle. */
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) {
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ if (wait_event_interruptible(priv->waitq,
+ (priv->cur_cmd == NULL &&
+ priv->dnld_sent == DNLD_RES_RECEIVED))) {
+ return -ERESTARTSYS;
+ }
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ }
+ priv->dnld_sent = DNLD_BOOTCMD_SENT;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ ret = __if_usb_prog_firmware(cardp, fwname, cmd);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ wake_up_interruptible(&priv->waitq);
+
+ return ret;
+}
+
+static int __if_usb_prog_firmware(struct if_usb_card *cardp,
+ const char *fwname, int cmd)
{
int i = 0;
static int reset_count = 10;
@@ -817,20 +933,32 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
lbs_deb_enter(LBS_DEB_USB);
- if ((ret = request_firmware(&cardp->fw, lbs_fw_name,
- &cardp->udev->dev)) < 0) {
+ ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+ if (ret < 0) {
lbs_pr_err("request_firmware() failed with %#x\n", ret);
- lbs_pr_err("firmware %s not found\n", lbs_fw_name);
+ lbs_pr_err("firmware %s not found\n", fwname);
goto done;
}
- if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
+ if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
+ ret = -EINVAL;
goto release_fw;
+ }
+
+ /* Cancel any pending usb business */
+ usb_kill_urb(cardp->rx_urb);
+ usb_kill_urb(cardp->tx_urb);
+
+ cardp->fwlastblksent = 0;
+ cardp->fwdnldover = 0;
+ cardp->totalbytes = 0;
+ cardp->fwfinalblk = 0;
+ cardp->bootcmdresp = 0;
restart:
if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
- ret = -1;
+ ret = -EIO;
goto release_fw;
}
@@ -838,8 +966,7 @@ restart:
do {
int j = 0;
i++;
- /* Issue Boot command = 1, Boot from Download-FW */
- if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
+ if_usb_issue_boot_command(cardp, cmd);
/* wait for command response */
do {
j++;
@@ -847,12 +974,21 @@ restart:
} while (cardp->bootcmdresp == 0 && j < 10);
} while (cardp->bootcmdresp == 0 && i < 5);
- if (cardp->bootcmdresp <= 0) {
+ if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
+ /* Return to normal operation */
+ ret = -EOPNOTSUPP;
+ usb_kill_urb(cardp->rx_urb);
+ usb_kill_urb(cardp->tx_urb);
+ if (if_usb_submit_rx_urb(cardp) < 0)
+ ret = -EIO;
+ goto release_fw;
+ } else if (cardp->bootcmdresp <= 0) {
if (--reset_count >= 0) {
if_usb_reset_device(cardp);
goto restart;
}
- return -1;
+ ret = -EIO;
+ goto release_fw;
}
i = 0;
@@ -882,7 +1018,7 @@ restart:
}
lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
- ret = -1;
+ ret = -EIO;
goto release_fw;
}
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 5771a83a43f..5ba0aee0eb2 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -30,6 +30,7 @@ struct bootcmd
#define BOOT_CMD_RESP_OK 0x0001
#define BOOT_CMD_RESP_FAIL 0x0000
+#define BOOT_CMD_RESP_NOT_SUPPORTED 0x0002
struct bootcmdresp
{
@@ -50,6 +51,10 @@ struct if_usb_card {
uint8_t ep_in;
uint8_t ep_out;
+ /* bootcmdresp == 0 means command is pending
+ * bootcmdresp < 0 means error
+ * bootcmdresp > 0 is a BOOT_CMD_RESP_* from firmware
+ */
int8_t bootcmdresp;
int ep_in_size;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index bd32ac0b4e0..73dc8c72402 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -291,9 +291,11 @@ static ssize_t lbs_rtap_set(struct device *dev,
if (priv->infra_open || priv->mesh_open)
return -EBUSY;
if (priv->mode == IW_MODE_INFRA)
- lbs_send_deauthentication(priv);
+ lbs_cmd_80211_deauthenticate(priv,
+ priv->curbssparams.bssid,
+ WLAN_REASON_DEAUTH_LEAVING);
else if (priv->mode == IW_MODE_ADHOC)
- lbs_stop_adhoc_network(priv);
+ lbs_adhoc_stop(priv);
lbs_add_rtap(priv);
}
priv->monitormode = monitor_mode;
@@ -956,17 +958,24 @@ EXPORT_SYMBOL_GPL(lbs_resume);
static int lbs_setup_firmware(struct lbs_private *priv)
{
int ret = -1;
+ s16 curlevel = 0, minlevel = 0, maxlevel = 0;
lbs_deb_enter(LBS_DEB_FW);
- /*
- * Read MAC address from HW
- */
+ /* Read MAC address from firmware */
memset(priv->current_addr, 0xff, ETH_ALEN);
ret = lbs_update_hw_spec(priv);
if (ret)
goto done;
+ /* Read power levels if available */
+ ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
+ if (ret == 0) {
+ priv->txpower_cur = curlevel;
+ priv->txpower_min = minlevel;
+ priv->txpower_max = maxlevel;
+ }
+
lbs_set_mac_control(priv);
done:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -1042,7 +1051,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->mode = IW_MODE_INFRA;
priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- priv->radioon = RADIO_ON;
+ priv->radio_on = 1;
priv->enablehwauto = 1;
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->psmode = LBS802_11POWERMODECAM;
@@ -1196,7 +1205,13 @@ void lbs_remove_card(struct lbs_private *priv)
cancel_delayed_work_sync(&priv->scan_work);
cancel_delayed_work_sync(&priv->assoc_work);
cancel_work_sync(&priv->mcast_work);
+
+ /* worker thread destruction blocks on the in-flight command which
+ * should have been cleared already in lbs_stop_card().
+ */
+ lbs_deb_main("destroying worker thread\n");
destroy_workqueue(priv->work_thread);
+ lbs_deb_main("done destroying worker thread\n");
if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
priv->psmode = LBS802_11POWERMODECAM;
@@ -1314,14 +1329,26 @@ void lbs_stop_card(struct lbs_private *priv)
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
}
- /* Flush pending command nodes */
+ /* Delete the timeout of the currently processing command */
del_timer_sync(&priv->command_timer);
+
+ /* Flush pending command nodes */
spin_lock_irqsave(&priv->driver_lock, flags);
+ lbs_deb_main("clearing pending commands\n");
list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
cmdnode->result = -ENOENT;
cmdnode->cmdwaitqwoken = 1;
wake_up_interruptible(&cmdnode->cmdwait_q);
}
+
+ /* Flush the command the card is currently processing */
+ if (priv->cur_cmd) {
+ lbs_deb_main("clearing current command\n");
+ priv->cur_cmd->result = -ENOENT;
+ priv->cur_cmd->cmdwaitqwoken = 1;
+ wake_up_interruptible(&priv->cur_cmd->cmdwait_q);
+ }
+ lbs_deb_main("done clearing commands\n");
spin_unlock_irqrestore(&priv->driver_lock, flags);
unregister_netdev(dev);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 4b274562f96..8f66903641b 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -944,6 +944,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT);
+ if (!priv->radio_on) {
+ ret = -EINVAL;
+ goto out;
+ }
+
if (!netif_running(dev)) {
ret = -ENETDOWN;
goto out;
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 8b3ed77860b..82c3e5a50ea 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -30,6 +30,14 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv)
queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
}
+static inline void lbs_do_association_work(struct lbs_private *priv)
+{
+ if (priv->surpriseremoved)
+ return;
+ cancel_delayed_work(&priv->assoc_work);
+ queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
+}
+
static inline void lbs_cancel_association_work(struct lbs_private *priv)
{
cancel_delayed_work(&priv->assoc_work);
@@ -120,34 +128,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
return cfp;
}
-
-/**
- * @brief Set Radio On/OFF
- *
- * @param priv A pointer to struct lbs_private structure
- * @option Radio Option
- * @return 0 --success, otherwise fail
- */
-static int lbs_radio_ioctl(struct lbs_private *priv, u8 option)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (priv->radioon != option) {
- lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
- priv->radioon = option;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RADIO_CONTROL,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- }
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
/**
* @brief Copy active data rates based on adapter mode and status
*
@@ -294,21 +274,17 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
{
int ret = 0;
struct lbs_private *priv = dev->priv;
- u32 rthr = vwrq->value;
+ u32 val = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
- if (vwrq->disabled) {
- priv->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
- } else {
- if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
- return -EINVAL;
- priv->rtsthsd = rthr;
- }
+ if (vwrq->disabled)
+ val = MRVDRV_RTS_MAX_VALUE;
+
+ if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
+ return -EINVAL;
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
- OID_802_11_RTS_THRESHOLD, &rthr);
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
@@ -317,21 +293,18 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- int ret = 0;
struct lbs_private *priv = dev->priv;
+ int ret = 0;
+ u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- priv->rtsthsd = 0;
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_RTS_THRESHOLD, NULL);
+ ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
if (ret)
goto out;
- vwrq->value = priv->rtsthsd;
- vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
- || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
+ vwrq->value = val;
+ vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
vwrq->fixed = 1;
out:
@@ -342,24 +315,19 @@ out:
static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- int ret = 0;
- u32 fthr = vwrq->value;
struct lbs_private *priv = dev->priv;
+ int ret = 0;
+ u32 val = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
- if (vwrq->disabled) {
- priv->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
- } else {
- if (fthr < MRVDRV_FRAG_MIN_VALUE
- || fthr > MRVDRV_FRAG_MAX_VALUE)
- return -EINVAL;
- priv->fragthsd = fthr;
- }
+ if (vwrq->disabled)
+ val = MRVDRV_FRAG_MAX_VALUE;
+
+ if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
+ return -EINVAL;
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
- OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
@@ -368,22 +336,19 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- int ret = 0;
struct lbs_private *priv = dev->priv;
+ int ret = 0;
+ u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- priv->fragthsd = 0;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
+ ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
if (ret)
goto out;
- vwrq->value = priv->fragthsd;
- vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
- || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
+ vwrq->value = val;
+ vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
+ || (val > MRVDRV_FRAG_MAX_VALUE));
vwrq->fixed = 1;
out:
@@ -410,7 +375,7 @@ static int mesh_wlan_get_mode(struct net_device *dev,
{
lbs_deb_enter(LBS_DEB_WEXT);
- *uwrq = IW_MODE_REPEAT ;
+ *uwrq = IW_MODE_REPEAT;
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
@@ -420,28 +385,30 @@ static int lbs_get_txpow(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- int ret = 0;
struct lbs_private *priv = dev->priv;
+ s16 curlevel = 0;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RF_TX_POWER,
- CMD_ACT_TX_POWER_OPT_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+ if (!priv->radio_on) {
+ lbs_deb_wext("tx power off\n");
+ vwrq->value = 0;
+ vwrq->disabled = 1;
+ goto out;
+ }
+ ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
if (ret)
goto out;
- lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel);
- vwrq->value = priv->txpowerlevel;
+ lbs_deb_wext("tx power level %d dbm\n", curlevel);
+ priv->txpower_cur = curlevel;
+
+ vwrq->value = curlevel;
vwrq->fixed = 1;
- if (priv->radioon) {
- vwrq->disabled = 0;
- vwrq->flags = IW_TXPOW_DBM;
- } else {
- vwrq->disabled = 1;
- }
+ vwrq->disabled = 0;
+ vwrq->flags = IW_TXPOW_DBM;
out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
@@ -451,31 +418,44 @@ out:
static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- int ret = 0;
struct lbs_private *priv = dev->priv;
+ int ret = 0;
+ u16 slimit = 0, llimit = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- if (vwrq->flags == IW_RETRY_LIMIT) {
- /* The MAC has a 4-bit Total_Tx_Count register
- Total_Tx_Count = 1 + Tx_Retry_Count */
+ if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
+ return -EOPNOTSUPP;
+
+ /* The MAC has a 4-bit Total_Tx_Count register
+ Total_Tx_Count = 1 + Tx_Retry_Count */
#define TX_RETRY_MIN 0
#define TX_RETRY_MAX 14
- if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
- return -EINVAL;
+ if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
+ return -EINVAL;
- /* Adding 1 to convert retry count to try count */
- priv->txretrycount = vwrq->value + 1;
+ /* Add 1 to convert retry count to try count */
+ if (vwrq->flags & IW_RETRY_SHORT)
+ slimit = (u16) (vwrq->value + 1);
+ else if (vwrq->flags & IW_RETRY_LONG)
+ llimit = (u16) (vwrq->value + 1);
+ else
+ slimit = llimit = (u16) (vwrq->value + 1); /* set both */
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP,
- OID_802_11_TX_RETRYCOUNT, NULL);
+ if (llimit) {
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
+ llimit);
+ if (ret)
+ goto out;
+ }
+ if (slimit) {
+ /* txretrycount follows the short retry limit */
+ priv->txretrycount = slimit;
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
+ slimit);
if (ret)
goto out;
- } else {
- return -EOPNOTSUPP;
}
out:
@@ -488,22 +468,30 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
{
struct lbs_private *priv = dev->priv;
int ret = 0;
+ u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- priv->txretrycount = 0;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_TX_RETRYCOUNT, NULL);
- if (ret)
- goto out;
-
vwrq->disabled = 0;
- if (!vwrq->flags) {
- vwrq->flags = IW_RETRY_LIMIT;
+
+ if (vwrq->flags & IW_RETRY_LONG) {
+ ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
+ if (ret)
+ goto out;
+
+ /* Subtract 1 to convert try count to retry count */
+ vwrq->value = val - 1;
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
+ } else {
+ ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
+ if (ret)
+ goto out;
+
+ /* txretry count follows the short retry limit */
+ priv->txretrycount = val;
/* Subtract 1 to convert try count to retry count */
- vwrq->value = priv->txretrycount - 1;
+ vwrq->value = val - 1;
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
}
out:
@@ -693,22 +681,12 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
range->sensitivity = 0;
- /*
- * Setup the supported power level ranges
- */
+ /* Setup the supported power level ranges */
memset(range->txpower, 0, sizeof(range->txpower));
- range->txpower[0] = 5;
- range->txpower[1] = 7;
- range->txpower[2] = 9;
- range->txpower[3] = 11;
- range->txpower[4] = 13;
- range->txpower[5] = 15;
- range->txpower[6] = 17;
- range->txpower[7] = 19;
-
- range->num_txpower = 8;
- range->txpower_capa = IW_TXPOW_DBM;
- range->txpower_capa |= IW_TXPOW_RANGE;
+ range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
+ range->txpower[0] = priv->txpower_min;
+ range->txpower[1] = priv->txpower_max;
+ range->num_txpower = 2;
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
IW_EVENT_CAPA_MASK(SIOCGIWAP) |
@@ -998,9 +976,11 @@ static int lbs_mesh_set_freq(struct net_device *dev,
if (fwrq->m != priv->curbssparams.channel) {
lbs_deb_wext("mesh channel change forces eth disconnect\n");
if (priv->mode == IW_MODE_INFRA)
- lbs_send_deauthentication(priv);
+ lbs_cmd_80211_deauthenticate(priv,
+ priv->curbssparams.bssid,
+ WLAN_REASON_DEAUTH_LEAVING);
else if (priv->mode == IW_MODE_ADHOC)
- lbs_stop_adhoc_network(priv);
+ lbs_adhoc_stop(priv);
}
lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
lbs_update_channel(priv);
@@ -1045,6 +1025,18 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
new_rate);
goto out;
}
+ if (priv->fwrelease < 0x09000000) {
+ ret = lbs_set_power_adapt_cfg(priv, 0,
+ POW_ADAPT_DEFAULT_P0,
+ POW_ADAPT_DEFAULT_P1,
+ POW_ADAPT_DEFAULT_P2);
+ if (ret)
+ goto out;
+ }
+ ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+ TPC_DEFAULT_P2, 1);
+ if (ret)
+ goto out;
}
/* Try the newer command first (Firmware Spec 5.1 and above) */
@@ -1612,12 +1604,26 @@ static int lbs_set_encodeext(struct net_device *dev,
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
}
- disable_wep (assoc_req);
+ /* Only disable wep if necessary: can't waste time here. */
+ if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
+ disable_wep(assoc_req);
}
out:
if (ret == 0) {
- lbs_postpone_association_work(priv);
+ /* 802.1x and WPA rekeying must happen as quickly as possible,
+ * especially during the 4-way handshake; thus if in
+ * infrastructure mode, and either (a) 802.1x is enabled or
+ * (b) WPA is being used, set the key right away.
+ */
+ if (assoc_req->mode == IW_MODE_INFRA &&
+ ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
+ (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
+ assoc_req->secinfo.WPAenabled ||
+ assoc_req->secinfo.WPA2enabled)) {
+ lbs_do_association_work(priv);
+ } else
+ lbs_postpone_association_work(priv);
} else {
lbs_cancel_association_work(priv);
}
@@ -1725,13 +1731,17 @@ static int lbs_set_auth(struct net_device *dev,
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_KEY_MGMT:
case IW_AUTH_DROP_UNENCRYPTED:
/*
* libertas does not use these parameters
*/
break;
+ case IW_AUTH_KEY_MGMT:
+ assoc_req->secinfo.key_mgmt = dwrq->value;
+ updated = 1;
+ break;
+
case IW_AUTH_WPA_VERSION:
if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
assoc_req->secinfo.WPAenabled = 0;
@@ -1811,6 +1821,10 @@ static int lbs_get_auth(struct net_device *dev,
lbs_deb_enter(LBS_DEB_WEXT);
switch (dwrq->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_KEY_MGMT:
+ dwrq->value = priv->secinfo.key_mgmt;
+ break;
+
case IW_AUTH_WPA_VERSION:
dwrq->value = 0;
if (priv->secinfo.WPAenabled)
@@ -1844,39 +1858,77 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
{
int ret = 0;
struct lbs_private *priv = dev->priv;
-
- u16 dbm;
+ s16 dbm = (s16) vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
- lbs_radio_ioctl(priv, RADIO_OFF);
- return 0;
+ lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
+ goto out;
}
- priv->preamble = CMD_TYPE_AUTO_PREAMBLE;
-
- lbs_radio_ioctl(priv, RADIO_ON);
+ if (vwrq->fixed == 0) {
+ /* User requests automatic tx power control, however there are
+ * many auto tx settings. For now use firmware defaults until
+ * we come up with a good way to expose these to the user. */
+ if (priv->fwrelease < 0x09000000) {
+ ret = lbs_set_power_adapt_cfg(priv, 1,
+ POW_ADAPT_DEFAULT_P0,
+ POW_ADAPT_DEFAULT_P1,
+ POW_ADAPT_DEFAULT_P2);
+ if (ret)
+ goto out;
+ }
+ ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+ TPC_DEFAULT_P2, 1);
+ if (ret)
+ goto out;
+ dbm = priv->txpower_max;
+ } else {
+ /* Userspace check in iwrange if it should use dBm or mW,
+ * therefore this should never happen... Jean II */
+ if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
- /* Userspace check in iwrange if it should use dBm or mW,
- * therefore this should never happen... Jean II */
- if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
- return -EOPNOTSUPP;
- } else
- dbm = (u16) vwrq->value;
+ /* Validate requested power level against firmware allowed
+ * levels */
+ if (priv->txpower_min && (dbm < priv->txpower_min)) {
+ ret = -EINVAL;
+ goto out;
+ }
- /* auto tx power control */
+ if (priv->txpower_max && (dbm > priv->txpower_max)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (priv->fwrelease < 0x09000000) {
+ ret = lbs_set_power_adapt_cfg(priv, 0,
+ POW_ADAPT_DEFAULT_P0,
+ POW_ADAPT_DEFAULT_P1,
+ POW_ADAPT_DEFAULT_P2);
+ if (ret)
+ goto out;
+ }
+ ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+ TPC_DEFAULT_P2, 1);
+ if (ret)
+ goto out;
+ }
- if (vwrq->fixed == 0)
- dbm = 0xffff;
+ /* If the radio was off, turn it on */
+ if (!priv->radio_on) {
+ ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
+ if (ret)
+ goto out;
+ }
- lbs_deb_wext("txpower set %d dbm\n", dbm);
+ lbs_deb_wext("txpower set %d dBm\n", dbm);
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RF_TX_POWER,
- CMD_ACT_TX_POWER_OPT_SET_LOW,
- CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
+ ret = lbs_set_tx_power(priv, dbm);
+out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1928,6 +1980,11 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT);
+ if (!priv->radio_on) {
+ ret = -EINVAL;
+ goto out;
+ }
+
/* Check the size of the string */
if (in_ssid_len > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
@@ -2005,6 +2062,11 @@ static int lbs_mesh_set_essid(struct net_device *dev,
lbs_deb_enter(LBS_DEB_WEXT);
+ if (!priv->radio_on) {
+ ret = -EINVAL;
+ goto out;
+ }
+
/* Check the size of the string */
if (dwrq->length > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
@@ -2046,6 +2108,9 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT);
+ if (!priv->radio_on)
+ return -EINVAL;
+
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
diff --git a/drivers/net/wireless/libertas_tf/Makefile b/drivers/net/wireless/libertas_tf/Makefile
new file mode 100644
index 00000000000..ff5544d6ac9
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/Makefile
@@ -0,0 +1,6 @@
+libertas_tf-objs := main.o cmd.o
+
+libertas_tf_usb-objs += if_usb.o
+
+obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf.o
+obj-$(CONFIG_LIBERTAS_THINFIRM_USB) += libertas_tf_usb.o
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
new file mode 100644
index 00000000000..fdbcf8ba3e8
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2008, cozybit Inc.
+ * Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#include "libertas_tf.h"
+
+static const struct channel_range channel_ranges[] = {
+ { LBTF_REGDOMAIN_US, 1, 12 },
+ { LBTF_REGDOMAIN_CA, 1, 12 },
+ { LBTF_REGDOMAIN_EU, 1, 14 },
+ { LBTF_REGDOMAIN_JP, 1, 14 },
+ { LBTF_REGDOMAIN_SP, 1, 14 },
+ { LBTF_REGDOMAIN_FR, 1, 14 },
+};
+
+static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+{
+ LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU,
+ LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP,
+};
+
+static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv);
+
+
+/**
+ * lbtf_cmd_copyback - Simple callback that copies response back into command
+ *
+ * @priv A pointer to struct lbtf_private structure
+ * @extra A pointer to the original command structure for which
+ * 'resp' is a response
+ * @resp A pointer to the command response
+ *
+ * Returns: 0 on success, error on failure
+ */
+int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
+ struct cmd_header *resp)
+{
+ struct cmd_header *buf = (void *)extra;
+ uint16_t copy_len;
+
+ copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+ memcpy(buf, resp, copy_len);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_cmd_copyback);
+
+#define CHAN_TO_IDX(chan) ((chan) - 1)
+
+static void lbtf_geo_init(struct lbtf_private *priv)
+{
+ const struct channel_range *range = channel_ranges;
+ u8 ch;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(channel_ranges); i++)
+ if (channel_ranges[i].regdomain == priv->regioncode) {
+ range = &channel_ranges[i];
+ break;
+ }
+
+ for (ch = priv->range.start; ch < priv->range.end; ch++)
+ priv->channels[CHAN_TO_IDX(ch)].flags = 0;
+}
+
+/**
+ * lbtf_update_hw_spec: Updates the hardware details.
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: 0 on success, error on failure
+ */
+int lbtf_update_hw_spec(struct lbtf_private *priv)
+{
+ struct cmd_ds_get_hw_spec cmd;
+ int ret = -1;
+ u32 i;
+ DECLARE_MAC_BUF(mac);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
+ ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
+ if (ret)
+ goto out;
+
+ priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
+
+ /* The firmware release is in an interesting format: the patch
+ * level is in the most significant nibble ... so fix that: */
+ priv->fwrelease = le32_to_cpu(cmd.fwrelease);
+ priv->fwrelease = (priv->fwrelease << 8) |
+ (priv->fwrelease >> 24 & 0xff);
+
+ printk(KERN_INFO "libertastf: %s, fw %u.%u.%up%u, cap 0x%08x\n",
+ print_mac(mac, cmd.permanentaddr),
+ priv->fwrelease >> 24 & 0xff,
+ priv->fwrelease >> 16 & 0xff,
+ priv->fwrelease >> 8 & 0xff,
+ priv->fwrelease & 0xff,
+ priv->fwcapinfo);
+
+ /* Clamp region code to 8-bit since FW spec indicates that it should
+ * only ever be 8-bit, even though the field size is 16-bit. Some
+ * firmware returns non-zero high 8 bits here.
+ */
+ priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* use the region code to search for the index */
+ if (priv->regioncode == lbtf_region_code_to_index[i])
+ break;
+ }
+
+ /* if it's unidentified region code, use the default (USA) */
+ if (i >= MRVDRV_MAX_REGION_CODE)
+ priv->regioncode = 0x10;
+
+ if (priv->current_addr[0] == 0xff)
+ memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
+
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr);
+
+ lbtf_geo_init(priv);
+out:
+ return ret;
+}
+
+/**
+ * lbtf_set_channel: Set the radio channel
+ *
+ * @priv A pointer to struct lbtf_private structure
+ * @channel The desired channel, or 0 to clear a locked channel
+ *
+ * Returns: 0 on success, error on failure
+ */
+int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
+{
+ struct cmd_ds_802_11_rf_channel cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+ cmd.channel = cpu_to_le16(channel);
+
+ return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+}
+
+int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
+{
+ struct cmd_ds_802_11_beacon_set cmd;
+ int size;
+
+ if (beacon->len > MRVL_MAX_BCN_SIZE)
+ return -1;
+ size = sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
+ cmd.hdr.size = cpu_to_le16(size);
+ cmd.len = cpu_to_le16(beacon->len);
+ memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
+
+ lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
+ return 0;
+}
+
+int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
+ int beacon_int) {
+ struct cmd_ds_802_11_beacon_control cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.beacon_enable = cpu_to_le16(beacon_enable);
+ cmd.beacon_period = cpu_to_le16(beacon_int);
+
+ lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
+ return 0;
+}
+
+static void lbtf_queue_cmd(struct lbtf_private *priv,
+ struct cmd_ctrl_node *cmdnode)
+{
+ unsigned long flags;
+
+ if (!cmdnode)
+ return;
+
+ if (!cmdnode->cmdbuf->size)
+ return;
+
+ cmdnode->result = 0;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ list_add_tail(&cmdnode->list, &priv->cmdpendingq);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+}
+
+static void lbtf_submit_command(struct lbtf_private *priv,
+ struct cmd_ctrl_node *cmdnode)
+{
+ unsigned long flags;
+ struct cmd_header *cmd;
+ uint16_t cmdsize;
+ uint16_t command;
+ int timeo = 5 * HZ;
+ int ret;
+
+ cmd = cmdnode->cmdbuf;
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->cur_cmd = cmdnode;
+ cmdsize = le16_to_cpu(cmd->size);
+ command = le16_to_cpu(cmd->command);
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ if (ret)
+ /* Let the timer kick in and retry, and potentially reset
+ the whole thing if the condition persists */
+ timeo = HZ;
+
+ /* Setup the timer after transmit command */
+ mod_timer(&priv->command_timer, jiffies + timeo);
+}
+
+/**
+ * This function inserts command node to cmdfreeq
+ * after cleans it. Requires priv->driver_lock held.
+ */
+static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
+ struct cmd_ctrl_node *cmdnode)
+{
+ if (!cmdnode)
+ return;
+
+ cmdnode->callback = NULL;
+ cmdnode->callback_arg = 0;
+
+ memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
+
+ list_add_tail(&cmdnode->list, &priv->cmdfreeq);
+}
+
+static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
+ struct cmd_ctrl_node *ptempcmd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ __lbtf_cleanup_and_insert_cmd(priv, ptempcmd);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+}
+
+void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
+{
+ cmd->result = result;
+ cmd->cmdwaitqwoken = 1;
+ wake_up_interruptible(&cmd->cmdwait_q);
+
+ if (!cmd->callback)
+ __lbtf_cleanup_and_insert_cmd(priv, cmd);
+ priv->cur_cmd = NULL;
+}
+
+int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
+{
+ struct cmd_ds_mac_multicast_addr cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+ cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
+ memcpy(cmd.maclist, priv->multicastlist,
+ priv->nr_of_multicastmacaddr * ETH_ALEN);
+
+ lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
+ return 0;
+}
+
+void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
+{
+ struct cmd_ds_set_mode cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.mode = cpu_to_le16(mode);
+ lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
+}
+
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid)
+{
+ struct cmd_ds_set_bssid cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.activate = activate ? 1 : 0;
+ if (activate)
+ memcpy(cmd.bssid, bssid, ETH_ALEN);
+
+ lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
+}
+
+int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
+{
+ struct cmd_ds_802_11_mac_address cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+ memcpy(cmd.macadd, mac_addr, ETH_ALEN);
+
+ lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
+ return 0;
+}
+
+int lbtf_set_radio_control(struct lbtf_private *priv)
+{
+ int ret = 0;
+ struct cmd_ds_802_11_radio_control cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+ switch (priv->preamble) {
+ case CMD_TYPE_SHORT_PREAMBLE:
+ cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
+ break;
+
+ case CMD_TYPE_LONG_PREAMBLE:
+ cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
+ break;
+
+ case CMD_TYPE_AUTO_PREAMBLE:
+ default:
+ cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
+ break;
+ }
+
+ if (priv->radioon)
+ cmd.control |= cpu_to_le16(TURN_ON_RF);
+ else
+ cmd.control &= cpu_to_le16(~TURN_ON_RF);
+
+ ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
+ return ret;
+}
+
+void lbtf_set_mac_control(struct lbtf_private *priv)
+{
+ struct cmd_ds_mac_control cmd;
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(priv->mac_control);
+ cmd.reserved = 0;
+
+ lbtf_cmd_async(priv, CMD_MAC_CONTROL,
+ &cmd.hdr, sizeof(cmd));
+}
+
+/**
+ * lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: 0 on success.
+ */
+int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
+{
+ u32 bufsize;
+ u32 i;
+ struct cmd_ctrl_node *cmdarray;
+
+ /* Allocate and initialize the command array */
+ bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
+ cmdarray = kzalloc(bufsize, GFP_KERNEL);
+ if (!cmdarray)
+ return -1;
+ priv->cmd_array = cmdarray;
+
+ /* Allocate and initialize each command buffer in the command array */
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
+ if (!cmdarray[i].cmdbuf)
+ return -1;
+ }
+
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ init_waitqueue_head(&cmdarray[i].cmdwait_q);
+ lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
+ }
+ return 0;
+}
+
+/**
+ * lbtf_free_cmd_buffer - Frees the cmd buffer.
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: 0
+ */
+int lbtf_free_cmd_buffer(struct lbtf_private *priv)
+{
+ struct cmd_ctrl_node *cmdarray;
+ unsigned int i;
+
+ /* need to check if cmd array is allocated or not */
+ if (priv->cmd_array == NULL)
+ return 0;
+
+ cmdarray = priv->cmd_array;
+
+ /* Release shared memory buffers */
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ kfree(cmdarray[i].cmdbuf);
+ cmdarray[i].cmdbuf = NULL;
+ }
+
+ /* Release cmd_ctrl_node */
+ kfree(priv->cmd_array);
+ priv->cmd_array = NULL;
+
+ return 0;
+}
+
+/**
+ * lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue.
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: pointer to a struct cmd_ctrl_node or NULL if none available.
+ */
+static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
+{
+ struct cmd_ctrl_node *tempnode;
+ unsigned long flags;
+
+ if (!priv)
+ return NULL;
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (!list_empty(&priv->cmdfreeq)) {
+ tempnode = list_first_entry(&priv->cmdfreeq,
+ struct cmd_ctrl_node, list);
+ list_del(&tempnode->list);
+ } else
+ tempnode = NULL;
+
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ return tempnode;
+}
+
+/**
+ * lbtf_execute_next_command: execute next command in cmd pending queue.
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: 0 on success.
+ */
+int lbtf_execute_next_command(struct lbtf_private *priv)
+{
+ struct cmd_ctrl_node *cmdnode = NULL;
+ struct cmd_header *cmd;
+ unsigned long flags;
+
+ /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
+ * only caller to us is lbtf_thread() and we get even when a
+ * data packet is received */
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (priv->cur_cmd) {
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ return -1;
+ }
+
+ if (!list_empty(&priv->cmdpendingq)) {
+ cmdnode = list_first_entry(&priv->cmdpendingq,
+ struct cmd_ctrl_node, list);
+ }
+
+ if (cmdnode) {
+ cmd = cmdnode->cmdbuf;
+
+ list_del(&cmdnode->list);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ lbtf_submit_command(priv, cmdnode);
+ } else
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ return 0;
+}
+
+static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
+ uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbtf_private *, unsigned long,
+ struct cmd_header *),
+ unsigned long callback_arg)
+{
+ struct cmd_ctrl_node *cmdnode;
+
+ if (priv->surpriseremoved)
+ return ERR_PTR(-ENOENT);
+
+ cmdnode = lbtf_get_cmd_ctrl_node(priv);
+ if (cmdnode == NULL) {
+ /* Wake up main thread to execute next command */
+ queue_work(lbtf_wq, &priv->cmd_work);
+ return ERR_PTR(-ENOBUFS);
+ }
+
+ cmdnode->callback = callback;
+ cmdnode->callback_arg = callback_arg;
+
+ /* Copy the incoming command to the buffer */
+ memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
+
+ /* Set sequence number, clean result, move to buffer */
+ priv->seqnum++;
+ cmdnode->cmdbuf->command = cpu_to_le16(command);
+ cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size);
+ cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum);
+ cmdnode->cmdbuf->result = 0;
+ cmdnode->cmdwaitqwoken = 0;
+ lbtf_queue_cmd(priv, cmdnode);
+ queue_work(lbtf_wq, &priv->cmd_work);
+
+ return cmdnode;
+}
+
+void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size)
+{
+ __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
+}
+
+int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbtf_private *,
+ unsigned long, struct cmd_header *),
+ unsigned long callback_arg)
+{
+ struct cmd_ctrl_node *cmdnode;
+ unsigned long flags;
+ int ret = 0;
+
+ cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
+ callback, callback_arg);
+ if (IS_ERR(cmdnode))
+ return PTR_ERR(cmdnode);
+
+ might_sleep();
+ ret = wait_event_interruptible(cmdnode->cmdwait_q,
+ cmdnode->cmdwaitqwoken);
+ if (ret) {
+ printk(KERN_DEBUG
+ "libertastf: command 0x%04x interrupted by signal",
+ command);
+ return ret;
+ }
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ ret = cmdnode->result;
+ if (ret)
+ printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n",
+ command, ret);
+
+ __lbtf_cleanup_and_insert_cmd(priv, cmdnode);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__lbtf_cmd);
+
+/* Call holding driver_lock */
+void lbtf_cmd_response_rx(struct lbtf_private *priv)
+{
+ priv->cmd_response_rxed = 1;
+ queue_work(lbtf_wq, &priv->cmd_work);
+}
+EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx);
+
+int lbtf_process_rx_command(struct lbtf_private *priv)
+{
+ uint16_t respcmd, curcmd;
+ struct cmd_header *resp;
+ int ret = 0;
+ unsigned long flags;
+ uint16_t result;
+
+ mutex_lock(&priv->lock);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (!priv->cur_cmd) {
+ ret = -1;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ goto done;
+ }
+
+ resp = (void *)priv->cmd_resp_buff;
+ curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
+ respcmd = le16_to_cpu(resp->command);
+ result = le16_to_cpu(resp->result);
+
+ if (net_ratelimit())
+ printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n",
+ respcmd, le16_to_cpu(resp->seqnum),
+ le16_to_cpu(resp->size));
+
+ if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ ret = -1;
+ goto done;
+ }
+ if (respcmd != CMD_RET(curcmd)) {
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ ret = -1;
+ goto done;
+ }
+
+ if (resp->result == cpu_to_le16(0x0004)) {
+ /* 0x0004 means -EAGAIN. Drop the response, let it time out
+ and be resubmitted */
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ ret = -1;
+ goto done;
+ }
+
+ /* Now we got response from FW, cancel the command timer */
+ del_timer(&priv->command_timer);
+ priv->cmd_timed_out = 0;
+ if (priv->nr_retries)
+ priv->nr_retries = 0;
+
+ /* If the command is not successful, cleanup and return failure */
+ if ((result != 0 || !(respcmd & 0x8000))) {
+ /*
+ * Handling errors here
+ */
+ switch (respcmd) {
+ case CMD_RET(CMD_GET_HW_SPEC):
+ case CMD_RET(CMD_802_11_RESET):
+ printk(KERN_DEBUG "libertastf: reset failed\n");
+ break;
+
+ }
+ lbtf_complete_command(priv, priv->cur_cmd, result);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ ret = -1;
+ goto done;
+ }
+
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ if (priv->cur_cmd && priv->cur_cmd->callback) {
+ ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
+ resp);
+ }
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (priv->cur_cmd) {
+ /* Clean up and Put current command back to cmdfreeq */
+ lbtf_complete_command(priv, priv->cur_cmd, result);
+ }
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+done:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
new file mode 100644
index 00000000000..1cc03a8dd67
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright (C) 2008, cozybit Inc.
+ * Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#define DRV_NAME "lbtf_usb"
+
+#include "libertas_tf.h"
+#include "if_usb.h"
+
+#define MESSAGE_HEADER_LEN 4
+
+static char *lbtf_fw_name = "lbtf_usb.bin";
+module_param_named(fw_name, lbtf_fw_name, charp, 0644);
+
+static struct usb_device_id if_usb_table[] = {
+ /* Enter the device signature inside */
+ { USB_DEVICE(0x1286, 0x2001) },
+ { USB_DEVICE(0x05a3, 0x8388) },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, if_usb_table);
+
+static void if_usb_receive(struct urb *urb);
+static void if_usb_receive_fwload(struct urb *urb);
+static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
+ uint8_t *payload, uint16_t nb);
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+ uint16_t nb, u8 data);
+static void if_usb_free(struct if_usb_card *cardp);
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct if_usb_card *cardp);
+
+/**
+ * if_usb_wrike_bulk_callback - call back to handle URB status
+ *
+ * @param urb pointer to urb structure
+ */
+static void if_usb_write_bulk_callback(struct urb *urb)
+{
+ if (urb->status != 0)
+ printk(KERN_INFO "libertastf: URB in failure status: %d\n",
+ urb->status);
+}
+
+/**
+ * if_usb_free - free tx/rx urb, skb and rx buffer
+ *
+ * @param cardp pointer if_usb_card
+ */
+static void if_usb_free(struct if_usb_card *cardp)
+{
+ /* Unlink tx & rx urb */
+ usb_kill_urb(cardp->tx_urb);
+ usb_kill_urb(cardp->rx_urb);
+ usb_kill_urb(cardp->cmd_urb);
+
+ usb_free_urb(cardp->tx_urb);
+ cardp->tx_urb = NULL;
+
+ usb_free_urb(cardp->rx_urb);
+ cardp->rx_urb = NULL;
+
+ usb_free_urb(cardp->cmd_urb);
+ cardp->cmd_urb = NULL;
+
+ kfree(cardp->ep_out_buf);
+ cardp->ep_out_buf = NULL;
+}
+
+static void if_usb_setup_firmware(struct lbtf_private *priv)
+{
+ struct if_usb_card *cardp = priv->card;
+ struct cmd_ds_set_boot2_ver b2_cmd;
+
+ if_usb_submit_rx_urb(cardp);
+ b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
+ b2_cmd.action = 0;
+ b2_cmd.version = cardp->boot2_version;
+
+ if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
+ printk(KERN_INFO "libertastf: setting boot2 version failed\n");
+}
+
+static void if_usb_fw_timeo(unsigned long priv)
+{
+ struct if_usb_card *cardp = (void *)priv;
+
+ if (!cardp->fwdnldover)
+ /* Download timed out */
+ cardp->priv->surpriseremoved = 1;
+ wake_up(&cardp->fw_wq);
+}
+
+/**
+ * if_usb_probe - sets the configuration values
+ *
+ * @ifnum interface number
+ * @id pointer to usb_device_id
+ *
+ * Returns: 0 on success, error code on failure
+ */
+static int if_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ struct lbtf_private *priv;
+ struct if_usb_card *cardp;
+ int i;
+
+ udev = interface_to_usbdev(intf);
+
+ cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
+ if (!cardp)
+ goto error;
+
+ setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
+ init_waitqueue_head(&cardp->fw_wq);
+
+ cardp->udev = udev;
+ iface_desc = intf->cur_altsetting;
+
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if (usb_endpoint_is_bulk_in(endpoint)) {
+ cardp->ep_in_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ cardp->ep_in = usb_endpoint_num(endpoint);
+ } else if (usb_endpoint_is_bulk_out(endpoint)) {
+ cardp->ep_out_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ cardp->ep_out = usb_endpoint_num(endpoint);
+ }
+ }
+ if (!cardp->ep_out_size || !cardp->ep_in_size)
+ /* Endpoints not found */
+ goto dealloc;
+
+ cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!cardp->rx_urb)
+ goto dealloc;
+
+ cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!cardp->tx_urb)
+ goto dealloc;
+
+ cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!cardp->cmd_urb)
+ goto dealloc;
+
+ cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!cardp->ep_out_buf)
+ goto dealloc;
+
+ priv = lbtf_add_card(cardp, &udev->dev);
+ if (!priv)
+ goto dealloc;
+
+ cardp->priv = priv;
+
+ priv->hw_host_to_card = if_usb_host_to_card;
+ priv->hw_prog_firmware = if_usb_prog_firmware;
+ priv->hw_reset_device = if_usb_reset_device;
+ cardp->boot2_version = udev->descriptor.bcdDevice;
+
+ usb_get_dev(udev);
+ usb_set_intfdata(intf, cardp);
+
+ return 0;
+
+dealloc:
+ if_usb_free(cardp);
+error:
+ return -ENOMEM;
+}
+
+/**
+ * if_usb_disconnect - free resource and cleanup
+ *
+ * @intf USB interface structure
+ */
+static void if_usb_disconnect(struct usb_interface *intf)
+{
+ struct if_usb_card *cardp = usb_get_intfdata(intf);
+ struct lbtf_private *priv = (struct lbtf_private *) cardp->priv;
+
+ if_usb_reset_device(cardp);
+
+ if (priv)
+ lbtf_remove_card(priv);
+
+ /* Unlink and free urb */
+ if_usb_free(cardp);
+
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(interface_to_usbdev(intf));
+}
+
+/**
+ * if_usb_send_fw_pkt - This function downloads the FW
+ *
+ * @priv pointer to struct lbtf_private
+ *
+ * Returns: 0
+ */
+static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
+{
+ struct fwdata *fwdata = cardp->ep_out_buf;
+ u8 *firmware = (u8 *) cardp->fw->data;
+
+ /* If we got a CRC failure on the last block, back
+ up and retry it */
+ if (!cardp->CRC_OK) {
+ cardp->totalbytes = cardp->fwlastblksent;
+ cardp->fwseqnum--;
+ }
+
+ /* struct fwdata (which we sent to the card) has an
+ extra __le32 field in between the header and the data,
+ which is not in the struct fwheader in the actual
+ firmware binary. Insert the seqnum in the middle... */
+ memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
+ sizeof(struct fwheader));
+
+ cardp->fwlastblksent = cardp->totalbytes;
+ cardp->totalbytes += sizeof(struct fwheader);
+
+ memcpy(fwdata->data, &firmware[cardp->totalbytes],
+ le32_to_cpu(fwdata->hdr.datalength));
+
+ fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
+ cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
+
+ usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
+ le32_to_cpu(fwdata->hdr.datalength), 0);
+
+ if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK))
+ /* Host has finished FW downloading
+ * Donwloading FW JUMP BLOCK
+ */
+ cardp->fwfinalblk = 1;
+
+ return 0;
+}
+
+static int if_usb_reset_device(struct if_usb_card *cardp)
+{
+ struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
+ int ret;
+
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
+
+ cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
+ cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset));
+ cmd->hdr.result = cpu_to_le16(0);
+ cmd->hdr.seqnum = cpu_to_le16(0x5a5a);
+ cmd->action = cpu_to_le16(CMD_ACT_HALT);
+ usb_tx_block(cardp, cardp->ep_out_buf,
+ 4 + sizeof(struct cmd_ds_802_11_reset), 0);
+
+ msleep(100);
+ ret = usb_reset_device(cardp->udev);
+ msleep(100);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(if_usb_reset_device);
+
+/**
+ * usb_tx_block - transfer data to the device
+ *
+ * @priv pointer to struct lbtf_private
+ * @payload pointer to payload data
+ * @nb data length
+ * @data non-zero for data, zero for commands
+ *
+ * Returns: 0 on success, nonzero otherwise.
+ */
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+ uint16_t nb, u8 data)
+{
+ struct urb *urb;
+
+ /* check if device is removed */
+ if (cardp->priv->surpriseremoved)
+ return -1;
+
+ if (data)
+ urb = cardp->tx_urb;
+ else
+ urb = cardp->cmd_urb;
+
+ usb_fill_bulk_urb(urb, cardp->udev,
+ usb_sndbulkpipe(cardp->udev,
+ cardp->ep_out),
+ payload, nb, if_usb_write_bulk_callback, cardp);
+
+ urb->transfer_flags |= URB_ZERO_PACKET;
+
+ if (usb_submit_urb(urb, GFP_ATOMIC))
+ return -1;
+ return 0;
+}
+
+static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
+ void (*callbackfn)(struct urb *urb))
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+ if (!skb)
+ return -1;
+
+ cardp->rx_skb = skb;
+
+ /* Fill the receive configuration URB and initialise the Rx call back */
+ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
+ usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
+ (void *) (skb->tail),
+ MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
+
+ cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+ if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) {
+ kfree_skb(skb);
+ cardp->rx_skb = NULL;
+ return -1;
+ } else
+ return 0;
+}
+
+static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
+{
+ return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
+}
+
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
+{
+ return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
+}
+
+static void if_usb_receive_fwload(struct urb *urb)
+{
+ struct if_usb_card *cardp = urb->context;
+ struct sk_buff *skb = cardp->rx_skb;
+ struct fwsyncheader *syncfwheader;
+ struct bootcmdresp bcmdresp;
+
+ if (urb->status) {
+ kfree_skb(skb);
+ return;
+ }
+
+ if (cardp->fwdnldover) {
+ __le32 *tmp = (__le32 *)(skb->data);
+
+ if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
+ tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY))
+ /* Firmware ready event received */
+ wake_up(&cardp->fw_wq);
+ else
+ if_usb_submit_rx_urb_fwload(cardp);
+ kfree_skb(skb);
+ return;
+ }
+ if (cardp->bootcmdresp <= 0) {
+ memcpy(&bcmdresp, skb->data, sizeof(bcmdresp));
+
+ if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
+ kfree_skb(skb);
+ if_usb_submit_rx_urb_fwload(cardp);
+ cardp->bootcmdresp = 1;
+ /* Received valid boot command response */
+ return;
+ }
+ if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
+ if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
+ bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
+ bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION))
+ cardp->bootcmdresp = -1;
+ } else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB &&
+ bcmdresp.result == BOOT_CMD_RESP_OK)
+ cardp->bootcmdresp = 1;
+
+ kfree_skb(skb);
+ if_usb_submit_rx_urb_fwload(cardp);
+ return;
+ }
+
+ syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
+ if (!syncfwheader) {
+ kfree_skb(skb);
+ return;
+ }
+
+ memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader));
+
+ if (!syncfwheader->cmd)
+ cardp->CRC_OK = 1;
+ else
+ cardp->CRC_OK = 0;
+ kfree_skb(skb);
+
+ /* reschedule timer for 200ms hence */
+ mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
+
+ if (cardp->fwfinalblk) {
+ cardp->fwdnldover = 1;
+ goto exit;
+ }
+
+ if_usb_send_fw_pkt(cardp);
+
+ exit:
+ if_usb_submit_rx_urb_fwload(cardp);
+
+ kfree(syncfwheader);
+
+ return;
+}
+
+#define MRVDRV_MIN_PKT_LEN 30
+
+static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
+ struct if_usb_card *cardp,
+ struct lbtf_private *priv)
+{
+ if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
+ || recvlength < MRVDRV_MIN_PKT_LEN) {
+ kfree_skb(skb);
+ return;
+ }
+
+ skb_put(skb, recvlength);
+ skb_pull(skb, MESSAGE_HEADER_LEN);
+ lbtf_rx(priv, skb);
+}
+
+static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+ struct sk_buff *skb,
+ struct if_usb_card *cardp,
+ struct lbtf_private *priv)
+{
+ if (recvlength > LBS_CMD_BUFFER_SIZE) {
+ kfree_skb(skb);
+ return;
+ }
+
+ if (!in_interrupt())
+ BUG();
+
+ spin_lock(&priv->driver_lock);
+ memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
+ recvlength - MESSAGE_HEADER_LEN);
+ kfree_skb(skb);
+ lbtf_cmd_response_rx(priv);
+ spin_unlock(&priv->driver_lock);
+}
+
+/**
+ * if_usb_receive - read data received from the device.
+ *
+ * @urb pointer to struct urb
+ */
+static void if_usb_receive(struct urb *urb)
+{
+ struct if_usb_card *cardp = urb->context;
+ struct sk_buff *skb = cardp->rx_skb;
+ struct lbtf_private *priv = cardp->priv;
+ int recvlength = urb->actual_length;
+ uint8_t *recvbuff = NULL;
+ uint32_t recvtype = 0;
+ __le32 *pkt = (__le32 *) skb->data;
+
+ if (recvlength) {
+ if (urb->status) {
+ kfree_skb(skb);
+ goto setup_for_next;
+ }
+
+ recvbuff = skb->data;
+ recvtype = le32_to_cpu(pkt[0]);
+ } else if (urb->status) {
+ kfree_skb(skb);
+ return;
+ }
+
+ switch (recvtype) {
+ case CMD_TYPE_DATA:
+ process_cmdtypedata(recvlength, skb, cardp, priv);
+ break;
+
+ case CMD_TYPE_REQUEST:
+ process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
+ break;
+
+ case CMD_TYPE_INDICATION:
+ {
+ /* Event cause handling */
+ u32 event_cause = le32_to_cpu(pkt[1]);
+
+ /* Icky undocumented magic special case */
+ if (event_cause & 0xffff0000) {
+ u16 tmp;
+ u8 retrycnt;
+ u8 failure;
+
+ tmp = event_cause >> 16;
+ retrycnt = tmp & 0x00ff;
+ failure = (tmp & 0xff00) >> 8;
+ lbtf_send_tx_feedback(priv, retrycnt, failure);
+ } else if (event_cause == LBTF_EVENT_BCN_SENT)
+ lbtf_bcn_sent(priv);
+ else
+ printk(KERN_DEBUG
+ "Unsupported notification %d received\n",
+ event_cause);
+ kfree_skb(skb);
+ break;
+ }
+ default:
+ printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n",
+ recvtype);
+ kfree_skb(skb);
+ break;
+ }
+
+setup_for_next:
+ if_usb_submit_rx_urb(cardp);
+}
+
+/**
+ * if_usb_host_to_card - Download data to the device
+ *
+ * @priv pointer to struct lbtf_private structure
+ * @type type of data
+ * @buf pointer to data buffer
+ * @len number of bytes
+ *
+ * Returns: 0 on success, nonzero otherwise
+ */
+static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
+ uint8_t *payload, uint16_t nb)
+{
+ struct if_usb_card *cardp = priv->card;
+ u8 data = 0;
+
+ if (type == MVMS_CMD) {
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
+ } else {
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
+ data = 1;
+ }
+
+ memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
+
+ return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN,
+ data);
+}
+
+/**
+ * if_usb_issue_boot_command - Issue boot command to Boot2.
+ *
+ * @ivalue 1 boots from FW by USB-Download, 2 boots from FW in EEPROM.
+ *
+ * Returns: 0
+ */
+static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
+{
+ struct bootcmd *bootcmd = cardp->ep_out_buf;
+
+ /* Prepare command */
+ bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
+ bootcmd->cmd = ivalue;
+ memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
+
+ /* Issue command */
+ usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd), 0);
+
+ return 0;
+}
+
+
+/**
+ * check_fwfile_format - Check the validity of Boot2/FW image.
+ *
+ * @data pointer to image
+ * @totlen image length
+ *
+ * Returns: 0 if the image is valid, nonzero otherwise.
+ */
+static int check_fwfile_format(const u8 *data, u32 totlen)
+{
+ u32 bincmd, exit;
+ u32 blksize, offset, len;
+ int ret;
+
+ ret = 1;
+ exit = len = 0;
+
+ do {
+ struct fwheader *fwh = (void *) data;
+
+ bincmd = le32_to_cpu(fwh->dnldcmd);
+ blksize = le32_to_cpu(fwh->datalength);
+ switch (bincmd) {
+ case FW_HAS_DATA_TO_RECV:
+ offset = sizeof(struct fwheader) + blksize;
+ data += offset;
+ len += offset;
+ if (len >= totlen)
+ exit = 1;
+ break;
+ case FW_HAS_LAST_BLOCK:
+ exit = 1;
+ ret = 0;
+ break;
+ default:
+ exit = 1;
+ break;
+ }
+ } while (!exit);
+
+ if (ret)
+ printk(KERN_INFO
+ "libertastf: firmware file format check failed\n");
+ return ret;
+}
+
+
+static int if_usb_prog_firmware(struct if_usb_card *cardp)
+{
+ int i = 0;
+ static int reset_count = 10;
+ int ret = 0;
+
+ ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
+ if (ret < 0) {
+ printk(KERN_INFO "libertastf: firmware %s not found\n",
+ lbtf_fw_name);
+ goto done;
+ }
+
+ if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
+ goto release_fw;
+
+restart:
+ if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
+ ret = -1;
+ goto release_fw;
+ }
+
+ cardp->bootcmdresp = 0;
+ do {
+ int j = 0;
+ i++;
+ /* Issue Boot command = 1, Boot from Download-FW */
+ if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
+ /* wait for command response */
+ do {
+ j++;
+ msleep_interruptible(100);
+ } while (cardp->bootcmdresp == 0 && j < 10);
+ } while (cardp->bootcmdresp == 0 && i < 5);
+
+ if (cardp->bootcmdresp <= 0) {
+ if (--reset_count >= 0) {
+ if_usb_reset_device(cardp);
+ goto restart;
+ }
+ return -1;
+ }
+
+ i = 0;
+
+ cardp->totalbytes = 0;
+ cardp->fwlastblksent = 0;
+ cardp->CRC_OK = 1;
+ cardp->fwdnldover = 0;
+ cardp->fwseqnum = -1;
+ cardp->totalbytes = 0;
+ cardp->fwfinalblk = 0;
+
+ /* Send the first firmware packet... */
+ if_usb_send_fw_pkt(cardp);
+
+ /* ... and wait for the process to complete */
+ wait_event_interruptible(cardp->fw_wq, cardp->priv->surpriseremoved ||
+ cardp->fwdnldover);
+
+ del_timer_sync(&cardp->fw_timeout);
+ usb_kill_urb(cardp->rx_urb);
+
+ if (!cardp->fwdnldover) {
+ printk(KERN_INFO "libertastf: failed to load fw,"
+ " resetting device!\n");
+ if (--reset_count >= 0) {
+ if_usb_reset_device(cardp);
+ goto restart;
+ }
+
+ printk(KERN_INFO "libertastf: fw download failure\n");
+ ret = -1;
+ goto release_fw;
+ }
+
+ cardp->priv->fw_ready = 1;
+
+ release_fw:
+ release_firmware(cardp->fw);
+ cardp->fw = NULL;
+
+ if_usb_setup_firmware(cardp->priv);
+
+ done:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(if_usb_prog_firmware);
+
+
+#define if_usb_suspend NULL
+#define if_usb_resume NULL
+
+static struct usb_driver if_usb_driver = {
+ .name = DRV_NAME,
+ .probe = if_usb_probe,
+ .disconnect = if_usb_disconnect,
+ .id_table = if_usb_table,
+ .suspend = if_usb_suspend,
+ .resume = if_usb_resume,
+};
+
+static int __init if_usb_init_module(void)
+{
+ int ret = 0;
+
+ ret = usb_register(&if_usb_driver);
+ return ret;
+}
+
+static void __exit if_usb_exit_module(void)
+{
+ usb_deregister(&if_usb_driver);
+}
+
+module_init(if_usb_init_module);
+module_exit(if_usb_exit_module);
+
+MODULE_DESCRIPTION("8388 USB WLAN Thinfirm Driver");
+MODULE_AUTHOR("Cozybit Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas_tf/if_usb.h b/drivers/net/wireless/libertas_tf/if_usb.h
new file mode 100644
index 00000000000..6fa5b3f59ef
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/if_usb.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008, cozybit Inc.
+ * Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+struct lbtf_private;
+
+/**
+ * This file contains definition for USB interface.
+ */
+#define CMD_TYPE_REQUEST 0xF00DFACE
+#define CMD_TYPE_DATA 0xBEADC0DE
+#define CMD_TYPE_INDICATION 0xBEEFFACE
+
+#define BOOT_CMD_FW_BY_USB 0x01
+#define BOOT_CMD_FW_IN_EEPROM 0x02
+#define BOOT_CMD_UPDATE_BOOT2 0x03
+#define BOOT_CMD_UPDATE_FW 0x04
+#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */
+
+struct bootcmd {
+ __le32 magic;
+ uint8_t cmd;
+ uint8_t pad[11];
+};
+
+#define BOOT_CMD_RESP_OK 0x0001
+#define BOOT_CMD_RESP_FAIL 0x0000
+
+struct bootcmdresp {
+ __le32 magic;
+ uint8_t cmd;
+ uint8_t result;
+ uint8_t pad[2];
+};
+
+/** USB card description structure*/
+struct if_usb_card {
+ struct usb_device *udev;
+ struct urb *rx_urb, *tx_urb, *cmd_urb;
+ struct lbtf_private *priv;
+
+ struct sk_buff *rx_skb;
+
+ uint8_t ep_in;
+ uint8_t ep_out;
+
+ int8_t bootcmdresp;
+
+ int ep_in_size;
+
+ void *ep_out_buf;
+ int ep_out_size;
+
+ const struct firmware *fw;
+ struct timer_list fw_timeout;
+ wait_queue_head_t fw_wq;
+ uint32_t fwseqnum;
+ uint32_t totalbytes;
+ uint32_t fwlastblksent;
+ uint8_t CRC_OK;
+ uint8_t fwdnldover;
+ uint8_t fwfinalblk;
+
+ __le16 boot2_version;
+};
+
+/** fwheader */
+struct fwheader {
+ __le32 dnldcmd;
+ __le32 baseaddr;
+ __le32 datalength;
+ __le32 CRC;
+};
+
+#define FW_MAX_DATA_BLK_SIZE 600
+/** FWData */
+struct fwdata {
+ struct fwheader hdr;
+ __le32 seqnum;
+ uint8_t data[0];
+};
+
+/** fwsyncheader */
+struct fwsyncheader {
+ __le32 cmd;
+ __le32 seqnum;
+};
+
+#define FW_HAS_DATA_TO_RECV 0x00000001
+#define FW_HAS_LAST_BLOCK 0x00000004
diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h
new file mode 100644
index 00000000000..8995cd7c29b
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/libertas_tf.h
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2008, cozybit Inc.
+ * Copyright (C) 2007, Red Hat, Inc.
+ * Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/kthread.h>
+#include <net/mac80211.h>
+
+#ifndef DRV_NAME
+#define DRV_NAME "libertas_tf"
+#endif
+
+#define MRVL_DEFAULT_RETRIES 9
+#define MRVL_PER_PACKET_RATE 0x10
+#define MRVL_MAX_BCN_SIZE 440
+#define CMD_OPTION_WAITFORRSP 0x0002
+
+/* Return command are almost always the same as the host command, but with
+ * bit 15 set high. There are a few exceptions, though...
+ */
+#define CMD_RET(cmd) (0x8000 | cmd)
+
+/* Command codes */
+#define CMD_GET_HW_SPEC 0x0003
+#define CMD_802_11_RESET 0x0005
+#define CMD_MAC_MULTICAST_ADR 0x0010
+#define CMD_802_11_RADIO_CONTROL 0x001c
+#define CMD_802_11_RF_CHANNEL 0x001d
+#define CMD_802_11_RF_TX_POWER 0x001e
+#define CMD_MAC_CONTROL 0x0028
+#define CMD_802_11_MAC_ADDRESS 0x004d
+#define CMD_SET_BOOT2_VER 0x00a5
+#define CMD_802_11_BEACON_CTRL 0x00b0
+#define CMD_802_11_BEACON_SET 0x00cb
+#define CMD_802_11_SET_MODE 0x00cc
+#define CMD_802_11_SET_BSSID 0x00cd
+
+#define CMD_ACT_GET 0x0000
+#define CMD_ACT_SET 0x0001
+
+/* Define action or option for CMD_802_11_RESET */
+#define CMD_ACT_HALT 0x0003
+
+/* Define action or option for CMD_MAC_CONTROL */
+#define CMD_ACT_MAC_RX_ON 0x0001
+#define CMD_ACT_MAC_TX_ON 0x0002
+#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
+#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
+#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
+#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
+
+/* Define action or option for CMD_802_11_RADIO_CONTROL */
+#define CMD_TYPE_AUTO_PREAMBLE 0x0001
+#define CMD_TYPE_SHORT_PREAMBLE 0x0002
+#define CMD_TYPE_LONG_PREAMBLE 0x0003
+
+#define TURN_ON_RF 0x01
+#define RADIO_ON 0x01
+#define RADIO_OFF 0x00
+
+#define SET_AUTO_PREAMBLE 0x05
+#define SET_SHORT_PREAMBLE 0x03
+#define SET_LONG_PREAMBLE 0x01
+
+/* Define action or option for CMD_802_11_RF_CHANNEL */
+#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
+#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
+
+/* Codes for CMD_802_11_SET_MODE */
+enum lbtf_mode {
+ LBTF_PASSIVE_MODE,
+ LBTF_STA_MODE,
+ LBTF_AP_MODE,
+};
+
+/** Card Event definition */
+#define MACREG_INT_CODE_FIRMWARE_READY 48
+/** Buffer Constants */
+
+/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
+* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
+* driver has more local TxPDs. Each TxPD on the host memory is associated
+* with a Tx control node. The driver maintains 8 RxPD descriptors for
+* station firmware to store Rx packet information.
+*
+* Current version of MAC has a 32x6 multicast address buffer.
+*
+* 802.11b can have up to 14 channels, the driver keeps the
+* BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
+*/
+
+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
+#define LBS_NUM_CMD_BUFFERS 10
+#define LBS_CMD_BUFFER_SIZE (2 * 1024)
+#define MRVDRV_MAX_CHANNEL_SIZE 14
+#define MRVDRV_SNAP_HEADER_LEN 8
+
+#define LBS_UPLD_SIZE 2312
+#define DEV_NAME_LEN 32
+
+/** Misc constants */
+/* This section defines 802.11 specific contants */
+
+#define MRVDRV_MAX_REGION_CODE 6
+/**
+ * the table to keep region code
+ */
+#define LBTF_REGDOMAIN_US 0x10
+#define LBTF_REGDOMAIN_CA 0x20
+#define LBTF_REGDOMAIN_EU 0x30
+#define LBTF_REGDOMAIN_SP 0x31
+#define LBTF_REGDOMAIN_FR 0x32
+#define LBTF_REGDOMAIN_JP 0x40
+
+#define SBI_EVENT_CAUSE_SHIFT 3
+
+/** RxPD status */
+
+#define MRVDRV_RXPD_STATUS_OK 0x0001
+
+
+/* This is for firmware specific length */
+#define EXTRA_LEN 36
+
+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
+ (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
+
+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
+ (ETH_FRAME_LEN + sizeof(struct rxpd) \
+ + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
+
+#define CMD_F_HOSTCMD (1 << 0)
+#define FW_CAPINFO_WPA (1 << 0)
+
+#define RF_ANTENNA_1 0x1
+#define RF_ANTENNA_2 0x2
+#define RF_ANTENNA_AUTO 0xFFFF
+
+#define LBTF_EVENT_BCN_SENT 55
+
+/** Global Variable Declaration */
+/** mv_ms_type */
+enum mv_ms_type {
+ MVMS_DAT = 0,
+ MVMS_CMD = 1,
+ MVMS_TXDONE = 2,
+ MVMS_EVENT
+};
+
+extern struct workqueue_struct *lbtf_wq;
+
+struct lbtf_private;
+
+struct lbtf_offset_value {
+ u32 offset;
+ u32 value;
+};
+
+struct channel_range {
+ u8 regdomain;
+ u8 start;
+ u8 end; /* exclusive (channel must be less than end) */
+};
+
+struct if_usb_card;
+
+/** Private structure for the MV device */
+struct lbtf_private {
+ void *card;
+ struct ieee80211_hw *hw;
+
+ /* Command response buffer */
+ u8 cmd_resp_buff[LBS_UPLD_SIZE];
+ /* Download sent:
+ bit0 1/0=data_sent/data_tx_done,
+ bit1 1/0=cmd_sent/cmd_tx_done,
+ all other bits reserved 0 */
+ struct ieee80211_vif *vif;
+
+ struct work_struct cmd_work;
+ struct work_struct tx_work;
+ /** Hardware access */
+ int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb);
+ int (*hw_prog_firmware) (struct if_usb_card *cardp);
+ int (*hw_reset_device) (struct if_usb_card *cardp);
+
+
+ /** Wlan adapter data structure*/
+ /** STATUS variables */
+ u32 fwrelease;
+ u32 fwcapinfo;
+ /* protected with big lock */
+
+ struct mutex lock;
+
+ /** command-related variables */
+ u16 seqnum;
+ /* protected by big lock */
+
+ struct cmd_ctrl_node *cmd_array;
+ /** Current command */
+ struct cmd_ctrl_node *cur_cmd;
+ /** command Queues */
+ /** Free command buffers */
+ struct list_head cmdfreeq;
+ /** Pending command buffers */
+ struct list_head cmdpendingq;
+
+ /** spin locks */
+ spinlock_t driver_lock;
+
+ /** Timers */
+ struct timer_list command_timer;
+ int nr_retries;
+ int cmd_timed_out;
+
+ u8 cmd_response_rxed;
+
+ /** capability Info used in Association, start, join */
+ u16 capability;
+
+ /** MAC address information */
+ u8 current_addr[ETH_ALEN];
+ u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+ u32 nr_of_multicastmacaddr;
+ int cur_freq;
+
+ struct sk_buff *skb_to_tx;
+ struct sk_buff *tx_skb;
+
+ /** NIC Operation characteristics */
+ u16 mac_control;
+ u16 regioncode;
+ struct channel_range range;
+
+ u8 radioon;
+ u32 preamble;
+
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_supported_band band;
+ struct lbtf_offset_value offsetvalue;
+
+ u8 fw_ready;
+ u8 surpriseremoved;
+ struct sk_buff_head bc_ps_buf;
+};
+
+/* 802.11-related definitions */
+
+/* TxPD descriptor */
+struct txpd {
+ /* Current Tx packet status */
+ __le32 tx_status;
+ /* Tx control */
+ __le32 tx_control;
+ __le32 tx_packet_location;
+ /* Tx packet length */
+ __le16 tx_packet_length;
+ /* First 2 byte of destination MAC address */
+ u8 tx_dest_addr_high[2];
+ /* Last 4 byte of destination MAC address */
+ u8 tx_dest_addr_low[4];
+ /* Pkt Priority */
+ u8 priority;
+ /* Pkt Trasnit Power control */
+ u8 powermgmt;
+ /* Time the packet has been queued in the driver (units = 2ms) */
+ u8 pktdelay_2ms;
+ /* reserved */
+ u8 reserved1;
+};
+
+/* RxPD Descriptor */
+struct rxpd {
+ /* Current Rx packet status */
+ __le16 status;
+
+ /* SNR */
+ u8 snr;
+
+ /* Tx control */
+ u8 rx_control;
+
+ /* Pkt length */
+ __le16 pkt_len;
+
+ /* Noise Floor */
+ u8 nf;
+
+ /* Rx Packet Rate */
+ u8 rx_rate;
+
+ /* Pkt addr */
+ __le32 pkt_ptr;
+
+ /* Next Rx RxPD addr */
+ __le32 next_rxpd_ptr;
+
+ /* Pkt Priority */
+ u8 priority;
+ u8 reserved[3];
+};
+
+struct cmd_header {
+ __le16 command;
+ __le16 size;
+ __le16 seqnum;
+ __le16 result;
+} __attribute__ ((packed));
+
+struct cmd_ctrl_node {
+ struct list_head list;
+ int result;
+ /* command response */
+ int (*callback)(struct lbtf_private *,
+ unsigned long, struct cmd_header *);
+ unsigned long callback_arg;
+ /* command data */
+ struct cmd_header *cmdbuf;
+ /* wait queue */
+ u16 cmdwaitqwoken;
+ wait_queue_head_t cmdwait_q;
+};
+
+/*
+ * Define data structure for CMD_GET_HW_SPEC
+ * This structure defines the response for the GET_HW_SPEC command
+ */
+struct cmd_ds_get_hw_spec {
+ struct cmd_header hdr;
+
+ /* HW Interface version number */
+ __le16 hwifversion;
+ /* HW version number */
+ __le16 version;
+ /* Max number of TxPD FW can handle */
+ __le16 nr_txpd;
+ /* Max no of Multicast address */
+ __le16 nr_mcast_adr;
+ /* MAC address */
+ u8 permanentaddr[6];
+
+ /* region Code */
+ __le16 regioncode;
+
+ /* Number of antenna used */
+ __le16 nr_antenna;
+
+ /* FW release number, example 0x01030304 = 2.3.4p1 */
+ __le32 fwrelease;
+
+ /* Base Address of TxPD queue */
+ __le32 wcb_base;
+ /* Read Pointer of RxPd queue */
+ __le32 rxpd_rdptr;
+
+ /* Write Pointer of RxPd queue */
+ __le32 rxpd_wrptr;
+
+ /*FW/HW capability */
+ __le32 fwcapinfo;
+} __attribute__ ((packed));
+
+struct cmd_ds_mac_control {
+ struct cmd_header hdr;
+ __le16 action;
+ u16 reserved;
+};
+
+struct cmd_ds_802_11_mac_address {
+ struct cmd_header hdr;
+
+ __le16 action;
+ uint8_t macadd[ETH_ALEN];
+};
+
+struct cmd_ds_mac_multicast_addr {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 nr_of_adrs;
+ u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
+};
+
+struct cmd_ds_set_mode {
+ struct cmd_header hdr;
+
+ __le16 mode;
+};
+
+struct cmd_ds_set_bssid {
+ struct cmd_header hdr;
+
+ u8 bssid[6];
+ u8 activate;
+};
+
+struct cmd_ds_802_11_radio_control {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 control;
+};
+
+
+struct cmd_ds_802_11_rf_channel {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 channel;
+ __le16 rftype; /* unused */
+ __le16 reserved; /* unused */
+ u8 channellist[32]; /* unused */
+};
+
+struct cmd_ds_set_boot2_ver {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 version;
+};
+
+struct cmd_ds_802_11_reset {
+ struct cmd_header hdr;
+
+ __le16 action;
+};
+
+struct cmd_ds_802_11_beacon_control {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 beacon_enable;
+ __le16 beacon_period;
+};
+
+struct cmd_ds_802_11_beacon_set {
+ struct cmd_header hdr;
+
+ __le16 len;
+ u8 beacon[MRVL_MAX_BCN_SIZE];
+};
+
+struct lbtf_private;
+struct cmd_ctrl_node;
+
+/** Function Prototype Declaration */
+void lbtf_set_mac_control(struct lbtf_private *priv);
+
+int lbtf_free_cmd_buffer(struct lbtf_private *priv);
+
+int lbtf_allocate_cmd_buffer(struct lbtf_private *priv);
+int lbtf_execute_next_command(struct lbtf_private *priv);
+int lbtf_set_radio_control(struct lbtf_private *priv);
+int lbtf_update_hw_spec(struct lbtf_private *priv);
+int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv);
+void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode);
+void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid);
+int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr);
+
+int lbtf_set_channel(struct lbtf_private *priv, u8 channel);
+
+int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon);
+int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
+ int beacon_int);
+
+
+int lbtf_process_rx_command(struct lbtf_private *priv);
+void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd,
+ int result);
+void lbtf_cmd_response_rx(struct lbtf_private *priv);
+
+/* main.c */
+struct chan_freq_power *lbtf_get_region_cfp_table(u8 region,
+ int *cfp_no);
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev);
+int lbtf_remove_card(struct lbtf_private *priv);
+int lbtf_start_card(struct lbtf_private *priv);
+int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb);
+void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail);
+void lbtf_bcn_sent(struct lbtf_private *priv);
+
+/* support functions for cmd.c */
+/* lbtf_cmd() infers the size of the buffer to copy data back into, from
+ the size of the target of the pointer. Since the command to be sent
+ may often be smaller, that size is set in cmd->size by the caller.*/
+#define lbtf_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
+ uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
+ (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
+ __lbtf_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
+})
+
+#define lbtf_cmd_with_response(priv, cmdnr, cmd) \
+ lbtf_cmd(priv, cmdnr, cmd, lbtf_cmd_copyback, (unsigned long) (cmd))
+
+void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size);
+
+int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbtf_private *, unsigned long,
+ struct cmd_header *),
+ unsigned long callback_arg);
+
+int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra,
+ struct cmd_header *resp);
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
new file mode 100644
index 00000000000..feff945ad85
--- /dev/null
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2008, cozybit Inc.
+ * Copyright (C) 2003-2006, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#include "libertas_tf.h"
+#include "linux/etherdevice.h"
+
+#define DRIVER_RELEASE_VERSION "004.p0"
+/* thinfirm version: 5.132.X.pX */
+#define LBTF_FW_VER_MIN 0x05840300
+#define LBTF_FW_VER_MAX 0x0584ffff
+#define QOS_CONTROL_LEN 2
+
+static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION;
+struct workqueue_struct *lbtf_wq;
+
+static const struct ieee80211_channel lbtf_channels[] = {
+ { .center_freq = 2412, .hw_value = 1 },
+ { .center_freq = 2417, .hw_value = 2 },
+ { .center_freq = 2422, .hw_value = 3 },
+ { .center_freq = 2427, .hw_value = 4 },
+ { .center_freq = 2432, .hw_value = 5 },
+ { .center_freq = 2437, .hw_value = 6 },
+ { .center_freq = 2442, .hw_value = 7 },
+ { .center_freq = 2447, .hw_value = 8 },
+ { .center_freq = 2452, .hw_value = 9 },
+ { .center_freq = 2457, .hw_value = 10 },
+ { .center_freq = 2462, .hw_value = 11 },
+ { .center_freq = 2467, .hw_value = 12 },
+ { .center_freq = 2472, .hw_value = 13 },
+ { .center_freq = 2484, .hw_value = 14 },
+};
+
+/* This table contains the hardware specific values for the modulation rates. */
+static const struct ieee80211_rate lbtf_rates[] = {
+ { .bitrate = 10,
+ .hw_value = 0, },
+ { .bitrate = 20,
+ .hw_value = 1,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55,
+ .hw_value = 2,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110,
+ .hw_value = 3,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 60,
+ .hw_value = 5,
+ .flags = 0 },
+ { .bitrate = 90,
+ .hw_value = 6,
+ .flags = 0 },
+ { .bitrate = 120,
+ .hw_value = 7,
+ .flags = 0 },
+ { .bitrate = 180,
+ .hw_value = 8,
+ .flags = 0 },
+ { .bitrate = 240,
+ .hw_value = 9,
+ .flags = 0 },
+ { .bitrate = 360,
+ .hw_value = 10,
+ .flags = 0 },
+ { .bitrate = 480,
+ .hw_value = 11,
+ .flags = 0 },
+ { .bitrate = 540,
+ .hw_value = 12,
+ .flags = 0 },
+};
+
+static void lbtf_cmd_work(struct work_struct *work)
+{
+ struct lbtf_private *priv = container_of(work, struct lbtf_private,
+ cmd_work);
+ spin_lock_irq(&priv->driver_lock);
+ /* command response? */
+ if (priv->cmd_response_rxed) {
+ priv->cmd_response_rxed = 0;
+ spin_unlock_irq(&priv->driver_lock);
+ lbtf_process_rx_command(priv);
+ spin_lock_irq(&priv->driver_lock);
+ }
+
+ if (priv->cmd_timed_out && priv->cur_cmd) {
+ struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
+
+ if (++priv->nr_retries > 10) {
+ lbtf_complete_command(priv, cmdnode,
+ -ETIMEDOUT);
+ priv->nr_retries = 0;
+ } else {
+ priv->cur_cmd = NULL;
+
+ /* Stick it back at the _top_ of the pending
+ * queue for immediate resubmission */
+ list_add(&cmdnode->list, &priv->cmdpendingq);
+ }
+ }
+ priv->cmd_timed_out = 0;
+ spin_unlock_irq(&priv->driver_lock);
+
+ if (!priv->fw_ready)
+ return;
+ /* Execute the next command */
+ if (!priv->cur_cmd)
+ lbtf_execute_next_command(priv);
+}
+
+/**
+ * lbtf_setup_firmware: initialize firmware.
+ *
+ * @priv A pointer to struct lbtf_private structure
+ *
+ * Returns: 0 on success.
+ */
+static int lbtf_setup_firmware(struct lbtf_private *priv)
+{
+ int ret = -1;
+
+ /*
+ * Read priv address from HW
+ */
+ memset(priv->current_addr, 0xff, ETH_ALEN);
+ ret = lbtf_update_hw_spec(priv);
+ if (ret) {
+ ret = -1;
+ goto done;
+ }
+
+ lbtf_set_mac_control(priv);
+ lbtf_set_radio_control(priv);
+
+ ret = 0;
+done:
+ return ret;
+}
+
+/**
+ * This function handles the timeout of command sending.
+ * It will re-send the same command again.
+ */
+static void command_timer_fn(unsigned long data)
+{
+ struct lbtf_private *priv = (struct lbtf_private *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (!priv->cur_cmd) {
+ printk(KERN_DEBUG "libertastf: command timer expired; "
+ "no pending command\n");
+ goto out;
+ }
+
+ printk(KERN_DEBUG "libertas: command %x timed out\n",
+ le16_to_cpu(priv->cur_cmd->cmdbuf->command));
+
+ priv->cmd_timed_out = 1;
+ queue_work(lbtf_wq, &priv->cmd_work);
+out:
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+}
+
+static int lbtf_init_adapter(struct lbtf_private *priv)
+{
+ memset(priv->current_addr, 0xff, ETH_ALEN);
+ mutex_init(&priv->lock);
+
+ priv->vif = NULL;
+ setup_timer(&priv->command_timer, command_timer_fn,
+ (unsigned long)priv);
+
+ INIT_LIST_HEAD(&priv->cmdfreeq);
+ INIT_LIST_HEAD(&priv->cmdpendingq);
+
+ spin_lock_init(&priv->driver_lock);
+
+ /* Allocate the command buffers */
+ if (lbtf_allocate_cmd_buffer(priv))
+ return -1;
+
+ return 0;
+}
+
+static void lbtf_free_adapter(struct lbtf_private *priv)
+{
+ lbtf_free_cmd_buffer(priv);
+ del_timer(&priv->command_timer);
+}
+
+static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct lbtf_private *priv = hw->priv;
+
+ priv->skb_to_tx = skb;
+ queue_work(lbtf_wq, &priv->tx_work);
+ /*
+ * queue will be restarted when we receive transmission feedback if
+ * there are no buffered multicast frames to send
+ */
+ ieee80211_stop_queues(priv->hw);
+ return 0;
+}
+
+static void lbtf_tx_work(struct work_struct *work)
+{
+ struct lbtf_private *priv = container_of(work, struct lbtf_private,
+ tx_work);
+ unsigned int len;
+ struct ieee80211_tx_info *info;
+ struct txpd *txpd;
+ struct sk_buff *skb = NULL;
+ int err;
+
+ if ((priv->vif->type == NL80211_IFTYPE_AP) &&
+ (!skb_queue_empty(&priv->bc_ps_buf)))
+ skb = skb_dequeue(&priv->bc_ps_buf);
+ else if (priv->skb_to_tx) {
+ skb = priv->skb_to_tx;
+ priv->skb_to_tx = NULL;
+ } else
+ return;
+
+ len = skb->len;
+ info = IEEE80211_SKB_CB(skb);
+ txpd = (struct txpd *) skb_push(skb, sizeof(struct txpd));
+
+ if (priv->surpriseremoved) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ memset(txpd, 0, sizeof(struct txpd));
+ /* Activate per-packet rate selection */
+ txpd->tx_control |= cpu_to_le32(MRVL_PER_PACKET_RATE |
+ ieee80211_get_tx_rate(priv->hw, info)->hw_value);
+
+ /* copy destination address from 802.11 header */
+ memcpy(txpd->tx_dest_addr_high, skb->data + sizeof(struct txpd) + 4,
+ ETH_ALEN);
+ txpd->tx_packet_length = cpu_to_le16(len);
+ txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
+ BUG_ON(priv->tx_skb);
+ spin_lock_irq(&priv->driver_lock);
+ priv->tx_skb = skb;
+ err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
+ spin_unlock_irq(&priv->driver_lock);
+ if (err) {
+ dev_kfree_skb_any(skb);
+ priv->tx_skb = NULL;
+ }
+}
+
+static int lbtf_op_start(struct ieee80211_hw *hw)
+{
+ struct lbtf_private *priv = hw->priv;
+ void *card = priv->card;
+ int ret = -1;
+
+ if (!priv->fw_ready)
+ /* Upload firmware */
+ if (priv->hw_prog_firmware(card))
+ goto err_prog_firmware;
+
+ /* poke the firmware */
+ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+ priv->radioon = RADIO_ON;
+ priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
+ ret = lbtf_setup_firmware(priv);
+ if (ret)
+ goto err_prog_firmware;
+
+ if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
+ (priv->fwrelease > LBTF_FW_VER_MAX)) {
+ ret = -1;
+ goto err_prog_firmware;
+ }
+
+ printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
+ return 0;
+
+err_prog_firmware:
+ priv->hw_reset_device(card);
+ return ret;
+}
+
+static void lbtf_op_stop(struct ieee80211_hw *hw)
+{
+ struct lbtf_private *priv = hw->priv;
+ unsigned long flags;
+ struct sk_buff *skb;
+
+ struct cmd_ctrl_node *cmdnode;
+ /* Flush pending command nodes */
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
+ cmdnode->result = -ENOENT;
+ cmdnode->cmdwaitqwoken = 1;
+ wake_up_interruptible(&cmdnode->cmdwait_q);
+ }
+
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ cancel_work_sync(&priv->cmd_work);
+ cancel_work_sync(&priv->tx_work);
+ while ((skb = skb_dequeue(&priv->bc_ps_buf)))
+ dev_kfree_skb_any(skb);
+ priv->radioon = RADIO_OFF;
+ lbtf_set_radio_control(priv);
+
+ return;
+}
+
+static int lbtf_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct lbtf_private *priv = hw->priv;
+ if (priv->vif != NULL)
+ return -EOPNOTSUPP;
+
+ priv->vif = conf->vif;
+ switch (conf->type) {
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_AP:
+ lbtf_set_mode(priv, LBTF_AP_MODE);
+ break;
+ case NL80211_IFTYPE_STATION:
+ lbtf_set_mode(priv, LBTF_STA_MODE);
+ break;
+ default:
+ priv->vif = NULL;
+ return -EOPNOTSUPP;
+ }
+ lbtf_set_mac_address(priv, (u8 *) conf->mac_addr);
+ return 0;
+}
+
+static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct lbtf_private *priv = hw->priv;
+
+ if (priv->vif->type == NL80211_IFTYPE_AP ||
+ priv->vif->type == NL80211_IFTYPE_MESH_POINT)
+ lbtf_beacon_ctrl(priv, 0, 0);
+ lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
+ lbtf_set_bssid(priv, 0, NULL);
+ priv->vif = NULL;
+}
+
+static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+{
+ struct lbtf_private *priv = hw->priv;
+ if (conf->channel->center_freq != priv->cur_freq) {
+ priv->cur_freq = conf->channel->center_freq;
+ lbtf_set_channel(priv, conf->channel->hw_value);
+ }
+ return 0;
+}
+
+static int lbtf_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ struct lbtf_private *priv = hw->priv;
+ struct sk_buff *beacon;
+
+ switch (priv->vif->type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ beacon = ieee80211_beacon_get(hw, vif);
+ if (beacon) {
+ lbtf_beacon_set(priv, beacon);
+ kfree_skb(beacon);
+ lbtf_beacon_ctrl(priv, 1, hw->conf.beacon_int);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (conf->bssid) {
+ u8 null_bssid[ETH_ALEN] = {0};
+ bool activate = compare_ether_addr(conf->bssid, null_bssid);
+ lbtf_set_bssid(priv, activate, conf->bssid);
+ }
+
+ return 0;
+}
+
+#define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
+static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ struct lbtf_private *priv = hw->priv;
+ int old_mac_control = priv->mac_control;
+ int i;
+ changed_flags &= SUPPORTED_FIF_FLAGS;
+ *new_flags &= SUPPORTED_FIF_FLAGS;
+
+ if (!changed_flags)
+ return;
+
+ if (*new_flags & (FIF_PROMISC_IN_BSS))
+ priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+ else
+ priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+ if (*new_flags & (FIF_ALLMULTI) ||
+ mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+ priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+ priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
+ } else if (mc_count) {
+ priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
+ priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+ priv->nr_of_multicastmacaddr = mc_count;
+ for (i = 0; i < mc_count; i++) {
+ if (!mclist)
+ break;
+ memcpy(&priv->multicastlist[i], mclist->da_addr,
+ ETH_ALEN);
+ mclist = mclist->next;
+ }
+ lbtf_cmd_set_mac_multicast_addr(priv);
+ } else {
+ priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
+ CMD_ACT_MAC_ALL_MULTICAST_ENABLE);
+ if (priv->nr_of_multicastmacaddr) {
+ priv->nr_of_multicastmacaddr = 0;
+ lbtf_cmd_set_mac_multicast_addr(priv);
+ }
+ }
+
+
+ if (priv->mac_control != old_mac_control)
+ lbtf_set_mac_control(priv);
+}
+
+static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
+{
+ struct lbtf_private *priv = hw->priv;
+
+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+ if (bss_conf->use_short_preamble)
+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+ else
+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+ lbtf_set_radio_control(priv);
+ }
+
+ return;
+}
+
+static const struct ieee80211_ops lbtf_ops = {
+ .tx = lbtf_op_tx,
+ .start = lbtf_op_start,
+ .stop = lbtf_op_stop,
+ .add_interface = lbtf_op_add_interface,
+ .remove_interface = lbtf_op_remove_interface,
+ .config = lbtf_op_config,
+ .config_interface = lbtf_op_config_interface,
+ .configure_filter = lbtf_op_configure_filter,
+ .bss_info_changed = lbtf_op_bss_info_changed,
+};
+
+int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
+{
+ struct ieee80211_rx_status stats;
+ struct rxpd *prxpd;
+ int need_padding;
+ unsigned int flags;
+ struct ieee80211_hdr *hdr;
+
+ prxpd = (struct rxpd *) skb->data;
+
+ stats.flag = 0;
+ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
+ stats.flag |= RX_FLAG_FAILED_FCS_CRC;
+ stats.freq = priv->cur_freq;
+ stats.band = IEEE80211_BAND_2GHZ;
+ stats.signal = prxpd->snr;
+ stats.noise = prxpd->nf;
+ stats.qual = prxpd->snr - prxpd->nf;
+ /* Marvell rate index has a hole at value 4 */
+ if (prxpd->rx_rate > 4)
+ --prxpd->rx_rate;
+ stats.rate_idx = prxpd->rx_rate;
+ skb_pull(skb, sizeof(struct rxpd));
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
+
+ need_padding = ieee80211_is_data_qos(hdr->frame_control);
+ need_padding ^= ieee80211_has_a4(hdr->frame_control);
+ need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
+ (*ieee80211_get_qos_ctl(hdr) &
+ IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+
+ if (need_padding) {
+ memmove(skb->data + 2, skb->data, skb->len);
+ skb_reserve(skb, 2);
+ }
+
+ ieee80211_rx_irqsafe(priv->hw, skb, &stats);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_rx);
+
+/**
+ * lbtf_add_card: Add and initialize the card, no fw upload yet.
+ *
+ * @card A pointer to card
+ *
+ * Returns: pointer to struct lbtf_priv.
+ */
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
+{
+ struct ieee80211_hw *hw;
+ struct lbtf_private *priv = NULL;
+
+ hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
+ if (!hw)
+ goto done;
+
+ priv = hw->priv;
+ if (lbtf_init_adapter(priv))
+ goto err_init_adapter;
+
+ priv->hw = hw;
+ priv->card = card;
+ priv->tx_skb = NULL;
+
+ hw->queues = 1;
+ hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ hw->extra_tx_headroom = sizeof(struct txpd);
+ memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
+ memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
+ priv->band.n_bitrates = ARRAY_SIZE(lbtf_rates);
+ priv->band.bitrates = priv->rates;
+ priv->band.n_channels = ARRAY_SIZE(lbtf_channels);
+ priv->band.channels = priv->channels;
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+ skb_queue_head_init(&priv->bc_ps_buf);
+
+ SET_IEEE80211_DEV(hw, dmdev);
+
+ INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
+ INIT_WORK(&priv->tx_work, lbtf_tx_work);
+ if (ieee80211_register_hw(hw))
+ goto err_init_adapter;
+
+ goto done;
+
+err_init_adapter:
+ lbtf_free_adapter(priv);
+ ieee80211_free_hw(hw);
+ priv = NULL;
+
+done:
+ return priv;
+}
+EXPORT_SYMBOL_GPL(lbtf_add_card);
+
+
+int lbtf_remove_card(struct lbtf_private *priv)
+{
+ struct ieee80211_hw *hw = priv->hw;
+
+ priv->surpriseremoved = 1;
+ del_timer(&priv->command_timer);
+ lbtf_free_adapter(priv);
+ priv->hw = NULL;
+ ieee80211_unregister_hw(hw);
+ ieee80211_free_hw(hw);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbtf_remove_card);
+
+void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
+ memset(&info->status, 0, sizeof(info->status));
+ /*
+ * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
+ * default pid rc algorithm.
+ *
+ * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
+ */
+ info->status.excessive_retries = fail ? 1 : 0;
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ skb_pull(priv->tx_skb, sizeof(struct txpd));
+ ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb);
+ priv->tx_skb = NULL;
+ if (!priv->skb_to_tx && skb_queue_empty(&priv->bc_ps_buf))
+ ieee80211_wake_queues(priv->hw);
+ else
+ queue_work(lbtf_wq, &priv->tx_work);
+}
+EXPORT_SYMBOL_GPL(lbtf_send_tx_feedback);
+
+void lbtf_bcn_sent(struct lbtf_private *priv)
+{
+ struct sk_buff *skb = NULL;
+
+ if (priv->vif->type != NL80211_IFTYPE_AP)
+ return;
+
+ if (skb_queue_empty(&priv->bc_ps_buf)) {
+ bool tx_buff_bc = 0;
+
+ while ((skb = ieee80211_get_buffered_bc(priv->hw, priv->vif))) {
+ skb_queue_tail(&priv->bc_ps_buf, skb);
+ tx_buff_bc = 1;
+ }
+ if (tx_buff_bc) {
+ ieee80211_stop_queues(priv->hw);
+ queue_work(lbtf_wq, &priv->tx_work);
+ }
+ }
+
+ skb = ieee80211_beacon_get(priv->hw, priv->vif);
+
+ if (skb) {
+ lbtf_beacon_set(priv, skb);
+ kfree_skb(skb);
+ }
+}
+EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
+
+static int __init lbtf_init_module(void)
+{
+ lbtf_wq = create_workqueue("libertastf");
+ if (lbtf_wq == NULL) {
+ printk(KERN_ERR "libertastf: couldn't create workqueue\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void __exit lbtf_exit_module(void)
+{
+ destroy_workqueue(lbtf_wq);
+}
+
+module_init(lbtf_init_module);
+module_exit(lbtf_exit_module);
+
+MODULE_DESCRIPTION("Libertas WLAN Thinfirm Driver Library");
+MODULE_AUTHOR("Cozybit Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 248d31a7aa3..1a019e98dac 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -14,6 +14,8 @@
* - RX filtering based on filter configuration (data->rx_filter)
*/
+#include <linux/list.h>
+#include <linux/spinlock.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <linux/if_arp.h>
@@ -28,11 +30,56 @@ static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
+struct hwsim_vif_priv {
+ u32 magic;
+};
+
+#define HWSIM_VIF_MAGIC 0x69537748
+
+static inline void hwsim_check_magic(struct ieee80211_vif *vif)
+{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+ WARN_ON(vp->magic != HWSIM_VIF_MAGIC);
+}
+
+static inline void hwsim_set_magic(struct ieee80211_vif *vif)
+{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+ vp->magic = HWSIM_VIF_MAGIC;
+}
+
+static inline void hwsim_clear_magic(struct ieee80211_vif *vif)
+{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+ vp->magic = 0;
+}
+
+struct hwsim_sta_priv {
+ u32 magic;
+};
+
+#define HWSIM_STA_MAGIC 0x6d537748
+
+static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
+{
+ struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
+ WARN_ON(sp->magic != HWSIM_VIF_MAGIC);
+}
+
+static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta)
+{
+ struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
+ sp->magic = HWSIM_VIF_MAGIC;
+}
+
+static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
+{
+ struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
+ sp->magic = 0;
+}
static struct class *hwsim_class;
-static struct ieee80211_hw **hwsim_radios;
-static int hwsim_radio_count;
static struct net_device *hwsim_mon; /* global monitor netdev */
@@ -68,7 +115,12 @@ static const struct ieee80211_rate hwsim_rates[] = {
{ .bitrate = 540 }
};
+static spinlock_t hwsim_radio_lock;
+static struct list_head hwsim_radios;
+
struct mac80211_hwsim_data {
+ struct list_head list;
+ struct ieee80211_hw *hw;
struct device *dev;
struct ieee80211_supported_band band;
struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)];
@@ -144,11 +196,11 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
}
-static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
{
- struct mac80211_hwsim_data *data = hw->priv;
- int i, ack = 0;
+ struct mac80211_hwsim_data *data = hw->priv, *data2;
+ bool ack = false;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rx_status rx_status;
@@ -161,13 +213,13 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
/* TODO: simulate signal strength (and optional packet drop) */
/* Copy skb to all enabled radios that are on the current frequency */
- for (i = 0; i < hwsim_radio_count; i++) {
- struct mac80211_hwsim_data *data2;
+ spin_lock(&hwsim_radio_lock);
+ list_for_each_entry(data2, &hwsim_radios, list) {
struct sk_buff *nskb;
- if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw)
+ if (data == data2)
continue;
- data2 = hwsim_radios[i]->priv;
+
if (!data2->started || !data2->radio_enabled ||
data->channel->center_freq != data2->channel->center_freq)
continue;
@@ -176,11 +228,12 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (nskb == NULL)
continue;
- if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr,
+ if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
ETH_ALEN) == 0)
- ack = 1;
- ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status);
+ ack = true;
+ ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
}
+ spin_unlock(&hwsim_radio_lock);
return ack;
}
@@ -189,7 +242,7 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv;
- int ack;
+ bool ack;
struct ieee80211_tx_info *txi;
mac80211_hwsim_monitor_rx(hw, skb);
@@ -210,6 +263,12 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ack = mac80211_hwsim_tx_frame(hw, skb);
txi = IEEE80211_SKB_CB(skb);
+
+ if (txi->control.vif)
+ hwsim_check_magic(txi->control.vif);
+ if (txi->control.sta)
+ hwsim_check_sta_magic(txi->control.sta);
+
memset(&txi->status, 0, sizeof(txi->status));
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (ack)
@@ -246,6 +305,7 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
print_mac(mac, conf->mac_addr));
+ hwsim_set_magic(conf->vif);
return 0;
}
@@ -257,6 +317,8 @@ static void mac80211_hwsim_remove_interface(
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
print_mac(mac, conf->mac_addr));
+ hwsim_check_magic(conf->vif);
+ hwsim_clear_magic(conf->vif);
}
@@ -267,7 +329,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct sk_buff *skb;
struct ieee80211_tx_info *info;
- if (vif->type != IEEE80211_IF_TYPE_AP)
+ hwsim_check_magic(vif);
+
+ if (vif->type != NL80211_IFTYPE_AP)
return;
skb = ieee80211_beacon_get(hw, vif);
@@ -341,7 +405,45 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
*total_flags = data->rx_filter;
}
+static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ hwsim_check_magic(vif);
+ return 0;
+}
+
+static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ hwsim_check_magic(vif);
+}
+
+static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
+{
+ hwsim_check_magic(vif);
+ switch (cmd) {
+ case STA_NOTIFY_ADD:
+ hwsim_set_sta_magic(sta);
+ break;
+ case STA_NOTIFY_REMOVE:
+ hwsim_clear_sta_magic(sta);
+ break;
+ }
+}
+static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ bool set)
+{
+ hwsim_check_sta_magic(sta);
+ return 0;
+}
static const struct ieee80211_ops mac80211_hwsim_ops =
{
@@ -352,23 +454,30 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
.remove_interface = mac80211_hwsim_remove_interface,
.config = mac80211_hwsim_config,
.configure_filter = mac80211_hwsim_configure_filter,
+ .config_interface = mac80211_hwsim_config_interface,
+ .bss_info_changed = mac80211_hwsim_bss_info_changed,
+ .sta_notify = mac80211_hwsim_sta_notify,
+ .set_tim = mac80211_hwsim_set_tim,
};
static void mac80211_hwsim_free(void)
{
- int i;
-
- for (i = 0; i < hwsim_radio_count; i++) {
- if (hwsim_radios[i]) {
- struct mac80211_hwsim_data *data;
- data = hwsim_radios[i]->priv;
- ieee80211_unregister_hw(hwsim_radios[i]);
- device_unregister(data->dev);
- ieee80211_free_hw(hwsim_radios[i]);
- }
+ struct list_head tmplist, *i, *tmp;
+ struct mac80211_hwsim_data *data;
+
+ INIT_LIST_HEAD(&tmplist);
+
+ spin_lock_bh(&hwsim_radio_lock);
+ list_for_each_safe(i, tmp, &hwsim_radios)
+ list_move(i, &tmplist);
+ spin_unlock_bh(&hwsim_radio_lock);
+
+ list_for_each_entry(data, &tmplist, list) {
+ ieee80211_unregister_hw(data->hw);
+ device_unregister(data->dev);
+ ieee80211_free_hw(data->hw);
}
- kfree(hwsim_radios);
class_destroy(hwsim_class);
}
@@ -398,42 +507,37 @@ static int __init init_mac80211_hwsim(void)
struct ieee80211_hw *hw;
DECLARE_MAC_BUF(mac);
- if (radios < 1 || radios > 65535)
+ if (radios < 1 || radios > 100)
return -EINVAL;
- hwsim_radio_count = radios;
- hwsim_radios = kcalloc(hwsim_radio_count,
- sizeof(struct ieee80211_hw *), GFP_KERNEL);
- if (hwsim_radios == NULL)
- return -ENOMEM;
+ spin_lock_init(&hwsim_radio_lock);
+ INIT_LIST_HEAD(&hwsim_radios);
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
- if (IS_ERR(hwsim_class)) {
- kfree(hwsim_radios);
+ if (IS_ERR(hwsim_class))
return PTR_ERR(hwsim_class);
- }
memset(addr, 0, ETH_ALEN);
addr[0] = 0x02;
- for (i = 0; i < hwsim_radio_count; i++) {
+ for (i = 0; i < radios; i++) {
printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
i);
hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
- if (hw == NULL) {
+ if (!hw) {
printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
"failed\n");
err = -ENOMEM;
goto failed;
}
- hwsim_radios[i] = hw;
-
data = hw->priv;
- data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
- "hwsim%d", i);
+ data->hw = hw;
+
+ data->dev = device_create(hwsim_class, NULL, 0, hw,
+ "hwsim%d", i);
if (IS_ERR(data->dev)) {
printk(KERN_DEBUG
- "mac80211_hwsim: device_create_drvdata "
+ "mac80211_hwsim: device_create "
"failed (%ld)\n", PTR_ERR(data->dev));
err = -ENOMEM;
goto failed_drvdata;
@@ -446,7 +550,15 @@ static int __init init_mac80211_hwsim(void)
SET_IEEE80211_PERM_ADDR(hw, addr);
hw->channel_change_time = 1;
- hw->queues = 1;
+ hw->queues = 4;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP);
+ hw->ampdu_queues = 1;
+
+ /* ask mac80211 to reserve space for magic */
+ hw->vif_data_size = sizeof(struct hwsim_vif_priv);
+ hw->sta_data_size = sizeof(struct hwsim_sta_priv);
memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
@@ -454,6 +566,19 @@ static int __init init_mac80211_hwsim(void)
data->band.n_channels = ARRAY_SIZE(hwsim_channels);
data->band.bitrates = data->rates;
data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
+ data->band.ht_info.ht_supported = 1;
+ data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
+ IEEE80211_HT_CAP_GRN_FLD |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_DSSSCCK40;
+ data->band.ht_info.ampdu_factor = 0x3;
+ data->band.ht_info.ampdu_density = 0x6;
+ memset(data->band.ht_info.supp_mcs_set, 0,
+ sizeof(data->band.ht_info.supp_mcs_set));
+ data->band.ht_info.supp_mcs_set[0] = 0xff;
+ data->band.ht_info.supp_mcs_set[1] = 0xff;
+ data->band.ht_info.supp_mcs_set[12] =
+ IEEE80211_HT_CAP_MCS_TX_DEFINED;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
err = ieee80211_register_hw(hw);
@@ -469,6 +594,8 @@ static int __init init_mac80211_hwsim(void)
setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
(unsigned long) hw);
+
+ list_add_tail(&data->list, &hwsim_radios);
}
hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
@@ -500,7 +627,6 @@ failed_hw:
device_unregister(data->dev);
failed_drvdata:
ieee80211_free_hw(hw);
- hwsim_radios[i] = NULL;
failed:
mac80211_hwsim_free();
return err;
@@ -509,8 +635,7 @@ failed:
static void __exit exit_mac80211_hwsim(void)
{
- printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n",
- hwsim_radio_count);
+ printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
unregister_netdev(hwsim_mon);
mac80211_hwsim_free();
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index f479c1af678..a670f36b5f3 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -398,7 +398,7 @@ static int netwave_probe(struct pcmcia_device *link)
link->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &netwave_interrupt;
@@ -749,9 +749,10 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {
for (i = j = 0x0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
+ if (i == 0)
+ break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 1ebcafe7ca5..50904771f29 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -79,15 +79,21 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/firmware.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+
#include "hermes_rid.h"
+#include "hermes_dld.h"
#include "orinoco.h"
/********************************************************************/
@@ -241,6 +247,74 @@ static int __orinoco_program_rids(struct net_device *dev);
static void __orinoco_set_multicast_list(struct net_device *dev);
/********************************************************************/
+/* Michael MIC crypto setup */
+/********************************************************************/
+#define MICHAEL_MIC_LEN 8
+static int orinoco_mic_init(struct orinoco_private *priv)
+{
+ priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
+ if (IS_ERR(priv->tx_tfm_mic)) {
+ printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
+ "crypto API michael_mic\n");
+ priv->tx_tfm_mic = NULL;
+ return -ENOMEM;
+ }
+
+ priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
+ if (IS_ERR(priv->rx_tfm_mic)) {
+ printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
+ "crypto API michael_mic\n");
+ priv->rx_tfm_mic = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void orinoco_mic_free(struct orinoco_private *priv)
+{
+ if (priv->tx_tfm_mic)
+ crypto_free_hash(priv->tx_tfm_mic);
+ if (priv->rx_tfm_mic)
+ crypto_free_hash(priv->rx_tfm_mic);
+}
+
+static int michael_mic(struct crypto_hash *tfm_michael, u8 *key,
+ u8 *da, u8 *sa, u8 priority,
+ u8 *data, size_t data_len, u8 *mic)
+{
+ struct hash_desc desc;
+ struct scatterlist sg[2];
+ u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
+
+ if (tfm_michael == NULL) {
+ printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
+ return -1;
+ }
+
+ /* Copy header into buffer. We need the padding on the end zeroed */
+ memcpy(&hdr[0], da, ETH_ALEN);
+ memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
+ hdr[ETH_ALEN*2] = priority;
+ hdr[ETH_ALEN*2+1] = 0;
+ hdr[ETH_ALEN*2+2] = 0;
+ hdr[ETH_ALEN*2+3] = 0;
+
+ /* Use scatter gather to MIC header and data in one go */
+ sg_init_table(sg, 2);
+ sg_set_buf(&sg[0], hdr, sizeof(hdr));
+ sg_set_buf(&sg[1], data, data_len);
+
+ if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))
+ return -1;
+
+ desc.tfm = tfm_michael;
+ desc.flags = 0;
+ return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),
+ mic);
+}
+
+/********************************************************************/
/* Internal helper functions */
/********************************************************************/
@@ -273,12 +347,19 @@ static inline void set_port_type(struct orinoco_private *priv)
#define ORINOCO_MAX_BSS_COUNT 64
static int orinoco_bss_data_allocate(struct orinoco_private *priv)
{
- if (priv->bss_data)
+ if (priv->bss_xbss_data)
return 0;
- priv->bss_data =
- kzalloc(ORINOCO_MAX_BSS_COUNT * sizeof(bss_element), GFP_KERNEL);
- if (!priv->bss_data) {
+ if (priv->has_ext_scan)
+ priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
+ sizeof(struct xbss_element),
+ GFP_KERNEL);
+ else
+ priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
+ sizeof(struct bss_element),
+ GFP_KERNEL);
+
+ if (!priv->bss_xbss_data) {
printk(KERN_WARNING "Out of memory allocating beacons");
return -ENOMEM;
}
@@ -287,18 +368,319 @@ static int orinoco_bss_data_allocate(struct orinoco_private *priv)
static void orinoco_bss_data_free(struct orinoco_private *priv)
{
- kfree(priv->bss_data);
- priv->bss_data = NULL;
+ kfree(priv->bss_xbss_data);
+ priv->bss_xbss_data = NULL;
}
+#define PRIV_BSS ((struct bss_element *)priv->bss_xbss_data)
+#define PRIV_XBSS ((struct xbss_element *)priv->bss_xbss_data)
static void orinoco_bss_data_init(struct orinoco_private *priv)
{
int i;
INIT_LIST_HEAD(&priv->bss_free_list);
INIT_LIST_HEAD(&priv->bss_list);
- for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
- list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list);
+ if (priv->has_ext_scan)
+ for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
+ list_add_tail(&(PRIV_XBSS[i].list),
+ &priv->bss_free_list);
+ else
+ for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
+ list_add_tail(&(PRIV_BSS[i].list),
+ &priv->bss_free_list);
+
+}
+
+static inline u8 *orinoco_get_ie(u8 *data, size_t len,
+ enum ieee80211_mfie eid)
+{
+ u8 *p = data;
+ while ((p + 2) < (data + len)) {
+ if (p[0] == eid)
+ return p;
+ p += p[1] + 2;
+ }
+ return NULL;
+}
+
+#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
+#define WPA_SELECTOR_LEN 4
+static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
+{
+ u8 *p = data;
+ while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
+ if ((p[0] == MFIE_TYPE_GENERIC) &&
+ (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
+ return p;
+ p += p[1] + 2;
+ }
+ return NULL;
+}
+
+
+/********************************************************************/
+/* Download functionality */
+/********************************************************************/
+
+struct fw_info {
+ char *pri_fw;
+ char *sta_fw;
+ char *ap_fw;
+ u32 pda_addr;
+ u16 pda_size;
+};
+
+const static struct fw_info orinoco_fw[] = {
+ { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
+ { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
+ { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 0x100 }
+};
+
+/* Structure used to access fields in FW
+ * Make sure LE decoding macros are used
+ */
+struct orinoco_fw_header {
+ char hdr_vers[6]; /* ASCII string for header version */
+ __le16 headersize; /* Total length of header */
+ __le32 entry_point; /* NIC entry point */
+ __le32 blocks; /* Number of blocks to program */
+ __le32 block_offset; /* Offset of block data from eof header */
+ __le32 pdr_offset; /* Offset to PDR data from eof header */
+ __le32 pri_offset; /* Offset to primary plug data */
+ __le32 compat_offset; /* Offset to compatibility data*/
+ char signature[0]; /* FW signature length headersize-20 */
+} __attribute__ ((packed));
+
+/* Download either STA or AP firmware into the card. */
+static int
+orinoco_dl_firmware(struct orinoco_private *priv,
+ const struct fw_info *fw,
+ int ap)
+{
+ /* Plug Data Area (PDA) */
+ __le16 pda[512] = { 0 };
+
+ hermes_t *hw = &priv->hw;
+ const struct firmware *fw_entry;
+ const struct orinoco_fw_header *hdr;
+ const unsigned char *first_block;
+ const unsigned char *end;
+ const char *firmware;
+ struct net_device *dev = priv->ndev;
+ int err;
+
+ if (ap)
+ firmware = fw->ap_fw;
+ else
+ firmware = fw->sta_fw;
+
+ printk(KERN_DEBUG "%s: Attempting to download firmware %s\n",
+ dev->name, firmware);
+
+ /* Read current plug data */
+ err = hermes_read_pda(hw, pda, fw->pda_addr,
+ min_t(u16, fw->pda_size, sizeof(pda)), 0);
+ printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
+ if (err)
+ return err;
+
+ err = request_firmware(&fw_entry, firmware, priv->dev);
+ if (err) {
+ printk(KERN_ERR "%s: Cannot find firmware %s\n",
+ dev->name, firmware);
+ return -ENOENT;
+ }
+
+ hdr = (const struct orinoco_fw_header *) fw_entry->data;
+
+ /* Enable aux port to allow programming */
+ err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
+ printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err);
+ if (err != 0)
+ goto abort;
+
+ /* Program data */
+ first_block = (fw_entry->data +
+ le16_to_cpu(hdr->headersize) +
+ le32_to_cpu(hdr->block_offset));
+ end = fw_entry->data + fw_entry->size;
+
+ err = hermes_program(hw, first_block, end);
+ printk(KERN_DEBUG "%s: Program returned %d\n", dev->name, err);
+ if (err != 0)
+ goto abort;
+
+ /* Update production data */
+ first_block = (fw_entry->data +
+ le16_to_cpu(hdr->headersize) +
+ le32_to_cpu(hdr->pdr_offset));
+
+ err = hermes_apply_pda_with_defaults(hw, first_block, pda);
+ printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err);
+ if (err)
+ goto abort;
+
+ /* Tell card we've finished */
+ err = hermesi_program_end(hw);
+ printk(KERN_DEBUG "%s: Program end returned %d\n", dev->name, err);
+ if (err != 0)
+ goto abort;
+
+ /* Check if we're running */
+ printk(KERN_DEBUG "%s: hermes_present returned %d\n",
+ dev->name, hermes_present(hw));
+
+abort:
+ release_firmware(fw_entry);
+ return err;
+}
+
+/* End markers */
+#define TEXT_END 0x1A /* End of text header */
+
+/*
+ * Process a firmware image - stop the card, load the firmware, reset
+ * the card and make sure it responds. For the secondary firmware take
+ * care of the PDA - read it and then write it on top of the firmware.
+ */
+static int
+symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
+ const unsigned char *image, const unsigned char *end,
+ int secondary)
+{
+ hermes_t *hw = &priv->hw;
+ int ret;
+ const unsigned char *ptr;
+ const unsigned char *first_block;
+
+ /* Plug Data Area (PDA) */
+ __le16 pda[256];
+
+ /* Binary block begins after the 0x1A marker */
+ ptr = image;
+ while (*ptr++ != TEXT_END);
+ first_block = ptr;
+
+ /* Read the PDA from EEPROM */
+ if (secondary) {
+ ret = hermes_read_pda(hw, pda, fw->pda_addr, sizeof(pda), 1);
+ if (ret)
+ return ret;
+ }
+
+ /* Stop the firmware, so that it can be safely rewritten */
+ if (priv->stop_fw) {
+ ret = priv->stop_fw(priv, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* Program the adapter with new firmware */
+ ret = hermes_program(hw, first_block, end);
+ if (ret)
+ return ret;
+
+ /* Write the PDA to the adapter */
+ if (secondary) {
+ size_t len = hermes_blocks_length(first_block);
+ ptr = first_block + len;
+ ret = hermes_apply_pda(hw, ptr, pda);
+ if (ret)
+ return ret;
+ }
+
+ /* Run the firmware */
+ if (priv->stop_fw) {
+ ret = priv->stop_fw(priv, 0);
+ if (ret)
+ return ret;
+ }
+
+ /* Reset hermes chip and make sure it responds */
+ ret = hermes_init(hw);
+
+ /* hermes_reset() should return 0 with the secondary firmware */
+ if (secondary && ret != 0)
+ return -ENODEV;
+
+ /* And this should work with any firmware */
+ if (!hermes_present(hw))
+ return -ENODEV;
+
+ return 0;
+}
+
+
+/*
+ * Download the firmware into the card, this also does a PCMCIA soft
+ * reset on the card, to make sure it's in a sane state.
+ */
+static int
+symbol_dl_firmware(struct orinoco_private *priv,
+ const struct fw_info *fw)
+{
+ struct net_device *dev = priv->ndev;
+ int ret;
+ const struct firmware *fw_entry;
+
+ if (request_firmware(&fw_entry, fw->pri_fw,
+ priv->dev) != 0) {
+ printk(KERN_ERR "%s: Cannot find firmware: %s\n",
+ dev->name, fw->pri_fw);
+ return -ENOENT;
+ }
+
+ /* Load primary firmware */
+ ret = symbol_dl_image(priv, fw, fw_entry->data,
+ fw_entry->data + fw_entry->size, 0);
+ release_firmware(fw_entry);
+ if (ret) {
+ printk(KERN_ERR "%s: Primary firmware download failed\n",
+ dev->name);
+ return ret;
+ }
+
+ if (request_firmware(&fw_entry, fw->sta_fw,
+ priv->dev) != 0) {
+ printk(KERN_ERR "%s: Cannot find firmware: %s\n",
+ dev->name, fw->sta_fw);
+ return -ENOENT;
+ }
+
+ /* Load secondary firmware */
+ ret = symbol_dl_image(priv, fw, fw_entry->data,
+ fw_entry->data + fw_entry->size, 1);
+ release_firmware(fw_entry);
+ if (ret) {
+ printk(KERN_ERR "%s: Secondary firmware download failed\n",
+ dev->name);
+ }
+
+ return ret;
+}
+
+static int orinoco_download(struct orinoco_private *priv)
+{
+ int err = 0;
+ /* Reload firmware */
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_AGERE:
+ /* case FIRMWARE_TYPE_INTERSIL: */
+ err = orinoco_dl_firmware(priv,
+ &orinoco_fw[priv->firmware_type], 0);
+ break;
+
+ case FIRMWARE_TYPE_SYMBOL:
+ err = symbol_dl_firmware(priv,
+ &orinoco_fw[priv->firmware_type]);
+ break;
+ case FIRMWARE_TYPE_INTERSIL:
+ break;
+ }
+ /* TODO: if we fail we probably need to reinitialise
+ * the driver */
+
+ return err;
}
/********************************************************************/
@@ -453,8 +835,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
int err = 0;
u16 txfid = priv->txfid;
struct ethhdr *eh;
- int data_off;
- struct hermes_tx_descriptor desc;
+ int tx_control;
unsigned long flags;
if (! netif_running(dev)) {
@@ -486,23 +867,54 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < ETH_HLEN)
goto drop;
- eh = (struct ethhdr *)skb->data;
+ tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
- memset(&desc, 0, sizeof(desc));
- desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
- err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
- if (err) {
- if (net_ratelimit())
- printk(KERN_ERR "%s: Error %d writing Tx descriptor "
- "to BAP\n", dev->name, err);
- goto busy;
+ if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
+ tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
+ HERMES_TXCTRL_MIC;
+
+ if (priv->has_alt_txcntl) {
+ /* WPA enabled firmwares have tx_cntl at the end of
+ * the 802.11 header. So write zeroed descriptor and
+ * 802.11 header at the same time
+ */
+ char desc[HERMES_802_3_OFFSET];
+ __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
+
+ memset(&desc, 0, sizeof(desc));
+
+ *txcntl = cpu_to_le16(tx_control);
+ err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
+ txfid, 0);
+ if (err) {
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Error %d writing Tx "
+ "descriptor to BAP\n", dev->name, err);
+ goto busy;
+ }
+ } else {
+ struct hermes_tx_descriptor desc;
+
+ memset(&desc, 0, sizeof(desc));
+
+ desc.tx_control = cpu_to_le16(tx_control);
+ err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
+ txfid, 0);
+ if (err) {
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Error %d writing Tx "
+ "descriptor to BAP\n", dev->name, err);
+ goto busy;
+ }
+
+ /* Clear the 802.11 header and data length fields - some
+ * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
+ * if this isn't done. */
+ hermes_clear_words(hw, HERMES_DATA0,
+ HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
}
- /* Clear the 802.11 header and data length fields - some
- * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
- * if this isn't done. */
- hermes_clear_words(hw, HERMES_DATA0,
- HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
+ eh = (struct ethhdr *)skb->data;
/* Encapsulate Ethernet-II frames */
if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
@@ -513,33 +925,65 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
/* Strip destination and source from the data */
skb_pull(skb, 2 * ETH_ALEN);
- data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
/* And move them to a separate header */
memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
- err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
- txfid, HERMES_802_3_OFFSET);
- if (err) {
- if (net_ratelimit())
- printk(KERN_ERR "%s: Error %d writing packet "
- "header to BAP\n", dev->name, err);
- goto busy;
+ /* Insert the SNAP header */
+ if (skb_headroom(skb) < sizeof(hdr)) {
+ printk(KERN_ERR
+ "%s: Not enough headroom for 802.2 headers %d\n",
+ dev->name, skb_headroom(skb));
+ goto drop;
}
- } else { /* IEEE 802.3 frame */
- data_off = HERMES_802_3_OFFSET;
+ eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
+ memcpy(eh, &hdr, sizeof(hdr));
}
err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
- txfid, data_off);
+ txfid, HERMES_802_3_OFFSET);
if (err) {
printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
dev->name, err);
goto busy;
}
+ /* Calculate Michael MIC */
+ if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
+ u8 mic_buf[MICHAEL_MIC_LEN + 1];
+ u8 *mic;
+ size_t offset;
+ size_t len;
+
+ if (skb->len % 2) {
+ /* MIC start is on an odd boundary */
+ mic_buf[0] = skb->data[skb->len - 1];
+ mic = &mic_buf[1];
+ offset = skb->len - 1;
+ len = MICHAEL_MIC_LEN + 1;
+ } else {
+ mic = &mic_buf[0];
+ offset = skb->len;
+ len = MICHAEL_MIC_LEN;
+ }
+
+ michael_mic(priv->tx_tfm_mic,
+ priv->tkip_key[priv->tx_key].tx_mic,
+ eh->h_dest, eh->h_source, 0 /* priority */,
+ skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
+
+ /* Write the MIC */
+ err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
+ txfid, HERMES_802_3_OFFSET + offset);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
+ dev->name, err);
+ goto busy;
+ }
+ }
+
/* Finally, we actually initiate the send */
netif_stop_queue(dev);
@@ -554,7 +998,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev->trans_start = jiffies;
- stats->tx_bytes += data_off + skb->len;
+ stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
goto ok;
drop:
@@ -834,21 +1278,48 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
stats->rx_dropped++;
}
+/* Get tsc from the firmware */
+static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,
+ u8 *tsc)
+{
+ hermes_t *hw = &priv->hw;
+ int err = 0;
+ u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
+
+ if ((key < 0) || (key > 4))
+ return -EINVAL;
+
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
+ sizeof(tsc_arr), NULL, &tsc_arr);
+ if (!err)
+ memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
+
+ return err;
+}
+
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct iw_statistics *wstats = &priv->wstats;
struct sk_buff *skb = NULL;
- u16 rxfid, status, fc;
+ u16 rxfid, status;
int length;
- struct hermes_rx_descriptor desc;
- struct ethhdr *hdr;
+ struct hermes_rx_descriptor *desc;
+ struct orinoco_rx_data *rx_data;
int err;
+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
+ if (!desc) {
+ printk(KERN_WARNING
+ "%s: Can't allocate space for RX descriptor\n",
+ dev->name);
+ goto update_stats;
+ }
+
rxfid = hermes_read_regn(hw, RXFID);
- err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
+ err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
rxfid, 0);
if (err) {
printk(KERN_ERR "%s: error %d reading Rx descriptor. "
@@ -856,7 +1327,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
goto update_stats;
}
- status = le16_to_cpu(desc.status);
+ status = le16_to_cpu(desc->status);
if (status & HERMES_RXSTAT_BADCRC) {
DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
@@ -867,8 +1338,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
/* Handle frames in monitor mode */
if (priv->iw_mode == IW_MODE_MONITOR) {
- orinoco_rx_monitor(dev, rxfid, &desc);
- return;
+ orinoco_rx_monitor(dev, rxfid, desc);
+ goto out;
}
if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
@@ -878,15 +1349,14 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
goto update_stats;
}
- length = le16_to_cpu(desc.data_len);
- fc = le16_to_cpu(desc.frame_ctl);
+ length = le16_to_cpu(desc->data_len);
/* Sanity checks */
if (length < 3) { /* No for even an 802.2 LLC header */
/* At least on Symbol firmware with PCF we get quite a
lot of these legitimately - Poll frames with no
data. */
- return;
+ goto out;
}
if (length > IEEE80211_DATA_LEN) {
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
@@ -895,6 +1365,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
goto update_stats;
}
+ /* Payload size does not include Michael MIC. Increase payload
+ * size to read it together with the data. */
+ if (status & HERMES_RXSTAT_MIC)
+ length += MICHAEL_MIC_LEN;
+
/* We need space for the packet data itself, plus an ethernet
header, plus 2 bytes so we can align the IP header on a
32bit boundary, plus 1 byte so we can read in odd length
@@ -921,6 +1396,100 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
goto drop;
}
+ /* Add desc and skb to rx queue */
+ rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC);
+ if (!rx_data) {
+ printk(KERN_WARNING "%s: Can't allocate RX packet\n",
+ dev->name);
+ goto drop;
+ }
+ rx_data->desc = desc;
+ rx_data->skb = skb;
+ list_add_tail(&rx_data->list, &priv->rx_list);
+ tasklet_schedule(&priv->rx_tasklet);
+
+ return;
+
+drop:
+ dev_kfree_skb_irq(skb);
+update_stats:
+ stats->rx_errors++;
+ stats->rx_dropped++;
+out:
+ kfree(desc);
+}
+
+static void orinoco_rx(struct net_device *dev,
+ struct hermes_rx_descriptor *desc,
+ struct sk_buff *skb)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &priv->stats;
+ u16 status, fc;
+ int length;
+ struct ethhdr *hdr;
+
+ status = le16_to_cpu(desc->status);
+ length = le16_to_cpu(desc->data_len);
+ fc = le16_to_cpu(desc->frame_ctl);
+
+ /* Calculate and check MIC */
+ if (status & HERMES_RXSTAT_MIC) {
+ int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
+ HERMES_MIC_KEY_ID_SHIFT);
+ u8 mic[MICHAEL_MIC_LEN];
+ u8 *rxmic;
+ u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
+ desc->addr3 : desc->addr2;
+
+ /* Extract Michael MIC from payload */
+ rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
+
+ skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+ length -= MICHAEL_MIC_LEN;
+
+ michael_mic(priv->rx_tfm_mic,
+ priv->tkip_key[key_id].rx_mic,
+ desc->addr1,
+ src,
+ 0, /* priority or QoS? */
+ skb->data,
+ skb->len,
+ &mic[0]);
+
+ if (memcmp(mic, rxmic,
+ MICHAEL_MIC_LEN)) {
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure wxmic;
+ DECLARE_MAC_BUF(mac);
+
+ printk(KERN_WARNING "%s: "
+ "Invalid Michael MIC in data frame from %s, "
+ "using key %i\n",
+ dev->name, print_mac(mac, src), key_id);
+
+ /* TODO: update stats */
+
+ /* Notify userspace */
+ memset(&wxmic, 0, sizeof(wxmic));
+ wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
+ wxmic.flags |= (desc->addr1[0] & 1) ?
+ IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
+ wxmic.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
+
+ (void) orinoco_hw_get_tkip_iv(priv, key_id,
+ &wxmic.tsc[0]);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(wxmic);
+ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
+ (char *) &wxmic);
+
+ goto drop;
+ }
+ }
+
/* Handle decapsulation
* In most cases, the firmware tell us about SNAP frames.
* For some reason, the SNAP frames sent by LinkSys APs
@@ -939,11 +1508,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
hdr->h_proto = htons(length);
}
- memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
+ memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
if (fc & IEEE80211_FCTL_FROMDS)
- memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
+ memcpy(hdr->h_source, desc->addr3, ETH_ALEN);
else
- memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
+ memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
@@ -952,7 +1521,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
skb->pkt_type = PACKET_OTHERHOST;
/* Process the wireless stats if needed */
- orinoco_stat_gather(dev, skb, &desc);
+ orinoco_stat_gather(dev, skb, desc);
/* Pass the packet to the networking stack */
netif_rx(skb);
@@ -961,13 +1530,33 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
return;
- drop:
- dev_kfree_skb_irq(skb);
- update_stats:
+ drop:
+ dev_kfree_skb(skb);
stats->rx_errors++;
stats->rx_dropped++;
}
+static void orinoco_rx_isr_tasklet(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_rx_data *rx_data, *temp;
+ struct hermes_rx_descriptor *desc;
+ struct sk_buff *skb;
+
+ /* extract desc and skb from queue */
+ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
+ desc = rx_data->desc;
+ skb = rx_data->skb;
+ list_del(&rx_data->list);
+ kfree(rx_data);
+
+ orinoco_rx(dev, desc, skb);
+
+ kfree(desc);
+ }
+}
+
/********************************************************************/
/* Rx path (info frames) */
/********************************************************************/
@@ -1087,52 +1676,172 @@ static void orinoco_join_ap(struct work_struct *work)
}
/* Send new BSSID to userspace */
-static void orinoco_send_wevents(struct work_struct *work)
+static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
{
- struct orinoco_private *priv =
- container_of(work, struct orinoco_private, wevent_work);
struct net_device *dev = priv->ndev;
struct hermes *hw = &priv->hw;
union iwreq_data wrqu;
int err;
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return;
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
- goto out;
+ return;
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+}
- out:
- orinoco_unlock(priv, &flags);
+static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ struct hermes *hw = &priv->hw;
+ union iwreq_data wrqu;
+ int err;
+ u8 buf[88];
+ u8 *ie;
+
+ if (!priv->has_wpa)
+ return;
+
+ err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
+ sizeof(buf), NULL, &buf);
+ if (err != 0)
+ return;
+
+ ie = orinoco_get_wpa_ie(buf, sizeof(buf));
+ if (ie) {
+ int rem = sizeof(buf) - (ie - &buf[0]);
+ wrqu.data.length = ie[1] + 2;
+ if (wrqu.data.length > rem)
+ wrqu.data.length = rem;
+
+ if (wrqu.data.length)
+ /* Send event to user space */
+ wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
+ }
}
+static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ struct hermes *hw = &priv->hw;
+ union iwreq_data wrqu;
+ int err;
+ u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
+ u8 *ie;
+
+ if (!priv->has_wpa)
+ return;
+
+ err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
+ sizeof(buf), NULL, &buf);
+ if (err != 0)
+ return;
+
+ ie = orinoco_get_wpa_ie(buf, sizeof(buf));
+ if (ie) {
+ int rem = sizeof(buf) - (ie - &buf[0]);
+ wrqu.data.length = ie[1] + 2;
+ if (wrqu.data.length > rem)
+ wrqu.data.length = rem;
+
+ if (wrqu.data.length)
+ /* Send event to user space */
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
+ }
+}
+
+static void orinoco_send_wevents(struct work_struct *work)
+{
+ struct orinoco_private *priv =
+ container_of(work, struct orinoco_private, wevent_work);
+ unsigned long flags;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return;
+
+ orinoco_send_assocreqie_wevent(priv);
+ orinoco_send_assocrespie_wevent(priv);
+ orinoco_send_bssid_wevent(priv);
+
+ orinoco_unlock(priv, &flags);
+}
static inline void orinoco_clear_scan_results(struct orinoco_private *priv,
unsigned long scan_age)
{
- bss_element *bss;
- bss_element *tmp_bss;
-
- /* Blow away current list of scan results */
- list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
- if (!scan_age ||
- time_after(jiffies, bss->last_scanned + scan_age)) {
- list_move_tail(&bss->list, &priv->bss_free_list);
- /* Don't blow away ->list, just BSS data */
- memset(bss, 0, sizeof(bss->bss));
- bss->last_scanned = 0;
+ if (priv->has_ext_scan) {
+ struct xbss_element *bss;
+ struct xbss_element *tmp_bss;
+
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
+ if (!scan_age ||
+ time_after(jiffies, bss->last_scanned + scan_age)) {
+ list_move_tail(&bss->list,
+ &priv->bss_free_list);
+ /* Don't blow away ->list, just BSS data */
+ memset(&bss->bss, 0, sizeof(bss->bss));
+ bss->last_scanned = 0;
+ }
+ }
+ } else {
+ struct bss_element *bss;
+ struct bss_element *tmp_bss;
+
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
+ if (!scan_age ||
+ time_after(jiffies, bss->last_scanned + scan_age)) {
+ list_move_tail(&bss->list,
+ &priv->bss_free_list);
+ /* Don't blow away ->list, just BSS data */
+ memset(&bss->bss, 0, sizeof(bss->bss));
+ bss->last_scanned = 0;
+ }
}
}
}
+static void orinoco_add_ext_scan_result(struct orinoco_private *priv,
+ struct agere_ext_scan_info *atom)
+{
+ struct xbss_element *bss = NULL;
+ int found = 0;
+
+ /* Try to update an existing bss first */
+ list_for_each_entry(bss, &priv->bss_list, list) {
+ if (compare_ether_addr(bss->bss.bssid, atom->bssid))
+ continue;
+ /* ESSID lengths */
+ if (bss->bss.data[1] != atom->data[1])
+ continue;
+ if (memcmp(&bss->bss.data[2], &atom->data[2],
+ atom->data[1]))
+ continue;
+ found = 1;
+ break;
+ }
+
+ /* Grab a bss off the free list */
+ if (!found && !list_empty(&priv->bss_free_list)) {
+ bss = list_entry(priv->bss_free_list.next,
+ struct xbss_element, list);
+ list_del(priv->bss_free_list.next);
+
+ list_add_tail(&bss->list, &priv->bss_list);
+ }
+
+ if (bss) {
+ /* Always update the BSS to get latest beacon info */
+ memcpy(&bss->bss, atom, sizeof(bss->bss));
+ bss->last_scanned = jiffies;
+ }
+}
+
static int orinoco_process_scan_results(struct net_device *dev,
unsigned char *buf,
int len)
@@ -1194,7 +1903,7 @@ static int orinoco_process_scan_results(struct net_device *dev,
/* Read the entries one by one */
for (; offset + atom_len <= len; offset += atom_len) {
int found = 0;
- bss_element *bss = NULL;
+ struct bss_element *bss = NULL;
/* Get next atom */
atom = (union hermes_scan_info *) (buf + offset);
@@ -1216,7 +1925,7 @@ static int orinoco_process_scan_results(struct net_device *dev,
/* Grab a bss off the free list */
if (!found && !list_empty(&priv->bss_free_list)) {
bss = list_entry(priv->bss_free_list.next,
- bss_element, list);
+ struct bss_element, list);
list_del(priv->bss_free_list.next);
list_add_tail(&bss->list, &priv->bss_list);
@@ -1404,6 +2113,63 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
kfree(buf);
}
break;
+ case HERMES_INQ_CHANNELINFO:
+ {
+ struct agere_ext_scan_info *bss;
+
+ if (!priv->scan_inprogress) {
+ printk(KERN_DEBUG "%s: Got chaninfo without scan, "
+ "len=%d\n", dev->name, len);
+ break;
+ }
+
+ /* An empty result indicates that the scan is complete */
+ if (len == 0) {
+ union iwreq_data wrqu;
+
+ /* Scan is no longer in progress */
+ priv->scan_inprogress = 0;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ break;
+ }
+
+ /* Sanity check */
+ else if (len > sizeof(*bss)) {
+ printk(KERN_WARNING
+ "%s: Ext scan results too large (%d bytes). "
+ "Truncating results to %zd bytes.\n",
+ dev->name, len, sizeof(*bss));
+ len = sizeof(*bss);
+ } else if (len < (offsetof(struct agere_ext_scan_info,
+ data) + 2)) {
+ /* Drop this result now so we don't have to
+ * keep checking later */
+ printk(KERN_WARNING
+ "%s: Ext scan results too short (%d bytes)\n",
+ dev->name, len);
+ break;
+ }
+
+ bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
+ if (bss == NULL)
+ break;
+
+ /* Read scan data */
+ err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
+ infofid, sizeof(info));
+ if (err) {
+ kfree(bss);
+ break;
+ }
+
+ orinoco_add_ext_scan_result(priv, bss);
+
+ kfree(bss);
+ break;
+ }
case HERMES_INQ_SEC_STAT_AGERE:
/* Security status (Agere specific) */
/* Ignore this frame for now */
@@ -1586,7 +2352,7 @@ static int __orinoco_hw_set_wap(struct orinoco_private *priv)
}
/* Change the WEP keys and/or the current keys. Can be called
- * either from __orinoco_hw_setup_wep() or directly from
+ * either from __orinoco_hw_setup_enc() or directly from
* orinoco_ioctl_setiwencode(). In the later case the association
* with the AP is not broken (if the firmware can handle it),
* which is needed for 802.1x implementations. */
@@ -1646,14 +2412,16 @@ static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
return 0;
}
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+static int __orinoco_hw_setup_enc(struct orinoco_private *priv)
{
hermes_t *hw = &priv->hw;
int err = 0;
int master_wep_flag;
int auth_flag;
+ int enc_flag;
- if (priv->wep_on)
+ /* Setup WEP keys for WEP and WPA */
+ if (priv->encode_alg)
__orinoco_hw_setup_wepkeys(priv);
if (priv->wep_restrict)
@@ -1661,9 +2429,16 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
else
auth_flag = HERMES_AUTH_OPEN;
+ if (priv->wpa_enabled)
+ enc_flag = 2;
+ else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
+ enc_flag = 1;
+ else
+ enc_flag = 0;
+
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
- if (priv->wep_on) {
+ if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
/* Enable the shared-key authentication. */
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFAUTHENTICATION_AGERE,
@@ -1671,14 +2446,24 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
}
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFWEPENABLED_AGERE,
- priv->wep_on);
+ enc_flag);
if (err)
return err;
+
+ if (priv->has_wpa) {
+ /* Set WPA key management */
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
+ priv->key_mgmt);
+ if (err)
+ return err;
+ }
+
break;
case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
- if (priv->wep_on) {
+ if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
if (priv->wep_restrict ||
(priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
@@ -1710,6 +2495,84 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
return 0;
}
+/* key must be 32 bytes, including the tx and rx MIC keys.
+ * rsc must be 8 bytes
+ * tsc must be 8 bytes or NULL
+ */
+static int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
+ u8 *key, u8 *rsc, u8 *tsc)
+{
+ struct {
+ __le16 idx;
+ u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
+ u8 key[TKIP_KEYLEN];
+ u8 tx_mic[MIC_KEYLEN];
+ u8 rx_mic[MIC_KEYLEN];
+ u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
+ } __attribute__ ((packed)) buf;
+ int ret;
+ int err;
+ int k;
+ u16 xmitting;
+
+ key_idx &= 0x3;
+
+ if (set_tx)
+ key_idx |= 0x8000;
+
+ buf.idx = cpu_to_le16(key_idx);
+ memcpy(buf.key, key,
+ sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
+
+ if (rsc == NULL)
+ memset(buf.rsc, 0, sizeof(buf.rsc));
+ else
+ memcpy(buf.rsc, rsc, sizeof(buf.rsc));
+
+ if (tsc == NULL) {
+ memset(buf.tsc, 0, sizeof(buf.tsc));
+ buf.tsc[4] = 0x10;
+ } else {
+ memcpy(buf.tsc, tsc, sizeof(buf.tsc));
+ }
+
+ /* Wait upto 100ms for tx queue to empty */
+ k = 100;
+ do {
+ k--;
+ udelay(1000);
+ ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
+ &xmitting);
+ if (ret)
+ break;
+ } while ((k > 0) && xmitting);
+
+ if (k == 0)
+ ret = -ETIMEDOUT;
+
+ err = HERMES_WRITE_RECORD(hw, USER_BAP,
+ HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
+ &buf);
+
+ return ret ? ret : err;
+}
+
+static int orinoco_clear_tkip_key(struct orinoco_private *priv,
+ int key_idx)
+{
+ hermes_t *hw = &priv->hw;
+ int err;
+
+ memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
+ key_idx);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
+ priv->ndev->name, err, key_idx);
+ return err;
+}
+
static int __orinoco_program_rids(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
@@ -1906,10 +2769,10 @@ static int __orinoco_program_rids(struct net_device *dev)
}
/* Set up encryption */
- if (priv->has_wep) {
- err = __orinoco_hw_setup_wep(priv);
+ if (priv->has_wep || priv->has_wpa) {
+ err = __orinoco_hw_setup_enc(priv);
if (err) {
- printk(KERN_ERR "%s: Error %d activating WEP\n",
+ printk(KERN_ERR "%s: Error %d activating encryption\n",
dev->name, err);
return err;
}
@@ -1970,6 +2833,9 @@ __orinoco_set_multicast_list(struct net_device *dev)
priv->promiscuous = promisc;
}
+ /* If we're not in promiscuous mode, then we need to set the
+ * group address if either we want to multicast, or if we were
+ * multicasting and want to stop */
if (! promisc && (mc_count || priv->mc_count) ) {
struct dev_mc_list *p = dev->mc_list;
struct hermes_multicast mclist;
@@ -1989,9 +2855,10 @@ __orinoco_set_multicast_list(struct net_device *dev)
printk(KERN_WARNING "%s: Multicast list is "
"longer than mc_count\n", dev->name);
- err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
- HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
- &mclist);
+ err = hermes_write_ltv(hw, USER_BAP,
+ HERMES_RID_CNFGROUPADDRESSES,
+ HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
+ &mclist);
if (err)
printk(KERN_ERR "%s: Error %d setting multicast list.\n",
dev->name, err);
@@ -2043,6 +2910,12 @@ static void orinoco_reset(struct work_struct *work)
}
}
+ if (priv->do_fw_download) {
+ err = orinoco_download(priv);
+ if (err)
+ priv->do_fw_download = 0;
+ }
+
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
@@ -2254,6 +3127,10 @@ static int determine_firmware(struct net_device *dev)
priv->has_ibss = 1;
priv->has_wep = 0;
priv->has_big_wep = 0;
+ priv->has_alt_txcntl = 0;
+ priv->has_ext_scan = 0;
+ priv->has_wpa = 0;
+ priv->do_fw_download = 0;
/* Determine capabilities from the firmware version */
switch (priv->firmware_type) {
@@ -2273,8 +3150,11 @@ static int determine_firmware(struct net_device *dev)
priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
priv->ibss_port = 1;
priv->has_hostscan = (firmver >= 0x8000a);
+ priv->do_fw_download = 1;
priv->broken_monitor = (firmver >= 0x80000);
-
+ priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
+ priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
+ priv->has_wpa = (firmver >= 0x9002a);
/* Tested with Agere firmware :
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
* Tested CableTron firmware : 4.32 => Anton */
@@ -2317,6 +3197,21 @@ static int determine_firmware(struct net_device *dev)
firmver >= 0x31000;
priv->has_preamble = (firmver >= 0x20000);
priv->ibss_port = 4;
+
+ /* Symbol firmware is found on various cards, but
+ * there has been no attempt to check firmware
+ * download on non-spectrum_cs based cards.
+ *
+ * Given that the Agere firmware download works
+ * differently, we should avoid doing a firmware
+ * download with the Symbol algorithm on non-spectrum
+ * cards.
+ *
+ * For now we can identify a spectrum_cs based card
+ * because it has a firmware reset function.
+ */
+ priv->do_fw_download = (priv->stop_fw != NULL);
+
priv->broken_disableport = (firmver == 0x25013) ||
(firmver >= 0x30000 && firmver <= 0x31000);
priv->has_hostscan = (firmver >= 0x31001) ||
@@ -2387,6 +3282,20 @@ static int orinoco_init(struct net_device *dev)
goto out;
}
+ if (priv->do_fw_download) {
+ err = orinoco_download(priv);
+ if (err)
+ priv->do_fw_download = 0;
+
+ /* Check firmware version again */
+ err = determine_firmware(dev);
+ if (err != 0) {
+ printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
+ dev->name);
+ goto out;
+ }
+ }
+
if (priv->has_port3)
printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
if (priv->has_ibss)
@@ -2399,6 +3308,20 @@ static int orinoco_init(struct net_device *dev)
else
printk("40-bit key\n");
}
+ if (priv->has_wpa) {
+ printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);
+ if (orinoco_mic_init(priv)) {
+ printk(KERN_ERR "%s: Failed to setup MIC crypto "
+ "algorithm. Disabling WPA support\n", dev->name);
+ priv->has_wpa = 0;
+ }
+ }
+
+ /* Now we have the firmware capabilities, allocate appropiate
+ * sized scan buffers */
+ if (orinoco_bss_data_allocate(priv))
+ goto out;
+ orinoco_bss_data_init(priv);
/* Get the MAC address */
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
@@ -2514,8 +3437,13 @@ static int orinoco_init(struct net_device *dev)
priv->channel = 0; /* use firmware default */
priv->promiscuous = 0;
- priv->wep_on = 0;
+ priv->encode_alg = IW_ENCODE_ALG_NONE;
priv->tx_key = 0;
+ priv->wpa_enabled = 0;
+ priv->tkip_cm_active = 0;
+ priv->key_mgmt = 0;
+ priv->wpa_ie_len = 0;
+ priv->wpa_ie = NULL;
/* Make the hardware available, as long as it hasn't been
* removed elsewhere (e.g. by PCMCIA hot unplug) */
@@ -2529,8 +3457,11 @@ static int orinoco_init(struct net_device *dev)
return err;
}
-struct net_device *alloc_orinocodev(int sizeof_card,
- int (*hard_reset)(struct orinoco_private *))
+struct net_device
+*alloc_orinocodev(int sizeof_card,
+ struct device *device,
+ int (*hard_reset)(struct orinoco_private *),
+ int (*stop_fw)(struct orinoco_private *, int))
{
struct net_device *dev;
struct orinoco_private *priv;
@@ -2545,10 +3476,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
+ sizeof(struct orinoco_private));
else
priv->card = NULL;
-
- if (orinoco_bss_data_allocate(priv))
- goto err_out_free;
- orinoco_bss_data_init(priv);
+ priv->dev = device;
/* Setup / override net_device fields */
dev->init = orinoco_init;
@@ -2566,10 +3494,14 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */
+ /* Reserve space in skb for the SNAP header */
+ dev->hard_header_len += ENCAPS_OVERHEAD;
+
/* Set up default callbacks */
dev->open = orinoco_open;
dev->stop = orinoco_stop;
priv->hard_reset = hard_reset;
+ priv->stop_fw = stop_fw;
spin_lock_init(&priv->lock);
priv->open = 0;
@@ -2580,20 +3512,27 @@ struct net_device *alloc_orinocodev(int sizeof_card,
INIT_WORK(&priv->join_work, orinoco_join_ap);
INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
+ INIT_LIST_HEAD(&priv->rx_list);
+ tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet,
+ (unsigned long) dev);
+
netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
return dev;
-
-err_out_free:
- free_netdev(dev);
- return NULL;
}
void free_orinocodev(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
+ /* No need to empty priv->rx_list: if the tasklet is scheduled
+ * when we call tasklet_kill it will run one final time,
+ * emptying the list */
+ tasklet_kill(&priv->rx_tasklet);
+ priv->wpa_ie_len = 0;
+ kfree(priv->wpa_ie);
+ orinoco_mic_free(priv);
orinoco_bss_data_free(priv);
free_netdev(dev);
}
@@ -2905,7 +3844,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
memset(range, 0, sizeof(struct iw_range));
range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 14;
+ range->we_version_source = 22;
/* Set available channels/frequencies */
range->num_channels = NUM_CHANNELS;
@@ -2935,6 +3874,9 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
}
}
+ if (priv->has_wpa)
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
+
if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
/* Quality stats meaningless in ad-hoc mode */
} else {
@@ -2982,6 +3924,11 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
range->min_r_time = 0;
range->max_r_time = 65535 * 1000; /* ??? */
+ if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+ else
+ range->scan_capa = IW_SCAN_CAPA_NONE;
+
/* Event capability (kernel) */
IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
/* Event capability (driver) */
@@ -3001,7 +3948,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
struct orinoco_private *priv = netdev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
int setindex = priv->tx_key;
- int enable = priv->wep_on;
+ int encode_alg = priv->encode_alg;
int restricted = priv->wep_restrict;
u16 xlen = 0;
int err = -EINPROGRESS; /* Call commit handler */
@@ -3022,6 +3969,10 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
+ /* Clear any TKIP key we have */
+ if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP))
+ (void) orinoco_clear_tkip_key(priv, setindex);
+
if (erq->length > 0) {
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
@@ -3035,9 +3986,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
xlen = 0;
/* Switch on WEP if off */
- if ((!enable) && (xlen > 0)) {
+ if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) {
setindex = index;
- enable = 1;
+ encode_alg = IW_ENCODE_ALG_WEP;
}
} else {
/* Important note : if the user do "iwconfig eth0 enc off",
@@ -3059,7 +4010,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
}
if (erq->flags & IW_ENCODE_DISABLED)
- enable = 0;
+ encode_alg = IW_ENCODE_ALG_NONE;
if (erq->flags & IW_ENCODE_OPEN)
restricted = 0;
if (erq->flags & IW_ENCODE_RESTRICTED)
@@ -3074,14 +4025,15 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
priv->tx_key = setindex;
/* Try fast key change if connected and only keys are changed */
- if (priv->wep_on && enable && (priv->wep_restrict == restricted) &&
+ if ((priv->encode_alg == encode_alg) &&
+ (priv->wep_restrict == restricted) &&
netif_carrier_ok(dev)) {
err = __orinoco_hw_setup_wepkeys(priv);
/* No need to commit if successful */
goto out;
}
- priv->wep_on = enable;
+ priv->encode_alg = encode_alg;
priv->wep_restrict = restricted;
out:
@@ -3110,7 +4062,7 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
index = priv->tx_key;
erq->flags = 0;
- if (! priv->wep_on)
+ if (!priv->encode_alg)
erq->flags |= IW_ENCODE_DISABLED;
erq->flags |= index + 1;
@@ -3685,6 +4637,399 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
return err;
}
+static int orinoco_ioctl_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, alg = ext->alg, set_key = 1;
+ unsigned long flags;
+ int err = -EINVAL;
+ u16 key_len;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ /* Determine and validate the key index */
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if ((idx < 1) || (idx > WEP_KEYS))
+ goto out;
+ idx--;
+ } else
+ idx = priv->tx_key;
+
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ alg = IW_ENCODE_ALG_NONE;
+
+ if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
+ /* Clear any TKIP TX key we had */
+ (void) orinoco_clear_tkip_key(priv, priv->tx_key);
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ priv->tx_key = idx;
+ set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
+ (ext->key_len > 0)) ? 1 : 0;
+ }
+
+ if (set_key) {
+ /* Set the requested key first */
+ switch (alg) {
+ case IW_ENCODE_ALG_NONE:
+ priv->encode_alg = alg;
+ priv->keys[idx].len = 0;
+ break;
+
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > SMALL_KEY_SIZE)
+ key_len = LARGE_KEY_SIZE;
+ else if (ext->key_len > 0)
+ key_len = SMALL_KEY_SIZE;
+ else
+ goto out;
+
+ priv->encode_alg = alg;
+ priv->keys[idx].len = cpu_to_le16(key_len);
+
+ key_len = min(ext->key_len, key_len);
+
+ memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
+ memcpy(priv->keys[idx].data, ext->key, key_len);
+ break;
+
+ case IW_ENCODE_ALG_TKIP:
+ {
+ hermes_t *hw = &priv->hw;
+ u8 *tkip_iv = NULL;
+
+ if (!priv->has_wpa ||
+ (ext->key_len > sizeof(priv->tkip_key[0])))
+ goto out;
+
+ priv->encode_alg = alg;
+ memset(&priv->tkip_key[idx], 0,
+ sizeof(priv->tkip_key[idx]));
+ memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
+
+ if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+ tkip_iv = &ext->rx_seq[0];
+
+ err = __orinoco_hw_set_tkip_key(hw, idx,
+ ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
+ (u8 *) &priv->tkip_key[idx],
+ tkip_iv, NULL);
+ if (err)
+ printk(KERN_ERR "%s: Error %d setting TKIP key"
+ "\n", dev->name, err);
+
+ goto out;
+ }
+ default:
+ goto out;
+ }
+ }
+ err = -EINPROGRESS;
+ out:
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
+static int orinoco_ioctl_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, max_key_len;
+ unsigned long flags;
+ int err;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ err = -EINVAL;
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ goto out;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if ((idx < 1) || (idx > WEP_KEYS))
+ goto out;
+ idx--;
+ } else
+ idx = priv->tx_key;
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ ext->alg = priv->encode_alg;
+ switch (priv->encode_alg) {
+ case IW_ENCODE_ALG_NONE:
+ ext->key_len = 0;
+ encoding->flags |= IW_ENCODE_DISABLED;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
+ max_key_len);
+ memcpy(ext->key, priv->keys[idx].data, ext->key_len);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
+ max_key_len);
+ memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ break;
+ }
+
+ err = 0;
+ out:
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
+static int orinoco_ioctl_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ hermes_t *hw = &priv->hw;
+ struct iw_param *param = &wrqu->param;
+ unsigned long flags;
+ int ret = -EINPROGRESS;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ case IW_AUTH_DROP_UNENCRYPTED:
+ /*
+ * orinoco does not use these parameters
+ */
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ /* wl_lkm implies value 2 == PSK for Hermes I
+ * which ties in with WEXT
+ * no other hints tho :(
+ */
+ priv->key_mgmt = param->value;
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ /* When countermeasures are enabled, shut down the
+ * card; when disabled, re-enable the card. This must
+ * take effect immediately.
+ *
+ * TODO: Make sure that the EAPOL message is getting
+ * out before card disabled
+ */
+ if (param->value) {
+ priv->tkip_cm_active = 1;
+ ret = hermes_enable_port(hw, 0);
+ } else {
+ priv->tkip_cm_active = 0;
+ ret = hermes_disable_port(hw, 0);
+ }
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (param->value & IW_AUTH_ALG_SHARED_KEY)
+ priv->wep_restrict = 1;
+ else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
+ priv->wep_restrict = 0;
+ else
+ ret = -EINVAL;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (priv->has_wpa) {
+ priv->wpa_enabled = param->value ? 1 : 0;
+ } else {
+ if (param->value)
+ ret = -EOPNOTSUPP;
+ /* else silently accept disable of WPA */
+ priv->wpa_enabled = 0;
+ }
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ orinoco_unlock(priv, &flags);
+ return ret;
+}
+
+static int orinoco_ioctl_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct iw_param *param = &wrqu->param;
+ unsigned long flags;
+ int ret = 0;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_KEY_MGMT:
+ param->value = priv->key_mgmt;
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ param->value = priv->tkip_cm_active;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (priv->wep_restrict)
+ param->value = IW_AUTH_ALG_SHARED_KEY;
+ else
+ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ param->value = priv->wpa_enabled;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ orinoco_unlock(priv, &flags);
+ return ret;
+}
+
+static int orinoco_ioctl_set_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ u8 *buf;
+ unsigned long flags;
+ int err = 0;
+
+ if ((wrqu->data.length > MAX_WPA_IE_LEN) ||
+ (wrqu->data.length && (extra == NULL)))
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ if (wrqu->data.length) {
+ buf = kmalloc(wrqu->data.length, GFP_KERNEL);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(buf, extra, wrqu->data.length);
+ kfree(priv->wpa_ie);
+ priv->wpa_ie = buf;
+ priv->wpa_ie_len = wrqu->data.length;
+ } else {
+ kfree(priv->wpa_ie);
+ priv->wpa_ie = NULL;
+ priv->wpa_ie_len = 0;
+ }
+
+ if (priv->wpa_ie) {
+ /* Looks like wl_lkm wants to check the auth alg, and
+ * somehow pass it to the firmware.
+ * Instead it just calls the key mgmt rid
+ * - we do this in set auth.
+ */
+ }
+
+out:
+ orinoco_unlock(priv, &flags);
+ return err;
+}
+
+static int orinoco_ioctl_get_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ int err = 0;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
+ wrqu->data.length = 0;
+ goto out;
+ }
+
+ if (wrqu->data.length < priv->wpa_ie_len) {
+ err = -E2BIG;
+ goto out;
+ }
+
+ wrqu->data.length = priv->wpa_ie_len;
+ memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
+
+out:
+ orinoco_unlock(priv, &flags);
+ return err;
+}
+
+static int orinoco_ioctl_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ hermes_t *hw = &priv->hw;
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ unsigned long flags;
+ int ret = 0;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ /* silently ignore */
+ break;
+
+ case IW_MLME_DISASSOC:
+ {
+ struct {
+ u8 addr[ETH_ALEN];
+ __le16 reason_code;
+ } __attribute__ ((packed)) buf;
+
+ memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
+ buf.reason_code = cpu_to_le16(mlme->reason_code);
+ ret = HERMES_WRITE_RECORD(hw, USER_BAP,
+ HERMES_RID_CNFDISASSOCIATE,
+ &buf);
+ break;
+ }
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ orinoco_unlock(priv, &flags);
+ return ret;
+}
+
static int orinoco_ioctl_getretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rrq,
@@ -3943,14 +5288,15 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err;
}
-/* Trigger a scan (look for other cells in the vicinity */
+/* Trigger a scan (look for other cells in the vicinity) */
static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *srq,
+ struct iw_point *srq,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
+ struct iw_scan_req *si = (struct iw_scan_req *) extra;
int err = 0;
unsigned long flags;
@@ -3982,7 +5328,6 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
* we access scan variables in priv is critical.
* o scan_inprogress : not touched by irq handler
* o scan_mode : not touched by irq handler
- * o scan_len : synchronised with scan_result
* Before modifying anything on those variables, please think hard !
* Jean II */
@@ -4012,13 +5357,43 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
}
break;
case FIRMWARE_TYPE_AGERE:
- err = hermes_write_wordrec(hw, USER_BAP,
+ if (priv->scan_mode & IW_SCAN_THIS_ESSID) {
+ struct hermes_idstring idbuf;
+ size_t len = min(sizeof(idbuf.val),
+ (size_t) si->essid_len);
+ idbuf.len = cpu_to_le16(len);
+ memcpy(idbuf.val, si->essid, len);
+
+ err = hermes_write_ltv(hw, USER_BAP,
+ HERMES_RID_CNFSCANSSID_AGERE,
+ HERMES_BYTES_TO_RECLEN(len + 2),
+ &idbuf);
+ } else
+ err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFSCANSSID_AGERE,
0); /* Any ESSID */
if (err)
break;
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
+ if (priv->has_ext_scan) {
+ /* Clear scan results at the start of
+ * an extended scan */
+ orinoco_clear_scan_results(priv,
+ msecs_to_jiffies(15000));
+
+ /* TODO: Is this available on older firmware?
+ * Can we use it to scan specific channels
+ * for IW_SCAN_THIS_FREQ? */
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFSCANCHANNELS2GHZ,
+ 0x7FFF);
+ if (err)
+ goto out;
+
+ err = hermes_inquire(hw,
+ HERMES_INQ_CHANNELINFO);
+ } else
+ err = hermes_inquire(hw, HERMES_INQ_SCAN);
break;
}
} else
@@ -4036,8 +5411,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
#define MAX_CUSTOM_LEN 64
/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II
- * Return message length or -errno for fatal errors */
+ * format that the Wireless Tools will understand - Jean II */
static inline char *orinoco_translate_scan(struct net_device *dev,
struct iw_request_info *info,
char *current_ev,
@@ -4049,9 +5423,10 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
u16 capabilities;
u16 channel;
struct iw_event iwe; /* Temporary buffer */
- char *p;
char custom[MAX_CUSTOM_LEN];
+ memset(&iwe, 0, sizeof(iwe));
+
/* First entry *MUST* be the AP MAC address */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
@@ -4073,8 +5448,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
/* Add mode */
iwe.cmd = SIOCGIWMODE;
capabilities = le16_to_cpu(bss->a.capabilities);
- if (capabilities & 0x3) {
- if (capabilities & 0x1)
+ if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+ if (capabilities & WLAN_CAPABILITY_ESS)
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
@@ -4084,17 +5459,22 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
channel = bss->s.channel;
if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
- /* Add frequency */
+ /* Add channel and frequency */
iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = channel;
+ iwe.u.freq.e = 0;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_FREQ_LEN);
+
iwe.u.freq.m = channel_frequency[channel-1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
}
- /* Add quality statistics */
+ /* Add quality statistics. level and noise in dB. No link quality */
iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = 0x10; /* no link quality */
+ iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
/* Wireless tools prior to 27.pre22 will show link quality
@@ -4108,25 +5488,13 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
/* Add encryption capability */
iwe.cmd = SIOCGIWENCODE;
- if (capabilities & 0x10)
+ if (capabilities & WLAN_CAPABILITY_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, bss->a.essid);
-
- /* Add EXTRA: Age to display seconds since last beacon/probe response
- * for given network. */
- iwe.cmd = IWEVCUSTOM;
- p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
- " Last beacon: %dms ago",
- jiffies_to_msecs(jiffies - last_scanned));
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
+ &iwe, NULL);
/* Bit rate is not available in Lucent/Agere firmwares */
if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
@@ -4148,7 +5516,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
if (bss->p.rates[i] == 0x0)
break;
/* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000);
+ iwe.u.bitrate.value =
+ ((bss->p.rates[i] & 0x7f) * 500000);
current_val = iwe_stream_add_value(info, current_ev,
current_val,
end_buf, &iwe,
@@ -4159,6 +5528,199 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
current_ev = current_val;
}
+ /* Beacon interval */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ "bcn_int=%d",
+ le16_to_cpu(bss->a.beacon_interv));
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ /* Capabilites */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ "capab=0x%04x",
+ capabilities);
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network. */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ " Last beacon: %dms ago",
+ jiffies_to_msecs(jiffies - last_scanned));
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ return current_ev;
+}
+
+static inline char *orinoco_translate_ext_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ char *current_ev,
+ char *end_buf,
+ struct agere_ext_scan_info *bss,
+ unsigned int last_scanned)
+{
+ u16 capabilities;
+ u16 channel;
+ struct iw_event iwe; /* Temporary buffer */
+ char custom[MAX_CUSTOM_LEN];
+ u8 *ie;
+
+ memset(&iwe, 0, sizeof(iwe));
+
+ /* First entry *MUST* be the AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_ADDR_LEN);
+
+ /* Other entries will be displayed in the order we give them */
+
+ /* Add the ESSID */
+ ie = bss->data;
+ iwe.u.data.length = ie[1];
+ if (iwe.u.data.length) {
+ if (iwe.u.data.length > 32)
+ iwe.u.data.length = 32;
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, &ie[2]);
+ }
+
+ /* Add mode */
+ capabilities = le16_to_cpu(bss->capabilities);
+ if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (capabilities & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_UINT_LEN);
+ }
+
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_DS_SET);
+ channel = ie ? ie[2] : 0;
+ if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
+ /* Add channel and frequency */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = channel;
+ iwe.u.freq.e = 0;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_FREQ_LEN);
+
+ iwe.u.freq.m = channel_frequency[channel-1] * 100000;
+ iwe.u.freq.e = 1;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_FREQ_LEN);
+ }
+
+ /* Add quality statistics. level and noise in dB. No link quality */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
+ iwe.u.qual.level = bss->level - 0x95;
+ iwe.u.qual.noise = bss->noise - 0x95;
+ /* Wireless tools prior to 27.pre22 will show link quality
+ * anyway, so we provide a reasonable value. */
+ if (iwe.u.qual.level > iwe.u.qual.noise)
+ iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
+ else
+ iwe.u.qual.qual = 0;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+ &iwe, IW_EV_QUAL_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (capabilities & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, NULL);
+
+ /* WPA IE */
+ ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
+ if (ie) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie[1] + 2;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, ie);
+ }
+
+ /* RSN IE */
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RSN);
+ if (ie) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie[1] + 2;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, ie);
+ }
+
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RATES);
+ if (ie) {
+ char *p = current_ev + iwe_stream_lcp_len(info);
+ int i;
+
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+ for (i = 2; i < (ie[1] + 2); i++) {
+ iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
+ p = iwe_stream_add_value(info, current_ev, p, end_buf,
+ &iwe, IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any event */
+ if (p > (current_ev + iwe_stream_lcp_len(info)))
+ current_ev = p;
+ }
+
+ /* Timestamp */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length =
+ snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
+ (unsigned long long) le64_to_cpu(bss->timestamp));
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ /* Beacon interval */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ "bcn_int=%d",
+ le16_to_cpu(bss->beacon_interval));
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ /* Capabilites */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ "capab=0x%04x",
+ capabilities);
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network. */
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
+ " Last beacon: %dms ago",
+ jiffies_to_msecs(jiffies - last_scanned));
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+ &iwe, custom);
+
return current_ev;
}
@@ -4169,7 +5731,6 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);
- bss_element *bss;
int err = 0;
unsigned long flags;
char *current_ev = extra;
@@ -4189,18 +5750,47 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
goto out;
}
- list_for_each_entry(bss, &priv->bss_list, list) {
- /* Translate to WE format this entry */
- current_ev = orinoco_translate_scan(dev, info, current_ev,
- extra + srq->length,
- &bss->bss,
- bss->last_scanned);
-
- /* Check if there is space for one more entry */
- if ((extra + srq->length - current_ev) <= IW_EV_ADDR_LEN) {
- /* Ask user space to try again with a bigger buffer */
- err = -E2BIG;
- goto out;
+ if (priv->has_ext_scan) {
+ struct xbss_element *bss;
+
+ list_for_each_entry(bss, &priv->bss_list, list) {
+ /* Translate this entry to WE format */
+ current_ev =
+ orinoco_translate_ext_scan(dev, info,
+ current_ev,
+ extra + srq->length,
+ &bss->bss,
+ bss->last_scanned);
+
+ /* Check if there is space for one more entry */
+ if ((extra + srq->length - current_ev)
+ <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a
+ * bigger buffer */
+ err = -E2BIG;
+ goto out;
+ }
+ }
+
+ } else {
+ struct bss_element *bss;
+
+ list_for_each_entry(bss, &priv->bss_list, list) {
+ /* Translate this entry to WE format */
+ current_ev = orinoco_translate_scan(dev, info,
+ current_ev,
+ extra + srq->length,
+ &bss->bss,
+ bss->last_scanned);
+
+ /* Check if there is space for one more entry */
+ if ((extra + srq->length - current_ev)
+ <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a
+ * bigger buffer */
+ err = -E2BIG;
+ goto out;
+ }
}
}
@@ -4291,39 +5881,48 @@ static const struct iw_priv_args orinoco_privtab[] = {
* Structures to export the Wireless Handlers
*/
+#define STD_IW_HANDLER(id, func) \
+ [IW_IOCTL_IDX(id)] = (iw_handler) func
static const iw_handler orinoco_handler[] = {
- [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_commit,
- [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getname,
- [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfreq,
- [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfreq,
- [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setmode,
- [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getmode,
- [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
- [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
- [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
- [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
- [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
- [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
- [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
- [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
- [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
- [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
- [SIOCGIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getscan,
- [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setessid,
- [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getessid,
- [SIOCSIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setnick,
- [SIOCGIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getnick,
- [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrate,
- [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrate,
- [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrts,
- [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrts,
- [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfrag,
- [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfrag,
- [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getretry,
- [SIOCSIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setiwencode,
- [SIOCGIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwencode,
- [SIOCSIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setpower,
- [SIOCGIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getpower,
+ STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
+ STD_IW_HANDLER(SIOCGIWNAME, orinoco_ioctl_getname),
+ STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
+ STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
+ STD_IW_HANDLER(SIOCSIWMODE, orinoco_ioctl_setmode),
+ STD_IW_HANDLER(SIOCGIWMODE, orinoco_ioctl_getmode),
+ STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
+ STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
+ STD_IW_HANDLER(SIOCGIWRANGE, orinoco_ioctl_getiwrange),
+ STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
+ STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
+ STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
+ STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
+ STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
+ STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
+ STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan),
+ STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan),
+ STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
+ STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
+ STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),
+ STD_IW_HANDLER(SIOCGIWNICKN, orinoco_ioctl_getnick),
+ STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
+ STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
+ STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts),
+ STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts),
+ STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag),
+ STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag),
+ STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry),
+ STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
+ STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
+ STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
+ STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
+ STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
+ STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
+ STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
+ STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
+ STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
+ STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
+ STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
};
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index c6b1858abde..981570bd3b9 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -9,6 +9,7 @@
#define DRIVER_VERSION "0.15"
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
@@ -30,27 +31,57 @@ struct orinoco_key {
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
+#define TKIP_KEYLEN 16
+#define MIC_KEYLEN 8
+
+struct orinoco_tkip_key {
+ u8 tkip[TKIP_KEYLEN];
+ u8 tx_mic[MIC_KEYLEN];
+ u8 rx_mic[MIC_KEYLEN];
+};
+
typedef enum {
FIRMWARE_TYPE_AGERE,
FIRMWARE_TYPE_INTERSIL,
FIRMWARE_TYPE_SYMBOL
} fwtype_t;
-typedef struct {
+struct bss_element {
union hermes_scan_info bss;
unsigned long last_scanned;
struct list_head list;
-} bss_element;
+};
+
+struct xbss_element {
+ struct agere_ext_scan_info bss;
+ unsigned long last_scanned;
+ struct list_head list;
+};
+
+struct hermes_rx_descriptor;
+
+struct orinoco_rx_data {
+ struct hermes_rx_descriptor *desc;
+ struct sk_buff *skb;
+ struct list_head list;
+};
struct orinoco_private {
void *card; /* Pointer to card dependent structure */
+ struct device *dev;
int (*hard_reset)(struct orinoco_private *);
+ int (*stop_fw)(struct orinoco_private *, int);
/* Synchronisation stuff */
spinlock_t lock;
int hw_unavailable;
struct work_struct reset_work;
+ /* Interrupt tasklets */
+ struct tasklet_struct rx_tasklet;
+ struct list_head rx_list;
+ struct orinoco_rx_data *rx_data;
+
/* driver state */
int open;
u16 last_linkstatus;
@@ -83,13 +114,17 @@ struct orinoco_private {
unsigned int has_preamble:1;
unsigned int has_sensitivity:1;
unsigned int has_hostscan:1;
+ unsigned int has_alt_txcntl:1;
+ unsigned int has_ext_scan:1;
+ unsigned int has_wpa:1;
+ unsigned int do_fw_download:1;
unsigned int broken_disableport:1;
unsigned int broken_monitor:1;
/* Configuration paramaters */
u32 iw_mode;
int prefer_port3;
- u16 wep_on, wep_restrict, tx_key;
+ u16 encode_alg, wep_restrict, tx_key;
struct orinoco_key keys[ORINOCO_MAX_KEYS];
int bitratemode;
char nick[IW_ESSID_MAX_SIZE+1];
@@ -113,10 +148,22 @@ struct orinoco_private {
/* Scanning support */
struct list_head bss_list;
struct list_head bss_free_list;
- bss_element *bss_data;
+ void *bss_xbss_data;
int scan_inprogress; /* Scan pending... */
u32 scan_mode; /* Type of scan done */
+
+ /* WPA support */
+ u8 *wpa_ie;
+ int wpa_ie_len;
+
+ struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
+ struct crypto_hash *rx_tfm_mic;
+ struct crypto_hash *tx_tfm_mic;
+
+ unsigned int wpa_enabled:1;
+ unsigned int tkip_cm_active:1;
+ unsigned int key_mgmt:3;
};
#ifdef ORINOCO_DEBUG
@@ -130,8 +177,10 @@ extern int orinoco_debug;
/* Exported prototypes */
/********************************************************************/
-extern struct net_device *alloc_orinocodev(int sizeof_card,
- int (*hard_reset)(struct orinoco_private *));
+extern struct net_device *alloc_orinocodev(
+ int sizeof_card, struct device *device,
+ int (*hard_reset)(struct orinoco_private *),
+ int (*stop_fw)(struct orinoco_private *, int));
extern void free_orinocodev(struct net_device *dev);
extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1c216e015f6..6fcf2bda7cd 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -80,7 +80,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
/* We need atomic ops here, because we're not holding the lock */
set_bit(0, &card->hard_reset_in_progress);
- err = pcmcia_reset_card(link, NULL);
+ err = pcmcia_reset_card(link->socket);
if (err)
return err;
@@ -109,7 +109,8 @@ orinoco_cs_probe(struct pcmcia_device *link)
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
+ dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ orinoco_cs_hard_reset, NULL);
if (! dev)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -120,7 +121,7 @@ orinoco_cs_probe(struct pcmcia_device *link)
link->priv = dev;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;
@@ -164,6 +165,70 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
} while (0)
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (cfg->index == 0)
+ goto next_entry;
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+ goto next_entry;
+ }
+ return 0;
+
+next_entry:
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+};
+
static int
orinoco_cs_config(struct pcmcia_device *link)
{
@@ -172,16 +237,8 @@ orinoco_cs_config(struct pcmcia_device *link)
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- tuple_t tuple;
- cisparse_t parse;
void __iomem *mem;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
/*
* In this loop, we scan the CIS for configuration table
* entries, each of which describes a valid card
@@ -196,94 +253,14 @@ orinoco_cs_config(struct pcmcia_device *link)
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_cftable_entry_t dflt = { .index = 0 };
-
- if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
- || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- dflt = *cfg;
- if (cfg->index == 0)
- goto next_entry;
- link->conf.ConfigIndex = cfg->index;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
- if(!ignore_cis_vcc)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io =
- (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 =
- IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 =
- IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines =
- io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 =
- link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- }
-
-
- /* If we got this far, we're cool! */
-
- break;
-
- next_entry:
- pcmcia_disable_device(link);
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- if (last_ret == CS_NO_MORE_ITEMS) {
+ last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
+ if (last_ret) {
+ if (!ignore_cis_vcc)
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
"ignore_cis_vcc=1 parameter.\n");
- goto cs_failed;
- }
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
/*
@@ -334,7 +311,6 @@ orinoco_cs_config(struct pcmcia_device *link)
"0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
link->irq.AssignedIRQ, link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1 - 1);
-
return 0;
cs_failed:
@@ -402,6 +378,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
+ unsigned long flags;
if (! test_bit(0, &card->hard_reset_in_progress)) {
err = orinoco_reinit_firmware(dev);
@@ -411,7 +388,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
return -EIO;
}
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
netif_device_attach(dev);
priv->hw_unavailable--;
@@ -423,7 +400,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
dev->name, err);
}
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return err;
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 35ec5fcf81a..2fc86596302 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -182,7 +182,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset);
+ dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_nortel_cor_reset, NULL);
if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 2547d5dac0d..4ebd638a073 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -139,7 +139,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
+ dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_pci_cor_reset, NULL);
if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 98fe165337d..ef761857bb3 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -221,7 +221,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset);
+ dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_plx_cor_reset, NULL);
if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index df493185a4a..ede24ec309c 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -124,7 +124,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
+ dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_tmd_cor_reset, NULL);
if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 4801a363507..1d0704fe146 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -1,5 +1,5 @@
-#ifndef PRISM54_H
-#define PRISM54_H
+#ifndef P54_H
+#define P54_H
/*
* Shared defines for all mac80211 Prism54 code
@@ -19,13 +19,24 @@ enum control_frame_types {
P54_CONTROL_TYPE_CHANNEL_CHANGE,
P54_CONTROL_TYPE_FREQDONE,
P54_CONTROL_TYPE_DCFINIT,
- P54_CONTROL_TYPE_FREEQUEUE = 7,
+ P54_CONTROL_TYPE_ENCRYPTION,
+ P54_CONTROL_TYPE_TIM,
+ P54_CONTROL_TYPE_POWERMGT,
+ P54_CONTROL_TYPE_FREEQUEUE,
P54_CONTROL_TYPE_TXDONE,
P54_CONTROL_TYPE_PING,
P54_CONTROL_TYPE_STAT_READBACK,
P54_CONTROL_TYPE_BBP,
P54_CONTROL_TYPE_EEPROM_READBACK,
- P54_CONTROL_TYPE_LED
+ P54_CONTROL_TYPE_LED,
+ P54_CONTROL_TYPE_GPIO,
+ P54_CONTROL_TYPE_TIMER,
+ P54_CONTROL_TYPE_MODULATION,
+ P54_CONTROL_TYPE_SYNTH_CONFIG,
+ P54_CONTROL_TYPE_DETECTOR_VALUE,
+ P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
+ P54_CONTROL_TYPE_CCE_QUIET,
+ P54_CONTROL_TYPE_PSM_STA_UNLOCK,
};
struct p54_control_hdr {
@@ -38,11 +49,15 @@ struct p54_control_hdr {
u8 data[0];
} __attribute__ ((packed));
-#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
-#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
+#define EEPROM_READBACK_LEN 0x3fc
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
+#define FW_FMAC 0x464d4143
+#define FW_LM86 0x4c4d3836
+#define FW_LM87 0x4c4d3837
+#define FW_LM20 0x4c4d3230
+
struct p54_common {
u32 rx_start;
u32 rx_end;
@@ -53,27 +68,43 @@ struct p54_common {
void (*stop)(struct ieee80211_hw *dev);
int mode;
u16 seqno;
+ u16 rx_mtu;
+ u8 headroom;
+ u8 tailroom;
struct mutex conf_mutex;
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
+ __le16 filter_type;
struct pda_iq_autocal_entry *iq_autocal;
unsigned int iq_autocal_len;
struct pda_channel_output_limit *output_limit;
unsigned int output_limit_len;
struct pda_pa_curve_data *curve_data;
- __le16 rxhw;
+ unsigned int filter_flags;
+ u16 rxhw;
u8 version;
+ u8 rx_antenna;
unsigned int tx_hdr_len;
void *cached_vdcf;
unsigned int fw_var;
- struct ieee80211_tx_queue_stats tx_stats[4];
+ unsigned int fw_interface;
+ unsigned int output_power;
+ u32 tsf_low32;
+ u32 tsf_high32;
+ struct ieee80211_tx_queue_stats tx_stats[8];
+ struct ieee80211_low_level_stats stats;
+ struct timer_list stats_timer;
+ struct completion stats_comp;
+ void *cached_stats;
+ int noise;
+ void *eeprom;
+ struct completion eeprom_comp;
};
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
+int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
+int p54_read_eeprom(struct ieee80211_hw *dev);
struct ieee80211_hw *p54_init_common(size_t priv_data_len);
void p54_free_common(struct ieee80211_hw *dev);
-#endif /* PRISM54_H */
+#endif /* P54_H */
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 29be3dc8ee0..117c7d3a52b 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -27,7 +27,7 @@ MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");
-static struct ieee80211_rate p54_rates[] = {
+static struct ieee80211_rate p54_bgrates[] = {
{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
@@ -42,7 +42,7 @@ static struct ieee80211_rate p54_rates[] = {
{ .bitrate = 540, .hw_value = 11, },
};
-static struct ieee80211_channel p54_channels[] = {
+static struct ieee80211_channel p54_bgchannels[] = {
{ .center_freq = 2412, .hw_value = 1, },
{ .center_freq = 2417, .hw_value = 2, },
{ .center_freq = 2422, .hw_value = 3, },
@@ -60,14 +60,69 @@ static struct ieee80211_channel p54_channels[] = {
};
static struct ieee80211_supported_band band_2GHz = {
- .channels = p54_channels,
- .n_channels = ARRAY_SIZE(p54_channels),
- .bitrates = p54_rates,
- .n_bitrates = ARRAY_SIZE(p54_rates),
+ .channels = p54_bgchannels,
+ .n_channels = ARRAY_SIZE(p54_bgchannels),
+ .bitrates = p54_bgrates,
+ .n_bitrates = ARRAY_SIZE(p54_bgrates),
};
+static struct ieee80211_rate p54_arates[] = {
+ { .bitrate = 60, .hw_value = 4, },
+ { .bitrate = 90, .hw_value = 5, },
+ { .bitrate = 120, .hw_value = 6, },
+ { .bitrate = 180, .hw_value = 7, },
+ { .bitrate = 240, .hw_value = 8, },
+ { .bitrate = 360, .hw_value = 9, },
+ { .bitrate = 480, .hw_value = 10, },
+ { .bitrate = 540, .hw_value = 11, },
+};
+
+static struct ieee80211_channel p54_achannels[] = {
+ { .center_freq = 4920 },
+ { .center_freq = 4940 },
+ { .center_freq = 4960 },
+ { .center_freq = 4980 },
+ { .center_freq = 5040 },
+ { .center_freq = 5060 },
+ { .center_freq = 5080 },
+ { .center_freq = 5170 },
+ { .center_freq = 5180 },
+ { .center_freq = 5190 },
+ { .center_freq = 5200 },
+ { .center_freq = 5210 },
+ { .center_freq = 5220 },
+ { .center_freq = 5230 },
+ { .center_freq = 5240 },
+ { .center_freq = 5260 },
+ { .center_freq = 5280 },
+ { .center_freq = 5300 },
+ { .center_freq = 5320 },
+ { .center_freq = 5500 },
+ { .center_freq = 5520 },
+ { .center_freq = 5540 },
+ { .center_freq = 5560 },
+ { .center_freq = 5580 },
+ { .center_freq = 5600 },
+ { .center_freq = 5620 },
+ { .center_freq = 5640 },
+ { .center_freq = 5660 },
+ { .center_freq = 5680 },
+ { .center_freq = 5700 },
+ { .center_freq = 5745 },
+ { .center_freq = 5765 },
+ { .center_freq = 5785 },
+ { .center_freq = 5805 },
+ { .center_freq = 5825 },
+};
+
+static struct ieee80211_supported_band band_5GHz = {
+ .channels = p54_achannels,
+ .n_channels = ARRAY_SIZE(p54_achannels),
+ .bitrates = p54_arates,
+ .n_bitrates = ARRAY_SIZE(p54_arates),
+};
-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
+int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
{
struct p54_common *priv = dev->priv;
struct bootrec_exp_if *exp_if;
@@ -79,7 +134,7 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
int i;
if (priv->rx_start)
- return;
+ return 0;
while (data < end_data && *data)
data++;
@@ -94,7 +149,9 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
u32 code = le32_to_cpu(bootrec->code);
switch (code) {
case BR_CODE_COMPONENT_ID:
- switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
+ priv->fw_interface = be32_to_cpup((__be32 *)
+ bootrec->data);
+ switch (priv->fw_interface) {
case FW_FMAC:
printk(KERN_INFO "p54: FreeMAC firmware\n");
break;
@@ -105,7 +162,7 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
printk(KERN_INFO "p54: LM86 firmware\n");
break;
case FW_LM87:
- printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
+ printk(KERN_INFO "p54: LM87 firmware\n");
break;
default:
printk(KERN_INFO "p54: unknown firmware\n");
@@ -117,11 +174,21 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
if (strnlen((unsigned char*)bootrec->data, 24) < 24)
fw_version = (unsigned char*)bootrec->data;
break;
- case BR_CODE_DESCR:
- priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
+ case BR_CODE_DESCR: {
+ struct bootrec_desc *desc =
+ (struct bootrec_desc *)bootrec->data;
+ priv->rx_start = le32_to_cpu(desc->rx_start);
/* FIXME add sanity checking */
- priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
+ priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
+ priv->headroom = desc->headroom;
+ priv->tailroom = desc->tailroom;
+ if (le32_to_cpu(bootrec->len) == 11)
+ priv->rx_mtu = le16_to_cpu(bootrec->rx_mtu);
+ else
+ priv->rx_mtu = (size_t)
+ 0x620 - priv->tx_hdr_len;
break;
+ }
case BR_CODE_EXPOSED_IF:
exp_if = (struct bootrec_exp_if *) bootrec->data;
for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
@@ -146,23 +213,25 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
if (priv->fw_var >= 0x300) {
/* Firmware supports QoS, use it! */
- priv->tx_stats[0].limit = 3;
- priv->tx_stats[1].limit = 4;
- priv->tx_stats[2].limit = 3;
- priv->tx_stats[3].limit = 1;
+ priv->tx_stats[4].limit = 3;
+ priv->tx_stats[5].limit = 4;
+ priv->tx_stats[6].limit = 3;
+ priv->tx_stats[7].limit = 1;
dev->queues = 4;
}
+
+ return 0;
}
EXPORT_SYMBOL_GPL(p54_parse_firmware);
-static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
- struct pda_pa_curve_data *curve_data)
+static int p54_convert_rev0(struct ieee80211_hw *dev,
+ struct pda_pa_curve_data *curve_data)
{
struct p54_common *priv = dev->priv;
- struct pda_pa_curve_data_sample_rev1 *rev1;
- struct pda_pa_curve_data_sample_rev0 *rev0;
+ struct p54_pa_curve_data_sample *dst;
+ struct pda_pa_curve_data_sample_rev0 *src;
size_t cd_len = sizeof(*curve_data) +
- (curve_data->points_per_channel*sizeof(*rev1) + 2) *
+ (curve_data->points_per_channel*sizeof(*dst) + 2) *
curve_data->channels;
unsigned int i, j;
void *source, *target;
@@ -180,28 +249,68 @@ static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
*((__le16 *)target) = *freq;
target += sizeof(__le16);
for (j = 0; j < curve_data->points_per_channel; j++) {
- rev1 = target;
- rev0 = source;
+ dst = target;
+ src = source;
- rev1->rf_power = rev0->rf_power;
- rev1->pa_detector = rev0->pa_detector;
- rev1->data_64qam = rev0->pcv;
+ dst->rf_power = src->rf_power;
+ dst->pa_detector = src->pa_detector;
+ dst->data_64qam = src->pcv;
/* "invent" the points for the other modulations */
#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
- rev1->data_16qam = SUB(rev0->pcv, 12);
- rev1->data_qpsk = SUB(rev1->data_16qam, 12);
- rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
- rev1->data_barker= SUB(rev1->data_bpsk, 14);
+ dst->data_16qam = SUB(src->pcv, 12);
+ dst->data_qpsk = SUB(dst->data_16qam, 12);
+ dst->data_bpsk = SUB(dst->data_qpsk, 12);
+ dst->data_barker = SUB(dst->data_bpsk, 14);
#undef SUB
- target += sizeof(*rev1);
- source += sizeof(*rev0);
+ target += sizeof(*dst);
+ source += sizeof(*src);
}
}
return 0;
}
-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
+static int p54_convert_rev1(struct ieee80211_hw *dev,
+ struct pda_pa_curve_data *curve_data)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_pa_curve_data_sample *dst;
+ struct pda_pa_curve_data_sample_rev1 *src;
+ size_t cd_len = sizeof(*curve_data) +
+ (curve_data->points_per_channel*sizeof(*dst) + 2) *
+ curve_data->channels;
+ unsigned int i, j;
+ void *source, *target;
+
+ priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
+ if (!priv->curve_data)
+ return -ENOMEM;
+
+ memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
+ source = curve_data->data;
+ target = priv->curve_data->data;
+ for (i = 0; i < curve_data->channels; i++) {
+ __le16 *freq = source;
+ source += sizeof(__le16);
+ *((__le16 *)target) = *freq;
+ target += sizeof(__le16);
+ for (j = 0; j < curve_data->points_per_channel; j++) {
+ memcpy(target, source, sizeof(*src));
+
+ target += sizeof(*dst);
+ source += sizeof(*src);
+ }
+ source++;
+ }
+
+ return 0;
+}
+
+static const char *p54_rf_chips[] = { "NULL", "Indigo?", "Duette",
+ "Frisbee", "Xbow", "Longbow" };
+static int p54_init_xbow_synth(struct ieee80211_hw *dev);
+
+static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
{
struct p54_common *priv = dev->priv;
struct eeprom_pda_wrap *wrap = NULL;
@@ -210,6 +319,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
void *tmp;
int err;
u8 *end = (u8 *)eeprom + len;
+ DECLARE_MAC_BUF(mac);
wrap = (struct eeprom_pda_wrap *) eeprom;
entry = (void *)wrap->data + le16_to_cpu(wrap->len);
@@ -250,27 +360,32 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
entry->data[1]*sizeof(*priv->output_limit));
priv->output_limit_len = entry->data[1];
break;
- case PDR_PRISM_PA_CAL_CURVE_DATA:
- if (data_len < sizeof(struct pda_pa_curve_data)) {
+ case PDR_PRISM_PA_CAL_CURVE_DATA: {
+ struct pda_pa_curve_data *curve_data =
+ (struct pda_pa_curve_data *)entry->data;
+ if (data_len < sizeof(*curve_data)) {
err = -EINVAL;
goto err;
}
- if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
- priv->curve_data = kmalloc(data_len, GFP_KERNEL);
- if (!priv->curve_data) {
- err = -ENOMEM;
- goto err;
- }
-
- memcpy(priv->curve_data, entry->data, data_len);
- } else {
- err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
- if (err)
- goto err;
+ switch (curve_data->cal_method_rev) {
+ case 0:
+ err = p54_convert_rev0(dev, curve_data);
+ break;
+ case 1:
+ err = p54_convert_rev1(dev, curve_data);
+ break;
+ default:
+ printk(KERN_ERR "p54: unknown curve data "
+ "revision %d\n",
+ curve_data->cal_method_rev);
+ err = -ENODEV;
+ break;
}
+ if (err)
+ goto err;
- break;
+ }
case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
if (!priv->iq_autocal) {
@@ -286,7 +401,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
while ((u8 *)tmp < entry->data + data_len) {
struct bootrec_exp_if *exp_if = tmp;
if (le16_to_cpu(exp_if->if_id) == 0xF)
- priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
+ priv->rxhw = le16_to_cpu(exp_if->variant) & 0x07;
tmp += sizeof(struct bootrec_exp_if);
}
break;
@@ -312,6 +427,37 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
goto err;
}
+ switch (priv->rxhw) {
+ case 4: /* XBow */
+ p54_init_xbow_synth(dev);
+ case 1: /* Indigo? */
+ case 2: /* Duette */
+ dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
+ case 3: /* Frisbee */
+ case 5: /* Longbow */
+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
+ break;
+ default:
+ printk(KERN_ERR "%s: unsupported RF-Chip\n",
+ wiphy_name(dev->wiphy));
+ err = -EINVAL;
+ goto err;
+ }
+
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ u8 perm_addr[ETH_ALEN];
+
+ printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
+ wiphy_name(dev->wiphy));
+ random_ether_addr(perm_addr);
+ SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+ }
+
+ printk(KERN_INFO "%s: hwaddr %s, MAC:isl38%02x RF:%s\n",
+ wiphy_name(dev->wiphy),
+ print_mac(mac, dev->wiphy->perm_addr),
+ priv->version, p54_rf_chips[priv->rxhw]);
+
return 0;
err:
@@ -333,42 +479,56 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
printk(KERN_ERR "p54: eeprom parse failed!\n");
return err;
}
-EXPORT_SYMBOL_GPL(p54_parse_eeprom);
-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
+static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
{
- struct p54_eeprom_lm86 *eeprom_hdr;
-
- hdr->magic1 = cpu_to_le16(0x8000);
- hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
- hdr->retry1 = hdr->retry2 = 0;
- eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
- eeprom_hdr->offset = 0x0;
- eeprom_hdr->len = cpu_to_le16(0x2000);
+ /* TODO: get the rssi_add & rssi_mul data from the eeprom */
+ return ((rssi * 0x83) / 64 - 400) / 4;
}
-EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
-static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
+static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
{
+ struct p54_common *priv = dev->priv;
struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
struct ieee80211_rx_status rx_status = {0};
u16 freq = le16_to_cpu(hdr->freq);
+ size_t header_len = sizeof(*hdr);
+ u32 tsf32;
+
+ if (!(hdr->magic & cpu_to_le16(0x0001))) {
+ if (priv->filter_flags & FIF_FCSFAIL)
+ rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
+ else
+ return 0;
+ }
- rx_status.signal = hdr->rssi;
+ rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
+ rx_status.noise = priv->noise;
/* XX correct? */
rx_status.qual = (100 * hdr->rssi) / 127;
- rx_status.rate_idx = hdr->rate & 0xf;
+ rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ?
+ hdr->rate : (hdr->rate - 4)) & 0xf;
rx_status.freq = freq;
- rx_status.band = IEEE80211_BAND_2GHZ;
+ rx_status.band = dev->conf.channel->band;
rx_status.antenna = hdr->antenna;
- rx_status.mactime = le64_to_cpu(hdr->timestamp);
+
+ tsf32 = le32_to_cpu(hdr->tsf32);
+ if (tsf32 < priv->tsf_low32)
+ priv->tsf_high32++;
+ rx_status.mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
+ priv->tsf_low32 = tsf32;
+
rx_status.flag |= RX_FLAG_TSFT;
- skb_pull(skb, sizeof(*hdr));
+ if (hdr->magic & cpu_to_le16(0x4000))
+ header_len += hdr->align[0];
+
+ skb_pull(skb, header_len);
skb_trim(skb, le16_to_cpu(hdr->len));
ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+ return -1;
}
static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
@@ -377,7 +537,7 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
int i;
for (i = 0; i < dev->queues; i++)
- if (priv->tx_stats[i].len < priv->tx_stats[i].limit)
+ if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
ieee80211_wake_queue(dev, i);
}
@@ -387,11 +547,13 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
- u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
+ u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
struct memrecord *range = NULL;
u32 freed = 0;
u32 last_addr = priv->rx_start;
+ unsigned long flags;
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
while (entry != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
range = (void *)info->driver_data;
@@ -412,13 +574,15 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
last_addr = range->end_addr;
__skb_unlink(entry, &priv->tx_queue);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+
memset(&info->status, 0, sizeof(info->status));
entry_hdr = (struct p54_control_hdr *) entry->data;
entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
pad = entry_data->align[0];
- priv->tx_stats[entry_data->hw_queue - 4].len--;
+ priv->tx_stats[entry_data->hw_queue].len--;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (!(payload->status & 0x01))
info->flags |= IEEE80211_TX_STAT_ACK;
@@ -426,21 +590,60 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
info->status.excessive_retries = 1;
}
info->status.retry_count = payload->retries - 1;
- info->status.ack_signal = le16_to_cpu(payload->ack_rssi);
+ info->status.ack_signal = p54_rssi_to_dbm(dev,
+ le16_to_cpu(payload->ack_rssi));
skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
ieee80211_tx_status_irqsafe(dev, entry);
- break;
+ goto out;
} else
last_addr = range->end_addr;
entry = entry->next;
}
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+out:
if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
sizeof(struct p54_control_hdr))
p54_wake_free_queues(dev);
}
-static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
+ struct sk_buff *skb)
+{
+ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+ struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
+ struct p54_common *priv = dev->priv;
+
+ if (!priv->eeprom)
+ return ;
+
+ memcpy(priv->eeprom, eeprom->data, le16_to_cpu(eeprom->len));
+
+ complete(&priv->eeprom_comp);
+}
+
+static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+ struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
+ u32 tsf32 = le32_to_cpu(stats->tsf32);
+
+ if (tsf32 < priv->tsf_low32)
+ priv->tsf_high32++;
+ priv->tsf_low32 = tsf32;
+
+ priv->stats.dot11RTSFailureCount = le32_to_cpu(stats->rts_fail);
+ priv->stats.dot11RTSSuccessCount = le32_to_cpu(stats->rts_success);
+ priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);
+
+ priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise));
+ complete(&priv->stats_comp);
+
+ mod_timer(&priv->stats_timer, jiffies + 5 * HZ);
+}
+
+static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
@@ -450,36 +653,30 @@ static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
break;
case P54_CONTROL_TYPE_BBP:
break;
+ case P54_CONTROL_TYPE_STAT_READBACK:
+ p54_rx_stats(dev, skb);
+ break;
+ case P54_CONTROL_TYPE_EEPROM_READBACK:
+ p54_rx_eeprom_readback(dev, skb);
+ break;
default:
printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
break;
}
+
+ return 0;
}
/* returns zero if skb can be reused */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
- switch (type) {
- case 0x00:
- case 0x01:
- p54_rx_data(dev, skb);
- return -1;
- case 0x4d:
- /* TODO: do something better... but then again, I've never seen this happen */
- printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
- wiphy_name(dev->wiphy));
- break;
- case 0x80:
- p54_rx_control(dev, skb);
- break;
- default:
- printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
- wiphy_name(dev->wiphy), type);
- break;
- }
- return 0;
+
+ if (type == 0x80)
+ return p54_rx_control(dev, skb);
+ else
+ return p54_rx_data(dev, skb);
}
EXPORT_SYMBOL_GPL(p54_rx);
@@ -503,7 +700,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
u32 target_addr = priv->rx_start;
unsigned long flags;
unsigned int left;
- len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
+ len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
spin_lock_irqsave(&priv->tx_queue.lock, flags);
left = skb_queue_len(&priv->tx_queue);
@@ -538,14 +735,74 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
range->start_addr = target_addr;
range->end_addr = target_addr + len;
__skb_queue_after(&priv->tx_queue, target_skb, skb);
- if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
+ if (largest_hole < priv->rx_mtu + priv->headroom +
+ priv->tailroom +
sizeof(struct p54_control_hdr))
ieee80211_stop_queues(dev);
}
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- data->req_id = cpu_to_le32(target_addr + 0x70);
+ data->req_id = cpu_to_le32(target_addr + priv->headroom);
+}
+
+int p54_read_eeprom(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_control_hdr *hdr = NULL;
+ struct p54_eeprom_lm86 *eeprom_hdr;
+ size_t eeprom_size = 0x2020, offset = 0, blocksize;
+ int ret = -ENOMEM;
+ void *eeprom = NULL;
+
+ hdr = (struct p54_control_hdr *)kzalloc(sizeof(*hdr) +
+ sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN, GFP_KERNEL);
+ if (!hdr)
+ goto free;
+
+ priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
+ if (!priv->eeprom)
+ goto free;
+
+ eeprom = kzalloc(eeprom_size, GFP_KERNEL);
+ if (!eeprom)
+ goto free;
+
+ hdr->magic1 = cpu_to_le16(0x8000);
+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
+ hdr->retry1 = hdr->retry2 = 0;
+ eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+
+ while (eeprom_size) {
+ blocksize = min(eeprom_size, (size_t)EEPROM_READBACK_LEN);
+ hdr->len = cpu_to_le16(blocksize + sizeof(*eeprom_hdr));
+ eeprom_hdr->offset = cpu_to_le16(offset);
+ eeprom_hdr->len = cpu_to_le16(blocksize);
+ p54_assign_address(dev, NULL, hdr, le16_to_cpu(hdr->len) +
+ sizeof(*hdr));
+ priv->tx(dev, hdr, le16_to_cpu(hdr->len) + sizeof(*hdr), 0);
+
+ if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
+ printk(KERN_ERR "%s: device does not respond!\n",
+ wiphy_name(dev->wiphy));
+ ret = -EBUSY;
+ goto free;
+ }
+
+ memcpy(eeprom + offset, priv->eeprom, blocksize);
+ offset += blocksize;
+ eeprom_size -= blocksize;
+ }
+
+ ret = p54_parse_eeprom(dev, eeprom, offset);
+free:
+ kfree(priv->eeprom);
+ priv->eeprom = NULL;
+ kfree(hdr);
+ kfree(eeprom);
+
+ return ret;
}
+EXPORT_SYMBOL_GPL(p54_read_eeprom);
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
@@ -559,7 +816,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
u8 rate;
u8 cts_rate = 0x20;
- current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)];
+ current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4];
if (unlikely(current_queue->len > current_queue->limit))
return NETDEV_TX_BUSY;
current_queue->len++;
@@ -601,7 +858,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
txhdr->hw_queue = skb_get_queue_mapping(skb) + 4;
txhdr->tx_antenna = (info->antenna_sel_tx == 0) ?
2 : info->antenna_sel_tx - 1;
- txhdr->output_power = 0x7f; // HW Maximum
+ txhdr->output_power = priv->output_power;
txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
0 : cts_rate;
if (padding)
@@ -628,12 +885,12 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
- const u8 *dst, const u8 *src, u8 antenna,
- u32 magic3, u32 magic8, u32 magic9)
+ const u8 *bssid)
{
struct p54_common *priv = dev->priv;
struct p54_control_hdr *hdr;
struct p54_tx_control_filter *filter;
+ size_t data_len;
hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
priv->tx_hdr_len, GFP_ATOMIC);
@@ -644,25 +901,35 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
filter = (struct p54_tx_control_filter *) hdr->data;
hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*filter));
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter));
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
- filter->filter_type = cpu_to_le16(filter_type);
- memcpy(filter->dst, dst, ETH_ALEN);
- if (!src)
- memset(filter->src, ~0, ETH_ALEN);
+ priv->filter_type = filter->filter_type = cpu_to_le16(filter_type);
+ memcpy(filter->mac_addr, priv->mac_addr, ETH_ALEN);
+ if (!bssid)
+ memset(filter->bssid, ~0, ETH_ALEN);
else
- memcpy(filter->src, src, ETH_ALEN);
- filter->antenna = antenna;
- filter->magic3 = cpu_to_le32(magic3);
- filter->rx_addr = cpu_to_le32(priv->rx_end);
- filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */
- filter->rxhw = priv->rxhw;
- filter->magic8 = cpu_to_le16(magic8);
- filter->magic9 = cpu_to_le16(magic9);
-
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
+ memcpy(filter->bssid, bssid, ETH_ALEN);
+
+ filter->rx_antenna = priv->rx_antenna;
+
+ if (priv->fw_var < 0x500) {
+ data_len = P54_TX_CONTROL_FILTER_V1_LEN;
+ filter->v1.basic_rate_mask = cpu_to_le32(0x15F);
+ filter->v1.rx_addr = cpu_to_le32(priv->rx_end);
+ filter->v1.max_rx = cpu_to_le16(priv->rx_mtu);
+ filter->v1.rxhw = cpu_to_le16(priv->rxhw);
+ filter->v1.wakeup_timer = cpu_to_le16(500);
+ } else {
+ data_len = P54_TX_CONTROL_FILTER_V2_LEN;
+ filter->v2.rx_addr = cpu_to_le32(priv->rx_end);
+ filter->v2.max_rx = cpu_to_le16(priv->rx_mtu);
+ filter->v2.rxhw = cpu_to_le16(priv->rxhw);
+ filter->v2.timer = cpu_to_le16(1000);
+ }
+
+ hdr->len = cpu_to_le16(data_len);
+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
+ priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
return 0;
}
@@ -672,12 +939,10 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
struct p54_control_hdr *hdr;
struct p54_tx_control_channel *chan;
unsigned int i;
- size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
- sizeof(*chan->curve_data) *
- priv->curve_data->points_per_channel;
+ size_t data_len;
void *entry;
- hdr = kzalloc(sizeof(*hdr) + payload_len +
+ hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
priv->tx_hdr_len, GFP_KERNEL);
if (!hdr)
return -ENOMEM;
@@ -687,12 +952,11 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
chan = (struct p54_tx_control_channel *) hdr->data;
hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*chan));
+
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len);
- chan->magic1 = cpu_to_le16(0x1);
- chan->magic2 = cpu_to_le16(0x0);
+ chan->flags = cpu_to_le16(0x1);
+ chan->dwell = cpu_to_le16(0x0);
for (i = 0; i < priv->iq_autocal_len; i++) {
if (priv->iq_autocal[i].freq != freq)
@@ -710,35 +974,51 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
continue;
chan->val_barker = 0x38;
- chan->val_bpsk = priv->output_limit[i].val_bpsk;
- chan->val_qpsk = priv->output_limit[i].val_qpsk;
- chan->val_16qam = priv->output_limit[i].val_16qam;
- chan->val_64qam = priv->output_limit[i].val_64qam;
+ chan->val_bpsk = chan->dup_bpsk =
+ priv->output_limit[i].val_bpsk;
+ chan->val_qpsk = chan->dup_qpsk =
+ priv->output_limit[i].val_qpsk;
+ chan->val_16qam = chan->dup_16qam =
+ priv->output_limit[i].val_16qam;
+ chan->val_64qam = chan->dup_64qam =
+ priv->output_limit[i].val_64qam;
break;
}
if (i == priv->output_limit_len)
goto err;
- chan->pa_points_per_curve = priv->curve_data->points_per_channel;
-
entry = priv->curve_data->data;
for (i = 0; i < priv->curve_data->channels; i++) {
if (*((__le16 *)entry) != freq) {
entry += sizeof(__le16);
- entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
- chan->pa_points_per_curve;
+ entry += sizeof(struct p54_pa_curve_data_sample) *
+ priv->curve_data->points_per_channel;
continue;
}
entry += sizeof(__le16);
+ chan->pa_points_per_curve =
+ min(priv->curve_data->points_per_channel, (u8) 8);
+
memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
chan->pa_points_per_curve);
break;
}
- memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
+ if (priv->fw_var < 0x500) {
+ data_len = P54_TX_CONTROL_CHANNEL_V1_LEN;
+ chan->v1.rssical_mul = cpu_to_le16(130);
+ chan->v1.rssical_add = cpu_to_le16(0xfe70);
+ } else {
+ data_len = P54_TX_CONTROL_CHANNEL_V2_LEN;
+ chan->v2.rssical_mul = cpu_to_le16(130);
+ chan->v2.rssical_add = cpu_to_le16(0xfe70);
+ chan->v2.basic_rate_mask = cpu_to_le32(0x15f);
+ }
- priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
+ hdr->len = cpu_to_le16(data_len);
+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
+ priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
return 0;
err:
@@ -846,12 +1126,25 @@ static int p54_start(struct ieee80211_hw *dev)
return -ENOMEM;
}
+ if (!priv->cached_stats) {
+ priv->cached_stats = kzalloc(sizeof(struct p54_statistics) +
+ priv->tx_hdr_len + sizeof(struct p54_control_hdr),
+ GFP_KERNEL);
+
+ if (!priv->cached_stats) {
+ kfree(priv->cached_vdcf);
+ priv->cached_vdcf = NULL;
+ return -ENOMEM;
+ }
+ }
+
err = priv->open(dev);
if (!err)
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
p54_init_vdcf(dev);
+ mod_timer(&priv->stats_timer, jiffies + HZ);
return err;
}
@@ -859,10 +1152,13 @@ static void p54_stop(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
struct sk_buff *skb;
+
+ del_timer(&priv->stats_timer);
while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);
priv->stop(dev);
- priv->mode = IEEE80211_IF_TYPE_INVALID;
+ priv->tsf_high32 = priv->tsf_low32 = 0;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
}
static int p54_add_interface(struct ieee80211_hw *dev,
@@ -870,11 +1166,11 @@ static int p54_add_interface(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@@ -883,12 +1179,11 @@ static int p54_add_interface(struct ieee80211_hw *dev,
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
- p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
- p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
+ p54_set_filter(dev, 0, NULL);
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
- p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
+ case NL80211_IFTYPE_STATION:
+ p54_set_filter(dev, 1, NULL);
break;
default:
BUG(); /* impossible */
@@ -904,9 +1199,9 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct p54_common *priv = dev->priv;
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
memset(priv->mac_addr, 0, ETH_ALEN);
- p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
+ p54_set_filter(dev, 0, NULL);
}
static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
@@ -915,6 +1210,9 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
struct p54_common *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
+ priv->rx_antenna = (conf->antenna_sel_rx == 0) ?
+ 2 : conf->antenna_sel_tx - 1;
+ priv->output_power = conf->power_level << 2;
ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
p54_set_vdcf(dev);
mutex_unlock(&priv->conf_mutex);
@@ -928,8 +1226,7 @@ static int p54_config_interface(struct ieee80211_hw *dev,
struct p54_common *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
+ p54_set_filter(dev, 0, conf->bssid);
p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
mutex_unlock(&priv->conf_mutex);
@@ -943,15 +1240,28 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- *total_flags &= FIF_BCN_PRBRESP_PROMISC;
+ *total_flags &= FIF_BCN_PRBRESP_PROMISC |
+ FIF_PROMISC_IN_BSS |
+ FIF_FCSFAIL;
+
+ priv->filter_flags = *total_flags;
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
- p54_set_filter(dev, 0, priv->mac_addr,
- NULL, 2, 0, 0, 0);
+ p54_set_filter(dev, le16_to_cpu(priv->filter_type),
+ NULL);
+ else
+ p54_set_filter(dev, le16_to_cpu(priv->filter_type),
+ priv->bssid);
+ }
+
+ if (changed_flags & FIF_PROMISC_IN_BSS) {
+ if (*total_flags & FIF_PROMISC_IN_BSS)
+ p54_set_filter(dev, le16_to_cpu(priv->filter_type) |
+ 0x8, NULL);
else
- p54_set_filter(dev, 0, priv->mac_addr,
- priv->bssid, 2, 0, 0, 0);
+ p54_set_filter(dev, le16_to_cpu(priv->filter_type) &
+ ~0x8, priv->bssid);
}
}
@@ -975,10 +1285,67 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
return 0;
}
+static int p54_init_xbow_synth(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_control_hdr *hdr;
+ struct p54_tx_control_xbow_synth *xbow;
+
+ hdr = kzalloc(sizeof(*hdr) + sizeof(*xbow) +
+ priv->tx_hdr_len, GFP_KERNEL);
+ if (!hdr)
+ return -ENOMEM;
+
+ hdr = (void *)hdr + priv->tx_hdr_len;
+ hdr->magic1 = cpu_to_le16(0x8001);
+ hdr->len = cpu_to_le16(sizeof(*xbow));
+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_XBOW_SYNTH_CFG);
+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*xbow));
+
+ xbow = (struct p54_tx_control_xbow_synth *) hdr->data;
+ xbow->magic1 = cpu_to_le16(0x1);
+ xbow->magic2 = cpu_to_le16(0x2);
+ xbow->freq = cpu_to_le16(5390);
+
+ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*xbow), 1);
+
+ return 0;
+}
+
+static void p54_statistics_timer(unsigned long data)
+{
+ struct ieee80211_hw *dev = (struct ieee80211_hw *) data;
+ struct p54_common *priv = dev->priv;
+ struct p54_control_hdr *hdr;
+ struct p54_statistics *stats;
+
+ BUG_ON(!priv->cached_stats);
+
+ hdr = (void *)priv->cached_stats + priv->tx_hdr_len;
+ hdr->magic1 = cpu_to_le16(0x8000);
+ hdr->len = cpu_to_le16(sizeof(*stats));
+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_STAT_READBACK);
+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*stats));
+
+ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*stats), 0);
+}
+
static int p54_get_stats(struct ieee80211_hw *dev,
struct ieee80211_low_level_stats *stats)
{
- /* TODO */
+ struct p54_common *priv = dev->priv;
+
+ del_timer(&priv->stats_timer);
+ p54_statistics_timer((unsigned long)dev);
+
+ if (!wait_for_completion_interruptible_timeout(&priv->stats_comp, HZ)) {
+ printk(KERN_ERR "%s: device does not respond!\n",
+ wiphy_name(dev->wiphy));
+ return -EBUSY;
+ }
+
+ memcpy(stats, &priv->stats, sizeof(*stats));
+
return 0;
}
@@ -987,7 +1354,7 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- memcpy(stats, &priv->tx_stats, sizeof(stats[0]) * dev->queues);
+ memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues);
return 0;
}
@@ -1016,22 +1383,32 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
return NULL;
priv = dev->priv;
- priv->mode = IEEE80211_IF_TYPE_INVALID;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
skb_queue_head_init(&priv->tx_queue);
- dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SIGNAL_UNSPEC;
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
+
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
dev->channel_change_time = 1000; /* TODO: find actual value */
- dev->max_signal = 127;
- priv->tx_stats[0].limit = 5;
+ priv->tx_stats[0].limit = 1;
+ priv->tx_stats[1].limit = 1;
+ priv->tx_stats[2].limit = 1;
+ priv->tx_stats[3].limit = 1;
+ priv->tx_stats[4].limit = 5;
dev->queues = 1;
-
+ priv->noise = -94;
dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
sizeof(struct p54_tx_control_allocdata);
mutex_init(&priv->conf_mutex);
+ init_completion(&priv->eeprom_comp);
+ init_completion(&priv->stats_comp);
+ setup_timer(&priv->stats_timer, p54_statistics_timer,
+ (unsigned long)dev);
return dev;
}
@@ -1040,6 +1417,7 @@ EXPORT_SYMBOL_GPL(p54_init_common);
void p54_free_common(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
+ kfree(priv->cached_stats);
kfree(priv->iq_autocal);
kfree(priv->output_limit);
kfree(priv->curve_data);
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index 8db6c0e8e54..2fa994cfcfe 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -1,5 +1,5 @@
-#ifndef PRISM54COMMON_H
-#define PRISM54COMMON_H
+#ifndef P54COMMON_H
+#define P54COMMON_H
/*
* Common code specific definitions for mac80211 Prism54 drivers
@@ -18,7 +18,8 @@
struct bootrec {
__le32 code;
__le32 len;
- u32 data[0];
+ u32 data[10];
+ __le16 rx_mtu;
} __attribute__((packed));
struct bootrec_exp_if {
@@ -29,6 +30,17 @@ struct bootrec_exp_if {
__le16 top_compat;
} __attribute__((packed));
+struct bootrec_desc {
+ __le16 modes;
+ __le16 flags;
+ __le32 rx_start;
+ __le32 rx_end;
+ u8 headroom;
+ u8 tailroom;
+ u8 unimportant[6];
+ u8 rates[16];
+} __attribute__((packed));
+
#define BR_CODE_MIN 0x80000000
#define BR_CODE_COMPONENT_ID 0x80000001
#define BR_CODE_COMPONENT_VERSION 0x80000002
@@ -39,11 +51,6 @@ struct bootrec_exp_if {
#define BR_CODE_END_OF_BRA 0xFF0000FF
#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
-#define FW_FMAC 0x464d4143
-#define FW_LM86 0x4c4d3836
-#define FW_LM87 0x4c4d3837
-#define FW_LM20 0x4c4d3230
-
/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
struct pda_entry {
@@ -89,6 +96,16 @@ struct pda_pa_curve_data_sample_rev1 {
u8 data_qpsk;
u8 data_16qam;
u8 data_64qam;
+} __attribute__ ((packed));
+
+struct p54_pa_curve_data_sample {
+ u8 rf_power;
+ u8 pa_detector;
+ u8 data_barker;
+ u8 data_bpsk;
+ u8 data_qpsk;
+ u8 data_16qam;
+ u8 data_64qam;
u8 padding;
} __attribute__ ((packed));
@@ -169,8 +186,9 @@ struct p54_rx_hdr {
u8 rssi;
u8 quality;
u16 unknown2;
- __le64 timestamp;
- u8 data[0];
+ __le32 tsf32;
+ __le32 unalloc0;
+ u8 align[0];
} __attribute__ ((packed));
struct p54_frame_sent_hdr {
@@ -198,22 +216,37 @@ struct p54_tx_control_allocdata {
struct p54_tx_control_filter {
__le16 filter_type;
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 antenna;
- u8 debug;
- __le32 magic3;
- u8 rates[8]; // FIXME: what's this for?
- __le32 rx_addr;
- __le16 max_rx;
- __le16 rxhw;
- __le16 magic8;
- __le16 magic9;
+ u8 mac_addr[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ u8 rx_antenna;
+ u8 rx_align;
+ union {
+ struct {
+ __le32 basic_rate_mask;
+ u8 rts_rates[8];
+ __le32 rx_addr;
+ __le16 max_rx;
+ __le16 rxhw;
+ __le16 wakeup_timer;
+ __le16 unalloc0;
+ } v1 __attribute__ ((packed));
+ struct {
+ __le32 rx_addr;
+ __le16 max_rx;
+ __le16 rxhw;
+ __le16 timer;
+ __le16 unalloc0;
+ __le32 unalloc1;
+ } v2 __attribute__ ((packed));
+ } __attribute__ ((packed));
} __attribute__ ((packed));
+#define P54_TX_CONTROL_FILTER_V1_LEN (sizeof(struct p54_tx_control_filter))
+#define P54_TX_CONTROL_FILTER_V2_LEN (sizeof(struct p54_tx_control_filter)-8)
+
struct p54_tx_control_channel {
- __le16 magic1;
- __le16 magic2;
+ __le16 flags;
+ __le16 dwell;
u8 padding1[20];
struct pda_iq_autocal_entry iq_autocal;
u8 pa_points_per_curve;
@@ -222,10 +255,29 @@ struct p54_tx_control_channel {
u8 val_qpsk;
u8 val_16qam;
u8 val_64qam;
- struct pda_pa_curve_data_sample_rev1 curve_data[0];
- /* additional padding/data after curve_data */
+ struct p54_pa_curve_data_sample curve_data[8];
+ u8 dup_bpsk;
+ u8 dup_qpsk;
+ u8 dup_16qam;
+ u8 dup_64qam;
+ union {
+ struct {
+ __le16 rssical_mul;
+ __le16 rssical_add;
+ } v1 __attribute__ ((packed));
+
+ struct {
+ __le32 basic_rate_mask;
+ u8 rts_rates[8];
+ __le16 rssical_mul;
+ __le16 rssical_add;
+ } v2 __attribute__ ((packed));
+ } __attribute__ ((packed));
} __attribute__ ((packed));
+#define P54_TX_CONTROL_CHANNEL_V1_LEN (sizeof(struct p54_tx_control_channel)-12)
+#define P54_TX_CONTROL_CHANNEL_V2_LEN (sizeof(struct p54_tx_control_channel))
+
struct p54_tx_control_led {
__le16 mode;
__le16 led_temporary;
@@ -250,4 +302,24 @@ struct p54_tx_control_vdcf {
__le16 frameburst;
} __attribute__ ((packed));
-#endif /* PRISM54COMMON_H */
+struct p54_statistics {
+ __le32 rx_success;
+ __le32 rx_bad_fcs;
+ __le32 rx_abort;
+ __le32 rx_abort_phy;
+ __le32 rts_success;
+ __le32 rts_fail;
+ __le32 tsf32;
+ __le32 airtime;
+ __le32 noise;
+ __le32 unkn[10]; /* CCE / CCA / RADAR */
+} __attribute__ ((packed));
+
+struct p54_tx_control_xbow_synth {
+ __le16 magic1;
+ __le16 magic2;
+ __le16 freq;
+ u32 padding[5];
+} __attribute__ ((packed));
+
+#endif /* P54COMMON_H */
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 7dd4add4bf4..1c2a02a741a 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -3,6 +3,7 @@
* Linux device driver for PCI based Prism54
*
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2008, Christian Lamparter <chunkeey@web.de>
*
* Based on the islsm (softmac prism54) driver, which is:
* Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al.
@@ -71,16 +72,18 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
P54P_WRITE(ctrl_stat, reg);
wmb();
- mdelay(50);
-
err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
if (err) {
- printk(KERN_ERR "%s (prism54pci): cannot find firmware "
+ printk(KERN_ERR "%s (p54pci): cannot find firmware "
"(isl3886)\n", pci_name(priv->pdev));
return err;
}
- p54_parse_firmware(dev, fw_entry);
+ err = p54_parse_firmware(dev, fw_entry);
+ if (err) {
+ release_firmware(fw_entry);
+ return err;
+ }
data = (__le32 *) fw_entry->data;
remains = fw_entry->size;
@@ -121,162 +124,147 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
wmb();
udelay(10);
+ /* wait for the firmware to boot properly */
+ mdelay(100);
+
return 0;
}
-static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
+static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
+ int ring_index, struct p54p_desc *ring, u32 ring_limit,
+ struct sk_buff **rx_buf)
{
- struct p54p_priv *priv = (struct p54p_priv *) dev_id;
- __le32 reg;
-
- reg = P54P_READ(int_ident);
- P54P_WRITE(int_ack, reg);
+ struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
+ u32 limit, idx, i;
- if (reg & P54P_READ(int_enable))
- complete(&priv->boot_comp);
+ idx = le32_to_cpu(ring_control->host_idx[ring_index]);
+ limit = idx;
+ limit -= le32_to_cpu(ring_control->device_idx[ring_index]);
+ limit = ring_limit - limit;
- return IRQ_HANDLED;
-}
+ i = idx % ring_limit;
+ while (limit-- > 1) {
+ struct p54p_desc *desc = &ring[i];
-static int p54p_read_eeprom(struct ieee80211_hw *dev)
-{
- struct p54p_priv *priv = dev->priv;
- struct p54p_ring_control *ring_control = priv->ring_control;
- int err;
- struct p54_control_hdr *hdr;
- void *eeprom;
- dma_addr_t rx_mapping, tx_mapping;
- u16 alen;
+ if (!desc->host_addr) {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ skb = dev_alloc_skb(priv->common.rx_mtu + 32);
+ if (!skb)
+ break;
- init_completion(&priv->boot_comp);
- err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
- IRQF_SHARED, "prism54pci", priv);
- if (err) {
- printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
- pci_name(priv->pdev));
- return err;
- }
+ mapping = pci_map_single(priv->pdev,
+ skb_tail_pointer(skb),
+ priv->common.rx_mtu + 32,
+ PCI_DMA_FROMDEVICE);
+ desc->host_addr = cpu_to_le32(mapping);
+ desc->device_addr = 0; // FIXME: necessary?
+ desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
+ desc->flags = 0;
+ rx_buf[i] = skb;
+ }
- eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
- if (!eeprom) {
- printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
- pci_name(priv->pdev));
- err = -ENOMEM;
- goto out;
+ i++;
+ idx++;
+ i %= ring_limit;
}
- memset(ring_control, 0, sizeof(*ring_control));
- P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
- P54P_READ(ring_control_base);
- udelay(10);
-
- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
- P54P_READ(int_enable);
- udelay(10);
+ wmb();
+ ring_control->host_idx[ring_index] = cpu_to_le32(idx);
+}
- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
+ int ring_index, struct p54p_desc *ring, u32 ring_limit,
+ struct sk_buff **rx_buf)
+{
+ struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
+ struct p54p_desc *desc;
+ u32 idx, i;
+
+ i = (*index) % ring_limit;
+ (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
+ idx %= ring_limit;
+ while (i != idx) {
+ u16 len;
+ struct sk_buff *skb;
+ desc = &ring[i];
+ len = le16_to_cpu(desc->len);
+ skb = rx_buf[i];
+
+ if (!skb) {
+ i++;
+ i %= ring_limit;
+ continue;
+ }
+ skb_put(skb, len);
+
+ if (p54_rx(dev, skb)) {
+ pci_unmap_single(priv->pdev,
+ le32_to_cpu(desc->host_addr),
+ priv->common.rx_mtu + 32,
+ PCI_DMA_FROMDEVICE);
+ rx_buf[i] = NULL;
+ desc->host_addr = 0;
+ } else {
+ skb_trim(skb, 0);
+ desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
+ }
- if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
- printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
- pci_name(priv->pdev));
- err = -EINVAL;
- goto out;
+ i++;
+ i %= ring_limit;
}
- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
- P54P_READ(int_enable);
+ p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
+}
- hdr = eeprom + 0x2010;
- p54_fill_eeprom_readback(hdr);
- hdr->req_id = cpu_to_le32(priv->common.rx_start);
+/* caller must hold priv->lock */
+static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
+ int ring_index, struct p54p_desc *ring, u32 ring_limit,
+ void **tx_buf)
+{
+ struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
+ struct p54p_desc *desc;
+ u32 idx, i;
- rx_mapping = pci_map_single(priv->pdev, eeprom,
- 0x2010, PCI_DMA_FROMDEVICE);
- tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
+ i = (*index) % ring_limit;
+ (*index) = idx = le32_to_cpu(ring_control->device_idx[1]);
+ idx %= ring_limit;
- ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
- ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
- ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
- ring_control->tx_data[0].device_addr = hdr->req_id;
- ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
+ while (i != idx) {
+ desc = &ring[i];
+ kfree(tx_buf[i]);
+ tx_buf[i] = NULL;
- ring_control->host_idx[2] = cpu_to_le32(1);
- ring_control->host_idx[1] = cpu_to_le32(1);
+ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+ le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
- wmb();
- mdelay(100);
- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+ desc->host_addr = 0;
+ desc->device_addr = 0;
+ desc->len = 0;
+ desc->flags = 0;
- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
-
- pci_unmap_single(priv->pdev, tx_mapping,
- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
- pci_unmap_single(priv->pdev, rx_mapping,
- 0x2010, PCI_DMA_FROMDEVICE);
-
- alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
- if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
- alen < 0x10) {
- printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
- pci_name(priv->pdev));
- err = -EINVAL;
- goto out;
+ i++;
+ i %= ring_limit;
}
-
- p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
-
- out:
- kfree(eeprom);
- P54P_WRITE(int_enable, cpu_to_le32(0));
- P54P_READ(int_enable);
- udelay(10);
- free_irq(priv->pdev->irq, priv);
- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
- return err;
}
-static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
+static void p54p_rx_tasklet(unsigned long dev_id)
{
+ struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
struct p54p_priv *priv = dev->priv;
struct p54p_ring_control *ring_control = priv->ring_control;
- u32 limit, host_idx, idx;
- host_idx = le32_to_cpu(ring_control->host_idx[0]);
- limit = host_idx;
- limit -= le32_to_cpu(ring_control->device_idx[0]);
- limit = ARRAY_SIZE(ring_control->rx_data) - limit;
-
- idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
- while (limit-- > 1) {
- struct p54p_desc *desc = &ring_control->rx_data[idx];
-
- if (!desc->host_addr) {
- struct sk_buff *skb;
- dma_addr_t mapping;
- skb = dev_alloc_skb(MAX_RX_SIZE);
- if (!skb)
- break;
-
- mapping = pci_map_single(priv->pdev,
- skb_tail_pointer(skb),
- MAX_RX_SIZE,
- PCI_DMA_FROMDEVICE);
- desc->host_addr = cpu_to_le32(mapping);
- desc->device_addr = 0; // FIXME: necessary?
- desc->len = cpu_to_le16(MAX_RX_SIZE);
- desc->flags = 0;
- priv->rx_buf[idx] = skb;
- }
+ p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
+ ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
- idx++;
- host_idx++;
- idx %= ARRAY_SIZE(ring_control->rx_data);
- }
+ p54p_check_rx_ring(dev, &priv->rx_idx_data, 0, ring_control->rx_data,
+ ARRAY_SIZE(ring_control->rx_data), priv->rx_buf_data);
wmb();
- ring_control->host_idx[0] = cpu_to_le32(host_idx);
+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
}
static irqreturn_t p54p_interrupt(int irq, void *dev_id)
@@ -298,65 +286,18 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
reg &= P54P_READ(int_enable);
if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
- struct p54p_desc *desc;
- u32 idx, i;
- i = priv->tx_idx;
- i %= ARRAY_SIZE(ring_control->tx_data);
- priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
- idx %= ARRAY_SIZE(ring_control->tx_data);
-
- while (i != idx) {
- desc = &ring_control->tx_data[i];
- if (priv->tx_buf[i]) {
- kfree(priv->tx_buf[i]);
- priv->tx_buf[i] = NULL;
- }
-
- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
-
- desc->host_addr = 0;
- desc->device_addr = 0;
- desc->len = 0;
- desc->flags = 0;
-
- i++;
- i %= ARRAY_SIZE(ring_control->tx_data);
- }
-
- i = priv->rx_idx;
- i %= ARRAY_SIZE(ring_control->rx_data);
- priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
- idx %= ARRAY_SIZE(ring_control->rx_data);
- while (i != idx) {
- u16 len;
- struct sk_buff *skb;
- desc = &ring_control->rx_data[i];
- len = le16_to_cpu(desc->len);
- skb = priv->rx_buf[i];
+ p54p_check_tx_ring(dev, &priv->tx_idx_mgmt,
+ 3, ring_control->tx_mgmt,
+ ARRAY_SIZE(ring_control->tx_mgmt),
+ priv->tx_buf_mgmt);
- skb_put(skb, len);
+ p54p_check_tx_ring(dev, &priv->tx_idx_data,
+ 1, ring_control->tx_data,
+ ARRAY_SIZE(ring_control->tx_data),
+ priv->tx_buf_data);
- if (p54_rx(dev, skb)) {
- pci_unmap_single(priv->pdev,
- le32_to_cpu(desc->host_addr),
- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+ tasklet_schedule(&priv->rx_tasklet);
- priv->rx_buf[i] = NULL;
- desc->host_addr = 0;
- } else {
- skb_trim(skb, 0);
- desc->len = cpu_to_le16(MAX_RX_SIZE);
- }
-
- i++;
- i %= ARRAY_SIZE(ring_control->rx_data);
- }
-
- p54p_refill_rx_ring(dev);
-
- wmb();
- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
} else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
complete(&priv->boot_comp);
@@ -392,7 +333,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
ring_control->host_idx[1] = cpu_to_le32(idx + 1);
if (free_on_tx)
- priv->tx_buf[i] = data;
+ priv->tx_buf_data[i] = data;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -412,7 +353,7 @@ static int p54p_open(struct ieee80211_hw *dev)
init_completion(&priv->boot_comp);
err = request_irq(priv->pdev->irq, &p54p_interrupt,
- IRQF_SHARED, "prism54pci", dev);
+ IRQF_SHARED, "p54pci", dev);
if (err) {
printk(KERN_ERR "%s: failed to register IRQ handler\n",
wiphy_name(dev->wiphy));
@@ -420,10 +361,19 @@ static int p54p_open(struct ieee80211_hw *dev)
}
memset(priv->ring_control, 0, sizeof(*priv->ring_control));
- priv->rx_idx = priv->tx_idx = 0;
- p54p_refill_rx_ring(dev);
+ err = p54p_upload_firmware(dev);
+ if (err) {
+ free_irq(priv->pdev->irq, dev);
+ return err;
+ }
+ priv->rx_idx_data = priv->tx_idx_data = 0;
+ priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0;
+
+ p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data,
+ ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data);
- p54p_upload_firmware(dev);
+ p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt,
+ ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt);
P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
P54P_READ(ring_control_base);
@@ -465,6 +415,8 @@ static void p54p_stop(struct ieee80211_hw *dev)
unsigned int i;
struct p54p_desc *desc;
+ tasklet_kill(&priv->rx_tasklet);
+
P54P_WRITE(int_enable, cpu_to_le32(0));
P54P_READ(int_enable);
udelay(10);
@@ -473,26 +425,53 @@ static void p54p_stop(struct ieee80211_hw *dev)
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
- for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
+ for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
desc = &ring_control->rx_data[i];
if (desc->host_addr)
- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
- kfree_skb(priv->rx_buf[i]);
- priv->rx_buf[i] = NULL;
+ pci_unmap_single(priv->pdev,
+ le32_to_cpu(desc->host_addr),
+ priv->common.rx_mtu + 32,
+ PCI_DMA_FROMDEVICE);
+ kfree_skb(priv->rx_buf_data[i]);
+ priv->rx_buf_data[i] = NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(priv->rx_buf_mgmt); i++) {
+ desc = &ring_control->rx_mgmt[i];
+ if (desc->host_addr)
+ pci_unmap_single(priv->pdev,
+ le32_to_cpu(desc->host_addr),
+ priv->common.rx_mtu + 32,
+ PCI_DMA_FROMDEVICE);
+ kfree_skb(priv->rx_buf_mgmt[i]);
+ priv->rx_buf_mgmt[i] = NULL;
}
- for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
+ for (i = 0; i < ARRAY_SIZE(priv->tx_buf_data); i++) {
desc = &ring_control->tx_data[i];
if (desc->host_addr)
- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
+ pci_unmap_single(priv->pdev,
+ le32_to_cpu(desc->host_addr),
+ le16_to_cpu(desc->len),
+ PCI_DMA_TODEVICE);
- kfree(priv->tx_buf[i]);
- priv->tx_buf[i] = NULL;
+ kfree(priv->tx_buf_data[i]);
+ priv->tx_buf_data[i] = NULL;
}
- memset(ring_control, 0, sizeof(ring_control));
+ for (i = 0; i < ARRAY_SIZE(priv->tx_buf_mgmt); i++) {
+ desc = &ring_control->tx_mgmt[i];
+ if (desc->host_addr)
+ pci_unmap_single(priv->pdev,
+ le32_to_cpu(desc->host_addr),
+ le16_to_cpu(desc->len),
+ PCI_DMA_TODEVICE);
+
+ kfree(priv->tx_buf_mgmt[i]);
+ priv->tx_buf_mgmt[i] = NULL;
+ }
+
+ memset(ring_control, 0, sizeof(*ring_control));
}
static int __devinit p54p_probe(struct pci_dev *pdev,
@@ -506,7 +485,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err) {
- printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
+ printk(KERN_ERR "%s (p54pci): Cannot enable new PCI device\n",
pci_name(pdev));
return err;
}
@@ -514,22 +493,22 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
mem_addr = pci_resource_start(pdev, 0);
mem_len = pci_resource_len(pdev, 0);
if (mem_len < sizeof(struct p54p_csr)) {
- printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
+ printk(KERN_ERR "%s (p54pci): Too short PCI resources\n",
pci_name(pdev));
pci_disable_device(pdev);
return err;
}
- err = pci_request_regions(pdev, "prism54pci");
+ err = pci_request_regions(pdev, "p54pci");
if (err) {
- printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
+ printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n",
pci_name(pdev));
return err;
}
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
- printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
+ printk(KERN_ERR "%s (p54pci): No suitable DMA available\n",
pci_name(pdev));
goto err_free_reg;
}
@@ -542,7 +521,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
dev = p54_init_common(sizeof(*priv));
if (!dev) {
- printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
+ printk(KERN_ERR "%s (p54pci): ieee80211 alloc failed\n",
pci_name(pdev));
err = -ENOMEM;
goto err_free_reg;
@@ -556,7 +535,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
priv->map = ioremap(mem_addr, mem_len);
if (!priv->map) {
- printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
+ printk(KERN_ERR "%s (p54pci): Cannot map device memory\n",
pci_name(pdev));
err = -EINVAL; // TODO: use a better error code?
goto err_free_dev;
@@ -565,39 +544,31 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
&priv->ring_control_dma);
if (!priv->ring_control) {
- printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
+ printk(KERN_ERR "%s (p54pci): Cannot allocate rings\n",
pci_name(pdev));
err = -ENOMEM;
goto err_iounmap;
}
- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
-
- err = p54p_upload_firmware(dev);
- if (err)
- goto err_free_desc;
-
- err = p54p_read_eeprom(dev);
- if (err)
- goto err_free_desc;
-
priv->common.open = p54p_open;
priv->common.stop = p54p_stop;
priv->common.tx = p54p_tx;
spin_lock_init(&priv->lock);
+ tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
+
+ p54p_open(dev);
+ err = p54_read_eeprom(dev);
+ p54p_stop(dev);
+ if (err)
+ goto err_free_desc;
err = ieee80211_register_hw(dev);
if (err) {
- printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
+ printk(KERN_ERR "%s (p54pci): Cannot register netdevice\n",
pci_name(pdev));
goto err_free_common;
}
- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
- wiphy_name(dev->wiphy),
- print_mac(mac, dev->wiphy->perm_addr),
- priv->common.version);
-
return 0;
err_free_common:
@@ -645,7 +616,7 @@ static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct p54p_priv *priv = dev->priv;
- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+ if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
ieee80211_stop_queues(dev);
p54p_stop(dev);
}
@@ -663,7 +634,7 @@ static int p54p_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+ if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
p54p_open(dev);
ieee80211_wake_queues(dev);
}
@@ -673,7 +644,7 @@ static int p54p_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
static struct pci_driver p54p_driver = {
- .name = "prism54pci",
+ .name = "p54pci",
.id_table = p54p_table,
.probe = p54p_probe,
.remove = __devexit_p(p54p_remove),
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index 5bedd7af385..4a6778070af 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -1,5 +1,5 @@
-#ifndef PRISM54PCI_H
-#define PRISM54PCI_H
+#ifndef P54PCI_H
+#define P54PCI_H
/*
* Defines for PCI based mac80211 Prism54 driver
@@ -68,7 +68,7 @@ struct p54p_csr {
} __attribute__ ((packed));
/* usb backend only needs the register defines above */
-#ifndef PRISM54USB_H
+#ifndef P54USB_H
struct p54p_desc {
__le32 host_addr;
__le32 device_addr;
@@ -92,15 +92,19 @@ struct p54p_priv {
struct p54_common common;
struct pci_dev *pdev;
struct p54p_csr __iomem *map;
+ struct tasklet_struct rx_tasklet;
spinlock_t lock;
struct p54p_ring_control *ring_control;
dma_addr_t ring_control_dma;
- u32 rx_idx, tx_idx;
- struct sk_buff *rx_buf[8];
- void *tx_buf[32];
+ u32 rx_idx_data, tx_idx_data;
+ u32 rx_idx_mgmt, tx_idx_mgmt;
+ struct sk_buff *rx_buf_data[8];
+ struct sk_buff *rx_buf_mgmt[4];
+ void *tx_buf_data[32];
+ void *tx_buf_mgmt[4];
struct completion boot_comp;
};
-#endif /* PRISM54USB_H */
-#endif /* PRISM54PCI_H */
+#endif /* P54USB_H */
+#endif /* P54PCI_H */
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index cbaca23a945..75d749bccb0 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -39,6 +39,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
{USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
{USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
+ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
{USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
{USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
@@ -63,8 +64,8 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
{USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
{USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
- {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
{USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
+ {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
{USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
@@ -91,11 +92,16 @@ static void p54u_rx_cb(struct urb *urb)
skb_unlink(skb, &priv->rx_queue);
skb_put(skb, urb->actual_length);
- if (!priv->hw_type)
- skb_pull(skb, sizeof(struct net2280_tx_hdr));
+
+ if (priv->hw_type == P54U_NET2280)
+ skb_pull(skb, priv->common.tx_hdr_len);
+ if (priv->common.fw_interface == FW_LM87) {
+ skb_pull(skb, 4);
+ skb_put(skb, 4);
+ }
if (p54_rx(dev, skb)) {
- skb = dev_alloc_skb(MAX_RX_SIZE);
+ skb = dev_alloc_skb(priv->common.rx_mtu + 32);
if (unlikely(!skb)) {
usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
@@ -109,9 +115,12 @@ static void p54u_rx_cb(struct urb *urb)
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
} else {
- if (!priv->hw_type)
- skb_push(skb, sizeof(struct net2280_tx_hdr));
-
+ if (priv->hw_type == P54U_NET2280)
+ skb_push(skb, priv->common.tx_hdr_len);
+ if (priv->common.fw_interface == FW_LM87) {
+ skb_push(skb, 4);
+ skb_put(skb, 4);
+ }
skb_reset_tail_pointer(skb);
skb_trim(skb, 0);
if (urb->transfer_buffer != skb_tail_pointer(skb)) {
@@ -145,7 +154,7 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
struct p54u_rx_info *info;
while (skb_queue_len(&priv->rx_queue) < 32) {
- skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
+ skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
if (!skb)
break;
entry = usb_alloc_urb(0, GFP_KERNEL);
@@ -153,7 +162,10 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
kfree_skb(skb);
break;
}
- usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
+ usb_fill_bulk_urb(entry, priv->udev,
+ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb_tail_pointer(skb),
+ priv->common.rx_mtu + 32, p54u_rx_cb, skb);
info = (struct p54u_rx_info *) skb->cb;
info->urb = entry;
info->dev = dev;
@@ -207,6 +219,42 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
usb_submit_urb(data_urb, GFP_ATOMIC);
}
+static __le32 p54u_lm87_chksum(const u32 *data, size_t length)
+{
+ u32 chk = 0;
+
+ length >>= 2;
+ while (length--) {
+ chk ^= *data++;
+ chk = (chk >> 5) ^ (chk << 3);
+ }
+
+ return cpu_to_le32(chk);
+}
+
+static void p54u_tx_lm87(struct ieee80211_hw *dev,
+ struct p54_control_hdr *data,
+ size_t len, int free_on_tx)
+{
+ struct p54u_priv *priv = dev->priv;
+ struct urb *data_urb;
+ struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
+
+ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!data_urb)
+ return;
+
+ hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
+ hdr->device_addr = data->req_id;
+
+ usb_fill_bulk_urb(data_urb, priv->udev,
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
+ len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
+ dev);
+
+ usb_submit_urb(data_urb, GFP_ATOMIC);
+}
+
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
size_t len, int free_on_tx)
{
@@ -312,73 +360,6 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
data, len, &alen, 2000);
}
-static int p54u_read_eeprom(struct ieee80211_hw *dev)
-{
- struct p54u_priv *priv = dev->priv;
- void *buf;
- struct p54_control_hdr *hdr;
- int err, alen;
- size_t offset = priv->hw_type ? 0x10 : 0x20;
-
- buf = kmalloc(0x2020, GFP_KERNEL);
- if (!buf) {
- printk(KERN_ERR "prism54usb: cannot allocate memory for "
- "eeprom readback!\n");
- return -ENOMEM;
- }
-
- if (priv->hw_type) {
- *((u32 *) buf) = priv->common.rx_start;
- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
- if (err) {
- printk(KERN_ERR "prism54usb: addr send failed\n");
- goto fail;
- }
- } else {
- struct net2280_reg_write *reg = buf;
- reg->port = cpu_to_le16(NET2280_DEV_U32);
- reg->addr = cpu_to_le32(P54U_DEV_BASE);
- reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
- err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
- if (err) {
- printk(KERN_ERR "prism54usb: dev_int send failed\n");
- goto fail;
- }
- }
-
- hdr = buf + priv->common.tx_hdr_len;
- p54_fill_eeprom_readback(hdr);
- hdr->req_id = cpu_to_le32(priv->common.rx_start);
- if (priv->common.tx_hdr_len) {
- struct net2280_tx_hdr *tx_hdr = buf;
- tx_hdr->device_addr = hdr->req_id;
- tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
- }
-
- /* we can just pretend to send 0x2000 bytes of nothing in the headers */
- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
- EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
- if (err) {
- printk(KERN_ERR "prism54usb: eeprom req send failed\n");
- goto fail;
- }
-
- err = usb_bulk_msg(priv->udev,
- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
- buf, 0x2020, &alen, 1000);
- if (!err && alen > offset) {
- p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
- } else {
- printk(KERN_ERR "prism54usb: eeprom read failed!\n");
- err = -EINVAL;
- goto fail;
- }
-
- fail:
- kfree(buf);
- return err;
-}
-
static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
{
static char start_string[] = "~~~~<\r";
@@ -412,7 +393,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
goto err_req_fw_failed;
}
- p54_parse_firmware(dev, fw_entry);
+ err = p54_parse_firmware(dev, fw_entry);
+ if (err)
+ goto err_upload_failed;
left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
strcpy(buf, start_string);
@@ -458,7 +441,7 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
if (err) {
- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+ printk(KERN_ERR "p54usb: firmware upload failed!\n");
goto err_upload_failed;
}
@@ -469,7 +452,7 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
if (err) {
- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+ printk(KERN_ERR "p54usb: firmware upload failed!\n");
goto err_upload_failed;
}
@@ -480,13 +463,13 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
break;
if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
- printk(KERN_INFO "prism54usb: firmware upload failed!\n");
+ printk(KERN_INFO "p54usb: firmware upload failed!\n");
err = -EINVAL;
break;
}
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
+ printk(KERN_ERR "p54usb: firmware boot timed out!\n");
err = -ETIMEDOUT;
break;
}
@@ -498,7 +481,7 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
buf[1] = '\r';
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
if (err) {
- printk(KERN_ERR "prism54usb: firmware boot failed!\n");
+ printk(KERN_ERR "p54usb: firmware boot failed!\n");
goto err_upload_failed;
}
@@ -549,7 +532,12 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
return err;
}
- p54_parse_firmware(dev, fw_entry);
+ err = p54_parse_firmware(dev, fw_entry);
+ if (err) {
+ kfree(buf);
+ release_firmware(fw_entry);
+ return err;
+ }
#define P54U_WRITE(type, addr, data) \
do {\
@@ -660,7 +648,7 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
if (err) {
- printk(KERN_ERR "prism54usb: firmware block upload "
+ printk(KERN_ERR "p54usb: firmware block upload "
"failed\n");
goto fail;
}
@@ -694,7 +682,7 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
0x002C | (unsigned long)&devreg->direct_mem_win);
if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
- printk(KERN_ERR "prism54usb: firmware DMA transfer "
+ printk(KERN_ERR "p54usb: firmware DMA transfer "
"failed\n");
goto fail;
}
@@ -802,7 +790,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
dev = p54_init_common(sizeof(*priv));
if (!dev) {
- printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
+ printk(KERN_ERR "p54usb: ieee80211 alloc failed\n");
return -ENOMEM;
}
@@ -833,49 +821,40 @@ static int __devinit p54u_probe(struct usb_interface *intf,
}
}
priv->common.open = p54u_open;
-
+ priv->common.stop = p54u_stop;
if (recognized_pipes < P54U_PIPE_NUMBER) {
priv->hw_type = P54U_3887;
- priv->common.tx = p54u_tx_3887;
+ err = p54u_upload_firmware_3887(dev);
+ if (priv->common.fw_interface == FW_LM87) {
+ dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
+ priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
+ priv->common.tx = p54u_tx_lm87;
+ } else
+ priv->common.tx = p54u_tx_3887;
} else {
+ priv->hw_type = P54U_NET2280;
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
priv->common.tx = p54u_tx_net2280;
- }
- priv->common.stop = p54u_stop;
-
- if (priv->hw_type)
- err = p54u_upload_firmware_3887(dev);
- else
err = p54u_upload_firmware_net2280(dev);
+ }
if (err)
goto err_free_dev;
- err = p54u_read_eeprom(dev);
+ skb_queue_head_init(&priv->rx_queue);
+
+ p54u_open(dev);
+ err = p54_read_eeprom(dev);
+ p54u_stop(dev);
if (err)
goto err_free_dev;
- if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
- u8 perm_addr[ETH_ALEN];
-
- printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
- random_ether_addr(perm_addr);
- SET_IEEE80211_PERM_ADDR(dev, perm_addr);
- }
-
- skb_queue_head_init(&priv->rx_queue);
-
err = ieee80211_register_hw(dev);
if (err) {
- printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
+ printk(KERN_ERR "p54usb: Cannot register netdevice\n");
goto err_free_dev;
}
- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
- wiphy_name(dev->wiphy),
- print_mac(mac, dev->wiphy->perm_addr),
- priv->common.version);
-
return 0;
err_free_dev:
@@ -902,7 +881,7 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
}
static struct usb_driver p54u_driver = {
- .name = "prism54usb",
+ .name = "p54usb",
.id_table = p54u_table,
.probe = p54u_probe,
.disconnect = p54u_disconnect,
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index d1896b396c1..5b8fe91379c 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -1,5 +1,5 @@
-#ifndef PRISM54USB_H
-#define PRISM54USB_H
+#ifndef P54USB_H
+#define P54USB_H
/*
* Defines for USB based mac80211 Prism54 driver
@@ -72,6 +72,11 @@ struct net2280_tx_hdr {
u8 padding[8];
} __attribute__((packed));
+struct lm87_tx_hdr {
+ __le32 device_addr;
+ __le32 chksum;
+} __attribute__((packed));
+
/* Some flags for the isl hardware registers controlling DMA inside the
* chip */
#define ISL38XX_DMA_STATUS_DONE 0x00000001
@@ -130,4 +135,4 @@ struct p54u_priv {
struct sk_buff_head rx_queue;
};
-#endif /* PRISM54USB_H */
+#endif /* P54USB_H */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 3d75a7137d3..16e68f4b654 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -71,7 +71,7 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
if (iw_mode == IW_MODE_REPEAT || iw_mode == IW_MODE_SECOND) {
printk(KERN_DEBUG
"%s(): Sorry, Repeater mode and Secondary mode "
- "are not yet supported by this driver.\n", __FUNCTION__);
+ "are not yet supported by this driver.\n", __func__);
return -EINVAL;
}
@@ -333,7 +333,7 @@ prism54_set_mode(struct net_device *ndev, struct iw_request_info *info,
if (*uwrq > IW_MODE_MONITOR || *uwrq < IW_MODE_AUTO) {
printk(KERN_DEBUG
"%s: %s() You passed a non-valid init_mode.\n",
- priv->ndev->name, __FUNCTION__);
+ priv->ndev->name, __func__);
return -EINVAL;
}
@@ -1234,7 +1234,7 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
/* don't know how to disable radio */
printk(KERN_DEBUG
"%s: %s() disabling radio is not yet supported.\n",
- priv->ndev->name, __FUNCTION__);
+ priv->ndev->name, __func__);
return -ENOTSUPP;
} else if (vwrq->fixed)
/* currently only fixed value is supported */
@@ -1242,7 +1242,7 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
else {
printk(KERN_DEBUG
"%s: %s() auto power will be implemented later.\n",
- priv->ndev->name, __FUNCTION__);
+ priv->ndev->name, __func__);
return -ENOTSUPP;
}
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 963960dc30f..1404a571752 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -325,7 +325,7 @@ static int ray_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 5;
/* Interrupt setup. For PCMCIA, driver takes what's given */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = &ray_interrupt;
@@ -798,9 +798,9 @@ static void ray_release(struct pcmcia_device *link)
iounmap(local->amem);
/* Do bother checking to see if these succeed or not */
i = pcmcia_release_window(local->amem_handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
+ if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
i = pcmcia_release_window(local->rmem_handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
+ if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
pcmcia_disable_device(link);
DEBUG(2,"ray_release ending\n");
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 00e965b9da7..2b414899dfa 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1627,7 +1627,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
static int rndis_iw_set_scan(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct iw_param *param = &wrqu->param;
struct usbnet *usbdev = dev->priv;
union iwreq_data evt;
int ret = -EINVAL;
@@ -1635,7 +1634,7 @@ static int rndis_iw_set_scan(struct net_device *dev,
devdbg(usbdev, "SIOCSIWSCAN");
- if (param->flags == 0) {
+ if (wrqu->data.flags == 0) {
tmp = ccpu2(1);
ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
sizeof(tmp));
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index d485a86bba7..f839ce044af 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -1,5 +1,5 @@
-config RT2X00
- tristate "Ralink driver support"
+menuconfig RT2X00
+ bool "Ralink driver support"
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
---help---
This will enable the experimental support for the Ralink drivers,
@@ -17,31 +17,6 @@ config RT2X00
if RT2X00
-config RT2X00_LIB
- tristate
-
-config RT2X00_LIB_PCI
- tristate
- select RT2X00_LIB
-
-config RT2X00_LIB_USB
- tristate
- select RT2X00_LIB
-
-config RT2X00_LIB_FIRMWARE
- boolean
- depends on RT2X00_LIB
- select FW_LOADER
-
-config RT2X00_LIB_RFKILL
- boolean
- depends on RT2X00_LIB
- select RFKILL
-
-config RT2X00_LIB_LEDS
- boolean
- depends on RT2X00_LIB && NEW_LEDS
-
config RT2400PCI
tristate "Ralink rt2400 (PCI/PCMCIA) support"
depends on PCI
@@ -53,23 +28,6 @@ config RT2400PCI
When compiled as a module, this driver will be called "rt2400pci.ko".
-config RT2400PCI_RFKILL
- bool "Ralink rt2400 rfkill support"
- depends on RT2400PCI
- select RT2X00_LIB_RFKILL
- ---help---
- This adds support for integrated rt2400 hardware that features a
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-config RT2400PCI_LEDS
- bool "Ralink rt2400 leds support"
- depends on RT2400PCI && NEW_LEDS
- select LEDS_CLASS
- select RT2X00_LIB_LEDS
- ---help---
- This adds support for led triggers provided my mac80211.
-
config RT2500PCI
tristate "Ralink rt2500 (PCI/PCMCIA) support"
depends on PCI
@@ -81,28 +39,12 @@ config RT2500PCI
When compiled as a module, this driver will be called "rt2500pci.ko".
-config RT2500PCI_RFKILL
- bool "Ralink rt2500 rfkill support"
- depends on RT2500PCI
- select RT2X00_LIB_RFKILL
- ---help---
- This adds support for integrated rt2500 hardware that features a
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-config RT2500PCI_LEDS
- bool "Ralink rt2500 leds support"
- depends on RT2500PCI && NEW_LEDS
- select LEDS_CLASS
- select RT2X00_LIB_LEDS
- ---help---
- This adds support for led triggers provided my mac80211.
-
config RT61PCI
tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
depends on PCI
select RT2X00_LIB_PCI
select RT2X00_LIB_FIRMWARE
+ select RT2X00_LIB_CRYPTO
select CRC_ITU_T
select EEPROM_93CX6
---help---
@@ -111,23 +53,6 @@ config RT61PCI
When compiled as a module, this driver will be called "rt61pci.ko".
-config RT61PCI_RFKILL
- bool "Ralink rt2501/rt61 rfkill support"
- depends on RT61PCI
- select RT2X00_LIB_RFKILL
- ---help---
- This adds support for integrated rt61 hardware that features a
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-config RT61PCI_LEDS
- bool "Ralink rt2501/rt61 leds support"
- depends on RT61PCI && NEW_LEDS
- select LEDS_CLASS
- select RT2X00_LIB_LEDS
- ---help---
- This adds support for led triggers provided my mac80211.
-
config RT2500USB
tristate "Ralink rt2500 (USB) support"
depends on USB
@@ -138,19 +63,12 @@ config RT2500USB
When compiled as a module, this driver will be called "rt2500usb.ko".
-config RT2500USB_LEDS
- bool "Ralink rt2500 leds support"
- depends on RT2500USB && NEW_LEDS
- select LEDS_CLASS
- select RT2X00_LIB_LEDS
- ---help---
- This adds support for led triggers provided my mac80211.
-
config RT73USB
tristate "Ralink rt2501/rt73 (USB) support"
depends on USB
select RT2X00_LIB_USB
select RT2X00_LIB_FIRMWARE
+ select RT2X00_LIB_CRYPTO
select CRC_ITU_T
---help---
This adds support for rt2501 wireless chipset family.
@@ -158,13 +76,37 @@ config RT73USB
When compiled as a module, this driver will be called "rt73usb.ko".
-config RT73USB_LEDS
- bool "Ralink rt2501/rt73 leds support"
- depends on RT73USB && NEW_LEDS
- select LEDS_CLASS
- select RT2X00_LIB_LEDS
- ---help---
- This adds support for led triggers provided my mac80211.
+config RT2X00_LIB_PCI
+ tristate
+ select RT2X00_LIB
+
+config RT2X00_LIB_USB
+ tristate
+ select RT2X00_LIB
+
+config RT2X00_LIB
+ tristate
+
+config RT2X00_LIB_FIRMWARE
+ boolean
+ select FW_LOADER
+
+config RT2X00_LIB_CRYPTO
+ boolean
+
+config RT2X00_LIB_RFKILL
+ boolean
+ default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n)
+
+comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00"
+ depends on RT2X00_LIB=y && RFKILL=m
+
+config RT2X00_LIB_LEDS
+ boolean
+ default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+
+comment "rt2x00 leds support disabled due to modularized LEDS_CLASS and built-in rt2x00"
+ depends on RT2X00_LIB=y && LEDS_CLASS=m
config RT2X00_LIB_DEBUGFS
bool "Ralink debugfs support"
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 1087dbcf1a0..917cb4f3b03 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -3,6 +3,7 @@ rt2x00lib-y += rt2x00mac.o
rt2x00lib-y += rt2x00config.o
rt2x00lib-y += rt2x00queue.o
rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 4c0538d6099..08cb9eec16a 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -231,7 +231,7 @@ static const struct rt2x00debug rt2400pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2400PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -241,9 +241,9 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
}
#else
#define rt2400pci_rfkill_poll NULL
-#endif /* CONFIG_RT2400PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
-#ifdef CONFIG_RT2400PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -288,7 +288,7 @@ static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt2400pci_blink_set;
led->flags = LED_INITIALIZED;
}
-#endif /* CONFIG_RT2400PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
@@ -1241,7 +1241,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
if (!reg)
return IRQ_NONE;
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
/*
@@ -1374,22 +1374,22 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
-#ifdef CONFIG_RT2400PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
if (value == LED_MODE_TXRX_ACTIVITY)
rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2400PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2400PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2400PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Check if the BBP tuning should be enabled.
@@ -1404,7 +1404,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* RF value list for RF2420 & RF2421
* Supports: 2.4 GHz
*/
-static const struct rf_channel rf_vals_bg[] = {
+static const struct rf_channel rf_vals_b[] = {
{ 1, 0x00022058, 0x000c1fda, 0x00000101, 0 },
{ 2, 0x00022058, 0x000c1fee, 0x00000101, 0 },
{ 3, 0x00022058, 0x000c2002, 0x00000101, 0 },
@@ -1421,10 +1421,11 @@ static const struct rf_channel rf_vals_bg[] = {
{ 14, 0x00022058, 0x000c20fa, 0x00000101, 0 },
};
-static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
- u8 *txpower;
+ struct channel_info *info;
+ char *tx_power;
unsigned int i;
/*
@@ -1440,23 +1441,28 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
EEPROM_MAC_ADDR_0));
/*
- * Convert tx_power array in eeprom.
- */
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
- /*
* Initialize hw_mode information.
*/
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
- spec->num_channels = ARRAY_SIZE(rf_vals_bg);
- spec->channels = rf_vals_bg;
+ spec->num_channels = ARRAY_SIZE(rf_vals_b);
+ spec->channels = rf_vals_b;
+
+ /*
+ * Create channel information array
+ */
+ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ spec->channels_info = info;
+
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+ for (i = 0; i < 14; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+ return 0;
}
static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1477,7 +1483,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw specifications.
*/
- rt2400pci_probe_hw_mode(rt2x00dev);
+ retval = rt2400pci_probe_hw_mode(rt2x00dev);
+ if (retval)
+ return retval;
/*
* This device requires the atim queue and DMA-mapped skbs.
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index bc556425822..bbff381ce39 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -938,19 +938,13 @@
#define MAX_TXPOWER 62
#define DEFAULT_TXPOWER 39
-#define TXPOWER_FROM_DEV(__txpower) \
-({ \
- ((__txpower) > MAX_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
- ((__txpower) < MIN_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
- (((__txpower) - MAX_TXPOWER) + MIN_TXPOWER); \
-})
-
-#define TXPOWER_TO_DEV(__txpower) \
-({ \
- (__txpower) += MIN_TXPOWER; \
- ((__txpower) <= MIN_TXPOWER) ? MAX_TXPOWER : \
- (((__txpower) >= MAX_TXPOWER) ? MIN_TXPOWER : \
- (MAX_TXPOWER - ((__txpower) - MIN_TXPOWER))); \
-})
+#define __CLAMP_TX(__txpower) \
+ clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER)
+
+#define TXPOWER_FROM_DEV(__txpower) \
+ ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
+
+#define TXPOWER_TO_DEV(__txpower) \
+ MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)
#endif /* RT2400PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 181a146b476..ef42cc04a2d 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -231,7 +231,7 @@ static const struct rt2x00debug rt2500pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2500PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -241,9 +241,9 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
}
#else
#define rt2500pci_rfkill_poll NULL
-#endif /* CONFIG_RT2500PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
-#ifdef CONFIG_RT2500PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -288,7 +288,7 @@ static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt2500pci_blink_set;
led->flags = LED_INITIALIZED;
}
-#endif /* CONFIG_RT2500PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
@@ -1316,6 +1316,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+ else
+ rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
}
@@ -1377,7 +1379,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
if (!reg)
return IRQ_NONE;
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
/*
@@ -1531,22 +1533,22 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
-#ifdef CONFIG_RT2500PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
if (value == LED_MODE_TXRX_ACTIVITY)
rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2500PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2500PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2500PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Check if the BBP tuning should be enabled.
@@ -1721,10 +1723,11 @@ static const struct rf_channel rf_vals_5222[] = {
{ 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
};
-static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
- u8 *txpower;
+ struct channel_info *info;
+ char *tx_power;
unsigned int i;
/*
@@ -1741,20 +1744,10 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
EEPROM_MAC_ADDR_0));
/*
- * Convert tx_power array in eeprom.
- */
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
- /*
* Initialize hw_mode information.
*/
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
@@ -1776,6 +1769,26 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
}
+
+ /*
+ * Create channel information array
+ */
+ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ spec->channels_info = info;
+
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+ for (i = 0; i < 14; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+ if (spec->num_channels > 14) {
+ for (i = 14; i < spec->num_channels; i++)
+ info[i].tx_power1 = DEFAULT_TXPOWER;
+ }
+
+ return 0;
}
static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1796,7 +1809,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw specifications.
*/
- rt2500pci_probe_hw_mode(rt2x00dev);
+ retval = rt2500pci_probe_hw_mode(rt2x00dev);
+ if (retval)
+ return retval;
/*
* This device requires the atim queue and DMA-mapped skbs.
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
index 42f376929ea..8c26bef6cf4 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -1223,17 +1223,10 @@
#define MAX_TXPOWER 31
#define DEFAULT_TXPOWER 24
-#define TXPOWER_FROM_DEV(__txpower) \
-({ \
- ((__txpower) > MAX_TXPOWER) ? \
- DEFAULT_TXPOWER : (__txpower); \
-})
-
-#define TXPOWER_TO_DEV(__txpower) \
-({ \
- ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
- (__txpower)); \
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
#endif /* RT2500PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index cd5af656932..d3bf7bba611 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -288,7 +288,7 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2500USB_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -333,7 +333,7 @@ static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt2500usb_blink_set;
led->flags = LED_INITIALIZED;
}
-#endif /* CONFIG_RT2500USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
@@ -384,7 +384,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
- 2 * (conf->type != IEEE80211_IF_TYPE_STA));
+ 2 * (conf->type != NL80211_IFTYPE_STATION));
rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
/*
@@ -1114,8 +1114,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
- skb->len - skbdesc->desc_len);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
@@ -1134,7 +1133,6 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
int pipe = usb_sndbulkpipe(usb_dev, 1);
int length;
u16 reg;
- u32 word, len;
/*
* Add the descriptor in front of the skb.
@@ -1144,17 +1142,6 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
skbdesc->desc = entry->skb->data;
/*
- * Adjust the beacon databyte count. The current number is
- * calculated before this function gets called, but falsely
- * assumes that the descriptor was already present in the SKB.
- */
- rt2x00_desc_read(skbdesc->desc, 0, &word);
- len = rt2x00_get_field32(word, TXD_W0_DATABYTE_COUNT);
- len += skbdesc->desc_len;
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, len);
- rt2x00_desc_write(skbdesc->desc, 0, word);
-
- /*
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
@@ -1280,6 +1267,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+ else
+ rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
@@ -1297,7 +1286,7 @@ static void rt2500usb_beacondone(struct urb *urb)
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
- if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
return;
/*
@@ -1484,14 +1473,14 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
-#ifdef CONFIG_RT2500USB_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
if (value == LED_MODE_TXRX_ACTIVITY)
rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2500USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Check if the BBP tuning should be disabled.
@@ -1665,10 +1654,11 @@ static const struct rf_channel rf_vals_5222[] = {
{ 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
};
-static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
- u8 *txpower;
+ struct channel_info *info;
+ char *tx_power;
unsigned int i;
/*
@@ -1687,20 +1677,10 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
EEPROM_MAC_ADDR_0));
/*
- * Convert tx_power array in eeprom.
- */
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
- /*
* Initialize hw_mode information.
*/
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
@@ -1722,6 +1702,26 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
}
+
+ /*
+ * Create channel information array
+ */
+ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ spec->channels_info = info;
+
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+ for (i = 0; i < 14; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+ if (spec->num_channels > 14) {
+ for (i = 14; i < spec->num_channels; i++)
+ info[i].tx_power1 = DEFAULT_TXPOWER;
+ }
+
+ return 0;
}
static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1742,7 +1742,9 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw specifications.
*/
- rt2500usb_probe_hw_mode(rt2x00dev);
+ retval = rt2500usb_probe_hw_mode(rt2x00dev);
+ if (retval)
+ return retval;
/*
* This device requires the atim queue
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index 4769ffeb4cc..89e5ed24e4f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -825,17 +825,10 @@
#define MAX_TXPOWER 31
#define DEFAULT_TXPOWER 24
-#define TXPOWER_FROM_DEV(__txpower) \
-({ \
- ((__txpower) > MAX_TXPOWER) ? \
- DEFAULT_TXPOWER : (__txpower); \
-})
-
-#define TXPOWER_TO_DEV(__txpower) \
-({ \
- ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
- (__txpower)); \
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
#endif /* RT2500USB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 8b10ea41b20..1359a376840 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -44,7 +44,7 @@
/*
* Module information.
*/
-#define DRV_VERSION "2.1.8"
+#define DRV_VERSION "2.2.1"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
/*
@@ -53,11 +53,11 @@
*/
#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \
printk(__kernlvl "%s -> %s: %s - " __msg, \
- wiphy_name((__dev)->hw->wiphy), __FUNCTION__, __lvl, ##__args)
+ wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args)
#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \
printk(__kernlvl "%s -> %s: %s - " __msg, \
- KBUILD_MODNAME, __FUNCTION__, __lvl, ##__args)
+ KBUILD_MODNAME, __func__, __lvl, ##__args)
#ifdef CONFIG_RT2X00_DEBUG
#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
@@ -144,6 +144,17 @@ struct rf_channel {
};
/*
+ * Channel information structure
+ */
+struct channel_info {
+ unsigned int flags;
+#define GEOGRAPHY_ALLOWED 0x00000001
+
+ short tx_power1;
+ short tx_power2;
+};
+
+/*
* Antenna setup values.
*/
struct antenna_setup {
@@ -394,10 +405,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
* @num_channels: Number of supported channels. This is used as array size
* for @tx_power_a, @tx_power_bg and @channels.
* @channels: Device/chipset specific channel values (See &struct rf_channel).
- * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
- * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
- * @tx_power_default: Default TX power value to use when either
- * @tx_power_a or @tx_power_bg is missing.
+ * @channels_info: Additional information for channels (See &struct channel_info).
*/
struct hw_mode_spec {
unsigned int supported_bands;
@@ -410,10 +418,7 @@ struct hw_mode_spec {
unsigned int num_channels;
const struct rf_channel *channels;
-
- const u8 *tx_power_a;
- const u8 *tx_power_bg;
- u8 tx_power_default;
+ const struct channel_info *channels_info;
};
/*
@@ -425,7 +430,9 @@ struct hw_mode_spec {
*/
struct rt2x00lib_conf {
struct ieee80211_conf *conf;
+
struct rf_channel rf;
+ struct channel_info channel;
struct antenna_setup ant;
@@ -452,6 +459,23 @@ struct rt2x00lib_erp {
};
/*
+ * Configuration structure for hardware encryption.
+ */
+struct rt2x00lib_crypto {
+ enum cipher cipher;
+
+ enum set_key_cmd cmd;
+ const u8 *address;
+
+ u32 bssidx;
+ u32 aid;
+
+ u8 key[16];
+ u8 tx_mic[8];
+ u8 rx_mic[8];
+};
+
+/*
* Configuration structure wrapper around the
* rt2x00 interface configuration handler.
*/
@@ -459,7 +483,7 @@ struct rt2x00intf_conf {
/*
* Interface type
*/
- enum ieee80211_if_types type;
+ enum nl80211_iftype type;
/*
* TSF sync value, this is dependant on the operation type.
@@ -547,6 +571,12 @@ struct rt2x00lib_ops {
/*
* Configuration handlers.
*/
+ int (*config_shared_key) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key);
+ int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key);
void (*config_filter) (struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void (*config_intf) (struct rt2x00_dev *rt2x00dev,
@@ -599,17 +629,16 @@ enum rt2x00_flags {
/*
* Device state flags
*/
- DEVICE_PRESENT,
- DEVICE_REGISTERED_HW,
- DEVICE_INITIALIZED,
- DEVICE_STARTED,
- DEVICE_STARTED_SUSPEND,
- DEVICE_ENABLED_RADIO,
- DEVICE_DISABLED_RADIO_HW,
- DEVICE_DIRTY_CONFIG,
+ DEVICE_STATE_PRESENT,
+ DEVICE_STATE_REGISTERED_HW,
+ DEVICE_STATE_INITIALIZED,
+ DEVICE_STATE_STARTED,
+ DEVICE_STATE_STARTED_SUSPEND,
+ DEVICE_STATE_ENABLED_RADIO,
+ DEVICE_STATE_DISABLED_RADIO_HW,
/*
- * Driver features
+ * Driver requirements
*/
DRIVER_REQUIRE_FIRMWARE,
DRIVER_REQUIRE_BEACON_GUARD,
@@ -618,9 +647,14 @@ enum rt2x00_flags {
DRIVER_REQUIRE_DMA,
/*
- * Driver configuration
+ * Driver features
*/
CONFIG_SUPPORT_HW_BUTTON,
+ CONFIG_SUPPORT_HW_CRYPTO,
+
+ /*
+ * Driver configuration
+ */
CONFIG_FRAME_TYPE,
CONFIG_RF_SEQUENCE,
CONFIG_EXTERNAL_LNA_A,
@@ -769,6 +803,11 @@ struct rt2x00_dev {
u32 *rf;
/*
+ * LNA gain
+ */
+ short lna_gain;
+
+ /*
* USB Max frame size (for rt2500usb & rt73usb).
*/
u16 usb_maxpacket;
@@ -966,6 +1005,13 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key);
+#else
+#define rt2x00mac_set_key NULL
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index d134c3be539..4d5e87b015a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -31,7 +31,7 @@
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
- enum ieee80211_if_types type,
+ enum nl80211_iftype type,
u8 *mac, u8 *bssid)
{
struct rt2x00intf_conf conf;
@@ -40,11 +40,11 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
conf.type = type;
switch (type) {
- case IEEE80211_IF_TYPE_IBSS:
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
conf.sync = TSF_SYNC_BEACON;
break;
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
conf.sync = TSF_SYNC_INFRA;
break;
default:
@@ -121,7 +121,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* Antenna setup changes require the RX to be disabled,
* else the changes will be ignored by the device.
*/
- if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);
/*
@@ -136,7 +136,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
rt2x00dev->link.ant.active.tx = libconf.ant.tx;
- if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
}
@@ -245,6 +245,10 @@ config:
memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel->hw_value],
sizeof(libconf.rf));
+
+ memcpy(&libconf.channel,
+ &rt2x00dev->spec.channels_info[conf->channel->hw_value],
+ sizeof(libconf.channel));
}
if (flags & CONFIG_UPDATE_ANTENNA) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
new file mode 100644
index 00000000000..5a858e5106c
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -0,0 +1,215 @@
+/*
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: rt2x00lib
+ Abstract: rt2x00 crypto specific routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
+{
+ switch (key->alg) {
+ case ALG_WEP:
+ if (key->keylen == LEN_WEP40)
+ return CIPHER_WEP64;
+ else
+ return CIPHER_WEP128;
+ case ALG_TKIP:
+ return CIPHER_TKIP;
+ case ALG_CCMP:
+ return CIPHER_AES;
+ default:
+ return CIPHER_NONE;
+ }
+}
+
+unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
+{
+ struct ieee80211_key_conf *key = tx_info->control.hw_key;
+ unsigned int overhead = 0;
+
+ /*
+ * Extend frame length to include IV/EIV/ICV/MMIC,
+ * note that these lengths should only be added when
+ * mac80211 does not generate it.
+ */
+ overhead += key->icv_len;
+
+ if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+ overhead += key->iv_len;
+
+ if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
+ if (key->alg == ALG_TKIP)
+ overhead += 8;
+ }
+
+ return overhead;
+}
+
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
+{
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
+
+ if (unlikely(!iv_len))
+ return;
+
+ /* Copy IV/EIV data */
+ if (iv_len >= 4)
+ memcpy(&skbdesc->iv, skb->data + header_length, 4);
+ if (iv_len >= 8)
+ memcpy(&skbdesc->eiv, skb->data + header_length + 4, 4);
+
+ /* Move ieee80211 header */
+ memmove(skb->data + iv_len, skb->data, header_length);
+
+ /* Pull buffer to correct size */
+ skb_pull(skb, iv_len);
+
+ /* IV/EIV data has officially be stripped */
+ skbdesc->flags |= FRAME_DESC_IV_STRIPPED;
+}
+
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
+{
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
+ const unsigned int iv_len =
+ ((!!(skbdesc->iv)) * 4) + ((!!(skbdesc->eiv)) * 4);
+
+ if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED))
+ return;
+
+ skb_push(skb, iv_len);
+
+ /* Move ieee80211 header */
+ memmove(skb->data, skb->data + iv_len, header_length);
+
+ /* Copy IV/EIV data */
+ if (iv_len >= 4)
+ memcpy(skb->data + header_length, &skbdesc->iv, 4);
+ if (iv_len >= 8)
+ memcpy(skb->data + header_length + 4, &skbdesc->eiv, 4);
+
+ /* IV/EIV data has returned into the frame */
+ skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED;
+}
+
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
+ unsigned int header_length,
+ struct rxdone_entry_desc *rxdesc)
+{
+ unsigned int payload_len = rxdesc->size - header_length;
+ unsigned int iv_len;
+ unsigned int icv_len;
+ unsigned int transfer = 0;
+
+ /*
+ * WEP64/WEP128: Provides IV & ICV
+ * TKIP: Provides IV/EIV & ICV
+ * AES: Provies IV/EIV & ICV
+ */
+ switch (rxdesc->cipher) {
+ case CIPHER_WEP64:
+ case CIPHER_WEP128:
+ iv_len = 4;
+ icv_len = 4;
+ break;
+ case CIPHER_TKIP:
+ iv_len = 8;
+ icv_len = 4;
+ break;
+ case CIPHER_AES:
+ iv_len = 8;
+ icv_len = 8;
+ break;
+ default:
+ /* Unsupport type */
+ return;
+ }
+
+ /*
+ * Make room for new data, note that we increase both
+ * headsize and tailsize when required. The tailsize is
+ * only needed when ICV data needs to be inserted and
+ * the padding is smaller then the ICV data.
+ * When alignment requirements is greater then the
+ * ICV data we must trim the skb to the correct size
+ * because we need to remove the extra bytes.
+ */
+ skb_push(skb, iv_len + align);
+ if (align < icv_len)
+ skb_put(skb, icv_len - align);
+ else if (align > icv_len)
+ skb_trim(skb, rxdesc->size + iv_len + icv_len);
+
+ /* Move ieee80211 header */
+ memmove(skb->data + transfer,
+ skb->data + transfer + iv_len + align,
+ header_length);
+ transfer += header_length;
+
+ /* Copy IV data */
+ if (iv_len >= 4) {
+ memcpy(skb->data + transfer, &rxdesc->iv, 4);
+ transfer += 4;
+ }
+
+ /* Copy EIV data */
+ if (iv_len >= 8) {
+ memcpy(skb->data + transfer, &rxdesc->eiv, 4);
+ transfer += 4;
+ }
+
+ /* Move payload */
+ if (align) {
+ memmove(skb->data + transfer,
+ skb->data + transfer + align,
+ payload_len);
+ }
+
+ /*
+ * NOTE: Always count the payload as transfered,
+ * even when alignment was set to zero. This is required
+ * for determining the correct offset for the ICV data.
+ */
+ transfer += payload_len;
+
+ /* Copy ICV data */
+ if (icv_len >= 4) {
+ memcpy(skb->data + transfer, &rxdesc->icv, 4);
+ /*
+ * AES appends 8 bytes, we can't fill the upper
+ * 4 bytes, but mac80211 doesn't care about what
+ * we provide here anyway and strips it immediately.
+ */
+ transfer += icv_len;
+ }
+
+ /* IV/EIV/ICV has been inserted into frame */
+ rxdesc->size = transfer;
+ rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
+}
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 6bee1d611bb..5cf4c859e39 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -35,6 +35,13 @@
#define MAX_LINE_LENGTH 64
+struct rt2x00debug_crypto {
+ unsigned long success;
+ unsigned long icv_error;
+ unsigned long mic_error;
+ unsigned long key_error;
+};
+
struct rt2x00debug_intf {
/*
* Pointer to driver structure where
@@ -63,6 +70,7 @@ struct rt2x00debug_intf {
* - queue folder
* - frame dump file
* - queue stats file
+ * - crypto stats file
*/
struct dentry *driver_folder;
struct dentry *driver_entry;
@@ -80,6 +88,7 @@ struct rt2x00debug_intf {
struct dentry *queue_folder;
struct dentry *queue_frame_dump_entry;
struct dentry *queue_stats_entry;
+ struct dentry *crypto_stats_entry;
/*
* The frame dump file only allows a single reader,
@@ -98,6 +107,12 @@ struct rt2x00debug_intf {
wait_queue_head_t frame_dump_waitqueue;
/*
+ * HW crypto statistics.
+ * All statistics are stored seperately per cipher type.
+ */
+ struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
+
+ /*
* Driver and chipset files will use a data buffer
* that has been created in advance. This will simplify
* the code since we can use the debugfs functions.
@@ -114,6 +129,25 @@ struct rt2x00debug_intf {
unsigned int offset_rf;
};
+void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+ enum cipher cipher, enum rx_crypto status)
+{
+ struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+
+ if (cipher == CIPHER_TKIP_NO_MIC)
+ cipher = CIPHER_TKIP;
+ if (cipher == CIPHER_NONE || cipher > CIPHER_MAX)
+ return;
+
+ /* Remove CIPHER_NONE index */
+ cipher--;
+
+ intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
+ intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
+ intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
+ intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
+}
+
void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
enum rt2x00_dump_type type, struct sk_buff *skb)
{
@@ -327,6 +361,59 @@ static const struct file_operations rt2x00debug_fop_queue_stats = {
.release = rt2x00debug_file_release,
};
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
+ char __user *buf,
+ size_t length,
+ loff_t *offset)
+{
+ struct rt2x00debug_intf *intf = file->private_data;
+ char *name[] = { "WEP64", "WEP128", "TKIP", "AES" };
+ char *data;
+ char *temp;
+ size_t size;
+ unsigned int i;
+
+ if (*offset)
+ return 0;
+
+ data = kzalloc((1 + CIPHER_MAX)* MAX_LINE_LENGTH, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ temp = data;
+ temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
+
+ for (i = 0; i < CIPHER_MAX; i++) {
+ temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
+ intf->crypto_stats[i].success,
+ intf->crypto_stats[i].icv_error,
+ intf->crypto_stats[i].mic_error,
+ intf->crypto_stats[i].key_error);
+ }
+
+ size = strlen(data);
+ size = min(size, length);
+
+ if (copy_to_user(buf, data, size)) {
+ kfree(data);
+ return -EFAULT;
+ }
+
+ kfree(data);
+
+ *offset += size;
+ return size;
+}
+
+static const struct file_operations rt2x00debug_fop_crypto_stats = {
+ .owner = THIS_MODULE,
+ .read = rt2x00debug_read_crypto_stats,
+ .open = rt2x00debug_file_open,
+ .release = rt2x00debug_file_release,
+};
+#endif
+
#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
static ssize_t rt2x00debug_read_##__name(struct file *file, \
char __user *buf, \
@@ -569,6 +656,13 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
debugfs_create_file("queue", S_IRUSR, intf->queue_folder,
intf, &rt2x00debug_fop_queue_stats);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ intf->crypto_stats_entry =
+ debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
+ intf, &rt2x00debug_fop_crypto_stats);
+#endif
+
return;
exit:
@@ -587,6 +681,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
skb_queue_purge(&intf->frame_dump_skbqueue);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+ debugfs_remove(intf->crypto_stats_entry);
+#endif
debugfs_remove(intf->queue_stats_entry);
debugfs_remove(intf->queue_frame_dump_entry);
debugfs_remove(intf->queue_folder);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index f42283ad7b0..86840e3585e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -34,7 +34,7 @@
*/
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
/*
@@ -94,8 +94,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
* Don't enable the radio twice.
* And check if the hardware button has been disabled.
*/
- if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
- test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
+ test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags))
return 0;
/*
@@ -117,7 +117,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00leds_led_radio(rt2x00dev, true);
rt2x00led_led_activity(rt2x00dev, true);
- __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
/*
* Enable RX.
@@ -134,7 +134,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
{
- if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
/*
@@ -354,7 +354,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
* When the radio is shutting down we should
* immediately cease all link tuning.
*/
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
/*
@@ -431,7 +431,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
* note that in the spinlock protected area above the delayed_flags
* have been cleared correctly.
*/
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
if (delayed_flags & DELAYED_UPDATE_BEACON)
@@ -467,8 +467,8 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
- if (vif->type != IEEE80211_IF_TYPE_AP &&
- vif->type != IEEE80211_IF_TYPE_IBSS)
+ if (vif->type != NL80211_IFTYPE_AP &&
+ vif->type != NL80211_IFTYPE_ADHOC)
return;
/*
@@ -484,7 +484,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
@@ -508,6 +508,15 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
/*
+ * If the IV/EIV data was stripped from the frame before it was
+ * passed to the hardware, we should now reinsert it again because
+ * mac80211 will expect the the same data to be present it the
+ * frame as it was passed to us.
+ */
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ rt2x00crypto_tx_insert_iv(entry->skb);
+
+ /*
* Send frame to debugfs immediately, after this call is completed
* we are going to overwrite the skb->cb array.
*/
@@ -563,7 +572,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry);
- __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
/*
@@ -585,7 +594,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
struct ieee80211_supported_band *sband;
struct ieee80211_hdr *hdr;
const struct rt2x00_rate *rate;
- unsigned int header_size;
+ unsigned int header_length;
unsigned int align;
unsigned int i;
int idx = -1;
@@ -613,10 +622,19 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
- header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
- align = ((unsigned long)(entry->skb->data + header_size)) & 3;
+ header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+ align = ((unsigned long)(entry->skb->data + header_length)) & 3;
- if (align) {
+ /*
+ * Hardware might have stripped the IV/EIV/ICV data,
+ * in that case it is possible that the data was
+ * provided seperately (through hardware descriptor)
+ * in which case we should reinsert the data into the frame.
+ */
+ if ((rxdesc.flags & RX_FLAG_IV_STRIPPED)) {
+ rt2x00crypto_rx_insert_iv(entry->skb, align,
+ header_length, &rxdesc);
+ } else if (align) {
skb_push(entry->skb, align);
/* Move entire frame in 1 command */
memmove(entry->skb->data, entry->skb->data + align,
@@ -635,7 +653,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
(rate->plcp == rxdesc.signal)) ||
- (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
+ ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) &&
(rate->bitrate == rxdesc.signal))) {
idx = i;
break;
@@ -657,6 +675,10 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
(rxdesc.dev_flags & RXDONE_MY_BSS))
rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi);
+ rt2x00debug_update_crypto(rt2x00dev,
+ rxdesc.cipher,
+ rxdesc.cipher_status);
+
rt2x00dev->link.qual.rx_success++;
rx_status->mactime = rxdesc.timestamp;
@@ -796,7 +818,6 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
struct ieee80211_rate *rates;
unsigned int num_rates;
unsigned int i;
- unsigned char tx_power;
num_rates = 0;
if (spec->supported_rates & SUPPORT_RATE_CCK)
@@ -822,20 +843,9 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
* Initialize Channel list.
*/
for (i = 0; i < spec->num_channels; i++) {
- if (spec->channels[i].channel <= 14) {
- if (spec->tx_power_bg)
- tx_power = spec->tx_power_bg[i];
- else
- tx_power = spec->tx_power_default;
- } else {
- if (spec->tx_power_a)
- tx_power = spec->tx_power_a[i];
- else
- tx_power = spec->tx_power_default;
- }
-
rt2x00lib_channel(&channels[i],
- spec->channels[i].channel, tx_power, i);
+ spec->channels[i].channel,
+ spec->channels_info[i].tx_power1, i);
}
/*
@@ -878,7 +888,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
{
- if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
ieee80211_unregister_hw(rt2x00dev->hw);
if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
@@ -887,6 +897,8 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
}
+
+ kfree(rt2x00dev->spec.channels_info);
}
static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -894,6 +906,9 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
struct hw_mode_spec *spec = &rt2x00dev->spec;
int status;
+ if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
+ return 0;
+
/*
* Initialize HW modes.
*/
@@ -915,7 +930,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
return status;
}
- __set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);
return 0;
}
@@ -925,7 +940,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
*/
static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
{
- if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
+ if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
return;
/*
@@ -948,7 +963,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
{
int status;
- if (test_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
return 0;
/*
@@ -967,7 +982,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
return status;
}
- __set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
/*
* Register the extra components.
@@ -981,7 +996,7 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
{
int retval;
- if (test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return 0;
/*
@@ -999,28 +1014,18 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
if (retval)
return retval;
- /*
- * Enable radio.
- */
- retval = rt2x00lib_enable_radio(rt2x00dev);
- if (retval) {
- rt2x00lib_uninitialize(rt2x00dev);
- return retval;
- }
-
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
rt2x00dev->intf_associated = 0;
- __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
- __set_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
return 0;
}
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return;
/*
@@ -1032,8 +1037,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
rt2x00dev->intf_associated = 0;
-
- __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
}
/*
@@ -1049,6 +1052,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
+ rt2x00dev->hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
/*
* Let the driver probe the device to detect the capabilities.
*/
@@ -1088,7 +1096,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00rfkill_allocate(rt2x00dev);
rt2x00debug_register(rt2x00dev);
- __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
return 0;
@@ -1101,7 +1109,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);
void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
{
- __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);
+ clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
/*
* Disable radio.
@@ -1146,14 +1154,15 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
int retval;
NOTICE(rt2x00dev, "Going to sleep.\n");
- __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);
/*
* Only continue if mac80211 has open interfaces.
*/
- if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+ !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
goto exit;
- __set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);
+
+ set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags);
/*
* Disable radio.
@@ -1203,8 +1212,8 @@ static void rt2x00lib_resume_intf(void *data, u8 *mac,
/*
* Master or Ad-hoc mode require a new beacon update.
*/
- if (vif->type == IEEE80211_IF_TYPE_AP ||
- vif->type == IEEE80211_IF_TYPE_IBSS)
+ if (vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_ADHOC)
intf->delayed_flags |= DELAYED_UPDATE_BEACON;
spin_unlock(&intf->lock);
@@ -1225,7 +1234,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* Only continue if mac80211 had open interfaces.
*/
- if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags))
+ if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags))
return 0;
/*
@@ -1252,7 +1261,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* We are ready again to receive requests from mac80211.
*/
- __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
/*
* It is possible that during that mac80211 has attempted
@@ -1272,7 +1281,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- rt2x00lib_disable_radio(rt2x00dev);
+ rt2x00lib_stop(rt2x00dev);
rt2x00lib_uninitialize(rt2x00dev);
rt2x00debug_deregister(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index c5fb3a72cf3..797eb619aa0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -88,7 +88,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
*/
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
- enum ieee80211_if_types type,
+ enum nl80211_iftype type,
u8 *mac, u8 *bssid);
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
@@ -181,6 +181,8 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
enum rt2x00_dump_type type, struct sk_buff *skb);
+void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+ enum cipher cipher, enum rx_crypto status);
#else
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
{
@@ -195,9 +197,54 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb)
{
}
+
+static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+ enum cipher cipher,
+ enum rx_crypto status)
+{
+}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
+ * Crypto handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
+unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info);
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len);
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb);
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
+ unsigned int header_length,
+ struct rxdone_entry_desc *rxdesc);
+#else
+static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
+{
+ return CIPHER_NONE;
+}
+
+static inline unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
+{
+ return 0;
+}
+
+static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
+ unsigned int iv_len)
+{
+}
+
+static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
+{
+}
+
+static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
+ unsigned int align,
+ unsigned int header_length,
+ struct rxdone_entry_desc *rxdesc)
+{
+}
+#endif
+
+/*
* RFkill handlers.
*/
#ifdef CONFIG_RT2X00_LIB_RFKILL
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index d0650738863..2c6cc5c374f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -36,21 +36,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
struct ieee80211_tx_info *rts_info;
struct sk_buff *skb;
- int size;
+ unsigned int data_length;
+ int retval = 0;
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
- size = sizeof(struct ieee80211_cts);
+ data_length = sizeof(struct ieee80211_cts);
else
- size = sizeof(struct ieee80211_rts);
+ data_length = sizeof(struct ieee80211_rts);
- skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom);
- if (!skb) {
+ skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
+ if (unlikely(!skb)) {
WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
- return NETDEV_TX_BUSY;
+ return -ENOMEM;
}
skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
- skb_put(skb, size);
+ skb_put(skb, data_length);
/*
* Copy TX information over from original frame to
@@ -63,7 +64,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
*/
memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
rts_info = IEEE80211_SKB_CB(skb);
- rts_info->control.hw_key = NULL;
rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -73,22 +73,33 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
else
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
+ skb->do_not_encrypt = 1;
+
+ /*
+ * RTS/CTS frame should use the length of the frame plus any
+ * encryption overhead that will be added by the hardware.
+ */
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+ if (!frag_skb->do_not_encrypt)
+ data_length += rt2x00crypto_tx_overhead(tx_info);
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
- frag_skb->data, size, tx_info,
+ frag_skb->data, data_length, tx_info,
(struct ieee80211_cts *)(skb->data));
else
ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
- frag_skb->data, size, tx_info,
+ frag_skb->data, data_length, tx_info,
(struct ieee80211_rts *)(skb->data));
- if (rt2x00queue_write_tx_frame(queue, skb)) {
+ retval = rt2x00queue_write_tx_frame(queue, skb);
+ if (retval) {
dev_kfree_skb_any(skb);
WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
- return NETDEV_TX_BUSY;
}
- return NETDEV_TX_OK;
+ return retval;
}
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -106,11 +117,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* Note that we can only stop the TX queues inside the TX path
* due to possible race conditions in mac80211.
*/
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
- ieee80211_stop_queues(hw);
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ goto exit_fail;
/*
* Determine which queue to put packet on.
@@ -141,26 +149,25 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
!rt2x00dev->ops->hw->set_rts_threshold) {
- if (rt2x00queue_available(queue) <= 1) {
- ieee80211_stop_queue(rt2x00dev->hw, qid);
- return NETDEV_TX_BUSY;
- }
-
- if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) {
- ieee80211_stop_queue(rt2x00dev->hw, qid);
- return NETDEV_TX_BUSY;
- }
- }
+ if (rt2x00queue_available(queue) <= 1)
+ goto exit_fail;
- if (rt2x00queue_write_tx_frame(queue, skb)) {
- ieee80211_stop_queue(rt2x00dev->hw, qid);
- return NETDEV_TX_BUSY;
+ if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
+ goto exit_fail;
}
+ if (rt2x00queue_write_tx_frame(queue, skb))
+ goto exit_fail;
+
if (rt2x00queue_threshold(queue))
ieee80211_stop_queue(rt2x00dev->hw, qid);
return NETDEV_TX_OK;
+
+ exit_fail:
+ ieee80211_stop_queue(rt2x00dev->hw, qid);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
EXPORT_SYMBOL_GPL(rt2x00mac_tx);
@@ -168,7 +175,7 @@ int rt2x00mac_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
return rt2x00lib_start(rt2x00dev);
@@ -179,7 +186,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return;
rt2x00lib_stop(rt2x00dev);
@@ -199,12 +206,12 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* Don't allow interfaces to be added
* the device has disappeared.
*/
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
- !test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+ !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return -ENODEV;
switch (conf->type) {
- case IEEE80211_IF_TYPE_AP:
+ case NL80211_IFTYPE_AP:
/*
* We don't support mixed combinations of
* sta and ap interfaces.
@@ -220,8 +227,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
return -ENOBUFS;
break;
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
/*
* We don't support mixed combinations of
* sta and ap interfaces.
@@ -249,7 +256,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
*/
for (i = 0; i < queue->limit; i++) {
entry = &queue->entries[i];
- if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
+ if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
break;
}
@@ -261,7 +268,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* increase interface count and start initialization.
*/
- if (conf->type == IEEE80211_IF_TYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count++;
else
rt2x00dev->intf_sta_count++;
@@ -270,7 +277,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
spin_lock_init(&intf->seqlock);
intf->beacon = entry;
- if (conf->type == IEEE80211_IF_TYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
@@ -303,12 +310,12 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* either the device has disappeared or when
* no interface is present.
*/
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
- (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
- (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+ (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
+ (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
return;
- if (conf->type == IEEE80211_IF_TYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count--;
else
rt2x00dev->intf_sta_count--;
@@ -317,59 +324,59 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* Release beacon entry so it is available for
* new interfaces again.
*/
- __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
+ clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
/*
* Make sure the bssid and mac address registers
* are cleared to prevent false ACKing of frames.
*/
rt2x00lib_config_intf(rt2x00dev, intf,
- IEEE80211_IF_TYPE_INVALID, NULL, NULL);
+ NL80211_IFTYPE_UNSPECIFIED, NULL, NULL);
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- int force_reconfig;
+ int radio_on;
+ int status;
/*
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
/*
- * Check if we need to disable the radio,
- * if this is not the case, at least the RX must be disabled.
+ * Only change device state when the radio is enabled. It does not
+ * matter what parameters we have configured when the radio is disabled
+ * because we won't be able to send or receive anyway. Also note that
+ * some configuration parameters (e.g. channel and antenna values) can
+ * only be set when the radio is enabled.
*/
- if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
- if (!conf->radio_enabled)
- rt2x00lib_disable_radio(rt2x00dev);
- else
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
- }
+ radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
+ if (conf->radio_enabled) {
+ /* For programming the values, we have to turn RX off */
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
- /*
- * When the DEVICE_DIRTY_CONFIG flag is set, the device has recently
- * been started and the configuration must be forced upon the hardware.
- * Otherwise registers will not be intialized correctly and could
- * result in non-working hardware because essential registers aren't
- * initialized.
- */
- force_reconfig =
- __test_and_clear_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);
+ /* Enable the radio */
+ status = rt2x00lib_enable_radio(rt2x00dev);
+ if (unlikely(status))
+ return status;
- rt2x00lib_config(rt2x00dev, conf, force_reconfig);
+ /*
+ * When we've just turned on the radio, we want to reprogram
+ * everything to ensure a consistent state
+ */
+ rt2x00lib_config(rt2x00dev, conf, !radio_on);
- /*
- * Reenable RX only if the radio should be on.
- */
- if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ /* Turn RX back on */
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
- else if (conf->radio_enabled)
- return rt2x00lib_enable_radio(rt2x00dev);
+ } else {
+ /* Disable the radio */
+ rt2x00lib_disable_radio(rt2x00dev);
+ }
return 0;
}
@@ -388,7 +395,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
spin_lock(&intf->lock);
@@ -467,6 +474,91 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ int (*set_key) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key);
+ struct rt2x00lib_crypto crypto;
+
+ if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ return -EOPNOTSUPP;
+ else if (key->keylen > 32)
+ return -ENOSPC;
+
+ memset(&crypto, 0, sizeof(crypto));
+
+ /*
+ * When in STA mode, bssidx is always 0 otherwise local_address[5]
+ * contains the bss number, see BSS_ID_MASK comments for details.
+ */
+ if (rt2x00dev->intf_sta_count)
+ crypto.bssidx = 0;
+ else
+ crypto.bssidx =
+ local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
+
+ crypto.cipher = rt2x00crypto_key_to_cipher(key);
+ if (crypto.cipher == CIPHER_NONE)
+ return -EOPNOTSUPP;
+
+ crypto.cmd = cmd;
+ crypto.address = address;
+
+ if (crypto.cipher == CIPHER_TKIP) {
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
+ memcpy(&crypto.key,
+ &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
+ sizeof(crypto.key));
+
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(&crypto.tx_mic,
+ &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
+ sizeof(crypto.tx_mic));
+
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
+ memcpy(&crypto.rx_mic,
+ &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
+ sizeof(crypto.rx_mic));
+ } else
+ memcpy(&crypto.key, &key->key[0], key->keylen);
+
+ /*
+ * Each BSS has a maximum of 4 shared keys.
+ * Shared key index values:
+ * 0) BSS0 key0
+ * 1) BSS0 key1
+ * ...
+ * 4) BSS1 key0
+ * ...
+ * 8) BSS2 key0
+ * ...
+ * Both pairwise as shared key indeces are determined by
+ * driver. This is required because the hardware requires
+ * keys to be assigned in correct order (When key 1 is
+ * provided but key 0 is not, then the key is not found
+ * by the hardware during RX).
+ */
+ if (cmd == SET_KEY)
+ key->hw_key_idx = 0;
+
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ set_key = rt2x00dev->ops->lib->config_pairwise_key;
+ else
+ set_key = rt2x00dev->ops->lib->config_shared_key;
+
+ if (!set_key)
+ return -EOPNOTSUPP;
+
+ return set_key(rt2x00dev, &crypto, key);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
@@ -575,10 +667,11 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
queue->aifs = params->aifs;
+ queue->txop = params->txop;
INFO(rt2x00dev,
- "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
- queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
+ "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n",
+ queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop);
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 898cdd7f57d..451d410ecda 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -33,10 +33,11 @@
struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
struct queue_entry *entry)
{
- unsigned int frame_size;
- unsigned int reserved_size;
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
+ unsigned int frame_size;
+ unsigned int head_size = 0;
+ unsigned int tail_size = 0;
/*
* The frame size includes descriptor size, because the
@@ -49,16 +50,32 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
* this means we need at least 3 bytes for moving the frame
* into the correct offset.
*/
- reserved_size = 4;
+ head_size = 4;
+
+ /*
+ * For IV/EIV/ICV assembly we must make sure there is
+ * at least 8 bytes bytes available in headroom for IV/EIV
+ * and 4 bytes for ICV data as tailroon.
+ */
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+ head_size += 8;
+ tail_size += 4;
+ }
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
/*
* Allocate skbuffer.
*/
- skb = dev_alloc_skb(frame_size + reserved_size);
+ skb = dev_alloc_skb(frame_size + head_size + tail_size);
if (!skb)
return NULL;
- skb_reserve(skb, reserved_size);
+ /*
+ * Make sure we not have a frame with the requested bytes
+ * available in the head and tail.
+ */
+ skb_reserve(skb, head_size);
skb_put(skb, frame_size);
/*
@@ -83,8 +100,21 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
+ /*
+ * If device has requested headroom, we should make sure that
+ * is also mapped to the DMA so it can be used for transfering
+ * additional descriptor information to the hardware.
+ */
+ skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
+
+ skbdesc->skb_dma =
+ dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+ /*
+ * Restore data pointer to original location again.
+ */
+ skb_pull(skb, rt2x00dev->hw->extra_tx_headroom);
+
skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
}
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
@@ -100,7 +130,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
}
if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
- dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
+ /*
+ * Add headroom to the skb length, it has been removed
+ * by the driver, but it was actually mapped to DMA.
+ */
+ dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
+ skb->len + rt2x00dev->hw->extra_tx_headroom,
DMA_TO_DEVICE);
skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
}
@@ -120,7 +155,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
struct ieee80211_rate *rate =
ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
@@ -140,7 +174,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
txdesc->cw_max = entry->queue->cw_max;
txdesc->aifs = entry->queue->aifs;
- /* Data length should be extended with 4 bytes for CRC */
+ /* Data length + CRC + IV/EIV/ICV/MMIC (when using encryption) */
data_length = entry->skb->len + 4;
/*
@@ -149,6 +183,35 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
__set_bit(ENTRY_TXD_ACK, &txdesc->flags);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) &&
+ !entry->skb->do_not_encrypt) {
+ struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+
+ __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
+
+ txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
+
+ if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
+
+ txdesc->key_idx = hw_key->hw_key_idx;
+ txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+ /*
+ * Extend frame length to include all encryption overhead
+ * that will be added by the hardware.
+ */
+ data_length += rt2x00crypto_tx_overhead(tx_info);
+
+ if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+ __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
+
+ if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
+ __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
+ }
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+
/*
* Check if this is a RTS/CTS frame
*/
@@ -214,16 +277,22 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* sequence counter given by mac80211.
*/
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- spin_lock_irqsave(&intf->seqlock, irqflags);
+ if (likely(tx_info->control.vif)) {
+ struct rt2x00_intf *intf;
+
+ intf = vif_to_intf(tx_info->control.vif);
- if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
- intf->seqno += 0x10;
- hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
+ spin_lock_irqsave(&intf->seqlock, irqflags);
- spin_unlock_irqrestore(&intf->seqlock, irqflags);
+ if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+ intf->seqno += 0x10;
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
- __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+ spin_unlock_irqrestore(&intf->seqlock, irqflags);
+
+ __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+ }
}
/*
@@ -305,11 +374,12 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
+ unsigned int iv_len = 0;
if (unlikely(rt2x00queue_full(queue)))
return -EINVAL;
- if (__test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+ if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
ERROR(queue->rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
@@ -325,22 +395,44 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
entry->skb = skb;
rt2x00queue_create_tx_descriptor(entry, &txdesc);
+ if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)
+ iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
+
/*
- * skb->cb array is now ours and we are free to use it.
+ * All information is retreived from the skb->cb array,
+ * now we should claim ownership of the driver part of that
+ * array.
*/
skbdesc = get_skb_frame_desc(entry->skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->entry = entry;
+ /*
+ * When hardware encryption is supported, and this frame
+ * is to be encrypted, we should strip the IV/EIV data from
+ * the frame so we can provide it to the driver seperately.
+ */
+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
+ !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
+ rt2x00crypto_tx_remove_iv(skb, iv_len);
+ }
+
+ /*
+ * It could be possible that the queue was corrupted and this
+ * call failed. Just drop the frame, we cannot rollback and pass
+ * the frame to mac80211 because the skb->cb has now been tainted.
+ */
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
- __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- return -EIO;
+ clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ dev_kfree_skb_any(entry->skb);
+ entry->skb = NULL;
+ return 0;
}
if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
rt2x00queue_map_txskb(queue->rt2x00dev, skb);
- __set_bit(ENTRY_DATA_PENDING, &entry->flags);
+ set_bit(ENTRY_DATA_PENDING, &entry->flags);
rt2x00queue_index_inc(queue, Q_INDEX);
rt2x00queue_write_tx_descriptor(entry, &txdesc);
@@ -653,6 +745,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
queue->rt2x00dev = rt2x00dev;
queue->qid = qid;
+ queue->txop = 0;
queue->aifs = 2;
queue->cw_min = 5;
queue->cw_max = 10;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index ff78e52ce43..9dbf04f0f04 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -87,10 +87,13 @@ enum data_queue_qid {
*
* @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX
* @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
+ * @FRAME_DESC_IV_STRIPPED: Frame contained a IV/EIV provided by
+ * mac80211 but was stripped for processing by the driver.
*/
enum skb_frame_desc_flags {
- SKBDESC_DMA_MAPPED_RX = (1 << 0),
- SKBDESC_DMA_MAPPED_TX = (1 << 1),
+ SKBDESC_DMA_MAPPED_RX = 1 << 0,
+ SKBDESC_DMA_MAPPED_TX = 1 << 1,
+ FRAME_DESC_IV_STRIPPED = 1 << 2,
};
/**
@@ -104,6 +107,8 @@ enum skb_frame_desc_flags {
* @desc: Pointer to descriptor part of the frame.
* Note that this pointer could point to something outside
* of the scope of the skb->data pointer.
+ * @iv: IV data used during encryption/decryption.
+ * @eiv: EIV data used during encryption/decryption.
* @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
* @entry: The entry to which this sk buffer belongs.
*/
@@ -113,6 +118,9 @@ struct skb_frame_desc {
unsigned int desc_len;
void *desc;
+ __le32 iv;
+ __le32 eiv;
+
dma_addr_t skb_dma;
struct queue_entry *entry;
@@ -132,13 +140,14 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
/**
* enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
*
- * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value,
- * or does it contain the bitrate itself.
+ * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
+ * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
* @RXDONE_MY_BSS: Does this frame originate from device's BSS.
*/
enum rxdone_entry_desc_flags {
RXDONE_SIGNAL_PLCP = 1 << 0,
- RXDONE_MY_BSS = 1 << 1,
+ RXDONE_SIGNAL_BITRATE = 1 << 1,
+ RXDONE_MY_BSS = 1 << 2,
};
/**
@@ -152,7 +161,11 @@ enum rxdone_entry_desc_flags {
* @size: Data size of the received frame.
* @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
* @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
-
+ * @cipher: Cipher type used during decryption.
+ * @cipher_status: Decryption status.
+ * @iv: IV data used during decryption.
+ * @eiv: EIV data used during decryption.
+ * @icv: ICV data used during decryption.
*/
struct rxdone_entry_desc {
u64 timestamp;
@@ -161,6 +174,12 @@ struct rxdone_entry_desc {
int size;
int flags;
int dev_flags;
+ u8 cipher;
+ u8 cipher_status;
+
+ __le32 iv;
+ __le32 eiv;
+ __le32 icv;
};
/**
@@ -206,6 +225,10 @@ struct txdone_entry_desc {
* @ENTRY_TXD_BURST: This frame belongs to the same burst event.
* @ENTRY_TXD_ACK: An ACK is required for this frame.
* @ENTRY_TXD_RETRY_MODE: When set, the long retry count is used.
+ * @ENTRY_TXD_ENCRYPT: This frame should be encrypted.
+ * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
+ * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
+ * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
*/
enum txentry_desc_flags {
ENTRY_TXD_RTS_FRAME,
@@ -218,6 +241,10 @@ enum txentry_desc_flags {
ENTRY_TXD_BURST,
ENTRY_TXD_ACK,
ENTRY_TXD_RETRY_MODE,
+ ENTRY_TXD_ENCRYPT,
+ ENTRY_TXD_ENCRYPT_PAIRWISE,
+ ENTRY_TXD_ENCRYPT_IV,
+ ENTRY_TXD_ENCRYPT_MMIC,
};
/**
@@ -236,6 +263,9 @@ enum txentry_desc_flags {
* @ifs: IFS value.
* @cw_min: cwmin value.
* @cw_max: cwmax value.
+ * @cipher: Cipher type used for encryption.
+ * @key_idx: Key index used for encryption.
+ * @iv_offset: Position where IV should be inserted by hardware.
*/
struct txentry_desc {
unsigned long flags;
@@ -252,6 +282,10 @@ struct txentry_desc {
short ifs;
short cw_min;
short cw_max;
+
+ enum cipher cipher;
+ u16 key_idx;
+ u16 iv_offset;
};
/**
@@ -335,6 +369,7 @@ enum queue_index {
* @length: Number of frames in queue.
* @index: Index pointers to entry positions in the queue,
* use &enum queue_index to get a specific index field.
+ * @txop: maximum burst time.
* @aifs: The aifs value for outgoing frames (field ignored in RX queue).
* @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
* @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
@@ -354,6 +389,7 @@ struct data_queue {
unsigned short length;
unsigned short index[Q_INDEX_MAX];
+ unsigned short txop;
unsigned short aifs;
unsigned short cw_min;
unsigned short cw_max;
@@ -484,25 +520,51 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
}
/**
- * rt2x00_desc_read - Read a word from the hardware descriptor.
+ * _rt2x00_desc_read - Read a word from the hardware descriptor.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be read.
+ * @value: Address where the descriptor value should be written into.
+ */
+static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
+{
+ *value = desc[word];
+}
+
+/**
+ * rt2x00_desc_read - Read a word from the hardware descriptor, this
+ * function will take care of the byte ordering.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be read.
* @value: Address where the descriptor value should be written into.
*/
static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
{
- *value = le32_to_cpu(desc[word]);
+ __le32 tmp;
+ _rt2x00_desc_read(desc, word, &tmp);
+ *value = le32_to_cpu(tmp);
+}
+
+/**
+ * rt2x00_desc_write - write a word to the hardware descriptor, this
+ * function will take care of the byte ordering.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be written.
+ * @value: Value that should be written into the descriptor.
+ */
+static inline void _rt2x00_desc_write(__le32 *desc, const u8 word, __le32 value)
+{
+ desc[word] = value;
}
/**
- * rt2x00_desc_write - wrote a word to the hardware descriptor.
+ * rt2x00_desc_write - write a word to the hardware descriptor.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be written.
* @value: Value that should be written into the descriptor.
*/
static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
{
- desc[word] = cpu_to_le32(value);
+ _rt2x00_desc_write(desc, word, cpu_to_le32(value));
}
#endif /* RT2X00QUEUE_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5651b..c2fba7c9f05 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -27,6 +27,16 @@
#define RT2X00REG_H
/*
+ * RX crypto status
+ */
+enum rx_crypto {
+ RX_CRYPTO_SUCCESS = 0,
+ RX_CRYPTO_FAIL_ICV = 1,
+ RX_CRYPTO_FAIL_MIC = 2,
+ RX_CRYPTO_FAIL_KEY = 3,
+};
+
+/*
* Antenna values
*/
enum antenna {
@@ -104,7 +114,14 @@ enum cipher {
*/
CIPHER_CKIP64 = 5,
CIPHER_CKIP128 = 6,
- CIPHER_TKIP_NO_MIC = 7,
+ CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
+
+/*
+ * Max cipher type.
+ * Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
+ * are excluded due to limitations in mac80211.
+ */
+ CIPHER_MAX = 4,
};
/*
@@ -136,7 +153,7 @@ struct rt2x00_field32 {
*/
#define is_power_of_two(x) ( !((x) & ((x)-1)) )
#define low_bit_mask(x) ( ((x)-1) & ~(x) )
-#define is_valid_mask(x) is_power_of_two(1 + (x) + low_bit_mask(x))
+#define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x))
/*
* Macro's to find first set bit in a variable.
@@ -173,8 +190,7 @@ struct rt2x00_field32 {
* does not exceed the given typelimit.
*/
#define FIELD_CHECK(__mask, __type) \
- BUILD_BUG_ON(!__builtin_constant_p(__mask) || \
- !(__mask) || \
+ BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (__type)(__mask)) \
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index 04b29716d35..c3f53a92180 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -41,20 +41,19 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
/*
* Only continue if there are enabled interfaces.
*/
- if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return 0;
if (state == RFKILL_STATE_UNBLOCKED) {
- INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n");
- __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
+ INFO(rt2x00dev, "RFKILL event: enabling radio.\n");
+ clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
retval = rt2x00lib_enable_radio(rt2x00dev);
} else if (state == RFKILL_STATE_SOFT_BLOCKED) {
- INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n");
- __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
+ INFO(rt2x00dev, "RFKILL event: disabling radio.\n");
+ set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
rt2x00lib_disable_radio(rt2x00dev);
} else {
- WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n",
- state);
+ WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state);
}
return retval;
@@ -64,7 +63,12 @@ static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state)
{
struct rt2x00_dev *rt2x00dev = data;
- *state = rt2x00dev->rfkill->state;
+ /*
+ * rfkill_poll reports 1 when the key has been pressed and the
+ * radio should be blocked.
+ */
+ *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ?
+ RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
return 0;
}
@@ -73,19 +77,18 @@ static void rt2x00rfkill_poll(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, rfkill_work.work);
- int state;
+ enum rfkill_state state;
- if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
+ if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) ||
+ !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return;
/*
- * rfkill_poll reports 1 when the key has been pressed and the
- * radio should be blocked.
+ * Poll latest state and report it to rfkill who should sort
+ * out if the state should be toggled or not.
*/
- state = !rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ?
- RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
-
- rfkill_force_state(rt2x00dev->rfkill, state);
+ if (!rt2x00rfkill_get_state(rt2x00dev, &state))
+ rfkill_force_state(rt2x00dev->rfkill, state);
queue_delayed_work(rt2x00dev->hw->workqueue,
&rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL);
@@ -93,8 +96,8 @@ static void rt2x00rfkill_poll(struct work_struct *work)
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
- !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+ if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
+ test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
return;
if (rfkill_register(rt2x00dev->rfkill)) {
@@ -114,7 +117,7 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
return;
@@ -127,21 +130,30 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy);
+
+ if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
return;
- rt2x00dev->rfkill =
- rfkill_allocate(wiphy_dev(rt2x00dev->hw->wiphy), RFKILL_TYPE_WLAN);
+ rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN);
if (!rt2x00dev->rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
return;
}
+ __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state);
+
rt2x00dev->rfkill->name = rt2x00dev->ops->name;
rt2x00dev->rfkill->data = rt2x00dev;
- rt2x00dev->rfkill->state = -1;
rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
- rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state;
+ if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) {
+ rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state;
+ rt2x00dev->rfkill->state =
+ rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ?
+ RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED;
+ } else {
+ rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED;
+ }
INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll);
@@ -150,8 +162,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
- !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+ if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags))
return;
cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 2050227ea53..b73a7e0aeed 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -163,16 +163,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct txdone_entry_desc txdesc;
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
/*
- * Remove the descriptor data from the buffer.
- */
- skb_pull(entry->skb, entry->queue->desc_size);
-
- /*
* Obtain the status about this packet.
* Note that when the status is 0 it does not mean the
* frame was send out correctly. It only means the frame
@@ -224,6 +219,12 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry)
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
+ /*
+ * Make sure the skb->data pointer points to the frame, not the
+ * descriptor.
+ */
+ skb_pull(entry->skb, entry->queue->desc_size);
+
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
@@ -232,7 +233,7 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
{
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
- if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+ if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
}
@@ -283,7 +284,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u8 rxd[32];
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
@@ -293,7 +294,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
* a problem.
*/
if (urb->actual_length < entry->queue->desc_size || urb->status) {
- __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
usb_submit_urb(urb, GFP_ATOMIC);
return;
}
@@ -361,7 +362,7 @@ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
entry->skb->data, entry->skb->len,
rt2x00usb_interrupt_rxdone, entry);
- __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
}
EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 087e90b328c..a461620b489 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -38,6 +38,13 @@
#include "rt61pci.h"
/*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 0;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
* Register access.
* BBP and RF register require indirect register access,
* and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this.
@@ -156,7 +163,7 @@ rf_write:
rt2x00_rf_write(rt2x00dev, word, value);
}
-#ifdef CONFIG_RT61PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
/*
* This function is only called from rt61pci_led_brightness()
* make gcc happy by placing this function inside the
@@ -188,7 +195,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
-#endif /* CONFIG_RT61PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
{
@@ -264,7 +271,7 @@ static const struct rt2x00debug rt61pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT61PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -274,9 +281,9 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
}
#else
#define rt61pci_rfkill_poll NULL
-#endif /* CONFIG_RT61PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
-#ifdef CONFIG_RT61PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt61pci_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -341,11 +348,209 @@ static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt61pci_blink_set;
led->flags = LED_INITIALIZED;
}
-#endif /* CONFIG_RT61PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
*/
+static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_key_entry key_entry;
+ struct rt2x00_field32 field;
+ u32 mask;
+ u32 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * rt2x00lib can't determine the correct free
+ * key_idx for shared keys. We have 1 register
+ * with key valid bits. The goal is simple, read
+ * the register, if that is full we have no slots
+ * left.
+ * Note that each BSS is allowed to have up to 4
+ * shared keys, so put a mask over the allowed
+ * entries.
+ */
+ mask = (0xf << crypto->bssidx);
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg &= mask;
+
+ if (reg && reg == mask)
+ return -ENOSPC;
+
+ key->hw_key_idx += reg ? ffz(reg) : 0;
+
+ /*
+ * Upload key to hardware
+ */
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ reg = SHARED_KEY_ENTRY(key->hw_key_idx);
+ rt2x00pci_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
+
+ /*
+ * The cipher types are stored over 2 registers.
+ * bssidx 0 and 1 keys are stored in SEC_CSR1 and
+ * bssidx 1 and 2 keys are stored in SEC_CSR5.
+ * Using the correct defines correctly will cause overhead,
+ * so just calculate the correct offset.
+ */
+ if (key->hw_key_idx < 8) {
+ field.bit_offset = (3 * key->hw_key_idx);
+ field.bit_mask = 0x7 << field.bit_offset;
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR1, &reg);
+ rt2x00_set_field32(&reg, field, crypto->cipher);
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg);
+ } else {
+ field.bit_offset = (3 * (key->hw_key_idx - 8));
+ field.bit_mask = 0x7 << field.bit_offset;
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR5, &reg);
+ rt2x00_set_field32(&reg, field, crypto->cipher);
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg);
+ }
+
+ /*
+ * The driver does not support the IV/EIV generation
+ * in hardware. However it doesn't support the IV/EIV
+ * inside the ieee80211 frame either, but requires it
+ * to be provided seperately for the descriptor.
+ * rt2x00lib will cut the IV/EIV data out of all frames
+ * given to us by mac80211, but we must tell mac80211
+ * to generate the IV/EIV data.
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ }
+
+ /*
+ * SEC_CSR0 contains only single-bit fields to indicate
+ * a particular key is valid. Because using the FIELD32()
+ * defines directly will cause a lot of overhead we use
+ * a calculation to determine the correct bit directly.
+ */
+ mask = 1 << key->hw_key_idx;
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg);
+
+ return 0;
+}
+
+static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_pairwise_ta_entry addr_entry;
+ struct hw_key_entry key_entry;
+ u32 mask;
+ u32 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * rt2x00lib can't determine the correct free
+ * key_idx for pairwise keys. We have 2 registers
+ * with key valid bits. The goal is simple, read
+ * the first register, if that is full move to
+ * the next register.
+ * When both registers are full, we drop the key,
+ * otherwise we use the first invalid entry.
+ */
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ if (reg && reg == ~0) {
+ key->hw_key_idx = 32;
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ if (reg && reg == ~0)
+ return -ENOSPC;
+ }
+
+ key->hw_key_idx += reg ? ffz(reg) : 0;
+
+ /*
+ * Upload key to hardware
+ */
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ memset(&addr_entry, 0, sizeof(addr_entry));
+ memcpy(&addr_entry, crypto->address, ETH_ALEN);
+ addr_entry.cipher = crypto->cipher;
+
+ reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+ rt2x00pci_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
+
+ reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
+ rt2x00pci_register_multiwrite(rt2x00dev, reg,
+ &addr_entry, sizeof(addr_entry));
+
+ /*
+ * Enable pairwise lookup table for given BSS idx,
+ * without this received frames will not be decrypted
+ * by the hardware.
+ */
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR4, &reg);
+ reg |= (1 << crypto->bssidx);
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg);
+
+ /*
+ * The driver does not support the IV/EIV generation
+ * in hardware. However it doesn't support the IV/EIV
+ * inside the ieee80211 frame either, but requires it
+ * to be provided seperately for the descriptor.
+ * rt2x00lib will cut the IV/EIV data out of all frames
+ * given to us by mac80211, but we must tell mac80211
+ * to generate the IV/EIV data.
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ }
+
+ /*
+ * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
+ * a particular key is valid. Because using the FIELD32()
+ * defines directly will cause a lot of overhead we use
+ * a calculation to determine the correct bit directly.
+ */
+ if (key->hw_key_idx < 32) {
+ mask = 1 << key->hw_key_idx;
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg);
+ } else {
+ mask = 1 << (key->hw_key_idx - 32);
+
+ rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg);
+ }
+
+ return 0;
+}
+
static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
@@ -440,6 +645,30 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
}
+
+static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u16 eeprom;
+ short lna_gain = 0;
+
+ if (libconf->band == IEEE80211_BAND_2GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+ } else {
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+ }
+
+ rt2x00dev->lna_gain = lna_gain;
+}
+
static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
const int basic_rate_mask)
{
@@ -758,6 +987,9 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
+ /* Always recalculate LNA gain before changing configuration */
+ rt61pci_config_lna_gain(rt2x00dev, libconf);
+
if (flags & CONFIG_UPDATE_PHYMODE)
rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
@@ -1246,16 +1478,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
- rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
- rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC0_TX_OP, 0);
- rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC1_TX_OP, 0);
- rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
-
- rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
- rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC2_TX_OP, 192);
- rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC3_TX_OP, 48);
- rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-
/*
* Clear all beacons
* For the Beacon base registers we only need to clear
@@ -1533,8 +1755,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
- struct txentry_desc *txdesc)
+ struct sk_buff *skb,
+ struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
@@ -1548,7 +1770,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
@@ -1561,6 +1783,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+ _rt2x00_desc_write(txd, 3, skbdesc->iv);
+ _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+ }
+
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
@@ -1595,11 +1822,15 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+ rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
+ test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
+ test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
rt2x00_set_field32(&word, TXD_W0_BURST,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
rt2x00_desc_write(txd, 0, word);
}
@@ -1676,40 +1907,27 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
*/
static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
{
- u16 eeprom;
- u8 offset;
+ u8 offset = rt2x00dev->lna_gain;
u8 lna;
lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
switch (lna) {
case 3:
- offset = 90;
+ offset += 90;
break;
case 2:
- offset = 74;
+ offset += 74;
break;
case 1:
- offset = 64;
+ offset += 64;
break;
default:
return 0;
}
if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
- offset += 14;
-
if (lna == 3 || lna == 2)
offset += 10;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
- offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
- } else {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
- offset += 14;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
- offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
}
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
@@ -1718,6 +1936,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
static void rt61pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
u32 word0;
u32 word1;
@@ -1728,6 +1947,38 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+ rxdesc->cipher =
+ rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+ rxdesc->cipher_status =
+ rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
+ }
+
+ if (rxdesc->cipher != CIPHER_NONE) {
+ _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv);
+ _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->eiv);
+ _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
+
+ /*
+ * Hardware has stripped IV/EIV data from 802.11 frame during
+ * decryption. It has provided the data seperately but rt2x00lib
+ * should decide if it should be reinserted.
+ */
+ rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+ /*
+ * FIXME: Legacy driver indicates that the frame does
+ * contain the Michael Mic. Unfortunately, in rt2x00
+ * the MIC seems to be missing completely...
+ */
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+ if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+ rxdesc->flags |= RX_FLAG_DECRYPTED;
+ else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+ rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+ }
+
/*
* Obtain the status about this packet.
* When frame was received with an OFDM bitrate,
@@ -1735,11 +1986,13 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
* a CCK bitrate the signal is the rate in 100kbit/s.
*/
rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
- rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
+ rxdesc->rssi = rt61pci_agc_to_rssi(rt2x00dev, word1);
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+ else
+ rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
}
@@ -1860,7 +2113,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
if (!reg && !reg_mcu)
return IRQ_NONE;
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
/*
@@ -2060,10 +2313,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT61PCI_RFKILL
+#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT61PCI_RFKILL */
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Read frequency offset and RF programming sequence.
@@ -2121,7 +2374,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* If the eeprom value is invalid,
* switch to default led mode.
*/
-#ifdef CONFIG_RT61PCI_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
@@ -2155,7 +2408,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_A));
-#endif /* CONFIG_RT61PCI_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
return 0;
}
@@ -2274,10 +2527,11 @@ static const struct rf_channel rf_vals_seq[] = {
{ 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000c0a23 },
};
-static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
- u8 *txpower;
+ struct channel_info *info;
+ char *tx_power;
unsigned int i;
/*
@@ -2294,20 +2548,10 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
EEPROM_MAC_ADDR_0));
/*
- * Convert tx_power array in eeprom.
- */
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
- /*
* Initialize hw_mode information.
*/
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) {
spec->num_channels = 14;
@@ -2321,13 +2565,28 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(&rt2x00dev->chip, RF5325)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_seq);
+ }
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
+ /*
+ * Create channel information array
+ */
+ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
- spec->tx_power_a = txpower;
+ spec->channels_info = info;
+
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
+ for (i = 0; i < 14; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+ if (spec->num_channels > 14) {
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+ for (i = 14; i < spec->num_channels; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
}
+
+ return 0;
}
static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -2348,13 +2607,17 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw specifications.
*/
- rt61pci_probe_hw_mode(rt2x00dev);
+ retval = rt61pci_probe_hw_mode(rt2x00dev);
+ if (retval)
+ return retval;
/*
* This device requires firmware and DMA mapped skbs.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+ if (!modparam_nohwcrypt)
+ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
/*
* Set the rssi offset.
@@ -2381,6 +2644,63 @@ static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
return 0;
}
+static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+ struct rt2x00_field32 field;
+ int retval;
+ u32 reg;
+
+ /*
+ * First pass the configuration through rt2x00lib, that will
+ * update the queue settings and validate the input. After that
+ * we are free to update the registers based on the value
+ * in the queue parameter.
+ */
+ retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ if (retval)
+ return retval;
+
+ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+
+ /* Update WMM TXOP register */
+ if (queue_idx < 2) {
+ field.bit_offset = queue_idx * 16;
+ field.bit_mask = 0xffff << field.bit_offset;
+
+ rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
+ rt2x00_set_field32(&reg, field, queue->txop);
+ rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
+ } else if (queue_idx < 4) {
+ field.bit_offset = (queue_idx - 2) * 16;
+ field.bit_mask = 0xffff << field.bit_offset;
+
+ rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
+ rt2x00_set_field32(&reg, field, queue->txop);
+ rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
+ }
+
+ /* Update WMM registers */
+ field.bit_offset = queue_idx * 4;
+ field.bit_mask = 0xf << field.bit_offset;
+
+ rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->aifs);
+ rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_min);
+ rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_max);
+ rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg);
+
+ return 0;
+}
+
static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -2404,10 +2724,11 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.config = rt2x00mac_config,
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2x00mac_configure_filter,
+ .set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt61pci_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
+ .conf_tx = rt61pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
};
@@ -2432,6 +2753,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.write_beacon = rt61pci_write_beacon,
.kick_tx_queue = rt61pci_kick_tx_queue,
.fill_rxdone = rt61pci_fill_rxdone,
+ .config_shared_key = rt61pci_config_shared_key,
+ .config_pairwise_key = rt61pci_config_pairwise_key,
.config_filter = rt61pci_config_filter,
.config_intf = rt61pci_config_intf,
.config_erp = rt61pci_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 1004d5b899e..8ec1451308c 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -134,6 +134,16 @@
#define PAIRWISE_KEY_TABLE_BASE 0x1200
#define PAIRWISE_TA_TABLE_BASE 0x1a00
+#define SHARED_KEY_ENTRY(__idx) \
+ ( SHARED_KEY_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+ ( PAIRWISE_KEY_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+ ( PAIRWISE_TA_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
struct hw_key_entry {
u8 key[16];
u8 tx_mic[8];
@@ -142,7 +152,8 @@ struct hw_key_entry {
struct hw_pairwise_ta_entry {
u8 address[6];
- u8 reserved[2];
+ u8 cipher;
+ u8 reserved;
} __attribute__ ((packed));
/*
@@ -662,6 +673,10 @@ struct hw_pairwise_ta_entry {
* SEC_CSR4: Pairwise key table lookup control.
*/
#define SEC_CSR4 0x30b0
+#define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008)
/*
* SEC_CSR5: shared key table security mode register.
@@ -1428,8 +1443,10 @@ struct hw_pairwise_ta_entry {
/*
* Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
*/
-#define RXD_W4_RESERVED FIELD32(0xffffffff)
+#define RXD_W4_ICV FIELD32(0xffffffff)
/*
* the above 20-byte is called RXINFO and will be DMAed to MAC RX block
@@ -1465,17 +1482,10 @@ struct hw_pairwise_ta_entry {
#define MAX_TXPOWER 31
#define DEFAULT_TXPOWER 24
-#define TXPOWER_FROM_DEV(__txpower) \
-({ \
- ((__txpower) > MAX_TXPOWER) ? \
- DEFAULT_TXPOWER : (__txpower); \
-})
-
-#define TXPOWER_TO_DEV(__txpower) \
-({ \
- ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
- (__txpower)); \
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
#endif /* RT61PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9761eaaa08b..934f8e03c5a 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -37,6 +37,13 @@
#include "rt73usb.h"
/*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 0;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
* Register access.
* All access to the CSR registers will go through the methods
* rt73usb_register_read and rt73usb_register_write.
@@ -285,7 +292,7 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT73USB_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt73usb_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -352,11 +359,224 @@ static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
led->led_dev.blink_set = rt73usb_blink_set;
led->flags = LED_INITIALIZED;
}
-#endif /* CONFIG_RT73USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
*/
+static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_key_entry key_entry;
+ struct rt2x00_field32 field;
+ int timeout;
+ u32 mask;
+ u32 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * rt2x00lib can't determine the correct free
+ * key_idx for shared keys. We have 1 register
+ * with key valid bits. The goal is simple, read
+ * the register, if that is full we have no slots
+ * left.
+ * Note that each BSS is allowed to have up to 4
+ * shared keys, so put a mask over the allowed
+ * entries.
+ */
+ mask = (0xf << crypto->bssidx);
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg &= mask;
+
+ if (reg && reg == mask)
+ return -ENOSPC;
+
+ key->hw_key_idx += reg ? ffz(reg) : 0;
+
+ /*
+ * Upload key to hardware
+ */
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ reg = SHARED_KEY_ENTRY(key->hw_key_idx);
+ timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, reg,
+ &key_entry,
+ sizeof(key_entry),
+ timeout);
+
+ /*
+ * The cipher types are stored over 2 registers.
+ * bssidx 0 and 1 keys are stored in SEC_CSR1 and
+ * bssidx 1 and 2 keys are stored in SEC_CSR5.
+ * Using the correct defines correctly will cause overhead,
+ * so just calculate the correct offset.
+ */
+ if (key->hw_key_idx < 8) {
+ field.bit_offset = (3 * key->hw_key_idx);
+ field.bit_mask = 0x7 << field.bit_offset;
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+ rt2x00_set_field32(&reg, field, crypto->cipher);
+ rt73usb_register_write(rt2x00dev, SEC_CSR1, reg);
+ } else {
+ field.bit_offset = (3 * (key->hw_key_idx - 8));
+ field.bit_mask = 0x7 << field.bit_offset;
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+ rt2x00_set_field32(&reg, field, crypto->cipher);
+ rt73usb_register_write(rt2x00dev, SEC_CSR5, reg);
+ }
+
+ /*
+ * The driver does not support the IV/EIV generation
+ * in hardware. However it doesn't support the IV/EIV
+ * inside the ieee80211 frame either, but requires it
+ * to be provided seperately for the descriptor.
+ * rt2x00lib will cut the IV/EIV data out of all frames
+ * given to us by mac80211, but we must tell mac80211
+ * to generate the IV/EIV data.
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ }
+
+ /*
+ * SEC_CSR0 contains only single-bit fields to indicate
+ * a particular key is valid. Because using the FIELD32()
+ * defines directly will cause a lot of overhead we use
+ * a calculation to determine the correct bit directly.
+ */
+ mask = 1 << key->hw_key_idx;
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt73usb_register_write(rt2x00dev, SEC_CSR0, reg);
+
+ return 0;
+}
+
+static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_pairwise_ta_entry addr_entry;
+ struct hw_key_entry key_entry;
+ int timeout;
+ u32 mask;
+ u32 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * rt2x00lib can't determine the correct free
+ * key_idx for pairwise keys. We have 2 registers
+ * with key valid bits. The goal is simple, read
+ * the first register, if that is full move to
+ * the next register.
+ * When both registers are full, we drop the key,
+ * otherwise we use the first invalid entry.
+ */
+ rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ if (reg && reg == ~0) {
+ key->hw_key_idx = 32;
+ rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ if (reg && reg == ~0)
+ return -ENOSPC;
+ }
+
+ key->hw_key_idx += reg ? ffz(reg) : 0;
+
+ /*
+ * Upload key to hardware
+ */
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+ timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, reg,
+ &key_entry,
+ sizeof(key_entry),
+ timeout);
+
+ /*
+ * Send the address and cipher type to the hardware register.
+ * This data fits within the CSR cache size, so we can use
+ * rt73usb_register_multiwrite() directly.
+ */
+ memset(&addr_entry, 0, sizeof(addr_entry));
+ memcpy(&addr_entry, crypto->address, ETH_ALEN);
+ addr_entry.cipher = crypto->cipher;
+
+ reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
+ rt73usb_register_multiwrite(rt2x00dev, reg,
+ &addr_entry, sizeof(addr_entry));
+
+ /*
+ * Enable pairwise lookup table for given BSS idx,
+ * without this received frames will not be decrypted
+ * by the hardware.
+ */
+ rt73usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+ reg |= (1 << crypto->bssidx);
+ rt73usb_register_write(rt2x00dev, SEC_CSR4, reg);
+
+ /*
+ * The driver does not support the IV/EIV generation
+ * in hardware. However it doesn't support the IV/EIV
+ * inside the ieee80211 frame either, but requires it
+ * to be provided seperately for the descriptor.
+ * rt2x00lib will cut the IV/EIV data out of all frames
+ * given to us by mac80211, but we must tell mac80211
+ * to generate the IV/EIV data.
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ }
+
+ /*
+ * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
+ * a particular key is valid. Because using the FIELD32()
+ * defines directly will cause a lot of overhead we use
+ * a calculation to determine the correct bit directly.
+ */
+ if (key->hw_key_idx < 32) {
+ mask = 1 << key->hw_key_idx;
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt73usb_register_write(rt2x00dev, SEC_CSR2, reg);
+ } else {
+ mask = 1 << (key->hw_key_idx - 32);
+
+ rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ if (crypto->cmd == SET_KEY)
+ reg |= mask;
+ else if (crypto->cmd == DISABLE_KEY)
+ reg &= ~mask;
+ rt73usb_register_write(rt2x00dev, SEC_CSR3, reg);
+ }
+
+ return 0;
+}
+
static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
@@ -451,6 +671,26 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
}
+static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u16 eeprom;
+ short lna_gain = 0;
+
+ if (libconf->band == IEEE80211_BAND_2GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+ } else {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+ }
+
+ rt2x00dev->lna_gain = lna_gain;
+}
+
static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
const int basic_rate_mask)
{
@@ -705,6 +945,9 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
+ /* Always recalculate LNA gain before changing configuration */
+ rt73usb_config_lna_gain(rt2x00dev, libconf);
+
if (flags & CONFIG_UPDATE_PHYMODE)
rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
@@ -1034,16 +1277,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
- rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
- rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC0_TX_OP, 0);
- rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC1_TX_OP, 0);
- rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
-
- rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
- rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC2_TX_OP, 192);
- rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC3_TX_OP, 48);
- rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-
rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -1265,8 +1498,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
- struct txentry_desc *txdesc)
+ struct sk_buff *skb,
+ struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
@@ -1280,7 +1513,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
rt2x00_desc_write(txd, 1, word);
@@ -1292,6 +1525,11 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+ _rt2x00_desc_write(txd, 3, skbdesc->iv);
+ _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+ }
+
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
TXPOWER_TO_DEV(rt2x00dev->tx_power));
@@ -1313,12 +1551,15 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
- skb->len - skbdesc->desc_len);
+ rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
+ test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
+ test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
rt2x00_set_field32(&word, TXD_W0_BURST2,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
rt2x00_desc_write(txd, 0, word);
}
@@ -1331,7 +1572,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
unsigned int beacon_base;
u32 reg;
- u32 word, len;
/*
* Add the descriptor in front of the skb.
@@ -1341,17 +1581,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
skbdesc->desc = entry->skb->data;
/*
- * Adjust the beacon databyte count. The current number is
- * calculated before this function gets called, but falsely
- * assumes that the descriptor was already present in the SKB.
- */
- rt2x00_desc_read(skbdesc->desc, 0, &word);
- len = rt2x00_get_field32(word, TXD_W0_DATABYTE_COUNT);
- len += skbdesc->desc_len;
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, len);
- rt2x00_desc_write(skbdesc->desc, 0, word);
-
- /*
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
@@ -1422,20 +1651,19 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
*/
static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
{
- u16 eeprom;
- u8 offset;
+ u8 offset = rt2x00dev->lna_gain;
u8 lna;
lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
switch (lna) {
case 3:
- offset = 90;
+ offset += 90;
break;
case 2:
- offset = 74;
+ offset += 74;
break;
case 1:
- offset = 64;
+ offset += 64;
break;
default:
return 0;
@@ -1451,15 +1679,6 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
else if (lna == 2)
offset += 8;
}
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
- offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
- } else {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
- offset += 14;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
- offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
}
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
@@ -1468,6 +1687,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
static void rt73usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxd = (__le32 *)entry->skb->data;
u32 word0;
@@ -1489,6 +1709,38 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+ rxdesc->cipher =
+ rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+ rxdesc->cipher_status =
+ rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
+ }
+
+ if (rxdesc->cipher != CIPHER_NONE) {
+ _rt2x00_desc_read(rxd, 2, &rxdesc->iv);
+ _rt2x00_desc_read(rxd, 3, &rxdesc->eiv);
+ _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+
+ /*
+ * Hardware has stripped IV/EIV data from 802.11 frame during
+ * decryption. It has provided the data seperately but rt2x00lib
+ * should decide if it should be reinserted.
+ */
+ rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+ /*
+ * FIXME: Legacy driver indicates that the frame does
+ * contain the Michael Mic. Unfortunately, in rt2x00
+ * the MIC seems to be missing completely...
+ */
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+ if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+ rxdesc->flags |= RX_FLAG_DECRYPTED;
+ else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+ rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+ }
+
/*
* Obtain the status about this packet.
* When frame was received with an OFDM bitrate,
@@ -1496,11 +1748,13 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
* a CCK bitrate the signal is the rate in 100kbit/s.
*/
rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
- rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
+ rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+ else
+ rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
@@ -1678,7 +1932,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led settings, for correct led behaviour.
*/
-#ifdef CONFIG_RT73USB_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
@@ -1711,7 +1965,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_A));
-#endif /* CONFIG_RT73USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
return 0;
}
@@ -1852,10 +2106,11 @@ static const struct rf_channel rf_vals_5225_2527[] = {
};
-static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
- u8 *txpower;
+ struct channel_info *info;
+ char *tx_power;
unsigned int i;
/*
@@ -1872,20 +2127,10 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
EEPROM_MAC_ADDR_0));
/*
- * Convert tx_power array in eeprom.
- */
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
- /*
* Initialize hw_mode information.
*/
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
if (rt2x00_rf(&rt2x00dev->chip, RF2528)) {
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
@@ -1903,14 +2148,26 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->channels = rf_vals_5225_2527;
}
- if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF5226)) {
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
+ /*
+ * Create channel information array
+ */
+ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
- spec->tx_power_a = txpower;
+ spec->channels_info = info;
+
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
+ for (i = 0; i < 14; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+ if (spec->num_channels > 14) {
+ tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+ for (i = 14; i < spec->num_channels; i++)
+ info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
}
+
+ return 0;
}
static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1931,13 +2188,17 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw specifications.
*/
- rt73usb_probe_hw_mode(rt2x00dev);
+ retval = rt73usb_probe_hw_mode(rt2x00dev);
+ if (retval)
+ return retval;
/*
* This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+ if (!modparam_nohwcrypt)
+ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
/*
* Set the rssi offset.
@@ -1964,6 +2225,63 @@ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
return 0;
}
+static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+ struct rt2x00_field32 field;
+ int retval;
+ u32 reg;
+
+ /*
+ * First pass the configuration through rt2x00lib, that will
+ * update the queue settings and validate the input. After that
+ * we are free to update the registers based on the value
+ * in the queue parameter.
+ */
+ retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ if (retval)
+ return retval;
+
+ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+
+ /* Update WMM TXOP register */
+ if (queue_idx < 2) {
+ field.bit_offset = queue_idx * 16;
+ field.bit_mask = 0xffff << field.bit_offset;
+
+ rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
+ rt2x00_set_field32(&reg, field, queue->txop);
+ rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
+ } else if (queue_idx < 4) {
+ field.bit_offset = (queue_idx - 2) * 16;
+ field.bit_mask = 0xffff << field.bit_offset;
+
+ rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
+ rt2x00_set_field32(&reg, field, queue->txop);
+ rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
+ }
+
+ /* Update WMM registers */
+ field.bit_offset = queue_idx * 4;
+ field.bit_mask = 0xf << field.bit_offset;
+
+ rt73usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->aifs);
+ rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg);
+
+ rt73usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_min);
+ rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg);
+
+ rt73usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_max);
+ rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg);
+
+ return 0;
+}
+
#if 0
/*
* Mac80211 demands get_tsf must be atomic.
@@ -1997,10 +2315,11 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.config = rt2x00mac_config,
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2x00mac_configure_filter,
+ .set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt73usb_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
+ .conf_tx = rt73usb_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
};
@@ -2024,6 +2343,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt73usb_kick_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
+ .config_shared_key = rt73usb_config_shared_key,
+ .config_pairwise_key = rt73usb_config_pairwise_key,
.config_filter = rt73usb_config_filter,
.config_intf = rt73usb_config_intf,
.config_erp = rt73usb_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index 14849350101..868386c457f 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -92,6 +92,16 @@
#define PAIRWISE_KEY_TABLE_BASE 0x1200
#define PAIRWISE_TA_TABLE_BASE 0x1a00
+#define SHARED_KEY_ENTRY(__idx) \
+ ( SHARED_KEY_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+ ( PAIRWISE_KEY_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+ ( PAIRWISE_TA_TABLE_BASE + \
+ ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
struct hw_key_entry {
u8 key[16];
u8 tx_mic[8];
@@ -100,7 +110,8 @@ struct hw_key_entry {
struct hw_pairwise_ta_entry {
u8 address[6];
- u8 reserved[2];
+ u8 cipher;
+ u8 reserved;
} __attribute__ ((packed));
/*
@@ -563,6 +574,10 @@ struct hw_pairwise_ta_entry {
* SEC_CSR4: Pairwise key table lookup control.
*/
#define SEC_CSR4 0x30b0
+#define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008)
/*
* SEC_CSR5: shared key table security mode register.
@@ -1010,8 +1025,10 @@ struct hw_pairwise_ta_entry {
/*
* Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
*/
-#define RXD_W4_RESERVED FIELD32(0xffffffff)
+#define RXD_W4_ICV FIELD32(0xffffffff)
/*
* the above 20-byte is called RXINFO and will be DMAed to MAC RX block
@@ -1033,17 +1050,10 @@ struct hw_pairwise_ta_entry {
#define MAX_TXPOWER 31
#define DEFAULT_TXPOWER 24
-#define TXPOWER_FROM_DEV(__txpower) \
-({ \
- ((__txpower) > MAX_TXPOWER) ? \
- DEFAULT_TXPOWER : (__txpower); \
-})
-
-#define TXPOWER_TO_DEV(__txpower) \
-({ \
- ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
- (__txpower)); \
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+ (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
#endif /* RT73USB_H */
diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
index 082a11f93be..8721282a818 100644
--- a/drivers/net/wireless/rtl8180.h
+++ b/drivers/net/wireless/rtl8180.h
@@ -24,20 +24,6 @@
#define ANAPARAM_PWR1_SHIFT 20
#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT)
-enum rtl8180_tx_desc_flags {
- RTL8180_TX_DESC_FLAG_NO_ENC = (1 << 15),
- RTL8180_TX_DESC_FLAG_TX_OK = (1 << 15),
- RTL8180_TX_DESC_FLAG_SPLCP = (1 << 16),
- RTL8180_TX_DESC_FLAG_RX_UNDER = (1 << 16),
- RTL8180_TX_DESC_FLAG_MOREFRAG = (1 << 17),
- RTL8180_TX_DESC_FLAG_CTS = (1 << 18),
- RTL8180_TX_DESC_FLAG_RTS = (1 << 23),
- RTL8180_TX_DESC_FLAG_LS = (1 << 28),
- RTL8180_TX_DESC_FLAG_FS = (1 << 29),
- RTL8180_TX_DESC_FLAG_DMA = (1 << 30),
- RTL8180_TX_DESC_FLAG_OWN = (1 << 31)
-};
-
struct rtl8180_tx_desc {
__le32 flags;
__le16 rts_duration;
@@ -52,23 +38,6 @@ struct rtl8180_tx_desc {
u32 reserved[2];
} __attribute__ ((packed));
-enum rtl8180_rx_desc_flags {
- RTL8180_RX_DESC_FLAG_ICV_ERR = (1 << 12),
- RTL8180_RX_DESC_FLAG_CRC32_ERR = (1 << 13),
- RTL8180_RX_DESC_FLAG_PM = (1 << 14),
- RTL8180_RX_DESC_FLAG_RX_ERR = (1 << 15),
- RTL8180_RX_DESC_FLAG_BCAST = (1 << 16),
- RTL8180_RX_DESC_FLAG_PAM = (1 << 17),
- RTL8180_RX_DESC_FLAG_MCAST = (1 << 18),
- RTL8180_RX_DESC_FLAG_SPLCP = (1 << 25),
- RTL8180_RX_DESC_FLAG_FOF = (1 << 26),
- RTL8180_RX_DESC_FLAG_DMA_FAIL = (1 << 27),
- RTL8180_RX_DESC_FLAG_LS = (1 << 28),
- RTL8180_RX_DESC_FLAG_FS = (1 << 29),
- RTL8180_RX_DESC_FLAG_EOR = (1 << 30),
- RTL8180_RX_DESC_FLAG_OWN = (1 << 31)
-};
-
struct rtl8180_rx_desc {
__le32 flags;
__le32 flags2;
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index b7172a12c05..df7e78ee8a8 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -110,12 +110,12 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
u32 flags = le32_to_cpu(entry->flags);
- if (flags & RTL8180_RX_DESC_FLAG_OWN)
+ if (flags & RTL818X_RX_DESC_FLAG_OWN)
return;
- if (unlikely(flags & (RTL8180_RX_DESC_FLAG_DMA_FAIL |
- RTL8180_RX_DESC_FLAG_FOF |
- RTL8180_RX_DESC_FLAG_RX_ERR)))
+ if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
+ RTL818X_RX_DESC_FLAG_FOF |
+ RTL818X_RX_DESC_FLAG_RX_ERR)))
goto done;
else {
u32 flags2 = le32_to_cpu(entry->flags2);
@@ -140,7 +140,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.band = dev->conf.channel->band;
rx_status.mactime = le64_to_cpu(entry->tsft);
rx_status.flag |= RX_FLAG_TSFT;
- if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
+ if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
ieee80211_rx_irqsafe(dev, skb, &rx_status);
@@ -154,10 +154,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
done:
entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
- entry->flags = cpu_to_le32(RTL8180_RX_DESC_FLAG_OWN |
+ entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
MAX_RX_SIZE);
if (priv->rx_idx == 31)
- entry->flags |= cpu_to_le32(RTL8180_RX_DESC_FLAG_EOR);
+ entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
priv->rx_idx = (priv->rx_idx + 1) % 32;
}
}
@@ -173,7 +173,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
struct ieee80211_tx_info *info;
u32 flags = le32_to_cpu(entry->flags);
- if (flags & RTL8180_TX_DESC_FLAG_OWN)
+ if (flags & RTL818X_TX_DESC_FLAG_OWN)
return;
ring->idx = (ring->idx + 1) % ring->entries;
@@ -185,7 +185,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
memset(&info->status, 0, sizeof(info->status));
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- if (flags & RTL8180_TX_DESC_FLAG_TX_OK)
+ if (flags & RTL818X_TX_DESC_FLAG_TX_OK)
info->flags |= IEEE80211_TX_STAT_ACK;
else
info->status.excessive_retries = 1;
@@ -252,20 +252,20 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
mapping = pci_map_single(priv->pdev, skb->data,
skb->len, PCI_DMA_TODEVICE);
- tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
- RTL8180_TX_DESC_FLAG_LS |
+ tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS |
+ RTL818X_TX_DESC_FLAG_LS |
(ieee80211_get_tx_rate(dev, info)->hw_value << 24) |
skb->len;
if (priv->r8185)
- tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
- RTL8180_TX_DESC_FLAG_NO_ENC;
+ tx_flags |= RTL818X_TX_DESC_FLAG_DMA |
+ RTL818X_TX_DESC_FLAG_NO_ENC;
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
- tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
+ tx_flags |= RTL818X_TX_DESC_FLAG_RTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
- tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
+ tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
@@ -292,8 +292,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(mapping);
entry->frame_len = cpu_to_le32(skb->len);
- entry->flags2 = info->control.alt_retry_rate_idx >= 0 ?
- ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0;
+ entry->flags2 = info->control.retries[0].rate_idx >= 0 ?
+ ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
entry->retry_limit = info->control.retry_limit;
entry->flags = cpu_to_le32(tx_flags);
__skb_queue_tail(&ring->queue, skb);
@@ -446,10 +446,10 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
*mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
entry->rx_buf = cpu_to_le32(*mapping);
- entry->flags = cpu_to_le32(RTL8180_RX_DESC_FLAG_OWN |
+ entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
MAX_RX_SIZE);
}
- entry->flags |= cpu_to_le32(RTL8180_RX_DESC_FLAG_EOR);
+ entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
return 0;
}
@@ -615,7 +615,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
reg |= RTL818X_CMD_TX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
return 0;
err_free_rings:
@@ -633,7 +633,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
u8 reg;
int i;
- priv->mode = IEEE80211_IF_TYPE_INVALID;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
@@ -661,11 +661,11 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
{
struct rtl8180_priv *priv = dev->priv;
- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@@ -688,7 +688,7 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
}
@@ -855,6 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
priv = dev->priv;
priv->pdev = pdev;
+ dev->max_altrates = 1;
SET_IEEE80211_DEV(dev, &pdev->dev);
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index 5a9515c9996..e82bb4d289e 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -58,12 +58,6 @@ struct rtl8187b_rx_hdr {
/* {rtl8187,rtl8187b}_tx_info is in skb */
-/* Tx flags are common between rtl8187 and rtl8187b */
-#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
-#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
-#define RTL8187_TX_FLAG_CTS (1 << 18)
-#define RTL8187_TX_FLAG_RTS (1 << 23)
-
struct rtl8187_tx_hdr {
__le32 flags;
__le16 rts_duration;
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index ca5deb6244e..431e3c78bf2 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -33,10 +33,13 @@ MODULE_LICENSE("GPL");
static struct usb_device_id rtl8187_table[] __devinitdata = {
/* Asus */
{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},
+ /* Belkin */
+ {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B},
/* Realtek */
{USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187},
{USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
{USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B},
+ {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},
/* Netgear */
{USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
{USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
@@ -187,18 +190,18 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
flags = skb->len;
- flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
+ flags |= RTL818X_TX_DESC_FLAG_NO_ENC;
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
- flags |= RTL8187_TX_FLAG_MORE_FRAG;
+ flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
- flags |= RTL8187_TX_FLAG_RTS;
+ flags |= RTL818X_TX_DESC_FLAG_RTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, info);
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
- flags |= RTL8187_TX_FLAG_CTS;
+ flags |= RTL818X_TX_DESC_FLAG_CTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
@@ -354,7 +357,7 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
rx_status.flag |= RX_FLAG_TSFT;
- if (flags & (1 << 13))
+ if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
ieee80211_rx_irqsafe(dev, skb, &rx_status);
@@ -836,11 +839,11 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
struct rtl8187_priv *priv = dev->priv;
int i;
- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
- case IEEE80211_IF_TYPE_STA:
+ case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@@ -865,7 +868,7 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
{
struct rtl8187_priv *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
mutex_unlock(&priv->conf_mutex);
}
@@ -1057,7 +1060,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
- priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->mode = NL80211_IFTYPE_MONITOR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS;
@@ -1184,6 +1187,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->max_signal = 65;
}
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
" info!\n");
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
index 00900fe16fc..3538b15211b 100644
--- a/drivers/net/wireless/rtl818x.h
+++ b/drivers/net/wireless/rtl818x.h
@@ -193,4 +193,39 @@ struct rtl818x_rf_ops {
void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
};
+/* Tx/Rx flags are common between RTL818X chips */
+
+enum rtl818x_tx_desc_flags {
+ RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15),
+ RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15),
+ RTL818X_TX_DESC_FLAG_SPLCP = (1 << 16),
+ RTL818X_TX_DESC_FLAG_RX_UNDER = (1 << 16),
+ RTL818X_TX_DESC_FLAG_MOREFRAG = (1 << 17),
+ RTL818X_TX_DESC_FLAG_CTS = (1 << 18),
+ RTL818X_TX_DESC_FLAG_RTS = (1 << 23),
+ RTL818X_TX_DESC_FLAG_LS = (1 << 28),
+ RTL818X_TX_DESC_FLAG_FS = (1 << 29),
+ RTL818X_TX_DESC_FLAG_DMA = (1 << 30),
+ RTL818X_TX_DESC_FLAG_OWN = (1 << 31)
+};
+
+enum rtl818x_rx_desc_flags {
+ RTL818X_RX_DESC_FLAG_ICV_ERR = (1 << 12),
+ RTL818X_RX_DESC_FLAG_CRC32_ERR = (1 << 13),
+ RTL818X_RX_DESC_FLAG_PM = (1 << 14),
+ RTL818X_RX_DESC_FLAG_RX_ERR = (1 << 15),
+ RTL818X_RX_DESC_FLAG_BCAST = (1 << 16),
+ RTL818X_RX_DESC_FLAG_PAM = (1 << 17),
+ RTL818X_RX_DESC_FLAG_MCAST = (1 << 18),
+ RTL818X_RX_DESC_FLAG_QOS = (1 << 19), /* RTL8187(B) only */
+ RTL818X_RX_DESC_FLAG_TRSW = (1 << 24), /* RTL8187(B) only */
+ RTL818X_RX_DESC_FLAG_SPLCP = (1 << 25),
+ RTL818X_RX_DESC_FLAG_FOF = (1 << 26),
+ RTL818X_RX_DESC_FLAG_DMA_FAIL = (1 << 27),
+ RTL818X_RX_DESC_FLAG_LS = (1 << 28),
+ RTL818X_RX_DESC_FLAG_FS = (1 << 29),
+ RTL818X_RX_DESC_FLAG_EOR = (1 << 30),
+ RTL818X_RX_DESC_FLAG_OWN = (1 << 31)
+};
+
#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 98df9bc7836..852789ad34b 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -25,7 +25,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/firmware.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
@@ -34,9 +33,6 @@
#include "orinoco.h"
-static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
-static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-
/********************************************************************/
/* Module stuff */
/********************************************************************/
@@ -71,161 +67,11 @@ struct orinoco_pccard {
static int spectrum_cs_config(struct pcmcia_device *link);
static void spectrum_cs_release(struct pcmcia_device *link);
-/********************************************************************/
-/* Firmware downloader */
-/********************************************************************/
-
-/* Position of PDA in the adapter memory */
-#define EEPROM_ADDR 0x3000
-#define EEPROM_LEN 0x200
-#define PDA_OFFSET 0x100
-
-#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
-#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
-
/* Constants for the CISREG_CCSR register */
#define HCR_RUN 0x07 /* run firmware after reset */
#define HCR_IDLE 0x0E /* don't run firmware after reset */
#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
-/*
- * AUX port access. To unlock the AUX port write the access keys to the
- * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
- * register. Then read it and make sure it's HERMES_AUX_ENABLED.
- */
-#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
-#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
-#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
-
-#define HERMES_AUX_PW0 0xFE01
-#define HERMES_AUX_PW1 0xDC23
-#define HERMES_AUX_PW2 0xBA45
-
-/* End markers */
-#define PDI_END 0x00000000 /* End of PDA */
-#define BLOCK_END 0xFFFFFFFF /* Last image block */
-#define TEXT_END 0x1A /* End of text header */
-
-/*
- * The following structures have little-endian fields denoted by
- * the leading underscore. Don't access them directly - use inline
- * functions defined below.
- */
-
-/*
- * The binary image to be downloaded consists of series of data blocks.
- * Each block has the following structure.
- */
-struct dblock {
- __le32 addr; /* adapter address where to write the block */
- __le16 len; /* length of the data only, in bytes */
- char data[0]; /* data to be written */
-} __attribute__ ((packed));
-
-/*
- * Plug Data References are located in in the image after the last data
- * block. They refer to areas in the adapter memory where the plug data
- * items with matching ID should be written.
- */
-struct pdr {
- __le32 id; /* record ID */
- __le32 addr; /* adapter address where to write the data */
- __le32 len; /* expected length of the data, in bytes */
- char next[0]; /* next PDR starts here */
-} __attribute__ ((packed));
-
-
-/*
- * Plug Data Items are located in the EEPROM read from the adapter by
- * primary firmware. They refer to the device-specific data that should
- * be plugged into the secondary firmware.
- */
-struct pdi {
- __le16 len; /* length of ID and data, in words */
- __le16 id; /* record ID */
- char data[0]; /* plug data */
-} __attribute__ ((packed));
-
-
-/* Functions for access to little-endian data */
-static inline u32
-dblock_addr(const struct dblock *blk)
-{
- return le32_to_cpu(blk->addr);
-}
-
-static inline u32
-dblock_len(const struct dblock *blk)
-{
- return le16_to_cpu(blk->len);
-}
-
-static inline u32
-pdr_id(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->id);
-}
-
-static inline u32
-pdr_addr(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->addr);
-}
-
-static inline u32
-pdr_len(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->len);
-}
-
-static inline u32
-pdi_id(const struct pdi *pdi)
-{
- return le16_to_cpu(pdi->id);
-}
-
-/* Return length of the data only, in bytes */
-static inline u32
-pdi_len(const struct pdi *pdi)
-{
- return 2 * (le16_to_cpu(pdi->len) - 1);
-}
-
-
-/* Set address of the auxiliary port */
-static inline void
-spectrum_aux_setaddr(hermes_t *hw, u32 addr)
-{
- hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
- hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
-}
-
-
-/* Open access to the auxiliary port */
-static int
-spectrum_aux_open(hermes_t *hw)
-{
- int i;
-
- /* Already open? */
- if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED)
- return 0;
-
- hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
- hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
- hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
- hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE);
-
- for (i = 0; i < 20; i++) {
- udelay(10);
- if (hermes_read_reg(hw, HERMES_CONTROL) ==
- HERMES_AUX_ENABLED)
- return 0;
- }
-
- return -EBUSY;
-}
-
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
@@ -292,275 +138,29 @@ spectrum_reset(struct pcmcia_device *link, int idle)
return -ENODEV;
}
+/********************************************************************/
+/* Device methods */
+/********************************************************************/
-/*
- * Scan PDR for the record with the specified RECORD_ID.
- * If it's not found, return NULL.
- */
-static struct pdr *
-spectrum_find_pdr(struct pdr *first_pdr, u32 record_id)
-{
- struct pdr *pdr = first_pdr;
-
- while (pdr_id(pdr) != PDI_END) {
- /*
- * PDR area is currently not terminated by PDI_END.
- * It's followed by CRC records, which have the type
- * field where PDR has length. The type can be 0 or 1.
- */
- if (pdr_len(pdr) < 2)
- return NULL;
-
- /* If the record ID matches, we are done */
- if (pdr_id(pdr) == record_id)
- return pdr;
-
- pdr = (struct pdr *) pdr->next;
- }
- return NULL;
-}
-
-
-/* Process one Plug Data Item - find corresponding PDR and plug it */
-static int
-spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
-{
- struct pdr *pdr;
-
- /* Find the PDI corresponding to this PDR */
- pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));
-
- /* No match is found, safe to ignore */
- if (!pdr)
- return 0;
-
- /* Lengths of the data in PDI and PDR must match */
- if (pdi_len(pdi) != pdr_len(pdr))
- return -EINVAL;
-
- /* do the actual plugging */
- spectrum_aux_setaddr(hw, pdr_addr(pdr));
- hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
-
- return 0;
-}
-
-
-/* Read PDA from the adapter */
-static int
-spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
-{
- int ret;
- int pda_size;
-
- /* Issue command to read EEPROM */
- ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
- if (ret)
- return ret;
-
- /* Open auxiliary port */
- ret = spectrum_aux_open(hw);
- if (ret)
- return ret;
-
- /* read PDA from EEPROM */
- spectrum_aux_setaddr(hw, PDA_ADDR);
- hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);
-
- /* Check PDA length */
- pda_size = le16_to_cpu(pda[0]);
- if (pda_size > pda_len)
- return -EINVAL;
-
- return 0;
-}
-
-
-/* Parse PDA and write the records into the adapter */
-static int
-spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
- __le16 *pda)
-{
- int ret;
- struct pdi *pdi;
- struct pdr *first_pdr;
- const struct dblock *blk = first_block;
-
- /* Skip all blocks to locate Plug Data References */
- while (dblock_addr(blk) != BLOCK_END)
- blk = (struct dblock *) &blk->data[dblock_len(blk)];
-
- first_pdr = (struct pdr *) blk;
-
- /* Go through every PDI and plug them into the adapter */
- pdi = (struct pdi *) (pda + 2);
- while (pdi_id(pdi) != PDI_END) {
- ret = spectrum_plug_pdi(hw, first_pdr, pdi);
- if (ret)
- return ret;
-
- /* Increment to the next PDI */
- pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
- }
- return 0;
-}
-
-
-/* Load firmware blocks into the adapter */
-static int
-spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
-{
- const struct dblock *blk;
- u32 blkaddr;
- u32 blklen;
-
- blk = first_block;
- blkaddr = dblock_addr(blk);
- blklen = dblock_len(blk);
-
- while (dblock_addr(blk) != BLOCK_END) {
- spectrum_aux_setaddr(hw, blkaddr);
- hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
- blklen);
-
- blk = (struct dblock *) &blk->data[blklen];
- blkaddr = dblock_addr(blk);
- blklen = dblock_len(blk);
- }
- return 0;
-}
-
-
-/*
- * Process a firmware image - stop the card, load the firmware, reset
- * the card and make sure it responds. For the secondary firmware take
- * care of the PDA - read it and then write it on top of the firmware.
- */
static int
-spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
- const unsigned char *image, int secondary)
+spectrum_cs_hard_reset(struct orinoco_private *priv)
{
- int ret;
- const unsigned char *ptr;
- const struct dblock *first_block;
-
- /* Plug Data Area (PDA) */
- __le16 pda[PDA_WORDS];
-
- /* Binary block begins after the 0x1A marker */
- ptr = image;
- while (*ptr++ != TEXT_END);
- first_block = (const struct dblock *) ptr;
-
- /* Read the PDA */
- if (secondary) {
- ret = spectrum_read_pda(hw, pda, sizeof(pda));
- if (ret)
- return ret;
- }
-
- /* Stop the firmware, so that it can be safely rewritten */
- ret = spectrum_reset(link, 1);
- if (ret)
- return ret;
-
- /* Program the adapter with new firmware */
- ret = spectrum_load_blocks(hw, first_block);
- if (ret)
- return ret;
-
- /* Write the PDA to the adapter */
- if (secondary) {
- ret = spectrum_apply_pda(hw, first_block, pda);
- if (ret)
- return ret;
- }
-
- /* Run the firmware */
- ret = spectrum_reset(link, 0);
- if (ret)
- return ret;
-
- /* Reset hermes chip and make sure it responds */
- ret = hermes_init(hw);
-
- /* hermes_reset() should return 0 with the secondary firmware */
- if (secondary && ret != 0)
- return -ENODEV;
+ struct orinoco_pccard *card = priv->card;
+ struct pcmcia_device *link = card->p_dev;
- /* And this should work with any firmware */
- if (!hermes_present(hw))
- return -ENODEV;
+ /* Soft reset using COR and HCR */
+ spectrum_reset(link, 0);
return 0;
}
-
-/*
- * Download the firmware into the card, this also does a PCMCIA soft
- * reset on the card, to make sure it's in a sane state.
- */
-static int
-spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
-{
- int ret;
- const struct firmware *fw_entry;
-
- if (request_firmware(&fw_entry, primary_fw_name,
- &handle_to_dev(link)) != 0) {
- printk(KERN_ERR PFX "Cannot find firmware: %s\n",
- primary_fw_name);
- return -ENOENT;
- }
-
- /* Load primary firmware */
- ret = spectrum_dl_image(hw, link, fw_entry->data, 0);
- release_firmware(fw_entry);
- if (ret) {
- printk(KERN_ERR PFX "Primary firmware download failed\n");
- return ret;
- }
-
- if (request_firmware(&fw_entry, secondary_fw_name,
- &handle_to_dev(link)) != 0) {
- printk(KERN_ERR PFX "Cannot find firmware: %s\n",
- secondary_fw_name);
- return -ENOENT;
- }
-
- /* Load secondary firmware */
- ret = spectrum_dl_image(hw, link, fw_entry->data, 1);
- release_firmware(fw_entry);
- if (ret) {
- printk(KERN_ERR PFX "Secondary firmware download failed\n");
- }
-
- return ret;
-}
-
-/********************************************************************/
-/* Device methods */
-/********************************************************************/
-
static int
-spectrum_cs_hard_reset(struct orinoco_private *priv)
+spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
{
struct orinoco_pccard *card = priv->card;
struct pcmcia_device *link = card->p_dev;
- int err;
- if (!hermes_present(&priv->hw)) {
- /* The firmware needs to be reloaded */
- if (spectrum_dl_firmware(&priv->hw, link) != 0) {
- printk(KERN_ERR PFX "Firmware download failed\n");
- err = -ENODEV;
- }
- } else {
- /* Soft reset using COR and HCR */
- spectrum_reset(link, 0);
- }
-
- return 0;
+ return spectrum_reset(link, idle);
}
/********************************************************************/
@@ -582,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+ dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ spectrum_cs_hard_reset,
+ spectrum_cs_stop_firmware);
if (! dev)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -593,7 +195,7 @@ spectrum_cs_probe(struct pcmcia_device *link)
link->priv = dev;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;
@@ -633,6 +235,70 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
* device available to the system.
*/
+static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (cfg->index == 0)
+ goto next_entry;
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+ goto next_entry;
+ }
+ return 0;
+
+next_entry:
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+};
+
static int
spectrum_cs_config(struct pcmcia_device *link)
{
@@ -641,16 +307,8 @@ spectrum_cs_config(struct pcmcia_device *link)
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- tuple_t tuple;
- cisparse_t parse;
void __iomem *mem;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
/*
* In this loop, we scan the CIS for configuration table
* entries, each of which describes a valid card
@@ -665,94 +323,14 @@ spectrum_cs_config(struct pcmcia_device *link)
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_cftable_entry_t dflt = { .index = 0 };
-
- if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
- || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- dflt = *cfg;
- if (cfg->index == 0)
- goto next_entry;
- link->conf.ConfigIndex = cfg->index;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
- if(!ignore_cis_vcc)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io =
- (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 =
- IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 =
- IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines =
- io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin > 1) {
- link->io.Attributes2 =
- link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- }
-
-
- /* If we got this far, we're cool! */
-
- break;
-
- next_entry:
- pcmcia_disable_device(link);
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- if (last_ret == CS_NO_MORE_ITEMS) {
+ last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
+ if (last_ret) {
+ if (!ignore_cis_vcc)
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
"ignore_cis_vcc=1 parameter.\n");
- goto cs_failed;
- }
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
/*
@@ -784,7 +362,7 @@ spectrum_cs_config(struct pcmcia_device *link)
dev->irq = link->irq.AssignedIRQ;
card->node.major = card->node.minor = 0;
- /* Reset card and download firmware */
+ /* Reset card */
if (spectrum_cs_hard_reset(priv) != 0) {
goto failed;
}
@@ -848,10 +426,11 @@ spectrum_cs_suspend(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
int err = 0;
/* Mark the device as stopped, to block IO until later */
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
err = __orinoco_down(dev);
if (err)
@@ -861,7 +440,7 @@ spectrum_cs_suspend(struct pcmcia_device *link)
netif_device_detach(dev);
priv->hw_unavailable++;
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
return err;
}
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 136220b5ca8..e939a73ff79 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -4387,7 +4387,7 @@ MODULE_LICENSE("GPL");
*
* Thanks go also to:
* James Ashton (jaa101@syseng.anu.edu.au),
- * Alan Cox (alan@redhat.com),
+ * Alan Cox (alan@lxorguk.ukuu.org.uk),
* Allan Creighton (allanc@cs.usyd.edu.au),
* Matthew Geier (matthew@cs.usyd.edu.au),
* Remo di Giovanni (remo@cs.usyd.edu.au),
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index b33ac47dd8d..44d31bbf39e 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -186,7 +186,7 @@
*
* Thanks go also to:
* James Ashton <jaa101@syseng.anu.edu.au>,
- * Alan Cox <alan@redhat.com>,
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>,
* Allan Creighton <allanc@cs.usyd.edu.au>,
* Matthew Geier <matthew@cs.usyd.edu.au>,
* Remo di Giovanni <remo@cs.usyd.edu.au>,
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 00a3559e5aa..e124b1d6267 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -3702,7 +3702,7 @@ wv_pcmcia_reset(struct net_device * dev)
#endif
i = pcmcia_access_configuration_register(link, &reg);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
@@ -3716,7 +3716,7 @@ wv_pcmcia_reset(struct net_device * dev)
reg.Action = CS_WRITE;
reg.Value = reg.Value | COR_SW_RESET;
i = pcmcia_access_configuration_register(link, &reg);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
@@ -3725,7 +3725,7 @@ wv_pcmcia_reset(struct net_device * dev)
reg.Action = CS_WRITE;
reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
i = pcmcia_access_configuration_register(link, &reg);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
@@ -3903,7 +3903,7 @@ wv_pcmcia_config(struct pcmcia_device * link)
do
{
i = pcmcia_request_io(link, &link->io);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestIO, i);
break;
@@ -3914,7 +3914,7 @@ wv_pcmcia_config(struct pcmcia_device * link)
* actually assign a handler to the interrupt.
*/
i = pcmcia_request_irq(link, &link->irq);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestIRQ, i);
break;
@@ -3926,7 +3926,7 @@ wv_pcmcia_config(struct pcmcia_device * link)
*/
link->conf.ConfigIndex = 1;
i = pcmcia_request_configuration(link, &link->conf);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestConfiguration, i);
break;
@@ -3942,7 +3942,7 @@ wv_pcmcia_config(struct pcmcia_device * link)
req.Base = req.Size = 0;
req.AccessSpeed = mem_speed;
i = pcmcia_request_window(&link, &req, &link->win);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestWindow, i);
break;
@@ -3954,7 +3954,7 @@ wv_pcmcia_config(struct pcmcia_device * link)
mem.CardOffset = 0; mem.Page = 0;
i = pcmcia_map_mem_page(link->win, &mem);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, MapMemPage, i);
break;
@@ -4496,7 +4496,7 @@ wavelan_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 3;
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wavelan_interrupt;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 377141995e3..68789c6e1ce 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -79,7 +79,7 @@ static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0);
#define dprintk(n, format, args...) \
{ if (pc_debug > (n)) \
- printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##args); }
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##args); }
#else
#define dprintk(n, format, args...)
#endif
@@ -470,7 +470,7 @@ static int wl3501_pwr_mgmt(struct wl3501_card *this, int suspend)
spin_unlock_irqrestore(&this->lock, flags);
rc = wait_event_interruptible(this->wait,
this->sig_pwr_mgmt_confirm.status != 255);
- printk(KERN_INFO "%s: %s status=%d\n", __FUNCTION__,
+ printk(KERN_INFO "%s: %s status=%d\n", __func__,
suspend ? "suspend" : "resume",
this->sig_pwr_mgmt_confirm.status);
goto out;
@@ -1199,7 +1199,7 @@ static int wl3501_reset_board(struct wl3501_card *this)
}
WL3501_NOPLOOP(10);
}
- printk(KERN_WARNING "%s: failed to reset the board!\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: failed to reset the board!\n", __func__);
rc = -ENODEV;
out:
return rc;
@@ -1250,7 +1250,7 @@ static int wl3501_init_firmware(struct wl3501_card *this)
out:
return rc;
fail:
- printk(KERN_WARNING "%s: failed!\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: failed!\n", __func__);
goto out;
}
@@ -1917,7 +1917,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wl3501_interrupt;
@@ -1977,10 +1977,10 @@ static int wl3501_config(struct pcmcia_device *link)
link->io.BasePort1 = j;
link->io.BasePort2 = link->io.BasePort1 + 0x10;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
+ if (i == 0)
break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index cc36126cee8..1907eafb9b1 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_ZD1211RW) += zd1211rw.o
-zd1211rw-objs := zd_chip.o zd_ieee80211.o zd_mac.o \
+zd1211rw-objs := zd_chip.o zd_mac.o \
zd_rf_al2230.o zd_rf_rf2959.o \
zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 0acb5c34573..e0ac58b8ff1 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -28,7 +28,6 @@
#include "zd_def.h"
#include "zd_chip.h"
-#include "zd_ieee80211.h"
#include "zd_mac.h"
#include "zd_rf.h"
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
deleted file mode 100644
index d8dc41ec0e5..00000000000
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * In the long term, we'll probably find a better way of handling regulatory
- * requirements outside of the driver.
- */
-
-#include <linux/kernel.h>
-#include <net/mac80211.h>
-
-#include "zd_ieee80211.h"
-#include "zd_mac.h"
-
-struct channel_range {
- u8 regdomain;
- u8 start;
- u8 end; /* exclusive (channel must be less than end) */
-};
-
-static const struct channel_range channel_ranges[] = {
- { ZD_REGDOMAIN_FCC, 1, 12 },
- { ZD_REGDOMAIN_IC, 1, 12 },
- { ZD_REGDOMAIN_ETSI, 1, 14 },
- { ZD_REGDOMAIN_JAPAN, 1, 14 },
- { ZD_REGDOMAIN_SPAIN, 1, 14 },
- { ZD_REGDOMAIN_FRANCE, 1, 14 },
-
- /* Japan originally only had channel 14 available (see CHNL_ID 0x40 in
- * 802.11). However, in 2001 the range was extended to include channels
- * 1-13. The ZyDAS devices still use the old region code but are
- * designed to allow the extra channel access in Japan. */
- { ZD_REGDOMAIN_JAPAN_ADD, 1, 15 },
-};
-
-static const struct channel_range *zd_channel_range(u8 regdomain)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) {
- const struct channel_range *range = &channel_ranges[i];
- if (range->regdomain == regdomain)
- return range;
- }
- return NULL;
-}
-
-#define CHAN_TO_IDX(chan) ((chan) - 1)
-
-static void unmask_bg_channels(struct ieee80211_hw *hw,
- const struct channel_range *range,
- struct ieee80211_supported_band *sband)
-{
- u8 channel;
-
- for (channel = range->start; channel < range->end; channel++) {
- struct ieee80211_channel *chan =
- &sband->channels[CHAN_TO_IDX(channel)];
- chan->flags = 0;
- }
-}
-
-void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
-{
- struct zd_mac *mac = zd_hw_mac(hw);
- const struct channel_range *range;
-
- dev_dbg(zd_mac_dev(mac), "regdomain %#02x\n", regdomain);
-
- range = zd_channel_range(regdomain);
- if (!range) {
- /* The vendor driver overrides the regulatory domain and
- * allowed channel registers and unconditionally restricts
- * available channels to 1-11 everywhere. Match their
- * questionable behaviour only for regdomains which we don't
- * recognise. */
- dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
- "%#02x. Defaulting to FCC.\n", regdomain);
- range = zd_channel_range(ZD_REGDOMAIN_FCC);
- }
-
- unmask_bg_channels(hw, range, &mac->band);
-}
-
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
deleted file mode 100644
index 26b79f19758..00000000000
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _ZD_IEEE80211_H
-#define _ZD_IEEE80211_H
-
-#include <net/mac80211.h>
-
-/* Additional definitions from the standards.
- */
-
-#define ZD_REGDOMAIN_FCC 0x10
-#define ZD_REGDOMAIN_IC 0x20
-#define ZD_REGDOMAIN_ETSI 0x30
-#define ZD_REGDOMAIN_SPAIN 0x31
-#define ZD_REGDOMAIN_FRANCE 0x32
-#define ZD_REGDOMAIN_JAPAN_ADD 0x40
-#define ZD_REGDOMAIN_JAPAN 0x41
-
-enum {
- MIN_CHANNEL24 = 1,
- MAX_CHANNEL24 = 14,
-};
-
-void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain);
-
-#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
-
-struct ofdm_plcp_header {
- u8 prefix[3];
- __le16 service;
-} __attribute__((packed));
-
-static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
-{
- return header->prefix[0] & 0xf;
-}
-
-/* The following defines give the encoding of the 4-bit rate field in the
- * OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
- * define the zd-rate values for OFDM.
- *
- * See the struct zd_ctrlset definition in zd_mac.h.
- */
-#define ZD_OFDM_PLCP_RATE_6M 0xb
-#define ZD_OFDM_PLCP_RATE_9M 0xf
-#define ZD_OFDM_PLCP_RATE_12M 0xa
-#define ZD_OFDM_PLCP_RATE_18M 0xe
-#define ZD_OFDM_PLCP_RATE_24M 0x9
-#define ZD_OFDM_PLCP_RATE_36M 0xd
-#define ZD_OFDM_PLCP_RATE_48M 0x8
-#define ZD_OFDM_PLCP_RATE_54M 0xc
-
-struct cck_plcp_header {
- u8 signal;
- u8 service;
- __le16 length;
- __le16 crc16;
-} __attribute__((packed));
-
-static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
-{
- return header->signal;
-}
-
-/* These defines give the encodings of the signal field in the 802.11b PLCP
- * header. The signal field gives the bit rate of the following packet. Even
- * if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
- * rate to stay consistent with Zydas and our use of the term.
- *
- * Notify that these values are *not* used in the zd-rates.
- */
-#define ZD_CCK_PLCP_SIGNAL_1M 0x0a
-#define ZD_CCK_PLCP_SIGNAL_2M 0x14
-#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
-#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
-
-#endif /* _ZD_IEEE80211_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 4d7b98b0503..fe1867b25ff 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -3,7 +3,7 @@
* Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
* Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
- * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
*
* 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
@@ -29,9 +29,23 @@
#include "zd_def.h"
#include "zd_chip.h"
#include "zd_mac.h"
-#include "zd_ieee80211.h"
#include "zd_rf.h"
+struct zd_reg_alpha2_map {
+ u32 reg;
+ char alpha2[2];
+};
+
+static struct zd_reg_alpha2_map reg_alpha2_map[] = {
+ { ZD_REGDOMAIN_FCC, "US" },
+ { ZD_REGDOMAIN_IC, "CA" },
+ { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
+ { ZD_REGDOMAIN_JAPAN, "JP" },
+ { ZD_REGDOMAIN_JAPAN_ADD, "JP" },
+ { ZD_REGDOMAIN_SPAIN, "ES" },
+ { ZD_REGDOMAIN_FRANCE, "FR" },
+};
+
/* This table contains the hardware specific values for the modulation rates. */
static const struct ieee80211_rate zd_rates[] = {
{ .bitrate = 10,
@@ -95,6 +109,21 @@ static void housekeeping_init(struct zd_mac *mac);
static void housekeeping_enable(struct zd_mac *mac);
static void housekeeping_disable(struct zd_mac *mac);
+static int zd_reg2alpha2(u8 regdomain, char *alpha2)
+{
+ unsigned int i;
+ struct zd_reg_alpha2_map *reg_map;
+ for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
+ reg_map = &reg_alpha2_map[i];
+ if (regdomain == reg_map->reg) {
+ alpha2[0] = reg_map->alpha2[0];
+ alpha2[1] = reg_map->alpha2[1];
+ return 0;
+ }
+ }
+ return 1;
+}
+
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
@@ -115,6 +144,7 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
int r;
struct zd_mac *mac = zd_hw_mac(hw);
struct zd_chip *chip = &mac->chip;
+ char alpha2[2];
u8 default_regdomain;
r = zd_chip_enable_int(chip);
@@ -139,7 +169,9 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
if (r)
goto disable_int;
- zd_geo_init(hw, mac->regdomain);
+ r = zd_reg2alpha2(mac->regdomain, alpha2);
+ if (!r)
+ regulatory_hint(hw->wiphy, alpha2, NULL);
r = 0;
disable_int:
@@ -579,7 +611,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
q = &zd_hw_mac(hw)->ack_wait_queue;
spin_lock_irqsave(&q->lock, flags);
- for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) {
+ skb_queue_walk(q, skb) {
struct ieee80211_hdr *tx_hdr;
tx_hdr = (struct ieee80211_hdr *)skb->data;
@@ -684,15 +716,15 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
{
struct zd_mac *mac = zd_hw_mac(hw);
- /* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */
- if (mac->type != IEEE80211_IF_TYPE_INVALID)
+ /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
+ if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
return -EOPNOTSUPP;
switch (conf->type) {
- case IEEE80211_IF_TYPE_MNTR:
- case IEEE80211_IF_TYPE_MESH_POINT:
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
mac->type = conf->type;
break;
default:
@@ -706,7 +738,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct zd_mac *mac = zd_hw_mac(hw);
- mac->type = IEEE80211_IF_TYPE_INVALID;
+ mac->type = NL80211_IFTYPE_UNSPECIFIED;
zd_set_beacon_interval(&mac->chip, 0);
zd_write_mac_addr(&mac->chip, NULL);
}
@@ -725,8 +757,8 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
int associated;
int r;
- if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
- mac->type == IEEE80211_IF_TYPE_IBSS) {
+ if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+ mac->type == NL80211_IFTYPE_ADHOC) {
associated = true;
if (conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
@@ -753,7 +785,7 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
return 0;
}
-void zd_process_intr(struct work_struct *work)
+static void zd_process_intr(struct work_struct *work)
{
u16 int_status;
struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
@@ -923,7 +955,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
spin_lock_init(&mac->lock);
mac->hw = hw;
- mac->type = IEEE80211_IF_TYPE_INVALID;
+ mac->type = NL80211_IFTYPE_UNSPECIFIED;
memcpy(mac->channels, zd_channels, sizeof(zd_channels));
memcpy(mac->rates, zd_rates, sizeof(zd_rates));
@@ -937,6 +969,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_DB;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
hw->max_signal = 100;
hw->queues = 1;
hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 18c1d56d3dd..4c05d3ee4c3 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -25,7 +25,6 @@
#include <net/mac80211.h>
#include "zd_chip.h"
-#include "zd_ieee80211.h"
struct zd_ctrlset {
u8 modulation;
@@ -187,6 +186,70 @@ struct zd_mac {
unsigned int pass_ctrl:1;
};
+#define ZD_REGDOMAIN_FCC 0x10
+#define ZD_REGDOMAIN_IC 0x20
+#define ZD_REGDOMAIN_ETSI 0x30
+#define ZD_REGDOMAIN_SPAIN 0x31
+#define ZD_REGDOMAIN_FRANCE 0x32
+#define ZD_REGDOMAIN_JAPAN_ADD 0x40
+#define ZD_REGDOMAIN_JAPAN 0x41
+
+enum {
+ MIN_CHANNEL24 = 1,
+ MAX_CHANNEL24 = 14,
+};
+
+#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
+
+struct ofdm_plcp_header {
+ u8 prefix[3];
+ __le16 service;
+} __attribute__((packed));
+
+static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
+{
+ return header->prefix[0] & 0xf;
+}
+
+/* The following defines give the encoding of the 4-bit rate field in the
+ * OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
+ * define the zd-rate values for OFDM.
+ *
+ * See the struct zd_ctrlset definition in zd_mac.h.
+ */
+#define ZD_OFDM_PLCP_RATE_6M 0xb
+#define ZD_OFDM_PLCP_RATE_9M 0xf
+#define ZD_OFDM_PLCP_RATE_12M 0xa
+#define ZD_OFDM_PLCP_RATE_18M 0xe
+#define ZD_OFDM_PLCP_RATE_24M 0x9
+#define ZD_OFDM_PLCP_RATE_36M 0xd
+#define ZD_OFDM_PLCP_RATE_48M 0x8
+#define ZD_OFDM_PLCP_RATE_54M 0xc
+
+struct cck_plcp_header {
+ u8 signal;
+ u8 service;
+ __le16 length;
+ __le16 crc16;
+} __attribute__((packed));
+
+static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
+{
+ return header->signal;
+}
+
+/* These defines give the encodings of the signal field in the 802.11b PLCP
+ * header. The signal field gives the bit rate of the following packet. Even
+ * if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
+ * rate to stay consistent with Zydas and our use of the term.
+ *
+ * Notify that these values are *not* used in the zd-rates.
+ */
+#define ZD_CCK_PLCP_SIGNAL_1M 0x0a
+#define ZD_CCK_PLCP_SIGNAL_2M 0x14
+#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
+#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
+
static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw)
{
return hw->priv;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index ec412931281..7207bfd2e6c 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -23,7 +23,7 @@
#include "zd_def.h"
#include "zd_rf.h"
-#include "zd_ieee80211.h"
+#include "zd_mac.h"
#include "zd_chip.h"
static const char * const rfs[] = {
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index da8b7433e3a..a60ae86bd5c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -58,6 +58,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index c749bdba214..c6948d8f53f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -239,11 +239,14 @@ static void xennet_alloc_rx_buffers(struct net_device *dev)
*/
batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
- skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD,
+ skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD + NET_IP_ALIGN,
GFP_ATOMIC | __GFP_NOWARN);
if (unlikely(!skb))
goto no_skb;
+ /* Align ip header to a 16 bytes boundary */
+ skb_reserve(skb, NET_IP_ALIGN);
+
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
if (!page) {
kfree_skb(skb);
@@ -471,7 +474,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int offset = offset_in_page(data);
unsigned int len = skb_headlen(skb);
- frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
+ frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
frags);
@@ -1794,10 +1797,10 @@ static struct xenbus_driver netfront = {
static int __init netif_init(void)
{
- if (!is_running_on_xen())
+ if (!xen_domain())
return -ENODEV;
- if (is_initial_xendomain())
+ if (xen_initial_domain())
return 0;
printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
@@ -1809,7 +1812,7 @@ module_init(netif_init);
static void __exit netif_exit(void)
{
- if (is_initial_xendomain())
+ if (xen_initial_domain())
return;
xenbus_unregister_driver(&netfront);
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 2f047e573d8..f5f75844954 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -126,7 +126,7 @@ static void nubus_advance(unsigned char **ptr, int len, int map)
{
while(not_useful(p,map))
p++;
- p++;
+ p++;
len--;
}
*ptr = p;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ad8ac1a8af2..7c79e94a35e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -410,7 +410,7 @@ struct of_modalias_table {
char *modalias;
};
static struct of_modalias_table of_modalias_table[] = {
- /* Empty for now; add entries as needed */
+ { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
};
/**
@@ -420,13 +420,12 @@ static struct of_modalias_table of_modalias_table[] = {
* @len: Length of modalias value
*
* Based on the value of the compatible property, this routine will determine
- * an appropriate modalias value for a particular device tree node. Three
- * separate methods are used to derive a modalias value.
+ * an appropriate modalias value for a particular device tree node. Two
+ * separate methods are attempted to derive a modalias value.
*
* First method is to lookup the compatible value in of_modalias_table.
- * Second is to look for a "linux,<modalias>" entry in the compatible list
- * and used that for modalias. Third is to strip off the manufacturer
- * prefix from the first compatible entry and use the remainder as modalias
+ * Second is to strip off the manufacturer prefix from the first
+ * compatible entry and use the remainder as modalias
*
* This routine returns 0 on success
*/
@@ -449,21 +448,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
if (!compatible)
return -ENODEV;
- /* 2. search for linux,<modalias> entry */
- p = compatible;
- while (cplen > 0) {
- if (!strncmp(p, "linux,", 6)) {
- p += 6;
- strlcpy(modalias, p, len);
- return 0;
- }
-
- i = strlen(p) + 1;
- p += i;
- cplen -= i;
- }
-
- /* 3. take first compatible entry and strip manufacturer */
+ /* 2. take first compatible entry and strip manufacturer */
p = strchr(compatible, ',');
if (!p)
return -ENODEV;
@@ -473,3 +458,112 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
}
EXPORT_SYMBOL_GPL(of_modalias_node);
+/**
+ * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * @np: pointer to a device tree node containing a list
+ * @list_name: property name that contains a list
+ * @cells_name: property name that specifies phandles' arguments count
+ * @index: index of a phandle to parse out
+ * @out_node: pointer to device_node struct pointer (will be filled)
+ * @out_args: pointer to arguments pointer (will be filled)
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_node and out_args, on error returns
+ * appropriate errno value.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ * #list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ * #list-cells = <1>;
+ * }
+ *
+ * node3 {
+ * list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ */
+int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
+ const char *cells_name, int index,
+ struct device_node **out_node,
+ const void **out_args)
+{
+ int ret = -EINVAL;
+ const u32 *list;
+ const u32 *list_end;
+ int size;
+ int cur_index = 0;
+ struct device_node *node = NULL;
+ const void *args;
+
+ list = of_get_property(np, list_name, &size);
+ if (!list) {
+ ret = -ENOENT;
+ goto err0;
+ }
+ list_end = list + size / sizeof(*list);
+
+ while (list < list_end) {
+ const u32 *cells;
+ const phandle *phandle;
+
+ phandle = list;
+ args = list + 1;
+
+ /* one cell hole in the list = <>; */
+ if (!*phandle) {
+ list++;
+ goto next;
+ }
+
+ node = of_find_node_by_phandle(*phandle);
+ if (!node) {
+ pr_debug("%s: could not find phandle\n",
+ np->full_name);
+ goto err0;
+ }
+
+ cells = of_get_property(node, cells_name, &size);
+ if (!cells || size != sizeof(*cells)) {
+ pr_debug("%s: could not get %s for %s\n",
+ np->full_name, cells_name, node->full_name);
+ goto err1;
+ }
+
+ /* Next phandle is at offset of one phandle cell + #cells */
+ list += 1 + *cells;
+ if (list > list_end) {
+ pr_debug("%s: insufficient arguments length\n",
+ np->full_name);
+ goto err1;
+ }
+next:
+ if (cur_index == index)
+ break;
+
+ of_node_put(node);
+ node = NULL;
+ cur_index++;
+ }
+
+ if (!node) {
+ ret = -ENOENT;
+ goto err0;
+ }
+
+ *out_node = node;
+ *out_args = args;
+
+ return 0;
+err1:
+ of_node_put(node);
+err0:
+ pr_debug("%s failed with status %d\n", __func__, ret);
+ return ret;
+}
+EXPORT_SYMBOL(of_parse_phandles_with_args);
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 1c9cab844f1..7cd7301b583 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -28,78 +28,35 @@
*/
int of_get_gpio(struct device_node *np, int index)
{
- int ret = -EINVAL;
+ int ret;
struct device_node *gc;
struct of_gpio_chip *of_gc = NULL;
int size;
- const u32 *gpios;
- u32 nr_cells;
- int i;
const void *gpio_spec;
const u32 *gpio_cells;
- int gpio_index = 0;
- gpios = of_get_property(np, "gpios", &size);
- if (!gpios) {
- ret = -ENOENT;
+ ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+ &gc, &gpio_spec);
+ if (ret) {
+ pr_debug("%s: can't parse gpios property\n", __func__);
goto err0;
}
- nr_cells = size / sizeof(u32);
-
- for (i = 0; i < nr_cells; gpio_index++) {
- const phandle *gpio_phandle;
-
- gpio_phandle = gpios + i;
- gpio_spec = gpio_phandle + 1;
-
- /* one cell hole in the gpios = <>; */
- if (!*gpio_phandle) {
- if (gpio_index == index)
- return -ENOENT;
- i++;
- continue;
- }
-
- gc = of_find_node_by_phandle(*gpio_phandle);
- if (!gc) {
- pr_debug("%s: could not find phandle for gpios\n",
- np->full_name);
- goto err0;
- }
-
- of_gc = gc->data;
- if (!of_gc) {
- pr_debug("%s: gpio controller %s isn't registered\n",
- np->full_name, gc->full_name);
- goto err1;
- }
-
- gpio_cells = of_get_property(gc, "#gpio-cells", &size);
- if (!gpio_cells || size != sizeof(*gpio_cells) ||
- *gpio_cells != of_gc->gpio_cells) {
- pr_debug("%s: wrong #gpio-cells for %s\n",
- np->full_name, gc->full_name);
- goto err1;
- }
-
- /* Next phandle is at phandle cells + #gpio-cells */
- i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
- if (i >= nr_cells + 1) {
- pr_debug("%s: insufficient gpio-spec length\n",
- np->full_name);
- goto err1;
- }
-
- if (gpio_index == index)
- break;
-
- of_gc = NULL;
- of_node_put(gc);
- }
+ of_gc = gc->data;
if (!of_gc) {
- ret = -ENOENT;
- goto err0;
+ pr_debug("%s: gpio controller %s isn't registered\n",
+ np->full_name, gc->full_name);
+ ret = -ENODEV;
+ goto err1;
+ }
+
+ gpio_cells = of_get_property(gc, "#gpio-cells", &size);
+ if (!gpio_cells || size != sizeof(*gpio_cells) ||
+ *gpio_cells != of_gc->gpio_cells) {
+ pr_debug("%s: wrong #gpio-cells for %s\n",
+ np->full_name, gc->full_name);
+ ret = -EINVAL;
+ goto err1;
}
ret = of_gc->xlate(of_gc, np, gpio_spec);
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 9304c455507..ed982273fb8 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -5,6 +5,7 @@
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
+ * @author Barry Kasindorf
*
* This is the core of the buffer management. Each
* CPU buffer is processed and entered into the
@@ -33,7 +34,7 @@
#include "event_buffer.h"
#include "cpu_buffer.h"
#include "buffer_sync.h"
-
+
static LIST_HEAD(dying_tasks);
static LIST_HEAD(dead_tasks);
static cpumask_t marked_cpus = CPU_MASK_NONE;
@@ -48,10 +49,11 @@ static void process_task_mortuary(void);
* Can be invoked from softirq via RCU callback due to
* call_rcu() of the task struct, hence the _irqsave.
*/
-static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+task_free_notify(struct notifier_block *self, unsigned long val, void *data)
{
unsigned long flags;
- struct task_struct * task = data;
+ struct task_struct *task = data;
spin_lock_irqsave(&task_mortuary, flags);
list_add(&task->tasks, &dying_tasks);
spin_unlock_irqrestore(&task_mortuary, flags);
@@ -62,13 +64,14 @@ static int task_free_notify(struct notifier_block * self, unsigned long val, voi
/* The task is on its way out. A sync of the buffer means we can catch
* any remaining samples for this task.
*/
-static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+task_exit_notify(struct notifier_block *self, unsigned long val, void *data)
{
/* To avoid latency problems, we only process the current CPU,
* hoping that most samples for the task are on this CPU
*/
sync_buffer(raw_smp_processor_id());
- return 0;
+ return 0;
}
@@ -77,11 +80,12 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi
* we don't lose any. This does not have to be exact, it's a QoI issue
* only.
*/
-static int munmap_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+munmap_notify(struct notifier_block *self, unsigned long val, void *data)
{
unsigned long addr = (unsigned long)data;
- struct mm_struct * mm = current->mm;
- struct vm_area_struct * mpnt;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *mpnt;
down_read(&mm->mmap_sem);
@@ -99,11 +103,12 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void *
return 0;
}
-
+
/* We need to be told about new modules so we don't attribute to a previously
* loaded module, or drop the samples on the floor.
*/
-static int module_load_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+module_load_notify(struct notifier_block *self, unsigned long val, void *data)
{
#ifdef CONFIG_MODULES
if (val != MODULE_STATE_COMING)
@@ -118,7 +123,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
return 0;
}
-
+
static struct notifier_block task_free_nb = {
.notifier_call = task_free_notify,
};
@@ -135,7 +140,7 @@ static struct notifier_block module_load_nb = {
.notifier_call = module_load_notify,
};
-
+
static void end_sync(void)
{
end_cpu_work();
@@ -208,14 +213,14 @@ static inline unsigned long fast_get_dcookie(struct path *path)
* not strictly necessary but allows oprofile to associate
* shared-library samples with particular applications
*/
-static unsigned long get_exec_dcookie(struct mm_struct * mm)
+static unsigned long get_exec_dcookie(struct mm_struct *mm)
{
unsigned long cookie = NO_COOKIE;
- struct vm_area_struct * vma;
-
+ struct vm_area_struct *vma;
+
if (!mm)
goto out;
-
+
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if (!vma->vm_file)
continue;
@@ -235,13 +240,14 @@ out:
* sure to do this lookup before a mm->mmap modification happens so
* we don't lose track.
*/
-static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
+static unsigned long
+lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
{
unsigned long cookie = NO_COOKIE;
- struct vm_area_struct * vma;
+ struct vm_area_struct *vma;
for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
-
+
if (addr < vma->vm_start || addr >= vma->vm_end)
continue;
@@ -263,9 +269,20 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
return cookie;
}
+static void increment_tail(struct oprofile_cpu_buffer *b)
+{
+ unsigned long new_tail = b->tail_pos + 1;
+
+ rmb(); /* be sure fifo pointers are synchromized */
+
+ if (new_tail < b->buffer_size)
+ b->tail_pos = new_tail;
+ else
+ b->tail_pos = 0;
+}
static unsigned long last_cookie = INVALID_COOKIE;
-
+
static void add_cpu_switch(int i)
{
add_event_entry(ESCAPE_CODE);
@@ -278,16 +295,16 @@ static void add_kernel_ctx_switch(unsigned int in_kernel)
{
add_event_entry(ESCAPE_CODE);
if (in_kernel)
- add_event_entry(KERNEL_ENTER_SWITCH_CODE);
+ add_event_entry(KERNEL_ENTER_SWITCH_CODE);
else
- add_event_entry(KERNEL_EXIT_SWITCH_CODE);
+ add_event_entry(KERNEL_EXIT_SWITCH_CODE);
}
-
+
static void
-add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
+add_user_ctx_switch(struct task_struct const *task, unsigned long cookie)
{
add_event_entry(ESCAPE_CODE);
- add_event_entry(CTX_SWITCH_CODE);
+ add_event_entry(CTX_SWITCH_CODE);
add_event_entry(task->pid);
add_event_entry(cookie);
/* Another code for daemon back-compat */
@@ -296,7 +313,7 @@ add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
add_event_entry(task->tgid);
}
-
+
static void add_cookie_switch(unsigned long cookie)
{
add_event_entry(ESCAPE_CODE);
@@ -304,13 +321,78 @@ static void add_cookie_switch(unsigned long cookie)
add_event_entry(cookie);
}
-
+
static void add_trace_begin(void)
{
add_event_entry(ESCAPE_CODE);
add_event_entry(TRACE_BEGIN_CODE);
}
+#ifdef CONFIG_OPROFILE_IBS
+
+#define IBS_FETCH_CODE_SIZE 2
+#define IBS_OP_CODE_SIZE 5
+#define IBS_EIP(offset) \
+ (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip)
+#define IBS_EVENT(offset) \
+ (((struct op_sample *)&cpu_buf->buffer[(offset)])->event)
+
+/*
+ * Add IBS fetch and op entries to event buffer
+ */
+static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
+ int in_kernel, struct mm_struct *mm)
+{
+ unsigned long rip;
+ int i, count;
+ unsigned long ibs_cookie = 0;
+ off_t offset;
+
+ increment_tail(cpu_buf); /* move to RIP entry */
+
+ rip = IBS_EIP(cpu_buf->tail_pos);
+
+#ifdef __LP64__
+ rip += IBS_EVENT(cpu_buf->tail_pos) << 32;
+#endif
+
+ if (mm) {
+ ibs_cookie = lookup_dcookie(mm, rip, &offset);
+
+ if (ibs_cookie == NO_COOKIE)
+ offset = rip;
+ if (ibs_cookie == INVALID_COOKIE) {
+ atomic_inc(&oprofile_stats.sample_lost_no_mapping);
+ offset = rip;
+ }
+ if (ibs_cookie != last_cookie) {
+ add_cookie_switch(ibs_cookie);
+ last_cookie = ibs_cookie;
+ }
+ } else
+ offset = rip;
+
+ add_event_entry(ESCAPE_CODE);
+ add_event_entry(code);
+ add_event_entry(offset); /* Offset from Dcookie */
+
+ /* we send the Dcookie offset, but send the raw Linear Add also*/
+ add_event_entry(IBS_EIP(cpu_buf->tail_pos));
+ add_event_entry(IBS_EVENT(cpu_buf->tail_pos));
+
+ if (code == IBS_FETCH_CODE)
+ count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/
+ else
+ count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/
+
+ for (i = 0; i < count; i++) {
+ increment_tail(cpu_buf);
+ add_event_entry(IBS_EIP(cpu_buf->tail_pos));
+ add_event_entry(IBS_EVENT(cpu_buf->tail_pos));
+ }
+}
+
+#endif
static void add_sample_entry(unsigned long offset, unsigned long event)
{
@@ -319,13 +401,13 @@ static void add_sample_entry(unsigned long offset, unsigned long event)
}
-static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
+static int add_us_sample(struct mm_struct *mm, struct op_sample *s)
{
unsigned long cookie;
off_t offset;
-
- cookie = lookup_dcookie(mm, s->eip, &offset);
-
+
+ cookie = lookup_dcookie(mm, s->eip, &offset);
+
if (cookie == INVALID_COOKIE) {
atomic_inc(&oprofile_stats.sample_lost_no_mapping);
return 0;
@@ -341,13 +423,13 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
return 1;
}
-
+
/* Add a sample to the global event buffer. If possible the
* sample is converted into a persistent dentry/offset pair
* for later lookup from userspace.
*/
static int
-add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
+add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
{
if (in_kernel) {
add_sample_entry(s->eip, s->event);
@@ -359,9 +441,9 @@ add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
}
return 0;
}
-
-static void release_mm(struct mm_struct * mm)
+
+static void release_mm(struct mm_struct *mm)
{
if (!mm)
return;
@@ -370,9 +452,9 @@ static void release_mm(struct mm_struct * mm)
}
-static struct mm_struct * take_tasks_mm(struct task_struct * task)
+static struct mm_struct *take_tasks_mm(struct task_struct *task)
{
- struct mm_struct * mm = get_task_mm(task);
+ struct mm_struct *mm = get_task_mm(task);
if (mm)
down_read(&mm->mmap_sem);
return mm;
@@ -383,10 +465,10 @@ static inline int is_code(unsigned long val)
{
return val == ESCAPE_CODE;
}
-
+
/* "acquire" as many cpu buffer slots as we can */
-static unsigned long get_slots(struct oprofile_cpu_buffer * b)
+static unsigned long get_slots(struct oprofile_cpu_buffer *b)
{
unsigned long head = b->head_pos;
unsigned long tail = b->tail_pos;
@@ -412,19 +494,6 @@ static unsigned long get_slots(struct oprofile_cpu_buffer * b)
}
-static void increment_tail(struct oprofile_cpu_buffer * b)
-{
- unsigned long new_tail = b->tail_pos + 1;
-
- rmb();
-
- if (new_tail < b->buffer_size)
- b->tail_pos = new_tail;
- else
- b->tail_pos = 0;
-}
-
-
/* Move tasks along towards death. Any tasks on dead_tasks
* will definitely have no remaining references in any
* CPU buffers at this point, because we use two lists,
@@ -435,8 +504,8 @@ static void process_task_mortuary(void)
{
unsigned long flags;
LIST_HEAD(local_dead_tasks);
- struct task_struct * task;
- struct task_struct * ttask;
+ struct task_struct *task;
+ struct task_struct *ttask;
spin_lock_irqsave(&task_mortuary, flags);
@@ -493,7 +562,7 @@ void sync_buffer(int cpu)
{
struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
struct mm_struct *mm = NULL;
- struct task_struct * new;
+ struct task_struct *new;
unsigned long cookie = 0;
int in_kernel = 1;
unsigned int i;
@@ -501,7 +570,7 @@ void sync_buffer(int cpu)
unsigned long available;
mutex_lock(&buffer_mutex);
-
+
add_cpu_switch(cpu);
/* Remember, only we can modify tail_pos */
@@ -509,8 +578,8 @@ void sync_buffer(int cpu)
available = get_slots(cpu_buf);
for (i = 0; i < available; ++i) {
- struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
-
+ struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos];
+
if (is_code(s->eip)) {
if (s->event <= CPU_IS_KERNEL) {
/* kernel/userspace switch */
@@ -521,8 +590,18 @@ void sync_buffer(int cpu)
} else if (s->event == CPU_TRACE_BEGIN) {
state = sb_bt_start;
add_trace_begin();
+#ifdef CONFIG_OPROFILE_IBS
+ } else if (s->event == IBS_FETCH_BEGIN) {
+ state = sb_bt_start;
+ add_ibs_begin(cpu_buf,
+ IBS_FETCH_CODE, in_kernel, mm);
+ } else if (s->event == IBS_OP_BEGIN) {
+ state = sb_bt_start;
+ add_ibs_begin(cpu_buf,
+ IBS_OP_CODE, in_kernel, mm);
+#endif
} else {
- struct mm_struct * oldmm = mm;
+ struct mm_struct *oldmm = mm;
/* userspace context switch */
new = (struct task_struct *)s->event;
@@ -533,13 +612,11 @@ void sync_buffer(int cpu)
cookie = get_exec_dcookie(mm);
add_user_ctx_switch(new, cookie);
}
- } else {
- if (state >= sb_bt_start &&
- !add_sample(mm, s, in_kernel)) {
- if (state == sb_bt_start) {
- state = sb_bt_ignore;
- atomic_inc(&oprofile_stats.bt_lost_no_mapping);
- }
+ } else if (state >= sb_bt_start &&
+ !add_sample(mm, s, in_kernel)) {
+ if (state == sb_bt_start) {
+ state = sb_bt_ignore;
+ atomic_inc(&oprofile_stats.bt_lost_no_mapping);
}
}
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 7ba78e6d210..e1bd5a937f6 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -5,6 +5,7 @@
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
+ * @author Barry Kasindorf <barry.kasindorf@amd.com>
*
* Each CPU has a local buffer that stores PC value/event
* pairs. We also log context switches when we notice them.
@@ -209,7 +210,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
return 1;
}
-static int oprofile_begin_trace(struct oprofile_cpu_buffer * cpu_buf)
+static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)
{
if (nr_available_slots(cpu_buf) < 4) {
cpu_buf->sample_lost_overflow++;
@@ -254,6 +255,75 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
oprofile_add_ext_sample(pc, regs, event, is_kernel);
}
+#ifdef CONFIG_OPROFILE_IBS
+
+#define MAX_IBS_SAMPLE_SIZE 14
+static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
+ unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code)
+{
+ struct task_struct *task;
+
+ cpu_buf->sample_received++;
+
+ if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) {
+ cpu_buf->sample_lost_overflow++;
+ return 0;
+ }
+
+ is_kernel = !!is_kernel;
+
+ /* notice a switch from user->kernel or vice versa */
+ if (cpu_buf->last_is_kernel != is_kernel) {
+ cpu_buf->last_is_kernel = is_kernel;
+ add_code(cpu_buf, is_kernel);
+ }
+
+ /* notice a task switch */
+ if (!is_kernel) {
+ task = current;
+
+ if (cpu_buf->last_task != task) {
+ cpu_buf->last_task = task;
+ add_code(cpu_buf, (unsigned long)task);
+ }
+ }
+
+ add_code(cpu_buf, ibs_code);
+ add_sample(cpu_buf, ibs[0], ibs[1]);
+ add_sample(cpu_buf, ibs[2], ibs[3]);
+ add_sample(cpu_buf, ibs[4], ibs[5]);
+
+ if (ibs_code == IBS_OP_BEGIN) {
+ add_sample(cpu_buf, ibs[6], ibs[7]);
+ add_sample(cpu_buf, ibs[8], ibs[9]);
+ add_sample(cpu_buf, ibs[10], ibs[11]);
+ }
+
+ return 1;
+}
+
+void oprofile_add_ibs_sample(struct pt_regs *const regs,
+ unsigned int * const ibs_sample, u8 code)
+{
+ int is_kernel = !user_mode(regs);
+ unsigned long pc = profile_pc(regs);
+
+ struct oprofile_cpu_buffer *cpu_buf =
+ &per_cpu(cpu_buffer, smp_processor_id());
+
+ if (!backtrace_depth) {
+ log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code);
+ return;
+ }
+
+ /* if log_sample() fails we can't backtrace since we lost the source
+ * of this event */
+ if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code))
+ oprofile_ops.backtrace(regs, backtrace_depth);
+}
+
+#endif
+
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
{
struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
@@ -296,7 +366,7 @@ static void wq_sync_buffer(struct work_struct *work)
struct oprofile_cpu_buffer * b =
container_of(work, struct oprofile_cpu_buffer, work.work);
if (b->cpu != smp_processor_id()) {
- printk("WQ on CPU%d, prefer CPU%d\n",
+ printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n",
smp_processor_id(), b->cpu);
}
sync_buffer(b->cpu);
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index c3e366b5226..9c44d004da6 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -55,5 +55,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
/* transient events for the CPU buffer -> event buffer */
#define CPU_IS_KERNEL 1
#define CPU_TRACE_BEGIN 2
+#define IBS_FETCH_BEGIN 3
+#define IBS_OP_BEGIN 4
#endif /* OPROFILE_CPU_BUFFER_H */
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
index db717c1d62a..8565bbbeb6e 100644
--- a/drivers/parport/ChangeLog
+++ b/drivers/parport/ChangeLog
@@ -311,7 +311,7 @@
* ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd
on timeout. Matches 2.2.x behaviour.
-2001-03-02 Andrew Morton <andrewm@uow.edu.au>
+2001-03-02 Andrew Morton
* parport_pc.c (registered_parport): New static variable.
(parport_pc_find_ports): Set it when we register PCI driver.
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index e97059415ab..ac2a805ac7e 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -1,4 +1,4 @@
-/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
+/*
* IEEE-1284 implementation for parport.
*
* Authors: Phil Blundell <philb@gnu.org>
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 00e1d9620f7..b1899e9c1f6 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -149,52 +149,44 @@ static void parport_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int parport_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ if (epp_mode)
+ p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (io->nwin == 2) {
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+ return -ENODEV;
+ return 0;
+ }
+ return -ENODEV;
+}
+
static int parport_config(struct pcmcia_device *link)
{
parport_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[128];
- cisparse_t parse;
- cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
- cistpl_cftable_entry_t dflt = { 0 };
struct parport *p;
int last_ret, last_fn;
-
+
DEBUG(0, "parport_config(0x%p)\n", link);
-
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
-
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->conf.ConfigIndex = cfg->index;
- if (epp_mode)
- link->conf.ConfigIndex |= FORCE_EPP_MODE;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (io->nwin == 2) {
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
-
- next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+
+ last_ret = pcmcia_loop_config(link, parport_config_check, NULL);
+ if (last_ret) {
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
-
+
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 9d595aa91e4..065f229580d 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -26,6 +26,8 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/parport.h>
@@ -34,7 +36,6 @@
#include <asm/io.h>
#include <asm/oplib.h> /* OpenProm Library */
-#include <asm/sbus.h>
#include <asm/dma.h> /* BPP uses LSI 64854 for DMA */
#include <asm/irq.h>
#include <asm/sunbpp.h>
@@ -285,38 +286,37 @@ static struct parport_operations parport_sunbpp_ops =
.owner = THIS_MODULE,
};
-static int __devinit init_one_port(struct sbus_dev *sdev)
+static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match)
{
- struct parport *p;
- /* at least in theory there may be a "we don't dma" case */
struct parport_operations *ops;
- void __iomem *base;
- int irq, dma, err = 0, size;
struct bpp_regs __iomem *regs;
+ int irq, dma, err = 0, size;
unsigned char value_tcr;
+ void __iomem *base;
+ struct parport *p;
- irq = sdev->irqs[0];
- base = sbus_ioremap(&sdev->resource[0], 0,
- sdev->reg_addrs[0].reg_size,
- "sunbpp");
+ irq = op->irqs[0];
+ base = of_ioremap(&op->resource[0], 0,
+ resource_size(&op->resource[0]),
+ "sunbpp");
if (!base)
return -ENODEV;
- size = sdev->reg_addrs[0].reg_size;
+ size = resource_size(&op->resource[0]);
dma = PARPORT_DMA_NONE;
ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
if (!ops)
goto out_unmap;
- memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
+ memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations));
dprintk(("register_port\n"));
if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
goto out_free_ops;
p->size = size;
- p->dev = &sdev->ofdev.dev;
+ p->dev = &op->dev;
if ((err = request_irq(p->irq, parport_irq_handler,
IRQF_SHARED, p->name, p)) != 0) {
@@ -333,7 +333,7 @@ static int __devinit init_one_port(struct sbus_dev *sdev)
printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
- dev_set_drvdata(&sdev->ofdev.dev, p);
+ dev_set_drvdata(&op->dev, p);
parport_announce_port(p);
@@ -346,21 +346,14 @@ out_free_ops:
kfree(ops);
out_unmap:
- sbus_iounmap(base, size);
+ of_iounmap(&op->resource[0], base, size);
return err;
}
-static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match)
-{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
-
- return init_one_port(sdev);
-}
-
-static int __devexit bpp_remove(struct of_device *dev)
+static int __devexit bpp_remove(struct of_device *op)
{
- struct parport *p = dev_get_drvdata(&dev->dev);
+ struct parport *p = dev_get_drvdata(&op->dev);
struct parport_operations *ops = p->ops;
parport_remove_port(p);
@@ -370,16 +363,16 @@ static int __devexit bpp_remove(struct of_device *dev)
free_irq(p->irq, p);
}
- sbus_iounmap((void __iomem *) p->base, p->size);
+ of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size);
parport_put_port(p);
kfree(ops);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
-static struct of_device_id bpp_match[] = {
+static const struct of_device_id bpp_match[] = {
{
.name = "SUNW,bpp",
},
@@ -397,7 +390,7 @@ static struct of_platform_driver bpp_sbus_driver = {
static int __init parport_sunbpp_init(void)
{
- return of_register_driver(&bpp_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&bpp_sbus_driver, &of_bus_type);
}
static void __exit parport_sunbpp_exit(void)
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index cd565bb4e1a..0f6550719bc 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -1,4 +1,4 @@
-/* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $
+/*
* Parallel port device probing code
*
* Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index a8a62bbbb57..0ebca450ed2 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -1,4 +1,4 @@
-/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
+/*
* Parallel-port resource manager code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 7d63f8ced24..4b47f4ece5b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
# Build Intel IOMMU support
obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
+obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+
#
# Some architectures use the generic PCI setup functions
#
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 8bf86ae2333..e842e756308 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -19,15 +19,18 @@
* Author: Shaohua Li <shaohua.li@intel.com>
* Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
*
- * This file implements early detection/parsing of DMA Remapping Devices
+ * This file implements early detection/parsing of Remapping Devices
* reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
* tables.
+ *
+ * These routines are used by both DMA-remapping and Interrupt-remapping
*/
#include <linux/pci.h>
#include <linux/dmar.h>
-#include "iova.h"
-#include "intel-iommu.h"
+#include <linux/iova.h>
+#include <linux/intel-iommu.h>
+#include <linux/timer.h>
#undef PREFIX
#define PREFIX "DMAR:"
@@ -37,7 +40,6 @@
* these units are not supported by the architecture.
*/
LIST_HEAD(dmar_drhd_units);
-LIST_HEAD(dmar_rmrr_units);
static struct acpi_table_header * __initdata dmar_tbl;
@@ -53,11 +55,6 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
list_add(&drhd->list, &dmar_drhd_units);
}
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
- list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
struct pci_dev **dev, u16 segment)
{
@@ -172,19 +169,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
struct acpi_dmar_hardware_unit *drhd;
struct dmar_drhd_unit *dmaru;
int ret = 0;
- static int include_all;
dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
if (!dmaru)
return -ENOMEM;
+ dmaru->hdr = header;
drhd = (struct acpi_dmar_hardware_unit *)header;
dmaru->reg_base_addr = drhd->address;
dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
+ ret = alloc_iommu(dmaru);
+ if (ret) {
+ kfree(dmaru);
+ return ret;
+ }
+ dmar_register_drhd_unit(dmaru);
+ return 0;
+}
+
+static int __init
+dmar_parse_dev(struct dmar_drhd_unit *dmaru)
+{
+ struct acpi_dmar_hardware_unit *drhd;
+ static int include_all;
+ int ret;
+
+ drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
+
if (!dmaru->include_all)
ret = dmar_parse_dev_scope((void *)(drhd + 1),
- ((void *)drhd) + header->length,
+ ((void *)drhd) + drhd->header.length,
&dmaru->devices_cnt, &dmaru->devices,
drhd->segment);
else {
@@ -197,37 +212,59 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
include_all = 1;
}
- if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all))
+ if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
+ list_del(&dmaru->list);
kfree(dmaru);
- else
- dmar_register_drhd_unit(dmaru);
+ }
return ret;
}
+#ifdef CONFIG_DMAR
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+ list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
static int __init
dmar_parse_one_rmrr(struct acpi_dmar_header *header)
{
struct acpi_dmar_reserved_memory *rmrr;
struct dmar_rmrr_unit *rmrru;
- int ret = 0;
rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
if (!rmrru)
return -ENOMEM;
+ rmrru->hdr = header;
rmrr = (struct acpi_dmar_reserved_memory *)header;
rmrru->base_address = rmrr->base_address;
rmrru->end_address = rmrr->end_address;
+
+ dmar_register_rmrr_unit(rmrru);
+ return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+ struct acpi_dmar_reserved_memory *rmrr;
+ int ret;
+
+ rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
ret = dmar_parse_dev_scope((void *)(rmrr + 1),
- ((void *)rmrr) + header->length,
+ ((void *)rmrr) + rmrr->header.length,
&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
- if (ret || (rmrru->devices_cnt == 0))
+ if (ret || (rmrru->devices_cnt == 0)) {
+ list_del(&rmrru->list);
kfree(rmrru);
- else
- dmar_register_rmrr_unit(rmrru);
+ }
return ret;
}
+#endif
static void __init
dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
@@ -252,6 +289,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
}
}
+
/**
* parse_dmar_table - parses the DMA reporting table
*/
@@ -284,7 +322,9 @@ parse_dmar_table(void)
ret = dmar_parse_one_drhd(entry_header);
break;
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+#ifdef CONFIG_DMAR
ret = dmar_parse_one_rmrr(entry_header);
+#endif
break;
default:
printk(KERN_WARNING PREFIX
@@ -300,15 +340,77 @@ parse_dmar_table(void)
return ret;
}
+int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+ struct pci_dev *dev)
+{
+ int index;
+
+ while (dev) {
+ for (index = 0; index < cnt; index++)
+ if (dev == devices[index])
+ return 1;
-int __init dmar_table_init(void)
+ /* Check our parent */
+ dev = dev->bus->self;
+ }
+
+ return 0;
+}
+
+struct dmar_drhd_unit *
+dmar_find_matched_drhd_unit(struct pci_dev *dev)
{
+ struct dmar_drhd_unit *drhd = NULL;
+
+ list_for_each_entry(drhd, &dmar_drhd_units, list) {
+ if (drhd->include_all || dmar_pci_device_match(drhd->devices,
+ drhd->devices_cnt, dev))
+ return drhd;
+ }
+
+ return NULL;
+}
+
+int __init dmar_dev_scope_init(void)
+{
+ struct dmar_drhd_unit *drhd;
+ int ret = -ENODEV;
+
+ for_each_drhd_unit(drhd) {
+ ret = dmar_parse_dev(drhd);
+ if (ret)
+ return ret;
+ }
+
+#ifdef CONFIG_DMAR
+ {
+ struct dmar_rmrr_unit *rmrr;
+ for_each_rmrr_units(rmrr) {
+ ret = rmrr_parse_dev(rmrr);
+ if (ret)
+ return ret;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+int __init dmar_table_init(void)
+{
+ static int dmar_table_initialized;
int ret;
+ if (dmar_table_initialized)
+ return 0;
+
+ dmar_table_initialized = 1;
+
ret = parse_dmar_table();
if (ret) {
- printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+ if (ret != -ENODEV)
+ printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
return ret;
}
@@ -317,9 +419,14 @@ int __init dmar_table_init(void)
return -ENODEV;
}
+#ifdef CONFIG_DMAR
if (list_empty(&dmar_rmrr_units))
printk(KERN_INFO PREFIX "No RMRR found\n");
+#endif
+#ifdef CONFIG_INTR_REMAP
+ parse_ioapics_under_ir();
+#endif
return 0;
}
@@ -341,3 +448,255 @@ int __init early_dmar_detect(void)
return (ACPI_SUCCESS(status) ? 1 : 0);
}
+
+void __init detect_intel_iommu(void)
+{
+ int ret;
+
+ ret = early_dmar_detect();
+
+#ifdef CONFIG_DMAR
+ {
+ struct acpi_table_dmar *dmar;
+ /*
+ * for now we will disable dma-remapping when interrupt
+ * remapping is enabled.
+ * When support for queued invalidation for IOTLB invalidation
+ * is added, we will not need this any more.
+ */
+ dmar = (struct acpi_table_dmar *) dmar_tbl;
+ if (ret && cpu_has_x2apic && dmar->flags & 0x1) {
+ printk(KERN_INFO
+ "Queued invalidation will be enabled to support "
+ "x2apic and Intr-remapping.\n");
+ printk(KERN_INFO
+ "Disabling IOMMU detection, because of missing "
+ "queued invalidation support for IOTLB "
+ "invalidation\n");
+ printk(KERN_INFO
+ "Use \"nox2apic\", if you want to use Intel "
+ " IOMMU for DMA-remapping and don't care about "
+ " x2apic support\n");
+
+ dmar_disabled = 1;
+ return;
+ }
+
+ if (ret && !no_iommu && !iommu_detected && !swiotlb &&
+ !dmar_disabled)
+ iommu_detected = 1;
+ }
+#endif
+}
+
+
+int alloc_iommu(struct dmar_drhd_unit *drhd)
+{
+ struct intel_iommu *iommu;
+ int map_size;
+ u32 ver;
+ static int iommu_allocated = 0;
+
+ iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return -ENOMEM;
+
+ iommu->seq_id = iommu_allocated++;
+
+ iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+ if (!iommu->reg) {
+ printk(KERN_ERR "IOMMU: can't map the region\n");
+ goto error;
+ }
+ iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+ iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+ /* the registers might be more than one page */
+ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+ cap_max_fault_reg_offset(iommu->cap));
+ map_size = PAGE_ALIGN_4K(map_size);
+ if (map_size > PAGE_SIZE_4K) {
+ iounmap(iommu->reg);
+ iommu->reg = ioremap(drhd->reg_base_addr, map_size);
+ if (!iommu->reg) {
+ printk(KERN_ERR "IOMMU: can't map the region\n");
+ goto error;
+ }
+ }
+
+ ver = readl(iommu->reg + DMAR_VER_REG);
+ pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
+ drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
+ iommu->cap, iommu->ecap);
+
+ spin_lock_init(&iommu->register_lock);
+
+ drhd->iommu = iommu;
+ return 0;
+error:
+ kfree(iommu);
+ return -1;
+}
+
+void free_iommu(struct intel_iommu *iommu)
+{
+ if (!iommu)
+ return;
+
+#ifdef CONFIG_DMAR
+ free_dmar_iommu(iommu);
+#endif
+
+ if (iommu->reg)
+ iounmap(iommu->reg);
+ kfree(iommu);
+}
+
+/*
+ * Reclaim all the submitted descriptors which have completed its work.
+ */
+static inline void reclaim_free_desc(struct q_inval *qi)
+{
+ while (qi->desc_status[qi->free_tail] == QI_DONE) {
+ qi->desc_status[qi->free_tail] = QI_FREE;
+ qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
+ qi->free_cnt++;
+ }
+}
+
+/*
+ * Submit the queued invalidation descriptor to the remapping
+ * hardware unit and wait for its completion.
+ */
+void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
+{
+ struct q_inval *qi = iommu->qi;
+ struct qi_desc *hw, wait_desc;
+ int wait_index, index;
+ unsigned long flags;
+
+ if (!qi)
+ return;
+
+ hw = qi->desc;
+
+ spin_lock(&qi->q_lock);
+ while (qi->free_cnt < 3) {
+ spin_unlock(&qi->q_lock);
+ cpu_relax();
+ spin_lock(&qi->q_lock);
+ }
+
+ index = qi->free_head;
+ wait_index = (index + 1) % QI_LENGTH;
+
+ qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE;
+
+ hw[index] = *desc;
+
+ wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
+ wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
+
+ hw[wait_index] = wait_desc;
+
+ __iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc));
+ __iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc));
+
+ qi->free_head = (qi->free_head + 2) % QI_LENGTH;
+ qi->free_cnt -= 2;
+
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ /*
+ * update the HW tail register indicating the presence of
+ * new descriptors.
+ */
+ writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+ while (qi->desc_status[wait_index] != QI_DONE) {
+ spin_unlock(&qi->q_lock);
+ cpu_relax();
+ spin_lock(&qi->q_lock);
+ }
+
+ qi->desc_status[index] = QI_DONE;
+
+ reclaim_free_desc(qi);
+ spin_unlock(&qi->q_lock);
+}
+
+/*
+ * Flush the global interrupt entry cache.
+ */
+void qi_global_iec(struct intel_iommu *iommu)
+{
+ struct qi_desc desc;
+
+ desc.low = QI_IEC_TYPE;
+ desc.high = 0;
+
+ qi_submit_sync(&desc, iommu);
+}
+
+/*
+ * Enable Queued Invalidation interface. This is a must to support
+ * interrupt-remapping. Also used by DMA-remapping, which replaces
+ * register based IOTLB invalidation.
+ */
+int dmar_enable_qi(struct intel_iommu *iommu)
+{
+ u32 cmd, sts;
+ unsigned long flags;
+ struct q_inval *qi;
+
+ if (!ecap_qis(iommu->ecap))
+ return -ENOENT;
+
+ /*
+ * queued invalidation is already setup and enabled.
+ */
+ if (iommu->qi)
+ return 0;
+
+ iommu->qi = kmalloc(sizeof(*qi), GFP_KERNEL);
+ if (!iommu->qi)
+ return -ENOMEM;
+
+ qi = iommu->qi;
+
+ qi->desc = (void *)(get_zeroed_page(GFP_KERNEL));
+ if (!qi->desc) {
+ kfree(qi);
+ iommu->qi = 0;
+ return -ENOMEM;
+ }
+
+ qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_KERNEL);
+ if (!qi->desc_status) {
+ free_page((unsigned long) qi->desc);
+ kfree(qi);
+ iommu->qi = 0;
+ return -ENOMEM;
+ }
+
+ qi->free_head = qi->free_tail = 0;
+ qi->free_cnt = QI_LENGTH;
+
+ spin_lock_init(&qi->q_lock);
+
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ /* write zero to the tail reg */
+ writel(0, iommu->reg + DMAR_IQT_REG);
+
+ dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
+
+ cmd = iommu->gcmd | DMA_GCMD_QIE;
+ iommu->gcmd |= DMA_GCMD_QIE;
+ writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+ /* Make sure hardware complete it */
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+ return 0;
+}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 40337a06c18..146ca9cd156 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -320,15 +320,15 @@ static int disable_slot(struct hotplug_slot *slot)
return -ENODEV;
}
+ /* remove the device from the pci core */
+ pci_remove_bus_device(dev);
+
/* queue work item to blow away this sysfs entry and other
* parts.
*/
INIT_WORK(&dslot->remove_work, remove_slot_worker);
queue_work(dummyphp_wq, &dslot->remove_work);
- /* blow away this sysfs entry and other parts. */
- remove_slot(dslot);
-
pci_dev_put(dev);
}
return 0;
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 8467d028732..7d27631e6e6 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -276,7 +276,7 @@ int __init ibmphp_access_ebda (void)
iounmap (io_mem);
debug ("returned ebda segment: %x\n", ebda_seg);
- io_mem = ioremap (ebda_seg<<4, 65000);
+ io_mem = ioremap(ebda_seg<<4, 1024);
if (!io_mem )
return -ENOMEM;
next_offset = 0x180;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index ab31f5ba665..9d934ddee95 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -258,7 +258,7 @@ static int pcie_poll_cmd(struct controller *ctrl)
return 1;
}
}
- while (timeout > 1000) {
+ while (timeout > 0) {
msleep(10);
timeout -= 10;
if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 9b714ea93d2..50884507b8b 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -147,9 +147,5 @@ int rpaphp_register_slot(struct slot *slot)
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
info("Slot [%s] registered\n", slot->name);
return 0;
-
-sysfs_fail:
- pci_hp_deregister(php_slot);
- return retval;
}
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 8d0e60ac849..fc5f2dbf532 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -33,8 +33,8 @@
#include <linux/dma-mapping.h>
#include <linux/mempool.h>
#include <linux/timer.h>
-#include "iova.h"
-#include "intel-iommu.h"
+#include <linux/iova.h>
+#include <linux/intel-iommu.h>
#include <asm/proto.h> /* force_iommu in this header in x86-64*/
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -49,8 +49,6 @@
#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
-#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */
-
#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
@@ -58,8 +56,6 @@ static void flush_unmaps_timeout(unsigned long data);
DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
-static struct intel_iommu *g_iommus;
-
#define HIGH_WATER_MARK 250
struct deferred_flush_tables {
int next;
@@ -80,7 +76,7 @@ static long list_size;
static void domain_remove_dev_info(struct dmar_domain *domain);
-static int dmar_disabled;
+int dmar_disabled;
static int __initdata dmar_map_gfx = 1;
static int dmar_forcedac;
static int intel_iommu_strict;
@@ -160,7 +156,7 @@ static inline void *alloc_domain_mem(void)
return iommu_kmem_cache_alloc(iommu_domain_cache);
}
-static inline void free_domain_mem(void *vaddr)
+static void free_domain_mem(void *vaddr)
{
kmem_cache_free(iommu_domain_cache, vaddr);
}
@@ -185,13 +181,6 @@ void free_iova_mem(struct iova *iova)
kmem_cache_free(iommu_iova_cache, iova);
}
-static inline void __iommu_flush_cache(
- struct intel_iommu *iommu, void *addr, int size)
-{
- if (!ecap_coherent(iommu->ecap))
- clflush_cache_range(addr, size);
-}
-
/* Gets context entry for a given bus and devfn */
static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
u8 bus, u8 devfn)
@@ -488,19 +477,6 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
return 0;
}
-#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
-{\
- cycles_t start_time = get_cycles();\
- while (1) {\
- sts = op (iommu->reg + offset);\
- if (cond)\
- break;\
- if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
- panic("DMAR hardware is malfunctioning\n");\
- cpu_relax();\
- }\
-}
-
static void iommu_set_root_entry(struct intel_iommu *iommu)
{
void *addr;
@@ -990,6 +966,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
return -ENOMEM;
}
+ spin_lock_init(&iommu->lock);
+
/*
* if Caching mode is set, then invalid translations are tagged
* with domainid 0. Hence we need to pre-allocate it.
@@ -998,62 +976,15 @@ static int iommu_init_domains(struct intel_iommu *iommu)
set_bit(0, iommu->domain_ids);
return 0;
}
-static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu,
- struct dmar_drhd_unit *drhd)
-{
- int ret;
- int map_size;
- u32 ver;
-
- iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
- if (!iommu->reg) {
- printk(KERN_ERR "IOMMU: can't map the region\n");
- goto error;
- }
- iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
- iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
- /* the registers might be more than one page */
- map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
- cap_max_fault_reg_offset(iommu->cap));
- map_size = PAGE_ALIGN_4K(map_size);
- if (map_size > PAGE_SIZE_4K) {
- iounmap(iommu->reg);
- iommu->reg = ioremap(drhd->reg_base_addr, map_size);
- if (!iommu->reg) {
- printk(KERN_ERR "IOMMU: can't map the region\n");
- goto error;
- }
- }
-
- ver = readl(iommu->reg + DMAR_VER_REG);
- pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
- drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
- iommu->cap, iommu->ecap);
- ret = iommu_init_domains(iommu);
- if (ret)
- goto error_unmap;
- spin_lock_init(&iommu->lock);
- spin_lock_init(&iommu->register_lock);
- drhd->iommu = iommu;
- return iommu;
-error_unmap:
- iounmap(iommu->reg);
-error:
- kfree(iommu);
- return NULL;
-}
static void domain_exit(struct dmar_domain *domain);
-static void free_iommu(struct intel_iommu *iommu)
+
+void free_dmar_iommu(struct intel_iommu *iommu)
{
struct dmar_domain *domain;
int i;
- if (!iommu)
- return;
-
i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
for (; i < cap_ndoms(iommu->cap); ) {
domain = iommu->domains[i];
@@ -1078,10 +1009,6 @@ static void free_iommu(struct intel_iommu *iommu)
/* free context mapping */
free_context_table(iommu);
-
- if (iommu->reg)
- iounmap(iommu->reg);
- kfree(iommu);
}
static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
@@ -1414,7 +1341,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
* find_domain
* Note: we use struct pci_dev->dev.archdata.iommu stores the info
*/
-struct dmar_domain *
+static struct dmar_domain *
find_domain(struct pci_dev *pdev)
{
struct device_domain_info *info;
@@ -1426,37 +1353,6 @@ find_domain(struct pci_dev *pdev)
return NULL;
}
-static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
- struct pci_dev *dev)
-{
- int index;
-
- while (dev) {
- for (index = 0; index < cnt; index++)
- if (dev == devices[index])
- return 1;
-
- /* Check our parent */
- dev = dev->bus->self;
- }
-
- return 0;
-}
-
-static struct dmar_drhd_unit *
-dmar_find_matched_drhd_unit(struct pci_dev *dev)
-{
- struct dmar_drhd_unit *drhd = NULL;
-
- list_for_each_entry(drhd, &dmar_drhd_units, list) {
- if (drhd->include_all || dmar_pci_device_match(drhd->devices,
- drhd->devices_cnt, dev))
- return drhd;
- }
-
- return NULL;
-}
-
/* domain is initialized */
static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
{
@@ -1729,8 +1625,6 @@ int __init init_dmars(void)
* endfor
*/
for_each_drhd_unit(drhd) {
- if (drhd->ignored)
- continue;
g_num_of_iommus++;
/*
* lock not needed as this is only incremented in the single
@@ -1739,12 +1633,6 @@ int __init init_dmars(void)
*/
}
- g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL);
- if (!g_iommus) {
- ret = -ENOMEM;
- goto error;
- }
-
deferred_flush = kzalloc(g_num_of_iommus *
sizeof(struct deferred_flush_tables), GFP_KERNEL);
if (!deferred_flush) {
@@ -1752,16 +1640,15 @@ int __init init_dmars(void)
goto error;
}
- i = 0;
for_each_drhd_unit(drhd) {
if (drhd->ignored)
continue;
- iommu = alloc_iommu(&g_iommus[i], drhd);
- i++;
- if (!iommu) {
- ret = -ENOMEM;
+
+ iommu = drhd->iommu;
+
+ ret = iommu_init_domains(iommu);
+ if (ret)
goto error;
- }
/*
* TBD:
@@ -1845,7 +1732,6 @@ error:
iommu = drhd->iommu;
free_iommu(iommu);
}
- kfree(g_iommus);
return ret;
}
@@ -2002,7 +1888,10 @@ static void flush_unmaps(void)
/* just flush them all */
for (i = 0; i < g_num_of_iommus; i++) {
if (deferred_flush[i].next) {
- iommu_flush_iotlb_global(&g_iommus[i], 0);
+ struct intel_iommu *iommu =
+ deferred_flush[i].domain[0]->iommu;
+
+ iommu_flush_iotlb_global(iommu, 0);
for (j = 0; j < deferred_flush[i].next; j++) {
__free_iova(&deferred_flush[i].domain[j]->iovad,
deferred_flush[i].iova[j]);
@@ -2032,7 +1921,8 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
if (list_size == HIGH_WATER_MARK)
flush_unmaps();
- iommu_id = dom->iommu - g_iommus;
+ iommu_id = dom->iommu->seq_id;
+
next = deferred_flush[iommu_id].next;
deferred_flush[iommu_id].domain[next] = dom;
deferred_flush[iommu_id].iova[next] = iova;
@@ -2348,15 +2238,6 @@ static void __init iommu_exit_mempool(void)
}
-void __init detect_intel_iommu(void)
-{
- if (swiotlb || no_iommu || iommu_detected || dmar_disabled)
- return;
- if (early_dmar_detect()) {
- iommu_detected = 1;
- }
-}
-
static void __init init_no_remapping_devices(void)
{
struct dmar_drhd_unit *drhd;
@@ -2403,12 +2284,19 @@ int __init intel_iommu_init(void)
{
int ret = 0;
- if (no_iommu || swiotlb || dmar_disabled)
- return -ENODEV;
-
if (dmar_table_init())
return -ENODEV;
+ if (dmar_dev_scope_init())
+ return -ENODEV;
+
+ /*
+ * Check the need for DMA-remapping initialization now.
+ * Above initialization will also be used by Interrupt-remapping.
+ */
+ if (no_iommu || swiotlb || dmar_disabled)
+ return -ENODEV;
+
iommu_init_mempool();
dmar_init_reserved_ranges();
@@ -2430,3 +2318,111 @@ int __init intel_iommu_init(void)
return 0;
}
+void intel_iommu_domain_exit(struct dmar_domain *domain)
+{
+ u64 end;
+
+ /* Domain 0 is reserved, so dont process it */
+ if (!domain)
+ return;
+
+ end = DOMAIN_MAX_ADDR(domain->gaw);
+ end = end & (~PAGE_MASK_4K);
+
+ /* clear ptes */
+ dma_pte_clear_range(domain, 0, end);
+
+ /* free page tables */
+ dma_pte_free_pagetable(domain, 0, end);
+
+ iommu_free_domain(domain);
+ free_domain_mem(domain);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_domain_exit);
+
+struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev)
+{
+ struct dmar_drhd_unit *drhd;
+ struct dmar_domain *domain;
+ struct intel_iommu *iommu;
+
+ drhd = dmar_find_matched_drhd_unit(pdev);
+ if (!drhd) {
+ printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n");
+ return NULL;
+ }
+
+ iommu = drhd->iommu;
+ if (!iommu) {
+ printk(KERN_ERR
+ "intel_iommu_domain_alloc: iommu == NULL\n");
+ return NULL;
+ }
+ domain = iommu_alloc_domain(iommu);
+ if (!domain) {
+ printk(KERN_ERR
+ "intel_iommu_domain_alloc: domain == NULL\n");
+ return NULL;
+ }
+ if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+ printk(KERN_ERR
+ "intel_iommu_domain_alloc: domain_init() failed\n");
+ intel_iommu_domain_exit(domain);
+ return NULL;
+ }
+ return domain;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc);
+
+int intel_iommu_context_mapping(
+ struct dmar_domain *domain, struct pci_dev *pdev)
+{
+ int rc;
+ rc = domain_context_mapping(domain, pdev);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_context_mapping);
+
+int intel_iommu_page_mapping(
+ struct dmar_domain *domain, dma_addr_t iova,
+ u64 hpa, size_t size, int prot)
+{
+ int rc;
+ rc = domain_page_mapping(domain, iova, hpa, size, prot);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_page_mapping);
+
+void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+{
+ detach_domain_for_dev(domain, bus, devfn);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_detach_dev);
+
+struct dmar_domain *
+intel_iommu_find_domain(struct pci_dev *pdev)
+{
+ return find_domain(pdev);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_find_domain);
+
+int intel_iommu_found(void)
+{
+ return g_num_of_iommus;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_found);
+
+u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
+{
+ struct dma_pte *pte;
+ u64 pfn;
+
+ pfn = 0;
+ pte = addr_to_dma_pte(domain, iova);
+
+ if (pte)
+ pfn = dma_pte_addr(*pte);
+
+ return pfn >> PAGE_SHIFT_4K;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
deleted file mode 100644
index afc0ad96122..00000000000
--- a/drivers/pci/intel-iommu.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- */
-
-#ifndef _INTEL_IOMMU_H_
-#define _INTEL_IOMMU_H_
-
-#include <linux/types.h>
-#include <linux/msi.h>
-#include <linux/sysdev.h>
-#include "iova.h"
-#include <linux/io.h>
-
-/*
- * We need a fixed PAGE_SIZE of 4K irrespective of
- * arch PAGE_SIZE for IOMMU page tables.
- */
-#define PAGE_SHIFT_4K (12)
-#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
-#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
-#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
-
-/*
- * Intel IOMMU register specification per version 1.0 public spec.
- */
-
-#define DMAR_VER_REG 0x0 /* Arch version supported by this IOMMU */
-#define DMAR_CAP_REG 0x8 /* Hardware supported capabilities */
-#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */
-#define DMAR_GCMD_REG 0x18 /* Global command register */
-#define DMAR_GSTS_REG 0x1c /* Global status register */
-#define DMAR_RTADDR_REG 0x20 /* Root entry table */
-#define DMAR_CCMD_REG 0x28 /* Context command reg */
-#define DMAR_FSTS_REG 0x34 /* Fault Status register */
-#define DMAR_FECTL_REG 0x38 /* Fault control register */
-#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data register */
-#define DMAR_FEADDR_REG 0x40 /* Fault event interrupt addr register */
-#define DMAR_FEUADDR_REG 0x44 /* Upper address register */
-#define DMAR_AFLOG_REG 0x58 /* Advanced Fault control */
-#define DMAR_PMEN_REG 0x64 /* Enable Protected Memory Region */
-#define DMAR_PLMBASE_REG 0x68 /* PMRR Low addr */
-#define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */
-#define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */
-#define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */
-
-#define OFFSET_STRIDE (9)
-/*
-#define dmar_readl(dmar, reg) readl(dmar + reg)
-#define dmar_readq(dmar, reg) ({ \
- u32 lo, hi; \
- lo = readl(dmar + reg); \
- hi = readl(dmar + reg + 4); \
- (((u64) hi) << 32) + lo; })
-*/
-static inline u64 dmar_readq(void __iomem *addr)
-{
- u32 lo, hi;
- lo = readl(addr);
- hi = readl(addr + 4);
- return (((u64) hi) << 32) + lo;
-}
-
-static inline void dmar_writeq(void __iomem *addr, u64 val)
-{
- writel((u32)val, addr);
- writel((u32)(val >> 32), addr + 4);
-}
-
-#define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4)
-#define DMAR_VER_MINOR(v) ((v) & 0x0f)
-
-/*
- * Decoding Capability Register
- */
-#define cap_read_drain(c) (((c) >> 55) & 1)
-#define cap_write_drain(c) (((c) >> 54) & 1)
-#define cap_max_amask_val(c) (((c) >> 48) & 0x3f)
-#define cap_num_fault_regs(c) ((((c) >> 40) & 0xff) + 1)
-#define cap_pgsel_inv(c) (((c) >> 39) & 1)
-
-#define cap_super_page_val(c) (((c) >> 34) & 0xf)
-#define cap_super_offset(c) (((find_first_bit(&cap_super_page_val(c), 4)) \
- * OFFSET_STRIDE) + 21)
-
-#define cap_fault_reg_offset(c) ((((c) >> 24) & 0x3ff) * 16)
-#define cap_max_fault_reg_offset(c) \
- (cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16)
-
-#define cap_zlr(c) (((c) >> 22) & 1)
-#define cap_isoch(c) (((c) >> 23) & 1)
-#define cap_mgaw(c) ((((c) >> 16) & 0x3f) + 1)
-#define cap_sagaw(c) (((c) >> 8) & 0x1f)
-#define cap_caching_mode(c) (((c) >> 7) & 1)
-#define cap_phmr(c) (((c) >> 6) & 1)
-#define cap_plmr(c) (((c) >> 5) & 1)
-#define cap_rwbf(c) (((c) >> 4) & 1)
-#define cap_afl(c) (((c) >> 3) & 1)
-#define cap_ndoms(c) (((unsigned long)1) << (4 + 2 * ((c) & 0x7)))
-/*
- * Extended Capability Register
- */
-
-#define ecap_niotlb_iunits(e) ((((e) >> 24) & 0xff) + 1)
-#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16)
-#define ecap_max_iotlb_offset(e) \
- (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
-#define ecap_coherent(e) ((e) & 0x1)
-
-
-/* IOTLB_REG */
-#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
-#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
-#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
-#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
-#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
-#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
-#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
-#define DMA_TLB_DID(id) (((u64)((id) & 0xffff)) << 32)
-#define DMA_TLB_IVT (((u64)1) << 63)
-#define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
-#define DMA_TLB_MAX_SIZE (0x3f)
-
-/* PMEN_REG */
-#define DMA_PMEN_EPM (((u32)1)<<31)
-#define DMA_PMEN_PRS (((u32)1)<<0)
-
-/* GCMD_REG */
-#define DMA_GCMD_TE (((u32)1) << 31)
-#define DMA_GCMD_SRTP (((u32)1) << 30)
-#define DMA_GCMD_SFL (((u32)1) << 29)
-#define DMA_GCMD_EAFL (((u32)1) << 28)
-#define DMA_GCMD_WBF (((u32)1) << 27)
-
-/* GSTS_REG */
-#define DMA_GSTS_TES (((u32)1) << 31)
-#define DMA_GSTS_RTPS (((u32)1) << 30)
-#define DMA_GSTS_FLS (((u32)1) << 29)
-#define DMA_GSTS_AFLS (((u32)1) << 28)
-#define DMA_GSTS_WBFS (((u32)1) << 27)
-
-/* CCMD_REG */
-#define DMA_CCMD_ICC (((u64)1) << 63)
-#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
-#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
-#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
-#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
-#define DMA_CCMD_MASK_NOBIT 0
-#define DMA_CCMD_MASK_1BIT 1
-#define DMA_CCMD_MASK_2BIT 2
-#define DMA_CCMD_MASK_3BIT 3
-#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
-#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
-
-/* FECTL_REG */
-#define DMA_FECTL_IM (((u32)1) << 31)
-
-/* FSTS_REG */
-#define DMA_FSTS_PPF ((u32)2)
-#define DMA_FSTS_PFO ((u32)1)
-#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
-
-/* FRCD_REG, 32 bits access */
-#define DMA_FRCD_F (((u32)1) << 31)
-#define dma_frcd_type(d) ((d >> 30) & 1)
-#define dma_frcd_fault_reason(c) (c & 0xff)
-#define dma_frcd_source_id(c) (c & 0xffff)
-#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
- u64 val;
- u64 rsvd1;
-};
-#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
- return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
- root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
- root->val |= value & PAGE_MASK_4K;
-}
-
-struct context_entry;
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
- return (struct context_entry *)
- (root_present(root)?phys_to_virt(
- root->val & PAGE_MASK_4K):
- NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
- u64 lo;
- u64 hi;
-};
-#define context_present(c) ((c).lo & 1)
-#define context_fault_disable(c) (((c).lo >> 1) & 1)
-#define context_translation_type(c) (((c).lo >> 2) & 3)
-#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
-#define context_address_width(c) ((c).hi & 7)
-#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
-
-#define context_set_present(c) do {(c).lo |= 1;} while (0)
-#define context_set_fault_enable(c) \
- do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
-#define context_set_translation_type(c, val) \
- do { \
- (c).lo &= (((u64)-1) << 4) | 3; \
- (c).lo |= ((val) & 3) << 2; \
- } while (0)
-#define CONTEXT_TT_MULTI_LEVEL 0
-#define context_set_address_root(c, val) \
- do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
-#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
-#define context_set_domain_id(c, val) \
- do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
-#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-11: available
- * 12-63: Host physcial address
- */
-struct dma_pte {
- u64 val;
-};
-#define dma_clear_pte(p) do {(p).val = 0;} while (0)
-
-#define DMA_PTE_READ (1)
-#define DMA_PTE_WRITE (2)
-
-#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
-#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
-#define dma_set_pte_prot(p, prot) \
- do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
-#define dma_set_pte_addr(p, addr) do {\
- (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
-#define dma_pte_present(p) (((p).val & 3) != 0)
-
-struct intel_iommu;
-
-struct dmar_domain {
- int id; /* domain id */
- struct intel_iommu *iommu; /* back pointer to owning iommu */
-
- struct list_head devices; /* all devices' list */
- struct iova_domain iovad; /* iova's that belong to this domain */
-
- struct dma_pte *pgd; /* virtual address */
- spinlock_t mapping_lock; /* page table lock */
- int gaw; /* max guest address width */
-
- /* adjusted guest address width, 0 is level 2 30-bit */
- int agaw;
-
-#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
- int flags;
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
- struct list_head link; /* link to domain siblings */
- struct list_head global; /* link to global list */
- u8 bus; /* PCI bus numer */
- u8 devfn; /* PCI devfn number */
- struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
- struct dmar_domain *domain; /* pointer to domain */
-};
-
-extern int init_dmars(void);
-
-struct intel_iommu {
- void __iomem *reg; /* Pointer to hardware regs, virtual addr */
- u64 cap;
- u64 ecap;
- unsigned long *domain_ids; /* bitmap of domains */
- struct dmar_domain **domains; /* ptr to domains */
- int seg;
- u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
- spinlock_t lock; /* protect context, domain ids */
- spinlock_t register_lock; /* protect register handling */
- struct root_entry *root_entry; /* virtual address */
-
- unsigned int irq;
- unsigned char name[7]; /* Device Name */
- struct msi_msg saved_msg;
- struct sys_device sysdev;
-};
-
-#ifndef CONFIG_DMAR_GFX_WA
-static inline void iommu_prepare_gfx_mapping(void)
-{
- return;
-}
-#endif /* !CONFIG_DMAR_GFX_WA */
-
-#endif
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
new file mode 100644
index 00000000000..738d4c89581
--- /dev/null
+++ b/drivers/pci/intr_remapping.c
@@ -0,0 +1,471 @@
+#include <linux/dmar.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/io_apic.h>
+#include <linux/intel-iommu.h>
+#include "intr_remapping.h"
+
+static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
+static int ir_ioapic_num;
+int intr_remapping_enabled;
+
+static struct {
+ struct intel_iommu *iommu;
+ u16 irte_index;
+ u16 sub_handle;
+ u8 irte_mask;
+} irq_2_iommu[NR_IRQS];
+
+static DEFINE_SPINLOCK(irq_2_ir_lock);
+
+int irq_remapped(int irq)
+{
+ if (irq > NR_IRQS)
+ return 0;
+
+ if (!irq_2_iommu[irq].iommu)
+ return 0;
+
+ return 1;
+}
+
+int get_irte(int irq, struct irte *entry)
+{
+ int index;
+
+ if (!entry || irq > NR_IRQS)
+ return -1;
+
+ spin_lock(&irq_2_ir_lock);
+ if (!irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ *entry = *(irq_2_iommu[irq].iommu->ir_table->base + index);
+
+ spin_unlock(&irq_2_ir_lock);
+ return 0;
+}
+
+int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+{
+ struct ir_table *table = iommu->ir_table;
+ u16 index, start_index;
+ unsigned int mask = 0;
+ int i;
+
+ if (!count)
+ return -1;
+
+ /*
+ * start the IRTE search from index 0.
+ */
+ index = start_index = 0;
+
+ if (count > 1) {
+ count = __roundup_pow_of_two(count);
+ mask = ilog2(count);
+ }
+
+ if (mask > ecap_max_handle_mask(iommu->ecap)) {
+ printk(KERN_ERR
+ "Requested mask %x exceeds the max invalidation handle"
+ " mask value %Lx\n", mask,
+ ecap_max_handle_mask(iommu->ecap));
+ return -1;
+ }
+
+ spin_lock(&irq_2_ir_lock);
+ do {
+ for (i = index; i < index + count; i++)
+ if (table->base[i].present)
+ break;
+ /* empty index found */
+ if (i == index + count)
+ break;
+
+ index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
+
+ if (index == start_index) {
+ spin_unlock(&irq_2_ir_lock);
+ printk(KERN_ERR "can't allocate an IRTE\n");
+ return -1;
+ }
+ } while (1);
+
+ for (i = index; i < index + count; i++)
+ table->base[i].present = 1;
+
+ irq_2_iommu[irq].iommu = iommu;
+ irq_2_iommu[irq].irte_index = index;
+ irq_2_iommu[irq].sub_handle = 0;
+ irq_2_iommu[irq].irte_mask = mask;
+
+ spin_unlock(&irq_2_ir_lock);
+
+ return index;
+}
+
+static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
+{
+ struct qi_desc desc;
+
+ desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
+ | QI_IEC_SELECTIVE;
+ desc.high = 0;
+
+ qi_submit_sync(&desc, iommu);
+}
+
+int map_irq_to_irte_handle(int irq, u16 *sub_handle)
+{
+ int index;
+
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ *sub_handle = irq_2_iommu[irq].sub_handle;
+ index = irq_2_iommu[irq].irte_index;
+ spin_unlock(&irq_2_ir_lock);
+ return index;
+}
+
+int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
+{
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ irq_2_iommu[irq].iommu = iommu;
+ irq_2_iommu[irq].irte_index = index;
+ irq_2_iommu[irq].sub_handle = subhandle;
+ irq_2_iommu[irq].irte_mask = 0;
+
+ spin_unlock(&irq_2_ir_lock);
+
+ return 0;
+}
+
+int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
+{
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ irq_2_iommu[irq].iommu = NULL;
+ irq_2_iommu[irq].irte_index = 0;
+ irq_2_iommu[irq].sub_handle = 0;
+ irq_2_iommu[irq].irte_mask = 0;
+
+ spin_unlock(&irq_2_ir_lock);
+
+ return 0;
+}
+
+int modify_irte(int irq, struct irte *irte_modified)
+{
+ int index;
+ struct irte *irte;
+ struct intel_iommu *iommu;
+
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ iommu = irq_2_iommu[irq].iommu;
+
+ index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ irte = &iommu->ir_table->base[index];
+
+ set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
+ __iommu_flush_cache(iommu, irte, sizeof(*irte));
+
+ qi_flush_iec(iommu, index, 0);
+
+ spin_unlock(&irq_2_ir_lock);
+ return 0;
+}
+
+int flush_irte(int irq)
+{
+ int index;
+ struct intel_iommu *iommu;
+
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ iommu = irq_2_iommu[irq].iommu;
+
+ index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+
+ qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+ spin_unlock(&irq_2_ir_lock);
+
+ return 0;
+}
+
+struct intel_iommu *map_ioapic_to_ir(int apic)
+{
+ int i;
+
+ for (i = 0; i < MAX_IO_APICS; i++)
+ if (ir_ioapic[i].id == apic)
+ return ir_ioapic[i].iommu;
+ return NULL;
+}
+
+struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
+{
+ struct dmar_drhd_unit *drhd;
+
+ drhd = dmar_find_matched_drhd_unit(dev);
+ if (!drhd)
+ return NULL;
+
+ return drhd->iommu;
+}
+
+int free_irte(int irq)
+{
+ int index, i;
+ struct irte *irte;
+ struct intel_iommu *iommu;
+
+ spin_lock(&irq_2_ir_lock);
+ if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+ spin_unlock(&irq_2_ir_lock);
+ return -1;
+ }
+
+ iommu = irq_2_iommu[irq].iommu;
+
+ index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
+ irte = &iommu->ir_table->base[index];
+
+ if (!irq_2_iommu[irq].sub_handle) {
+ for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++)
+ set_64bit((unsigned long *)irte, 0);
+ qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
+ }
+
+ irq_2_iommu[irq].iommu = NULL;
+ irq_2_iommu[irq].irte_index = 0;
+ irq_2_iommu[irq].sub_handle = 0;
+ irq_2_iommu[irq].irte_mask = 0;
+
+ spin_unlock(&irq_2_ir_lock);
+
+ return 0;
+}
+
+static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+ u64 addr;
+ u32 cmd, sts;
+ unsigned long flags;
+
+ addr = virt_to_phys((void *)iommu->ir_table->base);
+
+ spin_lock_irqsave(&iommu->register_lock, flags);
+
+ dmar_writeq(iommu->reg + DMAR_IRTA_REG,
+ (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
+
+ /* Set interrupt-remapping table pointer */
+ cmd = iommu->gcmd | DMA_GCMD_SIRTP;
+ writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (sts & DMA_GSTS_IRTPS), sts);
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+ /*
+ * global invalidation of interrupt entry cache before enabling
+ * interrupt-remapping.
+ */
+ qi_global_iec(iommu);
+
+ spin_lock_irqsave(&iommu->register_lock, flags);
+
+ /* Enable interrupt-remapping */
+ cmd = iommu->gcmd | DMA_GCMD_IRE;
+ iommu->gcmd |= DMA_GCMD_IRE;
+ writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+ readl, (sts & DMA_GSTS_IRES), sts);
+
+ spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+
+static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+ struct ir_table *ir_table;
+ struct page *pages;
+
+ ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
+ GFP_KERNEL);
+
+ if (!iommu->ir_table)
+ return -ENOMEM;
+
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
+
+ if (!pages) {
+ printk(KERN_ERR "failed to allocate pages of order %d\n",
+ INTR_REMAP_PAGE_ORDER);
+ kfree(iommu->ir_table);
+ return -ENOMEM;
+ }
+
+ ir_table->base = page_address(pages);
+
+ iommu_set_intr_remapping(iommu, mode);
+ return 0;
+}
+
+int __init enable_intr_remapping(int eim)
+{
+ struct dmar_drhd_unit *drhd;
+ int setup = 0;
+
+ /*
+ * check for the Interrupt-remapping support
+ */
+ for_each_drhd_unit(drhd) {
+ struct intel_iommu *iommu = drhd->iommu;
+
+ if (!ecap_ir_support(iommu->ecap))
+ continue;
+
+ if (eim && !ecap_eim_support(iommu->ecap)) {
+ printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
+ " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
+ return -1;
+ }
+ }
+
+ /*
+ * Enable queued invalidation for all the DRHD's.
+ */
+ for_each_drhd_unit(drhd) {
+ int ret;
+ struct intel_iommu *iommu = drhd->iommu;
+ ret = dmar_enable_qi(iommu);
+
+ if (ret) {
+ printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
+ " invalidation, ecap %Lx, ret %d\n",
+ drhd->reg_base_addr, iommu->ecap, ret);
+ return -1;
+ }
+ }
+
+ /*
+ * Setup Interrupt-remapping for all the DRHD's now.
+ */
+ for_each_drhd_unit(drhd) {
+ struct intel_iommu *iommu = drhd->iommu;
+
+ if (!ecap_ir_support(iommu->ecap))
+ continue;
+
+ if (setup_intr_remapping(iommu, eim))
+ goto error;
+
+ setup = 1;
+ }
+
+ if (!setup)
+ goto error;
+
+ intr_remapping_enabled = 1;
+
+ return 0;
+
+error:
+ /*
+ * handle error condition gracefully here!
+ */
+ return -1;
+}
+
+static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
+ struct intel_iommu *iommu)
+{
+ struct acpi_dmar_hardware_unit *drhd;
+ struct acpi_dmar_device_scope *scope;
+ void *start, *end;
+
+ drhd = (struct acpi_dmar_hardware_unit *)header;
+
+ start = (void *)(drhd + 1);
+ end = ((void *)drhd) + header->length;
+
+ while (start < end) {
+ scope = start;
+ if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
+ if (ir_ioapic_num == MAX_IO_APICS) {
+ printk(KERN_WARNING "Exceeded Max IO APICS\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "IOAPIC id %d under DRHD base"
+ " 0x%Lx\n", scope->enumeration_id,
+ drhd->address);
+
+ ir_ioapic[ir_ioapic_num].iommu = iommu;
+ ir_ioapic[ir_ioapic_num].id = scope->enumeration_id;
+ ir_ioapic_num++;
+ }
+ start += scope->length;
+ }
+
+ return 0;
+}
+
+/*
+ * Finds the assocaition between IOAPIC's and its Interrupt-remapping
+ * hardware unit.
+ */
+int __init parse_ioapics_under_ir(void)
+{
+ struct dmar_drhd_unit *drhd;
+ int ir_supported = 0;
+
+ for_each_drhd_unit(drhd) {
+ struct intel_iommu *iommu = drhd->iommu;
+
+ if (ecap_ir_support(iommu->ecap)) {
+ if (ir_parse_ioapic_scope(drhd->hdr, iommu))
+ return -1;
+
+ ir_supported = 1;
+ }
+ }
+
+ if (ir_supported && ir_ioapic_num != nr_ioapics) {
+ printk(KERN_WARNING
+ "Not all IO-APIC's listed under remapping hardware\n");
+ return -1;
+ }
+
+ return ir_supported;
+}
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
new file mode 100644
index 00000000000..ca48f0df8ac
--- /dev/null
+++ b/drivers/pci/intr_remapping.h
@@ -0,0 +1,8 @@
+#include <linux/intel-iommu.h>
+
+struct ioapic_scope {
+ struct intel_iommu *iommu;
+ unsigned int id;
+};
+
+#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
index 3ef4ac06431..2287116e982 100644
--- a/drivers/pci/iova.c
+++ b/drivers/pci/iova.c
@@ -7,7 +7,7 @@
* Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
*/
-#include "iova.h"
+#include <linux/iova.h>
void
init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h
deleted file mode 100644
index 228f6c94b69..00000000000
--- a/drivers/pci/iova.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This file is released under the GPLv2.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *
- */
-
-#ifndef _IOVA_H_
-#define _IOVA_H_
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/rbtree.h>
-#include <linux/dma-mapping.h>
-
-/* IO virtual address start page frame number */
-#define IOVA_START_PFN (1)
-
-/* iova structure */
-struct iova {
- struct rb_node node;
- unsigned long pfn_hi; /* IOMMU dish out addr hi */
- unsigned long pfn_lo; /* IOMMU dish out addr lo */
-};
-
-/* holds all the iova translations for a domain */
-struct iova_domain {
- spinlock_t iova_alloc_lock;/* Lock to protect iova allocation */
- spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
- struct rb_root rbroot; /* iova domain rbtree root */
- struct rb_node *cached32_node; /* Save last alloced node */
- unsigned long dma_32bit_pfn;
-};
-
-struct iova *alloc_iova_mem(void);
-void free_iova_mem(struct iova *iova);
-void free_iova(struct iova_domain *iovad, unsigned long pfn);
-void __free_iova(struct iova_domain *iovad, struct iova *iova);
-struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
- unsigned long limit_pfn,
- bool size_aligned);
-struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
- unsigned long pfn_hi);
-void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
-void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
-struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
-void put_iova_domain(struct iova_domain *iovad);
-
-#endif
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9c718583a23..77baff022f7 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/topology.h>
@@ -484,6 +485,21 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
#endif /* HAVE_PCI_LEGACY */
#ifdef HAVE_PCI_MMAP
+
+static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+{
+ unsigned long nr, start, size;
+
+ nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ start = vma->vm_pgoff;
+ size = pci_resource_len(pdev, resno) >> PAGE_SHIFT;
+ if (start < size && size - start >= nr)
+ return 1;
+ WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
+ current->comm, start, start+nr, pci_name(pdev), resno, size);
+ return 0;
+}
+
/**
* pci_mmap_resource - map a PCI resource into user memory space
* @kobj: kobject for mapping
@@ -510,6 +526,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
if (i >= PCI_ROM_RESOURCE)
return -ENODEV;
+ if (!pci_mmap_fits(pdev, i, vma))
+ return -EINVAL;
+
/* pci_mmap_page_range() expects the same kind of entry as coming
* from /proc/bus/pci/ which is a "user visible" value. If this is
* different from the resource itself, arch will do necessary fixup.
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 9a7c9e1408a..851f5b83cdb 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -527,7 +527,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
*/
pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
&reg32);
- if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) {
+ if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
printk("Pre-1.1 PCIe device detected, "
"disable ASPM for %s. It can be enabled forcedly"
" with 'pcie_aspm=force'\n", pci_name(pdev));
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cce2f4cb1fb..dd9161a054e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -304,6 +304,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else {
res->start = l64;
res->end = l64 + sz64;
+ printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n",
+ pci_name(dev), pos, (unsigned long long)res->start,
+ (unsigned long long)res->end);
}
} else {
sz = pci_size(l, sz, mask);
@@ -313,6 +316,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l;
res->end = l + sz;
+ printk(KERN_DEBUG "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev),
+ pos, (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
+ (unsigned long long)res->start, (unsigned long long)res->end);
}
out:
@@ -383,7 +389,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base;
if (!res->end)
res->end = limit + 0xfff;
- printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), res->start, res->end);
+ printk(KERN_DEBUG "PCI: bridge %s io port: [%llx, %llx]\n",
+ pci_name(dev), (unsigned long long) res->start,
+ (unsigned long long) res->end);
}
res = child->resource[1];
@@ -395,7 +403,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), res->start, res->end);
+ printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: [%llx, %llx]\n",
+ pci_name(dev), (unsigned long long) res->start,
+ (unsigned long long) res->end);
}
res = child->resource[2];
@@ -431,7 +441,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64)?"64":"32",res->start, res->end);
+ printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n",
+ pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
+ (unsigned long long) res->start, (unsigned long long) res->end);
}
}
@@ -1225,8 +1237,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
#endif
-static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
{
+ const struct pci_dev *a = to_pci_dev(d_a);
+ const struct pci_dev *b = to_pci_dev(d_b);
+
if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1;
@@ -1239,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
return 0;
}
-/*
- * Yes, this forcably breaks the klist abstraction temporarily. It
- * just wants to sort the klist, not change reference counts and
- * take/drop locks rapidly in the process. It does all this while
- * holding the lock for the list, so objects can't otherwise be
- * added/removed while we're swizzling.
- */
-static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
-{
- struct list_head *pos;
- struct klist_node *n;
- struct device *dev;
- struct pci_dev *b;
-
- list_for_each(pos, list) {
- n = container_of(pos, struct klist_node, n_node);
- dev = container_of(n, struct device, knode_bus);
- b = to_pci_dev(dev);
- if (pci_sort_bf_cmp(a, b) <= 0) {
- list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
- return;
- }
- }
- list_move_tail(&a->dev.knode_bus.n_node, list);
-}
-
void __init pci_sort_breadthfirst(void)
{
- LIST_HEAD(sorted_devices);
- struct list_head *pos, *tmp;
- struct klist_node *n;
- struct device *dev;
- struct pci_dev *pdev;
- struct klist *device_klist;
-
- device_klist = bus_get_device_klist(&pci_bus_type);
-
- spin_lock(&device_klist->k_lock);
- list_for_each_safe(pos, tmp, &device_klist->k_list) {
- n = container_of(pos, struct klist_node, n_node);
- dev = container_of(n, struct device, knode_bus);
- pdev = to_pci_dev(dev);
- pci_insertion_sort_klist(pdev, &sorted_devices);
- }
- list_splice(&sorted_devices, &device_klist->k_list);
- spin_unlock(&device_klist->k_lock);
+ bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 9236e7f869c..e872ac925b4 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1561,8 +1561,7 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
#ifdef DEBUG
- dev_dbg(&dev->dev, "calling ");
- print_fn_descriptor_symbol("%s\n", f->hook);
+ dev_dbg(&dev->dev, "calling %pF\n", f->hook);
#endif
f->hook(dev);
}
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 3b3b5f17879..4edfc4731bd 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -162,7 +162,7 @@ EXPORT_SYMBOL(pci_find_slot);
* time.
*/
struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
- const struct pci_dev *from)
+ struct pci_dev *from)
{
struct pci_dev *pdev;
@@ -263,7 +263,7 @@ static int match_pci_dev_by_id(struct device *dev, void *data)
* this file.
*/
static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
- const struct pci_dev *from)
+ struct pci_dev *from)
{
struct device *dev;
struct device *dev_start = NULL;
@@ -303,7 +303,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
*/
struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device,
- const struct pci_dev *from)
+ struct pci_dev *from)
{
struct pci_dev *pdev;
struct pci_device_id *id;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 82634a2f1b1..d5e2106760f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -352,11 +352,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
continue;
r_size = r->end - r->start + 1;
/* For bridges size != alignment */
- align = (i < PCI_BRIDGE_RESOURCES) ? r_size : r->start;
+ align = resource_alignment(r);
order = __ffs(align) - 20;
if (order > 11) {
- dev_warn(&dev->dev, "BAR %d too large: "
+ dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
"%#016llx-%#016llx\n", i,
+ (unsigned long long)align,
(unsigned long long)r->start,
(unsigned long long)r->end);
r->flags = 0;
@@ -377,11 +378,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
align = 0;
min_align = 0;
for (order = 0; order <= max_order; order++) {
-#ifdef CONFIG_RESOURCES_64BIT
- resource_size_t align1 = 1ULL << (order + 20);
-#else
- resource_size_t align1 = 1U << (order + 20);
-#endif
+ resource_size_t align1 = 1;
+
+ align1 <<= (order + 20);
+
if (!align)
min_align = align1;
else if (ALIGN(align + min_align, min_align) < align1)
@@ -539,7 +539,11 @@ static void pci_bus_dump_res(struct pci_bus *bus)
if (!res)
continue;
- printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", bus->number, i, (res->flags & IORESOURCE_IO)? "io port":"mmio", res->start, res->end);
+ printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n",
+ bus->number, i,
+ (res->flags & IORESOURCE_IO) ? "io port" : "mmio",
+ (unsigned long long) res->start,
+ (unsigned long long) res->end);
}
}
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index e0f884034c9..f57eeae3830 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -220,7 +220,8 @@ config PCMCIA_PXA2XX
tristate "PXA2xx support"
depends on ARM && ARCH_PXA && PCMCIA
depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
- || MACH_ARMCORE || ARCH_PXA_PALM)
+ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
+ || ARCH_VIPER)
help
Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 269a9e913ba..b46c60b7270 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -2,10 +2,6 @@
# Makefile for the kernel pcmcia subsystem (c/o David Hinds)
#
-ifeq ($(CONFIG_PCMCIA_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
-
pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
@@ -29,7 +25,6 @@ obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
-obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o
obj-$(CONFIG_M32R_PCC) += m32r_pcc.o
obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
@@ -68,9 +63,15 @@ sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
-pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
-pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
-pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
-pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
-pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
+pxa2xx_lubbock_cs-y += pxa2xx_lubbock.o sa1111_generic.o
+pxa2xx_cm_x2xx_cs-y += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o
+pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o
+pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
+pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
+pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o
+pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o
+pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o
+pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
+pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o
+obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y)
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 75e8f8505e4..fc1de46fd20 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -292,7 +292,7 @@ au1x00_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
skt->spd_io[map->map] = speed;
}
- map->start=(ioaddr_t)(u32)skt->virt_io;
+ map->start=(unsigned int)(u32)skt->virt_io;
map->stop=map->start+MAP_SIZE;
return 0;
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index a53ef590251..13a4fbc5871 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -116,7 +116,7 @@ struct au1000_pcmcia_socket {
struct resource res_attr;
void * virt_io;
- ioaddr_t phys_io;
+ unsigned int phys_io;
unsigned int phys_attr;
unsigned int phys_mem;
unsigned short speed_io, speed_attr, speed_mem;
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index aa1cd4d3aa2..d6b4bd1db7d 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -37,7 +37,6 @@
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/bus_ops.h>
-#include "cs_internal.h"
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c
index 8a9b18cee84..9627390835c 100644
--- a/drivers/pcmcia/au1000_xxs1500.c
+++ b/drivers/pcmcia/au1000_xxs1500.c
@@ -41,7 +41,6 @@
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/bus_ops.h>
-#include "cs_internal.h"
#include <asm/io.h>
#include <asm/irq.h>
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 911ca0e8dfc..db77e1f3309 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -238,7 +238,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
pci_bus_add_devices(bus);
s->irq.AssignedIRQ = s->pci_irq;
- return CS_SUCCESS;
+ return 0;
}
void cb_free(struct pcmcia_socket * s)
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 65129b54eb0..dcce9f5d846 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -92,7 +92,8 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
if (mem->res == NULL) {
- printk(KERN_NOTICE "cs: unable to map card memory!\n");
+ dev_printk(KERN_NOTICE, &s->dev,
+ "cs: unable to map card memory!\n");
return NULL;
}
s->cis_virt = NULL;
@@ -265,13 +266,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
======================================================================*/
static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
- u_int len, void *ptr)
+ size_t len, void *ptr)
{
struct cis_cache_entry *cis;
int ret;
if (s->fake_cis) {
- if (s->fake_cis_len > addr+len)
+ if (s->fake_cis_len >= addr+len)
memcpy(ptr, s->fake_cis+addr, len);
else
memset(ptr, 0xff, len);
@@ -351,7 +352,9 @@ int verify_cis_cache(struct pcmcia_socket *s)
buf = kmalloc(256, GFP_KERNEL);
if (buf == NULL)
- return -1;
+ dev_printk(KERN_WARNING, &s->dev,
+ "no memory for verifying CIS\n");
+ return -ENOMEM;
list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len;
@@ -380,18 +383,22 @@ int verify_cis_cache(struct pcmcia_socket *s)
======================================================================*/
-int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis)
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+ const u8 *data, const size_t len)
{
- kfree(s->fake_cis);
- s->fake_cis = NULL;
- if (cis->Length > CISTPL_MAX_CIS_SIZE)
- return CS_BAD_SIZE;
- s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
- if (s->fake_cis == NULL)
- return CS_OUT_OF_RESOURCE;
- s->fake_cis_len = cis->Length;
- memcpy(s->fake_cis, cis->Data, cis->Length);
- return CS_SUCCESS;
+ if (len > CISTPL_MAX_CIS_SIZE) {
+ dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n");
+ return -EINVAL;
+ }
+ kfree(s->fake_cis);
+ s->fake_cis = kmalloc(len, GFP_KERNEL);
+ if (s->fake_cis == NULL) {
+ dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n");
+ return -ENOMEM;
+ }
+ s->fake_cis_len = len;
+ memcpy(s->fake_cis, data, len);
+ return 0;
}
EXPORT_SYMBOL(pcmcia_replace_cis);
@@ -418,9 +425,9 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *t
int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
{
if (!s)
- return CS_BAD_HANDLE;
+ return -EINVAL;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
tuple->TupleLink = tuple->Flags = 0;
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) {
@@ -440,10 +447,10 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
!(tuple->Attributes & TUPLE_RETURN_COMMON)) {
cisdata_t req = tuple->DesiredTuple;
tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
- if (pccard_get_next_tuple(s, function, tuple) == CS_SUCCESS) {
+ if (pccard_get_next_tuple(s, function, tuple) == 0) {
tuple->DesiredTuple = CISTPL_LINKTARGET;
- if (pccard_get_next_tuple(s, function, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
+ if (pccard_get_next_tuple(s, function, tuple) != 0)
+ return -ENOSPC;
} else
tuple->CISOffset = tuple->TupleLink = 0;
tuple->DesiredTuple = req;
@@ -498,9 +505,9 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
int ofs, i, attr;
if (!s)
- return CS_BAD_HANDLE;
+ return -EINVAL;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
link[1] = tuple->TupleLink;
ofs = tuple->CISOffset + tuple->TupleLink;
@@ -519,7 +526,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
/* End of chain? Follow long link if possible */
if (link[0] == CISTPL_END) {
if ((ofs = follow_link(s, tuple)) < 0)
- return CS_NO_MORE_ITEMS;
+ return -ENOSPC;
attr = SPACE(tuple->Flags);
read_cis_cache(s, attr, ofs, 2, link);
}
@@ -577,13 +584,13 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
}
if (i == MAX_TUPLES) {
cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n");
- return CS_NO_MORE_ITEMS;
+ return -ENOSPC;
}
tuple->TupleCode = link[0];
tuple->TupleLink = link[1];
tuple->CISOffset = ofs + 2;
- return CS_SUCCESS;
+ return 0;
}
EXPORT_SYMBOL(pccard_get_next_tuple);
@@ -596,18 +603,18 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
u_int len;
if (!s)
- return CS_BAD_HANDLE;
+ return -EINVAL;
if (tuple->TupleLink < tuple->TupleOffset)
- return CS_NO_MORE_ITEMS;
+ return -ENOSPC;
len = tuple->TupleLink - tuple->TupleOffset;
tuple->TupleDataLen = tuple->TupleLink;
if (len == 0)
- return CS_SUCCESS;
+ return 0;
read_cis_cache(s, SPACE(tuple->Flags),
tuple->CISOffset + tuple->TupleOffset,
_MIN(len, tuple->TupleDataMax), tuple->TupleData);
- return CS_SUCCESS;
+ return 0;
}
EXPORT_SYMBOL(pccard_get_tuple_data);
@@ -640,25 +647,31 @@ static int parse_device(tuple_t *tuple, cistpl_device_t *device)
case 3: device->dev[i].speed = 150; break;
case 4: device->dev[i].speed = 100; break;
case 7:
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
device->dev[i].speed = SPEED_CVT(*p);
while (*p & 0x80)
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
break;
default:
- return CS_BAD_TUPLE;
+ return -EINVAL;
}
- if (++p == q) return CS_BAD_TUPLE;
- if (*p == 0xff) break;
+ if (++p == q)
+ return -EINVAL;
+ if (*p == 0xff)
+ break;
scale = *p & 7;
- if (scale == 7) return CS_BAD_TUPLE;
+ if (scale == 7)
+ return -EINVAL;
device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
device->ndev++;
- if (++p == q) break;
+ if (++p == q)
+ break;
}
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -667,12 +680,12 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
{
u_char *p;
if (tuple->TupleDataLen < 5)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = (u_char *) tuple->TupleData;
csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
csum->len = get_unaligned_le16(p + 2);
csum->sum = *(p + 4);
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -680,9 +693,9 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
{
if (tuple->TupleDataLen < 4)
- return CS_BAD_TUPLE;
+ return -EINVAL;
link->addr = get_unaligned_le32(tuple->TupleData);
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -697,13 +710,13 @@ static int parse_longlink_mfc(tuple_t *tuple,
link->nfn = *p; p++;
if (tuple->TupleDataLen <= link->nfn*5)
- return CS_BAD_TUPLE;
+ return -EINVAL;
for (i = 0; i < link->nfn; i++) {
link->fn[i].space = *p; p++;
link->fn[i].addr = get_unaligned_le32(p);
p += 4;
}
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -713,24 +726,27 @@ static int parse_strings(u_char *p, u_char *q, int max,
{
int i, j, ns;
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
ns = 0; j = 0;
for (i = 0; i < max; i++) {
- if (*p == 0xff) break;
+ if (*p == 0xff)
+ break;
ofs[i] = j;
ns++;
for (;;) {
s[j++] = (*p == 0xff) ? '\0' : *p;
if ((*p == '\0') || (*p == 0xff)) break;
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
}
if ((*p == 0xff) || (++p == q)) break;
}
if (found) {
*found = ns;
- return CS_SUCCESS;
+ return 0;
} else {
- return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
+ return (ns == max) ? 0 : -EINVAL;
}
}
@@ -745,7 +761,8 @@ static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
vers_1->major = *p; p++;
vers_1->minor = *p; p++;
- if (p >= q) return CS_BAD_TUPLE;
+ if (p >= q)
+ return -EINVAL;
return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
vers_1->str, vers_1->ofs, &vers_1->ns);
@@ -781,7 +798,7 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
p += 2;
}
jedec->nid = nid;
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -789,10 +806,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
{
if (tuple->TupleDataLen < 4)
- return CS_BAD_TUPLE;
+ return -EINVAL;
m->manf = get_unaligned_le16(tuple->TupleData);
m->card = get_unaligned_le16(tuple->TupleData + 2);
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -801,11 +818,11 @@ static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
{
u_char *p;
if (tuple->TupleDataLen < 2)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = (u_char *)tuple->TupleData;
f->func = p[0];
f->sysinit = p[1];
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -815,12 +832,12 @@ static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
u_char *p;
int i;
if (tuple->TupleDataLen < 1)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = (u_char *)tuple->TupleData;
f->type = p[0];
for (i = 1; i < tuple->TupleDataLen; i++)
f->data[i-1] = p[i];
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -834,7 +851,7 @@ static int parse_config(tuple_t *tuple, cistpl_config_t *config)
rasz = *p & 0x03;
rmsz = (*p & 0x3c) >> 2;
if (tuple->TupleDataLen < rasz+rmsz+4)
- return CS_BAD_TUPLE;
+ return -EINVAL;
config->last_idx = *(++p);
p++;
config->base = 0;
@@ -846,7 +863,7 @@ static int parse_config(tuple_t *tuple, cistpl_config_t *config)
for (i = 0; i <= rmsz; i++)
config->rmask[i>>2] += p[i] << (8*(i%4));
config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
- return CS_SUCCESS;
+ return 0;
}
/*======================================================================
@@ -1002,10 +1019,12 @@ static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
{
- if (p == q) return NULL;
+ if (p == q)
+ return NULL;
irq->IRQInfo1 = *p; p++;
if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
- if (p+2 > q) return NULL;
+ if (p+2 > q)
+ return NULL;
irq->IRQInfo2 = (p[1]<<8) + p[0];
p += 2;
}
@@ -1026,7 +1045,8 @@ static int parse_cftable_entry(tuple_t *tuple,
if (*p & 0x40)
entry->flags |= CISTPL_CFTABLE_DEFAULT;
if (*p & 0x80) {
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
if (*p & 0x10)
entry->flags |= CISTPL_CFTABLE_BVDS;
if (*p & 0x20)
@@ -1040,30 +1060,35 @@ static int parse_cftable_entry(tuple_t *tuple,
entry->interface = 0;
/* Process optional features */
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
features = *p; p++;
/* Power options */
if ((features & 3) > 0) {
p = parse_power(p, q, &entry->vcc);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vcc.present = 0;
if ((features & 3) > 1) {
p = parse_power(p, q, &entry->vpp1);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vpp1.present = 0;
if ((features & 3) > 2) {
p = parse_power(p, q, &entry->vpp2);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vpp2.present = 0;
/* Timing options */
if (features & 0x04) {
p = parse_timing(p, q, &entry->timing);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else {
entry->timing.wait = 0;
entry->timing.ready = 0;
@@ -1073,14 +1098,16 @@ static int parse_cftable_entry(tuple_t *tuple,
/* I/O window options */
if (features & 0x08) {
p = parse_io(p, q, &entry->io);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->io.nwin = 0;
/* Interrupt options */
if (features & 0x10) {
p = parse_irq(p, q, &entry->irq);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->irq.IRQInfo1 = 0;
@@ -1094,7 +1121,8 @@ static int parse_cftable_entry(tuple_t *tuple,
entry->mem.win[0].card_addr = 0;
entry->mem.win[0].host_addr = 0;
p += 2;
- if (p > q) return CS_BAD_TUPLE;
+ if (p > q)
+ return -EINVAL;
break;
case 0x40:
entry->mem.nwin = 1;
@@ -1102,26 +1130,30 @@ static int parse_cftable_entry(tuple_t *tuple,
entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
entry->mem.win[0].host_addr = 0;
p += 4;
- if (p > q) return CS_BAD_TUPLE;
+ if (p > q)
+ return -EINVAL;
break;
case 0x60:
p = parse_mem(p, q, &entry->mem);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
break;
}
/* Misc features */
if (features & 0x80) {
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
entry->flags |= (*p << 8);
while (*p & 0x80)
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
p++;
}
entry->subtuples = q-p;
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -1132,12 +1164,12 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
{
u_char *p;
if (tuple->TupleDataLen < 6)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = (u_char *)tuple->TupleData;
bar->attr = *p;
p += 2;
bar->size = get_unaligned_le32(p);
- return CS_SUCCESS;
+ return 0;
}
static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
@@ -1146,12 +1178,12 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
p = (u_char *)tuple->TupleData;
if ((*p != 3) || (tuple->TupleDataLen < 6))
- return CS_BAD_TUPLE;
+ return -EINVAL;
config->last_idx = *(++p);
p++;
config->base = get_unaligned_le32(p);
config->subtuples = tuple->TupleDataLen - 6;
- return CS_SUCCESS;
+ return 0;
}
static int parse_cftable_entry_cb(tuple_t *tuple,
@@ -1167,29 +1199,34 @@ static int parse_cftable_entry_cb(tuple_t *tuple,
entry->flags |= CISTPL_CFTABLE_DEFAULT;
/* Process optional features */
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
features = *p; p++;
/* Power options */
if ((features & 3) > 0) {
p = parse_power(p, q, &entry->vcc);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vcc.present = 0;
if ((features & 3) > 1) {
p = parse_power(p, q, &entry->vpp1);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vpp1.present = 0;
if ((features & 3) > 2) {
p = parse_power(p, q, &entry->vpp2);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->vpp2.present = 0;
/* I/O window options */
if (features & 0x08) {
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
entry->io = *p; p++;
} else
entry->io = 0;
@@ -1197,32 +1234,37 @@ static int parse_cftable_entry_cb(tuple_t *tuple,
/* Interrupt options */
if (features & 0x10) {
p = parse_irq(p, q, &entry->irq);
- if (p == NULL) return CS_BAD_TUPLE;
+ if (p == NULL)
+ return -EINVAL;
} else
entry->irq.IRQInfo1 = 0;
if (features & 0x20) {
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
entry->mem = *p; p++;
} else
entry->mem = 0;
/* Misc features */
if (features & 0x80) {
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
entry->flags |= (*p << 8);
if (*p & 0x80) {
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
entry->flags |= (*p << 16);
}
while (*p & 0x80)
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
p++;
}
entry->subtuples = q-p;
- return CS_SUCCESS;
+ return 0;
}
#endif
@@ -1248,7 +1290,7 @@ static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
p += 6;
}
geo->ngeo = n;
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -1258,7 +1300,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
u_char *p, *q;
if (tuple->TupleDataLen < 10)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = tuple->TupleData;
q = p + tuple->TupleDataLen;
@@ -1282,15 +1324,18 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org)
p = tuple->TupleData;
q = p + tuple->TupleDataLen;
- if (p == q) return CS_BAD_TUPLE;
+ if (p == q)
+ return -EINVAL;
org->data_org = *p;
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
for (i = 0; i < 30; i++) {
org->desc[i] = *p;
if (*p == '\0') break;
- if (++p == q) return CS_BAD_TUPLE;
+ if (++p == q)
+ return -EINVAL;
}
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
@@ -1300,7 +1345,7 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
u_char *p;
if (tuple->TupleDataLen < 10)
- return CS_BAD_TUPLE;
+ return -EINVAL;
p = tuple->TupleData;
@@ -1309,17 +1354,17 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
fmt->offset = get_unaligned_le32(p + 2);
fmt->length = get_unaligned_le32(p + 6);
- return CS_SUCCESS;
+ return 0;
}
/*====================================================================*/
-int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse)
+int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
{
- int ret = CS_SUCCESS;
+ int ret = 0;
if (tuple->TupleDataLen > tuple->TupleDataMax)
- return CS_BAD_TUPLE;
+ return -EINVAL;
switch (tuple->TupleCode) {
case CISTPL_DEVICE:
case CISTPL_DEVICE_A:
@@ -1387,15 +1432,17 @@ int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse)
break;
case CISTPL_NO_LINK:
case CISTPL_LINKTARGET:
- ret = CS_SUCCESS;
+ ret = 0;
break;
default:
- ret = CS_UNSUPPORTED_FUNCTION;
+ ret = -EINVAL;
break;
}
+ if (ret)
+ __cs_dbg(0, "parse_tuple failed %d\n", ret);
return ret;
}
-EXPORT_SYMBOL(pccard_parse_tuple);
+EXPORT_SYMBOL(pcmcia_parse_tuple);
/*======================================================================
@@ -1410,18 +1457,22 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
int ret;
buf = kmalloc(256, GFP_KERNEL);
- if (buf == NULL)
- return CS_OUT_OF_RESOURCE;
+ if (buf == NULL) {
+ dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
+ return -ENOMEM;
+ }
tuple.DesiredTuple = code;
tuple.Attributes = TUPLE_RETURN_COMMON;
ret = pccard_get_first_tuple(s, function, &tuple);
- if (ret != CS_SUCCESS) goto done;
+ if (ret != 0)
+ goto done;
tuple.TupleData = buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
ret = pccard_get_tuple_data(s, &tuple);
- if (ret != CS_SUCCESS) goto done;
- ret = pccard_parse_tuple(&tuple, parse);
+ if (ret != 0)
+ goto done;
+ ret = pcmcia_parse_tuple(&tuple, parse);
done:
kfree(buf);
return ret;
@@ -1446,37 +1497,40 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
int ret, reserved, dev_ok = 0, ident_ok = 0;
if (!s)
- return CS_BAD_HANDLE;
+ return -EINVAL;
tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
- if (tuple == NULL)
- return CS_OUT_OF_RESOURCE;
+ if (tuple == NULL) {
+ dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
+ return -ENOMEM;
+ }
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
- kfree(tuple);
- return CS_OUT_OF_RESOURCE;
+ kfree(tuple);
+ dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
+ return -ENOMEM;
}
count = reserved = 0;
tuple->DesiredTuple = RETURN_FIRST_TUPLE;
tuple->Attributes = TUPLE_RETURN_COMMON;
ret = pccard_get_first_tuple(s, function, tuple);
- if (ret != CS_SUCCESS)
+ if (ret != 0)
goto done;
/* First tuple should be DEVICE; we should really have either that
or a CFTABLE_ENTRY of some sort */
if ((tuple->TupleCode == CISTPL_DEVICE) ||
- (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) ||
- (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS))
+ (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == 0) ||
+ (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
dev_ok++;
/* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
tuple, for card identification. Certain old D-Link and Linksys
cards have only a broken VERS_2 tuple; hence the bogus test. */
- if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == CS_SUCCESS) ||
- (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == CS_SUCCESS) ||
- (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS))
+ if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == 0) ||
+ (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == 0) ||
+ (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != -ENOSPC))
ident_ok++;
if (!dev_ok && !ident_ok)
@@ -1484,7 +1538,8 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
for (count = 1; count < MAX_TUPLES; count++) {
ret = pccard_get_next_tuple(s, function, tuple);
- if (ret != CS_SUCCESS) break;
+ if (ret != 0)
+ break;
if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
@@ -1499,6 +1554,6 @@ done:
*info = count;
kfree(tuple);
kfree(p);
- return CS_SUCCESS;
+ return 0;
}
EXPORT_SYMBOL(pccard_validate_cis);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index d1207393fc3..c68c5d33828 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -61,7 +61,7 @@ INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */
/* Access speed for attribute memory windows */
INT_MODULE_PARM(cis_speed, 300); /* ns */
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
module_param(pc_debug, int, 0644);
@@ -247,7 +247,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
wait_for_completion(&socket->thread_done);
if (!socket->thread) {
- printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
+ dev_printk(KERN_WARNING, &socket->dev,
+ "PCMCIA: warning: socket thread did not start\n");
return -EIO;
}
@@ -366,16 +367,16 @@ static int socket_reset(struct pcmcia_socket *skt)
skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
- return CS_NO_CARD;
+ return -ENODEV;
if (status & SS_READY)
- return CS_SUCCESS;
+ return 0;
msleep(unreset_check * 10);
}
cs_err(skt, "time out after reset.\n");
- return CS_GENERAL_FAILURE;
+ return -ETIMEDOUT;
}
/*
@@ -412,7 +413,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
s->ops->get_status(s, &status);
if (status & SS_POWERON) {
- printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
+ dev_printk(KERN_ERR, &s->dev,
+ "*** DANGER *** unable to remove socket power\n");
}
cs_socket_put(s);
@@ -426,14 +428,14 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
- return CS_NO_CARD;
+ return -ENODEV;
msleep(initial_delay * 10);
for (i = 0; i < 100; i++) {
skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
- return CS_NO_CARD;
+ return -ENODEV;
if (!(status & SS_PENDING))
break;
@@ -443,13 +445,13 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
if (status & SS_PENDING) {
cs_err(skt, "voltage interrogation timed out.\n");
- return CS_GENERAL_FAILURE;
+ return -ETIMEDOUT;
}
if (status & SS_CARDBUS) {
if (!(skt->features & SS_CAP_CARDBUS)) {
cs_err(skt, "cardbus cards are not supported.\n");
- return CS_BAD_TYPE;
+ return -EINVAL;
}
skt->state |= SOCKET_CARDBUS;
}
@@ -463,7 +465,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
skt->socket.Vcc = skt->socket.Vpp = 50;
else {
cs_err(skt, "unsupported voltage key.\n");
- return CS_BAD_TYPE;
+ return -EIO;
}
if (skt->power_hook)
@@ -480,7 +482,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
skt->ops->get_status(skt, &status);
if (!(status & SS_POWERON)) {
cs_err(skt, "unable to apply power.\n");
- return CS_BAD_TYPE;
+ return -EIO;
}
status = socket_reset(skt);
@@ -502,15 +504,16 @@ static int socket_insert(struct pcmcia_socket *skt)
cs_dbg(skt, 4, "insert\n");
if (!cs_socket_get(skt))
- return CS_NO_CARD;
+ return -ENODEV;
ret = socket_setup(skt, setup_delay);
- if (ret == CS_SUCCESS) {
+ if (ret == 0) {
skt->state |= SOCKET_PRESENT;
- printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n",
- (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA",
- skt->sock);
+ dev_printk(KERN_NOTICE, &skt->dev,
+ "pccard: %s card inserted into slot %d\n",
+ (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA",
+ skt->sock);
#ifdef CONFIG_CARDBUS
if (skt->state & SOCKET_CARDBUS) {
@@ -531,7 +534,7 @@ static int socket_insert(struct pcmcia_socket *skt)
static int socket_suspend(struct pcmcia_socket *skt)
{
if (skt->state & SOCKET_SUSPEND)
- return CS_IN_USE;
+ return -EBUSY;
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
skt->socket = dead_socket;
@@ -540,7 +543,7 @@ static int socket_suspend(struct pcmcia_socket *skt)
skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND;
- return CS_SUCCESS;
+ return 0;
}
/*
@@ -553,7 +556,7 @@ static int socket_resume(struct pcmcia_socket *skt)
int ret;
if (!(skt->state & SOCKET_SUSPEND))
- return CS_IN_USE;
+ return -EBUSY;
skt->socket = dead_socket;
skt->ops->init(skt);
@@ -565,7 +568,7 @@ static int socket_resume(struct pcmcia_socket *skt)
}
ret = socket_setup(skt, resume_delay);
- if (ret == CS_SUCCESS) {
+ if (ret == 0) {
/*
* FIXME: need a better check here for cardbus cards.
*/
@@ -590,12 +593,13 @@ static int socket_resume(struct pcmcia_socket *skt)
skt->state &= ~SOCKET_SUSPEND;
- return CS_SUCCESS;
+ return 0;
}
static void socket_remove(struct pcmcia_socket *skt)
{
- printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
+ dev_printk(KERN_NOTICE, &skt->dev,
+ "pccard: card ejected from slot %d\n", skt->sock);
socket_shutdown(skt);
}
@@ -641,8 +645,8 @@ static int pccardd(void *__skt)
/* register with the device core */
ret = device_register(&skt->dev);
if (ret) {
- printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
- skt);
+ dev_printk(KERN_WARNING, &skt->dev,
+ "PCMCIA: unable to register socket\n");
skt->thread = NULL;
complete(&skt->thread_done);
return 0;
@@ -748,7 +752,7 @@ EXPORT_SYMBOL(pccard_register_pcmcia);
* CIS register.
*/
-int pccard_reset_card(struct pcmcia_socket *skt)
+int pcmcia_reset_card(struct pcmcia_socket *skt)
{
int ret;
@@ -757,15 +761,15 @@ int pccard_reset_card(struct pcmcia_socket *skt)
mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
- ret = CS_NO_CARD;
+ ret = -ENODEV;
break;
}
if (skt->state & SOCKET_SUSPEND) {
- ret = CS_IN_USE;
+ ret = -EBUSY;
break;
}
if (skt->state & SOCKET_CARDBUS) {
- ret = CS_UNSUPPORTED_FUNCTION;
+ ret = -EPERM;
break;
}
@@ -774,20 +778,20 @@ int pccard_reset_card(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
if (skt->callback)
skt->callback->suspend(skt);
- if (socket_reset(skt) == CS_SUCCESS) {
+ if (socket_reset(skt) == 0) {
send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
if (skt->callback)
skt->callback->resume(skt);
}
}
- ret = CS_SUCCESS;
+ ret = 0;
} while (0);
mutex_unlock(&skt->skt_mutex);
return ret;
} /* reset_card */
-EXPORT_SYMBOL(pccard_reset_card);
+EXPORT_SYMBOL(pcmcia_reset_card);
/* These shut down or wake up a socket. They are sort of user
@@ -802,11 +806,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
- ret = CS_NO_CARD;
+ ret = -ENODEV;
break;
}
if (skt->state & SOCKET_CARDBUS) {
- ret = CS_UNSUPPORTED_FUNCTION;
+ ret = -EPERM;
break;
}
if (skt->callback) {
@@ -832,11 +836,11 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
- ret = CS_NO_CARD;
+ ret = -ENODEV;
break;
}
if (skt->state & SOCKET_CARDBUS) {
- ret = CS_UNSUPPORTED_FUNCTION;
+ ret = -EPERM;
break;
}
ret = socket_resume(skt);
@@ -892,7 +896,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
ret = -EBUSY;
break;
}
- if (socket_insert(skt) == CS_NO_CARD) {
+ if (socket_insert(skt) == -ENODEV) {
ret = -ENODEV;
break;
}
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 63dc1a28bda..79615e6d540 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -1,5 +1,5 @@
/*
- * cs_internal.h
+ * cs_internal.h -- definitions internal to the PCMCIA core modules
*
* 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
@@ -10,6 +10,12 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
+ * (C) 2003 - 2008 Dominik Brodowski
+ *
+ *
+ * This file contains definitions _only_ needed by the PCMCIA core modules.
+ * It must not be included by PCMCIA socket drivers or by PCMCIA device
+ * drivers.
*/
#ifndef _LINUX_CS_INTERNAL_H
@@ -18,29 +24,24 @@
#include <linux/kref.h>
/* Flags in client state */
-#define CLIENT_CONFIG_LOCKED 0x0001
-#define CLIENT_IRQ_REQ 0x0002
-#define CLIENT_IO_REQ 0x0004
-#define CLIENT_UNBOUND 0x0008
-#define CLIENT_STALE 0x0010
#define CLIENT_WIN_REQ(i) (0x1<<(i))
-#define CLIENT_CARDBUS 0x8000
/* Each card function gets one of these guys */
typedef struct config_t {
struct kref ref;
- u_int state;
- u_int Attributes;
- u_int IntType;
- u_int ConfigBase;
- u_char Status, Pin, Copy, Option, ExtStatus;
- u_int CardValues;
- io_req_t io;
- struct {
- u_int Attributes;
- } irq;
+ unsigned int state;
+ unsigned int Attributes;
+ unsigned int IntType;
+ unsigned int ConfigBase;
+ unsigned char Status, Pin, Copy, Option, ExtStatus;
+ unsigned int CardValues;
+ io_req_t io;
+ struct {
+ u_int Attributes;
+ } irq;
} config_t;
+
struct cis_cache_entry {
struct list_head node;
unsigned int addr;
@@ -49,6 +50,30 @@ struct cis_cache_entry {
unsigned char cache[0];
};
+struct pccard_resource_ops {
+ int (*validate_mem) (struct pcmcia_socket *s);
+ int (*adjust_io_region) (struct resource *res,
+ unsigned long r_start,
+ unsigned long r_end,
+ struct pcmcia_socket *s);
+ struct resource* (*find_io) (unsigned long base, int num,
+ unsigned long align,
+ struct pcmcia_socket *s);
+ struct resource* (*find_mem) (unsigned long base, unsigned long num,
+ unsigned long align, int low,
+ struct pcmcia_socket *s);
+ int (*add_io) (struct pcmcia_socket *s,
+ unsigned int action,
+ unsigned long r_start,
+ unsigned long r_end);
+ int (*add_mem) (struct pcmcia_socket *s,
+ unsigned int action,
+ unsigned long r_start,
+ unsigned long r_end);
+ int (*init) (struct pcmcia_socket *s);
+ void (*exit) (struct pcmcia_socket *s);
+};
+
/* Flags in config state */
#define CONFIG_LOCKED 0x01
#define CONFIG_IRQ_REQ 0x02
@@ -59,7 +84,6 @@ struct cis_cache_entry {
#define SOCKET_INUSE 0x0010
#define SOCKET_SUSPEND 0x0080
#define SOCKET_WIN_REQ(i) (0x0100<<(i))
-#define SOCKET_REGION_INFO 0x4000
#define SOCKET_CARDBUS 0x8000
#define SOCKET_CARDBUS_CONFIG 0x10000
@@ -83,69 +107,153 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
}
}
-/* In cardbus.c */
-int cb_alloc(struct pcmcia_socket *s);
-void cb_free(struct pcmcia_socket *s);
-int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr);
+#ifdef CONFIG_PCMCIA_DEBUG
+extern int cs_debug_level(int);
-/* In cistpl.c */
-int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
- u_int addr, u_int len, void *ptr);
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
- u_int addr, u_int len, void *ptr);
-void release_cis_mem(struct pcmcia_socket *s);
-void destroy_cis_cache(struct pcmcia_socket *s);
+#define cs_dbg(skt, lvl, fmt, arg...) do { \
+ if (cs_debug_level(lvl)) \
+ dev_printk(KERN_DEBUG, &skt->dev, \
+ "cs: " fmt, ## arg); \
+} while (0)
+#define __cs_dbg(lvl, fmt, arg...) do { \
+ if (cs_debug_level(lvl)) \
+ printk(KERN_DEBUG \
+ "cs: " fmt, ## arg); \
+} while (0)
+
+#else
+#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0)
+#define __cs_dbg(lvl, fmt, arg...) do { } while (0)
+#endif
+
+#define cs_err(skt, fmt, arg...) \
+ dev_printk(KERN_ERR, &skt->dev, "cs: " fmt, ## arg)
+
+
+/*
+ * Stuff internal to module "pcmcia_core":
+ */
+
+/* cistpl.c */
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 */
-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,
- unsigned long r_end, struct pcmcia_socket *s);
-struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
- int low, struct pcmcia_socket *s);
+/* rsrc_mgr.c */
void release_resource_db(struct pcmcia_socket *s);
-/* In socket_sysfs.c */
+/* socket_sysfs.c */
extern int pccard_sysfs_add_socket(struct device *dev);
extern void pccard_sysfs_remove_socket(struct device *dev);
-/* In cs.c */
-extern struct rw_semaphore pcmcia_socket_list_rwsem;
-extern struct list_head pcmcia_socket_list;
-int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
-int pccard_reset_card(struct pcmcia_socket *skt);
+/* cardbus.c */
+int cb_alloc(struct pcmcia_socket *s);
+void cb_free(struct pcmcia_socket *s);
+int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
+ void *ptr);
+
+/*
+ * Stuff exported by module "pcmcia_core" to module "pcmcia"
+ */
+
struct pcmcia_callback{
struct module *owner;
- int (*event) (struct pcmcia_socket *s, event_t event, int priority);
+ int (*event) (struct pcmcia_socket *s,
+ event_t event, int priority);
void (*requery) (struct pcmcia_socket *s, int new_cis);
int (*suspend) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
};
+/* cs.c */
+extern struct rw_semaphore pcmcia_socket_list_rwsem;
+extern struct list_head pcmcia_socket_list;
+extern struct class pcmcia_socket_class;
+
+int pcmcia_get_window(struct pcmcia_socket *s,
+ window_handle_t *handle,
+ int idx,
+ win_req_t *req);
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr);
-#define cs_socket_name(skt) ((skt)->dev.bus_id)
+int pcmcia_suspend_card(struct pcmcia_socket *skt);
+int pcmcia_resume_card(struct pcmcia_socket *skt);
-#ifdef DEBUG
-extern int cs_debug_level(int);
+int pcmcia_eject_card(struct pcmcia_socket *skt);
+int pcmcia_insert_card(struct pcmcia_socket *skt);
-#define cs_dbg(skt, lvl, fmt, arg...) do { \
- if (cs_debug_level(lvl)) \
- printk(KERN_DEBUG "cs: %s: " fmt, \
- cs_socket_name(skt) , ## arg); \
-} while (0)
+struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
+void pcmcia_put_socket(struct pcmcia_socket *skt);
-#else
-#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0)
-#endif
+/* cistpl.c */
+int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
+ u_int addr, u_int len, void *ptr);
+void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
+ u_int addr, u_int len, void *ptr);
+void release_cis_mem(struct pcmcia_socket *s);
+void destroy_cis_cache(struct pcmcia_socket *s);
+int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
+ cisdata_t code, void *parse);
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+ const u8 *data, const size_t len);
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function,
+ unsigned int *count);
-#define cs_err(skt, fmt, arg...) \
- printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.bus_id , ## arg)
+/* rsrc_mgr.c */
+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,
+ unsigned long r_end,
+ struct pcmcia_socket *s);
+struct resource *pcmcia_find_mem_region(u_long base,
+ u_long num,
+ u_long align,
+ int low,
+ struct pcmcia_socket *s);
+
+/*
+ * Stuff internal to module "pcmcia".
+ */
+/* ds.c */
+extern struct bus_type pcmcia_bus_type;
+
+/* pcmcia_resource.c */
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
+#ifdef CONFIG_PCMCIA_IOCTL
+/* ds.c */
+extern spinlock_t pcmcia_dev_list_lock;
+
+extern struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev);
+extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
+
+struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+ unsigned int function);
+
+/* pcmcia_ioctl.c */
+extern void __init pcmcia_setup_ioctl(void);
+extern void __exit pcmcia_cleanup_ioctl(void);
+extern void handle_event(struct pcmcia_socket *s, event_t event);
+extern int handle_request(struct pcmcia_socket *s, event_t event);
+
+#else /* CONFIG_PCMCIA_IOCTL */
+
+static inline void __init pcmcia_setup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
+static inline void handle_event(struct pcmcia_socket *s, event_t event)
+{
+ return;
+}
+static inline int handle_request(struct pcmcia_socket *s, event_t event)
+{
+ return 0;
+}
+
+#endif /* CONFIG_PCMCIA_IOCTL */
#endif /* _LINUX_CS_INTERNAL_H */
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 4174d9656e3..79566025549 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -32,7 +32,6 @@
#include <pcmcia/ss.h>
#include "cs_internal.h"
-#include "ds_internal.h"
/*====================================================================*/
@@ -42,17 +41,22 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA Driver Services");
MODULE_LICENSE("GPL");
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
int ds_pc_debug;
module_param_named(pc_debug, ds_pc_debug, int, 0644);
#define ds_dbg(lvl, fmt, arg...) do { \
- if (ds_pc_debug > (lvl)) \
+ if (ds_pc_debug > (lvl)) \
printk(KERN_DEBUG "ds: " fmt , ## arg); \
} while (0)
+#define ds_dev_dbg(lvl, dev, fmt, arg...) do { \
+ if (ds_pc_debug > (lvl)) \
+ dev_printk(KERN_DEBUG, dev, "ds: " fmt , ## arg); \
+} while (0)
#else
#define ds_dbg(lvl, fmt, arg...) do { } while (0)
+#define ds_dev_dbg(lvl, dev, fmt, arg...) do { } while (0)
#endif
spinlock_t pcmcia_dev_list_lock;
@@ -64,42 +68,19 @@ spinlock_t pcmcia_dev_list_lock;
/* String tables for error messages */
typedef struct lookup_t {
- int key;
- char *msg;
+ const int key;
+ const char *msg;
} lookup_t;
static const lookup_t error_table[] = {
- { CS_SUCCESS, "Operation succeeded" },
- { CS_BAD_ADAPTER, "Bad adapter" },
- { CS_BAD_ATTRIBUTE, "Bad attribute", },
- { CS_BAD_BASE, "Bad base address" },
- { CS_BAD_EDC, "Bad EDC" },
- { CS_BAD_IRQ, "Bad IRQ" },
- { CS_BAD_OFFSET, "Bad offset" },
- { CS_BAD_PAGE, "Bad page number" },
- { CS_READ_FAILURE, "Read failure" },
- { CS_BAD_SIZE, "Bad size" },
- { CS_BAD_SOCKET, "Bad socket" },
- { CS_BAD_TYPE, "Bad type" },
- { CS_BAD_VCC, "Bad Vcc" },
- { CS_BAD_VPP, "Bad Vpp" },
- { CS_BAD_WINDOW, "Bad window" },
- { CS_WRITE_FAILURE, "Write failure" },
- { CS_NO_CARD, "No card present" },
- { CS_UNSUPPORTED_FUNCTION, "Usupported function" },
- { CS_UNSUPPORTED_MODE, "Unsupported mode" },
- { CS_BAD_SPEED, "Bad speed" },
- { CS_BUSY, "Resource busy" },
- { CS_GENERAL_FAILURE, "General failure" },
- { CS_WRITE_PROTECTED, "Write protected" },
- { CS_BAD_ARG_LENGTH, "Bad argument length" },
- { CS_BAD_ARGS, "Bad arguments" },
- { CS_CONFIGURATION_LOCKED, "Configuration locked" },
- { CS_IN_USE, "Resource in use" },
- { CS_NO_MORE_ITEMS, "No more items" },
- { CS_OUT_OF_RESOURCE, "Out of resource" },
- { CS_BAD_HANDLE, "Bad handle" },
- { CS_BAD_TUPLE, "Bad CIS tuple" }
+ { 0, "Operation succeeded" },
+ { -EIO, "Input/Output error" },
+ { -ENODEV, "No card present" },
+ { -EINVAL, "Bad parameter" },
+ { -EACCES, "Configuration locked" },
+ { -EBUSY, "Resource in use" },
+ { -ENOSPC, "No more items" },
+ { -ENOMEM, "Out of resource" },
};
@@ -155,46 +136,32 @@ static const lookup_t service_table[] = {
{ ReplaceCIS, "ReplaceCIS" }
};
-
-static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
+const char *pcmcia_error_func(int func)
{
int i;
- char *serv;
-
- if (!p_dev)
- printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
for (i = 0; i < ARRAY_SIZE(service_table); i++)
- if (service_table[i].key == err->func)
- break;
- if (i < ARRAY_SIZE(service_table))
- serv = service_table[i].msg;
- else
- serv = "Unknown service number";
+ if (service_table[i].key == func)
+ return service_table[i].msg;
- for (i = 0; i < ARRAY_SIZE(error_table); i++)
- if (error_table[i].key == err->retcode)
- break;
- if (i < ARRAY_SIZE(error_table))
- printk("%s: %s\n", serv, error_table[i].msg);
- else
- printk("%s: Unknown error code %#x\n", serv, err->retcode);
+ return "Unknown service number";
+}
+EXPORT_SYMBOL(pcmcia_error_func);
- return CS_SUCCESS;
-} /* report_error */
+const char *pcmcia_error_ret(int ret)
+{
+ int i;
-/* end of code which was in cs.c before */
+ for (i = 0; i < ARRAY_SIZE(error_table); i++)
+ if (error_table[i].key == ret)
+ return error_table[i].msg;
+
+ return "unknown";
+}
+EXPORT_SYMBOL(pcmcia_error_ret);
/*======================================================================*/
-void cs_error(struct pcmcia_device *p_dev, int func, int ret)
-{
- error_info_t err = { func, ret };
- pcmcia_report_error(p_dev, &err);
-}
-EXPORT_SYMBOL(cs_error);
static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
@@ -391,7 +358,7 @@ static void pcmcia_release_function(struct kref *ref)
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "releasing device\n");
pcmcia_put_socket(p_dev->socket);
kfree(p_dev->devname);
kref_put(&p_dev->function_config->ref, pcmcia_release_function);
@@ -401,7 +368,7 @@ static void pcmcia_release_dev(struct device *dev)
static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)
{
if (!s->pcmcia_state.device_add_pending) {
- ds_dbg(1, "scheduling to add %s secondary"
+ ds_dev_dbg(1, &s->dev, "scheduling to add %s secondary"
" device to %d\n", mfc ? "mfc" : "pfc", s->sock);
s->pcmcia_state.device_add_pending = 1;
s->pcmcia_state.mfc_pfc = mfc;
@@ -427,8 +394,19 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id,
- p_drv->drv.name);
+ /* The PCMCIA code passes the match data in via dev->driver_data
+ * which is an ugly hack. Once the driver probe is called it may
+ * and often will overwrite the match data so we must save it first
+ *
+ * handle pseudo multifunction devices:
+ * there are at most two pseudo multifunction devices.
+ * if we're matching against the first, schedule a
+ * call which will then check whether there are two
+ * pseudo devices, and if not, add the second one.
+ */
+ did = p_dev->dev.driver_data;
+
+ ds_dev_dbg(1, dev, "trying to bind to %s\n", p_drv->drv.name);
if ((!p_drv->probe) || (!p_dev->function_config) ||
(!try_module_get(p_drv->owner))) {
@@ -443,33 +421,27 @@ static int pcmcia_device_probe(struct device * dev)
p_dev->conf.ConfigBase = cis_config.base;
p_dev->conf.Present = cis_config.rmask[0];
} else {
- printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n");
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: could not parse base and rmask0 of CIS\n");
p_dev->conf.ConfigBase = 0;
p_dev->conf.Present = 0;
}
ret = p_drv->probe(p_dev);
if (ret) {
- ds_dbg(1, "binding %s to %s failed with %d\n",
- p_dev->dev.bus_id, p_drv->drv.name, ret);
+ ds_dev_dbg(1, dev, "binding to %s failed with %d\n",
+ p_drv->drv.name, ret);
goto put_module;
}
- /* handle pseudo multifunction devices:
- * there are at most two pseudo multifunction devices.
- * if we're matching against the first, schedule a
- * call which will then check whether there are two
- * pseudo devices, and if not, add the second one.
- */
- did = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0);
- put_module:
+put_module:
if (ret)
module_put(p_drv->owner);
- put_dev:
+put_dev:
if (ret)
put_device(dev);
return (ret);
@@ -485,8 +457,9 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
struct pcmcia_device *tmp;
unsigned long flags;
- ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock,
- leftover ? leftover->devname : "");
+ ds_dev_dbg(2, leftover ? &leftover->dev : &s->dev,
+ "pcmcia_card_remove(%d) %s\n", s->sock,
+ leftover ? leftover->devname : "");
if (!leftover)
s->device_count = 0;
@@ -503,7 +476,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
p_dev->_removed=1;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(2, &p_dev->dev, "unregistering device\n");
device_unregister(&p_dev->dev);
}
@@ -520,7 +493,7 @@ static int pcmcia_device_remove(struct device * dev)
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
- ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "removing device\n");
/* If we're removing the primary module driving a
* pseudo multi-function card, we need to unbind
@@ -543,13 +516,15 @@ static int pcmcia_device_remove(struct device * dev)
/* check for proper unloading */
if (p_dev->_irq || p_dev->_io || p_dev->_locked)
- printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
- p_drv->drv.name);
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: driver %s did not release config properly\n",
+ p_drv->drv.name);
for (i = 0; i < MAX_WIN; i++)
if (p_dev->_win & CLIENT_WIN_REQ(i))
- printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
- p_drv->drv.name);
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: driver %s did not release window properly\n",
+ p_drv->drv.name);
/* references from pcmcia_probe_device */
pcmcia_put_dev(p_dev);
@@ -598,8 +573,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
}
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
CISTPL_DEVICE_GEO, devgeo)) {
- ds_dbg(0, "mem device geometry probably means "
- "FUNCID_MEMORY\n");
+ ds_dev_dbg(0, &p_dev->dev,
+ "mem device geometry probably means "
+ "FUNCID_MEMORY\n");
p_dev->func_id = CISTPL_FUNCID_MEMORY;
p_dev->has_func_id = 1;
}
@@ -680,7 +656,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (!p_dev->devname)
goto err_free;
sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
- ds_dbg(3, "devname is %s\n", p_dev->devname);
+ ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
@@ -701,7 +677,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
if (!p_dev->function_config) {
- ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(3, &p_dev->dev, "creating config_t\n");
p_dev->function_config = kzalloc(sizeof(struct config_t),
GFP_KERNEL);
if (!p_dev->function_config)
@@ -709,8 +685,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
kref_init(&p_dev->function_config->ref);
}
- printk(KERN_NOTICE "pcmcia: registering new device %s\n",
- p_dev->devname);
+ dev_printk(KERN_NOTICE, &p_dev->dev,
+ "pcmcia: registering new device %s\n",
+ p_dev->devname);
pcmcia_device_query(p_dev);
@@ -745,19 +722,20 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
int ret = 0;
if (!(s->resource_setup_done)) {
- ds_dbg(3, "no resources available, delaying card_add\n");
+ ds_dev_dbg(3, &s->dev,
+ "no resources available, delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
if (pcmcia_validate_mem(s)) {
- ds_dbg(3, "validating mem resources failed, "
+ ds_dev_dbg(3, &s->dev, "validating mem resources failed, "
"delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
if (ret || !no_chains) {
- ds_dbg(0, "invalid CIS or invalid resources\n");
+ ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
return -ENODEV;
}
@@ -778,7 +756,7 @@ static void pcmcia_delayed_add_device(struct work_struct *work)
{
struct pcmcia_socket *s =
container_of(work, struct pcmcia_socket, device_add);
- ds_dbg(1, "adding additional device to %d\n", s->sock);
+ ds_dev_dbg(1, &s->dev, "adding additional device to %d\n", s->sock);
pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
s->pcmcia_state.device_add_pending = 0;
s->pcmcia_state.mfc_pfc = 0;
@@ -788,8 +766,7 @@ static int pcmcia_requery(struct device *dev, void * _data)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (!p_dev->dev.driver) {
- ds_dbg(1, "update device information for %s\n",
- p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "update device information\n");
pcmcia_device_query(p_dev);
}
@@ -803,7 +780,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis)
unsigned long flags;
/* must be called with skt_mutex held */
- ds_dbg(0, "re-scanning socket %d\n", skt->sock);
+ ds_dev_dbg(0, &skt->dev, "re-scanning socket %d\n", skt->sock);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&skt->devices_list))
@@ -854,17 +831,17 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
int ret = -ENOMEM;
int no_funcs;
int old_funcs;
- cisdump_t *cis;
cistpl_longlink_mfc_t mfc;
if (!filename)
return -EINVAL;
- ds_dbg(1, "trying to load CIS file %s\n", filename);
+ ds_dev_dbg(1, &dev->dev, "trying to load CIS file %s\n", filename);
if (strlen(filename) > (FIRMWARE_NAME_MAX - 1)) {
- printk(KERN_WARNING "pcmcia: CIS filename is too long [%s]\n",
- filename);
+ dev_printk(KERN_WARNING, &dev->dev,
+ "pcmcia: CIS filename is too long [%s]\n",
+ filename);
return -EINVAL;
}
@@ -873,23 +850,16 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
if (request_firmware(&fw, path, &dev->dev) == 0) {
if (fw->size >= CISTPL_MAX_CIS_SIZE) {
ret = -EINVAL;
- printk(KERN_ERR "pcmcia: CIS override is too big\n");
+ dev_printk(KERN_ERR, &dev->dev,
+ "pcmcia: CIS override is too big\n");
goto release;
}
- cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
- if (!cis) {
- ret = -ENOMEM;
- goto release;
- }
-
- cis->Length = fw->size + 1;
- memcpy(cis->Data, fw->data, fw->size);
-
- if (!pcmcia_replace_cis(s, cis))
+ if (!pcmcia_replace_cis(s, fw->data, fw->size))
ret = 0;
else {
- printk(KERN_ERR "pcmcia: CIS override failed\n");
+ dev_printk(KERN_ERR, &dev->dev,
+ "pcmcia: CIS override failed\n");
goto release;
}
@@ -993,14 +963,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
* after it has re-checked that there is no possible module
* with a prod_id/manf_id/card_id match.
*/
- ds_dbg(0, "skipping FUNC_ID match for %s until userspace "
- "interaction\n", dev->dev.bus_id);
+ ds_dev_dbg(0, &dev->dev,
+ "skipping FUNC_ID match until userspace interaction\n");
if (!dev->allow_func_id_match)
return 0;
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
- ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id);
+ ds_dev_dbg(0, &dev->dev, "device needs a fake CIS\n");
if (!dev->socket->fake_cis)
pcmcia_load_firmware(dev, did->cisfile);
@@ -1032,11 +1002,9 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
/* match dynamic devices first */
spin_lock(&p_drv->dynids.lock);
list_for_each_entry(dynid, &p_drv->dynids.list, node) {
- ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, &dynid->id)) {
- ds_dbg(0, "matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
spin_unlock(&p_drv->dynids.lock);
return 1;
}
@@ -1046,18 +1014,15 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if (p_dev->cardmgr == p_drv) {
- ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "cardmgr matched to %s\n", drv->name);
return 1;
}
#endif
while (did && did->match_flags) {
- ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, did)) {
- ds_dbg(0, "matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
return 1;
}
did++;
@@ -1263,7 +1228,7 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
if (p_dev->suspended)
return 0;
- ds_dbg(2, "suspending %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "suspending\n");
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
@@ -1274,15 +1239,16 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
if (p_drv->suspend) {
ret = p_drv->suspend(p_dev);
if (ret) {
- printk(KERN_ERR "pcmcia: device %s (driver %s) did "
- "not want to go to sleep (%d)\n",
- p_dev->devname, p_drv->drv.name, ret);
+ dev_printk(KERN_ERR, dev,
+ "pcmcia: device %s (driver %s) did "
+ "not want to go to sleep (%d)\n",
+ p_dev->devname, p_drv->drv.name, ret);
goto out;
}
}
if (p_dev->device_no == p_dev->func) {
- ds_dbg(2, "releasing configuration for %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "releasing configuration\n");
pcmcia_release_configuration(p_dev);
}
@@ -1302,7 +1268,7 @@ static int pcmcia_dev_resume(struct device * dev)
if (!p_dev->suspended)
return 0;
- ds_dbg(2, "resuming %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "resuming\n");
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
@@ -1311,7 +1277,7 @@ static int pcmcia_dev_resume(struct device * dev)
goto out;
if (p_dev->device_no == p_dev->func) {
- ds_dbg(2, "requesting configuration for %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "requesting configuration\n");
ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
if (ret)
goto out;
@@ -1353,14 +1319,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
static int pcmcia_bus_resume(struct pcmcia_socket *skt)
{
- ds_dbg(2, "resuming socket %d\n", skt->sock);
+ ds_dev_dbg(2, &skt->dev, "resuming socket %d\n", skt->sock);
bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
return 0;
}
static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
- ds_dbg(2, "suspending socket %d\n", skt->sock);
+ ds_dev_dbg(2, &skt->dev, "suspending socket %d\n", skt->sock);
if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
pcmcia_bus_suspend_callback)) {
pcmcia_bus_resume(skt);
@@ -1386,13 +1352,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
struct pcmcia_socket *s = pcmcia_get_socket(skt);
if (!s) {
- printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
- "failed, event 0x%x lost!\n", skt, event);
+ dev_printk(KERN_ERR, &skt->dev,
+ "PCMCIA obtaining reference to socket " \
+ "failed, event 0x%x lost!\n", event);
return -ENODEV;
}
- ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, skt);
+ ds_dev_dbg(1, &skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
+ event, priority, skt);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
@@ -1467,7 +1434,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
socket = pcmcia_get_socket(socket);
if (!socket) {
- printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
+ dev_printk(KERN_ERR, dev,
+ "PCMCIA obtaining reference to socket failed\n");
return -ENODEV;
}
@@ -1487,7 +1455,7 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
if (ret) {
- printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+ dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n");
pcmcia_put_socket(socket);
return (ret);
}
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h
deleted file mode 100644
index 3a2b25e6ed7..00000000000
--- a/drivers/pcmcia/ds_internal.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* ds_internal.h - internal header for 16-bit PCMCIA devices management */
-
-extern spinlock_t pcmcia_dev_list_lock;
-extern struct bus_type pcmcia_bus_type;
-
-extern struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev);
-extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
-
-struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
-
-extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-
-#ifdef CONFIG_PCMCIA_IOCTL
-extern void __init pcmcia_setup_ioctl(void);
-extern void __exit pcmcia_cleanup_ioctl(void);
-extern void handle_event(struct pcmcia_socket *s, event_t event);
-extern int handle_request(struct pcmcia_socket *s, event_t event);
-#else
-static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
-static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
-static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
-#endif
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index fb2bc1fb015..117dc12ab43 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -46,7 +46,6 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>
-#include "cs_internal.h"
#define MODNAME "hd64465_ss"
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 68f6b2702bc..71653ab8489 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -63,7 +63,7 @@
#include "vg468.h"
#include "ricoh.h"
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static const char version[] =
"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 3616da22715..2ab4f22c21d 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -38,7 +38,7 @@
#include "m32r_cfc.h"
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static int m32r_cfc_debug;
module_param(m32r_cfc_debug, int, 0644);
#define debug(lvl, fmt, arg...) do { \
@@ -505,7 +505,7 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)
pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);
}
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
if(state->flags & SS_IOCARD){
debug(3, ":IOCARD");
}
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 2b42b7155e3..2f108c23dbd 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -45,7 +45,7 @@
#define PCC_DEBUG_DBEX
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static int m32r_pcc_debug;
module_param(m32r_pcc_debug, int, 0644);
#define debug(lvl, fmt, arg...) do { \
@@ -460,7 +460,7 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)
pcc_set(sock,PCCSIGCR,reg);
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
if(state->flags & SS_IOCARD){
debug(3, ":IOCARD");
}
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index ff66604e90d..d1ad0966392 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -64,8 +64,8 @@
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
+#ifdef CONFIG_PCMCIA_DEBUG
+static int pc_debug;
module_param(pc_debug, int, 0);
#define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);
#else
diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
index a234ce1967a..5554015a781 100644
--- a/drivers/pcmcia/o2micro.h
+++ b/drivers/pcmcia/o2micro.h
@@ -140,7 +140,8 @@ static int o2micro_override(struct yenta_socket *socket)
a = config_readb(socket, O2_RESERVED1);
b = config_readb(socket, O2_RESERVED2);
- printk(KERN_INFO "Yenta O2: res at 0x94/0xD4: %02x/%02x\n", a, b);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "O2: res at 0x94/0xD4: %02x/%02x\n", a, b);
switch (socket->dev->device) {
/*
@@ -153,7 +154,9 @@ static int o2micro_override(struct yenta_socket *socket)
case PCI_DEVICE_ID_O2_6812:
case PCI_DEVICE_ID_O2_6832:
case PCI_DEVICE_ID_O2_6836:
- printk(KERN_INFO "Yenta O2: old bridge, disabling read prefetch/write burst\n");
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Yenta O2: old bridge, disabling read "
+ "prefetch/write burst\n");
config_writeb(socket, O2_RESERVED1,
a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
config_writeb(socket, O2_RESERVED2,
@@ -161,7 +164,8 @@ static int o2micro_override(struct yenta_socket *socket)
break;
default:
- printk(KERN_INFO "Yenta O2: enabling read prefetch/write burst\n");
+ dev_printk(KERN_INFO , &socket->dev->dev,
+ "O2: enabling read prefetch/write burst\n");
config_writeb(socket, O2_RESERVED1,
a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
config_writeb(socket, O2_RESERVED2,
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 419f97fc9a6..1703b20cad5 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -38,7 +38,6 @@
#include <pcmcia/ss.h>
#include "cs_internal.h"
-#include "ds_internal.h"
static int major_dev = -1;
@@ -58,7 +57,7 @@ typedef struct user_info_t {
} user_info_t;
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
extern int ds_pc_debug;
#define ds_dbg(lvl, fmt, arg...) do { \
@@ -149,7 +148,7 @@ static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
irq = adj->resource.irq.IRQ;
if ((irq < 0) || (irq > 15))
- return CS_BAD_IRQ;
+ return -EINVAL;
if (adj->Action != REMOVE_MANAGED_RESOURCE)
return 0;
@@ -167,7 +166,7 @@ static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
#else
static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
- return CS_SUCCESS;
+ return 0;
}
#endif
@@ -175,7 +174,7 @@ static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
static int pcmcia_adjust_resource_info(adjust_t *adj)
{
struct pcmcia_socket *s;
- int ret = CS_UNSUPPORTED_FUNCTION;
+ int ret = -ENOSYS;
unsigned long flags;
down_read(&pcmcia_socket_list_rwsem);
@@ -248,7 +247,7 @@ static int pccard_get_status(struct pcmcia_socket *s,
if (s->state & SOCKET_SUSPEND)
status->CardState |= CS_EVENT_PM_SUSPEND;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
c = (p_dev) ? p_dev->function_config : NULL;
@@ -274,7 +273,7 @@ static int pccard_get_status(struct pcmcia_socket *s,
status->CardState |=
(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
}
- return CS_SUCCESS;
+ return 0;
}
status->CardState |=
(val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -284,9 +283,81 @@ static int pccard_get_status(struct pcmcia_socket *s,
(val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
status->CardState |=
(val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
- return CS_SUCCESS;
+ return 0;
} /* pccard_get_status */
+int pccard_get_configuration_info(struct pcmcia_socket *s,
+ struct pcmcia_device *p_dev,
+ config_info_t *config)
+{
+ config_t *c;
+
+ if (!(s->state & SOCKET_PRESENT))
+ return -ENODEV;
+
+
+#ifdef CONFIG_CARDBUS
+ if (s->state & SOCKET_CARDBUS) {
+ memset(config, 0, sizeof(config_info_t));
+ config->Vcc = s->socket.Vcc;
+ config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+ config->Option = s->cb_dev->subordinate->number;
+ if (s->state & SOCKET_CARDBUS_CONFIG) {
+ config->Attributes = CONF_VALID_CLIENT;
+ config->IntType = INT_CARDBUS;
+ config->AssignedIRQ = s->irq.AssignedIRQ;
+ if (config->AssignedIRQ)
+ config->Attributes |= CONF_ENABLE_IRQ;
+ if (s->io[0].res) {
+ config->BasePort1 = s->io[0].res->start;
+ config->NumPorts1 = s->io[0].res->end -
+ config->BasePort1 + 1;
+ }
+ }
+ return 0;
+ }
+#endif
+
+ if (p_dev) {
+ c = p_dev->function_config;
+ config->Function = p_dev->func;
+ } else {
+ c = NULL;
+ config->Function = 0;
+ }
+
+ if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
+ config->Attributes = 0;
+ config->Vcc = s->socket.Vcc;
+ config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+ return 0;
+ }
+
+ config->Attributes = c->Attributes | CONF_VALID_CLIENT;
+ config->Vcc = s->socket.Vcc;
+ config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+ config->IntType = c->IntType;
+ config->ConfigBase = c->ConfigBase;
+ config->Status = c->Status;
+ config->Pin = c->Pin;
+ config->Copy = c->Copy;
+ config->Option = c->Option;
+ config->ExtStatus = c->ExtStatus;
+ config->Present = config->CardValues = c->CardValues;
+ config->IRQAttributes = c->irq.Attributes;
+ config->AssignedIRQ = s->irq.AssignedIRQ;
+ config->BasePort1 = c->io.BasePort1;
+ config->NumPorts1 = c->io.NumPorts1;
+ config->Attributes1 = c->io.Attributes1;
+ config->BasePort2 = c->io.BasePort2;
+ config->NumPorts2 = c->io.NumPorts2;
+ config->Attributes2 = c->io.Attributes2;
+ config->IOAddrLines = c->io.IOAddrLines;
+
+ return 0;
+} /* pccard_get_configuration_info */
+
+
/*======================================================================
These manage a ring buffer of events pending for one user process
@@ -764,7 +835,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
case DS_GET_CONFIGURATION_INFO:
if (buf->config.Function &&
(buf->config.Function >= s->functions))
- ret = CS_BAD_ARGS;
+ ret = -EINVAL;
else {
struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
ret = pccard_get_configuration_info(s, p_dev, &buf->config);
@@ -787,15 +858,15 @@ static int ds_ioctl(struct inode * inode, struct file * file,
break;
case DS_PARSE_TUPLE:
buf->tuple.TupleData = buf->tuple_parse.data;
- ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
+ ret = pcmcia_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
break;
case DS_RESET_CARD:
- ret = pccard_reset_card(s);
+ ret = pcmcia_reset_card(s);
break;
case DS_GET_STATUS:
if (buf->status.Function &&
(buf->status.Function >= s->functions))
- ret = CS_BAD_ARGS;
+ ret = -EINVAL;
else {
struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
ret = pccard_get_status(s, p_dev, &buf->status);
@@ -826,7 +897,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
goto free_out;
}
- ret = CS_BAD_ARGS;
+ ret = -EINVAL;
if (!(buf->conf_reg.Function &&
(buf->conf_reg.Function >= s->functions))) {
@@ -867,7 +938,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
&buf->win_info.map);
break;
case DS_REPLACE_CIS:
- ret = pcmcia_replace_cis(s, &buf->cisdump);
+ ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
break;
case DS_BIND_REQUEST:
if (!capable(CAP_SYS_ADMIN)) {
@@ -889,22 +960,19 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = -EINVAL;
}
- if ((err == 0) && (ret != CS_SUCCESS)) {
+ if ((err == 0) && (ret != 0)) {
ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
switch (ret) {
- case CS_BAD_SOCKET: case CS_NO_CARD:
- err = -ENODEV; break;
- case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
- case CS_BAD_TUPLE:
- err = -EINVAL; break;
- case CS_IN_USE:
- err = -EBUSY; break;
- case CS_OUT_OF_RESOURCE:
+ case -ENODEV:
+ case -EINVAL:
+ case -EBUSY:
+ case -ENOSYS:
+ err = ret;
+ break;
+ case -ENOMEM:
err = -ENOSPC; break;
- case CS_NO_MORE_ITEMS:
+ case -ENOSPC:
err = -ENODATA; break;
- case CS_UNSUPPORTED_FUNCTION:
- err = -ENOSYS; break;
default:
err = -EIO; break;
}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 4884a18cf9e..afea2b2558b 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -29,7 +29,6 @@
#include <pcmcia/ds.h>
#include "cs_internal.h"
-#include "ds_internal.h"
/* Access speed for IO windows */
@@ -44,16 +43,17 @@ static u8 pcmcia_used_irq[NR_IRQS];
#endif
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
extern int ds_pc_debug;
#define ds_dbg(skt, lvl, fmt, arg...) do { \
if (ds_pc_debug >= lvl) \
- printk(KERN_DEBUG "pcmcia_resource: %s: " fmt, \
- cs_socket_name(skt) , ## arg); \
+ dev_printk(KERN_DEBUG, &skt->dev, \
+ "pcmcia_resource: " fmt, \
+ ## arg); \
} while (0)
#else
-#define ds_dbg(lvl, fmt, arg...) do { } while (0)
+#define ds_dbg(skt, lvl, fmt, arg...) do { } while (0)
#endif
@@ -168,13 +168,13 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
u_char val;
if (!p_dev || !p_dev->function_config)
- return CS_NO_CARD;
+ return -EINVAL;
s = p_dev->socket;
c = p_dev->function_config;
if (!(c->state & CONFIG_LOCKED))
- return CS_CONFIGURATION_LOCKED;
+ return -EACCES;
addr = (c->ConfigBase + reg->Offset) >> 1;
@@ -188,93 +188,14 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
pcmcia_write_cis_mem(s, 1, addr, 1, &val);
break;
default:
- return CS_BAD_ARGS;
+ return -EINVAL;
break;
}
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_access_configuration_register */
EXPORT_SYMBOL(pcmcia_access_configuration_register);
-int pccard_get_configuration_info(struct pcmcia_socket *s,
- struct pcmcia_device *p_dev,
- config_info_t *config)
-{
- config_t *c;
-
- if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
-
-
-#ifdef CONFIG_CARDBUS
- if (s->state & SOCKET_CARDBUS) {
- memset(config, 0, sizeof(config_info_t));
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- config->Option = s->cb_dev->subordinate->number;
- if (s->state & SOCKET_CARDBUS_CONFIG) {
- config->Attributes = CONF_VALID_CLIENT;
- config->IntType = INT_CARDBUS;
- config->AssignedIRQ = s->irq.AssignedIRQ;
- if (config->AssignedIRQ)
- config->Attributes |= CONF_ENABLE_IRQ;
- if (s->io[0].res) {
- config->BasePort1 = s->io[0].res->start;
- config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
- }
- }
- return CS_SUCCESS;
- }
-#endif
-
- if (p_dev) {
- c = p_dev->function_config;
- config->Function = p_dev->func;
- } else {
- c = NULL;
- config->Function = 0;
- }
-
- if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
- config->Attributes = 0;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- return CS_SUCCESS;
- }
-
- config->Attributes = c->Attributes | CONF_VALID_CLIENT;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- config->IntType = c->IntType;
- config->ConfigBase = c->ConfigBase;
- config->Status = c->Status;
- config->Pin = c->Pin;
- config->Copy = c->Copy;
- config->Option = c->Option;
- config->ExtStatus = c->ExtStatus;
- config->Present = config->CardValues = c->CardValues;
- config->IRQAttributes = c->irq.Attributes;
- config->AssignedIRQ = s->irq.AssignedIRQ;
- config->BasePort1 = c->io.BasePort1;
- config->NumPorts1 = c->io.NumPorts1;
- config->Attributes1 = c->io.Attributes1;
- config->BasePort2 = c->io.BasePort2;
- config->NumPorts2 = c->io.NumPorts2;
- config->Attributes2 = c->io.Attributes2;
- config->IOAddrLines = c->io.IOAddrLines;
-
- return CS_SUCCESS;
-} /* pccard_get_configuration_info */
-
-int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
- config_info_t *config)
-{
- return pccard_get_configuration_info(p_dev->socket, p_dev,
- config);
-}
-EXPORT_SYMBOL(pcmcia_get_configuration_info);
-
-
/** pcmcia_get_window
*/
int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
@@ -284,12 +205,12 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
int w;
if (!s || !(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
for (w = idx; w < MAX_WIN; w++)
if (s->state & SOCKET_WIN_REQ(w))
break;
if (w == MAX_WIN)
- return CS_NO_MORE_ITEMS;
+ return -EINVAL;
win = &s->win[w];
req->Base = win->ctl.res->start;
req->Size = win->ctl.res->end - win->ctl.res->start + 1;
@@ -304,7 +225,7 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
if (win->ctl.flags & MAP_USE_WAIT)
req->Attributes |= WIN_USE_WAIT;
*handle = win;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_get_window */
EXPORT_SYMBOL(pcmcia_get_window);
@@ -316,10 +237,10 @@ EXPORT_SYMBOL(pcmcia_get_window);
int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
{
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
+ return -EINVAL;
req->Page = 0;
req->CardOffset = win->ctl.card_start;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_get_mem_page */
EXPORT_SYMBOL(pcmcia_get_mem_page);
@@ -328,14 +249,18 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
{
struct pcmcia_socket *s;
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
- if (req->Page != 0)
- return CS_BAD_PAGE;
+ return -EINVAL;
s = win->sock;
+ if (req->Page != 0) {
+ ds_dbg(s, 0, "failure: requested page is zero\n");
+ return -EINVAL;
+ }
win->ctl.card_start = req->CardOffset;
- if (s->ops->set_mem_map(s, &win->ctl) != 0)
- return CS_BAD_OFFSET;
- return CS_SUCCESS;
+ if (s->ops->set_mem_map(s, &win->ctl) != 0) {
+ ds_dbg(s, 0, "failed to set_mem_map\n");
+ return -EIO;
+ }
+ return 0;
} /* pcmcia_map_mem_page */
EXPORT_SYMBOL(pcmcia_map_mem_page);
@@ -354,9 +279,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
c = p_dev->function_config;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
if (!(c->state & CONFIG_LOCKED))
- return CS_CONFIGURATION_LOCKED;
+ return -EACCES;
if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
if (mod->Attributes & CONF_ENABLE_IRQ) {
@@ -369,20 +294,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
s->ops->set_socket(s, &s->socket);
}
- if (mod->Attributes & CONF_VCC_CHANGE_VALID)
- return CS_BAD_VCC;
+ if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
+ ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+ return -EINVAL;
+ }
/* We only allow changing Vpp1 and Vpp2 to the same value */
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
if (mod->Vpp1 != mod->Vpp2)
- return CS_BAD_VPP;
+ ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
+ return -EINVAL;
s->socket.Vpp = mod->Vpp1;
- if (s->ops->set_socket(s, &s->socket))
- return CS_BAD_VPP;
+ if (s->ops->set_socket(s, &s->socket)) {
+ dev_printk(KERN_WARNING, &s->dev,
+ "Unable to set VPP\n");
+ return -EIO;
+ }
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
- (mod->Attributes & CONF_VPP2_CHANGE_VALID))
- return CS_BAD_VPP;
+ (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
+ ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+ return -EINVAL;
+ }
if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
pccard_io_map io_off = { 0, 0, 0, 0, 1 };
@@ -406,7 +339,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
}
}
- return CS_SUCCESS;
+ return 0;
} /* modify_configuration */
EXPORT_SYMBOL(pcmcia_modify_configuration);
@@ -441,7 +374,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
}
}
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_release_configuration */
@@ -459,7 +392,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
config_t *c = p_dev->function_config;
if (!p_dev->_io )
- return CS_BAD_HANDLE;
+ return -EINVAL;
p_dev->_io = 0;
@@ -467,7 +400,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
(c->io.NumPorts1 != req->NumPorts1) ||
(c->io.BasePort2 != req->BasePort2) ||
(c->io.NumPorts2 != req->NumPorts2))
- return CS_BAD_ARGS;
+ return -EINVAL;
c->state &= ~CONFIG_IO_REQ;
@@ -475,7 +408,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
if (req->NumPorts2)
release_io_space(s, req->BasePort2, req->NumPorts2);
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_release_io */
@@ -485,15 +418,19 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
config_t *c= p_dev->function_config;
if (!p_dev->_irq)
- return CS_BAD_HANDLE;
+ return -EINVAL;
p_dev->_irq = 0;
if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if (c->irq.Attributes != req->Attributes)
- return CS_BAD_ATTRIBUTE;
- if (s->irq.AssignedIRQ != req->AssignedIRQ)
- return CS_BAD_IRQ;
+ return -EACCES;
+ if (c->irq.Attributes != req->Attributes) {
+ ds_dbg(s, 0, "IRQ attributes must match assigned ones\n");
+ return -EINVAL;
+ }
+ if (s->irq.AssignedIRQ != req->AssignedIRQ) {
+ ds_dbg(s, 0, "IRQ must match assigned one\n");
+ return -EINVAL;
+ }
if (--s->irq.Config == 0) {
c->state &= ~CONFIG_IRQ_REQ;
s->irq.AssignedIRQ = 0;
@@ -507,7 +444,7 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
pcmcia_used_irq[req->AssignedIRQ]--;
#endif
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_release_irq */
@@ -516,10 +453,10 @@ int pcmcia_release_window(window_handle_t win)
struct pcmcia_socket *s;
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
+ return -EINVAL;
s = win->sock;
if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
- return CS_BAD_HANDLE;
+ return -EINVAL;
/* Shut down memory window */
win->ctl.flags &= ~MAP_ACTIVE;
@@ -536,7 +473,7 @@ int pcmcia_release_window(window_handle_t win)
win->magic = 0;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_release_window */
EXPORT_SYMBOL(pcmcia_release_window);
@@ -551,18 +488,23 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
pccard_io_map iomap;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;;
- if (req->IntType & INT_CARDBUS)
- return CS_UNSUPPORTED_MODE;
+ if (req->IntType & INT_CARDBUS) {
+ ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n");
+ return -EINVAL;
+ }
c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
+ return -EACCES;
/* Do power control. We don't allow changes in Vcc. */
s->socket.Vpp = req->Vpp;
- if (s->ops->set_socket(s, &s->socket))
- return CS_BAD_VPP;
+ if (s->ops->set_socket(s, &s->socket)) {
+ dev_printk(KERN_WARNING, &s->dev,
+ "Unable to set socket state\n");
+ return -EINVAL;
+ }
/* Pick memory or I/O card, DMA mode, interrupt */
c->IntType = req->IntType;
@@ -651,7 +593,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
c->state |= CONFIG_LOCKED;
p_dev->_locked = 1;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_request_configuration */
EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -667,37 +609,48 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
config_t *c;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
if (!req)
- return CS_UNSUPPORTED_MODE;
+ return -EINVAL;
c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if (c->state & CONFIG_IO_REQ)
- return CS_IN_USE;
- if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
- return CS_BAD_ATTRIBUTE;
+ return -EACCES;
+ if (c->state & CONFIG_IO_REQ) {
+ ds_dbg(s, 0, "IO already configured\n");
+ return -EBUSY;
+ }
+ if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
+ ds_dbg(s, 0, "bad attribute setting for IO region 1\n");
+ return -EINVAL;
+ }
if ((req->NumPorts2 > 0) &&
- (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
- return CS_BAD_ATTRIBUTE;
+ (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
+ ds_dbg(s, 0, "bad attribute setting for IO region 2\n");
+ return -EINVAL;
+ }
+ ds_dbg(s, 1, "trying to allocate resource 1\n");
if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
- req->NumPorts1, req->IOAddrLines))
- return CS_IN_USE;
+ req->NumPorts1, req->IOAddrLines)) {
+ ds_dbg(s, 0, "allocation of resource 1 failed\n");
+ return -EBUSY;
+ }
if (req->NumPorts2) {
+ ds_dbg(s, 1, "trying to allocate resource 2\n");
if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
req->NumPorts2, req->IOAddrLines)) {
+ ds_dbg(s, 0, "allocation of resource 2 failed\n");
release_io_space(s, req->BasePort1, req->NumPorts1);
- return CS_IN_USE;
+ return -EBUSY;
}
}
c->io = *req;
c->state |= CONFIG_IO_REQ;
p_dev->_io = 1;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_request_io */
EXPORT_SYMBOL(pcmcia_request_io);
@@ -723,16 +676,18 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
{
struct pcmcia_socket *s = p_dev->socket;
config_t *c;
- int ret = CS_IN_USE, irq = 0;
+ int ret = -EINVAL, irq = 0;
int type;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
+ return -ENODEV;
c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if (c->state & CONFIG_IRQ_REQ)
- return CS_IN_USE;
+ return -EACCES;
+ if (c->state & CONFIG_IRQ_REQ) {
+ ds_dbg(s, 0, "IRQ already configured\n");
+ return -EBUSY;
+ }
/* Decide what type of interrupt we are registering */
type = 0;
@@ -795,15 +750,19 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
}
if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
- if (request_irq(irq, req->Handler, type, p_dev->devname, req->Instance))
- return CS_IN_USE;
+ ret = request_irq(irq, req->Handler, type,
+ p_dev->devname, req->Instance);
+ if (ret)
+ return ret;
}
/* Make sure the fact the request type was overridden is passed back */
if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
- printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n");
- printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n");
+ dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
+ "request for exclusive IRQ could not be fulfilled.\n");
+ dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
+ "needs updating to supported shared IRQ lines.\n");
}
c->irq.Attributes = req->Attributes;
s->irq.AssignedIRQ = req->AssignedIRQ = irq;
@@ -816,7 +775,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
pcmcia_used_irq[irq]++;
#endif
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_request_irq */
EXPORT_SYMBOL(pcmcia_request_irq);
@@ -834,9 +793,11 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
int w;
if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
- if (req->Attributes & (WIN_PAGED | WIN_SHARED))
- return CS_BAD_ATTRIBUTE;
+ return -ENODEV;
+ if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
+ ds_dbg(s, 0, "bad attribute setting for iomem region\n");
+ return -EINVAL;
+ }
/* Window size defaults to smallest available */
if (req->Size == 0)
@@ -844,19 +805,25 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
align = (((s->features & SS_CAP_MEM_ALIGN) ||
(req->Attributes & WIN_STRICT_ALIGN)) ?
req->Size : s->map_size);
- if (req->Size & (s->map_size-1))
- return CS_BAD_SIZE;
+ if (req->Size & (s->map_size-1)) {
+ ds_dbg(s, 0, "invalid map size\n");
+ return -EINVAL;
+ }
if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
- (req->Base & (align-1)))
- return CS_BAD_BASE;
+ (req->Base & (align-1))) {
+ ds_dbg(s, 0, "invalid base address\n");
+ return -EINVAL;
+ }
if (req->Base)
align = 0;
/* Allocate system memory window */
for (w = 0; w < MAX_WIN; w++)
if (!(s->state & SOCKET_WIN_REQ(w))) break;
- if (w == MAX_WIN)
- return CS_OUT_OF_RESOURCE;
+ if (w == MAX_WIN) {
+ ds_dbg(s, 0, "all windows are used already\n");
+ return -EINVAL;
+ }
win = &s->win[w];
win->magic = WINDOW_MAGIC;
@@ -867,8 +834,10 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
if (!(s->features & SS_CAP_STATIC_MAP)) {
win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align,
(req->Attributes & WIN_MAP_BELOW_1MB), s);
- if (!win->ctl.res)
- return CS_IN_USE;
+ if (!win->ctl.res) {
+ ds_dbg(s, 0, "allocating mem region failed\n");
+ return -EINVAL;
+ }
}
(*p_dev)->_win |= CLIENT_WIN_REQ(w);
@@ -885,8 +854,10 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
win->ctl.card_start = 0;
- if (s->ops->set_mem_map(s, &win->ctl) != 0)
- return CS_BAD_ARGS;
+ if (s->ops->set_mem_map(s, &win->ctl) != 0) {
+ ds_dbg(s, 0, "failed to set memory mapping\n");
+ return -EIO;
+ }
s->state |= SOCKET_WIN_REQ(w);
/* Return window handle */
@@ -897,7 +868,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
}
*wh = win;
- return CS_SUCCESS;
+ return 0;
} /* pcmcia_request_window */
EXPORT_SYMBOL(pcmcia_request_window);
@@ -909,3 +880,79 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
pcmcia_release_window(p_dev->win);
}
EXPORT_SYMBOL(pcmcia_disable_device);
+
+
+struct pcmcia_cfg_mem {
+ tuple_t tuple;
+ cisparse_t parse;
+ u8 buf[256];
+ cistpl_cftable_entry_t dflt;
+};
+
+/**
+ * pcmcia_loop_config() - loop over configuration options
+ * @p_dev: the struct pcmcia_device which we need to loop for.
+ * @conf_check: function to call for each configuration option.
+ * It gets passed the struct pcmcia_device, the CIS data
+ * describing the configuration option, and private data
+ * being passed to pcmcia_loop_config()
+ * @priv_data: private data to be passed to the conf_check function.
+ *
+ * pcmcia_loop_config() loops over all configuration options, and calls
+ * the driver-specific conf_check() for each one, checking whether
+ * it is a valid one.
+ */
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+ int (*conf_check) (struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data),
+ void *priv_data)
+{
+ struct pcmcia_cfg_mem *cfg_mem;
+
+ tuple_t *tuple;
+ int ret = -ENODEV;
+ unsigned int vcc;
+
+ cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
+ if (cfg_mem == NULL)
+ return -ENOMEM;
+
+ /* get the current Vcc setting */
+ vcc = p_dev->socket->socket.Vcc;
+
+ tuple = &cfg_mem->tuple;
+ tuple->TupleData = cfg_mem->buf;
+ tuple->TupleDataMax = 255;
+ tuple->TupleOffset = 0;
+ tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ tuple->Attributes = 0;
+
+ ret = pcmcia_get_first_tuple(p_dev, tuple);
+ while (!ret) {
+ cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
+
+ if (pcmcia_get_tuple_data(p_dev, tuple))
+ goto next_entry;
+
+ if (pcmcia_parse_tuple(tuple, &cfg_mem->parse))
+ goto next_entry;
+
+ /* default values */
+ p_dev->conf.ConfigIndex = cfg->index;
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ cfg_mem->dflt = *cfg;
+
+ ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
+ if (!ret)
+ break;
+
+next_entry:
+ ret = pcmcia_get_next_tuple(p_dev, tuple);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(pcmcia_loop_config);
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 1b07af5a2ed..bb9ddb9532e 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -30,12 +30,12 @@
#include <asm/system.h>
#include <mach/pxa-regs.h>
#include <mach/pxa2xx-regs.h>
+#include <asm/mach-types.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
#include "soc_common.h"
#include "pxa2xx_base.h"
@@ -166,18 +166,32 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
}
#endif
+static void pxa2xx_configure_sockets(struct device *dev)
+{
+ struct pcmcia_low_level *ops = dev->platform_data;
+
+ /*
+ * We have at least one socket, so set MECR:CIT
+ * (Card Is There)
+ */
+ MECR |= MECR_CIT;
+
+ /* Set MECR:NOS (Number Of Sockets) */
+ if (ops->nr > 1 || machine_is_viper())
+ MECR |= MECR_NOS;
+ else
+ MECR &= ~MECR_NOS;
+}
+
int __pxa2xx_drv_pcmcia_probe(struct device *dev)
{
int ret;
struct pcmcia_low_level *ops;
- int first, nr;
if (!dev || !dev->platform_data)
return -ENODEV;
ops = (struct pcmcia_low_level *)dev->platform_data;
- first = ops->first;
- nr = ops->nr;
/* Provide our PXA2xx specific timing routines. */
ops->set_timing = pxa2xx_pcmcia_set_timing;
@@ -185,21 +199,10 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)
ops->frequency_change = pxa2xx_pcmcia_frequency_change;
#endif
- ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+ ret = soc_common_drv_pcmcia_probe(dev, ops, ops->first, ops->nr);
- if (ret == 0) {
- /*
- * We have at least one socket, so set MECR:CIT
- * (Card Is There)
- */
- MECR |= MECR_CIT;
-
- /* Set MECR:NOS (Number Of Sockets) */
- if (nr > 1)
- MECR |= MECR_NOS;
- else
- MECR &= ~MECR_NOS;
- }
+ if (!ret)
+ pxa2xx_configure_sockets(dev);
return ret;
}
@@ -223,11 +226,7 @@ static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t s
static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev)
{
- struct pcmcia_low_level *ops = dev->dev.platform_data;
- int nr = ops ? ops->nr : 0;
-
- MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
-
+ pxa2xx_configure_sockets(&dev->dev);
return pcmcia_socket_dev_resume(&dev->dev);
}
diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c
new file mode 100644
index 00000000000..7c8bcb47662
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_cm_x255.c
@@ -0,0 +1,154 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa_cm_x255.c
+ *
+ * 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.
+ *
+ * Compulab Ltd., 2003, 2007, 2008
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <mach/pxa-regs.h>
+
+#include "soc_common.h"
+
+#define GPIO_PCMCIA_SKTSEL (54)
+#define GPIO_PCMCIA_S0_CD_VALID (16)
+#define GPIO_PCMCIA_S1_CD_VALID (17)
+#define GPIO_PCMCIA_S0_RDYINT (6)
+#define GPIO_PCMCIA_S1_RDYINT (8)
+#define GPIO_PCMCIA_RESET (9)
+
+#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
+#define PCMCIA_S1_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S1_CD_VALID)
+#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
+#define PCMCIA_S1_RDYINT IRQ_GPIO(GPIO_PCMCIA_S1_RDYINT)
+
+
+static struct pcmcia_irqs irqs[] = {
+ { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
+ { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
+};
+
+static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
+ if (ret)
+ return ret;
+ gpio_direction_output(GPIO_PCMCIA_RESET, 0);
+
+ skt->irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
+ ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ if (!ret)
+ gpio_free(GPIO_PCMCIA_RESET);
+
+ return ret;
+}
+
+static void cmx255_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
+{
+ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ gpio_free(GPIO_PCMCIA_RESET);
+}
+
+
+static void cmx255_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ int cd = skt->nr ? GPIO_PCMCIA_S1_CD_VALID : GPIO_PCMCIA_S0_CD_VALID;
+ int rdy = skt->nr ? GPIO_PCMCIA_S0_RDYINT : GPIO_PCMCIA_S1_RDYINT;
+
+ state->detect = !gpio_get_value(cd);
+ state->ready = !!gpio_get_value(rdy);
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->vs_3v = 0;
+ state->vs_Xv = 0;
+ state->wrprot = 0; /* not available */
+}
+
+
+static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ switch (skt->nr) {
+ case 0:
+ if (state->flags & SS_RESET) {
+ gpio_set_value(GPIO_PCMCIA_SKTSEL, 0);
+ udelay(1);
+ gpio_set_value(GPIO_PCMCIA_RESET, 1);
+ udelay(10);
+ gpio_set_value(GPIO_PCMCIA_RESET, 0);
+ }
+ break;
+ case 1:
+ if (state->flags & SS_RESET) {
+ gpio_set_value(GPIO_PCMCIA_SKTSEL, 1);
+ udelay(1);
+ gpio_set_value(GPIO_PCMCIA_RESET, 1);
+ udelay(10);
+ gpio_set_value(GPIO_PCMCIA_RESET, 0);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void cmx255_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void cmx255_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+
+static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = {
+ .owner = THIS_MODULE,
+ .hw_init = cmx255_pcmcia_hw_init,
+ .hw_shutdown = cmx255_pcmcia_shutdown,
+ .socket_state = cmx255_pcmcia_socket_state,
+ .configure_socket = cmx255_pcmcia_configure_socket,
+ .socket_init = cmx255_pcmcia_socket_init,
+ .socket_suspend = cmx255_pcmcia_socket_suspend,
+ .nr = 1,
+};
+
+static struct platform_device *cmx255_pcmcia_device;
+
+int __init cmx255_pcmcia_init(void)
+{
+ int ret;
+
+ cmx255_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+
+ if (!cmx255_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(cmx255_pcmcia_device, &cmx255_pcmcia_ops,
+ sizeof(cmx255_pcmcia_ops));
+
+ if (ret == 0) {
+ printk(KERN_INFO "Registering cm-x255 PCMCIA interface.\n");
+ ret = platform_device_add(cmx255_pcmcia_device);
+ }
+
+ if (ret)
+ platform_device_put(cmx255_pcmcia_device);
+
+ return ret;
+}
+
+void __exit cmx255_pcmcia_exit(void)
+{
+ platform_device_unregister(cmx255_pcmcia_device);
+}
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index bcff5cfed05..6c3aac37712 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -105,13 +105,10 @@ static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
static struct platform_device *cmx270_pcmcia_device;
-static int __init cmx270_pcmcia_init(void)
+int __init cmx270_pcmcia_init(void)
{
int ret;
- if (!machine_is_armcore())
- return -ENODEV;
-
cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
if (!cmx270_pcmcia_device)
@@ -131,14 +128,7 @@ static int __init cmx270_pcmcia_init(void)
return ret;
}
-static void __exit cmx270_pcmcia_exit(void)
+void __exit cmx270_pcmcia_exit(void)
{
platform_device_unregister(cmx270_pcmcia_device);
}
-
-module_init(cmx270_pcmcia_init);
-module_exit(cmx270_pcmcia_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
-MODULE_DESCRIPTION("CM-x270 PCMCIA driver");
diff --git a/drivers/pcmcia/pxa2xx_cm_x2xx.c b/drivers/pcmcia/pxa2xx_cm_x2xx.c
new file mode 100644
index 00000000000..4f09506ad8d
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_cm_x2xx.c
@@ -0,0 +1,49 @@
+/*
+ * linux/drivers/pcmcia/pxa/pxa_cm_x2xx.c
+ *
+ * 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.
+ *
+ * Compulab Ltd., 2003, 2007, 2008
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/system.h>
+
+int cmx255_pcmcia_init(void);
+int cmx270_pcmcia_init(void);
+void cmx255_pcmcia_exit(void);
+void cmx270_pcmcia_exit(void);
+
+static int __init cmx2xx_pcmcia_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_armcore() && cpu_is_pxa25x())
+ ret = cmx255_pcmcia_init();
+ else if (machine_is_armcore() && cpu_is_pxa27x())
+ ret = cmx270_pcmcia_init();
+
+ return ret;
+}
+
+static void __exit cmx2xx_pcmcia_exit(void)
+{
+ if (machine_is_armcore() && cpu_is_pxa25x())
+ cmx255_pcmcia_exit();
+ else if (machine_is_armcore() && cpu_is_pxa27x())
+ cmx270_pcmcia_exit();
+}
+
+module_init(cmx2xx_pcmcia_init);
+module_exit(cmx2xx_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("CM-x2xx PCMCIA driver");
diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c
new file mode 100644
index 00000000000..1736c67e547
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_palmld.c
@@ -0,0 +1,151 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_palmld.c
+ *
+ * Driver for Palm LifeDrive PCMCIA
+ *
+ * Copyright (C) 2006 Alex Osborne <ato@meshy.org>
+ * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <mach/palmld.h>
+#include "soc_common.h"
+
+static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret;
+
+ ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR");
+ if (ret)
+ goto err1;
+ ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0);
+ if (ret)
+ goto err2;
+
+ ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST");
+ if (ret)
+ goto err2;
+ ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1);
+ if (ret)
+ goto err3;
+
+ ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY");
+ if (ret)
+ goto err3;
+ ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY);
+ if (ret)
+ goto err4;
+
+ skt->irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);
+ return 0;
+
+err4:
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
+err3:
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
+err2:
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
+err1:
+ return ret;
+}
+
+static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
+ gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
+}
+
+static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->detect = 1; /* always inserted */
+ state->ready = !!gpio_get_value(GPIO_NR_PALMLD_PCMCIA_READY);
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->wrprot = 0;
+ state->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ gpio_set_value(GPIO_NR_PALMLD_PCMCIA_POWER, 1);
+ gpio_set_value(GPIO_NR_PALMLD_PCMCIA_RESET,
+ !!(state->flags & SS_RESET));
+
+ return 0;
+}
+
+static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level palmld_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .first = 0,
+ .nr = 2,
+
+ .hw_init = palmld_pcmcia_hw_init,
+ .hw_shutdown = palmld_pcmcia_hw_shutdown,
+
+ .socket_state = palmld_pcmcia_socket_state,
+ .configure_socket = palmld_pcmcia_configure_socket,
+
+ .socket_init = palmld_pcmcia_socket_init,
+ .socket_suspend = palmld_pcmcia_socket_suspend,
+};
+
+static struct platform_device *palmld_pcmcia_device;
+
+static int __init palmld_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_palmld())
+ return -ENODEV;
+
+ palmld_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!palmld_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(palmld_pcmcia_device, &palmld_pcmcia_ops,
+ sizeof(palmld_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(palmld_pcmcia_device);
+
+ if (ret)
+ platform_device_put(palmld_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit palmld_pcmcia_exit(void)
+{
+ platform_device_unregister(palmld_pcmcia_device);
+}
+
+module_init(palmld_pcmcia_init);
+module_exit(palmld_pcmcia_exit);
+
+MODULE_AUTHOR("Alex Osborne <ato@meshy.org>,"
+ " Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Palm LifeDrive");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
new file mode 100644
index 00000000000..36c7a0b324d
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -0,0 +1,256 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_trizeps4.c
+ *
+ * TRIZEPS PCMCIA specific routines.
+ *
+ * Author: JĂĽrgen Schindele
+ * Created: 20 02, 2006
+ * Copyright: JĂĽrgen Schindele
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
+#include <mach/trizeps4.h>
+
+#include "soc_common.h"
+
+extern void board_pcmcia_power(int power);
+
+static struct pcmcia_irqs irqs[] = {
+ { 0, IRQ_GPIO(GPIO_PCD), "cs0_cd" }
+ /* on other baseboards we can have more inputs */
+};
+
+static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret, i;
+ /* we dont have voltage/card/ready detection
+ * so we dont need interrupts for it
+ */
+ switch (skt->nr) {
+ case 0:
+ if (gpio_request(GPIO_PRDY, "cf_irq") < 0) {
+ pr_err("%s: sock %d unable to request gpio %d\n", __func__,
+ skt->nr, GPIO_PRDY);
+ return -EBUSY;
+ }
+ if (gpio_direction_input(GPIO_PRDY) < 0) {
+ pr_err("%s: sock %d unable to set input gpio %d\n", __func__,
+ skt->nr, GPIO_PRDY);
+ gpio_free(GPIO_PRDY);
+ return -EINVAL;
+ }
+ skt->irq = IRQ_GPIO(GPIO_PRDY);
+ break;
+
+#ifndef CONFIG_MACH_TRIZEPS_CONXS
+ case 1:
+#endif
+ default:
+ break;
+ }
+ /* release the reset of this card */
+ pr_debug("%s: sock %d irq %d\n", __func__, skt->nr, skt->irq);
+
+ /* supplementory irqs for the socket */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ if (irqs[i].sock != skt->nr)
+ continue;
+ if (gpio_request(IRQ_TO_GPIO(irqs[i].irq), irqs[i].str) < 0) {
+ pr_err("%s: sock %d unable to request gpio %d\n",
+ __func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+ ret = -EBUSY;
+ goto error;
+ }
+ if (gpio_direction_input(IRQ_TO_GPIO(irqs[i].irq)) < 0) {
+ pr_err("%s: sock %d unable to set input gpio %d\n",
+ __func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+ return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+error:
+ for (; i >= 0; i--) {
+ gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+ }
+ return (ret);
+}
+
+static void trizeps_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ int i;
+ /* free allocated gpio's */
+ gpio_free(GPIO_PRDY);
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+}
+
+static unsigned long trizeps_pcmcia_status[2];
+
+static void trizeps_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ unsigned short status = 0, change;
+ status = CFSR_readw();
+ change = (status ^ trizeps_pcmcia_status[skt->nr]) &
+ ConXS_CFSR_BVD_MASK;
+ if (change) {
+ trizeps_pcmcia_status[skt->nr] = status;
+ if (status & ConXS_CFSR_BVD1) {
+ /* enable_irq empty */
+ } else {
+ /* disable_irq empty */
+ }
+ }
+
+ switch (skt->nr) {
+ case 0:
+ /* just fill in fix states */
+ state->detect = gpio_get_value(GPIO_PCD) ? 0 : 1;
+ state->ready = gpio_get_value(GPIO_PRDY) ? 1 : 0;
+ state->bvd1 = (status & ConXS_CFSR_BVD1) ? 1 : 0;
+ state->bvd2 = (status & ConXS_CFSR_BVD2) ? 1 : 0;
+ state->vs_3v = (status & ConXS_CFSR_VS1) ? 0 : 1;
+ state->vs_Xv = (status & ConXS_CFSR_VS2) ? 0 : 1;
+ state->wrprot = 0; /* not available */
+ break;
+
+#ifndef CONFIG_MACH_TRIZEPS_CONXS
+ /* on ConXS we only have one slot. Second is inactive */
+ case 1:
+ state->detect = 0;
+ state->ready = 0;
+ state->bvd1 = 0;
+ state->bvd2 = 0;
+ state->vs_3v = 0;
+ state->vs_Xv = 0;
+ state->wrprot = 0;
+ break;
+
+#endif
+ }
+}
+
+static int trizeps_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ int ret = 0;
+ unsigned short power = 0;
+
+ /* we do nothing here just check a bit */
+ switch (state->Vcc) {
+ case 0: power &= 0xfc; break;
+ case 33: power |= ConXS_BCR_S0_VCC_3V3; break;
+ case 50:
+ pr_err("%s(): Vcc 5V not supported in socket\n", __func__);
+ break;
+ default:
+ pr_err("%s(): bad Vcc %u\n", __func__, state->Vcc);
+ ret = -1;
+ }
+
+ switch (state->Vpp) {
+ case 0: power &= 0xf3; break;
+ case 33: power |= ConXS_BCR_S0_VPP_3V3; break;
+ case 120:
+ pr_err("%s(): Vpp 12V not supported in socket\n", __func__);
+ break;
+ default:
+ if (state->Vpp != state->Vcc) {
+ pr_err("%s(): bad Vpp %u\n", __func__, state->Vpp);
+ ret = -1;
+ }
+ }
+
+ switch (skt->nr) {
+ case 0: /* we only have 3.3V */
+ board_pcmcia_power(power);
+ break;
+
+#ifndef CONFIG_MACH_TRIZEPS_CONXS
+ /* on ConXS we only have one slot. Second is inactive */
+ case 1:
+#endif
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void trizeps_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+ /* default is on */
+ board_pcmcia_power(0x9);
+}
+
+static void trizeps_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+ board_pcmcia_power(0x0);
+}
+
+static struct pcmcia_low_level trizeps_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .hw_init = trizeps_pcmcia_hw_init,
+ .hw_shutdown = trizeps_pcmcia_hw_shutdown,
+ .socket_state = trizeps_pcmcia_socket_state,
+ .configure_socket = trizeps_pcmcia_configure_socket,
+ .socket_init = trizeps_pcmcia_socket_init,
+ .socket_suspend = trizeps_pcmcia_socket_suspend,
+#ifdef CONFIG_MACH_TRIZEPS_CONXS
+ .nr = 1,
+#else
+ .nr = 2,
+#endif
+ .first = 0,
+};
+
+static struct platform_device *trizeps_pcmcia_device;
+
+static int __init trizeps_pcmcia_init(void)
+{
+ int ret;
+
+ trizeps_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!trizeps_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(trizeps_pcmcia_device,
+ &trizeps_pcmcia_ops, sizeof(trizeps_pcmcia_ops));
+
+ if (ret == 0)
+ ret = platform_device_add(trizeps_pcmcia_device);
+
+ if (ret)
+ platform_device_put(trizeps_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit trizeps_pcmcia_exit(void)
+{
+ platform_device_unregister(trizeps_pcmcia_device);
+}
+
+fs_initcall(trizeps_pcmcia_init);
+module_exit(trizeps_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Juergen Schindele");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c
new file mode 100644
index 00000000000..dd10481be7b
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_viper.c
@@ -0,0 +1,179 @@
+/*
+ * VIPER PCMCIA support
+ * Copyright 2004 Arcom Control Systems
+ *
+ * Maintained by Marc Zyngier <maz@misterjones.org>
+ * <marc.zyngier@altran.com>
+ *
+ * Based on:
+ * iPAQ h2200 PCMCIA support
+ * Copyright 2004 Koen Kooi <koen@vestingbar.nl>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/irq.h>
+
+#include <mach/pxa-regs.h>
+#include <mach/viper.h>
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+#include "pxa2xx_base.h"
+
+static struct pcmcia_irqs irqs[] = {
+ { 0, gpio_to_irq(VIPER_CF_CD_GPIO), "PCMCIA_CD" }
+};
+
+static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ unsigned long flags;
+
+ skt->irq = gpio_to_irq(VIPER_CF_RDY_GPIO);
+
+ if (gpio_request(VIPER_CF_CD_GPIO, "CF detect"))
+ goto err_request_cd;
+
+ if (gpio_request(VIPER_CF_RDY_GPIO, "CF ready"))
+ goto err_request_rdy;
+
+ if (gpio_request(VIPER_CF_POWER_GPIO, "CF power"))
+ goto err_request_pwr;
+
+ local_irq_save(flags);
+
+ /* GPIO 82 is the CF power enable line. initially off */
+ if (gpio_direction_output(VIPER_CF_POWER_GPIO, 0) ||
+ gpio_direction_input(VIPER_CF_CD_GPIO) ||
+ gpio_direction_input(VIPER_CF_RDY_GPIO)) {
+ local_irq_restore(flags);
+ goto err_dir;
+ }
+
+ local_irq_restore(flags);
+
+ return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+err_dir:
+ gpio_free(VIPER_CF_POWER_GPIO);
+err_request_pwr:
+ gpio_free(VIPER_CF_RDY_GPIO);
+err_request_rdy:
+ gpio_free(VIPER_CF_CD_GPIO);
+err_request_cd:
+ printk(KERN_ERR "viper: Failed to setup PCMCIA GPIOs\n");
+ return -1;
+}
+
+/*
+ * Release all resources.
+ */
+static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ gpio_free(VIPER_CF_POWER_GPIO);
+ gpio_free(VIPER_CF_RDY_GPIO);
+ gpio_free(VIPER_CF_CD_GPIO);
+}
+
+static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->detect = gpio_get_value(VIPER_CF_CD_GPIO) ? 0 : 1;
+ state->ready = gpio_get_value(VIPER_CF_RDY_GPIO) ? 1 : 0;
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->wrprot = 0;
+ state->vs_3v = 1; /* Can only apply 3.3V */
+ state->vs_Xv = 0;
+}
+
+static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ /* Silently ignore Vpp, output enable, speaker enable. */
+ viper_cf_rst(state->flags & SS_RESET);
+
+ /* Apply socket voltage */
+ switch (state->Vcc) {
+ case 0:
+ gpio_set_value(VIPER_CF_POWER_GPIO, 0);
+ break;
+ case 33:
+ gpio_set_value(VIPER_CF_POWER_GPIO, 1);
+ break;
+ default:
+ printk(KERN_ERR "%s: Unsupported Vcc:%d\n",
+ __func__, state->Vcc);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void viper_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level viper_pcmcia_ops __initdata = {
+ .owner = THIS_MODULE,
+ .hw_init = viper_pcmcia_hw_init,
+ .hw_shutdown = viper_pcmcia_hw_shutdown,
+ .socket_state = viper_pcmcia_socket_state,
+ .configure_socket = viper_pcmcia_configure_socket,
+ .socket_init = viper_pcmcia_socket_init,
+ .socket_suspend = viper_pcmcia_socket_suspend,
+ .nr = 1,
+};
+
+static struct platform_device *viper_pcmcia_device;
+
+static int __init viper_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_viper())
+ return -ENODEV;
+
+ viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!viper_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(viper_pcmcia_device,
+ &viper_pcmcia_ops,
+ sizeof(viper_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(viper_pcmcia_device);
+
+ if (ret)
+ platform_device_put(viper_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit viper_pcmcia_exit(void)
+{
+ platform_device_unregister(viper_pcmcia_device);
+}
+
+module_init(viper_pcmcia_init);
+module_exit(viper_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 203e579ebbd..17f4ecf1c0c 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -122,19 +122,22 @@ static void free_region(struct resource *res)
static int add_interval(struct resource_map *map, u_long base, u_long num)
{
- struct resource_map *p, *q;
+ struct resource_map *p, *q;
- for (p = map; ; p = p->next) {
- if ((p != map) && (p->base+p->num-1 >= base))
- return -1;
- if ((p->next == map) || (p->next->base > base+num-1))
- break;
- }
- q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
- if (!q) return CS_OUT_OF_RESOURCE;
- q->base = base; q->num = num;
- q->next = p->next; p->next = q;
- return CS_SUCCESS;
+ for (p = map; ; p = p->next) {
+ if ((p != map) && (p->base+p->num-1 >= base))
+ return -1;
+ if ((p->next == map) || (p->next->base > base+num-1))
+ break;
+ }
+ q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!q) {
+ printk(KERN_WARNING "out of memory to update resources\n");
+ return -ENOMEM;
+ }
+ q->base = base; q->num = num;
+ q->next = p->next; p->next = q;
+ return 0;
}
/*====================================================================*/
@@ -166,7 +169,10 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
} else {
/* Split the block into two pieces */
p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
- if (!p) return CS_OUT_OF_RESOURCE;
+ if (!p) {
+ printk(KERN_WARNING "out of memory to update resources\n");
+ return -ENOMEM;
+ }
p->base = base+num;
p->num = q->base+q->num - p->base;
q->num = base - q->base;
@@ -174,7 +180,7 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
}
}
}
- return CS_SUCCESS;
+ return 0;
}
/*======================================================================
@@ -194,13 +200,14 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
int any;
u_char *b, hole, most;
- printk(KERN_INFO "cs: IO port probe %#x-%#x:",
- base, base+num-1);
+ dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
+ base, base+num-1);
/* First, what does a floating port look like? */
b = kzalloc(256, GFP_KERNEL);
if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+ dev_printk(KERN_ERR, &s->dev,
+ "do_io_probe: unable to kmalloc 256 bytes");
return;
}
for (i = base, most = 0; i < base+num; i += 8) {
@@ -366,8 +373,8 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
struct socket_data *s_data = s->resource_data;
u_long i, j, bad, fail, step;
- printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
- base, base+num-1);
+ dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
+ base, base+num-1);
bad = fail = 0;
step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
/* don't allow too large steps */
@@ -431,8 +438,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
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");
+ dev_printk(KERN_NOTICE, &s->dev,
+ "cs: warning: no high memory space available!\n");
return -ENODEV;
}
@@ -794,10 +801,11 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
if (res->flags & IORESOURCE_IO) {
if (res == &ioport_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge I/O "
- "window: 0x%llx - 0x%llx\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_INFO, &s->cb_dev->dev,
+ "pcmcia: parent PCI bridge I/O "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_IO;
@@ -806,10 +814,11 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
if (res->flags & IORESOURCE_MEM) {
if (res == &iomem_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge Memory "
- "window: 0x%llx - 0x%llx\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_INFO, &s->cb_dev->dev,
+ "pcmcia: parent PCI bridge Memory "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_MEM;
}
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index c48f3f69bda..f49ac666615 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -54,7 +54,7 @@
#include <mach/pxa-regs.h>
#endif
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
module_param(pc_debug, int, 0644);
@@ -748,7 +748,9 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
add_timer(&skt->poll_timer);
- device_create_file(&skt->socket.dev, &dev_attr_status);
+ ret = device_create_file(&skt->socket.dev, &dev_attr_status);
+ if (ret)
+ goto out_err_8;
}
dev_set_drvdata(dev, sinfo);
@@ -758,6 +760,8 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
do {
skt = &sinfo->skt[i];
+ device_remove_file(&skt->socket.dev, &dev_attr_status);
+ out_err_8:
del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 91ef6a0da3a..38c67375f36 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -15,7 +15,6 @@
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
struct device;
@@ -137,7 +136,7 @@ extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_lev
extern int soc_common_drv_pcmcia_remove(struct device *dev);
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
int lvl, const char *fmt, ...);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 006a29e91d8..ff9a3bb3c88 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj,
char *buf, loff_t off, size_t count)
{
struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
- cisdump_t *cis;
int error;
if (off)
return -EINVAL;
- if (count >= 0x200)
+ if (count >= CISTPL_MAX_CIS_SIZE)
return -EINVAL;
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
- if (!cis)
- return -ENOMEM;
-
- cis->Length = count + 1;
- memcpy(cis->Data, buf, count);
-
- error = pcmcia_replace_cis(s, cis);
- kfree(cis);
+ error = pcmcia_replace_cis(s, buf, count);
if (error)
return -EIO;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 5792bd5c54f..2a613e920fd 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -55,7 +55,7 @@
#include <pcmcia/ss.h>
#include "tcic.h"
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
module_param(pc_debug, int, 0644);
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 129db7bd06c..aaa70227bfb 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -339,8 +339,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
- printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
- pci_name(socket->dev), mfunc, devctl);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: mfunc 0x%08x, devctl 0x%02x\n", mfunc, devctl);
/* make sure PCI interrupts are enabled before probing */
ti_init(socket);
@@ -354,8 +354,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
* We're here which means PCI interrupts are _not_ delivered. try to
* find the right setting (all serial or parallel)
*/
- printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: probing PCI interrupt failed, trying to fix\n");
/* for serial PCI make sure MFUNC3 is set to IRQSER */
if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) {
@@ -379,8 +379,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
pci_irq_status = yenta_probe_cb_irq(socket);
if (pci_irq_status == 1) {
- printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts ok\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: all-serial interrupts ok\n");
mfunc_old = mfunc;
goto out;
}
@@ -395,8 +395,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
}
/* serial PCI interrupts not working fall back to parallel */
- printk(KERN_INFO "Yenta TI: socket %s falling back to parallel PCI interrupts\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: falling back to parallel PCI interrupts\n");
devctl &= ~TI113X_DCR_IMODE_MASK;
devctl |= TI113X_DCR_IMODE_SERIAL; /* serial ISA could be right */
config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
@@ -427,8 +427,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
pci_irq_status = yenta_probe_cb_irq(socket);
if (pci_irq_status == 1) {
mfunc_old = mfunc;
- printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: parallel PCI interrupts ok\n");
} else {
/* not working, back to old value */
mfunc = mfunc_old;
@@ -440,8 +440,9 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
out:
if (pci_irq_status < 1) {
socket->cb_irq = 0;
- printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Yenta TI: no PCI interrupts. Fish. "
+ "Please report.\n");
}
}
@@ -513,8 +514,9 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
- printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
- pci_name(socket->dev), mfunc, devctl);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: mfunc 0x%08x, devctl 0x%02x\n",
+ mfunc, devctl);
/* if IRQs are configured as tied, align irq of func1 with func0 */
sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
@@ -533,9 +535,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
* We're here which means PCI interrupts are _not_ delivered. try to
* find the right setting
*/
- printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n",
- pci_name(socket->dev));
-
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: probing PCI interrupt failed, trying to fix\n");
/* if all serial: set INTRTIE, probe again */
if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) {
@@ -544,8 +545,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
if (ti12xx_tie_interrupts(socket, &old_irq)) {
pci_irq_status = yenta_probe_cb_irq(socket);
if (pci_irq_status == 1) {
- printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts, tied ok\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: all-serial interrupts, tied ok\n");
goto out;
}
@@ -582,8 +583,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
pci_irq_status = yenta_probe_cb_irq(socket);
if (pci_irq_status == 1) {
- printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: parallel PCI interrupts ok\n");
goto out;
}
@@ -593,13 +594,13 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
if (pci_irq_status == -1)
goto out;
}
-
+
/* still nothing: set INTRTIE */
if (ti12xx_tie_interrupts(socket, &old_irq)) {
pci_irq_status = yenta_probe_cb_irq(socket);
if (pci_irq_status == 1) {
- printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts, tied ok\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: parallel PCI interrupts, tied ok\n");
goto out;
}
@@ -610,8 +611,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
out:
if (pci_irq_status < 1) {
socket->cb_irq = 0;
- printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n",
- pci_name(socket->dev));
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "TI: no PCI interrupts. Fish. Please report.\n");
}
}
@@ -815,11 +816,13 @@ static int ti12xx_override(struct yenta_socket *socket)
/* make sure that memory burst is active */
val_orig = val = config_readl(socket, TI113X_SYSTEM_CONTROL);
if (disable_clkrun && PCI_FUNC(socket->dev->devfn) == 0) {
- printk(KERN_INFO "Yenta: Disabling CLKRUN feature\n");
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Disabling CLKRUN feature\n");
val |= TI113X_SCR_KEEPCLK;
}
if (!(val & TI122X_SCR_MRBURSTUP)) {
- printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n");
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Enabling burst memory read transactions\n");
val |= TI122X_SCR_MRBURSTUP;
}
if (val_orig != val)
@@ -830,10 +833,12 @@ static int ti12xx_override(struct yenta_socket *socket)
* CSC interrupts to PCI rather than INTVAL.
*/
val = config_readb(socket, TI1250_DIAGNOSTIC);
- printk(KERN_INFO "Yenta: Using %s to route CSC interrupts to PCI\n",
- (val & TI1250_DIAG_PCI_CSC) ? "CSCINT" : "INTVAL");
- printk(KERN_INFO "Yenta: Routing CardBus interrupts to %s\n",
- (val & TI1250_DIAG_PCI_IREQ) ? "PCI" : "ISA");
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Using %s to route CSC interrupts to PCI\n",
+ (val & TI1250_DIAG_PCI_CSC) ? "CSCINT" : "INTVAL");
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Routing CardBus interrupts to %s\n",
+ (val & TI1250_DIAG_PCI_IREQ) ? "PCI" : "ISA");
/* do irqrouting, depending on function */
if (PCI_FUNC(socket->dev->devfn) == 0)
@@ -858,8 +863,9 @@ static int ti1250_override(struct yenta_socket *socket)
diag |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
if (diag != old) {
- printk(KERN_INFO "Yenta: adjusting diagnostic: %02x -> %02x\n",
- old, diag);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "adjusting diagnostic: %02x -> %02x\n",
+ old, diag);
config_writeb(socket, TI1250_DIAGNOSTIC, diag);
}
@@ -924,7 +930,9 @@ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
/* default to clear TLTEnable bit, old behaviour */
test_c9 &= ~ENE_TEST_C9_TLTENABLE;
- printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "EnE: chaning testregister 0xC9, %02x -> %02x\n",
+ old_c9, test_c9);
config_writeb(socket, ENE_TEST_C9, test_c9);
}
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 0ab1fb65cdc..3ecd7c99d8e 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -38,11 +38,7 @@ static int pwr_irqs_off;
module_param(pwr_irqs_off, bool, 0644);
MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
-#if 0
-#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
-#else
-#define debug(x,args...)
-#endif
+#define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args)
/* Don't ask.. */
#define to_cycles(ns) ((ns)/120)
@@ -69,13 +65,13 @@ MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation");
static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
{
u32 val = readl(socket->base + reg);
- debug("%p %04x %08x\n", socket, reg, val);
+ debug("%04x %08x\n", socket, reg, val);
return val;
}
static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
{
- debug("%p %04x %08x\n", socket, reg, val);
+ debug("%04x %08x\n", socket, reg, val);
writel(val, socket->base + reg);
readl(socket->base + reg); /* avoid problems with PCI write posting */
}
@@ -84,7 +80,7 @@ static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
{
u8 val;
pci_read_config_byte(socket->dev, offset, &val);
- debug("%p %04x %02x\n", socket, offset, val);
+ debug("%04x %02x\n", socket, offset, val);
return val;
}
@@ -92,7 +88,7 @@ static inline u16 config_readw(struct yenta_socket *socket, unsigned offset)
{
u16 val;
pci_read_config_word(socket->dev, offset, &val);
- debug("%p %04x %04x\n", socket, offset, val);
+ debug("%04x %04x\n", socket, offset, val);
return val;
}
@@ -100,32 +96,32 @@ static inline u32 config_readl(struct yenta_socket *socket, unsigned offset)
{
u32 val;
pci_read_config_dword(socket->dev, offset, &val);
- debug("%p %04x %08x\n", socket, offset, val);
+ debug("%04x %08x\n", socket, offset, val);
return val;
}
static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
{
- debug("%p %04x %02x\n", socket, offset, val);
+ debug("%04x %02x\n", socket, offset, val);
pci_write_config_byte(socket->dev, offset, val);
}
static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
{
- debug("%p %04x %04x\n", socket, offset, val);
+ debug("%04x %04x\n", socket, offset, val);
pci_write_config_word(socket->dev, offset, val);
}
static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
{
- debug("%p %04x %08x\n", socket, offset, val);
+ debug("%04x %08x\n", socket, offset, val);
pci_write_config_dword(socket->dev, offset, val);
}
static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
{
u8 val = readb(socket->base + 0x800 + reg);
- debug("%p %04x %02x\n", socket, reg, val);
+ debug("%04x %02x\n", socket, reg, val);
return val;
}
@@ -134,20 +130,20 @@ static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg)
u16 val;
val = readb(socket->base + 0x800 + reg);
val |= readb(socket->base + 0x800 + reg + 1) << 8;
- debug("%p %04x %04x\n", socket, reg, val);
+ debug("%04x %04x\n", socket, reg, val);
return val;
}
static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
{
- debug("%p %04x %02x\n", socket, reg, val);
+ debug("%04x %02x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
readb(socket->base + 0x800 + reg); /* PCI write posting... */
}
static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
{
- debug("%p %04x %04x\n", socket, reg, val);
+ debug("%04x %04x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
writeb(val >> 8, socket->base + 0x800 + reg + 1);
@@ -207,7 +203,7 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
if (state & CB_CBCARD) {
- val |= SS_CARDBUS;
+ val |= SS_CARDBUS;
val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
@@ -650,8 +646,10 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
root = pci_find_parent_resource(socket->dev, res);
if (root && (request_resource(root, res) == 0))
return 0;
- printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
- pci_name(socket->dev), nr);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "Preassigned resource %d busy or not available, "
+ "reconfiguring...\n",
+ nr);
}
if (type & IORESOURCE_IO) {
@@ -674,8 +672,9 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
return 1;
}
- printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
- pci_name(socket->dev), type);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "no resource of type %x available, trying to continue...\n",
+ type);
res->start = res->end = res->flags = 0;
return 0;
}
@@ -923,7 +922,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
socket->probe_status = 0;
if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) {
- printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
+ dev_printk(KERN_WARNING, &socket->dev->dev,
+ "request_irq() in yenta_probe_cb_irq() failed!\n");
return -1;
}
@@ -960,8 +960,9 @@ static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_i
else
socket->socket.irq_mask = 0;
- printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
- socket->socket.irq_mask, socket->cb_irq);
+ dev_printk(KERN_INFO, &socket->dev->dev,
+ "ISA IRQ mask 0x%04x, PCI irq %d\n",
+ socket->socket.irq_mask, socket->cb_irq);
}
/*
@@ -1051,8 +1052,9 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
/* Show that the wanted subordinate number is not possible: */
if (cardbus_bridge->subordinate > upper_limit)
- printk(KERN_WARNING "Yenta: Upper limit for fixing this "
- "bridge's parent bridge: #%02x\n", upper_limit);
+ dev_printk(KERN_WARNING, &cardbus_bridge->dev,
+ "Upper limit for fixing this "
+ "bridge's parent bridge: #%02x\n", upper_limit);
/* If we have room to increase the bridge's subordinate number, */
if (bridge_to_fix->subordinate < upper_limit) {
@@ -1061,10 +1063,11 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
unsigned char subordinate_to_assign =
min(cardbus_bridge->subordinate, upper_limit);
- printk(KERN_INFO "Yenta: Raising subordinate bus# of parent "
- "bus (#%02x) from #%02x to #%02x\n",
- bridge_to_fix->number,
- bridge_to_fix->subordinate, subordinate_to_assign);
+ dev_printk(KERN_INFO, &bridge_to_fix->dev,
+ "Raising subordinate bus# of parent "
+ "bus (#%02x) from #%02x to #%02x\n",
+ bridge_to_fix->number,
+ bridge_to_fix->subordinate, subordinate_to_assign);
/* Save the new subordinate in the bus struct of the bridge */
bridge_to_fix->subordinate = subordinate_to_assign;
@@ -1091,8 +1094,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
* Bail out if so.
*/
if (!dev->subordinate) {
- printk(KERN_ERR "Yenta: no bus associated with %s! "
- "(try 'pci=assign-busses')\n", pci_name(dev));
+ dev_printk(KERN_ERR, &dev->dev, "no bus associated! "
+ "(try 'pci=assign-busses')\n");
return -ENODEV;
}
@@ -1127,7 +1130,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
goto disable;
if (!pci_resource_start(dev, 0)) {
- printk(KERN_ERR "No cardbus resource!\n");
+ dev_printk(KERN_ERR, &dev->dev, "No cardbus resource!\n");
ret = -ENODEV;
goto release;
}
@@ -1146,8 +1149,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
* report the subsystem vendor and device for help debugging
* the irq stuff...
*/
- printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n",
- pci_name(dev), dev->subsystem_vendor, dev->subsystem_device);
+ dev_printk(KERN_INFO, &dev->dev, "CardBus bridge found [%04x:%04x]\n",
+ dev->subsystem_vendor, dev->subsystem_device);
yenta_config_init(socket);
@@ -1179,8 +1182,12 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
socket->poll_timer.data = (unsigned long)socket;
socket->poll_timer.expires = jiffies + HZ;
add_timer(&socket->poll_timer);
- printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n"
- KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n");
+ dev_printk(KERN_INFO, &dev->dev,
+ "no PCI IRQ, CardBus support disabled for this "
+ "socket.\n");
+ dev_printk(KERN_INFO, &dev->dev,
+ "check your BIOS CardBus, BIOS IRQ or ACPI "
+ "settings.\n");
} else {
socket->socket.features |= SS_CAP_CARDBUS;
}
@@ -1188,7 +1195,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* Figure out what the dang thing can do for the PCMCIA layer... */
yenta_interrogate(socket);
yenta_get_socket_capabilities(socket, isa_interrupts);
- printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
+ dev_printk(KERN_INFO, &dev->dev,
+ "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
yenta_fixup_parent_bridge(dev->subordinate);
diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile
index 26f5abc9c3f..e83f34f1b5b 100644
--- a/drivers/pnp/Makefile
+++ b/drivers/pnp/Makefile
@@ -2,12 +2,15 @@
# Makefile for the Linux Plug-and-Play Support.
#
-obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o system.o
+obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o
obj-$(CONFIG_PNPACPI) += pnpacpi/
obj-$(CONFIG_PNPBIOS) += pnpbios/
obj-$(CONFIG_ISAPNP) += isapnp/
+# pnp_system_init goes after pnpacpi/pnpbios init
+obj-y += system.o
+
ifeq ($(CONFIG_PNP_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 9fd7bb9b7dc..3b8b9d3cb03 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -4,6 +4,7 @@
*/
extern spinlock_t pnp_lock;
+extern struct device_attribute pnp_interface_attrs[];
void *pnp_alloc(long size);
int pnp_register_protocol(struct pnp_protocol *protocol);
@@ -16,7 +17,6 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
int pnp_add_device(struct pnp_dev *dev);
struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
-int pnp_interface_attach_device(struct pnp_dev *dev);
int pnp_add_card(struct pnp_card *card);
void pnp_remove_card(struct pnp_card *card);
@@ -147,7 +147,7 @@ char *pnp_resource_type_name(struct resource *res);
void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
void pnp_free_resources(struct pnp_dev *dev);
-int pnp_resource_type(struct resource *res);
+unsigned long pnp_resource_type(struct resource *res);
struct pnp_resource {
struct list_head list;
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index a411582bcd7..817fe626e15 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -159,21 +159,13 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
int __pnp_add_device(struct pnp_dev *dev)
{
- int ret;
-
pnp_fixup_device(dev);
dev->status = PNP_READY;
spin_lock(&pnp_lock);
list_add_tail(&dev->global_list, &pnp_global);
list_add_tail(&dev->protocol_list, &dev->protocol->devices);
spin_unlock(&pnp_lock);
-
- ret = device_register(&dev->dev);
- if (ret)
- return ret;
-
- pnp_interface_attach_device(dev);
- return 0;
+ return device_register(&dev->dev);
}
/*
@@ -218,7 +210,6 @@ void __pnp_remove_device(struct pnp_dev *dev)
static int __init pnp_init(void)
{
- printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n");
return bus_register(&pnp_bus_type);
}
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d3f869ee1d9..e3f7e89c4df 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -206,6 +206,7 @@ struct bus_type pnp_bus_type = {
.remove = pnp_device_remove,
.suspend = pnp_bus_suspend,
.resume = pnp_bus_resume,
+ .dev_attrs = pnp_interface_attrs,
};
int pnp_register_driver(struct pnp_driver *drv)
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index a876ecf7028..478a4a739c0 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -243,8 +243,6 @@ static ssize_t pnp_show_options(struct device *dmdev,
return ret;
}
-static DEVICE_ATTR(options, S_IRUGO, pnp_show_options, NULL);
-
static ssize_t pnp_show_current_resources(struct device *dmdev,
struct device_attribute *attr,
char *buf)
@@ -420,9 +418,6 @@ done:
return count;
}
-static DEVICE_ATTR(resources, S_IRUGO | S_IWUSR,
- pnp_show_current_resources, pnp_set_current_resources);
-
static ssize_t pnp_show_current_ids(struct device *dmdev,
struct device_attribute *attr, char *buf)
{
@@ -437,27 +432,11 @@ static ssize_t pnp_show_current_ids(struct device *dmdev,
return (str - buf);
}
-static DEVICE_ATTR(id, S_IRUGO, pnp_show_current_ids, NULL);
-
-int pnp_interface_attach_device(struct pnp_dev *dev)
-{
- int rc = device_create_file(&dev->dev, &dev_attr_options);
-
- if (rc)
- goto err;
- rc = device_create_file(&dev->dev, &dev_attr_resources);
- if (rc)
- goto err_opt;
- rc = device_create_file(&dev->dev, &dev_attr_id);
- if (rc)
- goto err_res;
-
- return 0;
-
-err_res:
- device_remove_file(&dev->dev, &dev_attr_resources);
-err_opt:
- device_remove_file(&dev->dev, &dev_attr_options);
-err:
- return rc;
-}
+struct device_attribute pnp_interface_attrs[] = {
+ __ATTR(resources, S_IRUGO | S_IWUSR,
+ pnp_show_current_resources,
+ pnp_set_current_resources),
+ __ATTR(options, S_IRUGO, pnp_show_options, NULL),
+ __ATTR(id, S_IRUGO, pnp_show_current_ids, NULL),
+ __ATTR_NULL,
+};
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 101a835e875..46455fbab6d 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -1012,7 +1012,7 @@ static int __init isapnp_init(void)
printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
return 0;
}
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
if (check_legacy_ioport(_PIDXR) || check_legacy_ioport(_PNPWRP))
return -EINVAL;
#endif
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index c1b9ea34977..53561d72b4e 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -268,7 +268,7 @@ static int __init pnpacpi_init(void)
return 0;
}
-subsys_initcall(pnpacpi_init);
+fs_initcall(pnpacpi_init);
static int __init pnpacpi_setup(char *str)
{
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index d7e9f2152df..95015cbfd33 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -405,8 +405,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
extended_irq = &res->data.extended_irq;
- if (extended_irq->producer_consumer == ACPI_PRODUCER)
- return AE_OK;
if (extended_irq->interrupt_count == 0)
pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 19a4be1a9a3..2bfe13369df 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -519,7 +519,7 @@ static int __init pnpbios_init(void)
{
int ret;
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
if (check_legacy_ioport(PNPBIOS_BASE))
return -ENODEV;
#endif
@@ -571,13 +571,13 @@ static int __init pnpbios_init(void)
return 0;
}
-subsys_initcall(pnpbios_init);
+fs_initcall(pnpbios_init);
static int __init pnpbios_thread_init(void)
{
struct task_struct *task;
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
if (check_legacy_ioport(PNPBIOS_BASE))
return 0;
#endif
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 0bdf9b8a5e5..c144bd57561 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -245,7 +245,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
*/
for_each_pci_dev(pdev) {
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- unsigned int type;
+ unsigned long type;
type = pci_resource_flags(pdev, i) &
(IORESOURCE_IO | IORESOURCE_MEM);
@@ -338,8 +338,7 @@ void pnp_fixup_device(struct pnp_dev *dev)
if (!compare_pnp_id(dev->id, f->id))
continue;
#ifdef DEBUG
- dev_dbg(&dev->dev, "%s: calling ", f->id);
- print_fn_descriptor_symbol("%s\n", f->quirk_function);
+ dev_dbg(&dev->dev, "%s: calling %pF\n", f->id, f->quirk_function);
#endif
f->quirk_function(dev);
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 4cfe3a1efdf..dbae23acdd5 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -467,14 +467,14 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
#endif
}
-int pnp_resource_type(struct resource *res)
+unsigned long pnp_resource_type(struct resource *res)
{
return res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_IRQ | IORESOURCE_DMA);
}
struct resource *pnp_get_resource(struct pnp_dev *dev,
- unsigned int type, unsigned int num)
+ unsigned long type, unsigned int num)
{
struct pnp_resource *pnp_res;
struct resource *res;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ae095a498db..8e0c2b47803 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -56,11 +56,11 @@ config BATTERY_TOSA
Say Y to enable support for the battery on the Sharp Zaurus
SL-6000 (tosa) models.
-config BATTERY_PALMTX
- tristate "Palm T|X battery"
- depends on MACH_PALMTX
+config BATTERY_WM97XX
+ bool "WM97xx generic battery driver"
+ depends on TOUCHSCREEN_WM97XX=y
help
- Say Y to enable support for the battery in Palm T|X.
+ Say Y to enable support for battery measured by WM97xx aux port.
config BATTERY_BQ27x00
tristate "BQ27200 battery driver"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6cb301b779a..e8f1ecec5d8 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -21,5 +21,5 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
-obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o
+obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 32570af3c5c..5fbca2681ba 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -205,9 +205,9 @@ static int olpc_bat_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
int ret = 0;
- int16_t ec_word;
+ __be16 ec_word;
uint8_t ec_byte;
- uint64_t ser_buf;
+ __be64 ser_buf;
ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
if (ret)
@@ -257,16 +257,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
if (ret)
return ret;
- ec_word = be16_to_cpu(ec_word);
- val->intval = ec_word * 9760L / 32;
+ val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32;
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
if (ret)
return ret;
- ec_word = be16_to_cpu(ec_word);
- val->intval = ec_word * 15625L / 120;
+ val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120;
break;
case POWER_SUPPLY_PROP_CAPACITY:
ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -278,24 +276,22 @@ static int olpc_bat_get_property(struct power_supply *psy,
ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
if (ret)
return ret;
- ec_word = be16_to_cpu(ec_word);
- val->intval = ec_word * 100 / 256;
+
+ val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
break;
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
if (ret)
return ret;
- ec_word = be16_to_cpu(ec_word);
- val->intval = ec_word * 100 / 256;
+ val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
break;
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
if (ret)
return ret;
- ec_word = be16_to_cpu(ec_word);
- val->intval = ec_word * 6250 / 15;
+ val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15;
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
diff --git a/drivers/power/palmtx_battery.c b/drivers/power/palmtx_battery.c
deleted file mode 100644
index 7035bfa41c6..00000000000
--- a/drivers/power/palmtx_battery.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * linux/drivers/power/palmtx_battery.c
- *
- * Battery measurement code for Palm T|X Handheld computer
- *
- * based on tosa_battery.c
- *
- * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/power_supply.h>
-#include <linux/wm97xx.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <mach/palmtx.h>
-
-static DEFINE_MUTEX(bat_lock);
-static struct work_struct bat_work;
-struct mutex work_lock;
-int bat_status = POWER_SUPPLY_STATUS_DISCHARGING;
-
-static unsigned long palmtx_read_bat(struct power_supply *bat_ps)
-{
- return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
- WM97XX_AUX_ID3) * 1000 / 414;
-}
-
-static unsigned long palmtx_read_temp(struct power_supply *bat_ps)
-{
- return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
- WM97XX_AUX_ID2);
-}
-
-static int palmtx_bat_get_property(struct power_supply *bat_ps,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- switch (psp) {
- case POWER_SUPPLY_PROP_STATUS:
- val->intval = bat_status;
- break;
- case POWER_SUPPLY_PROP_TECHNOLOGY:
- val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = palmtx_read_bat(bat_ps);
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
- val->intval = PALMTX_BAT_MAX_VOLTAGE;
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
- val->intval = PALMTX_BAT_MIN_VOLTAGE;
- break;
- case POWER_SUPPLY_PROP_TEMP:
- val->intval = palmtx_read_temp(bat_ps);
- break;
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = 1;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static void palmtx_bat_external_power_changed(struct power_supply *bat_ps)
-{
- schedule_work(&bat_work);
-}
-
-static char *status_text[] = {
- [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown",
- [POWER_SUPPLY_STATUS_CHARGING] = "Charging",
- [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging",
-};
-
-static void palmtx_bat_update(struct power_supply *bat_ps)
-{
- int old_status = bat_status;
-
- mutex_lock(&work_lock);
-
- bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ?
- POWER_SUPPLY_STATUS_CHARGING :
- POWER_SUPPLY_STATUS_DISCHARGING;
-
- if (old_status != bat_status) {
- pr_debug("%s %s -> %s\n", bat_ps->name,
- status_text[old_status],
- status_text[bat_status]);
- power_supply_changed(bat_ps);
- }
-
- mutex_unlock(&work_lock);
-}
-
-static enum power_supply_property palmtx_bat_main_props[] = {
- POWER_SUPPLY_PROP_STATUS,
- POWER_SUPPLY_PROP_TECHNOLOGY,
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_VOLTAGE_MAX,
- POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_PRESENT,
-};
-
-struct power_supply bat_ps = {
- .name = "main-battery",
- .type = POWER_SUPPLY_TYPE_BATTERY,
- .properties = palmtx_bat_main_props,
- .num_properties = ARRAY_SIZE(palmtx_bat_main_props),
- .get_property = palmtx_bat_get_property,
- .external_power_changed = palmtx_bat_external_power_changed,
- .use_for_apm = 1,
-};
-
-static void palmtx_bat_work(struct work_struct *work)
-{
- palmtx_bat_update(&bat_ps);
-}
-
-#ifdef CONFIG_PM
-static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state)
-{
- flush_scheduled_work();
- return 0;
-}
-
-static int palmtx_bat_resume(struct platform_device *dev)
-{
- schedule_work(&bat_work);
- return 0;
-}
-#else
-#define palmtx_bat_suspend NULL
-#define palmtx_bat_resume NULL
-#endif
-
-static int __devinit palmtx_bat_probe(struct platform_device *dev)
-{
- int ret = 0;
-
- if (!machine_is_palmtx())
- return -ENODEV;
-
- mutex_init(&work_lock);
-
- INIT_WORK(&bat_work, palmtx_bat_work);
-
- ret = power_supply_register(&dev->dev, &bat_ps);
- if (!ret)
- schedule_work(&bat_work);
-
- return ret;
-}
-
-static int __devexit palmtx_bat_remove(struct platform_device *dev)
-{
- power_supply_unregister(&bat_ps);
- return 0;
-}
-
-static struct platform_driver palmtx_bat_driver = {
- .driver.name = "wm97xx-battery",
- .driver.owner = THIS_MODULE,
- .probe = palmtx_bat_probe,
- .remove = __devexit_p(palmtx_bat_remove),
- .suspend = palmtx_bat_suspend,
- .resume = palmtx_bat_resume,
-};
-
-static int __init palmtx_bat_init(void)
-{
- return platform_driver_register(&palmtx_bat_driver);
-}
-
-static void __exit palmtx_bat_exit(void)
-{
- platform_driver_unregister(&palmtx_bat_driver);
-}
-
-module_init(palmtx_bat_init);
-module_exit(palmtx_bat_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
-MODULE_DESCRIPTION("Palm T|X battery driver");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index f44f5b608f6..5520040449c 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -115,8 +115,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
{
int rc = 0;
- psy->dev = device_create_drvdata(power_supply_class, parent, 0,
- psy, "%s", psy->name);
+ psy->dev = device_create(power_supply_class, parent, 0, psy,
+ "%s", psy->name);
if (IS_ERR(psy->dev)) {
rc = PTR_ERR(psy->dev);
goto dev_create_failed;
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
new file mode 100644
index 00000000000..8bde92126d3
--- /dev/null
+++ b/drivers/power/wm97xx_battery.c
@@ -0,0 +1,272 @@
+/*
+ * linux/drivers/power/wm97xx_battery.c
+ *
+ * Battery measurement code for WM97xx
+ *
+ * based on tosa_battery.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/wm97xx.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/wm97xx_batt.h>
+
+static DEFINE_MUTEX(bat_lock);
+static struct work_struct bat_work;
+struct mutex work_lock;
+static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
+static struct wm97xx_batt_info *pdata;
+static enum power_supply_property *prop;
+
+static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ pdata->batt_aux) * pdata->batt_mult /
+ pdata->batt_div;
+}
+
+static unsigned long wm97xx_read_temp(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ pdata->temp_aux) * pdata->temp_mult /
+ pdata->temp_div;
+}
+
+static int wm97xx_bat_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = bat_status;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = pdata->batt_tech;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (pdata->batt_aux >= 0)
+ val->intval = wm97xx_read_bat(bat_ps);
+ else
+ return -EINVAL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ if (pdata->temp_aux >= 0)
+ val->intval = wm97xx_read_temp(bat_ps);
+ else
+ return -EINVAL;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ if (pdata->max_voltage >= 0)
+ val->intval = pdata->max_voltage;
+ else
+ return -EINVAL;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ if (pdata->min_voltage >= 0)
+ val->intval = pdata->min_voltage;
+ else
+ return -EINVAL;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps)
+{
+ schedule_work(&bat_work);
+}
+
+static void wm97xx_bat_update(struct power_supply *bat_ps)
+{
+ int old_status = bat_status;
+
+ mutex_lock(&work_lock);
+
+ bat_status = (pdata->charge_gpio >= 0) ?
+ (gpio_get_value(pdata->charge_gpio) ?
+ POWER_SUPPLY_STATUS_DISCHARGING :
+ POWER_SUPPLY_STATUS_CHARGING) :
+ POWER_SUPPLY_STATUS_UNKNOWN;
+
+ if (old_status != bat_status) {
+ pr_debug("%s: %i -> %i\n", bat_ps->name, old_status,
+ bat_status);
+ power_supply_changed(bat_ps);
+ }
+
+ mutex_unlock(&work_lock);
+}
+
+static struct power_supply bat_ps = {
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = wm97xx_bat_get_property,
+ .external_power_changed = wm97xx_bat_external_power_changed,
+ .use_for_apm = 1,
+};
+
+static void wm97xx_bat_work(struct work_struct *work)
+{
+ wm97xx_bat_update(&bat_ps);
+}
+
+#ifdef CONFIG_PM
+static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state)
+{
+ flush_scheduled_work();
+ return 0;
+}
+
+static int wm97xx_bat_resume(struct platform_device *dev)
+{
+ schedule_work(&bat_work);
+ return 0;
+}
+#else
+#define wm97xx_bat_suspend NULL
+#define wm97xx_bat_resume NULL
+#endif
+
+static int __devinit wm97xx_bat_probe(struct platform_device *dev)
+{
+ int ret = 0;
+ int props = 1; /* POWER_SUPPLY_PROP_PRESENT */
+ int i = 0;
+
+ if (dev->id != -1)
+ return -EINVAL;
+
+ mutex_init(&work_lock);
+
+ if (!pdata) {
+ dev_err(&dev->dev, "Please use wm97xx_bat_set_pdata\n");
+ return -EINVAL;
+ }
+
+ if (pdata->charge_gpio >= 0 && gpio_is_valid(pdata->charge_gpio)) {
+ ret = gpio_request(pdata->charge_gpio, "BATT CHRG");
+ if (ret)
+ goto err;
+ ret = gpio_direction_input(pdata->charge_gpio);
+ if (ret)
+ goto err2;
+ props++; /* POWER_SUPPLY_PROP_STATUS */
+ }
+
+ if (pdata->batt_tech >= 0)
+ props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */
+ if (pdata->temp_aux >= 0)
+ props++; /* POWER_SUPPLY_PROP_TEMP */
+ if (pdata->batt_aux >= 0)
+ props++; /* POWER_SUPPLY_PROP_VOLTAGE_NOW */
+ if (pdata->max_voltage >= 0)
+ props++; /* POWER_SUPPLY_PROP_VOLTAGE_MAX */
+ if (pdata->min_voltage >= 0)
+ props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */
+
+ prop = kzalloc(props * sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ goto err2;
+
+ prop[i++] = POWER_SUPPLY_PROP_PRESENT;
+ if (pdata->charge_gpio >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_STATUS;
+ if (pdata->batt_tech >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_TECHNOLOGY;
+ if (pdata->temp_aux >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_TEMP;
+ if (pdata->batt_aux >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_NOW;
+ if (pdata->max_voltage >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MAX;
+ if (pdata->min_voltage >= 0)
+ prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MIN;
+
+ INIT_WORK(&bat_work, wm97xx_bat_work);
+
+ if (!pdata->batt_name) {
+ dev_info(&dev->dev, "Please consider setting proper battery "
+ "name in platform definition file, falling "
+ "back to name \"wm97xx-batt\"\n");
+ bat_ps.name = "wm97xx-batt";
+ } else
+ bat_ps.name = pdata->batt_name;
+
+ bat_ps.properties = prop;
+ bat_ps.num_properties = props;
+
+ ret = power_supply_register(&dev->dev, &bat_ps);
+ if (!ret)
+ schedule_work(&bat_work);
+ else
+ goto err3;
+
+ return 0;
+err3:
+ kfree(prop);
+err2:
+ gpio_free(pdata->charge_gpio);
+err:
+ return ret;
+}
+
+static int __devexit wm97xx_bat_remove(struct platform_device *dev)
+{
+ if (pdata && pdata->charge_gpio && pdata->charge_gpio >= 0)
+ gpio_free(pdata->charge_gpio);
+ flush_scheduled_work();
+ power_supply_unregister(&bat_ps);
+ kfree(prop);
+ return 0;
+}
+
+static struct platform_driver wm97xx_bat_driver = {
+ .driver = {
+ .name = "wm97xx-battery",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm97xx_bat_probe,
+ .remove = __devexit_p(wm97xx_bat_remove),
+ .suspend = wm97xx_bat_suspend,
+ .resume = wm97xx_bat_resume,
+};
+
+static int __init wm97xx_bat_init(void)
+{
+ return platform_driver_register(&wm97xx_bat_driver);
+}
+
+static void __exit wm97xx_bat_exit(void)
+{
+ platform_driver_unregister(&wm97xx_bat_driver);
+}
+
+void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data)
+{
+ pdata = data;
+}
+EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata);
+
+module_init(wm97xx_bat_init);
+module_exit(wm97xx_bat_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("WM97xx battery driver");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index a656128f1fd..4dada6ee111 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -56,4 +56,28 @@ config REGULATOR_BQ24022
charging select between 100 mA and 500 mA charging current
limit.
+config REGULATOR_WM8350
+ tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
+ depends on MFD_WM8350
+ select REGULATOR
+ help
+ This driver provides support for the voltage and current regulators
+ of the WM8350 AudioPlus PMIC.
+
+config REGULATOR_WM8400
+ tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
+ depends on MFD_WM8400
+ select REGULATOR
+ help
+ This driver provides support for the voltage regulators of the
+ WM8400 AudioPlus PMIC.
+
+config REGULATOR_DA903X
+ tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
+ depends on PMIC_DA903X
+ select REGULATOR
+ help
+ Say y here to support the BUCKs and LDOs regulators found on
+ Dialog Semiconductor DA9030/DA9034 PMIC.
+
endmenu
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ac2c64efe65..254d40c02ee 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -8,5 +8,8 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
+obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
+obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c
index 263699d6152..366565aba86 100644
--- a/drivers/regulator/bq24022.c
+++ b/drivers/regulator/bq24022.c
@@ -18,13 +18,13 @@
#include <linux/regulator/bq24022.h>
#include <linux/regulator/driver.h>
+
static int bq24022_set_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
- struct platform_device *pdev = rdev_get_drvdata(rdev);
- struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+ struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
- dev_dbg(&pdev->dev, "setting current limit to %s mA\n",
+ dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n",
max_uA >= 500000 ? "500" : "100");
/* REVISIT: maybe return error if min_uA != 0 ? */
@@ -34,18 +34,16 @@ static int bq24022_set_current_limit(struct regulator_dev *rdev,
static int bq24022_get_current_limit(struct regulator_dev *rdev)
{
- struct platform_device *pdev = rdev_get_drvdata(rdev);
- struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+ struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
}
static int bq24022_enable(struct regulator_dev *rdev)
{
- struct platform_device *pdev = rdev_get_drvdata(rdev);
- struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+ struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
- dev_dbg(&pdev->dev, "enabling charger\n");
+ dev_dbg(rdev_get_dev(rdev), "enabling charger\n");
gpio_set_value(pdata->gpio_nce, 0);
return 0;
@@ -53,10 +51,9 @@ static int bq24022_enable(struct regulator_dev *rdev)
static int bq24022_disable(struct regulator_dev *rdev)
{
- struct platform_device *pdev = rdev_get_drvdata(rdev);
- struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+ struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
- dev_dbg(&pdev->dev, "disabling charger\n");
+ dev_dbg(rdev_get_dev(rdev), "disabling charger\n");
gpio_set_value(pdata->gpio_nce, 1);
return 0;
@@ -108,7 +105,7 @@ static int __init bq24022_probe(struct platform_device *pdev)
ret = gpio_direction_output(pdata->gpio_iset2, 0);
ret = gpio_direction_output(pdata->gpio_nce, 1);
- bq24022 = regulator_register(&bq24022_desc, pdev);
+ bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
if (IS_ERR(bq24022)) {
dev_dbg(&pdev->dev, "couldn't register regulator\n");
ret = PTR_ERR(bq24022);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9c798626156..02a774424e8 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2,8 +2,9 @@
* core.c -- Voltage/Current Regulator framework.
*
* Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
*
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* 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
@@ -64,14 +65,9 @@ struct regulator_map {
struct list_head list;
struct device *dev;
const char *supply;
- const char *regulator;
+ struct regulator_dev *regulator;
};
-static inline struct regulator_dev *to_rdev(struct device *d)
-{
- return container_of(d, struct regulator_dev, dev);
-}
-
/*
* struct regulator
*
@@ -227,7 +223,7 @@ static ssize_t device_requested_uA_show(struct device *dev,
static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
ssize_t ret;
mutex_lock(&rdev->mutex);
@@ -240,15 +236,31 @@ static ssize_t regulator_uV_show(struct device *dev,
static ssize_t regulator_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
}
+static ssize_t regulator_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+ const char *name;
+
+ if (rdev->constraints->name)
+ name = rdev->constraints->name;
+ else if (rdev->desc->name)
+ name = rdev->desc->name;
+ else
+ name = "";
+
+ return sprintf(buf, "%s\n", name);
+}
+
static ssize_t regulator_opmode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
int mode = _regulator_get_mode(rdev);
switch (mode) {
@@ -267,7 +279,7 @@ static ssize_t regulator_opmode_show(struct device *dev,
static ssize_t regulator_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
int state = _regulator_is_enabled(rdev);
if (state > 0)
@@ -281,7 +293,7 @@ static ssize_t regulator_state_show(struct device *dev,
static ssize_t regulator_min_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n");
@@ -292,7 +304,7 @@ static ssize_t regulator_min_uA_show(struct device *dev,
static ssize_t regulator_max_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n");
@@ -303,7 +315,7 @@ static ssize_t regulator_max_uA_show(struct device *dev,
static ssize_t regulator_min_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n");
@@ -314,7 +326,7 @@ static ssize_t regulator_min_uV_show(struct device *dev,
static ssize_t regulator_max_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n");
@@ -325,7 +337,7 @@ static ssize_t regulator_max_uV_show(struct device *dev,
static ssize_t regulator_total_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
struct regulator *regulator;
int uA = 0;
@@ -339,14 +351,14 @@ static ssize_t regulator_total_uA_show(struct device *dev,
static ssize_t regulator_num_users_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->use_count);
}
static ssize_t regulator_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
switch (rdev->desc->type) {
case REGULATOR_VOLTAGE:
@@ -360,7 +372,7 @@ static ssize_t regulator_type_show(struct device *dev,
static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -370,7 +382,7 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -380,7 +392,7 @@ static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -406,7 +418,7 @@ static ssize_t suspend_opmode_show(struct regulator_dev *rdev,
static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -417,7 +429,7 @@ static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -428,7 +440,7 @@ static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -439,7 +451,7 @@ static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
static ssize_t regulator_suspend_mem_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -453,7 +465,7 @@ static ssize_t regulator_suspend_mem_state_show(struct device *dev,
static ssize_t regulator_suspend_disk_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -467,7 +479,7 @@ static ssize_t regulator_suspend_disk_state_show(struct device *dev,
static ssize_t regulator_suspend_standby_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints)
return sprintf(buf, "not defined\n");
@@ -477,7 +489,9 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev,
else
return sprintf(buf, "disabled\n");
}
+
static struct device_attribute regulator_dev_attrs[] = {
+ __ATTR(name, 0444, regulator_name_show, NULL),
__ATTR(microvolts, 0444, regulator_uV_show, NULL),
__ATTR(microamps, 0444, regulator_uA_show, NULL),
__ATTR(opmode, 0444, regulator_opmode_show, NULL),
@@ -512,7 +526,7 @@ static struct device_attribute regulator_dev_attrs[] = {
static void regulator_dev_release(struct device *dev)
{
- struct regulator_dev *rdev = to_rdev(dev);
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
kfree(rdev);
}
@@ -569,8 +583,11 @@ static int suspend_set_state(struct regulator_dev *rdev,
/* enable & disable are mandatory for suspend control */
if (!rdev->desc->ops->set_suspend_enable ||
- !rdev->desc->ops->set_suspend_disable)
+ !rdev->desc->ops->set_suspend_disable) {
+ printk(KERN_ERR "%s: no way to set suspend state\n",
+ __func__);
return -EINVAL;
+ }
if (rstate->enabled)
ret = rdev->desc->ops->set_suspend_enable(rdev);
@@ -656,6 +673,155 @@ static void print_constraints(struct regulator_dev *rdev)
printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
}
+/**
+ * set_machine_constraints - sets regulator constraints
+ * @regulator: regulator source
+ *
+ * Allows platform initialisation code to define and constrain
+ * regulator circuits e.g. valid voltage/current ranges, etc. NOTE:
+ * Constraints *must* be set by platform code in order for some
+ * regulator operations to proceed i.e. set_voltage, set_current_limit,
+ * set_mode.
+ */
+static int set_machine_constraints(struct regulator_dev *rdev,
+ struct regulation_constraints *constraints)
+{
+ int ret = 0;
+ const char *name;
+ struct regulator_ops *ops = rdev->desc->ops;
+
+ if (constraints->name)
+ name = constraints->name;
+ else if (rdev->desc->name)
+ name = rdev->desc->name;
+ else
+ name = "regulator";
+
+ rdev->constraints = constraints;
+
+ /* do we need to apply the constraint voltage */
+ if (rdev->constraints->apply_uV &&
+ rdev->constraints->min_uV == rdev->constraints->max_uV &&
+ ops->set_voltage) {
+ ret = ops->set_voltage(rdev,
+ rdev->constraints->min_uV, rdev->constraints->max_uV);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
+ __func__,
+ rdev->constraints->min_uV, name);
+ rdev->constraints = NULL;
+ goto out;
+ }
+ }
+
+ /* are we enabled at boot time by firmware / bootloader */
+ if (rdev->constraints->boot_on)
+ rdev->use_count = 1;
+
+ /* do we need to setup our suspend state */
+ if (constraints->initial_state) {
+ ret = suspend_prepare(rdev, constraints->initial_state);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to set suspend state for %s\n",
+ __func__, name);
+ rdev->constraints = NULL;
+ goto out;
+ }
+ }
+
+ /* if always_on is set then turn the regulator on if it's not
+ * already on. */
+ if (constraints->always_on && ops->enable &&
+ ((ops->is_enabled && !ops->is_enabled(rdev)) ||
+ (!ops->is_enabled && !constraints->boot_on))) {
+ ret = ops->enable(rdev);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to enable %s\n",
+ __func__, name);
+ rdev->constraints = NULL;
+ goto out;
+ }
+ }
+
+ print_constraints(rdev);
+out:
+ return ret;
+}
+
+/**
+ * set_supply - set regulator supply regulator
+ * @regulator: regulator name
+ * @supply: supply regulator name
+ *
+ * Called by platform initialisation code to set the supply regulator for this
+ * regulator. This ensures that a regulators supply will also be enabled by the
+ * core if it's child is enabled.
+ */
+static int set_supply(struct regulator_dev *rdev,
+ struct regulator_dev *supply_rdev)
+{
+ int err;
+
+ err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
+ "supply");
+ if (err) {
+ printk(KERN_ERR
+ "%s: could not add device link %s err %d\n",
+ __func__, supply_rdev->dev.kobj.name, err);
+ goto out;
+ }
+ rdev->supply = supply_rdev;
+ list_add(&rdev->slist, &supply_rdev->supply_list);
+out:
+ return err;
+}
+
+/**
+ * set_consumer_device_supply: Bind a regulator to a symbolic supply
+ * @regulator: regulator source
+ * @dev: device the supply applies to
+ * @supply: symbolic name for supply
+ *
+ * Allows platform initialisation code to map physical regulator
+ * sources to symbolic names for supplies for use by devices. Devices
+ * should use these symbolic names to request regulators, avoiding the
+ * need to provide board-specific regulator names as platform data.
+ */
+static int set_consumer_device_supply(struct regulator_dev *rdev,
+ struct device *consumer_dev, const char *supply)
+{
+ struct regulator_map *node;
+
+ if (supply == NULL)
+ return -EINVAL;
+
+ node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
+ if (node == NULL)
+ return -ENOMEM;
+
+ node->regulator = rdev;
+ node->dev = consumer_dev;
+ node->supply = supply;
+
+ list_add(&node->list, &regulator_map_list);
+ return 0;
+}
+
+static void unset_consumer_device_supply(struct regulator_dev *rdev,
+ struct device *consumer_dev)
+{
+ struct regulator_map *node, *n;
+
+ list_for_each_entry_safe(node, n, &regulator_map_list, list) {
+ if (rdev == node->regulator &&
+ consumer_dev == node->dev) {
+ list_del(&node->list);
+ kfree(node);
+ return;
+ }
+ }
+}
+
#define REG_STR_SIZE 32
static struct regulator *create_regulator(struct regulator_dev *rdev,
@@ -746,7 +912,6 @@ struct regulator *regulator_get(struct device *dev, const char *id)
struct regulator_dev *rdev;
struct regulator_map *map;
struct regulator *regulator = ERR_PTR(-ENODEV);
- const char *supply = id;
if (id == NULL) {
printk(KERN_ERR "regulator: get() with no identifier\n");
@@ -758,15 +923,9 @@ struct regulator *regulator_get(struct device *dev, const char *id)
list_for_each_entry(map, &regulator_map_list, list) {
if (dev == map->dev &&
strcmp(map->supply, id) == 0) {
- supply = map->regulator;
- break;
- }
- }
-
- list_for_each_entry(rdev, &regulator_list, list) {
- if (strcmp(supply, rdev->desc->name) == 0 &&
- try_module_get(rdev->owner))
+ rdev = map->regulator;
goto found;
+ }
}
printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n",
id);
@@ -774,12 +933,16 @@ struct regulator *regulator_get(struct device *dev, const char *id)
return regulator;
found:
+ if (!try_module_get(rdev->owner))
+ goto out;
+
regulator = create_regulator(rdev, dev, id);
if (regulator == NULL) {
regulator = ERR_PTR(-ENOMEM);
module_put(rdev->owner);
}
+out:
mutex_unlock(&regulator_list_mutex);
return regulator;
}
@@ -1559,11 +1722,12 @@ EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
* Returns 0 on success.
*/
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
- void *reg_data)
+ struct device *dev, void *driver_data)
{
static atomic_t regulator_no = ATOMIC_INIT(0);
struct regulator_dev *rdev;
- int ret;
+ struct regulator_init_data *init_data = dev->platform_data;
+ int ret, i;
if (regulator_desc == NULL)
return ERR_PTR(-EINVAL);
@@ -1575,6 +1739,9 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
!regulator_desc->type == REGULATOR_CURRENT)
return ERR_PTR(-EINVAL);
+ if (!init_data)
+ return ERR_PTR(-EINVAL);
+
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
if (rdev == NULL)
return ERR_PTR(-ENOMEM);
@@ -1582,7 +1749,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
mutex_lock(&regulator_list_mutex);
mutex_init(&rdev->mutex);
- rdev->reg_data = reg_data;
+ rdev->reg_data = driver_data;
rdev->owner = regulator_desc->owner;
rdev->desc = regulator_desc;
INIT_LIST_HEAD(&rdev->consumer_list);
@@ -1591,20 +1758,68 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
INIT_LIST_HEAD(&rdev->slist);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
+ /* preform any regulator specific init */
+ if (init_data->regulator_init) {
+ ret = init_data->regulator_init(rdev->reg_data);
+ if (ret < 0) {
+ kfree(rdev);
+ rdev = ERR_PTR(ret);
+ goto out;
+ }
+ }
+
+ /* set regulator constraints */
+ ret = set_machine_constraints(rdev, &init_data->constraints);
+ if (ret < 0) {
+ kfree(rdev);
+ rdev = ERR_PTR(ret);
+ goto out;
+ }
+
+ /* register with sysfs */
rdev->dev.class = &regulator_class;
- device_initialize(&rdev->dev);
+ rdev->dev.parent = dev;
snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
- "regulator_%ld_%s",
- (unsigned long)atomic_inc_return(&regulator_no) - 1,
- regulator_desc->name);
-
- ret = device_add(&rdev->dev);
- if (ret == 0)
- list_add(&rdev->list, &regulator_list);
- else {
+ "regulator.%d", atomic_inc_return(&regulator_no) - 1);
+ ret = device_register(&rdev->dev);
+ if (ret != 0) {
kfree(rdev);
rdev = ERR_PTR(ret);
+ goto out;
+ }
+
+ dev_set_drvdata(&rdev->dev, rdev);
+
+ /* set supply regulator if it exists */
+ if (init_data->supply_regulator_dev) {
+ ret = set_supply(rdev,
+ dev_get_drvdata(init_data->supply_regulator_dev));
+ if (ret < 0) {
+ device_unregister(&rdev->dev);
+ kfree(rdev);
+ rdev = ERR_PTR(ret);
+ goto out;
+ }
}
+
+ /* add consumers devices */
+ for (i = 0; i < init_data->num_consumer_supplies; i++) {
+ ret = set_consumer_device_supply(rdev,
+ init_data->consumer_supplies[i].dev,
+ init_data->consumer_supplies[i].supply);
+ if (ret < 0) {
+ for (--i; i >= 0; i--)
+ unset_consumer_device_supply(rdev,
+ init_data->consumer_supplies[i].dev);
+ device_unregister(&rdev->dev);
+ kfree(rdev);
+ rdev = ERR_PTR(ret);
+ goto out;
+ }
+ }
+
+ list_add(&rdev->list, &regulator_list);
+out:
mutex_unlock(&regulator_list_mutex);
return rdev;
}
@@ -1631,187 +1846,6 @@ void regulator_unregister(struct regulator_dev *rdev)
EXPORT_SYMBOL_GPL(regulator_unregister);
/**
- * regulator_set_supply - set regulator supply regulator
- * @regulator: regulator name
- * @supply: supply regulator name
- *
- * Called by platform initialisation code to set the supply regulator for this
- * regulator. This ensures that a regulators supply will also be enabled by the
- * core if it's child is enabled.
- */
-int regulator_set_supply(const char *regulator, const char *supply)
-{
- struct regulator_dev *rdev, *supply_rdev;
- int err;
-
- if (regulator == NULL || supply == NULL)
- return -EINVAL;
-
- mutex_lock(&regulator_list_mutex);
-
- list_for_each_entry(rdev, &regulator_list, list) {
- if (!strcmp(rdev->desc->name, regulator))
- goto found_regulator;
- }
- mutex_unlock(&regulator_list_mutex);
- return -ENODEV;
-
-found_regulator:
- list_for_each_entry(supply_rdev, &regulator_list, list) {
- if (!strcmp(supply_rdev->desc->name, supply))
- goto found_supply;
- }
- mutex_unlock(&regulator_list_mutex);
- return -ENODEV;
-
-found_supply:
- err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
- "supply");
- if (err) {
- printk(KERN_ERR
- "%s: could not add device link %s err %d\n",
- __func__, supply_rdev->dev.kobj.name, err);
- goto out;
- }
- rdev->supply = supply_rdev;
- list_add(&rdev->slist, &supply_rdev->supply_list);
-out:
- mutex_unlock(&regulator_list_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(regulator_set_supply);
-
-/**
- * regulator_get_supply - get regulator supply regulator
- * @regulator: regulator name
- *
- * Returns the supply supply regulator name or NULL if no supply regulator
- * exists (i.e the regulator is supplied directly from USB, Line, Battery, etc)
- */
-const char *regulator_get_supply(const char *regulator)
-{
- struct regulator_dev *rdev;
-
- if (regulator == NULL)
- return NULL;
-
- mutex_lock(&regulator_list_mutex);
- list_for_each_entry(rdev, &regulator_list, list) {
- if (!strcmp(rdev->desc->name, regulator))
- goto found;
- }
- mutex_unlock(&regulator_list_mutex);
- return NULL;
-
-found:
- mutex_unlock(&regulator_list_mutex);
- if (rdev->supply)
- return rdev->supply->desc->name;
- else
- return NULL;
-}
-EXPORT_SYMBOL_GPL(regulator_get_supply);
-
-/**
- * regulator_set_machine_constraints - sets regulator constraints
- * @regulator: regulator source
- *
- * Allows platform initialisation code to define and constrain
- * regulator circuits e.g. valid voltage/current ranges, etc. NOTE:
- * Constraints *must* be set by platform code in order for some
- * regulator operations to proceed i.e. set_voltage, set_current_limit,
- * set_mode.
- */
-int regulator_set_machine_constraints(const char *regulator_name,
- struct regulation_constraints *constraints)
-{
- struct regulator_dev *rdev;
- int ret = 0;
-
- if (regulator_name == NULL)
- return -EINVAL;
-
- mutex_lock(&regulator_list_mutex);
-
- list_for_each_entry(rdev, &regulator_list, list) {
- if (!strcmp(regulator_name, rdev->desc->name))
- goto found;
- }
- ret = -ENODEV;
- goto out;
-
-found:
- mutex_lock(&rdev->mutex);
- rdev->constraints = constraints;
-
- /* do we need to apply the constraint voltage */
- if (rdev->constraints->apply_uV &&
- rdev->constraints->min_uV == rdev->constraints->max_uV &&
- rdev->desc->ops->set_voltage) {
- ret = rdev->desc->ops->set_voltage(rdev,
- rdev->constraints->min_uV, rdev->constraints->max_uV);
- if (ret < 0) {
- printk(KERN_ERR "%s: failed to apply %duV"
- " constraint\n", __func__,
- rdev->constraints->min_uV);
- rdev->constraints = NULL;
- goto out;
- }
- }
-
- /* are we enabled at boot time by firmware / bootloader */
- if (rdev->constraints->boot_on)
- rdev->use_count = 1;
-
- /* do we need to setup our suspend state */
- if (constraints->initial_state)
- ret = suspend_prepare(rdev, constraints->initial_state);
-
- print_constraints(rdev);
- mutex_unlock(&rdev->mutex);
-
-out:
- mutex_unlock(&regulator_list_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(regulator_set_machine_constraints);
-
-
-/**
- * regulator_set_device_supply: Bind a regulator to a symbolic supply
- * @regulator: regulator source
- * @dev: device the supply applies to
- * @supply: symbolic name for supply
- *
- * Allows platform initialisation code to map physical regulator
- * sources to symbolic names for supplies for use by devices. Devices
- * should use these symbolic names to request regulators, avoiding the
- * need to provide board-specific regulator names as platform data.
- */
-int regulator_set_device_supply(const char *regulator, struct device *dev,
- const char *supply)
-{
- struct regulator_map *node;
-
- if (regulator == NULL || supply == NULL)
- return -EINVAL;
-
- node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
- if (node == NULL)
- return -ENOMEM;
-
- node->regulator = regulator;
- node->dev = dev;
- node->supply = supply;
-
- mutex_lock(&regulator_list_mutex);
- list_add(&node->list, &regulator_map_list);
- mutex_unlock(&regulator_list_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(regulator_set_device_supply);
-
-/**
* regulator_suspend_prepare: prepare regulators for system wide suspend
* @state: system suspend state
*
@@ -1893,6 +1927,18 @@ int rdev_get_id(struct regulator_dev *rdev)
}
EXPORT_SYMBOL_GPL(rdev_get_id);
+struct device *rdev_get_dev(struct regulator_dev *rdev)
+{
+ return &rdev->dev;
+}
+EXPORT_SYMBOL_GPL(rdev_get_dev);
+
+void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
+{
+ return reg_init_data->driver_data;
+}
+EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
+
static int __init regulator_init(void)
{
printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
new file mode 100644
index 00000000000..3688e339db8
--- /dev/null
+++ b/drivers/regulator/da903x.c
@@ -0,0 +1,513 @@
+/*
+ * Regulators driver for Dialog Semiconductor DA903x
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Copyright (C) 2008 Compulab Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/da903x.h>
+
+/* DA9030 Registers */
+#define DA9030_INVAL (-1)
+#define DA9030_LDO1011 (0x10)
+#define DA9030_LDO15 (0x11)
+#define DA9030_LDO1416 (0x12)
+#define DA9030_LDO1819 (0x13)
+#define DA9030_LDO17 (0x14)
+#define DA9030_BUCK2DVM1 (0x15)
+#define DA9030_BUCK2DVM2 (0x16)
+#define DA9030_RCTL11 (0x17)
+#define DA9030_RCTL21 (0x18)
+#define DA9030_LDO1 (0x90)
+#define DA9030_LDO23 (0x91)
+#define DA9030_LDO45 (0x92)
+#define DA9030_LDO6 (0x93)
+#define DA9030_LDO78 (0x94)
+#define DA9030_LDO912 (0x95)
+#define DA9030_BUCK (0x96)
+#define DA9030_RCTL12 (0x97)
+#define DA9030_RCTL22 (0x98)
+#define DA9030_LDO_UNLOCK (0xa0)
+#define DA9030_LDO_UNLOCK_MASK (0xe0)
+#define DA9034_OVER1 (0x10)
+
+/* DA9034 Registers */
+#define DA9034_INVAL (-1)
+#define DA9034_OVER2 (0x11)
+#define DA9034_OVER3 (0x12)
+#define DA9034_LDO643 (0x13)
+#define DA9034_LDO987 (0x14)
+#define DA9034_LDO1110 (0x15)
+#define DA9034_LDO1312 (0x16)
+#define DA9034_LDO1514 (0x17)
+#define DA9034_VCC1 (0x20)
+#define DA9034_ADTV1 (0x23)
+#define DA9034_ADTV2 (0x24)
+#define DA9034_AVRC (0x25)
+#define DA9034_CDTV1 (0x26)
+#define DA9034_CDTV2 (0x27)
+#define DA9034_CVRC (0x28)
+#define DA9034_SDTV1 (0x29)
+#define DA9034_SDTV2 (0x2a)
+#define DA9034_SVRC (0x2b)
+#define DA9034_MDTV1 (0x32)
+#define DA9034_MDTV2 (0x33)
+#define DA9034_MVRC (0x34)
+
+struct da903x_regulator_info {
+ struct regulator_desc desc;
+
+ int min_uV;
+ int max_uV;
+ int step_uV;
+ int vol_reg;
+ int vol_shift;
+ int vol_nbits;
+ int update_reg;
+ int update_bit;
+ int enable_reg;
+ int enable_bit;
+};
+
+static inline int check_range(struct da903x_regulator_info *info,
+ int min_uV, int max_uV)
+{
+ if (min_uV < info->min_uV || min_uV > info->max_uV)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* DA9030/DA9034 common operations */
+static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+
+ if (check_range(info, min_uV, max_uV)) {
+ pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+ val <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+ return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da903x_get_voltage(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int ret;
+
+ ret = da903x_read(da9034_dev, info->vol_reg, &val);
+ if (ret)
+ return ret;
+
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ val = (val & mask) >> info->vol_shift;
+
+ return info->min_uV + info->step_uV * val;
+}
+
+static int da903x_enable(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+ return da903x_set_bits(da9034_dev, info->enable_reg,
+ 1 << info->enable_bit);
+}
+
+static int da903x_disable(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+ return da903x_clr_bits(da9034_dev, info->enable_reg,
+ 1 << info->enable_bit);
+}
+
+static int da903x_is_enabled(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t reg_val;
+ int ret;
+
+ ret = da903x_read(da9034_dev, info->enable_reg, &reg_val);
+ if (ret)
+ return ret;
+
+ return reg_val & (1 << info->enable_bit);
+}
+
+/* DA9030 specific operations */
+static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int ret;
+
+ if (check_range(info, min_uV, max_uV)) {
+ pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+ val <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
+ mask |= DA9030_LDO_UNLOCK_MASK;
+
+ /* write twice */
+ ret = da903x_update(da903x_dev, info->vol_reg, val, mask);
+ if (ret)
+ return ret;
+
+ return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int thresh;
+
+ if (check_range(info, min_uV, max_uV)) {
+ pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ thresh = (info->max_uV + info->min_uV) / 2;
+ if (min_uV < thresh) {
+ val = (thresh - min_uV + info->step_uV - 1) / info->step_uV;
+ val |= 0x4;
+ } else {
+ val = (min_uV - thresh + info->step_uV - 1) / info->step_uV;
+ }
+
+ val <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+ return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int ret;
+
+ ret = da903x_read(da903x_dev, info->vol_reg, &val);
+ if (ret)
+ return ret;
+
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ val = (val & mask) >> info->vol_shift;
+
+ if (val & 0x4)
+ return info->min_uV + info->step_uV * (3 - (val & ~0x4));
+ else
+ return (info->max_uV + info->min_uV) / 2 +
+ info->step_uV * (val & ~0x4);
+}
+
+/* DA9034 specific operations */
+static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int ret;
+
+ if (check_range(info, min_uV, max_uV)) {
+ pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+ val <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+ ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
+ if (ret)
+ return ret;
+
+ ret = da903x_set_bits(da9034_dev, info->update_reg,
+ 1 << info->update_bit);
+ return ret;
+}
+
+static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+
+ if (check_range(info, min_uV, max_uV)) {
+ pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+ val = (val > 7 || val < 20) ? 8 : val - 12;
+ val <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+ return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da9034_get_ldo12_voltage(struct regulator_dev *rdev)
+{
+ struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+ struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+ uint8_t val, mask;
+ int ret;
+
+ ret = da903x_read(da9034_dev, info->vol_reg, &val);
+ if (ret)
+ return ret;
+
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ val = (val & mask) >> info->vol_shift;
+
+ if (val >= 8)
+ return 2700000 + info->step_uV * (val - 8);
+
+ return info->min_uV + info->step_uV * val;
+}
+
+static struct regulator_ops da903x_regulator_ldo_ops = {
+ .set_voltage = da903x_set_ldo_voltage,
+ .get_voltage = da903x_get_voltage,
+ .enable = da903x_enable,
+ .disable = da903x_disable,
+ .is_enabled = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane DA9030 LDO14 */
+static struct regulator_ops da9030_regulator_ldo14_ops = {
+ .set_voltage = da9030_set_ldo14_voltage,
+ .get_voltage = da9030_get_ldo14_voltage,
+ .enable = da903x_enable,
+ .disable = da903x_disable,
+ .is_enabled = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks */
+static struct regulator_ops da9030_regulator_ldo1_15_ops = {
+ .set_voltage = da9030_set_ldo1_15_voltage,
+ .get_voltage = da903x_get_voltage,
+ .enable = da903x_enable,
+ .disable = da903x_disable,
+ .is_enabled = da903x_is_enabled,
+};
+
+static struct regulator_ops da9034_regulator_dvc_ops = {
+ .set_voltage = da9034_set_dvc_voltage,
+ .get_voltage = da903x_get_voltage,
+ .enable = da903x_enable,
+ .disable = da903x_disable,
+ .is_enabled = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane LDO12 */
+static struct regulator_ops da9034_regulator_ldo12_ops = {
+ .set_voltage = da9034_set_ldo12_voltage,
+ .get_voltage = da9034_get_ldo12_voltage,
+ .enable = da903x_enable,
+ .disable = da903x_disable,
+ .is_enabled = da903x_is_enabled,
+};
+
+#define DA903x_LDO(_pmic, _id, min, max, step, vreg, shift, nbits, ereg, ebit) \
+{ \
+ .desc = { \
+ .name = "LDO" #_id, \
+ .ops = &da903x_regulator_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = _pmic##_ID_LDO##_id, \
+ .owner = THIS_MODULE, \
+ }, \
+ .min_uV = (min) * 1000, \
+ .max_uV = (max) * 1000, \
+ .step_uV = (step) * 1000, \
+ .vol_reg = _pmic##_##vreg, \
+ .vol_shift = (shift), \
+ .vol_nbits = (nbits), \
+ .enable_reg = _pmic##_##ereg, \
+ .enable_bit = (ebit), \
+}
+
+#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{ \
+ .desc = { \
+ .name = #_id, \
+ .ops = &da9034_regulator_dvc_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = DA9034_ID_##_id, \
+ .owner = THIS_MODULE, \
+ }, \
+ .min_uV = (min) * 1000, \
+ .max_uV = (max) * 1000, \
+ .step_uV = (step) * 1000, \
+ .vol_reg = DA9034_##vreg, \
+ .vol_shift = (0), \
+ .vol_nbits = (nbits), \
+ .update_reg = DA9034_##ureg, \
+ .update_bit = (ubit), \
+ .enable_reg = DA9034_##ereg, \
+ .enable_bit = (ebit), \
+}
+
+#define DA9034_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit) \
+ DA903x_LDO(DA9034, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+#define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit) \
+ DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+static struct da903x_regulator_info da903x_regulator_info[] = {
+ /* DA9030 */
+ DA9030_LDO( 1, 1200, 3200, 100, LDO1, 0, 5, RCTL12, 1),
+ DA9030_LDO( 2, 1800, 3200, 100, LDO23, 0, 4, RCTL12, 2),
+ DA9030_LDO( 3, 1800, 3200, 100, LDO23, 4, 4, RCTL12, 3),
+ DA9030_LDO( 4, 1800, 3200, 100, LDO45, 0, 4, RCTL12, 4),
+ DA9030_LDO( 5, 1800, 3200, 100, LDO45, 4, 4, RCTL12, 5),
+ DA9030_LDO( 6, 1800, 3200, 100, LDO6, 0, 4, RCTL12, 6),
+ DA9030_LDO( 7, 1800, 3200, 100, LDO78, 0, 4, RCTL12, 7),
+ DA9030_LDO( 8, 1800, 3200, 100, LDO78, 4, 4, RCTL22, 0),
+ DA9030_LDO( 9, 1800, 3200, 100, LDO912, 0, 4, RCTL22, 1),
+ DA9030_LDO(10, 1800, 3200, 100, LDO1011, 0, 4, RCTL22, 2),
+ DA9030_LDO(11, 1800, 3200, 100, LDO1011, 4, 4, RCTL22, 3),
+ DA9030_LDO(12, 1800, 3200, 100, LDO912, 4, 4, RCTL22, 4),
+ DA9030_LDO(14, 2760, 2940, 30, LDO1416, 0, 3, RCTL11, 4),
+ DA9030_LDO(15, 1100, 2650, 50, LDO15, 0, 5, RCTL11, 5),
+ DA9030_LDO(16, 1100, 2650, 50, LDO1416, 3, 5, RCTL11, 6),
+ DA9030_LDO(17, 1800, 3200, 100, LDO17, 0, 4, RCTL11, 7),
+ DA9030_LDO(18, 1800, 3200, 100, LDO1819, 0, 4, RCTL21, 2),
+ DA9030_LDO(19, 1800, 3200, 100, LDO1819, 4, 4, RCTL21, 1),
+ DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */
+
+ /* DA9034 */
+ DA9034_DVC(BUCK1, 725, 1500, 25, ADTV1, 5, VCC1, 0, OVER1, 0),
+ DA9034_DVC(BUCK2, 725, 1500, 25, CDTV1, 5, VCC1, 2, OVER1, 1),
+ DA9034_DVC(LDO2, 725, 1500, 25, SDTV1, 5, VCC1, 4, OVER1, 2),
+ DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4),
+
+ DA9034_LDO( 3, 1800, 3300, 100, LDO643, 0, 4, OVER3, 5),
+ DA9034_LDO( 4, 1800, 2900,1100, LDO643, 4, 1, OVER3, 6),
+ DA9034_LDO( 6, 2500, 2850, 50, LDO643, 5, 3, OVER2, 0),
+ DA9034_LDO( 7, 2700, 3050, 50, LDO987, 0, 3, OVER2, 1),
+ DA9034_LDO( 8, 2700, 2850, 50, LDO987, 3, 2, OVER2, 2),
+ DA9034_LDO( 9, 2700, 3050, 50, LDO987, 5, 3, OVER2, 3),
+ DA9034_LDO(10, 2700, 3050, 50, LDO1110, 0, 3, OVER2, 4),
+ DA9034_LDO(11, 1800, 3300, 100, LDO1110, 4, 4, OVER2, 5),
+ DA9034_LDO(12, 1700, 3050, 50, LDO1312, 0, 4, OVER3, 6),
+ DA9034_LDO(13, 1800, 3300, 100, LDO1312, 4, 4, OVER2, 7),
+ DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0),
+ DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1),
+ DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */
+};
+
+static inline struct da903x_regulator_info *find_regulator_info(int id)
+{
+ struct da903x_regulator_info *ri;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(da903x_regulator_info); i++) {
+ ri = &da903x_regulator_info[i];
+ if (ri->desc.id == id)
+ return ri;
+ }
+ return NULL;
+}
+
+static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+{
+ struct da903x_regulator_info *ri = NULL;
+ struct regulator_dev *rdev;
+
+ ri = find_regulator_info(pdev->id);
+ if (ri == NULL) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ return -EINVAL;
+ }
+
+ /* Workaround for the weird LDO12 voltage setting */
+ if (ri->desc.id == DA9034_ID_LDO12)
+ ri->desc.ops = &da9034_regulator_ldo12_ops;
+
+ if (ri->desc.id == DA9030_ID_LDO14)
+ ri->desc.ops = &da9030_regulator_ldo14_ops;
+
+ if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
+ ri->desc.ops = &da9030_regulator_ldo1_15_ops;
+
+ rdev = regulator_register(&ri->desc, pdev->dev.parent, ri);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->desc.name);
+ return PTR_ERR(rdev);
+ }
+
+ platform_set_drvdata(pdev, rdev);
+ return 0;
+}
+
+static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+ return 0;
+}
+
+static struct platform_driver da903x_regulator_driver = {
+ .driver = {
+ .name = "da903x-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = da903x_regulator_probe,
+ .remove = da903x_regulator_remove,
+};
+
+static int __init da903x_regulator_init(void)
+{
+ return platform_driver_register(&da903x_regulator_driver);
+}
+module_init(da903x_regulator_init);
+
+static void __exit da903x_regulator_exit(void)
+{
+ platform_driver_unregister(&da903x_regulator_driver);
+}
+module_exit(da903x_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("Regulator Driver for Dialog Semiconductor DA903X PMIC");
+MODULE_ALIAS("platform:da903x-regulator");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
new file mode 100644
index 00000000000..1f44b17e23b
--- /dev/null
+++ b/drivers/regulator/wm8350-regulator.c
@@ -0,0 +1,1431 @@
+/*
+ * wm8350.c -- Voltage and current regulation for the Wolfson WM8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ * linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/* Microamps */
+static const int isink_cur[] = {
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 10,
+ 11,
+ 14,
+ 16,
+ 19,
+ 23,
+ 27,
+ 32,
+ 39,
+ 46,
+ 54,
+ 65,
+ 77,
+ 92,
+ 109,
+ 130,
+ 154,
+ 183,
+ 218,
+ 259,
+ 308,
+ 367,
+ 436,
+ 518,
+ 616,
+ 733,
+ 872,
+ 1037,
+ 1233,
+ 1466,
+ 1744,
+ 2073,
+ 2466,
+ 2933,
+ 3487,
+ 4147,
+ 4932,
+ 5865,
+ 6975,
+ 8294,
+ 9864,
+ 11730,
+ 13949,
+ 16589,
+ 19728,
+ 23460,
+ 27899,
+ 33178,
+ 39455,
+ 46920,
+ 55798,
+ 66355,
+ 78910,
+ 93840,
+ 111596,
+ 132710,
+ 157820,
+ 187681,
+ 223191
+};
+
+static int get_isink_val(int min_uA, int max_uA, u16 *setting)
+{
+ int i;
+
+ for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
+ if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
+ *setting = i;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
+{
+ if (val < 16)
+ return (val * 50) + 900;
+ else
+ return ((val - 16) * 100) + 1800;
+
+}
+
+static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
+{
+ if (mV < 1800)
+ return (mV - 900) / 50;
+ else
+ return ((mV - 1800) / 100) + 16;
+}
+
+static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
+{
+ return (val * 25) + 850;
+}
+
+static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
+{
+ return (mV - 850) / 25;
+}
+
+static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
+ int max_uA)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int isink = rdev_get_id(rdev);
+ u16 val, setting;
+ int ret;
+
+ ret = get_isink_val(min_uA, max_uA, &setting);
+ if (ret != 0)
+ return ret;
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+ ~WM8350_CS1_ISEL_MASK;
+ wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_A,
+ val | setting);
+ break;
+ case WM8350_ISINK_B:
+ val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+ ~WM8350_CS1_ISEL_MASK;
+ wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_B,
+ val | setting);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_isink_get_current(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int isink = rdev_get_id(rdev);
+ u16 val;
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+ WM8350_CS1_ISEL_MASK;
+ break;
+ case WM8350_ISINK_B:
+ val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+ WM8350_CS1_ISEL_MASK;
+ break;
+ default:
+ return 0;
+ }
+
+ return (isink_cur[val] + 50) / 100;
+}
+
+/* turn on ISINK followed by DCDC */
+static int wm8350_isink_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int isink = rdev_get_id(rdev);
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ switch (wm8350->pmic.isink_A_dcdc) {
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+ WM8350_CS1_ENA);
+ wm8350_set_bits(wm8350, WM8350_CSA_FLASH_CONTROL,
+ WM8350_CS1_DRIVE);
+ wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+ 1 << (wm8350->pmic.isink_A_dcdc -
+ WM8350_DCDC_1));
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case WM8350_ISINK_B:
+ switch (wm8350->pmic.isink_B_dcdc) {
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+ WM8350_CS2_ENA);
+ wm8350_set_bits(wm8350, WM8350_CSB_FLASH_CONTROL,
+ WM8350_CS2_DRIVE);
+ wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+ 1 << (wm8350->pmic.isink_B_dcdc -
+ WM8350_DCDC_1));
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_isink_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int isink = rdev_get_id(rdev);
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ switch (wm8350->pmic.isink_A_dcdc) {
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+ 1 << (wm8350->pmic.isink_A_dcdc -
+ WM8350_DCDC_1));
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+ WM8350_CS1_ENA);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case WM8350_ISINK_B:
+ switch (wm8350->pmic.isink_B_dcdc) {
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+ 1 << (wm8350->pmic.isink_B_dcdc -
+ WM8350_DCDC_1));
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+ WM8350_CS2_ENA);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_isink_is_enabled(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int isink = rdev_get_id(rdev);
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+ 0x8000;
+ case WM8350_ISINK_B:
+ return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+ 0x8000;
+ }
+ return -EINVAL;
+}
+
+int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
+ u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
+ u16 drive)
+{
+ switch (isink) {
+ case WM8350_ISINK_A:
+ wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL,
+ (mode ? WM8350_CS1_FLASH_MODE : 0) |
+ (trigger ? WM8350_CS1_TRIGSRC : 0) |
+ duration | on_ramp | off_ramp | drive);
+ break;
+ case WM8350_ISINK_B:
+ wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL,
+ (mode ? WM8350_CS2_FLASH_MODE : 0) |
+ (trigger ? WM8350_CS2_TRIGSRC : 0) |
+ duration | on_ramp | off_ramp | drive);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
+
+static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, dcdc = rdev_get_id(rdev), mV,
+ min_mV = min_uV / 1000, max_mV = max_uV / 1000;
+ u16 val;
+
+ if (min_mV < 850 || min_mV > 4025)
+ return -EINVAL;
+ if (max_mV < 850 || max_mV > 4025)
+ return -EINVAL;
+
+ /* step size is 25mV */
+ mV = (min_mV - 826) / 25;
+ if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
+ return -EINVAL;
+ BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ volt_reg = WM8350_DCDC1_CONTROL;
+ break;
+ case WM8350_DCDC_3:
+ volt_reg = WM8350_DCDC3_CONTROL;
+ break;
+ case WM8350_DCDC_4:
+ volt_reg = WM8350_DCDC4_CONTROL;
+ break;
+ case WM8350_DCDC_6:
+ volt_reg = WM8350_DCDC6_CONTROL;
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ /* all DCDCs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+ wm8350_reg_write(wm8350, volt_reg, val | mV);
+ return 0;
+}
+
+static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ volt_reg = WM8350_DCDC1_CONTROL;
+ break;
+ case WM8350_DCDC_3:
+ volt_reg = WM8350_DCDC3_CONTROL;
+ break;
+ case WM8350_DCDC_4:
+ volt_reg = WM8350_DCDC4_CONTROL;
+ break;
+ case WM8350_DCDC_6:
+ volt_reg = WM8350_DCDC6_CONTROL;
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ /* all DCDCs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
+ return wm8350_dcdc_val_to_mvolts(val) * 1000;
+}
+
+static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
+
+ if (mV && (mV < 850 || mV > 4025)) {
+ dev_err(wm8350->dev,
+ "DCDC%d suspend voltage %d mV out of range\n",
+ dcdc, mV);
+ return -EINVAL;
+ }
+ if (mV == 0)
+ mV = 850;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ volt_reg = WM8350_DCDC1_LOW_POWER;
+ break;
+ case WM8350_DCDC_3:
+ volt_reg = WM8350_DCDC3_LOW_POWER;
+ break;
+ case WM8350_DCDC_4:
+ volt_reg = WM8350_DCDC4_LOW_POWER;
+ break;
+ case WM8350_DCDC_6:
+ volt_reg = WM8350_DCDC6_LOW_POWER;
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ /* all DCDCs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+ wm8350_reg_write(wm8350, volt_reg,
+ val | wm8350_dcdc_mvolts_to_val(mV));
+ return 0;
+}
+
+static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
+ & ~WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+ wm8350->pmic.dcdc1_hib_mode);
+ break;
+ case WM8350_DCDC_3:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
+ & ~WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+ wm8350->pmic.dcdc3_hib_mode);
+ break;
+ case WM8350_DCDC_4:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
+ & ~WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+ wm8350->pmic.dcdc4_hib_mode);
+ break;
+ case WM8350_DCDC_6:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
+ & ~WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+ wm8350->pmic.dcdc6_hib_mode);
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+ wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+ WM8350_DCDC_HIB_MODE_DIS);
+ break;
+ case WM8350_DCDC_3:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+ wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+ WM8350_DCDC_HIB_MODE_DIS);
+ break;
+ case WM8350_DCDC_4:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+ wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+ WM8350_DCDC_HIB_MODE_DIS);
+ break;
+ case WM8350_DCDC_6:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+ wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+ WM8350_DCDC_HIB_MODE_DIS);
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ switch (dcdc) {
+ case WM8350_DCDC_2:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+ & ~WM8350_DC2_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+ WM8350_DC2_HIB_MODE_ACTIVE);
+ break;
+ case WM8350_DCDC_5:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+ & ~WM8350_DC2_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+ WM8350_DC5_HIB_MODE_ACTIVE);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ switch (dcdc) {
+ case WM8350_DCDC_2:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+ & ~WM8350_DC2_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+ WM8350_DC2_HIB_MODE_DISABLE);
+ break;
+ case WM8350_DCDC_5:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+ & ~WM8350_DC2_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+ WM8350_DC2_HIB_MODE_DISABLE);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 *hib_mode;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ hib_mode = &wm8350->pmic.dcdc1_hib_mode;
+ break;
+ case WM8350_DCDC_3:
+ hib_mode = &wm8350->pmic.dcdc3_hib_mode;
+ break;
+ case WM8350_DCDC_4:
+ hib_mode = &wm8350->pmic.dcdc4_hib_mode;
+ break;
+ case WM8350_DCDC_6:
+ hib_mode = &wm8350->pmic.dcdc6_hib_mode;
+ break;
+ case WM8350_DCDC_2:
+ case WM8350_DCDC_5:
+ default:
+ return -EINVAL;
+ }
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
+ break;
+ case REGULATOR_MODE_IDLE:
+ *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
+ u16 val;
+
+ dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
+
+ if (mV < 900 || mV > 3300) {
+ dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
+ ldo, mV);
+ return -EINVAL;
+ }
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ volt_reg = WM8350_LDO1_LOW_POWER;
+ break;
+ case WM8350_LDO_2:
+ volt_reg = WM8350_LDO2_LOW_POWER;
+ break;
+ case WM8350_LDO_3:
+ volt_reg = WM8350_LDO3_LOW_POWER;
+ break;
+ case WM8350_LDO_4:
+ volt_reg = WM8350_LDO4_LOW_POWER;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* all LDOs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+ wm8350_reg_write(wm8350, volt_reg,
+ val | wm8350_ldo_mvolts_to_val(mV));
+ return 0;
+}
+
+static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, ldo = rdev_get_id(rdev);
+ u16 val;
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ volt_reg = WM8350_LDO1_LOW_POWER;
+ break;
+ case WM8350_LDO_2:
+ volt_reg = WM8350_LDO2_LOW_POWER;
+ break;
+ case WM8350_LDO_3:
+ volt_reg = WM8350_LDO3_LOW_POWER;
+ break;
+ case WM8350_LDO_4:
+ volt_reg = WM8350_LDO4_LOW_POWER;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* all LDOs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, volt_reg, val);
+ return 0;
+}
+
+static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, ldo = rdev_get_id(rdev);
+ u16 val;
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ volt_reg = WM8350_LDO1_LOW_POWER;
+ break;
+ case WM8350_LDO_2:
+ volt_reg = WM8350_LDO2_LOW_POWER;
+ break;
+ case WM8350_LDO_3:
+ volt_reg = WM8350_LDO3_LOW_POWER;
+ break;
+ case WM8350_LDO_4:
+ volt_reg = WM8350_LDO4_LOW_POWER;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* all LDOs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+ wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
+ return 0;
+}
+
+static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
+ max_mV = max_uV / 1000;
+ u16 val;
+
+ if (min_mV < 900 || min_mV > 3300)
+ return -EINVAL;
+ if (max_mV < 900 || max_mV > 3300)
+ return -EINVAL;
+
+ if (min_mV < 1800) {
+ /* step size is 50mV < 1800mV */
+ mV = (min_mV - 851) / 50;
+ if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+ return -EINVAL;
+ BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+ } else {
+ /* step size is 100mV > 1800mV */
+ mV = ((min_mV - 1701) / 100) + 16;
+ if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+ return -EINVAL;
+ BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+ }
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ volt_reg = WM8350_LDO1_CONTROL;
+ break;
+ case WM8350_LDO_2:
+ volt_reg = WM8350_LDO2_CONTROL;
+ break;
+ case WM8350_LDO_3:
+ volt_reg = WM8350_LDO3_CONTROL;
+ break;
+ case WM8350_LDO_4:
+ volt_reg = WM8350_LDO4_CONTROL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* all LDOs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+ wm8350_reg_write(wm8350, volt_reg, val | mV);
+ return 0;
+}
+
+static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int volt_reg, ldo = rdev_get_id(rdev);
+ u16 val;
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ volt_reg = WM8350_LDO1_CONTROL;
+ break;
+ case WM8350_LDO_2:
+ volt_reg = WM8350_LDO2_CONTROL;
+ break;
+ case WM8350_LDO_3:
+ volt_reg = WM8350_LDO3_CONTROL;
+ break;
+ case WM8350_LDO_4:
+ volt_reg = WM8350_LDO4_CONTROL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* all LDOs have same mV bits */
+ val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
+ return wm8350_ldo_val_to_mvolts(val) * 1000;
+}
+
+int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
+ u16 stop, u16 fault)
+{
+ int slot_reg;
+ u16 val;
+
+ dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+ __func__, dcdc, start, stop);
+
+ /* slot valid ? */
+ if (start > 15 || stop > 15)
+ return -EINVAL;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ slot_reg = WM8350_DCDC1_TIMEOUTS;
+ break;
+ case WM8350_DCDC_2:
+ slot_reg = WM8350_DCDC2_TIMEOUTS;
+ break;
+ case WM8350_DCDC_3:
+ slot_reg = WM8350_DCDC3_TIMEOUTS;
+ break;
+ case WM8350_DCDC_4:
+ slot_reg = WM8350_DCDC4_TIMEOUTS;
+ break;
+ case WM8350_DCDC_5:
+ slot_reg = WM8350_DCDC5_TIMEOUTS;
+ break;
+ case WM8350_DCDC_6:
+ slot_reg = WM8350_DCDC6_TIMEOUTS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = wm8350_reg_read(wm8350, slot_reg) &
+ ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
+ WM8350_DC1_ERRACT_MASK);
+ wm8350_reg_write(wm8350, slot_reg,
+ val | (start << WM8350_DC1_ENSLOT_SHIFT) |
+ (stop << WM8350_DC1_SDSLOT_SHIFT) |
+ (fault << WM8350_DC1_ERRACT_SHIFT));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
+
+int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
+{
+ int slot_reg;
+ u16 val;
+
+ dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+ __func__, ldo, start, stop);
+
+ /* slot valid ? */
+ if (start > 15 || stop > 15)
+ return -EINVAL;
+
+ switch (ldo) {
+ case WM8350_LDO_1:
+ slot_reg = WM8350_LDO1_TIMEOUTS;
+ break;
+ case WM8350_LDO_2:
+ slot_reg = WM8350_LDO2_TIMEOUTS;
+ break;
+ case WM8350_LDO_3:
+ slot_reg = WM8350_LDO3_TIMEOUTS;
+ break;
+ case WM8350_LDO_4:
+ slot_reg = WM8350_LDO4_TIMEOUTS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
+ wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
+
+int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
+ u16 ilim, u16 ramp, u16 feedback)
+{
+ u16 val;
+
+ dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
+ mode ? "normal" : "boost", ilim ? "low" : "normal");
+
+ switch (dcdc) {
+ case WM8350_DCDC_2:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+ & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
+ WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
+ wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+ (mode << WM8350_DC2_MODE_SHIFT) |
+ (ilim << WM8350_DC2_ILIM_SHIFT) |
+ (ramp << WM8350_DC2_RMP_SHIFT) |
+ (feedback << WM8350_DC2_FBSRC_SHIFT));
+ break;
+ case WM8350_DCDC_5:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+ & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
+ WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
+ wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+ (mode << WM8350_DC5_MODE_SHIFT) |
+ (ilim << WM8350_DC5_ILIM_SHIFT) |
+ (ramp << WM8350_DC5_RMP_SHIFT) |
+ (feedback << WM8350_DC5_FBSRC_SHIFT));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
+
+static int wm8350_dcdc_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 shift;
+
+ if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+ return -EINVAL;
+
+ shift = dcdc - WM8350_DCDC_1;
+ wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+ return 0;
+}
+
+static int wm8350_dcdc_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 shift;
+
+ if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+ return -EINVAL;
+
+ shift = dcdc - WM8350_DCDC_1;
+ wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+
+ return 0;
+}
+
+static int wm8350_ldo_enable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int ldo = rdev_get_id(rdev);
+ u16 shift;
+
+ if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+ return -EINVAL;
+
+ shift = (ldo - WM8350_LDO_1) + 8;
+ wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+ return 0;
+}
+
+static int wm8350_ldo_disable(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int ldo = rdev_get_id(rdev);
+ u16 shift;
+
+ if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+ return -EINVAL;
+
+ shift = (ldo - WM8350_LDO_1) + 8;
+ wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+ return 0;
+}
+
+static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
+{
+ int reg = 0, ret;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ reg = WM8350_DCDC1_FORCE_PWM;
+ break;
+ case WM8350_DCDC_3:
+ reg = WM8350_DCDC3_FORCE_PWM;
+ break;
+ case WM8350_DCDC_4:
+ reg = WM8350_DCDC4_FORCE_PWM;
+ break;
+ case WM8350_DCDC_6:
+ reg = WM8350_DCDC6_FORCE_PWM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (enable)
+ ret = wm8350_set_bits(wm8350, reg,
+ WM8350_DCDC1_FORCE_PWM_ENA);
+ else
+ ret = wm8350_clear_bits(wm8350, reg,
+ WM8350_DCDC1_FORCE_PWM_ENA);
+ return ret;
+}
+
+static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 val;
+
+ if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+ return -EINVAL;
+
+ if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+ return -EINVAL;
+
+ val = 1 << (dcdc - WM8350_DCDC_1);
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ /* force continuous mode */
+ wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+ wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+ force_continuous_enable(wm8350, dcdc, 1);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ /* active / pulse skipping */
+ wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+ wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+ force_continuous_enable(wm8350, dcdc, 0);
+ break;
+ case REGULATOR_MODE_IDLE:
+ /* standby mode */
+ force_continuous_enable(wm8350, dcdc, 0);
+ wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+ wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+ break;
+ case REGULATOR_MODE_STANDBY:
+ /* LDO mode */
+ force_continuous_enable(wm8350, dcdc, 0);
+ wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+ break;
+ }
+
+ return 0;
+}
+
+static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev);
+ u16 mask, sleep, active, force;
+ int mode = REGULATOR_MODE_NORMAL;
+
+ if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+ return -EINVAL;
+
+ if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+ return -EINVAL;
+
+ mask = 1 << (dcdc - WM8350_DCDC_1);
+ active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
+ sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
+ force = wm8350_reg_read(wm8350, WM8350_DCDC1_FORCE_PWM)
+ & WM8350_DCDC1_FORCE_PWM_ENA;
+ dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
+ mask, active, sleep, force);
+
+ if (active && !sleep) {
+ if (force)
+ mode = REGULATOR_MODE_FAST;
+ else
+ mode = REGULATOR_MODE_NORMAL;
+ } else if (!active && !sleep)
+ mode = REGULATOR_MODE_IDLE;
+ else if (!sleep)
+ mode = REGULATOR_MODE_STANDBY;
+
+ return mode;
+}
+
+static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
+{
+ return REGULATOR_MODE_NORMAL;
+}
+
+struct wm8350_dcdc_efficiency {
+ int uA_load_min;
+ int uA_load_max;
+ unsigned int mode;
+};
+
+static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
+ {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
+ {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
+ {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+ {-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
+ {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */
+ {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */
+ {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+ {-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
+{
+ int i = 0;
+
+ while (eff[i].uA_load_min != -1) {
+ if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
+ return eff[i].mode;
+ }
+ return REGULATOR_MODE_NORMAL;
+}
+
+/* Query the regulator for it's most efficient mode @ uV,uA
+ * WM8350 regulator efficiency is pretty similar over
+ * different input and output uV.
+ */
+static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV,
+ int output_uA)
+{
+ int dcdc = rdev_get_id(rdev), mode;
+
+ switch (dcdc) {
+ case WM8350_DCDC_1:
+ case WM8350_DCDC_6:
+ mode = get_mode(output_uA, dcdc1_6_efficiency);
+ break;
+ case WM8350_DCDC_3:
+ case WM8350_DCDC_4:
+ mode = get_mode(output_uA, dcdc3_4_efficiency);
+ break;
+ default:
+ mode = REGULATOR_MODE_NORMAL;
+ break;
+ }
+ return mode;
+}
+
+static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int dcdc = rdev_get_id(rdev), shift;
+
+ if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+ return -EINVAL;
+
+ shift = dcdc - WM8350_DCDC_1;
+ return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+ & (1 << shift);
+}
+
+static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
+{
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+ int ldo = rdev_get_id(rdev), shift;
+
+ if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+ return -EINVAL;
+
+ shift = (ldo - WM8350_LDO_1) + 8;
+ return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+ & (1 << shift);
+}
+
+static struct regulator_ops wm8350_dcdc_ops = {
+ .set_voltage = wm8350_dcdc_set_voltage,
+ .get_voltage = wm8350_dcdc_get_voltage,
+ .enable = wm8350_dcdc_enable,
+ .disable = wm8350_dcdc_disable,
+ .get_mode = wm8350_dcdc_get_mode,
+ .set_mode = wm8350_dcdc_set_mode,
+ .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
+ .is_enabled = wm8350_dcdc_is_enabled,
+ .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
+ .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
+ .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
+ .set_suspend_mode = wm8350_dcdc_set_suspend_mode,
+};
+
+static struct regulator_ops wm8350_dcdc2_5_ops = {
+ .enable = wm8350_dcdc_enable,
+ .disable = wm8350_dcdc_disable,
+ .is_enabled = wm8350_dcdc_is_enabled,
+ .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
+ .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_ldo_ops = {
+ .set_voltage = wm8350_ldo_set_voltage,
+ .get_voltage = wm8350_ldo_get_voltage,
+ .enable = wm8350_ldo_enable,
+ .disable = wm8350_ldo_disable,
+ .is_enabled = wm8350_ldo_is_enabled,
+ .get_mode = wm8350_ldo_get_mode,
+ .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
+ .set_suspend_enable = wm8350_ldo_set_suspend_enable,
+ .set_suspend_disable = wm8350_ldo_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_isink_ops = {
+ .set_current_limit = wm8350_isink_set_current,
+ .get_current_limit = wm8350_isink_get_current,
+ .enable = wm8350_isink_enable,
+ .disable = wm8350_isink_disable,
+ .is_enabled = wm8350_isink_is_enabled,
+};
+
+static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
+ {
+ .name = "DCDC1",
+ .id = WM8350_DCDC_1,
+ .ops = &wm8350_dcdc_ops,
+ .irq = WM8350_IRQ_UV_DC1,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC2",
+ .id = WM8350_DCDC_2,
+ .ops = &wm8350_dcdc2_5_ops,
+ .irq = WM8350_IRQ_UV_DC2,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC3",
+ .id = WM8350_DCDC_3,
+ .ops = &wm8350_dcdc_ops,
+ .irq = WM8350_IRQ_UV_DC3,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC4",
+ .id = WM8350_DCDC_4,
+ .ops = &wm8350_dcdc_ops,
+ .irq = WM8350_IRQ_UV_DC4,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC5",
+ .id = WM8350_DCDC_5,
+ .ops = &wm8350_dcdc2_5_ops,
+ .irq = WM8350_IRQ_UV_DC5,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC6",
+ .id = WM8350_DCDC_6,
+ .ops = &wm8350_dcdc_ops,
+ .irq = WM8350_IRQ_UV_DC6,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO1",
+ .id = WM8350_LDO_1,
+ .ops = &wm8350_ldo_ops,
+ .irq = WM8350_IRQ_UV_LDO1,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO2",
+ .id = WM8350_LDO_2,
+ .ops = &wm8350_ldo_ops,
+ .irq = WM8350_IRQ_UV_LDO2,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO3",
+ .id = WM8350_LDO_3,
+ .ops = &wm8350_ldo_ops,
+ .irq = WM8350_IRQ_UV_LDO3,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO4",
+ .id = WM8350_LDO_4,
+ .ops = &wm8350_ldo_ops,
+ .irq = WM8350_IRQ_UV_LDO4,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ISINKA",
+ .id = WM8350_ISINK_A,
+ .ops = &wm8350_isink_ops,
+ .irq = WM8350_IRQ_CS1,
+ .type = REGULATOR_CURRENT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ISINKB",
+ .id = WM8350_ISINK_B,
+ .ops = &wm8350_isink_ops,
+ .irq = WM8350_IRQ_CS2,
+ .type = REGULATOR_CURRENT,
+ .owner = THIS_MODULE,
+ },
+};
+
+static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+ struct regulator_dev *rdev = (struct regulator_dev *)data;
+
+ if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
+ regulator_notifier_call_chain(rdev,
+ REGULATOR_EVENT_REGULATION_OUT,
+ wm8350);
+ else
+ regulator_notifier_call_chain(rdev,
+ REGULATOR_EVENT_UNDER_VOLTAGE,
+ wm8350);
+}
+
+static int wm8350_regulator_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+ struct regulator_dev *rdev;
+ int ret;
+ u16 val;
+
+ if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
+ return -ENODEV;
+
+ /* do any regulatior specific init */
+ switch (pdev->id) {
+ case WM8350_DCDC_1:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+ wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ break;
+ case WM8350_DCDC_3:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+ wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ break;
+ case WM8350_DCDC_4:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+ wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ break;
+ case WM8350_DCDC_6:
+ val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+ wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+ break;
+ }
+
+
+ /* register regulator */
+ rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
+ dev_get_drvdata(&pdev->dev));
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ wm8350_reg[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ /* register regulator IRQ */
+ ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
+ pmic_uv_handler, rdev);
+ if (ret < 0) {
+ regulator_unregister(rdev);
+ dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
+ wm8350_reg[pdev->id].name);
+ return ret;
+ }
+
+ wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+ return 0;
+}
+
+static int wm8350_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+
+ wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq);
+ wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (wm8350->pmic.pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("wm8350-regulator", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ wm8350->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = wm8350;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = wm8350->dev;
+ platform_set_drvdata(pdev, wm8350);
+
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ wm8350->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_regulator);
+
+static struct platform_driver wm8350_regulator_driver = {
+ .probe = wm8350_regulator_probe,
+ .remove = wm8350_regulator_remove,
+ .driver = {
+ .name = "wm8350-regulator",
+ },
+};
+
+static int __init wm8350_regulator_init(void)
+{
+ return platform_driver_register(&wm8350_regulator_driver);
+}
+subsys_initcall(wm8350_regulator_init);
+
+static void __exit wm8350_regulator_exit(void)
+{
+ platform_driver_unregister(&wm8350_regulator_driver);
+}
+module_exit(wm8350_regulator_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
new file mode 100644
index 00000000000..48b372e038a
--- /dev/null
+++ b/drivers/regulator/wm8400-regulator.c
@@ -0,0 +1,368 @@
+/*
+ * Regulator support for WM8400
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/wm8400-private.h>
+
+static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ u16 val;
+
+ val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+ return (val & WM8400_LDO1_ENA) != 0;
+}
+
+static int wm8400_ldo_enable(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+ return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+ WM8400_LDO1_ENA, WM8400_LDO1_ENA);
+}
+
+static int wm8400_ldo_disable(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+ return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+ WM8400_LDO1_ENA, 0);
+}
+
+static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ u16 val;
+
+ val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+ val &= WM8400_LDO1_VSEL_MASK;
+
+ if (val < 15)
+ return 900000 + (val * 50000);
+ else
+ return 1600000 + ((val - 14) * 100000);
+}
+
+static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ u16 val;
+
+ if (min_uV < 900000 || min_uV > 3300000)
+ return -EINVAL;
+
+ if (min_uV < 1700000) {
+ /* Steps of 50mV from 900mV; */
+ val = (min_uV - 850001) / 50000;
+
+ if ((val * 50000) + 900000 > max_uV)
+ return -EINVAL;
+ BUG_ON((val * 50000) + 900000 < min_uV);
+ } else {
+ /* Steps of 100mV from 1700mV */
+ val = ((min_uV - 1600001) / 100000);
+
+ if ((val * 100000) + 1700000 > max_uV)
+ return -EINVAL;
+ BUG_ON((val * 100000) + 1700000 < min_uV);
+
+ val += 0xf;
+ }
+
+ return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+ WM8400_LDO1_VSEL_MASK, val);
+}
+
+static struct regulator_ops wm8400_ldo_ops = {
+ .is_enabled = wm8400_ldo_is_enabled,
+ .enable = wm8400_ldo_enable,
+ .disable = wm8400_ldo_disable,
+ .get_voltage = wm8400_ldo_get_voltage,
+ .set_voltage = wm8400_ldo_set_voltage,
+};
+
+static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+ u16 val;
+
+ val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+ return (val & WM8400_DC1_ENA) != 0;
+}
+
+static int wm8400_dcdc_enable(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_ENA, WM8400_DC1_ENA);
+}
+
+static int wm8400_dcdc_disable(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_ENA, 0);
+}
+
+static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ u16 val;
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+ val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+ val &= WM8400_DC1_VSEL_MASK;
+
+ return 850000 + (25000 * val);
+}
+
+static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ u16 val;
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+ if (min_uV < 850000)
+ return -EINVAL;
+
+ val = (min_uV - 825001) / 25000;
+
+ if (850000 + (25000 * val) > max_uV)
+ return -EINVAL;
+ BUG_ON(850000 + (25000 * val) < min_uV);
+
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_VSEL_MASK, val);
+}
+
+static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+ u16 data[2];
+ int ret;
+
+ ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2,
+ data);
+ if (ret != 0)
+ return 0;
+
+ /* Datasheet: hibernate */
+ if (data[0] & WM8400_DC1_SLEEP)
+ return REGULATOR_MODE_STANDBY;
+
+ /* Datasheet: standby */
+ if (!(data[0] & WM8400_DC1_ACTIVE))
+ return REGULATOR_MODE_IDLE;
+
+ /* Datasheet: active with or without force PWM */
+ if (data[1] & WM8400_DC1_FRC_PWM)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+ struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+ int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+ int ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ /* Datasheet: active with force PWM */
+ ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+ WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
+ if (ret != 0)
+ return ret;
+
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+ WM8400_DC1_ACTIVE);
+
+ case REGULATOR_MODE_NORMAL:
+ /* Datasheet: active */
+ ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+ WM8400_DC1_FRC_PWM, 0);
+ if (ret != 0)
+ return ret;
+
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+ WM8400_DC1_ACTIVE);
+
+ case REGULATOR_MODE_IDLE:
+ /* Datasheet: standby */
+ ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_ACTIVE, 0);
+ if (ret != 0)
+ return ret;
+ return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+ WM8400_DC1_SLEEP, 0);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
+ int input_uV, int output_uV,
+ int load_uA)
+{
+ return REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops wm8400_dcdc_ops = {
+ .is_enabled = wm8400_dcdc_is_enabled,
+ .enable = wm8400_dcdc_enable,
+ .disable = wm8400_dcdc_disable,
+ .get_voltage = wm8400_dcdc_get_voltage,
+ .set_voltage = wm8400_dcdc_set_voltage,
+ .get_mode = wm8400_dcdc_get_mode,
+ .set_mode = wm8400_dcdc_set_mode,
+ .get_optimum_mode = wm8400_dcdc_get_optimum_mode,
+};
+
+static struct regulator_desc regulators[] = {
+ {
+ .name = "LDO1",
+ .id = WM8400_LDO1,
+ .ops = &wm8400_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO2",
+ .id = WM8400_LDO2,
+ .ops = &wm8400_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO3",
+ .id = WM8400_LDO3,
+ .ops = &wm8400_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO4",
+ .id = WM8400_LDO4,
+ .ops = &wm8400_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC1",
+ .id = WM8400_DCDC1,
+ .ops = &wm8400_dcdc_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC2",
+ .id = WM8400_DCDC2,
+ .ops = &wm8400_dcdc_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init wm8400_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
+ pdev->dev.driver_data);
+
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+
+ return 0;
+}
+
+static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+static struct platform_driver wm8400_regulator_driver = {
+ .driver = {
+ .name = "wm8400-regulator",
+ },
+ .probe = wm8400_regulator_probe,
+ .remove = __devexit_p(wm8400_regulator_remove),
+};
+
+/**
+ * wm8400_register_regulator - enable software control of a WM8400 regulator
+ *
+ * This function enables software control of a WM8400 regulator via
+ * the regulator API. It is intended to be called from the
+ * platform_init() callback of the WM8400 MFD driver.
+ *
+ * @param dev The WM8400 device to operate on.
+ * @param reg The regulator to control.
+ * @param initdata Regulator initdata for the regulator.
+ */
+int wm8400_register_regulator(struct device *dev, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct wm8400 *wm8400 = dev->driver_data;
+
+ if (wm8400->regulators[reg].name)
+ return -EBUSY;
+
+ initdata->driver_data = wm8400;
+
+ wm8400->regulators[reg].name = "wm8400-regulator";
+ wm8400->regulators[reg].id = reg;
+ wm8400->regulators[reg].dev.parent = dev;
+ wm8400->regulators[reg].dev.driver_data = wm8400;
+ wm8400->regulators[reg].dev.platform_data = initdata;
+
+ return platform_device_register(&wm8400->regulators[reg]);
+}
+EXPORT_SYMBOL_GPL(wm8400_register_regulator);
+
+static int __init wm8400_regulator_init(void)
+{
+ return platform_driver_register(&wm8400_regulator_driver);
+}
+module_init(wm8400_regulator_init);
+
+static void __exit wm8400_regulator_exit(void)
+{
+ platform_driver_unregister(&wm8400_regulator_driver);
+}
+module_exit(wm8400_regulator_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM8400 regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8400-regulator");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9a9755c92fa..f660ef3e5b2 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -220,22 +220,22 @@ config RTC_DRV_PCF8583
will be called rtc-pcf8583.
config RTC_DRV_M41T80
- tristate "ST M41T80/81/82/83/84/85/87"
+ tristate "ST M41T65/M41T80/81/82/83/84/85/87"
help
- If you say Y here you will get support for the
- ST M41T80 RTC chips series. Currently following chips are
- supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85
- and M41ST87.
+ If you say Y here you will get support for the ST M41T60
+ and M41T80 RTC chips series. Currently, the following chips are
+ supported: M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84,
+ M41ST85, and M41ST87.
This driver can also be built as a module. If so, the module
will be called rtc-m41t80.
config RTC_DRV_M41T80_WDT
- bool "ST M41T80 series RTC watchdog timer"
+ bool "ST M41T65/M41T80 series RTC watchdog timer"
depends on RTC_DRV_M41T80
help
If you say Y here you will get support for the
- watchdog timer in ST M41T80 RTC chips series.
+ watchdog timer in the ST M41T60 and M41T80 RTC chips series.
config RTC_DRV_TWL92330
boolean "TI TWL92330/Menelaus"
@@ -319,6 +319,15 @@ config RTC_DRV_RS5C348
This driver can also be built as a module. If so, the module
will be called rtc-rs5c348.
+config RTC_DRV_DS3234
+ tristate "Maxim/Dallas DS3234"
+ help
+ If you say yes here you get support for the
+ Maxim/Dallas DS3234 SPI RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds3234.
+
endif # SPI_MASTER
comment "Platform RTC drivers"
@@ -329,7 +338,7 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
- depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS
+ depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64
default y if X86
help
Say "yes" here to get direct support for the real time clock
@@ -352,6 +361,11 @@ config RTC_DRV_DS1216
help
If you say yes here you get support for the Dallas DS1216 RTC chips.
+config RTC_DRV_DS1286
+ tristate "Dallas DS1286"
+ help
+ If you say yes here you get support for the Dallas DS1286 RTC chips.
+
config RTC_DRV_DS1302
tristate "Dallas DS1302"
depends on SH_SECUREEDGE5410
@@ -405,15 +419,36 @@ config RTC_DRV_M48T86
This driver can also be built as a module. If so, the module
will be called rtc-m48t86.
+config RTC_DRV_M48T35
+ tristate "ST M48T35"
+ help
+ If you say Y here you will get support for the
+ ST M48T35 RTC chip.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-m48t35".
+
config RTC_DRV_M48T59
- tristate "ST M48T59"
+ tristate "ST M48T59/M48T08/M48T02"
help
If you say Y here you will get support for the
- ST M48T59 RTC chip.
+ ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
+
+ These chips are usually found in Sun SPARC and UltraSPARC
+ workstations.
This driver can also be built as a module, if so, the module
will be called "rtc-m48t59".
+config RTC_DRV_BQ4802
+ tristate "TI BQ4802"
+ help
+ If you say Y here you will get support for the TI
+ BQ4802 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-bq4802.
+
config RTC_DRV_V3020
tristate "EM Microelectronic V3020"
help
@@ -577,10 +612,24 @@ config RTC_DRV_RS5C313
config RTC_DRV_PPC
tristate "PowerPC machine dependent RTC support"
- depends on PPC_MERGE
+ depends on PPC
help
The PowerPC kernel has machine-specific functions for accessing
the RTC. This exposes that functionality through the generic RTC
class.
+config RTC_DRV_SUN4V
+ bool "SUN4V Hypervisor RTC"
+ depends on SPARC64
+ help
+ If you say Y here you will get support for the Hypervisor
+ based RTC on SUN4V systems.
+
+config RTC_DRV_STARFIRE
+ bool "Starfire RTC"
+ depends on SPARC64
+ help
+ If you say Y here you will get support for the RTC found on
+ Starfire systems.
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 18622ef84ca..d05928b3ca9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
+obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
@@ -31,13 +32,18 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o
obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
+obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
+obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
+obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
+obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
+obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 4e888cc8be5..37082616482 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -29,10 +29,10 @@
#include <linux/completion.h>
#include <asm/uaccess.h>
+
#include <mach/at91_rtc.h>
-#define AT91_RTC_FREQ 1
#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */
static DECLARE_COMPLETION(at91_rtc_updated);
@@ -228,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
(imr & AT91_RTC_SECEV) ? "yes" : "no");
- seq_printf(seq, "periodic_freq\t: %ld\n",
- (unsigned long) AT91_RTC_FREQ);
return 0;
}
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
new file mode 100644
index 00000000000..189a018bdf3
--- /dev/null
+++ b/drivers/rtc/rtc-bq4802.c
@@ -0,0 +1,230 @@
+/* rtc-bq4802.c: TI BQ4802 RTC driver.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("TI BQ4802 RTC driver");
+MODULE_LICENSE("GPL");
+
+struct bq4802 {
+ void __iomem *regs;
+ unsigned long ioport;
+ struct rtc_device *rtc;
+ spinlock_t lock;
+ struct resource *r;
+ u8 (*read)(struct bq4802 *, int);
+ void (*write)(struct bq4802 *, int, u8);
+};
+
+static u8 bq4802_read_io(struct bq4802 *p, int off)
+{
+ return inb(p->ioport + off);
+}
+
+static void bq4802_write_io(struct bq4802 *p, int off, u8 val)
+{
+ outb(val, p->ioport + off);
+}
+
+static u8 bq4802_read_mem(struct bq4802 *p, int off)
+{
+ return readb(p->regs + off);
+}
+
+static void bq4802_write_mem(struct bq4802 *p, int off, u8 val)
+{
+ writeb(val, p->regs + off);
+}
+
+static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct bq4802 *p = platform_get_drvdata(pdev);
+ unsigned long flags;
+ unsigned int century;
+ u8 val;
+
+ spin_lock_irqsave(&p->lock, flags);
+
+ val = p->read(p, 0x0e);
+ p->write(p, 0xe, val | 0x08);
+
+ tm->tm_sec = p->read(p, 0x00);
+ tm->tm_min = p->read(p, 0x02);
+ tm->tm_hour = p->read(p, 0x04);
+ tm->tm_mday = p->read(p, 0x06);
+ tm->tm_mon = p->read(p, 0x09);
+ tm->tm_year = p->read(p, 0x0a);
+ tm->tm_wday = p->read(p, 0x08);
+ century = p->read(p, 0x0f);
+
+ p->write(p, 0x0e, val);
+
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ BCD_TO_BIN(tm->tm_sec);
+ BCD_TO_BIN(tm->tm_min);
+ BCD_TO_BIN(tm->tm_hour);
+ BCD_TO_BIN(tm->tm_mday);
+ BCD_TO_BIN(tm->tm_mon);
+ BCD_TO_BIN(tm->tm_year);
+ BCD_TO_BIN(tm->tm_wday);
+ BCD_TO_BIN(century);
+
+ tm->tm_year += (century * 100);
+ tm->tm_year -= 1900;
+
+ tm->tm_mon--;
+
+ return 0;
+}
+
+static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct bq4802 *p = platform_get_drvdata(pdev);
+ u8 sec, min, hrs, day, mon, yrs, century, val;
+ unsigned long flags;
+ unsigned int year;
+
+ year = tm->tm_year + 1900;
+ century = year / 100;
+ yrs = year % 100;
+
+ mon = tm->tm_mon + 1; /* tm_mon starts at zero */
+ day = tm->tm_mday;
+ hrs = tm->tm_hour;
+ min = tm->tm_min;
+ sec = tm->tm_sec;
+
+ BIN_TO_BCD(sec);
+ BIN_TO_BCD(min);
+ BIN_TO_BCD(hrs);
+ BIN_TO_BCD(day);
+ BIN_TO_BCD(mon);
+ BIN_TO_BCD(yrs);
+ BIN_TO_BCD(century);
+
+ spin_lock_irqsave(&p->lock, flags);
+
+ val = p->read(p, 0x0e);
+ p->write(p, 0x0e, val | 0x08);
+
+ p->write(p, 0x00, sec);
+ p->write(p, 0x02, min);
+ p->write(p, 0x04, hrs);
+ p->write(p, 0x06, day);
+ p->write(p, 0x09, mon);
+ p->write(p, 0x0a, yrs);
+ p->write(p, 0x0f, century);
+
+ p->write(p, 0x0e, val);
+
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ return 0;
+}
+
+static const struct rtc_class_ops bq4802_ops = {
+ .read_time = bq4802_read_time,
+ .set_time = bq4802_set_time,
+};
+
+static int __devinit bq4802_probe(struct platform_device *pdev)
+{
+ struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ int err = -ENOMEM;
+
+ if (!p)
+ goto out;
+
+ spin_lock_init(&p->lock);
+
+ p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!p->r) {
+ p->r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ err = -EINVAL;
+ if (!p->r)
+ goto out_free;
+ }
+ if (p->r->flags & IORESOURCE_IO) {
+ p->ioport = p->r->start;
+ p->read = bq4802_read_io;
+ p->write = bq4802_write_io;
+ } else if (p->r->flags & IORESOURCE_MEM) {
+ p->regs = ioremap(p->r->start, resource_size(p->r));
+ p->read = bq4802_read_mem;
+ p->write = bq4802_write_mem;
+ } else {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ p->rtc = rtc_device_register("bq4802", &pdev->dev,
+ &bq4802_ops, THIS_MODULE);
+ if (IS_ERR(p->rtc)) {
+ err = PTR_ERR(p->rtc);
+ goto out_iounmap;
+ }
+
+ platform_set_drvdata(pdev, p);
+ err = 0;
+out:
+ return err;
+
+out_iounmap:
+ if (p->r->flags & IORESOURCE_MEM)
+ iounmap(p->regs);
+out_free:
+ kfree(p);
+ goto out;
+}
+
+static int __devexit bq4802_remove(struct platform_device *pdev)
+{
+ struct bq4802 *p = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(p->rtc);
+ if (p->r->flags & IORESOURCE_MEM)
+ iounmap(p->regs);
+
+ platform_set_drvdata(pdev, NULL);
+
+ kfree(p);
+
+ return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:rtc-bq4802");
+
+static struct platform_driver bq4802_driver = {
+ .driver = {
+ .name = "rtc-bq4802",
+ .owner = THIS_MODULE,
+ },
+ .probe = bq4802_probe,
+ .remove = __devexit_p(bq4802_remove),
+};
+
+static int __init bq4802_init(void)
+{
+ return platform_driver_register(&bq4802_driver);
+}
+
+static void __exit bq4802_exit(void)
+{
+ platform_driver_unregister(&bq4802_driver);
+}
+
+module_init(bq4802_init);
+module_exit(bq4802_exit);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 6ea349aba3b..963ad0b6a4e 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -636,7 +636,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
*/
#if defined(CONFIG_ATARI)
address_space = 64;
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__)
address_space = 128;
#else
#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@@ -699,7 +699,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
/* FIXME teach the alarm code how to handle binary mode;
* <asm-generic/rtc.h> doesn't know 12-hour mode either.
*/
- if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) {
+ if (is_valid_irq(rtc_irq) &&
+ (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) {
dev_dbg(dev, "only 24-hr BCD mode supported\n");
retval = -ENXIO;
goto cleanup1;
@@ -800,7 +801,6 @@ static void __exit cmos_do_remove(struct device *dev)
static int cmos_suspend(struct device *dev, pm_message_t mesg)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- int do_wake = device_may_wakeup(dev);
unsigned char tmp;
/* only the alarm might be a wakeup event source */
@@ -809,7 +809,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
unsigned char mask;
- if (do_wake)
+ if (device_may_wakeup(dev))
mask = RTC_IRQMASK & ~RTC_AIE;
else
mask = RTC_IRQMASK;
@@ -837,6 +837,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
return 0;
}
+/* We want RTC alarms to wake us from e.g. ACPI G2/S5 "soft off", even
+ * after a detour through G3 "mechanical off", although the ACPI spec
+ * says wakeup should only work from G1/S4 "hibernate". To most users,
+ * distinctions between S4 and S5 are pointless. So when the hardware
+ * allows, don't draw that distinction.
+ */
+static inline int cmos_poweroff(struct device *dev)
+{
+ return cmos_suspend(dev, PMSG_HIBERNATE);
+}
+
static int cmos_resume(struct device *dev)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -884,6 +895,12 @@ static int cmos_resume(struct device *dev)
#else
#define cmos_suspend NULL
#define cmos_resume NULL
+
+static inline int cmos_poweroff(struct device *dev)
+{
+ return -ENOSYS;
+}
+
#endif
/*----------------------------------------------------------------*/
@@ -896,6 +913,92 @@ static int cmos_resume(struct device *dev)
* predate even PNPBIOS should set up platform_bus devices.
*/
+#ifdef CONFIG_ACPI
+
+#include <linux/acpi.h>
+
+#ifdef CONFIG_PM
+static u32 rtc_handler(void *context)
+{
+ acpi_clear_event(ACPI_EVENT_RTC);
+ acpi_disable_event(ACPI_EVENT_RTC, 0);
+ return ACPI_INTERRUPT_HANDLED;
+}
+
+static inline void rtc_wake_setup(void)
+{
+ acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+ /*
+ * After the RTC handler is installed, the Fixed_RTC event should
+ * be disabled. Only when the RTC alarm is set will it be enabled.
+ */
+ acpi_clear_event(ACPI_EVENT_RTC);
+ acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_on(struct device *dev)
+{
+ acpi_clear_event(ACPI_EVENT_RTC);
+ acpi_enable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+ acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+#else
+#define rtc_wake_setup() do{}while(0)
+#define rtc_wake_on NULL
+#define rtc_wake_off NULL
+#endif
+
+/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
+ * its device node and pass extra config data. This helps its driver use
+ * capabilities that the now-obsolete mc146818 didn't have, and informs it
+ * that this board's RTC is wakeup-capable (per ACPI spec).
+ */
+static struct cmos_rtc_board_info acpi_rtc_info;
+
+static void __devinit
+cmos_wake_setup(struct device *dev)
+{
+ if (acpi_disabled)
+ return;
+
+ rtc_wake_setup();
+ acpi_rtc_info.wake_on = rtc_wake_on;
+ acpi_rtc_info.wake_off = rtc_wake_off;
+
+ /* workaround bug in some ACPI tables */
+ if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
+ dev_dbg(dev, "bogus FADT month_alarm (%d)\n",
+ acpi_gbl_FADT.month_alarm);
+ acpi_gbl_FADT.month_alarm = 0;
+ }
+
+ acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
+ acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
+ acpi_rtc_info.rtc_century = acpi_gbl_FADT.century;
+
+ /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */
+ if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
+ dev_info(dev, "RTC can wake from S4\n");
+
+ dev->platform_data = &acpi_rtc_info;
+
+ /* RTC always wakes from S1/S2/S3, and often S4/STD */
+ device_init_wakeup(dev, 1);
+}
+
+#else
+
+static void __devinit
+cmos_wake_setup(struct device *dev)
+{
+}
+
+#endif
+
#ifdef CONFIG_PNP
#include <linux/pnp.h>
@@ -903,10 +1006,8 @@ static int cmos_resume(struct device *dev)
static int __devinit
cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
{
- /* REVISIT paranoia argues for a shutdown notifier, since PNP
- * drivers can't provide shutdown() methods to disable IRQs.
- * Or better yet, fix PNP to allow those methods...
- */
+ cmos_wake_setup(&pnp->dev);
+
if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
/* Some machines contain a PNP entry for the RTC, but
* don't define the IRQ. It should always be safe to
@@ -942,6 +1043,13 @@ static int cmos_pnp_resume(struct pnp_dev *pnp)
#define cmos_pnp_resume NULL
#endif
+static void cmos_pnp_shutdown(struct device *pdev)
+{
+ if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev))
+ return;
+
+ cmos_do_shutdown();
+}
static const struct pnp_device_id rtc_ids[] = {
{ .id = "PNP0b00", },
@@ -961,6 +1069,10 @@ static struct pnp_driver cmos_pnp_driver = {
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
.suspend = cmos_pnp_suspend,
.resume = cmos_pnp_resume,
+ .driver = {
+ .name = (char *)driver_name,
+ .shutdown = cmos_pnp_shutdown,
+ }
};
#endif /* CONFIG_PNP */
@@ -973,6 +1085,7 @@ static struct pnp_driver cmos_pnp_driver = {
static int __init cmos_platform_probe(struct platform_device *pdev)
{
+ cmos_wake_setup(&pdev->dev);
return cmos_do_probe(&pdev->dev,
platform_get_resource(pdev, IORESOURCE_IO, 0),
platform_get_irq(pdev, 0));
@@ -986,6 +1099,9 @@ static int __exit cmos_platform_remove(struct platform_device *pdev)
static void cmos_platform_shutdown(struct platform_device *pdev)
{
+ if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev))
+ return;
+
cmos_do_shutdown();
}
@@ -1004,29 +1120,32 @@ static struct platform_driver cmos_platform_driver = {
static int __init cmos_init(void)
{
+ int retval = 0;
+
#ifdef CONFIG_PNP
- if (pnp_platform_devices)
- return pnp_register_driver(&cmos_pnp_driver);
- else
- return platform_driver_probe(&cmos_platform_driver,
- cmos_platform_probe);
-#else
- return platform_driver_probe(&cmos_platform_driver,
- cmos_platform_probe);
-#endif /* CONFIG_PNP */
+ pnp_register_driver(&cmos_pnp_driver);
+#endif
+
+ if (!cmos_rtc.dev)
+ retval = platform_driver_probe(&cmos_platform_driver,
+ cmos_platform_probe);
+
+ if (retval == 0)
+ return 0;
+
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&cmos_pnp_driver);
+#endif
+ return retval;
}
module_init(cmos_init);
static void __exit cmos_exit(void)
{
#ifdef CONFIG_PNP
- if (pnp_platform_devices)
- pnp_unregister_driver(&cmos_pnp_driver);
- else
- platform_driver_unregister(&cmos_platform_driver);
-#else
+ pnp_unregister_driver(&cmos_pnp_driver);
+#endif
platform_driver_unregister(&cmos_platform_driver);
-#endif /* CONFIG_PNP */
}
module_exit(cmos_exit);
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index f118252f3a9..079e9ed907e 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -422,28 +422,37 @@ done:
return err;
}
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+ struct rtc_device *rtc = file->private_data;
+ return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
static int rtc_dev_release(struct inode *inode, struct file *file)
{
struct rtc_device *rtc = file->private_data;
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
- clear_uie(rtc);
-#endif
+ /* We shut down the repeating IRQs that userspace enabled,
+ * since nothing is listening to them.
+ * - Update (UIE) ... currently only managed through ioctls
+ * - Periodic (PIE) ... also used through rtc_*() interface calls
+ *
+ * Leave the alarm alone; it may be set to trigger a system wakeup
+ * later, or be used by kernel code, and is a one-shot event anyway.
+ */
+ rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
rtc_irq_set_state(rtc, NULL, 0);
if (rtc->ops->release)
rtc->ops->release(rtc->dev.parent);
+ if (file->f_flags & FASYNC)
+ rtc_dev_fasync(-1, file, 0);
+
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
return 0;
}
-static int rtc_dev_fasync(int fd, struct file *file, int on)
-{
- struct rtc_device *rtc = file->private_data;
- return fasync_helper(fd, file, on, &rtc->async_queue);
-}
-
static const struct file_operations rtc_dev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
new file mode 100644
index 00000000000..4fcb16bbff4
--- /dev/null
+++ b/drivers/rtc/rtc-ds1286.c
@@ -0,0 +1,410 @@
+/*
+ * DS1286 Real Time Clock interface for Linux
+ *
+ * Copyright (C) 1998, 1999, 2000 Ralf Baechle
+ * Copyright (C) 2008 Thomas Bogendoerfer
+ *
+ * Based on code written by Paul Gortmaker.
+ *
+ * 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/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+#include <linux/ds1286.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "1.0"
+
+struct ds1286_priv {
+ struct rtc_device *rtc;
+ u32 __iomem *rtcregs;
+ size_t size;
+ unsigned long baseaddr;
+ spinlock_t lock;
+};
+
+static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg)
+{
+ return __raw_readl(&priv->rtcregs[reg]) & 0xff;
+}
+
+static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg)
+{
+ __raw_writel(data, &priv->rtcregs[reg]);
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned long flags;
+ unsigned char val;
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ /* Mask alarm int. enab. bit */
+ spin_lock_irqsave(&priv->lock, flags);
+ val = ds1286_rtc_read(priv, RTC_CMD);
+ val |= RTC_TDM;
+ ds1286_rtc_write(priv, val, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ break;
+ case RTC_AIE_ON:
+ /* Allow alarm interrupts. */
+ spin_lock_irqsave(&priv->lock, flags);
+ val = ds1286_rtc_read(priv, RTC_CMD);
+ val &= ~RTC_TDM;
+ ds1286_rtc_write(priv, val, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ break;
+ case RTC_WIE_OFF:
+ /* Mask watchdog int. enab. bit */
+ spin_lock_irqsave(&priv->lock, flags);
+ val = ds1286_rtc_read(priv, RTC_CMD);
+ val |= RTC_WAM;
+ ds1286_rtc_write(priv, val, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ break;
+ case RTC_WIE_ON:
+ /* Allow watchdog interrupts. */
+ spin_lock_irqsave(&priv->lock, flags);
+ val = ds1286_rtc_read(priv, RTC_CMD);
+ val &= ~RTC_WAM;
+ ds1286_rtc_write(priv, val, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+#else
+#define ds1286_ioctl NULL
+#endif
+
+#ifdef CONFIG_PROC_FS
+
+static int ds1286_proc(struct device *dev, struct seq_file *seq)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned char month, cmd, amode;
+ const char *s;
+
+ month = ds1286_rtc_read(priv, RTC_MONTH);
+ seq_printf(seq,
+ "oscillator\t: %s\n"
+ "square_wave\t: %s\n",
+ (month & RTC_EOSC) ? "disabled" : "enabled",
+ (month & RTC_ESQW) ? "disabled" : "enabled");
+
+ amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) |
+ ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) |
+ ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7);
+ switch (amode) {
+ case 7:
+ s = "each minute";
+ break;
+ case 3:
+ s = "minutes match";
+ break;
+ case 1:
+ s = "hours and minutes match";
+ break;
+ case 0:
+ s = "days, hours and minutes match";
+ break;
+ default:
+ s = "invalid";
+ break;
+ }
+ seq_printf(seq, "alarm_mode\t: %s\n", s);
+
+ cmd = ds1286_rtc_read(priv, RTC_CMD);
+ seq_printf(seq,
+ "alarm_enable\t: %s\n"
+ "wdog_alarm\t: %s\n"
+ "alarm_mask\t: %s\n"
+ "wdog_alarm_mask\t: %s\n"
+ "interrupt_mode\t: %s\n"
+ "INTB_mode\t: %s_active\n"
+ "interrupt_pins\t: %s\n",
+ (cmd & RTC_TDF) ? "yes" : "no",
+ (cmd & RTC_WAF) ? "yes" : "no",
+ (cmd & RTC_TDM) ? "disabled" : "enabled",
+ (cmd & RTC_WAM) ? "disabled" : "enabled",
+ (cmd & RTC_PU_LVL) ? "pulse" : "level",
+ (cmd & RTC_IBH_LO) ? "low" : "high",
+ (cmd & RTC_IPSW) ? "unswapped" : "swapped");
+ return 0;
+}
+
+#else
+#define ds1286_proc NULL
+#endif
+
+static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned char save_control;
+ unsigned long flags;
+ unsigned long uip_watchdog = jiffies;
+
+ /*
+ * read RTC once any update in progress is done. The update
+ * can take just over 2ms. We wait 10 to 20ms. There is no need to
+ * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+ * If you need to know *exactly* when a second has started, enable
+ * periodic update complete interrupts, (via ioctl) and then
+ * immediately read /dev/rtc which will block until you get the IRQ.
+ * Once the read clears, read the RTC time (again via ioctl). Easy.
+ */
+
+ if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE)
+ while (time_before(jiffies, uip_watchdog + 2*HZ/100))
+ barrier();
+
+ /*
+ * Only the values that we read from the RTC are set. We leave
+ * tm_wday, tm_yday and tm_isdst untouched. Even though the
+ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+ * by the RTC when initially set to a non-zero value.
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+ save_control = ds1286_rtc_read(priv, RTC_CMD);
+ ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
+
+ tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS);
+ tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES);
+ tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f;
+ tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE);
+ tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f;
+ tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR);
+
+ ds1286_rtc_write(priv, save_control, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ tm->tm_sec = bcd2bin(tm->tm_sec);
+ tm->tm_min = bcd2bin(tm->tm_min);
+ tm->tm_hour = bcd2bin(tm->tm_hour);
+ tm->tm_mday = bcd2bin(tm->tm_mday);
+ tm->tm_mon = bcd2bin(tm->tm_mon);
+ tm->tm_year = bcd2bin(tm->tm_year);
+
+ /*
+ * Account for differences between how the RTC uses the values
+ * and how they are defined in a struct rtc_time;
+ */
+ if (tm->tm_year < 45)
+ tm->tm_year += 30;
+ tm->tm_year += 40;
+ if (tm->tm_year < 70)
+ tm->tm_year += 100;
+
+ tm->tm_mon--;
+
+ return rtc_valid_tm(tm);
+}
+
+static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned char mon, day, hrs, min, sec;
+ unsigned char save_control;
+ unsigned int yrs;
+ unsigned long flags;
+
+ yrs = tm->tm_year + 1900;
+ mon = tm->tm_mon + 1; /* tm_mon starts at zero */
+ day = tm->tm_mday;
+ hrs = tm->tm_hour;
+ min = tm->tm_min;
+ sec = tm->tm_sec;
+
+ if (yrs < 1970)
+ return -EINVAL;
+
+ yrs -= 1940;
+ if (yrs > 255) /* They are unsigned */
+ return -EINVAL;
+
+ if (yrs >= 100)
+ yrs -= 100;
+
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ save_control = ds1286_rtc_read(priv, RTC_CMD);
+ ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
+
+ ds1286_rtc_write(priv, yrs, RTC_YEAR);
+ ds1286_rtc_write(priv, mon, RTC_MONTH);
+ ds1286_rtc_write(priv, day, RTC_DATE);
+ ds1286_rtc_write(priv, hrs, RTC_HOURS);
+ ds1286_rtc_write(priv, min, RTC_MINUTES);
+ ds1286_rtc_write(priv, sec, RTC_SECONDS);
+ ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND);
+
+ ds1286_rtc_write(priv, save_control, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+}
+
+static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned char cmd;
+ unsigned long flags;
+
+ /*
+ * Only the values that we read from the RTC are set. That
+ * means only tm_wday, tm_hour, tm_min.
+ */
+ spin_lock_irqsave(&priv->lock, flags);
+ alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;
+ alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x1f;
+ alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x07;
+ cmd = ds1286_rtc_read(priv, RTC_CMD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ alm->time.tm_min = bcd2bin(alm->time.tm_min);
+ alm->time.tm_hour = bcd2bin(alm->time.tm_hour);
+ alm->time.tm_sec = 0;
+ return 0;
+}
+
+static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1286_priv *priv = dev_get_drvdata(dev);
+ unsigned char hrs, min, sec;
+
+ hrs = alm->time.tm_hour;
+ min = alm->time.tm_min;
+ sec = alm->time.tm_sec;
+
+ if (hrs >= 24)
+ hrs = 0xff;
+
+ if (min >= 60)
+ min = 0xff;
+
+ if (sec != 0)
+ return -EINVAL;
+
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+
+ spin_lock(&priv->lock);
+ ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM);
+ ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM);
+ spin_unlock(&priv->lock);
+
+ return 0;
+}
+
+static const struct rtc_class_ops ds1286_ops = {
+ .ioctl = ds1286_ioctl,
+ .proc = ds1286_proc,
+ .read_time = ds1286_read_time,
+ .set_time = ds1286_set_time,
+ .read_alarm = ds1286_read_alarm,
+ .set_alarm = ds1286_set_alarm,
+};
+
+static int __devinit ds1286_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct resource *res;
+ struct ds1286_priv *priv;
+ int ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->size = res->end - res->start + 1;
+ if (!request_mem_region(res->start, priv->size, pdev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ priv->baseaddr = res->start;
+ priv->rtcregs = ioremap(priv->baseaddr, priv->size);
+ if (!priv->rtcregs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ spin_lock_init(&priv->lock);
+ rtc = rtc_device_register("ds1286", &pdev->dev,
+ &ds1286_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto out;
+ }
+ priv->rtc = rtc;
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+out:
+ if (priv->rtc)
+ rtc_device_unregister(priv->rtc);
+ if (priv->rtcregs)
+ iounmap(priv->rtcregs);
+ if (priv->baseaddr)
+ release_mem_region(priv->baseaddr, priv->size);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit ds1286_remove(struct platform_device *pdev)
+{
+ struct ds1286_priv *priv = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(priv->rtc);
+ iounmap(priv->rtcregs);
+ release_mem_region(priv->baseaddr, priv->size);
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver ds1286_platform_driver = {
+ .driver = {
+ .name = "rtc-ds1286",
+ .owner = THIS_MODULE,
+ },
+ .probe = ds1286_probe,
+ .remove = __devexit_p(ds1286_remove),
+};
+
+static int __init ds1286_init(void)
+{
+ return platform_driver_register(&ds1286_platform_driver);
+}
+
+static void __exit ds1286_exit(void)
+{
+ platform_driver_unregister(&ds1286_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("DS1286 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:rtc-ds1286");
+
+module_init(ds1286_init);
+module_exit(ds1286_exit);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index bbf97e65202..4fcf0734a6e 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -23,10 +23,6 @@
* to have set the chip up as a clock (turning on the oscillator and
* setting the date and time), Linux can ignore the non-clock features.
* That's a natural job for a factory or repair bench.
- *
- * This is currently a simple no-alarms driver. If your board has the
- * alarm irq wired up on a ds1337 or ds1339, and you want to use that,
- * then look at the rtc-rs5c372 driver for code to steal...
*/
enum ds_type {
ds_1307,
@@ -67,6 +63,7 @@ enum ds_type {
# define DS1307_BIT_RS0 0x01
#define DS1337_REG_CONTROL 0x0e
# define DS1337_BIT_nEOSC 0x80
+# define DS1339_BIT_BBSQI 0x20
# define DS1337_BIT_RS2 0x10
# define DS1337_BIT_RS1 0x08
# define DS1337_BIT_INTCN 0x04
@@ -83,19 +80,22 @@ enum ds_type {
# define DS1337_BIT_OSF 0x80
# define DS1337_BIT_A2I 0x02
# define DS1337_BIT_A1I 0x01
+#define DS1339_REG_ALARM1_SECS 0x07
#define DS1339_REG_TRICKLE 0x10
struct ds1307 {
u8 reg_addr;
- bool has_nvram;
- u8 regs[8];
+ u8 regs[11];
enum ds_type type;
+ unsigned long flags;
+#define HAS_NVRAM 0 /* bit 0 == sysfs file active */
+#define HAS_ALARM 1 /* bit 1 == irq claimed */
struct i2c_msg msg[2];
struct i2c_client *client;
- struct i2c_client dev;
struct rtc_device *rtc;
+ struct work_struct work;
};
struct chip_desc {
@@ -132,12 +132,79 @@ static const struct i2c_device_id ds1307_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ds1307_id);
+/*----------------------------------------------------------------------*/
+
+/*
+ * The IRQ logic includes a "real" handler running in IRQ context just
+ * long enough to schedule this workqueue entry. We need a task context
+ * to talk to the RTC, since I2C I/O calls require that; and disable the
+ * IRQ until we clear its status on the chip, so that this handler can
+ * work with any type of triggering (not just falling edge).
+ *
+ * The ds1337 and ds1339 both have two alarms, but we only use the first
+ * one (with a "seconds" field). For ds1337 we expect nINTA is our alarm
+ * signal; ds1339 chips have only one alarm signal.
+ */
+static void ds1307_work(struct work_struct *work)
+{
+ struct ds1307 *ds1307;
+ struct i2c_client *client;
+ struct mutex *lock;
+ int stat, control;
+
+ ds1307 = container_of(work, struct ds1307, work);
+ client = ds1307->client;
+ lock = &ds1307->rtc->ops_lock;
+
+ mutex_lock(lock);
+ stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+ if (stat < 0)
+ goto out;
+
+ if (stat & DS1337_BIT_A1I) {
+ stat &= ~DS1337_BIT_A1I;
+ i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat);
+
+ control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+ if (control < 0)
+ goto out;
+
+ control &= ~DS1337_BIT_A1IE;
+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+
+ /* rtc_update_irq() assumes that it is called
+ * from IRQ-disabled context.
+ */
+ local_irq_disable();
+ rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+ local_irq_enable();
+ }
+
+out:
+ if (test_bit(HAS_ALARM, &ds1307->flags))
+ enable_irq(client->irq);
+ mutex_unlock(lock);
+}
+
+static irqreturn_t ds1307_irq(int irq, void *dev_id)
+{
+ struct i2c_client *client = dev_id;
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+
+ disable_irq_nosync(irq);
+ schedule_work(&ds1307->work);
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
int tmp;
/* read the RTC date and time registers all at once */
+ ds1307->reg_addr = 0;
ds1307->msg[1].flags = I2C_M_RD;
ds1307->msg[1].len = 7;
@@ -231,9 +298,186 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
return 0;
}
+static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ int ret;
+
+ if (!test_bit(HAS_ALARM, &ds1307->flags))
+ return -EINVAL;
+
+ /* read all ALARM1, ALARM2, and status registers at once */
+ ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
+ ds1307->msg[1].flags = I2C_M_RD;
+ ds1307->msg[1].len = 9;
+
+ ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+ ds1307->msg, 2);
+ if (ret != 2) {
+ dev_err(dev, "%s error %d\n", "alarm read", ret);
+ return -EIO;
+ }
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
+ "alarm read",
+ ds1307->regs[0], ds1307->regs[1],
+ ds1307->regs[2], ds1307->regs[3],
+ ds1307->regs[4], ds1307->regs[5],
+ ds1307->regs[6], ds1307->regs[7],
+ ds1307->regs[8]);
+
+ /* report alarm time (ALARM1); assume 24 hour and day-of-month modes,
+ * and that all four fields are checked matches
+ */
+ t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f);
+ t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
+ t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
+ t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
+ t->time.tm_mon = -1;
+ t->time.tm_year = -1;
+ t->time.tm_wday = -1;
+ t->time.tm_yday = -1;
+ t->time.tm_isdst = -1;
+
+ /* ... and status */
+ t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
+ t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I);
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, enabled=%d, pending=%d\n",
+ "alarm read", t->time.tm_sec, t->time.tm_min,
+ t->time.tm_hour, t->time.tm_mday,
+ t->enabled, t->pending);
+
+ return 0;
+}
+
+static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ unsigned char *buf = ds1307->regs;
+ u8 control, status;
+ int ret;
+
+ if (!test_bit(HAS_ALARM, &ds1307->flags))
+ return -EINVAL;
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, enabled=%d, pending=%d\n",
+ "alarm set", t->time.tm_sec, t->time.tm_min,
+ t->time.tm_hour, t->time.tm_mday,
+ t->enabled, t->pending);
+
+ /* read current status of both alarms and the chip */
+ ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
+ ds1307->msg[1].flags = I2C_M_RD;
+ ds1307->msg[1].len = 9;
+
+ ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+ ds1307->msg, 2);
+ if (ret != 2) {
+ dev_err(dev, "%s error %d\n", "alarm write", ret);
+ return -EIO;
+ }
+ control = ds1307->regs[7];
+ status = ds1307->regs[8];
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
+ "alarm set (old status)",
+ ds1307->regs[0], ds1307->regs[1],
+ ds1307->regs[2], ds1307->regs[3],
+ ds1307->regs[4], ds1307->regs[5],
+ ds1307->regs[6], control, status);
+
+ /* set ALARM1, using 24 hour and day-of-month modes */
+ *buf++ = DS1339_REG_ALARM1_SECS; /* first register addr */
+ buf[0] = bin2bcd(t->time.tm_sec);
+ buf[1] = bin2bcd(t->time.tm_min);
+ buf[2] = bin2bcd(t->time.tm_hour);
+ buf[3] = bin2bcd(t->time.tm_mday);
+
+ /* set ALARM2 to non-garbage */
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+
+ /* optionally enable ALARM1 */
+ buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
+ if (t->enabled) {
+ dev_dbg(dev, "alarm IRQ armed\n");
+ buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */
+ }
+ buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
+
+ ds1307->msg[1].flags = 0;
+ ds1307->msg[1].len = 10;
+
+ ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+ &ds1307->msg[1], 1);
+ if (ret != 1) {
+ dev_err(dev, "can't set alarm time\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ int ret;
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ if (!test_bit(HAS_ALARM, &ds1307->flags))
+ return -ENOTTY;
+
+ ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret &= ~DS1337_BIT_A1IE;
+
+ ret = i2c_smbus_write_byte_data(client,
+ DS1337_REG_CONTROL, ret);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ case RTC_AIE_ON:
+ if (!test_bit(HAS_ALARM, &ds1307->flags))
+ return -ENOTTY;
+
+ ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret |= DS1337_BIT_A1IE;
+
+ ret = i2c_smbus_write_byte_data(client,
+ DS1337_REG_CONTROL, ret);
+ if (ret < 0)
+ return ret;
+
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
static const struct rtc_class_ops ds13xx_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
+ .read_alarm = ds1307_read_alarm,
+ .set_alarm = ds1307_set_alarm,
+ .ioctl = ds1307_ioctl,
};
/*----------------------------------------------------------------------*/
@@ -327,6 +571,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
int tmp;
const struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ int want_irq = false;
if (!i2c_check_functionality(adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
@@ -353,6 +598,12 @@ static int __devinit ds1307_probe(struct i2c_client *client,
switch (ds1307->type) {
case ds_1337:
case ds_1339:
+ /* has IRQ? */
+ if (ds1307->client->irq > 0 && chip->alarm) {
+ INIT_WORK(&ds1307->work, ds1307_work);
+ want_irq = true;
+ }
+
ds1307->reg_addr = DS1337_REG_CONTROL;
ds1307->msg[1].len = 2;
@@ -369,8 +620,20 @@ static int __devinit ds1307_probe(struct i2c_client *client,
/* oscillator off? turn it on, so clock can tick. */
if (ds1307->regs[0] & DS1337_BIT_nEOSC)
- i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
- ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+ ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
+
+ /* Using IRQ? Disable the square wave and both alarms.
+ * For ds1339, be sure alarms can trigger when we're
+ * running on Vbackup (BBSQI); we assume ds1337 will
+ * ignore that bit
+ */
+ if (want_irq) {
+ ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI;
+ ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
+ }
+
+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+ ds1307->regs[0]);
/* oscillator fault? clear flag, and warn */
if (ds1307->regs[1] & DS1337_BIT_OSF) {
@@ -495,10 +758,22 @@ read_rtc:
goto exit_free;
}
+ if (want_irq) {
+ err = request_irq(client->irq, ds1307_irq, 0,
+ ds1307->rtc->name, client);
+ if (err) {
+ dev_err(&client->dev,
+ "unable to request IRQ!\n");
+ goto exit_irq;
+ }
+ set_bit(HAS_ALARM, &ds1307->flags);
+ dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+ }
+
if (chip->nvram56) {
err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
if (err == 0) {
- ds1307->has_nvram = true;
+ set_bit(HAS_NVRAM, &ds1307->flags);
dev_info(&client->dev, "56 bytes nvram\n");
}
}
@@ -512,7 +787,9 @@ exit_bad:
ds1307->regs[2], ds1307->regs[3],
ds1307->regs[4], ds1307->regs[5],
ds1307->regs[6]);
-
+exit_irq:
+ if (ds1307->rtc)
+ rtc_device_unregister(ds1307->rtc);
exit_free:
kfree(ds1307);
return err;
@@ -520,9 +797,14 @@ exit_free:
static int __devexit ds1307_remove(struct i2c_client *client)
{
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+
+ if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) {
+ free_irq(client->irq, client);
+ cancel_work_sync(&ds1307->work);
+ }
- if (ds1307->has_nvram)
+ if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
sysfs_remove_bin_file(&client->dev.kobj, &nvram);
rtc_device_unregister(ds1307->rtc);
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index a150418fba7..a5b0fc09f0c 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -429,12 +429,33 @@ static int __devexit ds1374_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM
+static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
+{
+ if (client->irq >= 0 && device_may_wakeup(&client->dev))
+ enable_irq_wake(client->irq);
+ return 0;
+}
+
+static int ds1374_resume(struct i2c_client *client)
+{
+ if (client->irq >= 0 && device_may_wakeup(&client->dev))
+ disable_irq_wake(client->irq);
+ return 0;
+}
+#else
+#define ds1374_suspend NULL
+#define ds1374_resume NULL
+#endif
+
static struct i2c_driver ds1374_driver = {
.driver = {
.name = "rtc-ds1374",
.owner = THIS_MODULE,
},
.probe = ds1374_probe,
+ .suspend = ds1374_suspend,
+ .resume = ds1374_resume,
.remove = __devexit_p(ds1374_remove),
.id_table = ds1374_id,
};
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 0f0d27d1c4c..86981d34fbb 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -379,18 +379,6 @@ ds1511_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- static void
-ds1511_rtc_release(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
- if (pdata->irq >= 0) {
- pdata->irqen = 0;
- ds1511_rtc_update_alarm(pdata);
- }
-}
-
static int
ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
@@ -428,7 +416,6 @@ static const struct rtc_class_ops ds1511_rtc_ops = {
.set_time = ds1511_rtc_set_time,
.read_alarm = ds1511_rtc_read_alarm,
.set_alarm = ds1511_rtc_set_alarm,
- .release = ds1511_rtc_release,
.ioctl = ds1511_rtc_ioctl,
};
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index a19f1141554..4ef59285b48 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -207,17 +207,6 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void ds1553_rtc_release(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
- if (pdata->irq >= 0) {
- pdata->irqen = 0;
- ds1553_rtc_update_alarm(pdata);
- }
-}
-
static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
@@ -254,7 +243,6 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
.set_time = ds1553_rtc_set_time,
.read_alarm = ds1553_rtc_read_alarm,
.set_alarm = ds1553_rtc_set_alarm,
- .release = ds1553_rtc_release,
.ioctl = ds1553_rtc_ioctl,
};
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 6fa4556f5f5..341d7a5b45a 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -9,17 +9,10 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/rtc.h>
-#define DRV_VERSION "0.3"
-
-/* Addresses to scan: none. This chip cannot be detected. */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.4"
/* Registers */
@@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD;
#define DS1672_REG_CONTROL_EOSC 0x80
-/* Prototypes */
-static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
+static struct i2c_driver ds1672_driver;
/*
* In the routines that deal directly with the ds1672 hardware, we use
@@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
unsigned char buf[4];
struct i2c_msg msgs[] = {
- { client->addr, 0, 1, &addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 4, buf }, /* read date */
+ {client->addr, 0, 1, &addr}, /* setup read ptr */
+ {client->addr, I2C_M_RD, 4, buf}, /* read date */
};
/* read date registers */
@@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
buf[2] = (secs & 0x0000FF00) >> 8;
buf[3] = (secs & 0x00FF0000) >> 16;
buf[4] = (secs & 0xFF000000) >> 24;
- buf[5] = 0; /* set control reg to enable counting */
+ buf[5] = 0; /* set control reg to enable counting */
xfer = i2c_master_send(client, buf, 6);
if (xfer != 6) {
@@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
unsigned char addr = DS1672_REG_CONTROL;
struct i2c_msg msgs[] = {
- { client->addr, 0, 1, &addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, status }, /* read control */
+ {client->addr, 0, 1, &addr}, /* setup read ptr */
+ {client->addr, I2C_M_RD, 1, status}, /* read control */
};
/* read control register */
@@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
}
/* following are the sysfs callback functions */
-static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_control(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
u8 control;
@@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c
return err;
return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
- ? "disabled" : "enabled");
+ ? "disabled" : "enabled");
}
+
static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
static const struct rtc_class_ops ds1672_rtc_ops = {
- .read_time = ds1672_rtc_read_time,
- .set_time = ds1672_rtc_set_time,
- .set_mmss = ds1672_rtc_set_mmss,
+ .read_time = ds1672_rtc_read_time,
+ .set_time = ds1672_rtc_set_time,
+ .set_mmss = ds1672_rtc_set_mmss,
};
-static int ds1672_attach(struct i2c_adapter *adapter)
+static int ds1672_remove(struct i2c_client *client)
{
- return i2c_probe(adapter, &addr_data, ds1672_probe);
-}
-
-static int ds1672_detach(struct i2c_client *client)
-{
- int err;
struct rtc_device *rtc = i2c_get_clientdata(client);
- if (rtc)
+ if (rtc)
rtc_device_unregister(rtc);
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(client);
-
return 0;
}
-static struct i2c_driver ds1672_driver = {
- .driver = {
- .name = "ds1672",
- },
- .id = I2C_DRIVERID_DS1672,
- .attach_adapter = &ds1672_attach,
- .detach_client = &ds1672_detach,
-};
-
-static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
+static int ds1672_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err = 0;
u8 control;
- struct i2c_client *client;
struct rtc_device *rtc;
- dev_dbg(&adapter->dev, "%s\n", __func__);
+ dev_dbg(&client->dev, "%s\n", __func__);
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* I2C client */
- client->addr = address;
- client->driver = &ds1672_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
-
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
- &ds1672_rtc_ops, THIS_MODULE);
+ &ds1672_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- err = PTR_ERR(rtc);
- goto exit_detach;
- }
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
i2c_set_clientdata(client, rtc);
@@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
if (control & DS1672_REG_CONTROL_EOSC)
dev_warn(&client->dev, "Oscillator not enabled. "
- "Set time to enable.\n");
+ "Set time to enable.\n");
/* Register sysfs hooks */
err = device_create_file(&client->dev, &dev_attr_control);
@@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
return 0;
-exit_devreg:
+ exit_devreg:
rtc_device_unregister(rtc);
-
-exit_detach:
- i2c_detach_client(client);
-
-exit_kfree:
- kfree(client);
-
-exit:
return err;
}
+static struct i2c_driver ds1672_driver = {
+ .driver = {
+ .name = "rtc-ds1672",
+ },
+ .probe = &ds1672_probe,
+ .remove = &ds1672_remove,
+};
+
static int __init ds1672_init(void)
{
return i2c_add_driver(&ds1672_driver);
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
new file mode 100644
index 00000000000..37d131d03f3
--- /dev/null
+++ b/drivers/rtc/rtc-ds3234.c
@@ -0,0 +1,290 @@
+/* drivers/rtc/rtc-ds3234.c
+ *
+ * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
+ * and SRAM.
+ *
+ * Copyright (C) 2008 MIMOMax Wireless Ltd.
+ *
+ * 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.
+ *
+ * Changelog:
+ *
+ * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com>
+ * - Created based on the max6902 code. Only implements the
+ * date/time keeping functions; no SRAM yet.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define DS3234_REG_SECONDS 0x00
+#define DS3234_REG_MINUTES 0x01
+#define DS3234_REG_HOURS 0x02
+#define DS3234_REG_DAY 0x03
+#define DS3234_REG_DATE 0x04
+#define DS3234_REG_MONTH 0x05
+#define DS3234_REG_YEAR 0x06
+#define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */
+
+#define DS3234_REG_CONTROL 0x0E
+#define DS3234_REG_CONT_STAT 0x0F
+
+#undef DS3234_DEBUG
+
+struct ds3234 {
+ struct rtc_device *rtc;
+ u8 buf[8]; /* Burst read: addr + 7 regs */
+ u8 tx_buf[2];
+ u8 rx_buf[2];
+};
+
+static void ds3234_set_reg(struct device *dev, unsigned char address,
+ unsigned char data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ unsigned char buf[2];
+
+ /* MSB must be '1' to indicate write */
+ buf[0] = address | 0x80;
+ buf[1] = data;
+
+ spi_write(spi, buf, 2);
+}
+
+static int ds3234_get_reg(struct device *dev, unsigned char address,
+ unsigned char *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds3234 *chip = dev_get_drvdata(dev);
+ struct spi_message message;
+ struct spi_transfer xfer;
+ int status;
+
+ if (!data)
+ return -EINVAL;
+
+ /* Build our spi message */
+ spi_message_init(&message);
+ memset(&xfer, 0, sizeof(xfer));
+
+ /* Address + dummy tx byte */
+ xfer.len = 2;
+ xfer.tx_buf = chip->tx_buf;
+ xfer.rx_buf = chip->rx_buf;
+
+ chip->tx_buf[0] = address;
+ chip->tx_buf[1] = 0xff;
+
+ spi_message_add_tail(&xfer, &message);
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ status = message.status;
+ else
+ return status;
+
+ *data = chip->rx_buf[1];
+
+ return status;
+}
+
+static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds3234 *chip = dev_get_drvdata(dev);
+ struct spi_message message;
+ struct spi_transfer xfer;
+ int status;
+
+ /* build the message */
+ spi_message_init(&message);
+ memset(&xfer, 0, sizeof(xfer));
+ xfer.len = 1 + 7; /* Addr + 7 registers */
+ xfer.tx_buf = chip->buf;
+ xfer.rx_buf = chip->buf;
+ chip->buf[0] = 0x00; /* Start address */
+ spi_message_add_tail(&xfer, &message);
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ status = message.status;
+ else
+ return status;
+
+ /* Seconds, Minutes, Hours, Day, Date, Month, Year */
+ dt->tm_sec = bcd2bin(chip->buf[1]);
+ dt->tm_min = bcd2bin(chip->buf[2]);
+ dt->tm_hour = bcd2bin(chip->buf[3] & 0x3f);
+ dt->tm_wday = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */
+ dt->tm_mday = bcd2bin(chip->buf[5]);
+ dt->tm_mon = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */
+ dt->tm_year = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */
+
+#ifdef DS3234_DEBUG
+ dev_dbg(dev, "\n%s : Read RTC values\n", __func__);
+ dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
+ dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
+ dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
+ dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
+ dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
+ dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
+ dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
+#endif
+
+ return 0;
+}
+
+static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+#ifdef DS3234_DEBUG
+ dev_dbg(dev, "\n%s : Setting RTC values\n", __func__);
+ dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
+ dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
+ dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
+ dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
+ dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
+ dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
+ dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
+#endif
+
+ ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
+ ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
+ ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
+
+ /* 0 = Sun */
+ ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1));
+ ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday));
+
+ /* 0 = Jan */
+ ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1));
+
+ /* Assume 20YY although we just want to make sure not to go negative. */
+ if (dt->tm_year > 100)
+ dt->tm_year -= 100;
+
+ ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year));
+
+ return 0;
+}
+
+static int ds3234_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds3234_get_datetime(dev, tm);
+}
+
+static int ds3234_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds3234_set_datetime(dev, tm);
+}
+
+static const struct rtc_class_ops ds3234_rtc_ops = {
+ .read_time = ds3234_read_time,
+ .set_time = ds3234_set_time,
+};
+
+static int ds3234_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ unsigned char tmp;
+ struct ds3234 *chip;
+ int res;
+
+ rtc = rtc_device_register("ds3234",
+ &spi->dev, &ds3234_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ spi->mode = SPI_MODE_3;
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL);
+ if (!chip) {
+ rtc_device_unregister(rtc);
+ return -ENOMEM;
+ }
+ chip->rtc = rtc;
+ dev_set_drvdata(&spi->dev, chip);
+
+ res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
+ if (res) {
+ rtc_device_unregister(rtc);
+ return res;
+ }
+
+ /* Control settings
+ *
+ * CONTROL_REG
+ * BIT 7 6 5 4 3 2 1 0
+ * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
+ *
+ * 0 0 0 1 1 1 0 0
+ *
+ * CONTROL_STAT_REG
+ * BIT 7 6 5 4 3 2 1 0
+ * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F
+ *
+ * 1 0 0 0 1 0 0 0
+ */
+ ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
+ ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c);
+
+ ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
+ ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88);
+
+ /* Print our settings */
+ ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
+ dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
+
+ ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
+ dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
+
+ return 0;
+}
+
+static int __exit ds3234_remove(struct spi_device *spi)
+{
+ struct ds3234 *chip = platform_get_drvdata(spi);
+ struct rtc_device *rtc = chip->rtc;
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ kfree(chip);
+
+ return 0;
+}
+
+static struct spi_driver ds3234_driver = {
+ .driver = {
+ .name = "ds3234",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ds3234_probe,
+ .remove = __devexit_p(ds3234_remove),
+};
+
+static __init int ds3234_init(void)
+{
+ printk(KERN_INFO "DS3234 SPI RTC Driver\n");
+ return spi_register_driver(&ds3234_driver);
+}
+module_init(ds3234_init);
+
+static __exit void ds3234_exit(void)
+{
+ spi_unregister_driver(&ds3234_driver);
+}
+module_exit(ds3234_exit);
+
+MODULE_DESCRIPTION("DS3234 SPI RTC driver");
+MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index 9f996ec881c..dd70bf73ce9 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -51,10 +51,11 @@ EXPORT_SYMBOL(rtc_year_days);
*/
void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
{
- unsigned int days, month, year;
+ unsigned int month, year;
+ int days;
days = time / 86400;
- time -= days * 86400;
+ time -= (unsigned int) days * 86400;
/* day of the week, 1970-01-01 was a Thursday */
tm->tm_wday = (days + 4) % 7;
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 24bc1689fc7..470fb2d2954 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -56,21 +56,27 @@
#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
#define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
#define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
+#define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */
-#define M41T80_FEATURE_HT (1 << 0)
-#define M41T80_FEATURE_BL (1 << 1)
+#define M41T80_FEATURE_HT (1 << 0) /* Halt feature */
+#define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */
+#define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */
+#define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
#define DRV_VERSION "0.05"
static const struct i2c_device_id m41t80_id[] = {
- { "m41t80", 0 },
- { "m41t81", M41T80_FEATURE_HT },
- { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
- { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
- { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
- { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
- { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
- { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
+ { "m41t80", M41T80_FEATURE_SQ },
+ { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ},
+ { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
{ }
};
MODULE_DEVICE_TABLE(i2c, m41t80_id);
@@ -386,8 +392,12 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
int val;
+ if (!(clientdata->features & M41T80_FEATURE_SQ))
+ return -EINVAL;
+
val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
if (val < 0)
return -EIO;
@@ -408,9 +418,13 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
int almon, sqw;
int val = simple_strtoul(buf, NULL, 0);
+ if (!(clientdata->features & M41T80_FEATURE_SQ))
+ return -EINVAL;
+
if (val) {
if (!is_power_of_2(val))
return -EINVAL;
@@ -499,6 +513,8 @@ static void wdt_ping(void)
.buf = i2c_data,
},
};
+ struct m41t80_data *clientdata = i2c_get_clientdata(save_client);
+
i2c_data[0] = 0x09; /* watchdog register */
if (wdt_margin > 31)
@@ -509,6 +525,13 @@ static void wdt_ping(void)
*/
i2c_data[1] = wdt_margin<<2 | 0x82;
+ /*
+ * M41T65 has three bits for watchdog resolution. Don't set bit 7, as
+ * that would be an invalid resolution.
+ */
+ if (clientdata->features & M41T80_FEATURE_WD)
+ i2c_data[1] &= ~M41T80_WATCHDOG_RB2;
+
i2c_transfer(save_client->adapter, msgs1, 1);
}
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
new file mode 100644
index 00000000000..0b219755994
--- /dev/null
+++ b/drivers/rtc/rtc-m48t35.c
@@ -0,0 +1,235 @@
+/*
+ * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ *
+ * Copyright (C) 2008 Thomas Bogendoerfer
+ *
+ * Based on code written by Paul Gortmaker.
+ *
+ * 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/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "1.0"
+
+struct m48t35_rtc {
+ u8 pad[0x7ff8]; /* starts at 0x7ff8 */
+ u8 control;
+ u8 sec;
+ u8 min;
+ u8 hour;
+ u8 day;
+ u8 date;
+ u8 month;
+ u8 year;
+};
+
+#define M48T35_RTC_SET 0x80
+#define M48T35_RTC_READ 0x40
+
+struct m48t35_priv {
+ struct rtc_device *rtc;
+ struct m48t35_rtc __iomem *reg;
+ size_t size;
+ unsigned long baseaddr;
+ spinlock_t lock;
+};
+
+static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct m48t35_priv *priv = dev_get_drvdata(dev);
+ u8 control;
+
+ /*
+ * Only the values that we read from the RTC are set. We leave
+ * tm_wday, tm_yday and tm_isdst untouched. Even though the
+ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+ * by the RTC when initially set to a non-zero value.
+ */
+ spin_lock_irq(&priv->lock);
+ control = readb(&priv->reg->control);
+ writeb(control | M48T35_RTC_READ, &priv->reg->control);
+ tm->tm_sec = readb(&priv->reg->sec);
+ tm->tm_min = readb(&priv->reg->min);
+ tm->tm_hour = readb(&priv->reg->hour);
+ tm->tm_mday = readb(&priv->reg->date);
+ tm->tm_mon = readb(&priv->reg->month);
+ tm->tm_year = readb(&priv->reg->year);
+ writeb(control, &priv->reg->control);
+ spin_unlock_irq(&priv->lock);
+
+ tm->tm_sec = bcd2bin(tm->tm_sec);
+ tm->tm_min = bcd2bin(tm->tm_min);
+ tm->tm_hour = bcd2bin(tm->tm_hour);
+ tm->tm_mday = bcd2bin(tm->tm_mday);
+ tm->tm_mon = bcd2bin(tm->tm_mon);
+ tm->tm_year = bcd2bin(tm->tm_year);
+
+ /*
+ * Account for differences between how the RTC uses the values
+ * and how they are defined in a struct rtc_time;
+ */
+ tm->tm_year += 70;
+ if (tm->tm_year <= 69)
+ tm->tm_year += 100;
+
+ tm->tm_mon--;
+ return rtc_valid_tm(tm);
+}
+
+static int m48t35_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct m48t35_priv *priv = dev_get_drvdata(dev);
+ unsigned char mon, day, hrs, min, sec;
+ unsigned int yrs;
+ u8 control;
+
+ yrs = tm->tm_year + 1900;
+ mon = tm->tm_mon + 1; /* tm_mon starts at zero */
+ day = tm->tm_mday;
+ hrs = tm->tm_hour;
+ min = tm->tm_min;
+ sec = tm->tm_sec;
+
+ if (yrs < 1970)
+ return -EINVAL;
+
+ yrs -= 1970;
+ if (yrs > 255) /* They are unsigned */
+ return -EINVAL;
+
+ if (yrs > 169)
+ return -EINVAL;
+
+ if (yrs >= 100)
+ yrs -= 100;
+
+ sec = bin2bcd(sec);
+ min = bin2bcd(min);
+ hrs = bin2bcd(hrs);
+ day = bin2bcd(day);
+ mon = bin2bcd(mon);
+ yrs = bin2bcd(yrs);
+
+ spin_lock_irq(&priv->lock);
+ control = readb(&priv->reg->control);
+ writeb(control | M48T35_RTC_SET, &priv->reg->control);
+ writeb(yrs, &priv->reg->year);
+ writeb(mon, &priv->reg->month);
+ writeb(day, &priv->reg->date);
+ writeb(hrs, &priv->reg->hour);
+ writeb(min, &priv->reg->min);
+ writeb(sec, &priv->reg->sec);
+ writeb(control, &priv->reg->control);
+ spin_unlock_irq(&priv->lock);
+ return 0;
+}
+
+static const struct rtc_class_ops m48t35_ops = {
+ .read_time = m48t35_read_time,
+ .set_time = m48t35_set_time,
+};
+
+static int __devinit m48t35_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct resource *res;
+ struct m48t35_priv *priv;
+ int ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ priv = kzalloc(sizeof(struct m48t35_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->size = res->end - res->start + 1;
+ /*
+ * kludge: remove the #ifndef after ioc3 resource
+ * conflicts are resolved
+ */
+#ifndef CONFIG_SGI_IP27
+ if (!request_mem_region(res->start, priv->size, pdev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+#endif
+ priv->baseaddr = res->start;
+ priv->reg = ioremap(priv->baseaddr, priv->size);
+ if (!priv->reg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ spin_lock_init(&priv->lock);
+ rtc = rtc_device_register("m48t35", &pdev->dev,
+ &m48t35_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto out;
+ }
+ priv->rtc = rtc;
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+out:
+ if (priv->rtc)
+ rtc_device_unregister(priv->rtc);
+ if (priv->reg)
+ iounmap(priv->reg);
+ if (priv->baseaddr)
+ release_mem_region(priv->baseaddr, priv->size);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit m48t35_remove(struct platform_device *pdev)
+{
+ struct m48t35_priv *priv = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(priv->rtc);
+ iounmap(priv->reg);
+#ifndef CONFIG_SGI_IP27
+ release_mem_region(priv->baseaddr, priv->size);
+#endif
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver m48t35_platform_driver = {
+ .driver = {
+ .name = "rtc-m48t35",
+ .owner = THIS_MODULE,
+ },
+ .probe = m48t35_probe,
+ .remove = __devexit_p(m48t35_remove),
+};
+
+static int __init m48t35_init(void)
+{
+ return platform_driver_register(&m48t35_platform_driver);
+}
+
+static void __exit m48t35_exit(void)
+{
+ platform_driver_unregister(&m48t35_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("M48T35 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:rtc-m48t35");
+
+module_init(m48t35_init);
+module_exit(m48t35_exit);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 013e6c103b9..ce4eff6a8d5 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -24,8 +24,9 @@
#define NO_IRQ (-1)
#endif
-#define M48T59_READ(reg) pdata->read_byte(dev, reg)
-#define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val)
+#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg))
+#define M48T59_WRITE(val, reg) \
+ (pdata->write_byte(dev, pdata->offset + reg, val))
#define M48T59_SET_BITS(mask, reg) \
M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
@@ -34,7 +35,6 @@
struct m48t59_private {
void __iomem *ioaddr;
- unsigned int size; /* iomem size */
int irq;
struct rtc_device *rtc;
spinlock_t lock; /* serialize the NVRAM and RTC access */
@@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY));
val = M48T59_READ(M48T59_WDAY);
- if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
+ if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
+ (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
dev_dbg(dev, "Century bit is enabled\n");
tm->tm_year += 100; /* one century */
}
@@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
- if (tm->tm_year/100)
+ if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
val |= (BIN2BCD(tm->tm_wday) & 0x07);
M48T59_WRITE(val, M48T59_WDAY);
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = {
.proc = m48t59_rtc_proc,
};
+static const struct rtc_class_ops m48t02_rtc_ops = {
+ .read_time = m48t59_rtc_read_time,
+ .set_time = m48t59_rtc_set_time,
+};
+
static ssize_t m48t59_nvram_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj,
ssize_t cnt = 0;
unsigned long flags;
- for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+ for (; size > 0 && pos < pdata->offset; cnt++, size--) {
spin_lock_irqsave(&m48t59->lock, flags);
*buf++ = M48T59_READ(cnt);
spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
ssize_t cnt = 0;
unsigned long flags;
- for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+ for (; size > 0 && pos < pdata->offset; cnt++, size--) {
spin_lock_irqsave(&m48t59->lock, flags);
M48T59_WRITE(*buf++, cnt);
spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = {
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
- .size = M48T59_NVRAM_SIZE,
};
static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
@@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
struct m48t59_private *m48t59 = NULL;
struct resource *res;
int ret = -ENOMEM;
+ char *name;
+ const struct rtc_class_ops *ops;
/* This chip could be memory-mapped or I/O-mapped */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
/* Ensure we only kmalloc platform data once */
pdev->dev.platform_data = pdata;
}
+ if (!pdata->type)
+ pdata->type = M48T59RTC_TYPE_M48T59;
/* Try to use the generic memory read/write ops */
if (!pdata->write_byte)
@@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
if (!m48t59)
return -ENOMEM;
- m48t59->size = res->end - res->start + 1;
- m48t59->ioaddr = ioremap(res->start, m48t59->size);
- if (!m48t59->ioaddr)
- goto out;
+ m48t59->ioaddr = pdata->ioaddr;
+
+ if (!m48t59->ioaddr) {
+ /* ioaddr not mapped externally */
+ m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
+ if (!m48t59->ioaddr)
+ goto out;
+ }
/* Try to get irq number. We also can work in
* the mode without IRQ.
@@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
if (ret)
goto out;
}
+ switch (pdata->type) {
+ case M48T59RTC_TYPE_M48T59:
+ name = "m48t59";
+ ops = &m48t59_rtc_ops;
+ pdata->offset = 0x1ff0;
+ break;
+ case M48T59RTC_TYPE_M48T02:
+ name = "m48t02";
+ ops = &m48t02_rtc_ops;
+ pdata->offset = 0x7f0;
+ break;
+ case M48T59RTC_TYPE_M48T08:
+ name = "m48t08";
+ ops = &m48t02_rtc_ops;
+ pdata->offset = 0x1ff0;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown RTC type\n");
+ ret = -ENODEV;
+ goto out;
+ }
- m48t59->rtc = rtc_device_register("m48t59", &pdev->dev,
- &m48t59_rtc_ops, THIS_MODULE);
+ m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
if (IS_ERR(m48t59->rtc)) {
ret = PTR_ERR(m48t59->rtc);
goto out;
}
+ m48t59_nvram_attr.size = pdata->offset;
+
ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
if (ret)
goto out;
@@ -452,11 +487,12 @@ out:
static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
{
struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
if (!IS_ERR(m48t59->rtc))
rtc_device_unregister(m48t59->rtc);
- if (m48t59->ioaddr)
+ if (m48t59->ioaddr && !pdata->ioaddr)
iounmap(m48t59->ioaddr);
if (m48t59->irq != NO_IRQ)
free_irq(m48t59->irq, &pdev->dev);
@@ -491,5 +527,5 @@ module_init(m48t59_rtc_init);
module_exit(m48t59_rtc_exit);
MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
-MODULE_DESCRIPTION("M48T59 RTC driver");
+MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index ded3c0abad8..12c9cd25cad 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -17,19 +17,18 @@
#include <linux/rtc.h>
#include <linux/delay.h>
-#define DRV_NAME "max6900"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
/*
* register indices
*/
-#define MAX6900_REG_SC 0 /* seconds 00-59 */
-#define MAX6900_REG_MN 1 /* minutes 00-59 */
-#define MAX6900_REG_HR 2 /* hours 00-23 */
-#define MAX6900_REG_DT 3 /* day of month 00-31 */
-#define MAX6900_REG_MO 4 /* month 01-12 */
-#define MAX6900_REG_DW 5 /* day of week 1-7 */
-#define MAX6900_REG_YR 6 /* year 00-99 */
+#define MAX6900_REG_SC 0 /* seconds 00-59 */
+#define MAX6900_REG_MN 1 /* minutes 00-59 */
+#define MAX6900_REG_HR 2 /* hours 00-23 */
+#define MAX6900_REG_DT 3 /* day of month 00-31 */
+#define MAX6900_REG_MO 4 /* month 01-12 */
+#define MAX6900_REG_DW 5 /* day of week 1-7 */
+#define MAX6900_REG_YR 6 /* year 00-99 */
#define MAX6900_REG_CT 7 /* control */
/* register 8 is undocumented */
#define MAX6900_REG_CENTURY 9 /* century */
@@ -39,7 +38,6 @@
#define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */
-
/*
* register read/write commands
*/
@@ -52,16 +50,7 @@
#define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */
-#define MAX6900_I2C_ADDR 0xa0
-
-static const unsigned short normal_i2c[] = {
- MAX6900_I2C_ADDR >> 1,
- I2C_CLIENT_END
-};
-
-I2C_CLIENT_INSMOD; /* defines addr_data */
-
-static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind);
+static struct i2c_driver max6900_driver;
static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
{
@@ -69,36 +58,35 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ };
struct i2c_msg msgs[4] = {
{
- .addr = client->addr,
- .flags = 0, /* write */
- .len = sizeof(reg_burst_read),
- .buf = reg_burst_read
- },
+ .addr = client->addr,
+ .flags = 0, /* write */
+ .len = sizeof(reg_burst_read),
+ .buf = reg_burst_read}
+ ,
{
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = MAX6900_BURST_LEN,
- .buf = buf
- },
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = MAX6900_BURST_LEN,
+ .buf = buf}
+ ,
{
- .addr = client->addr,
- .flags = 0, /* write */
- .len = sizeof(reg_century_read),
- .buf = reg_century_read
- },
+ .addr = client->addr,
+ .flags = 0, /* write */
+ .len = sizeof(reg_century_read),
+ .buf = reg_century_read}
+ ,
{
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = sizeof(buf[MAX6900_REG_CENTURY]),
- .buf = &buf[MAX6900_REG_CENTURY]
- }
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = sizeof(buf[MAX6900_REG_CENTURY]),
+ .buf = &buf[MAX6900_REG_CENTURY]
+ }
};
int rc;
rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (rc != ARRAY_SIZE(msgs)) {
- dev_err(&client->dev, "%s: register read failed\n",
- __func__);
+ dev_err(&client->dev, "%s: register read failed\n", __func__);
return -EIO;
}
return 0;
@@ -109,20 +97,18 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE };
struct i2c_msg century_msgs[1] = {
{
- .addr = client->addr,
- .flags = 0, /* write */
- .len = sizeof(i2c_century_buf),
- .buf = i2c_century_buf
- }
+ .addr = client->addr,
+ .flags = 0, /* write */
+ .len = sizeof(i2c_century_buf),
+ .buf = i2c_century_buf}
};
u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE };
struct i2c_msg burst_msgs[1] = {
{
- .addr = client->addr,
- .flags = 0, /* write */
- .len = sizeof(i2c_burst_buf),
- .buf = i2c_burst_buf
- }
+ .addr = client->addr,
+ .flags = 0, /* write */
+ .len = sizeof(i2c_burst_buf),
+ .buf = i2c_burst_buf}
};
int rc;
@@ -133,10 +119,12 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
* bit as part of the burst write.
*/
i2c_century_buf[1] = buf[MAX6900_REG_CENTURY];
+
rc = i2c_transfer(client->adapter, century_msgs,
ARRAY_SIZE(century_msgs));
if (rc != ARRAY_SIZE(century_msgs))
goto write_failed;
+
msleep(MAX6900_IDLE_TIME_AFTER_WRITE);
memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN);
@@ -148,45 +136,11 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
return 0;
-write_failed:
- dev_err(&client->dev, "%s: register write failed\n",
- __func__);
+ write_failed:
+ dev_err(&client->dev, "%s: register write failed\n", __func__);
return -EIO;
}
-static int max6900_i2c_validate_client(struct i2c_client *client)
-{
- u8 regs[MAX6900_REG_LEN];
- u8 zero_mask[] = {
- 0x80, /* seconds */
- 0x80, /* minutes */
- 0x40, /* hours */
- 0xc0, /* day of month */
- 0xe0, /* month */
- 0xf8, /* day of week */
- 0x00, /* year */
- 0x7f, /* control */
- };
- int i;
- int rc;
- int reserved;
-
- reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ);
- if (reserved != 0x07)
- return -ENODEV;
-
- rc = max6900_i2c_read_regs(client, regs);
- if (rc < 0)
- return rc;
-
- for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) {
- if (regs[i] & zero_mask[i])
- return -ENODEV;
- }
-
- return 0;
-}
-
static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
{
int rc;
@@ -202,7 +156,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]);
tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1;
tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) +
- BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
+ BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]);
return 0;
@@ -211,7 +165,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
static int max6900_i2c_clear_write_protect(struct i2c_client *client)
{
int rc;
- rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0);
+ rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
if (rc < 0) {
dev_err(&client->dev, "%s: control register write failed\n",
__func__);
@@ -220,8 +174,8 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client)
return 0;
}
-static int max6900_i2c_set_time(struct i2c_client *client,
- struct rtc_time const *tm)
+static int
+max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
{
u8 regs[MAX6900_REG_LEN];
int rc;
@@ -258,89 +212,49 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
return max6900_i2c_set_time(to_i2c_client(dev), tm);
}
-static int max6900_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_probe(adapter, &addr_data, max6900_probe);
-}
-
-static int max6900_detach_client(struct i2c_client *client)
+static int max6900_remove(struct i2c_client *client)
{
- struct rtc_device *const rtc = i2c_get_clientdata(client);
+ struct rtc_device *rtc = i2c_get_clientdata(client);
if (rtc)
rtc_device_unregister(rtc);
- return i2c_detach_client(client);
+ return 0;
}
-static struct i2c_driver max6900_driver = {
- .driver = {
- .name = DRV_NAME,
- },
- .id = I2C_DRIVERID_MAX6900,
- .attach_adapter = max6900_attach_adapter,
- .detach_client = max6900_detach_client,
-};
-
static const struct rtc_class_ops max6900_rtc_ops = {
- .read_time = max6900_rtc_read_time,
- .set_time = max6900_rtc_set_time,
+ .read_time = max6900_rtc_read_time,
+ .set_time = max6900_rtc_set_time,
};
-static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind)
+static int
+max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- int rc = 0;
- struct i2c_client *client = NULL;
- struct rtc_device *rtc = NULL;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
- rc = -ENODEV;
- goto failout;
- }
-
- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL) {
- rc = -ENOMEM;
- goto failout;
- }
-
- client->addr = addr;
- client->adapter = adapter;
- client->driver = &max6900_driver;
- strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE);
-
- if (kind < 0) {
- rc = max6900_i2c_validate_client(client);
- if (rc < 0)
- goto failout;
- }
+ struct rtc_device *rtc;
- rc = i2c_attach_client(client);
- if (rc < 0)
- goto failout;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
- dev_info(&client->dev,
- "chip found, driver version " DRV_VERSION "\n");
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
rtc = rtc_device_register(max6900_driver.driver.name,
- &client->dev,
- &max6900_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- rc = PTR_ERR(rtc);
- goto failout_detach;
- }
+ &client->dev, &max6900_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
i2c_set_clientdata(client, rtc);
return 0;
-
-failout_detach:
- i2c_detach_client(client);
-failout:
- kfree(client);
- return rc;
}
+static struct i2c_driver max6900_driver = {
+ .driver = {
+ .name = "rtc-max6900",
+ },
+ .probe = max6900_probe,
+ .remove = max6900_remove,
+};
+
static int __init max6900_init(void)
{
return i2c_add_driver(&max6900_driver);
@@ -352,6 +266,7 @@ static void __exit max6900_exit(void)
}
MODULE_DESCRIPTION("Maxim MAX6900 RTC driver");
+MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 748a502a635..a829f20ad6d 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -179,58 +179,6 @@ struct pcf8563_limit
unsigned char max;
};
-static int pcf8563_validate_client(struct i2c_client *client)
-{
- int i;
-
- static const struct pcf8563_limit pattern[] = {
- /* register, mask, min, max */
- { PCF8563_REG_SC, 0x7F, 0, 59 },
- { PCF8563_REG_MN, 0x7F, 0, 59 },
- { PCF8563_REG_HR, 0x3F, 0, 23 },
- { PCF8563_REG_DM, 0x3F, 0, 31 },
- { PCF8563_REG_MO, 0x1F, 0, 12 },
- };
-
- /* check limits (only registers with bcd values) */
- for (i = 0; i < ARRAY_SIZE(pattern); i++) {
- int xfer;
- unsigned char value;
- unsigned char buf = pattern[i].reg;
-
- struct i2c_msg msgs[] = {
- { client->addr, 0, 1, &buf },
- { client->addr, I2C_M_RD, 1, &buf },
- };
-
- xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-
- if (xfer != ARRAY_SIZE(msgs)) {
- dev_err(&client->dev,
- "%s: could not read register 0x%02X\n",
- __func__, pattern[i].reg);
-
- return -EIO;
- }
-
- value = BCD2BIN(buf & pattern[i].mask);
-
- if (value > pattern[i].max ||
- value < pattern[i].min) {
- dev_dbg(&client->dev,
- "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
- "max=%d, value=%d, raw=0x%02X\n",
- __func__, i, pattern[i].reg, pattern[i].mask,
- pattern[i].min, pattern[i].max,
- value, buf);
-
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return pcf8563_get_datetime(to_i2c_client(dev), tm);
@@ -262,12 +210,6 @@ static int pcf8563_probe(struct i2c_client *client,
if (!pcf8563)
return -ENOMEM;
- /* Verify the chip is really an PCF8563 */
- if (pcf8563_validate_client(client) < 0) {
- err = -ENODEV;
- goto exit_kfree;
- }
-
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c
index 8448eeb9d67..82615355215 100644
--- a/drivers/rtc/rtc-pl030.c
+++ b/drivers/rtc/rtc-pl030.c
@@ -34,15 +34,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int pl030_open(struct device *dev)
-{
- return 0;
-}
-
-static void pl030_release(struct device *dev)
-{
-}
-
static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
@@ -104,8 +95,6 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm)
}
static const struct rtc_class_ops pl030_ops = {
- .open = pl030_open,
- .release = pl030_release,
.ioctl = pl030_ioctl,
.read_time = pl030_read_time,
.set_time = pl030_set_time,
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 08b4610ec5a..333eec689d2 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -45,18 +45,6 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int pl031_open(struct device *dev)
-{
- /*
- * We request IRQ in pl031_probe, so nothing to do here...
- */
- return 0;
-}
-
-static void pl031_release(struct device *dev)
-{
-}
-
static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct pl031_local *ldata = dev_get_drvdata(dev);
@@ -118,8 +106,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
}
static const struct rtc_class_ops pl031_ops = {
- .open = pl031_open,
- .release = pl031_release,
.ioctl = pl031_ioctl,
.read_time = pl031_read_time,
.set_time = pl031_set_time,
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 56caf6b2c3e..8b561958fb1 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -1,8 +1,9 @@
/*
- * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs
+ * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs
*
* Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net>
* Copyright (C) 2006 Tower Technologies
+ * Copyright (C) 2008 Paul Mundt
*
* 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
@@ -13,7 +14,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
-#define DRV_VERSION "0.5"
+#define DRV_VERSION "0.6"
/*
@@ -51,7 +52,8 @@
# define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */
#define RS5C_REG_CTRL2 15
# define RS5C372_CTRL2_24 (1 << 5)
-# define RS5C_CTRL2_XSTP (1 << 4)
+# define R2025_CTRL2_XST (1 << 5)
+# define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */
# define RS5C_CTRL2_CTFG (1 << 2)
# define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */
# define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */
@@ -63,6 +65,7 @@
enum rtc_type {
rtc_undef = 0,
+ rtc_r2025sd,
rtc_rs5c372a,
rtc_rs5c372b,
rtc_rv5c386,
@@ -70,6 +73,7 @@ enum rtc_type {
};
static const struct i2c_device_id rs5c372_id[] = {
+ { "r2025sd", rtc_r2025sd },
{ "rs5c372a", rtc_rs5c372a },
{ "rs5c372b", rtc_rs5c372b },
{ "rv5c386", rtc_rv5c386 },
@@ -89,6 +93,7 @@ struct rs5c372 {
enum rtc_type type;
unsigned time24:1;
unsigned has_irq:1;
+ unsigned smbus:1;
char buf[17];
char *regs;
};
@@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
*
* The first method doesn't work with the iop3xx adapter driver, on at
* least 80219 chips; this works around that bug.
+ *
+ * The third method on the other hand doesn't work for the SMBus-only
+ * configurations, so we use the the first method there, stripping off
+ * the extra register in the process.
*/
- if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
- dev_warn(&client->dev, "can't read registers\n");
- return -EIO;
+ if (rs5c->smbus) {
+ int addr = RS5C_ADDR(RS5C372_REG_SECS);
+ int size = sizeof(rs5c->buf) - 1;
+
+ if (i2c_smbus_read_i2c_block_data(client, addr, size,
+ rs5c->buf + 1) != size) {
+ dev_warn(&client->dev, "can't read registers\n");
+ return -EIO;
+ }
+ } else {
+ if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
+ dev_warn(&client->dev, "can't read registers\n");
+ return -EIO;
+ }
}
dev_dbg(&client->dev,
@@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct rs5c372 *rs5c = i2c_get_clientdata(client);
unsigned char buf[8];
+ int addr;
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- buf[0] = RS5C_ADDR(RS5C372_REG_SECS);
- buf[1] = BIN2BCD(tm->tm_sec);
- buf[2] = BIN2BCD(tm->tm_min);
- buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour);
- buf[4] = BIN2BCD(tm->tm_wday);
- buf[5] = BIN2BCD(tm->tm_mday);
- buf[6] = BIN2BCD(tm->tm_mon + 1);
- buf[7] = BIN2BCD(tm->tm_year - 100);
+ addr = RS5C_ADDR(RS5C372_REG_SECS);
+ buf[0] = BIN2BCD(tm->tm_sec);
+ buf[1] = BIN2BCD(tm->tm_min);
+ buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour);
+ buf[3] = BIN2BCD(tm->tm_wday);
+ buf[4] = BIN2BCD(tm->tm_mday);
+ buf[5] = BIN2BCD(tm->tm_mon + 1);
+ buf[6] = BIN2BCD(tm->tm_year - 100);
- if ((i2c_master_send(client, buf, 8)) != 8) {
+ if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
return -EIO;
}
@@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client);
- unsigned char buf[2];
- int status;
+ unsigned char buf;
+ int status, addr;
- buf[1] = rs5c->regs[RS5C_REG_CTRL1];
+ buf = rs5c->regs[RS5C_REG_CTRL1];
switch (cmd) {
case RTC_UIE_OFF:
case RTC_UIE_ON:
/* some 327a modes use a different IRQ pin for 1Hz irqs */
if (rs5c->type == rtc_rs5c372a
- && (buf[1] & RS5C372A_CTRL1_SL1))
+ && (buf & RS5C372A_CTRL1_SL1))
return -ENOIOCTLCMD;
case RTC_AIE_OFF:
case RTC_AIE_ON:
@@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
if (status < 0)
return status;
- buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+ addr = RS5C_ADDR(RS5C_REG_CTRL1);
switch (cmd) {
case RTC_AIE_OFF: /* alarm off */
- buf[1] &= ~RS5C_CTRL1_AALE;
+ buf &= ~RS5C_CTRL1_AALE;
break;
case RTC_AIE_ON: /* alarm on */
- buf[1] |= RS5C_CTRL1_AALE;
+ buf |= RS5C_CTRL1_AALE;
break;
case RTC_UIE_OFF: /* update off */
- buf[1] &= ~RS5C_CTRL1_CT_MASK;
+ buf &= ~RS5C_CTRL1_CT_MASK;
break;
case RTC_UIE_ON: /* update on */
- buf[1] &= ~RS5C_CTRL1_CT_MASK;
- buf[1] |= RS5C_CTRL1_CT4;
+ buf &= ~RS5C_CTRL1_CT_MASK;
+ buf |= RS5C_CTRL1_CT4;
break;
}
- if ((i2c_master_send(client, buf, 2)) != 2) {
+
+ if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
printk(KERN_WARNING "%s: can't update alarm\n",
rs5c->rtc->name);
status = -EIO;
} else
- rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ rs5c->regs[RS5C_REG_CTRL1] = buf;
+
return status;
}
@@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client);
- int status;
- unsigned char buf[4];
+ int status, addr, i;
+ unsigned char buf[3];
/* only handle up to 24 hours in the future, like RTC_ALM_SET */
if (t->time.tm_mday != -1
@@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
if (status < 0)
return status;
if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) {
- buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
- buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
- if (i2c_master_send(client, buf, 2) != 2) {
+ addr = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
+ if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) {
pr_debug("%s: can't disable alarm\n", rs5c->rtc->name);
return -EIO;
}
- rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ rs5c->regs[RS5C_REG_CTRL1] = buf[0];
}
/* set alarm */
- buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN);
- buf[1] = BIN2BCD(t->time.tm_min);
- buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour);
- buf[3] = 0x7f; /* any/all days */
- if ((i2c_master_send(client, buf, 4)) != 4) {
- pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
- return -EIO;
+ buf[0] = BIN2BCD(t->time.tm_min);
+ buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
+ buf[2] = 0x7f; /* any/all days */
+
+ for (i = 0; i < sizeof(buf); i++) {
+ addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);
+ if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) {
+ pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
+ return -EIO;
+ }
}
/* ... and maybe enable its irq */
if (t->enabled) {
- buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
- buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
- if ((i2c_master_send(client, buf, 2)) != 2)
+ addr = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
+ if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0)
printk(KERN_WARNING "%s: can't enable alarm\n",
rs5c->rtc->name);
- rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ rs5c->regs[RS5C_REG_CTRL1] = buf[0];
}
return 0;
@@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev)
static struct i2c_driver rs5c372_driver;
+static int rs5c_oscillator_setup(struct rs5c372 *rs5c372)
+{
+ unsigned char buf[2];
+ int addr, i, ret = 0;
+
+ if (rs5c372->type == rtc_r2025sd) {
+ if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST))
+ return ret;
+ rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST;
+ } else {
+ if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP))
+ return ret;
+ rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
+ }
+
+ addr = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[0] = rs5c372->regs[RS5C_REG_CTRL1];
+ buf[1] = rs5c372->regs[RS5C_REG_CTRL2];
+
+ /* use 24hr mode */
+ switch (rs5c372->type) {
+ case rtc_rs5c372a:
+ case rtc_rs5c372b:
+ buf[1] |= RS5C372_CTRL2_24;
+ rs5c372->time24 = 1;
+ break;
+ case rtc_r2025sd:
+ case rtc_rv5c386:
+ case rtc_rv5c387a:
+ buf[0] |= RV5C387_CTRL1_24;
+ rs5c372->time24 = 1;
+ break;
+ default:
+ /* impossible */
+ break;
+ }
+
+ for (i = 0; i < sizeof(buf); i++) {
+ addr = RS5C_ADDR(RS5C_REG_CTRL1 + i);
+ ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]);
+ if (unlikely(ret < 0))
+ return ret;
+ }
+
+ rs5c372->regs[RS5C_REG_CTRL1] = buf[0];
+ rs5c372->regs[RS5C_REG_CTRL2] = buf[1];
+
+ return 0;
+}
+
static int rs5c372_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
+ int smbus_mode = 0;
struct rs5c372 *rs5c372;
struct rtc_time tm;
dev_dbg(&client->dev, "%s\n", __func__);
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- err = -ENODEV;
- goto exit;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ /*
+ * If we don't have any master mode adapter, try breaking
+ * it down in to the barest of capabilities.
+ */
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ smbus_mode = 1;
+ else {
+ /* Still no good, give up */
+ err = -ENODEV;
+ goto exit;
+ }
}
if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
@@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client,
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs = &rs5c372->buf[1];
+ rs5c372->smbus = smbus_mode;
err = rs5c_get_regs(rs5c372);
if (err < 0)
@@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client,
if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24)
rs5c372->time24 = 1;
break;
+ case rtc_r2025sd:
case rtc_rv5c386:
case rtc_rv5c387a:
if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
@@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client,
/* if the oscillator lost power and no other software (like
* the bootloader) set it up, do it here.
+ *
+ * The R2025S/D does this a little differently than the other
+ * parts, so we special case that..
*/
- if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) {
- unsigned char buf[3];
-
- rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
-
- buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
- buf[1] = rs5c372->regs[RS5C_REG_CTRL1];
- buf[2] = rs5c372->regs[RS5C_REG_CTRL2];
-
- /* use 24hr mode */
- switch (rs5c372->type) {
- case rtc_rs5c372a:
- case rtc_rs5c372b:
- buf[2] |= RS5C372_CTRL2_24;
- rs5c372->time24 = 1;
- break;
- case rtc_rv5c386:
- case rtc_rv5c387a:
- buf[1] |= RV5C387_CTRL1_24;
- rs5c372->time24 = 1;
- break;
- default:
- /* impossible */
- break;
- }
-
- if ((i2c_master_send(client, buf, 3)) != 3) {
- dev_err(&client->dev, "setup error\n");
- goto exit_kfree;
- }
- rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
- rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
+ err = rs5c_oscillator_setup(rs5c372);
+ if (unlikely(err < 0)) {
+ dev_err(&client->dev, "setup error\n");
+ goto exit_kfree;
}
if (rs5c372_get_datetime(client, &tm) < 0)
@@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client,
dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
({ char *s; switch (rs5c372->type) {
+ case rtc_r2025sd: s = "r2025sd"; break;
case rtc_rs5c372a: s = "rs5c372a"; break;
case rtc_rs5c372b: s = "rs5c372b"; break;
case rtc_rv5c386: s = "rv5c386"; break;
@@ -667,7 +734,8 @@ module_exit(rs5c372_exit);
MODULE_AUTHOR(
"Pavel Mironchik <pmironchik@optifacio.net>, "
- "Alessandro Zummo <a.zummo@towertech.it>");
+ "Alessandro Zummo <a.zummo@towertech.it>, "
+ "Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 1f88e9e914e..fcead4c4cd1 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -257,12 +257,6 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
spin_unlock_irq(&rtc->lock);
}
-static void sh_rtc_release(struct device *dev)
-{
- sh_rtc_setpie(dev, 0);
- sh_rtc_setaie(dev, 0);
-}
-
static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -559,7 +553,6 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq)
}
static struct rtc_class_ops sh_rtc_ops = {
- .release = sh_rtc_release,
.ioctl = sh_rtc_ioctl,
.read_time = sh_rtc_read_time,
.set_time = sh_rtc_set_time,
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c
new file mode 100644
index 00000000000..7ccb0dd700a
--- /dev/null
+++ b/drivers/rtc/rtc-starfire.c
@@ -0,0 +1,120 @@
+/* rtc-starfire.c: Starfire platform RTC driver.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <asm/oplib.h>
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("Starfire RTC driver");
+MODULE_LICENSE("GPL");
+
+struct starfire_rtc {
+ struct rtc_device *rtc;
+ spinlock_t lock;
+};
+
+static u32 starfire_get_time(void)
+{
+ static char obp_gettod[32];
+ static u32 unix_tod;
+
+ sprintf(obp_gettod, "h# %08x unix-gettod",
+ (unsigned int) (long) &unix_tod);
+ prom_feval(obp_gettod);
+
+ return unix_tod;
+}
+
+static int starfire_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct starfire_rtc *p = dev_get_drvdata(dev);
+ unsigned long flags, secs;
+
+ spin_lock_irqsave(&p->lock, flags);
+ secs = starfire_get_time();
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ rtc_time_to_tm(secs, tm);
+
+ return 0;
+}
+
+static int starfire_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long secs;
+ int err;
+
+ err = rtc_tm_to_time(tm, &secs);
+ if (err)
+ return err;
+
+ /* Do nothing, time is set using the service processor
+ * console on this platform.
+ */
+ return 0;
+}
+
+static const struct rtc_class_ops starfire_rtc_ops = {
+ .read_time = starfire_read_time,
+ .set_time = starfire_set_time,
+};
+
+static int __devinit starfire_rtc_probe(struct platform_device *pdev)
+{
+ struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
+
+ if (!p)
+ return -ENOMEM;
+
+ spin_lock_init(&p->lock);
+
+ p->rtc = rtc_device_register("starfire", &pdev->dev,
+ &starfire_rtc_ops, THIS_MODULE);
+ if (IS_ERR(p->rtc)) {
+ int err = PTR_ERR(p->rtc);
+ kfree(p);
+ return err;
+ }
+ platform_set_drvdata(pdev, p);
+ return 0;
+}
+
+static int __devexit starfire_rtc_remove(struct platform_device *pdev)
+{
+ struct starfire_rtc *p = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(p->rtc);
+ kfree(p);
+
+ return 0;
+}
+
+static struct platform_driver starfire_rtc_driver = {
+ .driver = {
+ .name = "rtc-starfire",
+ .owner = THIS_MODULE,
+ },
+ .probe = starfire_rtc_probe,
+ .remove = __devexit_p(starfire_rtc_remove),
+};
+
+static int __init starfire_rtc_init(void)
+{
+ return platform_driver_register(&starfire_rtc_driver);
+}
+
+static void __exit starfire_rtc_exit(void)
+{
+ platform_driver_unregister(&starfire_rtc_driver);
+}
+
+module_init(starfire_rtc_init);
+module_exit(starfire_rtc_exit);
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 31d3c8c2858..9a7e920315f 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -215,17 +215,6 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void stk17ta8_rtc_release(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
- if (pdata->irq >= 0) {
- pdata->irqen = 0;
- stk17ta8_rtc_update_alarm(pdata);
- }
-}
-
static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
@@ -254,7 +243,6 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = {
.set_time = stk17ta8_rtc_set_time,
.read_alarm = stk17ta8_rtc_read_alarm,
.set_alarm = stk17ta8_rtc_set_alarm,
- .release = stk17ta8_rtc_release,
.ioctl = stk17ta8_rtc_ioctl,
};
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c
new file mode 100644
index 00000000000..2012ccbb4a5
--- /dev/null
+++ b/drivers/rtc/rtc-sun4v.c
@@ -0,0 +1,153 @@
+/* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <asm/hypervisor.h>
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("SUN4V RTC driver");
+MODULE_LICENSE("GPL");
+
+struct sun4v_rtc {
+ struct rtc_device *rtc;
+ spinlock_t lock;
+};
+
+static unsigned long hypervisor_get_time(void)
+{
+ unsigned long ret, time;
+ int retries = 10000;
+
+retry:
+ ret = sun4v_tod_get(&time);
+ if (ret == HV_EOK)
+ return time;
+ if (ret == HV_EWOULDBLOCK) {
+ if (--retries > 0) {
+ udelay(100);
+ goto retry;
+ }
+ printk(KERN_WARNING "SUN4V: tod_get() timed out.\n");
+ return 0;
+ }
+ printk(KERN_WARNING "SUN4V: tod_get() not supported.\n");
+ return 0;
+}
+
+static int sun4v_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct sun4v_rtc *p = dev_get_drvdata(dev);
+ unsigned long flags, secs;
+
+ spin_lock_irqsave(&p->lock, flags);
+ secs = hypervisor_get_time();
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ rtc_time_to_tm(secs, tm);
+
+ return 0;
+}
+
+static int hypervisor_set_time(unsigned long secs)
+{
+ unsigned long ret;
+ int retries = 10000;
+
+retry:
+ ret = sun4v_tod_set(secs);
+ if (ret == HV_EOK)
+ return 0;
+ if (ret == HV_EWOULDBLOCK) {
+ if (--retries > 0) {
+ udelay(100);
+ goto retry;
+ }
+ printk(KERN_WARNING "SUN4V: tod_set() timed out.\n");
+ return -EAGAIN;
+ }
+ printk(KERN_WARNING "SUN4V: tod_set() not supported.\n");
+ return -EOPNOTSUPP;
+}
+
+static int sun4v_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct sun4v_rtc *p = dev_get_drvdata(dev);
+ unsigned long flags, secs;
+ int err;
+
+ err = rtc_tm_to_time(tm, &secs);
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&p->lock, flags);
+ err = hypervisor_set_time(secs);
+ spin_unlock_irqrestore(&p->lock, flags);
+
+ return err;
+}
+
+static const struct rtc_class_ops sun4v_rtc_ops = {
+ .read_time = sun4v_read_time,
+ .set_time = sun4v_set_time,
+};
+
+static int __devinit sun4v_rtc_probe(struct platform_device *pdev)
+{
+ struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
+
+ if (!p)
+ return -ENOMEM;
+
+ spin_lock_init(&p->lock);
+
+ p->rtc = rtc_device_register("sun4v", &pdev->dev,
+ &sun4v_rtc_ops, THIS_MODULE);
+ if (IS_ERR(p->rtc)) {
+ int err = PTR_ERR(p->rtc);
+ kfree(p);
+ return err;
+ }
+ platform_set_drvdata(pdev, p);
+ return 0;
+}
+
+static int __devexit sun4v_rtc_remove(struct platform_device *pdev)
+{
+ struct sun4v_rtc *p = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(p->rtc);
+ kfree(p);
+
+ return 0;
+}
+
+static struct platform_driver sun4v_rtc_driver = {
+ .driver = {
+ .name = "rtc-sun4v",
+ .owner = THIS_MODULE,
+ },
+ .probe = sun4v_rtc_probe,
+ .remove = __devexit_p(sun4v_rtc_remove),
+};
+
+static int __init sun4v_rtc_init(void)
+{
+ return platform_driver_register(&sun4v_rtc_driver);
+}
+
+static void __exit sun4v_rtc_exit(void)
+{
+ platform_driver_unregister(&sun4v_rtc_driver);
+}
+
+module_init(sun4v_rtc_init);
+module_exit(sun4v_rtc_exit);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index acb78017e7d..0a225ccda02 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -215,7 +215,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
return rc;
}
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
- device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 1,
+ device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1,
8 * sizeof(long));
debug_register_view(device->debug_area, &debug_sprintf_view);
debug_set_level(device->debug_area, DBF_WARNING);
@@ -933,7 +933,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
MESSAGE(KERN_DEBUG,
"invalid status in handle_killed_request: "
"bus_id %s, status %02x",
- cdev->dev.bus_id, cqr->status);
+ dev_name(&cdev->dev), cqr->status);
return;
}
@@ -942,7 +942,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
device != dasd_device_from_cdev_locked(cdev) ||
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
return;
}
@@ -982,11 +982,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
break;
case -ETIMEDOUT:
printk(KERN_WARNING"%s(%s): request timed out\n",
- __func__, cdev->dev.bus_id);
+ __func__, dev_name(&cdev->dev));
break;
default:
printk(KERN_WARNING"%s(%s): unknown error %ld\n",
- __func__, cdev->dev.bus_id, PTR_ERR(irb));
+ __func__, dev_name(&cdev->dev), PTR_ERR(irb));
}
dasd_handle_killed_request(cdev, intparm);
return;
@@ -995,7 +995,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
now = get_clock();
DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
- cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) |
+ dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) |
irb->scsw.cmd.dstat), (unsigned int) intparm);
/* check for unsolicited interrupts */
@@ -1019,7 +1019,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
if (!device ||
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
return;
}
@@ -1037,7 +1037,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
if (cqr->status != DASD_CQR_IN_IO) {
MESSAGE(KERN_DEBUG,
"invalid status: bus_id %s, status %02x",
- cdev->dev.bus_id, cqr->status);
+ dev_name(&cdev->dev), cqr->status);
return;
}
DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
@@ -2134,14 +2134,14 @@ int dasd_generic_probe(struct ccw_device *cdev,
if (ret) {
printk(KERN_WARNING
"dasd_generic_probe: could not set ccw-device options "
- "for %s\n", cdev->dev.bus_id);
+ "for %s\n", dev_name(&cdev->dev));
return ret;
}
ret = dasd_add_sysfs_files(cdev);
if (ret) {
printk(KERN_WARNING
"dasd_generic_probe: could not add sysfs entries "
- "for %s\n", cdev->dev.bus_id);
+ "for %s\n", dev_name(&cdev->dev));
return ret;
}
cdev->handler = &dasd_int_handler;
@@ -2152,13 +2152,13 @@ int dasd_generic_probe(struct ccw_device *cdev,
* initial probe.
*/
if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
- (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0))
+ (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
ret = ccw_device_set_online(cdev);
if (ret)
printk(KERN_WARNING
"dasd_generic_probe: could not initially "
"online ccw-device %s; return code: %d\n",
- cdev->dev.bus_id, ret);
+ dev_name(&cdev->dev), ret);
return 0;
}
@@ -2224,7 +2224,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
printk (KERN_WARNING
"dasd_generic couldn't online device %s "
"- discipline DIAG not available\n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
dasd_delete_device(device);
return -ENODEV;
}
@@ -2248,7 +2248,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
printk (KERN_WARNING
"dasd_generic couldn't online device %s "
"with discipline %s rc=%i\n",
- cdev->dev.bus_id, discipline->name, rc);
+ dev_name(&cdev->dev), discipline->name, rc);
module_put(discipline->owner);
module_put(base_discipline->owner);
dasd_delete_device(device);
@@ -2259,7 +2259,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
if (device->state <= DASD_STATE_KNOWN) {
printk (KERN_WARNING
"dasd_generic discipline not found for %s\n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
rc = -ENODEV;
dasd_set_target_state(device, DASD_STATE_NEW);
if (device->block)
@@ -2267,7 +2267,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
dasd_delete_device(device);
} else
pr_debug("dasd_generic device %s found\n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
/* FIXME: we have to wait for the root device but we don't want
* to wait for each single device but for all at once. */
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 5c6e6f331cb..b8f9c00633f 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1397,7 +1397,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
DEV_MESSAGE(KERN_ERR, cqr->startdev,
"ERP on alias device for request %p,"
" recover on base device %s", cqr,
- cqr->block->base->cdev->dev.bus_id);
+ dev_name(&cqr->block->base->cdev->dev));
}
dasd_eckd_reset_ccw_to_base_io(cqr);
erp->startdev = cqr->block->base;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index cd3335c1c30..921443b01d1 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -515,9 +515,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev)
{
struct dasd_devmap *devmap;
- devmap = dasd_find_busid(cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&cdev->dev));
if (IS_ERR(devmap))
- devmap = dasd_add_busid(cdev->dev.bus_id,
+ devmap = dasd_add_busid(dev_name(&cdev->dev),
DASD_FEATURE_DEFAULT);
return devmap;
}
@@ -584,7 +584,7 @@ dasd_delete_device(struct dasd_device *device)
unsigned long flags;
/* First remove device pointer from devmap. */
- devmap = dasd_find_busid(device->cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&device->cdev->dev));
BUG_ON(IS_ERR(devmap));
spin_lock(&dasd_devmap_lock);
if (devmap->device != device) {
@@ -674,7 +674,7 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
int ro_flag;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
if (!IS_ERR(devmap))
ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
else
@@ -723,7 +723,7 @@ dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
int erplog;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
if (!IS_ERR(devmap))
erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
else
@@ -770,7 +770,7 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
int use_diag;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
if (!IS_ERR(devmap))
use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
else
@@ -876,7 +876,7 @@ dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
int alias;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
spin_lock(&dasd_devmap_lock);
if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
spin_unlock(&dasd_devmap_lock);
@@ -899,7 +899,7 @@ dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
char *vendor;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
spin_lock(&dasd_devmap_lock);
if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
vendor = devmap->uid.vendor;
@@ -924,7 +924,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
char ua_string[3];
struct dasd_uid *uid;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
spin_lock(&dasd_devmap_lock);
if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
spin_unlock(&dasd_devmap_lock);
@@ -972,7 +972,7 @@ dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
struct dasd_devmap *devmap;
int eer_flag;
- devmap = dasd_find_busid(dev->bus_id);
+ devmap = dasd_find_busid(dev_name(dev));
if (!IS_ERR(devmap) && devmap->device)
eer_flag = dasd_eer_enabled(devmap->device);
else
@@ -1034,7 +1034,7 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
{
struct dasd_devmap *devmap;
- devmap = dasd_find_busid(cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&cdev->dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
@@ -1057,7 +1057,7 @@ dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
{
struct dasd_devmap *devmap;
- devmap = dasd_find_busid(cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&cdev->dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
@@ -1077,7 +1077,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
{
struct dasd_devmap *devmap;
- devmap = dasd_find_busid(cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&cdev->dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
@@ -1093,7 +1093,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
{
struct dasd_devmap *devmap;
- devmap = dasd_find_busid(cdev->dev.bus_id);
+ devmap = dasd_find_busid(dev_name(&cdev->dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 85fcb437105..7844461a995 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -544,7 +544,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
}
cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
- if (req->cmd_flags & REQ_FAILFAST)
+ if (blk_noretry_request(req))
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = memdev;
cqr->memdev = memdev;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 773b3fe275b..2e60d5f968c 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -6,6 +6,8 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * EMC Symmetrix ioctl Copyright EMC Corporation, 2008
+ * Author.........: Nigel Hislop <hislop_nigel@emc.com>
*
*/
@@ -84,7 +86,7 @@ dasd_eckd_probe (struct ccw_device *cdev)
if (ret) {
printk(KERN_WARNING
"dasd_eckd_probe: could not set ccw-device options "
- "for %s\n", cdev->dev.bus_id);
+ "for %s\n", dev_name(&cdev->dev));
return ret;
}
ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
@@ -1501,12 +1503,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
return;
}
- /* just report other unsolicited interrupts */
- DEV_MESSAGE(KERN_DEBUG, device, "%s",
- "unsolicited interrupt received");
- device->discipline->dump_sense(device, NULL, irb);
- dasd_schedule_device_bh(device);
+ if ((irb->scsw.cmd.cc == 1) &&
+ (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
+ (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) &&
+ (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) {
+ /* fake irb do nothing, they are handled elsewhere */
+ dasd_schedule_device_bh(device);
+ return;
+ }
+
+ if (!(irb->esw.esw0.erw.cons)) {
+ /* just report other unsolicited interrupts */
+ DEV_MESSAGE(KERN_ERR, device, "%s",
+ "unsolicited interrupt received");
+ } else {
+ DEV_MESSAGE(KERN_ERR, device, "%s",
+ "unsolicited interrupt received "
+ "(sense available)");
+ device->discipline->dump_sense(device, NULL, irb);
+ }
+ dasd_schedule_device_bh(device);
return;
};
@@ -1683,7 +1700,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
recid++;
}
}
- if (req->cmd_flags & REQ_FAILFAST)
+ if (blk_noretry_request(req))
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = startdev;
cqr->memdev = startdev;
@@ -2068,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
return 0;
}
+/*
+ * Issue syscall I/O to EMC Symmetrix array.
+ * CCWs are PSF and RSSD
+ */
+static int dasd_symm_io(struct dasd_device *device, void __user *argp)
+{
+ struct dasd_symmio_parms usrparm;
+ char *psf_data, *rssd_result;
+ struct dasd_ccw_req *cqr;
+ struct ccw1 *ccw;
+ int rc;
+
+ /* Copy parms from caller */
+ rc = -EFAULT;
+ if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
+ goto out;
+#ifndef CONFIG_64BIT
+ /* Make sure pointers are sane even on 31 bit. */
+ if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+#endif
+ /* alloc I/O data area */
+ psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
+ rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
+ if (!psf_data || !rssd_result) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+
+ /* get syscall header from user space */
+ rc = -EFAULT;
+ if (copy_from_user(psf_data,
+ (void __user *)(unsigned long) usrparm.psf_data,
+ usrparm.psf_data_len))
+ goto out_free;
+
+ /* sanity check on syscall header */
+ if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
+ rc = -EINVAL;
+ goto out_free;
+ }
+
+ /* setup CCWs for PSF + RSSD */
+ cqr = dasd_smalloc_request("ECKD", 2 , 0, device);
+ if (IS_ERR(cqr)) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "Could not allocate initialization request");
+ rc = PTR_ERR(cqr);
+ goto out_free;
+ }
+
+ cqr->startdev = device;
+ cqr->memdev = device;
+ cqr->retries = 3;
+ cqr->expires = 10 * HZ;
+ cqr->buildclk = get_clock();
+ cqr->status = DASD_CQR_FILLED;
+
+ /* Build the ccws */
+ ccw = cqr->cpaddr;
+
+ /* PSF ccw */
+ ccw->cmd_code = DASD_ECKD_CCW_PSF;
+ ccw->count = usrparm.psf_data_len;
+ ccw->flags |= CCW_FLAG_CC;
+ ccw->cda = (__u32)(addr_t) psf_data;
+
+ ccw++;
+
+ /* RSSD ccw */
+ ccw->cmd_code = DASD_ECKD_CCW_RSSD;
+ ccw->count = usrparm.rssd_result_len;
+ ccw->flags = CCW_FLAG_SLI ;
+ ccw->cda = (__u32)(addr_t) rssd_result;
+
+ rc = dasd_sleep_on(cqr);
+ if (rc)
+ goto out_sfree;
+
+ rc = -EFAULT;
+ if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result,
+ rssd_result, usrparm.rssd_result_len))
+ goto out_sfree;
+ rc = 0;
+
+out_sfree:
+ dasd_sfree_request(cqr, cqr->memdev);
+out_free:
+ kfree(rssd_result);
+ kfree(psf_data);
+out:
+ DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
+ return rc;
+}
+
static int
dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
{
@@ -2086,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
return dasd_eckd_reserve(device);
case BIODASDSLCK:
return dasd_eckd_steal_lock(device);
+ case BIODASDSYMMIO:
+ return dasd_symm_io(device, argp);
default:
return -ENOIOCTLCMD;
}
@@ -2145,13 +2261,13 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
/* dump the sense data */
len = sprintf(page, KERN_ERR PRINTK_HEADER
" I/O status report for device %s:\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
" in req: %p CS: 0x%02X DS: 0x%02X\n", req,
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
" device %s: Failing CCW: %p\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
(void *) (addr_t) irb->scsw.cmd.cpa);
if (irb->esw.esw0.erw.cons) {
for (sl = 0; sl < 4; sl++) {
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index bf512ac75b9..892e2878d61 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -309,7 +309,8 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
do_gettimeofday(&tv);
header.tv_sec = tv.tv_sec;
header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
+ strncpy(header.busid, dev_name(&device->cdev->dev),
+ DASD_EER_BUSID_SIZE);
spin_lock_irqsave(&bufferlock, flags);
list_for_each_entry(eerb, &bufferlist, list) {
@@ -349,7 +350,8 @@ static void dasd_eer_write_snss_trigger(struct dasd_device *device,
do_gettimeofday(&tv);
header.tv_sec = tv.tv_sec;
header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
+ strncpy(header.busid, dev_name(&device->cdev->dev),
+ DASD_EER_BUSID_SIZE);
spin_lock_irqsave(&bufferlock, flags);
list_for_each_entry(eerb, &bufferlist, list) {
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index aa0c533423a..7d442aeff3d 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -355,7 +355,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
recid++;
}
}
- if (req->cmd_flags & REQ_FAILFAST)
+ if (blk_noretry_request(req))
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = memdev;
cqr->memdev = memdev;
@@ -451,13 +451,13 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
}
len = sprintf(page, KERN_ERR PRINTK_HEADER
" I/O status report for device %s:\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
" in req: %p CS: 0x%02X DS: 0x%02X\n", req,
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
" device %s: Failing CCW: %p\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
(void *) (addr_t) irb->scsw.cmd.cpa);
if (irb->esw.esw0.erw.cons) {
for (sl = 0; sl < 4; sl++) {
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 31ecaa4a40e..489d5fe488f 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -126,7 +126,7 @@ do { \
#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
do { \
printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
- d_device->cdev->dev.bus_id, d_args); \
+ dev_name(&d_device->cdev->dev), d_args); \
DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
} while(0)
@@ -140,7 +140,7 @@ do { \
#define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\
do { \
printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
- d_device->cdev->dev.bus_id, d_args); \
+ dev_name(&d_device->cdev->dev), d_args); \
} while(0)
#define MESSAGE_LOG(d_loglevel,d_string,d_args...)\
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 03c0e40a92f..9088de84b45 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -67,7 +67,7 @@ dasd_devices_show(struct seq_file *m, void *v)
return 0;
}
/* Print device number. */
- seq_printf(m, "%s", device->cdev->dev.bus_id);
+ seq_printf(m, "%s", dev_name(&device->cdev->dev));
/* Print discipline string. */
if (device != NULL && device->discipline != NULL)
seq_printf(m, "(%s)", device->discipline->name);
@@ -76,7 +76,8 @@ dasd_devices_show(struct seq_file *m, void *v)
/* Print kdev. */
if (block->gdp)
seq_printf(m, " at (%3d:%6d)",
- block->gdp->major, block->gdp->first_minor);
+ MAJOR(disk_devt(block->gdp)),
+ MINOR(disk_devt(block->gdp)));
else
seq_printf(m, " at (???:??????)");
/* Print device name. */
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 711b3004b3e..a7ff167d5b8 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -31,7 +31,6 @@
#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x)
#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x)
-
static int dcssblk_open(struct inode *inode, struct file *filp);
static int dcssblk_release(struct inode *inode, struct file *filp);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
@@ -48,6 +47,30 @@ static struct block_device_operations dcssblk_devops = {
.direct_access = dcssblk_direct_access,
};
+struct dcssblk_dev_info {
+ struct list_head lh;
+ struct device dev;
+ char segment_name[BUS_ID_SIZE];
+ atomic_t use_count;
+ struct gendisk *gd;
+ unsigned long start;
+ unsigned long end;
+ int segment_type;
+ unsigned char save_pending;
+ unsigned char is_shared;
+ struct request_queue *dcssblk_queue;
+ int num_of_segments;
+ struct list_head seg_list;
+};
+
+struct segment_info {
+ struct list_head lh;
+ char segment_name[BUS_ID_SIZE];
+ unsigned long start;
+ unsigned long end;
+ int segment_type;
+};
+
static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
@@ -58,30 +81,20 @@ static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *at
static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t dcssblk_seglist_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
-static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show,
+static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
dcssblk_save_store);
-static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show,
+static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
dcssblk_shared_store);
+static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
static struct device *dcssblk_root_dev;
-struct dcssblk_dev_info {
- struct list_head lh;
- struct device dev;
- char segment_name[BUS_ID_SIZE];
- atomic_t use_count;
- struct gendisk *gd;
- unsigned long start;
- unsigned long end;
- int segment_type;
- unsigned char save_pending;
- unsigned char is_shared;
- struct request_queue *dcssblk_queue;
-};
-
static LIST_HEAD(dcssblk_devices);
static struct rw_semaphore dcssblk_devices_sem;
@@ -91,8 +104,15 @@ static struct rw_semaphore dcssblk_devices_sem;
static void
dcssblk_release_segment(struct device *dev)
{
- PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id);
- kfree(container_of(dev, struct dcssblk_dev_info, dev));
+ struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry, *temp;
+
+ dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+ list_for_each_entry_safe(entry, temp, &dev_info->seg_list, lh) {
+ list_del(&entry->lh);
+ kfree(entry);
+ }
+ kfree(dev_info);
module_put(THIS_MODULE);
}
@@ -114,7 +134,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
found = 0;
// test if minor available
list_for_each_entry(entry, &dcssblk_devices, lh)
- if (minor == entry->gd->first_minor)
+ if (minor == MINOR(disk_devt(entry->gd)))
found++;
if (!found) break; // got unused minor
}
@@ -142,6 +162,169 @@ dcssblk_get_device_by_name(char *name)
return NULL;
}
+/*
+ * get the struct segment_info from seg_list
+ * for the given name.
+ * down_read(&dcssblk_devices_sem) must be held.
+ */
+static struct segment_info *
+dcssblk_get_segment_by_name(char *name)
+{
+ struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry;
+
+ list_for_each_entry(dev_info, &dcssblk_devices, lh) {
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ if (!strcmp(name, entry->segment_name))
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * get the highest address of the multi-segment block.
+ */
+static unsigned long
+dcssblk_find_highest_addr(struct dcssblk_dev_info *dev_info)
+{
+ unsigned long highest_addr;
+ struct segment_info *entry;
+
+ highest_addr = 0;
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ if (highest_addr < entry->end)
+ highest_addr = entry->end;
+ }
+ return highest_addr;
+}
+
+/*
+ * get the lowest address of the multi-segment block.
+ */
+static unsigned long
+dcssblk_find_lowest_addr(struct dcssblk_dev_info *dev_info)
+{
+ int set_first;
+ unsigned long lowest_addr;
+ struct segment_info *entry;
+
+ set_first = 0;
+ lowest_addr = 0;
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ if (set_first == 0) {
+ lowest_addr = entry->start;
+ set_first = 1;
+ } else {
+ if (lowest_addr > entry->start)
+ lowest_addr = entry->start;
+ }
+ }
+ return lowest_addr;
+}
+
+/*
+ * Check continuity of segments.
+ */
+static int
+dcssblk_is_continuous(struct dcssblk_dev_info *dev_info)
+{
+ int i, j, rc;
+ struct segment_info *sort_list, *entry, temp;
+
+ if (dev_info->num_of_segments <= 1)
+ return 0;
+
+ sort_list = kzalloc(
+ sizeof(struct segment_info) * dev_info->num_of_segments,
+ GFP_KERNEL);
+ if (sort_list == NULL)
+ return -ENOMEM;
+ i = 0;
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ memcpy(&sort_list[i], entry, sizeof(struct segment_info));
+ i++;
+ }
+
+ /* sort segments */
+ for (i = 0; i < dev_info->num_of_segments; i++)
+ for (j = 0; j < dev_info->num_of_segments; j++)
+ if (sort_list[j].start > sort_list[i].start) {
+ memcpy(&temp, &sort_list[i],
+ sizeof(struct segment_info));
+ memcpy(&sort_list[i], &sort_list[j],
+ sizeof(struct segment_info));
+ memcpy(&sort_list[j], &temp,
+ sizeof(struct segment_info));
+ }
+
+ /* check continuity */
+ for (i = 0; i < dev_info->num_of_segments - 1; i++) {
+ if ((sort_list[i].end + 1) != sort_list[i+1].start) {
+ PRINT_ERR("Segment %s is not contiguous with "
+ "segment %s\n",
+ sort_list[i].segment_name,
+ sort_list[i+1].segment_name);
+ rc = -EINVAL;
+ goto out;
+ }
+ /* EN and EW are allowed in a block device */
+ if (sort_list[i].segment_type != sort_list[i+1].segment_type) {
+ if (!(sort_list[i].segment_type & SEGMENT_EXCLUSIVE) ||
+ (sort_list[i].segment_type == SEG_TYPE_ER) ||
+ !(sort_list[i+1].segment_type &
+ SEGMENT_EXCLUSIVE) ||
+ (sort_list[i+1].segment_type == SEG_TYPE_ER)) {
+ PRINT_ERR("Segment %s has different type from "
+ "segment %s\n",
+ sort_list[i].segment_name,
+ sort_list[i+1].segment_name);
+ rc = -EINVAL;
+ goto out;
+ }
+ }
+ }
+ rc = 0;
+out:
+ kfree(sort_list);
+ return rc;
+}
+
+/*
+ * Load a segment
+ */
+static int
+dcssblk_load_segment(char *name, struct segment_info **seg_info)
+{
+ int rc;
+
+ /* already loaded? */
+ down_read(&dcssblk_devices_sem);
+ *seg_info = dcssblk_get_segment_by_name(name);
+ up_read(&dcssblk_devices_sem);
+ if (*seg_info != NULL)
+ return -EEXIST;
+
+ /* get a struct segment_info */
+ *seg_info = kzalloc(sizeof(struct segment_info), GFP_KERNEL);
+ if (*seg_info == NULL)
+ return -ENOMEM;
+
+ strcpy((*seg_info)->segment_name, name);
+
+ /* load the segment */
+ rc = segment_load(name, SEGMENT_SHARED,
+ &(*seg_info)->start, &(*seg_info)->end);
+ if (rc < 0) {
+ segment_warning(rc, (*seg_info)->segment_name);
+ kfree(*seg_info);
+ } else {
+ INIT_LIST_HEAD(&(*seg_info)->lh);
+ (*seg_info)->segment_type = rc;
+ }
+ return rc;
+}
+
static void dcssblk_unregister_callback(struct device *dev)
{
device_unregister(dev);
@@ -165,6 +348,7 @@ static ssize_t
dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
{
struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry, *temp;
int rc;
if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
@@ -172,46 +356,46 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
down_write(&dcssblk_devices_sem);
dev_info = container_of(dev, struct dcssblk_dev_info, dev);
if (atomic_read(&dev_info->use_count)) {
- PRINT_ERR("share: segment %s is busy!\n",
- dev_info->segment_name);
rc = -EBUSY;
goto out;
}
if (inbuf[0] == '1') {
- // reload segment in shared mode
- rc = segment_modify_shared(dev_info->segment_name,
- SEGMENT_SHARED);
- if (rc < 0) {
- BUG_ON(rc == -EINVAL);
- if (rc != -EAGAIN)
- goto removeseg;
- } else {
- dev_info->is_shared = 1;
- switch (dev_info->segment_type) {
- case SEG_TYPE_SR:
- case SEG_TYPE_ER:
- case SEG_TYPE_SC:
- set_disk_ro(dev_info->gd,1);
+ /* reload segments in shared mode */
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ rc = segment_modify_shared(entry->segment_name,
+ SEGMENT_SHARED);
+ if (rc < 0) {
+ BUG_ON(rc == -EINVAL);
+ if (rc != -EAGAIN)
+ goto removeseg;
}
}
+ dev_info->is_shared = 1;
+ switch (dev_info->segment_type) {
+ case SEG_TYPE_SR:
+ case SEG_TYPE_ER:
+ case SEG_TYPE_SC:
+ set_disk_ro(dev_info->gd, 1);
+ }
} else if (inbuf[0] == '0') {
- // reload segment in exclusive mode
+ /* reload segments in exclusive mode */
if (dev_info->segment_type == SEG_TYPE_SC) {
PRINT_ERR("Segment type SC (%s) cannot be loaded in "
- "non-shared mode\n", dev_info->segment_name);
+ "non-shared mode\n", dev_info->segment_name);
rc = -EINVAL;
goto out;
}
- rc = segment_modify_shared(dev_info->segment_name,
- SEGMENT_EXCLUSIVE);
- if (rc < 0) {
- BUG_ON(rc == -EINVAL);
- if (rc != -EAGAIN)
- goto removeseg;
- } else {
- dev_info->is_shared = 0;
- set_disk_ro(dev_info->gd, 0);
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ rc = segment_modify_shared(entry->segment_name,
+ SEGMENT_EXCLUSIVE);
+ if (rc < 0) {
+ BUG_ON(rc == -EINVAL);
+ if (rc != -EAGAIN)
+ goto removeseg;
+ }
}
+ dev_info->is_shared = 0;
+ set_disk_ro(dev_info->gd, 0);
} else {
rc = -EINVAL;
goto out;
@@ -220,8 +404,14 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
goto out;
removeseg:
- PRINT_ERR("Could not reload segment %s, removing it now!\n",
- dev_info->segment_name);
+ PRINT_ERR("Could not reload segment(s) of the device %s, removing "
+ "segment(s) now!\n",
+ dev_info->segment_name);
+ temp = entry;
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ if (entry != temp)
+ segment_unload(entry->segment_name);
+ }
list_del(&dev_info->lh);
del_gendisk(dev_info->gd);
@@ -254,6 +444,7 @@ static ssize_t
dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
{
struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry;
if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
return -EINVAL;
@@ -263,14 +454,16 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
if (inbuf[0] == '1') {
if (atomic_read(&dev_info->use_count) == 0) {
// device is idle => we save immediately
- PRINT_INFO("Saving segment %s\n",
+ PRINT_INFO("Saving segment(s) of the device %s\n",
dev_info->segment_name);
- segment_save(dev_info->segment_name);
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ segment_save(entry->segment_name);
+ }
} else {
// device is busy => we save it when it becomes
// idle in dcssblk_release
- PRINT_INFO("Segment %s is currently busy, it will "
- "be saved when it becomes idle...\n",
+ PRINT_INFO("Device %s is currently busy, segment(s) "
+ "will be saved when it becomes idle...\n",
dev_info->segment_name);
dev_info->save_pending = 1;
}
@@ -279,7 +472,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
// device is busy & the user wants to undo his save
// request
dev_info->save_pending = 0;
- PRINT_INFO("Pending save for segment %s deactivated\n",
+ PRINT_INFO("Pending save for segment(s) of the device "
+ "%s deactivated\n",
dev_info->segment_name);
}
} else {
@@ -291,66 +485,123 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
}
/*
+ * device attribute for showing all segments in a device
+ */
+static ssize_t
+dcssblk_seglist_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+
+ struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry;
+
+ down_read(&dcssblk_devices_sem);
+ dev_info = container_of(dev, struct dcssblk_dev_info, dev);
+ i = 0;
+ buf[0] = '\0';
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ strcpy(&buf[i], entry->segment_name);
+ i += strlen(entry->segment_name);
+ buf[i] = '\n';
+ i++;
+ }
+ up_read(&dcssblk_devices_sem);
+ return i;
+}
+
+/*
* device attribute for adding devices
*/
static ssize_t
dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- int rc, i;
+ int rc, i, j, num_of_segments;
struct dcssblk_dev_info *dev_info;
+ struct segment_info *seg_info, *temp;
char *local_buf;
unsigned long seg_byte_size;
dev_info = NULL;
+ seg_info = NULL;
if (dev != dcssblk_root_dev) {
rc = -EINVAL;
goto out_nobuf;
}
+ if ((count < 1) || (buf[0] == '\0') || (buf[0] == '\n')) {
+ rc = -ENAMETOOLONG;
+ goto out_nobuf;
+ }
+
local_buf = kmalloc(count + 1, GFP_KERNEL);
if (local_buf == NULL) {
rc = -ENOMEM;
goto out_nobuf;
}
+
/*
* parse input
*/
+ num_of_segments = 0;
for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) {
- local_buf[i] = toupper(buf[i]);
+ for (j = i; (buf[j] != ':') &&
+ (buf[j] != '\0') &&
+ (buf[j] != '\n') &&
+ j < count; j++) {
+ local_buf[j-i] = toupper(buf[j]);
+ }
+ local_buf[j-i] = '\0';
+ if (((j - i) == 0) || ((j - i) > 8)) {
+ rc = -ENAMETOOLONG;
+ goto seg_list_del;
+ }
+
+ rc = dcssblk_load_segment(local_buf, &seg_info);
+ if (rc < 0)
+ goto seg_list_del;
+ /*
+ * get a struct dcssblk_dev_info
+ */
+ if (num_of_segments == 0) {
+ dev_info = kzalloc(sizeof(struct dcssblk_dev_info),
+ GFP_KERNEL);
+ if (dev_info == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ strcpy(dev_info->segment_name, local_buf);
+ dev_info->segment_type = seg_info->segment_type;
+ INIT_LIST_HEAD(&dev_info->seg_list);
+ }
+ list_add_tail(&seg_info->lh, &dev_info->seg_list);
+ num_of_segments++;
+ i = j;
+
+ if ((buf[j] == '\0') || (buf[j] == '\n'))
+ break;
}
- local_buf[i] = '\0';
- if ((i == 0) || (i > 8)) {
+
+ /* no trailing colon at the end of the input */
+ if ((i > 0) && (buf[i-1] == ':')) {
rc = -ENAMETOOLONG;
- goto out;
- }
- /*
- * already loaded?
- */
- down_read(&dcssblk_devices_sem);
- dev_info = dcssblk_get_device_by_name(local_buf);
- up_read(&dcssblk_devices_sem);
- if (dev_info != NULL) {
- PRINT_WARN("Segment %s already loaded!\n", local_buf);
- rc = -EEXIST;
- goto out;
- }
- /*
- * get a struct dcssblk_dev_info
- */
- dev_info = kzalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL);
- if (dev_info == NULL) {
- rc = -ENOMEM;
- goto out;
+ goto seg_list_del;
}
+ strlcpy(local_buf, buf, i + 1);
+ dev_info->num_of_segments = num_of_segments;
+ rc = dcssblk_is_continuous(dev_info);
+ if (rc < 0)
+ goto seg_list_del;
+
+ dev_info->start = dcssblk_find_lowest_addr(dev_info);
+ dev_info->end = dcssblk_find_highest_addr(dev_info);
- strcpy(dev_info->segment_name, local_buf);
- strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE);
+ dev_set_name(&dev_info->dev, dev_info->segment_name);
dev_info->dev.release = dcssblk_release_segment;
INIT_LIST_HEAD(&dev_info->lh);
-
dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
if (dev_info->gd == NULL) {
rc = -ENOMEM;
- goto free_dev_info;
+ goto seg_list_del;
}
dev_info->gd->major = dcssblk_major;
dev_info->gd->fops = &dcssblk_devops;
@@ -360,59 +611,43 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
dev_info->gd->driverfs_dev = &dev_info->dev;
blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
- /*
- * load the segment
- */
- rc = segment_load(local_buf, SEGMENT_SHARED,
- &dev_info->start, &dev_info->end);
- if (rc < 0) {
- segment_warning(rc, dev_info->segment_name);
- goto dealloc_gendisk;
- }
+
seg_byte_size = (dev_info->end - dev_info->start + 1);
set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
- PRINT_INFO("Loaded segment %s, size = %lu Byte, "
+ PRINT_INFO("Loaded segment(s) %s, size = %lu Byte, "
"capacity = %lu (512 Byte) sectors\n", local_buf,
seg_byte_size, seg_byte_size >> 9);
- dev_info->segment_type = rc;
dev_info->save_pending = 0;
dev_info->is_shared = 1;
dev_info->dev.parent = dcssblk_root_dev;
/*
- * get minor, add to list
+ *get minor, add to list
*/
down_write(&dcssblk_devices_sem);
- if (dcssblk_get_device_by_name(local_buf)) {
- up_write(&dcssblk_devices_sem);
+ if (dcssblk_get_segment_by_name(local_buf)) {
rc = -EEXIST;
- goto unload_seg;
+ goto release_gd;
}
rc = dcssblk_assign_free_minor(dev_info);
- if (rc) {
- up_write(&dcssblk_devices_sem);
- PRINT_ERR("No free minor number available! "
- "Unloading segment...\n");
- goto unload_seg;
- }
+ if (rc)
+ goto release_gd;
sprintf(dev_info->gd->disk_name, "dcssblk%d",
- dev_info->gd->first_minor);
+ MINOR(disk_devt(dev_info->gd)));
list_add_tail(&dev_info->lh, &dcssblk_devices);
if (!try_module_get(THIS_MODULE)) {
rc = -ENODEV;
- goto list_del;
+ goto dev_list_del;
}
/*
* register the device
*/
rc = device_register(&dev_info->dev);
if (rc) {
- PRINT_ERR("Segment %s could not be registered RC=%d\n",
- local_buf, rc);
module_put(THIS_MODULE);
- goto list_del;
+ goto dev_list_del;
}
get_device(&dev_info->dev);
rc = device_create_file(&dev_info->dev, &dev_attr_shared);
@@ -421,6 +656,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
rc = device_create_file(&dev_info->dev, &dev_attr_save);
if (rc)
goto unregister_dev;
+ rc = device_create_file(&dev_info->dev, &dev_attr_seglist);
+ if (rc)
+ goto unregister_dev;
add_disk(dev_info->gd);
@@ -434,7 +672,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
set_disk_ro(dev_info->gd,0);
break;
}
- PRINT_DEBUG("Segment %s loaded successfully\n", local_buf);
up_write(&dcssblk_devices_sem);
rc = count;
goto out;
@@ -445,20 +682,27 @@ unregister_dev:
dev_info->gd->queue = NULL;
put_disk(dev_info->gd);
device_unregister(&dev_info->dev);
- segment_unload(dev_info->segment_name);
+ list_for_each_entry(seg_info, &dev_info->seg_list, lh) {
+ segment_unload(seg_info->segment_name);
+ }
put_device(&dev_info->dev);
up_write(&dcssblk_devices_sem);
goto out;
-list_del:
+dev_list_del:
list_del(&dev_info->lh);
- up_write(&dcssblk_devices_sem);
-unload_seg:
- segment_unload(local_buf);
-dealloc_gendisk:
+release_gd:
blk_cleanup_queue(dev_info->dcssblk_queue);
dev_info->gd->queue = NULL;
put_disk(dev_info->gd);
-free_dev_info:
+ up_write(&dcssblk_devices_sem);
+seg_list_del:
+ if (dev_info == NULL)
+ goto out;
+ list_for_each_entry_safe(seg_info, temp, &dev_info->seg_list, lh) {
+ list_del(&seg_info->lh);
+ segment_unload(seg_info->segment_name);
+ kfree(seg_info);
+ }
kfree(dev_info);
out:
kfree(local_buf);
@@ -473,6 +717,7 @@ static ssize_t
dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry;
int rc, i;
char *local_buf;
@@ -499,26 +744,28 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
dev_info = dcssblk_get_device_by_name(local_buf);
if (dev_info == NULL) {
up_write(&dcssblk_devices_sem);
- PRINT_WARN("Segment %s is not loaded!\n", local_buf);
+ PRINT_WARN("Device %s is not loaded!\n", local_buf);
rc = -ENODEV;
goto out_buf;
}
if (atomic_read(&dev_info->use_count) != 0) {
up_write(&dcssblk_devices_sem);
- PRINT_WARN("Segment %s is in use!\n", local_buf);
+ PRINT_WARN("Device %s is in use!\n", local_buf);
rc = -EBUSY;
goto out_buf;
}
- list_del(&dev_info->lh);
+ list_del(&dev_info->lh);
del_gendisk(dev_info->gd);
blk_cleanup_queue(dev_info->dcssblk_queue);
dev_info->gd->queue = NULL;
put_disk(dev_info->gd);
device_unregister(&dev_info->dev);
- segment_unload(dev_info->segment_name);
- PRINT_DEBUG("Segment %s unloaded successfully\n",
- dev_info->segment_name);
+
+ /* unload all related segments */
+ list_for_each_entry(entry, &dev_info->seg_list, lh)
+ segment_unload(entry->segment_name);
+
put_device(&dev_info->dev);
up_write(&dcssblk_devices_sem);
@@ -550,6 +797,7 @@ static int
dcssblk_release(struct inode *inode, struct file *filp)
{
struct dcssblk_dev_info *dev_info;
+ struct segment_info *entry;
int rc;
dev_info = inode->i_bdev->bd_disk->private_data;
@@ -560,9 +808,11 @@ dcssblk_release(struct inode *inode, struct file *filp)
down_write(&dcssblk_devices_sem);
if (atomic_dec_and_test(&dev_info->use_count)
&& (dev_info->save_pending)) {
- PRINT_INFO("Segment %s became idle and is being saved now\n",
+ PRINT_INFO("Device %s became idle and is being saved now\n",
dev_info->segment_name);
- segment_save(dev_info->segment_name);
+ list_for_each_entry(entry, &dev_info->seg_list, lh) {
+ segment_save(entry->segment_name);
+ }
dev_info->save_pending = 0;
}
up_write(&dcssblk_devices_sem);
@@ -602,7 +852,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
case SEG_TYPE_SC:
/* cannot write to these segments */
if (bio_data_dir(bio) == WRITE) {
- PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
+ PRINT_WARN("rejecting write to ro device %s\n",
+ dev_name(&dev_info->dev));
goto fail;
}
}
@@ -657,7 +908,7 @@ static void
dcssblk_check_params(void)
{
int rc, i, j, k;
- char buf[9];
+ char buf[DCSSBLK_PARM_LEN + 1];
struct dcssblk_dev_info *dev_info;
for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
@@ -665,15 +916,16 @@ dcssblk_check_params(void)
for (j = i; (dcssblk_segments[j] != ',') &&
(dcssblk_segments[j] != '\0') &&
(dcssblk_segments[j] != '(') &&
- (j - i) < 8; j++)
+ (j < DCSSBLK_PARM_LEN); j++)
{
buf[j-i] = dcssblk_segments[j];
}
buf[j-i] = '\0';
rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
- for (k = 0; buf[k] != '\0'; k++)
+ for (k = 0; (buf[k] != ':') && (buf[k] != '\0'); k++)
buf[k] = toupper(buf[k]);
+ buf[k] = '\0';
if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
down_read(&dcssblk_devices_sem);
dev_info = dcssblk_get_device_by_name(buf);
@@ -740,10 +992,12 @@ module_exit(dcssblk_exit);
module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
- "comma-separated list, each name max. 8 chars.\n"
- "Adding \"(local)\" to segment name equals echoing 0 to "
- "/sys/devices/dcssblk/<segment name>/shared after loading "
- "the segment - \n"
- "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\"");
+ "comma-separated list, names in each set separated "
+ "by commas are separated by colons, each set contains "
+ "names of contiguous segments and each name max. 8 chars.\n"
+ "Adding \"(local)\" to the end of each set equals echoing 0 "
+ "to /sys/devices/dcssblk/<device name>/shared after loading "
+ "the contiguous segments - \n"
+ "e.g. segments=\"mydcss1,mydcss2:mydcss3,mydcss4(local)\"");
MODULE_LICENSE("GPL");
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index dd9b986389a..03916989ed2 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -56,6 +56,7 @@ typedef struct {
static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
static unsigned int xpram_sizes[XPRAM_MAX_DEVS];
static struct gendisk *xpram_disks[XPRAM_MAX_DEVS];
+static struct request_queue *xpram_queues[XPRAM_MAX_DEVS];
static unsigned int xpram_pages;
static int xpram_devs;
@@ -330,18 +331,22 @@ static int __init xpram_setup_sizes(unsigned long pages)
return 0;
}
-static struct request_queue *xpram_queue;
-
static int __init xpram_setup_blkdev(void)
{
unsigned long offset;
int i, rc = -ENOMEM;
for (i = 0; i < xpram_devs; i++) {
- struct gendisk *disk = alloc_disk(1);
- if (!disk)
+ xpram_disks[i] = alloc_disk(1);
+ if (!xpram_disks[i])
+ goto out;
+ xpram_queues[i] = blk_alloc_queue(GFP_KERNEL);
+ if (!xpram_queues[i]) {
+ put_disk(xpram_disks[i]);
goto out;
- xpram_disks[i] = disk;
+ }
+ blk_queue_make_request(xpram_queues[i], xpram_make_request);
+ blk_queue_hardsect_size(xpram_queues[i], 4096);
}
/*
@@ -352,18 +357,6 @@ static int __init xpram_setup_blkdev(void)
goto out;
/*
- * Assign the other needed values: make request function, sizes and
- * hardsect size. All the minor devices feature the same value.
- */
- xpram_queue = blk_alloc_queue(GFP_KERNEL);
- if (!xpram_queue) {
- rc = -ENOMEM;
- goto out_unreg;
- }
- blk_queue_make_request(xpram_queue, xpram_make_request);
- blk_queue_hardsect_size(xpram_queue, 4096);
-
- /*
* Setup device structures.
*/
offset = 0;
@@ -377,18 +370,18 @@ static int __init xpram_setup_blkdev(void)
disk->first_minor = i;
disk->fops = &xpram_devops;
disk->private_data = &xpram_devices[i];
- disk->queue = xpram_queue;
+ disk->queue = xpram_queues[i];
sprintf(disk->disk_name, "slram%d", i);
set_capacity(disk, xpram_sizes[i] << 1);
add_disk(disk);
}
return 0;
-out_unreg:
- unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
out:
- while (i--)
+ while (i--) {
+ blk_cleanup_queue(xpram_queues[i]);
put_disk(xpram_disks[i]);
+ }
return rc;
}
@@ -400,10 +393,10 @@ static void __exit xpram_exit(void)
int i;
for (i = 0; i < xpram_devs; i++) {
del_gendisk(xpram_disks[i]);
+ blk_cleanup_queue(xpram_queues[i]);
put_disk(xpram_disks[i]);
}
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
- blk_cleanup_queue(xpram_queue);
}
static int __init xpram_init(void)
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index d3ec9b55ab3..9ab06e0dad4 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -21,6 +21,7 @@
#include <linux/console.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
@@ -88,7 +89,6 @@ struct raw3215_info {
int count; /* number of bytes in output buffer */
int written; /* number of bytes in write requests */
struct tty_struct *tty; /* pointer to tty structure if present */
- struct tasklet_struct tasklet;
struct raw3215_req *queued_read; /* pointer to queued read requests */
struct raw3215_req *queued_write;/* pointer to queued write requests */
wait_queue_head_t empty_wait; /* wait queue for flushing */
@@ -341,21 +341,14 @@ raw3215_try_io(struct raw3215_info *raw)
}
/*
- * The bottom half handler routine for 3215 devices. It tries to start
- * the next IO and wakes up processes waiting on the tty.
+ * Try to start the next IO and wake up processes waiting on the tty.
*/
-static void
-raw3215_tasklet(void *data)
+static void raw3215_next_io(struct raw3215_info *raw)
{
- struct raw3215_info *raw;
struct tty_struct *tty;
- unsigned long flags;
- raw = (struct raw3215_info *) data;
- spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw3215_mk_write_req(raw);
raw3215_try_io(raw);
- spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
tty = raw->tty;
if (tty != NULL &&
RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
@@ -380,7 +373,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
if (cstat != 0)
- tasklet_schedule(&raw->tasklet);
+ raw3215_next_io(raw);
if (dstat & 0x01) { /* we got a unit exception */
dstat &= ~0x01; /* we can ignore it */
}
@@ -390,7 +383,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
break;
/* Attention interrupt, someone hit the enter key */
raw3215_mk_read_req(raw);
- tasklet_schedule(&raw->tasklet);
+ raw3215_next_io(raw);
break;
case 0x08:
case 0x0C:
@@ -448,7 +441,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
raw->queued_read == NULL) {
wake_up_interruptible(&raw->empty_wait);
}
- tasklet_schedule(&raw->tasklet);
+ raw3215_next_io(raw);
break;
default:
/* Strange interrupt, I'll do my best to clean up */
@@ -460,7 +453,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
raw->flags &= ~RAW3215_WORKING;
raw3215_free_req(req);
}
- tasklet_schedule(&raw->tasklet);
+ raw3215_next_io(raw);
}
return;
}
@@ -674,9 +667,6 @@ raw3215_probe (struct ccw_device *cdev)
kfree(raw);
return -ENOMEM;
}
- tasklet_init(&raw->tasklet,
- (void (*)(unsigned long)) raw3215_tasklet,
- (unsigned long) raw);
init_waitqueue_head(&raw->empty_wait);
cdev->dev.driver_data = raw;
@@ -775,11 +765,11 @@ static struct tty_driver *con3215_device(struct console *c, int *index)
}
/*
- * panic() calls console_unblank before the system enters a
- * disabled, endless loop.
+ * panic() calls con3215_flush through a panic_notifier
+ * before the system enters a disabled, endless loop.
*/
static void
-con3215_unblank(void)
+con3215_flush(void)
{
struct raw3215_info *raw;
unsigned long flags;
@@ -790,6 +780,23 @@ con3215_unblank(void)
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
}
+static int con3215_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ con3215_flush();
+ return NOTIFY_OK;
+}
+
+static struct notifier_block on_panic_nb = {
+ .notifier_call = con3215_notify,
+ .priority = 0,
+};
+
+static struct notifier_block on_reboot_nb = {
+ .notifier_call = con3215_notify,
+ .priority = 0,
+};
+
/*
* The console structure for the 3215 console
*/
@@ -797,7 +804,6 @@ static struct console con3215 = {
.name = "ttyS",
.write = con3215_write,
.device = con3215_device,
- .unblank = con3215_unblank,
.flags = CON_PRINTBUFFER,
};
@@ -846,9 +852,6 @@ con3215_init(void)
cdev->handler = raw3215_irq;
raw->flags |= RAW3215_FIXED;
- tasklet_init(&raw->tasklet,
- (void (*)(unsigned long)) raw3215_tasklet,
- (unsigned long) raw);
init_waitqueue_head(&raw->empty_wait);
/* Request the console irq */
@@ -859,6 +862,8 @@ con3215_init(void)
raw3215[0] = NULL;
return -ENODEV;
}
+ atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
+ register_reboot_notifier(&on_reboot_nb);
register_console(&con3215);
return 0;
}
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 3c07974886e..d028d2ee83d 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/err.h>
+#include <linux/reboot.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -528,11 +529,11 @@ con3270_wait_write(struct con3270 *cp)
}
/*
- * panic() calls console_unblank before the system enters a
- * disabled, endless loop.
+ * panic() calls con3270_flush through a panic_notifier
+ * before the system enters a disabled, endless loop.
*/
static void
-con3270_unblank(void)
+con3270_flush(void)
{
struct con3270 *cp;
unsigned long flags;
@@ -554,6 +555,23 @@ con3270_unblank(void)
spin_unlock_irqrestore(&cp->view.lock, flags);
}
+static int con3270_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ con3270_flush();
+ return NOTIFY_OK;
+}
+
+static struct notifier_block on_panic_nb = {
+ .notifier_call = con3270_notify,
+ .priority = 0,
+};
+
+static struct notifier_block on_reboot_nb = {
+ .notifier_call = con3270_notify,
+ .priority = 0,
+};
+
/*
* The console structure for the 3270 console
*/
@@ -561,7 +579,6 @@ static struct console con3270 = {
.name = "tty3270",
.write = con3270_write,
.device = con3270_device,
- .unblank = con3270_unblank,
.flags = CON_PRINTBUFFER,
};
@@ -623,6 +640,8 @@ con3270_init(void)
condev->cline->len = 0;
con3270_create_status(condev);
condev->input = alloc_string(&condev->freemem, 80);
+ atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
+ register_reboot_notifier(&on_reboot_nb);
register_console(&con3270);
return 0;
}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index d18e6d2e0b4..40759c33477 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -418,25 +418,22 @@ fs3270_open(struct inode *inode, struct file *filp)
{
struct fs3270 *fp;
struct idal_buffer *ib;
- int minor, rc;
+ int minor, rc = 0;
if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
return -ENODEV;
- lock_kernel();
minor = iminor(filp->f_path.dentry->d_inode);
/* Check for minor 0 multiplexer. */
if (minor == 0) {
- struct tty_struct *tty;
- mutex_lock(&tty_mutex);
- tty = get_current_tty();
+ struct tty_struct *tty = get_current_tty();
if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
- mutex_unlock(&tty_mutex);
- rc = -ENODEV;
- goto out;
+ tty_kref_put(tty);
+ return -ENODEV;
}
minor = tty->index + RAW3270_FIRSTMINOR;
- mutex_unlock(&tty_mutex);
+ tty_kref_put(tty);
}
+ lock_kernel();
/* Check if some other program is already using fullscreen mode. */
fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
if (!IS_ERR(fp)) {
@@ -478,7 +475,7 @@ fs3270_open(struct inode *inode, struct file *filp)
filp->private_data = fp;
out:
unlock_kernel();
- return 0;
+ return rc;
}
/*
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index c3dee900a5c..0b15cf107ec 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1168,19 +1168,17 @@ static int raw3270_create_attributes(struct raw3270 *rp)
if (rc)
goto out;
- rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor),
- NULL,
- "tty%s", rp->cdev->dev.bus_id);
+ rp->clttydev = device_create(class3270, &rp->cdev->dev,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL,
+ "tty%s", dev_name(&rp->cdev->dev));
if (IS_ERR(rp->clttydev)) {
rc = PTR_ERR(rp->clttydev);
goto out_ttydev;
}
- rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
- MKDEV(IBM_FS3270_MAJOR, rp->minor),
- NULL,
- "tub%s", rp->cdev->dev.bus_id);
+ rp->cltubdev = device_create(class3270, &rp->cdev->dev,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL,
+ "tub%s", dev_name(&rp->cdev->dev));
if (!IS_ERR(rp->cltubdev))
goto out;
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index 7e619c534bf..9a25c4bd142 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/termios.h>
#include <linux/err.h>
+#include <linux/reboot.h>
#include "sclp.h"
#include "sclp_rw.h"
@@ -172,7 +173,7 @@ sclp_console_device(struct console *c, int *index)
* will be flushed to the SCLP.
*/
static void
-sclp_console_unblank(void)
+sclp_console_flush(void)
{
unsigned long flags;
@@ -188,6 +189,24 @@ sclp_console_unblank(void)
spin_unlock_irqrestore(&sclp_con_lock, flags);
}
+static int
+sclp_console_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ sclp_console_flush();
+ return NOTIFY_OK;
+}
+
+static struct notifier_block on_panic_nb = {
+ .notifier_call = sclp_console_notify,
+ .priority = 1,
+};
+
+static struct notifier_block on_reboot_nb = {
+ .notifier_call = sclp_console_notify,
+ .priority = 1,
+};
+
/*
* used to register the SCLP console to the kernel and to
* give printk necessary information
@@ -197,7 +216,6 @@ static struct console sclp_console =
.name = sclp_console_name,
.write = sclp_console_write,
.device = sclp_console_device,
- .unblank = sclp_console_unblank,
.flags = CON_PRINTBUFFER,
.index = 0 /* ttyS0 */
};
@@ -241,6 +259,8 @@ sclp_console_init(void)
sclp_con_width_htab = 8;
/* enable printk-access to this driver */
+ atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
+ register_reboot_notifier(&on_reboot_nb);
register_console(&sclp_console);
return 0;
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index ad51738c426..9854f19f5e6 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -24,6 +24,8 @@
#include <linux/bootmem.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/reboot.h>
+
#include <asm/uaccess.h>
#include "sclp.h"
@@ -743,24 +745,30 @@ sclp_vt220_con_device(struct console *c, int *index)
return sclp_vt220_driver;
}
-/*
- * This routine is called from panic when the kernel is going to give up.
- * We have to make sure that all buffers will be flushed to the SCLP.
- * Note that this function may be called from within an interrupt context.
- */
-static void
-sclp_vt220_con_unblank(void)
+static int
+sclp_vt220_notify(struct notifier_block *self,
+ unsigned long event, void *data)
{
__sclp_vt220_flush_buffer();
+ return NOTIFY_OK;
}
+static struct notifier_block on_panic_nb = {
+ .notifier_call = sclp_vt220_notify,
+ .priority = 1,
+};
+
+static struct notifier_block on_reboot_nb = {
+ .notifier_call = sclp_vt220_notify,
+ .priority = 1,
+};
+
/* Structure needed to register with printk */
static struct console sclp_vt220_console =
{
.name = SCLP_VT220_CONSOLE_NAME,
.write = sclp_vt220_con_write,
.device = sclp_vt220_con_device,
- .unblank = sclp_vt220_con_unblank,
.flags = CON_PRINTBUFFER,
.index = SCLP_VT220_CONSOLE_INDEX
};
@@ -776,6 +784,8 @@ sclp_vt220_con_init(void)
if (rc)
return rc;
/* Attach linux console */
+ atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
+ register_reboot_notifier(&on_reboot_nb);
register_console(&sclp_vt220_console);
return 0;
}
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 839987618ff..4005c44a404 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -910,7 +910,7 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request,
* should proceed with the new tape... this
* should probably be done in user space!
*/
- PRINT_WARN("(%s): Swap Tape Device!\n", device->cdev->dev.bus_id);
+ PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev));
return tape_3590_erp_basic(device, request, irb, -EIO);
}
@@ -1003,40 +1003,43 @@ tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb)
/* Exception Message */
switch (sense->fmt.f70.emc) {
case 0x02:
- PRINT_WARN("(%s): Data degraded\n", device->cdev->dev.bus_id);
+ PRINT_WARN("(%s): Data degraded\n",
+ dev_name(&device->cdev->dev));
break;
case 0x03:
PRINT_WARN("(%s): Data degraded in partion %i\n",
- device->cdev->dev.bus_id, sense->fmt.f70.mp);
+ dev_name(&device->cdev->dev), sense->fmt.f70.mp);
break;
case 0x04:
- PRINT_WARN("(%s): Medium degraded\n", device->cdev->dev.bus_id);
+ PRINT_WARN("(%s): Medium degraded\n",
+ dev_name(&device->cdev->dev));
break;
case 0x05:
PRINT_WARN("(%s): Medium degraded in partition %i\n",
- device->cdev->dev.bus_id, sense->fmt.f70.mp);
+ dev_name(&device->cdev->dev), sense->fmt.f70.mp);
break;
case 0x06:
- PRINT_WARN("(%s): Block 0 Error\n", device->cdev->dev.bus_id);
+ PRINT_WARN("(%s): Block 0 Error\n",
+ dev_name(&device->cdev->dev));
break;
case 0x07:
PRINT_WARN("(%s): Medium Exception 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f70.md);
+ dev_name(&device->cdev->dev), sense->fmt.f70.md);
break;
default:
PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f70.emc);
+ dev_name(&device->cdev->dev), sense->fmt.f70.emc);
break;
}
/* Service Message */
switch (sense->fmt.f70.smc) {
case 0x02:
PRINT_WARN("(%s): Reference Media maintenance procedure %i\n",
- device->cdev->dev.bus_id, sense->fmt.f70.md);
+ dev_name(&device->cdev->dev), sense->fmt.f70.md);
break;
default:
PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f70.smc);
+ dev_name(&device->cdev->dev), sense->fmt.f70.smc);
break;
}
}
@@ -1054,101 +1057,101 @@ tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb)
switch (sense->fmt.f71.emc) {
case 0x01:
PRINT_WARN("(%s): Effect of failure is unknown\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x02:
PRINT_WARN("(%s): CU Exception - no performance impact\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x03:
PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x04:
PRINT_WARN("(%s): CU Exception on device path 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x05:
PRINT_WARN("(%s): CU Exception on library path 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x06:
PRINT_WARN("(%s): CU Exception on node 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x07:
PRINT_WARN("(%s): CU Exception on partition 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
default:
PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.emc);
+ dev_name(&device->cdev->dev), sense->fmt.f71.emc);
}
/* Service Message */
switch (sense->fmt.f71.smc) {
case 0x01:
PRINT_WARN("(%s): Repair impact is unknown\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x02:
PRINT_WARN("(%s): Repair will not impact cu performance\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x03:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable node "
"0x%x on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable nodes "
"(0x%x-0x%x) on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x04:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable cannel path "
"0x%x on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable cannel paths "
"(0x%x-0x%x) on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x05:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable device path "
"0x%x on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable device paths "
"(0x%x-0x%x) on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x06:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable library path "
"0x%x on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable library paths "
"(0x%x-0x%x) on CU\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x07:
PRINT_WARN("(%s): Repair will disable access to CU\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
default:
PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.smc);
+ dev_name(&device->cdev->dev), sense->fmt.f71.smc);
}
}
@@ -1165,104 +1168,104 @@ tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb)
switch (sense->fmt.f71.emc) {
case 0x01:
PRINT_WARN("(%s): Effect of failure is unknown\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x02:
PRINT_WARN("(%s): DV Exception - no performance impact\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x03:
PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x04:
PRINT_WARN("(%s): DV Exception on loader 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x05:
PRINT_WARN("(%s): DV Exception on message display 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.md[0]);
+ dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
break;
case 0x06:
PRINT_WARN("(%s): DV Exception in tape path\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x07:
PRINT_WARN("(%s): DV Exception in drive\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
default:
PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.emc);
+ dev_name(&device->cdev->dev), sense->fmt.f71.emc);
}
/* Service Message */
switch (sense->fmt.f71.smc) {
case 0x01:
PRINT_WARN("(%s): Repair impact is unknown\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x02:
PRINT_WARN("(%s): Repair will not impact device performance\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x03:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable channel path "
"0x%x on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable channel path "
"(0x%x-0x%x) on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x04:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable interface 0x%x "
"on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable interfaces "
"(0x%x-0x%x) on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x05:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable loader 0x%x "
"on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable loader "
"(0x%x-0x%x) on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x07:
PRINT_WARN("(%s): Repair will disable access to DV\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case 0x08:
if (sense->fmt.f71.mdf == 0)
PRINT_WARN("(%s): Repair will disable message "
"display 0x%x on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1]);
else
PRINT_WARN("(%s): Repair will disable message "
"displays (0x%x-0x%x) on DV\n",
- device->cdev->dev.bus_id,
+ dev_name(&device->cdev->dev),
sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
break;
case 0x09:
- PRINT_WARN("(%s): Clean DV\n", device->cdev->dev.bus_id);
+ PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev));
break;
default:
PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.smc);
+ dev_name(&device->cdev->dev), sense->fmt.f71.smc);
}
}
@@ -1279,18 +1282,18 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
return;
if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) {
if (tape_3590_msg[sense->mc] != NULL)
- PRINT_WARN("(%s): %s\n", device->cdev->dev.bus_id,
+ PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev),
tape_3590_msg[sense->mc]);
else {
PRINT_WARN("(%s): Message Code 0x%x\n",
- device->cdev->dev.bus_id, sense->mc);
+ dev_name(&device->cdev->dev), sense->mc);
}
return;
}
if (sense->mc == 0xf0) {
/* Standard Media Information Message */
PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, "
- "RC=%02x-%04x-%02x\n", device->cdev->dev.bus_id,
+ "RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev),
sense->fmt.f70.sev, sense->mc,
sense->fmt.f70.emc, sense->fmt.f70.smc,
sense->fmt.f70.refcode, sense->fmt.f70.mid,
@@ -1302,7 +1305,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
/* Standard I/O Subsystem Service Information Message */
PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, "
"MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.sev,
+ dev_name(&device->cdev->dev), sense->fmt.f71.sev,
device->cdev->id.dev_model,
sense->mc, sense->fmt.f71.emc,
sense->fmt.f71.smc, sense->fmt.f71.refcode1,
@@ -1314,7 +1317,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
/* Standard Device Service Information Message */
PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, "
"MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
- device->cdev->dev.bus_id, sense->fmt.f71.sev,
+ dev_name(&device->cdev->dev), sense->fmt.f71.sev,
device->cdev->id.dev_model,
sense->mc, sense->fmt.f71.emc,
sense->fmt.f71.smc, sense->fmt.f71.refcode1,
@@ -1327,7 +1330,7 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
return;
}
PRINT_WARN("(%s): Device Message(%x)\n",
- device->cdev->dev.bus_id, sense->mc);
+ dev_name(&device->cdev->dev), sense->mc);
}
static int tape_3590_crypt_error(struct tape_device *device,
@@ -1336,10 +1339,11 @@ static int tape_3590_crypt_error(struct tape_device *device,
u8 cu_rc, ekm_rc1;
u16 ekm_rc2;
u32 drv_rc;
- char *bus_id, *sense;
+ const char *bus_id;
+ char *sense;
sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;
- bus_id = device->cdev->dev.bus_id;
+ bus_id = dev_name(&device->cdev->dev);
cu_rc = sense[0];
drv_rc = *((u32*) &sense[5]) & 0xffffff;
ekm_rc1 = sense[9];
@@ -1440,7 +1444,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
* "device intervention" is not very meaningfull
*/
PRINT_WARN("(%s): Tape operation when medium not loaded\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
tape_med_state_set(device, MS_UNLOADED);
tape_3590_schedule_work(device, TO_CRYPT_OFF);
return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
@@ -1487,18 +1491,18 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
case 0x6020:
PRINT_WARN("(%s): Cartridge of wrong type ?\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE);
case 0x8011:
PRINT_WARN("(%s): Another host has reserved the tape device\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
return tape_3590_erp_basic(device, request, irb, -EPERM);
case 0x8013:
PRINT_WARN("(%s): Another host has privileged access to the "
- "tape device\n", device->cdev->dev.bus_id);
+ "tape device\n", dev_name(&device->cdev->dev));
PRINT_WARN("(%s): To solve the problem unload the current "
- "cartridge!\n", device->cdev->dev.bus_id);
+ "cartridge!\n", dev_name(&device->cdev->dev));
return tape_3590_erp_basic(device, request, irb, -EPERM);
default:
return tape_3590_erp_basic(device, request, irb, -EIO);
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 95da72bc17e..a25b8bf54f4 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -278,7 +278,7 @@ tapeblock_cleanup_device(struct tape_device *device)
if (!device->blk_data.disk) {
PRINT_ERR("(%s): No gendisk to clean up!\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
goto cleanup_queue;
}
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 12c2a5aaf31..ddc914ccea8 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,9 +69,9 @@ struct tape_class_device *register_tape_dev(
if (rc)
goto fail_with_cdev;
- tcd->class_device = device_create_drvdata(tape_class, device,
- tcd->char_device->dev,
- NULL, "%s", tcd->device_name);
+ tcd->class_device = device_create(tape_class, device,
+ tcd->char_device->dev, NULL,
+ "%s", tcd->device_name);
rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
if (rc)
goto fail_with_cdev;
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 181a5441af1..d7073dbf825 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -215,12 +215,12 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
case MS_UNLOADED:
device->tape_generic_status |= GMT_DR_OPEN(~0);
PRINT_INFO("(%s): Tape is unloaded\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
case MS_LOADED:
device->tape_generic_status &= ~GMT_DR_OPEN(~0);
PRINT_INFO("(%s): Tape has been mounted\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
break;
default:
// print nothing
@@ -415,7 +415,7 @@ tape_generic_offline(struct tape_device *device)
device->cdev_id);
PRINT_WARN("(%s): Set offline failed "
"- drive in use.\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return -EBUSY;
}
@@ -538,7 +538,8 @@ tape_generic_probe(struct ccw_device *cdev)
ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
if (ret) {
tape_put_device(device);
- PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id);
+ PRINT_ERR("probe failed for tape device %s\n",
+ dev_name(&cdev->dev));
return ret;
}
cdev->dev.driver_data = device;
@@ -546,7 +547,7 @@ tape_generic_probe(struct ccw_device *cdev)
device->cdev = cdev;
ccw_device_get_id(cdev, &dev_id);
device->cdev_id = devid_to_int(&dev_id);
- PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
+ PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev));
return ret;
}
@@ -616,7 +617,7 @@ tape_generic_remove(struct ccw_device *cdev)
device->cdev_id);
PRINT_WARN("(%s): Drive in use vanished - "
"expect trouble!\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
PRINT_WARN("State was %i\n", device->tape_state);
tape_state_set(device, TS_NOT_OPER);
__tape_discard_requests(device);
@@ -840,7 +841,7 @@ tape_dump_sense(struct tape_device* device, struct tape_request *request,
PRINT_INFO("-------------------------------------------------\n");
PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n",
irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa);
- PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id);
+ PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev));
if (request != NULL)
PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]);
@@ -1051,7 +1052,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
device = (struct tape_device *) cdev->dev.driver_data;
if (device == NULL) {
PRINT_ERR("could not get device structure for %s "
- "in interrupt\n", cdev->dev.bus_id);
+ "in interrupt\n", dev_name(&cdev->dev));
return;
}
request = (struct tape_request *) intparm;
@@ -1064,13 +1065,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
switch (PTR_ERR(irb)) {
case -ETIMEDOUT:
PRINT_WARN("(%s): Request timed out\n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
case -EIO:
__tape_end_request(device, request, -EIO);
break;
default:
PRINT_ERR("(%s): Unexpected i/o error %li\n",
- cdev->dev.bus_id,
+ dev_name(&cdev->dev),
PTR_ERR(irb));
}
return;
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index e7c888c14e7..8a376af926a 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -52,7 +52,7 @@ static int tape_proc_show(struct seq_file *m, void *v)
return 0;
spin_lock_irq(get_ccwdev_lock(device->cdev));
seq_printf(m, "%d\t", (int) n);
- seq_printf(m, "%-10.10s ", device->cdev->dev.bus_id);
+ seq_printf(m, "%-10.10s ", dev_name(&device->cdev->dev));
seq_printf(m, "%04X/", device->cdev->id.cu_type);
seq_printf(m, "%02X\t", device->cdev->id.cu_model);
seq_printf(m, "%04X/", device->cdev->id.dev_type);
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index cc8fd781ee2..5bd573d144d 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -47,7 +47,7 @@ tape_std_assign_timeout(unsigned long data)
rc = tape_cancel_io(device, request);
if(rc)
PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n",
- device->cdev->dev.bus_id, rc);
+ dev_name(&device->cdev->dev), rc);
}
@@ -83,7 +83,7 @@ tape_std_assign(struct tape_device *device)
if (rc != 0) {
PRINT_WARN("%s: assign failed - device might be busy\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
device->cdev_id);
} else {
@@ -106,7 +106,7 @@ tape_std_unassign (struct tape_device *device)
DBF_EVENT(3, "(%08x): Can't unassign device\n",
device->cdev_id);
PRINT_WARN("(%s): Can't unassign device - device gone\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
return -EIO;
}
@@ -120,7 +120,8 @@ tape_std_unassign (struct tape_device *device)
if ((rc = tape_do_io(device, request)) != 0) {
DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);
- PRINT_WARN("%s: Unassign failed\n", device->cdev->dev.bus_id);
+ PRINT_WARN("%s: Unassign failed\n",
+ dev_name(&device->cdev->dev));
} else {
DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);
}
@@ -634,10 +635,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count)
DBF_EXCEPTION(6, "xcom parm\n");
if (*device->modeset_byte & 0x08)
PRINT_INFO("(%s) Compression is currently on\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
else
PRINT_INFO("(%s) Compression is currently off\n",
- device->cdev->dev.bus_id);
+ dev_name(&device->cdev->dev));
PRINT_INFO("Use 1 to switch compression on, 0 to "
"switch it off\n");
return -EINVAL;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c31faefa2b3..24762727bc2 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -724,8 +724,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (dev) {
- snprintf(dev->bus_id, BUS_ID_SIZE, "%s",
- priv->internal_name);
+ dev_set_name(dev, priv->internal_name);
dev->bus = &iucv_bus;
dev->parent = iucv_root;
dev->driver = &vmlogrdr_driver;
@@ -748,10 +747,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
device_unregister(dev);
return ret;
}
- priv->class_device = device_create_drvdata(vmlogrdr_class, dev,
- MKDEV(vmlogrdr_major,
- priv->minor_num),
- priv, "%s", dev->bus_id);
+ priv->class_device = device_create(vmlogrdr_class, dev,
+ MKDEV(vmlogrdr_major,
+ priv->minor_num),
+ priv, "%s", dev_name(dev));
if (IS_ERR(priv->class_device)) {
ret = PTR_ERR(priv->class_device);
priv->class_device=NULL;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index c1f352b8486..9020eba620e 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -886,19 +886,18 @@ static int ur_set_online(struct ccw_device *cdev)
goto fail_free_cdev;
if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) {
if (urd->class == DEV_CLASS_UR_I)
- sprintf(node_id, "vmrdr-%s", cdev->dev.bus_id);
+ sprintf(node_id, "vmrdr-%s", dev_name(&cdev->dev));
if (urd->class == DEV_CLASS_UR_O)
- sprintf(node_id, "vmpun-%s", cdev->dev.bus_id);
+ sprintf(node_id, "vmpun-%s", dev_name(&cdev->dev));
} else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) {
- sprintf(node_id, "vmprt-%s", cdev->dev.bus_id);
+ sprintf(node_id, "vmprt-%s", dev_name(&cdev->dev));
} else {
rc = -EOPNOTSUPP;
goto fail_free_cdev;
}
- urd->device = device_create_drvdata(vmur_class, NULL,
- urd->char_device->dev, NULL,
- "%s", node_id);
+ urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
+ NULL, "%s", node_id);
if (IS_ERR(urd->device)) {
rc = PTR_ERR(urd->device);
TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 0bfcbbe375c..2f547b840ef 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -24,6 +24,7 @@
#include "cio.h"
#include "cio_debug.h"
#include "css.h"
+#include "device.h"
/*
* "Blacklisting" of certain devices:
@@ -191,9 +192,9 @@ static int blacklist_parse_parameters(char *str, range_action action,
rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
msgtrigger);
if (rc)
- totalrc = 1;
+ totalrc = -EINVAL;
} else
- totalrc = 1;
+ totalrc = -EINVAL;
}
return totalrc;
@@ -240,8 +241,10 @@ static int blacklist_parse_proc_parameters(char *buf)
rc = blacklist_parse_parameters(buf, free, 0);
else if (strcmp("add", parm) == 0)
rc = blacklist_parse_parameters(buf, add, 0);
+ else if (strcmp("purge", parm) == 0)
+ return ccw_purge_blacklisted();
else
- return 1;
+ return -EINVAL;
css_schedule_reprobe();
@@ -353,7 +356,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
}
ret = blacklist_parse_proc_parameters(buf);
if (ret)
- rc = -EINVAL;
+ rc = ret;
else
rc = user_len;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e0ce65fca4e..3ac2c2019f5 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -113,7 +113,8 @@ ccwgroup_release (struct device *dev)
for (i = 0; i < gdev->count; i++) {
if (gdev->cdev[i]) {
- dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
+ if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
+ dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
put_device(&gdev->cdev[i]->dev);
}
}
@@ -268,8 +269,7 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
goto error;
}
- snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
- gdev->cdev[0]->dev.bus_id);
+ dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
rc = device_add(&gdev->dev);
if (rc)
@@ -296,6 +296,7 @@ error:
if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
put_device(&gdev->cdev[i]->dev);
+ gdev->cdev[i] = NULL;
}
mutex_unlock(&gdev->reg_mutex);
put_device(&gdev->dev);
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index db00b059173..1246f61a533 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -393,8 +393,7 @@ int chp_new(struct chp_id chpid)
chp->state = 1;
chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
chp->dev.release = chp_release;
- snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid,
- chpid.id);
+ dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
/* Obtain channel path description and fill it in. */
ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
@@ -423,7 +422,7 @@ int chp_new(struct chp_id chpid)
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
if (ret) {
device_unregister(&chp->dev);
- goto out_free;
+ goto out;
}
mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
if (channel_subsystems[chpid.cssid]->cm_enabled) {
@@ -432,14 +431,15 @@ int chp_new(struct chp_id chpid)
sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
device_unregister(&chp->dev);
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
- goto out_free;
+ goto out;
}
}
channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
- return ret;
+ goto out;
out_free:
kfree(chp);
+out:
return ret;
}
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 91ca87aa9f9..f49f0e502b8 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -261,7 +261,7 @@ static int chsc_examine_irb(struct chsc_request *request)
{
int backed_up;
- if (!scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND)
+ if (!(scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND))
return -EIO;
backed_up = scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHAIN_CHECK;
request->irb.scsw.cmd.cstat &= ~SCHN_STAT_CHAIN_CHECK;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 33bff8fec7d..3db2c386546 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -114,6 +114,7 @@ cio_tpi(void)
struct tpi_info *tpi_info;
struct subchannel *sch;
struct irb *irb;
+ int irq_context;
tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
if (tpi (NULL) != 1)
@@ -126,7 +127,9 @@ cio_tpi(void)
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
if (!sch)
return 1;
- local_bh_disable();
+ irq_context = in_interrupt();
+ if (!irq_context)
+ local_bh_disable();
irq_enter ();
spin_lock(sch->lock);
memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
@@ -134,7 +137,8 @@ cio_tpi(void)
sch->driver->irq(sch);
spin_unlock(sch->lock);
irq_exit ();
- _local_bh_enable();
+ if (!irq_context)
+ _local_bh_enable();
return 1;
}
@@ -153,7 +157,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
"subchannel 0.%x.%04x!\n", sch->schid.ssid,
sch->schid.sch_no);
- sprintf(dbf_text, "no%s", sch->dev.bus_id);
+ sprintf(dbf_text, "no%s", dev_name(&sch->dev));
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -171,9 +175,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
union orb *orb;
CIO_TRACE_EVENT(4, "stIO");
- CIO_TRACE_EVENT(4, sch->dev.bus_id);
+ CIO_TRACE_EVENT(4, dev_name(&sch->dev));
orb = &to_io_private(sch)->orb;
+ memset(orb, 0, sizeof(union orb));
/* sch is always under 2G. */
orb->cmd.intparm = (u32)(addr_t)sch;
orb->cmd.fmt = 1;
@@ -208,8 +213,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
case 1: /* status pending */
case 2: /* busy */
return -EBUSY;
- default: /* device/path not operational */
+ case 3: /* device/path not operational */
return cio_start_handle_notoper(sch, lpm);
+ default:
+ return ccode;
}
}
@@ -229,7 +236,7 @@ cio_resume (struct subchannel *sch)
int ccode;
CIO_TRACE_EVENT (4, "resIO");
- CIO_TRACE_EVENT (4, sch->dev.bus_id);
+ CIO_TRACE_EVENT(4, dev_name(&sch->dev));
ccode = rsch (sch->schid);
@@ -266,7 +273,7 @@ cio_halt(struct subchannel *sch)
return -ENODEV;
CIO_TRACE_EVENT (2, "haltIO");
- CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
/*
* Issue "Halt subchannel" and process condition code
@@ -301,7 +308,7 @@ cio_clear(struct subchannel *sch)
return -ENODEV;
CIO_TRACE_EVENT (2, "clearIO");
- CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
/*
* Issue "Clear subchannel" and process condition code
@@ -337,7 +344,7 @@ cio_cancel (struct subchannel *sch)
return -ENODEV;
CIO_TRACE_EVENT (2, "cancelIO");
- CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
ccode = xsch (sch->schid);
@@ -401,7 +408,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
int ret;
CIO_TRACE_EVENT (2, "ensch");
- CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
if (sch_is_pseudo_sch(sch))
return -EINVAL;
@@ -451,7 +458,7 @@ int cio_disable_subchannel(struct subchannel *sch)
int ret;
CIO_TRACE_EVENT (2, "dissch");
- CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
if (sch_is_pseudo_sch(sch))
return 0;
@@ -568,8 +575,10 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
}
mutex_init(&sch->reg_mutex);
/* Set a name for the subchannel */
- snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
- schid.sch_no);
+ if (cio_is_console(schid))
+ sch->dev.init_name = cio_get_console_sch_name(schid);
+ else
+ dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no);
/*
* The first subchannel that is not-operational (ccode==3)
@@ -674,6 +683,7 @@ do_IRQ (struct pt_regs *regs)
#ifdef CONFIG_CCW_CONSOLE
static struct subchannel console_subchannel;
+static char console_sch_name[10] = "0.x.xxxx";
static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
@@ -824,6 +834,12 @@ cio_get_console_subchannel(void)
return &console_subchannel;
}
+const char *cio_get_console_sch_name(struct subchannel_id schid)
+{
+ snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no);
+ return (const char *)console_sch_name;
+}
+
#endif
static int
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
@@ -843,19 +859,6 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
return -EBUSY; /* uhm... */
}
-/* we can't use the normal udelay here, since it enables external interrupts */
-
-static void udelay_reset(unsigned long usecs)
-{
- uint64_t start_cc, end_cc;
-
- asm volatile ("STCK %0" : "=m" (start_cc));
- do {
- cpu_relax();
- asm volatile ("STCK %0" : "=m" (end_cc));
- } while (((end_cc - start_cc)/4096) < usecs);
-}
-
static int
__clear_io_subchannel_easy(struct subchannel_id schid)
{
@@ -871,7 +874,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
if (schid_equal(&ti.schid, &schid))
return 0;
}
- udelay_reset(100);
+ udelay_simple(100);
}
return -EBUSY;
}
@@ -879,7 +882,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
static void __clear_chsc_subchannel_easy(void)
{
/* It seems we can only wait for a bit here :/ */
- udelay_reset(100);
+ udelay_simple(100);
}
static int pgm_check_occured;
@@ -889,7 +892,7 @@ static void cio_reset_pgm_check_handler(void)
pgm_check_occured = 1;
}
-static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
+static int stsch_reset(struct subchannel_id schid, struct schib *addr)
{
int rc;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 3b236d20e83..0fb24784e92 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -117,11 +117,15 @@ extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
extern spinlock_t * cio_get_console_lock(void);
extern void *cio_get_console_priv(void);
+extern const char *cio_get_console_sch_name(struct subchannel_id schid);
+extern const char *cio_get_console_cdev_name(struct subchannel *sch);
#else
#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#define cio_get_console_lock() NULL
#define cio_get_console_priv() NULL
+#define cio_get_console_sch_name(schid) NULL
+#define cio_get_console_cdev_name(sch) NULL
#endif
#endif
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 51489eff6b0..76bbb1e74c2 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
css = to_css(dev);
mutex_destroy(&css->mutex);
+ if (css->pseudo_subchannel) {
+ /* Implies that it has been generated but never registered. */
+ css_subchannel_release(&css->pseudo_subchannel->dev);
+ css->pseudo_subchannel = NULL;
+ }
kfree(css);
}
@@ -693,7 +698,7 @@ static int __init setup_css(int nr)
return -ENOMEM;
css->pseudo_subchannel->dev.parent = &css->device;
css->pseudo_subchannel->dev.release = css_subchannel_release;
- sprintf(css->pseudo_subchannel->dev.bus_id, "defunct");
+ dev_set_name(&css->pseudo_subchannel->dev, "defunct");
ret = cio_create_sch_lock(css->pseudo_subchannel);
if (ret) {
kfree(css->pseudo_subchannel);
@@ -702,7 +707,7 @@ static int __init setup_css(int nr)
mutex_init(&css->mutex);
css->valid = 1;
css->cssid = nr;
- sprintf(css->device.bus_id, "css%x", nr);
+ dev_set_name(&css->device, "css%x", nr);
css->device.release = channel_subsystem_release;
tod_high = (u32) (get_clock() >> 32);
css_generate_pgid(css, tod_high);
@@ -785,11 +790,15 @@ init_channel_subsystem (void)
}
channel_subsystems[i] = css;
ret = setup_css(i);
- if (ret)
- goto out_free;
+ if (ret) {
+ kfree(channel_subsystems[i]);
+ goto out_unregister;
+ }
ret = device_register(&css->device);
- if (ret)
- goto out_free_all;
+ if (ret) {
+ put_device(&css->device);
+ goto out_unregister;
+ }
if (css_chsc_characteristics.secm) {
ret = device_create_file(&css->device,
&dev_attr_cm_enable);
@@ -802,7 +811,7 @@ init_channel_subsystem (void)
}
ret = register_reboot_notifier(&css_reboot_notifier);
if (ret)
- goto out_pseudo;
+ goto out_unregister;
css_init_done = 1;
/* Enable default isc for I/O subchannels. */
@@ -810,18 +819,12 @@ init_channel_subsystem (void)
for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
-out_pseudo:
- device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
out_file:
- device_remove_file(&channel_subsystems[i]->device,
- &dev_attr_cm_enable);
+ if (css_chsc_characteristics.secm)
+ device_remove_file(&channel_subsystems[i]->device,
+ &dev_attr_cm_enable);
out_device:
device_unregister(&channel_subsystems[i]->device);
-out_free_all:
- kfree(channel_subsystems[i]->pseudo_subchannel->lock);
- kfree(channel_subsystems[i]->pseudo_subchannel);
-out_free:
- kfree(channel_subsystems[i]);
out_unregister:
while (i > 0) {
struct channel_subsystem *css;
@@ -829,6 +832,7 @@ out_unregister:
i--;
css = channel_subsystems[i];
device_unregister(&css->pseudo_subchannel->dev);
+ css->pseudo_subchannel = NULL;
if (css_chsc_characteristics.secm)
device_remove_file(&css->device,
&dev_attr_cm_enable);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 28221030b88..4e78c82194b 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -31,6 +31,7 @@
#include "device.h"
#include "ioasm.h"
#include "io_sch.h"
+#include "blacklist.h"
static struct timer_list recovery_timer;
static DEFINE_SPINLOCK(recovery_lock);
@@ -296,36 +297,33 @@ static void ccw_device_unregister(struct ccw_device *cdev)
device_del(&cdev->dev);
}
-static void ccw_device_remove_orphan_cb(struct device *dev)
+static void ccw_device_remove_orphan_cb(struct work_struct *work)
{
- struct ccw_device *cdev = to_ccwdev(dev);
+ struct ccw_device_private *priv;
+ struct ccw_device *cdev;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
ccw_device_unregister(cdev);
put_device(&cdev->dev);
+ /* Release cdev reference for workqueue processing. */
+ put_device(&cdev->dev);
}
-static void ccw_device_remove_sch_cb(struct device *dev)
-{
- struct subchannel *sch;
-
- sch = to_subchannel(dev);
- css_sch_device_unregister(sch);
- /* Reset intparm to zeroes. */
- sch->schib.pmcw.intparm = 0;
- cio_modify(sch);
- put_device(&sch->dev);
-}
+static void ccw_device_call_sch_unregister(struct work_struct *work);
static void
ccw_device_remove_disconnected(struct ccw_device *cdev)
{
unsigned long flags;
- int rc;
/*
* Forced offline in disconnected state means
* 'throw away device'.
*/
+ /* Get cdev reference for workqueue processing. */
+ if (!get_device(&cdev->dev))
+ return;
if (ccw_device_is_orphan(cdev)) {
/*
* Deregister ccw device.
@@ -335,23 +333,13 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
spin_lock_irqsave(cdev->ccwlock, flags);
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
- rc = device_schedule_callback(&cdev->dev,
- ccw_device_remove_orphan_cb);
- if (rc)
- CIO_MSG_EVENT(0, "Couldn't unregister orphan "
- "0.%x.%04x\n",
- cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno);
- return;
- }
- /* Deregister subchannel, which will kill the ccw device. */
- rc = device_schedule_callback(cdev->dev.parent,
- ccw_device_remove_sch_cb);
- if (rc)
- CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
- "0.%x.%04x\n",
- cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno);
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_remove_orphan_cb);
+ } else
+ /* Deregister subchannel, which will kill the ccw device. */
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_call_sch_unregister);
+ queue_work(slow_path_wq, &cdev->private->kick_work);
}
/**
@@ -970,12 +958,17 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
+ /* Get subchannel reference for local processing. */
+ if (!get_device(cdev->dev.parent))
+ return;
sch = to_subchannel(cdev->dev.parent);
css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
+ /* Release cdev reference for workqueue processing.*/
put_device(&cdev->dev);
+ /* Release subchannel reference for local processing. */
put_device(&sch->dev);
}
@@ -1001,6 +994,8 @@ io_subchannel_recog_done(struct ccw_device *cdev)
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_call_sch_unregister);
queue_work(slow_path_wq, &cdev->private->kick_work);
+ /* Release subchannel reference for asynchronous recognition. */
+ put_device(&sch->dev);
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
break;
@@ -1040,8 +1035,11 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
init_timer(&priv->timer);
/* Set an initial name for the device. */
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
- sch->schid.ssid, sch->schib.pmcw.dev);
+ if (cio_is_console(sch->schid))
+ cdev->dev.init_name = cio_get_console_cdev_name(sch);
+ else
+ dev_set_name(&cdev->dev, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
/* Increase counter of devices currently in recognition. */
atomic_inc(&ccw_device_init_count);
@@ -1106,7 +1104,7 @@ static void io_subchannel_irq(struct subchannel *sch)
cdev = sch_get_cdev(sch);
CIO_TRACE_EVENT(3, "IRQ");
- CIO_TRACE_EVENT(3, sch->dev.bus_id);
+ CIO_TRACE_EVENT(3, dev_name(&sch->dev));
if (cdev)
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
}
@@ -1476,6 +1474,45 @@ static void ccw_device_schedule_recovery(void)
spin_unlock_irqrestore(&recovery_lock, flags);
}
+static int purge_fn(struct device *dev, void *data)
+{
+ struct ccw_device *cdev = to_ccwdev(dev);
+ struct ccw_device_private *priv = cdev->private;
+ int unreg;
+
+ spin_lock_irq(cdev->ccwlock);
+ unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) &&
+ (priv->state == DEV_STATE_OFFLINE);
+ spin_unlock_irq(cdev->ccwlock);
+ if (!unreg)
+ goto out;
+ if (!get_device(&cdev->dev))
+ goto out;
+ CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
+ priv->dev_id.devno);
+ PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister);
+ queue_work(slow_path_wq, &cdev->private->kick_work);
+
+out:
+ /* Abort loop in case of pending signal. */
+ if (signal_pending(current))
+ return -EINTR;
+
+ return 0;
+}
+
+/**
+ * ccw_purge_blacklisted - purge unused, blacklisted devices
+ *
+ * Unregister all ccw devices that are offline and on the blacklist.
+ */
+int ccw_purge_blacklisted(void)
+{
+ CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
+ bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
+ return 0;
+}
+
static void device_set_disconnected(struct ccw_device *cdev)
{
if (!cdev)
@@ -1492,7 +1529,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
struct subchannel *sch = to_subchannel(cdev->dev.parent);
CIO_TRACE_EVENT(2, "notoper");
- CIO_TRACE_EVENT(2, sch->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&sch->dev));
ccw_device_set_timeout(cdev, 0);
cio_disable_subchannel(sch);
cdev->private->state = DEV_STATE_NOT_OPER;
@@ -1591,6 +1628,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
#ifdef CONFIG_CCW_CONSOLE
static struct ccw_device console_cdev;
+static char console_cdev_name[10] = "0.x.xxxx";
static struct ccw_device_private console_private;
static int console_cdev_in_use;
@@ -1661,6 +1699,14 @@ ccw_device_probe_console(void)
console_cdev.online = 1;
return &console_cdev;
}
+
+
+const char *cio_get_console_cdev_name(struct subchannel *sch)
+{
+ snprintf(console_cdev_name, 10, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
+ return (const char *)console_cdev_name;
+}
#endif
/*
@@ -1673,7 +1719,7 @@ __ccwdev_check_busid(struct device *dev, void *id)
bus_id = id;
- return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
+ return (strncmp(bus_id, dev_name(dev), BUS_ID_SIZE) == 0);
}
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 6f5c3f2b358..104ed669db4 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -86,6 +86,7 @@ int ccw_device_is_orphan(struct ccw_device *);
int ccw_device_recognition(struct ccw_device *);
int ccw_device_online(struct ccw_device *);
int ccw_device_offline(struct ccw_device *);
+int ccw_purge_blacklisted(void);
/* Function prototypes for device status and basic sense stuff. */
void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 550508df952..10bc03940fb 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -52,8 +52,10 @@ static void ccw_timeout_log(struct ccw_device *cdev)
printk(KERN_WARNING "cio: orb:\n");
print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
orb, sizeof(*orb), 0);
- printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id);
- printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id);
+ printk(KERN_WARNING "cio: ccw device bus id: %s\n",
+ dev_name(&cdev->dev));
+ printk(KERN_WARNING "cio: subchannel bus id: %s\n",
+ dev_name(&sch->dev));
printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, "
"vpm: %02x\n", sch->lpm, sch->opm, sch->vpm);
@@ -658,6 +660,13 @@ ccw_device_offline(struct ccw_device *cdev)
{
struct subchannel *sch;
+ /* Allow ccw_device_offline while disconnected. */
+ if (cdev->private->state == DEV_STATE_DISCONNECTED ||
+ cdev->private->state == DEV_STATE_NOT_OPER) {
+ cdev->private->flags.donotify = 0;
+ ccw_device_done(cdev, DEV_STATE_NOT_OPER);
+ return 0;
+ }
if (ccw_device_is_orphan(cdev)) {
ccw_device_done(cdev, DEV_STATE_OFFLINE);
return 0;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index ee1a28310fb..eabcc42d63d 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -498,7 +498,7 @@ ccw_device_stlck(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent);
CIO_TRACE_EVENT(2, "stl lock");
- CIO_TRACE_EVENT(2, cdev->dev.bus_id);
+ CIO_TRACE_EVENT(2, dev_name(&cdev->dev));
buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
if (!buf)
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 3f8f1cf69c7..c4f3e7c9a85 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -123,7 +123,7 @@ struct ccw_device_private {
void *cmb_wait; /* deferred cmb enable/disable */
};
-static inline int ssch(struct subchannel_id schid, volatile union orb *addr)
+static inline int ssch(struct subchannel_id schid, union orb *addr)
{
register struct subchannel_id reg1 asm("1") = schid;
int ccode = -EIO;
@@ -134,7 +134,9 @@ static inline int ssch(struct subchannel_id schid, volatile union orb *addr)
" srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
- : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc", "memory");
return ccode;
}
@@ -147,7 +149,9 @@ static inline int rsch(struct subchannel_id schid)
" rsch\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1) : "cc");
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc", "memory");
return ccode;
}
@@ -160,7 +164,9 @@ static inline int csch(struct subchannel_id schid)
" csch\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1) : "cc");
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc");
return ccode;
}
@@ -173,7 +179,9 @@ static inline int hsch(struct subchannel_id schid)
" hsch\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1) : "cc");
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc");
return ccode;
}
@@ -186,7 +194,9 @@ static inline int xsch(struct subchannel_id schid)
" .insn rre,0xb2760000,%1,0\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1) : "cc");
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc");
return ccode;
}
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 9fa2ac13ac8..75926279263 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -23,38 +23,39 @@ struct tpi_info {
* Some S390 specific IO instructions as inline
*/
-static inline int stsch(struct subchannel_id schid,
- volatile struct schib *addr)
+static inline int stsch(struct subchannel_id schid, struct schib *addr)
{
register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
asm volatile(
- " stsch 0(%2)\n"
+ " stsch 0(%3)\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "=d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
return ccode;
}
-static inline int stsch_err(struct subchannel_id schid,
- volatile struct schib *addr)
+static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
{
register struct subchannel_id reg1 asm ("1") = schid;
int ccode = -EIO;
asm volatile(
- " stsch 0(%2)\n"
+ " stsch 0(%3)\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
- : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "+d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
return ccode;
}
-static inline int msch(struct subchannel_id schid,
- volatile struct schib *addr)
+static inline int msch(struct subchannel_id schid, struct schib *addr)
{
register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
@@ -63,12 +64,13 @@ static inline int msch(struct subchannel_id schid,
" msch 0(%2)\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "=d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
return ccode;
}
-static inline int msch_err(struct subchannel_id schid,
- volatile struct schib *addr)
+static inline int msch_err(struct subchannel_id schid, struct schib *addr)
{
register struct subchannel_id reg1 asm ("1") = schid;
int ccode = -EIO;
@@ -79,33 +81,38 @@ static inline int msch_err(struct subchannel_id schid,
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
- : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
return ccode;
}
-static inline int tsch(struct subchannel_id schid,
- volatile struct irb *addr)
+static inline int tsch(struct subchannel_id schid, struct irb *addr)
{
register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
asm volatile(
- " tsch 0(%2)\n"
+ " tsch 0(%3)\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+ : "=d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
return ccode;
}
-static inline int tpi( volatile struct tpi_info *addr)
+static inline int tpi(struct tpi_info *addr)
{
int ccode;
asm volatile(
- " tpi 0(%1)\n"
+ " tpi 0(%2)\n"
" ipm %0\n"
" srl %0,28"
- : "=d" (ccode) : "a" (addr), "m" (*addr) : "cc");
+ : "=d" (ccode), "=m" (*addr)
+ : "a" (addr)
+ : "cc");
return ccode;
}
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index c1a70985abf..e3ea1d5f281 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -16,6 +16,14 @@
#define QDIO_BUSY_BIT_GIVE_UP 2000000 /* 2 seconds = eternity */
#define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */
+/*
+ * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
+ * till next initiative to give transmitted skbs back to the stack is too long.
+ * Therefore polling is started in case of multicast queue is filled more
+ * than 50 percent.
+ */
+#define QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */
+
enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE,
QDIO_IRQ_STATE_ESTABLISHED,
@@ -195,6 +203,9 @@ struct qdio_output_q {
/* PCIs are enabled for the queue */
int pci_out_enabled;
+ /* IQDIO: output multiple buffers (enhanced SIGA) */
+ int use_enh_siga;
+
/* timer to check for more outbound work */
struct timer_list timer;
};
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 337aa3087a7..b5390821434 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -155,7 +155,7 @@ static int qstat_seq_open(struct inode *inode, struct file *filp)
static void get_queue_name(struct qdio_q *q, struct ccw_device *cdev, char *name)
{
memset(name, 0, sizeof(name));
- sprintf(name, "%s", cdev->dev.bus_id);
+ sprintf(name, "%s", dev_name(&cdev->dev));
if (q->is_input_q)
sprintf(name + strlen(name), "_input");
else
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index e6eabc85342..a50682d2a0f 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -316,6 +316,9 @@ static inline int qdio_do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
unsigned int fc = 0;
unsigned long schid;
+ if (q->u.out.use_enh_siga) {
+ fc = 3;
+ }
if (!is_qebsm(q))
schid = *((u32 *)&q->irq_ptr->schid);
else {
@@ -851,6 +854,12 @@ static void __qdio_outbound_processing(struct qdio_q *q)
if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q))
return;
+ if ((queue_type(q) == QDIO_IQDIO_QFMT) &&
+ (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) {
+ tasklet_schedule(&q->tasklet);
+ return;
+ }
+
if (q->u.out.pci_out_enabled)
return;
@@ -956,7 +965,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
char dbf_text[15];
QDIO_DBF_TEXT2(1, trace, "ick2");
- sprintf(dbf_text, "%s", cdev->dev.bus_id);
+ sprintf(dbf_text, "%s", dev_name(&cdev->dev));
QDIO_DBF_TEXT2(1, trace, dbf_text);
QDIO_DBF_HEX2(0, trace, &intparm, sizeof(int));
QDIO_DBF_HEX2(0, trace, &dstat, sizeof(int));
@@ -1443,6 +1452,8 @@ int qdio_establish(struct qdio_initialize *init_data)
}
qdio_setup_ssqd_info(irq_ptr);
+ sprintf(dbf_text, "qDmmwc%2x", irq_ptr->ssqd_desc.mmwc);
+ QDIO_DBF_TEXT2(0, setup, dbf_text);
sprintf(dbf_text, "qib ac%2x", irq_ptr->qib.ac);
QDIO_DBF_TEXT2(0, setup, dbf_text);
@@ -1615,12 +1626,21 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags,
if (multicast_outbound(q))
qdio_kick_outbound_q(q);
else
- /*
- * One siga-w per buffer required for unicast
- * HiperSockets.
- */
- while (count--)
+ if ((q->irq_ptr->ssqd_desc.mmwc > 1) &&
+ (count > 1) &&
+ (count <= q->irq_ptr->ssqd_desc.mmwc)) {
+ /* exploit enhanced SIGA */
+ q->u.out.use_enh_siga = 1;
qdio_kick_outbound_q(q);
+ } else {
+ /*
+ * One siga-w per buffer required for unicast
+ * HiperSockets.
+ */
+ q->u.out.use_enh_siga = 0;
+ while (count--)
+ qdio_kick_outbound_q(q);
+ }
goto out;
}
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 1679e2f91c9..a0b6b46e746 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -447,51 +447,36 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
{
char s[80];
- sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no);
-
+ sprintf(s, "qdio: %s ", dev_name(&cdev->dev));
switch (irq_ptr->qib.qfmt) {
case QDIO_QETH_QFMT:
- sprintf(s + strlen(s), "OSADE ");
+ sprintf(s + strlen(s), "OSA ");
break;
case QDIO_ZFCP_QFMT:
sprintf(s + strlen(s), "ZFCP ");
break;
case QDIO_IQDIO_QFMT:
- sprintf(s + strlen(s), "HiperSockets ");
+ sprintf(s + strlen(s), "HS ");
break;
}
- sprintf(s + strlen(s), "using: ");
-
- if (!is_thinint_irq(irq_ptr))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "AdapterInterrupts ");
- if (!(irq_ptr->sch_token != 0))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "QEBSM ");
- if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "OutboundPCI ");
- if (!css_general_characteristics.aif_tdd)
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "TDD\n");
- printk(KERN_INFO "qdio: %s", s);
-
- memset(s, 0, sizeof(s));
- sprintf(s, "%s SIGA required: ", cdev->dev.bus_id);
- if (irq_ptr->siga_flag.input)
- sprintf(s + strlen(s), "Read ");
- if (irq_ptr->siga_flag.output)
- sprintf(s + strlen(s), "Write ");
- if (irq_ptr->siga_flag.sync)
- sprintf(s + strlen(s), "Sync ");
- if (!irq_ptr->siga_flag.no_sync_ti)
- sprintf(s + strlen(s), "SyncAI ");
- if (!irq_ptr->siga_flag.no_sync_out_ti)
- sprintf(s + strlen(s), "SyncOutAI ");
- if (!irq_ptr->siga_flag.no_sync_out_pci)
- sprintf(s + strlen(s), "SyncOutPCI");
+ sprintf(s + strlen(s), "on SC %x using ", irq_ptr->schid.sch_no);
+ sprintf(s + strlen(s), "AI:%d ", is_thinint_irq(irq_ptr));
+ sprintf(s + strlen(s), "QEBSM:%d ", (irq_ptr->sch_token) ? 1 : 0);
+ sprintf(s + strlen(s), "PCI:%d ",
+ (irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) ? 1 : 0);
+ sprintf(s + strlen(s), "TDD:%d ", css_general_characteristics.aif_tdd);
+ sprintf(s + strlen(s), "SIGA:");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.input) ? "R" : " ");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.output) ? "W" : " ");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.sync) ? "S" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
sprintf(s + strlen(s), "\n");
- printk(KERN_INFO "qdio: %s", s);
+ printk(KERN_INFO "%s", s);
}
int __init qdio_setup_init(void)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 62b6b55230d..326db1e827c 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -892,8 +892,8 @@ static void ap_scan_bus(struct work_struct *unused)
ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device;
- snprintf(ap_dev->device.bus_id, BUS_ID_SIZE, "card%02x",
- AP_QID_DEVICE(ap_dev->qid));
+ dev_set_name(&ap_dev->device, "card%02x",
+ AP_QID_DEVICE(ap_dev->qid));
ap_dev->device.release = ap_device_release;
rc = device_register(&ap_dev->device);
if (rc) {
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 292b60da6dc..ff4a6931bb8 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -24,6 +24,7 @@
#include <asm/kvm_virtio.h>
#include <asm/setup.h>
#include <asm/s390_ext.h>
+#include <asm/s390_rdev.h>
#define VIRTIO_SUBCODE_64 0x0D00
@@ -241,10 +242,7 @@ static struct virtio_config_ops kvm_vq_configspace_ops = {
* The root device for the kvm virtio devices.
* This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2.
*/
-static struct device kvm_root = {
- .parent = NULL,
- .bus_id = "kvm_s390",
-};
+static struct device *kvm_root;
/*
* adds a new device and register it with virtio
@@ -261,7 +259,7 @@ static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset)
return;
}
- kdev->vdev.dev.parent = &kvm_root;
+ kdev->vdev.dev.parent = kvm_root;
kdev->vdev.id.device = d->type;
kdev->vdev.config = &kvm_vq_configspace_ops;
kdev->desc = d;
@@ -317,15 +315,16 @@ static int __init kvm_devices_init(void)
if (!MACHINE_IS_KVM)
return -ENODEV;
- rc = device_register(&kvm_root);
- if (rc) {
+ kvm_root = s390_root_dev_register("kvm_s390");
+ if (IS_ERR(kvm_root)) {
+ rc = PTR_ERR(kvm_root);
printk(KERN_ERR "Could not register kvm_s390 root device");
return rc;
}
rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
if (rc) {
- device_unregister(&kvm_root);
+ s390_root_dev_unregister(kvm_root);
return rc;
}
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index e10ac9ab2d4..f5e618562c5 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -299,7 +299,7 @@ claw_probe(struct ccwgroup_device *cgdev)
probe_error(cgdev);
put_device(&cgdev->dev);
printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ dev_name(&cgdev->cdev[0]->dev), __func__, __LINE__);
CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
return rc;
}
@@ -584,7 +584,7 @@ claw_irq_handler(struct ccw_device *cdev,
if (!cdev->dev.driver_data) {
printk(KERN_WARNING "claw: unsolicited interrupt for device:"
"%s received c-%02x d-%02x\n",
- cdev->dev.bus_id, irb->scsw.cmd.cstat,
+ dev_name(&cdev->dev), irb->scsw.cmd.cstat,
irb->scsw.cmd.dstat);
CLAW_DBF_TEXT(2, trace, "badirq");
return;
@@ -598,7 +598,7 @@ claw_irq_handler(struct ccw_device *cdev,
p_ch = &privptr->channel[WRITE];
else {
printk(KERN_WARNING "claw: Can't determine channel for "
- "interrupt, device %s\n", cdev->dev.bus_id);
+ "interrupt, device %s\n", dev_name(&cdev->dev));
CLAW_DBF_TEXT(2, trace, "badchan");
return;
}
@@ -662,7 +662,7 @@ claw_irq_handler(struct ccw_device *cdev,
printk(KERN_WARNING "claw: unsolicited "
"interrupt for device:"
"%s received c-%02x d-%02x\n",
- cdev->dev.bus_id,
+ dev_name(&cdev->dev),
irb->scsw.cmd.cstat,
irb->scsw.cmd.dstat);
return;
@@ -1136,19 +1136,20 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
break;
case -ENODEV:
printk(KERN_EMERG "%s: Missing device called "
- "for IO ENODEV\n", cdev->dev.bus_id);
+ "for IO ENODEV\n", dev_name(&cdev->dev));
break;
case -EIO:
printk(KERN_EMERG "%s: Status pending... EIO \n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
break;
case -EINVAL:
printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
break;
default:
printk(KERN_EMERG "%s: Unknown error in "
- "Do_IO %d\n",cdev->dev.bus_id, return_code);
+ "Do_IO %d\n", dev_name(&cdev->dev),
+ return_code);
}
}
CLAW_DBF_TEXT(4, trace, "ccwret");
@@ -2848,11 +2849,11 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
struct chbk *p_ch;
struct ccw_dev_id dev_id;
- CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cdev->dev));
privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
p_ch = &privptr->channel[i];
p_ch->cdev = cdev;
- snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id);
+ snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", dev_name(&cdev->dev));
ccw_device_get_id(cdev, &dev_id);
p_ch->devno = dev_id.devno;
if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
@@ -2879,7 +2880,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
int ret;
struct ccw_dev_id dev_id;
- printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
+ printk(KERN_INFO "claw: add for %s\n",
+ dev_name(&cgdev->cdev[READ]->dev));
CLAW_DBF_TEXT(2, setup, "new_dev");
privptr = cgdev->dev.driver_data;
cgdev->cdev[READ]->dev.driver_data = privptr;
@@ -2903,14 +2905,16 @@ claw_new_device(struct ccwgroup_device *cgdev)
if (ret != 0) {
printk(KERN_WARNING
"claw: ccw_device_set_online %s READ failed "
- "with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
+ "with ret = %d\n", dev_name(&cgdev->cdev[READ]->dev),
+ ret);
goto out;
}
ret = ccw_device_set_online(cgdev->cdev[WRITE]);
if (ret != 0) {
printk(KERN_WARNING
"claw: ccw_device_set_online %s WRITE failed "
- "with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
+ "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev),
+ ret);
goto out;
}
dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
@@ -2986,7 +2990,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
struct net_device *ndev;
int ret;
- CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
priv = cgdev->dev.driver_data;
if (!priv)
return -ENODEV;
@@ -3016,11 +3020,11 @@ claw_remove_device(struct ccwgroup_device *cgdev)
struct claw_privbk *priv;
BUG_ON(!cgdev);
- CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
priv = cgdev->dev.driver_data;
BUG_ON(!priv);
printk(KERN_INFO "claw: %s() called %s will be removed.\n",
- __func__,cgdev->cdev[0]->dev.bus_id);
+ __func__, dev_name(&cgdev->cdev[0]->dev));
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
claw_remove_files(&cgdev->dev);
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 1a89d989f34..005072c420d 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -85,7 +85,7 @@
#define CLAW_MAX_DEV 256 /* max claw devices */
#define MAX_NAME_LEN 8 /* host name, adapter name length */
#define CLAW_FRAME_SIZE 4096
-#define CLAW_ID_SIZE BUS_ID_SIZE+3
+#define CLAW_ID_SIZE 20+3
/* state machine codes used in claw_irq_handler */
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index b11fec24c7d..a4e29836a2a 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -277,18 +277,18 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
"irb error %ld on device %s\n",
- PTR_ERR(irb), cdev->dev.bus_id);
+ PTR_ERR(irb), dev_name(&cdev->dev));
switch (PTR_ERR(irb)) {
case -EIO:
- ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
+ ctcm_pr_warn("i/o-error on device %s\n", dev_name(&cdev->dev));
break;
case -ETIMEDOUT:
- ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
+ ctcm_pr_warn("timeout on device %s\n", dev_name(&cdev->dev));
break;
default:
ctcm_pr_warn("unknown error %ld on device %s\n",
- PTR_ERR(irb), cdev->dev.bus_id);
+ PTR_ERR(irb), dev_name(&cdev->dev));
}
return PTR_ERR(irb);
}
@@ -1182,7 +1182,7 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
int dstat;
CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
- "Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id);
+ "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
if (ctcm_check_irb_error(cdev, irb))
return;
@@ -1208,14 +1208,14 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
ch = priv->channel[WRITE];
else {
ctcm_pr_err("ctcm: Can't determine channel for interrupt, "
- "device %s\n", cdev->dev.bus_id);
+ "device %s\n", dev_name(&cdev->dev));
return;
}
dev = ch->netdev;
if (dev == NULL) {
ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
- __func__, cdev->dev.bus_id, ch);
+ __func__, dev_name(&cdev->dev), ch);
return;
}
@@ -1329,7 +1329,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"%s(%s), type %d, proto %d",
- __func__, cdev->dev.bus_id, type, priv->protocol);
+ __func__, dev_name(&cdev->dev), type, priv->protocol);
ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
if (ch == NULL)
@@ -1358,7 +1358,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
goto nomem_return;
ch->cdev = cdev;
- snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id);
+ snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev));
ch->type = type;
/**
@@ -1518,8 +1518,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
type = get_channel_type(&cdev0->id);
- snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id);
- snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id);
+ snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
+ snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
ret = add_channel(cdev0, type, priv);
if (ret)
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 8e10ee86a5e..d77cce3fe4d 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -104,7 +104,7 @@
#define READ 0
#define WRITE 1
-#define CTCM_ID_SIZE BUS_ID_SIZE+3
+#define CTCM_ID_SIZE 20+3
struct ctcm_profile {
unsigned long maxmulti;
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index cbe470493bf..19f5d5ed85e 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -1673,7 +1673,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
done:
if (rc) {
- ctcm_pr_info("ctcmpc : %s() failed\n", __FUNCTION__);
+ ctcm_pr_info("ctcmpc : %s() failed\n", __func__);
priv->xid->xid2_flag2 = 0x40;
grp->saved_xid2->xid2_flag2 = 0x40;
}
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 9bcfa04d863..0825be87e5a 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -492,7 +492,7 @@ lcs_start_channel(struct lcs_channel *channel)
unsigned long flags;
int rc;
- LCS_DBF_TEXT_(4,trace,"ssch%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace,"ssch%s", dev_name(&channel->ccwdev->dev));
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
channel->ccws + channel->io_idx, 0, 0,
@@ -501,7 +501,8 @@ lcs_start_channel(struct lcs_channel *channel)
channel->state = LCS_CH_STATE_RUNNING;
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
- LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4,trace,"essh%s",
+ dev_name(&channel->ccwdev->dev));
PRINT_ERR("Error in starting channel, rc=%d!\n", rc);
}
return rc;
@@ -514,12 +515,13 @@ lcs_clear_channel(struct lcs_channel *channel)
int rc;
LCS_DBF_TEXT(4,trace,"clearch");
- LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev));
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_clear(channel->ccwdev, (addr_t) channel);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
- LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace, "ecsc%s",
+ dev_name(&channel->ccwdev->dev));
return rc;
}
wait_event(channel->wait_q, (channel->state == LCS_CH_STATE_CLEARED));
@@ -540,13 +542,14 @@ lcs_stop_channel(struct lcs_channel *channel)
if (channel->state == LCS_CH_STATE_STOPPED)
return 0;
LCS_DBF_TEXT(4,trace,"haltsch");
- LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace, "%s", dev_name(&channel->ccwdev->dev));
channel->state = LCS_CH_STATE_INIT;
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_halt(channel->ccwdev, (addr_t) channel);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
- LCS_DBF_TEXT_(4,trace,"ehsc%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace, "ehsc%s",
+ dev_name(&channel->ccwdev->dev));
return rc;
}
/* Asynchronous halt initialted. Wait for its completion. */
@@ -632,10 +635,11 @@ __lcs_resume_channel(struct lcs_channel *channel)
return 0;
if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND)
return 0;
- LCS_DBF_TEXT_(5, trace, "rsch%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(5, trace, "rsch%s", dev_name(&channel->ccwdev->dev));
rc = ccw_device_resume(channel->ccwdev);
if (rc) {
- LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(4, trace, "ersc%s",
+ dev_name(&channel->ccwdev->dev));
PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc);
} else
channel->state = LCS_CH_STATE_RUNNING;
@@ -1302,18 +1306,18 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
switch (PTR_ERR(irb)) {
case -EIO:
- PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+ PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev));
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT_(2, trace, " rc%d", -EIO);
break;
case -ETIMEDOUT:
- PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+ PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev));
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT_(2, trace, " rc%d", -ETIMEDOUT);
break;
default:
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT(2, trace, " rc???");
}
@@ -1390,7 +1394,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
- LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
+ LCS_DBF_TEXT_(5, trace, "Rint%s", dev_name(&cdev->dev));
LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.cstat,
irb->scsw.cmd.dstat);
LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.fctl,
@@ -1400,7 +1404,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
rc = lcs_get_problem(cdev, irb);
if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
- cdev->dev.bus_id, dstat, cstat);
+ dev_name(&cdev->dev), dstat, cstat);
if (rc) {
channel->state = LCS_CH_STATE_ERROR;
}
@@ -1463,7 +1467,7 @@ lcs_tasklet(unsigned long data)
int rc;
channel = (struct lcs_channel *) data;
- LCS_DBF_TEXT_(5, trace, "tlet%s",channel->ccwdev->dev.bus_id);
+ LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev));
/* Check for processed buffers. */
iob = channel->iob;
@@ -2244,7 +2248,7 @@ lcs_recovery(void *ptr)
return 0;
LCS_DBF_TEXT(4, trace, "recover2");
gdev = card->gdev;
- PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
+ PRINT_WARN("Recovery of device %s started...\n", dev_name(&gdev->dev));
rc = __lcs_shutdown_device(gdev, 1);
rc = lcs_new_device(gdev);
if (!rc)
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 9242b5acc66..0fea51e34b5 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1724,7 +1724,7 @@ static int netiucv_register_device(struct net_device *ndev)
IUCV_DBF_TEXT(trace, 3, __func__);
if (dev) {
- snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
+ dev_set_name(dev, "net%s", ndev->name);
dev->bus = &iucv_bus;
dev->parent = iucv_root;
/*
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index bf8a75c92f2..af6d6045851 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -90,11 +90,11 @@ struct qeth_dbf_info {
#define CARD_RDEV(card) card->read.ccwdev
#define CARD_WDEV(card) card->write.ccwdev
#define CARD_DDEV(card) card->data.ccwdev
-#define CARD_BUS_ID(card) card->gdev->dev.bus_id
-#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
-#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
-#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
-#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
+#define CARD_BUS_ID(card) dev_name(&card->gdev->dev)
+#define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev)
+#define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev)
+#define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev)
+#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev)
/**
* card stuff
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index c7ab1b86451..7de410d5be4 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -745,7 +745,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
- cdev->dev.bus_id, dstat, cstat);
+ dev_name(&cdev->dev), dstat, cstat);
print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
16, 1, irb, 64, 1);
return 1;
@@ -760,7 +760,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
if (sense[SENSE_COMMAND_REJECT_BYTE] &
SENSE_COMMAND_REJECT_FLAG) {
QETH_DBF_TEXT(TRACE, 2, "CMDREJi");
- return 0;
+ return 1;
}
if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
QETH_DBF_TEXT(TRACE, 2, "AFFE");
@@ -784,12 +784,12 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
switch (PTR_ERR(irb)) {
case -EIO:
- PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+ PRINT_WARN("i/o-error on device %s\n", dev_name(&cdev->dev));
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO);
break;
case -ETIMEDOUT:
- PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+ PRINT_WARN("timeout on device %s\n", dev_name(&cdev->dev));
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
QETH_DBF_TEXT_(TRACE, 2, " rc%d", -ETIMEDOUT);
if (intparm == QETH_RCD_PARM) {
@@ -803,7 +803,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
break;
default:
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
- cdev->dev.bus_id);
+ dev_name(&cdev->dev));
QETH_DBF_TEXT(TRACE, 2, "ckirberr");
QETH_DBF_TEXT(TRACE, 2, " rc???");
}
@@ -884,6 +884,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
}
rc = qeth_get_problem(cdev, irb);
if (rc) {
+ qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
goto out;
}
@@ -4081,7 +4082,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
if (!get_device(dev))
return -ENODEV;
- QETH_DBF_TEXT_(SETUP, 2, "%s", gdev->dev.bus_id);
+ QETH_DBF_TEXT_(SETUP, 2, "%s", dev_name(&gdev->dev));
card = qeth_alloc_card();
if (!card) {
@@ -4147,6 +4148,7 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
unsigned long flags;
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+ QETH_DBF_TEXT(SETUP, 2, "removedv");
if (card->discipline.ccwgdriver) {
card->discipline.ccwgdriver->remove(gdev);
qeth_core_free_discipline(card);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 3ac3cc1e03c..955ba7a31b9 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -395,7 +395,8 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
}
if (card->state == CARD_STATE_SOFTSETUP) {
qeth_l2_process_vlans(card, 1);
- qeth_l2_del_all_mc(card);
+ if (!card->use_hard_stop)
+ qeth_l2_del_all_mc(card);
qeth_clear_ipacmd_list(card);
card->state = CARD_STATE_HARDSETUP;
}
@@ -559,7 +560,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
"device %s: x%x\n", CARD_BUS_ID(card), rc);
}
- if (card->info.guestlan) {
+ if ((card->info.type == QETH_CARD_TYPE_IQD) ||
+ (card->info.guestlan)) {
rc = qeth_setadpparms_change_macaddr(card);
if (rc) {
QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
@@ -825,7 +827,6 @@ static int qeth_l2_open(struct net_device *dev)
}
card->data.state = CH_STATE_UP;
card->state = CARD_STATE_UP;
- card->dev->flags |= IFF_UP;
netif_start_queue(dev);
if (!card->lan_online && netif_carrier_ok(dev))
@@ -840,7 +841,6 @@ static int qeth_l2_stop(struct net_device *dev)
QETH_DBF_TEXT(TRACE, 4, "qethstop");
netif_tx_disable(dev);
- card->dev->flags &= ~IFF_UP;
if (card->state == CARD_STATE_UP)
card->state = CARD_STATE_SOFTSETUP;
return 0;
@@ -1137,9 +1137,13 @@ static int qeth_l2_recover(void *ptr)
if (!rc)
PRINT_INFO("Device %s successfully recovered!\n",
CARD_BUS_ID(card));
- else
+ else {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
PRINT_INFO("Device %s could not be recovered!\n",
CARD_BUS_ID(card));
+ }
return 0;
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index dd72c3c2016..99547dea44d 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2795,7 +2795,6 @@ static int qeth_l3_open(struct net_device *dev)
return -ENODEV;
card->data.state = CH_STATE_UP;
card->state = CARD_STATE_UP;
- card->dev->flags |= IFF_UP;
netif_start_queue(dev);
if (!card->lan_online && netif_carrier_ok(dev))
@@ -2809,7 +2808,6 @@ static int qeth_l3_stop(struct net_device *dev)
QETH_DBF_TEXT(TRACE, 4, "qethstop");
netif_tx_disable(dev);
- card->dev->flags &= ~IFF_UP;
if (card->state == CARD_STATE_UP)
card->state = CARD_STATE_SOFTSETUP;
return 0;
@@ -3218,9 +3216,13 @@ static int qeth_l3_recover(void *ptr)
if (!rc)
PRINT_INFO("Device %s successfully recovered!\n",
CARD_BUS_ID(card));
- else
+ else {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
PRINT_INFO("Device %s could not be recovered!\n",
CARD_BUS_ID(card));
+ }
return 0;
}
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
index 3c7145d9f9a..64371c05a3b 100644
--- a/drivers/s390/s390_rdev.c
+++ b/drivers/s390/s390_rdev.c
@@ -30,7 +30,7 @@ s390_root_dev_register(const char *name)
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
- strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
+ dev_set_name(dev, name);
dev->release = s390_root_dev_release;
ret = device_register(dev);
if (ret) {
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 90abfd06ed5..3b56220fb90 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -88,11 +88,13 @@ static int __init zfcp_device_setup(char *devstr)
strncpy(zfcp_data.init_busid, token, BUS_ID_SIZE);
token = strsep(&str, ",");
- if (!token || strict_strtoull(token, 0, &zfcp_data.init_wwpn))
+ if (!token || strict_strtoull(token, 0,
+ (unsigned long long *) &zfcp_data.init_wwpn))
goto err_out;
token = strsep(&str, ",");
- if (!token || strict_strtoull(token, 0, &zfcp_data.init_fcp_lun))
+ if (!token || strict_strtoull(token, 0,
+ (unsigned long long *) &zfcp_data.init_fcp_lun))
goto err_out;
kfree(str);
@@ -100,24 +102,10 @@ static int __init zfcp_device_setup(char *devstr)
err_out:
kfree(str);
- pr_err("zfcp: Parse error for device parameter string %s, "
- "device not attached.\n", devstr);
+ pr_err("zfcp: %s is not a valid SCSI device\n", devstr);
return 0;
}
-static struct zfcp_adapter *zfcp_get_adapter_by_busid(char *bus_id)
-{
- struct zfcp_adapter *adapter;
-
- list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list)
- if ((strncmp(bus_id, adapter->ccw_device->dev.bus_id,
- BUS_ID_SIZE) == 0) &&
- !(atomic_read(&adapter->status) &
- ZFCP_STATUS_COMMON_REMOVE))
- return adapter;
- return NULL;
-}
-
static void __init zfcp_init_device_configure(void)
{
struct zfcp_adapter *adapter;
@@ -141,7 +129,12 @@ static void __init zfcp_init_device_configure(void)
goto out_unit;
up(&zfcp_data.config_sema);
ccw_device_set_online(adapter->ccw_device);
+
zfcp_erp_wait(adapter);
+ wait_event(adapter->erp_done_wqh,
+ !(atomic_read(&unit->status) &
+ ZFCP_STATUS_UNIT_SCSI_WORK_PENDING));
+
down(&zfcp_data.config_sema);
zfcp_unit_put(unit);
out_unit:
@@ -180,9 +173,9 @@ static int __init zfcp_module_init(void)
if (!zfcp_data.gid_pn_cache)
goto out_gid_cache;
- INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
- INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);
+ zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq");
+ INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
sema_init(&zfcp_data.config_sema, 1);
rwlock_init(&zfcp_data.config_lock);
@@ -193,13 +186,14 @@ static int __init zfcp_module_init(void)
retval = misc_register(&zfcp_cfdc_misc);
if (retval) {
- pr_err("zfcp: registration of misc device zfcp_cfdc failed\n");
+ pr_err("zfcp: Registering the misc device zfcp_cfdc failed\n");
goto out_misc;
}
retval = zfcp_ccw_register();
if (retval) {
- pr_err("zfcp: Registration with common I/O layer failed.\n");
+ pr_err("zfcp: The zfcp device driver could not register with "
+ "the common I/O layer\n");
goto out_ccw_register;
}
@@ -231,8 +225,7 @@ module_init(zfcp_module_init);
*
* Returns: pointer to zfcp_unit or NULL
*/
-struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port,
- fcp_lun_t fcp_lun)
+struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
@@ -251,7 +244,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port,
* Returns: pointer to zfcp_port or NULL
*/
struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
- wwn_t wwpn)
+ u64 wwpn)
{
struct zfcp_port *port;
@@ -276,7 +269,7 @@ static void zfcp_sysfs_unit_release(struct device *dev)
*
* Sets up some unit internal structures and creates sysfs entry.
*/
-struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
+struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
@@ -290,7 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
unit->port = port;
unit->fcp_lun = fcp_lun;
- snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun);
+ dev_set_name(&unit->sysfs_device, "0x%016llx",
+ (unsigned long long) fcp_lun);
unit->sysfs_device.parent = &port->sysfs_device;
unit->sysfs_device.release = zfcp_sysfs_unit_release;
dev_set_drvdata(&unit->sysfs_device, unit);
@@ -323,7 +317,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
}
zfcp_unit_get(unit);
- unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
write_lock_irq(&zfcp_data.config_lock);
list_add_tail(&unit->list, &port->unit_list_head);
@@ -332,7 +325,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
write_unlock_irq(&zfcp_data.config_lock);
- port->units++;
zfcp_port_get(port);
return unit;
@@ -351,11 +343,10 @@ err_out_free:
*/
void zfcp_unit_dequeue(struct zfcp_unit *unit)
{
- zfcp_unit_wait(unit);
+ wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
write_lock_irq(&zfcp_data.config_lock);
list_del(&unit->list);
write_unlock_irq(&zfcp_data.config_lock);
- unit->port->units--;
zfcp_port_put(unit->port);
sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
device_unregister(&unit->sysfs_device);
@@ -416,11 +407,6 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
mempool_destroy(adapter->pool.data_gid_pn);
}
-static void zfcp_dummy_release(struct device *dev)
-{
- return;
-}
-
/**
* zfcp_status_read_refill - refill the long running status_read_requests
* @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled
@@ -450,19 +436,6 @@ static void _zfcp_status_read_scheduler(struct work_struct *work)
stat_work));
}
-static int zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
-{
- struct zfcp_port *port;
-
- port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
- ZFCP_DID_DIRECTORY_SERVICE);
- if (IS_ERR(port))
- return PTR_ERR(port);
- zfcp_port_put(port);
-
- return 0;
-}
-
/**
* zfcp_adapter_enqueue - enqueue a new adapter to the list
* @ccw_device: pointer to the struct cc_device
@@ -508,7 +481,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
init_waitqueue_head(&adapter->erp_done_wqh);
INIT_LIST_HEAD(&adapter->port_list_head);
- INIT_LIST_HEAD(&adapter->port_remove_lh);
INIT_LIST_HEAD(&adapter->erp_ready_head);
INIT_LIST_HEAD(&adapter->erp_running_head);
@@ -518,7 +490,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
spin_lock_init(&adapter->san_dbf_lock);
spin_lock_init(&adapter->scsi_dbf_lock);
spin_lock_init(&adapter->rec_dbf_lock);
- spin_lock_init(&adapter->req_q.lock);
+ spin_lock_init(&adapter->req_q_lock);
rwlock_init(&adapter->erp_lock);
rwlock_init(&adapter->abort_lock);
@@ -537,28 +509,15 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
&zfcp_sysfs_adapter_attrs))
goto sysfs_failed;
- adapter->generic_services.parent = &adapter->ccw_device->dev;
- adapter->generic_services.release = zfcp_dummy_release;
- snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE,
- "generic_services");
-
- if (device_register(&adapter->generic_services))
- goto generic_services_failed;
-
write_lock_irq(&zfcp_data.config_lock);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
list_add_tail(&adapter->list, &zfcp_data.adapter_list_head);
write_unlock_irq(&zfcp_data.config_lock);
- zfcp_data.adapters++;
-
- zfcp_nameserver_enqueue(adapter);
+ zfcp_fc_nameserver_init(adapter);
return 0;
-generic_services_failed:
- sysfs_remove_group(&ccw_device->dev.kobj,
- &zfcp_sysfs_adapter_attrs);
sysfs_failed:
zfcp_adapter_debug_unregister(adapter);
debug_register_failed:
@@ -585,7 +544,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
cancel_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
zfcp_adapter_scsi_unregister(adapter);
- device_unregister(&adapter->generic_services);
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_adapter_attrs);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
@@ -603,9 +561,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
list_del(&adapter->list);
write_unlock_irq(&zfcp_data.config_lock);
- /* decrease number of adapters in list */
- zfcp_data.adapters--;
-
zfcp_qdio_free(adapter);
zfcp_free_low_mem_buffers(adapter);
@@ -633,21 +588,19 @@ static void zfcp_sysfs_port_release(struct device *dev)
* d_id is used to enqueue ports with a well known address like the Directory
* Service for nameserver lookup.
*/
-struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
+struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
u32 status, u32 d_id)
{
struct zfcp_port *port;
int retval;
- char *bus_id;
port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
if (!port)
return ERR_PTR(-ENOMEM);
init_waitqueue_head(&port->remove_wq);
-
INIT_LIST_HEAD(&port->unit_list_head);
- INIT_LIST_HEAD(&port->unit_remove_lh);
+ INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
port->adapter = adapter;
port->d_id = d_id;
@@ -657,34 +610,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set(&port->refcount, 0);
- if (status & ZFCP_STATUS_PORT_WKA) {
- switch (d_id) {
- case ZFCP_DID_DIRECTORY_SERVICE:
- bus_id = "directory";
- break;
- case ZFCP_DID_MANAGEMENT_SERVICE:
- bus_id = "management";
- break;
- case ZFCP_DID_KEY_DISTRIBUTION_SERVICE:
- bus_id = "key_distribution";
- break;
- case ZFCP_DID_ALIAS_SERVICE:
- bus_id = "alias";
- break;
- case ZFCP_DID_TIME_SERVICE:
- bus_id = "time";
- break;
- default:
- kfree(port);
- return ERR_PTR(-EINVAL);
- }
- snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "%s", bus_id);
- port->sysfs_device.parent = &adapter->generic_services;
- } else {
- snprintf(port->sysfs_device.bus_id,
- BUS_ID_SIZE, "0x%016llx", wwpn);
- port->sysfs_device.parent = &adapter->ccw_device->dev;
- }
+ dev_set_name(&port->sysfs_device, "0x%016llx", wwpn);
+ port->sysfs_device.parent = &adapter->ccw_device->dev;
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
@@ -700,12 +627,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
if (device_register(&port->sysfs_device))
goto err_out_free;
- if (status & ZFCP_STATUS_PORT_WKA)
- retval = sysfs_create_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_ns_port_attrs);
- else
- retval = sysfs_create_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_port_attrs);
+ retval = sysfs_create_group(&port->sysfs_device.kobj,
+ &zfcp_sysfs_port_attrs);
if (retval) {
device_unregister(&port->sysfs_device);
@@ -718,10 +641,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
list_add_tail(&port->list, &adapter->port_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
- if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
- if (!adapter->nameserver_port)
- adapter->nameserver_port = port;
- adapter->ports++;
write_unlock_irq(&zfcp_data.config_lock);
@@ -740,21 +659,15 @@ err_out:
*/
void zfcp_port_dequeue(struct zfcp_port *port)
{
- zfcp_port_wait(port);
+ wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list);
- port->adapter->ports--;
write_unlock_irq(&zfcp_data.config_lock);
if (port->rport)
fc_remote_port_delete(port->rport);
port->rport = NULL;
zfcp_adapter_put(port->adapter);
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)
- sysfs_remove_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_ns_port_attrs);
- else
- sysfs_remove_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_port_attrs);
+ sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device);
}
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 391dd29749f..b04038c7478 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -25,7 +25,8 @@ static int zfcp_ccw_probe(struct ccw_device *ccw_device)
down(&zfcp_data.config_sema);
if (zfcp_adapter_enqueue(ccw_device)) {
dev_err(&ccw_device->dev,
- "Setup of data structures failed.\n");
+ "Setting up data structures for the "
+ "FCP adapter failed\n");
retval = -EINVAL;
}
up(&zfcp_data.config_sema);
@@ -46,6 +47,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
struct zfcp_adapter *adapter;
struct zfcp_port *port, *p;
struct zfcp_unit *unit, *u;
+ LIST_HEAD(unit_remove_lh);
+ LIST_HEAD(port_remove_lh);
ccw_device_set_offline(ccw_device);
down(&zfcp_data.config_sema);
@@ -54,26 +57,26 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
- list_move(&unit->list, &port->unit_remove_lh);
+ list_move(&unit->list, &unit_remove_lh);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
&unit->status);
}
- list_move(&port->list, &adapter->port_remove_lh);
+ list_move(&port->list, &port_remove_lh);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
}
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
write_unlock_irq(&zfcp_data.config_lock);
- list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) {
- list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) {
- if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED,
- &unit->status))
+ list_for_each_entry_safe(port, p, &port_remove_lh, list) {
+ list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
+ if (atomic_read(&unit->status) &
+ ZFCP_STATUS_UNIT_REGISTERED)
scsi_remove_device(unit->device);
zfcp_unit_dequeue(unit);
}
zfcp_port_dequeue(port);
}
- zfcp_adapter_wait(adapter);
+ wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
zfcp_adapter_dequeue(adapter);
up(&zfcp_data.config_sema);
@@ -152,21 +155,22 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
*/
static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
{
- struct zfcp_adapter *adapter;
+ struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
- down(&zfcp_data.config_sema);
- adapter = dev_get_drvdata(&ccw_device->dev);
switch (event) {
case CIO_GONE:
- dev_warn(&adapter->ccw_device->dev, "device gone\n");
+ dev_warn(&adapter->ccw_device->dev,
+ "The FCP device has been detached\n");
zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
break;
case CIO_NO_PATH:
- dev_warn(&adapter->ccw_device->dev, "no path\n");
+ dev_warn(&adapter->ccw_device->dev,
+ "The CHPID for the FCP device is offline\n");
zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
break;
case CIO_OPER:
- dev_info(&adapter->ccw_device->dev, "operational again\n");
+ dev_info(&adapter->ccw_device->dev,
+ "The FCP device is operational again\n");
zfcp_erp_modify_adapter_status(adapter, 11, NULL,
ZFCP_STATUS_COMMON_RUNNING,
ZFCP_SET);
@@ -174,8 +178,6 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
89, NULL);
break;
}
- zfcp_erp_wait(adapter);
- up(&zfcp_data.config_sema);
return 1;
}
@@ -224,3 +226,20 @@ int __init zfcp_ccw_register(void)
{
return ccw_driver_register(&zfcp_ccw_driver);
}
+
+/**
+ * zfcp_get_adapter_by_busid - find zfcp_adapter struct
+ * @busid: bus id string of zfcp adapter to find
+ */
+struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
+{
+ struct ccw_device *ccw_device;
+ struct zfcp_adapter *adapter = NULL;
+
+ ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+ if (ccw_device) {
+ adapter = dev_get_drvdata(&ccw_device->dev);
+ put_device(&ccw_device->dev);
+ }
+ return adapter;
+}
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index fca48b88fc5..060f5f2352e 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -318,6 +318,26 @@ void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter,
spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
}
+/**
+ * zfcp_hba_dbf_event_berr - trace event for bit error threshold
+ * @adapter: adapter affected by this QDIO related event
+ * @req: fsf request
+ */
+void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter,
+ struct zfcp_fsf_req *req)
+{
+ struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ struct fsf_status_read_buffer *sr_buf = req->data;
+ struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ memset(r, 0, sizeof(*r));
+ strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE);
+ memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload));
+ debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
static void zfcp_hba_dbf_view_response(char **p,
struct zfcp_hba_dbf_record_response *r)
{
@@ -399,6 +419,30 @@ static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
}
+static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
+{
+ zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count);
+ zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count);
+ zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count);
+ zfcp_dbf_out(p, "prim_seq_err", "%d",
+ r->primitive_sequence_error_count);
+ zfcp_dbf_out(p, "inval_trans_word_err", "%d",
+ r->invalid_transmission_word_error_count);
+ zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count);
+ zfcp_dbf_out(p, "prim_seq_event_to", "%d",
+ r->primitive_sequence_event_timeout_count);
+ zfcp_dbf_out(p, "elast_buf_overrun_err", "%d",
+ r->elastic_buffer_overrun_error_count);
+ zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d",
+ r->advertised_receive_b2b_credit);
+ zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d",
+ r->current_receive_b2b_credit);
+ zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d",
+ r->advertised_transmit_b2b_credit);
+ zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d",
+ r->current_transmit_b2b_credit);
+}
+
static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
@@ -418,6 +462,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_hba_dbf_view_status(&p, &r->u.status);
else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
+ else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
+ zfcp_hba_dbf_view_berr(&p, &r->u.berr);
p += sprintf(p, "\n");
return p - out_buf;
@@ -519,14 +565,14 @@ static const char *zfcp_rec_dbf_ids[] = {
[75] = "physical port recovery escalation after failed port "
"recovery",
[76] = "port recovery escalation after failed unit recovery",
- [77] = "recovery opening nameserver port",
+ [77] = "",
[78] = "duplicate request id",
[79] = "link down",
[80] = "exclusive read-only unit access unsupported",
[81] = "shared read-write unit access unsupported",
[82] = "incoming rscn",
[83] = "incoming wwpn",
- [84] = "",
+ [84] = "wka port handle not valid close port",
[85] = "online",
[86] = "offline",
[87] = "ccw device gone",
@@ -570,7 +616,7 @@ static const char *zfcp_rec_dbf_ids[] = {
[125] = "need newer zfcp",
[126] = "need newer microcode",
[127] = "arbitrated loop not supported",
- [128] = "unknown topology",
+ [128] = "",
[129] = "qtcb size mismatch",
[130] = "unknown fsf status ecd",
[131] = "fcp request too big",
@@ -829,9 +875,9 @@ void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action)
void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
- struct ct_hdr *hdr = zfcp_sg_to_address(ct->req);
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct ct_hdr *hdr = sg_virt(ct->req);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
unsigned long flags;
@@ -842,7 +888,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
r->fsf_reqid = (unsigned long)fsf_req;
r->fsf_seqno = fsf_req->seq_no;
r->s_id = fc_host_port_id(adapter->scsi_host);
- r->d_id = port->d_id;
+ r->d_id = wka_port->d_id;
oct->cmd_req_code = hdr->cmd_rsp_code;
oct->revision = hdr->revision;
oct->gs_type = hdr->gs_type;
@@ -863,9 +909,9 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
- struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp);
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct ct_hdr *hdr = sg_virt(ct->resp);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
unsigned long flags;
@@ -875,7 +921,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
r->fsf_reqid = (unsigned long)fsf_req;
r->fsf_seqno = fsf_req->seq_no;
- r->s_id = port->d_id;
+ r->s_id = wka_port->d_id;
r->d_id = fc_host_port_id(adapter->scsi_host);
rct->cmd_rsp_code = hdr->cmd_rsp_code;
rct->revision = hdr->revision;
@@ -922,8 +968,8 @@ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
zfcp_san_dbf_event_els("oels", 2, fsf_req,
fc_host_port_id(els->adapter->scsi_host),
- els->d_id, *(u8 *) zfcp_sg_to_address(els->req),
- zfcp_sg_to_address(els->req), els->req->length);
+ els->d_id, *(u8 *) sg_virt(els->req),
+ sg_virt(els->req), els->req->length);
}
/**
@@ -936,8 +982,7 @@ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
fc_host_port_id(els->adapter->scsi_host),
- *(u8 *)zfcp_sg_to_address(els->req),
- zfcp_sg_to_address(els->resp),
+ *(u8 *)sg_virt(els->req), sg_virt(els->resp),
els->resp->length);
}
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 0ddb18449d1..e8f450801fe 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -151,6 +151,7 @@ struct zfcp_hba_dbf_record {
struct zfcp_hba_dbf_record_response response;
struct zfcp_hba_dbf_record_status status;
struct zfcp_hba_dbf_record_qdio qdio;
+ struct fsf_bit_error_payload berr;
} u;
} __attribute__ ((packed));
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 67f45fc62f5..9ce4c75bd19 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -39,29 +39,6 @@
/********************* GENERAL DEFINES *********************************/
-/**
- * zfcp_sg_to_address - determine kernel address from struct scatterlist
- * @list: struct scatterlist
- * Return: kernel address
- */
-static inline void *
-zfcp_sg_to_address(struct scatterlist *list)
-{
- return sg_virt(list);
-}
-
-/**
- * zfcp_address_to_sg - set up struct scatterlist from kernel address
- * @address: kernel address
- * @list: struct scatterlist
- * @size: buffer size
- */
-static inline void
-zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
-{
- sg_set_buf(list, address, size);
-}
-
#define REQUEST_LIST_SIZE 128
/********************* SCSI SPECIFIC DEFINES *********************************/
@@ -101,11 +78,6 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
-typedef unsigned long long wwn_t;
-typedef unsigned long long fcp_lun_t;
-/* data length field may be at variable position in FCP-2 FCP_CMND IU */
-typedef unsigned int fcp_dl_t;
-
/* timeout for name-server lookup (in seconds) */
#define ZFCP_NS_GID_PN_TIMEOUT 10
@@ -129,7 +101,7 @@ typedef unsigned int fcp_dl_t;
/* FCP(-2) FCP_CMND IU */
struct fcp_cmnd_iu {
- fcp_lun_t fcp_lun; /* FCP logical unit number */
+ u64 fcp_lun; /* FCP logical unit number */
u8 crn; /* command reference number */
u8 reserved0:5; /* reserved */
u8 task_attribute:3; /* task attribute */
@@ -204,7 +176,7 @@ struct fcp_rscn_element {
struct fcp_logo {
u32 command;
u32 nport_did;
- wwn_t nport_wwpn;
+ u64 nport_wwpn;
} __attribute__((packed));
/*
@@ -218,13 +190,6 @@ struct fcp_logo {
#define ZFCP_LS_RSCN 0x61
#define ZFCP_LS_RNID 0x78
-struct zfcp_ls_rjt_par {
- u8 action;
- u8 reason_code;
- u8 reason_expl;
- u8 vendor_unique;
-} __attribute__ ((packed));
-
struct zfcp_ls_adisc {
u8 code;
u8 field[3];
@@ -234,20 +199,6 @@ struct zfcp_ls_adisc {
u32 nport_id;
} __attribute__ ((packed));
-struct zfcp_ls_adisc_acc {
- u8 code;
- u8 field[3];
- u32 hard_nport_id;
- u64 wwpn;
- u64 wwnn;
- u32 nport_id;
-} __attribute__ ((packed));
-
-struct zfcp_rc_entry {
- u8 code;
- const char *description;
-};
-
/*
* FC-GS-2 stuff
*/
@@ -281,9 +232,7 @@ struct zfcp_rc_entry {
#define ZFCP_STATUS_COMMON_RUNNING 0x40000000
#define ZFCP_STATUS_COMMON_ERP_FAILED 0x20000000
#define ZFCP_STATUS_COMMON_UNBLOCKED 0x10000000
-#define ZFCP_STATUS_COMMON_OPENING 0x08000000
#define ZFCP_STATUS_COMMON_OPEN 0x04000000
-#define ZFCP_STATUS_COMMON_CLOSING 0x02000000
#define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000
#define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000
@@ -291,16 +240,15 @@ struct zfcp_rc_entry {
/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
-#define ZFCP_STATUS_ADAPTER_REGISTERED 0x00000004
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
#define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020
#define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080
#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
-#define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800
/* FC-PH/FC-GS well-known address identifiers for generic services */
+#define ZFCP_DID_WKA 0xFFFFF0
#define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA
#define ZFCP_DID_TIME_SERVICE 0xFFFFFB
#define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC
@@ -312,29 +260,27 @@ struct zfcp_rc_entry {
#define ZFCP_STATUS_PORT_DID_DID 0x00000002
#define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004
#define ZFCP_STATUS_PORT_NO_WWPN 0x00000008
-#define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010
#define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020
-/* for ports with well known addresses */
-#define ZFCP_STATUS_PORT_WKA \
- (ZFCP_STATUS_PORT_NO_WWPN | \
- ZFCP_STATUS_PORT_NO_SCSI_ID)
+/* well known address (WKA) port status*/
+enum zfcp_wka_status {
+ ZFCP_WKA_PORT_OFFLINE,
+ ZFCP_WKA_PORT_CLOSING,
+ ZFCP_WKA_PORT_OPENING,
+ ZFCP_WKA_PORT_ONLINE,
+};
/* logical unit status */
-#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
-#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
-#define ZFCP_STATUS_FSFREQ_POOL 0x00000001
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
#define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004
#define ZFCP_STATUS_FSFREQ_ERROR 0x00000008
#define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010
-#define ZFCP_STATUS_FSFREQ_ABORTING 0x00000020
#define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040
#define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080
#define ZFCP_STATUS_FSFREQ_ABORTED 0x00000100
@@ -379,7 +325,7 @@ struct ct_hdr {
* a port name is required */
struct ct_iu_gid_pn_req {
struct ct_hdr header;
- wwn_t wwpn;
+ u64 wwpn;
} __attribute__ ((packed));
/* FS_ACC IU and data unit for GID_PN nameserver request */
@@ -388,11 +334,9 @@ struct ct_iu_gid_pn_resp {
u32 d_id;
} __attribute__ ((packed));
-typedef void (*zfcp_send_ct_handler_t)(unsigned long);
-
/**
* struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
- * @port: port where the request is sent to
+ * @wka_port: port where the request is sent to
* @req: scatter-gather list for request
* @resp: scatter-gather list for response
* @req_count: number of elements in request scatter-gather list
@@ -404,12 +348,12 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long);
* @status: used to pass error status to calling function
*/
struct zfcp_send_ct {
- struct zfcp_port *port;
+ struct zfcp_wka_port *wka_port;
struct scatterlist *req;
struct scatterlist *resp;
unsigned int req_count;
unsigned int resp_count;
- zfcp_send_ct_handler_t handler;
+ void (*handler)(unsigned long);
unsigned long handler_data;
int timeout;
struct completion *completion;
@@ -426,8 +370,6 @@ struct zfcp_gid_pn_data {
struct zfcp_port *port;
};
-typedef void (*zfcp_send_els_handler_t)(unsigned long);
-
/**
* struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
* @adapter: adapter where request is sent from
@@ -451,22 +393,28 @@ struct zfcp_send_els {
struct scatterlist *resp;
unsigned int req_count;
unsigned int resp_count;
- zfcp_send_els_handler_t handler;
+ void (*handler)(unsigned long);
unsigned long handler_data;
struct completion *completion;
int ls_code;
int status;
};
+struct zfcp_wka_port {
+ struct zfcp_adapter *adapter;
+ wait_queue_head_t completion_wq;
+ enum zfcp_wka_status status;
+ atomic_t refcount;
+ u32 d_id;
+ u32 handle;
+ struct mutex mutex;
+ struct delayed_work work;
+};
+
struct zfcp_qdio_queue {
- struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
- u8 first; /* index of next free bfr
- in queue (free_count>0) */
- atomic_t count; /* number of free buffers
- in queue */
- spinlock_t lock; /* lock for operations on queue */
- int pci_batch; /* SBALs since PCI indication
- was last set */
+ struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
+ u8 first; /* index of next free bfr in queue */
+ atomic_t count; /* number of free buffers in queue */
};
struct zfcp_erp_action {
@@ -475,7 +423,7 @@ struct zfcp_erp_action {
struct zfcp_adapter *adapter; /* device which should be recovered */
struct zfcp_port *port;
struct zfcp_unit *unit;
- volatile u32 status; /* recovery status */
+ u32 status; /* recovery status */
u32 step; /* active step of this erp action */
struct zfcp_fsf_req *fsf_req; /* fsf request currently pending
for this action */
@@ -506,8 +454,8 @@ struct zfcp_adapter {
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
refcount drop to zero */
- wwn_t peer_wwnn; /* P2P peer WWNN */
- wwn_t peer_wwpn; /* P2P peer WWPN */
+ u64 peer_wwnn; /* P2P peer WWNN */
+ u64 peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u32 hydra_version; /* Hydra version */
@@ -518,13 +466,13 @@ struct zfcp_adapter {
u16 timer_ticks; /* time int for a tick */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
struct list_head port_list_head; /* remote port list */
- struct list_head port_remove_lh; /* head of ports to be
- removed */
- u32 ports; /* number of remote ports */
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
spinlock_t req_list_lock; /* request list lock */
struct zfcp_qdio_queue req_q; /* request queue */
+ spinlock_t req_q_lock; /* for operations on queue */
+ int req_q_pci_batch; /* SBALs since PCI indication
+ was last set */
u32 fsf_req_seq_no; /* FSF cmnd seq number */
wait_queue_head_t request_wq; /* can be used to wait for
more avaliable SBALs */
@@ -548,7 +496,7 @@ struct zfcp_adapter {
actions */
u32 erp_low_mem_count; /* nr of erp actions waiting
for memory */
- struct zfcp_port *nameserver_port; /* adapter's nameserver */
+ struct zfcp_wka_port nsp; /* adapter's nameserver */
debug_info_t *rec_dbf;
debug_info_t *hba_dbf;
debug_info_t *san_dbf; /* debug feature areas */
@@ -563,11 +511,11 @@ struct zfcp_adapter {
struct zfcp_scsi_dbf_record scsi_dbf_buf;
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
struct qdio_initialize qdio_init_data; /* for qdio_establish */
- struct device generic_services; /* directory for WKA ports */
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
unsigned long stats_reset;
struct work_struct scan_work;
+ atomic_t qdio_outb_full; /* queue full incidents */
};
struct zfcp_port {
@@ -579,18 +527,16 @@ struct zfcp_port {
refcount drop to zero */
struct zfcp_adapter *adapter; /* adapter used to access port */
struct list_head unit_list_head; /* head of logical unit list */
- struct list_head unit_remove_lh; /* head of luns to be removed
- list */
- u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */
- wwn_t wwnn; /* WWNN if known */
- wwn_t wwpn; /* WWPN */
+ u64 wwnn; /* WWNN if known */
+ u64 wwpn; /* WWPN */
u32 d_id; /* D_ID */
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
u32 maxframe_size;
u32 supported_classes;
+ struct work_struct gid_pn_work;
};
struct zfcp_unit {
@@ -601,8 +547,7 @@ struct zfcp_unit {
refcount drop to zero */
struct zfcp_port *port; /* remote port of unit */
atomic_t status; /* status of this logical unit */
- unsigned int scsi_lun; /* own SCSI LUN */
- fcp_lun_t fcp_lun; /* own FCP_LUN */
+ u64 fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
@@ -625,7 +570,7 @@ struct zfcp_fsf_req {
u8 sbal_response; /* SBAL used in interrupt */
wait_queue_head_t completion_wq; /* can be used by a routine
to wait for completion */
- volatile u32 status; /* status of this request */
+ u32 status; /* status of this request */
u32 fsf_command; /* FSF Command copy */
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
@@ -638,29 +583,28 @@ struct zfcp_fsf_req {
unsigned long long issued; /* request sent time (STCK) */
struct zfcp_unit *unit;
void (*handler)(struct zfcp_fsf_req *);
+ u16 qdio_outb_usage;/* usage of outbound queue */
+ u16 qdio_inb_usage; /* usage of inbound queue */
};
/* driver data */
struct zfcp_data {
struct scsi_host_template scsi_host_template;
struct scsi_transport_template *scsi_transport_template;
- atomic_t status; /* Module status flags */
struct list_head adapter_list_head; /* head of adapter list */
- struct list_head adapter_remove_lh; /* head of adapters to be
- removed */
- u32 adapters; /* # of adapters in list */
rwlock_t config_lock; /* serialises changes
to adapter/port/unit
lists */
struct semaphore config_sema; /* serialises configuration
changes */
atomic_t loglevel; /* current loglevel */
- char init_busid[BUS_ID_SIZE];
- wwn_t init_wwpn;
- fcp_lun_t init_fcp_lun;
- struct kmem_cache *fsf_req_qtcb_cache;
- struct kmem_cache *sr_buffer_cache;
- struct kmem_cache *gid_pn_cache;
+ char init_busid[20];
+ u64 init_wwpn;
+ u64 init_fcp_lun;
+ struct kmem_cache *fsf_req_qtcb_cache;
+ struct kmem_cache *sr_buffer_cache;
+ struct kmem_cache *gid_pn_cache;
+ struct workqueue_struct *work_queue;
};
/* struct used by memory pools for fsf_requests */
@@ -677,14 +621,7 @@ struct zfcp_fsf_req_qtcb {
#define ZFCP_SET 0x00000100
#define ZFCP_CLEAR 0x00000200
-#ifndef atomic_test_mask
-#define atomic_test_mask(mask, target) \
- ((atomic_read(target) & mask) == mask)
-#endif
-
-#define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id)
-#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
-#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))
+#define zfcp_get_busid_by_adapter(adapter) (dev_name(&adapter->ccw_device->dev))
/*
* Helper functions for request ID management.
@@ -745,12 +682,6 @@ zfcp_unit_put(struct zfcp_unit *unit)
}
static inline void
-zfcp_unit_wait(struct zfcp_unit *unit)
-{
- wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
-}
-
-static inline void
zfcp_port_get(struct zfcp_port *port)
{
atomic_inc(&port->refcount);
@@ -764,12 +695,6 @@ zfcp_port_put(struct zfcp_port *port)
}
static inline void
-zfcp_port_wait(struct zfcp_port *port)
-{
- wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
-}
-
-static inline void
zfcp_adapter_get(struct zfcp_adapter *adapter)
{
atomic_inc(&adapter->refcount);
@@ -782,10 +707,4 @@ zfcp_adapter_put(struct zfcp_adapter *adapter)
wake_up(&adapter->remove_wq);
}
-static inline void
-zfcp_adapter_wait(struct zfcp_adapter *adapter)
-{
- wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
-}
-
#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 643ac4bba5b..9040f738ff3 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -23,7 +23,6 @@ enum zfcp_erp_steps {
ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
- ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200,
ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
@@ -532,8 +531,7 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list)
- if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA))
- _zfcp_erp_port_reopen(port, clear, id, ref);
+ _zfcp_erp_port_reopen(port, clear, id, ref);
}
static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id,
@@ -669,8 +667,6 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
int ret;
struct zfcp_adapter *adapter = act->adapter;
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
write_lock_irq(&adapter->erp_lock);
zfcp_erp_action_to_running(act);
write_unlock_irq(&adapter->erp_lock);
@@ -741,8 +737,7 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
failed_qdio:
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
- ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
- ZFCP_STATUS_ADAPTER_XPORT_OK,
+ ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&act->adapter->status);
return retval;
}
@@ -751,15 +746,11 @@ static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
{
int retval;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status);
zfcp_erp_adapter_strategy_generic(act, 1); /* close */
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status);
if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
return ZFCP_ERP_EXIT;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status);
retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status);
if (retval == ZFCP_ERP_FAILED)
ssleep(8);
@@ -783,10 +774,7 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
{
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
- ZFCP_STATUS_COMMON_CLOSING |
- ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_PORT_DID_DID |
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_PORT_PHYS_CLOSING |
ZFCP_STATUS_PORT_INVALID_WWPN,
&port->status);
@@ -839,73 +827,12 @@ static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
return ZFCP_ERP_CONTINUES;
}
-static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act)
-{
- unsigned long flags;
- struct zfcp_adapter *adapter = ns_act->adapter;
- struct zfcp_erp_action *act, *tmp;
- int status;
-
- read_lock_irqsave(&adapter->erp_lock, flags);
- list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) {
- if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
- status = atomic_read(&adapter->nameserver_port->status);
- if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
- zfcp_erp_port_failed(act->port, 27, NULL);
- zfcp_erp_action_ready(act);
- }
- }
- read_unlock_irqrestore(&adapter->erp_lock, flags);
-}
-
-static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act)
-{
- int retval;
-
- switch (act->step) {
- case ZFCP_ERP_STEP_UNINITIALIZED:
- case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
- case ZFCP_ERP_STEP_PORT_CLOSING:
- return zfcp_erp_port_strategy_open_port(act);
-
- case ZFCP_ERP_STEP_PORT_OPENING:
- if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN)
- retval = ZFCP_ERP_SUCCEEDED;
- else
- retval = ZFCP_ERP_FAILED;
- /* this is needed anyway */
- zfcp_erp_port_strategy_open_ns_wake(act);
- return retval;
-
- default:
- return ZFCP_ERP_FAILED;
- }
-}
-
-static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act)
-{
- int retval;
-
- retval = zfcp_fc_ns_gid_pn_request(act);
- if (retval == -ENOMEM)
- return ZFCP_ERP_NOMEM;
- act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
- if (retval)
- return ZFCP_ERP_FAILED;
- return ZFCP_ERP_CONTINUES;
-}
-
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
{
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
if (port->wwpn != adapter->peer_wwpn) {
- dev_err(&adapter->ccw_device->dev,
- "Failed to open port 0x%016Lx, "
- "Peer WWPN 0x%016Lx does not "
- "match.\n", port->wwpn,
- adapter->peer_wwpn);
zfcp_erp_port_failed(port, 25, NULL);
return ZFCP_ERP_FAILED;
}
@@ -914,11 +841,25 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
return zfcp_erp_port_strategy_open_port(act);
}
+void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
+{
+ int retval;
+ struct zfcp_port *port = container_of(work, struct zfcp_port,
+ gid_pn_work);
+
+ retval = zfcp_fc_ns_gid_pn(&port->erp_action);
+ if (retval == -ENOMEM)
+ zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM);
+ port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
+ if (retval)
+ zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED);
+
+}
+
static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
{
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
- struct zfcp_port *ns_port = adapter->nameserver_port;
int p_status = atomic_read(&port->status);
switch (act->step) {
@@ -927,28 +868,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
case ZFCP_ERP_STEP_PORT_CLOSING:
if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
return zfcp_erp_open_ptp_port(act);
- if (!ns_port) {
- dev_err(&adapter->ccw_device->dev,
- "Nameserver port unavailable.\n");
- return ZFCP_ERP_FAILED;
- }
- if (!(atomic_read(&ns_port->status) &
- ZFCP_STATUS_COMMON_UNBLOCKED)) {
- /* nameserver port may live again */
- atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
- &ns_port->status);
- if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) {
- act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN;
- return ZFCP_ERP_CONTINUES;
- }
- return ZFCP_ERP_FAILED;
+ if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
+ queue_work(zfcp_data.work_queue, &port->gid_pn_work);
+ return ZFCP_ERP_CONTINUES;
}
- /* else nameserver port is already open, fall through */
- case ZFCP_ERP_STEP_NAMESERVER_OPEN:
- if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN))
- return ZFCP_ERP_FAILED;
- return zfcp_erp_port_strategy_open_lookup(act);
-
case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) {
@@ -961,25 +884,26 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
case ZFCP_ERP_STEP_PORT_OPENING:
/* D_ID might have changed during open */
- if ((p_status & ZFCP_STATUS_COMMON_OPEN) &&
- (p_status & ZFCP_STATUS_PORT_DID_DID))
- return ZFCP_ERP_SUCCEEDED;
+ if (p_status & ZFCP_STATUS_COMMON_OPEN) {
+ if (p_status & ZFCP_STATUS_PORT_DID_DID)
+ return ZFCP_ERP_SUCCEEDED;
+ else {
+ act->step = ZFCP_ERP_STEP_PORT_CLOSING;
+ return ZFCP_ERP_CONTINUES;
+ }
/* fall through otherwise */
+ }
}
return ZFCP_ERP_FAILED;
}
-static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act)
-{
- if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA))
- return zfcp_erp_port_strategy_open_nameserver(act);
- return zfcp_erp_port_strategy_open_common(act);
-}
-
static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
{
struct zfcp_port *port = erp_action->port;
+ if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)
+ goto close_init_done;
+
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
zfcp_erp_port_strategy_clearstati(port);
@@ -992,19 +916,17 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
return ZFCP_ERP_FAILED;
break;
}
+
+close_init_done:
if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
return ZFCP_ERP_EXIT;
- else
- return zfcp_erp_port_strategy_open(erp_action);
- return ZFCP_ERP_FAILED;
+ return zfcp_erp_port_strategy_open_common(erp_action);
}
static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
{
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
- ZFCP_STATUS_COMMON_CLOSING |
- ZFCP_STATUS_COMMON_ACCESS_DENIED |
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_UNIT_SHARED |
ZFCP_STATUS_UNIT_READONLY,
&unit->status);
@@ -1065,8 +987,14 @@ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
break;
case ZFCP_ERP_FAILED :
atomic_inc(&unit->erp_counter);
- if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&unit->port->adapter->ccw_device->dev,
+ "ERP failed for unit 0x%016Lx on "
+ "port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 21, NULL);
+ }
break;
}
@@ -1091,8 +1019,12 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
result = ZFCP_ERP_EXIT;
}
atomic_inc(&port->erp_counter);
- if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&port->adapter->ccw_device->dev,
+ "ERP failed for remote port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 22, NULL);
+ }
break;
}
@@ -1114,8 +1046,12 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
case ZFCP_ERP_FAILED :
atomic_inc(&adapter->erp_counter);
- if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&adapter->ccw_device->dev,
+ "ERP cannot recover an error "
+ "on the FCP device\n");
zfcp_erp_adapter_failed(adapter, 23, NULL);
+ }
break;
}
@@ -1250,9 +1186,10 @@ static void zfcp_erp_scsi_scan(struct work_struct *work)
struct zfcp_unit *unit = p->unit;
struct fc_rport *rport = unit->port->rport;
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
- unit->scsi_lun, 0);
+ scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
zfcp_unit_put(unit);
+ wake_up(&unit->port->adapter->erp_done_wqh);
kfree(p);
}
@@ -1263,9 +1200,9 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p) {
dev_err(&unit->port->adapter->ccw_device->dev,
- "Out of resources. Could not register unit "
- "0x%016Lx on port 0x%016Lx with SCSI stack.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
return;
}
@@ -1273,7 +1210,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
INIT_WORK(&p->work, zfcp_erp_scsi_scan);
p->unit = unit;
- schedule_work(&p->work);
+ queue_work(zfcp_data.work_queue, &p->work);
}
static void zfcp_erp_rport_register(struct zfcp_port *port)
@@ -1286,8 +1223,8 @@ static void zfcp_erp_rport_register(struct zfcp_port *port)
port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
if (!port->rport) {
dev_err(&port->adapter->ccw_device->dev,
- "Failed registration of rport "
- "0x%016Lx.\n", port->wwpn);
+ "Registering port 0x%016Lx failed\n",
+ (unsigned long long)port->wwpn);
return;
}
@@ -1299,12 +1236,12 @@ static void zfcp_erp_rport_register(struct zfcp_port *port)
static void zfcp_erp_rports_del(struct zfcp_adapter *adapter)
{
struct zfcp_port *port;
- list_for_each_entry(port, &adapter->port_list_head, list)
- if (port->rport && !(atomic_read(&port->status) &
- ZFCP_STATUS_PORT_WKA)) {
- fc_remote_port_delete(port->rport);
- port->rport = NULL;
- }
+ list_for_each_entry(port, &adapter->port_list_head, list) {
+ if (!port->rport)
+ continue;
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
+ }
}
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
@@ -1439,7 +1376,7 @@ static int zfcp_erp_thread(void *data)
struct zfcp_erp_action *act;
unsigned long flags;
- daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id);
+ daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
/* Block all signals */
siginitsetinv(&current->blocked, 0);
atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
@@ -1459,9 +1396,9 @@ static int zfcp_erp_thread(void *data)
zfcp_erp_wakeup(adapter);
}
- zfcp_rec_dbf_event_thread(4, adapter);
+ zfcp_rec_dbf_event_thread_lock(4, adapter);
down_interruptible(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread(5, adapter);
+ zfcp_rec_dbf_event_thread_lock(5, adapter);
}
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
@@ -1484,7 +1421,7 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
if (retval < 0) {
dev_err(&adapter->ccw_device->dev,
- "Creation of ERP thread failed.\n");
+ "Creating an ERP thread for the FCP device failed.\n");
return retval;
}
wait_event(adapter->erp_thread_wqh,
@@ -1506,7 +1443,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
{
atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
up(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock(2, adapter);
+ zfcp_rec_dbf_event_thread_lock(3, adapter);
wait_event(adapter->erp_thread_wqh,
!(atomic_read(&adapter->status) &
@@ -1526,7 +1463,6 @@ void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
{
zfcp_erp_modify_adapter_status(adapter, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
- dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n");
}
/**
@@ -1539,15 +1475,6 @@ void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
{
zfcp_erp_modify_port_status(port, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)
- dev_err(&port->adapter->ccw_device->dev,
- "Port ERP failed for WKA port d_id=0x%06x.\n",
- port->d_id);
- else
- dev_err(&port->adapter->ccw_device->dev,
- "Port ERP failed for port wwpn=0x%016Lx.\n",
- port->wwpn);
}
/**
@@ -1560,10 +1487,6 @@ void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
{
zfcp_erp_modify_unit_status(unit, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-
- dev_err(&unit->port->adapter->ccw_device->dev,
- "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
}
/**
@@ -1754,9 +1677,8 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id,
if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
- if (!(status & ZFCP_STATUS_PORT_WKA))
- list_for_each_entry(unit, &port->unit_list_head, list)
- zfcp_erp_unit_access_changed(unit, id, ref);
+ list_for_each_entry(unit, &port->unit_list_head, list)
+ zfcp_erp_unit_access_changed(unit, id, ref);
return;
}
@@ -1779,10 +1701,7 @@ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
return;
read_lock_irqsave(&zfcp_data.config_lock, flags);
- if (adapter->nameserver_port)
- zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
list_for_each_entry(port, &adapter->port_list_head, list)
- if (port != adapter->nameserver_port)
- zfcp_erp_port_access_changed(port, id, ref);
+ zfcp_erp_port_access_changed(port, id, ref);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index edfdb21591f..b5adeda93e1 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -12,16 +12,14 @@
#include "zfcp_def.h"
/* zfcp_aux.c */
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
- fcp_lun_t);
-extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *,
- wwn_t);
+extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
+extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
extern int zfcp_adapter_enqueue(struct ccw_device *);
extern void zfcp_adapter_dequeue(struct zfcp_adapter *);
-extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32,
+extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
u32);
extern void zfcp_port_dequeue(struct zfcp_port *);
-extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
+extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
extern void zfcp_unit_dequeue(struct zfcp_unit *);
extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
extern void zfcp_sg_free_table(struct scatterlist *, int);
@@ -29,6 +27,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
/* zfcp_ccw.c */
extern int zfcp_ccw_register(void);
+extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
/* zfcp_cfdc.c */
extern struct miscdevice zfcp_cfdc_misc;
@@ -50,6 +49,8 @@ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
struct fsf_status_read_buffer *);
extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int,
int);
+extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *,
+ struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
@@ -91,17 +92,21 @@ extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8, void *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *);
extern void zfcp_erp_timeout_handler(unsigned long);
+extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *);
/* zfcp_fc.c */
extern int zfcp_scan_ports(struct zfcp_adapter *);
extern void _zfcp_scan_ports_later(struct work_struct *);
extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
-extern int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *);
+extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *);
extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
extern void zfcp_test_link(struct zfcp_port *);
+extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
+extern int zfcp_fsf_open_wka_port(struct zfcp_wka_port *);
+extern int zfcp_fsf_close_wka_port(struct zfcp_wka_port *);
extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
@@ -135,10 +140,8 @@ extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
extern int zfcp_qdio_allocate(struct zfcp_adapter *);
extern void zfcp_qdio_free(struct zfcp_adapter *);
extern int zfcp_qdio_send(struct zfcp_fsf_req *);
-extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req(
- struct zfcp_fsf_req *);
-extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr(
- struct zfcp_fsf_req *);
+extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *);
+extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *);
extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long,
struct scatterlist *, int);
extern int zfcp_qdio_open(struct zfcp_adapter *);
@@ -148,14 +151,12 @@ extern void zfcp_qdio_close(struct zfcp_adapter *);
extern struct zfcp_data zfcp_data;
extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
-extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t);
extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
extern struct fc_function_template zfcp_transport_functions;
/* zfcp_sysfs.c */
extern struct attribute_group zfcp_sysfs_unit_attrs;
extern struct attribute_group zfcp_sysfs_adapter_attrs;
-extern struct attribute_group zfcp_sysfs_ns_port_attrs;
extern struct attribute_group zfcp_sysfs_port_attrs;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index e984469bb98..1a7c80a77ff 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -39,16 +39,82 @@ struct zfcp_gpn_ft {
struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS];
};
-static struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *adapter,
- u32 d_id)
+struct zfcp_fc_ns_handler_data {
+ struct completion done;
+ void (*handler)(unsigned long);
+ unsigned long handler_data;
+};
+
+static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
{
- struct zfcp_port *port;
+ if (mutex_lock_interruptible(&wka_port->mutex))
+ return -ERESTARTSYS;
- list_for_each_entry(port, &adapter->port_list_head, list)
- if ((port->d_id == d_id) &&
- !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status))
- return port;
- return NULL;
+ if (wka_port->status != ZFCP_WKA_PORT_ONLINE) {
+ wka_port->status = ZFCP_WKA_PORT_OPENING;
+ if (zfcp_fsf_open_wka_port(wka_port))
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ }
+
+ mutex_unlock(&wka_port->mutex);
+
+ wait_event_timeout(
+ wka_port->completion_wq,
+ wka_port->status == ZFCP_WKA_PORT_ONLINE ||
+ wka_port->status == ZFCP_WKA_PORT_OFFLINE,
+ HZ >> 1);
+
+ if (wka_port->status == ZFCP_WKA_PORT_ONLINE) {
+ atomic_inc(&wka_port->refcount);
+ return 0;
+ }
+ return -EIO;
+}
+
+static void zfcp_wka_port_offline(struct work_struct *work)
+{
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct zfcp_wka_port *wka_port =
+ container_of(dw, struct zfcp_wka_port, work);
+
+ wait_event(wka_port->completion_wq,
+ atomic_read(&wka_port->refcount) == 0);
+
+ mutex_lock(&wka_port->mutex);
+ if ((atomic_read(&wka_port->refcount) != 0) ||
+ (wka_port->status != ZFCP_WKA_PORT_ONLINE))
+ goto out;
+
+ wka_port->status = ZFCP_WKA_PORT_CLOSING;
+ if (zfcp_fsf_close_wka_port(wka_port)) {
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ wake_up(&wka_port->completion_wq);
+ }
+out:
+ mutex_unlock(&wka_port->mutex);
+}
+
+static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
+{
+ if (atomic_dec_return(&wka_port->refcount) != 0)
+ return;
+ /* wait 10 miliseconds, other reqs might pop in */
+ schedule_delayed_work(&wka_port->work, HZ / 100);
+}
+
+void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter)
+{
+ struct zfcp_wka_port *wka_port = &adapter->nsp;
+
+ init_waitqueue_head(&wka_port->completion_wq);
+
+ wka_port->adapter = adapter;
+ wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE;
+
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ atomic_set(&wka_port->refcount, 0);
+ mutex_init(&wka_port->mutex);
+ INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
}
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
@@ -59,10 +125,8 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
- if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
- continue;
/* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */
- if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status))
+ if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID))
/* Try to connect to unused ports anyway. */
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -114,7 +178,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
schedule_work(&fsf_req->adapter->scan_work);
}
-static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, wwn_t wwpn)
+static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
{
struct zfcp_adapter *adapter = req->adapter;
struct zfcp_port *port;
@@ -169,7 +233,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
zfcp_fc_incoming_rscn(fsf_req);
}
-static void zfcp_ns_gid_pn_handler(unsigned long data)
+static void zfcp_fc_ns_handler(unsigned long data)
+{
+ struct zfcp_fc_ns_handler_data *compl_rec =
+ (struct zfcp_fc_ns_handler_data *) data;
+
+ if (compl_rec->handler)
+ compl_rec->handler(compl_rec->handler_data);
+
+ complete(&compl_rec->done);
+}
+
+static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
{
struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data;
struct zfcp_send_ct *ct = &gid_pn->ct;
@@ -178,43 +253,31 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
struct zfcp_port *port = gid_pn->port;
if (ct->status)
- goto out;
+ return;
if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
- goto out;
+ return;
}
/* paranoia */
if (ct_iu_req->wwpn != port->wwpn)
- goto out;
+ return;
/* looks like a valid d_id */
port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
-out:
- mempool_free(gid_pn, port->adapter->pool.data_gid_pn);
}
-/**
- * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
- * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
- * return: -ENOMEM on error, 0 otherwise
- */
-int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
+int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
+ struct zfcp_gid_pn_data *gid_pn)
{
- int ret;
- struct zfcp_gid_pn_data *gid_pn;
struct zfcp_adapter *adapter = erp_action->adapter;
-
- gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
- if (!gid_pn)
- return -ENOMEM;
-
- memset(gid_pn, 0, sizeof(*gid_pn));
+ struct zfcp_fc_ns_handler_data compl_rec;
+ int ret;
/* setup parameters for send generic command */
gid_pn->port = erp_action->port;
- gid_pn->ct.port = adapter->nameserver_port;
- gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
- gid_pn->ct.handler_data = (unsigned long) gid_pn;
+ gid_pn->ct.wka_port = &adapter->nsp;
+ gid_pn->ct.handler = zfcp_fc_ns_handler;
+ gid_pn->ct.handler_data = (unsigned long) &compl_rec;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
gid_pn->ct.req = &gid_pn->req;
gid_pn->ct.resp = &gid_pn->resp;
@@ -234,10 +297,42 @@ int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE;
gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
+ init_completion(&compl_rec.done);
+ compl_rec.handler = zfcp_fc_ns_gid_pn_eval;
+ compl_rec.handler_data = (unsigned long) gid_pn;
ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
erp_action);
+ if (!ret)
+ wait_for_completion(&compl_rec.done);
+ return ret;
+}
+
+/**
+ * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
+ * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
+ * return: -ENOMEM on error, 0 otherwise
+ */
+int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action)
+{
+ int ret;
+ struct zfcp_gid_pn_data *gid_pn;
+ struct zfcp_adapter *adapter = erp_action->adapter;
+
+ gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
+ if (!gid_pn)
+ return -ENOMEM;
+
+ memset(gid_pn, 0, sizeof(*gid_pn));
+
+ ret = zfcp_wka_port_get(&adapter->nsp);
if (ret)
- mempool_free(gid_pn, adapter->pool.data_gid_pn);
+ goto out;
+
+ ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
+
+ zfcp_wka_port_put(&adapter->nsp);
+out:
+ mempool_free(gid_pn, adapter->pool.data_gid_pn);
return ret;
}
@@ -267,14 +362,14 @@ struct zfcp_els_adisc {
struct scatterlist req;
struct scatterlist resp;
struct zfcp_ls_adisc ls_adisc;
- struct zfcp_ls_adisc_acc ls_adisc_acc;
+ struct zfcp_ls_adisc ls_adisc_acc;
};
static void zfcp_fc_adisc_handler(unsigned long data)
{
struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data;
struct zfcp_port *port = adisc->els.port;
- struct zfcp_ls_adisc_acc *ls_adisc = &adisc->ls_adisc_acc;
+ struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc;
if (adisc->els.status) {
/* request rejected or timed out */
@@ -307,7 +402,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
sg_init_one(adisc->els.req, &adisc->ls_adisc,
sizeof(struct zfcp_ls_adisc));
sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc,
- sizeof(struct zfcp_ls_adisc_acc));
+ sizeof(struct zfcp_ls_adisc));
adisc->els.req_count = 1;
adisc->els.resp_count = 1;
@@ -341,37 +436,13 @@ void zfcp_test_link(struct zfcp_port *port)
zfcp_port_get(port);
retval = zfcp_fc_adisc(port);
- if (retval == 0 || retval == -EBUSY)
+ if (retval == 0)
return;
/* send of ADISC was not possible */
zfcp_port_put(port);
- zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
-}
-
-static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter)
-{
- int ret;
-
- if (!adapter->nameserver_port)
- return -EINTR;
-
- if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
- &adapter->nameserver_port->status)) {
- ret = zfcp_erp_port_reopen(adapter->nameserver_port, 0, 148,
- NULL);
- if (ret)
- return ret;
- zfcp_erp_wait(adapter);
- zfcp_port_put(adapter->nameserver_port);
- }
- return !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
- &adapter->nameserver_port->status);
-}
-
-static void zfcp_gpn_ft_handler(unsigned long _done)
-{
- complete((struct completion *)_done);
+ if (retval != -EBUSY)
+ zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
}
static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft)
@@ -415,7 +486,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
{
struct zfcp_send_ct *ct = &gpn_ft->ct;
struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
- struct completion done;
+ struct zfcp_fc_ns_handler_data compl_rec;
int ret;
/* prepare CT IU for GPN_FT */
@@ -432,19 +503,20 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
req->fc4_type = ZFCP_CT_SCSI_FCP;
/* prepare zfcp_send_ct */
- ct->port = adapter->nameserver_port;
- ct->handler = zfcp_gpn_ft_handler;
- ct->handler_data = (unsigned long)&done;
+ ct->wka_port = &adapter->nsp;
+ ct->handler = zfcp_fc_ns_handler;
+ ct->handler_data = (unsigned long)&compl_rec;
ct->timeout = 10;
ct->req = &gpn_ft->sg_req;
ct->resp = gpn_ft->sg_resp;
ct->req_count = 1;
ct->resp_count = ZFCP_GPN_FT_BUFFERS;
- init_completion(&done);
+ init_completion(&compl_rec.done);
+ compl_rec.handler = NULL;
ret = zfcp_fsf_send_ct(ct, NULL, NULL);
if (!ret)
- wait_for_completion(&done);
+ wait_for_completion(&compl_rec.done);
return ret;
}
@@ -454,9 +526,8 @@ static void zfcp_validate_port(struct zfcp_port *port)
atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
- if (port == adapter->nameserver_port)
- return;
- if ((port->supported_classes != 0) || (port->units != 0)) {
+ if ((port->supported_classes != 0) ||
+ !list_empty(&port->unit_list_head)) {
zfcp_port_put(port);
return;
}
@@ -472,10 +543,10 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
struct scatterlist *sg = gpn_ft->sg_resp;
struct ct_hdr *hdr = sg_virt(sg);
struct gpn_ft_resp_acc *acc = sg_virt(sg);
- struct zfcp_adapter *adapter = ct->port->adapter;
+ struct zfcp_adapter *adapter = ct->wka_port->adapter;
struct zfcp_port *port, *tmp;
u32 d_id;
- int ret = 0, x;
+ int ret = 0, x, last = 0;
if (ct->status)
return -EIO;
@@ -492,19 +563,27 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
down(&zfcp_data.config_sema);
/* first entry is the header */
- for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES; x++) {
+ for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) {
if (x % (ZFCP_GPN_FT_ENTRIES + 1))
acc++;
else
acc = sg_virt(++sg);
+ last = acc->control & 0x80;
d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 |
acc->port_id[2];
+ /* don't attach ports with a well known address */
+ if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA)
+ continue;
/* skip the adapter's port and known remote ports */
- if (acc->wwpn == fc_host_port_name(adapter->scsi_host) ||
- zfcp_get_port_by_did(adapter, d_id))
+ if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
continue;
+ port = zfcp_get_port_by_wwpn(adapter, acc->wwpn);
+ if (port) {
+ zfcp_port_get(port);
+ continue;
+ }
port = zfcp_port_enqueue(adapter, acc->wwpn,
ZFCP_STATUS_PORT_DID_DID |
@@ -513,8 +592,6 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
ret = PTR_ERR(port);
else
zfcp_erp_port_reopen(port, 0, 149, NULL);
- if (acc->control & 0x80) /* last entry */
- break;
}
zfcp_erp_wait(adapter);
@@ -537,13 +614,15 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
return 0;
- ret = zfcp_scan_get_nameserver(adapter);
+ ret = zfcp_wka_port_get(&adapter->nsp);
if (ret)
return ret;
gpn_ft = zfcp_alloc_sg_env();
- if (!gpn_ft)
- return -ENOMEM;
+ if (!gpn_ft) {
+ ret = -ENOMEM;
+ goto out;
+ }
for (i = 0; i < 3; i++) {
ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter);
@@ -556,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
}
}
zfcp_free_sg_env(gpn_ft);
-
+out:
+ zfcp_wka_port_put(&adapter->nsp);
return ret;
}
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 19c1ca91387..5ae1d497e5e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -6,6 +6,7 @@
* Copyright IBM Corporation 2002, 2008
*/
+#include <linux/blktrace_api.h>
#include "zfcp_ext.h"
static void zfcp_fsf_request_timeout_handler(unsigned long data)
@@ -50,19 +51,16 @@ static u32 fsf_qtcb_type[] = {
[FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND
};
-static const char *zfcp_act_subtable_type[] = {
- "unknown", "OS", "WWPN", "DID", "LUN"
-};
-
static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
{
u16 subtable = table >> 16;
u16 rule = table & 0xffff;
+ const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
- if (subtable && subtable < ARRAY_SIZE(zfcp_act_subtable_type))
+ if (subtable && subtable < ARRAY_SIZE(act_type))
dev_warn(&adapter->ccw_device->dev,
- "Access denied in subtable %s, rule %d.\n",
- zfcp_act_subtable_type[subtable], rule);
+ "Access denied according to ACT rule type %s, "
+ "rule %d\n", act_type[subtable], rule);
}
static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
@@ -70,8 +68,8 @@ static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
{
struct fsf_qtcb_header *header = &req->qtcb->header;
dev_warn(&req->adapter->ccw_device->dev,
- "Access denied, cannot send command to port 0x%016Lx.\n",
- port->wwpn);
+ "Access denied to port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
zfcp_erp_port_access_denied(port, 55, req);
@@ -83,8 +81,9 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
{
struct fsf_qtcb_header *header = &req->qtcb->header;
dev_warn(&req->adapter->ccw_device->dev,
- "Access denied for unit 0x%016Lx on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
zfcp_erp_unit_access_denied(unit, 59, req);
@@ -93,9 +92,8 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
- dev_err(&req->adapter->ccw_device->dev,
- "Required FC class not supported by adapter, "
- "shutting down adapter.\n");
+ dev_err(&req->adapter->ccw_device->dev, "FCP device not "
+ "operational because of an unsupported FC class\n");
zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
@@ -171,42 +169,6 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
-static void zfcp_fsf_bit_error_threshold(struct zfcp_fsf_req *req)
-{
- struct zfcp_adapter *adapter = req->adapter;
- struct fsf_status_read_buffer *sr_buf = req->data;
- struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
-
- dev_warn(&adapter->ccw_device->dev,
- "Warning: bit error threshold data "
- "received for the adapter: "
- "link failures = %i, loss of sync errors = %i, "
- "loss of signal errors = %i, "
- "primitive sequence errors = %i, "
- "invalid transmission word errors = %i, "
- "CRC errors = %i).\n",
- err->link_failure_error_count,
- err->loss_of_sync_error_count,
- err->loss_of_signal_error_count,
- err->primitive_sequence_error_count,
- err->invalid_transmission_word_error_count,
- err->crc_error_count);
- dev_warn(&adapter->ccw_device->dev,
- "Additional bit error threshold data of the adapter: "
- "primitive sequence event time-outs = %i, "
- "elastic buffer overrun errors = %i, "
- "advertised receive buffer-to-buffer credit = %i, "
- "current receice buffer-to-buffer credit = %i, "
- "advertised transmit buffer-to-buffer credit = %i, "
- "current transmit buffer-to-buffer credit = %i).\n",
- err->primitive_sequence_event_timeout_count,
- err->elastic_buffer_overrun_error_count,
- err->advertised_receive_b2b_credit,
- err->current_receive_b2b_credit,
- err->advertised_transmit_b2b_credit,
- err->current_transmit_b2b_credit);
-}
-
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id,
struct fsf_link_down_info *link_down)
{
@@ -223,62 +185,66 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id,
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: no light detected.\n");
+ "There is no light signal from the local "
+ "fibre channel cable\n");
break;
case FSF_PSQ_LINK_WRAP_PLUG:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: wrap plug detected.\n");
+ "There is a wrap plug instead of a fibre "
+ "channel cable\n");
break;
case FSF_PSQ_LINK_NO_FCP:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "adjacent node on link does not support FCP.\n");
+ "The adjacent fibre channel node does not "
+ "support FCP\n");
break;
case FSF_PSQ_LINK_FIRMWARE_UPDATE:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "firmware update in progress.\n");
+ "The FCP device is suspended because of a "
+ "firmware update\n");
break;
case FSF_PSQ_LINK_INVALID_WWPN:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "duplicate or invalid WWPN detected.\n");
+ "The FCP device detected a WWPN that is "
+ "duplicate or not valid\n");
break;
case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "no support for NPIV by Fabric.\n");
+ "The fibre channel fabric does not support NPIV\n");
break;
case FSF_PSQ_LINK_NO_FCP_RESOURCES:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "out of resource in FCP daughtercard.\n");
+ "The FCP adapter cannot support more NPIV ports\n");
break;
case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "out of resource in Fabric.\n");
+ "The adjacent switch cannot support "
+ "more NPIV ports\n");
break;
case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "unable to login to Fabric.\n");
+ "The FCP adapter could not log in to the "
+ "fibre channel fabric\n");
break;
case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
dev_warn(&req->adapter->ccw_device->dev,
- "WWPN assignment file corrupted on adapter.\n");
+ "The WWPN assignment file on the FCP adapter "
+ "has been damaged\n");
break;
case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
dev_warn(&req->adapter->ccw_device->dev,
- "Mode table corrupted on adapter.\n");
+ "The mode table on the FCP adapter "
+ "has been damaged\n");
break;
case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
dev_warn(&req->adapter->ccw_device->dev,
- "No WWPN for assignment table on adapter.\n");
+ "All NPIV ports on the FCP adapter have "
+ "been assigned\n");
break;
default:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link to adapter is down.\n");
+ "The link between the FCP adapter and "
+ "the FC fabric is down\n");
}
out:
zfcp_erp_adapter_failed(adapter, id, req);
@@ -286,27 +252,18 @@ out:
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
{
- struct zfcp_adapter *adapter = req->adapter;
struct fsf_status_read_buffer *sr_buf = req->data;
struct fsf_link_down_info *ldi =
(struct fsf_link_down_info *) &sr_buf->payload;
switch (sr_buf->status_subtype) {
case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
- dev_warn(&adapter->ccw_device->dev,
- "Physical link is down.\n");
zfcp_fsf_link_down_info_eval(req, 38, ldi);
break;
case FSF_STATUS_READ_SUB_FDISC_FAILED:
- dev_warn(&adapter->ccw_device->dev,
- "Local link is down "
- "due to failed FDISC login.\n");
zfcp_fsf_link_down_info_eval(req, 39, ldi);
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
- dev_warn(&adapter->ccw_device->dev,
- "Local link is down "
- "due to firmware update on adapter.\n");
zfcp_fsf_link_down_info_eval(req, 40, NULL);
};
}
@@ -335,14 +292,17 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
case FSF_STATUS_READ_SENSE_DATA_AVAIL:
break;
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
- zfcp_fsf_bit_error_threshold(req);
+ dev_warn(&adapter->ccw_device->dev,
+ "The error threshold for checksum statistics "
+ "has been exceeded\n");
+ zfcp_hba_dbf_event_berr(adapter, req);
break;
case FSF_STATUS_READ_LINK_DOWN:
zfcp_fsf_status_read_link_down(req);
break;
case FSF_STATUS_READ_LINK_UP:
dev_info(&adapter->ccw_device->dev,
- "Local link was replugged.\n");
+ "The local link has been restored\n");
/* All ports should be marked as ready to run again */
zfcp_erp_modify_adapter_status(adapter, 30, NULL,
ZFCP_STATUS_COMMON_RUNNING,
@@ -370,7 +330,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
zfcp_fsf_req_free(req);
atomic_inc(&adapter->stat_miss);
- schedule_work(&adapter->stat_work);
+ queue_work(zfcp_data.work_queue, &adapter->stat_work);
}
static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
@@ -386,8 +346,8 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
break;
case FSF_SQ_NO_RECOM:
dev_err(&req->adapter->ccw_device->dev,
- "No recommendation could be given for a "
- "problem on the adapter.\n");
+ "The FCP adapter reported a problem "
+ "that cannot be recovered\n");
zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req);
break;
}
@@ -403,8 +363,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
switch (req->qtcb->header.fsf_status) {
case FSF_UNKNOWN_COMMAND:
dev_err(&req->adapter->ccw_device->dev,
- "Command issued by the device driver (0x%x) is "
- "not known by the adapter.\n",
+ "The FCP adapter does not recognize the command 0x%x\n",
req->qtcb->header.fsf_command);
zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -435,11 +394,9 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
return;
case FSF_PROT_QTCB_VERSION_ERROR:
dev_err(&adapter->ccw_device->dev,
- "The QTCB version requested by zfcp (0x%x) is not "
- "supported by the FCP adapter (lowest supported "
- "0x%x, highest supported 0x%x).\n",
- FSF_QTCB_CURRENT_VERSION, psq->word[0],
- psq->word[1]);
+ "QTCB version 0x%x not supported by FCP adapter "
+ "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
+ psq->word[0], psq->word[1]);
zfcp_erp_adapter_shutdown(adapter, 0, 117, req);
break;
case FSF_PROT_ERROR_STATE:
@@ -449,8 +406,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
case FSF_PROT_UNSUPP_QTCB_TYPE:
dev_err(&adapter->ccw_device->dev,
- "Packet header type used by the device driver is "
- "incompatible with that used on the adapter.\n");
+ "The QTCB type is not supported by the FCP adapter\n");
zfcp_erp_adapter_shutdown(adapter, 0, 118, req);
break;
case FSF_PROT_HOST_CONNECTION_INITIALIZING:
@@ -459,7 +415,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
case FSF_PROT_DUPLICATE_REQUEST_ID:
dev_err(&adapter->ccw_device->dev,
- "The request identifier 0x%Lx is ambiguous.\n",
+ "0x%Lx is an ambiguous request identifier\n",
(unsigned long long)qtcb->bottom.support.req_handle);
zfcp_erp_adapter_shutdown(adapter, 0, 78, req);
break;
@@ -479,9 +435,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
default:
dev_err(&adapter->ccw_device->dev,
- "Transfer protocol status information"
- "provided by the adapter (0x%x) "
- "is not compatible with the device driver.\n",
+ "0x%x is not a valid transfer protocol status\n",
qtcb->prefix.prot_status);
zfcp_erp_adapter_shutdown(adapter, 0, 119, req);
}
@@ -559,33 +513,17 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
adapter->peer_wwpn = bottom->plogi_payload.wwpn;
adapter->peer_wwnn = bottom->plogi_payload.wwnn;
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
- if (req->erp_action)
- dev_info(&adapter->ccw_device->dev,
- "Point-to-Point fibrechannel "
- "configuration detected.\n");
break;
case FSF_TOPO_FABRIC:
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
- if (req->erp_action)
- dev_info(&adapter->ccw_device->dev,
- "Switched fabric fibrechannel "
- "network detected.\n");
break;
case FSF_TOPO_AL:
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
- dev_err(&adapter->ccw_device->dev,
- "Unsupported arbitrated loop fibrechannel "
- "topology detected, shutting down "
- "adapter.\n");
- zfcp_erp_adapter_shutdown(adapter, 0, 127, req);
- return -EIO;
default:
- fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
dev_err(&adapter->ccw_device->dev,
- "The fibrechannel topology reported by the"
- " adapter is not known by the zfcp driver,"
- " shutting down adapter.\n");
- zfcp_erp_adapter_shutdown(adapter, 0, 128, req);
+ "Unknown or unsupported arbitrated loop "
+ "fibre channel topology detected\n");
+ zfcp_erp_adapter_shutdown(adapter, 0, 127, req);
return -EIO;
}
@@ -616,11 +554,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
dev_err(&adapter->ccw_device->dev,
- "Maximum QTCB size (%d bytes) allowed by "
- "the adapter is lower than the minimum "
- "required by the driver (%ld bytes).\n",
- bottom->max_qtcb_size,
- sizeof(struct fsf_qtcb));
+ "FCP adapter maximum QTCB size (%d bytes) "
+ "is too small\n",
+ bottom->max_qtcb_size);
zfcp_erp_adapter_shutdown(adapter, 0, 129, req);
return;
}
@@ -656,15 +592,15 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
dev_err(&adapter->ccw_device->dev,
- "The adapter only supports newer control block "
- "versions, try updated device driver.\n");
+ "The FCP adapter only supports newer "
+ "control block versions\n");
zfcp_erp_adapter_shutdown(adapter, 0, 125, req);
return;
}
if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
dev_err(&adapter->ccw_device->dev,
- "The adapter only supports older control block "
- "versions, consider a microcode upgrade.\n");
+ "The FCP adapter only supports older "
+ "control block versions\n");
zfcp_erp_adapter_shutdown(adapter, 0, 126, req);
}
}
@@ -688,7 +624,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
{
- struct zfcp_adapter *adapter = req->adapter;
struct fsf_qtcb *qtcb = req->qtcb;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -697,38 +632,47 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
zfcp_fsf_exchange_port_evaluate(req);
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
zfcp_fsf_exchange_port_evaluate(req);
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
zfcp_fsf_link_down_info_eval(req, 43,
&qtcb->header.fsf_status_qual.link_down_info);
break;
}
}
-static int zfcp_fsf_sbal_check(struct zfcp_qdio_queue *queue)
+static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
{
- spin_lock(&queue->lock);
- if (atomic_read(&queue->count))
+ struct zfcp_qdio_queue *req_q = &adapter->req_q;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (atomic_read(&req_q->count))
return 1;
- spin_unlock(&queue->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return 0;
}
+static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter)
+{
+ unsigned int count = atomic_read(&adapter->req_q.count);
+ if (!count)
+ atomic_inc(&adapter->qdio_outb_full);
+ return count > 0;
+}
+
static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
{
long ret;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
- spin_unlock(&req_q->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
ret = wait_event_interruptible_timeout(adapter->request_wq,
- zfcp_fsf_sbal_check(req_q), 5 * HZ);
+ zfcp_fsf_sbal_check(adapter), 5 * HZ);
if (ret > 0)
return 0;
+ if (!ret)
+ atomic_inc(&adapter->qdio_outb_full);
- spin_lock(&req_q->lock);
+ spin_lock_bh(&adapter->req_q_lock);
return -EIO;
}
@@ -765,7 +709,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
u32 fsf_cmd, int req_flags,
mempool_t *pool)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_qdio_queue *req_q = &adapter->req_q;
@@ -834,6 +778,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
list_add_tail(&req->list, &adapter->req_list[idx]);
spin_unlock(&adapter->req_list_lock);
+ req->qdio_outb_usage = atomic_read(&req_q->count);
req->issued = get_clock();
if (zfcp_qdio_send(req)) {
/* Queues are down..... */
@@ -867,17 +812,17 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
{
struct zfcp_fsf_req *req;
struct fsf_status_read_buffer *sr_buf;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
ZFCP_REQ_NO_QTCB,
adapter->pool.fsf_req_status_read);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -910,7 +855,7 @@ failed_buf:
zfcp_fsf_req_free(req);
zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -980,15 +925,15 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
struct zfcp_unit *unit,
int req_flags)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
req_flags, adapter->pool.fsf_req_abort);
- if (unlikely(IS_ERR(req)))
+ if (IS_ERR(req))
goto out;
if (unlikely(!(atomic_read(&unit->status) &
@@ -1013,7 +958,7 @@ out_error_free:
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return req;
}
@@ -1021,7 +966,6 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
struct zfcp_send_ct *send_ct = req->data;
- struct zfcp_port *port = send_ct->port;
struct fsf_qtcb_header *header = &req->qtcb->header;
send_ct->status = -EINVAL;
@@ -1040,17 +984,14 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_test_link(port);
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
break;
case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_port(req, port);
break;
case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(port, 49, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
@@ -1101,18 +1042,18 @@ static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req,
int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
struct zfcp_erp_action *erp_action)
{
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
struct zfcp_fsf_req *req;
int ret = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
ZFCP_REQ_AUTO_CLEANUP, pool);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
@@ -1123,7 +1064,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
goto failed_send;
req->handler = zfcp_fsf_send_ct_handler;
- req->qtcb->header.port_handle = port->handle;
+ req->qtcb->header.port_handle = wka_port->handle;
req->qtcb->bottom.support.service_class = FSF_CLASS_3;
req->qtcb->bottom.support.timeout = ct->timeout;
req->data = ct;
@@ -1148,7 +1089,7 @@ failed_send:
if (erp_action)
erp_action->fsf_req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return ret;
}
@@ -1218,18 +1159,18 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
ZFCP_REQ_AUTO_CLEANUP, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
- ret = zfcp_fsf_setup_sbals(req, els->req, els->resp,
- FSF_MAX_SBALS_PER_ELS_REQ);
+ ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2);
+
if (ret)
goto failed_send;
@@ -1252,25 +1193,25 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
failed_send:
zfcp_fsf_req_free(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return ret;
}
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_adapter *adapter = erp_action->adapter;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter,
FSF_QTCB_EXCHANGE_CONFIG_DATA,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1295,24 +1236,24 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
struct fsf_qtcb_bottom_config *data)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
0, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1334,7 +1275,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
@@ -1351,7 +1292,7 @@ out:
*/
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_adapter *adapter = erp_action->adapter;
int retval = -EIO;
@@ -1359,13 +1300,13 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1385,7 +1326,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1398,20 +1339,20 @@ out:
int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
struct fsf_qtcb_bottom_port *data)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1427,7 +1368,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
@@ -1443,7 +1384,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
struct fsf_plogi *plogi;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (header->fsf_status) {
case FSF_PORT_ALREADY_OPEN:
@@ -1453,9 +1394,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
break;
case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
dev_warn(&req->adapter->ccw_device->dev,
- "The adapter is out of resources. The remote port "
- "0x%016Lx could not be opened, disabling it.\n",
- port->wwpn);
+ "Not enough FCP adapter resources to open "
+ "remote port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 31, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -1467,8 +1408,8 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
break;
case FSF_SQ_NO_RETRY_POSSIBLE:
dev_warn(&req->adapter->ccw_device->dev,
- "The remote port 0x%016Lx could not be "
- "opened. Disabling it.\n", port->wwpn);
+ "Remote port 0x%016Lx could not be opened\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 32, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -1496,9 +1437,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
* another GID_PN straight after a port has been opened.
* Alternately, an ADISC/PDISC ELS should suffice, as well.
*/
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN)
- break;
-
plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) {
if (plogi->serv_param.wwpn != port->wwpn)
@@ -1514,9 +1452,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status);
}
/**
@@ -1526,12 +1461,12 @@ skip_fsfstatus:
*/
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
@@ -1539,7 +1474,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_PORT_WITH_DID,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1553,7 +1488,6 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
req->data = erp_action->port;
req->erp_action = erp_action;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1562,7 +1496,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1571,7 +1505,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
struct zfcp_port *port = req->data;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
@@ -1586,9 +1520,6 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
ZFCP_CLEAR);
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status);
}
/**
@@ -1598,19 +1529,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1624,7 +1555,6 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
req->erp_action = erp_action;
req->qtcb->header.port_handle = erp_action->port->handle;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1633,7 +1563,131 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
+}
+
+static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
+{
+ struct zfcp_wka_port *wka_port = req->data;
+ struct fsf_qtcb_header *header = &req->qtcb->header;
+
+ if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ goto out;
+ }
+
+ switch (header->fsf_status) {
+ case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
+ dev_warn(&req->adapter->ccw_device->dev,
+ "Opening WKA port 0x%x failed\n", wka_port->d_id);
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ case FSF_ACCESS_DENIED:
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ break;
+ case FSF_PORT_ALREADY_OPEN:
+ case FSF_GOOD:
+ wka_port->handle = header->port_handle;
+ wka_port->status = ZFCP_WKA_PORT_ONLINE;
+ }
+out:
+ wake_up(&wka_port->completion_wq);
+}
+
+/**
+ * zfcp_fsf_open_wka_port - create and send open wka-port request
+ * @wka_port: pointer to struct zfcp_wka_port
+ * Returns: 0 on success, error otherwise
+ */
+int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
+{
+ struct qdio_buffer_element *sbale;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_fsf_req *req;
+ int retval = -EIO;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(adapter))
+ goto out;
+
+ req = zfcp_fsf_req_create(adapter,
+ FSF_QTCB_OPEN_PORT_WITH_DID,
+ ZFCP_REQ_AUTO_CLEANUP,
+ adapter->pool.fsf_req_erp);
+ if (unlikely(IS_ERR(req))) {
+ retval = PTR_ERR(req);
+ goto out;
+ }
+
+ sbale = zfcp_qdio_sbale_req(req);
+ sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+ sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+ req->handler = zfcp_fsf_open_wka_port_handler;
+ req->qtcb->bottom.support.d_id = wka_port->d_id;
+ req->data = wka_port;
+
+ zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(req);
+ if (retval)
+ zfcp_fsf_req_free(req);
+out:
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
+}
+
+static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
+{
+ struct zfcp_wka_port *wka_port = req->data;
+
+ if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ zfcp_erp_adapter_reopen(wka_port->adapter, 0, 84, req);
+ }
+
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ wake_up(&wka_port->completion_wq);
+}
+
+/**
+ * zfcp_fsf_close_wka_port - create and send close wka port request
+ * @erp_action: pointer to struct zfcp_erp_action
+ * Returns: 0 on success, error otherwise
+ */
+int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
+{
+ struct qdio_buffer_element *sbale;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_fsf_req *req;
+ int retval = -EIO;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(adapter))
+ goto out;
+
+ req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
+ ZFCP_REQ_AUTO_CLEANUP,
+ adapter->pool.fsf_req_erp);
+ if (unlikely(IS_ERR(req))) {
+ retval = PTR_ERR(req);
+ goto out;
+ }
+
+ sbale = zfcp_qdio_sbale_req(req);
+ sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+ sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+ req->handler = zfcp_fsf_close_wka_port_handler;
+ req->data = wka_port;
+ req->qtcb->header.port_handle = wka_port->handle;
+
+ zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(req);
+ if (retval)
+ zfcp_fsf_req_free(req);
+out:
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1695,19 +1749,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1731,7 +1785,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1746,7 +1800,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
int exclusive, readwrite;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED |
@@ -1774,14 +1828,12 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
case FSF_LUN_SHARING_VIOLATION:
if (header->fsf_status_qual.word[0])
dev_warn(&adapter->ccw_device->dev,
- "FCP-LUN 0x%Lx at the remote port "
- "with WWPN 0x%Lx "
- "connected to the adapter "
- "is already in use in LPAR%d, CSS%d.\n",
- unit->fcp_lun,
- unit->port->wwpn,
- queue_designator->hla,
- queue_designator->cssid);
+ "LUN 0x%Lx on port 0x%Lx is already in "
+ "use by CSS%d, MIF Image ID %x\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn,
+ queue_designator->cssid,
+ queue_designator->hla);
else
zfcp_act_eval_err(adapter,
header->fsf_status_qual.word[2]);
@@ -1792,9 +1844,10 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
break;
case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
dev_warn(&adapter->ccw_device->dev,
- "The adapter ran out of resources. There is no "
- "handle available for unit 0x%016Lx on port 0x%016Lx.",
- unit->fcp_lun, unit->port->wwpn);
+ "No handle is available for LUN "
+ "0x%016Lx on port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 34, req);
/* fall through */
case FSF_INVALID_COMMAND_OPTION:
@@ -1831,26 +1884,29 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
&unit->status);
dev_info(&adapter->ccw_device->dev,
- "Read-only access for unit 0x%016Lx "
- "on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "SCSI device at LUN 0x%016Lx on port "
+ "0x%016Lx opened read-only\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
}
if (exclusive && !readwrite) {
dev_err(&adapter->ccw_device->dev,
- "Exclusive access of read-only unit "
- "0x%016Lx on port 0x%016Lx not "
- "supported, disabling unit.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Exclusive read-only access not "
+ "supported (unit 0x%016Lx, "
+ "port 0x%016Lx)\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 35, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
zfcp_erp_unit_shutdown(unit, 0, 80, req);
} else if (!exclusive && readwrite) {
dev_err(&adapter->ccw_device->dev,
- "Shared access of read-write unit "
- "0x%016Lx on port 0x%016Lx not "
- "supported, disabling unit.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Shared read-write access not "
+ "supported (unit 0x%016Lx, port "
+ "0x%016Lx\n)",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 36, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
zfcp_erp_unit_shutdown(unit, 0, 81, req);
@@ -1858,9 +1914,6 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
}
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status);
}
/**
@@ -1870,19 +1923,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1901,8 +1954,6 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
-
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
if (retval) {
@@ -1910,7 +1961,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1919,7 +1970,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
struct zfcp_unit *unit = req->data;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
@@ -1949,8 +2000,6 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
break;
}
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status);
}
/**
@@ -1960,18 +2009,18 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1986,7 +2035,6 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
req->data = erp_action->unit;
req->erp_action = erp_action;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1995,7 +2043,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -2036,6 +2084,36 @@ static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
spin_unlock_irqrestore(&unit->latencies.lock, flags);
}
+#ifdef CONFIG_BLK_DEV_IO_TRACE
+static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
+{
+ struct fsf_qual_latency_info *lat_inf;
+ struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+ struct request *req = scsi_cmnd->request;
+ struct zfcp_blk_drv_data trace;
+ int ticks = fsf_req->adapter->timer_ticks;
+
+ trace.flags = 0;
+ trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
+ if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
+ trace.flags |= ZFCP_BLK_LAT_VALID;
+ lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
+ trace.channel_lat = lat_inf->channel_lat * ticks;
+ trace.fabric_lat = lat_inf->fabric_lat * ticks;
+ }
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
+ trace.flags |= ZFCP_BLK_REQ_ERROR;
+ trace.inb_usage = fsf_req->qdio_inb_usage;
+ trace.outb_usage = fsf_req->qdio_outb_usage;
+
+ blk_add_driver_data(req->q, req, &trace, sizeof(trace));
+}
+#else
+static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
+{
+}
+#endif
+
static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
{
struct scsi_cmnd *scpnt = req->data;
@@ -2068,6 +2146,8 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
zfcp_fsf_req_latency(req);
+ zfcp_fsf_trace_latency(req);
+
if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
if (fcp_rsp_info[3] == RSP_CODE_GOOD)
set_host_byte(scpnt, DID_OK);
@@ -2156,21 +2236,21 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
break;
case FSF_DIRECTION_INDICATOR_NOT_VALID:
dev_err(&req->adapter->ccw_device->dev,
- "Invalid data direction (%d) given for unit "
- "0x%016Lx on port 0x%016Lx, shutting down "
- "adapter.\n",
+ "Incorrect direction %d, unit 0x%016Lx on port "
+ "0x%016Lx closed\n",
req->qtcb->bottom.io.data_direction,
- unit->fcp_lun, unit->port->wwpn);
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_CMND_LENGTH_NOT_VALID:
dev_err(&req->adapter->ccw_device->dev,
- "An invalid control-data-block length field (%d) "
- "was found in a command for unit 0x%016Lx on port "
- "0x%016Lx. Shutting down adapter.\n",
+ "Incorrect CDB length %d, unit 0x%016Lx on "
+ "port 0x%016Lx closed\n",
req->qtcb->bottom.io.fcp_cmnd_length,
- unit->fcp_lun, unit->port->wwpn);
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2201,6 +2281,20 @@ skip_fsfstatus:
}
}
+static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
+{
+ u32 *fcp_dl_ptr;
+
+ /*
+ * fcp_dl_addr = start address of fcp_cmnd structure +
+ * size of fixed part + size of dynamically sized add_dcp_cdb field
+ * SEE FCP-2 documentation
+ */
+ fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
+ (fcp_cmd->add_fcp_cdb_length << 2));
+ *fcp_dl_ptr = fcp_dl;
+}
+
/**
* zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
* @adapter: adapter where scsi command is issued
@@ -2223,12 +2317,12 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
adapter->pool.fsf_req_scsi);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -2286,7 +2380,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
- fcp_cmnd_iu->add_fcp_cdb_length + sizeof(fcp_dl_t);
+ fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype,
scsi_sglist(scsi_cmnd),
@@ -2296,10 +2390,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
retval = -EIO;
else {
dev_err(&adapter->ccw_device->dev,
- "SCSI request too large. "
- "Shutting down unit 0x%016Lx on port "
- "0x%016Lx.\n", unit->fcp_lun,
- unit->port->wwpn);
+ "Oversize data package, unit 0x%016Lx "
+ "on port 0x%016Lx closed\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_shutdown(unit, 0, 131, req);
retval = -EINVAL;
}
@@ -2322,7 +2416,7 @@ failed_scsi_cmnd:
zfcp_fsf_req_free(req);
scsi_cmnd->host_scribble = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return retval;
}
@@ -2338,7 +2432,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
struct zfcp_unit *unit,
u8 tm_flags, int req_flags)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -2346,12 +2440,12 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
ZFCP_STATUS_COMMON_UNBLOCKED)))
return NULL;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
adapter->pool.fsf_req_scsi);
- if (unlikely(IS_ERR(req)))
+ if (IS_ERR(req))
goto out;
req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
@@ -2362,7 +2456,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
req->qtcb->bottom.io.service_class = FSF_CLASS_3;
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
- sizeof(fcp_dl_t);
+ sizeof(u32);
sbale = zfcp_qdio_sbale_req(req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
@@ -2379,7 +2473,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return req;
}
@@ -2398,7 +2492,7 @@ static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_cfdc *fsf_cfdc)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
struct fsf_qtcb_bottom_support *bottom;
int direction, retval = -EIO, bytes;
@@ -2417,12 +2511,12 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
return ERR_PTR(-EINVAL);
}
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = -EPERM;
goto out;
}
@@ -2447,7 +2541,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval) {
wait_event(req->completion_wq,
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index bf94b4da076..fa2a3178061 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -71,13 +71,6 @@
#define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041
#define FSF_ELS_COMMAND_REJECTED 0x00000050
#define FSF_GENERIC_COMMAND_REJECTED 0x00000051
-#define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052
-#define FSF_AUTHORIZATION_FAILURE 0x00000053
-#define FSF_CFDC_ERROR_DETECTED 0x00000054
-#define FSF_CONTROL_FILE_UPDATE_ERROR 0x00000055
-#define FSF_CONTROL_FILE_TOO_LARGE 0x00000056
-#define FSF_ACCESS_CONFLICT_DETECTED 0x00000057
-#define FSF_CONFLICTS_OVERRULED 0x00000058
#define FSF_PORT_BOXED 0x00000059
#define FSF_LUN_BOXED 0x0000005A
#define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B
@@ -85,9 +78,7 @@
#define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061
#define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062
#define FSF_SBAL_MISMATCH 0x00000063
-#define FSF_OPEN_PORT_WITHOUT_PRLI 0x00000064
#define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD
-#define FSF_FCP_RSP_AVAILABLE 0x000000AF
#define FSF_UNKNOWN_COMMAND 0x000000E2
#define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3
#define FSF_INVALID_COMMAND_OPTION 0x000000E5
@@ -102,20 +93,9 @@
#define FSF_SQ_RETRY_IF_POSSIBLE 0x02
#define FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED 0x03
#define FSF_SQ_INVOKE_LINK_TEST_PROCEDURE 0x04
-#define FSF_SQ_ULP_PROGRAMMING_ERROR 0x05
#define FSF_SQ_COMMAND_ABORTED 0x06
#define FSF_SQ_NO_RETRY_POSSIBLE 0x07
-/* FSF status qualifier for CFDC commands */
-#define FSF_SQ_CFDC_HARDENED_ON_SE 0x00000000
-#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE 0x00000001
-#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2 0x00000002
-/* CFDC subtable codes */
-#define FSF_SQ_CFDC_SUBTABLE_OS 0x0001
-#define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN 0x0002
-#define FSF_SQ_CFDC_SUBTABLE_PORT_DID 0x0003
-#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004
-
/* FSF status qualifier (most significant 4 bytes), local link down */
#define FSF_PSQ_LINK_NO_LIGHT 0x00000004
#define FSF_PSQ_LINK_WRAP_PLUG 0x00000008
@@ -145,7 +125,6 @@
#define FSF_STATUS_READ_LINK_UP 0x00000006
#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
-#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
/* status subtypes in status read buffer */
@@ -159,20 +138,9 @@
/* status subtypes for unsolicited status notification lost */
#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001
-#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002
-#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004
-#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008
-#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010
#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020
-#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040
-#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
-
-/* status subtypes for CFDC */
-#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
-#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
/* topologie that is detected by the adapter */
-#define FSF_TOPO_ERROR 0x00000000
#define FSF_TOPO_P2P 0x00000001
#define FSF_TOPO_FABRIC 0x00000002
#define FSF_TOPO_AL 0x00000003
@@ -180,17 +148,13 @@
/* data direction for FCP commands */
#define FSF_DATADIR_WRITE 0x00000001
#define FSF_DATADIR_READ 0x00000002
-#define FSF_DATADIR_READ_WRITE 0x00000003
#define FSF_DATADIR_CMND 0x00000004
/* fc service class */
-#define FSF_CLASS_1 0x00000001
-#define FSF_CLASS_2 0x00000002
#define FSF_CLASS_3 0x00000003
/* SBAL chaining */
#define FSF_MAX_SBALS_PER_REQ 36
-#define FSF_MAX_SBALS_PER_ELS_REQ 2
/* logging space behind QTCB */
#define FSF_QTCB_LOG_SIZE 1024
@@ -200,50 +164,16 @@
#define FSF_FEATURE_LUN_SHARING 0x00000004
#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
-#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
/* host connection features */
#define FSF_FEATURE_NPIV_MODE 0x00000001
-#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002
/* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
-#define FSF_OPEN_LUN_REPLICATE_SENSE 0x00000002
-
-/* adapter types */
-#define FSF_ADAPTER_TYPE_FICON 0x00000001
-#define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002
-
-/* port types */
-#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001
-#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
-#define FSF_HBA_PORTTYPE_NPORT 0x00000005
-#define FSF_HBA_PORTTYPE_PTP 0x00000021
-/* following are not defined and used by FSF Spec
- but are additionally defined by FC-HBA */
-#define FSF_HBA_PORTTYPE_OTHER 0x00000002
-#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
-#define FSF_HBA_PORTTYPE_NLPORT 0x00000006
-#define FSF_HBA_PORTTYPE_FLPORT 0x00000007
-#define FSF_HBA_PORTTYPE_FPORT 0x00000008
-#define FSF_HBA_PORTTYPE_LPORT 0x00000020
-
-/* port states */
-#define FSF_HBA_PORTSTATE_UNKNOWN 0x00000001
-#define FSF_HBA_PORTSTATE_ONLINE 0x00000002
-#define FSF_HBA_PORTSTATE_OFFLINE 0x00000003
-#define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006
-#define FSF_HBA_PORTSTATE_ERROR 0x00000007
-
-/* IO states of adapter */
-#define FSF_IOSTAT_NPORT_RJT 0x00000004
-#define FSF_IOSTAT_FABRIC_RJT 0x00000005
-#define FSF_IOSTAT_LS_RJT 0x00000009
/* open LUN access flags*/
-#define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000
#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000
#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000
@@ -265,11 +195,6 @@ struct fsf_queue_designator {
u32 res1;
} __attribute__ ((packed));
-struct fsf_port_closed_payload {
- struct fsf_queue_designator queue_designator;
- u32 port_handle;
-} __attribute__ ((packed));
-
struct fsf_bit_error_payload {
u32 res1;
u32 link_failure_error_count;
@@ -514,4 +439,16 @@ struct fsf_qtcb {
u8 log[FSF_QTCB_LOG_SIZE];
} __attribute__ ((packed));
+struct zfcp_blk_drv_data {
+#define ZFCP_BLK_DRV_DATA_MAGIC 0x1
+ u32 magic;
+#define ZFCP_BLK_LAT_VALID 0x1
+#define ZFCP_BLK_REQ_ERROR 0x2
+ u16 flags;
+ u8 inb_usage;
+ u8 outb_usage;
+ u64 channel_lat;
+ u64 fabric_lat;
+} __attribute__ ((packed));
+
#endif /* FSF_H */
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d6dbd653fde..664752f90b2 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -28,7 +28,7 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
return 0;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
{
return &q->sbal[sbal_idx]->element[sbale_idx];
@@ -57,7 +57,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter)
static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id)
{
- dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n");
+ dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
@@ -115,6 +115,7 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
fsf_req->sbal_response = sbal_idx;
+ fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
zfcp_fsf_req_complete(fsf_req);
}
@@ -145,7 +146,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
{
struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
struct zfcp_qdio_queue *queue = &adapter->resp_q;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int sbal_idx, sbale_idx, sbal_no;
if (unlikely(qdio_err)) {
@@ -174,8 +175,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
dev_warn(&adapter->ccw_device->dev,
- "Protocol violation by adapter. "
- "Continuing operations.\n");
+ "A QDIO protocol error occurred, "
+ "operations continue\n");
}
/*
@@ -190,8 +191,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
* @fsf_req: pointer to struct fsf_req
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
{
return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
}
@@ -201,8 +201,7 @@ zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
* @fsf_req: pointer to struct fsf_req
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
{
return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
req->sbale_curr);
@@ -216,10 +215,10 @@ static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
% QDIO_MAX_BUFFERS_PER_Q;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
/* set last entry flag in current SBALE of current SBAL */
sbale = zfcp_qdio_sbale_curr(fsf_req);
@@ -250,7 +249,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
return sbale;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
{
if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
@@ -273,7 +272,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
unsigned int sbtype, void *start_addr,
unsigned int total_length)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
unsigned long remaining, length;
void *addr;
@@ -282,6 +281,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
addr += length, remaining -= length) {
sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
if (!sbale) {
+ atomic_inc(&fsf_req->adapter->qdio_outb_full);
zfcp_qdio_undo_sbals(fsf_req);
return -EINVAL;
}
@@ -307,7 +307,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
struct scatterlist *sg, int max_sbals)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int retval, bytes = 0;
/* figure out last allowed SBAL */
@@ -344,10 +344,10 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
int first = fsf_req->sbal_first;
int count = fsf_req->sbal_number;
int retval, pci, pci_batch;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
/* acknowledgements for transferred buffers */
- pci_batch = req_q->pci_batch + count;
+ pci_batch = adapter->req_q_pci_batch + count;
if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) {
pci_batch %= ZFCP_QDIO_PCI_INTERVAL;
pci = first + count - (pci_batch + 1);
@@ -367,7 +367,7 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
atomic_sub(count, &req_q->count);
req_q->first += count;
req_q->first %= QDIO_MAX_BUFFERS_PER_Q;
- req_q->pci_batch = pci_batch;
+ adapter->req_q_pci_batch = pci_batch;
return 0;
}
@@ -418,14 +418,14 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
struct zfcp_qdio_queue *req_q;
int first, count;
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
req_q = &adapter->req_q;
- spin_lock(&req_q->lock);
+ spin_lock_bh(&adapter->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- spin_unlock(&req_q->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
@@ -438,7 +438,7 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
}
req_q->first = 0;
atomic_set(&req_q->count, 0);
- req_q->pci_batch = 0;
+ adapter->req_q_pci_batch = 0;
adapter->resp_q.first = 0;
atomic_set(&adapter->resp_q.count, 0);
}
@@ -450,23 +450,17 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
*/
int zfcp_qdio_open(struct zfcp_adapter *adapter)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int cc;
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
return -EIO;
- if (qdio_establish(&adapter->qdio_init_data)) {
- dev_err(&adapter->ccw_device->dev,
- "Establish of QDIO queues failed.\n");
- return -EIO;
- }
+ if (qdio_establish(&adapter->qdio_init_data))
+ goto failed_establish;
- if (qdio_activate(adapter->ccw_device)) {
- dev_err(&adapter->ccw_device->dev,
- "Activate of QDIO queues failed.\n");
+ if (qdio_activate(adapter->ccw_device))
goto failed_qdio;
- }
for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
sbale = &(adapter->resp_q.sbal[cc]->element[0]);
@@ -476,20 +470,20 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter)
}
if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
- QDIO_MAX_BUFFERS_PER_Q)) {
- dev_err(&adapter->ccw_device->dev,
- "Init of QDIO response queue failed.\n");
+ QDIO_MAX_BUFFERS_PER_Q))
goto failed_qdio;
- }
/* set index of first avalable SBALS / number of available SBALS */
adapter->req_q.first = 0;
atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
- adapter->req_q.pci_batch = 0;
+ adapter->req_q_pci_batch = 0;
return 0;
failed_qdio:
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+failed_establish:
+ dev_err(&adapter->ccw_device->dev,
+ "Setting up the QDIO connection to the FCP adapter failed\n");
return -EIO;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index aeae56b00b4..ca8f85f3dad 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -21,20 +21,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
return fcp_sns_info_ptr;
}
-void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl)
-{
- fcp_dl_t *fcp_dl_ptr;
-
- /*
- * fcp_dl_addr = start address of fcp_cmnd structure +
- * size of fixed part + size of dynamically sized add_dcp_cdb field
- * SEE FCP-2 documentation
- */
- fcp_dl_ptr = (fcp_dl_t *) ((unsigned char *) &fcp_cmd[1] +
- (fcp_cmd->add_fcp_cdb_length << 2));
- *fcp_dl_ptr = fcp_dl;
-}
-
static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
{
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
@@ -119,13 +105,17 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
{
struct zfcp_port *port;
struct zfcp_unit *unit;
+ int scsi_lun;
list_for_each_entry(port, &adapter->port_list_head, list) {
if (!port->rport || (id != port->rport->scsi_target_id))
continue;
- list_for_each_entry(unit, &port->unit_list_head, list)
- if (lun == unit->scsi_lun)
+ list_for_each_entry(unit, &port->unit_list_head, list) {
+ scsi_lun = scsilun_to_int(
+ (struct scsi_lun *)&unit->fcp_lun);
+ if (lun == scsi_lun)
return unit;
+ }
}
return NULL;
@@ -183,7 +173,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
return retval;
}
fsf_req->data = NULL;
- fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
/* don't access old fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
@@ -294,7 +283,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
sizeof (struct zfcp_adapter *));
if (!adapter->scsi_host) {
dev_err(&adapter->ccw_device->dev,
- "registration with SCSI stack failed.");
+ "Registering the FCP device with the "
+ "SCSI stack failed\n");
return -EIO;
}
@@ -312,7 +302,6 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
scsi_host_put(adapter->scsi_host);
return -EIO;
}
- atomic_set_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return 0;
}
@@ -336,7 +325,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return;
}
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 2e85c6c49e7..ca9293ba176 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -26,9 +26,9 @@ static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n",
atomic_read(&adapter->status));
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n",
- adapter->peer_wwnn);
+ (unsigned long long) adapter->peer_wwnn);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n",
- adapter->peer_wwpn);
+ (unsigned long long) adapter->peer_wwpn);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n",
adapter->peer_d_id);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n",
@@ -135,8 +135,9 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
{
struct zfcp_adapter *adapter = dev_get_drvdata(dev);
struct zfcp_port *port;
- wwn_t wwpn;
+ u64 wwpn;
int retval = 0;
+ LIST_HEAD(port_remove_lh);
down(&zfcp_data.config_sema);
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
@@ -144,7 +145,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &wwpn)) {
+ if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) {
retval = -EINVAL;
goto out;
}
@@ -154,7 +155,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
if (port && (atomic_read(&port->refcount) == 0)) {
zfcp_port_get(port);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
- list_move(&port->list, &adapter->port_remove_lh);
+ list_move(&port->list, &port_remove_lh);
} else
port = NULL;
write_unlock_irq(&zfcp_data.config_lock);
@@ -200,7 +201,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
{
struct zfcp_port *port = dev_get_drvdata(dev);
struct zfcp_unit *unit;
- fcp_lun_t fcp_lun;
+ u64 fcp_lun;
int retval = -EINVAL;
down(&zfcp_data.config_sema);
@@ -209,7 +210,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &fcp_lun))
+ if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
goto out;
unit = zfcp_unit_enqueue(port, fcp_lun);
@@ -233,8 +234,9 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
{
struct zfcp_port *port = dev_get_drvdata(dev);
struct zfcp_unit *unit;
- fcp_lun_t fcp_lun;
+ u64 fcp_lun;
int retval = 0;
+ LIST_HEAD(unit_remove_lh);
down(&zfcp_data.config_sema);
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
@@ -242,7 +244,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &fcp_lun)) {
+ if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
retval = -EINVAL;
goto out;
}
@@ -252,7 +254,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
if (unit && (atomic_read(&unit->refcount) == 0)) {
zfcp_unit_get(unit);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
- list_move(&unit->list, &port->unit_remove_lh);
+ list_move(&unit->list, &unit_remove_lh);
} else
unit = NULL;
@@ -273,22 +275,7 @@ out:
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
-static struct attribute *zfcp_port_ns_attrs[] = {
- &dev_attr_port_failed.attr,
- &dev_attr_port_in_recovery.attr,
- &dev_attr_port_status.attr,
- &dev_attr_port_access_denied.attr,
- NULL
-};
-
-/**
- * zfcp_sysfs_ns_port_attrs - sysfs attributes for nameserver
- */
-struct attribute_group zfcp_sysfs_ns_port_attrs = {
- .attrs = zfcp_port_ns_attrs,
-};
-
-static struct attribute *zfcp_port_no_ns_attrs[] = {
+static struct attribute *zfcp_port_attrs[] = {
&dev_attr_unit_add.attr,
&dev_attr_unit_remove.attr,
&dev_attr_port_failed.attr,
@@ -302,7 +289,7 @@ static struct attribute *zfcp_port_no_ns_attrs[] = {
* zfcp_sysfs_port_attrs - sysfs attributes for all other ports
*/
struct attribute_group zfcp_sysfs_port_attrs = {
- .attrs = zfcp_port_no_ns_attrs,
+ .attrs = zfcp_port_attrs,
};
static struct attribute *zfcp_unit_attrs[] = {
@@ -394,9 +381,11 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
- unit->port->adapter->ccw_device->dev.bus_id);
-ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
-ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
+ dev_name(&unit->port->adapter->ccw_device->dev));
+ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
+ (unsigned long long) unit->port->wwpn);
+ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
+ (unsigned long long) unit->fcp_lun);
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
@@ -487,10 +476,23 @@ ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n",
ZFCP_SHOST_ATTR(seconds_active, "%llu\n",
(unsigned long long) stat_info.seconds_act);
+static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *scsi_host = class_to_shost(dev);
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *) scsi_host->hostdata[0];
+
+ return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full));
+}
+static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
+
struct device_attribute *zfcp_sysfs_shost_attrs[] = {
&dev_attr_utilization,
&dev_attr_requests,
&dev_attr_megabytes,
&dev_attr_seconds_active,
+ &dev_attr_queue_full,
NULL
};
diff --git a/drivers/sbus/Makefile b/drivers/sbus/Makefile
index 7b1d24d9530..e94dc25805f 100644
--- a/drivers/sbus/Makefile
+++ b/drivers/sbus/Makefile
@@ -2,8 +2,4 @@
# Makefile for the linux kernel.
#
-ifneq ($(ARCH),m68k)
-obj-y := sbus.o dvma.o
-endif
-
obj-$(CONFIG_SBUSCHAR) += char/
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig
index 400c65bfb8c..73cde85d04d 100644
--- a/drivers/sbus/char/Kconfig
+++ b/drivers/sbus/char/Kconfig
@@ -13,16 +13,6 @@ config SUN_OPENPROMIO
If unsure, say Y.
-config SUN_MOSTEK_RTC
- tristate "Mostek real time clock support"
- depends on SPARC32
- help
- The Mostek RTC chip is used on all known Sun computers except
- some JavaStations. For a JavaStation you need to say Y both here
- and to "Enhanced Real Time Clock Support".
-
- Say Y here unless you are building a special purpose kernel.
-
config OBP_FLASH
tristate "OBP Flash Device support"
depends on SPARC64
@@ -30,26 +20,9 @@ config OBP_FLASH
The OpenBoot PROM on Ultra systems is flashable. If you want to be
able to upgrade the OBP firmware, say Y here.
-config SUN_BPP
- tristate "Bidirectional parallel port support (OBSOLETE)"
- depends on EXPERIMENTAL
- help
- Say Y here to support Sun's obsolete variant of IEEE1284
- bidirectional parallel port protocol as /dev/bppX. Can be built on
- x86 machines.
-
-config SUN_VIDEOPIX
- tristate "Videopix Frame Grabber (EXPERIMENTAL)"
- depends on EXPERIMENTAL && (BROKEN || !64BIT)
- help
- Say Y here to support the Videopix Frame Grabber from Sun
- Microsystems, commonly found on SPARCstations. This card, which is
- based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and
- SVIDEO signals.
-
config TADPOLE_TS102_UCTRL
tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SPARC32
+ depends on EXPERIMENTAL
help
Say Y here to directly support the TS102 Microcontroller interface
on the Tadpole Sparcbook 3. This device handles power-management
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile
index 7ab060e9a5f..78b6183c986 100644
--- a/drivers/sbus/char/Makefile
+++ b/drivers/sbus/char/Makefile
@@ -7,18 +7,12 @@
# Rewritten to use lists instead of if-statements.
#
-vfc-objs := vfc_dev.o vfc_i2c.o
bbc-objs := bbc_i2c.o bbc_envctrl.o
obj-$(CONFIG_ENVCTRL) += envctrl.o
obj-$(CONFIG_DISPLAY7SEG) += display7seg.o
-obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwatchdog.o
-obj-$(CONFIG_WATCHDOG_RIO) += riowatchdog.o
obj-$(CONFIG_OBP_FLASH) += flash.o
obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o
-obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o
-obj-$(CONFIG_SUN_BPP) += bpp.o
-obj-$(CONFIG_SUN_VIDEOPIX) += vfc.o
obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o
obj-$(CONFIG_SUN_JSFLASH) += jsflash.o
obj-$(CONFIG_BBC_I2C) += bbc.o
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 0bde26989a2..15dab96d05e 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -1,15 +1,15 @@
-/* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $
- * bbc_envctrl.c: UltraSPARC-III environment control driver.
+/* bbc_envctrl.c: UltraSPARC-III environment control driver.
*
- * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/kmod.h>
#include <linux/reboot.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/oplib.h>
-#include <asm/ebus.h>
#include "bbc_i2c.h"
#include "max1617.h"
@@ -75,43 +75,8 @@ static struct temp_limits amb_temp_limits[2] = {
{ 65, 55, 40, 5, -5, -10 },
};
-enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX };
-
-struct bbc_cpu_temperature {
- struct bbc_cpu_temperature *next;
-
- struct bbc_i2c_client *client;
- int index;
-
- /* Current readings, and history. */
- s8 curr_cpu_temp;
- s8 curr_amb_temp;
- s8 prev_cpu_temp;
- s8 prev_amb_temp;
- s8 avg_cpu_temp;
- s8 avg_amb_temp;
-
- int sample_tick;
-
- enum fan_action fan_todo[2];
-#define FAN_AMBIENT 0
-#define FAN_CPU 1
-};
-
-struct bbc_cpu_temperature *all_bbc_temps;
-
-struct bbc_fan_control {
- struct bbc_fan_control *next;
-
- struct bbc_i2c_client *client;
- int index;
-
- int psupply_fan_on;
- int cpu_fan_speed;
- int system_fan_speed;
-};
-
-struct bbc_fan_control *all_bbc_fans;
+static LIST_HEAD(all_temps);
+static LIST_HEAD(all_fans);
#define CPU_FAN_REG 0xf0
#define SYS_FAN_REG 0xf2
@@ -330,7 +295,7 @@ static enum fan_action prioritize_fan_action(int which_fan)
* recommend we do, and perform that action on all the
* fans.
*/
- for (tp = all_bbc_temps; tp; tp = tp->next) {
+ list_for_each_entry(tp, &all_temps, glob_list) {
if (tp->fan_todo[which_fan] == FAN_FULLBLAST) {
decision = FAN_FULLBLAST;
break;
@@ -439,7 +404,7 @@ static void fans_full_blast(void)
/* Since we will not be monitoring things anymore, put
* the fans on full blast.
*/
- for (fp = all_bbc_fans; fp; fp = fp->next) {
+ list_for_each_entry(fp, &all_fans, glob_list) {
fp->cpu_fan_speed = FAN_SPEED_MAX;
fp->system_fan_speed = FAN_SPEED_MAX;
fp->psupply_fan_on = 1;
@@ -463,11 +428,11 @@ static int kenvctrld(void *__unused)
if (kthread_should_stop())
break;
- for (tp = all_bbc_temps; tp; tp = tp->next) {
+ list_for_each_entry(tp, &all_temps, glob_list) {
get_current_temps(tp);
analyze_temps(tp, &last_warning_jiffies);
}
- for (fp = all_bbc_fans; fp; fp = fp->next)
+ list_for_each_entry(fp, &all_fans, glob_list)
maybe_new_fan_speeds(fp);
}
printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n");
@@ -477,7 +442,8 @@ static int kenvctrld(void *__unused)
return 0;
}
-static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
+static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op,
+ int temp_idx)
{
struct bbc_cpu_temperature *tp;
@@ -485,20 +451,17 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
if (!tp)
return;
- tp->client = bbc_i2c_attach(echild);
+ tp->client = bbc_i2c_attach(bp, op);
if (!tp->client) {
kfree(tp);
return;
}
+
tp->index = temp_idx;
- {
- struct bbc_cpu_temperature **tpp = &all_bbc_temps;
- while (*tpp)
- tpp = &((*tpp)->next);
- tp->next = NULL;
- *tpp = tp;
- }
+
+ list_add(&tp->glob_list, &all_temps);
+ list_add(&tp->bp_list, &bp->temps);
/* Tell it to convert once every 5 seconds, clear all cfg
* bits.
@@ -524,7 +487,8 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx)
tp->fan_todo[FAN_CPU] = FAN_SAME;
}
-static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
+static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
+ int fan_idx)
{
struct bbc_fan_control *fp;
@@ -532,7 +496,7 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
if (!fp)
return;
- fp->client = bbc_i2c_attach(echild);
+ fp->client = bbc_i2c_attach(bp, op);
if (!fp->client) {
kfree(fp);
return;
@@ -540,13 +504,8 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
fp->index = fan_idx;
- {
- struct bbc_fan_control **fpp = &all_bbc_fans;
- while (*fpp)
- fpp = &((*fpp)->next);
- fp->next = NULL;
- *fpp = fp;
- }
+ list_add(&fp->glob_list, &all_fans);
+ list_add(&fp->bp_list, &bp->fans);
/* The i2c device controlling the fans is write-only.
* So the only way to keep track of the current power
@@ -563,18 +522,18 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx)
set_fan_speeds(fp);
}
-int bbc_envctrl_init(void)
+int bbc_envctrl_init(struct bbc_i2c_bus *bp)
{
- struct linux_ebus_child *echild;
+ struct of_device *op;
int temp_index = 0;
int fan_index = 0;
int devidx = 0;
- while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
- if (!strcmp(echild->prom_node->name, "temperature"))
- attach_one_temp(echild, temp_index++);
- if (!strcmp(echild->prom_node->name, "fan-control"))
- attach_one_fan(echild, fan_index++);
+ while ((op = bbc_i2c_getdev(bp, devidx++)) != NULL) {
+ if (!strcmp(op->node->name, "temperature"))
+ attach_one_temp(bp, op, temp_index++);
+ if (!strcmp(op->node->name, "fan-control"))
+ attach_one_fan(bp, op, fan_index++);
}
if (temp_index != 0 && fan_index != 0) {
kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
@@ -597,26 +556,22 @@ static void destroy_one_fan(struct bbc_fan_control *fp)
kfree(fp);
}
-void bbc_envctrl_cleanup(void)
+void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
{
- struct bbc_cpu_temperature *tp;
- struct bbc_fan_control *fp;
+ struct bbc_cpu_temperature *tp, *tpos;
+ struct bbc_fan_control *fp, *fpos;
kthread_stop(kenvctrld_task);
- tp = all_bbc_temps;
- while (tp != NULL) {
- struct bbc_cpu_temperature *next = tp->next;
+ list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
+ list_del(&tp->bp_list);
+ list_del(&tp->glob_list);
destroy_one_temp(tp);
- tp = next;
}
- all_bbc_temps = NULL;
- fp = all_bbc_fans;
- while (fp != NULL) {
- struct bbc_fan_control *next = fp->next;
+ list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
+ list_del(&fp->bp_list);
+ list_del(&fp->glob_list);
destroy_one_fan(fp);
- fp = next;
}
- all_bbc_fans = NULL;
}
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index ac8ef2ce07f..f08e169ba1b 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -1,8 +1,7 @@
-/* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $
- * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
+/* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
* platforms.
*
- * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -14,9 +13,8 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/oplib.h>
-#include <asm/ebus.h>
-#include <asm/spitfire.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/bbc.h>
#include <asm/io.h>
@@ -53,54 +51,12 @@
* The second controller also connects to the smartcard reader, if present.
*/
-#define NUM_CHILDREN 8
-struct bbc_i2c_bus {
- struct bbc_i2c_bus *next;
- int index;
- spinlock_t lock;
- void __iomem *i2c_bussel_reg;
- void __iomem *i2c_control_regs;
- unsigned char own, clock;
-
- wait_queue_head_t wq;
- volatile int waiting;
-
- struct linux_ebus_device *bus_edev;
- struct {
- struct linux_ebus_child *device;
- int client_claimed;
- } devs[NUM_CHILDREN];
-};
-
-static struct bbc_i2c_bus *all_bbc_i2c;
-
-struct bbc_i2c_client {
- struct bbc_i2c_bus *bp;
- struct linux_ebus_child *echild;
- int bus;
- int address;
-};
-
-static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild)
+static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val)
{
int i;
for (i = 0; i < NUM_CHILDREN; i++) {
- if (bp->devs[i].device == echild) {
- if (bp->devs[i].client_claimed)
- return 0;
- return 1;
- }
- }
- return 0;
-}
-
-static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val)
-{
- int i;
-
- for (i = 0; i < NUM_CHILDREN; i++) {
- if (bp->devs[i].device == echild) {
+ if (bp->devs[i].device == op) {
bp->devs[i].client_claimed = val;
return;
}
@@ -110,61 +66,47 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child
#define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1)
#define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0)
-static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild)
+struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index)
{
- struct bbc_i2c_bus *bp = all_bbc_i2c;
+ struct of_device *op = NULL;
+ int curidx = 0, i;
- while (bp != NULL) {
- if (find_device(bp, echild) != 0)
+ for (i = 0; i < NUM_CHILDREN; i++) {
+ if (!(op = bp->devs[i].device))
break;
- bp = bp->next;
+ if (curidx == index)
+ goto out;
+ op = NULL;
+ curidx++;
}
- return bp;
-}
-
-struct linux_ebus_child *bbc_i2c_getdev(int index)
-{
- struct bbc_i2c_bus *bp = all_bbc_i2c;
- struct linux_ebus_child *echild = NULL;
- int curidx = 0;
-
- while (bp != NULL) {
- struct bbc_i2c_bus *next = bp->next;
- int i;
-
- for (i = 0; i < NUM_CHILDREN; i++) {
- if (!(echild = bp->devs[i].device))
- break;
- if (curidx == index)
- goto out;
- echild = NULL;
- curidx++;
- }
- bp = next;
- }
out:
if (curidx == index)
- return echild;
+ return op;
return NULL;
}
-struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild)
+struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op)
{
- struct bbc_i2c_bus *bp = find_bus_for_device(echild);
struct bbc_i2c_client *client;
+ const u32 *reg;
- if (!bp)
- return NULL;
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return NULL;
client->bp = bp;
- client->echild = echild;
- client->bus = echild->resource[0].start;
- client->address = echild->resource[1].start;
+ client->op = op;
+
+ reg = of_get_property(op->node, "reg", NULL);
+ if (!reg) {
+ kfree(client);
+ return NULL;
+ }
- claim_device(bp, echild);
+ client->bus = reg[0];
+ client->address = reg[1];
+
+ claim_device(bp, op);
return client;
}
@@ -172,9 +114,9 @@ struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild)
void bbc_i2c_detach(struct bbc_i2c_client *client)
{
struct bbc_i2c_bus *bp = client->bp;
- struct linux_ebus_child *echild = client->echild;
+ struct of_device *op = client->op;
- release_device(bp, echild);
+ release_device(bp, op);
kfree(client);
}
@@ -355,44 +297,43 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
}
-static int __init attach_one_i2c(struct linux_ebus_device *edev, int index)
+static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index)
{
struct bbc_i2c_bus *bp;
- struct linux_ebus_child *echild;
+ struct device_node *dp;
int entry;
bp = kzalloc(sizeof(*bp), GFP_KERNEL);
if (!bp)
- return -ENOMEM;
+ return NULL;
- bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2);
+ bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
if (!bp->i2c_control_regs)
goto fail;
- if (edev->num_addrs == 2) {
- bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1);
- if (!bp->i2c_bussel_reg)
- goto fail;
- }
+ bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
+ if (!bp->i2c_bussel_reg)
+ goto fail;
bp->waiting = 0;
init_waitqueue_head(&bp->wq);
- if (request_irq(edev->irqs[0], bbc_i2c_interrupt,
+ if (request_irq(op->irqs[0], bbc_i2c_interrupt,
IRQF_SHARED, "bbc_i2c", bp))
goto fail;
bp->index = index;
- bp->bus_edev = edev;
+ bp->op = op;
spin_lock_init(&bp->lock);
- bp->next = all_bbc_i2c;
- all_bbc_i2c = bp;
entry = 0;
- for (echild = edev->children;
- echild && entry < 8;
- echild = echild->next, entry++) {
- bp->devs[entry].device = echild;
+ for (dp = op->node->child;
+ dp && entry < 8;
+ dp = dp->sibling, entry++) {
+ struct of_device *child_op;
+
+ child_op = of_find_device_by_node(dp);
+ bp->devs[entry].device = child_op;
bp->devs[entry].client_claimed = 0;
}
@@ -406,86 +347,90 @@ static int __init attach_one_i2c(struct linux_ebus_device *edev, int index)
reset_one_i2c(bp);
- return 0;
+ return bp;
fail:
if (bp->i2c_bussel_reg)
- iounmap(bp->i2c_bussel_reg);
+ of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1);
if (bp->i2c_control_regs)
- iounmap(bp->i2c_control_regs);
+ of_iounmap(&op->resource[0], bp->i2c_control_regs, 2);
kfree(bp);
- return -EINVAL;
-}
-
-static int __init bbc_present(void)
-{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "bbc"))
- return 1;
- }
- }
- return 0;
+ return NULL;
}
-extern int bbc_envctrl_init(void);
-extern void bbc_envctrl_cleanup(void);
-static void bbc_i2c_cleanup(void);
+extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
+extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
-static int __init bbc_i2c_init(void)
+static int __devinit bbc_i2c_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
+ struct bbc_i2c_bus *bp;
int err, index = 0;
- if ((tlb_type != cheetah && tlb_type != cheetah_plus) ||
- !bbc_present())
- return -ENODEV;
+ bp = attach_one_i2c(op, index);
+ if (!bp)
+ return -EINVAL;
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "i2c")) {
- if (!attach_one_i2c(edev, index))
- index++;
- }
- }
+ err = bbc_envctrl_init(bp);
+ if (err) {
+ free_irq(op->irqs[0], bp);
+ if (bp->i2c_bussel_reg)
+ of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
+ if (bp->i2c_control_regs)
+ of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
+ kfree(bp);
+ } else {
+ dev_set_drvdata(&op->dev, bp);
}
- if (!index)
- return -ENODEV;
-
- err = bbc_envctrl_init();
- if (err)
- bbc_i2c_cleanup();
return err;
}
-static void bbc_i2c_cleanup(void)
+static int __devexit bbc_i2c_remove(struct of_device *op)
{
- struct bbc_i2c_bus *bp = all_bbc_i2c;
+ struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev);
+
+ bbc_envctrl_cleanup(bp);
+
+ free_irq(op->irqs[0], bp);
- bbc_envctrl_cleanup();
+ if (bp->i2c_bussel_reg)
+ of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1);
+ if (bp->i2c_control_regs)
+ of_iounmap(&op->resource[1], bp->i2c_control_regs, 2);
- while (bp != NULL) {
- struct bbc_i2c_bus *next = bp->next;
+ kfree(bp);
- free_irq(bp->bus_edev->irqs[0], bp);
+ return 0;
+}
- if (bp->i2c_bussel_reg)
- iounmap(bp->i2c_bussel_reg);
- if (bp->i2c_control_regs)
- iounmap(bp->i2c_control_regs);
+static const struct of_device_id bbc_i2c_match[] = {
+ {
+ .name = "i2c",
+ .compatible = "SUNW,bbc-i2c",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bbc_i2c_match);
- kfree(bp);
+static struct of_platform_driver bbc_i2c_driver = {
+ .name = "bbc_i2c",
+ .match_table = bbc_i2c_match,
+ .probe = bbc_i2c_probe,
+ .remove = __devexit_p(bbc_i2c_remove),
+};
- bp = next;
- }
- all_bbc_i2c = NULL;
+static int __init bbc_i2c_init(void)
+{
+ return of_register_driver(&bbc_i2c_driver, &of_bus_type);
+}
+
+static void __exit bbc_i2c_exit(void)
+{
+ of_unregister_driver(&bbc_i2c_driver);
}
module_init(bbc_i2c_init);
-module_exit(bbc_i2c_cleanup);
+module_exit(bbc_i2c_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h
index fb01bd17704..83c4811b7b5 100644
--- a/drivers/sbus/char/bbc_i2c.h
+++ b/drivers/sbus/char/bbc_i2c.h
@@ -1,14 +1,79 @@
-/* $Id: bbc_i2c.h,v 1.2 2001/04/02 09:59:25 davem Exp $ */
#ifndef _BBC_I2C_H
#define _BBC_I2C_H
-#include <asm/ebus.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/list.h>
-struct bbc_i2c_client;
+struct bbc_i2c_client {
+ struct bbc_i2c_bus *bp;
+ struct of_device *op;
+ int bus;
+ int address;
+};
+
+enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX };
+
+struct bbc_cpu_temperature {
+ struct list_head bp_list;
+ struct list_head glob_list;
+
+ struct bbc_i2c_client *client;
+ int index;
+
+ /* Current readings, and history. */
+ s8 curr_cpu_temp;
+ s8 curr_amb_temp;
+ s8 prev_cpu_temp;
+ s8 prev_amb_temp;
+ s8 avg_cpu_temp;
+ s8 avg_amb_temp;
+
+ int sample_tick;
+
+ enum fan_action fan_todo[2];
+#define FAN_AMBIENT 0
+#define FAN_CPU 1
+};
+
+struct bbc_fan_control {
+ struct list_head bp_list;
+ struct list_head glob_list;
+
+ struct bbc_i2c_client *client;
+ int index;
+
+ int psupply_fan_on;
+ int cpu_fan_speed;
+ int system_fan_speed;
+};
+
+#define NUM_CHILDREN 8
+
+struct bbc_i2c_bus {
+ struct bbc_i2c_bus *next;
+ int index;
+ spinlock_t lock;
+ void __iomem *i2c_bussel_reg;
+ void __iomem *i2c_control_regs;
+ unsigned char own, clock;
+
+ wait_queue_head_t wq;
+ volatile int waiting;
+
+ struct list_head temps;
+ struct list_head fans;
+
+ struct of_device *op;
+ struct {
+ struct of_device *device;
+ int client_claimed;
+ } devs[NUM_CHILDREN];
+};
/* Probing and attachment. */
-extern struct linux_ebus_child *bbc_i2c_getdev(int);
-extern struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *);
+extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int);
+extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *);
extern void bbc_i2c_detach(struct bbc_i2c_client *);
/* Register read/write. NOTE: Blocking! */
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
deleted file mode 100644
index bba21e053a1..00000000000
--- a/drivers/sbus/char/bpp.c
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
- * drivers/sbus/char/bpp.c
- *
- * Copyright (c) 1995 Picture Elements
- * Stephen Williams (steve@icarus.com)
- * Gus Baldauf (gbaldauf@ix.netcom.com)
- *
- * Linux/SPARC port by Peter Zaitcev.
- * Integration into SPARC tree by Tom Dyas.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/smp_lock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#if defined(__i386__)
-# include <asm/system.h>
-#endif
-
-#if defined(__sparc__)
-# include <linux/init.h>
-# include <linux/delay.h> /* udelay() */
-
-# include <asm/oplib.h> /* OpenProm Library */
-# include <asm/sbus.h>
-#endif
-
-#include <asm/bpp.h>
-
-#define BPP_PROBE_CODE 0x55
-#define BPP_DELAY 100
-
-static const unsigned BPP_MAJOR = LP_MAJOR;
-static const char *bpp_dev_name = "bpp";
-
-/* When switching from compatibility to a mode where I can read, try
- the following mode first. */
-
-/* const unsigned char DEFAULT_ECP = 0x10; */
-static const unsigned char DEFAULT_ECP = 0x30;
-static const unsigned char DEFAULT_NIBBLE = 0x00;
-
-/*
- * These are 1284 time constraints, in units of jiffies.
- */
-
-static const unsigned long TIME_PSetup = 1;
-static const unsigned long TIME_PResponse = 6;
-static const unsigned long TIME_IDLE_LIMIT = 2000;
-
-/*
- * One instance per supported subdevice...
- */
-# define BPP_NO 3
-
-enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP };
-
-struct inst {
- unsigned present : 1; /* True if the hardware exists */
- unsigned enhanced : 1; /* True if the hardware in "enhanced" */
- unsigned opened : 1; /* True if the device is opened already */
- unsigned run_flag : 1; /* True if waiting for a repeate byte */
-
- unsigned char direction; /* 0 --> out, 0x20 --> IN */
- unsigned char pp_state; /* State of host controlled pins. */
- enum IEEE_Mode mode;
-
- unsigned char run_length;
- unsigned char repeat_byte;
-};
-
-static struct inst instances[BPP_NO];
-
-#if defined(__i386__)
-
-static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc };
-
-/*
- * These are for data access.
- * Control lines accesses are hidden in set_bits() and get_bits().
- * The exception is the probe procedure, which is system-dependent.
- */
-#define bpp_outb_p(data, base) outb_p((data), (base))
-#define bpp_inb(base) inb(base)
-#define bpp_inb_p(base) inb_p(base)
-
-/*
- * This method takes the pin values mask and sets the hardware pins to
- * the requested value: 1 == high voltage, 0 == low voltage. This
- * burries the annoying PC bit inversion and preserves the direction
- * flag.
- */
-static void set_pins(unsigned short pins, unsigned minor)
-{
- unsigned char bits = instances[minor].direction; /* == 0x20 */
-
- if (! (pins & BPP_PP_nStrobe)) bits |= 1;
- if (! (pins & BPP_PP_nAutoFd)) bits |= 2;
- if ( pins & BPP_PP_nInit) bits |= 4;
- if (! (pins & BPP_PP_nSelectIn)) bits |= 8;
-
- instances[minor].pp_state = bits;
-
- outb_p(bits, base_addrs[minor]+2);
-}
-
-static unsigned short get_pins(unsigned minor)
-{
- unsigned short bits = 0;
-
- unsigned value = instances[minor].pp_state;
- if (! (value & 0x01)) bits |= BPP_PP_nStrobe;
- if (! (value & 0x02)) bits |= BPP_PP_nAutoFd;
- if (value & 0x04) bits |= BPP_PP_nInit;
- if (! (value & 0x08)) bits |= BPP_PP_nSelectIn;
-
- value = inb_p(base_addrs[minor]+1);
- if (value & 0x08) bits |= BPP_GP_nFault;
- if (value & 0x10) bits |= BPP_GP_Select;
- if (value & 0x20) bits |= BPP_GP_PError;
- if (value & 0x40) bits |= BPP_GP_nAck;
- if (! (value & 0x80)) bits |= BPP_GP_Busy;
-
- return bits;
-}
-
-#endif /* __i386__ */
-
-#if defined(__sparc__)
-
-/*
- * Register block
- */
- /* DMA registers */
-#define BPP_CSR 0x00
-#define BPP_ADDR 0x04
-#define BPP_BCNT 0x08
-#define BPP_TST_CSR 0x0C
- /* Parallel Port registers */
-#define BPP_HCR 0x10
-#define BPP_OCR 0x12
-#define BPP_DR 0x14
-#define BPP_TCR 0x15
-#define BPP_OR 0x16
-#define BPP_IR 0x17
-#define BPP_ICR 0x18
-#define BPP_SIZE 0x1A
-
-/* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */
-#define P_DEV_ID_MASK 0xf0000000 /* R */
-#define P_DEV_ID_ZEBRA 0x40000000
-#define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */
-#define P_NA_LOADED 0x08000000 /* R NA wirtten but was not used */
-#define P_A_LOADED 0x04000000 /* R */
-#define P_DMA_ON 0x02000000 /* R DMA is not disabled */
-#define P_EN_NEXT 0x01000000 /* RW */
-#define P_TCI_DIS 0x00800000 /* RW TCI forbidden from interrupts */
-#define P_DIAG 0x00100000 /* RW Disables draining and resetting
- of P-FIFO on loading of P_ADDR*/
-#define P_BURST_SIZE 0x000c0000 /* RW SBus burst size */
-#define P_BURST_8 0x00000000
-#define P_BURST_4 0x00040000
-#define P_BURST_1 0x00080000 /* "No burst" write */
-#define P_TC 0x00004000 /* RW1 Term Count, can be cleared when
- P_EN_NEXT=1 */
-#define P_EN_CNT 0x00002000 /* RW */
-#define P_EN_DMA 0x00000200 /* RW */
-#define P_WRITE 0x00000100 /* R DMA dir, 1=to ram, 0=to port */
-#define P_RESET 0x00000080 /* RW */
-#define P_SLAVE_ERR 0x00000040 /* RW1 Access size error */
-#define P_INVALIDATE 0x00000020 /* W Drop P-FIFO */
-#define P_INT_EN 0x00000010 /* RW OK to P_INT_PEND||P_ERR_PEND */
-#define P_DRAINING 0x0000000c /* R P-FIFO is draining to memory */
-#define P_ERR_PEND 0x00000002 /* R */
-#define P_INT_PEND 0x00000001 /* R */
-
-/* BPP_HCR. Time is in increments of SBus clock. */
-#define P_HCR_TEST 0x8000 /* Allows buried counters to be read */
-#define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */
-#define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */
-
-/* BPP_OCR. */
-#define P_OCR_MEM_CLR 0x8000
-#define P_OCR_DATA_SRC 0x4000 /* ) */
-#define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */
-#define P_OCR_BUSY_DSEL 0x1000 /* ) selects */
-#define P_OCR_ACK_DSEL 0x0800 /* ) */
-#define P_OCR_EN_DIAG 0x0400
-#define P_OCR_BUSY_OP 0x0200 /* Busy operation */
-#define P_OCR_ACK_OP 0x0100 /* Ack operation */
-#define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */
-#define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */
-#define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */
-#define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */
-
-/* BPP_TCR */
-#define P_TCR_DIR 0x08
-#define P_TCR_BUSY 0x04
-#define P_TCR_ACK 0x02
-#define P_TCR_DS 0x01 /* Strobe */
-
-/* BPP_OR */
-#define P_OR_V3 0x20 /* ) */
-#define P_OR_V2 0x10 /* ) on Zebra only */
-#define P_OR_V1 0x08 /* ) */
-#define P_OR_INIT 0x04
-#define P_OR_AFXN 0x02 /* Auto Feed */
-#define P_OR_SLCT_IN 0x01
-
-/* BPP_IR */
-#define P_IR_PE 0x04
-#define P_IR_SLCT 0x02
-#define P_IR_ERR 0x01
-
-/* BPP_ICR */
-#define P_DS_IRQ 0x8000 /* RW1 */
-#define P_ACK_IRQ 0x4000 /* RW1 */
-#define P_BUSY_IRQ 0x2000 /* RW1 */
-#define P_PE_IRQ 0x1000 /* RW1 */
-#define P_SLCT_IRQ 0x0800 /* RW1 */
-#define P_ERR_IRQ 0x0400 /* RW1 */
-#define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */
-#define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */
-#define P_BUSY_IRP 0x0080 /* RW 1= rising edge */
-#define P_BUSY_IRQ_EN 0x0040 /* RW */
-#define P_PE_IRP 0x0020 /* RW 1= rising edge */
-#define P_PE_IRQ_EN 0x0010 /* RW */
-#define P_SLCT_IRP 0x0008 /* RW 1= rising edge */
-#define P_SLCT_IRQ_EN 0x0004 /* RW */
-#define P_ERR_IRP 0x0002 /* RW1 1= rising edge */
-#define P_ERR_IRQ_EN 0x0001 /* RW */
-
-static void __iomem *base_addrs[BPP_NO];
-
-#define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR)
-#define bpp_inb_p(base) sbus_readb((base) + BPP_DR)
-#define bpp_inb(base) sbus_readb((base) + BPP_DR)
-
-static void set_pins(unsigned short pins, unsigned minor)
-{
- void __iomem *base = base_addrs[minor];
- unsigned char bits_tcr = 0, bits_or = 0;
-
- if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR;
- if ( pins & BPP_PP_nStrobe) bits_tcr |= P_TCR_DS;
-
- if ( pins & BPP_PP_nAutoFd) bits_or |= P_OR_AFXN;
- if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT;
- if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN;
-
- sbus_writeb(bits_or, base + BPP_OR);
- sbus_writeb(bits_tcr, base + BPP_TCR);
-}
-
-/*
- * i386 people read output pins from a software image.
- * We may get them back from hardware.
- * Again, inversion of pins must he buried here.
- */
-static unsigned short get_pins(unsigned minor)
-{
- void __iomem *base = base_addrs[minor];
- unsigned short bits = 0;
- unsigned value_tcr = sbus_readb(base + BPP_TCR);
- unsigned value_ir = sbus_readb(base + BPP_IR);
- unsigned value_or = sbus_readb(base + BPP_OR);
-
- if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe;
- if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd;
- if (! (value_or & P_OR_INIT)) bits |= BPP_PP_nInit;
- if (! (value_or & P_OR_SLCT_IN)) bits |= BPP_PP_nSelectIn;
-
- if (value_ir & P_IR_ERR) bits |= BPP_GP_nFault;
- if (! (value_ir & P_IR_SLCT)) bits |= BPP_GP_Select;
- if (! (value_ir & P_IR_PE)) bits |= BPP_GP_PError;
- if (! (value_tcr & P_TCR_ACK)) bits |= BPP_GP_nAck;
- if (value_tcr & P_TCR_BUSY) bits |= BPP_GP_Busy;
-
- return bits;
-}
-
-#endif /* __sparc__ */
-
-static void snooze(unsigned long snooze_time, unsigned minor)
-{
- schedule_timeout_uninterruptible(snooze_time + 1);
-}
-
-static int wait_for(unsigned short set, unsigned short clr,
- unsigned long delay, unsigned minor)
-{
- unsigned short pins = get_pins(minor);
-
- unsigned long extime = 0;
-
- /*
- * Try a real fast scan for the first jiffy, in case the device
- * responds real good. The first while loop guesses an expire
- * time accounting for possible wraparound of jiffies.
- */
- while (time_after_eq(jiffies, extime)) extime = jiffies + 1;
- while ( (time_before(jiffies, extime))
- && (((pins & set) != set) || ((pins & clr) != 0)) ) {
- pins = get_pins(minor);
- }
-
- delay -= 1;
-
- /*
- * If my delay expired or the pins are still not where I want
- * them, then resort to using the timer and greatly reduce my
- * sample rate. If the peripheral is going to be slow, this will
- * give the CPU up to some more worthy process.
- */
- while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) {
-
- snooze(1, minor);
- pins = get_pins(minor);
- delay -= 1;
- }
-
- if (delay == 0) return -1;
- else return pins;
-}
-
-/*
- * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An
- * errno means something broke, and I do not yet know how to fix it.
- */
-static int negotiate(unsigned char mode, unsigned minor)
-{
- int rc;
- unsigned short pins = get_pins(minor);
- if (pins & BPP_PP_nSelectIn) return -EIO;
-
-
- /* Event 0: Write the mode to the data lines */
- bpp_outb_p(mode, base_addrs[minor]);
-
- snooze(TIME_PSetup, minor);
-
- /* Event 1: Strobe the mode code into the peripheral */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor);
-
- /* Wait for Event 2: Peripheral responds as a 1284 device. */
- rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault,
- BPP_GP_nAck,
- TIME_PResponse,
- minor);
-
- if (rc == -1) return -ETIMEDOUT;
-
- /* Event 3: latch extensibility request */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor);
-
- /* ... quick nap while peripheral ponders the byte i'm sending...*/
- snooze(1, minor);
-
- /* Event 4: restore strobe, to ACK peripheral's response. */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);
-
- /* Wait for Event 6: Peripheral latches response bits */
- rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor);
- if (rc == -1) return -EIO;
-
- /* A 1284 device cannot refuse nibble mode */
- if (mode == DEFAULT_NIBBLE) return 0;
-
- if (pins & BPP_GP_Select) return 0;
-
- return -EPROTONOSUPPORT;
-}
-
-static int terminate(unsigned minor)
-{
- int rc;
-
- /* Event 22: Request termination of 1284 mode */
- set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);
-
- /* Wait for Events 23 and 24: ACK termination request. */
- rc = wait_for(BPP_GP_Busy|BPP_GP_nFault,
- BPP_GP_nAck,
- TIME_PSetup+TIME_PResponse,
- minor);
-
- instances[minor].direction = 0;
- instances[minor].mode = COMPATIBILITY;
-
- if (rc == -1) {
- return -EIO;
- }
-
- /* Event 25: Handshake by lowering nAutoFd */
- set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor);
-
- /* Event 26: Peripheral wiggles lines... */
-
- /* Event 27: Peripheral sets nAck HIGH to ack handshake */
- rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);
- if (rc == -1) {
- set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);
- return -EIO;
- }
-
- /* Event 28: Finish phase by raising nAutoFd */
- set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor);
-
- return 0;
-}
-
-static DEFINE_SPINLOCK(bpp_open_lock);
-
-/*
- * Allow only one process to open the device at a time.
- */
-static int bpp_open(struct inode *inode, struct file *f)
-{
- unsigned minor = iminor(inode);
- int ret;
-
- lock_kernel();
- spin_lock(&bpp_open_lock);
- ret = 0;
- if (minor >= BPP_NO) {
- ret = -ENODEV;
- } else {
- if (! instances[minor].present) {
- ret = -ENODEV;
- } else {
- if (instances[minor].opened)
- ret = -EBUSY;
- else
- instances[minor].opened = 1;
- }
- }
- spin_unlock(&bpp_open_lock);
- unlock_kernel();
-
- return ret;
-}
-
-/*
- * When the process closes the device, this method is called to clean
- * up and reset the hardware. Always leave the device in compatibility
- * mode as this is a reasonable place to clean up from messes made by
- * ioctls, or other mayhem.
- */
-static int bpp_release(struct inode *inode, struct file *f)
-{
- unsigned minor = iminor(inode);
-
- spin_lock(&bpp_open_lock);
- instances[minor].opened = 0;
-
- if (instances[minor].mode != COMPATIBILITY)
- terminate(minor);
-
- spin_unlock(&bpp_open_lock);
-
- return 0;
-}
-
-static long read_nibble(unsigned minor, char __user *c, unsigned long cnt)
-{
- unsigned long remaining = cnt;
- long rc;
-
- while (remaining > 0) {
- unsigned char byte = 0;
- int pins;
-
- /* Event 7: request nibble */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor);
-
- /* Wait for event 9: Peripher strobes first nibble */
- pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor);
- if (pins == -1) return -ETIMEDOUT;
-
- /* Event 10: I handshake nibble */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor);
- if (pins & BPP_GP_nFault) byte |= 0x01;
- if (pins & BPP_GP_Select) byte |= 0x02;
- if (pins & BPP_GP_PError) byte |= 0x04;
- if (pins & BPP_GP_Busy) byte |= 0x08;
-
- /* Wait for event 11: Peripheral handshakes nibble */
- rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);
-
- /* Event 7: request nibble */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor);
-
- /* Wait for event 9: Peripher strobes first nibble */
- pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor);
- if (rc == -1) return -ETIMEDOUT;
-
- /* Event 10: I handshake nibble */
- set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor);
- if (pins & BPP_GP_nFault) byte |= 0x10;
- if (pins & BPP_GP_Select) byte |= 0x20;
- if (pins & BPP_GP_PError) byte |= 0x40;
- if (pins & BPP_GP_Busy) byte |= 0x80;
-
- if (put_user(byte, c))
- return -EFAULT;
- c += 1;
- remaining -= 1;
-
- /* Wait for event 11: Peripheral handshakes nibble */
- rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);
- if (rc == -1) return -EIO;
- }
-
- return cnt - remaining;
-}
-
-static long read_ecp(unsigned minor, char __user *c, unsigned long cnt)
-{
- unsigned long remaining;
- long rc;
-
- /* Turn ECP mode from forward to reverse if needed. */
- if (! instances[minor].direction) {
- unsigned short pins = get_pins(minor);
-
- /* Event 38: Turn the bus around */
- instances[minor].direction = 0x20;
- pins &= ~BPP_PP_nAutoFd;
- set_pins(pins, minor);
-
- /* Event 39: Set pins for reverse mode. */
- snooze(TIME_PSetup, minor);
- set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor);
-
- /* Wait for event 40: Peripheral ready to be strobed */
- rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor);
- if (rc == -1) return -ETIMEDOUT;
- }
-
- remaining = cnt;
-
- while (remaining > 0) {
-
- /* If there is a run length for a repeated byte, repeat */
- /* that byte a few times. */
- if (instances[minor].run_length && !instances[minor].run_flag) {
-
- char buffer[128];
- unsigned idx;
- unsigned repeat = remaining < instances[minor].run_length
- ? remaining
- : instances[minor].run_length;
-
- for (idx = 0 ; idx < repeat ; idx += 1)
- buffer[idx] = instances[minor].repeat_byte;
-
- if (copy_to_user(c, buffer, repeat))
- return -EFAULT;
- remaining -= repeat;
- c += repeat;
- instances[minor].run_length -= repeat;
- }
-
- if (remaining == 0) break;
-
-
- /* Wait for Event 43: Data active on the bus. */
- rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor);
- if (rc == -1) break;
-
- if (rc & BPP_GP_Busy) {
- /* OK, this is data. read it in. */
- unsigned char byte = bpp_inb(base_addrs[minor]);
- if (put_user(byte, c))
- return -EFAULT;
- c += 1;
- remaining -= 1;
-
- if (instances[minor].run_flag) {
- instances[minor].repeat_byte = byte;
- instances[minor].run_flag = 0;
- }
-
- } else {
- unsigned char byte = bpp_inb(base_addrs[minor]);
- if (byte & 0x80) {
- printk("bpp%d: "
- "Ignoring ECP channel %u from device.\n",
- minor, byte & 0x7f);
- } else {
- instances[minor].run_length = byte;
- instances[minor].run_flag = 1;
- }
- }
-
- /* Event 44: I got it. */
- set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor);
-
- /* Wait for event 45: peripheral handshake */
- rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor);
- if (rc == -1) return -ETIMEDOUT;
-
- /* Event 46: Finish handshake */
- set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor);
-
- }
-
-
- return cnt - remaining;
-}
-
-static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos)
-{
- long rc;
- unsigned minor = iminor(f->f_path.dentry->d_inode);
- if (minor >= BPP_NO) return -ENODEV;
- if (!instances[minor].present) return -ENODEV;
-
- switch (instances[minor].mode) {
-
- default:
- if (instances[minor].mode != COMPATIBILITY)
- terminate(minor);
-
- if (instances[minor].enhanced) {
- /* For now, do all reads with ECP-RLE mode */
- unsigned short pins;
-
- rc = negotiate(DEFAULT_ECP, minor);
- if (rc < 0) break;
-
- instances[minor].mode = ECP_RLE;
-
- /* Event 30: set nAutoFd low to setup for ECP mode */
- pins = get_pins(minor);
- pins &= ~BPP_PP_nAutoFd;
- set_pins(pins, minor);
-
- /* Wait for Event 31: peripheral ready */
- rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor);
- if (rc == -1) return -ETIMEDOUT;
-
- rc = read_ecp(minor, c, cnt);
-
- } else {
- rc = negotiate(DEFAULT_NIBBLE, minor);
- if (rc < 0) break;
-
- instances[minor].mode = NIBBLE;
-
- rc = read_nibble(minor, c, cnt);
- }
- break;
-
- case NIBBLE:
- rc = read_nibble(minor, c, cnt);
- break;
-
- case ECP:
- case ECP_RLE:
- rc = read_ecp(minor, c, cnt);
- break;
-
- }
-
-
- return rc;
-}
-
-/*
- * Compatibility mode handshaking is a matter of writing data,
- * strobing it, and waiting for the printer to stop being busy.
- */
-static long write_compat(unsigned minor, const char __user *c, unsigned long cnt)
-{
- long rc;
- unsigned short pins = get_pins(minor);
-
- unsigned long remaining = cnt;
-
-
- while (remaining > 0) {
- unsigned char byte;
-
- if (get_user(byte, c))
- return -EFAULT;
- c += 1;
-
- rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor);
- if (rc == -1) return -ETIMEDOUT;
-
- bpp_outb_p(byte, base_addrs[minor]);
- remaining -= 1;
- /* snooze(1, minor); */
-
- pins &= ~BPP_PP_nStrobe;
- set_pins(pins, minor);
-
- rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor);
-
- pins |= BPP_PP_nStrobe;
- set_pins(pins, minor);
- }
-
- return cnt - remaining;
-}
-
-/*
- * Write data using ECP mode. Watch out that the port may be set up
- * for reading. If so, turn the port around.
- */
-static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt)
-{
- unsigned short pins = get_pins(minor);
- unsigned long remaining = cnt;
-
- if (instances[minor].direction) {
- int rc;
-
- /* Event 47 Request bus be turned around */
- pins |= BPP_PP_nInit;
- set_pins(pins, minor);
-
- /* Wait for Event 49: Peripheral relinquished bus */
- rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor);
-
- pins |= BPP_PP_nAutoFd;
- instances[minor].direction = 0;
- set_pins(pins, minor);
- }
-
- while (remaining > 0) {
- unsigned char byte;
- int rc;
-
- if (get_user(byte, c))
- return -EFAULT;
-
- rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor);
- if (rc == -1) return -ETIMEDOUT;
-
- c += 1;
-
- bpp_outb_p(byte, base_addrs[minor]);
-
- pins &= ~BPP_PP_nStrobe;
- set_pins(pins, minor);
-
- pins |= BPP_PP_nStrobe;
- rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor);
- if (rc == -1) return -EIO;
-
- set_pins(pins, minor);
- }
-
- return cnt - remaining;
-}
-
-/*
- * Write to the peripheral. Be sensitive of the current mode. If I'm
- * in a mode that can be turned around (ECP) then just do
- * that. Otherwise, terminate and do my writing in compat mode. This
- * is the safest course as any device can handle it.
- */
-static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos)
-{
- long errno = 0;
- unsigned minor = iminor(f->f_path.dentry->d_inode);
- if (minor >= BPP_NO) return -ENODEV;
- if (!instances[minor].present) return -ENODEV;
-
- switch (instances[minor].mode) {
-
- case ECP:
- case ECP_RLE:
- errno = write_ecp(minor, c, cnt);
- break;
- case COMPATIBILITY:
- errno = write_compat(minor, c, cnt);
- break;
- default:
- terminate(minor);
- errno = write_compat(minor, c, cnt);
- }
-
- return errno;
-}
-
-static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd,
- unsigned long arg)
-{
- int errno = 0;
-
- unsigned minor = iminor(inode);
- if (minor >= BPP_NO) return -ENODEV;
- if (!instances[minor].present) return -ENODEV;
-
-
- switch (cmd) {
-
- case BPP_PUT_PINS:
- set_pins(arg, minor);
- break;
-
- case BPP_GET_PINS:
- errno = get_pins(minor);
- break;
-
- case BPP_PUT_DATA:
- bpp_outb_p(arg, base_addrs[minor]);
- break;
-
- case BPP_GET_DATA:
- errno = bpp_inb_p(base_addrs[minor]);
- break;
-
- case BPP_SET_INPUT:
- if (arg)
- if (instances[minor].enhanced) {
- unsigned short bits = get_pins(minor);
- instances[minor].direction = 0x20;
- set_pins(bits, minor);
- } else {
- errno = -ENOTTY;
- }
- else {
- unsigned short bits = get_pins(minor);
- instances[minor].direction = 0x00;
- set_pins(bits, minor);
- }
- break;
-
- default:
- errno = -EINVAL;
- }
-
- return errno;
-}
-
-static const struct file_operations bpp_fops = {
- .owner = THIS_MODULE,
- .read = bpp_read,
- .write = bpp_write,
- .ioctl = bpp_ioctl,
- .open = bpp_open,
- .release = bpp_release,
-};
-
-#if defined(__i386__)
-
-#define collectLptPorts() {}
-
-static void probeLptPort(unsigned idx)
-{
- unsigned int testvalue;
- const unsigned short lpAddr = base_addrs[idx];
-
- instances[idx].present = 0;
- instances[idx].enhanced = 0;
- instances[idx].direction = 0;
- instances[idx].mode = COMPATIBILITY;
- instances[idx].run_length = 0;
- instances[idx].run_flag = 0;
- if (!request_region(lpAddr,3, bpp_dev_name)) return;
-
- /*
- * First, make sure the instance exists. Do this by writing to
- * the data latch and reading the value back. If the port *is*
- * present, test to see if it supports extended-mode
- * operation. This will be required for IEEE1284 reverse
- * transfers.
- */
-
- outb_p(BPP_PROBE_CODE, lpAddr);
- for (testvalue=0; testvalue<BPP_DELAY; testvalue++)
- ;
- testvalue = inb_p(lpAddr);
- if (testvalue == BPP_PROBE_CODE) {
- unsigned save;
- instances[idx].present = 1;
-
- save = inb_p(lpAddr+2);
- for (testvalue=0; testvalue<BPP_DELAY; testvalue++)
- ;
- outb_p(save|0x20, lpAddr+2);
- for (testvalue=0; testvalue<BPP_DELAY; testvalue++)
- ;
- outb_p(~BPP_PROBE_CODE, lpAddr);
- for (testvalue=0; testvalue<BPP_DELAY; testvalue++)
- ;
- testvalue = inb_p(lpAddr);
- if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE))
- instances[idx].enhanced = 0;
- else
- instances[idx].enhanced = 1;
- outb_p(save, lpAddr+2);
- }
- else {
- release_region(lpAddr,3);
- }
- /*
- * Leave the port in compat idle mode.
- */
- set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx);
-
- printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx],
- instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE");
-}
-
-static inline void freeLptPort(int idx)
-{
- release_region(base_addrs[idx], 3);
-}
-
-#endif
-
-#if defined(__sparc__)
-
-static void __iomem *map_bpp(struct sbus_dev *dev, int idx)
-{
- return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp");
-}
-
-static int collectLptPorts(void)
-{
- struct sbus_bus *bus;
- struct sbus_dev *dev;
- int count;
-
- count = 0;
- for_all_sbusdev(dev, bus) {
- if (strcmp(dev->prom_name, "SUNW,bpp") == 0) {
- if (count >= BPP_NO) {
- printk(KERN_NOTICE
- "bpp: More than %d bpp ports,"
- " rest is ignored\n", BPP_NO);
- return count;
- }
- base_addrs[count] = map_bpp(dev, count);
- count++;
- }
- }
- return count;
-}
-
-static void probeLptPort(unsigned idx)
-{
- void __iomem *rp = base_addrs[idx];
- __u32 csr;
- char *brand;
-
- instances[idx].present = 0;
- instances[idx].enhanced = 0;
- instances[idx].direction = 0;
- instances[idx].mode = COMPATIBILITY;
- instances[idx].run_length = 0;
- instances[idx].run_flag = 0;
-
- if (!rp) return;
-
- instances[idx].present = 1;
- instances[idx].enhanced = 1; /* Sure */
-
- csr = sbus_readl(rp + BPP_CSR);
- if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) {
- udelay(20);
- csr = sbus_readl(rp + BPP_CSR);
- if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) {
- printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr);
- }
- }
- printk("bpp%d: reset with 0x%08x ..", idx, csr);
- sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR);
- udelay(500);
- sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR);
- csr = sbus_readl(rp + BPP_CSR);
- printk(" done with csr=0x%08x ocr=0x%04x\n",
- csr, sbus_readw(rp + BPP_OCR));
-
- switch (csr & P_DEV_ID_MASK) {
- case P_DEV_ID_ZEBRA:
- brand = "Zebra";
- break;
- case P_DEV_ID_L64854:
- brand = "DMA2";
- break;
- default:
- brand = "Unknown";
- }
- printk("bpp%d: %s at %p\n", idx, brand, rp);
-
- /*
- * Leave the port in compat idle mode.
- */
- set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx);
-
- return;
-}
-
-static inline void freeLptPort(int idx)
-{
- sbus_iounmap(base_addrs[idx], BPP_SIZE);
-}
-
-#endif
-
-static int __init bpp_init(void)
-{
- int rc;
- unsigned idx;
-
- rc = collectLptPorts();
- if (rc == 0)
- return -ENODEV;
-
- rc = register_chrdev(BPP_MAJOR, bpp_dev_name, &bpp_fops);
- if (rc < 0)
- return rc;
-
- for (idx = 0; idx < BPP_NO; idx++) {
- instances[idx].opened = 0;
- probeLptPort(idx);
- }
-
- return 0;
-}
-
-static void __exit bpp_cleanup(void)
-{
- unsigned idx;
-
- unregister_chrdev(BPP_MAJOR, bpp_dev_name);
-
- for (idx = 0; idx < BPP_NO; idx++) {
- if (instances[idx].present)
- freeLptPort(idx);
- }
-}
-
-module_init(bpp_init);
-module_exit(bpp_cleanup);
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
deleted file mode 100644
index 23abfdfb44f..00000000000
--- a/drivers/sbus/char/cpwatchdog.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/* cpwatchdog.c - driver implementation for hardware watchdog
- * timers found on Sun Microsystems CP1400 and CP1500 boards.
- *
- * This device supports both the generic Linux watchdog
- * interface and Solaris-compatible ioctls as best it is
- * able.
- *
- * NOTE: CP1400 systems appear to have a defective intr_mask
- * register on the PLD, preventing the disabling of
- * timer interrupts. We use a timer to periodically
- * reset 'stopped' watchdogs on affected platforms.
- *
- * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/smp_lock.h>
-#include <linux/io.h>
-#include <asm/irq.h>
-#include <asm/ebus.h>
-#include <asm/oplib.h>
-#include <asm/uaccess.h>
-
-#include <asm/watchdog.h>
-
-#define WD_OBPNAME "watchdog"
-#define WD_BADMODEL "SUNW,501-5336"
-#define WD_BTIMEOUT (jiffies + (HZ * 1000))
-#define WD_BLIMIT 0xFFFF
-
-#define WD0_DEVNAME "watchdog0"
-#define WD1_DEVNAME "watchdog1"
-#define WD2_DEVNAME "watchdog2"
-
-#define WD0_MINOR 212
-#define WD1_MINOR 213
-#define WD2_MINOR 214
-
-
-/* Internal driver definitions
- */
-#define WD0_ID 0 /* Watchdog0 */
-#define WD1_ID 1 /* Watchdog1 */
-#define WD2_ID 2 /* Watchdog2 */
-#define WD_NUMDEVS 3 /* Device contains 3 timers */
-
-#define WD_INTR_OFF 0 /* Interrupt disable value */
-#define WD_INTR_ON 1 /* Interrupt enable value */
-
-#define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */
-#define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */
-#define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */
-
-/* Register value definitions
- */
-#define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */
-#define WD1_INTR_MASK 0x02
-#define WD2_INTR_MASK 0x04
-
-#define WD_S_RUNNING 0x01 /* Watchdog device status running */
-#define WD_S_EXPIRED 0x02 /* Watchdog device status expired */
-
-/* Sun uses Altera PLD EPF8820ATC144-4
- * providing three hardware watchdogs:
- *
- * 1) RIC - sends an interrupt when triggered
- * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU
- * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
- *
- *** Timer register block definition (struct wd_timer_regblk)
- *
- * dcntr and limit registers (halfword access):
- * -------------------
- * | 15 | ...| 1 | 0 |
- * -------------------
- * |- counter val -|
- * -------------------
- * dcntr - Current 16-bit downcounter value.
- * When downcounter reaches '0' watchdog expires.
- * Reading this register resets downcounter with 'limit' value.
- * limit - 16-bit countdown value in 1/10th second increments.
- * Writing this register begins countdown with input value.
- * Reading from this register does not affect counter.
- * NOTES: After watchdog reset, dcntr and limit contain '1'
- *
- * status register (byte access):
- * ---------------------------
- * | 7 | ... | 2 | 1 | 0 |
- * --------------+------------
- * |- UNUSED -| EXP | RUN |
- * ---------------------------
- * status- Bit 0 - Watchdog is running
- * Bit 1 - Watchdog has expired
- *
- *** PLD register block definition (struct wd_pld_regblk)
- *
- * intr_mask register (byte access):
- * ---------------------------------
- * | 7 | ... | 3 | 2 | 1 | 0 |
- * +-------------+------------------
- * |- UNUSED -| WD3 | WD2 | WD1 |
- * ---------------------------------
- * WD3 - 1 == Interrupt disabled for watchdog 3
- * WD2 - 1 == Interrupt disabled for watchdog 2
- * WD1 - 1 == Interrupt disabled for watchdog 1
- *
- * pld_status register (byte access):
- * UNKNOWN, MAGICAL MYSTERY REGISTER
- *
- */
-#define WD_TIMER_REGSZ 16
-#define WD0_OFF 0
-#define WD1_OFF (WD_TIMER_REGSZ * 1)
-#define WD2_OFF (WD_TIMER_REGSZ * 2)
-#define PLD_OFF (WD_TIMER_REGSZ * 3)
-
-#define WD_DCNTR 0x00
-#define WD_LIMIT 0x04
-#define WD_STATUS 0x08
-
-#define PLD_IMASK (PLD_OFF + 0x00)
-#define PLD_STATUS (PLD_OFF + 0x04)
-
-/* Individual timer structure
- */
-struct wd_timer {
- __u16 timeout;
- __u8 intr_mask;
- unsigned char runstatus;
- void __iomem *regs;
-};
-
-/* Device structure
- */
-struct wd_device {
- int irq;
- spinlock_t lock;
- unsigned char isbaddoggie; /* defective PLD */
- unsigned char opt_enable;
- unsigned char opt_reboot;
- unsigned short opt_timeout;
- unsigned char initialized;
- struct wd_timer watchdog[WD_NUMDEVS];
- void __iomem *regs;
-};
-
-static struct wd_device wd_dev = {
- 0, __SPIN_LOCK_UNLOCKED(wd_dev.lock), 0, 0, 0, 0,
-};
-
-static struct timer_list wd_timer;
-
-static int wd0_timeout = 0;
-static int wd1_timeout = 0;
-static int wd2_timeout = 0;
-
-#ifdef MODULE
-module_param (wd0_timeout, int, 0);
-MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
-module_param (wd1_timeout, int, 0);
-MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
-module_param (wd2_timeout, int, 0);
-MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
-
-MODULE_AUTHOR
- ("Eric Brower <ebrower@usa.net>");
-MODULE_DESCRIPTION
- ("Hardware watchdog driver for Sun Microsystems CP1400/1500");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE
- ("watchdog");
-#endif /* ifdef MODULE */
-
-/* Forward declarations of internal methods
- */
-#ifdef WD_DEBUG
-static void wd_dumpregs(void);
-#endif
-static irqreturn_t wd_interrupt(int irq, void *dev_id);
-static void wd_toggleintr(struct wd_timer* pTimer, int enable);
-static void wd_pingtimer(struct wd_timer* pTimer);
-static void wd_starttimer(struct wd_timer* pTimer);
-static void wd_resetbrokentimer(struct wd_timer* pTimer);
-static void wd_stoptimer(struct wd_timer* pTimer);
-static void wd_brokentimer(unsigned long data);
-static int wd_getstatus(struct wd_timer* pTimer);
-
-/* PLD expects words to be written in LSB format,
- * so we must flip all words prior to writing them to regs
- */
-static inline unsigned short flip_word(unsigned short word)
-{
- return ((word & 0xff) << 8) | ((word >> 8) & 0xff);
-}
-
-#define wd_writew(val, addr) (writew(flip_word(val), addr))
-#define wd_readw(addr) (flip_word(readw(addr)))
-#define wd_writeb(val, addr) (writeb(val, addr))
-#define wd_readb(addr) (readb(addr))
-
-
-/* CP1400s seem to have broken PLD implementations--
- * the interrupt_mask register cannot be written, so
- * no timer interrupts can be masked within the PLD.
- */
-static inline int wd_isbroken(void)
-{
- /* we could test this by read/write/read/restore
- * on the interrupt mask register only if OBP
- * 'watchdog-enable?' == FALSE, but it seems
- * ubiquitous on CP1400s
- */
- char val[32];
- prom_getproperty(prom_root_node, "model", val, sizeof(val));
- return((!strcmp(val, WD_BADMODEL)) ? 1 : 0);
-}
-
-/* Retrieve watchdog-enable? option from OBP
- * Returns 0 if false, 1 if true
- */
-static inline int wd_opt_enable(void)
-{
- int opt_node;
-
- opt_node = prom_getchild(prom_root_node);
- opt_node = prom_searchsiblings(opt_node, "options");
- return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1);
-}
-
-/* Retrieve watchdog-reboot? option from OBP
- * Returns 0 if false, 1 if true
- */
-static inline int wd_opt_reboot(void)
-{
- int opt_node;
-
- opt_node = prom_getchild(prom_root_node);
- opt_node = prom_searchsiblings(opt_node, "options");
- return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1);
-}
-
-/* Retrieve watchdog-timeout option from OBP
- * Returns OBP value, or 0 if not located
- */
-static inline int wd_opt_timeout(void)
-{
- int opt_node;
- char value[32];
- char *p = value;
-
- opt_node = prom_getchild(prom_root_node);
- opt_node = prom_searchsiblings(opt_node, "options");
- opt_node = prom_getproperty(opt_node,
- "watchdog-timeout",
- value,
- sizeof(value));
- if(-1 != opt_node) {
- /* atoi implementation */
- for(opt_node = 0; /* nop */; p++) {
- if(*p >= '0' && *p <= '9') {
- opt_node = (10*opt_node)+(*p-'0');
- }
- else {
- break;
- }
- }
- }
- return((-1 == opt_node) ? (0) : (opt_node));
-}
-
-static int wd_open(struct inode *inode, struct file *f)
-{
- lock_kernel();
- switch(iminor(inode))
- {
- case WD0_MINOR:
- f->private_data = &wd_dev.watchdog[WD0_ID];
- break;
- case WD1_MINOR:
- f->private_data = &wd_dev.watchdog[WD1_ID];
- break;
- case WD2_MINOR:
- f->private_data = &wd_dev.watchdog[WD2_ID];
- break;
- default:
- unlock_kernel();
- return(-ENODEV);
- }
-
- /* Register IRQ on first open of device */
- if(0 == wd_dev.initialized)
- {
- if (request_irq(wd_dev.irq,
- &wd_interrupt,
- IRQF_SHARED,
- WD_OBPNAME,
- (void *)wd_dev.regs)) {
- printk("%s: Cannot register IRQ %d\n",
- WD_OBPNAME, wd_dev.irq);
- unlock_kernel();
- return(-EBUSY);
- }
- wd_dev.initialized = 1;
- }
-
- unlock_kernel();
- return(nonseekable_open(inode, f));
-}
-
-static int wd_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static int wd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int setopt = 0;
- struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
- void __user *argp = (void __user *)arg;
- struct watchdog_info info = {
- 0,
- 0,
- "Altera EPF8820ATC144-4"
- };
-
- if(NULL == pTimer) {
- return(-EINVAL);
- }
-
- switch(cmd)
- {
- /* Generic Linux IOCTLs */
- case WDIOC_GETSUPPORT:
- if(copy_to_user(argp, &info, sizeof(struct watchdog_info))) {
- return(-EFAULT);
- }
- break;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- if (put_user(0, (int __user *)argp))
- return -EFAULT;
- break;
- case WDIOC_KEEPALIVE:
- wd_pingtimer(pTimer);
- break;
- case WDIOC_SETOPTIONS:
- if(copy_from_user(&setopt, argp, sizeof(unsigned int))) {
- return -EFAULT;
- }
- if(setopt & WDIOS_DISABLECARD) {
- if(wd_dev.opt_enable) {
- printk(
- "%s: cannot disable watchdog in ENABLED mode\n",
- WD_OBPNAME);
- return(-EINVAL);
- }
- wd_stoptimer(pTimer);
- }
- else if(setopt & WDIOS_ENABLECARD) {
- wd_starttimer(pTimer);
- }
- else {
- return(-EINVAL);
- }
- break;
- /* Solaris-compatible IOCTLs */
- case WIOCGSTAT:
- setopt = wd_getstatus(pTimer);
- if(copy_to_user(argp, &setopt, sizeof(unsigned int))) {
- return(-EFAULT);
- }
- break;
- case WIOCSTART:
- wd_starttimer(pTimer);
- break;
- case WIOCSTOP:
- if(wd_dev.opt_enable) {
- printk("%s: cannot disable watchdog in ENABLED mode\n",
- WD_OBPNAME);
- return(-EINVAL);
- }
- wd_stoptimer(pTimer);
- break;
- default:
- return(-EINVAL);
- }
- return(0);
-}
-
-static long wd_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int rval = -ENOIOCTLCMD;
-
- switch (cmd) {
- /* solaris ioctls are specific to this driver */
- case WIOCSTART:
- case WIOCSTOP:
- case WIOCGSTAT:
- lock_kernel();
- rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
- unlock_kernel();
- break;
- /* everything else is handled by the generic compat layer */
- default:
- break;
- }
-
- return rval;
-}
-
-static ssize_t wd_write(struct file *file,
- const char __user *buf,
- size_t count,
- loff_t *ppos)
-{
- struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
-
- if(NULL == pTimer) {
- return(-EINVAL);
- }
-
- if (count) {
- wd_pingtimer(pTimer);
- return 1;
- }
- return 0;
-}
-
-static ssize_t wd_read(struct file * file, char __user *buffer,
- size_t count, loff_t *ppos)
-{
-#ifdef WD_DEBUG
- wd_dumpregs();
- return(0);
-#else
- return(-EINVAL);
-#endif /* ifdef WD_DEBUG */
-}
-
-static irqreturn_t wd_interrupt(int irq, void *dev_id)
-{
- /* Only WD0 will interrupt-- others are NMI and we won't
- * see them here....
- */
- spin_lock_irq(&wd_dev.lock);
- if((unsigned long)wd_dev.regs == (unsigned long)dev_id)
- {
- wd_stoptimer(&wd_dev.watchdog[WD0_ID]);
- wd_dev.watchdog[WD0_ID].runstatus |= WD_STAT_SVCD;
- }
- spin_unlock_irq(&wd_dev.lock);
- return IRQ_HANDLED;
-}
-
-static const struct file_operations wd_fops = {
- .owner = THIS_MODULE,
- .ioctl = wd_ioctl,
- .compat_ioctl = wd_compat_ioctl,
- .open = wd_open,
- .write = wd_write,
- .read = wd_read,
- .release = wd_release,
-};
-
-static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops };
-static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops };
-static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops };
-
-#ifdef WD_DEBUG
-static void wd_dumpregs(void)
-{
- /* Reading from downcounters initiates watchdog countdown--
- * Example is included below for illustration purposes.
- */
- int i;
- printk("%s: dumping register values\n", WD_OBPNAME);
- for(i = WD0_ID; i < WD_NUMDEVS; ++i) {
- /* printk("\t%s%i: dcntr at 0x%lx: 0x%x\n",
- * WD_OBPNAME,
- * i,
- * (unsigned long)(&wd_dev.watchdog[i].regs->dcntr),
- * readw(&wd_dev.watchdog[i].regs->dcntr));
- */
- printk("\t%s%i: limit at 0x%lx: 0x%x\n",
- WD_OBPNAME,
- i,
- (unsigned long)(&wd_dev.watchdog[i].regs->limit),
- readw(&wd_dev.watchdog[i].regs->limit));
- printk("\t%s%i: status at 0x%lx: 0x%x\n",
- WD_OBPNAME,
- i,
- (unsigned long)(&wd_dev.watchdog[i].regs->status),
- readb(&wd_dev.watchdog[i].regs->status));
- printk("\t%s%i: driver status: 0x%x\n",
- WD_OBPNAME,
- i,
- wd_getstatus(&wd_dev.watchdog[i]));
- }
- printk("\tintr_mask at %p: 0x%x\n",
- wd_dev.regs + PLD_IMASK,
- readb(wd_dev.regs + PLD_IMASK));
- printk("\tpld_status at %p: 0x%x\n",
- wd_dev.regs + PLD_STATUS,
- readb(wd_dev.regs + PLD_STATUS));
-}
-#endif
-
-/* Enable or disable watchdog interrupts
- * Because of the CP1400 defect this should only be
- * called during initialzation or by wd_[start|stop]timer()
- *
- * pTimer - pointer to timer device, or NULL to indicate all timers
- * enable - non-zero to enable interrupts, zero to disable
- */
-static void wd_toggleintr(struct wd_timer* pTimer, int enable)
-{
- unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK);
- unsigned char setregs =
- (NULL == pTimer) ?
- (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) :
- (pTimer->intr_mask);
-
- (WD_INTR_ON == enable) ?
- (curregs &= ~setregs):
- (curregs |= setregs);
-
- wd_writeb(curregs, wd_dev.regs + PLD_IMASK);
- return;
-}
-
-/* Reset countdown timer with 'limit' value and continue countdown.
- * This will not start a stopped timer.
- *
- * pTimer - pointer to timer device
- */
-static void wd_pingtimer(struct wd_timer* pTimer)
-{
- if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
- wd_readw(pTimer->regs + WD_DCNTR);
- }
-}
-
-/* Stop a running watchdog timer-- the timer actually keeps
- * running, but the interrupt is masked so that no action is
- * taken upon expiration.
- *
- * pTimer - pointer to timer device
- */
-static void wd_stoptimer(struct wd_timer* pTimer)
-{
- if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
- wd_toggleintr(pTimer, WD_INTR_OFF);
-
- if(wd_dev.isbaddoggie) {
- pTimer->runstatus |= WD_STAT_BSTOP;
- wd_brokentimer((unsigned long)&wd_dev);
- }
- }
-}
-
-/* Start a watchdog timer with the specified limit value
- * If the watchdog is running, it will be restarted with
- * the provided limit value.
- *
- * This function will enable interrupts on the specified
- * watchdog.
- *
- * pTimer - pointer to timer device
- * limit - limit (countdown) value in 1/10th seconds
- */
-static void wd_starttimer(struct wd_timer* pTimer)
-{
- if(wd_dev.isbaddoggie) {
- pTimer->runstatus &= ~WD_STAT_BSTOP;
- }
- pTimer->runstatus &= ~WD_STAT_SVCD;
-
- wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT);
- wd_toggleintr(pTimer, WD_INTR_ON);
-}
-
-/* Restarts timer with maximum limit value and
- * does not unset 'brokenstop' value.
- */
-static void wd_resetbrokentimer(struct wd_timer* pTimer)
-{
- wd_toggleintr(pTimer, WD_INTR_ON);
- wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT);
-}
-
-/* Timer device initialization helper.
- * Returns 0 on success, other on failure
- */
-static int wd_inittimer(int whichdog)
-{
- struct miscdevice *whichmisc;
- void __iomem *whichregs;
- char whichident[8];
- int whichmask;
- __u16 whichlimit;
-
- switch(whichdog)
- {
- case WD0_ID:
- whichmisc = &wd0_miscdev;
- strcpy(whichident, "RIC");
- whichregs = wd_dev.regs + WD0_OFF;
- whichmask = WD0_INTR_MASK;
- whichlimit= (0 == wd0_timeout) ?
- (wd_dev.opt_timeout):
- (wd0_timeout);
- break;
- case WD1_ID:
- whichmisc = &wd1_miscdev;
- strcpy(whichident, "XIR");
- whichregs = wd_dev.regs + WD1_OFF;
- whichmask = WD1_INTR_MASK;
- whichlimit= (0 == wd1_timeout) ?
- (wd_dev.opt_timeout):
- (wd1_timeout);
- break;
- case WD2_ID:
- whichmisc = &wd2_miscdev;
- strcpy(whichident, "POR");
- whichregs = wd_dev.regs + WD2_OFF;
- whichmask = WD2_INTR_MASK;
- whichlimit= (0 == wd2_timeout) ?
- (wd_dev.opt_timeout):
- (wd2_timeout);
- break;
- default:
- printk("%s: %s: invalid watchdog id: %i\n",
- WD_OBPNAME, __func__, whichdog);
- return(1);
- }
- if(0 != misc_register(whichmisc))
- {
- return(1);
- }
- wd_dev.watchdog[whichdog].regs = whichregs;
- wd_dev.watchdog[whichdog].timeout = whichlimit;
- wd_dev.watchdog[whichdog].intr_mask = whichmask;
- wd_dev.watchdog[whichdog].runstatus &= ~WD_STAT_BSTOP;
- wd_dev.watchdog[whichdog].runstatus |= WD_STAT_INIT;
-
- printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n",
- WD_OBPNAME,
- whichdog,
- whichident,
- wd_dev.watchdog[whichdog].timeout / 10,
- wd_dev.watchdog[whichdog].timeout % 10,
- (0 != wd_dev.opt_enable) ? "in ENABLED mode" : "");
- return(0);
-}
-
-/* Timer method called to reset stopped watchdogs--
- * because of the PLD bug on CP1400, we cannot mask
- * interrupts within the PLD so me must continually
- * reset the timers ad infinitum.
- */
-static void wd_brokentimer(unsigned long data)
-{
- struct wd_device* pDev = (struct wd_device*)data;
- int id, tripped = 0;
-
- /* kill a running timer instance, in case we
- * were called directly instead of by kernel timer
- */
- if(timer_pending(&wd_timer)) {
- del_timer(&wd_timer);
- }
-
- for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
- if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) {
- ++tripped;
- wd_resetbrokentimer(&pDev->watchdog[id]);
- }
- }
-
- if(tripped) {
- /* there is at least one timer brokenstopped-- reschedule */
- init_timer(&wd_timer);
- wd_timer.expires = WD_BTIMEOUT;
- add_timer(&wd_timer);
- }
-}
-
-static int wd_getstatus(struct wd_timer* pTimer)
-{
- unsigned char stat = wd_readb(pTimer->regs + WD_STATUS);
- unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK);
- unsigned char ret = WD_STOPPED;
-
- /* determine STOPPED */
- if(0 == stat ) {
- return(ret);
- }
- /* determine EXPIRED vs FREERUN vs RUNNING */
- else if(WD_S_EXPIRED & stat) {
- ret = WD_EXPIRED;
- }
- else if(WD_S_RUNNING & stat) {
- if(intr & pTimer->intr_mask) {
- ret = WD_FREERUN;
- }
- else {
- /* Fudge WD_EXPIRED status for defective CP1400--
- * IF timer is running
- * AND brokenstop is set
- * AND an interrupt has been serviced
- * we are WD_EXPIRED.
- *
- * IF timer is running
- * AND brokenstop is set
- * AND no interrupt has been serviced
- * we are WD_FREERUN.
- */
- if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) {
- if(pTimer->runstatus & WD_STAT_SVCD) {
- ret = WD_EXPIRED;
- }
- else {
- /* we could as well pretend we are expired */
- ret = WD_FREERUN;
- }
- }
- else {
- ret = WD_RUNNING;
- }
- }
- }
-
- /* determine SERVICED */
- if(pTimer->runstatus & WD_STAT_SVCD) {
- ret |= WD_SERVICED;
- }
-
- return(ret);
-}
-
-static int __init wd_init(void)
-{
- int id;
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->ofdev.node->name, WD_OBPNAME))
- goto ebus_done;
- }
- }
-
-ebus_done:
- if(!edev) {
- printk("%s: unable to locate device\n", WD_OBPNAME);
- return -ENODEV;
- }
-
- wd_dev.regs =
- ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */
-
- if(NULL == wd_dev.regs) {
- printk("%s: unable to map registers\n", WD_OBPNAME);
- return(-ENODEV);
- }
-
- /* initialize device structure from OBP parameters */
- wd_dev.irq = edev->irqs[0];
- wd_dev.opt_enable = wd_opt_enable();
- wd_dev.opt_reboot = wd_opt_reboot();
- wd_dev.opt_timeout = wd_opt_timeout();
- wd_dev.isbaddoggie = wd_isbroken();
-
- /* disable all interrupts unless watchdog-enabled? == true */
- if(! wd_dev.opt_enable) {
- wd_toggleintr(NULL, WD_INTR_OFF);
- }
-
- /* register miscellaneous devices */
- for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
- if(0 != wd_inittimer(id)) {
- printk("%s%i: unable to initialize\n", WD_OBPNAME, id);
- }
- }
-
- /* warn about possible defective PLD */
- if(wd_dev.isbaddoggie) {
- init_timer(&wd_timer);
- wd_timer.function = wd_brokentimer;
- wd_timer.data = (unsigned long)&wd_dev;
- wd_timer.expires = WD_BTIMEOUT;
-
- printk("%s: PLD defect workaround enabled for model %s\n",
- WD_OBPNAME, WD_BADMODEL);
- }
- return(0);
-}
-
-static void __exit wd_cleanup(void)
-{
- int id;
-
- /* if 'watchdog-enable?' == TRUE, timers are not stopped
- * when module is unloaded. All brokenstopped timers will
- * also now eventually trip.
- */
- for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
- if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) {
- if(wd_dev.opt_enable) {
- printk(KERN_WARNING "%s%i: timer not stopped at release\n",
- WD_OBPNAME, id);
- }
- else {
- wd_stoptimer(&wd_dev.watchdog[id]);
- if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) {
- wd_resetbrokentimer(&wd_dev.watchdog[id]);
- printk(KERN_WARNING
- "%s%i: defect workaround disabled at release, "\
- "timer expires in ~%01i sec\n",
- WD_OBPNAME, id,
- wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10);
- }
- }
- }
- }
-
- if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) {
- del_timer(&wd_timer);
- }
- if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) {
- misc_deregister(&wd0_miscdev);
- }
- if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) {
- misc_deregister(&wd1_miscdev);
- }
- if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) {
- misc_deregister(&wd2_miscdev);
- }
- if(0 != wd_dev.initialized) {
- free_irq(wd_dev.irq, (void *)wd_dev.regs);
- }
- iounmap(wd_dev.regs);
-}
-
-module_init(wd_init);
-module_exit(wd_cleanup);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index d8f5c0ca236..2550af4ae43 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -1,10 +1,7 @@
-/* $Id: display7seg.c,v 1.6 2002/01/08 16:00:16 davem Exp $
- *
- * display7seg - Driver implementation for the 7-segment display
- * present on Sun Microsystems CP1400 and CP1500
+/* display7seg.c - Driver implementation for the 7-segment display
+ * present on Sun Microsystems CP1400 and CP1500
*
* Copyright (c) 2000 Eric Brower (ebrower@usa.net)
- *
*/
#include <linux/kernel.h>
@@ -16,22 +13,20 @@
#include <linux/miscdevice.h>
#include <linux/ioport.h> /* request_region */
#include <linux/smp_lock.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/atomic.h>
-#include <asm/ebus.h> /* EBus device */
-#include <asm/oplib.h> /* OpenProm Library */
#include <asm/uaccess.h> /* put_/get_user */
#include <asm/io.h>
#include <asm/display7seg.h>
#define D7S_MINOR 193
-#define D7S_OBPNAME "display7seg"
-#define D7S_DEVNAME "d7s"
+#define DRIVER_NAME "d7s"
+#define PFX DRIVER_NAME ": "
static int sol_compat = 0; /* Solaris compatibility mode */
-#ifdef MODULE
-
/* Solaris compatibility flag -
* The Solaris implementation omits support for several
* documented driver features (ref Sun doc 806-0180-03).
@@ -46,20 +41,20 @@ static int sol_compat = 0; /* Solaris compatibility mode */
* If you wish the device to operate as under Solaris,
* omitting above features, set this parameter to non-zero.
*/
-module_param
- (sol_compat, int, 0);
-MODULE_PARM_DESC
- (sol_compat,
- "Disables documented functionality omitted from Solaris driver");
-
-MODULE_AUTHOR
- ("Eric Brower <ebrower@usa.net>");
-MODULE_DESCRIPTION
- ("7-Segment Display driver for Sun Microsystems CP1400/1500");
+module_param(sol_compat, int, 0);
+MODULE_PARM_DESC(sol_compat,
+ "Disables documented functionality omitted from Solaris driver");
+
+MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
+MODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE
- ("d7s");
-#endif /* ifdef MODULE */
+MODULE_SUPPORTED_DEVICE("d7s");
+
+struct d7s {
+ void __iomem *regs;
+ bool flipped;
+};
+struct d7s *d7s_device;
/*
* Register block address- see header for details
@@ -72,22 +67,6 @@ MODULE_SUPPORTED_DEVICE
* FLIP - Inverts display for upside-down mounted board
* bits 0-4 - 7-segment display contents
*/
-static void __iomem* d7s_regs;
-
-static inline void d7s_free(void)
-{
- iounmap(d7s_regs);
-}
-
-static inline int d7s_obpflipped(void)
-{
- int opt_node;
-
- opt_node = prom_getchild(prom_root_node);
- opt_node = prom_searchsiblings(opt_node, "options");
- return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1);
-}
-
static atomic_t d7s_users = ATOMIC_INIT(0);
static int d7s_open(struct inode *inode, struct file *f)
@@ -106,12 +85,15 @@ static int d7s_release(struct inode *inode, struct file *f)
* are not operating in solaris-compat mode
*/
if (atomic_dec_and_test(&d7s_users) && !sol_compat) {
- int regval = 0;
-
- regval = readb(d7s_regs);
- (0 == d7s_obpflipped()) ?
- writeb(regval |= D7S_FLIP, d7s_regs):
- writeb(regval &= ~D7S_FLIP, d7s_regs);
+ struct d7s *p = d7s_device;
+ u8 regval = 0;
+
+ regval = readb(p->regs);
+ if (p->flipped)
+ regval |= D7S_FLIP;
+ else
+ regval &= ~D7S_FLIP;
+ writeb(regval, p->regs);
}
return 0;
@@ -119,9 +101,10 @@ static int d7s_release(struct inode *inode, struct file *f)
static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- __u8 regs = readb(d7s_regs);
- __u8 ireg = 0;
+ struct d7s *p = d7s_device;
+ u8 regs = readb(p->regs);
int error = 0;
+ u8 ireg = 0;
if (D7S_MINOR != iminor(file->f_path.dentry->d_inode))
return -ENODEV;
@@ -129,18 +112,20 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
lock_kernel();
switch (cmd) {
case D7SIOCWR:
- /* assign device register values
- * we mask-out D7S_FLIP if in sol_compat mode
+ /* assign device register values we mask-out D7S_FLIP
+ * if in sol_compat mode
*/
if (get_user(ireg, (int __user *) arg)) {
error = -EFAULT;
break;
}
- if (0 != sol_compat) {
- (regs & D7S_FLIP) ?
- (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP);
+ if (sol_compat) {
+ if (regs & D7S_FLIP)
+ ireg |= D7S_FLIP;
+ else
+ ireg &= ~D7S_FLIP;
}
- writeb(ireg, d7s_regs);
+ writeb(ireg, p->regs);
break;
case D7SIOCRD:
@@ -158,9 +143,11 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case D7SIOCTM:
/* toggle device mode-- flip display orientation */
- (regs & D7S_FLIP) ?
- (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP);
- writeb(regs, d7s_regs);
+ if (regs & D7S_FLIP)
+ regs &= ~D7S_FLIP;
+ else
+ regs |= D7S_FLIP;
+ writeb(regs, p->regs);
break;
};
unlock_kernel();
@@ -176,69 +163,123 @@ static const struct file_operations d7s_fops = {
.release = d7s_release,
};
-static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops };
+static struct miscdevice d7s_miscdev = {
+ .minor = D7S_MINOR,
+ .name = DRIVER_NAME,
+ .fops = &d7s_fops
+};
-static int __init d7s_init(void)
+static int __devinit d7s_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
- int iTmp = 0, regs = 0;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, D7S_OBPNAME))
- goto ebus_done;
- }
+ struct device_node *opts;
+ int err = -EINVAL;
+ struct d7s *p;
+ u8 regs;
+
+ if (d7s_device)
+ goto out;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!p)
+ goto out;
+
+ p->regs = of_ioremap(&op->resource[0], 0, sizeof(u8), "d7s");
+ if (!p->regs) {
+ printk(KERN_ERR PFX "Cannot map chip registers\n");
+ goto out_free;
}
-ebus_done:
- if(!edev) {
- printk("%s: unable to locate device\n", D7S_DEVNAME);
- return -ENODEV;
+ err = misc_register(&d7s_miscdev);
+ if (err) {
+ printk(KERN_ERR PFX "Unable to acquire miscdevice minor %i\n",
+ D7S_MINOR);
+ goto out_iounmap;
}
- d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8));
-
- iTmp = misc_register(&d7s_miscdev);
- if (0 != iTmp) {
- printk("%s: unable to acquire miscdevice minor %i\n",
- D7S_DEVNAME, D7S_MINOR);
- iounmap(d7s_regs);
- return iTmp;
- }
-
- /* OBP option "d7s-flipped?" is honored as default
- * for the device, and reset default when detached
+ /* OBP option "d7s-flipped?" is honored as default for the
+ * device, and reset default when detached
*/
- regs = readb(d7s_regs);
- iTmp = d7s_obpflipped();
- (0 == iTmp) ?
- writeb(regs |= D7S_FLIP, d7s_regs):
- writeb(regs &= ~D7S_FLIP, d7s_regs);
-
- printk("%s: 7-Segment Display%s at 0x%lx %s\n",
- D7S_DEVNAME,
- (0 == iTmp) ? (" (FLIPPED)") : (""),
- edev->resource[0].start,
- (0 != sol_compat) ? ("in sol_compat mode") : (""));
-
- return 0;
+ regs = readb(p->regs);
+ opts = of_find_node_by_path("/options");
+ if (opts &&
+ of_get_property(opts, "d7s-flipped?", NULL))
+ p->flipped = true;
+
+ if (p->flipped)
+ regs |= D7S_FLIP;
+ else
+ regs &= ~D7S_FLIP;
+
+ writeb(regs, p->regs);
+
+ printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%lx] %s\n",
+ op->node->full_name,
+ (regs & D7S_FLIP) ? " (FLIPPED)" : "",
+ op->resource[0].start,
+ sol_compat ? "in sol_compat mode" : "");
+
+ dev_set_drvdata(&op->dev, p);
+ d7s_device = p;
+ err = 0;
+
+out:
+ return err;
+
+out_iounmap:
+ of_iounmap(&op->resource[0], p->regs, sizeof(u8));
+
+out_free:
+ kfree(p);
+ goto out;
}
-static void __exit d7s_cleanup(void)
+static int __devexit d7s_remove(struct of_device *op)
{
- int regs = readb(d7s_regs);
+ struct d7s *p = dev_get_drvdata(&op->dev);
+ u8 regs = readb(p->regs);
/* Honor OBP d7s-flipped? unless operating in solaris-compat mode */
- if (0 == sol_compat) {
- (0 == d7s_obpflipped()) ?
- writeb(regs |= D7S_FLIP, d7s_regs):
- writeb(regs &= ~D7S_FLIP, d7s_regs);
+ if (sol_compat) {
+ if (p->flipped)
+ regs |= D7S_FLIP;
+ else
+ regs &= ~D7S_FLIP;
+ writeb(regs, p->regs);
}
misc_deregister(&d7s_miscdev);
- d7s_free();
+ of_iounmap(&op->resource[0], p->regs, sizeof(u8));
+ kfree(p);
+
+ return 0;
+}
+
+static const struct of_device_id d7s_match[] = {
+ {
+ .name = "display7seg",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, d7s_match);
+
+static struct of_platform_driver d7s_driver = {
+ .name = DRIVER_NAME,
+ .match_table = d7s_match,
+ .probe = d7s_probe,
+ .remove = __devexit_p(d7s_remove),
+};
+
+static int __init d7s_init(void)
+{
+ return of_register_driver(&d7s_driver, &of_bus_type);
+}
+
+static void __exit d7s_exit(void)
+{
+ of_unregister_driver(&d7s_driver);
}
module_init(d7s_init);
-module_exit(d7s_cleanup);
+module_exit(d7s_exit);
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index a408402426f..58e583b61e6 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1,5 +1,4 @@
-/* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $
- * envctrl.c: Temperature and Fan monitoring on Machines providing it.
+/* envctrl.c: Temperature and Fan monitoring on Machines providing it.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com)
@@ -28,12 +27,16 @@
#include <linux/kmod.h>
#include <linux/reboot.h>
#include <linux/smp_lock.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
-#include <asm/ebus.h>
#include <asm/uaccess.h>
#include <asm/envctrl.h>
#include <asm/io.h>
+#define DRIVER_NAME "envctrl"
+#define PFX DRIVER_NAME ": "
+
#define ENVCTRL_MINOR 162
#define PCF8584_ADDRESS 0x55
@@ -193,7 +196,7 @@ static void envtrl_i2c_test_pin(void)
}
if (limit <= 0)
- printk(KERN_INFO "envctrl: Pin status will not clear.\n");
+ printk(KERN_INFO PFX "Pin status will not clear.\n");
}
/* Function Description: Test busy bit.
@@ -211,7 +214,7 @@ static void envctrl_i2c_test_bb(void)
}
if (limit <= 0)
- printk(KERN_INFO "envctrl: Busy bit will not clear.\n");
+ printk(KERN_INFO PFX "Busy bit will not clear.\n");
}
/* Function Description: Send the address for a read access.
@@ -858,11 +861,10 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild)
/* Function Description: Initialize i2c child device.
* Return: None.
*/
-static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
+static void envctrl_init_i2c_child(struct device_node *dp,
struct i2c_child_t *pchild)
{
int len, i, tbls_size = 0;
- struct device_node *dp = edev_child->prom_node;
const void *pval;
/* Get device address. */
@@ -882,12 +884,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
pchild->tables = kmalloc(tbls_size, GFP_KERNEL);
if (pchild->tables == NULL){
- printk("envctrl: Failed to allocate table.\n");
+ printk(KERN_ERR PFX "Failed to allocate table.\n");
return;
}
pval = of_get_property(dp, "tables", &len);
if (!pval || len <= 0) {
- printk("envctrl: Failed to get table.\n");
+ printk(KERN_ERR PFX "Failed to get table.\n");
return;
}
memcpy(pchild->tables, pval, len);
@@ -993,14 +995,14 @@ static int kenvctrld(void *__unused)
struct i2c_child_t *cputemp;
if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) {
- printk(KERN_ERR
- "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n");
+ printk(KERN_ERR PFX
+ "kenvctrld unable to monitor CPU temp-- exiting\n");
return -ENODEV;
}
poll_interval = 5000; /* TODO env_mon_interval */
- printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
+ printk(KERN_INFO PFX "%s starting...\n", current->comm);
for (;;) {
msleep_interruptible(poll_interval);
@@ -1022,54 +1024,35 @@ static int kenvctrld(void *__unused)
}
}
}
- printk(KERN_INFO "envctrl: %s exiting...\n", current->comm);
+ printk(KERN_INFO PFX "%s exiting...\n", current->comm);
return 0;
}
-static int __init envctrl_init(void)
+static int __devinit envctrl_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
- struct linux_ebus_child *edev_child = NULL;
- int err, i = 0;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "bbc")) {
- /* If we find a boot-bus controller node,
- * then this envctrl driver is not for us.
- */
- return -ENODEV;
- }
- }
- }
+ struct device_node *dp;
+ int index, err;
- /* Traverse through ebus and ebus device list for i2c device and
- * adc and gpio nodes.
- */
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "i2c")) {
- i2c = ioremap(edev->resource[0].start, 0x2);
- for_each_edevchild(edev, edev_child) {
- if (!strcmp("gpio", edev_child->prom_node->name)) {
- i2c_childlist[i].i2ctype = I2C_GPIO;
- envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
- }
- if (!strcmp("adc", edev_child->prom_node->name)) {
- i2c_childlist[i].i2ctype = I2C_ADC;
- envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
- }
- }
- goto done;
- }
+ if (i2c)
+ return -EINVAL;
+
+ i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME);
+ if (!i2c)
+ return -ENOMEM;
+
+ index = 0;
+ dp = op->node->child;
+ while (dp) {
+ if (!strcmp(dp->name, "gpio")) {
+ i2c_childlist[index].i2ctype = I2C_GPIO;
+ envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
+ } else if (!strcmp(dp->name, "adc")) {
+ i2c_childlist[index].i2ctype = I2C_ADC;
+ envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
}
- }
-done:
- if (!edev) {
- printk("envctrl: I2C device not found.\n");
- return -ENODEV;
+ dp = dp->sibling;
}
/* Set device address. */
@@ -1087,7 +1070,7 @@ done:
/* Register the device as a minor miscellaneous device. */
err = misc_register(&envctrl_dev);
if (err) {
- printk("envctrl: Unable to get misc minor %d\n",
+ printk(KERN_ERR PFX "Unable to get misc minor %d\n",
envctrl_dev.minor);
goto out_iounmap;
}
@@ -1096,12 +1079,12 @@ done:
* a next child device, so we decrement before reverse-traversal of
* child devices.
*/
- printk("envctrl: initialized ");
- for (--i; i >= 0; --i) {
+ printk(KERN_INFO PFX "Initialized ");
+ for (--index; index >= 0; --index) {
printk("[%s 0x%lx]%s",
- (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") :
- ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")),
- i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
+ (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" :
+ ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"),
+ i2c_childlist[index].addr, (0 == index) ? "\n" : " ");
}
kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
@@ -1115,26 +1098,54 @@ done:
out_deregister:
misc_deregister(&envctrl_dev);
out_iounmap:
- iounmap(i2c);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
- kfree(i2c_childlist[i].tables);
+ of_iounmap(&op->resource[0], i2c, 0x2);
+ for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
+ kfree(i2c_childlist[index].tables);
return err;
}
-static void __exit envctrl_cleanup(void)
+static int __devexit envctrl_remove(struct of_device *op)
{
- int i;
+ int index;
kthread_stop(kenvctrld_task);
- iounmap(i2c);
+ of_iounmap(&op->resource[0], i2c, 0x2);
misc_deregister(&envctrl_dev);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
- kfree(i2c_childlist[i].tables);
+ for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
+ kfree(i2c_childlist[index].tables);
+
+ return 0;
+}
+
+static const struct of_device_id envctrl_match[] = {
+ {
+ .name = "i2c",
+ .compatible = "i2cpcf,8584",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, envctrl_match);
+
+static struct of_platform_driver envctrl_driver = {
+ .name = DRIVER_NAME,
+ .match_table = envctrl_match,
+ .probe = envctrl_probe,
+ .remove = __devexit_p(envctrl_remove),
+};
+
+static int __init envctrl_init(void)
+{
+ return of_register_driver(&envctrl_driver, &of_bus_type);
+}
+
+static void __exit envctrl_exit(void)
+{
+ of_unregister_driver(&envctrl_driver);
}
module_init(envctrl_init);
-module_exit(envctrl_cleanup);
+module_exit(envctrl_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 7d95e151513..41083472ff4 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -1,5 +1,4 @@
-/* $Id: flash.c,v 1.25 2001/12/21 04:56:16 davem Exp $
- * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
+/* flash.c: Allow mmap access to the OBP Flash, for OBP updates.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
*/
@@ -15,13 +14,13 @@
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
-#include <asm/sbus.h>
-#include <asm/ebus.h>
#include <asm/upa.h>
static DEFINE_SPINLOCK(flash_lock);
@@ -161,97 +160,68 @@ static const struct file_operations flash_fops = {
static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
-static int __init flash_init(void)
+static int __devinit flash_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
-#ifdef CONFIG_PCI
- struct linux_ebus *ebus;
- struct linux_ebus_device *edev = NULL;
- struct linux_prom_registers regs[2];
- int len, nregs;
-#endif
- int err;
-
- for_all_sbusdev(sdev, sbus) {
- if (!strcmp(sdev->prom_name, "flashprom")) {
- if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) {
- flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) |
- (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL);
- flash.read_size = sdev->reg_addrs[0].reg_size;
- flash.write_base = flash.read_base;
- flash.write_size = flash.read_size;
- } else {
- flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) |
- (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL);
- flash.read_size = sdev->reg_addrs[0].reg_size;
- flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) |
- (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL);
- flash.write_size = sdev->reg_addrs[1].reg_size;
- }
- flash.busy = 0;
- break;
- }
- }
- if (!sdev) {
-#ifdef CONFIG_PCI
- const struct linux_prom_registers *ebus_regs;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_node->name, "flashprom"))
- goto ebus_done;
- }
- }
- ebus_done:
- if (!edev)
- return -ENODEV;
-
- ebus_regs = of_get_property(edev->prom_node, "reg", &len);
- if (!ebus_regs || (len % sizeof(regs[0])) != 0) {
- printk("flash: Strange reg property size %d\n", len);
- return -ENODEV;
- }
-
- nregs = len / sizeof(ebus_regs[0]);
+ struct device_node *dp = op->node;
+ struct device_node *parent;
- flash.read_base = edev->resource[0].start;
- flash.read_size = ebus_regs[0].reg_size;
+ parent = dp->parent;
- if (nregs == 1) {
- flash.write_base = edev->resource[0].start;
- flash.write_size = ebus_regs[0].reg_size;
- } else if (nregs == 2) {
- flash.write_base = edev->resource[1].start;
- flash.write_size = ebus_regs[1].reg_size;
- } else {
- printk("flash: Strange number of regs %d\n", nregs);
- return -ENODEV;
- }
-
- flash.busy = 0;
-
-#else
+ if (strcmp(parent->name, "sbus") &&
+ strcmp(parent->name, "sbi") &&
+ strcmp(parent->name, "ebus"))
return -ENODEV;
-#endif
+
+ flash.read_base = op->resource[0].start;
+ flash.read_size = resource_size(&op->resource[0]);
+ if (op->resource[1].flags) {
+ flash.write_base = op->resource[1].start;
+ flash.write_size = resource_size(&op->resource[1]);
+ } else {
+ flash.write_base = op->resource[0].start;
+ flash.write_size = resource_size(&op->resource[0]);
}
+ flash.busy = 0;
- printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n",
+ printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n",
+ op->node->full_name,
flash.read_base, flash.read_size,
flash.write_base, flash.write_size);
- err = misc_register(&flash_dev);
- if (err) {
- printk(KERN_ERR "flash: unable to get misc minor\n");
- return err;
- }
+ return misc_register(&flash_dev);
+}
+
+static int __devexit flash_remove(struct of_device *op)
+{
+ misc_deregister(&flash_dev);
return 0;
}
+static const struct of_device_id flash_match[] = {
+ {
+ .name = "flashprom",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, flash_match);
+
+static struct of_platform_driver flash_driver = {
+ .name = "flash",
+ .match_table = flash_match,
+ .probe = flash_probe,
+ .remove = __devexit_p(flash_remove),
+};
+
+static int __init flash_init(void)
+{
+ return of_register_driver(&flash_driver, &of_bus_type);
+}
+
static void __exit flash_cleanup(void)
{
- misc_deregister(&flash_dev);
+ of_unregister_driver(&flash_driver);
}
module_init(flash_init);
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
deleted file mode 100644
index b0429917154..00000000000
--- a/drivers/sbus/char/rtc.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* $Id: rtc.c,v 1.28 2001/10/08 22:19:51 davem Exp $
- *
- * Linux/SPARC Real Time Clock Driver
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- *
- * This is a little driver that lets a user-level program access
- * the SPARC Mostek real time clock chip. It is no use unless you
- * use the modified clock utility.
- *
- * Get the modified clock utility from:
- * ftp://vger.kernel.org/pub/linux/Sparc/userland/clock.c
- */
-
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/mostek.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/rtc.h>
-
-static int rtc_busy = 0;
-
-/* This is the structure layout used by drivers/char/rtc.c, we
- * support that driver's ioctls so that things are less messy in
- * userspace.
- */
-struct rtc_time_generic {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_wday;
- int tm_yday;
- int tm_isdst;
-};
-#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
-#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
-#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
-#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
-#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
-#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
-#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */
-#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */
-#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */
-#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */
-#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */
-#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */
-#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
-#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
-#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
-#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
-#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
-#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
-#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
-#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
-
-/* Retrieve the current date and time from the real time clock. */
-static void get_rtc_time(struct rtc_time *t)
-{
- void __iomem *regs = mstk48t02_regs;
- u8 tmp;
-
- spin_lock_irq(&mostek_lock);
-
- tmp = mostek_read(regs + MOSTEK_CREG);
- tmp |= MSTK_CREG_READ;
- mostek_write(regs + MOSTEK_CREG, tmp);
-
- t->sec = MSTK_REG_SEC(regs);
- t->min = MSTK_REG_MIN(regs);
- t->hour = MSTK_REG_HOUR(regs);
- t->dow = MSTK_REG_DOW(regs);
- t->dom = MSTK_REG_DOM(regs);
- t->month = MSTK_REG_MONTH(regs);
- t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) );
-
- tmp = mostek_read(regs + MOSTEK_CREG);
- tmp &= ~MSTK_CREG_READ;
- mostek_write(regs + MOSTEK_CREG, tmp);
-
- spin_unlock_irq(&mostek_lock);
-}
-
-/* Set the current date and time inthe real time clock. */
-void set_rtc_time(struct rtc_time *t)
-{
- void __iomem *regs = mstk48t02_regs;
- u8 tmp;
-
- spin_lock_irq(&mostek_lock);
-
- tmp = mostek_read(regs + MOSTEK_CREG);
- tmp |= MSTK_CREG_WRITE;
- mostek_write(regs + MOSTEK_CREG, tmp);
-
- MSTK_SET_REG_SEC(regs,t->sec);
- MSTK_SET_REG_MIN(regs,t->min);
- MSTK_SET_REG_HOUR(regs,t->hour);
- MSTK_SET_REG_DOW(regs,t->dow);
- MSTK_SET_REG_DOM(regs,t->dom);
- MSTK_SET_REG_MONTH(regs,t->month);
- MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO);
-
- tmp = mostek_read(regs + MOSTEK_CREG);
- tmp &= ~MSTK_CREG_WRITE;
- mostek_write(regs + MOSTEK_CREG, tmp);
-
- spin_unlock_irq(&mostek_lock);
-}
-
-static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm)
-{
- struct rtc_time_generic __user *utm = argp;
-
- if (__put_user(tm->sec, &utm->tm_sec) ||
- __put_user(tm->min, &utm->tm_min) ||
- __put_user(tm->hour, &utm->tm_hour) ||
- __put_user(tm->dom, &utm->tm_mday) ||
- __put_user(tm->month, &utm->tm_mon) ||
- __put_user(tm->year, &utm->tm_year) ||
- __put_user(tm->dow, &utm->tm_wday) ||
- __put_user(0, &utm->tm_yday) ||
- __put_user(0, &utm->tm_isdst))
- return -EFAULT;
-
- return 0;
-}
-
-static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp)
-{
- struct rtc_time_generic __user *utm = argp;
-
- if (__get_user(tm->sec, &utm->tm_sec) ||
- __get_user(tm->min, &utm->tm_min) ||
- __get_user(tm->hour, &utm->tm_hour) ||
- __get_user(tm->dom, &utm->tm_mday) ||
- __get_user(tm->month, &utm->tm_mon) ||
- __get_user(tm->year, &utm->tm_year) ||
- __get_user(tm->dow, &utm->tm_wday))
- return -EFAULT;
-
- return 0;
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct rtc_time rtc_tm;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- /* No interrupt support, return an error
- * compatible with drivers/char/rtc.c
- */
- case RTC_AIE_OFF:
- case RTC_AIE_ON:
- case RTC_PIE_OFF:
- case RTC_PIE_ON:
- case RTC_UIE_OFF:
- case RTC_UIE_ON:
- case RTC_IRQP_READ:
- case RTC_IRQP_SET:
- case RTC_EPOCH_SET:
- case RTC_EPOCH_READ:
- return -EINVAL;
-
- case RTCGET:
- case RTC_RD_TIME:
- memset(&rtc_tm, 0, sizeof(struct rtc_time));
- get_rtc_time(&rtc_tm);
-
- if (cmd == RTCGET) {
- if (copy_to_user(argp, &rtc_tm,
- sizeof(struct rtc_time)))
- return -EFAULT;
- } else if (put_rtc_time_generic(argp, &rtc_tm))
- return -EFAULT;
-
- return 0;
-
-
- case RTCSET:
- case RTC_SET_TIME:
- if (!capable(CAP_SYS_TIME))
- return -EPERM;
-
- if (cmd == RTCSET) {
- if (copy_from_user(&rtc_tm, argp,
- sizeof(struct rtc_time)))
- return -EFAULT;
- } else if (get_rtc_time_generic(&rtc_tm, argp))
- return -EFAULT;
-
- set_rtc_time(&rtc_tm);
-
- return 0;
-
- default:
- return -EINVAL;
- }
-}
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
- int ret;
-
- lock_kernel();
- spin_lock_irq(&mostek_lock);
- if (rtc_busy) {
- ret = -EBUSY;
- } else {
- rtc_busy = 1;
- ret = 0;
- }
- spin_unlock_irq(&mostek_lock);
- unlock_kernel();
-
- return ret;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
- rtc_busy = 0;
-
- return 0;
-}
-
-static const struct file_operations rtc_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
-};
-
-static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
-
-static int __init rtc_sun_init(void)
-{
- int error;
-
- /* It is possible we are being driven by some other RTC chip
- * and thus another RTC driver is handling things.
- */
- if (!mstk48t02_regs)
- return -ENODEV;
-
- error = misc_register(&rtc_dev);
- if (error) {
- printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n");
- return error;
- }
- printk("rtc_sun_init: Registered Mostek RTC driver.\n");
-
- return 0;
-}
-
-static void __exit rtc_sun_cleanup(void)
-{
- misc_deregister(&rtc_dev);
-}
-
-module_init(rtc_sun_init);
-module_exit(rtc_sun_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 777637594ac..27993c37775 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -1,7 +1,7 @@
-/* $Id: uctrl.c,v 1.12 2001/10/08 22:19:51 davem Exp $
- * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
+/* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
*
* Copyright 1999 Derrick J Brashear (shadow@dementia.org)
+ * Copyright 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -14,6 +14,8 @@
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -21,7 +23,6 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/sbus.h>
#define UCTRL_MINOR 174
@@ -33,26 +34,26 @@
#endif
struct uctrl_regs {
- volatile u32 uctrl_intr;
- volatile u32 uctrl_data;
- volatile u32 uctrl_stat;
- volatile u32 uctrl_xxx[5];
+ u32 uctrl_intr;
+ u32 uctrl_data;
+ u32 uctrl_stat;
+ u32 uctrl_xxx[5];
};
struct ts102_regs {
- volatile u32 card_a_intr;
- volatile u32 card_a_stat;
- volatile u32 card_a_ctrl;
- volatile u32 card_a_xxx;
- volatile u32 card_b_intr;
- volatile u32 card_b_stat;
- volatile u32 card_b_ctrl;
- volatile u32 card_b_xxx;
- volatile u32 uctrl_intr;
- volatile u32 uctrl_data;
- volatile u32 uctrl_stat;
- volatile u32 uctrl_xxx;
- volatile u32 ts102_xxx[4];
+ u32 card_a_intr;
+ u32 card_a_stat;
+ u32 card_a_ctrl;
+ u32 card_a_xxx;
+ u32 card_b_intr;
+ u32 card_b_stat;
+ u32 card_b_ctrl;
+ u32 card_b_xxx;
+ u32 uctrl_intr;
+ u32 uctrl_data;
+ u32 uctrl_stat;
+ u32 uctrl_xxx;
+ u32 ts102_xxx[4];
};
/* Bits for uctrl_intr register */
@@ -186,17 +187,15 @@ enum uctrl_opcode {
POWER_RESTART=0x83,
};
-struct uctrl_driver {
- struct uctrl_regs *regs;
+static struct uctrl_driver {
+ struct uctrl_regs __iomem *regs;
int irq;
int pending;
struct uctrl_status status;
-};
-
-static struct uctrl_driver drv;
+} *global_driver;
-static void uctrl_get_event_status(void);
-static void uctrl_get_external_status(void);
+static void uctrl_get_event_status(struct uctrl_driver *);
+static void uctrl_get_external_status(struct uctrl_driver *);
static int
uctrl_ioctl(struct inode *inode, struct file *file,
@@ -213,16 +212,14 @@ static int
uctrl_open(struct inode *inode, struct file *file)
{
lock_kernel();
- uctrl_get_event_status();
- uctrl_get_external_status();
+ uctrl_get_event_status(global_driver);
+ uctrl_get_external_status(global_driver);
unlock_kernel();
return 0;
}
static irqreturn_t uctrl_interrupt(int irq, void *dev_id)
{
- struct uctrl_driver *driver = (struct uctrl_driver *)dev_id;
- printk("in uctrl_interrupt\n");
return IRQ_HANDLED;
}
@@ -244,11 +241,11 @@ static struct miscdevice uctrl_dev = {
{ \
unsigned int i; \
for (i = 0; i < 10000; i++) { \
- if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \
+ if (UCTRL_STAT_TXNF_STA & sbus_readl(&driver->regs->uctrl_stat)) \
break; \
} \
dprintk(("write data 0x%02x\n", value)); \
- driver->regs->uctrl_data = value; \
+ sbus_writel(value, &driver->regs->uctrl_data); \
}
/* Wait for something to read, read it, then clear the bit */
@@ -257,24 +254,23 @@ static struct miscdevice uctrl_dev = {
unsigned int i; \
value = 0; \
for (i = 0; i < 10000; i++) { \
- if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \
+ if ((UCTRL_STAT_RXNE_STA & sbus_readl(&driver->regs->uctrl_stat)) == 0) \
break; \
udelay(1); \
} \
- value = driver->regs->uctrl_data; \
+ value = sbus_readl(&driver->regs->uctrl_data); \
dprintk(("read data 0x%02x\n", value)); \
- driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \
+ sbus_writel(UCTRL_STAT_RXNE_STA, &driver->regs->uctrl_stat); \
}
-static void uctrl_do_txn(struct uctrl_txn *txn)
+static void uctrl_do_txn(struct uctrl_driver *driver, struct uctrl_txn *txn)
{
- struct uctrl_driver *driver = &drv;
int stat, incnt, outcnt, bytecnt, intr;
u32 byte;
- stat = driver->regs->uctrl_stat;
- intr = driver->regs->uctrl_intr;
- driver->regs->uctrl_stat = stat;
+ stat = sbus_readl(&driver->regs->uctrl_stat);
+ intr = sbus_readl(&driver->regs->uctrl_intr);
+ sbus_writel(stat, &driver->regs->uctrl_stat);
dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr));
@@ -305,9 +301,8 @@ static void uctrl_do_txn(struct uctrl_txn *txn)
}
}
-static void uctrl_get_event_status(void)
+static void uctrl_get_event_status(struct uctrl_driver *driver)
{
- struct uctrl_driver *driver = &drv;
struct uctrl_txn txn;
u8 outbits[2];
@@ -317,7 +312,7 @@ static void uctrl_get_event_status(void)
txn.inbuf = NULL;
txn.outbuf = outbits;
- uctrl_do_txn(&txn);
+ uctrl_do_txn(driver, &txn);
dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff)));
driver->status.event_status =
@@ -325,9 +320,8 @@ static void uctrl_get_event_status(void)
dprintk(("ev is %x\n", driver->status.event_status));
}
-static void uctrl_get_external_status(void)
+static void uctrl_get_external_status(struct uctrl_driver *driver)
{
- struct uctrl_driver *driver = &drv;
struct uctrl_txn txn;
u8 outbits[2];
int i, v;
@@ -338,7 +332,7 @@ static void uctrl_get_external_status(void)
txn.inbuf = NULL;
txn.outbuf = outbits;
- uctrl_do_txn(&txn);
+ uctrl_do_txn(driver, &txn);
dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff)));
driver->status.external_status =
@@ -354,71 +348,101 @@ static void uctrl_get_external_status(void)
}
-static int __init ts102_uctrl_init(void)
+static int __devinit uctrl_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct uctrl_driver *driver = &drv;
- int len;
- struct linux_prom_irqs tmp_irq[2];
- unsigned int vaddr[2] = { 0, 0 };
- int tmpnode, uctrlnode = prom_getchild(prom_root_node);
- int err;
+ struct uctrl_driver *p;
+ int err = -ENOMEM;
- tmpnode = prom_searchsiblings(uctrlnode, "obio");
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ printk(KERN_ERR "uctrl: Unable to allocate device struct.\n");
+ goto out;
+ }
- if (tmpnode)
- uctrlnode = prom_getchild(tmpnode);
+ p->regs = of_ioremap(&op->resource[0], 0,
+ resource_size(&op->resource[0]),
+ "uctrl");
+ if (!p->regs) {
+ printk(KERN_ERR "uctrl: Unable to map registers.\n");
+ goto out_free;
+ }
- uctrlnode = prom_searchsiblings(uctrlnode, "uctrl");
+ p->irq = op->irqs[0];
+ err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p);
+ if (err) {
+ printk(KERN_ERR "uctrl: Unable to register irq.\n");
+ goto out_iounmap;
+ }
- if (!uctrlnode)
- return -ENODEV;
+ err = misc_register(&uctrl_dev);
+ if (err) {
+ printk(KERN_ERR "uctrl: Unable to register misc device.\n");
+ goto out_free_irq;
+ }
- /* the prom mapped it for us */
- len = prom_getproperty(uctrlnode, "address", (void *) vaddr,
- sizeof(vaddr));
- driver->regs = (struct uctrl_regs *)vaddr[0];
+ sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr);
+ printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n",
+ op->node->full_name, p->regs, p->irq);
+ uctrl_get_event_status(p);
+ uctrl_get_external_status(p);
- len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq,
- sizeof(tmp_irq));
+ dev_set_drvdata(&op->dev, p);
+ global_driver = p;
- /* Flush device */
- READUCTLDATA(len);
+out:
+ return err;
- if(!driver->irq)
- driver->irq = tmp_irq[0].pri;
+out_free_irq:
+ free_irq(p->irq, p);
- err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
- if (err) {
- printk("%s: unable to register irq %d\n",
- __func__, driver->irq);
- return err;
- }
+out_iounmap:
+ of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0]));
- if (misc_register(&uctrl_dev)) {
- printk("%s: unable to get misc minor %d\n",
- __func__, uctrl_dev.minor);
- free_irq(driver->irq, driver);
- return -ENODEV;
- }
+out_free:
+ kfree(p);
+ goto out;
+}
- driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK;
- printk("uctrl: 0x%p (irq %d)\n", driver->regs, driver->irq);
- uctrl_get_event_status();
- uctrl_get_external_status();
- return 0;
+static int __devexit uctrl_remove(struct of_device *op)
+{
+ struct uctrl_driver *p = dev_get_drvdata(&op->dev);
+
+ if (p) {
+ misc_deregister(&uctrl_dev);
+ free_irq(p->irq, p);
+ of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0]));
+ kfree(p);
+ }
+ return 0;
}
-static void __exit ts102_uctrl_cleanup(void)
+static const struct of_device_id uctrl_match[] = {
+ {
+ .name = "uctrl",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, uctrl_match);
+
+static struct of_platform_driver uctrl_driver = {
+ .name = "uctrl",
+ .match_table = uctrl_match,
+ .probe = uctrl_probe,
+ .remove = __devexit_p(uctrl_remove),
+};
+
+
+static int __init uctrl_init(void)
{
- struct uctrl_driver *driver = &drv;
+ return of_register_driver(&uctrl_driver, &of_bus_type);
+}
- misc_deregister(&uctrl_dev);
- if (driver->irq)
- free_irq(driver->irq, driver);
- if (driver->regs)
- driver->regs = NULL;
+static void __exit uctrl_exit(void)
+{
+ of_unregister_driver(&uctrl_driver);
}
-module_init(ts102_uctrl_init);
-module_exit(ts102_uctrl_cleanup);
+module_init(uctrl_init);
+module_exit(uctrl_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
deleted file mode 100644
index a5240c52aa0..00000000000
--- a/drivers/sbus/char/vfc.h
+++ /dev/null
@@ -1,171 +0,0 @@
-#ifndef _LINUX_VFC_H_
-#define _LINUX_VFC_H_
-
-/*
- * The control register for the vfc is at offset 0x4000
- * The first field ram bank is located at offset 0x5000
- * The second field ram bank is at offset 0x7000
- * i2c_reg address the Phillips PCF8584(see notes in vfc_i2c.c)
- * data and transmit register.
- * i2c_s1 controls register s1 of the PCF8584
- * i2c_write seems to be similar to i2c_write but I am not
- * quite sure why sun uses it
- *
- * I am also not sure whether or not you can read the fram bank as a
- * whole or whether you must read each word individually from offset
- * 0x5000 as soon as I figure it out I will update this file */
-
-struct vfc_regs {
- char pad1[0x4000];
- unsigned int control; /* Offset 0x4000 */
- char pad2[0xffb]; /* from offset 0x4004 to 0x5000 */
- unsigned int fram_bank1; /* Offset 0x5000 */
- char pad3[0xffb]; /* from offset 0x5004 to 0x6000 */
- unsigned int i2c_reg; /* Offset 0x6000 */
- unsigned int i2c_magic2; /* Offset 0x6004 */
- unsigned int i2c_s1; /* Offset 0x6008 */
- unsigned int i2c_write; /* Offset 0x600c */
- char pad4[0xff0]; /* from offset 0x6010 to 0x7000 */
- unsigned int fram_bank2; /* Offset 0x7000 */
- char pad5[0x1000];
-};
-
-#define VFC_SAA9051_NR (13)
-#define VFC_SAA9051_ADDR (0x8a)
- /* The saa9051 returns the following for its status
- * bit 0 - 0
- * bit 1 - SECAM color detected (1=found,0=not found)
- * bit 2 - COLOR detected (1=found,0=not found)
- * bit 3 - 0
- * bit 4 - Field frequency bit (1=60Hz (NTSC), 0=50Hz (PAL))
- * bit 5 - 1
- * bit 6 - horizontal frequency lock (1=transmitter found,
- * 0=no transmitter)
- * bit 7 - Power on reset bit (1=reset,0=at least one successful
- * read of the status byte)
- */
-
-#define VFC_SAA9051_PONRES (0x80)
-#define VFC_SAA9051_HLOCK (0x40)
-#define VFC_SAA9051_FD (0x10)
-#define VFC_SAA9051_CD (0x04)
-#define VFC_SAA9051_CS (0x02)
-
-
-/* The various saa9051 sub addresses */
-
-#define VFC_SAA9051_IDEL (0)
-#define VFC_SAA9051_HSY_START (1)
-#define VFC_SAA9051_HSY_STOP (2)
-#define VFC_SAA9051_HC_START (3)
-#define VFC_SAA9051_HC_STOP (4)
-#define VFC_SAA9051_HS_START (5)
-#define VFC_SAA9051_HORIZ_PEAK (6)
-#define VFC_SAA9051_HUE (7)
-#define VFC_SAA9051_C1 (8)
-#define VFC_SAA9051_C2 (9)
-#define VFC_SAA9051_C3 (0xa)
-#define VFC_SAA9051_SECAM_DELAY (0xb)
-
-
-/* Bit settings for saa9051 sub address 0x06 */
-
-#define VFC_SAA9051_AP1 (0x01)
-#define VFC_SAA9051_AP2 (0x02)
-#define VFC_SAA9051_COR1 (0x04)
-#define VFC_SAA9051_COR2 (0x08)
-#define VFC_SAA9051_BP1 (0x10)
-#define VFC_SAA9051_BP2 (0x20)
-#define VFC_SAA9051_PF (0x40)
-#define VFC_SAA9051_BY (0x80)
-
-
-/* Bit settings for saa9051 sub address 0x08 */
-
-#define VFC_SAA9051_CCFR0 (0x01)
-#define VFC_SAA9051_CCFR1 (0x02)
-#define VFC_SAA9051_YPN (0x04)
-#define VFC_SAA9051_ALT (0x08)
-#define VFC_SAA9051_CO (0x10)
-#define VFC_SAA9051_VTR (0x20)
-#define VFC_SAA9051_FS (0x40)
-#define VFC_SAA9051_HPLL (0x80)
-
-
-/* Bit settings for saa9051 sub address 9 */
-
-#define VFC_SAA9051_SS0 (0x01)
-#define VFC_SAA9051_SS1 (0x02)
-#define VFC_SAA9051_AFCC (0x04)
-#define VFC_SAA9051_CI (0x08)
-#define VFC_SAA9051_SA9D4 (0x10) /* Don't care bit */
-#define VFC_SAA9051_OEC (0x20)
-#define VFC_SAA9051_OEY (0x40)
-#define VFC_SAA9051_VNL (0x80)
-
-
-/* Bit settings for saa9051 sub address 0x0A */
-
-#define VFC_SAA9051_YDL0 (0x01)
-#define VFC_SAA9051_YDL1 (0x02)
-#define VFC_SAA9051_YDL2 (0x04)
-#define VFC_SAA9051_SS2 (0x08)
-#define VFC_SAA9051_SS3 (0x10)
-#define VFC_SAA9051_YC (0x20)
-#define VFC_SAA9051_CT (0x40)
-#define VFC_SAA9051_SYC (0x80)
-
-
-#define VFC_SAA9051_SA(a,b) ((a)->saa9051_state_array[(b)+1])
-#define vfc_update_saa9051(a) (vfc_i2c_sendbuf((a),VFC_SAA9051_ADDR,\
- (a)->saa9051_state_array,\
- VFC_SAA9051_NR))
-
-
-struct vfc_dev {
- volatile struct vfc_regs __iomem *regs;
- struct vfc_regs *phys_regs;
- unsigned int control_reg;
- struct mutex device_lock_mtx;
- int instance;
- int busy;
- unsigned long which_io;
- unsigned char saa9051_state_array[VFC_SAA9051_NR];
-};
-
-void captstat_reset(struct vfc_dev *);
-void memptr_reset(struct vfc_dev *);
-
-int vfc_pcf8584_init(struct vfc_dev *);
-void vfc_i2c_delay_no_busy(struct vfc_dev *, unsigned long);
-void vfc_i2c_delay(struct vfc_dev *);
-int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ;
-int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ;
-int vfc_i2c_reset_bus(struct vfc_dev *);
-int vfc_init_i2c_bus(struct vfc_dev *);
-
-#define VFC_CONTROL_DIAGMODE 0x10000000
-#define VFC_CONTROL_MEMPTR 0x20000000
-#define VFC_CONTROL_CAPTURE 0x02000000
-#define VFC_CONTROL_CAPTRESET 0x04000000
-
-#define VFC_STATUS_CAPTURE 0x08000000
-
-#ifdef VFC_IOCTL_DEBUG
-#define VFC_IOCTL_DEBUG_PRINTK(a) printk a
-#else
-#define VFC_IOCTL_DEBUG_PRINTK(a)
-#endif
-
-#ifdef VFC_I2C_DEBUG
-#define VFC_I2C_DEBUG_PRINTK(a) printk a
-#else
-#define VFC_I2C_DEBUG_PRINTK(a)
-#endif
-
-#endif /* _LINUX_VFC_H_ */
-
-
-
-
-
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
deleted file mode 100644
index 25181bb7d62..00000000000
--- a/drivers/sbus/char/vfc_dev.c
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * drivers/sbus/char/vfc_dev.c
- *
- * Driver for the Videopix Frame Grabber.
- *
- * In order to use the VFC you need to program the video controller
- * chip. This chip is the Phillips SAA9051. You need to call their
- * documentation ordering line to get the docs.
- *
- * There is very little documentation on the VFC itself. There is
- * some useful info that can be found in the manuals that come with
- * the card. I will hopefully write some better docs at a later date.
- *
- * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/sbus.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-
-#define VFC_MAJOR (60)
-
-#if 0
-#define VFC_IOCTL_DEBUG
-#endif
-
-#include "vfc.h"
-#include <asm/vfc_ioctls.h>
-
-static const struct file_operations vfc_fops;
-static struct vfc_dev **vfc_dev_lst;
-static char vfcstr[]="vfc";
-static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
- 0x00, 0x64, 0x72, 0x52,
- 0x36, 0x18, 0xff, 0x20,
- 0xfc, 0x77, 0xe3, 0x50,
- 0x3e
-};
-
-static void vfc_lock_device(struct vfc_dev *dev)
-{
- mutex_lock(&dev->device_lock_mtx);
-}
-
-static void vfc_unlock_device(struct vfc_dev *dev)
-{
- mutex_unlock(&dev->device_lock_mtx);
-}
-
-
-static void vfc_captstat_reset(struct vfc_dev *dev)
-{
- dev->control_reg |= VFC_CONTROL_CAPTRESET;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg &= ~VFC_CONTROL_CAPTRESET;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg |= VFC_CONTROL_CAPTRESET;
- sbus_writel(dev->control_reg, &dev->regs->control);
-}
-
-static void vfc_memptr_reset(struct vfc_dev *dev)
-{
- dev->control_reg |= VFC_CONTROL_MEMPTR;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg &= ~VFC_CONTROL_MEMPTR;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg |= VFC_CONTROL_MEMPTR;
- sbus_writel(dev->control_reg, &dev->regs->control);
-}
-
-static int vfc_csr_init(struct vfc_dev *dev)
-{
- dev->control_reg = 0x80000000;
- sbus_writel(dev->control_reg, &dev->regs->control);
- udelay(200);
- dev->control_reg &= ~0x80000000;
- sbus_writel(dev->control_reg, &dev->regs->control);
- udelay(100);
- sbus_writel(0x0f000000, &dev->regs->i2c_magic2);
-
- vfc_memptr_reset(dev);
-
- dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
- dev->control_reg &= ~VFC_CONTROL_CAPTURE;
- dev->control_reg |= 0x40000000;
- sbus_writel(dev->control_reg, &dev->regs->control);
-
- vfc_captstat_reset(dev);
-
- return 0;
-}
-
-static int vfc_saa9051_init(struct vfc_dev *dev)
-{
- int i;
-
- for (i = 0; i < VFC_SAA9051_NR; i++)
- dev->saa9051_state_array[i] = saa9051_init_array[i];
-
- vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR,
- dev->saa9051_state_array, VFC_SAA9051_NR);
- return 0;
-}
-
-static int init_vfc_hw(struct vfc_dev *dev)
-{
- vfc_lock_device(dev);
- vfc_csr_init(dev);
-
- vfc_pcf8584_init(dev);
- vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic
- sun code above*/
- vfc_saa9051_init(dev);
- vfc_unlock_device(dev);
- return 0;
-}
-
-static int init_vfc_devstruct(struct vfc_dev *dev, int instance)
-{
- dev->instance=instance;
- mutex_init(&dev->device_lock_mtx);
- dev->control_reg=0;
- dev->busy=0;
- return 0;
-}
-
-static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev,
- int instance)
-{
- if(dev == NULL) {
- printk(KERN_ERR "VFC: Bogus pointer passed\n");
- return -ENOMEM;
- }
- printk("Initializing vfc%d\n",instance);
- dev->regs = NULL;
- dev->regs = (volatile struct vfc_regs __iomem *)
- sbus_ioremap(&sdev->resource[0], 0,
- sizeof(struct vfc_regs), vfcstr);
- dev->which_io = sdev->reg_addrs[0].which_io;
- dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr;
- if (dev->regs == NULL)
- return -EIO;
-
- printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n",
- instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);
-
- if (init_vfc_devstruct(dev, instance))
- return -EINVAL;
- if (init_vfc_hw(dev))
- return -EIO;
- return 0;
-}
-
-
-static struct vfc_dev *vfc_get_dev_ptr(int instance)
-{
- return vfc_dev_lst[instance];
-}
-
-static DEFINE_SPINLOCK(vfc_dev_lock);
-
-static int vfc_open(struct inode *inode, struct file *file)
-{
- struct vfc_dev *dev;
-
- lock_kernel();
- spin_lock(&vfc_dev_lock);
- dev = vfc_get_dev_ptr(iminor(inode));
- if (dev == NULL) {
- spin_unlock(&vfc_dev_lock);
- unlock_kernel();
- return -ENODEV;
- }
- if (dev->busy) {
- spin_unlock(&vfc_dev_lock);
- unlock_kernel();
- return -EBUSY;
- }
-
- dev->busy = 1;
- spin_unlock(&vfc_dev_lock);
-
- vfc_lock_device(dev);
-
- vfc_csr_init(dev);
- vfc_pcf8584_init(dev);
- vfc_init_i2c_bus(dev);
- vfc_saa9051_init(dev);
- vfc_memptr_reset(dev);
- vfc_captstat_reset(dev);
-
- vfc_unlock_device(dev);
- unlock_kernel();
- return 0;
-}
-
-static int vfc_release(struct inode *inode,struct file *file)
-{
- struct vfc_dev *dev;
-
- spin_lock(&vfc_dev_lock);
- dev = vfc_get_dev_ptr(iminor(inode));
- if (!dev || !dev->busy) {
- spin_unlock(&vfc_dev_lock);
- return -EINVAL;
- }
- dev->busy = 0;
- spin_unlock(&vfc_dev_lock);
- return 0;
-}
-
-static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp)
-{
- struct vfc_debug_inout inout;
- unsigned char *buffer;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- switch(cmd) {
- case VFC_I2C_SEND:
- if(copy_from_user(&inout, argp, sizeof(inout)))
- return -EFAULT;
-
- buffer = kmalloc(inout.len, GFP_KERNEL);
- if (buffer == NULL)
- return -ENOMEM;
-
- if(copy_from_user(buffer, inout.buffer, inout.len)) {
- kfree(buffer);
- return -EFAULT;
- }
-
-
- vfc_lock_device(dev);
- inout.ret=
- vfc_i2c_sendbuf(dev,inout.addr & 0xff,
- buffer,inout.len);
-
- if (copy_to_user(argp,&inout,sizeof(inout))) {
- vfc_unlock_device(dev);
- kfree(buffer);
- return -EFAULT;
- }
- vfc_unlock_device(dev);
-
- break;
- case VFC_I2C_RECV:
- if (copy_from_user(&inout, argp, sizeof(inout)))
- return -EFAULT;
-
- buffer = kzalloc(inout.len, GFP_KERNEL);
- if (buffer == NULL)
- return -ENOMEM;
-
- vfc_lock_device(dev);
- inout.ret=
- vfc_i2c_recvbuf(dev,inout.addr & 0xff
- ,buffer,inout.len);
- vfc_unlock_device(dev);
-
- if (copy_to_user(inout.buffer, buffer, inout.len)) {
- kfree(buffer);
- return -EFAULT;
- }
- if (copy_to_user(argp,&inout,sizeof(inout))) {
- kfree(buffer);
- return -EFAULT;
- }
- kfree(buffer);
- break;
- default:
- return -EINVAL;
- };
-
- return 0;
-}
-
-static int vfc_capture_start(struct vfc_dev *dev)
-{
- vfc_captstat_reset(dev);
- dev->control_reg = sbus_readl(&dev->regs->control);
- if((dev->control_reg & VFC_STATUS_CAPTURE)) {
- printk(KERN_ERR "vfc%d: vfc capture status not reset\n",
- dev->instance);
- return -EIO;
- }
-
- vfc_lock_device(dev);
- dev->control_reg &= ~VFC_CONTROL_CAPTURE;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg |= VFC_CONTROL_CAPTURE;
- sbus_writel(dev->control_reg, &dev->regs->control);
- dev->control_reg &= ~VFC_CONTROL_CAPTURE;
- sbus_writel(dev->control_reg, &dev->regs->control);
- vfc_unlock_device(dev);
-
- return 0;
-}
-
-static int vfc_capture_poll(struct vfc_dev *dev)
-{
- int timeout = 1000;
-
- while (!timeout--) {
- if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE)
- break;
- vfc_i2c_delay_no_busy(dev, 100);
- }
- if(!timeout) {
- printk(KERN_WARNING "vfc%d: capture timed out\n",
- dev->instance);
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-
-
-static int vfc_set_control_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
-{
- int setcmd, ret = 0;
-
- if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int)))
- return -EFAULT;
-
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n",
- dev->instance,setcmd));
-
- switch(setcmd) {
- case MEMPRST:
- vfc_lock_device(dev);
- vfc_memptr_reset(dev);
- vfc_unlock_device(dev);
- ret=0;
- break;
- case CAPTRCMD:
- vfc_capture_start(dev);
- vfc_capture_poll(dev);
- break;
- case DIAGMODE:
- if(capable(CAP_SYS_ADMIN)) {
- vfc_lock_device(dev);
- dev->control_reg |= VFC_CONTROL_DIAGMODE;
- sbus_writel(dev->control_reg, &dev->regs->control);
- vfc_unlock_device(dev);
- ret = 0;
- } else {
- ret = -EPERM;
- }
- break;
- case NORMMODE:
- vfc_lock_device(dev);
- dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
- sbus_writel(dev->control_reg, &dev->regs->control);
- vfc_unlock_device(dev);
- ret = 0;
- break;
- case CAPTRSTR:
- vfc_capture_start(dev);
- ret = 0;
- break;
- case CAPTRWAIT:
- vfc_capture_poll(dev);
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- break;
- };
-
- return ret;
-}
-
-
-static int vfc_port_change_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
-{
- int ret = 0;
- int cmd;
-
- if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) {
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
- "vfc_port_change_ioctl\n",
- dev->instance));
- return -EFAULT;
- }
-
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n",
- dev->instance, cmd));
-
- switch(cmd) {
- case 1:
- case 2:
- VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2;
- VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3;
- VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e;
- break;
- case 3:
- VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) =
- VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2;
- VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC;
- VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0;
- VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
- ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
- break;
- default:
- ret = -EINVAL;
- return ret;
- break;
- }
-
- switch(cmd) {
- case 1:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |=
- (VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
- break;
- case 2:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
- ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
- VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0;
- break;
- case 3:
- break;
- default:
- ret = -EINVAL;
- return ret;
- break;
- }
- VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2);
- ret=vfc_update_saa9051(dev);
- udelay(500);
- VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2);
- ret=vfc_update_saa9051(dev);
- return ret;
-}
-
-static int vfc_set_video_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
-{
- int ret = 0;
- int cmd;
-
- if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) {
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
- "vfc_set_video_ioctl\n",
- dev->instance));
- return ret;
- }
-
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n",
- dev->instance, cmd));
- switch(cmd) {
- case STD_NTSC:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT;
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN |
- VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS;
- ret = vfc_update_saa9051(dev);
- break;
- case STD_PAL:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN |
- VFC_SAA9051_CCFR1 |
- VFC_SAA9051_CCFR0 |
- VFC_SAA9051_FS);
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT;
- ret = vfc_update_saa9051(dev);
- break;
-
- case COLOR_ON:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO;
- VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &=
- ~(VFC_SAA9051_BY | VFC_SAA9051_PF);
- ret = vfc_update_saa9051(dev);
- break;
- case MONO:
- VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO);
- VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |=
- (VFC_SAA9051_BY | VFC_SAA9051_PF);
- ret = vfc_update_saa9051(dev);
- break;
- default:
- ret = -EINVAL;
- break;
- };
-
- return ret;
-}
-
-static int vfc_get_video_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
-{
- int ret = 0;
- unsigned int status = NO_LOCK;
- unsigned char buf[1];
-
- if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) {
- printk(KERN_ERR "vfc%d: Unable to get status\n",
- dev->instance);
- return -EIO;
- }
-
- if(buf[0] & VFC_SAA9051_HLOCK) {
- status = NO_LOCK;
- } else if(buf[0] & VFC_SAA9051_FD) {
- if(buf[0] & VFC_SAA9051_CD)
- status = NTSC_COLOR;
- else
- status = NTSC_NOCOLOR;
- } else {
- if(buf[0] & VFC_SAA9051_CD)
- status = PAL_COLOR;
- else
- status = PAL_NOCOLOR;
- }
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; "
- "buf[0]=%x\n", dev->instance, status, buf[0]));
-
- if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) {
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
- "vfc_get_video_ioctl\n",
- dev->instance));
- return ret;
- }
- return ret;
-}
-
-static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret = 0;
- unsigned int tmp;
- struct vfc_dev *dev;
- void __user *argp = (void __user *)arg;
-
- dev = vfc_get_dev_ptr(iminor(inode));
- if(dev == NULL)
- return -ENODEV;
-
- switch(cmd & 0x0000ffff) {
- case VFCGCTRL:
-#if 0
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance));
-#endif
- tmp = sbus_readl(&dev->regs->control);
- if(copy_to_user(argp, &tmp, sizeof(unsigned int))) {
- ret = -EFAULT;
- break;
- }
- ret = 0;
- break;
- case VFCSCTRL:
- ret = vfc_set_control_ioctl(inode, file, dev, arg);
- break;
- case VFCGVID:
- ret = vfc_get_video_ioctl(inode, file, dev, arg);
- break;
- case VFCSVID:
- ret = vfc_set_video_ioctl(inode, file, dev, arg);
- break;
- case VFCHUE:
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance));
- if(copy_from_user(&tmp,argp,sizeof(unsigned int))) {
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer "
- "to IOCTL(VFCHUE)", dev->instance));
- ret = -EFAULT;
- } else {
- VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp;
- vfc_update_saa9051(dev);
- ret = 0;
- }
- break;
- case VFCPORTCHG:
- ret = vfc_port_change_ioctl(inode, file, dev, arg);
- break;
- case VFCRDINFO:
- ret = -EINVAL;
- VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance));
- break;
- default:
- ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp);
- break;
- };
-
- return ret;
-}
-
-static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
-{
- unsigned int map_size, ret, map_offset;
- struct vfc_dev *dev;
-
- dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode));
- if(dev == NULL)
- return -ENODEV;
-
- map_size = vma->vm_end - vma->vm_start;
- if(map_size > sizeof(struct vfc_regs))
- map_size = sizeof(struct vfc_regs);
-
- vma->vm_flags |=
- (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
- map_offset = (unsigned int) (long)dev->phys_regs;
- ret = io_remap_pfn_range(vma, vma->vm_start,
- MK_IOSPACE_PFN(dev->which_io,
- map_offset >> PAGE_SHIFT),
- map_size, vma->vm_page_prot);
-
- if(ret)
- return -EAGAIN;
-
- return 0;
-}
-
-
-static const struct file_operations vfc_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = vfc_ioctl,
- .mmap = vfc_mmap,
- .open = vfc_open,
- .release = vfc_release,
-};
-
-static int vfc_probe(void)
-{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
- int ret;
- int instance = 0, cards = 0;
-
- for_all_sbusdev(sdev, sbus) {
- if (strcmp(sdev->prom_name, "vfc") == 0) {
- cards++;
- continue;
- }
- }
-
- if (!cards)
- return -ENODEV;
-
- vfc_dev_lst = kcalloc(cards + 1, sizeof(struct vfc_dev*), GFP_KERNEL);
- if (vfc_dev_lst == NULL)
- return -ENOMEM;
- vfc_dev_lst[cards] = NULL;
-
- ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
- if(ret) {
- printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR);
- kfree(vfc_dev_lst);
- return -EIO;
- }
- instance = 0;
- for_all_sbusdev(sdev, sbus) {
- if (strcmp(sdev->prom_name, "vfc") == 0) {
- vfc_dev_lst[instance]=(struct vfc_dev *)
- kmalloc(sizeof(struct vfc_dev), GFP_KERNEL);
- if (vfc_dev_lst[instance] == NULL)
- return -ENOMEM;
- ret = init_vfc_device(sdev,
- vfc_dev_lst[instance],
- instance);
- if(ret) {
- printk(KERN_ERR "Unable to initialize"
- " vfc%d device\n",
- instance);
- } else {
- }
-
- instance++;
- continue;
- }
- }
-
- return 0;
-}
-
-#ifdef MODULE
-int init_module(void)
-#else
-int vfc_init(void)
-#endif
-{
- return vfc_probe();
-}
-
-#ifdef MODULE
-static void deinit_vfc_device(struct vfc_dev *dev)
-{
- if(dev == NULL)
- return;
- sbus_iounmap(dev->regs, sizeof(struct vfc_regs));
- kfree(dev);
-}
-
-void cleanup_module(void)
-{
- struct vfc_dev **devp;
-
- unregister_chrdev(VFC_MAJOR,vfcstr);
-
- for (devp = vfc_dev_lst; *devp; devp++)
- deinit_vfc_device(*devp);
-
- kfree(vfc_dev_lst);
- return;
-}
-#endif
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
deleted file mode 100644
index 32b986e0ed7..00000000000
--- a/drivers/sbus/char/vfc_i2c.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * drivers/sbus/char/vfc_i2c.c
- *
- * Driver for the Videopix Frame Grabber.
- *
- * Functions that support the Phillips i2c(I squared C) bus on the vfc
- * Documentation for the Phillips I2C bus can be found on the
- * phillips home page
- *
- * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
- *
- */
-
-/* NOTE: It seems to me that the documentation regarding the
-pcd8584t/pcf8584 does not show the correct way to address the i2c bus.
-Based on the information on the I2C bus itself and the remainder of
-the Phillips docs the following algorithms appear to be correct. I am
-fairly certain that the flowcharts in the phillips docs are wrong. */
-
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/sbus.h>
-
-#if 0
-#define VFC_I2C_DEBUG
-#endif
-
-#include "vfc.h"
-#include "vfc_i2c.h"
-
-#define WRITE_S1(__val) \
- sbus_writel(__val, &dev->regs->i2c_s1)
-#define WRITE_REG(__val) \
- sbus_writel(__val, &dev->regs->i2c_reg)
-
-#define VFC_I2C_READ (0x1)
-#define VFC_I2C_WRITE (0x0)
-
-/******
- The i2c bus controller chip on the VFC is a pcd8584t, but
- phillips claims it doesn't exist. As far as I can tell it is
- identical to the PCF8584 so I treat it like it is the pcf8584.
-
- NOTE: The pcf8584 only cares
- about the msb of the word you feed it
-*****/
-
-int vfc_pcf8584_init(struct vfc_dev *dev)
-{
- /* This will also choose register S0_OWN so we can set it. */
- WRITE_S1(RESET);
-
- /* The pcf8584 shifts this value left one bit and uses
- * it as its i2c bus address.
- */
- WRITE_REG(0x55000000);
-
- /* This will set the i2c bus at the same speed sun uses,
- * and set another magic bit.
- */
- WRITE_S1(SELECT(S2));
- WRITE_REG(0x14000000);
-
- /* Enable the serial port, idle the i2c bus and set
- * the data reg to s0.
- */
- WRITE_S1(CLEAR_I2C_BUS);
- udelay(100);
- return 0;
-}
-
-void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs)
-{
- schedule_timeout_uninterruptible(usecs_to_jiffies(usecs));
-}
-
-void inline vfc_i2c_delay(struct vfc_dev *dev)
-{
- vfc_i2c_delay_no_busy(dev, 100);
-}
-
-int vfc_init_i2c_bus(struct vfc_dev *dev)
-{
- WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK);
- vfc_i2c_reset_bus(dev);
- return 0;
-}
-
-int vfc_i2c_reset_bus(struct vfc_dev *dev)
-{
- VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n",
- dev->instance));
- if(dev == NULL)
- return -EINVAL;
- if(dev->regs == NULL)
- return -EINVAL;
- WRITE_S1(SEND_I2C_STOP);
- WRITE_S1(SEND_I2C_STOP | ACK);
- vfc_i2c_delay(dev);
- WRITE_S1(CLEAR_I2C_BUS);
- VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n",
- dev->instance,
- sbus_readl(&dev->regs->i2c_s1)));
- return 0;
-}
-
-static int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
-{
- int timeout = 1000;
-
- while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) {
- if(!(timeout--))
- return -ETIMEDOUT;
- vfc_i2c_delay(dev);
- }
- return 0;
-}
-
-static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
-{
- int timeout = 1000;
- int s1;
-
- while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) {
- if (!(timeout--))
- return -ETIMEDOUT;
- vfc_i2c_delay(dev);
- }
- if (ack == VFC_I2C_ACK_CHECK) {
- if(s1 & LRB)
- return -EIO;
- }
- return 0;
-}
-
-#define SHIFT(a) ((a) << 24)
-static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr,
- char mode)
-{
- int ret, raddr;
-#if 1
- WRITE_S1(SEND_I2C_STOP | ACK);
- WRITE_S1(SELECT(S0) | ENABLE_SERIAL);
- vfc_i2c_delay(dev);
-#endif
-
- switch(mode) {
- case VFC_I2C_READ:
- raddr = SHIFT(((unsigned int)addr | 0x1));
- WRITE_REG(raddr);
- VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
- dev->instance, addr | 0x1));
- break;
- case VFC_I2C_WRITE:
- raddr = SHIFT((unsigned int)addr & ~0x1);
- WRITE_REG(raddr);
- VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n",
- dev->instance, addr & ~0x1));
- break;
- default:
- return -EINVAL;
- };
-
- WRITE_S1(SEND_I2C_START);
- vfc_i2c_delay(dev);
- ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait
- for the
- i2c send
- to finish
- here but
- Sun
- doesn't,
- hmm */
- if (ret) {
- printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n",
- dev->instance);
- return ret;
- } else if (mode == VFC_I2C_READ) {
- if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) {
- printk(KERN_WARNING
- "vfc%d: returned slave address "
- "mismatch(%x,%x)\n",
- dev->instance, raddr, ret);
- }
- }
- return 0;
-}
-
-static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
-{
- int ret;
- u32 val = SHIFT((unsigned int)*byte);
-
- WRITE_REG(val);
-
- ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK);
- switch(ret) {
- case -ETIMEDOUT:
- printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n",
- dev->instance);
- break;
- case -EIO:
- ret = XMIT_LAST_BYTE;
- break;
- default:
- break;
- };
-
- return ret;
-}
-
-static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte,
- int last)
-{
- int ret;
-
- if (last) {
- WRITE_REG(NEGATIVE_ACK);
- VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n",
- dev->instance));
- } else {
- WRITE_S1(ACK);
- }
-
- ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK);
- if(ret) {
- printk(KERN_ERR "vfc%d: "
- "VFC recv byte timed out\n",
- dev->instance);
- }
- *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24;
- return ret;
-}
-
-int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr,
- char *buf, int count)
-{
- int ret, last;
-
- if(!(count && buf && dev && dev->regs) )
- return -EINVAL;
-
- if ((ret = vfc_i2c_wait_for_bus(dev))) {
- printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
- return ret;
- }
-
- if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) {
- WRITE_S1(SEND_I2C_STOP);
- vfc_i2c_delay(dev);
- return ret;
- }
-
- last = 0;
- while (count--) {
- if (!count)
- last = 1;
- if ((ret = vfc_i2c_recv_byte(dev, buf, last))) {
- printk(KERN_ERR "vfc%d: "
- "VFC error while receiving byte\n",
- dev->instance);
- WRITE_S1(SEND_I2C_STOP);
- ret = -EINVAL;
- }
- buf++;
- }
- WRITE_S1(SEND_I2C_STOP | ACK);
- vfc_i2c_delay(dev);
- return ret;
-}
-
-int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr,
- char *buf, int count)
-{
- int ret;
-
- if (!(buf && dev && dev->regs))
- return -EINVAL;
-
- if ((ret = vfc_i2c_wait_for_bus(dev))) {
- printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
- return ret;
- }
-
- if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) {
- WRITE_S1(SEND_I2C_STOP);
- vfc_i2c_delay(dev);
- return ret;
- }
-
- while(count--) {
- ret = vfc_i2c_xmit_byte(dev, buf);
- switch(ret) {
- case XMIT_LAST_BYTE:
- VFC_I2C_DEBUG_PRINTK(("vfc%d: "
- "Receiver ended transmission with "
- " %d bytes remaining\n",
- dev->instance, count));
- ret = 0;
- goto done;
- break;
- case 0:
- break;
- default:
- printk(KERN_ERR "vfc%d: "
- "VFC error while sending byte\n", dev->instance);
- break;
- };
-
- buf++;
- }
-done:
- WRITE_S1(SEND_I2C_STOP | ACK);
- vfc_i2c_delay(dev);
- return ret;
-}
-
-
-
-
-
-
-
-
-
diff --git a/drivers/sbus/char/vfc_i2c.h b/drivers/sbus/char/vfc_i2c.h
deleted file mode 100644
index a2e6973209d..00000000000
--- a/drivers/sbus/char/vfc_i2c.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _LINUX_VFC_I2C_H_
-#define _LINUX_VFC_I2C_H_
-
-/* control bits */
-#define PIN (0x80000000)
-#define ESO (0x40000000)
-#define ES1 (0x20000000)
-#define ES2 (0x10000000)
-#define ENI (0x08000000)
-#define STA (0x04000000)
-#define STO (0x02000000)
-#define ACK (0x01000000)
-
-/* status bits */
-#define STS (0x20000000)
-#define BER (0x10000000)
-#define LRB (0x08000000)
-#define AAS (0x04000000)
-#define LAB (0x02000000)
-#define BB (0x01000000)
-
-#define SEND_I2C_START (PIN | ESO | STA)
-#define SEND_I2C_STOP (PIN | ESO | STO)
-#define CLEAR_I2C_BUS (PIN | ESO | ACK)
-#define NEGATIVE_ACK ((ESO) & ~ACK)
-
-#define SELECT(a) (a)
-#define S0 (PIN | ESO | ES1)
-#define S0_OWN (PIN)
-#define S2 (PIN | ES1)
-#define S3 (PIN | ES2)
-
-#define ENABLE_SERIAL (PIN | ESO)
-#define DISABLE_SERIAL (PIN)
-#define RESET (PIN)
-
-#define XMIT_LAST_BYTE (1)
-#define VFC_I2C_ACK_CHECK (1)
-#define VFC_I2C_NO_ACK_CHECK (0)
-
-#endif /* _LINUX_VFC_I2C_H_ */
-
-
-
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c
deleted file mode 100644
index ab0d2de3324..00000000000
--- a/drivers/sbus/dvma.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* dvma.c: Routines that are used to access DMA on the Sparc SBus.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/oplib.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/sbus.h>
-
-struct sbus_dma *dma_chain;
-
-static void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
-{
- printk("dma%d: ", num_dma);
-
- dma->next = NULL;
- dma->running = 0; /* No transfers going on as of yet */
- dma->allocated = 0; /* No one has allocated us yet */
- switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) {
- case DMA_VERS0:
- dma->revision = dvmarev0;
- printk("Revision 0 ");
- break;
- case DMA_ESCV1:
- dma->revision = dvmaesc1;
- printk("ESC Revision 1 ");
- break;
- case DMA_VERS1:
- dma->revision = dvmarev1;
- printk("Revision 1 ");
- break;
- case DMA_VERS2:
- dma->revision = dvmarev2;
- printk("Revision 2 ");
- break;
- case DMA_VERHME:
- dma->revision = dvmahme;
- printk("HME DVMA gate array ");
- break;
- case DMA_VERSPLUS:
- dma->revision = dvmarevplus;
- printk("Revision 1 PLUS ");
- break;
- default:
- printk("unknown dma version %08x",
- sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID);
- dma->allocated = 1;
- break;
- }
- printk("\n");
-}
-
-/* Probe this SBus DMA module(s) */
-void __init dvma_init(struct sbus_bus *sbus)
-{
- struct sbus_dev *this_dev;
- struct sbus_dma *dma;
- struct sbus_dma *dchain;
- static int num_dma = 0;
-
- for_each_sbusdev(this_dev, sbus) {
- char *name = this_dev->prom_name;
- int hme = 0;
-
- if(!strcmp(name, "SUNW,fas"))
- hme = 1;
- else if(strcmp(name, "dma") &&
- strcmp(name, "ledma") &&
- strcmp(name, "espdma"))
- continue;
-
- /* Found one... */
- dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);
-
- dma->sdev = this_dev;
-
- /* Put at end of dma chain */
- dchain = dma_chain;
- if(dchain) {
- while(dchain->next)
- dchain = dchain->next;
- dchain->next = dma;
- } else {
- /* We're the first in line */
- dma_chain = dma;
- }
-
- dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0,
- dma->sdev->resource[0].end - dma->sdev->resource[0].start + 1,
- "dma");
-
- dma->node = dma->sdev->prom_node;
-
- init_one_dvma(dma, num_dma++);
- }
-}
-
-#ifdef CONFIG_SUN4
-
-#include <asm/sun4paddr.h>
-
-void __init sun4_dvma_init(void)
-{
- struct sbus_dma *dma;
- struct resource r;
-
- if(sun4_dma_physaddr) {
- dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);
-
- /* No SBUS */
- dma->sdev = NULL;
-
- /* Only one DMA device */
- dma_chain = dma;
-
- memset(&r, 0, sizeof(r));
- r.start = sun4_dma_physaddr;
- dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma");
-
- /* No prom node */
- dma->node = 0x0;
-
- init_one_dvma(dma, 0);
- } else {
- dma_chain = NULL;
- }
-}
-
-#endif
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
deleted file mode 100644
index 9c129248466..00000000000
--- a/drivers/sbus/sbus.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* sbus.c: SBus support routines.
- *
- * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/of_device.h>
-
-#include <asm/system.h>
-#include <asm/sbus.h>
-#include <asm/dma.h>
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/bpp.h>
-#include <asm/irq.h>
-
-static ssize_t
-show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf)
-{
- struct sbus_dev *sbus;
-
- sbus = to_sbus_device(dev);
-
- return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name);
-}
-
-static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL);
-
-struct sbus_bus *sbus_root;
-
-static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
-{
- struct dev_archdata *sd;
- unsigned long base;
- const void *pval;
- int len, err;
-
- sdev->prom_node = dp->node;
- strcpy(sdev->prom_name, dp->name);
-
- pval = of_get_property(dp, "reg", &len);
- sdev->num_registers = 0;
- if (pval) {
- memcpy(sdev->reg_addrs, pval, len);
-
- sdev->num_registers =
- len / sizeof(struct linux_prom_registers);
-
- base = (unsigned long) sdev->reg_addrs[0].phys_addr;
-
- /* Compute the slot number. */
- if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m)
- sdev->slot = sbus_dev_slot(base);
- else
- sdev->slot = sdev->reg_addrs[0].which_io;
- }
-
- pval = of_get_property(dp, "ranges", &len);
- sdev->num_device_ranges = 0;
- if (pval) {
- memcpy(sdev->device_ranges, pval, len);
- sdev->num_device_ranges =
- len / sizeof(struct linux_prom_ranges);
- }
-
- sbus_fill_device_irq(sdev);
-
- sd = &sdev->ofdev.dev.archdata;
- sd->prom_node = dp;
- sd->op = &sdev->ofdev;
-
- sdev->ofdev.node = dp;
- if (sdev->parent)
- sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev;
- else
- sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
- sdev->ofdev.dev.bus = &sbus_bus_type;
- dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node);
-
- if (of_device_register(&sdev->ofdev) != 0)
- printk(KERN_DEBUG "sbus: device registration error for %s!\n",
- dp->path_component_name);
-
- /* WE HAVE BEEN INVADED BY ALIENS! */
- err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr);
-}
-
-static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus)
-{
- const void *pval;
- int len;
-
- pval = of_get_property(dp, "ranges", &len);
- sbus->num_sbus_ranges = 0;
- if (pval) {
- memcpy(sbus->sbus_ranges, pval, len);
- sbus->num_sbus_ranges =
- len / sizeof(struct linux_prom_ranges);
-
- sbus_arch_bus_ranges_init(dp->parent, sbus);
- }
-}
-
-static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
- int num_ranges,
- struct linux_prom_registers *regs,
- int num_regs)
-{
- if (num_ranges) {
- int regnum;
-
- for (regnum = 0; regnum < num_regs; regnum++) {
- int rngnum;
-
- for (rngnum = 0; rngnum < num_ranges; rngnum++) {
- if (regs[regnum].which_io == ranges[rngnum].ot_child_space)
- break;
- }
- if (rngnum == num_ranges) {
- /* We used to flag this as an error. Actually
- * some devices do not report the regs as we expect.
- * For example, see SUNW,pln device. In that case
- * the reg property is in a format internal to that
- * node, ie. it is not in the SBUS register space
- * per se. -DaveM
- */
- return;
- }
- regs[regnum].which_io = ranges[rngnum].ot_parent_space;
- regs[regnum].phys_addr -= ranges[rngnum].ot_child_base;
- regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
- }
- }
-}
-
-static void __init __fixup_regs_sdev(struct sbus_dev *sdev)
-{
- if (sdev->num_registers != 0) {
- struct sbus_dev *parent = sdev->parent;
- int i;
-
- while (parent != NULL) {
- __apply_ranges_to_regs(parent->device_ranges,
- parent->num_device_ranges,
- sdev->reg_addrs,
- sdev->num_registers);
-
- parent = parent->parent;
- }
-
- __apply_ranges_to_regs(sdev->bus->sbus_ranges,
- sdev->bus->num_sbus_ranges,
- sdev->reg_addrs,
- sdev->num_registers);
-
- for (i = 0; i < sdev->num_registers; i++) {
- struct resource *res = &sdev->resource[i];
-
- res->start = sdev->reg_addrs[i].phys_addr;
- res->end = (res->start +
- (unsigned long)sdev->reg_addrs[i].reg_size - 1UL);
- res->flags = IORESOURCE_IO |
- (sdev->reg_addrs[i].which_io & 0xff);
- }
- }
-}
-
-static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev)
-{
- struct sbus_dev *sdev;
-
- for (sdev = first_sdev; sdev; sdev = sdev->next) {
- if (sdev->child)
- sbus_fixup_all_regs(sdev->child);
- __fixup_regs_sdev(sdev);
- }
-}
-
-/* We preserve the "probe order" of these bus and device lists to give
- * the same ordering as the old code.
- */
-static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root)
-{
- while (*root)
- root = &(*root)->next;
- *root = sbus;
- sbus->next = NULL;
-}
-
-static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root)
-{
- while (*root)
- root = &(*root)->next;
- *root = sdev;
- sdev->next = NULL;
-}
-
-static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus)
-{
- dp = dp->child;
- while (dp) {
- struct sbus_dev *sdev;
-
- sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
- if (sdev) {
- sdev_insert(sdev, &parent->child);
-
- sdev->bus = sbus;
- sdev->parent = parent;
- sdev->ofdev.dev.archdata.iommu =
- sbus->ofdev.dev.archdata.iommu;
- sdev->ofdev.dev.archdata.stc =
- sbus->ofdev.dev.archdata.stc;
-
- fill_sbus_device(dp, sdev);
-
- walk_children(dp, sdev, sbus);
- }
- dp = dp->sibling;
- }
-}
-
-static void __init build_one_sbus(struct device_node *dp, int num_sbus)
-{
- struct sbus_bus *sbus;
- unsigned int sbus_clock;
- struct device_node *dev_dp;
-
- sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
- if (!sbus)
- return;
-
- sbus_insert(sbus, &sbus_root);
- sbus->prom_node = dp->node;
-
- sbus_setup_iommu(sbus, dp);
-
- printk("sbus%d: ", num_sbus);
-
- sbus_clock = of_getintprop_default(dp, "clock-frequency",
- (25*1000*1000));
- sbus->clock_freq = sbus_clock;
-
- printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
- (int) (((sbus_clock/1000)%1000 != 0) ?
- (((sbus_clock/1000)%1000) + 1000) : 0));
-
- strcpy(sbus->prom_name, dp->name);
-
- sbus_setup_arch_props(sbus, dp);
-
- sbus_bus_ranges_init(dp, sbus);
-
- sbus->ofdev.node = dp;
- sbus->ofdev.dev.parent = NULL;
- sbus->ofdev.dev.bus = &sbus_bus_type;
- dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus);
-
- if (of_device_register(&sbus->ofdev) != 0)
- printk(KERN_DEBUG "sbus: device registration error for %s!\n",
- dev_name(&sbus->ofdev.dev));
-
- dev_dp = dp->child;
- while (dev_dp) {
- struct sbus_dev *sdev;
-
- sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
- if (sdev) {
- sdev_insert(sdev, &sbus->devices);
-
- sdev->bus = sbus;
- sdev->parent = NULL;
- sdev->ofdev.dev.archdata.iommu =
- sbus->ofdev.dev.archdata.iommu;
- sdev->ofdev.dev.archdata.stc =
- sbus->ofdev.dev.archdata.stc;
-
- fill_sbus_device(dev_dp, sdev);
-
- walk_children(dev_dp, sdev, sbus);
- }
- dev_dp = dev_dp->sibling;
- }
-
- sbus_fixup_all_regs(sbus->devices);
-
- dvma_init(sbus);
-}
-
-static int __init sbus_init(void)
-{
- struct device_node *dp;
- const char *sbus_name = "sbus";
- int num_sbus = 0;
-
- if (sbus_arch_preinit())
- return 0;
-
- if (sparc_cpu_model == sun4d)
- sbus_name = "sbi";
-
- for_each_node_by_name(dp, sbus_name) {
- build_one_sbus(dp, num_sbus);
- num_sbus++;
-
- }
-
- sbus_arch_postinit();
-
- return 0;
-}
-
-subsys_initcall(sbus_init);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index c7f06298bd3..403ecad48d4 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -63,7 +63,7 @@ comment "SCSI support type (disk, tape, CD-ROM)"
config BLK_DEV_SD
tristate "SCSI disk support"
depends on SCSI
- select CRC_T10DIF
+ select CRC_T10DIF if BLK_DEV_INTEGRITY
---help---
If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
@@ -1325,14 +1325,6 @@ config SCSI_QLOGIC_FAS
To compile this driver as a module, choose M here: the
module will be called qlogicfas.
-config SCSI_QLOGIC_FC_FIRMWARE
- bool "Include loadable firmware in driver"
- depends on SCSI_QLOGIC_FC
- help
- Say Y to include ISP2X00 Fabric Initiator/Target Firmware, with
- expanded LUN addressing and FcTape (FCP-2) support, in the
- qlogicfc driver. This is required on some platforms.
-
config SCSI_QLOGIC_1280
tristate "Qlogic QLA 1240/1x80/1x160 SCSI support"
depends on PCI && SCSI
@@ -1648,6 +1640,7 @@ config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI
select SCSI_SPI_ATTRS
+ select NVRAM
---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
@@ -1678,14 +1671,6 @@ config ATARI_SCSI_RESET_BOOT
boot process fractionally longer but may assist recovery from errors
that leave the devices with SCSI operations partway completed.
-config TT_DMA_EMUL
- bool "Hades SCSI DMA emulator"
- depends on ATARI_SCSI && HADES
- help
- This option enables code which emulates the TT SCSI DMA chip on the
- Hades. This increases the SCSI transfer rates at least ten times
- compared to PIO transfers.
-
config MAC_SCSI
bool "Macintosh NCR5380 SCSI"
depends on MAC && SCSI=y
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index aa4e77c2527..8abfd06b5a7 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -1139,7 +1139,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd
srbcmd->id = cpu_to_le32(scmd_id(cmd));
srbcmd->lun = cpu_to_le32(cmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
- timeout = cmd->timeout_per_command/HZ;
+ timeout = cmd->request->timeout/HZ;
if (timeout == 0)
timeout = 1;
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c
deleted file mode 100644
index cdc710ea00f..00000000000
--- a/drivers/scsi/atari_dma_emul.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * atari_dma_emul.c -- TT SCSI DMA emulator for the Hades.
- *
- * Copyright 1997 Wout Klaren <W.Klaren@inter.nl.net>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * This code was written using the Hades TOS source code as a
- * reference. This source code can be found on the home page
- * of Medusa Computer Systems.
- *
- * Version 0.1, 1997-09-24.
- *
- * This code should be considered experimental. It has only been
- * tested on a Hades with a 68060. It might not work on a Hades
- * with a 68040. Make backups of your hard drives before using
- * this code.
- */
-
-#include <linux/compiler.h>
-#include <asm/thread_info.h>
-#include <asm/uaccess.h>
-
-#define hades_dma_ctrl (*(unsigned char *) 0xffff8717)
-#define hades_psdm_reg (*(unsigned char *) 0xffff8741)
-
-#define TRANSFER_SIZE 16
-
-struct m68040_frame {
- unsigned long effaddr; /* effective address */
- unsigned short ssw; /* special status word */
- unsigned short wb3s; /* write back 3 status */
- unsigned short wb2s; /* write back 2 status */
- unsigned short wb1s; /* write back 1 status */
- unsigned long faddr; /* fault address */
- unsigned long wb3a; /* write back 3 address */
- unsigned long wb3d; /* write back 3 data */
- unsigned long wb2a; /* write back 2 address */
- unsigned long wb2d; /* write back 2 data */
- unsigned long wb1a; /* write back 1 address */
- unsigned long wb1dpd0; /* write back 1 data/push data 0*/
- unsigned long pd1; /* push data 1*/
- unsigned long pd2; /* push data 2*/
- unsigned long pd3; /* push data 3*/
-};
-
-static void writeback (unsigned short wbs, unsigned long wba,
- unsigned long wbd, void *old_buserr)
-{
- mm_segment_t fs = get_fs();
- static void *save_buserr;
-
- __asm__ __volatile__ ("movec.l %%vbr,%%a0\n\t"
- "move.l %0,8(%%a0)\n\t"
- :
- : "r" (&&bus_error)
- : "a0" );
-
- save_buserr = old_buserr;
-
- set_fs (MAKE_MM_SEG(wbs & WBTM_040));
-
- switch (wbs & WBSIZ_040) {
- case BA_SIZE_BYTE:
- put_user (wbd & 0xff, (char *)wba);
- break;
- case BA_SIZE_WORD:
- put_user (wbd & 0xffff, (short *)wba);
- break;
- case BA_SIZE_LONG:
- put_user (wbd, (int *)wba);
- break;
- }
-
- set_fs (fs);
- return;
-
-bus_error:
- __asm__ __volatile__ ("cmp.l %0,2(%%sp)\n\t"
- "bcs.s .jump_old\n\t"
- "cmp.l %1,2(%%sp)\n\t"
- "bls.s .restore_old\n"
- ".jump_old:\n\t"
- "move.l %2,-(%%sp)\n\t"
- "rts\n"
- ".restore_old:\n\t"
- "move.l %%a0,-(%%sp)\n\t"
- "movec.l %%vbr,%%a0\n\t"
- "move.l %2,8(%%a0)\n\t"
- "move.l (%%sp)+,%%a0\n\t"
- "rte\n\t"
- :
- : "i" (writeback), "i" (&&bus_error),
- "m" (save_buserr) );
-}
-
-/*
- * static inline void set_restdata_reg(unsigned char *cur_addr)
- *
- * Set the rest data register if necessary.
- */
-
-static inline void set_restdata_reg(unsigned char *cur_addr)
-{
- if (((long) cur_addr & ~3) != 0)
- tt_scsi_dma.dma_restdata =
- *((unsigned long *) ((long) cur_addr & ~3));
-}
-
-/*
- * void hades_dma_emulator(int irq, void *dummy)
- *
- * This code emulates TT SCSI DMA on the Hades.
- *
- * Note the following:
- *
- * 1. When there is no byte available to read from the SCSI bus, or
- * when a byte cannot yet bet written to the SCSI bus, a bus
- * error occurs when reading or writing the pseudo DMA data
- * register (hades_psdm_reg). We have to catch this bus error
- * and try again to read or write the byte. If after several tries
- * we still get a bus error, the interrupt handler is left. When
- * the byte can be read or written, the interrupt handler is
- * called again.
- *
- * 2. The SCSI interrupt must be disabled in this interrupt handler.
- *
- * 3. If we set the EOP signal, the SCSI controller still expects one
- * byte to be read or written. Therefore the last byte is transferred
- * separately, after setting the EOP signal.
- *
- * 4. When this function is left, the address pointer (start_addr) is
- * converted to a physical address. Because it points one byte
- * further than the last transferred byte, it can point outside the
- * current page. If virt_to_phys() is called with this address we
- * might get an access error. Therefore virt_to_phys() is called with
- * start_addr - 1 if the count has reached zero. The result is
- * increased with one.
- */
-
-static irqreturn_t hades_dma_emulator(int irq, void *dummy)
-{
- unsigned long dma_base;
- register unsigned long dma_cnt asm ("d3");
- static long save_buserr;
- register unsigned long save_sp asm ("d4");
- register int tries asm ("d5");
- register unsigned char *start_addr asm ("a3"), *end_addr asm ("a4");
- register unsigned char *eff_addr;
- register unsigned char *psdm_reg;
- unsigned long rem;
-
- atari_disable_irq(IRQ_TT_MFP_SCSI);
-
- /*
- * Read the dma address and count registers.
- */
-
- dma_base = SCSI_DMA_READ_P(dma_addr);
- dma_cnt = SCSI_DMA_READ_P(dma_cnt);
-
- /*
- * Check if DMA is still enabled.
- */
-
- if ((tt_scsi_dma.dma_ctrl & 2) == 0)
- {
- atari_enable_irq(IRQ_TT_MFP_SCSI);
- return IRQ_HANDLED;
- }
-
- if (dma_cnt == 0)
- {
- printk(KERN_NOTICE "DMA emulation: count is zero.\n");
- tt_scsi_dma.dma_ctrl &= 0xfd; /* DMA ready. */
- atari_enable_irq(IRQ_TT_MFP_SCSI);
- return IRQ_HANDLED;
- }
-
- /*
- * Install new bus error routine.
- */
-
- __asm__ __volatile__ ("movec.l %%vbr,%%a0\n\t"
- "move.l 8(%%a0),%0\n\t"
- "move.l %1,8(%%a0)\n\t"
- : "=&r" (save_buserr)
- : "r" (&&scsi_bus_error)
- : "a0" );
-
- hades_dma_ctrl &= 0xfc; /* Bus error and EOP off. */
-
- /*
- * Save the stack pointer.
- */
-
- __asm__ __volatile__ ("move.l %%sp,%0\n\t"
- : "=&r" (save_sp) );
-
- tries = 100; /* Maximum number of bus errors. */
- start_addr = phys_to_virt(dma_base);
- end_addr = start_addr + dma_cnt;
-
-scsi_loop:
- dma_cnt--;
- rem = dma_cnt & (TRANSFER_SIZE - 1);
- dma_cnt &= ~(TRANSFER_SIZE - 1);
- psdm_reg = &hades_psdm_reg;
-
- if (tt_scsi_dma.dma_ctrl & 1) /* Read or write? */
- {
- /*
- * SCSI write. Abort when count is zero.
- */
-
- switch (rem)
- {
- case 0:
- while (dma_cnt > 0)
- {
- dma_cnt -= TRANSFER_SIZE;
-
- *psdm_reg = *start_addr++;
- case 15:
- *psdm_reg = *start_addr++;
- case 14:
- *psdm_reg = *start_addr++;
- case 13:
- *psdm_reg = *start_addr++;
- case 12:
- *psdm_reg = *start_addr++;
- case 11:
- *psdm_reg = *start_addr++;
- case 10:
- *psdm_reg = *start_addr++;
- case 9:
- *psdm_reg = *start_addr++;
- case 8:
- *psdm_reg = *start_addr++;
- case 7:
- *psdm_reg = *start_addr++;
- case 6:
- *psdm_reg = *start_addr++;
- case 5:
- *psdm_reg = *start_addr++;
- case 4:
- *psdm_reg = *start_addr++;
- case 3:
- *psdm_reg = *start_addr++;
- case 2:
- *psdm_reg = *start_addr++;
- case 1:
- *psdm_reg = *start_addr++;
- }
- }
-
- hades_dma_ctrl |= 1; /* Set EOP. */
- udelay(10);
- *psdm_reg = *start_addr++; /* Dummy byte. */
- tt_scsi_dma.dma_ctrl &= 0xfd; /* DMA ready. */
- }
- else
- {
- /*
- * SCSI read. Abort when count is zero.
- */
-
- switch (rem)
- {
- case 0:
- while (dma_cnt > 0)
- {
- dma_cnt -= TRANSFER_SIZE;
-
- *start_addr++ = *psdm_reg;
- case 15:
- *start_addr++ = *psdm_reg;
- case 14:
- *start_addr++ = *psdm_reg;
- case 13:
- *start_addr++ = *psdm_reg;
- case 12:
- *start_addr++ = *psdm_reg;
- case 11:
- *start_addr++ = *psdm_reg;
- case 10:
- *start_addr++ = *psdm_reg;
- case 9:
- *start_addr++ = *psdm_reg;
- case 8:
- *start_addr++ = *psdm_reg;
- case 7:
- *start_addr++ = *psdm_reg;
- case 6:
- *start_addr++ = *psdm_reg;
- case 5:
- *start_addr++ = *psdm_reg;
- case 4:
- *start_addr++ = *psdm_reg;
- case 3:
- *start_addr++ = *psdm_reg;
- case 2:
- *start_addr++ = *psdm_reg;
- case 1:
- *start_addr++ = *psdm_reg;
- }
- }
-
- hades_dma_ctrl |= 1; /* Set EOP. */
- udelay(10);
- *start_addr++ = *psdm_reg;
- tt_scsi_dma.dma_ctrl &= 0xfd; /* DMA ready. */
-
- set_restdata_reg(start_addr);
- }
-
- if (start_addr != end_addr)
- printk(KERN_CRIT "DMA emulation: FATAL: Count is not zero at end of transfer.\n");
-
- dma_cnt = end_addr - start_addr;
-
-scsi_end:
- dma_base = (dma_cnt == 0) ? virt_to_phys(start_addr - 1) + 1 :
- virt_to_phys(start_addr);
-
- SCSI_DMA_WRITE_P(dma_addr, dma_base);
- SCSI_DMA_WRITE_P(dma_cnt, dma_cnt);
-
- /*
- * Restore old bus error routine.
- */
-
- __asm__ __volatile__ ("movec.l %%vbr,%%a0\n\t"
- "move.l %0,8(%%a0)\n\t"
- :
- : "r" (save_buserr)
- : "a0" );
-
- atari_enable_irq(IRQ_TT_MFP_SCSI);
-
- return IRQ_HANDLED;
-
-scsi_bus_error:
- /*
- * First check if the bus error is caused by our code.
- * If not, call the original handler.
- */
-
- __asm__ __volatile__ ("cmp.l %0,2(%%sp)\n\t"
- "bcs.s .old_vector\n\t"
- "cmp.l %1,2(%%sp)\n\t"
- "bls.s .scsi_buserr\n"
- ".old_vector:\n\t"
- "move.l %2,-(%%sp)\n\t"
- "rts\n"
- ".scsi_buserr:\n\t"
- :
- : "i" (&&scsi_loop), "i" (&&scsi_end),
- "m" (save_buserr) );
-
- if (CPU_IS_060)
- {
- /*
- * Get effective address and restore the stack.
- */
-
- __asm__ __volatile__ ("move.l 8(%%sp),%0\n\t"
- "move.l %1,%%sp\n\t"
- : "=a&" (eff_addr)
- : "r" (save_sp) );
- }
- else
- {
- register struct m68040_frame *frame;
-
- __asm__ __volatile__ ("lea 8(%%sp),%0\n\t"
- : "=a&" (frame) );
-
- if (tt_scsi_dma.dma_ctrl & 1)
- {
- /*
- * Bus error while writing.
- */
-
- if (frame->wb3s & WBV_040)
- {
- if (frame->wb3a == (long) &hades_psdm_reg)
- start_addr--;
- else
- writeback(frame->wb3s, frame->wb3a,
- frame->wb3d, &&scsi_bus_error);
- }
-
- if (frame->wb2s & WBV_040)
- {
- if (frame->wb2a == (long) &hades_psdm_reg)
- start_addr--;
- else
- writeback(frame->wb2s, frame->wb2a,
- frame->wb2d, &&scsi_bus_error);
- }
-
- if (frame->wb1s & WBV_040)
- {
- if (frame->wb1a == (long) &hades_psdm_reg)
- start_addr--;
- }
- }
- else
- {
- /*
- * Bus error while reading.
- */
-
- if (frame->wb3s & WBV_040)
- writeback(frame->wb3s, frame->wb3a,
- frame->wb3d, &&scsi_bus_error);
- }
-
- eff_addr = (unsigned char *) frame->faddr;
-
- __asm__ __volatile__ ("move.l %0,%%sp\n\t"
- :
- : "r" (save_sp) );
- }
-
- dma_cnt = end_addr - start_addr;
-
- if (eff_addr == &hades_psdm_reg)
- {
- /*
- * Bus error occurred while reading the pseudo
- * DMA register. Time out.
- */
-
- tries--;
-
- if (tries <= 0)
- {
- if ((tt_scsi_dma.dma_ctrl & 1) == 0) /* Read or write? */
- set_restdata_reg(start_addr);
-
- if (dma_cnt <= 1)
- printk(KERN_CRIT "DMA emulation: Fatal "
- "error while %s the last byte.\n",
- (tt_scsi_dma.dma_ctrl & 1)
- ? "writing" : "reading");
-
- goto scsi_end;
- }
- else
- goto scsi_loop;
- }
- else
- {
- /*
- * Bus error during pseudo DMA transfer.
- * Terminate the DMA transfer.
- */
-
- hades_dma_ctrl |= 3; /* Set EOP and bus error. */
- if ((tt_scsi_dma.dma_ctrl & 1) == 0) /* Read or write? */
- set_restdata_reg(start_addr);
- goto scsi_end;
- }
-}
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index f5732d8f67f..21fe07f9df8 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -249,10 +249,6 @@ static int setup_hostid = -1;
module_param(setup_hostid, int, 0);
-#if defined(CONFIG_TT_DMA_EMUL)
-#include "atari_dma_emul.c"
-#endif
-
#if defined(REAL_DMA)
static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
@@ -695,21 +691,8 @@ int atari_scsi_detect(struct scsi_host_template *host)
#ifdef REAL_DMA
tt_scsi_dma.dma_ctrl = 0;
atari_dma_residual = 0;
-#ifdef CONFIG_TT_DMA_EMUL
- if (MACH_IS_HADES) {
- if (request_irq(IRQ_AUTO_2, hades_dma_emulator,
- IRQ_TYPE_PRIO, "Hades DMA emulator",
- hades_dma_emulator)) {
- printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting (MACH_IS_HADES)",IRQ_AUTO_2);
- free_irq(IRQ_TT_MFP_SCSI, instance);
- scsi_unregister(atari_scsi_host);
- atari_stram_free(atari_dma_buffer);
- atari_dma_buffer = 0;
- return 0;
- }
- }
-#endif
- if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+
+ if (MACH_IS_MEDUSA) {
/* While the read overruns (described by Drew Eckhardt in
* NCR5380.c) never happened on TTs, they do in fact on the Medusa
* (This was the cause why SCSI didn't work right for so long
@@ -1007,11 +990,7 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
Scsi_Cmnd *cmd, int write_flag)
{
unsigned long possible_len, limit;
-#ifndef CONFIG_TT_DMA_EMUL
- if (MACH_IS_HADES)
- /* Hades has no SCSI DMA at all :-( Always force use of PIO */
- return 0;
-#endif
+
if (IS_A_TT())
/* TT SCSI DMA can transfer arbitrary #bytes */
return wanted_len;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 3c257fe0893..88ecf94ad97 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -914,9 +914,9 @@ static int ch_probe(struct device *dev)
ch->minor = minor;
sprintf(ch->name,"ch%d",ch->minor);
- class_dev = device_create_drvdata(ch_sysfs_class, dev,
- MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
- ch, "s%s", ch->name);
+ class_dev = device_create(ch_sysfs_class, dev,
+ MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
+ "s%s", ch->name);
if (IS_ERR(class_dev)) {
printk(KERN_WARNING "ch%d: device_create failed\n",
ch->minor);
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 9785d738419..4003deefb7d 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1364,7 +1364,8 @@ EXPORT_SYMBOL(scsi_print_sense);
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", "DID_REQUEUE"};
+"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
+"DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST" };
#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
static const char * const driverbyte_table[]={
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 994da56fffe..e356b43753f 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -109,7 +109,8 @@ static struct request *get_alua_req(struct scsi_device *sdev,
}
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+ rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER;
rq->retries = ALUA_FAILOVER_RETRIES;
rq->timeout = ALUA_FAILOVER_TIMEOUT;
@@ -425,7 +426,7 @@ static int alua_check_sense(struct scsi_device *sdev,
/*
* LUN Not Accessible - ALUA state transition
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b)
/*
* LUN Not Accessible -- Target port in standby state
@@ -447,18 +448,18 @@ static int alua_check_sense(struct scsi_device *sdev,
/*
* Power On, Reset, or Bus Device Reset, just retry.
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
/*
* ALUA state changed
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
}
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
/*
* Implicit ALUA state transition failed
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
}
break;
}
@@ -490,7 +491,7 @@ static int alua_stpg(struct scsi_device *sdev, int state,
if (!err)
return SCSI_DH_IO;
err = alua_check_sense(sdev, &sense_hdr);
- if (retry > 0 && err == NEEDS_RETRY) {
+ if (retry > 0 && err == ADD_TO_MLQUEUE) {
retry--;
goto retry;
}
@@ -535,7 +536,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
return SCSI_DH_IO;
err = alua_check_sense(sdev, &sense_hdr);
- if (err == NEEDS_RETRY)
+ if (err == ADD_TO_MLQUEUE)
goto retry;
sdev_printk(KERN_INFO, sdev,
"%s: rtpg sense code %02x/%02x/%02x\n",
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index b9d23e9e9a4..0e572d2c5b0 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -84,7 +84,7 @@ struct clariion_dh_data {
/*
* I/O buffer for both MODE_SELECT and INQUIRY commands.
*/
- char buffer[CLARIION_BUFFER_SIZE];
+ unsigned char buffer[CLARIION_BUFFER_SIZE];
/*
* SCSI sense buffer for commands -- assumes serial issuance
* and completion sequence of all commands for same multipath.
@@ -176,7 +176,7 @@ static int parse_sp_info_reply(struct scsi_device *sdev,
err = SCSI_DH_DEV_TEMP_BUSY;
goto out;
}
- if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) {
+ if (csdev->buffer[4] > 2) {
/* Invalid buffer format */
sdev_printk(KERN_NOTICE, sdev,
"%s: invalid VPD page 0xC0 format\n",
@@ -278,7 +278,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
return NULL;
}
- memset(rq->cmd, 0, BLK_MAX_CDB);
rq->cmd_len = COMMAND_SIZE(cmd);
rq->cmd[0] = cmd;
@@ -304,7 +303,8 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
rq->cmd[4] = len;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->cmd_flags |= REQ_FAILFAST;
+ rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER;
rq->timeout = CLARIION_TIMEOUT;
rq->retries = CLARIION_RETRIES;
@@ -439,7 +439,7 @@ static int clariion_check_sense(struct scsi_device *sdev,
* Unit Attention Code. This is the first IO
* to the new path, so just retry.
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
break;
}
@@ -514,7 +514,7 @@ retry:
return SCSI_DH_IO;
err = clariion_check_sense(sdev, &sshdr);
- if (retry > 0 && err == NEEDS_RETRY) {
+ if (retry > 0 && err == ADD_TO_MLQUEUE) {
retry--;
goto retry;
}
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index a6a4ef3ad51..9aec4ca64e5 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -112,9 +112,9 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
return SCSI_DH_RES_TEMP_UNAVAIL;
req->cmd_type = REQ_TYPE_BLOCK_PC;
- req->cmd_flags |= REQ_FAILFAST;
+ req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER;
req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
- memset(req->cmd, 0, MAX_COMMAND_SIZE);
req->cmd[0] = TEST_UNIT_READY;
req->timeout = HP_SW_TIMEOUT;
req->sense = h->sense;
@@ -205,9 +205,9 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
return SCSI_DH_RES_TEMP_UNAVAIL;
req->cmd_type = REQ_TYPE_BLOCK_PC;
- req->cmd_flags |= REQ_FAILFAST;
+ req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER;
req->cmd_len = COMMAND_SIZE(START_STOP);
- memset(req->cmd, 0, MAX_COMMAND_SIZE);
req->cmd[0] = START_STOP;
req->cmd[4] = 1; /* Start spin cycle */
req->timeout = HP_SW_TIMEOUT;
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 2dee69da35c..a43c3ed4df2 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -225,10 +225,9 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
return NULL;
}
- memset(rq->cmd, 0, BLK_MAX_CDB);
-
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+ rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER;
rq->retries = RDAC_RETRIES;
rq->timeout = RDAC_TIMEOUT;
@@ -551,7 +550,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
*
* Just retry and wait.
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
break;
case ILLEGAL_REQUEST:
if (sense_hdr->asc == 0x94 && sense_hdr->ascq == 0x01) {
@@ -568,7 +567,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
/*
* Power On, Reset, or Bus Device Reset, just retry.
*/
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
break;
}
/* success just means we do not care what scsi-ml does */
@@ -590,6 +589,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"STK", "OPENstorage D280"},
{"SUN", "CSM200_R"},
{"SUN", "LCSM100_F"},
+ {"DELL", "MD3000"},
+ {"DELL", "MD3000i"},
{NULL, NULL},
};
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 1fe0901e811..8aba4fdfb52 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -271,7 +271,7 @@ rebuild_sys_tab:
pHba->initialized = TRUE;
pHba->state &= ~DPTI_STATE_RESET;
if (adpt_sysfs_class) {
- struct device *dev = device_create_drvdata(adpt_sysfs_class,
+ struct device *dev = device_create(adpt_sysfs_class,
NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
"dpti%d", pHba->unit);
if (IS_ERR(dev)) {
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index bb43a138818..28e22acf87e 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -521,7 +521,8 @@ struct esp {
struct completion *eh_reset;
- struct sbus_dma *dma;
+ void *dma;
+ int dmarev;
};
/* A front-end driver for the ESP chip should do the following in
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 822d5214692..c387c15a212 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -464,7 +464,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
/* use request field to save the ptr. to completion struct. */
scp->request = (struct request *)&wait;
- scp->timeout_per_command = timeout*HZ;
scp->cmd_len = 12;
scp->cmnd = cmnd;
cmndinfo.priority = IOCTL_PRI;
@@ -1995,23 +1994,12 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority)
register Scsi_Cmnd *pscp;
register Scsi_Cmnd *nscp;
ulong flags;
- unchar b, t;
TRACE(("gdth_putq() priority %d\n",priority));
spin_lock_irqsave(&ha->smp_lock, flags);
- if (!cmndinfo->internal_command) {
+ if (!cmndinfo->internal_command)
cmndinfo->priority = priority;
- b = scp->device->channel;
- t = scp->device->id;
- if (priority >= DEFAULT_PRI) {
- if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
- (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
- TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
- cmndinfo->timeout = gdth_update_timeout(scp, 0);
- }
- }
- }
if (ha->req_first==NULL) {
ha->req_first = scp; /* queue was empty */
@@ -3899,6 +3887,39 @@ static const char *gdth_info(struct Scsi_Host *shp)
return ((const char *)ha->binfo.type_string);
}
+static enum blk_eh_timer_return gdth_timed_out(struct scsi_cmnd *scp)
+{
+ gdth_ha_str *ha = shost_priv(scp->device->host);
+ struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
+ unchar b, t;
+ ulong flags;
+ enum blk_eh_timer_return retval = BLK_EH_NOT_HANDLED;
+
+ TRACE(("%s() cmd 0x%x\n", scp->cmnd[0], __func__));
+ b = scp->device->channel;
+ t = scp->device->id;
+
+ /*
+ * We don't really honor the command timeout, but we try to
+ * honor 6 times of the actual command timeout! So reset the
+ * timer if this is less than 6th timeout on this command!
+ */
+ if (++cmndinfo->timeout_count < 6)
+ retval = BLK_EH_RESET_TIMER;
+
+ /* Reset the timeout if it is locked IO */
+ spin_lock_irqsave(&ha->smp_lock, flags);
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha, b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
+ TRACE2(("%s(): locked IO, reset timeout\n", __func__));
+ retval = BLK_EH_RESET_TIMER;
+ }
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
+
+ return retval;
+}
+
+
static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
{
gdth_ha_str *ha = shost_priv(scp->device->host);
@@ -3992,7 +4013,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
BUG_ON(!cmndinfo);
scp->scsi_done = done;
- gdth_update_timeout(scp, scp->timeout_per_command * 6);
+ cmndinfo->timeout_count = 0;
cmndinfo->priority = DEFAULT_PRI;
return __gdth_queuecommand(ha, scp, cmndinfo);
@@ -4096,12 +4117,10 @@ static int ioc_lockdrv(void __user *arg)
ha->hdr[j].lock = 1;
spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_wait_completion(ha, ha->bus_cnt, j);
- gdth_stop_timeout(ha, ha->bus_cnt, j);
} else {
spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 0;
spin_unlock_irqrestore(&ha->smp_lock, flags);
- gdth_start_timeout(ha, ha->bus_cnt, j);
gdth_next(ha);
}
}
@@ -4539,18 +4558,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 1;
spin_unlock_irqrestore(&ha->smp_lock, flags);
- for (j = 0; j < ha->tid_cnt; ++j) {
+ for (j = 0; j < ha->tid_cnt; ++j)
gdth_wait_completion(ha, i, j);
- gdth_stop_timeout(ha, i, j);
- }
} else {
spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 0;
spin_unlock_irqrestore(&ha->smp_lock, flags);
- for (j = 0; j < ha->tid_cnt; ++j) {
- gdth_start_timeout(ha, i, j);
+ for (j = 0; j < ha->tid_cnt; ++j)
gdth_next(ha);
- }
}
}
break;
@@ -4644,6 +4659,7 @@ static struct scsi_host_template gdth_template = {
.slave_configure = gdth_slave_configure,
.bios_param = gdth_bios_param,
.proc_info = gdth_proc_info,
+ .eh_timed_out = gdth_timed_out,
.proc_name = "gdth",
.can_queue = GDTH_MAXCMDS,
.this_id = -1,
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index ca92476727c..1646444e9bd 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -916,7 +916,7 @@ typedef struct {
gdth_cmd_str *internal_cmd_str; /* crier for internal messages*/
dma_addr_t sense_paddr; /* sense dma-addr */
unchar priority;
- int timeout;
+ int timeout_count; /* # of timeout calls */
volatile int wait_for_completion;
ushort status;
ulong32 info;
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index ce0228e26ae..59349a316e1 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -748,69 +748,3 @@ static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id)
}
spin_unlock_irqrestore(&ha->smp_lock, flags);
}
-
-static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id)
-{
- ulong flags;
- Scsi_Cmnd *scp;
- unchar b, t;
-
- spin_lock_irqsave(&ha->smp_lock, flags);
-
- for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
- if (!cmndinfo->internal_command) {
- b = scp->device->channel;
- t = scp->device->id;
- if (t == (unchar)id && b == (unchar)busnum) {
- TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
- cmndinfo->timeout = gdth_update_timeout(scp, 0);
- }
- }
- }
- spin_unlock_irqrestore(&ha->smp_lock, flags);
-}
-
-static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id)
-{
- ulong flags;
- Scsi_Cmnd *scp;
- unchar b, t;
-
- spin_lock_irqsave(&ha->smp_lock, flags);
-
- for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
- if (!cmndinfo->internal_command) {
- b = scp->device->channel;
- t = scp->device->id;
- if (t == (unchar)id && b == (unchar)busnum) {
- TRACE2(("gdth_start_timeout(): update_timeout()\n"));
- gdth_update_timeout(scp, cmndinfo->timeout);
- }
- }
- }
- spin_unlock_irqrestore(&ha->smp_lock, flags);
-}
-
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout)
-{
- int oldto;
-
- oldto = scp->timeout_per_command;
- scp->timeout_per_command = timeout;
-
- if (timeout == 0) {
- del_timer(&scp->eh_timeout);
- scp->eh_timeout.data = (unsigned long) NULL;
- scp->eh_timeout.expires = 0;
- } else {
- if (scp->eh_timeout.data != (unsigned long) NULL)
- del_timer(&scp->eh_timeout);
- scp->eh_timeout.data = (unsigned long) scp;
- scp->eh_timeout.expires = jiffies + timeout;
- add_timer(&scp->eh_timeout);
- }
-
- return oldto;
-}
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index 45e6fdacf36..9b900cc9ebe 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -20,9 +20,6 @@ static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch,
ulong64 *paddr);
static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr);
static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id);
-static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id);
-static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id);
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout);
#endif
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index fed0b02ebc1..3fdbb13e80a 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -464,7 +464,7 @@ static int __scsi_host_match(struct device *dev, void *data)
struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
{
struct device *cdev;
- struct Scsi_Host *shost = ERR_PTR(-ENXIO);
+ struct Scsi_Host *shost = NULL;
cdev = class_find_device(&shost_class, NULL, &hostnum,
__scsi_host_match);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 4e0b7c8eb32..7650707a40d 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2031,8 +2031,6 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
spin_unlock_irqrestore(shost->host_lock, flags);
} else
ibmvfc_issue_fc_host_lip(shost);
-
- scsi_target_unblock(&rport->dev);
LEAVE;
}
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 7b1502c0ab6..87e09f35d3d 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -756,7 +756,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
init_event_struct(evt_struct,
handle_cmd_rsp,
VIOSRP_SRP_FORMAT,
- cmnd->timeout_per_command/HZ);
+ cmnd->request->timeout/HZ);
evt_struct->cmnd = cmnd;
evt_struct->cmnd_done = done;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 461331d3dc4..740bad43599 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -40,7 +40,6 @@
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/errno.h>
-#include <linux/hdreg.h>
#include <linux/slab.h>
#include <linux/ide.h>
#include <linux/scatterlist.h>
@@ -83,7 +82,6 @@ typedef struct ide_scsi_obj {
struct gendisk *disk;
struct Scsi_Host *host;
- struct ide_atapi_pc *pc; /* Current packet command */
unsigned long transform; /* SCSI cmd translation layer */
unsigned long log; /* log flags */
} idescsi_scsi_t;
@@ -131,50 +129,6 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
return scsihost_to_idescsi(ide_drive->driver_data);
}
-/*
- * PIO data transfer routine using the scatter gather table.
- */
-static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int write)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
- char *buf;
- int count;
-
- while (bcount) {
- count = min(pc->sg->length - pc->b_count, bcount);
- if (PageHighMem(sg_page(pc->sg))) {
- unsigned long flags;
-
- local_irq_save(flags);
- buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
- pc->sg->offset;
- xf(drive, NULL, buf + pc->b_count, count);
- kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
- local_irq_restore(flags);
- } else {
- buf = sg_virt(pc->sg);
- xf(drive, NULL, buf + pc->b_count, count);
- }
- bcount -= count; pc->b_count += count;
- if (pc->b_count == pc->sg->length) {
- if (!--pc->sg_cnt)
- break;
- pc->sg = sg_next(pc->sg);
- pc->b_count = 0;
- }
- }
-
- if (bcount) {
- printk(KERN_ERR "%s: scatter gather table too small, %s\n",
- drive->name, write ? "padding with zeros"
- : "discarding data");
- ide_pad_transfer(drive, write, bcount);
- }
-}
-
static void ide_scsi_hex_dump(u8 *data, int len)
{
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
@@ -182,10 +136,10 @@ static void ide_scsi_hex_dump(u8 *data, int len)
static int idescsi_end_request(ide_drive_t *, int, int);
-static void ide_scsi_callback(ide_drive_t *drive)
+static void ide_scsi_callback(ide_drive_t *drive, int dsc)
{
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc = scsi->pc;
+ struct ide_atapi_pc *pc = drive->pc;
if (pc->flags & PC_FLAG_TIMEDOUT)
debug_log("%s: got timed out packet %lu at %lu\n", __func__,
@@ -244,9 +198,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
- if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
/* force an abort */
- hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
rq->errors++;
@@ -312,49 +266,10 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
spin_unlock_irqrestore(host->host_lock, flags);
kfree(pc);
blk_put_request(rq);
- scsi->pc = NULL;
+ drive->pc = NULL;
return 0;
}
-static inline unsigned long get_timeout(struct ide_atapi_pc *pc)
-{
- return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
-}
-
-static int idescsi_expiry(ide_drive_t *drive)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc = scsi->pc;
-
- debug_log("%s called for %lu at %lu\n", __func__,
- pc->scsi_cmd->serial_number, jiffies);
-
- pc->flags |= PC_FLAG_TIMEDOUT;
-
- return 0; /* we do not want the ide subsystem to retry */
-}
-
-/*
- * Our interrupt handler.
- */
-static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc = scsi->pc;
-
- return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc),
- idescsi_expiry, NULL, NULL, NULL,
- ide_scsi_io_buffers);
-}
-
-static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
- return ide_transfer_pc(drive, scsi->pc, idescsi_pc_intr,
- get_timeout(scsi->pc), idescsi_expiry);
-}
-
static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
{
switch (pc->c[0]) {
@@ -397,13 +312,10 @@ static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
/* Set the current packet command */
- scsi->pc = pc;
+ drive->pc = pc;
- return ide_issue_pc(drive, pc, idescsi_transfer_pc,
- get_timeout(pc), idescsi_expiry);
+ return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);
}
/*
@@ -419,7 +331,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
if (blk_sense_request(rq) || blk_special_request(rq)) {
struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
- if (drive->using_dma && !idescsi_map_sg(drive, pc))
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&
+ idescsi_map_sg(drive, pc) == 0)
pc->flags |= PC_FLAG_DMA_OK;
return idescsi_issue_pc(drive, pc);
@@ -430,21 +343,41 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
}
#ifdef CONFIG_IDE_PROC_FS
-static void idescsi_add_settings(ide_drive_t *drive)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
-/*
- * drive setting name read/write data type min max mul_factor div_factor data pointer set function
- */
- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
- ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
- ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
- ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL);
- ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL);
-}
-#else
-static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
+#define ide_scsi_devset_get(name, field) \
+static int get_##name(ide_drive_t *drive) \
+{ \
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
+ return scsi->field; \
+}
+
+#define ide_scsi_devset_set(name, field) \
+static int set_##name(ide_drive_t *drive, int arg) \
+{ \
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
+ scsi->field = arg; \
+ return 0; \
+}
+
+#define ide_scsi_devset_rw_field(_name, _field) \
+ide_scsi_devset_get(_name, _field); \
+ide_scsi_devset_set(_name, _field); \
+IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name);
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+
+ide_scsi_devset_rw_field(transform, transform);
+ide_scsi_devset_rw_field(log, log);
+
+static const struct ide_proc_devset idescsi_settings[] = {
+ IDE_PROC_DEVSET(bios_cyl, 0, 1023),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(log, 0, 1),
+ IDE_PROC_DEVSET(transform, 0, 3),
+ { 0 },
+};
#endif
/*
@@ -452,16 +385,16 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
*/
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
- if (drive->id && (drive->id->config & 0x0060) == 0x20)
- set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
- drive->pc_callback = ide_scsi_callback;
+ drive->pc_callback = ide_scsi_callback;
+ drive->pc_update_buffers = NULL;
+ drive->pc_io_buffers = ide_io_buffers;
- idescsi_add_settings(drive);
+ ide_proc_register_driver(drive, scsi->driver);
}
static void ide_scsi_remove(ide_drive_t *drive)
@@ -481,7 +414,7 @@ static void ide_scsi_remove(ide_drive_t *drive)
ide_scsi_put(scsi);
- drive->scsi = 0;
+ drive->dev_flags &= ~IDE_DFLAG_SCSI;
}
static int ide_scsi_probe(ide_drive_t *);
@@ -502,13 +435,12 @@ static ide_driver_t idescsi_driver = {
.probe = ide_scsi_probe,
.remove = ide_scsi_remove,
.version = IDESCSI_VERSION,
- .media = ide_scsi,
- .supports_dsc_overlap = 0,
.do_request = idescsi_do_request,
.end_request = idescsi_end_request,
.error = idescsi_atapi_error,
#ifdef CONFIG_IDE_PROC_FS
.proc = idescsi_proc,
+ .settings = idescsi_settings,
#endif
};
@@ -612,7 +544,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);
pc->scsi_cmd = cmd;
pc->done = done;
- pc->timeout = jiffies + cmd->timeout_per_command;
+ pc->timeout = jiffies + cmd->request->timeout;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -647,6 +579,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
int busy;
int ret = FAILED;
+ struct ide_atapi_pc *pc;
+
/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
@@ -667,26 +601,27 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
spin_lock_irq(&ide_lock);
/* If there is no pc running we're done (our interrupt took care of it) */
- if (!scsi->pc) {
+ pc = drive->pc;
+ if (pc == NULL) {
ret = SUCCESS;
goto ide_unlock;
}
/* It's somewhere in flight. Does ide subsystem agree? */
- if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
- elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
+ if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
+ elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {
/*
* FIXME - not sure this condition can ever occur
*/
printk (KERN_ERR "ide-scsi: cmd aborted!\n");
- if (blk_sense_request(scsi->pc->rq))
- kfree(scsi->pc->buf);
+ if (blk_sense_request(pc->rq))
+ kfree(pc->buf);
/* we need to call blk_put_request twice. */
- blk_put_request(scsi->pc->rq);
- blk_put_request(scsi->pc->rq);
- kfree(scsi->pc);
- scsi->pc = NULL;
+ blk_put_request(pc->rq);
+ blk_put_request(pc->rq);
+ kfree(pc);
+ drive->pc = NULL;
ret = SUCCESS;
}
@@ -708,6 +643,8 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
int ready = 0;
int ret = SUCCESS;
+ struct ide_atapi_pc *pc;
+
/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
@@ -722,7 +659,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
spin_lock_irq(cmd->device->host->host_lock);
spin_lock(&ide_lock);
- if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+ pc = drive->pc;
+
+ if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
spin_unlock(&ide_lock);
spin_unlock_irq(cmd->device->host->host_lock);
@@ -733,9 +672,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
if (__blk_end_request(req, -EIO, 0))
BUG();
if (blk_sense_request(req))
- kfree(scsi->pc->buf);
- kfree(scsi->pc);
- scsi->pc = NULL;
+ kfree(pc->buf);
+ kfree(pc);
+ drive->pc = NULL;
blk_put_request(req);
/* now nuke the drive queue */
@@ -811,6 +750,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
struct gendisk *g;
static int warned;
int err = -ENOMEM;
+ u16 last_lun;
if (!warned && drive->media == ide_cdrom) {
printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n");
@@ -821,12 +761,11 @@ static int ide_scsi_probe(ide_drive_t *drive)
return -ENODEV;
if (!strstr("ide-scsi", drive->driver_req) ||
- !drive->present ||
drive->media == ide_disk ||
!(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
return -ENODEV;
- drive->scsi = 1;
+ drive->dev_flags |= IDE_DFLAG_SCSI;
g = alloc_disk(1 << PARTN_BITS);
if (!g)
@@ -836,12 +775,12 @@ static int ide_scsi_probe(ide_drive_t *drive)
host->max_id = 1;
- if (drive->id->last_lun)
- debug_log("%s: id->last_lun=%u\n", drive->name,
- drive->id->last_lun);
+ last_lun = drive->id[ATA_ID_LAST_LUN];
+ if (last_lun)
+ debug_log("%s: last_lun=%u\n", drive->name, last_lun);
- if ((drive->id->last_lun & 0x7) != 7)
- host->max_lun = (drive->id->last_lun & 0x7) + 1;
+ if ((last_lun & 7) != 7)
+ host->max_lun = (last_lun & 7) + 1;
else
host->max_lun = 1;
@@ -852,7 +791,6 @@ static int ide_scsi_probe(ide_drive_t *drive)
idescsi->host = host;
idescsi->disk = g;
g->private_data = &idescsi->driver;
- ide_proc_register_driver(drive, &idescsi_driver);
err = 0;
idescsi_setup(drive, idescsi);
g->fops = &idescsi_ops;
@@ -868,7 +806,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
put_disk(g);
out_host_put:
- drive->scsi = 0;
+ drive->dev_flags &= ~IDE_DFLAG_SCSI;
scsi_host_put(host);
return err;
}
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index e7a3a655442..d30eb7ba018 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3670,7 +3670,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
sdev->no_uld_attach = 1;
}
if (ipr_is_vset_device(res)) {
- sdev->timeout = IPR_VSET_RW_TIMEOUT;
+ blk_queue_rq_timeout(sdev->request_queue,
+ IPR_VSET_RW_TIMEOUT);
blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
}
if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index bc9e6ddf41d..ef683f0d2b5 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -3818,7 +3818,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
scb->cmd.dcdb.segment_4G = 0;
scb->cmd.dcdb.enhanced_sg = 0;
- TimeOut = scb->scsi_cmd->timeout_per_command;
+ TimeOut = scb->scsi_cmd->request->timeout;
if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
if (!scb->sg_len) {
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 2a2f0094570..ed6c54cae7b 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -523,22 +523,20 @@ iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
}
/**
- * iscsi_data_rsp - SCSI Data-In Response processing
+ * iscsi_data_in - SCSI Data-In Response processing
* @conn: iscsi connection
* @task: scsi command task
**/
static int
-iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_tcp_task *tcp_task = task->dd_data;
struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
- struct iscsi_session *session = conn->session;
- struct scsi_cmnd *sc = task->sc;
int datasn = be32_to_cpu(rhdr->datasn);
- unsigned total_in_length = scsi_in(sc)->length;
+ unsigned total_in_length = scsi_in(task->sc)->length;
- iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
if (tcp_conn->in.datalen == 0)
return 0;
@@ -558,23 +556,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
return ISCSI_ERR_DATA_OFFSET;
}
- if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
- sc->result = (DID_OK << 16) | rhdr->cmd_status;
- conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
- if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
- ISCSI_FLAG_DATA_OVERFLOW)) {
- int res_count = be32_to_cpu(rhdr->residual_count);
-
- if (res_count > 0 &&
- (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
- res_count <= total_in_length))
- scsi_in(sc)->resid = res_count;
- else
- sc->result = (DID_BAD_TARGET << 16) |
- rhdr->cmd_status;
- }
- }
-
conn->datain_pdus_cnt++;
return 0;
}
@@ -774,7 +755,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
if (!task)
rc = ISCSI_ERR_BAD_ITT;
else
- rc = iscsi_data_rsp(conn, task);
+ rc = iscsi_data_in(conn, task);
if (rc) {
spin_unlock(&conn->session->lock);
break;
@@ -998,7 +979,7 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
error:
debug_tcp("Error receiving PDU, errno=%d\n", rc);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_failure(conn, rc);
return 0;
}
@@ -1117,8 +1098,10 @@ iscsi_xmit(struct iscsi_conn *conn)
while (1) {
rc = iscsi_tcp_xmit_segment(tcp_conn, segment);
- if (rc < 0)
+ if (rc < 0) {
+ rc = ISCSI_ERR_XMIT_FAILED;
goto error;
+ }
if (rc == 0)
break;
@@ -1127,7 +1110,7 @@ iscsi_xmit(struct iscsi_conn *conn)
if (segment->total_copied >= segment->total_size) {
if (segment->done != NULL) {
rc = segment->done(tcp_conn, segment);
- if (rc < 0)
+ if (rc != 0)
goto error;
}
}
@@ -1142,8 +1125,8 @@ error:
/* Transmit error. We could initiate error recovery
* here. */
debug_tcp("Error sending PDU, errno=%d\n", rc);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
- return rc;
+ iscsi_conn_failure(conn, rc);
+ return -EIO;
}
/**
@@ -1904,6 +1887,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
iscsi_r2tpool_free(cls_session->dd_data);
+ iscsi_session_teardown(cls_session);
iscsi_host_remove(shost);
iscsi_host_free(shost);
@@ -1927,7 +1911,7 @@ static struct scsi_host_template iscsi_sht = {
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
- .eh_host_reset_handler = iscsi_eh_host_reset,
+ .eh_target_reset_handler= iscsi_eh_target_reset,
.use_clustering = DISABLE_CLUSTERING,
.slave_configure = iscsi_tcp_slave_configure,
.proc_name = "iscsi_tcp",
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 299e075a7b3..801c7cf54d2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -404,11 +404,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
conn->session->queued_cmdsn--;
else
conn->session->tt->cleanup_task(conn, task);
- /*
- * Check if cleanup_task dropped the lock and the command completed,
- */
- if (!task->sc)
- return;
sc->result = err;
if (!scsi_bidi_cmnd(sc))
@@ -633,6 +628,40 @@ out:
__iscsi_put_task(task);
}
+/**
+ * iscsi_data_in_rsp - SCSI Data-In Response processing
+ * @conn: iscsi connection
+ * @hdr: iscsi pdu
+ * @task: scsi command task
+ **/
+static void
+iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ struct iscsi_task *task)
+{
+ struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)hdr;
+ struct scsi_cmnd *sc = task->sc;
+
+ if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
+ return;
+
+ sc->result = (DID_OK << 16) | rhdr->cmd_status;
+ conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+ if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
+ ISCSI_FLAG_DATA_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_in(sc)->length))
+ scsi_in(sc)->resid = res_count;
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ }
+
+ conn->scsirsp_pdus_cnt++;
+ __iscsi_put_task(task);
+}
+
static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
{
struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
@@ -818,12 +847,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
break;
case ISCSI_OP_SCSI_DATA_IN:
- if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
- conn->scsirsp_pdus_cnt++;
- iscsi_update_cmdsn(session,
- (struct iscsi_nopin*) hdr);
- __iscsi_put_task(task);
- }
+ iscsi_data_in_rsp(conn, hdr, task);
break;
case ISCSI_OP_LOGOUT_RSP:
iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
@@ -954,6 +978,38 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
}
EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
+void iscsi_session_failure(struct iscsi_cls_session *cls_session,
+ enum iscsi_err err)
+{
+ struct iscsi_session *session = cls_session->dd_data;
+ struct iscsi_conn *conn;
+ struct device *dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&session->lock, flags);
+ conn = session->leadconn;
+ if (session->state == ISCSI_STATE_TERMINATE || !conn) {
+ spin_unlock_irqrestore(&session->lock, flags);
+ return;
+ }
+
+ dev = get_device(&conn->cls_conn->dev);
+ spin_unlock_irqrestore(&session->lock, flags);
+ if (!dev)
+ return;
+ /*
+ * if the host is being removed bypass the connection
+ * recovery initialization because we are going to kill
+ * the session.
+ */
+ if (err == ISCSI_ERR_INVALID_HOST)
+ iscsi_conn_error_event(conn->cls_conn, err);
+ else
+ iscsi_conn_failure(conn, err);
+ put_device(dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_failure);
+
void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
{
struct iscsi_session *session = conn->session;
@@ -968,9 +1024,10 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
if (conn->stop_stage == 0)
session->state = ISCSI_STATE_FAILED;
spin_unlock_irqrestore(&session->lock, flags);
+
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
- iscsi_conn_error(conn->cls_conn, err);
+ iscsi_conn_error_event(conn->cls_conn, err);
}
EXPORT_SYMBOL_GPL(iscsi_conn_failure);
@@ -1194,15 +1251,13 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
switch (session->state) {
case ISCSI_STATE_IN_RECOVERY:
reason = FAILURE_SESSION_IN_RECOVERY;
- sc->result = DID_IMM_RETRY << 16;
- break;
+ goto reject;
case ISCSI_STATE_LOGGING_OUT:
reason = FAILURE_SESSION_LOGGING_OUT;
- sc->result = DID_IMM_RETRY << 16;
- break;
+ goto reject;
case ISCSI_STATE_RECOVERY_FAILED:
reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
- sc->result = DID_NO_CONNECT << 16;
+ sc->result = DID_TRANSPORT_FAILFAST << 16;
break;
case ISCSI_STATE_TERMINATE:
reason = FAILURE_SESSION_TERMINATE;
@@ -1267,7 +1322,7 @@ reject:
spin_unlock(&session->lock);
debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
spin_lock(host->host_lock);
- return SCSI_MLQUEUE_HOST_BUSY;
+ return SCSI_MLQUEUE_TARGET_BUSY;
fault:
spin_unlock(&session->lock);
@@ -1307,7 +1362,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
}
EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
-int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+int iscsi_eh_target_reset(struct scsi_cmnd *sc)
{
struct iscsi_cls_session *cls_session;
struct iscsi_session *session;
@@ -1321,7 +1376,7 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_TERMINATE) {
failed:
- debug_scsi("failing host reset: session terminated "
+ debug_scsi("failing target reset: session terminated "
"[CID %d age %d]\n", conn->id, session->age);
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
@@ -1336,7 +1391,7 @@ failed:
*/
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
- debug_scsi("iscsi_eh_host_reset wait for relogin\n");
+ debug_scsi("iscsi_eh_target_reset wait for relogin\n");
wait_event_interruptible(conn->ehwait,
session->state == ISCSI_STATE_TERMINATE ||
session->state == ISCSI_STATE_LOGGED_IN ||
@@ -1348,14 +1403,14 @@ failed:
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_LOGGED_IN)
iscsi_session_printk(KERN_INFO, session,
- "host reset succeeded\n");
+ "target reset succeeded\n");
else
goto failed;
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return SUCCESS;
}
-EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
+EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
static void iscsi_tmf_timedout(unsigned long data)
{
@@ -1456,7 +1511,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
if (lun == task->sc->device->lun || lun == -1) {
debug_scsi("failing in progress sc %p itt 0x%x\n",
task->sc, task->itt);
- fail_command(conn, task, DID_BUS_BUSY << 16);
+ fail_command(conn, task, error << 16);
}
}
}
@@ -1476,12 +1531,12 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
scsi_queue_work(conn->session->host, &conn->xmitwork);
}
-static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
{
struct iscsi_cls_session *cls_session;
struct iscsi_session *session;
struct iscsi_conn *conn;
- enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
+ enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
cls_session = starget_to_session(scsi_target(scmd->device));
session = cls_session->dd_data;
@@ -1494,14 +1549,14 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
* We are probably in the middle of iscsi recovery so let
* that complete and handle the error.
*/
- rc = EH_RESET_TIMER;
+ rc = BLK_EH_RESET_TIMER;
goto done;
}
conn = session->leadconn;
if (!conn) {
/* In the middle of shuting down */
- rc = EH_RESET_TIMER;
+ rc = BLK_EH_RESET_TIMER;
goto done;
}
@@ -1513,20 +1568,21 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
*/
if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
(conn->ping_timeout * HZ), jiffies))
- rc = EH_RESET_TIMER;
+ rc = BLK_EH_RESET_TIMER;
/*
* if we are about to check the transport then give the command
* more time
*/
if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
jiffies))
- rc = EH_RESET_TIMER;
+ rc = BLK_EH_RESET_TIMER;
/* if in the middle of checking the transport then give us more time */
if (conn->ping_task)
- rc = EH_RESET_TIMER;
+ rc = BLK_EH_RESET_TIMER;
done:
spin_unlock(&session->lock);
- debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh");
+ debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ?
+ "timer reset" : "nh");
return rc;
}
@@ -1768,10 +1824,10 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
iscsi_suspend_tx(conn);
- spin_lock(&session->lock);
+ spin_lock_bh(&session->lock);
fail_all_commands(conn, sc->device->lun, DID_ERROR);
conn->tmf_state = TMF_INITIAL;
- spin_unlock(&session->lock);
+ spin_unlock_bh(&session->lock);
iscsi_start_tx(conn);
goto done;
@@ -1877,6 +1933,7 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
int dd_data_size, uint16_t qdepth)
{
struct Scsi_Host *shost;
+ struct iscsi_host *ihost;
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
if (!shost)
@@ -1891,22 +1948,43 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
qdepth = ISCSI_DEF_CMD_PER_LUN;
}
shost->cmd_per_lun = qdepth;
+
+ ihost = shost_priv(shost);
+ spin_lock_init(&ihost->lock);
+ ihost->state = ISCSI_HOST_SETUP;
+ ihost->num_sessions = 0;
+ init_waitqueue_head(&ihost->session_removal_wq);
return shost;
}
EXPORT_SYMBOL_GPL(iscsi_host_alloc);
+static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
+{
+ iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
+}
+
/**
* iscsi_host_remove - remove host and sessions
* @shost: scsi host
*
- * This will also remove any sessions attached to the host, but if userspace
- * is managing the session at the same time this will break. TODO: add
- * refcounting to the netlink iscsi interface so a rmmod or host hot unplug
- * does not remove the memory from under us.
+ * If there are any sessions left, this will initiate the removal and wait
+ * for the completion.
*/
void iscsi_host_remove(struct Scsi_Host *shost)
{
- iscsi_host_for_each_session(shost, iscsi_session_teardown);
+ struct iscsi_host *ihost = shost_priv(shost);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ihost->lock, flags);
+ ihost->state = ISCSI_HOST_REMOVED;
+ spin_unlock_irqrestore(&ihost->lock, flags);
+
+ iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
+ wait_event_interruptible(ihost->session_removal_wq,
+ ihost->num_sessions == 0);
+ if (signal_pending(current))
+ flush_signals(current);
+
scsi_remove_host(shost);
}
EXPORT_SYMBOL_GPL(iscsi_host_remove);
@@ -1922,6 +2000,27 @@ void iscsi_host_free(struct Scsi_Host *shost)
}
EXPORT_SYMBOL_GPL(iscsi_host_free);
+static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost)
+{
+ struct iscsi_host *ihost = shost_priv(shost);
+ unsigned long flags;
+
+ shost = scsi_host_get(shost);
+ if (!shost) {
+ printk(KERN_ERR "Invalid state. Cannot notify host removal "
+ "of session teardown event because host already "
+ "removed.\n");
+ return;
+ }
+
+ spin_lock_irqsave(&ihost->lock, flags);
+ ihost->num_sessions--;
+ if (ihost->num_sessions == 0)
+ wake_up(&ihost->session_removal_wq);
+ spin_unlock_irqrestore(&ihost->lock, flags);
+ scsi_host_put(shost);
+}
+
/**
* iscsi_session_setup - create iscsi cls session and host and session
* @iscsit: iscsi transport template
@@ -1942,9 +2041,19 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
uint16_t cmds_max, int cmd_task_size,
uint32_t initial_cmdsn, unsigned int id)
{
+ struct iscsi_host *ihost = shost_priv(shost);
struct iscsi_session *session;
struct iscsi_cls_session *cls_session;
int cmd_i, scsi_cmds, total_cmds = cmds_max;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ihost->lock, flags);
+ if (ihost->state == ISCSI_HOST_REMOVED) {
+ spin_unlock_irqrestore(&ihost->lock, flags);
+ return NULL;
+ }
+ ihost->num_sessions++;
+ spin_unlock_irqrestore(&ihost->lock, flags);
if (!total_cmds)
total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
@@ -1957,7 +2066,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
"must be a power of two that is at least %d.\n",
total_cmds, ISCSI_TOTAL_CMDS_MIN);
- return NULL;
+ goto dec_session_count;
}
if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
@@ -1981,7 +2090,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
cls_session = iscsi_alloc_session(shost, iscsit,
sizeof(struct iscsi_session));
if (!cls_session)
- return NULL;
+ goto dec_session_count;
session = cls_session->dd_data;
session->cls_session = cls_session;
session->host = shost;
@@ -2020,6 +2129,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
if (iscsi_add_session(cls_session, id))
goto cls_session_fail;
+
return cls_session;
cls_session_fail:
@@ -2028,6 +2138,8 @@ module_get_fail:
iscsi_pool_free(&session->cmdpool);
cmdpool_alloc_fail:
iscsi_free_session(cls_session);
+dec_session_count:
+ iscsi_host_dec_session_cnt(shost);
return NULL;
}
EXPORT_SYMBOL_GPL(iscsi_session_setup);
@@ -2043,6 +2155,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
{
struct iscsi_session *session = cls_session->dd_data;
struct module *owner = cls_session->transport->owner;
+ struct Scsi_Host *shost = session->host;
iscsi_pool_free(&session->cmdpool);
@@ -2055,6 +2168,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
kfree(session->ifacename);
iscsi_destroy_session(cls_session);
+ iscsi_host_dec_session_cnt(shost);
module_put(owner);
}
EXPORT_SYMBOL_GPL(iscsi_session_teardown);
@@ -2334,8 +2448,10 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
* flush queues.
*/
spin_lock_bh(&session->lock);
- fail_all_commands(conn, -1,
- STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR);
+ if (flag == STOP_CONN_RECOVER)
+ fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED);
+ else
+ fail_all_commands(conn, -1, DID_ERROR);
flush_control_queues(session, conn);
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 48ee8c7f5bd..e1550117069 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -294,10 +294,10 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
}
}
-static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+static int sas_ata_scr_write(struct ata_link *link, unsigned int sc_reg_in,
u32 val)
{
- struct domain_device *dev = ap->private_data;
+ struct domain_device *dev = link->ap->private_data;
SAS_DPRINTK("STUB %s\n", __func__);
switch (sc_reg_in) {
@@ -319,10 +319,10 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
return 0;
}
-static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
+static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in,
u32 *val)
{
- struct domain_device *dev = ap->private_data;
+ struct domain_device *dev = link->ap->private_data;
SAS_DPRINTK("STUB %s\n", __func__);
switch (sc_reg_in) {
@@ -398,7 +398,7 @@ void sas_ata_task_abort(struct sas_task *task)
/* Bounce SCSI-initiated commands to the SCSI EH */
if (qc->scsicmd) {
- scsi_req_abort_cmd(qc->scsicmd);
+ blk_abort_request(qc->scsicmd->request);
scsi_schedule_eh(qc->scsicmd->device->host);
return;
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index b4f9368f116..0001374bd6b 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -55,7 +55,7 @@ void sas_unregister_phys(struct sas_ha_struct *sas_ha);
int sas_register_ports(struct sas_ha_struct *sas_ha);
void sas_unregister_ports(struct sas_ha_struct *sas_ha);
-enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
+enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
int sas_init_queue(struct sas_ha_struct *sas_ha);
int sas_init_events(struct sas_ha_struct *sas_ha);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index a8e3ef30907..744838780ad 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -673,43 +673,43 @@ out:
return;
}
-enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
+enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
{
struct sas_task *task = TO_SAS_TASK(cmd);
unsigned long flags;
if (!task) {
- cmd->timeout_per_command /= 2;
+ cmd->request->timeout /= 2;
SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n",
- cmd, task, (cmd->timeout_per_command ?
- "EH_RESET_TIMER" : "EH_NOT_HANDLED"));
- if (!cmd->timeout_per_command)
- return EH_NOT_HANDLED;
- return EH_RESET_TIMER;
+ cmd, task, (cmd->request->timeout ?
+ "BLK_EH_RESET_TIMER" : "BLK_EH_NOT_HANDLED"));
+ if (!cmd->request->timeout)
+ return BLK_EH_NOT_HANDLED;
+ return BLK_EH_RESET_TIMER;
}
spin_lock_irqsave(&task->task_state_lock, flags);
BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
- SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
- cmd, task);
- return EH_HANDLED;
+ SAS_DPRINTK("command 0x%p, task 0x%p, timed out: "
+ "BLK_EH_HANDLED\n", cmd, task);
+ return BLK_EH_HANDLED;
}
if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
- "EH_RESET_TIMER\n",
+ "BLK_EH_RESET_TIMER\n",
cmd, task);
- return EH_RESET_TIMER;
+ return BLK_EH_RESET_TIMER;
}
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_NOT_HANDLED\n",
+ SAS_DPRINTK("command 0x%p, task 0x%p, timed out: BLK_EH_NOT_HANDLED\n",
cmd, task);
- return EH_NOT_HANDLED;
+ return BLK_EH_NOT_HANDLED;
}
int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
@@ -1039,7 +1039,7 @@ void sas_task_abort(struct sas_task *task)
return;
}
- scsi_req_abort_cmd(sc);
+ blk_abort_request(sc->request);
scsi_schedule_eh(sc->device->host);
}
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index e0e018d1265..60a9e6e9384 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -34,7 +34,14 @@ struct lpfc_sli2_slim;
#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 LPFC_VNAME_LEN 100 /* vport symbolic name length */
-
+#define LPFC_TGTQ_INTERVAL 40000 /* Min amount of time between tgt
+ queue depth change in millisecs */
+#define LPFC_TGTQ_RAMPUP_PCENT 5 /* Target queue rampup in percentage */
+#define LPFC_MIN_TGT_QDEPTH 100
+#define LPFC_MAX_TGT_QDEPTH 0xFFFF
+
+#define LPFC_MAX_BUCKET_COUNT 20 /* Maximum no. of buckets for stat data
+ collection. */
/*
* Following time intervals are used of adjusting SCSI device
* queue depths when there are driver resource error or Firmware
@@ -49,6 +56,9 @@ struct lpfc_sli2_slim;
#define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */
#define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */
+/* Error Attention event polling interval */
+#define LPFC_ERATT_POLL_INTERVAL 5 /* EATT poll interval in seconds */
+
/* Define macros for 64 bit support */
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
#define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
@@ -60,6 +70,9 @@ struct lpfc_sli2_slim;
#define MAX_HBAEVT 32
+/* Number of MSI-X vectors the driver uses */
+#define LPFC_MSIX_VECTORS 2
+
/* lpfc wait event data ready flag */
#define LPFC_DATA_READY (1<<0)
@@ -357,6 +370,7 @@ struct lpfc_vport {
uint32_t cfg_log_verbose;
uint32_t cfg_max_luns;
uint32_t cfg_enable_da_id;
+ uint32_t cfg_max_scsicmpl_time;
uint32_t dev_loss_tmo_changed;
@@ -369,6 +383,8 @@ struct lpfc_vport {
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
#endif
+ uint8_t stat_data_enabled;
+ uint8_t stat_data_blocked;
};
struct hbq_s {
@@ -407,10 +423,11 @@ struct lpfc_hba {
struct lpfc_sli sli;
uint32_t sli_rev; /* SLI2 or SLI3 */
uint32_t sli3_options; /* Mask of enabled SLI3 options */
-#define LPFC_SLI3_ENABLED 0x01
-#define LPFC_SLI3_HBQ_ENABLED 0x02
-#define LPFC_SLI3_NPIV_ENABLED 0x04
-#define LPFC_SLI3_VPORT_TEARDOWN 0x08
+#define LPFC_SLI3_HBQ_ENABLED 0x01
+#define LPFC_SLI3_NPIV_ENABLED 0x02
+#define LPFC_SLI3_VPORT_TEARDOWN 0x04
+#define LPFC_SLI3_CRP_ENABLED 0x08
+#define LPFC_SLI3_INB_ENABLED 0x10
uint32_t iocb_cmd_size;
uint32_t iocb_rsp_size;
@@ -422,10 +439,20 @@ struct lpfc_hba {
#define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */
#define LS_IGNORE_ERATT 0x4 /* intr handler should ignore ERATT */
- struct lpfc_sli2_slim *slim2p;
- struct lpfc_dmabuf hbqslimp;
+ uint32_t hba_flag; /* hba generic flags */
+#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
+
+ struct lpfc_dmabuf slim2p;
- dma_addr_t slim2p_mapping;
+ MAILBOX_t *mbox;
+ uint32_t *inb_ha_copy;
+ uint32_t *inb_counter;
+ uint32_t inb_last_counter;
+ uint32_t ha_copy;
+ struct _PCB *pcb;
+ struct _IOCB *IOCBs;
+
+ struct lpfc_dmabuf hbqslimp;
uint16_t pci_cfg_value;
@@ -492,7 +519,7 @@ struct lpfc_hba {
wait_queue_head_t work_waitq;
struct task_struct *worker_thread;
- long data_flags;
+ unsigned long data_flags;
uint32_t hbq_in_use; /* HBQs in use flag */
struct list_head hbqbuf_in_list; /* in-fly hbq buffer list */
@@ -514,6 +541,7 @@ struct lpfc_hba {
void __iomem *HCregaddr; /* virtual address for host ctl reg */
struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */
+ struct lpfc_pgp *port_gp;
uint32_t __iomem *hbq_put; /* Address in SLIM to HBQ put ptrs */
uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */
@@ -536,6 +564,7 @@ struct lpfc_hba {
uint8_t soft_wwn_enable;
struct timer_list fcp_poll_timer;
+ struct timer_list eratt_poll;
/*
* stat counters
@@ -565,7 +594,7 @@ struct lpfc_hba {
struct fc_host_statistics link_stats;
enum intr_type_t intr_type;
- struct msix_entry msix_entries[1];
+ struct msix_entry msix_entries[LPFC_MSIX_VECTORS];
struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
@@ -605,6 +634,7 @@ struct lpfc_hba {
unsigned long last_completion_time;
struct timer_list hb_tmofunc;
uint8_t hb_outstanding;
+ enum hba_temp_state over_temp_state;
/* ndlp reference management */
spinlock_t ndlp_lock;
/*
@@ -613,7 +643,19 @@ struct lpfc_hba {
*/
#define QUE_BUFTAG_BIT (1<<31)
uint32_t buffer_tag_count;
- enum hba_temp_state over_temp_state;
+ int wait_4_mlo_maint_flg;
+ wait_queue_head_t wait_4_mlo_m_q;
+ /* data structure used for latency data collection */
+#define LPFC_NO_BUCKET 0
+#define LPFC_LINEAR_BUCKET 1
+#define LPFC_POWER2_BUCKET 2
+ uint8_t bucket_type;
+ uint32_t bucket_base;
+ uint32_t bucket_step;
+
+/* Maximum number of events that can be outstanding at any time*/
+#define LPFC_MAX_EVT_COUNT 512
+ atomic_t fast_event_count;
};
static inline struct Scsi_Host *
@@ -650,15 +692,25 @@ lpfc_worker_wake_up(struct lpfc_hba *phba)
return;
}
-#define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */
-#define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature
- event */
+static inline void
+lpfc_sli_read_hs(struct lpfc_hba *phba)
+{
+ /*
+ * There was a link/board error. Read the status register to retrieve
+ * the error event and process it.
+ */
+ phba->sli.slistat.err_attn_event++;
+
+ /* Save status info */
+ phba->work_hs = readl(phba->HSregaddr);
+ phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
+ phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
+
+ /* Clear chip Host Attention error bit */
+ writel(HA_ERATT, phba->HAregaddr);
+ readl(phba->HAregaddr); /* flush */
+ phba->pport->stopped = 1;
+
+ return;
+}
-struct temp_event {
- uint32_t event_type;
- uint32_t event_code;
- uint32_t data;
-};
-#define LPFC_CRIT_TEMP 0x1
-#define LPFC_THRESHOLD_TEMP 0x2
-#define LPFC_NORMAL_TEMP 0x3
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 37bfa0bd1da..aa3d6277581 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -32,6 +32,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -49,6 +50,21 @@
#define LPFC_LINK_SPEED_BITMAP 0x00000117
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
+/**
+ * lpfc_jedec_to_ascii: Hex to ascii convertor according to JEDEC rules.
+ * @incr: integer to convert.
+ * @hdw: ascii string holding converted integer plus a string terminator.
+ *
+ * Description:
+ * JEDEC Joint Electron Device Engineering Council.
+ * Convert a 32 bit integer composed of 8 nibbles into an 8 byte ascii
+ * character string. The string is then terminated with a NULL in byte 9.
+ * Hex 0-9 becomes ascii '0' to '9'.
+ * Hex a-f becomes ascii '=' to 'B' capital B.
+ *
+ * Notes:
+ * Coded for 32 bit integers only.
+ **/
static void
lpfc_jedec_to_ascii(int incr, char hdw[])
{
@@ -65,6 +81,14 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
return;
}
+/**
+ * lpfc_drvr_version_show: Return the Emulex driver string with version number.
+ * @dev: class unused variable.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the module description text.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -72,6 +96,14 @@ lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
}
+/**
+ * lpfc_info_show: Return some pci info about the host in ascii.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the formatted text from lpfc_info().
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_info_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -81,6 +113,14 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
}
+/**
+ * lpfc_serialnum_show: Return the hba serial number in ascii.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the formatted text serial number.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -92,6 +132,18 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
}
+/**
+ * lpfc_temp_sensor_show: Return the temperature sensor level.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the formatted support level.
+ *
+ * Description:
+ * Returns a number indicating the temperature sensor level currently
+ * supported, zero or one in ascii.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -102,6 +154,14 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
}
+/**
+ * lpfc_modeldesc_show: Return the model description of the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the scsi vpd model description.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -113,6 +173,14 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
}
+/**
+ * lpfc_modelname_show: Return the model name of the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the scsi vpd model name.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -124,6 +192,14 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
}
+/**
+ * lpfc_programtype_show: Return the program type of the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the scsi vpd program type.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -135,6 +211,33 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
}
+/**
+ * lpfc_mlomgmt_show: Return the Menlo Maintenance sli flag.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the Menlo Maintenance sli flag.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (phba->sli.sli_flag & LPFC_MENLO_MAINT));
+}
+
+/**
+ * lpfc_vportnum_show: Return the port number in ascii of the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains scsi vpd program type.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -146,6 +249,14 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
}
+/**
+ * lpfc_fwrev_show: Return the firmware rev running in the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the scsi vpd program type.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -159,6 +270,14 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
}
+/**
+ * lpfc_hdw_show: Return the jedec information about the hba.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the scsi vpd program type.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -171,6 +290,15 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
}
+
+/**
+ * lpfc_option_rom_version_show: Return the adapter ROM FCode version.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the ROM and FCode ascii strings.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -181,6 +309,18 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
}
+
+/**
+ * lpfc_state_show: Return the link state of the port.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains text describing the state of the link.
+ *
+ * Notes:
+ * The switch statement has no default so zero will be returned.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -232,8 +372,10 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
"Unknown\n");
break;
}
-
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ " Menlo Maint Mode\n");
+ else if (phba->fc_topology == TOPOLOGY_LOOP) {
if (vport->fc_flag & FC_PUBLIC_LOOP)
len += snprintf(buf + len, PAGE_SIZE-len,
" Public Loop\n");
@@ -253,6 +395,18 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
return len;
}
+/**
+ * lpfc_num_discovered_ports_show: Return sum of mapped and unmapped vports.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the sum of fc mapped and unmapped.
+ *
+ * Description:
+ * Returns the ascii text number of the sum of the fc mapped and unmapped
+ * vport counts.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_num_discovered_ports_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -264,7 +418,20 @@ lpfc_num_discovered_ports_show(struct device *dev,
vport->fc_map_cnt + vport->fc_unmap_cnt);
}
-
+/**
+ * lpfc_issue_lip: Misnomer, name carried over from long ago.
+ * @shost: Scsi_Host pointer.
+ *
+ * Description:
+ * Bring the link down gracefully then re-init the link. The firmware will
+ * re-init the fiber channel interface as required. Does not issue a LIP.
+ *
+ * Returns:
+ * -EPERM port offline or management commands are being blocked
+ * -ENOMEM cannot allocate memory for the mailbox command
+ * -EIO error sending the mailbox command
+ * zero for success
+ **/
static int
lpfc_issue_lip(struct Scsi_Host *shost)
{
@@ -306,6 +473,21 @@ lpfc_issue_lip(struct Scsi_Host *shost)
return 0;
}
+/**
+ * lpfc_do_offline: Issues a mailbox command to bring the link down.
+ * @phba: lpfc_hba pointer.
+ * @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL.
+ *
+ * Notes:
+ * Assumes any error from lpfc_do_offline() will be negative.
+ * Can wait up to 5 seconds for the port ring buffers count
+ * to reach zero, prints a warning if it is not zero and continues.
+ * lpfc_workq_post_event() returns a non-zero return coce if call fails.
+ *
+ * Returns:
+ * -EIO error posting the event
+ * zero for success
+ **/
static int
lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
{
@@ -353,6 +535,22 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
return 0;
}
+/**
+ * lpfc_selective_reset: Offline then onlines the port.
+ * @phba: lpfc_hba pointer.
+ *
+ * Description:
+ * If the port is configured to allow a reset then the hba is brought
+ * offline then online.
+ *
+ * Notes:
+ * Assumes any error from lpfc_do_offline() will be negative.
+ *
+ * Returns:
+ * lpfc_do_offline() return code if not zero
+ * -EIO reset not configured or error posting the event
+ * zero for success
+ **/
static int
lpfc_selective_reset(struct lpfc_hba *phba)
{
@@ -378,6 +576,27 @@ lpfc_selective_reset(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_issue_reset: Selectively resets an adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing the string "selective".
+ * @count: unused variable.
+ *
+ * Description:
+ * If the buf contains the string "selective" then lpfc_selective_reset()
+ * is called to perform the reset.
+ *
+ * Notes:
+ * Assumes any error from lpfc_selective_reset() will be negative.
+ * If lpfc_selective_reset() returns zero then the length of the buffer
+ * is returned which indicates succcess
+ *
+ * Returns:
+ * -EINVAL if the buffer does not contain the string "selective"
+ * length of buf if lpfc-selective_reset() if the call succeeds
+ * return value of lpfc_selective_reset() if the call fails
+**/
static ssize_t
lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -397,6 +616,14 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
return status;
}
+/**
+ * lpfc_nport_evt_cnt_show: Return the number of nport events.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the ascii number of nport events.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -408,6 +635,14 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
}
+/**
+ * lpfc_board_mode_show: Return the state of the board.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the state of the adapter.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -429,6 +664,19 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n", state);
}
+/**
+ * lpfc_board_mode_store: Puts the hba in online, offline, warm or error state.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing one of the strings "online", "offline", "warm" or "error".
+ * @count: unused variable.
+ *
+ * Returns:
+ * -EACCES if enable hba reset not enabled
+ * -EINVAL if the buffer does not contain a valid string (see above)
+ * -EIO if lpfc_workq_post_event() or lpfc_do_offline() fails
+ * buf length greater than zero indicates success
+ **/
static ssize_t
lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -462,6 +710,24 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
return -EIO;
}
+/**
+ * lpfc_get_hba_info: Return various bits of informaton about the adapter.
+ * @phba: pointer to the adapter structure.
+ * @mxri max xri count.
+ * @axri available xri count.
+ * @mrpi max rpi count.
+ * @arpi available rpi count.
+ * @mvpi max vpi count.
+ * @avpi available vpi count.
+ *
+ * Description:
+ * If an integer pointer for an count is not null then the value for the
+ * count is returned.
+ *
+ * Returns:
+ * zero on error
+ * one for success
+ **/
static int
lpfc_get_hba_info(struct lpfc_hba *phba,
uint32_t *mxri, uint32_t *axri,
@@ -524,6 +790,20 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
return 1;
}
+/**
+ * lpfc_max_rpi_show: Return maximum rpi.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the maximum rpi count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mrpi count.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -538,6 +818,20 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_used_rpi_show: Return maximum rpi minus available rpi.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing the used rpi count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mrpi and arpi counts.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -552,6 +846,20 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_max_xri_show: Return maximum xri.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the maximum xri count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mrpi count.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -566,6 +874,20 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_used_xri_show: Return maximum xpi minus the available xpi.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the used xri count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mxri and axri counts.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -580,6 +902,20 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_max_vpi_show: Return maximum vpi.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the maximum vpi count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mvpi count.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -594,6 +930,20 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_used_vpi_show: Return maximum vpi minus the available vpi.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the used vpi count in decimal or "Unknown".
+ *
+ * Description:
+ * Calls lpfc_get_hba_info() asking for just the mvpi and avpi counts.
+ * If lpfc_get_hba_info() returns zero (failure) the buffer text is set
+ * to "Unknown" and the buffer length is returned, therefore the caller
+ * must check for "Unknown" in the buffer to detect a failure.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -608,6 +958,19 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n");
}
+/**
+ * lpfc_npiv_info_show: Return text about NPIV support for the adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: text that must be interpreted to determine if npiv is supported.
+ *
+ * Description:
+ * Buffer will contain text indicating npiv is not suppoerted on the port,
+ * the port is an NPIV physical port, or it is an npiv virtual port with
+ * the id of the vport.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -623,6 +986,17 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
}
+/**
+ * lpfc_poll_show: Return text about poll support for the adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the cfg_poll in hex.
+ *
+ * Notes:
+ * cfg_poll should be a lpfc_polling_flags type.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_poll_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -634,6 +1008,20 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
}
+/**
+ * lpfc_poll_store: Set the value of cfg_poll for the adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: one or more lpfc_polling_flags values.
+ * @count: not used.
+ *
+ * Notes:
+ * buf contents converted to integer and checked for a valid value.
+ *
+ * Returns:
+ * -EINVAL if the buffer connot be converted or is out of range
+ * length of the buf on success
+ **/
static ssize_t
lpfc_poll_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -692,6 +1080,20 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
return strlen(buf);
}
+/**
+ * lpfc_param_show: Return a cfg attribute value in decimal.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_show.
+ *
+ * lpfc_##attr##_show: Return the decimal value of an adapters cfg_xxx field.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the attribute value in decimal.
+ *
+ * Returns: size of formatted string.
+ **/
#define lpfc_param_show(attr) \
static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
@@ -706,6 +1108,20 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
phba->cfg_##attr);\
}
+/**
+ * lpfc_param_hex_show: Return a cfg attribute value in hex.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_show
+ *
+ * lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the attribute value in hexidecimal.
+ *
+ * Returns: size of formatted string.
+ **/
#define lpfc_param_hex_show(attr) \
static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
@@ -720,6 +1136,25 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
phba->cfg_##attr);\
}
+/**
+ * lpfc_param_init: Intializes a cfg attribute.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_init. The macro also
+ * takes a default argument, a minimum and maximum argument.
+ *
+ * lpfc_##attr##_init: Initializes an attribute.
+ * @phba: pointer the the adapter structure.
+ * @val: integer attribute value.
+ *
+ * Validates the min and max values then sets the adapter config field
+ * accordingly, or uses the default if out of range and prints an error message.
+ *
+ * Returns:
+ * zero on success
+ * -EINVAL if default used
+ **/
#define lpfc_param_init(attr, default, minval, maxval) \
static int \
lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
@@ -735,6 +1170,26 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
return -EINVAL;\
}
+/**
+ * lpfc_param_set: Set a cfg attribute value.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_set
+ *
+ * lpfc_##attr##_set: Sets an attribute value.
+ * @phba: pointer the the adapter structure.
+ * @val: integer attribute value.
+ *
+ * Description:
+ * Validates the min and max values then sets the
+ * adapter config field if in the valid range. prints error message
+ * and does not set the parameter if invalid.
+ *
+ * Returns:
+ * zero on success
+ * -EINVAL if val is invalid
+ **/
#define lpfc_param_set(attr, default, minval, maxval) \
static int \
lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
@@ -749,6 +1204,27 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
return -EINVAL;\
}
+/**
+ * lpfc_param_store: Set a vport attribute value.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_store.
+ *
+ * lpfc_##attr##_store: Set an sttribute value.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: contains the attribute value in ascii.
+ * @count: not used.
+ *
+ * Description:
+ * Convert the ascii text number to an integer, then
+ * use the lpfc_##attr##_set function to set the value.
+ *
+ * Returns:
+ * -EINVAL if val is invalid or lpfc_##attr##_set() fails
+ * length of buffer upon success.
+ **/
#define lpfc_param_store(attr) \
static ssize_t \
lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
@@ -768,6 +1244,20 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
return -EINVAL;\
}
+/**
+ * lpfc_vport_param_show: Return decimal formatted cfg attribute value.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_show
+ *
+ * lpfc_##attr##_show: prints the attribute value in decimal.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the attribute value in decimal.
+ *
+ * Returns: length of formatted string.
+ **/
#define lpfc_vport_param_show(attr) \
static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
@@ -780,6 +1270,21 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
}
+/**
+ * lpfc_vport_param_hex_show: Return hex formatted attribute value.
+ *
+ * Description:
+ * Macro that given an attr e.g.
+ * hba_queue_depth expands into a function with the name
+ * lpfc_hba_queue_depth_show
+ *
+ * lpfc_##attr##_show: prints the attribute value in hexidecimal.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the attribute value in hexidecimal.
+ *
+ * Returns: length of formatted string.
+ **/
#define lpfc_vport_param_hex_show(attr) \
static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
@@ -792,6 +1297,24 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
}
+/**
+ * lpfc_vport_param_init: Initialize a vport cfg attribute.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_init. The macro also
+ * takes a default argument, a minimum and maximum argument.
+ *
+ * lpfc_##attr##_init: validates the min and max values then sets the
+ * adapter config field accordingly, or uses the default if out of range
+ * and prints an error message.
+ * @phba: pointer the the adapter structure.
+ * @val: integer attribute value.
+ *
+ * Returns:
+ * zero on success
+ * -EINVAL if default used
+ **/
#define lpfc_vport_param_init(attr, default, minval, maxval) \
static int \
lpfc_##attr##_init(struct lpfc_vport *vport, int val) \
@@ -801,12 +1324,29 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \
return 0;\
}\
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
- "0449 lpfc_"#attr" attribute cannot be set to %d, "\
+ "0423 lpfc_"#attr" attribute cannot be set to %d, "\
"allowed range is ["#minval", "#maxval"]\n", val); \
vport->cfg_##attr = default;\
return -EINVAL;\
}
+/**
+ * lpfc_vport_param_set: Set a vport cfg attribute.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth expands
+ * into a function with the name lpfc_hba_queue_depth_set
+ *
+ * lpfc_##attr##_set: validates the min and max values then sets the
+ * adapter config field if in the valid range. prints error message
+ * and does not set the parameter if invalid.
+ * @phba: pointer the the adapter structure.
+ * @val: integer attribute value.
+ *
+ * Returns:
+ * zero on success
+ * -EINVAL if val is invalid
+ **/
#define lpfc_vport_param_set(attr, default, minval, maxval) \
static int \
lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
@@ -816,11 +1356,28 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
return 0;\
}\
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
- "0450 lpfc_"#attr" attribute cannot be set to %d, "\
+ "0424 lpfc_"#attr" attribute cannot be set to %d, "\
"allowed range is ["#minval", "#maxval"]\n", val); \
return -EINVAL;\
}
+/**
+ * lpfc_vport_param_store: Set a vport attribute.
+ *
+ * Description:
+ * Macro that given an attr e.g. hba_queue_depth
+ * expands into a function with the name lpfc_hba_queue_depth_store
+ *
+ * lpfc_##attr##_store: convert the ascii text number to an integer, then
+ * use the lpfc_##attr##_set function to set the value.
+ * @cdev: class device that is converted into a Scsi_host.
+ * @buf: contains the attribute value in decimal.
+ * @count: not used.
+ *
+ * Returns:
+ * -EINVAL if val is invalid or lpfc_##attr##_set() fails
+ * length of buffer upon success.
+ **/
#define lpfc_vport_param_store(attr) \
static ssize_t \
lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
@@ -941,6 +1498,7 @@ static DEVICE_ATTR(option_rom_version, S_IRUGO,
lpfc_option_rom_version_show, NULL);
static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
lpfc_num_discovered_ports_show, NULL);
+static DEVICE_ATTR(menlo_mgmt_mode, S_IRUGO, lpfc_mlomgmt_show, NULL);
static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
static DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL);
static DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
@@ -958,6 +1516,17 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
+/**
+ * lpfc_soft_wwn_enable_store: Allows setting of the wwn if the key is valid.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing the string lpfc_soft_wwn_key.
+ * @count: must be size of lpfc_soft_wwn_key.
+ *
+ * Returns:
+ * -EINVAL if the buffer does not contain lpfc_soft_wwn_key
+ * length of buf indicates success
+ **/
static ssize_t
lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -994,6 +1563,14 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
lpfc_soft_wwn_enable_store);
+/**
+ * lpfc_soft_wwpn_show: Return the cfg soft ww port name of the adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the wwpn in hexidecimal.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1006,7 +1583,19 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
(unsigned long long)phba->cfg_soft_wwpn);
}
-
+/**
+ * lpfc_soft_wwpn_store: Set the ww port name of the adapter.
+ * @dev class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: contains the wwpn in hexidecimal.
+ * @count: number of wwpn bytes in buf
+ *
+ * Returns:
+ * -EACCES hba reset not enabled, adapter over temp
+ * -EINVAL soft wwn not enabled, count is invalid, invalid wwpn byte invalid
+ * -EIO error taking adapter offline or online
+ * value of count on success
+ **/
static ssize_t
lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -1080,6 +1669,14 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
+/**
+ * lpfc_soft_wwnn_show: Return the cfg soft ww node name for the adapter.
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the wwnn in hexidecimal.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1090,7 +1687,16 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
(unsigned long long)phba->cfg_soft_wwnn);
}
-
+/**
+ * lpfc_soft_wwnn_store: sets the ww node name of the adapter.
+ * @cdev: class device that is converted into a Scsi_host.
+ * @buf: contains the ww node name in hexidecimal.
+ * @count: number of wwnn bytes in buf.
+ *
+ * Returns:
+ * -EINVAL soft wwn not enabled, count is invalid, invalid wwnn byte invalid
+ * value of count on success
+ **/
static ssize_t
lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -1178,6 +1784,15 @@ module_param(lpfc_nodev_tmo, int, 0);
MODULE_PARM_DESC(lpfc_nodev_tmo,
"Seconds driver will hold I/O waiting "
"for a device to come back");
+
+/**
+ * lpfc_nodev_tmo_show: Return the hba dev loss timeout value.
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the dev loss timeout in decimal.
+ *
+ * Returns: size of formatted string.
+ **/
static ssize_t
lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1189,6 +1804,21 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo);
}
+/**
+ * lpfc_nodev_tmo_init: Set the hba nodev timeout value.
+ * @vport: lpfc vport structure pointer.
+ * @val: contains the nodev timeout value.
+ *
+ * Description:
+ * If the devloss tmo is already set then nodev tmo is set to devloss tmo,
+ * a kernel error message is printed and zero is returned.
+ * Else if val is in range then nodev tmo and devloss tmo are set to val.
+ * Otherwise nodev tmo is set to the default value.
+ *
+ * Returns:
+ * zero if already set or if val is in range
+ * -EINVAL val out of range
+ **/
static int
lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
{
@@ -1196,7 +1826,7 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
vport->cfg_nodev_tmo = vport->cfg_devloss_tmo;
if (val != LPFC_DEF_DEVLOSS_TMO)
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0402 Ignoring nodev_tmo module "
+ "0407 Ignoring nodev_tmo module "
"parameter because devloss_tmo is "
"set.\n");
return 0;
@@ -1215,6 +1845,13 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
return -EINVAL;
}
+/**
+ * lpfc_update_rport_devloss_tmo: Update dev loss tmo value.
+ * @vport: lpfc vport structure pointer.
+ *
+ * Description:
+ * Update all the ndlp's dev loss tmo with the vport devloss tmo value.
+ **/
static void
lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
{
@@ -1229,6 +1866,21 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
spin_unlock_irq(shost->host_lock);
}
+/**
+ * lpfc_nodev_tmo_set: Set the vport nodev tmo and devloss tmo values.
+ * @vport: lpfc vport structure pointer.
+ * @val: contains the tmo value.
+ *
+ * Description:
+ * If the devloss tmo is already set or the vport dev loss tmo has changed
+ * then a kernel error message is printed and zero is returned.
+ * Else if val is in range then nodev tmo and devloss tmo are set to val.
+ * Otherwise nodev tmo is set to the default value.
+ *
+ * Returns:
+ * zero if already set or if val is in range
+ * -EINVAL val out of range
+ **/
static int
lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
{
@@ -1269,6 +1921,21 @@ MODULE_PARM_DESC(lpfc_devloss_tmo,
lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,
LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO)
lpfc_vport_param_show(devloss_tmo)
+
+/**
+ * lpfc_devloss_tmo_set: Sets vport nodev tmo, devloss tmo values, changed bit.
+ * @vport: lpfc vport structure pointer.
+ * @val: contains the tmo value.
+ *
+ * Description:
+ * If val is in a valid range then set the vport nodev tmo,
+ * devloss tmo, also set the vport dev loss tmo changed flag.
+ * Else a kernel error message is printed.
+ *
+ * Returns:
+ * zero if val is in range
+ * -EINVAL val out of range
+ **/
static int
lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
{
@@ -1366,12 +2033,27 @@ MODULE_PARM_DESC(lpfc_restrict_login,
"Restrict virtual ports login to remote initiators.");
lpfc_vport_param_show(restrict_login);
+/**
+ * lpfc_restrict_login_init: Set the vport restrict login flag.
+ * @vport: lpfc vport structure pointer.
+ * @val: contains the restrict login value.
+ *
+ * Description:
+ * If val is not in a valid range then log a kernel error message and set
+ * the vport restrict login to one.
+ * If the port type is physical clear the restrict login flag and return.
+ * Else set the restrict login flag to val.
+ *
+ * Returns:
+ * zero if val is in range
+ * -EINVAL val out of range
+ **/
static int
lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
{
if (val < 0 || val > 1) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0449 lpfc_restrict_login attribute cannot "
+ "0422 lpfc_restrict_login attribute cannot "
"be set to %d, allowed range is [0, 1]\n",
val);
vport->cfg_restrict_login = 1;
@@ -1385,12 +2067,28 @@ lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
return 0;
}
+/**
+ * lpfc_restrict_login_set: Set the vport restrict login flag.
+ * @vport: lpfc vport structure pointer.
+ * @val: contains the restrict login value.
+ *
+ * Description:
+ * If val is not in a valid range then log a kernel error message and set
+ * the vport restrict login to one.
+ * If the port type is physical and the val is not zero log a kernel
+ * error message, clear the restrict login flag and return zero.
+ * Else set the restrict login flag to val.
+ *
+ * Returns:
+ * zero if val is in range
+ * -EINVAL val out of range
+ **/
static int
lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
{
if (val < 0 || val > 1) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0450 lpfc_restrict_login attribute cannot "
+ "0425 lpfc_restrict_login attribute cannot "
"be set to %d, allowed range is [0, 1]\n",
val);
vport->cfg_restrict_login = 1;
@@ -1441,6 +2139,23 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
# Default value is 0.
*/
+
+/**
+ * lpfc_topology_set: Set the adapters topology field.
+ * @phba: lpfc_hba pointer.
+ * @val: topology value.
+ *
+ * Description:
+ * If val is in a valid range then set the adapter's topology field and
+ * issue a lip; if the lip fails reset the topology to the old value.
+ *
+ * If the value is not in range log a kernel error message and return an error.
+ *
+ * Returns:
+ * zero if val is in range and lip okay
+ * non-zero return value from lpfc_issue_lip()
+ * -EINVAL val out of range
+ **/
static int
lpfc_topology_set(struct lpfc_hba *phba, int val)
{
@@ -1469,6 +2184,335 @@ lpfc_param_store(topology)
static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store);
+
+/**
+ * lpfc_stat_data_ctrl_store: write call back for lpfc_stat_data_ctrl
+ * sysfs file.
+ * @dev: Pointer to class device.
+ * @buf: Data buffer.
+ * @count: Size of the data buffer.
+ *
+ * This function get called when an user write to the lpfc_stat_data_ctrl
+ * sysfs file. This function parse the command written to the sysfs file
+ * and take appropriate action. These commands are used for controlling
+ * driver statistical data collection.
+ * Following are the command this function handles.
+ *
+ * setbucket <bucket_type> <base> <step>
+ * = Set the latency buckets.
+ * destroybucket = destroy all the buckets.
+ * start = start data collection
+ * stop = stop data collection
+ * reset = reset the collected data
+ **/
+static ssize_t
+lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+#define LPFC_MAX_DATA_CTRL_LEN 1024
+ static char bucket_data[LPFC_MAX_DATA_CTRL_LEN];
+ unsigned long i;
+ char *str_ptr, *token;
+ struct lpfc_vport **vports;
+ struct Scsi_Host *v_shost;
+ char *bucket_type_str, *base_str, *step_str;
+ unsigned long base, step, bucket_type;
+
+ if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
+ if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN)
+ return -EINVAL;
+
+ strcpy(bucket_data, buf);
+ str_ptr = &bucket_data[0];
+ /* Ignore this token - this is command token */
+ token = strsep(&str_ptr, "\t ");
+ if (!token)
+ return -EINVAL;
+
+ bucket_type_str = strsep(&str_ptr, "\t ");
+ if (!bucket_type_str)
+ return -EINVAL;
+
+ if (!strncmp(bucket_type_str, "linear", strlen("linear")))
+ bucket_type = LPFC_LINEAR_BUCKET;
+ else if (!strncmp(bucket_type_str, "power2", strlen("power2")))
+ bucket_type = LPFC_POWER2_BUCKET;
+ else
+ return -EINVAL;
+
+ base_str = strsep(&str_ptr, "\t ");
+ if (!base_str)
+ return -EINVAL;
+ base = simple_strtoul(base_str, NULL, 0);
+
+ step_str = strsep(&str_ptr, "\t ");
+ if (!step_str)
+ return -EINVAL;
+ step = simple_strtoul(step_str, NULL, 0);
+ if (!step)
+ return -EINVAL;
+
+ /* Block the data collection for every vport */
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ v_shost = lpfc_shost_from_vport(vports[i]);
+ spin_lock_irq(v_shost->host_lock);
+ /* Block and reset data collection */
+ vports[i]->stat_data_blocked = 1;
+ if (vports[i]->stat_data_enabled)
+ lpfc_vport_reset_stat_data(vports[i]);
+ spin_unlock_irq(v_shost->host_lock);
+ }
+
+ /* Set the bucket attributes */
+ phba->bucket_type = bucket_type;
+ phba->bucket_base = base;
+ phba->bucket_step = step;
+
+ for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ v_shost = lpfc_shost_from_vport(vports[i]);
+
+ /* Unblock data collection */
+ spin_lock_irq(v_shost->host_lock);
+ vports[i]->stat_data_blocked = 0;
+ spin_unlock_irq(v_shost->host_lock);
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+ return strlen(buf);
+ }
+
+ if (!strncmp(buf, "destroybucket", strlen("destroybucket"))) {
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ v_shost = lpfc_shost_from_vport(vports[i]);
+ spin_lock_irq(shost->host_lock);
+ vports[i]->stat_data_blocked = 1;
+ lpfc_free_bucket(vport);
+ vport->stat_data_enabled = 0;
+ vports[i]->stat_data_blocked = 0;
+ spin_unlock_irq(shost->host_lock);
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+ phba->bucket_type = LPFC_NO_BUCKET;
+ phba->bucket_base = 0;
+ phba->bucket_step = 0;
+ return strlen(buf);
+ }
+
+ if (!strncmp(buf, "start", strlen("start"))) {
+ /* If no buckets configured return error */
+ if (phba->bucket_type == LPFC_NO_BUCKET)
+ return -EINVAL;
+ spin_lock_irq(shost->host_lock);
+ if (vport->stat_data_enabled) {
+ spin_unlock_irq(shost->host_lock);
+ return strlen(buf);
+ }
+ lpfc_alloc_bucket(vport);
+ vport->stat_data_enabled = 1;
+ spin_unlock_irq(shost->host_lock);
+ return strlen(buf);
+ }
+
+ if (!strncmp(buf, "stop", strlen("stop"))) {
+ spin_lock_irq(shost->host_lock);
+ if (vport->stat_data_enabled == 0) {
+ spin_unlock_irq(shost->host_lock);
+ return strlen(buf);
+ }
+ lpfc_free_bucket(vport);
+ vport->stat_data_enabled = 0;
+ spin_unlock_irq(shost->host_lock);
+ return strlen(buf);
+ }
+
+ if (!strncmp(buf, "reset", strlen("reset"))) {
+ if ((phba->bucket_type == LPFC_NO_BUCKET)
+ || !vport->stat_data_enabled)
+ return strlen(buf);
+ spin_lock_irq(shost->host_lock);
+ vport->stat_data_blocked = 1;
+ lpfc_vport_reset_stat_data(vport);
+ vport->stat_data_blocked = 0;
+ spin_unlock_irq(shost->host_lock);
+ return strlen(buf);
+ }
+ return -EINVAL;
+}
+
+
+/**
+ * lpfc_stat_data_ctrl_show: Read callback function for
+ * lpfc_stat_data_ctrl sysfs file.
+ * @dev: Pointer to class device object.
+ * @buf: Data buffer.
+ *
+ * This function is the read call back function for
+ * lpfc_stat_data_ctrl sysfs file. This function report the
+ * current statistical data collection state.
+ **/
+static ssize_t
+lpfc_stat_data_ctrl_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int index = 0;
+ int i;
+ char *bucket_type;
+ unsigned long bucket_value;
+
+ switch (phba->bucket_type) {
+ case LPFC_LINEAR_BUCKET:
+ bucket_type = "linear";
+ break;
+ case LPFC_POWER2_BUCKET:
+ bucket_type = "power2";
+ break;
+ default:
+ bucket_type = "No Bucket";
+ break;
+ }
+
+ sprintf(&buf[index], "Statistical Data enabled :%d, "
+ "blocked :%d, Bucket type :%s, Bucket base :%d,"
+ " Bucket step :%d\nLatency Ranges :",
+ vport->stat_data_enabled, vport->stat_data_blocked,
+ bucket_type, phba->bucket_base, phba->bucket_step);
+ index = strlen(buf);
+ if (phba->bucket_type != LPFC_NO_BUCKET) {
+ for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
+ if (phba->bucket_type == LPFC_LINEAR_BUCKET)
+ bucket_value = phba->bucket_base +
+ phba->bucket_step * i;
+ else
+ bucket_value = phba->bucket_base +
+ (1 << i) * phba->bucket_step;
+
+ if (index + 10 > PAGE_SIZE)
+ break;
+ sprintf(&buf[index], "%08ld ", bucket_value);
+ index = strlen(buf);
+ }
+ }
+ sprintf(&buf[index], "\n");
+ return strlen(buf);
+}
+
+/*
+ * Sysfs attribute to control the statistical data collection.
+ */
+static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR,
+ lpfc_stat_data_ctrl_show, lpfc_stat_data_ctrl_store);
+
+/*
+ * lpfc_drvr_stat_data: sysfs attr to get driver statistical data.
+ */
+
+/*
+ * Each Bucket takes 11 characters and 1 new line + 17 bytes WWN
+ * for each target.
+ */
+#define STAT_DATA_SIZE_PER_TARGET(NUM_BUCKETS) ((NUM_BUCKETS) * 11 + 18)
+#define MAX_STAT_DATA_SIZE_PER_TARGET \
+ STAT_DATA_SIZE_PER_TARGET(LPFC_MAX_BUCKET_COUNT)
+
+
+/**
+ * sysfs_drvr_stat_data_read: Read callback function for lpfc_drvr_stat_data
+ * sysfs attribute.
+ * @kobj: Pointer to the kernel object
+ * @bin_attr: Attribute object
+ * @buff: Buffer pointer
+ * @off: File offset
+ * @count: Buffer size
+ *
+ * This function is the read call back function for lpfc_drvr_stat_data
+ * sysfs file. This function export the statistical data to user
+ * applications.
+ **/
+static ssize_t
+sysfs_drvr_stat_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device,
+ kobj);
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int i = 0, index = 0;
+ unsigned long nport_index;
+ struct lpfc_nodelist *ndlp = NULL;
+ nport_index = (unsigned long)off /
+ MAX_STAT_DATA_SIZE_PER_TARGET;
+
+ if (!vport->stat_data_enabled || vport->stat_data_blocked
+ || (phba->bucket_type == LPFC_NO_BUCKET))
+ return 0;
+
+ spin_lock_irq(shost->host_lock);
+ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp) || !ndlp->lat_data)
+ continue;
+
+ if (nport_index > 0) {
+ nport_index--;
+ continue;
+ }
+
+ if ((index + MAX_STAT_DATA_SIZE_PER_TARGET)
+ > count)
+ break;
+
+ if (!ndlp->lat_data)
+ continue;
+
+ /* Print the WWN */
+ sprintf(&buf[index], "%02x%02x%02x%02x%02x%02x%02x%02x:",
+ ndlp->nlp_portname.u.wwn[0],
+ ndlp->nlp_portname.u.wwn[1],
+ ndlp->nlp_portname.u.wwn[2],
+ ndlp->nlp_portname.u.wwn[3],
+ ndlp->nlp_portname.u.wwn[4],
+ ndlp->nlp_portname.u.wwn[5],
+ ndlp->nlp_portname.u.wwn[6],
+ ndlp->nlp_portname.u.wwn[7]);
+
+ index = strlen(buf);
+
+ for (i = 0; i < LPFC_MAX_BUCKET_COUNT; i++) {
+ sprintf(&buf[index], "%010u,",
+ ndlp->lat_data[i].cmd_count);
+ index = strlen(buf);
+ }
+ sprintf(&buf[index], "\n");
+ index = strlen(buf);
+ }
+ spin_unlock_irq(shost->host_lock);
+ return index;
+}
+
+static struct bin_attribute sysfs_drvr_stat_data_attr = {
+ .attr = {
+ .name = "lpfc_drvr_stat_data",
+ .mode = S_IRUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
+ .read = sysfs_drvr_stat_data_read,
+ .write = NULL,
+};
+
/*
# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
# connection.
@@ -1479,6 +2523,24 @@ static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
# 8 = 8 Gigabaud
# Value range is [0,8]. Default value is 0.
*/
+
+/**
+ * lpfc_link_speed_set: Set the adapters link speed.
+ * @phba: lpfc_hba pointer.
+ * @val: link speed value.
+ *
+ * Description:
+ * If val is in a valid range then set the adapter's link speed field and
+ * issue a lip; if the lip fails reset the link speed to the old value.
+ *
+ * Notes:
+ * If the value is not in range log a kernel error message and return an error.
+ *
+ * Returns:
+ * zero if val is in range and lip okay.
+ * non-zero return value from lpfc_issue_lip()
+ * -EINVAL val out of range
+ **/
static int
lpfc_link_speed_set(struct lpfc_hba *phba, int val)
{
@@ -1513,6 +2575,23 @@ static int lpfc_link_speed = 0;
module_param(lpfc_link_speed, int, 0);
MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
lpfc_param_show(link_speed)
+
+/**
+ * lpfc_link_speed_init: Set the adapters link speed.
+ * @phba: lpfc_hba pointer.
+ * @val: link speed value.
+ *
+ * Description:
+ * If val is in a valid range then set the adapter's link speed field.
+ *
+ * Notes:
+ * If the value is not in range log a kernel error message, clear the link
+ * speed and return an error.
+ *
+ * Returns:
+ * zero if val saved.
+ * -EINVAL val out of range
+ **/
static int
lpfc_link_speed_init(struct lpfc_hba *phba, int val)
{
@@ -1522,7 +2601,7 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
return 0;
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0454 lpfc_link_speed attribute cannot "
+ "0405 lpfc_link_speed attribute cannot "
"be set to %d, allowed values are "
"["LPFC_LINK_SPEED_STRING"]\n", val);
phba->cfg_link_speed = 0;
@@ -1548,6 +2627,48 @@ LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,
"Use ADISC on rediscovery to authenticate FCP devices");
/*
+# lpfc_max_scsicmpl_time: Use scsi command completion time to control I/O queue
+# depth. Default value is 0. When the value of this parameter is zero the
+# SCSI command completion time is not used for controlling I/O queue depth. When
+# the parameter is set to a non-zero value, the I/O queue depth is controlled
+# to limit the I/O completion time to the parameter value.
+# The value is set in milliseconds.
+*/
+static int lpfc_max_scsicmpl_time;
+module_param(lpfc_max_scsicmpl_time, int, 0);
+MODULE_PARM_DESC(lpfc_max_scsicmpl_time,
+ "Use command completion time to control queue depth");
+lpfc_vport_param_show(max_scsicmpl_time);
+lpfc_vport_param_init(max_scsicmpl_time, 0, 0, 60000);
+static int
+lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val)
+{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct lpfc_nodelist *ndlp, *next_ndlp;
+
+ if (val == vport->cfg_max_scsicmpl_time)
+ return 0;
+ if ((val < 0) || (val > 60000))
+ return -EINVAL;
+ vport->cfg_max_scsicmpl_time = val;
+
+ spin_lock_irq(shost->host_lock);
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+ continue;
+ ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
+ }
+ spin_unlock_irq(shost->host_lock);
+ return 0;
+}
+lpfc_vport_param_store(max_scsicmpl_time);
+static DEVICE_ATTR(lpfc_max_scsicmpl_time, S_IRUGO | S_IWUSR,
+ lpfc_max_scsicmpl_time_show,
+ lpfc_max_scsicmpl_time_store);
+
+/*
# lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value
# range is [0,1]. Default value is 0.
*/
@@ -1623,12 +2744,12 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
/*
# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that
# support this feature
-# 0 = MSI disabled (default)
+# 0 = MSI disabled
# 1 = MSI enabled
-# 2 = MSI-X enabled
-# Value range is [0,2]. Default value is 0.
+# 2 = MSI-X enabled (default)
+# Value range is [0,2]. Default value is 2.
*/
-LPFC_ATTR_R(use_msi, 0, 0, 2, "Use Message Signaled Interrupts (1) or "
+LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
"MSI-X (2), if possible");
/*
@@ -1668,6 +2789,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_option_rom_version,
&dev_attr_link_state,
&dev_attr_num_discovered_ports,
+ &dev_attr_menlo_mgmt_mode,
&dev_attr_lpfc_drvr_version,
&dev_attr_lpfc_temp_sensor,
&dev_attr_lpfc_log_verbose,
@@ -1709,6 +2831,8 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_enable_hba_reset,
&dev_attr_lpfc_enable_hba_heartbeat,
&dev_attr_lpfc_sg_seg_cnt,
+ &dev_attr_lpfc_max_scsicmpl_time,
+ &dev_attr_lpfc_stat_data_ctrl,
NULL,
};
@@ -1731,9 +2855,29 @@ struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_nport_evt_cnt,
&dev_attr_npiv_info,
&dev_attr_lpfc_enable_da_id,
+ &dev_attr_lpfc_max_scsicmpl_time,
+ &dev_attr_lpfc_stat_data_ctrl,
NULL,
};
+/**
+ * sysfs_ctlreg_write: Write method for writing to ctlreg.
+ * @kobj: kernel kobject that contains the kernel class device.
+ * @bin_attr: kernel attributes passed to us.
+ * @buf: contains the data to be written to the adapter IOREG space.
+ * @off: offset into buffer to beginning of data.
+ * @count: bytes to transfer.
+ *
+ * Description:
+ * Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
+ * Uses the adapter io control registers to send buf contents to the adapter.
+ *
+ * Returns:
+ * -ERANGE off and count combo out of range
+ * -EINVAL off, count or buff address invalid
+ * -EPERM adapter is offline
+ * value of count, buf contents written
+ **/
static ssize_t
sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
@@ -1766,6 +2910,23 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
return count;
}
+/**
+ * sysfs_ctlreg_read: Read method for reading from ctlreg.
+ * @kobj: kernel kobject that contains the kernel class device.
+ * @bin_attr: kernel attributes passed to us.
+ * @buf: if succesful contains the data from the adapter IOREG space.
+ * @off: offset into buffer to beginning of data.
+ * @count: bytes to transfer.
+ *
+ * Description:
+ * Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
+ * Uses the adapter io control registers to read data into buf.
+ *
+ * Returns:
+ * -ERANGE off and count combo out of range
+ * -EINVAL off, count or buff address invalid
+ * value of count, buf contents read
+ **/
static ssize_t
sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
@@ -1810,7 +2971,10 @@ static struct bin_attribute sysfs_ctlreg_attr = {
.write = sysfs_ctlreg_write,
};
-
+/**
+ * sysfs_mbox_idle: frees the sysfs mailbox.
+ * @phba: lpfc_hba pointer
+ **/
static void
sysfs_mbox_idle(struct lpfc_hba *phba)
{
@@ -1824,6 +2988,27 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
}
}
+/**
+ * sysfs_mbox_write: Write method for writing information via mbox.
+ * @kobj: kernel kobject that contains the kernel class device.
+ * @bin_attr: kernel attributes passed to us.
+ * @buf: contains the data to be written to sysfs mbox.
+ * @off: offset into buffer to beginning of data.
+ * @count: bytes to transfer.
+ *
+ * Description:
+ * Accessed via /sys/class/scsi_host/hostxxx/mbox.
+ * Uses the sysfs mbox to send buf contents to the adapter.
+ *
+ * Returns:
+ * -ERANGE off and count combo out of range
+ * -EINVAL off, count or buff address invalid
+ * zero if count is zero
+ * -EPERM adapter is offline
+ * -ENOMEM failed to allocate memory for the mail box
+ * -EAGAIN offset, state or mbox is NULL
+ * count number of bytes transferred
+ **/
static ssize_t
sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
@@ -1878,6 +3063,29 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
return count;
}
+/**
+ * sysfs_mbox_read: Read method for reading information via mbox.
+ * @kobj: kernel kobject that contains the kernel class device.
+ * @bin_attr: kernel attributes passed to us.
+ * @buf: contains the data to be read from sysfs mbox.
+ * @off: offset into buffer to beginning of data.
+ * @count: bytes to transfer.
+ *
+ * Description:
+ * Accessed via /sys/class/scsi_host/hostxxx/mbox.
+ * Uses the sysfs mbox to receive data from to the adapter.
+ *
+ * Returns:
+ * -ERANGE off greater than mailbox command size
+ * -EINVAL off, count or buff address invalid
+ * zero if off and count are zero
+ * -EACCES adapter over temp
+ * -EPERM garbage can value to catch a multitude of errors
+ * -EAGAIN management IO not permitted, state or off error
+ * -ETIME mailbox timeout
+ * -ENODEV mailbox error
+ * count number of bytes transferred
+ **/
static ssize_t
sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
@@ -1954,6 +3162,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
case MBX_DEL_LD_ENTRY:
case MBX_SET_VARIABLE:
case MBX_WRITE_WWN:
+ case MBX_PORT_CAPABILITIES:
+ case MBX_PORT_IOV_CONTROL:
break;
case MBX_READ_SPARM64:
case MBX_READ_LA:
@@ -1978,17 +3188,15 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
/* If HBA encountered an error attention, allow only DUMP
* or RESTART mailbox commands until the HBA is restarted.
*/
- if ((phba->pport->stopped) &&
- (phba->sysfs_mbox.mbox->mb.mbxCommand !=
- MBX_DUMP_MEMORY &&
- phba->sysfs_mbox.mbox->mb.mbxCommand !=
- MBX_RESTART &&
- phba->sysfs_mbox.mbox->mb.mbxCommand !=
- MBX_WRITE_VPARMS)) {
- sysfs_mbox_idle(phba);
- spin_unlock_irq(&phba->hbalock);
- return -EPERM;
- }
+ if (phba->pport->stopped &&
+ phba->sysfs_mbox.mbox->mb.mbxCommand != MBX_DUMP_MEMORY &&
+ phba->sysfs_mbox.mbox->mb.mbxCommand != MBX_RESTART &&
+ phba->sysfs_mbox.mbox->mb.mbxCommand != MBX_WRITE_VPARMS &&
+ phba->sysfs_mbox.mbox->mb.mbxCommand != MBX_WRITE_WWN)
+ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
+ "1259 mbox: Issued mailbox cmd "
+ "0x%x while in stopped state.\n",
+ phba->sysfs_mbox.mbox->mb.mbxCommand);
phba->sysfs_mbox.mbox->vport = vport;
@@ -2059,6 +3267,14 @@ static struct bin_attribute sysfs_mbox_attr = {
.write = sysfs_mbox_write,
};
+/**
+ * lpfc_alloc_sysfs_attr: Creates the ctlreg and mbox entries.
+ * @vport: address of lpfc vport structure.
+ *
+ * Return codes:
+ * zero on success
+ * error return code from sysfs_create_bin_file()
+ **/
int
lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
{
@@ -2075,18 +3291,30 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
if (error)
goto out_remove_ctlreg_attr;
+ error = sysfs_create_bin_file(&shost->shost_dev.kobj,
+ &sysfs_drvr_stat_data_attr);
+ if (error)
+ goto out_remove_mbox_attr;
+
return 0;
+out_remove_mbox_attr:
+ sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
out_remove_ctlreg_attr:
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
out:
return error;
}
+/**
+ * lpfc_free_sysfs_attr: Removes the ctlreg and mbox entries.
+ * @vport: address of lpfc vport structure.
+ **/
void
lpfc_free_sysfs_attr(struct lpfc_vport *vport)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-
+ sysfs_remove_bin_file(&shost->shost_dev.kobj,
+ &sysfs_drvr_stat_data_attr);
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
}
@@ -2096,6 +3324,10 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
* Dynamic FC Host Attributes Support
*/
+/**
+ * lpfc_get_host_port_id: Copy the vport DID into the scsi host port id.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_get_host_port_id(struct Scsi_Host *shost)
{
@@ -2105,6 +3337,10 @@ lpfc_get_host_port_id(struct Scsi_Host *shost)
fc_host_port_id(shost) = vport->fc_myDID;
}
+/**
+ * lpfc_get_host_port_type: Set the value of the scsi host port type.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_get_host_port_type(struct Scsi_Host *shost)
{
@@ -2133,6 +3369,10 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock);
}
+/**
+ * lpfc_get_host_port_state: Set the value of the scsi host port state.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_get_host_port_state(struct Scsi_Host *shost)
{
@@ -2167,6 +3407,10 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock);
}
+/**
+ * lpfc_get_host_speed: Set the value of the scsi host speed.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_get_host_speed(struct Scsi_Host *shost)
{
@@ -2199,6 +3443,10 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock);
}
+/**
+ * lpfc_get_host_fabric_name: Set the value of the scsi host fabric name.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{
@@ -2221,6 +3469,18 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
fc_host_fabric_name(shost) = node_name;
}
+/**
+ * lpfc_get_stats: Return statistical information about the adapter.
+ * @shost: kernel scsi host pointer.
+ *
+ * Notes:
+ * NULL on error for link down, no mbox pool, sli2 active,
+ * management not allowed, memory allocation error, or mbox error.
+ *
+ * Returns:
+ * NULL for error
+ * address of the adapter host statistics
+ **/
static struct fc_host_statistics *
lpfc_get_stats(struct Scsi_Host *shost)
{
@@ -2334,6 +3594,10 @@ lpfc_get_stats(struct Scsi_Host *shost)
return hs;
}
+/**
+ * lpfc_reset_stats: Copy the adapter link stats information.
+ * @shost: kernel scsi host pointer.
+ **/
static void
lpfc_reset_stats(struct Scsi_Host *shost)
{
@@ -2411,6 +3675,14 @@ lpfc_reset_stats(struct Scsi_Host *shost)
* are no sysfs handlers for link_down_tmo.
*/
+/**
+ * lpfc_get_node_by_target: Return the nodelist for a target.
+ * @starget: kernel scsi target pointer.
+ *
+ * Returns:
+ * address of the node list if found
+ * NULL target not found
+ **/
static struct lpfc_nodelist *
lpfc_get_node_by_target(struct scsi_target *starget)
{
@@ -2432,6 +3704,10 @@ lpfc_get_node_by_target(struct scsi_target *starget)
return NULL;
}
+/**
+ * lpfc_get_starget_port_id: Set the target port id to the ndlp DID or -1.
+ * @starget: kernel scsi target pointer.
+ **/
static void
lpfc_get_starget_port_id(struct scsi_target *starget)
{
@@ -2440,6 +3716,12 @@ lpfc_get_starget_port_id(struct scsi_target *starget)
fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1;
}
+/**
+ * lpfc_get_starget_node_name: Set the target node name.
+ * @starget: kernel scsi target pointer.
+ *
+ * Description: Set the target node name to the ndlp node name wwn or zero.
+ **/
static void
lpfc_get_starget_node_name(struct scsi_target *starget)
{
@@ -2449,6 +3731,12 @@ lpfc_get_starget_node_name(struct scsi_target *starget)
ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0;
}
+/**
+ * lpfc_get_starget_port_name: Set the target port name.
+ * @starget: kernel scsi target pointer.
+ *
+ * Description: set the target port name to the ndlp port name wwn or zero.
+ **/
static void
lpfc_get_starget_port_name(struct scsi_target *starget)
{
@@ -2458,6 +3746,15 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
}
+/**
+ * lpfc_set_rport_loss_tmo: Set the rport dev loss tmo.
+ * @rport: fc rport address.
+ * @timeout: new value for dev loss tmo.
+ *
+ * Description:
+ * If timeout is non zero set the dev_loss_tmo to timeout, else set
+ * dev_loss_tmo to one.
+ **/
static void
lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
@@ -2467,7 +3764,18 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
rport->dev_loss_tmo = 1;
}
-
+/**
+ * lpfc_rport_show_function: Return rport target information.
+ *
+ * Description:
+ * Macro that uses field to generate a function with the name lpfc_show_rport_
+ *
+ * lpfc_show_rport_##field: returns the bytes formatted in buf
+ * @cdev: class converted to an fc_rport.
+ * @buf: on return contains the target_field or zero.
+ *
+ * Returns: size of formatted string.
+ **/
#define lpfc_rport_show_function(field, format_string, sz, cast) \
static ssize_t \
lpfc_show_rport_##field (struct device *dev, \
@@ -2602,6 +3910,10 @@ struct fc_function_template lpfc_vport_transport_functions = {
.vport_disable = lpfc_vport_disable,
};
+/**
+ * lpfc_get_cfgparam: Used during probe_one to init the adapter structure.
+ * @phba: lpfc_hba pointer.
+ **/
void
lpfc_get_cfgparam(struct lpfc_hba *phba)
{
@@ -2637,6 +3949,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
return;
}
+/**
+ * lpfc_get_vport_cfgparam: Used during port create, init the vport structure.
+ * @vport: lpfc_vport pointer.
+ **/
void
lpfc_get_vport_cfgparam(struct lpfc_vport *vport)
{
@@ -2648,6 +3964,7 @@ lpfc_get_vport_cfgparam(struct lpfc_vport *vport)
lpfc_restrict_login_init(vport, lpfc_restrict_login);
lpfc_fcp_class_init(vport, lpfc_fcp_class);
lpfc_use_adisc_init(vport, lpfc_use_adisc);
+ lpfc_max_scsicmpl_time_init(vport, lpfc_max_scsicmpl_time);
lpfc_fdmi_on_init(vport, lpfc_fdmi_on);
lpfc_discovery_threads_init(vport, lpfc_discovery_threads);
lpfc_max_luns_init(vport, lpfc_max_luns);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 1b8245213b8..044ef4057d2 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
+typedef int (*node_filter)(struct lpfc_nodelist *, void *);
struct fc_rport;
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
@@ -26,11 +26,11 @@ void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
- struct lpfc_dmabuf *mp);
+int lpfc_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
-void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
+void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
+int lpfc_config_msi(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -43,7 +43,7 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
-void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
+void lpfc_cleanup_rpis(struct lpfc_vport *, int);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_port_link_failure(struct lpfc_vport *);
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -135,7 +135,7 @@ void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_fdmi_tmo(unsigned long);
-void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
+void lpfc_fdmi_timeout_handler(struct lpfc_vport *);
int lpfc_config_port_prep(struct lpfc_hba *);
int lpfc_config_port_post(struct lpfc_hba *);
@@ -155,6 +155,8 @@ int lpfc_sli_queue_setup(struct lpfc_hba *);
void lpfc_handle_eratt(struct lpfc_hba *);
void lpfc_handle_latt(struct lpfc_hba *);
irqreturn_t lpfc_intr_handler(int, void *);
+irqreturn_t lpfc_sp_intr_handler(int, void *);
+irqreturn_t lpfc_fp_intr_handler(int, void *);
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
@@ -175,11 +177,12 @@ void lpfc_mem_free(struct lpfc_hba *);
void lpfc_stop_vport_timers(struct lpfc_vport *);
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);
+void lpfc_poll_start_timer(struct lpfc_hba *);
+void lpfc_poll_eratt(unsigned long);
+void lpfc_sli_poll_fcp_ring(struct lpfc_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);
+void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
+uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
@@ -187,11 +190,13 @@ int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *);
+int lpfc_sli_config_port(struct lpfc_hba *, int);
int lpfc_sli_host_down(struct lpfc_vport *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
+int lpfc_sli_check_eratt(struct lpfc_hba *);
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -199,6 +204,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *, uint32_t);
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
+void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *);
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
@@ -226,17 +232,13 @@ struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
struct lpfc_name *);
-int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
- uint32_t timeout);
+int lpfc_sli_issue_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
-int lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
- struct lpfc_sli_ring * pring,
- struct lpfc_iocbq * piocb,
- struct lpfc_iocbq * prspiocbq,
- uint32_t timeout);
-void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
- struct lpfc_iocbq * cmdiocb,
- struct lpfc_iocbq * rspiocb);
+int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, struct lpfc_sli_ring *,
+ struct lpfc_iocbq *, struct lpfc_iocbq *,
+ uint32_t);
+void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *, struct lpfc_iocbq *,
+ struct lpfc_iocbq *);
void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
@@ -269,7 +271,7 @@ void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct device *);
int lpfc_vport_disable(struct fc_vport *fc_vport, bool disable);
-void lpfc_mbx_unreg_vpi(struct lpfc_vport *);
+int lpfc_mbx_unreg_vpi(struct lpfc_vport *);
void destroy_port(struct lpfc_vport *);
int lpfc_get_instance(void);
void lpfc_host_attrib_init(struct Scsi_Host *);
@@ -290,6 +292,13 @@ void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
void lpfc_adjust_queue_depth(struct lpfc_hba *);
void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
+void lpfc_scsi_dev_block(struct lpfc_hba *);
+
+void
+lpfc_send_els_failure_event(struct lpfc_hba *, struct lpfc_iocbq *,
+ struct lpfc_iocbq *);
+struct lpfc_fast_path_event *lpfc_alloc_fast_evt(struct lpfc_hba *);
+void lpfc_free_fast_evt(struct lpfc_hba *, struct lpfc_fast_path_event *);
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
#define HBA_EVENT_RSCN 5
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 7fc74cf5823..26dae8bae2d 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -34,6 +34,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -134,25 +135,24 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
list_del(&head);
} else {
- struct lpfc_iocbq *next;
-
- list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
+ INIT_LIST_HEAD(&head);
+ list_add_tail(&head, &piocbq->list);
+ list_for_each_entry(iocbq, &head, list) {
icmd = &iocbq->iocb;
if (icmd->ulpBdeCount == 0)
- lpfc_ct_unsol_buffer(phba, piocbq, NULL, 0);
+ lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0);
for (i = 0; i < icmd->ulpBdeCount; i++) {
paddr = getPaddr(icmd->un.cont64[i].addrHigh,
icmd->un.cont64[i].addrLow);
mp = lpfc_sli_ringpostbuf_get(phba, pring,
paddr);
size = icmd->un.cont64[i].tus.f.bdeSize;
- lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
+ lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
lpfc_in_buf_free(phba, mp);
}
- list_del(&iocbq->list);
- lpfc_sli_release_iocbq(phba, iocbq);
lpfc_post_buffer(phba, pring, i);
}
+ list_del(&head);
}
}
@@ -212,7 +212,7 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
else
list_add_tail(&mp->list, &mlist->list);
- bpl->tus.f.bdeFlags = BUFF_USE_RCV;
+ bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
/* build buffer ptr list for IOCB */
bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
@@ -283,7 +283,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
icmd->un.genreq64.bdl.ulpIoTag32 = 0;
icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
- icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
+ icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof (struct ulp_bde64));
if (usr_flg)
@@ -861,7 +861,7 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry++;
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "0216 Retrying NS cmd %x\n", cmdcode);
+ "0250 Retrying NS cmd %x\n", cmdcode);
rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
if (rc == 0)
goto out;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 094b47e94b2..771920bdde4 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2007 Emulex. All rights reserved. *
+ * Copyright (C) 2007-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -35,6 +35,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -46,13 +47,14 @@
#include "lpfc_debugfs.h"
#ifdef CONFIG_LPFC_DEBUG_FS
-/* debugfs interface
+/**
+ * debugfs interface
*
* To access this interface the user should:
* # mkdir /debug
* # mount -t debugfs none /debug
*
- * The lpfc debugfs directory hierachy is:
+ * The lpfc debugfs directory hierarchy is:
* lpfc/lpfcX/vportY
* where X is the lpfc hba unique_id
* where Y is the vport VPI on that hba
@@ -61,14 +63,21 @@
* discovery_trace
* This is an ACSII readable file that contains a trace of the last
* lpfc_debugfs_max_disc_trc events that happened on a specific vport.
- * See lpfc_debugfs.h for different categories of
- * discovery events. To enable the discovery trace, the following
- * module parameters must be set:
+ * See lpfc_debugfs.h for different categories of discovery events.
+ * To enable the discovery trace, the following module parameters must be set:
* lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
* lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for
* EACH vport. X MUST also be a power of 2.
* lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in
* lpfc_debugfs.h .
+ *
+ * slow_ring_trace
+ * This is an ACSII readable file that contains a trace of the last
+ * lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA.
+ * To enable the slow ring trace, the following module parameters must be set:
+ * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
+ * lpfc_debugfs_max_slow_ring_trc=X Where X is the event trace depth for
+ * the HBA. X MUST also be a power of 2.
*/
static int lpfc_debugfs_enable = 1;
module_param(lpfc_debugfs_enable, int, 0);
@@ -117,6 +126,25 @@ struct lpfc_debug {
static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
static unsigned long lpfc_debugfs_start_time = 0L;
+/**
+ * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer.
+ * @vport: The vport to gather the log info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine gathers the lpfc discovery debugfs data from the @vport and
+ * dumps it to @buf up to @size number of bytes. It will start at the next entry
+ * in the log and process the log until the end of the buffer. Then it will
+ * gather from the beginning of the log and process until the current entry.
+ *
+ * Notes:
+ * Discovery logging will be disabled while while this routine dumps the log.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
{
@@ -125,7 +153,6 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
struct lpfc_debugfs_trc *dtp;
char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
-
enable = lpfc_debugfs_enable;
lpfc_debugfs_enable = 0;
@@ -159,6 +186,25 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
return len;
}
+/**
+ * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer.
+ * @phba: The HBA to gather the log info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine gathers the lpfc slow ring debugfs data from the @phba and
+ * dumps it to @buf up to @size number of bytes. It will start at the next entry
+ * in the log and process the log until the end of the buffer. Then it will
+ * gather from the beginning of the log and process until the current entry.
+ *
+ * Notes:
+ * Slow ring logging will be disabled while while this routine dumps the log.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
{
@@ -203,6 +249,25 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
static int lpfc_debugfs_last_hbq = -1;
+/**
+ * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer.
+ * @phba: The HBA to gather host buffer info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine dumps the host buffer queue info from the @phba to @buf up to
+ * @size number of bytes. A header that describes the current hbq state will be
+ * dumped to @buf first and then info on each hbq entry will be dumped to @buf
+ * until @size bytes have been dumped or all the hbq info has been dumped.
+ *
+ * Notes:
+ * This routine will rotate through each configured HBQ each time called.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
{
@@ -303,6 +368,24 @@ skipit:
static int lpfc_debugfs_last_hba_slim_off;
+/**
+ * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer.
+ * @phba: The HBA to gather SLIM info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine dumps the current contents of HBA SLIM for the HBA associated
+ * with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data.
+ *
+ * Notes:
+ * This routine will only dump up to 1024 bytes of data each time called and
+ * should be called multiple times to dump the entire HBA SLIM.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
{
@@ -342,6 +425,21 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
return len;
}
+/**
+ * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer.
+ * @phba: The HBA to gather Host SLIM info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine dumps the current contents of host SLIM for the host associated
+ * with @phba to @buf up to @size bytes of data. The dump will contain the
+ * Mailbox, PCB, Rings, and Registers that are located in host memory.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
{
@@ -357,7 +455,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
spin_lock_irq(&phba->hbalock);
len += snprintf(buf+len, size-len, "SLIM Mailbox\n");
- ptr = (uint32_t *)phba->slim2p;
+ ptr = (uint32_t *)phba->slim2p.virt;
i = sizeof(MAILBOX_t);
while (i > 0) {
len += snprintf(buf+len, size-len,
@@ -370,7 +468,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
}
len += snprintf(buf+len, size-len, "SLIM PCB\n");
- ptr = (uint32_t *)&phba->slim2p->pcb;
+ ptr = (uint32_t *)phba->pcb;
i = sizeof(PCB_t);
while (i > 0) {
len += snprintf(buf+len, size-len,
@@ -382,44 +480,16 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
off += (8 * sizeof(uint32_t));
}
- pgpp = (struct lpfc_pgp *)&phba->slim2p->mbx.us.s3_pgp.port;
- pring = &psli->ring[0];
- len += snprintf(buf+len, size-len,
- "Ring 0: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) "
- "RSP PutInx:%d Max:%d\n",
- pgpp->cmdGetInx, pring->numCiocb,
- pring->next_cmdidx, pring->local_getidx, pring->flag,
- pgpp->rspPutInx, pring->numRiocb);
- pgpp++;
-
- pring = &psli->ring[1];
- len += snprintf(buf+len, size-len,
- "Ring 1: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) "
- "RSP PutInx:%d Max:%d\n",
- pgpp->cmdGetInx, pring->numCiocb,
- pring->next_cmdidx, pring->local_getidx, pring->flag,
- pgpp->rspPutInx, pring->numRiocb);
- pgpp++;
-
- pring = &psli->ring[2];
- len += snprintf(buf+len, size-len,
- "Ring 2: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) "
- "RSP PutInx:%d Max:%d\n",
- pgpp->cmdGetInx, pring->numCiocb,
- pring->next_cmdidx, pring->local_getidx, pring->flag,
- pgpp->rspPutInx, pring->numRiocb);
- pgpp++;
-
- pring = &psli->ring[3];
- len += snprintf(buf+len, size-len,
- "Ring 3: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) "
- "RSP PutInx:%d Max:%d\n",
- pgpp->cmdGetInx, pring->numCiocb,
- pring->next_cmdidx, pring->local_getidx, pring->flag,
- pgpp->rspPutInx, pring->numRiocb);
-
-
- ptr = (uint32_t *)&phba->slim2p->mbx.us.s3_pgp.hbq_get;
+ for (i = 0; i < 4; i++) {
+ pgpp = &phba->port_gp[i];
+ pring = &psli->ring[i];
+ len += snprintf(buf+len, size-len,
+ "Ring %d: CMD GetInx:%d (Max:%d Next:%d "
+ "Local:%d flg:x%x) RSP PutInx:%d Max:%d\n",
+ i, pgpp->cmdGetInx, pring->numCiocb,
+ pring->next_cmdidx, pring->local_getidx,
+ pring->flag, pgpp->rspPutInx, pring->numRiocb);
+ }
word0 = readl(phba->HAregaddr);
word1 = readl(phba->CAregaddr);
word2 = readl(phba->HSregaddr);
@@ -430,6 +500,21 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
return len;
}
+/**
+ * lpfc_debugfs_nodelist_data - Dump target node list to a buffer.
+ * @vport: The vport to gather target node info from.
+ * @buf: The buffer to dump log into.
+ * @size: The maximum amount of data to process.
+ *
+ * Description:
+ * This routine dumps the current target node list associated with @vport to
+ * @buf up to @size bytes of data. Each node entry in the dump will contain a
+ * node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into @buf and will
+ * not exceed @size.
+ **/
static int
lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
{
@@ -513,7 +598,22 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
}
#endif
-
+/**
+ * lpfc_debugfs_disc_trc - Store discovery trace log.
+ * @vport: The vport to associate this trace string with for retrieval.
+ * @mask: Log entry classification.
+ * @fmt: Format string to be displayed when dumping the log.
+ * @data1: 1st data parameter to be applied to @fmt.
+ * @data2: 2nd data parameter to be applied to @fmt.
+ * @data3: 3rd data parameter to be applied to @fmt.
+ *
+ * Description:
+ * This routine is used by the driver code to add a debugfs log entry to the
+ * discovery trace buffer associated with @vport. Only entries with a @mask that
+ * match the current debugfs discovery mask will be saved. Entries that do not
+ * match will be thrown away. @fmt, @data1, @data2, and @data3 are used like
+ * printf when displaying the log.
+ **/
inline void
lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
uint32_t data1, uint32_t data2, uint32_t data3)
@@ -542,6 +642,19 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
return;
}
+/**
+ * lpfc_debugfs_slow_ring_trc - Store slow ring trace log.
+ * @phba: The phba to associate this trace string with for retrieval.
+ * @fmt: Format string to be displayed when dumping the log.
+ * @data1: 1st data parameter to be applied to @fmt.
+ * @data2: 2nd data parameter to be applied to @fmt.
+ * @data3: 3rd data parameter to be applied to @fmt.
+ *
+ * Description:
+ * This routine is used by the driver code to add a debugfs log entry to the
+ * discovery trace buffer associated with @vport. @fmt, @data1, @data2, and
+ * @data3 are used like printf when displaying the log.
+ **/
inline void
lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
uint32_t data1, uint32_t data2, uint32_t data3)
@@ -568,6 +681,21 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
}
#ifdef CONFIG_LPFC_DEBUG_FS
+/**
+ * lpfc_debugfs_disc_trc_open - Open the discovery trace log.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
{
@@ -585,7 +713,7 @@ lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
size = PAGE_ALIGN(size);
@@ -603,6 +731,21 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
{
@@ -620,7 +763,7 @@ lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
size = PAGE_ALIGN(size);
@@ -638,6 +781,21 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
{
@@ -649,7 +807,7 @@ lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
@@ -665,6 +823,21 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
{
@@ -676,7 +849,7 @@ lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
@@ -692,6 +865,21 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
{
@@ -703,7 +891,7 @@ lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
@@ -719,6 +907,21 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file.
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an negative
+ * error value.
+ **/
static int
lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
{
@@ -730,7 +933,7 @@ lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
if (!debug)
goto out;
- /* Round to page boundry */
+ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
@@ -746,6 +949,23 @@ out:
return rc;
}
+/**
+ * lpfc_debugfs_lseek - Seek through a debugfs file.
+ * @file: The file pointer to seek through.
+ * @off: The offset to seek to or the amount to seek by.
+ * @whence: Indicates how to seek.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs lseek file operation. The
+ * @whence parameter indicates whether @off is the offset to directly seek to,
+ * or if it is a value to seek forward or reverse by. This function figures out
+ * what the new offset of the debugfs file will be and assigns that value to the
+ * f_pos field of @file.
+ *
+ * Returns:
+ * This function returns the new offset if successful and returns a negative
+ * error if unable to process the seek.
+ **/
static loff_t
lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
{
@@ -767,6 +987,22 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
}
+/**
+ * lpfc_debugfs_read - Read a debugfs file.
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from from the buffer indicated in the private_data
+ * field of @file. It will start reading at @ppos and copy up to @nbytes of
+ * data to @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
static ssize_t
lpfc_debugfs_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
@@ -776,6 +1012,18 @@ lpfc_debugfs_read(struct file *file, char __user *buf,
debug->len);
}
+/**
+ * lpfc_debugfs_release - Release the buffer used to store debugfs file data.
+ * @inode: The inode pointer that contains a vport pointer. (unused)
+ * @file: The file pointer that contains the buffer to release.
+ *
+ * Description:
+ * This routine frees the buffer that was allocated when the debugfs file was
+ * opened.
+ *
+ * Returns:
+ * This function returns zero.
+ **/
static int
lpfc_debugfs_release(struct inode *inode, struct file *file)
{
@@ -845,6 +1093,16 @@ static struct dentry *lpfc_debugfs_root = NULL;
static atomic_t lpfc_debugfs_hba_count;
#endif
+/**
+ * lpfc_debugfs_initialize - Initialize debugfs for a vport.
+ * @vport: The vport pointer to initialize.
+ *
+ * Description:
+ * When Debugfs is configured this routine sets up the lpfc debugfs file system.
+ * If not already created, this routine will create the lpfc directory, and
+ * lpfcX directory (for this HBA), and vportX directory for this vport. It will
+ * also create each file used to access lpfc specific debugfs information.
+ **/
inline void
lpfc_debugfs_initialize(struct lpfc_vport *vport)
{
@@ -862,7 +1120,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
atomic_set(&lpfc_debugfs_hba_count, 0);
if (!lpfc_debugfs_root) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs root\n");
+ "0408 Cannot create debugfs root\n");
goto debug_failed;
}
}
@@ -876,7 +1134,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
debugfs_create_dir(name, lpfc_debugfs_root);
if (!phba->hba_debugfs_root) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs hba\n");
+ "0412 Cannot create debugfs hba\n");
goto debug_failed;
}
atomic_inc(&lpfc_debugfs_hba_count);
@@ -890,7 +1148,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba, &lpfc_debugfs_op_hbqinfo);
if (!phba->debug_hbqinfo) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs hbqinfo\n");
+ "0411 Cannot create debugfs hbqinfo\n");
goto debug_failed;
}
@@ -902,7 +1160,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba, &lpfc_debugfs_op_dumpHBASlim);
if (!phba->debug_dumpHBASlim) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs dumpHBASlim\n");
+ "0413 Cannot create debugfs dumpHBASlim\n");
goto debug_failed;
}
@@ -914,7 +1172,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba, &lpfc_debugfs_op_dumpHostSlim);
if (!phba->debug_dumpHostSlim) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs dumpHostSlim\n");
+ "0414 Cannot create debugfs dumpHostSlim\n");
goto debug_failed;
}
@@ -944,7 +1202,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba, &lpfc_debugfs_op_slow_ring_trc);
if (!phba->debug_slow_ring_trc) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs "
+ "0415 Cannot create debugfs "
"slow_ring_trace\n");
goto debug_failed;
}
@@ -955,7 +1213,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
GFP_KERNEL);
if (!phba->slow_ring_trc) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs "
+ "0416 Cannot create debugfs "
"slow_ring buffer\n");
goto debug_failed;
}
@@ -972,7 +1230,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
debugfs_create_dir(name, phba->hba_debugfs_root);
if (!vport->vport_debugfs_root) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cant create debugfs");
+ "0417 Cant create debugfs");
goto debug_failed;
}
atomic_inc(&phba->debugfs_vport_count);
@@ -1001,7 +1259,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
if (!vport->disc_trc) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs disc trace "
+ "0418 Cannot create debugfs disc trace "
"buffer\n");
goto debug_failed;
}
@@ -1014,7 +1272,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
vport, &lpfc_debugfs_op_disc_trc);
if (!vport->debug_disc_trc) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "0409 Cannot create debugfs "
+ "0419 Cannot create debugfs "
"discovery_trace\n");
goto debug_failed;
}
@@ -1033,7 +1291,17 @@ debug_failed:
#endif
}
-
+/**
+ * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport.
+ * @vport: The vport pointer to remove from debugfs.
+ *
+ * Description:
+ * When Debugfs is configured this routine removes debugfs file system elements
+ * that are specific to this vport. It also checks to see if there are any
+ * users left for the debugfs directories associated with the HBA and driver. If
+ * this is the last user of the HBA directory or driver directory then it will
+ * remove those from the debugfs infrastructure as well.
+ **/
inline void
lpfc_debugfs_terminate(struct lpfc_vport *vport)
{
@@ -1096,5 +1364,3 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
#endif
return;
}
-
-
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 2db0b74b6fa..f29e548a90d 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -37,6 +37,7 @@ enum lpfc_work_type {
LPFC_EVT_KILL,
LPFC_EVT_ELS_RETRY,
LPFC_EVT_DEV_LOSS,
+ LPFC_EVT_FASTPATH_MGMT_EVT,
};
/* structure used to queue event to the discovery tasklet */
@@ -47,6 +48,24 @@ struct lpfc_work_evt {
enum lpfc_work_type evt;
};
+struct lpfc_scsi_check_condition_event;
+struct lpfc_scsi_varqueuedepth_event;
+struct lpfc_scsi_event_header;
+struct lpfc_fabric_event_header;
+struct lpfc_fcprdchkerr_event;
+
+/* structure used for sending events from fast path */
+struct lpfc_fast_path_event {
+ struct lpfc_work_evt work_evt;
+ struct lpfc_vport *vport;
+ union {
+ struct lpfc_scsi_check_condition_event check_cond_evt;
+ struct lpfc_scsi_varqueuedepth_event queue_depth_evt;
+ struct lpfc_scsi_event_header scsi_evt;
+ struct lpfc_fabric_event_header fabric_evt;
+ struct lpfc_fcprdchkerr_event read_check_error;
+ } un;
+};
struct lpfc_nodelist {
struct list_head nlp_listp;
@@ -88,6 +107,10 @@ struct lpfc_nodelist {
unsigned long last_ramp_up_time; /* jiffy of last ramp up */
unsigned long last_q_full_time; /* jiffy of last queue full */
struct kref kref;
+ atomic_t cmd_pending;
+ uint32_t cmd_qdepth;
+ unsigned long last_change_time;
+ struct lpfc_scsicmd_bkt *lat_data; /* Latency data */
};
/* Defines for nlp_flag (uint32) */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index f54e0f7eaee..630bd28fb99 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -30,6 +30,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -53,6 +54,28 @@ static void lpfc_register_new_vport(struct lpfc_hba *phba,
static int lpfc_max_els_tries = 3;
+/**
+ * lpfc_els_chk_latt: Check host link attention event for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine checks whether there is an outstanding host link
+ * attention event during the discovery process with the @vport. It is done
+ * by reading the HBA's Host Attention (HA) register. If there is any host
+ * link attention events during this @vport's discovery process, the @vport
+ * shall be marked as FC_ABORT_DISCOVERY, a host link attention clear shall
+ * be issued if the link state is not already in host link cleared state,
+ * and a return code shall indicate whether the host link attention event
+ * had happened.
+ *
+ * Note that, if either the host link is in state LPFC_LINK_DOWN or @vport
+ * state in LPFC_VPORT_READY, the request for checking host link attention
+ * event will be ignored and a return code shall indicate no host link
+ * attention event had happened.
+ *
+ * Return codes
+ * 0 - no host link attention event happened
+ * 1 - host link attention event happened
+ **/
int
lpfc_els_chk_latt(struct lpfc_vport *vport)
{
@@ -92,6 +115,34 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
return 1;
}
+/**
+ * lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @expectRsp: flag indicating whether response is expected.
+ * @cmdSize: size of the ELS command.
+ * @retry: number of retries to the command IOCB when it fails.
+ * @ndlp: pointer to a node-list data structure.
+ * @did: destination identifier.
+ * @elscmd: the ELS command code.
+ *
+ * This routine is used for allocating a lpfc-IOCB data structure from
+ * the driver lpfc-IOCB free-list and prepare the IOCB with the parameters
+ * passed into the routine for discovery state machine to issue an Extended
+ * Link Service (ELS) commands. It is a generic lpfc-IOCB allocation
+ * and preparation routine that is used by all the discovery state machine
+ * routines and the ELS command-specific fields will be later set up by
+ * the individual discovery machine routines after calling this routine
+ * allocating and preparing a generic IOCB data structure. It fills in the
+ * Buffer Descriptor Entries (BDEs), allocates buffers for both command
+ * payload and response payload (if expected). The reference count on the
+ * ndlp is incremented by 1 and the reference to the ndlp is put into
+ * context1 of the IOCB data structure for this IOCB to hold the ndlp
+ * reference for the command's callback function to access later.
+ *
+ * Return code
+ * Pointer to the newly allocated/prepared els iocb data structure
+ * NULL - when els iocb data structure allocation/preparation failed
+ **/
static struct lpfc_iocbq *
lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
uint16_t cmdSize, uint8_t retry,
@@ -150,7 +201,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
- icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
+ icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.elsreq64.remoteID = did; /* DID */
if (expectRsp) {
icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
@@ -185,7 +236,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
bpl->tus.f.bdeSize = FCELSSIZE;
- bpl->tus.f.bdeFlags = BUFF_USE_RCV;
+ bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
bpl->tus.w = le32_to_cpu(bpl->tus.w);
}
@@ -233,6 +284,22 @@ els_iocb_free_pcmb_exit:
return NULL;
}
+/**
+ * lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues a fabric registration login for a @vport. An
+ * active ndlp node with Fabric_DID must already exist for this @vport.
+ * The routine invokes two mailbox commands to carry out fabric registration
+ * login through the HBA firmware: the first mailbox command requests the
+ * HBA to perform link configuration for the @vport; and the second mailbox
+ * command requests the HBA to perform the actual fabric registration login
+ * with the @vport.
+ *
+ * Return code
+ * 0 - successfully issued fabric registration login for @vport
+ * -ENXIO -- failed to issue fabric registration login for @vport
+ **/
static int
lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
{
@@ -313,6 +380,26 @@ fail:
return -ENXIO;
}
+/**
+ * lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @sp: pointer to service parameter data structure.
+ * @irsp: pointer to the IOCB within the lpfc response IOCB.
+ *
+ * This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
+ * function to handle the completion of a Fabric Login (FLOGI) into a fabric
+ * port in a fabric topology. It properly sets up the parameters to the @ndlp
+ * from the IOCB response. It also check the newly assigned N_Port ID to the
+ * @vport against the previously assigned N_Port ID. If it is different from
+ * the previously assigned Destination ID (DID), the lpfc_unreg_rpi() routine
+ * is invoked on all the remaining nodes with the @vport to unregister the
+ * Remote Port Indicators (RPIs). Finally, the lpfc_issue_fabric_reglogin()
+ * is invoked to register login to the fabric.
+ *
+ * Return code
+ * 0 - Success (currently, always return 0)
+ **/
static int
lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm *sp, IOCB_t *irsp)
@@ -387,7 +474,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
*/
list_for_each_entry_safe(np, next_np,
&vport->fc_nodes, nlp_listp) {
- if (!NLP_CHK_NODE_ACT(ndlp))
+ if (!NLP_CHK_NODE_ACT(np))
continue;
if ((np->nlp_state != NLP_STE_NPR_NODE) ||
!(np->nlp_flag & NLP_NPR_ADISC))
@@ -416,9 +503,26 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
-/*
- * We FLOGIed into an NPort, initiate pt2pt protocol
- */
+/**
+ * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @sp: pointer to service parameter data structure.
+ *
+ * This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
+ * function to handle the completion of a Fabric Login (FLOGI) into an N_Port
+ * in a point-to-point topology. First, the @vport's N_Port Name is compared
+ * with the received N_Port Name: if the @vport's N_Port Name is greater than
+ * the received N_Port Name lexicographically, this node shall assign local
+ * N_Port ID (PT2PT_LocalID: 1) and remote N_Port ID (PT2PT_RemoteID: 2) and
+ * will send out Port Login (PLOGI) with the N_Port IDs assigned. Otherwise,
+ * this node shall just wait for the remote node to issue PLOGI and assign
+ * N_Port IDs.
+ *
+ * Return code
+ * 0 - Success
+ * -ENXIO - Fail
+ **/
static int
lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm *sp)
@@ -516,6 +620,29 @@ fail:
return -ENXIO;
}
+/**
+ * lpfc_cmpl_els_flogi: Completion callback function for flogi.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the top-level completion callback function for issuing
+ * a Fabric Login (FLOGI) command. If the response IOCB reported error,
+ * the lpfc_els_retry() routine shall be invoked to retry the FLOGI. If
+ * retry has been made (either immediately or delayed with lpfc_els_retry()
+ * returning 1), the command IOCB will be released and function returned.
+ * If the retry attempt has been given up (possibly reach the maximum
+ * number of retries), one additional decrement of ndlp reference shall be
+ * invoked before going out after releasing the command IOCB. This will
+ * actually release the remote node (Note, lpfc_els_free_iocb() will also
+ * invoke one decrement of ndlp reference count). If no error reported in
+ * the IOCB status, the command Port ID field is used to determine whether
+ * this is a point-to-point topology or a fabric topology: if the Port ID
+ * field is assigned, it is a fabric topology; otherwise, it is a
+ * point-to-point topology. The routine lpfc_cmpl_els_flogi_fabric() or
+ * lpfc_cmpl_els_flogi_nport() shall be invoked accordingly to handle the
+ * specific topology completion conditions.
+ **/
static void
lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -618,6 +745,28 @@ out:
lpfc_els_free_iocb(phba, cmdiocb);
}
+/**
+ * lpfc_issue_els_flogi: Issue an flogi iocb command for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues a Fabric Login (FLOGI) Request ELS command
+ * for a @vport. The initiator service parameters are put into the payload
+ * of the FLOGI Request IOCB and the top-level callback function pointer
+ * to lpfc_cmpl_els_flogi() routine is put to the IOCB completion callback
+ * function field. The lpfc_issue_fabric_iocb routine is invoked to send
+ * out FLOGI ELS command with one outstanding fabric IOCB at a time.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the FLOGI ELS command.
+ *
+ * Return code
+ * 0 - successfully issued flogi iocb for @vport
+ * 1 - failed to issue flogi iocb for @vport
+ **/
static int
lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
@@ -694,6 +843,20 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
+/**
+ * lpfc_els_abort_flogi: Abort all outstanding flogi iocbs.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs
+ * with a @phba. This routine walks all the outstanding IOCBs on the txcmplq
+ * list and issues an abort IOCB commond on each outstanding IOCB that
+ * contains a active Fabric_DID ndlp. Note that this function is to issue
+ * the abort IOCB command on all the outstanding IOCBs, thus when this
+ * function returns, it does not guarantee all the IOCBs are actually aborted.
+ *
+ * Return code
+ * 0 - Sucessfully issued abort iocb on all outstanding flogis (Always 0)
+ **/
int
lpfc_els_abort_flogi(struct lpfc_hba *phba)
{
@@ -729,6 +892,22 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_initial_flogi: Issue an initial fabric login for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues an initial Fabric Login (FLOGI) for the @vport
+ * specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
+ * the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
+ * put it into the @vport's ndlp list. If an inactive ndlp found on the list,
+ * it will just be enabled and made active. The lpfc_issue_els_flogi() routine
+ * is then invoked with the @vport and the ndlp to perform the FLOGI for the
+ * @vport.
+ *
+ * Return code
+ * 0 - failed to issue initial flogi for @vport
+ * 1 - successfully issued initial flogi for @vport
+ **/
int
lpfc_initial_flogi(struct lpfc_vport *vport)
{
@@ -764,6 +943,22 @@ lpfc_initial_flogi(struct lpfc_vport *vport)
return 1;
}
+/**
+ * lpfc_initial_fdisc: Issue an initial fabric discovery for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues an initial Fabric Discover (FDISC) for the @vport
+ * specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
+ * the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
+ * put it into the @vport's ndlp list. If an inactive ndlp found on the list,
+ * it will just be enabled and made active. The lpfc_issue_els_fdisc() routine
+ * is then invoked with the @vport and the ndlp to perform the FDISC for the
+ * @vport.
+ *
+ * Return code
+ * 0 - failed to issue initial fdisc for @vport
+ * 1 - successfully issued initial fdisc for @vport
+ **/
int
lpfc_initial_fdisc(struct lpfc_vport *vport)
{
@@ -797,6 +992,17 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
return 1;
}
+/**
+ * lpfc_more_plogi: Check and issue remaining plogis for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine checks whether there are more remaining Port Logins
+ * (PLOGI) to be issued for the @vport. If so, it will invoke the routine
+ * lpfc_els_disc_plogi() to go through the Node Port Recovery (NPR) nodes
+ * to issue ELS PLOGIs up to the configured discover threads with the
+ * @vport (@vport->cfg_discovery_threads). The function also decrement
+ * the @vport's num_disc_node by 1 if it is not already 0.
+ **/
void
lpfc_more_plogi(struct lpfc_vport *vport)
{
@@ -819,6 +1025,37 @@ lpfc_more_plogi(struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp.
+ * @phba: pointer to lpfc hba data structure.
+ * @prsp: pointer to response IOCB payload.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine checks and indicates whether the WWPN of an N_Port, retrieved
+ * from a PLOGI, matches the WWPN that is stored in the @ndlp for that N_POrt.
+ * The following cases are considered N_Port confirmed:
+ * 1) The N_Port is a Fabric ndlp; 2) The @ndlp is on vport list and matches
+ * the WWPN of the N_Port logged into; 3) The @ndlp is not on vport list but
+ * it does not have WWPN assigned either. If the WWPN is confirmed, the
+ * pointer to the @ndlp will be returned. If the WWPN is not confirmed:
+ * 1) if there is a node on vport list other than the @ndlp with the same
+ * WWPN of the N_Port PLOGI logged into, the lpfc_unreg_rpi() will be invoked
+ * on that node to release the RPI associated with the node; 2) if there is
+ * no node found on vport list with the same WWPN of the N_Port PLOGI logged
+ * into, a new node shall be allocated (or activated). In either case, the
+ * parameters of the @ndlp shall be copied to the new_ndlp, the @ndlp shall
+ * be released and the new_ndlp shall be put on to the vport node list and
+ * its pointer returned as the confirmed node.
+ *
+ * Note that before the @ndlp got "released", the keepDID from not-matching
+ * or inactive "new_ndlp" on the vport node list is assigned to the nlp_DID
+ * of the @ndlp. This is because the release of @ndlp is actually to put it
+ * into an inactive state on the vport node list and the vport node list
+ * management algorithm does not allow two node with a same DID.
+ *
+ * Return code
+ * pointer to the PLOGI N_Port @ndlp
+ **/
static struct lpfc_nodelist *
lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
struct lpfc_nodelist *ndlp)
@@ -922,6 +1159,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
return new_ndlp;
}
+/**
+ * lpfc_end_rscn: Check and handle more rscn for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine checks whether more Registration State Change
+ * Notifications (RSCNs) came in while the discovery state machine was in
+ * the FC_RSCN_MODE. If so, the lpfc_els_handle_rscn() routine will be
+ * invoked to handle the additional RSCNs for the @vport. Otherwise, the
+ * FC_RSCN_MODE bit will be cleared with the @vport to mark as the end of
+ * handling the RSCNs.
+ **/
void
lpfc_end_rscn(struct lpfc_vport *vport)
{
@@ -943,6 +1191,26 @@ lpfc_end_rscn(struct lpfc_vport *vport)
}
}
+/**
+ * lpfc_cmpl_els_plogi: Completion callback function for plogi.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function for issuing the Port
+ * Login (PLOGI) command. For PLOGI completion, there must be an active
+ * ndlp on the vport node list that matches the remote node ID from the
+ * PLOGI reponse IOCB. If such ndlp does not exist, the PLOGI is simply
+ * ignored and command IOCB released. The PLOGI response IOCB status is
+ * checked for error conditons. If there is error status reported, PLOGI
+ * retry shall be attempted by invoking the lpfc_els_retry() routine.
+ * Otherwise, the lpfc_plogi_confirm_nport() routine shall be invoked on
+ * the ndlp and the NLP_EVT_CMPL_PLOGI state to the Discover State Machine
+ * (DSM) is set for this PLOGI completion. Finally, it checks whether
+ * there are additional N_Port nodes with the vport that need to perform
+ * PLOGI. If so, the lpfc_more_plogi() routine is invoked to issue addition
+ * PLOGIs.
+ **/
static void
lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1048,6 +1316,27 @@ out:
return;
}
+/**
+ * lpfc_issue_els_plogi: Issue an plogi iocb command for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @did: destination port identifier.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues a Port Login (PLOGI) command to a remote N_Port
+ * (with the @did) for a @vport. Before issuing a PLOGI to a remote N_Port,
+ * the ndlp with the remote N_Port DID must exist on the @vport's ndlp list.
+ * This routine constructs the proper feilds of the PLOGI IOCB and invokes
+ * the lpfc_sli_issue_iocb() routine to send out PLOGI ELS command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the PLOGI ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued a plogi for @vport
+ * 1 - failed to issue a plogi for @vport
+ **/
int
lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
{
@@ -1106,6 +1395,19 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
return 0;
}
+/**
+ * lpfc_cmpl_els_prli: Completion callback function for prli.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function for a Process Login
+ * (PRLI) ELS command. The PRLI response IOCB status is checked for error
+ * status. If there is error status reported, PRLI retry shall be attempted
+ * by invoking the lpfc_els_retry() routine. Otherwise, the state
+ * NLP_EVT_CMPL_PRLI is sent to the Discover State Machine (DSM) for this
+ * ndlp to mark the PRLI completion.
+ **/
static void
lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1164,6 +1466,27 @@ out:
return;
}
+/**
+ * lpfc_issue_els_prli: Issue a prli iocb command for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues a Process Login (PRLI) ELS command for the
+ * @vport. The PRLI service parameters are set up in the payload of the
+ * PRLI Request command and the pointer to lpfc_cmpl_els_prli() routine
+ * is put to the IOCB completion callback func field before invoking the
+ * routine lpfc_sli_issue_iocb() to send out PRLI command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the PRLI ELS command.
+ *
+ * Return code
+ * 0 - successfully issued prli iocb command for @vport
+ * 1 - failed to issue prli iocb command for @vport
+ **/
int
lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
@@ -1233,6 +1556,92 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
+/**
+ * lpfc_rscn_disc: Perform rscn discovery for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine performs Registration State Change Notification (RSCN)
+ * discovery for a @vport. If the @vport's node port recovery count is not
+ * zero, it will invoke the lpfc_els_disc_plogi() to perform PLOGI for all
+ * the nodes that need recovery. If none of the PLOGI were needed through
+ * the lpfc_els_disc_plogi() routine, the lpfc_end_rscn() routine shall be
+ * invoked to check and handle possible more RSCN came in during the period
+ * of processing the current ones.
+ **/
+static void
+lpfc_rscn_disc(struct lpfc_vport *vport)
+{
+ lpfc_can_disctmo(vport);
+
+ /* RSCN discovery */
+ /* go thru NPR nodes and issue ELS PLOGIs */
+ if (vport->fc_npr_cnt)
+ if (lpfc_els_disc_plogi(vport))
+ return;
+
+ lpfc_end_rscn(vport);
+}
+
+/**
+ * lpfc_adisc_done: Complete the adisc phase of discovery.
+ * @vport: pointer to lpfc_vport hba data structure that finished all ADISCs.
+ *
+ * This function is called when the final ADISC is completed during discovery.
+ * This function handles clearing link attention or issuing reg_vpi depending
+ * on whether npiv is enabled. This function also kicks off the PLOGI phase of
+ * discovery.
+ * This function is called with no locks held.
+ **/
+static void
+lpfc_adisc_done(struct lpfc_vport *vport)
+{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct lpfc_hba *phba = vport->phba;
+
+ /*
+ * For NPIV, cmpl_reg_vpi will set port_state to READY,
+ * and continue discovery.
+ */
+ if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+ !(vport->fc_flag & FC_RSCN_MODE)) {
+ lpfc_issue_reg_vpi(phba, vport);
+ return;
+ }
+ /*
+ * For SLI2, we need to set port_state to READY
+ * and continue discovery.
+ */
+ if (vport->port_state < LPFC_VPORT_READY) {
+ /* If we get here, there is nothing to ADISC */
+ if (vport->port_type == LPFC_PHYSICAL_PORT)
+ lpfc_issue_clear_la(phba, vport);
+ if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
+ vport->num_disc_nodes = 0;
+ /* go thru NPR list, issue ELS PLOGIs */
+ if (vport->fc_npr_cnt)
+ lpfc_els_disc_plogi(vport);
+ if (!vport->num_disc_nodes) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_NDISC_ACTIVE;
+ spin_unlock_irq(shost->host_lock);
+ lpfc_can_disctmo(vport);
+ lpfc_end_rscn(vport);
+ }
+ }
+ vport->port_state = LPFC_VPORT_READY;
+ } else
+ lpfc_rscn_disc(vport);
+}
+
+/**
+ * lpfc_more_adisc: Issue more adisc as needed.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine determines whether there are more ndlps on a @vport
+ * node list need to have Address Discover (ADISC) issued. If so, it will
+ * invoke the lpfc_els_disc_adisc() routine to issue ADISC on the @vport's
+ * remaining nodes which need to have ADISC sent.
+ **/
void
lpfc_more_adisc(struct lpfc_vport *vport)
{
@@ -1252,23 +1661,27 @@ lpfc_more_adisc(struct lpfc_vport *vport)
/* go thru NPR nodes and issue any remaining ELS ADISCs */
sentadisc = lpfc_els_disc_adisc(vport);
}
+ if (!vport->num_disc_nodes)
+ lpfc_adisc_done(vport);
return;
}
-static void
-lpfc_rscn_disc(struct lpfc_vport *vport)
-{
- lpfc_can_disctmo(vport);
-
- /* RSCN discovery */
- /* go thru NPR nodes and issue ELS PLOGIs */
- if (vport->fc_npr_cnt)
- if (lpfc_els_disc_plogi(vport))
- return;
-
- lpfc_end_rscn(vport);
-}
-
+/**
+ * lpfc_cmpl_els_adisc: Completion callback function for adisc.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion function for issuing the Address Discover
+ * (ADISC) command. It first checks to see whether link went down during
+ * the discovery process. If so, the node will be marked as node port
+ * recovery for issuing discover IOCB by the link attention handler and
+ * exit. Otherwise, the response status is checked. If error was reported
+ * in the response status, the ADISC command shall be retried by invoking
+ * the lpfc_els_retry() routine. Otherwise, if no error was reported in
+ * the response status, the state machine is invoked to set transition
+ * with respect to NLP_EVT_CMPL_ADISC event.
+ **/
static void
lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1333,57 +1746,34 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_ADISC);
- if (disc && vport->num_disc_nodes) {
- /* Check to see if there are more ADISCs to be sent */
+ /* Check to see if there are more ADISCs to be sent */
+ if (disc && vport->num_disc_nodes)
lpfc_more_adisc(vport);
-
- /* Check to see if we are done with ADISC authentication */
- if (vport->num_disc_nodes == 0) {
- /* If we get here, there is nothing left to ADISC */
- /*
- * For NPIV, cmpl_reg_vpi will set port_state to READY,
- * and continue discovery.
- */
- if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
- !(vport->fc_flag & FC_RSCN_MODE)) {
- lpfc_issue_reg_vpi(phba, vport);
- goto out;
- }
- /*
- * For SLI2, we need to set port_state to READY
- * and continue discovery.
- */
- if (vport->port_state < LPFC_VPORT_READY) {
- /* If we get here, there is nothing to ADISC */
- if (vport->port_type == LPFC_PHYSICAL_PORT)
- lpfc_issue_clear_la(phba, vport);
-
- if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
- vport->num_disc_nodes = 0;
- /* go thru NPR list, issue ELS PLOGIs */
- if (vport->fc_npr_cnt)
- lpfc_els_disc_plogi(vport);
-
- if (!vport->num_disc_nodes) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &=
- ~FC_NDISC_ACTIVE;
- spin_unlock_irq(
- shost->host_lock);
- lpfc_can_disctmo(vport);
- }
- }
- vport->port_state = LPFC_VPORT_READY;
- } else {
- lpfc_rscn_disc(vport);
- }
- }
- }
out:
lpfc_els_free_iocb(phba, cmdiocb);
return;
}
+/**
+ * lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues an Address Discover (ADISC) for an @ndlp on a
+ * @vport. It prepares the payload of the ADISC ELS command, updates the
+ * and states of the ndlp, and invokes the lpfc_sli_issue_iocb() routine
+ * to issue the ADISC ELS command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the ADISC ELS command.
+ *
+ * Return code
+ * 0 - successfully issued adisc
+ * 1 - failed to issue adisc
+ **/
int
lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
@@ -1437,6 +1827,18 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
+/**
+ * lpfc_cmpl_els_logo: Completion callback function for logo.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion function for issuing the ELS Logout (LOGO)
+ * command. If no error status was reported from the LOGO response, the
+ * state machine of the associated ndlp shall be invoked for transition with
+ * respect to NLP_EVT_CMPL_LOGO event. Otherwise, if error status was reported,
+ * the lpfc_els_retry() routine will be invoked to retry the LOGO command.
+ **/
static void
lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1502,6 +1904,26 @@ out:
return;
}
+/**
+ * lpfc_issue_els_logo: Issue a logo to an node on a vport.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine constructs and issues an ELS Logout (LOGO) iocb command
+ * to a remote node, referred by an @ndlp on a @vport. It constructs the
+ * payload of the IOCB, properly sets up the @ndlp state, and invokes the
+ * lpfc_sli_issue_iocb() routine to send out the LOGO ELS command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the LOGO ELS command.
+ *
+ * Return code
+ * 0 - successfully issued logo
+ * 1 - failed to issue logo
+ **/
int
lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
@@ -1563,6 +1985,22 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
+/**
+ * lpfc_cmpl_els_cmd: Completion callback function for generic els command.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is a generic completion callback function for ELS commands.
+ * Specifically, it is the callback function which does not need to perform
+ * any command specific operations. It is currently used by the ELS command
+ * issuing routines for the ELS State Change Request (SCR),
+ * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution
+ * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than
+ * certain debug loggings, this callback function simply invokes the
+ * lpfc_els_chk_latt() routine to check whether link went down during the
+ * discovery process.
+ **/
static void
lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1587,6 +2025,28 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
+/**
+ * lpfc_issue_els_scr: Issue a scr to an node on a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @nportid: N_Port identifier to the remote node.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues a State Change Request (SCR) to a fabric node
+ * on a @vport. The remote node @nportid is passed into the function. It
+ * first search the @vport node list to find the matching ndlp. If no such
+ * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An
+ * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb()
+ * routine is invoked to send the SCR IOCB.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the SCR ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued scr command
+ * 1 - Failed to issue scr command
+ **/
int
lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{
@@ -1659,6 +2119,28 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 0;
}
+/**
+ * lpfc_issue_els_farpr: Issue a farp to an node on a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @nportid: N_Port identifier to the remote node.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine issues a Fibre Channel Address Resolution Response
+ * (FARPR) to a node on a vport. The remote node N_Port identifier (@nportid)
+ * is passed into the function. It first search the @vport node list to find
+ * the matching ndlp. If no such ndlp is found, a new ndlp shall be created
+ * for this (FARPR) purpose. An IOCB is allocated, payload prepared, and the
+ * lpfc_sli_issue_iocb() routine is invoked to send the FARPR ELS command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the PARPR ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued farpr command
+ * 1 - Failed to issue farpr command
+ **/
static int
lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{
@@ -1748,6 +2230,18 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 0;
}
+/**
+ * lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @nlp: pointer to a node-list data structure.
+ *
+ * This routine cancels the timer with a delayed IOCB-command retry for
+ * a @vport's @ndlp. It stops the timer for the delayed function retrial and
+ * removes the ELS retry event if it presents. In addition, if the
+ * NLP_NPR_2B_DISC bit is set in the @nlp's nlp_flag bitmap, ADISC IOCB
+ * commands are sent for the @vport's nodes that require issuing discovery
+ * ADISC.
+ **/
void
lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
{
@@ -1775,25 +2269,36 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
if (vport->port_state < LPFC_VPORT_READY) {
/* Check if there are more ADISCs to be sent */
lpfc_more_adisc(vport);
- if ((vport->num_disc_nodes == 0) &&
- (vport->fc_npr_cnt))
- lpfc_els_disc_plogi(vport);
} else {
/* Check if there are more PLOGIs to be sent */
lpfc_more_plogi(vport);
- }
- if (vport->num_disc_nodes == 0) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_NDISC_ACTIVE;
- spin_unlock_irq(shost->host_lock);
- lpfc_can_disctmo(vport);
- lpfc_end_rscn(vport);
+ if (vport->num_disc_nodes == 0) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_NDISC_ACTIVE;
+ spin_unlock_irq(shost->host_lock);
+ lpfc_can_disctmo(vport);
+ lpfc_end_rscn(vport);
+ }
}
}
}
return;
}
+/**
+ * lpfc_els_retry_delay: Timer function with a ndlp delayed function timer.
+ * @ptr: holder for the pointer to the timer function associated data (ndlp).
+ *
+ * This routine is invoked by the ndlp delayed-function timer to check
+ * whether there is any pending ELS retry event(s) with the node. If not, it
+ * simply returns. Otherwise, if there is at least one ELS delayed event, it
+ * adds the delayed events to the HBA work list and invokes the
+ * lpfc_worker_wake_up() routine to wake up worker thread to process the
+ * event. Note that lpfc_nlp_get() is called before posting the event to
+ * the work list to hold reference count of ndlp so that it guarantees the
+ * reference to ndlp will still be available when the worker thread gets
+ * to the event associated with the ndlp.
+ **/
void
lpfc_els_retry_delay(unsigned long ptr)
{
@@ -1822,6 +2327,15 @@ lpfc_els_retry_delay(unsigned long ptr)
return;
}
+/**
+ * lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine is the worker-thread handler for processing the @ndlp delayed
+ * event(s), posted by the lpfc_els_retry_delay() routine. It simply retrieves
+ * the last ELS command from the associated ndlp and invokes the proper ELS
+ * function according to the delayed ELS command to retry the command.
+ **/
void
lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
{
@@ -1884,6 +2398,27 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
return;
}
+/**
+ * lpfc_els_retry: Make retry decision on an els command iocb.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine makes a retry decision on an ELS command IOCB, which has
+ * failed. The following ELS IOCBs use this function for retrying the command
+ * when previously issued command responsed with error status: FLOGI, PLOGI,
+ * PRLI, ADISC, LOGO, and FDISC. Based on the ELS command type and the
+ * returned error status, it makes the decision whether a retry shall be
+ * issued for the command, and whether a retry shall be made immediately or
+ * delayed. In the former case, the corresponding ELS command issuing-function
+ * is called to retry the command. In the later case, the ELS command shall
+ * be posted to the ndlp delayed event and delayed function timer set to the
+ * ndlp for the delayed command issusing.
+ *
+ * Return code
+ * 0 - No retry of els command is made
+ * 1 - Immediate or delayed retry of els command is made
+ **/
static int
lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -2051,7 +2586,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
(stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "0123 FDISC Failed (x%x). "
+ "0122 FDISC Failed (x%x). "
"Fabric Detected Bad WWN\n",
stat.un.lsRjtError);
lpfc_vport_set_state(vport,
@@ -2182,12 +2717,26 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb.
+ * @phba: pointer to lpfc hba data structure.
+ * @buf_ptr1: pointer to the lpfc DMA buffer data structure.
+ *
+ * This routine releases the lpfc DMA (Direct Memory Access) buffer(s)
+ * associated with a command IOCB back to the lpfc DMA buffer pool. It first
+ * checks to see whether there is a lpfc DMA buffer associated with the
+ * response of the command IOCB. If so, it will be released before releasing
+ * the lpfc DMA buffer associated with the IOCB itself.
+ *
+ * Return code
+ * 0 - Successfully released lpfc DMA buffer (currently, always return 0)
+ **/
static int
lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
{
struct lpfc_dmabuf *buf_ptr;
- /* Free the response before processing the command. */
+ /* Free the response before processing the command. */
if (!list_empty(&buf_ptr1->list)) {
list_remove_head(&buf_ptr1->list, buf_ptr,
struct lpfc_dmabuf,
@@ -2200,6 +2749,18 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
return 0;
}
+/**
+ * lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl.
+ * @phba: pointer to lpfc hba data structure.
+ * @buf_ptr: pointer to the lpfc dma buffer data structure.
+ *
+ * This routine releases the lpfc Direct Memory Access (DMA) buffer
+ * associated with a Buffer Pointer List (BPL) back to the lpfc DMA buffer
+ * pool.
+ *
+ * Return code
+ * 0 - Successfully released lpfc DMA buffer (currently, always return 0)
+ **/
static int
lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
{
@@ -2208,6 +2769,33 @@ lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
return 0;
}
+/**
+ * lpfc_els_free_iocb: Free a command iocb and its associated resources.
+ * @phba: pointer to lpfc hba data structure.
+ * @elsiocb: pointer to lpfc els command iocb data structure.
+ *
+ * This routine frees a command IOCB and its associated resources. The
+ * command IOCB data structure contains the reference to various associated
+ * resources, these fields must be set to NULL if the associated reference
+ * not present:
+ * context1 - reference to ndlp
+ * context2 - reference to cmd
+ * context2->next - reference to rsp
+ * context3 - reference to bpl
+ *
+ * It first properly decrements the reference count held on ndlp for the
+ * IOCB completion callback function. If LPFC_DELAY_MEM_FREE flag is not
+ * set, it invokes the lpfc_els_free_data() routine to release the Direct
+ * Memory Access (DMA) buffers associated with the IOCB. Otherwise, it
+ * adds the DMA buffer the @phba data structure for the delayed release.
+ * If reference to the Buffer Pointer List (BPL) is present, the
+ * lpfc_els_free_bpl() routine is invoked to release the DMA memory
+ * associated with BPL. Finally, the lpfc_sli_release_iocbq() routine is
+ * invoked to release the IOCB data structure back to @phba IOCBQ list.
+ *
+ * Return code
+ * 0 - Success (currently, always return 0)
+ **/
int
lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
@@ -2274,6 +2862,23 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
return 0;
}
+/**
+ * lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function to the Logout (LOGO)
+ * Accept (ACC) Response ELS command. This routine is invoked to indicate
+ * the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to
+ * release the ndlp if it has the last reference remaining (reference count
+ * is 1). If succeeded (meaning ndlp released), it sets the IOCB context1
+ * field to NULL to inform the following lpfc_els_free_iocb() routine no
+ * ndlp reference count needs to be decremented. Otherwise, the ndlp
+ * reference use-count shall be decremented by the lpfc_els_free_iocb()
+ * routine. Finally, the lpfc_els_free_iocb() is invoked to release the
+ * IOCB data structure.
+ **/
static void
lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -2311,6 +2916,19 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
+/**
+ * lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine is the completion callback function for unregister default
+ * RPI (Remote Port Index) mailbox command to the @phba. It simply releases
+ * the associated lpfc Direct Memory Access (DMA) buffer back to the pool and
+ * decrements the ndlp reference count held for this completion callback
+ * function. After that, it invokes the lpfc_nlp_not_used() to check
+ * whether there is only one reference left on the ndlp. If so, it will
+ * perform one more decrement and trigger the release of the ndlp.
+ **/
void
lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
@@ -2332,6 +2950,22 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
+/**
+ * lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function for ELS Response IOCB
+ * command. In normal case, this callback function just properly sets the
+ * nlp_flag bitmap in the ndlp data structure, if the mbox command reference
+ * field in the command IOCB is not NULL, the referred mailbox command will
+ * be send out, and then invokes the lpfc_els_free_iocb() routine to release
+ * the IOCB. Under error conditions, such as when a LS_RJT is returned or a
+ * link down event occurred during the discovery, the lpfc_nlp_not_used()
+ * routine shall be invoked trying to release the ndlp if no other threads
+ * are currently referring it.
+ **/
static void
lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -2487,6 +3121,31 @@ out:
return;
}
+/**
+ * lpfc_els_rsp_acc: Prepare and issue an acc response iocb command.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @flag: the els command code to be accepted.
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @mbox: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine prepares and issues an Accept (ACC) response IOCB
+ * command. It uses the @flag to properly set up the IOCB field for the
+ * specific ACC response command to be issued and invokes the
+ * lpfc_sli_issue_iocb() routine to send out ACC response IOCB. If a
+ * @mbox pointer is passed in, it will be put into the context_un.mbox
+ * field of the IOCB for the completion callback function to issue the
+ * mailbox command to the HBA later when callback is invoked.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the corresponding response ELS IOCB command.
+ *
+ * Return code
+ * 0 - Successfully issued acc response
+ * 1 - Failed to issue acc response
+ **/
int
lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
@@ -2601,6 +3260,28 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
return 0;
}
+/**
+ * lpfc_els_rsp_reject: Propare and issue a rjt response iocb command.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @rejectError:
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @mbox: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine prepares and issue an Reject (RJT) response IOCB
+ * command. If a @mbox pointer is passed in, it will be put into the
+ * context_un.mbox field of the IOCB for the completion callback function
+ * to issue to the HBA later.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the reject response ELS IOCB command.
+ *
+ * Return code
+ * 0 - Successfully issued reject response
+ * 1 - Failed to issue reject response
+ **/
int
lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
@@ -2660,6 +3341,25 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
return 0;
}
+/**
+ * lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine prepares and issues an Accept (ACC) response to Address
+ * Discover (ADISC) ELS command. It simply prepares the payload of the IOCB
+ * and invokes the lpfc_sli_issue_iocb() routine to send out the command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the ADISC Accept response ELS IOCB command.
+ *
+ * Return code
+ * 0 - Successfully issued acc adisc response
+ * 1 - Failed to issue adisc acc response
+ **/
int
lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
struct lpfc_nodelist *ndlp)
@@ -2716,6 +3416,25 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
return 0;
}
+/**
+ * lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine prepares and issues an Accept (ACC) response to Process
+ * Login (PRLI) ELS command. It simply prepares the payload of the IOCB
+ * and invokes the lpfc_sli_issue_iocb() routine to send out the command.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the PRLI Accept response ELS IOCB command.
+ *
+ * Return code
+ * 0 - Successfully issued acc prli response
+ * 1 - Failed to issue acc prli response
+ **/
int
lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
struct lpfc_nodelist *ndlp)
@@ -2795,6 +3514,32 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
return 0;
}
+/**
+ * lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @format: rnid command format.
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine issues a Request Node Identification Data (RNID) Accept
+ * (ACC) response. It constructs the RNID ACC response command according to
+ * the proper @format and then calls the lpfc_sli_issue_iocb() routine to
+ * issue the response. Note that this command does not need to hold the ndlp
+ * reference count for the callback. So, the ndlp reference count taken by
+ * the lpfc_prep_els_iocb() routine is put back and the context1 field of
+ * IOCB is set to NULL to indicate to the lpfc_els_free_iocb() routine that
+ * there is no ndlp reference available.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function. However, for the RNID Accept Response ELS command,
+ * this is undone later by this routine after the IOCB is allocated.
+ *
+ * Return code
+ * 0 - Successfully issued acc rnid response
+ * 1 - Failed to issue acc rnid response
+ **/
static int
lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
@@ -2875,6 +3620,25 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
return 0;
}
+/**
+ * lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues Address Discover (ADISC) ELS commands to those
+ * N_Ports which are in node port recovery state and ADISC has not been issued
+ * for the @vport. Each time an ELS ADISC IOCB is issued by invoking the
+ * lpfc_issue_els_adisc() routine, the per @vport number of discover count
+ * (num_disc_nodes) shall be incremented. If the num_disc_nodes reaches a
+ * pre-configured threshold (cfg_discovery_threads), the @vport fc_flag will
+ * be marked with FC_NLP_MORE bit and the process of issuing remaining ADISC
+ * IOCBs quit for later pick up. On the other hand, after walking through
+ * all the ndlps with the @vport and there is none ADISC IOCB issued, the
+ * @vport fc_flag shall be cleared with FC_NLP_MORE bit indicating there is
+ * no more ADISC need to be sent.
+ *
+ * Return code
+ * The number of N_Ports with adisc issued.
+ **/
int
lpfc_els_disc_adisc(struct lpfc_vport *vport)
{
@@ -2914,6 +3678,25 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)
return sentadisc;
}
+/**
+ * lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues Port Login (PLOGI) ELS commands to all the N_Ports
+ * which are in node port recovery state, with a @vport. Each time an ELS
+ * ADISC PLOGI IOCB is issued by invoking the lpfc_issue_els_plogi() routine,
+ * the per @vport number of discover count (num_disc_nodes) shall be
+ * incremented. If the num_disc_nodes reaches a pre-configured threshold
+ * (cfg_discovery_threads), the @vport fc_flag will be marked with FC_NLP_MORE
+ * bit set and quit the process of issuing remaining ADISC PLOGIN IOCBs for
+ * later pick up. On the other hand, after walking through all the ndlps with
+ * the @vport and there is none ADISC PLOGI IOCB issued, the @vport fc_flag
+ * shall be cleared with the FC_NLP_MORE bit indicating there is no more ADISC
+ * PLOGI need to be sent.
+ *
+ * Return code
+ * The number of N_Ports with plogi issued.
+ **/
int
lpfc_els_disc_plogi(struct lpfc_vport *vport)
{
@@ -2954,6 +3737,15 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
return sentplogi;
}
+/**
+ * lpfc_els_flush_rscn: Clean up any rscn activities with a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine cleans up any Registration State Change Notification
+ * (RSCN) activity with a @vport. Note that the fc_rscn_flush flag of the
+ * @vport together with the host_lock is used to prevent multiple thread
+ * trying to access the RSCN array on a same @vport at the same time.
+ **/
void
lpfc_els_flush_rscn(struct lpfc_vport *vport)
{
@@ -2984,6 +3776,18 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport)
vport->fc_rscn_flush = 0;
}
+/**
+ * lpfc_rscn_payload_check: Check whether there is a pending rscn to a did.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @did: remote destination port identifier.
+ *
+ * This routine checks whether there is any pending Registration State
+ * Configuration Notification (RSCN) to a @did on @vport.
+ *
+ * Return code
+ * None zero - The @did matched with a pending rscn
+ * 0 - not able to match @did with a pending rscn
+ **/
int
lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
{
@@ -3053,6 +3857,17 @@ return_did_out:
return did;
}
+/**
+ * lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the
+ * state machine for a @vport's nodes that are with pending RSCN (Registration
+ * State Change Notification).
+ *
+ * Return code
+ * 0 - Successful (currently alway return 0)
+ **/
static int
lpfc_rscn_recovery_check(struct lpfc_vport *vport)
{
@@ -3071,6 +3886,28 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
return 0;
}
+/**
+ * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes an unsolicited RSCN (Registration State Change
+ * Notification) IOCB. First, the payload of the unsolicited RSCN is walked
+ * to invoke fc_host_post_event() routine to the FC transport layer. If the
+ * discover state machine is about to begin discovery, it just accepts the
+ * RSCN and the discovery process will satisfy the RSCN. If this RSCN only
+ * contains N_Port IDs for other vports on this HBA, it just accepts the
+ * RSCN and ignore processing it. If the state machine is in the recovery
+ * state, the fc_rscn_id_list of this @vport is walked and the
+ * lpfc_rscn_recovery_check() routine is invoked to send recovery event for
+ * all nodes that match RSCN payload. Otherwise, the lpfc_els_handle_rscn()
+ * routine is invoked to handle the RSCN event.
+ *
+ * Return code
+ * 0 - Just sent the acc response
+ * 1 - Sent the acc response and waited for name server completion
+ **/
static int
lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3130,7 +3967,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
if (rscn_id == hba_id) {
/* ALL NPortIDs in RSCN are on HBA */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "0214 Ignore RSCN "
+ "0219 Ignore RSCN "
"Data: x%x x%x x%x x%x\n",
vport->fc_flag, payload_len,
*lp, vport->fc_rscn_id_cnt);
@@ -3241,6 +4078,22 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return lpfc_els_handle_rscn(vport);
}
+/**
+ * lpfc_els_handle_rscn: Handle rscn for a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine handles the Registration State Configuration Notification
+ * (RSCN) for a @vport. If login to NameServer does not exist, a new ndlp shall
+ * be created and a Port Login (PLOGI) to the NameServer is issued. Otherwise,
+ * if the ndlp to NameServer exists, a Common Transport (CT) command to the
+ * NameServer shall be issued. If CT command to the NameServer fails to be
+ * issued, the lpfc_els_flush_rscn() routine shall be invoked to clean up any
+ * RSCN activities with the @vport.
+ *
+ * Return code
+ * 0 - Cleaned up rscn on the @vport
+ * 1 - Wait for plogi to name server before proceed
+ **/
int
lpfc_els_handle_rscn(struct lpfc_vport *vport)
{
@@ -3313,6 +4166,31 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
return 0;
}
+/**
+ * lpfc_els_rcv_flogi: Process an unsolicited flogi iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Fabric Login (FLOGI) IOCB received as an ELS
+ * unsolicited event. An unsolicited FLOGI can be received in a point-to-
+ * point topology. As an unsolicited FLOGI should not be received in a loop
+ * mode, any unsolicited FLOGI received in loop mode shall be ignored. The
+ * lpfc_check_sparm() routine is invoked to check the parameters in the
+ * unsolicited FLOGI. If parameters validation failed, the routine
+ * lpfc_els_rsp_reject() shall be called with reject reason code set to
+ * LSEXP_SPARM_OPTIONS to reject the FLOGI. Otherwise, the Port WWN in the
+ * FLOGI shall be compared with the Port WWN of the @vport to determine who
+ * will initiate PLOGI. The higher lexicographical value party shall has
+ * higher priority (as the winning port) and will initiate PLOGI and
+ * communicate Port_IDs (Addresses) for both nodes in PLOGI. The result
+ * of this will be marked in the @vport fc_flag field with FC_PT2PT_PLOGI
+ * and then the lpfc_els_rsp_acc() routine is invoked to accept the FLOGI.
+ *
+ * Return code
+ * 0 - Successfully processed the unsolicited flogi
+ * 1 - Failed to process the unsolicited flogi
+ **/
static int
lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3402,6 +4280,22 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rcv_rnid: Process an unsolicited rnid iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Request Node Identification Data (RNID) IOCB
+ * received as an ELS unsolicited event. Only when the RNID specified format
+ * 0x0 or 0xDF (Topology Discovery Specific Node Identification Data)
+ * present, this routine will invoke the lpfc_els_rsp_rnid_acc() routine to
+ * Accept (ACC) the RNID ELS command. All the other RNID formats are
+ * rejected by invoking the lpfc_els_rsp_reject() routine.
+ *
+ * Return code
+ * 0 - Successfully processed rnid iocb (currently always return 0)
+ **/
static int
lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3441,6 +4335,19 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rcv_lirr: Process an unsolicited lirr iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes a Link Incident Report Registration(LIRR) IOCB
+ * received as an ELS unsolicited event. Currently, this function just invokes
+ * the lpfc_els_rsp_reject() routine to reject the LIRR IOCB unconditionally.
+ *
+ * Return code
+ * 0 - Successfully processed lirr iocb (currently always return 0)
+ **/
static int
lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3456,6 +4363,25 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine is the completion callback function for the MBX_READ_LNK_STAT
+ * mailbox command. This callback function is to actually send the Accept
+ * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It
+ * collects the link statistics from the completion of the MBX_READ_LNK_STAT
+ * mailbox command, constructs the RPS response with the link statistics
+ * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC
+ * response to the RPS.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the RPS Accept Response ELS IOCB command.
+ *
+ **/
static void
lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
@@ -3531,6 +4457,24 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
+/**
+ * lpfc_els_rcv_rps: Process an unsolicited rps iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Read Port Status (RPS) IOCB received as an
+ * ELS unsolicited event. It first checks the remote port state. If the
+ * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
+ * state, it invokes the lpfc_els_rsp_reject() routine to send the reject
+ * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command
+ * for reading the HBA link statistics. It is for the callback function,
+ * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command
+ * to actually sending out RPS Accept (ACC) response.
+ *
+ * Return codes
+ * 0 - Successfully processed rps iocb (currently always return 0)
+ **/
static int
lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3544,14 +4488,9 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct ls_rjt stat;
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
- (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
- stat.un.b.lsRjtRsvd0 = 0;
- stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
- stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
- stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
- NULL);
- }
+ (ndlp->nlp_state != NLP_STE_MAPPED_NODE))
+ /* reject the unsolicited RPS request and done with it */
+ goto reject_out;
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt;
@@ -3584,6 +4523,9 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
mempool_free(mbox, phba->mbox_mem_pool);
}
}
+
+reject_out:
+ /* issue rejection response */
stat.un.b.lsRjtRsvd0 = 0;
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
@@ -3592,6 +4534,25 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rsp_rpl_acc: Issue an accept rpl els command.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdsize: size of the ELS command.
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine issuees an Accept (ACC) Read Port List (RPL) ELS command.
+ * It is to be called by the lpfc_els_rcv_rpl() routine to accept the RPL.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the RPL Accept Response ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued ACC RPL ELS command
+ * 1 - Failed to issue ACC RPL ELS command
+ **/
static int
lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
@@ -3645,6 +4606,22 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
return 0;
}
+/**
+ * lpfc_els_rcv_rpl: Process an unsolicited rpl iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Read Port List (RPL) IOCB received as an ELS
+ * unsolicited event. It first checks the remote port state. If the remote
+ * port is not in NLP_STE_UNMAPPED_NODE and NLP_STE_MAPPED_NODE states, it
+ * invokes the lpfc_els_rsp_reject() routine to send reject response.
+ * Otherwise, this routine then invokes the lpfc_els_rsp_rpl_acc() routine
+ * to accept the RPL.
+ *
+ * Return code
+ * 0 - Successfully processed rpl iocb (currently always return 0)
+ **/
static int
lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3658,12 +4635,15 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
+ /* issue rejection response */
stat.un.b.lsRjtRsvd0 = 0;
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
NULL);
+ /* rejected the unsolicited RPL request and done with it */
+ return 0;
}
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -3685,6 +4665,30 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rcv_farp: Process an unsolicited farp request els command.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Fibre Channel Address Resolution Protocol
+ * (FARP) Request IOCB received as an ELS unsolicited event. Currently,
+ * the lpfc driver only supports matching on WWPN or WWNN for FARP. As such,
+ * FARP_MATCH_PORT flag and FARP_MATCH_NODE flag are checked against the
+ * Match Flag in the FARP request IOCB: if FARP_MATCH_PORT flag is set, the
+ * remote PortName is compared against the FC PortName stored in the @vport
+ * data structure; if FARP_MATCH_NODE flag is set, the remote NodeName is
+ * compared against the FC NodeName stored in the @vport data structure.
+ * If any of these matches and the FARP_REQUEST_FARPR flag is set in the
+ * FARP request IOCB Response Flag, the lpfc_issue_els_farpr() routine is
+ * invoked to send out FARP Response to the remote node. Before sending the
+ * FARP Response, however, the FARP_REQUEST_PLOGI flag is check in the FARP
+ * request IOCB Response Flag and, if it is set, the lpfc_issue_els_plogi()
+ * routine is invoked to log into the remote port first.
+ *
+ * Return code
+ * 0 - Either the FARP Match Mode not supported or successfully processed
+ **/
static int
lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3744,6 +4748,20 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rcv_farpr: Process an unsolicited farp response iocb.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes Fibre Channel Address Resolution Protocol
+ * Response (FARPR) IOCB received as an ELS unsolicited event. It simply
+ * invokes the lpfc_els_rsp_acc() routine to the remote node to accept
+ * the FARP response request.
+ *
+ * Return code
+ * 0 - Successfully processed FARPR IOCB (currently always return 0)
+ **/
static int
lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
@@ -3768,6 +4786,25 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_rcv_fan: Process an unsolicited fan iocb command.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @fan_ndlp: pointer to a node-list data structure.
+ *
+ * This routine processes a Fabric Address Notification (FAN) IOCB
+ * command received as an ELS unsolicited event. The FAN ELS command will
+ * only be processed on a physical port (i.e., the @vport represents the
+ * physical port). The fabric NodeName and PortName from the FAN IOCB are
+ * compared against those in the phba data structure. If any of those is
+ * different, the lpfc_initial_flogi() routine is invoked to initialize
+ * Fabric Login (FLOGI) to the fabric to start the discover over. Otherwise,
+ * if both of those are identical, the lpfc_issue_fabric_reglogin() routine
+ * is invoked to register login to the fabric.
+ *
+ * Return code
+ * 0 - Successfully processed fan iocb (currently always return 0).
+ **/
static int
lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *fan_ndlp)
@@ -3797,6 +4834,16 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0;
}
+/**
+ * lpfc_els_timeout: Handler funciton to the els timer.
+ * @ptr: holder for the timer function associated data.
+ *
+ * This routine is invoked by the ELS timer after timeout. It posts the ELS
+ * timer timeout event by setting the WORKER_ELS_TMO bit to the work port
+ * event bitmap and then invokes the lpfc_worker_wake_up() routine to wake
+ * up the worker thread. It is for the worker thread to invoke the routine
+ * lpfc_els_timeout_handler() to work on the posted event WORKER_ELS_TMO.
+ **/
void
lpfc_els_timeout(unsigned long ptr)
{
@@ -3816,6 +4863,15 @@ lpfc_els_timeout(unsigned long ptr)
return;
}
+/**
+ * lpfc_els_timeout_handler: Process an els timeout event.
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine is the actual handler function that processes an ELS timeout
+ * event. It walks the ELS ring to get and abort all the IOCBs (except the
+ * ABORT/CLOSE/FARP/FARPR/FDISC), which are associated with the @vport by
+ * invoking the lpfc_sli_issue_abort_iotag() routine.
+ **/
void
lpfc_els_timeout_handler(struct lpfc_vport *vport)
{
@@ -3886,6 +4942,26 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
}
+/**
+ * lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine is used to clean up all the outstanding ELS commands on a
+ * @vport. It first aborts the @vport by invoking lpfc_fabric_abort_vport()
+ * routine. After that, it walks the ELS transmit queue to remove all the
+ * IOCBs with the @vport other than the QUE_RING and ABORT/CLOSE IOCBs. For
+ * the IOCBs with a non-NULL completion callback function, the callback
+ * function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
+ * un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs with a NULL completion
+ * callback function, the IOCB will simply be released. Finally, it walks
+ * the ELS transmit completion queue to issue an abort IOCB to any transmit
+ * completion queue IOCB that is associated with the @vport and is not
+ * an IOCB from libdfc (i.e., the management plane IOCBs that are not
+ * part of the discovery state machine) out to HBA by invoking the
+ * lpfc_sli_issue_abort_iotag() routine. Note that this function issues the
+ * abort IOCB to any transmit completion queueed IOCB, it does not guarantee
+ * the IOCBs are aborted when this function returns.
+ **/
void
lpfc_els_flush_cmd(struct lpfc_vport *vport)
{
@@ -3948,6 +5024,23 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is used to clean up all the outstanding ELS commands on a
+ * @phba. It first aborts the @phba by invoking the lpfc_fabric_abort_hba()
+ * routine. After that, it walks the ELS transmit queue to remove all the
+ * IOCBs to the @phba other than the QUE_RING and ABORT/CLOSE IOCBs. For
+ * the IOCBs with the completion callback function associated, the callback
+ * function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
+ * un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs without the completion
+ * callback function associated, the IOCB will simply be released. Finally,
+ * it walks the ELS transmit completion queue to issue an abort IOCB to any
+ * transmit completion queue IOCB that is not an IOCB from libdfc (i.e., the
+ * management plane IOCBs that are not part of the discovery state machine)
+ * out to HBA by invoking the lpfc_sli_issue_abort_iotag() routine.
+ **/
void
lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
{
@@ -3992,6 +5085,130 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
return;
}
+/**
+ * lpfc_send_els_failure_event: Posts an ELS command failure event.
+ * @phba: Pointer to hba context object.
+ * @cmdiocbp: Pointer to command iocb which reported error.
+ * @rspiocbp: Pointer to response iocb which reported error.
+ *
+ * This function sends an event when there is an ELS command
+ * failure.
+ **/
+void
+lpfc_send_els_failure_event(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdiocbp,
+ struct lpfc_iocbq *rspiocbp)
+{
+ struct lpfc_vport *vport = cmdiocbp->vport;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct lpfc_lsrjt_event lsrjt_event;
+ struct lpfc_fabric_event_header fabric_event;
+ struct ls_rjt stat;
+ struct lpfc_nodelist *ndlp;
+ uint32_t *pcmd;
+
+ ndlp = cmdiocbp->context1;
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ return;
+
+ if (rspiocbp->iocb.ulpStatus == IOSTAT_LS_RJT) {
+ lsrjt_event.header.event_type = FC_REG_ELS_EVENT;
+ lsrjt_event.header.subcategory = LPFC_EVENT_LSRJT_RCV;
+ memcpy(lsrjt_event.header.wwpn, &ndlp->nlp_portname,
+ sizeof(struct lpfc_name));
+ memcpy(lsrjt_event.header.wwnn, &ndlp->nlp_nodename,
+ sizeof(struct lpfc_name));
+ pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
+ cmdiocbp->context2)->virt);
+ lsrjt_event.command = *pcmd;
+ stat.un.lsRjtError = be32_to_cpu(rspiocbp->iocb.un.ulpWord[4]);
+ lsrjt_event.reason_code = stat.un.b.lsRjtRsnCode;
+ lsrjt_event.explanation = stat.un.b.lsRjtRsnCodeExp;
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ sizeof(lsrjt_event),
+ (char *)&lsrjt_event,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+ return;
+ }
+ if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
+ (rspiocbp->iocb.ulpStatus == IOSTAT_FABRIC_BSY)) {
+ fabric_event.event_type = FC_REG_FABRIC_EVENT;
+ if (rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY)
+ fabric_event.subcategory = LPFC_EVENT_PORT_BUSY;
+ else
+ fabric_event.subcategory = LPFC_EVENT_FABRIC_BUSY;
+ memcpy(fabric_event.wwpn, &ndlp->nlp_portname,
+ sizeof(struct lpfc_name));
+ memcpy(fabric_event.wwnn, &ndlp->nlp_nodename,
+ sizeof(struct lpfc_name));
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ sizeof(fabric_event),
+ (char *)&fabric_event,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+ return;
+ }
+
+}
+
+/**
+ * lpfc_send_els_event: Posts unsolicited els event.
+ * @vport: Pointer to vport object.
+ * @ndlp: Pointer FC node object.
+ * @cmd: ELS command code.
+ *
+ * This function posts an event when there is an incoming
+ * unsolicited ELS command.
+ **/
+static void
+lpfc_send_els_event(struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp,
+ uint32_t cmd)
+{
+ struct lpfc_els_event_header els_data;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+ els_data.event_type = FC_REG_ELS_EVENT;
+ switch (cmd) {
+ case ELS_CMD_PLOGI:
+ els_data.subcategory = LPFC_EVENT_PLOGI_RCV;
+ break;
+ case ELS_CMD_PRLO:
+ els_data.subcategory = LPFC_EVENT_PRLO_RCV;
+ break;
+ case ELS_CMD_ADISC:
+ els_data.subcategory = LPFC_EVENT_ADISC_RCV;
+ break;
+ default:
+ return;
+ }
+ memcpy(els_data.wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(els_data.wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ sizeof(els_data),
+ (char *)&els_data,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+
+ return;
+}
+
+
+/**
+ * lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
+ * @phba: pointer to lpfc hba data structure.
+ * @pring: pointer to a SLI ring.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @elsiocb: pointer to lpfc els command iocb data structure.
+ *
+ * This routine is used for processing the IOCB associated with a unsolicited
+ * event. It first determines whether there is an existing ndlp that matches
+ * the DID from the unsolicited IOCB. If not, it will create a new one with
+ * the DID from the unsolicited IOCB. The ELS command from the unsolicited
+ * IOCB is then used to invoke the proper routine and to set up proper state
+ * of the discovery state machine.
+ **/
static void
lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
@@ -4059,8 +5276,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
phba->fc_stat.elsRcvFrame++;
- if (elsiocb->context1)
- lpfc_nlp_put(elsiocb->context1);
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->vport = vport;
@@ -4081,6 +5296,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvPLOGI++;
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+ lpfc_send_els_event(vport, ndlp, cmd);
if (vport->port_state < LPFC_DISC_AUTH) {
if (!(phba->pport->fc_flag & FC_PT2PT) ||
(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -4130,6 +5346,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag);
phba->fc_stat.elsRcvPRLO++;
+ lpfc_send_els_event(vport, ndlp, cmd);
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
break;
@@ -4147,6 +5364,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
"RCV ADISC: did:x%x/ste:x%x flg:x%x",
did, vport->port_state, ndlp->nlp_flag);
+ lpfc_send_els_event(vport, ndlp, cmd);
phba->fc_stat.elsRcvADISC++;
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
@@ -4270,6 +5488,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
NULL);
}
+ lpfc_nlp_put(elsiocb->context1);
+ elsiocb->context1 = NULL;
return;
dropit:
@@ -4282,6 +5502,19 @@ dropit:
phba->fc_stat.elsRcvDrop++;
}
+/**
+ * lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: host virtual N_Port identifier.
+ *
+ * This routine finds a vport on a HBA (referred by @phba) through a
+ * @vpi. The function walks the HBA's vport list and returns the address
+ * of the vport with the matching @vpi.
+ *
+ * Return code
+ * NULL - No vport with the matching @vpi found
+ * Otherwise - Address to the vport with the matching @vpi.
+ **/
static struct lpfc_vport *
lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
{
@@ -4299,6 +5532,18 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
return NULL;
}
+/**
+ * lpfc_els_unsol_event: Process an unsolicited event from an els sli ring.
+ * @phba: pointer to lpfc hba data structure.
+ * @pring: pointer to a SLI ring.
+ * @elsiocb: pointer to lpfc els iocb data structure.
+ *
+ * This routine is used to process an unsolicited event received from a SLI
+ * (Service Level Interface) ring. The actual processing of the data buffer
+ * associated with the unsolicited event is done by invoking the routine
+ * lpfc_els_unsol_buffer() after properly set up the iocb buffer from the
+ * SLI ring on which the unsolicited event was received.
+ **/
void
lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *elsiocb)
@@ -4309,6 +5554,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
+ elsiocb->context1 = NULL;
elsiocb->context2 = NULL;
elsiocb->context3 = NULL;
@@ -4356,8 +5602,6 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* The different unsolicited event handlers would tell us
* if they are done with "mp" by setting context2 to NULL.
*/
- lpfc_nlp_put(elsiocb->context1);
- elsiocb->context1 = NULL;
if (elsiocb->context2) {
lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
elsiocb->context2 = NULL;
@@ -4376,6 +5620,19 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
}
+/**
+ * lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr.
+ * @phba: pointer to lpfc hba data structure.
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine issues a Port Login (PLOGI) to the Name Server with
+ * State Change Request (SCR) for a @vport. This routine will create an
+ * ndlp for the Name Server associated to the @vport if such node does
+ * not already exist. The PLOGI to Name Server is issued by invoking the
+ * lpfc_issue_els_plogi() routine. If Fabric-Device Management Interface
+ * (FDMI) is configured to the @vport, a FDMI node will be created and
+ * the PLOGI to FDMI is issued by invoking lpfc_issue_els_plogi() routine.
+ **/
void
lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
{
@@ -4434,6 +5691,18 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_cmpl_reg_new_vport: Completion callback function to register new vport.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine is the completion callback function to register new vport
+ * mailbox command. If the new vport mailbox command completes successfully,
+ * the fabric registration login shall be performed on physical port (the
+ * new vport created is actually a physical port, with VPI 0) or the port
+ * login to Name Server for State Change Request (SCR) will be performed
+ * on virtual port (real virtual port, with VPI greater than 0).
+ **/
static void
lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
@@ -4491,6 +5760,15 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
+/**
+ * lpfc_register_new_vport: Register a new vport with a HBA.
+ * @phba: pointer to lpfc hba data structure.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine registers the @vport as a new virtual port with a HBA.
+ * It is done through a registering vpi mailbox command.
+ **/
static void
lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp)
@@ -4531,6 +5809,26 @@ mbox_err_exit:
return;
}
+/**
+ * lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function to a Fabric Discover
+ * (FDISC) ELS command. Since all the FDISC ELS commands are issued
+ * single threaded, each FDISC completion callback function will reset
+ * the discovery timer for all vports such that the timers will not get
+ * unnecessary timeout. The function checks the FDISC IOCB status. If error
+ * detected, the vport will be set to FC_VPORT_FAILED state. Otherwise,the
+ * vport will set to FC_VPORT_ACTIVE state. It then checks whether the DID
+ * assigned to the vport has been changed with the completion of the FDISC
+ * command. If so, both RPI (Remote Port Index) and VPI (Virtual Port Index)
+ * are unregistered from the HBA, and then the lpfc_register_new_vport()
+ * routine is invoked to register new vport with the HBA. Otherwise, the
+ * lpfc_do_scr_ns_plogi() routine is invoked to issue a PLOGI to the Name
+ * Server for State Change Request (SCR).
+ **/
static void
lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -4565,58 +5863,80 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
/* FDISC failed */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "0124 FDISC failed. (%d/%d)\n",
+ "0126 FDISC failed. (%d/%d)\n",
irsp->ulpStatus, irsp->un.ulpWord[4]);
+ goto fdisc_failed;
+ }
if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_nlp_put(ndlp);
/* giving up on FDISC. Cancel discovery timer */
lpfc_can_disctmo(vport);
- } else {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag |= FC_FABRIC;
- if (vport->phba->fc_topology == TOPOLOGY_LOOP)
- vport->fc_flag |= FC_PUBLIC_LOOP;
- spin_unlock_irq(shost->host_lock);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= FC_FABRIC;
+ if (vport->phba->fc_topology == TOPOLOGY_LOOP)
+ vport->fc_flag |= FC_PUBLIC_LOOP;
+ spin_unlock_irq(shost->host_lock);
- vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
- lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
- if ((vport->fc_prevDID != vport->fc_myDID) &&
- !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
- /* If our NportID changed, we need to ensure all
- * remaining NPORTs get unreg_login'ed so we can
- * issue unreg_vpi.
- */
- list_for_each_entry_safe(np, next_np,
- &vport->fc_nodes, nlp_listp) {
- if (!NLP_CHK_NODE_ACT(ndlp) ||
- (np->nlp_state != NLP_STE_NPR_NODE) ||
- !(np->nlp_flag & NLP_NPR_ADISC))
- continue;
- spin_lock_irq(shost->host_lock);
- np->nlp_flag &= ~NLP_NPR_ADISC;
- spin_unlock_irq(shost->host_lock);
- lpfc_unreg_rpi(vport, np);
- }
- lpfc_mbx_unreg_vpi(vport);
+ vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
+ lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
+ if ((vport->fc_prevDID != vport->fc_myDID) &&
+ !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
+ /* If our NportID changed, we need to ensure all
+ * remaining NPORTs get unreg_login'ed so we can
+ * issue unreg_vpi.
+ */
+ list_for_each_entry_safe(np, next_np,
+ &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp) ||
+ (np->nlp_state != NLP_STE_NPR_NODE) ||
+ !(np->nlp_flag & NLP_NPR_ADISC))
+ continue;
spin_lock_irq(shost->host_lock);
- vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ np->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(shost->host_lock);
+ lpfc_unreg_rpi(vport, np);
}
-
- if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
- lpfc_register_new_vport(phba, vport, ndlp);
- else
- lpfc_do_scr_ns_plogi(phba, vport);
-
- /* Unconditionaly kick off releasing fabric node for vports */
- lpfc_nlp_put(ndlp);
+ lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
}
+ if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
+ lpfc_register_new_vport(phba, vport, ndlp);
+ else
+ lpfc_do_scr_ns_plogi(phba, vport);
+ goto out;
+fdisc_failed:
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ /* Cancel discovery timer */
+ lpfc_can_disctmo(vport);
+ lpfc_nlp_put(ndlp);
out:
lpfc_els_free_iocb(phba, cmdiocb);
}
+/**
+ * lpfc_issue_els_fdisc: Issue a fdisc iocb command.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @retry: number of retries to the command IOCB.
+ *
+ * This routine prepares and issues a Fabric Discover (FDISC) IOCB to
+ * a remote node (@ndlp) off a @vport. It uses the lpfc_issue_fabric_iocb()
+ * routine to issue the IOCB, which makes sure only one outstanding fabric
+ * IOCB will be sent off HBA at any given time.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the FDISC ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued fdisc iocb command
+ * 1 - Failed to issue fdisc iocb command
+ **/
static int
lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
@@ -4691,6 +6011,20 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0;
}
+/**
+ * lpfc_cmpl_els_npiv_logo: Completion function with vport logo.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function to the issuing of a LOGO
+ * ELS command off a vport. It frees the command IOCB and then decrement the
+ * reference count held on ndlp for this completion function, indicating that
+ * the reference to the ndlp is no long needed. Note that the
+ * lpfc_els_free_iocb() routine decrements the ndlp reference held for this
+ * callback function and an additional explicit ndlp reference decrementation
+ * will trigger the actual release of the ndlp.
+ **/
static void
lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -4712,6 +6046,22 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_nlp_put(ndlp);
}
+/**
+ * lpfc_issue_els_npiv_logo: Issue a logo off a vport.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine issues a LOGO ELS command to an @ndlp off a @vport.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the LOGO ELS command.
+ *
+ * Return codes
+ * 0 - Successfully issued logo off the @vport
+ * 1 - Failed to issue logo off the @vport
+ **/
int
lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
@@ -4757,6 +6107,17 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
return 0;
}
+/**
+ * lpfc_fabric_block_timeout: Handler function to the fabric block timer.
+ * @ptr: holder for the timer function associated data.
+ *
+ * This routine is invoked by the fabric iocb block timer after
+ * timeout. It posts the fabric iocb block timeout event by setting the
+ * WORKER_FABRIC_BLOCK_TMO bit to work port event bitmap and then invokes
+ * lpfc_worker_wake_up() routine to wake up the worker thread. It is for
+ * the worker thread to invoke the lpfc_unblock_fabric_iocbs() on the
+ * posted event WORKER_FABRIC_BLOCK_TMO.
+ **/
void
lpfc_fabric_block_timeout(unsigned long ptr)
{
@@ -4775,6 +6136,16 @@ lpfc_fabric_block_timeout(unsigned long ptr)
return;
}
+/**
+ * lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine issues one fabric iocb from the driver internal list to
+ * the HBA. It first checks whether it's ready to issue one fabric iocb to
+ * the HBA (whether there is no outstanding fabric iocb). If so, it shall
+ * remove one pending fabric iocb from the driver internal list and invokes
+ * lpfc_sli_issue_iocb() routine to send the fabric iocb to the HBA.
+ **/
static void
lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
{
@@ -4824,6 +6195,15 @@ repeat:
return;
}
+/**
+ * lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine unblocks the issuing fabric iocb command. The function
+ * will clear the fabric iocb block bit and then invoke the routine
+ * lpfc_resume_fabric_iocbs() to issue one of the pending fabric iocb
+ * from the driver internal fabric iocb list.
+ **/
void
lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
{
@@ -4833,6 +6213,15 @@ lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
return;
}
+/**
+ * lpfc_block_fabric_iocbs: Block issuing fabric iocb command.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine blocks the issuing fabric iocb for a specified amount of
+ * time (currently 100 ms). This is done by set the fabric iocb block bit
+ * and set up a timeout timer for 100ms. When the block bit is set, no more
+ * fabric iocb will be issued out of the HBA.
+ **/
static void
lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
{
@@ -4846,6 +6235,19 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
return;
}
+/**
+ * lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the callback function that is put to the fabric iocb's
+ * callback function pointer (iocb->iocb_cmpl). The original iocb's callback
+ * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback
+ * function first restores and invokes the original iocb's callback function
+ * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next
+ * fabric bound iocb from the driver internal fabric iocb list onto the wire.
+ **/
static void
lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -4892,6 +6294,30 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
}
+/**
+ * lpfc_issue_fabric_iocb: Issue a fabric iocb command.
+ * @phba: pointer to lpfc hba data structure.
+ * @iocb: pointer to lpfc command iocb data structure.
+ *
+ * This routine is used as the top-level API for issuing a fabric iocb command
+ * such as FLOGI and FDISC. To accommodate certain switch fabric, this driver
+ * function makes sure that only one fabric bound iocb will be outstanding at
+ * any given time. As such, this function will first check to see whether there
+ * is already an outstanding fabric iocb on the wire. If so, it will put the
+ * newly issued iocb onto the driver internal fabric iocb list, waiting to be
+ * issued later. Otherwise, it will issue the iocb on the wire and update the
+ * fabric iocb count it indicate that there is one fabric iocb on the wire.
+ *
+ * Note, this implementation has a potential sending out fabric IOCBs out of
+ * order. The problem is caused by the construction of the "ready" boolen does
+ * not include the condition that the internal fabric IOCB list is empty. As
+ * such, it is possible a fabric IOCB issued by this routine might be "jump"
+ * ahead of the fabric IOCBs in the internal list.
+ *
+ * Return code
+ * IOCB_SUCCESS - either fabric iocb put on the list or issued successfully
+ * IOCB_ERROR - failed to issue fabric iocb
+ **/
static int
lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
{
@@ -4937,7 +6363,17 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
return ret;
}
-
+/**
+ * lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list.
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine aborts all the IOCBs associated with a @vport from the
+ * driver internal fabric IOCB list. The list contains fabric IOCBs to be
+ * issued to the ELS IOCB ring. This abort function walks the fabric IOCB
+ * list, removes each IOCB associated with the @vport off the list, set the
+ * status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
+ * associated with the IOCB.
+ **/
static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
{
LIST_HEAD(completions);
@@ -4967,6 +6403,17 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
}
}
+/**
+ * lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * This routine aborts all the IOCBs associated with an @ndlp from the
+ * driver internal fabric IOCB list. The list contains fabric IOCBs to be
+ * issued to the ELS IOCB ring. This abort function walks the fabric IOCB
+ * list, removes each IOCB associated with the @ndlp off the list, set the
+ * status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
+ * associated with the IOCB.
+ **/
void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
@@ -4996,6 +6443,17 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
}
}
+/**
+ * lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine aborts all the IOCBs currently on the driver internal
+ * fabric IOCB list. The list contains fabric IOCBs to be issued to the ELS
+ * IOCB ring. This function takes the entire IOCB list off the fabric IOCB
+ * list, removes IOCBs off the list, set the status feild to
+ * IOSTAT_LOCAL_REJECT, and invokes the callback function associated with
+ * the IOCB.
+ **/
void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index a98d11bf357..a1a70d9ffc2 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -30,6 +30,7 @@
#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_sli.h"
#include "lpfc_scsi.h"
@@ -88,14 +89,6 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
&phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
}
-
- /*
- * A device is normally blocked for rediscovery and unblocked when
- * devloss timeout happens. In case a vport is removed or driver
- * unloaded before devloss timeout happens, we need to unblock here.
- */
- scsi_target_unblock(&rport->dev);
- return;
}
/*
@@ -215,8 +208,16 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
return;
}
- if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+ if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0284 Devloss timeout Ignored on "
+ "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+ "NPort x%x\n",
+ *name, *(name+1), *(name+2), *(name+3),
+ *(name+4), *(name+5), *(name+6), *(name+7),
+ ndlp->nlp_DID);
return;
+ }
if (ndlp->nlp_type & NLP_FABRIC) {
/* We will clean up these Nodes in linkup */
@@ -237,8 +238,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
}
- if (vport->load_flag & FC_UNLOADING)
- warn_on = 0;
if (warn_on) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
@@ -276,6 +275,124 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
}
+/**
+ * lpfc_alloc_fast_evt: Allocates data structure for posting event.
+ * @phba: Pointer to hba context object.
+ *
+ * This function is called from the functions which need to post
+ * events from interrupt context. This function allocates data
+ * structure required for posting event. It also keeps track of
+ * number of events pending and prevent event storm when there are
+ * too many events.
+ **/
+struct lpfc_fast_path_event *
+lpfc_alloc_fast_evt(struct lpfc_hba *phba) {
+ struct lpfc_fast_path_event *ret;
+
+ /* If there are lot of fast event do not exhaust memory due to this */
+ if (atomic_read(&phba->fast_event_count) > LPFC_MAX_EVT_COUNT)
+ return NULL;
+
+ ret = kzalloc(sizeof(struct lpfc_fast_path_event),
+ GFP_ATOMIC);
+ if (ret)
+ atomic_inc(&phba->fast_event_count);
+ INIT_LIST_HEAD(&ret->work_evt.evt_listp);
+ ret->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
+ return ret;
+}
+
+/**
+ * lpfc_free_fast_evt: Frees event data structure.
+ * @phba: Pointer to hba context object.
+ * @evt: Event object which need to be freed.
+ *
+ * This function frees the data structure required for posting
+ * events.
+ **/
+void
+lpfc_free_fast_evt(struct lpfc_hba *phba,
+ struct lpfc_fast_path_event *evt) {
+
+ atomic_dec(&phba->fast_event_count);
+ kfree(evt);
+}
+
+/**
+ * lpfc_send_fastpath_evt: Posts events generated from fast path.
+ * @phba: Pointer to hba context object.
+ * @evtp: Event data structure.
+ *
+ * This function is called from worker thread, when the interrupt
+ * context need to post an event. This function posts the event
+ * to fc transport netlink interface.
+ **/
+static void
+lpfc_send_fastpath_evt(struct lpfc_hba *phba,
+ struct lpfc_work_evt *evtp)
+{
+ unsigned long evt_category, evt_sub_category;
+ struct lpfc_fast_path_event *fast_evt_data;
+ char *evt_data;
+ uint32_t evt_data_size;
+ struct Scsi_Host *shost;
+
+ fast_evt_data = container_of(evtp, struct lpfc_fast_path_event,
+ work_evt);
+
+ evt_category = (unsigned long) fast_evt_data->un.fabric_evt.event_type;
+ evt_sub_category = (unsigned long) fast_evt_data->un.
+ fabric_evt.subcategory;
+ shost = lpfc_shost_from_vport(fast_evt_data->vport);
+ if (evt_category == FC_REG_FABRIC_EVENT) {
+ if (evt_sub_category == LPFC_EVENT_FCPRDCHKERR) {
+ evt_data = (char *) &fast_evt_data->un.read_check_error;
+ evt_data_size = sizeof(fast_evt_data->un.
+ read_check_error);
+ } else if ((evt_sub_category == LPFC_EVENT_FABRIC_BUSY) ||
+ (evt_sub_category == IOSTAT_NPORT_BSY)) {
+ evt_data = (char *) &fast_evt_data->un.fabric_evt;
+ evt_data_size = sizeof(fast_evt_data->un.fabric_evt);
+ } else {
+ lpfc_free_fast_evt(phba, fast_evt_data);
+ return;
+ }
+ } else if (evt_category == FC_REG_SCSI_EVENT) {
+ switch (evt_sub_category) {
+ case LPFC_EVENT_QFULL:
+ case LPFC_EVENT_DEVBSY:
+ evt_data = (char *) &fast_evt_data->un.scsi_evt;
+ evt_data_size = sizeof(fast_evt_data->un.scsi_evt);
+ break;
+ case LPFC_EVENT_CHECK_COND:
+ evt_data = (char *) &fast_evt_data->un.check_cond_evt;
+ evt_data_size = sizeof(fast_evt_data->un.
+ check_cond_evt);
+ break;
+ case LPFC_EVENT_VARQUEDEPTH:
+ evt_data = (char *) &fast_evt_data->un.queue_depth_evt;
+ evt_data_size = sizeof(fast_evt_data->un.
+ queue_depth_evt);
+ break;
+ default:
+ lpfc_free_fast_evt(phba, fast_evt_data);
+ return;
+ }
+ } else {
+ lpfc_free_fast_evt(phba, fast_evt_data);
+ return;
+ }
+
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ evt_data_size,
+ evt_data,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+
+ lpfc_free_fast_evt(phba, fast_evt_data);
+ return;
+}
+
static void
lpfc_work_list_done(struct lpfc_hba *phba)
{
@@ -347,6 +464,10 @@ lpfc_work_list_done(struct lpfc_hba *phba)
lpfc_unblock_mgmt_io(phba);
complete((struct completion *)(evtp->evt_arg2));
break;
+ case LPFC_EVT_FASTPATH_MGMT_EVT:
+ lpfc_send_fastpath_evt(phba, evtp);
+ free_evt = 0;
+ break;
}
if (free_evt)
kfree(evtp);
@@ -371,6 +492,7 @@ lpfc_work_done(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
if (ha_copy & HA_ERATT)
+ /* Handle the error attention event */
lpfc_handle_eratt(phba);
if (ha_copy & HA_MBATT)
@@ -378,6 +500,7 @@ lpfc_work_done(struct lpfc_hba *phba)
if (ha_copy & HA_LATT)
lpfc_handle_latt(phba);
+
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0; i <= phba->max_vpi; i++) {
@@ -1013,14 +1136,10 @@ out:
}
static void
-lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
+lpfc_enable_la(struct lpfc_hba *phba)
{
uint32_t control;
struct lpfc_sli *psli = &phba->sli;
-
- lpfc_linkdown(phba);
-
- /* turn on Link Attention interrupts - no CLEAR_LA needed */
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_PROCESS_LA;
control = readl(phba->HCregaddr);
@@ -1030,6 +1149,15 @@ lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
}
+static void
+lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
+{
+ lpfc_linkdown(phba);
+ lpfc_enable_la(phba);
+ /* turn on Link Attention interrupts - no CLEAR_LA needed */
+}
+
+
/*
* This routine handles processing a READ_LA mailbox
* command upon completion. It is setup in the LPFC_MBOXQ
@@ -1077,8 +1205,12 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
phba->fc_eventTag = la->eventTag;
+ if (la->mm)
+ phba->sli.sli_flag |= LPFC_MENLO_MAINT;
+ else
+ phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
- if (la->attType == AT_LINK_UP) {
+ if (la->attType == AT_LINK_UP && (!la->mm)) {
phba->fc_stat.LinkUp++;
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -1090,13 +1222,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
} else {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1303 Link Up Event x%x received "
- "Data: x%x x%x x%x x%x\n",
+ "Data: x%x x%x x%x x%x x%x x%x %d\n",
la->eventTag, phba->fc_eventTag,
la->granted_AL_PA, la->UlnkSpeed,
- phba->alpa_map[0]);
+ phba->alpa_map[0],
+ la->mm, la->fa,
+ phba->wait_4_mlo_maint_flg);
}
lpfc_mbx_process_link_up(phba, la);
- } else {
+ } else if (la->attType == AT_LINK_DOWN) {
phba->fc_stat.LinkDown++;
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -1109,11 +1243,46 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
else {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1305 Link Down Event x%x received "
+ "Data: x%x x%x x%x x%x x%x\n",
+ la->eventTag, phba->fc_eventTag,
+ phba->pport->port_state, vport->fc_flag,
+ la->mm, la->fa);
+ }
+ lpfc_mbx_issue_link_down(phba);
+ }
+ if (la->mm && la->attType == AT_LINK_UP) {
+ if (phba->link_state != LPFC_LINK_DOWN) {
+ phba->fc_stat.LinkDown++;
+ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+ "1312 Link Down Event x%x received "
+ "Data: x%x x%x x%x\n",
+ la->eventTag, phba->fc_eventTag,
+ phba->pport->port_state, vport->fc_flag);
+ lpfc_mbx_issue_link_down(phba);
+ } else
+ lpfc_enable_la(phba);
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+ "1310 Menlo Maint Mode Link up Event x%x rcvd "
"Data: x%x x%x x%x\n",
la->eventTag, phba->fc_eventTag,
phba->pport->port_state, vport->fc_flag);
+ /*
+ * The cmnd that triggered this will be waiting for this
+ * signal.
+ */
+ /* WAKEUP for MENLO_SET_MODE or MENLO_RESET command. */
+ if (phba->wait_4_mlo_maint_flg) {
+ phba->wait_4_mlo_maint_flg = 0;
+ wake_up_interruptible(&phba->wait_4_mlo_m_q);
}
- lpfc_mbx_issue_link_down(phba);
+ }
+
+ if (la->fa) {
+ if (la->mm)
+ lpfc_issue_clear_la(phba, vport);
+ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+ "1311 fa %d\n", la->fa);
}
lpfc_mbx_cmpl_read_la_free_mbuf:
@@ -1177,7 +1346,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
scsi_host_put(shost);
}
-void
+int
lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
@@ -1186,7 +1355,7 @@ lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
- return;
+ return 1;
lpfc_unreg_vpi(phba, vport->vpi, mbox);
mbox->vport = vport;
@@ -1197,7 +1366,9 @@ lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
"1800 Could not issue unreg_vpi\n");
mempool_free(mbox, phba->mbox_mem_pool);
vport->unreg_vpi_cmpl = VPORT_ERROR;
+ return rc;
}
+ return 0;
}
static void
@@ -1553,6 +1724,22 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
*/
lpfc_register_remote_port(vport, ndlp);
}
+ if ((new_state == NLP_STE_MAPPED_NODE) &&
+ (vport->stat_data_enabled)) {
+ /*
+ * A new target is discovered, if there is no buffer for
+ * statistical data collection allocate buffer.
+ */
+ ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
+ sizeof(struct lpfc_scsicmd_bkt),
+ GFP_KERNEL);
+
+ if (!ndlp->lat_data)
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
+ "0286 lpfc_nlp_state_cleanup failed to "
+ "allocate statistical data buffer DID "
+ "0x%x\n", ndlp->nlp_DID);
+ }
/*
* if we added to Mapped list, but the remote port
* registration failed or assigned a target id outside
@@ -2786,7 +2973,7 @@ restart_disc:
default:
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
- "0229 Unexpected discovery timeout, "
+ "0273 Unexpected discovery timeout, "
"vport State x%x\n", vport->port_state);
break;
}
@@ -2940,6 +3127,8 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
INIT_LIST_HEAD(&ndlp->nlp_listp);
kref_init(&ndlp->kref);
NLP_INT_NODE_ACT(ndlp);
+ atomic_set(&ndlp->cmd_pending, 0);
+ ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
"node init: did:x%x",
@@ -2979,8 +3168,10 @@ lpfc_nlp_release(struct kref *kref)
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
/* free ndlp memory for final ndlp release */
- if (NLP_CHK_FREE_REQ(ndlp))
+ if (NLP_CHK_FREE_REQ(ndlp)) {
+ kfree(ndlp->lat_data);
mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
+ }
}
/* This routine bumps the reference count for a ndlp structure to ensure
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 7773b949aa7..5de5dabbbee 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1107,6 +1107,8 @@ typedef struct {
/* Start FireFly Register definitions */
#define PCI_VENDOR_ID_EMULEX 0x10df
#define PCI_DEVICE_ID_FIREFLY 0x1ae5
+#define PCI_DEVICE_ID_PROTEUS_VF 0xe100
+#define PCI_DEVICE_ID_PROTEUS_PF 0xe180
#define PCI_DEVICE_ID_SAT_SMB 0xf011
#define PCI_DEVICE_ID_SAT_MID 0xf015
#define PCI_DEVICE_ID_RFLY 0xf095
@@ -1133,10 +1135,12 @@ typedef struct {
#define PCI_DEVICE_ID_LP11000S 0xfc10
#define PCI_DEVICE_ID_LPE11000S 0xfc20
#define PCI_DEVICE_ID_SAT_S 0xfc40
+#define PCI_DEVICE_ID_PROTEUS_S 0xfc50
#define PCI_DEVICE_ID_HELIOS 0xfd00
#define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11
#define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12
#define PCI_DEVICE_ID_ZEPHYR 0xfe00
+#define PCI_DEVICE_ID_HORNET 0xfe05
#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
@@ -1154,6 +1158,7 @@ typedef struct {
#define ZEPHYR_JEDEC_ID 0x0577
#define VIPER_JEDEC_ID 0x4838
#define SATURN_JEDEC_ID 0x1004
+#define HORNET_JDEC_ID 0x2057706D
#define JEDEC_ID_MASK 0x0FFFF000
#define JEDEC_ID_SHIFT 12
@@ -1198,6 +1203,18 @@ typedef struct { /* FireFly BIU registers */
#define HA_RXATT 0x00000008 /* Bit 3 */
#define HA_RXMASK 0x0000000f
+#define HA_R0_CLR_MSK (HA_R0RE_REQ | HA_R0CE_RSP | HA_R0ATT)
+#define HA_R1_CLR_MSK (HA_R1RE_REQ | HA_R1CE_RSP | HA_R1ATT)
+#define HA_R2_CLR_MSK (HA_R2RE_REQ | HA_R2CE_RSP | HA_R2ATT)
+#define HA_R3_CLR_MSK (HA_R3RE_REQ | HA_R3CE_RSP | HA_R3ATT)
+
+#define HA_R0_POS 3
+#define HA_R1_POS 7
+#define HA_R2_POS 11
+#define HA_R3_POS 15
+#define HA_LE_POS 29
+#define HA_MB_POS 30
+#define HA_ER_POS 31
/* Chip Attention Register */
#define CA_REG_OFFSET 4 /* Byte offset from register base address */
@@ -1235,7 +1252,7 @@ typedef struct { /* FireFly BIU registers */
/* Host Control Register */
-#define HC_REG_OFFSET 12 /* Word offset from register base address */
+#define HC_REG_OFFSET 12 /* Byte offset from register base address */
#define HC_MBINT_ENA 0x00000001 /* Bit 0 */
#define HC_R0INT_ENA 0x00000002 /* Bit 1 */
@@ -1248,6 +1265,19 @@ typedef struct { /* FireFly BIU registers */
#define HC_LAINT_ENA 0x20000000 /* Bit 29 */
#define HC_ERINT_ENA 0x80000000 /* Bit 31 */
+/* Message Signaled Interrupt eXtension (MSI-X) message identifiers */
+#define MSIX_DFLT_ID 0
+#define MSIX_RNG0_ID 0
+#define MSIX_RNG1_ID 1
+#define MSIX_RNG2_ID 2
+#define MSIX_RNG3_ID 3
+
+#define MSIX_LINK_ID 4
+#define MSIX_MBOX_ID 5
+
+#define MSIX_SPARE0_ID 6
+#define MSIX_SPARE1_ID 7
+
/* Mailbox Commands */
#define MBX_SHUTDOWN 0x00 /* terminate testing */
#define MBX_LOAD_SM 0x01
@@ -1285,10 +1315,14 @@ typedef struct { /* FireFly BIU registers */
#define MBX_KILL_BOARD 0x24
#define MBX_CONFIG_FARP 0x25
#define MBX_BEACON 0x2A
+#define MBX_CONFIG_MSI 0x30
#define MBX_HEARTBEAT 0x31
#define MBX_WRITE_VPARMS 0x32
#define MBX_ASYNCEVT_ENABLE 0x33
+#define MBX_PORT_CAPABILITIES 0x3B
+#define MBX_PORT_IOV_CONTROL 0x3C
+
#define MBX_CONFIG_HBQ 0x7C
#define MBX_LOAD_AREA 0x81
#define MBX_RUN_BIU_DIAG64 0x84
@@ -1474,24 +1508,18 @@ struct ulp_bde64 { /* SLI-2 */
uint32_t bdeFlags:8; /* BDE Flags 0 IS A SUPPORTED
VALUE !! */
#endif
-
-#define BUFF_USE_RSVD 0x01 /* bdeFlags */
-#define BUFF_USE_INTRPT 0x02 /* Not Implemented with LP6000 */
-#define BUFF_USE_CMND 0x04 /* Optional, 1=cmd/rsp 0=data buffer */
-#define BUFF_USE_RCV 0x08 /* "" "", 1=rcv buffer, 0=xmit
- buffer */
-#define BUFF_TYPE_32BIT 0x10 /* "" "", 1=32 bit addr 0=64 bit
- addr */
-#define BUFF_TYPE_SPECIAL 0x20 /* Not Implemented with LP6000 */
-#define BUFF_TYPE_BDL 0x40 /* Optional, may be set in BDL */
-#define BUFF_TYPE_INVALID 0x80 /* "" "" */
+#define BUFF_TYPE_BDE_64 0x00 /* BDE (Host_resident) */
+#define BUFF_TYPE_BDE_IMMED 0x01 /* Immediate Data BDE */
+#define BUFF_TYPE_BDE_64P 0x02 /* BDE (Port-resident) */
+#define BUFF_TYPE_BDE_64I 0x08 /* Input BDE (Host-resident) */
+#define BUFF_TYPE_BDE_64IP 0x0A /* Input BDE (Port-resident) */
+#define BUFF_TYPE_BLP_64 0x40 /* BLP (Host-resident) */
+#define BUFF_TYPE_BLP_64P 0x42 /* BLP (Port-resident) */
} f;
} tus;
uint32_t addrLow;
uint32_t addrHigh;
};
-#define BDE64_SIZE_WORD 0
-#define BPL64_SIZE_WORD 0x40
typedef struct ULP_BDL { /* SLI-2 */
#ifdef __BIG_ENDIAN_BITFIELD
@@ -2201,7 +2229,10 @@ typedef struct {
typedef struct {
uint32_t eventTag; /* Event tag */
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd1:22;
+ uint32_t rsvd1:19;
+ uint32_t fa:1;
+ uint32_t mm:1; /* Menlo Maintenance mode enabled */
+ uint32_t rx:1;
uint32_t pb:1;
uint32_t il:1;
uint32_t attType:8;
@@ -2209,7 +2240,10 @@ typedef struct {
uint32_t attType:8;
uint32_t il:1;
uint32_t pb:1;
- uint32_t rsvd1:22;
+ uint32_t rx:1;
+ uint32_t mm:1;
+ uint32_t fa:1;
+ uint32_t rsvd1:19;
#endif
#define AT_RESERVED 0x00 /* Reserved - attType */
@@ -2230,6 +2264,7 @@ typedef struct {
#define TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */
#define TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */
+#define TOPOLOGY_LNK_MENLO_MAINTENANCE 0x05 /* maint mode zephtr to menlo */
union {
struct ulp_bde lilpBde; /* This BDE points to a 128 byte buffer
@@ -2324,6 +2359,36 @@ typedef struct {
#define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */
#define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */
+/* Structure for MB Command UPDATE_CFG (0x1B) */
+
+struct update_cfg_var {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint32_t rsvd2:16;
+ uint32_t type:8;
+ uint32_t rsvd:1;
+ uint32_t ra:1;
+ uint32_t co:1;
+ uint32_t cv:1;
+ uint32_t req:4;
+ uint32_t entry_length:16;
+ uint32_t region_id:16;
+#else /* __LITTLE_ENDIAN_BITFIELD */
+ uint32_t req:4;
+ uint32_t cv:1;
+ uint32_t co:1;
+ uint32_t ra:1;
+ uint32_t rsvd:1;
+ uint32_t type:8;
+ uint32_t rsvd2:16;
+ uint32_t region_id:16;
+ uint32_t entry_length:16;
+#endif
+
+ uint32_t resp_info;
+ uint32_t byte_cnt;
+ uint32_t data_offset;
+};
+
struct hbq_mask {
#ifdef __BIG_ENDIAN_BITFIELD
uint8_t tmatch;
@@ -2560,6 +2625,40 @@ typedef struct {
} CONFIG_PORT_VAR;
+/* Structure for MB Command CONFIG_MSI (0x30) */
+struct config_msi_var {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint32_t dfltMsgNum:8; /* Default message number */
+ uint32_t rsvd1:11; /* Reserved */
+ uint32_t NID:5; /* Number of secondary attention IDs */
+ uint32_t rsvd2:5; /* Reserved */
+ uint32_t dfltPresent:1; /* Default message number present */
+ uint32_t addFlag:1; /* Add association flag */
+ uint32_t reportFlag:1; /* Report association flag */
+#else /* __LITTLE_ENDIAN_BITFIELD */
+ uint32_t reportFlag:1; /* Report association flag */
+ uint32_t addFlag:1; /* Add association flag */
+ uint32_t dfltPresent:1; /* Default message number present */
+ uint32_t rsvd2:5; /* Reserved */
+ uint32_t NID:5; /* Number of secondary attention IDs */
+ uint32_t rsvd1:11; /* Reserved */
+ uint32_t dfltMsgNum:8; /* Default message number */
+#endif
+ uint32_t attentionConditions[2];
+ uint8_t attentionId[16];
+ uint8_t messageNumberByHA[64];
+ uint8_t messageNumberByID[16];
+ uint32_t autoClearHA[2];
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint32_t rsvd3:16;
+ uint32_t autoClearID:16;
+#else /* __LITTLE_ENDIAN_BITFIELD */
+ uint32_t autoClearID:16;
+ uint32_t rsvd3:16;
+#endif
+ uint32_t rsvd4;
+};
+
/* SLI-2 Port Control Block */
/* SLIM POINTER */
@@ -2678,10 +2777,12 @@ typedef union {
* NEW_FEATURE
*/
struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ) */
+ struct update_cfg_var varUpdateCfg; /* cmd = 0x1B (UPDATE_CFG)*/
CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */
REG_VPI_VAR varRegVpi; /* cmd = 0x96 (REG_VPI) */
UNREG_VPI_VAR varUnregVpi; /* cmd = 0x97 (UNREG_VPI) */
ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */
+ struct config_msi_var varCfgMSI;/* cmd = x30 (CONFIG_MSI) */
} MAILVARIANTS;
/*
@@ -2715,11 +2816,19 @@ struct sli3_pgp {
uint32_t hbq_get[16];
};
-typedef union {
- struct sli2_desc s2;
- struct sli3_desc s3;
- struct sli3_pgp s3_pgp;
-} SLI_VAR;
+struct sli3_inb_pgp {
+ uint32_t ha_copy;
+ uint32_t counter;
+ struct lpfc_pgp port[MAX_RINGS];
+ uint32_t hbq_get[16];
+};
+
+union sli_var {
+ struct sli2_desc s2;
+ struct sli3_desc s3;
+ struct sli3_pgp s3_pgp;
+ struct sli3_inb_pgp s3_inb_pgp;
+};
typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD
@@ -2737,7 +2846,7 @@ typedef struct {
#endif
MAILVARIANTS un;
- SLI_VAR us;
+ union sli_var us;
} MAILBOX_t;
/*
@@ -3105,6 +3214,27 @@ struct que_xri64cx_ext_fields {
struct lpfc_hbq_entry buff[5];
};
+#define LPFC_EXT_DATA_BDE_COUNT 3
+struct fcp_irw_ext {
+ uint32_t io_tag64_low;
+ uint32_t io_tag64_high;
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint8_t reserved1;
+ uint8_t reserved2;
+ uint8_t reserved3;
+ uint8_t ebde_count;
+#else /* __LITTLE_ENDIAN */
+ uint8_t ebde_count;
+ uint8_t reserved3;
+ uint8_t reserved2;
+ uint8_t reserved1;
+#endif
+ uint32_t reserved4;
+ struct ulp_bde64 rbde; /* response bde */
+ struct ulp_bde64 dbde[LPFC_EXT_DATA_BDE_COUNT]; /* data BDE or BPL */
+ uint8_t icd[32]; /* immediate command data (32 bytes) */
+};
+
typedef struct _IOCB { /* IOCB structure */
union {
GENERIC_RSP grsp; /* Generic response */
@@ -3190,7 +3320,7 @@ typedef struct _IOCB { /* IOCB structure */
/* words 8-31 used for que_xri_cx iocb */
struct que_xri64cx_ext_fields que_xri64cx_ext_words;
-
+ struct fcp_irw_ext fcp_ext;
uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */
} unsli3;
@@ -3292,3 +3422,10 @@ lpfc_error_lost_link(IOCB_t *iocbp)
iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
}
+
+#define MENLO_TRANSPORT_TYPE 0xfe
+#define MENLO_CONTEXT 0
+#define MENLO_PU 3
+#define MENLO_TIMEOUT 30
+#define SETVAR_MLOMNT 0x103107
+#define SETVAR_MLORST 0x103007
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index d51a2a4b43e..909be3301bb 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -36,6 +36,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -52,17 +53,20 @@ static struct scsi_transport_template *lpfc_transport_template = NULL;
static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index);
-/************************************************************************/
-/* */
-/* lpfc_config_port_prep */
-/* This routine will do LPFC initialization prior to the */
-/* CONFIG_PORT mailbox command. This will be initialized */
-/* as a SLI layer callback routine. */
-/* This routine returns 0 on success or -ERESTART if it wants */
-/* the SLI layer to reset the HBA and try again. Any */
-/* other return value indicates an error. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_config_port_prep: Perform lpfc initialization prior to config port.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine will do LPFC initialization prior to issuing the CONFIG_PORT
+ * mailbox command. It retrieves the revision information from the HBA and
+ * collects the Vital Product Data (VPD) about the HBA for preparing the
+ * configuration of the HBA.
+ *
+ * Return codes:
+ * 0 - success.
+ * -ERESTART - requests the SLI layer to reset the HBA and try again.
+ * Any other value - indicates an error.
+ **/
int
lpfc_config_port_prep(struct lpfc_hba *phba)
{
@@ -180,12 +184,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
sizeof (phba->RandomData));
/* Get adapter VPD information */
- pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL);
- if (!pmb->context2)
- goto out_free_mbox;
lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL);
if (!lpfc_vpd_data)
- goto out_free_context2;
+ goto out_free_mbox;
do {
lpfc_dump_mem(phba, pmb, offset);
@@ -200,21 +201,29 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
}
if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
- lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset,
+ lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
+ lpfc_vpd_data + offset,
mb->un.varDmp.word_cnt);
offset += mb->un.varDmp.word_cnt;
} while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
kfree(lpfc_vpd_data);
-out_free_context2:
- kfree(pmb->context2);
out_free_mbox:
mempool_free(pmb, phba->mbox_mem_pool);
return 0;
}
-/* Completion handler for config async event mailbox command. */
+/**
+ * lpfc_config_async_cmpl: Completion handler for config async event mbox cmd.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmboxq: pointer to the driver internal queue element for mailbox command.
+ *
+ * This is the completion handler for driver's configuring asynchronous event
+ * mailbox command to the device. If the mailbox command returns successfully,
+ * it will set internal async event support flag to 1; otherwise, it will
+ * set internal async event support flag to 0.
+ **/
static void
lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
{
@@ -226,16 +235,19 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
return;
}
-/************************************************************************/
-/* */
-/* lpfc_config_port_post */
-/* This routine will do LPFC initialization after the */
-/* CONFIG_PORT mailbox command. This will be initialized */
-/* as a SLI layer callback routine. */
-/* This routine returns 0 on success. Any other return value */
-/* indicates an error. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_config_port_post: Perform lpfc initialization after config port.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine will do LPFC initialization after the CONFIG_PORT mailbox
+ * command call. It performs all internal resource and state setups on the
+ * port: post IOCB buffers, enable appropriate host interrupt attentions,
+ * ELS ring timers, etc.
+ *
+ * Return codes
+ * 0 - success.
+ * Any other value - error.
+ **/
int
lpfc_config_port_post(struct lpfc_hba *phba)
{
@@ -378,6 +390,29 @@ lpfc_config_port_post(struct lpfc_hba *phba)
if (phba->sli_rev != 3)
lpfc_post_rcv_buf(phba);
+ /*
+ * Configure HBA MSI-X attention conditions to messages if MSI-X mode
+ */
+ if (phba->intr_type == MSIX) {
+ rc = lpfc_config_msi(phba, pmb);
+ if (rc) {
+ mempool_free(pmb, phba->mbox_mem_pool);
+ return -EIO;
+ }
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+ if (rc != MBX_SUCCESS) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ "0352 Config MSI mailbox command "
+ "failed, mbxCmd x%x, mbxStatus x%x\n",
+ pmb->mb.mbxCommand, pmb->mb.mbxStatus);
+ mempool_free(pmb, phba->mbox_mem_pool);
+ return -EIO;
+ }
+ }
+
+ /* Initialize ERATT handling flag */
+ phba->hba_flag &= ~HBA_ERATT_HANDLED;
+
/* Enable appropriate host interrupts */
spin_lock_irq(&phba->hbalock);
status = readl(phba->HCregaddr);
@@ -393,26 +428,26 @@ lpfc_config_port_post(struct lpfc_hba *phba)
if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) &&
(phba->cfg_poll & DISABLE_FCP_RING_INT))
- status &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+ status &= ~(HC_R0INT_ENA);
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(&phba->hbalock);
- /*
- * Setup the ring 0 (els) timeout handler
- */
- timeout = phba->fc_ratov << 1;
+ /* Set up ring-0 (ELS) timer */
+ timeout = phba->fc_ratov * 2;
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+ /* Set up heart beat (HB) timer */
mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
phba->hb_outstanding = 0;
phba->last_completion_time = jiffies;
+ /* Set up error attention (ERATT) polling timer */
+ mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
- pmb->vport = vport;
- rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
lpfc_set_loopback_flag(phba);
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0454 Adapter failed to init, mbxCmd x%x "
@@ -447,19 +482,20 @@ lpfc_config_port_post(struct lpfc_hba *phba)
rc);
mempool_free(pmb, phba->mbox_mem_pool);
}
- return (0);
+ return 0;
}
-/************************************************************************/
-/* */
-/* lpfc_hba_down_prep */
-/* This routine will do LPFC uninitialization before the */
-/* HBA is reset when bringing down the SLI Layer. This will be */
-/* initialized as a SLI layer callback routine. */
-/* This routine returns 0 on success. Any other return value */
-/* indicates an error. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_hba_down_prep: Perform lpfc uninitialization prior to HBA reset.
+ * @phba: pointer to lpfc HBA data structure.
+ *
+ * This routine will do LPFC uninitialization before the HBA is reset when
+ * bringing down the SLI Layer.
+ *
+ * Return codes
+ * 0 - success.
+ * Any other value - error.
+ **/
int
lpfc_hba_down_prep(struct lpfc_hba *phba)
{
@@ -481,15 +517,17 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
return 0;
}
-/************************************************************************/
-/* */
-/* lpfc_hba_down_post */
-/* This routine will do uninitialization after the HBA is reset */
-/* when bringing down the SLI Layer. */
-/* This routine returns 0 on success. Any other return value */
-/* indicates an error. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_hba_down_post: Perform lpfc uninitialization after HBA reset.
+ * @phba: pointer to lpfc HBA data structure.
+ *
+ * This routine will do uninitialization after the HBA is reset when bring
+ * down the SLI Layer.
+ *
+ * Return codes
+ * 0 - sucess.
+ * Any other value - error.
+ **/
int
lpfc_hba_down_post(struct lpfc_hba *phba)
{
@@ -548,7 +586,18 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
return 0;
}
-/* HBA heart beat timeout handler */
+/**
+ * lpfc_hb_timeout: The HBA-timer timeout handler.
+ * @ptr: unsigned long holds the pointer to lpfc hba data structure.
+ *
+ * This is the HBA-timer timeout handler registered to the lpfc driver. When
+ * this timer fires, a HBA timeout event shall be posted to the lpfc driver
+ * work-port-events bitmap and the worker thread is notified. This timeout
+ * event will be used by the worker thread to invoke the actual timeout
+ * handler routine, lpfc_hb_timeout_handler. Any periodical operations will
+ * be performed in the timeout handler and the HBA timeout event bit shall
+ * be cleared by the worker thread after it has taken the event bitmap out.
+ **/
static void
lpfc_hb_timeout(unsigned long ptr)
{
@@ -557,17 +606,36 @@ lpfc_hb_timeout(unsigned long ptr)
unsigned long iflag;
phba = (struct lpfc_hba *)ptr;
+
+ /* Check for heart beat timeout conditions */
spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
tmo_posted = phba->pport->work_port_events & WORKER_HB_TMO;
if (!tmo_posted)
phba->pport->work_port_events |= WORKER_HB_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+ /* Tell the worker thread there is work to do */
if (!tmo_posted)
lpfc_worker_wake_up(phba);
return;
}
+/**
+ * lpfc_hb_mbox_cmpl: The lpfc heart-beat mailbox command callback function.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmboxq: pointer to the driver internal queue element for mailbox command.
+ *
+ * This is the callback function to the lpfc heart-beat mailbox command.
+ * If configured, the lpfc driver issues the heart-beat mailbox command to
+ * the HBA every LPFC_HB_MBOX_INTERVAL (current 5) seconds. At the time the
+ * heart-beat mailbox command is issued, the driver shall set up heart-beat
+ * timeout timer to LPFC_HB_MBOX_TIMEOUT (current 30) seconds and marks
+ * heart-beat outstanding state. Once the mailbox command comes back and
+ * no error conditions detected, the heart-beat mailbox command timer is
+ * reset to LPFC_HB_MBOX_INTERVAL seconds and the heart-beat outstanding
+ * state is cleared for the next heart-beat. If the timer expired with the
+ * heart-beat outstanding state set, the driver will put the HBA offline.
+ **/
static void
lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
{
@@ -577,6 +645,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
phba->hb_outstanding = 0;
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ /* Check and reset heart-beat timer is necessary */
mempool_free(pmboxq, phba->mbox_mem_pool);
if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
!(phba->link_state == LPFC_HBA_ERROR) &&
@@ -586,6 +655,22 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
return;
}
+/**
+ * lpfc_hb_timeout_handler: The HBA-timer timeout handler.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This is the actual HBA-timer timeout handler to be invoked by the worker
+ * thread whenever the HBA timer fired and HBA-timeout event posted. This
+ * handler performs any periodic operations needed for the device. If such
+ * periodic event has already been attended to either in the interrupt handler
+ * or by processing slow-ring or fast-ring events within the HBA-timer
+ * timeout window (LPFC_HB_MBOX_INTERVAL), this handler just simply resets
+ * the timer for the next timeout period. If lpfc heart-beat mailbox command
+ * is configured and there is no heart-beat mailbox command outstanding, a
+ * heart-beat mailbox is issued and timer set properly. Otherwise, if there
+ * has been a heart-beat mailbox command outstanding, the HBA shall be put
+ * to offline.
+ **/
void
lpfc_hb_timeout_handler(struct lpfc_hba *phba)
{
@@ -684,6 +769,13 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
}
}
+/**
+ * lpfc_offline_eratt: Bring lpfc offline on hardware error attention.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to bring the HBA offline when HBA hardware error
+ * other than Port Error 6 has been detected.
+ **/
static void
lpfc_offline_eratt(struct lpfc_hba *phba)
{
@@ -704,14 +796,16 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
return;
}
-/************************************************************************/
-/* */
-/* lpfc_handle_eratt */
-/* This routine will handle processing a Host Attention */
-/* Error Status event. This will be initialized */
-/* as a SLI layer callback routine. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_handle_eratt: The HBA hardware error handler.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to handle the following HBA hardware error
+ * conditions:
+ * 1 - HBA error attention interrupt
+ * 2 - DMA ring index out of range
+ * 3 - Mailbox command came back as unknown
+ **/
void
lpfc_handle_eratt(struct lpfc_hba *phba)
{
@@ -722,6 +816,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
unsigned long temperature;
struct temp_event temp_event_data;
struct Scsi_Host *shost;
+ struct lpfc_board_event_header board_event;
/* If the pci channel is offline, ignore possible errors,
* since we cannot communicate with the pci card anyway. */
@@ -731,6 +826,16 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
if (!phba->cfg_enable_hba_reset)
return;
+ /* Send an internal error event to mgmt application */
+ board_event.event_type = FC_REG_BOARD_EVENT;
+ board_event.subcategory = LPFC_EVENT_PORTINTERR;
+ shost = lpfc_shost_from_vport(phba->pport);
+ fc_host_post_vendor_event(shost, fc_get_event_number(),
+ sizeof(board_event),
+ (char *) &board_event,
+ SCSI_NL_VID_TYPE_PCI
+ | PCI_VENDOR_ID_EMULEX);
+
if (phba->work_hs & HS_FFER6) {
/* Re-establishing Link */
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@@ -771,7 +876,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
temp_event_data.data = (uint32_t)temperature;
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0459 Adapter maximum temperature exceeded "
+ "0406 Adapter maximum temperature exceeded "
"(%ld), taking this port offline "
"Data: x%x x%x x%x\n",
temperature, phba->work_hs,
@@ -791,8 +896,8 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
} else {
/* The if clause above forces this code path when the status
- * failure is a value other than FFER6. Do not call the offline
- * twice. This is the adapter hardware error path.
+ * failure is a value other than FFER6. Do not call the offline
+ * twice. This is the adapter hardware error path.
*/
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0457 Adapter Hardware Error "
@@ -808,16 +913,16 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
lpfc_offline_eratt(phba);
}
+ return;
}
-/************************************************************************/
-/* */
-/* lpfc_handle_latt */
-/* This routine will handle processing a Host Attention */
-/* Link Status event. This will be initialized */
-/* as a SLI layer callback routine. */
-/* */
-/************************************************************************/
+/**
+ * lpfc_handle_latt: The HBA link event handler.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked from the worker thread to handle a HBA host
+ * attention link event.
+ **/
void
lpfc_handle_latt(struct lpfc_hba *phba)
{
@@ -898,12 +1003,20 @@ lpfc_handle_latt_err_exit:
return;
}
-/************************************************************************/
-/* */
-/* lpfc_parse_vpd */
-/* This routine will parse the VPD data */
-/* */
-/************************************************************************/
+/**
+ * lpfc_parse_vpd: Parse VPD (Vital Product Data).
+ * @phba: pointer to lpfc hba data structure.
+ * @vpd: pointer to the vital product data.
+ * @len: length of the vital product data in bytes.
+ *
+ * This routine parses the Vital Product Data (VPD). The VPD is treated as
+ * an array of characters. In this routine, the ModelName, ProgramType, and
+ * ModelDesc, etc. fields of the phba data structure will be populated.
+ *
+ * Return codes
+ * 0 - pointer to the VPD passed in is NULL
+ * 1 - success
+ **/
static int
lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
{
@@ -1040,12 +1153,25 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
return(1);
}
+/**
+ * lpfc_get_hba_model_desc: Retrieve HBA device model name and description.
+ * @phba: pointer to lpfc hba data structure.
+ * @mdp: pointer to the data structure to hold the derived model name.
+ * @descp: pointer to the data structure to hold the derived description.
+ *
+ * This routine retrieves HBA's description based on its registered PCI device
+ * ID. The @descp passed into this function points to an array of 256 chars. It
+ * shall be returned with the model name, maximum speed, and the host bus type.
+ * The @mdp passed into this function points to an array of 80 chars. When the
+ * function returns, the @mdp will be filled with the model name.
+ **/
static void
lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
{
lpfc_vpd_t *vp;
uint16_t dev_id = phba->pcidev->device;
int max_speed;
+ int GE = 0;
struct {
char * name;
int max_speed;
@@ -1177,6 +1303,19 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
case PCI_DEVICE_ID_SAT_S:
m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
break;
+ case PCI_DEVICE_ID_HORNET:
+ m = (typeof(m)){"LP21000", max_speed, "PCIe"};
+ GE = 1;
+ break;
+ case PCI_DEVICE_ID_PROTEUS_VF:
+ m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+ break;
+ case PCI_DEVICE_ID_PROTEUS_PF:
+ m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+ break;
+ case PCI_DEVICE_ID_PROTEUS_S:
+ m = (typeof(m)) {"LPemv12002-S", max_speed, "PCIe IOV"};
+ break;
default:
m = (typeof(m)){ NULL };
break;
@@ -1186,18 +1325,25 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
snprintf(mdp, 79,"%s", m.name);
if (descp && descp[0] == '\0')
snprintf(descp, 255,
- "Emulex %s %dGb %s Fibre Channel Adapter",
- m.name, m.max_speed, m.bus);
+ "Emulex %s %d%s %s %s",
+ m.name, m.max_speed,
+ (GE) ? "GE" : "Gb",
+ m.bus,
+ (GE) ? "FCoE Adapter" : "Fibre Channel Adapter");
}
-/**************************************************/
-/* lpfc_post_buffer */
-/* */
-/* This routine will post count buffers to the */
-/* ring with the QUE_RING_BUF_CN command. This */
-/* allows 3 buffers / command to be posted. */
-/* Returns the number of buffers NOT posted. */
-/**************************************************/
+/**
+ * lpfc_post_buffer: Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring.
+ * @phba: pointer to lpfc hba data structure.
+ * @pring: pointer to a IOCB ring.
+ * @cnt: the number of IOCBs to be posted to the IOCB ring.
+ *
+ * This routine posts a given number of IOCBs with the associated DMA buffer
+ * descriptors specified by the cnt argument to the given IOCB ring.
+ *
+ * Return codes
+ * The number of IOCBs NOT able to be posted to the IOCB ring.
+ **/
int
lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
{
@@ -1287,12 +1433,17 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
return 0;
}
-/************************************************************************/
-/* */
-/* lpfc_post_rcv_buf */
-/* This routine post initial rcv buffers to the configured rings */
-/* */
-/************************************************************************/
+/**
+ * lpfc_post_rcv_buf: Post the initial receive IOCB buffers to ELS ring.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine posts initial receive IOCB buffers to the ELS ring. The
+ * current number of initial IOCB buffers specified by LPFC_BUF_RING0 is
+ * set to 64 IOCBs.
+ *
+ * Return codes
+ * 0 - success (currently always success)
+ **/
static int
lpfc_post_rcv_buf(struct lpfc_hba *phba)
{
@@ -1307,11 +1458,13 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba)
#define S(N,V) (((V)<<(N))|((V)>>(32-(N))))
-/************************************************************************/
-/* */
-/* lpfc_sha_init */
-/* */
-/************************************************************************/
+/**
+ * lpfc_sha_init: Set up initial array of hash table entries.
+ * @HashResultPointer: pointer to an array as hash table.
+ *
+ * This routine sets up the initial values to the array of hash table entries
+ * for the LC HBAs.
+ **/
static void
lpfc_sha_init(uint32_t * HashResultPointer)
{
@@ -1322,11 +1475,16 @@ lpfc_sha_init(uint32_t * HashResultPointer)
HashResultPointer[4] = 0xC3D2E1F0;
}
-/************************************************************************/
-/* */
-/* lpfc_sha_iterate */
-/* */
-/************************************************************************/
+/**
+ * lpfc_sha_iterate: Iterate initial hash table with the working hash table.
+ * @HashResultPointer: pointer to an initial/result hash table.
+ * @HashWorkingPointer: pointer to an working hash table.
+ *
+ * This routine iterates an initial hash table pointed by @HashResultPointer
+ * with the values from the working hash table pointeed by @HashWorkingPointer.
+ * The results are putting back to the initial hash table, returned through
+ * the @HashResultPointer as the result hash table.
+ **/
static void
lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer)
{
@@ -1374,22 +1532,29 @@ lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer)
}
-/************************************************************************/
-/* */
-/* lpfc_challenge_key */
-/* */
-/************************************************************************/
+/**
+ * lpfc_challenge_key: Create challenge key based on WWPN of the HBA.
+ * @RandomChallenge: pointer to the entry of host challenge random number array.
+ * @HashWorking: pointer to the entry of the working hash array.
+ *
+ * This routine calculates the working hash array referred by @HashWorking
+ * from the challenge random numbers associated with the host, referred by
+ * @RandomChallenge. The result is put into the entry of the working hash
+ * array and returned by reference through @HashWorking.
+ **/
static void
lpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking)
{
*HashWorking = (*RandomChallenge ^ *HashWorking);
}
-/************************************************************************/
-/* */
-/* lpfc_hba_init */
-/* */
-/************************************************************************/
+/**
+ * lpfc_hba_init: Perform special handling for LC HBA initialization.
+ * @phba: pointer to lpfc hba data structure.
+ * @hbainit: pointer to an array of unsigned 32-bit integers.
+ *
+ * This routine performs the special handling for LC HBA initialization.
+ **/
void
lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
{
@@ -1412,6 +1577,15 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
kfree(HashWorking);
}
+/**
+ * lpfc_cleanup: Performs vport cleanups before deleting a vport.
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine performs the necessary cleanups before deleting the @vport.
+ * It invokes the discovery state machine to perform necessary state
+ * transitions and to release the ndlps associated with the @vport. Note,
+ * the physical port is treated as @vport 0.
+ **/
void
lpfc_cleanup(struct lpfc_vport *vport)
{
@@ -1459,14 +1633,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
lpfc_disc_state_machine(vport, ndlp, NULL,
NLP_EVT_DEVICE_RM);
- /* nlp_type zero is not defined, nlp_flag zero also not defined,
- * nlp_state is unused, this happens when
- * an initiator has logged
- * into us so cleanup this ndlp.
- */
- if ((ndlp->nlp_type == 0) && (ndlp->nlp_flag == 0) &&
- (ndlp->nlp_state == 0))
- lpfc_nlp_put(ndlp);
}
/* At this point, ALL ndlp's should be gone
@@ -1482,7 +1648,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
&vport->fc_nodes, nlp_listp) {
lpfc_printf_vlog(ndlp->vport, KERN_ERR,
LOG_NODE,
- "0282: did:x%x ndlp:x%p "
+ "0282 did:x%x ndlp:x%p "
"usgmap:x%x refcnt:%d\n",
ndlp->nlp_DID, (void *)ndlp,
ndlp->nlp_usg_map,
@@ -1498,6 +1664,14 @@ lpfc_cleanup(struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_stop_vport_timers: Stop all the timers associated with a vport.
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine stops all the timers associated with a @vport. This function
+ * is invoked before disabling or deleting a @vport. Note that the physical
+ * port is treated as @vport 0.
+ **/
void
lpfc_stop_vport_timers(struct lpfc_vport *vport)
{
@@ -1507,6 +1681,13 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_stop_phba_timers: Stop all the timers associated with an HBA.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine stops all the timers associated with a HBA. This function is
+ * invoked before either putting a HBA offline or unloading the driver.
+ **/
static void
lpfc_stop_phba_timers(struct lpfc_hba *phba)
{
@@ -1516,9 +1697,20 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba)
del_timer_sync(&phba->fabric_block_timer);
phba->hb_outstanding = 0;
del_timer_sync(&phba->hb_tmofunc);
+ del_timer_sync(&phba->eratt_poll);
return;
}
+/**
+ * lpfc_block_mgmt_io: Mark a HBA's management interface as blocked.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine marks a HBA's management interface as blocked. Once the HBA's
+ * management interface is marked as blocked, all the user space access to
+ * the HBA, whether they are from sysfs interface or libdfc interface will
+ * all be blocked. The HBA is set to block the management interface when the
+ * driver prepares the HBA interface for online or offline.
+ **/
static void
lpfc_block_mgmt_io(struct lpfc_hba * phba)
{
@@ -1529,6 +1721,18 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
spin_unlock_irqrestore(&phba->hbalock, iflag);
}
+/**
+ * lpfc_online: Initialize and bring a HBA online.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine initializes the HBA and brings a HBA online. During this
+ * process, the management interface is blocked to prevent user space access
+ * to the HBA interfering with the driver initialization.
+ *
+ * Return codes
+ * 0 - successful
+ * 1 - failed
+ **/
int
lpfc_online(struct lpfc_hba *phba)
{
@@ -1574,6 +1778,17 @@ lpfc_online(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_unblock_mgmt_io: Mark a HBA's management interface to be not blocked.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine marks a HBA's management interface as not blocked. Once the
+ * HBA's management interface is marked as not blocked, all the user space
+ * access to the HBA, whether they are from sysfs interface or libdfc
+ * interface will be allowed. The HBA is set to block the management interface
+ * when the driver prepares the HBA interface for online or offline and then
+ * set to unblock the management interface afterwards.
+ **/
void
lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
{
@@ -1584,6 +1799,14 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
spin_unlock_irqrestore(&phba->hbalock, iflag);
}
+/**
+ * lpfc_offline_prep: Prepare a HBA to be brought offline.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to prepare a HBA to be brought offline. It performs
+ * unregistration login to all the nodes on all vports and flushes the mailbox
+ * queue to make it ready to be brought offline.
+ **/
void
lpfc_offline_prep(struct lpfc_hba * phba)
{
@@ -1633,6 +1856,14 @@ lpfc_offline_prep(struct lpfc_hba * phba)
lpfc_sli_flush_mbox_queue(phba);
}
+/**
+ * lpfc_offline: Bring a HBA offline.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine actually brings a HBA offline. It stops all the timers
+ * associated with the HBA, brings down the SLI layer, and eventually
+ * marks the HBA as in offline state for the upper layer protocol.
+ **/
void
lpfc_offline(struct lpfc_hba *phba)
{
@@ -1670,12 +1901,17 @@ lpfc_offline(struct lpfc_hba *phba)
lpfc_destroy_vport_work_array(phba, vports);
}
-/******************************************************************************
-* Function name: lpfc_scsi_free
-*
-* Description: Called from lpfc_pci_remove_one free internal driver resources
-*
-******************************************************************************/
+/**
+ * lpfc_scsi_free: Free all the SCSI buffers and IOCBs from driver lists.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is to free all the SCSI buffers and IOCBs from the driver
+ * list back to kernel. It is called from lpfc_pci_remove_one to free
+ * the internal resources before the device is removed from the system.
+ *
+ * Return codes
+ * 0 - successful (for now, it always returns 0)
+ **/
static int
lpfc_scsi_free(struct lpfc_hba *phba)
{
@@ -1704,6 +1940,22 @@ lpfc_scsi_free(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_create_port: Create an FC port.
+ * @phba: pointer to lpfc hba data structure.
+ * @instance: a unique integer ID to this FC port.
+ * @dev: pointer to the device data structure.
+ *
+ * This routine creates a FC port for the upper layer protocol. The FC port
+ * can be created on top of either a physical port or a virtual port provided
+ * by the HBA. This routine also allocates a SCSI host data structure (shost)
+ * and associates the FC port created before adding the shost into the SCSI
+ * layer.
+ *
+ * Return codes
+ * @vport - pointer to the virtual N_Port data structure.
+ * NULL - port create failed.
+ **/
struct lpfc_vport *
lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
{
@@ -1777,6 +2029,13 @@ out:
return NULL;
}
+/**
+ * destroy_port: Destroy an FC port.
+ * @vport: pointer to an lpfc virtual N_Port data structure.
+ *
+ * This routine destroys a FC port from the upper layer protocol. All the
+ * resources associated with the port are released.
+ **/
void
destroy_port(struct lpfc_vport *vport)
{
@@ -1797,6 +2056,16 @@ destroy_port(struct lpfc_vport *vport)
return;
}
+/**
+ * lpfc_get_instance: Get a unique integer ID.
+ *
+ * This routine allocates a unique integer ID from lpfc_hba_index pool. It
+ * uses the kernel idr facility to perform the task.
+ *
+ * Return codes:
+ * instance - a unique integer ID allocated as the new instance.
+ * -1 - lpfc get instance failed.
+ **/
int
lpfc_get_instance(void)
{
@@ -1810,11 +2079,21 @@ lpfc_get_instance(void)
return instance;
}
-/*
- * Note: there is no scan_start function as adapter initialization
- * will have asynchronously kicked off the link initialization.
- */
-
+/**
+ * lpfc_scan_finished: method for SCSI layer to detect whether scan is done.
+ * @shost: pointer to SCSI host data structure.
+ * @time: elapsed time of the scan in jiffies.
+ *
+ * This routine is called by the SCSI layer with a SCSI host to determine
+ * whether the scan host is finished.
+ *
+ * Note: there is no scan_start function as adapter initialization will have
+ * asynchronously kicked off the link initialization.
+ *
+ * Return codes
+ * 0 - SCSI host scan is not over yet.
+ * 1 - SCSI host scan is over.
+ **/
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
@@ -1858,6 +2137,13 @@ finished:
return stat;
}
+/**
+ * lpfc_host_attrib_init: Initialize SCSI host attributes on a FC port.
+ * @shost: pointer to SCSI host data structure.
+ *
+ * This routine initializes a given SCSI host attributes on a FC port. The
+ * SCSI host can be either on top of a physical port or a virtual port.
+ **/
void lpfc_host_attrib_init(struct Scsi_Host *shost)
{
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
@@ -1906,42 +2192,157 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock);
}
+/**
+ * lpfc_enable_msix: Enable MSI-X interrupt mode.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to enable the MSI-X interrupt vectors. The kernel
+ * function pci_enable_msix() is called to enable the MSI-X vectors. Note that
+ * pci_enable_msix(), once invoked, enables either all or nothing, depending
+ * on the current availability of PCI vector resources. The device driver is
+ * responsible for calling the individual request_irq() to register each MSI-X
+ * vector with a interrupt handler, which is done in this function. Note that
+ * later when device is unloading, the driver should always call free_irq()
+ * on all MSI-X vectors it has done request_irq() on before calling
+ * pci_disable_msix(). Failure to do so results in a BUG_ON() and a device
+ * will be left with MSI-X enabled and leaks its vectors.
+ *
+ * Return codes
+ * 0 - sucessful
+ * other values - error
+ **/
static int
lpfc_enable_msix(struct lpfc_hba *phba)
{
- int error;
+ int rc, i;
+ LPFC_MBOXQ_t *pmb;
- phba->msix_entries[0].entry = 0;
- phba->msix_entries[0].vector = 0;
+ /* Set up MSI-X multi-message vectors */
+ for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+ phba->msix_entries[i].entry = i;
- error = pci_enable_msix(phba->pcidev, phba->msix_entries,
+ /* Configure MSI-X capability structure */
+ rc = pci_enable_msix(phba->pcidev, phba->msix_entries,
ARRAY_SIZE(phba->msix_entries));
- if (error) {
+ if (rc) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0420 Enable MSI-X failed (%d), continuing "
- "with MSI\n", error);
- pci_disable_msix(phba->pcidev);
- return error;
+ "with MSI\n", rc);
+ goto msi_fail_out;
+ } else
+ for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0477 MSI-X entry[%d]: vector=x%x "
+ "message=%d\n", i,
+ phba->msix_entries[i].vector,
+ phba->msix_entries[i].entry);
+ /*
+ * Assign MSI-X vectors to interrupt handlers
+ */
+
+ /* vector-0 is associated to slow-path handler */
+ rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler,
+ IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0421 MSI-X slow-path request_irq failed "
+ "(%d), continuing with MSI\n", rc);
+ goto msi_fail_out;
}
- error = request_irq(phba->msix_entries[0].vector, lpfc_intr_handler, 0,
- LPFC_DRIVER_NAME, phba);
- if (error) {
+ /* vector-1 is associated to fast-path handler */
+ rc = request_irq(phba->msix_entries[1].vector, &lpfc_fp_intr_handler,
+ IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba);
+
+ if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0421 MSI-X request_irq failed (%d), "
- "continuing with MSI\n", error);
- pci_disable_msix(phba->pcidev);
+ "0429 MSI-X fast-path request_irq failed "
+ "(%d), continuing with MSI\n", rc);
+ goto irq_fail_out;
}
- return error;
+
+ /*
+ * Configure HBA MSI-X attention conditions to messages
+ */
+ pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+
+ if (!pmb) {
+ rc = -ENOMEM;
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0474 Unable to allocate memory for issuing "
+ "MBOX_CONFIG_MSI command\n");
+ goto mem_fail_out;
+ }
+ rc = lpfc_config_msi(phba, pmb);
+ if (rc)
+ goto mbx_fail_out;
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+ if (rc != MBX_SUCCESS) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ "0351 Config MSI mailbox command failed, "
+ "mbxCmd x%x, mbxStatus x%x\n",
+ pmb->mb.mbxCommand, pmb->mb.mbxStatus);
+ goto mbx_fail_out;
+ }
+
+ /* Free memory allocated for mailbox command */
+ mempool_free(pmb, phba->mbox_mem_pool);
+ return rc;
+
+mbx_fail_out:
+ /* Free memory allocated for mailbox command */
+ mempool_free(pmb, phba->mbox_mem_pool);
+
+mem_fail_out:
+ /* free the irq already requested */
+ free_irq(phba->msix_entries[1].vector, phba);
+
+irq_fail_out:
+ /* free the irq already requested */
+ free_irq(phba->msix_entries[0].vector, phba);
+
+msi_fail_out:
+ /* Unconfigure MSI-X capability structure */
+ pci_disable_msix(phba->pcidev);
+ return rc;
}
+/**
+ * lpfc_disable_msix: Disable MSI-X interrupt mode.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to release the MSI-X vectors and then disable the
+ * MSI-X interrupt mode.
+ **/
static void
lpfc_disable_msix(struct lpfc_hba *phba)
{
- free_irq(phba->msix_entries[0].vector, phba);
+ int i;
+
+ /* Free up MSI-X multi-message vectors */
+ for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+ free_irq(phba->msix_entries[i].vector, phba);
+ /* Disable MSI-X */
pci_disable_msix(phba->pcidev);
}
+/**
+ * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
+ * @pdev: pointer to PCI device
+ * @pid: pointer to PCI device identifier
+ *
+ * This routine is to be registered to the kernel's PCI subsystem. When an
+ * Emulex HBA is presented in PCI bus, the kernel PCI subsystem looks at
+ * PCI device-specific information of the device and driver to see if the
+ * driver state that it can support this kind of device. If the match is
+ * successful, the driver core invokes this routine. If this routine
+ * determines it can claim the HBA, it does all the initialization that it
+ * needs to do to handle the HBA properly.
+ *
+ * Return code
+ * 0 - driver can claim the device
+ * negative value - driver can not claim the device
+ **/
static int __devinit
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{
@@ -1956,6 +2357,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
int i, hbq_count;
uint16_t iotag;
int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ struct lpfc_adapter_event_header adapter_event;
if (pci_enable_device_mem(pdev))
goto out;
@@ -1966,6 +2368,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (!phba)
goto out_release_regions;
+ atomic_set(&phba->fast_event_count, 0);
spin_lock_init(&phba->hbalock);
/* Initialize ndlp management spinlock */
@@ -1978,6 +2381,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_phba;
INIT_LIST_HEAD(&phba->port_list);
+ init_waitqueue_head(&phba->wait_4_mlo_m_q);
/*
* Get all the module params for configuring this host and then
* establish the host.
@@ -2000,6 +2404,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
init_timer(&phba->fabric_block_timer);
phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
phba->fabric_block_timer.data = (unsigned long) phba;
+ init_timer(&phba->eratt_poll);
+ phba->eratt_poll.function = lpfc_poll_eratt;
+ phba->eratt_poll.data = (unsigned long) phba;
pci_set_master(pdev);
pci_try_set_mwi(pdev);
@@ -2019,7 +2426,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
bar2map_len = pci_resource_len(phba->pcidev, 2);
/* Map HBA SLIM to a kernel virtual address. */
- phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len);
+ phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len);
if (!phba->slim_memmap_p) {
error = -ENODEV;
dev_printk(KERN_ERR, &pdev->dev,
@@ -2037,12 +2444,18 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
}
/* Allocate memory for SLI-2 structures */
- phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
- &phba->slim2p_mapping, GFP_KERNEL);
- if (!phba->slim2p)
+ phba->slim2p.virt = dma_alloc_coherent(&phba->pcidev->dev,
+ SLI2_SLIM_SIZE,
+ &phba->slim2p.phys,
+ GFP_KERNEL);
+ if (!phba->slim2p.virt)
goto out_iounmap;
- memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
+ memset(phba->slim2p.virt, 0, SLI2_SLIM_SIZE);
+ phba->mbox = phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, mbx);
+ phba->pcb = (phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, pcb));
+ phba->IOCBs = (phba->slim2p.virt +
+ offsetof(struct lpfc_sli2_slim, IOCBs));
phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
lpfc_sli_hbq_size(),
@@ -2111,7 +2524,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->fc_arbtov = FF_DEF_ARBTOV;
INIT_LIST_HEAD(&phba->work_list);
- phba->work_ha_mask = (HA_ERATT|HA_MBATT|HA_LATT);
+ phba->work_ha_mask = (HA_ERATT | HA_MBATT | HA_LATT);
phba->work_ha_mask |= (HA_RXMASK << (LPFC_ELS_RING * 4));
/* Initialize the wait queue head for the kernel thread */
@@ -2146,21 +2559,42 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
pci_set_drvdata(pdev, shost);
phba->intr_type = NONE;
+ phba->MBslimaddr = phba->slim_memmap_p;
+ phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+ phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+ phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+ phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+
+ /* Configure and enable interrupt */
if (phba->cfg_use_msi == 2) {
- error = lpfc_enable_msix(phba);
- if (!error)
- phba->intr_type = MSIX;
+ /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
+ error = lpfc_sli_config_port(phba, 3);
+ if (error)
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0427 Firmware not capable of SLI 3 mode.\n");
+ else {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0426 Firmware capable of SLI 3 mode.\n");
+ /* Now, try to enable MSI-X interrupt mode */
+ error = lpfc_enable_msix(phba);
+ if (!error) {
+ phba->intr_type = MSIX;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0430 enable MSI-X mode.\n");
+ }
+ }
}
/* Fallback to MSI if MSI-X initialization failed */
if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
retval = pci_enable_msi(phba->pcidev);
- if (!retval)
+ if (!retval) {
phba->intr_type = MSI;
- else
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "0452 Enable MSI failed, continuing "
- "with IRQ\n");
+ "0473 enable MSI mode.\n");
+ } else
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0452 enable IRQ mode.\n");
}
/* MSI-X is the only case the doesn't need to call request_irq */
@@ -2176,18 +2610,16 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->intr_type = INTx;
}
- phba->MBslimaddr = phba->slim_memmap_p;
- phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
- phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
- phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
- phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
-
if (lpfc_alloc_sysfs_attr(vport)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1476 Failed to allocate sysfs attr\n");
error = -ENOMEM;
goto out_free_irq;
}
if (lpfc_sli_hba_setup(phba)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1477 Failed to set up hba\n");
error = -ENODEV;
goto out_remove_device;
}
@@ -2206,6 +2638,16 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
spin_unlock_irq(shost->host_lock);
}
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0428 Perform SCSI scan\n");
+ /* Send board arrival event to upper layer */
+ adapter_event.event_type = FC_REG_ADAPTER_EVENT;
+ adapter_event.subcategory = LPFC_EVENT_ARRIVAL;
+ fc_host_post_vendor_event(shost, fc_get_event_number(),
+ sizeof(adapter_event),
+ (char *) &adapter_event,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+
scsi_scan_host(shost);
return 0;
@@ -2238,11 +2680,11 @@ out_free_iocbq:
}
lpfc_mem_free(phba);
out_free_hbqslimp:
- dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
- phba->hbqslimp.phys);
+ dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(),
+ phba->hbqslimp.virt, phba->hbqslimp.phys);
out_free_slim:
- dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
- phba->slim2p_mapping);
+ dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+ phba->slim2p.virt, phba->slim2p.phys);
out_iounmap:
iounmap(phba->ctrl_regs_memmap_p);
out_iounmap_slim:
@@ -2262,6 +2704,14 @@ out:
return error;
}
+/**
+ * lpfc_pci_remove_one: lpfc PCI func to unregister device from PCI subsystem.
+ * @pdev: pointer to PCI device
+ *
+ * This routine is to be registered to the kernel's PCI subsystem. When an
+ * Emulex HBA is removed from PCI bus. It perform all the necessary cleanup
+ * for the HBA device to be removed from the PCI subsystem properly.
+ **/
static void __devexit
lpfc_pci_remove_one(struct pci_dev *pdev)
{
@@ -2316,12 +2766,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
lpfc_scsi_free(phba);
lpfc_mem_free(phba);
- dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
- phba->hbqslimp.phys);
+ dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(),
+ phba->hbqslimp.virt, phba->hbqslimp.phys);
/* Free resources associated with SLI2 interface */
dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
- phba->slim2p, phba->slim2p_mapping);
+ phba->slim2p.virt, phba->slim2p.phys);
/* unmap adapter SLIM and Control Registers */
iounmap(phba->ctrl_regs_memmap_p);
@@ -2336,13 +2786,21 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
}
/**
- * lpfc_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci conneection state
+ * lpfc_io_error_detected: Driver method for handling PCI I/O error detected.
+ * @pdev: pointer to PCI device.
+ * @state: the current PCI connection state.
*
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
+ * This routine is registered to the PCI subsystem for error handling. This
+ * function is called by the PCI subsystem after a PCI bus error affecting
+ * this device has been detected. When this function is invoked, it will
+ * need to stop all the I/Os and interrupt(s) to the device. Once that is
+ * done, it will return PCI_ERS_RESULT_NEED_RESET for the PCI subsystem to
+ * perform proper recovery as desired.
+ *
+ * Return codes
+ * PCI_ERS_RESULT_NEED_RESET - need to reset before recovery
+ * PCI_ERS_RESULT_DISCONNECT - device could not be recovered
+ **/
static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
@@ -2351,8 +2809,15 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
- if (state == pci_channel_io_perm_failure)
+ if (state == pci_channel_io_perm_failure) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0472 PCI channel I/O permanent failure\n");
+ /* Block all SCSI devices' I/Os on the host */
+ lpfc_scsi_dev_block(phba);
+ /* Clean up all driver's outstanding SCSI I/Os */
+ lpfc_sli_flush_fcp_rings(phba);
return PCI_ERS_RESULT_DISCONNECT;
+ }
pci_disable_device(pdev);
/*
@@ -2376,10 +2841,21 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
}
/**
- * lpfc_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
+ * lpfc_io_slot_reset: Restart a PCI device from scratch.
+ * @pdev: pointer to PCI device.
+ *
+ * This routine is registered to the PCI subsystem for error handling. This is
+ * called after PCI bus has been reset to restart the PCI card from scratch,
+ * as if from a cold-boot. During the PCI subsystem error recovery, after the
+ * driver returns PCI_ERS_RESULT_NEED_RESET, the PCI subsystem will perform
+ * proper error recovery and then call this routine before calling the .resume
+ * method to recover the device. This function will initialize the HBA device,
+ * enable the interrupt, but it will just put the HBA to offline state without
+ * passing any I/O traffic.
*
- * Restart the card from scratch, as if from a cold-boot.
+ * Return codes
+ * PCI_ERS_RESULT_RECOVERED - the device has been recovered
+ * PCI_ERS_RESULT_DISCONNECT - device could not be recovered
*/
static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
{
@@ -2404,20 +2880,34 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
/* Enable configured interrupt method */
phba->intr_type = NONE;
if (phba->cfg_use_msi == 2) {
- error = lpfc_enable_msix(phba);
- if (!error)
- phba->intr_type = MSIX;
+ /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
+ error = lpfc_sli_config_port(phba, 3);
+ if (error)
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0478 Firmware not capable of SLI 3 mode.\n");
+ else {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0479 Firmware capable of SLI 3 mode.\n");
+ /* Now, try to enable MSI-X interrupt mode */
+ error = lpfc_enable_msix(phba);
+ if (!error) {
+ phba->intr_type = MSIX;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0480 enable MSI-X mode.\n");
+ }
+ }
}
/* Fallback to MSI if MSI-X initialization failed */
if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
retval = pci_enable_msi(phba->pcidev);
- if (!retval)
+ if (!retval) {
phba->intr_type = MSI;
- else
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "0470 Enable MSI failed, continuing "
- "with IRQ\n");
+ "0481 enable MSI mode.\n");
+ } else
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "0470 enable IRQ mode.\n");
}
/* MSI-X is the only case the doesn't need to call request_irq */
@@ -2440,11 +2930,13 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
}
/**
- * lpfc_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
+ * lpfc_io_resume: Resume PCI I/O operation.
+ * @pdev: pointer to PCI device
*
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation.
+ * This routine is registered to the PCI subsystem for error handling. It is
+ * called when kernel error recovery tells the lpfc driver that it is ok to
+ * resume normal PCI operation after PCI bus error recovery. After this call,
+ * traffic can start to flow from this device again.
*/
static void lpfc_io_resume(struct pci_dev *pdev)
{
@@ -2491,6 +2983,8 @@ static struct pci_device_id lpfc_id_table[] = {
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_HORNET,
+ 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,
@@ -2521,6 +3015,12 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_VF,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_PF,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_S,
+ PCI_ANY_ID, PCI_ANY_ID, },
{ 0 }
};
@@ -2540,6 +3040,18 @@ static struct pci_driver lpfc_driver = {
.err_handler = &lpfc_err_handler,
};
+/**
+ * lpfc_init: lpfc module initialization routine.
+ *
+ * This routine is to be invoked when the lpfc module is loaded into the
+ * kernel. The special kernel macro module_init() is used to indicate the
+ * role of this routine to the kernel as lpfc module entry point.
+ *
+ * Return codes
+ * 0 - successful
+ * -ENOMEM - FC attach transport failed
+ * all others - failed
+ */
static int __init
lpfc_init(void)
{
@@ -2567,12 +3079,20 @@ lpfc_init(void)
error = pci_register_driver(&lpfc_driver);
if (error) {
fc_release_transport(lpfc_transport_template);
- fc_release_transport(lpfc_vport_transport_template);
+ if (lpfc_enable_npiv)
+ fc_release_transport(lpfc_vport_transport_template);
}
return error;
}
+/**
+ * lpfc_exit: lpfc module removal routine.
+ *
+ * This routine is invoked when the lpfc module is removed from the kernel.
+ * The special kernel macro module_exit() is used to indicate the role of
+ * this routine to the kernel as lpfc module exit point.
+ */
static void __exit
lpfc_exit(void)
{
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 7a9be4c5b7c..7465fe746fe 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2007 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -30,6 +30,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -37,10 +38,20 @@
#include "lpfc_crtn.h"
#include "lpfc_compat.h"
-/**********************************************/
-
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_dump_mem: Prepare a mailbox command for retrieving HBA's VPD memory.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @offset: offset for dumping VPD memory mailbox command.
+ *
+ * The dump mailbox command provides a method for the device driver to obtain
+ * various types of information from the HBA device.
+ *
+ * This routine prepares the mailbox command for dumping HBA Vital Product
+ * Data (VPD) memory. This mailbox command is to be used for retrieving a
+ * portion (DMP_RSP_SIZE bytes) of a HBA's VPD from the HBA at an address
+ * offset specified by the offset parameter.
+ **/
void
lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
{
@@ -65,10 +76,17 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
return;
}
-/**********************************************/
-/* lpfc_read_nv Issue a READ NVPARAM */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The read NVRAM mailbox command returns the HBA's non-volatile parameters
+ * that are used as defaults when the Fibre Channel link is brought on-line.
+ *
+ * This routine prepares the mailbox command for reading information stored
+ * in the HBA's NVRAM. Specifically, the HBA's WWNN and WWPN.
+ **/
void
lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -81,10 +99,19 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/**********************************************/
-/* lpfc_config_async Issue a */
-/* MBX_ASYNC_EVT_ENABLE mailbox command */
-/**********************************************/
+/**
+ * lpfc_config_async: Prepare a mailbox command for enabling HBA async event.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @ring: ring number for the asynchronous event to be configured.
+ *
+ * The asynchronous event enable mailbox command is used to enable the
+ * asynchronous event posting via the ASYNC_STATUS_CN IOCB response and
+ * specifies the default ring to which events are posted.
+ *
+ * This routine prepares the mailbox command for enabling HBA asynchronous
+ * event support on a IOCB ring.
+ **/
void
lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
uint32_t ring)
@@ -99,10 +126,19 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
return;
}
-/**********************************************/
-/* lpfc_heart_beat Issue a HEART_BEAT */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_heart_beat: Prepare a mailbox command for heart beat.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The heart beat mailbox command is used to detect an unresponsive HBA, which
+ * is defined as any device where no error attention is sent and both mailbox
+ * and rings are not processed.
+ *
+ * This routine prepares the mailbox command for issuing a heart beat in the
+ * form of mailbox command to the HBA. The timely completion of the heart
+ * beat mailbox command indicates the health of the HBA.
+ **/
void
lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -115,10 +151,26 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/**********************************************/
-/* lpfc_read_la Issue a READ LA */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_read_la: Prepare a mailbox command for reading HBA link attention.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @mp: DMA buffer memory for reading the link attention information into.
+ *
+ * The read link attention mailbox command is issued to read the Link Event
+ * Attention information indicated by the HBA port when the Link Event bit
+ * of the Host Attention (HSTATT) register is set to 1. A Link Event
+ * Attention occurs based on an exception detected at the Fibre Channel link
+ * interface.
+ *
+ * This routine prepares the mailbox command for reading HBA link attention
+ * information. A DMA memory has been set aside and address passed to the
+ * HBA through @mp for the HBA to DMA link attention information into the
+ * memory as part of the execution of the mailbox command.
+ *
+ * Return codes
+ * 0 - Success (currently always return 0)
+ **/
int
lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
{
@@ -143,10 +195,21 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
return (0);
}
-/**********************************************/
-/* lpfc_clear_la Issue a CLEAR LA */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_clear_la: Prepare a mailbox command for clearing HBA link attention.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The clear link attention mailbox command is issued to clear the link event
+ * attention condition indicated by the Link Event bit of the Host Attention
+ * (HSTATT) register. The link event attention condition is cleared only if
+ * the event tag specified matches that of the current link event counter.
+ * The current event tag is read using the read link attention event mailbox
+ * command.
+ *
+ * This routine prepares the mailbox command for clearing HBA link attention
+ * information.
+ **/
void
lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -161,10 +224,20 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/**************************************************/
-/* lpfc_config_link Issue a CONFIG LINK */
-/* mailbox command */
-/**************************************************/
+/**
+ * lpfc_config_link: Prepare a mailbox command for configuring link on a HBA.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The configure link mailbox command is used before the initialize link
+ * mailbox command to override default value and to configure link-oriented
+ * parameters such as DID address and various timers. Typically, this
+ * command would be used after an F_Port login to set the returned DID address
+ * and the fabric timeout values. This command is not valid before a configure
+ * port command has configured the HBA port.
+ *
+ * This routine prepares the mailbox command for configuring link on a HBA.
+ **/
void
lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -199,10 +272,98 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/**********************************************/
-/* lpfc_init_link Issue an INIT LINK */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_config_msi: Prepare a mailbox command for configuring msi-x.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The configure MSI-X mailbox command is used to configure the HBA's SLI-3
+ * MSI-X multi-message interrupt vector association to interrupt attention
+ * conditions.
+ *
+ * Return codes
+ * 0 - Success
+ * -EINVAL - Failure
+ **/
+int
+lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+ MAILBOX_t *mb = &pmb->mb;
+ uint32_t attentionConditions[2];
+
+ /* Sanity check */
+ if (phba->cfg_use_msi != 2) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0475 Not configured for supporting MSI-X "
+ "cfg_use_msi: 0x%x\n", phba->cfg_use_msi);
+ return -EINVAL;
+ }
+
+ if (phba->sli_rev < 3) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0476 HBA not supporting SLI-3 or later "
+ "SLI Revision: 0x%x\n", phba->sli_rev);
+ return -EINVAL;
+ }
+
+ /* Clear mailbox command fields */
+ memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
+
+ /*
+ * SLI-3, Message Signaled Interrupt Fearure.
+ */
+
+ /* Multi-message attention configuration */
+ attentionConditions[0] = (HA_R0ATT | HA_R1ATT | HA_R2ATT | HA_ERATT |
+ HA_LATT | HA_MBATT);
+ attentionConditions[1] = 0;
+
+ mb->un.varCfgMSI.attentionConditions[0] = attentionConditions[0];
+ mb->un.varCfgMSI.attentionConditions[1] = attentionConditions[1];
+
+ /*
+ * Set up message number to HA bit association
+ */
+#ifdef __BIG_ENDIAN_BITFIELD
+ /* RA0 (FCP Ring) */
+ mb->un.varCfgMSI.messageNumberByHA[HA_R0_POS] = 1;
+ /* RA1 (Other Protocol Extra Ring) */
+ mb->un.varCfgMSI.messageNumberByHA[HA_R1_POS] = 1;
+#else /* __LITTLE_ENDIAN_BITFIELD */
+ /* RA0 (FCP Ring) */
+ mb->un.varCfgMSI.messageNumberByHA[HA_R0_POS^3] = 1;
+ /* RA1 (Other Protocol Extra Ring) */
+ mb->un.varCfgMSI.messageNumberByHA[HA_R1_POS^3] = 1;
+#endif
+ /* Multi-message interrupt autoclear configuration*/
+ mb->un.varCfgMSI.autoClearHA[0] = attentionConditions[0];
+ mb->un.varCfgMSI.autoClearHA[1] = attentionConditions[1];
+
+ /* For now, HBA autoclear does not work reliably, disable it */
+ mb->un.varCfgMSI.autoClearHA[0] = 0;
+ mb->un.varCfgMSI.autoClearHA[1] = 0;
+
+ /* Set command and owner bit */
+ mb->mbxCommand = MBX_CONFIG_MSI;
+ mb->mbxOwner = OWN_HOST;
+
+ return 0;
+}
+
+/**
+ * lpfc_init_link: Prepare a mailbox command for initialize link on a HBA.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @topology: the link topology for the link to be initialized to.
+ * @linkspeed: the link speed for the link to be initialized to.
+ *
+ * The initialize link mailbox command is used to initialize the Fibre
+ * Channel link. This command must follow a configure port command that
+ * establishes the mode of operation.
+ *
+ * This routine prepares the mailbox command for initializing link on a HBA
+ * with the specified link topology and speed.
+ **/
void
lpfc_init_link(struct lpfc_hba * phba,
LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
@@ -269,10 +430,27 @@ lpfc_init_link(struct lpfc_hba * phba,
return;
}
-/**********************************************/
-/* lpfc_read_sparam Issue a READ SPARAM */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_read_sparam: Prepare a mailbox command for reading HBA parameters.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @vpi: virtual N_Port identifier.
+ *
+ * The read service parameter mailbox command is used to read the HBA port
+ * service parameters. The service parameters are read into the buffer
+ * specified directly by a BDE in the mailbox command. These service
+ * parameters may then be used to build the payload of an N_Port/F_POrt
+ * login request and reply (LOGI/ACC).
+ *
+ * This routine prepares the mailbox command for reading HBA port service
+ * parameters. The DMA memory is allocated in this function and the addresses
+ * are populated into the mailbox command for the HBA to DMA the service
+ * parameters into.
+ *
+ * Return codes
+ * 0 - Success
+ * 1 - DMA memory allocation failed
+ **/
int
lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
{
@@ -312,10 +490,21 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
return (0);
}
-/********************************************/
-/* lpfc_unreg_did Issue a UNREG_DID */
-/* mailbox command */
-/********************************************/
+/**
+ * lpfc_unreg_did: Prepare a mailbox command for unregistering DID.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: virtual N_Port identifier.
+ * @did: remote port identifier.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The unregister DID mailbox command is used to unregister an N_Port/F_Port
+ * login for an unknown RPI by specifying the DID of a remote port. This
+ * command frees an RPI context in the HBA port. This has the effect of
+ * performing an implicit N_Port/F_Port logout.
+ *
+ * This routine prepares the mailbox command for unregistering a remote
+ * N_Port/F_Port (DID) login.
+ **/
void
lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
LPFC_MBOXQ_t * pmb)
@@ -333,10 +522,19 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
return;
}
-/**********************************************/
-/* lpfc_read_nv Issue a READ CONFIG */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_read_config: Prepare a mailbox command for reading HBA configuration.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The read configuration mailbox command is used to read the HBA port
+ * configuration parameters. This mailbox command provides a method for
+ * seeing any parameters that may have changed via various configuration
+ * mailbox commands.
+ *
+ * This routine prepares the mailbox command for reading out HBA configuration
+ * parameters.
+ **/
void
lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -350,10 +548,18 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/*************************************************/
-/* lpfc_read_lnk_stat Issue a READ LINK STATUS */
-/* mailbox command */
-/*************************************************/
+/**
+ * lpfc_read_lnk_stat: Prepare a mailbox command for reading HBA link stats.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The read link status mailbox command is used to read the link status from
+ * the HBA. Link status includes all link-related error counters. These
+ * counters are maintained by the HBA and originated in the link hardware
+ * unit. Note that all of these counters wrap.
+ *
+ * This routine prepares the mailbox command for reading out HBA link status.
+ **/
void
lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -367,10 +573,30 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
-/********************************************/
-/* lpfc_reg_login Issue a REG_LOGIN */
-/* mailbox command */
-/********************************************/
+/**
+ * lpfc_reg_login: Prepare a mailbox command for registering remote login.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: virtual N_Port identifier.
+ * @did: remote port identifier.
+ * @param: pointer to memory holding the server parameters.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * @flag: action flag to be passed back for the complete function.
+ *
+ * The registration login mailbox command is used to register an N_Port or
+ * F_Port login. This registration allows the HBA to cache the remote N_Port
+ * service parameters internally and thereby make the appropriate FC-2
+ * decisions. The remote port service parameters are handed off by the driver
+ * to the HBA using a descriptor entry that directly identifies a buffer in
+ * host memory. In exchange, the HBA returns an RPI identifier.
+ *
+ * This routine prepares the mailbox command for registering remote port login.
+ * The function allocates DMA buffer for passing the service parameters to the
+ * HBA with the mailbox command.
+ *
+ * Return codes
+ * 0 - Success
+ * 1 - DMA memory allocation failed
+ **/
int
lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
@@ -418,10 +644,20 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
return (0);
}
-/**********************************************/
-/* lpfc_unreg_login Issue a UNREG_LOGIN */
-/* mailbox command */
-/**********************************************/
+/**
+ * lpfc_unreg_login: Prepare a mailbox command for unregistering remote login.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: virtual N_Port identifier.
+ * @rpi: remote port identifier
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The unregistration login mailbox command is used to unregister an N_Port
+ * or F_Port login. This command frees an RPI context in the HBA. It has the
+ * effect of performing an implicit N_Port/F_Port logout.
+ *
+ * This routine prepares the mailbox command for unregistering remote port
+ * login.
+ **/
void
lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
LPFC_MBOXQ_t * pmb)
@@ -440,10 +676,21 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
return;
}
-/**************************************************/
-/* lpfc_reg_vpi Issue a REG_VPI */
-/* mailbox command */
-/**************************************************/
+/**
+ * lpfc_reg_vpi: Prepare a mailbox command for registering vport identifier.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: virtual N_Port identifier.
+ * @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port).
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The registration vport identifier mailbox command is used to activate a
+ * virtual N_Port after it has acquired an N_Port_ID. The HBA validates the
+ * N_Port_ID against the information in the selected virtual N_Port context
+ * block and marks it active to allow normal processing of IOCB commands and
+ * received unsolicited exchanges.
+ *
+ * This routine prepares the mailbox command for registering a virtual N_Port.
+ **/
void
lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
LPFC_MBOXQ_t *pmb)
@@ -461,10 +708,22 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
}
-/**************************************************/
-/* lpfc_unreg_vpi Issue a UNREG_VNPI */
-/* mailbox command */
-/**************************************************/
+/**
+ * lpfc_unreg_vpi: Prepare a mailbox command for unregistering vport id.
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: virtual N_Port identifier.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The unregistration vport identifier mailbox command is used to inactivate
+ * a virtual N_Port. The driver must have logged out and unregistered all
+ * remote N_Ports to abort any activity on the virtual N_Port. The HBA will
+ * unregisters any default RPIs associated with the specified vpi, aborting
+ * any active exchanges. The HBA will post the mailbox response after making
+ * the virtual N_Port inactive.
+ *
+ * This routine prepares the mailbox command for unregistering a virtual
+ * N_Port.
+ **/
void
lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
{
@@ -479,12 +738,19 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
}
+/**
+ * lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB)
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine sets up and initializes the IOCB rings in the Port Control
+ * Block (PCB).
+ **/
static void
lpfc_config_pcb_setup(struct lpfc_hba * phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
- PCB_t *pcbp = &phba->slim2p->pcb;
+ PCB_t *pcbp = phba->pcb;
dma_addr_t pdma_addr;
uint32_t offset;
uint32_t iocbCnt = 0;
@@ -513,29 +779,43 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
continue;
}
/* Command ring setup for ring */
- pring->cmdringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
+ pring->cmdringaddr = (void *)&phba->IOCBs[iocbCnt];
pcbp->rdsc[i].cmdEntries = pring->numCiocb;
- offset = (uint8_t *) &phba->slim2p->IOCBs[iocbCnt] -
- (uint8_t *) phba->slim2p;
- pdma_addr = phba->slim2p_mapping + offset;
+ offset = (uint8_t *) &phba->IOCBs[iocbCnt] -
+ (uint8_t *) phba->slim2p.virt;
+ pdma_addr = phba->slim2p.phys + offset;
pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
iocbCnt += pring->numCiocb;
/* Response ring setup for ring */
- pring->rspringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
+ pring->rspringaddr = (void *) &phba->IOCBs[iocbCnt];
pcbp->rdsc[i].rspEntries = pring->numRiocb;
- offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
- (uint8_t *)phba->slim2p;
- pdma_addr = phba->slim2p_mapping + offset;
+ offset = (uint8_t *)&phba->IOCBs[iocbCnt] -
+ (uint8_t *)phba->slim2p.virt;
+ pdma_addr = phba->slim2p.phys + offset;
pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr);
pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr);
iocbCnt += pring->numRiocb;
}
}
+/**
+ * lpfc_read_rev: Prepare a mailbox command for reading HBA revision.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The read revision mailbox command is used to read the revision levels of
+ * the HBA components. These components include hardware units, resident
+ * firmware, and available firmware. HBAs that supports SLI-3 mode of
+ * operation provide different response information depending on the version
+ * requested by the driver.
+ *
+ * This routine prepares the mailbox command for reading HBA revision
+ * information.
+ **/
void
lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -548,6 +828,16 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
+/**
+ * lpfc_build_hbq_profile2: Set up the HBQ Selection Profile 2.
+ * @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
+ * @hbq_desc: pointer to the HBQ selection profile descriptor.
+ *
+ * The Host Buffer Queue (HBQ) Selection Profile 2 specifies that the HBA
+ * tests the incoming frames' R_CTL/TYPE fields with works 10:15 and performs
+ * the Sequence Length Test using the fields in the Selection Profile 2
+ * extension in words 20:31.
+ **/
static void
lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
@@ -557,6 +847,16 @@ lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff;
}
+/**
+ * lpfc_build_hbq_profile3: Set up the HBQ Selection Profile 3.
+ * @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
+ * @hbq_desc: pointer to the HBQ selection profile descriptor.
+ *
+ * The Host Buffer Queue (HBQ) Selection Profile 3 specifies that the HBA
+ * tests the incoming frame's R_CTL/TYPE fields with words 10:15 and performs
+ * the Sequence Length Test and Byte Field Test using the fields in the
+ * Selection Profile 3 extension in words 20:31.
+ **/
static void
lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
@@ -569,6 +869,17 @@ lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
sizeof(hbqmb->profiles.profile3.cmdmatch));
}
+/**
+ * lpfc_build_hbq_profile5: Set up the HBQ Selection Profile 5.
+ * @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
+ * @hbq_desc: pointer to the HBQ selection profile descriptor.
+ *
+ * The Host Buffer Queue (HBQ) Selection Profile 5 specifies a header HBQ. The
+ * HBA tests the initial frame of an incoming sequence using the frame's
+ * R_CTL/TYPE fields with words 10:15 and performs the Sequence Length Test
+ * and Byte Field Test using the fields in the Selection Profile 5 extension
+ * words 20:31.
+ **/
static void
lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
@@ -581,6 +892,20 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
sizeof(hbqmb->profiles.profile5.cmdmatch));
}
+/**
+ * lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ.
+ * @phba: pointer to lpfc hba data structure.
+ * @id: HBQ identifier.
+ * @hbq_desc: pointer to the HBA descriptor data structure.
+ * @hbq_entry_index: index of the HBQ entry data structures.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The configure HBQ (Host Buffer Queue) mailbox command is used to configure
+ * an HBQ. The configuration binds events that require buffers to a particular
+ * ring and HBQ based on a selection profile.
+ *
+ * This routine prepares the mailbox command for configuring an HBQ.
+ **/
void
lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
struct lpfc_hbq_init *hbq_desc,
@@ -641,8 +966,23 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
return;
}
-
-
+/**
+ * lpfc_config_ring: Prepare a mailbox command for configuring an IOCB ring.
+ * @phba: pointer to lpfc hba data structure.
+ * @ring:
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The configure ring mailbox command is used to configure an IOCB ring. This
+ * configuration binds from one to six of HBA RC_CTL/TYPE mask entries to the
+ * ring. This is used to map incoming sequences to a particular ring whose
+ * RC_CTL/TYPE mask entry matches that of the sequence. The driver should not
+ * attempt to configure a ring whose number is greater than the number
+ * specified in the Port Control Block (PCB). It is an error to issue the
+ * configure ring command more than once with the same ring number. The HBA
+ * returns an error if the driver attempts this.
+ *
+ * This routine prepares the mailbox command for configuring IOCB ring.
+ **/
void
lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
{
@@ -684,6 +1024,20 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
return;
}
+/**
+ * lpfc_config_port: Prepare a mailbox command for configuring port.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The configure port mailbox command is used to identify the Port Control
+ * Block (PCB) in the driver memory. After this command is issued, the
+ * driver must not access the mailbox in the HBA without first resetting
+ * the HBA. The HBA may copy the PCB information to internal storage for
+ * subsequent use; the driver can not change the PCB information unless it
+ * resets the HBA.
+ *
+ * This routine prepares the mailbox command for configuring port.
+ **/
void
lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
@@ -702,8 +1056,8 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
mb->un.varCfgPort.pcbLen = sizeof(PCB_t);
- offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p;
- pdma_addr = phba->slim2p_mapping + offset;
+ offset = (uint8_t *)phba->pcb - (uint8_t *)phba->slim2p.virt;
+ pdma_addr = phba->slim2p.phys + offset;
mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
@@ -711,12 +1065,13 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
+ mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */
+ mb->un.varCfgPort.cinb = 1; /* Interrupt Notification Block */
mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
if (phba->max_vpi && phba->cfg_enable_npiv &&
phba->vpd.sli3Feat.cmv) {
mb->un.varCfgPort.max_vpi = phba->max_vpi;
mb->un.varCfgPort.cmv = 1;
- phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
} else
mb->un.varCfgPort.max_vpi = phba->max_vpi = 0;
} else
@@ -724,16 +1079,15 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
mb->un.varCfgPort.sli_mode = phba->sli_rev;
/* Now setup pcb */
- phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
- phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
+ phba->pcb->type = TYPE_NATIVE_SLI2;
+ phba->pcb->feature = FEATURE_INITIAL_SLI2;
/* Setup Mailbox pointers */
- phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
- sizeof(struct sli2_desc);
- offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
- pdma_addr = phba->slim2p_mapping + offset;
- phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
- phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr);
+ phba->pcb->mailBoxSize = sizeof(MAILBOX_t);
+ offset = (uint8_t *)phba->mbox - (uint8_t *)phba->slim2p.virt;
+ pdma_addr = phba->slim2p.phys + offset;
+ phba->pcb->mbAddrHigh = putPaddrHigh(pdma_addr);
+ phba->pcb->mbAddrLow = putPaddrLow(pdma_addr);
/*
* Setup Host Group ring pointer.
@@ -794,13 +1148,13 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/* mask off BAR0's flag bits 0 - 3 */
- phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
- (void __iomem *) phba->host_gp -
+ phba->pcb->hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
+ (void __iomem *)phba->host_gp -
(void __iomem *)phba->MBslimaddr;
if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
- phba->slim2p->pcb.hgpAddrHigh = bar_high;
+ phba->pcb->hgpAddrHigh = bar_high;
else
- phba->slim2p->pcb.hgpAddrHigh = 0;
+ phba->pcb->hgpAddrHigh = 0;
/* write HGP data to SLIM at the required longword offset */
memset(&hgp, 0, sizeof(struct lpfc_hgp));
@@ -810,17 +1164,19 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/* Setup Port Group ring pointer */
- if (phba->sli_rev == 3)
- pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
- (uint8_t *)phba->slim2p;
- else
- pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
- (uint8_t *)phba->slim2p;
-
- pdma_addr = phba->slim2p_mapping + pgp_offset;
- phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
- phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
- phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
+ if (phba->sli3_options & LPFC_SLI3_INB_ENABLED) {
+ pgp_offset = offsetof(struct lpfc_sli2_slim,
+ mbx.us.s3_inb_pgp.port);
+ phba->hbq_get = phba->mbox->us.s3_inb_pgp.hbq_get;
+ } else if (phba->sli_rev == 3) {
+ pgp_offset = offsetof(struct lpfc_sli2_slim,
+ mbx.us.s3_pgp.port);
+ phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get;
+ } else
+ pgp_offset = offsetof(struct lpfc_sli2_slim, mbx.us.s2.port);
+ pdma_addr = phba->slim2p.phys + pgp_offset;
+ phba->pcb->pgpAddrHigh = putPaddrHigh(pdma_addr);
+ phba->pcb->pgpAddrLow = putPaddrLow(pdma_addr);
/* Use callback routine to setp rings in the pcb */
lpfc_config_pcb_setup(phba);
@@ -835,10 +1191,24 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
/* Swap PCB if needed */
- lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
- sizeof(PCB_t));
+ lpfc_sli_pcimem_bcopy(phba->pcb, phba->pcb, sizeof(PCB_t));
}
+/**
+ * lpfc_kill_board: Prepare a mailbox command for killing board.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ *
+ * The kill board mailbox command is used to tell firmware to perform a
+ * graceful shutdown of a channel on a specified board to prepare for reset.
+ * When the kill board mailbox command is received, the ER3 bit is set to 1
+ * in the Host Status register and the ER Attention bit is set to 1 in the
+ * Host Attention register of the HBA function that received the kill board
+ * command.
+ *
+ * This routine prepares the mailbox command for killing the board in
+ * preparation for a graceful shutdown.
+ **/
void
lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
@@ -850,6 +1220,16 @@ lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return;
}
+/**
+ * lpfc_mbox_put: Put a mailbox cmd into the tail of driver's mailbox queue.
+ * @phba: pointer to lpfc hba data structure.
+ * @mbq: pointer to the driver internal queue element for mailbox command.
+ *
+ * Driver maintains a internal mailbox command queue implemented as a linked
+ * list. When a mailbox command is issued, it shall be put into the mailbox
+ * command queue such that they shall be processed orderly as HBA can process
+ * one mailbox command at a time.
+ **/
void
lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{
@@ -864,6 +1244,20 @@ lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
return;
}
+/**
+ * lpfc_mbox_get: Remove a mailbox cmd from the head of driver's mailbox queue.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * Driver maintains a internal mailbox command queue implemented as a linked
+ * list. When a mailbox command is issued, it shall be put into the mailbox
+ * command queue such that they shall be processed orderly as HBA can process
+ * one mailbox command at a time. After HBA finished processing a mailbox
+ * command, the driver will remove a pending mailbox command from the head of
+ * the mailbox command queue and send to the HBA for processing.
+ *
+ * Return codes
+ * pointer to the driver internal queue element for mailbox command.
+ **/
LPFC_MBOXQ_t *
lpfc_mbox_get(struct lpfc_hba * phba)
{
@@ -877,6 +1271,17 @@ lpfc_mbox_get(struct lpfc_hba * phba)
return mbq;
}
+/**
+ * lpfc_mbox_cmpl_put: Put mailbox command into mailbox command complete list.
+ * @phba: pointer to lpfc hba data structure.
+ * @mbq: pointer to the driver internal queue element for mailbox command.
+ *
+ * This routine put the completed mailbox command into the mailbox command
+ * complete list. This routine is called from driver interrupt handler
+ * context.The mailbox complete list is used by the driver worker thread
+ * to process mailbox complete callback functions outside the driver interrupt
+ * handler.
+ **/
void
lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{
@@ -887,6 +1292,17 @@ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
return;
}
+/**
+ * lpfc_mbox_tmo_val: Retrieve mailbox command timeout value.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmd: mailbox command code.
+ *
+ * This routine retrieves the proper timeout value according to the mailbox
+ * command code.
+ *
+ * Return codes
+ * Timeout value to be used for the given mailbox command
+ **/
int
lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
{
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 3c0cebc7180..a4bba206924 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2006 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -30,6 +30,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -39,7 +40,21 @@
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
-
+/**
+ * lpfc_mem_alloc: create and allocate all PCI and memory pools
+ * @phba: HBA to allocate pools for
+ *
+ * Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
+ * lpfc_mbuf_pool, lpfc_hbq_pool. Creates and allocates kmalloc-backed mempools
+ * for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask.
+ *
+ * Notes: Not interrupt-safe. Must be called with no locks held. If any
+ * allocation fails, frees all successfully allocated memory before returning.
+ *
+ * Returns:
+ * 0 on success
+ * -ENOMEM on failure (if any memory allocations fail)
+ **/
int
lpfc_mem_alloc(struct lpfc_hba * phba)
{
@@ -120,6 +135,16 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
return -ENOMEM;
}
+/**
+ * lpfc_mem_free: Frees all PCI and memory allocated by lpfc_mem_alloc
+ * @phba: HBA to free memory for
+ *
+ * Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool,
+ * lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and
+ * lpfc_nodelist. Also frees the VPI bitmask.
+ *
+ * Returns: None
+ **/
void
lpfc_mem_free(struct lpfc_hba * phba)
{
@@ -181,12 +206,29 @@ lpfc_mem_free(struct lpfc_hba * phba)
phba->lpfc_scsi_dma_buf_pool = NULL;
phba->lpfc_mbuf_pool = NULL;
- /* Free the iocb lookup array */
+ /* Free the iocb lookup array */
kfree(psli->iocbq_lookup);
psli->iocbq_lookup = NULL;
-
}
+/**
+ * lpfc_mbuf_alloc: Allocate an mbuf from the lpfc_mbuf_pool PCI pool
+ * @phba: HBA which owns the pool to allocate from
+ * @mem_flags: indicates if this is a priority (MEM_PRI) allocation
+ * @handle: used to return the DMA-mapped address of the mbuf
+ *
+ * Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool.
+ * Allocates from generic pci_pool_alloc function first and if that fails and
+ * mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the
+ * HBA's pool.
+ *
+ * Notes: Not interrupt-safe. Must be called with no locks held. Takes
+ * phba->hbalock.
+ *
+ * Returns:
+ * pointer to the allocated mbuf on success
+ * NULL on failure
+ **/
void *
lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{
@@ -206,6 +248,20 @@ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
return ret;
}
+/**
+ * __lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
+ * @phba: HBA which owns the pool to return to
+ * @virt: mbuf to free
+ * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
+ *
+ * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
+ * it is below its max_count, frees the mbuf otherwise.
+ *
+ * Notes: Must be called with phba->hbalock held to synchronize access to
+ * lpfc_mbuf_safety_pool.
+ *
+ * Returns: None
+ **/
void
__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
@@ -221,7 +277,21 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
return;
}
+/**
+ * lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
+ * @phba: HBA which owns the pool to return to
+ * @virt: mbuf to free
+ * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
+ *
+ * Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
+ * it is below its max_count, frees the mbuf otherwise.
+ *
+ * Notes: Takes phba->hbalock. Can be called with or without other locks held.
+ *
+ * Returns: None
+ **/
void
+
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
unsigned long iflags;
@@ -232,6 +302,19 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
return;
}
+/**
+ * lpfc_els_hbq_alloc: Allocate an HBQ buffer
+ * @phba: HBA to allocate HBQ buffer for
+ *
+ * Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI
+ * pool along a non-DMA-mapped container for it.
+ *
+ * Notes: Not interrupt-safe. Must be called with no locks held.
+ *
+ * Returns:
+ * pointer to HBQ on success
+ * NULL on failure
+ **/
struct hbq_dmabuf *
lpfc_els_hbq_alloc(struct lpfc_hba *phba)
{
@@ -251,6 +334,18 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
return hbqbp;
}
+/**
+ * lpfc_mem_hbq_free: Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
+ * @phba: HBA buffer was allocated for
+ * @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
+ *
+ * Description: Frees both the container and the DMA-mapped buffer returned by
+ * lpfc_els_hbq_alloc.
+ *
+ * Notes: Can be called with or without locks held.
+ *
+ * Returns: None
+ **/
void
lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
{
@@ -259,7 +354,18 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
return;
}
-/* This is ONLY called for the LPFC_ELS_HBQ */
+/**
+ * lpfc_in_buf_free: Free a DMA buffer
+ * @phba: HBA buffer is associated with
+ * @mp: Buffer to free
+ *
+ * Description: Frees the given DMA buffer in the appropriate way given if the
+ * HBA is running in SLI3 mode with HBQs enabled.
+ *
+ * Notes: Takes phba->hbalock. Can be called with or without other locks held.
+ *
+ * Returns: None
+ **/
void
lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
{
diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h
new file mode 100644
index 00000000000..1accb5a9f4e
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_nl.h
@@ -0,0 +1,163 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for *
+ * Fibre Channel Host Bus Adapters. *
+ * Copyright (C) 2008 Emulex. All rights reserved. *
+ * EMULEX and SLI are trademarks of Emulex. *
+ * www.emulex.com *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of version 2 of the GNU General *
+ * Public License as published by the Free Software Foundation. *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID. See the GNU General Public License for *
+ * more details, a copy of which can be found in the file COPYING *
+ * included with this package. *
+ *******************************************************************/
+
+/* Event definitions for RegisterForEvent */
+#define FC_REG_LINK_EVENT 0x0001 /* link up / down events */
+#define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */
+#define FC_REG_CT_EVENT 0x0004 /* CT request events */
+#define FC_REG_DUMP_EVENT 0x0008 /* Dump events */
+#define FC_REG_TEMPERATURE_EVENT 0x0010 /* temperature events */
+#define FC_REG_ELS_EVENT 0x0020 /* lpfc els events */
+#define FC_REG_FABRIC_EVENT 0x0040 /* lpfc fabric events */
+#define FC_REG_SCSI_EVENT 0x0080 /* lpfc scsi events */
+#define FC_REG_BOARD_EVENT 0x0100 /* lpfc board events */
+#define FC_REG_ADAPTER_EVENT 0x0200 /* lpfc adapter events */
+#define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \
+ FC_REG_RSCN_EVENT | \
+ FC_REG_CT_EVENT | \
+ FC_REG_DUMP_EVENT | \
+ FC_REG_TEMPERATURE_EVENT | \
+ FC_REG_ELS_EVENT | \
+ FC_REG_FABRIC_EVENT | \
+ FC_REG_SCSI_EVENT | \
+ FC_REG_BOARD_EVENT | \
+ FC_REG_ADAPTER_EVENT)
+/* Temperature events */
+#define LPFC_CRIT_TEMP 0x1
+#define LPFC_THRESHOLD_TEMP 0x2
+#define LPFC_NORMAL_TEMP 0x3
+/*
+ * All net link event payloads will begin with and event type
+ * and subcategory. The event type must come first.
+ * The subcategory further defines the data that follows in the rest
+ * of the payload. Each category will have its own unique header plus
+ * any addtional data unique to the subcategory.
+ * The payload sent via the fc transport is one-way driver->application.
+ */
+
+/* els event header */
+struct lpfc_els_event_header {
+ uint32_t event_type;
+ uint32_t subcategory;
+ uint8_t wwpn[8];
+ uint8_t wwnn[8];
+};
+
+/* subcategory codes for FC_REG_ELS_EVENT */
+#define LPFC_EVENT_PLOGI_RCV 0x01
+#define LPFC_EVENT_PRLO_RCV 0x02
+#define LPFC_EVENT_ADISC_RCV 0x04
+#define LPFC_EVENT_LSRJT_RCV 0x08
+
+/* special els lsrjt event */
+struct lpfc_lsrjt_event {
+ struct lpfc_els_event_header header;
+ uint32_t command;
+ uint32_t reason_code;
+ uint32_t explanation;
+};
+
+
+/* fabric event header */
+struct lpfc_fabric_event_header {
+ uint32_t event_type;
+ uint32_t subcategory;
+ uint8_t wwpn[8];
+ uint8_t wwnn[8];
+};
+
+/* subcategory codes for FC_REG_FABRIC_EVENT */
+#define LPFC_EVENT_FABRIC_BUSY 0x01
+#define LPFC_EVENT_PORT_BUSY 0x02
+#define LPFC_EVENT_FCPRDCHKERR 0x04
+
+/* special case fabric fcprdchkerr event */
+struct lpfc_fcprdchkerr_event {
+ struct lpfc_fabric_event_header header;
+ uint32_t lun;
+ uint32_t opcode;
+ uint32_t fcpiparam;
+};
+
+
+/* scsi event header */
+struct lpfc_scsi_event_header {
+ uint32_t event_type;
+ uint32_t subcategory;
+ uint32_t lun;
+ uint8_t wwpn[8];
+ uint8_t wwnn[8];
+};
+
+/* subcategory codes for FC_REG_SCSI_EVENT */
+#define LPFC_EVENT_QFULL 0x0001
+#define LPFC_EVENT_DEVBSY 0x0002
+#define LPFC_EVENT_CHECK_COND 0x0004
+#define LPFC_EVENT_LUNRESET 0x0008
+#define LPFC_EVENT_TGTRESET 0x0010
+#define LPFC_EVENT_BUSRESET 0x0020
+#define LPFC_EVENT_VARQUEDEPTH 0x0040
+
+/* special case scsi varqueuedepth event */
+struct lpfc_scsi_varqueuedepth_event {
+ struct lpfc_scsi_event_header scsi_event;
+ uint32_t oldval;
+ uint32_t newval;
+};
+
+/* special case scsi check condition event */
+struct lpfc_scsi_check_condition_event {
+ struct lpfc_scsi_event_header scsi_event;
+ uint8_t sense_key;
+ uint8_t asc;
+ uint8_t ascq;
+};
+
+/* event codes for FC_REG_BOARD_EVENT */
+#define LPFC_EVENT_PORTINTERR 0x01
+
+/* board event header */
+struct lpfc_board_event_header {
+ uint32_t event_type;
+ uint32_t subcategory;
+};
+
+
+/* event codes for FC_REG_ADAPTER_EVENT */
+#define LPFC_EVENT_ARRIVAL 0x01
+
+/* adapter event header */
+struct lpfc_adapter_event_header {
+ uint32_t event_type;
+ uint32_t subcategory;
+};
+
+
+/* event codes for temp_event */
+#define LPFC_CRIT_TEMP 0x1
+#define LPFC_THRESHOLD_TEMP 0x2
+#define LPFC_NORMAL_TEMP 0x3
+
+struct temp_event {
+ uint32_t event_type;
+ uint32_t event_code;
+ uint32_t data;
+};
+
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 6688a8689b5..0c25d97acb4 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -30,6 +30,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -1003,20 +1004,8 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
-
- if (vport->num_disc_nodes) {
+ if (vport->num_disc_nodes)
lpfc_more_adisc(vport);
- if ((vport->num_disc_nodes == 0) &&
- (vport->fc_npr_cnt))
- lpfc_els_disc_plogi(vport);
- if (vport->num_disc_nodes == 0) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_NDISC_ACTIVE;
- spin_unlock_irq(shost->host_lock);
- lpfc_can_disctmo(vport);
- lpfc_end_rscn(vport);
- }
- }
}
return ndlp->nlp_state;
}
@@ -1865,8 +1854,13 @@ static uint32_t
lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ if (ndlp->nlp_DID == Fabric_DID) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+ spin_unlock_irq(shost->host_lock);
+ }
lpfc_unreg_rpi(vport, ndlp);
- /* This routine does nothing, just return the current state */
return ndlp->nlp_state;
}
@@ -2155,7 +2149,7 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_nlp_put(ndlp);
} else {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "0212 DSM out state %d on NPort free\n", rc);
+ "0213 DSM out state %d on NPort free\n", rc);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
"DSM out: ste:%d did:x%x flg:x%x",
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 1bcebbd3dfa..bd186741182 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -32,6 +32,7 @@
#include "lpfc_version.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -42,6 +43,111 @@
#define LPFC_RESET_WAIT 2
#define LPFC_ABORT_WAIT 2
+/**
+ * lpfc_update_stats: Update statistical data for the command completion.
+ * @phba: Pointer to HBA object.
+ * @lpfc_cmd: lpfc scsi command object pointer.
+ *
+ * This function is called when there is a command completion and this
+ * function updates the statistical data for the command completion.
+ **/
+static void
+lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
+{
+ struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
+ struct lpfc_nodelist *pnode = rdata->pnode;
+ struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+ unsigned long flags;
+ struct Scsi_Host *shost = cmd->device->host;
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ unsigned long latency;
+ int i;
+
+ if (cmd->result)
+ return;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (!vport->stat_data_enabled ||
+ vport->stat_data_blocked ||
+ !pnode->lat_data ||
+ (phba->bucket_type == LPFC_NO_BUCKET)) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ return;
+ }
+ latency = jiffies_to_msecs(jiffies - lpfc_cmd->start_time);
+
+ if (phba->bucket_type == LPFC_LINEAR_BUCKET) {
+ i = (latency + phba->bucket_step - 1 - phba->bucket_base)/
+ phba->bucket_step;
+ if (i >= LPFC_MAX_BUCKET_COUNT)
+ i = LPFC_MAX_BUCKET_COUNT;
+ } else {
+ for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++)
+ if (latency <= (phba->bucket_base +
+ ((1<<i)*phba->bucket_step)))
+ break;
+ }
+
+ pnode->lat_data[i].cmd_count++;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+
+/**
+ * lpfc_send_sdev_queuedepth_change_event: Posts a queuedepth change
+ * event.
+ * @phba: Pointer to HBA context object.
+ * @vport: Pointer to vport object.
+ * @ndlp: Pointer to FC node associated with the target.
+ * @lun: Lun number of the scsi device.
+ * @old_val: Old value of the queue depth.
+ * @new_val: New value of the queue depth.
+ *
+ * This function sends an event to the mgmt application indicating
+ * there is a change in the scsi device queue depth.
+ **/
+static void
+lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
+ struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp,
+ uint32_t lun,
+ uint32_t old_val,
+ uint32_t new_val)
+{
+ struct lpfc_fast_path_event *fast_path_evt;
+ unsigned long flags;
+
+ fast_path_evt = lpfc_alloc_fast_evt(phba);
+ if (!fast_path_evt)
+ return;
+
+ fast_path_evt->un.queue_depth_evt.scsi_event.event_type =
+ FC_REG_SCSI_EVENT;
+ fast_path_evt->un.queue_depth_evt.scsi_event.subcategory =
+ LPFC_EVENT_VARQUEDEPTH;
+
+ /* Report all luns with change in queue depth */
+ fast_path_evt->un.queue_depth_evt.scsi_event.lun = lun;
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwpn,
+ &ndlp->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwnn,
+ &ndlp->nlp_nodename, sizeof(struct lpfc_name));
+ }
+
+ fast_path_evt->un.queue_depth_evt.oldval = old_val;
+ fast_path_evt->un.queue_depth_evt.newval = new_val;
+ fast_path_evt->vport = vport;
+
+ fast_path_evt->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
+ spin_lock_irqsave(&phba->hbalock, flags);
+ list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ lpfc_worker_wake_up(phba);
+
+ return;
+}
+
/*
* This function is called with no lock held when there is a resource
* error in driver or in firmware.
@@ -117,9 +223,10 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
struct lpfc_vport **vports;
struct Scsi_Host *shost;
struct scsi_device *sdev;
- unsigned long new_queue_depth;
+ unsigned long new_queue_depth, old_queue_depth;
unsigned long num_rsrc_err, num_cmd_success;
int i;
+ struct lpfc_rport_data *rdata;
num_rsrc_err = atomic_read(&phba->num_rsrc_err);
num_cmd_success = atomic_read(&phba->num_cmd_success);
@@ -137,6 +244,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
else
new_queue_depth = sdev->queue_depth -
new_queue_depth;
+ old_queue_depth = sdev->queue_depth;
if (sdev->ordered_tags)
scsi_adjust_queue_depth(sdev,
MSG_ORDERED_TAG,
@@ -145,6 +253,13 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
scsi_adjust_queue_depth(sdev,
MSG_SIMPLE_TAG,
new_queue_depth);
+ rdata = sdev->hostdata;
+ if (rdata)
+ lpfc_send_sdev_queuedepth_change_event(
+ phba, vports[i],
+ rdata->pnode,
+ sdev->lun, old_queue_depth,
+ new_queue_depth);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -159,6 +274,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
struct Scsi_Host *shost;
struct scsi_device *sdev;
int i;
+ struct lpfc_rport_data *rdata;
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
@@ -176,6 +292,14 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
scsi_adjust_queue_depth(sdev,
MSG_SIMPLE_TAG,
sdev->queue_depth+1);
+ rdata = sdev->hostdata;
+ if (rdata)
+ lpfc_send_sdev_queuedepth_change_event(
+ phba, vports[i],
+ rdata->pnode,
+ sdev->lun,
+ sdev->queue_depth - 1,
+ sdev->queue_depth);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -183,6 +307,35 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
atomic_set(&phba->num_cmd_success, 0);
}
+/**
+ * lpfc_scsi_dev_block: set all scsi hosts to block state.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function walks vport list and set each SCSI host to block state
+ * by invoking fc_remote_port_delete() routine. This function is invoked
+ * with EEH when device's PCI slot has been permanently disabled.
+ **/
+void
+lpfc_scsi_dev_block(struct lpfc_hba *phba)
+{
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
+ struct scsi_device *sdev;
+ struct fc_rport *rport;
+ int i;
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+ for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ shost_for_each_device(sdev, shost) {
+ rport = starget_to_rport(scsi_target(sdev));
+ fc_remote_port_delete(rport);
+ }
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+}
+
/*
* This routine allocates a scsi buffer, which contains all the necessary
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
@@ -198,7 +351,9 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
struct lpfc_scsi_buf *psb;
struct ulp_bde64 *bpl;
IOCB_t *iocb;
- dma_addr_t pdma_phys;
+ dma_addr_t pdma_phys_fcp_cmd;
+ dma_addr_t pdma_phys_fcp_rsp;
+ dma_addr_t pdma_phys_bpl;
uint16_t iotag;
psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
@@ -238,40 +393,60 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
/* Initialize local short-hand pointers. */
bpl = psb->fcp_bpl;
- pdma_phys = psb->dma_handle;
+ pdma_phys_fcp_cmd = psb->dma_handle;
+ pdma_phys_fcp_rsp = psb->dma_handle + sizeof(struct fcp_cmnd);
+ pdma_phys_bpl = psb->dma_handle + sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp);
/*
* The first two bdes are the FCP_CMD and FCP_RSP. The balance are sg
* list bdes. Initialize the first two and leave the rest for
* queuecommand.
*/
- bpl->addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys));
- bpl->addrLow = le32_to_cpu(putPaddrLow(pdma_phys));
- bpl->tus.f.bdeSize = sizeof (struct fcp_cmnd);
- bpl->tus.f.bdeFlags = BUFF_USE_CMND;
- bpl->tus.w = le32_to_cpu(bpl->tus.w);
- bpl++;
+ bpl[0].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_cmd));
+ bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd));
+ bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd);
+ bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ bpl[0].tus.w = le32_to_cpu(bpl->tus.w);
/* Setup the physical region for the FCP RSP */
- pdma_phys += sizeof (struct fcp_cmnd);
- bpl->addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys));
- bpl->addrLow = le32_to_cpu(putPaddrLow(pdma_phys));
- bpl->tus.f.bdeSize = sizeof (struct fcp_rsp);
- bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV);
- bpl->tus.w = le32_to_cpu(bpl->tus.w);
+ bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp));
+ bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp));
+ bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp);
+ bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ bpl[1].tus.w = le32_to_cpu(bpl->tus.w);
/*
* Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf,
* initialize it with all known data now.
*/
- pdma_phys += (sizeof (struct fcp_rsp));
iocb = &psb->cur_iocbq.iocb;
iocb->un.fcpi64.bdl.ulpIoTag32 = 0;
- iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys);
- iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys);
- iocb->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
- iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL;
- iocb->ulpBdeCount = 1;
+ if (phba->sli_rev == 3) {
+ /* fill in immediate fcp command BDE */
+ iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_IMMED;
+ iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd);
+ iocb->un.fcpi64.bdl.addrLow = offsetof(IOCB_t,
+ unsli3.fcp_ext.icd);
+ iocb->un.fcpi64.bdl.addrHigh = 0;
+ iocb->ulpBdeCount = 0;
+ iocb->ulpLe = 0;
+ /* fill in responce BDE */
+ iocb->unsli3.fcp_ext.rbde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ iocb->unsli3.fcp_ext.rbde.tus.f.bdeSize =
+ sizeof(struct fcp_rsp);
+ iocb->unsli3.fcp_ext.rbde.addrLow =
+ putPaddrLow(pdma_phys_fcp_rsp);
+ iocb->unsli3.fcp_ext.rbde.addrHigh =
+ putPaddrHigh(pdma_phys_fcp_rsp);
+ } else {
+ iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
+ iocb->un.fcpi64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
+ iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys_bpl);
+ iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys_bpl);
+ iocb->ulpBdeCount = 1;
+ iocb->ulpLe = 1;
+ }
iocb->ulpClass = CLASS3;
return psb;
@@ -313,8 +488,9 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl;
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
+ struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde;
dma_addr_t physaddr;
- uint32_t i, num_bde = 0;
+ uint32_t num_bde = 0;
int nseg, datadir = scsi_cmnd->sc_data_direction;
/*
@@ -352,37 +528,159 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
* during probe that limits the number of sg elements in any
* single scsi command. Just run through the seg_cnt and format
* the bde's.
+ * When using SLI-3 the driver will try to fit all the BDEs into
+ * the IOCB. If it can't then the BDEs get added to a BPL as it
+ * does for SLI-2 mode.
*/
- scsi_for_each_sg(scsi_cmnd, sgel, nseg, i) {
+ scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) {
physaddr = sg_dma_address(sgel);
- bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
- bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- if (datadir == DMA_TO_DEVICE)
- bpl->tus.f.bdeFlags = 0;
- else
- bpl->tus.f.bdeFlags = BUFF_USE_RCV;
- bpl->tus.w = le32_to_cpu(bpl->tus.w);
- bpl++;
- num_bde++;
+ if (phba->sli_rev == 3 &&
+ nseg <= LPFC_EXT_DATA_BDE_COUNT) {
+ data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ data_bde->tus.f.bdeSize = sg_dma_len(sgel);
+ data_bde->addrLow = putPaddrLow(physaddr);
+ data_bde->addrHigh = putPaddrHigh(physaddr);
+ data_bde++;
+ } else {
+ bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ bpl->tus.f.bdeSize = sg_dma_len(sgel);
+ bpl->tus.w = le32_to_cpu(bpl->tus.w);
+ bpl->addrLow =
+ le32_to_cpu(putPaddrLow(physaddr));
+ bpl->addrHigh =
+ le32_to_cpu(putPaddrHigh(physaddr));
+ bpl++;
+ }
}
}
/*
* Finish initializing those IOCB fields that are dependent on the
- * scsi_cmnd request_buffer. Note that the bdeSize is explicitly
- * reinitialized since all iocb memory resources are used many times
- * for transmit, receive, and continuation bpl's.
+ * scsi_cmnd request_buffer. Note that for SLI-2 the bdeSize is
+ * explicitly reinitialized and for SLI-3 the extended bde count is
+ * explicitly reinitialized since all iocb memory resources are reused.
*/
- iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
- iocb_cmd->un.fcpi64.bdl.bdeSize +=
- (num_bde * sizeof (struct ulp_bde64));
- iocb_cmd->ulpBdeCount = 1;
- iocb_cmd->ulpLe = 1;
+ if (phba->sli_rev == 3) {
+ if (num_bde > LPFC_EXT_DATA_BDE_COUNT) {
+ /*
+ * The extended IOCB format can only fit 3 BDE or a BPL.
+ * This I/O has more than 3 BDE so the 1st data bde will
+ * be a BPL that is filled in here.
+ */
+ physaddr = lpfc_cmd->dma_handle;
+ data_bde->tus.f.bdeFlags = BUFF_TYPE_BLP_64;
+ data_bde->tus.f.bdeSize = (num_bde *
+ sizeof(struct ulp_bde64));
+ physaddr += (sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp) +
+ (2 * sizeof(struct ulp_bde64)));
+ data_bde->addrHigh = putPaddrHigh(physaddr);
+ data_bde->addrLow = putPaddrLow(physaddr);
+ /* ebde count includes the responce bde and data bpl */
+ iocb_cmd->unsli3.fcp_ext.ebde_count = 2;
+ } else {
+ /* ebde count includes the responce bde and data bdes */
+ iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1);
+ }
+ } else {
+ iocb_cmd->un.fcpi64.bdl.bdeSize =
+ ((num_bde + 2) * sizeof(struct ulp_bde64));
+ }
fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
return 0;
}
+/**
+ * lpfc_send_scsi_error_event: Posts an event when there is SCSI error.
+ * @phba: Pointer to hba context object.
+ * @vport: Pointer to vport object.
+ * @lpfc_cmd: Pointer to lpfc scsi command which reported the error.
+ * @rsp_iocb: Pointer to response iocb object which reported error.
+ *
+ * This function posts an event when there is a SCSI command reporting
+ * error from the scsi device.
+ **/
+static void
+lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
+ struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) {
+ struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
+ struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
+ uint32_t resp_info = fcprsp->rspStatus2;
+ uint32_t scsi_status = fcprsp->rspStatus3;
+ uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
+ struct lpfc_fast_path_event *fast_path_evt = NULL;
+ struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode;
+ unsigned long flags;
+
+ /* If there is queuefull or busy condition send a scsi event */
+ if ((cmnd->result == SAM_STAT_TASK_SET_FULL) ||
+ (cmnd->result == SAM_STAT_BUSY)) {
+ fast_path_evt = lpfc_alloc_fast_evt(phba);
+ if (!fast_path_evt)
+ return;
+ fast_path_evt->un.scsi_evt.event_type =
+ FC_REG_SCSI_EVENT;
+ fast_path_evt->un.scsi_evt.subcategory =
+ (cmnd->result == SAM_STAT_TASK_SET_FULL) ?
+ LPFC_EVENT_QFULL : LPFC_EVENT_DEVBSY;
+ fast_path_evt->un.scsi_evt.lun = cmnd->device->lun;
+ memcpy(&fast_path_evt->un.scsi_evt.wwpn,
+ &pnode->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(&fast_path_evt->un.scsi_evt.wwnn,
+ &pnode->nlp_nodename, sizeof(struct lpfc_name));
+ } else if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen &&
+ ((cmnd->cmnd[0] == READ_10) || (cmnd->cmnd[0] == WRITE_10))) {
+ fast_path_evt = lpfc_alloc_fast_evt(phba);
+ if (!fast_path_evt)
+ return;
+ fast_path_evt->un.check_cond_evt.scsi_event.event_type =
+ FC_REG_SCSI_EVENT;
+ fast_path_evt->un.check_cond_evt.scsi_event.subcategory =
+ LPFC_EVENT_CHECK_COND;
+ fast_path_evt->un.check_cond_evt.scsi_event.lun =
+ cmnd->device->lun;
+ memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwpn,
+ &pnode->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwnn,
+ &pnode->nlp_nodename, sizeof(struct lpfc_name));
+ fast_path_evt->un.check_cond_evt.sense_key =
+ cmnd->sense_buffer[2] & 0xf;
+ fast_path_evt->un.check_cond_evt.asc = cmnd->sense_buffer[12];
+ fast_path_evt->un.check_cond_evt.ascq = cmnd->sense_buffer[13];
+ } else if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
+ fcpi_parm &&
+ ((be32_to_cpu(fcprsp->rspResId) != fcpi_parm) ||
+ ((scsi_status == SAM_STAT_GOOD) &&
+ !(resp_info & (RESID_UNDER | RESID_OVER))))) {
+ /*
+ * If status is good or resid does not match with fcp_param and
+ * there is valid fcpi_parm, then there is a read_check error
+ */
+ fast_path_evt = lpfc_alloc_fast_evt(phba);
+ if (!fast_path_evt)
+ return;
+ fast_path_evt->un.read_check_error.header.event_type =
+ FC_REG_FABRIC_EVENT;
+ fast_path_evt->un.read_check_error.header.subcategory =
+ LPFC_EVENT_FCPRDCHKERR;
+ memcpy(&fast_path_evt->un.read_check_error.header.wwpn,
+ &pnode->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(&fast_path_evt->un.read_check_error.header.wwnn,
+ &pnode->nlp_nodename, sizeof(struct lpfc_name));
+ fast_path_evt->un.read_check_error.lun = cmnd->device->lun;
+ fast_path_evt->un.read_check_error.opcode = cmnd->cmnd[0];
+ fast_path_evt->un.read_check_error.fcpiparam =
+ fcpi_parm;
+ } else
+ return;
+
+ fast_path_evt->vport = vport;
+ spin_lock_irqsave(&phba->hbalock, flags);
+ list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ lpfc_worker_wake_up(phba);
+ return;
+}
static void
lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
{
@@ -411,6 +709,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
uint32_t rsplen = 0;
uint32_t logit = LOG_FCP | LOG_FCP_ERROR;
+
/*
* If this is a task management command, there is no
* scsi packet associated with this lpfc_cmd. The driver
@@ -526,6 +825,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
out:
cmnd->result = ScsiResult(host_status, scsi_status);
+ lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, rsp_iocb);
}
static void
@@ -542,9 +842,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct scsi_device *sdev, *tmp_sdev;
int depth = 0;
unsigned long flags;
+ struct lpfc_fast_path_event *fast_path_evt;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
+ atomic_dec(&pnode->cmd_pending);
if (lpfc_cmd->status) {
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
@@ -570,12 +872,36 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
break;
case IOSTAT_NPORT_BSY:
case IOSTAT_FABRIC_BSY:
- cmd->result = ScsiResult(DID_BUS_BUSY, 0);
+ cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
+ fast_path_evt = lpfc_alloc_fast_evt(phba);
+ if (!fast_path_evt)
+ break;
+ fast_path_evt->un.fabric_evt.event_type =
+ FC_REG_FABRIC_EVENT;
+ fast_path_evt->un.fabric_evt.subcategory =
+ (lpfc_cmd->status == IOSTAT_NPORT_BSY) ?
+ LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY;
+ if (pnode && NLP_CHK_NODE_ACT(pnode)) {
+ memcpy(&fast_path_evt->un.fabric_evt.wwpn,
+ &pnode->nlp_portname,
+ sizeof(struct lpfc_name));
+ memcpy(&fast_path_evt->un.fabric_evt.wwnn,
+ &pnode->nlp_nodename,
+ sizeof(struct lpfc_name));
+ }
+ fast_path_evt->vport = vport;
+ fast_path_evt->work_evt.evt =
+ LPFC_EVT_FASTPATH_MGMT_EVT;
+ spin_lock_irqsave(&phba->hbalock, flags);
+ list_add_tail(&fast_path_evt->work_evt.evt_listp,
+ &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ lpfc_worker_wake_up(phba);
break;
case IOSTAT_LOCAL_REJECT:
- if (lpfc_cmd->result == RJT_UNAVAIL_PERM ||
+ if (lpfc_cmd->result == IOERR_INVALID_RPI ||
lpfc_cmd->result == IOERR_NO_RESOURCES ||
- lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
+ lpfc_cmd->result == IOERR_ABORT_REQUESTED) {
cmd->result = ScsiResult(DID_REQUEUE, 0);
break;
} /* else: fall through */
@@ -586,7 +912,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
if (!pnode || !NLP_CHK_NODE_ACT(pnode)
|| (pnode->nlp_state != NLP_STE_MAPPED_NODE))
- cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
+ cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED,
+ SAM_STAT_BUSY);
} else {
cmd->result = ScsiResult(DID_OK, 0);
}
@@ -602,8 +929,32 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
scsi_get_resid(cmd));
}
+ lpfc_update_stats(phba, lpfc_cmd);
result = cmd->result;
sdev = cmd->device;
+ if (vport->cfg_max_scsicmpl_time &&
+ time_after(jiffies, lpfc_cmd->start_time +
+ msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
+ spin_lock_irqsave(sdev->host->host_lock, flags);
+ if ((pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) &&
+ (atomic_read(&pnode->cmd_pending) > LPFC_MIN_TGT_QDEPTH) &&
+ ((cmd->cmnd[0] == READ_10) || (cmd->cmnd[0] == WRITE_10))))
+ pnode->cmd_qdepth = atomic_read(&pnode->cmd_pending);
+
+ pnode->last_change_time = jiffies;
+ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ } else if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
+ time_after(jiffies, pnode->last_change_time +
+ msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
+ spin_lock_irqsave(sdev->host->host_lock, flags);
+ pnode->cmd_qdepth += pnode->cmd_qdepth *
+ LPFC_TGTQ_RAMPUP_PCENT / 100;
+ if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
+ pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
+ pnode->last_change_time = jiffies;
+ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ }
+
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
cmd->scsi_done(cmd);
@@ -647,6 +998,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
pnode->last_ramp_up_time = jiffies;
}
}
+ lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
+ 0xFFFFFFFF,
+ sdev->queue_depth - 1, sdev->queue_depth);
}
/*
@@ -676,6 +1030,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"0711 detected queue full - lun queue "
"depth adjusted to %d.\n", depth);
+ lpfc_send_sdev_queuedepth_change_event(phba, vport,
+ pnode, 0xFFFFFFFF,
+ depth+1, depth);
}
}
@@ -692,6 +1049,24 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_release_scsi_buf(phba, lpfc_cmd);
}
+/**
+ * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB.
+ * @data: A pointer to the immediate command data portion of the IOCB.
+ * @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
+ *
+ * The routine copies the entire FCP command from @fcp_cmnd to @data while
+ * byte swapping the data to big endian format for transmission on the wire.
+ **/
+static void
+lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
+{
+ int i, j;
+ for (i = 0, j = 0; i < sizeof(struct fcp_cmnd);
+ i += sizeof(uint32_t), j++) {
+ ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]);
+ }
+}
+
static void
lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
struct lpfc_nodelist *pnode)
@@ -758,7 +1133,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
fcp_cmnd->fcpCntl3 = 0;
phba->fc4ControlRequests++;
}
-
+ if (phba->sli_rev == 3)
+ lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd);
/*
* Finish initializing those IOCB fields that are independent
* of the scsi_cmnd request_buffer
@@ -798,11 +1174,13 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
piocb = &piocbq->iocb;
fcp_cmnd = lpfc_cmd->fcp_cmnd;
- int_to_scsilun(lun, &lpfc_cmd->fcp_cmnd->fcp_lun);
+ /* Clear out any old data in the FCP command area */
+ memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+ int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
-
+ if (vport->phba->sli_rev == 3)
+ lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd);
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
-
piocb->ulpContext = ndlp->nlp_rpi;
if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
piocb->ulpFCP2Rcvy = 1;
@@ -967,9 +1345,12 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
* transport is still transitioning.
*/
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
goto out_fail_command;
}
+ if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
+ goto out_host_busy;
+
lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL) {
lpfc_adjust_queue_depth(phba);
@@ -980,6 +1361,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
goto out_host_busy;
}
+ lpfc_cmd->start_time = jiffies;
/*
* Store the midlayer's command structure for the completion phase
* and complete the command initialization.
@@ -987,6 +1369,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
lpfc_cmd->pCmd = cmnd;
lpfc_cmd->rdata = rdata;
lpfc_cmd->timeout = 0;
+ lpfc_cmd->start_time = jiffies;
cmnd->host_scribble = (unsigned char *)lpfc_cmd;
cmnd->scsi_done = done;
@@ -996,6 +1379,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
+ atomic_inc(&ndlp->cmd_pending);
err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
if (err)
@@ -1010,6 +1394,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
return 0;
out_host_busy_free_buf:
+ atomic_dec(&ndlp->cmd_pending);
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
out_host_busy:
@@ -1145,6 +1530,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
int ret = SUCCESS;
int status;
int cnt;
+ struct lpfc_scsi_event_header scsi_event;
lpfc_block_error_handler(cmnd);
/*
@@ -1163,6 +1549,19 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
break;
pnode = rdata->pnode;
}
+
+ scsi_event.event_type = FC_REG_SCSI_EVENT;
+ scsi_event.subcategory = LPFC_EVENT_TGTRESET;
+ scsi_event.lun = 0;
+ memcpy(scsi_event.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name));
+ memcpy(scsi_event.wwnn, &pnode->nlp_nodename, sizeof(struct lpfc_name));
+
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ sizeof(scsi_event),
+ (char *)&scsi_event,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+
if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
"0721 LUN Reset rport "
@@ -1242,10 +1641,23 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = NULL;
int match;
- int ret = SUCCESS, status, i;
+ int ret = SUCCESS, status = SUCCESS, i;
int cnt;
struct lpfc_scsi_buf * lpfc_cmd;
unsigned long later;
+ struct lpfc_scsi_event_header scsi_event;
+
+ scsi_event.event_type = FC_REG_SCSI_EVENT;
+ scsi_event.subcategory = LPFC_EVENT_BUSRESET;
+ scsi_event.lun = 0;
+ memcpy(scsi_event.wwpn, &vport->fc_portname, sizeof(struct lpfc_name));
+ memcpy(scsi_event.wwnn, &vport->fc_nodename, sizeof(struct lpfc_name));
+
+ fc_host_post_vendor_event(shost,
+ fc_get_event_number(),
+ sizeof(scsi_event),
+ (char *)&scsi_event,
+ SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
lpfc_block_error_handler(cmnd);
/*
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index daba9237498..437f182e232 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -107,6 +107,10 @@ struct fcp_cmnd {
};
+struct lpfc_scsicmd_bkt {
+ uint32_t cmd_count;
+};
+
struct lpfc_scsi_buf {
struct list_head list;
struct scsi_cmnd *pCmd;
@@ -139,6 +143,7 @@ struct lpfc_scsi_buf {
*/
struct lpfc_iocbq cur_iocbq;
wait_queue_head_t *waitq;
+ unsigned long start_time;
};
#define LPFC_SCSI_DMA_EXT_SIZE 264
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 50fe0764673..8ab5babdeeb 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -32,6 +32,7 @@
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -66,10 +67,16 @@ typedef enum _lpfc_iocb_type {
LPFC_ABORT_IOCB
} lpfc_iocb_type;
- /* SLI-2/SLI-3 provide different sized iocbs. Given a pointer
- * to the start of the ring, and the slot number of the
- * desired iocb entry, calc a pointer to that entry.
- */
+/**
+ * lpfc_cmd_iocb: Get next command iocb entry in the ring.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function returns pointer to next command iocb entry
+ * in the command ring. The caller must hold hbalock to prevent
+ * other threads consume the next command iocb.
+ * SLI-2/SLI-3 provide different sized iocbs.
+ **/
static inline IOCB_t *
lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -77,6 +84,16 @@ lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->cmdidx * phba->iocb_cmd_size);
}
+/**
+ * lpfc_resp_iocb: Get next response iocb entry in the ring.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function returns pointer to next response iocb entry
+ * in the response ring. The caller must hold hbalock to make sure
+ * that no other thread consume the next response iocb.
+ * SLI-2/SLI-3 provide different sized iocbs.
+ **/
static inline IOCB_t *
lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -84,6 +101,15 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->rspidx * phba->iocb_rsp_size);
}
+/**
+ * __lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with hbalock held. This function
+ * allocates a new driver iocb object from the iocb pool. If the
+ * allocation is successful, it returns pointer to the newly
+ * allocated iocb object else it returns NULL.
+ **/
static struct lpfc_iocbq *
__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{
@@ -94,6 +120,15 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
return iocbq;
}
+/**
+ * lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with no lock held. This function
+ * allocates a new driver iocb object from the iocb pool. If the
+ * allocation is successful, it returns pointer to the newly
+ * allocated iocb object else it returns NULL.
+ **/
struct lpfc_iocbq *
lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{
@@ -106,6 +141,16 @@ lpfc_sli_get_iocbq(struct lpfc_hba *phba)
return iocbq;
}
+/**
+ * __lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * @phba: Pointer to HBA context object.
+ * @iocbq: Pointer to driver iocb object.
+ *
+ * This function is called with hbalock held to release driver
+ * iocb object to the iocb pool. The iotag in the iocb object
+ * does not change for each use of the iocb object. This function
+ * clears all other fields of the iocb object when it is freed.
+ **/
static void
__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
@@ -118,6 +163,14 @@ __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
}
+/**
+ * lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * @phba: Pointer to HBA context object.
+ * @iocbq: Pointer to driver iocb object.
+ *
+ * This function is called with no lock held to release the iocb to
+ * iocb pool.
+ **/
void
lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
@@ -131,10 +184,21 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
-/*
- * Translate the iocb command to an iocb command type used to decide the final
- * disposition of each completed IOCB.
- */
+/**
+ * lpfc_sli_iocb_cmd_type: Get the iocb type.
+ * @iocb_cmnd : iocb command code.
+ *
+ * This function is called by ring event handler function to get the iocb type.
+ * This function translates the iocb command to an iocb command type used to
+ * decide the final disposition of each completed IOCB.
+ * The function returns
+ * LPFC_UNKNOWN_IOCB if it is an unsupported iocb
+ * LPFC_SOL_IOCB if it is a solicited iocb completion
+ * LPFC_ABORT_IOCB if it is an abort iocb
+ * LPFC_UNSOL_IOCB if it is an unsolicited iocb
+ *
+ * The caller is not required to hold any lock.
+ **/
static lpfc_iocb_type
lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
{
@@ -230,6 +294,17 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
return type;
}
+/**
+ * lpfc_sli_ring_map: Issue config_ring mbox for all rings.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called from SLI initialization code
+ * to configure every ring of the HBA's SLI interface. The
+ * caller is not required to hold any lock. This function issues
+ * a config_ring mailbox command for each ring.
+ * This function returns zero if successful else returns a negative
+ * error code.
+ **/
static int
lpfc_sli_ring_map(struct lpfc_hba *phba)
{
@@ -262,6 +337,18 @@ lpfc_sli_ring_map(struct lpfc_hba *phba)
return ret;
}
+/**
+ * lpfc_sli_ringtxcmpl_put: Adds new iocb to the txcmplq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @piocb: Pointer to the driver iocb object.
+ *
+ * This function is called with hbalock held. The function adds the
+ * new iocb to txcmplq of the given ring. This function always returns
+ * 0. If this function is called for ELS ring, this function checks if
+ * there is a vport associated with the ELS command. This function also
+ * starts els_tmofunc timer if this is an ELS command.
+ **/
static int
lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
@@ -282,6 +369,16 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 0;
}
+/**
+ * lpfc_sli_ringtx_get: Get first element of the txq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function is called with hbalock held to get next
+ * iocb in txq of the given ring. If there is any iocb in
+ * the txq, the function returns first iocb in the list after
+ * removing the iocb from the list, else it returns NULL.
+ **/
static struct lpfc_iocbq *
lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -293,14 +390,25 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return cmd_iocb;
}
+/**
+ * lpfc_sli_next_iocb_slot: Get next iocb slot in the ring.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function is called with hbalock held and the caller must post the
+ * iocb without releasing the lock. If the caller releases the lock,
+ * iocb slot returned by the function is not guaranteed to be available.
+ * The function returns pointer to the next available iocb slot if there
+ * is available slot in the ring, else it returns NULL.
+ * If the get index of the ring is ahead of the put index, the function
+ * will post an error attention event to the worker thread to take the
+ * HBA to offline state.
+ **/
static IOCB_t *
lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
- struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
- &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
- &phba->slim2p->mbx.us.s2.port[pring->ringno];
+ struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
uint32_t max_cmd_idx = pring->numCiocb;
-
if ((pring->next_cmdidx == pring->cmdidx) &&
(++pring->next_cmdidx >= max_cmd_idx))
pring->next_cmdidx = 0;
@@ -336,6 +444,18 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return lpfc_cmd_iocb(phba, pring);
}
+/**
+ * lpfc_sli_next_iotag: Get an iotag for the iocb.
+ * @phba: Pointer to HBA context object.
+ * @iocbq: Pointer to driver iocb object.
+ *
+ * This function gets an iotag for the iocb. If there is no unused iotag and
+ * the iocbq_lookup_len < 0xffff, this function allocates a bigger iotag_lookup
+ * array and assigns a new iotag.
+ * The function returns the allocated iotag if successful, else returns zero.
+ * Zero is not a valid iotag.
+ * The caller is not required to hold any lock.
+ **/
uint16_t
lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
@@ -399,6 +519,20 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
return 0;
}
+/**
+ * lpfc_sli_submit_iocb: Submit an iocb to the firmware.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @iocb: Pointer to iocb slot in the ring.
+ * @nextiocb: Pointer to driver iocb object which need to be
+ * posted to firmware.
+ *
+ * This function is called with hbalock held to post a new iocb to
+ * the firmware. This function copies the new iocb to ring iocb slot and
+ * updates the ring pointers. It adds the new iocb to txcmplq if there is
+ * a completion call back for this iocb else the function will free the
+ * iocb object.
+ **/
static void
lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
IOCB_t *iocb, struct lpfc_iocbq *nextiocb)
@@ -441,6 +575,18 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
}
+/**
+ * lpfc_sli_update_full_ring: Update the chip attention register.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * The caller is not required to hold any lock for calling this function.
+ * This function updates the chip attention bits for the ring to inform firmware
+ * that there are pending work to be done for this ring and requests an
+ * interrupt when there is space available in the ring. This function is
+ * called when the driver is unable to post more iocbs to the ring due
+ * to unavailability of space in the ring.
+ **/
static void
lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -460,6 +606,15 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->stats.iocb_cmd_full++;
}
+/**
+ * lpfc_sli_update_ring: Update chip attention register.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function updates the chip attention register bit for the
+ * given ring to inform HBA that there is more work to be done
+ * in this ring. The caller is not required to hold any lock.
+ **/
static void
lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -468,11 +623,22 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
/*
* Tell the HBA that there is work to do in this ring.
*/
- wmb();
- writel(CA_R0ATT << (ringno * 4), phba->CAregaddr);
- readl(phba->CAregaddr); /* flush */
+ if (!(phba->sli3_options & LPFC_SLI3_CRP_ENABLED)) {
+ wmb();
+ writel(CA_R0ATT << (ringno * 4), phba->CAregaddr);
+ readl(phba->CAregaddr); /* flush */
+ }
}
+/**
+ * lpfc_sli_resume_iocb: Process iocbs in the txq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function is called with hbalock held to post pending iocbs
+ * in the txq to the firmware. This function is called when driver
+ * detects space available in the ring.
+ **/
static void
lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -504,6 +670,16 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return;
}
+/**
+ * lpfc_sli_next_hbq_slot: Get next hbq entry for the HBQ.
+ * @phba: Pointer to HBA context object.
+ * @hbqno: HBQ number.
+ *
+ * This function is called with hbalock held to get the next
+ * available slot for the given HBQ. If there is free slot
+ * available for the HBQ it will return pointer to the next available
+ * HBQ entry else it will return NULL.
+ **/
static struct lpfc_hbq_entry *
lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
{
@@ -539,6 +715,15 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
hbqp->hbqPutIdx;
}
+/**
+ * lpfc_sli_hbqbuf_free_all: Free all the hbq buffers.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with no lock held to free all the
+ * hbq buffers while uninitializing the SLI interface. It also
+ * frees the HBQ buffers returned by the firmware but not yet
+ * processed by the upper layers.
+ **/
void
lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
{
@@ -584,6 +769,18 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
spin_unlock_irqrestore(&phba->hbalock, flags);
}
+/**
+ * lpfc_sli_hbq_to_firmware: Post the hbq buffer to firmware.
+ * @phba: Pointer to HBA context object.
+ * @hbqno: HBQ number.
+ * @hbq_buf: Pointer to HBQ buffer.
+ *
+ * This function is called with the hbalock held to post a
+ * hbq buffer to the firmware. If the function finds an empty
+ * slot in the HBQ, it will post the buffer. The function will return
+ * pointer to the hbq entry if it successfully post the buffer
+ * else it will return NULL.
+ **/
static struct lpfc_hbq_entry *
lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
struct hbq_dmabuf *hbq_buf)
@@ -612,6 +809,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
return hbqe;
}
+/* HBQ for ELS and CT traffic. */
static struct lpfc_hbq_init lpfc_els_hbq = {
.rn = 1,
.entry_count = 200,
@@ -623,6 +821,7 @@ static struct lpfc_hbq_init lpfc_els_hbq = {
.add_count = 5,
};
+/* HBQ for the extra ring if needed */
static struct lpfc_hbq_init lpfc_extra_hbq = {
.rn = 1,
.entry_count = 200,
@@ -634,51 +833,81 @@ static struct lpfc_hbq_init lpfc_extra_hbq = {
.add_count = 5,
};
+/* Array of HBQs */
struct lpfc_hbq_init *lpfc_hbq_defs[] = {
&lpfc_els_hbq,
&lpfc_extra_hbq,
};
+/**
+ * lpfc_sli_hbqbuf_fill_hbqs: Post more hbq buffers to HBQ.
+ * @phba: Pointer to HBA context object.
+ * @hbqno: HBQ number.
+ * @count: Number of HBQ buffers to be posted.
+ *
+ * This function is called with no lock held to post more hbq buffers to the
+ * given HBQ. The function returns the number of HBQ buffers successfully
+ * posted.
+ **/
static int
lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
{
- uint32_t i, start, end;
+ uint32_t i, posted = 0;
unsigned long flags;
struct hbq_dmabuf *hbq_buffer;
-
+ LIST_HEAD(hbq_buf_list);
if (!phba->hbqs[hbqno].hbq_alloc_buffer)
return 0;
- start = phba->hbqs[hbqno].buffer_count;
- end = count + start;
- if (end > lpfc_hbq_defs[hbqno]->entry_count)
- end = lpfc_hbq_defs[hbqno]->entry_count;
-
+ if ((phba->hbqs[hbqno].buffer_count + count) >
+ lpfc_hbq_defs[hbqno]->entry_count)
+ count = lpfc_hbq_defs[hbqno]->entry_count -
+ phba->hbqs[hbqno].buffer_count;
+ if (!count)
+ return 0;
+ /* Allocate HBQ entries */
+ for (i = 0; i < count; i++) {
+ hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
+ if (!hbq_buffer)
+ break;
+ list_add_tail(&hbq_buffer->dbuf.list, &hbq_buf_list);
+ }
/* Check whether HBQ is still in use */
spin_lock_irqsave(&phba->hbalock, flags);
if (!phba->hbq_in_use)
- goto out;
-
- /* Populate HBQ entries */
- for (i = start; i < end; i++) {
- hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
- if (!hbq_buffer)
- goto err;
- hbq_buffer->tag = (i | (hbqno << 16));
- if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
+ goto err;
+ while (!list_empty(&hbq_buf_list)) {
+ list_remove_head(&hbq_buf_list, hbq_buffer, struct hbq_dmabuf,
+ dbuf.list);
+ hbq_buffer->tag = (phba->hbqs[hbqno].buffer_count |
+ (hbqno << 16));
+ if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) {
phba->hbqs[hbqno].buffer_count++;
- else
+ posted++;
+ } else
(phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
}
-
- out:
spin_unlock_irqrestore(&phba->hbalock, flags);
- return 0;
- err:
+ return posted;
+err:
spin_unlock_irqrestore(&phba->hbalock, flags);
- return 1;
+ while (!list_empty(&hbq_buf_list)) {
+ list_remove_head(&hbq_buf_list, hbq_buffer, struct hbq_dmabuf,
+ dbuf.list);
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
+ }
+ return 0;
}
+/**
+ * lpfc_sli_hbqbuf_add_hbqs: Post more HBQ buffers to firmware.
+ * @phba: Pointer to HBA context object.
+ * @qno: HBQ number.
+ *
+ * This function posts more buffers to the HBQ. This function
+ * is called with no lock held. The function returns the number of HBQ entries
+ * successfully allocated.
+ **/
int
lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
{
@@ -686,6 +915,15 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
lpfc_hbq_defs[qno]->add_count));
}
+/**
+ * lpfc_sli_hbqbuf_init_hbqs: Post initial buffers to the HBQ.
+ * @phba: Pointer to HBA context object.
+ * @qno: HBQ queue number.
+ *
+ * This function is called from SLI initialization code path with
+ * no lock held to post initial HBQ buffers to firmware. The
+ * function returns the number of HBQ entries successfully allocated.
+ **/
static int
lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
{
@@ -693,6 +931,16 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
lpfc_hbq_defs[qno]->init_count));
}
+/**
+ * lpfc_sli_hbqbuf_find: Find the hbq buffer associated with a tag.
+ * @phba: Pointer to HBA context object.
+ * @tag: Tag of the hbq buffer.
+ *
+ * This function is called with hbalock held. This function searches
+ * for the hbq buffer associated with the given tag in the hbq buffer
+ * list. If it finds the hbq buffer, it returns the hbq_buffer other wise
+ * it returns NULL.
+ **/
static struct hbq_dmabuf *
lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
{
@@ -716,6 +964,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
return NULL;
}
+/**
+ * lpfc_sli_free_hbq: Give back the hbq buffer to firmware.
+ * @phba: Pointer to HBA context object.
+ * @hbq_buffer: Pointer to HBQ buffer.
+ *
+ * This function is called with hbalock. This function gives back
+ * the hbq buffer to firmware. If the HBQ does not have space to
+ * post the buffer, it will free the buffer.
+ **/
void
lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
{
@@ -729,6 +986,15 @@ lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
}
}
+/**
+ * lpfc_sli_chk_mbx_command: Check if the mailbox is a legitimate mailbox.
+ * @mbxCommand: mailbox command code.
+ *
+ * This function is called by the mailbox event handler function to verify
+ * that the completed mailbox command is a legitimate mailbox command. If the
+ * completed mailbox is not known to the function, it will return MBX_SHUTDOWN
+ * and the mailbox event handler will take the HBA offline.
+ **/
static int
lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
{
@@ -785,6 +1051,8 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_REG_VPI:
case MBX_UNREG_VPI:
case MBX_HEARTBEAT:
+ case MBX_PORT_CAPABILITIES:
+ case MBX_PORT_IOV_CONTROL:
ret = mbxCommand;
break;
default:
@@ -793,6 +1061,19 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
}
return ret;
}
+
+/**
+ * lpfc_sli_wake_mbox_wait: Completion handler for mbox issued from
+ * lpfc_sli_issue_mbox_wait.
+ * @phba: Pointer to HBA context object.
+ * @pmboxq: Pointer to mailbox command.
+ *
+ * This is completion handler function for mailbox commands issued from
+ * lpfc_sli_issue_mbox_wait function. This function is called by the
+ * mailbox event handler function with no lock held. This function
+ * will wake up thread waiting on the wait queue pointed by context1
+ * of the mailbox.
+ **/
static void
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
@@ -812,6 +1093,17 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
return;
}
+
+/**
+ * lpfc_sli_def_mbox_cmpl: Default mailbox completion handler.
+ * @phba: Pointer to HBA context object.
+ * @pmb: Pointer to mailbox object.
+ *
+ * This function is the default mailbox completion handler. It
+ * frees the memory resources associated with the completed mailbox
+ * command. If the completed command is a REG_LOGIN mailbox command,
+ * this function will issue a UREG_LOGIN to re-claim the RPI.
+ **/
void
lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
@@ -846,6 +1138,19 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
+/**
+ * lpfc_sli_handle_mb_event: Handle mailbox completions from firmware.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with no lock held. This function processes all
+ * the completed mailbox commands and gives it to upper layers. The interrupt
+ * service routine processes mailbox completion interrupt and adds completed
+ * mailbox commands to the mboxq_cmpl queue and signals the worker thread.
+ * Worker thread call lpfc_sli_handle_mb_event, which will return the
+ * completed mailbox commands in mboxq_cmpl queue to the upper layers. This
+ * function returns the mailbox commands to the upper layer by calling the
+ * completion handler function of each mailbox.
+ **/
int
lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
{
@@ -953,6 +1258,18 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_replace_hbqbuff: Replace the HBQ buffer with a new buffer.
+ * @phba: Pointer to HBA context object.
+ * @tag: Tag for the HBQ buffer.
+ *
+ * This function is called from unsolicited event handler code path to get the
+ * HBQ buffer associated with an unsolicited iocb. This function is called with
+ * no lock held. It returns the buffer associated with the given tag and posts
+ * another buffer to the firmware. Note that the new buffer must be allocated
+ * before taking the hbalock and that the hba lock must be held until it is
+ * finished with the hbq entry swap.
+ **/
static struct lpfc_dmabuf *
lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
{
@@ -962,22 +1279,28 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
dma_addr_t phys; /* mapped address */
unsigned long flags;
+ hbqno = tag >> 16;
+ new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
/* Check whether HBQ is still in use */
spin_lock_irqsave(&phba->hbalock, flags);
if (!phba->hbq_in_use) {
+ if (new_hbq_entry)
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba,
+ new_hbq_entry);
spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}
hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
if (hbq_entry == NULL) {
+ if (new_hbq_entry)
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba,
+ new_hbq_entry);
spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}
list_del(&hbq_entry->dbuf.list);
- hbqno = tag >> 16;
- new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
if (new_hbq_entry == NULL) {
list_add_tail(&hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
spin_unlock_irqrestore(&phba->hbalock, flags);
@@ -997,6 +1320,18 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
return &new_hbq_entry->dbuf;
}
+/**
+ * lpfc_sli_get_buff: Get the buffer associated with the buffer tag.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @tag: buffer tag.
+ *
+ * This function is called with no lock held. When QUE_BUFTAG_BIT bit
+ * is set in the tag the buffer is posted for a particular exchange,
+ * the function will return the buffer without replacing the buffer.
+ * If the buffer is for unsolicited ELS or CT traffic, this function
+ * returns the buffer and also posts another buffer to the firmware.
+ **/
static struct lpfc_dmabuf *
lpfc_sli_get_buff(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
@@ -1008,6 +1343,21 @@ lpfc_sli_get_buff(struct lpfc_hba *phba,
return lpfc_sli_replace_hbqbuff(phba, tag);
}
+
+/**
+ * lpfc_sli_process_unsol_iocb: Unsolicited iocb handler.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @saveq: Pointer to the unsolicited iocb.
+ *
+ * This function is called with no lock held by the ring event handler
+ * when there is an unsolicited iocb posted to the response ring by the
+ * firmware. This function gets the buffer associated with the iocbs
+ * and calls the event handler for the ring. This function handles both
+ * qring buffers and hbq buffers.
+ * When the function returns 1 the caller can free the iocb object otherwise
+ * upper layer functions will free the iocb objects.
+ **/
static int
lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *saveq)
@@ -1192,6 +1542,18 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 1;
}
+/**
+ * lpfc_sli_iocbq_lookup: Find command iocb for the given response iocb.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @prspiocb: Pointer to response iocb object.
+ *
+ * This function looks up the iocb_lookup table to get the command iocb
+ * corresponding to the given response iocb using the iotag of the
+ * response iocb. This function is called with the hbalock held.
+ * This function returns the command iocb object if it finds the command
+ * iocb else returns NULL.
+ **/
static struct lpfc_iocbq *
lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
@@ -1217,6 +1579,23 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
return NULL;
}
+/**
+ * lpfc_sli_process_sol_iocb: process solicited iocb completion.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @saveq: Pointer to the response iocb to be processed.
+ *
+ * This function is called by the ring event handler for non-fcp
+ * rings when there is a new response iocb in the response ring.
+ * The caller is not required to hold any locks. This function
+ * gets the command iocb associated with the response iocb and
+ * calls the completion handler for the command iocb. If there
+ * is no completion handler, the function will free the resources
+ * associated with command iocb. If the response iocb is for
+ * an already aborted command iocb, the status of the completion
+ * is changed to IOSTAT_LOCAL_REJECT/IOERR_SLI_ABORTED.
+ * This function always returns 1.
+ **/
static int
lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *saveq)
@@ -1233,6 +1612,17 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (cmdiocbp) {
if (cmdiocbp->iocb_cmpl) {
/*
+ * If an ELS command failed send an event to mgmt
+ * application.
+ */
+ if (saveq->iocb.ulpStatus &&
+ (pring->ringno == LPFC_ELS_RING) &&
+ (cmdiocbp->iocb.ulpCommand ==
+ CMD_ELS_REQUEST64_CR))
+ lpfc_send_els_failure_event(phba,
+ cmdiocbp, saveq);
+
+ /*
* Post all ELS completions to the worker thread.
* All other are passed to the completion callback.
*/
@@ -1282,12 +1672,20 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return rc;
}
+/**
+ * lpfc_sli_rsp_pointers_error: Response ring pointer error handler.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function is called from the iocb ring event handlers when
+ * put pointer is ahead of the get pointer for a ring. This function signal
+ * an error attention condition to the worker thread and the worker
+ * thread will transition the HBA to offline state.
+ **/
static void
lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
- struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
- &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
- &phba->slim2p->mbx.us.s2.port[pring->ringno];
+ struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
/*
* Ring <ringno> handler: portRspPut <portRspPut> is bigger then
* rsp ring <portRspMax>
@@ -1312,6 +1710,51 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return;
}
+/**
+ * lpfc_poll_eratt: Error attention polling timer timeout handler.
+ * @ptr: Pointer to address of HBA context object.
+ *
+ * This function is invoked by the Error Attention polling timer when the
+ * timer times out. It will check the SLI Error Attention register for
+ * possible attention events. If so, it will post an Error Attention event
+ * and wake up worker thread to process it. Otherwise, it will set up the
+ * Error Attention polling timer for the next poll.
+ **/
+void lpfc_poll_eratt(unsigned long ptr)
+{
+ struct lpfc_hba *phba;
+ uint32_t eratt = 0;
+
+ phba = (struct lpfc_hba *)ptr;
+
+ /* Check chip HA register for error event */
+ eratt = lpfc_sli_check_eratt(phba);
+
+ if (eratt)
+ /* Tell the worker thread there is work to do */
+ lpfc_worker_wake_up(phba);
+ else
+ /* Restart the timer for next eratt poll */
+ mod_timer(&phba->eratt_poll, jiffies +
+ HZ * LPFC_ERATT_POLL_INTERVAL);
+ return;
+}
+
+/**
+ * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called from lpfc_queuecommand, lpfc_poll_timeout,
+ * lpfc_abort_handler and lpfc_slave_configure when FCP_RING_POLLING
+ * is enabled.
+ *
+ * The caller does not hold any lock.
+ * The function processes each response iocb in the response ring until it
+ * finds an iocb with LE bit set and chains all the iocbs upto the iocb with
+ * LE bit set. The function will call the completion handler of the command iocb
+ * if the response iocb indicates a completion for a command iocb or it is
+ * an abort completion.
+ **/
void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
@@ -1320,7 +1763,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
struct lpfc_iocbq rspiocbq;
- struct lpfc_pgp *pgp;
+ struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
uint32_t status;
uint32_t portRspPut, portRspMax;
int type;
@@ -1330,11 +1773,6 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
pring->stats.iocb_event++;
- pgp = (phba->sli_rev == 3) ?
- &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
- &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.
@@ -1372,8 +1810,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
irsp->un.ulpWord[3],
irsp->un.ulpWord[4],
irsp->un.ulpWord[5],
- *(((uint32_t *) irsp) + 6),
- *(((uint32_t *) irsp) + 7));
+ *(uint32_t *)&irsp->un1,
+ *((uint32_t *)&irsp->un1 + 1));
}
switch (type) {
@@ -1465,17 +1903,28 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
return;
}
-/*
+/**
+ * lpfc_sli_handle_fast_ring_event: Handle ring events on FCP ring.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @mask: Host attention register mask for this ring.
+ *
+ * This function is called from the interrupt context when there is a ring
+ * event for the fcp ring. The caller does not hold any lock.
+ * The function processes each response iocb in the response ring until it
+ * finds an iocb with LE bit set and chains all the iocbs upto the iocb with
+ * LE bit set. The function will call the completion handler of the command iocb
+ * if the response iocb indicates a completion for a command iocb or it is
+ * an abort completion. The function will call lpfc_sli_process_unsol_iocb
+ * function if this is an unsolicited iocb.
* This routine presumes LPFC_FCP_RING handling and doesn't bother
- * to check it explicitly.
- */
+ * to check it explicitly. This function always returns 1.
+ **/
static int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask)
{
- struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
- &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
- &phba->slim2p->mbx.us.s2.port[pring->ringno];
+ struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
IOCB_t *irsp = NULL;
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
@@ -1548,8 +1997,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
irsp->un.ulpWord[3],
irsp->un.ulpWord[4],
irsp->un.ulpWord[5],
- *(((uint32_t *) irsp) + 6),
- *(((uint32_t *) irsp) + 7));
+ *(uint32_t *)&irsp->un1,
+ *((uint32_t *)&irsp->un1 + 1));
}
switch (type) {
@@ -1646,13 +2095,28 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
return rc;
}
+/**
+ * lpfc_sli_handle_slow_ring_event: Handle ring events for non-FCP rings.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @mask: Host attention register mask for this ring.
+ *
+ * This function is called from the worker thread when there is a ring
+ * event for non-fcp rings. The caller does not hold any lock .
+ * The function processes each response iocb in the response ring until it
+ * finds an iocb with LE bit set and chains all the iocbs upto the iocb with
+ * LE bit set. The function will call lpfc_sli_process_sol_iocb function if the
+ * response iocb indicates a completion of a command iocb. The function
+ * will call lpfc_sli_process_unsol_iocb function if this is an unsolicited
+ * iocb. The function frees the resources or calls the completion handler if
+ * this iocb is an abort completion. The function returns 0 when the allocated
+ * iocbs are not freed, otherwise returns 1.
+ **/
int
lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask)
{
- struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
- &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
- &phba->slim2p->mbx.us.s2.port[pring->ringno];
+ struct lpfc_pgp *pgp;
IOCB_t *entry;
IOCB_t *irsp = NULL;
struct lpfc_iocbq *rspiocbp = NULL;
@@ -1666,6 +2130,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
int rc = 1;
unsigned long iflag;
+ pgp = &phba->port_gp[pring->ringno];
spin_lock_irqsave(&phba->hbalock, iflag);
pring->stats.iocb_event++;
@@ -1904,6 +2369,16 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
return rc;
}
+/**
+ * lpfc_sli_abort_iocb_ring: Abort all iocbs in the ring.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function aborts all iocbs in the given ring and frees all the iocb
+ * objects in txq. This function issues an abort iocb for all the iocb commands
+ * in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before
+ * the return of this function. The caller is not required to hold any locks.
+ **/
void
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
@@ -1943,6 +2418,83 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
}
+/**
+ * lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function flushes all iocbs in the fcp ring and frees all the iocb
+ * objects in txq and txcmplq. This function will not issue abort iocbs
+ * for all the iocb commands in txcmplq, they will just be returned with
+ * IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI
+ * slot has been permanently disabled.
+ **/
+void
+lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
+{
+ LIST_HEAD(txq);
+ LIST_HEAD(txcmplq);
+ struct lpfc_iocbq *iocb;
+ IOCB_t *cmd = NULL;
+ struct lpfc_sli *psli = &phba->sli;
+ struct lpfc_sli_ring *pring;
+
+ /* Currently, only one fcp ring */
+ pring = &psli->ring[psli->fcp_ring];
+
+ spin_lock_irq(&phba->hbalock);
+ /* Retrieve everything on txq */
+ list_splice_init(&pring->txq, &txq);
+ pring->txq_cnt = 0;
+
+ /* Retrieve everything on the txcmplq */
+ list_splice_init(&pring->txcmplq, &txcmplq);
+ pring->txcmplq_cnt = 0;
+ spin_unlock_irq(&phba->hbalock);
+
+ /* Flush the txq */
+ while (!list_empty(&txq)) {
+ iocb = list_get_first(&txq, struct lpfc_iocbq, list);
+ cmd = &iocb->iocb;
+ list_del_init(&iocb->list);
+
+ if (!iocb->iocb_cmpl)
+ lpfc_sli_release_iocbq(phba, iocb);
+ else {
+ cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+ cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
+ (iocb->iocb_cmpl) (phba, iocb, iocb);
+ }
+ }
+
+ /* Flush the txcmpq */
+ while (!list_empty(&txcmplq)) {
+ iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list);
+ cmd = &iocb->iocb;
+ list_del_init(&iocb->list);
+
+ if (!iocb->iocb_cmpl)
+ lpfc_sli_release_iocbq(phba, iocb);
+ else {
+ cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+ cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
+ (iocb->iocb_cmpl) (phba, iocb, iocb);
+ }
+ }
+}
+
+/**
+ * lpfc_sli_brdready: Check for host status bits.
+ * @phba: Pointer to HBA context object.
+ * @mask: Bit mask to be checked.
+ *
+ * This function reads the host status register and compares
+ * with the provided bit mask to check if HBA completed
+ * the restart. This function will wait in a loop for the
+ * HBA to complete restart. If the HBA does not restart within
+ * 15 iterations, the function will reset the HBA again. The
+ * function returns 1 when HBA fail to restart otherwise returns
+ * zero.
+ **/
int
lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
{
@@ -1990,6 +2542,13 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
#define BARRIER_TEST_PATTERN (0xdeadbeef)
+/**
+ * lpfc_reset_barrier: Make HBA ready for HBA reset.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called before resetting an HBA. This
+ * function requests HBA to quiesce DMAs before a reset.
+ **/
void lpfc_reset_barrier(struct lpfc_hba *phba)
{
uint32_t __iomem *resp_buf;
@@ -2063,6 +2622,17 @@ restore_hc:
readl(phba->HCregaddr); /* flush */
}
+/**
+ * lpfc_sli_brdkill: Issue a kill_board mailbox command.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function issues a kill_board mailbox command and waits for
+ * the error attention interrupt. This function is called for stopping
+ * the firmware processing. The caller is not required to hold any
+ * locks. This function calls lpfc_hba_down_post function to free
+ * any pending commands after the kill. The function will return 1 when it
+ * fails to kill the board else will return 0.
+ **/
int
lpfc_sli_brdkill(struct lpfc_hba *phba)
{
@@ -2139,6 +2709,17 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
return ha_copy & HA_ERATT ? 0 : 1;
}
+/**
+ * lpfc_sli_brdreset: Reset the HBA.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function resets the HBA by writing HC_INITFF to the control
+ * register. After the HBA resets, this function resets all the iocb ring
+ * indices. This function disables PCI layer parity checking during
+ * the reset.
+ * This function returns 0 always.
+ * The caller is not required to hold any locks.
+ **/
int
lpfc_sli_brdreset(struct lpfc_hba *phba)
{
@@ -2191,6 +2772,19 @@ lpfc_sli_brdreset(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_brdrestart: Restart the HBA.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called in the SLI initialization code path to
+ * restart the HBA. The caller is not required to hold any lock.
+ * This function writes MBX_RESTART mailbox command to the SLIM and
+ * resets the HBA. At the end of the function, it calls lpfc_hba_down_post
+ * function to free any pending commands. The function enables
+ * POST only during the first initialization. The function returns zero.
+ * The function does not guarantee completion of MBX_RESTART mailbox
+ * command before the return of this function.
+ **/
int
lpfc_sli_brdrestart(struct lpfc_hba *phba)
{
@@ -2251,6 +2845,16 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_chipset_init: Wait for the restart of the HBA after a restart.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called after a HBA restart to wait for successful
+ * restart of the HBA. Successful restart of the HBA is indicated by
+ * HS_FFRDY and HS_MBRDY bits. If the HBA fails to restart even after 15
+ * iteration, the function will restart the HBA again. The function returns
+ * zero if HBA successfully restarted else returns negative error code.
+ **/
static int
lpfc_sli_chipset_init(struct lpfc_hba *phba)
{
@@ -2336,12 +2940,25 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_hbq_count: Get the number of HBQs to be configured.
+ *
+ * This function calculates and returns the number of HBQs required to be
+ * configured.
+ **/
int
lpfc_sli_hbq_count(void)
{
return ARRAY_SIZE(lpfc_hbq_defs);
}
+/**
+ * lpfc_sli_hbq_entry_count: Calculate total number of hbq entries.
+ *
+ * This function adds the number of hbq entries in every HBQ to get
+ * the total number of hbq entries required for the HBA and returns
+ * the total count.
+ **/
static int
lpfc_sli_hbq_entry_count(void)
{
@@ -2354,12 +2971,27 @@ lpfc_sli_hbq_entry_count(void)
return count;
}
+/**
+ * lpfc_sli_hbq_size: Calculate memory required for all hbq entries.
+ *
+ * This function calculates amount of memory required for all hbq entries
+ * to be configured and returns the total memory required.
+ **/
int
lpfc_sli_hbq_size(void)
{
return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
}
+/**
+ * lpfc_sli_hbq_setup: configure and initialize HBQs.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called during the SLI initialization to configure
+ * all the HBQs and post buffers to the HBQ. The caller is not
+ * required to hold any locks. This function will return zero if successful
+ * else it will return negative error code.
+ **/
static int
lpfc_sli_hbq_setup(struct lpfc_hba *phba)
{
@@ -2415,15 +3047,26 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
mempool_free(pmb, phba->mbox_mem_pool);
/* Initially populate or replenish the HBQs */
- for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
- if (lpfc_sli_hbqbuf_init_hbqs(phba, hbqno))
- return -ENOMEM;
- }
+ for (hbqno = 0; hbqno < hbq_count; ++hbqno)
+ lpfc_sli_hbqbuf_init_hbqs(phba, hbqno);
return 0;
}
-static int
-lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
+/**
+ * lpfc_sli_config_port: Issue config port mailbox command.
+ * @phba: Pointer to HBA context object.
+ * @sli_mode: sli mode - 2/3
+ *
+ * This function is called by the sli intialization code path
+ * to issue config_port mailbox command. This function restarts the
+ * HBA firmware and issues a config_port mailbox command to configure
+ * the SLI interface in the sli mode specified by sli_mode
+ * variable. The caller is not required to hold any locks.
+ * The function returns 0 if successful, else returns negative error
+ * code.
+ **/
+int
+lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
{
LPFC_MBOXQ_t *pmb;
uint32_t resetcount = 0, rc = 0, done = 0;
@@ -2460,13 +3103,15 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
if (rc == -ERESTART) {
phba->link_state = LPFC_LINK_UNKNOWN;
continue;
- } else if (rc) {
+ } else if (rc)
break;
- }
-
phba->link_state = LPFC_INIT_MBX_CMDS;
lpfc_config_port(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+ phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |
+ LPFC_SLI3_HBQ_ENABLED |
+ LPFC_SLI3_CRP_ENABLED |
+ LPFC_SLI3_INB_ENABLED);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0442 Adapter failed to init, mbxCmd x%x "
@@ -2476,30 +3121,64 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
rc = -ENXIO;
- } else {
+ } else
done = 1;
- phba->max_vpi = (phba->max_vpi &&
- pmb->mb.un.varCfgPort.gmv) != 0
- ? pmb->mb.un.varCfgPort.max_vpi
- : 0;
- }
}
-
if (!done) {
rc = -EINVAL;
goto do_prep_failed;
}
-
- if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
- (!pmb->mb.un.varCfgPort.cMA)) {
- rc = -ENXIO;
+ if (pmb->mb.un.varCfgPort.sli_mode == 3) {
+ if (!pmb->mb.un.varCfgPort.cMA) {
+ rc = -ENXIO;
+ goto do_prep_failed;
+ }
+ if (phba->max_vpi && pmb->mb.un.varCfgPort.gmv) {
+ phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
+ phba->max_vpi = pmb->mb.un.varCfgPort.max_vpi;
+ } else
+ phba->max_vpi = 0;
+ if (pmb->mb.un.varCfgPort.gerbm)
+ phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
+ if (pmb->mb.un.varCfgPort.gcrp)
+ phba->sli3_options |= LPFC_SLI3_CRP_ENABLED;
+ if (pmb->mb.un.varCfgPort.ginb) {
+ phba->sli3_options |= LPFC_SLI3_INB_ENABLED;
+ phba->port_gp = phba->mbox->us.s3_inb_pgp.port;
+ phba->inb_ha_copy = &phba->mbox->us.s3_inb_pgp.ha_copy;
+ phba->inb_counter = &phba->mbox->us.s3_inb_pgp.counter;
+ phba->inb_last_counter =
+ phba->mbox->us.s3_inb_pgp.counter;
+ } else {
+ phba->port_gp = phba->mbox->us.s3_pgp.port;
+ phba->inb_ha_copy = NULL;
+ phba->inb_counter = NULL;
+ }
+ } else {
+ phba->port_gp = phba->mbox->us.s2.port;
+ phba->inb_ha_copy = NULL;
+ phba->inb_counter = NULL;
+ phba->max_vpi = 0;
}
-
do_prep_failed:
mempool_free(pmb, phba->mbox_mem_pool);
return rc;
}
+
+/**
+ * lpfc_sli_hba_setup: SLI intialization function.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is the main SLI intialization function. This function
+ * is called by the HBA intialization code, HBA reset code and HBA
+ * error attention handler code. Caller is not required to hold any
+ * locks. This function issues config_port mailbox command to configure
+ * the SLI, setup iocb rings and HBQ rings. In the end the function
+ * calls the config_port_post function to issue init_link mailbox
+ * command and to start the discovery. The function will return zero
+ * if successful, else it will return negative error code.
+ **/
int
lpfc_sli_hba_setup(struct lpfc_hba *phba)
{
@@ -2528,22 +3207,20 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
break;
}
- rc = lpfc_do_config_port(phba, mode);
+ rc = lpfc_sli_config_port(phba, mode);
+
if (rc && lpfc_sli_mode == 3)
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
"1820 Unable to select SLI-3. "
"Not supported by adapter.\n");
if (rc && mode != 2)
- rc = lpfc_do_config_port(phba, 2);
+ rc = lpfc_sli_config_port(phba, 2);
if (rc)
goto lpfc_sli_hba_setup_error;
if (phba->sli_rev == 3) {
phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
- phba->sli3_options |= LPFC_SLI3_ENABLED;
- phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
-
} else {
phba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
phba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
@@ -2558,8 +3235,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
if (rc)
goto lpfc_sli_hba_setup_error;
- /* Init HBQs */
-
+ /* Init HBQs */
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
rc = lpfc_sli_hbq_setup(phba);
if (rc)
@@ -2581,19 +3257,19 @@ lpfc_sli_hba_setup_error:
return rc;
}
-/*! lpfc_mbox_timeout
- *
- * \pre
- * \post
- * \param hba Pointer to per struct lpfc_hba structure
- * \param l1 Pointer to the driver's mailbox queue.
- * \return
- * void
- *
- * \b Description:
+
+/**
+ * lpfc_mbox_timeout: Timeout call back function for mbox timer.
+ * @ptr: context object - pointer to hba structure.
*
- * This routine handles mailbox timeout events at timer interrupt context.
- */
+ * This is the callback function for mailbox timer. The mailbox
+ * timer is armed when a new mailbox command is issued and the timer
+ * is deleted when the mailbox complete. The function is called by
+ * the kernel timer code when a mailbox does not complete within
+ * expected time. This function wakes up the worker thread to
+ * process the mailbox timeout and returns. All the processing is
+ * done by the worker thread function lpfc_mbox_timeout_handler.
+ **/
void
lpfc_mbox_timeout(unsigned long ptr)
{
@@ -2612,6 +3288,15 @@ lpfc_mbox_timeout(unsigned long ptr)
return;
}
+
+/**
+ * lpfc_mbox_timeout_handler: Worker thread function to handle mailbox timeout.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called from worker thread when a mailbox command times out.
+ * The caller is not required to hold any locks. This function will reset the
+ * HBA and recover all the pending commands.
+ **/
void
lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
{
@@ -2666,6 +3351,32 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
return;
}
+/**
+ * lpfc_sli_issue_mbox: Issue a mailbox command to firmware.
+ * @phba: Pointer to HBA context object.
+ * @pmbox: Pointer to mailbox object.
+ * @flag: Flag indicating how the mailbox need to be processed.
+ *
+ * This function is called by discovery code and HBA management code
+ * to submit a mailbox command to firmware. This function gets the
+ * hbalock to protect the data structures.
+ * The mailbox command can be submitted in polling mode, in which case
+ * this function will wait in a polling loop for the completion of the
+ * mailbox.
+ * If the mailbox is submitted in no_wait mode (not polling) the
+ * function will submit the command and returns immediately without waiting
+ * for the mailbox completion. The no_wait is supported only when HBA
+ * is in SLI2/SLI3 mode - interrupts are enabled.
+ * The SLI interface allows only one mailbox pending at a time. If the
+ * mailbox is issued in polling mode and there is already a mailbox
+ * pending, then the function will return an error. If the mailbox is issued
+ * in NO_WAIT mode and there is a mailbox pending already, the function
+ * will return MBX_BUSY after queuing the mailbox into mailbox queue.
+ * The sli layer owns the mailbox object until the completion of mailbox
+ * command if this function return MBX_BUSY or MBX_SUCCESS. For all other
+ * return codes the caller owns the mailbox command after the return of
+ * the function.
+ **/
int
lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
{
@@ -2676,7 +3387,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
int i;
unsigned long timeout;
unsigned long drvr_flag = 0;
- volatile uint32_t word0, ldata;
+ uint32_t word0, ldata;
void __iomem *to_slim;
int processing_queue = 0;
@@ -2836,12 +3547,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data to host SLIM area */
- lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(mb, phba->mbox, MAILBOX_CMD_SIZE);
} else {
if (mb->mbxCommand == MBX_CONFIG_PORT) {
/* copy command data into host mbox for cmpl */
- lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx,
- MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(mb, phba->mbox, MAILBOX_CMD_SIZE);
}
/* First copy mbox command data to HBA SLIM, skip past first
@@ -2851,7 +3561,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
MAILBOX_CMD_SIZE - sizeof (uint32_t));
/* Next copy over first word, with mbxOwner set */
- ldata = *((volatile uint32_t *)mb);
+ ldata = *((uint32_t *)mb);
to_slim = phba->MBslimaddr;
writel(ldata, to_slim);
readl(to_slim); /* flush */
@@ -2883,7 +3593,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First read mbox status word */
- word0 = *((volatile uint32_t *)&phba->slim2p->mbx);
+ word0 = *((uint32_t *)phba->mbox);
word0 = le32_to_cpu(word0);
} else {
/* First read mbox status word */
@@ -2922,12 +3632,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */
- word0 = *((volatile uint32_t *)
- &phba->slim2p->mbx);
+ word0 = *((uint32_t *)phba->mbox);
word0 = le32_to_cpu(word0);
if (mb->mbxCommand == MBX_CONFIG_PORT) {
MAILBOX_t *slimmb;
- volatile uint32_t slimword0;
+ uint32_t slimword0;
/* Check real SLIM for any errors */
slimword0 = readl(phba->MBslimaddr);
slimmb = (MAILBOX_t *) & slimword0;
@@ -2948,8 +3657,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* copy results back to user */
- lpfc_sli_pcimem_bcopy(&phba->slim2p->mbx, mb,
- MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(phba->mbox, mb, MAILBOX_CMD_SIZE);
} else {
/* First copy command data */
lpfc_memcpy_from_slim(mb, phba->MBslimaddr,
@@ -2980,9 +3688,16 @@ out_not_finished:
return MBX_NOT_FINISHED;
}
-/*
- * Caller needs to hold lock.
- */
+/**
+ * __lpfc_sli_ringtx_put: Add an iocb to the txq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @piocb: Pointer to address of newly added command iocb.
+ *
+ * This function is called with hbalock held to add a command
+ * iocb to the txq when SLI layer cannot submit the command iocb
+ * to the ring.
+ **/
static void
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
@@ -2992,6 +3707,23 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
pring->txq_cnt++;
}
+/**
+ * lpfc_sli_next_iocb: Get the next iocb in the txq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @piocb: Pointer to address of newly added command iocb.
+ *
+ * This function is called with hbalock held before a new
+ * iocb is submitted to the firmware. This function checks
+ * txq to flush the iocbs in txq to Firmware before
+ * submitting new iocbs to the Firmware.
+ * If there are iocbs in the txq which need to be submitted
+ * to firmware, lpfc_sli_next_iocb returns the first element
+ * of the txq after dequeuing it from txq.
+ * If there is no iocb in the txq then the function will return
+ * *piocb and *piocb is set to NULL. Caller needs to check
+ * *piocb to find if there are more commands in the txq.
+ **/
static struct lpfc_iocbq *
lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq **piocb)
@@ -3007,9 +3739,30 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return nextiocb;
}
-/*
- * Lockless version of lpfc_sli_issue_iocb.
- */
+/**
+ * __lpfc_sli_issue_iocb: Lockless version of lpfc_sli_issue_iocb.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @piocb: Pointer to command iocb.
+ * @flag: Flag indicating if this command can be put into txq.
+ *
+ * __lpfc_sli_issue_iocb is used by other functions in the driver
+ * to issue an iocb command to the HBA. If the PCI slot is recovering
+ * from error state or if HBA is resetting or if LPFC_STOP_IOCB_EVENT
+ * flag is turned on, the function returns IOCB_ERROR.
+ * When the link is down, this function allows only iocbs for
+ * posting buffers.
+ * This function finds next available slot in the command ring and
+ * posts the command to the available slot and writes the port
+ * attention register to request HBA start processing new iocb.
+ * If there is no slot available in the ring and
+ * flag & SLI_IOCB_RET_IOCB is set, the new iocb is added to the
+ * txq, otherwise the function returns IOCB_BUSY.
+ *
+ * This function is called with hbalock held.
+ * The function will return success after it successfully submit the
+ * iocb to firmware or after adding to the txq.
+ **/
static int
__lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb, uint32_t flag)
@@ -3052,6 +3805,16 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* can be issued if the link is not up.
*/
switch (piocb->iocb.ulpCommand) {
+ case CMD_GEN_REQUEST64_CR:
+ case CMD_GEN_REQUEST64_CX:
+ if (!(phba->sli.sli_flag & LPFC_MENLO_MAINT) ||
+ (piocb->iocb.un.genreq64.w5.hcsw.Rctl !=
+ FC_FCP_CMND) ||
+ (piocb->iocb.un.genreq64.w5.hcsw.Type !=
+ MENLO_TRANSPORT_TYPE))
+
+ goto iocb_busy;
+ break;
case CMD_QUE_RING_BUF_CN:
case CMD_QUE_RING_BUF64_CN:
/*
@@ -3106,6 +3869,19 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
+/**
+ * lpfc_sli_issue_iocb: Wrapper function for __lpfc_sli_issue_iocb.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @piocb: Pointer to command iocb.
+ * @flag: Flag indicating if this command can be put into txq.
+ *
+ * lpfc_sli_issue_iocb is a wrapper around __lpfc_sli_issue_iocb
+ * function. This function gets the hbalock and calls
+ * __lpfc_sli_issue_iocb function and will return the error returned
+ * by __lpfc_sli_issue_iocb function. This wrapper is used by
+ * functions which do not hold hbalock.
+ **/
int
lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb, uint32_t flag)
@@ -3120,6 +3896,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return rc;
}
+/**
+ * lpfc_extra_ring_setup: Extra ring setup function.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called while driver attaches with the
+ * HBA to setup the extra ring. The extra ring is used
+ * only when driver needs to support target mode functionality
+ * or IP over FC functionalities.
+ *
+ * This function is called with no lock held.
+ **/
static int
lpfc_extra_ring_setup( struct lpfc_hba *phba)
{
@@ -3155,6 +3942,19 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_async_event_handler: ASYNC iocb handler function.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @iocbq: Pointer to iocb object.
+ *
+ * This function is called by the slow ring event handler
+ * function when there is an ASYNC event iocb in the ring.
+ * This function is called with no lock held.
+ * Currently this function handles only temperature related
+ * ASYNC events. The function decodes the temperature sensor
+ * event message and posts events for the management applications.
+ **/
static void
lpfc_sli_async_event_handler(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq)
@@ -3210,6 +4010,17 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
}
+/**
+ * lpfc_sli_setup: SLI ring setup function.
+ * @phba: Pointer to HBA context object.
+ *
+ * lpfc_sli_setup sets up rings of the SLI interface with
+ * number of iocbs per ring and iotags. This function is
+ * called while driver attach to the HBA and before the
+ * interrupts are enabled. So there is no need for locking.
+ *
+ * This function always returns 0.
+ **/
int
lpfc_sli_setup(struct lpfc_hba *phba)
{
@@ -3321,6 +4132,17 @@ lpfc_sli_setup(struct lpfc_hba *phba)
return 0;
}
+/**
+ * lpfc_sli_queue_setup: Queue initialization function.
+ * @phba: Pointer to HBA context object.
+ *
+ * lpfc_sli_queue_setup sets up mailbox queues and iocb queues for each
+ * ring. This function also initializes ring indices of each ring.
+ * This function is called during the initialization of the SLI
+ * interface of an HBA.
+ * This function is called with no lock held and always returns
+ * 1.
+ **/
int
lpfc_sli_queue_setup(struct lpfc_hba *phba)
{
@@ -3349,6 +4171,23 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
return 1;
}
+/**
+ * lpfc_sli_host_down: Vport cleanup function.
+ * @vport: Pointer to virtual port object.
+ *
+ * lpfc_sli_host_down is called to clean up the resources
+ * associated with a vport before destroying virtual
+ * port data structures.
+ * This function does following operations:
+ * - Free discovery resources associated with this virtual
+ * port.
+ * - Free iocbs associated with this virtual port in
+ * the txq.
+ * - Send abort for all iocb commands associated with this
+ * vport in txcmplq.
+ *
+ * This function is called with no lock held and always returns 1.
+ **/
int
lpfc_sli_host_down(struct lpfc_vport *vport)
{
@@ -3411,6 +4250,21 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
return 1;
}
+/**
+ * lpfc_sli_hba_down: Resource cleanup function for the HBA.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function cleans up all iocb, buffers, mailbox commands
+ * while shutting down the HBA. This function is called with no
+ * lock held and always returns 1.
+ * This function does the following to cleanup driver resources:
+ * - Free discovery resources for each virtual port
+ * - Cleanup any pending fabric iocbs
+ * - Iterate through the iocb txq and free each entry
+ * in the list.
+ * - Free up any buffer posted to the HBA
+ * - Free mailbox commands in the mailbox queue.
+ **/
int
lpfc_sli_hba_down(struct lpfc_hba *phba)
{
@@ -3501,6 +4355,18 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
return 1;
}
+/**
+ * lpfc_sli_pcimem_bcopy: SLI memory copy function.
+ * @srcp: Source memory pointer.
+ * @destp: Destination memory pointer.
+ * @cnt: Number of words required to be copied.
+ *
+ * This function is used for copying data between driver memory
+ * and the SLI memory. This function also changes the endianness
+ * of each word if native endianness is different from SLI
+ * endianness. This function can be called with or without
+ * lock.
+ **/
void
lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
{
@@ -3518,6 +4384,17 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
}
}
+
+/**
+ * lpfc_sli_ringpostbuf_put: Function to add a buffer to postbufq.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @mp: Pointer to driver buffer object.
+ *
+ * This function is called with no lock held.
+ * It always return zero after adding the buffer to the postbufq
+ * buffer list.
+ **/
int
lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_dmabuf *mp)
@@ -3531,6 +4408,18 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 0;
}
+/**
+ * lpfc_sli_get_buffer_tag: Tag allocation function for a buffer posted
+ * using CMD_QUE_XRI64_CX iocb.
+ * @phba: Pointer to HBA context object.
+ *
+ * When HBQ is enabled, buffers are searched based on tags. This function
+ * allocates a tag for buffer posted using CMD_QUE_XRI64_CX iocb. The
+ * tag is bit wise or-ed with QUE_BUFTAG_BIT to make sure that the tag
+ * does not conflict with tags of buffer posted for unsolicited events.
+ * The function returns the allocated tag. The function is called with
+ * no locks held.
+ **/
uint32_t
lpfc_sli_get_buffer_tag(struct lpfc_hba *phba)
{
@@ -3545,6 +4434,22 @@ lpfc_sli_get_buffer_tag(struct lpfc_hba *phba)
return phba->buffer_tag_count;
}
+/**
+ * lpfc_sli_ring_taggedbuf_get: Search HBQ buffer associated with
+ * posted using CMD_QUE_XRI64_CX iocb.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @tag: Buffer tag.
+ *
+ * Buffers posted using CMD_QUE_XRI64_CX iocb are in pring->postbufq
+ * list. After HBA DMA data to these buffers, CMD_IOCB_RET_XRI64_CX
+ * iocb is posted to the response ring with the tag of the buffer.
+ * This function searches the pring->postbufq list using the tag
+ * to find buffer associated with CMD_IOCB_RET_XRI64_CX
+ * iocb. If the buffer is found then lpfc_dmabuf object of the
+ * buffer is returned to the caller else NULL is returned.
+ * This function is called with no lock held.
+ **/
struct lpfc_dmabuf *
lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint32_t tag)
@@ -3565,7 +4470,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0410 Cannot find virtual addr for buffer tag on "
+ "0402 Cannot find virtual addr for buffer tag on "
"ring %d Data x%lx x%p x%p x%x\n",
pring->ringno, (unsigned long) tag,
slp->next, slp->prev, pring->postbufq_cnt);
@@ -3573,6 +4478,23 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return NULL;
}
+/**
+ * lpfc_sli_ringpostbuf_get: SLI2 buffer search function for
+ * unsolicited ct and els events.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @phys: DMA address of the buffer.
+ *
+ * This function searches the buffer list using the dma_address
+ * of unsolicited event to find the driver's lpfc_dmabuf object
+ * corresponding to the dma_address. The function returns the
+ * lpfc_dmabuf object if a buffer is found else it returns NULL.
+ * This function is called by the ct and els unsolicited event
+ * handlers to get the buffer associated with the unsolicited
+ * event.
+ *
+ * This function is called with no lock held.
+ **/
struct lpfc_dmabuf *
lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
dma_addr_t phys)
@@ -3600,6 +4522,17 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return NULL;
}
+/**
+ * lpfc_sli_abort_els_cmpl: Completion handler for the els abort iocbs.
+ * @phba: Pointer to HBA context object.
+ * @cmdiocb: Pointer to driver command iocb object.
+ * @rspiocb: Pointer to driver response iocb object.
+ *
+ * This function is the completion handler for the abort iocbs for
+ * ELS commands. This function is called from the ELS ring event
+ * handler with no lock held. This function frees memory resources
+ * associated with the abort iocb.
+ **/
static void
lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -3665,6 +4598,17 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
+/**
+ * lpfc_ignore_els_cmpl: Completion handler for aborted ELS command.
+ * @phba: Pointer to HBA context object.
+ * @cmdiocb: Pointer to driver command iocb object.
+ * @rspiocb: Pointer to driver response iocb object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for ELS commands
+ * which are aborted. The function frees memory resources used for
+ * the aborted ELS commands.
+ **/
static void
lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -3673,7 +4617,7 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* ELS cmd tag <ulpIoTag> completes */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "0133 Ignoring ELS cmd tag x%x completion Data: "
+ "0139 Ignoring ELS cmd tag x%x completion Data: "
"x%x x%x x%x\n",
irsp->ulpIoTag, irsp->ulpStatus,
irsp->un.ulpWord[4], irsp->ulpTimeout);
@@ -3684,6 +4628,17 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
+/**
+ * lpfc_sli_issue_abort_iotag: Abort function for a command iocb.
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ * @cmdiocb: Pointer to driver command iocb object.
+ *
+ * This function issues an abort iocb for the provided command
+ * iocb. This function is called with hbalock held.
+ * The function returns 0 when it fails due to memory allocation
+ * failure or when the command iocb is an abort request.
+ **/
int
lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *cmdiocb)
@@ -3748,6 +4703,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
+ if (retval)
+ __lpfc_sli_release_iocbq(phba, abtsiocbp);
abort_iotag_exit:
/*
* Caller to this routine should check for IOCB_ERROR
@@ -3757,6 +4714,29 @@ abort_iotag_exit:
return retval;
}
+/**
+ * lpfc_sli_validate_fcp_iocb: Filtering function, used to find commands
+ * associated with a vport/SCSI target/lun.
+ * @iocbq: Pointer to driver iocb object.
+ * @vport: Pointer to driver virtual port object.
+ * @tgt_id: SCSI ID of the target.
+ * @lun_id: LUN ID of the scsi device.
+ * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST
+ *
+ * This function acts as iocb filter for functions which abort or count
+ * all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return
+ * 0 if the filtering criteria is met for the given iocb and will return
+ * 1 if the filtering criteria is not met.
+ * If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the
+ * given iocb is for the SCSI device specified by vport, tgt_id and
+ * lun_id parameter.
+ * If ctx_cmd == LPFC_CTX_TGT, the function returns 0 only if the
+ * given iocb is for the SCSI target specified by vport and tgt_id
+ * parameters.
+ * If ctx_cmd == LPFC_CTX_HOST, the function returns 0 only if the
+ * given iocb is for the SCSI host associated with the given vport.
+ * This function is called with no locks held.
+ **/
static int
lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
uint16_t tgt_id, uint64_t lun_id,
@@ -3800,6 +4780,25 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
return rc;
}
+/**
+ * lpfc_sli_sum_iocb: Function to count the number of FCP iocbs pending.
+ * @vport: Pointer to virtual port.
+ * @tgt_id: SCSI ID of the target.
+ * @lun_id: LUN ID of the scsi device.
+ * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
+ *
+ * This function returns number of FCP commands pending for the vport.
+ * When ctx_cmd == LPFC_CTX_LUN, the function returns number of FCP
+ * commands pending on the vport associated with SCSI device specified
+ * by tgt_id and lun_id parameters.
+ * When ctx_cmd == LPFC_CTX_TGT, the function returns number of FCP
+ * commands pending on the vport associated with SCSI target specified
+ * by tgt_id parameter.
+ * When ctx_cmd == LPFC_CTX_HOST, the function returns number of FCP
+ * commands pending on the vport.
+ * This function returns the number of iocbs which satisfy the filter.
+ * This function is called without any lock held.
+ **/
int
lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
lpfc_ctx_cmd ctx_cmd)
@@ -3819,6 +4818,17 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
return sum;
}
+/**
+ * lpfc_sli_abort_fcp_cmpl: Completion handler function for an aborted
+ * FCP iocb.
+ * @phba: Pointer to HBA context object
+ * @cmdiocb: Pointer to command iocb object.
+ * @rspiocb: Pointer to response iocb object.
+ *
+ * This function is called when an aborted FCP iocb completes. This
+ * function is called by the ring event handler with no lock held.
+ * This function frees the iocb.
+ **/
void
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -3827,6 +4837,28 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
+/**
+ * lpfc_sli_abort_iocb: This function issue abort for all SCSI commands
+ * pending on a SCSI host(vport)/target/lun.
+ * @vport: Pointer to virtual port.
+ * @pring: Pointer to driver SLI ring object.
+ * @tgt_id: SCSI ID of the target.
+ * @lun_id: LUN ID of the scsi device.
+ * @abort_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
+ *
+ * This function sends an abort command for every SCSI command
+ * associated with the given virtual port pending on the ring
+ * filtered by lpfc_sli_validate_fcp_iocb function.
+ * When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the
+ * FCP iocbs associated with lun specified by tgt_id and lun_id
+ * parameters
+ * When abort_cmd == LPFC_CTX_TGT, the function sends abort only to the
+ * FCP iocbs associated with SCSI target specified by tgt_id parameter.
+ * When abort_cmd == LPFC_CTX_HOST, the function sends abort to all
+ * FCP iocbs associated with virtual port.
+ * This function returns number of iocbs it failed to abort.
+ * This function is called with no locks held.
+ **/
int
lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd)
@@ -3878,6 +4910,24 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
return errcnt;
}
+/**
+ * lpfc_sli_wake_iocb_wait: iocb completion handler for iocb issued using
+ * lpfc_sli_issue_iocb_wait.
+ * @phba: Pointer to HBA context object.
+ * @cmdiocbq: Pointer to command iocb.
+ * @rspiocbq: Pointer to response iocb.
+ *
+ * This function is the completion handler for iocbs issued using
+ * lpfc_sli_issue_iocb_wait function. This function is called by the
+ * ring event handler function without any lock held. This function
+ * can be called from both worker thread context and interrupt
+ * context. This function also can be called from other thread which
+ * cleans up the SLI layer objects.
+ * This function copy the contents of the response iocb to the
+ * response iocb memory object provided by the caller of
+ * lpfc_sli_issue_iocb_wait and then wakes up the thread which
+ * sleeps for the iocb completion.
+ **/
static void
lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
@@ -3899,13 +4949,36 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
return;
}
-/*
- * Issue the caller's iocb and wait for its completion, but no longer than the
- * caller's timeout. Note that iocb_flags is cleared before the
- * lpfc_sli_issue_call since the wake routine sets a unique value and by
- * definition this is a wait function.
- */
-
+/**
+ * lpfc_sli_issue_iocb_wait: Synchronous function to issue iocb commands.
+ * @phba: Pointer to HBA context object..
+ * @pring: Pointer to sli ring.
+ * @piocb: Pointer to command iocb.
+ * @prspiocbq: Pointer to response iocb.
+ * @timeout: Timeout in number of seconds.
+ *
+ * This function issues the iocb to firmware and waits for the
+ * iocb to complete. If the iocb command is not
+ * completed within timeout seconds, it returns IOCB_TIMEDOUT.
+ * Caller should not free the iocb resources if this function
+ * returns IOCB_TIMEDOUT.
+ * The function waits for the iocb completion using an
+ * non-interruptible wait.
+ * This function will sleep while waiting for iocb completion.
+ * So, this function should not be called from any context which
+ * does not allow sleeping. Due to the same reason, this function
+ * cannot be called with interrupt disabled.
+ * This function assumes that the iocb completions occur while
+ * this function sleep. So, this function cannot be called from
+ * the thread which process iocb completion for this ring.
+ * This function clears the iocb_flag of the iocb object before
+ * issuing the iocb and the iocb completion handler sets this
+ * flag and wakes this thread when the iocb completes.
+ * The contents of the response iocb will be copied to prspiocbq
+ * by the completion handler when the command completes.
+ * This function returns IOCB_SUCCESS when success.
+ * This function is called with no lock held.
+ **/
int
lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
@@ -3963,7 +5036,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
}
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- ":0332 IOCB wait issue failed, Data x%x\n",
+ "0332 IOCB wait issue failed, Data x%x\n",
retval);
retval = IOCB_ERROR;
}
@@ -3983,6 +5056,32 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
return retval;
}
+/**
+ * lpfc_sli_issue_mbox_wait: Synchronous function to issue mailbox.
+ * @phba: Pointer to HBA context object.
+ * @pmboxq: Pointer to driver mailbox object.
+ * @timeout: Timeout in number of seconds.
+ *
+ * This function issues the mailbox to firmware and waits for the
+ * mailbox command to complete. If the mailbox command is not
+ * completed within timeout seconds, it returns MBX_TIMEOUT.
+ * The function waits for the mailbox completion using an
+ * interruptible wait. If the thread is woken up due to a
+ * signal, MBX_TIMEOUT error is returned to the caller. Caller
+ * should not free the mailbox resources, if this function returns
+ * MBX_TIMEOUT.
+ * This function will sleep while waiting for mailbox completion.
+ * So, this function should not be called from any context which
+ * does not allow sleeping. Due to the same reason, this function
+ * cannot be called with interrupt disabled.
+ * This function assumes that the mailbox completion occurs while
+ * this function sleep. So, this function cannot be called from
+ * the worker thread which processes mailbox completion.
+ * This function is called in the context of HBA management
+ * applications.
+ * This function returns MBX_SUCCESS when successful.
+ * This function is called with no lock held.
+ **/
int
lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
uint32_t timeout)
@@ -4027,6 +5126,18 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
return retval;
}
+/**
+ * lpfc_sli_flush_mbox_queue: mailbox queue cleanup function.
+ * @phba: Pointer to HBA context.
+ *
+ * This function is called to cleanup any pending mailbox
+ * objects in the driver queue before bringing the HBA offline.
+ * This function is called while resetting the HBA.
+ * The function is called without any lock held. The function
+ * takes hbalock to update SLI data structure.
+ * This function returns 1 when there is an active mailbox
+ * command pending else returns 0.
+ **/
int
lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
{
@@ -4058,8 +5169,74 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
}
+/**
+ * lpfc_sli_check_eratt: check error attention events
+ * @phba: Pointer to HBA context.
+ *
+ * This function is called form timer soft interrupt context to check HBA's
+ * error attention register bit for error attention events.
+ *
+ * This fucntion returns 1 when there is Error Attention in the Host Attention
+ * Register and returns 0 otherwise.
+ **/
+int
+lpfc_sli_check_eratt(struct lpfc_hba *phba)
+{
+ uint32_t ha_copy;
+
+ /* If somebody is waiting to handle an eratt, don't process it
+ * here. The brdkill function will do this.
+ */
+ if (phba->link_flag & LS_IGNORE_ERATT)
+ return 0;
+
+ /* Check if interrupt handler handles this ERATT */
+ spin_lock_irq(&phba->hbalock);
+ if (phba->hba_flag & HBA_ERATT_HANDLED) {
+ /* Interrupt handler has handled ERATT */
+ spin_unlock_irq(&phba->hbalock);
+ return 0;
+ }
+
+ /* Read chip Host Attention (HA) register */
+ ha_copy = readl(phba->HAregaddr);
+ if (ha_copy & HA_ERATT) {
+ /* Read host status register to retrieve error event */
+ lpfc_sli_read_hs(phba);
+ /* Set the driver HA work bitmap */
+ phba->work_ha |= HA_ERATT;
+ /* Indicate polling handles this ERATT */
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ spin_unlock_irq(&phba->hbalock);
+ return 1;
+ }
+ spin_unlock_irq(&phba->hbalock);
+ return 0;
+}
+
+/**
+ * lpfc_sp_intr_handler: The slow-path interrupt handler of lpfc driver.
+ * @irq: Interrupt number.
+ * @dev_id: The device context pointer.
+ *
+ * This function is directly called from the PCI layer as an interrupt
+ * service routine when the device is enabled with MSI-X multi-message
+ * interrupt mode and there are slow-path events in the HBA. However,
+ * when the device is enabled with either MSI or Pin-IRQ interrupt mode,
+ * this function is called as part of the device-level interrupt handler.
+ * When the PCI slot is in error recovery or the HBA is undergoing
+ * initialization, the interrupt handler will not process the interrupt.
+ * The link attention and ELS ring attention events are handled by the
+ * worker thread. The interrupt handler signals the worker thread and
+ * and returns for these events. This function is called without any
+ * lock held. It gets the hbalock to access and update SLI data
+ * structures.
+ *
+ * This function returns IRQ_HANDLED when interrupt is handled else it
+ * returns IRQ_NONE.
+ **/
irqreturn_t
-lpfc_intr_handler(int irq, void *dev_id)
+lpfc_sp_intr_handler(int irq, void *dev_id)
{
struct lpfc_hba *phba;
uint32_t ha_copy;
@@ -4078,48 +5255,52 @@ lpfc_intr_handler(int irq, void *dev_id)
* Get the driver's phba structure from the dev_id and
* assume the HBA is not interrupting.
*/
- phba = (struct lpfc_hba *) dev_id;
+ phba = (struct lpfc_hba *)dev_id;
if (unlikely(!phba))
return IRQ_NONE;
- /* If the pci channel is offline, ignore all the interrupts. */
- if (unlikely(pci_channel_offline(phba->pcidev)))
- return IRQ_NONE;
-
- phba->sli.slistat.sli_intr++;
-
/*
- * Call the HBA to see if it is interrupting. If not, don't claim
- * the interrupt
- */
-
- /* Ignore all interrupts during initialization. */
- if (unlikely(phba->link_state < LPFC_LINK_DOWN))
- return IRQ_NONE;
-
- /*
- * Read host attention register to determine interrupt source
- * Clear Attention Sources, except Error Attention (to
- * preserve status) and Link Attention
- */
- spin_lock(&phba->hbalock);
- ha_copy = readl(phba->HAregaddr);
- /* If somebody is waiting to handle an eratt don't process it
- * here. The brdkill function will do this.
+ * Stuff needs to be attented to when this function is invoked as an
+ * individual interrupt handler in MSI-X multi-message interrupt mode
*/
- if (phba->link_flag & LS_IGNORE_ERATT)
- ha_copy &= ~HA_ERATT;
- writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
- readl(phba->HAregaddr); /* flush */
- spin_unlock(&phba->hbalock);
-
- if (unlikely(!ha_copy))
- return IRQ_NONE;
+ if (phba->intr_type == MSIX) {
+ /* If the pci channel is offline, ignore all the interrupts */
+ if (unlikely(pci_channel_offline(phba->pcidev)))
+ return IRQ_NONE;
+ /* Update device-level interrupt statistics */
+ phba->sli.slistat.sli_intr++;
+ /* Ignore all interrupts during initialization. */
+ if (unlikely(phba->link_state < LPFC_LINK_DOWN))
+ return IRQ_NONE;
+ /* Need to read HA REG for slow-path events */
+ spin_lock(&phba->hbalock);
+ ha_copy = readl(phba->HAregaddr);
+ /* If somebody is waiting to handle an eratt don't process it
+ * here. The brdkill function will do this.
+ */
+ if (phba->link_flag & LS_IGNORE_ERATT)
+ ha_copy &= ~HA_ERATT;
+ /* Check the need for handling ERATT in interrupt handler */
+ if (ha_copy & HA_ERATT) {
+ if (phba->hba_flag & HBA_ERATT_HANDLED)
+ /* ERATT polling has handled ERATT */
+ ha_copy &= ~HA_ERATT;
+ else
+ /* Indicate interrupt handler handles ERATT */
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ }
+ /* Clear up only attention source related to slow-path */
+ writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
+ phba->HAregaddr);
+ readl(phba->HAregaddr); /* flush */
+ spin_unlock(&phba->hbalock);
+ } else
+ ha_copy = phba->ha_copy;
work_ha_copy = ha_copy & phba->work_ha_mask;
- if (unlikely(work_ha_copy)) {
+ if (work_ha_copy) {
if (work_ha_copy & HA_LATT) {
if (phba->sli.sli_flag & LPFC_PROCESS_LA) {
/*
@@ -4138,7 +5319,7 @@ lpfc_intr_handler(int irq, void *dev_id)
work_ha_copy &= ~HA_LATT;
}
- if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
+ if (work_ha_copy & ~(HA_ERATT | HA_MBATT | HA_LATT)) {
/*
* Turn off Slow Rings interrupts, LPFC_ELS_RING is
* the only slow ring.
@@ -4179,31 +5360,13 @@ lpfc_intr_handler(int irq, void *dev_id)
spin_unlock(&phba->hbalock);
}
}
-
- if (work_ha_copy & HA_ERATT) {
- /*
- * There was a link/board error. Read the
- * status register to retrieve the error event
- * and process it.
- */
- phba->sli.slistat.err_attn_event++;
- /* Save status info */
- phba->work_hs = readl(phba->HSregaddr);
- phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
- phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
-
- /* Clear Chip error bit */
- writel(HA_ERATT, phba->HAregaddr);
- readl(phba->HAregaddr); /* flush */
- phba->pport->stopped = 1;
- }
-
spin_lock(&phba->hbalock);
- if ((work_ha_copy & HA_MBATT) &&
- (phba->sli.mbox_active)) {
+ if (work_ha_copy & HA_ERATT)
+ lpfc_sli_read_hs(phba);
+ if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
pmb = phba->sli.mbox_active;
pmbox = &pmb->mb;
- mbox = &phba->slim2p->mbx;
+ mbox = phba->mbox;
vport = pmb->vport;
/* First check out the status word */
@@ -4270,7 +5433,7 @@ lpfc_intr_handler(int irq, void *dev_id)
lpfc_printf_log(phba,
KERN_ERR,
LOG_MBOX | LOG_SLI,
- "0306 rc should have"
+ "0350 rc should have"
"been MBX_BUSY");
goto send_current_mbox;
}
@@ -4283,6 +5446,7 @@ lpfc_intr_handler(int irq, void *dev_id)
}
} else
spin_unlock(&phba->hbalock);
+
if ((work_ha_copy & HA_MBATT) &&
(phba->sli.mbox_active == NULL)) {
send_current_mbox:
@@ -4302,15 +5466,74 @@ send_current_mbox:
spin_unlock(&phba->hbalock);
lpfc_worker_wake_up(phba);
}
+ return IRQ_HANDLED;
- ha_copy &= ~(phba->work_ha_mask);
+} /* lpfc_sp_intr_handler */
+
+/**
+ * lpfc_fp_intr_handler: The fast-path interrupt handler of lpfc driver.
+ * @irq: Interrupt number.
+ * @dev_id: The device context pointer.
+ *
+ * This function is directly called from the PCI layer as an interrupt
+ * service routine when the device is enabled with MSI-X multi-message
+ * interrupt mode and there is a fast-path FCP IOCB ring event in the
+ * HBA. However, when the device is enabled with either MSI or Pin-IRQ
+ * interrupt mode, this function is called as part of the device-level
+ * interrupt handler. When the PCI slot is in error recovery or the HBA
+ * is undergoing initialization, the interrupt handler will not process
+ * the interrupt. The SCSI FCP fast-path ring event are handled in the
+ * intrrupt context. This function is called without any lock held. It
+ * gets the hbalock to access and update SLI data structures.
+ *
+ * This function returns IRQ_HANDLED when interrupt is handled else it
+ * returns IRQ_NONE.
+ **/
+irqreturn_t
+lpfc_fp_intr_handler(int irq, void *dev_id)
+{
+ struct lpfc_hba *phba;
+ uint32_t ha_copy;
+ unsigned long status;
+
+ /* Get the driver's phba structure from the dev_id and
+ * assume the HBA is not interrupting.
+ */
+ phba = (struct lpfc_hba *) dev_id;
+
+ if (unlikely(!phba))
+ return IRQ_NONE;
+
+ /*
+ * Stuff needs to be attented to when this function is invoked as an
+ * individual interrupt handler in MSI-X multi-message interrupt mode
+ */
+ if (phba->intr_type == MSIX) {
+ /* If pci channel is offline, ignore all the interrupts */
+ if (unlikely(pci_channel_offline(phba->pcidev)))
+ return IRQ_NONE;
+ /* Update device-level interrupt statistics */
+ phba->sli.slistat.sli_intr++;
+ /* Ignore all interrupts during initialization. */
+ if (unlikely(phba->link_state < LPFC_LINK_DOWN))
+ return IRQ_NONE;
+ /* Need to read HA REG for FCP ring and other ring events */
+ ha_copy = readl(phba->HAregaddr);
+ /* Clear up only attention source related to fast-path */
+ spin_lock(&phba->hbalock);
+ writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
+ phba->HAregaddr);
+ readl(phba->HAregaddr); /* flush */
+ spin_unlock(&phba->hbalock);
+ } else
+ ha_copy = phba->ha_copy;
/*
- * Process all events on FCP ring. Take the optimized path for
- * FCP IO. Any other IO is slow path and is handled by
- * the worker thread.
+ * Process all events on FCP ring. Take the optimized path for FCP IO.
*/
- status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
+ ha_copy &= ~(phba->work_ha_mask);
+
+ status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
status >>= (4*LPFC_FCP_RING);
if (status & HA_RXMASK)
lpfc_sli_handle_fast_ring_event(phba,
@@ -4319,11 +5542,10 @@ send_current_mbox:
if (phba->cfg_multi_ring_support == 2) {
/*
- * Process all events on extra ring. Take the optimized path
- * for extra ring IO. Any other IO is slow path and is handled
- * by the worker thread.
+ * Process all events on extra ring. Take the optimized path
+ * for extra ring IO.
*/
- status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
+ status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
status >>= (4*LPFC_EXTRA_RING);
if (status & HA_RXMASK) {
lpfc_sli_handle_fast_ring_event(phba,
@@ -4332,5 +5554,106 @@ send_current_mbox:
}
}
return IRQ_HANDLED;
+} /* lpfc_fp_intr_handler */
+
+/**
+ * lpfc_intr_handler: The device-level interrupt handler of lpfc driver.
+ * @irq: Interrupt number.
+ * @dev_id: The device context pointer.
+ *
+ * This function is the device-level interrupt handler called from the PCI
+ * layer when either MSI or Pin-IRQ interrupt mode is enabled and there is
+ * an event in the HBA which requires driver attention. This function
+ * invokes the slow-path interrupt attention handling function and fast-path
+ * interrupt attention handling function in turn to process the relevant
+ * HBA attention events. This function is called without any lock held. It
+ * gets the hbalock to access and update SLI data structures.
+ *
+ * This function returns IRQ_HANDLED when interrupt is handled, else it
+ * returns IRQ_NONE.
+ **/
+irqreturn_t
+lpfc_intr_handler(int irq, void *dev_id)
+{
+ struct lpfc_hba *phba;
+ irqreturn_t sp_irq_rc, fp_irq_rc;
+ unsigned long status1, status2;
+
+ /*
+ * Get the driver's phba structure from the dev_id and
+ * assume the HBA is not interrupting.
+ */
+ phba = (struct lpfc_hba *) dev_id;
+
+ if (unlikely(!phba))
+ return IRQ_NONE;
+
+ /* If the pci channel is offline, ignore all the interrupts. */
+ if (unlikely(pci_channel_offline(phba->pcidev)))
+ return IRQ_NONE;
+
+ /* Update device level interrupt statistics */
+ phba->sli.slistat.sli_intr++;
+
+ /* Ignore all interrupts during initialization. */
+ if (unlikely(phba->link_state < LPFC_LINK_DOWN))
+ return IRQ_NONE;
+
+ spin_lock(&phba->hbalock);
+ phba->ha_copy = readl(phba->HAregaddr);
+ if (unlikely(!phba->ha_copy)) {
+ spin_unlock(&phba->hbalock);
+ return IRQ_NONE;
+ } else if (phba->ha_copy & HA_ERATT) {
+ if (phba->hba_flag & HBA_ERATT_HANDLED)
+ /* ERATT polling has handled ERATT */
+ phba->ha_copy &= ~HA_ERATT;
+ else
+ /* Indicate interrupt handler handles ERATT */
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ }
+
+ /* Clear attention sources except link and error attentions */
+ writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
+ readl(phba->HAregaddr); /* flush */
+ spin_unlock(&phba->hbalock);
+
+ /*
+ * Invokes slow-path host attention interrupt handling as appropriate.
+ */
+
+ /* status of events with mailbox and link attention */
+ status1 = phba->ha_copy & (HA_MBATT | HA_LATT | HA_ERATT);
+
+ /* status of events with ELS ring */
+ status2 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
+ status2 >>= (4*LPFC_ELS_RING);
+
+ if (status1 || (status2 & HA_RXMASK))
+ sp_irq_rc = lpfc_sp_intr_handler(irq, dev_id);
+ else
+ sp_irq_rc = IRQ_NONE;
+
+ /*
+ * Invoke fast-path host attention interrupt handling as appropriate.
+ */
+
+ /* status of events with FCP ring */
+ status1 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
+ status1 >>= (4*LPFC_FCP_RING);
+
+ /* status of events with extra ring */
+ if (phba->cfg_multi_ring_support == 2) {
+ status2 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
+ status2 >>= (4*LPFC_EXTRA_RING);
+ } else
+ status2 = 0;
+
+ if ((status1 & HA_RXMASK) || (status2 & HA_RXMASK))
+ fp_irq_rc = lpfc_fp_intr_handler(irq, dev_id);
+ else
+ fp_irq_rc = IRQ_NONE;
-} /* lpfc_intr_handler */
+ /* Return device-level interrupt handling status */
+ return (sp_irq_rc == IRQ_HANDLED) ? sp_irq_rc : fp_irq_rc;
+} /* lpfc_intr_handler */
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 7249fd252cb..883938652a6 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -233,6 +233,7 @@ struct lpfc_sli {
#define LPFC_SLI2_ACTIVE 0x200 /* SLI2 overlay in firmware is active */
#define LPFC_PROCESS_LA 0x400 /* Able to process link attention */
#define LPFC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
+#define LPFC_MENLO_MAINT 0x1000 /* need for menl fw download */
struct lpfc_sli_ring ring[LPFC_MAX_RING];
int fcp_ring; /* ring used for FCP initiator commands */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index ad24cacfbe1..cc43e9de22c 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,9 +18,11 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.2.7"
+#define LPFC_DRIVER_VERSION "8.2.8"
-#define LPFC_DRIVER_NAME "lpfc"
+#define LPFC_DRIVER_NAME "lpfc"
+#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
+#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 109f89d9883..a7de1cc02b4 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -34,6 +34,7 @@
#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
#include "lpfc_sli.h"
+#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
@@ -204,6 +205,77 @@ lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
return 1;
}
+/**
+ * lpfc_discovery_wait: Wait for driver discovery to quiesce.
+ * @vport: The virtual port for which this call is being executed.
+ *
+ * This driver calls this routine specifically from lpfc_vport_delete
+ * to enforce a synchronous execution of vport
+ * delete relative to discovery activities. The
+ * lpfc_vport_delete routine should not return until it
+ * can reasonably guarantee that discovery has quiesced.
+ * Post FDISC LOGO, the driver must wait until its SAN teardown is
+ * complete and all resources recovered before allowing
+ * cleanup.
+ *
+ * This routine does not require any locks held.
+ **/
+static void lpfc_discovery_wait(struct lpfc_vport *vport)
+{
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t wait_flags = 0;
+ unsigned long wait_time_max;
+ unsigned long start_time;
+
+ wait_flags = FC_RSCN_MODE | FC_RSCN_DISCOVERY | FC_NLP_MORE |
+ FC_RSCN_DEFERRED | FC_NDISC_ACTIVE | FC_DISC_TMO;
+
+ /*
+ * The time constraint on this loop is a balance between the
+ * fabric RA_TOV value and dev_loss tmo. The driver's
+ * devloss_tmo is 10 giving this loop a 3x multiplier minimally.
+ */
+ wait_time_max = msecs_to_jiffies(((phba->fc_ratov * 3) + 3) * 1000);
+ wait_time_max += jiffies;
+ start_time = jiffies;
+ while (time_before(jiffies, wait_time_max)) {
+ if ((vport->num_disc_nodes > 0) ||
+ (vport->fc_flag & wait_flags) ||
+ ((vport->port_state > LPFC_VPORT_FAILED) &&
+ (vport->port_state < LPFC_VPORT_READY))) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_VPORT,
+ "1833 Vport discovery quiesce Wait:"
+ " vpi x%x state x%x fc_flags x%x"
+ " num_nodes x%x, waiting 1000 msecs"
+ " total wait msecs x%x\n",
+ vport->vpi, vport->port_state,
+ vport->fc_flag, vport->num_disc_nodes,
+ jiffies_to_msecs(jiffies - start_time));
+ msleep(1000);
+ } else {
+ /* Base case. Wait variants satisfied. Break out */
+ lpfc_printf_log(phba, KERN_INFO, LOG_VPORT,
+ "1834 Vport discovery quiesced:"
+ " vpi x%x state x%x fc_flags x%x"
+ " wait msecs x%x\n",
+ vport->vpi, vport->port_state,
+ vport->fc_flag,
+ jiffies_to_msecs(jiffies
+ - start_time));
+ break;
+ }
+ }
+
+ if (time_after(jiffies, wait_time_max))
+ lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ "1835 Vport discovery quiesce failed:"
+ " vpi x%x state x%x fc_flags x%x"
+ " wait msecs x%x\n",
+ vport->vpi, vport->port_state,
+ vport->fc_flag,
+ jiffies_to_msecs(jiffies - start_time));
+}
+
int
lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
{
@@ -506,8 +578,12 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
* initiated after we've disposed of all other resources associated
* with the port.
*/
- if (!scsi_host_get(shost) || !scsi_host_get(shost))
+ if (!scsi_host_get(shost))
+ return VPORT_INVAL;
+ if (!scsi_host_get(shost)) {
+ scsi_host_put(shost);
return VPORT_INVAL;
+ }
spin_lock_irq(&phba->hbalock);
vport->load_flag |= FC_UNLOADING;
spin_unlock_irq(&phba->hbalock);
@@ -597,11 +673,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
}
vport->unreg_vpi_cmpl = VPORT_INVAL;
timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+ goto skip_logo;
if (!lpfc_issue_els_npiv_logo(vport, ndlp))
while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
timeout = schedule_timeout(timeout);
}
+ if (!(phba->pport->load_flag & FC_UNLOADING))
+ lpfc_discovery_wait(vport);
+
skip_logo:
lpfc_cleanup(vport);
lpfc_sli_host_down(vport);
@@ -615,8 +696,10 @@ skip_logo:
* Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi)
* does the scsi_host_put() to release the vport.
*/
- lpfc_mbx_unreg_vpi(vport);
- }
+ if (lpfc_mbx_unreg_vpi(vport))
+ scsi_host_put(shost);
+ } else
+ scsi_host_put(shost);
lpfc_free_vpi(phba, vport->vpi);
vport->work_port_events = 0;
@@ -663,3 +746,82 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
scsi_host_put(lpfc_shost_from_vport(vports[i]));
kfree(vports);
}
+
+
+/**
+ * lpfc_vport_reset_stat_data: Reset the statistical data for the vport.
+ * @vport: Pointer to vport object.
+ *
+ * This function resets the statistical data for the vport. This function
+ * is called with the host_lock held
+ **/
+void
+lpfc_vport_reset_stat_data(struct lpfc_vport *vport)
+{
+ struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
+
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
+ if (ndlp->lat_data)
+ memset(ndlp->lat_data, 0, LPFC_MAX_BUCKET_COUNT *
+ sizeof(struct lpfc_scsicmd_bkt));
+ }
+}
+
+
+/**
+ * lpfc_alloc_bucket: Allocate data buffer required for collecting
+ * statistical data.
+ * @vport: Pointer to vport object.
+ *
+ * This function allocates data buffer required for all the FC
+ * nodes of the vport to collect statistical data.
+ **/
+void
+lpfc_alloc_bucket(struct lpfc_vport *vport)
+{
+ struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
+
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
+
+ kfree(ndlp->lat_data);
+ ndlp->lat_data = NULL;
+
+ if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
+ ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
+ sizeof(struct lpfc_scsicmd_bkt),
+ GFP_ATOMIC);
+
+ if (!ndlp->lat_data)
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
+ "0287 lpfc_alloc_bucket failed to "
+ "allocate statistical data buffer DID "
+ "0x%x\n", ndlp->nlp_DID);
+ }
+ }
+}
+
+/**
+ * lpfc_free_bucket: Free data buffer required for collecting
+ * statistical data.
+ * @vport: Pointer to vport object.
+ *
+ * Th function frees statistical data buffer of all the FC
+ * nodes of the vport.
+ **/
+void
+lpfc_free_bucket(struct lpfc_vport *vport)
+{
+ struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
+
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
+
+ kfree(ndlp->lat_data);
+ ndlp->lat_data = NULL;
+ }
+}
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h
index 96c445333b6..90828340ace 100644
--- a/drivers/scsi/lpfc/lpfc_vport.h
+++ b/drivers/scsi/lpfc/lpfc_vport.h
@@ -112,4 +112,8 @@ struct vport_cmd_tag {
void lpfc_vport_set_state(struct lpfc_vport *vport,
enum fc_vport_state new_state);
+void lpfc_vport_reset_stat_data(struct lpfc_vport *);
+void lpfc_alloc_bucket(struct lpfc_vport *);
+void lpfc_free_bucket(struct lpfc_vport *);
+
#endif /* H_LPFC_VPORT */
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 97b763378e7..afe1de99876 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1167,7 +1167,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
* cmd has not been completed within the timeout period.
*/
static enum
-scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
{
struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
struct megasas_instance *instance;
@@ -1175,7 +1175,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
if (time_after(jiffies, scmd->jiffies_at_alloc +
(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
- return EH_NOT_HANDLED;
+ return BLK_EH_NOT_HANDLED;
}
instance = cmd->instance;
@@ -1189,7 +1189,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
spin_unlock_irqrestore(instance->host->host_lock, flags);
}
- return EH_RESET_TIMER;
+ return BLK_EH_RESET_TIMER;
}
/**
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index c57c94c0ffd..3b7240e4081 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -4170,8 +4170,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**
**----------------------------------------------------
*/
- if (np->settle_time && cmd->timeout_per_command >= HZ) {
- u_long tlimit = jiffies + cmd->timeout_per_command - HZ;
+ if (np->settle_time && cmd->request->timeout >= HZ) {
+ u_long tlimit = jiffies + cmd->request->timeout - HZ;
if (time_after(np->settle_time, tlimit))
np->settle_time = tlimit;
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 1c79f9794f4..0ea78d9a37d 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5708,7 +5708,8 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S
struct device *osst_member;
int err;
- osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name);
+ osst_member = device_create(osst_sysfs_class, device, dev, STp,
+ "%s", name);
if (IS_ERR(osst_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return PTR_ERR(osst_member);
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 2dd0dc9a9ae..165ff884f48 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -140,44 +140,41 @@ static void aha152x_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int aha152x_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ /* For New Media T&J, look for a SCSI window */
+ if (cfg->io.win[0].len >= 0x20)
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ else if ((cfg->io.nwin > 1) &&
+ (cfg->io.win[1].len >= 0x20))
+ p_dev->io.BasePort1 = cfg->io.win[1].base;
+ if ((cfg->io.nwin > 0) &&
+ (p_dev->io.BasePort1 < 0xffff)) {
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -EINVAL;
+}
+
static int aha152x_config_cs(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
struct aha152x_setup s;
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn;
- u_char tuple_data[64];
+ int last_ret, last_fn;
struct Scsi_Host *host;
-
+
DEBUG(0, "aha152x_config(0x%p)\n", link);
- tuple.TupleData = tuple_data;
- tuple.TupleDataMax = 64;
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
- /* For New Media T&J, look for a SCSI window */
- if (parse.cftable_entry.io.win[0].len >= 0x20)
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- else if ((parse.cftable_entry.io.nwin > 1) &&
- (parse.cftable_entry.io.win[1].len >= 0x20))
- link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
- if ((parse.cftable_entry.io.nwin > 0) &&
- (link->io.BasePort1 < 0xffff)) {
- link->conf.ConfigIndex = parse.cftable_entry.index;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
+ if (last_ret) {
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
-
+
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@@ -208,6 +205,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
cs_failed:
cs_error(link, last_fn, last_ret);
+failed:
aha152x_release_cs(link);
return -ENODEV;
}
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index d8b99351b05..06254f46a0d 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -123,34 +123,30 @@ static void fdomain_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int fdomain_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
+
static int fdomain_config(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn;
- u_char tuple_data[64];
+ int last_ret, last_fn;
char str[22];
struct Scsi_Host *host;
DEBUG(0, "fdomain_config(0x%p)\n", link);
- tuple.TupleData = tuple_data;
- tuple.TupleDataMax = 64;
- tuple.TupleOffset = 0;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
- link->conf.ConfigIndex = parse.cftable_entry.index;
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ last_ret = pcmcia_loop_config(link, fdomain_config_check, NULL);
+ if (last_ret) {
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -181,6 +177,7 @@ static int fdomain_config(struct pcmcia_device *link)
cs_failed:
cs_error(link, last_fn, last_ret);
+failed:
fdomain_release(link);
return -ENODEV;
} /* fdomain_config */
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 24e6cb8396e..11a61ea8d5d 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1606,133 +1606,129 @@ static void nsp_cs_detach(struct pcmcia_device *link)
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
======================================================================*/
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-/*====================================================================*/
-static int nsp_cs_config(struct pcmcia_device *link)
-{
- int ret;
- scsi_info_t *info = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int last_ret, last_fn;
- unsigned char tuple_data[64];
- config_info_t conf;
- win_req_t req;
- memreq_t map;
- cistpl_cftable_entry_t dflt = { 0 };
- struct Scsi_Host *host;
- nsp_hw_data *data = &nsp_data_base;
-
- nsp_dbg(NSP_DEBUG_INIT, "in");
-
- tuple.Attributes = 0;
- tuple.TupleData = tuple_data;
- tuple.TupleDataMax = sizeof(tuple_data);
- tuple.TupleOffset = 0;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+struct nsp_cs_configdata {
+ nsp_hw_data *data;
+ win_req_t req;
+};
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
+static int nsp_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ struct nsp_cs_configdata *cfg_mem = priv_data;
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
- if (cfg->index == 0) { goto next_entry; }
- link->conf.ConfigIndex = cfg->index;
+ if (cfg->index == 0)
+ return -ENODEV;
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
+ }
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
- goto next_entry;
- }
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
+ else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp =
+ p_dev->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
/* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
- link->conf.Attributes |= CONF_ENABLE_IRQ;
- }
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
goto next_entry;
}
- if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
- cistpl_mem_t *mem =
- (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- req.Attributes |= WIN_ENABLE;
- req.Base = mem->win[0].host_addr;
- req.Size = mem->win[0].len;
- if (req.Size < 0x1000) {
- req.Size = 0x1000;
- }
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link, &req, &link->win) != 0)
+ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+ memreq_t map;
+ cistpl_mem_t *mem =
+ (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+ cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+ cfg_mem->req.Attributes |= WIN_ENABLE;
+ cfg_mem->req.Base = mem->win[0].host_addr;
+ cfg_mem->req.Size = mem->win[0].len;
+ if (cfg_mem->req.Size < 0x1000)
+ cfg_mem->req.Size = 0x1000;
+ cfg_mem->req.AccessSpeed = 0;
+ if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
+ if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
goto next_entry;
- data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
- data->MmioLength = req.Size;
+ cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
+ cfg_mem->data->MmioLength = cfg_mem->req.Size;
}
/* If we got this far, we're cool! */
- break;
-
- next_entry:
- nsp_dbg(NSP_DEBUG_INIT, "next");
- pcmcia_disable_device(link);
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ return 0;
}
+next_entry:
+ nsp_dbg(NSP_DEBUG_INIT, "next");
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+}
+
+static int nsp_cs_config(struct pcmcia_device *link)
+{
+ int ret;
+ scsi_info_t *info = link->priv;
+ struct nsp_cs_configdata *cfg_mem;
+ struct Scsi_Host *host;
+ nsp_hw_data *data = &nsp_data_base;
+
+ nsp_dbg(NSP_DEBUG_INIT, "in");
+
+ cfg_mem = kzalloc(sizeof(cfg_mem), GFP_KERNEL);
+ if (!cfg_mem)
+ return -ENOMEM;
+ cfg_mem->data = data;
+
+ ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+ goto cs_failed;
+
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ if (pcmcia_request_irq(link, &link->irq))
+ goto cs_failed;
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
+ ret = pcmcia_request_configuration(link, &link->conf);
+ if (ret)
+ goto cs_failed;
if (free_ports) {
if (link->io.BasePort1) {
@@ -1790,20 +1786,20 @@ static int nsp_cs_config(struct pcmcia_device *link)
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
if (link->win)
- printk(", mem 0x%06lx-0x%06lx", req.Base,
- req.Base+req.Size-1);
+ printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
+ cfg_mem->req.Base+cfg_mem->req.Size-1);
printk("\n");
+ kfree(cfg_mem);
return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
- cs_error(link, last_fn, last_ret);
nsp_cs_release(link);
+ kfree(cfg_mem);
return -ENODEV;
} /* nsp_cs_config */
-#undef CS_CHECK
/*======================================================================
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 67c5a58d17d..20c3e5e6d88 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -195,39 +195,33 @@ static void qlogic_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int qlogic_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ p_dev->io.NumPorts1 = cfg->io.win[0].len;
+
+ if (p_dev->io.BasePort1 == 0)
+ return -ENODEV;
+
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int qlogic_config(struct pcmcia_device * link)
{
scsi_info_t *info = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn;
- unsigned short tuple_data[32];
+ int last_ret, last_fn;
struct Scsi_Host *host;
DEBUG(0, "qlogic_config(0x%p)\n", link);
- info->manf_id = link->manf_id;
-
- tuple.TupleData = (cisdata_t *) tuple_data;
- tuple.TupleDataMax = 64;
- tuple.TupleOffset = 0;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
- link->conf.ConfigIndex = parse.cftable_entry.index;
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
- if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- break;
- }
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ last_ret = pcmcia_loop_config(link, qlogic_config_check, NULL);
+ if (last_ret) {
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -262,6 +256,7 @@ static int qlogic_config(struct pcmcia_device * link)
cs_failed:
cs_error(link, last_fn, last_ret);
pcmcia_disable_device(link);
+failed:
return -ENODEV;
} /* qlogic_config */
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 0be232b58ff..b330c11a175 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -700,15 +700,27 @@ static struct scsi_host_template sym53c500_driver_template = {
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int SYM53C500_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ p_dev->io.BasePort1 = cfg->io.win[0].base;
+ p_dev->io.NumPorts1 = cfg->io.win[0].len;
+
+ if (p_dev->io.BasePort1 == 0)
+ return -ENODEV;
+
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int
SYM53C500_config(struct pcmcia_device *link)
{
struct scsi_info_t *info = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn;
+ int last_ret, last_fn;
int irq_level, port_base;
- unsigned short tuple_data[32];
struct Scsi_Host *host;
struct scsi_host_template *tpnt = &sym53c500_driver_template;
struct sym53c500_data *data;
@@ -717,27 +729,10 @@ SYM53C500_config(struct pcmcia_device *link)
info->manf_id = link->manf_id;
- tuple.TupleData = (cisdata_t *)tuple_data;
- tuple.TupleDataMax = 64;
- tuple.TupleOffset = 0;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
- link->conf.ConfigIndex = parse.cftable_entry.index;
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-
- if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- break;
- }
-next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ last_ret = pcmcia_loop_config(link, SYM53C500_config_check, NULL);
+ if (last_ret) {
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -831,6 +826,7 @@ err_release:
cs_failed:
cs_error(link, last_fn, last_ret);
+failed:
SYM53C500_release(link);
return -ENODEV;
} /* SYM53C500_config */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 37f9ba0cd79..b6cd12b2e99 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2845,7 +2845,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
- pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ);
+ pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ);
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
@@ -3114,7 +3114,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
- pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ);
+ pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ);
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 45e7dcb4b34..ed731968f15 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -292,10 +292,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
valid = 0;
if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
valid = 1;
- else if (start == (FA_BOOT_CODE_ADDR*4) ||
- start == (FA_RISC_CODE_ADDR*4))
+ else if (start == (ha->flt_region_boot * 4) ||
+ start == (ha->flt_region_fw * 4))
valid = 1;
- else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4))
+ else if (IS_QLA25XX(ha) &&
+ start == (ha->flt_region_vpd_nvram * 4))
valid = 1;
if (!valid) {
qla_printk(KERN_WARNING, ha,
@@ -1005,7 +1006,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
}
qla2x00_abort_fcport_cmds(fcport);
- scsi_target_unblock(&rport->dev);
}
static int
@@ -1065,6 +1065,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat->dumped_frames = stats->dumped_frames;
pfc_host_stat->nos_count = stats->nos_rcvd;
}
+ pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20;
+ pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20;
done_free:
dma_pool_free(ha->s_dma_pool, stats, stats_dma);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 94a720eabfd..83c81921677 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -25,7 +25,6 @@
#include <linux/firmware.h>
#include <linux/aer.h>
#include <linux/mutex.h>
-#include <linux/semaphore.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -2157,6 +2156,8 @@ struct qla_chip_state_84xx {
struct qla_statistics {
uint32_t total_isp_aborts;
+ uint64_t input_bytes;
+ uint64_t output_bytes;
};
/*
@@ -2238,6 +2239,7 @@ typedef struct scsi_qla_host {
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
#define UNLOADING 29
+#define NPIV_CONFIG_NEEDED 30
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@@ -2507,7 +2509,6 @@ typedef struct scsi_qla_host {
uint64_t fce_wr, fce_rd;
struct mutex fce_mutex;
- uint32_t hw_event_start;
uint32_t hw_event_ptr;
uint32_t hw_event_pause_errors;
@@ -2553,6 +2554,14 @@ typedef struct scsi_qla_host {
uint32_t fdt_unprotect_sec_cmd;
uint32_t fdt_protect_sec_cmd;
+ uint32_t flt_region_flt;
+ uint32_t flt_region_fdt;
+ uint32_t flt_region_boot;
+ uint32_t flt_region_fw;
+ uint32_t flt_region_vpd_nvram;
+ uint32_t flt_region_hw_event;
+ uint32_t flt_region_npiv_conf;
+
/* Needed for BEACON */
uint16_t beacon_blink_led;
uint8_t beacon_color_state;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index cf194517400..d1d14202575 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -789,14 +789,23 @@ struct device_reg_24xx {
#define FA_RISC_CODE_ADDR 0x20000
#define FA_RISC_CODE_SEGMENTS 2
+#define FA_FLASH_DESCR_ADDR_24 0x11000
+#define FA_FLASH_LAYOUT_ADDR_24 0x11400
+#define FA_NPIV_CONF0_ADDR_24 0x16000
+#define FA_NPIV_CONF1_ADDR_24 0x17000
+
#define FA_FW_AREA_ADDR 0x40000
#define FA_VPD_NVRAM_ADDR 0x48000
#define FA_FEATURE_ADDR 0x4C000
#define FA_FLASH_DESCR_ADDR 0x50000
+#define FA_FLASH_LAYOUT_ADDR 0x50400
#define FA_HW_EVENT0_ADDR 0x54000
-#define FA_HW_EVENT1_ADDR 0x54200
+#define FA_HW_EVENT1_ADDR 0x54400
#define FA_HW_EVENT_SIZE 0x200
#define FA_HW_EVENT_ENTRY_SIZE 4
+#define FA_NPIV_CONF0_ADDR 0x5C000
+#define FA_NPIV_CONF1_ADDR 0x5D000
+
/*
* Flash Error Log Event Codes.
*/
@@ -806,10 +815,6 @@ struct device_reg_24xx {
#define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023
#define HW_EVENT_FLASH_FW_ERR 0xF024
-#define FA_BOOT_LOG_ADDR 0x58000
-#define FA_FW_DUMP0_ADDR 0x60000
-#define FA_FW_DUMP1_ADDR 0x70000
-
uint32_t flash_data; /* Flash/NVRAM BIOS data. */
uint32_t ctrl_status; /* Control/Status. */
@@ -1203,6 +1208,62 @@ struct qla_fdt_layout {
uint8_t unused2[65];
};
+/* Flash Layout Table ********************************************************/
+
+struct qla_flt_location {
+ uint8_t sig[4];
+ uint32_t start_lo;
+ uint32_t start_hi;
+ uint16_t unused;
+ uint16_t checksum;
+};
+
+struct qla_flt_header {
+ uint16_t version;
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t unused;
+};
+
+#define FLT_REG_FW 0x01
+#define FLT_REG_BOOT_CODE 0x07
+#define FLT_REG_VPD_0 0x14
+#define FLT_REG_NVRAM_0 0x15
+#define FLT_REG_VPD_1 0x16
+#define FLT_REG_NVRAM_1 0x17
+#define FLT_REG_FDT 0x1a
+#define FLT_REG_FLT 0x1c
+#define FLT_REG_HW_EVENT_0 0x1d
+#define FLT_REG_HW_EVENT_1 0x1f
+#define FLT_REG_NPIV_CONF_0 0x29
+#define FLT_REG_NPIV_CONF_1 0x2a
+
+struct qla_flt_region {
+ uint32_t code;
+ uint32_t size;
+ uint32_t start;
+ uint32_t end;
+};
+
+/* Flash NPIV Configuration Table ********************************************/
+
+struct qla_npiv_header {
+ uint8_t sig[2];
+ uint16_t version;
+ uint16_t entries;
+ uint16_t unused[4];
+ uint16_t checksum;
+};
+
+struct qla_npiv_entry {
+ uint16_t flags;
+ uint16_t vf_id;
+ uint16_t qos;
+ uint16_t unused1;
+ uint8_t port_name[WWN_SIZE];
+ uint8_t node_name[WWN_SIZE];
+};
+
/* 84XX Support **************************************************************/
#define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0b156735e9a..753dbe6cce6 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -313,9 +313,11 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
uint16_t, uint16_t);
-extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+extern int qla2xxx_get_flash_info(scsi_qla_host_t *);
extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
+extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_dbg.c source file.
*/
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index ee89ddd64aa..a470f2d3270 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -83,6 +83,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
ha->isp_ops->reset_chip(ha);
+ rval = qla2xxx_get_flash_info(ha);
+ if (rval) {
+ DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n",
+ ha->host_no));
+ return (rval);
+ }
+
ha->isp_ops->get_flash_version(ha, ha->request_ring);
qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
@@ -109,7 +116,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
rval = qla2x00_setup_chip(ha);
if (rval)
return (rval);
- qla2xxx_get_flash_info(ha);
}
if (IS_QLA84XX(ha)) {
ha->cs84xx = qla84xx_get_chip(ha);
@@ -2016,7 +2022,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
DEBUG3(printk("%s: exiting normally\n", __func__));
}
- /* Restore state if a resync event occured during processing */
+ /* Restore state if a resync event occurred during processing */
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
@@ -2561,7 +2567,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
rval = QLA_SUCCESS;
/* Try GID_PT to get device list, else GAN. */
- swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC);
+ swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL);
if (!swl) {
/*EMPTY*/
DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback "
@@ -3751,7 +3757,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
- faddr = FA_RISC_CODE_ADDR;
+ faddr = ha->flt_region_fw;
dcode = (uint32_t *)ha->request_ring;
*srisc_addr = 0;
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 92fafbdbbaa..e90afad120e 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -52,7 +52,7 @@ to_qla_parent(scsi_qla_host_t *ha)
* @ha: HA context
* @ha_locked: is function called with the hardware lock
*
- * Returns non-zero if a failure occured, else zero.
+ * Returns non-zero if a failure occurred, else zero.
*/
static inline int
qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked)
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d57669aa461..85bc0a48598 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -21,17 +21,22 @@ static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
* Returns the proper CF_* direction based on CDB.
*/
static inline uint16_t
-qla2x00_get_cmd_direction(struct scsi_cmnd *cmd)
+qla2x00_get_cmd_direction(srb_t *sp)
{
uint16_t cflags;
cflags = 0;
/* Set transfer direction */
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ if (sp->cmd->sc_data_direction == DMA_TO_DEVICE) {
cflags = CF_WRITE;
- else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+ sp->fcport->ha->qla_stats.output_bytes +=
+ scsi_bufflen(sp->cmd);
+ } else if (sp->cmd->sc_data_direction == DMA_FROM_DEVICE) {
cflags = CF_READ;
+ sp->fcport->ha->qla_stats.input_bytes +=
+ scsi_bufflen(sp->cmd);
+ }
return (cflags);
}
@@ -169,7 +174,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
ha = sp->ha;
- cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd));
+ cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Three DSDs are available in the Command Type 2 IOCB */
avail_dsds = 3;
@@ -228,7 +233,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
ha = sp->ha;
- cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd));
+ cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Two DSDs are available in the Command Type 3 IOCB */
avail_dsds = 2;
@@ -262,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
* qla2x00_start_scsi() - Send a SCSI command to the ISP
* @sp: command to send to the ISP
*
- * Returns non-zero if a failure occured, else zero.
+ * Returns non-zero if a failure occurred, else zero.
*/
int
qla2x00_start_scsi(srb_t *sp)
@@ -407,7 +412,7 @@ queuing_error:
*
* Can be called from both normal and interrupt context.
*
- * Returns non-zero if a failure occured, else zero.
+ * Returns non-zero if a failure occurred, else zero.
*/
int
__qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
@@ -625,12 +630,17 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
ha = sp->ha;
/* Set transfer direction */
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ if (cmd->sc_data_direction == DMA_TO_DEVICE) {
cmd_pkt->task_mgmt_flags =
__constant_cpu_to_le16(TMF_WRITE_DATA);
- else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+ sp->fcport->ha->qla_stats.output_bytes +=
+ scsi_bufflen(sp->cmd);
+ } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
cmd_pkt->task_mgmt_flags =
__constant_cpu_to_le16(TMF_READ_DATA);
+ sp->fcport->ha->qla_stats.input_bytes +=
+ scsi_bufflen(sp->cmd);
+ }
/* One DSD is available in the Command Type 3 IOCB */
avail_dsds = 1;
@@ -666,7 +676,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
* qla24xx_start_scsi() - Send a SCSI command to the ISP
* @sp: command to send to the ISP
*
- * Returns non-zero if a failure occured, else zero.
+ * Returns non-zero if a failure occurred, else zero.
*/
int
qla24xx_start_scsi(srb_t *sp)
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 45a3b93eed5..a76efd99d00 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -391,9 +391,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
- DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no,
+ DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", ha->host_no,
mb[1]));
- qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]);
+ qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
@@ -460,7 +460,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
ha->host_no, mb[1]));
qla_printk(KERN_INFO, ha,
- "LIP reset occured (%x).\n", mb[1]);
+ "LIP reset occurred (%x).\n", mb[1]);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
@@ -543,7 +543,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
case MBA_PORT_UPDATE: /* Port database update */
/*
- * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
+ * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET
* event etc. earlier indicating loop is down) then process
* it. Otherwise ignore it and Wait for RSCN to come in.
*/
@@ -589,7 +589,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
"scsi(%ld): RSCN database changed -- %04x %04x %04x.\n",
ha->host_no, mb[1], mb[2], mb[3]));
- rscn_entry = (mb[1] << 16) | mb[2];
+ rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) |
ha->d_id.b.al_pa;
if (rscn_entry == host_pid) {
@@ -600,6 +600,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
}
+ /* Ignore reserved bits from RSCN-payload. */
+ rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
rscn_queue_index = ha->rscn_in_ptr + 1;
if (rscn_queue_index == MAX_RSCN_COUNT)
rscn_queue_index = 0;
@@ -1060,8 +1062,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
resid = resid_len;
/* Use F/W calculated residual length. */
if (IS_FWI2_CAPABLE(ha)) {
- if (scsi_status & SS_RESIDUAL_UNDER &&
- resid != fw_resid_len) {
+ if (!(scsi_status & SS_RESIDUAL_UNDER)) {
+ lscsi_status = 0;
+ } else if (resid != fw_resid_len) {
scsi_status &= ~SS_RESIDUAL_UNDER;
lscsi_status = 0;
}
@@ -1184,7 +1187,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
cp->serial_number, comp_status,
atomic_read(&fcport->state)));
- cp->result = DID_BUS_BUSY << 16;
+ /*
+ * We are going to have the fc class block the rport
+ * while we try to recover so instruct the mid layer
+ * to requeue until the class decides how to handle this.
+ */
+ cp->result = DID_TRANSPORT_DISRUPTED << 16;
if (atomic_read(&fcport->state) == FCS_ONLINE)
qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
@@ -1211,7 +1219,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
break;
case CS_TIMEOUT:
- cp->result = DID_BUS_BUSY << 16;
+ /*
+ * We are going to have the fc class block the rport
+ * while we try to recover so instruct the mid layer
+ * to requeue until the class decides how to handle this.
+ */
+ cp->result = DID_TRANSPORT_DISRUPTED << 16;
if (IS_FWI2_CAPABLE(ha)) {
DEBUG2(printk(KERN_INFO
@@ -1834,7 +1847,6 @@ clear_risc_ints:
WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
}
spin_unlock_irq(&ha->hardware_lock);
- ha->isp_ops->enable_intrs(ha);
fail:
return ret;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 813bc7784c0..36bc6851e23 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -233,7 +233,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
DEBUG2_3_11(printk("%s(%ld): timeout schedule "
"isp_abort_needed.\n", __func__, ha->host_no));
qla_printk(KERN_WARNING, ha,
- "Mailbox command timeout occured. Scheduling ISP "
+ "Mailbox command timeout occurred. Scheduling ISP "
"abort.\n");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
qla2xxx_wake_dpc(ha);
@@ -244,7 +244,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
DEBUG2_3_11(printk("%s(%ld): timeout calling "
"abort_isp\n", __func__, ha->host_no));
qla_printk(KERN_WARNING, ha,
- "Mailbox command timeout occured. Issuing ISP "
+ "Mailbox command timeout occurred. Issuing ISP "
"abort.\n");
set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
@@ -1995,7 +1995,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
char *pmap;
dma_addr_t pmap_dma;
- pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma);
+ pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma);
if (pmap == NULL) {
DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****",
__func__, ha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 26afe44265c..2aed4721c0d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -394,10 +394,8 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
- if (fcport->drport) {
- cmd->result = DID_IMM_RETRY << 16;
- goto qc_fail_command;
- }
+ if (fcport->drport)
+ goto qc_target_busy;
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
@@ -405,7 +403,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
cmd->result = DID_NO_CONNECT << 16;
goto qc_fail_command;
}
- goto qc_host_busy;
+ goto qc_target_busy;
}
spin_unlock_irq(ha->host->host_lock);
@@ -428,10 +426,11 @@ qc_host_busy_free_sp:
qc_host_busy_lock:
spin_lock_irq(ha->host->host_lock);
-
-qc_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
+qc_target_busy:
+ return SCSI_MLQUEUE_TARGET_BUSY;
+
qc_fail_command:
done(cmd);
@@ -461,10 +460,8 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
- if (fcport->drport) {
- cmd->result = DID_IMM_RETRY << 16;
- goto qc24_fail_command;
- }
+ if (fcport->drport)
+ goto qc24_target_busy;
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
@@ -472,7 +469,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
- goto qc24_host_busy;
+ goto qc24_target_busy;
}
spin_unlock_irq(ha->host->host_lock);
@@ -495,10 +492,11 @@ qc24_host_busy_free_sp:
qc24_host_busy_lock:
spin_lock_irq(ha->host->host_lock);
-
-qc24_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
+qc24_target_busy:
+ return SCSI_MLQUEUE_TARGET_BUSY;
+
qc24_fail_command:
done(cmd);
@@ -1517,6 +1515,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost)
set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
set_bit(RSCN_UPDATE, &ha->dpc_flags);
+ set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags);
}
static int
@@ -1663,8 +1662,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->gid_list_info_size = 8;
ha->optrom_size = OPTROM_SIZE_25XX;
ha->isp_ops = &qla25xx_isp_ops;
- ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
- FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
}
host->can_queue = ha->request_q_length + 128;
@@ -1740,6 +1737,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto probe_failed;
+ ha->isp_ops->enable_intrs(ha);
+
scsi_scan_host(host);
qla2x00_alloc_sysfs_attr(ha);
@@ -2431,6 +2430,12 @@ qla2x00_do_dpc(void *data)
ha->host_no));
}
+ if (test_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags) &&
+ atomic_read(&ha->loop_state) == LOOP_READY) {
+ clear_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags);
+ qla2xxx_flash_npiv_conf(ha);
+ }
+
if (!ha->interrupts_on)
ha->isp_ops->enable_intrs(ha);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 1bca7447493..90a13211717 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -543,23 +543,198 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
}
}
-void
-qla2xxx_get_flash_info(scsi_qla_host_t *ha)
+static int
+qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start)
+{
+ const char *loc, *locations[] = { "DEF", "PCI" };
+ uint32_t pcihdr, pcids;
+ uint32_t *dcode;
+ uint8_t *buf, *bcode, last_image;
+ uint16_t cnt, chksum, *wptr;
+ struct qla_flt_location *fltl;
+
+ /*
+ * FLT-location structure resides after the last PCI region.
+ */
+
+ /* Begin with sane defaults. */
+ loc = locations[0];
+ *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24:
+ FA_FLASH_LAYOUT_ADDR;
+
+ /* Begin with first PCI expansion ROM header. */
+ buf = (uint8_t *)ha->request_ring;
+ dcode = (uint32_t *)ha->request_ring;
+ pcihdr = 0;
+ last_image = 1;
+ do {
+ /* Verify PCI expansion ROM header. */
+ qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20);
+ bcode = buf + (pcihdr % 4);
+ if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa)
+ goto end;
+
+ /* Locate PCI data structure. */
+ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
+ qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20);
+ bcode = buf + (pcihdr % 4);
+
+ /* Validate signature of PCI data structure. */
+ if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
+ bcode[0x2] != 'I' || bcode[0x3] != 'R')
+ goto end;
+
+ last_image = bcode[0x15] & BIT_7;
+
+ /* Locate next PCI expansion ROM. */
+ pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
+ } while (!last_image);
+
+ /* Now verify FLT-location structure. */
+ fltl = (struct qla_flt_location *)ha->request_ring;
+ qla24xx_read_flash_data(ha, dcode, pcihdr >> 2,
+ sizeof(struct qla_flt_location) >> 2);
+ if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' ||
+ fltl->sig[2] != 'L' || fltl->sig[3] != 'T')
+ goto end;
+
+ wptr = (uint16_t *)ha->request_ring;
+ cnt = sizeof(struct qla_flt_location) >> 1;
+ for (chksum = 0; cnt; cnt--)
+ chksum += le16_to_cpu(*wptr++);
+ if (chksum) {
+ qla_printk(KERN_ERR, ha,
+ "Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
+ qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location));
+ return QLA_FUNCTION_FAILED;
+ }
+
+ /* Good data. Use specified location. */
+ loc = locations[1];
+ *start = le16_to_cpu(fltl->start_hi) << 16 |
+ le16_to_cpu(fltl->start_lo);
+end:
+ DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start));
+ return QLA_SUCCESS;
+}
+
+static void
+qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr)
+{
+ const char *loc, *locations[] = { "DEF", "FLT" };
+ uint16_t *wptr;
+ uint16_t cnt, chksum;
+ uint32_t start;
+ struct qla_flt_header *flt;
+ struct qla_flt_region *region;
+
+ ha->flt_region_flt = flt_addr;
+ wptr = (uint16_t *)ha->request_ring;
+ flt = (struct qla_flt_header *)ha->request_ring;
+ region = (struct qla_flt_region *)&flt[1];
+ ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
+ flt_addr << 2, OPTROM_BURST_SIZE);
+ if (*wptr == __constant_cpu_to_le16(0xffff))
+ goto no_flash_data;
+ if (flt->version != __constant_cpu_to_le16(1)) {
+ DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: "
+ "version=0x%x length=0x%x checksum=0x%x.\n",
+ le16_to_cpu(flt->version), le16_to_cpu(flt->length),
+ le16_to_cpu(flt->checksum)));
+ goto no_flash_data;
+ }
+
+ cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1;
+ for (chksum = 0; cnt; cnt--)
+ chksum += le16_to_cpu(*wptr++);
+ if (chksum) {
+ DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: "
+ "version=0x%x length=0x%x checksum=0x%x.\n",
+ le16_to_cpu(flt->version), le16_to_cpu(flt->length),
+ chksum));
+ goto no_flash_data;
+ }
+
+ loc = locations[1];
+ cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
+ for ( ; cnt; cnt--, region++) {
+ /* Store addresses as DWORD offsets. */
+ start = le32_to_cpu(region->start) >> 2;
+
+ DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x "
+ "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
+ le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
+
+ switch (le32_to_cpu(region->code)) {
+ case FLT_REG_FW:
+ ha->flt_region_fw = start;
+ break;
+ case FLT_REG_BOOT_CODE:
+ ha->flt_region_boot = start;
+ break;
+ case FLT_REG_VPD_0:
+ ha->flt_region_vpd_nvram = start;
+ break;
+ case FLT_REG_FDT:
+ ha->flt_region_fdt = start;
+ break;
+ case FLT_REG_HW_EVENT_0:
+ if (!PCI_FUNC(ha->pdev->devfn))
+ ha->flt_region_hw_event = start;
+ break;
+ case FLT_REG_HW_EVENT_1:
+ if (PCI_FUNC(ha->pdev->devfn))
+ ha->flt_region_hw_event = start;
+ break;
+ case FLT_REG_NPIV_CONF_0:
+ if (!PCI_FUNC(ha->pdev->devfn))
+ ha->flt_region_npiv_conf = start;
+ break;
+ case FLT_REG_NPIV_CONF_1:
+ if (PCI_FUNC(ha->pdev->devfn))
+ ha->flt_region_npiv_conf = start;
+ break;
+ }
+ }
+ goto done;
+
+no_flash_data:
+ /* Use hardcoded defaults. */
+ loc = locations[0];
+ ha->flt_region_fw = FA_RISC_CODE_ADDR;
+ ha->flt_region_boot = FA_BOOT_CODE_ADDR;
+ ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR;
+ ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24:
+ FA_FLASH_DESCR_ADDR;
+ ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ?
+ FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR;
+ ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ?
+ (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR):
+ (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR);
+done:
+ DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
+ "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc,
+ ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram,
+ ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event,
+ ha->flt_region_npiv_conf));
+}
+
+static void
+qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
{
#define FLASH_BLK_SIZE_32K 0x8000
#define FLASH_BLK_SIZE_64K 0x10000
+ const char *loc, *locations[] = { "MID", "FDT" };
uint16_t cnt, chksum;
uint16_t *wptr;
struct qla_fdt_layout *fdt;
uint8_t man_id, flash_id;
-
- if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
- return;
+ uint16_t mid, fid;
wptr = (uint16_t *)ha->request_ring;
fdt = (struct qla_fdt_layout *)ha->request_ring;
ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
- FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE);
+ ha->flt_region_fdt << 2, OPTROM_BURST_SIZE);
if (*wptr == __constant_cpu_to_le16(0xffff))
goto no_flash_data;
if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
@@ -577,7 +752,10 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha)
goto no_flash_data;
}
- ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f;
+ loc = locations[1];
+ mid = le16_to_cpu(fdt->man_id);
+ fid = le16_to_cpu(fdt->id);
+ ha->fdt_odd_index = mid == 0x1f;
ha->fdt_wrt_disable = fdt->wrt_disable_bits;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
ha->fdt_block_size = le32_to_cpu(fdt->block_size);
@@ -588,16 +766,12 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha)
flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd):
flash_conf_to_access_addr(0x0336);
}
-
- DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x "
- "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n",
- le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd,
- ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd,
- ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size));
- return;
-
+ goto done;
no_flash_data:
+ loc = locations[0];
qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
+ mid = man_id;
+ fid = flash_id;
ha->fdt_wrt_disable = 0x9c;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8);
switch (man_id) {
@@ -625,14 +799,117 @@ no_flash_data:
ha->fdt_block_size = FLASH_BLK_SIZE_64K;
break;
}
-
- DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x "
- "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id,
+done:
+ DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "
+ "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
ha->fdt_block_size));
}
+int
+qla2xxx_get_flash_info(scsi_qla_host_t *ha)
+{
+ int ret;
+ uint32_t flt_addr;
+
+ if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+ return QLA_SUCCESS;
+
+ ret = qla2xxx_find_flt_start(ha, &flt_addr);
+ if (ret != QLA_SUCCESS)
+ return ret;
+
+ qla2xxx_get_flt_info(ha, flt_addr);
+ qla2xxx_get_fdt_info(ha);
+
+ return QLA_SUCCESS;
+}
+
+void
+qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha)
+{
+#define NPIV_CONFIG_SIZE (16*1024)
+ void *data;
+ uint16_t *wptr;
+ uint16_t cnt, chksum;
+ struct qla_npiv_header hdr;
+ struct qla_npiv_entry *entry;
+
+ if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+ return;
+
+ ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr,
+ ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header));
+ if (hdr.version == __constant_cpu_to_le16(0xffff))
+ return;
+ if (hdr.version != __constant_cpu_to_le16(1)) {
+ DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config "
+ "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
+ le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
+ le16_to_cpu(hdr.checksum)));
+ return;
+ }
+
+ data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL);
+ if (!data) {
+ DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to "
+ "allocate memory.\n"));
+ return;
+ }
+
+ ha->isp_ops->read_optrom(ha, (uint8_t *)data,
+ ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE);
+
+ cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) *
+ sizeof(struct qla_npiv_entry)) >> 1;
+ for (wptr = data, chksum = 0; cnt; cnt--)
+ chksum += le16_to_cpu(*wptr++);
+ if (chksum) {
+ DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config "
+ "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
+ le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
+ chksum));
+ goto done;
+ }
+
+ entry = data + sizeof(struct qla_npiv_header);
+ cnt = le16_to_cpu(hdr.entries);
+ for ( ; cnt; cnt--, entry++) {
+ uint16_t flags;
+ struct fc_vport_identifiers vid;
+ struct fc_vport *vport;
+
+ flags = le16_to_cpu(entry->flags);
+ if (flags == 0xffff)
+ continue;
+ if ((flags & BIT_0) == 0)
+ continue;
+
+ memset(&vid, 0, sizeof(vid));
+ vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
+ vid.vport_type = FC_PORTTYPE_NPIV;
+ vid.disable = false;
+ vid.port_name = wwn_to_u64(entry->port_name);
+ vid.node_name = wwn_to_u64(entry->node_name);
+
+ DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx "
+ "wwnn=%llx vf_id=0x%x qos=0x%x.\n", cnt,
+ (unsigned long long)vid.port_name,
+ (unsigned long long)vid.node_name,
+ le16_to_cpu(entry->vf_id), le16_to_cpu(entry->qos)));
+
+ vport = fc_vport_create(ha->host, 0, &vid);
+ if (!vport)
+ qla_printk(KERN_INFO, ha, "NPIV-Config: Failed to "
+ "create vport [%02x]: wwpn=%llx wwnn=%llx.\n", cnt,
+ (unsigned long long)vid.port_name,
+ (unsigned long long)vid.node_name);
+ }
+done:
+ kfree(data);
+}
+
static void
qla24xx_unprotect_flash(scsi_qla_host_t *ha)
{
@@ -920,7 +1197,8 @@ qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
- flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr)));
+ flash_data_to_access_addr(ha->flt_region_vpd_nvram |
+ naddr)));
return buf;
}
@@ -935,10 +1213,10 @@ qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
dbuf = vmalloc(RMW_BUFFER_SIZE);
if (!dbuf)
return QLA_MEMORY_ALLOC_FAILED;
- ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ ha->isp_ops->read_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2,
RMW_BUFFER_SIZE);
memcpy(dbuf + (naddr << 2), buf, bytes);
- ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ ha->isp_ops->write_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2,
RMW_BUFFER_SIZE);
vfree(dbuf);
@@ -2166,7 +2444,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
memset(dbyte, 0, 8);
dcode = (uint16_t *)dbyte;
- qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10,
+ qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10,
8);
DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n",
__func__, ha->host_no));
@@ -2177,7 +2455,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
DEBUG2(printk("%s(): Unrecognized fw revision at "
- "%x.\n", __func__, FA_RISC_CODE_ADDR * 4));
+ "%x.\n", __func__, ha->flt_region_fw * 4));
} else {
/* values are in big endian */
ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
@@ -2212,7 +2490,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
dcode = mbuf;
/* Begin with first PCI expansion ROM header. */
- pcihdr = 0;
+ pcihdr = ha->flt_region_boot;
last_image = 1;
do {
/* Verify PCI expansion ROM header. */
@@ -2282,7 +2560,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
dcode = mbuf;
- qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4);
+ qla24xx_read_flash_data(ha, dcode, ha->flt_region_fw + 4, 4);
for (i = 0; i < 4; i++)
dcode[i] = be32_to_cpu(dcode[i]);
@@ -2291,7 +2569,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
DEBUG2(printk("%s(): Unrecognized fw version at %x.\n",
- __func__, FA_RISC_CODE_ADDR));
+ __func__, ha->flt_region_fw));
} else {
ha->fw_revision[0] = dcode[0];
ha->fw_revision[1] = dcode[1];
@@ -2355,7 +2633,7 @@ qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
/* Locate first empty entry. */
for (;;) {
if (ha->hw_event_ptr >=
- ha->hw_event_start + FA_HW_EVENT_SIZE) {
+ ha->flt_region_hw_event + FA_HW_EVENT_SIZE) {
DEBUG2(qla_printk(KERN_WARNING, ha,
"HW event -- Log Full!\n"));
return QLA_MEMORY_ALLOC_FAILED;
@@ -2391,7 +2669,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
int rval;
uint32_t marker[2], fdata[4];
- if (ha->hw_event_start == 0)
+ if (ha->flt_region_hw_event == 0)
return QLA_FUNCTION_FAILED;
DEBUG2(qla_printk(KERN_WARNING, ha,
@@ -2406,7 +2684,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
/* Locate marker. */
- ha->hw_event_ptr = ha->hw_event_start;
+ ha->hw_event_ptr = ha->flt_region_hw_event;
for (;;) {
qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
4);
@@ -2415,7 +2693,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
break;
ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
if (ha->hw_event_ptr >=
- ha->hw_event_start + FA_HW_EVENT_SIZE) {
+ ha->flt_region_hw_event + FA_HW_EVENT_SIZE) {
DEBUG2(qla_printk(KERN_WARNING, ha,
"HW event -- Log Full!\n"));
return QLA_MEMORY_ALLOC_FAILED;
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 4160e4caa7b..be5e299df52 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k7"
+#define QLA2XXX_VERSION "8.02.01-k8"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index a91a57c57bf..799120fcb9b 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -139,7 +139,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
ha->host_no, cmd->device->channel,
cmd->device->id, cmd->device->lun));
- cmd->result = DID_BUS_BUSY << 16;
+ cmd->result = DID_TRANSPORT_DISRUPTED << 16;
/*
* Mark device missing so that we won't continue to send
@@ -243,7 +243,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
qla4xxx_mark_device_missing(ha, ddb_entry);
- cmd->result = DID_BUS_BUSY << 16;
+ cmd->result = DID_TRANSPORT_DISRUPTED << 16;
break;
case SCS_QUEUE_FULL:
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 88bebb13bc5..db7ea3bb4e8 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -353,7 +353,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
ha->host_no, ddb_entry->bus, ddb_entry->target,
ddb_entry->fw_ddb_index));
iscsi_block_session(ddb_entry->sess);
- iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
}
static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
@@ -439,7 +439,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
cmd->result = DID_NO_CONNECT << 16;
goto qc_fail_command;
}
- goto qc_host_busy;
+ return SCSI_MLQUEUE_TARGET_BUSY;
}
if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
@@ -1542,7 +1542,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
DEBUG2(printk(KERN_INFO
"scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
"dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
- cmd, jiffies, cmd->timeout_per_command / HZ,
+ cmd, jiffies, cmd->request->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
/* FIXME: wait for hba to go online */
@@ -1598,7 +1598,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
DEBUG2(printk(KERN_INFO
"scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
"to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
- ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
+ ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
stat = qla4xxx_reset_target(ha, ddb_entry);
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 4a1cf6377f6..69d6ad862b6 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1,6 +1,6 @@
/* qlogicpti.c: Performance Technologies QlogicISP sbus card driver.
*
- * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996, 2006, 2008 David S. Miller (davem@davemloft.net)
*
* A lot of this driver was directly stolen from Erik H. Moe's PCI
* Qlogic ISP driver. Mucho kudos to him for this code.
@@ -25,12 +25,14 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/byteorder.h>
#include "qlogicpti.h"
-#include <asm/sbus.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/ptrace.h>
@@ -157,7 +159,7 @@ static inline void set_sbus_cfg1(struct qlogicpti *qpti)
* is a nop and the chip ends up using the smallest burst
* size. -DaveM
*/
- if (sbus_can_burst64(qpti->sdev) && (bursts & DMA_BURST64)) {
+ if (sbus_can_burst64() && (bursts & DMA_BURST64)) {
val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64);
} else
#endif
@@ -684,19 +686,19 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti)
static int __devinit qpti_map_regs(struct qlogicpti *qpti)
{
- struct sbus_dev *sdev = qpti->sdev;
+ struct of_device *op = qpti->op;
- qpti->qregs = sbus_ioremap(&sdev->resource[0], 0,
- sdev->reg_addrs[0].reg_size,
- "PTI Qlogic/ISP");
+ qpti->qregs = of_ioremap(&op->resource[0], 0,
+ resource_size(&op->resource[0]),
+ "PTI Qlogic/ISP");
if (!qpti->qregs) {
printk("PTI: Qlogic/ISP registers are unmappable\n");
return -1;
}
if (qpti->is_pti) {
- qpti->sreg = sbus_ioremap(&sdev->resource[0], (16 * 4096),
- sizeof(unsigned char),
- "PTI Qlogic/ISP statreg");
+ qpti->sreg = of_ioremap(&op->resource[0], (16 * 4096),
+ sizeof(unsigned char),
+ "PTI Qlogic/ISP statreg");
if (!qpti->sreg) {
printk("PTI: Qlogic/ISP status register is unmappable\n");
return -1;
@@ -707,9 +709,9 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti)
static int __devinit qpti_register_irq(struct qlogicpti *qpti)
{
- struct sbus_dev *sdev = qpti->sdev;
+ struct of_device *op = qpti->op;
- qpti->qhost->irq = qpti->irq = sdev->irqs[0];
+ qpti->qhost->irq = qpti->irq = op->irqs[0];
/* We used to try various overly-clever things to
* reduce the interrupt processing overhead on
@@ -732,17 +734,19 @@ fail:
static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti)
{
- qpti->scsi_id = prom_getintdefault(qpti->prom_node,
- "initiator-id",
- -1);
+ struct of_device *op = qpti->op;
+ struct device_node *dp;
+
+ dp = op->node;
+
+ qpti->scsi_id = of_getintprop_default(dp, "initiator-id", -1);
if (qpti->scsi_id == -1)
- qpti->scsi_id = prom_getintdefault(qpti->prom_node,
- "scsi-initiator-id",
- -1);
+ qpti->scsi_id = of_getintprop_default(dp, "scsi-initiator-id",
+ -1);
if (qpti->scsi_id == -1)
qpti->scsi_id =
- prom_getintdefault(qpti->sdev->bus->prom_node,
- "scsi-initiator-id", 7);
+ of_getintprop_default(dp->parent,
+ "scsi-initiator-id", 7);
qpti->qhost->this_id = qpti->scsi_id;
qpti->qhost->max_sectors = 64;
@@ -751,12 +755,11 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti)
static void qpti_get_bursts(struct qlogicpti *qpti)
{
- struct sbus_dev *sdev = qpti->sdev;
+ struct of_device *op = qpti->op;
u8 bursts, bmask;
- bursts = prom_getintdefault(qpti->prom_node, "burst-sizes", 0xff);
- bmask = prom_getintdefault(sdev->bus->prom_node,
- "burst-sizes", 0xff);
+ bursts = of_getintprop_default(op->node, "burst-sizes", 0xff);
+ bmask = of_getintprop_default(op->node->parent, "burst-sizes", 0xff);
if (bmask != 0xff)
bursts &= bmask;
if (bursts == 0xff ||
@@ -785,25 +788,25 @@ static void qpti_get_clock(struct qlogicpti *qpti)
*/
static int __devinit qpti_map_queues(struct qlogicpti *qpti)
{
- struct sbus_dev *sdev = qpti->sdev;
+ struct of_device *op = qpti->op;
#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN)
- qpti->res_cpu = sbus_alloc_consistent(sdev,
- QSIZE(RES_QUEUE_LEN),
- &qpti->res_dvma);
+ qpti->res_cpu = dma_alloc_coherent(&op->dev,
+ QSIZE(RES_QUEUE_LEN),
+ &qpti->res_dvma, GFP_ATOMIC);
if (qpti->res_cpu == NULL ||
qpti->res_dvma == 0) {
printk("QPTI: Cannot map response queue.\n");
return -1;
}
- qpti->req_cpu = sbus_alloc_consistent(sdev,
- QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
- &qpti->req_dvma);
+ qpti->req_cpu = dma_alloc_coherent(&op->dev,
+ QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+ &qpti->req_dvma, GFP_ATOMIC);
if (qpti->req_cpu == NULL ||
qpti->req_dvma == 0) {
- sbus_free_consistent(sdev, QSIZE(RES_QUEUE_LEN),
- qpti->res_cpu, qpti->res_dvma);
+ dma_free_coherent(&op->dev, QSIZE(RES_QUEUE_LEN),
+ qpti->res_cpu, qpti->res_dvma);
printk("QPTI: Cannot map request queue.\n");
return -1;
}
@@ -875,8 +878,9 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
int sg_count;
sg = scsi_sglist(Cmnd);
- sg_count = sbus_map_sg(qpti->sdev, sg, scsi_sg_count(Cmnd),
- Cmnd->sc_data_direction);
+ sg_count = dma_map_sg(&qpti->op->dev, sg,
+ scsi_sg_count(Cmnd),
+ Cmnd->sc_data_direction);
ds = cmd->dataseg;
cmd->segment_cnt = sg_count;
@@ -914,6 +918,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
ds[i].d_count = sg_dma_len(s);
}
sg_count -= n;
+ sg = s;
}
} else {
cmd->dataseg[0].d_base = 0;
@@ -1151,9 +1156,9 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
Cmnd->result = DID_ERROR << 16;
if (scsi_bufflen(Cmnd))
- sbus_unmap_sg(qpti->sdev,
- scsi_sglist(Cmnd), scsi_sg_count(Cmnd),
- Cmnd->sc_data_direction);
+ dma_unmap_sg(&qpti->op->dev,
+ scsi_sglist(Cmnd), scsi_sg_count(Cmnd),
+ Cmnd->sc_data_direction);
qpti->cmd_count[Cmnd->device->id]--;
sbus_writew(out_ptr, qpti->qregs + MBOX5);
@@ -1267,34 +1272,32 @@ static struct scsi_host_template qpti_template = {
.use_clustering = ENABLE_CLUSTERING,
};
-static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- static int nqptis;
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
struct scsi_host_template *tpnt = match->data;
+ struct device_node *dp = op->node;
struct Scsi_Host *host;
struct qlogicpti *qpti;
+ static int nqptis;
const char *fcode;
/* Sometimes Antares cards come up not completely
* setup, and we get a report of a zero IRQ.
*/
- if (sdev->irqs[0] == 0)
+ if (op->irqs[0] == 0)
return -ENODEV;
host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
if (!host)
return -ENOMEM;
- qpti = (struct qlogicpti *) host->hostdata;
+ qpti = shost_priv(host);
host->max_id = MAX_TARGETS;
qpti->qhost = host;
- qpti->sdev = sdev;
+ qpti->op = op;
qpti->qpti_id = nqptis;
- qpti->prom_node = sdev->prom_node;
- strcpy(qpti->prom_name, sdev->ofdev.node->name);
+ strcpy(qpti->prom_name, op->node->name);
qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp");
if (qpti_map_regs(qpti) < 0)
@@ -1340,12 +1343,12 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi
(qpti->ultra ? "Ultra" : "Fast"),
(qpti->differential ? "differential" : "single ended"));
- if (scsi_add_host(host, &dev->dev)) {
+ if (scsi_add_host(host, &op->dev)) {
printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id);
goto fail_unmap_queues;
}
- dev_set_drvdata(&sdev->ofdev.dev, qpti);
+ dev_set_drvdata(&op->dev, qpti);
qpti_chain_add(qpti);
@@ -1356,19 +1359,20 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi
fail_unmap_queues:
#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN)
- sbus_free_consistent(qpti->sdev,
- QSIZE(RES_QUEUE_LEN),
- qpti->res_cpu, qpti->res_dvma);
- sbus_free_consistent(qpti->sdev,
- QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
- qpti->req_cpu, qpti->req_dvma);
+ dma_free_coherent(&op->dev,
+ QSIZE(RES_QUEUE_LEN),
+ qpti->res_cpu, qpti->res_dvma);
+ dma_free_coherent(&op->dev,
+ QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+ qpti->req_cpu, qpti->req_dvma);
#undef QSIZE
fail_unmap_regs:
- sbus_iounmap(qpti->qregs,
- qpti->sdev->reg_addrs[0].reg_size);
+ of_iounmap(&op->resource[0], qpti->qregs,
+ resource_size(&op->resource[0]));
if (qpti->is_pti)
- sbus_iounmap(qpti->sreg, sizeof(unsigned char));
+ of_iounmap(&op->resource[0], qpti->sreg,
+ sizeof(unsigned char));
fail_free_irq:
free_irq(qpti->irq, qpti);
@@ -1379,9 +1383,9 @@ fail_unlink:
return -ENODEV;
}
-static int __devexit qpti_sbus_remove(struct of_device *dev)
+static int __devexit qpti_sbus_remove(struct of_device *op)
{
- struct qlogicpti *qpti = dev_get_drvdata(&dev->dev);
+ struct qlogicpti *qpti = dev_get_drvdata(&op->dev);
qpti_chain_del(qpti);
@@ -1394,24 +1398,25 @@ static int __devexit qpti_sbus_remove(struct of_device *dev)
free_irq(qpti->irq, qpti);
#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN)
- sbus_free_consistent(qpti->sdev,
- QSIZE(RES_QUEUE_LEN),
- qpti->res_cpu, qpti->res_dvma);
- sbus_free_consistent(qpti->sdev,
- QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
- qpti->req_cpu, qpti->req_dvma);
+ dma_free_coherent(&op->dev,
+ QSIZE(RES_QUEUE_LEN),
+ qpti->res_cpu, qpti->res_dvma);
+ dma_free_coherent(&op->dev,
+ QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+ qpti->req_cpu, qpti->req_dvma);
#undef QSIZE
- sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size);
+ of_iounmap(&op->resource[0], qpti->qregs,
+ resource_size(&op->resource[0]));
if (qpti->is_pti)
- sbus_iounmap(qpti->sreg, sizeof(unsigned char));
+ of_iounmap(&op->resource[0], qpti->sreg, sizeof(unsigned char));
scsi_host_put(qpti->qhost);
return 0;
}
-static struct of_device_id qpti_match[] = {
+static const struct of_device_id qpti_match[] = {
{
.name = "ptisp",
.data = &qpti_template,
@@ -1441,7 +1446,7 @@ static struct of_platform_driver qpti_sbus_driver = {
static int __init qpti_init(void)
{
- return of_register_driver(&qpti_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&qpti_sbus_driver, &of_bus_type);
}
static void __exit qpti_exit(void)
@@ -1452,7 +1457,7 @@ static void __exit qpti_exit(void)
MODULE_DESCRIPTION("QlogicISP SBUS driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
-MODULE_VERSION("2.0");
+MODULE_VERSION("2.1");
module_init(qpti_init);
module_exit(qpti_exit);
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
index ef6da2df584..9c053bbaa87 100644
--- a/drivers/scsi/qlogicpti.h
+++ b/drivers/scsi/qlogicpti.h
@@ -342,7 +342,7 @@ struct qlogicpti {
u_int req_in_ptr; /* index of next request slot */
u_int res_out_ptr; /* index of next result slot */
long send_marker; /* must we send a marker? */
- struct sbus_dev *sdev;
+ struct of_device *op;
unsigned long __pad;
int cmd_count[MAX_TARGETS];
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ee6be596503..f8b79d401d5 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -291,7 +291,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
unsigned long flags;
cmd->device = dev;
- init_timer(&cmd->eh_timeout);
INIT_LIST_HEAD(&cmd->list);
spin_lock_irqsave(&dev->list_lock, flags);
list_add_tail(&cmd->list, &dev->cmd_list);
@@ -652,26 +651,33 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
unsigned long timeout;
int rtn = 0;
+ /*
+ * We will use a queued command if possible, otherwise we will
+ * emulate the queuing and calling of completion function ourselves.
+ */
+ atomic_inc(&cmd->device->iorequest_cnt);
+
/* check if the device is still usable */
if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
/* in SDEV_DEL we error all commands. DID_NO_CONNECT
* returns an immediate error upwards, and signals
* that the device is no longer present */
cmd->result = DID_NO_CONNECT << 16;
- atomic_inc(&cmd->device->iorequest_cnt);
- __scsi_done(cmd);
+ scsi_done(cmd);
/* return 0 (because the command has been processed) */
goto out;
}
- /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */
- if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {
+ /* Check to see if the scsi lld made this device blocked. */
+ if (unlikely(scsi_device_blocked(cmd->device))) {
/*
- * in SDEV_BLOCK, the command is just put back on the device
- * queue. The suspend state has already blocked the queue so
- * future requests should not occur until the device
- * transitions out of the suspend state.
+ * in blocked state, the command is just put back on
+ * the device queue. The suspend state has already
+ * blocked the queue so future requests should not
+ * occur until the device transitions out of the
+ * suspend state.
*/
+
scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n"));
@@ -714,21 +720,9 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
host->resetting = 0;
}
- /*
- * AK: unlikely race here: for some reason the timer could
- * expire before the serial number is set up below.
- */
- scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);
-
scsi_log_send(cmd);
/*
- * We will use a queued command if possible, otherwise we will
- * emulate the queuing and calling of completion function ourselves.
- */
- atomic_inc(&cmd->device->iorequest_cnt);
-
- /*
* Before we queue this command, check if the command
* length exceeds what the host adapter can handle.
*/
@@ -744,6 +738,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
spin_lock_irqsave(host->host_lock, flags);
+ /*
+ * AK: unlikely race here: for some reason the timer could
+ * expire before the serial number is set up below.
+ *
+ * TODO: kill serial or move to blk layer
+ */
scsi_cmd_get_serial(host, cmd);
if (unlikely(host->shost_state == SHOST_DEL)) {
@@ -754,12 +754,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn) {
- if (scsi_delete_timer(cmd)) {
- atomic_inc(&cmd->device->iodone_cnt);
- scsi_queue_insert(cmd,
- (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
- rtn : SCSI_MLQUEUE_HOST_BUSY);
- }
+ if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
+ rtn != SCSI_MLQUEUE_TARGET_BUSY)
+ rtn = SCSI_MLQUEUE_HOST_BUSY;
+
+ scsi_queue_insert(cmd, rtn);
+
SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n"));
}
@@ -770,24 +770,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
/**
- * scsi_req_abort_cmd -- Request command recovery for the specified command
- * @cmd: pointer to the SCSI command of interest
- *
- * This function requests that SCSI Core start recovery for the
- * command by deleting the timer and adding the command to the eh
- * queue. It can be called by either LLDDs or SCSI Core. LLDDs who
- * implement their own error recovery MAY ignore the timeout event if
- * they generated scsi_req_abort_cmd.
- */
-void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
-{
- if (!scsi_delete_timer(cmd))
- return;
- scsi_times_out(cmd);
-}
-EXPORT_SYMBOL(scsi_req_abort_cmd);
-
-/**
* scsi_done - Enqueue the finished SCSI command into the done queue.
* @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
* ownership back to SCSI Core -- i.e. the LLDD has finished with it.
@@ -802,42 +784,7 @@ EXPORT_SYMBOL(scsi_req_abort_cmd);
*/
static void scsi_done(struct scsi_cmnd *cmd)
{
- /*
- * We don't have to worry about this one timing out anymore.
- * If we are unable to remove the timer, then the command
- * has already timed out. In which case, we have no choice but to
- * let the timeout function run, as we have no idea where in fact
- * that function could really be. It might be on another processor,
- * etc, etc.
- */
- if (!scsi_delete_timer(cmd))
- return;
- __scsi_done(cmd);
-}
-
-/* Private entry to scsi_done() to complete a command when the timer
- * isn't running --- used by scsi_times_out */
-void __scsi_done(struct scsi_cmnd *cmd)
-{
- struct request *rq = cmd->request;
-
- /*
- * Set the serial numbers back to zero
- */
- cmd->serial_number = 0;
-
- atomic_inc(&cmd->device->iodone_cnt);
- if (cmd->result)
- atomic_inc(&cmd->device->ioerr_cnt);
-
- BUG_ON(!rq);
-
- /*
- * The uptodate/nbytes values don't matter, as we allow partial
- * completes and thus will check this in the softirq callback
- */
- rq->completion_data = cmd;
- blk_complete_request(rq);
+ blk_complete_request(cmd->request);
}
/* Move this to a header if it becomes more generally useful */
@@ -857,6 +804,7 @@ static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
void scsi_finish_command(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
+ struct scsi_target *starget = scsi_target(sdev);
struct Scsi_Host *shost = sdev->host;
struct scsi_driver *drv;
unsigned int good_bytes;
@@ -872,6 +820,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
* XXX(hch): What about locking?
*/
shost->host_blocked = 0;
+ starget->target_blocked = 0;
sdev->device_blocked = 0;
/*
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 880051c89bd..94ed262bdf0 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -112,69 +112,8 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
}
/**
- * scsi_add_timer - Start timeout timer for a single scsi command.
- * @scmd: scsi command that is about to start running.
- * @timeout: amount of time to allow this command to run.
- * @complete: timeout function to call if timer isn't canceled.
- *
- * Notes:
- * This should be turned into an inline function. Each scsi command
- * has its own timer, and as it is added to the queue, we set up the
- * timer. When the command completes, we cancel the timer.
- */
-void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
- void (*complete)(struct scsi_cmnd *))
-{
-
- /*
- * If the clock was already running for this command, then
- * first delete the timer. The timer handling code gets rather
- * confused if we don't do this.
- */
- if (scmd->eh_timeout.function)
- del_timer(&scmd->eh_timeout);
-
- scmd->eh_timeout.data = (unsigned long)scmd;
- scmd->eh_timeout.expires = jiffies + timeout;
- scmd->eh_timeout.function = (void (*)(unsigned long)) complete;
-
- SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
- " %d, (%p)\n", __func__,
- scmd, timeout, complete));
-
- add_timer(&scmd->eh_timeout);
-}
-
-/**
- * scsi_delete_timer - Delete/cancel timer for a given function.
- * @scmd: Cmd that we are canceling timer for
- *
- * Notes:
- * This should be turned into an inline function.
- *
- * Return value:
- * 1 if we were able to detach the timer. 0 if we blew it, and the
- * timer function has already started to run.
- */
-int scsi_delete_timer(struct scsi_cmnd *scmd)
-{
- int rtn;
-
- rtn = del_timer(&scmd->eh_timeout);
-
- SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
- " rtn: %d\n", __func__,
- scmd, rtn));
-
- scmd->eh_timeout.data = (unsigned long)NULL;
- scmd->eh_timeout.function = NULL;
-
- return rtn;
-}
-
-/**
* scsi_times_out - Timeout function for normal scsi commands.
- * @scmd: Cmd that is timing out.
+ * @req: request that is timing out.
*
* Notes:
* We do not need to lock this. There is the potential for a race
@@ -182,9 +121,11 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
* normal completion function determines that the timer has already
* fired, then it mustn't do anything.
*/
-void scsi_times_out(struct scsi_cmnd *scmd)
+enum blk_eh_timer_return scsi_times_out(struct request *req)
{
- enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+ struct scsi_cmnd *scmd = req->special;
+ enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *);
+ enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
scsi_log_completion(scmd, TIMEOUT_ERROR);
@@ -196,22 +137,20 @@ void scsi_times_out(struct scsi_cmnd *scmd)
eh_timed_out = NULL;
if (eh_timed_out)
- switch (eh_timed_out(scmd)) {
- case EH_HANDLED:
- __scsi_done(scmd);
- return;
- case EH_RESET_TIMER:
- scsi_add_timer(scmd, scmd->timeout_per_command,
- scsi_times_out);
- return;
- case EH_NOT_HANDLED:
+ rtn = eh_timed_out(scmd);
+ switch (rtn) {
+ case BLK_EH_NOT_HANDLED:
break;
+ default:
+ return rtn;
}
if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
scmd->result |= DID_TIME_OUT << 16;
- __scsi_done(scmd);
+ return BLK_EH_HANDLED;
}
+
+ return BLK_EH_NOT_HANDLED;
}
/**
@@ -391,7 +330,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
case HARDWARE_ERROR:
if (scmd->device->retry_hwerror)
- return NEEDS_RETRY;
+ return ADD_TO_MLQUEUE;
else
return SUCCESS;
@@ -1126,10 +1065,10 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
struct list_head *done_q)
{
struct scsi_cmnd *scmd, *tgtr_scmd, *next;
- unsigned int id;
+ unsigned int id = 0;
int rtn;
- for (id = 0; id <= shost->max_id; id++) {
+ do {
tgtr_scmd = NULL;
list_for_each_entry(scmd, work_q, eh_entry) {
if (id == scmd_id(scmd)) {
@@ -1137,8 +1076,18 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
break;
}
}
+ if (!tgtr_scmd) {
+ /* not one exactly equal; find the next highest */
+ list_for_each_entry(scmd, work_q, eh_entry) {
+ if (scmd_id(scmd) > id &&
+ (!tgtr_scmd ||
+ scmd_id(tgtr_scmd) > scmd_id(scmd)))
+ tgtr_scmd = scmd;
+ }
+ }
if (!tgtr_scmd)
- continue;
+ /* no more commands, that's it */
+ break;
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
"to target %d\n",
@@ -1157,7 +1106,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
" failed target: "
"%d\n",
current->comm, id));
- }
+ id++;
+ } while(id != 0);
return list_empty(work_q);
}
@@ -1280,6 +1230,40 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
}
/**
+ * scsi_noretry_cmd - determinte if command should be failed fast
+ * @scmd: SCSI cmd to examine.
+ */
+int scsi_noretry_cmd(struct scsi_cmnd *scmd)
+{
+ switch (host_byte(scmd->result)) {
+ case DID_OK:
+ break;
+ case DID_BUS_BUSY:
+ return blk_failfast_transport(scmd->request);
+ case DID_PARITY:
+ return blk_failfast_dev(scmd->request);
+ case DID_ERROR:
+ if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
+ status_byte(scmd->result) == RESERVATION_CONFLICT)
+ return 0;
+ /* fall through */
+ case DID_SOFT_ERROR:
+ return blk_failfast_driver(scmd->request);
+ }
+
+ switch (status_byte(scmd->result)) {
+ case CHECK_CONDITION:
+ /*
+ * assume caller has checked sense and determinted
+ * the check condition was retryable.
+ */
+ return blk_failfast_dev(scmd->request);
+ }
+
+ return 0;
+}
+
+/**
* scsi_decide_disposition - Disposition a cmd on return from LLD.
* @scmd: SCSI cmd to examine.
*
@@ -1351,7 +1335,20 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
case DID_REQUEUE:
return ADD_TO_MLQUEUE;
-
+ case DID_TRANSPORT_DISRUPTED:
+ /*
+ * LLD/transport was disrupted during processing of the IO.
+ * The transport class is now blocked/blocking,
+ * and the transport will decide what to do with the IO
+ * based on its timers and recovery capablilities.
+ */
+ return ADD_TO_MLQUEUE;
+ case DID_TRANSPORT_FAILFAST:
+ /*
+ * The transport decided to failfast the IO (most likely
+ * the fast io fail tmo fired), so send IO directly upwards.
+ */
+ return SUCCESS;
case DID_ERROR:
if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
status_byte(scmd->result) == RESERVATION_CONFLICT)
@@ -1444,7 +1441,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
* even if the request is marked fast fail, we still requeue
* for queue congestion conditions (QUEUE_FULL or BUSY) */
if ((++scmd->retries) <= scmd->allowed
- && !blk_noretry_request(scmd->request)) {
+ && !scsi_noretry_cmd(scmd)) {
return NEEDS_RETRY;
} else {
/*
@@ -1569,7 +1566,7 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
list_del_init(&scmd->eh_entry);
if (scsi_device_online(scmd->device) &&
- !blk_noretry_request(scmd->request) &&
+ !scsi_noretry_cmd(scmd) &&
(++scmd->retries <= scmd->allowed)) {
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
" retry cmd: %p\n",
@@ -1793,7 +1790,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
blk_rq_init(NULL, &req);
scmd->request = &req;
- memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
scmd->cmnd = req.cmd;
@@ -1804,8 +1800,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->sc_data_direction = DMA_BIDIRECTIONAL;
- init_timer(&scmd->eh_timeout);
-
spin_lock_irqsave(shost->host_lock, flags);
shost->tmf_in_progress = 1;
spin_unlock_irqrestore(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ff5d56b3ee4..e5a9526d203 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -114,6 +114,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
+ struct scsi_target *starget = scsi_target(device);
struct request_queue *q = device->request_queue;
unsigned long flags;
@@ -133,10 +134,17 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
* if a command is requeued with no other commands outstanding
* either for the device or for the host.
*/
- if (reason == SCSI_MLQUEUE_HOST_BUSY)
+ switch (reason) {
+ case SCSI_MLQUEUE_HOST_BUSY:
host->host_blocked = host->max_host_blocked;
- else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
+ break;
+ case SCSI_MLQUEUE_DEVICE_BUSY:
device->device_blocked = device->max_device_blocked;
+ break;
+ case SCSI_MLQUEUE_TARGET_BUSY:
+ starget->target_blocked = starget->max_target_blocked;
+ break;
+ }
/*
* Decrement the counters, since these commands are no longer
@@ -460,10 +468,12 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
void scsi_device_unbusy(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
+ struct scsi_target *starget = scsi_target(sdev);
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
+ starget->target_busy--;
if (unlikely(scsi_host_in_recovery(shost) &&
(shost->host_failed || shost->host_eh_scheduled)))
scsi_eh_wakeup(shost);
@@ -519,6 +529,13 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
spin_unlock_irqrestore(shost->host_lock, flags);
}
+static inline int scsi_target_is_busy(struct scsi_target *starget)
+{
+ return ((starget->can_queue > 0 &&
+ starget->target_busy >= starget->can_queue) ||
+ starget->target_blocked);
+}
+
/*
* Function: scsi_run_queue()
*
@@ -533,7 +550,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
*/
static void scsi_run_queue(struct request_queue *q)
{
- struct scsi_device *sdev = q->queuedata;
+ struct scsi_device *starved_head = NULL, *sdev = q->queuedata;
struct Scsi_Host *shost = sdev->host;
unsigned long flags;
@@ -560,6 +577,21 @@ static void scsi_run_queue(struct request_queue *q)
*/
sdev = list_entry(shost->starved_list.next,
struct scsi_device, starved_entry);
+ /*
+ * The *queue_ready functions can add a device back onto the
+ * starved list's tail, so we must check for a infinite loop.
+ */
+ if (sdev == starved_head)
+ break;
+ if (!starved_head)
+ starved_head = sdev;
+
+ if (scsi_target_is_busy(scsi_target(sdev))) {
+ list_move_tail(&sdev->starved_entry,
+ &shost->starved_list);
+ continue;
+ }
+
list_del_init(&sdev->starved_entry);
spin_unlock(shost->host_lock);
@@ -575,13 +607,6 @@ static void scsi_run_queue(struct request_queue *q)
spin_unlock(sdev->request_queue->queue_lock);
spin_lock(shost->host_lock);
- if (unlikely(!list_empty(&sdev->starved_entry)))
- /*
- * sdev lost a race, and was put back on the
- * starved list. This is unlikely but without this
- * in theory we could loop forever.
- */
- break;
}
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -681,7 +706,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
leftover = req->data_len;
/* kill remainder if no retrys */
- if (error && blk_noretry_request(req))
+ if (error && scsi_noretry_cmd(cmd))
blk_end_request(req, error, leftover);
else {
if (requeue) {
@@ -852,7 +877,7 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
int result = cmd->result;
- int this_count = scsi_bufflen(cmd);
+ int this_count;
struct request_queue *q = cmd->device->request_queue;
struct request *req = cmd->request;
int error = 0;
@@ -908,6 +933,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
*/
if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
return;
+ this_count = blk_rq_bytes(req);
/* good_bytes = 0, or (inclusive) there were leftovers and
* result = 0, so scsi_end_request couldn't retry.
@@ -1180,7 +1206,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
cmd->transfersize = req->data_len;
cmd->allowed = req->retries;
- cmd->timeout_per_command = req->timeout;
return BLKPREP_OK;
}
EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd);
@@ -1250,6 +1275,7 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
break;
case SDEV_QUIESCE:
case SDEV_BLOCK:
+ case SDEV_CREATED_BLOCK:
/*
* If the devices is blocked we defer normal commands.
*/
@@ -1343,6 +1369,52 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
return 1;
}
+
+/*
+ * scsi_target_queue_ready: checks if there we can send commands to target
+ * @sdev: scsi device on starget to check.
+ *
+ * Called with the host lock held.
+ */
+static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
+ struct scsi_device *sdev)
+{
+ struct scsi_target *starget = scsi_target(sdev);
+
+ if (starget->single_lun) {
+ if (starget->starget_sdev_user &&
+ starget->starget_sdev_user != sdev)
+ return 0;
+ starget->starget_sdev_user = sdev;
+ }
+
+ if (starget->target_busy == 0 && starget->target_blocked) {
+ /*
+ * unblock after target_blocked iterates to zero
+ */
+ if (--starget->target_blocked == 0) {
+ SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
+ "unblocking target at zero depth\n"));
+ } else {
+ blk_plug_device(sdev->request_queue);
+ return 0;
+ }
+ }
+
+ if (scsi_target_is_busy(starget)) {
+ if (list_empty(&sdev->starved_entry)) {
+ list_add_tail(&sdev->starved_entry,
+ &shost->starved_list);
+ return 0;
+ }
+ }
+
+ /* We're OK to process the command, so we can't be starved */
+ if (!list_empty(&sdev->starved_entry))
+ list_del_init(&sdev->starved_entry);
+ return 1;
+}
+
/*
* scsi_host_queue_ready: if we can send requests to shost, return 1 else
* return 0. We must end up running the queue again whenever 0 is
@@ -1389,6 +1461,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
{
struct scsi_cmnd *cmd = req->special;
struct scsi_device *sdev = cmd->device;
+ struct scsi_target *starget = scsi_target(sdev);
struct Scsi_Host *shost = sdev->host;
blkdev_dequeue_request(req);
@@ -1412,20 +1485,30 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
spin_unlock(sdev->request_queue->queue_lock);
spin_lock(shost->host_lock);
shost->host_busy++;
+ starget->target_busy++;
spin_unlock(shost->host_lock);
spin_lock(sdev->request_queue->queue_lock);
- __scsi_done(cmd);
+ blk_complete_request(req);
}
static void scsi_softirq_done(struct request *rq)
{
- struct scsi_cmnd *cmd = rq->completion_data;
- unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command;
+ struct scsi_cmnd *cmd = rq->special;
+ unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
int disposition;
INIT_LIST_HEAD(&cmd->eh_entry);
+ /*
+ * Set the serial numbers back to zero
+ */
+ cmd->serial_number = 0;
+
+ atomic_inc(&cmd->device->iodone_cnt);
+ if (cmd->result)
+ atomic_inc(&cmd->device->ioerr_cnt);
+
disposition = scsi_decide_disposition(cmd);
if (disposition != SUCCESS &&
time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
@@ -1540,14 +1623,13 @@ static void scsi_request_fn(struct request_queue *q)
goto not_ready;
}
+ if (!scsi_target_queue_ready(shost, sdev))
+ goto not_ready;
+
if (!scsi_host_queue_ready(q, shost, sdev))
goto not_ready;
- if (scsi_target(sdev)->single_lun) {
- if (scsi_target(sdev)->starget_sdev_user &&
- scsi_target(sdev)->starget_sdev_user != sdev)
- goto not_ready;
- scsi_target(sdev)->starget_sdev_user = sdev;
- }
+
+ scsi_target(sdev)->target_busy++;
shost->host_busy++;
/*
@@ -1674,6 +1756,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_prep_rq(q, scsi_prep_fn);
blk_queue_softirq_done(q, scsi_softirq_done);
+ blk_queue_rq_timed_out(q, scsi_times_out);
return q;
}
@@ -2063,10 +2146,13 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
switch (state) {
case SDEV_CREATED:
- /* There are no legal states that come back to
- * created. This is the manually initialised start
- * state */
- goto illegal;
+ switch (oldstate) {
+ case SDEV_CREATED_BLOCK:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
case SDEV_RUNNING:
switch (oldstate) {
@@ -2104,8 +2190,17 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
case SDEV_BLOCK:
switch (oldstate) {
- case SDEV_CREATED:
case SDEV_RUNNING:
+ case SDEV_CREATED_BLOCK:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SDEV_CREATED_BLOCK:
+ switch (oldstate) {
+ case SDEV_CREATED:
break;
default:
goto illegal;
@@ -2393,8 +2488,12 @@ scsi_internal_device_block(struct scsi_device *sdev)
int err = 0;
err = scsi_device_set_state(sdev, SDEV_BLOCK);
- if (err)
- return err;
+ if (err) {
+ err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
+
+ if (err)
+ return err;
+ }
/*
* The device has transitioned to SDEV_BLOCK. Stop the
@@ -2437,8 +2536,12 @@ scsi_internal_device_unblock(struct scsi_device *sdev)
* and goose the device queue if successful.
*/
err = scsi_device_set_state(sdev, SDEV_RUNNING);
- if (err)
- return err;
+ if (err) {
+ err = scsi_device_set_state(sdev, SDEV_CREATED);
+
+ if (err)
+ return err;
+ }
spin_lock_irqsave(q->queue_lock, flags);
blk_start_queue(q);
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index ae7ed9a2266..b37e133de80 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -21,6 +21,7 @@
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/security.h>
+#include <linux/delay.h>
#include <net/sock.h>
#include <net/netlink.h>
@@ -30,6 +31,39 @@
struct sock *scsi_nl_sock = NULL;
EXPORT_SYMBOL_GPL(scsi_nl_sock);
+static DEFINE_SPINLOCK(scsi_nl_lock);
+static struct list_head scsi_nl_drivers;
+
+static u32 scsi_nl_state;
+#define STATE_EHANDLER_BSY 0x00000001
+
+struct scsi_nl_transport {
+ int (*msg_handler)(struct sk_buff *);
+ void (*event_handler)(struct notifier_block *, unsigned long, void *);
+ unsigned int refcnt;
+ int flags;
+};
+
+/* flags values (bit flags) */
+#define HANDLER_DELETING 0x1
+
+static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] =
+ { {NULL, }, };
+
+
+struct scsi_nl_drvr {
+ struct list_head next;
+ int (*dmsg_handler)(struct Scsi_Host *shost, void *payload,
+ u32 len, u32 pid);
+ void (*devt_handler)(struct notifier_block *nb,
+ unsigned long event, void *notify_ptr);
+ struct scsi_host_template *hostt;
+ u64 vendor_id;
+ unsigned int refcnt;
+ int flags;
+};
+
+
/**
* scsi_nl_rcv_msg - Receive message handler.
@@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
struct scsi_nl_hdr *hdr;
- uint32_t rlen;
- int err;
+ unsigned long flags;
+ u32 rlen;
+ int err, tport;
while (skb->len >= NLMSG_SPACE(0)) {
err = 0;
@@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
err = -EBADMSG;
- return;
+ goto next_msg;
}
hdr = NLMSG_DATA(nlh);
@@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
printk(KERN_WARNING "%s: discarding partial message\n",
__func__);
- return;
+ goto next_msg;
}
/*
- * We currently don't support anyone sending us a message
+ * Deliver message to the appropriate transport
*/
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+
+ tport = hdr->transport;
+ if ((tport < SCSI_NL_MAX_TRANSPORTS) &&
+ !(transports[tport].flags & HANDLER_DELETING) &&
+ (transports[tport].msg_handler)) {
+ transports[tport].refcnt++;
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ err = transports[tport].msg_handler(skb);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ transports[tport].refcnt--;
+ } else
+ err = -ENOENT;
+
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
next_msg:
if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
@@ -110,14 +160,42 @@ static int
scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct netlink_notify *n = ptr;
+ struct scsi_nl_drvr *driver;
+ unsigned long flags;
+ int tport;
if (n->protocol != NETLINK_SCSITRANSPORT)
return NOTIFY_DONE;
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ scsi_nl_state |= STATE_EHANDLER_BSY;
+
/*
- * Currently, we are not tracking PID's, etc. There is nothing
- * to handle.
+ * Pass event on to any transports that may be listening
*/
+ for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) {
+ if (!(transports[tport].flags & HANDLER_DELETING) &&
+ (transports[tport].event_handler)) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ transports[tport].event_handler(this, event, ptr);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+ }
+
+ /*
+ * Pass event on to any drivers that may be listening
+ */
+ list_for_each_entry(driver, &scsi_nl_drivers, next) {
+ if (!(driver->flags & HANDLER_DELETING) &&
+ (driver->devt_handler)) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ driver->devt_handler(this, event, ptr);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+ }
+
+ scsi_nl_state &= ~STATE_EHANDLER_BSY;
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
return NOTIFY_DONE;
}
@@ -128,7 +206,281 @@ static struct notifier_block scsi_netlink_notifier = {
/**
- * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface
+ * GENERIC SCSI transport receive and event handlers
+ **/
+
+/**
+ * scsi_generic_msg_handler - receive message handler for GENERIC transport
+ * messages
+ *
+ * @skb: socket receive buffer
+ *
+ **/
+static int
+scsi_generic_msg_handler(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(skb);
+ struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh);
+ struct scsi_nl_drvr *driver;
+ struct Scsi_Host *shost;
+ unsigned long flags;
+ int err = 0, match, pid;
+
+ pid = NETLINK_CREDS(skb)->pid;
+
+ switch (snlh->msgtype) {
+ case SCSI_NL_SHOST_VENDOR:
+ {
+ struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh);
+
+ /* Locate the driver that corresponds to the message */
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ match = 0;
+ list_for_each_entry(driver, &scsi_nl_drivers, next) {
+ if (driver->vendor_id == msg->vendor_id) {
+ match = 1;
+ break;
+ }
+ }
+
+ if ((!match) || (!driver->dmsg_handler)) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ err = -ESRCH;
+ goto rcv_exit;
+ }
+
+ if (driver->flags & HANDLER_DELETING) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ err = -ESHUTDOWN;
+ goto rcv_exit;
+ }
+
+ driver->refcnt++;
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+
+
+ /* if successful, scsi_host_lookup takes a shost reference */
+ shost = scsi_host_lookup(msg->host_no);
+ if (!shost) {
+ err = -ENODEV;
+ goto driver_exit;
+ }
+
+ /* is this host owned by the vendor ? */
+ if (shost->hostt != driver->hostt) {
+ err = -EINVAL;
+ goto vendormsg_put;
+ }
+
+ /* pass message on to the driver */
+ err = driver->dmsg_handler(shost, (void *)&msg[1],
+ msg->vmsg_datalen, pid);
+
+vendormsg_put:
+ /* release reference by scsi_host_lookup */
+ scsi_host_put(shost);
+
+driver_exit:
+ /* release our own reference on the registration object */
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ driver->refcnt--;
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ break;
+ }
+
+ default:
+ err = -EBADR;
+ break;
+ }
+
+rcv_exit:
+ if (err)
+ printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
+ __func__, snlh->msgtype, err);
+ return err;
+}
+
+
+/**
+ * scsi_nl_add_transport -
+ * Registers message and event handlers for a transport. Enables
+ * receipt of netlink messages and events to a transport.
+ *
+ * @tport: transport registering handlers
+ * @msg_handler: receive message handler callback
+ * @event_handler: receive event handler callback
+ **/
+int
+scsi_nl_add_transport(u8 tport,
+ int (*msg_handler)(struct sk_buff *),
+ void (*event_handler)(struct notifier_block *, unsigned long, void *))
+{
+ unsigned long flags;
+ int err = 0;
+
+ if (tport >= SCSI_NL_MAX_TRANSPORTS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+
+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ msleep(1);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+
+ if (transports[tport].msg_handler || transports[tport].event_handler) {
+ err = -EALREADY;
+ goto register_out;
+ }
+
+ transports[tport].msg_handler = msg_handler;
+ transports[tport].event_handler = event_handler;
+ transports[tport].flags = 0;
+ transports[tport].refcnt = 0;
+
+register_out:
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(scsi_nl_add_transport);
+
+
+/**
+ * scsi_nl_remove_transport -
+ * Disable transport receiption of messages and events
+ *
+ * @tport: transport deregistering handlers
+ *
+ **/
+void
+scsi_nl_remove_transport(u8 tport)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ msleep(1);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+
+ if (tport < SCSI_NL_MAX_TRANSPORTS) {
+ transports[tport].flags |= HANDLER_DELETING;
+
+ while (transports[tport].refcnt != 0) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ schedule_timeout_uninterruptible(HZ/4);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+ transports[tport].msg_handler = NULL;
+ transports[tport].event_handler = NULL;
+ transports[tport].flags = 0;
+ }
+
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+
+ return;
+}
+EXPORT_SYMBOL_GPL(scsi_nl_remove_transport);
+
+
+/**
+ * scsi_nl_add_driver -
+ * A driver is registering its interfaces for SCSI netlink messages
+ *
+ * @vendor_id: A unique identification value for the driver.
+ * @hostt: address of the driver's host template. Used
+ * to verify an shost is bound to the driver
+ * @nlmsg_handler: receive message handler callback
+ * @nlevt_handler: receive event handler callback
+ *
+ * Returns:
+ * 0 on Success
+ * error result otherwise
+ **/
+int
+scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
+ int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
+ u32 len, u32 pid),
+ void (*nlevt_handler)(struct notifier_block *nb,
+ unsigned long event, void *notify_ptr))
+{
+ struct scsi_nl_drvr *driver;
+ unsigned long flags;
+
+ driver = kzalloc(sizeof(*driver), GFP_KERNEL);
+ if (unlikely(!driver)) {
+ printk(KERN_ERR "%s: allocation failure\n", __func__);
+ return -ENOMEM;
+ }
+
+ driver->dmsg_handler = nlmsg_handler;
+ driver->devt_handler = nlevt_handler;
+ driver->hostt = hostt;
+ driver->vendor_id = vendor_id;
+
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ msleep(1);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+ list_add_tail(&driver->next, &scsi_nl_drivers);
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_nl_add_driver);
+
+
+/**
+ * scsi_nl_remove_driver -
+ * An driver is unregistering with the SCSI netlink messages
+ *
+ * @vendor_id: The unique identification value for the driver.
+ **/
+void
+scsi_nl_remove_driver(u64 vendor_id)
+{
+ struct scsi_nl_drvr *driver;
+ unsigned long flags;
+
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ msleep(1);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+
+ list_for_each_entry(driver, &scsi_nl_drivers, next) {
+ if (driver->vendor_id == vendor_id) {
+ driver->flags |= HANDLER_DELETING;
+ while (driver->refcnt != 0) {
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ schedule_timeout_uninterruptible(HZ/4);
+ spin_lock_irqsave(&scsi_nl_lock, flags);
+ }
+ list_del(&driver->next);
+ kfree(driver);
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+ return;
+ }
+ }
+
+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
+
+ printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n",
+ __func__, (unsigned long long)vendor_id);
+ return;
+}
+EXPORT_SYMBOL_GPL(scsi_nl_remove_driver);
+
+
+/**
+ * scsi_netlink_init - Called by SCSI subsystem to intialize
+ * the SCSI transport netlink interface
*
**/
void
@@ -136,6 +488,8 @@ scsi_netlink_init(void)
{
int error;
+ INIT_LIST_HEAD(&scsi_nl_drivers);
+
error = netlink_register_notifier(&scsi_netlink_notifier);
if (error) {
printk(KERN_ERR "%s: register of event handler failed - %d\n",
@@ -150,8 +504,15 @@ scsi_netlink_init(void)
printk(KERN_ERR "%s: register of recieve handler failed\n",
__func__);
netlink_unregister_notifier(&scsi_netlink_notifier);
+ return;
}
+ /* Register the entry points for the generic SCSI transport */
+ error = scsi_nl_add_transport(SCSI_NL_TRANSPORT,
+ scsi_generic_msg_handler, NULL);
+ if (error)
+ printk(KERN_ERR "%s: register of GENERIC transport handler"
+ " failed - %d\n", __func__, error);
return;
}
@@ -163,6 +524,8 @@ scsi_netlink_init(void)
void
scsi_netlink_exit(void)
{
+ scsi_nl_remove_transport(SCSI_NL_TRANSPORT);
+
if (scsi_nl_sock) {
netlink_kernel_release(scsi_nl_sock);
netlink_unregister_notifier(&scsi_netlink_notifier);
@@ -172,3 +535,147 @@ scsi_netlink_exit(void)
}
+/*
+ * Exported Interfaces
+ */
+
+/**
+ * scsi_nl_send_transport_msg -
+ * Generic function to send a single message from a SCSI transport to
+ * a single process
+ *
+ * @pid: receiving pid
+ * @hdr: message payload
+ *
+ **/
+void
+scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ const char *fn;
+ char *datab;
+ u32 len, skblen;
+ int err;
+
+ if (!scsi_nl_sock) {
+ err = -ENOENT;
+ fn = "netlink socket";
+ goto msg_fail;
+ }
+
+ len = NLMSG_SPACE(hdr->msglen);
+ skblen = NLMSG_SPACE(len);
+
+ skb = alloc_skb(skblen, GFP_KERNEL);
+ if (!skb) {
+ err = -ENOBUFS;
+ fn = "alloc_skb";
+ goto msg_fail;
+ }
+
+ nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0);
+ if (!nlh) {
+ err = -ENOBUFS;
+ fn = "nlmsg_put";
+ goto msg_fail_skb;
+ }
+ datab = NLMSG_DATA(nlh);
+ memcpy(datab, hdr, hdr->msglen);
+
+ err = nlmsg_unicast(scsi_nl_sock, skb, pid);
+ if (err < 0) {
+ fn = "nlmsg_unicast";
+ /* nlmsg_unicast already kfree_skb'd */
+ goto msg_fail;
+ }
+
+ return;
+
+msg_fail_skb:
+ kfree_skb(skb);
+msg_fail:
+ printk(KERN_WARNING
+ "%s: Dropped Message : pid %d Transport %d, msgtype x%x, "
+ "msglen %d: %s : err %d\n",
+ __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen,
+ fn, err);
+ return;
+}
+EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg);
+
+
+/**
+ * scsi_nl_send_vendor_msg - called to send a shost vendor unique message
+ * to a specific process id.
+ *
+ * @pid: process id of the receiver
+ * @host_no: host # sending the message
+ * @vendor_id: unique identifier for the driver's vendor
+ * @data_len: amount, in bytes, of vendor unique payload data
+ * @data_buf: pointer to vendor unique data buffer
+ *
+ * Returns:
+ * 0 on succesful return
+ * otherwise, failing error code
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+int
+scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
+ char *data_buf, u32 data_len)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct scsi_nl_host_vendor_msg *msg;
+ u32 len, skblen;
+ int err;
+
+ if (!scsi_nl_sock) {
+ err = -ENOENT;
+ goto send_vendor_fail;
+ }
+
+ len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len);
+ skblen = NLMSG_SPACE(len);
+
+ skb = alloc_skb(skblen, GFP_KERNEL);
+ if (!skb) {
+ err = -ENOBUFS;
+ goto send_vendor_fail;
+ }
+
+ nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
+ skblen - sizeof(*nlh), 0);
+ if (!nlh) {
+ err = -ENOBUFS;
+ goto send_vendor_fail_skb;
+ }
+ msg = NLMSG_DATA(nlh);
+
+ INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT,
+ SCSI_NL_SHOST_VENDOR, len);
+ msg->vendor_id = vendor_id;
+ msg->host_no = host_no;
+ msg->vmsg_datalen = data_len; /* bytes */
+ memcpy(&msg[1], data_buf, data_len);
+
+ err = nlmsg_unicast(scsi_nl_sock, skb, pid);
+ if (err)
+ /* nlmsg_multicast already kfree_skb'd */
+ goto send_vendor_fail;
+
+ return 0;
+
+send_vendor_fail_skb:
+ kfree_skb(skb);
+send_vendor_fail:
+ printk(KERN_WARNING
+ "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n",
+ __func__, host_no, err);
+ return err;
+}
+EXPORT_SYMBOL(scsi_nl_send_vendor_msg);
+
+
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 79f0f751120..e1850904ff7 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -4,6 +4,7 @@
#include <linux/device.h>
struct request_queue;
+struct request;
struct scsi_cmnd;
struct scsi_device;
struct scsi_host_template;
@@ -27,7 +28,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 void __scsi_done(struct scsi_cmnd *cmd);
#ifdef CONFIG_SCSI_LOGGING
void scsi_log_send(struct scsi_cmnd *cmd);
void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
@@ -49,10 +49,7 @@ extern int __init scsi_init_devinfo(void);
extern void scsi_exit_devinfo(void);
/* scsi_error.c */
-extern void scsi_add_timer(struct scsi_cmnd *, int,
- void (*)(struct scsi_cmnd *));
-extern int scsi_delete_timer(struct scsi_cmnd *);
-extern void scsi_times_out(struct scsi_cmnd *cmd);
+extern enum blk_eh_timer_return scsi_times_out(struct request *req);
extern int scsi_error_handler(void *host);
extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
extern void scsi_eh_wakeup(struct Scsi_Host *shost);
@@ -62,6 +59,7 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
struct list_head *done_q);
int scsi_eh_get_sense(struct list_head *work_q,
struct list_head *done_q);
+int scsi_noretry_cmd(struct scsi_cmnd *scmd);
/* scsi_lib.c */
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index c6a904a45bf..82f7b2dd08a 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -259,8 +259,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
int error = -ENXIO;
shost = scsi_host_lookup(host);
- if (IS_ERR(shost))
- return PTR_ERR(shost);
+ if (!shost)
+ return error;
if (shost->transportt->user_scan)
error = shost->transportt->user_scan(shost, channel, id, lun);
@@ -287,8 +287,8 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
int error = -ENXIO;
shost = scsi_host_lookup(host);
- if (IS_ERR(shost))
- return PTR_ERR(shost);
+ if (!shost)
+ return error;
sdev = scsi_device_lookup(shost, channel, id, lun);
if (sdev) {
scsi_remove_device(sdev);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 84b4879cff1..b14dc02c3de 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -419,6 +419,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
dev->type = &scsi_target_type;
starget->id = id;
starget->channel = channel;
+ starget->can_queue = 0;
INIT_LIST_HEAD(&starget->siblings);
INIT_LIST_HEAD(&starget->devices);
starget->state = STARGET_CREATED;
@@ -730,6 +731,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
int *bflags, int async)
{
+ int ret;
+
/*
* XXX do not save the inquiry, since it can change underneath us,
* save just vendor/model/rev.
@@ -885,7 +888,17 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
/* set the device running here so that slave configure
* may do I/O */
- scsi_device_set_state(sdev, SDEV_RUNNING);
+ ret = scsi_device_set_state(sdev, SDEV_RUNNING);
+ if (ret) {
+ ret = scsi_device_set_state(sdev, SDEV_BLOCK);
+
+ if (ret) {
+ sdev_printk(KERN_ERR, sdev,
+ "in wrong state %s to complete scan\n",
+ scsi_device_state_name(sdev->sdev_state));
+ return SCSI_SCAN_NO_RESPONSE;
+ }
+ }
if (*bflags & BLIST_MS_192_BYTES_FOR_3F)
sdev->use_192_bytes_for_3f = 1;
@@ -899,7 +912,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
transport_configure_device(&sdev->sdev_gendev);
if (sdev->host->hostt->slave_configure) {
- int ret = sdev->host->hostt->slave_configure(sdev);
+ ret = sdev->host->hostt->slave_configure(sdev);
if (ret) {
/*
* if LLDD reports slave not present, don't clutter
@@ -994,7 +1007,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
*/
sdev = scsi_device_lookup_by_target(starget, lun);
if (sdev) {
- if (rescan || sdev->sdev_state != SDEV_CREATED) {
+ if (rescan || !scsi_device_created(sdev)) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: device exists on %s\n",
sdev->sdev_gendev.bus_id));
@@ -1080,7 +1093,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
* PDT=1Fh none (no FDD connected to the requested logical unit)
*/
if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) &&
- (result[0] & 0x1f) == 0x1f) {
+ (result[0] & 0x1f) == 0x1f &&
+ !scsi_is_wlun(lun)) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: peripheral device type"
" of 31, no device added\n"));
@@ -1466,7 +1480,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
kfree(lun_data);
out:
scsi_device_put(sdev);
- if (sdev->sdev_state == SDEV_CREATED)
+ if (scsi_device_created(sdev))
/*
* the sdev we used didn't appear in the report luns scan
*/
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index ab3c71869be..93c28f30bbd 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -34,6 +34,7 @@ static const struct {
{ SDEV_QUIESCE, "quiesce" },
{ SDEV_OFFLINE, "offline" },
{ SDEV_BLOCK, "blocked" },
+ { SDEV_CREATED_BLOCK, "created-blocked" },
};
const char *scsi_device_state_name(enum scsi_device_state state)
@@ -560,12 +561,15 @@ sdev_rd_attr (vendor, "%.8s\n");
sdev_rd_attr (model, "%.16s\n");
sdev_rd_attr (rev, "%.4s\n");
+/*
+ * TODO: can we make these symlinks to the block layer ones?
+ */
static ssize_t
sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev;
sdev = to_scsi_device(dev);
- return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
+ return snprintf(buf, 20, "%d\n", sdev->request_queue->rq_timeout / HZ);
}
static ssize_t
@@ -576,7 +580,7 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr,
int timeout;
sdev = to_scsi_device(dev);
sscanf (buf, "%d\n", &timeout);
- sdev->timeout = timeout * HZ;
+ blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
return count;
}
static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index 257e097c39a..48ba413f7f6 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -362,7 +362,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
int err;
dprintk("%lx %u\n", uaddr, len);
- err = blk_rq_map_user(q, rq, (void *)uaddr, len);
+ err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL);
if (err) {
/*
* TODO: need to fixup sg_tablesize, max_segment_size,
@@ -460,7 +460,7 @@ int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag,
/* TODO: replace with a O(1) alg */
shost = scsi_host_lookup(host_no);
- if (IS_ERR(shost)) {
+ if (!shost) {
printk(KERN_ERR "Could not find host no %d\n", host_no);
return -EINVAL;
}
@@ -550,7 +550,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result)
dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
shost = scsi_host_lookup(host_no);
- if (IS_ERR(shost)) {
+ if (!shost) {
printk(KERN_ERR "Could not find host no %d\n", host_no);
return err;
}
@@ -603,7 +603,7 @@ int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result)
dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id);
shost = scsi_host_lookup(host_no);
- if (IS_ERR(shost)) {
+ if (!shost) {
printk(KERN_ERR "Could not find host no %d\n", host_no);
return err;
}
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 56823fd1fb8..1e71abf0607 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -40,31 +40,7 @@
static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
static void fc_vport_sched_delete(struct work_struct *work);
-
-/*
- * This is a temporary carrier for creating a vport. It will eventually
- * be replaced by a real message definition for sgio or netlink.
- *
- * fc_vport_identifiers: This set of data contains all elements
- * to uniquely identify and instantiate a FC virtual port.
- *
- * Notes:
- * symbolic_name: The driver is to append the symbolic_name string data
- * to the symbolic_node_name data that it generates by default.
- * the resulting combination should then be registered with the switch.
- * It is expected that things like Xen may stuff a VM title into
- * this field.
- */
-struct fc_vport_identifiers {
- u64 node_name;
- u64 port_name;
- u32 roles;
- bool disable;
- enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
- char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
-};
-
-static int fc_vport_create(struct Scsi_Host *shost, int channel,
+static int fc_vport_setup(struct Scsi_Host *shost, int channel,
struct device *pdev, struct fc_vport_identifiers *ids,
struct fc_vport **vport);
@@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,
vid.disable = false; /* always enabled */
/* we only allow support on Channel 0 !!! */
- stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+ stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);
return stat ? stat : count;
}
static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
@@ -1950,15 +1926,15 @@ static int fc_vport_match(struct attribute_container *cont,
* Notes:
* This routine assumes no locks are held on entry.
*/
-static enum scsi_eh_timer_return
+static enum blk_eh_timer_return
fc_timed_out(struct scsi_cmnd *scmd)
{
struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
if (rport->port_state == FC_PORTSTATE_BLOCKED)
- return EH_RESET_TIMER;
+ return BLK_EH_RESET_TIMER;
- return EH_NOT_HANDLED;
+ return BLK_EH_NOT_HANDLED;
}
/*
@@ -2157,8 +2133,7 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
- if (ft->terminate_rport_io)
- SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
BUG_ON(count > FC_RPORT_NUM_ATTRS);
@@ -2352,6 +2327,22 @@ fc_remove_host(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(fc_remove_host);
+static void fc_terminate_rport_io(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+
+ /* Involve the LLDD if possible to terminate all io on the rport. */
+ if (i->f->terminate_rport_io)
+ i->f->terminate_rport_io(rport);
+
+ /*
+ * must unblock to flush queued IO. The caller will have set
+ * the port_state or flags, so that fc_remote_port_chkready will
+ * fail IO.
+ */
+ scsi_target_unblock(&rport->dev);
+}
/**
* fc_starget_delete - called to delete the scsi decendents of an rport
@@ -2364,13 +2355,8 @@ fc_starget_delete(struct work_struct *work)
{
struct fc_rport *rport =
container_of(work, struct fc_rport, stgt_delete_work);
- struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_internal *i = to_fc_internal(shost->transportt);
-
- /* Involve the LLDD if possible to terminate all io on the rport. */
- if (i->f->terminate_rport_io)
- i->f->terminate_rport_io(rport);
+ fc_terminate_rport_io(rport);
scsi_remove_target(&rport->dev);
}
@@ -2396,10 +2382,7 @@ fc_rport_final_delete(struct work_struct *work)
if (rport->flags & FC_RPORT_SCAN_PENDING)
scsi_flush_work(shost);
- /* involve the LLDD to terminate all pending i/o */
- if (i->f->terminate_rport_io)
- i->f->terminate_rport_io(rport);
-
+ fc_terminate_rport_io(rport);
/*
* Cancel any outstanding timers. These should really exist
* only when rmmod'ing the LLDD and we're asking for
@@ -2663,7 +2646,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
spin_lock_irqsave(shost->host_lock, flags);
- rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
+ FC_RPORT_DEVLOSS_PENDING);
/* if target, initiate a scan */
if (rport->scsi_target_id != -1) {
@@ -2726,6 +2710,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
rport->port_id = ids->port_id;
rport->roles = ids->roles;
rport->port_state = FC_PORTSTATE_ONLINE;
+ rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
if (fci->f->dd_fcrport_size)
memset(rport->dd_data, 0,
@@ -2808,7 +2793,6 @@ void
fc_remote_port_delete(struct fc_rport *rport)
{
struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_internal *i = to_fc_internal(shost->transportt);
int timeout = rport->dev_loss_tmo;
unsigned long flags;
@@ -2854,7 +2838,7 @@ fc_remote_port_delete(struct fc_rport *rport)
/* see if we need to kill io faster than waiting for device loss */
if ((rport->fast_io_fail_tmo != -1) &&
- (rport->fast_io_fail_tmo < timeout) && (i->f->terminate_rport_io))
+ (rport->fast_io_fail_tmo < timeout))
fc_queue_devloss_work(shost, &rport->fail_io_work,
rport->fast_io_fail_tmo * HZ);
@@ -2930,7 +2914,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
fc_flush_devloss(shost);
spin_lock_irqsave(shost->host_lock, flags);
- rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
+ FC_RPORT_DEVLOSS_PENDING);
spin_unlock_irqrestore(shost->host_lock, flags);
/* ensure any stgt delete functions are done */
@@ -3025,6 +3010,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
rport->supported_classes = FC_COS_UNSPECIFIED;
rport->roles = FC_PORT_ROLE_UNKNOWN;
rport->port_state = FC_PORTSTATE_NOTPRESENT;
+ rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
/* remove the identifiers that aren't used in the consisting binding */
switch (fc_host->tgtid_bind_type) {
@@ -3067,13 +3053,12 @@ fc_timeout_fail_rport_io(struct work_struct *work)
{
struct fc_rport *rport =
container_of(work, struct fc_rport, fail_io_work.work);
- struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_internal *i = to_fc_internal(shost->transportt);
if (rport->port_state != FC_PORTSTATE_BLOCKED)
return;
- i->f->terminate_rport_io(rport);
+ rport->flags |= FC_RPORT_FAST_FAIL_TIMEDOUT;
+ fc_terminate_rport_io(rport);
}
/**
@@ -3103,7 +3088,7 @@ fc_scsi_scan_rport(struct work_struct *work)
/**
- * fc_vport_create - allocates and creates a FC virtual port.
+ * fc_vport_setup - allocates and creates a FC virtual port.
* @shost: scsi host the virtual port is connected to.
* @channel: Channel on shost port connected to.
* @pdev: parent device for vport
@@ -3118,7 +3103,7 @@ fc_scsi_scan_rport(struct work_struct *work)
* This routine assumes no locks are held on entry.
*/
static int
-fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
+fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
struct fc_vport_identifiers *ids, struct fc_vport **ret_vport)
{
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
@@ -3231,6 +3216,28 @@ delete_vport:
return error;
}
+/**
+ * fc_vport_create - Admin App or LLDD requests creation of a vport
+ * @shost: scsi host the virtual port is connected to.
+ * @channel: channel on shost port connected to.
+ * @ids: The world wide names, FC4 port roles, etc for
+ * the virtual port.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+struct fc_vport *
+fc_vport_create(struct Scsi_Host *shost, int channel,
+ struct fc_vport_identifiers *ids)
+{
+ int stat;
+ struct fc_vport *vport;
+
+ stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
+ ids, &vport);
+ return stat ? NULL : vport;
+}
+EXPORT_SYMBOL(fc_vport_create);
/**
* fc_vport_terminate - Admin App or LLDD requests termination of a vport
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 043c3921164..4a803ebaf50 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -138,7 +138,7 @@ static ssize_t
show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
- return sprintf(buf, "%u\n", ep->id);
+ return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
}
static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
@@ -156,7 +156,7 @@ static struct attribute_group iscsi_endpoint_group = {
static int iscsi_match_epid(struct device *dev, void *data)
{
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
- unsigned int *epid = (unsigned int *) data;
+ uint64_t *epid = (uint64_t *) data;
return *epid == ep->id;
}
@@ -166,7 +166,7 @@ iscsi_create_endpoint(int dd_size)
{
struct device *dev;
struct iscsi_endpoint *ep;
- unsigned int id;
+ uint64_t id;
int err;
for (id = 1; id < ISCSI_MAX_EPID; id++) {
@@ -187,7 +187,8 @@ iscsi_create_endpoint(int dd_size)
ep->id = id;
ep->dev.class = &iscsi_endpoint_class;
- snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
+ snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%llu",
+ (unsigned long long) id);
err = device_register(&ep->dev);
if (err)
goto free_ep;
@@ -374,10 +375,10 @@ int iscsi_session_chkready(struct iscsi_cls_session *session)
err = 0;
break;
case ISCSI_SESSION_FAILED:
- err = DID_IMM_RETRY << 16;
+ err = DID_TRANSPORT_DISRUPTED << 16;
break;
case ISCSI_SESSION_FREE:
- err = DID_NO_CONNECT << 16;
+ err = DID_TRANSPORT_FAILFAST << 16;
break;
default:
err = DID_NO_CONNECT << 16;
@@ -1010,7 +1011,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
skb = alloc_skb(len, GFP_ATOMIC);
if (!skb) {
- iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
"control PDU: OOM\n");
return -ENOMEM;
@@ -1031,7 +1032,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
}
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
-void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
{
struct nlmsghdr *nlh;
struct sk_buff *skb;
@@ -1063,7 +1064,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
error);
}
-EXPORT_SYMBOL_GPL(iscsi_conn_error);
+EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
static int
iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
@@ -1361,7 +1362,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport,
return -EINVAL;
shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
- if (IS_ERR(shost)) {
+ if (!shost) {
printk(KERN_ERR "target discovery could not find host no %u\n",
ev->u.tgt_dscvr.host_no);
return -ENODEV;
@@ -1387,7 +1388,7 @@ iscsi_set_host_param(struct iscsi_transport *transport,
return -ENOSYS;
shost = scsi_host_lookup(ev->u.set_host_param.host_no);
- if (IS_ERR(shost)) {
+ if (!shost) {
printk(KERN_ERR "set_host_param could not find host no %u\n",
ev->u.set_host_param.host_no);
return -ENODEV;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index b29360ed0bd..7c2d28924d2 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -109,7 +109,9 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
for(i = 0; i < DV_RETRIES; i++) {
result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
sense, DV_TIMEOUT, /* retries */ 1,
- REQ_FAILFAST);
+ REQ_FAILFAST_DEV |
+ REQ_FAILFAST_TRANSPORT |
+ REQ_FAILFAST_DRIVER);
if (result & DRIVER_SENSE) {
struct scsi_sense_hdr sshdr_tmp;
if (!sshdr)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index e5e7d785645..7c4d2e68df1 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -47,6 +47,7 @@
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/string_helpers.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -86,6 +87,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
+#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
+#define SD_MINORS 16
+#else
+#define SD_MINORS 0
+#endif
+
static int sd_revalidate_disk(struct gendisk *);
static int sd_probe(struct device *);
static int sd_remove(struct device *);
@@ -159,7 +166,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
sd_print_sense_hdr(sdkp, &sshdr);
return -EINVAL;
}
- sd_revalidate_disk(sdkp->disk);
+ revalidate_disk(sdkp->disk);
return count;
}
@@ -377,8 +384,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
sector_t block = rq->sector;
sector_t threshold;
unsigned int this_count = rq->nr_sectors;
- unsigned int timeout = sdp->timeout;
- int ret;
+ int ret, host_dif;
if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
ret = scsi_setup_blk_pc_cmnd(sdp, rq);
@@ -509,7 +515,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
rq->nr_sectors));
/* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */
- if (scsi_host_dif_capable(sdp->host, sdkp->protection_type))
+ host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type);
+ if (host_dif)
SCpnt->cmnd[1] = 1 << 5;
else
SCpnt->cmnd[1] = 0;
@@ -567,8 +574,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
SCpnt->sdb.length = this_count * sdp->sector_size;
/* If DIF or DIX is enabled, tell HBA how to handle request */
- if (sdkp->protection_type || scsi_prot_sg_count(SCpnt))
- sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt));
+ if (host_dif || scsi_prot_sg_count(SCpnt))
+ sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt),
+ sdkp->protection_type);
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -578,7 +586,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
SCpnt->transfersize = sdp->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = SD_MAX_RETRIES;
- SCpnt->timeout_per_command = timeout;
/*
* This indicates that the command is ready from our end to be
@@ -910,7 +917,7 @@ static void sd_rescan(struct device *dev)
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
if (sdkp) {
- sd_revalidate_disk(sdkp->disk);
+ revalidate_disk(sdkp->disk);
scsi_disk_put(sdkp);
}
}
@@ -1247,14 +1254,12 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
else
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
+ sdkp->protection_type = type;
+
switch (type) {
case SD_DIF_TYPE0_PROTECTION:
- sdkp->protection_type = 0;
- break;
-
case SD_DIF_TYPE1_PROTECTION:
case SD_DIF_TYPE3_PROTECTION:
- sdkp->protection_type = type;
break;
case SD_DIF_TYPE2_PROTECTION:
@@ -1272,7 +1277,6 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
return;
disable:
- sdkp->protection_type = 0;
sdkp->capacity = 0;
}
@@ -1429,27 +1433,21 @@ got_data:
*/
sector_size = 512;
}
+ blk_queue_hardsect_size(sdp->request_queue, sector_size);
+
{
- /*
- * The msdos fs needs to know the hardware sector size
- * So I have created this table. See ll_rw_blk.c
- * Jacques Gelinas (Jacques@solucorp.qc.ca)
- */
- int hard_sector = sector_size;
- sector_t sz = (sdkp->capacity/2) * (hard_sector/256);
- struct request_queue *queue = sdp->request_queue;
- sector_t mb = sz;
+ char cap_str_2[10], cap_str_10[10];
+ u64 sz = sdkp->capacity << ffz(~sector_size);
- blk_queue_hardsect_size(queue, hard_sector);
- /* avoid 64-bit division on 32-bit platforms */
- sector_div(sz, 625);
- mb -= sz - 974;
- sector_div(mb, 1950);
+ string_get_size(sz, STRING_UNITS_2, cap_str_2,
+ sizeof(cap_str_2));
+ string_get_size(sz, STRING_UNITS_10, cap_str_10,
+ sizeof(cap_str_10));
sd_printk(KERN_NOTICE, sdkp,
- "%llu %d-byte hardware sectors (%llu MB)\n",
+ "%llu %d-byte hardware sectors: (%s/%s)\n",
(unsigned long long)sdkp->capacity,
- hard_sector, (unsigned long long)mb);
+ sector_size, cap_str_10, cap_str_2);
}
/* Rescale capacity to 512-byte units */
@@ -1764,6 +1762,52 @@ static int sd_revalidate_disk(struct gendisk *disk)
}
/**
+ * sd_format_disk_name - format disk name
+ * @prefix: name prefix - ie. "sd" for SCSI disks
+ * @index: index of the disk to format name for
+ * @buf: output buffer
+ * @buflen: length of the output buffer
+ *
+ * SCSI disk names starts at sda. The 26th device is sdz and the
+ * 27th is sdaa. The last one for two lettered suffix is sdzz
+ * which is followed by sdaaa.
+ *
+ * This is basically 26 base counting with one extra 'nil' entry
+ * at the beggining from the second digit on and can be
+ * determined using similar method as 26 base conversion with the
+ * index shifted -1 after each digit is computed.
+ *
+ * CONTEXT:
+ * Don't care.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
+{
+ const int base = 'z' - 'a' + 1;
+ char *begin = buf + strlen(prefix);
+ char *end = buf + buflen;
+ char *p;
+ int unit;
+
+ p = end - 1;
+ *p = '\0';
+ unit = base;
+ do {
+ if (p == begin)
+ return -EINVAL;
+ *--p = 'a' + (index % unit);
+ index = (index / unit) - 1;
+ } while (index >= 0);
+
+ memmove(begin, p, end - p);
+ memcpy(buf, prefix, strlen(prefix));
+
+ return 0;
+}
+
+/**
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
* for each scsi device (not just disks) present.
@@ -1801,7 +1845,7 @@ static int sd_probe(struct device *dev)
if (!sdkp)
goto out;
- gd = alloc_disk(16);
+ gd = alloc_disk(SD_MINORS);
if (!gd)
goto out_free;
@@ -1815,8 +1859,8 @@ static int sd_probe(struct device *dev)
if (error)
goto out_put;
- error = -EBUSY;
- if (index >= SD_MAX_DISKS)
+ error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
+ if (error)
goto out_free_index;
sdkp->device = sdp;
@@ -1826,11 +1870,12 @@ static int sd_probe(struct device *dev)
sdkp->openers = 0;
sdkp->previous_state = 1;
- if (!sdp->timeout) {
+ if (!sdp->request_queue->rq_timeout) {
if (sdp->type != TYPE_MOD)
- sdp->timeout = SD_TIMEOUT;
+ blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
else
- sdp->timeout = SD_MOD_TIMEOUT;
+ blk_queue_rq_timeout(sdp->request_queue,
+ SD_MOD_TIMEOUT);
}
device_initialize(&sdkp->dev);
@@ -1843,24 +1888,12 @@ static int sd_probe(struct device *dev)
get_device(&sdp->sdev_gendev);
- gd->major = sd_major((index & 0xf0) >> 4);
- gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
- gd->minors = 16;
- gd->fops = &sd_fops;
-
- if (index < 26) {
- sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
- } else if (index < (26 + 1) * 26) {
- sprintf(gd->disk_name, "sd%c%c",
- 'a' + index / 26 - 1,'a' + index % 26);
- } else {
- const unsigned int m1 = (index / 26 - 1) / 26 - 1;
- const unsigned int m2 = (index / 26 - 1) % 26;
- const unsigned int m3 = index % 26;
- sprintf(gd->disk_name, "sd%c%c%c",
- 'a' + m1, 'a' + m2, 'a' + m3);
+ if (index < SD_MAX_DISKS) {
+ gd->major = sd_major((index & 0xf0) >> 4);
+ gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+ gd->minors = SD_MINORS;
}
-
+ gd->fops = &sd_fops;
gd->private_data = &sdkp->driver;
gd->queue = sdkp->device->request_queue;
@@ -1869,7 +1902,7 @@ static int sd_probe(struct device *dev)
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
gd->driverfs_dev = &sdp->sdev_gendev;
- gd->flags = GENHD_FL_DRIVERFS;
+ gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 95b9f06534d..75638e7d3f6 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -97,19 +97,28 @@ struct sd_dif_tuple {
__be32 ref_tag; /* Target LBA or indirect LBA */
};
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
+#ifdef CONFIG_BLK_DEV_INTEGRITY
-extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int);
+extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int);
extern void sd_dif_config_host(struct scsi_disk *);
extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int);
extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
#else /* CONFIG_BLK_DEV_INTEGRITY */
-#define sd_dif_op(a, b, c) do { } while (0)
-#define sd_dif_config_host(a) do { } while (0)
-#define sd_dif_prepare(a, b, c) (0)
-#define sd_dif_complete(a, b) (0)
+static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c)
+{
+}
+static inline void sd_dif_config_host(struct scsi_disk *disk)
+{
+}
+static inline int sd_dif_prepare(struct request *rq, sector_t s, unsigned int a)
+{
+ return 0;
+}
+static inline void sd_dif_complete(struct scsi_cmnd *cmd, unsigned int a)
+{
+}
#endif /* CONFIG_BLK_DEV_INTEGRITY */
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 4d17f3d35aa..3ebb1f28949 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -311,25 +311,26 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
struct scsi_device *sdp = sdkp->device;
struct gendisk *disk = sdkp->disk;
u8 type = sdkp->protection_type;
+ int dif, dix;
- /* If this HBA doesn't support DIX, resort to normal I/O or DIF */
- if (scsi_host_dix_capable(sdp->host, type) == 0) {
+ dif = scsi_host_dif_capable(sdp->host, type);
+ dix = scsi_host_dix_capable(sdp->host, type);
- if (type == SD_DIF_TYPE0_PROTECTION)
- return;
-
- if (scsi_host_dif_capable(sdp->host, type) == 0) {
- sd_printk(KERN_INFO, sdkp, "Type %d protection " \
- "unsupported by HBA. Disabling DIF.\n", type);
- sdkp->protection_type = 0;
- return;
- }
+ if (!dix && scsi_host_dix_capable(sdp->host, 0)) {
+ dif = 0; dix = 1;
+ }
- sd_printk(KERN_INFO, sdkp, "Enabling DIF Type %d protection\n",
- type);
+ if (type) {
+ if (dif)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Enabling DIF Type %d protection\n", type);
+ else
+ sd_printk(KERN_NOTICE, sdkp,
+ "Disabling DIF Type %d protection\n", type);
+ }
+ if (!dix)
return;
- }
/* Enable DMA of protection information */
if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP)
@@ -343,17 +344,17 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
else
blk_integrity_register(disk, &dif_type1_integrity_crc);
- sd_printk(KERN_INFO, sdkp,
- "Enabling %s integrity protection\n", disk->integrity->name);
+ sd_printk(KERN_NOTICE, sdkp,
+ "Enabling DIX %s protection\n", disk->integrity->name);
/* Signal to block layer that we support sector tagging */
- if (type && sdkp->ATO) {
+ if (dif && type && sdkp->ATO) {
if (type == SD_DIF_TYPE3_PROTECTION)
disk->integrity->tag_size = sizeof(u16) + sizeof(u32);
else
disk->integrity->tag_size = sizeof(u16);
- sd_printk(KERN_INFO, sdkp, "DIF application tag size %u\n",
+ sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n",
disk->integrity->tag_size);
}
}
@@ -361,7 +362,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
/*
* DIF DMA operation magic decoder ring.
*/
-void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix)
+void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type)
{
int csum_convert, prot_op;
@@ -406,7 +407,8 @@ void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix)
}
scsi_set_prot_op(scmd, prot_op);
- scsi_set_prot_type(scmd, dif);
+ if (dif)
+ scsi_set_prot_type(scmd, type);
}
/*
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 661f9f21650..93bd59a1ed7 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -47,7 +47,6 @@ static int sg_version_num = 30534; /* 2 digits for each component */
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
-#include <linux/scatterlist.h>
#include <linux/blktrace_api.h>
#include <linux/smp_lock.h>
@@ -69,7 +68,6 @@ static void sg_proc_cleanup(void);
#endif
#define SG_ALLOW_DIO_DEF 0
-#define SG_ALLOW_DIO_CODE /* compile out by commenting this define */
#define SG_MAX_DEVS 32768
@@ -118,8 +116,8 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
unsigned 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 */
- struct scatterlist *buffer;/* scatter list */
+ struct page **pages;
+ int page_order;
char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */
unsigned char cmd_opcode; /* first byte of command */
} Sg_scatter_hold;
@@ -137,6 +135,8 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
char orphan; /* 1 -> drop on sight, 0 -> normal */
char sg_io_owned; /* 1 -> packet belongs to SG_IO */
volatile char done; /* 0->before bh, 1->before read, 2->read */
+ struct request *rq;
+ struct bio *bio;
} Sg_request;
typedef struct sg_fd { /* holds the state of a file descriptor */
@@ -175,8 +175,8 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
static int sg_fasync(int fd, struct file *filp, int mode);
/* 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_rq_end_io(struct request *rq, int uptodate);
+static int sg_start_req(Sg_request *srp, unsigned char *cmd);
static void sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
@@ -188,17 +188,11 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
int read_only, Sg_request **o_srp);
static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
unsigned char *cmnd, int timeout, int blocking);
-static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
- int wr_xf, int *countp, unsigned char __user **up);
-static int sg_write_xfer(Sg_request * srp);
-static int sg_read_xfer(Sg_request * srp);
static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
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 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);
@@ -206,7 +200,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
static Sg_request *sg_add_request(Sg_fd * sfp);
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
static int sg_res_in_use(Sg_fd * sfp);
-static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
static Sg_device *sg_get_dev(int dev);
#ifdef CONFIG_SCSI_PROC_FS
static int sg_last_dev(void);
@@ -529,8 +522,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
err = -EFAULT;
goto err_out;
}
- err = sg_read_xfer(srp);
- err_out:
+err_out:
sg_finish_rem_req(srp);
return (0 == err) ? count : err;
}
@@ -612,7 +604,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
else
hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE;
hp->dxfer_len = mxsize;
- hp->dxferp = (char __user *)buf + cmd_size;
+ if (hp->dxfer_direction == SG_DXFER_TO_DEV)
+ hp->dxferp = (char __user *)buf + cmd_size;
+ else
+ hp->dxferp = NULL;
hp->sbp = NULL;
hp->timeout = old_hdr.reply_len; /* structure abuse ... */
hp->flags = input_size; /* structure abuse ... */
@@ -732,16 +727,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n",
(int) cmnd[0], (int) hp->cmd_len));
- if ((k = sg_start_req(srp))) {
+ k = sg_start_req(srp, cmnd);
+ if (k) {
SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));
sg_finish_rem_req(srp);
return k; /* probably out of space --> ENOMEM */
}
- if ((k = sg_write_xfer(srp))) {
- SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n"));
- sg_finish_rem_req(srp);
- return k;
- }
if (sdp->detached) {
sg_finish_rem_req(srp);
return -ENODEV;
@@ -763,20 +754,11 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
break;
}
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). */
- if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, 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_common_write: scsi_execute_async failed\n"));
- /*
- * most likely out of mem, but could also be a bad map
- */
- sg_finish_rem_req(srp);
- return -ENOMEM;
- } else
- return 0;
+
+ srp->rq->timeout = timeout;
+ blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
+ srp->rq, 1, sg_rq_end_io);
+ return 0;
}
static int
@@ -1192,8 +1174,7 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
Sg_fd *sfp;
unsigned long offset, len, sa;
Sg_scatter_hold *rsv_schp;
- struct scatterlist *sg;
- int k;
+ int k, length;
if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
return VM_FAULT_SIGBUS;
@@ -1203,15 +1184,14 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n",
offset, rsv_schp->k_use_sg));
- sg = rsv_schp->buffer;
sa = vma->vm_start;
- for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, sg = sg_next(sg)) {
+ length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
+ for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) {
len = vma->vm_end - sa;
- len = (len < sg->length) ? len : sg->length;
+ len = (len < length) ? len : length;
if (offset < len) {
- struct page *page;
- page = virt_to_page(page_address(sg_page(sg)) + offset);
+ struct page *page = nth_page(rsv_schp->pages[k],
+ offset >> PAGE_SHIFT);
get_page(page); /* increment page count */
vmf->page = page;
return 0; /* success */
@@ -1233,8 +1213,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
Sg_fd *sfp;
unsigned long req_sz, len, sa;
Sg_scatter_hold *rsv_schp;
- int k;
- struct scatterlist *sg;
+ int k, length;
if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
return -ENXIO;
@@ -1248,11 +1227,10 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
return -ENOMEM; /* cannot map more than reserved buffer */
sa = vma->vm_start;
- sg = rsv_schp->buffer;
- for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, sg = sg_next(sg)) {
+ length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
+ for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) {
len = vma->vm_end - sa;
- len = (len < sg->length) ? len : sg->length;
+ len = (len < length) ? len : length;
sa += len;
}
@@ -1263,16 +1241,19 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
-/* 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(void *data, char *sense, int result, int resid)
+/*
+ * 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_rq_end_io(struct request *rq, int uptodate)
{
- Sg_request *srp = data;
+ struct sg_request *srp = rq->end_io_data;
Sg_device *sdp = NULL;
Sg_fd *sfp;
unsigned long iflags;
unsigned int ms;
+ char *sense;
+ int result, resid;
if (NULL == srp) {
printk(KERN_ERR "sg_cmd_done: NULL request\n");
@@ -1286,6 +1267,9 @@ sg_cmd_done(void *data, char *sense, int result, int resid)
return;
}
+ sense = rq->sense;
+ result = rq->errors;
+ resid = rq->data_len;
SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
sdp->disk->disk_name, srp->header.pack_id, result));
@@ -1296,7 +1280,6 @@ sg_cmd_done(void *data, char *sense, int result, int resid)
if (0 != result) {
struct scsi_sense_hdr sshdr;
- 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);
@@ -1467,12 +1450,10 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
if (sg_sysfs_valid) {
struct device *sg_class_member;
- sg_class_member = device_create_drvdata(sg_sysfs_class,
- cl_dev->parent,
- MKDEV(SCSI_GENERIC_MAJOR,
- sdp->index),
- sdp,
- "%s", disk->disk_name);
+ sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
+ MKDEV(SCSI_GENERIC_MAJOR,
+ sdp->index),
+ sdp, "%s", disk->disk_name);
if (IS_ERR(sg_class_member)) {
printk(KERN_ERR "sg_add: "
"device_create failed\n");
@@ -1634,37 +1615,79 @@ exit_sg(void)
idr_destroy(&sg_index_idr);
}
-static int
-sg_start_req(Sg_request * srp)
+static int sg_start_req(Sg_request *srp, unsigned char *cmd)
{
int res;
+ struct request *rq;
Sg_fd *sfp = srp->parentfp;
sg_io_hdr_t *hp = &srp->header;
int dxfer_len = (int) hp->dxfer_len;
int dxfer_dir = hp->dxfer_direction;
+ unsigned int iov_count = hp->iovec_count;
Sg_scatter_hold *req_schp = &srp->data;
Sg_scatter_hold *rsv_schp = &sfp->reserve;
+ struct request_queue *q = sfp->parentdp->device->request_queue;
+ struct rq_map_data *md, map_data;
+ int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
+
+ SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n",
+ dxfer_len));
+
+ rq = blk_get_request(q, rw, GFP_ATOMIC);
+ if (!rq)
+ return -ENOMEM;
+
+ memcpy(rq->cmd, cmd, hp->cmd_len);
+
+ rq->cmd_len = hp->cmd_len;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+ srp->rq = rq;
+ rq->end_io_data = srp;
+ rq->sense = srp->sense_b;
+ rq->retries = SG_DEFAULT_RETRIES;
- SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len));
if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
return 0;
- if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) &&
- (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) &&
- (!sfp->parentdp->device->host->unchecked_isa_dma)) {
- res = sg_build_direct(srp, sfp, dxfer_len);
- if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */
- return res;
- }
- if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen))
- sg_link_reserve(sfp, srp, dxfer_len);
- else {
- res = sg_build_indirect(req_schp, sfp, dxfer_len);
- if (res) {
- sg_remove_scat(req_schp);
- return res;
+
+ if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO &&
+ dxfer_dir != SG_DXFER_UNKNOWN && !iov_count &&
+ !sfp->parentdp->device->host->unchecked_isa_dma &&
+ blk_rq_aligned(q, hp->dxferp, dxfer_len))
+ md = NULL;
+ else
+ md = &map_data;
+
+ if (md) {
+ if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
+ sg_link_reserve(sfp, srp, dxfer_len);
+ else {
+ res = sg_build_indirect(req_schp, sfp, dxfer_len);
+ if (res)
+ return res;
}
+
+ md->pages = req_schp->pages;
+ md->page_order = req_schp->page_order;
+ md->nr_entries = req_schp->k_use_sg;
}
- return 0;
+
+ if (iov_count)
+ res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
+ hp->dxfer_len, GFP_ATOMIC);
+ else
+ res = blk_rq_map_user(q, rq, md, hp->dxferp,
+ hp->dxfer_len, GFP_ATOMIC);
+
+ if (!res) {
+ srp->bio = rq->bio;
+
+ if (!md) {
+ req_schp->dio_in_use = 1;
+ hp->info |= SG_INFO_DIRECT_IO;
+ }
+ }
+ return res;
}
static void
@@ -1678,186 +1701,37 @@ sg_finish_rem_req(Sg_request * srp)
sg_unlink_reserve(sfp, srp);
else
sg_remove_scat(req_schp);
+
+ if (srp->rq) {
+ if (srp->bio)
+ blk_rq_unmap_user(srp->bio);
+
+ blk_put_request(srp->rq);
+ }
+
sg_remove_request(sfp, srp);
}
static int
sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
{
- int sg_bufflen = tablesize * sizeof(struct scatterlist);
+ int sg_bufflen = tablesize * sizeof(struct page *);
gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
- /*
- * 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)
+ schp->pages = kzalloc(sg_bufflen, gfp_flags);
+ if (!schp->pages)
return -ENOMEM;
- sg_init_table(schp->buffer, tablesize);
schp->sglist_len = sg_bufflen;
return tablesize; /* number of scat_gath elements allocated */
}
-#ifdef SG_ALLOW_DIO_CODE
-/* vvvvvvvv following code borrowed from st driver's direct IO vvvvvvvvv */
- /* 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
- (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 end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
- unsigned long start = uaddr >> PAGE_SHIFT;
- const int nr_pages = end - start;
- int res, i, j;
- struct page **pages;
-
- /* User attempted Overflow! */
- if ((uaddr + count) < uaddr)
- return -EINVAL;
-
- /* Too big */
- if (nr_pages > max_pages)
- return -ENOMEM;
-
- /* Hmm? */
- if (count == 0)
- return 0;
-
- if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_ATOMIC)) == NULL)
- return -ENOMEM;
-
- /* Try to fault in all of the necessary pages */
- down_read(&current->mm->mmap_sem);
- /* rw==READ means read from drive, write into memory area */
- res = get_user_pages(
- current,
- current->mm,
- uaddr,
- nr_pages,
- rw == READ,
- 0, /* don't force */
- pages,
- NULL);
- up_read(&current->mm->mmap_sem);
-
- /* Errors and no page mapped should return here */
- if (res < nr_pages)
- goto out_unmap;
-
- for (i=0; i < nr_pages; i++) {
- /* FIXME: flush superflous for rw==READ,
- * probably wrong function for rw==WRITE
- */
- flush_dcache_page(pages[i]);
- /* ?? Is locking needed? I don't think so */
- /* if (!trylock_page(pages[i]))
- goto out_unlock; */
- }
-
- sg_set_page(sgl, pages[0], 0, 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++)
- sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0);
- }
- else {
- sgl[0].length = count;
- }
-
- kfree(pages);
- return nr_pages;
-
- out_unmap:
- if (res > 0) {
- for (j=0; j < res; j++)
- page_cache_release(pages[j]);
- res = 0;
- }
- kfree(pages);
- return res;
-}
-
-
-/* And unmap them... */
-static int
-st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
- int dirtied)
-{
- int i;
-
- for (i=0; i < nr_pages; i++) {
- struct page *page = sg_page(&sgl[i]);
-
- if (dirtied)
- SetPageDirty(page);
- /* unlock_page(page); */
- /* FIXME: cache flush missing for rw==READ
- * FIXME: call the correct reference counting function
- */
- page_cache_release(page);
- }
-
- return 0;
-}
-
-/* ^^^^^^^^ above code borrowed from st driver's direct IO ^^^^^^^^^ */
-#endif
-
-
-/* Returns: -ve -> error, 0 -> done, 1 -> try indirect */
-static int
-sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
-{
-#ifdef SG_ALLOW_DIO_CODE
- sg_io_hdr_t *hp = &srp->header;
- Sg_scatter_hold *schp = &srp->data;
- int sg_tablesize = sfp->parentdp->sg_tablesize;
- 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;
- }
- 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) {
- sg_remove_scat(schp);
- return 1;
- }
- schp->k_use_sg = res;
- schp->dio_in_use = 1;
- hp->info |= SG_INFO_DIRECT_IO;
- return 0;
-#else
- return 1;
-#endif
-}
-
static int
sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
{
- struct scatterlist *sg;
- int ret_sz = 0, k, rem_sz, num, mx_sc_elems;
+ int ret_sz = 0, i, k, rem_sz, num, mx_sc_elems;
int sg_tablesize = sfp->parentdp->sg_tablesize;
- int blk_size = buff_size;
- struct page *p = NULL;
+ int blk_size = buff_size, order;
+ gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN;
if (blk_size < 0)
return -EFAULT;
@@ -1881,15 +1755,26 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
} else
scatter_elem_sz_prev = num;
}
- for (k = 0, sg = schp->buffer, rem_sz = blk_size;
- (rem_sz > 0) && (k < mx_sc_elems);
- ++k, rem_sz -= ret_sz, sg = sg_next(sg)) {
-
+
+ if (sfp->low_dma)
+ gfp_mask |= GFP_DMA;
+
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ gfp_mask |= __GFP_ZERO;
+
+ order = get_order(num);
+retry:
+ ret_sz = 1 << (PAGE_SHIFT + order);
+
+ for (k = 0, rem_sz = blk_size; rem_sz > 0 && k < mx_sc_elems;
+ k++, rem_sz -= ret_sz) {
+
num = (rem_sz > scatter_elem_sz_prev) ?
- scatter_elem_sz_prev : rem_sz;
- p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
- if (!p)
- return -ENOMEM;
+ scatter_elem_sz_prev : rem_sz;
+
+ schp->pages[k] = alloc_pages(gfp_mask, order);
+ if (!schp->pages[k])
+ goto out;
if (num == scatter_elem_sz_prev) {
if (unlikely(ret_sz > scatter_elem_sz_prev)) {
@@ -1897,12 +1782,12 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
scatter_elem_sz_prev = ret_sz;
}
}
- sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0);
SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, "
"ret_sz=%d\n", k, num, ret_sz));
} /* end of for loop */
+ schp->page_order = order;
schp->k_use_sg = k;
SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, "
"rem_sz=%d\n", k, rem_sz));
@@ -1910,223 +1795,42 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
schp->bufflen = blk_size;
if (rem_sz > 0) /* must have failed */
return -ENOMEM;
-
return 0;
-}
-
-static int
-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;
- int dxfer_dir = hp->dxfer_direction;
- unsigned char *p;
- unsigned char __user *up;
- int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
-
- if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) ||
- (SG_DXFER_TO_FROM_DEV == dxfer_dir)) {
- num_xfer = (int) (new_interface ? hp->dxfer_len : hp->flags);
- if (schp->bufflen < num_xfer)
- num_xfer = schp->bufflen;
- }
- if ((num_xfer <= 0) || (schp->dio_in_use) ||
- (new_interface
- && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
- return 0;
-
- SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n",
- num_xfer, iovec_count, schp->k_use_sg));
- if (iovec_count) {
- onum = iovec_count;
- if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum))
- return -EFAULT;
- } else
- onum = 1;
-
- ksglen = sg->length;
- p = page_address(sg_page(sg));
- 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 = sg_next(sg), ksglen = sg->length,
- p = page_address(sg_page(sg))) {
- 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))
- return -EFAULT;
- up += ksglen;
- usglen -= ksglen;
- }
- ++k;
- if (k >= schp->k_use_sg)
- return 0;
- }
- }
-
- return 0;
-}
+out:
+ for (i = 0; i < k; i++)
+ __free_pages(schp->pages[k], order);
-static int
-sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
- int wr_xf, int *countp, unsigned char __user **up)
-{
- int num_xfer = (int) hp->dxfer_len;
- unsigned char __user *p = hp->dxferp;
- int count;
+ if (--order >= 0)
+ goto retry;
- if (0 == sg_num) {
- if (wr_xf && ('\0' == hp->interface_id))
- count = (int) hp->flags; /* holds "old" input_size */
- else
- count = num_xfer;
- } else {
- sg_iovec_t iovec;
- if (__copy_from_user(&iovec, p + ind*SZ_SG_IOVEC, SZ_SG_IOVEC))
- return -EFAULT;
- p = iovec.iov_base;
- count = (int) iovec.iov_len;
- }
- if (!access_ok(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count))
- return -EFAULT;
- if (up)
- *up = p;
- if (countp)
- *countp = count;
- return 0;
+ return -ENOMEM;
}
static void
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 *sg = schp->buffer;
-
- if (schp->dio_in_use) {
-#ifdef SG_ALLOW_DIO_CODE
- st_unmap_user_pages(sg, schp->k_use_sg, TRUE);
-#endif
- } else {
+ if (schp->pages && schp->sglist_len > 0) {
+ if (!schp->dio_in_use) {
int k;
- for (k = 0; (k < schp->k_use_sg) && sg_page(sg);
- ++k, sg = sg_next(sg)) {
+ for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) {
SCSI_LOG_TIMEOUT(5, printk(
- "sg_remove_scat: k=%d, pg=0x%p, len=%d\n",
- k, sg_page(sg), sg->length));
- sg_page_free(sg_page(sg), sg->length);
+ "sg_remove_scat: k=%d, pg=0x%p\n",
+ k, schp->pages[k]));
+ __free_pages(schp->pages[k], schp->page_order);
}
- }
- kfree(schp->buffer);
- }
- memset(schp, 0, sizeof (*schp));
-}
-static int
-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;
- int dxfer_dir = hp->dxfer_direction;
- unsigned char *p;
- unsigned char __user *up;
- int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
-
- if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir)
- || (SG_DXFER_TO_FROM_DEV == dxfer_dir)) {
- num_xfer = hp->dxfer_len;
- if (schp->bufflen < num_xfer)
- num_xfer = schp->bufflen;
- }
- if ((num_xfer <= 0) || (schp->dio_in_use) ||
- (new_interface
- && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
- return 0;
-
- SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n",
- num_xfer, iovec_count, schp->k_use_sg));
- if (iovec_count) {
- onum = iovec_count;
- if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum))
- return -EFAULT;
- } else
- onum = 1;
-
- p = page_address(sg_page(sg));
- 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 = sg_next(sg), ksglen = sg->length,
- p = page_address(sg_page(sg))) {
- 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))
- return -EFAULT;
- up += ksglen;
- usglen -= ksglen;
- }
- ++k;
- if (k >= schp->k_use_sg)
- return 0;
+ kfree(schp->pages);
}
}
-
- return 0;
+ memset(schp, 0, sizeof (*schp));
}
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",
@@ -2134,15 +1838,15 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
if ((!outp) || (num_read_xfer <= 0))
return 0;
- for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) {
- num = sg->length;
+ num = 1 << (PAGE_SHIFT + schp->page_order);
+ for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) {
if (num > num_read_xfer) {
- if (__copy_to_user(outp, page_address(sg_page(sg)),
+ if (__copy_to_user(outp, page_address(schp->pages[k]),
num_read_xfer))
return -EFAULT;
break;
} else {
- if (__copy_to_user(outp, page_address(sg_page(sg)),
+ if (__copy_to_user(outp, page_address(schp->pages[k]),
num))
return -EFAULT;
num_read_xfer -= num;
@@ -2177,24 +1881,21 @@ 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));
rem = size;
- for (k = 0; k < rsv_schp->k_use_sg; ++k, sg = sg_next(sg)) {
- num = sg->length;
+ num = 1 << (PAGE_SHIFT + rsv_schp->page_order);
+ for (k = 0; k < rsv_schp->k_use_sg; k++) {
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->pages = rsv_schp->pages;
req_schp->bufflen = size;
- req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+ req_schp->page_order = rsv_schp->page_order;
break;
} else
rem -= num;
@@ -2208,22 +1909,13 @@ static void
sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
{
Sg_scatter_hold *req_schp = &srp->data;
- Sg_scatter_hold *rsv_schp = &sfp->reserve;
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 *sg = rsv_schp->buffer;
-
- if (sfp->save_scat_len > 0)
- (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"));
- }
req_schp->k_use_sg = 0;
req_schp->bufflen = 0;
- req_schp->buffer = NULL;
+ req_schp->pages = NULL;
+ req_schp->page_order = 0;
req_schp->sglist_len = 0;
sfp->save_scat_len = 0;
srp->res_used = 0;
@@ -2481,53 +2173,6 @@ sg_res_in_use(Sg_fd * sfp)
return srp ? 1 : 0;
}
-/* The size fetched (value output via retSzp) set when non-NULL return */
-static struct page *
-sg_page_malloc(int rqSz, int lowDma, int *retSzp)
-{
- struct page *resp = NULL;
- gfp_t page_mask;
- int order, a_size;
- int resSz;
-
- if ((rqSz <= 0) || (NULL == retSzp))
- return resp;
-
- if (lowDma)
- page_mask = GFP_ATOMIC | GFP_DMA | __GFP_COMP | __GFP_NOWARN;
- else
- page_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN;
-
- for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
- order++, a_size <<= 1) ;
- resSz = a_size; /* rounded up if necessary */
- resp = alloc_pages(page_mask, order);
- while ((!resp) && order) {
- --order;
- a_size >>= 1; /* divide by 2, until PAGE_SIZE */
- resp = alloc_pages(page_mask, order); /* try half */
- resSz = a_size;
- }
- if (resp) {
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- memset(page_address(resp), 0, resSz);
- *retSzp = resSz;
- }
- return resp;
-}
-
-static void
-sg_page_free(struct page *page, int size)
-{
- int order, a_size;
-
- if (!page)
- return;
- for (order = 0, a_size = PAGE_SIZE; a_size < size;
- order++, a_size <<= 1) ;
- __free_pages(page, order);
-}
-
#ifdef CONFIG_SCSI_PROC_FS
static int
sg_idr_max_id(int id, void *p, void *data)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 27f5bfd1def..0f17009c99d 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -331,7 +331,7 @@ static int sr_done(struct scsi_cmnd *SCpnt)
static int sr_prep_fn(struct request_queue *q, struct request *rq)
{
- int block=0, this_count, s_size, timeout = SR_TIMEOUT;
+ int block = 0, this_count, s_size;
struct scsi_cd *cd;
struct scsi_cmnd *SCpnt;
struct scsi_device *sdp = q->queuedata;
@@ -461,7 +461,6 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES;
- SCpnt->timeout_per_command = timeout;
/*
* This indicates that the command is ready from our end to be
@@ -620,6 +619,8 @@ static int sr_probe(struct device *dev)
disk->fops = &sr_bdops;
disk->flags = GENHD_FL_CD;
+ blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
+
cd->device = sdev;
cd->disk = disk;
cd->driver = &sr_template;
@@ -878,7 +879,7 @@ static void sr_kref_release(struct kref *kref)
struct gendisk *disk = cd->disk;
spin_lock(&sr_index_lock);
- clear_bit(disk->first_minor, sr_index_bits);
+ clear_bit(MINOR(disk_devt(disk)), sr_index_bits);
spin_unlock(&sr_index_lock);
unregister_cdrom(&cd->cdi);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c2bb53e3d94..5c28d08f18f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4428,13 +4428,10 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]);
st_class_member =
- device_create_drvdata(st_sysfs_class,
- &STp->device->sdev_gendev,
- MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(dev_num,
- mode, rew)),
- &STp->modes[mode],
- "%s", name);
+ device_create(st_sysfs_class, &STp->device->sdev_gendev,
+ MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(dev_num, mode, rew)),
+ &STp->modes[mode], "%s", name);
if (IS_ERR(st_class_member)) {
printk(KERN_WARNING "st%d: device_create failed\n",
dev_num);
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index f9cf7015136..3d73aad4bc8 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -1,6 +1,6 @@
/* sun_esp.c: ESP front-end for Sparc SBUS systems.
*
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@@ -9,60 +9,70 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/sbus.h>
-
#include <scsi/scsi_host.h>
#include "esp_scsi.h"
#define DRV_MODULE_NAME "sun_esp"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_VERSION "1.000"
-#define DRV_MODULE_RELDATE "April 19, 2007"
+#define DRV_VERSION "1.100"
+#define DRV_MODULE_RELDATE "August 27, 2008"
#define dma_read32(REG) \
sbus_readl(esp->dma_regs + (REG))
#define dma_write32(VAL, REG) \
sbus_writel((VAL), esp->dma_regs + (REG))
-static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev)
-{
- struct sbus_dev *sdev = esp->dev;
- struct sbus_dma *dma;
+/* DVMA chip revisions */
+enum dvma_rev {
+ dvmarev0,
+ dvmaesc1,
+ dvmarev1,
+ dvmarev2,
+ dvmarev3,
+ dvmarevplus,
+ dvmahme
+};
- if (dma_sdev != NULL) {
- for_each_dvma(dma) {
- if (dma->sdev == dma_sdev)
- break;
- }
- } else {
- for_each_dvma(dma) {
- if (dma->sdev == NULL)
- break;
+static int __devinit esp_sbus_setup_dma(struct esp *esp,
+ struct of_device *dma_of)
+{
+ esp->dma = dma_of;
- /* If bus + slot are the same and it has the
- * correct OBP name, it's ours.
- */
- if (sdev->bus == dma->sdev->bus &&
- sdev->slot == dma->sdev->slot &&
- (!strcmp(dma->sdev->prom_name, "dma") ||
- !strcmp(dma->sdev->prom_name, "espdma")))
- break;
- }
- }
+ esp->dma_regs = of_ioremap(&dma_of->resource[0], 0,
+ resource_size(&dma_of->resource[0]),
+ "espdma");
+ if (!esp->dma_regs)
+ return -ENOMEM;
- if (dma == NULL) {
- printk(KERN_ERR PFX "[%s] Cannot find dma.\n",
- sdev->ofdev.node->full_name);
- return -ENODEV;
+ switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) {
+ case DMA_VERS0:
+ esp->dmarev = dvmarev0;
+ break;
+ case DMA_ESCV1:
+ esp->dmarev = dvmaesc1;
+ break;
+ case DMA_VERS1:
+ esp->dmarev = dvmarev1;
+ break;
+ case DMA_VERS2:
+ esp->dmarev = dvmarev2;
+ break;
+ case DMA_VERHME:
+ esp->dmarev = dvmahme;
+ break;
+ case DMA_VERSPLUS:
+ esp->dmarev = dvmarevplus;
+ break;
}
- esp->dma = dma;
- esp->dma_regs = dma->regs;
return 0;
@@ -70,18 +80,18 @@ static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sde
static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
{
- struct sbus_dev *sdev = esp->dev;
+ struct of_device *op = esp->dev;
struct resource *res;
/* On HME, two reg sets exist, first is DVMA,
* second is ESP registers.
*/
if (hme)
- res = &sdev->resource[1];
+ res = &op->resource[1];
else
- res = &sdev->resource[0];
+ res = &op->resource[0];
- esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
+ esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
if (!esp->regs)
return -ENOMEM;
@@ -90,10 +100,11 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
static int __devinit esp_sbus_map_command_block(struct esp *esp)
{
- struct sbus_dev *sdev = esp->dev;
+ struct of_device *op = esp->dev;
- esp->command_block = sbus_alloc_consistent(sdev, 16,
- &esp->command_block_dma);
+ esp->command_block = dma_alloc_coherent(&op->dev, 16,
+ &esp->command_block_dma,
+ GFP_ATOMIC);
if (!esp->command_block)
return -ENOMEM;
return 0;
@@ -102,17 +113,18 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp)
static int __devinit esp_sbus_register_irq(struct esp *esp)
{
struct Scsi_Host *host = esp->host;
- struct sbus_dev *sdev = esp->dev;
+ struct of_device *op = esp->dev;
- host->irq = sdev->irqs[0];
+ host->irq = op->irqs[0];
return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
}
-static void __devinit esp_get_scsi_id(struct esp *esp)
+static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma)
{
- struct sbus_dev *sdev = esp->dev;
- struct device_node *dp = sdev->ofdev.node;
+ struct of_device *op = esp->dev;
+ struct device_node *dp;
+ dp = op->node;
esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
if (esp->scsi_id != 0xff)
goto done;
@@ -121,13 +133,7 @@ static void __devinit esp_get_scsi_id(struct esp *esp)
if (esp->scsi_id != 0xff)
goto done;
- if (!sdev->bus) {
- /* SUN4 */
- esp->scsi_id = 7;
- goto done;
- }
-
- esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node,
+ esp->scsi_id = of_getintprop_default(espdma->node,
"scsi-initiator-id", 7);
done:
@@ -137,9 +143,10 @@ done:
static void __devinit esp_get_differential(struct esp *esp)
{
- struct sbus_dev *sdev = esp->dev;
- struct device_node *dp = sdev->ofdev.node;
+ struct of_device *op = esp->dev;
+ struct device_node *dp;
+ dp = op->node;
if (of_find_property(dp, "differential", NULL))
esp->flags |= ESP_FLAG_DIFFERENTIAL;
else
@@ -148,43 +155,36 @@ static void __devinit esp_get_differential(struct esp *esp)
static void __devinit esp_get_clock_params(struct esp *esp)
{
- struct sbus_dev *sdev = esp->dev;
- struct device_node *dp = sdev->ofdev.node;
- struct device_node *bus_dp;
+ struct of_device *op = esp->dev;
+ struct device_node *bus_dp, *dp;
int fmhz;
- bus_dp = NULL;
- if (sdev != NULL && sdev->bus != NULL)
- bus_dp = sdev->bus->ofdev.node;
+ dp = op->node;
+ bus_dp = dp->parent;
fmhz = of_getintprop_default(dp, "clock-frequency", 0);
if (fmhz == 0)
- fmhz = (!bus_dp) ? 0 :
- of_getintprop_default(bus_dp, "clock-frequency", 0);
+ fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0);
esp->cfreq = fmhz;
}
-static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma)
+static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of)
{
- struct sbus_dev *sdev = esp->dev;
- struct device_node *dp = sdev->ofdev.node;
- u8 bursts;
+ struct device_node *dma_dp = dma_of->node;
+ struct of_device *op = esp->dev;
+ struct device_node *dp;
+ u8 bursts, val;
+ dp = op->node;
bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
- if (dma) {
- struct device_node *dma_dp = dma->ofdev.node;
- u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
- if (val != 0xff)
- bursts &= val;
- }
+ val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
+ if (val != 0xff)
+ bursts &= val;
- if (sdev->bus) {
- u8 val = of_getintprop_default(sdev->bus->ofdev.node,
- "burst-sizes", 0xff);
- if (val != 0xff)
- bursts &= val;
- }
+ val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff);
+ if (val != 0xff)
+ bursts &= val;
if (bursts == 0xff ||
(bursts & DMA_BURST16) == 0 ||
@@ -194,9 +194,9 @@ static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma)
esp->bursts = bursts;
}
-static void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma)
+static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma)
{
- esp_get_scsi_id(esp);
+ esp_get_scsi_id(esp, espdma);
esp_get_differential(esp);
esp_get_clock_params(esp);
esp_get_bursts(esp, espdma);
@@ -215,25 +215,33 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
size_t sz, int dir)
{
- return sbus_map_single(esp->dev, buf, sz, dir);
+ struct of_device *op = esp->dev;
+
+ return dma_map_single(&op->dev, buf, sz, dir);
}
static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
- return sbus_map_sg(esp->dev, sg, num_sg, dir);
+ struct of_device *op = esp->dev;
+
+ return dma_map_sg(&op->dev, sg, num_sg, dir);
}
static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
size_t sz, int dir)
{
- sbus_unmap_single(esp->dev, addr, sz, dir);
+ struct of_device *op = esp->dev;
+
+ dma_unmap_single(&op->dev, addr, sz, dir);
}
static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
- sbus_unmap_sg(esp->dev, sg, num_sg, dir);
+ struct of_device *op = esp->dev;
+
+ dma_unmap_sg(&op->dev, sg, num_sg, dir);
}
static int sbus_esp_irq_pending(struct esp *esp)
@@ -247,24 +255,26 @@ static void sbus_esp_reset_dma(struct esp *esp)
{
int can_do_burst16, can_do_burst32, can_do_burst64;
int can_do_sbus64, lim;
+ struct of_device *op;
u32 val;
can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
can_do_burst64 = 0;
can_do_sbus64 = 0;
- if (sbus_can_dma_64bit(esp->dev))
+ op = esp->dev;
+ if (sbus_can_dma_64bit())
can_do_sbus64 = 1;
- if (sbus_can_burst64(esp->sdev))
+ if (sbus_can_burst64())
can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
/* Put the DVMA into a known state. */
- if (esp->dma->revision != dvmahme) {
+ if (esp->dmarev != dvmahme) {
val = dma_read32(DMA_CSR);
dma_write32(val | DMA_RST_SCSI, DMA_CSR);
dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
}
- switch (esp->dma->revision) {
+ switch (esp->dmarev) {
case dvmahme:
dma_write32(DMA_RESET_FAS366, DMA_CSR);
dma_write32(DMA_RST_SCSI, DMA_CSR);
@@ -282,7 +292,7 @@ static void sbus_esp_reset_dma(struct esp *esp)
if (can_do_sbus64) {
esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
- sbus_set_sbus64(esp->dev, esp->bursts);
+ sbus_set_sbus64(&op->dev, esp->bursts);
}
lim = 1000;
@@ -346,14 +356,14 @@ static void sbus_esp_dma_drain(struct esp *esp)
u32 csr;
int lim;
- if (esp->dma->revision == dvmahme)
+ if (esp->dmarev == dvmahme)
return;
csr = dma_read32(DMA_CSR);
if (!(csr & DMA_FIFO_ISDRAIN))
return;
- if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1)
+ if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1)
dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
lim = 1000;
@@ -369,7 +379,7 @@ static void sbus_esp_dma_drain(struct esp *esp)
static void sbus_esp_dma_invalidate(struct esp *esp)
{
- if (esp->dma->revision == dvmahme) {
+ if (esp->dmarev == dvmahme) {
dma_write32(DMA_RST_SCSI, DMA_CSR);
esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
@@ -440,7 +450,7 @@ static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
else
csr &= ~DMA_ST_WRITE;
dma_write32(csr, DMA_CSR);
- if (esp->dma->revision == dvmaesc1) {
+ if (esp->dmarev == dvmaesc1) {
u32 end = PAGE_ALIGN(addr + dma_count + 16U);
dma_write32(end - addr, DMA_COUNT);
}
@@ -476,10 +486,8 @@ static const struct esp_driver_ops sbus_esp_ops = {
.dma_error = sbus_esp_dma_error,
};
-static int __devinit esp_sbus_probe_one(struct device *dev,
- struct sbus_dev *esp_dev,
- struct sbus_dev *espdma,
- struct sbus_bus *sbus,
+static int __devinit esp_sbus_probe_one(struct of_device *op,
+ struct of_device *espdma,
int hme)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
@@ -497,13 +505,13 @@ static int __devinit esp_sbus_probe_one(struct device *dev,
esp = shost_priv(host);
esp->host = host;
- esp->dev = esp_dev;
+ esp->dev = op;
esp->ops = &sbus_esp_ops;
if (hme)
esp->flags |= ESP_FLAG_WIDE_CAPABLE;
- err = esp_sbus_find_dma(esp, espdma);
+ err = esp_sbus_setup_dma(esp, espdma);
if (err < 0)
goto fail_unlink;
@@ -525,15 +533,15 @@ static int __devinit esp_sbus_probe_one(struct device *dev,
* come up with the reset bit set, so make sure that
* is clear first.
*/
- if (esp->dma->revision == dvmaesc1) {
+ if (esp->dmarev == dvmaesc1) {
u32 val = dma_read32(DMA_CSR);
dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
}
- dev_set_drvdata(&esp_dev->ofdev.dev, esp);
+ dev_set_drvdata(&op->dev, esp);
- err = scsi_esp_register(esp, dev);
+ err = scsi_esp_register(esp, &op->dev);
if (err)
goto fail_free_irq;
@@ -542,41 +550,46 @@ static int __devinit esp_sbus_probe_one(struct device *dev,
fail_free_irq:
free_irq(host->irq, esp);
fail_unmap_command_block:
- sbus_free_consistent(esp->dev, 16,
- esp->command_block,
- esp->command_block_dma);
+ dma_free_coherent(&op->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
fail_unmap_regs:
- sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
+ of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE);
fail_unlink:
scsi_host_put(host);
fail:
return err;
}
-static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
- struct sbus_dev *sdev = to_sbus_device(&dev->dev);
- struct device_node *dp = dev->node;
- struct sbus_dev *dma_sdev = NULL;
+ struct device_node *dma_node = NULL;
+ struct device_node *dp = op->node;
+ struct of_device *dma_of = NULL;
int hme = 0;
if (dp->parent &&
(!strcmp(dp->parent->name, "espdma") ||
!strcmp(dp->parent->name, "dma")))
- dma_sdev = sdev->parent;
+ dma_node = dp->parent;
else if (!strcmp(dp->name, "SUNW,fas")) {
- dma_sdev = sdev;
+ dma_node = op->node;
hme = 1;
}
+ if (dma_node)
+ dma_of = of_find_device_by_node(dma_node);
+ if (!dma_of)
+ return -ENODEV;
- return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev,
- sdev->bus, hme);
+ return esp_sbus_probe_one(op, dma_of, hme);
}
-static int __devexit esp_sbus_remove(struct of_device *dev)
+static int __devexit esp_sbus_remove(struct of_device *op)
{
- struct esp *esp = dev_get_drvdata(&dev->dev);
+ struct esp *esp = dev_get_drvdata(&op->dev);
+ struct of_device *dma_of = esp->dma;
unsigned int irq = esp->host->irq;
+ bool is_hme;
u32 val;
scsi_esp_unregister(esp);
@@ -586,17 +599,25 @@ static int __devexit esp_sbus_remove(struct of_device *dev)
dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
free_irq(irq, esp);
- sbus_free_consistent(esp->dev, 16,
- esp->command_block,
- esp->command_block_dma);
- sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
+
+ is_hme = (esp->dmarev == dvmahme);
+
+ dma_free_coherent(&op->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+ of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs,
+ SBUS_ESP_REG_SIZE);
+ of_iounmap(&dma_of->resource[0], esp->dma_regs,
+ resource_size(&dma_of->resource[0]));
scsi_host_put(esp->host);
+ dev_set_drvdata(&op->dev, NULL);
+
return 0;
}
-static struct of_device_id esp_match[] = {
+static const struct of_device_id esp_match[] = {
{
.name = "SUNW,esp",
},
@@ -619,7 +640,7 @@ static struct of_platform_driver esp_sbus_driver = {
static int __init sunesp_init(void)
{
- return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
+ return of_register_driver(&esp_sbus_driver, &of_bus_type);
}
static void __exit sunesp_exit(void)
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index d39107b7669..f4e6cde1fd0 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -519,8 +519,8 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
* Shorten our settle_time if needed for
* this command not to time out.
*/
- if (np->s.settle_time_valid && cmd->timeout_per_command) {
- unsigned long tlimit = jiffies + cmd->timeout_per_command;
+ if (np->s.settle_time_valid && cmd->request->timeout) {
+ unsigned long tlimit = jiffies + cmd->request->timeout;
tlimit -= SYM_CONF_TIMER_INTERVAL*2;
if (time_after(np->s.settle_time, tlimit)) {
np->s.settle_time = tlimit;
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 1723d71cbf3..69ac6e590f1 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2573,8 +2573,8 @@ static struct pci_driver dc390_driver = {
static int __init dc390_module_init(void)
{
if (!disable_clustering)
- printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n"
- "\twith \"disable_clustering=1\" and report to maintainers\n");
+ printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
+ printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n");
if (tmscsim[0] == -1 || tmscsim[0] > 15) {
tmscsim[0] = 7;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 342e12fb1c2..1528de23a65 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -44,6 +44,10 @@
#include "8250.h"
+#ifdef CONFIG_SPARC
+#include "suncore.h"
+#endif
+
/*
* Configuration:
* share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
@@ -53,6 +57,13 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+static struct uart_driver serial8250_reg;
+
+static int serial_index(struct uart_port *port)
+{
+ return (serial8250_reg.minor - 64) + port->line;
+}
+
/*
* Debugging.
*/
@@ -536,7 +547,7 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
/*
* FIFO support.
*/
-static inline void serial8250_clear_fifos(struct uart_8250_port *p)
+static void serial8250_clear_fifos(struct uart_8250_port *p)
{
if (p->capabilities & UART_CAP_FIFO) {
serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -551,7 +562,7 @@ static inline void serial8250_clear_fifos(struct uart_8250_port *p)
* capability" bit enabled. Note that on XR16C850s, we need to
* reset LCR to write to IER.
*/
-static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
@@ -993,7 +1004,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
return;
DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
- up->port.line, up->port.iobase, up->port.membase);
+ serial_index(&up->port), up->port.iobase, up->port.membase);
/*
* We really do need global IRQs disabled here - we're going to
@@ -1128,8 +1139,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
if (up->capabilities != uart_config[up->port.type].flags) {
printk(KERN_WARNING
"ttyS%d: detected caps %08x should be %08x\n",
- up->port.line, up->capabilities,
- uart_config[up->port.type].flags);
+ serial_index(&up->port), up->capabilities,
+ uart_config[up->port.type].flags);
}
up->port.fifosize = uart_config[up->port.type].fifo_size;
@@ -1424,8 +1435,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
/*
* This handles the interrupt from one port.
*/
-static inline void
-serial8250_handle_port(struct uart_8250_port *up)
+static void serial8250_handle_port(struct uart_8250_port *up)
{
unsigned int status;
unsigned long flags;
@@ -1719,7 +1729,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
/*
* Wait for transmitter & holding register to empty
*/
-static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
@@ -1854,7 +1864,8 @@ static int serial8250_startup(struct uart_port *port)
*/
if (!(up->port.flags & UPF_BUGGY_UART) &&
(serial_inp(up, UART_LSR) == 0xff)) {
- printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
+ printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+ serial_index(&up->port));
return -ENODEV;
}
@@ -1908,15 +1919,24 @@ static int serial8250_startup(struct uart_port *port)
* kick the UART on a regular basis.
*/
if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
- pr_debug("ttyS%d - using backup timer\n", port->line);
- up->timer.function = serial8250_backup_timeout;
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies +
- poll_timeout(up->port.timeout) + HZ / 5);
+ up->bugs |= UART_BUG_THRE;
+ pr_debug("ttyS%d - using backup timer\n",
+ serial_index(port));
}
}
/*
+ * The above check will only give an accurate result the first time
+ * the port is opened so this value needs to be preserved.
+ */
+ if (up->bugs & UART_BUG_THRE) {
+ up->timer.function = serial8250_backup_timeout;
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies +
+ poll_timeout(up->port.timeout) + HZ / 5);
+ }
+
+ /*
* If the "interrupt" for this port doesn't correspond with any
* hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0.
@@ -1961,7 +1981,7 @@ static int serial8250_startup(struct uart_port *port)
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
pr_debug("ttyS%d - enabling bad tx status workarounds\n",
- port->line);
+ serial_index(port));
}
} else {
up->bugs &= ~UART_BUG_TXEN;
@@ -2203,9 +2223,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
serial_outp(up, UART_EFR, efr);
}
-#ifdef CONFIG_ARCH_OMAP15XX
+#ifdef CONFIG_ARCH_OMAP
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) {
+ if (cpu_is_omap1510() && is_omap_port(up)) {
if (baud == 115200) {
quot = 1;
serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
@@ -2258,18 +2278,27 @@ serial8250_pm(struct uart_port *port, unsigned int state,
p->pm(port, state, oldstate);
}
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+ if (pt->port.iotype == UPIO_AU)
+ return 0x100000;
+#ifdef CONFIG_ARCH_OMAP
+ if (is_omap_port(pt))
+ return 0x16 << pt->port.regshift;
+#endif
+ return 8 << pt->port.regshift;
+}
+
/*
* Resource handling.
*/
static int serial8250_request_std_resource(struct uart_8250_port *up)
{
- unsigned int size = 8 << up->port.regshift;
+ unsigned int size = serial8250_port_size(up);
int ret = 0;
switch (up->port.iotype) {
case UPIO_AU:
- size = 0x100000;
- /* fall thru */
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM:
@@ -2303,12 +2332,10 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
static void serial8250_release_std_resource(struct uart_8250_port *up)
{
- unsigned int size = 8 << up->port.regshift;
+ unsigned int size = serial8250_port_size(up);
switch (up->port.iotype) {
case UPIO_AU:
- size = 0x100000;
- /* fall thru */
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM:
@@ -2622,7 +2649,6 @@ static int serial8250_console_early_setup(void)
return serial8250_find_port_for_earlycon();
}
-static struct uart_driver serial8250_reg;
static struct console serial8250_console = {
.name = "ttyS",
.write = serial8250_console_write,
@@ -2669,7 +2695,6 @@ static struct uart_driver serial8250_reg = {
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
- .nr = UART_NR,
.cons = SERIAL8250_CONSOLE,
};
@@ -2954,7 +2979,12 @@ static int __init serial8250_init(void)
for (i = 0; i < NR_IRQS; i++)
spin_lock_init(&irq_lists[i].lock);
+#ifdef CONFIG_SPARC
+ ret = sunserial_register_minors(&serial8250_reg, UART_NR);
+#else
+ serial8250_reg.nr = UART_NR;
ret = uart_register_driver(&serial8250_reg);
+#endif
if (ret)
goto out;
@@ -2979,7 +3009,11 @@ static int __init serial8250_init(void)
put_dev:
platform_device_put(serial8250_isa_devs);
unreg_uart_drv:
+#ifdef CONFIG_SPARC
+ sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
uart_unregister_driver(&serial8250_reg);
+#endif
out:
return ret;
}
@@ -2998,7 +3032,11 @@ static void __exit serial8250_exit(void)
platform_driver_unregister(&serial8250_isa_driver);
platform_device_unregister(isa_dev);
+#ifdef CONFIG_SPARC
+ sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
uart_unregister_driver(&serial8250_reg);
+#endif
}
module_init(serial8250_init);
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 78c00162b04..520260326f3 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -47,6 +47,7 @@ struct serial8250_config {
#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index c2f23933155..c014ffb110e 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -2041,9 +2041,9 @@ static int pciserial_resume_one(struct pci_dev *dev)
* The device may have been disabled. Re-enable it.
*/
err = pci_enable_device(dev);
+ /* FIXME: We cannot simply error out here */
if (err)
- return err;
-
+ printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
pciserial_resume_ports(priv);
}
return 0;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 77cb34270fc..db783b77a88 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -9,7 +9,6 @@ menu "Serial drivers"
# The new 8250/16550 serial drivers
config SERIAL_8250
tristate "8250/16550 and compatible serial support"
- depends on (BROKEN || !SPARC)
select SERIAL_CORE
---help---
This selects whether you want to include the driver for the standard
@@ -994,24 +993,12 @@ config SERIAL_68328_RTS_CTS
bool "Support RTS/CTS on 68328 serial port"
depends on SERIAL_68328
-config SERIAL_COLDFIRE
- bool "ColdFire serial support (DEPRECATED)"
- depends on COLDFIRE
- help
- This driver supports the built-in serial ports of the Motorola ColdFire
- family of CPUs.
- This driver is deprecated because it supports only the old interface
- for serial drivers and features like magic keys are not working.
- Please switch to the new style driver because this driver will be
- removed soon.
-
config SERIAL_MCF
- bool "Coldfire serial support (new style driver)"
+ bool "Coldfire serial support"
depends on COLDFIRE
select SERIAL_CORE
help
- This new serial driver supports the Freescale Coldfire serial ports
- using the new serial driver subsystem.
+ This serial driver supports the Freescale Coldfire serial ports.
config SERIAL_MCF_BAUDRATE
int "Default baudrate for Coldfire serial ports"
@@ -1136,42 +1123,6 @@ config SERIAL_CPM_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
-config SERIAL_CPM_SCC1
- bool "Support for SCC1 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SCC1 as a serial port
-
-config SERIAL_CPM_SCC2
- bool "Support for SCC2 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SCC2 as a serial port
-
-config SERIAL_CPM_SCC3
- bool "Support for SCC3 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SCC3 as a serial port
-
-config SERIAL_CPM_SCC4
- bool "Support for SCC4 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SCC4 as a serial port
-
-config SERIAL_CPM_SMC1
- bool "Support for SMC1 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SMC1 as a serial port
-
-config SERIAL_CPM_SMC2
- bool "Support for SMC2 serial port"
- depends on SERIAL_CPM=y
- help
- Select this option to use SMC2 as a serial port
-
config SERIAL_SGI_L1_CONSOLE
bool "SGI Altix L1 serial console support"
depends on IA64_GENERIC || IA64_SGI_SN2
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 7e7383e890d..0c17c8ddb19 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -4,6 +4,16 @@
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
+
+# These Sparc drivers have to appear before others such as 8250
+# which share ttySx minor node space. Otherwise console device
+# names change and other unplesantries.
+obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
+obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
+obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
+obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
+obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
+
obj-$(CONFIG_SERIAL_8250) += 8250.o
obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
@@ -31,16 +41,10 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
-obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
-obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
-obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
-obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
-obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
obj-$(CONFIG_SERIAL_68360) += 68360serial.o
-obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
obj-$(CONFIG_SERIAL_MCF) += mcf.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3a6da80b081..61fb8b6d19a 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -131,7 +131,8 @@ struct atmel_uart_char {
struct atmel_uart_port {
struct uart_port uart; /* uart */
struct clk *clk; /* uart clock */
- unsigned short suspended; /* is port suspended? */
+ int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */
+ u32 backup_imr; /* IMR saved during suspend */
int break_active; /* break being received */
short use_dma_rx; /* enable PDC receiver */
@@ -984,8 +985,15 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
* This is called on uart_open() or a resume event.
*/
clk_enable(atmel_port->clk);
+
+ /* re-enable interrupts if we disabled some on suspend */
+ UART_PUT_IER(port, atmel_port->backup_imr);
break;
case 3:
+ /* Back up the interrupt mask and disable all interrupts */
+ atmel_port->backup_imr = UART_GET_IMR(port);
+ UART_PUT_IDR(port, -1);
+
/*
* Disable the peripheral clock for this serial port.
* This is called on uart_close() or a suspend event.
@@ -1475,13 +1483,12 @@ static int atmel_serial_suspend(struct platform_device *pdev,
cpu_relax();
}
- if (device_may_wakeup(&pdev->dev)
- && !atmel_serial_clk_will_stop())
- enable_irq_wake(port->irq);
- else {
- uart_suspend_port(&atmel_uart, port);
- atmel_port->suspended = 1;
- }
+ /* we can not wake up if we're running on slow clock */
+ atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
+ if (atmel_serial_clk_will_stop())
+ device_set_wakeup_enable(&pdev->dev, 0);
+
+ uart_suspend_port(&atmel_uart, port);
return 0;
}
@@ -1491,11 +1498,8 @@ static int atmel_serial_resume(struct platform_device *pdev)
struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- if (atmel_port->suspended) {
- uart_resume_port(&atmel_uart, port);
- atmel_port->suspended = 0;
- } else
- disable_irq_wake(port->irq);
+ uart_resume_port(&atmel_uart, port);
+ device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup);
return 0;
}
@@ -1513,6 +1517,8 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE));
port = &atmel_ports[pdev->id];
+ port->backup_imr = 0;
+
atmel_init_port(port, pdev);
if (!atmel_use_dma_rx(&port->uart)) {
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 4a0d30bed9f..569f0e2476c 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -1,7 +1,7 @@
/*
* Blackfin On-Chip Serial Driver
*
- * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2008 Analog Devices Inc.
*
* Enter bugs at http://blackfin.uclinux.org/
*
@@ -42,6 +42,9 @@
#define BFIN_SERIAL_MAJOR 204
#define BFIN_SERIAL_MINOR 64
+static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
+
/*
* Setup for console. Argument comes from the menuconfig
*/
@@ -126,13 +129,13 @@ static int kgdb_entry_state;
void kgdb_put_debug_char(int chr)
{
struct bfin_serial_port *uart;
-
+
if (CONFIG_KGDB_UART_PORT < 0
|| CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
uart = &bfin_serial_ports[0];
else
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-
+
while (!(UART_GET_LSR(uart) & THRE)) {
SSYNC();
}
@@ -152,7 +155,7 @@ int kgdb_get_debug_char(void)
uart = &bfin_serial_ports[0];
else
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-
+
while(!(UART_GET_LSR(uart) & DR)) {
SSYNC();
}
@@ -298,7 +301,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
bfin_serial_mctrl_check(uart);
if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
- bfin_serial_stop_tx(&uart->port);
+#ifdef CONFIG_BF54x
+ /* Clear TFI bit */
+ UART_PUT_LSR(uart, TFI);
+#endif
+ UART_CLEAR_IER(uart, ETBEI);
return;
}
@@ -317,9 +324,6 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uart->port);
-
- if (uart_circ_empty(xmit))
- bfin_serial_stop_tx(&uart->port);
}
static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
@@ -645,6 +649,42 @@ static int bfin_serial_startup(struct uart_port *port)
free_irq(uart->port.irq, uart);
return -EBUSY;
}
+
+# ifdef CONFIG_BF54x
+ {
+ unsigned uart_dma_ch_rx, uart_dma_ch_tx;
+
+ switch (uart->port.irq) {
+ case IRQ_UART3_RX:
+ uart_dma_ch_rx = CH_UART3_RX;
+ uart_dma_ch_tx = CH_UART3_TX;
+ break;
+ case IRQ_UART2_RX:
+ uart_dma_ch_rx = CH_UART2_RX;
+ uart_dma_ch_tx = CH_UART2_TX;
+ break;
+ default:
+ uart_dma_ch_rx = uart_dma_ch_tx = 0;
+ break;
+ };
+
+ if (uart_dma_ch_rx &&
+ request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) {
+ printk(KERN_NOTICE"Fail to attach UART interrupt\n");
+ free_irq(uart->port.irq, uart);
+ free_irq(uart->port.irq + 1, uart);
+ return -EBUSY;
+ }
+ if (uart_dma_ch_tx &&
+ request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) {
+ printk(KERN_NOTICE "Fail to attach UART interrupt\n");
+ free_dma(uart_dma_ch_rx);
+ free_irq(uart->port.irq, uart);
+ free_irq(uart->port.irq + 1, uart);
+ return -EBUSY;
+ }
+ }
+# endif
#endif
UART_SET_IER(uart, ERBFI);
return 0;
@@ -662,6 +702,20 @@ static void bfin_serial_shutdown(struct uart_port *port)
del_timer(&(uart->rx_dma_timer));
dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0);
#else
+#ifdef CONFIG_BF54x
+ switch (uart->port.irq) {
+ case IRQ_UART3_RX:
+ free_dma(CH_UART3_RX);
+ free_dma(CH_UART3_TX);
+ break;
+ case IRQ_UART2_RX:
+ free_dma(CH_UART2_RX);
+ free_dma(CH_UART2_TX);
+ break;
+ default:
+ break;
+ };
+#endif
#ifdef CONFIG_KGDB_UART
if (uart->port.line != CONFIG_KGDB_UART_PORT)
#endif
@@ -757,6 +811,9 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
val |= UCEN;
UART_PUT_GCTL(uart, val);
+ /* Port speed changed, update the per-port timeout. */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
spin_unlock_irqrestore(&uart->port.lock, flags);
}
@@ -859,8 +916,9 @@ static void __init bfin_serial_init_ports(void)
return;
first = 0;
- for (i = 0; i < nr_ports; i++) {
+ for (i = 0; i < nr_active_ports; i++) {
bfin_serial_ports[i].port.uartclk = get_sclk();
+ bfin_serial_ports[i].port.fifosize = BFIN_UART_TX_FIFO_SIZE;
bfin_serial_ports[i].port.ops = &bfin_serial_pops;
bfin_serial_ports[i].port.line = i;
bfin_serial_ports[i].port.iotype = UPIO_MEM;
@@ -961,7 +1019,7 @@ bfin_serial_console_setup(struct console *co, char *options)
* if so, search for the first available port that does have
* console support.
*/
- if (co->index == -1 || co->index >= nr_ports)
+ if (co->index == -1 || co->index >= nr_active_ports)
co->index = 0;
uart = &bfin_serial_ports[co->index];
@@ -1056,7 +1114,7 @@ static __init void early_serial_write(struct console *con, const char *s,
}
}
-static struct __init console bfin_early_serial_console = {
+static struct __initdata console bfin_early_serial_console = {
.name = "early_BFuart",
.write = early_serial_write,
.device = uart_console_device,
@@ -1072,7 +1130,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port,
struct bfin_serial_port *uart;
struct ktermios t;
- if (port == -1 || port >= nr_ports)
+ if (port == -1 || port >= nr_active_ports)
port = 0;
bfin_serial_init_ports();
bfin_early_serial_console.index = port;
@@ -1100,20 +1158,26 @@ static struct uart_driver bfin_serial_reg = {
static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state)
{
- struct bfin_serial_port *uart = platform_get_drvdata(dev);
+ int i;
- if (uart)
- uart_suspend_port(&bfin_serial_reg, &uart->port);
+ for (i = 0; i < nr_active_ports; i++) {
+ if (bfin_serial_ports[i].port.dev != &dev->dev)
+ continue;
+ uart_suspend_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+ }
return 0;
}
static int bfin_serial_resume(struct platform_device *dev)
{
- struct bfin_serial_port *uart = platform_get_drvdata(dev);
+ int i;
- if (uart)
- uart_resume_port(&bfin_serial_reg, &uart->port);
+ for (i = 0; i < nr_active_ports; i++) {
+ if (bfin_serial_ports[i].port.dev != &dev->dev)
+ continue;
+ uart_resume_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+ }
return 0;
}
@@ -1128,32 +1192,31 @@ static int bfin_serial_probe(struct platform_device *dev)
break;
if (i < dev->num_resources) {
- for (i = 0; i < nr_ports; i++, res++) {
+ for (i = 0; i < nr_active_ports; i++, res++) {
if (bfin_serial_ports[i].port.mapbase != res->start)
continue;
bfin_serial_ports[i].port.dev = &dev->dev;
uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
- platform_set_drvdata(dev, &bfin_serial_ports[i]);
}
}
return 0;
}
-static int bfin_serial_remove(struct platform_device *pdev)
+static int bfin_serial_remove(struct platform_device *dev)
{
- struct bfin_serial_port *uart = platform_get_drvdata(pdev);
-
+ int i;
+ for (i = 0; i < nr_active_ports; i++) {
+ if (bfin_serial_ports[i].port.dev != &dev->dev)
+ continue;
+ uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+ bfin_serial_ports[i].port.dev = NULL;
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
- gpio_free(uart->cts_pin);
- gpio_free(uart->rts_pin);
+ gpio_free(bfin_serial_ports[i].cts_pin);
+ gpio_free(bfin_serial_ports[i].rts_pin);
#endif
-
- platform_set_drvdata(pdev, NULL);
-
- if (uart)
- uart_remove_one_port(&bfin_serial_reg, &uart->port);
+ }
return 0;
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 25efca5a7a1..a6c4d744495 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -1333,6 +1333,9 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev,
if (ret)
return ret;
+ /* initialize the device pointer for the port */
+ pinfo->port.dev = &ofdev->dev;
+
return uart_add_one_port(&cpm_reg, &pinfo->port);
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 0f0aff06c59..1b94c56ec23 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -100,7 +100,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = (u32)cpm_dpram_phys(mem_addr);
} else
- mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+ mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
GFP_KERNEL);
if (mem_addr == NULL) {
@@ -127,8 +127,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
{
- dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
- pinfo->rx_fifosize) +
+ dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+ pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
pinfo->tx_fifosize), pinfo->mem_addr,
pinfo->dma_addr);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index b8db4d3eed3..141c0a3333a 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -136,7 +136,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
dma_addr = virt_to_bus(mem_addr);
}
else
- mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+ mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
GFP_KERNEL);
if (mem_addr == NULL) {
@@ -163,8 +163,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
{
- dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
- pinfo->rx_fifosize) +
+ dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+ pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
pinfo->dma_addr);
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index bf94a770bb4..211c21797ce 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -457,7 +457,6 @@ static struct e100_serial rs_table[] = {
#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
static struct ktermios *serial_termios[NR_PORTS];
-static struct ktermios *serial_termios_locked[NR_PORTS];
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
static struct fast_timer fast_timers[NR_PORTS];
#endif
@@ -4419,6 +4418,7 @@ rs_init(void)
rs485_pa_bit)) {
printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
"RS485 pin\n");
+ put_tty_driver(driver);
return -EBUSY;
}
#endif
@@ -4427,6 +4427,7 @@ rs_init(void)
rs485_port_g_bit)) {
printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
"RS485 pin\n");
+ put_tty_driver(driver);
return -EBUSY;
}
#endif
@@ -4446,8 +4447,6 @@ rs_init(void)
driver->init_termios.c_ispeed = 115200;
driver->init_termios.c_ospeed = 115200;
driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- driver->termios = serial_termios;
- driver->termios_locked = serial_termios_locked;
tty_set_operations(driver, &rs_ops);
serial_driver = driver;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 6a29f9330a7..3f90f1bbbbc 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -127,8 +127,13 @@
#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
-#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */
-#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */
+#ifdef CONFIG_ARCH_IMX
+#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */
+#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */
+#endif
+#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3
+#define UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */
+#endif
#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
#define UCR3_BPEN (1<<0) /* Preset registers enable */
#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
@@ -445,7 +450,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
imx_txint(irq, dev_id);
- if (sts & USR1_RTSS)
+ if (sts & USR1_RTSD)
imx_rtsint(irq, dev_id);
return IRQ_HANDLED;
@@ -598,6 +603,12 @@ static int imx_startup(struct uart_port *port)
temp |= (UCR2_RXEN | UCR2_TXEN);
writel(temp, sport->port.membase + UCR2);
+#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3
+ temp = readl(sport->port.membase + UCR3);
+ temp |= UCR3_RXDMUXSEL;
+ writel(temp, sport->port.membase + UCR3);
+#endif
+
/*
* Enable modem status interrupts
*/
@@ -1133,13 +1144,19 @@ static int serial_imx_probe(struct platform_device *pdev)
if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
sport->have_rtscts = 1;
- if (pdata->init)
- pdata->init(pdev);
+ if (pdata->init) {
+ ret = pdata->init(pdev);
+ if (ret)
+ goto clkput;
+ }
uart_add_one_port(&imx_reg, &sport->port);
platform_set_drvdata(pdev, &sport->port);
return 0;
+clkput:
+ clk_put(sport->clk);
+ clk_disable(sport->clk);
unmap:
iounmap(sport->port.membase);
free:
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
deleted file mode 100644
index fbe3835f6b7..00000000000
--- a/drivers/serial/mcfserial.c
+++ /dev/null
@@ -1,1965 +0,0 @@
-#warning This driver is deprecated. Check Kconfig for details.
-/*
- * mcfserial.c -- serial driver for ColdFire internal UARTS.
- *
- * Copyright (C) 1999-2003 Greg Ungerer <gerg@snapgear.com>
- * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com>
- * Copyright (C) 2001-2002 SnapGear Inc. <www.snapgear.com>
- *
- * Based on code from 68332serial.c which was:
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 TSHG
- * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org>
- *
- * Changes:
- * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
- * some cleanups in mcfrs_write.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/delay.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/nettel.h>
-#include <asm/uaccess.h>
-#include "mcfserial.h"
-
-struct timer_list mcfrs_timer_struct;
-
-/*
- * Default console baud rate, we use this as the default
- * for all ports so init can just open /dev/console and
- * keep going. Perhaps one day the cflag settings for the
- * console can be used instead.
- */
-#if defined(CONFIG_HW_FEITH)
-#define CONSOLE_BAUD_RATE 38400
-#define DEFAULT_CBAUD B38400
-#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \
- defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO)
-#define CONSOLE_BAUD_RATE 115200
-#define DEFAULT_CBAUD B115200
-#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
- defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET)
-#define CONSOLE_BAUD_RATE 19200
-#define DEFAULT_CBAUD B19200
-#endif
-
-#ifndef CONSOLE_BAUD_RATE
-#define CONSOLE_BAUD_RATE 9600
-#define DEFAULT_CBAUD B9600
-#endif
-
-int mcfrs_console_inited = 0;
-int mcfrs_console_port = -1;
-int mcfrs_console_baud = CONSOLE_BAUD_RATE;
-int mcfrs_console_cbaud = DEFAULT_CBAUD;
-
-/*
- * Driver data structures.
- */
-static struct tty_driver *mcfrs_serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* Debugging...
- */
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x)
-#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
-#else
-#define IRQBASE 73
-#endif
-
-/*
- * Configuration table, UARTs to look for at startup.
- */
-static struct mcf_serial mcfrs_table[] = {
- { /* ttyS0 */
- .magic = 0,
- .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE1),
- .irq = IRQBASE,
- .flags = ASYNC_BOOT_AUTOCONF,
- },
-#ifdef MCFUART_BASE2
- { /* ttyS1 */
- .magic = 0,
- .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2),
- .irq = IRQBASE+1,
- .flags = ASYNC_BOOT_AUTOCONF,
- },
-#endif
-#ifdef MCFUART_BASE3
- { /* ttyS2 */
- .magic = 0,
- .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3),
- .irq = IRQBASE+2,
- .flags = ASYNC_BOOT_AUTOCONF,
- },
-#endif
-#ifdef MCFUART_BASE4
- { /* ttyS3 */
- .magic = 0,
- .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4),
- .irq = IRQBASE+3,
- .flags = ASYNC_BOOT_AUTOCONF,
- },
-#endif
-};
-
-
-#define NR_PORTS (sizeof(mcfrs_table) / sizeof(struct mcf_serial))
-
-/*
- * This is used to figure out the divisor speeds and the timeouts.
- */
-static int mcfrs_baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0
-};
-#define MCFRS_BAUD_TABLE_SIZE \
- (sizeof(mcfrs_baud_table)/sizeof(mcfrs_baud_table[0]))
-
-
-#ifdef CONFIG_MAGIC_SYSRQ
-/*
- * Magic system request keys. Used for debugging...
- */
-extern int magic_sysrq_key(int ch);
-#endif
-
-
-/*
- * Forware declarations...
- */
-static void mcfrs_change_speed(struct mcf_serial *info);
-static void mcfrs_wait_until_sent(struct tty_struct *tty, int timeout);
-
-
-static inline int serial_paranoia_check(struct mcf_serial *info,
- char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- static const char badmagic[] =
- "MCFRS(warning): bad magic number for serial struct %s in %s\n";
- static const char badinfo[] =
- "MCFRS(warning): null mcf_serial for %s in %s\n";
-
- if (!info) {
- printk(badinfo, name, routine);
- return 1;
- }
- if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
- * Sets or clears DTR and RTS on the requested line.
- */
-static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
-
-#if 0
- printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n",
- __FILE__, __LINE__, info, dtr, rts);
-#endif
-
- local_irq_save(flags);
- if (dtr >= 0) {
-#ifdef MCFPP_DTR0
- if (info->line)
- mcf_setppdata(MCFPP_DTR1, (dtr ? 0 : MCFPP_DTR1));
- else
- mcf_setppdata(MCFPP_DTR0, (dtr ? 0 : MCFPP_DTR0));
-#endif
- }
- if (rts >= 0) {
- uartp = info->addr;
- if (rts) {
- info->sigs |= TIOCM_RTS;
- uartp[MCFUART_UOP1] = MCFUART_UOP_RTS;
- } else {
- info->sigs &= ~TIOCM_RTS;
- uartp[MCFUART_UOP0] = MCFUART_UOP_RTS;
- }
- }
- local_irq_restore(flags);
- return;
-}
-
-/*
- * Gets values of serial signals.
- */
-static int mcfrs_getsignals(struct mcf_serial *info)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
- int sigs;
-#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
- unsigned short ppdata;
-#endif
-
-#if 0
- printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__);
-#endif
-
- local_irq_save(flags);
- uartp = info->addr;
- sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS;
- sigs |= (info->sigs & TIOCM_RTS);
-
-#ifdef MCFPP_DCD0
-{
- unsigned int ppdata;
- ppdata = mcf_getppdata();
- if (info->line == 0) {
- sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD;
- sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR;
- } else if (info->line == 1) {
- sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD;
- sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR;
- }
-}
-#endif
-
- local_irq_restore(flags);
- return(sigs);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_stop() and mcfrs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void mcfrs_stop(struct tty_struct *tty)
-{
- volatile unsigned char *uartp;
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_stop"))
- return;
-
- local_irq_save(flags);
- uartp = info->addr;
- info->imr &= ~MCFUART_UIR_TXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- local_irq_restore(flags);
-}
-
-static void mcfrs_start(struct tty_struct *tty)
-{
- volatile unsigned char *uartp;
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_start"))
- return;
-
- local_irq_save(flags);
- if (info->xmit_cnt && info->xmit_buf) {
- uartp = info->addr;
- info->imr |= MCFUART_UIR_TXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- }
- local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * mcfrs_interrupt(). They were separated out for readability's sake.
- *
- * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * mcfrs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-static inline void receive_chars(struct mcf_serial *info)
-{
- volatile unsigned char *uartp;
- struct tty_struct *tty = info->port.tty;
- unsigned char status, ch, flag;
-
- if (!tty)
- return;
-
- uartp = info->addr;
-
- while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
- ch = uartp[MCFUART_URB];
- info->stats.rx++;
-
-#ifdef CONFIG_MAGIC_SYSRQ
- if (mcfrs_console_inited && (info->line == mcfrs_console_port)) {
- if (magic_sysrq_key(ch))
- continue;
- }
-#endif
-
- flag = TTY_NORMAL;
- if (status & MCFUART_USR_RXERR) {
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
- if (status & MCFUART_USR_RXBREAK) {
- info->stats.rxbreak++;
- flag = TTY_BREAK;
- } else if (status & MCFUART_USR_RXPARITY) {
- info->stats.rxparity++;
- flag = TTY_PARITY;
- } else if (status & MCFUART_USR_RXOVERRUN) {
- info->stats.rxoverrun++;
- flag = TTY_OVERRUN;
- } else if (status & MCFUART_USR_RXFRAMING) {
- info->stats.rxframing++;
- flag = TTY_FRAME;
- }
- }
- tty_insert_flip_char(tty, ch, flag);
- }
- tty_schedule_flip(tty);
- return;
-}
-
-static inline void transmit_chars(struct mcf_serial *info)
-{
- volatile unsigned char *uartp;
-
- uartp = info->addr;
-
- if (info->x_char) {
- /* Send special char - probably flow control */
- uartp[MCFUART_UTB] = info->x_char;
- info->x_char = 0;
- info->stats.tx++;
- }
-
- if ((info->xmit_cnt <= 0) || info->port.tty->stopped) {
- info->imr &= ~MCFUART_UIR_TXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- return;
- }
-
- while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) {
- uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
- info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
- info->stats.tx++;
- if (--info->xmit_cnt <= 0)
- break;
- }
-
- if (info->xmit_cnt < WAKEUP_CHARS)
- schedule_work(&info->tqueue);
- return;
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-irqreturn_t mcfrs_interrupt(int irq, void *dev_id)
-{
- struct mcf_serial *info;
- unsigned char isr;
-
- info = &mcfrs_table[(irq - IRQBASE)];
- isr = info->addr[MCFUART_UISR] & info->imr;
-
- if (isr & MCFUART_UIR_RXREADY)
- receive_chars(info);
- if (isr & MCFUART_UIR_TXREADY)
- transmit_chars(info);
- return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-static void mcfrs_offintr(struct work_struct *work)
-{
- struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue);
- struct tty_struct *tty = info->port.tty;
-
- if (tty)
- tty_wakeup(tty);
-}
-
-
-/*
- * Change of state on a DCD line.
- */
-void mcfrs_modem_change(struct mcf_serial *info, int dcd)
-{
- if (info->count == 0)
- return;
-
- if (info->flags & ASYNC_CHECK_CD) {
- if (dcd)
- wake_up_interruptible(&info->open_wait);
- else
- schedule_work(&info->tqueue_hangup);
- }
-}
-
-
-#ifdef MCFPP_DCD0
-
-unsigned short mcfrs_ppstatus;
-
-/*
- * This subroutine is called when the RS_TIMER goes off. It is used
- * to monitor the state of the DCD lines - since they have no edge
- * sensors and interrupt generators.
- */
-static void mcfrs_timer(void)
-{
- unsigned int ppstatus, dcdval, i;
-
- ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1);
-
- if (ppstatus != mcfrs_ppstatus) {
- for (i = 0; (i < 2); i++) {
- dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0);
- if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) {
- mcfrs_modem_change(&mcfrs_table[i],
- ((ppstatus & dcdval) ? 0 : 1));
- }
- }
- }
- mcfrs_ppstatus = ppstatus;
-
- /* Re-arm timer */
- mcfrs_timer_struct.expires = jiffies + HZ/25;
- add_timer(&mcfrs_timer_struct);
-}
-
-#endif /* MCFPP_DCD0 */
-
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> mcfrs_hangup()
- *
- */
-static void do_serial_hangup(struct work_struct *work)
-{
- struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup);
- struct tty_struct *tty = info->port.tty;
-
- if (tty)
- tty_hangup(tty);
-}
-
-static int startup(struct mcf_serial * info)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
-
- if (info->flags & ASYNC_INITIALIZED)
- return 0;
-
- if (!info->xmit_buf) {
- info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL);
- if (!info->xmit_buf)
- return -ENOMEM;
- }
-
- local_irq_save(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
-
- /*
- * Reset UART, get it into known state...
- */
- uartp = info->addr;
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
- mcfrs_setsignals(info, 1, 1);
-
- if (info->port.tty)
- clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
- /*
- * and set the speed of the serial port
- */
- mcfrs_change_speed(info);
-
- /*
- * Lastly enable the UART transmitter and receiver, and
- * interrupt enables.
- */
- info->imr = MCFUART_UIR_RXREADY;
- uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
- uartp[MCFUART_UIMR] = info->imr;
-
- info->flags |= ASYNC_INITIALIZED;
- local_irq_restore(flags);
- return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct mcf_serial * info)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial port %d (irq %d)....\n", info->line,
- info->irq);
-#endif
-
- local_irq_save(flags);
-
- uartp = info->addr;
- uartp[MCFUART_UIMR] = 0; /* mask all interrupts */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
-
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
- mcfrs_setsignals(info, 0, 0);
-
- if (info->xmit_buf) {
- free_page((unsigned long) info->xmit_buf);
- info->xmit_buf = 0;
- }
-
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- local_irq_restore(flags);
-}
-
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void mcfrs_change_speed(struct mcf_serial *info)
-{
- volatile unsigned char *uartp;
- unsigned int baudclk, cflag;
- unsigned long flags;
- unsigned char mr1, mr2;
- int i;
-#ifdef CONFIG_M5272
- unsigned int fraction;
-#endif
-
- if (!info->port.tty || !info->port.tty->termios)
- return;
- cflag = info->port.tty->termios->c_cflag;
- if (info->addr == 0)
- return;
-
-#if 0
- printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__);
-#endif
-
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~CBAUDEX;
- if (i < 1 || i > 4)
- info->port.tty->termios->c_cflag &= ~CBAUDEX;
- else
- i += 15;
- }
- if (i == 0) {
- mcfrs_setsignals(info, 0, -1);
- return;
- }
-
- /* compute the baudrate clock */
-#ifdef CONFIG_M5272
- /*
- * For the MCF5272, also compute the baudrate fraction.
- */
- baudclk = (MCF_BUSCLK / mcfrs_baud_table[i]) / 32;
- fraction = MCF_BUSCLK - (baudclk * 32 * mcfrs_baud_table[i]);
- fraction *= 16;
- fraction /= (32 * mcfrs_baud_table[i]);
-#else
- baudclk = ((MCF_BUSCLK / mcfrs_baud_table[i]) + 16) / 32;
-#endif
-
- info->baud = mcfrs_baud_table[i];
-
- mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
- mr2 = 0;
-
- switch (cflag & CSIZE) {
- case CS5: mr1 |= MCFUART_MR1_CS5; break;
- case CS6: mr1 |= MCFUART_MR1_CS6; break;
- case CS7: mr1 |= MCFUART_MR1_CS7; break;
- case CS8:
- default: mr1 |= MCFUART_MR1_CS8; break;
- }
-
- if (cflag & PARENB) {
- if (cflag & CMSPAR) {
- if (cflag & PARODD)
- mr1 |= MCFUART_MR1_PARITYMARK;
- else
- mr1 |= MCFUART_MR1_PARITYSPACE;
- } else {
- if (cflag & PARODD)
- mr1 |= MCFUART_MR1_PARITYODD;
- else
- mr1 |= MCFUART_MR1_PARITYEVEN;
- }
- } else {
- mr1 |= MCFUART_MR1_PARITYNONE;
- }
-
- if (cflag & CSTOPB)
- mr2 |= MCFUART_MR2_STOP2;
- else
- mr2 |= MCFUART_MR2_STOP1;
-
- if (cflag & CRTSCTS) {
- mr1 |= MCFUART_MR1_RXRTS;
- mr2 |= MCFUART_MR2_TXCTS;
- }
-
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else
- info->flags |= ASYNC_CHECK_CD;
-
- uartp = info->addr;
-
- local_irq_save(flags);
-#if 0
- printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__,
- mr1, mr2, baudclk);
-#endif
- /*
- Note: pg 12-16 of MCF5206e User's Manual states that a
- software reset should be performed prior to changing
- UMR1,2, UCSR, UACR, bit 7
- */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
- uartp[MCFUART_UMR] = mr1;
- uartp[MCFUART_UMR] = mr2;
- uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8; /* set msb byte */
- uartp[MCFUART_UBG2] = (baudclk & 0xff); /* set lsb byte */
-#ifdef CONFIG_M5272
- uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */
-#endif
- uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
- uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
- mcfrs_setsignals(info, 1, -1);
- local_irq_restore(flags);
- return;
-}
-
-static void mcfrs_flush_chars(struct tty_struct *tty)
-{
- volatile unsigned char *uartp;
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_flush_chars"))
- return;
-
- uartp = (volatile unsigned char *) info->addr;
-
- /*
- * re-enable receiver interrupt
- */
- local_irq_save(flags);
- if ((!(info->imr & MCFUART_UIR_RXREADY)) &&
- (info->flags & ASYNC_INITIALIZED) ) {
- info->imr |= MCFUART_UIR_RXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- }
- local_irq_restore(flags);
-
- if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !info->xmit_buf)
- return;
-
- /* Enable transmitter */
- local_irq_save(flags);
- info->imr |= MCFUART_UIR_TXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- local_irq_restore(flags);
-}
-
-static int mcfrs_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- volatile unsigned char *uartp;
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
- int c, total = 0;
-
-#if 0
- printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n",
- __FILE__, __LINE__, (int)tty, (int)buf, count);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_write"))
- return 0;
-
- if (!tty || !info->xmit_buf)
- return 0;
-
- local_save_flags(flags);
- while (1) {
- local_irq_disable();
- c = min(count, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1,
- ((int)SERIAL_XMIT_SIZE) - info->xmit_head));
- local_irq_restore(flags);
-
- if (c <= 0)
- break;
-
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
-
- local_irq_disable();
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- local_irq_restore(flags);
-
- buf += c;
- count -= c;
- total += c;
- }
-
- local_irq_disable();
- uartp = info->addr;
- info->imr |= MCFUART_UIR_TXREADY;
- uartp[MCFUART_UIMR] = info->imr;
- local_irq_restore(flags);
-
- return total;
-}
-
-static int mcfrs_write_room(struct tty_struct *tty)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- int ret;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_write_room"))
- return 0;
- ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
- return ret;
-}
-
-static int mcfrs_chars_in_buffer(struct tty_struct *tty)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_chars_in_buffer"))
- return 0;
- return info->xmit_cnt;
-}
-
-static void mcfrs_flush_buffer(struct tty_struct *tty)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_flush_buffer"))
- return;
-
- local_irq_save(flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- local_irq_restore(flags);
-
- tty_wakeup(tty);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void mcfrs_throttle(struct tty_struct * tty)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
- return;
-
- if (I_IXOFF(tty))
- info->x_char = STOP_CHAR(tty);
-
- /* Turn off RTS line (do this atomic) */
-}
-
-static void mcfrs_unthrottle(struct tty_struct * tty)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- info->x_char = START_CHAR(tty);
- }
-
- /* Assert RTS line (do this atomic) */
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct mcf_serial * info,
- struct serial_struct * retinfo)
-{
- struct serial_struct tmp;
-
- if (!retinfo)
- return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = info->type;
- tmp.line = info->line;
- tmp.port = (unsigned int) info->addr;
- tmp.irq = info->irq;
- tmp.flags = info->flags;
- tmp.baud_base = info->baud_base;
- tmp.close_delay = info->close_delay;
- tmp.closing_wait = info->closing_wait;
- tmp.custom_divisor = info->custom_divisor;
- return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-static int set_serial_info(struct mcf_serial * info,
- struct serial_struct * new_info)
-{
- struct serial_struct new_serial;
- struct mcf_serial old_info;
- int retval = 0;
-
- if (!new_info)
- return -EFAULT;
- if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
- return -EFAULT;
- old_info = *info;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.baud_base != info->baud_base) ||
- (new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (info->flags & ~ASYNC_USR_MASK)))
- return -EPERM;
- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- info->custom_divisor = new_serial.custom_divisor;
- goto check_and_exit;
- }
-
- if (info->count > 1)
- return -EBUSY;
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- info->baud_base = new_serial.baud_base;
- info->flags = ((info->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
- info->type = new_serial.type;
- info->close_delay = new_serial.close_delay;
- info->closing_wait = new_serial.closing_wait;
-
-check_and_exit:
- retval = startup(info);
- return retval;
-}
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct mcf_serial * info, unsigned int *value)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
- unsigned char status;
-
- local_irq_save(flags);
- uartp = info->addr;
- status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0;
- local_irq_restore(flags);
-
- return put_user(status,value);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break( struct mcf_serial * info, int duration)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
-
- if (!info->addr)
- return;
- set_current_state(TASK_INTERRUPTIBLE);
- uartp = info->addr;
-
- local_irq_save(flags);
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART;
- schedule_timeout(duration);
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP;
- local_irq_restore(flags);
-}
-
-static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
-{
- struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
- return -ENODEV;
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
-
- return mcfrs_getsignals(info);
-}
-
-static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
- int rts = -1, dtr = -1;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
- return -ENODEV;
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
-
- if (set & TIOCM_RTS)
- rts = 1;
- if (set & TIOCM_DTR)
- dtr = 1;
- if (clear & TIOCM_RTS)
- rts = 0;
- if (clear & TIOCM_DTR)
- dtr = 0;
-
- mcfrs_setsignals(info, dtr, rts);
-
- return 0;
-}
-
-static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
- int retval, error;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
- return -ENODEV;
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
- (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- send_break(info, HZ/4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
- return 0;
- case TIOCGSERIAL:
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct)))
- return get_serial_info(info,
- (struct serial_struct *) arg);
- return -EFAULT;
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int)))
- return get_lsr_info(info, (unsigned int *) arg);
- return -EFAULT;
- case TIOCSERGSTRUCT:
- error = copy_to_user((struct mcf_serial *) arg,
- info, sizeof(struct mcf_serial));
- if (error)
- return -EFAULT;
- return 0;
-
-#ifdef TIOCSET422
- case TIOCSET422: {
- unsigned int val;
- get_user(val, (unsigned int *) arg);
- mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11));
- break;
- }
- case TIOCGET422: {
- unsigned int val;
- val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1;
- put_user(val, (unsigned int *) arg);
- break;
- }
-#endif
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-
- if (tty->termios->c_cflag == old_termios->c_cflag)
- return;
-
- mcfrs_change_speed(info);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- mcfrs_setsignals(info, -1, 1);
-#if 0
- mcfrs_start(tty);
-#endif
- }
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * S structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void mcfrs_close(struct tty_struct *tty, struct file * filp)
-{
- volatile unsigned char *uartp;
- struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info || serial_paranoia_check(info, tty->name, "mcfrs_close"))
- return;
-
- local_irq_save(flags);
-
- if (tty_hung_up_p(filp)) {
- local_irq_restore(flags);
- return;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count);
-#endif
- if ((tty->count == 1) && (info->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("MCFRS: bad serial port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
- }
- if (--info->count < 0) {
- printk("MCFRS: bad serial port count for ttyS%d: %d\n",
- info->line, info->count);
- info->count = 0;
- }
- if (info->count) {
- local_irq_restore(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
-
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
-
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
- info->imr &= ~MCFUART_UIR_RXREADY;
- uartp = info->addr;
- uartp[MCFUART_UIMR] = info->imr;
-
-#if 0
- /* FIXME: do we need to keep this enabled for console?? */
- if (mcfrs_console_inited && (mcfrs_console_port == info->line)) {
- /* Do not disable the UART */ ;
- } else
-#endif
- shutdown(info);
- mcfrs_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- tty->closing = 0;
- info->event = 0;
- info->port.tty = NULL;
-#if 0
- if (tty->ldisc.num != ldiscs[N_TTY].num) {
- if (tty->ldisc.close)
- (tty->ldisc.close)(tty);
- tty->ldisc = ldiscs[N_TTY];
- tty->termios->c_line = N_TTY;
- if (tty->ldisc.open)
- (tty->ldisc.open)(tty);
- }
-#endif
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- local_irq_restore(flags);
-}
-
-/*
- * mcfrs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void
-mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-#ifdef CONFIG_M5272
-#define MCF5272_FIFO_SIZE 25 /* fifo size + shift reg */
-
- struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
- volatile unsigned char *uartp;
- unsigned long orig_jiffies, fifo_time, char_time, fifo_cnt;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_wait_until_sent"))
- return;
-
- orig_jiffies = jiffies;
-
- /*
- * Set the check interval to be 1/5 of the approximate time
- * to send the entire fifo, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- lock_kernel();
-
- fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud;
- char_time = fifo_time / 5;
- if (char_time == 0)
- char_time = 1;
- if (timeout && timeout < char_time)
- char_time = timeout;
-
- /*
- * Clamp the timeout period at 2 * the time to empty the
- * fifo. Just to be safe, set the minimum at .5 seconds.
- */
- fifo_time *= 2;
- if (fifo_time < (HZ/2))
- fifo_time = HZ/2;
- if (!timeout || timeout > fifo_time)
- timeout = fifo_time;
-
- /*
- * Account for the number of bytes in the UART
- * transmitter FIFO plus any byte being shifted out.
- */
- uartp = (volatile unsigned char *) info->addr;
- for (;;) {
- fifo_cnt = (uartp[MCFUART_UTF] & MCFUART_UTF_TXB);
- if ((uartp[MCFUART_USR] & (MCFUART_USR_TXREADY|
- MCFUART_USR_TXEMPTY)) ==
- MCFUART_USR_TXREADY)
- fifo_cnt++;
- if (fifo_cnt == 0)
- break;
- msleep_interruptible(jiffies_to_msecs(char_time));
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
- unlock_kernel();
-#else
- /*
- * For the other coldfire models, assume all data has been sent
- */
-#endif
-}
-
-/*
- * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void mcfrs_hangup(struct tty_struct *tty)
-{
- struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "mcfrs_hangup"))
- return;
-
- mcfrs_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- info->count = 0;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct mcf_serial *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (info->flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * mcfrs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- info->count--;
- info->blocked_open++;
- while (1) {
- local_irq_disable();
- mcfrs_setsignals(info, 1, 1);
- local_irq_enable();
- current->state = TASK_INTERRUPTIBLE;
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ASYNC_CLOSING) &&
- (do_clocal || (mcfrs_getsignals(info) & TIOCM_CD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready blocking: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- schedule();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttyS%d, count = %d\n",
- info->line, info->count);
-#endif
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-int mcfrs_open(struct tty_struct *tty, struct file * filp)
-{
- struct mcf_serial *info;
- int retval, line;
-
- line = tty->index;
- if ((line < 0) || (line >= NR_PORTS))
- return -ENODEV;
- info = mcfrs_table + line;
- if (serial_paranoia_check(info, tty->name, "mcfrs_open"))
- return -ENODEV;
-#ifdef SERIAL_DEBUG_OPEN
- printk("mcfrs_open %s, count = %d\n", tty->name, info->count);
-#endif
- info->count++;
- tty->driver_data = info;
- info->port.tty = tty;
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval)
- return retval;
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("mcfrs_open returning after block_til_ready with %d\n",
- retval);
-#endif
- return retval;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("mcfrs_open %s successful...\n", tty->name);
-#endif
- return 0;
-}
-
-/*
- * Based on the line number set up the internal interrupt stuff.
- */
-static void mcfrs_irqinit(struct mcf_serial *info)
-{
-#if defined(CONFIG_M5272)
- volatile unsigned long *icrp;
- volatile unsigned long *portp;
- volatile unsigned char *uartp;
-
- uartp = info->addr;
- icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2);
-
- switch (info->line) {
- case 0:
- *icrp = 0xe0000000;
- break;
- case 1:
- *icrp = 0x0e000000;
- break;
- default:
- printk("MCFRS: don't know how to handle UART %d interrupt?\n",
- info->line);
- return;
- }
-
- /* Enable the output lines for the serial ports */
- portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PBCNT);
- *portp = (*portp & ~0x000000ff) | 0x00000055;
- portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
- *portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
- volatile unsigned char *icrp, *uartp;
- volatile unsigned long *imrp;
-
- uartp = info->addr;
-
- icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
- MCFINTC_ICR0 + MCFINT_UART0 + info->line);
- *icrp = 0x30 + info->line; /* level 6, line based priority */
-
- imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
- MCFINTC_IMRL);
- *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
-#if defined(CONFIG_M527x)
- {
- /*
- * External Pin Mask Setting & Enable External Pin for Interface
- * mrcbis@aliceposta.it
- */
- u16 *serpin_enable_mask;
- serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART);
- if (info->line == 0)
- *serpin_enable_mask |= UART0_ENABLE_MASK;
- else if (info->line == 1)
- *serpin_enable_mask |= UART1_ENABLE_MASK;
- else if (info->line == 2)
- *serpin_enable_mask |= UART2_ENABLE_MASK;
- }
-#endif
-#if defined(CONFIG_M528x)
- /* make sure PUAPAR is set for UART0 and UART1 */
- if (info->line < 2) {
- volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR);
- *portp |= (0x03 << (info->line * 2));
- }
-#endif
-#elif defined(CONFIG_M520x)
- volatile unsigned char *icrp, *uartp;
- volatile unsigned long *imrp;
-
- uartp = info->addr;
-
- icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
- MCFINTC_ICR0 + MCFINT_UART0 + info->line);
- *icrp = 0x03;
-
- imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
- MCFINTC_IMRL);
- *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
- if (info->line < 2) {
- unsigned short *uart_par;
- uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART);
- if (info->line == 0)
- *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0
- | MCF_GPIO_PAR_UART_PAR_URXD0;
- else if (info->line == 1)
- *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1
- | MCF_GPIO_PAR_UART_PAR_URXD1;
- } else if (info->line == 2) {
- unsigned char *feci2c_par;
- feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
- *feci2c_par &= ~0x0F;
- *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
- | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
- }
-#elif defined(CONFIG_M532x)
- volatile unsigned char *uartp;
- uartp = info->addr;
- switch (info->line) {
- case 0:
- MCF_INTC0_ICR26 = 0x3;
- MCF_INTC0_CIMR = 26;
- /* GPIO initialization */
- MCF_GPIO_PAR_UART |= 0x000F;
- break;
- case 1:
- MCF_INTC0_ICR27 = 0x3;
- MCF_INTC0_CIMR = 27;
- /* GPIO initialization */
- MCF_GPIO_PAR_UART |= 0x0FF0;
- break;
- case 2:
- MCF_INTC0_ICR28 = 0x3;
- MCF_INTC0_CIMR = 28;
- /* GPIOs also must be initalized, depends on board */
- break;
- }
-#else
- volatile unsigned char *icrp, *uartp;
-
- switch (info->line) {
- case 0:
- icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR);
- *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
- MCFSIM_ICR_PRI1;
- mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
- break;
- case 1:
- icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR);
- *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
- MCFSIM_ICR_PRI2;
- mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
- break;
- default:
- printk("MCFRS: don't know how to handle UART %d interrupt?\n",
- info->line);
- return;
- }
-
- uartp = info->addr;
- uartp[MCFUART_UIVR] = info->irq;
-#endif
-
- /* Clear mask, so no surprise interrupts. */
- uartp[MCFUART_UIMR] = 0;
-
- if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED,
- "ColdFire UART", NULL)) {
- printk("MCFRS: Unable to attach ColdFire UART %d interrupt "
- "vector=%d\n", info->line, info->irq);
- }
-
- return;
-}
-
-
-char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n";
-
-
-/*
- * Serial stats reporting...
- */
-int mcfrs_readproc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct mcf_serial *info;
- char str[20];
- int len, sigs, i;
-
- len = sprintf(page, mcfrs_drivername);
- for (i = 0; (i < NR_PORTS); i++) {
- info = &mcfrs_table[i];
- len += sprintf((page + len), "%d: port:%x irq=%d baud:%d ",
- i, (unsigned int) info->addr, info->irq, info->baud);
- if (info->stats.rx || info->stats.tx)
- len += sprintf((page + len), "tx:%d rx:%d ",
- info->stats.tx, info->stats.rx);
- if (info->stats.rxframing)
- len += sprintf((page + len), "fe:%d ",
- info->stats.rxframing);
- if (info->stats.rxparity)
- len += sprintf((page + len), "pe:%d ",
- info->stats.rxparity);
- if (info->stats.rxbreak)
- len += sprintf((page + len), "brk:%d ",
- info->stats.rxbreak);
- if (info->stats.rxoverrun)
- len += sprintf((page + len), "oe:%d ",
- info->stats.rxoverrun);
-
- str[0] = str[1] = 0;
- if ((sigs = mcfrs_getsignals(info))) {
- if (sigs & TIOCM_RTS)
- strcat(str, "|RTS");
- if (sigs & TIOCM_CTS)
- strcat(str, "|CTS");
- if (sigs & TIOCM_DTR)
- strcat(str, "|DTR");
- if (sigs & TIOCM_CD)
- strcat(str, "|CD");
- }
-
- len += sprintf((page + len), "%s\n", &str[1]);
- }
-
- return(len);
-}
-
-
-/* Finally, routines used to initialize the serial driver. */
-
-static void show_serial_version(void)
-{
- printk(mcfrs_drivername);
-}
-
-static const struct tty_operations mcfrs_ops = {
- .open = mcfrs_open,
- .close = mcfrs_close,
- .write = mcfrs_write,
- .flush_chars = mcfrs_flush_chars,
- .write_room = mcfrs_write_room,
- .chars_in_buffer = mcfrs_chars_in_buffer,
- .flush_buffer = mcfrs_flush_buffer,
- .ioctl = mcfrs_ioctl,
- .throttle = mcfrs_throttle,
- .unthrottle = mcfrs_unthrottle,
- .set_termios = mcfrs_set_termios,
- .stop = mcfrs_stop,
- .start = mcfrs_start,
- .hangup = mcfrs_hangup,
- .read_proc = mcfrs_readproc,
- .wait_until_sent = mcfrs_wait_until_sent,
- .tiocmget = mcfrs_tiocmget,
- .tiocmset = mcfrs_tiocmset,
-};
-
-/* mcfrs_init inits the driver */
-static int __init
-mcfrs_init(void)
-{
- struct mcf_serial *info;
- unsigned long flags;
- int i;
-
- /* Setup base handler, and timer table. */
-#ifdef MCFPP_DCD0
- init_timer(&mcfrs_timer_struct);
- mcfrs_timer_struct.function = mcfrs_timer;
- mcfrs_timer_struct.data = 0;
- mcfrs_timer_struct.expires = jiffies + HZ/25;
- add_timer(&mcfrs_timer_struct);
- mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1);
-#endif
- mcfrs_serial_driver = alloc_tty_driver(NR_PORTS);
- if (!mcfrs_serial_driver)
- return -ENOMEM;
-
- show_serial_version();
-
- /* Initialize the tty_driver structure */
- mcfrs_serial_driver->owner = THIS_MODULE;
- mcfrs_serial_driver->name = "ttyS";
- mcfrs_serial_driver->driver_name = "mcfserial";
- mcfrs_serial_driver->major = TTY_MAJOR;
- mcfrs_serial_driver->minor_start = 64;
- mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL;
- mcfrs_serial_driver->init_termios = tty_std_termios;
-
- mcfrs_serial_driver->init_termios.c_cflag =
- mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL;
- mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-
- tty_set_operations(mcfrs_serial_driver, &mcfrs_ops);
-
- if (tty_register_driver(mcfrs_serial_driver)) {
- printk("MCFRS: Couldn't register serial driver\n");
- put_tty_driver(mcfrs_serial_driver);
- return(-EBUSY);
- }
-
- local_irq_save(flags);
-
- /*
- * Configure all the attached serial ports.
- */
- for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) {
- info->magic = SERIAL_MAGIC;
- info->line = i;
- info->port.tty = NULL;
- info->custom_divisor = 16;
- info->close_delay = 50;
- info->closing_wait = 3000;
- info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- INIT_WORK(&info->tqueue, mcfrs_offintr);
- INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
-
- info->imr = 0;
- mcfrs_setsignals(info, 0, 0);
- mcfrs_irqinit(info);
-
- printk("ttyS%d at 0x%04x (irq = %d)", info->line,
- (unsigned int) info->addr, info->irq);
- printk(" is a builtin ColdFire UART\n");
- }
-
- local_irq_restore(flags);
- return 0;
-}
-
-module_init(mcfrs_init);
-
-/****************************************************************************/
-/* Serial Console */
-/****************************************************************************/
-
-/*
- * Quick and dirty UART initialization, for console output.
- */
-
-void mcfrs_init_console(void)
-{
- volatile unsigned char *uartp;
- unsigned int clk;
-
- /*
- * Reset UART, get it into known state...
- */
- uartp = (volatile unsigned char *) (MCF_MBAR +
- (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
-
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
- uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
-
- /*
- * Set port for defined baud , 8 data bits, 1 stop bit, no parity.
- */
- uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
- uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
-
-#ifdef CONFIG_M5272
-{
- /*
- * For the MCF5272, also compute the baudrate fraction.
- */
- int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud);
- fraction *= 16;
- fraction /= (32 * mcfrs_console_baud);
- uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */
- clk = (MCF_BUSCLK / mcfrs_console_baud) / 32;
-}
-#else
- clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */
-#endif
-
- uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */
- uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */
- uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
- uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
-
- mcfrs_console_inited++;
- return;
-}
-
-
-/*
- * Setup for console. Argument comes from the boot command line.
- */
-
-int mcfrs_console_setup(struct console *cp, char *arg)
-{
- int i, n = CONSOLE_BAUD_RATE;
-
- if (!cp)
- return(-1);
-
- if (!strncmp(cp->name, "ttyS", 4))
- mcfrs_console_port = cp->index;
- else if (!strncmp(cp->name, "cua", 3))
- mcfrs_console_port = cp->index;
- else
- return(-1);
-
- if (arg)
- n = simple_strtoul(arg,NULL,0);
- for (i = 0; i < MCFRS_BAUD_TABLE_SIZE; i++)
- if (mcfrs_baud_table[i] == n)
- break;
- if (i < MCFRS_BAUD_TABLE_SIZE) {
- mcfrs_console_baud = n;
- mcfrs_console_cbaud = 0;
- if (i > 15) {
- mcfrs_console_cbaud |= CBAUDEX;
- i -= 15;
- }
- mcfrs_console_cbaud |= i;
- }
- mcfrs_init_console(); /* make sure baud rate changes */
- return(0);
-}
-
-
-static struct tty_driver *mcfrs_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return mcfrs_serial_driver;
-}
-
-
-/*
- * Output a single character, using UART polled mode.
- * This is used for console output.
- */
-
-int mcfrs_put_char(char ch)
-{
- volatile unsigned char *uartp;
- unsigned long flags;
- int i;
-
- uartp = (volatile unsigned char *) (MCF_MBAR +
- (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
-
- local_irq_save(flags);
- for (i = 0; (i < 0x10000); i++) {
- if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY)
- break;
- }
- if (i < 0x10000) {
- uartp[MCFUART_UTB] = ch;
- for (i = 0; (i < 0x10000); i++)
- if (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY)
- break;
- }
- if (i >= 0x10000)
- mcfrs_init_console(); /* try and get it back */
- local_irq_restore(flags);
-
- return 1;
-}
-
-
-/*
- * rs_console_write is registered for printk output.
- */
-
-void mcfrs_console_write(struct console *cp, const char *p, unsigned len)
-{
- if (!mcfrs_console_inited)
- mcfrs_init_console();
- while (len-- > 0) {
- if (*p == '\n')
- mcfrs_put_char('\r');
- mcfrs_put_char(*p++);
- }
-}
-
-/*
- * declare our consoles
- */
-
-struct console mcfrs_console = {
- .name = "ttyS",
- .write = mcfrs_console_write,
- .device = mcfrs_console_device,
- .setup = mcfrs_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int __init mcfrs_console_init(void)
-{
- register_console(&mcfrs_console);
- return 0;
-}
-
-console_initcall(mcfrs_console_init);
-
-/****************************************************************************/
diff --git a/drivers/serial/mcfserial.h b/drivers/serial/mcfserial.h
deleted file mode 100644
index 56420e2cb11..00000000000
--- a/drivers/serial/mcfserial.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * mcfserial.c -- serial driver for ColdFire internal UARTS.
- *
- * Copyright (c) 1999 Greg Ungerer <gerg@snapgear.com>
- * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com>
- * Copyright (c) 2002 SnapGear Inc., <www.snapgear.com>
- *
- * Based on code from 68332serial.c which was:
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 TSHG
- * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org>
- */
-#ifndef _MCF_SERIAL_H
-#define _MCF_SERIAL_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-/*
- * Define a local serial stats structure.
- */
-
-struct mcf_stats {
- unsigned int rx;
- unsigned int tx;
- unsigned int rxbreak;
- unsigned int rxframing;
- unsigned int rxparity;
- unsigned int rxoverrun;
-};
-
-
-/*
- * This is our internal structure for each serial port's state.
- * Each serial port has one of these structures associated with it.
- */
-
-struct mcf_serial {
- int magic;
- volatile unsigned char *addr; /* UART memory address */
- int irq;
- int flags; /* defined in tty.h */
- int type; /* UART type */
- struct tty_struct *tty;
- unsigned char imr; /* Software imr register */
- unsigned int baud;
- int sigs;
- int custom_divisor;
- int x_char; /* xon/xoff character */
- int baud_base;
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- unsigned long event;
- int line;
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- struct mcf_stats stats;
- struct work_struct tqueue;
- struct work_struct tqueue_hangup;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-
-};
-
-#endif /* __KERNEL__ */
-
-#endif /* _MCF_SERIAL_H */
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 36126070d9a..6117d3db0b6 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -72,13 +72,8 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/io.h>
-
-#if defined(CONFIG_PPC_MERGE)
#include <linux/of.h>
#include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
#include <asm/mpc52xx.h>
#include <asm/mpc512x.h>
@@ -107,12 +102,11 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
* it's cleared, then a memset(...,0,...) should be added to
* the console_init
*/
-#if defined(CONFIG_PPC_MERGE)
+
/* lookup table for matching device nodes to index numbers */
static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
static void mpc52xx_uart_of_enumerate(void);
-#endif
#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
@@ -255,17 +249,12 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
/* Search for bus-frequency property in this node or a parent */
static unsigned long mpc52xx_getuartclk(void *p)
{
-#if defined(CONFIG_PPC_MERGE)
/*
* 5200 UARTs have a / 32 prescaler
* but the generic serial code assumes 16
* so return ipb freq / 2
*/
return mpc52xx_find_ipb_freq(p) / 2;
-#else
- pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n");
- return NULL;
-#endif
}
static struct psc_ops mpc52xx_psc_ops = {
@@ -886,10 +875,6 @@ mpc52xx_console_get_options(struct uart_port *port,
/* CT{U,L}R are write-only ! */
*baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
-#if !defined(CONFIG_PPC_MERGE)
- if (__res.bi_baudrate)
- *baud = __res.bi_baudrate;
-#endif
/* Parse them */
switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
@@ -946,42 +931,6 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
psc_ops->cw_restore_ints(port);
}
-#if !defined(CONFIG_PPC_MERGE)
-static int __init
-mpc52xx_console_setup(struct console *co, char *options)
-{
- struct uart_port *port = &mpc52xx_uart_ports[co->index];
-
- int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
- return -EINVAL;
-
- /* Basic port init. Needed since we use some uart_??? func before
- * real init for early access */
- spin_lock_init(&port->lock);
- port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
- port->ops = &mpc52xx_uart_ops;
- port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
-
- /* We ioremap ourself */
- port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
- if (port->membase == NULL)
- return -EINVAL;
-
- /* Setup the port parameters accoding to options */
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-#else
static int __init
mpc52xx_console_setup(struct console *co, char *options)
@@ -1053,7 +1002,6 @@ mpc52xx_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-#endif /* defined(CONFIG_PPC_MERGE) */
static struct uart_driver mpc52xx_uart_driver;
@@ -1072,9 +1020,7 @@ static struct console mpc52xx_console = {
static int __init
mpc52xx_console_init(void)
{
-#if defined(CONFIG_PPC_MERGE)
mpc52xx_uart_of_enumerate();
-#endif
register_console(&mpc52xx_console);
return 0;
}
@@ -1100,115 +1046,6 @@ static struct uart_driver mpc52xx_uart_driver = {
.cons = MPC52xx_PSC_CONSOLE,
};
-
-#if !defined(CONFIG_PPC_MERGE)
-/* ======================================================================== */
-/* Platform Driver */
-/* ======================================================================== */
-
-static int __devinit
-mpc52xx_uart_probe(struct platform_device *dev)
-{
- struct resource *res = dev->resource;
-
- struct uart_port *port = NULL;
- int i, idx, ret;
-
- /* Check validity & presence */
- idx = dev->id;
- if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
- return -EINVAL;
-
- if (!mpc52xx_match_psc_function(idx, "uart"))
- return -ENODEV;
-
- /* Init the port structure */
- port = &mpc52xx_uart_ports[idx];
-
- spin_lock_init(&port->lock);
- port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
- port->fifosize = 512;
- port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF |
- (uart_console(port) ? 0 : UPF_IOREMAP);
- port->line = idx;
- port->ops = &mpc52xx_uart_ops;
- port->dev = &dev->dev;
-
- /* Search for IRQ and mapbase */
- for (i = 0 ; i < dev->num_resources ; i++, res++) {
- if (res->flags & IORESOURCE_MEM)
- port->mapbase = res->start;
- else if (res->flags & IORESOURCE_IRQ)
- port->irq = res->start;
- }
- if (!port->irq || !port->mapbase)
- return -EINVAL;
-
- /* Add the port to the uart sub-system */
- ret = uart_add_one_port(&mpc52xx_uart_driver, port);
- if (!ret)
- platform_set_drvdata(dev, (void *)port);
-
- return ret;
-}
-
-static int
-mpc52xx_uart_remove(struct platform_device *dev)
-{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
- platform_set_drvdata(dev, NULL);
-
- if (port)
- uart_remove_one_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
- if (port)
- uart_suspend_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-
-static int
-mpc52xx_uart_resume(struct platform_device *dev)
-{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
- if (port)
- uart_resume_port(&mpc52xx_uart_driver, port);
-
- return 0;
-}
-#endif
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc");
-
-static struct platform_driver mpc52xx_uart_platform_driver = {
- .probe = mpc52xx_uart_probe,
- .remove = mpc52xx_uart_remove,
-#ifdef CONFIG_PM
- .suspend = mpc52xx_uart_suspend,
- .resume = mpc52xx_uart_resume,
-#endif
- .driver = {
- .owner = THIS_MODULE,
- .name = "mpc52xx-psc",
- },
-};
-#endif /* !defined(CONFIG_PPC_MERGE) */
-
-
-#if defined(CONFIG_PPC_MERGE)
/* ======================================================================== */
/* OF Platform Driver */
/* ======================================================================== */
@@ -1402,7 +1239,6 @@ static struct of_platform_driver mpc52xx_uart_of_driver = {
.name = "mpc52xx-psc-uart",
},
};
-#endif /* defined(CONFIG_PPC_MERGE) */
/* ======================================================================== */
@@ -1423,7 +1259,6 @@ mpc52xx_uart_init(void)
return ret;
}
-#if defined(CONFIG_PPC_MERGE)
mpc52xx_uart_of_enumerate();
ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
@@ -1433,16 +1268,6 @@ mpc52xx_uart_init(void)
uart_unregister_driver(&mpc52xx_uart_driver);
return ret;
}
-#else
- psc_ops = &mpc52xx_psc_ops;
- ret = platform_driver_register(&mpc52xx_uart_platform_driver);
- if (ret) {
- printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
- __FILE__, ret);
- uart_unregister_driver(&mpc52xx_uart_driver);
- return ret;
- }
-#endif
return 0;
}
@@ -1450,11 +1275,7 @@ mpc52xx_uart_init(void)
static void __exit
mpc52xx_uart_exit(void)
{
-#if defined(CONFIG_PPC_MERGE)
of_unregister_platform_driver(&mpc52xx_uart_of_driver);
-#else
- platform_driver_unregister(&mpc52xx_uart_platform_driver);
-#endif
uart_unregister_driver(&mpc52xx_uart_driver);
}
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index f7a0d37c422..abc00be5543 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -534,6 +534,11 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_IER, up->ier);
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
+ else
+ up->mcr &= ~UART_MCR_AFE;
+
serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
diff --git a/drivers/serial/s3c2400.c b/drivers/serial/s3c2400.c
index c8b4266ac35..4873f2978bd 100644
--- a/drivers/serial/s3c2400.c
+++ b/drivers/serial/s3c2400.c
@@ -19,7 +19,7 @@
#include <mach/hardware.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 40a2531b554..87c182ef71b 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -21,7 +21,7 @@
#include <asm/irq.h>
#include <mach/hardware.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c
index d0170319c72..fd017b37556 100644
--- a/drivers/serial/s3c2412.c
+++ b/drivers/serial/s3c2412.c
@@ -21,7 +21,7 @@
#include <asm/irq.h>
#include <mach/hardware.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c
index d4a2b17b249..317d239ab74 100644
--- a/drivers/serial/s3c2440.c
+++ b/drivers/serial/s3c2440.c
@@ -21,7 +21,7 @@
#include <asm/irq.h>
#include <mach/hardware.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 5a88b3f9fe9..1e219d3d035 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -47,7 +47,7 @@
#include <mach/hardware.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include "samsung.h"
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index f977c98cfa9..6bdf3362e3b 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2051,7 +2051,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
"transmitter\n",
port->dev ? port->dev->bus_id : "",
port->dev ? ": " : "",
- drv->dev_name, port->line);
+ drv->dev_name,
+ drv->tty_driver->name_base + port->line);
ops->shutdown(port);
}
@@ -2154,12 +2155,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
switch (port->iotype) {
case UPIO_PORT:
- snprintf(address, sizeof(address),
- "I/O 0x%x", port->iobase);
+ snprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
break;
case UPIO_HUB6:
snprintf(address, sizeof(address),
- "I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+ "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
break;
case UPIO_MEM:
case UPIO_MEM32:
@@ -2177,7 +2177,9 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
port->dev ? port->dev->bus_id : "",
port->dev ? ": " : "",
- drv->dev_name, port->line, address, port->irq, uart_type(port));
+ drv->dev_name,
+ drv->tty_driver->name_base + port->line,
+ address, port->irq, uart_type(port));
}
static void
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 164d2a42eb5..7546aa887fa 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -431,131 +431,103 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
int i;
i = pcmcia_get_first_tuple(handle, tuple);
- if (i != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
+ if (i != 0)
return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int
-next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
-{
- int i;
- i = pcmcia_get_next_tuple(handle, tuple);
- if (i != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
+ if (i != 0)
return i;
- return pcmcia_parse_tuple(handle, tuple, parse);
+ return pcmcia_parse_tuple(tuple, parse);
}
/*====================================================================*/
-static int simple_config(struct pcmcia_device *link)
+static int simple_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
static const int size_table[2] = { 8, 16 };
- struct serial_info *info = link->priv;
- struct serial_cfg_mem *cfg_mem;
- tuple_t *tuple;
- u_char *buf;
- cisparse_t *parse;
- cistpl_cftable_entry_t *cf;
- config_info_t config;
- int i, j, try;
- int s;
+ int *try = priv_data;
+
+ if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
+ && (cf->io.win[0].base != 0)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
+ 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -EINVAL;
+}
- cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
- if (!cfg_mem)
- return -1;
+static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+ for (j = 0; j < 5; j++) {
+ p_dev->io.BasePort1 = base[j];
+ p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
- tuple = &cfg_mem->tuple;
- parse = &cfg_mem->parse;
- cf = &parse->cftable_entry;
- buf = cfg_mem->buf;
+static int simple_config(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i = -ENODEV, try;
/* If the card is already configured, look up the port and irq */
- i = pcmcia_get_configuration_info(link, &config);
- if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
+ if (link->function_config) {
unsigned int port = 0;
- if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
- port = config.BasePort2;
+ if ((link->io.BasePort2 != 0) &&
+ (link->io.NumPorts2 == 8)) {
+ port = link->io.BasePort2;
info->slave = 1;
} else if ((info->manfid == MANFID_OSITECH) &&
- (config.NumPorts1 == 0x40)) {
- port = config.BasePort1 + 0x28;
+ (link->io.NumPorts1 == 0x40)) {
+ port = link->io.BasePort1 + 0x28;
info->slave = 1;
}
if (info->slave) {
- kfree(cfg_mem);
- return setup_serial(link, info, port, config.AssignedIRQ);
+ return setup_serial(link, info, port,
+ link->irq.AssignedIRQ);
}
}
- /* First pass: look for a config entry that looks normal. */
- tuple->TupleData = (cisdata_t *) buf;
- tuple->TupleOffset = 0;
- tuple->TupleDataMax = 255;
- tuple->Attributes = 0;
- tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- /* Two tries: without IO aliases, then with aliases */
- for (s = 0; s < 2; s++) {
- for (try = 0; try < 2; try++) {
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i != CS_SUCCESS)
- goto next_entry;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
- (cf->io.win[0].base != 0)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = (try == 0) ?
- 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
-next_entry:
- i = next_tuple(link, tuple, parse);
- }
- }
- }
+ /* First pass: look for a config entry that looks normal.
+ * Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 4; try++)
+ if (!pcmcia_loop_config(link, simple_config_check, &try))
+ goto found_port;
+
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
- ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- link->conf.ConfigIndex = cf->index;
- for (j = 0; j < 5; j++) {
- link->io.BasePort1 = base[j];
- link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- }
- i = next_tuple(link, tuple, parse);
- }
+ if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
+ goto found_port;
- found_port:
- if (i != CS_SUCCESS) {
- printk(KERN_NOTICE
- "serial_cs: no usable port range found, giving up\n");
- cs_error(link, RequestIO, i);
- kfree(cfg_mem);
- return -1;
- }
+ printk(KERN_NOTICE
+ "serial_cs: no usable port range found, giving up\n");
+ cs_error(link, RequestIO, i);
+ return -1;
+found_port:
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
@@ -569,88 +541,76 @@ next_entry:
info->quirk->config(link);
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
- kfree(cfg_mem);
return -1;
}
- kfree(cfg_mem);
return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
}
-static int multi_config(struct pcmcia_device * link)
+static int multi_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- struct serial_info *info = link->priv;
- struct serial_cfg_mem *cfg_mem;
- tuple_t *tuple;
- u_char *buf;
- cisparse_t *parse;
- cistpl_cftable_entry_t *cf;
- int i, rc, base2 = 0;
+ int *base2 = priv_data;
+
+ /* The quad port cards have bad CIS's, so just look for a
+ window larger than 8 ports and assume it will be right */
+ if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+ *base2 = p_dev->io.BasePort1 + 8;
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
- cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
- if (!cfg_mem)
- return -1;
- tuple = &cfg_mem->tuple;
- parse = &cfg_mem->parse;
- cf = &parse->cftable_entry;
- buf = cfg_mem->buf;
+static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ int *base2 = priv_data;
+
+ if (cf->io.nwin == 2) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.BasePort2 = cf->io.win[1].base;
+ p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+ *base2 = p_dev->io.BasePort2;
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
- tuple->TupleData = (cisdata_t *) buf;
- tuple->TupleOffset = 0;
- tuple->TupleDataMax = 255;
- tuple->Attributes = 0;
- tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+static int multi_config(struct pcmcia_device *link)
+{
+ struct serial_info *info = link->priv;
+ int i, base2 = 0;
/* First, look for a generic full-sized window */
link->io.NumPorts1 = info->multi * 8;
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- /* The quad port cards have bad CIS's, so just look for a
- window larger than 8 ports and assume it will be right */
- if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
- (cf->io.win[0].len > 8)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines =
- cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- base2 = link->io.BasePort1 + 8;
- if (i == CS_SUCCESS)
- break;
- }
- i = next_tuple(link, tuple, parse);
- }
-
- /* If that didn't work, look for two windows */
- if (i != CS_SUCCESS) {
+ if (pcmcia_loop_config(link, multi_config_check, &base2)) {
+ /* If that didn't work, look for two windows */
link->io.NumPorts1 = link->io.NumPorts2 = 8;
info->multi = 2;
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.BasePort2 = cf->io.win[1].base;
- link->io.IOAddrLines =
- cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- base2 = link->io.BasePort2;
- if (i == CS_SUCCESS)
- break;
- }
- i = next_tuple(link, tuple, parse);
+ if (pcmcia_loop_config(link, multi_config_check_notpicky,
+ &base2)) {
+ printk(KERN_NOTICE "serial_cs: no usable port range"
+ "found, giving up\n");
+ return -ENODEV;
}
}
- if (i != CS_SUCCESS) {
- cs_error(link, RequestIO, i);
- rc = -1;
- goto free_cfg_mem;
- }
-
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
+ /* FIXME: comment does not fit, error handling does not fit */
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
cs_error(link, RequestIRQ, i);
@@ -664,10 +624,9 @@ static int multi_config(struct pcmcia_device * link)
info->quirk->config(link);
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
- rc = -1;
- goto free_cfg_mem;
+ return -ENODEV;
}
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -678,7 +637,8 @@ static int multi_config(struct pcmcia_device * link)
info->prodid == PRODID_POSSIO_GCC)) {
int err;
- if (cf->index == 1 || cf->index == 3) {
+ if (link->conf.ConfigIndex == 1 ||
+ link->conf.ConfigIndex == 3) {
err = setup_serial(link, info, base2,
link->irq.AssignedIRQ);
base2 = link->io.BasePort1;
@@ -695,18 +655,14 @@ static int multi_config(struct pcmcia_device * link)
if (info->quirk && info->quirk->wakeup)
info->quirk->wakeup(link);
- rc = 0;
- goto free_cfg_mem;
+ return 0;
}
setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
for (i = 0; i < info->multi - 1; i++)
setup_serial(link, info, base2 + (8 * i),
link->irq.AssignedIRQ);
- rc = 0;
-free_cfg_mem:
- kfree(cfg_mem);
- return rc;
+ return 0;
}
/*======================================================================
@@ -746,7 +702,7 @@ static int serial_config(struct pcmcia_device * link)
/* Is this a compliant multifunction card? */
tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
- info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
+ info->multi = (first_tuple(link, tuple, parse) == 0);
/* Is this a multiport card? */
tuple->DesiredTuple = CISTPL_MANFID;
@@ -770,7 +726,7 @@ static int serial_config(struct pcmcia_device * link)
((link->func_id == CISTPL_FUNCID_MULTI) ||
(link->func_id == CISTPL_FUNCID_SERIAL))) {
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == 0) {
if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
info->multi = cf->io.win[0].len >> 3;
if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
index b9cbfc87f61..998e89dc5aa 100644
--- a/drivers/serial/serial_ks8695.c
+++ b/drivers/serial/serial_ks8695.c
@@ -63,8 +63,44 @@
#define UART_DUMMY_LSR_RX 0x100
#define UART_PORT_SIZE (KS8695_USR - KS8695_URRB + 4)
-#define tx_enabled(port) ((port)->unused[0])
-#define rx_enabled(port) ((port)->unused[1])
+static inline int tx_enabled(struct uart_port *port)
+{
+ return port->unused[0] & 1;
+}
+
+static inline int rx_enabled(struct uart_port *port)
+{
+ return port->unused[0] & 2;
+}
+
+static inline int ms_enabled(struct uart_port *port)
+{
+ return port->unused[0] & 4;
+}
+
+static inline void ms_enable(struct uart_port *port, int enabled)
+{
+ if(enabled)
+ port->unused[0] |= 4;
+ else
+ port->unused[0] &= ~4;
+}
+
+static inline void rx_enable(struct uart_port *port, int enabled)
+{
+ if(enabled)
+ port->unused[0] |= 2;
+ else
+ port->unused[0] &= ~2;
+}
+
+static inline void tx_enable(struct uart_port *port, int enabled)
+{
+ if(enabled)
+ port->unused[0] |= 1;
+ else
+ port->unused[0] &= ~1;
+}
#ifdef SUPPORT_SYSRQ
@@ -75,7 +111,7 @@ static void ks8695uart_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(KS8695_IRQ_UART_TX);
- tx_enabled(port) = 0;
+ tx_enable(port, 0);
}
}
@@ -83,7 +119,7 @@ static void ks8695uart_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(KS8695_IRQ_UART_TX);
- tx_enabled(port) = 1;
+ tx_enable(port, 1);
}
}
@@ -91,18 +127,24 @@ static void ks8695uart_stop_rx(struct uart_port *port)
{
if (rx_enabled(port)) {
disable_irq(KS8695_IRQ_UART_RX);
- rx_enabled(port) = 0;
+ rx_enable(port, 0);
}
}
static void ks8695uart_enable_ms(struct uart_port *port)
{
- enable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+ if (!ms_enabled(port)) {
+ enable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+ ms_enable(port,1);
+ }
}
static void ks8695uart_disable_ms(struct uart_port *port)
{
- disable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+ if (ms_enabled(port)) {
+ disable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+ ms_enable(port,0);
+ }
}
static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id)
@@ -285,8 +327,9 @@ static int ks8695uart_startup(struct uart_port *port)
int retval;
set_irq_flags(KS8695_IRQ_UART_TX, IRQF_VALID | IRQF_NOAUTOEN);
- tx_enabled(port) = 0;
- rx_enabled(port) = 1;
+ tx_enable(port, 0);
+ rx_enable(port, 1);
+ ms_enable(port, 1);
/*
* Allocate the IRQ
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index e41766d0803..a94a2ab4b57 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -616,7 +616,7 @@ static int __devexit hv_remove(struct of_device *dev)
return 0;
}
-static struct of_device_id hv_match[] = {
+static const struct of_device_id hv_match[] = {
{
.name = "console",
.compatible = "qcn",
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 29b4458abf7..0355efe115d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1078,7 +1078,7 @@ static int __devexit sab_remove(struct of_device *op)
return 0;
}
-static struct of_device_id sab_match[] = {
+static const struct of_device_id sab_match[] = {
{
.name = "se",
},
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index a378464f929..a4dc79b1d7a 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1506,7 +1506,7 @@ static int __devexit su_remove(struct of_device *op)
return 0;
}
-static struct of_device_id su_match[] = {
+static const struct of_device_id su_match[] = {
{
.name = "su",
},
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 3cb4c8aee13..45a299f3561 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1480,7 +1480,7 @@ static int __devexit zs_remove(struct of_device *op)
return 0;
}
-static struct of_device_id zs_match[] = {
+static const struct of_device_id zs_match[] = {
{
.name = "zs",
},
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 5c5d18dcb6a..539c933b335 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1009,7 +1009,7 @@ static int qe_uart_request_port(struct uart_port *port)
rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
- bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr,
+ bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr,
GFP_KERNEL);
if (!bd_virt) {
dev_err(port->dev, "could not allocate buffer descriptors\n");
@@ -1051,7 +1051,7 @@ static void qe_uart_release_port(struct uart_port *port)
container_of(port, struct uart_qe_port, port);
struct ucc_slow_private *uccs = qe_port->us_private;
- dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt,
+ dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt,
qe_port->bd_dma_addr);
ucc_slow_free(uccs);
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 25eda71f4bf..0debe11b67b 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -15,13 +15,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-
-#if defined(CONFIG_PPC_MERGE)
#include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
-
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/io.h>
@@ -108,13 +102,13 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
* Because psc->ccr is defined as 16bit register instead of 32bit
* just set the lower byte of BitClkDiv
*/
- ccr = in_be16(&psc->ccr);
+ ccr = in_be16((u16 __iomem *)&psc->ccr);
ccr &= 0xFF00;
if (cs->speed_hz)
ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
else /* by default SPI Clk 1MHz */
ccr |= (MCLK / 1000000 - 1) & 0xFF;
- out_be16(&psc->ccr, ccr);
+ out_be16((u16 __iomem *)&psc->ccr, ccr);
mps->bits_per_word = cs->bits_per_word;
if (mps->activate_cs)
@@ -347,7 +341,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
/* Configure 8bit codec mode as a SPI master and use EOF flags */
/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
out_be32(&psc->sicr, 0x0180C800);
- out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+ out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
/* Set 2ms DTL delay */
out_8(&psc->ctur, 0x00);
@@ -471,53 +465,6 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
return 0;
}
-#if !defined(CONFIG_PPC_MERGE)
-static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
-{
- switch(dev->id) {
- case 1:
- case 2:
- case 3:
- case 6:
- return mpc52xx_psc_spi_do_probe(&dev->dev,
- MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
- MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
- default:
- return -EINVAL;
- }
-}
-
-static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
-{
- return mpc52xx_psc_spi_do_remove(&dev->dev);
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc-spi");
-
-static struct platform_driver mpc52xx_psc_spi_platform_driver = {
- .remove = __exit_p(mpc52xx_psc_spi_remove),
- .driver = {
- .name = "mpc52xx-psc-spi",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init mpc52xx_psc_spi_init(void)
-{
- return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
- mpc52xx_psc_spi_probe);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
- platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
-
-#else /* defined(CONFIG_PPC_MERGE) */
-
static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
const struct of_device_id *match)
{
@@ -586,8 +533,6 @@ static void __exit mpc52xx_psc_spi_exit(void)
}
module_exit(mpc52xx_psc_spi_exit);
-#endif /* defined(CONFIG_PPC_MERGE) */
-
MODULE_AUTHOR("Dragos Carp");
MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 9d2186fd74a..454a2712e62 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -119,12 +119,14 @@ struct omap2_mcspi {
struct clk *fck;
/* Virtual base address of the controller */
void __iomem *base;
+ unsigned long phys;
/* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels;
};
struct omap2_mcspi_cs {
void __iomem *base;
+ unsigned long phys;
int word_len;
};
@@ -233,7 +235,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
c = count;
word_len = cs->word_len;
- base = (unsigned long) io_v2p(cs->base);
+ base = cs->phys;
tx_reg = base + OMAP2_MCSPI_TX0;
rx_reg = base + OMAP2_MCSPI_RX0;
rx = xfer->rx_buf;
@@ -633,6 +635,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
if (!cs)
return -ENOMEM;
cs->base = mcspi->base + spi->chip_select * 0x14;
+ cs->phys = mcspi->phys + spi->chip_select * 0x14;
spi->controller_state = cs;
}
@@ -1005,7 +1008,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
goto err1;
}
- mcspi->base = (void __iomem *) io_p2v(r->start);
+ mcspi->phys = r->start;
+ mcspi->base = ioremap(r->start, r->end - r->start + 1);
+ if (!mcspi->base) {
+ dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
+ status = -ENOMEM;
+ goto err1aa;
+ }
INIT_WORK(&mcspi->work, omap2_mcspi_work);
@@ -1055,6 +1064,8 @@ err3:
err2:
clk_put(mcspi->ick);
err1a:
+ iounmap(mcspi->base);
+err1aa:
release_mem_region(r->start, (r->end - r->start) + 1);
err1:
spi_master_put(master);
@@ -1067,6 +1078,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *dma_channels;
struct resource *r;
+ void __iomem *base;
master = dev_get_drvdata(&pdev->dev);
mcspi = spi_master_get_devdata(master);
@@ -1078,7 +1090,9 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, (r->end - r->start) + 1);
+ base = mcspi->base;
spi_unregister_master(master);
+ iounmap(base);
kfree(dma_channels);
return 0;
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 5515eb97d7c..bab6ff061e9 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -59,7 +59,6 @@
* and irqs should show there too...
*/
#define UWIRE_BASE_PHYS 0xFFFB3000
-#define UWIRE_BASE ((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS))
/* uWire Registers: */
#define UWIRE_IO_SIZE 0x20
@@ -103,16 +102,21 @@ struct uwire_state {
};
/* REVISIT compile time constant for idx_shift? */
+/*
+ * Or, put it in a structure which is used throughout the driver;
+ * that avoids having to issue two loads for each bit of static data.
+ */
static unsigned int uwire_idx_shift;
+static void __iomem *uwire_base;
static inline void uwire_write_reg(int idx, u16 val)
{
- __raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift));
+ __raw_writew(val, uwire_base + (idx << uwire_idx_shift));
}
static inline u16 uwire_read_reg(int idx)
{
- return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift));
+ return __raw_readw(uwire_base + (idx << uwire_idx_shift));
}
static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
@@ -492,6 +496,14 @@ static int __init uwire_probe(struct platform_device *pdev)
return -ENODEV;
uwire = spi_master_get_devdata(master);
+
+ uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
+ if (!uwire_base) {
+ dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
+ spi_master_put(master);
+ return -ENOMEM;
+ }
+
dev_set_drvdata(&pdev->dev, uwire);
uwire->ck = clk_get(&pdev->dev, "armxor_ck");
@@ -520,8 +532,10 @@ static int __init uwire_probe(struct platform_device *pdev)
uwire->bitbang.txrx_bufs = uwire_txrx;
status = spi_bitbang_start(&uwire->bitbang);
- if (status < 0)
+ if (status < 0) {
uwire_off(uwire);
+ iounmap(uwire_base);
+ }
return status;
}
@@ -534,6 +548,7 @@ static int __exit uwire_remove(struct platform_device *pdev)
status = spi_bitbang_stop(&uwire->bitbang);
uwire_off(uwire);
+ iounmap(uwire_base);
return status;
}
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
index c4eaacd6e55..014becb7d53 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/orion_spi.c
@@ -364,6 +364,11 @@ static int orion_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ /* Fix ac timing if required. */
+ if (orion_spi->spi_info->enable_clock_fix)
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+ (1 << 14));
+
if (spi->bits_per_word == 0)
spi->bits_per_word = 8;
@@ -427,7 +432,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
goto msg_rejected;
}
- if (t->speed_hz < orion_spi->min_speed) {
+ if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
dev_err(&spi->dev,
"message rejected : "
"device min speed (%d Hz) exceeds "
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 34c7c987568..dae87b1a4c6 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -47,9 +47,14 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define MAX_BUSES 3
-#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+#define RX_THRESH_DFLT 8
+#define TX_THRESH_DFLT 8
+#define TIMOUT_DFLT 1000
+
+#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
+#define MAX_DMA_LEN 8191
/*
* for testing SSCR1 changes that require SSP restart, basically
@@ -144,7 +149,6 @@ struct driver_data {
size_t tx_map_len;
u8 n_bytes;
u32 dma_width;
- int cs_change;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
@@ -406,8 +410,45 @@ static void giveback(struct driver_data *drv_data)
struct spi_transfer,
transfer_list);
+ /* Delay if requested before any change in chip select */
+ if (last_transfer->delay_usecs)
+ udelay(last_transfer->delay_usecs);
+
+ /* Drop chip select UNLESS cs_change is true or we are returning
+ * a message with an error, or next message is for another chip
+ */
if (!last_transfer->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ else {
+ struct spi_message *next_msg;
+
+ /* Holding of cs was hinted, but we need to make sure
+ * the next message is for the same chip. Don't waste
+ * time with the following tests unless this was hinted.
+ *
+ * We cannot postpone this until pump_messages, because
+ * after calling msg->complete (below) the driver that
+ * sent the current message could be unloaded, which
+ * could invalidate the cs_control() callback...
+ */
+
+ /* get a pointer to the next message, if any */
+ spin_lock_irqsave(&drv_data->lock, flags);
+ if (list_empty(&drv_data->queue))
+ next_msg = NULL;
+ else
+ next_msg = list_entry(drv_data->queue.next,
+ struct spi_message, queue);
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ /* see if the next and current messages point
+ * to the same chip
+ */
+ if (next_msg && next_msg->spi != msg->spi)
+ next_msg = NULL;
+ if (!next_msg || msg->state == ERROR_STATE)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ }
msg->state = NULL;
if (msg->complete)
@@ -490,10 +531,9 @@ static void dma_transfer_complete(struct driver_data *drv_data)
msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ /* Transfer delays and chip select release are
+ * handled in pump_transfers or giveback
+ */
/* Move to next transfer */
msg->state = next_transfer(drv_data);
@@ -602,10 +642,9 @@ static void int_transfer_complete(struct driver_data *drv_data)
drv_data->cur_msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ /* Transfer delays and chip select release are
+ * handled in pump_transfers or giveback
+ */
/* Move to next transfer */
drv_data->cur_msg->state = next_transfer(drv_data);
@@ -840,23 +879,40 @@ static void pump_transfers(unsigned long data)
return;
}
- /* Delay if requested at end of transfer*/
+ /* Delay if requested at end of transfer before CS change */
if (message->state == RUNNING_STATE) {
previous = list_entry(transfer->transfer_list.prev,
struct spi_transfer,
transfer_list);
if (previous->delay_usecs)
udelay(previous->delay_usecs);
+
+ /* Drop chip select only if cs_change is requested */
+ if (previous->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
}
- /* Check transfer length */
- if (transfer->len > 8191)
- {
- dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer "
- "length greater than 8191\n");
- message->status = -EINVAL;
- giveback(drv_data);
- return;
+ /* Check for transfers that need multiple DMA segments */
+ if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
+
+ /* reject already-mapped transfers; PIO won't always work */
+ if (message->is_dma_mapped
+ || transfer->rx_dma || transfer->tx_dma) {
+ dev_err(&drv_data->pdev->dev,
+ "pump_transfers: mapped transfer length "
+ "of %u is greater than %d\n",
+ transfer->len, MAX_DMA_LEN);
+ message->status = -EINVAL;
+ giveback(drv_data);
+ return;
+ }
+
+ /* warn ... we force this to PIO mode */
+ if (printk_ratelimit())
+ dev_warn(&message->spi->dev, "pump_transfers: "
+ "DMA disabled for transfer length %ld "
+ "greater than %d\n",
+ (long)drv_data->len, MAX_DMA_LEN);
}
/* Setup the transfer state based on the type of transfer */
@@ -878,7 +934,6 @@ static void pump_transfers(unsigned long data)
drv_data->len = transfer->len & DCMD_LENGTH;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
- drv_data->cs_change = transfer->cs_change;
/* Change speed and bit per word on a per transfer */
cr0 = chip->cr0;
@@ -925,7 +980,7 @@ static void pump_transfers(unsigned long data)
&dma_thresh))
if (printk_ratelimit())
dev_warn(&message->spi->dev,
- "pump_transfer: "
+ "pump_transfers: "
"DMA burst size reduced to "
"match bits_per_word\n");
}
@@ -939,8 +994,23 @@ static void pump_transfers(unsigned long data)
message->state = RUNNING_STATE;
- /* Try to map dma buffer and do a dma transfer if successful */
- if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) {
+ /* Try to map dma buffer and do a dma transfer if successful, but
+ * only if the length is non-zero and less than MAX_DMA_LEN.
+ *
+ * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
+ * of PIO instead. Care is needed above because the transfer may
+ * have have been passed with buffers that are already dma mapped.
+ * A zero-length transfer in PIO mode will not try to write/read
+ * to/from the buffers
+ *
+ * REVISIT large transfers are exactly where we most want to be
+ * using DMA. If this happens much, split those transfers into
+ * multiple DMA segments rather than forcing PIO.
+ */
+ drv_data->dma_mapped = 0;
+ if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
+ drv_data->dma_mapped = map_dma_buffers(drv_data);
+ if (drv_data->dma_mapped) {
/* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = dma_transfer;
@@ -1105,6 +1175,8 @@ static int setup(struct spi_device *spi)
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div;
+ uint tx_thres = TX_THRESH_DFLT;
+ uint rx_thres = RX_THRESH_DFLT;
if (!spi->bits_per_word)
spi->bits_per_word = 8;
@@ -1143,8 +1215,7 @@ static int setup(struct spi_device *spi)
chip->cs_control = null_cs_control;
chip->enable_dma = 0;
- chip->timeout = 1000;
- chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
+ chip->timeout = TIMOUT_DFLT;
chip->dma_burst_size = drv_data->master_info->enable_dma ?
DCMD_BURST8 : 0;
}
@@ -1158,22 +1229,21 @@ static int setup(struct spi_device *spi)
if (chip_info) {
if (chip_info->cs_control)
chip->cs_control = chip_info->cs_control;
-
- chip->timeout = chip_info->timeout;
-
- chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
- SSCR1_RFT) |
- (SSCR1_TxTresh(chip_info->tx_threshold) &
- SSCR1_TFT);
-
- chip->enable_dma = chip_info->dma_burst_size != 0
- && drv_data->master_info->enable_dma;
+ if (chip_info->timeout)
+ chip->timeout = chip_info->timeout;
+ if (chip_info->tx_threshold)
+ tx_thres = chip_info->tx_threshold;
+ if (chip_info->rx_threshold)
+ rx_thres = chip_info->rx_threshold;
+ chip->enable_dma = drv_data->master_info->enable_dma;
chip->dma_threshold = 0;
-
if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM;
}
+ chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+ (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+
/* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the
* burst and threshold can still respond to changes in bits_per_word */
@@ -1202,17 +1272,19 @@ static int setup(struct spi_device *spi)
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (drv_data->ssp_type != PXA25x_SSP)
- dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+ dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
spi->bits_per_word,
clk_get_rate(ssp->clk)
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
- spi->mode & 0x3);
+ spi->mode & 0x3,
+ chip->enable_dma ? "DMA" : "PIO");
else
- dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+ dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
spi->bits_per_word,
- clk_get_rate(ssp->clk)
+ clk_get_rate(ssp->clk) / 2
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
- spi->mode & 0x3);
+ spi->mode & 0x3,
+ chip->enable_dma ? "DMA" : "PIO");
if (spi->bits_per_word <= 8) {
chip->n_bytes = 1;
@@ -1341,9 +1413,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct pxa2xx_spi_master *platform_info;
struct spi_master *master;
- struct driver_data *drv_data = NULL;
+ struct driver_data *drv_data;
struct ssp_device *ssp;
- int status = 0;
+ int status;
platform_info = dev->platform_data;
@@ -1356,7 +1428,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
/* Allocate master with space for drv_data and null dma buffer */
master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
if (!master) {
- dev_err(&pdev->dev, "can not alloc spi_master\n");
+ dev_err(&pdev->dev, "cannot alloc spi_master\n");
ssp_free(ssp);
return -ENOMEM;
}
@@ -1392,7 +1464,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data);
if (status < 0) {
- dev_err(&pdev->dev, "can not get IRQ\n");
+ dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
goto out_error_master_alloc;
}
@@ -1432,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
/* Load default SSP configuration */
write_SSCR0(0, drv_data->ioaddr);
- write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
+ write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+ SSCR1_TxTresh(TX_THRESH_DFLT),
+ drv_data->ioaddr);
write_SSCR0(SSCR0_SerClkDiv(2)
| SSCR0_Motorola
| SSCR0_DataSize(8),
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 75e86865234..3734dc9708e 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -660,7 +660,7 @@ int spi_write_then_read(struct spi_device *spi,
int status;
struct spi_message message;
- struct spi_transfer x[2];
+ struct spi_transfer x;
u8 *local_buf;
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
@@ -671,15 +671,9 @@ int spi_write_then_read(struct spi_device *spi,
return -EINVAL;
spi_message_init(&message);
- memset(x, 0, sizeof x);
- if (n_tx) {
- x[0].len = n_tx;
- spi_message_add_tail(&x[0], &message);
- }
- if (n_rx) {
- x[1].len = n_rx;
- spi_message_add_tail(&x[1], &message);
- }
+ memset(&x, 0, sizeof x);
+ x.len = n_tx + n_rx;
+ spi_message_add_tail(&x, &message);
/* ... unless someone else is using the pre-allocated buffer */
if (!mutex_trylock(&lock)) {
@@ -690,15 +684,15 @@ int spi_write_then_read(struct spi_device *spi,
local_buf = buf;
memcpy(local_buf, txbuf, n_tx);
- x[0].tx_buf = local_buf;
- x[1].rx_buf = local_buf + n_tx;
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf;
/* do the i/o */
status = spi_sync(spi, &message);
if (status == 0)
- memcpy(rxbuf, x[1].rx_buf, n_rx);
+ memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
- if (x[0].tx_buf == buf)
+ if (x.tx_buf == buf)
mutex_unlock(&lock);
else
kfree(local_buf);
@@ -744,5 +738,5 @@ err0:
* driver registration) _could_ be dynamically linked (modular) ... costs
* include needing to have boardinfo data structures be much more public.
*/
-subsys_initcall(spi_init);
+postcore_initcall(spi_init);
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 070c6219e2d..ac0e3e4b3c5 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -267,16 +267,13 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
cs->hw_mode |= SPMODE_LEN(bits_per_word);
if ((mpc83xx_spi->spibrg / hz) > 64) {
+ cs->hw_mode |= SPMODE_DIV16;
pm = mpc83xx_spi->spibrg / (hz * 64);
if (pm > 16) {
- cs->hw_mode |= SPMODE_DIV16;
- pm /= 16;
- if (pm > 16) {
- dev_err(&spi->dev, "Requested speed is too "
- "low: %d Hz. Will use %d Hz instead.\n",
- hz, mpc83xx_spi->spibrg / 1024);
- pm = 16;
- }
+ dev_err(&spi->dev, "Requested speed is too "
+ "low: %d Hz. Will use %d Hz instead.\n",
+ hz, mpc83xx_spi->spibrg / 1024);
+ pm = 16;
}
} else
pm = mpc83xx_spi->spibrg / (hz * 4);
@@ -315,11 +312,20 @@ static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
if (t->bits_per_word)
bits_per_word = t->bits_per_word;
len = t->len;
- if (bits_per_word > 8)
+ if (bits_per_word > 8) {
+ /* invalid length? */
+ if (len & 1)
+ return -EINVAL;
len /= 2;
- if (bits_per_word > 16)
+ }
+ if (bits_per_word > 16) {
+ /* invalid length? */
+ if (len & 1)
+ return -EINVAL;
len /= 2;
+ }
mpc83xx_spi->count = len;
+
INIT_COMPLETION(mpc83xx_spi->done);
/* enable rx ints */
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 98abc73c1a1..c252cbac00f 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -247,6 +247,9 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
writeb(0xff, hw->regs + S3C2410_SPPRE);
writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
+
+ if (hw->pdata && hw->pdata->gpio_setup)
+ hw->pdata->gpio_setup(hw->pdata, 1);
}
static int __init s3c24xx_spi_probe(struct platform_device *pdev)
@@ -412,6 +415,9 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
{
struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
+ if (hw->pdata && hw->pdata->gpio_setup)
+ hw->pdata->gpio_setup(hw->pdata, 0);
+
clk_disable(hw->clk);
return 0;
}
@@ -430,7 +436,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev)
#endif
MODULE_ALIAS("platform:s3c2410-spi");
-static struct platform_driver s3c24xx_spidrv = {
+static struct platform_driver s3c24xx_spi_driver = {
.remove = __exit_p(s3c24xx_spi_remove),
.suspend = s3c24xx_spi_suspend,
.resume = s3c24xx_spi_resume,
@@ -442,12 +448,12 @@ static struct platform_driver s3c24xx_spidrv = {
static int __init s3c24xx_spi_init(void)
{
- return platform_driver_probe(&s3c24xx_spidrv, s3c24xx_spi_probe);
+ return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
}
static void __exit s3c24xx_spi_exit(void)
{
- platform_driver_unregister(&s3c24xx_spidrv);
+ platform_driver_unregister(&s3c24xx_spi_driver);
}
module_init(s3c24xx_spi_init);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index e5e0cfed5e3..89a43755a45 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -583,10 +583,9 @@ static int spidev_probe(struct spi_device *spi)
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create_drvdata(spidev_class, &spi->dev,
- spidev->devt, spidev,
- "spidev%d.%d",
- spi->master->bus_num, spi->chip_select);
+ dev = device_create(spidev_class, &spi->dev, spidev->devt,
+ spidev, "spidev%d.%d",
+ spi->master->bus_num, spi->chip_select);
status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 87ab2443e66..0ffabf5c0b6 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -471,6 +471,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
#endif
break;
case SSB_BUSTYPE_SSB:
+ dev->dma_mask = &dev->coherent_dma_mask;
break;
}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index f883dcfffe0..d5cde051806 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -327,11 +327,9 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
s8 gain;
u16 loc[3];
- if (out->revision == 3) { /* rev 3 moved MAC */
+ if (out->revision == 3) /* rev 3 moved MAC */
loc[0] = SSB_SPROM3_IL0MAC;
- loc[1] = SSB_SPROM3_ET0MAC;
- loc[2] = SSB_SPROM3_ET1MAC;
- } else {
+ else {
loc[0] = SSB_SPROM1_IL0MAC;
loc[1] = SSB_SPROM1_ET0MAC;
loc[2] = SSB_SPROM1_ET1MAC;
@@ -340,13 +338,15 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
v = in[SPOFF(loc[0]) + i];
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
}
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(loc[1]) + i];
- *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
- }
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(loc[2]) + i];
- *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
+ if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
+ for (i = 0; i < 3; i++) {
+ v = in[SPOFF(loc[1]) + i];
+ *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+ }
+ for (i = 0; i < 3; i++) {
+ v = in[SPOFF(loc[2]) + i];
+ *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
+ }
}
SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
@@ -399,30 +399,33 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
out->antenna_gain.ghz5.a3 = gain;
}
-static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
+static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
{
int i;
u16 v;
+ u16 il0mac_offset;
- /* extract the equivalent of the r1 variables */
+ if (out->revision == 4)
+ il0mac_offset = SSB_SPROM4_IL0MAC;
+ else
+ il0mac_offset = SSB_SPROM5_IL0MAC;
+ /* extract the MAC address */
for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
+ v = in[SPOFF(il0mac_offset) + i];
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
}
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
- *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
- }
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
- *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
- }
SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
SSB_SPROM4_ETHPHY_ET1A_SHIFT);
- SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
- SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
- SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ if (out->revision == 4) {
+ SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
+ SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ } else {
+ SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
+ SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ }
SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
SSB_SPROM4_ANTAVAIL_A_SHIFT);
SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
@@ -433,12 +436,21 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
SSB_SPROM4_ITSSI_A_SHIFT);
- SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
- SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
- SSB_SPROM4_GPIOA_P1_SHIFT);
- SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
- SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
- SSB_SPROM4_GPIOB_P3_SHIFT);
+ if (out->revision == 4) {
+ SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
+ SSB_SPROM4_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
+ SSB_SPROM4_GPIOB_P3_SHIFT);
+ } else {
+ SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
+ SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
+ SSB_SPROM5_GPIOA_P1_SHIFT);
+ SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
+ SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
+ SSB_SPROM5_GPIOB_P3_SHIFT);
+ }
/* Extract the antenna gain values. */
SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
@@ -462,6 +474,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
out->revision = in[size - 1] & 0x00FF;
ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
+ memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
+ memset(out->et1mac, 0xFF, 6);
if ((bus->chip_id & 0xFF00) == 0x4400) {
/* Workaround: The BCM44XX chip has a stupid revision
* number stored in the SPROM.
@@ -471,16 +485,16 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
} else if (bus->chip_id == 0x4321) {
/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
out->revision = 4;
- sprom_extract_r4(out, in);
+ sprom_extract_r45(out, in);
} else {
if (out->revision == 0)
goto unsupported;
if (out->revision >= 1 && out->revision <= 3) {
sprom_extract_r123(out, in);
}
- if (out->revision == 4)
- sprom_extract_r4(out, in);
- if (out->revision >= 5)
+ if (out->revision == 4 || out->revision == 5)
+ sprom_extract_r45(out, in);
+ if (out->revision > 5)
goto unsupported;
}
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 24c2a46c147..fbfadbac67e 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -80,7 +80,7 @@ static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
reg.Action = CS_WRITE;
reg.Value = value;
res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
- if (unlikely(res != CS_SUCCESS))
+ if (unlikely(res != 0))
return -EBUSY;
return 0;
@@ -96,7 +96,7 @@ static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
reg.Offset = offset;
reg.Action = CS_READ;
res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
- if (unlikely(res != CS_SUCCESS))
+ if (unlikely(res != 0))
return -EBUSY;
*value = reg.Value;
@@ -638,17 +638,17 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
+ GOTO_ERROR_ON(res != 0, "MAC first tpl");
res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
+ GOTO_ERROR_ON(res != 0, "MAC first tpl data");
while (1) {
GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
break;
res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
+ GOTO_ERROR_ON(res != 0, "MAC next tpl");
res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
+ GOTO_ERROR_ON(res != 0, "MAC next tpl data");
}
GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
@@ -659,9 +659,9 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
+ GOTO_ERROR_ON(res != 0, "VEN first tpl");
res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
+ GOTO_ERROR_ON(res != 0, "VEN first tpl data");
while (1) {
GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
switch (tuple.TupleData[0]) {
@@ -733,11 +733,11 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
break;
}
res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
- if (res == CS_NO_MORE_ITEMS)
+ if (res == -ENOSPC)
break;
- GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
+ GOTO_ERROR_ON(res != 0, "VEN next tpl");
res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
- GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
+ GOTO_ERROR_ON(res != 0, "VEN next tpl data");
}
return 0;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
new file mode 100644
index 00000000000..2a79decd7df
--- /dev/null
+++ b/drivers/staging/Kconfig
@@ -0,0 +1,46 @@
+menuconfig STAGING
+ bool "Staging drivers"
+ default n
+ ---help---
+ This option allows you to select a number of drivers that are
+ not of the "normal" Linux kernel quality level. These drivers
+ are placed here in order to get a wider audience for use of
+ them. Please note that these drivers are under heavy
+ development, may or may not work, and may contain userspace
+ interfaces that most likely will be changed in the near
+ future.
+
+ Using any of these drivers will taint your kernel which might
+ affect support options from both the community, and various
+ commercial support orginizations.
+
+ If you wish to work on these drivers, to help improve them, or
+ to report problems you have with them, please see the
+ driver_name.README file in the drivers/staging/ directory to
+ see what needs to be worked on, and who to contact.
+
+ If in doubt, say N here.
+
+if STAGING
+
+source "drivers/staging/et131x/Kconfig"
+
+source "drivers/staging/slicoss/Kconfig"
+
+source "drivers/staging/sxg/Kconfig"
+
+source "drivers/staging/me4000/Kconfig"
+
+source "drivers/staging/go7007/Kconfig"
+
+source "drivers/staging/usbip/Kconfig"
+
+source "drivers/staging/winbond/Kconfig"
+
+source "drivers/staging/wlan-ng/Kconfig"
+
+source "drivers/staging/echo/Kconfig"
+
+source "drivers/staging/at76_usb/Kconfig"
+
+endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
new file mode 100644
index 00000000000..325bca4f71c
--- /dev/null
+++ b/drivers/staging/Makefile
@@ -0,0 +1,15 @@
+# Makefile for staging directory
+
+# fix for build system bug...
+obj-$(CONFIG_STAGING) += staging.o
+
+obj-$(CONFIG_ET131X) += et131x/
+obj-$(CONFIG_SLICOSS) += slicoss/
+obj-$(CONFIG_SXG) += sxg/
+obj-$(CONFIG_ME4000) += me4000/
+obj-$(CONFIG_VIDEO_GO7007) += go7007/
+obj-$(CONFIG_USB_IP_COMMON) += usbip/
+obj-$(CONFIG_W35UND) += winbond/
+obj-$(CONFIG_PRISM2_USB) += wlan-ng/
+obj-$(CONFIG_ECHO) += echo/
+obj-$(CONFIG_USB_ATMEL) += at76_usb/
diff --git a/drivers/staging/at76_usb/Kconfig b/drivers/staging/at76_usb/Kconfig
new file mode 100644
index 00000000000..8606f962162
--- /dev/null
+++ b/drivers/staging/at76_usb/Kconfig
@@ -0,0 +1,8 @@
+config USB_ATMEL
+ tristate "Atmel at76c503/at76c505/at76c505a USB cards"
+ depends on WLAN_80211 && USB
+ default N
+ select FW_LOADER
+ ---help---
+ Enable support for USB Wireless devices using Atmel at76c503,
+ at76c505 or at76c505a chips.
diff --git a/drivers/staging/at76_usb/Makefile b/drivers/staging/at76_usb/Makefile
new file mode 100644
index 00000000000..6a47e887230
--- /dev/null
+++ b/drivers/staging/at76_usb/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_ATMEL) += at76_usb.o
diff --git a/drivers/staging/at76_usb/TODO b/drivers/staging/at76_usb/TODO
new file mode 100644
index 00000000000..6911ca71a41
--- /dev/null
+++ b/drivers/staging/at76_usb/TODO
@@ -0,0 +1,2 @@
+rewrite the driver to use the proper in-kernel wireless stack
+instead of using its own.
diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c
new file mode 100644
index 00000000000..52df0c66518
--- /dev/null
+++ b/drivers/staging/at76_usb/at76_usb.c
@@ -0,0 +1,5559 @@
+/*
+ * at76c503/at76c505 USB driver
+ *
+ * Copyright (c) 2002 - 2003 Oliver Kurth
+ * Copyright (c) 2004 Joerg Albert <joerg.albert@gmx.de>
+ * Copyright (c) 2004 Nick Jones
+ * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
+ * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.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 file is part of the Berlios driver for WLAN USB devices based on the
+ * Atmel AT76C503A/505/505A.
+ *
+ * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/firmware.h>
+#include <linux/leds.h>
+#include <net/ieee80211.h>
+
+#include "at76_usb.h"
+
+/* Version information */
+#define DRIVER_NAME "at76_usb"
+#define DRIVER_VERSION "0.17"
+#define DRIVER_DESC "Atmel at76x USB Wireless LAN Driver"
+
+/* at76_debug bits */
+#define DBG_PROGRESS 0x00000001 /* authentication/accociation */
+#define DBG_BSS_TABLE 0x00000002 /* show BSS table after scans */
+#define DBG_IOCTL 0x00000004 /* ioctl calls / settings */
+#define DBG_MAC_STATE 0x00000008 /* MAC state transitions */
+#define DBG_TX_DATA 0x00000010 /* tx header */
+#define DBG_TX_DATA_CONTENT 0x00000020 /* tx content */
+#define DBG_TX_MGMT 0x00000040 /* tx management */
+#define DBG_RX_DATA 0x00000080 /* rx data header */
+#define DBG_RX_DATA_CONTENT 0x00000100 /* rx data content */
+#define DBG_RX_MGMT 0x00000200 /* rx mgmt frame headers */
+#define DBG_RX_BEACON 0x00000400 /* rx beacon */
+#define DBG_RX_CTRL 0x00000800 /* rx control */
+#define DBG_RX_MGMT_CONTENT 0x00001000 /* rx mgmt content */
+#define DBG_RX_FRAGS 0x00002000 /* rx data fragment handling */
+#define DBG_DEVSTART 0x00004000 /* fw download, device start */
+#define DBG_URB 0x00008000 /* rx urb status, ... */
+#define DBG_RX_ATMEL_HDR 0x00010000 /* Atmel-specific Rx headers */
+#define DBG_PROC_ENTRY 0x00020000 /* procedure entries/exits */
+#define DBG_PM 0x00040000 /* power management settings */
+#define DBG_BSS_MATCH 0x00080000 /* BSS match failures */
+#define DBG_PARAMS 0x00100000 /* show configured parameters */
+#define DBG_WAIT_COMPLETE 0x00200000 /* command completion */
+#define DBG_RX_FRAGS_SKB 0x00400000 /* skb header of Rx fragments */
+#define DBG_BSS_TABLE_RM 0x00800000 /* purging bss table entries */
+#define DBG_MONITOR_MODE 0x01000000 /* monitor mode */
+#define DBG_MIB 0x02000000 /* dump all MIBs on startup */
+#define DBG_MGMT_TIMER 0x04000000 /* dump mgmt_timer ops */
+#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */
+#define DBG_FW 0x10000000 /* firmware download */
+#define DBG_DFU 0x20000000 /* device firmware upgrade */
+
+#define DBG_DEFAULTS 0
+
+/* Use our own dbg macro */
+#define at76_dbg(bits, format, arg...) \
+ do { \
+ if (at76_debug & (bits)) \
+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
+ } while (0)
+
+static int at76_debug = DBG_DEFAULTS;
+
+/* Protect against concurrent firmware loading and parsing */
+static struct mutex fw_mutex;
+
+static struct fwentry firmwares[] = {
+ [0] = {""},
+ [BOARD_503_ISL3861] = {"atmel_at76c503-i3861.bin"},
+ [BOARD_503_ISL3863] = {"atmel_at76c503-i3863.bin"},
+ [BOARD_503] = {"atmel_at76c503-rfmd.bin"},
+ [BOARD_503_ACC] = {"atmel_at76c503-rfmd-acc.bin"},
+ [BOARD_505] = {"atmel_at76c505-rfmd.bin"},
+ [BOARD_505_2958] = {"atmel_at76c505-rfmd2958.bin"},
+ [BOARD_505A] = {"atmel_at76c505a-rfmd2958.bin"},
+ [BOARD_505AMX] = {"atmel_at76c505amx-rfmd.bin"},
+};
+
+#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
+
+static struct usb_device_id dev_table[] = {
+ /*
+ * at76c503-i3861
+ */
+ /* Generic AT76C503/3861 device */
+ {USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Linksys WUSB11 v2.1/v2.6 */
+ {USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Netgear MA101 rev. A */
+ {USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Tekram U300C / Allnet ALL0193 */
+ {USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* HP HN210W J7801A */
+ {USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Sitecom/Z-Com/Zyxel M4Y-750 */
+ {USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Dynalink/Askey WLL013 (intersil) */
+ {USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
+ {USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* BenQ AWL300 */
+ {USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Addtron AWU-120, Compex WLU11 */
+ {USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Intel AP310 AnyPoint II USB */
+ {USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Dynalink L11U */
+ {USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* Arescom WL-210, FCC id 07J-GL2411USB */
+ {USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* I-O DATA WN-B11/USB */
+ {USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /* BT Voyager 1010 */
+ {USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ /*
+ * at76c503-i3863
+ */
+ /* Generic AT76C503/3863 device */
+ {USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863)},
+ /* Samsung SWL-2100U */
+ {USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863)},
+ /*
+ * at76c503-rfmd
+ */
+ /* Generic AT76C503/RFMD device */
+ {USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503)},
+ /* Dynalink/Askey WLL013 (rfmd) */
+ {USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503)},
+ /* Linksys WUSB11 v2.6 */
+ {USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503)},
+ /* Network Everywhere NWU11B */
+ {USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503)},
+ /* Netgear MA101 rev. B */
+ {USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503)},
+ /* D-Link DWL-120 rev. E */
+ {USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503)},
+ /* Actiontec 802UAT1, HWU01150-01UK */
+ {USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503)},
+ /* AirVast W-Buddie WN210 */
+ {USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503)},
+ /* Dick Smith Electronics XH1153 802.11b USB adapter */
+ {USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503)},
+ /* CNet CNUSB611 */
+ {USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503)},
+ /* FiberLine FL-WL200U */
+ {USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503)},
+ /* BenQ AWL400 USB stick */
+ {USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503)},
+ /* 3Com 3CRSHEW696 */
+ {USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503)},
+ /* Siemens Santis ADSL WLAN USB adapter WLL 013 */
+ {USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503)},
+ /* Belkin F5D6050, version 2 */
+ {USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503)},
+ /* iBlitzz, BWU613 (not *B or *SB) */
+ {USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503)},
+ /* Gigabyte GN-WLBM101 */
+ {USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503)},
+ /* Planex GW-US11S */
+ {USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503)},
+ /* Internal WLAN adapter in h5[4,5]xx series iPAQs */
+ {USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503)},
+ /* Corega Wireless LAN USB-11 mini */
+ {USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503)},
+ /* Corega Wireless LAN USB-11 mini2 */
+ {USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503)},
+ /* Uniden PCW100 */
+ {USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503)},
+ /*
+ * at76c503-rfmd-acc
+ */
+ /* SMC2664W */
+ {USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC)},
+ /* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */
+ {USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC)},
+ /*
+ * at76c505-rfmd
+ */
+ /* Generic AT76C505/RFMD */
+ {USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505)},
+ /*
+ * at76c505-rfmd2958
+ */
+ /* Generic AT76C505/RFMD, OvisLink WL-1130USB */
+ {USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* Fiberline FL-WL240U */
+ {USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* CNet CNUSB-611G */
+ {USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* Linksys WUSB11 v2.8 */
+ {USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
+ {USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* Corega WLAN USB Stick 11 */
+ {USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
+ /* Microstar MSI Box MS6978 */
+ {USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958)},
+ /*
+ * at76c505a-rfmd2958
+ */
+ /* Generic AT76C505A device */
+ {USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A)},
+ /* Generic AT76C505AS device */
+ {USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A)},
+ /* Siemens Gigaset USB WLAN Adapter 11 */
+ {USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A)},
+ /*
+ * at76c505amx-rfmd
+ */
+ /* Generic AT76C505AMX device */
+ {USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, dev_table);
+
+/* Supported rates of this hardware, bit 7 marks basic rates */
+static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 };
+
+/* Frequency of each channel in MHz */
+static const long channel_frequency[] = {
+ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+
+#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
+
+static const char *const preambles[] = { "long", "short", "auto" };
+
+static const char *const mac_states[] = {
+ [MAC_INIT] = "INIT",
+ [MAC_SCANNING] = "SCANNING",
+ [MAC_AUTH] = "AUTH",
+ [MAC_ASSOC] = "ASSOC",
+ [MAC_JOINING] = "JOINING",
+ [MAC_CONNECTED] = "CONNECTED",
+ [MAC_OWN_IBSS] = "OWN_IBSS"
+};
+
+/* Firmware download */
+/* DFU states */
+#define STATE_IDLE 0x00
+#define STATE_DETACH 0x01
+#define STATE_DFU_IDLE 0x02
+#define STATE_DFU_DOWNLOAD_SYNC 0x03
+#define STATE_DFU_DOWNLOAD_BUSY 0x04
+#define STATE_DFU_DOWNLOAD_IDLE 0x05
+#define STATE_DFU_MANIFEST_SYNC 0x06
+#define STATE_DFU_MANIFEST 0x07
+#define STATE_DFU_MANIFEST_WAIT_RESET 0x08
+#define STATE_DFU_UPLOAD_IDLE 0x09
+#define STATE_DFU_ERROR 0x0a
+
+/* DFU commands */
+#define DFU_DETACH 0
+#define DFU_DNLOAD 1
+#define DFU_UPLOAD 2
+#define DFU_GETSTATUS 3
+#define DFU_CLRSTATUS 4
+#define DFU_GETSTATE 5
+#define DFU_ABORT 6
+
+#define FW_BLOCK_SIZE 1024
+
+struct dfu_status {
+ unsigned char status;
+ unsigned char poll_timeout[3];
+ unsigned char state;
+ unsigned char string;
+} __attribute__((packed));
+
+static inline int at76_is_intersil(enum board_type board)
+{
+ return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863);
+}
+
+static inline int at76_is_503rfmd(enum board_type board)
+{
+ return (board == BOARD_503 || board == BOARD_503_ACC);
+}
+
+static inline int at76_is_505a(enum board_type board)
+{
+ return (board == BOARD_505A || board == BOARD_505AMX);
+}
+
+/* Load a block of the first (internal) part of the firmware */
+static int at76_load_int_fw_block(struct usb_device *udev, int blockno,
+ void *block, int size)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), DFU_DNLOAD,
+ USB_TYPE_CLASS | USB_DIR_OUT |
+ USB_RECIP_INTERFACE, blockno, 0, block, size,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static int at76_dfu_get_status(struct usb_device *udev,
+ struct dfu_status *status)
+{
+ int ret;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATUS,
+ USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
+ 0, 0, status, sizeof(struct dfu_status),
+ USB_CTRL_GET_TIMEOUT);
+ return ret;
+}
+
+static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state)
+{
+ int ret;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATE,
+ USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
+ 0, 0, state, 1, USB_CTRL_GET_TIMEOUT);
+ return ret;
+}
+
+/* Convert timeout from the DFU status to jiffies */
+static inline unsigned long at76_get_timeout(struct dfu_status *s)
+{
+ return msecs_to_jiffies((s->poll_timeout[2] << 16)
+ | (s->poll_timeout[1] << 8)
+ | (s->poll_timeout[0]));
+}
+
+/* Load internal firmware from the buffer. If manifest_sync_timeout > 0, use
+ * its value in jiffies in the MANIFEST_SYNC state. */
+static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
+ int manifest_sync_timeout)
+{
+ u8 *block;
+ struct dfu_status dfu_stat_buf;
+ int ret = 0;
+ int need_dfu_state = 1;
+ int is_done = 0;
+ u8 dfu_state = 0;
+ u32 dfu_timeout = 0;
+ int bsize = 0;
+ int blockno = 0;
+
+ at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size,
+ manifest_sync_timeout);
+
+ if (!size) {
+ dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
+ return -EINVAL;
+ }
+
+ block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
+ if (!block)
+ return -ENOMEM;
+
+ do {
+ if (need_dfu_state) {
+ ret = at76_dfu_get_state(udev, &dfu_state);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "cannot get DFU state: %d\n", ret);
+ goto exit;
+ }
+ need_dfu_state = 0;
+ }
+
+ switch (dfu_state) {
+ case STATE_DFU_DOWNLOAD_SYNC:
+ at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC");
+ ret = at76_dfu_get_status(udev, &dfu_stat_buf);
+ if (ret >= 0) {
+ dfu_state = dfu_stat_buf.state;
+ dfu_timeout = at76_get_timeout(&dfu_stat_buf);
+ need_dfu_state = 0;
+ } else
+ dev_printk(KERN_ERR, &udev->dev,
+ "at76_dfu_get_status returned %d\n",
+ ret);
+ break;
+
+ case STATE_DFU_DOWNLOAD_BUSY:
+ at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_BUSY");
+ need_dfu_state = 1;
+
+ at76_dbg(DBG_DFU, "DFU: Resetting device");
+ schedule_timeout_interruptible(dfu_timeout);
+ break;
+
+ case STATE_DFU_DOWNLOAD_IDLE:
+ at76_dbg(DBG_DFU, "DOWNLOAD...");
+ /* fall through */
+ case STATE_DFU_IDLE:
+ at76_dbg(DBG_DFU, "DFU IDLE");
+
+ bsize = min_t(int, size, FW_BLOCK_SIZE);
+ memcpy(block, buf, bsize);
+ at76_dbg(DBG_DFU, "int fw, size left = %5d, "
+ "bsize = %4d, blockno = %2d", size, bsize,
+ blockno);
+ ret =
+ at76_load_int_fw_block(udev, blockno, block, bsize);
+ buf += bsize;
+ size -= bsize;
+ blockno++;
+
+ if (ret != bsize)
+ dev_printk(KERN_ERR, &udev->dev,
+ "at76_load_int_fw_block "
+ "returned %d\n", ret);
+ need_dfu_state = 1;
+ break;
+
+ case STATE_DFU_MANIFEST_SYNC:
+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC");
+
+ ret = at76_dfu_get_status(udev, &dfu_stat_buf);
+ if (ret < 0)
+ break;
+
+ dfu_state = dfu_stat_buf.state;
+ dfu_timeout = at76_get_timeout(&dfu_stat_buf);
+ need_dfu_state = 0;
+
+ /* override the timeout from the status response,
+ needed for AT76C505A */
+ if (manifest_sync_timeout > 0)
+ dfu_timeout = manifest_sync_timeout;
+
+ at76_dbg(DBG_DFU, "DFU: Waiting for manifest phase");
+ schedule_timeout_interruptible(dfu_timeout);
+ break;
+
+ case STATE_DFU_MANIFEST:
+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST");
+ is_done = 1;
+ break;
+
+ case STATE_DFU_MANIFEST_WAIT_RESET:
+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_WAIT_RESET");
+ is_done = 1;
+ break;
+
+ case STATE_DFU_UPLOAD_IDLE:
+ at76_dbg(DBG_DFU, "STATE_DFU_UPLOAD_IDLE");
+ break;
+
+ case STATE_DFU_ERROR:
+ at76_dbg(DBG_DFU, "STATE_DFU_ERROR");
+ ret = -EPIPE;
+ break;
+
+ default:
+ at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state);
+ ret = -EINVAL;
+ break;
+ }
+ } while (!is_done && (ret >= 0));
+
+exit:
+ kfree(block);
+ if (ret >= 0)
+ ret = 0;
+
+ return ret;
+}
+
+/* Report that the scan results are ready */
+static inline void at76_iwevent_scan_complete(struct net_device *netdev)
+{
+ union iwreq_data wrqu;
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(netdev, SIOCGIWSCAN, &wrqu, NULL);
+ at76_dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", netdev->name);
+}
+
+static inline void at76_iwevent_bss_connect(struct net_device *netdev,
+ u8 *bssid)
+{
+ union iwreq_data wrqu;
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
+ at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
+ __func__);
+}
+
+static inline void at76_iwevent_bss_disconnect(struct net_device *netdev)
+{
+ union iwreq_data wrqu;
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
+ at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
+ __func__);
+}
+
+#define HEX2STR_BUFFERS 4
+#define HEX2STR_MAX_LEN 64
+#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10)
+
+/* Convert binary data into hex string */
+static char *hex2str(void *buf, int len)
+{
+ static atomic_t a = ATOMIC_INIT(0);
+ static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
+ char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)];
+ char *obuf = ret;
+ u8 *ibuf = buf;
+
+ if (len > HEX2STR_MAX_LEN)
+ len = HEX2STR_MAX_LEN;
+
+ if (len <= 0) {
+ ret[0] = '\0';
+ return ret;
+ }
+
+ while (len--) {
+ *obuf++ = BIN2HEX(*ibuf >> 4);
+ *obuf++ = BIN2HEX(*ibuf & 0xf);
+ *obuf++ = '-';
+ ibuf++;
+ }
+ *(--obuf) = '\0';
+
+ return ret;
+}
+
+#define MAC2STR_BUFFERS 4
+
+static inline char *mac2str(u8 *mac)
+{
+ static atomic_t a = ATOMIC_INIT(0);
+ static char bufs[MAC2STR_BUFFERS][6 * 3];
+ char *str;
+
+ str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)];
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ return str;
+}
+
+/* LED trigger */
+static int tx_activity;
+static void at76_ledtrig_tx_timerfunc(unsigned long data);
+static DEFINE_TIMER(ledtrig_tx_timer, at76_ledtrig_tx_timerfunc, 0, 0);
+DEFINE_LED_TRIGGER(ledtrig_tx);
+
+static void at76_ledtrig_tx_timerfunc(unsigned long data)
+{
+ static int tx_lastactivity;
+
+ if (tx_lastactivity != tx_activity) {
+ tx_lastactivity = tx_activity;
+ led_trigger_event(ledtrig_tx, LED_FULL);
+ mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
+ } else
+ led_trigger_event(ledtrig_tx, LED_OFF);
+}
+
+static void at76_ledtrig_tx_activity(void)
+{
+ tx_activity++;
+ if (!timer_pending(&ledtrig_tx_timer))
+ mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
+}
+
+/* Check if the given ssid is hidden */
+static inline int at76_is_hidden_ssid(u8 *ssid, int length)
+{
+ static const u8 zeros[32];
+
+ if (length == 0)
+ return 1;
+
+ if (length == 1 && ssid[0] == ' ')
+ return 1;
+
+ return (memcmp(ssid, zeros, length) == 0);
+}
+
+static inline void at76_free_bss_list(struct at76_priv *priv)
+{
+ struct list_head *next, *ptr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+
+ priv->curr_bss = NULL;
+
+ list_for_each_safe(ptr, next, &priv->bss_list) {
+ list_del(ptr);
+ kfree(list_entry(ptr, struct bss_info, list));
+ }
+
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+}
+
+static int at76_remap(struct usb_device *udev)
+{
+ int ret;
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0a,
+ USB_TYPE_VENDOR | USB_DIR_OUT |
+ USB_RECIP_INTERFACE, 0, 0, NULL, 0,
+ USB_CTRL_GET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int at76_get_op_mode(struct usb_device *udev)
+{
+ int ret;
+ u8 op_mode;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE, 0x01, 0, &op_mode, 1,
+ USB_CTRL_GET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ else if (ret < 1)
+ return -EIO;
+ else
+ return op_mode;
+}
+
+/* Load a block of the second ("external") part of the firmware */
+static inline int at76_load_ext_fw_block(struct usb_device *udev, int blockno,
+ void *block, int size)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+ 0x0802, blockno, block, size,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static inline int at76_get_hw_cfg(struct usb_device *udev,
+ union at76_hwcfg *buf, int buf_size)
+{
+ return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE, 0x0a02, 0,
+ buf, buf_size, USB_CTRL_GET_TIMEOUT);
+}
+
+/* Intersil boards use a different "value" for GetHWConfig requests */
+static inline int at76_get_hw_cfg_intersil(struct usb_device *udev,
+ union at76_hwcfg *buf, int buf_size)
+{
+ return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE, 0x0902, 0,
+ buf, buf_size, USB_CTRL_GET_TIMEOUT);
+}
+
+/* Get the hardware configuration for the adapter and put it to the appropriate
+ * fields of 'priv' (the GetHWConfig request and interpretation of the result
+ * depends on the board type) */
+static int at76_get_hw_config(struct at76_priv *priv)
+{
+ int ret;
+ union at76_hwcfg *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL);
+
+ if (!hwcfg)
+ return -ENOMEM;
+
+ if (at76_is_intersil(priv->board_type)) {
+ ret = at76_get_hw_cfg_intersil(priv->udev, hwcfg,
+ sizeof(hwcfg->i));
+ if (ret < 0)
+ goto exit;
+ memcpy(priv->mac_addr, hwcfg->i.mac_addr, ETH_ALEN);
+ priv->regulatory_domain = hwcfg->i.regulatory_domain;
+ } else if (at76_is_503rfmd(priv->board_type)) {
+ ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r3));
+ if (ret < 0)
+ goto exit;
+ memcpy(priv->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN);
+ priv->regulatory_domain = hwcfg->r3.regulatory_domain;
+ } else {
+ ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r5));
+ if (ret < 0)
+ goto exit;
+ memcpy(priv->mac_addr, hwcfg->r5.mac_addr, ETH_ALEN);
+ priv->regulatory_domain = hwcfg->r5.regulatory_domain;
+ }
+
+exit:
+ kfree(hwcfg);
+ if (ret < 0)
+ printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static struct reg_domain const *at76_get_reg_domain(u16 code)
+{
+ int i;
+ static struct reg_domain const fd_tab[] = {
+ {0x10, "FCC (USA)", 0x7ff}, /* ch 1-11 */
+ {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */
+ {0x30, "ETSI (most of Europe)", 0x1fff}, /* ch 1-13 */
+ {0x31, "Spain", 0x600}, /* ch 10-11 */
+ {0x32, "France", 0x1e00}, /* ch 10-13 */
+ {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */
+ {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */
+ {0x50, "Israel", 0x3fc}, /* ch 3-9 */
+ {0x00, "<unknown>", 0xffffffff} /* ch 1-32 */
+ };
+
+ /* Last entry is fallback for unknown domain code */
+ for (i = 0; i < ARRAY_SIZE(fd_tab) - 1; i++)
+ if (code == fd_tab[i].code)
+ break;
+
+ return &fd_tab[i];
+}
+
+static inline int at76_get_mib(struct usb_device *udev, u16 mib, void *buf,
+ int buf_size)
+{
+ int ret;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE, mib << 8, 0, buf, buf_size,
+ USB_CTRL_GET_TIMEOUT);
+ if (ret >= 0 && ret != buf_size)
+ return -EIO;
+ return ret;
+}
+
+/* Return positive number for status, negative for an error */
+static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd)
+{
+ u8 stat_buf[40];
+ int ret;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x22,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE, cmd, 0, stat_buf,
+ sizeof(stat_buf), USB_CTRL_GET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ return stat_buf[5];
+}
+
+static int at76_set_card_command(struct usb_device *udev, int cmd, void *buf,
+ int buf_size)
+{
+ int ret;
+ struct at76_command *cmd_buf = kmalloc(sizeof(struct at76_command) +
+ buf_size, GFP_KERNEL);
+
+ if (!cmd_buf)
+ return -ENOMEM;
+
+ cmd_buf->cmd = cmd;
+ cmd_buf->reserved = 0;
+ cmd_buf->size = cpu_to_le16(buf_size);
+ memcpy(cmd_buf->data, buf, buf_size);
+
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+ 0, 0, cmd_buf,
+ sizeof(struct at76_command) + buf_size,
+ USB_CTRL_GET_TIMEOUT);
+ kfree(cmd_buf);
+ return ret;
+}
+
+#define MAKE_CMD_STATUS_CASE(c) case (c): return #c
+static const char *at76_get_cmd_status_string(u8 cmd_status)
+{
+ switch (cmd_status) {
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_IDLE);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_COMPLETE);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_UNKNOWN);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_INVALID_PARAMETER);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_FUNCTION_NOT_SUPPORTED);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_TIME_OUT);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_IN_PROGRESS);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_HOST_FAILURE);
+ MAKE_CMD_STATUS_CASE(CMD_STATUS_SCAN_FAILED);
+ }
+
+ return "UNKNOWN";
+}
+
+/* Wait until the command is completed */
+static int at76_wait_completion(struct at76_priv *priv, int cmd)
+{
+ int status = 0;
+ unsigned long timeout = jiffies + CMD_COMPLETION_TIMEOUT;
+
+ do {
+ status = at76_get_cmd_status(priv->udev, cmd);
+ if (status < 0) {
+ printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
+ priv->netdev->name, status);
+ break;
+ }
+
+ at76_dbg(DBG_WAIT_COMPLETE,
+ "%s: Waiting on cmd %d, status = %d (%s)",
+ priv->netdev->name, cmd, status,
+ at76_get_cmd_status_string(status));
+
+ if (status != CMD_STATUS_IN_PROGRESS
+ && status != CMD_STATUS_IDLE)
+ break;
+
+ schedule_timeout_interruptible(HZ / 10); /* 100 ms */
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR
+ "%s: completion timeout for command %d\n",
+ priv->netdev->name, cmd);
+ status = -ETIMEDOUT;
+ break;
+ }
+ } while (1);
+
+ return status;
+}
+
+static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf)
+{
+ int ret;
+
+ ret = at76_set_card_command(priv->udev, CMD_SET_MIB, buf,
+ offsetof(struct set_mib_buffer,
+ data) + buf->size);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_wait_completion(priv, CMD_SET_MIB);
+ if (ret != CMD_STATUS_COMPLETE) {
+ printk(KERN_INFO
+ "%s: set_mib: at76_wait_completion failed "
+ "with %d\n", priv->netdev->name, ret);
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+/* Return < 0 on error, == 0 if no command sent, == 1 if cmd sent */
+static int at76_set_radio(struct at76_priv *priv, int enable)
+{
+ int ret;
+ int cmd;
+
+ if (priv->radio_on == enable)
+ return 0;
+
+ cmd = enable ? CMD_RADIO_ON : CMD_RADIO_OFF;
+
+ ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
+ if (ret < 0)
+ printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
+ priv->netdev->name, cmd, ret);
+ else
+ ret = 1;
+
+ priv->radio_on = enable;
+ return ret;
+}
+
+/* Set current power save mode (AT76_PM_OFF/AT76_PM_ON/AT76_PM_SMART) */
+static int at76_set_pm_mode(struct at76_priv *priv)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC_MGMT;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, power_mgmt_mode);
+ priv->mib_buf.data.byte = priv->pm_mode;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+/* Set the association id for power save mode */
+static int at76_set_associd(struct at76_priv *priv, u16 id)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC_MGMT;
+ priv->mib_buf.size = 2;
+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, station_id);
+ priv->mib_buf.data.word = cpu_to_le16(id);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (associd) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+/* Set the listen interval for power save mode */
+static int at76_set_listen_interval(struct at76_priv *priv, u16 interval)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC;
+ priv->mib_buf.size = 2;
+ priv->mib_buf.index = offsetof(struct mib_mac, listen_interval);
+ priv->mib_buf.data.word = cpu_to_le16(interval);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR
+ "%s: set_mib (listen_interval) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static int at76_set_preamble(struct at76_priv *priv, u8 type)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_LOCAL;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_local, preamble_type);
+ priv->mib_buf.data.byte = type;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static int at76_set_frag(struct at76_priv *priv, u16 size)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC;
+ priv->mib_buf.size = 2;
+ priv->mib_buf.index = offsetof(struct mib_mac, frag_threshold);
+ priv->mib_buf.data.word = cpu_to_le16(size);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static int at76_set_rts(struct at76_priv *priv, u16 size)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC;
+ priv->mib_buf.size = 2;
+ priv->mib_buf.index = offsetof(struct mib_mac, rts_threshold);
+ priv->mib_buf.data.word = cpu_to_le16(size);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_LOCAL;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_local, txautorate_fallback);
+ priv->mib_buf.data.byte = onoff;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static int at76_add_mac_address(struct at76_priv *priv, void *addr)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC_ADDR;
+ priv->mib_buf.size = ETH_ALEN;
+ priv->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr);
+ memcpy(priv->mib_buf.data.addr, addr, ETH_ALEN);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (MAC_ADDR, mac_addr) failed: %d\n",
+ priv->netdev->name, ret);
+
+ return ret;
+}
+
+static void at76_dump_mib_mac_addr(struct at76_priv *priv)
+{
+ int i;
+ int ret;
+ struct mib_mac_addr *m = kmalloc(sizeof(struct mib_mac_addr),
+ GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m,
+ sizeof(struct mib_mac_addr));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
+ priv->netdev->name,
+ mac2str(m->mac_addr), m->res[0], m->res[1]);
+ for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
+ at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
+ "status %d", priv->netdev->name, i,
+ mac2str(m->group_addr[i]), m->group_addr_status[i]);
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_mac_wep(struct at76_priv *priv)
+{
+ int i;
+ int ret;
+ int key_len;
+ struct mib_mac_wep *m = kmalloc(sizeof(struct mib_mac_wep), GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m,
+ sizeof(struct mib_mac_wep));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u "
+ "key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u "
+ "encr_level %u key %d", priv->netdev->name,
+ m->privacy_invoked, m->wep_default_key_id,
+ m->wep_key_mapping_len, m->exclude_unencrypted,
+ le32_to_cpu(m->wep_icv_error_count),
+ le32_to_cpu(m->wep_excluded_count), m->encryption_level,
+ m->wep_default_key_id);
+
+ key_len = (m->encryption_level == 1) ?
+ WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
+
+ for (i = 0; i < WEP_KEYS; i++)
+ at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s",
+ priv->netdev->name, i,
+ hex2str(m->wep_default_keyvalue[i], key_len));
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
+{
+ int ret;
+ struct mib_mac_mgmt *m = kmalloc(sizeof(struct mib_mac_mgmt),
+ GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m,
+ sizeof(struct mib_mac_mgmt));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
+ "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
+ "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
+ "current_bssid %s current_essid %s current_bss_type %d "
+ "pm_mode %d ibss_change %d res %d "
+ "multi_domain_capability_implemented %d "
+ "international_roaming %d country_string %.3s",
+ priv->netdev->name, le16_to_cpu(m->beacon_period),
+ le16_to_cpu(m->CFP_max_duration),
+ le16_to_cpu(m->medium_occupancy_limit),
+ le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
+ m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
+ m->CFP_period, mac2str(m->current_bssid),
+ hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
+ m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
+ m->res, m->multi_domain_capability_implemented,
+ m->multi_domain_capability_enabled, m->country_string);
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_mac(struct at76_priv *priv)
+{
+ int ret;
+ struct mib_mac *m = kmalloc(sizeof(struct mib_mac), GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB MAC: max_tx_msdu_lifetime %d "
+ "max_rx_lifetime %d frag_threshold %d rts_threshold %d "
+ "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
+ "scan_type %d scan_channel %d probe_delay %u "
+ "min_channel_time %d max_channel_time %d listen_int %d "
+ "desired_ssid %s desired_bssid %s desired_bsstype %d",
+ priv->netdev->name, le32_to_cpu(m->max_tx_msdu_lifetime),
+ le32_to_cpu(m->max_rx_lifetime),
+ le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold),
+ le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax),
+ m->short_retry_time, m->long_retry_time, m->scan_type,
+ m->scan_channel, le16_to_cpu(m->probe_delay),
+ le16_to_cpu(m->min_channel_time),
+ le16_to_cpu(m->max_channel_time),
+ le16_to_cpu(m->listen_interval),
+ hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
+ mac2str(m->desired_bssid), m->desired_bsstype);
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_phy(struct at76_priv *priv)
+{
+ int ret;
+ struct mib_phy *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB PHY: ed_threshold %d slot_time %d "
+ "sifs_time %d preamble_length %d plcp_header_length %d "
+ "mpdu_max_length %d cca_mode_supported %d operation_rate_set "
+ "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d "
+ "phy_type %d current_reg_domain %d",
+ priv->netdev->name, le32_to_cpu(m->ed_threshold),
+ le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time),
+ le16_to_cpu(m->preamble_length),
+ le16_to_cpu(m->plcp_header_length),
+ le16_to_cpu(m->mpdu_max_length),
+ le16_to_cpu(m->cca_mode_supported), m->operation_rate_set[0],
+ m->operation_rate_set[1], m->operation_rate_set[2],
+ m->operation_rate_set[3], m->channel_id, m->current_cca_mode,
+ m->phy_type, m->current_reg_domain);
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_local(struct at76_priv *priv)
+{
+ int ret;
+ struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d "
+ "txautorate_fallback %d ssid_size %d promiscuous_mode %d "
+ "preamble_type %d", priv->netdev->name, m->beacon_enable,
+ m->txautorate_fallback, m->ssid_size, m->promiscuous_mode,
+ m->preamble_type);
+exit:
+ kfree(m);
+}
+
+static void at76_dump_mib_mdomain(struct at76_priv *priv)
+{
+ int ret;
+ struct mib_mdomain *m = kmalloc(sizeof(struct mib_mdomain), GFP_KERNEL);
+
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m,
+ sizeof(struct mib_mdomain));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s",
+ priv->netdev->name,
+ hex2str(m->channel_list, sizeof(m->channel_list)));
+
+ at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s",
+ priv->netdev->name,
+ hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
+exit:
+ kfree(m);
+}
+
+static int at76_get_current_bssid(struct at76_priv *priv)
+{
+ int ret = 0;
+ struct mib_mac_mgmt *mac_mgmt =
+ kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL);
+
+ if (!mac_mgmt) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, mac_mgmt,
+ sizeof(struct mib_mac_mgmt));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
+ priv->netdev->name, ret);
+ goto error;
+ }
+ memcpy(priv->bssid, mac_mgmt->current_bssid, ETH_ALEN);
+ printk(KERN_INFO "%s: using BSSID %s\n", priv->netdev->name,
+ mac2str(priv->bssid));
+error:
+ kfree(mac_mgmt);
+exit:
+ return ret;
+}
+
+static int at76_get_current_channel(struct at76_priv *priv)
+{
+ int ret = 0;
+ struct mib_phy *phy = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
+
+ if (!phy) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+ ret = at76_get_mib(priv->udev, MIB_PHY, phy, sizeof(struct mib_phy));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib(MIB_PHY) failed: %d\n",
+ priv->netdev->name, ret);
+ goto error;
+ }
+ priv->channel = phy->channel_id;
+error:
+ kfree(phy);
+exit:
+ return ret;
+}
+
+/**
+ * at76_start_scan - start a scan
+ *
+ * @use_essid - use the configured ESSID in non passive mode
+ */
+static int at76_start_scan(struct at76_priv *priv, int use_essid)
+{
+ struct at76_req_scan scan;
+
+ memset(&scan, 0, sizeof(struct at76_req_scan));
+ memset(scan.bssid, 0xff, ETH_ALEN);
+
+ if (use_essid) {
+ memcpy(scan.essid, priv->essid, IW_ESSID_MAX_SIZE);
+ scan.essid_size = priv->essid_size;
+ } else
+ scan.essid_size = 0;
+
+ /* jal: why should we start at a certain channel? we do scan the whole
+ range allowed by reg domain. */
+ scan.channel = priv->channel;
+
+ /* atmelwlandriver differs between scan type 0 and 1 (active/passive)
+ For ad-hoc mode, it uses type 0 only. */
+ scan.scan_type = priv->scan_mode;
+
+ /* INFO: For probe_delay, not multiplying by 1024 as this will be
+ slightly less than min_channel_time
+ (per spec: probe delay < min. channel time) */
+ scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
+ scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
+ scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000);
+ scan.international_scan = 0;
+
+ /* other values are set to 0 for type 0 */
+
+ at76_dbg(DBG_PROGRESS, "%s: start_scan (use_essid = %d, intl = %d, "
+ "channel = %d, probe_delay = %d, scan_min_time = %d, "
+ "scan_max_time = %d)",
+ priv->netdev->name, use_essid,
+ scan.international_scan, scan.channel,
+ le16_to_cpu(scan.probe_delay),
+ le16_to_cpu(scan.min_channel_time),
+ le16_to_cpu(scan.max_channel_time));
+
+ return at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
+}
+
+/* Enable monitor mode */
+static int at76_start_monitor(struct at76_priv *priv)
+{
+ struct at76_req_scan scan;
+ int ret;
+
+ memset(&scan, 0, sizeof(struct at76_req_scan));
+ memset(scan.bssid, 0xff, ETH_ALEN);
+
+ scan.channel = priv->channel;
+ scan.scan_type = SCAN_TYPE_PASSIVE;
+ scan.international_scan = 0;
+
+ ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
+ if (ret >= 0)
+ ret = at76_get_cmd_status(priv->udev, CMD_SCAN);
+
+ return ret;
+}
+
+static int at76_start_ibss(struct at76_priv *priv)
+{
+ struct at76_req_ibss bss;
+ int ret;
+
+ WARN_ON(priv->mac_state != MAC_OWN_IBSS);
+ if (priv->mac_state != MAC_OWN_IBSS)
+ return -EBUSY;
+
+ memset(&bss, 0, sizeof(struct at76_req_ibss));
+ memset(bss.bssid, 0xff, ETH_ALEN);
+ memcpy(bss.essid, priv->essid, IW_ESSID_MAX_SIZE);
+ bss.essid_size = priv->essid_size;
+ bss.bss_type = ADHOC_MODE;
+ bss.channel = priv->channel;
+
+ ret = at76_set_card_command(priv->udev, CMD_START_IBSS, &bss,
+ sizeof(struct at76_req_ibss));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: start_ibss failed: %d\n",
+ priv->netdev->name, ret);
+ return ret;
+ }
+
+ ret = at76_wait_completion(priv, CMD_START_IBSS);
+ if (ret != CMD_STATUS_COMPLETE) {
+ printk(KERN_ERR "%s: start_ibss failed to complete, %d\n",
+ priv->netdev->name, ret);
+ return ret;
+ }
+
+ ret = at76_get_current_bssid(priv);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_get_current_channel(priv);
+ if (ret < 0)
+ return ret;
+
+ /* not sure what this is good for ??? */
+ priv->mib_buf.type = MIB_MAC_MGMT;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
+ priv->mib_buf.data.byte = 0;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
+ priv->netdev->name, ret);
+ return ret;
+ }
+
+ netif_carrier_on(priv->netdev);
+ netif_start_queue(priv->netdev);
+ return 0;
+}
+
+/* Request card to join BSS in managed or ad-hoc mode */
+static int at76_join_bss(struct at76_priv *priv, struct bss_info *ptr)
+{
+ struct at76_req_join join;
+
+ BUG_ON(!ptr);
+
+ memset(&join, 0, sizeof(struct at76_req_join));
+ memcpy(join.bssid, ptr->bssid, ETH_ALEN);
+ memcpy(join.essid, ptr->ssid, ptr->ssid_len);
+ join.essid_size = ptr->ssid_len;
+ join.bss_type = (priv->iw_mode == IW_MODE_ADHOC ? 1 : 2);
+ join.channel = ptr->channel;
+ join.timeout = cpu_to_le16(2000);
+
+ at76_dbg(DBG_PROGRESS,
+ "%s join addr %s ssid %s type %d ch %d timeout %d",
+ priv->netdev->name, mac2str(join.bssid), join.essid,
+ join.bss_type, join.channel, le16_to_cpu(join.timeout));
+ return at76_set_card_command(priv->udev, CMD_JOIN, &join,
+ sizeof(struct at76_req_join));
+}
+
+/* Calculate padding from txbuf->wlength (which excludes the USB TX header),
+ likely to compensate a flaw in the AT76C503A USB part ... */
+static inline int at76_calc_padding(int wlen)
+{
+ /* add the USB TX header */
+ wlen += AT76_TX_HDRLEN;
+
+ wlen = wlen % 64;
+
+ if (wlen < 50)
+ return 50 - wlen;
+
+ if (wlen >= 61)
+ return 64 + 50 - wlen;
+
+ return 0;
+}
+
+/* We are doing a lot of things here in an interrupt. Need
+ a bh handler (Watching TV with a TV card is probably
+ a good test: if you see flickers, we are doing too much.
+ Currently I do see flickers... even with our tasklet :-( )
+ Maybe because the bttv driver and usb-uhci use the same interrupt
+*/
+/* Or maybe because our BH handler is preempting bttv's BH handler.. BHs don't
+ * solve everything.. (alex) */
+static void at76_rx_callback(struct urb *urb)
+{
+ struct at76_priv *priv = urb->context;
+
+ priv->rx_tasklet.data = (unsigned long)urb;
+ tasklet_schedule(&priv->rx_tasklet);
+ return;
+}
+
+static void at76_tx_callback(struct urb *urb)
+{
+ struct at76_priv *priv = urb->context;
+ struct net_device_stats *stats = &priv->stats;
+ unsigned long flags;
+ struct at76_tx_buffer *mgmt_buf;
+ int ret;
+
+ switch (urb->status) {
+ case 0:
+ stats->tx_packets++;
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ /* urb has been unlinked */
+ return;
+ default:
+ at76_dbg(DBG_URB, "%s - nonzero tx status received: %d",
+ __func__, urb->status);
+ stats->tx_errors++;
+ break;
+ }
+
+ spin_lock_irqsave(&priv->mgmt_spinlock, flags);
+ mgmt_buf = priv->next_mgmt_bulk;
+ priv->next_mgmt_bulk = NULL;
+ spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
+
+ if (!mgmt_buf) {
+ netif_wake_queue(priv->netdev);
+ return;
+ }
+
+ /* we don't copy the padding bytes, but add them
+ to the length */
+ memcpy(priv->bulk_out_buffer, mgmt_buf,
+ le16_to_cpu(mgmt_buf->wlength) + AT76_TX_HDRLEN);
+ usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
+ priv->bulk_out_buffer,
+ le16_to_cpu(mgmt_buf->wlength) + mgmt_buf->padding +
+ AT76_TX_HDRLEN, at76_tx_callback, priv);
+ ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
+ if (ret)
+ printk(KERN_ERR "%s: error in tx submit urb: %d\n",
+ priv->netdev->name, ret);
+
+ kfree(mgmt_buf);
+}
+
+/* Send a management frame on bulk-out. txbuf->wlength must be set */
+static int at76_tx_mgmt(struct at76_priv *priv, struct at76_tx_buffer *txbuf)
+{
+ unsigned long flags;
+ int ret;
+ int urb_status;
+ void *oldbuf = NULL;
+
+ netif_carrier_off(priv->netdev); /* stop netdev watchdog */
+ netif_stop_queue(priv->netdev); /* stop tx data packets */
+
+ spin_lock_irqsave(&priv->mgmt_spinlock, flags);
+
+ urb_status = priv->tx_urb->status;
+ if (urb_status == -EINPROGRESS) {
+ /* cannot transmit now, put in the queue */
+ oldbuf = priv->next_mgmt_bulk;
+ priv->next_mgmt_bulk = txbuf;
+ }
+ spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
+
+ if (oldbuf) {
+ /* a data/mgmt tx is already pending in the URB -
+ if this is no error in some situations we must
+ implement a queue or silently modify the old msg */
+ printk(KERN_ERR "%s: removed pending mgmt buffer %s\n",
+ priv->netdev->name, hex2str(oldbuf, 64));
+ kfree(oldbuf);
+ return 0;
+ }
+
+ txbuf->tx_rate = TX_RATE_1MBIT;
+ txbuf->padding = at76_calc_padding(le16_to_cpu(txbuf->wlength));
+ memset(txbuf->reserved, 0, sizeof(txbuf->reserved));
+
+ if (priv->next_mgmt_bulk)
+ printk(KERN_ERR "%s: URB status %d, but mgmt is pending\n",
+ priv->netdev->name, urb_status);
+
+ at76_dbg(DBG_TX_MGMT,
+ "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",
+ priv->netdev->name, le16_to_cpu(txbuf->wlength),
+ txbuf->tx_rate, txbuf->padding,
+ hex2str(txbuf->packet, le16_to_cpu(txbuf->wlength)));
+
+ /* txbuf was not consumed above -> send mgmt msg immediately */
+ memcpy(priv->bulk_out_buffer, txbuf,
+ le16_to_cpu(txbuf->wlength) + AT76_TX_HDRLEN);
+ usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
+ priv->bulk_out_buffer,
+ le16_to_cpu(txbuf->wlength) + txbuf->padding +
+ AT76_TX_HDRLEN, at76_tx_callback, priv);
+ ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
+ if (ret)
+ printk(KERN_ERR "%s: error in tx submit urb: %d\n",
+ priv->netdev->name, ret);
+
+ kfree(txbuf);
+
+ return ret;
+}
+
+/* Go to the next information element */
+static inline void next_ie(struct ieee80211_info_element **ie)
+{
+ *ie = (struct ieee80211_info_element *)(&(*ie)->data[(*ie)->len]);
+}
+
+/* Challenge is the challenge string (in TLV format)
+ we got with seq_nr 2 for shared secret authentication only and
+ send in seq_nr 3 WEP encrypted to prove we have the correct WEP key;
+ otherwise it is NULL */
+static int at76_auth_req(struct at76_priv *priv, struct bss_info *bss,
+ int seq_nr, struct ieee80211_info_element *challenge)
+{
+ struct at76_tx_buffer *tx_buffer;
+ struct ieee80211_hdr_3addr *mgmt;
+ struct ieee80211_auth *req;
+ int buf_len = (seq_nr != 3 ? AUTH_FRAME_SIZE :
+ AUTH_FRAME_SIZE + 1 + 1 + challenge->len);
+
+ BUG_ON(!bss);
+ BUG_ON(seq_nr == 3 && !challenge);
+ tx_buffer = kmalloc(buf_len + MAX_PADDING_SIZE, GFP_ATOMIC);
+ if (!tx_buffer)
+ return -ENOMEM;
+
+ req = (struct ieee80211_auth *)tx_buffer->packet;
+ mgmt = &req->header;
+
+ /* make wireless header */
+ /* first auth msg is not encrypted, only the second (seq_nr == 3) */
+ mgmt->frame_ctl =
+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH |
+ (seq_nr == 3 ? IEEE80211_FCTL_PROTECTED : 0));
+
+ mgmt->duration_id = cpu_to_le16(0x8000);
+ memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
+ memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
+ mgmt->seq_ctl = cpu_to_le16(0);
+
+ req->algorithm = cpu_to_le16(priv->auth_mode);
+ req->transaction = cpu_to_le16(seq_nr);
+ req->status = cpu_to_le16(0);
+
+ if (seq_nr == 3)
+ memcpy(req->info_element, challenge, 1 + 1 + challenge->len);
+
+ /* init. at76_priv tx header */
+ tx_buffer->wlength = cpu_to_le16(buf_len - AT76_TX_HDRLEN);
+ at76_dbg(DBG_TX_MGMT, "%s: AuthReq bssid %s alg %d seq_nr %d",
+ priv->netdev->name, mac2str(mgmt->addr3),
+ le16_to_cpu(req->algorithm), le16_to_cpu(req->transaction));
+ if (seq_nr == 3)
+ at76_dbg(DBG_TX_MGMT, "%s: AuthReq challenge: %s ...",
+ priv->netdev->name, hex2str(req->info_element, 18));
+
+ /* either send immediately (if no data tx is pending
+ or put it in pending list */
+ return at76_tx_mgmt(priv, tx_buffer);
+}
+
+static int at76_assoc_req(struct at76_priv *priv, struct bss_info *bss)
+{
+ struct at76_tx_buffer *tx_buffer;
+ struct ieee80211_hdr_3addr *mgmt;
+ struct ieee80211_assoc_request *req;
+ struct ieee80211_info_element *ie;
+ char *essid;
+ int essid_len;
+ u16 capa;
+
+ BUG_ON(!bss);
+
+ tx_buffer = kmalloc(ASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE, GFP_ATOMIC);
+ if (!tx_buffer)
+ return -ENOMEM;
+
+ req = (struct ieee80211_assoc_request *)tx_buffer->packet;
+ mgmt = &req->header;
+ ie = req->info_element;
+
+ /* make wireless header */
+ mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ASSOC_REQ);
+
+ mgmt->duration_id = cpu_to_le16(0x8000);
+ memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
+ memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
+ mgmt->seq_ctl = cpu_to_le16(0);
+
+ /* we must set the Privacy bit in the capabilities to assure an
+ Agere-based AP with optional WEP transmits encrypted frames
+ to us. AP only set the Privacy bit in their capabilities
+ if WEP is mandatory in the BSS! */
+ capa = bss->capa;
+ if (priv->wep_enabled)
+ capa |= WLAN_CAPABILITY_PRIVACY;
+ if (priv->preamble_type != PREAMBLE_TYPE_LONG)
+ capa |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+ req->capability = cpu_to_le16(capa);
+
+ req->listen_interval = cpu_to_le16(2 * bss->beacon_interval);
+
+ /* write TLV data elements */
+
+ ie->id = MFIE_TYPE_SSID;
+ ie->len = bss->ssid_len;
+ memcpy(ie->data, bss->ssid, bss->ssid_len);
+ next_ie(&ie);
+
+ ie->id = MFIE_TYPE_RATES;
+ ie->len = sizeof(hw_rates);
+ memcpy(ie->data, hw_rates, sizeof(hw_rates));
+ next_ie(&ie); /* ie points behind the supp_rates field */
+
+ /* init. at76_priv tx header */
+ tx_buffer->wlength = cpu_to_le16((u8 *)ie - (u8 *)mgmt);
+
+ ie = req->info_element;
+ essid = ie->data;
+ essid_len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
+
+ next_ie(&ie); /* points to IE of rates now */
+ at76_dbg(DBG_TX_MGMT,
+ "%s: AssocReq bssid %s capa 0x%04x ssid %.*s rates %s",
+ priv->netdev->name, mac2str(mgmt->addr3),
+ le16_to_cpu(req->capability), essid_len, essid,
+ hex2str(ie->data, ie->len));
+
+ /* either send immediately (if no data tx is pending
+ or put it in pending list */
+ return at76_tx_mgmt(priv, tx_buffer);
+}
+
+/* We got to check the bss_list for old entries */
+static void at76_bss_list_timeout(unsigned long par)
+{
+ struct at76_priv *priv = (struct at76_priv *)par;
+ unsigned long flags;
+ struct list_head *lptr, *nptr;
+ struct bss_info *ptr;
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+
+ list_for_each_safe(lptr, nptr, &priv->bss_list) {
+
+ ptr = list_entry(lptr, struct bss_info, list);
+
+ if (ptr != priv->curr_bss
+ && time_after(jiffies, ptr->last_rx + BSS_LIST_TIMEOUT)) {
+ at76_dbg(DBG_BSS_TABLE_RM,
+ "%s: bss_list: removing old BSS %s ch %d",
+ priv->netdev->name, mac2str(ptr->bssid),
+ ptr->channel);
+ list_del(&ptr->list);
+ kfree(ptr);
+ }
+ }
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+ /* restart the timer */
+ mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
+}
+
+static inline void at76_set_mac_state(struct at76_priv *priv,
+ enum mac_state mac_state)
+{
+ at76_dbg(DBG_MAC_STATE, "%s state: %s", priv->netdev->name,
+ mac_states[mac_state]);
+ priv->mac_state = mac_state;
+}
+
+static void at76_dump_bss_table(struct at76_priv *priv)
+{
+ struct bss_info *ptr;
+ unsigned long flags;
+ struct list_head *lptr;
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+
+ at76_dbg(DBG_BSS_TABLE, "%s BSS table (curr=%p):", priv->netdev->name,
+ priv->curr_bss);
+
+ list_for_each(lptr, &priv->bss_list) {
+ ptr = list_entry(lptr, struct bss_info, list);
+ at76_dbg(DBG_BSS_TABLE, "0x%p: bssid %s channel %d ssid %.*s "
+ "(%s) capa 0x%04x rates %s rssi %d link %d noise %d",
+ ptr, mac2str(ptr->bssid), ptr->channel, ptr->ssid_len,
+ ptr->ssid, hex2str(ptr->ssid, ptr->ssid_len),
+ ptr->capa, hex2str(ptr->rates, ptr->rates_len),
+ ptr->rssi, ptr->link_qual, ptr->noise_level);
+ }
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+}
+
+/* Called upon successful association to mark interface as connected */
+static void at76_work_assoc_done(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_assoc_done);
+
+ mutex_lock(&priv->mtx);
+
+ WARN_ON(priv->mac_state != MAC_ASSOC);
+ WARN_ON(!priv->curr_bss);
+ if (priv->mac_state != MAC_ASSOC || !priv->curr_bss)
+ goto exit;
+
+ if (priv->iw_mode == IW_MODE_INFRA) {
+ if (priv->pm_mode != AT76_PM_OFF) {
+ /* calculate the listen interval in units of
+ beacon intervals of the curr_bss */
+ u32 pm_period_beacon = (priv->pm_period >> 10) /
+ priv->curr_bss->beacon_interval;
+
+ pm_period_beacon = max(pm_period_beacon, 2u);
+ pm_period_beacon = min(pm_period_beacon, 0xffffu);
+
+ at76_dbg(DBG_PM,
+ "%s: pm_mode %d assoc id 0x%x listen int %d",
+ priv->netdev->name, priv->pm_mode,
+ priv->assoc_id, pm_period_beacon);
+
+ at76_set_associd(priv, priv->assoc_id);
+ at76_set_listen_interval(priv, (u16)pm_period_beacon);
+ }
+ schedule_delayed_work(&priv->dwork_beacon, BEACON_TIMEOUT);
+ }
+ at76_set_pm_mode(priv);
+
+ netif_carrier_on(priv->netdev);
+ netif_wake_queue(priv->netdev);
+ at76_set_mac_state(priv, MAC_CONNECTED);
+ at76_iwevent_bss_connect(priv->netdev, priv->curr_bss->bssid);
+ at76_dbg(DBG_PROGRESS, "%s: connected to BSSID %s",
+ priv->netdev->name, mac2str(priv->curr_bss->bssid));
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* We only store the new mac address in netdev struct,
+ it gets set when the netdev is opened. */
+static int at76_set_mac_address(struct net_device *netdev, void *addr)
+{
+ struct sockaddr *mac = addr;
+ memcpy(netdev->dev_addr, mac->sa_data, ETH_ALEN);
+ return 1;
+}
+
+static struct net_device_stats *at76_get_stats(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ return &priv->stats;
+}
+
+static struct iw_statistics *at76_get_wireless_stats(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "RETURN qual %d level %d noise %d updated %d",
+ priv->wstats.qual.qual, priv->wstats.qual.level,
+ priv->wstats.qual.noise, priv->wstats.qual.updated);
+
+ return &priv->wstats;
+}
+
+static void at76_set_multicast(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int promisc;
+
+ promisc = ((netdev->flags & IFF_PROMISC) != 0);
+ if (promisc != priv->promisc) {
+ /* This gets called in interrupt, must reschedule */
+ priv->promisc = promisc;
+ schedule_work(&priv->work_set_promisc);
+ }
+}
+
+/* Stop all network activity, flush all pending tasks */
+static void at76_quiesce(struct at76_priv *priv)
+{
+ unsigned long flags;
+
+ netif_stop_queue(priv->netdev);
+ netif_carrier_off(priv->netdev);
+
+ at76_set_mac_state(priv, MAC_INIT);
+
+ cancel_delayed_work(&priv->dwork_get_scan);
+ cancel_delayed_work(&priv->dwork_beacon);
+ cancel_delayed_work(&priv->dwork_auth);
+ cancel_delayed_work(&priv->dwork_assoc);
+ cancel_delayed_work(&priv->dwork_restart);
+
+ spin_lock_irqsave(&priv->mgmt_spinlock, flags);
+ kfree(priv->next_mgmt_bulk);
+ priv->next_mgmt_bulk = NULL;
+ spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
+}
+
+/*******************************************************************************
+ * at76_priv implementations of iw_handler functions:
+ */
+static int at76_iw_handler_commit(struct net_device *netdev,
+ struct iw_request_info *info,
+ void *null, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "%s %s: restarting the device", netdev->name,
+ __func__);
+
+ if (priv->mac_state != MAC_INIT)
+ at76_quiesce(priv);
+
+ /* Wait half second before the restart to process subsequent
+ * requests from the same iwconfig in a single restart */
+ schedule_delayed_work(&priv->dwork_restart, HZ / 2);
+
+ return 0;
+}
+
+static int at76_iw_handler_get_name(struct net_device *netdev,
+ struct iw_request_info *info,
+ char *name, char *extra)
+{
+ strcpy(name, "IEEE 802.11b");
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWNAME - name %s", netdev->name, name);
+ return 0;
+}
+
+static int at76_iw_handler_set_freq(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int chan = -1;
+ int ret = -EIWCOMMIT;
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - freq.m %d freq.e %d",
+ netdev->name, freq->m, freq->e);
+
+ if ((freq->e == 0) && (freq->m <= 1000))
+ /* Setting by channel number */
+ chan = freq->m;
+ else {
+ /* Setting by frequency - search the table */
+ int mult = 1;
+ int i;
+
+ for (i = 0; i < (6 - freq->e); i++)
+ mult *= 10;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (freq->m == (channel_frequency[i] * mult))
+ chan = i + 1;
+ }
+ }
+
+ if (chan < 1 || !priv->domain)
+ /* non-positive channels are invalid
+ * we need a domain info to set the channel
+ * either that or an invalid frequency was
+ * provided by the user */
+ ret = -EINVAL;
+ else if (!(priv->domain->channel_map & (1 << (chan - 1)))) {
+ printk(KERN_INFO "%s: channel %d not allowed for domain %s\n",
+ priv->netdev->name, chan, priv->domain->name);
+ ret = -EINVAL;
+ }
+
+ if (ret == -EIWCOMMIT) {
+ priv->channel = chan;
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - ch %d", netdev->name,
+ chan);
+ }
+
+ return ret;
+}
+
+static int at76_iw_handler_get_freq(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ freq->m = priv->channel;
+ freq->e = 0;
+
+ if (priv->channel)
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - freq %ld x 10e%d",
+ netdev->name, channel_frequency[priv->channel - 1], 6);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - ch %d", netdev->name,
+ priv->channel);
+
+ return 0;
+}
+
+static int at76_iw_handler_set_mode(struct net_device *netdev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWMODE - %d", netdev->name, *mode);
+
+ if ((*mode != IW_MODE_ADHOC) && (*mode != IW_MODE_INFRA) &&
+ (*mode != IW_MODE_MONITOR))
+ return -EINVAL;
+
+ priv->iw_mode = *mode;
+ if (priv->iw_mode != IW_MODE_INFRA)
+ priv->pm_mode = AT76_PM_OFF;
+
+ return -EIWCOMMIT;
+}
+
+static int at76_iw_handler_get_mode(struct net_device *netdev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ *mode = priv->iw_mode;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWMODE - %d", netdev->name, *mode);
+
+ return 0;
+}
+
+static int at76_iw_handler_get_range(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ /* inspired by atmel.c */
+ struct at76_priv *priv = netdev_priv(netdev);
+ struct iw_range *range = (struct iw_range *)extra;
+ int i;
+
+ data->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
+ /* TODO: range->throughput = xxxxxx; */
+
+ range->min_nwid = 0x0000;
+ range->max_nwid = 0x0000;
+
+ /* this driver doesn't maintain sensitivity information */
+ range->sensitivity = 0;
+
+ range->max_qual.qual = 100;
+ range->max_qual.level = 100;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = IW_QUAL_NOISE_INVALID;
+
+ range->avg_qual.qual = 50;
+ range->avg_qual.level = 50;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
+
+ range->bitrate[0] = 1000000;
+ range->bitrate[1] = 2000000;
+ range->bitrate[2] = 5500000;
+ range->bitrate[3] = 11000000;
+ range->num_bitrates = 4;
+
+ range->min_rts = 0;
+ range->max_rts = MAX_RTS_THRESHOLD;
+
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->pmp_flags = IW_POWER_PERIOD;
+ range->pmt_flags = IW_POWER_ON;
+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_ALL_R;
+
+ range->encoding_size[0] = WEP_SMALL_KEY_LEN;
+ range->encoding_size[1] = WEP_LARGE_KEY_LEN;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = WEP_KEYS;
+
+ /* both WL-240U and Linksys WUSB11 v2.6 specify 15 dBm as output power
+ - take this for all (ignore antenna gains) */
+ range->txpower[0] = 15;
+ range->num_txpower = 1;
+ range->txpower_capa = IW_TXPOW_DBM;
+
+ range->we_version_source = WIRELESS_EXT;
+ range->we_version_compiled = WIRELESS_EXT;
+
+ /* same as the values used in atmel.c */
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->r_time_flags = 0;
+ range->min_retry = 1;
+ range->max_retry = 255;
+
+ range->num_channels = NUM_CHANNELS;
+ range->num_frequency = 0;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ /* test if channel map bit is raised */
+ if (priv->domain->channel_map & (0x1 << i)) {
+ range->num_frequency += 1;
+
+ range->freq[i].i = i + 1;
+ range->freq[i].m = channel_frequency[i] * 100000;
+ range->freq[i].e = 1; /* freq * 10^1 */
+ }
+ }
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWRANGE", netdev->name);
+
+ return 0;
+}
+
+static int at76_iw_handler_set_spy(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = 0;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWSPY - number of addresses %d",
+ netdev->name, data->length);
+
+ spin_lock_bh(&priv->spy_spinlock);
+ ret = iw_handler_set_spy(priv->netdev, info, (union iwreq_data *)data,
+ extra);
+ spin_unlock_bh(&priv->spy_spinlock);
+
+ return ret;
+}
+
+static int at76_iw_handler_get_spy(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = 0;
+
+ spin_lock_bh(&priv->spy_spinlock);
+ ret = iw_handler_get_spy(priv->netdev, info,
+ (union iwreq_data *)data, extra);
+ spin_unlock_bh(&priv->spy_spinlock);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWSPY - number of addresses %d",
+ netdev->name, data->length);
+
+ return ret;
+}
+
+static int at76_iw_handler_set_thrspy(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWTHRSPY - number of addresses %d)",
+ netdev->name, data->length);
+
+ spin_lock_bh(&priv->spy_spinlock);
+ ret = iw_handler_set_thrspy(netdev, info, (union iwreq_data *)data,
+ extra);
+ spin_unlock_bh(&priv->spy_spinlock);
+
+ return ret;
+}
+
+static int at76_iw_handler_get_thrspy(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret;
+
+ spin_lock_bh(&priv->spy_spinlock);
+ ret = iw_handler_get_thrspy(netdev, info, (union iwreq_data *)data,
+ extra);
+ spin_unlock_bh(&priv->spy_spinlock);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWTHRSPY - number of addresses %d)",
+ netdev->name, data->length);
+
+ return ret;
+}
+
+static int at76_iw_handler_set_wap(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWAP - wap/bssid %s", netdev->name,
+ mac2str(ap_addr->sa_data));
+
+ /* if the incoming address == ff:ff:ff:ff:ff:ff, the user has
+ chosen any or auto AP preference */
+ if (is_broadcast_ether_addr(ap_addr->sa_data)
+ || is_zero_ether_addr(ap_addr->sa_data))
+ priv->wanted_bssid_valid = 0;
+ else {
+ /* user wants to set a preferred AP address */
+ priv->wanted_bssid_valid = 1;
+ memcpy(priv->wanted_bssid, ap_addr->sa_data, ETH_ALEN);
+ }
+
+ return -EIWCOMMIT;
+}
+
+static int at76_iw_handler_get_wap(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ ap_addr->sa_family = ARPHRD_ETHER;
+ memcpy(ap_addr->sa_data, priv->bssid, ETH_ALEN);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWAP - wap/bssid %s", netdev->name,
+ mac2str(ap_addr->sa_data));
+
+ return 0;
+}
+
+static int at76_iw_handler_set_scan(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = 0;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWSCAN", netdev->name);
+
+ if (mutex_lock_interruptible(&priv->mtx))
+ return -EINTR;
+
+ if (!netif_running(netdev)) {
+ ret = -ENETDOWN;
+ goto exit;
+ }
+
+ /* jal: we don't allow "iwlist ethX scan" while we are
+ in monitor mode */
+ if (priv->iw_mode == IW_MODE_MONITOR) {
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ /* Discard old scan results */
+ if ((jiffies - priv->last_scan) > (20 * HZ))
+ priv->scan_state = SCAN_IDLE;
+ priv->last_scan = jiffies;
+
+ /* Initiate a scan command */
+ if (priv->scan_state == SCAN_IN_PROGRESS) {
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ priv->scan_state = SCAN_IN_PROGRESS;
+
+ at76_quiesce(priv);
+
+ /* Try to do passive or active scan if WE asks as. */
+ if (wrqu->data.length
+ && wrqu->data.length == sizeof(struct iw_scan_req)) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+
+ if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
+ priv->scan_mode = SCAN_TYPE_PASSIVE;
+ else if (req->scan_type == IW_SCAN_TYPE_ACTIVE)
+ priv->scan_mode = SCAN_TYPE_ACTIVE;
+
+ /* Sanity check values? */
+ if (req->min_channel_time > 0)
+ priv->scan_min_time = req->min_channel_time;
+
+ if (req->max_channel_time > 0)
+ priv->scan_max_time = req->max_channel_time;
+ }
+
+ /* change to scanning state */
+ at76_set_mac_state(priv, MAC_SCANNING);
+ schedule_work(&priv->work_start_scan);
+
+exit:
+ mutex_unlock(&priv->mtx);
+ return ret;
+}
+
+static int at76_iw_handler_get_scan(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ unsigned long flags;
+ struct list_head *lptr, *nptr;
+ struct bss_info *curr_bss;
+ struct iw_event *iwe = kmalloc(sizeof(struct iw_event), GFP_KERNEL);
+ char *curr_val, *curr_pos = extra;
+ int i;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWSCAN", netdev->name);
+
+ if (!iwe)
+ return -ENOMEM;
+
+ if (priv->scan_state != SCAN_COMPLETED)
+ /* scan not yet finished */
+ return -EAGAIN;
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+
+ list_for_each_safe(lptr, nptr, &priv->bss_list) {
+ curr_bss = list_entry(lptr, struct bss_info, list);
+
+ iwe->cmd = SIOCGIWAP;
+ iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe->u.ap_addr.sa_data, curr_bss->bssid, 6);
+ curr_pos = iwe_stream_add_event(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ IW_EV_ADDR_LEN);
+
+ iwe->u.data.length = curr_bss->ssid_len;
+ iwe->cmd = SIOCGIWESSID;
+ iwe->u.data.flags = 1;
+
+ curr_pos = iwe_stream_add_point(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ curr_bss->ssid);
+
+ iwe->cmd = SIOCGIWMODE;
+ iwe->u.mode = (curr_bss->capa & WLAN_CAPABILITY_IBSS) ?
+ IW_MODE_ADHOC :
+ (curr_bss->capa & WLAN_CAPABILITY_ESS) ?
+ IW_MODE_MASTER : IW_MODE_AUTO;
+ /* IW_MODE_AUTO = 0 which I thought is
+ * the most logical value to return in this case */
+ curr_pos = iwe_stream_add_event(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ IW_EV_UINT_LEN);
+
+ iwe->cmd = SIOCGIWFREQ;
+ iwe->u.freq.m = curr_bss->channel;
+ iwe->u.freq.e = 0;
+ curr_pos = iwe_stream_add_event(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ IW_EV_FREQ_LEN);
+
+ iwe->cmd = SIOCGIWENCODE;
+ if (curr_bss->capa & WLAN_CAPABILITY_PRIVACY)
+ iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe->u.data.flags = IW_ENCODE_DISABLED;
+
+ iwe->u.data.length = 0;
+ curr_pos = iwe_stream_add_point(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ NULL);
+
+ /* Add quality statistics */
+ iwe->cmd = IWEVQUAL;
+ iwe->u.qual.noise = 0;
+ iwe->u.qual.updated =
+ IW_QUAL_NOISE_INVALID | IW_QUAL_LEVEL_UPDATED;
+ iwe->u.qual.level = (curr_bss->rssi * 100 / 42);
+ if (iwe->u.qual.level > 100)
+ iwe->u.qual.level = 100;
+ if (at76_is_intersil(priv->board_type))
+ iwe->u.qual.qual = curr_bss->link_qual;
+ else {
+ iwe->u.qual.qual = 0;
+ iwe->u.qual.updated |= IW_QUAL_QUAL_INVALID;
+ }
+ /* Add new value to event */
+ curr_pos = iwe_stream_add_event(info, curr_pos,
+ extra + IW_SCAN_MAX_DATA, iwe,
+ IW_EV_QUAL_LEN);
+
+ /* Rate: stuffing multiple values in a single event requires
+ * a bit more of magic - Jean II */
+ curr_val = curr_pos + IW_EV_LCP_LEN;
+
+ iwe->cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe->u.bitrate.fixed = 0;
+ iwe->u.bitrate.disabled = 0;
+ /* Max 8 values */
+ for (i = 0; i < curr_bss->rates_len; i++) {
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe->u.bitrate.value =
+ ((curr_bss->rates[i] & 0x7f) * 500000);
+ /* Add new value to event */
+ curr_val = iwe_stream_add_value(info, curr_pos,
+ curr_val,
+ extra +
+ IW_SCAN_MAX_DATA, iwe,
+ IW_EV_PARAM_LEN);
+ }
+
+ /* Check if we added any event */
+ if ((curr_val - curr_pos) > IW_EV_LCP_LEN)
+ curr_pos = curr_val;
+
+ /* more information may be sent back using IWECUSTOM */
+
+ }
+
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+
+ data->length = (curr_pos - extra);
+ data->flags = 0;
+
+ kfree(iwe);
+ return 0;
+}
+
+static int at76_iw_handler_set_essid(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWESSID - %s", netdev->name, extra);
+
+ if (data->flags) {
+ memcpy(priv->essid, extra, data->length);
+ priv->essid_size = data->length;
+ } else
+ priv->essid_size = 0; /* Use any SSID */
+
+ return -EIWCOMMIT;
+}
+
+static int at76_iw_handler_get_essid(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ if (priv->essid_size) {
+ /* not the ANY ssid in priv->essid */
+ data->flags = 1;
+ data->length = priv->essid_size;
+ memcpy(extra, priv->essid, data->length);
+ } else {
+ /* the ANY ssid was specified */
+ if (priv->mac_state == MAC_CONNECTED && priv->curr_bss) {
+ /* report the SSID we have found */
+ data->flags = 1;
+ data->length = priv->curr_bss->ssid_len;
+ memcpy(extra, priv->curr_bss->ssid, data->length);
+ } else {
+ /* report ANY back */
+ data->flags = 0;
+ data->length = 0;
+ }
+ }
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWESSID - %.*s", netdev->name,
+ data->length, extra);
+
+ return 0;
+}
+
+static int at76_iw_handler_set_rate(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *bitrate, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWRATE - %d", netdev->name,
+ bitrate->value);
+
+ switch (bitrate->value) {
+ case -1:
+ priv->txrate = TX_RATE_AUTO;
+ break; /* auto rate */
+ case 1000000:
+ priv->txrate = TX_RATE_1MBIT;
+ break;
+ case 2000000:
+ priv->txrate = TX_RATE_2MBIT;
+ break;
+ case 5500000:
+ priv->txrate = TX_RATE_5_5MBIT;
+ break;
+ case 11000000:
+ priv->txrate = TX_RATE_11MBIT;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int at76_iw_handler_get_rate(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *bitrate, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = 0;
+
+ switch (priv->txrate) {
+ /* return max rate if RATE_AUTO */
+ case TX_RATE_AUTO:
+ bitrate->value = 11000000;
+ break;
+ case TX_RATE_1MBIT:
+ bitrate->value = 1000000;
+ break;
+ case TX_RATE_2MBIT:
+ bitrate->value = 2000000;
+ break;
+ case TX_RATE_5_5MBIT:
+ bitrate->value = 5500000;
+ break;
+ case TX_RATE_11MBIT:
+ bitrate->value = 11000000;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ bitrate->fixed = (priv->txrate != TX_RATE_AUTO);
+ bitrate->disabled = 0;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWRATE - %d", netdev->name,
+ bitrate->value);
+
+ return ret;
+}
+
+static int at76_iw_handler_set_rts(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = -EIWCOMMIT;
+ int rthr = rts->value;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWRTS - value %d disabled %s",
+ netdev->name, rts->value, (rts->disabled) ? "true" : "false");
+
+ if (rts->disabled)
+ rthr = MAX_RTS_THRESHOLD;
+
+ if ((rthr < 0) || (rthr > MAX_RTS_THRESHOLD))
+ ret = -EINVAL;
+ else
+ priv->rts_threshold = rthr;
+
+ return ret;
+}
+
+static int at76_iw_handler_get_rts(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ rts->value = priv->rts_threshold;
+ rts->disabled = (rts->value >= MAX_RTS_THRESHOLD);
+ rts->fixed = 1;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWRTS - value %d disabled %s",
+ netdev->name, rts->value, (rts->disabled) ? "true" : "false");
+
+ return 0;
+}
+
+static int at76_iw_handler_set_frag(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = -EIWCOMMIT;
+ int fthr = frag->value;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWFRAG - value %d, disabled %s",
+ netdev->name, frag->value,
+ (frag->disabled) ? "true" : "false");
+
+ if (frag->disabled)
+ fthr = MAX_FRAG_THRESHOLD;
+
+ if ((fthr < MIN_FRAG_THRESHOLD) || (fthr > MAX_FRAG_THRESHOLD))
+ ret = -EINVAL;
+ else
+ priv->frag_threshold = fthr & ~0x1; /* get an even value */
+
+ return ret;
+}
+
+static int at76_iw_handler_get_frag(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ frag->value = priv->frag_threshold;
+ frag->disabled = (frag->value >= MAX_FRAG_THRESHOLD);
+ frag->fixed = 1;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWFRAG - value %d, disabled %s",
+ netdev->name, frag->value,
+ (frag->disabled) ? "true" : "false");
+
+ return 0;
+}
+
+static int at76_iw_handler_get_txpow(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *power, char *extra)
+{
+ power->value = 15;
+ power->fixed = 1; /* No power control */
+ power->disabled = 0;
+ power->flags = IW_TXPOW_DBM;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWTXPOW - txpow %d dBm", netdev->name,
+ power->value);
+
+ return 0;
+}
+
+/* jal: short retry is handled by the firmware (at least 0.90.x),
+ while long retry is not (?) */
+static int at76_iw_handler_set_retry(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *retry, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWRETRY disabled %d flags 0x%x val %d",
+ netdev->name, retry->disabled, retry->flags, retry->value);
+
+ if (!retry->disabled && (retry->flags & IW_RETRY_LIMIT)) {
+ if ((retry->flags & IW_RETRY_MIN) ||
+ !(retry->flags & IW_RETRY_MAX))
+ priv->short_retry_limit = retry->value;
+ else
+ ret = -EINVAL;
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+/* Adapted (ripped) from atmel.c */
+static int at76_iw_handler_get_retry(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *retry, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWRETRY", netdev->name);
+
+ retry->disabled = 0; /* Can't be disabled */
+ retry->flags = IW_RETRY_LIMIT;
+ retry->value = priv->short_retry_limit;
+
+ return 0;
+}
+
+static int at76_iw_handler_set_encode(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *encoding, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
+ int len = encoding->length;
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - enc.flags %08x "
+ "pointer %p len %d", netdev->name, encoding->flags,
+ encoding->pointer, encoding->length);
+ at76_dbg(DBG_IOCTL,
+ "%s: SIOCSIWENCODE - old wepstate: enabled %s key_id %d "
+ "auth_mode %s", netdev->name,
+ (priv->wep_enabled) ? "true" : "false", priv->wep_key_id,
+ (priv->auth_mode ==
+ WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
+
+ /* take the old default key if index is invalid */
+ if ((index < 0) || (index >= WEP_KEYS))
+ index = priv->wep_key_id;
+
+ if (len > 0) {
+ if (len > WEP_LARGE_KEY_LEN)
+ len = WEP_LARGE_KEY_LEN;
+
+ memset(priv->wep_keys[index], 0, WEP_KEY_LEN);
+ memcpy(priv->wep_keys[index], extra, len);
+ priv->wep_keys_len[index] = (len <= WEP_SMALL_KEY_LEN) ?
+ WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
+ priv->wep_enabled = 1;
+ }
+
+ priv->wep_key_id = index;
+ priv->wep_enabled = ((encoding->flags & IW_ENCODE_DISABLED) == 0);
+
+ if (encoding->flags & IW_ENCODE_RESTRICTED)
+ priv->auth_mode = WLAN_AUTH_SHARED_KEY;
+ if (encoding->flags & IW_ENCODE_OPEN)
+ priv->auth_mode = WLAN_AUTH_OPEN;
+
+ at76_dbg(DBG_IOCTL,
+ "%s: SIOCSIWENCODE - new wepstate: enabled %s key_id %d "
+ "key_len %d auth_mode %s", netdev->name,
+ (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
+ priv->wep_keys_len[priv->wep_key_id],
+ (priv->auth_mode ==
+ WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
+
+ return -EIWCOMMIT;
+}
+
+static int at76_iw_handler_get_encode(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *encoding, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
+
+ if ((index < 0) || (index >= WEP_KEYS))
+ index = priv->wep_key_id;
+
+ encoding->flags =
+ (priv->auth_mode == WLAN_AUTH_SHARED_KEY) ?
+ IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
+
+ if (!priv->wep_enabled)
+ encoding->flags |= IW_ENCODE_DISABLED;
+
+ if (encoding->pointer) {
+ encoding->length = priv->wep_keys_len[index];
+
+ memcpy(extra, priv->wep_keys[index], priv->wep_keys_len[index]);
+
+ encoding->flags |= (index + 1);
+ }
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWENCODE - enc.flags %08x "
+ "pointer %p len %d", netdev->name, encoding->flags,
+ encoding->pointer, encoding->length);
+ at76_dbg(DBG_IOCTL,
+ "%s: SIOCGIWENCODE - wepstate: enabled %s key_id %d "
+ "key_len %d auth_mode %s", netdev->name,
+ (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
+ priv->wep_keys_len[priv->wep_key_id],
+ (priv->auth_mode ==
+ WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
+
+ return 0;
+}
+
+static int at76_iw_handler_set_power(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *prq, char *extra)
+{
+ int err = -EIWCOMMIT;
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_IOCTL,
+ "%s: SIOCSIWPOWER - disabled %s flags 0x%x value 0x%x",
+ netdev->name, (prq->disabled) ? "true" : "false", prq->flags,
+ prq->value);
+
+ if (prq->disabled)
+ priv->pm_mode = AT76_PM_OFF;
+ else {
+ switch (prq->flags & IW_POWER_MODE) {
+ case IW_POWER_ALL_R:
+ case IW_POWER_ON:
+ break;
+ default:
+ err = -EINVAL;
+ goto exit;
+ }
+ if (prq->flags & IW_POWER_PERIOD)
+ priv->pm_period = prq->value;
+
+ if (prq->flags & IW_POWER_TIMEOUT) {
+ err = -EINVAL;
+ goto exit;
+ }
+ priv->pm_mode = AT76_PM_ON;
+ }
+exit:
+ return err;
+}
+
+static int at76_iw_handler_get_power(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_param *power, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ power->disabled = (priv->pm_mode == AT76_PM_OFF);
+ if (!power->disabled) {
+ power->flags = IW_POWER_PERIOD | IW_POWER_ALL_R;
+ power->value = priv->pm_period;
+ }
+
+ at76_dbg(DBG_IOCTL, "%s: SIOCGIWPOWER - %s flags 0x%x value 0x%x",
+ netdev->name, power->disabled ? "disabled" : "enabled",
+ power->flags, power->value);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Private IOCTLS
+ */
+static int at76_iw_set_short_preamble(struct net_device *netdev,
+ struct iw_request_info *info, char *name,
+ char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int val = *((int *)name);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_SHORT_PREAMBLE, %d",
+ netdev->name, val);
+
+ if (val < PREAMBLE_TYPE_LONG || val > PREAMBLE_TYPE_AUTO)
+ ret = -EINVAL;
+ else
+ priv->preamble_type = val;
+
+ return ret;
+}
+
+static int at76_iw_get_short_preamble(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ snprintf(wrqu->name, sizeof(wrqu->name), "%s (%d)",
+ preambles[priv->preamble_type], priv->preamble_type);
+ return 0;
+}
+
+static int at76_iw_set_debug(struct net_device *netdev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ char *ptr;
+ u32 val;
+
+ if (data->length > 0) {
+ val = simple_strtol(extra, &ptr, 0);
+
+ if (ptr == extra)
+ val = DBG_DEFAULTS;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG input %d: %s -> 0x%x",
+ netdev->name, data->length, extra, val);
+ } else
+ val = DBG_DEFAULTS;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG, old 0x%x, new 0x%x",
+ netdev->name, at76_debug, val);
+
+ /* jal: some more output to pin down lockups */
+ at76_dbg(DBG_IOCTL, "%s: netif running %d queue_stopped %d "
+ "carrier_ok %d", netdev->name, netif_running(netdev),
+ netif_queue_stopped(netdev), netif_carrier_ok(netdev));
+
+ at76_debug = val;
+
+ return 0;
+}
+
+static int at76_iw_get_debug(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ snprintf(wrqu->name, sizeof(wrqu->name), "0x%08x", at76_debug);
+ return 0;
+}
+
+static int at76_iw_set_powersave_mode(struct net_device *netdev,
+ struct iw_request_info *info, char *name,
+ char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int val = *((int *)name);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_POWERSAVE_MODE, %d (%s)",
+ netdev->name, val,
+ val == AT76_PM_OFF ? "active" : val == AT76_PM_ON ? "save" :
+ val == AT76_PM_SMART ? "smart save" : "<invalid>");
+ if (val < AT76_PM_OFF || val > AT76_PM_SMART)
+ ret = -EINVAL;
+ else
+ priv->pm_mode = val;
+
+ return ret;
+}
+
+static int at76_iw_get_powersave_mode(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int *param = (int *)extra;
+
+ param[0] = priv->pm_mode;
+ return 0;
+}
+
+static int at76_iw_set_scan_times(struct net_device *netdev,
+ struct iw_request_info *info, char *name,
+ char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int mint = *((int *)name);
+ int maxt = *((int *)name + 1);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_TIMES - min %d max %d",
+ netdev->name, mint, maxt);
+ if (mint <= 0 || maxt <= 0 || mint > maxt)
+ ret = -EINVAL;
+ else {
+ priv->scan_min_time = mint;
+ priv->scan_max_time = maxt;
+ }
+
+ return ret;
+}
+
+static int at76_iw_get_scan_times(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int *param = (int *)extra;
+
+ param[0] = priv->scan_min_time;
+ param[1] = priv->scan_max_time;
+ return 0;
+}
+
+static int at76_iw_set_scan_mode(struct net_device *netdev,
+ struct iw_request_info *info, char *name,
+ char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int val = *((int *)name);
+ int ret = -EIWCOMMIT;
+
+ at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_MODE - mode %s",
+ netdev->name, (val = SCAN_TYPE_ACTIVE) ? "active" :
+ (val = SCAN_TYPE_PASSIVE) ? "passive" : "<invalid>");
+
+ if (val != SCAN_TYPE_ACTIVE && val != SCAN_TYPE_PASSIVE)
+ ret = -EINVAL;
+ else
+ priv->scan_mode = val;
+
+ return ret;
+}
+
+static int at76_iw_get_scan_mode(struct net_device *netdev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int *param = (int *)extra;
+
+ param[0] = priv->scan_mode;
+ return 0;
+}
+
+#define AT76_SET_HANDLER(h, f) [h - SIOCIWFIRST] = (iw_handler) f
+
+/* Standard wireless handlers */
+static const iw_handler at76_handlers[] = {
+ AT76_SET_HANDLER(SIOCSIWCOMMIT, at76_iw_handler_commit),
+ AT76_SET_HANDLER(SIOCGIWNAME, at76_iw_handler_get_name),
+ AT76_SET_HANDLER(SIOCSIWFREQ, at76_iw_handler_set_freq),
+ AT76_SET_HANDLER(SIOCGIWFREQ, at76_iw_handler_get_freq),
+ AT76_SET_HANDLER(SIOCSIWMODE, at76_iw_handler_set_mode),
+ AT76_SET_HANDLER(SIOCGIWMODE, at76_iw_handler_get_mode),
+ AT76_SET_HANDLER(SIOCGIWRANGE, at76_iw_handler_get_range),
+ AT76_SET_HANDLER(SIOCSIWSPY, at76_iw_handler_set_spy),
+ AT76_SET_HANDLER(SIOCGIWSPY, at76_iw_handler_get_spy),
+ AT76_SET_HANDLER(SIOCSIWTHRSPY, at76_iw_handler_set_thrspy),
+ AT76_SET_HANDLER(SIOCGIWTHRSPY, at76_iw_handler_get_thrspy),
+ AT76_SET_HANDLER(SIOCSIWAP, at76_iw_handler_set_wap),
+ AT76_SET_HANDLER(SIOCGIWAP, at76_iw_handler_get_wap),
+ AT76_SET_HANDLER(SIOCSIWSCAN, at76_iw_handler_set_scan),
+ AT76_SET_HANDLER(SIOCGIWSCAN, at76_iw_handler_get_scan),
+ AT76_SET_HANDLER(SIOCSIWESSID, at76_iw_handler_set_essid),
+ AT76_SET_HANDLER(SIOCGIWESSID, at76_iw_handler_get_essid),
+ AT76_SET_HANDLER(SIOCSIWRATE, at76_iw_handler_set_rate),
+ AT76_SET_HANDLER(SIOCGIWRATE, at76_iw_handler_get_rate),
+ AT76_SET_HANDLER(SIOCSIWRTS, at76_iw_handler_set_rts),
+ AT76_SET_HANDLER(SIOCGIWRTS, at76_iw_handler_get_rts),
+ AT76_SET_HANDLER(SIOCSIWFRAG, at76_iw_handler_set_frag),
+ AT76_SET_HANDLER(SIOCGIWFRAG, at76_iw_handler_get_frag),
+ AT76_SET_HANDLER(SIOCGIWTXPOW, at76_iw_handler_get_txpow),
+ AT76_SET_HANDLER(SIOCSIWRETRY, at76_iw_handler_set_retry),
+ AT76_SET_HANDLER(SIOCGIWRETRY, at76_iw_handler_get_retry),
+ AT76_SET_HANDLER(SIOCSIWENCODE, at76_iw_handler_set_encode),
+ AT76_SET_HANDLER(SIOCGIWENCODE, at76_iw_handler_get_encode),
+ AT76_SET_HANDLER(SIOCSIWPOWER, at76_iw_handler_set_power),
+ AT76_SET_HANDLER(SIOCGIWPOWER, at76_iw_handler_get_power)
+};
+
+#define AT76_SET_PRIV(h, f) [h - SIOCIWFIRSTPRIV] = (iw_handler) f
+
+/* Private wireless handlers */
+static const iw_handler at76_priv_handlers[] = {
+ AT76_SET_PRIV(AT76_SET_SHORT_PREAMBLE, at76_iw_set_short_preamble),
+ AT76_SET_PRIV(AT76_GET_SHORT_PREAMBLE, at76_iw_get_short_preamble),
+ AT76_SET_PRIV(AT76_SET_DEBUG, at76_iw_set_debug),
+ AT76_SET_PRIV(AT76_GET_DEBUG, at76_iw_get_debug),
+ AT76_SET_PRIV(AT76_SET_POWERSAVE_MODE, at76_iw_set_powersave_mode),
+ AT76_SET_PRIV(AT76_GET_POWERSAVE_MODE, at76_iw_get_powersave_mode),
+ AT76_SET_PRIV(AT76_SET_SCAN_TIMES, at76_iw_set_scan_times),
+ AT76_SET_PRIV(AT76_GET_SCAN_TIMES, at76_iw_get_scan_times),
+ AT76_SET_PRIV(AT76_SET_SCAN_MODE, at76_iw_set_scan_mode),
+ AT76_SET_PRIV(AT76_GET_SCAN_MODE, at76_iw_get_scan_mode),
+};
+
+/* Names and arguments of private wireless handlers */
+static const struct iw_priv_args at76_priv_args[] = {
+ /* 0 - long, 1 - short */
+ {AT76_SET_SHORT_PREAMBLE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"},
+
+ {AT76_GET_SHORT_PREAMBLE,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_preamble"},
+
+ /* we must pass the new debug mask as a string, because iwpriv cannot
+ * parse hex numbers starting with 0x :-( */
+ {AT76_SET_DEBUG,
+ IW_PRIV_TYPE_CHAR | 10, 0, "set_debug"},
+
+ {AT76_GET_DEBUG,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_debug"},
+
+ /* 1 - active, 2 - power save, 3 - smart power save */
+ {AT76_SET_POWERSAVE_MODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_powersave"},
+
+ {AT76_GET_POWERSAVE_MODE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_powersave"},
+
+ /* min_channel_time, max_channel_time */
+ {AT76_SET_SCAN_TIMES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_scan_times"},
+
+ {AT76_GET_SCAN_TIMES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, "get_scan_times"},
+
+ /* 0 - active, 1 - passive scan */
+ {AT76_SET_SCAN_MODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_scan_mode"},
+
+ {AT76_GET_SCAN_MODE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_scan_mode"},
+};
+
+static const struct iw_handler_def at76_handler_def = {
+ .num_standard = ARRAY_SIZE(at76_handlers),
+ .num_private = ARRAY_SIZE(at76_priv_handlers),
+ .num_private_args = ARRAY_SIZE(at76_priv_args),
+ .standard = at76_handlers,
+ .private = at76_priv_handlers,
+ .private_args = at76_priv_args,
+ .get_wireless_stats = at76_get_wireless_stats,
+};
+
+static const u8 snapsig[] = { 0xaa, 0xaa, 0x03 };
+
+/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with
+ * a SNAP OID of 0 (0x00, 0x00, 0x00) */
+static const u8 rfc1042sig[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ struct net_device_stats *stats = &priv->stats;
+ int ret = 0;
+ int wlen;
+ int submit_len;
+ struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
+ struct ieee80211_hdr_3addr *i802_11_hdr =
+ (struct ieee80211_hdr_3addr *)tx_buffer->packet;
+ u8 *payload = i802_11_hdr->payload;
+ struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+ if (netif_queue_stopped(netdev)) {
+ printk(KERN_ERR "%s: %s called while netdev is stopped\n",
+ netdev->name, __func__);
+ /* skip this packet */
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ if (priv->tx_urb->status == -EINPROGRESS) {
+ printk(KERN_ERR "%s: %s called while tx urb is pending\n",
+ netdev->name, __func__);
+ /* skip this packet */
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ if (skb->len < ETH_HLEN) {
+ printk(KERN_ERR "%s: %s: skb too short (%d)\n",
+ netdev->name, __func__, skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
+
+ /* we can get rid of memcpy if we set netdev->hard_header_len to
+ reserve enough space, but we would need to keep the skb around */
+
+ if (ntohs(eh->h_proto) <= ETH_DATA_LEN) {
+ /* this is a 802.3 packet */
+ if (skb->len >= ETH_HLEN + sizeof(rfc1042sig)
+ && skb->data[ETH_HLEN] == rfc1042sig[0]
+ && skb->data[ETH_HLEN + 1] == rfc1042sig[1]) {
+ /* higher layer delivered SNAP header - keep it */
+ memcpy(payload, skb->data + ETH_HLEN,
+ skb->len - ETH_HLEN);
+ wlen = IEEE80211_3ADDR_LEN + skb->len - ETH_HLEN;
+ } else {
+ printk(KERN_ERR "%s: dropping non-SNAP 802.2 packet "
+ "(DSAP 0x%02x SSAP 0x%02x cntrl 0x%02x)\n",
+ priv->netdev->name, skb->data[ETH_HLEN],
+ skb->data[ETH_HLEN + 1],
+ skb->data[ETH_HLEN + 2]);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ } else {
+ /* add RFC 1042 header in front */
+ memcpy(payload, rfc1042sig, sizeof(rfc1042sig));
+ memcpy(payload + sizeof(rfc1042sig), &eh->h_proto,
+ skb->len - offsetof(struct ethhdr, h_proto));
+ wlen = IEEE80211_3ADDR_LEN + sizeof(rfc1042sig) + skb->len -
+ offsetof(struct ethhdr, h_proto);
+ }
+
+ /* make wireless header */
+ i802_11_hdr->frame_ctl =
+ cpu_to_le16(IEEE80211_FTYPE_DATA |
+ (priv->wep_enabled ? IEEE80211_FCTL_PROTECTED : 0) |
+ (priv->iw_mode ==
+ IW_MODE_INFRA ? IEEE80211_FCTL_TODS : 0));
+
+ if (priv->iw_mode == IW_MODE_ADHOC) {
+ memcpy(i802_11_hdr->addr1, eh->h_dest, ETH_ALEN);
+ memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
+ memcpy(i802_11_hdr->addr3, priv->bssid, ETH_ALEN);
+ } else if (priv->iw_mode == IW_MODE_INFRA) {
+ memcpy(i802_11_hdr->addr1, priv->bssid, ETH_ALEN);
+ memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
+ memcpy(i802_11_hdr->addr3, eh->h_dest, ETH_ALEN);
+ }
+
+ i802_11_hdr->duration_id = cpu_to_le16(0);
+ i802_11_hdr->seq_ctl = cpu_to_le16(0);
+
+ /* setup 'Atmel' header */
+ tx_buffer->wlength = cpu_to_le16(wlen);
+ tx_buffer->tx_rate = priv->txrate;
+ /* for broadcast destination addresses, the firmware 0.100.x
+ seems to choose the highest rate set with CMD_STARTUP in
+ basic_rate_set replacing this value */
+
+ memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved));
+
+ tx_buffer->padding = at76_calc_padding(wlen);
+ submit_len = wlen + AT76_TX_HDRLEN + tx_buffer->padding;
+
+ at76_dbg(DBG_TX_DATA_CONTENT, "%s skb->data %s", priv->netdev->name,
+ hex2str(skb->data, 32));
+ at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr %s",
+ priv->netdev->name,
+ le16_to_cpu(tx_buffer->wlength),
+ tx_buffer->padding, tx_buffer->tx_rate,
+ hex2str(i802_11_hdr, sizeof(*i802_11_hdr)));
+ at76_dbg(DBG_TX_DATA_CONTENT, "%s payload %s", priv->netdev->name,
+ hex2str(payload, 48));
+
+ /* send stuff */
+ netif_stop_queue(netdev);
+ netdev->trans_start = jiffies;
+
+ usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer,
+ submit_len, at76_tx_callback, priv);
+ ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
+ if (ret) {
+ stats->tx_errors++;
+ printk(KERN_ERR "%s: error in tx submit urb: %d\n",
+ netdev->name, ret);
+ if (ret == -EINVAL)
+ printk(KERN_ERR
+ "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
+ priv->netdev->name, priv->tx_urb,
+ priv->tx_urb->hcpriv, priv->tx_urb->complete);
+ } else {
+ stats->tx_bytes += skb->len;
+ dev_kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+static void at76_tx_timeout(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ if (!priv)
+ return;
+ dev_warn(&netdev->dev, "tx timeout.");
+
+ usb_unlink_urb(priv->tx_urb);
+ priv->stats.tx_errors++;
+}
+
+static int at76_submit_rx_urb(struct at76_priv *priv)
+{
+ int ret;
+ int size;
+ struct sk_buff *skb = priv->rx_skb;
+
+ if (!priv->rx_urb) {
+ printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
+ priv->netdev->name, __func__);
+ return -EFAULT;
+ }
+
+ if (!skb) {
+ skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
+ if (!skb) {
+ printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
+ priv->netdev->name);
+ ret = -ENOMEM;
+ goto exit;
+ }
+ priv->rx_skb = skb;
+ } else {
+ skb_push(skb, skb_headroom(skb));
+ skb_trim(skb, 0);
+ }
+
+ size = skb_tailroom(skb);
+ usb_fill_bulk_urb(priv->rx_urb, priv->udev, priv->rx_pipe,
+ skb_put(skb, size), size, at76_rx_callback, priv);
+ ret = usb_submit_urb(priv->rx_urb, GFP_ATOMIC);
+ if (ret < 0) {
+ if (ret == -ENODEV)
+ at76_dbg(DBG_DEVSTART,
+ "usb_submit_urb returned -ENODEV");
+ else
+ printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
+ priv->netdev->name, ret);
+ }
+
+exit:
+ if (ret < 0 && ret != -ENODEV)
+ printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
+ "driver and/or power cycle the device\n",
+ priv->netdev->name);
+
+ return ret;
+}
+
+static int at76_open(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ int ret = 0;
+
+ at76_dbg(DBG_PROC_ENTRY, "%s(): entry", __func__);
+
+ if (mutex_lock_interruptible(&priv->mtx))
+ return -EINTR;
+
+ /* if netdev->dev_addr != priv->mac_addr we must
+ set the mac address in the device ! */
+ if (compare_ether_addr(netdev->dev_addr, priv->mac_addr)) {
+ if (at76_add_mac_address(priv, netdev->dev_addr) >= 0)
+ at76_dbg(DBG_PROGRESS, "%s: set new MAC addr %s",
+ netdev->name, mac2str(netdev->dev_addr));
+ }
+
+ priv->scan_state = SCAN_IDLE;
+ priv->last_scan = jiffies;
+
+ ret = at76_submit_rx_urb(priv);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
+ netdev->name, ret);
+ goto error;
+ }
+
+ schedule_delayed_work(&priv->dwork_restart, 0);
+
+ at76_dbg(DBG_PROC_ENTRY, "%s(): end", __func__);
+error:
+ mutex_unlock(&priv->mtx);
+ return ret < 0 ? ret : 0;
+}
+
+static int at76_stop(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ at76_dbg(DBG_DEVSTART, "%s: ENTER", __func__);
+
+ if (mutex_lock_interruptible(&priv->mtx))
+ return -EINTR;
+
+ at76_quiesce(priv);
+
+ if (!priv->device_unplugged) {
+ /* We are called by "ifconfig ethX down", not because the
+ * device is not available anymore. */
+ at76_set_radio(priv, 0);
+
+ /* We unlink rx_urb because at76_open() re-submits it.
+ * If unplugged, at76_delete_device() takes care of it. */
+ usb_kill_urb(priv->rx_urb);
+ }
+
+ /* free the bss_list */
+ at76_free_bss_list(priv);
+
+ mutex_unlock(&priv->mtx);
+ at76_dbg(DBG_DEVSTART, "%s: EXIT", __func__);
+
+ return 0;
+}
+
+static void at76_ethtool_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+
+ strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+ strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
+
+ usb_make_path(priv->udev, info->bus_info, sizeof(info->bus_info));
+
+ snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d-%d",
+ priv->fw_version.major, priv->fw_version.minor,
+ priv->fw_version.patch, priv->fw_version.build);
+}
+
+static u32 at76_ethtool_get_link(struct net_device *netdev)
+{
+ struct at76_priv *priv = netdev_priv(netdev);
+ return priv->mac_state == MAC_CONNECTED;
+}
+
+static struct ethtool_ops at76_ethtool_ops = {
+ .get_drvinfo = at76_ethtool_get_drvinfo,
+ .get_link = at76_ethtool_get_link,
+};
+
+/* Download external firmware */
+static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
+{
+ int ret;
+ int op_mode;
+ int blockno = 0;
+ int bsize;
+ u8 *block;
+ u8 *buf = fwe->extfw;
+ int size = fwe->extfw_size;
+
+ if (!buf || !size)
+ return -ENOENT;
+
+ op_mode = at76_get_op_mode(udev);
+ at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
+
+ if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
+ dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
+ op_mode);
+ return -EINVAL;
+ }
+
+ block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
+ if (!block)
+ return -ENOMEM;
+
+ at76_dbg(DBG_DEVSTART, "downloading external firmware");
+
+ /* for fw >= 0.100, the device needs an extra empty block */
+ do {
+ bsize = min_t(int, size, FW_BLOCK_SIZE);
+ memcpy(block, buf, bsize);
+ at76_dbg(DBG_DEVSTART,
+ "ext fw, size left = %5d, bsize = %4d, blockno = %2d",
+ size, bsize, blockno);
+ ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
+ if (ret != bsize) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "loading %dth firmware block failed: %d\n",
+ blockno, ret);
+ goto exit;
+ }
+ buf += bsize;
+ size -= bsize;
+ blockno++;
+ } while (bsize > 0);
+
+ if (at76_is_505a(fwe->board_type)) {
+ at76_dbg(DBG_DEVSTART, "200 ms delay for 505a");
+ schedule_timeout_interruptible(HZ / 5 + 1);
+ }
+
+exit:
+ kfree(block);
+ if (ret < 0)
+ dev_printk(KERN_ERR, &udev->dev,
+ "downloading external firmware failed: %d\n", ret);
+ return ret;
+}
+
+/* Download internal firmware */
+static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
+{
+ int ret;
+ int need_remap = !at76_is_505a(fwe->board_type);
+
+ ret = at76_usbdfu_download(udev, fwe->intfw, fwe->intfw_size,
+ need_remap ? 0 : 2 * HZ);
+
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "downloading internal fw failed with %d\n", ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_DEVSTART, "sending REMAP");
+
+ /* no REMAP for 505A (see SF driver) */
+ if (need_remap) {
+ ret = at76_remap(udev);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "sending REMAP failed with %d\n", ret);
+ goto exit;
+ }
+ }
+
+ at76_dbg(DBG_DEVSTART, "sleeping for 2 seconds");
+ schedule_timeout_interruptible(2 * HZ + 1);
+ usb_reset_device(udev);
+
+exit:
+ return ret;
+}
+
+static int at76_match_essid(struct at76_priv *priv, struct bss_info *ptr)
+{
+ /* common criteria for both modi */
+
+ int ret = (priv->essid_size == 0 /* ANY ssid */ ||
+ (priv->essid_size == ptr->ssid_len &&
+ !memcmp(priv->essid, ptr->ssid, ptr->ssid_len)));
+ if (!ret)
+ at76_dbg(DBG_BSS_MATCH,
+ "%s bss table entry %p: essid didn't match",
+ priv->netdev->name, ptr);
+ return ret;
+}
+
+static inline int at76_match_mode(struct at76_priv *priv, struct bss_info *ptr)
+{
+ int ret;
+
+ if (priv->iw_mode == IW_MODE_ADHOC)
+ ret = ptr->capa & WLAN_CAPABILITY_IBSS;
+ else
+ ret = ptr->capa & WLAN_CAPABILITY_ESS;
+ if (!ret)
+ at76_dbg(DBG_BSS_MATCH,
+ "%s bss table entry %p: mode didn't match",
+ priv->netdev->name, ptr);
+ return ret;
+}
+
+static int at76_match_rates(struct at76_priv *priv, struct bss_info *ptr)
+{
+ int i;
+
+ for (i = 0; i < ptr->rates_len; i++) {
+ u8 rate = ptr->rates[i];
+
+ if (!(rate & 0x80))
+ continue;
+
+ /* this is a basic rate we have to support
+ (see IEEE802.11, ch. 7.3.2.2) */
+ if (rate != (0x80 | hw_rates[0])
+ && rate != (0x80 | hw_rates[1])
+ && rate != (0x80 | hw_rates[2])
+ && rate != (0x80 | hw_rates[3])) {
+ at76_dbg(DBG_BSS_MATCH,
+ "%s: bss table entry %p: basic rate %02x not "
+ "supported", priv->netdev->name, ptr, rate);
+ return 0;
+ }
+ }
+
+ /* if we use short preamble, the bss must support it */
+ if (priv->preamble_type == PREAMBLE_TYPE_SHORT &&
+ !(ptr->capa & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
+ at76_dbg(DBG_BSS_MATCH,
+ "%s: %p does not support short preamble",
+ priv->netdev->name, ptr);
+ return 0;
+ } else
+ return 1;
+}
+
+static inline int at76_match_wep(struct at76_priv *priv, struct bss_info *ptr)
+{
+ if (!priv->wep_enabled && ptr->capa & WLAN_CAPABILITY_PRIVACY) {
+ /* we have disabled WEP, but the BSS signals privacy */
+ at76_dbg(DBG_BSS_MATCH,
+ "%s: bss table entry %p: requires encryption",
+ priv->netdev->name, ptr);
+ return 0;
+ }
+ /* otherwise if the BSS does not signal privacy it may well
+ accept encrypted packets from us ... */
+ return 1;
+}
+
+static inline int at76_match_bssid(struct at76_priv *priv, struct bss_info *ptr)
+{
+ if (!priv->wanted_bssid_valid ||
+ !compare_ether_addr(ptr->bssid, priv->wanted_bssid))
+ return 1;
+
+ at76_dbg(DBG_BSS_MATCH,
+ "%s: requested bssid - %s does not match",
+ priv->netdev->name, mac2str(priv->wanted_bssid));
+ at76_dbg(DBG_BSS_MATCH,
+ " AP bssid - %s of bss table entry %p",
+ mac2str(ptr->bssid), ptr);
+ return 0;
+}
+
+/**
+ * at76_match_bss - try to find a matching bss in priv->bss
+ *
+ * last - last bss tried
+ *
+ * last == NULL signals a new round starting with priv->bss_list.next
+ * this function must be called inside an acquired priv->bss_list_spinlock
+ * otherwise the timeout on bss may remove the newly chosen entry
+ */
+static struct bss_info *at76_match_bss(struct at76_priv *priv,
+ struct bss_info *last)
+{
+ struct bss_info *ptr = NULL;
+ struct list_head *curr;
+
+ curr = last ? last->list.next : priv->bss_list.next;
+ while (curr != &priv->bss_list) {
+ ptr = list_entry(curr, struct bss_info, list);
+ if (at76_match_essid(priv, ptr) && at76_match_mode(priv, ptr)
+ && at76_match_wep(priv, ptr) && at76_match_rates(priv, ptr)
+ && at76_match_bssid(priv, ptr))
+ break;
+ curr = curr->next;
+ }
+
+ if (curr == &priv->bss_list)
+ ptr = NULL;
+ /* otherwise ptr points to the struct bss_info we have chosen */
+
+ at76_dbg(DBG_BSS_TABLE, "%s %s: returned %p", priv->netdev->name,
+ __func__, ptr);
+ return ptr;
+}
+
+/* Start joining a matching BSS, or create own IBSS */
+static void at76_work_join(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_join);
+ int ret;
+ unsigned long flags;
+
+ mutex_lock(&priv->mtx);
+
+ WARN_ON(priv->mac_state != MAC_JOINING);
+ if (priv->mac_state != MAC_JOINING)
+ goto exit;
+
+ /* secure the access to priv->curr_bss ! */
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+ priv->curr_bss = at76_match_bss(priv, priv->curr_bss);
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+
+ if (!priv->curr_bss) {
+ /* here we haven't found a matching (i)bss ... */
+ if (priv->iw_mode == IW_MODE_ADHOC) {
+ at76_set_mac_state(priv, MAC_OWN_IBSS);
+ at76_start_ibss(priv);
+ goto exit;
+ }
+ /* haven't found a matching BSS in infra mode - try again */
+ at76_set_mac_state(priv, MAC_SCANNING);
+ schedule_work(&priv->work_start_scan);
+ goto exit;
+ }
+
+ ret = at76_join_bss(priv, priv->curr_bss);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: join_bss failed with %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ ret = at76_wait_completion(priv, CMD_JOIN);
+ if (ret != CMD_STATUS_COMPLETE) {
+ if (ret != CMD_STATUS_TIME_OUT)
+ printk(KERN_ERR "%s: join_bss completed with %d\n",
+ priv->netdev->name, ret);
+ else
+ printk(KERN_INFO "%s: join_bss ssid %s timed out\n",
+ priv->netdev->name,
+ mac2str(priv->curr_bss->bssid));
+
+ /* retry next BSS immediately */
+ schedule_work(&priv->work_join);
+ goto exit;
+ }
+
+ /* here we have joined the (I)BSS */
+ if (priv->iw_mode == IW_MODE_ADHOC) {
+ struct bss_info *bptr = priv->curr_bss;
+ at76_set_mac_state(priv, MAC_CONNECTED);
+ /* get ESSID, BSSID and channel for priv->curr_bss */
+ priv->essid_size = bptr->ssid_len;
+ memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
+ memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
+ priv->channel = bptr->channel;
+ at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
+ netif_carrier_on(priv->netdev);
+ netif_start_queue(priv->netdev);
+ /* just to be sure */
+ cancel_delayed_work(&priv->dwork_get_scan);
+ cancel_delayed_work(&priv->dwork_auth);
+ cancel_delayed_work(&priv->dwork_assoc);
+ } else {
+ /* send auth req */
+ priv->retries = AUTH_RETRIES;
+ at76_set_mac_state(priv, MAC_AUTH);
+ at76_auth_req(priv, priv->curr_bss, 1, NULL);
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
+ schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
+ }
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Reap scan results */
+static void at76_dwork_get_scan(struct work_struct *work)
+{
+ int status;
+ int ret;
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_get_scan.work);
+
+ mutex_lock(&priv->mtx);
+ WARN_ON(priv->mac_state != MAC_SCANNING);
+ if (priv->mac_state != MAC_SCANNING)
+ goto exit;
+
+ status = at76_get_cmd_status(priv->udev, CMD_SCAN);
+ if (status < 0) {
+ printk(KERN_ERR "%s: %s: at76_get_cmd_status failed with %d\n",
+ priv->netdev->name, __func__, status);
+ status = CMD_STATUS_IN_PROGRESS;
+ /* INFO: Hope it was a one off error - if not, scanning
+ further down the line and stop this cycle */
+ }
+ at76_dbg(DBG_PROGRESS,
+ "%s %s: got cmd_status %d (state %s, need_any %d)",
+ priv->netdev->name, __func__, status,
+ mac_states[priv->mac_state], priv->scan_need_any);
+
+ if (status != CMD_STATUS_COMPLETE) {
+ if ((status != CMD_STATUS_IN_PROGRESS) &&
+ (status != CMD_STATUS_IDLE))
+ printk(KERN_ERR "%s: %s: Bad scan status: %s\n",
+ priv->netdev->name, __func__,
+ at76_get_cmd_status_string(status));
+
+ /* the first cmd status after scan start is always a IDLE ->
+ start the timer to poll again until COMPLETED */
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer for %d ticks",
+ __func__, __LINE__, SCAN_POLL_INTERVAL);
+ schedule_delayed_work(&priv->dwork_get_scan,
+ SCAN_POLL_INTERVAL);
+ goto exit;
+ }
+
+ if (at76_debug & DBG_BSS_TABLE)
+ at76_dump_bss_table(priv);
+
+ if (priv->scan_need_any) {
+ ret = at76_start_scan(priv, 0);
+ if (ret < 0)
+ printk(KERN_ERR
+ "%s: %s: start_scan (ANY) failed with %d\n",
+ priv->netdev->name, __func__, ret);
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer for %d ticks", __func__,
+ __LINE__, SCAN_POLL_INTERVAL);
+ schedule_delayed_work(&priv->dwork_get_scan,
+ SCAN_POLL_INTERVAL);
+ priv->scan_need_any = 0;
+ } else {
+ priv->scan_state = SCAN_COMPLETED;
+ /* report the end of scan to user space */
+ at76_iwevent_scan_complete(priv->netdev);
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ }
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Handle loss of beacons from the AP */
+static void at76_dwork_beacon(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_beacon.work);
+
+ mutex_lock(&priv->mtx);
+ if (priv->mac_state != MAC_CONNECTED || priv->iw_mode != IW_MODE_INFRA)
+ goto exit;
+
+ /* We haven't received any beacons from out AP for BEACON_TIMEOUT */
+ printk(KERN_INFO "%s: lost beacon bssid %s\n",
+ priv->netdev->name, mac2str(priv->curr_bss->bssid));
+
+ netif_carrier_off(priv->netdev);
+ netif_stop_queue(priv->netdev);
+ at76_iwevent_bss_disconnect(priv->netdev);
+ at76_set_mac_state(priv, MAC_SCANNING);
+ schedule_work(&priv->work_start_scan);
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Handle authentication response timeout */
+static void at76_dwork_auth(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_auth.work);
+
+ mutex_lock(&priv->mtx);
+ WARN_ON(priv->mac_state != MAC_AUTH);
+ if (priv->mac_state != MAC_AUTH)
+ goto exit;
+
+ at76_dbg(DBG_PROGRESS, "%s: authentication response timeout",
+ priv->netdev->name);
+
+ if (priv->retries-- >= 0) {
+ at76_auth_req(priv, priv->curr_bss, 1, NULL);
+ at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
+ __func__, __LINE__);
+ schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
+ } else {
+ /* try to get next matching BSS */
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ }
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Handle association response timeout */
+static void at76_dwork_assoc(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_assoc.work);
+
+ mutex_lock(&priv->mtx);
+ WARN_ON(priv->mac_state != MAC_ASSOC);
+ if (priv->mac_state != MAC_ASSOC)
+ goto exit;
+
+ at76_dbg(DBG_PROGRESS, "%s: association response timeout",
+ priv->netdev->name);
+
+ if (priv->retries-- >= 0) {
+ at76_assoc_req(priv, priv->curr_bss);
+ at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
+ __func__, __LINE__);
+ schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
+ } else {
+ /* try to get next matching BSS */
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ }
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Read new bssid in ad-hoc mode */
+static void at76_work_new_bss(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_new_bss);
+ int ret;
+ struct mib_mac_mgmt mac_mgmt;
+
+ mutex_lock(&priv->mtx);
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, &mac_mgmt,
+ sizeof(struct mib_mac_mgmt));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
+ priv->netdev->name, ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_PROGRESS, "ibss_change = 0x%2x", mac_mgmt.ibss_change);
+ memcpy(priv->bssid, mac_mgmt.current_bssid, ETH_ALEN);
+ at76_dbg(DBG_PROGRESS, "using BSSID %s", mac2str(priv->bssid));
+
+ at76_iwevent_bss_connect(priv->netdev, priv->bssid);
+
+ priv->mib_buf.type = MIB_MAC_MGMT;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
+ priv->mib_buf.data.byte = 0;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
+ priv->netdev->name, ret);
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+static int at76_startup_device(struct at76_priv *priv)
+{
+ struct at76_card_config *ccfg = &priv->card_config;
+ int ret;
+
+ at76_dbg(DBG_PARAMS,
+ "%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d "
+ "keylen %d", priv->netdev->name, priv->essid_size, priv->essid,
+ hex2str(priv->essid, IW_ESSID_MAX_SIZE),
+ priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
+ priv->channel, priv->wep_enabled ? "enabled" : "disabled",
+ priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);
+ at76_dbg(DBG_PARAMS,
+ "%s param: preamble %s rts %d retry %d frag %d "
+ "txrate %s auth_mode %d", priv->netdev->name,
+ preambles[priv->preamble_type], priv->rts_threshold,
+ priv->short_retry_limit, priv->frag_threshold,
+ priv->txrate == TX_RATE_1MBIT ? "1MBit" : priv->txrate ==
+ TX_RATE_2MBIT ? "2MBit" : priv->txrate ==
+ TX_RATE_5_5MBIT ? "5.5MBit" : priv->txrate ==
+ TX_RATE_11MBIT ? "11MBit" : priv->txrate ==
+ TX_RATE_AUTO ? "auto" : "<invalid>", priv->auth_mode);
+ at76_dbg(DBG_PARAMS,
+ "%s param: pm_mode %d pm_period %d auth_mode %s "
+ "scan_times %d %d scan_mode %s",
+ priv->netdev->name, priv->pm_mode, priv->pm_period,
+ priv->auth_mode == WLAN_AUTH_OPEN ? "open" : "shared_secret",
+ priv->scan_min_time, priv->scan_max_time,
+ priv->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive");
+
+ memset(ccfg, 0, sizeof(struct at76_card_config));
+ ccfg->promiscuous_mode = 0;
+ ccfg->short_retry_limit = priv->short_retry_limit;
+
+ if (priv->wep_enabled) {
+ if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN)
+ ccfg->encryption_type = 2;
+ else
+ ccfg->encryption_type = 1;
+
+ /* jal: always exclude unencrypted if WEP is active */
+ ccfg->exclude_unencrypted = 1;
+ } else {
+ ccfg->exclude_unencrypted = 0;
+ ccfg->encryption_type = 0;
+ }
+
+ ccfg->rts_threshold = cpu_to_le16(priv->rts_threshold);
+ ccfg->fragmentation_threshold = cpu_to_le16(priv->frag_threshold);
+
+ memcpy(ccfg->basic_rate_set, hw_rates, 4);
+ /* jal: really needed, we do a set_mib for autorate later ??? */
+ ccfg->auto_rate_fallback = (priv->txrate == TX_RATE_AUTO ? 1 : 0);
+ ccfg->channel = priv->channel;
+ ccfg->privacy_invoked = priv->wep_enabled;
+ memcpy(ccfg->current_ssid, priv->essid, IW_ESSID_MAX_SIZE);
+ ccfg->ssid_len = priv->essid_size;
+
+ ccfg->wep_default_key_id = priv->wep_key_id;
+ memcpy(ccfg->wep_default_key_value, priv->wep_keys, 4 * WEP_KEY_LEN);
+
+ ccfg->short_preamble = priv->preamble_type;
+ ccfg->beacon_period = cpu_to_le16(priv->beacon_period);
+
+ ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config,
+ sizeof(struct at76_card_config));
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
+ priv->netdev->name, ret);
+ return ret;
+ }
+
+ at76_wait_completion(priv, CMD_STARTUP);
+
+ /* remove BSSID from previous run */
+ memset(priv->bssid, 0, ETH_ALEN);
+
+ if (at76_set_radio(priv, 1) == 1)
+ at76_wait_completion(priv, CMD_RADIO_ON);
+
+ ret = at76_set_preamble(priv, priv->preamble_type);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_set_frag(priv, priv->frag_threshold);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_set_rts(priv, priv->rts_threshold);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_set_autorate_fallback(priv,
+ priv->txrate == TX_RATE_AUTO ? 1 : 0);
+ if (ret < 0)
+ return ret;
+
+ ret = at76_set_pm_mode(priv);
+ if (ret < 0)
+ return ret;
+
+ if (at76_debug & DBG_MIB) {
+ at76_dump_mib_mac(priv);
+ at76_dump_mib_mac_addr(priv);
+ at76_dump_mib_mac_mgmt(priv);
+ at76_dump_mib_mac_wep(priv);
+ at76_dump_mib_mdomain(priv);
+ at76_dump_mib_phy(priv);
+ at76_dump_mib_local(priv);
+ }
+
+ return 0;
+}
+
+/* Restart the interface */
+static void at76_dwork_restart(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_restart.work);
+
+ mutex_lock(&priv->mtx);
+
+ netif_carrier_off(priv->netdev); /* stop netdev watchdog */
+ netif_stop_queue(priv->netdev); /* stop tx data packets */
+
+ at76_startup_device(priv);
+
+ if (priv->iw_mode != IW_MODE_MONITOR) {
+ priv->netdev->type = ARPHRD_ETHER;
+ at76_set_mac_state(priv, MAC_SCANNING);
+ schedule_work(&priv->work_start_scan);
+ } else {
+ priv->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
+ at76_start_monitor(priv);
+ }
+
+ mutex_unlock(&priv->mtx);
+}
+
+/* Initiate scanning */
+static void at76_work_start_scan(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_start_scan);
+ int ret;
+
+ mutex_lock(&priv->mtx);
+
+ WARN_ON(priv->mac_state != MAC_SCANNING);
+ if (priv->mac_state != MAC_SCANNING)
+ goto exit;
+
+ /* only clear the bss list when a scan is actively initiated,
+ * otherwise simply rely on at76_bss_list_timeout */
+ if (priv->scan_state == SCAN_IN_PROGRESS) {
+ at76_free_bss_list(priv);
+ priv->scan_need_any = 1;
+ } else
+ priv->scan_need_any = 0;
+
+ ret = at76_start_scan(priv, 1);
+
+ if (ret < 0)
+ printk(KERN_ERR "%s: %s: start_scan failed with %d\n",
+ priv->netdev->name, __func__, ret);
+ else {
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer for %d ticks",
+ __func__, __LINE__, SCAN_POLL_INTERVAL);
+ schedule_delayed_work(&priv->dwork_get_scan,
+ SCAN_POLL_INTERVAL);
+ }
+
+exit:
+ mutex_unlock(&priv->mtx);
+}
+
+/* Enable or disable promiscuous mode */
+static void at76_work_set_promisc(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_set_promisc);
+ int ret = 0;
+
+ mutex_lock(&priv->mtx);
+
+ priv->mib_buf.type = MIB_LOCAL;
+ priv->mib_buf.size = 1;
+ priv->mib_buf.index = offsetof(struct mib_local, promiscuous_mode);
+ priv->mib_buf.data.byte = priv->promisc ? 1 : 0;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
+ priv->netdev->name, ret);
+
+ mutex_unlock(&priv->mtx);
+}
+
+/* Submit Rx urb back to the device */
+static void at76_work_submit_rx(struct work_struct *work)
+{
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ work_submit_rx);
+
+ mutex_lock(&priv->mtx);
+ at76_submit_rx_urb(priv);
+ mutex_unlock(&priv->mtx);
+}
+
+/* We got an association response */
+static void at76_rx_mgmt_assoc(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct ieee80211_assoc_response *resp =
+ (struct ieee80211_assoc_response *)buf->packet;
+ u16 assoc_id = le16_to_cpu(resp->aid);
+ u16 status = le16_to_cpu(resp->status);
+
+ at76_dbg(DBG_RX_MGMT, "%s: rx AssocResp bssid %s capa 0x%04x status "
+ "0x%04x assoc_id 0x%04x rates %s", priv->netdev->name,
+ mac2str(resp->header.addr3), le16_to_cpu(resp->capability),
+ status, assoc_id, hex2str(resp->info_element->data,
+ resp->info_element->len));
+
+ if (priv->mac_state != MAC_ASSOC) {
+ printk(KERN_INFO "%s: AssocResp in state %s ignored\n",
+ priv->netdev->name, mac_states[priv->mac_state]);
+ return;
+ }
+
+ BUG_ON(!priv->curr_bss);
+
+ cancel_delayed_work(&priv->dwork_assoc);
+ if (status == WLAN_STATUS_SUCCESS) {
+ struct bss_info *ptr = priv->curr_bss;
+ priv->assoc_id = assoc_id & 0x3fff;
+ /* update iwconfig params */
+ memcpy(priv->bssid, ptr->bssid, ETH_ALEN);
+ memcpy(priv->essid, ptr->ssid, ptr->ssid_len);
+ priv->essid_size = ptr->ssid_len;
+ priv->channel = ptr->channel;
+ schedule_work(&priv->work_assoc_done);
+ } else {
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ }
+}
+
+/* Process disassociation request from the AP */
+static void at76_rx_mgmt_disassoc(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct ieee80211_disassoc *resp =
+ (struct ieee80211_disassoc *)buf->packet;
+ struct ieee80211_hdr_3addr *mgmt = &resp->header;
+
+ at76_dbg(DBG_RX_MGMT,
+ "%s: rx DisAssoc bssid %s reason 0x%04x destination %s",
+ priv->netdev->name, mac2str(mgmt->addr3),
+ le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
+
+ /* We are not connected, ignore */
+ if (priv->mac_state == MAC_SCANNING || priv->mac_state == MAC_INIT
+ || !priv->curr_bss)
+ return;
+
+ /* Not our BSSID, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
+ return;
+
+ /* Not for our STA and not broadcast, ignore */
+ if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
+ && !is_broadcast_ether_addr(mgmt->addr1))
+ return;
+
+ if (priv->mac_state != MAC_ASSOC && priv->mac_state != MAC_CONNECTED
+ && priv->mac_state != MAC_JOINING) {
+ printk(KERN_INFO "%s: DisAssoc in state %s ignored\n",
+ priv->netdev->name, mac_states[priv->mac_state]);
+ return;
+ }
+
+ if (priv->mac_state == MAC_CONNECTED) {
+ netif_carrier_off(priv->netdev);
+ netif_stop_queue(priv->netdev);
+ at76_iwevent_bss_disconnect(priv->netdev);
+ }
+ cancel_delayed_work(&priv->dwork_get_scan);
+ cancel_delayed_work(&priv->dwork_beacon);
+ cancel_delayed_work(&priv->dwork_auth);
+ cancel_delayed_work(&priv->dwork_assoc);
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+}
+
+static void at76_rx_mgmt_auth(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct ieee80211_auth *resp = (struct ieee80211_auth *)buf->packet;
+ struct ieee80211_hdr_3addr *mgmt = &resp->header;
+ int seq_nr = le16_to_cpu(resp->transaction);
+ int alg = le16_to_cpu(resp->algorithm);
+ int status = le16_to_cpu(resp->status);
+
+ at76_dbg(DBG_RX_MGMT,
+ "%s: rx AuthFrame bssid %s alg %d seq_nr %d status %d "
+ "destination %s", priv->netdev->name, mac2str(mgmt->addr3),
+ alg, seq_nr, status, mac2str(mgmt->addr1));
+
+ if (alg == WLAN_AUTH_SHARED_KEY && seq_nr == 2)
+ at76_dbg(DBG_RX_MGMT, "%s: AuthFrame challenge %s ...",
+ priv->netdev->name, hex2str(resp->info_element, 18));
+
+ if (priv->mac_state != MAC_AUTH) {
+ printk(KERN_INFO "%s: ignored AuthFrame in state %s\n",
+ priv->netdev->name, mac_states[priv->mac_state]);
+ return;
+ }
+ if (priv->auth_mode != alg) {
+ printk(KERN_INFO "%s: ignored AuthFrame for alg %d\n",
+ priv->netdev->name, alg);
+ return;
+ }
+
+ BUG_ON(!priv->curr_bss);
+
+ /* Not our BSSID or not for our STA, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid)
+ || compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1))
+ return;
+
+ cancel_delayed_work(&priv->dwork_auth);
+ if (status != WLAN_STATUS_SUCCESS) {
+ /* try to join next bss */
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ return;
+ }
+
+ if (priv->auth_mode == WLAN_AUTH_OPEN || seq_nr == 4) {
+ priv->retries = ASSOC_RETRIES;
+ at76_set_mac_state(priv, MAC_ASSOC);
+ at76_assoc_req(priv, priv->curr_bss);
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
+ schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
+ return;
+ }
+
+ WARN_ON(seq_nr != 2);
+ at76_auth_req(priv, priv->curr_bss, seq_nr + 1, resp->info_element);
+ at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", __func__,
+ __LINE__);
+ schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
+}
+
+static void at76_rx_mgmt_deauth(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct ieee80211_disassoc *resp =
+ (struct ieee80211_disassoc *)buf->packet;
+ struct ieee80211_hdr_3addr *mgmt = &resp->header;
+
+ at76_dbg(DBG_RX_MGMT | DBG_PROGRESS,
+ "%s: rx DeAuth bssid %s reason 0x%04x destination %s",
+ priv->netdev->name, mac2str(mgmt->addr3),
+ le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
+
+ if (priv->mac_state != MAC_AUTH && priv->mac_state != MAC_ASSOC
+ && priv->mac_state != MAC_CONNECTED) {
+ printk(KERN_INFO "%s: DeAuth in state %s ignored\n",
+ priv->netdev->name, mac_states[priv->mac_state]);
+ return;
+ }
+
+ BUG_ON(!priv->curr_bss);
+
+ /* Not our BSSID, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
+ return;
+
+ /* Not for our STA and not broadcast, ignore */
+ if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
+ && !is_broadcast_ether_addr(mgmt->addr1))
+ return;
+
+ if (priv->mac_state == MAC_CONNECTED)
+ at76_iwevent_bss_disconnect(priv->netdev);
+
+ at76_set_mac_state(priv, MAC_JOINING);
+ schedule_work(&priv->work_join);
+ cancel_delayed_work(&priv->dwork_get_scan);
+ cancel_delayed_work(&priv->dwork_beacon);
+ cancel_delayed_work(&priv->dwork_auth);
+ cancel_delayed_work(&priv->dwork_assoc);
+}
+
+static void at76_rx_mgmt_beacon(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ int varpar_len;
+ /* beacon content */
+ struct ieee80211_beacon *bdata = (struct ieee80211_beacon *)buf->packet;
+ struct ieee80211_hdr_3addr *mgmt = &bdata->header;
+
+ struct list_head *lptr;
+ struct bss_info *match; /* entry matching addr3 with its bssid */
+ int new_entry = 0;
+ int len;
+ struct ieee80211_info_element *ie;
+ int have_ssid = 0;
+ int have_rates = 0;
+ int have_channel = 0;
+ int keep_going = 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+ if (priv->mac_state == MAC_CONNECTED) {
+ /* in state MAC_CONNECTED we use the mgmt_timer to control
+ the beacon of the BSS */
+ BUG_ON(!priv->curr_bss);
+
+ if (!compare_ether_addr(priv->curr_bss->bssid, mgmt->addr3)) {
+ /* We got our AP's beacon, defer the timeout handler.
+ Kill pending work first, as schedule_delayed_work()
+ won't do it. */
+ cancel_delayed_work(&priv->dwork_beacon);
+ schedule_delayed_work(&priv->dwork_beacon,
+ BEACON_TIMEOUT);
+ priv->curr_bss->rssi = buf->rssi;
+ priv->beacons_received++;
+ goto exit;
+ }
+ }
+
+ /* look if we have this BSS already in the list */
+ match = NULL;
+
+ if (!list_empty(&priv->bss_list)) {
+ list_for_each(lptr, &priv->bss_list) {
+ struct bss_info *bss_ptr =
+ list_entry(lptr, struct bss_info, list);
+ if (!compare_ether_addr(bss_ptr->bssid, mgmt->addr3)) {
+ match = bss_ptr;
+ break;
+ }
+ }
+ }
+
+ if (!match) {
+ /* BSS not in the list - append it */
+ match = kzalloc(sizeof(struct bss_info), GFP_ATOMIC);
+ if (!match) {
+ at76_dbg(DBG_BSS_TABLE,
+ "%s: cannot kmalloc new bss info (%zd byte)",
+ priv->netdev->name, sizeof(struct bss_info));
+ goto exit;
+ }
+ new_entry = 1;
+ list_add_tail(&match->list, &priv->bss_list);
+ }
+
+ match->capa = le16_to_cpu(bdata->capability);
+ match->beacon_interval = le16_to_cpu(bdata->beacon_interval);
+ match->rssi = buf->rssi;
+ match->link_qual = buf->link_quality;
+ match->noise_level = buf->noise_level;
+ memcpy(match->bssid, mgmt->addr3, ETH_ALEN);
+ at76_dbg(DBG_RX_BEACON, "%s: bssid %s", priv->netdev->name,
+ mac2str(match->bssid));
+
+ ie = bdata->info_element;
+
+ /* length of var length beacon parameters */
+ varpar_len = min_t(int, le16_to_cpu(buf->wlength) -
+ sizeof(struct ieee80211_beacon),
+ BEACON_MAX_DATA_LENGTH);
+
+ /* This routine steps through the bdata->data array to get
+ * some useful information about the access point.
+ * Currently, this implementation supports receipt of: SSID,
+ * supported transfer rates and channel, in any order, with some
+ * tolerance for intermittent unknown codes (although this
+ * functionality may not be necessary as the useful information will
+ * usually arrive in consecutively, but there have been some
+ * reports of some of the useful information fields arriving in a
+ * different order).
+ * It does not support any more IE types although MFIE_TYPE_TIM may
+ * be supported (on my AP at least).
+ * The bdata->data array is about 1500 bytes long but only ~36 of those
+ * bytes are useful, hence the have_ssid etc optimizations. */
+
+ while (keep_going &&
+ ((&ie->data[ie->len] - (u8 *)bdata->info_element) <=
+ varpar_len)) {
+
+ switch (ie->id) {
+
+ case MFIE_TYPE_SSID:
+ if (have_ssid)
+ break;
+
+ len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
+
+ /* we copy only if this is a new entry,
+ or the incoming SSID is not a hidden SSID. This
+ will protect us from overwriting a real SSID read
+ in a ProbeResponse with a hidden one from a
+ following beacon. */
+ if (!new_entry && at76_is_hidden_ssid(ie->data, len)) {
+ have_ssid = 1;
+ break;
+ }
+
+ match->ssid_len = len;
+ memcpy(match->ssid, ie->data, len);
+ at76_dbg(DBG_RX_BEACON, "%s: SSID - %.*s",
+ priv->netdev->name, len, match->ssid);
+ have_ssid = 1;
+ break;
+
+ case MFIE_TYPE_RATES:
+ if (have_rates)
+ break;
+
+ match->rates_len =
+ min_t(int, sizeof(match->rates), ie->len);
+ memcpy(match->rates, ie->data, match->rates_len);
+ have_rates = 1;
+ at76_dbg(DBG_RX_BEACON, "%s: SUPPORTED RATES %s",
+ priv->netdev->name,
+ hex2str(ie->data, ie->len));
+ break;
+
+ case MFIE_TYPE_DS_SET:
+ if (have_channel)
+ break;
+
+ match->channel = ie->data[0];
+ have_channel = 1;
+ at76_dbg(DBG_RX_BEACON, "%s: CHANNEL - %d",
+ priv->netdev->name, match->channel);
+ break;
+
+ case MFIE_TYPE_CF_SET:
+ case MFIE_TYPE_TIM:
+ case MFIE_TYPE_IBSS_SET:
+ default:
+ at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
+ priv->netdev->name, ie->id, ie->len,
+ hex2str(ie->data, ie->len));
+ break;
+ }
+
+ /* advance to the next informational element */
+ next_ie(&ie);
+
+ /* Optimization: after all, the bdata->data array is
+ * varpar_len bytes long, whereas we get all of the useful
+ * information after only ~36 bytes, this saves us a lot of
+ * time (and trouble as the remaining portion of the array
+ * could be full of junk)
+ * Comment this out if you want to see what other information
+ * comes from the AP - although little of it may be useful */
+ }
+
+ at76_dbg(DBG_RX_BEACON, "%s: Finished processing beacon data",
+ priv->netdev->name);
+
+ match->last_rx = jiffies; /* record last rx of beacon */
+
+exit:
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+}
+
+/* Calculate the link level from a given rx_buffer */
+static void at76_calc_level(struct at76_priv *priv, struct at76_rx_buffer *buf,
+ struct iw_quality *qual)
+{
+ /* just a guess for now, might be different for other chips */
+ int max_rssi = 42;
+
+ qual->level = (buf->rssi * 100 / max_rssi);
+ if (qual->level > 100)
+ qual->level = 100;
+ qual->updated |= IW_QUAL_LEVEL_UPDATED;
+}
+
+/* Calculate the link quality from a given rx_buffer */
+static void at76_calc_qual(struct at76_priv *priv, struct at76_rx_buffer *buf,
+ struct iw_quality *qual)
+{
+ if (at76_is_intersil(priv->board_type))
+ qual->qual = buf->link_quality;
+ else {
+ unsigned long elapsed;
+
+ /* Update qual at most once a second */
+ elapsed = jiffies - priv->beacons_last_qual;
+ if (elapsed < 1 * HZ)
+ return;
+
+ qual->qual = qual->level * priv->beacons_received *
+ msecs_to_jiffies(priv->beacon_period) / elapsed;
+
+ priv->beacons_last_qual = jiffies;
+ priv->beacons_received = 0;
+ }
+ qual->qual = (qual->qual > 100) ? 100 : qual->qual;
+ qual->updated |= IW_QUAL_QUAL_UPDATED;
+}
+
+/* Calculate the noise quality from a given rx_buffer */
+static void at76_calc_noise(struct at76_priv *priv, struct at76_rx_buffer *buf,
+ struct iw_quality *qual)
+{
+ qual->noise = 0;
+ qual->updated |= IW_QUAL_NOISE_INVALID;
+}
+
+static void at76_update_wstats(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct iw_quality *qual = &priv->wstats.qual;
+
+ if (buf->rssi && priv->mac_state == MAC_CONNECTED) {
+ qual->updated = 0;
+ at76_calc_level(priv, buf, qual);
+ at76_calc_qual(priv, buf, qual);
+ at76_calc_noise(priv, buf, qual);
+ } else {
+ qual->qual = 0;
+ qual->level = 0;
+ qual->noise = 0;
+ qual->updated = IW_QUAL_ALL_INVALID;
+ }
+}
+
+static void at76_rx_mgmt(struct at76_priv *priv, struct at76_rx_buffer *buf)
+{
+ struct ieee80211_hdr_3addr *mgmt =
+ (struct ieee80211_hdr_3addr *)buf->packet;
+ u16 framectl = le16_to_cpu(mgmt->frame_ctl);
+
+ /* update wstats */
+ if (priv->mac_state != MAC_INIT && priv->mac_state != MAC_SCANNING) {
+ /* jal: this is a dirty hack needed by Tim in ad-hoc mode */
+ /* Data packets always seem to have a 0 link level, so we
+ only read link quality info from management packets.
+ Atmel driver actually averages the present, and previous
+ values, we just present the raw value at the moment - TJS */
+ if (priv->iw_mode == IW_MODE_ADHOC
+ || (priv->curr_bss
+ && !compare_ether_addr(mgmt->addr3,
+ priv->curr_bss->bssid)))
+ at76_update_wstats(priv, buf);
+ }
+
+ at76_dbg(DBG_RX_MGMT_CONTENT, "%s rx mgmt framectl 0x%x %s",
+ priv->netdev->name, framectl,
+ hex2str(mgmt, le16_to_cpu(buf->wlength)));
+
+ switch (framectl & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_BEACON:
+ case IEEE80211_STYPE_PROBE_RESP:
+ at76_rx_mgmt_beacon(priv, buf);
+ break;
+
+ case IEEE80211_STYPE_ASSOC_RESP:
+ at76_rx_mgmt_assoc(priv, buf);
+ break;
+
+ case IEEE80211_STYPE_DISASSOC:
+ at76_rx_mgmt_disassoc(priv, buf);
+ break;
+
+ case IEEE80211_STYPE_AUTH:
+ at76_rx_mgmt_auth(priv, buf);
+ break;
+
+ case IEEE80211_STYPE_DEAUTH:
+ at76_rx_mgmt_deauth(priv, buf);
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
+ priv->netdev->name, framectl);
+ }
+
+ return;
+}
+
+/* Convert the 802.11 header into an ethernet-style header, make skb
+ * ready for consumption by netif_rx() */
+static void at76_ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
+{
+ struct ieee80211_hdr_3addr *i802_11_hdr;
+ struct ethhdr *eth_hdr_p;
+ u8 *src_addr;
+ u8 *dest_addr;
+
+ i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
+
+ /* That would be the ethernet header if the hardware converted
+ * the frame for us. Make sure the source and the destination
+ * match the 802.11 header. Which hardware does it? */
+ eth_hdr_p = (struct ethhdr *)skb_pull(skb, IEEE80211_3ADDR_LEN);
+
+ dest_addr = i802_11_hdr->addr1;
+ if (iw_mode == IW_MODE_ADHOC)
+ src_addr = i802_11_hdr->addr2;
+ else
+ src_addr = i802_11_hdr->addr3;
+
+ if (!compare_ether_addr(eth_hdr_p->h_source, src_addr) &&
+ !compare_ether_addr(eth_hdr_p->h_dest, dest_addr))
+ /* Yes, we already have an ethernet header */
+ skb_reset_mac_header(skb);
+ else {
+ u16 len;
+
+ /* Need to build an ethernet header */
+ if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
+ /* SNAP frame - decapsulate, keep proto */
+ skb_push(skb, offsetof(struct ethhdr, h_proto) -
+ sizeof(rfc1042sig));
+ len = 0;
+ } else {
+ /* 802.3 frame, proto is length */
+ len = skb->len;
+ skb_push(skb, ETH_HLEN);
+ }
+
+ skb_reset_mac_header(skb);
+ eth_hdr_p = eth_hdr(skb);
+ /* This needs to be done in this order (eth_hdr_p->h_dest may
+ * overlap src_addr) */
+ memcpy(eth_hdr_p->h_source, src_addr, ETH_ALEN);
+ memcpy(eth_hdr_p->h_dest, dest_addr, ETH_ALEN);
+ if (len)
+ eth_hdr_p->h_proto = htons(len);
+ }
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+}
+
+/* Check for fragmented data in priv->rx_skb. If the packet was no fragment
+ or it was the last of a fragment set a skb containing the whole packet
+ is returned for further processing. Otherwise we get NULL and are
+ done and the packet is either stored inside the fragment buffer
+ or thrown away. Every returned skb starts with the ieee802_11 header
+ and contains _no_ FCS at the end */
+static struct sk_buff *at76_check_for_rx_frags(struct at76_priv *priv)
+{
+ struct sk_buff *skb = priv->rx_skb;
+ struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
+ struct ieee80211_hdr_3addr *i802_11_hdr =
+ (struct ieee80211_hdr_3addr *)buf->packet;
+ /* seq_ctrl, fragment_number, sequence number of new packet */
+ u16 sctl = le16_to_cpu(i802_11_hdr->seq_ctl);
+ u16 fragnr = sctl & 0xf;
+ u16 seqnr = sctl >> 4;
+ u16 frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
+
+ /* Length including the IEEE802.11 header, but without the trailing
+ * FCS and without the Atmel Rx header */
+ int length = le16_to_cpu(buf->wlength) - IEEE80211_FCS_LEN;
+
+ /* where does the data payload start in skb->data ? */
+ u8 *data = i802_11_hdr->payload;
+
+ /* length of payload, excl. the trailing FCS */
+ int data_len = length - IEEE80211_3ADDR_LEN;
+
+ int i;
+ struct rx_data_buf *bptr, *optr;
+ unsigned long oldest = ~0UL;
+
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: rx data frame_ctl %04x addr2 %s seq/frag %d/%d "
+ "length %d data %d: %s ...", priv->netdev->name, frame_ctl,
+ mac2str(i802_11_hdr->addr2), seqnr, fragnr, length, data_len,
+ hex2str(data, 32));
+
+ at76_dbg(DBG_RX_FRAGS_SKB, "%s: incoming skb: head %p data %p "
+ "tail %p end %p len %d", priv->netdev->name, skb->head,
+ skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
+ skb->len);
+
+ if (data_len < 0) {
+ /* make sure data starts in the buffer */
+ printk(KERN_INFO "%s: data frame too short\n",
+ priv->netdev->name);
+ return NULL;
+ }
+
+ WARN_ON(length <= AT76_RX_HDRLEN);
+ if (length <= AT76_RX_HDRLEN)
+ return NULL;
+
+ /* remove the at76_rx_buffer header - we don't need it anymore */
+ /* we need the IEEE802.11 header (for the addresses) if this packet
+ is the first of a chain */
+ skb_pull(skb, AT76_RX_HDRLEN);
+
+ /* remove FCS at end */
+ skb_trim(skb, length);
+
+ at76_dbg(DBG_RX_FRAGS_SKB, "%s: trimmed skb: head %p data %p tail %p "
+ "end %p len %d data %p data_len %d", priv->netdev->name,
+ skb->head, skb->data, skb_tail_pointer(skb),
+ skb_end_pointer(skb), skb->len, data, data_len);
+
+ if (fragnr == 0 && !(frame_ctl & IEEE80211_FCTL_MOREFRAGS)) {
+ /* unfragmented packet received */
+ /* Use a new skb for the next receive */
+ priv->rx_skb = NULL;
+ at76_dbg(DBG_RX_FRAGS, "%s: unfragmented", priv->netdev->name);
+ return skb;
+ }
+
+ /* look if we've got a chain for the sender address.
+ afterwards optr points to first free or the oldest entry,
+ or, if i < NR_RX_DATA_BUF, bptr points to the entry for the
+ sender address */
+ /* determining the oldest entry doesn't cope with jiffies wrapping
+ but I don't care to delete a young entry at these rare moments ... */
+
+ bptr = priv->rx_data;
+ optr = NULL;
+ for (i = 0; i < NR_RX_DATA_BUF; i++, bptr++) {
+ if (!bptr->skb) {
+ optr = bptr;
+ oldest = 0UL;
+ continue;
+ }
+
+ if (!compare_ether_addr(i802_11_hdr->addr2, bptr->sender))
+ break;
+
+ if (!optr) {
+ optr = bptr;
+ oldest = bptr->last_rx;
+ } else if (bptr->last_rx < oldest)
+ optr = bptr;
+ }
+
+ if (i < NR_RX_DATA_BUF) {
+
+ at76_dbg(DBG_RX_FRAGS, "%s: %d. cacheentry (seq/frag = %d/%d) "
+ "matched sender addr",
+ priv->netdev->name, i, bptr->seqnr, bptr->fragnr);
+
+ /* bptr points to an entry for the sender address */
+ if (bptr->seqnr == seqnr) {
+ int left;
+ /* the fragment has the current sequence number */
+ if (((bptr->fragnr + 1) & 0xf) != fragnr) {
+ /* wrong fragment number -> ignore it */
+ /* is & 0xf necessary above ??? */
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: frag nr mismatch: %d + 1 != %d",
+ priv->netdev->name, bptr->fragnr,
+ fragnr);
+ return NULL;
+ }
+ bptr->last_rx = jiffies;
+ /* the next following fragment number ->
+ add the data at the end */
+
+ /* for test only ??? */
+ left = skb_tailroom(bptr->skb);
+ if (left < data_len)
+ printk(KERN_INFO
+ "%s: only %d byte free (need %d)\n",
+ priv->netdev->name, left, data_len);
+ else
+ memcpy(skb_put(bptr->skb, data_len), data,
+ data_len);
+
+ bptr->fragnr = fragnr;
+ if (frame_ctl & IEEE80211_FCTL_MOREFRAGS)
+ return NULL;
+
+ /* this was the last fragment - send it */
+ skb = bptr->skb;
+ bptr->skb = NULL; /* free the entry */
+ at76_dbg(DBG_RX_FRAGS, "%s: last frag of seq %d",
+ priv->netdev->name, seqnr);
+ return skb;
+ }
+
+ /* got another sequence number */
+ if (fragnr == 0) {
+ /* it's the start of a new chain - replace the
+ old one by this */
+ /* bptr->sender has the correct value already */
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: start of new seq %d, removing old seq %d",
+ priv->netdev->name, seqnr, bptr->seqnr);
+ bptr->seqnr = seqnr;
+ bptr->fragnr = 0;
+ bptr->last_rx = jiffies;
+ /* swap bptr->skb and priv->rx_skb */
+ skb = bptr->skb;
+ bptr->skb = priv->rx_skb;
+ priv->rx_skb = skb;
+ } else {
+ /* it from the middle of a new chain ->
+ delete the old entry and skip the new one */
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: middle of new seq %d (%d) "
+ "removing old seq %d",
+ priv->netdev->name, seqnr, fragnr,
+ bptr->seqnr);
+ dev_kfree_skb(bptr->skb);
+ bptr->skb = NULL;
+ }
+ return NULL;
+ }
+
+ /* if we didn't find a chain for the sender address, optr
+ points either to the first free or the oldest entry */
+
+ if (fragnr != 0) {
+ /* this is not the begin of a fragment chain ... */
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: no chain for non-first fragment (%d)",
+ priv->netdev->name, fragnr);
+ return NULL;
+ }
+
+ BUG_ON(!optr);
+ if (optr->skb) {
+ /* swap the skb's */
+ skb = optr->skb;
+ optr->skb = priv->rx_skb;
+ priv->rx_skb = skb;
+
+ at76_dbg(DBG_RX_FRAGS,
+ "%s: free old contents: sender %s seq/frag %d/%d",
+ priv->netdev->name, mac2str(optr->sender),
+ optr->seqnr, optr->fragnr);
+
+ } else {
+ /* take the skb from priv->rx_skb */
+ optr->skb = priv->rx_skb;
+ /* let at76_submit_rx_urb() allocate a new skb */
+ priv->rx_skb = NULL;
+
+ at76_dbg(DBG_RX_FRAGS, "%s: use a free entry",
+ priv->netdev->name);
+ }
+ memcpy(optr->sender, i802_11_hdr->addr2, ETH_ALEN);
+ optr->seqnr = seqnr;
+ optr->fragnr = 0;
+ optr->last_rx = jiffies;
+
+ return NULL;
+}
+
+/* Rx interrupt: we expect the complete data buffer in priv->rx_skb */
+static void at76_rx_data(struct at76_priv *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct net_device_stats *stats = &priv->stats;
+ struct sk_buff *skb = priv->rx_skb;
+ struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
+ struct ieee80211_hdr_3addr *i802_11_hdr;
+ int length = le16_to_cpu(buf->wlength);
+
+ at76_dbg(DBG_RX_DATA, "%s received data packet: %s", netdev->name,
+ hex2str(skb->data, AT76_RX_HDRLEN));
+
+ at76_dbg(DBG_RX_DATA_CONTENT, "rx packet: %s",
+ hex2str(skb->data + AT76_RX_HDRLEN, length));
+
+ skb = at76_check_for_rx_frags(priv);
+ if (!skb)
+ return;
+
+ /* Atmel header and the FCS are already removed */
+ i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
+
+ skb->dev = netdev;
+ skb->ip_summed = CHECKSUM_NONE; /* TODO: should check CRC */
+
+ if (is_broadcast_ether_addr(i802_11_hdr->addr1)) {
+ if (!compare_ether_addr(i802_11_hdr->addr1, netdev->broadcast))
+ skb->pkt_type = PACKET_BROADCAST;
+ else
+ skb->pkt_type = PACKET_MULTICAST;
+ } else if (compare_ether_addr(i802_11_hdr->addr1, netdev->dev_addr))
+ skb->pkt_type = PACKET_OTHERHOST;
+
+ at76_ieee80211_to_eth(skb, priv->iw_mode);
+
+ netdev->last_rx = jiffies;
+ netif_rx(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += length;
+
+ return;
+}
+
+static void at76_rx_monitor_mode(struct at76_priv *priv)
+{
+ struct at76_rx_radiotap *rt;
+ u8 *payload;
+ int skblen;
+ struct net_device *netdev = priv->netdev;
+ struct at76_rx_buffer *buf =
+ (struct at76_rx_buffer *)priv->rx_skb->data;
+ /* length including the IEEE802.11 header and the trailing FCS,
+ but not at76_rx_buffer */
+ int length = le16_to_cpu(buf->wlength);
+ struct sk_buff *skb = priv->rx_skb;
+ struct net_device_stats *stats = &priv->stats;
+
+ if (length < IEEE80211_FCS_LEN) {
+ /* buffer contains no data */
+ at76_dbg(DBG_MONITOR_MODE,
+ "%s: MONITOR MODE: rx skb without data",
+ priv->netdev->name);
+ return;
+ }
+
+ skblen = sizeof(struct at76_rx_radiotap) + length;
+
+ skb = dev_alloc_skb(skblen);
+ if (!skb) {
+ printk(KERN_ERR "%s: MONITOR MODE: dev_alloc_skb for radiotap "
+ "header returned NULL\n", priv->netdev->name);
+ return;
+ }
+
+ skb_put(skb, skblen);
+
+ rt = (struct at76_rx_radiotap *)skb->data;
+ payload = skb->data + sizeof(struct at76_rx_radiotap);
+
+ rt->rt_hdr.it_version = 0;
+ rt->rt_hdr.it_pad = 0;
+ rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct at76_rx_radiotap));
+ rt->rt_hdr.it_present = cpu_to_le32(AT76_RX_RADIOTAP_PRESENT);
+
+ rt->rt_tsft = cpu_to_le64(le32_to_cpu(buf->rx_time));
+ rt->rt_rate = hw_rates[buf->rx_rate] & (~0x80);
+ rt->rt_signal = buf->rssi;
+ rt->rt_noise = buf->noise_level;
+ rt->rt_flags = IEEE80211_RADIOTAP_F_FCS;
+ if (buf->fragmentation)
+ rt->rt_flags |= IEEE80211_RADIOTAP_F_FRAG;
+
+ memcpy(payload, buf->packet, length);
+ skb->dev = netdev;
+ skb->ip_summed = CHECKSUM_NONE;
+ skb_reset_mac_header(skb);
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_802_2);
+
+ netdev->last_rx = jiffies;
+ netif_rx(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += length;
+}
+
+/* Check if we spy on the sender address in buf and update stats */
+static void at76_iwspy_update(struct at76_priv *priv,
+ struct at76_rx_buffer *buf)
+{
+ struct ieee80211_hdr_3addr *hdr =
+ (struct ieee80211_hdr_3addr *)buf->packet;
+ struct iw_quality qual;
+
+ /* We can only set the level here */
+ qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;
+ qual.level = 0;
+ qual.noise = 0;
+ at76_calc_level(priv, buf, &qual);
+
+ spin_lock_bh(&priv->spy_spinlock);
+
+ if (priv->spy_data.spy_number > 0)
+ wireless_spy_update(priv->netdev, hdr->addr2, &qual);
+
+ spin_unlock_bh(&priv->spy_spinlock);
+}
+
+static void at76_rx_tasklet(unsigned long param)
+{
+ struct urb *urb = (struct urb *)param;
+ struct at76_priv *priv = urb->context;
+ struct net_device *netdev = priv->netdev;
+ struct at76_rx_buffer *buf;
+ struct ieee80211_hdr_3addr *i802_11_hdr;
+ u16 frame_ctl;
+
+ if (priv->device_unplugged) {
+ at76_dbg(DBG_DEVSTART, "device unplugged");
+ if (urb)
+ at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
+ return;
+ }
+
+ if (!priv->rx_skb || !netdev || !priv->rx_skb->data)
+ return;
+
+ buf = (struct at76_rx_buffer *)priv->rx_skb->data;
+
+ i802_11_hdr = (struct ieee80211_hdr_3addr *)buf->packet;
+
+ frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
+
+ if (urb->status != 0) {
+ if (urb->status != -ENOENT && urb->status != -ECONNRESET)
+ at76_dbg(DBG_URB,
+ "%s %s: - nonzero Rx bulk status received: %d",
+ __func__, netdev->name, urb->status);
+ return;
+ }
+
+ at76_dbg(DBG_RX_ATMEL_HDR,
+ "%s: rx frame: rate %d rssi %d noise %d link %d %s",
+ priv->netdev->name, buf->rx_rate, buf->rssi, buf->noise_level,
+ buf->link_quality, hex2str(i802_11_hdr, 48));
+ if (priv->iw_mode == IW_MODE_MONITOR) {
+ at76_rx_monitor_mode(priv);
+ goto exit;
+ }
+
+ /* there is a new bssid around, accept it: */
+ if (buf->newbss && priv->iw_mode == IW_MODE_ADHOC) {
+ at76_dbg(DBG_PROGRESS, "%s: rx newbss", netdev->name);
+ schedule_work(&priv->work_new_bss);
+ }
+
+ switch (frame_ctl & IEEE80211_FCTL_FTYPE) {
+ case IEEE80211_FTYPE_DATA:
+ at76_rx_data(priv);
+ break;
+
+ case IEEE80211_FTYPE_MGMT:
+ /* jal: TODO: find out if we can update iwspy also on
+ other frames than management (might depend on the
+ radio chip / firmware version !) */
+
+ at76_iwspy_update(priv, buf);
+
+ at76_rx_mgmt(priv, buf);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+ at76_dbg(DBG_RX_CTRL, "%s: ignored ctrl frame: %04x",
+ priv->netdev->name, frame_ctl);
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
+ priv->netdev->name, frame_ctl);
+ }
+exit:
+ at76_submit_rx_urb(priv);
+}
+
+/* Load firmware into kernel memory and parse it */
+static struct fwentry *at76_load_firmware(struct usb_device *udev,
+ enum board_type board_type)
+{
+ int ret;
+ char *str;
+ struct at76_fw_header *fwh;
+ struct fwentry *fwe = &firmwares[board_type];
+
+ mutex_lock(&fw_mutex);
+
+ if (fwe->loaded) {
+ at76_dbg(DBG_FW, "re-using previously loaded fw");
+ goto exit;
+ }
+
+ at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
+ ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
+ fwe->fwname);
+ dev_printk(KERN_ERR, &udev->dev,
+ "you may need to download the firmware from "
+ "http://developer.berlios.de/projects/at76c503a/");
+ goto exit;
+ }
+
+ at76_dbg(DBG_FW, "got it.");
+ fwh = (struct at76_fw_header *)(fwe->fw->data);
+
+ if (fwe->fw->size <= sizeof(*fwh)) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "firmware is too short (0x%zx)\n", fwe->fw->size);
+ goto exit;
+ }
+
+ /* CRC currently not checked */
+ fwe->board_type = le32_to_cpu(fwh->board_type);
+ if (fwe->board_type != board_type) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "board type mismatch, requested %u, got %u\n",
+ board_type, fwe->board_type);
+ goto exit;
+ }
+
+ fwe->fw_version.major = fwh->major;
+ fwe->fw_version.minor = fwh->minor;
+ fwe->fw_version.patch = fwh->patch;
+ fwe->fw_version.build = fwh->build;
+
+ str = (char *)fwh + le32_to_cpu(fwh->str_offset);
+ fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset);
+ fwe->intfw_size = le32_to_cpu(fwh->int_fw_len);
+ fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset);
+ fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len);
+
+ fwe->loaded = 1;
+
+ dev_printk(KERN_DEBUG, &udev->dev,
+ "using firmware %s (version %d.%d.%d-%d)\n",
+ fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build);
+
+ at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type,
+ le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len),
+ le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len));
+ at76_dbg(DBG_DEVSTART, "firmware id %s", str);
+
+exit:
+ mutex_unlock(&fw_mutex);
+
+ if (fwe->loaded)
+ return fwe;
+ else
+ return NULL;
+}
+
+/* Allocate network device and initialize private data */
+static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
+{
+ struct net_device *netdev;
+ struct at76_priv *priv;
+ int i;
+
+ /* allocate memory for our device state and initialize it */
+ netdev = alloc_etherdev(sizeof(struct at76_priv));
+ if (!netdev) {
+ dev_printk(KERN_ERR, &udev->dev, "out of memory\n");
+ return NULL;
+ }
+
+ priv = netdev_priv(netdev);
+
+ priv->udev = udev;
+ priv->netdev = netdev;
+
+ mutex_init(&priv->mtx);
+ INIT_WORK(&priv->work_assoc_done, at76_work_assoc_done);
+ INIT_WORK(&priv->work_join, at76_work_join);
+ INIT_WORK(&priv->work_new_bss, at76_work_new_bss);
+ INIT_WORK(&priv->work_start_scan, at76_work_start_scan);
+ INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
+ INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
+ INIT_DELAYED_WORK(&priv->dwork_restart, at76_dwork_restart);
+ INIT_DELAYED_WORK(&priv->dwork_get_scan, at76_dwork_get_scan);
+ INIT_DELAYED_WORK(&priv->dwork_beacon, at76_dwork_beacon);
+ INIT_DELAYED_WORK(&priv->dwork_auth, at76_dwork_auth);
+ INIT_DELAYED_WORK(&priv->dwork_assoc, at76_dwork_assoc);
+
+ spin_lock_init(&priv->mgmt_spinlock);
+ priv->next_mgmt_bulk = NULL;
+ priv->mac_state = MAC_INIT;
+
+ /* initialize empty BSS list */
+ priv->curr_bss = NULL;
+ INIT_LIST_HEAD(&priv->bss_list);
+ spin_lock_init(&priv->bss_list_spinlock);
+
+ init_timer(&priv->bss_list_timer);
+ priv->bss_list_timer.data = (unsigned long)priv;
+ priv->bss_list_timer.function = at76_bss_list_timeout;
+
+ spin_lock_init(&priv->spy_spinlock);
+
+ /* mark all rx data entries as unused */
+ for (i = 0; i < NR_RX_DATA_BUF; i++)
+ priv->rx_data[i].skb = NULL;
+
+ priv->rx_tasklet.func = at76_rx_tasklet;
+ priv->rx_tasklet.data = 0;
+
+ priv->pm_mode = AT76_PM_OFF;
+ priv->pm_period = 0;
+
+ return priv;
+}
+
+static int at76_alloc_urbs(struct at76_priv *priv,
+ struct usb_interface *interface)
+{
+ struct usb_endpoint_descriptor *endpoint, *ep_in, *ep_out;
+ int i;
+ int buffer_size;
+ struct usb_host_interface *iface_desc;
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
+
+ at76_dbg(DBG_URB, "%s: NumEndpoints %d ", __func__,
+ interface->altsetting[0].desc.bNumEndpoints);
+
+ ep_in = NULL;
+ ep_out = NULL;
+ iface_desc = interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ at76_dbg(DBG_URB, "%s: %d. endpoint: addr 0x%x attr 0x%x",
+ __func__, i, endpoint->bEndpointAddress,
+ endpoint->bmAttributes);
+
+ if (!ep_in && usb_endpoint_is_bulk_in(endpoint))
+ ep_in = endpoint;
+
+ if (!ep_out && usb_endpoint_is_bulk_out(endpoint))
+ ep_out = endpoint;
+ }
+
+ if (!ep_in || !ep_out) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "bulk endpoints missing\n");
+ return -ENXIO;
+ }
+
+ priv->rx_pipe = usb_rcvbulkpipe(priv->udev, ep_in->bEndpointAddress);
+ priv->tx_pipe = usb_sndbulkpipe(priv->udev, ep_out->bEndpointAddress);
+
+ priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!priv->rx_urb || !priv->tx_urb) {
+ dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
+ return -ENOMEM;
+ }
+
+ buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
+ priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!priv->bulk_out_buffer) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "cannot allocate output buffer\n");
+ return -ENOMEM;
+ }
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
+
+ return 0;
+}
+
+/* Register network device and initialize the hardware */
+static int at76_init_new_device(struct at76_priv *priv,
+ struct usb_interface *interface)
+{
+ struct net_device *netdev = priv->netdev;
+ int ret;
+
+ /* set up the endpoint information */
+ /* check out the endpoints */
+
+ at76_dbg(DBG_DEVSTART, "USB interface: %d endpoints",
+ interface->cur_altsetting->desc.bNumEndpoints);
+
+ ret = at76_alloc_urbs(priv, interface);
+ if (ret < 0)
+ goto exit;
+
+ /* MAC address */
+ ret = at76_get_hw_config(priv);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "cannot get MAC address\n");
+ goto exit;
+ }
+
+ priv->domain = at76_get_reg_domain(priv->regulatory_domain);
+ /* init. netdev->dev_addr */
+ memcpy(netdev->dev_addr, priv->mac_addr, ETH_ALEN);
+
+ priv->channel = DEF_CHANNEL;
+ priv->iw_mode = IW_MODE_INFRA;
+ priv->rts_threshold = DEF_RTS_THRESHOLD;
+ priv->frag_threshold = DEF_FRAG_THRESHOLD;
+ priv->short_retry_limit = DEF_SHORT_RETRY_LIMIT;
+ priv->txrate = TX_RATE_AUTO;
+ priv->preamble_type = PREAMBLE_TYPE_LONG;
+ priv->beacon_period = 100;
+ priv->beacons_last_qual = jiffies;
+ priv->auth_mode = WLAN_AUTH_OPEN;
+ priv->scan_min_time = DEF_SCAN_MIN_TIME;
+ priv->scan_max_time = DEF_SCAN_MAX_TIME;
+ priv->scan_mode = SCAN_TYPE_ACTIVE;
+
+ netdev->flags &= ~IFF_MULTICAST; /* not yet or never */
+ netdev->open = at76_open;
+ netdev->stop = at76_stop;
+ netdev->get_stats = at76_get_stats;
+ netdev->ethtool_ops = &at76_ethtool_ops;
+
+ /* Add pointers to enable iwspy support. */
+ priv->wireless_data.spy_data = &priv->spy_data;
+ netdev->wireless_data = &priv->wireless_data;
+
+ netdev->hard_start_xmit = at76_tx;
+ netdev->tx_timeout = at76_tx_timeout;
+ netdev->watchdog_timeo = 2 * HZ;
+ netdev->wireless_handlers = &at76_handler_def;
+ netdev->set_multicast_list = at76_set_multicast;
+ netdev->set_mac_address = at76_set_mac_address;
+ dev_alloc_name(netdev, "wlan%d");
+
+ ret = register_netdev(priv->netdev);
+ if (ret) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "cannot register netdevice (status %d)!\n", ret);
+ goto exit;
+ }
+ priv->netdev_registered = 1;
+
+ printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
+ netdev->name, interface->dev.bus_id, mac2str(priv->mac_addr),
+ priv->fw_version.major, priv->fw_version.minor,
+ priv->fw_version.patch, priv->fw_version.build);
+ printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n", netdev->name,
+ priv->regulatory_domain, priv->domain->name);
+
+ /* we let this timer run the whole time this driver instance lives */
+ mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
+
+exit:
+ return ret;
+}
+
+static void at76_delete_device(struct at76_priv *priv)
+{
+ int i;
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
+
+ /* The device is gone, don't bother turning it off */
+ priv->device_unplugged = 1;
+
+ if (priv->netdev_registered)
+ unregister_netdev(priv->netdev);
+
+ /* assuming we used keventd, it must quiesce too */
+ flush_scheduled_work();
+
+ kfree(priv->bulk_out_buffer);
+
+ if (priv->tx_urb) {
+ usb_kill_urb(priv->tx_urb);
+ usb_free_urb(priv->tx_urb);
+ }
+ if (priv->rx_urb) {
+ usb_kill_urb(priv->rx_urb);
+ usb_free_urb(priv->rx_urb);
+ }
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__);
+
+ if (priv->rx_skb)
+ kfree_skb(priv->rx_skb);
+
+ at76_free_bss_list(priv);
+ del_timer_sync(&priv->bss_list_timer);
+ cancel_delayed_work(&priv->dwork_get_scan);
+ cancel_delayed_work(&priv->dwork_beacon);
+ cancel_delayed_work(&priv->dwork_auth);
+ cancel_delayed_work(&priv->dwork_assoc);
+
+ if (priv->mac_state == MAC_CONNECTED)
+ at76_iwevent_bss_disconnect(priv->netdev);
+
+ for (i = 0; i < NR_RX_DATA_BUF; i++)
+ if (priv->rx_data[i].skb) {
+ dev_kfree_skb(priv->rx_data[i].skb);
+ priv->rx_data[i].skb = NULL;
+ }
+ usb_put_dev(priv->udev);
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/netdev", __func__);
+ free_netdev(priv->netdev); /* priv is in netdev */
+
+ at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
+}
+
+static int at76_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int ret;
+ struct at76_priv *priv;
+ struct fwentry *fwe;
+ struct usb_device *udev;
+ int op_mode;
+ int need_ext_fw = 0;
+ struct mib_fw_version fwv;
+ int board_type = (int)id->driver_info;
+
+ udev = usb_get_dev(interface_to_usbdev(interface));
+
+ /* Load firmware into kernel memory */
+ fwe = at76_load_firmware(udev, board_type);
+ if (!fwe) {
+ ret = -ENOENT;
+ goto error;
+ }
+
+ op_mode = at76_get_op_mode(udev);
+
+ at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
+
+ /* we get OPMODE_NONE with 2.4.23, SMC2662W-AR ???
+ we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
+
+ if (op_mode == OPMODE_HW_CONFIG_MODE) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "cannot handle a device in HW_CONFIG_MODE\n");
+ ret = -EBUSY;
+ goto error;
+ }
+
+ if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH
+ && op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
+ /* download internal firmware part */
+ dev_printk(KERN_DEBUG, &interface->dev,
+ "downloading internal firmware\n");
+ ret = at76_load_internal_fw(udev, fwe);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "error %d downloading internal firmware\n",
+ ret);
+ goto error;
+ }
+ usb_put_dev(udev);
+ return ret;
+ }
+
+ /* Internal firmware already inside the device. Get firmware
+ * version to test if external firmware is loaded.
+ * This works only for newer firmware, e.g. the Intersil 0.90.x
+ * says "control timeout on ep0in" and subsequent
+ * at76_get_op_mode() fail too :-( */
+
+ /* if version >= 0.100.x.y or device with built-in flash we can
+ * query the device for the fw version */
+ if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100)
+ || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) {
+ ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
+ if (ret < 0 || (fwv.major | fwv.minor) == 0)
+ need_ext_fw = 1;
+ } else
+ /* No way to check firmware version, reload to be sure */
+ need_ext_fw = 1;
+
+ if (need_ext_fw) {
+ dev_printk(KERN_DEBUG, &interface->dev,
+ "downloading external firmware\n");
+
+ ret = at76_load_external_fw(udev, fwe);
+ if (ret)
+ goto error;
+
+ /* Re-check firmware version */
+ ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &interface->dev,
+ "error %d getting firmware version\n", ret);
+ goto error;
+ }
+ }
+
+ priv = at76_alloc_new_device(udev);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ SET_NETDEV_DEV(priv->netdev, &interface->dev);
+ usb_set_intfdata(interface, priv);
+
+ memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version));
+ priv->board_type = board_type;
+
+ ret = at76_init_new_device(priv, interface);
+ if (ret < 0)
+ at76_delete_device(priv);
+
+ return ret;
+
+error:
+ usb_put_dev(udev);
+ return ret;
+}
+
+static void at76_disconnect(struct usb_interface *interface)
+{
+ struct at76_priv *priv;
+
+ priv = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+ /* Disconnect after loading internal firmware */
+ if (!priv)
+ return;
+
+ printk(KERN_INFO "%s: disconnecting\n", priv->netdev->name);
+ at76_delete_device(priv);
+ dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
+}
+
+/* Structure for registering this driver with the USB subsystem */
+static struct usb_driver at76_driver = {
+ .name = DRIVER_NAME,
+ .probe = at76_probe,
+ .disconnect = at76_disconnect,
+ .id_table = dev_table,
+};
+
+static int __init at76_mod_init(void)
+{
+ int result;
+
+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " loading\n");
+
+ mutex_init(&fw_mutex);
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&at76_driver);
+ if (result < 0)
+ printk(KERN_ERR DRIVER_NAME
+ ": usb_register failed (status %d)\n", result);
+
+ led_trigger_register_simple("at76_usb-tx", &ledtrig_tx);
+ return result;
+}
+
+static void __exit at76_mod_exit(void)
+{
+ int i;
+
+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n");
+ usb_deregister(&at76_driver);
+ for (i = 0; i < ARRAY_SIZE(firmwares); i++) {
+ if (firmwares[i].fw)
+ release_firmware(firmwares[i].fw);
+ }
+ led_trigger_unregister_simple(ledtrig_tx);
+}
+
+module_param_named(debug, at76_debug, int, 0600);
+MODULE_PARM_DESC(debug, "Debugging level");
+
+module_init(at76_mod_init);
+module_exit(at76_mod_exit);
+
+MODULE_AUTHOR("Oliver Kurth <oku@masqmail.cx>");
+MODULE_AUTHOR("Joerg Albert <joerg.albert@gmx.de>");
+MODULE_AUTHOR("Alex <alex@foogod.com>");
+MODULE_AUTHOR("Nick Jones");
+MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/at76_usb/at76_usb.h b/drivers/staging/at76_usb/at76_usb.h
new file mode 100644
index 00000000000..b20be9da1fa
--- /dev/null
+++ b/drivers/staging/at76_usb/at76_usb.h
@@ -0,0 +1,619 @@
+/*
+ * Copyright (c) 2002,2003 Oliver Kurth
+ * (c) 2003,2004 Joerg Albert <joerg.albert@gmx.de>
+ * (c) 2007 Guido Guenther <agx@sigxcpu.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 driver was based on information from the Sourceforge driver
+ * released and maintained by Atmel:
+ *
+ * http://sourceforge.net/projects/atmelwlandriver/
+ *
+ * Although the code was completely re-written,
+ * it would have been impossible without Atmel's decision to
+ * release an Open Source driver (unfortunately the firmware was
+ * kept binary only). Thanks for that decision to Atmel!
+ */
+
+#ifndef _AT76_USB_H
+#define _AT76_USB_H
+
+/* Board types */
+enum board_type {
+ BOARD_503_ISL3861 = 1,
+ BOARD_503_ISL3863 = 2,
+ BOARD_503 = 3,
+ BOARD_503_ACC = 4,
+ BOARD_505 = 5,
+ BOARD_505_2958 = 6,
+ BOARD_505A = 7,
+ BOARD_505AMX = 8
+};
+
+/* our private ioctl's */
+/* preamble length (0 - long, 1 - short, 2 - auto) */
+#define AT76_SET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 0)
+#define AT76_GET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 1)
+/* which debug channels are enabled */
+#define AT76_SET_DEBUG (SIOCIWFIRSTPRIV + 2)
+#define AT76_GET_DEBUG (SIOCIWFIRSTPRIV + 3)
+/* power save mode (incl. the Atmel proprietary smart save mode) */
+#define AT76_SET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 4)
+#define AT76_GET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 5)
+/* min and max channel times for scan */
+#define AT76_SET_SCAN_TIMES (SIOCIWFIRSTPRIV + 6)
+#define AT76_GET_SCAN_TIMES (SIOCIWFIRSTPRIV + 7)
+/* scan mode (0 - active, 1 - passive) */
+#define AT76_SET_SCAN_MODE (SIOCIWFIRSTPRIV + 8)
+#define AT76_GET_SCAN_MODE (SIOCIWFIRSTPRIV + 9)
+
+#define CMD_STATUS_IDLE 0x00
+#define CMD_STATUS_COMPLETE 0x01
+#define CMD_STATUS_UNKNOWN 0x02
+#define CMD_STATUS_INVALID_PARAMETER 0x03
+#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
+#define CMD_STATUS_TIME_OUT 0x07
+#define CMD_STATUS_IN_PROGRESS 0x08
+#define CMD_STATUS_HOST_FAILURE 0xff
+#define CMD_STATUS_SCAN_FAILED 0xf0
+
+/* answers to get op mode */
+#define OPMODE_NONE 0x00
+#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01
+#define OPMODE_HW_CONFIG_MODE 0x02
+#define OPMODE_DFU_MODE_WITH_FLASH 0x03
+#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04
+
+#define CMD_SET_MIB 0x01
+#define CMD_GET_MIB 0x02
+#define CMD_SCAN 0x03
+#define CMD_JOIN 0x04
+#define CMD_START_IBSS 0x05
+#define CMD_RADIO_ON 0x06
+#define CMD_RADIO_OFF 0x07
+#define CMD_STARTUP 0x0B
+
+#define MIB_LOCAL 0x01
+#define MIB_MAC_ADDR 0x02
+#define MIB_MAC 0x03
+#define MIB_MAC_MGMT 0x05
+#define MIB_MAC_WEP 0x06
+#define MIB_PHY 0x07
+#define MIB_FW_VERSION 0x08
+#define MIB_MDOMAIN 0x09
+
+#define ADHOC_MODE 1
+#define INFRASTRUCTURE_MODE 2
+
+/* values for struct mib_local, field preamble_type */
+#define PREAMBLE_TYPE_LONG 0
+#define PREAMBLE_TYPE_SHORT 1
+#define PREAMBLE_TYPE_AUTO 2
+
+/* values for tx_rate */
+#define TX_RATE_1MBIT 0
+#define TX_RATE_2MBIT 1
+#define TX_RATE_5_5MBIT 2
+#define TX_RATE_11MBIT 3
+#define TX_RATE_AUTO 4
+
+/* power management modes */
+#define AT76_PM_OFF 1
+#define AT76_PM_ON 2
+#define AT76_PM_SMART 3
+
+struct hwcfg_r505 {
+ u8 cr39_values[14];
+ u8 reserved1[14];
+ u8 bb_cr[14];
+ u8 pidvid[4];
+ u8 mac_addr[ETH_ALEN];
+ u8 regulatory_domain;
+ u8 reserved2[14];
+ u8 cr15_values[14];
+ u8 reserved3[3];
+} __attribute__((packed));
+
+struct hwcfg_rfmd {
+ u8 cr20_values[14];
+ u8 cr21_values[14];
+ u8 bb_cr[14];
+ u8 pidvid[4];
+ u8 mac_addr[ETH_ALEN];
+ u8 regulatory_domain;
+ u8 low_power_values[14];
+ u8 normal_power_values[14];
+ u8 reserved1[3];
+} __attribute__((packed));
+
+struct hwcfg_intersil {
+ u8 mac_addr[ETH_ALEN];
+ u8 cr31_values[14];
+ u8 cr58_values[14];
+ u8 pidvid[4];
+ u8 regulatory_domain;
+ u8 reserved[1];
+} __attribute__((packed));
+
+union at76_hwcfg {
+ struct hwcfg_intersil i;
+ struct hwcfg_rfmd r3;
+ struct hwcfg_r505 r5;
+};
+
+#define WEP_SMALL_KEY_LEN (40 / 8)
+#define WEP_LARGE_KEY_LEN (104 / 8)
+
+struct at76_card_config {
+ u8 exclude_unencrypted;
+ u8 promiscuous_mode;
+ u8 short_retry_limit;
+ u8 encryption_type;
+ __le16 rts_threshold;
+ __le16 fragmentation_threshold; /* 256..2346 */
+ u8 basic_rate_set[4];
+ u8 auto_rate_fallback; /* 0,1 */
+ u8 channel;
+ u8 privacy_invoked;
+ u8 wep_default_key_id; /* 0..3 */
+ u8 current_ssid[32];
+ u8 wep_default_key_value[4][WEP_KEY_LEN];
+ u8 ssid_len;
+ u8 short_preamble;
+ __le16 beacon_period;
+} __attribute__((packed));
+
+struct at76_command {
+ u8 cmd;
+ u8 reserved;
+ __le16 size;
+ u8 data[0];
+} __attribute__((packed));
+
+/* Length of Atmel-specific Rx header before 802.11 frame */
+#define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet)
+
+struct at76_rx_buffer {
+ __le16 wlength;
+ u8 rx_rate;
+ u8 newbss;
+ u8 fragmentation;
+ u8 rssi;
+ u8 link_quality;
+ u8 noise_level;
+ __le32 rx_time;
+ u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
+} __attribute__((packed));
+
+/* Length of Atmel-specific Tx header before 802.11 frame */
+#define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet)
+
+struct at76_tx_buffer {
+ __le16 wlength;
+ u8 tx_rate;
+ u8 padding;
+ u8 reserved[4];
+ u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
+} __attribute__((packed));
+
+/* defines for scan_type below */
+#define SCAN_TYPE_ACTIVE 0
+#define SCAN_TYPE_PASSIVE 1
+
+struct at76_req_scan {
+ u8 bssid[ETH_ALEN];
+ u8 essid[32];
+ u8 scan_type;
+ u8 channel;
+ __le16 probe_delay;
+ __le16 min_channel_time;
+ __le16 max_channel_time;
+ u8 essid_size;
+ u8 international_scan;
+} __attribute__((packed));
+
+struct at76_req_ibss {
+ u8 bssid[ETH_ALEN];
+ u8 essid[32];
+ u8 bss_type;
+ u8 channel;
+ u8 essid_size;
+ u8 reserved[3];
+} __attribute__((packed));
+
+struct at76_req_join {
+ u8 bssid[ETH_ALEN];
+ u8 essid[32];
+ u8 bss_type;
+ u8 channel;
+ __le16 timeout;
+ u8 essid_size;
+ u8 reserved;
+} __attribute__((packed));
+
+struct set_mib_buffer {
+ u8 type;
+ u8 size;
+ u8 index;
+ u8 reserved;
+ union {
+ u8 byte;
+ __le16 word;
+ u8 addr[ETH_ALEN];
+ } data;
+} __attribute__((packed));
+
+struct mib_local {
+ u16 reserved0;
+ u8 beacon_enable;
+ u8 txautorate_fallback;
+ u8 reserved1;
+ u8 ssid_size;
+ u8 promiscuous_mode;
+ u16 reserved2;
+ u8 preamble_type;
+ u16 reserved3;
+} __attribute__((packed));
+
+struct mib_mac_addr {
+ u8 mac_addr[ETH_ALEN];
+ u8 res[2]; /* ??? */
+ u8 group_addr[4][ETH_ALEN];
+ u8 group_addr_status[4];
+} __attribute__((packed));
+
+struct mib_mac {
+ __le32 max_tx_msdu_lifetime;
+ __le32 max_rx_lifetime;
+ __le16 frag_threshold;
+ __le16 rts_threshold;
+ __le16 cwmin;
+ __le16 cwmax;
+ u8 short_retry_time;
+ u8 long_retry_time;
+ u8 scan_type; /* active or passive */
+ u8 scan_channel;
+ __le16 probe_delay; /* delay before ProbeReq in active scan, RO */
+ __le16 min_channel_time;
+ __le16 max_channel_time;
+ __le16 listen_interval;
+ u8 desired_ssid[32];
+ u8 desired_bssid[ETH_ALEN];
+ u8 desired_bsstype; /* ad-hoc or infrastructure */
+ u8 reserved2;
+} __attribute__((packed));
+
+struct mib_mac_mgmt {
+ __le16 beacon_period;
+ __le16 CFP_max_duration;
+ __le16 medium_occupancy_limit;
+ __le16 station_id; /* assoc id */
+ __le16 ATIM_window;
+ u8 CFP_mode;
+ u8 privacy_option_implemented;
+ u8 DTIM_period;
+ u8 CFP_period;
+ u8 current_bssid[ETH_ALEN];
+ u8 current_essid[32];
+ u8 current_bss_type;
+ u8 power_mgmt_mode;
+ /* rfmd and 505 */
+ u8 ibss_change;
+ u8 res;
+ u8 multi_domain_capability_implemented;
+ u8 multi_domain_capability_enabled;
+ u8 country_string[3];
+ u8 reserved[3];
+} __attribute__((packed));
+
+struct mib_mac_wep {
+ u8 privacy_invoked; /* 0 disable encr., 1 enable encr */
+ u8 wep_default_key_id;
+ u8 wep_key_mapping_len;
+ u8 exclude_unencrypted;
+ __le32 wep_icv_error_count;
+ __le32 wep_excluded_count;
+ u8 wep_default_keyvalue[WEP_KEYS][WEP_KEY_LEN];
+ u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */
+} __attribute__((packed));
+
+struct mib_phy {
+ __le32 ed_threshold;
+
+ __le16 slot_time;
+ __le16 sifs_time;
+ __le16 preamble_length;
+ __le16 plcp_header_length;
+ __le16 mpdu_max_length;
+ __le16 cca_mode_supported;
+
+ u8 operation_rate_set[4];
+ u8 channel_id;
+ u8 current_cca_mode;
+ u8 phy_type;
+ u8 current_reg_domain;
+} __attribute__((packed));
+
+struct mib_fw_version {
+ u8 major;
+ u8 minor;
+ u8 patch;
+ u8 build;
+} __attribute__((packed));
+
+struct mib_mdomain {
+ u8 tx_powerlevel[14];
+ u8 channel_list[14]; /* 0 for invalid channels */
+} __attribute__((packed));
+
+struct at76_fw_header {
+ __le32 crc; /* CRC32 of the whole image */
+ __le32 board_type; /* firmware compatibility code */
+ u8 build; /* firmware build number */
+ u8 patch; /* firmware patch level */
+ u8 minor; /* firmware minor version */
+ u8 major; /* firmware major version */
+ __le32 str_offset; /* offset of the copyright string */
+ __le32 int_fw_offset; /* internal firmware image offset */
+ __le32 int_fw_len; /* internal firmware image length */
+ __le32 ext_fw_offset; /* external firmware image offset */
+ __le32 ext_fw_len; /* external firmware image length */
+} __attribute__((packed));
+
+enum mac_state {
+ MAC_INIT,
+ MAC_SCANNING,
+ MAC_AUTH,
+ MAC_ASSOC,
+ MAC_JOINING,
+ MAC_CONNECTED,
+ MAC_OWN_IBSS
+};
+
+/* a description of a regulatory domain and the allowed channels */
+struct reg_domain {
+ u16 code;
+ char const *name;
+ u32 channel_map; /* if bit N is set, channel (N+1) is allowed */
+};
+
+/* how long do we keep a (I)BSS in the bss_list in jiffies
+ this should be long enough for the user to retrieve the table
+ (by iwlist ?) after the device started, because all entries from
+ other channels than the one the device locks on get removed, too */
+#define BSS_LIST_TIMEOUT (120 * HZ)
+/* struct to store BSS info found during scan */
+#define BSS_LIST_MAX_RATE_LEN 32 /* 32 rates should be enough ... */
+
+struct bss_info {
+ struct list_head list;
+
+ u8 bssid[ETH_ALEN]; /* bssid */
+ u8 ssid[IW_ESSID_MAX_SIZE]; /* essid */
+ u8 ssid_len; /* length of ssid above */
+ u8 channel;
+ u16 capa; /* BSS capabilities */
+ u16 beacon_interval; /* beacon interval, Kus (1024 microseconds) */
+ u8 rates[BSS_LIST_MAX_RATE_LEN]; /* supported rates in units of
+ 500 kbps, ORed with 0x80 for
+ basic rates */
+ u8 rates_len;
+
+ /* quality of received beacon */
+ u8 rssi;
+ u8 link_qual;
+ u8 noise_level;
+
+ unsigned long last_rx; /* time (jiffies) of last beacon received */
+};
+
+/* a rx data buffer to collect rx fragments */
+struct rx_data_buf {
+ u8 sender[ETH_ALEN]; /* sender address */
+ u16 seqnr; /* sequence number */
+ u16 fragnr; /* last fragment received */
+ unsigned long last_rx; /* jiffies of last rx */
+ struct sk_buff *skb; /* == NULL if entry is free */
+};
+
+#define NR_RX_DATA_BUF 8
+
+/* Data for one loaded firmware file */
+struct fwentry {
+ const char *const fwname;
+ const struct firmware *fw;
+ int extfw_size;
+ int intfw_size;
+ /* pointer to loaded firmware, no need to free */
+ u8 *extfw; /* external firmware, extfw_size bytes long */
+ u8 *intfw; /* internal firmware, intfw_size bytes long */
+ enum board_type board_type; /* board type */
+ struct mib_fw_version fw_version;
+ int loaded; /* Loaded and parsed successfully */
+};
+
+struct at76_priv {
+ struct usb_device *udev; /* USB device pointer */
+ struct net_device *netdev; /* net device pointer */
+ struct net_device_stats stats; /* net device stats */
+ struct iw_statistics wstats; /* wireless stats */
+
+ struct sk_buff *rx_skb; /* skbuff for receiving data */
+ void *bulk_out_buffer; /* buffer for sending data */
+
+ struct urb *tx_urb; /* URB for sending data */
+ struct urb *rx_urb; /* URB for receiving data */
+
+ unsigned int tx_pipe; /* bulk out pipe */
+ unsigned int rx_pipe; /* bulk in pipe */
+
+ struct mutex mtx; /* locks this structure */
+
+ /* work queues */
+ struct work_struct work_assoc_done;
+ struct work_struct work_join;
+ struct work_struct work_new_bss;
+ struct work_struct work_start_scan;
+ struct work_struct work_set_promisc;
+ struct work_struct work_submit_rx;
+ struct delayed_work dwork_restart;
+ struct delayed_work dwork_get_scan;
+ struct delayed_work dwork_beacon;
+ struct delayed_work dwork_auth;
+ struct delayed_work dwork_assoc;
+
+ struct tasklet_struct rx_tasklet;
+
+ /* the WEP stuff */
+ int wep_enabled; /* 1 if WEP is enabled */
+ int wep_key_id; /* key id to be used */
+ u8 wep_keys[WEP_KEYS][WEP_KEY_LEN]; /* the four WEP keys,
+ 5 or 13 bytes are used */
+ u8 wep_keys_len[WEP_KEYS]; /* the length of the above keys */
+
+ int channel;
+ int iw_mode;
+ u8 bssid[ETH_ALEN];
+ u8 essid[IW_ESSID_MAX_SIZE];
+ int essid_size;
+ int radio_on;
+ int promisc;
+
+ int preamble_type; /* 0 - long, 1 - short, 2 - auto */
+ int auth_mode; /* authentication type: 0 open, 1 shared key */
+ int txrate; /* 0,1,2,3 = 1,2,5.5,11 Mbps, 4 is auto */
+ int frag_threshold; /* threshold for fragmentation of tx packets */
+ int rts_threshold; /* threshold for RTS mechanism */
+ int short_retry_limit;
+
+ int scan_min_time; /* scan min channel time */
+ int scan_max_time; /* scan max channel time */
+ int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
+ int scan_need_any; /* if set, need to scan for any ESSID */
+
+ /* the list we got from scanning */
+ spinlock_t bss_list_spinlock; /* protects bss_list operations */
+ struct list_head bss_list; /* list of BSS we got beacons from */
+ struct timer_list bss_list_timer; /* timer to purge old entries
+ from bss_list */
+ struct bss_info *curr_bss; /* current BSS */
+ u16 assoc_id; /* current association ID, if associated */
+
+ u8 wanted_bssid[ETH_ALEN];
+ int wanted_bssid_valid; /* != 0 if wanted_bssid is to be used */
+
+ /* some data for infrastructure mode only */
+ spinlock_t mgmt_spinlock; /* this spinlock protects access to
+ next_mgmt_bulk */
+
+ struct at76_tx_buffer *next_mgmt_bulk; /* pending management msg to
+ send via bulk out */
+ enum mac_state mac_state;
+ enum {
+ SCAN_IDLE,
+ SCAN_IN_PROGRESS,
+ SCAN_COMPLETED
+ } scan_state;
+ time_t last_scan;
+
+ int retries; /* remaining retries in case of timeout when
+ * sending AuthReq or AssocReq */
+ u8 pm_mode; /* power management mode */
+ u32 pm_period; /* power management period in microseconds */
+
+ struct reg_domain const *domain; /* reg domain description */
+
+ /* iwspy support */
+ spinlock_t spy_spinlock;
+ struct iw_spy_data spy_data;
+
+ struct iw_public_data wireless_data;
+
+ /* These fields contain HW config provided by the device (not all of
+ * these fields are used by all board types) */
+ u8 mac_addr[ETH_ALEN];
+ u8 regulatory_domain;
+
+ struct at76_card_config card_config;
+
+ /* store rx fragments until complete */
+ struct rx_data_buf rx_data[NR_RX_DATA_BUF];
+
+ enum board_type board_type;
+ struct mib_fw_version fw_version;
+
+ unsigned int device_unplugged:1;
+ unsigned int netdev_registered:1;
+ struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */
+
+ /* beacon counting */
+ int beacon_period; /* period of mgmt beacons, Kus */
+ int beacons_received;
+ unsigned long beacons_last_qual; /* time we restarted counting
+ beacons */
+};
+
+struct at76_rx_radiotap {
+ struct ieee80211_radiotap_header rt_hdr;
+ __le64 rt_tsft;
+ u8 rt_flags;
+ u8 rt_rate;
+ s8 rt_signal;
+ s8 rt_noise;
+};
+
+#define AT76_RX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DB_ANTNOISE))
+
+#define BEACON_MAX_DATA_LENGTH 1500
+
+/* the maximum size of an AssocReq packet */
+#define ASSOCREQ_MAX_SIZE \
+ (AT76_TX_HDRLEN + sizeof(struct ieee80211_assoc_request) + \
+ 1 + 1 + IW_ESSID_MAX_SIZE + 1 + 1 + 4)
+
+/* for shared secret auth, add the challenge text size */
+#define AUTH_FRAME_SIZE (AT76_TX_HDRLEN + sizeof(struct ieee80211_auth))
+
+/* Maximal number of AuthReq retries */
+#define AUTH_RETRIES 3
+
+/* Maximal number of AssocReq retries */
+#define ASSOC_RETRIES 3
+
+/* Beacon timeout in managed mode when we are connected */
+#define BEACON_TIMEOUT (10 * HZ)
+
+/* Timeout for authentication response */
+#define AUTH_TIMEOUT (1 * HZ)
+
+/* Timeout for association response */
+#define ASSOC_TIMEOUT (1 * HZ)
+
+/* Polling interval when scan is running */
+#define SCAN_POLL_INTERVAL (HZ / 4)
+
+/* Command completion timeout */
+#define CMD_COMPLETION_TIMEOUT (5 * HZ)
+
+#define DEF_RTS_THRESHOLD 1536
+#define DEF_FRAG_THRESHOLD 1536
+#define DEF_SHORT_RETRY_LIMIT 8
+#define DEF_CHANNEL 10
+#define DEF_SCAN_MIN_TIME 10
+#define DEF_SCAN_MAX_TIME 120
+
+#define MAX_RTS_THRESHOLD (MAX_FRAG_THRESHOLD + 1)
+
+/* the max padding size for tx in bytes (see calc_padding) */
+#define MAX_PADDING_SIZE 53
+
+#endif /* _AT76_USB_H */
diff --git a/drivers/staging/echo/Kconfig b/drivers/staging/echo/Kconfig
new file mode 100644
index 00000000000..f1d41ea9cd4
--- /dev/null
+++ b/drivers/staging/echo/Kconfig
@@ -0,0 +1,9 @@
+config ECHO
+ tristate "Line Echo Canceller support"
+ default n
+ ---help---
+ This driver provides line echo cancelling support for mISDN and
+ Zaptel drivers.
+
+ To compile this driver as a module, choose M here. The module
+ will be called echo.
diff --git a/drivers/staging/echo/Makefile b/drivers/staging/echo/Makefile
new file mode 100644
index 00000000000..7d4caac12a8
--- /dev/null
+++ b/drivers/staging/echo/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ECHO) += echo.o
diff --git a/drivers/staging/echo/TODO b/drivers/staging/echo/TODO
new file mode 100644
index 00000000000..1ca09afd603
--- /dev/null
+++ b/drivers/staging/echo/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - checkpatch.pl cleanups
+ - Lindent
+ - typedef removals
+ - handle bit_operations.h (merge in or make part of common code?)
+ - remove proc interface, only use echo.h interface (proc interface is
+ racy and not correct.)
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: Steve
+Underwood <steveu@coppice.org> and David Rowe <david@rowetel.com>
diff --git a/drivers/staging/echo/bit_operations.h b/drivers/staging/echo/bit_operations.h
new file mode 100644
index 00000000000..b32f4bf9939
--- /dev/null
+++ b/drivers/staging/echo/bit_operations.h
@@ -0,0 +1,253 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * bit_operations.h - Various bit level operations, such as bit reversal
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * 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 version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * $Id: bit_operations.h,v 1.11 2006/11/28 15:37:03 steveu Exp $
+ */
+
+/*! \file */
+
+#if !defined(_BIT_OPERATIONS_H_)
+#define _BIT_OPERATIONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+/*! \brief Find the bit position of the highest set bit in a word
+ \param bits The word to be searched
+ \return The bit number of the highest set bit, or -1 if the word is zero. */
+static __inline__ int top_bit(unsigned int bits)
+{
+ int res;
+
+ __asm__ (" xorl %[res],%[res];\n"
+ " decl %[res];\n"
+ " bsrl %[bits],%[res]\n"
+ : [res] "=&r" (res)
+ : [bits] "rm" (bits));
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the bit position of the lowest set bit in a word
+ \param bits The word to be searched
+ \return The bit number of the lowest set bit, or -1 if the word is zero. */
+static __inline__ int bottom_bit(unsigned int bits)
+{
+ int res;
+
+ __asm__ (" xorl %[res],%[res];\n"
+ " decl %[res];\n"
+ " bsfl %[bits],%[res]\n"
+ : [res] "=&r" (res)
+ : [bits] "rm" (bits));
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+#else
+static __inline__ int top_bit(unsigned int bits)
+{
+ int i;
+
+ if (bits == 0)
+ return -1;
+ i = 0;
+ if (bits & 0xFFFF0000)
+ {
+ bits &= 0xFFFF0000;
+ i += 16;
+ }
+ if (bits & 0xFF00FF00)
+ {
+ bits &= 0xFF00FF00;
+ i += 8;
+ }
+ if (bits & 0xF0F0F0F0)
+ {
+ bits &= 0xF0F0F0F0;
+ i += 4;
+ }
+ if (bits & 0xCCCCCCCC)
+ {
+ bits &= 0xCCCCCCCC;
+ i += 2;
+ }
+ if (bits & 0xAAAAAAAA)
+ {
+ bits &= 0xAAAAAAAA;
+ i += 1;
+ }
+ return i;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int bottom_bit(unsigned int bits)
+{
+ int i;
+
+ if (bits == 0)
+ return -1;
+ i = 32;
+ if (bits & 0x0000FFFF)
+ {
+ bits &= 0x0000FFFF;
+ i -= 16;
+ }
+ if (bits & 0x00FF00FF)
+ {
+ bits &= 0x00FF00FF;
+ i -= 8;
+ }
+ if (bits & 0x0F0F0F0F)
+ {
+ bits &= 0x0F0F0F0F;
+ i -= 4;
+ }
+ if (bits & 0x33333333)
+ {
+ bits &= 0x33333333;
+ i -= 2;
+ }
+ if (bits & 0x55555555)
+ {
+ bits &= 0x55555555;
+ i -= 1;
+ }
+ return i;
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+/*! \brief Bit reverse a byte.
+ \param data The byte to be reversed.
+ \return The bit reversed version of data. */
+static __inline__ uint8_t bit_reverse8(uint8_t x)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ /* If multiply is fast */
+ return ((x*0x0802U & 0x22110U) | (x*0x8020U & 0x88440U))*0x10101U >> 16;
+#else
+ /* If multiply is slow, but we have a barrel shifter */
+ x = (x >> 4) | (x << 4);
+ x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2);
+ return ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
+#endif
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Bit reverse a 16 bit word.
+ \param data The word to be reversed.
+ \return The bit reversed version of data. */
+uint16_t bit_reverse16(uint16_t data);
+
+/*! \brief Bit reverse a 32 bit word.
+ \param data The word to be reversed.
+ \return The bit reversed version of data. */
+uint32_t bit_reverse32(uint32_t data);
+
+/*! \brief Bit reverse each of the four bytes in a 32 bit word.
+ \param data The word to be reversed.
+ \return The bit reversed version of data. */
+uint32_t bit_reverse_4bytes(uint32_t data);
+
+/*! \brief Find the number of set bits in a 32 bit word.
+ \param x The word to be searched.
+ \return The number of set bits. */
+int one_bits32(uint32_t x);
+
+/*! \brief Create a mask as wide as the number in a 32 bit word.
+ \param x The word to be searched.
+ \return The mask. */
+uint32_t make_mask32(uint32_t x);
+
+/*! \brief Create a mask as wide as the number in a 16 bit word.
+ \param x The word to be searched.
+ \return The mask. */
+uint16_t make_mask16(uint16_t x);
+
+/*! \brief Find the least significant one in a word, and return a word
+ with just that bit set.
+ \param x The word to be searched.
+ \return The word with the single set bit. */
+static __inline__ uint32_t least_significant_one32(uint32_t x)
+{
+ return (x & (-(int32_t) x));
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the most significant one in a word, and return a word
+ with just that bit set.
+ \param x The word to be searched.
+ \return The word with the single set bit. */
+static __inline__ uint32_t most_significant_one32(uint32_t x)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ return 1 << top_bit(x);
+#else
+ x = make_mask32(x);
+ return (x ^ (x >> 1));
+#endif
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the parity of a byte.
+ \param x The byte to be checked.
+ \return 1 for odd, or 0 for even. */
+static __inline__ int parity8(uint8_t x)
+{
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the parity of a 16 bit word.
+ \param x The word to be checked.
+ \return 1 for odd, or 0 for even. */
+static __inline__ int parity16(uint16_t x)
+{
+ x ^= (x >> 8);
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+/*! \brief Find the parity of a 32 bit word.
+ \param x The word to be checked.
+ \return 1 for odd, or 0 for even. */
+static __inline__ int parity32(uint32_t x)
+{
+ x ^= (x >> 16);
+ x ^= (x >> 8);
+ x = (x ^ (x >> 4)) & 0x0F;
+ return (0x6996 >> x) & 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
new file mode 100644
index 00000000000..4a281b14fc5
--- /dev/null
+++ b/drivers/staging/echo/echo.c
@@ -0,0 +1,632 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * echo.c - A line echo canceller. This code is being developed
+ * against and partially complies with G168.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ * and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
+ *
+ * Based on a bit from here, a bit from there, eye of toad, ear of
+ * bat, 15 years of failed attempts by David and a few fried brain
+ * cells.
+ *
+ * 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 version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * $Id: echo.c,v 1.20 2006/12/01 18:00:48 steveu Exp $
+ */
+
+/*! \file */
+
+/* Implementation Notes
+ David Rowe
+ April 2007
+
+ This code started life as Steve's NLMS algorithm with a tap
+ rotation algorithm to handle divergence during double talk. I
+ added a Geigel Double Talk Detector (DTD) [2] and performed some
+ G168 tests. However I had trouble meeting the G168 requirements,
+ especially for double talk - there were always cases where my DTD
+ failed, for example where near end speech was under the 6dB
+ threshold required for declaring double talk.
+
+ So I tried a two path algorithm [1], which has so far given better
+ results. The original tap rotation/Geigel algorithm is available
+ in SVN http://svn.rowetel.com/software/oslec/tags/before_16bit.
+ It's probably possible to make it work if some one wants to put some
+ serious work into it.
+
+ At present no special treatment is provided for tones, which
+ generally cause NLMS algorithms to diverge. Initial runs of a
+ subset of the G168 tests for tones (e.g ./echo_test 6) show the
+ current algorithm is passing OK, which is kind of surprising. The
+ full set of tests needs to be performed to confirm this result.
+
+ One other interesting change is that I have managed to get the NLMS
+ code to work with 16 bit coefficients, rather than the original 32
+ bit coefficents. This reduces the MIPs and storage required.
+ I evaulated the 16 bit port using g168_tests.sh and listening tests
+ on 4 real-world samples.
+
+ I also attempted the implementation of a block based NLMS update
+ [2] but although this passes g168_tests.sh it didn't converge well
+ on the real-world samples. I have no idea why, perhaps a scaling
+ problem. The block based code is also available in SVN
+ http://svn.rowetel.com/software/oslec/tags/before_16bit. If this
+ code can be debugged, it will lead to further reduction in MIPS, as
+ the block update code maps nicely onto DSP instruction sets (it's a
+ dot product) compared to the current sample-by-sample update.
+
+ Steve also has some nice notes on echo cancellers in echo.h
+
+
+ References:
+
+ [1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
+ Path Models", IEEE Transactions on communications, COM-25,
+ No. 6, June
+ 1977.
+ http://www.rowetel.com/images/echo/dual_path_paper.pdf
+
+ [2] The classic, very useful paper that tells you how to
+ actually build a real world echo canceller:
+ Messerschmitt, Hedberg, Cole, Haoui, Winship, "Digital Voice
+ Echo Canceller with a TMS320020,
+ http://www.rowetel.com/images/echo/spra129.pdf
+
+ [3] I have written a series of blog posts on this work, here is
+ Part 1: http://www.rowetel.com/blog/?p=18
+
+ [4] The source code http://svn.rowetel.com/software/oslec/
+
+ [5] A nice reference on LMS filters:
+ http://en.wikipedia.org/wiki/Least_mean_squares_filter
+
+ Credits:
+
+ Thanks to Steve Underwood, Jean-Marc Valin, and Ramakrishnan
+ Muthukrishnan for their suggestions and email discussions. Thanks
+ also to those people who collected echo samples for me such as
+ Mark, Pawel, and Pavel.
+*/
+
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#define malloc(a) kmalloc((a), GFP_KERNEL)
+#define free(a) kfree(a)
+
+#include "bit_operations.h"
+#include "echo.h"
+
+#define MIN_TX_POWER_FOR_ADAPTION 64
+#define MIN_RX_POWER_FOR_ADAPTION 64
+#define DTD_HANGOVER 600 /* 600 samples, or 75ms */
+#define DC_LOG2BETA 3 /* log2() of DC filter Beta */
+
+/*-----------------------------------------------------------------------*\
+ FUNCTIONS
+\*-----------------------------------------------------------------------*/
+
+/* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
+
+
+#ifdef __BLACKFIN_ASM__
+static void __inline__ lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
+{
+ int i, j;
+ int offset1;
+ int offset2;
+ int factor;
+ int exp;
+ int16_t *phist;
+ int n;
+
+ if (shift > 0)
+ factor = clean << shift;
+ else
+ factor = clean >> -shift;
+
+ /* Update the FIR taps */
+
+ offset2 = ec->curr_pos;
+ offset1 = ec->taps - offset2;
+ phist = &ec->fir_state_bg.history[offset2];
+
+ /* st: and en: help us locate the assembler in echo.s */
+
+ //asm("st:");
+ n = ec->taps;
+ for (i = 0, j = offset2; i < n; i++, j++)
+ {
+ exp = *phist++ * factor;
+ ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
+ }
+ //asm("en:");
+
+ /* Note the asm for the inner loop above generated by Blackfin gcc
+ 4.1.1 is pretty good (note even parallel instructions used):
+
+ R0 = W [P0++] (X);
+ R0 *= R2;
+ R0 = R0 + R3 (NS) ||
+ R1 = W [P1] (X) ||
+ nop;
+ R0 >>>= 15;
+ R0 = R0 + R1;
+ W [P1++] = R0;
+
+ A block based update algorithm would be much faster but the
+ above can't be improved on much. Every instruction saved in
+ the loop above is 2 MIPs/ch! The for loop above is where the
+ Blackfin spends most of it's time - about 17 MIPs/ch measured
+ with speedtest.c with 256 taps (32ms). Write-back and
+ Write-through cache gave about the same performance.
+ */
+}
+
+/*
+ IDEAS for further optimisation of lms_adapt_bg():
+
+ 1/ The rounding is quite costly. Could we keep as 32 bit coeffs
+ then make filter pluck the MS 16-bits of the coeffs when filtering?
+ However this would lower potential optimisation of filter, as I
+ think the dual-MAC architecture requires packed 16 bit coeffs.
+
+ 2/ Block based update would be more efficient, as per comments above,
+ could use dual MAC architecture.
+
+ 3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC
+ packing.
+
+ 4/ Execute the whole e/c in a block of say 20ms rather than sample
+ by sample. Processing a few samples every ms is inefficient.
+*/
+
+#else
+static __inline__ void lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
+{
+ int i;
+
+ int offset1;
+ int offset2;
+ int factor;
+ int exp;
+
+ if (shift > 0)
+ factor = clean << shift;
+ else
+ factor = clean >> -shift;
+
+ /* Update the FIR taps */
+
+ offset2 = ec->curr_pos;
+ offset1 = ec->taps - offset2;
+
+ for (i = ec->taps - 1; i >= offset1; i--)
+ {
+ exp = (ec->fir_state_bg.history[i - offset1]*factor);
+ ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
+ }
+ for ( ; i >= 0; i--)
+ {
+ exp = (ec->fir_state_bg.history[i + offset2]*factor);
+ ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
+ }
+}
+#endif
+
+/*- End of function --------------------------------------------------------*/
+
+echo_can_state_t *echo_can_create(int len, int adaption_mode)
+{
+ echo_can_state_t *ec;
+ int i;
+ int j;
+
+ ec = kmalloc(sizeof(*ec), GFP_KERNEL);
+ if (ec == NULL)
+ return NULL;
+ memset(ec, 0, sizeof(*ec));
+
+ ec->taps = len;
+ ec->log2taps = top_bit(len);
+ ec->curr_pos = ec->taps - 1;
+
+ for (i = 0; i < 2; i++)
+ {
+ if ((ec->fir_taps16[i] = (int16_t *) malloc((ec->taps)*sizeof(int16_t))) == NULL)
+ {
+ for (j = 0; j < i; j++)
+ kfree(ec->fir_taps16[j]);
+ kfree(ec);
+ return NULL;
+ }
+ memset(ec->fir_taps16[i], 0, (ec->taps)*sizeof(int16_t));
+ }
+
+ fir16_create(&ec->fir_state,
+ ec->fir_taps16[0],
+ ec->taps);
+ fir16_create(&ec->fir_state_bg,
+ ec->fir_taps16[1],
+ ec->taps);
+
+ for(i=0; i<5; i++) {
+ ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
+ }
+
+ ec->cng_level = 1000;
+ echo_can_adaption_mode(ec, adaption_mode);
+
+ ec->snapshot = (int16_t*)malloc(ec->taps*sizeof(int16_t));
+ memset(ec->snapshot, 0, sizeof(int16_t)*ec->taps);
+
+ ec->cond_met = 0;
+ ec->Pstates = 0;
+ ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
+ ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
+ ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+ ec->Lbgn = ec->Lbgn_acc = 0;
+ ec->Lbgn_upper = 200;
+ ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
+
+ return ec;
+}
+/*- End of function --------------------------------------------------------*/
+
+void echo_can_free(echo_can_state_t *ec)
+{
+ int i;
+
+ fir16_free(&ec->fir_state);
+ fir16_free(&ec->fir_state_bg);
+ for (i = 0; i < 2; i++)
+ kfree(ec->fir_taps16[i]);
+ kfree(ec->snapshot);
+ kfree(ec);
+}
+/*- End of function --------------------------------------------------------*/
+
+void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode)
+{
+ ec->adaption_mode = adaption_mode;
+}
+/*- End of function --------------------------------------------------------*/
+
+void echo_can_flush(echo_can_state_t *ec)
+{
+ int i;
+
+ ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
+ ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
+ ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
+
+ ec->Lbgn = ec->Lbgn_acc = 0;
+ ec->Lbgn_upper = 200;
+ ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
+
+ ec->nonupdate_dwell = 0;
+
+ fir16_flush(&ec->fir_state);
+ fir16_flush(&ec->fir_state_bg);
+ ec->fir_state.curr_pos = ec->taps - 1;
+ ec->fir_state_bg.curr_pos = ec->taps - 1;
+ for (i = 0; i < 2; i++)
+ memset(ec->fir_taps16[i], 0, ec->taps*sizeof(int16_t));
+
+ ec->curr_pos = ec->taps - 1;
+ ec->Pstates = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+void echo_can_snapshot(echo_can_state_t *ec) {
+ memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps*sizeof(int16_t));
+}
+/*- End of function --------------------------------------------------------*/
+
+/* Dual Path Echo Canceller ------------------------------------------------*/
+
+int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
+{
+ int32_t echo_value;
+ int clean_bg;
+ int tmp, tmp1;
+
+ /* Input scaling was found be required to prevent problems when tx
+ starts clipping. Another possible way to handle this would be the
+ filter coefficent scaling. */
+
+ ec->tx = tx; ec->rx = rx;
+ tx >>=1;
+ rx >>=1;
+
+ /*
+ Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required
+ otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta)
+ only real axis. Some chip sets (like Si labs) don't need
+ this, but something like a $10 X100P card does. Any DC really slows
+ down convergence.
+
+ Note: removes some low frequency from the signal, this reduces
+ the speech quality when listening to samples through headphones
+ but may not be obvious through a telephone handset.
+
+ Note that the 3dB frequency in radians is approx Beta, e.g. for
+ Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
+ */
+
+ if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
+ tmp = rx << 15;
+#if 1
+ /* Make sure the gain of the HPF is 1.0. This can still saturate a little under
+ impulse conditions, and it might roll to 32768 and need clipping on sustained peak
+ level signals. However, the scale of such clipping is small, and the error due to
+ any saturation should not markedly affect the downstream processing. */
+ tmp -= (tmp >> 4);
+#endif
+ ec->rx_1 += -(ec->rx_1>>DC_LOG2BETA) + tmp - ec->rx_2;
+
+ /* hard limit filter to prevent clipping. Note that at this stage
+ rx should be limited to +/- 16383 due to right shift above */
+ tmp1 = ec->rx_1 >> 15;
+ if (tmp1 > 16383) tmp1 = 16383;
+ if (tmp1 < -16383) tmp1 = -16383;
+ rx = tmp1;
+ ec->rx_2 = tmp;
+ }
+
+ /* Block average of power in the filter states. Used for
+ adaption power calculation. */
+
+ {
+ int new, old;
+
+ /* efficient "out with the old and in with the new" algorithm so
+ we don't have to recalculate over the whole block of
+ samples. */
+ new = (int)tx * (int)tx;
+ old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
+ (int)ec->fir_state.history[ec->fir_state.curr_pos];
+ ec->Pstates += ((new - old) + (1<<ec->log2taps)) >> ec->log2taps;
+ if (ec->Pstates < 0) ec->Pstates = 0;
+ }
+
+ /* Calculate short term average levels using simple single pole IIRs */
+
+ ec->Ltxacc += abs(tx) - ec->Ltx;
+ ec->Ltx = (ec->Ltxacc + (1<<4)) >> 5;
+ ec->Lrxacc += abs(rx) - ec->Lrx;
+ ec->Lrx = (ec->Lrxacc + (1<<4)) >> 5;
+
+ /* Foreground filter ---------------------------------------------------*/
+
+ ec->fir_state.coeffs = ec->fir_taps16[0];
+ echo_value = fir16(&ec->fir_state, tx);
+ ec->clean = rx - echo_value;
+ ec->Lcleanacc += abs(ec->clean) - ec->Lclean;
+ ec->Lclean = (ec->Lcleanacc + (1<<4)) >> 5;
+
+ /* Background filter ---------------------------------------------------*/
+
+ echo_value = fir16(&ec->fir_state_bg, tx);
+ clean_bg = rx - echo_value;
+ ec->Lclean_bgacc += abs(clean_bg) - ec->Lclean_bg;
+ ec->Lclean_bg = (ec->Lclean_bgacc + (1<<4)) >> 5;
+
+ /* Background Filter adaption -----------------------------------------*/
+
+ /* Almost always adap bg filter, just simple DT and energy
+ detection to minimise adaption in cases of strong double talk.
+ However this is not critical for the dual path algorithm.
+ */
+ ec->factor = 0;
+ ec->shift = 0;
+ if ((ec->nonupdate_dwell == 0)) {
+ int P, logP, shift;
+
+ /* Determine:
+
+ f = Beta * clean_bg_rx/P ------ (1)
+
+ where P is the total power in the filter states.
+
+ The Boffins have shown that if we obey (1) we converge
+ quickly and avoid instability.
+
+ The correct factor f must be in Q30, as this is the fixed
+ point format required by the lms_adapt_bg() function,
+ therefore the scaled version of (1) is:
+
+ (2^30) * f = (2^30) * Beta * clean_bg_rx/P
+ factor = (2^30) * Beta * clean_bg_rx/P ----- (2)
+
+ We have chosen Beta = 0.25 by experiment, so:
+
+ factor = (2^30) * (2^-2) * clean_bg_rx/P
+
+ (30 - 2 - log2(P))
+ factor = clean_bg_rx 2 ----- (3)
+
+ To avoid a divide we approximate log2(P) as top_bit(P),
+ which returns the position of the highest non-zero bit in
+ P. This approximation introduces an error as large as a
+ factor of 2, but the algorithm seems to handle it OK.
+
+ Come to think of it a divide may not be a big deal on a
+ modern DSP, so its probably worth checking out the cycles
+ for a divide versus a top_bit() implementation.
+ */
+
+ P = MIN_TX_POWER_FOR_ADAPTION + ec->Pstates;
+ logP = top_bit(P) + ec->log2taps;
+ shift = 30 - 2 - logP;
+ ec->shift = shift;
+
+ lms_adapt_bg(ec, clean_bg, shift);
+ }
+
+ /* very simple DTD to make sure we dont try and adapt with strong
+ near end speech */
+
+ ec->adapt = 0;
+ if ((ec->Lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->Lrx > ec->Ltx))
+ ec->nonupdate_dwell = DTD_HANGOVER;
+ if (ec->nonupdate_dwell)
+ ec->nonupdate_dwell--;
+
+ /* Transfer logic ------------------------------------------------------*/
+
+ /* These conditions are from the dual path paper [1], I messed with
+ them a bit to improve performance. */
+
+ if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
+ (ec->nonupdate_dwell == 0) &&
+ (8*ec->Lclean_bg < 7*ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ &&
+ (8*ec->Lclean_bg < ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ )
+ {
+ if (ec->cond_met == 6) {
+ /* BG filter has had better results for 6 consecutive samples */
+ ec->adapt = 1;
+ memcpy(ec->fir_taps16[0], ec->fir_taps16[1], ec->taps*sizeof(int16_t));
+ }
+ else
+ ec->cond_met++;
+ }
+ else
+ ec->cond_met = 0;
+
+ /* Non-Linear Processing ---------------------------------------------------*/
+
+ ec->clean_nlp = ec->clean;
+ if (ec->adaption_mode & ECHO_CAN_USE_NLP)
+ {
+ /* Non-linear processor - a fancy way to say "zap small signals, to avoid
+ residual echo due to (uLaw/ALaw) non-linearity in the channel.". */
+
+ if ((16*ec->Lclean < ec->Ltx))
+ {
+ /* Our e/c has improved echo by at least 24 dB (each factor of 2 is 6dB,
+ so 2*2*2*2=16 is the same as 6+6+6+6=24dB) */
+ if (ec->adaption_mode & ECHO_CAN_USE_CNG)
+ {
+ ec->cng_level = ec->Lbgn;
+
+ /* Very elementary comfort noise generation. Just random
+ numbers rolled off very vaguely Hoth-like. DR: This
+ noise doesn't sound quite right to me - I suspect there
+ are some overlfow issues in the filtering as it's too
+ "crackly". TODO: debug this, maybe just play noise at
+ high level or look at spectrum.
+ */
+
+ ec->cng_rndnum = 1664525U*ec->cng_rndnum + 1013904223U;
+ ec->cng_filter = ((ec->cng_rndnum & 0xFFFF) - 32768 + 5*ec->cng_filter) >> 3;
+ ec->clean_nlp = (ec->cng_filter*ec->cng_level*8) >> 14;
+
+ }
+ else if (ec->adaption_mode & ECHO_CAN_USE_CLIP)
+ {
+ /* This sounds much better than CNG */
+ if (ec->clean_nlp > ec->Lbgn)
+ ec->clean_nlp = ec->Lbgn;
+ if (ec->clean_nlp < -ec->Lbgn)
+ ec->clean_nlp = -ec->Lbgn;
+ }
+ else
+ {
+ /* just mute the residual, doesn't sound very good, used mainly
+ in G168 tests */
+ ec->clean_nlp = 0;
+ }
+ }
+ else {
+ /* Background noise estimator. I tried a few algorithms
+ here without much luck. This very simple one seems to
+ work best, we just average the level using a slow (1 sec
+ time const) filter if the current level is less than a
+ (experimentally derived) constant. This means we dont
+ include high level signals like near end speech. When
+ combined with CNG or especially CLIP seems to work OK.
+ */
+ if (ec->Lclean < 40) {
+ ec->Lbgn_acc += abs(ec->clean) - ec->Lbgn;
+ ec->Lbgn = (ec->Lbgn_acc + (1<<11)) >> 12;
+ }
+ }
+ }
+
+ /* Roll around the taps buffer */
+ if (ec->curr_pos <= 0)
+ ec->curr_pos = ec->taps;
+ ec->curr_pos--;
+
+ if (ec->adaption_mode & ECHO_CAN_DISABLE)
+ ec->clean_nlp = rx;
+
+ /* Output scaled back up again to match input scaling */
+
+ return (int16_t) ec->clean_nlp << 1;
+}
+
+/*- End of function --------------------------------------------------------*/
+
+/* This function is seperated from the echo canceller is it is usually called
+ as part of the tx process. See rx HP (DC blocking) filter above, it's
+ the same design.
+
+ Some soft phones send speech signals with a lot of low frequency
+ energy, e.g. down to 20Hz. This can make the hybrid non-linear
+ which causes the echo canceller to fall over. This filter can help
+ by removing any low frequency before it gets to the tx port of the
+ hybrid.
+
+ It can also help by removing and DC in the tx signal. DC is bad
+ for LMS algorithms.
+
+ This is one of the classic DC removal filters, adjusted to provide sufficient
+ bass rolloff to meet the above requirement to protect hybrids from things that
+ upset them. The difference between successive samples produces a lousy HPF, and
+ then a suitably placed pole flattens things out. The final result is a nicely
+ rolled off bass end. The filtering is implemented with extended fractional
+ precision, which noise shapes things, giving very clean DC removal.
+*/
+
+int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx) {
+ int tmp, tmp1;
+
+ if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
+ tmp = tx << 15;
+#if 1
+ /* Make sure the gain of the HPF is 1.0. The first can still saturate a little under
+ impulse conditions, and it might roll to 32768 and need clipping on sustained peak
+ level signals. However, the scale of such clipping is small, and the error due to
+ any saturation should not markedly affect the downstream processing. */
+ tmp -= (tmp >> 4);
+#endif
+ ec->tx_1 += -(ec->tx_1>>DC_LOG2BETA) + tmp - ec->tx_2;
+ tmp1 = ec->tx_1 >> 15;
+ if (tmp1 > 32767) tmp1 = 32767;
+ if (tmp1 < -32767) tmp1 = -32767;
+ tx = tmp1;
+ ec->tx_2 = tmp;
+ }
+
+ return tx;
+}
diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h
new file mode 100644
index 00000000000..7a91b4390f3
--- /dev/null
+++ b/drivers/staging/echo/echo.h
@@ -0,0 +1,220 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * echo.c - A line echo canceller. This code is being developed
+ * against and partially complies with G168.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ * and David Rowe <david_at_rowetel_dot_com>
+ *
+ * Copyright (C) 2001 Steve Underwood and 2007 David Rowe
+ *
+ * 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 version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * $Id: echo.h,v 1.9 2006/10/24 13:45:28 steveu Exp $
+ */
+
+#ifndef __ECHO_H
+#define __ECHO_H
+
+/*! \page echo_can_page Line echo cancellation for voice
+
+\section echo_can_page_sec_1 What does it do?
+This module aims to provide G.168-2002 compliant echo cancellation, to remove
+electrical echoes (e.g. from 2-4 wire hybrids) from voice calls.
+
+\section echo_can_page_sec_2 How does it work?
+The heart of the echo cancellor is FIR filter. This is adapted to match the
+echo impulse response of the telephone line. It must be long enough to
+adequately cover the duration of that impulse response. The signal transmitted
+to the telephone line is passed through the FIR filter. Once the FIR is
+properly adapted, the resulting output is an estimate of the echo signal
+received from the line. This is subtracted from the received signal. The result
+is an estimate of the signal which originated at the far end of the line, free
+from echos of our own transmitted signal.
+
+The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and
+was introduced in 1960. It is the commonest form of filter adaption used in
+things like modem line equalisers and line echo cancellers. There it works very
+well. However, it only works well for signals of constant amplitude. It works
+very poorly for things like speech echo cancellation, where the signal level
+varies widely. This is quite easy to fix. If the signal level is normalised -
+similar to applying AGC - LMS can work as well for a signal of varying
+amplitude as it does for a modem signal. This normalised least mean squares
+(NLMS) algorithm is the commonest one used for speech echo cancellation. Many
+other algorithms exist - e.g. RLS (essentially the same as Kalman filtering),
+FAP, etc. Some perform significantly better than NLMS. However, factors such
+as computational complexity and patents favour the use of NLMS.
+
+A simple refinement to NLMS can improve its performance with speech. NLMS tends
+to adapt best to the strongest parts of a signal. If the signal is white noise,
+the NLMS algorithm works very well. However, speech has more low frequency than
+high frequency content. Pre-whitening (i.e. filtering the signal to flatten its
+spectrum) the echo signal improves the adapt rate for speech, and ensures the
+final residual signal is not heavily biased towards high frequencies. A very
+low complexity filter is adequate for this, so pre-whitening adds little to the
+compute requirements of the echo canceller.
+
+An FIR filter adapted using pre-whitened NLMS performs well, provided certain
+conditions are met:
+
+ - The transmitted signal has poor self-correlation.
+ - There is no signal being generated within the environment being
+ cancelled.
+
+The difficulty is that neither of these can be guaranteed.
+
+If the adaption is performed while transmitting noise (or something fairly
+noise like, such as voice) the adaption works very well. If the adaption is
+performed while transmitting something highly correlative (typically narrow
+band energy such as signalling tones or DTMF), the adaption can go seriously
+wrong. The reason is there is only one solution for the adaption on a near
+random signal - the impulse response of the line. For a repetitive signal,
+there are any number of solutions which converge the adaption, and nothing
+guides the adaption to choose the generalised one. Allowing an untrained
+canceller to converge on this kind of narrowband energy probably a good thing,
+since at least it cancels the tones. Allowing a well converged canceller to
+continue converging on such energy is just a way to ruin its generalised
+adaption. A narrowband detector is needed, so adapation can be suspended at
+appropriate times.
+
+The adaption process is based on trying to eliminate the received signal. When
+there is any signal from within the environment being cancelled it may upset
+the adaption process. Similarly, if the signal we are transmitting is small,
+noise may dominate and disturb the adaption process. If we can ensure that the
+adaption is only performed when we are transmitting a significant signal level,
+and the environment is not, things will be OK. Clearly, it is easy to tell when
+we are sending a significant signal. Telling, if the environment is generating
+a significant signal, and doing it with sufficient speed that the adaption will
+not have diverged too much more we stop it, is a little harder.
+
+The key problem in detecting when the environment is sourcing significant
+energy is that we must do this very quickly. Given a reasonably long sample of
+the received signal, there are a number of strategies which may be used to
+assess whether that signal contains a strong far end component. However, by the
+time that assessment is complete the far end signal will have already caused
+major mis-convergence in the adaption process. An assessment algorithm is
+needed which produces a fairly accurate result from a very short burst of far
+end energy.
+
+\section echo_can_page_sec_3 How do I use it?
+The echo cancellor processes both the transmit and receive streams sample by
+sample. The processing function is not declared inline. Unfortunately,
+cancellation requires many operations per sample, so the call overhead is only
+a minor burden.
+*/
+
+#include "fir.h"
+
+/* Mask bits for the adaption mode */
+#define ECHO_CAN_USE_ADAPTION 0x01
+#define ECHO_CAN_USE_NLP 0x02
+#define ECHO_CAN_USE_CNG 0x04
+#define ECHO_CAN_USE_CLIP 0x08
+#define ECHO_CAN_USE_TX_HPF 0x10
+#define ECHO_CAN_USE_RX_HPF 0x20
+#define ECHO_CAN_DISABLE 0x40
+
+/*!
+ G.168 echo canceller descriptor. This defines the working state for a line
+ echo canceller.
+*/
+typedef struct
+{
+ int16_t tx,rx;
+ int16_t clean;
+ int16_t clean_nlp;
+
+ int nonupdate_dwell;
+ int curr_pos;
+ int taps;
+ int log2taps;
+ int adaption_mode;
+
+ int cond_met;
+ int32_t Pstates;
+ int16_t adapt;
+ int32_t factor;
+ int16_t shift;
+
+ /* Average levels and averaging filter states */
+ int Ltxacc, Lrxacc, Lcleanacc, Lclean_bgacc;
+ int Ltx, Lrx;
+ int Lclean;
+ int Lclean_bg;
+ int Lbgn, Lbgn_acc, Lbgn_upper, Lbgn_upper_acc;
+
+ /* foreground and background filter states */
+ fir16_state_t fir_state;
+ fir16_state_t fir_state_bg;
+ int16_t *fir_taps16[2];
+
+ /* DC blocking filter states */
+ int tx_1, tx_2, rx_1, rx_2;
+
+ /* optional High Pass Filter states */
+ int32_t xvtx[5], yvtx[5];
+ int32_t xvrx[5], yvrx[5];
+
+ /* Parameters for the optional Hoth noise generator */
+ int cng_level;
+ int cng_rndnum;
+ int cng_filter;
+
+ /* snapshot sample of coeffs used for development */
+ int16_t *snapshot;
+} echo_can_state_t;
+
+/*! Create a voice echo canceller context.
+ \param len The length of the canceller, in samples.
+ \return The new canceller context, or NULL if the canceller could not be created.
+*/
+echo_can_state_t *echo_can_create(int len, int adaption_mode);
+
+/*! Free a voice echo canceller context.
+ \param ec The echo canceller context.
+*/
+void echo_can_free(echo_can_state_t *ec);
+
+/*! Flush (reinitialise) a voice echo canceller context.
+ \param ec The echo canceller context.
+*/
+void echo_can_flush(echo_can_state_t *ec);
+
+/*! Set the adaption mode of a voice echo canceller context.
+ \param ec The echo canceller context.
+ \param adapt The mode.
+*/
+void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode);
+
+void echo_can_snapshot(echo_can_state_t *ec);
+
+/*! Process a sample through a voice echo canceller.
+ \param ec The echo canceller context.
+ \param tx The transmitted audio sample.
+ \param rx The received audio sample.
+ \return The clean (echo cancelled) received sample.
+*/
+int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx);
+
+/*! Process to high pass filter the tx signal.
+ \param ec The echo canceller context.
+ \param tx The transmitted auio sample.
+ \return The HP filtered transmit sample, send this to your D/A.
+*/
+int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx);
+
+#endif /* __ECHO_H */
diff --git a/drivers/staging/echo/fir.h b/drivers/staging/echo/fir.h
new file mode 100644
index 00000000000..e1bfc499488
--- /dev/null
+++ b/drivers/staging/echo/fir.h
@@ -0,0 +1,369 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * fir.h - General telephony FIR routines
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2002 Steve Underwood
+ *
+ * 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 version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * $Id: fir.h,v 1.8 2006/10/24 13:45:28 steveu Exp $
+ */
+
+/*! \page fir_page FIR filtering
+\section fir_page_sec_1 What does it do?
+???.
+
+\section fir_page_sec_2 How does it work?
+???.
+*/
+
+#if !defined(_FIR_H_)
+#define _FIR_H_
+
+/*
+ Blackfin NOTES & IDEAS:
+
+ A simple dot product function is used to implement the filter. This performs
+ just one MAC/cycle which is inefficient but was easy to implement as a first
+ pass. The current Blackfin code also uses an unrolled form of the filter
+ history to avoid 0 length hardware loop issues. This is wasteful of
+ memory.
+
+ Ideas for improvement:
+
+ 1/ Rewrite filter for dual MAC inner loop. The issue here is handling
+ history sample offsets that are 16 bit aligned - the dual MAC needs
+ 32 bit aligmnent. There are some good examples in libbfdsp.
+
+ 2/ Use the hardware circular buffer facility tohalve memory usage.
+
+ 3/ Consider using internal memory.
+
+ Using less memory might also improve speed as cache misses will be
+ reduced. A drop in MIPs and memory approaching 50% should be
+ possible.
+
+ The foreground and background filters currenlty use a total of
+ about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
+ can.
+*/
+
+#if defined(USE_MMX) || defined(USE_SSE2)
+#include "mmx.h"
+#endif
+
+/*!
+ 16 bit integer FIR descriptor. This defines the working state for a single
+ instance of an FIR filter using 16 bit integer coefficients.
+*/
+typedef struct
+{
+ int taps;
+ int curr_pos;
+ const int16_t *coeffs;
+ int16_t *history;
+} fir16_state_t;
+
+/*!
+ 32 bit integer FIR descriptor. This defines the working state for a single
+ instance of an FIR filter using 32 bit integer coefficients, and filtering
+ 16 bit integer data.
+*/
+typedef struct
+{
+ int taps;
+ int curr_pos;
+ const int32_t *coeffs;
+ int16_t *history;
+} fir32_state_t;
+
+/*!
+ Floating point FIR descriptor. This defines the working state for a single
+ instance of an FIR filter using floating point coefficients and data.
+*/
+typedef struct
+{
+ int taps;
+ int curr_pos;
+ const float *coeffs;
+ float *history;
+} fir_float_state_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static __inline__ const int16_t *fir16_create(fir16_state_t *fir,
+ const int16_t *coeffs,
+ int taps)
+{
+ fir->taps = taps;
+ fir->curr_pos = taps - 1;
+ fir->coeffs = coeffs;
+#if defined(USE_MMX) || defined(USE_SSE2) || defined(__BLACKFIN_ASM__)
+ if ((fir->history = malloc(2*taps*sizeof(int16_t))))
+ memset(fir->history, 0, 2*taps*sizeof(int16_t));
+#else
+ if ((fir->history = (int16_t *) malloc(taps*sizeof(int16_t))))
+ memset(fir->history, 0, taps*sizeof(int16_t));
+#endif
+ return fir->history;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ void fir16_flush(fir16_state_t *fir)
+{
+#if defined(USE_MMX) || defined(USE_SSE2) || defined(__BLACKFIN_ASM__)
+ memset(fir->history, 0, 2*fir->taps*sizeof(int16_t));
+#else
+ memset(fir->history, 0, fir->taps*sizeof(int16_t));
+#endif
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ void fir16_free(fir16_state_t *fir)
+{
+ free(fir->history);
+}
+/*- End of function --------------------------------------------------------*/
+
+#ifdef __BLACKFIN_ASM__
+static inline int32_t dot_asm(short *x, short *y, int len)
+{
+ int dot;
+
+ len--;
+
+ __asm__
+ (
+ "I0 = %1;\n\t"
+ "I1 = %2;\n\t"
+ "A0 = 0;\n\t"
+ "R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+ "LOOP dot%= LC0 = %3;\n\t"
+ "LOOP_BEGIN dot%=;\n\t"
+ "A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t"
+ "LOOP_END dot%=;\n\t"
+ "A0 += R0.L*R1.L (IS);\n\t"
+ "R0 = A0;\n\t"
+ "%0 = R0;\n\t"
+ : "=&d" (dot)
+ : "a" (x), "a" (y), "a" (len)
+ : "I0", "I1", "A1", "A0", "R0", "R1"
+ );
+
+ return dot;
+}
+#endif
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int16_t fir16(fir16_state_t *fir, int16_t sample)
+{
+ int32_t y;
+#if defined(USE_MMX)
+ int i;
+ mmx_t *mmx_coeffs;
+ mmx_t *mmx_hist;
+
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+
+ mmx_coeffs = (mmx_t *) fir->coeffs;
+ mmx_hist = (mmx_t *) &fir->history[fir->curr_pos];
+ i = fir->taps;
+ pxor_r2r(mm4, mm4);
+ /* 8 samples per iteration, so the filter must be a multiple of 8 long. */
+ while (i > 0)
+ {
+ movq_m2r(mmx_coeffs[0], mm0);
+ movq_m2r(mmx_coeffs[1], mm2);
+ movq_m2r(mmx_hist[0], mm1);
+ movq_m2r(mmx_hist[1], mm3);
+ mmx_coeffs += 2;
+ mmx_hist += 2;
+ pmaddwd_r2r(mm1, mm0);
+ pmaddwd_r2r(mm3, mm2);
+ paddd_r2r(mm0, mm4);
+ paddd_r2r(mm2, mm4);
+ i -= 8;
+ }
+ movq_r2r(mm4, mm0);
+ psrlq_i2r(32, mm0);
+ paddd_r2r(mm0, mm4);
+ movd_r2m(mm4, y);
+ emms();
+#elif defined(USE_SSE2)
+ int i;
+ xmm_t *xmm_coeffs;
+ xmm_t *xmm_hist;
+
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+
+ xmm_coeffs = (xmm_t *) fir->coeffs;
+ xmm_hist = (xmm_t *) &fir->history[fir->curr_pos];
+ i = fir->taps;
+ pxor_r2r(xmm4, xmm4);
+ /* 16 samples per iteration, so the filter must be a multiple of 16 long. */
+ while (i > 0)
+ {
+ movdqu_m2r(xmm_coeffs[0], xmm0);
+ movdqu_m2r(xmm_coeffs[1], xmm2);
+ movdqu_m2r(xmm_hist[0], xmm1);
+ movdqu_m2r(xmm_hist[1], xmm3);
+ xmm_coeffs += 2;
+ xmm_hist += 2;
+ pmaddwd_r2r(xmm1, xmm0);
+ pmaddwd_r2r(xmm3, xmm2);
+ paddd_r2r(xmm0, xmm4);
+ paddd_r2r(xmm2, xmm4);
+ i -= 16;
+ }
+ movdqa_r2r(xmm4, xmm0);
+ psrldq_i2r(8, xmm0);
+ paddd_r2r(xmm0, xmm4);
+ movdqa_r2r(xmm4, xmm0);
+ psrldq_i2r(4, xmm0);
+ paddd_r2r(xmm0, xmm4);
+ movd_r2m(xmm4, y);
+#elif defined(__BLACKFIN_ASM__)
+ fir->history[fir->curr_pos] = sample;
+ fir->history[fir->curr_pos + fir->taps] = sample;
+ y = dot_asm((int16_t*)fir->coeffs, &fir->history[fir->curr_pos], fir->taps);
+#else
+ int i;
+ int offset1;
+ int offset2;
+
+ fir->history[fir->curr_pos] = sample;
+
+ offset2 = fir->curr_pos;
+ offset1 = fir->taps - offset2;
+ y = 0;
+ for (i = fir->taps - 1; i >= offset1; i--)
+ y += fir->coeffs[i]*fir->history[i - offset1];
+ for ( ; i >= 0; i--)
+ y += fir->coeffs[i]*fir->history[i + offset2];
+#endif
+ if (fir->curr_pos <= 0)
+ fir->curr_pos = fir->taps;
+ fir->curr_pos--;
+ return (int16_t) (y >> 15);
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ const int16_t *fir32_create(fir32_state_t *fir,
+ const int32_t *coeffs,
+ int taps)
+{
+ fir->taps = taps;
+ fir->curr_pos = taps - 1;
+ fir->coeffs = coeffs;
+ fir->history = (int16_t *) malloc(taps*sizeof(int16_t));
+ if (fir->history)
+ memset(fir->history, '\0', taps*sizeof(int16_t));
+ return fir->history;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ void fir32_flush(fir32_state_t *fir)
+{
+ memset(fir->history, 0, fir->taps*sizeof(int16_t));
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ void fir32_free(fir32_state_t *fir)
+{
+ free(fir->history);
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int16_t fir32(fir32_state_t *fir, int16_t sample)
+{
+ int i;
+ int32_t y;
+ int offset1;
+ int offset2;
+
+ fir->history[fir->curr_pos] = sample;
+ offset2 = fir->curr_pos;
+ offset1 = fir->taps - offset2;
+ y = 0;
+ for (i = fir->taps - 1; i >= offset1; i--)
+ y += fir->coeffs[i]*fir->history[i - offset1];
+ for ( ; i >= 0; i--)
+ y += fir->coeffs[i]*fir->history[i + offset2];
+ if (fir->curr_pos <= 0)
+ fir->curr_pos = fir->taps;
+ fir->curr_pos--;
+ return (int16_t) (y >> 15);
+}
+/*- End of function --------------------------------------------------------*/
+
+#ifndef __KERNEL__
+static __inline__ const float *fir_float_create(fir_float_state_t *fir,
+ const float *coeffs,
+ int taps)
+{
+ fir->taps = taps;
+ fir->curr_pos = taps - 1;
+ fir->coeffs = coeffs;
+ fir->history = (float *) malloc(taps*sizeof(float));
+ if (fir->history)
+ memset(fir->history, '\0', taps*sizeof(float));
+ return fir->history;
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ void fir_float_free(fir_float_state_t *fir)
+{
+ free(fir->history);
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ int16_t fir_float(fir_float_state_t *fir, int16_t sample)
+{
+ int i;
+ float y;
+ int offset1;
+ int offset2;
+
+ fir->history[fir->curr_pos] = sample;
+
+ offset2 = fir->curr_pos;
+ offset1 = fir->taps - offset2;
+ y = 0;
+ for (i = fir->taps - 1; i >= offset1; i--)
+ y += fir->coeffs[i]*fir->history[i - offset1];
+ for ( ; i >= 0; i--)
+ y += fir->coeffs[i]*fir->history[i + offset2];
+ if (fir->curr_pos <= 0)
+ fir->curr_pos = fir->taps;
+ fir->curr_pos--;
+ return (int16_t) y;
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/drivers/staging/echo/mmx.h b/drivers/staging/echo/mmx.h
new file mode 100644
index 00000000000..b5a3964865b
--- /dev/null
+++ b/drivers/staging/echo/mmx.h
@@ -0,0 +1,288 @@
+/*
+ * mmx.h
+ * Copyright (C) 1997-2001 H. Dietz and R. Fisher
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef AVCODEC_I386MMX_H
+#define AVCODEC_I386MMX_H
+
+/*
+ * The type of an value that fits in an MMX register (note that long
+ * long constant values MUST be suffixed by LL and unsigned long long
+ * values by ULL, lest they be truncated by the compiler)
+ */
+
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} mmx_t; /* On an 8-byte (64-bit) boundary */
+
+/* SSE registers */
+typedef union {
+ char b[16];
+} xmm_t;
+
+
+#define mmx_i2r(op,imm,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "i" (imm) )
+
+#define mmx_m2r(op,mem,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "m" (mem))
+
+#define mmx_r2m(op,reg,mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=m" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op,regs,regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
+#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
+#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
+
+#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
+#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
+#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
+
+#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
+#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
+#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
+#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
+
+#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
+#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
+
+#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
+#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
+#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
+#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
+#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
+#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
+
+#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
+#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
+#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
+#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
+
+#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
+#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
+#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
+#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
+
+#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
+#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
+
+#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
+#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
+
+#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
+#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
+#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
+
+#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
+#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
+#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
+
+#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
+#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
+
+#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
+#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
+
+#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
+#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
+
+#define por_m2r(var,reg) mmx_m2r (por, var, reg)
+#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
+
+#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
+#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
+#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
+#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
+#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
+#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
+#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
+#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
+#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
+
+#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
+#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
+#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
+#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
+#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
+#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
+
+#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
+#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
+#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
+#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
+#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
+#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
+#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
+#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
+#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
+
+#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
+#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
+#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
+#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
+#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
+#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
+
+#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
+#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
+#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
+#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
+
+#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
+#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
+#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
+#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
+
+#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
+#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
+#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
+#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
+#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
+#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
+
+#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
+#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
+#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
+#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
+#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
+#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
+
+#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
+#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
+
+
+/* 3DNOW extensions */
+
+#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
+#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
+
+
+/* AMD MMX extensions - also available in intel SSE */
+
+
+#define mmx_m2ri(op,mem,reg,imm) \
+ __asm__ __volatile__ (#op " %1, %0, %%" #reg \
+ : /* nothing */ \
+ : "m" (mem), "i" (imm))
+#define mmx_r2ri(op,regs,regd,imm) \
+ __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
+ : /* nothing */ \
+ : "i" (imm) )
+
+#define mmx_fetch(mem,hint) \
+ __asm__ __volatile__ ("prefetch" #hint " %0" \
+ : /* nothing */ \
+ : "m" (mem))
+
+
+#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
+
+#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
+
+#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
+#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
+#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
+#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
+
+#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
+
+#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
+
+#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
+#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
+
+#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
+#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
+
+#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
+#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
+
+#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
+#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
+
+#define pmovmskb(mmreg,reg) \
+ __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
+
+#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
+#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
+
+#define prefetcht0(mem) mmx_fetch (mem, t0)
+#define prefetcht1(mem) mmx_fetch (mem, t1)
+#define prefetcht2(mem) mmx_fetch (mem, t2)
+#define prefetchnta(mem) mmx_fetch (mem, nta)
+
+#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
+#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
+
+#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
+#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
+
+#define sfence() __asm__ __volatile__ ("sfence\n\t")
+
+/* SSE2 */
+#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm)
+#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm)
+#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm)
+#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm)
+
+#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm)
+
+#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg)
+#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var)
+#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd)
+#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg)
+#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var)
+#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd)
+
+#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var)
+
+#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg)
+#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg)
+
+#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
+#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
+
+
+#endif /* AVCODEC_I386MMX_H */
diff --git a/drivers/staging/et131x/Kconfig b/drivers/staging/et131x/Kconfig
new file mode 100644
index 00000000000..e11cf340856
--- /dev/null
+++ b/drivers/staging/et131x/Kconfig
@@ -0,0 +1,18 @@
+config ET131X
+ tristate "Agere ET-1310 Gigabit Ethernet support"
+ depends on NETDEV_1000 && PCI
+ default n
+ ---help---
+ This driver supports Agere ET-1310 ethernet adapters.
+
+ To compile this driver as a module, choose M here. The module
+ will be called et131x.
+
+config ET131X_DEBUG
+ bool "Enable et131x debugging"
+ depends on ET131X
+ default n
+ ---help---
+ Say Y for detailed debug information.
+
+ If in doubt, say N.
diff --git a/drivers/staging/et131x/Makefile b/drivers/staging/et131x/Makefile
new file mode 100644
index 00000000000..3ad571d8a68
--- /dev/null
+++ b/drivers/staging/et131x/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Agere ET-131x ethernet driver
+#
+
+obj-$(CONFIG_ET131X) += et131x.o
+
+et131x-objs := et1310_eeprom.o \
+ et1310_jagcore.o \
+ et1310_mac.o \
+ et1310_phy.o \
+ et1310_pm.o \
+ et1310_rx.o \
+ et1310_tx.o \
+ et131x_config.o \
+ et131x_debug.o \
+ et131x_initpci.o \
+ et131x_isr.o \
+ et131x_netdev.o
diff --git a/drivers/staging/et131x/README b/drivers/staging/et131x/README
new file mode 100644
index 00000000000..28752a50231
--- /dev/null
+++ b/drivers/staging/et131x/README
@@ -0,0 +1,25 @@
+This is a driver for the ET1310 network device.
+
+Based on the driver found at https://sourceforge.net/projects/et131x/
+
+Cleaned up immensely by Olaf Hartman <o.hartmann@telovital.com> and Christoph
+Hellwig <hch@infradead.org>
+
+Note, the powermanagement options were removed from the vendor provided
+driver as they did not build properly at the time.
+
+TODO:
+ - kernel coding style cleanups
+ - forward port for latest network driver changes
+ - kill useless typecasts (e.g. in et1310_phy.c)
+ - alloc_etherdev is initializing memory with zero?!?
+ - add_timer call in et131x_netdev.c is correct?
+ - Add power saving functionality (suspend, sleep, resume)
+ - Implement a few more kernel Parameter (set mac )
+
+Please send patches to:
+ Greg Kroah-Hartman <gregkh@suse.de>
+
+And Cc: Olaf Hartmann <o.hartmann@telovital.com> as he has this device and can
+test any changes.
+
diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h
new file mode 100644
index 00000000000..3c85999d64d
--- /dev/null
+++ b/drivers/staging/et131x/et1310_address_map.h
@@ -0,0 +1,2399 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_address_map.h - Contains the register mapping for the ET1310
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef _ET1310_ADDRESS_MAP_H_
+#define _ET1310_ADDRESS_MAP_H_
+
+
+/* START OF GLOBAL REGISTER ADDRESS MAP */
+
+typedef union _Q_ADDR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:22; // bits 10-31
+ u32 addr:10; // bits 0-9
+#else
+ u32 addr:10; // bits 0-9
+ u32 unused:22; // bits 10-31
+#endif
+ } bits;
+} Q_ADDR_t, *PQ_ADDR_t;
+
+/*
+ * structure for tx queue start address reg in global address map
+ * located at address 0x0000
+ * Defined earlier (Q_ADDR_t)
+ */
+
+/*
+ * structure for tx queue end address reg in global address map
+ * located at address 0x0004
+ * Defined earlier (Q_ADDR_t)
+ */
+
+/*
+ * structure for rx queue start address reg in global address map
+ * located at address 0x0008
+ * Defined earlier (Q_ADDR_t)
+ */
+
+/*
+ * structure for rx queue end address reg in global address map
+ * located at address 0x000C
+ * Defined earlier (Q_ADDR_t)
+ */
+
+/*
+ * structure for power management control status reg in global address map
+ * located at address 0x0010
+ */
+typedef union _PM_CSR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:22; // bits 10-31
+ u32 pm_jagcore_rx_rdy:1; // bit 9
+ u32 pm_jagcore_tx_rdy:1; // bit 8
+ u32 pm_phy_lped_en:1; // bit 7
+ u32 pm_phy_sw_coma:1; // bit 6
+ u32 pm_rxclk_gate:1; // bit 5
+ u32 pm_txclk_gate:1; // bit 4
+ u32 pm_sysclk_gate:1; // bit 3
+ u32 pm_jagcore_rx_en:1; // bit 2
+ u32 pm_jagcore_tx_en:1; // bit 1
+ u32 pm_gigephy_en:1; // bit 0
+#else
+ u32 pm_gigephy_en:1; // bit 0
+ u32 pm_jagcore_tx_en:1; // bit 1
+ u32 pm_jagcore_rx_en:1; // bit 2
+ u32 pm_sysclk_gate:1; // bit 3
+ u32 pm_txclk_gate:1; // bit 4
+ u32 pm_rxclk_gate:1; // bit 5
+ u32 pm_phy_sw_coma:1; // bit 6
+ u32 pm_phy_lped_en:1; // bit 7
+ u32 pm_jagcore_tx_rdy:1; // bit 8
+ u32 pm_jagcore_rx_rdy:1; // bit 9
+ u32 unused:22; // bits 10-31
+#endif
+ } bits;
+} PM_CSR_t, *PPM_CSR_t;
+
+/*
+ * structure for interrupt status reg in global address map
+ * located at address 0x0018
+ */
+typedef union _INTERRUPT_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused5:11; // bits 21-31
+ u32 slv_timeout:1; // bit 20
+ u32 mac_stat_interrupt:1; // bit 19
+ u32 rxmac_interrupt:1; // bit 18
+ u32 txmac_interrupt:1; // bit 17
+ u32 phy_interrupt:1; // bit 16
+ u32 wake_on_lan:1; // bit 15
+ u32 watchdog_interrupt:1; // bit 14
+ u32 unused4:4; // bits 10-13
+ u32 rxdma_err:1; // bit 9
+ u32 rxdma_pkt_stat_ring_low:1; // bit 8
+ u32 rxdma_fb_ring1_low:1; // bit 7
+ u32 rxdma_fb_ring0_low:1; // bit 6
+ u32 rxdma_xfr_done:1; // bit 5
+ u32 txdma_err:1; // bit 4
+ u32 txdma_isr:1; // bit 3
+ u32 unused3:1; // bit 2
+ u32 unused2:1; // bit 1
+ u32 unused1:1; // bit 0
+#else
+ u32 unused1:1; // bit 0
+ u32 unused2:1; // bit 1
+ u32 unused3:1; // bit 2
+ u32 txdma_isr:1; // bit 3
+ u32 txdma_err:1; // bit 4
+ u32 rxdma_xfr_done:1; // bit 5
+ u32 rxdma_fb_ring0_low:1; // bit 6
+ u32 rxdma_fb_ring1_low:1; // bit 7
+ u32 rxdma_pkt_stat_ring_low:1; // bit 8
+ u32 rxdma_err:1; // bit 9
+ u32 unused4:4; // bits 10-13
+ u32 watchdog_interrupt:1; // bit 14
+ u32 wake_on_lan:1; // bit 15
+ u32 phy_interrupt:1; // bit 16
+ u32 txmac_interrupt:1; // bit 17
+ u32 rxmac_interrupt:1; // bit 18
+ u32 mac_stat_interrupt:1; // bit 19
+ u32 slv_timeout:1; // bit 20
+ u32 unused5:11; // bits 21-31
+#endif
+ } bits;
+} INTERRUPT_t, *PINTERRUPT_t;
+
+/*
+ * structure for interrupt mask reg in global address map
+ * located at address 0x001C
+ * Defined earlier (INTERRUPT_t), but 'watchdog_interrupt' is not used.
+ */
+
+/*
+ * structure for interrupt alias clear mask reg in global address map
+ * located at address 0x0020
+ * Defined earlier (INTERRUPT_t)
+ */
+
+/*
+ * structure for interrupt status alias reg in global address map
+ * located at address 0x0024
+ * Defined earlier (INTERRUPT_t)
+ */
+
+/*
+ * structure for software reset reg in global address map
+ * located at address 0x0028
+ */
+typedef union _SW_RESET_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 selfclr_disable:1; // bit 31
+ u32 unused:24; // bits 7-30
+ u32 mmc_sw_reset:1; // bit 6
+ u32 mac_stat_sw_reset:1; // bit 5
+ u32 mac_sw_reset:1; // bit 4
+ u32 rxmac_sw_reset:1; // bit 3
+ u32 txmac_sw_reset:1; // bit 2
+ u32 rxdma_sw_reset:1; // bit 1
+ u32 txdma_sw_reset:1; // bit 0
+#else
+ u32 txdma_sw_reset:1; // bit 0
+ u32 rxdma_sw_reset:1; // bit 1
+ u32 txmac_sw_reset:1; // bit 2
+ u32 rxmac_sw_reset:1; // bit 3
+ u32 mac_sw_reset:1; // bit 4
+ u32 mac_stat_sw_reset:1; // bit 5
+ u32 mmc_sw_reset:1; // bit 6
+ u32 unused:24; // bits 7-30
+ u32 selfclr_disable:1; // bit 31
+#endif
+ } bits;
+} SW_RESET_t, *PSW_RESET_t;
+
+/*
+ * structure for SLV Timer reg in global address map
+ * located at address 0x002C
+ */
+typedef union _SLV_TIMER_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:8; // bits 24-31
+ u32 timer_ini:24; // bits 0-23
+#else
+ u32 timer_ini:24; // bits 0-23
+ u32 unused:8; // bits 24-31
+#endif
+ } bits;
+} SLV_TIMER_t, *PSLV_TIMER_t;
+
+/*
+ * structure for MSI Configuration reg in global address map
+ * located at address 0x0030
+ */
+typedef union _MSI_CONFIG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused1:13; // bits 19-31
+ u32 msi_tc:3; // bits 16-18
+ u32 unused2:11; // bits 5-15
+ u32 msi_vector:5; // bits 0-4
+#else
+ u32 msi_vector:5; // bits 0-4
+ u32 unused2:11; // bits 5-15
+ u32 msi_tc:3; // bits 16-18
+ u32 unused1:13; // bits 19-31
+#endif
+ } bits;
+} MSI_CONFIG_t, *PMSI_CONFIG_t;
+
+/*
+ * structure for Loopback reg in global address map
+ * located at address 0x0034
+ */
+typedef union _LOOPBACK_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:30; // bits 2-31
+ u32 dma_loopback:1; // bit 1
+ u32 mac_loopback:1; // bit 0
+#else
+ u32 mac_loopback:1; // bit 0
+ u32 dma_loopback:1; // bit 1
+ u32 unused:30; // bits 2-31
+#endif
+ } bits;
+} LOOPBACK_t, *PLOOPBACK_t;
+
+/*
+ * GLOBAL Module of JAGCore Address Mapping
+ * Located at address 0x0000
+ */
+typedef struct _GLOBAL_t { // Location:
+ Q_ADDR_t txq_start_addr; // 0x0000
+ Q_ADDR_t txq_end_addr; // 0x0004
+ Q_ADDR_t rxq_start_addr; // 0x0008
+ Q_ADDR_t rxq_end_addr; // 0x000C
+ PM_CSR_t pm_csr; // 0x0010
+ u32 unused; // 0x0014
+ INTERRUPT_t int_status; // 0x0018
+ INTERRUPT_t int_mask; // 0x001C
+ INTERRUPT_t int_alias_clr_en; // 0x0020
+ INTERRUPT_t int_status_alias; // 0x0024
+ SW_RESET_t sw_reset; // 0x0028
+ SLV_TIMER_t slv_timer; // 0x002C
+ MSI_CONFIG_t msi_config; // 0x0030
+ LOOPBACK_t loopback; // 0x0034
+ u32 watchdog_timer; // 0x0038
+} GLOBAL_t, *PGLOBAL_t;
+
+/* END OF GLOBAL REGISTER ADDRESS MAP */
+
+
+/* START OF TXDMA REGISTER ADDRESS MAP */
+
+/*
+ * structure for txdma control status reg in txdma address map
+ * located at address 0x1000
+ */
+typedef union _TXDMA_CSR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:19; // bits 13-31
+ u32 traffic_class:4; // bits 9-12
+ u32 sngl_epkt_mode:1; // bit 8
+ u32 cache_thrshld:4; // bits 4-7
+ u32 unused1:2; // bits 2-3
+ u32 drop_TLP_disable:1; // bit 1
+ u32 halt:1; // bit 0
+#else
+ u32 halt:1; // bit 0
+ u32 drop_TLP_disable:1; // bit 1
+ u32 unused1:2; // bits 2-3
+ u32 cache_thrshld:4; // bits 4-7
+ u32 sngl_epkt_mode:1; // bit 8
+ u32 traffic_class:4; // bits 9-12
+ u32 unused2:19; // bits 13-31
+#endif
+ } bits;
+} TXDMA_CSR_t, *PTXDMA_CSR_t;
+
+/*
+ * structure for txdma packet ring base address hi reg in txdma address map
+ * located at address 0x1004
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for txdma packet ring base address low reg in txdma address map
+ * located at address 0x1008
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for txdma packet ring number of descriptor reg in txdma address
+ * map. Located at address 0x100C
+ */
+typedef union _TXDMA_PR_NUM_DES_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:22; // bits 10-31
+ u32 pr_ndes:10; // bits 0-9
+#else
+ u32 pr_ndes:10; // bits 0-9
+ u32 unused:22; // bits 10-31
+#endif
+ } bits;
+} TXDMA_PR_NUM_DES_t, *PTXDMA_PR_NUM_DES_t;
+
+
+typedef union _DMA10W_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:21; // bits 11-31
+ u32 wrap:1; // bit 10
+ u32 val:10; // bits 0-9
+#else
+ u32 val:10; // bits 0-9
+ u32 wrap:1; // bit 10
+ u32 unused:21; // bits 11-31
+#endif
+ } bits;
+} DMA10W_t, *PDMA10W_t;
+
+/*
+ * structure for txdma tx queue write address reg in txdma address map
+ * located at address 0x1010
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for txdma tx queue write address external reg in txdma address map
+ * located at address 0x1014
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for txdma tx queue read address reg in txdma address map
+ * located at address 0x1018
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for txdma status writeback address hi reg in txdma address map
+ * located at address 0x101C
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for txdma status writeback address lo reg in txdma address map
+ * located at address 0x1020
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for txdma service request reg in txdma address map
+ * located at address 0x1024
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for txdma service complete reg in txdma address map
+ * located at address 0x1028
+ * Defined earlier (DMA10W_t)
+ */
+
+typedef union _DMA4W_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:27; // bits 5-31
+ u32 wrap:1; // bit 4
+ u32 val:4; // bit 0-3
+#else
+ u32 val:4; // bits 0-3
+ u32 wrap:1; // bit 4
+ u32 unused:27; // bits 5-31
+#endif
+ } bits;
+} DMA4W_t, *PDMA4W_t;
+
+/*
+ * structure for txdma tx descriptor cache read index reg in txdma address map
+ * located at address 0x102C
+ * Defined earlier (DMA4W_t)
+ */
+
+/*
+ * structure for txdma tx descriptor cache write index reg in txdma address map
+ * located at address 0x1030
+ * Defined earlier (DMA4W_t)
+ */
+
+/*
+ * structure for txdma error reg in txdma address map
+ * located at address 0x1034
+ */
+typedef union _TXDMA_ERROR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused3:22; // bits 10-31
+ u32 WrbkRewind:1; // bit 9
+ u32 WrbkResend:1; // bit 8
+ u32 unused2:2; // bits 6-7
+ u32 DescrRewind:1; // bit 5
+ u32 DescrResend:1; // bit 4
+ u32 unused1:2; // bits 2-3
+ u32 PyldRewind:1; // bit 1
+ u32 PyldResend:1; // bit 0
+#else
+ u32 PyldResend:1; // bit 0
+ u32 PyldRewind:1; // bit 1
+ u32 unused1:2; // bits 2-3
+ u32 DescrResend:1; // bit 4
+ u32 DescrRewind:1; // bit 5
+ u32 unused2:2; // bits 6-7
+ u32 WrbkResend:1; // bit 8
+ u32 WrbkRewind:1; // bit 9
+ u32 unused3:22; // bits 10-31
+#endif
+ } bits;
+} TXDMA_ERROR_t, *PTXDMA_ERROR_t;
+
+/*
+ * Tx DMA Module of JAGCore Address Mapping
+ * Located at address 0x1000
+ */
+typedef struct _TXDMA_t { // Location:
+ TXDMA_CSR_t csr; // 0x1000
+ u32 pr_base_hi; // 0x1004
+ u32 pr_base_lo; // 0x1008
+ TXDMA_PR_NUM_DES_t pr_num_des; // 0x100C
+ DMA10W_t txq_wr_addr; // 0x1010
+ DMA10W_t txq_wr_addr_ext; // 0x1014
+ DMA10W_t txq_rd_addr; // 0x1018
+ u32 dma_wb_base_hi; // 0x101C
+ u32 dma_wb_base_lo; // 0x1020
+ DMA10W_t service_request; // 0x1024
+ DMA10W_t service_complete; // 0x1028
+ DMA4W_t cache_rd_index; // 0x102C
+ DMA4W_t cache_wr_index; // 0x1030
+ TXDMA_ERROR_t TxDmaError; // 0x1034
+ u32 DescAbortCount; // 0x1038
+ u32 PayloadAbortCnt; // 0x103c
+ u32 WriteBackAbortCnt; // 0x1040
+ u32 DescTimeoutCnt; // 0x1044
+ u32 PayloadTimeoutCnt; // 0x1048
+ u32 WriteBackTimeoutCnt; // 0x104c
+ u32 DescErrorCount; // 0x1050
+ u32 PayloadErrorCnt; // 0x1054
+ u32 WriteBackErrorCnt; // 0x1058
+ u32 DroppedTLPCount; // 0x105c
+ DMA10W_t NewServiceComplete; // 0x1060
+ u32 EthernetPacketCount; // 0x1064
+} TXDMA_t, *PTXDMA_t;
+
+/* END OF TXDMA REGISTER ADDRESS MAP */
+
+
+/* START OF RXDMA REGISTER ADDRESS MAP */
+
+/*
+ * structure for control status reg in rxdma address map
+ * Located at address 0x2000
+ */
+typedef union _RXDMA_CSR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:14; // bits 18-31
+ u32 halt_status:1; // bit 17
+ u32 pkt_done_flush:1; // bit 16
+ u32 pkt_drop_disable:1; // bit 15
+ u32 unused1:1; // bit 14
+ u32 fbr1_enable:1; // bit 13
+ u32 fbr1_size:2; // bits 11-12
+ u32 fbr0_enable:1; // bit 10
+ u32 fbr0_size:2; // bits 8-9
+ u32 dma_big_endian:1; // bit 7
+ u32 pkt_big_endian:1; // bit 6
+ u32 psr_big_endian:1; // bit 5
+ u32 fbr_big_endian:1; // bit 4
+ u32 tc:3; // bits 1-3
+ u32 halt:1; // bit 0
+#else
+ u32 halt:1; // bit 0
+ u32 tc:3; // bits 1-3
+ u32 fbr_big_endian:1; // bit 4
+ u32 psr_big_endian:1; // bit 5
+ u32 pkt_big_endian:1; // bit 6
+ u32 dma_big_endian:1; // bit 7
+ u32 fbr0_size:2; // bits 8-9
+ u32 fbr0_enable:1; // bit 10
+ u32 fbr1_size:2; // bits 11-12
+ u32 fbr1_enable:1; // bit 13
+ u32 unused1:1; // bit 14
+ u32 pkt_drop_disable:1; // bit 15
+ u32 pkt_done_flush:1; // bit 16
+ u32 halt_status:1; // bit 17
+ u32 unused2:14; // bits 18-31
+#endif
+ } bits;
+} RXDMA_CSR_t, *PRXDMA_CSR_t;
+
+/*
+ * structure for dma writeback lo reg in rxdma address map
+ * located at address 0x2004
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for dma writeback hi reg in rxdma address map
+ * located at address 0x2008
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for number of packets done reg in rxdma address map
+ * located at address 0x200C
+ */
+typedef union _RXDMA_NUM_PKT_DONE_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:24; // bits 8-31
+ u32 num_done:8; // bits 0-7
+#else
+ u32 num_done:8; // bits 0-7
+ u32 unused:24; // bits 8-31
+#endif
+ } bits;
+} RXDMA_NUM_PKT_DONE_t, *PRXDMA_NUM_PKT_DONE_t;
+
+/*
+ * structure for max packet time reg in rxdma address map
+ * located at address 0x2010
+ */
+typedef union _RXDMA_MAX_PKT_TIME_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:14; // bits 18-31
+ u32 time_done:18; // bits 0-17
+#else
+ u32 time_done:18; // bits 0-17
+ u32 unused:14; // bits 18-31
+#endif
+ } bits;
+} RXDMA_MAX_PKT_TIME_t, *PRXDMA_MAX_PKT_TIME_t;
+
+/*
+ * structure for rx queue read address reg in rxdma address map
+ * located at address 0x2014
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for rx queue read address external reg in rxdma address map
+ * located at address 0x2018
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for rx queue write address reg in rxdma address map
+ * located at address 0x201C
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for packet status ring base address lo reg in rxdma address map
+ * located at address 0x2020
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for packet status ring base address hi reg in rxdma address map
+ * located at address 0x2024
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for packet status ring number of descriptors reg in rxdma address
+ * map. Located at address 0x2028
+ */
+typedef union _RXDMA_PSR_NUM_DES_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:20; // bits 12-31
+ u32 psr_ndes:12; // bit 0-11
+#else
+ u32 psr_ndes:12; // bit 0-11
+ u32 unused:20; // bits 12-31
+#endif
+ } bits;
+} RXDMA_PSR_NUM_DES_t, *PRXDMA_PSR_NUM_DES_t;
+
+/*
+ * structure for packet status ring available offset reg in rxdma address map
+ * located at address 0x202C
+ */
+typedef union _RXDMA_PSR_AVAIL_OFFSET_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:19; // bits 13-31
+ u32 psr_avail_wrap:1; // bit 12
+ u32 psr_avail:12; // bit 0-11
+#else
+ u32 psr_avail:12; // bit 0-11
+ u32 psr_avail_wrap:1; // bit 12
+ u32 unused:19; // bits 13-31
+#endif
+ } bits;
+} RXDMA_PSR_AVAIL_OFFSET_t, *PRXDMA_PSR_AVAIL_OFFSET_t;
+
+/*
+ * structure for packet status ring full offset reg in rxdma address map
+ * located at address 0x2030
+ */
+typedef union _RXDMA_PSR_FULL_OFFSET_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:19; // bits 13-31
+ u32 psr_full_wrap:1; // bit 12
+ u32 psr_full:12; // bit 0-11
+#else
+ u32 psr_full:12; // bit 0-11
+ u32 psr_full_wrap:1; // bit 12
+ u32 unused:19; // bits 13-31
+#endif
+ } bits;
+} RXDMA_PSR_FULL_OFFSET_t, *PRXDMA_PSR_FULL_OFFSET_t;
+
+/*
+ * structure for packet status ring access index reg in rxdma address map
+ * located at address 0x2034
+ */
+typedef union _RXDMA_PSR_ACCESS_INDEX_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:27; // bits 5-31
+ u32 psr_ai:5; // bits 0-4
+#else
+ u32 psr_ai:5; // bits 0-4
+ u32 unused:27; // bits 5-31
+#endif
+ } bits;
+} RXDMA_PSR_ACCESS_INDEX_t, *PRXDMA_PSR_ACCESS_INDEX_t;
+
+/*
+ * structure for packet status ring minimum descriptors reg in rxdma address
+ * map. Located at address 0x2038
+ */
+typedef union _RXDMA_PSR_MIN_DES_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:20; // bits 12-31
+ u32 psr_min:12; // bits 0-11
+#else
+ u32 psr_min:12; // bits 0-11
+ u32 unused:20; // bits 12-31
+#endif
+ } bits;
+} RXDMA_PSR_MIN_DES_t, *PRXDMA_PSR_MIN_DES_t;
+
+/*
+ * structure for free buffer ring base lo address reg in rxdma address map
+ * located at address 0x203C
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for free buffer ring base hi address reg in rxdma address map
+ * located at address 0x2040
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for free buffer ring number of descriptors reg in rxdma address
+ * map. Located at address 0x2044
+ */
+typedef union _RXDMA_FBR_NUM_DES_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:22; // bits 10-31
+ u32 fbr_ndesc:10; // bits 0-9
+#else
+ u32 fbr_ndesc:10; // bits 0-9
+ u32 unused:22; // bits 10-31
+#endif
+ } bits;
+} RXDMA_FBR_NUM_DES_t, *PRXDMA_FBR_NUM_DES_t;
+
+/*
+ * structure for free buffer ring 0 available offset reg in rxdma address map
+ * located at address 0x2048
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for free buffer ring 0 full offset reg in rxdma address map
+ * located at address 0x204C
+ * Defined earlier (DMA10W_t)
+ */
+
+/*
+ * structure for free buffer cache 0 full offset reg in rxdma address map
+ * located at address 0x2050
+ */
+typedef union _RXDMA_FBC_RD_INDEX_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:27; // bits 5-31
+ u32 fbc_rdi:5; // bit 0-4
+#else
+ u32 fbc_rdi:5; // bit 0-4
+ u32 unused:27; // bits 5-31
+#endif
+ } bits;
+} RXDMA_FBC_RD_INDEX_t, *PRXDMA_FBC_RD_INDEX_t;
+
+/*
+ * structure for free buffer ring 0 minimum descriptor reg in rxdma address map
+ * located at address 0x2054
+ */
+typedef union _RXDMA_FBR_MIN_DES_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:22; // bits 10-31
+ u32 fbr_min:10; // bits 0-9
+#else
+ u32 fbr_min:10; // bits 0-9
+ u32 unused:22; // bits 10-31
+#endif
+ } bits;
+} RXDMA_FBR_MIN_DES_t, *PRXDMA_FBR_MIN_DES_t;
+
+/*
+ * structure for free buffer ring 1 base address lo reg in rxdma address map
+ * located at address 0x2058 - 0x205C
+ * Defined earlier (RXDMA_FBR_BASE_LO_t and RXDMA_FBR_BASE_HI_t)
+ */
+
+/*
+ * structure for free buffer ring 1 number of descriptors reg in rxdma address
+ * map. Located at address 0x2060
+ * Defined earlier (RXDMA_FBR_NUM_DES_t)
+ */
+
+/*
+ * structure for free buffer ring 1 available offset reg in rxdma address map
+ * located at address 0x2064
+ * Defined Earlier (RXDMA_FBR_AVAIL_OFFSET_t)
+ */
+
+/*
+ * structure for free buffer ring 1 full offset reg in rxdma address map
+ * located at address 0x2068
+ * Defined Earlier (RXDMA_FBR_FULL_OFFSET_t)
+ */
+
+/*
+ * structure for free buffer cache 1 read index reg in rxdma address map
+ * located at address 0x206C
+ * Defined Earlier (RXDMA_FBC_RD_INDEX_t)
+ */
+
+/*
+ * structure for free buffer ring 1 minimum descriptor reg in rxdma address map
+ * located at address 0x2070
+ * Defined Earlier (RXDMA_FBR_MIN_DES_t)
+ */
+
+/*
+ * Rx DMA Module of JAGCore Address Mapping
+ * Located at address 0x2000
+ */
+typedef struct _RXDMA_t { // Location:
+ RXDMA_CSR_t csr; // 0x2000
+ u32 dma_wb_base_lo; // 0x2004
+ u32 dma_wb_base_hi; // 0x2008
+ RXDMA_NUM_PKT_DONE_t num_pkt_done; // 0x200C
+ RXDMA_MAX_PKT_TIME_t max_pkt_time; // 0x2010
+ DMA10W_t rxq_rd_addr; // 0x2014
+ DMA10W_t rxq_rd_addr_ext; // 0x2018
+ DMA10W_t rxq_wr_addr; // 0x201C
+ u32 psr_base_lo; // 0x2020
+ u32 psr_base_hi; // 0x2024
+ RXDMA_PSR_NUM_DES_t psr_num_des; // 0x2028
+ RXDMA_PSR_AVAIL_OFFSET_t psr_avail_offset; // 0x202C
+ RXDMA_PSR_FULL_OFFSET_t psr_full_offset; // 0x2030
+ RXDMA_PSR_ACCESS_INDEX_t psr_access_index; // 0x2034
+ RXDMA_PSR_MIN_DES_t psr_min_des; // 0x2038
+ u32 fbr0_base_lo; // 0x203C
+ u32 fbr0_base_hi; // 0x2040
+ RXDMA_FBR_NUM_DES_t fbr0_num_des; // 0x2044
+ DMA10W_t fbr0_avail_offset; // 0x2048
+ DMA10W_t fbr0_full_offset; // 0x204C
+ RXDMA_FBC_RD_INDEX_t fbr0_rd_index; // 0x2050
+ RXDMA_FBR_MIN_DES_t fbr0_min_des; // 0x2054
+ u32 fbr1_base_lo; // 0x2058
+ u32 fbr1_base_hi; // 0x205C
+ RXDMA_FBR_NUM_DES_t fbr1_num_des; // 0x2060
+ DMA10W_t fbr1_avail_offset; // 0x2064
+ DMA10W_t fbr1_full_offset; // 0x2068
+ RXDMA_FBC_RD_INDEX_t fbr1_rd_index; // 0x206C
+ RXDMA_FBR_MIN_DES_t fbr1_min_des; // 0x2070
+} RXDMA_t, *PRXDMA_t;
+
+/* END OF RXDMA REGISTER ADDRESS MAP */
+
+
+/* START OF TXMAC REGISTER ADDRESS MAP */
+
+/*
+ * structure for control reg in txmac address map
+ * located at address 0x3000
+ */
+typedef union _TXMAC_CTL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:24; // bits 8-31
+ u32 cklseg_diable:1; // bit 7
+ u32 ckbcnt_disable:1; // bit 6
+ u32 cksegnum:1; // bit 5
+ u32 async_disable:1; // bit 4
+ u32 fc_disable:1; // bit 3
+ u32 mcif_disable:1; // bit 2
+ u32 mif_disable:1; // bit 1
+ u32 txmac_en:1; // bit 0
+#else
+ u32 txmac_en:1; // bit 0
+ u32 mif_disable:1; // bit 1 mac interface
+ u32 mcif_disable:1; // bit 2 mem. contr. interface
+ u32 fc_disable:1; // bit 3
+ u32 async_disable:1; // bit 4
+ u32 cksegnum:1; // bit 5
+ u32 ckbcnt_disable:1; // bit 6
+ u32 cklseg_diable:1; // bit 7
+ u32 unused:24; // bits 8-31
+#endif
+ } bits;
+} TXMAC_CTL_t, *PTXMAC_CTL_t;
+
+/*
+ * structure for shadow pointer reg in txmac address map
+ * located at address 0x3004
+ */
+typedef union _TXMAC_SHADOW_PTR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:5; // bits 27-31
+ u32 txq_rd_ptr:11; // bits 16-26
+ u32 reserved:5; // bits 11-15
+ u32 txq_wr_ptr:11; // bits 0-10
+#else
+ u32 txq_wr_ptr:11; // bits 0-10
+ u32 reserved:5; // bits 11-15
+ u32 txq_rd_ptr:11; // bits 16-26
+ u32 reserved2:5; // bits 27-31
+#endif
+ } bits;
+} TXMAC_SHADOW_PTR_t, *PTXMAC_SHADOW_PTR_t;
+
+/*
+ * structure for error count reg in txmac address map
+ * located at address 0x3008
+ */
+typedef union _TXMAC_ERR_CNT_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:20; // bits 12-31
+ u32 reserved:4; // bits 8-11
+ u32 txq_underrun:4; // bits 4-7
+ u32 fifo_underrun:4; // bits 0-3
+#else
+ u32 fifo_underrun:4; // bits 0-3
+ u32 txq_underrun:4; // bits 4-7
+ u32 reserved:4; // bits 8-11
+ u32 unused:20; // bits 12-31
+#endif
+ } bits;
+} TXMAC_ERR_CNT_t, *PTXMAC_ERR_CNT_t;
+
+/*
+ * structure for max fill reg in txmac address map
+ * located at address 0x300C
+ */
+typedef union _TXMAC_MAX_FILL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:20; // bits 12-31
+ u32 max_fill:12; // bits 0-11
+#else
+ u32 max_fill:12; // bits 0-11
+ u32 unused:20; // bits 12-31
+#endif
+ } bits;
+} TXMAC_MAX_FILL_t, *PTXMAC_MAX_FILL_t;
+
+/*
+ * structure for cf parameter reg in txmac address map
+ * located at address 0x3010
+ */
+typedef union _TXMAC_CF_PARAM_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 cfep:16; // bits 16-31
+ u32 cfpt:16; // bits 0-15
+#else
+ u32 cfpt:16; // bits 0-15
+ u32 cfep:16; // bits 16-31
+#endif
+ } bits;
+} TXMAC_CF_PARAM_t, *PTXMAC_CF_PARAM_t;
+
+/*
+ * structure for tx test reg in txmac address map
+ * located at address 0x3014
+ */
+typedef union _TXMAC_TXTEST_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:15; // bits 17-31
+ u32 reserved1:1; // bit 16
+ u32 txtest_en:1; // bit 15
+ u32 unused1:4; // bits 11-14
+ u32 txqtest_ptr:11; // bits 0-11
+#else
+ u32 txqtest_ptr:11; // bits 0-10
+ u32 unused1:4; // bits 11-14
+ u32 txtest_en:1; // bit 15
+ u32 reserved1:1; // bit 16
+ u32 unused2:15; // bits 17-31
+#endif
+ } bits;
+} TXMAC_TXTEST_t, *PTXMAC_TXTEST_t;
+
+/*
+ * structure for error reg in txmac address map
+ * located at address 0x3018
+ */
+typedef union _TXMAC_ERR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:23; // bits 9-31
+ u32 fifo_underrun:1; // bit 8
+ u32 unused1:2; // bits 6-7
+ u32 ctrl2_err:1; // bit 5
+ u32 txq_underrun:1; // bit 4
+ u32 bcnt_err:1; // bit 3
+ u32 lseg_err:1; // bit 2
+ u32 segnum_err:1; // bit 1
+ u32 seg0_err:1; // bit 0
+#else
+ u32 seg0_err:1; // bit 0
+ u32 segnum_err:1; // bit 1
+ u32 lseg_err:1; // bit 2
+ u32 bcnt_err:1; // bit 3
+ u32 txq_underrun:1; // bit 4
+ u32 ctrl2_err:1; // bit 5
+ u32 unused1:2; // bits 6-7
+ u32 fifo_underrun:1; // bit 8
+ u32 unused2:23; // bits 9-31
+#endif
+ } bits;
+} TXMAC_ERR_t, *PTXMAC_ERR_t;
+
+/*
+ * structure for error interrupt reg in txmac address map
+ * located at address 0x301C
+ */
+typedef union _TXMAC_ERR_INT_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:23; // bits 9-31
+ u32 fifo_underrun:1; // bit 8
+ u32 unused1:2; // bits 6-7
+ u32 ctrl2_err:1; // bit 5
+ u32 txq_underrun:1; // bit 4
+ u32 bcnt_err:1; // bit 3
+ u32 lseg_err:1; // bit 2
+ u32 segnum_err:1; // bit 1
+ u32 seg0_err:1; // bit 0
+#else
+ u32 seg0_err:1; // bit 0
+ u32 segnum_err:1; // bit 1
+ u32 lseg_err:1; // bit 2
+ u32 bcnt_err:1; // bit 3
+ u32 txq_underrun:1; // bit 4
+ u32 ctrl2_err:1; // bit 5
+ u32 unused1:2; // bits 6-7
+ u32 fifo_underrun:1; // bit 8
+ u32 unused2:23; // bits 9-31
+#endif
+ } bits;
+} TXMAC_ERR_INT_t, *PTXMAC_ERR_INT_t;
+
+/*
+ * structure for error interrupt reg in txmac address map
+ * located at address 0x3020
+ */
+typedef union _TXMAC_CP_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:30; // bits 2-31
+ u32 bp_req:1; // bit 1
+ u32 bp_xonxoff:1; // bit 0
+#else
+ u32 bp_xonxoff:1; // bit 0
+ u32 bp_req:1; // bit 1
+ u32 unused:30; // bits 2-31
+#endif
+ } bits;
+} TXMAC_BP_CTRL_t, *PTXMAC_BP_CTRL_t;
+
+/*
+ * Tx MAC Module of JAGCore Address Mapping
+ */
+typedef struct _TXMAC_t { // Location:
+ TXMAC_CTL_t ctl; // 0x3000
+ TXMAC_SHADOW_PTR_t shadow_ptr; // 0x3004
+ TXMAC_ERR_CNT_t err_cnt; // 0x3008
+ TXMAC_MAX_FILL_t max_fill; // 0x300C
+ TXMAC_CF_PARAM_t cf_param; // 0x3010
+ TXMAC_TXTEST_t tx_test; // 0x3014
+ TXMAC_ERR_t err; // 0x3018
+ TXMAC_ERR_INT_t err_int; // 0x301C
+ TXMAC_BP_CTRL_t bp_ctrl; // 0x3020
+} TXMAC_t, *PTXMAC_t;
+
+/* END OF TXMAC REGISTER ADDRESS MAP */
+
+/* START OF RXMAC REGISTER ADDRESS MAP */
+
+/*
+ * structure for rxmac control reg in rxmac address map
+ * located at address 0x4000
+ */
+typedef union _RXMAC_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:25; // bits 7-31
+ u32 rxmac_int_disable:1; // bit 6
+ u32 async_disable:1; // bit 5
+ u32 mif_disable:1; // bit 4
+ u32 wol_disable:1; // bit 3
+ u32 pkt_filter_disable:1; // bit 2
+ u32 mcif_disable:1; // bit 1
+ u32 rxmac_en:1; // bit 0
+#else
+ u32 rxmac_en:1; // bit 0
+ u32 mcif_disable:1; // bit 1
+ u32 pkt_filter_disable:1; // bit 2
+ u32 wol_disable:1; // bit 3
+ u32 mif_disable:1; // bit 4
+ u32 async_disable:1; // bit 5
+ u32 rxmac_int_disable:1; // bit 6
+ u32 reserved:25; // bits 7-31
+#endif
+ } bits;
+} RXMAC_CTRL_t, *PRXMAC_CTRL_t;
+
+/*
+ * structure for Wake On Lan Control and CRC 0 reg in rxmac address map
+ * located at address 0x4004
+ */
+typedef union _RXMAC_WOL_CTL_CRC0_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 crc0:16; // bits 16-31
+ u32 reserve:4; // bits 12-15
+ u32 ignore_pp:1; // bit 11
+ u32 ignore_mp:1; // bit 10
+ u32 clr_intr:1; // bit 9
+ u32 ignore_link_chg:1; // bit 8
+ u32 ignore_uni:1; // bit 7
+ u32 ignore_multi:1; // bit 6
+ u32 ignore_broad:1; // bit 5
+ u32 valid_crc4:1; // bit 4
+ u32 valid_crc3:1; // bit 3
+ u32 valid_crc2:1; // bit 2
+ u32 valid_crc1:1; // bit 1
+ u32 valid_crc0:1; // bit 0
+#else
+ u32 valid_crc0:1; // bit 0
+ u32 valid_crc1:1; // bit 1
+ u32 valid_crc2:1; // bit 2
+ u32 valid_crc3:1; // bit 3
+ u32 valid_crc4:1; // bit 4
+ u32 ignore_broad:1; // bit 5
+ u32 ignore_multi:1; // bit 6
+ u32 ignore_uni:1; // bit 7
+ u32 ignore_link_chg:1; // bit 8
+ u32 clr_intr:1; // bit 9
+ u32 ignore_mp:1; // bit 10
+ u32 ignore_pp:1; // bit 11
+ u32 reserve:4; // bits 12-15
+ u32 crc0:16; // bits 16-31
+#endif
+ } bits;
+} RXMAC_WOL_CTL_CRC0_t, *PRXMAC_WOL_CTL_CRC0_t;
+
+/*
+ * structure for CRC 1 and CRC 2 reg in rxmac address map
+ * located at address 0x4008
+ */
+typedef union _RXMAC_WOL_CRC12_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 crc2:16; // bits 16-31
+ u32 crc1:16; // bits 0-15
+#else
+ u32 crc1:16; // bits 0-15
+ u32 crc2:16; // bits 16-31
+#endif
+ } bits;
+} RXMAC_WOL_CRC12_t, *PRXMAC_WOL_CRC12_t;
+
+/*
+ * structure for CRC 3 and CRC 4 reg in rxmac address map
+ * located at address 0x400C
+ */
+typedef union _RXMAC_WOL_CRC34_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 crc4:16; // bits 16-31
+ u32 crc3:16; // bits 0-15
+#else
+ u32 crc3:16; // bits 0-15
+ u32 crc4:16; // bits 16-31
+#endif
+ } bits;
+} RXMAC_WOL_CRC34_t, *PRXMAC_WOL_CRC34_t;
+
+/*
+ * structure for Wake On Lan Source Address Lo reg in rxmac address map
+ * located at address 0x4010
+ */
+typedef union _RXMAC_WOL_SA_LO_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 sa3:8; // bits 24-31
+ u32 sa4:8; // bits 16-23
+ u32 sa5:8; // bits 8-15
+ u32 sa6:8; // bits 0-7
+#else
+ u32 sa6:8; // bits 0-7
+ u32 sa5:8; // bits 8-15
+ u32 sa4:8; // bits 16-23
+ u32 sa3:8; // bits 24-31
+#endif
+ } bits;
+} RXMAC_WOL_SA_LO_t, *PRXMAC_WOL_SA_LO_t;
+
+/*
+ * structure for Wake On Lan Source Address Hi reg in rxmac address map
+ * located at address 0x4014
+ */
+typedef union _RXMAC_WOL_SA_HI_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:16; // bits 16-31
+ u32 sa1:8; // bits 8-15
+ u32 sa2:8; // bits 0-7
+#else
+ u32 sa2:8; // bits 0-7
+ u32 sa1:8; // bits 8-15
+ u32 reserved:16; // bits 16-31
+#endif
+ } bits;
+} RXMAC_WOL_SA_HI_t, *PRXMAC_WOL_SA_HI_t;
+
+/*
+ * structure for Wake On Lan mask reg in rxmac address map
+ * located at address 0x4018 - 0x4064
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for Unicast Paket Filter Address 1 reg in rxmac address map
+ * located at address 0x4068
+ */
+typedef union _RXMAC_UNI_PF_ADDR1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 addr1_3:8; // bits 24-31
+ u32 addr1_4:8; // bits 16-23
+ u32 addr1_5:8; // bits 8-15
+ u32 addr1_6:8; // bits 0-7
+#else
+ u32 addr1_6:8; // bits 0-7
+ u32 addr1_5:8; // bits 8-15
+ u32 addr1_4:8; // bits 16-23
+ u32 addr1_3:8; // bits 24-31
+#endif
+ } bits;
+} RXMAC_UNI_PF_ADDR1_t, *PRXMAC_UNI_PF_ADDR1_t;
+
+/*
+ * structure for Unicast Paket Filter Address 2 reg in rxmac address map
+ * located at address 0x406C
+ */
+typedef union _RXMAC_UNI_PF_ADDR2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 addr2_3:8; // bits 24-31
+ u32 addr2_4:8; // bits 16-23
+ u32 addr2_5:8; // bits 8-15
+ u32 addr2_6:8; // bits 0-7
+#else
+ u32 addr2_6:8; // bits 0-7
+ u32 addr2_5:8; // bits 8-15
+ u32 addr2_4:8; // bits 16-23
+ u32 addr2_3:8; // bits 24-31
+#endif
+ } bits;
+} RXMAC_UNI_PF_ADDR2_t, *PRXMAC_UNI_PF_ADDR2_t;
+
+/*
+ * structure for Unicast Paket Filter Address 1 & 2 reg in rxmac address map
+ * located at address 0x4070
+ */
+typedef union _RXMAC_UNI_PF_ADDR3_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 addr2_1:8; // bits 24-31
+ u32 addr2_2:8; // bits 16-23
+ u32 addr1_1:8; // bits 8-15
+ u32 addr1_2:8; // bits 0-7
+#else
+ u32 addr1_2:8; // bits 0-7
+ u32 addr1_1:8; // bits 8-15
+ u32 addr2_2:8; // bits 16-23
+ u32 addr2_1:8; // bits 24-31
+#endif
+ } bits;
+} RXMAC_UNI_PF_ADDR3_t, *PRXMAC_UNI_PF_ADDR3_t;
+
+/*
+ * structure for Multicast Hash reg in rxmac address map
+ * located at address 0x4074 - 0x4080
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for Packet Filter Control reg in rxmac address map
+ * located at address 0x4084
+ */
+typedef union _RXMAC_PF_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused2:9; // bits 23-31
+ u32 min_pkt_size:7; // bits 16-22
+ u32 unused1:12; // bits 4-15
+ u32 filter_frag_en:1; // bit 3
+ u32 filter_uni_en:1; // bit 2
+ u32 filter_multi_en:1; // bit 1
+ u32 filter_broad_en:1; // bit 0
+#else
+ u32 filter_broad_en:1; // bit 0
+ u32 filter_multi_en:1; // bit 1
+ u32 filter_uni_en:1; // bit 2
+ u32 filter_frag_en:1; // bit 3
+ u32 unused1:12; // bits 4-15
+ u32 min_pkt_size:7; // bits 16-22
+ u32 unused2:9; // bits 23-31
+#endif
+ } bits;
+} RXMAC_PF_CTRL_t, *PRXMAC_PF_CTRL_t;
+
+/*
+ * structure for Memory Controller Interface Control Max Segment reg in rxmac
+ * address map. Located at address 0x4088
+ */
+typedef union _RXMAC_MCIF_CTRL_MAX_SEG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:22; // bits 10-31
+ u32 max_size:8; // bits 2-9
+ u32 fc_en:1; // bit 1
+ u32 seg_en:1; // bit 0
+#else
+ u32 seg_en:1; // bit 0
+ u32 fc_en:1; // bit 1
+ u32 max_size:8; // bits 2-9
+ u32 reserved:22; // bits 10-31
+#endif
+ } bits;
+} RXMAC_MCIF_CTRL_MAX_SEG_t, *PRXMAC_MCIF_CTRL_MAX_SEG_t;
+
+/*
+ * structure for Memory Controller Interface Water Mark reg in rxmac address
+ * map. Located at address 0x408C
+ */
+typedef union _RXMAC_MCIF_WATER_MARK_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:6; // bits 26-31
+ u32 mark_hi:10; // bits 16-25
+ u32 reserved1:6; // bits 10-15
+ u32 mark_lo:10; // bits 0-9
+#else
+ u32 mark_lo:10; // bits 0-9
+ u32 reserved1:6; // bits 10-15
+ u32 mark_hi:10; // bits 16-25
+ u32 reserved2:6; // bits 26-31
+#endif
+ } bits;
+} RXMAC_MCIF_WATER_MARK_t, *PRXMAC_MCIF_WATER_MARK_t;
+
+/*
+ * structure for Rx Queue Dialog reg in rxmac address map.
+ * located at address 0x4090
+ */
+typedef union _RXMAC_RXQ_DIAG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:6; // bits 26-31
+ u32 rd_ptr:10; // bits 16-25
+ u32 reserved1:6; // bits 10-15
+ u32 wr_ptr:10; // bits 0-9
+#else
+ u32 wr_ptr:10; // bits 0-9
+ u32 reserved1:6; // bits 10-15
+ u32 rd_ptr:10; // bits 16-25
+ u32 reserved2:6; // bits 26-31
+#endif
+ } bits;
+} RXMAC_RXQ_DIAG_t, *PRXMAC_RXQ_DIAG_t;
+
+/*
+ * structure for space availiable reg in rxmac address map.
+ * located at address 0x4094
+ */
+typedef union _RXMAC_SPACE_AVAIL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:15; // bits 17-31
+ u32 space_avail_en:1; // bit 16
+ u32 reserved1:6; // bits 10-15
+ u32 space_avail:10; // bits 0-9
+#else
+ u32 space_avail:10; // bits 0-9
+ u32 reserved1:6; // bits 10-15
+ u32 space_avail_en:1; // bit 16
+ u32 reserved2:15; // bits 17-31
+#endif
+ } bits;
+} RXMAC_SPACE_AVAIL_t, *PRXMAC_SPACE_AVAIL_t;
+
+/*
+ * structure for management interface reg in rxmac address map.
+ * located at address 0x4098
+ */
+typedef union _RXMAC_MIF_CTL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserve:14; // bits 18-31
+ u32 drop_pkt_en:1; // bit 17
+ u32 drop_pkt_mask:17; // bits 0-16
+#else
+ u32 drop_pkt_mask:17; // bits 0-16
+ u32 drop_pkt_en:1; // bit 17
+ u32 reserve:14; // bits 18-31
+#endif
+ } bits;
+} RXMAC_MIF_CTL_t, *PRXMAC_MIF_CTL_t;
+
+/*
+ * structure for Error reg in rxmac address map.
+ * located at address 0x409C
+ */
+typedef union _RXMAC_ERROR_REG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserve:28; // bits 4-31
+ u32 mif:1; // bit 3
+ u32 async:1; // bit 2
+ u32 pkt_filter:1; // bit 1
+ u32 mcif:1; // bit 0
+#else
+ u32 mcif:1; // bit 0
+ u32 pkt_filter:1; // bit 1
+ u32 async:1; // bit 2
+ u32 mif:1; // bit 3
+ u32 reserve:28; // bits 4-31
+#endif
+ } bits;
+} RXMAC_ERROR_REG_t, *PRXMAC_ERROR_REG_t;
+
+/*
+ * Rx MAC Module of JAGCore Address Mapping
+ */
+typedef struct _RXMAC_t { // Location:
+ RXMAC_CTRL_t ctrl; // 0x4000
+ RXMAC_WOL_CTL_CRC0_t crc0; // 0x4004
+ RXMAC_WOL_CRC12_t crc12; // 0x4008
+ RXMAC_WOL_CRC34_t crc34; // 0x400C
+ RXMAC_WOL_SA_LO_t sa_lo; // 0x4010
+ RXMAC_WOL_SA_HI_t sa_hi; // 0x4014
+ u32 mask0_word0; // 0x4018
+ u32 mask0_word1; // 0x401C
+ u32 mask0_word2; // 0x4020
+ u32 mask0_word3; // 0x4024
+ u32 mask1_word0; // 0x4028
+ u32 mask1_word1; // 0x402C
+ u32 mask1_word2; // 0x4030
+ u32 mask1_word3; // 0x4034
+ u32 mask2_word0; // 0x4038
+ u32 mask2_word1; // 0x403C
+ u32 mask2_word2; // 0x4040
+ u32 mask2_word3; // 0x4044
+ u32 mask3_word0; // 0x4048
+ u32 mask3_word1; // 0x404C
+ u32 mask3_word2; // 0x4050
+ u32 mask3_word3; // 0x4054
+ u32 mask4_word0; // 0x4058
+ u32 mask4_word1; // 0x405C
+ u32 mask4_word2; // 0x4060
+ u32 mask4_word3; // 0x4064
+ RXMAC_UNI_PF_ADDR1_t uni_pf_addr1; // 0x4068
+ RXMAC_UNI_PF_ADDR2_t uni_pf_addr2; // 0x406C
+ RXMAC_UNI_PF_ADDR3_t uni_pf_addr3; // 0x4070
+ u32 multi_hash1; // 0x4074
+ u32 multi_hash2; // 0x4078
+ u32 multi_hash3; // 0x407C
+ u32 multi_hash4; // 0x4080
+ RXMAC_PF_CTRL_t pf_ctrl; // 0x4084
+ RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg; // 0x4088
+ RXMAC_MCIF_WATER_MARK_t mcif_water_mark; // 0x408C
+ RXMAC_RXQ_DIAG_t rxq_diag; // 0x4090
+ RXMAC_SPACE_AVAIL_t space_avail; // 0x4094
+
+ RXMAC_MIF_CTL_t mif_ctrl; // 0x4098
+ RXMAC_ERROR_REG_t err_reg; // 0x409C
+} RXMAC_t, *PRXMAC_t;
+
+/* END OF TXMAC REGISTER ADDRESS MAP */
+
+
+/* START OF MAC REGISTER ADDRESS MAP */
+
+/*
+ * structure for configuration #1 reg in mac address map.
+ * located at address 0x5000
+ */
+typedef union _MAC_CFG1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 soft_reset:1; // bit 31
+ u32 sim_reset:1; // bit 30
+ u32 reserved3:10; // bits 20-29
+ u32 reset_rx_mc:1; // bit 19
+ u32 reset_tx_mc:1; // bit 18
+ u32 reset_rx_fun:1; // bit 17
+ u32 reset_tx_fun:1; // bit 16
+ u32 reserved2:7; // bits 9-15
+ u32 loop_back:1; // bit 8
+ u32 reserved1:2; // bits 6-7
+ u32 rx_flow:1; // bit 5
+ u32 tx_flow:1; // bit 4
+ u32 syncd_rx_en:1; // bit 3
+ u32 rx_enable:1; // bit 2
+ u32 syncd_tx_en:1; // bit 1
+ u32 tx_enable:1; // bit 0
+#else
+ u32 tx_enable:1; // bit 0
+ u32 syncd_tx_en:1; // bit 1
+ u32 rx_enable:1; // bit 2
+ u32 syncd_rx_en:1; // bit 3
+ u32 tx_flow:1; // bit 4
+ u32 rx_flow:1; // bit 5
+ u32 reserved1:2; // bits 6-7
+ u32 loop_back:1; // bit 8
+ u32 reserved2:7; // bits 9-15
+ u32 reset_tx_fun:1; // bit 16
+ u32 reset_rx_fun:1; // bit 17
+ u32 reset_tx_mc:1; // bit 18
+ u32 reset_rx_mc:1; // bit 19
+ u32 reserved3:10; // bits 20-29
+ u32 sim_reset:1; // bit 30
+ u32 soft_reset:1; // bit 31
+#endif
+ } bits;
+} MAC_CFG1_t, *PMAC_CFG1_t;
+
+/*
+ * structure for configuration #2 reg in mac address map.
+ * located at address 0x5004
+ */
+typedef union _MAC_CFG2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved3:16; // bits 16-31
+ u32 preamble_len:4; // bits 12-15
+ u32 reserved2:2; // bits 10-11
+ u32 if_mode:2; // bits 8-9
+ u32 reserved1:2; // bits 6-7
+ u32 huge_frame:1; // bit 5
+ u32 len_check:1; // bit 4
+ u32 undefined:1; // bit 3
+ u32 pad_crc:1; // bit 2
+ u32 crc_enable:1; // bit 1
+ u32 full_duplex:1; // bit 0
+#else
+ u32 full_duplex:1; // bit 0
+ u32 crc_enable:1; // bit 1
+ u32 pad_crc:1; // bit 2
+ u32 undefined:1; // bit 3
+ u32 len_check:1; // bit 4
+ u32 huge_frame:1; // bit 5
+ u32 reserved1:2; // bits 6-7
+ u32 if_mode:2; // bits 8-9
+ u32 reserved2:2; // bits 10-11
+ u32 preamble_len:4; // bits 12-15
+ u32 reserved3:16; // bits 16-31
+#endif
+ } bits;
+} MAC_CFG2_t, *PMAC_CFG2_t;
+
+/*
+ * structure for Interpacket gap reg in mac address map.
+ * located at address 0x5008
+ */
+typedef union _MAC_IPG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:1; // bit 31
+ u32 non_B2B_ipg_1:7; // bits 24-30
+ u32 undefined2:1; // bit 23
+ u32 non_B2B_ipg_2:7; // bits 16-22
+ u32 min_ifg_enforce:8; // bits 8-15
+ u32 undefined1:1; // bit 7
+ u32 B2B_ipg:7; // bits 0-6
+#else
+ u32 B2B_ipg:7; // bits 0-6
+ u32 undefined1:1; // bit 7
+ u32 min_ifg_enforce:8; // bits 8-15
+ u32 non_B2B_ipg_2:7; // bits 16-22
+ u32 undefined2:1; // bit 23
+ u32 non_B2B_ipg_1:7; // bits 24-30
+ u32 reserved:1; // bit 31
+#endif
+ } bits;
+} MAC_IPG_t, *PMAC_IPG_t;
+
+/*
+ * structure for half duplex reg in mac address map.
+ * located at address 0x500C
+ */
+typedef union _MAC_HFDP_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:8; // bits 24-31
+ u32 alt_beb_trunc:4; // bits 23-20
+ u32 alt_beb_enable:1; // bit 19
+ u32 bp_no_backoff:1; // bit 18
+ u32 no_backoff:1; // bit 17
+ u32 excess_defer:1; // bit 16
+ u32 rexmit_max:4; // bits 12-15
+ u32 reserved1:2; // bits 10-11
+ u32 coll_window:10; // bits 0-9
+#else
+ u32 coll_window:10; // bits 0-9
+ u32 reserved1:2; // bits 10-11
+ u32 rexmit_max:4; // bits 12-15
+ u32 excess_defer:1; // bit 16
+ u32 no_backoff:1; // bit 17
+ u32 bp_no_backoff:1; // bit 18
+ u32 alt_beb_enable:1; // bit 19
+ u32 alt_beb_trunc:4; // bits 23-20
+ u32 reserved2:8; // bits 24-31
+#endif
+ } bits;
+} MAC_HFDP_t, *PMAC_HFDP_t;
+
+/*
+ * structure for Maximum Frame Length reg in mac address map.
+ * located at address 0x5010
+ */
+typedef union _MAC_MAX_FM_LEN_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:16; // bits 16-31
+ u32 max_len:16; // bits 0-15
+#else
+ u32 max_len:16; // bits 0-15
+ u32 reserved:16; // bits 16-31
+#endif
+ } bits;
+} MAC_MAX_FM_LEN_t, *PMAC_MAX_FM_LEN_t;
+
+/*
+ * structure for Reserve 1 reg in mac address map.
+ * located at address 0x5014 - 0x5018
+ * Defined earlier (u32)
+ */
+
+/*
+ * structure for Test reg in mac address map.
+ * located at address 0x501C
+ */
+typedef union _MAC_TEST_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:29; // bits 3-31
+ u32 mac_test:3; // bits 0-2
+#else
+ u32 mac_test:3; // bits 0-2
+ u32 unused:29; // bits 3-31
+#endif
+ } bits;
+} MAC_TEST_t, *PMAC_TEST_t;
+
+/*
+ * structure for MII Management Configuration reg in mac address map.
+ * located at address 0x5020
+ */
+typedef union _MII_MGMT_CFG_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reset_mii_mgmt:1; // bit 31
+ u32 reserved:25; // bits 6-30
+ u32 scan_auto_incremt:1; // bit 5
+ u32 preamble_suppress:1; // bit 4
+ u32 undefined:1; // bit 3
+ u32 mgmt_clk_reset:3; // bits 0-2
+#else
+ u32 mgmt_clk_reset:3; // bits 0-2
+ u32 undefined:1; // bit 3
+ u32 preamble_suppress:1; // bit 4
+ u32 scan_auto_incremt:1; // bit 5
+ u32 reserved:25; // bits 6-30
+ u32 reset_mii_mgmt:1; // bit 31
+#endif
+ } bits;
+} MII_MGMT_CFG_t, *PMII_MGMT_CFG_t;
+
+/*
+ * structure for MII Management Command reg in mac address map.
+ * located at address 0x5024
+ */
+typedef union _MII_MGMT_CMD_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:30; // bits 2-31
+ u32 scan_cycle:1; // bit 1
+ u32 read_cycle:1; // bit 0
+#else
+ u32 read_cycle:1; // bit 0
+ u32 scan_cycle:1; // bit 1
+ u32 reserved:30; // bits 2-31
+#endif
+ } bits;
+} MII_MGMT_CMD_t, *PMII_MGMT_CMD_t;
+
+/*
+ * structure for MII Management Address reg in mac address map.
+ * located at address 0x5028
+ */
+typedef union _MII_MGMT_ADDR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved2:19; // bit 13-31
+ u32 phy_addr:5; // bits 8-12
+ u32 reserved1:3; // bits 5-7
+ u32 reg_addr:5; // bits 0-4
+#else
+ u32 reg_addr:5; // bits 0-4
+ u32 reserved1:3; // bits 5-7
+ u32 phy_addr:5; // bits 8-12
+ u32 reserved2:19; // bit 13-31
+#endif
+ } bits;
+} MII_MGMT_ADDR_t, *PMII_MGMT_ADDR_t;
+
+/*
+ * structure for MII Management Control reg in mac address map.
+ * located at address 0x502C
+ */
+typedef union _MII_MGMT_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:16; // bits 16-31
+ u32 phy_ctrl:16; // bits 0-15
+#else
+ u32 phy_ctrl:16; // bits 0-15
+ u32 reserved:16; // bits 16-31
+#endif
+ } bits;
+} MII_MGMT_CTRL_t, *PMII_MGMT_CTRL_t;
+
+/*
+ * structure for MII Management Status reg in mac address map.
+ * located at address 0x5030
+ */
+typedef union _MII_MGMT_STAT_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:16; // bits 16-31
+ u32 phy_stat:16; // bits 0-15
+#else
+ u32 phy_stat:16; // bits 0-15
+ u32 reserved:16; // bits 16-31
+#endif
+ } bits;
+} MII_MGMT_STAT_t, *PMII_MGMT_STAT_t;
+
+/*
+ * structure for MII Management Indicators reg in mac address map.
+ * located at address 0x5034
+ */
+typedef union _MII_MGMT_INDICATOR_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:29; // bits 3-31
+ u32 not_valid:1; // bit 2
+ u32 scanning:1; // bit 1
+ u32 busy:1; // bit 0
+#else
+ u32 busy:1; // bit 0
+ u32 scanning:1; // bit 1
+ u32 not_valid:1; // bit 2
+ u32 reserved:29; // bits 3-31
+#endif
+ } bits;
+} MII_MGMT_INDICATOR_t, *PMII_MGMT_INDICATOR_t;
+
+/*
+ * structure for Interface Control reg in mac address map.
+ * located at address 0x5038
+ */
+typedef union _MAC_IF_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reset_if_module:1; // bit 31
+ u32 reserved4:3; // bit 28-30
+ u32 tbi_mode:1; // bit 27
+ u32 ghd_mode:1; // bit 26
+ u32 lhd_mode:1; // bit 25
+ u32 phy_mode:1; // bit 24
+ u32 reset_per_mii:1; // bit 23
+ u32 reserved3:6; // bits 17-22
+ u32 speed:1; // bit 16
+ u32 reset_pe100x:1; // bit 15
+ u32 reserved2:4; // bits 11-14
+ u32 force_quiet:1; // bit 10
+ u32 no_cipher:1; // bit 9
+ u32 disable_link_fail:1; // bit 8
+ u32 reset_gpsi:1; // bit 7
+ u32 reserved1:6; // bits 1-6
+ u32 enab_jab_protect:1; // bit 0
+#else
+ u32 enab_jab_protect:1; // bit 0
+ u32 reserved1:6; // bits 1-6
+ u32 reset_gpsi:1; // bit 7
+ u32 disable_link_fail:1; // bit 8
+ u32 no_cipher:1; // bit 9
+ u32 force_quiet:1; // bit 10
+ u32 reserved2:4; // bits 11-14
+ u32 reset_pe100x:1; // bit 15
+ u32 speed:1; // bit 16
+ u32 reserved3:6; // bits 17-22
+ u32 reset_per_mii:1; // bit 23
+ u32 phy_mode:1; // bit 24
+ u32 lhd_mode:1; // bit 25
+ u32 ghd_mode:1; // bit 26
+ u32 tbi_mode:1; // bit 27
+ u32 reserved4:3; // bit 28-30
+ u32 reset_if_module:1; // bit 31
+#endif
+ } bits;
+} MAC_IF_CTRL_t, *PMAC_IF_CTRL_t;
+
+/*
+ * structure for Interface Status reg in mac address map.
+ * located at address 0x503C
+ */
+typedef union _MAC_IF_STAT_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:22; // bits 10-31
+ u32 excess_defer:1; // bit 9
+ u32 clash:1; // bit 8
+ u32 phy_jabber:1; // bit 7
+ u32 phy_link_ok:1; // bit 6
+ u32 phy_full_duplex:1; // bit 5
+ u32 phy_speed:1; // bit 4
+ u32 pe100x_link_fail:1; // bit 3
+ u32 pe10t_loss_carrie:1; // bit 2
+ u32 pe10t_sqe_error:1; // bit 1
+ u32 pe10t_jabber:1; // bit 0
+#else
+ u32 pe10t_jabber:1; // bit 0
+ u32 pe10t_sqe_error:1; // bit 1
+ u32 pe10t_loss_carrie:1; // bit 2
+ u32 pe100x_link_fail:1; // bit 3
+ u32 phy_speed:1; // bit 4
+ u32 phy_full_duplex:1; // bit 5
+ u32 phy_link_ok:1; // bit 6
+ u32 phy_jabber:1; // bit 7
+ u32 clash:1; // bit 8
+ u32 excess_defer:1; // bit 9
+ u32 reserved:22; // bits 10-31
+#endif
+ } bits;
+} MAC_IF_STAT_t, *PMAC_IF_STAT_t;
+
+/*
+ * structure for Mac Station Address, Part 1 reg in mac address map.
+ * located at address 0x5040
+ */
+typedef union _MAC_STATION_ADDR1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 Octet6:8; // bits 24-31
+ u32 Octet5:8; // bits 16-23
+ u32 Octet4:8; // bits 8-15
+ u32 Octet3:8; // bits 0-7
+#else
+ u32 Octet3:8; // bits 0-7
+ u32 Octet4:8; // bits 8-15
+ u32 Octet5:8; // bits 16-23
+ u32 Octet6:8; // bits 24-31
+#endif
+ } bits;
+} MAC_STATION_ADDR1_t, *PMAC_STATION_ADDR1_t;
+
+/*
+ * structure for Mac Station Address, Part 2 reg in mac address map.
+ * located at address 0x5044
+ */
+typedef union _MAC_STATION_ADDR2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 Octet2:8; // bits 24-31
+ u32 Octet1:8; // bits 16-23
+ u32 reserved:16; // bits 0-15
+#else
+ u32 reserved:16; // bit 0-15
+ u32 Octet1:8; // bits 16-23
+ u32 Octet2:8; // bits 24-31
+#endif
+ } bits;
+} MAC_STATION_ADDR2_t, *PMAC_STATION_ADDR2_t;
+
+/*
+ * MAC Module of JAGCore Address Mapping
+ */
+typedef struct _MAC_t { // Location:
+ MAC_CFG1_t cfg1; // 0x5000
+ MAC_CFG2_t cfg2; // 0x5004
+ MAC_IPG_t ipg; // 0x5008
+ MAC_HFDP_t hfdp; // 0x500C
+ MAC_MAX_FM_LEN_t max_fm_len; // 0x5010
+ u32 rsv1; // 0x5014
+ u32 rsv2; // 0x5018
+ MAC_TEST_t mac_test; // 0x501C
+ MII_MGMT_CFG_t mii_mgmt_cfg; // 0x5020
+ MII_MGMT_CMD_t mii_mgmt_cmd; // 0x5024
+ MII_MGMT_ADDR_t mii_mgmt_addr; // 0x5028
+ MII_MGMT_CTRL_t mii_mgmt_ctrl; // 0x502C
+ MII_MGMT_STAT_t mii_mgmt_stat; // 0x5030
+ MII_MGMT_INDICATOR_t mii_mgmt_indicator; // 0x5034
+ MAC_IF_CTRL_t if_ctrl; // 0x5038
+ MAC_IF_STAT_t if_stat; // 0x503C
+ MAC_STATION_ADDR1_t station_addr_1; // 0x5040
+ MAC_STATION_ADDR2_t station_addr_2; // 0x5044
+} MAC_t, *PMAC_t;
+
+/* END OF MAC REGISTER ADDRESS MAP */
+
+/* START OF MAC STAT REGISTER ADDRESS MAP */
+
+/*
+ * structure for Carry Register One and it's Mask Register reg located in mac
+ * stat address map address 0x6130 and 0x6138.
+ */
+typedef union _MAC_STAT_REG_1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 tr64:1; // bit 31
+ u32 tr127:1; // bit 30
+ u32 tr255:1; // bit 29
+ u32 tr511:1; // bit 28
+ u32 tr1k:1; // bit 27
+ u32 trmax:1; // bit 26
+ u32 trmgv:1; // bit 25
+ u32 unused:8; // bits 17-24
+ u32 rbyt:1; // bit 16
+ u32 rpkt:1; // bit 15
+ u32 rfcs:1; // bit 14
+ u32 rmca:1; // bit 13
+ u32 rbca:1; // bit 12
+ u32 rxcf:1; // bit 11
+ u32 rxpf:1; // bit 10
+ u32 rxuo:1; // bit 9
+ u32 raln:1; // bit 8
+ u32 rflr:1; // bit 7
+ u32 rcde:1; // bit 6
+ u32 rcse:1; // bit 5
+ u32 rund:1; // bit 4
+ u32 rovr:1; // bit 3
+ u32 rfrg:1; // bit 2
+ u32 rjbr:1; // bit 1
+ u32 rdrp:1; // bit 0
+#else
+ u32 rdrp:1; // bit 0
+ u32 rjbr:1; // bit 1
+ u32 rfrg:1; // bit 2
+ u32 rovr:1; // bit 3
+ u32 rund:1; // bit 4
+ u32 rcse:1; // bit 5
+ u32 rcde:1; // bit 6
+ u32 rflr:1; // bit 7
+ u32 raln:1; // bit 8
+ u32 rxuo:1; // bit 9
+ u32 rxpf:1; // bit 10
+ u32 rxcf:1; // bit 11
+ u32 rbca:1; // bit 12
+ u32 rmca:1; // bit 13
+ u32 rfcs:1; // bit 14
+ u32 rpkt:1; // bit 15
+ u32 rbyt:1; // bit 16
+ u32 unused:8; // bits 17-24
+ u32 trmgv:1; // bit 25
+ u32 trmax:1; // bit 26
+ u32 tr1k:1; // bit 27
+ u32 tr511:1; // bit 28
+ u32 tr255:1; // bit 29
+ u32 tr127:1; // bit 30
+ u32 tr64:1; // bit 31
+#endif
+ } bits;
+} MAC_STAT_REG_1_t, *PMAC_STAT_REG_1_t;
+
+/*
+ * structure for Carry Register Two Mask Register reg in mac stat address map.
+ * located at address 0x613C
+ */
+typedef union _MAC_STAT_REG_2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:12; // bit 20-31
+ u32 tjbr:1; // bit 19
+ u32 tfcs:1; // bit 18
+ u32 txcf:1; // bit 17
+ u32 tovr:1; // bit 16
+ u32 tund:1; // bit 15
+ u32 tfrg:1; // bit 14
+ u32 tbyt:1; // bit 13
+ u32 tpkt:1; // bit 12
+ u32 tmca:1; // bit 11
+ u32 tbca:1; // bit 10
+ u32 txpf:1; // bit 9
+ u32 tdfr:1; // bit 8
+ u32 tedf:1; // bit 7
+ u32 tscl:1; // bit 6
+ u32 tmcl:1; // bit 5
+ u32 tlcl:1; // bit 4
+ u32 txcl:1; // bit 3
+ u32 tncl:1; // bit 2
+ u32 tpfh:1; // bit 1
+ u32 tdrp:1; // bit 0
+#else
+ u32 tdrp:1; // bit 0
+ u32 tpfh:1; // bit 1
+ u32 tncl:1; // bit 2
+ u32 txcl:1; // bit 3
+ u32 tlcl:1; // bit 4
+ u32 tmcl:1; // bit 5
+ u32 tscl:1; // bit 6
+ u32 tedf:1; // bit 7
+ u32 tdfr:1; // bit 8
+ u32 txpf:1; // bit 9
+ u32 tbca:1; // bit 10
+ u32 tmca:1; // bit 11
+ u32 tpkt:1; // bit 12
+ u32 tbyt:1; // bit 13
+ u32 tfrg:1; // bit 14
+ u32 tund:1; // bit 15
+ u32 tovr:1; // bit 16
+ u32 txcf:1; // bit 17
+ u32 tfcs:1; // bit 18
+ u32 tjbr:1; // bit 19
+ u32 unused:12; // bit 20-31
+#endif
+ } bits;
+} MAC_STAT_REG_2_t, *PMAC_STAT_REG_2_t;
+
+/*
+ * MAC STATS Module of JAGCore Address Mapping
+ */
+typedef struct _MAC_STAT_t { // Location:
+ u32 pad[32]; // 0x6000 - 607C
+
+ // Tx/Rx 0-64 Byte Frame Counter
+ u32 TR64; // 0x6080
+
+ // Tx/Rx 65-127 Byte Frame Counter
+ u32 TR127; // 0x6084
+
+ // Tx/Rx 128-255 Byte Frame Counter
+ u32 TR255; // 0x6088
+
+ // Tx/Rx 256-511 Byte Frame Counter
+ u32 TR511; // 0x608C
+
+ // Tx/Rx 512-1023 Byte Frame Counter
+ u32 TR1K; // 0x6090
+
+ // Tx/Rx 1024-1518 Byte Frame Counter
+ u32 TRMax; // 0x6094
+
+ // Tx/Rx 1519-1522 Byte Good VLAN Frame Count
+ u32 TRMgv; // 0x6098
+
+ // Rx Byte Counter
+ u32 RByt; // 0x609C
+
+ // Rx Packet Counter
+ u32 RPkt; // 0x60A0
+
+ // Rx FCS Error Counter
+ u32 RFcs; // 0x60A4
+
+ // Rx Multicast Packet Counter
+ u32 RMca; // 0x60A8
+
+ // Rx Broadcast Packet Counter
+ u32 RBca; // 0x60AC
+
+ // Rx Control Frame Packet Counter
+ u32 RxCf; // 0x60B0
+
+ // Rx Pause Frame Packet Counter
+ u32 RxPf; // 0x60B4
+
+ // Rx Unknown OP Code Counter
+ u32 RxUo; // 0x60B8
+
+ // Rx Alignment Error Counter
+ u32 RAln; // 0x60BC
+
+ // Rx Frame Length Error Counter
+ u32 RFlr; // 0x60C0
+
+ // Rx Code Error Counter
+ u32 RCde; // 0x60C4
+
+ // Rx Carrier Sense Error Counter
+ u32 RCse; // 0x60C8
+
+ // Rx Undersize Packet Counter
+ u32 RUnd; // 0x60CC
+
+ // Rx Oversize Packet Counter
+ u32 ROvr; // 0x60D0
+
+ // Rx Fragment Counter
+ u32 RFrg; // 0x60D4
+
+ // Rx Jabber Counter
+ u32 RJbr; // 0x60D8
+
+ // Rx Drop
+ u32 RDrp; // 0x60DC
+
+ // Tx Byte Counter
+ u32 TByt; // 0x60E0
+
+ // Tx Packet Counter
+ u32 TPkt; // 0x60E4
+
+ // Tx Multicast Packet Counter
+ u32 TMca; // 0x60E8
+
+ // Tx Broadcast Packet Counter
+ u32 TBca; // 0x60EC
+
+ // Tx Pause Control Frame Counter
+ u32 TxPf; // 0x60F0
+
+ // Tx Deferral Packet Counter
+ u32 TDfr; // 0x60F4
+
+ // Tx Excessive Deferral Packet Counter
+ u32 TEdf; // 0x60F8
+
+ // Tx Single Collision Packet Counter
+ u32 TScl; // 0x60FC
+
+ // Tx Multiple Collision Packet Counter
+ u32 TMcl; // 0x6100
+
+ // Tx Late Collision Packet Counter
+ u32 TLcl; // 0x6104
+
+ // Tx Excessive Collision Packet Counter
+ u32 TXcl; // 0x6108
+
+ // Tx Total Collision Packet Counter
+ u32 TNcl; // 0x610C
+
+ // Tx Pause Frame Honored Counter
+ u32 TPfh; // 0x6110
+
+ // Tx Drop Frame Counter
+ u32 TDrp; // 0x6114
+
+ // Tx Jabber Frame Counter
+ u32 TJbr; // 0x6118
+
+ // Tx FCS Error Counter
+ u32 TFcs; // 0x611C
+
+ // Tx Control Frame Counter
+ u32 TxCf; // 0x6120
+
+ // Tx Oversize Frame Counter
+ u32 TOvr; // 0x6124
+
+ // Tx Undersize Frame Counter
+ u32 TUnd; // 0x6128
+
+ // Tx Fragments Frame Counter
+ u32 TFrg; // 0x612C
+
+ // Carry Register One Register
+ MAC_STAT_REG_1_t Carry1; // 0x6130
+
+ // Carry Register Two Register
+ MAC_STAT_REG_2_t Carry2; // 0x6134
+
+ // Carry Register One Mask Register
+ MAC_STAT_REG_1_t Carry1M; // 0x6138
+
+ // Carry Register Two Mask Register
+ MAC_STAT_REG_2_t Carry2M; // 0x613C
+} MAC_STAT_t, *PMAC_STAT_t;
+
+/* END OF MAC STAT REGISTER ADDRESS MAP */
+
+
+/* START OF MMC REGISTER ADDRESS MAP */
+
+/*
+ * structure for Main Memory Controller Control reg in mmc address map.
+ * located at address 0x7000
+ */
+typedef union _MMC_CTRL_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:25; // bits 7-31
+ u32 force_ce:1; // bit 6
+ u32 rxdma_disable:1; // bit 5
+ u32 txdma_disable:1; // bit 4
+ u32 txmac_disable:1; // bit 3
+ u32 rxmac_disable:1; // bit 2
+ u32 arb_disable:1; // bit 1
+ u32 mmc_enable:1; // bit 0
+#else
+ u32 mmc_enable:1; // bit 0
+ u32 arb_disable:1; // bit 1
+ u32 rxmac_disable:1; // bit 2
+ u32 txmac_disable:1; // bit 3
+ u32 txdma_disable:1; // bit 4
+ u32 rxdma_disable:1; // bit 5
+ u32 force_ce:1; // bit 6
+ u32 reserved:25; // bits 7-31
+#endif
+ } bits;
+} MMC_CTRL_t, *PMMC_CTRL_t;
+
+/*
+ * structure for Main Memory Controller Host Memory Access Address reg in mmc
+ * address map. Located at address 0x7004
+ */
+typedef union _MMC_SRAM_ACCESS_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 byte_enable:16; // bits 16-31
+ u32 reserved2:2; // bits 14-15
+ u32 req_addr:10; // bits 4-13
+ u32 reserved1:1; // bit 3
+ u32 is_ctrl_word:1; // bit 2
+ u32 wr_access:1; // bit 1
+ u32 req_access:1; // bit 0
+#else
+ u32 req_access:1; // bit 0
+ u32 wr_access:1; // bit 1
+ u32 is_ctrl_word:1; // bit 2
+ u32 reserved1:1; // bit 3
+ u32 req_addr:10; // bits 4-13
+ u32 reserved2:2; // bits 14-15
+ u32 byte_enable:16; // bits 16-31
+#endif
+ } bits;
+} MMC_SRAM_ACCESS_t, *PMMC_SRAM_ACCESS_t;
+
+/*
+ * structure for Main Memory Controller Host Memory Access Data reg in mmc
+ * address map. Located at address 0x7008 - 0x7014
+ * Defined earlier (u32)
+ */
+
+/*
+ * Memory Control Module of JAGCore Address Mapping
+ */
+typedef struct _MMC_t { // Location:
+ MMC_CTRL_t mmc_ctrl; // 0x7000
+ MMC_SRAM_ACCESS_t sram_access; // 0x7004
+ u32 sram_word1; // 0x7008
+ u32 sram_word2; // 0x700C
+ u32 sram_word3; // 0x7010
+ u32 sram_word4; // 0x7014
+} MMC_t, *PMMC_t;
+
+/* END OF MMC REGISTER ADDRESS MAP */
+
+
+/* START OF EXP ROM REGISTER ADDRESS MAP */
+
+/*
+ * Expansion ROM Module of JAGCore Address Mapping
+ */
+
+/* Take this out until it is not empty */
+#if 0
+typedef struct _EXP_ROM_t {
+
+} EXP_ROM_t, *PEXP_ROM_t;
+#endif
+
+/* END OF EXP ROM REGISTER ADDRESS MAP */
+
+
+/*
+ * JAGCore Address Mapping
+ */
+typedef struct _ADDRESS_MAP_t {
+ GLOBAL_t global;
+ // unused section of global address map
+ u8 unused_global[4096 - sizeof(GLOBAL_t)];
+ TXDMA_t txdma;
+ // unused section of txdma address map
+ u8 unused_txdma[4096 - sizeof(TXDMA_t)];
+ RXDMA_t rxdma;
+ // unused section of rxdma address map
+ u8 unused_rxdma[4096 - sizeof(RXDMA_t)];
+ TXMAC_t txmac;
+ // unused section of txmac address map
+ u8 unused_txmac[4096 - sizeof(TXMAC_t)];
+ RXMAC_t rxmac;
+ // unused section of rxmac address map
+ u8 unused_rxmac[4096 - sizeof(RXMAC_t)];
+ MAC_t mac;
+ // unused section of mac address map
+ u8 unused_mac[4096 - sizeof(MAC_t)];
+ MAC_STAT_t macStat;
+ // unused section of mac stat address map
+ u8 unused_mac_stat[4096 - sizeof(MAC_STAT_t)];
+ MMC_t mmc;
+ // unused section of mmc address map
+ u8 unused_mmc[4096 - sizeof(MMC_t)];
+ // unused section of address map
+ u8 unused_[1015808];
+
+/* Take this out until it is not empty */
+#if 0
+ EXP_ROM_t exp_rom;
+#endif
+
+ u8 unused_exp_rom[4096]; // MGS-size TBD
+ u8 unused__[524288]; // unused section of address map
+} ADDRESS_MAP_t, *PADDRESS_MAP_t;
+
+#endif /* _ET1310_ADDRESS_MAP_H_ */
diff --git a/drivers/staging/et131x/et1310_eeprom.c b/drivers/staging/et131x/et1310_eeprom.c
new file mode 100644
index 00000000000..c2b194e6a54
--- /dev/null
+++ b/drivers/staging/et131x/et1310_eeprom.c
@@ -0,0 +1,480 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_eeprom.c - Code used to access the device's EEPROM
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+#include "et1310_eeprom.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+#include "et131x_isr.h"
+
+#include "et1310_tx.h"
+
+
+/*
+ * EEPROM Defines
+ */
+
+/* LBCIF Register Groups (addressed via 32-bit offsets) */
+#define LBCIF_DWORD0_GROUP_OFFSET 0xAC
+#define LBCIF_DWORD1_GROUP_OFFSET 0xB0
+
+/* LBCIF Registers (addressed via 8-bit offsets) */
+#define LBCIF_ADDRESS_REGISTER_OFFSET 0xAC
+#define LBCIF_DATA_REGISTER_OFFSET 0xB0
+#define LBCIF_CONTROL_REGISTER_OFFSET 0xB1
+#define LBCIF_STATUS_REGISTER_OFFSET 0xB2
+
+/* LBCIF Control Register Bits */
+#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01
+#define LBCIF_CONTROL_PAGE_WRITE 0x02
+#define LBCIF_CONTROL_UNUSED1 0x04
+#define LBCIF_CONTROL_EEPROM_RELOAD 0x08
+#define LBCIF_CONTROL_UNUSED2 0x10
+#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20
+#define LBCIF_CONTROL_I2C_WRITE 0x40
+#define LBCIF_CONTROL_LBCIF_ENABLE 0x80
+
+/* LBCIF Status Register Bits */
+#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01
+#define LBCIF_STATUS_I2C_IDLE 0x02
+#define LBCIF_STATUS_ACK_ERROR 0x04
+#define LBCIF_STATUS_GENERAL_ERROR 0x08
+#define LBCIF_STATUS_UNUSED 0x30
+#define LBCIF_STATUS_CHECKSUM_ERROR 0x40
+#define LBCIF_STATUS_EEPROM_PRESENT 0x80
+
+/* Miscellaneous Constraints */
+#define MAX_NUM_REGISTER_POLLS 1000
+#define MAX_NUM_WRITE_RETRIES 2
+
+/*
+ * Define macros that allow individual register values to be extracted from a
+ * DWORD1 register grouping
+ */
+#define EXTRACT_DATA_REGISTER(x) (uint8_t)(x & 0xFF)
+#define EXTRACT_STATUS_REGISTER(x) (uint8_t)((x >> 16) & 0xFF)
+#define EXTRACT_CONTROL_REG(x) (uint8_t)((x >> 8) & 0xFF)
+
+/**
+ * EepromWriteByte - Write a byte to the ET1310's EEPROM
+ * @pAdapter: pointer to our private adapter structure
+ * @unAddress: the address to write
+ * @bData: the value to write
+ * @unEepronId: the ID of the EEPROM
+ * @unAddressingMode: how the EEPROM is to be accessed
+ *
+ * Returns SUCCESS or FAILURE
+ */
+int32_t EepromWriteByte(struct et131x_adapter *pAdapter, uint32_t unAddress,
+ uint8_t bData, uint32_t unEepromId,
+ uint32_t unAddressingMode)
+{
+ struct pci_dev *pdev = pAdapter->pdev;
+ int32_t nIndex;
+ int32_t nRetries;
+ int32_t nError = false;
+ int32_t nI2CWriteActive = 0;
+ int32_t nWriteSuccessful = 0;
+ uint8_t bControl;
+ uint8_t bStatus = 0;
+ uint32_t unDword1 = 0;
+ uint32_t unData = 0;
+
+ /*
+ * The following excerpt is from "Serial EEPROM HW Design
+ * Specification" Version 0.92 (9/20/2004):
+ *
+ * Single Byte Writes
+ *
+ * For an EEPROM, an I2C single byte write is defined as a START
+ * condition followed by the device address, EEPROM address, one byte
+ * of data and a STOP condition. The STOP condition will trigger the
+ * EEPROM's internally timed write cycle to the nonvolatile memory.
+ * All inputs are disabled during this write cycle and the EEPROM will
+ * not respond to any access until the internal write is complete.
+ * The steps to execute a single byte write are as follows:
+ *
+ * 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and
+ * bits 7,1:0 both equal to 1, at least once after reset.
+ * Subsequent operations need only to check that bits 1:0 are
+ * equal to 1 prior to starting a single byte write.
+ *
+ * 2. Write to the LBCIF Control Register: bit 7=1, bit 6=1, bit 3=0,
+ * and bits 1:0 both =0. Bit 5 should be set according to the
+ * type of EEPROM being accessed (1=two byte addressing, 0=one
+ * byte addressing).
+ *
+ * 3. Write the address to the LBCIF Address Register.
+ *
+ * 4. Write the data to the LBCIF Data Register (the I2C write will
+ * begin).
+ *
+ * 5. Monitor bit 1:0 of the LBCIF Status Register. When bits 1:0 are
+ * both equal to 1, the I2C write has completed and the internal
+ * write cycle of the EEPROM is about to start. (bits 1:0 = 01 is
+ * a legal state while waiting from both equal to 1, but bits
+ * 1:0 = 10 is invalid and implies that something is broken).
+ *
+ * 6. Check bit 3 of the LBCIF Status Register. If equal to 1, an
+ * error has occurred.
+ *
+ * 7. Check bit 2 of the LBCIF Status Register. If equal to 1 an ACK
+ * error has occurred on the address phase of the write. This
+ * could be due to an actual hardware failure or the EEPROM may
+ * still be in its internal write cycle from a previous write.
+ * This write operation was ignored and must be repeated later.
+ *
+ * 8. Set bit 6 of the LBCIF Control Register = 0. If another write is
+ * required, go to step 1.
+ */
+
+ /* Step 1: */
+ for (nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) {
+ /* Read registers grouped in DWORD1 */
+ if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET,
+ &unDword1)) {
+ nError = 1;
+ break;
+ }
+
+ bStatus = EXTRACT_STATUS_REGISTER(unDword1);
+
+ if (bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL &&
+ bStatus & LBCIF_STATUS_I2C_IDLE) {
+ /* bits 1:0 are equal to 1 */
+ break;
+ }
+ }
+
+ if (nError || (nIndex >= MAX_NUM_REGISTER_POLLS)) {
+ return FAILURE;
+ }
+
+ /* Step 2: */
+ bControl = 0;
+ bControl |= LBCIF_CONTROL_LBCIF_ENABLE | LBCIF_CONTROL_I2C_WRITE;
+
+ if (unAddressingMode == DUAL_BYTE) {
+ bControl |= LBCIF_CONTROL_TWO_BYTE_ADDR;
+ }
+
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET,
+ bControl)) {
+ return FAILURE;
+ }
+
+ nI2CWriteActive = 1;
+
+ /* Prepare EEPROM address for Step 3 */
+ unAddress |= (unAddressingMode == DUAL_BYTE) ?
+ (unEepromId << 16) : (unEepromId << 8);
+
+ for (nRetries = 0; nRetries < MAX_NUM_WRITE_RETRIES; nRetries++) {
+ /* Step 3:*/
+ if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER_OFFSET,
+ unAddress)) {
+ break;
+ }
+
+ /* Step 4: */
+ if (pci_write_config_byte(pdev, LBCIF_DATA_REGISTER_OFFSET,
+ bData)) {
+ break;
+ }
+
+ /* Step 5: */
+ for (nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) {
+ /* Read registers grouped in DWORD1 */
+ if (pci_read_config_dword(pdev,
+ LBCIF_DWORD1_GROUP_OFFSET,
+ &unDword1)) {
+ nError = 1;
+ break;
+ }
+
+ bStatus = EXTRACT_STATUS_REGISTER(unDword1);
+
+ if (bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL &&
+ bStatus & LBCIF_STATUS_I2C_IDLE) {
+ /* I2C write complete */
+ break;
+ }
+ }
+
+ if (nError || (nIndex >= MAX_NUM_REGISTER_POLLS)) {
+ break;
+ }
+
+ /*
+ * Step 6: Don't break here if we are revision 1, this is
+ * so we do a blind write for load bug.
+ */
+ if (bStatus & LBCIF_STATUS_GENERAL_ERROR
+ && pAdapter->RevisionID == 0) {
+ break;
+ }
+
+ /* Step 7 */
+ if (bStatus & LBCIF_STATUS_ACK_ERROR) {
+ /*
+ * This could be due to an actual hardware failure
+ * or the EEPROM may still be in its internal write
+ * cycle from a previous write. This write operation
+ * was ignored and must be repeated later.
+ */
+ udelay(10);
+ continue;
+ }
+
+ nWriteSuccessful = 1;
+ break;
+ }
+
+ /* Step 8: */
+ udelay(10);
+ nIndex = 0;
+ while (nI2CWriteActive) {
+ bControl &= ~LBCIF_CONTROL_I2C_WRITE;
+
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET,
+ bControl)) {
+ nWriteSuccessful = 0;
+ }
+
+ /* Do read until internal ACK_ERROR goes away meaning write
+ * completed
+ */
+ do {
+ pci_write_config_dword(pdev,
+ LBCIF_ADDRESS_REGISTER_OFFSET,
+ unAddress);
+ do {
+ pci_read_config_dword(pdev,
+ LBCIF_DATA_REGISTER_OFFSET, &unData);
+ } while ((unData & 0x00010000) == 0);
+ } while (unData & 0x00040000);
+
+ bControl = EXTRACT_CONTROL_REG(unData);
+
+ if (bControl != 0xC0 || nIndex == 10000) {
+ break;
+ }
+
+ nIndex++;
+ }
+
+ return nWriteSuccessful ? SUCCESS : FAILURE;
+}
+
+/**
+ * EepromReadByte - Read a byte from the ET1310's EEPROM
+ * @pAdapter: pointer to our private adapter structure
+ * @unAddress: the address from which to read
+ * @pbData: a pointer to a byte in which to store the value of the read
+ * @unEepronId: the ID of the EEPROM
+ * @unAddressingMode: how the EEPROM is to be accessed
+ *
+ * Returns SUCCESS or FAILURE
+ */
+int32_t EepromReadByte(struct et131x_adapter *pAdapter, uint32_t unAddress,
+ uint8_t *pbData, uint32_t unEepromId,
+ uint32_t unAddressingMode)
+{
+ struct pci_dev *pdev = pAdapter->pdev;
+ int32_t nIndex;
+ int32_t nError = 0;
+ uint8_t bControl;
+ uint8_t bStatus = 0;
+ uint32_t unDword1 = 0;
+
+ /*
+ * The following excerpt is from "Serial EEPROM HW Design
+ * Specification" Version 0.92 (9/20/2004):
+ *
+ * Single Byte Reads
+ *
+ * A single byte read is similar to the single byte write, with the
+ * exception of the data flow:
+ *
+ * 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and
+ * bits 7,1:0 both equal to 1, at least once after reset.
+ * Subsequent operations need only to check that bits 1:0 are equal
+ * to 1 prior to starting a single byte read.
+ *
+ * 2. Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0,
+ * and bits 1:0 both =0. Bit 5 should be set according to the type
+ * of EEPROM being accessed (1=two byte addressing, 0=one byte
+ * addressing).
+ *
+ * 3. Write the address to the LBCIF Address Register (I2C read will
+ * begin).
+ *
+ * 4. Monitor bit 0 of the LBCIF Status Register. When =1, I2C read
+ * is complete. (if bit 1 =1 and bit 0 stays =0, a hardware failure
+ * has occurred).
+ *
+ * 5. Check bit 2 of the LBCIF Status Register. If =1, then an error
+ * has occurred. The data that has been returned from the PHY may
+ * be invalid.
+ *
+ * 6. Regardless of error status, read data byte from LBCIF Data
+ * Register. If another byte is required, go to step 1.
+ */
+
+ /* Step 1: */
+ for (nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) {
+ /* Read registers grouped in DWORD1 */
+ if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET,
+ &unDword1)) {
+ nError = 1;
+ break;
+ }
+
+ bStatus = EXTRACT_STATUS_REGISTER(unDword1);
+
+ if (bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL &&
+ bStatus & LBCIF_STATUS_I2C_IDLE) {
+ /* bits 1:0 are equal to 1 */
+ break;
+ }
+ }
+
+ if (nError || (nIndex >= MAX_NUM_REGISTER_POLLS)) {
+ return FAILURE;
+ }
+
+ /* Step 2: */
+ bControl = 0;
+ bControl |= LBCIF_CONTROL_LBCIF_ENABLE;
+
+ if (unAddressingMode == DUAL_BYTE) {
+ bControl |= LBCIF_CONTROL_TWO_BYTE_ADDR;
+ }
+
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER_OFFSET,
+ bControl)) {
+ return FAILURE;
+ }
+
+ /* Step 3: */
+ unAddress |= (unAddressingMode == DUAL_BYTE) ?
+ (unEepromId << 16) : (unEepromId << 8);
+
+ if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER_OFFSET,
+ unAddress)) {
+ return FAILURE;
+ }
+
+ /* Step 4: */
+ for (nIndex = 0; nIndex < MAX_NUM_REGISTER_POLLS; nIndex++) {
+ /* Read registers grouped in DWORD1 */
+ if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP_OFFSET,
+ &unDword1)) {
+ nError = 1;
+ break;
+ }
+
+ bStatus = EXTRACT_STATUS_REGISTER(unDword1);
+
+ if (bStatus & LBCIF_STATUS_PHY_QUEUE_AVAIL
+ && bStatus & LBCIF_STATUS_I2C_IDLE) {
+ /* I2C read complete */
+ break;
+ }
+ }
+
+ if (nError || (nIndex >= MAX_NUM_REGISTER_POLLS)) {
+ return FAILURE;
+ }
+
+ /* Step 6: */
+ *pbData = EXTRACT_DATA_REGISTER(unDword1);
+
+ return (bStatus & LBCIF_STATUS_ACK_ERROR) ? FAILURE : SUCCESS;
+}
diff --git a/drivers/staging/et131x/et1310_eeprom.h b/drivers/staging/et131x/et1310_eeprom.h
new file mode 100644
index 00000000000..9b6f8ad77b4
--- /dev/null
+++ b/drivers/staging/et131x/et1310_eeprom.h
@@ -0,0 +1,89 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_eeprom.h - Defines, structs, enums, prototypes, etc. used for EEPROM
+ * access routines
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET1310_EEPROM_H__
+#define __ET1310_EEPROM_H__
+
+#include "et1310_address_map.h"
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#define FAILURE 1
+#endif
+
+#ifndef READ
+#define READ 0
+#define WRITE 1
+#endif
+
+#ifndef SINGLE_BYTE
+#define SINGLE_BYTE 0
+#define DUAL_BYTE 1
+#endif
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+int32_t EepromWriteByte(struct et131x_adapter *adapter, u32 unAddress,
+ u8 bData, u32 unEepromId,
+ u32 unAddressingMode);
+int32_t EepromReadByte(struct et131x_adapter *adapter, u32 unAddress,
+ u8 *pbData, u32 unEepromId,
+ u32 unAddressingMode);
+
+#endif /* _ET1310_EEPROM_H_ */
diff --git a/drivers/staging/et131x/et1310_jagcore.c b/drivers/staging/et131x/et1310_jagcore.c
new file mode 100644
index 00000000000..993b30ea71e
--- /dev/null
+++ b/drivers/staging/et131x/et1310_jagcore.c
@@ -0,0 +1,220 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_jagcore.c - All code pertaining to the ET1301/ET131x's JAGcore
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/**
+ * ConfigGlobalRegs - Used to configure the global registers on the JAGCore
+ * @pAdpater: pointer to our adapter structure
+ */
+void ConfigGlobalRegs(struct et131x_adapter *pAdapter)
+{
+ struct _GLOBAL_t __iomem *pGbl = &pAdapter->CSRAddress->global;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ if (pAdapter->RegistryPhyLoopbk == false) {
+ if (pAdapter->RegistryJumboPacket < 2048) {
+ /* Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word
+ * block of RAM that the driver can split between Tx
+ * and Rx as it desires. Our default is to split it
+ * 50/50:
+ */
+ writel(0, &pGbl->rxq_start_addr.value);
+ writel(pAdapter->RegistryRxMemEnd,
+ &pGbl->rxq_end_addr.value);
+ writel(pAdapter->RegistryRxMemEnd + 1,
+ &pGbl->txq_start_addr.value);
+ writel(INTERNAL_MEM_SIZE - 1,
+ &pGbl->txq_end_addr.value);
+ } else if (pAdapter->RegistryJumboPacket < 8192) {
+ /* For jumbo packets > 2k but < 8k, split 50-50. */
+ writel(0, &pGbl->rxq_start_addr.value);
+ writel(INTERNAL_MEM_RX_OFFSET,
+ &pGbl->rxq_end_addr.value);
+ writel(INTERNAL_MEM_RX_OFFSET + 1,
+ &pGbl->txq_start_addr.value);
+ writel(INTERNAL_MEM_SIZE - 1,
+ &pGbl->txq_end_addr.value);
+ } else {
+ /* 9216 is the only packet size greater than 8k that
+ * is available. The Tx buffer has to be big enough
+ * for one whole packet on the Tx side. We'll make
+ * the Tx 9408, and give the rest to Rx
+ */
+ writel(0x0000, &pGbl->rxq_start_addr.value);
+ writel(0x01b3, &pGbl->rxq_end_addr.value);
+ writel(0x01b4, &pGbl->txq_start_addr.value);
+ writel(INTERNAL_MEM_SIZE - 1,
+ &pGbl->txq_end_addr.value);
+ }
+
+ /* Initialize the loopback register. Disable all loopbacks. */
+ writel(0, &pGbl->loopback.value);
+ } else {
+ /* For PHY Line loopback, the memory is configured as if Tx
+ * and Rx both have all the memory. This is because the
+ * RxMAC will write data into the space, and the TxMAC will
+ * read it out.
+ */
+ writel(0, &pGbl->rxq_start_addr.value);
+ writel(INTERNAL_MEM_SIZE - 1, &pGbl->rxq_end_addr.value);
+ writel(0, &pGbl->txq_start_addr.value);
+ writel(INTERNAL_MEM_SIZE - 1, &pGbl->txq_end_addr.value);
+
+ /* Initialize the loopback register (MAC loopback). */
+ writel(1, &pGbl->loopback.value);
+ }
+
+ /* MSI Register */
+ writel(0, &pGbl->msi_config.value);
+
+ /* By default, disable the watchdog timer. It will be enabled when
+ * a packet is queued.
+ */
+ writel(0, &pGbl->watchdog_timer);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * ConfigMMCRegs - Used to configure the main memory registers in the JAGCore
+ * @pAdapter: pointer to our adapter structure
+ */
+void ConfigMMCRegs(struct et131x_adapter *pAdapter)
+{
+ MMC_CTRL_t mmc_ctrl = { 0 };
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* All we need to do is initialize the Memory Control Register */
+ mmc_ctrl.bits.force_ce = 0x0;
+ mmc_ctrl.bits.rxdma_disable = 0x0;
+ mmc_ctrl.bits.txdma_disable = 0x0;
+ mmc_ctrl.bits.txmac_disable = 0x0;
+ mmc_ctrl.bits.rxmac_disable = 0x0;
+ mmc_ctrl.bits.arb_disable = 0x0;
+ mmc_ctrl.bits.mmc_enable = 0x1;
+
+ writel(mmc_ctrl.value, &pAdapter->CSRAddress->mmc.mmc_ctrl.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void et131x_enable_interrupts(struct et131x_adapter *adapter)
+{
+ uint32_t MaskValue;
+
+ /* Enable all global interrupts */
+ if ((adapter->FlowControl == TxOnly) || (adapter->FlowControl == Both)) {
+ MaskValue = INT_MASK_ENABLE;
+ } else {
+ MaskValue = INT_MASK_ENABLE_NO_FLOW;
+ }
+
+ if (adapter->DriverNoPhyAccess) {
+ MaskValue |= 0x10000;
+ }
+
+ adapter->CachedMaskValue.value = MaskValue;
+ writel(MaskValue, &adapter->CSRAddress->global.int_mask.value);
+}
+
+void et131x_disable_interrupts(struct et131x_adapter * adapter)
+{
+ /* Disable all global interrupts */
+ adapter->CachedMaskValue.value = INT_MASK_DISABLE;
+ writel(INT_MASK_DISABLE, &adapter->CSRAddress->global.int_mask.value);
+}
diff --git a/drivers/staging/et131x/et1310_jagcore.h b/drivers/staging/et131x/et1310_jagcore.h
new file mode 100644
index 00000000000..9fc829336df
--- /dev/null
+++ b/drivers/staging/et131x/et1310_jagcore.h
@@ -0,0 +1,112 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_jagcore.h - Defines, structs, enums, prototypes, etc. pertaining to
+ * the JAGCore
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET1310_JAGCORE_H__
+#define __ET1310_JAGCORE_H__
+
+#include "et1310_address_map.h"
+
+
+#define INTERNAL_MEM_SIZE 0x400 //1024 of internal memory
+#define INTERNAL_MEM_RX_OFFSET 0x1FF //50% Tx, 50% Rx
+
+#define REGS_MAX_ARRAY 4096
+
+/*
+ * For interrupts, normal running is:
+ * rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
+ * watchdog_interrupt & txdma_xfer_done
+ *
+ * In both cases, when flow control is enabled for either Tx or bi-direction,
+ * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
+ * buffer rings are running low.
+ */
+#define INT_MASK_DISABLE 0xffffffff
+
+// NOTE: Masking out MAC_STAT Interrupt for now...
+//#define INT_MASK_ENABLE 0xfff6bf17
+//#define INT_MASK_ENABLE_NO_FLOW 0xfff6bfd7
+#define INT_MASK_ENABLE 0xfffebf17
+#define INT_MASK_ENABLE_NO_FLOW 0xfffebfd7
+
+/* DATA STRUCTURES FOR DIRECT REGISTER ACCESS */
+
+typedef struct {
+ u8 bReadWrite;
+ u32 nRegCount;
+ u32 nData[REGS_MAX_ARRAY];
+ u32 nOffsets[REGS_MAX_ARRAY];
+} JAGCORE_ACCESS_REGS, *PJAGCORE_ACCESS_REGS;
+
+typedef struct {
+ u8 bReadWrite;
+ u32 nDataWidth;
+ u32 nRegCount;
+ u32 nOffsets[REGS_MAX_ARRAY];
+ u32 nData[REGS_MAX_ARRAY];
+} PCI_CFG_SPACE_REGS, *PPCI_CFG_SPACE_REGS;
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+void ConfigGlobalRegs(struct et131x_adapter *pAdapter);
+void ConfigMMCRegs(struct et131x_adapter *pAdapter);
+void et131x_enable_interrupts(struct et131x_adapter *adapter);
+void et131x_disable_interrupts(struct et131x_adapter *adapter);
+
+#endif /* __ET1310_JAGCORE_H__ */
diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c
new file mode 100644
index 00000000000..1924968ab24
--- /dev/null
+++ b/drivers/staging/et131x/et1310_mac.c
@@ -0,0 +1,792 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_mac.c - All code and routines pertaining to the MAC
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+#include "et1310_mac.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/**
+ * ConfigMacRegs1 - Initialize the first part of MAC regs
+ * @pAdpater: pointer to our adapter structure
+ */
+void ConfigMACRegs1(struct et131x_adapter *pAdapter)
+{
+ struct _MAC_t __iomem *pMac = &pAdapter->CSRAddress->mac;
+ MAC_STATION_ADDR1_t station1;
+ MAC_STATION_ADDR2_t station2;
+ MAC_IPG_t ipg;
+ MAC_HFDP_t hfdp;
+ MII_MGMT_CFG_t mii_mgmt_cfg;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* First we need to reset everything. Write to MAC configuration
+ * register 1 to perform reset.
+ */
+ writel(0xC00F0000, &pMac->cfg1.value);
+
+ /* Next lets configure the MAC Inter-packet gap register */
+ ipg.bits.non_B2B_ipg_1 = 0x38; // 58d
+ ipg.bits.non_B2B_ipg_2 = 0x58; // 88d
+ ipg.bits.min_ifg_enforce = 0x50; // 80d
+ ipg.bits.B2B_ipg = 0x60; // 96d
+ writel(ipg.value, &pMac->ipg.value);
+
+ /* Next lets configure the MAC Half Duplex register */
+ hfdp.bits.alt_beb_trunc = 0xA;
+ hfdp.bits.alt_beb_enable = 0x0;
+ hfdp.bits.bp_no_backoff = 0x0;
+ hfdp.bits.no_backoff = 0x0;
+ hfdp.bits.excess_defer = 0x1;
+ hfdp.bits.rexmit_max = 0xF;
+ hfdp.bits.coll_window = 0x37; // 55d
+ writel(hfdp.value, &pMac->hfdp.value);
+
+ /* Next lets configure the MAC Interface Control register */
+ writel(0, &pMac->if_ctrl.value);
+
+ /* Let's move on to setting up the mii managment configuration */
+ mii_mgmt_cfg.bits.reset_mii_mgmt = 0;
+ mii_mgmt_cfg.bits.scan_auto_incremt = 0;
+ mii_mgmt_cfg.bits.preamble_suppress = 0;
+ mii_mgmt_cfg.bits.mgmt_clk_reset = 0x7;
+ writel(mii_mgmt_cfg.value, &pMac->mii_mgmt_cfg.value);
+
+ /* Next lets configure the MAC Station Address register. These
+ * values are read from the EEPROM during initialization and stored
+ * in the adapter structure. We write what is stored in the adapter
+ * structure to the MAC Station Address registers high and low. This
+ * station address is used for generating and checking pause control
+ * packets.
+ */
+ station2.bits.Octet1 = pAdapter->CurrentAddress[0];
+ station2.bits.Octet2 = pAdapter->CurrentAddress[1];
+ station1.bits.Octet3 = pAdapter->CurrentAddress[2];
+ station1.bits.Octet4 = pAdapter->CurrentAddress[3];
+ station1.bits.Octet5 = pAdapter->CurrentAddress[4];
+ station1.bits.Octet6 = pAdapter->CurrentAddress[5];
+ writel(station1.value, &pMac->station_addr_1.value);
+ writel(station2.value, &pMac->station_addr_2.value);
+
+ /* Max ethernet packet in bytes that will passed by the mac without
+ * being truncated. Allow the MAC to pass 4 more than our max packet
+ * size. This is 4 for the Ethernet CRC.
+ *
+ * Packets larger than (RegistryJumboPacket) that do not contain a
+ * VLAN ID will be dropped by the Rx function.
+ */
+ writel(pAdapter->RegistryJumboPacket + 4, &pMac->max_fm_len.value);
+
+ /* clear out MAC config reset */
+ writel(0, &pMac->cfg1.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * ConfigMacRegs2 - Initialize the second part of MAC regs
+ * @pAdpater: pointer to our adapter structure
+ */
+void ConfigMACRegs2(struct et131x_adapter *pAdapter)
+{
+ int32_t delay = 0;
+ struct _MAC_t __iomem *pMac = &pAdapter->CSRAddress->mac;
+ MAC_CFG1_t cfg1;
+ MAC_CFG2_t cfg2;
+ MAC_IF_CTRL_t ifctrl;
+ TXMAC_CTL_t ctl;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ ctl.value = readl(&pAdapter->CSRAddress->txmac.ctl.value);
+ cfg1.value = readl(&pMac->cfg1.value);
+ cfg2.value = readl(&pMac->cfg2.value);
+ ifctrl.value = readl(&pMac->if_ctrl.value);
+
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) {
+ cfg2.bits.if_mode = 0x2;
+ ifctrl.bits.phy_mode = 0x0;
+ } else {
+ cfg2.bits.if_mode = 0x1;
+ ifctrl.bits.phy_mode = 0x1;
+ }
+
+ /* We need to enable Rx/Tx */
+ cfg1.bits.rx_enable = 0x1;
+ cfg1.bits.tx_enable = 0x1;
+
+ /* Set up flow control */
+ cfg1.bits.tx_flow = 0x1;
+
+ if ((pAdapter->FlowControl == RxOnly) ||
+ (pAdapter->FlowControl == Both)) {
+ cfg1.bits.rx_flow = 0x1;
+ } else {
+ cfg1.bits.rx_flow = 0x0;
+ }
+
+ /* Initialize loop back to off */
+ cfg1.bits.loop_back = 0;
+
+ writel(cfg1.value, &pMac->cfg1.value);
+
+ /* Now we need to initialize the MAC Configuration 2 register */
+ cfg2.bits.preamble_len = 0x7;
+ cfg2.bits.huge_frame = 0x0;
+ /* LENGTH FIELD CHECKING bit4: Set this bit to cause the MAC to check
+ * the frame's length field to ensure it matches the actual data
+ * field length. Clear this bit if no length field checking is
+ * desired. Its default is 0.
+ */
+ cfg2.bits.len_check = 0x1;
+
+ if (pAdapter->RegistryPhyLoopbk == false) {
+ cfg2.bits.pad_crc = 0x1;
+ cfg2.bits.crc_enable = 0x1;
+ } else {
+ cfg2.bits.pad_crc = 0;
+ cfg2.bits.crc_enable = 0;
+ }
+
+ /* 1 - full duplex, 0 - half-duplex */
+ cfg2.bits.full_duplex = pAdapter->uiDuplexMode;
+ ifctrl.bits.ghd_mode = !pAdapter->uiDuplexMode;
+
+ writel(ifctrl.value, &pMac->if_ctrl.value);
+ writel(cfg2.value, &pMac->cfg2.value);
+
+ do {
+ udelay(10);
+ delay++;
+ cfg1.value = readl(&pMac->cfg1.value);
+ } while ((!cfg1.bits.syncd_rx_en ||
+ !cfg1.bits.syncd_tx_en) &&
+ delay < 100);
+
+ if (delay == 100) {
+ DBG_ERROR(et131x_dbginfo,
+ "Syncd bits did not respond correctly cfg1 word 0x%08x\n",
+ cfg1.value);
+ }
+
+ DBG_TRACE(et131x_dbginfo,
+ "Speed %d, Dup %d, CFG1 0x%08x, CFG2 0x%08x, if_ctrl 0x%08x\n",
+ pAdapter->uiLinkSpeed, pAdapter->uiDuplexMode,
+ readl(&pMac->cfg1.value), readl(&pMac->cfg2.value),
+ readl(&pMac->if_ctrl.value));
+
+ /* Enable TXMAC */
+ ctl.bits.txmac_en = 0x1;
+ ctl.bits.fc_disable = 0x1;
+ writel(ctl.value, &pAdapter->CSRAddress->txmac.ctl.value);
+
+ /* Ready to start the RXDMA/TXDMA engine */
+ if (!MP_TEST_FLAG(pAdapter, fMP_ADAPTER_LOWER_POWER)) {
+ et131x_rx_dma_enable(pAdapter);
+ et131x_tx_dma_enable(pAdapter);
+ } else {
+ DBG_WARNING(et131x_dbginfo,
+ "Didn't enable Rx/Tx due to low-power mode\n");
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void ConfigRxMacRegs(struct et131x_adapter *pAdapter)
+{
+ struct _RXMAC_t __iomem *pRxMac = &pAdapter->CSRAddress->rxmac;
+ RXMAC_WOL_SA_LO_t sa_lo;
+ RXMAC_WOL_SA_HI_t sa_hi;
+ RXMAC_PF_CTRL_t pf_ctrl = { 0 };
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Disable the MAC while it is being configured (also disable WOL) */
+ writel(0x8, &pRxMac->ctrl.value);
+
+ /* Initialize WOL to disabled. */
+ writel(0, &pRxMac->crc0.value);
+ writel(0, &pRxMac->crc12.value);
+ writel(0, &pRxMac->crc34.value);
+
+ /* We need to set the WOL mask0 - mask4 next. We initialize it to
+ * its default Values of 0x00000000 because there are not WOL masks
+ * as of this time.
+ */
+ writel(0, &pRxMac->mask0_word0);
+ writel(0, &pRxMac->mask0_word1);
+ writel(0, &pRxMac->mask0_word2);
+ writel(0, &pRxMac->mask0_word3);
+
+ writel(0, &pRxMac->mask1_word0);
+ writel(0, &pRxMac->mask1_word1);
+ writel(0, &pRxMac->mask1_word2);
+ writel(0, &pRxMac->mask1_word3);
+
+ writel(0, &pRxMac->mask2_word0);
+ writel(0, &pRxMac->mask2_word1);
+ writel(0, &pRxMac->mask2_word2);
+ writel(0, &pRxMac->mask2_word3);
+
+ writel(0, &pRxMac->mask3_word0);
+ writel(0, &pRxMac->mask3_word1);
+ writel(0, &pRxMac->mask3_word2);
+ writel(0, &pRxMac->mask3_word3);
+
+ writel(0, &pRxMac->mask4_word0);
+ writel(0, &pRxMac->mask4_word1);
+ writel(0, &pRxMac->mask4_word2);
+ writel(0, &pRxMac->mask4_word3);
+
+ /* Lets setup the WOL Source Address */
+ sa_lo.bits.sa3 = pAdapter->CurrentAddress[2];
+ sa_lo.bits.sa4 = pAdapter->CurrentAddress[3];
+ sa_lo.bits.sa5 = pAdapter->CurrentAddress[4];
+ sa_lo.bits.sa6 = pAdapter->CurrentAddress[5];
+ writel(sa_lo.value, &pRxMac->sa_lo.value);
+
+ sa_hi.bits.sa1 = pAdapter->CurrentAddress[0];
+ sa_hi.bits.sa2 = pAdapter->CurrentAddress[1];
+ writel(sa_hi.value, &pRxMac->sa_hi.value);
+
+ /* Disable all Packet Filtering */
+ writel(0, &pRxMac->pf_ctrl.value);
+
+ /* Let's initialize the Unicast Packet filtering address */
+ if (pAdapter->PacketFilter & ET131X_PACKET_TYPE_DIRECTED) {
+ SetupDeviceForUnicast(pAdapter);
+ pf_ctrl.bits.filter_uni_en = 1;
+ } else {
+ writel(0, &pRxMac->uni_pf_addr1.value);
+ writel(0, &pRxMac->uni_pf_addr2.value);
+ writel(0, &pRxMac->uni_pf_addr3.value);
+ }
+
+ /* Let's initialize the Multicast hash */
+ if (pAdapter->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
+ pf_ctrl.bits.filter_multi_en = 0;
+ } else {
+ pf_ctrl.bits.filter_multi_en = 1;
+ SetupDeviceForMulticast(pAdapter);
+ }
+
+ /* Runt packet filtering. Didn't work in version A silicon. */
+ pf_ctrl.bits.min_pkt_size = NIC_MIN_PACKET_SIZE + 4;
+ pf_ctrl.bits.filter_frag_en = 1;
+
+ if (pAdapter->RegistryJumboPacket > 8192) {
+ RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg;
+
+ /* In order to transmit jumbo packets greater than 8k, the
+ * FIFO between RxMAC and RxDMA needs to be reduced in size
+ * to (16k - Jumbo packet size). In order to implement this,
+ * we must use "cut through" mode in the RxMAC, which chops
+ * packets down into segments which are (max_size * 16). In
+ * this case we selected 256 bytes, since this is the size of
+ * the PCI-Express TLP's that the 1310 uses.
+ */
+ mcif_ctrl_max_seg.bits.seg_en = 0x1;
+ mcif_ctrl_max_seg.bits.fc_en = 0x0;
+ mcif_ctrl_max_seg.bits.max_size = 0x10;
+
+ writel(mcif_ctrl_max_seg.value,
+ &pRxMac->mcif_ctrl_max_seg.value);
+ } else {
+ writel(0, &pRxMac->mcif_ctrl_max_seg.value);
+ }
+
+ /* Initialize the MCIF water marks */
+ writel(0, &pRxMac->mcif_water_mark.value);
+
+ /* Initialize the MIF control */
+ writel(0, &pRxMac->mif_ctrl.value);
+
+ /* Initialize the Space Available Register */
+ writel(0, &pRxMac->space_avail.value);
+
+ /* Initialize the the mif_ctrl register
+ * bit 3: Receive code error. One or more nibbles were signaled as
+ * errors during the reception of the packet. Clear this
+ * bit in Gigabit, set it in 100Mbit. This was derived
+ * experimentally at UNH.
+ * bit 4: Receive CRC error. The packet's CRC did not match the
+ * internally generated CRC.
+ * bit 5: Receive length check error. Indicates that frame length
+ * field value in the packet does not match the actual data
+ * byte length and is not a type field.
+ * bit 16: Receive frame truncated.
+ * bit 17: Drop packet enable
+ */
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_100MBPS) {
+ writel(0x30038, &pRxMac->mif_ctrl.value);
+ } else {
+ writel(0x30030, &pRxMac->mif_ctrl.value);
+ }
+
+ /* Finally we initialize RxMac to be enabled & WOL disabled. Packet
+ * filter is always enabled since it is where the runt packets are
+ * supposed to be dropped. For version A silicon, runt packet
+ * dropping doesn't work, so it is disabled in the pf_ctrl register,
+ * but we still leave the packet filter on.
+ */
+ writel(pf_ctrl.value, &pRxMac->pf_ctrl.value);
+ writel(0x9, &pRxMac->ctrl.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void ConfigTxMacRegs(struct et131x_adapter *pAdapter)
+{
+ struct _TXMAC_t __iomem *pTxMac = &pAdapter->CSRAddress->txmac;
+ TXMAC_CF_PARAM_t Local;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* We need to update the Control Frame Parameters
+ * cfpt - control frame pause timer set to 64 (0x40)
+ * cfep - control frame extended pause timer set to 0x0
+ */
+ if (pAdapter->FlowControl == None) {
+ writel(0, &pTxMac->cf_param.value);
+ } else {
+ Local.bits.cfpt = 0x40;
+ Local.bits.cfep = 0x0;
+ writel(Local.value, &pTxMac->cf_param.value);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void ConfigMacStatRegs(struct et131x_adapter *pAdapter)
+{
+ struct _MAC_STAT_t __iomem *pDevMacStat =
+ &pAdapter->CSRAddress->macStat;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Next we need to initialize all the MAC_STAT registers to zero on
+ * the device.
+ */
+ writel(0, &pDevMacStat->RFcs);
+ writel(0, &pDevMacStat->RAln);
+ writel(0, &pDevMacStat->RFlr);
+ writel(0, &pDevMacStat->RDrp);
+ writel(0, &pDevMacStat->RCde);
+ writel(0, &pDevMacStat->ROvr);
+ writel(0, &pDevMacStat->RFrg);
+
+ writel(0, &pDevMacStat->TScl);
+ writel(0, &pDevMacStat->TDfr);
+ writel(0, &pDevMacStat->TMcl);
+ writel(0, &pDevMacStat->TLcl);
+ writel(0, &pDevMacStat->TNcl);
+ writel(0, &pDevMacStat->TOvr);
+ writel(0, &pDevMacStat->TUnd);
+
+ /* Unmask any counters that we want to track the overflow of.
+ * Initially this will be all counters. It may become clear later
+ * that we do not need to track all counters.
+ */
+ {
+ MAC_STAT_REG_1_t Carry1M = { 0xffffffff };
+
+ Carry1M.bits.rdrp = 0;
+ Carry1M.bits.rjbr = 1;
+ Carry1M.bits.rfrg = 0;
+ Carry1M.bits.rovr = 0;
+ Carry1M.bits.rund = 1;
+ Carry1M.bits.rcse = 1;
+ Carry1M.bits.rcde = 0;
+ Carry1M.bits.rflr = 0;
+ Carry1M.bits.raln = 0;
+ Carry1M.bits.rxuo = 1;
+ Carry1M.bits.rxpf = 1;
+ Carry1M.bits.rxcf = 1;
+ Carry1M.bits.rbca = 1;
+ Carry1M.bits.rmca = 1;
+ Carry1M.bits.rfcs = 0;
+ Carry1M.bits.rpkt = 1;
+ Carry1M.bits.rbyt = 1;
+ Carry1M.bits.trmgv = 1;
+ Carry1M.bits.trmax = 1;
+ Carry1M.bits.tr1k = 1;
+ Carry1M.bits.tr511 = 1;
+ Carry1M.bits.tr255 = 1;
+ Carry1M.bits.tr127 = 1;
+ Carry1M.bits.tr64 = 1;
+
+ writel(Carry1M.value, &pDevMacStat->Carry1M.value);
+ }
+
+ {
+ MAC_STAT_REG_2_t Carry2M = { 0xffffffff };
+
+ Carry2M.bits.tdrp = 1;
+ Carry2M.bits.tpfh = 1;
+ Carry2M.bits.tncl = 0;
+ Carry2M.bits.txcl = 1;
+ Carry2M.bits.tlcl = 0;
+ Carry2M.bits.tmcl = 0;
+ Carry2M.bits.tscl = 0;
+ Carry2M.bits.tedf = 1;
+ Carry2M.bits.tdfr = 0;
+ Carry2M.bits.txpf = 1;
+ Carry2M.bits.tbca = 1;
+ Carry2M.bits.tmca = 1;
+ Carry2M.bits.tpkt = 1;
+ Carry2M.bits.tbyt = 1;
+ Carry2M.bits.tfrg = 1;
+ Carry2M.bits.tund = 0;
+ Carry2M.bits.tovr = 0;
+ Carry2M.bits.txcf = 1;
+ Carry2M.bits.tfcs = 1;
+ Carry2M.bits.tjbr = 1;
+
+ writel(Carry2M.value, &pDevMacStat->Carry2M.value);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void ConfigFlowControl(struct et131x_adapter * pAdapter)
+{
+ if (pAdapter->uiDuplexMode == 0) {
+ pAdapter->FlowControl = None;
+ } else {
+ char RemotePause, RemoteAsyncPause;
+
+ ET1310_PhyAccessMiBit(pAdapter,
+ TRUEPHY_BIT_READ, 5, 10, &RemotePause);
+ ET1310_PhyAccessMiBit(pAdapter,
+ TRUEPHY_BIT_READ, 5, 11,
+ &RemoteAsyncPause);
+
+ if ((RemotePause == TRUEPHY_BIT_SET) &&
+ (RemoteAsyncPause == TRUEPHY_BIT_SET)) {
+ pAdapter->FlowControl = pAdapter->RegistryFlowControl;
+ } else if ((RemotePause == TRUEPHY_BIT_SET) &&
+ (RemoteAsyncPause == TRUEPHY_BIT_CLEAR)) {
+ if (pAdapter->RegistryFlowControl == Both) {
+ pAdapter->FlowControl = Both;
+ } else {
+ pAdapter->FlowControl = None;
+ }
+ } else if ((RemotePause == TRUEPHY_BIT_CLEAR) &&
+ (RemoteAsyncPause == TRUEPHY_BIT_CLEAR)) {
+ pAdapter->FlowControl = None;
+ } else {/* if (RemotePause == TRUEPHY_CLEAR_BIT &&
+ RemoteAsyncPause == TRUEPHY_SET_BIT) */
+ if (pAdapter->RegistryFlowControl == Both) {
+ pAdapter->FlowControl = RxOnly;
+ } else {
+ pAdapter->FlowControl = None;
+ }
+ }
+ }
+}
+
+/**
+ * UpdateMacStatHostCounters - Update the local copy of the statistics
+ * @pAdapter: pointer to the adapter structure
+ */
+void UpdateMacStatHostCounters(struct et131x_adapter *pAdapter)
+{
+ struct _ce_stats_t *stats = &pAdapter->Stats;
+ struct _MAC_STAT_t __iomem *pDevMacStat =
+ &pAdapter->CSRAddress->macStat;
+
+ stats->collisions += readl(&pDevMacStat->TNcl);
+ stats->first_collision += readl(&pDevMacStat->TScl);
+ stats->tx_deferred += readl(&pDevMacStat->TDfr);
+ stats->excessive_collisions += readl(&pDevMacStat->TMcl);
+ stats->late_collisions += readl(&pDevMacStat->TLcl);
+ stats->tx_uflo += readl(&pDevMacStat->TUnd);
+ stats->max_pkt_error += readl(&pDevMacStat->TOvr);
+
+ stats->alignment_err += readl(&pDevMacStat->RAln);
+ stats->crc_err += readl(&pDevMacStat->RCde);
+ stats->norcvbuf += readl(&pDevMacStat->RDrp);
+ stats->rx_ov_flow += readl(&pDevMacStat->ROvr);
+ stats->code_violations += readl(&pDevMacStat->RFcs);
+ stats->length_err += readl(&pDevMacStat->RFlr);
+
+ stats->other_errors += readl(&pDevMacStat->RFrg);
+}
+
+/**
+ * HandleMacStatInterrupt
+ * @pAdapter: pointer to the adapter structure
+ *
+ * One of the MACSTAT counters has wrapped. Update the local copy of
+ * the statistics held in the adapter structure, checking the "wrap"
+ * bit for each counter.
+ */
+void HandleMacStatInterrupt(struct et131x_adapter *pAdapter)
+{
+ MAC_STAT_REG_1_t Carry1;
+ MAC_STAT_REG_2_t Carry2;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Read the interrupt bits from the register(s). These are Clear On
+ * Write.
+ */
+ Carry1.value = readl(&pAdapter->CSRAddress->macStat.Carry1.value);
+ Carry2.value = readl(&pAdapter->CSRAddress->macStat.Carry2.value);
+
+ writel(Carry1.value, &pAdapter->CSRAddress->macStat.Carry1.value);
+ writel(Carry2.value, &pAdapter->CSRAddress->macStat.Carry2.value);
+
+ /* We need to do update the host copy of all the MAC_STAT counters.
+ * For each counter, check it's overflow bit. If the overflow bit is
+ * set, then increment the host version of the count by one complete
+ * revolution of the counter. This routine is called when the counter
+ * block indicates that one of the counters has wrapped.
+ */
+ if (Carry1.bits.rfcs) {
+ pAdapter->Stats.code_violations += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry1.bits.raln) {
+ pAdapter->Stats.alignment_err += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry1.bits.rflr) {
+ pAdapter->Stats.length_err += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry1.bits.rfrg) {
+ pAdapter->Stats.other_errors += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry1.bits.rcde) {
+ pAdapter->Stats.crc_err += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry1.bits.rovr) {
+ pAdapter->Stats.rx_ov_flow += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry1.bits.rdrp) {
+ pAdapter->Stats.norcvbuf += COUNTER_WRAP_16_BIT;
+ }
+ if (Carry2.bits.tovr) {
+ pAdapter->Stats.max_pkt_error += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tund) {
+ pAdapter->Stats.tx_uflo += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tscl) {
+ pAdapter->Stats.first_collision += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tdfr) {
+ pAdapter->Stats.tx_deferred += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tmcl) {
+ pAdapter->Stats.excessive_collisions += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tlcl) {
+ pAdapter->Stats.late_collisions += COUNTER_WRAP_12_BIT;
+ }
+ if (Carry2.bits.tncl) {
+ pAdapter->Stats.collisions += COUNTER_WRAP_12_BIT;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void SetupDeviceForMulticast(struct et131x_adapter *pAdapter)
+{
+ struct _RXMAC_t __iomem *rxmac = &pAdapter->CSRAddress->rxmac;
+ uint32_t nIndex;
+ uint32_t result;
+ uint32_t hash1 = 0;
+ uint32_t hash2 = 0;
+ uint32_t hash3 = 0;
+ uint32_t hash4 = 0;
+ PM_CSR_t pm_csr;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision
+ * the multi-cast LIST. If it is NOT specified, (and "ALL" is not
+ * specified) then we should pass NO multi-cast addresses to the
+ * driver.
+ */
+ if (pAdapter->PacketFilter & ET131X_PACKET_TYPE_MULTICAST) {
+ DBG_VERBOSE(et131x_dbginfo,
+ "MULTICAST flag is set, MCCount: %d\n",
+ pAdapter->MCAddressCount);
+
+ /* Loop through our multicast array and set up the device */
+ for (nIndex = 0; nIndex < pAdapter->MCAddressCount; nIndex++) {
+ DBG_VERBOSE(et131x_dbginfo,
+ "MCList[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ nIndex,
+ pAdapter->MCList[nIndex][0],
+ pAdapter->MCList[nIndex][1],
+ pAdapter->MCList[nIndex][2],
+ pAdapter->MCList[nIndex][3],
+ pAdapter->MCList[nIndex][4],
+ pAdapter->MCList[nIndex][5]);
+
+ result = ether_crc(6, pAdapter->MCList[nIndex]);
+
+ result = (result & 0x3F800000) >> 23;
+
+ if (result < 32) {
+ hash1 |= (1 << result);
+ } else if ((31 < result) && (result < 64)) {
+ result -= 32;
+ hash2 |= (1 << result);
+ } else if ((63 < result) && (result < 96)) {
+ result -= 64;
+ hash3 |= (1 << result);
+ } else {
+ result -= 96;
+ hash4 |= (1 << result);
+ }
+ }
+ }
+
+ /* Write out the new hash to the device */
+ pm_csr.value = readl(&pAdapter->CSRAddress->global.pm_csr.value);
+ if (pm_csr.bits.pm_phy_sw_coma == 0) {
+ writel(hash1, &rxmac->multi_hash1);
+ writel(hash2, &rxmac->multi_hash2);
+ writel(hash3, &rxmac->multi_hash3);
+ writel(hash4, &rxmac->multi_hash4);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+void SetupDeviceForUnicast(struct et131x_adapter *pAdapter)
+{
+ struct _RXMAC_t __iomem *rxmac = &pAdapter->CSRAddress->rxmac;
+ RXMAC_UNI_PF_ADDR1_t uni_pf1;
+ RXMAC_UNI_PF_ADDR2_t uni_pf2;
+ RXMAC_UNI_PF_ADDR3_t uni_pf3;
+ PM_CSR_t pm_csr;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Set up unicast packet filter reg 3 to be the first two octets of
+ * the MAC address for both address
+ *
+ * Set up unicast packet filter reg 2 to be the octets 2 - 5 of the
+ * MAC address for second address
+ *
+ * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the
+ * MAC address for first address
+ */
+ uni_pf3.bits.addr1_1 = pAdapter->CurrentAddress[0];
+ uni_pf3.bits.addr1_2 = pAdapter->CurrentAddress[1];
+ uni_pf3.bits.addr2_1 = pAdapter->CurrentAddress[0];
+ uni_pf3.bits.addr2_2 = pAdapter->CurrentAddress[1];
+
+ uni_pf2.bits.addr2_3 = pAdapter->CurrentAddress[2];
+ uni_pf2.bits.addr2_4 = pAdapter->CurrentAddress[3];
+ uni_pf2.bits.addr2_5 = pAdapter->CurrentAddress[4];
+ uni_pf2.bits.addr2_6 = pAdapter->CurrentAddress[5];
+
+ uni_pf1.bits.addr1_3 = pAdapter->CurrentAddress[2];
+ uni_pf1.bits.addr1_4 = pAdapter->CurrentAddress[3];
+ uni_pf1.bits.addr1_5 = pAdapter->CurrentAddress[4];
+ uni_pf1.bits.addr1_6 = pAdapter->CurrentAddress[5];
+
+ pm_csr.value = readl(&pAdapter->CSRAddress->global.pm_csr.value);
+ if (pm_csr.bits.pm_phy_sw_coma == 0) {
+ writel(uni_pf1.value, &rxmac->uni_pf_addr1.value);
+ writel(uni_pf2.value, &rxmac->uni_pf_addr2.value);
+ writel(uni_pf3.value, &rxmac->uni_pf_addr3.value);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
diff --git a/drivers/staging/et131x/et1310_mac.h b/drivers/staging/et131x/et1310_mac.h
new file mode 100644
index 00000000000..bd26cd35178
--- /dev/null
+++ b/drivers/staging/et131x/et1310_mac.h
@@ -0,0 +1,93 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_mac.h - Defines, structs, enums, prototypes, etc. pertaining to the
+ * MAC.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef _ET1310_MAC_H_
+#define _ET1310_MAC_H_
+
+
+#include "et1310_address_map.h"
+
+
+#define COUNTER_WRAP_28_BIT 0x10000000
+#define COUNTER_WRAP_22_BIT 0x400000
+#define COUNTER_WRAP_16_BIT 0x10000
+#define COUNTER_WRAP_12_BIT 0x1000
+
+#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1)
+#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1)
+#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1)
+#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1)
+
+#define UPDATE_COUNTER(HostCnt,DevCnt) \
+ HostCnt = HostCnt + DevCnt;
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+void ConfigMACRegs1(struct et131x_adapter *adapter);
+void ConfigMACRegs2(struct et131x_adapter *adapter);
+void ConfigRxMacRegs(struct et131x_adapter *adapter);
+void ConfigTxMacRegs(struct et131x_adapter *adapter);
+void ConfigMacStatRegs(struct et131x_adapter *adapter);
+void ConfigFlowControl(struct et131x_adapter *adapter);
+void UpdateMacStatHostCounters(struct et131x_adapter *adapter);
+void HandleMacStatInterrupt(struct et131x_adapter *adapter);
+void SetupDeviceForMulticast(struct et131x_adapter *adapter);
+void SetupDeviceForUnicast(struct et131x_adapter *adapter);
+
+#endif /* _ET1310_MAC_H_ */
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
new file mode 100644
index 00000000000..6c4fa54419e
--- /dev/null
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -0,0 +1,1281 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_phy.c - Routines for configuring and accessing the PHY
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_netdev.h"
+#include "et131x_initpci.h"
+
+#include "et1310_address_map.h"
+#include "et1310_jagcore.h"
+#include "et1310_tx.h"
+#include "et1310_rx.h"
+#include "et1310_mac.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/* Prototypes for functions with local scope */
+static int et131x_xcvr_init(struct et131x_adapter *adapter);
+
+/**
+ * PhyMiRead - Read from the PHY through the MII Interface on the MAC
+ * @adapter: pointer to our private adapter structure
+ * @xcvrAddr: the address of the transciever
+ * @xcvrReg: the register to read
+ * @value: pointer to a 16-bit value in which the value will be stored
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int PhyMiRead(struct et131x_adapter *adapter, uint8_t xcvrAddr,
+ uint8_t xcvrReg, uint16_t *value)
+{
+ struct _MAC_t __iomem *mac = &adapter->CSRAddress->mac;
+ int status = 0;
+ uint32_t delay;
+ MII_MGMT_ADDR_t miiAddr;
+ MII_MGMT_CMD_t miiCmd;
+ MII_MGMT_INDICATOR_t miiIndicator;
+
+ /* Save a local copy of the registers we are dealing with so we can
+ * set them back
+ */
+ miiAddr.value = readl(&mac->mii_mgmt_addr.value);
+ miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
+
+ /* Stop the current operation */
+ writel(0, &mac->mii_mgmt_cmd.value);
+
+ /* Set up the register we need to read from on the correct PHY */
+ {
+ MII_MGMT_ADDR_t mii_mgmt_addr = { 0 };
+
+ mii_mgmt_addr.bits.phy_addr = xcvrAddr;
+ mii_mgmt_addr.bits.reg_addr = xcvrReg;
+ writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
+ }
+
+ /* Kick the read cycle off */
+ delay = 0;
+
+ writel(0x1, &mac->mii_mgmt_cmd.value);
+
+ do {
+ udelay(50);
+ delay++;
+ miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
+ } while ((miiIndicator.bits.not_valid || miiIndicator.bits.busy) &&
+ delay < 50);
+
+ /* If we hit the max delay, we could not read the register */
+ if (delay >= 50) {
+ DBG_WARNING(et131x_dbginfo,
+ "xcvrReg 0x%08x could not be read\n", xcvrReg);
+ DBG_WARNING(et131x_dbginfo, "status is 0x%08x\n",
+ miiIndicator.value);
+
+ status = -EIO;
+ }
+
+ /* If we hit here we were able to read the register and we need to
+ * return the value to the caller
+ */
+ /* TODO: make this stuff a simple readw()?! */
+ {
+ MII_MGMT_STAT_t mii_mgmt_stat;
+
+ mii_mgmt_stat.value = readl(&mac->mii_mgmt_stat.value);
+ *value = (uint16_t) mii_mgmt_stat.bits.phy_stat;
+ }
+
+ /* Stop the read operation */
+ writel(0, &mac->mii_mgmt_cmd.value);
+
+ DBG_VERBOSE(et131x_dbginfo, " xcvr_addr = 0x%02x, "
+ "xcvr_reg = 0x%02x, "
+ "value = 0x%04x.\n", xcvrAddr, xcvrReg, *value);
+
+ /* set the registers we touched back to the state at which we entered
+ * this function
+ */
+ writel(miiAddr.value, &mac->mii_mgmt_addr.value);
+ writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
+
+ return status;
+}
+
+/**
+ * MiWrite - Write to a PHY register through the MII interface of the MAC
+ * @adapter: pointer to our private adapter structure
+ * @xcvrReg: the register to read
+ * @value: 16-bit value to write
+ *
+ * Return 0 on success, errno on failure (as defined in errno.h)
+ */
+int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value)
+{
+ struct _MAC_t __iomem *mac = &adapter->CSRAddress->mac;
+ int status = 0;
+ uint8_t xcvrAddr = adapter->Stats.xcvr_addr;
+ uint32_t delay;
+ MII_MGMT_ADDR_t miiAddr;
+ MII_MGMT_CMD_t miiCmd;
+ MII_MGMT_INDICATOR_t miiIndicator;
+
+ /* Save a local copy of the registers we are dealing with so we can
+ * set them back
+ */
+ miiAddr.value = readl(&mac->mii_mgmt_addr.value);
+ miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
+
+ /* Stop the current operation */
+ writel(0, &mac->mii_mgmt_cmd.value);
+
+ /* Set up the register we need to write to on the correct PHY */
+ {
+ MII_MGMT_ADDR_t mii_mgmt_addr;
+
+ mii_mgmt_addr.bits.phy_addr = xcvrAddr;
+ mii_mgmt_addr.bits.reg_addr = xcvrReg;
+ writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
+ }
+
+ /* Add the value to write to the registers to the mac */
+ writel(value, &mac->mii_mgmt_ctrl.value);
+ delay = 0;
+
+ do {
+ udelay(50);
+ delay++;
+ miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
+ } while (miiIndicator.bits.busy && delay < 100);
+
+ /* If we hit the max delay, we could not write the register */
+ if (delay == 100) {
+ uint16_t TempValue;
+
+ DBG_WARNING(et131x_dbginfo,
+ "xcvrReg 0x%08x could not be written", xcvrReg);
+ DBG_WARNING(et131x_dbginfo, "status is 0x%08x\n",
+ miiIndicator.value);
+ DBG_WARNING(et131x_dbginfo, "command is 0x%08x\n",
+ readl(&mac->mii_mgmt_cmd.value));
+
+ MiRead(adapter, xcvrReg, &TempValue);
+
+ status = -EIO;
+ }
+
+ /* Stop the write operation */
+ writel(0, &mac->mii_mgmt_cmd.value);
+
+ /* set the registers we touched back to the state at which we entered
+ * this function
+ */
+ writel(miiAddr.value, &mac->mii_mgmt_addr.value);
+ writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
+
+ DBG_VERBOSE(et131x_dbginfo, " xcvr_addr = 0x%02x, "
+ "xcvr_reg = 0x%02x, "
+ "value = 0x%04x.\n", xcvrAddr, xcvrReg, value);
+
+ return status;
+}
+
+/**
+ * et131x_xcvr_find - Find the PHY ID
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_xcvr_find(struct et131x_adapter *adapter)
+{
+ int status = -ENODEV;
+ uint8_t xcvr_addr;
+ MI_IDR1_t idr1;
+ MI_IDR2_t idr2;
+ uint32_t xcvr_id;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* We need to get xcvr id and address we just get the first one */
+ for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
+ /* Read the ID from the PHY */
+ PhyMiRead(adapter, xcvr_addr,
+ (uint8_t) offsetof(MI_REGS_t, idr1),
+ &idr1.value);
+ PhyMiRead(adapter, xcvr_addr,
+ (uint8_t) offsetof(MI_REGS_t, idr2),
+ &idr2.value);
+
+ xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value);
+
+ if ((idr1.value != 0) && (idr1.value != 0xffff)) {
+ DBG_TRACE(et131x_dbginfo,
+ "Xcvr addr: 0x%02x\tXcvr_id: 0x%08x\n",
+ xcvr_addr, xcvr_id);
+
+ adapter->Stats.xcvr_id = xcvr_id;
+ adapter->Stats.xcvr_addr = xcvr_addr;
+
+ status = 0;
+ break;
+ }
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_setphy_normal - Set PHY for normal operation.
+ * @adapter: pointer to our private adapter structure
+ *
+ * Used by Power Management to force the PHY into 10 Base T half-duplex mode,
+ * when going to D3 in WOL mode. Also used during initialization to set the
+ * PHY for normal operation.
+ */
+int et131x_setphy_normal(struct et131x_adapter *adapter)
+{
+ int status;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Make sure the PHY is powered up */
+ ET1310_PhyPowerDown(adapter, 0);
+ status = et131x_xcvr_init(adapter);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_xcvr_init - Init the phy if we are setting it into force mode
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+static int et131x_xcvr_init(struct et131x_adapter *adapter)
+{
+ int status = 0;
+ MI_IMR_t imr;
+ MI_ISR_t isr;
+ MI_LCR2_t lcr2;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Zero out the adapter structure variable representing BMSR */
+ adapter->Bmsr.value = 0;
+
+ MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value);
+
+ MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value);
+
+ /* Set the link status interrupt only. Bad behavior when link status
+ * and auto neg are set, we run into a nested interrupt problem
+ */
+ imr.bits.int_en = 0x1;
+ imr.bits.link_status = 0x1;
+ imr.bits.autoneg_status = 0x1;
+
+ MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value);
+
+ /* Set the LED behavior such that LED 1 indicates speed (off =
+ * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
+ * link and activity (on for link, blink off for activity).
+ *
+ * NOTE: Some customizations have been added here for specific
+ * vendors; The LED behavior is now determined by vendor data in the
+ * EEPROM. However, the above description is the default.
+ */
+ if ((adapter->eepromData[1] & 0x4) == 0) {
+ MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
+ &lcr2.value);
+ if ((adapter->eepromData[1] & 0x8) == 0)
+ lcr2.bits.led_tx_rx = 0x3;
+ else
+ lcr2.bits.led_tx_rx = 0x4;
+ lcr2.bits.led_link = 0xa;
+ MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
+ lcr2.value);
+ }
+
+ /* Determine if we need to go into a force mode and set it */
+ if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) {
+ if ((adapter->RegistryFlowControl == TxOnly) ||
+ (adapter->RegistryFlowControl == Both)) {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_SET, 4, 11, NULL);
+ } else {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 11, NULL);
+ }
+
+ if (adapter->RegistryFlowControl == Both) {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_SET, 4, 10, NULL);
+ } else {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 10, NULL);
+ }
+
+ /* Set the phy to autonegotiation */
+ ET1310_PhyAutoNeg(adapter, true);
+
+ /* NOTE - Do we need this? */
+ ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+ } else {
+ ET1310_PhyAutoNeg(adapter, false);
+
+ /* Set to the correct force mode. */
+ if (adapter->AiForceDpx != 1) {
+ if ((adapter->RegistryFlowControl == TxOnly) ||
+ (adapter->RegistryFlowControl == Both)) {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_SET, 4, 11,
+ NULL);
+ } else {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 11,
+ NULL);
+ }
+
+ if (adapter->RegistryFlowControl == Both) {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_SET, 4, 10,
+ NULL);
+ } else {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 10,
+ NULL);
+ }
+ } else {
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 10, NULL);
+ ET1310_PhyAccessMiBit(adapter,
+ TRUEPHY_BIT_CLEAR, 4, 11, NULL);
+ }
+
+ switch (adapter->AiForceSpeed) {
+ case 10:
+ if (adapter->AiForceDpx == 1) {
+ TPAL_SetPhy10HalfDuplex(adapter);
+ } else if (adapter->AiForceDpx == 2) {
+ TPAL_SetPhy10FullDuplex(adapter);
+ } else {
+ TPAL_SetPhy10Force(adapter);
+ }
+ break;
+ case 100:
+ if (adapter->AiForceDpx == 1) {
+ TPAL_SetPhy100HalfDuplex(adapter);
+ } else if (adapter->AiForceDpx == 2) {
+ TPAL_SetPhy100FullDuplex(adapter);
+ } else {
+ TPAL_SetPhy100Force(adapter);
+ }
+ break;
+ case 1000:
+ TPAL_SetPhy1000FullDuplex(adapter);
+ break;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+ }
+}
+
+void et131x_Mii_check(struct et131x_adapter *pAdapter,
+ MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
+{
+ uint8_t ucLinkStatus;
+ uint32_t uiAutoNegStatus;
+ uint32_t uiSpeed;
+ uint32_t uiDuplex;
+ uint32_t uiMdiMdix;
+ uint32_t uiMasterSlave;
+ uint32_t uiPolarity;
+ unsigned long lockflags;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ if (bmsr_ints.bits.link_status) {
+ if (bmsr.bits.link_status) {
+ pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20;
+
+ /* Update our state variables and indicate the
+ * connected state
+ */
+ spin_lock_irqsave(&pAdapter->Lock, lockflags);
+
+ pAdapter->MediaState = NETIF_STATUS_MEDIA_CONNECT;
+ MP_CLEAR_FLAG(pAdapter, fMP_ADAPTER_LINK_DETECTION);
+
+ spin_unlock_irqrestore(&pAdapter->Lock, lockflags);
+
+ /* Don't indicate state if we're in loopback mode */
+ if (pAdapter->RegistryPhyLoopbk == false) {
+ netif_carrier_on(pAdapter->netdev);
+ }
+ } else {
+ DBG_WARNING(et131x_dbginfo,
+ "Link down cable problem\n");
+
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS) {
+ // NOTE - Is there a way to query this without TruePHY?
+ // && TRU_QueryCoreType(pAdapter->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
+ uint16_t Register18;
+
+ MiRead(pAdapter, 0x12, &Register18);
+ MiWrite(pAdapter, 0x12, Register18 | 0x4);
+ MiWrite(pAdapter, 0x10, Register18 | 0x8402);
+ MiWrite(pAdapter, 0x11, Register18 | 511);
+ MiWrite(pAdapter, 0x12, Register18);
+ }
+
+ /* For the first N seconds of life, we are in "link
+ * detection" When we are in this state, we should
+ * only report "connected". When the LinkDetection
+ * Timer expires, we can report disconnected (handled
+ * in the LinkDetectionDPC).
+ */
+ if ((MP_IS_FLAG_CLEAR
+ (pAdapter, fMP_ADAPTER_LINK_DETECTION))
+ || (pAdapter->MediaState ==
+ NETIF_STATUS_MEDIA_DISCONNECT)) {
+ spin_lock_irqsave(&pAdapter->Lock, lockflags);
+ pAdapter->MediaState =
+ NETIF_STATUS_MEDIA_DISCONNECT;
+ spin_unlock_irqrestore(&pAdapter->Lock,
+ lockflags);
+
+ /* Only indicate state if we're in loopback
+ * mode
+ */
+ if (pAdapter->RegistryPhyLoopbk == false) {
+ netif_carrier_off(pAdapter->netdev);
+ }
+ }
+
+ pAdapter->uiLinkSpeed = 0;
+ pAdapter->uiDuplexMode = 0;
+
+ /* Free the packets being actively sent & stopped */
+ et131x_free_busy_send_packets(pAdapter);
+
+ /* Re-initialize the send structures */
+ et131x_init_send(pAdapter);
+
+ /* Reset the RFD list and re-start RU */
+ et131x_reset_recv(pAdapter);
+
+ /*
+ * Bring the device back to the state it was during
+ * init prior to autonegotiation being complete. This
+ * way, when we get the auto-neg complete interrupt,
+ * we can complete init by calling ConfigMacREGS2.
+ */
+ et131x_soft_reset(pAdapter);
+
+ /* Setup ET1310 as per the documentation */
+ et131x_adapter_setup(pAdapter);
+
+ /* Setup the PHY into coma mode until the cable is
+ * plugged back in
+ */
+ if (pAdapter->RegistryPhyComa == 1) {
+ EnablePhyComa(pAdapter);
+ }
+ }
+ }
+
+ if (bmsr_ints.bits.auto_neg_complete ||
+ ((pAdapter->AiForceDpx == 3) && (bmsr_ints.bits.link_status))) {
+ if (bmsr.bits.auto_neg_complete || (pAdapter->AiForceDpx == 3)) {
+ ET1310_PhyLinkStatus(pAdapter,
+ &ucLinkStatus, &uiAutoNegStatus,
+ &uiSpeed, &uiDuplex, &uiMdiMdix,
+ &uiMasterSlave, &uiPolarity);
+
+ pAdapter->uiLinkSpeed = uiSpeed;
+ pAdapter->uiDuplexMode = uiDuplex;
+
+ DBG_TRACE(et131x_dbginfo,
+ "pAdapter->uiLinkSpeed 0x%04x, pAdapter->uiDuplex 0x%08x\n",
+ pAdapter->uiLinkSpeed,
+ pAdapter->uiDuplexMode);
+
+ pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20;
+
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS) {
+ // NOTE - Is there a way to query this without TruePHY?
+ // && TRU_QueryCoreType(pAdapter->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
+ uint16_t Register18;
+
+ MiRead(pAdapter, 0x12, &Register18);
+ MiWrite(pAdapter, 0x12, Register18 | 0x4);
+ MiWrite(pAdapter, 0x10, Register18 | 0x8402);
+ MiWrite(pAdapter, 0x11, Register18 | 511);
+ MiWrite(pAdapter, 0x12, Register18);
+ }
+
+ ConfigFlowControl(pAdapter);
+
+ if ((pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) &&
+ (pAdapter->RegistryJumboPacket > 2048))
+ {
+ ET1310_PhyAndOrReg(pAdapter, 0x16, 0xcfff,
+ 0x2000);
+ }
+
+ SetRxDmaTimer(pAdapter);
+ ConfigMACRegs2(pAdapter);
+ }
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode.
+ * @pAdapter: pointer to the adapter structure
+ *
+ * Also sets the MAC so it is syncd up properly
+ */
+void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* First we need to turn off all other advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Set our advertise values accordingly */
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_HALF);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode.
+ * @pAdapter: pointer to the adapter structure
+ *
+ * Also sets the MAC so it is syncd up properly
+ */
+void TPAL_SetPhy10FullDuplex(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* First we need to turn off all other advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Set our advertise values accordingly */
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation
+ * @pAdapter: pointer to the adapter structure
+ */
+void TPAL_SetPhy10Force(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* Disable autoneg */
+ ET1310_PhyAutoNeg(pAdapter, false);
+
+ /* Disable all advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Force 10 Mbps */
+ ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_10MBPS);
+
+ /* Force Full duplex */
+ ET1310_PhyDuplexMode(pAdapter, TRUEPHY_DUPLEX_FULL);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode.
+ * @pAdapter: pointer to the adapter structure
+ *
+ * Also sets the MAC so it is syncd up properly.
+ */
+void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* first we need to turn off all other advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Set our advertise values accordingly */
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_HALF);
+
+ /* Set speed */
+ ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_100MBPS);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode.
+ * @pAdapter: pointer to the adapter structure
+ *
+ * Also sets the MAC so it is syncd up properly
+ */
+void TPAL_SetPhy100FullDuplex(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* First we need to turn off all other advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Set our advertise values accordingly */
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation
+ * @pAdapter: pointer to the adapter structure
+ */
+void TPAL_SetPhy100Force(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* Disable autoneg */
+ ET1310_PhyAutoNeg(pAdapter, false);
+
+ /* Disable all advertisement */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* Force 100 Mbps */
+ ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_100MBPS);
+
+ /* Force Full duplex */
+ ET1310_PhyDuplexMode(pAdapter, TRUEPHY_DUPLEX_FULL);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode
+ * @pAdapter: pointer to the adapter structure
+ *
+ * Also sets the MAC so it is syncd up properly.
+ */
+void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* first we need to turn off all other advertisement */
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+
+ /* set our advertise values accordingly */
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
+
+ /* power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode.
+ * @pAdapter: pointer to the adapter structure
+ */
+void TPAL_SetPhyAutoNeg(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /* Turn on advertisement of all capabilities */
+ ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_BOTH);
+
+ ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_BOTH);
+
+ if (pAdapter->DeviceID != ET131X_PCI_DEVICE_ID_FAST) {
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
+ } else {
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ }
+
+ /* Make sure auto-neg is ON (it is disabled in FORCE modes) */
+ ET1310_PhyAutoNeg(pAdapter, true);
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+
+/*
+ * The routines which follow provide low-level access to the PHY, and are used
+ * primarily by the routines above (although there are a few places elsewhere
+ * in the driver where this level of access is required).
+ */
+
+static const uint16_t ConfigPhy[25][2] = {
+ /* Reg Value Register */
+ /* Addr */
+ {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */
+ {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */
+ {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */
+
+ {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */
+ {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */
+ {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */
+
+ {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */
+ {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */
+ {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */
+
+ {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */
+ {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */
+ {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */
+
+ {0x300D, 1}, /* DisableNorm */
+
+ {0x280C, 0x0180}, /* LinkHoldEnd */
+
+ {0x1C21, 0x0002}, /* AlphaM */
+
+ {0x3821, 6}, /* FfeLkgTx0 */
+ {0x381D, 1}, /* FfeLkg1g4 */
+ {0x381E, 1}, /* FfeLkg1g5 */
+ {0x381F, 1}, /* FfeLkg1g6 */
+ {0x3820, 1}, /* FfeLkg1g7 */
+
+ {0x8402, 0x01F0}, /* Btinact */
+ {0x800E, 20}, /* LftrainTime */
+ {0x800F, 24}, /* DvguardTime */
+ {0x8010, 46}, /* IdlguardTime */
+
+ {0, 0}
+
+};
+
+/* condensed version of the phy initialization routine */
+void ET1310_PhyInit(struct et131x_adapter *pAdapter)
+{
+ uint16_t usData, usIndex;
+
+ if (pAdapter == NULL) {
+ return;
+ }
+
+ // get the identity (again ?)
+ MiRead(pAdapter, PHY_ID_1, &usData);
+ MiRead(pAdapter, PHY_ID_2, &usData);
+
+ // what does this do/achieve ?
+ MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData); // should read 0002
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0006);
+
+ // read modem register 0402, should I do something with the return data ?
+ MiWrite(pAdapter, PHY_INDEX_REG, 0x0402);
+ MiRead(pAdapter, PHY_DATA_REG, &usData);
+
+ // what does this do/achieve ?
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
+
+ // get the identity (again ?)
+ MiRead(pAdapter, PHY_ID_1, &usData);
+ MiRead(pAdapter, PHY_ID_2, &usData);
+
+ // what does this achieve ?
+ MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData); // should read 0002
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0006);
+
+ // read modem register 0402, should I do something with the return data?
+ MiWrite(pAdapter, PHY_INDEX_REG, 0x0402);
+ MiRead(pAdapter, PHY_DATA_REG, &usData);
+
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
+
+ // what does this achieve (should return 0x1040)
+ MiRead(pAdapter, PHY_CONTROL, &usData);
+ MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData); // should read 0002
+ MiWrite(pAdapter, PHY_CONTROL, 0x1840);
+
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0007);
+
+ // here the writing of the array starts....
+ usIndex = 0;
+ while (ConfigPhy[usIndex][0] != 0x0000) {
+ // write value
+ MiWrite(pAdapter, PHY_INDEX_REG, ConfigPhy[usIndex][0]);
+ MiWrite(pAdapter, PHY_DATA_REG, ConfigPhy[usIndex][1]);
+
+ // read it back
+ MiWrite(pAdapter, PHY_INDEX_REG, ConfigPhy[usIndex][0]);
+ MiRead(pAdapter, PHY_DATA_REG, &usData);
+
+ // do a check on the value read back ?
+ usIndex++;
+ }
+ // here the writing of the array ends...
+
+ MiRead(pAdapter, PHY_CONTROL, &usData); // 0x1840
+ MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData); // should read 0007
+ MiWrite(pAdapter, PHY_CONTROL, 0x1040);
+ MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
+}
+
+void ET1310_PhyReset(struct et131x_adapter *pAdapter)
+{
+ MiWrite(pAdapter, PHY_CONTROL, 0x8000);
+}
+
+void ET1310_PhyPowerDown(struct et131x_adapter *pAdapter, bool down)
+{
+ uint16_t usData;
+
+ MiRead(pAdapter, PHY_CONTROL, &usData);
+
+ if (down == false) {
+ // Power UP
+ usData &= ~0x0800;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ } else {
+ // Power DOWN
+ usData |= 0x0800;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ }
+}
+
+void ET1310_PhyAutoNeg(struct et131x_adapter *pAdapter, bool enable)
+{
+ uint16_t usData;
+
+ MiRead(pAdapter, PHY_CONTROL, &usData);
+
+ if (enable == true) {
+ // Autonegotiation ON
+ usData |= 0x1000;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ } else {
+ // Autonegotiation OFF
+ usData &= ~0x1000;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ }
+}
+
+void ET1310_PhyDuplexMode(struct et131x_adapter *pAdapter, uint16_t duplex)
+{
+ uint16_t usData;
+
+ MiRead(pAdapter, PHY_CONTROL, &usData);
+
+ if (duplex == TRUEPHY_DUPLEX_FULL) {
+ // Set Full Duplex
+ usData |= 0x100;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ } else {
+ // Set Half Duplex
+ usData &= ~0x100;
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+ }
+}
+
+void ET1310_PhySpeedSelect(struct et131x_adapter *pAdapter, uint16_t speed)
+{
+ uint16_t usData;
+
+ // Read the PHY control register
+ MiRead(pAdapter, PHY_CONTROL, &usData);
+
+ // Clear all Speed settings (Bits 6, 13)
+ usData &= ~0x2040;
+
+ // Reset the speed bits based on user selection
+ switch (speed) {
+ case TRUEPHY_SPEED_10MBPS:
+ // Bits already cleared above, do nothing
+ break;
+
+ case TRUEPHY_SPEED_100MBPS:
+ // 100M == Set bit 13
+ usData |= 0x2000;
+ break;
+
+ case TRUEPHY_SPEED_1000MBPS:
+ default:
+ usData |= 0x0040;
+ break;
+ }
+
+ // Write back the new speed
+ MiWrite(pAdapter, PHY_CONTROL, usData);
+}
+
+void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *pAdapter,
+ uint16_t duplex)
+{
+ uint16_t usData;
+
+ // Read the PHY 1000 Base-T Control Register
+ MiRead(pAdapter, PHY_1000_CONTROL, &usData);
+
+ // Clear Bits 8,9
+ usData &= ~0x0300;
+
+ switch (duplex) {
+ case TRUEPHY_ADV_DUPLEX_NONE:
+ // Duplex already cleared, do nothing
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_FULL:
+ // Set Bit 9
+ usData |= 0x0200;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_HALF:
+ // Set Bit 8
+ usData |= 0x0100;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_BOTH:
+ default:
+ usData |= 0x0300;
+ break;
+ }
+
+ // Write back advertisement
+ MiWrite(pAdapter, PHY_1000_CONTROL, usData);
+}
+
+void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *pAdapter,
+ uint16_t duplex)
+{
+ uint16_t usData;
+
+ // Read the Autonegotiation Register (10/100)
+ MiRead(pAdapter, PHY_AUTO_ADVERTISEMENT, &usData);
+
+ // Clear bits 7,8
+ usData &= ~0x0180;
+
+ switch (duplex) {
+ case TRUEPHY_ADV_DUPLEX_NONE:
+ // Duplex already cleared, do nothing
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_FULL:
+ // Set Bit 8
+ usData |= 0x0100;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_HALF:
+ // Set Bit 7
+ usData |= 0x0080;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_BOTH:
+ default:
+ // Set Bits 7,8
+ usData |= 0x0180;
+ break;
+ }
+
+ // Write back advertisement
+ MiWrite(pAdapter, PHY_AUTO_ADVERTISEMENT, usData);
+}
+
+void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *pAdapter,
+ uint16_t duplex)
+{
+ uint16_t usData;
+
+ // Read the Autonegotiation Register (10/100)
+ MiRead(pAdapter, PHY_AUTO_ADVERTISEMENT, &usData);
+
+ // Clear bits 5,6
+ usData &= ~0x0060;
+
+ switch (duplex) {
+ case TRUEPHY_ADV_DUPLEX_NONE:
+ // Duplex already cleared, do nothing
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_FULL:
+ // Set Bit 6
+ usData |= 0x0040;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_HALF:
+ // Set Bit 5
+ usData |= 0x0020;
+ break;
+
+ case TRUEPHY_ADV_DUPLEX_BOTH:
+ default:
+ // Set Bits 5,6
+ usData |= 0x0060;
+ break;
+ }
+
+ // Write back advertisement
+ MiWrite(pAdapter, PHY_AUTO_ADVERTISEMENT, usData);
+}
+
+void ET1310_PhyLinkStatus(struct et131x_adapter *pAdapter,
+ uint8_t *ucLinkStatus,
+ uint32_t *uiAutoNeg,
+ uint32_t *uiLinkSpeed,
+ uint32_t *uiDuplexMode,
+ uint32_t *uiMdiMdix,
+ uint32_t *uiMasterSlave, uint32_t *uiPolarity)
+{
+ uint16_t usMiStatus = 0;
+ uint16_t us1000BaseT = 0;
+ uint16_t usVmiPhyStatus = 0;
+ uint16_t usControl = 0;
+
+ MiRead(pAdapter, PHY_STATUS, &usMiStatus);
+ MiRead(pAdapter, PHY_1000_STATUS, &us1000BaseT);
+ MiRead(pAdapter, PHY_PHY_STATUS, &usVmiPhyStatus);
+ MiRead(pAdapter, PHY_CONTROL, &usControl);
+
+ if (ucLinkStatus) {
+ *ucLinkStatus =
+ (unsigned char)((usVmiPhyStatus & 0x0040) ? 1 : 0);
+ }
+
+ if (uiAutoNeg) {
+ *uiAutoNeg =
+ (usControl & 0x1000) ? ((usVmiPhyStatus & 0x0020) ?
+ TRUEPHY_ANEG_COMPLETE :
+ TRUEPHY_ANEG_NOT_COMPLETE) :
+ TRUEPHY_ANEG_DISABLED;
+ }
+
+ if (uiLinkSpeed) {
+ *uiLinkSpeed = (usVmiPhyStatus & 0x0300) >> 8;
+ }
+
+ if (uiDuplexMode) {
+ *uiDuplexMode = (usVmiPhyStatus & 0x0080) >> 7;
+ }
+
+ if (uiMdiMdix) {
+ /* NOTE: Need to complete this */
+ *uiMdiMdix = 0;
+ }
+
+ if (uiMasterSlave) {
+ *uiMasterSlave =
+ (us1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER :
+ TRUEPHY_CFG_SLAVE;
+ }
+
+ if (uiPolarity) {
+ *uiPolarity =
+ (usVmiPhyStatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED :
+ TRUEPHY_POLARITY_NORMAL;
+ }
+}
+
+void ET1310_PhyAndOrReg(struct et131x_adapter *pAdapter,
+ uint16_t regnum, uint16_t andMask, uint16_t orMask)
+{
+ uint16_t reg;
+
+ // Read the requested register
+ MiRead(pAdapter, regnum, &reg);
+
+ // Apply the AND mask
+ reg &= andMask;
+
+ // Apply the OR mask
+ reg |= orMask;
+
+ // Write the value back to the register
+ MiWrite(pAdapter, regnum, reg);
+}
+
+void ET1310_PhyAccessMiBit(struct et131x_adapter *pAdapter, uint16_t action,
+ uint16_t regnum, uint16_t bitnum, uint8_t *value)
+{
+ uint16_t reg;
+ uint16_t mask = 0;
+
+ // Create a mask to isolate the requested bit
+ mask = 0x0001 << bitnum;
+
+ // Read the requested register
+ MiRead(pAdapter, regnum, &reg);
+
+ switch (action) {
+ case TRUEPHY_BIT_READ:
+ if (value != NULL) {
+ *value = (reg & mask) >> bitnum;
+ }
+ break;
+
+ case TRUEPHY_BIT_SET:
+ reg |= mask;
+ MiWrite(pAdapter, regnum, reg);
+ break;
+
+ case TRUEPHY_BIT_CLEAR:
+ reg &= ~mask;
+ MiWrite(pAdapter, regnum, reg);
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h
new file mode 100644
index 00000000000..d624cbbadbd
--- /dev/null
+++ b/drivers/staging/et131x/et1310_phy.h
@@ -0,0 +1,910 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_phy.h - Defines, structs, enums, prototypes, etc. pertaining to the
+ * PHY.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef _ET1310_PHY_H_
+#define _ET1310_PHY_H_
+
+#include "et1310_address_map.h"
+
+#define TRUEPHY_SUCCESS 0
+#define TRUEPHY_FAILURE 1
+typedef void *TRUEPHY_HANDLE;
+typedef void *TRUEPHY_PLATFORM_HANDLE;
+typedef void *TRUEPHY_OSAL_HANDLE;
+
+/* MI Register Addresses */
+#define MI_CONTROL_REG 0
+#define MI_STATUS_REG 1
+#define MI_PHY_IDENTIFIER_1_REG 2
+#define MI_PHY_IDENTIFIER_2_REG 3
+#define MI_AUTONEG_ADVERTISEMENT_REG 4
+#define MI_AUTONEG_LINK_PARTNER_ABILITY_REG 5
+#define MI_AUTONEG_EXPANSION_REG 6
+#define MI_AUTONEG_NEXT_PAGE_TRANSMIT_REG 7
+#define MI_LINK_PARTNER_NEXT_PAGE_REG 8
+#define MI_1000BASET_CONTROL_REG 9
+#define MI_1000BASET_STATUS_REG 10
+#define MI_RESERVED11_REG 11
+#define MI_RESERVED12_REG 12
+#define MI_RESERVED13_REG 13
+#define MI_RESERVED14_REG 14
+#define MI_EXTENDED_STATUS_REG 15
+
+/* VMI Register Addresses */
+#define VMI_RESERVED16_REG 16
+#define VMI_RESERVED17_REG 17
+#define VMI_RESERVED18_REG 18
+#define VMI_LOOPBACK_CONTROL_REG 19
+#define VMI_RESERVED20_REG 20
+#define VMI_MI_CONTROL_REG 21
+#define VMI_PHY_CONFIGURATION_REG 22
+#define VMI_PHY_CONTROL_REG 23
+#define VMI_INTERRUPT_MASK_REG 24
+#define VMI_INTERRUPT_STATUS_REG 25
+#define VMI_PHY_STATUS_REG 26
+#define VMI_LED_CONTROL_1_REG 27
+#define VMI_LED_CONTROL_2_REG 28
+#define VMI_RESERVED29_REG 29
+#define VMI_RESERVED30_REG 30
+#define VMI_RESERVED31_REG 31
+
+/* PHY Register Mapping(MI) Management Interface Regs */
+typedef struct _MI_REGS_t {
+ u8 bmcr; // Basic mode control reg(Reg 0x00)
+ u8 bmsr; // Basic mode status reg(Reg 0x01)
+ u8 idr1; // Phy identifier reg 1(Reg 0x02)
+ u8 idr2; // Phy identifier reg 2(Reg 0x03)
+ u8 anar; // Auto-Negotiation advertisement(Reg 0x04)
+ u8 anlpar; // Auto-Negotiation link Partner Ability(Reg 0x05)
+ u8 aner; // Auto-Negotiation expansion reg(Reg 0x06)
+ u8 annptr; // Auto-Negotiation next page transmit reg(Reg 0x07)
+ u8 lpnpr; // link partner next page reg(Reg 0x08)
+ u8 gcr; // Gigabit basic mode control reg(Reg 0x09)
+ u8 gsr; // Gigabit basic mode status reg(Reg 0x0A)
+ u8 mi_res1[4]; // Future use by MI working group(Reg 0x0B - 0x0E)
+ u8 esr; // Extended status reg(Reg 0x0F)
+ u8 mi_res2[3]; // Future use by MI working group(Reg 0x10 - 0x12)
+ u8 loop_ctl; // Loopback Control Reg(Reg 0x13)
+ u8 mi_res3; // Future use by MI working group(Reg 0x14)
+ u8 mcr; // MI Control Reg(Reg 0x15)
+ u8 pcr; // Configuration Reg(Reg 0x16)
+ u8 phy_ctl; // PHY Control Reg(Reg 0x17)
+ u8 imr; // Interrupt Mask Reg(Reg 0x18)
+ u8 isr; // Interrupt Status Reg(Reg 0x19)
+ u8 psr; // PHY Status Reg(Reg 0x1A)
+ u8 lcr1; // LED Control 1 Reg(Reg 0x1B)
+ u8 lcr2; // LED Control 2 Reg(Reg 0x1C)
+ u8 mi_res4[3]; // Future use by MI working group(Reg 0x1D - 0x1F)
+} MI_REGS_t, *PMI_REGS_t;
+
+/* MI Register 0: Basic mode control register */
+typedef union _MI_BMCR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 reset:1; // bit 15
+ u16 loopback:1; // bit 14
+ u16 speed_sel:1; // bit 13
+ u16 enable_autoneg:1; // bit 12
+ u16 power_down:1; // bit 11
+ u16 isolate:1; // bit 10
+ u16 restart_autoneg:1; // bit 9
+ u16 duplex_mode:1; // bit 8
+ u16 col_test:1; // bit 7
+ u16 speed_1000_sel:1; // bit 6
+ u16 res1:6; // bits 0-5
+#else
+ u16 res1:6; // bits 0-5
+ u16 speed_1000_sel:1; // bit 6
+ u16 col_test:1; // bit 7
+ u16 duplex_mode:1; // bit 8
+ u16 restart_autoneg:1; // bit 9
+ u16 isolate:1; // bit 10
+ u16 power_down:1; // bit 11
+ u16 enable_autoneg:1; // bit 12
+ u16 speed_sel:1; // bit 13
+ u16 loopback:1; // bit 14
+ u16 reset:1; // bit 15
+#endif
+ } bits;
+} MI_BMCR_t, *PMI_BMCR_t;
+
+/* MI Register 1: Basic mode status register */
+typedef union _MI_BMSR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 link_100T4:1; // bit 15
+ u16 link_100fdx:1; // bit 14
+ u16 link_100hdx:1; // bit 13
+ u16 link_10fdx:1; // bit 12
+ u16 link_10hdx:1; // bit 11
+ u16 link_100T2fdx:1; // bit 10
+ u16 link_100T2hdx:1; // bit 9
+ u16 extend_status:1; // bit 8
+ u16 res1:1; // bit 7
+ u16 preamble_supress:1; // bit 6
+ u16 auto_neg_complete:1; // bit 5
+ u16 remote_fault:1; // bit 4
+ u16 auto_neg_able:1; // bit 3
+ u16 link_status:1; // bit 2
+ u16 jabber_detect:1; // bit 1
+ u16 ext_cap:1; // bit 0
+#else
+ u16 ext_cap:1; // bit 0
+ u16 jabber_detect:1; // bit 1
+ u16 link_status:1; // bit 2
+ u16 auto_neg_able:1; // bit 3
+ u16 remote_fault:1; // bit 4
+ u16 auto_neg_complete:1; // bit 5
+ u16 preamble_supress:1; // bit 6
+ u16 res1:1; // bit 7
+ u16 extend_status:1; // bit 8
+ u16 link_100T2hdx:1; // bit 9
+ u16 link_100T2fdx:1; // bit 10
+ u16 link_10hdx:1; // bit 11
+ u16 link_10fdx:1; // bit 12
+ u16 link_100hdx:1; // bit 13
+ u16 link_100fdx:1; // bit 14
+ u16 link_100T4:1; // bit 15
+#endif
+ } bits;
+} MI_BMSR_t, *PMI_BMSR_t;
+
+/* MI Register 2: Physical Identifier 1 */
+typedef union _MI_IDR1_t {
+ u16 value;
+ struct {
+ u16 ieee_address:16; // 0x0282 default(bits 0-15)
+ } bits;
+} MI_IDR1_t, *PMI_IDR1_t;
+
+/* MI Register 3: Physical Identifier 2 */
+typedef union _MI_IDR2_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 ieee_address:6; // 111100 default(bits 10-15)
+ u16 model_no:6; // 000001 default(bits 4-9)
+ u16 rev_no:4; // 0010 default(bits 0-3)
+#else
+ u16 rev_no:4; // 0010 default(bits 0-3)
+ u16 model_no:6; // 000001 default(bits 4-9)
+ u16 ieee_address:6; // 111100 default(bits 10-15)
+#endif
+ } bits;
+} MI_IDR2_t, *PMI_IDR2_t;
+
+/* MI Register 4: Auto-negotiation advertisement register */
+typedef union _MI_ANAR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 np_indication:1; // bit 15
+ u16 res2:1; // bit 14
+ u16 remote_fault:1; // bit 13
+ u16 res1:1; // bit 12
+ u16 cap_asmpause:1; // bit 11
+ u16 cap_pause:1; // bit 10
+ u16 cap_100T4:1; // bit 9
+ u16 cap_100fdx:1; // bit 8
+ u16 cap_100hdx:1; // bit 7
+ u16 cap_10fdx:1; // bit 6
+ u16 cap_10hdx:1; // bit 5
+ u16 selector:5; // bits 0-4
+#else
+ u16 selector:5; // bits 0-4
+ u16 cap_10hdx:1; // bit 5
+ u16 cap_10fdx:1; // bit 6
+ u16 cap_100hdx:1; // bit 7
+ u16 cap_100fdx:1; // bit 8
+ u16 cap_100T4:1; // bit 9
+ u16 cap_pause:1; // bit 10
+ u16 cap_asmpause:1; // bit 11
+ u16 res1:1; // bit 12
+ u16 remote_fault:1; // bit 13
+ u16 res2:1; // bit 14
+ u16 np_indication:1; // bit 15
+#endif
+ } bits;
+} MI_ANAR_t, *PMI_ANAR_t;
+
+/* MI Register 5: Auto-negotiation link partner advertisement register */
+typedef struct _MI_ANLPAR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 np_indication:1; // bit 15
+ u16 acknowledge:1; // bit 14
+ u16 remote_fault:1; // bit 13
+ u16 res1:1; // bit 12
+ u16 cap_asmpause:1; // bit 11
+ u16 cap_pause:1; // bit 10
+ u16 cap_100T4:1; // bit 9
+ u16 cap_100fdx:1; // bit 8
+ u16 cap_100hdx:1; // bit 7
+ u16 cap_10fdx:1; // bit 6
+ u16 cap_10hdx:1; // bit 5
+ u16 selector:5; // bits 0-4
+#else
+ u16 selector:5; // bits 0-4
+ u16 cap_10hdx:1; // bit 5
+ u16 cap_10fdx:1; // bit 6
+ u16 cap_100hdx:1; // bit 7
+ u16 cap_100fdx:1; // bit 8
+ u16 cap_100T4:1; // bit 9
+ u16 cap_pause:1; // bit 10
+ u16 cap_asmpause:1; // bit 11
+ u16 res1:1; // bit 12
+ u16 remote_fault:1; // bit 13
+ u16 acknowledge:1; // bit 14
+ u16 np_indication:1; // bit 15
+#endif
+ } bits;
+} MI_ANLPAR_t, *PMI_ANLPAR_t;
+
+/* MI Register 6: Auto-negotiation expansion register */
+typedef union _MI_ANER_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res:11; // bits 5-15
+ u16 pdf:1; // bit 4
+ u16 lp_np_able:1; // bit 3
+ u16 np_able:1; // bit 2
+ u16 page_rx:1; // bit 1
+ u16 lp_an_able:1; // bit 0
+#else
+ u16 lp_an_able:1; // bit 0
+ u16 page_rx:1; // bit 1
+ u16 np_able:1; // bit 2
+ u16 lp_np_able:1; // bit 3
+ u16 pdf:1; // bit 4
+ u16 res:11; // bits 5-15
+#endif
+ } bits;
+} MI_ANER_t, *PMI_ANER_t;
+
+/* MI Register 7: Auto-negotiation next page transmit reg(0x07) */
+typedef union _MI_ANNPTR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 np:1; // bit 15
+ u16 res1:1; // bit 14
+ u16 msg_page:1; // bit 13
+ u16 ack2:1; // bit 12
+ u16 toggle:1; // bit 11
+ u16 msg:11; // bits 0-10
+#else
+ u16 msg:11; // bits 0-10
+ u16 toggle:1; // bit 11
+ u16 ack2:1; // bit 12
+ u16 msg_page:1; // bit 13
+ u16 res1:1; // bit 14
+ u16 np:1; // bit 15
+#endif
+ } bits;
+} MI_ANNPTR_t, *PMI_ANNPTR_t;
+
+/* MI Register 8: Link Partner Next Page Reg(0x08) */
+typedef union _MI_LPNPR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 np:1; // bit 15
+ u16 ack:1; // bit 14
+ u16 msg_page:1; // bit 13
+ u16 ack2:1; // bit 12
+ u16 toggle:1; // bit 11
+ u16 msg:11; // bits 0-10
+#else
+ u16 msg:11; // bits 0-10
+ u16 toggle:1; // bit 11
+ u16 ack2:1; // bit 12
+ u16 msg_page:1; // bit 13
+ u16 ack:1; // bit 14
+ u16 np:1; // bit 15
+#endif
+ } bits;
+} MI_LPNPR_t, *PMI_LPNPR_t;
+
+/* MI Register 9: 1000BaseT Control Reg(0x09) */
+typedef union _MI_GCR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 test_mode:3; // bits 13-15
+ u16 ms_config_en:1; // bit 12
+ u16 ms_value:1; // bit 11
+ u16 port_type:1; // bit 10
+ u16 link_1000fdx:1; // bit 9
+ u16 link_1000hdx:1; // bit 8
+ u16 res:8; // bit 0-7
+#else
+ u16 res:8; // bit 0-7
+ u16 link_1000hdx:1; // bit 8
+ u16 link_1000fdx:1; // bit 9
+ u16 port_type:1; // bit 10
+ u16 ms_value:1; // bit 11
+ u16 ms_config_en:1; // bit 12
+ u16 test_mode:3; // bits 13-15
+#endif
+ } bits;
+} MI_GCR_t, *PMI_GCR_t;
+
+/* MI Register 10: 1000BaseT Status Reg(0x0A) */
+typedef union _MI_GSR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 ms_config_fault:1; // bit 15
+ u16 ms_resolve:1; // bit 14
+ u16 local_rx_status:1; // bit 13
+ u16 remote_rx_status:1; // bit 12
+ u16 link_1000fdx:1; // bit 11
+ u16 link_1000hdx:1; // bit 10
+ u16 res:2; // bits 8-9
+ u16 idle_err_cnt:8; // bits 0-7
+#else
+ u16 idle_err_cnt:8; // bits 0-7
+ u16 res:2; // bits 8-9
+ u16 link_1000hdx:1; // bit 10
+ u16 link_1000fdx:1; // bit 11
+ u16 remote_rx_status:1; // bit 12
+ u16 local_rx_status:1; // bit 13
+ u16 ms_resolve:1; // bit 14
+ u16 ms_config_fault:1; // bit 15
+#endif
+ } bits;
+} MI_GSR_t, *PMI_GSR_t;
+
+/* MI Register 11 - 14: Reserved Regs(0x0B - 0x0E) */
+typedef union _MI_RES_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res15:1; // bit 15
+ u16 res14:1; // bit 14
+ u16 res13:1; // bit 13
+ u16 res12:1; // bit 12
+ u16 res11:1; // bit 11
+ u16 res10:1; // bit 10
+ u16 res9:1; // bit 9
+ u16 res8:1; // bit 8
+ u16 res7:1; // bit 7
+ u16 res6:1; // bit 6
+ u16 res5:1; // bit 5
+ u16 res4:1; // bit 4
+ u16 res3:1; // bit 3
+ u16 res2:1; // bit 2
+ u16 res1:1; // bit 1
+ u16 res0:1; // bit 0
+#else
+ u16 res0:1; // bit 0
+ u16 res1:1; // bit 1
+ u16 res2:1; // bit 2
+ u16 res3:1; // bit 3
+ u16 res4:1; // bit 4
+ u16 res5:1; // bit 5
+ u16 res6:1; // bit 6
+ u16 res7:1; // bit 7
+ u16 res8:1; // bit 8
+ u16 res9:1; // bit 9
+ u16 res10:1; // bit 10
+ u16 res11:1; // bit 11
+ u16 res12:1; // bit 12
+ u16 res13:1; // bit 13
+ u16 res14:1; // bit 14
+ u16 res15:1; // bit 15
+#endif
+ } bits;
+} MI_RES_t, *PMI_RES_t;
+
+/* MI Register 15: Extended status Reg(0x0F) */
+typedef union _MI_ESR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 link_1000Xfdx:1; // bit 15
+ u16 link_1000Xhdx:1; // bit 14
+ u16 link_1000fdx:1; // bit 13
+ u16 link_1000hdx:1; // bit 12
+ u16 res:12; // bit 0-11
+#else
+ u16 res:12; // bit 0-11
+ u16 link_1000hdx:1; // bit 12
+ u16 link_1000fdx:1; // bit 13
+ u16 link_1000Xhdx:1; // bit 14
+ u16 link_1000Xfdx:1; // bit 15
+#endif
+ } bits;
+} MI_ESR_t, *PMI_ESR_t;
+
+/* MI Register 16 - 18: Reserved Reg(0x10-0x12) */
+
+/* MI Register 19: Loopback Control Reg(0x13) */
+typedef union _MI_LCR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 mii_en:1; // bit 15
+ u16 pcs_en:1; // bit 14
+ u16 pmd_en:1; // bit 13
+ u16 all_digital_en:1; // bit 12
+ u16 replica_en:1; // bit 11
+ u16 line_driver_en:1; // bit 10
+ u16 res:10; // bit 0-9
+#else
+ u16 res:10; // bit 0-9
+ u16 line_driver_en:1; // bit 10
+ u16 replica_en:1; // bit 11
+ u16 all_digital_en:1; // bit 12
+ u16 pmd_en:1; // bit 13
+ u16 pcs_en:1; // bit 14
+ u16 mii_en:1; // bit 15
+#endif
+ } bits;
+} MI_LCR_t, *PMI_LCR_t;
+
+/* MI Register 20: Reserved Reg(0x14) */
+
+/* MI Register 21: Management Interface Control Reg(0x15) */
+typedef union _MI_MICR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:5; // bits 11-15
+ u16 mi_error_count:7; // bits 4-10
+ u16 res2:1; // bit 3
+ u16 ignore_10g_fr:1; // bit 2
+ u16 res3:1; // bit 1
+ u16 preamble_supress_en:1; // bit 0
+#else
+ u16 preamble_supress_en:1; // bit 0
+ u16 res3:1; // bit 1
+ u16 ignore_10g_fr:1; // bit 2
+ u16 res2:1; // bit 3
+ u16 mi_error_count:7; // bits 4-10
+ u16 res1:5; // bits 11-15
+#endif
+ } bits;
+} MI_MICR_t, *PMI_MICR_t;
+
+/* MI Register 22: PHY Configuration Reg(0x16) */
+typedef union _MI_PHY_CONFIG_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 crs_tx_en:1; // bit 15
+ u16 res1:1; // bit 14
+ u16 tx_fifo_depth:2; // bits 12-13
+ u16 speed_downshift:2; // bits 10-11
+ u16 pbi_detect:1; // bit 9
+ u16 tbi_rate:1; // bit 8
+ u16 alternate_np:1; // bit 7
+ u16 group_mdio_en:1; // bit 6
+ u16 tx_clock_en:1; // bit 5
+ u16 sys_clock_en:1; // bit 4
+ u16 res2:1; // bit 3
+ u16 mac_if_mode:3; // bits 0-2
+#else
+ u16 mac_if_mode:3; // bits 0-2
+ u16 res2:1; // bit 3
+ u16 sys_clock_en:1; // bit 4
+ u16 tx_clock_en:1; // bit 5
+ u16 group_mdio_en:1; // bit 6
+ u16 alternate_np:1; // bit 7
+ u16 tbi_rate:1; // bit 8
+ u16 pbi_detect:1; // bit 9
+ u16 speed_downshift:2; // bits 10-11
+ u16 tx_fifo_depth:2; // bits 12-13
+ u16 res1:1; // bit 14
+ u16 crs_tx_en:1; // bit 15
+#endif
+ } bits;
+} MI_PHY_CONFIG_t, *PMI_PHY_CONFIG_t;
+
+/* MI Register 23: PHY CONTROL Reg(0x17) */
+typedef union _MI_PHY_CONTROL_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:1; // bit 15
+ u16 tdr_en:1; // bit 14
+ u16 res2:1; // bit 13
+ u16 downshift_attempts:2; // bits 11-12
+ u16 res3:5; // bit 6-10
+ u16 jabber_10baseT:1; // bit 5
+ u16 sqe_10baseT:1; // bit 4
+ u16 tp_loopback_10baseT:1; // bit 3
+ u16 preamble_gen_en:1; // bit 2
+ u16 res4:1; // bit 1
+ u16 force_int:1; // bit 0
+#else
+ u16 force_int:1; // bit 0
+ u16 res4:1; // bit 1
+ u16 preamble_gen_en:1; // bit 2
+ u16 tp_loopback_10baseT:1; // bit 3
+ u16 sqe_10baseT:1; // bit 4
+ u16 jabber_10baseT:1; // bit 5
+ u16 res3:5; // bit 6-10
+ u16 downshift_attempts:2; // bits 11-12
+ u16 res2:1; // bit 13
+ u16 tdr_en:1; // bit 14
+ u16 res1:1; // bit 15
+#endif
+ } bits;
+} MI_PHY_CONTROL_t, *PMI_PHY_CONTROL_t;
+
+/* MI Register 24: Interrupt Mask Reg(0x18) */
+typedef union _MI_IMR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:6; // bits 10-15
+ u16 mdio_sync_lost:1; // bit 9
+ u16 autoneg_status:1; // bit 8
+ u16 hi_bit_err:1; // bit 7
+ u16 np_rx:1; // bit 6
+ u16 err_counter_full:1; // bit 5
+ u16 fifo_over_underflow:1; // bit 4
+ u16 rx_status:1; // bit 3
+ u16 link_status:1; // bit 2
+ u16 automatic_speed:1; // bit 1
+ u16 int_en:1; // bit 0
+#else
+ u16 int_en:1; // bit 0
+ u16 automatic_speed:1; // bit 1
+ u16 link_status:1; // bit 2
+ u16 rx_status:1; // bit 3
+ u16 fifo_over_underflow:1; // bit 4
+ u16 err_counter_full:1; // bit 5
+ u16 np_rx:1; // bit 6
+ u16 hi_bit_err:1; // bit 7
+ u16 autoneg_status:1; // bit 8
+ u16 mdio_sync_lost:1; // bit 9
+ u16 res1:6; // bits 10-15
+#endif
+ } bits;
+} MI_IMR_t, *PMI_IMR_t;
+
+/* MI Register 25: Interrupt Status Reg(0x19) */
+typedef union _MI_ISR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:6; // bits 10-15
+ u16 mdio_sync_lost:1; // bit 9
+ u16 autoneg_status:1; // bit 8
+ u16 hi_bit_err:1; // bit 7
+ u16 np_rx:1; // bit 6
+ u16 err_counter_full:1; // bit 5
+ u16 fifo_over_underflow:1; // bit 4
+ u16 rx_status:1; // bit 3
+ u16 link_status:1; // bit 2
+ u16 automatic_speed:1; // bit 1
+ u16 int_en:1; // bit 0
+#else
+ u16 int_en:1; // bit 0
+ u16 automatic_speed:1; // bit 1
+ u16 link_status:1; // bit 2
+ u16 rx_status:1; // bit 3
+ u16 fifo_over_underflow:1; // bit 4
+ u16 err_counter_full:1; // bit 5
+ u16 np_rx:1; // bit 6
+ u16 hi_bit_err:1; // bit 7
+ u16 autoneg_status:1; // bit 8
+ u16 mdio_sync_lost:1; // bit 9
+ u16 res1:6; // bits 10-15
+#endif
+ } bits;
+} MI_ISR_t, *PMI_ISR_t;
+
+/* MI Register 26: PHY Status Reg(0x1A) */
+typedef union _MI_PSR_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:1; // bit 15
+ u16 autoneg_fault:2; // bit 13-14
+ u16 autoneg_status:1; // bit 12
+ u16 mdi_x_status:1; // bit 11
+ u16 polarity_status:1; // bit 10
+ u16 speed_status:2; // bits 8-9
+ u16 duplex_status:1; // bit 7
+ u16 link_status:1; // bit 6
+ u16 tx_status:1; // bit 5
+ u16 rx_status:1; // bit 4
+ u16 collision_status:1; // bit 3
+ u16 autoneg_en:1; // bit 2
+ u16 pause_en:1; // bit 1
+ u16 asymmetric_dir:1; // bit 0
+#else
+ u16 asymmetric_dir:1; // bit 0
+ u16 pause_en:1; // bit 1
+ u16 autoneg_en:1; // bit 2
+ u16 collision_status:1; // bit 3
+ u16 rx_status:1; // bit 4
+ u16 tx_status:1; // bit 5
+ u16 link_status:1; // bit 6
+ u16 duplex_status:1; // bit 7
+ u16 speed_status:2; // bits 8-9
+ u16 polarity_status:1; // bit 10
+ u16 mdi_x_status:1; // bit 11
+ u16 autoneg_status:1; // bit 12
+ u16 autoneg_fault:2; // bit 13-14
+ u16 res1:1; // bit 15
+#endif
+ } bits;
+} MI_PSR_t, *PMI_PSR_t;
+
+/* MI Register 27: LED Control Reg 1(0x1B) */
+typedef union _MI_LCR1_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 res1:2; // bits 14-15
+ u16 led_dup_indicate:2; // bits 12-13
+ u16 led_10baseT:2; // bits 10-11
+ u16 led_collision:2; // bits 8-9
+ u16 res2:2; // bits 6-7
+ u16 res3:2; // bits 4-5
+ u16 pulse_dur:2; // bits 2-3
+ u16 pulse_stretch1:1; // bit 1
+ u16 pulse_stretch0:1; // bit 0
+#else
+ u16 pulse_stretch0:1; // bit 0
+ u16 pulse_stretch1:1; // bit 1
+ u16 pulse_dur:2; // bits 2-3
+ u16 res3:2; // bits 4-5
+ u16 res2:2; // bits 6-7
+ u16 led_collision:2; // bits 8-9
+ u16 led_10baseT:2; // bits 10-11
+ u16 led_dup_indicate:2; // bits 12-13
+ u16 res1:2; // bits 14-15
+#endif
+ } bits;
+} MI_LCR1_t, *PMI_LCR1_t;
+
+/* MI Register 28: LED Control Reg 2(0x1C) */
+typedef union _MI_LCR2_t {
+ u16 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u16 led_link:4; // bits 12-15
+ u16 led_tx_rx:4; // bits 8-11
+ u16 led_100BaseTX:4; // bits 4-7
+ u16 led_1000BaseT:4; // bits 0-3
+#else
+ u16 led_1000BaseT:4; // bits 0-3
+ u16 led_100BaseTX:4; // bits 4-7
+ u16 led_tx_rx:4; // bits 8-11
+ u16 led_link:4; // bits 12-15
+#endif
+ } bits;
+} MI_LCR2_t, *PMI_LCR2_t;
+
+/* MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) */
+
+/* TruePHY headers */
+typedef struct _TRUEPHY_ACCESS_MI_REGS_ {
+ TRUEPHY_HANDLE hTruePhy;
+ int32_t nPhyId;
+ u8 bReadWrite;
+ u8 *pbyRegs;
+ u8 *pwData;
+ int32_t nRegCount;
+} TRUEPHY_ACCESS_MI_REGS, *PTRUEPHY_ACCESS_MI_REGS;
+
+/* TruePHY headers */
+typedef struct _TAG_TPAL_ACCESS_MI_REGS_ {
+ u32 nPhyId;
+ u8 bReadWrite;
+ u32 nRegCount;
+ u16 Data[4096];
+ u8 Regs[4096];
+} TPAL_ACCESS_MI_REGS, *PTPAL_ACCESS_MI_REGS;
+
+
+typedef TRUEPHY_HANDLE TPAL_HANDLE;
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+/* OS Specific Functions*/
+void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *adapter);
+void TPAL_SetPhy10FullDuplex(struct et131x_adapter *adapter);
+void TPAL_SetPhy10Force(struct et131x_adapter *pAdapter);
+void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *adapter);
+void TPAL_SetPhy100FullDuplex(struct et131x_adapter *adapter);
+void TPAL_SetPhy100Force(struct et131x_adapter *pAdapter);
+void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *adapter);
+void TPAL_SetPhyAutoNeg(struct et131x_adapter *adapter);
+
+/* Prototypes for ET1310_phy.c */
+int et131x_xcvr_find(struct et131x_adapter *adapter);
+int et131x_setphy_normal(struct et131x_adapter *adapter);
+int32_t PhyMiRead(struct et131x_adapter *adapter,
+ u8 xcvrAddr, u8 xcvrReg, u16 *value);
+
+/* static inline function does not work because et131x_adapter is not always
+ * defined
+ */
+#define MiRead(adapter, xcvrReg, value) \
+ PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
+
+int32_t MiWrite(struct et131x_adapter *adapter,
+ u8 xcvReg, u16 value);
+void et131x_Mii_check(struct et131x_adapter *pAdapter,
+ MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
+
+/* This last is not strictly required (the driver could call the TPAL
+ * version instead), but this sets the adapter up correctly, and calls the
+ * access routine indirectly. This protects the driver from changes in TPAL.
+ */
+void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
+
+/* Defines for PHY access routines */
+
+// Define bit operation flags
+#define TRUEPHY_BIT_CLEAR 0
+#define TRUEPHY_BIT_SET 1
+#define TRUEPHY_BIT_READ 2
+
+// Define read/write operation flags
+#ifndef TRUEPHY_READ
+#define TRUEPHY_READ 0
+#define TRUEPHY_WRITE 1
+#define TRUEPHY_MASK 2
+#endif
+
+// Define speeds
+#define TRUEPHY_SPEED_10MBPS 0
+#define TRUEPHY_SPEED_100MBPS 1
+#define TRUEPHY_SPEED_1000MBPS 2
+
+// Define duplex modes
+#define TRUEPHY_DUPLEX_HALF 0
+#define TRUEPHY_DUPLEX_FULL 1
+
+// Define master/slave configuration values
+#define TRUEPHY_CFG_SLAVE 0
+#define TRUEPHY_CFG_MASTER 1
+
+// Define MDI/MDI-X settings
+#define TRUEPHY_MDI 0
+#define TRUEPHY_MDIX 1
+#define TRUEPHY_AUTO_MDI_MDIX 2
+
+// Define 10Base-T link polarities
+#define TRUEPHY_POLARITY_NORMAL 0
+#define TRUEPHY_POLARITY_INVERTED 1
+
+// Define auto-negotiation results
+#define TRUEPHY_ANEG_NOT_COMPLETE 0
+#define TRUEPHY_ANEG_COMPLETE 1
+#define TRUEPHY_ANEG_DISABLED 2
+
+/* Define duplex advertisment flags */
+#define TRUEPHY_ADV_DUPLEX_NONE 0x00
+#define TRUEPHY_ADV_DUPLEX_FULL 0x01
+#define TRUEPHY_ADV_DUPLEX_HALF 0x02
+#define TRUEPHY_ADV_DUPLEX_BOTH \
+ (TRUEPHY_ADV_DUPLEX_FULL | TRUEPHY_ADV_DUPLEX_HALF)
+
+#define PHY_CONTROL 0x00 //#define TRU_MI_CONTROL_REGISTER 0
+#define PHY_STATUS 0x01 //#define TRU_MI_STATUS_REGISTER 1
+#define PHY_ID_1 0x02 //#define TRU_MI_PHY_IDENTIFIER_1_REGISTER 2
+#define PHY_ID_2 0x03 //#define TRU_MI_PHY_IDENTIFIER_2_REGISTER 3
+#define PHY_AUTO_ADVERTISEMENT 0x04 //#define TRU_MI_ADVERTISEMENT_REGISTER 4
+#define PHY_AUTO_LINK_PARTNER 0x05 //#define TRU_MI_LINK_PARTNER_ABILITY_REGISTER 5
+#define PHY_AUTO_EXPANSION 0x06 //#define TRU_MI_EXPANSION_REGISTER 6
+#define PHY_AUTO_NEXT_PAGE_TX 0x07 //#define TRU_MI_NEXT_PAGE_TRANSMIT_REGISTER 7
+#define PHY_LINK_PARTNER_NEXT_PAGE 0x08 //#define TRU_MI_LINK_PARTNER_NEXT_PAGE_REGISTER 8
+#define PHY_1000_CONTROL 0x09 //#define TRU_MI_1000BASET_CONTROL_REGISTER 9
+#define PHY_1000_STATUS 0x0A //#define TRU_MI_1000BASET_STATUS_REGISTER 10
+
+#define PHY_EXTENDED_STATUS 0x0F //#define TRU_MI_EXTENDED_STATUS_REGISTER 15
+
+// some defines for modem registers that seem to be 'reserved'
+#define PHY_INDEX_REG 0x10
+#define PHY_DATA_REG 0x11
+
+#define PHY_MPHY_CONTROL_REG 0x12 //#define TRU_VMI_MPHY_CONTROL_REGISTER 18
+
+#define PHY_LOOPBACK_CONTROL 0x13 //#define TRU_VMI_LOOPBACK_CONTROL_1_REGISTER 19
+ //#define TRU_VMI_LOOPBACK_CONTROL_2_REGISTER 20
+#define PHY_REGISTER_MGMT_CONTROL 0x15 //#define TRU_VMI_MI_SEQ_CONTROL_REGISTER 21
+#define PHY_CONFIG 0x16 //#define TRU_VMI_CONFIGURATION_REGISTER 22
+#define PHY_PHY_CONTROL 0x17 //#define TRU_VMI_PHY_CONTROL_REGISTER 23
+#define PHY_INTERRUPT_MASK 0x18 //#define TRU_VMI_INTERRUPT_MASK_REGISTER 24
+#define PHY_INTERRUPT_STATUS 0x19 //#define TRU_VMI_INTERRUPT_STATUS_REGISTER 25
+#define PHY_PHY_STATUS 0x1A //#define TRU_VMI_PHY_STATUS_REGISTER 26
+#define PHY_LED_1 0x1B //#define TRU_VMI_LED_CONTROL_1_REGISTER 27
+#define PHY_LED_2 0x1C //#define TRU_VMI_LED_CONTROL_2_REGISTER 28
+ //#define TRU_VMI_LINK_CONTROL_REGISTER 29
+ //#define TRU_VMI_TIMING_CONTROL_REGISTER
+
+/* Prototypes for PHY access routines */
+void ET1310_PhyInit(struct et131x_adapter *adapter);
+void ET1310_PhyReset(struct et131x_adapter *adapter);
+void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down);
+void ET1310_PhyAutoNeg(struct et131x_adapter *adapter, bool enable);
+void ET1310_PhyDuplexMode(struct et131x_adapter *adapter, u16 duplex);
+void ET1310_PhySpeedSelect(struct et131x_adapter *adapter, u16 speed);
+void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter,
+ u16 duplex);
+void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *adapter,
+ u16 duplex);
+void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *adapter,
+ u16 duplex);
+void ET1310_PhyLinkStatus(struct et131x_adapter *adapter,
+ u8 *ucLinkStatus,
+ u32 *uiAutoNeg,
+ u32 *uiLinkSpeed,
+ u32 *uiDuplexMode,
+ u32 *uiMdiMdix,
+ u32 *uiMasterSlave, u32 *uiPolarity);
+void ET1310_PhyAndOrReg(struct et131x_adapter *adapter,
+ u16 regnum, u16 andMask, u16 orMask);
+void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter,
+ u16 action,
+ u16 regnum, u16 bitnum, u8 *value);
+
+#endif /* _ET1310_PHY_H_ */
diff --git a/drivers/staging/et131x/et1310_pm.c b/drivers/staging/et131x/et1310_pm.c
new file mode 100644
index 00000000000..9539bc628ca
--- /dev/null
+++ b/drivers/staging/et131x/et1310_pm.c
@@ -0,0 +1,207 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_pm.c - All power management related code (not completely implemented)
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+#include "et1310_mac.h"
+#include "et1310_rx.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/**
+ * EnablePhyComa - called when network cable is unplugged
+ * @pAdapter: pointer to our adapter structure
+ *
+ * driver receive an phy status change interrupt while in D0 and check that
+ * phy_status is down.
+ *
+ * -- gate off JAGCore;
+ * -- set gigE PHY in Coma mode
+ * -- wake on phy_interrupt; Perform software reset JAGCore,
+ * re-initialize jagcore and gigE PHY
+ *
+ * Add D0-ASPM-PhyLinkDown Support:
+ * -- while in D0, when there is a phy_interrupt indicating phy link
+ * down status, call the MPSetPhyComa routine to enter this active
+ * state power saving mode
+ * -- while in D0-ASPM-PhyLinkDown mode, when there is a phy_interrupt
+ * indicating linkup status, call the MPDisablePhyComa routine to
+ * restore JAGCore and gigE PHY
+ */
+void EnablePhyComa(struct et131x_adapter *pAdapter)
+{
+ unsigned long lockflags;
+ PM_CSR_t GlobalPmCSR;
+ int32_t LoopCounter = 10;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ GlobalPmCSR.value = readl(&pAdapter->CSRAddress->global.pm_csr.value);
+
+ /* Save the GbE PHY speed and duplex modes. Need to restore this
+ * when cable is plugged back in
+ */
+ pAdapter->PoMgmt.PowerDownSpeed = pAdapter->AiForceSpeed;
+ pAdapter->PoMgmt.PowerDownDuplex = pAdapter->AiForceDpx;
+
+ /* Stop sending packets. */
+ spin_lock_irqsave(&pAdapter->SendHWLock, lockflags);
+ MP_SET_FLAG(pAdapter, fMP_ADAPTER_LOWER_POWER);
+ spin_unlock_irqrestore(&pAdapter->SendHWLock, lockflags);
+
+ /* Wait for outstanding Receive packets */
+ while ((MP_GET_RCV_REF(pAdapter) != 0) && (LoopCounter-- > 0)) {
+ mdelay(2);
+ }
+
+ /* Gate off JAGCore 3 clock domains */
+ GlobalPmCSR.bits.pm_sysclk_gate = 0;
+ GlobalPmCSR.bits.pm_txclk_gate = 0;
+ GlobalPmCSR.bits.pm_rxclk_gate = 0;
+ writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value);
+
+ /* Program gigE PHY in to Coma mode */
+ GlobalPmCSR.bits.pm_phy_sw_coma = 1;
+ writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * DisablePhyComa - Disable the Phy Coma Mode
+ * @pAdapter: pointer to our adapter structure
+ */
+void DisablePhyComa(struct et131x_adapter *pAdapter)
+{
+ PM_CSR_t GlobalPmCSR;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ GlobalPmCSR.value = readl(&pAdapter->CSRAddress->global.pm_csr.value);
+
+ /* Disable phy_sw_coma register and re-enable JAGCore clocks */
+ GlobalPmCSR.bits.pm_sysclk_gate = 1;
+ GlobalPmCSR.bits.pm_txclk_gate = 1;
+ GlobalPmCSR.bits.pm_rxclk_gate = 1;
+ GlobalPmCSR.bits.pm_phy_sw_coma = 0;
+ writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value);
+
+ /* Restore the GbE PHY speed and duplex modes;
+ * Reset JAGCore; re-configure and initialize JAGCore and gigE PHY
+ */
+ pAdapter->AiForceSpeed = pAdapter->PoMgmt.PowerDownSpeed;
+ pAdapter->AiForceDpx = pAdapter->PoMgmt.PowerDownDuplex;
+
+ /* Re-initialize the send structures */
+ et131x_init_send(pAdapter);
+
+ /* Reset the RFD list and re-start RU */
+ et131x_reset_recv(pAdapter);
+
+ /* Bring the device back to the state it was during init prior to
+ * autonegotiation being complete. This way, when we get the auto-neg
+ * complete interrupt, we can complete init by calling ConfigMacREGS2.
+ */
+ et131x_soft_reset(pAdapter);
+
+ /* setup et1310 as per the documentation ?? */
+ et131x_adapter_setup(pAdapter);
+
+ /* Allow Tx to restart */
+ MP_CLEAR_FLAG(pAdapter, fMP_ADAPTER_LOWER_POWER);
+
+ /* Need to re-enable Rx. */
+ et131x_rx_dma_enable(pAdapter);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
diff --git a/drivers/staging/et131x/et1310_pm.h b/drivers/staging/et131x/et1310_pm.h
new file mode 100644
index 00000000000..6802338e29d
--- /dev/null
+++ b/drivers/staging/et131x/et1310_pm.h
@@ -0,0 +1,125 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_pm.h - Defines, structs, enums, prototypes, etc. pertaining to power
+ * management.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef _ET1310_PM_H_
+#define _ET1310_PM_H_
+
+#include "et1310_address_map.h"
+
+#define MAX_WOL_PACKET_SIZE 0x80
+#define MAX_WOL_MASK_SIZE ( MAX_WOL_PACKET_SIZE / 8 )
+#define NUM_WOL_PATTERNS 0x5
+#define CRC16_POLY 0x1021
+
+/* Definition of NDIS_DEVICE_POWER_STATE */
+typedef enum {
+ NdisDeviceStateUnspecified = 0,
+ NdisDeviceStateD0,
+ NdisDeviceStateD1,
+ NdisDeviceStateD2,
+ NdisDeviceStateD3
+} NDIS_DEVICE_POWER_STATE;
+
+typedef struct _MP_POWER_MGMT {
+ /* variable putting the phy into coma mode when boot up with no cable
+ * plugged in after 5 seconds
+ */
+ u8 TransPhyComaModeOnBoot;
+
+ /* Array holding the five CRC values that the device is currently
+ * using for WOL. This will be queried when a pattern is to be
+ * removed.
+ */
+ u32 localWolAndCrc0;
+ u16 WOLPatternList[NUM_WOL_PATTERNS];
+ u8 WOLMaskList[NUM_WOL_PATTERNS][MAX_WOL_MASK_SIZE];
+ u32 WOLMaskSize[NUM_WOL_PATTERNS];
+
+ /* IP address */
+ union {
+ u32 u32;
+ u8 u8[4];
+ } IPAddress;
+
+ /* Current Power state of the adapter. */
+ NDIS_DEVICE_POWER_STATE PowerState;
+ bool WOLState;
+ bool WOLEnabled;
+ bool Failed10Half;
+ bool bFailedStateTransition;
+
+ /* Next two used to save power information at power down. This
+ * information will be used during power up to set up parts of Power
+ * Management in JAGCore
+ */
+ u32 tx_en;
+ u32 rx_en;
+ u16 PowerDownSpeed;
+ u8 PowerDownDuplex;
+} MP_POWER_MGMT, *PMP_POWER_MGMT;
+
+/* Forward declaration of the private adapter structure
+ * ( IS THERE A WAY TO DO THIS WITH A TYPEDEF??? )
+ */
+struct et131x_adapter;
+
+u16 CalculateCCITCRC16(u8 *Pattern, u8 *Mask, u32 MaskSize);
+void EnablePhyComa(struct et131x_adapter *adapter);
+void DisablePhyComa(struct et131x_adapter *adapter);
+
+#endif /* _ET1310_PM_H_ */
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
new file mode 100644
index 00000000000..ec98da5da5b
--- /dev/null
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -0,0 +1,1391 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_rx.c - Routines used to perform data reception
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+
+#include "et1310_rx.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+
+void nic_return_rfd(struct et131x_adapter *pAdapter, PMP_RFD pMpRfd);
+
+/**
+ * et131x_rx_dma_memory_alloc
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success and errno on failure (as defined in errno.h)
+ *
+ * Allocates Free buffer ring 1 for sure, free buffer ring 0 if required,
+ * and the Packet Status Ring.
+ */
+int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
+{
+ uint32_t OuterLoop, InnerLoop;
+ uint32_t bufsize;
+ uint32_t pktStatRingSize, FBRChunkSize;
+ RX_RING_t *rx_ring;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup some convenience pointers */
+ rx_ring = (RX_RING_t *) & adapter->RxRing;
+
+ /* Alloc memory for the lookup table */
+#ifdef USE_FBR0
+ rx_ring->Fbr[0] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+#endif
+
+ rx_ring->Fbr[1] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+
+ /* The first thing we will do is configure the sizes of the buffer
+ * rings. These will change based on jumbo packet support. Larger
+ * jumbo packets increases the size of each entry in FBR0, and the
+ * number of entries in FBR0, while at the same time decreasing the
+ * number of entries in FBR1.
+ *
+ * FBR1 holds "large" frames, FBR0 holds "small" frames. If FBR1
+ * entries are huge in order to accomodate a "jumbo" frame, then it
+ * will have less entries. Conversely, FBR1 will now be relied upon
+ * to carry more "normal" frames, thus it's entry size also increases
+ * and the number of entries goes up too (since it now carries
+ * "small" + "regular" packets.
+ *
+ * In this scheme, we try to maintain 512 entries between the two
+ * rings. Also, FBR1 remains a constant size - when it's size doubles
+ * the number of entries halves. FBR0 increases in size, however.
+ */
+
+ if (adapter->RegistryJumboPacket < 2048) {
+#ifdef USE_FBR0
+ rx_ring->Fbr0BufferSize = 256;
+ rx_ring->Fbr0NumEntries = 512;
+#endif
+ rx_ring->Fbr1BufferSize = 2048;
+ rx_ring->Fbr1NumEntries = 512;
+ } else if (adapter->RegistryJumboPacket < 4096) {
+#ifdef USE_FBR0
+ rx_ring->Fbr0BufferSize = 512;
+ rx_ring->Fbr0NumEntries = 1024;
+#endif
+ rx_ring->Fbr1BufferSize = 4096;
+ rx_ring->Fbr1NumEntries = 512;
+ } else {
+#ifdef USE_FBR0
+ rx_ring->Fbr0BufferSize = 1024;
+ rx_ring->Fbr0NumEntries = 768;
+#endif
+ rx_ring->Fbr1BufferSize = 16384;
+ rx_ring->Fbr1NumEntries = 128;
+ }
+
+#ifdef USE_FBR0
+ adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr0NumEntries +
+ adapter->RxRing.Fbr1NumEntries;
+#else
+ adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr1NumEntries;
+#endif
+
+ /* Allocate an area of memory for Free Buffer Ring 1 */
+ bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+ rx_ring->pFbr1RingVa = pci_alloc_consistent(adapter->pdev,
+ bufsize,
+ &rx_ring->pFbr1RingPa);
+ if (!rx_ring->pFbr1RingVa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Free Buffer Ring 1\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Save physical address
+ *
+ * NOTE: pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here
+ * before storing the adjusted address.
+ */
+ rx_ring->Fbr1Realpa = rx_ring->pFbr1RingPa;
+
+ /* Align Free Buffer Ring 1 on a 4K boundary */
+ et131x_align_allocated_memory(adapter,
+ &rx_ring->Fbr1Realpa,
+ &rx_ring->Fbr1offset, 0x0FFF);
+
+ rx_ring->pFbr1RingVa = (void *)((uint8_t *) rx_ring->pFbr1RingVa +
+ rx_ring->Fbr1offset);
+
+#ifdef USE_FBR0
+ /* Allocate an area of memory for Free Buffer Ring 0 */
+ bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+ rx_ring->pFbr0RingVa = pci_alloc_consistent(adapter->pdev,
+ bufsize,
+ &rx_ring->pFbr0RingPa);
+ if (!rx_ring->pFbr0RingVa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Free Buffer Ring 0\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Save physical address
+ *
+ * NOTE: pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here before
+ * storing the adjusted address.
+ */
+ rx_ring->Fbr0Realpa = rx_ring->pFbr0RingPa;
+
+ /* Align Free Buffer Ring 0 on a 4K boundary */
+ et131x_align_allocated_memory(adapter,
+ &rx_ring->Fbr0Realpa,
+ &rx_ring->Fbr0offset, 0x0FFF);
+
+ rx_ring->pFbr0RingVa = (void *)((uint8_t *) rx_ring->pFbr0RingVa +
+ rx_ring->Fbr0offset);
+#endif
+
+ for (OuterLoop = 0; OuterLoop < (rx_ring->Fbr1NumEntries / FBR_CHUNKS);
+ OuterLoop++) {
+ uint64_t Fbr1Offset;
+ uint64_t Fbr1TempPa;
+ uint32_t Fbr1Align;
+
+ /* This code allocates an area of memory big enough for N
+ * free buffers + (buffer_size - 1) so that the buffers can
+ * be aligned on 4k boundaries. If each buffer were aligned
+ * to a buffer_size boundary, the effect would be to double
+ * the size of FBR0. By allocating N buffers at once, we
+ * reduce this overhead.
+ */
+ if (rx_ring->Fbr1BufferSize > 4096) {
+ Fbr1Align = 4096;
+ } else {
+ Fbr1Align = rx_ring->Fbr1BufferSize;
+ }
+
+ FBRChunkSize =
+ (FBR_CHUNKS * rx_ring->Fbr1BufferSize) + Fbr1Align - 1;
+ rx_ring->Fbr1MemVa[OuterLoop] =
+ pci_alloc_consistent(adapter->pdev, FBRChunkSize,
+ &rx_ring->Fbr1MemPa[OuterLoop]);
+
+ if (!rx_ring->Fbr1MemVa[OuterLoop]) {
+ DBG_ERROR(et131x_dbginfo, "Could not alloc memory\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* See NOTE in "Save Physical Address" comment above */
+ Fbr1TempPa = rx_ring->Fbr1MemPa[OuterLoop];
+
+ et131x_align_allocated_memory(adapter,
+ &Fbr1TempPa,
+ &Fbr1Offset, (Fbr1Align - 1));
+
+ for (InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++) {
+ uint32_t index = (OuterLoop * FBR_CHUNKS) + InnerLoop;
+
+ /* Save the Virtual address of this index for quick
+ * access later
+ */
+ rx_ring->Fbr[1]->Va[index] =
+ (uint8_t *) rx_ring->Fbr1MemVa[OuterLoop] +
+ (InnerLoop * rx_ring->Fbr1BufferSize) + Fbr1Offset;
+
+ /* now store the physical address in the descriptor
+ * so the device can access it
+ */
+ rx_ring->Fbr[1]->PAHigh[index] =
+ (uint32_t) (Fbr1TempPa >> 32);
+ rx_ring->Fbr[1]->PALow[index] = (uint32_t) Fbr1TempPa;
+
+ Fbr1TempPa += rx_ring->Fbr1BufferSize;
+
+ rx_ring->Fbr[1]->Buffer1[index] =
+ rx_ring->Fbr[1]->Va[index];
+ rx_ring->Fbr[1]->Buffer2[index] =
+ rx_ring->Fbr[1]->Va[index] - 4;
+ }
+ }
+
+#ifdef USE_FBR0
+ /* Same for FBR0 (if in use) */
+ for (OuterLoop = 0; OuterLoop < (rx_ring->Fbr0NumEntries / FBR_CHUNKS);
+ OuterLoop++) {
+ uint64_t Fbr0Offset;
+ uint64_t Fbr0TempPa;
+
+ FBRChunkSize = ((FBR_CHUNKS + 1) * rx_ring->Fbr0BufferSize) - 1;
+ rx_ring->Fbr0MemVa[OuterLoop] =
+ pci_alloc_consistent(adapter->pdev, FBRChunkSize,
+ &rx_ring->Fbr0MemPa[OuterLoop]);
+
+ if (!rx_ring->Fbr0MemVa[OuterLoop]) {
+ DBG_ERROR(et131x_dbginfo, "Could not alloc memory\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* See NOTE in "Save Physical Address" comment above */
+ Fbr0TempPa = rx_ring->Fbr0MemPa[OuterLoop];
+
+ et131x_align_allocated_memory(adapter,
+ &Fbr0TempPa,
+ &Fbr0Offset,
+ rx_ring->Fbr0BufferSize - 1);
+
+ for (InnerLoop = 0; InnerLoop < FBR_CHUNKS; InnerLoop++) {
+ uint32_t index = (OuterLoop * FBR_CHUNKS) + InnerLoop;
+
+ rx_ring->Fbr[0]->Va[index] =
+ (uint8_t *) rx_ring->Fbr0MemVa[OuterLoop] +
+ (InnerLoop * rx_ring->Fbr0BufferSize) + Fbr0Offset;
+
+ rx_ring->Fbr[0]->PAHigh[index] =
+ (uint32_t) (Fbr0TempPa >> 32);
+ rx_ring->Fbr[0]->PALow[index] = (uint32_t) Fbr0TempPa;
+
+ Fbr0TempPa += rx_ring->Fbr0BufferSize;
+
+ rx_ring->Fbr[0]->Buffer1[index] =
+ rx_ring->Fbr[0]->Va[index];
+ rx_ring->Fbr[0]->Buffer2[index] =
+ rx_ring->Fbr[0]->Va[index] - 4;
+ }
+ }
+#endif
+
+ /* Allocate an area of memory for FIFO of Packet Status ring entries */
+ pktStatRingSize =
+ sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+
+ rx_ring->pPSRingVa = pci_alloc_consistent(adapter->pdev,
+ pktStatRingSize + 0x0fff,
+ &rx_ring->pPSRingPa);
+
+ if (!rx_ring->pPSRingVa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Packet Status Ring\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Save physical address
+ *
+ * NOTE : pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here before
+ * storing the adjusted address.
+ */
+ rx_ring->pPSRingRealPa = rx_ring->pPSRingPa;
+
+ /* Align Packet Status Ring on a 4K boundary */
+ et131x_align_allocated_memory(adapter,
+ &rx_ring->pPSRingRealPa,
+ &rx_ring->pPSRingOffset, 0x0FFF);
+
+ rx_ring->pPSRingVa = (void *)((uint8_t *) rx_ring->pPSRingVa +
+ rx_ring->pPSRingOffset);
+
+ /* Allocate an area of memory for writeback of status information */
+ rx_ring->pRxStatusVa = pci_alloc_consistent(adapter->pdev,
+ sizeof(RX_STATUS_BLOCK_t) +
+ 0x7, &rx_ring->pRxStatusPa);
+ if (!rx_ring->pRxStatusVa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Status Block\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Save physical address */
+ rx_ring->RxStatusRealPA = rx_ring->pRxStatusPa;
+
+ /* Align write back on an 8 byte boundary */
+ et131x_align_allocated_memory(adapter,
+ &rx_ring->RxStatusRealPA,
+ &rx_ring->RxStatusOffset, 0x07);
+
+ rx_ring->pRxStatusVa = (void *)((uint8_t *) rx_ring->pRxStatusVa +
+ rx_ring->RxStatusOffset);
+ rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD;
+
+ /* Recv
+ * pci_pool_create initializes a lookaside list. After successful
+ * creation, nonpaged fixed-size blocks can be allocated from and
+ * freed to the lookaside list.
+ * RFDs will be allocated from this pool.
+ */
+ rx_ring->RecvLookaside = kmem_cache_create(adapter->netdev->name,
+ sizeof(MP_RFD),
+ 0,
+ SLAB_CACHE_DMA |
+ SLAB_HWCACHE_ALIGN,
+ NULL);
+
+ MP_SET_FLAG(adapter, fMP_ADAPTER_RECV_LOOKASIDE);
+
+ /* The RFDs are going to be put on lists later on, so initialize the
+ * lists now.
+ */
+ INIT_LIST_HEAD(&rx_ring->RecvList);
+ INIT_LIST_HEAD(&rx_ring->RecvPendingList);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/**
+ * et131x_rx_dma_memory_free - Free all memory allocated within this module.
+ * @adapter: pointer to our private adapter structure
+ */
+void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
+{
+ uint32_t index;
+ uint32_t bufsize;
+ uint32_t pktStatRingSize;
+ PMP_RFD pMpRfd;
+ RX_RING_t *rx_ring;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup some convenience pointers */
+ rx_ring = (RX_RING_t *) & adapter->RxRing;
+
+ /* Free RFDs and associated packet descriptors */
+ DBG_ASSERT(rx_ring->nReadyRecv == rx_ring->NumRfd);
+
+ while (!list_empty(&rx_ring->RecvList)) {
+ pMpRfd = (MP_RFD *) list_entry(rx_ring->RecvList.next,
+ MP_RFD, list_node);
+
+ list_del(&pMpRfd->list_node);
+ et131x_rfd_resources_free(adapter, pMpRfd);
+ }
+
+ while (!list_empty(&rx_ring->RecvPendingList)) {
+ pMpRfd = (MP_RFD *) list_entry(rx_ring->RecvPendingList.next,
+ MP_RFD, list_node);
+ list_del(&pMpRfd->list_node);
+ et131x_rfd_resources_free(adapter, pMpRfd);
+ }
+
+ /* Free Free Buffer Ring 1 */
+ if (rx_ring->pFbr1RingVa) {
+ /* First the packet memory */
+ for (index = 0; index <
+ (rx_ring->Fbr1NumEntries / FBR_CHUNKS); index++) {
+ if (rx_ring->Fbr1MemVa[index]) {
+ uint32_t Fbr1Align;
+
+ if (rx_ring->Fbr1BufferSize > 4096) {
+ Fbr1Align = 4096;
+ } else {
+ Fbr1Align = rx_ring->Fbr1BufferSize;
+ }
+
+ bufsize =
+ (rx_ring->Fbr1BufferSize * FBR_CHUNKS) +
+ Fbr1Align - 1;
+
+ pci_free_consistent(adapter->pdev,
+ bufsize,
+ rx_ring->Fbr1MemVa[index],
+ rx_ring->Fbr1MemPa[index]);
+
+ rx_ring->Fbr1MemVa[index] = NULL;
+ }
+ }
+
+ /* Now the FIFO itself */
+ rx_ring->pFbr1RingVa = (void *)((uint8_t *) rx_ring->pFbr1RingVa -
+ rx_ring->Fbr1offset);
+
+ bufsize =
+ (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+
+ pci_free_consistent(adapter->pdev,
+ bufsize,
+ rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa);
+
+ rx_ring->pFbr1RingVa = NULL;
+ }
+
+#ifdef USE_FBR0
+ /* Now the same for Free Buffer Ring 0 */
+ if (rx_ring->pFbr0RingVa) {
+ /* First the packet memory */
+ for (index = 0; index <
+ (rx_ring->Fbr0NumEntries / FBR_CHUNKS); index++) {
+ if (rx_ring->Fbr0MemVa[index]) {
+ bufsize =
+ (rx_ring->Fbr0BufferSize *
+ (FBR_CHUNKS + 1)) - 1;
+
+ pci_free_consistent(adapter->pdev,
+ bufsize,
+ rx_ring->Fbr0MemVa[index],
+ rx_ring->Fbr0MemPa[index]);
+
+ rx_ring->Fbr0MemVa[index] = NULL;
+ }
+ }
+
+ /* Now the FIFO itself */
+ rx_ring->pFbr0RingVa = (void *)((uint8_t *) rx_ring->pFbr0RingVa -
+ rx_ring->Fbr0offset);
+
+ bufsize =
+ (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+
+ pci_free_consistent(adapter->pdev,
+ bufsize,
+ rx_ring->pFbr0RingVa, rx_ring->pFbr0RingPa);
+
+ rx_ring->pFbr0RingVa = NULL;
+ }
+#endif
+
+ /* Free Packet Status Ring */
+ if (rx_ring->pPSRingVa) {
+ rx_ring->pPSRingVa = (void *)((uint8_t *) rx_ring->pPSRingVa -
+ rx_ring->pPSRingOffset);
+
+ pktStatRingSize =
+ sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+
+ pci_free_consistent(adapter->pdev,
+ pktStatRingSize + 0x0fff,
+ rx_ring->pPSRingVa, rx_ring->pPSRingPa);
+
+ rx_ring->pPSRingVa = NULL;
+ }
+
+ /* Free area of memory for the writeback of status information */
+ if (rx_ring->pRxStatusVa) {
+ rx_ring->pRxStatusVa = (void *)((uint8_t *) rx_ring->pRxStatusVa -
+ rx_ring->RxStatusOffset);
+
+ pci_free_consistent(adapter->pdev,
+ sizeof(RX_STATUS_BLOCK_t) + 0x7,
+ rx_ring->pRxStatusVa, rx_ring->pRxStatusPa);
+
+ rx_ring->pRxStatusVa = NULL;
+ }
+
+ /* Free receive buffer pool */
+
+ /* Free receive packet pool */
+
+ /* Destroy the lookaside (RFD) pool */
+ if (MP_TEST_FLAG(adapter, fMP_ADAPTER_RECV_LOOKASIDE)) {
+ kmem_cache_destroy(rx_ring->RecvLookaside);
+ MP_CLEAR_FLAG(adapter, fMP_ADAPTER_RECV_LOOKASIDE);
+ }
+
+ /* Free the FBR Lookup Table */
+#ifdef USE_FBR0
+ kfree(rx_ring->Fbr[0]);
+#endif
+
+ kfree(rx_ring->Fbr[1]);
+
+ /* Reset Counters */
+ rx_ring->nReadyRecv = 0;
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_init_recv - Initialize receive data structures.
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success and errno on failure (as defined in errno.h)
+ */
+int et131x_init_recv(struct et131x_adapter *adapter)
+{
+ int status = -ENOMEM;
+ PMP_RFD pMpRfd = NULL;
+ uint32_t RfdCount;
+ uint32_t TotalNumRfd = 0;
+ RX_RING_t *rx_ring = NULL;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup some convenience pointers */
+ rx_ring = (RX_RING_t *) & adapter->RxRing;
+
+ /* Setup each RFD */
+ for (RfdCount = 0; RfdCount < rx_ring->NumRfd; RfdCount++) {
+ pMpRfd = (MP_RFD *) kmem_cache_alloc(rx_ring->RecvLookaside,
+ GFP_ATOMIC | GFP_DMA);
+
+ if (!pMpRfd) {
+ DBG_ERROR(et131x_dbginfo,
+ "Couldn't alloc RFD out of kmem_cache\n");
+ status = -ENOMEM;
+ continue;
+ }
+
+ status = et131x_rfd_resources_alloc(adapter, pMpRfd);
+ if (status != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "Couldn't alloc packet for RFD\n");
+ kmem_cache_free(rx_ring->RecvLookaside, pMpRfd);
+ continue;
+ }
+
+ /* Add this RFD to the RecvList */
+ list_add_tail(&pMpRfd->list_node, &rx_ring->RecvList);
+
+ /* Increment both the available RFD's, and the total RFD's. */
+ rx_ring->nReadyRecv++;
+ TotalNumRfd++;
+ }
+
+ if (TotalNumRfd > NIC_MIN_NUM_RFD) {
+ status = 0;
+ }
+
+ rx_ring->NumRfd = TotalNumRfd;
+
+ if (status != 0) {
+ kmem_cache_free(rx_ring->RecvLookaside, pMpRfd);
+ DBG_ERROR(et131x_dbginfo,
+ "Allocation problems in et131x_init_recv\n");
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_rfd_resources_alloc
+ * @adapter: pointer to our private adapter structure
+ * @pMpRfd: pointer to a RFD
+ *
+ * Returns 0 on success and errno on failure (as defined in errno.h)
+ */
+int et131x_rfd_resources_alloc(struct et131x_adapter *adapter, MP_RFD *pMpRfd)
+{
+ pMpRfd->Packet = NULL;
+
+ return 0;
+}
+
+/**
+ * et131x_rfd_resources_free - Free the packet allocated for the given RFD
+ * @adapter: pointer to our private adapter structure
+ * @pMpRfd: pointer to a RFD
+ */
+void et131x_rfd_resources_free(struct et131x_adapter *adapter, MP_RFD *pMpRfd)
+{
+ pMpRfd->Packet = NULL;
+ kmem_cache_free(adapter->RxRing.RecvLookaside, pMpRfd);
+}
+
+/**
+ * ConfigRxDmaRegs - Start of Rx_DMA init sequence
+ * @pAdapter: pointer to our adapter structure
+ */
+void ConfigRxDmaRegs(struct et131x_adapter *pAdapter)
+{
+ struct _RXDMA_t __iomem *pRxDma = &pAdapter->CSRAddress->rxdma;
+ struct _rx_ring_t *pRxLocal = &pAdapter->RxRing;
+ PFBR_DESC_t pFbrEntry;
+ uint32_t iEntry;
+ RXDMA_PSR_NUM_DES_t psr_num_des;
+ unsigned long lockflags;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Halt RXDMA to perform the reconfigure. */
+ et131x_rx_dma_disable(pAdapter);
+
+ /* Load the completion writeback physical address
+ *
+ * NOTE : pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here
+ * before storing the adjusted address.
+ */
+ writel((uint32_t) (pRxLocal->RxStatusRealPA >> 32),
+ &pRxDma->dma_wb_base_hi);
+ writel((uint32_t) pRxLocal->RxStatusRealPA, &pRxDma->dma_wb_base_lo);
+
+ memset(pRxLocal->pRxStatusVa, 0, sizeof(RX_STATUS_BLOCK_t));
+
+ /* Set the address and parameters of the packet status ring into the
+ * 1310's registers
+ */
+ writel((uint32_t) (pRxLocal->pPSRingRealPa >> 32),
+ &pRxDma->psr_base_hi);
+ writel((uint32_t) pRxLocal->pPSRingRealPa, &pRxDma->psr_base_lo);
+ writel(pRxLocal->PsrNumEntries - 1, &pRxDma->psr_num_des.value);
+ writel(0, &pRxDma->psr_full_offset.value);
+
+ psr_num_des.value = readl(&pRxDma->psr_num_des.value);
+ writel((psr_num_des.bits.psr_ndes * LO_MARK_PERCENT_FOR_PSR) / 100,
+ &pRxDma->psr_min_des.value);
+
+ spin_lock_irqsave(&pAdapter->RcvLock, lockflags);
+
+ /* These local variables track the PSR in the adapter structure */
+ pRxLocal->local_psr_full.bits.psr_full = 0;
+ pRxLocal->local_psr_full.bits.psr_full_wrap = 0;
+
+ /* Now's the best time to initialize FBR1 contents */
+ pFbrEntry = (PFBR_DESC_t) pRxLocal->pFbr1RingVa;
+ for (iEntry = 0; iEntry < pRxLocal->Fbr1NumEntries; iEntry++) {
+ pFbrEntry->addr_hi = pRxLocal->Fbr[1]->PAHigh[iEntry];
+ pFbrEntry->addr_lo = pRxLocal->Fbr[1]->PALow[iEntry];
+ pFbrEntry->word2.bits.bi = iEntry;
+ pFbrEntry++;
+ }
+
+ /* Set the address and parameters of Free buffer ring 1 (and 0 if
+ * required) into the 1310's registers
+ */
+ writel((uint32_t) (pRxLocal->Fbr1Realpa >> 32), &pRxDma->fbr1_base_hi);
+ writel((uint32_t) pRxLocal->Fbr1Realpa, &pRxDma->fbr1_base_lo);
+ writel(pRxLocal->Fbr1NumEntries - 1, &pRxDma->fbr1_num_des.value);
+
+ {
+ DMA10W_t fbr1_full = { 0 };
+
+ fbr1_full.bits.val = 0;
+ fbr1_full.bits.wrap = 1;
+ writel(fbr1_full.value, &pRxDma->fbr1_full_offset.value);
+ }
+
+ /* This variable tracks the free buffer ring 1 full position, so it
+ * has to match the above.
+ */
+ pRxLocal->local_Fbr1_full.bits.val = 0;
+ pRxLocal->local_Fbr1_full.bits.wrap = 1;
+ writel(((pRxLocal->Fbr1NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
+ &pRxDma->fbr1_min_des.value);
+
+#ifdef USE_FBR0
+ /* Now's the best time to initialize FBR0 contents */
+ pFbrEntry = (PFBR_DESC_t) pRxLocal->pFbr0RingVa;
+ for (iEntry = 0; iEntry < pRxLocal->Fbr0NumEntries; iEntry++) {
+ pFbrEntry->addr_hi = pRxLocal->Fbr[0]->PAHigh[iEntry];
+ pFbrEntry->addr_lo = pRxLocal->Fbr[0]->PALow[iEntry];
+ pFbrEntry->word2.bits.bi = iEntry;
+ pFbrEntry++;
+ }
+
+ writel((uint32_t) (pRxLocal->Fbr0Realpa >> 32), &pRxDma->fbr0_base_hi);
+ writel((uint32_t) pRxLocal->Fbr0Realpa, &pRxDma->fbr0_base_lo);
+ writel(pRxLocal->Fbr0NumEntries - 1, &pRxDma->fbr0_num_des.value);
+
+ {
+ DMA10W_t fbr0_full = { 0 };
+
+ fbr0_full.bits.val = 0;
+ fbr0_full.bits.wrap = 1;
+ writel(fbr0_full.value, &pRxDma->fbr0_full_offset.value);
+ }
+
+ /* This variable tracks the free buffer ring 0 full position, so it
+ * has to match the above.
+ */
+ pRxLocal->local_Fbr0_full.bits.val = 0;
+ pRxLocal->local_Fbr0_full.bits.wrap = 1;
+ writel(((pRxLocal->Fbr0NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
+ &pRxDma->fbr0_min_des.value);
+#endif
+
+ /* Program the number of packets we will receive before generating an
+ * interrupt.
+ * For version B silicon, this value gets updated once autoneg is
+ *complete.
+ */
+ writel(pAdapter->RegistryRxNumBuffers, &pRxDma->num_pkt_done.value);
+
+ /* The "time_done" is not working correctly to coalesce interrupts
+ * after a given time period, but rather is giving us an interrupt
+ * regardless of whether we have received packets.
+ * This value gets updated once autoneg is complete.
+ */
+ writel(pAdapter->RegistryRxTimeInterval, &pRxDma->max_pkt_time.value);
+
+ spin_unlock_irqrestore(&pAdapter->RcvLock, lockflags);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * SetRxDmaTimer - Set the heartbeat timer according to line rate.
+ * @pAdapter: pointer to our adapter structure
+ */
+void SetRxDmaTimer(struct et131x_adapter *pAdapter)
+{
+ /* For version B silicon, we do not use the RxDMA timer for 10 and 100
+ * Mbits/s line rates. We do not enable and RxDMA interrupt coalescing.
+ */
+ if ((pAdapter->uiLinkSpeed == TRUEPHY_SPEED_100MBPS) ||
+ (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS)) {
+ writel(0, &pAdapter->CSRAddress->rxdma.max_pkt_time.value);
+ writel(1, &pAdapter->CSRAddress->rxdma.num_pkt_done.value);
+ }
+}
+
+/**
+ * et131x_rx_dma_disable - Stop of Rx_DMA on the ET1310
+ * @pAdapter: pointer to our adapter structure
+ */
+void et131x_rx_dma_disable(struct et131x_adapter *pAdapter)
+{
+ RXDMA_CSR_t csr;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup the receive dma configuration register */
+ writel(0x00002001, &pAdapter->CSRAddress->rxdma.csr.value);
+ csr.value = readl(&pAdapter->CSRAddress->rxdma.csr.value);
+ if (csr.bits.halt_status != 1) {
+ udelay(5);
+ csr.value = readl(&pAdapter->CSRAddress->rxdma.csr.value);
+ if (csr.bits.halt_status != 1) {
+ DBG_ERROR(et131x_dbginfo,
+ "RX Dma failed to enter halt state. CSR 0x%08x\n",
+ csr.value);
+ }
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_rx_dma_enable - re-start of Rx_DMA on the ET1310.
+ * @pAdapter: pointer to our adapter structure
+ */
+void et131x_rx_dma_enable(struct et131x_adapter *pAdapter)
+{
+ DBG_RX_ENTER(et131x_dbginfo);
+
+ if (pAdapter->RegistryPhyLoopbk) {
+ /* RxDMA is disabled for loopback operation. */
+ writel(0x1, &pAdapter->CSRAddress->rxdma.csr.value);
+ } else {
+ /* Setup the receive dma configuration register for normal operation */
+ RXDMA_CSR_t csr = { 0 };
+
+ csr.bits.fbr1_enable = 1;
+ if (pAdapter->RxRing.Fbr1BufferSize == 4096) {
+ csr.bits.fbr1_size = 1;
+ } else if (pAdapter->RxRing.Fbr1BufferSize == 8192) {
+ csr.bits.fbr1_size = 2;
+ } else if (pAdapter->RxRing.Fbr1BufferSize == 16384) {
+ csr.bits.fbr1_size = 3;
+ }
+#ifdef USE_FBR0
+ csr.bits.fbr0_enable = 1;
+ if (pAdapter->RxRing.Fbr0BufferSize == 256) {
+ csr.bits.fbr0_size = 1;
+ } else if (pAdapter->RxRing.Fbr0BufferSize == 512) {
+ csr.bits.fbr0_size = 2;
+ } else if (pAdapter->RxRing.Fbr0BufferSize == 1024) {
+ csr.bits.fbr0_size = 3;
+ }
+#endif
+ writel(csr.value, &pAdapter->CSRAddress->rxdma.csr.value);
+
+ csr.value = readl(&pAdapter->CSRAddress->rxdma.csr.value);
+ if (csr.bits.halt_status != 0) {
+ udelay(5);
+ csr.value = readl(&pAdapter->CSRAddress->rxdma.csr.value);
+ if (csr.bits.halt_status != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "RX Dma failed to exit halt state. CSR 0x%08x\n",
+ csr.value);
+ }
+ }
+ }
+
+ DBG_RX_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * nic_rx_pkts - Checks the hardware for available packets
+ * @pAdapter: pointer to our adapter
+ *
+ * Returns pMpRfd, a pointer to our MPRFD.
+ *
+ * Checks the hardware for available packets, using completion ring
+ * If packets are available, it gets an RFD from the RecvList, attaches
+ * the packet to it, puts the RFD in the RecvPendList, and also returns
+ * the pointer to the RFD.
+ */
+PMP_RFD nic_rx_pkts(struct et131x_adapter *pAdapter)
+{
+ struct _rx_ring_t *pRxLocal = &pAdapter->RxRing;
+ PRX_STATUS_BLOCK_t pRxStatusBlock;
+ PPKT_STAT_DESC_t pPSREntry;
+ PMP_RFD pMpRfd;
+ uint32_t nIndex;
+ uint8_t *pBufVa;
+ unsigned long lockflags;
+ struct list_head *element;
+ uint8_t ringIndex;
+ uint16_t bufferIndex;
+ uint32_t localLen;
+ PKT_STAT_DESC_WORD0_t Word0;
+
+
+ DBG_RX_ENTER(et131x_dbginfo);
+
+ /* RX Status block is written by the DMA engine prior to every
+ * interrupt. It contains the next to be used entry in the Packet
+ * Status Ring, and also the two Free Buffer rings.
+ */
+ pRxStatusBlock = (PRX_STATUS_BLOCK_t) pRxLocal->pRxStatusVa;
+
+ if (pRxStatusBlock->Word1.bits.PSRoffset ==
+ pRxLocal->local_psr_full.bits.psr_full &&
+ pRxStatusBlock->Word1.bits.PSRwrap ==
+ pRxLocal->local_psr_full.bits.psr_full_wrap) {
+ /* Looks like this ring is not updated yet */
+ DBG_RX(et131x_dbginfo, "(0)\n");
+ DBG_RX_LEAVE(et131x_dbginfo);
+ return NULL;
+ }
+
+ /* The packet status ring indicates that data is available. */
+ pPSREntry = (PPKT_STAT_DESC_t) (pRxLocal->pPSRingVa) +
+ pRxLocal->local_psr_full.bits.psr_full;
+
+ /* Grab any information that is required once the PSR is
+ * advanced, since we can no longer rely on the memory being
+ * accurate
+ */
+ localLen = pPSREntry->word1.bits.length;
+ ringIndex = (uint8_t) pPSREntry->word1.bits.ri;
+ bufferIndex = (uint16_t) pPSREntry->word1.bits.bi;
+ Word0 = pPSREntry->word0;
+
+ DBG_RX(et131x_dbginfo, "RX PACKET STATUS\n");
+ DBG_RX(et131x_dbginfo, "\tlength : %d\n", localLen);
+ DBG_RX(et131x_dbginfo, "\tringIndex : %d\n", ringIndex);
+ DBG_RX(et131x_dbginfo, "\tbufferIndex : %d\n", bufferIndex);
+ DBG_RX(et131x_dbginfo, "\tword0 : 0x%08x\n", Word0.value);
+
+#if 0
+ /* Check the Status Word that the MAC has appended to the PSR
+ * entry in case the MAC has detected errors.
+ */
+ if (Word0.value & ALCATEL_BAD_STATUS) {
+ DBG_ERROR(et131x_dbginfo,
+ "NICRxPkts >> Alcatel Status Word error."
+ "Value 0x%08x\n", pPSREntry->word0.value);
+ }
+#endif
+
+ /* Indicate that we have used this PSR entry. */
+ if (++pRxLocal->local_psr_full.bits.psr_full >
+ pRxLocal->PsrNumEntries - 1) {
+ pRxLocal->local_psr_full.bits.psr_full = 0;
+ pRxLocal->local_psr_full.bits.psr_full_wrap ^= 1;
+ }
+
+ writel(pRxLocal->local_psr_full.value,
+ &pAdapter->CSRAddress->rxdma.psr_full_offset.value);
+
+#ifndef USE_FBR0
+ if (ringIndex != 1) {
+ DBG_ERROR(et131x_dbginfo,
+ "NICRxPkts PSR Entry %d indicates "
+ "Buffer Ring 0 in use\n",
+ pRxLocal->local_psr_full.bits.psr_full);
+ DBG_RX_LEAVE(et131x_dbginfo);
+ return NULL;
+ }
+#endif
+
+#ifdef USE_FBR0
+ if (ringIndex > 1 ||
+ (ringIndex == 0 &&
+ bufferIndex > pRxLocal->Fbr0NumEntries - 1) ||
+ (ringIndex == 1 &&
+ bufferIndex > pRxLocal->Fbr1NumEntries - 1))
+#else
+ if (ringIndex != 1 ||
+ bufferIndex > pRxLocal->Fbr1NumEntries - 1)
+#endif
+ {
+ /* Illegal buffer or ring index cannot be used by S/W*/
+ DBG_ERROR(et131x_dbginfo,
+ "NICRxPkts PSR Entry %d indicates "
+ "length of %d and/or bad bi(%d)\n",
+ pRxLocal->local_psr_full.bits.psr_full,
+ localLen, bufferIndex);
+ DBG_RX_LEAVE(et131x_dbginfo);
+ return NULL;
+ }
+
+ /* Get and fill the RFD. */
+ spin_lock_irqsave(&pAdapter->RcvLock, lockflags);
+
+ pMpRfd = NULL;
+ element = pRxLocal->RecvList.next;
+ pMpRfd = (PMP_RFD) list_entry(element, MP_RFD, list_node);
+
+ if (pMpRfd == NULL) {
+ DBG_RX(et131x_dbginfo,
+ "NULL RFD returned from RecvList via list_entry()\n");
+ DBG_RX_LEAVE(et131x_dbginfo);
+ spin_unlock_irqrestore(&pAdapter->RcvLock, lockflags);
+ return NULL;
+ }
+
+ list_del(&pMpRfd->list_node);
+ pRxLocal->nReadyRecv--;
+
+ spin_unlock_irqrestore(&pAdapter->RcvLock, lockflags);
+
+ pMpRfd->iBufferIndex = bufferIndex;
+ pMpRfd->iRingIndex = ringIndex;
+
+ /* In V1 silicon, there is a bug which screws up filtering of
+ * runt packets. Therefore runt packet filtering is disabled
+ * in the MAC and the packets are dropped here. They are
+ * also counted here.
+ */
+ if (localLen < (NIC_MIN_PACKET_SIZE + 4)) {
+ pAdapter->Stats.other_errors++;
+ localLen = 0;
+ }
+
+ if (localLen) {
+ if (pAdapter->ReplicaPhyLoopbk == 1) {
+ pBufVa = pRxLocal->Fbr[ringIndex]->Va[bufferIndex];
+
+ if (memcmp(&pBufVa[6], &pAdapter->CurrentAddress[0],
+ ETH_ALEN) == 0) {
+ if (memcmp(&pBufVa[42], "Replica packet",
+ ETH_HLEN)) {
+ pAdapter->ReplicaPhyLoopbkPF = 1;
+ }
+ }
+ DBG_WARNING(et131x_dbginfo,
+ "pBufVa:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pBufVa[6], pBufVa[7], pBufVa[8],
+ pBufVa[9], pBufVa[10], pBufVa[11]);
+
+ DBG_WARNING(et131x_dbginfo,
+ "CurrentAddr:\t%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAdapter->CurrentAddress[0],
+ pAdapter->CurrentAddress[1],
+ pAdapter->CurrentAddress[2],
+ pAdapter->CurrentAddress[3],
+ pAdapter->CurrentAddress[4],
+ pAdapter->CurrentAddress[5]);
+ }
+
+ /* Determine if this is a multicast packet coming in */
+ if ((Word0.value & ALCATEL_MULTICAST_PKT) &&
+ !(Word0.value & ALCATEL_BROADCAST_PKT)) {
+ /* Promiscuous mode and Multicast mode are
+ * not mutually exclusive as was first
+ * thought. I guess Promiscuous is just
+ * considered a super-set of the other
+ * filters. Generally filter is 0x2b when in
+ * promiscuous mode.
+ */
+ if ((pAdapter->PacketFilter & ET131X_PACKET_TYPE_MULTICAST)
+ && !(pAdapter->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS)
+ && !(pAdapter->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
+ pBufVa = pRxLocal->Fbr[ringIndex]->
+ Va[bufferIndex];
+
+ /* Loop through our list to see if the
+ * destination address of this packet
+ * matches one in our list.
+ */
+ for (nIndex = 0;
+ nIndex < pAdapter->MCAddressCount;
+ nIndex++) {
+ if (pBufVa[0] ==
+ pAdapter->MCList[nIndex][0]
+ && pBufVa[1] ==
+ pAdapter->MCList[nIndex][1]
+ && pBufVa[2] ==
+ pAdapter->MCList[nIndex][2]
+ && pBufVa[3] ==
+ pAdapter->MCList[nIndex][3]
+ && pBufVa[4] ==
+ pAdapter->MCList[nIndex][4]
+ && pBufVa[5] ==
+ pAdapter->MCList[nIndex][5]) {
+ break;
+ }
+ }
+
+ /* If our index is equal to the number
+ * of Multicast address we have, then
+ * this means we did not find this
+ * packet's matching address in our
+ * list. Set the PacketSize to zero,
+ * so we free our RFD when we return
+ * from this function.
+ */
+ if (nIndex == pAdapter->MCAddressCount) {
+ localLen = 0;
+ }
+ }
+
+ if (localLen > 0) {
+ pAdapter->Stats.multircv++;
+ }
+ } else if (Word0.value & ALCATEL_BROADCAST_PKT) {
+ pAdapter->Stats.brdcstrcv++;
+ } else {
+ /* Not sure what this counter measures in
+ * promiscuous mode. Perhaps we should check
+ * the MAC address to see if it is directed
+ * to us in promiscuous mode.
+ */
+ pAdapter->Stats.unircv++;
+ }
+ }
+
+ if (localLen > 0) {
+ struct sk_buff *skb = NULL;
+
+ //pMpRfd->PacketSize = localLen - 4;
+ pMpRfd->PacketSize = localLen;
+
+ skb = dev_alloc_skb(pMpRfd->PacketSize + 2);
+ if (!skb) {
+ DBG_ERROR(et131x_dbginfo,
+ "Couldn't alloc an SKB for Rx\n");
+ DBG_RX_LEAVE(et131x_dbginfo);
+ return NULL;
+ }
+
+ pAdapter->net_stats.rx_bytes += pMpRfd->PacketSize;
+
+ memcpy(skb_put(skb, pMpRfd->PacketSize),
+ pRxLocal->Fbr[ringIndex]->Va[bufferIndex],
+ pMpRfd->PacketSize);
+
+ skb->dev = pAdapter->netdev;
+ skb->protocol = eth_type_trans(skb, pAdapter->netdev);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ netif_rx(skb);
+ } else {
+ pMpRfd->PacketSize = 0;
+ }
+
+ nic_return_rfd(pAdapter, pMpRfd);
+
+ DBG_RX(et131x_dbginfo, "(1)\n");
+ DBG_RX_LEAVE(et131x_dbginfo);
+ return pMpRfd;
+}
+
+/**
+ * et131x_reset_recv - Reset the receive list
+ * @pAdapter: pointer to our adapter
+ *
+ * Assumption, Rcv spinlock has been acquired.
+ */
+void et131x_reset_recv(struct et131x_adapter *pAdapter)
+{
+ PMP_RFD pMpRfd;
+ struct list_head *element;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ DBG_ASSERT(!list_empty(&pAdapter->RxRing.RecvList));
+
+ /* Take all the RFD's from the pending list, and stick them on the
+ * RecvList.
+ */
+ while (!list_empty(&pAdapter->RxRing.RecvPendingList)) {
+ element = pAdapter->RxRing.RecvPendingList.next;
+
+ pMpRfd = (PMP_RFD) list_entry(element, MP_RFD, list_node);
+
+ list_del(&pMpRfd->list_node);
+ list_add_tail(&pMpRfd->list_node, &pAdapter->RxRing.RecvList);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_handle_recv_interrupt - Interrupt handler for receive processing
+ * @pAdapter: pointer to our adapter
+ *
+ * Assumption, Rcv spinlock has been acquired.
+ */
+void et131x_handle_recv_interrupt(struct et131x_adapter *pAdapter)
+{
+ PMP_RFD pMpRfd = NULL;
+ struct sk_buff *PacketArray[NUM_PACKETS_HANDLED];
+ PMP_RFD RFDFreeArray[NUM_PACKETS_HANDLED];
+ uint32_t PacketArrayCount = 0;
+ uint32_t PacketsToHandle;
+ uint32_t PacketFreeCount = 0;
+ bool TempUnfinishedRec = false;
+
+ DBG_RX_ENTER(et131x_dbginfo);
+
+ PacketsToHandle = NUM_PACKETS_HANDLED;
+
+ /* Process up to available RFD's */
+ while (PacketArrayCount < PacketsToHandle) {
+ if (list_empty(&pAdapter->RxRing.RecvList)) {
+ DBG_ASSERT(pAdapter->RxRing.nReadyRecv == 0);
+ DBG_ERROR(et131x_dbginfo, "NO RFD's !!!!!!!!!!!!!\n");
+ TempUnfinishedRec = true;
+ break;
+ }
+
+ pMpRfd = nic_rx_pkts(pAdapter);
+
+ if (pMpRfd == NULL) {
+ break;
+ }
+
+ /* Do not receive any packets until a filter has been set.
+ * Do not receive any packets until we are at D0.
+ * Do not receive any packets until we have link.
+ * If length is zero, return the RFD in order to advance the
+ * Free buffer ring.
+ */
+ if ((!pAdapter->PacketFilter) ||
+ (pAdapter->PoMgmt.PowerState != NdisDeviceStateD0) ||
+ (!MP_LINK_DETECTED(pAdapter)) ||
+ (pMpRfd->PacketSize == 0)) {
+ continue;
+ }
+
+ /* Increment the number of packets we received */
+ pAdapter->Stats.ipackets++;
+
+ /* Set the status on the packet, either resources or success */
+ if (pAdapter->RxRing.nReadyRecv >= RFD_LOW_WATER_MARK) {
+ /* Put this RFD on the pending list
+ *
+ * NOTE: nic_rx_pkts() above is already returning the
+ * RFD to the RecvList, so don't additionally do that
+ * here.
+ * Besides, we don't really need (at this point) the
+ * pending list anyway.
+ */
+ //spin_lock_irqsave( &pAdapter->RcvPendLock, lockflags );
+ //list_add_tail( &pMpRfd->list_node, &pAdapter->RxRing.RecvPendingList );
+ //spin_unlock_irqrestore( &pAdapter->RcvPendLock, lockflags );
+
+ /* Update the number of outstanding Recvs */
+ //MP_INC_RCV_REF( pAdapter );
+ } else {
+ RFDFreeArray[PacketFreeCount] = pMpRfd;
+ PacketFreeCount++;
+
+ DBG_WARNING(et131x_dbginfo,
+ "RFD's are running out !!!!!!!!!!!!!\n");
+ }
+
+ PacketArray[PacketArrayCount] = pMpRfd->Packet;
+ PacketArrayCount++;
+ }
+
+ if ((PacketArrayCount == NUM_PACKETS_HANDLED) || TempUnfinishedRec) {
+ pAdapter->RxRing.UnfinishedReceives = true;
+ writel(pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO,
+ &pAdapter->CSRAddress->global.watchdog_timer);
+ } else {
+ /* Watchdog timer will disable itself if appropriate. */
+ pAdapter->RxRing.UnfinishedReceives = false;
+ }
+
+ DBG_RX_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * NICReturnRFD - Recycle a RFD and put it back onto the receive list
+ * @pAdapter: pointer to our adapter
+ * @pMpRfd: pointer to the RFD
+ */
+void nic_return_rfd(struct et131x_adapter *pAdapter, PMP_RFD pMpRfd)
+{
+ struct _rx_ring_t *pRxLocal = &pAdapter->RxRing;
+ struct _RXDMA_t __iomem *pRxDma = &pAdapter->CSRAddress->rxdma;
+ uint16_t bi = pMpRfd->iBufferIndex;
+ uint8_t ri = pMpRfd->iRingIndex;
+ unsigned long lockflags;
+
+ DBG_RX_ENTER(et131x_dbginfo);
+
+ /* We don't use any of the OOB data besides status. Otherwise, we
+ * need to clean up OOB data
+ */
+ if (
+#ifdef USE_FBR0
+ (ri == 0 && bi < pRxLocal->Fbr0NumEntries) ||
+#endif
+ (ri == 1 && bi < pRxLocal->Fbr1NumEntries)) {
+ spin_lock_irqsave(&pAdapter->FbrLock, lockflags);
+
+ if (ri == 1) {
+ PFBR_DESC_t pNextDesc =
+ (PFBR_DESC_t) (pRxLocal->pFbr1RingVa) +
+ pRxLocal->local_Fbr1_full.bits.val;
+
+ /* Handle the Free Buffer Ring advancement here. Write
+ * the PA / Buffer Index for the returned buffer into
+ * the oldest (next to be freed)FBR entry
+ */
+ pNextDesc->addr_hi = pRxLocal->Fbr[1]->PAHigh[bi];
+ pNextDesc->addr_lo = pRxLocal->Fbr[1]->PALow[bi];
+ pNextDesc->word2.value = bi;
+
+ if (++pRxLocal->local_Fbr1_full.bits.val >
+ (pRxLocal->Fbr1NumEntries - 1)) {
+ pRxLocal->local_Fbr1_full.bits.val = 0;
+ pRxLocal->local_Fbr1_full.bits.wrap ^= 1;
+ }
+
+ writel(pRxLocal->local_Fbr1_full.value,
+ &pRxDma->fbr1_full_offset.value);
+ }
+#ifdef USE_FBR0
+ else {
+ PFBR_DESC_t pNextDesc =
+ (PFBR_DESC_t) pRxLocal->pFbr0RingVa +
+ pRxLocal->local_Fbr0_full.bits.val;
+
+ /* Handle the Free Buffer Ring advancement here. Write
+ * the PA / Buffer Index for the returned buffer into
+ * the oldest (next to be freed) FBR entry
+ */
+ pNextDesc->addr_hi = pRxLocal->Fbr[0]->PAHigh[bi];
+ pNextDesc->addr_lo = pRxLocal->Fbr[0]->PALow[bi];
+ pNextDesc->word2.value = bi;
+
+ if (++pRxLocal->local_Fbr0_full.bits.val >
+ (pRxLocal->Fbr0NumEntries - 1)) {
+ pRxLocal->local_Fbr0_full.bits.val = 0;
+ pRxLocal->local_Fbr0_full.bits.wrap ^= 1;
+ }
+
+ writel(pRxLocal->local_Fbr0_full.value,
+ &pRxDma->fbr0_full_offset.value);
+ }
+#endif
+ spin_unlock_irqrestore(&pAdapter->FbrLock, lockflags);
+ } else {
+ DBG_ERROR(et131x_dbginfo,
+ "NICReturnRFD illegal Buffer Index returned\n");
+ }
+
+ /* The processing on this RFD is done, so put it back on the tail of
+ * our list
+ */
+ spin_lock_irqsave(&pAdapter->RcvLock, lockflags);
+ list_add_tail(&pMpRfd->list_node, &pRxLocal->RecvList);
+ pRxLocal->nReadyRecv++;
+ spin_unlock_irqrestore(&pAdapter->RcvLock, lockflags);
+
+ DBG_ASSERT(pRxLocal->nReadyRecv <= pRxLocal->NumRfd);
+ DBG_RX_LEAVE(et131x_dbginfo);
+}
diff --git a/drivers/staging/et131x/et1310_rx.h b/drivers/staging/et131x/et1310_rx.h
new file mode 100644
index 00000000000..ea66dbcd8df
--- /dev/null
+++ b/drivers/staging/et131x/et1310_rx.h
@@ -0,0 +1,373 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_rx.h - Defines, structs, enums, prototypes, etc. pertaining to data
+ * reception.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET1310_RX_H__
+#define __ET1310_RX_H__
+
+#include "et1310_address_map.h"
+
+#define USE_FBR0 true
+
+#ifdef USE_FBR0
+//#define FBR0_BUFFER_SIZE 256
+#endif
+
+//#define FBR1_BUFFER_SIZE 2048
+
+#define FBR_CHUNKS 32
+
+#define MAX_DESC_PER_RING_RX 1024
+
+/* number of RFDs - default and min */
+#ifdef USE_FBR0
+#define RFD_LOW_WATER_MARK 40
+#define NIC_MIN_NUM_RFD 64
+#define NIC_DEFAULT_NUM_RFD 1024
+#else
+#define RFD_LOW_WATER_MARK 20
+#define NIC_MIN_NUM_RFD 64
+#define NIC_DEFAULT_NUM_RFD 256
+#endif
+
+#define NUM_PACKETS_HANDLED 256
+
+#define ALCATEL_BAD_STATUS 0xe47f0000
+#define ALCATEL_MULTICAST_PKT 0x01000000
+#define ALCATEL_BROADCAST_PKT 0x02000000
+
+/* typedefs for Free Buffer Descriptors */
+typedef union _FBR_WORD2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 reserved:22; // bits 10-31
+ u32 bi:10; // bits 0-9(Buffer Index)
+#else
+ u32 bi:10; // bits 0-9(Buffer Index)
+ u32 reserved:22; // bit 10-31
+#endif
+ } bits;
+} FBR_WORD2_t, *PFBR_WORD2_t;
+
+typedef struct _FBR_DESC_t {
+ u32 addr_lo;
+ u32 addr_hi;
+ FBR_WORD2_t word2;
+} FBR_DESC_t, *PFBR_DESC_t;
+
+/* Typedefs for Packet Status Ring Descriptors */
+typedef union _PKT_STAT_DESC_WORD0_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ // top 16 bits are from the Alcatel Status Word as enumerated in
+ // PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2)
+#if 0
+ u32 asw_trunc:1; // bit 31(Rx frame truncated)
+#endif
+ u32 asw_long_evt:1; // bit 31(Rx long event)
+ u32 asw_VLAN_tag:1; // bit 30(VLAN tag detected)
+ u32 asw_unsupported_op:1; // bit 29(unsupported OP code)
+ u32 asw_pause_frame:1; // bit 28(is a pause frame)
+ u32 asw_control_frame:1; // bit 27(is a control frame)
+ u32 asw_dribble_nibble:1; // bit 26(spurious bits after EOP)
+ u32 asw_broadcast:1; // bit 25(has a broadcast address)
+ u32 asw_multicast:1; // bit 24(has a multicast address)
+ u32 asw_OK:1; // bit 23(valid CRC + no code error)
+ u32 asw_too_long:1; // bit 22(frame length > 1518 bytes)
+ u32 asw_len_chk_err:1; // bit 21(frame length field incorrect)
+ u32 asw_CRC_err:1; // bit 20(CRC error)
+ u32 asw_code_err:1; // bit 19(one or more nibbles signalled as errors)
+ u32 asw_false_carrier_event:1; // bit 18(bad carrier since last good packet)
+ u32 asw_RX_DV_event:1; // bit 17(short receive event detected)
+ u32 asw_prev_pkt_dropped:1;// bit 16(e.g. IFG too small on previous)
+ u32 unused:5; // bits 11-15
+ u32 vp:1; // bit 10(VLAN Packet)
+ u32 jp:1; // bit 9(Jumbo Packet)
+ u32 ft:1; // bit 8(Frame Truncated)
+ u32 drop:1; // bit 7(Drop packet)
+ u32 rxmac_error:1; // bit 6(RXMAC Error Indicator)
+ u32 wol:1; // bit 5(WOL Event)
+ u32 tcpp:1; // bit 4(TCP checksum pass)
+ u32 tcpa:1; // bit 3(TCP checksum assist)
+ u32 ipp:1; // bit 2(IP checksum pass)
+ u32 ipa:1; // bit 1(IP checksum assist)
+ u32 hp:1; // bit 0(hash pass)
+#else
+ u32 hp:1; // bit 0(hash pass)
+ u32 ipa:1; // bit 1(IP checksum assist)
+ u32 ipp:1; // bit 2(IP checksum pass)
+ u32 tcpa:1; // bit 3(TCP checksum assist)
+ u32 tcpp:1; // bit 4(TCP checksum pass)
+ u32 wol:1; // bit 5(WOL Event)
+ u32 rxmac_error:1; // bit 6(RXMAC Error Indicator)
+ u32 drop:1; // bit 7(Drop packet)
+ u32 ft:1; // bit 8(Frame Truncated)
+ u32 jp:1; // bit 9(Jumbo Packet)
+ u32 vp:1; // bit 10(VLAN Packet)
+ u32 unused:5; // bits 11-15
+ u32 asw_prev_pkt_dropped:1;// bit 16(e.g. IFG too small on previous)
+ u32 asw_RX_DV_event:1; // bit 17(short receive event detected)
+ u32 asw_false_carrier_event:1; // bit 18(bad carrier since last good packet)
+ u32 asw_code_err:1; // bit 19(one or more nibbles signalled as errors)
+ u32 asw_CRC_err:1; // bit 20(CRC error)
+ u32 asw_len_chk_err:1; // bit 21(frame length field incorrect)
+ u32 asw_too_long:1; // bit 22(frame length > 1518 bytes)
+ u32 asw_OK:1; // bit 23(valid CRC + no code error)
+ u32 asw_multicast:1; // bit 24(has a multicast address)
+ u32 asw_broadcast:1; // bit 25(has a broadcast address)
+ u32 asw_dribble_nibble:1; // bit 26(spurious bits after EOP)
+ u32 asw_control_frame:1; // bit 27(is a control frame)
+ u32 asw_pause_frame:1; // bit 28(is a pause frame)
+ u32 asw_unsupported_op:1; // bit 29(unsupported OP code)
+ u32 asw_VLAN_tag:1; // bit 30(VLAN tag detected)
+ u32 asw_long_evt:1; // bit 31(Rx long event)
+#if 0
+ u32 asw_trunc:1; // bit 31(Rx frame truncated)
+#endif
+#endif
+ } bits;
+} PKT_STAT_DESC_WORD0_t, *PPKT_STAT_WORD0_t;
+
+typedef union _PKT_STAT_DESC_WORD1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:4; // bits 28-31
+ u32 ri:2; // bits 26-27(Ring Index)
+ u32 bi:10; // bits 16-25(Buffer Index)
+ u32 length:16; // bit 0-15(length in bytes)
+#else
+ u32 length:16; // bit 0-15(length in bytes)
+ u32 bi:10; // bits 16-25(Buffer Index)
+ u32 ri:2; // bits 26-27(Ring Index)
+ u32 unused:4; // bits 28-31
+#endif
+ } bits;
+} PKT_STAT_DESC_WORD1_t, *PPKT_STAT_WORD1_t;
+
+typedef struct _PKT_STAT_DESC_t {
+ PKT_STAT_DESC_WORD0_t word0;
+ PKT_STAT_DESC_WORD1_t word1;
+} PKT_STAT_DESC_t, *PPKT_STAT_DESC_t;
+
+/* Typedefs for the RX DMA status word */
+
+/*
+ * RXSTAT_WORD0_t structure holds part of the status bits of the Rx DMA engine
+ * that get copied out to memory by the ET-1310. Word 0 is a 32 bit word
+ * whichcontains Free Buffer ring 0 and 1 available offset.
+ */
+typedef union _rxstat_word0_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 FBR1unused:5; // bits 27-31
+ u32 FBR1wrap:1; // bit 26
+ u32 FBR1offset:10; // bits 16-25
+ u32 FBR0unused:5; // bits 11-15
+ u32 FBR0wrap:1; // bit 10
+ u32 FBR0offset:10; // bits 0-9
+#else
+ u32 FBR0offset:10; // bits 0-9
+ u32 FBR0wrap:1; // bit 10
+ u32 FBR0unused:5; // bits 11-15
+ u32 FBR1offset:10; // bits 16-25
+ u32 FBR1wrap:1; // bit 26
+ u32 FBR1unused:5; // bits 27-31
+#endif
+ } bits;
+} RXSTAT_WORD0_t, *PRXSTAT_WORD0_t;
+
+/*
+ * RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine
+ * that get copied out to memory by the ET-1310. Word 3 is a 32 bit word
+ * which contains the Packet Status Ring available offset.
+ */
+typedef union _rxstat_word1_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 PSRunused:3; // bits 29-31
+ u32 PSRwrap:1; // bit 28
+ u32 PSRoffset:12; // bits 16-27
+ u32 reserved:16; // bits 0-15
+#else
+ u32 reserved:16; // bits 0-15
+ u32 PSRoffset:12; // bits 16-27
+ u32 PSRwrap:1; // bit 28
+ u32 PSRunused:3; // bits 29-31
+#endif
+ } bits;
+} RXSTAT_WORD1_t, *PRXSTAT_WORD1_t;
+
+/*
+ * RX_STATUS_BLOCK_t is sructure representing the status of the Rx DMA engine
+ * it sits in free memory, and is pointed to by 0x101c / 0x1020
+ */
+typedef struct _rx_status_block_t {
+ RXSTAT_WORD0_t Word0;
+ RXSTAT_WORD1_t Word1;
+} RX_STATUS_BLOCK_t, *PRX_STATUS_BLOCK_t;
+
+/*
+ * Structure for look-up table holding free buffer ring pointers
+ */
+typedef struct _FbrLookupTable {
+ void *Va[MAX_DESC_PER_RING_RX];
+ void *Buffer1[MAX_DESC_PER_RING_RX];
+ void *Buffer2[MAX_DESC_PER_RING_RX];
+ u32 PAHigh[MAX_DESC_PER_RING_RX];
+ u32 PALow[MAX_DESC_PER_RING_RX];
+} FBRLOOKUPTABLE, *PFBRLOOKUPTABLE;
+
+typedef enum {
+ ONE_PACKET_INTERRUPT,
+ FOUR_PACKET_INTERRUPT
+} eRX_INTERRUPT_STATE_t, *PeRX_INTERRUPT_STATE_t;
+
+/*
+ * Structure to hold the skb's in a list
+ */
+typedef struct rx_skb_list_elem {
+ struct list_head skb_list_elem;
+ dma_addr_t dma_addr;
+ struct sk_buff *skb;
+} RX_SKB_LIST_ELEM, *PRX_SKB_LIST_ELEM;
+
+/*
+ * RX_RING_t is sructure representing the adaptor's local reference(s) to the
+ * rings
+ */
+typedef struct _rx_ring_t {
+#ifdef USE_FBR0
+ void *pFbr0RingVa;
+ dma_addr_t pFbr0RingPa;
+ void *Fbr0MemVa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ dma_addr_t Fbr0MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ uint64_t Fbr0Realpa;
+ uint64_t Fbr0offset;
+ DMA10W_t local_Fbr0_full;
+ u32 Fbr0NumEntries;
+ u32 Fbr0BufferSize;
+#endif
+ void *pFbr1RingVa;
+ dma_addr_t pFbr1RingPa;
+ void *Fbr1MemVa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ dma_addr_t Fbr1MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ uint64_t Fbr1Realpa;
+ uint64_t Fbr1offset;
+ FBRLOOKUPTABLE *Fbr[2];
+ DMA10W_t local_Fbr1_full;
+ u32 Fbr1NumEntries;
+ u32 Fbr1BufferSize;
+
+ void *pPSRingVa;
+ dma_addr_t pPSRingPa;
+ uint64_t pPSRingRealPa;
+ uint64_t pPSRingOffset;
+ RXDMA_PSR_FULL_OFFSET_t local_psr_full;
+ u32 PsrNumEntries;
+
+ void *pRxStatusVa;
+ dma_addr_t pRxStatusPa;
+ uint64_t RxStatusRealPA;
+ uint64_t RxStatusOffset;
+
+ struct list_head RecvBufferPool;
+
+ /* RECV */
+ struct list_head RecvList;
+ struct list_head RecvPendingList;
+ u32 nReadyRecv;
+
+ u32 NumRfd;
+
+ bool UnfinishedReceives;
+
+ struct list_head RecvPacketPool;
+
+ /* lookaside lists */
+ struct kmem_cache *RecvLookaside;
+} RX_RING_t, *PRX_RING_t;
+
+/* Forward reference of RFD */
+struct _MP_RFD;
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+/* PROTOTYPES for Initialization */
+int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
+int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
+ struct _MP_RFD *pMpRfd);
+void et131x_rfd_resources_free(struct et131x_adapter *adapter,
+ struct _MP_RFD *pMpRfd);
+int et131x_init_recv(struct et131x_adapter *adapter);
+
+void ConfigRxDmaRegs(struct et131x_adapter *adapter);
+void SetRxDmaTimer(struct et131x_adapter *adapter);
+void et131x_rx_dma_disable(struct et131x_adapter *adapter);
+void et131x_rx_dma_enable(struct et131x_adapter *adapter);
+
+void et131x_reset_recv(struct et131x_adapter *adapter);
+
+void et131x_handle_recv_interrupt(struct et131x_adapter *adapter);
+
+#endif /* __ET1310_RX_H__ */
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
new file mode 100644
index 00000000000..a95c2608a0c
--- /dev/null
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -0,0 +1,1525 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_tx.c - Routines used to perform data transmission.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+#include "et131x_isr.h"
+
+#include "et1310_tx.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+static void et131x_update_tcb_list(struct et131x_adapter *pAdapter);
+static void et131x_check_send_wait_list(struct et131x_adapter *pAdapter);
+static inline void et131x_free_send_packet(struct et131x_adapter *pAdapter,
+ PMP_TCB pMpTcb);
+static int et131x_send_packet(struct sk_buff *skb,
+ struct et131x_adapter *pAdapter);
+static int nic_send_packet(struct et131x_adapter *pAdapter, PMP_TCB pMpTcb);
+
+/**
+ * et131x_tx_dma_memory_alloc
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success and errno on failure (as defined in errno.h).
+ *
+ * Allocates memory that will be visible both to the device and to the CPU.
+ * The OS will pass us packets, pointers to which we will insert in the Tx
+ * Descriptor queue. The device will read this queue to find the packets in
+ * memory. The device will update the "status" in memory each time it xmits a
+ * packet.
+ */
+int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
+{
+ int desc_size = 0;
+ TX_RING_t *tx_ring = &adapter->TxRing;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Allocate memory for the TCB's (Transmit Control Block) */
+ adapter->TxRing.MpTcbMem = (MP_TCB *) kcalloc(NUM_TCB, sizeof(MP_TCB),
+ GFP_ATOMIC | GFP_DMA);
+ if (!adapter->TxRing.MpTcbMem) {
+ DBG_ERROR(et131x_dbginfo, "Cannot alloc memory for TCBs\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Allocate enough memory for the Tx descriptor ring, and allocate
+ * some extra so that the ring can be aligned on a 4k boundary.
+ */
+ desc_size = (sizeof(TX_DESC_ENTRY_t) * NUM_DESC_PER_RING_TX) + 4096 - 1;
+ tx_ring->pTxDescRingVa =
+ (PTX_DESC_ENTRY_t) pci_alloc_consistent(adapter->pdev, desc_size,
+ &tx_ring->pTxDescRingPa);
+ if (!adapter->TxRing.pTxDescRingVa) {
+ DBG_ERROR(et131x_dbginfo, "Cannot alloc memory for Tx Ring\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Save physical address
+ *
+ * NOTE: pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here before
+ * storing the adjusted address.
+ */
+ tx_ring->pTxDescRingAdjustedPa = tx_ring->pTxDescRingPa;
+
+ /* Align Tx Descriptor Ring on a 4k (0x1000) byte boundary */
+ et131x_align_allocated_memory(adapter,
+ &tx_ring->pTxDescRingAdjustedPa,
+ &tx_ring->TxDescOffset, 0x0FFF);
+
+ tx_ring->pTxDescRingVa += tx_ring->TxDescOffset;
+
+ /* Allocate memory for the Tx status block */
+ tx_ring->pTxStatusVa = pci_alloc_consistent(adapter->pdev,
+ sizeof(TX_STATUS_BLOCK_t),
+ &tx_ring->pTxStatusPa);
+ if (!adapter->TxRing.pTxStatusPa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Tx status block\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ /* Allocate memory for a dummy buffer */
+ tx_ring->pTxDummyBlkVa = pci_alloc_consistent(adapter->pdev,
+ NIC_MIN_PACKET_SIZE,
+ &tx_ring->pTxDummyBlkPa);
+ if (!adapter->TxRing.pTxDummyBlkPa) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot alloc memory for Tx dummy buffer\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/**
+ * et131x_tx_dma_memory_free - Free all memory allocated within this module
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success and errno on failure (as defined in errno.h).
+ */
+void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
+{
+ int desc_size = 0;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ if (adapter->TxRing.pTxDescRingVa) {
+ /* Free memory relating to Tx rings here */
+ adapter->TxRing.pTxDescRingVa -= adapter->TxRing.TxDescOffset;
+
+ desc_size =
+ (sizeof(TX_DESC_ENTRY_t) * NUM_DESC_PER_RING_TX) + 4096 - 1;
+
+ pci_free_consistent(adapter->pdev,
+ desc_size,
+ adapter->TxRing.pTxDescRingVa,
+ adapter->TxRing.pTxDescRingPa);
+
+ adapter->TxRing.pTxDescRingVa = NULL;
+ }
+
+ /* Free memory for the Tx status block */
+ if (adapter->TxRing.pTxStatusVa) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(TX_STATUS_BLOCK_t),
+ adapter->TxRing.pTxStatusVa,
+ adapter->TxRing.pTxStatusPa);
+
+ adapter->TxRing.pTxStatusVa = NULL;
+ }
+
+ /* Free memory for the dummy buffer */
+ if (adapter->TxRing.pTxDummyBlkVa) {
+ pci_free_consistent(adapter->pdev,
+ NIC_MIN_PACKET_SIZE,
+ adapter->TxRing.pTxDummyBlkVa,
+ adapter->TxRing.pTxDummyBlkPa);
+
+ adapter->TxRing.pTxDummyBlkVa = NULL;
+ }
+
+ /* Free the memory for MP_TCB structures */
+ if (adapter->TxRing.MpTcbMem) {
+ kfree(adapter->TxRing.MpTcbMem);
+ adapter->TxRing.MpTcbMem = NULL;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * ConfigTxDmaRegs - Set up the tx dma section of the JAGCore.
+ * @adapter: pointer to our private adapter structure
+ */
+void ConfigTxDmaRegs(struct et131x_adapter *pAdapter)
+{
+ struct _TXDMA_t __iomem *pTxDma = &pAdapter->CSRAddress->txdma;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Load the hardware with the start of the transmit descriptor ring. */
+ writel((uint32_t) (pAdapter->TxRing.pTxDescRingAdjustedPa >> 32),
+ &pTxDma->pr_base_hi);
+ writel((uint32_t) pAdapter->TxRing.pTxDescRingAdjustedPa,
+ &pTxDma->pr_base_lo);
+
+ /* Initialise the transmit DMA engine */
+ writel(NUM_DESC_PER_RING_TX - 1, &pTxDma->pr_num_des.value);
+
+ /* Load the completion writeback physical address
+ *
+ * NOTE: pci_alloc_consistent(), used above to alloc DMA regions,
+ * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
+ * are ever returned, make sure the high part is retrieved here before
+ * storing the adjusted address.
+ */
+ writel(0, &pTxDma->dma_wb_base_hi);
+ writel(pAdapter->TxRing.pTxStatusPa, &pTxDma->dma_wb_base_lo);
+
+ memset(pAdapter->TxRing.pTxStatusVa, 0, sizeof(TX_STATUS_BLOCK_t));
+
+ writel(0, &pTxDma->service_request.value);
+ pAdapter->TxRing.txDmaReadyToSend.value = 0;
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310
+ * @pAdapter: pointer to our adapter structure
+ */
+void et131x_tx_dma_disable(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup the tramsmit dma configuration register */
+ writel(0x101, &pAdapter->CSRAddress->txdma.csr.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_tx_dma_enable - re-start of Tx_DMA on the ET1310.
+ * @pAdapter: pointer to our adapter structure
+ *
+ * Mainly used after a return to the D0 (full-power) state from a lower state.
+ */
+void et131x_tx_dma_enable(struct et131x_adapter *pAdapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ if (pAdapter->RegistryPhyLoopbk) {
+ /* TxDMA is disabled for loopback operation. */
+ writel(0x101, &pAdapter->CSRAddress->txdma.csr.value);
+ } else {
+ TXDMA_CSR_t csr = { 0 };
+
+ /* Setup the transmit dma configuration register for normal
+ * operation
+ */
+ csr.bits.sngl_epkt_mode = 1;
+ csr.bits.halt = 0;
+ csr.bits.cache_thrshld = pAdapter->RegistryDMACache;
+ writel(csr.value, &pAdapter->CSRAddress->txdma.csr.value);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_init_send - Initialize send data structures
+ * @adapter: pointer to our private adapter structure
+ */
+void et131x_init_send(struct et131x_adapter *adapter)
+{
+ PMP_TCB pMpTcb;
+ uint32_t TcbCount;
+ TX_RING_t *tx_ring;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Setup some convenience pointers */
+ tx_ring = &adapter->TxRing;
+ pMpTcb = adapter->TxRing.MpTcbMem;
+
+ tx_ring->TCBReadyQueueHead = pMpTcb;
+
+ /* Go through and set up each TCB */
+ for (TcbCount = 0; TcbCount < NUM_TCB; TcbCount++) {
+ memset(pMpTcb, 0, sizeof(MP_TCB));
+
+ /* Set the link pointer in HW TCB to the next TCB in the
+ * chain. If this is the last TCB in the chain, also set the
+ * tail pointer.
+ */
+ if (TcbCount < NUM_TCB - 1) {
+ pMpTcb->Next = pMpTcb + 1;
+ } else {
+ tx_ring->TCBReadyQueueTail = pMpTcb;
+ pMpTcb->Next = (PMP_TCB) NULL;
+ }
+
+ pMpTcb++;
+ }
+
+ /* Curr send queue should now be empty */
+ tx_ring->CurrSendHead = (PMP_TCB) NULL;
+ tx_ring->CurrSendTail = (PMP_TCB) NULL;
+
+ INIT_LIST_HEAD(&adapter->TxRing.SendWaitQueue);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_send_packets - This function is called by the OS to send packets
+ * @skb: the packet(s) to send
+ * @netdev:device on which to TX the above packet(s)
+ *
+ * Return 0 in almost all cases; non-zero value in extreme hard failure only
+ */
+int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev)
+{
+ int status = 0;
+ struct et131x_adapter *pAdapter = NULL;
+
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ pAdapter = netdev_priv(netdev);
+
+ /* Send these packets
+ *
+ * NOTE: The Linux Tx entry point is only given one packet at a time
+ * to Tx, so the PacketCount and it's array used makes no sense here
+ */
+
+ /* Queue is not empty or TCB is not available */
+ if (!list_empty(&pAdapter->TxRing.SendWaitQueue) ||
+ MP_TCB_RESOURCES_NOT_AVAILABLE(pAdapter)) {
+ /* NOTE: If there's an error on send, no need to queue the
+ * packet under Linux; if we just send an error up to the
+ * netif layer, it will resend the skb to us.
+ */
+ DBG_VERBOSE(et131x_dbginfo, "TCB Resources Not Available\n");
+ status = -ENOMEM;
+ } else {
+ /* We need to see if the link is up; if it's not, make the
+ * netif layer think we're good and drop the packet
+ */
+ //if( MP_SHOULD_FAIL_SEND( pAdapter ) || pAdapter->DriverNoPhyAccess )
+ if (MP_SHOULD_FAIL_SEND(pAdapter) || pAdapter->DriverNoPhyAccess
+ || !netif_carrier_ok(netdev)) {
+ DBG_VERBOSE(et131x_dbginfo,
+ "Can't Tx, Link is DOWN; drop the packet\n");
+
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+
+ pAdapter->net_stats.tx_dropped++;
+ } else {
+ status = et131x_send_packet(skb, pAdapter);
+
+ if (status == -ENOMEM) {
+
+ /* NOTE: If there's an error on send, no need
+ * to queue the packet under Linux; if we just
+ * send an error up to the netif layer, it
+ * will resend the skb to us.
+ */
+ DBG_WARNING(et131x_dbginfo,
+ "Resources problem, Queue tx packet\n");
+ } else if (status != 0) {
+ /* On any other error, make netif think we're
+ * OK and drop the packet
+ */
+ DBG_WARNING(et131x_dbginfo,
+ "General error, drop packet\n");
+
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+
+ pAdapter->net_stats.tx_dropped++;
+ }
+ }
+ }
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_send_packet - Do the work to send a packet
+ * @skb: the packet(s) to send
+ * @pAdapter: a pointer to the device's private adapter structure
+ *
+ * Return 0 in almost all cases; non-zero value in extreme hard failure only.
+ *
+ * Assumption: Send spinlock has been acquired
+ */
+static int et131x_send_packet(struct sk_buff *skb,
+ struct et131x_adapter *pAdapter)
+{
+ int status = 0;
+ PMP_TCB pMpTcb = NULL;
+ uint16_t *pShBufVa;
+ unsigned long lockflags;
+
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ /* Is our buffer scattered, or continuous? */
+ if (skb_shinfo(skb)->nr_frags == 0) {
+ DBG_TX(et131x_dbginfo, "Scattered buffer: NO\n");
+ } else {
+ DBG_TX(et131x_dbginfo, "Scattered buffer: YES, Num Frags: %d\n",
+ skb_shinfo(skb)->nr_frags);
+ }
+
+ /* All packets must have at least a MAC address and a protocol type */
+ if (skb->len < ETH_HLEN) {
+ DBG_ERROR(et131x_dbginfo,
+ "Packet size < ETH_HLEN (14 bytes)\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* Get a TCB for this packet */
+ spin_lock_irqsave(&pAdapter->TCBReadyQLock, lockflags);
+
+ pMpTcb = pAdapter->TxRing.TCBReadyQueueHead;
+
+ if (pMpTcb == NULL) {
+ spin_unlock_irqrestore(&pAdapter->TCBReadyQLock, lockflags);
+
+ DBG_WARNING(et131x_dbginfo, "Can't obtain a TCB\n");
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return -ENOMEM;
+ }
+
+ pAdapter->TxRing.TCBReadyQueueHead = pMpTcb->Next;
+
+ if (pAdapter->TxRing.TCBReadyQueueHead == NULL) {
+ pAdapter->TxRing.TCBReadyQueueTail = NULL;
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBReadyQLock, lockflags);
+
+ pMpTcb->PacketLength = skb->len;
+ pMpTcb->Packet = skb;
+
+ if ((skb->data != NULL) && ((skb->len - skb->data_len) >= 6)) {
+ pShBufVa = (uint16_t *) skb->data;
+
+ if ((pShBufVa[0] == 0xffff) &&
+ (pShBufVa[1] == 0xffff) && (pShBufVa[2] == 0xffff)) {
+ MP_SET_FLAG(pMpTcb, fMP_DEST_BROAD);
+ } else if ((pShBufVa[0] & 0x3) == 0x0001) {
+ MP_SET_FLAG(pMpTcb, fMP_DEST_MULTI);
+ }
+ }
+
+ pMpTcb->Next = NULL;
+
+ /* Call the NIC specific send handler. */
+ if (status == 0) {
+ status = nic_send_packet(pAdapter, pMpTcb);
+ }
+
+ if (status != 0) {
+ spin_lock_irqsave(&pAdapter->TCBReadyQLock, lockflags);
+
+ if (pAdapter->TxRing.TCBReadyQueueTail) {
+ pAdapter->TxRing.TCBReadyQueueTail->Next = pMpTcb;
+ } else {
+ /* Apparently ready Q is empty. */
+ pAdapter->TxRing.TCBReadyQueueHead = pMpTcb;
+ }
+
+ pAdapter->TxRing.TCBReadyQueueTail = pMpTcb;
+
+ spin_unlock_irqrestore(&pAdapter->TCBReadyQLock, lockflags);
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return status;
+ }
+
+ DBG_ASSERT(pAdapter->TxRing.nBusySend <= NUM_TCB);
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/**
+ * nic_send_packet - NIC specific send handler for version B silicon.
+ * @pAdapter: pointer to our adapter
+ * @pMpTcb: pointer to MP_TCB
+ *
+ * Returns 0 or errno.
+ */
+static int nic_send_packet(struct et131x_adapter *pAdapter, PMP_TCB pMpTcb)
+{
+ uint32_t loopIndex;
+ TX_DESC_ENTRY_t CurDesc[24];
+ uint32_t FragmentNumber = 0;
+ uint32_t iThisCopy, iRemainder;
+ struct sk_buff *pPacket = pMpTcb->Packet;
+ uint32_t FragListCount = skb_shinfo(pPacket)->nr_frags + 1;
+ struct skb_frag_struct *pFragList = &skb_shinfo(pPacket)->frags[0];
+ unsigned long lockflags1, lockflags2;
+
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ /* Part of the optimizations of this send routine restrict us to
+ * sending 24 fragments at a pass. In practice we should never see
+ * more than 5 fragments.
+ *
+ * NOTE: The older version of this function (below) can handle any
+ * number of fragments. If needed, we can call this function,
+ * although it is less efficient.
+ */
+ if (FragListCount > 23) {
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ memset(CurDesc, 0, sizeof(TX_DESC_ENTRY_t) * (FragListCount + 1));
+
+ for (loopIndex = 0; loopIndex < FragListCount; loopIndex++) {
+ /* If there is something in this element, lets get a
+ * descriptor from the ring and get the necessary data
+ */
+ if (loopIndex == 0) {
+ /* If the fragments are smaller than a standard MTU,
+ * then map them to a single descriptor in the Tx
+ * Desc ring. However, if they're larger, as is
+ * possible with support for jumbo packets, then
+ * split them each across 2 descriptors.
+ *
+ * This will work until we determine why the hardware
+ * doesn't seem to like large fragments.
+ */
+ if ((pPacket->len - pPacket->data_len) <= 1514) {
+ DBG_TX(et131x_dbginfo,
+ "Got packet of length %d, "
+ "filling desc entry %d, "
+ "TCB: 0x%p\n",
+ (pPacket->len - pPacket->data_len),
+ pAdapter->TxRing.txDmaReadyToSend.bits.
+ val, pMpTcb);
+
+ CurDesc[FragmentNumber].DataBufferPtrHigh = 0;
+
+ CurDesc[FragmentNumber].word2.bits.
+ length_in_bytes =
+ pPacket->len - pPacket->data_len;
+
+ /* NOTE: Here, the dma_addr_t returned from
+ * pci_map_single() is implicitly cast as a
+ * uint32_t. Although dma_addr_t can be
+ * 64-bit, the address returned by
+ * pci_map_single() is always 32-bit
+ * addressable (as defined by the pci/dma
+ * subsystem)
+ */
+ CurDesc[FragmentNumber++].DataBufferPtrLow =
+ pci_map_single(pAdapter->pdev,
+ pPacket->data,
+ pPacket->len -
+ pPacket->data_len,
+ PCI_DMA_TODEVICE);
+ } else {
+ DBG_TX(et131x_dbginfo,
+ "Got packet of length %d, "
+ "filling desc entry %d, "
+ "TCB: 0x%p\n",
+ (pPacket->len - pPacket->data_len),
+ pAdapter->TxRing.txDmaReadyToSend.bits.
+ val, pMpTcb);
+
+ CurDesc[FragmentNumber].DataBufferPtrHigh = 0;
+
+ CurDesc[FragmentNumber].word2.bits.
+ length_in_bytes =
+ ((pPacket->len - pPacket->data_len) / 2);
+
+ /* NOTE: Here, the dma_addr_t returned from
+ * pci_map_single() is implicitly cast as a
+ * uint32_t. Although dma_addr_t can be
+ * 64-bit, the address returned by
+ * pci_map_single() is always 32-bit
+ * addressable (as defined by the pci/dma
+ * subsystem)
+ */
+ CurDesc[FragmentNumber++].DataBufferPtrLow =
+ pci_map_single(pAdapter->pdev,
+ pPacket->data,
+ ((pPacket->len -
+ pPacket->data_len) / 2),
+ PCI_DMA_TODEVICE);
+ CurDesc[FragmentNumber].DataBufferPtrHigh = 0;
+
+ CurDesc[FragmentNumber].word2.bits.
+ length_in_bytes =
+ ((pPacket->len - pPacket->data_len) / 2);
+
+ /* NOTE: Here, the dma_addr_t returned from
+ * pci_map_single() is implicitly cast as a
+ * uint32_t. Although dma_addr_t can be
+ * 64-bit, the address returned by
+ * pci_map_single() is always 32-bit
+ * addressable (as defined by the pci/dma
+ * subsystem)
+ */
+ CurDesc[FragmentNumber++].DataBufferPtrLow =
+ pci_map_single(pAdapter->pdev,
+ pPacket->data +
+ ((pPacket->len -
+ pPacket->data_len) / 2),
+ ((pPacket->len -
+ pPacket->data_len) / 2),
+ PCI_DMA_TODEVICE);
+ }
+ } else {
+ DBG_TX(et131x_dbginfo,
+ "Got packet of length %d,"
+ "filling desc entry %d\n"
+ "TCB: 0x%p\n",
+ pFragList[loopIndex].size,
+ pAdapter->TxRing.txDmaReadyToSend.bits.val,
+ pMpTcb);
+
+ CurDesc[FragmentNumber].DataBufferPtrHigh = 0;
+
+ CurDesc[FragmentNumber].word2.bits.length_in_bytes =
+ pFragList[loopIndex - 1].size;
+
+ /* NOTE: Here, the dma_addr_t returned from
+ * pci_map_page() is implicitly cast as a uint32_t.
+ * Although dma_addr_t can be 64-bit, the address
+ * returned by pci_map_page() is always 32-bit
+ * addressable (as defined by the pci/dma subsystem)
+ */
+ CurDesc[FragmentNumber++].DataBufferPtrLow =
+ pci_map_page(pAdapter->pdev,
+ pFragList[loopIndex - 1].page,
+ pFragList[loopIndex - 1].page_offset,
+ pFragList[loopIndex - 1].size,
+ PCI_DMA_TODEVICE);
+ }
+ }
+
+ if (FragmentNumber == 0) {
+ DBG_WARNING(et131x_dbginfo, "No. frags is 0\n");
+ return -EIO;
+ }
+
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) {
+ if (++pAdapter->TxRing.TxPacketsSinceLastinterrupt ==
+ pAdapter->RegistryTxNumBuffers) {
+ CurDesc[FragmentNumber - 1].word3.value = 0x5;
+ pAdapter->TxRing.TxPacketsSinceLastinterrupt = 0;
+ } else {
+ CurDesc[FragmentNumber - 1].word3.value = 0x1;
+ }
+ } else {
+ CurDesc[FragmentNumber - 1].word3.value = 0x5;
+ }
+
+ CurDesc[0].word3.bits.f = 1;
+
+ pMpTcb->WrIndexStart = pAdapter->TxRing.txDmaReadyToSend;
+ pMpTcb->PacketStaleCount = 0;
+
+ spin_lock_irqsave(&pAdapter->SendHWLock, lockflags1);
+
+ iThisCopy =
+ NUM_DESC_PER_RING_TX - pAdapter->TxRing.txDmaReadyToSend.bits.val;
+
+ if (iThisCopy >= FragmentNumber) {
+ iRemainder = 0;
+ iThisCopy = FragmentNumber;
+ } else {
+ iRemainder = FragmentNumber - iThisCopy;
+ }
+
+ memcpy(pAdapter->TxRing.pTxDescRingVa +
+ pAdapter->TxRing.txDmaReadyToSend.bits.val, CurDesc,
+ sizeof(TX_DESC_ENTRY_t) * iThisCopy);
+
+ pAdapter->TxRing.txDmaReadyToSend.bits.val += iThisCopy;
+
+ if ((pAdapter->TxRing.txDmaReadyToSend.bits.val == 0) ||
+ (pAdapter->TxRing.txDmaReadyToSend.bits.val ==
+ NUM_DESC_PER_RING_TX)) {
+ if (pAdapter->TxRing.txDmaReadyToSend.bits.wrap) {
+ pAdapter->TxRing.txDmaReadyToSend.value = 0;
+ } else {
+ pAdapter->TxRing.txDmaReadyToSend.value = 0x400;
+ }
+ }
+
+ if (iRemainder) {
+ memcpy(pAdapter->TxRing.pTxDescRingVa,
+ CurDesc + iThisCopy,
+ sizeof(TX_DESC_ENTRY_t) * iRemainder);
+
+ pAdapter->TxRing.txDmaReadyToSend.bits.val += iRemainder;
+ }
+
+ if (pAdapter->TxRing.txDmaReadyToSend.bits.val == 0) {
+ if (pAdapter->TxRing.txDmaReadyToSend.value) {
+ pMpTcb->WrIndex.value = NUM_DESC_PER_RING_TX - 1;
+ } else {
+ pMpTcb->WrIndex.value =
+ 0x400 | (NUM_DESC_PER_RING_TX - 1);
+ }
+ } else {
+ pMpTcb->WrIndex.value =
+ pAdapter->TxRing.txDmaReadyToSend.value - 1;
+ }
+
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags2);
+
+ if (pAdapter->TxRing.CurrSendTail) {
+ pAdapter->TxRing.CurrSendTail->Next = pMpTcb;
+ } else {
+ pAdapter->TxRing.CurrSendHead = pMpTcb;
+ }
+
+ pAdapter->TxRing.CurrSendTail = pMpTcb;
+
+ DBG_ASSERT(pMpTcb->Next == NULL);
+
+ pAdapter->TxRing.nBusySend++;
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags2);
+
+ /* Write the new write pointer back to the device. */
+ writel(pAdapter->TxRing.txDmaReadyToSend.value,
+ &pAdapter->CSRAddress->txdma.service_request.value);
+
+ /* For Gig only, we use Tx Interrupt coalescing. Enable the software
+ * timer to wake us up if this packet isn't followed by N more.
+ */
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) {
+ writel(pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO,
+ &pAdapter->CSRAddress->global.watchdog_timer);
+ }
+
+ spin_unlock_irqrestore(&pAdapter->SendHWLock, lockflags1);
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/*
+ * NOTE: For now, keep this older version of NICSendPacket around for
+ * reference, even though it's not used
+ */
+#if 0
+
+/**
+ * NICSendPacket - NIC specific send handler.
+ * @pAdapter: pointer to our adapter
+ * @pMpTcb: pointer to MP_TCB
+ *
+ * Returns 0 on succes, errno on failure.
+ *
+ * This version of the send routine is designed for version A silicon.
+ * Assumption - Send spinlock has been acquired.
+ */
+static int nic_send_packet(struct et131x_adapter *pAdapter, PMP_TCB pMpTcb)
+{
+ uint32_t loopIndex, fragIndex, loopEnd;
+ uint32_t iSplitFirstElement = 0;
+ uint32_t SegmentSize = 0;
+ TX_DESC_ENTRY_t CurDesc;
+ TX_DESC_ENTRY_t *CurDescPostCopy = NULL;
+ uint32_t SlotsAvailable;
+ DMA10W_t ServiceComplete;
+ unsigned int lockflags1, lockflags2;
+ struct sk_buff *pPacket = pMpTcb->Packet;
+ uint32_t FragListCount = skb_shinfo(pPacket)->nr_frags + 1;
+ struct skb_frag_struct *pFragList = &skb_shinfo(pPacket)->frags[0];
+
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ ServiceComplete.value =
+ readl(&pAdapter->CSRAddress->txdma.NewServiceComplete.value);
+
+ /*
+ * Attempt to fix TWO hardware bugs:
+ * 1) NEVER write an odd number of descriptors.
+ * 2) If packet length is less than NIC_MIN_PACKET_SIZE, then pad the
+ * packet to NIC_MIN_PACKET_SIZE bytes by adding a new last
+ * descriptor IN HALF DUPLEX MODE ONLY
+ * NOTE that (2) interacts with (1). If the packet is less than
+ * NIC_MIN_PACKET_SIZE bytes then we will append a descriptor.
+ * Therefore if it is even now, it will eventually end up odd, and
+ * so will need adjusting.
+ *
+ * VLAN tags get involved since VLAN tags add another one or two
+ * segments.
+ */
+ DBG_TX(et131x_dbginfo,
+ "pMpTcb->PacketLength: %d\n", pMpTcb->PacketLength);
+
+ if ((pAdapter->uiDuplexMode == 0)
+ && (pMpTcb->PacketLength < NIC_MIN_PACKET_SIZE)) {
+ DBG_TX(et131x_dbginfo,
+ "HALF DUPLEX mode AND len < MIN_PKT_SIZE\n");
+ if ((FragListCount & 0x1) == 0) {
+ DBG_TX(et131x_dbginfo,
+ "Even number of descs, split 1st elem\n");
+ iSplitFirstElement = 1;
+ //SegmentSize = pFragList[0].size / 2;
+ SegmentSize = (pPacket->len - pPacket->data_len) / 2;
+ }
+ } else if (FragListCount & 0x1) {
+ DBG_TX(et131x_dbginfo, "Odd number of descs, split 1st elem\n");
+
+ iSplitFirstElement = 1;
+ //SegmentSize = pFragList[0].size / 2;
+ SegmentSize = (pPacket->len - pPacket->data_len) / 2;
+ }
+
+ spin_lock_irqsave(&pAdapter->SendHWLock, lockflags1);
+
+ if (pAdapter->TxRing.txDmaReadyToSend.bits.serv_req_wrap ==
+ ServiceComplete.bits.serv_cpl_wrap) {
+ /* The ring hasn't wrapped. Slots available should be
+ * (RING_SIZE) - the difference between the two pointers.
+ */
+ SlotsAvailable = NUM_DESC_PER_RING_TX -
+ (pAdapter->TxRing.txDmaReadyToSend.bits.serv_req -
+ ServiceComplete.bits.serv_cpl);
+ } else {
+ /* The ring has wrapped. Slots available should be the
+ * difference between the two pointers.
+ */
+ SlotsAvailable = ServiceComplete.bits.serv_cpl -
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req;
+ }
+
+ if ((FragListCount + iSplitFirstElement) > SlotsAvailable) {
+ DBG_WARNING(et131x_dbginfo,
+ "Not Enough Space in Tx Desc Ring\n");
+ spin_unlock_irqrestore(&pAdapter->SendHWLock, lockflags1);
+ return -ENOMEM;
+ }
+
+ loopEnd = (FragListCount) + iSplitFirstElement;
+ fragIndex = 0;
+
+ DBG_TX(et131x_dbginfo,
+ "TCB : 0x%p\n"
+ "Packet (SKB) : 0x%p\t Packet->len: %d\t Packet->data_len: %d\n"
+ "FragListCount : %d\t iSplitFirstElement: %d\t loopEnd:%d\n",
+ pMpTcb,
+ pPacket, pPacket->len, pPacket->data_len,
+ FragListCount, iSplitFirstElement, loopEnd);
+
+ for (loopIndex = 0; loopIndex < loopEnd; loopIndex++) {
+ if (loopIndex > iSplitFirstElement) {
+ fragIndex++;
+ }
+
+ DBG_TX(et131x_dbginfo,
+ "In loop, loopIndex: %d\t fragIndex: %d\n", loopIndex,
+ fragIndex);
+
+ /* If there is something in this element, let's get a
+ * descriptor from the ring and get the necessary data
+ */
+ DBG_TX(et131x_dbginfo,
+ "Packet Length %d,"
+ "filling desc entry %d\n",
+ pPacket->len,
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req);
+
+ // NOTE - Should we do a paranoia check here to make sure the fragment
+ // actually has a length? It's HIGHLY unlikely the fragment would
+ // contain no data...
+ if (1) {
+ // NOTE - Currently always getting 32-bit addrs, and dma_addr_t is
+ // only 32-bit, so leave "high" ptr value out for now
+ CurDesc.DataBufferPtrHigh = 0;
+
+ CurDesc.word2.value = 0;
+ CurDesc.word3.value = 0;
+
+ if (fragIndex == 0) {
+ if (iSplitFirstElement) {
+ DBG_TX(et131x_dbginfo,
+ "Split first element: YES\n");
+
+ if (loopIndex == 0) {
+ DBG_TX(et131x_dbginfo,
+ "Got fragment of length %d, fragIndex: %d\n",
+ pPacket->len -
+ pPacket->data_len,
+ fragIndex);
+ DBG_TX(et131x_dbginfo,
+ "SegmentSize: %d\n",
+ SegmentSize);
+
+ CurDesc.word2.bits.
+ length_in_bytes =
+ SegmentSize;
+ CurDesc.DataBufferPtrLow =
+ pci_map_single(pAdapter->
+ pdev,
+ pPacket->
+ data,
+ SegmentSize,
+ PCI_DMA_TODEVICE);
+ DBG_TX(et131x_dbginfo,
+ "pci_map_single() returns: 0x%08x\n",
+ CurDesc.
+ DataBufferPtrLow);
+ } else {
+ DBG_TX(et131x_dbginfo,
+ "Got fragment of length %d, fragIndex: %d\n",
+ pPacket->len -
+ pPacket->data_len,
+ fragIndex);
+ DBG_TX(et131x_dbginfo,
+ "Leftover Size: %d\n",
+ (pPacket->len -
+ pPacket->data_len -
+ SegmentSize));
+
+ CurDesc.word2.bits.
+ length_in_bytes =
+ ((pPacket->len -
+ pPacket->data_len) -
+ SegmentSize);
+ CurDesc.DataBufferPtrLow =
+ pci_map_single(pAdapter->
+ pdev,
+ (pPacket->
+ data +
+ SegmentSize),
+ (pPacket->
+ len -
+ pPacket->
+ data_len -
+ SegmentSize),
+ PCI_DMA_TODEVICE);
+ DBG_TX(et131x_dbginfo,
+ "pci_map_single() returns: 0x%08x\n",
+ CurDesc.
+ DataBufferPtrLow);
+ }
+ } else {
+ DBG_TX(et131x_dbginfo,
+ "Split first element: NO\n");
+
+ CurDesc.word2.bits.length_in_bytes =
+ pPacket->len - pPacket->data_len;
+
+ CurDesc.DataBufferPtrLow =
+ pci_map_single(pAdapter->pdev,
+ pPacket->data,
+ (pPacket->len -
+ pPacket->data_len),
+ PCI_DMA_TODEVICE);
+ DBG_TX(et131x_dbginfo,
+ "pci_map_single() returns: 0x%08x\n",
+ CurDesc.DataBufferPtrLow);
+ }
+ } else {
+
+ CurDesc.word2.bits.length_in_bytes =
+ pFragList[fragIndex - 1].size;
+ CurDesc.DataBufferPtrLow =
+ pci_map_page(pAdapter->pdev,
+ pFragList[fragIndex - 1].page,
+ pFragList[fragIndex -
+ 1].page_offset,
+ pFragList[fragIndex - 1].size,
+ PCI_DMA_TODEVICE);
+ DBG_TX(et131x_dbginfo,
+ "pci_map_page() returns: 0x%08x\n",
+ CurDesc.DataBufferPtrLow);
+ }
+
+ if (loopIndex == 0) {
+ /* This is the first descriptor of the packet
+ *
+ * Set the "f" bit to indicate this is the
+ * first descriptor in the packet.
+ */
+ DBG_TX(et131x_dbginfo,
+ "This is our FIRST descriptor\n");
+ CurDesc.word3.bits.f = 1;
+
+ pMpTcb->WrIndexStart =
+ pAdapter->TxRing.txDmaReadyToSend;
+ }
+
+ if ((loopIndex == (loopEnd - 1)) &&
+ (pAdapter->uiDuplexMode ||
+ (pMpTcb->PacketLength >= NIC_MIN_PACKET_SIZE))) {
+ /* This is the Last descriptor of the packet */
+ DBG_TX(et131x_dbginfo,
+ "THIS is our LAST descriptor\n");
+
+ if (pAdapter->uiLinkSpeed ==
+ TRUEPHY_SPEED_1000MBPS) {
+ if (++pAdapter->TxRing.
+ TxPacketsSinceLastinterrupt >=
+ pAdapter->RegistryTxNumBuffers) {
+ CurDesc.word3.value = 0x5;
+ pAdapter->TxRing.
+ TxPacketsSinceLastinterrupt
+ = 0;
+ } else {
+ CurDesc.word3.value = 0x1;
+ }
+ } else {
+ CurDesc.word3.value = 0x5;
+ }
+
+ /* Following index will be used during freeing
+ * of packet
+ */
+ pMpTcb->WrIndex =
+ pAdapter->TxRing.txDmaReadyToSend;
+ pMpTcb->PacketStaleCount = 0;
+ }
+
+ /* Copy the descriptor (filled above) into the
+ * descriptor ring at the next free entry. Advance
+ * the "next free entry" variable
+ */
+ memcpy(pAdapter->TxRing.pTxDescRingVa +
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req,
+ &CurDesc, sizeof(TX_DESC_ENTRY_t));
+
+ CurDescPostCopy =
+ pAdapter->TxRing.pTxDescRingVa +
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req;
+
+ DBG_TX(et131x_dbginfo,
+ "CURRENT DESCRIPTOR\n"
+ "\tAddress : 0x%p\n"
+ "\tDataBufferPtrHigh : 0x%08x\n"
+ "\tDataBufferPtrLow : 0x%08x\n"
+ "\tword2 : 0x%08x\n"
+ "\tword3 : 0x%08x\n",
+ CurDescPostCopy,
+ CurDescPostCopy->DataBufferPtrHigh,
+ CurDescPostCopy->DataBufferPtrLow,
+ CurDescPostCopy->word2.value,
+ CurDescPostCopy->word3.value);
+
+ if (++pAdapter->TxRing.txDmaReadyToSend.bits.serv_req >=
+ NUM_DESC_PER_RING_TX) {
+ if (pAdapter->TxRing.txDmaReadyToSend.bits.
+ serv_req_wrap) {
+ pAdapter->TxRing.txDmaReadyToSend.
+ value = 0;
+ } else {
+ pAdapter->TxRing.txDmaReadyToSend.
+ value = 0x400;
+ }
+ }
+ }
+ }
+
+ if (pAdapter->uiDuplexMode == 0 &&
+ pMpTcb->PacketLength < NIC_MIN_PACKET_SIZE) {
+ // NOTE - Same 32/64-bit issue as above...
+ CurDesc.DataBufferPtrHigh = 0x0;
+ CurDesc.DataBufferPtrLow = pAdapter->TxRing.pTxDummyBlkPa;
+ CurDesc.word2.value = 0;
+
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) {
+ if (++pAdapter->TxRing.TxPacketsSinceLastinterrupt >=
+ pAdapter->RegistryTxNumBuffers) {
+ CurDesc.word3.value = 0x5;
+ pAdapter->TxRing.TxPacketsSinceLastinterrupt =
+ 0;
+ } else {
+ CurDesc.word3.value = 0x1;
+ }
+ } else {
+ CurDesc.word3.value = 0x5;
+ }
+
+ CurDesc.word2.bits.length_in_bytes =
+ NIC_MIN_PACKET_SIZE - pMpTcb->PacketLength;
+
+ pMpTcb->WrIndex = pAdapter->TxRing.txDmaReadyToSend;
+
+ memcpy(pAdapter->TxRing.pTxDescRingVa +
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req,
+ &CurDesc, sizeof(TX_DESC_ENTRY_t));
+
+ CurDescPostCopy =
+ pAdapter->TxRing.pTxDescRingVa +
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req;
+
+ DBG_TX(et131x_dbginfo,
+ "CURRENT DESCRIPTOR\n"
+ "\tAddress : 0x%p\n"
+ "\tDataBufferPtrHigh : 0x%08x\n"
+ "\tDataBufferPtrLow : 0x%08x\n"
+ "\tword2 : 0x%08x\n"
+ "\tword3 : 0x%08x\n",
+ CurDescPostCopy,
+ CurDescPostCopy->DataBufferPtrHigh,
+ CurDescPostCopy->DataBufferPtrLow,
+ CurDescPostCopy->word2.value,
+ CurDescPostCopy->word3.value);
+
+ if (++pAdapter->TxRing.txDmaReadyToSend.bits.serv_req >=
+ NUM_DESC_PER_RING_TX) {
+ if (pAdapter->TxRing.txDmaReadyToSend.bits.
+ serv_req_wrap) {
+ pAdapter->TxRing.txDmaReadyToSend.value = 0;
+ } else {
+ pAdapter->TxRing.txDmaReadyToSend.value = 0x400;
+ }
+ }
+
+ DBG_TX(et131x_dbginfo, "Padding descriptor %d by %d bytes\n",
+ //pAdapter->TxRing.txDmaReadyToSend.value,
+ pAdapter->TxRing.txDmaReadyToSend.bits.serv_req,
+ NIC_MIN_PACKET_SIZE - pMpTcb->PacketLength);
+ }
+
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags2);
+
+ if (pAdapter->TxRing.CurrSendTail) {
+ pAdapter->TxRing.CurrSendTail->Next = pMpTcb;
+ } else {
+ pAdapter->TxRing.CurrSendHead = pMpTcb;
+ }
+
+ pAdapter->TxRing.CurrSendTail = pMpTcb;
+
+ DBG_ASSERT(pMpTcb->Next == NULL);
+
+ pAdapter->TxRing.nBusySend++;
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags2);
+
+ /* Write the new write pointer back to the device. */
+ writel(pAdapter->TxRing.txDmaReadyToSend.value,
+ &pAdapter->CSRAddress->txdma.service_request.value);
+
+#ifdef CONFIG_ET131X_DEBUG
+ DumpDeviceBlock(DBG_TX_ON, pAdapter, 1);
+#endif
+
+ /* For Gig only, we use Tx Interrupt coalescing. Enable the software
+ * timer to wake us up if this packet isn't followed by N more.
+ */
+ if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) {
+ writel(pAdapter->RegistryTxTimeInterval * NANO_IN_A_MICRO,
+ &pAdapter->CSRAddress->global.watchdog_timer);
+ }
+
+ spin_unlock_irqrestore(&pAdapter->SendHWLock, lockflags1);
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+#endif
+
+/**
+ * et131x_free_send_packet - Recycle a MP_TCB, complete the packet if necessary
+ * @pAdapter: pointer to our adapter
+ * @pMpTcb: pointer to MP_TCB
+ *
+ * Assumption - Send spinlock has been acquired
+ */
+__inline void et131x_free_send_packet(struct et131x_adapter *pAdapter, PMP_TCB pMpTcb)
+{
+ unsigned long lockflags;
+ TX_DESC_ENTRY_t *desc = NULL;
+ struct net_device_stats *stats = &pAdapter->net_stats;
+
+ if (MP_TEST_FLAG(pMpTcb, fMP_DEST_BROAD)) {
+ atomic_inc(&pAdapter->Stats.brdcstxmt);
+ } else if (MP_TEST_FLAG(pMpTcb, fMP_DEST_MULTI)) {
+ atomic_inc(&pAdapter->Stats.multixmt);
+ } else {
+ atomic_inc(&pAdapter->Stats.unixmt);
+ }
+
+ if (pMpTcb->Packet) {
+ stats->tx_bytes += pMpTcb->Packet->len;
+
+ /* Iterate through the TX descriptors on the ring
+ * corresponding to this packet and umap the fragments
+ * they point to
+ */
+ DBG_TX(et131x_dbginfo,
+ "Unmap descriptors Here\n"
+ "TCB : 0x%p\n"
+ "TCB Next : 0x%p\n"
+ "TCB PacketLength : %d\n"
+ "TCB WrIndex.value : 0x%08x\n"
+ "TCB WrIndex.bits.val : %d\n"
+ "TCB WrIndex.value : 0x%08x\n"
+ "TCB WrIndex.bits.val : %d\n",
+ pMpTcb,
+ pMpTcb->Next,
+ pMpTcb->PacketLength,
+ pMpTcb->WrIndexStart.value,
+ pMpTcb->WrIndexStart.bits.val,
+ pMpTcb->WrIndex.value,
+ pMpTcb->WrIndex.bits.val);
+
+ do {
+ desc =
+ (TX_DESC_ENTRY_t *) (pAdapter->TxRing.
+ pTxDescRingVa +
+ pMpTcb->WrIndexStart.bits.val);
+
+ DBG_TX(et131x_dbginfo,
+ "CURRENT DESCRIPTOR\n"
+ "\tAddress : 0x%p\n"
+ "\tDataBufferPtrHigh : 0x%08x\n"
+ "\tDataBufferPtrLow : 0x%08x\n"
+ "\tword2 : 0x%08x\n"
+ "\tword3 : 0x%08x\n",
+ desc,
+ desc->DataBufferPtrHigh,
+ desc->DataBufferPtrLow,
+ desc->word2.value,
+ desc->word3.value);
+
+ pci_unmap_single(pAdapter->pdev,
+ desc->DataBufferPtrLow,
+ desc->word2.value, PCI_DMA_TODEVICE);
+
+ if (++pMpTcb->WrIndexStart.bits.val >=
+ NUM_DESC_PER_RING_TX) {
+ if (pMpTcb->WrIndexStart.bits.wrap) {
+ pMpTcb->WrIndexStart.value = 0;
+ } else {
+ pMpTcb->WrIndexStart.value = 0x400;
+ }
+ }
+ }
+ while (desc != (pAdapter->TxRing.pTxDescRingVa +
+ pMpTcb->WrIndex.bits.val));
+
+ DBG_TX(et131x_dbginfo,
+ "Free Packet (SKB) : 0x%p\n", pMpTcb->Packet);
+
+ dev_kfree_skb_any(pMpTcb->Packet);
+ }
+
+ memset(pMpTcb, 0, sizeof(MP_TCB));
+
+ /* Add the TCB to the Ready Q */
+ spin_lock_irqsave(&pAdapter->TCBReadyQLock, lockflags);
+
+ pAdapter->Stats.opackets++;
+
+ if (pAdapter->TxRing.TCBReadyQueueTail) {
+ pAdapter->TxRing.TCBReadyQueueTail->Next = pMpTcb;
+ } else {
+ /* Apparently ready Q is empty. */
+ pAdapter->TxRing.TCBReadyQueueHead = pMpTcb;
+ }
+
+ pAdapter->TxRing.TCBReadyQueueTail = pMpTcb;
+
+ spin_unlock_irqrestore(&pAdapter->TCBReadyQLock, lockflags);
+
+ DBG_ASSERT(pAdapter->TxRing.nBusySend >= 0);
+}
+
+/**
+ * et131x_free_busy_send_packets - Free and complete the stopped active sends
+ * @pAdapter: pointer to our adapter
+ *
+ * Assumption - Send spinlock has been acquired
+ */
+void et131x_free_busy_send_packets(struct et131x_adapter *pAdapter)
+{
+ PMP_TCB pMpTcb;
+ struct list_head *pEntry;
+ struct sk_buff *pPacket = NULL;
+ unsigned long lockflags;
+ uint32_t FreeCounter = 0;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ while (!list_empty(&pAdapter->TxRing.SendWaitQueue)) {
+ spin_lock_irqsave(&pAdapter->SendWaitLock, lockflags);
+
+ pAdapter->TxRing.nWaitSend--;
+ spin_unlock_irqrestore(&pAdapter->SendWaitLock, lockflags);
+
+ pEntry = pAdapter->TxRing.SendWaitQueue.next;
+
+ pPacket = NULL;
+ }
+
+ pAdapter->TxRing.nWaitSend = 0;
+
+ /* Any packets being sent? Check the first TCB on the send list */
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+
+ while ((pMpTcb != NULL) && (FreeCounter < NUM_TCB)) {
+ PMP_TCB pNext = pMpTcb->Next;
+
+ pAdapter->TxRing.CurrSendHead = pNext;
+
+ if (pNext == NULL) {
+ pAdapter->TxRing.CurrSendTail = NULL;
+ }
+
+ pAdapter->TxRing.nBusySend--;
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+
+ DBG_VERBOSE(et131x_dbginfo, "pMpTcb = 0x%p\n", pMpTcb);
+
+ FreeCounter++;
+ MP_FREE_SEND_PACKET_FUN(pAdapter, pMpTcb);
+
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+ }
+
+ if (FreeCounter == NUM_TCB) {
+ DBG_ERROR(et131x_dbginfo,
+ "MpFreeBusySendPackets exitted loop for a bad reason\n");
+ BUG();
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+
+ pAdapter->TxRing.nBusySend = 0;
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_handle_send_interrupt - Interrupt handler for sending processing
+ * @pAdapter: pointer to our adapter
+ *
+ * Re-claim the send resources, complete sends and get more to send from
+ * the send wait queue.
+ *
+ * Assumption - Send spinlock has been acquired
+ */
+void et131x_handle_send_interrupt(struct et131x_adapter *pAdapter)
+{
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ /* Mark as completed any packets which have been sent by the device. */
+ et131x_update_tcb_list(pAdapter);
+
+ /* If we queued any transmits because we didn't have any TCBs earlier,
+ * dequeue and send those packets now, as long as we have free TCBs.
+ */
+ et131x_check_send_wait_list(pAdapter);
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_update_tcb_list - Helper routine for Send Interrupt handler
+ * @pAdapter: pointer to our adapter
+ *
+ * Re-claims the send resources and completes sends. Can also be called as
+ * part of the NIC send routine when the "ServiceComplete" indication has
+ * wrapped.
+ */
+static void et131x_update_tcb_list(struct et131x_adapter *pAdapter)
+{
+ unsigned long lockflags;
+ DMA10W_t ServiceComplete;
+ PMP_TCB pMpTcb;
+
+ ServiceComplete.value =
+ readl(&pAdapter->CSRAddress->txdma.NewServiceComplete.value);
+
+ /* Has the ring wrapped? Process any descriptors that do not have
+ * the same "wrap" indicator as the current completion indicator
+ */
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+ while (pMpTcb &&
+ ServiceComplete.bits.wrap != pMpTcb->WrIndex.bits.wrap &&
+ ServiceComplete.bits.val < pMpTcb->WrIndex.bits.val) {
+ pAdapter->TxRing.nBusySend--;
+ pAdapter->TxRing.CurrSendHead = pMpTcb->Next;
+ if (pMpTcb->Next == NULL) {
+ pAdapter->TxRing.CurrSendTail = NULL;
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+ MP_FREE_SEND_PACKET_FUN(pAdapter, pMpTcb);
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ /* Goto the next packet */
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+ }
+ while (pMpTcb &&
+ ServiceComplete.bits.wrap == pMpTcb->WrIndex.bits.wrap &&
+ ServiceComplete.bits.val > pMpTcb->WrIndex.bits.val) {
+ pAdapter->TxRing.nBusySend--;
+ pAdapter->TxRing.CurrSendHead = pMpTcb->Next;
+ if (pMpTcb->Next == NULL) {
+ pAdapter->TxRing.CurrSendTail = NULL;
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+ MP_FREE_SEND_PACKET_FUN(pAdapter, pMpTcb);
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ /* Goto the next packet */
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+ }
+
+ /* Wake up the queue when we hit a low-water mark */
+ if (pAdapter->TxRing.nBusySend <= (NUM_TCB / 3)) {
+ netif_wake_queue(pAdapter->netdev);
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+}
+
+/**
+ * et131x_check_send_wait_list - Helper routine for the interrupt handler
+ * @pAdapter: pointer to our adapter
+ *
+ * Takes packets from the send wait queue and posts them to the device (if
+ * room available).
+ */
+static void et131x_check_send_wait_list(struct et131x_adapter *pAdapter)
+{
+ unsigned long lockflags;
+
+ spin_lock_irqsave(&pAdapter->SendWaitLock, lockflags);
+
+ while (!list_empty(&pAdapter->TxRing.SendWaitQueue) &&
+ MP_TCB_RESOURCES_AVAILABLE(pAdapter)) {
+ struct list_head *pEntry;
+
+ DBG_VERBOSE(et131x_dbginfo, "Tx packets on the wait queue\n");
+
+ pEntry = pAdapter->TxRing.SendWaitQueue.next;
+
+ pAdapter->TxRing.nWaitSend--;
+
+ DBG_WARNING(et131x_dbginfo,
+ "MpHandleSendInterrupt - sent a queued pkt. Waiting %d\n",
+ pAdapter->TxRing.nWaitSend);
+ }
+
+ spin_unlock_irqrestore(&pAdapter->SendWaitLock, lockflags);
+}
diff --git a/drivers/staging/et131x/et1310_tx.h b/drivers/staging/et131x/et1310_tx.h
new file mode 100644
index 00000000000..2819c7843d2
--- /dev/null
+++ b/drivers/staging/et131x/et1310_tx.h
@@ -0,0 +1,242 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et1310_tx.h - Defines, structs, enums, prototypes, etc. pertaining to data
+ * transmission.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET1310_TX_H__
+#define __ET1310_TX_H__
+
+
+/* Typedefs for Tx Descriptor Ring */
+
+/*
+ * TXDESC_WORD2_t structure holds part of the control bits in the Tx Descriptor
+ * ring for the ET-1310
+ */
+typedef union _txdesc_word2_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 vlan_prio:3; // bits 29-31(VLAN priority)
+ u32 vlan_cfi:1; // bit 28(cfi)
+ u32 vlan_tag:12; // bits 16-27(VLAN tag)
+ u32 length_in_bytes:16; // bits 0-15(packet length)
+#else
+ u32 length_in_bytes:16; // bits 0-15(packet length)
+ u32 vlan_tag:12; // bits 16-27(VLAN tag)
+ u32 vlan_cfi:1; // bit 28(cfi)
+ u32 vlan_prio:3; // bits 29-31(VLAN priority)
+#endif /* _BIT_FIELDS_HTOL */
+ } bits;
+} TXDESC_WORD2_t, *PTXDESC_WORD2_t;
+
+/*
+ * TXDESC_WORD3_t structure holds part of the control bits in the Tx Descriptor
+ * ring for the ET-1310
+ */
+typedef union _txdesc_word3_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:17; // bits 15-31
+ u32 udpa:1; // bit 14(UDP checksum assist)
+ u32 tcpa:1; // bit 13(TCP checksum assist)
+ u32 ipa:1; // bit 12(IP checksum assist)
+ u32 vlan:1; // bit 11(append VLAN tag)
+ u32 hp:1; // bit 10(Packet is a Huge packet)
+ u32 pp:1; // bit 9(pad packet)
+ u32 mac:1; // bit 8(MAC override)
+ u32 crc:1; // bit 7(append CRC)
+ u32 e:1; // bit 6(Tx frame has error)
+ u32 pf:1; // bit 5(send pause frame)
+ u32 bp:1; // bit 4(Issue half-duplex backpressure (XON/XOFF)
+ u32 cw:1; // bit 3(Control word - no packet data)
+ u32 ir:1; // bit 2(interrupt the processor when this pkt sent)
+ u32 f:1; // bit 1(first packet in the sequence)
+ u32 l:1; // bit 0(last packet in the sequence)
+#else
+ u32 l:1; // bit 0(last packet in the sequence)
+ u32 f:1; // bit 1(first packet in the sequence)
+ u32 ir:1; // bit 2(interrupt the processor when this pkt sent)
+ u32 cw:1; // bit 3(Control word - no packet data)
+ u32 bp:1; // bit 4(Issue half-duplex backpressure (XON/XOFF)
+ u32 pf:1; // bit 5(send pause frame)
+ u32 e:1; // bit 6(Tx frame has error)
+ u32 crc:1; // bit 7(append CRC)
+ u32 mac:1; // bit 8(MAC override)
+ u32 pp:1; // bit 9(pad packet)
+ u32 hp:1; // bit 10(Packet is a Huge packet)
+ u32 vlan:1; // bit 11(append VLAN tag)
+ u32 ipa:1; // bit 12(IP checksum assist)
+ u32 tcpa:1; // bit 13(TCP checksum assist)
+ u32 udpa:1; // bit 14(UDP checksum assist)
+ u32 unused:17; // bits 15-31
+#endif /* _BIT_FIELDS_HTOL */
+ } bits;
+} TXDESC_WORD3_t, *PTXDESC_WORD3_t;
+
+/* TX_DESC_ENTRY_t is sructure representing each descriptor on the ring */
+typedef struct _tx_desc_entry_t {
+ u32 DataBufferPtrHigh;
+ u32 DataBufferPtrLow;
+ TXDESC_WORD2_t word2; // control words how to xmit the
+ TXDESC_WORD3_t word3; // data (detailed above)
+} TX_DESC_ENTRY_t, *PTX_DESC_ENTRY_t;
+
+
+/* Typedefs for Tx DMA engine status writeback */
+
+/*
+ * TX_STATUS_BLOCK_t is sructure representing the status of the Tx DMA engine
+ * it sits in free memory, and is pointed to by 0x101c / 0x1020
+ */
+typedef union _tx_status_block_t {
+ u32 value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ u32 unused:21; // bits 11-31
+ u32 serv_cpl_wrap:1; // bit 10
+ u32 serv_cpl:10; // bits 0-9
+#else
+ u32 serv_cpl:10; // bits 0-9
+ u32 serv_cpl_wrap:1; // bit 10
+ u32 unused:21; // bits 11-31
+#endif
+ } bits;
+} TX_STATUS_BLOCK_t, *PTX_STATUS_BLOCK_t;
+
+/* TCB (Transmit Control Block) */
+typedef struct _MP_TCB {
+ struct _MP_TCB *Next;
+ u32 Flags;
+ u32 Count;
+ u32 PacketStaleCount;
+ struct sk_buff *Packet;
+ u32 PacketLength;
+ DMA10W_t WrIndex;
+ DMA10W_t WrIndexStart;
+} MP_TCB, *PMP_TCB;
+
+/* Structure to hold the skb's in a list */
+typedef struct tx_skb_list_elem {
+ struct list_head skb_list_elem;
+ struct sk_buff *skb;
+} TX_SKB_LIST_ELEM, *PTX_SKB_LIST_ELEM;
+
+/* TX_RING_t is sructure representing our local reference(s) to the ring */
+typedef struct _tx_ring_t {
+ /* TCB (Transmit Control Block) memory and lists */
+ PMP_TCB MpTcbMem;
+
+ /* List of TCBs that are ready to be used */
+ PMP_TCB TCBReadyQueueHead;
+ PMP_TCB TCBReadyQueueTail;
+
+ /* list of TCBs that are currently being sent. NOTE that access to all
+ * three of these (including nBusySend) are controlled via the
+ * TCBSendQLock. This lock should be secured prior to incementing /
+ * decrementing nBusySend, or any queue manipulation on CurrSendHead /
+ * Tail
+ */
+ PMP_TCB CurrSendHead;
+ PMP_TCB CurrSendTail;
+ int32_t nBusySend;
+
+ /* List of packets (not TCBs) that were queued for lack of resources */
+ struct list_head SendWaitQueue;
+ int32_t nWaitSend;
+
+ /* The actual descriptor ring */
+ PTX_DESC_ENTRY_t pTxDescRingVa;
+ dma_addr_t pTxDescRingPa;
+ uint64_t pTxDescRingAdjustedPa;
+ uint64_t TxDescOffset;
+
+ /* ReadyToSend indicates where we last wrote to in the descriptor ring. */
+ DMA10W_t txDmaReadyToSend;
+
+ /* The location of the write-back status block */
+ PTX_STATUS_BLOCK_t pTxStatusVa;
+ dma_addr_t pTxStatusPa;
+
+ /* A Block of zeroes used to pad packets that are less than 60 bytes */
+ void *pTxDummyBlkVa;
+ dma_addr_t pTxDummyBlkPa;
+
+ TXMAC_ERR_t TxMacErr;
+
+ /* Variables to track the Tx interrupt coalescing features */
+ int32_t TxPacketsSinceLastinterrupt;
+} TX_RING_t, *PTX_RING_t;
+
+/* Forward declaration of the frag-list for the following prototypes */
+typedef struct _MP_FRAG_LIST MP_FRAG_LIST, *PMP_FRAG_LIST;
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+/* PROTOTYPES for et1310_tx.c */
+int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_tx_dma_memory_free(struct et131x_adapter *adapter);
+void ConfigTxDmaRegs(struct et131x_adapter *pAdapter);
+void et131x_init_send(struct et131x_adapter *adapter);
+void et131x_tx_dma_disable(struct et131x_adapter *pAdapter);
+void et131x_tx_dma_enable(struct et131x_adapter *pAdapter);
+void et131x_handle_send_interrupt(struct et131x_adapter *pAdapter);
+void et131x_free_busy_send_packets(struct et131x_adapter *pAdapter);
+int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev);
+
+#endif /* __ET1310_TX_H__ */
diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h
new file mode 100644
index 00000000000..36e61a47ae2
--- /dev/null
+++ b/drivers/staging/et131x/et131x_adapter.h
@@ -0,0 +1,347 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_adapter.h - Header which includes the private adapter structure, along
+ * with related support structures, macros, definitions, etc.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_ADAPTER_H__
+#define __ET131X_ADAPTER_H__
+
+#include "et1310_address_map.h"
+#include "et1310_tx.h"
+#include "et1310_rx.h"
+
+/*
+ * Do not change these values: if changed, then change also in respective
+ * TXdma and Rxdma engines
+ */
+#define NUM_DESC_PER_RING_TX 512 // TX Do not change these values
+#define NUM_TCB 64
+
+/*
+ * These values are all superseded by registry entries to facilitate tuning.
+ * Once the desired performance has been achieved, the optimal registry values
+ * should be re-populated to these #defines:
+ */
+#define NUM_TRAFFIC_CLASSES 1
+
+/*
+ * There are three ways of counting errors - if there are more than X errors
+ * in Y packets (represented by the "SAMPLE" macros), if there are more than
+ * N errors in a S mSec time period (the "PERIOD" macros), or if there are
+ * consecutive packets with errors (CONSEC_ERRORED_THRESH). This last covers
+ * for "Bursty" errors, and the errored packets may well not be contiguous,
+ * but several errors where the packet counter has changed by less than a
+ * small amount will cause this count to increment.
+ */
+#define TX_PACKETS_IN_SAMPLE 10000
+#define TX_MAX_ERRORS_IN_SAMPLE 50
+
+#define TX_ERROR_PERIOD 1000
+#define TX_MAX_ERRORS_IN_PERIOD 10
+
+#define LINK_DETECTION_TIMER 5000
+
+#define TX_CONSEC_RANGE 5
+#define TX_CONSEC_ERRORED_THRESH 10
+
+#define LO_MARK_PERCENT_FOR_PSR 15
+#define LO_MARK_PERCENT_FOR_RX 15
+
+/* Macros for flag and ref count operations */
+#define MP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F))
+#define MP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F))
+#define MP_CLEAR_FLAGS(_M) ((_M)->Flags = 0)
+#define MP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0)
+#define MP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F))
+#define MP_IS_FLAG_CLEAR(_M, _F) (((_M)->Flags & (_F)) == 0)
+
+#define MP_INC_RCV_REF(_A) atomic_inc(&(_A)->RcvRefCount)
+#define MP_DEC_RCV_REF(_A) atomic_dec(&(_A)->RcvRefCount)
+#define MP_GET_RCV_REF(_A) atomic_read(&(_A)->RcvRefCount)
+
+/* Macros specific to the private adapter structure */
+#define MP_TCB_RESOURCES_AVAILABLE(_M) ((_M)->TxRing.nBusySend < NUM_TCB)
+#define MP_TCB_RESOURCES_NOT_AVAILABLE(_M) ((_M)->TxRing.nBusySend >= NUM_TCB)
+
+#define MP_SHOULD_FAIL_SEND(_M) ((_M)->Flags & fMP_ADAPTER_FAIL_SEND_MASK)
+#define MP_IS_NOT_READY(_M) ((_M)->Flags & fMP_ADAPTER_NOT_READY_MASK)
+#define MP_IS_READY(_M) !((_M)->Flags & fMP_ADAPTER_NOT_READY_MASK)
+
+#define MP_HAS_CABLE(_M) !((_M)->Flags & fMP_ADAPTER_NO_CABLE)
+#define MP_LINK_DETECTED(_M) !((_M)->Flags & fMP_ADAPTER_LINK_DETECTION)
+
+/* Counters for error rate monitoring */
+typedef struct _MP_ERR_COUNTERS {
+ u32 PktCountTxPackets;
+ u32 PktCountTxErrors;
+ u32 TimerBasedTxErrors;
+ u32 PktCountLastError;
+ u32 ErredConsecPackets;
+} MP_ERR_COUNTERS, *PMP_ERR_COUNTERS;
+
+/* RFD (Receive Frame Descriptor) */
+typedef struct _MP_RFD {
+ struct list_head list_node;
+ struct sk_buff *Packet;
+ u32 PacketSize; // total size of receive frame
+ u16 iBufferIndex;
+ u8 iRingIndex;
+} MP_RFD, *PMP_RFD;
+
+/* Enum for Flow Control */
+typedef enum _eflow_control_t {
+ Both = 0,
+ TxOnly = 1,
+ RxOnly = 2,
+ None = 3
+} eFLOW_CONTROL_t, *PeFLOW_CONTROL_t;
+
+/* Struct to define some device statistics */
+typedef struct _ce_stats_t {
+ /* Link Input/Output stats */
+ uint64_t ipackets; // # of in packets
+ uint64_t opackets; // # of out packets
+
+ /* MIB II variables
+ *
+ * NOTE: atomic_t types are only guaranteed to store 24-bits; if we
+ * MUST have 32, then we'll need another way to perform atomic
+ * operations
+ */
+ u32 unircv; // # multicast packets received
+ atomic_t unixmt; // # multicast packets for Tx
+ u32 multircv; // # multicast packets received
+ atomic_t multixmt; // # multicast packets for Tx
+ u32 brdcstrcv; // # broadcast packets received
+ atomic_t brdcstxmt; // # broadcast packets for Tx
+ u32 norcvbuf; // # Rx packets discarded
+ u32 noxmtbuf; // # Tx packets discarded
+
+ /* Transciever state informations. */
+ u8 xcvr_addr;
+ u32 xcvr_id;
+
+ /* Tx Statistics. */
+ u32 tx_uflo; // Tx Underruns
+
+ u32 collisions;
+ u32 excessive_collisions;
+ u32 first_collision;
+ u32 late_collisions;
+ u32 max_pkt_error;
+ u32 tx_deferred;
+
+ /* Rx Statistics. */
+ u32 rx_ov_flow; // Rx Over Flow
+
+ u32 length_err;
+ u32 alignment_err;
+ u32 crc_err;
+ u32 code_violations;
+ u32 other_errors;
+
+#ifdef CONFIG_ET131X_DEBUG
+ u32 UnhandledInterruptsPerSec;
+ u32 RxDmaInterruptsPerSec;
+ u32 TxDmaInterruptsPerSec;
+ u32 WatchDogInterruptsPerSec;
+#endif /* CONFIG_ET131X_DEBUG */
+
+ u32 SynchrounousIterations;
+ INTERRUPT_t InterruptStatus;
+} CE_STATS_t, *PCE_STATS_t;
+
+/* The private adapter structure */
+struct et131x_adapter {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+
+ struct work_struct task;
+
+ /* Flags that indicate current state of the adapter */
+ u32 Flags;
+ u32 HwErrCount;
+
+ /* Configuration */
+ u8 PermanentAddress[ETH_ALEN];
+ u8 CurrentAddress[ETH_ALEN];
+ bool bOverrideAddress;
+ bool bEepromPresent;
+ u8 eepromData[2];
+
+ /* Spinlocks */
+ spinlock_t Lock;
+
+ spinlock_t TCBSendQLock;
+ spinlock_t TCBReadyQLock;
+ spinlock_t SendHWLock;
+ spinlock_t SendWaitLock;
+
+ spinlock_t RcvLock;
+ spinlock_t RcvPendLock;
+ spinlock_t FbrLock;
+
+ spinlock_t PHYLock;
+
+ /* Packet Filter and look ahead size */
+ u32 PacketFilter;
+ u32 ulLookAhead;
+ u32 uiLinkSpeed;
+ u32 uiDuplexMode;
+ u32 uiAutoNegStatus;
+ u8 ucLinkStatus;
+
+ /* multicast list */
+ u32 MCAddressCount;
+ u8 MCList[NIC_MAX_MCAST_LIST][ETH_ALEN];
+
+ /* MAC test */
+ TXMAC_TXTEST_t TxMacTest;
+
+ /* Pointer to the device's PCI register space */
+ ADDRESS_MAP_t __iomem *CSRAddress;
+
+ /* PCI config space info, for debug purposes only. */
+ u8 RevisionID;
+ u16 VendorID;
+ u16 DeviceID;
+ u16 SubVendorID;
+ u16 SubSystemID;
+ u32 CacheFillSize;
+ u16 PciXDevCtl;
+ u8 pci_lat_timer;
+ u8 pci_hdr_type;
+ u8 pci_bist;
+ u32 pci_cfg_state[64 / sizeof(u32)];
+
+ /* Registry parameters */
+ u8 SpeedDuplex; // speed/duplex
+ eFLOW_CONTROL_t RegistryFlowControl; // for 802.3x flow control
+ u8 RegistryWOLMatch; // Enable WOL pattern-matching
+ u8 RegistryWOLLink; // Link state change is independant
+ u8 RegistryPhyComa; // Phy Coma mode enable/disable
+
+ u32 RegistryRxMemEnd; // Size of internal rx memory
+ u8 RegistryMACStat; // If set, read MACSTAT, else don't
+ u32 RegistryVlanTag; // 802.1q Vlan TAG
+ u32 RegistryJumboPacket; // Max supported ethernet packet size
+
+ u32 RegistryTxNumBuffers;
+ u32 RegistryTxTimeInterval;
+
+ u32 RegistryRxNumBuffers;
+ u32 RegistryRxTimeInterval;
+
+ /* Validation helpers */
+ u8 RegistryPMWOL;
+ u8 RegistryNMIDisable;
+ u32 RegistryDMACache;
+ u32 RegistrySCGain;
+ u8 RegistryPhyLoopbk; // Enable Phy loopback
+
+ /* Derived from the registry: */
+ u8 AiForceDpx; // duplex setting
+ u16 AiForceSpeed; // 'Speed', user over-ride of line speed
+ eFLOW_CONTROL_t FlowControl; // flow control validated by the far-end
+ enum {
+ NETIF_STATUS_INVALID = 0,
+ NETIF_STATUS_MEDIA_CONNECT,
+ NETIF_STATUS_MEDIA_DISCONNECT,
+ NETIF_STATUS_MAX
+ } MediaState;
+ u8 DriverNoPhyAccess;
+
+ /* Minimize init-time */
+ bool bQueryPending;
+ bool bSetPending;
+ bool bResetPending;
+ struct timer_list ErrorTimer;
+ bool bLinkTimerActive;
+ MP_POWER_MGMT PoMgmt;
+ INTERRUPT_t CachedMaskValue;
+
+ atomic_t RcvRefCount; // Num packets not yet returned
+
+ /* Xcvr status at last poll */
+ MI_BMSR_t Bmsr;
+
+ /* Tx Memory Variables */
+ TX_RING_t TxRing;
+
+ /* Rx Memory Variables */
+ RX_RING_t RxRing;
+
+ /* ET1310 register Access */
+ JAGCORE_ACCESS_REGS JagCoreRegs;
+ PCI_CFG_SPACE_REGS PciCfgRegs;
+
+ /* Loopback specifics */
+ u8 ReplicaPhyLoopbk; // Replica Enable
+ u8 ReplicaPhyLoopbkPF; // Replica Enable Pass/Fail
+
+ /* Stats */
+ CE_STATS_t Stats;
+
+ struct net_device_stats net_stats;
+ struct net_device_stats net_stats_prev;
+};
+
+#define MPSendPacketsHandler MPSendPackets
+#define MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb) \
+ et131x_free_send_packet(Adapter, pMpTcb)
+#define MpSendPacketFun(Adapter, Packet) MpSendPacket(Adapter, Packet)
+
+#endif /* __ET131X_ADAPTER_H__ */
diff --git a/drivers/staging/et131x/et131x_config.c b/drivers/staging/et131x/et131x_config.c
new file mode 100644
index 00000000000..0adbaa6ca07
--- /dev/null
+++ b/drivers/staging/et131x/et131x_config.c
@@ -0,0 +1,325 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_config.c - Handles parsing of configuration data during
+ * initialization.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_initpci.h"
+#include "et131x_config.h"
+
+#include "et1310_tx.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/* Defines for Parameter Default/Min/Max vaules */
+#define PARM_SPEED_DUPLEX_DEF 0
+#define PARM_SPEED_DUPLEX_MIN 0
+#define PARM_SPEED_DUPLEX_MAX 5
+
+#define PARM_VLAN_TAG_DEF 0
+#define PARM_VLAN_TAG_MIN 0
+#define PARM_VLAN_TAG_MAX 4095
+
+#define PARM_FLOW_CTL_DEF 0
+#define PARM_FLOW_CTL_MIN 0
+#define PARM_FLOW_CTL_MAX 3
+
+#define PARM_WOL_LINK_DEF 3
+#define PARM_WOL_LINK_MIN 0
+#define PARM_WOL_LINK_MAX 3
+
+#define PARM_WOL_MATCH_DEF 7
+#define PARM_WOL_MATCH_MIN 0
+#define PARM_WOL_MATCH_MAX 7
+
+#define PARM_JUMBO_PKT_DEF 1514
+#define PARM_JUMBO_PKT_MIN 1514
+#define PARM_JUMBO_PKT_MAX 9216
+
+#define PARM_PHY_COMA_DEF 0
+#define PARM_PHY_COMA_MIN 0
+#define PARM_PHY_COMA_MAX 1
+
+#define PARM_RX_NUM_BUFS_DEF 4
+#define PARM_RX_NUM_BUFS_MIN 1
+#define PARM_RX_NUM_BUFS_MAX 64
+
+#define PARM_RX_TIME_INT_DEF 10
+#define PARM_RX_TIME_INT_MIN 2
+#define PARM_RX_TIME_INT_MAX 320
+
+#define PARM_TX_NUM_BUFS_DEF 4
+#define PARM_TX_NUM_BUFS_MIN 1
+#define PARM_TX_NUM_BUFS_MAX 40
+
+#define PARM_TX_TIME_INT_DEF 40
+#define PARM_TX_TIME_INT_MIN 1
+#define PARM_TX_TIME_INT_MAX 140
+
+#define PARM_RX_MEM_END_DEF 0x2bc
+#define PARM_RX_MEM_END_MIN 0
+#define PARM_RX_MEM_END_MAX 0x3ff
+
+#define PARM_MAC_STAT_DEF 1
+#define PARM_MAC_STAT_MIN 0
+#define PARM_MAC_STAT_MAX 1
+
+#define PARM_SC_GAIN_DEF 7
+#define PARM_SC_GAIN_MIN 0
+#define PARM_SC_GAIN_MAX 7
+
+#define PARM_PM_WOL_DEF 0
+#define PARM_PM_WOL_MIN 0
+#define PARM_PM_WOL_MAX 1
+
+#define PARM_NMI_DISABLE_DEF 0
+#define PARM_NMI_DISABLE_MIN 0
+#define PARM_NMI_DISABLE_MAX 2
+
+#define PARM_DMA_CACHE_DEF 0
+#define PARM_DMA_CACHE_MIN 0
+#define PARM_DMA_CACHE_MAX 15
+
+#define PARM_PHY_LOOPBK_DEF 0
+#define PARM_PHY_LOOPBK_MIN 0
+#define PARM_PHY_LOOPBK_MAX 1
+
+#define PARM_MAC_ADDRESS_DEF { 0x00, 0x05, 0x3d, 0x00, 0x02, 0x00 }
+
+/* Module parameter for disabling NMI
+ * et131x_speed_set :
+ * Set Link speed and dublex manually (0-5) [0]
+ * 1 : 10Mb Half-Duplex
+ * 2 : 10Mb Full-Duplex
+ * 3 : 100Mb Half-Duplex
+ * 4 : 100Mb Full-Duplex
+ * 5 : 1000Mb Full-Duplex
+ * 0 : Auto Speed Auto Dublex // default
+ */
+static u32 et131x_nmi_disable = PARM_NMI_DISABLE_DEF;
+module_param(et131x_nmi_disable, uint, 0);
+MODULE_PARM_DESC(et131x_nmi_disable, "Disable NMI (0-2) [0]");
+
+/* Module parameter for manual speed setting
+ * et131x_nmi_disable :
+ * Disable NMI (0-2) [0]
+ * 0 :
+ * 1 :
+ * 2 :
+ */
+static u32 et131x_speed_set = PARM_SPEED_DUPLEX_DEF;
+module_param(et131x_speed_set, uint, 0);
+MODULE_PARM_DESC(et131x_speed_set,
+ "Set Link speed and dublex manually (0-5) [0] \n 1 : 10Mb Half-Duplex \n 2 : 10Mb Full-Duplex \n 3 : 100Mb Half-Duplex \n 4 : 100Mb Full-Duplex \n 5 : 1000Mb Full-Duplex \n 0 : Auto Speed Auto Dublex");
+
+/**
+ * et131x_config_parse
+ * @pAdapter: pointer to the private adapter struct
+ *
+ * Parses a configuration from some location (module parameters, for example)
+ * into the private adapter struct
+ */
+void et131x_config_parse(struct et131x_adapter *pAdapter)
+{
+ uint8_t macAddrDef[] = PARM_MAC_ADDRESS_DEF;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /*
+ * The NDIS driver uses the registry to store persistent per-device
+ * configuration, and reads this configuration into the appropriate
+ * elements of the private adapter structure on initialization.
+ * Because Linux has no analog to the registry, use this function to
+ * initialize the private adapter structure with a default
+ * configuration.
+ *
+ * One other possibility is to use a series of module parameters which
+ * can be passed in by the caller when the module is initialized.
+ * However, this implementation does not allow for seperate
+ * configurations in the event multiple devices are present, and hence
+ * will not suffice.
+ *
+ * If another method is derived which addresses this problem, this is
+ * where it should be implemented.
+ */
+
+ /* Set the private adapter struct with default values for the
+ * corresponding parameters
+ */
+ if (et131x_speed_set != PARM_SPEED_DUPLEX_DEF) {
+ DBG_VERBOSE(et131x_dbginfo, "Speed set manually to : %d \n",
+ et131x_speed_set);
+ pAdapter->SpeedDuplex = et131x_speed_set;
+ } else {
+ pAdapter->SpeedDuplex = PARM_SPEED_DUPLEX_DEF;
+ }
+
+ // pAdapter->SpeedDuplex = PARM_SPEED_DUPLEX_DEF;
+
+ pAdapter->RegistryVlanTag = PARM_VLAN_TAG_DEF;
+ pAdapter->RegistryFlowControl = PARM_FLOW_CTL_DEF;
+ pAdapter->RegistryWOLLink = PARM_WOL_LINK_DEF;
+ pAdapter->RegistryWOLMatch = PARM_WOL_MATCH_DEF;
+ pAdapter->RegistryJumboPacket = PARM_JUMBO_PKT_DEF;
+ pAdapter->RegistryPhyComa = PARM_PHY_COMA_DEF;
+ pAdapter->RegistryRxNumBuffers = PARM_RX_NUM_BUFS_DEF;
+ pAdapter->RegistryRxTimeInterval = PARM_RX_TIME_INT_DEF;
+ pAdapter->RegistryTxNumBuffers = PARM_TX_NUM_BUFS_DEF;
+ pAdapter->RegistryTxTimeInterval = PARM_TX_TIME_INT_DEF;
+ pAdapter->RegistryRxMemEnd = PARM_RX_MEM_END_DEF;
+ pAdapter->RegistryMACStat = PARM_MAC_STAT_DEF;
+ pAdapter->RegistrySCGain = PARM_SC_GAIN_DEF;
+ pAdapter->RegistryPMWOL = PARM_PM_WOL_DEF;
+
+ if (et131x_nmi_disable != PARM_NMI_DISABLE_DEF) {
+ pAdapter->RegistryNMIDisable = et131x_nmi_disable;
+ } else {
+ pAdapter->RegistryNMIDisable = PARM_NMI_DISABLE_DEF;
+ }
+
+ pAdapter->RegistryDMACache = PARM_DMA_CACHE_DEF;
+ pAdapter->RegistryPhyLoopbk = PARM_PHY_LOOPBK_DEF;
+
+ /* Set the MAC address to a default */
+ memcpy(pAdapter->CurrentAddress, macAddrDef, ETH_ALEN);
+ pAdapter->bOverrideAddress = false;
+
+ DBG_TRACE(et131x_dbginfo,
+ "Default MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAdapter->CurrentAddress[0], pAdapter->CurrentAddress[1],
+ pAdapter->CurrentAddress[2], pAdapter->CurrentAddress[3],
+ pAdapter->CurrentAddress[4], pAdapter->CurrentAddress[5]);
+
+ /* Decode SpeedDuplex
+ *
+ * Set up as if we are auto negotiating always and then change if we
+ * go into force mode
+ */
+ pAdapter->AiForceSpeed = 0; // Auto speed
+ pAdapter->AiForceDpx = 0; // Auto FDX
+
+ /* If we are the 10/100 device, and gigabit is somehow requested then
+ * knock it down to 100 full.
+ */
+ if ((pAdapter->DeviceID == ET131X_PCI_DEVICE_ID_FAST) &&
+ (pAdapter->SpeedDuplex == 5)) {
+ pAdapter->SpeedDuplex = 4;
+ }
+
+ switch (pAdapter->SpeedDuplex) {
+ case 1: // 10Mb Half-Duplex
+ pAdapter->AiForceSpeed = 10;
+ pAdapter->AiForceDpx = 1;
+ break;
+
+ case 2: // 10Mb Full-Duplex
+ pAdapter->AiForceSpeed = 10;
+ pAdapter->AiForceDpx = 2;
+ break;
+
+ case 3: // 100Mb Half-Duplex
+ pAdapter->AiForceSpeed = 100;
+ pAdapter->AiForceDpx = 1;
+ break;
+
+ case 4: // 100Mb Full-Duplex
+ pAdapter->AiForceSpeed = 100;
+ pAdapter->AiForceDpx = 2;
+ break;
+
+ case 5: // 1000Mb Full-Duplex
+ pAdapter->AiForceSpeed = 1000;
+ pAdapter->AiForceDpx = 2;
+ break;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
diff --git a/drivers/staging/et131x/et131x_config.h b/drivers/staging/et131x/et131x_config.h
new file mode 100644
index 00000000000..642c0f6dd6f
--- /dev/null
+++ b/drivers/staging/et131x/et131x_config.h
@@ -0,0 +1,67 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_config.h - Defines, structs, enums, prototypes, etc. to support
+ * et131x_config.c
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_CONFIG_H__
+#define __ET131X_CONFIG_H__
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+void et131x_config_parse(struct et131x_adapter *adapter);
+
+#endif /* __ET131X_CONFIG_H__ */
diff --git a/drivers/staging/et131x/et131x_debug.c b/drivers/staging/et131x/et131x_debug.c
new file mode 100644
index 00000000000..9ee5bce92c2
--- /dev/null
+++ b/drivers/staging/et131x/et131x_debug.c
@@ -0,0 +1,218 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_debug.c - Routines used for debugging.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifdef CONFIG_ET131X_DEBUG
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/random.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_netdev.h"
+#include "et131x_config.h"
+#include "et131x_isr.h"
+
+#include "et1310_address_map.h"
+#include "et1310_jagcore.h"
+#include "et1310_tx.h"
+#include "et1310_rx.h"
+#include "et1310_mac.h"
+
+/* Data for debugging facilities */
+extern dbg_info_t *et131x_dbginfo;
+
+/**
+ * DumpTxQueueContents - Dump out the tx queue and the shadow pointers
+ * @pAdapter: pointer to our adapter structure
+ */
+void DumpTxQueueContents(int dbgLvl, struct et131x_adapter *pAdapter)
+{
+ MMC_t __iomem *mmc = &pAdapter->CSRAddress->mmc;
+ uint32_t TxQueueAddr;
+
+ if (DBG_FLAGS(et131x_dbginfo) & dbgLvl) {
+ for (TxQueueAddr = 0x200; TxQueueAddr < 0x3ff; TxQueueAddr++) {
+ MMC_SRAM_ACCESS_t sram_access;
+
+ sram_access.value = readl(&mmc->sram_access.value);
+ sram_access.bits.req_addr = TxQueueAddr;
+ sram_access.bits.req_access = 1;
+ writel(sram_access.value, &mmc->sram_access.value);
+
+ DBG_PRINT("Addr 0x%x, Access 0x%08x\t"
+ "Value 1 0x%08x, Value 2 0x%08x, "
+ "Value 3 0x%08x, Value 4 0x%08x, \n",
+ TxQueueAddr,
+ readl(&mmc->sram_access.value),
+ readl(&mmc->sram_word1),
+ readl(&mmc->sram_word2),
+ readl(&mmc->sram_word3),
+ readl(&mmc->sram_word4));
+ }
+
+ DBG_PRINT("Shadow Pointers 0x%08x\n",
+ readl(&pAdapter->CSRAddress->txmac.shadow_ptr.value));
+ }
+}
+
+/**
+ * DumpDeviceBlock
+ * @pAdapter: pointer to our adapter
+ *
+ * Dumps the first 64 regs of each block of the et-1310 (each block is
+ * mapped to a new page, each page is 4096 bytes).
+ */
+#define NUM_BLOCKS 8
+void DumpDeviceBlock(int dbgLvl, struct et131x_adapter *pAdapter,
+ uint32_t Block)
+{
+ uint32_t Address1, Address2;
+ uint32_t __iomem *BigDevicePointer =
+ (uint32_t __iomem *) pAdapter->CSRAddress;
+ const char *BlockNames[NUM_BLOCKS] = {
+ "Global", "Tx DMA", "Rx DMA", "Tx MAC",
+ "Rx MAC", "MAC", "MAC Stat", "MMC"
+ };
+
+ /* Output the debug counters to the debug terminal */
+ if (DBG_FLAGS(et131x_dbginfo) & dbgLvl) {
+ DBG_PRINT("%s block\n", BlockNames[Block]);
+ BigDevicePointer += Block * 1024;
+ for (Address1 = 0; Address1 < 8; Address1++) {
+ for (Address2 = 0; Address2 < 8; Address2++) {
+ if (Block == 0 &&
+ (Address1 * 8 + Address2) == 6) {
+ DBG_PRINT(" ISR , ");
+ } else {
+ DBG_PRINT("0x%08x, ",
+ readl(BigDevicePointer++));
+ }
+ }
+ DBG_PRINT("\n");
+ }
+ DBG_PRINT("\n");
+ }
+}
+
+/**
+ * DumpDeviceReg
+ * @pAdapter: pointer to our adapter
+ *
+ * Dumps the first 64 regs of each block of the et-1310 (each block is
+ * mapped to a new page, each page is 4096 bytes).
+ */
+void DumpDeviceReg(int dbgLvl, struct et131x_adapter *pAdapter)
+{
+ uint32_t Address1, Address2;
+ uint32_t Block;
+ uint32_t __iomem *BigDevicePointer =
+ (uint32_t __iomem *) pAdapter->CSRAddress;
+ uint32_t __iomem *Pointer;
+ const char *BlockNames[NUM_BLOCKS] = {
+ "Global", "Tx DMA", "Rx DMA", "Tx MAC",
+ "Rx MAC", "MAC", "MAC Stat", "MMC"
+ };
+
+ /* Output the debug counters to the debug terminal */
+ if (DBG_FLAGS(et131x_dbginfo) & dbgLvl) {
+ for (Block = 0; Block < NUM_BLOCKS; Block++) {
+ DBG_PRINT("%s block\n", BlockNames[Block]);
+ Pointer = BigDevicePointer + (Block * 1024);
+
+ for (Address1 = 0; Address1 < 8; Address1++) {
+ for (Address2 = 0; Address2 < 8; Address2++) {
+ DBG_PRINT("0x%08x, ",
+ readl(Pointer++));
+ }
+ DBG_PRINT("\n");
+ }
+ DBG_PRINT("\n");
+ }
+ }
+}
+
+#endif // CONFIG_ET131X_DEBUG
diff --git a/drivers/staging/et131x/et131x_debug.h b/drivers/staging/et131x/et131x_debug.h
new file mode 100644
index 00000000000..dab608031d0
--- /dev/null
+++ b/drivers/staging/et131x/et131x_debug.h
@@ -0,0 +1,201 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_debug.h - Defines, structs, enums, prototypes, etc. used for
+ * outputting debug messages to the system logging facility
+ * (ksyslogd)
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_DBG_H__
+#define __ET131X_DBG_H__
+
+/* Define Masks for debugging types/levels */
+#define DBG_ERROR_ON 0x00000001L
+#define DBG_WARNING_ON 0x00000002L
+#define DBG_NOTICE_ON 0x00000004L
+#define DBG_TRACE_ON 0x00000008L
+#define DBG_VERBOSE_ON 0x00000010L
+#define DBG_PARAM_ON 0x00000020L
+#define DBG_BREAK_ON 0x00000040L
+#define DBG_RX_ON 0x00000100L
+#define DBG_TX_ON 0x00000200L
+
+#ifdef CONFIG_ET131X_DEBUG
+
+/*
+ * Set the level of debugging if not done with a preprocessor define. See
+ * et131x_main.c, function et131x_init_module() for how the debug level
+ * translates into the types of messages displayed.
+ */
+#ifndef DBG_LVL
+#define DBG_LVL 3
+#endif /* DBG_LVL */
+
+#define DBG_DEFAULTS (DBG_ERROR_ON | DBG_WARNING_ON | DBG_BREAK_ON )
+
+#define DBG_FLAGS(A) (A)->dbgFlags
+#define DBG_NAME(A) (A)->dbgName
+#define DBG_LEVEL(A) (A)->dbgLevel
+
+#ifndef DBG_PRINT
+#define DBG_PRINT(S...) printk(KERN_DEBUG S)
+#endif /* DBG_PRINT */
+
+#ifndef DBG_PRINTC
+#define DBG_PRINTC(S...) printk(S)
+#endif /* DBG_PRINTC */
+
+#ifndef DBG_TRAP
+#define DBG_TRAP {} /* BUG() */
+#endif /* DBG_TRAP */
+
+#define _ENTER_STR ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+#define _LEAVE_STR "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
+
+#define _DBG_ENTER(A) printk(KERN_DEBUG "%s:%.*s:%s\n", DBG_NAME(A), \
+ ++DBG_LEVEL(A), _ENTER_STR, __func__)
+#define _DBG_LEAVE(A) printk(KERN_DEBUG "%s:%.*s:%s\n", DBG_NAME(A), \
+ DBG_LEVEL(A)--, _LEAVE_STR, __func__)
+
+#define DBG_ENTER(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
+ _DBG_ENTER(A);}
+
+#define DBG_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
+ _DBG_LEAVE(A);}
+
+#define DBG_PARAM(A,N,F,S...) {if (DBG_FLAGS(A) & DBG_PARAM_ON) \
+ DBG_PRINT(" %s -- "F"\n",N,S);}
+
+#define DBG_ERROR(A,S...) \
+ if (DBG_FLAGS(A) & DBG_ERROR_ON) { \
+ DBG_PRINT("%s:ERROR:%s ",DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ DBG_TRAP; \
+ }
+
+#define DBG_WARNING(A,S...) {if (DBG_FLAGS(A) & DBG_WARNING_ON) \
+ {DBG_PRINT("%s:WARNING:%s ",DBG_NAME(A),__func__);DBG_PRINTC(S);}}
+
+#define DBG_NOTICE(A,S...) {if (DBG_FLAGS(A) & DBG_NOTICE_ON) \
+ {DBG_PRINT("%s:NOTICE:%s ",DBG_NAME(A),__func__);DBG_PRINTC(S);}}
+
+#define DBG_TRACE(A,S...) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
+ {DBG_PRINT("%s:TRACE:%s ",DBG_NAME(A), __func__);DBG_PRINTC(S);}}
+
+#define DBG_VERBOSE(A,S...) {if (DBG_FLAGS(A) & DBG_VERBOSE_ON) \
+ {DBG_PRINT("%s:VERBOSE:%s ",DBG_NAME(A), __func__);DBG_PRINTC(S);}}
+
+#define DBG_RX(A,S...) {if (DBG_FLAGS(A) & DBG_RX_ON) \
+ {DBG_PRINT(S);}}
+
+#define DBG_RX_ENTER(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \
+ _DBG_ENTER(A);}
+
+#define DBG_RX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \
+ _DBG_LEAVE(A);}
+
+#define DBG_TX(A,S...) {if (DBG_FLAGS(A) & DBG_TX_ON) \
+ {DBG_PRINT(S);}}
+
+#define DBG_TX_ENTER(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \
+ _DBG_ENTER(A);}
+
+#define DBG_TX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \
+ _DBG_LEAVE(A);}
+
+#define DBG_ASSERT(C) {if (!(C)) \
+ {DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \
+ #C,__FILE__,__LINE__,__func__); \
+ DBG_TRAP;}}
+#define STATIC
+
+typedef struct {
+ char *dbgName;
+ int dbgLevel;
+ unsigned long dbgFlags;
+} dbg_info_t;
+
+#else /* CONFIG_ET131X_DEBUG */
+
+#define DBG_DEFN
+#define DBG_TRAP
+#define DBG_PRINT(S...)
+#define DBG_ENTER(A)
+#define DBG_LEAVE(A)
+#define DBG_PARAM(A,N,F,S...)
+#define DBG_ERROR(A,S...)
+#define DBG_WARNING(A,S...)
+#define DBG_NOTICE(A,S...)
+#define DBG_TRACE(A,S...)
+#define DBG_VERBOSE(A,S...)
+#define DBG_RX(A,S...)
+#define DBG_RX_ENTER(A)
+#define DBG_RX_LEAVE(A)
+#define DBG_TX(A,S...)
+#define DBG_TX_ENTER(A)
+#define DBG_TX_LEAVE(A)
+#define DBG_ASSERT(C)
+#define STATIC static
+
+#endif /* CONFIG_ET131X_DEBUG */
+
+/* Forward declaration of the private adapter structure */
+struct et131x_adapter;
+
+void DumpTxQueueContents(int dbgLvl, struct et131x_adapter *adapter);
+void DumpDeviceBlock(int dbgLvl, struct et131x_adapter *adapter,
+ unsigned int Block);
+void DumpDeviceReg(int dbgLvl, struct et131x_adapter *adapter);
+
+#endif /* __ET131X_DBG_H__ */
diff --git a/drivers/staging/et131x/et131x_defs.h b/drivers/staging/et131x/et131x_defs.h
new file mode 100644
index 00000000000..886cb78698e
--- /dev/null
+++ b/drivers/staging/et131x/et131x_defs.h
@@ -0,0 +1,128 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_defs.h - Defines, structs, enums, prototypes, etc. to assist with OS
+ * compatibility
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_DEFS_H__
+#define __ET131X_DEFS_H__
+
+/* Packet and header sizes */
+#define NIC_MIN_PACKET_SIZE 60
+#define NIC_HEADER_SIZE ETH_HLEN /* 14 */
+
+/* Multicast list size */
+#define NIC_MAX_MCAST_LIST 128
+
+/* Supported Filters */
+#define ET131X_PACKET_TYPE_DIRECTED 0x0001
+#define ET131X_PACKET_TYPE_MULTICAST 0x0002
+#define ET131X_PACKET_TYPE_BROADCAST 0x0004
+#define ET131X_PACKET_TYPE_PROMISCUOUS 0x0008
+#define ET131X_PACKET_TYPE_ALL_MULTICAST 0x0010
+
+/* Tx Timeout */
+#define ET131X_TX_TIMEOUT (1 * HZ)
+#define NIC_SEND_HANG_THRESHOLD 0
+
+/* MP_TCB flags */
+#define fMP_DEST_MULTI 0x00000001
+#define fMP_DEST_BROAD 0x00000002
+
+/* MP_ADAPTER flags */
+#define fMP_ADAPTER_RECV_LOOKASIDE 0x00000004
+#define fMP_ADAPTER_INTERRUPT_IN_USE 0x00000008
+#define fMP_ADAPTER_SECONDARY 0x00000010
+
+/* MP_SHARED flags */
+#define fMP_ADAPTER_SHUTDOWN 0x00100000
+#define fMP_ADAPTER_LOWER_POWER 0x00200000
+
+#define fMP_ADAPTER_NON_RECOVER_ERROR 0x00800000
+#define fMP_ADAPTER_RESET_IN_PROGRESS 0x01000000
+#define fMP_ADAPTER_NO_CABLE 0x02000000
+#define fMP_ADAPTER_HARDWARE_ERROR 0x04000000
+#define fMP_ADAPTER_REMOVE_IN_PROGRESS 0x08000000
+#define fMP_ADAPTER_HALT_IN_PROGRESS 0x10000000
+#define fMP_ADAPTER_LINK_DETECTION 0x20000000
+
+#define fMP_ADAPTER_FAIL_SEND_MASK 0x3ff00000
+#define fMP_ADAPTER_NOT_READY_MASK 0x3ff00000
+
+/* Some offsets in PCI config space that are actually used. */
+#define ET1310_PCI_PM_CAPABILITY 0x40
+#define ET1310_PCI_PM_CSR 0x44
+#define ET1310_PCI_MAX_PYLD 0x4C
+#define ET1310_PCI_DEV_CTRL 0x50
+#define ET1310_PCI_DEV_STAT 0x52
+#define ET1310_NMI_DISABLE 0x61
+#define ET1310_PCI_MAC_ADDRESS 0xA4
+#define ET1310_PCI_EEPROM_STATUS 0xB2
+#define ET1310_PCI_PHY_INDEX_REG 0xB4
+#define ET1310_PCI_ACK_NACK 0xC0
+#define ET1310_PCI_REPLAY 0xC2
+#define ET1310_PCI_L0L1LATENCY 0xCF
+#define ET1310_PCI_SEL_PHY_CTRL 0xE4
+#define ET1310_PCI_ADVANCED_ERR 0x100
+
+/* PCI Vendor/Product IDs */
+#define ET131X_PCI_VENDOR_ID 0x11C1 // Agere Systems
+#define ET131X_PCI_DEVICE_ID_GIG 0xED00 // ET1310 1000 Base-T
+#define ET131X_PCI_DEVICE_ID_FAST 0xED01 // ET1310 100 Base-T
+
+/* Define order of magnitude converter */
+#define NANO_IN_A_MICRO 1000
+
+#endif /* __ET131X_DEFS_H__ */
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
new file mode 100644
index 00000000000..4c6f171f5b7
--- /dev/null
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -0,0 +1,1046 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_initpci.c - Routines and data used to register the driver with the
+ * PCI (and PCI Express) subsystem, as well as basic driver
+ * init and startup.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/random.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+
+#include "et131x_adapter.h"
+#include "et131x_netdev.h"
+#include "et131x_config.h"
+#include "et131x_isr.h"
+
+#include "et1310_address_map.h"
+#include "et1310_jagcore.h"
+#include "et1310_tx.h"
+#include "et1310_rx.h"
+#include "et1310_mac.h"
+#include "et1310_eeprom.h"
+
+
+int __devinit et131x_pci_setup(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+void __devexit et131x_pci_remove(struct pci_dev *pdev);
+
+
+/* Modinfo parameters (filled out using defines from et131x_version.h) */
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_INFO);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+/* Module Parameters and related data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+static u32 et131x_debug_level = DBG_LVL;
+static u32 et131x_debug_flags = DBG_DEFAULTS;
+
+/*
+et131x_debug_level :
+ Level of debugging desired (0-7)
+ 7 : DBG_RX_ON | DBG_TX_ON
+ 6 : DBG_PARAM_ON
+ 5 : DBG_VERBOSE_ON
+ 4 : DBG_TRACE_ON
+ 3 : DBG_NOTICE_ON
+ 2 : no debug info
+ 1 : no debug info
+ 0 : no debug info
+*/
+
+module_param(et131x_debug_level, uint, 0);
+module_param(et131x_debug_flags, uint, 0);
+
+MODULE_PARM_DESC(et131x_debug_level, "Level of debugging desired (0-7)");
+
+static dbg_info_t et131x_info = { DRIVER_NAME_EXT, 0, 0 };
+dbg_info_t *et131x_dbginfo = &et131x_info;
+#endif /* CONFIG_ET131X_DEBUG */
+
+static struct pci_device_id et131x_pci_table[] __devinitdata = {
+ {ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_GIG, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0UL},
+ {ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_FAST, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0UL},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, et131x_pci_table);
+
+static struct pci_driver et131x_driver = {
+ .name = DRIVER_NAME,
+ .id_table = et131x_pci_table,
+ .probe = et131x_pci_setup,
+ .remove = __devexit_p(et131x_pci_remove),
+ .suspend = NULL, //et131x_pci_suspend,
+ .resume = NULL, //et131x_pci_resume,
+};
+
+
+/**
+ * et131x_init_module - The "main" entry point called on driver initialization
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_init_module(void)
+{
+ int result;
+
+#ifdef CONFIG_ET131X_DEBUG
+ /* Set the level of debug messages displayed using the module
+ * parameter
+ */
+ et131x_dbginfo->dbgFlags = et131x_debug_flags;
+
+ switch (et131x_debug_level) {
+ case 7:
+ et131x_dbginfo->dbgFlags |= (DBG_RX_ON | DBG_TX_ON);
+
+ case 6:
+ et131x_dbginfo->dbgFlags |= DBG_PARAM_ON;
+
+ case 5:
+ et131x_dbginfo->dbgFlags |= DBG_VERBOSE_ON;
+
+ case 4:
+ et131x_dbginfo->dbgFlags |= DBG_TRACE_ON;
+
+ case 3:
+ et131x_dbginfo->dbgFlags |= DBG_NOTICE_ON;
+
+ case 2:
+ case 1:
+ case 0:
+ default:
+ break;
+ }
+#endif /* CONFIG_ET131X_DEBUG */
+
+ DBG_ENTER(et131x_dbginfo);
+ DBG_PRINT("%s\n", DRIVER_INFO);
+
+ result = pci_register_driver(&et131x_driver);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+}
+
+/**
+ * et131x_cleanup_module - The entry point called on driver cleanup
+ */
+void et131x_cleanup_module(void)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ pci_unregister_driver(&et131x_driver);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/*
+ * These macros map the driver-specific init_module() and cleanup_module()
+ * routines so they can be called by the kernel.
+ */
+module_init(et131x_init_module);
+module_exit(et131x_cleanup_module);
+
+
+/**
+ * et131x_find_adapter - Find the adapter and get all the assigned resources
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev)
+{
+ int result;
+ uint8_t eepromStat;
+ uint8_t maxPayload = 0;
+ uint8_t read_size_reg;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Allow disabling of Non-Maskable Interrupts in I/O space, to
+ * support validation.
+ */
+ if (adapter->RegistryNMIDisable) {
+ uint8_t RegisterVal;
+
+ RegisterVal = inb(ET1310_NMI_DISABLE);
+ RegisterVal &= 0xf3;
+
+ if (adapter->RegistryNMIDisable == 2) {
+ RegisterVal |= 0xc;
+ }
+
+ outb(ET1310_NMI_DISABLE, RegisterVal);
+ }
+
+ /* We first need to check the EEPROM Status code located at offset
+ * 0xB2 of config space
+ */
+ result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS,
+ &eepromStat);
+
+ /* THIS IS A WORKAROUND:
+ * I need to call this function twice to get my card in a
+ * LG M1 Express Dual running. I tried also a msleep before this
+ * function, because I thougth there could be some time condidions
+ * but it didn't work. Call the whole function twice also work.
+ */
+ result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS,
+ &eepromStat);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo, "Could not read PCI config space for "
+ "EEPROM Status\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* Determine if the error(s) we care about are present. If they are
+ * present, we need to fail.
+ */
+ if (eepromStat & 0x4C) {
+ result = pci_read_config_byte(pdev, PCI_REVISION_ID,
+ &adapter->RevisionID);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not read PCI config space for "
+ "Revision ID\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ } else if (adapter->RevisionID == 0x01) {
+ int32_t nLoop;
+ uint8_t ucTemp[4] = { 0xFE, 0x13, 0x10, 0xFF };
+
+ /* Re-write the first 4 bytes if we have an eeprom
+ * present and the revision id is 1, this fixes the
+ * corruption seen with 1310 B Silicon
+ */
+ for (nLoop = 0; nLoop < 3; nLoop++) {
+ EepromWriteByte(adapter, nLoop, ucTemp[nLoop],
+ 0, SINGLE_BYTE);
+ }
+ }
+
+ DBG_ERROR(et131x_dbginfo,
+ "Fatal EEPROM Status Error - 0x%04x\n", eepromStat);
+
+ /* This error could mean that there was an error reading the
+ * eeprom or that the eeprom doesn't exist. We will treat
+ * each case the same and not try to gather additional
+ * information that normally would come from the eeprom, like
+ * MAC Address
+ */
+ adapter->bEepromPresent = false;
+
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ } else {
+ DBG_TRACE(et131x_dbginfo, "EEPROM Status Code - 0x%04x\n",
+ eepromStat);
+ adapter->bEepromPresent = true;
+ }
+
+ /* Read the EEPROM for information regarding LED behavior. Refer to
+ * ET1310_phy.c, et131x_xcvr_init(), for its use.
+ */
+ EepromReadByte(adapter, 0x70, &adapter->eepromData[0], 0, SINGLE_BYTE);
+ EepromReadByte(adapter, 0x71, &adapter->eepromData[1], 0, SINGLE_BYTE);
+
+ if (adapter->eepromData[0] != 0xcd) {
+ adapter->eepromData[1] = 0x00; // Disable all optional features
+ }
+
+ /* Let's set up the PORT LOGIC Register. First we need to know what
+ * the max_payload_size is
+ */
+ result = pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &maxPayload);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo, "Could not read PCI config space for "
+ "Max Payload Size\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* Program the Ack/Nak latency and replay timers */
+ maxPayload &= 0x07; // Only the lower 3 bits are valid
+
+ if (maxPayload < 2) {
+ const uint16_t AckNak[2] = { 0x76, 0xD0 };
+ const uint16_t Replay[2] = { 0x1E0, 0x2ED };
+
+ result = pci_write_config_word(pdev, ET1310_PCI_ACK_NACK,
+ AckNak[maxPayload]);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not write PCI config space "
+ "for ACK/NAK\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ result = pci_write_config_word(pdev, ET1310_PCI_REPLAY,
+ Replay[maxPayload]);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not write PCI config space "
+ "for Replay Timer\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+ }
+
+ /* l0s and l1 latency timers. We are using default values.
+ * Representing 001 for L0s and 010 for L1
+ */
+ result = pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not write PCI config space for "
+ "Latency Timers\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* Change the max read size to 2k */
+ result = pci_read_config_byte(pdev, 0x51, &read_size_reg);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not read PCI config space for Max read size\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ read_size_reg &= 0x8f;
+ read_size_reg |= 0x40;
+
+ result = pci_write_config_byte(pdev, 0x51, read_size_reg);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not write PCI config space for Max read size\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* PCI Express Configuration registers 0x48-0x5B (Device Control) */
+ result = pci_read_config_word(pdev, ET1310_PCI_DEV_CTRL,
+ &adapter->PciXDevCtl);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not read PCI config space for PCI Express Dev Ctl\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+
+ /* Get MAC address from config space if an eeprom exists, otherwise
+ * the MAC address there will not be valid
+ */
+ if (adapter->bEepromPresent) {
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ result = pci_read_config_byte(
+ pdev, ET1310_PCI_MAC_ADDRESS + i,
+ adapter->PermanentAddress + i);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not read PCI config space for MAC address\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return -EIO;
+ }
+ }
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/**
+ * et131x_error_timer_handler
+ * @data: timer-specific variable; here a pointer to our adapter structure
+ *
+ * The routine called when the error timer expires, to track the number of
+ * recurring errors.
+ */
+void et131x_error_timer_handler(unsigned long data)
+{
+ struct et131x_adapter *pAdapter = (struct et131x_adapter *) data;
+ PM_CSR_t pm_csr;
+
+ pm_csr.value = readl(&pAdapter->CSRAddress->global.pm_csr.value);
+
+ if (pm_csr.bits.pm_phy_sw_coma == 0) {
+ if (pAdapter->RegistryMACStat) {
+ UpdateMacStatHostCounters(pAdapter);
+ }
+ } else {
+ DBG_VERBOSE(et131x_dbginfo,
+ "No interrupts, in PHY coma, pm_csr = 0x%x\n",
+ pm_csr.value);
+ }
+
+ if (!pAdapter->Bmsr.bits.link_status &&
+ pAdapter->RegistryPhyComa &&
+ pAdapter->PoMgmt.TransPhyComaModeOnBoot < 11) {
+ pAdapter->PoMgmt.TransPhyComaModeOnBoot++;
+ }
+
+ if (pAdapter->PoMgmt.TransPhyComaModeOnBoot == 10) {
+ if (!pAdapter->Bmsr.bits.link_status
+ && pAdapter->RegistryPhyComa) {
+ if (pm_csr.bits.pm_phy_sw_coma == 0) {
+ // NOTE - This was originally a 'sync with interrupt'. How
+ // to do that under Linux?
+ et131x_enable_interrupts(pAdapter);
+ EnablePhyComa(pAdapter);
+ }
+ }
+ }
+
+ /* This is a periodic timer, so reschedule */
+ mod_timer(&pAdapter->ErrorTimer, jiffies +
+ TX_ERROR_PERIOD * HZ / 1000);
+}
+
+/**
+ * et131x_link_detection_handler
+ *
+ * Timer function for link up at driver load time
+ */
+void et131x_link_detection_handler(unsigned long data)
+{
+ struct et131x_adapter *pAdapter = (struct et131x_adapter *) data;
+ unsigned long lockflags;
+
+ /* Let everyone know that we have run */
+ pAdapter->bLinkTimerActive = false;
+
+ if (pAdapter->MediaState == 0) {
+ spin_lock_irqsave(&pAdapter->Lock, lockflags);
+
+ pAdapter->MediaState = NETIF_STATUS_MEDIA_DISCONNECT;
+ MP_CLEAR_FLAG(pAdapter, fMP_ADAPTER_LINK_DETECTION);
+
+ spin_unlock_irqrestore(&pAdapter->Lock, lockflags);
+
+ netif_carrier_off(pAdapter->netdev);
+
+ pAdapter->bSetPending = false;
+ }
+}
+
+/**
+ * et131x_adapter_setup - Set the adapter up as per cassini+ documentation
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_adapter_setup(struct et131x_adapter *pAdapter)
+{
+ int status = 0;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Configure the JAGCore */
+ ConfigGlobalRegs(pAdapter);
+
+ ConfigMACRegs1(pAdapter);
+ ConfigMMCRegs(pAdapter);
+
+ ConfigRxMacRegs(pAdapter);
+ ConfigTxMacRegs(pAdapter);
+
+ ConfigRxDmaRegs(pAdapter);
+ ConfigTxDmaRegs(pAdapter);
+
+ ConfigMacStatRegs(pAdapter);
+
+ /* Move the following code to Timer function?? */
+ status = et131x_xcvr_find(pAdapter);
+
+ if (status != 0) {
+ DBG_WARNING(et131x_dbginfo, "Could not find the xcvr\n");
+ }
+
+ /* Prepare the TRUEPHY library. */
+ ET1310_PhyInit(pAdapter);
+
+ /* Reset the phy now so changes take place */
+ ET1310_PhyReset(pAdapter);
+
+ /* Power down PHY */
+ ET1310_PhyPowerDown(pAdapter, 1);
+
+ /*
+ * We need to turn off 1000 base half dulplex, the mac does not
+ * support it. For the 10/100 part, turn off all gig advertisement
+ */
+ if (pAdapter->DeviceID != ET131X_PCI_DEVICE_ID_FAST) {
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
+ } else {
+ ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
+ }
+
+ /* Power up PHY */
+ ET1310_PhyPowerDown(pAdapter, 0);
+
+ et131x_setphy_normal(pAdapter);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_setup_hardware_properties - set up the MAC Address on the ET1310
+ * @adapter: pointer to our private adapter structure
+ */
+void et131x_setup_hardware_properties(struct et131x_adapter *adapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* If have our default mac from registry and no mac address from
+ * EEPROM then we need to generate the last octet and set it on the
+ * device
+ */
+ if (!adapter->bOverrideAddress) {
+ if (adapter->PermanentAddress[0] == 0x00 &&
+ adapter->PermanentAddress[1] == 0x00 &&
+ adapter->PermanentAddress[2] == 0x00 &&
+ adapter->PermanentAddress[3] == 0x00 &&
+ adapter->PermanentAddress[4] == 0x00 &&
+ adapter->PermanentAddress[5] == 0x00) {
+ /*
+ * We need to randomly generate the last octet so we
+ * decrease our chances of setting the mac address to
+ * same as another one of our cards in the system
+ */
+ get_random_bytes(&adapter->CurrentAddress[5], 1);
+
+ /*
+ * We have the default value in the register we are
+ * working with so we need to copy the current
+ * address into the permanent address
+ */
+ memcpy(adapter->PermanentAddress,
+ adapter->CurrentAddress, ETH_ALEN);
+ } else {
+ /* We do not have an override address, so set the
+ * current address to the permanent address and add
+ * it to the device
+ */
+ memcpy(adapter->CurrentAddress,
+ adapter->PermanentAddress, ETH_ALEN);
+ }
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310
+ * @adapter: pointer to our private adapter structure
+ */
+void et131x_soft_reset(struct et131x_adapter *adapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Disable MAC Core */
+ writel(0xc00f0000, &adapter->CSRAddress->mac.cfg1.value);
+
+ /* Set everything to a reset value */
+ writel(0x7F, &adapter->CSRAddress->global.sw_reset.value);
+ writel(0x000f0000, &adapter->CSRAddress->mac.cfg1.value);
+ writel(0x00000000, &adapter->CSRAddress->mac.cfg1.value);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_align_allocated_memory - Align allocated memory on a given boundary
+ * @adapter: pointer to our adapter structure
+ * @phys_addr: pointer to Physical address
+ * @offset: pointer to the offset variable
+ * @mask: correct mask
+ */
+void et131x_align_allocated_memory(struct et131x_adapter *adapter,
+ uint64_t *phys_addr,
+ uint64_t *offset, uint64_t mask)
+{
+ uint64_t new_addr;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ *offset = 0;
+
+ new_addr = *phys_addr & ~mask;
+
+ if (new_addr != *phys_addr) {
+ /* Move to next aligned block */
+ new_addr += mask + 1;
+ /* Return offset for adjusting virt addr */
+ *offset = new_addr - *phys_addr;
+ /* Return new physical address */
+ *phys_addr = new_addr;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_adapter_memory_alloc
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h).
+ *
+ * Allocate all the memory blocks for send, receive and others.
+ */
+int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
+{
+ int status = 0;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ do {
+ /* Allocate memory for the Tx Ring */
+ status = et131x_tx_dma_memory_alloc(adapter);
+ if (status != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "et131x_tx_dma_memory_alloc FAILED\n");
+ break;
+ }
+
+ /* Receive buffer memory allocation */
+ status = et131x_rx_dma_memory_alloc(adapter);
+ if (status != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "et131x_rx_dma_memory_alloc FAILED\n");
+ et131x_tx_dma_memory_free(adapter);
+ break;
+ }
+
+ /* Init receive data structures */
+ status = et131x_init_recv(adapter);
+ if (status != 0) {
+ DBG_ERROR(et131x_dbginfo, "et131x_init_recv FAILED\n");
+ et131x_tx_dma_memory_free(adapter);
+ et131x_rx_dma_memory_free(adapter);
+ break;
+ }
+ } while (0);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx
+ * @adapter: pointer to our private adapter structure
+ */
+void et131x_adapter_memory_free(struct et131x_adapter *adapter)
+{
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Free DMA memory */
+ et131x_tx_dma_memory_free(adapter);
+ et131x_rx_dma_memory_free(adapter);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_pci_remove
+ * @pdev: a pointer to the device's pci_dev structure
+ *
+ * Registered in the pci_driver structure, this function is called when the
+ * PCI subsystem detects that a PCI device which matches the information
+ * contained in the pci_device_id table has been removed.
+ */
+void __devexit et131x_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev;
+ struct et131x_adapter *adapter;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Retrieve the net_device pointer from the pci_dev struct, as well
+ * as the private adapter struct
+ */
+ netdev = (struct net_device *) pci_get_drvdata(pdev);
+ adapter = netdev_priv(netdev);
+
+ /* Perform device cleanup */
+ unregister_netdev(netdev);
+ et131x_adapter_memory_free(adapter);
+ iounmap(adapter->CSRAddress);
+ free_netdev(netdev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_pci_setup - Perform device initialization
+ * @pdev: a pointer to the device's pci_dev structure
+ * @ent: this device's entry in the pci_device_id table
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ *
+ * Registered in the pci_driver structure, this function is called when the
+ * PCI subsystem finds a new PCI device which matches the information
+ * contained in the pci_device_id table. This routine is the equivalent to
+ * a device insertion routine.
+ */
+int __devinit et131x_pci_setup(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int result = 0;
+ int pm_cap;
+ bool pci_using_dac;
+ struct net_device *netdev = NULL;
+ struct et131x_adapter *adapter = NULL;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Enable the device via the PCI subsystem */
+ result = pci_enable_device(pdev);
+ if (result != 0) {
+ DBG_ERROR(et131x_dbginfo, "pci_enable_device() failed\n");
+ goto out;
+ }
+
+ /* Perform some basic PCI checks */
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ DBG_ERROR(et131x_dbginfo,
+ "Can't find PCI device's base address\n");
+ result = -ENODEV;
+ goto out;
+ }
+
+ result = pci_request_regions(pdev, DRIVER_NAME);
+ if (result != 0) {
+ DBG_ERROR(et131x_dbginfo, "Can't get PCI resources\n");
+ goto err_disable;
+ }
+
+ /* Enable PCI bus mastering */
+ DBG_TRACE(et131x_dbginfo, "Setting PCI Bus Mastering...\n");
+ pci_set_master(pdev);
+
+ /* Query PCI for Power Mgmt Capabilities
+ *
+ * NOTE: Now reading PowerMgmt in another location; is this still
+ * needed?
+ */
+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (pm_cap == 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "Cannot find Power Management capabilities\n");
+ result = -EIO;
+ goto err_release_res;
+ }
+
+ /* Check the DMA addressing support of this device */
+ if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
+ DBG_TRACE(et131x_dbginfo, "64-bit DMA addressing supported\n");
+ pci_using_dac = true;
+
+ result =
+ pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (result != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "Unable to obtain 64 bit DMA for consistent allocations\n");
+ goto err_release_res;
+ }
+ } else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) {
+ DBG_TRACE(et131x_dbginfo,
+ "64-bit DMA addressing NOT supported\n");
+ DBG_TRACE(et131x_dbginfo,
+ "32-bit DMA addressing will be used\n");
+ pci_using_dac = false;
+ } else {
+ DBG_ERROR(et131x_dbginfo, "No usable DMA addressing method\n");
+ result = -EIO;
+ goto err_release_res;
+ }
+
+ /* Allocate netdev and private adapter structs */
+ DBG_TRACE(et131x_dbginfo,
+ "Allocate netdev and private adapter structs...\n");
+ netdev = et131x_device_alloc();
+ if (netdev == NULL) {
+ DBG_ERROR(et131x_dbginfo, "Couldn't alloc netdev struct\n");
+ result = -ENOMEM;
+ goto err_release_res;
+ }
+
+ /* Setup the fundamental net_device and private adapter structure elements */
+ DBG_TRACE(et131x_dbginfo, "Setting fundamental net_device info...\n");
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ if (pci_using_dac) {
+ //netdev->features |= NETIF_F_HIGHDMA;
+ }
+
+ /*
+ * NOTE - Turn this on when we're ready to deal with SG-DMA
+ *
+ * NOTE: According to "Linux Device Drivers", 3rd ed, Rubini et al,
+ * if checksumming is not performed in HW, then the kernel will not
+ * use SG.
+ * From pp 510-511:
+ *
+ * "Note that the kernel does not perform scatter/gather I/O to your
+ * device if it does not also provide some form of checksumming as
+ * well. The reason is that, if the kernel has to make a pass over a
+ * fragmented ("nonlinear") packet to calculate the checksum, it
+ * might as well copy the data and coalesce the packet at the same
+ * time."
+ *
+ * This has been verified by setting the flags below and still not
+ * receiving a scattered buffer from the network stack, so leave it
+ * off until checksums are calculated in HW.
+ */
+ //netdev->features |= NETIF_F_SG;
+ //netdev->features |= NETIF_F_NO_CSUM;
+ //netdev->features |= NETIF_F_LLTX;
+
+ /* Allocate private adapter struct and copy in relevant information */
+ adapter = netdev_priv(netdev);
+ adapter->pdev = pdev;
+ adapter->netdev = netdev;
+ adapter->VendorID = pdev->vendor;
+ adapter->DeviceID = pdev->device;
+
+ /* Do the same for the netdev struct */
+ netdev->irq = pdev->irq;
+ netdev->base_addr = pdev->resource[0].start;
+
+ /* Initialize spinlocks here */
+ DBG_TRACE(et131x_dbginfo, "Initialize spinlocks...\n");
+
+ spin_lock_init(&adapter->Lock);
+ spin_lock_init(&adapter->TCBSendQLock);
+ spin_lock_init(&adapter->TCBReadyQLock);
+ spin_lock_init(&adapter->SendHWLock);
+ spin_lock_init(&adapter->SendWaitLock);
+ spin_lock_init(&adapter->RcvLock);
+ spin_lock_init(&adapter->RcvPendLock);
+ spin_lock_init(&adapter->FbrLock);
+ spin_lock_init(&adapter->PHYLock);
+
+ /* Parse configuration parameters into the private adapter struct */
+ et131x_config_parse(adapter);
+
+ /* Find the physical adapter
+ *
+ * NOTE: This is the equivalent of the MpFindAdapter() routine; can we
+ * lump it's init with the device specific init below into a
+ * single init function?
+ */
+ //while (et131x_find_adapter(adapter, pdev) != 0);
+ et131x_find_adapter(adapter, pdev);
+
+ /* Map the bus-relative registers to system virtual memory */
+ DBG_TRACE(et131x_dbginfo,
+ "Mapping bus-relative registers to virtual memory...\n");
+
+ adapter->CSRAddress = ioremap_nocache(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (adapter->CSRAddress == NULL) {
+ DBG_ERROR(et131x_dbginfo, "Cannot map device registers\n");
+ result = -ENOMEM;
+ goto err_free_dev;
+ }
+
+ /* Perform device-specific initialization here (See code below) */
+
+ /* If Phy COMA mode was enabled when we went down, disable it here. */
+ {
+ PM_CSR_t GlobalPmCSR = { 0 };
+
+ GlobalPmCSR.bits.pm_sysclk_gate = 1;
+ GlobalPmCSR.bits.pm_txclk_gate = 1;
+ GlobalPmCSR.bits.pm_rxclk_gate = 1;
+ writel(GlobalPmCSR.value,
+ &adapter->CSRAddress->global.pm_csr.value);
+ }
+
+ /* Issue a global reset to the et1310 */
+ DBG_TRACE(et131x_dbginfo, "Issuing soft reset...\n");
+ et131x_soft_reset(adapter);
+
+ /* Disable all interrupts (paranoid) */
+ DBG_TRACE(et131x_dbginfo, "Disable device interrupts...\n");
+ et131x_disable_interrupts(adapter);
+
+ /* Allocate DMA memory */
+ result = et131x_adapter_memory_alloc(adapter);
+ if (result != 0) {
+ DBG_ERROR(et131x_dbginfo,
+ "Could not alloc adapater memory (DMA)\n");
+ goto err_iounmap;
+ }
+
+ /* Init send data structures */
+ DBG_TRACE(et131x_dbginfo, "Init send data structures...\n");
+ et131x_init_send(adapter);
+
+ adapter->PoMgmt.PowerState = NdisDeviceStateD0;
+
+ /* Register the interrupt
+ *
+ * NOTE - This is being done in the open routine, where most other
+ * Linux drivers setup IRQ handlers. Make sure device
+ * interrupts are not turned on before the IRQ is registered!!
+ *
+ * What we will do here is setup the task structure for the
+ * ISR's deferred handler
+ */
+ INIT_WORK(&adapter->task, et131x_isr_handler);
+
+ /* Determine MAC Address, and copy into the net_device struct */
+ DBG_TRACE(et131x_dbginfo, "Retrieve MAC address...\n");
+ et131x_setup_hardware_properties(adapter);
+
+ memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN);
+
+ /* Setup et1310 as per the documentation */
+ DBG_TRACE(et131x_dbginfo, "Setup the adapter...\n");
+ et131x_adapter_setup(adapter);
+
+ /* Create a timer to count errors received by the NIC */
+ init_timer(&adapter->ErrorTimer);
+
+ adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000;
+ adapter->ErrorTimer.function = et131x_error_timer_handler;
+ adapter->ErrorTimer.data = (unsigned long)adapter;
+
+ /* Initialize link state */
+ et131x_link_detection_handler((unsigned long)adapter);
+
+ /* Intialize variable for counting how long we do not have link status */
+ adapter->PoMgmt.TransPhyComaModeOnBoot = 0;
+
+ /* We can enable interrupts now
+ *
+ * NOTE - Because registration of interrupt handler is done in the
+ * device's open(), defer enabling device interrupts to that
+ * point
+ */
+
+ /* Register the net_device struct with the Linux network layer */
+ DBG_TRACE(et131x_dbginfo, "Registering net_device...\n");
+ if ((result = register_netdev(netdev)) != 0) {
+ DBG_ERROR(et131x_dbginfo, "register_netdev() failed\n");
+ goto err_mem_free;
+ }
+
+ /* Register the net_device struct with the PCI subsystem. Save a copy
+ * of the PCI config space for this device now that the device has
+ * been initialized, just in case it needs to be quickly restored.
+ */
+ pci_set_drvdata(pdev, netdev);
+
+ pci_save_state(adapter->pdev);
+
+out:
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+
+err_mem_free:
+ et131x_adapter_memory_free(adapter);
+err_iounmap:
+ iounmap(adapter->CSRAddress);
+err_free_dev:
+ free_netdev(netdev);
+err_release_res:
+ pci_release_regions(pdev);
+err_disable:
+ pci_disable_device(pdev);
+ goto out;
+}
diff --git a/drivers/staging/et131x/et131x_initpci.h b/drivers/staging/et131x/et131x_initpci.h
new file mode 100644
index 00000000000..bbacb627759
--- /dev/null
+++ b/drivers/staging/et131x/et131x_initpci.h
@@ -0,0 +1,73 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_initpci.h - Header which includes common data and function prototypes
+ * related to the driver's PCI (and PCI Express) information.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_INITPCI_H__
+#define __ET131X_INITPCI_H__
+
+/* Function Prototypes */
+void et131x_align_allocated_memory(struct et131x_adapter *adapter,
+ u64 *phys_addr,
+ u64 *offset, u64 mask);
+
+int et131x_adapter_setup(struct et131x_adapter *adapter);
+int et131x_adapter_memory_alloc(struct et131x_adapter *adapter);
+void et131x_adapter_memory_free(struct et131x_adapter *adapter);
+void et131x_setup_hardware_properties(struct et131x_adapter *adapter);
+void et131x_soft_reset(struct et131x_adapter *adapter);
+
+#endif /* __ET131X_INITPCI_H__ */
diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c
new file mode 100644
index 00000000000..00afad174a6
--- /dev/null
+++ b/drivers/staging/et131x/et131x_isr.c
@@ -0,0 +1,488 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_isr.c - File which contains the ISR, ISR handler, and related routines
+ * for processing interrupts from the device.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+#include "et1310_mac.h"
+
+#include "et131x_adapter.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+/**
+ * et131x_isr - The Interrupt Service Routine for the driver.
+ * @irq: the IRQ on which the interrupt was received.
+ * @dev_id: device-specific info (here a pointer to a net_device struct)
+ *
+ * Returns a value indicating if the interrupt was handled.
+ */
+irqreturn_t et131x_isr(int irq, void *dev_id)
+{
+ bool handled = true;
+ struct net_device *netdev = (struct net_device *)dev_id;
+ struct et131x_adapter *adapter = NULL;
+ INTERRUPT_t status;
+
+ if (netdev == NULL || !netif_device_present(netdev)) {
+ DBG_WARNING(et131x_dbginfo,
+ "No net_device struct or device not present\n");
+ handled = false;
+ goto out;
+ }
+
+ adapter = netdev_priv(netdev);
+
+ /* If the adapter is in low power state, then it should not
+ * recognize any interrupt
+ */
+
+ /* Disable Device Interrupts */
+ et131x_disable_interrupts(adapter);
+
+ /* Get a copy of the value in the interrupt status register
+ * so we can process the interrupting section
+ */
+ status.value = readl(&adapter->CSRAddress->global.int_status.value);
+
+ if (adapter->FlowControl == TxOnly ||
+ adapter->FlowControl == Both) {
+ status.value &= ~INT_MASK_ENABLE;
+ } else {
+ status.value &= ~INT_MASK_ENABLE_NO_FLOW;
+ }
+
+ /* Make sure this is our interrupt */
+ if (!status.value) {
+#ifdef CONFIG_ET131X_DEBUG
+ adapter->Stats.UnhandledInterruptsPerSec++;
+#endif
+ handled = false;
+ DBG_VERBOSE(et131x_dbginfo, "NOT OUR INTERRUPT\n");
+ et131x_enable_interrupts(adapter);
+ goto out;
+ }
+
+ /* This is our interrupt, so process accordingly */
+#ifdef CONFIG_ET131X_DEBUG
+ if (status.bits.rxdma_xfr_done) {
+ adapter->Stats.RxDmaInterruptsPerSec++;
+ }
+
+ if (status.bits.txdma_isr) {
+ adapter->Stats.TxDmaInterruptsPerSec++;
+ }
+#endif
+
+ if (status.bits.watchdog_interrupt) {
+ PMP_TCB pMpTcb = adapter->TxRing.CurrSendHead;
+
+ if (pMpTcb) {
+ if (++pMpTcb->PacketStaleCount > 1) {
+ status.bits.txdma_isr = 1;
+ }
+ }
+
+ if (adapter->RxRing.UnfinishedReceives) {
+ status.bits.rxdma_xfr_done = 1;
+ } else if (pMpTcb == NULL) {
+ writel(0, &adapter->CSRAddress->global.watchdog_timer);
+ }
+
+ status.bits.watchdog_interrupt = 0;
+#ifdef CONFIG_ET131X_DEBUG
+ adapter->Stats.WatchDogInterruptsPerSec++;
+#endif
+ }
+
+ if (status.value == 0) {
+ /* This interrupt has in some way been "handled" by
+ * the ISR. Either it was a spurious Rx interrupt, or
+ * it was a Tx interrupt that has been filtered by
+ * the ISR.
+ */
+ et131x_enable_interrupts(adapter);
+ goto out;
+ }
+
+ /* We need to save the interrupt status value for use in our
+ * DPC. We will clear the software copy of that in that
+ * routine.
+ */
+ adapter->Stats.InterruptStatus = status;
+
+ /* Schedule the ISR handler as a bottom-half task in the
+ * kernel's tq_immediate queue, and mark the queue for
+ * execution
+ */
+ schedule_work(&adapter->task);
+
+out:
+ return IRQ_RETVAL(handled);
+}
+
+/**
+ * et131x_isr_handler - The ISR handler
+ * @p_adapter, a pointer to the device's private adapter structure
+ *
+ * scheduled to run in a deferred context by the ISR. This is where the ISR's
+ * work actually gets done.
+ */
+void et131x_isr_handler(struct work_struct *work)
+{
+ struct et131x_adapter *pAdapter =
+ container_of(work, struct et131x_adapter, task);
+ INTERRUPT_t GlobStatus = pAdapter->Stats.InterruptStatus;
+ ADDRESS_MAP_t __iomem *iomem = pAdapter->CSRAddress;
+
+ /*
+ * These first two are by far the most common. Once handled, we clear
+ * their two bits in the status word. If the word is now zero, we
+ * exit.
+ */
+ /* Handle all the completed Transmit interrupts */
+ if (GlobStatus.bits.txdma_isr) {
+ DBG_TX(et131x_dbginfo, "TXDMA_ISR interrupt\n");
+ et131x_handle_send_interrupt(pAdapter);
+ }
+
+ /* Handle all the completed Receives interrupts */
+ if (GlobStatus.bits.rxdma_xfr_done) {
+ DBG_RX(et131x_dbginfo, "RXDMA_XFR_DONE interrupt\n");
+ et131x_handle_recv_interrupt(pAdapter);
+ }
+
+ GlobStatus.value &= 0xffffffd7;
+
+ if (GlobStatus.value) {
+ /* Handle the TXDMA Error interrupt */
+ if (GlobStatus.bits.txdma_err) {
+ TXDMA_ERROR_t TxDmaErr;
+
+ /* Following read also clears the register (COR) */
+ TxDmaErr.value = readl(&iomem->txdma.TxDmaError.value);
+
+ DBG_WARNING(et131x_dbginfo,
+ "TXDMA_ERR interrupt, error = %d\n",
+ TxDmaErr.value);
+ }
+
+ /* Handle Free Buffer Ring 0 and 1 Low interrupt */
+ if (GlobStatus.bits.rxdma_fb_ring0_low ||
+ GlobStatus.bits.rxdma_fb_ring1_low) {
+ /*
+ * This indicates the number of unused buffers in
+ * RXDMA free buffer ring 0 is <= the limit you
+ * programmed. Free buffer resources need to be
+ * returned. Free buffers are consumed as packets
+ * are passed from the network to the host. The host
+ * becomes aware of the packets from the contents of
+ * the packet status ring. This ring is queried when
+ * the packet done interrupt occurs. Packets are then
+ * passed to the OS. When the OS is done with the
+ * packets the resources can be returned to the
+ * ET1310 for re-use. This interrupt is one method of
+ * returning resources.
+ */
+ DBG_WARNING(et131x_dbginfo,
+ "RXDMA_FB_RING0_LOW or "
+ "RXDMA_FB_RING1_LOW interrupt\n");
+
+ /* If the user has flow control on, then we will
+ * send a pause packet, otherwise just exit
+ */
+ if (pAdapter->FlowControl == TxOnly ||
+ pAdapter->FlowControl == Both) {
+ PM_CSR_t pm_csr;
+
+ /* Tell the device to send a pause packet via
+ * the back pressure register
+ */
+ pm_csr.value = readl(&iomem->global.pm_csr.value);
+ if (pm_csr.bits.pm_phy_sw_coma == 0) {
+ TXMAC_BP_CTRL_t bp_ctrl = { 0 };
+
+ bp_ctrl.bits.bp_req = 1;
+ bp_ctrl.bits.bp_xonxoff = 1;
+ writel(bp_ctrl.value,
+ &iomem->txmac.bp_ctrl.value);
+ }
+ }
+ }
+
+ /* Handle Packet Status Ring Low Interrupt */
+ if (GlobStatus.bits.rxdma_pkt_stat_ring_low) {
+ DBG_WARNING(et131x_dbginfo,
+ "RXDMA_PKT_STAT_RING_LOW interrupt\n");
+
+ /*
+ * Same idea as with the two Free Buffer Rings.
+ * Packets going from the network to the host each
+ * consume a free buffer resource and a packet status
+ * resource. These resoures are passed to the OS.
+ * When the OS is done with the resources, they need
+ * to be returned to the ET1310. This is one method
+ * of returning the resources.
+ */
+ }
+
+ /* Handle RXDMA Error Interrupt */
+ if (GlobStatus.bits.rxdma_err) {
+ /*
+ * The rxdma_error interrupt is sent when a time-out
+ * on a request issued by the JAGCore has occurred or
+ * a completion is returned with an un-successful
+ * status. In both cases the request is considered
+ * complete. The JAGCore will automatically re-try the
+ * request in question. Normally information on events
+ * like these are sent to the host using the "Advanced
+ * Error Reporting" capability. This interrupt is
+ * another way of getting similar information. The
+ * only thing required is to clear the interrupt by
+ * reading the ISR in the global resources. The
+ * JAGCore will do a re-try on the request. Normally
+ * you should never see this interrupt. If you start
+ * to see this interrupt occurring frequently then
+ * something bad has occurred. A reset might be the
+ * thing to do.
+ */
+ // TRAP();
+
+ pAdapter->TxMacTest.value =
+ readl(&iomem->txmac.tx_test.value);
+ DBG_WARNING(et131x_dbginfo,
+ "RxDMA_ERR interrupt, error %x\n",
+ pAdapter->TxMacTest.value);
+ }
+
+ /* Handle the Wake on LAN Event */
+ if (GlobStatus.bits.wake_on_lan) {
+ /*
+ * This is a secondary interrupt for wake on LAN.
+ * The driver should never see this, if it does,
+ * something serious is wrong. We will TRAP the
+ * message when we are in DBG mode, otherwise we
+ * will ignore it.
+ */
+ DBG_ERROR(et131x_dbginfo, "WAKE_ON_LAN interrupt\n");
+ }
+
+ /* Handle the PHY interrupt */
+ if (GlobStatus.bits.phy_interrupt) {
+ PM_CSR_t pm_csr;
+ MI_BMSR_t BmsrInts, BmsrData;
+ MI_ISR_t myIsr;
+
+ DBG_VERBOSE(et131x_dbginfo, "PHY interrupt\n");
+
+ /* If we are in coma mode when we get this interrupt,
+ * we need to disable it.
+ */
+ pm_csr.value = readl(&iomem->global.pm_csr.value);
+ if (pm_csr.bits.pm_phy_sw_coma == 1) {
+ /*
+ * Check to see if we are in coma mode and if
+ * so, disable it because we will not be able
+ * to read PHY values until we are out.
+ */
+ DBG_VERBOSE(et131x_dbginfo,
+ "Device is in COMA mode, "
+ "need to wake up\n");
+ DisablePhyComa(pAdapter);
+ }
+
+ /* Read the PHY ISR to clear the reason for the
+ * interrupt.
+ */
+ MiRead(pAdapter, (uint8_t) offsetof(MI_REGS_t, isr),
+ &myIsr.value);
+
+ if (!pAdapter->ReplicaPhyLoopbk) {
+ MiRead(pAdapter,
+ (uint8_t) offsetof(MI_REGS_t, bmsr),
+ &BmsrData.value);
+
+ BmsrInts.value =
+ pAdapter->Bmsr.value ^ BmsrData.value;
+ pAdapter->Bmsr.value = BmsrData.value;
+
+ DBG_VERBOSE(et131x_dbginfo,
+ "Bmsr.value = 0x%04x,"
+ "Bmsr_ints.value = 0x%04x\n",
+ BmsrData.value, BmsrInts.value);
+
+ /* Do all the cable in / cable out stuff */
+ et131x_Mii_check(pAdapter, BmsrData, BmsrInts);
+ }
+ }
+
+ /* Let's move on to the TxMac */
+ if (GlobStatus.bits.txmac_interrupt) {
+ pAdapter->TxRing.TxMacErr.value =
+ readl(&iomem->txmac.err.value);
+
+ /*
+ * When any of the errors occur and TXMAC generates
+ * an interrupt to report these errors, it usually
+ * means that TXMAC has detected an error in the data
+ * stream retrieved from the on-chip Tx Q. All of
+ * these errors are catastrophic and TXMAC won't be
+ * able to recover data when these errors occur. In
+ * a nutshell, the whole Tx path will have to be reset
+ * and re-configured afterwards.
+ */
+ DBG_WARNING(et131x_dbginfo,
+ "TXMAC interrupt, error 0x%08x\n",
+ pAdapter->TxRing.TxMacErr.value);
+
+ /* If we are debugging, we want to see this error,
+ * otherwise we just want the device to be reset and
+ * continue
+ */
+ //DBG_TRAP();
+ }
+
+ /* Handle RXMAC Interrupt */
+ if (GlobStatus.bits.rxmac_interrupt) {
+ /*
+ * These interrupts are catastrophic to the device,
+ * what we need to do is disable the interrupts and
+ * set the flag to cause us to reset so we can solve
+ * this issue.
+ */
+ // MP_SET_FLAG( pAdapter, fMP_ADAPTER_HARDWARE_ERROR );
+
+ DBG_WARNING(et131x_dbginfo,
+ "RXMAC interrupt, error 0x%08x. Requesting reset\n",
+ readl(&iomem->rxmac.err_reg.value));
+
+ DBG_WARNING(et131x_dbginfo,
+ "Enable 0x%08x, Diag 0x%08x\n",
+ readl(&iomem->rxmac.ctrl.value),
+ readl(&iomem->rxmac.rxq_diag.value));
+
+ /*
+ * If we are debugging, we want to see this error,
+ * otherwise we just want the device to be reset and
+ * continue
+ */
+ // TRAP();
+ }
+
+ /* Handle MAC_STAT Interrupt */
+ if (GlobStatus.bits.mac_stat_interrupt) {
+ /*
+ * This means at least one of the un-masked counters
+ * in the MAC_STAT block has rolled over. Use this
+ * to maintain the top, software managed bits of the
+ * counter(s).
+ */
+ DBG_VERBOSE(et131x_dbginfo, "MAC_STAT interrupt\n");
+ HandleMacStatInterrupt(pAdapter);
+ }
+
+ /* Handle SLV Timeout Interrupt */
+ if (GlobStatus.bits.slv_timeout) {
+ /*
+ * This means a timeout has occured on a read or
+ * write request to one of the JAGCore registers. The
+ * Global Resources block has terminated the request
+ * and on a read request, returned a "fake" value.
+ * The most likely reasons are: Bad Address or the
+ * addressed module is in a power-down state and
+ * can't respond.
+ */
+ DBG_VERBOSE(et131x_dbginfo, "SLV_TIMEOUT interrupt\n");
+ }
+ }
+
+ if (pAdapter->PoMgmt.PowerState == NdisDeviceStateD0) {
+ et131x_enable_interrupts(pAdapter);
+ }
+}
diff --git a/drivers/staging/et131x/et131x_isr.h b/drivers/staging/et131x/et131x_isr.h
new file mode 100644
index 00000000000..76a51d56551
--- /dev/null
+++ b/drivers/staging/et131x/et131x_isr.h
@@ -0,0 +1,65 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_isr.h - Defines, structs, enums, prototypes, etc. pertaining to the
+ * ISR processing code.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_ISR_H__
+#define __ET131X_ISR_H__
+
+irqreturn_t et131x_isr(int irq, void *dev_id);
+void et131x_isr_handler(struct work_struct *work);
+
+#endif /* __ET131X_ISR_H__ */
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
new file mode 100644
index 00000000000..de65972ff36
--- /dev/null
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -0,0 +1,856 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_netdev.c - Routines and data required by all Linux network devices.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#include "et131x_version.h"
+#include "et131x_debug.h"
+#include "et131x_defs.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+
+#include "et1310_phy.h"
+#include "et1310_pm.h"
+#include "et1310_jagcore.h"
+#include "et1310_mac.h"
+#include "et1310_tx.h"
+
+#include "et131x_adapter.h"
+#include "et131x_isr.h"
+#include "et131x_initpci.h"
+
+/* Data for debugging facilities */
+#ifdef CONFIG_ET131X_DEBUG
+extern dbg_info_t *et131x_dbginfo;
+#endif /* CONFIG_ET131X_DEBUG */
+
+struct net_device_stats *et131x_stats(struct net_device *netdev);
+int et131x_open(struct net_device *netdev);
+int et131x_close(struct net_device *netdev);
+int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd);
+void et131x_multicast(struct net_device *netdev);
+int et131x_tx(struct sk_buff *skb, struct net_device *netdev);
+void et131x_tx_timeout(struct net_device *netdev);
+int et131x_change_mtu(struct net_device *netdev, int new_mtu);
+int et131x_set_mac_addr(struct net_device *netdev, void *new_mac);
+void et131x_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+void et131x_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+void et131x_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+
+/**
+ * et131x_device_alloc
+ *
+ * Returns pointer to the allocated and initialized net_device struct for
+ * this device.
+ *
+ * Create instances of net_device and wl_private for the new adapter and
+ * register the device's entry points in the net_device structure.
+ */
+struct net_device *et131x_device_alloc(void)
+{
+ struct net_device *netdev;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Alloc net_device and adapter structs */
+ netdev = alloc_etherdev(sizeof(struct et131x_adapter));
+
+ if (netdev == NULL) {
+ DBG_ERROR(et131x_dbginfo,
+ "Alloc of net_device struct failed\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return NULL;
+ }
+
+ /* Setup the function registration table (and other data) for a
+ * net_device
+ */
+ //netdev->init = &et131x_init;
+ //netdev->set_config = &et131x_config;
+ netdev->get_stats = &et131x_stats;
+ netdev->open = &et131x_open;
+ netdev->stop = &et131x_close;
+ netdev->do_ioctl = &et131x_ioctl;
+ netdev->set_multicast_list = &et131x_multicast;
+ netdev->hard_start_xmit = &et131x_tx;
+ netdev->tx_timeout = &et131x_tx_timeout;
+ netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
+ netdev->change_mtu = &et131x_change_mtu;
+ netdev->set_mac_address = &et131x_set_mac_addr;
+
+ //netdev->ethtool_ops = &et131x_ethtool_ops;
+
+ // Poll?
+ //netdev->poll = &et131x_poll;
+ //netdev->poll_controller = &et131x_poll_controller;
+
+ DBG_LEAVE(et131x_dbginfo);
+ return netdev;
+}
+
+/**
+ * et131x_stats - Return the current device statistics.
+ * @netdev: device whose stats are being queried
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+struct net_device_stats *et131x_stats(struct net_device *netdev)
+{
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+ struct net_device_stats *stats = &adapter->net_stats;
+ CE_STATS_t *devstat = &adapter->Stats;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ stats->rx_packets = devstat->ipackets;
+ stats->tx_packets = devstat->opackets;
+ stats->rx_errors = devstat->length_err + devstat->alignment_err +
+ devstat->crc_err + devstat->code_violations + devstat->other_errors;
+ stats->tx_errors = devstat->max_pkt_error;
+ stats->multicast = devstat->multircv;
+ stats->collisions = devstat->collisions;
+
+ stats->rx_length_errors = devstat->length_err;
+ stats->rx_over_errors = devstat->rx_ov_flow;
+ stats->rx_crc_errors = devstat->crc_err;
+
+ // NOTE: These stats don't have corresponding values in CE_STATS, so we're
+ // going to have to update these directly from within the TX/RX code
+ //stats->rx_bytes = 20; //devstat->;
+ //stats->tx_bytes = 20; //devstat->;
+ //stats->rx_dropped = devstat->;
+ //stats->tx_dropped = devstat->;
+
+ // NOTE: Not used, can't find analogous statistics
+ //stats->rx_frame_errors = devstat->;
+ //stats->rx_fifo_errors = devstat->;
+ //stats->rx_missed_errors = devstat->;
+
+ //stats->tx_aborted_errors = devstat->;
+ //stats->tx_carrier_errors = devstat->;
+ //stats->tx_fifo_errors = devstat->;
+ //stats->tx_heartbeat_errors = devstat->;
+ //stats->tx_window_errors = devstat->;
+
+ DBG_LEAVE(et131x_dbginfo);
+ return stats;
+}
+
+/**
+ * et131x_open - Open the device for use.
+ * @netdev: device to be opened
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_open(struct net_device *netdev)
+{
+ int result = 0;
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Start the timer to track NIC errors */
+ add_timer(&adapter->ErrorTimer);
+
+ /* Register our ISR */
+ DBG_TRACE(et131x_dbginfo, "Registering ISR...\n");
+
+ result =
+ request_irq(netdev->irq, et131x_isr, IRQF_SHARED, netdev->name,
+ netdev);
+ if (result) {
+ DBG_ERROR(et131x_dbginfo, "Could not register ISR\n");
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+ }
+
+ /* Enable the Tx and Rx DMA engines (if not already enabled) */
+ et131x_rx_dma_enable(adapter);
+ et131x_tx_dma_enable(adapter);
+
+ /* Enable device interrupts */
+ et131x_enable_interrupts(adapter);
+
+ MP_SET_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
+
+ /* We're ready to move some data, so start the queue */
+ netif_start_queue(netdev);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+}
+
+/**
+ * et131x_close - Close the device
+ * @netdev: device to be closed
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_close(struct net_device *netdev)
+{
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* First thing is to stop the queue */
+ netif_stop_queue(netdev);
+
+ /* Stop the Tx and Rx DMA engines */
+ et131x_rx_dma_disable(adapter);
+ et131x_tx_dma_disable(adapter);
+
+ /* Disable device interrupts */
+ et131x_disable_interrupts(adapter);
+
+ /* Deregistering ISR */
+ MP_CLEAR_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
+
+ DBG_TRACE(et131x_dbginfo, "Deregistering ISR...\n");
+ free_irq(netdev->irq, netdev);
+
+ /* Stop the error timer */
+ del_timer_sync(&adapter->ErrorTimer);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return 0;
+}
+
+/**
+ * et131x_ioctl_mii - The function which handles MII IOCTLs
+ * @netdev: device on which the query is being made
+ * @reqbuf: the request-specific data buffer
+ * @cmd: the command request code
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_ioctl_mii(struct net_device *netdev, struct ifreq *reqbuf, int cmd)
+{
+ int status = 0;
+ struct et131x_adapter *pAdapter = netdev_priv(netdev);
+ struct mii_ioctl_data *data = if_mii(reqbuf);
+
+ DBG_ENTER(et131x_dbginfo);
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ DBG_VERBOSE(et131x_dbginfo, "SIOCGMIIPHY\n");
+ data->phy_id = pAdapter->Stats.xcvr_addr;
+ break;
+
+ case SIOCGMIIREG:
+ DBG_VERBOSE(et131x_dbginfo, "SIOCGMIIREG\n");
+ if (!capable(CAP_NET_ADMIN)) {
+ status = -EPERM;
+ } else {
+ status = MiRead(pAdapter,
+ data->reg_num, &data->val_out);
+ }
+ break;
+
+ case SIOCSMIIREG:
+ DBG_VERBOSE(et131x_dbginfo, "SIOCSMIIREG\n");
+ if (!capable(CAP_NET_ADMIN)) {
+ status = -EPERM;
+ } else {
+ status = MiWrite(pAdapter, data->reg_num,
+ data->val_in);
+ }
+ break;
+
+ default:
+ status = -EOPNOTSUPP;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_ioctl - The I/O Control handler for the driver
+ * @netdev: device on which the control request is being made
+ * @reqbuf: a pointer to the IOCTL request buffer
+ * @cmd: the IOCTL command code
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd)
+{
+ int status = 0;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ status = et131x_ioctl_mii(netdev, reqbuf, cmd);
+ break;
+
+ default:
+ DBG_WARNING(et131x_dbginfo, "Unhandled IOCTL Code: 0x%04x\n",
+ cmd);
+ status = -EOPNOTSUPP;
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_set_packet_filter - Configures the Rx Packet filtering on the device
+ * @adapter: pointer to our private adapter structure
+ *
+ * Returns 0 on success, errno on failure
+ */
+int et131x_set_packet_filter(struct et131x_adapter *adapter)
+{
+ int status = 0;
+ uint32_t filter = adapter->PacketFilter;
+ RXMAC_CTRL_t ctrl;
+ RXMAC_PF_CTRL_t pf_ctrl;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ ctrl.value = readl(&adapter->CSRAddress->rxmac.ctrl.value);
+ pf_ctrl.value = readl(&adapter->CSRAddress->rxmac.pf_ctrl.value);
+
+ /* Default to disabled packet filtering. Enable it in the individual
+ * case statements that require the device to filter something
+ */
+ ctrl.bits.pkt_filter_disable = 1;
+
+ /* Set us to be in promiscuous mode so we receive everything, this
+ * is also true when we get a packet filter of 0
+ */
+ if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0) {
+ pf_ctrl.bits.filter_broad_en = 0;
+ pf_ctrl.bits.filter_multi_en = 0;
+ pf_ctrl.bits.filter_uni_en = 0;
+ } else {
+ /*
+ * Set us up with Multicast packet filtering. Three cases are
+ * possible - (1) we have a multi-cast list, (2) we receive ALL
+ * multicast entries or (3) we receive none.
+ */
+ if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
+ DBG_VERBOSE(et131x_dbginfo,
+ "Multicast filtering OFF (Rx ALL MULTICAST)\n");
+ pf_ctrl.bits.filter_multi_en = 0;
+ } else {
+ DBG_VERBOSE(et131x_dbginfo, "Multicast filtering ON\n");
+ SetupDeviceForMulticast(adapter);
+ pf_ctrl.bits.filter_multi_en = 1;
+ ctrl.bits.pkt_filter_disable = 0;
+ }
+
+ /* Set us up with Unicast packet filtering */
+ if (filter & ET131X_PACKET_TYPE_DIRECTED) {
+ DBG_VERBOSE(et131x_dbginfo, "Unicast Filtering ON\n");
+ SetupDeviceForUnicast(adapter);
+ pf_ctrl.bits.filter_uni_en = 1;
+ ctrl.bits.pkt_filter_disable = 0;
+ }
+
+ /* Set us up with Broadcast packet filtering */
+ if (filter & ET131X_PACKET_TYPE_BROADCAST) {
+ DBG_VERBOSE(et131x_dbginfo, "Broadcast Filtering ON\n");
+ pf_ctrl.bits.filter_broad_en = 1;
+ ctrl.bits.pkt_filter_disable = 0;
+ } else {
+ DBG_VERBOSE(et131x_dbginfo,
+ "Broadcast Filtering OFF\n");
+ pf_ctrl.bits.filter_broad_en = 0;
+ }
+
+ /* Setup the receive mac configuration registers - Packet
+ * Filter control + the enable / disable for packet filter
+ * in the control reg.
+ */
+ writel(pf_ctrl.value,
+ &adapter->CSRAddress->rxmac.pf_ctrl.value);
+ writel(ctrl.value, &adapter->CSRAddress->rxmac.ctrl.value);
+ }
+
+ DBG_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_multicast - The handler to configure multicasting on the interface
+ * @netdev: a pointer to a net_device struct representing the device
+ */
+void et131x_multicast(struct net_device *netdev)
+{
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+ uint32_t PacketFilter = 0;
+ uint32_t count;
+ unsigned long lockflags;
+ struct dev_mc_list *mclist = netdev->mc_list;
+
+ DBG_ENTER(et131x_dbginfo);
+
+ spin_lock_irqsave(&adapter->Lock, lockflags);
+
+ /* Before we modify the platform-independent filter flags, store them
+ * locally. This allows us to determine if anything's changed and if
+ * we even need to bother the hardware
+ */
+ PacketFilter = adapter->PacketFilter;
+
+ /* Clear the 'multicast' flag locally; becuase we only have a single
+ * flag to check multicast, and multiple multicast addresses can be
+ * set, this is the easiest way to determine if more than one
+ * multicast address is being set.
+ */
+ PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST;
+
+ /* Check the net_device flags and set the device independent flags
+ * accordingly
+ */
+ DBG_VERBOSE(et131x_dbginfo,
+ "MULTICAST ADDR COUNT: %d\n", netdev->mc_count);
+
+ if (netdev->flags & IFF_PROMISC) {
+ DBG_VERBOSE(et131x_dbginfo, "Request: PROMISCUOUS MODE ON\n");
+ adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS;
+ } else {
+ DBG_VERBOSE(et131x_dbginfo, "Request: PROMISCUOUS MODE OFF\n");
+ adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS;
+ }
+
+ if (netdev->flags & IFF_ALLMULTI) {
+ DBG_VERBOSE(et131x_dbginfo, "Request: ACCEPT ALL MULTICAST\n");
+ adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST;
+ }
+
+ if (netdev->mc_count > NIC_MAX_MCAST_LIST) {
+ DBG_WARNING(et131x_dbginfo,
+ "ACCEPT ALL MULTICAST for now, as there's more Multicast "
+ "addresses than the HW supports\n");
+
+ adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST;
+ }
+
+ if (netdev->mc_count < 1) {
+ DBG_VERBOSE(et131x_dbginfo, "Request: REJECT ALL MULTICAST\n");
+ adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST;
+ adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST;
+ } else {
+ DBG_VERBOSE(et131x_dbginfo,
+ "Request: SET MULTICAST FILTER(S)\n");
+ adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST;
+ }
+
+ /* Set values in the private adapter struct */
+ adapter->MCAddressCount = netdev->mc_count;
+
+ if (netdev->mc_count) {
+ if (mclist->dmi_addrlen != ETH_ALEN) {
+ DBG_WARNING(et131x_dbginfo,
+ "Multicast addrs are not ETH_ALEN in size\n");
+ } else {
+ count = netdev->mc_count - 1;
+ memcpy(adapter->MCList[count], mclist->dmi_addr,
+ ETH_ALEN);
+ }
+ }
+
+ /* Are the new flags different from the previous ones? If not, then no
+ * action is required
+ *
+ * NOTE - This block will always update the MCList with the hardware,
+ * even if the addresses aren't the same.
+ */
+ if (PacketFilter != adapter->PacketFilter) {
+ /* Call the device's filter function */
+ DBG_VERBOSE(et131x_dbginfo, "UPDATE REQUIRED, FLAGS changed\n");
+
+ et131x_set_packet_filter(adapter);
+ } else {
+ DBG_VERBOSE(et131x_dbginfo,
+ "NO UPDATE REQUIRED, FLAGS didn't change\n");
+ }
+
+ spin_unlock_irqrestore(&adapter->Lock, lockflags);
+
+ DBG_LEAVE(et131x_dbginfo);
+}
+
+/**
+ * et131x_tx - The handler to tx a packet on the device
+ * @skb: data to be Tx'd
+ * @netdev: device on which data is to be Tx'd
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+ int status = 0;
+
+ DBG_TX_ENTER(et131x_dbginfo);
+
+ /* Save the timestamp for the TX timeout watchdog */
+ netdev->trans_start = jiffies;
+
+ /* Call the device-specific data Tx routine */
+ status = et131x_send_packets(skb, netdev);
+
+ /* Check status and manage the netif queue if necessary */
+ if (status != 0) {
+ if (status == -ENOMEM) {
+ DBG_VERBOSE(et131x_dbginfo,
+ "OUT OF TCBs; STOP NETIF QUEUE\n");
+
+ /* Put the queue to sleep until resources are
+ * available
+ */
+ netif_stop_queue(netdev);
+ status = 1;
+ } else {
+ DBG_WARNING(et131x_dbginfo,
+ "Misc error; drop packet\n");
+ status = 0;
+ }
+ }
+
+ DBG_TX_LEAVE(et131x_dbginfo);
+ return status;
+}
+
+/**
+ * et131x_tx_timeout - Timeout handler
+ * @netdev: a pointer to a net_device struct representing the device
+ *
+ * The handler called when a Tx request times out. The timeout period is
+ * specified by the 'tx_timeo" element in the net_device structure (see
+ * et131x_alloc_device() to see how this value is set).
+ */
+void et131x_tx_timeout(struct net_device *netdev)
+{
+ struct et131x_adapter *pAdapter = netdev_priv(netdev);
+ PMP_TCB pMpTcb;
+ unsigned long lockflags;
+
+ DBG_WARNING(et131x_dbginfo, "TX TIMEOUT\n");
+
+ /* Just skip this part if the adapter is doing link detection */
+ if (MP_TEST_FLAG(pAdapter, fMP_ADAPTER_LINK_DETECTION)) {
+ DBG_ERROR(et131x_dbginfo, "Still doing link detection\n");
+ return;
+ }
+
+ /* Any nonrecoverable hardware error?
+ * Checks adapter->flags for any failure in phy reading
+ */
+ if (MP_TEST_FLAG(pAdapter, fMP_ADAPTER_NON_RECOVER_ERROR)) {
+ DBG_WARNING(et131x_dbginfo, "Non recoverable error - remove\n");
+ return;
+ }
+
+ /* Hardware failure? */
+ if (MP_TEST_FLAG(pAdapter, fMP_ADAPTER_HARDWARE_ERROR)) {
+ DBG_WARNING(et131x_dbginfo, "hardware error - reset\n");
+ return;
+ }
+
+ /* Is send stuck? */
+ spin_lock_irqsave(&pAdapter->TCBSendQLock, lockflags);
+
+ pMpTcb = pAdapter->TxRing.CurrSendHead;
+
+ if (pMpTcb != NULL) {
+ pMpTcb->Count++;
+
+ if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD) {
+#ifdef CONFIG_ET131X_DEBUG
+ TX_STATUS_BLOCK_t txDmaComplete =
+ *(pAdapter->TxRing.pTxStatusVa);
+ PTX_DESC_ENTRY_t pDesc =
+ pAdapter->TxRing.pTxDescRingVa +
+ pMpTcb->WrIndex.bits.val;
+#endif
+ TX_DESC_ENTRY_t StuckDescriptors[10];
+
+ if (pMpTcb->WrIndex.bits.val > 7) {
+ memcpy(StuckDescriptors,
+ pAdapter->TxRing.pTxDescRingVa +
+ pMpTcb->WrIndex.bits.val - 6,
+ sizeof(TX_DESC_ENTRY_t) * 10);
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock,
+ lockflags);
+
+ DBG_WARNING(et131x_dbginfo,
+ "Send stuck - reset. pMpTcb->WrIndex %x, Flags 0x%08x\n",
+ pMpTcb->WrIndex.bits.val,
+ pMpTcb->Flags);
+
+ DBG_WARNING(et131x_dbginfo,
+ "pDesc 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ pDesc->DataBufferPtrHigh,
+ pDesc->DataBufferPtrLow, pDesc->word2.value,
+ pDesc->word3.value);
+
+ DBG_WARNING(et131x_dbginfo,
+ "WbStatus 0x%08x\n", txDmaComplete.value);
+
+#ifdef CONFIG_ET131X_DEBUG
+ DumpDeviceBlock(DBG_WARNING_ON, pAdapter, 0);
+ DumpDeviceBlock(DBG_WARNING_ON, pAdapter, 1);
+ DumpDeviceBlock(DBG_WARNING_ON, pAdapter, 3);
+ DumpDeviceBlock(DBG_WARNING_ON, pAdapter, 5);
+#endif
+ et131x_close(netdev);
+ et131x_open(netdev);
+
+ return;
+ }
+ }
+
+ spin_unlock_irqrestore(&pAdapter->TCBSendQLock, lockflags);
+}
+
+/**
+ * et131x_change_mtu - The handler called to change the MTU for the device
+ * @netdev: device whose MTU is to be changed
+ * @new_mtu: the desired MTU
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ */
+int et131x_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ int result = 0;
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+
+ DBG_ENTER(et131x_dbginfo);
+
+ /* Make sure the requested MTU is valid */
+ if (new_mtu == 0 || new_mtu > 9216) {
+ DBG_LEAVE(et131x_dbginfo);
+ return -EINVAL;
+ }
+
+ /* Stop the netif queue */
+ netif_stop_queue(netdev);
+
+ /* Stop the Tx and Rx DMA engines */
+ et131x_rx_dma_disable(adapter);
+ et131x_tx_dma_disable(adapter);
+
+ /* Disable device interrupts */
+ et131x_disable_interrupts(adapter);
+ et131x_handle_send_interrupt(adapter);
+ et131x_handle_recv_interrupt(adapter);
+
+ /* Set the new MTU */
+ netdev->mtu = new_mtu;
+
+ /* Free Rx DMA memory */
+ et131x_adapter_memory_free(adapter);
+
+ /* Set the config parameter for Jumbo Packet support */
+ adapter->RegistryJumboPacket = new_mtu + 14;
+ et131x_soft_reset(adapter);
+
+ /* Alloc and init Rx DMA memory */
+ result = et131x_adapter_memory_alloc(adapter);
+ if (result != 0) {
+ DBG_WARNING(et131x_dbginfo,
+ "Change MTU failed; couldn't re-alloc DMA memory\n");
+ return result;
+ }
+
+ et131x_init_send(adapter);
+
+ et131x_setup_hardware_properties(adapter);
+ memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN);
+
+ /* Init the device with the new settings */
+ et131x_adapter_setup(adapter);
+
+ /* Enable interrupts */
+ if (MP_TEST_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE)) {
+ et131x_enable_interrupts(adapter);
+ }
+
+ /* Restart the Tx and Rx DMA engines */
+ et131x_rx_dma_enable(adapter);
+ et131x_tx_dma_enable(adapter);
+
+ /* Restart the netif queue */
+ netif_wake_queue(netdev);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+}
+
+/**
+ * et131x_set_mac_addr - handler to change the MAC address for the device
+ * @netdev: device whose MAC is to be changed
+ * @new_mac: the desired MAC address
+ *
+ * Returns 0 on success, errno on failure (as defined in errno.h)
+ *
+ * IMPLEMENTED BY : blux http://berndlux.de 22.01.2007 21:14
+ */
+int et131x_set_mac_addr(struct net_device *netdev, void *new_mac)
+{
+ int result = 0;
+ struct et131x_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *address = new_mac;
+
+ DBG_ENTER(et131x_dbginfo);
+ // begin blux
+ // DBG_VERBOSE( et131x_dbginfo, "Function not implemented!!\n" );
+
+ if (adapter == NULL) {
+ DBG_LEAVE(et131x_dbginfo);
+ return -ENODEV;
+ }
+
+ /* Make sure the requested MAC is valid */
+ if (!is_valid_ether_addr(address->sa_data)) {
+ DBG_LEAVE(et131x_dbginfo);
+ return -EINVAL;
+ }
+
+ /* Stop the netif queue */
+ netif_stop_queue(netdev);
+
+ /* Stop the Tx and Rx DMA engines */
+ et131x_rx_dma_disable(adapter);
+ et131x_tx_dma_disable(adapter);
+
+ /* Disable device interrupts */
+ et131x_disable_interrupts(adapter);
+ et131x_handle_send_interrupt(adapter);
+ et131x_handle_recv_interrupt(adapter);
+
+ /* Set the new MAC */
+ // netdev->set_mac_address = &new_mac;
+ // netdev->mtu = new_mtu;
+
+ memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len);
+
+ printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->name, netdev->dev_addr[0], netdev->dev_addr[1],
+ netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4],
+ netdev->dev_addr[5]);
+
+ /* Free Rx DMA memory */
+ et131x_adapter_memory_free(adapter);
+
+ /* Set the config parameter for Jumbo Packet support */
+ // adapter->RegistryJumboPacket = new_mtu + 14;
+ // blux: not needet here, w'll change the MAC
+
+ et131x_soft_reset(adapter);
+
+ /* Alloc and init Rx DMA memory */
+ result = et131x_adapter_memory_alloc(adapter);
+ if (result != 0) {
+ DBG_WARNING(et131x_dbginfo,
+ "Change MAC failed; couldn't re-alloc DMA memory\n");
+ return result;
+ }
+
+ et131x_init_send(adapter);
+
+ et131x_setup_hardware_properties(adapter);
+ // memcpy( netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN );
+ // blux: no, do not override our nice address
+
+ /* Init the device with the new settings */
+ et131x_adapter_setup(adapter);
+
+ /* Enable interrupts */
+ if (MP_TEST_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE)) {
+ et131x_enable_interrupts(adapter);
+ }
+
+ /* Restart the Tx and Rx DMA engines */
+ et131x_rx_dma_enable(adapter);
+ et131x_tx_dma_enable(adapter);
+
+ /* Restart the netif queue */
+ netif_wake_queue(netdev);
+
+ DBG_LEAVE(et131x_dbginfo);
+ return result;
+}
diff --git a/drivers/staging/et131x/et131x_netdev.h b/drivers/staging/et131x/et131x_netdev.h
new file mode 100644
index 00000000000..b8acd14ff83
--- /dev/null
+++ b/drivers/staging/et131x/et131x_netdev.h
@@ -0,0 +1,64 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_netdev.h - Defines, structs, enums, prototypes, etc. related to the
+ * driver's net_device support.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_NETDEV_H__
+#define __ET131X_NETDEV_H__
+
+struct net_device *et131x_device_alloc(void);
+
+#endif /* __ET131X_NETDEV_H__ */
diff --git a/drivers/staging/et131x/et131x_version.h b/drivers/staging/et131x/et131x_version.h
new file mode 100644
index 00000000000..2ea645e1066
--- /dev/null
+++ b/drivers/staging/et131x/et131x_version.h
@@ -0,0 +1,81 @@
+/*
+ * Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ *------------------------------------------------------------------------------
+ *
+ * et131x_version.h - This file provides system and device version information.
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . 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.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. 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, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+#ifndef __ET131X_VERSION_H__
+#define __ET131X_VERSION_H__
+
+#define DRIVER_AUTHOR "Victor Soriano (vjsoriano@agere.com)"
+#define DRIVER_LICENSE "Dual BSD/GPL"
+#define DRIVER_DEVICE_STRING "ET1310"
+#define DRIVER_NAME "et131x"
+#define DRIVER_MAJOR_VERSION 1
+#define DRIVER_MINOR_VERSION 2
+#define DRIVER_PATCH_VERSION 3
+#define DRIVER_VERSION_STRING "1.2.3"
+#define DRIVER_VENDOR "Agere Systems, http://www.agere.com"
+#define DRIVER_DESC "10/100/1000 Base-T Ethernet Driver"
+
+#define STRUCT_MODULE "net" /* blux: missed by the kernel */
+
+#define DRIVER_INFO DRIVER_DESC " for the "\
+ DRIVER_DEVICE_STRING ", v" \
+ DRIVER_VERSION_STRING " by " \
+ DRIVER_VENDOR
+
+#define DRIVER_NAME_EXT "et131x.ko"
+
+#endif /* __ET131X_VERSION_H__ */
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
new file mode 100644
index 00000000000..57a121c338c
--- /dev/null
+++ b/drivers/staging/go7007/Kconfig
@@ -0,0 +1,25 @@
+config VIDEO_GO7007
+ tristate "Go 7007 support"
+ depends on VIDEO_DEV && PCI && I2C && INPUT
+ select VIDEOBUF_DMA_SG
+ select VIDEO_IR
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select CRC32
+ default N
+ ---help---
+ This is a video4linux driver for some wierd device...
+
+ To compile this driver as a module, choose M here: the
+ module will be called go7007
+
+config VIDEO_GO7007_USB
+ tristate "Go 7007 USB support"
+ depends on VIDEO_GO7007 && USB
+ default N
+ ---help---
+ This is a video4linux driver for some wierd device...
+
+ To compile this driver as a module, choose M here: the
+ module will be called go7007-usb
+
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile
new file mode 100644
index 00000000000..9b9310cae1c
--- /dev/null
+++ b/drivers/staging/go7007/Makefile
@@ -0,0 +1,18 @@
+#obj-m += go7007.o go7007-usb.o snd-go7007.o wis-saa7115.o wis-tw9903.o \
+ wis-uda1342.o wis-sony-tuner.o wis-saa7113.o wis-ov7640.o \
+ wis-tw2804.o
+
+
+obj-$(CONFIG_VIDEO_GO7007) += go7007.o
+obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
+
+go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o snd-go7007.o
+
+
+#ifneq ($(SAA7134_BUILD),)
+#obj-m += saa7134-go7007.o
+#endif
+
+EXTRA_CFLAGS += -Idrivers/staging/saa7134
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/go7007/README b/drivers/staging/go7007/README
new file mode 100644
index 00000000000..48f44763781
--- /dev/null
+++ b/drivers/staging/go7007/README
@@ -0,0 +1,11 @@
+Todo:
+ - checkpatch.pl cleanups
+ - sparse cleanups
+ - lots of little modules, should be merged together
+ and added to the build.
+ - testing?
+ - handle churn in v4l layer.
+
+Please send patchs to Greg Kroah-Hartman <greg@kroah.com> and Cc: Ross
+Cohen <rcohen@snurgle.org> as well.
+
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
new file mode 100644
index 00000000000..81ae4b0fa89
--- /dev/null
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+
+#include "go7007-priv.h"
+#include "wis-i2c.h"
+
+/*
+ * Wait for an interrupt to be delivered from the GO7007SB and return
+ * the associated value and data.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
+{
+ go->interrupt_available = 0;
+ go->hpi_ops->read_interrupt(go);
+ if (wait_event_timeout(go->interrupt_waitq,
+ go->interrupt_available, 5*HZ) < 0) {
+ printk(KERN_ERR "go7007: timeout waiting for read interrupt\n");
+ return -1;
+ }
+ if (!go->interrupt_available)
+ return -1;
+ go->interrupt_available = 0;
+ *value = go->interrupt_value & 0xfffe;
+ *data = go->interrupt_data;
+ return 0;
+}
+EXPORT_SYMBOL(go7007_read_interrupt);
+
+/*
+ * Read a register/address on the GO7007SB.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data)
+{
+ int count = 100;
+ u16 value;
+
+ if (go7007_write_interrupt(go, 0x0010, addr) < 0)
+ return -EIO;
+ while (count-- > 0) {
+ if (go7007_read_interrupt(go, &value, data) == 0 &&
+ value == 0xa000)
+ return 0;
+ }
+ return -EIO;
+}
+EXPORT_SYMBOL(go7007_read_addr);
+
+/*
+ * Send the boot firmware to the encoder, which just wakes it up and lets
+ * us talk to the GPIO pins and on-board I2C adapter.
+ *
+ * Must be called with the hw_lock held.
+ */
+static int go7007_load_encoder(struct go7007 *go)
+{
+ const struct firmware *fw_entry;
+ char fw_name[] = "go7007fw.bin";
+ void *bounce;
+ int fw_len, rv = 0;
+ u16 intr_val, intr_data;
+
+ if (request_firmware(&fw_entry, fw_name, go->dev)) {
+ printk(KERN_ERR
+ "go7007: unable to load firmware from file \"%s\"\n",
+ fw_name);
+ return -1;
+ }
+ if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
+ printk(KERN_ERR "go7007: file \"%s\" does not appear to be "
+ "go7007 firmware\n", fw_name);
+ release_firmware(fw_entry);
+ return -1;
+ }
+ fw_len = fw_entry->size - 16;
+ bounce = kmalloc(fw_len, GFP_KERNEL);
+ if (bounce == NULL) {
+ printk(KERN_ERR "go7007: unable to allocate %d bytes for "
+ "firmware transfer\n", fw_len);
+ release_firmware(fw_entry);
+ return -1;
+ }
+ memcpy(bounce, fw_entry->data + 16, fw_len);
+ release_firmware(fw_entry);
+ if (go7007_interface_reset(go) < 0 ||
+ go7007_send_firmware(go, bounce, fw_len) < 0 ||
+ go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+ (intr_val & ~0x1) != 0x5a5a) {
+ printk(KERN_ERR "go7007: error transferring firmware\n");
+ rv = -1;
+ }
+ kfree(bounce);
+ return rv;
+}
+
+/*
+ * Boot the encoder and register the I2C adapter if requested. Do the
+ * minimum initialization necessary, since the board-specific code may
+ * still need to probe the board ID.
+ *
+ * Must NOT be called with the hw_lock held.
+ */
+int go7007_boot_encoder(struct go7007 *go, int init_i2c)
+{
+ int ret;
+
+ down(&go->hw_lock);
+ ret = go7007_load_encoder(go);
+ up(&go->hw_lock);
+ if (ret < 0)
+ return -1;
+ if (!init_i2c)
+ return 0;
+ if (go7007_i2c_init(go) < 0)
+ return -1;
+ go->i2c_adapter_online = 1;
+ return 0;
+}
+EXPORT_SYMBOL(go7007_boot_encoder);
+
+/*
+ * Configure any hardware-related registers in the GO7007, such as GPIO
+ * pins and bus parameters, which are board-specific. This assumes
+ * the boot firmware has already been downloaded.
+ *
+ * Must be called with the hw_lock held.
+ */
+static int go7007_init_encoder(struct go7007 *go)
+{
+ if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
+ go7007_write_addr(go, 0x1000, 0x0811);
+ go7007_write_addr(go, 0x1000, 0x0c11);
+ }
+ if (go->board_id == GO7007_BOARDID_MATRIX_REV) {
+ /* Set GPIO pin 0 to be an output (audio clock control) */
+ go7007_write_addr(go, 0x3c82, 0x0001);
+ go7007_write_addr(go, 0x3c80, 0x00fe);
+ }
+ return 0;
+}
+
+/*
+ * Send the boot firmware to the GO7007 and configure the registers. This
+ * is the only way to stop the encoder once it has started streaming video.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_reset_encoder(struct go7007 *go)
+{
+ if (go7007_load_encoder(go) < 0)
+ return -1;
+ return go7007_init_encoder(go);
+}
+
+/*
+ * Attempt to instantiate an I2C client by ID, probably loading a module.
+ */
+static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
+{
+ char *modname;
+
+ switch (id) {
+ case I2C_DRIVERID_WIS_SAA7115:
+ modname = "wis-saa7115";
+ break;
+ case I2C_DRIVERID_WIS_SAA7113:
+ modname = "wis-saa7113";
+ break;
+ case I2C_DRIVERID_WIS_UDA1342:
+ modname = "wis-uda1342";
+ break;
+ case I2C_DRIVERID_WIS_SONY_TUNER:
+ modname = "wis-sony-tuner";
+ break;
+ case I2C_DRIVERID_WIS_TW9903:
+ modname = "wis-tw9903";
+ break;
+ case I2C_DRIVERID_WIS_TW2804:
+ modname = "wis-tw2804";
+ break;
+ case I2C_DRIVERID_WIS_OV7640:
+ modname = "wis-ov7640";
+ break;
+ default:
+ modname = NULL;
+ break;
+ }
+ if (modname != NULL)
+ request_module(modname);
+ if (wis_i2c_probe_device(adapter, id, addr) == 1)
+ return 0;
+ if (modname != NULL)
+ printk(KERN_INFO
+ "go7007: probing for module %s failed", modname);
+ else
+ printk(KERN_INFO
+ "go7007: sensor %u seems to be unsupported!\n", id);
+ return -1;
+}
+
+/*
+ * Finalize the GO7007 hardware setup, register the on-board I2C adapter
+ * (if used on this board), load the I2C client driver for the sensor
+ * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2
+ * interfaces.
+ *
+ * Must NOT be called with the hw_lock held.
+ */
+int go7007_register_encoder(struct go7007 *go)
+{
+ int i, ret;
+
+ printk(KERN_INFO "go7007: registering new %s\n", go->name);
+
+ down(&go->hw_lock);
+ ret = go7007_init_encoder(go);
+ up(&go->hw_lock);
+ if (ret < 0)
+ return -1;
+
+ if (!go->i2c_adapter_online &&
+ go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
+ if (go7007_i2c_init(go) < 0)
+ return -1;
+ go->i2c_adapter_online = 1;
+ }
+ if (go->i2c_adapter_online) {
+ for (i = 0; i < go->board_info->num_i2c_devs; ++i)
+ init_i2c_module(&go->i2c_adapter,
+ go->board_info->i2c_devs[i].id,
+ go->board_info->i2c_devs[i].addr);
+#ifdef TUNER_SET_TYPE_ADDR
+ if (go->tuner_type >= 0) {
+ struct tuner_setup tun_setup = {
+ .mode_mask = T_ANALOG_TV,
+ .addr = ADDR_UNSET,
+ .type = go->tuner_type
+ };
+ i2c_clients_command(&go->i2c_adapter,
+ TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+#else
+ if (go->tuner_type >= 0)
+ i2c_clients_command(&go->i2c_adapter,
+ TUNER_SET_TYPE, &go->tuner_type);
+#endif
+ if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
+ i2c_clients_command(&go->i2c_adapter,
+ DECODER_SET_CHANNEL, &go->channel_number);
+ }
+ if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
+ go->audio_enabled = 1;
+ go7007_snd_init(go);
+ }
+ return go7007_v4l2_init(go);
+}
+EXPORT_SYMBOL(go7007_register_encoder);
+
+/*
+ * Send the encode firmware to the encoder, which will cause it
+ * to immediately start delivering the video and audio streams.
+ *
+ * Must be called with the hw_lock held.
+ */
+int go7007_start_encoder(struct go7007 *go)
+{
+ u8 *fw;
+ int fw_len, rv = 0, i;
+ u16 intr_val, intr_data;
+
+ go->modet_enable = 0;
+ if (!go->dvd_mode)
+ for (i = 0; i < 4; ++i) {
+ if (go->modet[i].enable) {
+ go->modet_enable = 1;
+ continue;
+ }
+ go->modet[i].pixel_threshold = 32767;
+ go->modet[i].motion_threshold = 32767;
+ go->modet[i].mb_threshold = 32767;
+ }
+
+ if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
+ return -1;
+
+ if (go7007_send_firmware(go, fw, fw_len) < 0 ||
+ go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
+ printk(KERN_ERR "go7007: error transferring firmware\n");
+ rv = -1;
+ goto start_error;
+ }
+
+ go->state = STATE_DATA;
+ go->parse_length = 0;
+ go->seen_frame = 0;
+ if (go7007_stream_start(go) < 0) {
+ printk(KERN_ERR "go7007: error starting stream transfer\n");
+ rv = -1;
+ goto start_error;
+ }
+
+start_error:
+ kfree(fw);
+ return rv;
+}
+
+/*
+ * Store a byte in the current video buffer, if there is one.
+ */
+static inline void store_byte(struct go7007_buffer *gobuf, u8 byte)
+{
+ if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) {
+ unsigned int pgidx = gobuf->offset >> PAGE_SHIFT;
+ unsigned int pgoff = gobuf->offset & ~PAGE_MASK;
+
+ *((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte;
+ ++gobuf->offset;
+ ++gobuf->bytesused;
+ }
+}
+
+/*
+ * Deliver the last video buffer and get a new one to start writing to.
+ */
+static void frame_boundary(struct go7007 *go)
+{
+ struct go7007_buffer *gobuf;
+ int i;
+
+ if (go->active_buf) {
+ if (go->active_buf->modet_active) {
+ if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) {
+ for (i = 0; i < 216; ++i)
+ store_byte(go->active_buf,
+ go->active_map[i]);
+ go->active_buf->bytesused -= 216;
+ } else
+ go->active_buf->modet_active = 0;
+ }
+ go->active_buf->state = BUF_STATE_DONE;
+ wake_up_interruptible(&go->frame_waitq);
+ go->active_buf = NULL;
+ }
+ list_for_each_entry(gobuf, &go->stream, stream)
+ if (gobuf->state == BUF_STATE_QUEUED) {
+ gobuf->seq = go->next_seq;
+ do_gettimeofday(&gobuf->timestamp);
+ go->active_buf = gobuf;
+ break;
+ }
+ ++go->next_seq;
+}
+
+static void write_bitmap_word(struct go7007 *go)
+{
+ int x, y, i, stride = ((go->width >> 4) + 7) >> 3;
+
+ for (i = 0; i < 16; ++i) {
+ y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4);
+ x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4);
+ go->active_map[stride * y + (x >> 3)] |=
+ (go->modet_word & 1) << (x & 0x7);
+ go->modet_word >>= 1;
+ }
+}
+
+/*
+ * Parse a chunk of the video stream into frames. The frames are not
+ * delimited by the hardware, so we have to parse the frame boundaries
+ * based on the type of video stream we're receiving.
+ */
+void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
+{
+ int i, seq_start_code = -1, frame_start_code = -1;
+
+ spin_lock(&go->spinlock);
+
+ switch (go->format) {
+ case GO7007_FORMAT_MPEG4:
+ seq_start_code = 0xB0;
+ frame_start_code = 0xB6;
+ break;
+ case GO7007_FORMAT_MPEG1:
+ case GO7007_FORMAT_MPEG2:
+ seq_start_code = 0xB3;
+ frame_start_code = 0x00;
+ break;
+ }
+
+ for (i = 0; i < length; ++i) {
+ if (go->active_buf != NULL &&
+ go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) {
+ printk(KERN_DEBUG "go7007: dropping oversized frame\n");
+ go->active_buf->offset -= go->active_buf->bytesused;
+ go->active_buf->bytesused = 0;
+ go->active_buf->modet_active = 0;
+ go->active_buf = NULL;
+ }
+
+ switch (go->state) {
+ case STATE_DATA:
+ switch (buf[i]) {
+ case 0x00:
+ go->state = STATE_00;
+ break;
+ case 0xFF:
+ go->state = STATE_FF;
+ break;
+ default:
+ store_byte(go->active_buf, buf[i]);
+ break;
+ }
+ break;
+ case STATE_00:
+ switch (buf[i]) {
+ case 0x00:
+ go->state = STATE_00_00;
+ break;
+ case 0xFF:
+ store_byte(go->active_buf, 0x00);
+ go->state = STATE_FF;
+ break;
+ default:
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, buf[i]);
+ go->state = STATE_DATA;
+ break;
+ }
+ break;
+ case STATE_00_00:
+ switch (buf[i]) {
+ case 0x00:
+ store_byte(go->active_buf, 0x00);
+ /* go->state remains STATE_00_00 */
+ break;
+ case 0x01:
+ go->state = STATE_00_00_01;
+ break;
+ case 0xFF:
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x00);
+ go->state = STATE_FF;
+ break;
+ default:
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, buf[i]);
+ go->state = STATE_DATA;
+ break;
+ }
+ break;
+ case STATE_00_00_01:
+ /* If this is the start of a new MPEG frame,
+ * get a new buffer */
+ if ((go->format == GO7007_FORMAT_MPEG1 ||
+ go->format == GO7007_FORMAT_MPEG2 ||
+ go->format == GO7007_FORMAT_MPEG4) &&
+ (buf[i] == seq_start_code ||
+ buf[i] == 0xB8 || /* GOP code */
+ buf[i] == frame_start_code)) {
+ if (go->active_buf == NULL || go->seen_frame)
+ frame_boundary(go);
+ if (buf[i] == frame_start_code) {
+ if (go->active_buf != NULL)
+ go->active_buf->frame_offset =
+ go->active_buf->offset;
+ go->seen_frame = 1;
+ } else {
+ go->seen_frame = 0;
+ }
+ }
+ /* Handle any special chunk types, or just write the
+ * start code to the (potentially new) buffer */
+ switch (buf[i]) {
+ case 0xF5: /* timestamp */
+ go->parse_length = 12;
+ go->state = STATE_UNPARSED;
+ break;
+ case 0xF6: /* vbi */
+ go->state = STATE_VBI_LEN_A;
+ break;
+ case 0xF8: /* MD map */
+ go->parse_length = 0;
+ memset(go->active_map, 0,
+ sizeof(go->active_map));
+ go->state = STATE_MODET_MAP;
+ break;
+ case 0xFF: /* Potential JPEG start code */
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x01);
+ go->state = STATE_FF;
+ break;
+ default:
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x00);
+ store_byte(go->active_buf, 0x01);
+ store_byte(go->active_buf, buf[i]);
+ go->state = STATE_DATA;
+ break;
+ }
+ break;
+ case STATE_FF:
+ switch (buf[i]) {
+ case 0x00:
+ store_byte(go->active_buf, 0xFF);
+ go->state = STATE_00;
+ break;
+ case 0xFF:
+ store_byte(go->active_buf, 0xFF);
+ /* go->state remains STATE_FF */
+ break;
+ case 0xD8:
+ if (go->format == GO7007_FORMAT_MJPEG)
+ frame_boundary(go);
+ /* fall through */
+ default:
+ store_byte(go->active_buf, 0xFF);
+ store_byte(go->active_buf, buf[i]);
+ go->state = STATE_DATA;
+ break;
+ }
+ break;
+ case STATE_VBI_LEN_A:
+ go->parse_length = buf[i] << 8;
+ go->state = STATE_VBI_LEN_B;
+ break;
+ case STATE_VBI_LEN_B:
+ go->parse_length |= buf[i];
+ if (go->parse_length > 0)
+ go->state = STATE_UNPARSED;
+ else
+ go->state = STATE_DATA;
+ break;
+ case STATE_MODET_MAP:
+ if (go->parse_length < 204) {
+ if (go->parse_length & 1) {
+ go->modet_word |= buf[i];
+ write_bitmap_word(go);
+ } else
+ go->modet_word = buf[i] << 8;
+ } else if (go->parse_length == 207 && go->active_buf) {
+ go->active_buf->modet_active = buf[i];
+ }
+ if (++go->parse_length == 208)
+ go->state = STATE_DATA;
+ break;
+ case STATE_UNPARSED:
+ if (--go->parse_length == 0)
+ go->state = STATE_DATA;
+ break;
+ }
+ }
+
+ spin_unlock(&go->spinlock);
+}
+EXPORT_SYMBOL(go7007_parse_video_stream);
+
+/*
+ * Allocate a new go7007 struct. Used by the hardware-specific probe.
+ */
+struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
+{
+ struct go7007 *go;
+ int i;
+
+ go = kmalloc(sizeof(struct go7007), GFP_KERNEL);
+ if (go == NULL)
+ return NULL;
+ go->dev = dev;
+ go->board_info = board;
+ go->board_id = 0;
+ go->tuner_type = -1;
+ go->channel_number = 0;
+ go->name[0] = 0;
+ init_MUTEX(&go->hw_lock);
+ init_waitqueue_head(&go->frame_waitq);
+ spin_lock_init(&go->spinlock);
+ go->video_dev = NULL;
+ go->ref_count = 0;
+ go->status = STATUS_INIT;
+ memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
+ go->i2c_adapter_online = 0;
+ go->interrupt_available = 0;
+ init_waitqueue_head(&go->interrupt_waitq);
+ go->in_use = 0;
+ go->input = 0;
+ if (board->sensor_flags & GO7007_SENSOR_TV) {
+ go->standard = GO7007_STD_NTSC;
+ go->width = 720;
+ go->height = 480;
+ go->sensor_framerate = 30000;
+ } else {
+ go->standard = GO7007_STD_OTHER;
+ go->width = board->sensor_width;
+ go->height = board->sensor_height;
+ go->sensor_framerate = board->sensor_framerate;
+ }
+ go->encoder_v_offset = board->sensor_v_offset;
+ go->encoder_h_offset = board->sensor_h_offset;
+ go->encoder_h_halve = 0;
+ go->encoder_v_halve = 0;
+ go->encoder_subsample = 0;
+ go->streaming = 0;
+ go->format = GO7007_FORMAT_MJPEG;
+ go->bitrate = 1500000;
+ go->fps_scale = 1;
+ go->pali = 0;
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ go->gop_size = 0;
+ go->ipb = 0;
+ go->closed_gop = 0;
+ go->repeat_seqhead = 0;
+ go->seq_header_enable = 0;
+ go->gop_header_enable = 0;
+ go->dvd_mode = 0;
+ go->interlace_coding = 0;
+ for (i = 0; i < 4; ++i)
+ go->modet[i].enable = 0;;
+ for (i = 0; i < 1624; ++i)
+ go->modet_map[i] = 0;
+ go->audio_deliver = NULL;
+ go->audio_enabled = 0;
+ INIT_LIST_HEAD(&go->stream);
+
+ return go;
+}
+EXPORT_SYMBOL(go7007_alloc);
+
+/*
+ * Detach and unregister the encoder. The go7007 struct won't be freed
+ * until v4l2 finishes releasing its resources and all associated fds are
+ * closed by applications.
+ */
+void go7007_remove(struct go7007 *go)
+{
+ if (go->i2c_adapter_online) {
+ if (i2c_del_adapter(&go->i2c_adapter) == 0)
+ go->i2c_adapter_online = 0;
+ else
+ printk(KERN_ERR
+ "go7007: error removing I2C adapter!\n");
+ }
+
+ if (go->audio_enabled)
+ go7007_snd_remove(go);
+ go7007_v4l2_remove(go);
+}
+EXPORT_SYMBOL(go7007_remove);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/go7007-fw.c b/drivers/staging/go7007/go7007-fw.c
new file mode 100644
index 00000000000..c2aea1020b0
--- /dev/null
+++ b/drivers/staging/go7007/go7007-fw.c
@@ -0,0 +1,1639 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+/*
+ * This file contains code to generate a firmware image for the GO7007SB
+ * encoder. Much of the firmware is read verbatim from a file, but some of
+ * it concerning bitrate control and other things that can be configured at
+ * run-time are generated dynamically. Note that the format headers
+ * generated here do not affect the functioning of the encoder; they are
+ * merely parroted back to the host at the start of each frame.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <asm/byteorder.h>
+
+#include "go7007-priv.h"
+
+/* Constants used in the source firmware image to describe code segments */
+
+#define FLAG_MODE_MJPEG (1)
+#define FLAG_MODE_MPEG1 (1<<1)
+#define FLAG_MODE_MPEG2 (1<<2)
+#define FLAG_MODE_MPEG4 (1<<3)
+#define FLAG_MODE_H263 (1<<4)
+#define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \
+ FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \
+ FLAG_MODE_H263)
+#define FLAG_SPECIAL (1<<8)
+
+#define SPECIAL_FRM_HEAD 0
+#define SPECIAL_BRC_CTRL 1
+#define SPECIAL_CONFIG 2
+#define SPECIAL_SEQHEAD 3
+#define SPECIAL_AV_SYNC 4
+#define SPECIAL_FINAL 5
+#define SPECIAL_AUDIO 6
+#define SPECIAL_MODET 7
+
+/* Little data class for creating MPEG headers bit-by-bit */
+
+struct code_gen {
+ unsigned char *p; /* destination */
+ u32 a; /* collects bits at the top of the variable */
+ int b; /* bit position of most recently-written bit */
+ int len; /* written out so far */
+};
+
+#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 }
+
+#define CODE_ADD(name, val, length) do { \
+ name.b -= (length); \
+ name.a |= (val) << name.b; \
+ while (name.b <= 24) { \
+ *name.p = name.a >> 24; \
+ ++name.p; \
+ name.a <<= 8; \
+ name.b += 8; \
+ name.len += 8; \
+ } \
+} while (0)
+
+#define CODE_LENGTH(name) (name.len + (32 - name.b))
+
+/* Tables for creating the bitrate control data */
+
+static const s16 converge_speed_ip[101] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+ 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
+ 9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
+ 19, 20, 22, 23, 25, 27, 30, 32, 35, 38,
+ 41, 45, 49, 53, 58, 63, 69, 76, 83, 91,
+ 100
+};
+
+static const s16 converge_speed_ipb[101] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
+ 6, 6, 6, 7, 7, 7, 7, 8, 8, 9,
+ 9, 9, 10, 10, 11, 12, 12, 13, 14, 14,
+ 15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
+ 28, 30, 32, 34, 37, 40, 42, 46, 49, 53,
+ 57, 61, 66, 71, 77, 83, 90, 97, 106, 115,
+ 125, 135, 147, 161, 175, 191, 209, 228, 249, 273,
+ 300
+};
+
+static const s16 LAMBDA_table[4][101] = {
+ { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
+ 19, 19, 19, 20, 20, 20, 21, 21, 22, 22,
+ 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
+ 27, 27, 28, 28, 29, 29, 30, 31, 31, 32,
+ 32, 33, 33, 34, 35, 35, 36, 37, 37, 38,
+ 39, 39, 40, 41, 42, 42, 43, 44, 45, 46,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 67, 68, 69, 70, 72, 73, 74, 76, 77, 78,
+ 80, 81, 83, 84, 86, 87, 89, 90, 92, 94,
+ 96
+ },
+ {
+ 20, 20, 20, 21, 21, 21, 22, 22, 23, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27, 27, 28,
+ 28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
+ 34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
+ 40, 41, 42, 43, 43, 44, 45, 46, 47, 48,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 64, 65, 66, 67, 68,
+ 70, 71, 72, 73, 75, 76, 78, 79, 80, 82,
+ 83, 85, 86, 88, 90, 91, 93, 95, 96, 98,
+ 100, 102, 103, 105, 107, 109, 111, 113, 115, 117,
+ 120
+ },
+ {
+ 24, 24, 24, 25, 25, 26, 26, 27, 27, 28,
+ 28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
+ 34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
+ 41, 41, 42, 43, 44, 44, 45, 46, 47, 48,
+ 49, 50, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 62, 63, 64, 65, 66, 67, 69,
+ 70, 71, 72, 74, 75, 76, 78, 79, 81, 82,
+ 84, 85, 87, 88, 90, 92, 93, 95, 97, 98,
+ 100, 102, 104, 106, 108, 110, 112, 114, 116, 118,
+ 120, 122, 124, 127, 129, 131, 134, 136, 138, 141,
+ 144
+ },
+ {
+ 32, 32, 33, 33, 34, 34, 35, 36, 36, 37,
+ 38, 38, 39, 40, 41, 41, 42, 43, 44, 44,
+ 45, 46, 47, 48, 49, 50, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 62, 63, 64,
+ 65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
+ 78, 79, 81, 82, 84, 85, 87, 88, 90, 92,
+ 93, 95, 97, 98, 100, 102, 104, 106, 108, 110,
+ 112, 114, 116, 118, 120, 122, 124, 127, 129, 131,
+ 134, 136, 139, 141, 144, 146, 149, 152, 154, 157,
+ 160, 163, 166, 169, 172, 175, 178, 181, 185, 188,
+ 192
+ }
+};
+
+/* MPEG blank frame generation tables */
+
+enum mpeg_frame_type {
+ PFRAME,
+ BFRAME_PRE,
+ BFRAME_POST,
+ BFRAME_BIDIR,
+ BFRAME_EMPTY
+};
+
+static const u32 addrinctab[33][2] = {
+ { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 },
+ { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 },
+ { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 },
+ { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 },
+ { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 },
+ { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 },
+ { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 },
+ { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 },
+ { 0x18, 11 }
+};
+
+/* Standard JPEG tables */
+
+static const u8 default_intra_quant_table[] = {
+ 8, 16, 19, 22, 26, 27, 29, 34,
+ 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38,
+ 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48,
+ 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69,
+ 27, 29, 35, 38, 46, 56, 69, 83
+};
+
+static const u8 bits_dc_luminance[] = {
+ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 val_dc_luminance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 bits_dc_chrominance[] = {
+ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+};
+
+static const u8 val_dc_chrominance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 bits_ac_luminance[] = {
+ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+static const u8 val_ac_luminance[] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+static const u8 bits_ac_chrominance[] = {
+ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+};
+
+static const u8 val_ac_chrominance[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+/* Zig-zag mapping for quant table
+ *
+ * OK, let's do this mapping on the actual table above so it doesn't have
+ * to be done on the fly.
+ */
+static const int zz[64] = {
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+static int copy_packages(u16 *dest, u16 *src, int pkg_cnt, int space)
+{
+ int i, cnt = pkg_cnt * 32;
+
+ if (space < cnt)
+ return -1;
+
+ for (i = 0; i < cnt; ++i)
+ dest[i] = __cpu_to_le16(src[i]);
+
+ return cnt;
+}
+
+static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q)
+{
+ int i, p = 0;
+
+ buf[p++] = 0xff;
+ buf[p++] = 0xd8;
+ buf[p++] = 0xff;
+ buf[p++] = 0xdb;
+ buf[p++] = 0;
+ buf[p++] = 2 + 65;
+ buf[p++] = 0;
+ buf[p++] = default_intra_quant_table[0];
+ for (i = 1; i < 64; ++i)
+ /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */
+ buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3;
+ buf[p++] = 0xff;
+ buf[p++] = 0xc0;
+ buf[p++] = 0;
+ buf[p++] = 17;
+ buf[p++] = 8;
+ buf[p++] = go->height >> 8;
+ buf[p++] = go->height & 0xff;
+ buf[p++] = go->width >> 8;
+ buf[p++] = go->width & 0xff;
+ buf[p++] = 3;
+ buf[p++] = 1;
+ buf[p++] = 0x22;
+ buf[p++] = 0;
+ buf[p++] = 2;
+ buf[p++] = 0x11;
+ buf[p++] = 0;
+ buf[p++] = 3;
+ buf[p++] = 0x11;
+ buf[p++] = 0;
+ buf[p++] = 0xff;
+ buf[p++] = 0xc4;
+ buf[p++] = 418 >> 8;
+ buf[p++] = 418 & 0xff;
+ buf[p++] = 0x00;
+ memcpy(buf + p, bits_dc_luminance + 1, 16);
+ p += 16;
+ memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance));
+ p += sizeof(val_dc_luminance);
+ buf[p++] = 0x01;
+ memcpy(buf + p, bits_dc_chrominance + 1, 16);
+ p += 16;
+ memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance));
+ p += sizeof(val_dc_chrominance);
+ buf[p++] = 0x10;
+ memcpy(buf + p, bits_ac_luminance + 1, 16);
+ p += 16;
+ memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance));
+ p += sizeof(val_ac_luminance);
+ buf[p++] = 0x11;
+ memcpy(buf + p, bits_ac_chrominance + 1, 16);
+ p += 16;
+ memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance));
+ p += sizeof(val_ac_chrominance);
+ buf[p++] = 0xff;
+ buf[p++] = 0xda;
+ buf[p++] = 0;
+ buf[p++] = 12;
+ buf[p++] = 3;
+ buf[p++] = 1;
+ buf[p++] = 0x00;
+ buf[p++] = 2;
+ buf[p++] = 0x11;
+ buf[p++] = 3;
+ buf[p++] = 0x11;
+ buf[p++] = 0;
+ buf[p++] = 63;
+ buf[p++] = 0;
+ return p;
+}
+
+static int gen_mjpeghdr_to_package(struct go7007 *go, u16 *code, int space)
+{
+ u8 *buf;
+ u16 mem = 0x3e00;
+ unsigned int addr = 0x19;
+ int size = 0, i, off = 0, chunk;
+
+ buf = kmalloc(4096, GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_ERR "go7007: unable to allocate 4096 bytes for "
+ "firmware construction\n");
+ return -1;
+ }
+ memset(buf, 0, 4096);
+
+ for (i = 1; i < 32; ++i) {
+ mjpeg_frame_header(go, buf + size, i);
+ size += 80;
+ }
+ chunk = mjpeg_frame_header(go, buf + size, 1);
+ memmove(buf + size, buf + size + 80, chunk - 80);
+ size += chunk - 80;
+
+ for (i = 0; i < size; i += chunk * 2) {
+ if (space - off < 32) {
+ off = -1;
+ goto done;
+ }
+
+ code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+ chunk = 28;
+ if (mem + chunk > 0x4000)
+ chunk = 0x4000 - mem;
+ if (i + 2 * chunk > size)
+ chunk = (size - i) / 2;
+
+ if (chunk < 28) {
+ code[off] = __cpu_to_le16(0x4000 | chunk);
+ code[off + 31] = __cpu_to_le16(addr++);
+ mem = 0x3e00;
+ } else {
+ code[off] = __cpu_to_le16(0x1000 | 28);
+ code[off + 31] = 0;
+ mem += 28;
+ }
+
+ memcpy(&code[off + 2], buf + i, chunk * 2);
+ off += 32;
+ }
+done:
+ kfree(buf);
+ return off;
+}
+
+static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
+ int modulo, int pict_struct, enum mpeg_frame_type frame)
+{
+ int i, j, mb_code, mb_len;
+ int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+ CODE_GEN(c, buf + 6);
+
+ switch (frame) {
+ case PFRAME:
+ mb_code = 0x1;
+ mb_len = 3;
+ break;
+ case BFRAME_PRE:
+ mb_code = 0x2;
+ mb_len = 4;
+ break;
+ case BFRAME_POST:
+ mb_code = 0x2;
+ mb_len = 3;
+ break;
+ case BFRAME_BIDIR:
+ mb_code = 0x2;
+ mb_len = 2;
+ break;
+ default: /* keep the compiler happy */
+ mb_code = mb_len = 0;
+ break;
+ }
+
+ CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13);
+ CODE_ADD(c, 0xffff, 16);
+ CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4);
+ if (frame != PFRAME)
+ CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4);
+ else
+ CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */
+ CODE_ADD(c, 0, 3); /* What is this?? */
+ /* Byte-align with zeros */
+ j = 8 - (CODE_LENGTH(c) % 8);
+ if (j != 8)
+ CODE_ADD(c, 0, j);
+
+ if (go->format == GO7007_FORMAT_MPEG2) {
+ CODE_ADD(c, 0x1, 24);
+ CODE_ADD(c, 0xb5, 8);
+ CODE_ADD(c, 0x844, 12);
+ CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8);
+ if (go->interlace_coding) {
+ CODE_ADD(c, pict_struct, 4);
+ if (go->dvd_mode)
+ CODE_ADD(c, 0x000, 11);
+ else
+ CODE_ADD(c, 0x200, 11);
+ } else {
+ CODE_ADD(c, 0x3, 4);
+ CODE_ADD(c, 0x20c, 11);
+ }
+ /* Byte-align with zeros */
+ j = 8 - (CODE_LENGTH(c) % 8);
+ if (j != 8)
+ CODE_ADD(c, 0, j);
+ }
+
+ for (i = 0; i < rows; ++i) {
+ CODE_ADD(c, 1, 24);
+ CODE_ADD(c, i + 1, 8);
+ CODE_ADD(c, 0x2, 6);
+ CODE_ADD(c, 0x1, 1);
+ CODE_ADD(c, mb_code, mb_len);
+ if (go->interlace_coding) {
+ CODE_ADD(c, 0x1, 2);
+ CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+ }
+ if (frame == BFRAME_BIDIR) {
+ CODE_ADD(c, 0x3, 2);
+ if (go->interlace_coding)
+ CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+ }
+ CODE_ADD(c, 0x3, 2);
+ for (j = (go->width >> 4) - 2; j >= 33; j -= 33)
+ CODE_ADD(c, 0x8, 11);
+ CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]);
+ CODE_ADD(c, mb_code, mb_len);
+ if (go->interlace_coding) {
+ CODE_ADD(c, 0x1, 2);
+ CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+ }
+ if (frame == BFRAME_BIDIR) {
+ CODE_ADD(c, 0x3, 2);
+ if (go->interlace_coding)
+ CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
+ }
+ CODE_ADD(c, 0x3, 2);
+
+ /* Byte-align with zeros */
+ j = 8 - (CODE_LENGTH(c) % 8);
+ if (j != 8)
+ CODE_ADD(c, 0, j);
+ }
+
+ i = CODE_LENGTH(c) + 4 * 8;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x01;
+ buf[5] = 0x00;
+ return i;
+}
+
+static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
+{
+ int i, aspect_ratio, picture_rate;
+ CODE_GEN(c, buf + 6);
+
+ if (go->format == GO7007_FORMAT_MPEG1) {
+ switch (go->aspect_ratio) {
+ case GO7007_RATIO_4_3:
+ aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
+ break;
+ case GO7007_RATIO_16_9:
+ aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
+ break;
+ default:
+ aspect_ratio = 1;
+ break;
+ }
+ } else {
+ switch (go->aspect_ratio) {
+ case GO7007_RATIO_4_3:
+ aspect_ratio = 2;
+ break;
+ case GO7007_RATIO_16_9:
+ aspect_ratio = 3;
+ break;
+ default:
+ aspect_ratio = 1;
+ break;
+ }
+ }
+ switch (go->sensor_framerate) {
+ case 24000:
+ picture_rate = 1;
+ break;
+ case 24024:
+ picture_rate = 2;
+ break;
+ case 25025:
+ picture_rate = go->interlace_coding ? 6 : 3;
+ break;
+ case 30000:
+ picture_rate = go->interlace_coding ? 7 : 4;
+ break;
+ case 30030:
+ picture_rate = go->interlace_coding ? 8 : 5;
+ break;
+ default:
+ picture_rate = 5; /* 30 fps seems like a reasonable default */
+ break;
+ }
+
+ CODE_ADD(c, go->width, 12);
+ CODE_ADD(c, go->height, 12);
+ CODE_ADD(c, aspect_ratio, 4);
+ CODE_ADD(c, picture_rate, 4);
+ CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 20000 : 0x3ffff, 18);
+ CODE_ADD(c, 1, 1);
+ CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 112 : 20, 10);
+ CODE_ADD(c, 0, 3);
+
+ /* Byte-align with zeros */
+ i = 8 - (CODE_LENGTH(c) % 8);
+ if (i != 8)
+ CODE_ADD(c, 0, i);
+
+ if (go->format == GO7007_FORMAT_MPEG2) {
+ CODE_ADD(c, 0x1, 24);
+ CODE_ADD(c, 0xb5, 8);
+ CODE_ADD(c, 0x148, 12);
+ if (go->interlace_coding)
+ CODE_ADD(c, 0x20001, 20);
+ else
+ CODE_ADD(c, 0xa0001, 20);
+ CODE_ADD(c, 0, 16);
+
+ /* Byte-align with zeros */
+ i = 8 - (CODE_LENGTH(c) % 8);
+ if (i != 8)
+ CODE_ADD(c, 0, i);
+
+ if (ext) {
+ CODE_ADD(c, 0x1, 24);
+ CODE_ADD(c, 0xb52, 12);
+ CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3);
+ CODE_ADD(c, 0x105, 9);
+ CODE_ADD(c, 0x505, 16);
+ CODE_ADD(c, go->width, 14);
+ CODE_ADD(c, 1, 1);
+ CODE_ADD(c, go->height, 14);
+
+ /* Byte-align with zeros */
+ i = 8 - (CODE_LENGTH(c) % 8);
+ if (i != 8)
+ CODE_ADD(c, 0, i);
+ }
+ }
+
+ i = CODE_LENGTH(c) + 4 * 8;
+ buf[0] = i & 0xff;
+ buf[1] = i >> 8;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x01;
+ buf[5] = 0xb3;
+ return i;
+}
+
+static int gen_mpeg1hdr_to_package(struct go7007 *go,
+ u16 *code, int space, int *framelen)
+{
+ u8 *buf;
+ u16 mem = 0x3e00;
+ unsigned int addr = 0x19;
+ int i, off = 0, chunk;
+
+ buf = kmalloc(5120, GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
+ "firmware construction\n");
+ return -1;
+ }
+ memset(buf, 0, 5120);
+ framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
+ if (go->interlace_coding)
+ framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8,
+ 0, 2, PFRAME);
+ buf[0] = framelen[0] & 0xff;
+ buf[1] = framelen[0] >> 8;
+ i = 368;
+ framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE);
+ if (go->interlace_coding)
+ framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8,
+ 0, 2, BFRAME_PRE);
+ buf[i] = framelen[1] & 0xff;
+ buf[i + 1] = framelen[1] >> 8;
+ i += 1632;
+ framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST);
+ if (go->interlace_coding)
+ framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8,
+ 0, 2, BFRAME_POST);
+ buf[i] = framelen[2] & 0xff;
+ buf[i + 1] = framelen[2] >> 8;
+ i += 1432;
+ framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR);
+ if (go->interlace_coding)
+ framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8,
+ 0, 2, BFRAME_BIDIR);
+ buf[i] = framelen[3] & 0xff;
+ buf[i + 1] = framelen[3] >> 8;
+ i += 1632 + 16;
+ mpeg1_sequence_header(go, buf + i, 0);
+ i += 40;
+ for (i = 0; i < 5120; i += chunk * 2) {
+ if (space - off < 32) {
+ off = -1;
+ goto done;
+ }
+
+ code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+ chunk = 28;
+ if (mem + chunk > 0x4000)
+ chunk = 0x4000 - mem;
+ if (i + 2 * chunk > 5120)
+ chunk = (5120 - i) / 2;
+
+ if (chunk < 28) {
+ code[off] = __cpu_to_le16(0x4000 | chunk);
+ code[off + 31] = __cpu_to_le16(addr);
+ if (mem + chunk == 0x4000) {
+ mem = 0x3e00;
+ ++addr;
+ }
+ } else {
+ code[off] = __cpu_to_le16(0x1000 | 28);
+ code[off + 31] = 0;
+ mem += 28;
+ }
+
+ memcpy(&code[off + 2], buf + i, chunk * 2);
+ off += 32;
+ }
+done:
+ kfree(buf);
+ return off;
+}
+
+static int vti_bitlen(struct go7007 *go)
+{
+ unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale;
+
+ for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i);
+ return i + 1;
+}
+
+static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf,
+ int modulo, enum mpeg_frame_type frame)
+{
+ int i;
+ CODE_GEN(c, buf + 6);
+ int mb_count = (go->width >> 4) * (go->height >> 4);
+
+ CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2);
+ if (modulo)
+ CODE_ADD(c, 0x1, 1);
+ CODE_ADD(c, 0x1, 2);
+ CODE_ADD(c, 0, vti_bitlen(go));
+ CODE_ADD(c, 0x3, 2);
+ if (frame == PFRAME)
+ CODE_ADD(c, 0, 1);
+ CODE_ADD(c, 0xc, 11);
+ if (frame != PFRAME)
+ CODE_ADD(c, 0x4, 3);
+ if (frame != BFRAME_EMPTY) {
+ for (i = 0; i < mb_count; ++i) {
+ switch (frame) {
+ case PFRAME:
+ CODE_ADD(c, 0x1, 1);
+ break;
+ case BFRAME_PRE:
+ CODE_ADD(c, 0x47, 8);
+ break;
+ case BFRAME_POST:
+ CODE_ADD(c, 0x27, 7);
+ break;
+ case BFRAME_BIDIR:
+ CODE_ADD(c, 0x5f, 8);
+ break;
+ case BFRAME_EMPTY: /* keep compiler quiet */
+ break;
+ }
+ }
+ }
+
+ /* Byte-align with a zero followed by ones */
+ i = 8 - (CODE_LENGTH(c) % 8);
+ CODE_ADD(c, 0, 1);
+ CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
+
+ i = CODE_LENGTH(c) + 4 * 8;
+ buf[0] = i & 0xff;
+ buf[1] = i >> 8;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x01;
+ buf[5] = 0xb6;
+ return i;
+}
+
+static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
+{
+ const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali,
+ 0x00, 0x00, 0x01, 0xb5, 0x09,
+ 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x20, };
+ int i, aspect_ratio;
+ int fps = go->sensor_framerate / go->fps_scale;
+ CODE_GEN(c, buf + 2 + sizeof(head));
+
+ switch (go->aspect_ratio) {
+ case GO7007_RATIO_4_3:
+ aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
+ break;
+ case GO7007_RATIO_16_9:
+ aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
+ break;
+ default:
+ aspect_ratio = 1;
+ break;
+ }
+
+ memcpy(buf + 2, head, sizeof(head));
+ CODE_ADD(c, 0x191, 17);
+ CODE_ADD(c, aspect_ratio, 4);
+ CODE_ADD(c, 0x1, 4);
+ CODE_ADD(c, fps, 16);
+ CODE_ADD(c, 0x3, 2);
+ CODE_ADD(c, 1001, vti_bitlen(go));
+ CODE_ADD(c, 1, 1);
+ CODE_ADD(c, go->width, 13);
+ CODE_ADD(c, 1, 1);
+ CODE_ADD(c, go->height, 13);
+ CODE_ADD(c, 0x2830, 14);
+
+ /* Byte-align */
+ i = 8 - (CODE_LENGTH(c) % 8);
+ CODE_ADD(c, 0, 1);
+ CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
+
+ i = CODE_LENGTH(c) + sizeof(head) * 8;
+ buf[0] = i & 0xff;
+ buf[1] = i >> 8;
+ return i;
+}
+
+static int gen_mpeg4hdr_to_package(struct go7007 *go,
+ u16 *code, int space, int *framelen)
+{
+ u8 *buf;
+ u16 mem = 0x3e00;
+ unsigned int addr = 0x19;
+ int i, off = 0, chunk;
+
+ buf = kmalloc(5120, GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
+ "firmware construction\n");
+ return -1;
+ }
+ memset(buf, 0, 5120);
+ framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
+ i = 368;
+ framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE);
+ i += 1632;
+ framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST);
+ i += 1432;
+ framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR);
+ i += 1632;
+ mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY);
+ i += 16;
+ mpeg4_sequence_header(go, buf + i, 0);
+ i += 40;
+ for (i = 0; i < 5120; i += chunk * 2) {
+ if (space - off < 32) {
+ off = -1;
+ goto done;
+ }
+
+ code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+ chunk = 28;
+ if (mem + chunk > 0x4000)
+ chunk = 0x4000 - mem;
+ if (i + 2 * chunk > 5120)
+ chunk = (5120 - i) / 2;
+
+ if (chunk < 28) {
+ code[off] = __cpu_to_le16(0x4000 | chunk);
+ code[off + 31] = __cpu_to_le16(addr);
+ if (mem + chunk == 0x4000) {
+ mem = 0x3e00;
+ ++addr;
+ }
+ } else {
+ code[off] = __cpu_to_le16(0x1000 | 28);
+ code[off + 31] = 0;
+ mem += 28;
+ }
+
+ memcpy(&code[off + 2], buf + i, chunk * 2);
+ off += 32;
+ }
+ mem = 0x3e00;
+ addr = go->ipb ? 0x14f9 : 0x0af9;
+ memset(buf, 0, 5120);
+ framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME);
+ i = 368;
+ framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE);
+ i += 1632;
+ framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST);
+ i += 1432;
+ framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR);
+ i += 1632;
+ mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY);
+ i += 16;
+ for (i = 0; i < 5120; i += chunk * 2) {
+ if (space - off < 32) {
+ off = -1;
+ goto done;
+ }
+
+ code[off + 1] = __cpu_to_le16(0x8000 | mem);
+
+ chunk = 28;
+ if (mem + chunk > 0x4000)
+ chunk = 0x4000 - mem;
+ if (i + 2 * chunk > 5120)
+ chunk = (5120 - i) / 2;
+
+ if (chunk < 28) {
+ code[off] = __cpu_to_le16(0x4000 | chunk);
+ code[off + 31] = __cpu_to_le16(addr);
+ if (mem + chunk == 0x4000) {
+ mem = 0x3e00;
+ ++addr;
+ }
+ } else {
+ code[off] = __cpu_to_le16(0x1000 | 28);
+ code[off + 31] = 0;
+ mem += 28;
+ }
+
+ memcpy(&code[off + 2], buf + i, chunk * 2);
+ off += 32;
+ }
+done:
+ kfree(buf);
+ return off;
+}
+
+static int brctrl_to_package(struct go7007 *go,
+ u16 *code, int space, int *framelen)
+{
+ int converge_speed = 0;
+ int lambda = (go->format == GO7007_FORMAT_MJPEG || go->dvd_mode) ?
+ 100 : 0;
+ int peak_rate = 6 * go->bitrate / 5;
+ int vbv_buffer = go->format == GO7007_FORMAT_MJPEG ?
+ go->bitrate :
+ (go->dvd_mode ? 900000 : peak_rate);
+ int fps = go->sensor_framerate / go->fps_scale;
+ int q = 0;
+ /* Bizarre math below depends on rounding errors in division */
+ u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps;
+ u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps;
+ u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000);
+ u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32);
+ u32 cplx[] = {
+ q > 0 ? sgop_expt_addr * q :
+ 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+ q > 0 ? sgop_expt_addr * q :
+ 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+ q > 0 ? sgop_expt_addr * q :
+ 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+ q > 0 ? sgop_expt_addr * q :
+ 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
+ };
+ u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr;
+ u16 pack[] = {
+ 0x200e, 0x0000,
+ 0xBF20, go->ipb ? converge_speed_ipb[converge_speed]
+ : converge_speed_ip[converge_speed],
+ 0xBF21, go->ipb ? 2 : 0,
+ 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50]
+ : 32767,
+ 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767,
+ 0xBF24, 32767,
+ 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda],
+ 0xBF26, sgop_expt_addr & 0x0000FFFF,
+ 0xBF27, sgop_expt_addr >> 16,
+ 0xBF28, sgop_peak_addr & 0x0000FFFF,
+ 0xBF29, sgop_peak_addr >> 16,
+ 0xBF2A, vbv_alert_addr & 0x0000FFFF,
+ 0xBF2B, vbv_alert_addr >> 16,
+ 0xBF2C, 0,
+ 0xBF2D, 0,
+ 0, 0,
+
+ 0x200e, 0x0000,
+ 0xBF2E, vbv_alert_addr & 0x0000FFFF,
+ 0xBF2F, vbv_alert_addr >> 16,
+ 0xBF30, cplx[0] & 0x0000FFFF,
+ 0xBF31, cplx[0] >> 16,
+ 0xBF32, cplx[1] & 0x0000FFFF,
+ 0xBF33, cplx[1] >> 16,
+ 0xBF34, cplx[2] & 0x0000FFFF,
+ 0xBF35, cplx[2] >> 16,
+ 0xBF36, cplx[3] & 0x0000FFFF,
+ 0xBF37, cplx[3] >> 16,
+ 0xBF38, 0,
+ 0xBF39, 0,
+ 0xBF3A, total_expt_addr & 0x0000FFFF,
+ 0xBF3B, total_expt_addr >> 16,
+ 0, 0,
+
+ 0x200e, 0x0000,
+ 0xBF3C, total_expt_addr & 0x0000FFFF,
+ 0xBF3D, total_expt_addr >> 16,
+ 0xBF3E, 0,
+ 0xBF3F, 0,
+ 0xBF48, 0,
+ 0xBF49, 0,
+ 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q),
+ 0xBF4B, 4,
+ 0xBF4C, 0,
+ 0xBF4D, 0,
+ 0xBF4E, 0,
+ 0xBF4F, 0,
+ 0xBF50, 0,
+ 0xBF51, 0,
+ 0, 0,
+
+ 0x200e, 0x0000,
+ 0xBF40, sgop_expt_addr & 0x0000FFFF,
+ 0xBF41, sgop_expt_addr >> 16,
+ 0xBF42, 0,
+ 0xBF43, 0,
+ 0xBF44, 0,
+ 0xBF45, 0,
+ 0xBF46, (go->width >> 4) * (go->height >> 4),
+ 0xBF47, 0,
+ 0xBF64, 0,
+ 0xBF65, 0,
+ 0xBF18, framelen[4],
+ 0xBF19, framelen[5],
+ 0xBF1A, framelen[6],
+ 0xBF1B, framelen[7],
+ 0, 0,
+
+#if 0 /* Remove once we don't care about matching */
+ 0x200e, 0x0000,
+ 0xBF56, 4,
+ 0xBF57, 0,
+ 0xBF58, 5,
+ 0xBF59, 0,
+ 0xBF5A, 6,
+ 0xBF5B, 0,
+ 0xBF5C, 8,
+ 0xBF5D, 0,
+ 0xBF5E, 1,
+ 0xBF5F, 0,
+ 0xBF60, 1,
+ 0xBF61, 0,
+ 0xBF62, 0,
+ 0xBF63, 0,
+ 0, 0,
+#else
+ 0x2008, 0x0000,
+ 0xBF56, 4,
+ 0xBF57, 0,
+ 0xBF58, 5,
+ 0xBF59, 0,
+ 0xBF5A, 6,
+ 0xBF5B, 0,
+ 0xBF5C, 8,
+ 0xBF5D, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+#endif
+
+ 0x200e, 0x0000,
+ 0xBF10, 0,
+ 0xBF11, 0,
+ 0xBF12, 0,
+ 0xBF13, 0,
+ 0xBF14, 0,
+ 0xBF15, 0,
+ 0xBF16, 0,
+ 0xBF17, 0,
+ 0xBF7E, 0,
+ 0xBF7F, 1,
+ 0xBF52, framelen[0],
+ 0xBF53, framelen[1],
+ 0xBF54, framelen[2],
+ 0xBF55, framelen[3],
+ 0, 0,
+ };
+
+ return copy_packages(code, pack, 6, space);
+}
+
+static int config_package(struct go7007 *go, u16 *code, int space)
+{
+ int fps = go->sensor_framerate / go->fps_scale / 1000;
+ int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+ int brc_window_size = fps;
+ int q_min = 2, q_max = 31;
+ int THACCoeffSet0 = 0;
+ u16 pack[] = {
+ 0x200e, 0x0000,
+ 0xc002, 0x14b4,
+ 0xc003, 0x28b4,
+ 0xc004, 0x3c5a,
+ 0xdc05, 0x2a77,
+ 0xc6c3, go->format == GO7007_FORMAT_MPEG4 ? 0 :
+ (go->format == GO7007_FORMAT_H263 ? 0 : 1),
+ 0xc680, go->format == GO7007_FORMAT_MPEG4 ? 0xf1 :
+ (go->format == GO7007_FORMAT_H263 ? 0x61 :
+ 0xd3),
+ 0xc780, 0x0140,
+ 0xe009, 0x0001,
+ 0xc60f, 0x0008,
+ 0xd4ff, 0x0002,
+ 0xe403, 2340,
+ 0xe406, 75,
+ 0xd411, 0x0001,
+ 0xd410, 0xa1d6,
+ 0x0001, 0x2801,
+
+ 0x200d, 0x0000,
+ 0xe402, 0x018b,
+ 0xe401, 0x8b01,
+ 0xd472, (go->board_info->sensor_flags &
+ GO7007_SENSOR_TV) &&
+ (!go->interlace_coding) ?
+ 0x01b0 : 0x0170,
+ 0xd475, (go->board_info->sensor_flags &
+ GO7007_SENSOR_TV) &&
+ (!go->interlace_coding) ?
+ 0x0008 : 0x0009,
+ 0xc404, go->interlace_coding ? 0x44 :
+ (go->format == GO7007_FORMAT_MPEG4 ? 0x11 :
+ (go->format == GO7007_FORMAT_MPEG1 ? 0x02 :
+ (go->format == GO7007_FORMAT_MPEG2 ? 0x04 :
+ (go->format == GO7007_FORMAT_H263 ? 0x08 :
+ 0x20)))),
+ 0xbf0a, (go->format == GO7007_FORMAT_MPEG4 ? 8 :
+ (go->format == GO7007_FORMAT_MPEG1 ? 1 :
+ (go->format == GO7007_FORMAT_MPEG2 ? 2 :
+ (go->format == GO7007_FORMAT_H263 ? 4 : 16)))) |
+ ((go->repeat_seqhead ? 1 : 0) << 6) |
+ ((go->dvd_mode ? 1 : 0) << 9) |
+ ((go->gop_header_enable ? 1 : 0) << 10),
+ 0xbf0b, 0,
+ 0xdd5a, go->ipb ? 0x14 : 0x0a,
+ 0xbf0c, 0,
+ 0xbf0d, 0,
+ 0xc683, THACCoeffSet0,
+ 0xc40a, (go->width << 4) | rows,
+ 0xe01a, go->board_info->hpi_buffer_cap,
+ 0, 0,
+ 0, 0,
+
+ 0x2008, 0,
+ 0xe402, 0x88,
+ 0xe401, 0x8f01,
+ 0xbf6a, 0,
+ 0xbf6b, 0,
+ 0xbf6c, 0,
+ 0xbf6d, 0,
+ 0xbf6e, 0,
+ 0xbf6f, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0x200e, 0,
+ 0xbf66, brc_window_size,
+ 0xbf67, 0,
+ 0xbf68, q_min,
+ 0xbf69, q_max,
+ 0xbfe0, 0,
+ 0xbfe1, 0,
+ 0xbfe2, 0,
+ 0xbfe3, go->ipb ? 3 : 1,
+ 0xc031, go->board_info->sensor_flags &
+ GO7007_SENSOR_VBI ? 1 : 0,
+ 0xc01c, 0x1f,
+ 0xdd8c, 0x15,
+ 0xdd94, 0x15,
+ 0xdd88, go->ipb ? 0x1401 : 0x0a01,
+ 0xdd90, go->ipb ? 0x1401 : 0x0a01,
+ 0, 0,
+
+ 0x200e, 0,
+ 0xbfe4, 0,
+ 0xbfe5, 0,
+ 0xbfe6, 0,
+ 0xbfe7, fps << 8,
+ 0xbfe8, 0x3a00,
+ 0xbfe9, 0,
+ 0xbfea, 0,
+ 0xbfeb, 0,
+ 0xbfec, (go->interlace_coding ? 1 << 15 : 0) |
+ (go->modet_enable ? 0xa : 0) |
+ (go->board_info->sensor_flags &
+ GO7007_SENSOR_VBI ? 1 : 0),
+ 0xbfed, 0,
+ 0xbfee, 0,
+ 0xbfef, 0,
+ 0xbff0, go->board_info->sensor_flags &
+ GO7007_SENSOR_TV ? 0xf060 : 0xb060,
+ 0xbff1, 0,
+ 0, 0,
+ };
+
+ return copy_packages(code, pack, 5, space);
+}
+
+static int seqhead_to_package(struct go7007 *go, u16 *code, int space,
+ int (*sequence_header_func)(struct go7007 *go,
+ unsigned char *buf, int ext))
+{
+ int vop_time_increment_bitlength = vti_bitlen(go);
+ int fps = go->sensor_framerate / go->fps_scale *
+ (go->interlace_coding ? 2 : 1);
+ unsigned char buf[40] = { };
+ int len = sequence_header_func(go, buf, 1);
+ u16 pack[] = {
+ 0x2006, 0,
+ 0xbf08, fps,
+ 0xbf09, 0,
+ 0xbff2, vop_time_increment_bitlength,
+ 0xbff3, (1 << vop_time_increment_bitlength) - 1,
+ 0xbfe6, 0,
+ 0xbfe7, (fps / 1000) << 8,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0x2007, 0,
+ 0xc800, buf[2] << 8 | buf[3],
+ 0xc801, buf[4] << 8 | buf[5],
+ 0xc802, buf[6] << 8 | buf[7],
+ 0xc803, buf[8] << 8 | buf[9],
+ 0xc406, 64,
+ 0xc407, len - 64,
+ 0xc61b, 1,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+
+ 0x200e, 0,
+ 0xc808, buf[10] << 8 | buf[11],
+ 0xc809, buf[12] << 8 | buf[13],
+ 0xc80a, buf[14] << 8 | buf[15],
+ 0xc80b, buf[16] << 8 | buf[17],
+ 0xc80c, buf[18] << 8 | buf[19],
+ 0xc80d, buf[20] << 8 | buf[21],
+ 0xc80e, buf[22] << 8 | buf[23],
+ 0xc80f, buf[24] << 8 | buf[25],
+ 0xc810, buf[26] << 8 | buf[27],
+ 0xc811, buf[28] << 8 | buf[29],
+ 0xc812, buf[30] << 8 | buf[31],
+ 0xc813, buf[32] << 8 | buf[33],
+ 0xc814, buf[34] << 8 | buf[35],
+ 0xc815, buf[36] << 8 | buf[37],
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ };
+
+ return copy_packages(code, pack, 3, space);
+}
+
+static int relative_prime(int big, int little)
+{
+ int remainder;
+
+ while (little != 0) {
+ remainder = big % little;
+ big = little;
+ little = remainder;
+ }
+ return big;
+}
+
+static int avsync_to_package(struct go7007 *go, u16 *code, int space)
+{
+ int arate = go->board_info->audio_rate * 1001 * go->fps_scale;
+ int ratio = arate / go->sensor_framerate;
+ int adjratio = ratio * 215 / 100;
+ int rprime = relative_prime(go->sensor_framerate,
+ arate % go->sensor_framerate);
+ int f1 = (arate % go->sensor_framerate) / rprime;
+ int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime;
+ u16 pack[] = {
+ 0x200e, 0,
+ 0xbf98, (u16)((-adjratio) & 0xffff),
+ 0xbf99, (u16)((-adjratio) >> 16),
+ 0xbf92, 0,
+ 0xbf93, 0,
+ 0xbff4, f1 > f2 ? f1 : f2,
+ 0xbff5, f1 < f2 ? f1 : f2,
+ 0xbff6, f1 < f2 ? ratio : ratio + 1,
+ 0xbff7, f1 > f2 ? ratio : ratio + 1,
+ 0xbff8, 0,
+ 0xbff9, 0,
+ 0xbffa, adjratio & 0xffff,
+ 0xbffb, adjratio >> 16,
+ 0xbf94, 0,
+ 0xbf95, 0,
+ 0, 0,
+ };
+
+ return copy_packages(code, pack, 1, space);
+}
+
+static int final_package(struct go7007 *go, u16 *code, int space)
+{
+ int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
+ u16 pack[] = {
+ 0x8000,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 2,
+ ((go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
+ (!go->interlace_coding) ?
+ (1 << 14) | (1 << 9) : 0) |
+ ((go->encoder_subsample ? 1 : 0) << 8) |
+ (go->board_info->sensor_flags &
+ GO7007_SENSOR_CONFIG_MASK),
+ ((go->encoder_v_halve ? 1 : 0) << 14) |
+ (go->encoder_v_halve ? rows << 9 : rows << 8) |
+ (go->encoder_h_halve ? 1 << 6 : 0) |
+ (go->encoder_h_halve ? go->width >> 3 : go->width >> 4),
+ (1 << 15) | (go->encoder_v_offset << 6) |
+ (1 << 7) | (go->encoder_h_offset >> 2),
+ (1 << 6),
+ 0,
+ 0,
+ ((go->fps_scale - 1) << 8) |
+ (go->board_info->sensor_flags & GO7007_SENSOR_TV ?
+ (1 << 7) : 0) |
+ 0x41,
+ go->ipb ? 0xd4c : 0x36b,
+ (rows << 8) | (go->width >> 4),
+ go->format == GO7007_FORMAT_MPEG4 ? 0x0404 : 0,
+ (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) |
+ ((go->closed_gop ? 1 : 0) << 12) |
+ ((go->format == GO7007_FORMAT_MPEG4 ? 1 : 0) << 11) |
+ /* (1 << 9) | */
+ ((go->ipb ? 3 : 0) << 7) |
+ ((go->modet_enable ? 1 : 0) << 2) |
+ ((go->dvd_mode ? 1 : 0) << 1) | 1,
+ (go->format == GO7007_FORMAT_MPEG1 ? 0x89a0 :
+ (go->format == GO7007_FORMAT_MPEG2 ? 0x89a0 :
+ (go->format == GO7007_FORMAT_MJPEG ? 0x89a0 :
+ (go->format == GO7007_FORMAT_MPEG4 ? 0x8920 :
+ (go->format == GO7007_FORMAT_H263 ? 0x8920 : 0))))),
+ go->ipb ? 0x1f15 : 0x1f0b,
+ go->ipb ? 0x0015 : 0x000b,
+ go->ipb ? 0xa800 : 0x5800,
+ 0xffff,
+ 0x0020 + 0x034b * 0,
+ 0x0020 + 0x034b * 1,
+ 0x0020 + 0x034b * 2,
+ 0x0020 + 0x034b * 3,
+ 0x0020 + 0x034b * 4,
+ 0x0020 + 0x034b * 5,
+ go->ipb ? (go->gop_size / 3) : go->gop_size,
+ (go->height >> 4) * (go->width >> 4) * 110 / 100,
+ };
+
+ return copy_packages(code, pack, 1, space);
+}
+
+static int audio_to_package(struct go7007 *go, u16 *code, int space)
+{
+ int clock_config = ((go->board_info->audio_flags &
+ GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) |
+ ((go->board_info->audio_flags &
+ GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) |
+ (((go->board_info->audio_bclk_div / 4) - 1) << 4) |
+ (go->board_info->audio_main_div - 1);
+ u16 pack[] = {
+ 0x200d, 0,
+ 0x9002, 0,
+ 0x9002, 0,
+ 0x9031, 0,
+ 0x9032, 0,
+ 0x9033, 0,
+ 0x9034, 0,
+ 0x9035, 0,
+ 0x9036, 0,
+ 0x9037, 0,
+ 0x9040, 0,
+ 0x9000, clock_config,
+ 0x9001, (go->board_info->audio_flags & 0xffff) |
+ (1 << 9),
+ 0x9000, ((go->board_info->audio_flags &
+ GO7007_AUDIO_I2S_MASTER ?
+ 1 : 0) << 10) |
+ clock_config,
+ 0, 0,
+ 0, 0,
+ 0x2005, 0,
+ 0x9041, 0,
+ 0x9042, 256,
+ 0x9043, 0,
+ 0x9044, 16,
+ 0x9045, 16,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ };
+
+ return copy_packages(code, pack, 2, space);
+}
+
+static int modet_to_package(struct go7007 *go, u16 *code, int space)
+{
+ int ret, mb, i, addr, cnt = 0;
+ u16 pack[32];
+ u16 thresholds[] = {
+ 0x200e, 0,
+ 0xbf82, go->modet[0].pixel_threshold,
+ 0xbf83, go->modet[1].pixel_threshold,
+ 0xbf84, go->modet[2].pixel_threshold,
+ 0xbf85, go->modet[3].pixel_threshold,
+ 0xbf86, go->modet[0].motion_threshold,
+ 0xbf87, go->modet[1].motion_threshold,
+ 0xbf88, go->modet[2].motion_threshold,
+ 0xbf89, go->modet[3].motion_threshold,
+ 0xbf8a, go->modet[0].mb_threshold,
+ 0xbf8b, go->modet[1].mb_threshold,
+ 0xbf8c, go->modet[2].mb_threshold,
+ 0xbf8d, go->modet[3].mb_threshold,
+ 0xbf8e, 0,
+ 0xbf8f, 0,
+ 0, 0,
+ };
+
+ ret = copy_packages(code, thresholds, 1, space);
+ if (ret < 0)
+ return -1;
+ cnt += ret;
+
+ addr = 0xbac0;
+ memset(pack, 0, 64);
+ i = 0;
+ for (mb = 0; mb < 1624; ++mb) {
+ pack[i * 2 + 3] <<= 2;
+ pack[i * 2 + 3] |= go->modet_map[mb];
+ if (mb % 8 != 7)
+ continue;
+ pack[i * 2 + 2] = addr++;
+ ++i;
+ if (i == 10 || mb == 1623) {
+ pack[0] = 0x2000 | i;
+ ret = copy_packages(code + cnt, pack, 1, space - cnt);
+ if (ret < 0)
+ return -1;
+ cnt += ret;
+ i = 0;
+ memset(pack, 0, 64);
+ }
+ pack[i * 2 + 3] = 0;
+ }
+
+ memset(pack, 0, 64);
+ i = 0;
+ for (addr = 0xbb90; addr < 0xbbfa; ++addr) {
+ pack[i * 2 + 2] = addr;
+ pack[i * 2 + 3] = 0;
+ ++i;
+ if (i == 10 || addr == 0xbbf9) {
+ pack[0] = 0x2000 | i;
+ ret = copy_packages(code + cnt, pack, 1, space - cnt);
+ if (ret < 0)
+ return -1;
+ cnt += ret;
+ i = 0;
+ memset(pack, 0, 64);
+ }
+ }
+ return cnt;
+}
+
+static int do_special(struct go7007 *go, u16 type, u16 *code, int space,
+ int *framelen)
+{
+ switch (type) {
+ case SPECIAL_FRM_HEAD:
+ switch (go->format) {
+ case GO7007_FORMAT_MJPEG:
+ return gen_mjpeghdr_to_package(go, code, space);
+ case GO7007_FORMAT_MPEG1:
+ case GO7007_FORMAT_MPEG2:
+ return gen_mpeg1hdr_to_package(go, code, space,
+ framelen);
+ case GO7007_FORMAT_MPEG4:
+ return gen_mpeg4hdr_to_package(go, code, space,
+ framelen);
+ }
+ case SPECIAL_BRC_CTRL:
+ return brctrl_to_package(go, code, space, framelen);
+ case SPECIAL_CONFIG:
+ return config_package(go, code, space);
+ case SPECIAL_SEQHEAD:
+ switch (go->format) {
+ case GO7007_FORMAT_MPEG1:
+ case GO7007_FORMAT_MPEG2:
+ return seqhead_to_package(go, code, space,
+ mpeg1_sequence_header);
+ case GO7007_FORMAT_MPEG4:
+ return seqhead_to_package(go, code, space,
+ mpeg4_sequence_header);
+ default:
+ return 0;
+ }
+ case SPECIAL_AV_SYNC:
+ return avsync_to_package(go, code, space);
+ case SPECIAL_FINAL:
+ return final_package(go, code, space);
+ case SPECIAL_AUDIO:
+ return audio_to_package(go, code, space);
+ case SPECIAL_MODET:
+ return modet_to_package(go, code, space);
+ }
+ printk(KERN_ERR
+ "go7007: firmware file contains unsupported feature %04x\n",
+ type);
+ return -1;
+}
+
+int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
+{
+ const struct firmware *fw_entry;
+ u16 *code, *src;
+ int framelen[8] = { }; /* holds the lengths of empty frame templates */
+ int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags;
+ int mode_flag;
+ int ret;
+
+ switch (go->format) {
+ case GO7007_FORMAT_MJPEG:
+ mode_flag = FLAG_MODE_MJPEG;
+ break;
+ case GO7007_FORMAT_MPEG1:
+ mode_flag = FLAG_MODE_MPEG1;
+ break;
+ case GO7007_FORMAT_MPEG2:
+ mode_flag = FLAG_MODE_MPEG2;
+ break;
+ case GO7007_FORMAT_MPEG4:
+ mode_flag = FLAG_MODE_MPEG4;
+ break;
+ default:
+ return -1;
+ }
+ if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) {
+ printk(KERN_ERR
+ "go7007: unable to load firmware from file \"%s\"\n",
+ go->board_info->firmware);
+ return -1;
+ }
+ code = kmalloc(codespace * 2, GFP_KERNEL);
+ if (code == NULL) {
+ printk(KERN_ERR "go7007: unable to allocate %d bytes for "
+ "firmware construction\n", codespace * 2);
+ goto fw_failed;
+ }
+ memset(code, 0, codespace * 2);
+ src = (u16 *)fw_entry->data;
+ srclen = fw_entry->size / 2;
+ while (srclen >= 2) {
+ chunk_flags = __le16_to_cpu(src[0]);
+ chunk_len = __le16_to_cpu(src[1]);
+ if (chunk_len + 2 > srclen) {
+ printk(KERN_ERR "go7007: firmware file \"%s\" "
+ "appears to be corrupted\n",
+ go->board_info->firmware);
+ goto fw_failed;
+ }
+ if (chunk_flags & mode_flag) {
+ if (chunk_flags & FLAG_SPECIAL) {
+ ret = do_special(go, __le16_to_cpu(src[2]),
+ &code[i], codespace - i, framelen);
+ if (ret < 0) {
+ printk(KERN_ERR "go7007: insufficient "
+ "memory for firmware "
+ "construction\n");
+ goto fw_failed;
+ }
+ i += ret;
+ } else {
+ if (codespace - i < chunk_len) {
+ printk(KERN_ERR "go7007: insufficient "
+ "memory for firmware "
+ "construction\n");
+ goto fw_failed;
+ }
+ memcpy(&code[i], &src[2], chunk_len * 2);
+ i += chunk_len;
+ }
+ }
+ srclen -= chunk_len + 2;
+ src += chunk_len + 2;
+ }
+ release_firmware(fw_entry);
+ *fw = (u8 *)code;
+ *fwlen = i * 2;
+ return 0;
+
+fw_failed:
+ kfree(code);
+ release_firmware(fw_entry);
+ return -1;
+}
diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c
new file mode 100644
index 00000000000..10baae3dade
--- /dev/null
+++ b/drivers/staging/go7007/go7007-i2c.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include "go7007-priv.h"
+#include "wis-i2c.h"
+
+/************** Registration interface for I2C client drivers **************/
+
+/* Since there's no way to auto-probe the I2C devices connected to the I2C
+ * bus on the go7007, we have this silly little registration system that
+ * client drivers can use to register their I2C driver ID and their
+ * detect_client function (the one that's normally passed to i2c_probe).
+ *
+ * When a new go7007 device is connected, we can look up in a board info
+ * table by the USB or PCI vendor/product/revision ID to determine
+ * which I2C client module to load. The client driver module will register
+ * itself here, and then we can call the registered detect_client function
+ * to force-load a new client at the address listed in the board info table.
+ *
+ * Really the I2C subsystem should have a way to force-load I2C client
+ * drivers when we have a priori knowledge of what's on the bus, especially
+ * since the existing I2C auto-probe mechanism is so hokey, but we'll use
+ * our own mechanism for the time being. */
+
+struct wis_i2c_client_driver {
+ unsigned int id;
+ found_proc found_proc;
+ struct list_head list;
+};
+
+static LIST_HEAD(i2c_client_drivers);
+static DECLARE_MUTEX(i2c_client_driver_list_lock);
+
+/* Client drivers register here by their I2C driver ID */
+int wis_i2c_add_driver(unsigned int id, found_proc found_proc)
+{
+ struct wis_i2c_client_driver *driver;
+
+ driver = kmalloc(sizeof(struct wis_i2c_client_driver), GFP_KERNEL);
+ if (driver == NULL)
+ return -ENOMEM;
+ driver->id = id;
+ driver->found_proc = found_proc;
+
+ down(&i2c_client_driver_list_lock);
+ list_add_tail(&driver->list, &i2c_client_drivers);
+ up(&i2c_client_driver_list_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(wis_i2c_add_driver);
+
+void wis_i2c_del_driver(found_proc found_proc)
+{
+ struct wis_i2c_client_driver *driver, *next;
+
+ down(&i2c_client_driver_list_lock);
+ list_for_each_entry_safe(driver, next, &i2c_client_drivers, list)
+ if (driver->found_proc == found_proc) {
+ list_del(&driver->list);
+ kfree(driver);
+ }
+ up(&i2c_client_driver_list_lock);
+}
+EXPORT_SYMBOL(wis_i2c_del_driver);
+
+/* The main go7007 driver calls this to instantiate a client by driver
+ * ID and bus address, which are both stored in the board info table */
+int wis_i2c_probe_device(struct i2c_adapter *adapter,
+ unsigned int id, int addr)
+{
+ struct wis_i2c_client_driver *driver;
+ int found = 0;
+
+ if (addr < 0 || addr > 0x7f)
+ return -1;
+ down(&i2c_client_driver_list_lock);
+ list_for_each_entry(driver, &i2c_client_drivers, list)
+ if (driver->id == id) {
+ if (driver->found_proc(adapter, addr, 0) == 0)
+ found = 1;
+ break;
+ }
+ up(&i2c_client_driver_list_lock);
+ return found;
+}
+
+/********************* Driver for on-board I2C adapter *********************/
+
+/* #define GO7007_I2C_DEBUG */
+
+#define SPI_I2C_ADDR_BASE 0x1400
+#define STATUS_REG_ADDR (SPI_I2C_ADDR_BASE + 0x2)
+#define I2C_CTRL_REG_ADDR (SPI_I2C_ADDR_BASE + 0x6)
+#define I2C_DEV_UP_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x7)
+#define I2C_LO_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x8)
+#define I2C_DATA_REG_ADDR (SPI_I2C_ADDR_BASE + 0x9)
+#define I2C_CLKFREQ_REG_ADDR (SPI_I2C_ADDR_BASE + 0xa)
+
+#define I2C_STATE_MASK 0x0007
+#define I2C_READ_READY_MASK 0x0008
+
+/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs
+ * on the Adlink PCI-MPG24, so access is shared between all of them. */
+static DECLARE_MUTEX(adlink_mpg24_i2c_lock);
+
+static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
+ u16 command, int flags, u8 *data)
+{
+ int i, ret = -1;
+ u16 val;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return -1;
+
+#ifdef GO7007_I2C_DEBUG
+ if (read)
+ printk(KERN_DEBUG "go7007-i2c: reading 0x%02x on 0x%02x\n",
+ command, addr);
+ else
+ printk(KERN_DEBUG
+ "go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n",
+ *data, command, addr);
+#endif
+
+ down(&go->hw_lock);
+
+ if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
+ /* Bridge the I2C port on this GO7007 to the shared bus */
+ down(&adlink_mpg24_i2c_lock);
+ go7007_write_addr(go, 0x3c82, 0x0020);
+ }
+
+ /* Wait for I2C adapter to be ready */
+ for (i = 0; i < 10; ++i) {
+ if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
+ goto i2c_done;
+ if (!(val & I2C_STATE_MASK))
+ break;
+ msleep(100);
+ }
+ if (i == 10) {
+ printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n");
+ goto i2c_done;
+ }
+
+ /* Set target register (command) */
+ go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags);
+ go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command);
+
+ /* If we're writing, send the data and target address and we're done */
+ if (!read) {
+ go7007_write_addr(go, I2C_DATA_REG_ADDR, *data);
+ go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
+ (addr << 9) | (command >> 8));
+ ret = 0;
+ goto i2c_done;
+ }
+
+ /* Otherwise, we're reading. First clear i2c_rx_data_rdy. */
+ if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
+ goto i2c_done;
+
+ /* Send the target address plus read flag */
+ go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR,
+ (addr << 9) | 0x0100 | (command >> 8));
+
+ /* Wait for i2c_rx_data_rdy */
+ for (i = 0; i < 10; ++i) {
+ if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0)
+ goto i2c_done;
+ if (val & I2C_READ_READY_MASK)
+ break;
+ msleep(100);
+ }
+ if (i == 10) {
+ printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n");
+ goto i2c_done;
+ }
+
+ /* Retrieve the read byte */
+ if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0)
+ goto i2c_done;
+ *data = val;
+ ret = 0;
+
+i2c_done:
+ if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
+ /* Isolate the I2C port on this GO7007 from the shared bus */
+ go7007_write_addr(go, 0x3c82, 0x0000);
+ up(&adlink_mpg24_i2c_lock);
+ }
+ up(&go->hw_lock);
+ return ret;
+}
+
+static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data *data)
+{
+ struct go7007 *go = i2c_get_adapdata(adapter);
+
+ if (size != I2C_SMBUS_BYTE_DATA)
+ return -1;
+ return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command,
+ flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte);
+}
+
+/* VERY LIMITED I2C master xfer function -- only needed because the
+ * SMBus functions only support 8-bit commands and the SAA7135 uses
+ * 16-bit commands. The I2C interface on the GO7007, as limited as
+ * it is, does support this mode. */
+
+static int go7007_i2c_master_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg msgs[], int num)
+{
+ struct go7007 *go = i2c_get_adapdata(adapter);
+ int i;
+
+ for (i = 0; i < num; ++i) {
+ /* We can only do two things here -- write three bytes, or
+ * write two bytes and read one byte. */
+ if (msgs[i].len == 2) {
+ if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr ||
+ (msgs[i].flags & I2C_M_RD) ||
+ !(msgs[i + 1].flags & I2C_M_RD) ||
+ msgs[i + 1].len != 1)
+ return -1;
+ if (go7007_i2c_xfer(go, msgs[i].addr, 1,
+ (msgs[i].buf[0] << 8) | msgs[i].buf[1],
+ 0x01, &msgs[i + 1].buf[0]) < 0)
+ return -1;
+ ++i;
+ } else if (msgs[i].len == 3) {
+ if (msgs[i].flags & I2C_M_RD)
+ return -1;
+ if (msgs[i].len != 3)
+ return -1;
+ if (go7007_i2c_xfer(go, msgs[i].addr, 0,
+ (msgs[i].buf[0] << 8) | msgs[i].buf[1],
+ 0x01, &msgs[i].buf[2]) < 0)
+ return -1;
+ } else
+ return -1;
+ }
+
+ return 0;
+}
+
+static u32 go7007_functionality(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static struct i2c_algorithm go7007_algo = {
+ .smbus_xfer = go7007_smbus_xfer,
+ .master_xfer = go7007_i2c_master_xfer,
+ .functionality = go7007_functionality,
+};
+
+static struct i2c_adapter go7007_adap_templ = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_TV_ANALOG,
+ .name = "WIS GO7007SB",
+ .id = I2C_ALGO_GO7007,
+ .algo = &go7007_algo,
+};
+
+int go7007_i2c_init(struct go7007 *go)
+{
+ memcpy(&go->i2c_adapter, &go7007_adap_templ,
+ sizeof(go7007_adap_templ));
+ go->i2c_adapter.dev.parent = go->dev;
+ i2c_set_adapdata(&go->i2c_adapter, go);
+ if (i2c_add_adapter(&go->i2c_adapter) < 0) {
+ printk(KERN_ERR
+ "go7007-i2c: error: i2c_add_adapter failed\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h
new file mode 100644
index 00000000000..005542d16a5
--- /dev/null
+++ b/drivers/staging/go7007/go7007-priv.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+/*
+ * This is the private include file for the go7007 driver. It should not
+ * be included by anybody but the driver itself, and especially not by
+ * user-space applications.
+ */
+
+struct go7007;
+
+/* IDs to activate board-specific support code */
+#define GO7007_BOARDID_MATRIX_II 0
+#define GO7007_BOARDID_MATRIX_RELOAD 1
+#define GO7007_BOARDID_STAR_TREK 2
+#define GO7007_BOARDID_PCI_VOYAGER 3
+#define GO7007_BOARDID_XMEN 4
+#define GO7007_BOARDID_XMEN_II 5
+#define GO7007_BOARDID_XMEN_III 6
+#define GO7007_BOARDID_MATRIX_REV 7
+#define GO7007_BOARDID_PX_M402U 16
+#define GO7007_BOARDID_PX_TV402U_ANY 17 /* need to check tuner model */
+#define GO7007_BOARDID_PX_TV402U_NA 18 /* detected NTSC tuner */
+#define GO7007_BOARDID_PX_TV402U_EU 19 /* detected PAL tuner */
+#define GO7007_BOARDID_PX_TV402U_JP 20 /* detected NTSC-J tuner */
+#define GO7007_BOARDID_LIFEVIEW_LR192 21 /* TV Walker Ultra */
+#define GO7007_BOARDID_ENDURA 22
+#define GO7007_BOARDID_ADLINK_MPG24 23
+
+/* Various characteristics of each board */
+#define GO7007_BOARD_HAS_AUDIO (1<<0)
+#define GO7007_BOARD_USE_ONBOARD_I2C (1<<1)
+#define GO7007_BOARD_HAS_TUNER (1<<2)
+
+/* Characteristics of sensor devices */
+#define GO7007_SENSOR_VALID_POLAR (1<<0)
+#define GO7007_SENSOR_HREF_POLAR (1<<1)
+#define GO7007_SENSOR_VREF_POLAR (1<<2)
+#define GO7007_SENSOR_FIELD_ID_POLAR (1<<3)
+#define GO7007_SENSOR_BIT_WIDTH (1<<4)
+#define GO7007_SENSOR_VALID_ENABLE (1<<5)
+#define GO7007_SENSOR_656 (1<<6)
+#define GO7007_SENSOR_CONFIG_MASK 0x7f
+#define GO7007_SENSOR_TV (1<<7)
+#define GO7007_SENSOR_VBI (1<<8)
+#define GO7007_SENSOR_SCALING (1<<9)
+
+/* Characteristics of audio sensor devices */
+#define GO7007_AUDIO_I2S_MODE_1 (1)
+#define GO7007_AUDIO_I2S_MODE_2 (2)
+#define GO7007_AUDIO_I2S_MODE_3 (3)
+#define GO7007_AUDIO_BCLK_POLAR (1<<2)
+#define GO7007_AUDIO_WORD_14 (14<<4)
+#define GO7007_AUDIO_WORD_16 (16<<4)
+#define GO7007_AUDIO_ONE_CHANNEL (1<<11)
+#define GO7007_AUDIO_I2S_MASTER (1<<16)
+#define GO7007_AUDIO_OKI_MODE (1<<17)
+
+struct go7007_board_info {
+ char *firmware;
+ unsigned int flags;
+ int hpi_buffer_cap;
+ unsigned int sensor_flags;
+ int sensor_width;
+ int sensor_height;
+ int sensor_framerate;
+ int sensor_h_offset;
+ int sensor_v_offset;
+ unsigned int audio_flags;
+ int audio_rate;
+ int audio_bclk_div;
+ int audio_main_div;
+ int num_i2c_devs;
+ struct {
+ int id;
+ int addr;
+ } i2c_devs[4];
+ int num_inputs;
+ struct {
+ int video_input;
+ int audio_input;
+ char *name;
+ } inputs[4];
+};
+
+struct go7007_hpi_ops {
+ int (*interface_reset)(struct go7007 *go);
+ int (*write_interrupt)(struct go7007 *go, int addr, int data);
+ int (*read_interrupt)(struct go7007 *go);
+ int (*stream_start)(struct go7007 *go);
+ int (*stream_stop)(struct go7007 *go);
+ int (*send_firmware)(struct go7007 *go, u8 *data, int len);
+};
+
+/* The video buffer size must be a multiple of PAGE_SIZE */
+#define GO7007_BUF_PAGES (128 * 1024 / PAGE_SIZE)
+#define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT)
+
+struct go7007_buffer {
+ struct go7007 *go; /* Reverse reference for VMA ops */
+ int index; /* Reverse reference for DQBUF */
+ enum { BUF_STATE_IDLE, BUF_STATE_QUEUED, BUF_STATE_DONE } state;
+ u32 seq;
+ struct timeval timestamp;
+ struct list_head stream;
+ struct page *pages[GO7007_BUF_PAGES + 1]; /* extra for straddling */
+ unsigned long user_addr;
+ unsigned int page_count;
+ unsigned int offset;
+ unsigned int bytesused;
+ unsigned int frame_offset;
+ u32 modet_active;
+ int mapped;
+};
+
+struct go7007_file {
+ struct go7007 *go;
+ struct semaphore lock;
+ int buf_count;
+ struct go7007_buffer *bufs;
+};
+
+#define GO7007_FORMAT_MJPEG 0
+#define GO7007_FORMAT_MPEG4 1
+#define GO7007_FORMAT_MPEG1 2
+#define GO7007_FORMAT_MPEG2 3
+#define GO7007_FORMAT_H263 4
+
+#define GO7007_RATIO_1_1 0
+#define GO7007_RATIO_4_3 1
+#define GO7007_RATIO_16_9 2
+
+enum go7007_parser_state {
+ STATE_DATA,
+ STATE_00,
+ STATE_00_00,
+ STATE_00_00_01,
+ STATE_FF,
+ STATE_VBI_LEN_A,
+ STATE_VBI_LEN_B,
+ STATE_MODET_MAP,
+ STATE_UNPARSED,
+};
+
+struct go7007 {
+ struct device *dev;
+ struct go7007_board_info *board_info;
+ unsigned int board_id;
+ int tuner_type;
+ int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */
+ char name[64];
+ struct video_device *video_dev;
+ int ref_count;
+ enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
+ spinlock_t spinlock;
+ struct semaphore hw_lock;
+ int streaming;
+ int in_use;
+ int audio_enabled;
+
+ /* Video input */
+ int input;
+ enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard;
+ int sensor_framerate;
+ int width;
+ int height;
+ int encoder_h_offset;
+ int encoder_v_offset;
+ unsigned int encoder_h_halve:1;
+ unsigned int encoder_v_halve:1;
+ unsigned int encoder_subsample:1;
+
+ /* Encoder config */
+ int format;
+ int bitrate;
+ int fps_scale;
+ int pali;
+ int aspect_ratio;
+ int gop_size;
+ unsigned int ipb:1;
+ unsigned int closed_gop:1;
+ unsigned int repeat_seqhead:1;
+ unsigned int seq_header_enable:1;
+ unsigned int gop_header_enable:1;
+ unsigned int dvd_mode:1;
+ unsigned int interlace_coding:1;
+
+ /* Motion detection */
+ unsigned int modet_enable:1;
+ struct {
+ unsigned int enable:1;
+ int pixel_threshold;
+ int motion_threshold;
+ int mb_threshold;
+ } modet[4];
+ unsigned char modet_map[1624];
+ unsigned char active_map[216];
+
+ /* Video streaming */
+ struct go7007_buffer *active_buf;
+ enum go7007_parser_state state;
+ int parse_length;
+ u16 modet_word;
+ int seen_frame;
+ u32 next_seq;
+ struct list_head stream;
+ wait_queue_head_t frame_waitq;
+
+ /* Audio streaming */
+ void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
+ void *snd_context;
+
+ /* I2C */
+ int i2c_adapter_online;
+ struct i2c_adapter i2c_adapter;
+
+ /* HPI driver */
+ struct go7007_hpi_ops *hpi_ops;
+ void *hpi_context;
+ int interrupt_available;
+ wait_queue_head_t interrupt_waitq;
+ unsigned short interrupt_value;
+ unsigned short interrupt_data;
+};
+
+/* All of these must be called with the hpi_lock semaphore held! */
+#define go7007_interface_reset(go) \
+ ((go)->hpi_ops->interface_reset(go))
+#define go7007_write_interrupt(go, x, y) \
+ ((go)->hpi_ops->write_interrupt)((go), (x), (y))
+#define go7007_stream_start(go) \
+ ((go)->hpi_ops->stream_start(go))
+#define go7007_stream_stop(go) \
+ ((go)->hpi_ops->stream_stop(go))
+#define go7007_send_firmware(go, x, y) \
+ ((go)->hpi_ops->send_firmware)((go), (x), (y))
+#define go7007_write_addr(go, x, y) \
+ ((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y))
+
+/* go7007-driver.c */
+int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data);
+int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data);
+int go7007_boot_encoder(struct go7007 *go, int init_i2c);
+int go7007_reset_encoder(struct go7007 *go);
+int go7007_register_encoder(struct go7007 *go);
+int go7007_start_encoder(struct go7007 *go);
+void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length);
+struct go7007 *go7007_alloc(struct go7007_board_info *board,
+ struct device *dev);
+void go7007_remove(struct go7007 *go);
+
+/* go7007-fw.c */
+int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen);
+
+/* go7007-i2c.c */
+int go7007_i2c_init(struct go7007 *go);
+int go7007_i2c_remove(struct go7007 *go);
+
+/* go7007-v4l2.c */
+int go7007_v4l2_init(struct go7007 *go);
+void go7007_v4l2_remove(struct go7007 *go);
+
+/* snd-go7007.c */
+int go7007_snd_init(struct go7007 *go);
+int go7007_snd_remove(struct go7007 *go);
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
new file mode 100644
index 00000000000..d4ed6d2b715
--- /dev/null
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -0,0 +1,1229 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <asm/byteorder.h>
+#include <media/tvaudio.h>
+
+#include "go7007-priv.h"
+#include "wis-i2c.h"
+
+static unsigned int assume_endura;
+module_param(assume_endura, int, 0644);
+MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura");
+
+/* #define GO7007_USB_DEBUG */
+/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
+
+#define HPI_STATUS_ADDR 0xFFF4
+#define INT_PARAM_ADDR 0xFFF6
+#define INT_INDEX_ADDR 0xFFF8
+
+/*
+ * Pipes on EZ-USB interface:
+ * 0 snd - Control
+ * 0 rcv - Control
+ * 2 snd - Download firmware (control)
+ * 4 rcv - Read Interrupt (interrupt)
+ * 6 rcv - Read Video (bulk)
+ * 8 rcv - Read Audio (bulk)
+ */
+
+#define GO7007_USB_EZUSB (1<<0)
+#define GO7007_USB_EZUSB_I2C (1<<1)
+
+struct go7007_usb_board {
+ unsigned int flags;
+ struct go7007_board_info main_info;
+};
+
+struct go7007_usb {
+ struct go7007_usb_board *board;
+ struct semaphore i2c_lock;
+ struct usb_device *usbdev;
+ struct urb *video_urbs[8];
+ struct urb *audio_urbs[8];
+ struct urb *intr_urb;
+};
+
+/*********************** Product specification data ***********************/
+
+static struct go7007_usb_board board_matrix_ii = {
+ .flags = GO7007_USB_EZUSB,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO |
+ GO7007_BOARD_USE_ONBOARD_I2C,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_VALID_ENABLE |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI |
+ GO7007_SENSOR_SCALING,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_SAA7115,
+ .addr = 0x20,
+ },
+ },
+ .num_inputs = 2,
+ .inputs = {
+ {
+ .video_input = 0,
+ .name = "Composite",
+ },
+ {
+ .video_input = 9,
+ .name = "S-Video",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_matrix_reload = {
+ .flags = GO7007_USB_EZUSB,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO |
+ GO7007_BOARD_USE_ONBOARD_I2C,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_TV,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_SAA7113,
+ .addr = 0x25,
+ },
+ },
+ .num_inputs = 2,
+ .inputs = {
+ {
+ .video_input = 0,
+ .name = "Composite",
+ },
+ {
+ .video_input = 9,
+ .name = "S-Video",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_star_trek = {
+ .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO, /* |
+ GO7007_BOARD_HAS_TUNER, */
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_VALID_ENABLE |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI |
+ GO7007_SENSOR_SCALING,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_WORD_16,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_SAA7115,
+ .addr = 0x20,
+ },
+ },
+ .num_inputs = 2,
+ .inputs = {
+ {
+ .video_input = 1,
+ /* .audio_input = AUDIO_EXTERN, */
+ .name = "Composite",
+ },
+ {
+ .video_input = 8,
+ /* .audio_input = AUDIO_EXTERN, */
+ .name = "S-Video",
+ },
+ /* {
+ * .video_input = 3,
+ * .audio_input = AUDIO_TUNER,
+ * .name = "Tuner",
+ * },
+ */
+ },
+ },
+};
+
+static struct go7007_usb_board board_px_tv402u = {
+ .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO |
+ GO7007_BOARD_HAS_TUNER,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_VALID_ENABLE |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI |
+ GO7007_SENSOR_SCALING,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_WORD_16,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .num_i2c_devs = 3,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_SAA7115,
+ .addr = 0x20,
+ },
+ {
+ .id = I2C_DRIVERID_WIS_UDA1342,
+ .addr = 0x1a,
+ },
+ {
+ .id = I2C_DRIVERID_WIS_SONY_TUNER,
+ .addr = 0x60,
+ },
+ },
+ .num_inputs = 3,
+ .inputs = {
+ {
+ .video_input = 1,
+ .audio_input = TVAUDIO_INPUT_EXTERN,
+ .name = "Composite",
+ },
+ {
+ .video_input = 8,
+ .audio_input = TVAUDIO_INPUT_EXTERN,
+ .name = "S-Video",
+ },
+ {
+ .video_input = 3,
+ .audio_input = TVAUDIO_INPUT_TUNER,
+ .name = "Tuner",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_xmen = {
+ .flags = 0,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_USE_ONBOARD_I2C,
+ .hpi_buffer_cap = 0,
+ .sensor_flags = GO7007_SENSOR_VREF_POLAR,
+ .sensor_width = 320,
+ .sensor_height = 240,
+ .sensor_framerate = 30030,
+ .audio_flags = GO7007_AUDIO_ONE_CHANNEL |
+ GO7007_AUDIO_I2S_MODE_3 |
+ GO7007_AUDIO_WORD_14 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_BCLK_POLAR |
+ GO7007_AUDIO_OKI_MODE,
+ .audio_rate = 8000,
+ .audio_bclk_div = 48,
+ .audio_main_div = 1,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_OV7640,
+ .addr = 0x21,
+ },
+ },
+ .num_inputs = 1,
+ .inputs = {
+ {
+ .name = "Camera",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_matrix_revolution = {
+ .flags = GO7007_USB_EZUSB,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO |
+ GO7007_BOARD_USE_ONBOARD_I2C,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_TW9903,
+ .addr = 0x44,
+ },
+ },
+ .num_inputs = 2,
+ .inputs = {
+ {
+ .video_input = 2,
+ .name = "Composite",
+ },
+ {
+ .video_input = 8,
+ .name = "S-Video",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_lifeview_lr192 = {
+ .flags = GO7007_USB_EZUSB,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_HAS_AUDIO |
+ GO7007_BOARD_USE_ONBOARD_I2C,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_VALID_ENABLE |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI |
+ GO7007_SENSOR_SCALING,
+ .num_i2c_devs = 0,
+ .num_inputs = 1,
+ .inputs = {
+ {
+ .video_input = 0,
+ .name = "Composite",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_endura = {
+ .flags = 0,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = 0,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 8000,
+ .audio_bclk_div = 48,
+ .audio_main_div = 8,
+ .hpi_buffer_cap = 0,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_TV,
+ .sensor_h_offset = 8,
+ .num_i2c_devs = 0,
+ .num_inputs = 1,
+ .inputs = {
+ {
+ .name = "Camera",
+ },
+ },
+ },
+};
+
+static struct go7007_usb_board board_adlink_mpg24 = {
+ .flags = 0,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .flags = GO7007_BOARD_USE_ONBOARD_I2C,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 0,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_WIS_TW2804,
+ .addr = 0x00, /* yes, really */
+ },
+ },
+ .num_inputs = 1,
+ .inputs = {
+ {
+ .name = "Composite",
+ },
+ },
+ },
+};
+
+static struct usb_device_id go7007_usb_id_table[] = {
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x200, /* Revision number of XMen */
+ .bcdDevice_hi = 0x200,
+ .bInterfaceClass = 255,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 255,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x202, /* Revision number of Matrix II */
+ .bcdDevice_hi = 0x202,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x204, /* Revision number of Matrix */
+ .bcdDevice_hi = 0x204, /* Reloaded */
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x205, /* Revision number of XMen-II */
+ .bcdDevice_hi = 0x205,
+ .bInterfaceClass = 255,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 255,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x208, /* Revision number of Star Trek */
+ .bcdDevice_hi = 0x208,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x209, /* Revision number of XMen-III */
+ .bcdDevice_hi = 0x209,
+ .bInterfaceClass = 255,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 255,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */
+ .idProduct = 0x7007, /* Product ID of GO7007SB chip */
+ .bcdDevice_lo = 0x210, /* Revision number of Matrix */
+ .bcdDevice_hi = 0x210, /* Revolution */
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x093b, /* Vendor ID of Plextor */
+ .idProduct = 0xa102, /* Product ID of M402U */
+ .bcdDevice_lo = 0x1, /* revision number of Blueberry */
+ .bcdDevice_hi = 0x1,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x093b, /* Vendor ID of Plextor */
+ .idProduct = 0xa104, /* Product ID of TV402U */
+ .bcdDevice_lo = 0x1,
+ .bcdDevice_hi = 0x1,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U_ANY,
+ },
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */
+ .idProduct = 0xde00, /* Product ID of Lifeview LR192 */
+ .bcdDevice_lo = 0x1,
+ .bcdDevice_hi = 0x1,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
+ },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, go7007_usb_id_table);
+
+/********************* Driver for EZ-USB HPI interface *********************/
+
+static int go7007_usb_vendor_request(struct go7007 *go, int request,
+ int value, int index, void *transfer_buffer, int length, int in)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int timeout = 5000;
+
+ if (in) {
+ return usb_control_msg(usb->usbdev,
+ usb_rcvctrlpipe(usb->usbdev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+ value, index, transfer_buffer, length, timeout);
+ } else {
+ return usb_control_msg(usb->usbdev,
+ usb_sndctrlpipe(usb->usbdev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, transfer_buffer, length, timeout);
+ }
+}
+
+static int go7007_usb_interface_reset(struct go7007 *go)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ u16 intr_val, intr_data;
+
+ /* Reset encoder */
+ if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
+ return -1;
+ msleep(100);
+
+ if (usb->board->flags & GO7007_USB_EZUSB) {
+ /* Reset buffer in EZ-USB */
+#ifdef GO7007_USB_DEBUG
+ printk(KERN_DEBUG "go7007-usb: resetting EZ-USB buffers\n");
+#endif
+ if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
+ go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
+ return -1;
+
+ /* Reset encoder again */
+ if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
+ return -1;
+ msleep(100);
+ }
+
+ /* Wait for an interrupt to indicate successful hardware reset */
+ if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+ (intr_val & ~0x1) != 0x55aa) {
+ printk(KERN_ERR
+ "go7007-usb: unable to reset the USB interface\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
+ int addr, int data)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int i, r;
+ u16 status_reg;
+ int timeout = 500;
+
+#ifdef GO7007_USB_DEBUG
+ printk(KERN_DEBUG
+ "go7007-usb: WriteInterrupt: %04x %04x\n", addr, data);
+#endif
+
+ for (i = 0; i < 100; ++i) {
+ r = usb_control_msg(usb->usbdev,
+ usb_rcvctrlpipe(usb->usbdev, 0), 0x14,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+ 0, HPI_STATUS_ADDR, &status_reg,
+ sizeof(status_reg), timeout);
+ if (r < 0)
+ goto write_int_error;
+ __le16_to_cpus(&status_reg);
+ if (!(status_reg & 0x0010))
+ break;
+ msleep(10);
+ }
+ if (i == 100) {
+ printk(KERN_ERR
+ "go7007-usb: device is hung, status reg = 0x%04x\n",
+ status_reg);
+ return -1;
+ }
+ r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE, data,
+ INT_PARAM_ADDR, NULL, 0, timeout);
+ if (r < 0)
+ goto write_int_error;
+ r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0),
+ 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr,
+ INT_INDEX_ADDR, NULL, 0, timeout);
+ if (r < 0)
+ goto write_int_error;
+ return 0;
+
+write_int_error:
+ printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r);
+ return r;
+}
+
+static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
+ int addr, int data)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ u8 *tbuf;
+ int r;
+ int timeout = 500;
+
+#ifdef GO7007_USB_DEBUG
+ printk(KERN_DEBUG
+ "go7007-usb: WriteInterrupt: %04x %04x\n", addr, data);
+#endif
+
+ tbuf = kmalloc(8, GFP_KERNEL);
+ if (tbuf == NULL)
+ return -ENOMEM;
+ memset(tbuf, 0, 8);
+ tbuf[0] = data & 0xff;
+ tbuf[1] = data >> 8;
+ tbuf[2] = addr & 0xff;
+ tbuf[3] = addr >> 8;
+ r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
+ 0xf0f0, tbuf, 8, timeout);
+ kfree(tbuf);
+ if (r < 0) {
+ printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r);
+ return r;
+ }
+ return 0;
+}
+
+static void go7007_usb_readinterrupt_complete(struct urb *urb)
+{
+ struct go7007 *go = (struct go7007 *)urb->context;
+ u16 *regs = (u16 *)urb->transfer_buffer;
+
+ if (urb->status != 0) {
+ if (urb->status != -ESHUTDOWN &&
+ go->status != STATUS_SHUTDOWN) {
+ printk(KERN_ERR
+ "go7007-usb: error in read interrupt: %d\n",
+ urb->status);
+ } else {
+ wake_up(&go->interrupt_waitq);
+ return;
+ }
+ } else if (urb->actual_length != urb->transfer_buffer_length) {
+ printk(KERN_ERR "go7007-usb: short read in interrupt pipe!\n");
+ } else {
+ go->interrupt_available = 1;
+ go->interrupt_data = __le16_to_cpu(regs[0]);
+ go->interrupt_value = __le16_to_cpu(regs[1]);
+#ifdef GO7007_USB_DEBUG
+ printk(KERN_DEBUG "go7007-usb: ReadInterrupt: %04x %04x\n",
+ go->interrupt_value, go->interrupt_data);
+#endif
+ }
+
+ wake_up(&go->interrupt_waitq);
+}
+
+static int go7007_usb_read_interrupt(struct go7007 *go)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int r;
+
+ r = usb_submit_urb(usb->intr_urb, GFP_KERNEL);
+ if (r < 0) {
+ printk(KERN_ERR
+ "go7007-usb: unable to submit interrupt urb: %d\n", r);
+ return r;
+ }
+ return 0;
+}
+
+static void go7007_usb_read_video_pipe_complete(struct urb *urb)
+{
+ struct go7007 *go = (struct go7007 *)urb->context;
+ int r;
+
+ if (!go->streaming) {
+ wake_up_interruptible(&go->frame_waitq);
+ return;
+ }
+ if (urb->status != 0) {
+ printk(KERN_ERR "go7007-usb: error in video pipe: %d\n",
+ urb->status);
+ return;
+ }
+ if (urb->actual_length != urb->transfer_buffer_length) {
+ printk(KERN_ERR "go7007-usb: short read in video pipe!\n");
+ return;
+ }
+ go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length);
+ r = usb_submit_urb(urb, GFP_ATOMIC);
+ if (r < 0)
+ printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", r);
+}
+
+static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
+{
+ struct go7007 *go = (struct go7007 *)urb->context;
+ int r;
+
+ if (!go->streaming)
+ return;
+ if (urb->status != 0) {
+ printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
+ urb->status);
+ return;
+ }
+ if (urb->actual_length != urb->transfer_buffer_length) {
+ printk(KERN_ERR "go7007-usb: short read in audio pipe!\n");
+ return;
+ }
+ if (go->audio_deliver != NULL)
+ go->audio_deliver(go, urb->transfer_buffer, urb->actual_length);
+ r = usb_submit_urb(urb, GFP_ATOMIC);
+ if (r < 0)
+ printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", r);
+}
+
+static int go7007_usb_stream_start(struct go7007 *go)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int i, r;
+
+ for (i = 0; i < 8; ++i) {
+ r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL);
+ if (r < 0) {
+ printk(KERN_ERR "go7007-usb: error submitting video "
+ "urb %d: %d\n", i, r);
+ goto video_submit_failed;
+ }
+ }
+ if (!go->audio_enabled)
+ return 0;
+
+ for (i = 0; i < 8; ++i) {
+ r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL);
+ if (r < 0) {
+ printk(KERN_ERR "go7007-usb: error submitting audio "
+ "urb %d: %d\n", i, r);
+ goto audio_submit_failed;
+ }
+ }
+ return 0;
+
+audio_submit_failed:
+ for (i = 0; i < 8; ++i)
+ usb_kill_urb(usb->audio_urbs[i]);
+video_submit_failed:
+ for (i = 0; i < 8; ++i)
+ usb_kill_urb(usb->video_urbs[i]);
+ return -1;
+}
+
+static int go7007_usb_stream_stop(struct go7007 *go)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int i;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return 0;
+ for (i = 0; i < 8; ++i)
+ usb_kill_urb(usb->video_urbs[i]);
+ if (go->audio_enabled)
+ for (i = 0; i < 8; ++i)
+ usb_kill_urb(usb->audio_urbs[i]);
+ return 0;
+}
+
+static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int transferred, pipe;
+ int timeout = 500;
+
+#ifdef GO7007_USB_DEBUG
+ printk(KERN_DEBUG "go7007-usb: DownloadBuffer sending %d bytes\n", len);
+#endif
+
+ if (usb->board->flags & GO7007_USB_EZUSB)
+ pipe = usb_sndbulkpipe(usb->usbdev, 2);
+ else
+ pipe = usb_sndbulkpipe(usb->usbdev, 3);
+
+ return usb_bulk_msg(usb->usbdev, pipe, data, len,
+ &transferred, timeout);
+}
+
+static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
+ .interface_reset = go7007_usb_interface_reset,
+ .write_interrupt = go7007_usb_ezusb_write_interrupt,
+ .read_interrupt = go7007_usb_read_interrupt,
+ .stream_start = go7007_usb_stream_start,
+ .stream_stop = go7007_usb_stream_stop,
+ .send_firmware = go7007_usb_send_firmware,
+};
+
+static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
+ .interface_reset = go7007_usb_interface_reset,
+ .write_interrupt = go7007_usb_onboard_write_interrupt,
+ .read_interrupt = go7007_usb_read_interrupt,
+ .stream_start = go7007_usb_stream_start,
+ .stream_stop = go7007_usb_stream_stop,
+ .send_firmware = go7007_usb_send_firmware,
+};
+
+/********************* Driver for EZ-USB I2C adapter *********************/
+
+static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg msgs[], int num)
+{
+ struct go7007 *go = i2c_get_adapdata(adapter);
+ struct go7007_usb *usb = go->hpi_context;
+ u8 buf[16];
+ int buf_len, i;
+ int ret = -1;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return -1;
+
+ down(&usb->i2c_lock);
+
+ for (i = 0; i < num; ++i) {
+ /* The hardware command is "write some bytes then read some
+ * bytes", so we try to coalesce a write followed by a read
+ * into a single USB transaction */
+ if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr &&
+ !(msgs[i].flags & I2C_M_RD) &&
+ (msgs[i + 1].flags & I2C_M_RD)) {
+#ifdef GO7007_I2C_DEBUG
+ printk(KERN_DEBUG "go7007-usb: i2c write/read %d/%d "
+ "bytes on %02x\n", msgs[i].len,
+ msgs[i + 1].len, msgs[i].addr);
+#endif
+ buf[0] = 0x01;
+ buf[1] = msgs[i].len + 1;
+ buf[2] = msgs[i].addr << 1;
+ memcpy(&buf[3], msgs[i].buf, msgs[i].len);
+ buf_len = msgs[i].len + 3;
+ buf[buf_len++] = msgs[++i].len;
+ } else if (msgs[i].flags & I2C_M_RD) {
+#ifdef GO7007_I2C_DEBUG
+ printk(KERN_DEBUG "go7007-usb: i2c read %d "
+ "bytes on %02x\n", msgs[i].len,
+ msgs[i].addr);
+#endif
+ buf[0] = 0x01;
+ buf[1] = 1;
+ buf[2] = msgs[i].addr << 1;
+ buf[3] = msgs[i].len;
+ buf_len = 4;
+ } else {
+#ifdef GO7007_I2C_DEBUG
+ printk(KERN_DEBUG "go7007-usb: i2c write %d "
+ "bytes on %02x\n", msgs[i].len,
+ msgs[i].addr);
+#endif
+ buf[0] = 0x00;
+ buf[1] = msgs[i].len + 1;
+ buf[2] = msgs[i].addr << 1;
+ memcpy(&buf[3], msgs[i].buf, msgs[i].len);
+ buf_len = msgs[i].len + 3;
+ buf[buf_len++] = 0;
+ }
+ if (go7007_usb_vendor_request(go, 0x24, 0, 0,
+ buf, buf_len, 0) < 0)
+ goto i2c_done;
+ if (msgs[i].flags & I2C_M_RD) {
+ memset(buf, 0, sizeof(buf));
+ if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
+ msgs[i].len + 1, 1) < 0)
+ goto i2c_done;
+ memcpy(msgs[i].buf, buf + 1, msgs[i].len);
+ }
+ }
+ ret = 0;
+
+i2c_done:
+ up(&usb->i2c_lock);
+ return ret;
+}
+
+static u32 go7007_usb_functionality(struct i2c_adapter *adapter)
+{
+ /* No errors are reported by the hardware, so we don't bother
+ * supporting quick writes to avoid confusing probing */
+ return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK;
+}
+
+static struct i2c_algorithm go7007_usb_algo = {
+ .master_xfer = go7007_usb_i2c_master_xfer,
+ .functionality = go7007_usb_functionality,
+};
+
+static struct i2c_adapter go7007_usb_adap_templ = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_TV_ANALOG,
+ .name = "WIS GO7007SB EZ-USB",
+ .id = I2C_ALGO_GO7007_USB,
+ .algo = &go7007_usb_algo,
+};
+
+/********************* USB add/remove functions *********************/
+
+static int go7007_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct go7007 *go;
+ struct go7007_usb *usb;
+ struct go7007_usb_board *board;
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+ char *name;
+ int video_pipe, i, v_urb_len;
+
+ printk(KERN_DEBUG "go7007-usb: probing new GO7007 USB board\n");
+
+ switch (id->driver_info) {
+ case GO7007_BOARDID_MATRIX_II:
+ name = "WIS Matrix II or compatible";
+ board = &board_matrix_ii;
+ break;
+ case GO7007_BOARDID_MATRIX_RELOAD:
+ name = "WIS Matrix Reloaded or compatible";
+ board = &board_matrix_reload;
+ break;
+ case GO7007_BOARDID_MATRIX_REV:
+ name = "WIS Matrix Revolution or compatible";
+ board = &board_matrix_revolution;
+ break;
+ case GO7007_BOARDID_STAR_TREK:
+ name = "WIS Star Trek or compatible";
+ board = &board_star_trek;
+ break;
+ case GO7007_BOARDID_XMEN:
+ name = "WIS XMen or compatible";
+ board = &board_xmen;
+ break;
+ case GO7007_BOARDID_XMEN_II:
+ name = "WIS XMen II or compatible";
+ board = &board_xmen;
+ break;
+ case GO7007_BOARDID_XMEN_III:
+ name = "WIS XMen III or compatible";
+ board = &board_xmen;
+ break;
+ case GO7007_BOARDID_PX_M402U:
+ name = "Plextor PX-M402U";
+ board = &board_matrix_ii;
+ break;
+ case GO7007_BOARDID_PX_TV402U_ANY:
+ name = "Plextor PX-TV402U (unknown tuner)";
+ board = &board_px_tv402u;
+ break;
+ case GO7007_BOARDID_LIFEVIEW_LR192:
+ printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra "
+ "is not supported. Sorry!\n");
+ return 0;
+ name = "Lifeview TV Walker Ultra";
+ board = &board_lifeview_lr192;
+ break;
+ default:
+ printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
+ (unsigned int)id->driver_info);
+ return 0;
+ }
+
+ usb = kmalloc(sizeof(struct go7007_usb), GFP_KERNEL);
+ if (usb == NULL)
+ return -ENOMEM;
+ memset(usb, 0, sizeof(struct go7007_usb));
+
+ /* Allocate the URB and buffer for receiving incoming interrupts */
+ usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (usb->intr_urb == NULL)
+ goto allocfail;
+ usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
+ if (usb->intr_urb->transfer_buffer == NULL)
+ goto allocfail;
+
+ go = go7007_alloc(&board->main_info, &intf->dev);
+ if (go == NULL)
+ goto allocfail;
+ usb->board = board;
+ usb->usbdev = usbdev;
+ go->board_id = id->driver_info;
+ strncpy(go->name, name, sizeof(go->name));
+ if (board->flags & GO7007_USB_EZUSB)
+ go->hpi_ops = &go7007_usb_ezusb_hpi_ops;
+ else
+ go->hpi_ops = &go7007_usb_onboard_hpi_ops;
+ go->hpi_context = usb;
+ usb_fill_int_urb(usb->intr_urb, usb->usbdev,
+ usb_rcvintpipe(usb->usbdev, 4),
+ usb->intr_urb->transfer_buffer, 2*sizeof(u16),
+ go7007_usb_readinterrupt_complete, go, 8);
+ usb_set_intfdata(intf, go);
+
+ /* Boot the GO7007 */
+ if (go7007_boot_encoder(go, go->board_info->flags &
+ GO7007_BOARD_USE_ONBOARD_I2C) < 0)
+ goto initfail;
+
+ /* Register the EZ-USB I2C adapter, if we're using it */
+ if (board->flags & GO7007_USB_EZUSB_I2C) {
+ memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
+ sizeof(go7007_usb_adap_templ));
+ init_MUTEX(&usb->i2c_lock);
+ go->i2c_adapter.dev.parent = go->dev;
+ i2c_set_adapdata(&go->i2c_adapter, go);
+ if (i2c_add_adapter(&go->i2c_adapter) < 0) {
+ printk(KERN_ERR
+ "go7007-usb: error: i2c_add_adapter failed\n");
+ goto initfail;
+ }
+ go->i2c_adapter_online = 1;
+ }
+
+ /* Pelco and Adlink reused the XMen and XMen-III vendor and product
+ * IDs for their own incompatible designs. We can detect XMen boards
+ * by probing the sensor, but there is no way to probe the sensors on
+ * the Pelco and Adlink designs so we default to the Adlink. If it
+ * is actually a Pelco, the user must set the assume_endura module
+ * parameter. */
+ if ((go->board_id == GO7007_BOARDID_XMEN ||
+ go->board_id == GO7007_BOARDID_XMEN_III) &&
+ go->i2c_adapter_online) {
+ union i2c_smbus_data data;
+
+ /* Check to see if register 0x0A is 0x76 */
+ i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
+ I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
+ if (data.byte != 0x76) {
+ if (assume_endura) {
+ go->board_id = GO7007_BOARDID_ENDURA;
+ usb->board = board = &board_endura;
+ go->board_info = &board->main_info;
+ strncpy(go->name, "Pelco Endura",
+ sizeof(go->name));
+ } else {
+ u16 channel;
+
+ /* set GPIO5 to be an output, currently low */
+ go7007_write_addr(go, 0x3c82, 0x0000);
+ go7007_write_addr(go, 0x3c80, 0x00df);
+ /* read channel number from GPIO[1:0] */
+ go7007_read_addr(go, 0x3c81, &channel);
+ channel &= 0x3;
+ go->board_id = GO7007_BOARDID_ADLINK_MPG24;
+ usb->board = board = &board_adlink_mpg24;
+ go->board_info = &board->main_info;
+ go->channel_number = channel;
+ snprintf(go->name, sizeof(go->name),
+ "Adlink PCI-MPG24, channel #%d",
+ channel);
+ }
+ }
+ }
+
+ /* Probe the tuner model on the TV402U */
+ if (go->board_id == GO7007_BOARDID_PX_TV402U_ANY) {
+ u8 data[3];
+
+ /* Board strapping indicates tuner model */
+ if (go7007_usb_vendor_request(go, 0x41, 0, 0, data, 3, 1) < 0) {
+ printk(KERN_ERR "go7007-usb: GPIO read failed!\n");
+ goto initfail;
+ }
+ switch (data[0] >> 6) {
+ case 1:
+ go->board_id = GO7007_BOARDID_PX_TV402U_EU;
+ go->tuner_type = TUNER_SONY_BTF_PG472Z;
+ strncpy(go->name, "Plextor PX-TV402U-EU",
+ sizeof(go->name));
+ break;
+ case 2:
+ go->board_id = GO7007_BOARDID_PX_TV402U_JP;
+ go->tuner_type = TUNER_SONY_BTF_PK467Z;
+ strncpy(go->name, "Plextor PX-TV402U-JP",
+ sizeof(go->name));
+ break;
+ case 3:
+ go->board_id = GO7007_BOARDID_PX_TV402U_NA;
+ go->tuner_type = TUNER_SONY_BTF_PB463Z;
+ strncpy(go->name, "Plextor PX-TV402U-NA",
+ sizeof(go->name));
+ break;
+ default:
+ printk(KERN_DEBUG "go7007-usb: unable to detect "
+ "tuner type!\n");
+ break;
+ }
+ /* Configure tuner mode selection inputs connected
+ * to the EZ-USB GPIO output pins */
+ if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
+ NULL, 0, 0) < 0) {
+ printk(KERN_ERR
+ "go7007-usb: GPIO write failed!\n");
+ goto initfail;
+ }
+ }
+
+ /* Print a nasty message if the user attempts to use a USB2.0 device in
+ * a USB1.1 port. There will be silent corruption of the stream. */
+ if ((board->flags & GO7007_USB_EZUSB) &&
+ usbdev->speed != USB_SPEED_HIGH)
+ printk(KERN_ERR "go7007-usb: *** WARNING *** This device "
+ "must be connected to a USB 2.0 port! "
+ "Attempting to capture video through a USB 1.1 "
+ "port will result in stream corruption, even "
+ "at low bitrates!\n");
+
+ /* Do any final GO7007 initialization, then register the
+ * V4L2 and ALSA interfaces */
+ if (go7007_register_encoder(go) < 0)
+ goto initfail;
+
+ /* Allocate the URBs and buffers for receiving the video stream */
+ if (board->flags & GO7007_USB_EZUSB) {
+ v_urb_len = 1024;
+ video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
+ } else {
+ v_urb_len = 512;
+ video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (usb->video_urbs[i] == NULL)
+ goto initfail;
+ usb->video_urbs[i]->transfer_buffer =
+ kmalloc(v_urb_len, GFP_KERNEL);
+ if (usb->video_urbs[i]->transfer_buffer == NULL)
+ goto initfail;
+ usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
+ usb->video_urbs[i]->transfer_buffer, v_urb_len,
+ go7007_usb_read_video_pipe_complete, go);
+ }
+
+ /* Allocate the URBs and buffers for receiving the audio stream */
+ if ((board->flags & GO7007_USB_EZUSB) && go->audio_enabled)
+ for (i = 0; i < 8; ++i) {
+ usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (usb->audio_urbs[i] == NULL)
+ goto initfail;
+ usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
+ GFP_KERNEL);
+ if (usb->audio_urbs[i]->transfer_buffer == NULL)
+ goto initfail;
+ usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
+ usb_rcvbulkpipe(usb->usbdev, 8),
+ usb->audio_urbs[i]->transfer_buffer, 4096,
+ go7007_usb_read_audio_pipe_complete, go);
+ }
+
+
+ go->status = STATUS_ONLINE;
+ return 0;
+
+initfail:
+ go->status = STATUS_SHUTDOWN;
+ return 0;
+
+allocfail:
+ if (usb->intr_urb) {
+ kfree(usb->intr_urb->transfer_buffer);
+ usb_free_urb(usb->intr_urb);
+ }
+ kfree(usb);
+ return -ENOMEM;
+}
+
+static void go7007_usb_disconnect(struct usb_interface *intf)
+{
+ struct go7007 *go = usb_get_intfdata(intf);
+ struct go7007_usb *usb = go->hpi_context;
+ int i;
+
+ go->status = STATUS_SHUTDOWN;
+ usb_kill_urb(usb->intr_urb);
+
+ /* Free USB-related structs */
+ for (i = 0; i < 8; ++i) {
+ if (usb->video_urbs[i] != NULL) {
+ if (usb->video_urbs[i]->transfer_buffer != NULL)
+ kfree(usb->video_urbs[i]->transfer_buffer);
+ usb_free_urb(usb->video_urbs[i]);
+ }
+ if (usb->audio_urbs[i] != NULL) {
+ if (usb->audio_urbs[i]->transfer_buffer != NULL)
+ kfree(usb->audio_urbs[i]->transfer_buffer);
+ usb_free_urb(usb->audio_urbs[i]);
+ }
+ }
+ kfree(usb->intr_urb->transfer_buffer);
+ usb_free_urb(usb->intr_urb);
+
+ kfree(go->hpi_context);
+
+ go7007_remove(go);
+}
+
+static struct usb_driver go7007_usb_driver = {
+ .name = "go7007",
+ .probe = go7007_usb_probe,
+ .disconnect = go7007_usb_disconnect,
+ .id_table = go7007_usb_id_table,
+};
+
+static int __init go7007_usb_init(void)
+{
+ return usb_register(&go7007_usb_driver);
+}
+
+static void __exit go7007_usb_cleanup(void)
+{
+ usb_deregister(&go7007_usb_driver);
+}
+
+module_init(go7007_usb_init);
+module_exit(go7007_usb_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c
new file mode 100644
index 00000000000..94e1141a1fc
--- /dev/null
+++ b/drivers/staging/go7007/go7007-v4l2.c
@@ -0,0 +1,1499 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/i2c.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include "go7007.h"
+#include "go7007-priv.h"
+#include "wis-i2c.h"
+
+static void deactivate_buffer(struct go7007_buffer *gobuf)
+{
+ int i;
+
+ if (gobuf->state != BUF_STATE_IDLE) {
+ list_del(&gobuf->stream);
+ gobuf->state = BUF_STATE_IDLE;
+ }
+ if (gobuf->page_count > 0) {
+ for (i = 0; i < gobuf->page_count; ++i)
+ page_cache_release(gobuf->pages[i]);
+ gobuf->page_count = 0;
+ }
+}
+
+static void abort_queued(struct go7007 *go)
+{
+ struct go7007_buffer *gobuf, *next;
+
+ list_for_each_entry_safe(gobuf, next, &go->stream, stream) {
+ deactivate_buffer(gobuf);
+ }
+}
+
+static int go7007_streamoff(struct go7007 *go)
+{
+ int retval = -EINVAL;
+ unsigned long flags;
+
+ down(&go->hw_lock);
+ if (go->streaming) {
+ go->streaming = 0;
+ go7007_stream_stop(go);
+ spin_lock_irqsave(&go->spinlock, flags);
+ abort_queued(go);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ go7007_reset_encoder(go);
+ retval = 0;
+ }
+ up(&go->hw_lock);
+ return 0;
+}
+
+static int go7007_open(struct inode *inode, struct file *file)
+{
+ struct go7007 *go = video_get_drvdata(video_devdata(file));
+ struct go7007_file *gofh;
+
+ if (go->status != STATUS_ONLINE)
+ return -EBUSY;
+ gofh = kmalloc(sizeof(struct go7007_file), GFP_KERNEL);
+ if (gofh == NULL)
+ return -ENOMEM;
+ ++go->ref_count;
+ gofh->go = go;
+ init_MUTEX(&gofh->lock);
+ gofh->buf_count = 0;
+ file->private_data = gofh;
+ return 0;
+}
+
+static int go7007_release(struct inode *inode, struct file *file)
+{
+ struct go7007_file *gofh = file->private_data;
+ struct go7007 *go = gofh->go;
+
+ if (gofh->buf_count > 0) {
+ go7007_streamoff(go);
+ go->in_use = 0;
+ kfree(gofh->bufs);
+ gofh->buf_count = 0;
+ }
+ kfree(gofh);
+ if (--go->ref_count == 0)
+ kfree(go);
+ file->private_data = NULL;
+ return 0;
+}
+
+static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format)
+{
+ u8 *f = page_address(gobuf->pages[0]);
+
+ switch (format) {
+ case GO7007_FORMAT_MJPEG:
+ return V4L2_BUF_FLAG_KEYFRAME;
+ case GO7007_FORMAT_MPEG4:
+ switch ((f[gobuf->frame_offset + 4] >> 6) & 0x3) {
+ case 0:
+ return V4L2_BUF_FLAG_KEYFRAME;
+ case 1:
+ return V4L2_BUF_FLAG_PFRAME;
+ case 2:
+ return V4L2_BUF_FLAG_BFRAME;
+ default:
+ return 0;
+ }
+ case GO7007_FORMAT_MPEG1:
+ case GO7007_FORMAT_MPEG2:
+ switch ((f[gobuf->frame_offset + 5] >> 3) & 0x7) {
+ case 1:
+ return V4L2_BUF_FLAG_KEYFRAME;
+ case 2:
+ return V4L2_BUF_FLAG_PFRAME;
+ case 3:
+ return V4L2_BUF_FLAG_BFRAME;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
+{
+ int sensor_height = 0, sensor_width = 0;
+ int width, height, i;
+
+ if (fmt != NULL && fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
+ fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG &&
+ fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG4)
+ return -EINVAL;
+
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ sensor_width = 720;
+ sensor_height = 480;
+ break;
+ case GO7007_STD_PAL:
+ sensor_width = 720;
+ sensor_height = 576;
+ break;
+ case GO7007_STD_OTHER:
+ sensor_width = go->board_info->sensor_width;
+ sensor_height = go->board_info->sensor_height;
+ break;
+ }
+
+ if (fmt == NULL) {
+ width = sensor_width;
+ height = sensor_height;
+ } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
+ if (fmt->fmt.pix.width > sensor_width)
+ width = sensor_width;
+ else if (fmt->fmt.pix.width < 144)
+ width = 144;
+ else
+ width = fmt->fmt.pix.width & ~0x0f;
+
+ if (fmt->fmt.pix.height > sensor_height)
+ height = sensor_height;
+ else if (fmt->fmt.pix.height < 96)
+ height = 96;
+ else
+ height = fmt->fmt.pix.height & ~0x0f;
+ } else {
+ int requested_size = fmt->fmt.pix.width * fmt->fmt.pix.height;
+ int sensor_size = sensor_width * sensor_height;
+
+ if (64 * requested_size < 9 * sensor_size) {
+ width = sensor_width / 4;
+ height = sensor_height / 4;
+ } else if (64 * requested_size < 36 * sensor_size) {
+ width = sensor_width / 2;
+ height = sensor_height / 2;
+ } else {
+ width = sensor_width;
+ height = sensor_height;
+ }
+ width &= ~0xf;
+ height &= ~0xf;
+ }
+
+ if (fmt != NULL) {
+ u32 pixelformat = fmt->fmt.pix.pixelformat;
+
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt->fmt.pix.width = width;
+ fmt->fmt.pix.height = height;
+ fmt->fmt.pix.pixelformat = pixelformat;
+ fmt->fmt.pix.field = V4L2_FIELD_NONE;
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
+ }
+
+ if (try)
+ return 0;
+
+ go->width = width;
+ go->height = height;
+ go->encoder_h_offset = go->board_info->sensor_h_offset;
+ go->encoder_v_offset = go->board_info->sensor_v_offset;
+ for (i = 0; i < 4; ++i)
+ go->modet[i].enable = 0;
+ for (i = 0; i < 1624; ++i)
+ go->modet_map[i] = 0;
+
+ if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
+ struct video_decoder_resolution res;
+
+ res.width = width;
+ if (height > sensor_height / 2) {
+ res.height = height / 2;
+ go->encoder_v_halve = 0;
+ } else {
+ res.height = height;
+ go->encoder_v_halve = 1;
+ }
+ if (go->i2c_adapter_online)
+ i2c_clients_command(&go->i2c_adapter,
+ DECODER_SET_RESOLUTION, &res);
+ } else {
+ if (width <= sensor_width / 4) {
+ go->encoder_h_halve = 1;
+ go->encoder_v_halve = 1;
+ go->encoder_subsample = 1;
+ } else if (width <= sensor_width / 2) {
+ go->encoder_h_halve = 1;
+ go->encoder_v_halve = 1;
+ go->encoder_subsample = 0;
+ } else {
+ go->encoder_h_halve = 0;
+ go->encoder_v_halve = 0;
+ go->encoder_subsample = 0;
+ }
+ }
+
+ if (fmt == NULL)
+ return 0;
+
+ switch (fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_MPEG:
+ if (go->format == GO7007_FORMAT_MPEG1 ||
+ go->format == GO7007_FORMAT_MPEG2 ||
+ go->format == GO7007_FORMAT_MPEG4)
+ break;
+ go->format = GO7007_FORMAT_MPEG1;
+ go->pali = 0;
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ go->gop_size = go->sensor_framerate / 1000;
+ go->ipb = 0;
+ go->closed_gop = 1;
+ go->repeat_seqhead = 1;
+ go->seq_header_enable = 1;
+ go->gop_header_enable = 1;
+ go->dvd_mode = 0;
+ break;
+ /* Backwards compatibility only! */
+ case V4L2_PIX_FMT_MPEG4:
+ if (go->format == GO7007_FORMAT_MPEG4)
+ break;
+ go->format = GO7007_FORMAT_MPEG4;
+ go->pali = 0xf5;
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ go->gop_size = go->sensor_framerate / 1000;
+ go->ipb = 0;
+ go->closed_gop = 1;
+ go->repeat_seqhead = 1;
+ go->seq_header_enable = 1;
+ go->gop_header_enable = 1;
+ go->dvd_mode = 0;
+ break;
+ case V4L2_PIX_FMT_MJPEG:
+ go->format = GO7007_FORMAT_MJPEG;
+ go->pali = 0;
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ go->gop_size = 0;
+ go->ipb = 0;
+ go->closed_gop = 0;
+ go->repeat_seqhead = 0;
+ go->seq_header_enable = 0;
+ go->gop_header_enable = 0;
+ go->dvd_mode = 0;
+ break;
+ }
+ return 0;
+}
+
+static int clip_to_modet_map(struct go7007 *go, int region,
+ struct v4l2_clip *clip_list)
+{
+ struct v4l2_clip clip, *clip_ptr;
+ int x, y, mbnum;
+
+ /* Check if coordinates are OK and if any macroblocks are already
+ * used by other regions (besides 0) */
+ clip_ptr = clip_list;
+ while (clip_ptr) {
+ if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
+ return -EFAULT;
+ if (clip.c.left < 0 || (clip.c.left & 0xF) ||
+ clip.c.width <= 0 || (clip.c.width & 0xF))
+ return -EINVAL;
+ if (clip.c.left + clip.c.width > go->width)
+ return -EINVAL;
+ if (clip.c.top < 0 || (clip.c.top & 0xF) ||
+ clip.c.height <= 0 || (clip.c.height & 0xF))
+ return -EINVAL;
+ if (clip.c.top + clip.c.height > go->height)
+ return -EINVAL;
+ for (y = 0; y < clip.c.height; y += 16)
+ for (x = 0; x < clip.c.width; x += 16) {
+ mbnum = (go->width >> 4) *
+ ((clip.c.top + y) >> 4) +
+ ((clip.c.left + x) >> 4);
+ if (go->modet_map[mbnum] != 0 &&
+ go->modet_map[mbnum] != region)
+ return -EBUSY;
+ }
+ clip_ptr = clip.next;
+ }
+
+ /* Clear old region macroblocks */
+ for (mbnum = 0; mbnum < 1624; ++mbnum)
+ if (go->modet_map[mbnum] == region)
+ go->modet_map[mbnum] = 0;
+
+ /* Claim macroblocks in this list */
+ clip_ptr = clip_list;
+ while (clip_ptr) {
+ if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
+ return -EFAULT;
+ for (y = 0; y < clip.c.height; y += 16)
+ for (x = 0; x < clip.c.width; x += 16) {
+ mbnum = (go->width >> 4) *
+ ((clip.c.top + y) >> 4) +
+ ((clip.c.left + x) >> 4);
+ go->modet_map[mbnum] = region;
+ }
+ clip_ptr = clip.next;
+ }
+ return 0;
+}
+
+static int go7007_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct go7007_file *gofh = file->private_data;
+ struct go7007 *go = gofh->go;
+ unsigned long flags;
+ int retval = 0;
+
+ switch (cmd) {
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap, 0, sizeof(*cap));
+ strcpy(cap->driver, "go7007");
+ strncpy(cap->card, go->name, sizeof(cap->card));
+ cap->version = KERNEL_VERSION(0, 9, 8);
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
+ if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
+ cap->capabilities |= V4L2_CAP_TUNER;
+ return 0;
+ }
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *fmt = arg;
+ unsigned int index;
+ char *desc;
+ u32 pixelformat;
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ switch (fmt->index) {
+ case 0:
+ pixelformat = V4L2_PIX_FMT_MJPEG;
+ desc = "Motion-JPEG";
+ break;
+ case 1:
+ pixelformat = V4L2_PIX_FMT_MPEG;
+ desc = "MPEG1/MPEG2/MPEG4";
+ break;
+ default:
+ return -EINVAL;
+ }
+ index = fmt->index;
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->index = index;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
+ strncpy(fmt->description, desc, sizeof(fmt->description));
+ fmt->pixelformat = pixelformat;
+
+ return 0;
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *fmt = arg;
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ return set_capture_size(go, fmt, 1);
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *fmt = arg;
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt->fmt.pix.width = go->width;
+ fmt->fmt.pix.height = go->height;
+ fmt->fmt.pix.pixelformat = go->format == GO7007_FORMAT_MJPEG ?
+ V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
+ fmt->fmt.pix.field = V4L2_FIELD_NONE;
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
+ return 0;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *fmt = arg;
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (go->streaming)
+ return -EBUSY;
+ return set_capture_size(go, fmt, 0);
+ }
+ case VIDIOC_G_FBUF:
+ case VIDIOC_S_FBUF:
+ return -EINVAL;
+ case VIDIOC_REQBUFS:
+ {
+ struct v4l2_requestbuffers *req = arg;
+ unsigned int count, i;
+
+ if (go->streaming)
+ return -EBUSY;
+ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ req->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+
+ down(&gofh->lock);
+ retval = -EBUSY;
+ for (i = 0; i < gofh->buf_count; ++i)
+ if (gofh->bufs[i].mapped > 0)
+ goto unlock_and_return;
+ down(&go->hw_lock);
+ if (go->in_use > 0 && gofh->buf_count == 0) {
+ up(&go->hw_lock);
+ goto unlock_and_return;
+ }
+ if (gofh->buf_count > 0)
+ kfree(gofh->bufs);
+ retval = -ENOMEM;
+ count = req->count;
+ if (count > 0) {
+ if (count < 2)
+ count = 2;
+ if (count > 32)
+ count = 32;
+ gofh->bufs = kmalloc(count *
+ sizeof(struct go7007_buffer),
+ GFP_KERNEL);
+ if (gofh->bufs == NULL) {
+ up(&go->hw_lock);
+ goto unlock_and_return;
+ }
+ memset(gofh->bufs, 0,
+ count * sizeof(struct go7007_buffer));
+ for (i = 0; i < count; ++i) {
+ gofh->bufs[i].go = go;
+ gofh->bufs[i].index = i;
+ gofh->bufs[i].state = BUF_STATE_IDLE;
+ gofh->bufs[i].mapped = 0;
+ }
+ go->in_use = 1;
+ } else {
+ go->in_use = 0;
+ }
+ gofh->buf_count = count;
+ up(&go->hw_lock);
+ up(&gofh->lock);
+ memset(req, 0, sizeof(*req));
+ req->count = count;
+ req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req->memory = V4L2_MEMORY_MMAP;
+ return 0;
+ }
+ case VIDIOC_QUERYBUF:
+ {
+ struct v4l2_buffer *buf = arg;
+ unsigned int index;
+
+ retval = -EINVAL;
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ index = buf->index;
+ down(&gofh->lock);
+ if (index >= gofh->buf_count)
+ goto unlock_and_return;
+ memset(buf, 0, sizeof(*buf));
+ buf->index = index;
+ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ switch (gofh->bufs[index].state) {
+ case BUF_STATE_QUEUED:
+ buf->flags = V4L2_BUF_FLAG_QUEUED;
+ break;
+ case BUF_STATE_DONE:
+ buf->flags = V4L2_BUF_FLAG_DONE;
+ break;
+ default:
+ buf->flags = 0;
+ }
+ if (gofh->bufs[index].mapped)
+ buf->flags |= V4L2_BUF_FLAG_MAPPED;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = index * GO7007_BUF_SIZE;
+ buf->length = GO7007_BUF_SIZE;
+ up(&gofh->lock);
+
+ return 0;
+ }
+ case VIDIOC_QBUF:
+ {
+ struct v4l2_buffer *buf = arg;
+ struct go7007_buffer *gobuf;
+ int ret;
+
+ retval = -EINVAL;
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ buf->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+ down(&gofh->lock);
+ if (buf->index < 0 || buf->index >= gofh->buf_count)
+ goto unlock_and_return;
+ gobuf = &gofh->bufs[buf->index];
+ if (gobuf->mapped == 0)
+ goto unlock_and_return;
+ retval = -EBUSY;
+ if (gobuf->state != BUF_STATE_IDLE)
+ goto unlock_and_return;
+ /* offset will be 0 until we really support USERPTR streaming */
+ gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
+ gobuf->bytesused = 0;
+ gobuf->frame_offset = 0;
+ gobuf->modet_active = 0;
+ if (gobuf->offset > 0)
+ gobuf->page_count = GO7007_BUF_PAGES + 1;
+ else
+ gobuf->page_count = GO7007_BUF_PAGES;
+ retval = -ENOMEM;
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm,
+ gobuf->user_addr & PAGE_MASK, gobuf->page_count,
+ 1, 1, gobuf->pages, NULL);
+ up_read(&current->mm->mmap_sem);
+ if (ret != gobuf->page_count) {
+ int i;
+ for (i = 0; i < ret; ++i)
+ page_cache_release(gobuf->pages[i]);
+ gobuf->page_count = 0;
+ goto unlock_and_return;
+ }
+ gobuf->state = BUF_STATE_QUEUED;
+ spin_lock_irqsave(&go->spinlock, flags);
+ list_add_tail(&gobuf->stream, &go->stream);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ up(&gofh->lock);
+ return 0;
+ }
+ case VIDIOC_DQBUF:
+ {
+ struct v4l2_buffer *buf = arg;
+ struct go7007_buffer *gobuf;
+ u32 frame_type_flag;
+ DEFINE_WAIT(wait);
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (buf->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+ down(&gofh->lock);
+ retval = -EINVAL;
+ if (list_empty(&go->stream))
+ goto unlock_and_return;
+ gobuf = list_entry(go->stream.next,
+ struct go7007_buffer, stream);
+ retval = -EAGAIN;
+ if (gobuf->state != BUF_STATE_DONE &&
+ !(file->f_flags & O_NONBLOCK)) {
+ for (;;) {
+ prepare_to_wait(&go->frame_waitq, &wait,
+ TASK_INTERRUPTIBLE);
+ if (gobuf->state == BUF_STATE_DONE)
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ }
+ finish_wait(&go->frame_waitq, &wait);
+ }
+ if (gobuf->state != BUF_STATE_DONE)
+ goto unlock_and_return;
+ spin_lock_irqsave(&go->spinlock, flags);
+ deactivate_buffer(gobuf);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ frame_type_flag = get_frame_type_flag(gobuf, go->format);
+ gobuf->state = BUF_STATE_IDLE;
+ memset(buf, 0, sizeof(*buf));
+ buf->index = gobuf->index;
+ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf->bytesused = gobuf->bytesused;
+ buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
+ buf->field = V4L2_FIELD_NONE;
+ buf->timestamp = gobuf->timestamp;
+ buf->sequence = gobuf->seq;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
+ buf->length = GO7007_BUF_SIZE;
+ buf->reserved = gobuf->modet_active;
+ up(&gofh->lock);
+ return 0;
+ }
+ case VIDIOC_STREAMON:
+ {
+ unsigned int *type = arg;
+
+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ down(&gofh->lock);
+ down(&go->hw_lock);
+ if (!go->streaming) {
+ go->streaming = 1;
+ go->next_seq = 0;
+ go->active_buf = NULL;
+ if (go7007_start_encoder(go) < 0)
+ retval = -EIO;
+ else
+ retval = 0;
+ }
+ up(&go->hw_lock);
+ up(&gofh->lock);
+ return retval;
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ unsigned int *type = arg;
+
+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ down(&gofh->lock);
+ go7007_streamoff(go);
+ up(&gofh->lock);
+ return 0;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+ u32 id;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ id = ctrl->id;
+ memset(ctrl, 0, sizeof(*ctrl));
+ ctrl->id = id;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, arg);
+ return ctrl->name[0] == 0 ? -EINVAL : 0;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ struct v4l2_queryctrl query;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ memset(&query, 0, sizeof(query));
+ query.id = ctrl->id;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
+ if (query.name[0] == 0)
+ return -EINVAL;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, arg);
+ return 0;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ struct v4l2_queryctrl query;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ memset(&query, 0, sizeof(query));
+ query.id = ctrl->id;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
+ if (query.name[0] == 0)
+ return -EINVAL;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, arg);
+ return 0;
+ }
+ case VIDIOC_G_PARM:
+ {
+ struct v4l2_streamparm *parm = arg;
+ struct v4l2_fract timeperframe = {
+ .numerator = 1001 * go->fps_scale,
+ .denominator = go->sensor_framerate,
+ };
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ memset(parm, 0, sizeof(*parm));
+ parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+ parm->parm.capture.timeperframe = timeperframe;
+ return 0;
+ }
+ case VIDIOC_S_PARM:
+ {
+ struct v4l2_streamparm *parm = arg;
+ unsigned int n, d;
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (parm->parm.capture.capturemode != 0)
+ return -EINVAL;
+ n = go->sensor_framerate *
+ parm->parm.capture.timeperframe.numerator;
+ d = 1001 * parm->parm.capture.timeperframe.denominator;
+ if (n != 0 && d != 0 && n > d)
+ go->fps_scale = (n + d/2) / d;
+ else
+ go->fps_scale = 1;
+ return 0;
+ }
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *std = arg;
+
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_ENUMSTD, arg);
+ if (!std->id) /* hack to indicate EINVAL from tuner */
+ return -EINVAL;
+ } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
+ switch (std->index) {
+ case 0:
+ v4l2_video_std_construct(std,
+ V4L2_STD_NTSC, "NTSC");
+ break;
+ case 1:
+ v4l2_video_std_construct(std,
+ V4L2_STD_PAL | V4L2_STD_SECAM,
+ "PAL/SECAM");
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ if (std->index != 0)
+ return -EINVAL;
+ memset(std, 0, sizeof(*std));
+ snprintf(std->name, sizeof(std->name), "%dx%d, %dfps",
+ go->board_info->sensor_width,
+ go->board_info->sensor_height,
+ go->board_info->sensor_framerate / 1000);
+ std->frameperiod.numerator = 1001;
+ std->frameperiod.denominator =
+ go->board_info->sensor_framerate;
+ }
+ return 0;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *std = arg;
+
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_G_STD, arg);
+ } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
+ if (go->standard == GO7007_STD_NTSC)
+ *std = V4L2_STD_NTSC;
+ else
+ *std = V4L2_STD_PAL | V4L2_STD_SECAM;
+ } else
+ *std = 0;
+ return 0;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *std = arg;
+
+ if (go->streaming)
+ return -EBUSY;
+ if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
+ *std != 0)
+ return -EINVAL;
+ if (*std == 0)
+ return -EINVAL;
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_S_STD, arg);
+ if (!*std) /* hack to indicate EINVAL from tuner */
+ return -EINVAL;
+ }
+ if (*std & V4L2_STD_NTSC) {
+ go->standard = GO7007_STD_NTSC;
+ go->sensor_framerate = 30000;
+ } else if (*std & V4L2_STD_PAL) {
+ go->standard = GO7007_STD_PAL;
+ go->sensor_framerate = 25025;
+ } else if (*std & V4L2_STD_SECAM) {
+ go->standard = GO7007_STD_PAL;
+ go->sensor_framerate = 25025;
+ } else
+ return -EINVAL;
+ if (go->i2c_adapter_online)
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_S_STD, std);
+ set_capture_size(go, NULL, 0);
+ return 0;
+ }
+ case VIDIOC_QUERYSTD:
+ {
+ v4l2_std_id *std = arg;
+
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_QUERYSTD, arg);
+ } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+ *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+ else
+ *std = 0;
+ return 0;
+ }
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *inp = arg;
+ int index;
+
+ if (inp->index >= go->board_info->num_inputs)
+ return -EINVAL;
+ index = inp->index;
+ memset(inp, 0, sizeof(*inp));
+ inp->index = index;
+ strncpy(inp->name, go->board_info->inputs[index].name,
+ sizeof(inp->name));
+ /* If this board has a tuner, it will be the last input */
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ index == go->board_info->num_inputs - 1)
+ inp->type = V4L2_INPUT_TYPE_TUNER;
+ else
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ inp->audioset = 0;
+ inp->tuner = 0;
+ if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+ inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
+ V4L2_STD_SECAM;
+ else
+ inp->std = 0;
+ return 0;
+ }
+ case VIDIOC_G_INPUT:
+ {
+ int *input = arg;
+
+ *input = go->input;
+ return 0;
+ }
+ case VIDIOC_S_INPUT:
+ {
+ int *input = arg;
+
+ if (*input >= go->board_info->num_inputs)
+ return -EINVAL;
+ if (go->streaming)
+ return -EBUSY;
+ go->input = *input;
+ if (go->i2c_adapter_online) {
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
+ &go->board_info->inputs[*input].video_input);
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
+ &go->board_info->inputs[*input].audio_input);
+ }
+ return 0;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (t->index != 0)
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, arg);
+ t->index = 0;
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (t->index != 0)
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ switch (go->board_id) {
+ case GO7007_BOARDID_PX_TV402U_NA:
+ case GO7007_BOARDID_PX_TV402U_JP:
+ /* No selectable options currently */
+ if (t->audmode != V4L2_TUNER_MODE_STEREO)
+ return -EINVAL;
+ break;
+ }
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, arg);
+ return 0;
+ }
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ memset(f, 0, sizeof(*f));
+ f->type = V4L2_TUNER_ANALOG_TV;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, arg);
+ return 0;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, arg);
+ return 0;
+ }
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *cropcap = arg;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ memset(cropcap, 0, sizeof(*cropcap));
+ cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /* These specify the raw input of the sensor */
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 480;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 480;
+ break;
+ case GO7007_STD_PAL:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 576;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 576;
+ break;
+ case GO7007_STD_OTHER:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = go->board_info->sensor_width;
+ cropcap->bounds.height = go->board_info->sensor_height;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = go->board_info->sensor_width;
+ cropcap->defrect.height = go->board_info->sensor_height;
+ break;
+ }
+
+ return 0;
+ }
+ case VIDIOC_G_CROP:
+ {
+ struct v4l2_crop *crop = arg;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ memset(crop, 0, sizeof(*crop));
+ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /* These specify the raw input of the sensor */
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = 720;
+ crop->c.height = 480;
+ break;
+ case GO7007_STD_PAL:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = 720;
+ crop->c.height = 576;
+ break;
+ case GO7007_STD_OTHER:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = go->board_info->sensor_width;
+ crop->c.height = go->board_info->sensor_height;
+ break;
+ }
+
+ return 0;
+ }
+ case VIDIOC_S_CROP:
+ {
+ struct v4l2_crop *crop = arg;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ return 0;
+ }
+ case VIDIOC_G_JPEGCOMP:
+ {
+ struct v4l2_jpegcompression *params = arg;
+
+ memset(params, 0, sizeof(*params));
+ params->quality = 50; /* ?? */
+ params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
+ V4L2_JPEG_MARKER_DQT;
+
+ return 0;
+ }
+ case VIDIOC_S_JPEGCOMP:
+ {
+ struct v4l2_jpegcompression *params = arg;
+
+ if (params->quality != 50 ||
+ params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
+ V4L2_JPEG_MARKER_DQT))
+ return -EINVAL;
+ return 0;
+ }
+ /* Temporary ioctls for controlling compression characteristics */
+ case GO7007IOC_S_BITRATE:
+ {
+ int *bitrate = arg;
+
+ if (go->streaming)
+ return -EINVAL;
+ /* Upper bound is kind of arbitrary here */
+ if (*bitrate < 64000 || *bitrate > 10000000)
+ return -EINVAL;
+ go->bitrate = *bitrate;
+ return 0;
+ }
+ case GO7007IOC_G_BITRATE:
+ {
+ int *bitrate = arg;
+
+ *bitrate = go->bitrate;
+ return 0;
+ }
+ case GO7007IOC_S_COMP_PARAMS:
+ {
+ struct go7007_comp_params *comp = arg;
+
+ if (go->format == GO7007_FORMAT_MJPEG)
+ return -EINVAL;
+ if (comp->gop_size > 0)
+ go->gop_size = comp->gop_size;
+ else
+ go->gop_size = go->sensor_framerate / 1000;
+ if (go->gop_size != 15)
+ go->dvd_mode = 0;
+ /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
+ if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
+ switch (comp->aspect_ratio) {
+ case GO7007_ASPECT_RATIO_4_3_NTSC:
+ case GO7007_ASPECT_RATIO_4_3_PAL:
+ go->aspect_ratio = GO7007_RATIO_4_3;
+ break;
+ case GO7007_ASPECT_RATIO_16_9_NTSC:
+ case GO7007_ASPECT_RATIO_16_9_PAL:
+ go->aspect_ratio = GO7007_RATIO_16_9;
+ break;
+ default:
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ break;
+ }
+ }
+ if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
+ go->dvd_mode = 0;
+ go->seq_header_enable = 0;
+ } else {
+ go->seq_header_enable = 1;
+ }
+ /* fall-through */
+ }
+ case GO7007IOC_G_COMP_PARAMS:
+ {
+ struct go7007_comp_params *comp = arg;
+
+ if (go->format == GO7007_FORMAT_MJPEG)
+ return -EINVAL;
+ memset(comp, 0, sizeof(*comp));
+ comp->gop_size = go->gop_size;
+ comp->max_b_frames = go->ipb ? 2 : 0;
+ switch (go->aspect_ratio) {
+ case GO7007_RATIO_4_3:
+ if (go->standard == GO7007_STD_NTSC)
+ comp->aspect_ratio =
+ GO7007_ASPECT_RATIO_4_3_NTSC;
+ else
+ comp->aspect_ratio =
+ GO7007_ASPECT_RATIO_4_3_PAL;
+ break;
+ case GO7007_RATIO_16_9:
+ if (go->standard == GO7007_STD_NTSC)
+ comp->aspect_ratio =
+ GO7007_ASPECT_RATIO_16_9_NTSC;
+ else
+ comp->aspect_ratio =
+ GO7007_ASPECT_RATIO_16_9_PAL;
+ break;
+ default:
+ comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
+ break;
+ }
+ if (go->closed_gop)
+ comp->flags |= GO7007_COMP_CLOSED_GOP;
+ if (!go->seq_header_enable)
+ comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
+ return 0;
+ }
+ case GO7007IOC_S_MPEG_PARAMS:
+ {
+ struct go7007_mpeg_params *mpeg = arg;
+
+ if (go->format != GO7007_FORMAT_MPEG1 &&
+ go->format != GO7007_FORMAT_MPEG2 &&
+ go->format != GO7007_FORMAT_MPEG4)
+ return -EINVAL;
+
+ if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
+ go->format = GO7007_FORMAT_MPEG2;
+ go->bitrate = 9800000;
+ go->gop_size = 15;
+ go->pali = 0x48;
+ go->closed_gop = 1;
+ go->repeat_seqhead = 0;
+ go->seq_header_enable = 1;
+ go->gop_header_enable = 1;
+ go->dvd_mode = 1;
+ } else {
+ switch (mpeg->mpeg_video_standard) {
+ case GO7007_MPEG_VIDEO_MPEG1:
+ go->format = GO7007_FORMAT_MPEG1;
+ go->pali = 0;
+ break;
+ case GO7007_MPEG_VIDEO_MPEG2:
+ go->format = GO7007_FORMAT_MPEG2;
+ if (mpeg->pali >> 24 == 2)
+ go->pali = mpeg->pali & 0xff;
+ else
+ go->pali = 0x48;
+ break;
+ case GO7007_MPEG_VIDEO_MPEG4:
+ go->format = GO7007_FORMAT_MPEG4;
+ if (mpeg->pali >> 24 == 4)
+ go->pali = mpeg->pali & 0xff;
+ else
+ go->pali = 0xf5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ go->gop_header_enable =
+ mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
+ ? 0 : 1;
+ if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
+ go->repeat_seqhead = 1;
+ else
+ go->repeat_seqhead = 0;
+ go->dvd_mode = 0;
+ }
+ /* fall-through */
+ }
+ case GO7007IOC_G_MPEG_PARAMS:
+ {
+ struct go7007_mpeg_params *mpeg = arg;
+
+ memset(mpeg, 0, sizeof(*mpeg));
+ switch (go->format) {
+ case GO7007_FORMAT_MPEG1:
+ mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
+ mpeg->pali = 0;
+ break;
+ case GO7007_FORMAT_MPEG2:
+ mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
+ mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
+ break;
+ case GO7007_FORMAT_MPEG4:
+ mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
+ mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (!go->gop_header_enable)
+ mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
+ if (go->repeat_seqhead)
+ mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
+ if (go->dvd_mode)
+ mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
+ return 0;
+ }
+ case GO7007IOC_S_MD_PARAMS:
+ {
+ struct go7007_md_params *mdp = arg;
+
+ if (mdp->region > 3)
+ return -EINVAL;
+ if (mdp->trigger > 0) {
+ go->modet[mdp->region].pixel_threshold =
+ mdp->pixel_threshold >> 1;
+ go->modet[mdp->region].motion_threshold =
+ mdp->motion_threshold >> 1;
+ go->modet[mdp->region].mb_threshold =
+ mdp->trigger >> 1;
+ go->modet[mdp->region].enable = 1;
+ } else
+ go->modet[mdp->region].enable = 0;
+ /* fall-through */
+ }
+ case GO7007IOC_G_MD_PARAMS:
+ {
+ struct go7007_md_params *mdp = arg;
+ int region = mdp->region;
+
+ if (mdp->region > 3)
+ return -EINVAL;
+ memset(mdp, 0, sizeof(struct go7007_md_params));
+ mdp->region = region;
+ if (!go->modet[region].enable)
+ return 0;
+ mdp->pixel_threshold =
+ (go->modet[region].pixel_threshold << 1) + 1;
+ mdp->motion_threshold =
+ (go->modet[region].motion_threshold << 1) + 1;
+ mdp->trigger =
+ (go->modet[region].mb_threshold << 1) + 1;
+ return 0;
+ }
+ case GO7007IOC_S_MD_REGION:
+ {
+ struct go7007_md_region *region = arg;
+
+ if (region->region < 1 || region->region > 3)
+ return -EINVAL;
+ return clip_to_modet_map(go, region->region, region->clips);
+ }
+ default:
+ printk(KERN_DEBUG "go7007: unsupported ioctl %d\n", cmd);
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+
+unlock_and_return:
+ up(&gofh->lock);
+ return retval;
+}
+
+static int go7007_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct go7007_file *gofh = file->private_data;
+
+ if (gofh->go->status != STATUS_ONLINE)
+ return -EIO;
+
+ return video_usercopy(inode, file, cmd, arg, go7007_do_ioctl);
+}
+
+static ssize_t go7007_read(struct file *file, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static void go7007_vm_open(struct vm_area_struct *vma)
+{
+ struct go7007_buffer *gobuf = vma->vm_private_data;
+
+ ++gobuf->mapped;
+}
+
+static void go7007_vm_close(struct vm_area_struct *vma)
+{
+ struct go7007_buffer *gobuf = vma->vm_private_data;
+ unsigned long flags;
+
+ if (--gobuf->mapped == 0) {
+ spin_lock_irqsave(&gobuf->go->spinlock, flags);
+ deactivate_buffer(gobuf);
+ spin_unlock_irqrestore(&gobuf->go->spinlock, flags);
+ }
+}
+
+/* Copied from videobuf-dma-sg.c */
+static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct page *page;
+
+ page = alloc_page(GFP_USER | __GFP_DMA32);
+ if (!page)
+ return VM_FAULT_OOM;
+ clear_user_page(page_address(page), (unsigned long)vmf->virtual_address,
+ page);
+ vmf->page = page;
+ return 0;
+}
+
+static struct vm_operations_struct go7007_vm_ops = {
+ .open = go7007_vm_open,
+ .close = go7007_vm_close,
+ .fault = go7007_vm_fault,
+};
+
+static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct go7007_file *gofh = file->private_data;
+ unsigned int index;
+
+ if (gofh->go->status != STATUS_ONLINE)
+ return -EIO;
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL; /* only support VM_SHARED mapping */
+ if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
+ return -EINVAL; /* must map exactly one full buffer */
+ down(&gofh->lock);
+ index = vma->vm_pgoff / GO7007_BUF_PAGES;
+ if (index >= gofh->buf_count) {
+ up(&gofh->lock);
+ return -EINVAL; /* trying to map beyond requested buffers */
+ }
+ if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
+ up(&gofh->lock);
+ return -EINVAL; /* offset is not aligned on buffer boundary */
+ }
+ if (gofh->bufs[index].mapped > 0) {
+ up(&gofh->lock);
+ return -EBUSY;
+ }
+ gofh->bufs[index].mapped = 1;
+ gofh->bufs[index].user_addr = vma->vm_start;
+ vma->vm_ops = &go7007_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_flags &= ~VM_IO;
+ vma->vm_private_data = &gofh->bufs[index];
+ up(&gofh->lock);
+ return 0;
+}
+
+static unsigned int go7007_poll(struct file *file, poll_table *wait)
+{
+ struct go7007_file *gofh = file->private_data;
+ struct go7007_buffer *gobuf;
+
+ if (list_empty(&gofh->go->stream))
+ return POLLERR;
+ gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream);
+ poll_wait(file, &gofh->go->frame_waitq, wait);
+ if (gobuf->state == BUF_STATE_DONE)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static void go7007_vfl_release(struct video_device *vfd)
+{
+ struct go7007 *go = video_get_drvdata(vfd);
+
+ video_device_release(vfd);
+ if (--go->ref_count == 0)
+ kfree(go);
+}
+
+static struct file_operations go7007_fops = {
+ .owner = THIS_MODULE,
+ .open = go7007_open,
+ .release = go7007_release,
+ .ioctl = go7007_ioctl,
+ .llseek = no_llseek,
+ .read = go7007_read,
+ .mmap = go7007_mmap,
+ .poll = go7007_poll,
+};
+
+static struct video_device go7007_template = {
+ .name = "go7007",
+ .vfl_type = VID_TYPE_CAPTURE,
+ .fops = &go7007_fops,
+ .minor = -1,
+ .release = go7007_vfl_release,
+};
+
+int go7007_v4l2_init(struct go7007 *go)
+{
+ int rv;
+
+ go->video_dev = video_device_alloc();
+ if (go->video_dev == NULL)
+ return -ENOMEM;
+ memcpy(go->video_dev, &go7007_template, sizeof(go7007_template));
+ go->video_dev->parent = go->dev;
+ rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1);
+ if (rv < 0) {
+ video_device_release(go->video_dev);
+ go->video_dev = NULL;
+ return rv;
+ }
+ video_set_drvdata(go->video_dev, go);
+ ++go->ref_count;
+
+ return 0;
+}
+
+void go7007_v4l2_remove(struct go7007 *go)
+{
+ unsigned long flags;
+
+ down(&go->hw_lock);
+ if (go->streaming) {
+ go->streaming = 0;
+ go7007_stream_stop(go);
+ spin_lock_irqsave(&go->spinlock, flags);
+ abort_queued(go);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ }
+ up(&go->hw_lock);
+ if (go->video_dev)
+ video_unregister_device(go->video_dev);
+}
diff --git a/drivers/staging/go7007/go7007.h b/drivers/staging/go7007/go7007.h
new file mode 100644
index 00000000000..7399c915a93
--- /dev/null
+++ b/drivers/staging/go7007/go7007.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and the associated README documentation file (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* DEPRECATED -- use V4L2_PIX_FMT_MPEG and then call GO7007IOC_S_MPEG_PARAMS
+ * to select between MPEG1, MPEG2, and MPEG4 */
+#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG4 */
+
+/* These will be replaced with a better interface
+ * soon, so don't get too attached to them */
+#define GO7007IOC_S_BITRATE _IOW('V', BASE_VIDIOC_PRIVATE + 0, int)
+#define GO7007IOC_G_BITRATE _IOR('V', BASE_VIDIOC_PRIVATE + 1, int)
+
+enum go7007_aspect_ratio {
+ GO7007_ASPECT_RATIO_1_1 = 0,
+ GO7007_ASPECT_RATIO_4_3_NTSC = 1,
+ GO7007_ASPECT_RATIO_4_3_PAL = 2,
+ GO7007_ASPECT_RATIO_16_9_NTSC = 3,
+ GO7007_ASPECT_RATIO_16_9_PAL = 4,
+};
+
+/* Used to set generic compression parameters */
+struct go7007_comp_params {
+ __u32 gop_size;
+ __u32 max_b_frames;
+ enum go7007_aspect_ratio aspect_ratio;
+ __u32 flags;
+ __u32 reserved[8];
+};
+
+#define GO7007_COMP_CLOSED_GOP 0x00000001
+#define GO7007_COMP_OMIT_SEQ_HEADER 0x00000002
+
+enum go7007_mpeg_video_standard {
+ GO7007_MPEG_VIDEO_MPEG1 = 0,
+ GO7007_MPEG_VIDEO_MPEG2 = 1,
+ GO7007_MPEG_VIDEO_MPEG4 = 2,
+};
+
+/* Used to set parameters for V4L2_PIX_FMT_MPEG format */
+struct go7007_mpeg_params {
+ enum go7007_mpeg_video_standard mpeg_video_standard;
+ __u32 flags;
+ __u32 pali;
+ __u32 reserved[8];
+};
+
+#define GO7007_MPEG_FORCE_DVD_MODE 0x00000001
+#define GO7007_MPEG_OMIT_GOP_HEADER 0x00000002
+#define GO7007_MPEG_REPEAT_SEQHEADER 0x00000004
+
+#define GO7007_MPEG_PROFILE(format, pali) (((format)<<24)|(pali))
+
+#define GO7007_MPEG2_PROFILE_MAIN_MAIN GO7007_MPEG_PROFILE(2, 0x48)
+
+#define GO7007_MPEG4_PROFILE_S_L0 GO7007_MPEG_PROFILE(4, 0x08)
+#define GO7007_MPEG4_PROFILE_S_L1 GO7007_MPEG_PROFILE(4, 0x01)
+#define GO7007_MPEG4_PROFILE_S_L2 GO7007_MPEG_PROFILE(4, 0x02)
+#define GO7007_MPEG4_PROFILE_S_L3 GO7007_MPEG_PROFILE(4, 0x03)
+#define GO7007_MPEG4_PROFILE_ARTS_L1 GO7007_MPEG_PROFILE(4, 0x91)
+#define GO7007_MPEG4_PROFILE_ARTS_L2 GO7007_MPEG_PROFILE(4, 0x92)
+#define GO7007_MPEG4_PROFILE_ARTS_L3 GO7007_MPEG_PROFILE(4, 0x93)
+#define GO7007_MPEG4_PROFILE_ARTS_L4 GO7007_MPEG_PROFILE(4, 0x94)
+#define GO7007_MPEG4_PROFILE_AS_L0 GO7007_MPEG_PROFILE(4, 0xf0)
+#define GO7007_MPEG4_PROFILE_AS_L1 GO7007_MPEG_PROFILE(4, 0xf1)
+#define GO7007_MPEG4_PROFILE_AS_L2 GO7007_MPEG_PROFILE(4, 0xf2)
+#define GO7007_MPEG4_PROFILE_AS_L3 GO7007_MPEG_PROFILE(4, 0xf3)
+#define GO7007_MPEG4_PROFILE_AS_L4 GO7007_MPEG_PROFILE(4, 0xf4)
+#define GO7007_MPEG4_PROFILE_AS_L5 GO7007_MPEG_PROFILE(4, 0xf5)
+
+struct go7007_md_params {
+ __u16 region;
+ __u16 trigger;
+ __u16 pixel_threshold;
+ __u16 motion_threshold;
+ __u32 reserved[8];
+};
+
+struct go7007_md_region {
+ __u16 region;
+ __u16 flags;
+ struct v4l2_clip *clips;
+ __u32 reserved[8];
+};
+
+#define GO7007IOC_S_MPEG_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 2, \
+ struct go7007_mpeg_params)
+#define GO7007IOC_G_MPEG_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 3, \
+ struct go7007_mpeg_params)
+#define GO7007IOC_S_COMP_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 4, \
+ struct go7007_comp_params)
+#define GO7007IOC_G_COMP_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 5, \
+ struct go7007_comp_params)
+#define GO7007IOC_S_MD_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 6, \
+ struct go7007_md_params)
+#define GO7007IOC_G_MD_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 7, \
+ struct go7007_md_params)
+#define GO7007IOC_S_MD_REGION _IOW('V', BASE_VIDIOC_PRIVATE + 8, \
+ struct go7007_md_region)
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c
new file mode 100644
index 00000000000..c4a6d8ef907
--- /dev/null
+++ b/drivers/staging/go7007/saa7134-go7007.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <asm/byteorder.h>
+#include <media/audiochip.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+#include "go7007-priv.h"
+
+#define GO7007_HPI_DEBUG
+
+enum hpi_address {
+ HPI_ADDR_VIDEO_BUFFER = 0xe4,
+ HPI_ADDR_INIT_BUFFER = 0xea,
+ HPI_ADDR_INTR_RET_VALUE = 0xee,
+ HPI_ADDR_INTR_RET_DATA = 0xec,
+ HPI_ADDR_INTR_STATUS = 0xf4,
+ HPI_ADDR_INTR_WR_PARAM = 0xf6,
+ HPI_ADDR_INTR_WR_INDEX = 0xf8,
+};
+
+enum gpio_command {
+ GPIO_COMMAND_RESET = 0x00, /* 000b */
+ GPIO_COMMAND_REQ1 = 0x04, /* 001b */
+ GPIO_COMMAND_WRITE = 0x20, /* 010b */
+ GPIO_COMMAND_REQ2 = 0x24, /* 011b */
+ GPIO_COMMAND_READ = 0x80, /* 100b */
+ GPIO_COMMAND_VIDEO = 0x84, /* 101b */
+ GPIO_COMMAND_IDLE = 0xA0, /* 110b */
+ GPIO_COMMAND_ADDR = 0xA4, /* 111b */
+};
+
+struct saa7134_go7007 {
+ struct saa7134_dev *dev;
+ u8 *top;
+ u8 *bottom;
+ dma_addr_t top_dma;
+ dma_addr_t bottom_dma;
+};
+
+static struct go7007_board_info board_voyager = {
+ .firmware = "go7007tv.bin",
+ .flags = 0,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_VALID_ENABLE |
+ GO7007_SENSOR_TV |
+ GO7007_SENSOR_VBI,
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_WORD_16,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .num_inputs = 1,
+ .inputs = {
+ {
+ .name = "SAA7134",
+ },
+ },
+};
+
+/********************* Driver for GPIO HPI interface *********************/
+
+static int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data)
+{
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
+
+ /* Write HPI address */
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ /* Write low byte */
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ /* Write high byte */
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ return 0;
+}
+
+static int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data)
+{
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
+
+ /* Write HPI address */
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
+
+ /* Read low byte */
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ *data = saa_readb(SAA7134_GPIO_GPSTATUS0);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ /* Read high byte */
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ *data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8;
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+
+ return 0;
+}
+
+static int saa7134_go7007_interface_reset(struct go7007 *go)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+ u32 status;
+ u16 intr_val, intr_data;
+ int count = 20;
+
+ saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */
+ saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4);
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
+
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET);
+ msleep(1);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
+ msleep(10);
+
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+ status = saa_readb(SAA7134_GPIO_GPSTATUS2);
+ /*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */
+
+ /* enter command mode...(?) */
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
+
+ do {
+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+ status = saa_readb(SAA7134_GPIO_GPSTATUS2);
+ /*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
+ } while (--count > 0);
+
+ /* Wait for an interrupt to indicate successful hardware reset */
+ if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+ (intr_val & ~0x1) != 0x55aa) {
+ printk(KERN_ERR
+ "saa7134-go7007: unable to reset the GO7007\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+ int i;
+ u16 status_reg;
+
+#ifdef GO7007_HPI_DEBUG
+ printk(KERN_DEBUG
+ "saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
+#endif
+
+ for (i = 0; i < 100; ++i) {
+ gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
+ if (!(status_reg & 0x0010))
+ break;
+ msleep(10);
+ }
+ if (i == 100) {
+ printk(KERN_ERR
+ "saa7134-go7007: device is hung, status reg = 0x%04x\n",
+ status_reg);
+ return -1;
+ }
+ gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data);
+ gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr);
+
+ return 0;
+}
+
+static int saa7134_go7007_read_interrupt(struct go7007 *go)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+
+ /* XXX we need to wait if there is no interrupt available */
+ go->interrupt_available = 1;
+ gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value);
+ gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data);
+#ifdef GO7007_HPI_DEBUG
+ printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n",
+ go->interrupt_value, go->interrupt_data);
+#endif
+ return 0;
+}
+
+static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
+ unsigned long status)
+{
+ struct go7007 *go = video_get_drvdata(dev->empress_dev);
+ struct saa7134_go7007 *saa = go->hpi_context;
+
+ if (!go->streaming)
+ return;
+ if (0 != (status & 0x000f0000))
+ printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
+ (status >> 16) & 0x0f);
+ if (status & 0x100000) {
+ dma_sync_single(&dev->pci->dev,
+ saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE);
+ go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE);
+ saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
+ } else {
+ dma_sync_single(&dev->pci->dev,
+ saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE);
+ go7007_parse_video_stream(go, saa->top, PAGE_SIZE);
+ saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
+ }
+}
+
+static int saa7134_go7007_stream_start(struct go7007 *go)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+
+ saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top),
+ 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (!saa->top_dma)
+ return -ENOMEM;
+ saa->bottom_dma = dma_map_page(&dev->pci->dev,
+ virt_to_page(saa->bottom),
+ 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (!saa->bottom_dma) {
+ dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ return -ENOMEM;
+ }
+
+ saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000);
+ saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200);
+
+ /* Set HPI interface for video */
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
+
+ /* Enable TS interface */
+ saa_writeb(SAA7134_TS_PARALLEL, 0xe6);
+
+ /* Reset TS interface */
+ saa_setb(SAA7134_TS_SERIAL1, 0x01);
+ saa_clearb(SAA7134_TS_SERIAL1, 0x01);
+
+ /* Set up transfer block size */
+ saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1);
+ saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1);
+ saa_writeb(SAA7134_TS_DMA1, 0);
+ saa_writeb(SAA7134_TS_DMA2, 0);
+
+ /* Enable video streaming mode */
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO);
+
+ saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
+ saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
+ saa_writel(SAA7134_RS_PITCH(5), 128);
+ saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX);
+
+ /* Enable TS FIFO */
+ saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
+
+ /* Enable DMA IRQ */
+ saa_setl(SAA7134_IRQ1,
+ SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
+
+ return 0;
+}
+
+static int saa7134_go7007_stream_stop(struct go7007 *go)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+
+ /* Shut down TS FIFO */
+ saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
+
+ /* Disable DMA IRQ */
+ saa_clearl(SAA7134_IRQ1,
+ SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
+
+ /* Disable TS interface */
+ saa_clearb(SAA7134_TS_PARALLEL, 0x80);
+
+ dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+
+ return 0;
+}
+
+static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+ u16 status_reg;
+ int i;
+
+#ifdef GO7007_HPI_DEBUG
+ printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer "
+ "sending %d bytes\n", len);
+#endif
+
+ while (len > 0) {
+ i = len > 64 ? 64 : len;
+ saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+ while (i-- > 0) {
+ saa_writeb(SAA7134_GPIO_GPSTATUS0, *data);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
+ saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
+ ++data;
+ --len;
+ }
+ for (i = 0; i < 100; ++i) {
+ gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
+ if (!(status_reg & 0x0002))
+ break;
+ }
+ if (i == 100) {
+ printk(KERN_ERR "saa7134-go7007: device is hung, "
+ "status reg = 0x%04x\n", status_reg);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
+ .interface_reset = saa7134_go7007_interface_reset,
+ .write_interrupt = saa7134_go7007_write_interrupt,
+ .read_interrupt = saa7134_go7007_read_interrupt,
+ .stream_start = saa7134_go7007_stream_start,
+ .stream_stop = saa7134_go7007_stream_stop,
+ .send_firmware = saa7134_go7007_send_firmware,
+};
+
+/********************* Add/remove functions *********************/
+
+static int saa7134_go7007_init(struct saa7134_dev *dev)
+{
+ struct go7007 *go;
+ struct saa7134_go7007 *saa;
+
+ printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
+
+ saa = kmalloc(sizeof(struct saa7134_go7007), GFP_KERNEL);
+ if (saa == NULL)
+ return -ENOMEM;
+ memset(saa, 0, sizeof(struct saa7134_go7007));
+
+ /* Allocate a couple pages for receiving the compressed stream */
+ saa->top = (u8 *)get_zeroed_page(GFP_KERNEL);
+ if (!saa->top)
+ goto allocfail;
+ saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL);
+ if (!saa->bottom)
+ goto allocfail;
+
+ go = go7007_alloc(&board_voyager, &dev->pci->dev);
+ if (go == NULL)
+ goto allocfail;
+ go->board_id = GO7007_BOARDID_PCI_VOYAGER;
+ strncpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
+ go->hpi_ops = &saa7134_go7007_hpi_ops;
+ go->hpi_context = saa;
+ saa->dev = dev;
+
+ /* Boot the GO7007 */
+ if (go7007_boot_encoder(go, go->board_info->flags &
+ GO7007_BOARD_USE_ONBOARD_I2C) < 0)
+ goto initfail;
+
+ /* Do any final GO7007 initialization, then register the
+ * V4L2 and ALSA interfaces */
+ if (go7007_register_encoder(go) < 0)
+ goto initfail;
+ dev->empress_dev = go->video_dev;
+ video_set_drvdata(dev->empress_dev, go);
+
+ go->status = STATUS_ONLINE;
+ return 0;
+
+initfail:
+ go->status = STATUS_SHUTDOWN;
+ return 0;
+
+allocfail:
+ if (saa->top)
+ free_page((unsigned long)saa->top);
+ if (saa->bottom)
+ free_page((unsigned long)saa->bottom);
+ kfree(saa);
+ return -ENOMEM;
+}
+
+static int saa7134_go7007_fini(struct saa7134_dev *dev)
+{
+ struct go7007 *go;
+ struct saa7134_go7007 *saa;
+
+ if (NULL == dev->empress_dev)
+ return 0;
+
+ go = video_get_drvdata(dev->empress_dev);
+ saa = go->hpi_context;
+ go->status = STATUS_SHUTDOWN;
+ free_page((unsigned long)saa->top);
+ free_page((unsigned long)saa->bottom);
+ kfree(saa);
+ go7007_remove(go);
+ dev->empress_dev = NULL;
+
+ return 0;
+}
+
+static struct saa7134_mpeg_ops saa7134_go7007_ops = {
+ .type = SAA7134_MPEG_GO7007,
+ .init = saa7134_go7007_init,
+ .fini = saa7134_go7007_fini,
+ .irq_ts_done = saa7134_go7007_irq_ts_done,
+};
+
+static int __init saa7134_go7007_mod_init(void)
+{
+ return saa7134_ts_register(&saa7134_go7007_ops);
+}
+
+static void __exit saa7134_go7007_mod_cleanup(void)
+{
+ saa7134_ts_unregister(&saa7134_go7007_ops);
+}
+
+module_init(saa7134_go7007_mod_init);
+module_exit(saa7134_go7007_mod_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c
new file mode 100644
index 00000000000..382740c405f
--- /dev/null
+++ b/drivers/staging/go7007/snd-go7007.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/i2c.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+#include "go7007-priv.h"
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+module_param_array(id, charp, NULL, 0444);
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the go7007 audio driver");
+MODULE_PARM_DESC(id, "ID string for the go7007 audio driver");
+MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver");
+
+struct go7007_snd {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
+ spinlock_t lock;
+ int w_idx;
+ int hw_ptr;
+ int avail;
+ int capturing;
+};
+
+static struct snd_pcm_hardware go7007_snd_capture_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 4096,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 32,
+};
+
+static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length)
+{
+ struct go7007_snd *gosnd = go->snd_context;
+ struct snd_pcm_runtime *runtime = gosnd->substream->runtime;
+ int frames = bytes_to_frames(runtime, length);
+
+ spin_lock(&gosnd->lock);
+ gosnd->hw_ptr += frames;
+ if (gosnd->hw_ptr >= runtime->buffer_size)
+ gosnd->hw_ptr -= runtime->buffer_size;
+ gosnd->avail += frames;
+ spin_unlock(&gosnd->lock);
+ if (gosnd->w_idx + length > runtime->dma_bytes) {
+ int cpy = runtime->dma_bytes - gosnd->w_idx;
+
+ memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy);
+ length -= cpy;
+ buf += cpy;
+ gosnd->w_idx = 0;
+ }
+ memcpy(runtime->dma_area + gosnd->w_idx, buf, length);
+ gosnd->w_idx += length;
+ spin_lock(&gosnd->lock);
+ if (gosnd->avail < runtime->period_size) {
+ spin_unlock(&gosnd->lock);
+ return;
+ }
+ gosnd->avail -= runtime->period_size;
+ spin_unlock(&gosnd->lock);
+ if (gosnd->capturing)
+ snd_pcm_period_elapsed(gosnd->substream);
+}
+
+static int go7007_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+ unsigned int bytes;
+
+ bytes = params_buffer_bytes(hw_params);
+ if (substream->runtime->dma_bytes > 0)
+ vfree(substream->runtime->dma_area);
+ substream->runtime->dma_bytes = 0;
+ substream->runtime->dma_area = vmalloc(bytes);
+ if (substream->runtime->dma_area == NULL)
+ return -ENOMEM;
+ substream->runtime->dma_bytes = bytes;
+ go->audio_deliver = parse_audio_stream_data;
+ return 0;
+}
+
+static int go7007_snd_hw_free(struct snd_pcm_substream *substream)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+
+ go->audio_deliver = NULL;
+ if (substream->runtime->dma_bytes > 0)
+ vfree(substream->runtime->dma_area);
+ substream->runtime->dma_bytes = 0;
+ return 0;
+}
+
+static int go7007_snd_capture_open(struct snd_pcm_substream *substream)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+ struct go7007_snd *gosnd = go->snd_context;
+ unsigned long flags;
+ int r;
+
+ spin_lock_irqsave(&gosnd->lock, flags);
+ if (gosnd->substream == NULL) {
+ gosnd->substream = substream;
+ substream->runtime->hw = go7007_snd_capture_hw;
+ r = 0;
+ } else
+ r = -EBUSY;
+ spin_unlock_irqrestore(&gosnd->lock, flags);
+ return r;
+}
+
+static int go7007_snd_capture_close(struct snd_pcm_substream *substream)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+ struct go7007_snd *gosnd = go->snd_context;
+
+ gosnd->substream = NULL;
+ return 0;
+}
+
+static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+ struct go7007_snd *gosnd = go->snd_context;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* Just set a flag to indicate we should signal ALSA when
+ * sound comes in */
+ gosnd->capturing = 1;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
+ gosnd->capturing = 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct go7007 *go = snd_pcm_substream_chip(substream);
+ struct go7007_snd *gosnd = go->snd_context;
+
+ return gosnd->hw_ptr;
+}
+
+static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+{
+ return vmalloc_to_page(substream->runtime->dma_area + offset);
+}
+
+static struct snd_pcm_ops go7007_snd_capture_ops = {
+ .open = go7007_snd_capture_open,
+ .close = go7007_snd_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = go7007_snd_hw_params,
+ .hw_free = go7007_snd_hw_free,
+ .prepare = go7007_snd_pcm_prepare,
+ .trigger = go7007_snd_pcm_trigger,
+ .pointer = go7007_snd_pcm_pointer,
+ .page = go7007_snd_pcm_page,
+};
+
+static int go7007_snd_free(struct snd_device *device)
+{
+ struct go7007 *go = device->device_data;
+
+ kfree(go->snd_context);
+ go->snd_context = NULL;
+ if (--go->ref_count == 0)
+ kfree(go);
+ return 0;
+}
+
+static struct snd_device_ops go7007_snd_device_ops = {
+ .dev_free = go7007_snd_free,
+};
+
+int go7007_snd_init(struct go7007 *go)
+{
+ static int dev;
+ struct go7007_snd *gosnd;
+ int ret = 0;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+ gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL);
+ if (gosnd == NULL)
+ return -ENOMEM;
+ spin_lock_init(&gosnd->lock);
+ gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
+ gosnd->capturing = 0;
+ gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (gosnd->card == NULL) {
+ kfree(gosnd);
+ return -ENOMEM;
+ }
+ ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
+ &go7007_snd_device_ops);
+ if (ret < 0) {
+ kfree(gosnd);
+ return ret;
+ }
+ snd_card_set_dev(gosnd->card, go->dev);
+ ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
+ if (ret < 0) {
+ snd_card_free(gosnd->card);
+ kfree(gosnd);
+ return ret;
+ }
+ strncpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
+ strncpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
+ strncpy(gosnd->card->longname, gosnd->card->shortname,
+ sizeof(gosnd->card->longname));
+
+ gosnd->pcm->private_data = go;
+ snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &go7007_snd_capture_ops);
+
+ ret = snd_card_register(gosnd->card);
+ if (ret < 0) {
+ snd_card_free(gosnd->card);
+ kfree(gosnd);
+ return ret;
+ }
+
+ gosnd->substream = NULL;
+ go->snd_context = gosnd;
+ ++dev;
+ ++go->ref_count;
+
+ return 0;
+}
+EXPORT_SYMBOL(go7007_snd_init);
+
+int go7007_snd_remove(struct go7007 *go)
+{
+ struct go7007_snd *gosnd = go->snd_context;
+
+ snd_card_disconnect(gosnd->card);
+ snd_card_free_when_closed(gosnd->card);
+ return 0;
+}
+EXPORT_SYMBOL(go7007_snd_remove);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-i2c.h b/drivers/staging/go7007/wis-i2c.h
new file mode 100644
index 00000000000..993f658ad73
--- /dev/null
+++ b/drivers/staging/go7007/wis-i2c.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/* Temporary I2C IDs -- these need to be replaced with real registered IDs */
+#define I2C_DRIVERID_WIS_SAA7115 0xf0f0
+#define I2C_DRIVERID_WIS_UDA1342 0xf0f1
+#define I2C_DRIVERID_WIS_SONY_TUNER 0xf0f2
+#define I2C_DRIVERID_WIS_TW9903 0xf0f3
+#define I2C_DRIVERID_WIS_SAA7113 0xf0f4
+#define I2C_DRIVERID_WIS_OV7640 0xf0f5
+#define I2C_DRIVERID_WIS_TW2804 0xf0f6
+#define I2C_ALGO_GO7007 0xf00000
+#define I2C_ALGO_GO7007_USB 0xf10000
+
+/* Flag to indicate that the client needs to be accessed with SCCB semantics */
+/* We re-use the I2C_M_TEN value so the flag passes through the masks in the
+ * core I2C code. Major kludge, but the I2C layer ain't exactly flexible. */
+#define I2C_CLIENT_SCCB 0x10
+
+typedef int (*found_proc) (struct i2c_adapter *, int, int);
+int wis_i2c_add_driver(unsigned int id, found_proc found_proc);
+void wis_i2c_del_driver(found_proc found_proc);
+
+int wis_i2c_probe_device(struct i2c_adapter *adapter,
+ unsigned int id, int addr);
+
+/* Definitions for new video decoder commands */
+
+struct video_decoder_resolution {
+ unsigned int width;
+ unsigned int height;
+};
+
+#define DECODER_SET_RESOLUTION _IOW('d', 200, struct video_decoder_resolution)
+#define DECODER_SET_CHANNEL _IOW('d', 201, int)
+
+/* Sony tuner types */
+
+#define TUNER_SONY_BTF_PG472Z 200
+#define TUNER_SONY_BTF_PK467Z 201
+#define TUNER_SONY_BTF_PB463Z 202
diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c
new file mode 100644
index 00000000000..f5f11e927af
--- /dev/null
+++ b/drivers/staging/go7007/wis-ov7640.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+
+#include "wis-i2c.h"
+
+struct wis_ov7640 {
+ int brightness;
+ int contrast;
+ int saturation;
+ int hue;
+};
+
+static u8 initial_registers[] =
+{
+ 0x12, 0x80,
+ 0x12, 0x54,
+ 0x14, 0x24,
+ 0x15, 0x01,
+ 0x28, 0x20,
+ 0x75, 0x82,
+ 0xFF, 0xFF, /* Terminator (reg 0xFF is unused) */
+};
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+ int i;
+
+ for (i = 0; regs[i] != 0xFF; i += 2)
+ if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+ return -1;
+ return 0;
+}
+
+static struct i2c_driver wis_ov7640_driver;
+
+static struct i2c_client wis_ov7640_client_templ = {
+ .name = "OV7640 (WIS)",
+ .driver = &wis_ov7640_driver,
+};
+
+static int wis_ov7640_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_ov7640_client_templ,
+ sizeof(wis_ov7640_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+ client->flags = I2C_CLIENT_SCCB;
+
+ printk(KERN_DEBUG
+ "wis-ov7640: initializing OV7640 at address %d on %s\n",
+ addr, adapter->name);
+
+ if (write_regs(client, initial_registers) < 0) {
+ printk(KERN_ERR "wis-ov7640: error initializing OV7640\n");
+ kfree(client);
+ return 0;
+ }
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_ov7640_detach(struct i2c_client *client)
+{
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ return 0;
+}
+
+static struct i2c_driver wis_ov7640_driver = {
+ .driver = {
+ .name = "WIS OV7640 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_OV7640,
+ .detach_client = wis_ov7640_detach,
+};
+
+static int __init wis_ov7640_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_ov7640_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_ov7640_driver.id, wis_ov7640_detect);
+}
+
+static void __exit wis_ov7640_cleanup(void)
+{
+ wis_i2c_del_driver(wis_ov7640_detect);
+ i2c_del_driver(&wis_ov7640_driver);
+}
+
+module_init(wis_ov7640_init);
+module_exit(wis_ov7640_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
new file mode 100644
index 00000000000..c1aff1b923a
--- /dev/null
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+
+#include "wis-i2c.h"
+
+struct wis_saa7113 {
+ int norm;
+ int brightness;
+ int contrast;
+ int saturation;
+ int hue;
+};
+
+static u8 initial_registers[] =
+{
+ 0x01, 0x08,
+ 0x02, 0xc0,
+ 0x03, 0x33,
+ 0x04, 0x00,
+ 0x05, 0x00,
+ 0x06, 0xe9,
+ 0x07, 0x0d,
+ 0x08, 0xd8,
+ 0x09, 0x40,
+ 0x0a, 0x80,
+ 0x0b, 0x47,
+ 0x0c, 0x40,
+ 0x0d, 0x00,
+ 0x0e, 0x01,
+ 0x0f, 0x2a,
+ 0x10, 0x40,
+ 0x11, 0x0c,
+ 0x12, 0xfe,
+ 0x13, 0x00,
+ 0x14, 0x00,
+ 0x15, 0x04,
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1b, 0x00,
+ 0x1c, 0x00,
+ 0x1d, 0x00,
+ 0x1e, 0x00,
+ 0x1f, 0xc8,
+ 0x40, 0x00,
+ 0x41, 0xff,
+ 0x42, 0xff,
+ 0x43, 0xff,
+ 0x44, 0xff,
+ 0x45, 0xff,
+ 0x46, 0xff,
+ 0x47, 0xff,
+ 0x48, 0xff,
+ 0x49, 0xff,
+ 0x4a, 0xff,
+ 0x4b, 0xff,
+ 0x4c, 0xff,
+ 0x4d, 0xff,
+ 0x4e, 0xff,
+ 0x4f, 0xff,
+ 0x50, 0xff,
+ 0x51, 0xff,
+ 0x52, 0xff,
+ 0x53, 0xff,
+ 0x54, 0xff,
+ 0x55, 0xff,
+ 0x56, 0xff,
+ 0x57, 0xff,
+ 0x58, 0x00,
+ 0x59, 0x54,
+ 0x5a, 0x07,
+ 0x5b, 0x83,
+ 0x5c, 0x00,
+ 0x5d, 0x00,
+ 0x5e, 0x00,
+ 0x5f, 0x00,
+ 0x60, 0x00,
+ 0x61, 0x00,
+ 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+ int i;
+
+ for (i = 0; regs[i] != 0x00; i += 2)
+ if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+ return -1;
+ return 0;
+}
+
+static int wis_saa7113_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct wis_saa7113 *dec = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_S_INPUT:
+ {
+ int *input = arg;
+
+ i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
+ i2c_smbus_write_byte_data(client, 0x09,
+ *input < 6 ? 0x40 : 0x80);
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *input = arg;
+ dec->norm = *input;
+ if (dec->norm & V4L2_STD_NTSC) {
+ write_reg(client, 0x0e, 0x01);
+ write_reg(client, 0x10, 0x40);
+ } else if (dec->norm & V4L2_STD_PAL) {
+ write_reg(client, 0x0e, 0x01);
+ write_reg(client, 0x10, 0x48);
+ } else if (dec->norm * V4L2_STD_SECAM) {
+ write_reg(client, 0x0e, 0x50);
+ write_reg(client, 0x10, 0x48);
+ }
+ break;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 71;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 64;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
+ ctrl->minimum = -128;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 0;
+ ctrl->flags = 0;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value > 255)
+ dec->brightness = 255;
+ else if (ctrl->value < 0)
+ dec->brightness = 0;
+ else
+ dec->brightness = ctrl->value;
+ write_reg(client, 0x0a, dec->brightness);
+ break;
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value > 127)
+ dec->contrast = 127;
+ else if (ctrl->value < 0)
+ dec->contrast = 0;
+ else
+ dec->contrast = ctrl->value;
+ write_reg(client, 0x0b, dec->contrast);
+ break;
+ case V4L2_CID_SATURATION:
+ if (ctrl->value > 127)
+ dec->saturation = 127;
+ else if (ctrl->value < 0)
+ dec->saturation = 0;
+ else
+ dec->saturation = ctrl->value;
+ write_reg(client, 0x0c, dec->saturation);
+ break;
+ case V4L2_CID_HUE:
+ if (ctrl->value > 127)
+ dec->hue = 127;
+ else if (ctrl->value < -128)
+ dec->hue = -128;
+ else
+ dec->hue = ctrl->value;
+ write_reg(client, 0x0d, dec->hue);
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = dec->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = dec->contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->value = dec->saturation;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->value = dec->hue;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_saa7113_driver;
+
+static struct i2c_client wis_saa7113_client_templ = {
+ .name = "SAA7113 (WIS)",
+ .driver = &wis_saa7113_driver,
+};
+
+static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+ struct wis_saa7113 *dec;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_saa7113_client_templ,
+ sizeof(wis_saa7113_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
+ if (dec == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ dec->norm = V4L2_STD_NTSC;
+ dec->brightness = 128;
+ dec->contrast = 71;
+ dec->saturation = 64;
+ dec->hue = 0;
+ i2c_set_clientdata(client, dec);
+
+ printk(KERN_DEBUG
+ "wis-saa7113: initializing SAA7113 at address %d on %s\n",
+ addr, adapter->name);
+
+ if (write_regs(client, initial_registers) < 0) {
+ printk(KERN_ERR
+ "wis-saa7113: error initializing SAA7113\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_saa7113_detach(struct i2c_client *client)
+{
+ struct wis_saa7113 *dec = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ kfree(dec);
+ return 0;
+}
+
+static struct i2c_driver wis_saa7113_driver = {
+ .driver = {
+ .name = "WIS SAA7113 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_SAA7113,
+ .detach_client = wis_saa7113_detach,
+ .command = wis_saa7113_command,
+};
+
+static int __init wis_saa7113_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_saa7113_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_saa7113_driver.id, wis_saa7113_detect);
+}
+
+static void __exit wis_saa7113_cleanup(void)
+{
+ wis_i2c_del_driver(wis_saa7113_detect);
+ i2c_del_driver(&wis_saa7113_driver);
+}
+
+module_init(wis_saa7113_init);
+module_exit(wis_saa7113_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
new file mode 100644
index 00000000000..5c94c883b31
--- /dev/null
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+
+#include "wis-i2c.h"
+
+struct wis_saa7115 {
+ int norm;
+ int brightness;
+ int contrast;
+ int saturation;
+ int hue;
+};
+
+static u8 initial_registers[] =
+{
+ 0x01, 0x08,
+ 0x02, 0xc0,
+ 0x03, 0x20,
+ 0x04, 0x80,
+ 0x05, 0x80,
+ 0x06, 0xeb,
+ 0x07, 0xe0,
+ 0x08, 0xf0, /* always toggle FID */
+ 0x09, 0x40,
+ 0x0a, 0x80,
+ 0x0b, 0x40,
+ 0x0c, 0x40,
+ 0x0d, 0x00,
+ 0x0e, 0x03,
+ 0x0f, 0x2a,
+ 0x10, 0x0e,
+ 0x11, 0x00,
+ 0x12, 0x8d,
+ 0x13, 0x00,
+ 0x14, 0x00,
+ 0x15, 0x11,
+ 0x16, 0x01,
+ 0x17, 0xda,
+ 0x18, 0x40,
+ 0x19, 0x80,
+ 0x1a, 0x00,
+ 0x1b, 0x42,
+ 0x1c, 0xa9,
+ 0x30, 0x66,
+ 0x31, 0x90,
+ 0x32, 0x01,
+ 0x34, 0x00,
+ 0x35, 0x00,
+ 0x36, 0x20,
+ 0x38, 0x03,
+ 0x39, 0x20,
+ 0x3a, 0x88,
+ 0x40, 0x00,
+ 0x41, 0xff,
+ 0x42, 0xff,
+ 0x43, 0xff,
+ 0x44, 0xff,
+ 0x45, 0xff,
+ 0x46, 0xff,
+ 0x47, 0xff,
+ 0x48, 0xff,
+ 0x49, 0xff,
+ 0x4a, 0xff,
+ 0x4b, 0xff,
+ 0x4c, 0xff,
+ 0x4d, 0xff,
+ 0x4e, 0xff,
+ 0x4f, 0xff,
+ 0x50, 0xff,
+ 0x51, 0xff,
+ 0x52, 0xff,
+ 0x53, 0xff,
+ 0x54, 0xf4 /*0xff*/,
+ 0x55, 0xff,
+ 0x56, 0xff,
+ 0x57, 0xff,
+ 0x58, 0x40,
+ 0x59, 0x47,
+ 0x5a, 0x06 /*0x03*/,
+ 0x5b, 0x83,
+ 0x5d, 0x06,
+ 0x5e, 0x00,
+ 0x80, 0x30, /* window defined scaler operation, task A and B enabled */
+ 0x81, 0x03, /* use scaler datapath generated V */
+ 0x83, 0x00,
+ 0x84, 0x00,
+ 0x85, 0x00,
+ 0x86, 0x45,
+ 0x87, 0x31,
+ 0x88, 0xc0,
+ 0x90, 0x02, /* task A process top field */
+ 0x91, 0x08,
+ 0x92, 0x09,
+ 0x93, 0x80,
+ 0x94, 0x06,
+ 0x95, 0x00,
+ 0x96, 0xc0,
+ 0x97, 0x02,
+ 0x98, 0x12,
+ 0x99, 0x00,
+ 0x9a, 0xf2,
+ 0x9b, 0x00,
+ 0x9c, 0xd0,
+ 0x9d, 0x02,
+ 0x9e, 0xf2,
+ 0x9f, 0x00,
+ 0xa0, 0x01,
+ 0xa1, 0x01,
+ 0xa2, 0x01,
+ 0xa4, 0x80,
+ 0xa5, 0x40,
+ 0xa6, 0x40,
+ 0xa8, 0x00,
+ 0xa9, 0x04,
+ 0xaa, 0x00,
+ 0xac, 0x00,
+ 0xad, 0x02,
+ 0xae, 0x00,
+ 0xb0, 0x00,
+ 0xb1, 0x04,
+ 0xb2, 0x00,
+ 0xb3, 0x04,
+ 0xb4, 0x00,
+ 0xb8, 0x00,
+ 0xbc, 0x00,
+ 0xc0, 0x03, /* task B process bottom field */
+ 0xc1, 0x08,
+ 0xc2, 0x09,
+ 0xc3, 0x80,
+ 0xc4, 0x06,
+ 0xc5, 0x00,
+ 0xc6, 0xc0,
+ 0xc7, 0x02,
+ 0xc8, 0x12,
+ 0xc9, 0x00,
+ 0xca, 0xf2,
+ 0xcb, 0x00,
+ 0xcc, 0xd0,
+ 0xcd, 0x02,
+ 0xce, 0xf2,
+ 0xcf, 0x00,
+ 0xd0, 0x01,
+ 0xd1, 0x01,
+ 0xd2, 0x01,
+ 0xd4, 0x80,
+ 0xd5, 0x40,
+ 0xd6, 0x40,
+ 0xd8, 0x00,
+ 0xd9, 0x04,
+ 0xda, 0x00,
+ 0xdc, 0x00,
+ 0xdd, 0x02,
+ 0xde, 0x00,
+ 0xe0, 0x00,
+ 0xe1, 0x04,
+ 0xe2, 0x00,
+ 0xe3, 0x04,
+ 0xe4, 0x00,
+ 0xe8, 0x00,
+ 0x88, 0xf0, /* End of original static list */
+ 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+ int i;
+
+ for (i = 0; regs[i] != 0x00; i += 2)
+ if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+ return -1;
+ return 0;
+}
+
+static int wis_saa7115_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct wis_saa7115 *dec = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_S_INPUT:
+ {
+ int *input = arg;
+
+ i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
+ i2c_smbus_write_byte_data(client, 0x09,
+ *input < 6 ? 0x40 : 0xC0);
+ break;
+ }
+ case DECODER_SET_RESOLUTION:
+ {
+ struct video_decoder_resolution *res = arg;
+ /* Course-grained scaler */
+ int h_integer_scaler = res->width < 704 ? 704 / res->width : 1;
+ /* Fine-grained scaler to take care of remainder */
+ int h_scaling_increment = (704 / h_integer_scaler) *
+ 1024 / res->width;
+ /* Fine-grained scaler only */
+ int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
+ 240 : 288) * 1024 / res->height;
+ u8 regs[] = {
+ 0x88, 0xc0,
+ 0x9c, res->width & 0xff,
+ 0x9d, res->width >> 8,
+ 0x9e, res->height & 0xff,
+ 0x9f, res->height >> 8,
+ 0xa0, h_integer_scaler,
+ 0xa1, 1,
+ 0xa2, 1,
+ 0xa8, h_scaling_increment & 0xff,
+ 0xa9, h_scaling_increment >> 8,
+ 0xac, (h_scaling_increment / 2) & 0xff,
+ 0xad, (h_scaling_increment / 2) >> 8,
+ 0xb0, v_scaling_increment & 0xff,
+ 0xb1, v_scaling_increment >> 8,
+ 0xb2, v_scaling_increment & 0xff,
+ 0xb3, v_scaling_increment >> 8,
+ 0xcc, res->width & 0xff,
+ 0xcd, res->width >> 8,
+ 0xce, res->height & 0xff,
+ 0xcf, res->height >> 8,
+ 0xd0, h_integer_scaler,
+ 0xd1, 1,
+ 0xd2, 1,
+ 0xd8, h_scaling_increment & 0xff,
+ 0xd9, h_scaling_increment >> 8,
+ 0xdc, (h_scaling_increment / 2) & 0xff,
+ 0xdd, (h_scaling_increment / 2) >> 8,
+ 0xe0, v_scaling_increment & 0xff,
+ 0xe1, v_scaling_increment >> 8,
+ 0xe2, v_scaling_increment & 0xff,
+ 0xe3, v_scaling_increment >> 8,
+ 0x88, 0xf0,
+ 0, 0,
+ };
+ write_regs(client, regs);
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *input = arg;
+ u8 regs[] = {
+ 0x88, 0xc0,
+ 0x98, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
+ 0x9a, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
+ 0x9b, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
+ 0xc8, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
+ 0xca, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
+ 0xcb, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
+ 0x88, 0xf0,
+ 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00,
+ 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0,
+ 0, 0,
+ };
+ write_regs(client, regs);
+ dec->norm = *input;
+ break;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 64;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 64;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
+ ctrl->minimum = -128;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 0;
+ ctrl->flags = 0;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value > 255)
+ dec->brightness = 255;
+ else if (ctrl->value < 0)
+ dec->brightness = 0;
+ else
+ dec->brightness = ctrl->value;
+ write_reg(client, 0x0a, dec->brightness);
+ break;
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value > 127)
+ dec->contrast = 127;
+ else if (ctrl->value < 0)
+ dec->contrast = 0;
+ else
+ dec->contrast = ctrl->value;
+ write_reg(client, 0x0b, dec->contrast);
+ break;
+ case V4L2_CID_SATURATION:
+ if (ctrl->value > 127)
+ dec->saturation = 127;
+ else if (ctrl->value < 0)
+ dec->saturation = 0;
+ else
+ dec->saturation = ctrl->value;
+ write_reg(client, 0x0c, dec->saturation);
+ break;
+ case V4L2_CID_HUE:
+ if (ctrl->value > 127)
+ dec->hue = 127;
+ else if (ctrl->value < -128)
+ dec->hue = -128;
+ else
+ dec->hue = ctrl->value;
+ write_reg(client, 0x0d, dec->hue);
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = dec->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = dec->contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->value = dec->saturation;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->value = dec->hue;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_saa7115_driver;
+
+static struct i2c_client wis_saa7115_client_templ = {
+ .name = "SAA7115 (WIS)",
+ .driver = &wis_saa7115_driver,
+};
+
+static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+ struct wis_saa7115 *dec;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_saa7115_client_templ,
+ sizeof(wis_saa7115_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
+ if (dec == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ dec->norm = V4L2_STD_NTSC;
+ dec->brightness = 128;
+ dec->contrast = 64;
+ dec->saturation = 64;
+ dec->hue = 0;
+ i2c_set_clientdata(client, dec);
+
+ printk(KERN_DEBUG
+ "wis-saa7115: initializing SAA7115 at address %d on %s\n",
+ addr, adapter->name);
+
+ if (write_regs(client, initial_registers) < 0) {
+ printk(KERN_ERR
+ "wis-saa7115: error initializing SAA7115\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_saa7115_detach(struct i2c_client *client)
+{
+ struct wis_saa7115 *dec = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ kfree(dec);
+ return 0;
+}
+
+static struct i2c_driver wis_saa7115_driver = {
+ .driver = {
+ .name = "WIS SAA7115 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_SAA7115,
+ .detach_client = wis_saa7115_detach,
+ .command = wis_saa7115_command,
+};
+
+static int __init wis_saa7115_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_saa7115_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect);
+}
+
+static void __exit wis_saa7115_cleanup(void)
+{
+ wis_i2c_del_driver(wis_saa7115_detect);
+ i2c_del_driver(&wis_saa7115_driver);
+}
+
+module_init(wis_saa7115_init);
+module_exit(wis_saa7115_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
new file mode 100644
index 00000000000..5997fb47945
--- /dev/null
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -0,0 +1,742 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#include "wis-i2c.h"
+
+/* #define MPX_DEBUG */
+
+/* AS(IF/MPX) pin: LOW HIGH/OPEN
+ * IF/MPX address: 0x42/0x40 0x43/0x44
+ */
+#define IF_I2C_ADDR 0x43
+#define MPX_I2C_ADDR 0x44
+
+static v4l2_std_id force_band;
+static char force_band_str[] = "-";
+module_param_string(force_band, force_band_str, sizeof(force_band_str), 0644);
+static int force_mpx_mode = -1;
+module_param(force_mpx_mode, int, 0644);
+
+/* Store tuner info in the same format as tuner.c, so maybe we can put the
+ * Sony tuner support in there. */
+struct sony_tunertype {
+ char *name;
+ unsigned char Vendor; /* unused here */
+ unsigned char Type; /* unused here */
+
+ unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */
+ unsigned short thresh2; /* band switch VHF_HI <=> UHF */
+ unsigned char VHF_L;
+ unsigned char VHF_H;
+ unsigned char UHF;
+ unsigned char config;
+ unsigned short IFPCoff;
+};
+
+/* This array is indexed by (tuner_type - 200) */
+static struct sony_tunertype sony_tuners[] = {
+ { "Sony PAL+SECAM (BTF-PG472Z)", 0, 0,
+ 16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623},
+ { "Sony NTSC_JP (BTF-PK467Z)", 0, 0,
+ 16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940},
+ { "Sony NTSC (BTF-PB463Z)", 0, 0,
+ 16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732},
+};
+
+struct wis_sony_tuner {
+ int type;
+ v4l2_std_id std;
+ unsigned int freq;
+ int mpxmode;
+ u32 audmode;
+};
+
+/* Basically the same as default_set_tv_freq() in tuner.c */
+static int set_freq(struct i2c_client *client, int freq)
+{
+ struct wis_sony_tuner *t = i2c_get_clientdata(client);
+ char *band_name;
+ int n;
+ int band_select;
+ struct sony_tunertype *tun;
+ u8 buffer[4];
+
+ tun = &sony_tuners[t->type - 200];
+ if (freq < tun->thresh1) {
+ band_name = "VHF_L";
+ band_select = tun->VHF_L;
+ } else if (freq < tun->thresh2) {
+ band_name = "VHF_H";
+ band_select = tun->VHF_H;
+ } else {
+ band_name = "UHF";
+ band_select = tun->UHF;
+ }
+ printk(KERN_DEBUG "wis-sony-tuner: tuning to frequency %d.%04d (%s)\n",
+ freq / 16, (freq % 16) * 625, band_name);
+ n = freq + tun->IFPCoff;
+
+ buffer[0] = n >> 8;
+ buffer[1] = n & 0xff;
+ buffer[2] = tun->config;
+ buffer[3] = band_select;
+ i2c_master_send(client, buffer, 4);
+
+ return 0;
+}
+
+static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
+{
+ u8 buffer[5];
+ struct i2c_msg msg;
+
+ buffer[0] = dev;
+ buffer[1] = addr >> 8;
+ buffer[2] = addr & 0xff;
+ buffer[3] = val >> 8;
+ buffer[4] = val & 0xff;
+ msg.addr = MPX_I2C_ADDR;
+ msg.flags = 0;
+ msg.len = 5;
+ msg.buf = buffer;
+ i2c_transfer(client->adapter, &msg, 1);
+ return 0;
+}
+
+/*
+ * MPX register values for the BTF-PG472Z:
+ *
+ * FM_ NICAM_ SCART_
+ * MODUS SOURCE ACB PRESCAL PRESCAL PRESCAL SYSTEM VOLUME
+ * 10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
+ * ---------------------------------------------------------------
+ * Auto 1003 0020 0100 2603 5000 XXXX 0001 7500
+ *
+ * B/G
+ * Mono 1003 0020 0100 2603 5000 XXXX 0003 7500
+ * A2 1003 0020 0100 2601 5000 XXXX 0003 7500
+ * NICAM 1003 0120 0100 2603 5000 XXXX 0008 7500
+ *
+ * I
+ * Mono 1003 0020 0100 2603 7900 XXXX 000A 7500
+ * NICAM 1003 0120 0100 2603 7900 XXXX 000A 7500
+ *
+ * D/K
+ * Mono 1003 0020 0100 2603 5000 XXXX 0004 7500
+ * A2-1 1003 0020 0100 2601 5000 XXXX 0004 7500
+ * A2-2 1003 0020 0100 2601 5000 XXXX 0005 7500
+ * A2-3 1003 0020 0100 2601 5000 XXXX 0007 7500
+ * NICAM 1003 0120 0100 2603 5000 XXXX 000B 7500
+ *
+ * L/L'
+ * Mono 0003 0200 0100 7C03 5000 2200 0009 7500
+ * NICAM 0003 0120 0100 7C03 5000 XXXX 0009 7500
+ *
+ * M
+ * Mono 1003 0200 0100 2B03 5000 2B00 0002 7500
+ *
+ * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
+ *
+ * Bilingual selection in A2/NICAM:
+ *
+ * High byte of SOURCE Left chan Right chan
+ * 0x01 MAIN SUB
+ * 0x03 MAIN MAIN
+ * 0x04 SUB SUB
+ *
+ * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
+ * 0x00 (all other bands). Force mono in A2 with FMONO_A2:
+ *
+ * FMONO_A2
+ * 10/0022
+ * --------
+ * Forced mono ON 07F0
+ * Forced mono OFF 0190
+ */
+
+static struct {
+ enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
+ u16 modus;
+ u16 source;
+ u16 acb;
+ u16 fm_prescale;
+ u16 nicam_prescale;
+ u16 scart_prescale;
+ u16 system;
+ u16 volume;
+} mpx_audio_modes[] = {
+ /* Auto */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
+ 0x5000, 0x0000, 0x0001, 0x7500 },
+ /* B/G Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
+ 0x5000, 0x0000, 0x0003, 0x7500 },
+ /* B/G A2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
+ 0x5000, 0x0000, 0x0003, 0x7500 },
+ /* B/G NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
+ 0x5000, 0x0000, 0x0008, 0x7500 },
+ /* I Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
+ 0x7900, 0x0000, 0x000A, 0x7500 },
+ /* I NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
+ 0x7900, 0x0000, 0x000A, 0x7500 },
+ /* D/K Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
+ 0x5000, 0x0000, 0x0004, 0x7500 },
+ /* D/K A2-1 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
+ 0x5000, 0x0000, 0x0004, 0x7500 },
+ /* D/K A2-2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
+ 0x5000, 0x0000, 0x0005, 0x7500 },
+ /* D/K A2-3 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
+ 0x5000, 0x0000, 0x0007, 0x7500 },
+ /* D/K NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
+ 0x5000, 0x0000, 0x000B, 0x7500 },
+ /* L/L' Mono */ { AUD_MONO, 0x0003, 0x0200, 0x0100, 0x7C03,
+ 0x5000, 0x2200, 0x0009, 0x7500 },
+ /* L/L' NICAM */{ AUD_NICAM_L, 0x0003, 0x0120, 0x0100, 0x7C03,
+ 0x5000, 0x0000, 0x0009, 0x7500 },
+};
+
+#define MPX_NUM_MODES ARRAY_SIZE(mpx_audio_modes)
+
+static int mpx_setup(struct i2c_client *client)
+{
+ struct wis_sony_tuner *t = i2c_get_clientdata(client);
+ u16 source = 0;
+ u8 buffer[3];
+ struct i2c_msg msg;
+
+ /* reset MPX */
+ buffer[0] = 0x00;
+ buffer[1] = 0x80;
+ buffer[2] = 0x00;
+ msg.addr = MPX_I2C_ADDR;
+ msg.flags = 0;
+ msg.len = 3;
+ msg.buf = buffer;
+ i2c_transfer(client->adapter, &msg, 1);
+ buffer[1] = 0x00;
+ i2c_transfer(client->adapter, &msg, 1);
+
+ if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) {
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ switch (mpx_audio_modes[t->mpxmode].audio_mode) {
+ case AUD_A2:
+ source = mpx_audio_modes[t->mpxmode].source;
+ break;
+ case AUD_NICAM:
+ source = 0x0000;
+ break;
+ case AUD_NICAM_L:
+ source = 0x0200;
+ break;
+ default:
+ break;
+ }
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ source = mpx_audio_modes[t->mpxmode].source;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ source = 0x0300;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ source = 0x0400;
+ break;
+ }
+ source |= mpx_audio_modes[t->mpxmode].source & 0x00ff;
+ } else
+ source = mpx_audio_modes[t->mpxmode].source;
+
+ mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus);
+ mpx_write(client, 0x12, 0x0008, source);
+ mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb);
+ mpx_write(client, 0x12, 0x000e,
+ mpx_audio_modes[t->mpxmode].fm_prescale);
+ mpx_write(client, 0x12, 0x0010,
+ mpx_audio_modes[t->mpxmode].nicam_prescale);
+ mpx_write(client, 0x12, 0x000d,
+ mpx_audio_modes[t->mpxmode].scart_prescale);
+ mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system);
+ mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume);
+ if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2)
+ mpx_write(client, 0x10, 0x0022,
+ t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190);
+
+#ifdef MPX_DEBUG
+ {
+ u8 buf1[3], buf2[2];
+ struct i2c_msg msgs[2];
+
+ printk(KERN_DEBUG "wis-sony-tuner: MPX registers: %04x %04x "
+ "%04x %04x %04x %04x %04x %04x\n",
+ mpx_audio_modes[t->mpxmode].modus,
+ source,
+ mpx_audio_modes[t->mpxmode].acb,
+ mpx_audio_modes[t->mpxmode].fm_prescale,
+ mpx_audio_modes[t->mpxmode].nicam_prescale,
+ mpx_audio_modes[t->mpxmode].scart_prescale,
+ mpx_audio_modes[t->mpxmode].system,
+ mpx_audio_modes[t->mpxmode].volume);
+ buf1[0] = 0x11;
+ buf1[1] = 0x00;
+ buf1[2] = 0x7e;
+ msgs[0].addr = MPX_I2C_ADDR;
+ msgs[0].flags = 0;
+ msgs[0].len = 3;
+ msgs[0].buf = buf1;
+ msgs[1].addr = MPX_I2C_ADDR;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = 2;
+ msgs[1].buf = buf2;
+ i2c_transfer(client->adapter, msgs, 2);
+ printk(KERN_DEBUG "wis-sony-tuner: MPX system: %02x%02x\n",
+ buf2[0], buf2[1]);
+ buf1[0] = 0x11;
+ buf1[1] = 0x02;
+ buf1[2] = 0x00;
+ i2c_transfer(client->adapter, msgs, 2);
+ printk(KERN_DEBUG "wis-sony-tuner: MPX status: %02x%02x\n",
+ buf2[0], buf2[1]);
+ }
+#endif
+ return 0;
+}
+
+/*
+ * IF configuration values for the BTF-PG472Z:
+ *
+ * B/G: 0x94 0x70 0x49
+ * I: 0x14 0x70 0x4a
+ * D/K: 0x14 0x70 0x4b
+ * L: 0x04 0x70 0x4b
+ * L': 0x44 0x70 0x53
+ * M: 0x50 0x30 0x4c
+ */
+
+static int set_if(struct i2c_client *client)
+{
+ struct wis_sony_tuner *t = i2c_get_clientdata(client);
+ u8 buffer[4];
+ struct i2c_msg msg;
+ int default_mpx_mode = 0;
+
+ /* configure IF */
+ buffer[0] = 0;
+ if (t->std & V4L2_STD_PAL_BG) {
+ buffer[1] = 0x94;
+ buffer[2] = 0x70;
+ buffer[3] = 0x49;
+ default_mpx_mode = 1;
+ } else if (t->std & V4L2_STD_PAL_I) {
+ buffer[1] = 0x14;
+ buffer[2] = 0x70;
+ buffer[3] = 0x4a;
+ default_mpx_mode = 4;
+ } else if (t->std & V4L2_STD_PAL_DK) {
+ buffer[1] = 0x14;
+ buffer[2] = 0x70;
+ buffer[3] = 0x4b;
+ default_mpx_mode = 6;
+ } else if (t->std & V4L2_STD_SECAM_L) {
+ buffer[1] = 0x04;
+ buffer[2] = 0x70;
+ buffer[3] = 0x4b;
+ default_mpx_mode = 11;
+ }
+ msg.addr = IF_I2C_ADDR;
+ msg.flags = 0;
+ msg.len = 4;
+ msg.buf = buffer;
+ i2c_transfer(client->adapter, &msg, 1);
+
+ /* Select MPX mode if not forced by the user */
+ if (force_mpx_mode >= 0 || force_mpx_mode < MPX_NUM_MODES)
+ t->mpxmode = force_mpx_mode;
+ else
+ t->mpxmode = default_mpx_mode;
+ printk(KERN_DEBUG "wis-sony-tuner: setting MPX to mode %d\n",
+ t->mpxmode);
+ mpx_setup(client);
+
+ return 0;
+}
+
+static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct wis_sony_tuner *t = i2c_get_clientdata(client);
+
+ switch (cmd) {
+#ifdef TUNER_SET_TYPE_ADDR
+ case TUNER_SET_TYPE_ADDR:
+ {
+ struct tuner_setup *tun_setup = arg;
+ int *type = &tun_setup->type;
+#else
+ case TUNER_SET_TYPE:
+ {
+ int *type = arg;
+#endif
+
+ if (t->type >= 0) {
+ if (t->type != *type)
+ printk(KERN_ERR "wis-sony-tuner: type already "
+ "set to %d, ignoring request for %d\n",
+ t->type, *type);
+ break;
+ }
+ t->type = *type;
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ switch (force_band_str[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ printk(KERN_INFO "wis-sony-tuner: forcing "
+ "tuner to PAL-B/G bands\n");
+ force_band = V4L2_STD_PAL_BG;
+ break;
+ case 'i':
+ case 'I':
+ printk(KERN_INFO "wis-sony-tuner: forcing "
+ "tuner to PAL-I band\n");
+ force_band = V4L2_STD_PAL_I;
+ break;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ printk(KERN_INFO "wis-sony-tuner: forcing "
+ "tuner to PAL-D/K bands\n");
+ force_band = V4L2_STD_PAL_I;
+ break;
+ case 'l':
+ case 'L':
+ printk(KERN_INFO "wis-sony-tuner: forcing "
+ "tuner to SECAM-L band\n");
+ force_band = V4L2_STD_SECAM_L;
+ break;
+ default:
+ force_band = 0;
+ break;
+ }
+ if (force_band)
+ t->std = force_band;
+ else
+ t->std = V4L2_STD_PAL_BG;
+ set_if(client);
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ t->std = V4L2_STD_NTSC_M_JP;
+ break;
+ case TUNER_SONY_BTF_PB463Z:
+ t->std = V4L2_STD_NTSC_M;
+ break;
+ default:
+ printk(KERN_ERR "wis-sony-tuner: tuner type %d is not "
+ "supported by this module\n", *type);
+ break;
+ }
+ if (type >= 0)
+ printk(KERN_INFO
+ "wis-sony-tuner: type set to %d (%s)\n",
+ t->type, sony_tuners[t->type - 200].name);
+ break;
+ }
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ f->frequency = t->freq;
+ break;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ t->freq = f->frequency;
+ set_freq(client, t->freq);
+ break;
+ }
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *std = arg;
+
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ switch (std->index) {
+ case 0:
+ v4l2_video_std_construct(std,
+ V4L2_STD_PAL_BG, "PAL-B/G");
+ break;
+ case 1:
+ v4l2_video_std_construct(std,
+ V4L2_STD_PAL_I, "PAL-I");
+ break;
+ case 2:
+ v4l2_video_std_construct(std,
+ V4L2_STD_PAL_DK, "PAL-D/K");
+ break;
+ case 3:
+ v4l2_video_std_construct(std,
+ V4L2_STD_SECAM_L, "SECAM-L");
+ break;
+ default:
+ std->id = 0; /* hack to indicate EINVAL */
+ break;
+ }
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ if (std->index != 0) {
+ std->id = 0; /* hack to indicate EINVAL */
+ break;
+ }
+ v4l2_video_std_construct(std,
+ V4L2_STD_NTSC_M_JP, "NTSC-J");
+ break;
+ case TUNER_SONY_BTF_PB463Z:
+ if (std->index != 0) {
+ std->id = 0; /* hack to indicate EINVAL */
+ break;
+ }
+ v4l2_video_std_construct(std, V4L2_STD_NTSC_M, "NTSC");
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *std = arg;
+
+ *std = t->std;
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *std = arg;
+ v4l2_std_id old = t->std;
+
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ if (force_band && (*std & force_band) != *std &&
+ *std != V4L2_STD_PAL &&
+ *std != V4L2_STD_SECAM) {
+ printk(KERN_DEBUG "wis-sony-tuner: ignoring "
+ "requested TV standard in "
+ "favor of force_band value\n");
+ t->std = force_band;
+ } else if (*std & V4L2_STD_PAL_BG) { /* default */
+ t->std = V4L2_STD_PAL_BG;
+ } else if (*std & V4L2_STD_PAL_I) {
+ t->std = V4L2_STD_PAL_I;
+ } else if (*std & V4L2_STD_PAL_DK) {
+ t->std = V4L2_STD_PAL_DK;
+ } else if (*std & V4L2_STD_SECAM_L) {
+ t->std = V4L2_STD_SECAM_L;
+ } else {
+ printk(KERN_ERR "wis-sony-tuner: TV standard "
+ "not supported\n");
+ *std = 0; /* hack to indicate EINVAL */
+ break;
+ }
+ if (old != t->std)
+ set_if(client);
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ if (!(*std & V4L2_STD_NTSC_M_JP)) {
+ printk(KERN_ERR "wis-sony-tuner: TV standard "
+ "not supported\n");
+ *std = 0; /* hack to indicate EINVAL */
+ }
+ break;
+ case TUNER_SONY_BTF_PB463Z:
+ if (!(*std & V4L2_STD_NTSC_M)) {
+ printk(KERN_ERR "wis-sony-tuner: TV standard "
+ "not supported\n");
+ *std = 0; /* hack to indicate EINVAL */
+ }
+ break;
+ }
+ break;
+ }
+ case VIDIOC_QUERYSTD:
+ {
+ v4l2_std_id *std = arg;
+
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ if (force_band)
+ *std = force_band;
+ else
+ *std = V4L2_STD_PAL_BG | V4L2_STD_PAL_I |
+ V4L2_STD_PAL_DK | V4L2_STD_SECAM_L;
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ *std = V4L2_STD_NTSC_M_JP;
+ break;
+ case TUNER_SONY_BTF_PB463Z:
+ *std = V4L2_STD_NTSC_M;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *tun = arg;
+
+ memset(t, 0, sizeof(*tun));
+ strcpy(tun->name, "Television");
+ tun->type = V4L2_TUNER_ANALOG_TV;
+ tun->rangelow = 0UL; /* does anything use these? */
+ tun->rangehigh = 0xffffffffUL;
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ tun->capability = V4L2_TUNER_CAP_NORM |
+ V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+ V4L2_TUNER_CAP_LANG2;
+ tun->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ case TUNER_SONY_BTF_PB463Z:
+ tun->capability = V4L2_TUNER_CAP_STEREO;
+ tun->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO;
+ break;
+ }
+ tun->audmode = t->audmode;
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *tun = arg;
+
+ switch (t->type) {
+ case TUNER_SONY_BTF_PG472Z:
+ if (tun->audmode != t->audmode) {
+ t->audmode = tun->audmode;
+ mpx_setup(client);
+ }
+ break;
+ case TUNER_SONY_BTF_PK467Z:
+ case TUNER_SONY_BTF_PB463Z:
+ break;
+ }
+ return 0;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_sony_tuner_driver;
+
+static struct i2c_client wis_sony_tuner_client_templ = {
+ .name = "Sony TV Tuner (WIS)",
+ .driver = &wis_sony_tuner_driver,
+};
+
+static int wis_sony_tuner_detect(struct i2c_adapter *adapter,
+ int addr, int kind)
+{
+ struct i2c_client *client;
+ struct wis_sony_tuner *t;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_sony_tuner_client_templ,
+ sizeof(wis_sony_tuner_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL);
+ if (t == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ t->type = -1;
+ t->freq = 0;
+ t->mpxmode = 0;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ i2c_set_clientdata(client, t);
+
+ printk(KERN_DEBUG
+ "wis-sony-tuner: initializing tuner at address %d on %s\n",
+ addr, adapter->name);
+
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int wis_sony_tuner_detach(struct i2c_client *client)
+{
+ struct wis_sony_tuner *t = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(t);
+ kfree(client);
+ return 0;
+}
+
+static struct i2c_driver wis_sony_tuner_driver = {
+ .driver = {
+ .name = "WIS Sony TV Tuner I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_SONY_TUNER,
+ .detach_client = wis_sony_tuner_detach,
+ .command = tuner_command,
+};
+
+static int __init wis_sony_tuner_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_sony_tuner_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_sony_tuner_driver.id,
+ wis_sony_tuner_detect);
+}
+
+static void __exit wis_sony_tuner_cleanup(void)
+{
+ wis_i2c_del_driver(wis_sony_tuner_detect);
+ i2c_del_driver(&wis_sony_tuner_driver);
+}
+
+module_init(wis_sony_tuner_init);
+module_exit(wis_sony_tuner_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
new file mode 100644
index 00000000000..27fe4d0d4ed
--- /dev/null
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+
+#include "wis-i2c.h"
+
+struct wis_tw2804 {
+ int channel;
+ int norm;
+ int brightness;
+ int contrast;
+ int saturation;
+ int hue;
+};
+
+static u8 global_registers[] =
+{
+ 0x39, 0x00,
+ 0x3a, 0xff,
+ 0x3b, 0x84,
+ 0x3c, 0x80,
+ 0x3d, 0x80,
+ 0x3e, 0x82,
+ 0x3f, 0x82,
+ 0xff, 0xff, /* Terminator (reg 0xff does not exist) */
+};
+
+static u8 channel_registers[] =
+{
+ 0x01, 0xc4,
+ 0x02, 0xa5,
+ 0x03, 0x20,
+ 0x04, 0xd0,
+ 0x05, 0x20,
+ 0x06, 0xd0,
+ 0x07, 0x88,
+ 0x08, 0x20,
+ 0x09, 0x07,
+ 0x0a, 0xf0,
+ 0x0b, 0x07,
+ 0x0c, 0xf0,
+ 0x0d, 0x40,
+ 0x0e, 0xd2,
+ 0x0f, 0x80,
+ 0x10, 0x80,
+ 0x11, 0x80,
+ 0x12, 0x80,
+ 0x13, 0x1f,
+ 0x14, 0x00,
+ 0x15, 0x00,
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0xff,
+ 0x19, 0xff,
+ 0x1a, 0xff,
+ 0x1b, 0xff,
+ 0x1c, 0xff,
+ 0x1d, 0xff,
+ 0x1e, 0xff,
+ 0x1f, 0xff,
+ 0x20, 0x07,
+ 0x21, 0x07,
+ 0x22, 0x00,
+ 0x23, 0x91,
+ 0x24, 0x51,
+ 0x25, 0x03,
+ 0x26, 0x00,
+ 0x27, 0x00,
+ 0x28, 0x00,
+ 0x29, 0x00,
+ 0x2a, 0x00,
+ 0x2b, 0x00,
+ 0x2c, 0x00,
+ 0x2d, 0x00,
+ 0x2e, 0x00,
+ 0x2f, 0x00,
+ 0x30, 0x00,
+ 0x31, 0x00,
+ 0x32, 0x00,
+ 0x33, 0x00,
+ 0x34, 0x00,
+ 0x35, 0x00,
+ 0x36, 0x00,
+ 0x37, 0x00,
+ 0xff, 0xff, /* Terminator (reg 0xff does not exist) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel)
+{
+ return i2c_smbus_write_byte_data(client, reg | (channel << 6), value);
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs, int channel)
+{
+ int i;
+
+ for (i = 0; regs[i] != 0xff; i += 2)
+ if (i2c_smbus_write_byte_data(client,
+ regs[i] | (channel << 6), regs[i + 1]) < 0)
+ return -1;
+ return 0;
+}
+
+static int wis_tw2804_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct wis_tw2804 *dec = i2c_get_clientdata(client);
+
+ if (cmd == DECODER_SET_CHANNEL) {
+ int *input = arg;
+
+ if (*input < 0 || *input > 3) {
+ printk(KERN_ERR "wis-tw2804: channel %d is not "
+ "between 0 and 3!\n", *input);
+ return 0;
+ }
+ dec->channel = *input;
+ printk(KERN_DEBUG "wis-tw2804: initializing TW2804 "
+ "channel %d\n", dec->channel);
+ if (dec->channel == 0 &&
+ write_regs(client, global_registers, 0) < 0) {
+ printk(KERN_ERR "wis-tw2804: error initializing "
+ "TW2804 global registers\n");
+ return 0;
+ }
+ if (write_regs(client, channel_registers, dec->channel) < 0) {
+ printk(KERN_ERR "wis-tw2804: error initializing "
+ "TW2804 channel %d\n", dec->channel);
+ return 0;
+ }
+ return 0;
+ }
+
+ if (dec->channel < 0) {
+ printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until "
+ "channel number is set\n", cmd);
+ return 0;
+ }
+
+ switch (cmd) {
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *input = arg;
+ u8 regs[] = {
+ 0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84,
+ 0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
+ 0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
+ 0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
+ 0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
+ 0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a,
+ 0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
+ 0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
+ 0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
+ 0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
+ 0xff, 0xff,
+ };
+ write_regs(client, regs, dec->channel);
+ dec->norm = *input;
+ break;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 128;
+ ctrl->flags = 0;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value > 255)
+ dec->brightness = 255;
+ else if (ctrl->value < 0)
+ dec->brightness = 0;
+ else
+ dec->brightness = ctrl->value;
+ write_reg(client, 0x12, dec->brightness, dec->channel);
+ break;
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value > 255)
+ dec->contrast = 255;
+ else if (ctrl->value < 0)
+ dec->contrast = 0;
+ else
+ dec->contrast = ctrl->value;
+ write_reg(client, 0x11, dec->contrast, dec->channel);
+ break;
+ case V4L2_CID_SATURATION:
+ if (ctrl->value > 255)
+ dec->saturation = 255;
+ else if (ctrl->value < 0)
+ dec->saturation = 0;
+ else
+ dec->saturation = ctrl->value;
+ write_reg(client, 0x10, dec->saturation, dec->channel);
+ break;
+ case V4L2_CID_HUE:
+ if (ctrl->value > 255)
+ dec->hue = 255;
+ else if (ctrl->value < 0)
+ dec->hue = 0;
+ else
+ dec->hue = ctrl->value;
+ write_reg(client, 0x0f, dec->hue, dec->channel);
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = dec->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = dec->contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->value = dec->saturation;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->value = dec->hue;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_tw2804_driver;
+
+static struct i2c_client wis_tw2804_client_templ = {
+ .name = "TW2804 (WIS)",
+ .driver = &wis_tw2804_driver,
+};
+
+static int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+ struct wis_tw2804 *dec;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_tw2804_client_templ,
+ sizeof(wis_tw2804_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL);
+ if (dec == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ dec->channel = -1;
+ dec->norm = V4L2_STD_NTSC;
+ dec->brightness = 128;
+ dec->contrast = 128;
+ dec->saturation = 128;
+ dec->hue = 128;
+ i2c_set_clientdata(client, dec);
+
+ printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n",
+ addr, adapter->name);
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_tw2804_detach(struct i2c_client *client)
+{
+ struct wis_tw2804 *dec = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ kfree(dec);
+ return 0;
+}
+
+static struct i2c_driver wis_tw2804_driver = {
+ .driver = {
+ .name = "WIS TW2804 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_TW2804,
+ .detach_client = wis_tw2804_detach,
+ .command = wis_tw2804_command,
+};
+
+static int __init wis_tw2804_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_tw2804_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_tw2804_driver.id, wis_tw2804_detect);
+}
+
+static void __exit wis_tw2804_cleanup(void)
+{
+ wis_i2c_del_driver(wis_tw2804_detect);
+ i2c_del_driver(&wis_tw2804_driver);
+}
+
+module_init(wis_tw2804_init);
+module_exit(wis_tw2804_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
new file mode 100644
index 00000000000..d8e41968022
--- /dev/null
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+
+#include "wis-i2c.h"
+
+struct wis_tw9903 {
+ int norm;
+ int brightness;
+ int contrast;
+ int hue;
+};
+
+static u8 initial_registers[] =
+{
+ 0x02, 0x44, /* input 1, composite */
+ 0x03, 0x92, /* correct digital format */
+ 0x04, 0x00,
+ 0x05, 0x80, /* or 0x00 for PAL */
+ 0x06, 0x40, /* second internal current reference */
+ 0x07, 0x02, /* window */
+ 0x08, 0x14, /* window */
+ 0x09, 0xf0, /* window */
+ 0x0a, 0x81, /* window */
+ 0x0b, 0xd0, /* window */
+ 0x0c, 0x8c,
+ 0x0d, 0x00, /* scaling */
+ 0x0e, 0x11, /* scaling */
+ 0x0f, 0x00, /* scaling */
+ 0x10, 0x00, /* brightness */
+ 0x11, 0x60, /* contrast */
+ 0x12, 0x01, /* sharpness */
+ 0x13, 0x7f, /* U gain */
+ 0x14, 0x5a, /* V gain */
+ 0x15, 0x00, /* hue */
+ 0x16, 0xc3, /* sharpness */
+ 0x18, 0x00,
+ 0x19, 0x58, /* vbi */
+ 0x1a, 0x80,
+ 0x1c, 0x0f, /* video norm */
+ 0x1d, 0x7f, /* video norm */
+ 0x20, 0xa0, /* clamping gain (working 0x50) */
+ 0x21, 0x22,
+ 0x22, 0xf0,
+ 0x23, 0xfe,
+ 0x24, 0x3c,
+ 0x25, 0x38,
+ 0x26, 0x44,
+ 0x27, 0x20,
+ 0x28, 0x00,
+ 0x29, 0x15,
+ 0x2a, 0xa0,
+ 0x2b, 0x44,
+ 0x2c, 0x37,
+ 0x2d, 0x00,
+ 0x2e, 0xa5, /* burst PLL control (working: a9) */
+ 0x2f, 0xe0, /* 0xea is blue test frame -- 0xe0 for normal */
+ 0x31, 0x00,
+ 0x33, 0x22,
+ 0x34, 0x11,
+ 0x35, 0x35,
+ 0x3b, 0x05,
+ 0x06, 0xc0, /* reset device */
+ 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+ int i;
+
+ for (i = 0; regs[i] != 0x00; i += 2)
+ if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+ return -1;
+ return 0;
+}
+
+static int wis_tw9903_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct wis_tw9903 *dec = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_S_INPUT:
+ {
+ int *input = arg;
+
+ i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1));
+ break;
+ }
+#if 0 /* The scaler on this thing seems to be horribly broken */
+ case DECODER_SET_RESOLUTION:
+ {
+ struct video_decoder_resolution *res = arg;
+ /*int hscale = 256 * 720 / res->width;*/
+ int hscale = 256 * 720 / (res->width - (res->width > 704 ? 0 : 8));
+ int vscale = 256 * (dec->norm & V4L2_STD_NTSC ? 240 : 288)
+ / res->height;
+ u8 regs[] = {
+ 0x0d, vscale & 0xff,
+ 0x0f, hscale & 0xff,
+ 0x0e, ((vscale & 0xf00) >> 4) | ((hscale & 0xf00) >> 8),
+ 0x06, 0xc0, /* reset device */
+ 0, 0,
+ };
+ printk(KERN_DEBUG "vscale is %04x, hscale is %04x\n",
+ vscale, hscale);
+ /*write_regs(client, regs);*/
+ break;
+ }
+#endif
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *input = arg;
+ u8 regs[] = {
+ 0x05, *input & V4L2_STD_NTSC ? 0x80 : 0x00,
+ 0x07, *input & V4L2_STD_NTSC ? 0x02 : 0x12,
+ 0x08, *input & V4L2_STD_NTSC ? 0x14 : 0x18,
+ 0x09, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
+ 0, 0,
+ };
+ write_regs(client, regs);
+ dec->norm = *input;
+ break;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
+ ctrl->minimum = -128;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 0x00;
+ ctrl->flags = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 255;
+ ctrl->step = 1;
+ ctrl->default_value = 0x60;
+ ctrl->flags = 0;
+ break;
+#if 0
+ /* I don't understand how the Chroma Gain registers work... */
+ case V4L2_CID_SATURATION:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
+ ctrl->minimum = 0;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 64;
+ ctrl->flags = 0;
+ break;
+#endif
+ case V4L2_CID_HUE:
+ ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
+ ctrl->minimum = -128;
+ ctrl->maximum = 127;
+ ctrl->step = 1;
+ ctrl->default_value = 0;
+ ctrl->flags = 0;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value > 127)
+ dec->brightness = 127;
+ else if (ctrl->value < -128)
+ dec->brightness = -128;
+ else
+ dec->brightness = ctrl->value;
+ write_reg(client, 0x10, dec->brightness);
+ break;
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value > 255)
+ dec->contrast = 255;
+ else if (ctrl->value < 0)
+ dec->contrast = 0;
+ else
+ dec->contrast = ctrl->value;
+ write_reg(client, 0x11, dec->contrast);
+ break;
+#if 0
+ case V4L2_CID_SATURATION:
+ if (ctrl->value > 127)
+ dec->saturation = 127;
+ else if (ctrl->value < 0)
+ dec->saturation = 0;
+ else
+ dec->saturation = ctrl->value;
+ /*write_reg(client, 0x0c, dec->saturation);*/
+ break;
+#endif
+ case V4L2_CID_HUE:
+ if (ctrl->value > 127)
+ dec->hue = 127;
+ else if (ctrl->value < -128)
+ dec->hue = -128;
+ else
+ dec->hue = ctrl->value;
+ write_reg(client, 0x15, dec->hue);
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = dec->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = dec->contrast;
+ break;
+#if 0
+ case V4L2_CID_SATURATION:
+ ctrl->value = dec->saturation;
+ break;
+#endif
+ case V4L2_CID_HUE:
+ ctrl->value = dec->hue;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_tw9903_driver;
+
+static struct i2c_client wis_tw9903_client_templ = {
+ .name = "TW9903 (WIS)",
+ .driver = &wis_tw9903_driver,
+};
+
+static int wis_tw9903_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+ struct wis_tw9903 *dec;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_tw9903_client_templ,
+ sizeof(wis_tw9903_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ dec = kmalloc(sizeof(struct wis_tw9903), GFP_KERNEL);
+ if (dec == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ dec->norm = V4L2_STD_NTSC;
+ dec->brightness = 0;
+ dec->contrast = 0x60;
+ dec->hue = 0;
+ i2c_set_clientdata(client, dec);
+
+ printk(KERN_DEBUG
+ "wis-tw9903: initializing TW9903 at address %d on %s\n",
+ addr, adapter->name);
+
+ if (write_regs(client, initial_registers) < 0) {
+ printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_tw9903_detach(struct i2c_client *client)
+{
+ struct wis_tw9903 *dec = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ kfree(dec);
+ return 0;
+}
+
+static struct i2c_driver wis_tw9903_driver = {
+ .driver = {
+ .name = "WIS TW9903 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_TW9903,
+ .detach_client = wis_tw9903_detach,
+ .command = wis_tw9903_command,
+};
+
+static int __init wis_tw9903_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_tw9903_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_tw9903_driver.id, wis_tw9903_detect);
+}
+
+static void __exit wis_tw9903_cleanup(void)
+{
+ wis_i2c_del_driver(wis_tw9903_detect);
+ i2c_del_driver(&wis_tw9903_driver);
+}
+
+module_init(wis_tw9903_init);
+module_exit(wis_tw9903_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c
new file mode 100644
index 00000000000..a0894e3cb8c
--- /dev/null
+++ b/drivers/staging/go7007/wis-uda1342.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/tvaudio.h>
+#include <media/v4l2-common.h>
+
+#include "wis-i2c.h"
+
+static int write_reg(struct i2c_client *client, int reg, int value)
+{
+ /* UDA1342 wants MSB first, but SMBus sends LSB first */
+ i2c_smbus_write_word_data(client, reg, swab16(value));
+ return 0;
+}
+
+static int wis_uda1342_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ switch (cmd) {
+ case VIDIOC_S_AUDIO:
+ {
+ int *inp = arg;
+
+ switch (*inp) {
+ case TVAUDIO_INPUT_TUNER:
+ write_reg(client, 0x00, 0x1441); /* select input 2 */
+ break;
+ case TVAUDIO_INPUT_EXTERN:
+ write_reg(client, 0x00, 0x1241); /* select input 1 */
+ break;
+ default:
+ printk(KERN_ERR "wis-uda1342: input %d not supported\n",
+ *inp);
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver wis_uda1342_driver;
+
+static struct i2c_client wis_uda1342_client_templ = {
+ .name = "UDA1342 (WIS)",
+ .driver = &wis_uda1342_driver,
+};
+
+static int wis_uda1342_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return 0;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &wis_uda1342_client_templ,
+ sizeof(wis_uda1342_client_templ));
+ client->adapter = adapter;
+ client->addr = addr;
+
+ printk(KERN_DEBUG
+ "wis-uda1342: initializing UDA1342 at address %d on %s\n",
+ addr, adapter->name);
+
+ write_reg(client, 0x00, 0x8000); /* reset registers */
+ write_reg(client, 0x00, 0x1241); /* select input 1 */
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int wis_uda1342_detach(struct i2c_client *client)
+{
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ return 0;
+}
+
+static struct i2c_driver wis_uda1342_driver = {
+ .driver = {
+ .name = "WIS UDA1342 I2C driver",
+ },
+ .id = I2C_DRIVERID_WIS_UDA1342,
+ .detach_client = wis_uda1342_detach,
+ .command = wis_uda1342_command,
+};
+
+static int __init wis_uda1342_init(void)
+{
+ int r;
+
+ r = i2c_add_driver(&wis_uda1342_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(wis_uda1342_driver.id, wis_uda1342_detect);
+}
+
+static void __exit wis_uda1342_cleanup(void)
+{
+ wis_i2c_del_driver(wis_uda1342_detect);
+ i2c_del_driver(&wis_uda1342_driver);
+}
+
+module_init(wis_uda1342_init);
+module_exit(wis_uda1342_cleanup);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/me4000/Kconfig b/drivers/staging/me4000/Kconfig
new file mode 100644
index 00000000000..5e6c9de1f11
--- /dev/null
+++ b/drivers/staging/me4000/Kconfig
@@ -0,0 +1,10 @@
+config ME4000
+ tristate "Meilhaus ME-4000 support"
+ default n
+ depends on PCI
+ help
+ This driver supports the Meilhaus ME-4000 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me4000.
diff --git a/drivers/staging/me4000/Makefile b/drivers/staging/me4000/Makefile
new file mode 100644
index 00000000000..74487cd7bec
--- /dev/null
+++ b/drivers/staging/me4000/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ME4000) += me4000.o
diff --git a/drivers/staging/me4000/README b/drivers/staging/me4000/README
new file mode 100644
index 00000000000..bbb83863220
--- /dev/null
+++ b/drivers/staging/me4000/README
@@ -0,0 +1,13 @@
+
+TODO:
+ - checkpatch.pl cleanups
+ - sparse cleanups
+ - possible /proc interaction cleanups
+ - more info needed for Kconfig entry
+ - real device id?
+ - module parameter cleanup
+
+Please send patches to Greg Kroah-Hartman <gregkh@suse.de>
+and Cc: Wolfgang Beiter <w.beiter@aon.at> and
+Guenter Gebhardt <g.gebhardt@meilhaus.de>
+
diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c
new file mode 100644
index 00000000000..862dd7ffb5c
--- /dev/null
+++ b/drivers/staging/me4000/me4000.c
@@ -0,0 +1,6133 @@
+/* Device driver for Meilhaus ME-4000 board family.
+ * ================================================
+ *
+ * Copyright (C) 2003 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file 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.
+ *
+ * Author: Guenter Gebhardt <g.gebhardt@meilhaus.de>
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/unistd.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include <linux/poll.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+
+#include <linux/slab.h>
+
+/* Include-File for the Meilhaus ME-4000 I/O board */
+#include "me4000.h"
+#include "me4000_firmware.h"
+#include "me4610_firmware.h"
+
+/* Administrative stuff for modinfo */
+MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
+MODULE_DESCRIPTION
+ ("Device Driver Module for Meilhaus ME-4000 boards version 1.0.5");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-4000 Multi I/O boards");
+MODULE_LICENSE("GPL");
+
+/* Board specific data are kept in a global list */
+LIST_HEAD(me4000_board_info_list);
+
+/* Major Device Numbers. 0 means to get it automatically from the System */
+static int me4000_ao_major_driver_no = 0;
+static int me4000_ai_major_driver_no = 0;
+static int me4000_dio_major_driver_no = 0;
+static int me4000_cnt_major_driver_no = 0;
+static int me4000_ext_int_major_driver_no = 0;
+
+/* Let the user specify a custom major driver number */
+module_param(me4000_ao_major_driver_no, int, 0);
+MODULE_PARM_DESC(me4000_ao_major_driver_no,
+ "Major driver number for analog output (default 0)");
+
+module_param(me4000_ai_major_driver_no, int, 0);
+MODULE_PARM_DESC(me4000_ai_major_driver_no,
+ "Major driver number for analog input (default 0)");
+
+module_param(me4000_dio_major_driver_no, int, 0);
+MODULE_PARM_DESC(me4000_dio_major_driver_no,
+ "Major driver number digital I/O (default 0)");
+
+module_param(me4000_cnt_major_driver_no, int, 0);
+MODULE_PARM_DESC(me4000_cnt_major_driver_no,
+ "Major driver number for counter (default 0)");
+
+module_param(me4000_ext_int_major_driver_no, int, 0);
+MODULE_PARM_DESC(me4000_ext_int_major_driver_no,
+ "Major driver number for external interrupt (default 0)");
+
+/*-----------------------------------------------------------------------------
+ Module stuff
+ ---------------------------------------------------------------------------*/
+int init_module(void);
+void cleanup_module(void);
+
+/*-----------------------------------------------------------------------------
+ Board detection and initialization
+ ---------------------------------------------------------------------------*/
+static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id);
+static int me4000_xilinx_download(me4000_info_t *);
+static int me4000_reset_board(me4000_info_t *);
+
+static void clear_board_info_list(void);
+static int get_registers(struct pci_dev *dev, me4000_info_t * info);
+static int init_board_info(struct pci_dev *dev, me4000_info_t * board_info);
+static int alloc_ao_contexts(me4000_info_t * info);
+static void release_ao_contexts(me4000_info_t * board_info);
+static int alloc_ai_context(me4000_info_t * info);
+static int alloc_dio_context(me4000_info_t * info);
+static int alloc_cnt_context(me4000_info_t * info);
+static int alloc_ext_int_context(me4000_info_t * info);
+
+/*-----------------------------------------------------------------------------
+ Stuff used by all device parts
+ ---------------------------------------------------------------------------*/
+static int me4000_open(struct inode *, struct file *);
+static int me4000_release(struct inode *, struct file *);
+
+static int me4000_get_user_info(me4000_user_info_t *,
+ me4000_info_t * board_info);
+static int me4000_read_procmem(char *, char **, off_t, int, int *, void *);
+
+/*-----------------------------------------------------------------------------
+ Analog output stuff
+ ---------------------------------------------------------------------------*/
+static ssize_t me4000_ao_write_sing(struct file *, const char *, size_t,
+ loff_t *);
+static ssize_t me4000_ao_write_wrap(struct file *, const char *, size_t,
+ loff_t *);
+static ssize_t me4000_ao_write_cont(struct file *, const char *, size_t,
+ loff_t *);
+
+static int me4000_ao_ioctl_sing(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int me4000_ao_ioctl_wrap(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int me4000_ao_ioctl_cont(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+static unsigned int me4000_ao_poll_cont(struct file *, poll_table *);
+static int me4000_ao_fsync_cont(struct file *, struct dentry *, int);
+
+static int me4000_ao_start(unsigned long *, me4000_ao_context_t *);
+static int me4000_ao_stop(me4000_ao_context_t *);
+static int me4000_ao_immediate_stop(me4000_ao_context_t *);
+static int me4000_ao_timer_set_divisor(u32 *, me4000_ao_context_t *);
+static int me4000_ao_preload(me4000_ao_context_t *);
+static int me4000_ao_preload_update(me4000_ao_context_t *);
+static int me4000_ao_ex_trig_set_edge(int *, me4000_ao_context_t *);
+static int me4000_ao_ex_trig_enable(me4000_ao_context_t *);
+static int me4000_ao_ex_trig_disable(me4000_ao_context_t *);
+static int me4000_ao_prepare(me4000_ao_context_t * ao_info);
+static int me4000_ao_reset(me4000_ao_context_t * ao_info);
+static int me4000_ao_enable_do(me4000_ao_context_t *);
+static int me4000_ao_disable_do(me4000_ao_context_t *);
+static int me4000_ao_fsm_state(int *, me4000_ao_context_t *);
+
+static int me4000_ao_simultaneous_ex_trig(me4000_ao_context_t * ao_context);
+static int me4000_ao_simultaneous_sw(me4000_ao_context_t * ao_context);
+static int me4000_ao_simultaneous_disable(me4000_ao_context_t * ao_context);
+static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * channels,
+ me4000_ao_context_t * ao_context);
+
+static int me4000_ao_synchronous_ex_trig(me4000_ao_context_t * ao_context);
+static int me4000_ao_synchronous_sw(me4000_ao_context_t * ao_context);
+static int me4000_ao_synchronous_disable(me4000_ao_context_t * ao_context);
+
+static int me4000_ao_ex_trig_timeout(unsigned long *arg,
+ me4000_ao_context_t * ao_context);
+static int me4000_ao_get_free_buffer(unsigned long *arg,
+ me4000_ao_context_t * ao_context);
+
+/*-----------------------------------------------------------------------------
+ Analog input stuff
+ ---------------------------------------------------------------------------*/
+static int me4000_ai_single(me4000_ai_single_t *, me4000_ai_context_t *);
+static int me4000_ai_ioctl_sing(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+static ssize_t me4000_ai_read(struct file *, char *, size_t, loff_t *);
+static int me4000_ai_ioctl_sw(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static unsigned int me4000_ai_poll(struct file *, poll_table *);
+static int me4000_ai_fasync(int fd, struct file *file_p, int mode);
+
+static int me4000_ai_ioctl_ext(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+static int me4000_ai_prepare(me4000_ai_context_t * ai_context);
+static int me4000_ai_reset(me4000_ai_context_t * ai_context);
+static int me4000_ai_config(me4000_ai_config_t *, me4000_ai_context_t *);
+static int me4000_ai_start(me4000_ai_context_t *);
+static int me4000_ai_start_ex(unsigned long *, me4000_ai_context_t *);
+static int me4000_ai_stop(me4000_ai_context_t *);
+static int me4000_ai_immediate_stop(me4000_ai_context_t *);
+static int me4000_ai_ex_trig_enable(me4000_ai_context_t *);
+static int me4000_ai_ex_trig_disable(me4000_ai_context_t *);
+static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t *,
+ me4000_ai_context_t *);
+static int me4000_ai_sc_setup(me4000_ai_sc_t * arg,
+ me4000_ai_context_t * ai_context);
+static int me4000_ai_offset_enable(me4000_ai_context_t * ai_context);
+static int me4000_ai_offset_disable(me4000_ai_context_t * ai_context);
+static int me4000_ai_fullscale_enable(me4000_ai_context_t * ai_context);
+static int me4000_ai_fullscale_disable(me4000_ai_context_t * ai_context);
+static int me4000_ai_fsm_state(int *arg, me4000_ai_context_t * ai_context);
+static int me4000_ai_get_count_buffer(unsigned long *arg,
+ me4000_ai_context_t * ai_context);
+
+/*-----------------------------------------------------------------------------
+ EEPROM stuff
+ ---------------------------------------------------------------------------*/
+static int me4000_eeprom_read(me4000_eeprom_t * arg,
+ me4000_ai_context_t * ai_context);
+static int me4000_eeprom_write(me4000_eeprom_t * arg,
+ me4000_ai_context_t * ai_context);
+static unsigned short eeprom_read_cmd(me4000_ai_context_t * ai_context,
+ unsigned long cmd, int length);
+static int eeprom_write_cmd(me4000_ai_context_t * ai_context, unsigned long cmd,
+ int length);
+
+/*-----------------------------------------------------------------------------
+ Digital I/O stuff
+ ---------------------------------------------------------------------------*/
+static int me4000_dio_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int me4000_dio_config(me4000_dio_config_t *, me4000_dio_context_t *);
+static int me4000_dio_get_byte(me4000_dio_byte_t *, me4000_dio_context_t *);
+static int me4000_dio_set_byte(me4000_dio_byte_t *, me4000_dio_context_t *);
+static int me4000_dio_reset(me4000_dio_context_t *);
+
+/*-----------------------------------------------------------------------------
+ Counter stuff
+ ---------------------------------------------------------------------------*/
+static int me4000_cnt_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int me4000_cnt_config(me4000_cnt_config_t *, me4000_cnt_context_t *);
+static int me4000_cnt_read(me4000_cnt_t *, me4000_cnt_context_t *);
+static int me4000_cnt_write(me4000_cnt_t *, me4000_cnt_context_t *);
+static int me4000_cnt_reset(me4000_cnt_context_t *);
+
+/*-----------------------------------------------------------------------------
+ External interrupt routines
+ ---------------------------------------------------------------------------*/
+static int me4000_ext_int_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int me4000_ext_int_enable(me4000_ext_int_context_t *);
+static int me4000_ext_int_disable(me4000_ext_int_context_t *);
+static int me4000_ext_int_count(unsigned long *arg,
+ me4000_ext_int_context_t * ext_int_context);
+static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode);
+
+/*-----------------------------------------------------------------------------
+ The interrupt service routines
+ ---------------------------------------------------------------------------*/
+static irqreturn_t me4000_ao_isr(int, void *);
+static irqreturn_t me4000_ai_isr(int, void *);
+static irqreturn_t me4000_ext_int_isr(int, void *);
+
+/*-----------------------------------------------------------------------------
+ Inline functions
+ ---------------------------------------------------------------------------*/
+static int inline me4000_buf_count(me4000_circ_buf_t, int);
+static int inline me4000_buf_space(me4000_circ_buf_t, int);
+static int inline me4000_space_to_end(me4000_circ_buf_t, int);
+static int inline me4000_values_to_end(me4000_circ_buf_t, int);
+
+static void inline me4000_outb(unsigned char value, unsigned long port);
+static void inline me4000_outl(unsigned long value, unsigned long port);
+static unsigned long inline me4000_inl(unsigned long port);
+static unsigned char inline me4000_inb(unsigned long port);
+
+static int me4000_buf_count(me4000_circ_buf_t buf, int size)
+{
+ return ((buf.head - buf.tail) & (size - 1));
+}
+
+static int me4000_buf_space(me4000_circ_buf_t buf, int size)
+{
+ return ((buf.tail - (buf.head + 1)) & (size - 1));
+}
+
+static int me4000_values_to_end(me4000_circ_buf_t buf, int size)
+{
+ int end;
+ int n;
+ end = size - buf.tail;
+ n = (buf.head + end) & (size - 1);
+ return (n < end) ? n : end;
+}
+
+static int me4000_space_to_end(me4000_circ_buf_t buf, int size)
+{
+ int end;
+ int n;
+
+ end = size - 1 - buf.head;
+ n = (end + buf.tail) & (size - 1);
+ return (n <= end) ? n : (end + 1);
+}
+
+static void me4000_outb(unsigned char value, unsigned long port)
+{
+ PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
+ outb(value, port);
+}
+
+static void me4000_outl(unsigned long value, unsigned long port)
+{
+ PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
+ outl(value, port);
+}
+
+static unsigned long me4000_inl(unsigned long port)
+{
+ unsigned long value;
+ value = inl(port);
+ PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
+ return value;
+}
+
+static unsigned char me4000_inb(unsigned long port)
+{
+ unsigned char value;
+ value = inb(port);
+ PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
+ return value;
+}
+
+struct pci_driver me4000_driver = {
+ .name = ME4000_NAME,
+ .id_table = me4000_pci_table,
+ .probe = me4000_probe
+};
+
+static struct file_operations me4000_ao_fops_sing = {
+ owner:THIS_MODULE,
+ write:me4000_ao_write_sing,
+ ioctl:me4000_ao_ioctl_sing,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ao_fops_wrap = {
+ owner:THIS_MODULE,
+ write:me4000_ao_write_wrap,
+ ioctl:me4000_ao_ioctl_wrap,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ao_fops_cont = {
+ owner:THIS_MODULE,
+ write:me4000_ao_write_cont,
+ poll:me4000_ao_poll_cont,
+ ioctl:me4000_ao_ioctl_cont,
+ open:me4000_open,
+ release:me4000_release,
+ fsync:me4000_ao_fsync_cont,
+};
+
+static struct file_operations me4000_ai_fops_sing = {
+ owner:THIS_MODULE,
+ ioctl:me4000_ai_ioctl_sing,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ai_fops_cont_sw = {
+ owner:THIS_MODULE,
+ read:me4000_ai_read,
+ poll:me4000_ai_poll,
+ ioctl:me4000_ai_ioctl_sw,
+ open:me4000_open,
+ release:me4000_release,
+ fasync:me4000_ai_fasync,
+};
+
+static struct file_operations me4000_ai_fops_cont_et = {
+ owner:THIS_MODULE,
+ read:me4000_ai_read,
+ poll:me4000_ai_poll,
+ ioctl:me4000_ai_ioctl_ext,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ai_fops_cont_et_value = {
+ owner:THIS_MODULE,
+ read:me4000_ai_read,
+ poll:me4000_ai_poll,
+ ioctl:me4000_ai_ioctl_ext,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ai_fops_cont_et_chanlist = {
+ owner:THIS_MODULE,
+ read:me4000_ai_read,
+ poll:me4000_ai_poll,
+ ioctl:me4000_ai_ioctl_ext,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_dio_fops = {
+ owner:THIS_MODULE,
+ ioctl:me4000_dio_ioctl,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_cnt_fops = {
+ owner:THIS_MODULE,
+ ioctl:me4000_cnt_ioctl,
+ open:me4000_open,
+ release:me4000_release,
+};
+
+static struct file_operations me4000_ext_int_fops = {
+ owner:THIS_MODULE,
+ ioctl:me4000_ext_int_ioctl,
+ open:me4000_open,
+ release:me4000_release,
+ fasync:me4000_ext_int_fasync,
+};
+
+static struct file_operations *me4000_ao_fops_array[] = {
+ &me4000_ao_fops_sing, // single operations
+ &me4000_ao_fops_wrap, // wraparound operations
+ &me4000_ao_fops_cont, // continous operations
+};
+
+static struct file_operations *me4000_ai_fops_array[] = {
+ &me4000_ai_fops_sing, // single operations
+ &me4000_ai_fops_cont_sw, // continuous operations with software start
+ &me4000_ai_fops_cont_et, // continous operations with external trigger
+ &me4000_ai_fops_cont_et_value, // sample values by external trigger
+ &me4000_ai_fops_cont_et_chanlist, // work through one channel list by external trigger
+};
+
+int __init me4000_init_module(void)
+{
+ int result = 0;
+
+ CALL_PDEBUG("init_module() is executed\n");
+
+ /* Register driver capabilities */
+ result = pci_register_driver(&me4000_driver);
+ PDEBUG("init_module():%d devices detected\n", result);
+ if (result < 0) {
+ printk(KERN_ERR "ME4000:init_module():Can't register driver\n");
+ goto INIT_ERROR_1;
+ }
+
+ /* Allocate major number for analog output */
+ result =
+ register_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME,
+ &me4000_ao_fops_sing);
+ if (result < 0) {
+ printk(KERN_ERR "ME4000:init_module():Can't get AO major no\n");
+ goto INIT_ERROR_2;
+ } else {
+ me4000_ao_major_driver_no = result;
+ }
+ PDEBUG("init_module():Major driver number for AO = %ld\n",
+ me4000_ao_major_driver_no);
+
+ /* Allocate major number for analog input */
+ result =
+ register_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME,
+ &me4000_ai_fops_sing);
+ if (result < 0) {
+ printk(KERN_ERR "ME4000:init_module():Can't get AI major no\n");
+ goto INIT_ERROR_3;
+ } else {
+ me4000_ai_major_driver_no = result;
+ }
+ PDEBUG("init_module():Major driver number for AI = %ld\n",
+ me4000_ai_major_driver_no);
+
+ /* Allocate major number for digital I/O */
+ result =
+ register_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME,
+ &me4000_dio_fops);
+ if (result < 0) {
+ printk(KERN_ERR
+ "ME4000:init_module():Can't get DIO major no\n");
+ goto INIT_ERROR_4;
+ } else {
+ me4000_dio_major_driver_no = result;
+ }
+ PDEBUG("init_module():Major driver number for DIO = %ld\n",
+ me4000_dio_major_driver_no);
+
+ /* Allocate major number for counter */
+ result =
+ register_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME,
+ &me4000_cnt_fops);
+ if (result < 0) {
+ printk(KERN_ERR
+ "ME4000:init_module():Can't get CNT major no\n");
+ goto INIT_ERROR_5;
+ } else {
+ me4000_cnt_major_driver_no = result;
+ }
+ PDEBUG("init_module():Major driver number for CNT = %ld\n",
+ me4000_cnt_major_driver_no);
+
+ /* Allocate major number for external interrupt */
+ result =
+ register_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME,
+ &me4000_ext_int_fops);
+ if (result < 0) {
+ printk(KERN_ERR
+ "ME4000:init_module():Can't get major no for external interrupt\n");
+ goto INIT_ERROR_6;
+ } else {
+ me4000_ext_int_major_driver_no = result;
+ }
+ PDEBUG
+ ("init_module():Major driver number for external interrupt = %ld\n",
+ me4000_ext_int_major_driver_no);
+
+ /* Create the /proc/me4000 entry */
+ if (!create_proc_read_entry
+ ("me4000", 0, NULL, me4000_read_procmem, NULL)) {
+ result = -ENODEV;
+ printk(KERN_ERR
+ "ME4000:init_module():Can't create proc entry\n");
+ goto INIT_ERROR_7;
+ }
+
+ return 0;
+
+ INIT_ERROR_7:
+ unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME);
+
+ INIT_ERROR_6:
+ unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME);
+
+ INIT_ERROR_5:
+ unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME);
+
+ INIT_ERROR_4:
+ unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME);
+
+ INIT_ERROR_3:
+ unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME);
+
+ INIT_ERROR_2:
+ pci_unregister_driver(&me4000_driver);
+ clear_board_info_list();
+
+ INIT_ERROR_1:
+ return result;
+}
+
+module_init(me4000_init_module);
+
+static void clear_board_info_list(void)
+{
+ struct list_head *board_p;
+ struct list_head *dac_p;
+ me4000_info_t *board_info;
+ me4000_ao_context_t *ao_context;
+
+ /* Clear context lists */
+ for (board_p = me4000_board_info_list.next;
+ board_p != &me4000_board_info_list; board_p = board_p->next) {
+ board_info = list_entry(board_p, me4000_info_t, list);
+ /* Clear analog output context list */
+ while (!list_empty(&board_info->ao_context_list)) {
+ dac_p = board_info->ao_context_list.next;
+ ao_context =
+ list_entry(dac_p, me4000_ao_context_t, list);
+ me4000_ao_reset(ao_context);
+ free_irq(ao_context->irq, ao_context);
+ if (ao_context->circ_buf.buf)
+ kfree(ao_context->circ_buf.buf);
+ list_del(dac_p);
+ kfree(ao_context);
+ }
+
+ /* Clear analog input context */
+ if (board_info->ai_context->circ_buf.buf)
+ kfree(board_info->ai_context->circ_buf.buf);
+ kfree(board_info->ai_context);
+
+ /* Clear digital I/O context */
+ kfree(board_info->dio_context);
+
+ /* Clear counter context */
+ kfree(board_info->cnt_context);
+
+ /* Clear external interrupt context */
+ kfree(board_info->ext_int_context);
+ }
+
+ /* Clear the board info list */
+ while (!list_empty(&me4000_board_info_list)) {
+ board_p = me4000_board_info_list.next;
+ board_info = list_entry(board_p, me4000_info_t, list);
+ pci_release_regions(board_info->pci_dev_p);
+ list_del(board_p);
+ kfree(board_info);
+ }
+}
+
+static int get_registers(struct pci_dev *dev, me4000_info_t * board_info)
+{
+
+ /*--------------------------- plx regbase ---------------------------------*/
+
+ board_info->plx_regbase = pci_resource_start(dev, 1);
+ if (board_info->plx_regbase == 0) {
+ printk(KERN_ERR
+ "ME4000:get_registers():PCI base address 1 is not available\n");
+ return -ENODEV;
+ }
+ board_info->plx_regbase_size = pci_resource_len(dev, 1);
+
+ PDEBUG
+ ("get_registers():PLX configuration registers at address 0x%4lX [0x%4lX]\n",
+ board_info->plx_regbase, board_info->plx_regbase_size);
+
+ /*--------------------------- me4000 regbase ------------------------------*/
+
+ board_info->me4000_regbase = pci_resource_start(dev, 2);
+ if (board_info->me4000_regbase == 0) {
+ printk(KERN_ERR
+ "ME4000:get_registers():PCI base address 2 is not available\n");
+ return -ENODEV;
+ }
+ board_info->me4000_regbase_size = pci_resource_len(dev, 2);
+
+ PDEBUG("get_registers():ME4000 registers at address 0x%4lX [0x%4lX]\n",
+ board_info->me4000_regbase, board_info->me4000_regbase_size);
+
+ /*--------------------------- timer regbase ------------------------------*/
+
+ board_info->timer_regbase = pci_resource_start(dev, 3);
+ if (board_info->timer_regbase == 0) {
+ printk(KERN_ERR
+ "ME4000:get_registers():PCI base address 3 is not available\n");
+ return -ENODEV;
+ }
+ board_info->timer_regbase_size = pci_resource_len(dev, 3);
+
+ PDEBUG("get_registers():Timer registers at address 0x%4lX [0x%4lX]\n",
+ board_info->timer_regbase, board_info->timer_regbase_size);
+
+ /*--------------------------- program regbase ------------------------------*/
+
+ board_info->program_regbase = pci_resource_start(dev, 5);
+ if (board_info->program_regbase == 0) {
+ printk(KERN_ERR
+ "get_registers():ME4000:PCI base address 5 is not available\n");
+ return -ENODEV;
+ }
+ board_info->program_regbase_size = pci_resource_len(dev, 5);
+
+ PDEBUG("get_registers():Program registers at address 0x%4lX [0x%4lX]\n",
+ board_info->program_regbase, board_info->program_regbase_size);
+
+ return 0;
+}
+
+static int init_board_info(struct pci_dev *pci_dev_p,
+ me4000_info_t * board_info)
+{
+ int i;
+ int result;
+ struct list_head *board_p;
+ board_info->pci_dev_p = pci_dev_p;
+
+ for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
+ if (me4000_boards[i].device_id == pci_dev_p->device) {
+ board_info->board_p = &me4000_boards[i];
+ break;
+ }
+ }
+ if (i == ME4000_BOARD_VERSIONS) {
+ printk(KERN_ERR
+ "ME4000:init_board_info():Device ID not valid\n");
+ return -ENODEV;
+ }
+
+ /* Get the index of the board in the global list */
+ for (board_p = me4000_board_info_list.next, i = 0;
+ board_p != &me4000_board_info_list; board_p = board_p->next, i++) {
+ if (board_p == &board_info->list) {
+ board_info->board_count = i;
+ break;
+ }
+ }
+ if (board_p == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:init_board_info():Cannot get index of baord\n");
+ return -ENODEV;
+ }
+
+ /* Init list head for analog output contexts */
+ INIT_LIST_HEAD(&board_info->ao_context_list);
+
+ /* Init spin locks */
+ spin_lock_init(&board_info->preload_lock);
+ spin_lock_init(&board_info->ai_ctrl_lock);
+
+ /* Get the serial number */
+ result = pci_read_config_dword(pci_dev_p, 0x2C, &board_info->serial_no);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ printk(KERN_WARNING
+ "ME4000:init_board_info: Can't get serial_no\n");
+ return result;
+ }
+ PDEBUG("init_board_info():serial_no = 0x%x\n", board_info->serial_no);
+
+ /* Get the hardware revision */
+ result =
+ pci_read_config_byte(pci_dev_p, 0x08, &board_info->hw_revision);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ printk(KERN_WARNING
+ "ME4000:init_board_info():Can't get hw_revision\n");
+ return result;
+ }
+ PDEBUG("init_board_info():hw_revision = 0x%x\n",
+ board_info->hw_revision);
+
+ /* Get the vendor id */
+ board_info->vendor_id = pci_dev_p->vendor;
+ PDEBUG("init_board_info():vendor_id = 0x%x\n", board_info->vendor_id);
+
+ /* Get the device id */
+ board_info->device_id = pci_dev_p->device;
+ PDEBUG("init_board_info():device_id = 0x%x\n", board_info->device_id);
+
+ /* Get the pci device number */
+ board_info->pci_dev_no = PCI_FUNC(pci_dev_p->devfn);
+ PDEBUG("init_board_info():pci_func_no = 0x%x\n",
+ board_info->pci_func_no);
+
+ /* Get the pci slot number */
+ board_info->pci_dev_no = PCI_SLOT(pci_dev_p->devfn);
+ PDEBUG("init_board_info():pci_dev_no = 0x%x\n", board_info->pci_dev_no);
+
+ /* Get the pci bus number */
+ board_info->pci_bus_no = pci_dev_p->bus->number;
+ PDEBUG("init_board_info():pci_bus_no = 0x%x\n", board_info->pci_bus_no);
+
+ /* Get the irq assigned to the board */
+ board_info->irq = pci_dev_p->irq;
+ PDEBUG("init_board_info():irq = %d\n", board_info->irq);
+
+ return 0;
+}
+
+static int alloc_ao_contexts(me4000_info_t * info)
+{
+ int i;
+ int err;
+ me4000_ao_context_t *ao_context;
+
+ for (i = 0; i < info->board_p->ao.count; i++) {
+ ao_context = kmalloc(sizeof(me4000_ao_context_t), GFP_KERNEL);
+ if (!ao_context) {
+ printk(KERN_ERR
+ "alloc_ao_contexts():Can't get memory for ao context\n");
+ release_ao_contexts(info);
+ return -ENOMEM;
+ }
+ memset(ao_context, 0, sizeof(me4000_ao_context_t));
+
+ spin_lock_init(&ao_context->use_lock);
+ spin_lock_init(&ao_context->int_lock);
+ ao_context->irq = info->irq;
+ init_waitqueue_head(&ao_context->wait_queue);
+ ao_context->board_info = info;
+
+ if (info->board_p->ao.fifo_count) {
+ /* Allocate circular buffer */
+ ao_context->circ_buf.buf =
+ kmalloc(ME4000_AO_BUFFER_SIZE, GFP_KERNEL);
+ if (!ao_context->circ_buf.buf) {
+ printk(KERN_ERR
+ "alloc_ao_contexts():Can't get circular buffer\n");
+ release_ao_contexts(info);
+ return -ENOMEM;
+ }
+ memset(ao_context->circ_buf.buf, 0,
+ ME4000_AO_BUFFER_SIZE);
+
+ /* Clear the circular buffer */
+ ao_context->circ_buf.head = 0;
+ ao_context->circ_buf.tail = 0;
+ }
+
+ switch (i) {
+ case 0:
+ ao_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AO_00_CTRL_REG;
+ ao_context->status_reg =
+ info->me4000_regbase + ME4000_AO_00_STATUS_REG;
+ ao_context->fifo_reg =
+ info->me4000_regbase + ME4000_AO_00_FIFO_REG;
+ ao_context->single_reg =
+ info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
+ ao_context->timer_reg =
+ info->me4000_regbase + ME4000_AO_00_TIMER_REG;
+ ao_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ ao_context->preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 1:
+ ao_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AO_01_CTRL_REG;
+ ao_context->status_reg =
+ info->me4000_regbase + ME4000_AO_01_STATUS_REG;
+ ao_context->fifo_reg =
+ info->me4000_regbase + ME4000_AO_01_FIFO_REG;
+ ao_context->single_reg =
+ info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
+ ao_context->timer_reg =
+ info->me4000_regbase + ME4000_AO_01_TIMER_REG;
+ ao_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ ao_context->preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 2:
+ ao_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AO_02_CTRL_REG;
+ ao_context->status_reg =
+ info->me4000_regbase + ME4000_AO_02_STATUS_REG;
+ ao_context->fifo_reg =
+ info->me4000_regbase + ME4000_AO_02_FIFO_REG;
+ ao_context->single_reg =
+ info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
+ ao_context->timer_reg =
+ info->me4000_regbase + ME4000_AO_02_TIMER_REG;
+ ao_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ ao_context->preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 3:
+ ao_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AO_03_CTRL_REG;
+ ao_context->status_reg =
+ info->me4000_regbase + ME4000_AO_03_STATUS_REG;
+ ao_context->fifo_reg =
+ info->me4000_regbase + ME4000_AO_03_FIFO_REG;
+ ao_context->single_reg =
+ info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
+ ao_context->timer_reg =
+ info->me4000_regbase + ME4000_AO_03_TIMER_REG;
+ ao_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ ao_context->preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ default:
+ break;
+ }
+
+ if (info->board_p->ao.fifo_count) {
+ /* Request the interrupt line */
+ err =
+ request_irq(ao_context->irq, me4000_ao_isr,
+ IRQF_DISABLED | IRQF_SHARED,
+ ME4000_NAME, ao_context);
+ if (err) {
+ printk(KERN_ERR
+ "alloc_ao_contexts():Can't get interrupt line");
+ if (ao_context->circ_buf.buf)
+ kfree(ao_context->circ_buf.buf);
+ kfree(ao_context);
+ release_ao_contexts(info);
+ return -ENODEV;
+ }
+ }
+
+ list_add_tail(&ao_context->list, &info->ao_context_list);
+ ao_context->index = i;
+ }
+
+ return 0;
+}
+
+static void release_ao_contexts(me4000_info_t * board_info)
+{
+ struct list_head *dac_p;
+ me4000_ao_context_t *ao_context;
+
+ /* Clear analog output context list */
+ while (!list_empty(&board_info->ao_context_list)) {
+ dac_p = board_info->ao_context_list.next;
+ ao_context = list_entry(dac_p, me4000_ao_context_t, list);
+ free_irq(ao_context->irq, ao_context);
+ if (ao_context->circ_buf.buf)
+ kfree(ao_context->circ_buf.buf);
+ list_del(dac_p);
+ kfree(ao_context);
+ }
+}
+
+static int alloc_ai_context(me4000_info_t * info)
+{
+ me4000_ai_context_t *ai_context;
+
+ if (info->board_p->ai.count) {
+ ai_context = kmalloc(sizeof(me4000_ai_context_t), GFP_KERNEL);
+ if (!ai_context) {
+ printk(KERN_ERR
+ "ME4000:alloc_ai_context():Can't get memory for ai context\n");
+ return -ENOMEM;
+ }
+ memset(ai_context, 0, sizeof(me4000_ai_context_t));
+
+ info->ai_context = ai_context;
+
+ spin_lock_init(&ai_context->use_lock);
+ spin_lock_init(&ai_context->int_lock);
+ ai_context->number = 0;
+ ai_context->irq = info->irq;
+ init_waitqueue_head(&ai_context->wait_queue);
+ ai_context->board_info = info;
+
+ ai_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AI_CTRL_REG;
+ ai_context->status_reg =
+ info->me4000_regbase + ME4000_AI_STATUS_REG;
+ ai_context->channel_list_reg =
+ info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
+ ai_context->data_reg =
+ info->me4000_regbase + ME4000_AI_DATA_REG;
+ ai_context->chan_timer_reg =
+ info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
+ ai_context->chan_pre_timer_reg =
+ info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
+ ai_context->scan_timer_low_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
+ ai_context->scan_timer_high_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
+ ai_context->scan_pre_timer_low_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
+ ai_context->scan_pre_timer_high_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
+ ai_context->start_reg =
+ info->me4000_regbase + ME4000_AI_START_REG;
+ ai_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ ai_context->sample_counter_reg =
+ info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
+ }
+
+ return 0;
+}
+
+static int alloc_dio_context(me4000_info_t * info)
+{
+ me4000_dio_context_t *dio_context;
+
+ if (info->board_p->dio.count) {
+ dio_context = kmalloc(sizeof(me4000_dio_context_t), GFP_KERNEL);
+ if (!dio_context) {
+ printk(KERN_ERR
+ "ME4000:alloc_dio_context():Can't get memory for dio context\n");
+ return -ENOMEM;
+ }
+ memset(dio_context, 0, sizeof(me4000_dio_context_t));
+
+ info->dio_context = dio_context;
+
+ spin_lock_init(&dio_context->use_lock);
+ dio_context->board_info = info;
+
+ dio_context->dio_count = info->board_p->dio.count;
+
+ dio_context->dir_reg =
+ info->me4000_regbase + ME4000_DIO_DIR_REG;
+ dio_context->ctrl_reg =
+ info->me4000_regbase + ME4000_DIO_CTRL_REG;
+ dio_context->port_0_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_0_REG;
+ dio_context->port_1_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_1_REG;
+ dio_context->port_2_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_2_REG;
+ dio_context->port_3_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_3_REG;
+ }
+
+ return 0;
+}
+
+static int alloc_cnt_context(me4000_info_t * info)
+{
+ me4000_cnt_context_t *cnt_context;
+
+ if (info->board_p->cnt.count) {
+ cnt_context = kmalloc(sizeof(me4000_cnt_context_t), GFP_KERNEL);
+ if (!cnt_context) {
+ printk(KERN_ERR
+ "ME4000:alloc_cnt_context():Can't get memory for cnt context\n");
+ return -ENOMEM;
+ }
+ memset(cnt_context, 0, sizeof(me4000_cnt_context_t));
+
+ info->cnt_context = cnt_context;
+
+ spin_lock_init(&cnt_context->use_lock);
+ cnt_context->board_info = info;
+
+ cnt_context->ctrl_reg =
+ info->timer_regbase + ME4000_CNT_CTRL_REG;
+ cnt_context->counter_0_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
+ cnt_context->counter_1_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
+ cnt_context->counter_2_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
+ }
+
+ return 0;
+}
+
+static int alloc_ext_int_context(me4000_info_t * info)
+{
+ me4000_ext_int_context_t *ext_int_context;
+
+ if (info->board_p->cnt.count) {
+ ext_int_context =
+ kmalloc(sizeof(me4000_ext_int_context_t), GFP_KERNEL);
+ if (!ext_int_context) {
+ printk(KERN_ERR
+ "ME4000:alloc_ext_int_context():Can't get memory for cnt context\n");
+ return -ENOMEM;
+ }
+ memset(ext_int_context, 0, sizeof(me4000_ext_int_context_t));
+
+ info->ext_int_context = ext_int_context;
+
+ spin_lock_init(&ext_int_context->use_lock);
+ ext_int_context->board_info = info;
+
+ ext_int_context->fasync_ptr = NULL;
+ ext_int_context->irq = info->irq;
+
+ ext_int_context->ctrl_reg =
+ info->me4000_regbase + ME4000_AI_CTRL_REG;
+ ext_int_context->irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ }
+
+ return 0;
+}
+
+static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int result = 0;
+ me4000_info_t *board_info;
+
+ CALL_PDEBUG("me4000_probe() is executed\n");
+
+ /* Allocate structure for board context */
+ board_info = kmalloc(sizeof(me4000_info_t), GFP_KERNEL);
+ if (!board_info) {
+ printk(KERN_ERR
+ "ME4000:Can't get memory for board info structure\n");
+ result = -ENOMEM;
+ goto PROBE_ERROR_1;
+ }
+ memset(board_info, 0, sizeof(me4000_info_t));
+
+ /* Add to global linked list */
+ list_add_tail(&board_info->list, &me4000_board_info_list);
+
+ /* Get the PCI base registers */
+ result = get_registers(dev, board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot get registers\n");
+ goto PROBE_ERROR_2;
+ }
+
+ /* Enable the device */
+ result = pci_enable_device(dev);
+ if (result < 0) {
+ printk(KERN_ERR "me4000_probe():Cannot enable PCI device\n");
+ goto PROBE_ERROR_2;
+ }
+
+ /* Request the PCI register regions */
+ result = pci_request_regions(dev, ME4000_NAME);
+ if (result < 0) {
+ printk(KERN_ERR "me4000_probe():Cannot request I/O regions\n");
+ goto PROBE_ERROR_2;
+ }
+
+ /* Initialize board info */
+ result = init_board_info(dev, board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot init baord info\n");
+ goto PROBE_ERROR_3;
+ }
+
+ /* Download the xilinx firmware */
+ result = me4000_xilinx_download(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe:Can't download firmware\n");
+ goto PROBE_ERROR_3;
+ }
+
+ /* Make a hardware reset */
+ result = me4000_reset_board(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe:Can't reset board\n");
+ goto PROBE_ERROR_3;
+ }
+
+ /* Allocate analog output context structures */
+ result = alloc_ao_contexts(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot allocate ao contexts\n");
+ goto PROBE_ERROR_3;
+ }
+
+ /* Allocate analog input context */
+ result = alloc_ai_context(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot allocate ai context\n");
+ goto PROBE_ERROR_4;
+ }
+
+ /* Allocate digital I/O context */
+ result = alloc_dio_context(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot allocate dio context\n");
+ goto PROBE_ERROR_5;
+ }
+
+ /* Allocate counter context */
+ result = alloc_cnt_context(board_info);
+ if (result) {
+ printk(KERN_ERR "me4000_probe():Cannot allocate cnt context\n");
+ goto PROBE_ERROR_6;
+ }
+
+ /* Allocate external interrupt context */
+ result = alloc_ext_int_context(board_info);
+ if (result) {
+ printk(KERN_ERR
+ "me4000_probe():Cannot allocate ext_int context\n");
+ goto PROBE_ERROR_7;
+ }
+
+ return 0;
+
+ PROBE_ERROR_7:
+ kfree(board_info->cnt_context);
+
+ PROBE_ERROR_6:
+ kfree(board_info->dio_context);
+
+ PROBE_ERROR_5:
+ kfree(board_info->ai_context);
+
+ PROBE_ERROR_4:
+ release_ao_contexts(board_info);
+
+ PROBE_ERROR_3:
+ pci_release_regions(dev);
+
+ PROBE_ERROR_2:
+ list_del(&board_info->list);
+ kfree(board_info);
+
+ PROBE_ERROR_1:
+ return result;
+}
+
+static int me4000_xilinx_download(me4000_info_t * info)
+{
+ int size = 0;
+ u32 value = 0;
+ int idx = 0;
+ unsigned char *firm;
+ wait_queue_head_t queue;
+
+ CALL_PDEBUG("me4000_xilinx_download() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ firm = (info->device_id == 0x4610) ? xilinx_firm_4610 : xilinx_firm;
+
+ /*
+ * Set PLX local interrupt 2 polarity to high.
+ * Interrupt is thrown by init pin of xilinx.
+ */
+ outl(0x10, info->plx_regbase + PLX_INTCSR);
+
+ /* Set /CS and /WRITE of the Xilinx */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value |= 0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+
+ /* Init Xilinx with CS1 */
+ inb(info->program_regbase + 0xC8);
+
+ /* Wait until /INIT pin is set */
+ udelay(20);
+ if (!inl(info->plx_regbase + PLX_INTCSR) & 0x20) {
+ printk(KERN_ERR "me4000_xilinx_download():Can't init Xilinx\n");
+ return -EIO;
+ }
+
+ /* Reset /CS and /WRITE of the Xilinx */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value &= ~0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+
+ /* Download Xilinx firmware */
+ size = (firm[0] << 24) + (firm[1] << 16) + (firm[2] << 8) + firm[3];
+ udelay(10);
+
+ for (idx = 0; idx < size; idx++) {
+ outb(firm[16 + idx], info->program_regbase);
+
+ udelay(10);
+
+ /* Check if BUSY flag is low */
+ if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
+ printk(KERN_ERR
+ "me4000_xilinx_download():Xilinx is still busy (idx = %d)\n",
+ idx);
+ return -EIO;
+ }
+ }
+
+ PDEBUG("me4000_xilinx_download():%d bytes written\n", idx);
+
+ /* If done flag is high download was successful */
+ if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
+ PDEBUG("me4000_xilinx_download():Done flag is set\n");
+ PDEBUG("me4000_xilinx_download():Download was successful\n");
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_xilinx_download():DONE flag is not set\n");
+ printk(KERN_ERR
+ "ME4000:me4000_xilinx_download():Download not succesful\n");
+ return -EIO;
+ }
+
+ /* Set /CS and /WRITE */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value |= 0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+
+ return 0;
+}
+
+static int me4000_reset_board(me4000_info_t * info)
+{
+ unsigned long icr;
+
+ CALL_PDEBUG("me4000_reset_board() is executed\n");
+
+ /* Make a hardware reset */
+ icr = me4000_inl(info->plx_regbase + PLX_ICR);
+ icr |= 0x40000000;
+ me4000_outl(icr, info->plx_regbase + PLX_ICR);
+ icr &= ~0x40000000;
+ me4000_outl(icr, info->plx_regbase + PLX_ICR);
+
+ /* Set both stop bits in the analog input control register */
+ me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AI_CTRL_REG);
+
+ /* Set both stop bits in the analog output control register */
+ me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_00_CTRL_REG);
+ me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_01_CTRL_REG);
+ me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_02_CTRL_REG);
+ me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_03_CTRL_REG);
+
+ /* 0x8000 to the DACs means an output voltage of 0V */
+ me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
+ me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
+ me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
+ me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
+
+ /* Enable interrupts on the PLX */
+ me4000_outl(0x43, info->plx_regbase + PLX_INTCSR);
+
+ /* Set the adustment register for AO demux */
+ me4000_outl(ME4000_AO_DEMUX_ADJUST_VALUE,
+ info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
+
+ /* Set digital I/O direction for port 0 to output on isolated versions */
+ if (!(me4000_inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) {
+ me4000_outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
+ }
+
+ return 0;
+}
+
+static int me4000_open(struct inode *inode_p, struct file *file_p)
+{
+ int board, dev, mode;
+ int err = 0;
+ int i;
+ struct list_head *ptr;
+ me4000_info_t *board_info = NULL;
+ me4000_ao_context_t *ao_context = NULL;
+ me4000_ai_context_t *ai_context = NULL;
+ me4000_dio_context_t *dio_context = NULL;
+ me4000_cnt_context_t *cnt_context = NULL;
+ me4000_ext_int_context_t *ext_int_context = NULL;
+
+ CALL_PDEBUG("me4000_open() is executed\n");
+
+ /* Analog output */
+ if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) {
+ board = AO_BOARD(inode_p->i_rdev);
+ dev = AO_PORT(inode_p->i_rdev);
+ mode = AO_MODE(inode_p->i_rdev);
+
+ PDEBUG("me4000_open():board = %d ao = %d mode = %d\n", board,
+ dev, mode);
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next, i = 0;
+ ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+ if (i == board)
+ break;
+ }
+
+ if (ptr == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Board %d not in device list\n",
+ board);
+ return -ENODEV;
+ }
+
+ /* Search for the dac context */
+ for (ptr = board_info->ao_context_list.next, i = 0;
+ ptr != &board_info->ao_context_list;
+ ptr = ptr->next, i++) {
+ ao_context = list_entry(ptr, me4000_ao_context_t, list);
+ if (i == dev)
+ break;
+ }
+
+ if (ptr == &board_info->ao_context_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Device %d not in device list\n",
+ dev);
+ return -ENODEV;
+ }
+
+ /* Check if mode is valid */
+ if (mode > 2) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Mode is not valid\n");
+ return -ENODEV;
+ }
+
+ /* Check if mode is valid for this AO */
+ if ((mode != ME4000_AO_CONV_MODE_SINGLE)
+ && (dev >= board_info->board_p->ao.fifo_count)) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():AO %d only in single mode available\n",
+ dev);
+ return -ENODEV;
+ }
+
+ /* Check if already opened */
+ spin_lock(&ao_context->use_lock);
+ if (ao_context->dac_in_use) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():AO %d already in use\n",
+ dev);
+ spin_unlock(&ao_context->use_lock);
+ return -EBUSY;
+ }
+ ao_context->dac_in_use = 1;
+ spin_unlock(&ao_context->use_lock);
+
+ ao_context->mode = mode;
+
+ /* Hold the context in private data */
+ file_p->private_data = ao_context;
+
+ /* Set file operations pointer */
+ file_p->f_op = me4000_ao_fops_array[mode];
+
+ err = me4000_ao_prepare(ao_context);
+ if (err) {
+ ao_context->dac_in_use = 0;
+ return 1;
+ }
+ }
+ /* Analog input */
+ else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) {
+ board = AI_BOARD(inode_p->i_rdev);
+ mode = AI_MODE(inode_p->i_rdev);
+
+ PDEBUG("me4000_open():ai board = %d mode = %d\n", board, mode);
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next, i = 0;
+ ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+ if (i == board)
+ break;
+ }
+
+ if (ptr == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Board %d not in device list\n",
+ board);
+ return -ENODEV;
+ }
+
+ ai_context = board_info->ai_context;
+
+ /* Check if mode is valid */
+ if (mode > 5) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Mode is not valid\n");
+ return -EINVAL;
+ }
+
+ /* Check if already opened */
+ spin_lock(&ai_context->use_lock);
+ if (ai_context->in_use) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():AI already in use\n");
+ spin_unlock(&ai_context->use_lock);
+ return -EBUSY;
+ }
+ ai_context->in_use = 1;
+ spin_unlock(&ai_context->use_lock);
+
+ ai_context->mode = mode;
+
+ /* Hold the context in private data */
+ file_p->private_data = ai_context;
+
+ /* Set file operations pointer */
+ file_p->f_op = me4000_ai_fops_array[mode];
+
+ /* Prepare analog input */
+ me4000_ai_prepare(ai_context);
+ }
+ /* Digital I/O */
+ else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) {
+ board = DIO_BOARD(inode_p->i_rdev);
+ dev = 0;
+ mode = 0;
+
+ PDEBUG("me4000_open():board = %d\n", board);
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next;
+ ptr != &me4000_board_info_list; ptr = ptr->next) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+ if (board_info->board_count == board)
+ break;
+ }
+
+ if (ptr == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Board %d not in device list\n",
+ board);
+ return -ENODEV;
+ }
+
+ /* Search for the dio context */
+ dio_context = board_info->dio_context;
+
+ /* Check if already opened */
+ spin_lock(&dio_context->use_lock);
+ if (dio_context->in_use) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():DIO already in use\n");
+ spin_unlock(&dio_context->use_lock);
+ return -EBUSY;
+ }
+ dio_context->in_use = 1;
+ spin_unlock(&dio_context->use_lock);
+
+ /* Hold the context in private data */
+ file_p->private_data = dio_context;
+
+ /* Set file operations pointer to single functions */
+ file_p->f_op = &me4000_dio_fops;
+
+ //me4000_dio_reset(dio_context);
+ }
+ /* Counters */
+ else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) {
+ board = CNT_BOARD(inode_p->i_rdev);
+ dev = 0;
+ mode = 0;
+
+ PDEBUG("me4000_open():board = %d\n", board);
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next;
+ ptr != &me4000_board_info_list; ptr = ptr->next) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+ if (board_info->board_count == board)
+ break;
+ }
+
+ if (ptr == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Board %d not in device list\n",
+ board);
+ return -ENODEV;
+ }
+
+ /* Get the cnt context */
+ cnt_context = board_info->cnt_context;
+
+ /* Check if already opened */
+ spin_lock(&cnt_context->use_lock);
+ if (cnt_context->in_use) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():CNT already in use\n");
+ spin_unlock(&cnt_context->use_lock);
+ return -EBUSY;
+ }
+ cnt_context->in_use = 1;
+ spin_unlock(&cnt_context->use_lock);
+
+ /* Hold the context in private data */
+ file_p->private_data = cnt_context;
+
+ /* Set file operations pointer to single functions */
+ file_p->f_op = &me4000_cnt_fops;
+ }
+ /* External Interrupt */
+ else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) {
+ board = EXT_INT_BOARD(inode_p->i_rdev);
+ dev = 0;
+ mode = 0;
+
+ PDEBUG("me4000_open():board = %d\n", board);
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next;
+ ptr != &me4000_board_info_list; ptr = ptr->next) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+ if (board_info->board_count == board)
+ break;
+ }
+
+ if (ptr == &me4000_board_info_list) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Board %d not in device list\n",
+ board);
+ return -ENODEV;
+ }
+
+ /* Get the external interrupt context */
+ ext_int_context = board_info->ext_int_context;
+
+ /* Check if already opened */
+ spin_lock(&cnt_context->use_lock);
+ if (ext_int_context->in_use) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():External interrupt already in use\n");
+ spin_unlock(&ext_int_context->use_lock);
+ return -EBUSY;
+ }
+ ext_int_context->in_use = 1;
+ spin_unlock(&ext_int_context->use_lock);
+
+ /* Hold the context in private data */
+ file_p->private_data = ext_int_context;
+
+ /* Set file operations pointer to single functions */
+ file_p->f_op = &me4000_ext_int_fops;
+
+ /* Request the interrupt line */
+ err =
+ request_irq(ext_int_context->irq, me4000_ext_int_isr,
+ IRQF_DISABLED | IRQF_SHARED, ME4000_NAME,
+ ext_int_context);
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_open():Can't get interrupt line");
+ ext_int_context->in_use = 0;
+ return -ENODEV;
+ }
+
+ /* Reset the counter */
+ me4000_ext_int_disable(ext_int_context);
+ } else {
+ printk(KERN_ERR "ME4000:me4000_open():Major number unknown\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_release(struct inode *inode_p, struct file *file_p)
+{
+ me4000_ao_context_t *ao_context;
+ me4000_ai_context_t *ai_context;
+ me4000_dio_context_t *dio_context;
+ me4000_cnt_context_t *cnt_context;
+ me4000_ext_int_context_t *ext_int_context;
+
+ CALL_PDEBUG("me4000_release() is executed\n");
+
+ if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) {
+ ao_context = file_p->private_data;
+
+ /* Mark DAC as unused */
+ ao_context->dac_in_use = 0;
+ } else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) {
+ ai_context = file_p->private_data;
+
+ /* Reset the analog input */
+ me4000_ai_reset(ai_context);
+
+ /* Free the interrupt and the circular buffer */
+ if (ai_context->mode) {
+ free_irq(ai_context->irq, ai_context);
+ kfree(ai_context->circ_buf.buf);
+ ai_context->circ_buf.buf = NULL;
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+ }
+
+ /* Mark AI as unused */
+ ai_context->in_use = 0;
+ } else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) {
+ dio_context = file_p->private_data;
+
+ /* Mark digital I/O as unused */
+ dio_context->in_use = 0;
+ } else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) {
+ cnt_context = file_p->private_data;
+
+ /* Mark counters as unused */
+ cnt_context->in_use = 0;
+ } else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) {
+ ext_int_context = file_p->private_data;
+
+ /* Disable the externel interrupt */
+ me4000_ext_int_disable(ext_int_context);
+
+ free_irq(ext_int_context->irq, ext_int_context);
+
+ /* Delete the fasync structure and free memory */
+ me4000_ext_int_fasync(0, file_p, 0);
+
+ /* Mark as unused */
+ ext_int_context->in_use = 0;
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_release():Major number unknown\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*------------------------------- Analog output stuff --------------------------------------*/
+
+static int me4000_ao_prepare(me4000_ao_context_t * ao_context)
+{
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_prepare() is executed\n");
+
+ if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) {
+ /* Only do anything if not already in the correct mode */
+ unsigned long mode = me4000_inl(ao_context->ctrl_reg);
+ if ((mode & ME4000_AO_CONV_MODE_CONTINUOUS)
+ && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) {
+ return 0;
+ }
+
+ /* Stop any conversion */
+ me4000_ao_immediate_stop(ao_context);
+
+ /* Set the control register to default state */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS |
+ ME4000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
+ ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ /* Set to fastest sample rate */
+ me4000_outl(65, ao_context->timer_reg);
+ } else if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) {
+ /* Only do anything if not already in the correct mode */
+ unsigned long mode = me4000_inl(ao_context->ctrl_reg);
+ if ((mode & ME4000_AO_CONV_MODE_WRAPAROUND)
+ && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) {
+ return 0;
+ }
+
+ /* Stop any conversion */
+ me4000_ao_immediate_stop(ao_context);
+
+ /* Set the control register to default state */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND |
+ ME4000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
+ ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ /* Set to fastest sample rate */
+ me4000_outl(65, ao_context->timer_reg);
+ } else if (ao_context->mode == ME4000_AO_CONV_MODE_SINGLE) {
+ /* Only do anything if not already in the correct mode */
+ unsigned long mode = me4000_inl(ao_context->ctrl_reg);
+ if (!
+ (mode &
+ (ME4000_AO_CONV_MODE_WRAPAROUND |
+ ME4000_AO_CONV_MODE_CONTINUOUS))) {
+ return 0;
+ }
+
+ /* Stop any conversion */
+ me4000_ao_immediate_stop(ao_context);
+
+ /* Clear the control register */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ me4000_outl(0x0, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ /* Set voltage to 0V */
+ me4000_outl(0x8000, ao_context->single_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_prepare():Invalid mode specified\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_ao_reset(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_reset() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) {
+ /*
+ * First stop conversion of the DAC before reconfigure.
+ * This is essantial, cause of the state machine.
+ * If not stopped before configuring mode, it could
+ * walk in a undefined state.
+ */
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+
+ while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ sleep_on_timeout(&queue, 1);
+ }
+
+ /* Set to transparent mode */
+ me4000_ao_simultaneous_disable(ao_context);
+
+ /* Set to single mode in order to set default voltage */
+ me4000_outl(0x0, ao_context->ctrl_reg);
+
+ /* Set voltage to 0V */
+ me4000_outl(0x8000, ao_context->single_reg);
+
+ /* Set to fastest sample rate */
+ me4000_outl(65, ao_context->timer_reg);
+
+ /* Set the original mode and enable FIFO */
+ me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND |
+ ME4000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
+ ao_context->ctrl_reg);
+ } else if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) {
+ /*
+ * First stop conversion of the DAC before reconfigure.
+ * This is essantial, cause of the state machine.
+ * If not stopped before configuring mode, it could
+ * walk in a undefined state.
+ */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_STOP;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ sleep_on_timeout(&queue, 1);
+ }
+
+ /* Clear the circular buffer */
+ ao_context->circ_buf.head = 0;
+ ao_context->circ_buf.tail = 0;
+
+ /* Set to transparent mode */
+ me4000_ao_simultaneous_disable(ao_context);
+
+ /* Set to single mode in order to set default voltage */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ me4000_outl(0x0, ao_context->ctrl_reg);
+
+ /* Set voltage to 0V */
+ me4000_outl(0x8000, ao_context->single_reg);
+
+ /* Set to fastest sample rate */
+ me4000_outl(65, ao_context->timer_reg);
+
+ /* Set the original mode and enable FIFO */
+ me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS |
+ ME4000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
+ ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ } else {
+ /* Set to transparent mode */
+ me4000_ao_simultaneous_disable(ao_context);
+
+ /* Set voltage to 0V */
+ me4000_outl(0x8000, ao_context->single_reg);
+ }
+
+ return 0;
+}
+
+static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff,
+ size_t cnt, loff_t * offp)
+{
+ me4000_ao_context_t *ao_context = filep->private_data;
+ u32 value;
+ const u16 *buffer = (const u16 *)buff;
+
+ CALL_PDEBUG("me4000_ao_write_sing() is executed\n");
+
+ if (cnt != 2) {
+ printk(KERN_ERR
+ "me4000_ao_write_sing():Write count is not 2\n");
+ return -EINVAL;
+ }
+
+ if (get_user(value, buffer)) {
+ printk(KERN_ERR
+ "me4000_ao_write_sing():Cannot copy data from user\n");
+ return -EFAULT;
+ }
+
+ me4000_outl(value, ao_context->single_reg);
+
+ return 2;
+}
+
+static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
+ size_t cnt, loff_t * offp)
+{
+ me4000_ao_context_t *ao_context = filep->private_data;
+ size_t i;
+ u32 value;
+ u32 tmp;
+ const u16 *buffer = (const u16 *)buff;
+ size_t count = cnt / 2;
+
+ CALL_PDEBUG("me4000_ao_write_wrap() is executed\n");
+
+ /* Check if a conversion is already running */
+ if (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_write_wrap():There is already a conversion running\n");
+ return -EBUSY;
+ }
+
+ if (count > ME4000_AO_FIFO_COUNT) {
+ printk(KERN_ERR
+ "me4000_ao_write_wrap():Can't load more than %d values\n",
+ ME4000_AO_FIFO_COUNT);
+ return -ENOSPC;
+ }
+
+ /* Reset the FIFO */
+ tmp = inl(ao_context->ctrl_reg);
+ tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(tmp, ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(tmp, ao_context->ctrl_reg);
+
+ for (i = 0; i < count; i++) {
+ if (get_user(value, buffer + i)) {
+ printk(KERN_ERR
+ "me4000_ao_write_single():Cannot copy data from user\n");
+ return -EFAULT;
+ }
+ if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG)
+ || ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG))
+ value = value << 16;
+ outl(value, ao_context->fifo_reg);
+ }
+ CALL_PDEBUG("me4000_ao_write_wrap() is leaved with %d\n", i * 2);
+
+ return i * 2;
+}
+
+static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff,
+ size_t cnt, loff_t * offp)
+{
+ me4000_ao_context_t *ao_context = filep->private_data;
+ const u16 *buffer = (const u16 *)buff;
+ size_t count = cnt / 2;
+ unsigned long flags;
+ u32 tmp;
+ int c = 0;
+ int k = 0;
+ int ret = 0;
+ u16 svalue;
+ u32 lvalue;
+ int i;
+ wait_queue_head_t queue;
+
+ CALL_PDEBUG("me4000_ao_write_cont() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Check count */
+ if (count <= 0) {
+ PDEBUG("me4000_ao_write_cont():Count is 0\n");
+ return 0;
+ }
+
+ if (filep->f_flags & O_APPEND) {
+ PDEBUG("me4000_ao_write_cont():Append data to data stream\n");
+ while (count > 0) {
+ if (filep->f_flags & O_NONBLOCK) {
+ if (ao_context->pipe_flag) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_write_cont():Broken pipe in nonblocking write\n");
+ return -EPIPE;
+ }
+ c = me4000_space_to_end(ao_context->circ_buf,
+ ME4000_AO_BUFFER_COUNT);
+ if (!c) {
+ PDEBUG
+ ("me4000_ao_write_cont():Returning from nonblocking write\n");
+ break;
+ }
+ } else {
+ wait_event_interruptible(ao_context->wait_queue,
+ (c =
+ me4000_space_to_end
+ (ao_context->circ_buf,
+ ME4000_AO_BUFFER_COUNT)));
+ if (ao_context->pipe_flag) {
+ printk(KERN_ERR
+ "me4000_ao_write_cont():Broken pipe in blocking write\n");
+ return -EPIPE;
+ }
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ao_write_cont():Wait for free buffer interrupted from signal\n");
+ return -EINTR;
+ }
+ }
+
+ PDEBUG("me4000_ao_write_cont():Space to end = %d\n", c);
+
+ /* Only able to write size of free buffer or size of count */
+ if (count < c)
+ c = count;
+
+ k = 2 * c;
+ k -= copy_from_user(ao_context->circ_buf.buf +
+ ao_context->circ_buf.head, buffer,
+ k);
+ c = k / 2;
+ PDEBUG
+ ("me4000_ao_write_cont():Copy %d values from user space\n",
+ c);
+
+ if (!c)
+ return -EFAULT;
+
+ ao_context->circ_buf.head =
+ (ao_context->circ_buf.head +
+ c) & (ME4000_AO_BUFFER_COUNT - 1);
+ buffer += c;
+ count -= c;
+ ret += c;
+
+ /* Values are now available so enable interrupts */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ if (me4000_buf_count
+ (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ }
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ }
+
+ /* Wait until the state machine is stopped if O_SYNC is set */
+ if (filep->f_flags & O_SYNC) {
+ while (inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (ao_context->pipe_flag) {
+ PDEBUG
+ ("me4000_ao_write_cont():Broken pipe detected after sync\n");
+ return -EPIPE;
+ }
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ao_write_cont():Wait on state machine after sync interrupted\n");
+ return -EINTR;
+ }
+ }
+ }
+ } else {
+ PDEBUG("me4000_ao_write_cont():Preload DAC FIFO\n");
+ if ((me4000_inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM)) {
+ printk(KERN_ERR
+ "me4000_ao_write_cont():Can't Preload DAC FIFO while conversion is running\n");
+ return -EBUSY;
+ }
+
+ /* Clear the FIFO */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4000_AO_CTRL_BIT_ENABLE_IRQ);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ /* Clear the circular buffer */
+ ao_context->circ_buf.head = 0;
+ ao_context->circ_buf.tail = 0;
+
+ /* Reset the broken pipe flag */
+ ao_context->pipe_flag = 0;
+
+ /* Only able to write size of fifo or count */
+ c = ME4000_AO_FIFO_COUNT;
+ if (count < c)
+ c = count;
+
+ PDEBUG
+ ("me4000_ao_write_cont():Write %d values to DAC on 0x%lX\n",
+ c, ao_context->fifo_reg);
+
+ /* Write values to the fifo */
+ for (i = 0; i < c; i++) {
+ if (get_user(svalue, buffer))
+ return -EFAULT;
+
+ if (((ao_context->fifo_reg & 0xFF) ==
+ ME4000_AO_01_FIFO_REG)
+ || ((ao_context->fifo_reg & 0xFF) ==
+ ME4000_AO_03_FIFO_REG)) {
+ lvalue = ((u32) svalue) << 16;
+ } else
+ lvalue = (u32) svalue;
+
+ outl(lvalue, ao_context->fifo_reg);
+ buffer++;
+ }
+ count -= c;
+ ret += c;
+
+ while (1) {
+ /* Get free buffer */
+ c = me4000_space_to_end(ao_context->circ_buf,
+ ME4000_AO_BUFFER_COUNT);
+
+ if (c == 0)
+ return (2 * ret);
+
+ /* Only able to write size of free buffer or size of count */
+ if (count < c)
+ c = count;
+
+ /* If count = 0 return to user */
+ if (c <= 0) {
+ PDEBUG
+ ("me4000_ao_write_cont():Count reached 0\n");
+ break;
+ }
+
+ k = 2 * c;
+ k -= copy_from_user(ao_context->circ_buf.buf +
+ ao_context->circ_buf.head, buffer,
+ k);
+ c = k / 2;
+ PDEBUG
+ ("me4000_ao_write_cont():Wrote %d values to buffer\n",
+ c);
+
+ if (!c)
+ return -EFAULT;
+
+ ao_context->circ_buf.head =
+ (ao_context->circ_buf.head +
+ c) & (ME4000_AO_BUFFER_COUNT - 1);
+ buffer += c;
+ count -= c;
+ ret += c;
+
+ /* If values in the buffer are available so enable interrupts */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ if (me4000_buf_count
+ (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
+ PDEBUG
+ ("me4000_ao_write_cont():Enable Interrupts\n");
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ }
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ }
+ }
+
+ if (filep->f_flags & O_NONBLOCK) {
+ return (ret == 0) ? -EAGAIN : 2 * ret;
+ }
+
+ return 2 * ret;
+}
+
+static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table * wait)
+{
+ me4000_ao_context_t *ao_context;
+ unsigned long mask = 0;
+
+ CALL_PDEBUG("me4000_ao_poll_cont() is executed\n");
+
+ ao_context = file_p->private_data;
+
+ poll_wait(file_p, &ao_context->wait_queue, wait);
+
+ /* Get free buffer */
+ if (me4000_space_to_end(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT))
+ mask |= POLLOUT | POLLWRNORM;
+
+ CALL_PDEBUG("me4000_ao_poll_cont():Return mask %lX\n", mask);
+
+ return mask;
+}
+
+static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p,
+ int datasync)
+{
+ me4000_ao_context_t *ao_context;
+ wait_queue_head_t queue;
+
+ CALL_PDEBUG("me4000_ao_fsync_cont() is executed\n");
+
+ ao_context = file_p->private_data;
+ init_waitqueue_head(&queue);
+
+ while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (ao_context->pipe_flag) {
+ printk(KERN_ERR
+ "me4000_ao_fsync_cont():Broken pipe detected\n");
+ return -EPIPE;
+ }
+
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ao_fsync_cont():Wait on state machine interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ return 0;
+}
+
+static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ao_context_t *ao_context;
+
+ CALL_PDEBUG("me4000_ao_ioctl_sing() is executed\n");
+
+ ao_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ return -ENOTTY;
+ PDEBUG("me4000_ao_ioctl_sing():Wrong magic number\n");
+ }
+
+ switch (service) {
+ case ME4000_AO_EX_TRIG_SETUP:
+ return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
+ case ME4000_AO_EX_TRIG_ENABLE:
+ return me4000_ao_ex_trig_enable(ao_context);
+ case ME4000_AO_EX_TRIG_DISABLE:
+ return me4000_ao_ex_trig_disable(ao_context);
+ case ME4000_AO_PRELOAD:
+ return me4000_ao_preload(ao_context);
+ case ME4000_AO_PRELOAD_UPDATE:
+ return me4000_ao_preload_update(ao_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ao_context->board_info);
+ case ME4000_AO_SIMULTANEOUS_EX_TRIG:
+ return me4000_ao_simultaneous_ex_trig(ao_context);
+ case ME4000_AO_SIMULTANEOUS_SW:
+ return me4000_ao_simultaneous_sw(ao_context);
+ case ME4000_AO_SIMULTANEOUS_DISABLE:
+ return me4000_ao_simultaneous_disable(ao_context);
+ case ME4000_AO_SIMULTANEOUS_UPDATE:
+ return
+ me4000_ao_simultaneous_update((me4000_ao_channel_list_t *)
+ arg, ao_context);
+ case ME4000_AO_EX_TRIG_TIMEOUT:
+ return me4000_ao_ex_trig_timeout((unsigned long *)arg,
+ ao_context);
+ case ME4000_AO_DISABLE_DO:
+ return me4000_ao_disable_do(ao_context);
+ default:
+ printk(KERN_ERR
+ "me4000_ao_ioctl_sing():Service number invalid\n");
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ao_context_t *ao_context;
+
+ CALL_PDEBUG("me4000_ao_ioctl_wrap() is executed\n");
+
+ ao_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ return -ENOTTY;
+ PDEBUG("me4000_ao_ioctl_wrap():Wrong magic number\n");
+ }
+
+ switch (service) {
+ case ME4000_AO_START:
+ return me4000_ao_start((unsigned long *)arg, ao_context);
+ case ME4000_AO_STOP:
+ return me4000_ao_stop(ao_context);
+ case ME4000_AO_IMMEDIATE_STOP:
+ return me4000_ao_immediate_stop(ao_context);
+ case ME4000_AO_RESET:
+ return me4000_ao_reset(ao_context);
+ case ME4000_AO_TIMER_SET_DIVISOR:
+ return me4000_ao_timer_set_divisor((u32 *) arg, ao_context);
+ case ME4000_AO_EX_TRIG_SETUP:
+ return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
+ case ME4000_AO_EX_TRIG_ENABLE:
+ return me4000_ao_ex_trig_enable(ao_context);
+ case ME4000_AO_EX_TRIG_DISABLE:
+ return me4000_ao_ex_trig_disable(ao_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ao_context->board_info);
+ case ME4000_AO_FSM_STATE:
+ return me4000_ao_fsm_state((int *)arg, ao_context);
+ case ME4000_AO_ENABLE_DO:
+ return me4000_ao_enable_do(ao_context);
+ case ME4000_AO_DISABLE_DO:
+ return me4000_ao_disable_do(ao_context);
+ case ME4000_AO_SYNCHRONOUS_EX_TRIG:
+ return me4000_ao_synchronous_ex_trig(ao_context);
+ case ME4000_AO_SYNCHRONOUS_SW:
+ return me4000_ao_synchronous_sw(ao_context);
+ case ME4000_AO_SYNCHRONOUS_DISABLE:
+ return me4000_ao_synchronous_disable(ao_context);
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ao_context_t *ao_context;
+
+ CALL_PDEBUG("me4000_ao_ioctl_cont() is executed\n");
+
+ ao_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ return -ENOTTY;
+ PDEBUG("me4000_ao_ioctl_cont():Wrong magic number\n");
+ }
+
+ switch (service) {
+ case ME4000_AO_START:
+ return me4000_ao_start((unsigned long *)arg, ao_context);
+ case ME4000_AO_STOP:
+ return me4000_ao_stop(ao_context);
+ case ME4000_AO_IMMEDIATE_STOP:
+ return me4000_ao_immediate_stop(ao_context);
+ case ME4000_AO_RESET:
+ return me4000_ao_reset(ao_context);
+ case ME4000_AO_TIMER_SET_DIVISOR:
+ return me4000_ao_timer_set_divisor((u32 *) arg, ao_context);
+ case ME4000_AO_EX_TRIG_SETUP:
+ return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
+ case ME4000_AO_EX_TRIG_ENABLE:
+ return me4000_ao_ex_trig_enable(ao_context);
+ case ME4000_AO_EX_TRIG_DISABLE:
+ return me4000_ao_ex_trig_disable(ao_context);
+ case ME4000_AO_ENABLE_DO:
+ return me4000_ao_enable_do(ao_context);
+ case ME4000_AO_DISABLE_DO:
+ return me4000_ao_disable_do(ao_context);
+ case ME4000_AO_FSM_STATE:
+ return me4000_ao_fsm_state((int *)arg, ao_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ao_context->board_info);
+ case ME4000_AO_SYNCHRONOUS_EX_TRIG:
+ return me4000_ao_synchronous_ex_trig(ao_context);
+ case ME4000_AO_SYNCHRONOUS_SW:
+ return me4000_ao_synchronous_sw(ao_context);
+ case ME4000_AO_SYNCHRONOUS_DISABLE:
+ return me4000_ao_synchronous_disable(ao_context);
+ case ME4000_AO_GET_FREE_BUFFER:
+ return me4000_ao_get_free_buffer((unsigned long *)arg,
+ ao_context);
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ao_start(unsigned long *arg, me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long ref;
+ unsigned long timeout;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_start() is executed\n");
+
+ if (get_user(timeout, arg)) {
+ printk(KERN_ERR
+ "me4000_ao_start():Cannot copy data from user\n");
+ return -EFAULT;
+ }
+
+ init_waitqueue_head(&queue);
+
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = inl(ao_context->ctrl_reg);
+ tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) {
+ if (timeout) {
+ ref = jiffies;
+ while (!
+ (inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_start():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space
+ printk(KERN_ERR
+ "ME4000:me4000_ao_start():Timeout reached\n");
+ return -EIO;
+ }
+ }
+ }
+ } else {
+ me4000_outl(0x8000, ao_context->single_reg);
+ }
+
+ return 0;
+}
+
+static int me4000_ao_stop(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long flags;
+
+ init_waitqueue_head(&queue);
+
+ CALL_PDEBUG("me4000_ao_stop() is executed\n");
+
+ /* Set the stop bit */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_STOP;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ao_stop():Wait on state machine after stop interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ /* Clear the stop bit */
+ //tmp &= ~ME4000_AO_CTRL_BIT_STOP;
+ //me4000_outl(tmp, ao_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ao_immediate_stop(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long flags;
+
+ init_waitqueue_head(&queue);
+
+ CALL_PDEBUG("me4000_ao_immediate_stop() is executed\n");
+
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ao_immediate_stop():Wait on state machine after stop interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ /* Clear the stop bits */
+ //tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
+ //me4000_outl(tmp, ao_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ao_timer_set_divisor(u32 * arg,
+ me4000_ao_context_t * ao_context)
+{
+ u32 divisor;
+ u32 tmp;
+
+ CALL_PDEBUG("me4000_ao_timer set_divisor() is executed\n");
+
+ if (get_user(divisor, arg))
+ return -EFAULT;
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_timer_set_divisor():Can't set timer while DAC is running\n");
+ return -EBUSY;
+ }
+
+ PDEBUG("me4000_ao_timer set_divisor():Divisor from user = %d\n",
+ divisor);
+
+ /* Check if the divisor is right. ME4000_AO_MIN_TICKS is the lowest */
+ if (divisor < ME4000_AO_MIN_TICKS) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_timer set_divisor():Divisor to low\n");
+ return -EINVAL;
+ }
+
+ /* Fix bug in Firmware */
+ divisor -= 2;
+
+ PDEBUG("me4000_ao_timer set_divisor():Divisor to HW = %d\n", divisor);
+
+ /* Write the divisor */
+ me4000_outl(divisor, ao_context->timer_reg);
+
+ return 0;
+}
+
+static int me4000_ao_ex_trig_set_edge(int *arg,
+ me4000_ao_context_t * ao_context)
+{
+ int mode;
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_ex_trig_set_edge() is executed\n");
+
+ if (get_user(mode, arg))
+ return -EFAULT;
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_ex_trig_set_edge():Can't set trigger while DAC is running\n");
+ return -EBUSY;
+ }
+
+ if (mode == ME4000_AO_TRIGGER_EXT_EDGE_RISING) {
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4000_AO_CTRL_BIT_EX_TRIG_BOTH);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_FALLING) {
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp &= ~ME4000_AO_CTRL_BIT_EX_TRIG_BOTH;
+ tmp |= ME4000_AO_CTRL_BIT_EX_TRIG_EDGE;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_BOTH) {
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |=
+ ME4000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4000_AO_CTRL_BIT_EX_TRIG_BOTH;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+ } else {
+ printk(KERN_ERR
+ "me4000_ao_ex_trig_set_edge():Invalid trigger mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_ao_ex_trig_enable(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_ex_trig_enable() is executed\n");
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_ex_trig_enable():Can't enable trigger while DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_ex_trig_disable(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_ex_trig_disable() is executed\n");
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_ex_trig_disable():Can't disable trigger while DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_simultaneous_disable(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+
+ CALL_PDEBUG("me4000_ao_simultaneous_disable() is executed\n");
+
+ /* Check if the state machine is stopped */
+ /* Be careful here because this function is called from
+ me4000_ao_synchronous disable */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_simultaneous_disable():Can't disable while DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ tmp &= ~(0x1 << ao_context->index); // Disable preload bit
+ tmp &= ~(0x1 << (ao_context->index + 16)); // Disable hw simultaneous bit
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ return 0;
+}
+
+static int me4000_ao_simultaneous_ex_trig(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+
+ CALL_PDEBUG("me4000_ao_simultaneous_ex_trig() is executed\n");
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ tmp |= (0x1 << ao_context->index); // Enable preload bit
+ tmp |= (0x1 << (ao_context->index + 16)); // Enable hw simultaneous bit
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ return 0;
+}
+
+static int me4000_ao_simultaneous_sw(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+
+ CALL_PDEBUG("me4000_ao_simultaneous_sw() is executed\n");
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ tmp |= (0x1 << ao_context->index); // Enable preload bit
+ tmp &= ~(0x1 << (ao_context->index + 16)); // Disable hw simultaneous bit
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ return 0;
+}
+
+static int me4000_ao_preload(me4000_ao_context_t * ao_context)
+{
+ CALL_PDEBUG("me4000_ao_preload() is executed\n");
+ return me4000_ao_simultaneous_sw(ao_context);
+}
+
+static int me4000_ao_preload_update(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ u32 ctrl;
+ struct list_head *entry;
+
+ CALL_PDEBUG("me4000_ao_preload_update() is executed\n");
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ list_for_each(entry, &ao_context->board_info->ao_context_list) {
+ /* The channels we update must be in the following state :
+ - Mode A
+ - Hardware trigger is disabled
+ - Corresponding simultaneous bit is reset
+ */
+ ctrl = me4000_inl(ao_context->ctrl_reg);
+ if (!
+ (ctrl &
+ (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1 |
+ ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG))) {
+ if (!
+ (tmp &
+ (0x1 <<
+ (((me4000_ao_context_t *) entry)->index + 16)))) {
+ tmp &=
+ ~(0x1 <<
+ (((me4000_ao_context_t *) entry)->index));
+ }
+ }
+ }
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ return 0;
+}
+
+static int me4000_ao_simultaneous_update(me4000_ao_channel_list_t * arg,
+ me4000_ao_context_t * ao_context)
+{
+ int err;
+ int i;
+ u32 tmp;
+ me4000_ao_channel_list_t channels;
+
+ CALL_PDEBUG("me4000_ao_simultaneous_update() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&channels, arg, sizeof(me4000_ao_channel_list_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_simultaneous_update():Can't copy command\n");
+ return -EFAULT;
+ }
+
+ channels.list =
+ kmalloc(sizeof(unsigned long) * channels.count, GFP_KERNEL);
+ if (!channels.list) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_simultaneous_update():Can't get buffer\n");
+ return -ENOMEM;
+ }
+ memset(channels.list, 0, sizeof(unsigned long) * channels.count);
+
+ /* Copy channel list from user */
+ err =
+ copy_from_user(channels.list, arg->list,
+ sizeof(unsigned long) * channels.count);
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_simultaneous_update():Can't copy list\n");
+ kfree(channels.list);
+ return -EFAULT;
+ }
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ for (i = 0; i < channels.count; i++) {
+ if (channels.list[i] >
+ ao_context->board_info->board_p->ao.count) {
+ spin_unlock(&ao_context->board_info->preload_lock);
+ kfree(channels.list);
+ printk(KERN_ERR
+ "ME4000:me4000_ao_simultaneous_update():Invalid board number specified\n");
+ return -EFAULT;
+ }
+ tmp &= ~(0x1 << channels.list[i]); // Clear the preload bit
+ tmp &= ~(0x1 << (channels.list[i] + 16)); // Clear the hw simultaneous bit
+ }
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+ kfree(channels.list);
+
+ return 0;
+}
+
+static int me4000_ao_synchronous_ex_trig(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_synchronous_ex_trig() is executed\n");
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "me4000_ao_synchronous_ex_trig(): DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ tmp &= ~(0x1 << ao_context->index); // Disable synchronous sw bit
+ tmp |= 0x1 << (ao_context->index + 16); // Enable synchronous hw bit
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ /* Make runnable */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) {
+ tmp &=
+ ~(ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ }
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_synchronous_sw(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_synchronous_sw() is executed\n");
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR "me4000_ao_synchronous_sw(): DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock(&ao_context->board_info->preload_lock);
+ tmp = me4000_inl(ao_context->preload_reg);
+ tmp |= 0x1 << ao_context->index; // Enable synchronous sw bit
+ tmp &= ~(0x1 << (ao_context->index + 16)); // Disable synchronous hw bit
+ me4000_outl(tmp, ao_context->preload_reg);
+ spin_unlock(&ao_context->board_info->preload_lock);
+
+ /* Make runnable */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) {
+ tmp &=
+ ~(ME4000_AO_CTRL_BIT_STOP |
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ }
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_synchronous_disable(me4000_ao_context_t * ao_context)
+{
+ return me4000_ao_simultaneous_disable(ao_context);
+}
+
+static int me4000_ao_get_free_buffer(unsigned long *arg,
+ me4000_ao_context_t * ao_context)
+{
+ unsigned long c;
+ int err;
+
+ c = me4000_buf_space(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT);
+
+ err = copy_to_user(arg, &c, sizeof(unsigned long));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_get_free_buffer():Can't copy to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me4000_ao_ex_trig_timeout(unsigned long *arg,
+ me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long ref;
+ unsigned long timeout;
+
+ CALL_PDEBUG("me4000_ao_ex_trig_timeout() is executed\n");
+
+ if (get_user(timeout, arg)) {
+ printk(KERN_ERR
+ "me4000_ao_ex_trig_timeout():Cannot copy data from user\n");
+ return -EFAULT;
+ }
+
+ init_waitqueue_head(&queue);
+
+ tmp = inl(ao_context->ctrl_reg);
+
+ if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) {
+ if (timeout) {
+ ref = jiffies;
+ while ((inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space
+ printk(KERN_ERR
+ "ME4000:me4000_ao_ex_trig_timeout():Timeout reached\n");
+ return -EIO;
+ }
+ }
+ } else {
+ while ((inl(ao_context->status_reg) &
+ ME4000_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ }
+ }
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_ao_ex_trig_timeout():External Trigger is not enabled\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_ao_enable_do(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_enable_do() is executed\n");
+
+ /* Only available for analog output 3 */
+ if (ao_context->index != 3) {
+ printk(KERN_ERR
+ "me4000_ao_enable_do():Only available for analog output 3\n");
+ return -ENOTTY;
+ }
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR "me4000_ao_enable_do(): DAC is running\n");
+ return -EBUSY;
+ }
+
+ /* Set the stop bit */
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_ENABLE_DO;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_disable_do(me4000_ao_context_t * ao_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ao_disable_do() is executed\n");
+
+ /* Only available for analog output 3 */
+ if (ao_context->index != 3) {
+ printk(KERN_ERR
+ "me4000_ao_disable():Only available for analog output 3\n");
+ return -ENOTTY;
+ }
+
+ /* Check if the state machine is stopped */
+ tmp = me4000_inl(ao_context->status_reg);
+ if (tmp & ME4000_AO_STATUS_BIT_FSM) {
+ printk(KERN_ERR "me4000_ao_disable_do(): DAC is running\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&ao_context->int_lock, flags);
+ tmp = inl(ao_context->ctrl_reg);
+ tmp &= ~(ME4000_AO_CTRL_BIT_ENABLE_DO);
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock_irqrestore(&ao_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ao_fsm_state(int *arg, me4000_ao_context_t * ao_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ao_fsm_state() is executed\n");
+
+ tmp =
+ (me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) ? 1
+ : 0;
+
+ if (ao_context->pipe_flag) {
+ printk(KERN_ERR "me4000_ao_fsm_state():Broken pipe detected\n");
+ return -EPIPE;
+ }
+
+ if (put_user(tmp, arg)) {
+ printk(KERN_ERR "me4000_ao_fsm_state():Cannot copy to user\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*------------------------------- Analog input stuff --------------------------------------*/
+
+static int me4000_ai_prepare(me4000_ai_context_t * ai_context)
+{
+ wait_queue_head_t queue;
+ int err;
+
+ CALL_PDEBUG("me4000_ai_prepare() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Set the new mode and stop bits */
+ me4000_outl(ai_context->
+ mode | ME4000_AI_CTRL_BIT_STOP |
+ ME4000_AI_CTRL_BIT_IMMEDIATE_STOP, ai_context->ctrl_reg);
+
+ /* Set the timer registers */
+ ai_context->chan_timer = 66;
+ ai_context->chan_pre_timer = 66;
+ ai_context->scan_timer_low = 0;
+ ai_context->scan_timer_high = 0;
+
+ me4000_outl(65, ai_context->chan_timer_reg);
+ me4000_outl(65, ai_context->chan_pre_timer_reg);
+ me4000_outl(0, ai_context->scan_timer_low_reg);
+ me4000_outl(0, ai_context->scan_timer_high_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_low_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_high_reg);
+
+ ai_context->channel_list_count = 0;
+
+ if (ai_context->mode) {
+ /* Request the interrupt line */
+ err =
+ request_irq(ai_context->irq, me4000_ai_isr,
+ IRQF_DISABLED | IRQF_SHARED, ME4000_NAME,
+ ai_context);
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_prepare():Can't get interrupt line");
+ return -ENODEV;
+ }
+
+ /* Allocate circular buffer */
+ ai_context->circ_buf.buf =
+ kmalloc(ME4000_AI_BUFFER_SIZE, GFP_KERNEL);
+ if (!ai_context->circ_buf.buf) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_prepare():Can't get circular buffer\n");
+ free_irq(ai_context->irq, ai_context);
+ return -ENOMEM;
+ }
+ memset(ai_context->circ_buf.buf, 0, ME4000_AI_BUFFER_SIZE);
+
+ /* Clear the circular buffer */
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+ }
+
+ return 0;
+}
+
+static int me4000_ai_reset(me4000_ai_context_t * ai_context)
+{
+ wait_queue_head_t queue;
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_reset() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /*
+ * First stop conversion of the state machine before reconfigure.
+ * If not stopped before configuring mode, it could
+ * walk in a undefined state.
+ */
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "me4000_ai_reset():Wait on state machine after stop interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ /* Clear the control register and set the stop bits */
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
+ ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ /* Reset timer registers */
+ ai_context->chan_timer = 66;
+ ai_context->chan_pre_timer = 66;
+ ai_context->scan_timer_low = 0;
+ ai_context->scan_timer_high = 0;
+ ai_context->sample_counter = 0;
+ ai_context->sample_counter_reload = 0;
+
+ me4000_outl(65, ai_context->chan_timer_reg);
+ me4000_outl(65, ai_context->chan_pre_timer_reg);
+ me4000_outl(0, ai_context->scan_timer_low_reg);
+ me4000_outl(0, ai_context->scan_timer_high_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_low_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_high_reg);
+ me4000_outl(0, ai_context->sample_counter_reg);
+
+ ai_context->channel_list_count = 0;
+
+ /* Clear the circular buffer */
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+
+ return 0;
+}
+
+static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ai_context_t *ai_context;
+
+ CALL_PDEBUG("me4000_ai_ioctl_sing() is executed\n");
+
+ ai_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_ai_ioctl_sing():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR
+ "me4000_ai_ioctl_sing():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_AI_SINGLE:
+ return me4000_ai_single((me4000_ai_single_t *) arg, ai_context);
+ case ME4000_AI_EX_TRIG_ENABLE:
+ return me4000_ai_ex_trig_enable(ai_context);
+ case ME4000_AI_EX_TRIG_DISABLE:
+ return me4000_ai_ex_trig_disable(ai_context);
+ case ME4000_AI_EX_TRIG_SETUP:
+ return me4000_ai_ex_trig_setup((me4000_ai_trigger_t *) arg,
+ ai_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ai_context->board_info);
+ case ME4000_AI_OFFSET_ENABLE:
+ return me4000_ai_offset_enable(ai_context);
+ case ME4000_AI_OFFSET_DISABLE:
+ return me4000_ai_offset_disable(ai_context);
+ case ME4000_AI_FULLSCALE_ENABLE:
+ return me4000_ai_fullscale_enable(ai_context);
+ case ME4000_AI_FULLSCALE_DISABLE:
+ return me4000_ai_fullscale_disable(ai_context);
+ case ME4000_AI_EEPROM_READ:
+ return me4000_eeprom_read((me4000_eeprom_t *) arg, ai_context);
+ case ME4000_AI_EEPROM_WRITE:
+ return me4000_eeprom_write((me4000_eeprom_t *) arg, ai_context);
+ default:
+ printk(KERN_ERR
+ "me4000_ai_ioctl_sing():Invalid service number\n");
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ai_single(me4000_ai_single_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ me4000_ai_single_t cmd;
+ int err;
+ u32 tmp;
+ wait_queue_head_t queue;
+ unsigned long jiffy;
+
+ CALL_PDEBUG("me4000_ai_single() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_ai_single_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Check range parameter */
+ switch (cmd.range) {
+ case ME4000_AI_LIST_RANGE_BIPOLAR_10:
+ case ME4000_AI_LIST_RANGE_BIPOLAR_2_5:
+ case ME4000_AI_LIST_RANGE_UNIPOLAR_10:
+ case ME4000_AI_LIST_RANGE_UNIPOLAR_2_5:
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Invalid range specified\n");
+ return -EINVAL;
+ }
+
+ /* Check mode and channel number */
+ switch (cmd.mode) {
+ case ME4000_AI_LIST_INPUT_SINGLE_ENDED:
+ if (cmd.channel >= ai_context->board_info->board_p->ai.count) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Analog input is not available\n");
+ return -EINVAL;
+ }
+ break;
+ case ME4000_AI_LIST_INPUT_DIFFERENTIAL:
+ if (cmd.channel >=
+ ai_context->board_info->board_p->ai.diff_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Analog input is not available in differential mode\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Invalid mode specified\n");
+ return -EINVAL;
+ }
+
+ /* Clear channel list, data fifo and both stop bits */
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO |
+ ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ /* Enable channel list and data fifo */
+ tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ /* Generate channel list entry */
+ me4000_outl(cmd.channel | cmd.range | cmd.
+ mode | ME4000_AI_LIST_LAST_ENTRY,
+ ai_context->channel_list_reg);
+
+ /* Set the timer to maximum */
+ me4000_outl(66, ai_context->chan_timer_reg);
+ me4000_outl(66, ai_context->chan_pre_timer_reg);
+
+ if (tmp & ME4000_AI_CTRL_BIT_EX_TRIG) {
+ jiffy = jiffies;
+ while (!
+ (me4000_inl(ai_context->status_reg) &
+ ME4000_AI_STATUS_BIT_EF_DATA)) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ if (((jiffies - jiffy) > (cmd.timeout * HZ / USER_HZ)) && cmd.timeout) { // 2.6 has diffrent definitions for HZ in user and kernel space
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Timeout reached\n");
+ return -EIO;
+ }
+ }
+ } else {
+ /* Start conversion */
+ me4000_inl(ai_context->start_reg);
+
+ /* Wait until ready */
+ udelay(10);
+ if (!
+ (me4000_inl(ai_context->status_reg) &
+ ME4000_AI_STATUS_BIT_EF_DATA)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Value not available after wait\n");
+ return -EIO;
+ }
+ }
+
+ /* Read value from data fifo */
+ cmd.value = me4000_inl(ai_context->data_reg) & 0xFFFF;
+
+ /* Copy result back to user */
+ err = copy_to_user(arg, &cmd, sizeof(me4000_ai_single_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_single():Can't copy to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ai_context_t *ai_context;
+
+ CALL_PDEBUG("me4000_ai_ioctl_sw() is executed\n");
+
+ ai_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_ai_ioctl_sw():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR
+ "me4000_ai_ioctl_sw():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_AI_SC_SETUP:
+ return me4000_ai_sc_setup((me4000_ai_sc_t *) arg, ai_context);
+ case ME4000_AI_CONFIG:
+ return me4000_ai_config((me4000_ai_config_t *) arg, ai_context);
+ case ME4000_AI_START:
+ return me4000_ai_start(ai_context);
+ case ME4000_AI_STOP:
+ return me4000_ai_stop(ai_context);
+ case ME4000_AI_IMMEDIATE_STOP:
+ return me4000_ai_immediate_stop(ai_context);
+ case ME4000_AI_FSM_STATE:
+ return me4000_ai_fsm_state((int *)arg, ai_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ai_context->board_info);
+ case ME4000_AI_EEPROM_READ:
+ return me4000_eeprom_read((me4000_eeprom_t *) arg, ai_context);
+ case ME4000_AI_EEPROM_WRITE:
+ return me4000_eeprom_write((me4000_eeprom_t *) arg, ai_context);
+ case ME4000_AI_GET_COUNT_BUFFER:
+ return me4000_ai_get_count_buffer((unsigned long *)arg,
+ ai_context);
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ioctl_sw():Invalid service number %d\n",
+ service);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ai_context_t *ai_context;
+
+ CALL_PDEBUG("me4000_ai_ioctl_ext() is executed\n");
+
+ ai_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_ai_ioctl_ext():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR
+ "me4000_ai_ioctl_ext():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_AI_SC_SETUP:
+ return me4000_ai_sc_setup((me4000_ai_sc_t *) arg, ai_context);
+ case ME4000_AI_CONFIG:
+ return me4000_ai_config((me4000_ai_config_t *) arg, ai_context);
+ case ME4000_AI_START:
+ return me4000_ai_start_ex((unsigned long *)arg, ai_context);
+ case ME4000_AI_STOP:
+ return me4000_ai_stop(ai_context);
+ case ME4000_AI_IMMEDIATE_STOP:
+ return me4000_ai_immediate_stop(ai_context);
+ case ME4000_AI_EX_TRIG_ENABLE:
+ return me4000_ai_ex_trig_enable(ai_context);
+ case ME4000_AI_EX_TRIG_DISABLE:
+ return me4000_ai_ex_trig_disable(ai_context);
+ case ME4000_AI_EX_TRIG_SETUP:
+ return me4000_ai_ex_trig_setup((me4000_ai_trigger_t *) arg,
+ ai_context);
+ case ME4000_AI_FSM_STATE:
+ return me4000_ai_fsm_state((int *)arg, ai_context);
+ case ME4000_GET_USER_INFO:
+ return me4000_get_user_info((me4000_user_info_t *) arg,
+ ai_context->board_info);
+ case ME4000_AI_GET_COUNT_BUFFER:
+ return me4000_ai_get_count_buffer((unsigned long *)arg,
+ ai_context);
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ioctl_ext():Invalid service number %d\n",
+ service);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ai_fasync(int fd, struct file *file_p, int mode)
+{
+ me4000_ai_context_t *ai_context;
+
+ CALL_PDEBUG("me4000_ao_fasync_cont() is executed\n");
+
+ ai_context = file_p->private_data;
+ return fasync_helper(fd, file_p, mode, &ai_context->fasync_p);
+}
+
+static int me4000_ai_config(me4000_ai_config_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ me4000_ai_config_t cmd;
+ u32 *list = NULL;
+ u32 mode;
+ int i;
+ int err;
+ wait_queue_head_t queue;
+ u64 scan;
+ u32 tmp;
+
+ CALL_PDEBUG("me4000_ai_config() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Check if conversion is stopped */
+ if (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Conversion is not stopped\n");
+ err = -EBUSY;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_ai_config_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Can't copy from user space\n");
+ err = -EFAULT;
+ goto AI_CONFIG_ERR;
+ }
+
+ PDEBUG
+ ("me4000_ai_config():chan = %ld, pre_chan = %ld, scan_low = %ld, scan_high = %ld, count = %ld\n",
+ cmd.timer.chan, cmd.timer.pre_chan, cmd.timer.scan_low,
+ cmd.timer.scan_high, cmd.channel_list.count);
+
+ /* Check whether sample and hold is available for this board */
+ if (cmd.sh) {
+ if (!ai_context->board_info->board_p->ai.sh_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Sample and Hold is not available for this board\n");
+ err = -ENODEV;
+ goto AI_CONFIG_ERR;
+ }
+ }
+
+ /* Check the channel list size */
+ if (cmd.channel_list.count > ME4000_AI_CHANNEL_LIST_COUNT) {
+ printk(KERN_ERR
+ "me4000_ai_config():Channel list is to large\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Copy channel list from user */
+ list = kmalloc(sizeof(u32) * cmd.channel_list.count, GFP_KERNEL);
+ if (!list) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Can't get memory for channel list\n");
+ err = -ENOMEM;
+ goto AI_CONFIG_ERR;
+ }
+ err =
+ copy_from_user(list, cmd.channel_list.list,
+ sizeof(u32) * cmd.channel_list.count);
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Can't copy from user space\n");
+ err = -EFAULT;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Check if last entry bit is set */
+ if (!(list[cmd.channel_list.count - 1] & ME4000_AI_LIST_LAST_ENTRY)) {
+ printk(KERN_WARNING
+ "me4000_ai_config():Last entry bit is not set\n");
+ list[cmd.channel_list.count - 1] |= ME4000_AI_LIST_LAST_ENTRY;
+ }
+
+ /* Check whether mode is equal for all entries */
+ mode = list[0] & 0x20;
+ for (i = 0; i < cmd.channel_list.count; i++) {
+ if ((list[i] & 0x20) != mode) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Mode is not equal for all entries\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+ }
+
+ /* Check whether channels are available for this mode */
+ if (mode == ME4000_AI_LIST_INPUT_SINGLE_ENDED) {
+ for (i = 0; i < cmd.channel_list.count; i++) {
+ if ((list[i] & 0x1F) >=
+ ai_context->board_info->board_p->ai.count) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Channel is not available for single ended\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+ }
+ } else if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) {
+ for (i = 0; i < cmd.channel_list.count; i++) {
+ if ((list[i] & 0x1F) >=
+ ai_context->board_info->board_p->ai.diff_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Channel is not available for differential\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+ }
+ }
+
+ /* Check if bipolar is set for all entries when in differential mode */
+ if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) {
+ for (i = 0; i < cmd.channel_list.count; i++) {
+ if ((list[i] & 0xC0) != ME4000_AI_LIST_RANGE_BIPOLAR_10
+ && (list[i] & 0xC0) !=
+ ME4000_AI_LIST_RANGE_BIPOLAR_2_5) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Bipolar is not selected in differential mode\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+ }
+ }
+
+ if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_VALUE) {
+ /* Check for minimum channel divisor */
+ if (cmd.timer.chan < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Channel timer divisor is to low\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Check if minimum channel divisor is adjusted when sample and hold is activated */
+ if ((cmd.sh) && (cmd.timer.chan != ME4000_AI_MIN_TICKS)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Channel timer divisor must be at minimum when sample and hold is activated\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Check for minimum channel pre divisor */
+ if (cmd.timer.pre_chan < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Channel pre timer divisor is to low\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+
+ /* Write the channel timers */
+ me4000_outl(cmd.timer.chan - 1, ai_context->chan_timer_reg);
+ me4000_outl(cmd.timer.pre_chan - 1,
+ ai_context->chan_pre_timer_reg);
+
+ /* Save the timer values in the board context */
+ ai_context->chan_timer = cmd.timer.chan;
+ ai_context->chan_pre_timer = cmd.timer.pre_chan;
+
+ if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_CHANLIST) {
+ /* Check for scan timer divisor */
+ scan =
+ (u64) cmd.timer.scan_low | ((u64) cmd.timer.
+ scan_high << 32);
+ if (scan != 0) {
+ if (scan <
+ cmd.channel_list.count * cmd.timer.chan +
+ 1) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_config():Scan timer divisor is to low\n");
+ err = -EINVAL;
+ goto AI_CONFIG_ERR;
+ }
+ }
+
+ /* Write the scan timers */
+ if (scan != 0) {
+ scan--;
+ tmp = (u32) (scan & 0xFFFFFFFF);
+ me4000_outl(tmp,
+ ai_context->scan_timer_low_reg);
+ tmp = (u32) ((scan >> 32) & 0xFFFFFFFF);
+ me4000_outl(tmp,
+ ai_context->scan_timer_high_reg);
+
+ scan =
+ scan - (cmd.timer.chan - 1) +
+ (cmd.timer.pre_chan - 1);
+ tmp = (u32) (scan & 0xFFFFFFFF);
+ me4000_outl(tmp,
+ ai_context->scan_pre_timer_low_reg);
+ tmp = (u32) ((scan >> 32) & 0xFFFFFFFF);
+ me4000_outl(tmp,
+ ai_context->
+ scan_pre_timer_high_reg);
+ } else {
+ me4000_outl(0x0,
+ ai_context->scan_timer_low_reg);
+ me4000_outl(0x0,
+ ai_context->scan_timer_high_reg);
+
+ me4000_outl(0x0,
+ ai_context->scan_pre_timer_low_reg);
+ me4000_outl(0x0,
+ ai_context->
+ scan_pre_timer_high_reg);
+ }
+
+ ai_context->scan_timer_low = cmd.timer.scan_low;
+ ai_context->scan_timer_high = cmd.timer.scan_high;
+ }
+ }
+
+ /* Clear the channel list */
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_CHANNEL_FIFO;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ /* Write the channel list */
+ for (i = 0; i < cmd.channel_list.count; i++) {
+ me4000_outl(list[i], ai_context->channel_list_reg);
+ }
+
+ /* Setup sample and hold */
+ if (cmd.sh) {
+ tmp |= ME4000_AI_CTRL_BIT_SAMPLE_HOLD;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ } else {
+ tmp &= ~ME4000_AI_CTRL_BIT_SAMPLE_HOLD;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ }
+
+ /* Save the channel list size in the board context */
+ ai_context->channel_list_count = cmd.channel_list.count;
+
+ kfree(list);
+
+ return 0;
+
+ AI_CONFIG_ERR:
+
+ /* Reset the timers */
+ ai_context->chan_timer = 66;
+ ai_context->chan_pre_timer = 66;
+ ai_context->scan_timer_low = 0;
+ ai_context->scan_timer_high = 0;
+
+ me4000_outl(65, ai_context->chan_timer_reg);
+ me4000_outl(65, ai_context->chan_pre_timer_reg);
+ me4000_outl(0, ai_context->scan_timer_high_reg);
+ me4000_outl(0, ai_context->scan_timer_low_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_high_reg);
+ me4000_outl(0, ai_context->scan_pre_timer_low_reg);
+
+ ai_context->channel_list_count = 0;
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_SAMPLE_HOLD);
+
+ if (list)
+ kfree(list);
+
+ return err;
+
+}
+
+static int ai_common_start(me4000_ai_context_t * ai_context)
+{
+ u32 tmp;
+ CALL_PDEBUG("ai_common_start() is executed\n");
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ /* Check if conversion is stopped */
+ if (tmp & ME4000_AI_STATUS_BIT_FSM) {
+ printk(KERN_ERR
+ "ME4000:ai_common_start():Conversion is not stopped\n");
+ return -EBUSY;
+ }
+
+ /* Clear data fifo, disable all interrupts, clear sample counter reload */
+ tmp &= ~(ME4000_AI_CTRL_BIT_DATA_FIFO | ME4000_AI_CTRL_BIT_LE_IRQ |
+ ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_SC_RELOAD);
+
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ /* Clear circular buffer */
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+
+ /* Enable data fifo */
+ tmp |= ME4000_AI_CTRL_BIT_DATA_FIFO;
+
+ /* Determine interrupt setup */
+ if (ai_context->sample_counter && !ai_context->sample_counter_reload) {
+ /* Enable Half Full Interrupt and Sample Counter Interrupt */
+ tmp |= ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ;
+ } else if (ai_context->sample_counter
+ && ai_context->sample_counter_reload) {
+ if (ai_context->sample_counter <= ME4000_AI_FIFO_COUNT / 2) {
+ /* Enable only Sample Counter Interrupt */
+ tmp |=
+ ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_SC_RELOAD;
+ } else {
+ /* Enable Half Full Interrupt and Sample Counter Interrupt */
+ tmp |=
+ ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_SC_RELOAD;
+ }
+ } else {
+ /* Enable only Half Full Interrupt */
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
+ }
+
+ /* Clear the stop bits */
+ tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
+
+ /* Write setup to hardware */
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ /* Write sample counter */
+ me4000_outl(ai_context->sample_counter, ai_context->sample_counter_reg);
+
+ return 0;
+}
+
+static int me4000_ai_start(me4000_ai_context_t * ai_context)
+{
+ int err;
+ CALL_PDEBUG("me4000_ai_start() is executed\n");
+
+ /* Prepare Hardware */
+ err = ai_common_start(ai_context);
+ if (err)
+ return err;
+
+ /* Start conversion by dummy read */
+ me4000_inl(ai_context->start_reg);
+
+ return 0;
+}
+
+static int me4000_ai_start_ex(unsigned long *arg,
+ me4000_ai_context_t * ai_context)
+{
+ int err;
+ wait_queue_head_t queue;
+ unsigned long ref;
+ unsigned long timeout;
+
+ CALL_PDEBUG("me4000_ai_start_ex() is executed\n");
+
+ if (get_user(timeout, arg)) {
+ printk(KERN_ERR
+ "me4000_ai_start_ex():Cannot copy data from user\n");
+ return -EFAULT;
+ }
+
+ init_waitqueue_head(&queue);
+
+ /* Prepare Hardware */
+ err = ai_common_start(ai_context);
+ if (err)
+ return err;
+
+ if (timeout) {
+ ref = jiffies;
+ while (!
+ (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space
+ printk(KERN_ERR
+ "ME4000:me4000_ai_start_ex():Timeout reached\n");
+ return -EIO;
+ }
+ }
+ } else {
+ while (!
+ (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n");
+ return -EINTR;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int me4000_ai_stop(me4000_ai_context_t * ai_context)
+{
+ wait_queue_head_t queue;
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_stop() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Disable irqs and clear data fifo */
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_DATA_FIFO);
+ /* Stop conversion of the state machine */
+ tmp |= ME4000_AI_CTRL_BIT_STOP;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ /* Clear circular buffer */
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+
+ while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ return 0;
+}
+
+static int me4000_ai_immediate_stop(me4000_ai_context_t * ai_context)
+{
+ wait_queue_head_t queue;
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_stop() is executed\n");
+
+ init_waitqueue_head(&queue);
+
+ /* Disable irqs and clear data fifo */
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_DATA_FIFO);
+ /* Stop conversion of the state machine */
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ /* Clear circular buffer */
+ ai_context->circ_buf.head = 0;
+ ai_context->circ_buf.tail = 0;
+
+ while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n");
+ return -EINTR;
+ }
+ }
+
+ return 0;
+}
+
+static int me4000_ai_ex_trig_enable(me4000_ai_context_t * ai_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_ex_trig_enable() is executed\n");
+
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_EX_TRIG;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ai_ex_trig_disable(me4000_ai_context_t * ai_context)
+{
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_ex_trig_disable() is executed\n");
+
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+
+ return 0;
+}
+
+static int me4000_ai_ex_trig_setup(me4000_ai_trigger_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ me4000_ai_trigger_t cmd;
+ int err;
+ u32 tmp;
+ unsigned long flags;
+
+ CALL_PDEBUG("me4000_ai_ex_trig_setup() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_ai_trigger_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ex_trig_setup():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ if (cmd.mode == ME4000_AI_TRIGGER_EXT_DIGITAL) {
+ tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG;
+ } else if (cmd.mode == ME4000_AI_TRIGGER_EXT_ANALOG) {
+ if (!ai_context->board_info->board_p->ai.ex_trig_analog) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ex_trig_setup():No analog trigger available\n");
+ return -EINVAL;
+ }
+ tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG;
+ } else {
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ex_trig_setup():Invalid trigger mode specified\n");
+ return -EINVAL;
+ }
+
+ if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_RISING) {
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_EX_TRIG_BOTH |
+ ME4000_AI_CTRL_BIT_EX_TRIG_FALLING);
+ } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_FALLING) {
+ tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_FALLING;
+ tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_BOTH;
+ } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_BOTH) {
+ tmp |=
+ ME4000_AI_CTRL_BIT_EX_TRIG_BOTH |
+ ME4000_AI_CTRL_BIT_EX_TRIG_FALLING;
+ } else {
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+ printk(KERN_ERR
+ "ME4000:me4000_ai_ex_trig_setup():Invalid trigger edge specified\n");
+ return -EINVAL;
+ }
+
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+ return 0;
+}
+
+static int me4000_ai_sc_setup(me4000_ai_sc_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ me4000_ai_sc_t cmd;
+ int err;
+
+ CALL_PDEBUG("me4000_ai_sc_setup() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_ai_sc_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_sc_setup():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ ai_context->sample_counter = cmd.value;
+ ai_context->sample_counter_reload = cmd.reload;
+
+ return 0;
+}
+
+static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt,
+ loff_t * offp)
+{
+ me4000_ai_context_t *ai_context = filep->private_data;
+ s16 *buffer = (s16 *) buff;
+ size_t count = cnt / 2;
+ unsigned long flags;
+ int tmp;
+ int c = 0;
+ int k = 0;
+ int ret = 0;
+ wait_queue_t wait;
+
+ CALL_PDEBUG("me4000_ai_read() is executed\n");
+
+ init_waitqueue_entry(&wait, current);
+
+ /* Check count */
+ if (count <= 0) {
+ PDEBUG("me4000_ai_read():Count is 0\n");
+ return 0;
+ }
+
+ while (count > 0) {
+ if (filep->f_flags & O_NONBLOCK) {
+ c = me4000_values_to_end(ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ if (!c) {
+ PDEBUG
+ ("me4000_ai_read():Returning from nonblocking read\n");
+ break;
+ }
+ } else {
+ /* Check if conversion is still running */
+ if (!
+ (me4000_inl(ai_context->status_reg) &
+ ME4000_AI_STATUS_BIT_FSM)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_read():Conversion interrupted\n");
+ return -EPIPE;
+ }
+
+ wait_event_interruptible(ai_context->wait_queue,
+ (me4000_values_to_end
+ (ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT)));
+ if (signal_pending(current)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_read():Wait on values interrupted from signal\n");
+ return -EINTR;
+ }
+ }
+
+ /* Only read count values or as much as available */
+ c = me4000_values_to_end(ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ PDEBUG("me4000_ai_read():%d values to end\n", c);
+ if (count < c)
+ c = count;
+
+ PDEBUG("me4000_ai_read():Copy %d values to user space\n", c);
+ k = 2 * c;
+ k -= copy_to_user(buffer,
+ ai_context->circ_buf.buf +
+ ai_context->circ_buf.tail, k);
+ c = k / 2;
+ if (!c) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_read():Cannot copy new values to user\n");
+ return -EFAULT;
+ }
+
+ ai_context->circ_buf.tail =
+ (ai_context->circ_buf.tail + c) & (ME4000_AI_BUFFER_COUNT -
+ 1);
+ buffer += c;
+ count -= c;
+ ret += c;
+
+ spin_lock_irqsave(&ai_context->int_lock, flags);
+ if (me4000_buf_space
+ (ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ /* Determine interrupt setup */
+ if (ai_context->sample_counter
+ && !ai_context->sample_counter_reload) {
+ /* Enable Half Full Interrupt and Sample Counter Interrupt */
+ tmp |=
+ ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_HF_IRQ;
+ } else if (ai_context->sample_counter
+ && ai_context->sample_counter_reload) {
+ if (ai_context->sample_counter <
+ ME4000_AI_FIFO_COUNT / 2) {
+ /* Enable only Sample Counter Interrupt */
+ tmp |= ME4000_AI_CTRL_BIT_SC_IRQ;
+ } else {
+ /* Enable Half Full Interrupt and Sample Counter Interrupt */
+ tmp |=
+ ME4000_AI_CTRL_BIT_SC_IRQ |
+ ME4000_AI_CTRL_BIT_HF_IRQ;
+ }
+ } else {
+ /* Enable only Half Full Interrupt */
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
+ }
+
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ }
+ spin_unlock_irqrestore(&ai_context->int_lock, flags);
+ }
+
+ /* Check if conversion is still running */
+ if (!(me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_read():Conversion not running after complete read\n");
+ return -EPIPE;
+ }
+
+ if (filep->f_flags & O_NONBLOCK) {
+ return (k == 0) ? -EAGAIN : 2 * ret;
+ }
+
+ CALL_PDEBUG("me4000_ai_read() is leaved\n");
+ return ret * 2;
+}
+
+static unsigned int me4000_ai_poll(struct file *file_p, poll_table * wait)
+{
+ me4000_ai_context_t *ai_context;
+ unsigned long mask = 0;
+
+ CALL_PDEBUG("me4000_ai_poll() is executed\n");
+
+ ai_context = file_p->private_data;
+
+ /* Register wait queue */
+ poll_wait(file_p, &ai_context->wait_queue, wait);
+
+ /* Get available values */
+ if (me4000_values_to_end(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT))
+ mask |= POLLIN | POLLRDNORM;
+
+ PDEBUG("me4000_ai_poll():Return mask %lX\n", mask);
+
+ return mask;
+}
+
+static int me4000_ai_offset_enable(me4000_ai_context_t * ai_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ai_offset_enable() is executed\n");
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_OFFSET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ai_offset_disable(me4000_ai_context_t * ai_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ai_offset_disable() is executed\n");
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_OFFSET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ai_fullscale_enable(me4000_ai_context_t * ai_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ai_fullscale_enable() is executed\n");
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_FULLSCALE;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ai_fullscale_disable(me4000_ai_context_t * ai_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ai_fullscale_disable() is executed\n");
+
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_FULLSCALE;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ai_fsm_state(int *arg, me4000_ai_context_t * ai_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ai_fsm_state() is executed\n");
+
+ tmp =
+ (me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) ? 1
+ : 0;
+
+ if (put_user(tmp, arg)) {
+ printk(KERN_ERR "me4000_ai_fsm_state():Cannot copy to user\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me4000_ai_get_count_buffer(unsigned long *arg,
+ me4000_ai_context_t * ai_context)
+{
+ unsigned long c;
+ int err;
+
+ c = me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT);
+
+ err = copy_to_user(arg, &c, sizeof(unsigned long));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_ai_get_count_buffer():Can't copy to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*---------------------------------- EEPROM stuff ---------------------------*/
+
+static int eeprom_write_cmd(me4000_ai_context_t * ai_context, unsigned long cmd,
+ int length)
+{
+ int i;
+ unsigned long value;
+
+ CALL_PDEBUG("eeprom_write_cmd() is executed\n");
+
+ PDEBUG("eeprom_write_cmd():Write command 0x%08lX with length = %d\n",
+ cmd, length);
+
+ /* Get the ICR register and clear the related bits */
+ value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR);
+ value &= ~(PLX_ICR_MASK_EEPROM);
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+
+ /* Raise the chip select */
+ value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT;
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ for (i = 0; i < length; i++) {
+ if (cmd & ((0x1 << (length - 1)) >> i)) {
+ value |= PLX_ICR_BIT_EEPROM_WRITE;
+ } else {
+ value &= ~PLX_ICR_BIT_EEPROM_WRITE;
+ }
+
+ /* Write to EEPROM */
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Raising edge of the clock */
+ value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Falling edge of the clock */
+ value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+ }
+
+ /* Clear the chip select */
+ value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT;
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Wait until hardware is ready for sure */
+ mdelay(10);
+
+ return 0;
+}
+
+static unsigned short eeprom_read_cmd(me4000_ai_context_t * ai_context,
+ unsigned long cmd, int length)
+{
+ int i;
+ unsigned long value;
+ unsigned short id = 0;
+
+ CALL_PDEBUG("eeprom_read_cmd() is executed\n");
+
+ PDEBUG("eeprom_read_cmd():Read command 0x%08lX with length = %d\n", cmd,
+ length);
+
+ /* Get the ICR register and clear the related bits */
+ value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR);
+ value &= ~(PLX_ICR_MASK_EEPROM);
+
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+
+ /* Raise the chip select */
+ value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT;
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Write the read command to the eeprom */
+ for (i = 0; i < length; i++) {
+ if (cmd & ((0x1 << (length - 1)) >> i)) {
+ value |= PLX_ICR_BIT_EEPROM_WRITE;
+ } else {
+ value &= ~PLX_ICR_BIT_EEPROM_WRITE;
+ }
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Raising edge of the clock */
+ value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ /* Falling edge of the clock */
+ value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+ }
+
+ /* Read the value from the eeprom */
+ for (i = 0; i < 16; i++) {
+ /* Raising edge of the clock */
+ value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ if (me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR) &
+ PLX_ICR_BIT_EEPROM_READ) {
+ id |= (0x8000 >> i);
+ PDEBUG("eeprom_read_cmd():OR with 0x%04X\n",
+ (0x8000 >> i));
+ } else {
+ PDEBUG("eeprom_read_cmd():Dont't OR\n");
+ }
+
+ /* Falling edge of the clock */
+ value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
+ me4000_outl(value,
+ ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+ }
+
+ /* Clear the chip select */
+ value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT;
+ me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
+ udelay(EEPROM_DELAY);
+
+ return id;
+}
+
+static int me4000_eeprom_write(me4000_eeprom_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ int err;
+ me4000_eeprom_t setup;
+ unsigned long cmd;
+ unsigned long date_high;
+ unsigned long date_low;
+
+ CALL_PDEBUG("me4000_eeprom_write() is executed\n");
+
+ err = copy_from_user(&setup, arg, sizeof(setup));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_eeprom_write():Cannot copy from user\n");
+ return err;
+ }
+
+ /* Enable writing */
+ eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_ENABLE,
+ ME4000_EEPROM_CMD_LENGTH_WRITE_ENABLE);
+
+ /* Command for date */
+ date_high = (setup.date & 0xFFFF0000) >> 16;
+ date_low = (setup.date & 0x0000FFFF);
+
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_HIGH <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ date_high);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_LOW <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ date_low);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for unipolar 10V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ uni_10_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for unipolar 10V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ uni_10_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for unipolar 2,5V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ uni_2_5_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for unipolar 2,5V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ uni_2_5_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for bipolar 10V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ bi_10_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for bipolar 10V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ bi_10_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for bipolar 2,5V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ bi_2_5_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for bipolar 2,5V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ bi_2_5_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for differential 10V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ diff_10_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for differential 10V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE
+ << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ diff_10_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for differential 2,5V offset */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET <<
+ ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ diff_2_5_offset);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Command for differential 2,5V fullscale */
+ cmd =
+ ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE
+ << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
+ (unsigned
+ long)
+ setup.
+ diff_2_5_fullscale);
+ err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
+ if (err)
+ return err;
+
+ /* Disable writing */
+ eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_DISABLE,
+ ME4000_EEPROM_CMD_LENGTH_WRITE_DISABLE);
+
+ return 0;
+}
+
+static int me4000_eeprom_read(me4000_eeprom_t * arg,
+ me4000_ai_context_t * ai_context)
+{
+ int err;
+ unsigned long cmd;
+ me4000_eeprom_t setup;
+
+ CALL_PDEBUG("me4000_eeprom_read() is executed\n");
+
+ /* Command for date */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_HIGH;
+ setup.date =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+ setup.date <<= 16;
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_LOW;
+ setup.date |=
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for unipolar 10V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET;
+ setup.uni_10_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for unipolar 10V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE;
+ setup.uni_10_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for unipolar 2,5V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET;
+ setup.uni_2_5_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for unipolar 2,5V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE;
+ setup.uni_2_5_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for bipolar 10V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET;
+ setup.bi_10_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for bipolar 10V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE;
+ setup.bi_10_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for bipolar 2,5V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET;
+ setup.bi_2_5_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for bipolar 2,5V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE;
+ setup.bi_2_5_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for differntial 10V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET;
+ setup.diff_10_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for differential 10V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE;
+ setup.diff_10_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for differntial 2,5V offset */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET;
+ setup.diff_2_5_offset =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ /* Command for differential 2,5V fullscale */
+ cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE;
+ setup.diff_2_5_fullscale =
+ eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
+
+ err = copy_to_user(arg, &setup, sizeof(setup));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_eeprom_read():Cannot copy to user\n");
+ return err;
+ }
+
+ return 0;
+}
+
+/*------------------------------------ DIO stuff ----------------------------------------------*/
+
+static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_dio_context_t *dio_context;
+
+ CALL_PDEBUG("me4000_dio_ioctl() is executed\n");
+
+ dio_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_DIO_CONFIG:
+ return me4000_dio_config((me4000_dio_config_t *) arg,
+ dio_context);
+ case ME4000_DIO_SET_BYTE:
+ return me4000_dio_set_byte((me4000_dio_byte_t *) arg,
+ dio_context);
+ case ME4000_DIO_GET_BYTE:
+ return me4000_dio_get_byte((me4000_dio_byte_t *) arg,
+ dio_context);
+ case ME4000_DIO_RESET:
+ return me4000_dio_reset(dio_context);
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_dio_ioctl():Invalid service number %d\n",
+ service);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_dio_config(me4000_dio_config_t * arg,
+ me4000_dio_context_t * dio_context)
+{
+ me4000_dio_config_t cmd;
+ u32 tmp;
+ int err;
+
+ CALL_PDEBUG("me4000_dio_config() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_dio_config_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Check port parameter */
+ if (cmd.port >= dio_context->dio_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port,
+ cmd.mode, cmd.function);
+
+ if (cmd.port == ME4000_DIO_PORT_A) {
+ if (cmd.mode == ME4000_DIO_PORT_INPUT) {
+ /* Check if opto isolated version */
+ if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Cannot set to input on opto isolated versions\n");
+ return -EIO;
+ }
+
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1);
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_0);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_0;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Mode %d is not available\n",
+ cmd.mode);
+ return -EINVAL;
+ }
+ } else if (cmd.port == ME4000_DIO_PORT_B) {
+ if (cmd.mode == ME4000_DIO_PORT_INPUT) {
+ /* Only do anything when TTL version is installed */
+ if ((me4000_inl(dio_context->dir_reg) & 0x1)) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3);
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ }
+ } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
+ /* Check if opto isolated version */
+ if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Cannot set to output on opto isolated versions\n");
+ return -EIO;
+ }
+
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
+ /* Check if opto isolated version */
+ if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Cannot set to FIFO low output on opto isolated versions\n");
+ return -EIO;
+ }
+
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_1);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
+ /* Check if opto isolated version */
+ if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Cannot set to FIFO high output on opto isolated versions\n");
+ return -EIO;
+ }
+
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_1;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Mode %d is not available\n",
+ cmd.mode);
+ return -EINVAL;
+ }
+ } else if (cmd.port == ME4000_DIO_PORT_C) {
+ if (cmd.mode == ME4000_DIO_PORT_INPUT) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5);
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_2);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_2;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Mode %d is not available\n",
+ cmd.mode);
+ return -EINVAL;
+ }
+ } else if (cmd.port == ME4000_DIO_PORT_D) {
+ if (cmd.mode == ME4000_DIO_PORT_INPUT) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7);
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_3);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp |=
+ ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7 |
+ ME4000_DIO_CTRL_BIT_FIFO_HIGH_3;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Mode %d is not available\n",
+ cmd.mode);
+ return -EINVAL;
+ }
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port,
+ cmd.mode, cmd.function);
+
+ if ((cmd.mode == ME4000_DIO_FIFO_HIGH)
+ || (cmd.mode == ME4000_DIO_FIFO_LOW)) {
+ tmp = me4000_inl(dio_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4000_DIO_CTRL_BIT_FUNCTION_1);
+ if (cmd.function == ME4000_DIO_FUNCTION_PATTERN) {
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.function == ME4000_DIO_FUNCTION_DEMUX) {
+ tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_0;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else if (cmd.function == ME4000_DIO_FUNCTION_MUX) {
+ tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_1;
+ me4000_outl(tmp, dio_context->ctrl_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_config():Invalid port function specified\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int me4000_dio_set_byte(me4000_dio_byte_t * arg,
+ me4000_dio_context_t * dio_context)
+{
+ me4000_dio_byte_t cmd;
+ int err;
+
+ CALL_PDEBUG("me4000_dio_set_byte() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_dio_byte_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Check port parameter */
+ if (cmd.port >= dio_context->dio_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ if (cmd.port == ME4000_DIO_PORT_A) {
+ if ((me4000_inl(dio_context->ctrl_reg) & 0x3) != 0x1) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
+ cmd.port);
+ return -EIO;
+ }
+ me4000_outl(cmd.byte, dio_context->port_0_reg);
+ } else if (cmd.port == ME4000_DIO_PORT_B) {
+ if ((me4000_inl(dio_context->ctrl_reg) & 0xC) != 0x4) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
+ cmd.port);
+ return -EIO;
+ }
+ me4000_outl(cmd.byte, dio_context->port_1_reg);
+ } else if (cmd.port == ME4000_DIO_PORT_C) {
+ if ((me4000_inl(dio_context->ctrl_reg) & 0x30) != 0x10) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
+ cmd.port);
+ return -EIO;
+ }
+ me4000_outl(cmd.byte, dio_context->port_2_reg);
+ } else if (cmd.port == ME4000_DIO_PORT_D) {
+ if ((me4000_inl(dio_context->ctrl_reg) & 0xC0) != 0x40) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
+ cmd.port);
+ return -EIO;
+ }
+ me4000_outl(cmd.byte, dio_context->port_3_reg);
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_set_byte():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_dio_get_byte(me4000_dio_byte_t * arg,
+ me4000_dio_context_t * dio_context)
+{
+ me4000_dio_byte_t cmd;
+ int err;
+
+ CALL_PDEBUG("me4000_dio_get_byte() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_dio_byte_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_get_byte():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Check port parameter */
+ if (cmd.port >= dio_context->dio_count) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_get_byte():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ if (cmd.port == ME4000_DIO_PORT_A) {
+ cmd.byte = me4000_inl(dio_context->port_0_reg) & 0xFF;
+ } else if (cmd.port == ME4000_DIO_PORT_B) {
+ cmd.byte = me4000_inl(dio_context->port_1_reg) & 0xFF;
+ } else if (cmd.port == ME4000_DIO_PORT_C) {
+ cmd.byte = me4000_inl(dio_context->port_2_reg) & 0xFF;
+ } else if (cmd.port == ME4000_DIO_PORT_D) {
+ cmd.byte = me4000_inl(dio_context->port_3_reg) & 0xFF;
+ } else {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_get_byte():Port %d is not available\n",
+ cmd.port);
+ return -EINVAL;
+ }
+
+ /* Copy result back to user */
+ err = copy_to_user(arg, &cmd, sizeof(me4000_dio_byte_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_dio_get_byte():Can't copy to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me4000_dio_reset(me4000_dio_context_t * dio_context)
+{
+ CALL_PDEBUG("me4000_dio_reset() is executed\n");
+
+ /* Clear the control register */
+ me4000_outl(0, dio_context->ctrl_reg);
+
+ /* Check for opto isolated version */
+ if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
+ me4000_outl(0x1, dio_context->ctrl_reg);
+ me4000_outl(0x0, dio_context->port_0_reg);
+ }
+
+ return 0;
+}
+
+/*------------------------------------ COUNTER STUFF ------------------------------------*/
+
+static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_cnt_context_t *cnt_context;
+
+ CALL_PDEBUG("me4000_cnt_ioctl() is executed\n");
+
+ cnt_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_CNT_READ:
+ return me4000_cnt_read((me4000_cnt_t *) arg, cnt_context);
+ case ME4000_CNT_WRITE:
+ return me4000_cnt_write((me4000_cnt_t *) arg, cnt_context);
+ case ME4000_CNT_CONFIG:
+ return me4000_cnt_config((me4000_cnt_config_t *) arg,
+ cnt_context);
+ case ME4000_CNT_RESET:
+ return me4000_cnt_reset(cnt_context);
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_dio_ioctl():Invalid service number %d\n",
+ service);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_cnt_config(me4000_cnt_config_t * arg,
+ me4000_cnt_context_t * cnt_context)
+{
+ me4000_cnt_config_t cmd;
+ u8 counter;
+ u8 mode;
+ int err;
+
+ CALL_PDEBUG("me4000_cnt_config() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_config_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_config():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Check counter parameter */
+ switch (cmd.counter) {
+ case ME4000_CNT_COUNTER_0:
+ counter = ME4000_CNT_CTRL_BIT_COUNTER_0;
+ break;
+ case ME4000_CNT_COUNTER_1:
+ counter = ME4000_CNT_CTRL_BIT_COUNTER_1;
+ break;
+ case ME4000_CNT_COUNTER_2:
+ counter = ME4000_CNT_CTRL_BIT_COUNTER_2;
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_config():Counter %d is not available\n",
+ cmd.counter);
+ return -EINVAL;
+ }
+
+ /* Check mode parameter */
+ switch (cmd.mode) {
+ case ME4000_CNT_MODE_0:
+ mode = ME4000_CNT_CTRL_BIT_MODE_0;
+ break;
+ case ME4000_CNT_MODE_1:
+ mode = ME4000_CNT_CTRL_BIT_MODE_1;
+ break;
+ case ME4000_CNT_MODE_2:
+ mode = ME4000_CNT_CTRL_BIT_MODE_2;
+ break;
+ case ME4000_CNT_MODE_3:
+ mode = ME4000_CNT_CTRL_BIT_MODE_3;
+ break;
+ case ME4000_CNT_MODE_4:
+ mode = ME4000_CNT_CTRL_BIT_MODE_4;
+ break;
+ case ME4000_CNT_MODE_5:
+ mode = ME4000_CNT_CTRL_BIT_MODE_5;
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_config():Mode %d is not available\n",
+ cmd.mode);
+ return -EINVAL;
+ }
+
+ /* Write the control word */
+ me4000_outb((counter | mode | 0x30), cnt_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_cnt_read(me4000_cnt_t * arg,
+ me4000_cnt_context_t * cnt_context)
+{
+ me4000_cnt_t cmd;
+ u8 tmp;
+ int err;
+
+ CALL_PDEBUG("me4000_cnt_read() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_read():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Read counter */
+ switch (cmd.counter) {
+ case ME4000_CNT_COUNTER_0:
+ tmp = me4000_inb(cnt_context->counter_0_reg);
+ cmd.value = tmp;
+ tmp = me4000_inb(cnt_context->counter_0_reg);
+ cmd.value |= ((u16) tmp) << 8;
+ break;
+ case ME4000_CNT_COUNTER_1:
+ tmp = me4000_inb(cnt_context->counter_1_reg);
+ cmd.value = tmp;
+ tmp = me4000_inb(cnt_context->counter_1_reg);
+ cmd.value |= ((u16) tmp) << 8;
+ break;
+ case ME4000_CNT_COUNTER_2:
+ tmp = me4000_inb(cnt_context->counter_2_reg);
+ cmd.value = tmp;
+ tmp = me4000_inb(cnt_context->counter_2_reg);
+ cmd.value |= ((u16) tmp) << 8;
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_read():Counter %d is not available\n",
+ cmd.counter);
+ return -EINVAL;
+ }
+
+ /* Copy result back to user */
+ err = copy_to_user(arg, &cmd, sizeof(me4000_cnt_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_read():Can't copy to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me4000_cnt_write(me4000_cnt_t * arg,
+ me4000_cnt_context_t * cnt_context)
+{
+ me4000_cnt_t cmd;
+ u8 tmp;
+ int err;
+
+ CALL_PDEBUG("me4000_cnt_write() is executed\n");
+
+ /* Copy data from user */
+ err = copy_from_user(&cmd, arg, sizeof(me4000_cnt_t));
+ if (err) {
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_write():Can't copy from user space\n");
+ return -EFAULT;
+ }
+
+ /* Write counter */
+ switch (cmd.counter) {
+ case ME4000_CNT_COUNTER_0:
+ tmp = cmd.value & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_0_reg);
+ tmp = (cmd.value >> 8) & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_0_reg);
+ break;
+ case ME4000_CNT_COUNTER_1:
+ tmp = cmd.value & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_1_reg);
+ tmp = (cmd.value >> 8) & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_1_reg);
+ break;
+ case ME4000_CNT_COUNTER_2:
+ tmp = cmd.value & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_2_reg);
+ tmp = (cmd.value >> 8) & 0xFF;
+ me4000_outb(tmp, cnt_context->counter_2_reg);
+ break;
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_cnt_write():Counter %d is not available\n",
+ cmd.counter);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int me4000_cnt_reset(me4000_cnt_context_t * cnt_context)
+{
+ CALL_PDEBUG("me4000_cnt_reset() is executed\n");
+
+ /* Set the mode and value for counter 0 */
+ me4000_outb(0x30, cnt_context->ctrl_reg);
+ me4000_outb(0x00, cnt_context->counter_0_reg);
+ me4000_outb(0x00, cnt_context->counter_0_reg);
+
+ /* Set the mode and value for counter 1 */
+ me4000_outb(0x70, cnt_context->ctrl_reg);
+ me4000_outb(0x00, cnt_context->counter_1_reg);
+ me4000_outb(0x00, cnt_context->counter_1_reg);
+
+ /* Set the mode and value for counter 2 */
+ me4000_outb(0xB0, cnt_context->ctrl_reg);
+ me4000_outb(0x00, cnt_context->counter_2_reg);
+ me4000_outb(0x00, cnt_context->counter_2_reg);
+
+ return 0;
+}
+
+/*------------------------------------ External Interrupt stuff ------------------------------------*/
+
+static int me4000_ext_int_ioctl(struct inode *inode_p, struct file *file_p,
+ unsigned int service, unsigned long arg)
+{
+ me4000_ext_int_context_t *ext_int_context;
+
+ CALL_PDEBUG("me4000_ext_int_ioctl() is executed\n");
+
+ ext_int_context = file_p->private_data;
+
+ if (_IOC_TYPE(service) != ME4000_MAGIC) {
+ printk(KERN_ERR "me4000_ext_int_ioctl():Wrong magic number\n");
+ return -ENOTTY;
+ }
+ if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
+ printk(KERN_ERR
+ "me4000_ext_int_ioctl():Service number to high\n");
+ return -ENOTTY;
+ }
+
+ switch (service) {
+ case ME4000_EXT_INT_ENABLE:
+ return me4000_ext_int_enable(ext_int_context);
+ case ME4000_EXT_INT_DISABLE:
+ return me4000_ext_int_disable(ext_int_context);
+ case ME4000_EXT_INT_COUNT:
+ return me4000_ext_int_count((unsigned long *)arg,
+ ext_int_context);
+ default:
+ printk(KERN_ERR
+ "ME4000:me4000_ext_int_ioctl():Invalid service number %d\n",
+ service);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int me4000_ext_int_enable(me4000_ext_int_context_t * ext_int_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ext_int_enable() is executed\n");
+
+ tmp = me4000_inl(ext_int_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_EX_IRQ;
+ me4000_outl(tmp, ext_int_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ext_int_disable(me4000_ext_int_context_t * ext_int_context)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("me4000_ext_int_disable() is executed\n");
+
+ tmp = me4000_inl(ext_int_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ;
+ me4000_outl(tmp, ext_int_context->ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_ext_int_count(unsigned long *arg,
+ me4000_ext_int_context_t * ext_int_context)
+{
+
+ CALL_PDEBUG("me4000_ext_int_count() is executed\n");
+
+ put_user(ext_int_context->int_count, arg);
+ return 0;
+}
+
+/*------------------------------------ General stuff ------------------------------------*/
+
+static int me4000_get_user_info(me4000_user_info_t * arg,
+ me4000_info_t * board_info)
+{
+ me4000_user_info_t user_info;
+
+ CALL_PDEBUG("me4000_get_user_info() is executed\n");
+
+ user_info.board_count = board_info->board_count;
+ user_info.plx_regbase = board_info->plx_regbase;
+ user_info.plx_regbase_size = board_info->plx_regbase_size;
+ user_info.me4000_regbase = board_info->me4000_regbase;
+ user_info.me4000_regbase_size = board_info->me4000_regbase_size;
+ user_info.serial_no = board_info->serial_no;
+ user_info.hw_revision = board_info->hw_revision;
+ user_info.vendor_id = board_info->vendor_id;
+ user_info.device_id = board_info->device_id;
+ user_info.pci_bus_no = board_info->pci_bus_no;
+ user_info.pci_dev_no = board_info->pci_dev_no;
+ user_info.pci_func_no = board_info->pci_func_no;
+ user_info.irq = board_info->irq;
+ user_info.irq_count = board_info->irq_count;
+ user_info.driver_version = ME4000_DRIVER_VERSION;
+ user_info.ao_count = board_info->board_p->ao.count;
+ user_info.ao_fifo_count = board_info->board_p->ao.fifo_count;
+
+ user_info.ai_count = board_info->board_p->ai.count;
+ user_info.ai_sh_count = board_info->board_p->ai.sh_count;
+ user_info.ai_ex_trig_analog = board_info->board_p->ai.ex_trig_analog;
+
+ user_info.dio_count = board_info->board_p->dio.count;
+
+ user_info.cnt_count = board_info->board_p->cnt.count;
+
+ if (copy_to_user(arg, &user_info, sizeof(me4000_user_info_t)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*------------------------------------ ISR STUFF ------------------------------------*/
+
+static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode)
+{
+ int result = 0;
+ me4000_ext_int_context_t *ext_int_context;
+
+ CALL_PDEBUG("me4000_ext_int_fasync() is executed\n");
+
+ ext_int_context = file_ptr->private_data;
+
+ result =
+ fasync_helper(fd, file_ptr, mode, &ext_int_context->fasync_ptr);
+
+ CALL_PDEBUG("me4000_ext_int_fasync() is leaved\n");
+ return result;
+}
+
+static irqreturn_t me4000_ao_isr(int irq, void *dev_id)
+{
+ u32 tmp;
+ u32 value;
+ me4000_ao_context_t *ao_context;
+ int i;
+ int c = 0;
+ int c1 = 0;
+ //unsigned long before;
+ //unsigned long after;
+
+ ISR_PDEBUG("me4000_ao_isr() is executed\n");
+
+ ao_context = dev_id;
+
+ /* Check if irq number is right */
+ if (irq != ao_context->irq) {
+ ISR_PDEBUG("me4000_ao_isr():incorrect interrupt num: %d\n",
+ irq);
+ return IRQ_NONE;
+ }
+
+ /* Check if this DAC rised an interrupt */
+ if (!
+ ((0x1 << (ao_context->index + 3)) &
+ me4000_inl(ao_context->irq_status_reg))) {
+ ISR_PDEBUG("me4000_ao_isr():Not this DAC\n");
+ return IRQ_NONE;
+ }
+
+ /* Read status register to find out what happened */
+ tmp = me4000_inl(ao_context->status_reg);
+
+ if (!(tmp & ME4000_AO_STATUS_BIT_EF) && (tmp & ME4000_AO_STATUS_BIT_HF)
+ && (tmp & ME4000_AO_STATUS_BIT_HF)) {
+ c = ME4000_AO_FIFO_COUNT;
+ ISR_PDEBUG("me4000_ao_isr():Fifo empty\n");
+ } else if ((tmp & ME4000_AO_STATUS_BIT_EF)
+ && (tmp & ME4000_AO_STATUS_BIT_HF)
+ && (tmp & ME4000_AO_STATUS_BIT_HF)) {
+ c = ME4000_AO_FIFO_COUNT / 2;
+ ISR_PDEBUG("me4000_ao_isr():Fifo under half full\n");
+ } else {
+ c = 0;
+ ISR_PDEBUG("me4000_ao_isr():Fifo full\n");
+ }
+
+ ISR_PDEBUG("me4000_ao_isr():Try to write 0x%04X values\n", c);
+
+ while (1) {
+ c1 = me4000_values_to_end(ao_context->circ_buf,
+ ME4000_AO_BUFFER_COUNT);
+ ISR_PDEBUG("me4000_ao_isr():Values to end = %d\n", c1);
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ ISR_PDEBUG
+ ("me4000_ao_isr():Work done or buffer empty\n");
+ break;
+ }
+ //rdtscl(before);
+ if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG) ||
+ ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG)) {
+ for (i = 0; i < c1; i++) {
+ value =
+ ((u32)
+ (*
+ (ao_context->circ_buf.buf +
+ ao_context->circ_buf.tail + i))) << 16;
+ outl(value, ao_context->fifo_reg);
+ }
+ } else
+ outsw(ao_context->fifo_reg,
+ ao_context->circ_buf.buf +
+ ao_context->circ_buf.tail, c1);
+
+ //rdtscl(after);
+ //printk(KERN_ERR"ME4000:me4000_ao_isr():Time lapse = %lu\n", after - before);
+
+ ao_context->circ_buf.tail =
+ (ao_context->circ_buf.tail + c1) & (ME4000_AO_BUFFER_COUNT -
+ 1);
+ ISR_PDEBUG("me4000_ao_isr():%d values wrote to port 0x%04X\n",
+ c1, ao_context->fifo_reg);
+ c -= c1;
+ }
+
+ /* If there are no values left in the buffer, disable interrupts */
+ spin_lock(&ao_context->int_lock);
+ if (!me4000_buf_count(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
+ ISR_PDEBUG
+ ("me4000_ao_isr():Disable Interrupt because no values left in buffer\n");
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ }
+ spin_unlock(&ao_context->int_lock);
+
+ /* Reset the interrupt */
+ spin_lock(&ao_context->int_lock);
+ tmp = me4000_inl(ao_context->ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_RESET_IRQ;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ tmp &= ~ME4000_AO_CTRL_BIT_RESET_IRQ;
+ me4000_outl(tmp, ao_context->ctrl_reg);
+
+ /* If state machine is stopped, flow was interrupted */
+ if (!(me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM)) {
+ printk(KERN_ERR "ME4000:me4000_ao_isr():Broken pipe\n");
+ ao_context->pipe_flag = 1; // Set flag in order to inform write routine
+ tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ; // Disable interrupt
+ }
+ me4000_outl(tmp, ao_context->ctrl_reg);
+ spin_unlock(&ao_context->int_lock);
+
+ /* Wake up waiting process */
+ wake_up_interruptible(&(ao_context->wait_queue));
+
+ /* Count the interrupt */
+ ao_context->board_info->irq_count++;
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
+{
+ u32 tmp;
+ me4000_ai_context_t *ai_context;
+ int i;
+ int c = 0;
+ int c1 = 0;
+#ifdef ME4000_ISR_DEBUG
+ unsigned long before;
+ unsigned long after;
+#endif
+
+ ISR_PDEBUG("me4000_ai_isr() is executed\n");
+
+#ifdef ME4000_ISR_DEBUG
+ rdtscl(before);
+#endif
+
+ ai_context = dev_id;
+
+ /* Check if irq number is right */
+ if (irq != ai_context->irq) {
+ ISR_PDEBUG("me4000_ai_isr():incorrect interrupt num: %d\n",
+ irq);
+ return IRQ_NONE;
+ }
+
+ if (me4000_inl(ai_context->irq_status_reg) &
+ ME4000_IRQ_STATUS_BIT_AI_HF) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Fifo half full interrupt occured\n");
+
+ /* Read status register to find out what happened */
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG("me4000_ai_isr():Fifo full\n");
+ c = ME4000_AI_FIFO_COUNT;
+
+ /* FIFO overflow, so stop conversion and disable all interrupts */
+ spin_lock(&ai_context->int_lock);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_SC_IRQ);
+ outl(tmp, ai_context->ctrl_reg);
+ spin_unlock(&ai_context->int_lock);
+ } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG("me4000_ai_isr():Fifo half full\n");
+ c = ME4000_AI_FIFO_COUNT / 2;
+ } else {
+ c = 0;
+ ISR_PDEBUG
+ ("me4000_ai_isr():Can't determine state of fifo\n");
+ }
+
+ ISR_PDEBUG("me4000_ai_isr():Try to read %d values\n", c);
+
+ while (1) {
+ c1 = me4000_space_to_end(ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ ISR_PDEBUG("me4000_ai_isr():Space to end = %d\n", c1);
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Work done or buffer full\n");
+ break;
+ }
+
+ insw(ai_context->data_reg,
+ ai_context->circ_buf.buf +
+ ai_context->circ_buf.head, c1);
+ ai_context->circ_buf.head =
+ (ai_context->circ_buf.head +
+ c1) & (ME4000_AI_BUFFER_COUNT - 1);
+ c -= c1;
+ }
+
+ /* Work is done, so reset the interrupt */
+ ISR_PDEBUG
+ ("me4000_ai_isr():reset interrupt fifo half full interrupt\n");
+ spin_lock(&ai_context->int_lock);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock(&ai_context->int_lock);
+ }
+
+ if (me4000_inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Sample counter interrupt occured\n");
+
+ if (!ai_context->sample_counter_reload) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Single data block available\n");
+
+ /* Poll data until fifo empty */
+ for (i = 0;
+ (i < ME4000_AI_FIFO_COUNT / 2)
+ && (inl(ai_context->ctrl_reg) &
+ ME4000_AI_STATUS_BIT_EF_DATA); i++) {
+ if (me4000_space_to_end
+ (ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT)) {
+ *(ai_context->circ_buf.buf +
+ ai_context->circ_buf.head) =
+ inw(ai_context->data_reg);
+ ai_context->circ_buf.head =
+ (ai_context->circ_buf.head +
+ 1) & (ME4000_AI_BUFFER_COUNT - 1);
+ } else
+ break;
+ }
+ ISR_PDEBUG("me4000_ai_isr():%d values read\n", i);
+ } else {
+ if (ai_context->sample_counter <=
+ ME4000_AI_FIFO_COUNT / 2) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Interrupt from adjustable half full threshold\n");
+
+ /* Read status register to find out what happened */
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Fifo full\n");
+ c = ME4000_AI_FIFO_COUNT;
+
+ /* FIFO overflow, so stop conversion */
+ spin_lock(&ai_context->int_lock);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |=
+ ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, ai_context->ctrl_reg);
+ spin_unlock(&ai_context->int_lock);
+ } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
+ && !(tmp &
+ ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp &
+ ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Fifo half full\n");
+ c = ME4000_AI_FIFO_COUNT / 2;
+ } else {
+ c = ai_context->sample_counter;
+ ISR_PDEBUG
+ ("me4000_ai_isr():Sample count values\n");
+ }
+
+ ISR_PDEBUG
+ ("me4000_ai_isr():Try to read %d values\n",
+ c);
+
+ while (1) {
+ c1 = me4000_space_to_end(ai_context->
+ circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ ISR_PDEBUG
+ ("me4000_ai_isr():Space to end = %d\n",
+ c1);
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Work done or buffer full\n");
+ break;
+ }
+
+ insw(ai_context->data_reg,
+ ai_context->circ_buf.buf +
+ ai_context->circ_buf.head, c1);
+ ai_context->circ_buf.head =
+ (ai_context->circ_buf.head +
+ c1) & (ME4000_AI_BUFFER_COUNT - 1);
+ c -= c1;
+ }
+ } else {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Multiple data block available\n");
+
+ /* Read status register to find out what happened */
+ tmp = me4000_inl(ai_context->ctrl_reg);
+
+ if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Fifo full\n");
+ c = ME4000_AI_FIFO_COUNT;
+
+ /* FIFO overflow, so stop conversion */
+ spin_lock(&ai_context->int_lock);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |=
+ ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, ai_context->ctrl_reg);
+ spin_unlock(&ai_context->int_lock);
+
+ while (1) {
+ c1 = me4000_space_to_end
+ (ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ ISR_PDEBUG
+ ("me4000_ai_isr():Space to end = %d\n",
+ c1);
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Work done or buffer full\n");
+ break;
+ }
+
+ insw(ai_context->data_reg,
+ ai_context->circ_buf.buf +
+ ai_context->circ_buf.head,
+ c1);
+ ai_context->circ_buf.head =
+ (ai_context->circ_buf.head +
+ c1) &
+ (ME4000_AI_BUFFER_COUNT -
+ 1);
+ c -= c1;
+ }
+ } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
+ && !(tmp &
+ ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp &
+ ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Fifo half full\n");
+ c = ME4000_AI_FIFO_COUNT / 2;
+
+ while (1) {
+ c1 = me4000_space_to_end
+ (ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT);
+ ISR_PDEBUG
+ ("me4000_ai_isr():Space to end = %d\n",
+ c1);
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Work done or buffer full\n");
+ break;
+ }
+
+ insw(ai_context->data_reg,
+ ai_context->circ_buf.buf +
+ ai_context->circ_buf.head,
+ c1);
+ ai_context->circ_buf.head =
+ (ai_context->circ_buf.head +
+ c1) &
+ (ME4000_AI_BUFFER_COUNT -
+ 1);
+ c -= c1;
+ }
+ } else {
+ /* Poll data until fifo empty */
+ for (i = 0;
+ (i < ME4000_AI_FIFO_COUNT / 2)
+ && (inl(ai_context->ctrl_reg) &
+ ME4000_AI_STATUS_BIT_EF_DATA);
+ i++) {
+ if (me4000_space_to_end
+ (ai_context->circ_buf,
+ ME4000_AI_BUFFER_COUNT)) {
+ *(ai_context->circ_buf.
+ buf +
+ ai_context->circ_buf.
+ head) =
+ inw(ai_context->data_reg);
+ ai_context->circ_buf.
+ head =
+ (ai_context->
+ circ_buf.head +
+ 1) &
+ (ME4000_AI_BUFFER_COUNT
+ - 1);
+ } else
+ break;
+ }
+ ISR_PDEBUG
+ ("me4000_ai_isr():%d values read\n",
+ i);
+ }
+ }
+ }
+
+ /* Work is done, so reset the interrupt */
+ ISR_PDEBUG
+ ("me4000_ai_isr():reset interrupt from sample counter\n");
+ spin_lock(&ai_context->int_lock);
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ spin_unlock(&ai_context->int_lock);
+ }
+
+ /* Values are now available, so wake up waiting process */
+ if (me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
+ ISR_PDEBUG("me4000_ai_isr():Wake up waiting process\n");
+ wake_up_interruptible(&(ai_context->wait_queue));
+ }
+
+ /* If there is no space left in the buffer, disable interrupts */
+ spin_lock(&ai_context->int_lock);
+ if (!me4000_buf_space(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
+ ISR_PDEBUG
+ ("me4000_ai_isr():Disable Interrupt because no space left in buffer\n");
+ tmp = me4000_inl(ai_context->ctrl_reg);
+ tmp &=
+ ~(ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_LE_IRQ);
+ me4000_outl(tmp, ai_context->ctrl_reg);
+ }
+ spin_unlock(&ai_context->int_lock);
+
+#ifdef ME4000_ISR_DEBUG
+ rdtscl(after);
+ printk(KERN_ERR "ME4000:me4000_ai_isr():Time lapse = %lu\n",
+ after - before);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id)
+{
+ me4000_ext_int_context_t *ext_int_context;
+ unsigned long tmp;
+
+ ISR_PDEBUG("me4000_ext_int_isr() is executed\n");
+
+ ext_int_context = dev_id;
+
+ /* Check if irq number is right */
+ if (irq != ext_int_context->irq) {
+ ISR_PDEBUG("me4000_ext_int_isr():incorrect interrupt num: %d\n",
+ irq);
+ return IRQ_NONE;
+ }
+
+ if (me4000_inl(ext_int_context->irq_status_reg) &
+ ME4000_IRQ_STATUS_BIT_EX) {
+ ISR_PDEBUG("me4000_ext_int_isr():External interrupt occured\n");
+ tmp = me4000_inl(ext_int_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_EX_IRQ_RESET;
+ me4000_outl(tmp, ext_int_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ_RESET;
+ me4000_outl(tmp, ext_int_context->ctrl_reg);
+
+ ext_int_context->int_count++;
+
+ if (ext_int_context->fasync_ptr) {
+ ISR_PDEBUG
+ ("me2600_ext_int_isr():Send signal to process\n");
+ kill_fasync(&ext_int_context->fasync_ptr, SIGIO,
+ POLL_IN);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+void __exit me4000_module_exit(void)
+{
+ struct list_head *board_p;
+ me4000_info_t *board_info;
+
+ CALL_PDEBUG("cleanup_module() is executed\n");
+
+ unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME);
+
+ unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME);
+
+ unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME);
+
+ unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME);
+
+ unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME);
+
+ remove_proc_entry("me4000", NULL);
+
+ pci_unregister_driver(&me4000_driver);
+
+ /* Reset the boards */
+ for (board_p = me4000_board_info_list.next;
+ board_p != &me4000_board_info_list; board_p = board_p->next) {
+ board_info = list_entry(board_p, me4000_info_t, list);
+ me4000_reset_board(board_info);
+ }
+
+ clear_board_info_list();
+}
+
+module_exit(me4000_module_exit);
+
+static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+ int limit = count - 1000;
+ me4000_info_t *board_info;
+ struct list_head *ptr;
+
+ len += sprintf(buf + len, "\nME4000 DRIVER VERSION %X.%X.%X\n\n",
+ (ME4000_DRIVER_VERSION & 0xFF0000) >> 16,
+ (ME4000_DRIVER_VERSION & 0xFF00) >> 8,
+ (ME4000_DRIVER_VERSION & 0xFF));
+
+ /* Search for the board context */
+ for (ptr = me4000_board_info_list.next;
+ (ptr != &me4000_board_info_list) && (len < limit);
+ ptr = ptr->next) {
+ board_info = list_entry(ptr, me4000_info_t, list);
+
+ len +=
+ sprintf(buf + len, "Board number %d:\n",
+ board_info->board_count);
+ len += sprintf(buf + len, "---------------\n");
+ len +=
+ sprintf(buf + len, "PLX base register = 0x%lX\n",
+ board_info->plx_regbase);
+ len +=
+ sprintf(buf + len, "PLX base register size = 0x%lX\n",
+ board_info->plx_regbase_size);
+ len +=
+ sprintf(buf + len, "ME4000 base register = 0x%lX\n",
+ board_info->me4000_regbase);
+ len +=
+ sprintf(buf + len, "ME4000 base register size = 0x%lX\n",
+ board_info->me4000_regbase_size);
+ len +=
+ sprintf(buf + len, "Serial number = 0x%X\n",
+ board_info->serial_no);
+ len +=
+ sprintf(buf + len, "Hardware revision = 0x%X\n",
+ board_info->hw_revision);
+ len +=
+ sprintf(buf + len, "Vendor id = 0x%X\n",
+ board_info->vendor_id);
+ len +=
+ sprintf(buf + len, "Device id = 0x%X\n",
+ board_info->device_id);
+ len +=
+ sprintf(buf + len, "PCI bus number = %d\n",
+ board_info->pci_bus_no);
+ len +=
+ sprintf(buf + len, "PCI device number = %d\n",
+ board_info->pci_dev_no);
+ len +=
+ sprintf(buf + len, "PCI function number = %d\n",
+ board_info->pci_func_no);
+ len += sprintf(buf + len, "IRQ = %u\n", board_info->irq);
+ len +=
+ sprintf(buf + len,
+ "Count of interrupts since module was loaded = %d\n",
+ board_info->irq_count);
+
+ len +=
+ sprintf(buf + len, "Count of analog outputs = %d\n",
+ board_info->board_p->ao.count);
+ len +=
+ sprintf(buf + len, "Count of analog output fifos = %d\n",
+ board_info->board_p->ao.fifo_count);
+
+ len +=
+ sprintf(buf + len, "Count of analog inputs = %d\n",
+ board_info->board_p->ai.count);
+ len +=
+ sprintf(buf + len,
+ "Count of sample and hold devices for analog input = %d\n",
+ board_info->board_p->ai.sh_count);
+ len +=
+ sprintf(buf + len,
+ "Analog external trigger available for analog input = %d\n",
+ board_info->board_p->ai.ex_trig_analog);
+
+ len +=
+ sprintf(buf + len, "Count of digital ports = %d\n",
+ board_info->board_p->dio.count);
+
+ len +=
+ sprintf(buf + len, "Count of counter devices = %d\n",
+ board_info->board_p->cnt.count);
+ len +=
+ sprintf(buf + len, "AI control register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AI_CTRL_REG));
+
+ len += sprintf(buf + len, "AO 0 control register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_00_CTRL_REG));
+ len +=
+ sprintf(buf + len, "AO 0 status register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_00_STATUS_REG));
+ len +=
+ sprintf(buf + len, "AO 1 control register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_01_CTRL_REG));
+ len +=
+ sprintf(buf + len, "AO 1 status register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_01_STATUS_REG));
+ len +=
+ sprintf(buf + len, "AO 2 control register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_02_CTRL_REG));
+ len +=
+ sprintf(buf + len, "AO 2 status register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_02_STATUS_REG));
+ len +=
+ sprintf(buf + len, "AO 3 control register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_03_CTRL_REG));
+ len +=
+ sprintf(buf + len, "AO 3 status register = 0x%08X\n",
+ inl(board_info->me4000_regbase +
+ ME4000_AO_03_STATUS_REG));
+ }
+
+ *eof = 1;
+ return len;
+}
diff --git a/drivers/staging/me4000/me4000.h b/drivers/staging/me4000/me4000.h
new file mode 100644
index 00000000000..c35e4b9793a
--- /dev/null
+++ b/drivers/staging/me4000/me4000.h
@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 2003 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : me4000.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _ME4000_H_
+#define _ME4000_H_
+
+#ifdef __KERNEL__
+
+/*=============================================================================
+ The version of the driver release
+ ===========================================================================*/
+
+#define ME4000_DRIVER_VERSION 0x10009 // Version 1.00.09
+
+/*=============================================================================
+ Debug section
+ ===========================================================================*/
+
+#undef ME4000_CALL_DEBUG // Debug function entry and exit
+#undef ME4000_ISR_DEBUG // Debug the interrupt service routine
+#undef ME4000_PORT_DEBUG // Debug port access
+#undef ME4000_DEBUG // General purpose debug masseges
+
+#ifdef ME4000_CALL_DEBUG
+#undef CALL_PDEBUG
+#define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"ME4000:" fmt, ##args)
+#else
+# define CALL_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_ISR_DEBUG
+#undef ISR_PDEBUG
+#define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"ME4000:" fmt, ##args)
+#else
+#define ISR_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_PORT_DEBUG
+#undef PORT_PDEBUG
+#define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"ME4000:" fmt, ##args)
+#else
+#define PORT_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_DEBUG
+#undef PDEBUG
+#define PDEBUG(fmt, args...) printk(KERN_DEBUG"ME4000:" fmt, ##args)
+#else
+#define PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+/*=============================================================================
+ PCI vendor and device IDs
+ ===========================================================================*/
+
+#define PCI_VENDOR_ID_MEILHAUS 0x1402
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold
+
+/*=============================================================================
+ Device names, for entries in /proc/..
+ ===========================================================================*/
+
+#define ME4000_NAME "me4000"
+#define ME4000_AO_NAME "me4000_ao"
+#define ME4000_AI_NAME "me4000_ai"
+#define ME4000_DIO_NAME "me4000_dio"
+#define ME4000_CNT_NAME "me4000_cnt"
+#define ME4000_EXT_INT_NAME "me4000_ext_int"
+
+/*=============================================================================
+ ME-4000 base register offsets
+ ===========================================================================*/
+
+#define ME4000_AO_00_CTRL_REG 0x00 // R/W
+#define ME4000_AO_00_STATUS_REG 0x04 // R/_
+#define ME4000_AO_00_FIFO_REG 0x08 // _/W
+#define ME4000_AO_00_SINGLE_REG 0x0C // R/W
+#define ME4000_AO_00_TIMER_REG 0x10 // _/W
+
+#define ME4000_AO_01_CTRL_REG 0x18 // R/W
+#define ME4000_AO_01_STATUS_REG 0x1C // R/_
+#define ME4000_AO_01_FIFO_REG 0x20 // _/W
+#define ME4000_AO_01_SINGLE_REG 0x24 // R/W
+#define ME4000_AO_01_TIMER_REG 0x28 // _/W
+
+#define ME4000_AO_02_CTRL_REG 0x30 // R/W
+#define ME4000_AO_02_STATUS_REG 0x34 // R/_
+#define ME4000_AO_02_FIFO_REG 0x38 // _/W
+#define ME4000_AO_02_SINGLE_REG 0x3C // R/W
+#define ME4000_AO_02_TIMER_REG 0x40 // _/W
+
+#define ME4000_AO_03_CTRL_REG 0x48 // R/W
+#define ME4000_AO_03_STATUS_REG 0x4C // R/_
+#define ME4000_AO_03_FIFO_REG 0x50 // _/W
+#define ME4000_AO_03_SINGLE_REG 0x54 // R/W
+#define ME4000_AO_03_TIMER_REG 0x58 // _/W
+
+#define ME4000_AI_CTRL_REG 0x74 // _/W
+#define ME4000_AI_STATUS_REG 0x74 // R/_
+#define ME4000_AI_CHANNEL_LIST_REG 0x78 // _/W
+#define ME4000_AI_DATA_REG 0x7C // R/_
+#define ME4000_AI_CHAN_TIMER_REG 0x80 // _/W
+#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 // _/W
+#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 // _/W
+#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C // _/W
+#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 // _/W
+#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 // _/W
+#define ME4000_AI_START_REG 0x98 // R/_
+
+#define ME4000_IRQ_STATUS_REG 0x9C // R/_
+
+#define ME4000_DIO_PORT_0_REG 0xA0 // R/W
+#define ME4000_DIO_PORT_1_REG 0xA4 // R/W
+#define ME4000_DIO_PORT_2_REG 0xA8 // R/W
+#define ME4000_DIO_PORT_3_REG 0xAC // R/W
+#define ME4000_DIO_DIR_REG 0xB0 // R/W
+
+#define ME4000_AO_LOADSETREG_XX 0xB4 // R/W
+
+#define ME4000_DIO_CTRL_REG 0xB8 // R/W
+
+#define ME4000_AO_DEMUX_ADJUST_REG 0xBC // -/W
+
+#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 // _/W
+
+/*=============================================================================
+ Value to adjust Demux
+ ===========================================================================*/
+
+#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4C
+
+/*=============================================================================
+ Counter base register offsets
+ ===========================================================================*/
+
+#define ME4000_CNT_COUNTER_0_REG 0x00
+#define ME4000_CNT_COUNTER_1_REG 0x01
+#define ME4000_CNT_COUNTER_2_REG 0x02
+#define ME4000_CNT_CTRL_REG 0x03
+
+/*=============================================================================
+ PLX base register offsets
+ ===========================================================================*/
+
+#define PLX_INTCSR 0x4C // Interrupt control and status register
+#define PLX_ICR 0x50 // Initialization control register
+
+/*=============================================================================
+ Bits for the PLX_ICSR register
+ ===========================================================================*/
+
+#define PLX_INTCSR_LOCAL_INT1_EN 0x01 // If set, local interrupt 1 is enabled (r/w)
+#define PLX_INTCSR_LOCAL_INT1_POL 0x02 // If set, local interrupt 1 polarity is active high (r/w)
+#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 // If set, local interrupt 1 is active (r/_)
+#define PLX_INTCSR_LOCAL_INT2_EN 0x08 // If set, local interrupt 2 is enabled (r/w)
+#define PLX_INTCSR_LOCAL_INT2_POL 0x10 // If set, local interrupt 2 polarity is active high (r/w)
+#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 // If set, local interrupt 2 is active (r/_)
+#define PLX_INTCSR_PCI_INT_EN 0x40 // If set, PCI interrupt is enabled (r/w)
+#define PLX_INTCSR_SOFT_INT 0x80 // If set, a software interrupt is generated (r/w)
+
+/*=============================================================================
+ Bits for the PLX_ICR register
+ ===========================================================================*/
+
+#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000
+#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000
+#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000
+#define PLX_ICR_BIT_EEPROM_READ 0x08000000
+#define PLX_ICR_BIT_EEPROM_VALID 0x10000000
+
+#define PLX_ICR_MASK_EEPROM 0x1F000000
+
+#define EEPROM_DELAY 1
+
+/*=============================================================================
+ Bits for the ME4000_AO_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_AO_CTRL_BIT_MODE_0 0x001
+#define ME4000_AO_CTRL_BIT_MODE_1 0x002
+#define ME4000_AO_CTRL_MASK_MODE 0x003
+#define ME4000_AO_CTRL_BIT_STOP 0x004
+#define ME4000_AO_CTRL_BIT_ENABLE_FIFO 0x008
+#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010
+#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020
+#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080
+#define ME4000_AO_CTRL_BIT_ENABLE_DO 0x100
+#define ME4000_AO_CTRL_BIT_ENABLE_IRQ 0x200
+#define ME4000_AO_CTRL_BIT_RESET_IRQ 0x400
+#define ME4000_AO_CTRL_BIT_EX_TRIG_BOTH 0x800
+
+/*=============================================================================
+ Bits for the ME4000_AO_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_AO_STATUS_BIT_FSM 0x01
+#define ME4000_AO_STATUS_BIT_FF 0x02
+#define ME4000_AO_STATUS_BIT_HF 0x04
+#define ME4000_AO_STATUS_BIT_EF 0x08
+
+/*=============================================================================
+ Bits for the ME4000_AI_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_AI_CTRL_BIT_MODE_0 0x00000001
+#define ME4000_AI_CTRL_BIT_MODE_1 0x00000002
+#define ME4000_AI_CTRL_BIT_MODE_2 0x00000004
+#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008
+#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010
+#define ME4000_AI_CTRL_BIT_STOP 0x00000020
+#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040
+#define ME4000_AI_CTRL_BIT_DATA_FIFO 0x00000080
+#define ME4000_AI_CTRL_BIT_FULLSCALE 0x00000100
+#define ME4000_AI_CTRL_BIT_OFFSET 0x00000200
+#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400
+#define ME4000_AI_CTRL_BIT_EX_TRIG 0x00000800
+#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000
+#define ME4000_AI_CTRL_BIT_EX_IRQ 0x00002000
+#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000
+#define ME4000_AI_CTRL_BIT_LE_IRQ 0x00008000
+#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000
+#define ME4000_AI_CTRL_BIT_HF_IRQ 0x00020000
+#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000
+#define ME4000_AI_CTRL_BIT_SC_IRQ 0x00080000
+#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000
+#define ME4000_AI_CTRL_BIT_SC_RELOAD 0x00200000
+#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000
+
+/*=============================================================================
+ Bits for the ME4000_AI_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_AI_STATUS_BIT_EF_CHANNEL 0x00400000
+#define ME4000_AI_STATUS_BIT_HF_CHANNEL 0x00800000
+#define ME4000_AI_STATUS_BIT_FF_CHANNEL 0x01000000
+#define ME4000_AI_STATUS_BIT_EF_DATA 0x02000000
+#define ME4000_AI_STATUS_BIT_HF_DATA 0x04000000
+#define ME4000_AI_STATUS_BIT_FF_DATA 0x08000000
+#define ME4000_AI_STATUS_BIT_LE 0x10000000
+#define ME4000_AI_STATUS_BIT_FSM 0x20000000
+
+/*=============================================================================
+ Bits for the ME4000_IRQ_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_IRQ_STATUS_BIT_EX 0x01
+#define ME4000_IRQ_STATUS_BIT_LE 0x02
+#define ME4000_IRQ_STATUS_BIT_AI_HF 0x04
+#define ME4000_IRQ_STATUS_BIT_AO_0_HF 0x08
+#define ME4000_IRQ_STATUS_BIT_AO_1_HF 0x10
+#define ME4000_IRQ_STATUS_BIT_AO_2_HF 0x20
+#define ME4000_IRQ_STATUS_BIT_AO_3_HF 0x40
+#define ME4000_IRQ_STATUS_BIT_SC 0x80
+
+/*=============================================================================
+ Bits for the ME4000_DIO_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_DIO_CTRL_BIT_MODE_0 0X0001
+#define ME4000_DIO_CTRL_BIT_MODE_1 0X0002
+#define ME4000_DIO_CTRL_BIT_MODE_2 0X0004
+#define ME4000_DIO_CTRL_BIT_MODE_3 0X0008
+#define ME4000_DIO_CTRL_BIT_MODE_4 0X0010
+#define ME4000_DIO_CTRL_BIT_MODE_5 0X0020
+#define ME4000_DIO_CTRL_BIT_MODE_6 0X0040
+#define ME4000_DIO_CTRL_BIT_MODE_7 0X0080
+
+#define ME4000_DIO_CTRL_BIT_FUNCTION_0 0X0100
+#define ME4000_DIO_CTRL_BIT_FUNCTION_1 0X0200
+
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 0X0400
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 0X0800
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 0X1000
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 0X2000
+
+/*=============================================================================
+ Bits for the ME4000_CNT_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_CNT_CTRL_BIT_COUNTER_0 0x00
+#define ME4000_CNT_CTRL_BIT_COUNTER_1 0x40
+#define ME4000_CNT_CTRL_BIT_COUNTER_2 0x80
+
+#define ME4000_CNT_CTRL_BIT_MODE_0 0x00 // Change state if zero crossing
+#define ME4000_CNT_CTRL_BIT_MODE_1 0x02 // Retriggerable One-Shot
+#define ME4000_CNT_CTRL_BIT_MODE_2 0x04 // Asymmetrical divider
+#define ME4000_CNT_CTRL_BIT_MODE_3 0x06 // Symmetrical divider
+#define ME4000_CNT_CTRL_BIT_MODE_4 0x08 // Counter start by software trigger
+#define ME4000_CNT_CTRL_BIT_MODE_5 0x0A // Counter start by hardware trigger
+
+/*=============================================================================
+ Extract information from minor device number
+ ===========================================================================*/
+
+#define AO_BOARD(dev) ((MINOR(dev) >> 6) & 0x3)
+#define AO_PORT(dev) ((MINOR(dev) >> 2) & 0xF)
+#define AO_MODE(dev) (MINOR(dev) & 0x3)
+
+#define AI_BOARD(dev) ((MINOR(dev) >> 3) & 0x1F)
+#define AI_MODE(dev) (MINOR(dev) & 0x7)
+
+#define DIO_BOARD(dev) (MINOR(dev))
+
+#define CNT_BOARD(dev) (MINOR(dev))
+
+#define EXT_INT_BOARD(dev) (MINOR(dev))
+
+/*=============================================================================
+ Circular buffer used for analog input/output reads/writes.
+ ===========================================================================*/
+
+typedef struct me4000_circ_buf {
+ s16 *buf;
+ int volatile head;
+ int volatile tail;
+} me4000_circ_buf_t;
+
+/*=============================================================================
+ Information about the hardware capabilities
+ ===========================================================================*/
+
+typedef struct me4000_ao_info {
+ int count;
+ int fifo_count;
+} me4000_ao_info_t;
+
+typedef struct me4000_ai_info {
+ int count;
+ int sh_count;
+ int diff_count;
+ int ex_trig_analog;
+} me4000_ai_info_t;
+
+typedef struct me4000_dio_info {
+ int count;
+} me4000_dio_info_t;
+
+typedef struct me4000_cnt_info {
+ int count;
+} me4000_cnt_info_t;
+
+typedef struct me4000_board {
+ u16 vendor_id;
+ u16 device_id;
+ me4000_ao_info_t ao;
+ me4000_ai_info_t ai;
+ me4000_dio_info_t dio;
+ me4000_cnt_info_t cnt;
+} me4000_board_t;
+
+static me4000_board_t me4000_boards[] = {
+ {PCI_VENDOR_ID_MEILHAUS, 0x4610, {0, 0}, {16, 0, 0, 0}, {4}, {3}},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4660, {2, 0}, {16, 0, 0, 0}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4661, {2, 0}, {16, 0, 0, 0}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4662, {2, 0}, {16, 8, 0, 0}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4663, {2, 0}, {16, 8, 0, 0}, {4}, {3}},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
+
+ {0},
+};
+
+#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1)
+
+/*=============================================================================
+ PCI device table.
+ This is used by modprobe to translate PCI IDs to drivers.
+ ===========================================================================*/
+
+static struct pci_device_id me4000_pci_table[] __devinitdata = {
+ {PCI_VENDOR_ID_MEILHAUS, 0x4610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4661, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4662, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4682, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4683, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, me4000_pci_table);
+
+/*=============================================================================
+ Global board and subdevice information structures
+ ===========================================================================*/
+
+typedef struct me4000_info {
+ struct list_head list; // List of all detected boards
+ int board_count; // Index of the board after detection
+
+ unsigned long plx_regbase; // PLX configuration space base address
+ unsigned long me4000_regbase; // Base address of the ME4000
+ unsigned long timer_regbase; // Base address of the timer circuit
+ unsigned long program_regbase; // Base address to set the program pin for the xilinx
+
+ unsigned long plx_regbase_size; // PLX register set space
+ unsigned long me4000_regbase_size; // ME4000 register set space
+ unsigned long timer_regbase_size; // Timer circuit register set space
+ unsigned long program_regbase_size; // Size of program base address of the ME4000
+
+ unsigned int serial_no; // Serial number of the board
+ unsigned char hw_revision; // Hardware revision of the board
+ unsigned short vendor_id; // Meilhaus vendor id (0x1402)
+ unsigned short device_id; // Device ID
+
+ int pci_bus_no; // PCI bus number
+ int pci_dev_no; // PCI device number
+ int pci_func_no; // PCI function number
+ struct pci_dev *pci_dev_p; // General PCI information
+
+ me4000_board_t *board_p; // Holds the board capabilities
+
+ unsigned int irq; // IRQ assigned from the PCI BIOS
+ unsigned int irq_count; // Count of external interrupts
+
+ spinlock_t preload_lock; // Guards the analog output preload register
+ spinlock_t ai_ctrl_lock; // Guards the analog input control register
+
+ struct list_head ao_context_list; // List with analog output specific context
+ struct me4000_ai_context *ai_context; // Analog input specific context
+ struct me4000_dio_context *dio_context; // Digital I/O specific context
+ struct me4000_cnt_context *cnt_context; // Counter specific context
+ struct me4000_ext_int_context *ext_int_context; // External interrupt specific context
+} me4000_info_t;
+
+typedef struct me4000_ao_context {
+ struct list_head list; // linked list of me4000_ao_context_t
+ int index; // Index in the list
+ int mode; // Indicates mode (0 = single, 1 = wraparound, 2 = continous)
+ int dac_in_use; // Indicates if already opend
+ spinlock_t use_lock; // Guards in_use
+ spinlock_t int_lock; // Used when locking out interrupts
+ me4000_circ_buf_t circ_buf; // Circular buffer
+ wait_queue_head_t wait_queue; // Wait queue to sleep while blocking write
+ me4000_info_t *board_info;
+ unsigned int irq; // The irq associated with this ADC
+ int volatile pipe_flag; // Indicates broken pipe set from me4000_ao_isr()
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long fifo_reg;
+ unsigned long single_reg;
+ unsigned long timer_reg;
+ unsigned long irq_status_reg;
+ unsigned long preload_reg;
+ struct fasync_struct *fasync_p; // Queue for asynchronous notification
+} me4000_ao_context_t;
+
+typedef struct me4000_ai_context {
+ struct list_head list; // linked list of me4000_ai_info_t
+ int mode; // Indicates mode
+ int in_use; // Indicates if already opend
+ spinlock_t use_lock; // Guards in_use
+ spinlock_t int_lock; // Used when locking out interrupts
+ int number; // Number of the DAC
+ unsigned int irq; // The irq associated with this ADC
+ me4000_circ_buf_t circ_buf; // Circular buffer
+ wait_queue_head_t wait_queue; // Wait queue to sleep while blocking read
+ me4000_info_t *board_info;
+
+ struct fasync_struct *fasync_p; // Queue for asynchronous notification
+
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long channel_list_reg;
+ unsigned long data_reg;
+ unsigned long chan_timer_reg;
+ unsigned long chan_pre_timer_reg;
+ unsigned long scan_timer_low_reg;
+ unsigned long scan_timer_high_reg;
+ unsigned long scan_pre_timer_low_reg;
+ unsigned long scan_pre_timer_high_reg;
+ unsigned long start_reg;
+ unsigned long irq_status_reg;
+ unsigned long sample_counter_reg;
+
+ unsigned long chan_timer;
+ unsigned long chan_pre_timer;
+ unsigned long scan_timer_low;
+ unsigned long scan_timer_high;
+ unsigned long channel_list_count;
+ unsigned long sample_counter;
+ int sample_counter_reload;
+} me4000_ai_context_t;
+
+typedef struct me4000_dio_context {
+ struct list_head list; // linked list of me4000_dio_context_t
+ int in_use; // Indicates if already opend
+ spinlock_t use_lock; // Guards in_use
+ int number;
+ int dio_count;
+ me4000_info_t *board_info;
+ unsigned long dir_reg;
+ unsigned long ctrl_reg;
+ unsigned long port_0_reg;
+ unsigned long port_1_reg;
+ unsigned long port_2_reg;
+ unsigned long port_3_reg;
+} me4000_dio_context_t;
+
+typedef struct me4000_cnt_context {
+ struct list_head list; // linked list of me4000_dio_context_t
+ int in_use; // Indicates if already opend
+ spinlock_t use_lock; // Guards in_use
+ int number;
+ int cnt_count;
+ me4000_info_t *board_info;
+ unsigned long ctrl_reg;
+ unsigned long counter_0_reg;
+ unsigned long counter_1_reg;
+ unsigned long counter_2_reg;
+} me4000_cnt_context_t;
+
+typedef struct me4000_ext_int_context {
+ struct list_head list; // linked list of me4000_dio_context_t
+ int in_use; // Indicates if already opend
+ spinlock_t use_lock; // Guards in_use
+ int number;
+ me4000_info_t *board_info;
+ unsigned int irq;
+ unsigned long int_count;
+ struct fasync_struct *fasync_ptr;
+ unsigned long ctrl_reg;
+ unsigned long irq_status_reg;
+} me4000_ext_int_context_t;
+
+#endif
+
+/*=============================================================================
+ Application include section starts here
+ ===========================================================================*/
+
+/*-----------------------------------------------------------------------------
+ Defines for analog input
+ ----------------------------------------------------------------------------*/
+
+/* General stuff */
+#define ME4000_AI_FIFO_COUNT 2048
+
+#define ME4000_AI_MIN_TICKS 66
+#define ME4000_AI_MAX_SCAN_TICKS 0xFFFFFFFFFFLL
+
+#define ME4000_AI_BUFFER_SIZE (32 * 1024) // Size in bytes
+
+#define ME4000_AI_BUFFER_COUNT ((ME4000_AI_BUFFER_SIZE) / 2) // Size in values
+
+/* Channel list defines and masks */
+#define ME4000_AI_CHANNEL_LIST_COUNT 1024
+
+#define ME4000_AI_LIST_INPUT_SINGLE_ENDED 0x000
+#define ME4000_AI_LIST_INPUT_DIFFERENTIAL 0x020
+
+#define ME4000_AI_LIST_RANGE_BIPOLAR_10 0x000
+#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 0x040
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 0x080
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0
+
+#define ME4000_AI_LIST_LAST_ENTRY 0x100
+
+/* External trigger defines */
+#define ME4000_AI_TRIGGER_SOFTWARE 0x0 // Use only with API
+#define ME4000_AI_TRIGGER_EXT_DIGITAL 0x1
+#define ME4000_AI_TRIGGER_EXT_ANALOG 0x2
+
+#define ME4000_AI_TRIGGER_EXT_EDGE_RISING 0x0
+#define ME4000_AI_TRIGGER_EXT_EDGE_FALLING 0x1
+#define ME4000_AI_TRIGGER_EXT_EDGE_BOTH 0x2
+
+/* Sample and Hold */
+#define ME4000_AI_SIMULTANEOUS_DISABLE 0x0
+#define ME4000_AI_SIMULTANEOUS_ENABLE 0x1
+
+/* Defines for the Sample Counter */
+#define ME4000_AI_SC_RELOAD 0x0
+#define ME4000_AI_SC_ONCE 0x1
+
+/* Modes for analog input */
+#define ME4000_AI_ACQ_MODE_SINGLE 0x00 // Catch one single value
+#define ME4000_AI_ACQ_MODE_SOFTWARE 0x01 // Continous sampling with software start
+#define ME4000_AI_ACQ_MODE_EXT 0x02 // Continous sampling with external trigger start
+#define ME4000_AI_ACQ_MODE_EXT_SINGLE_VALUE 0x03 // Sample one value by external trigger
+#define ME4000_AI_ACQ_MODE_EXT_SINGLE_CHANLIST 0x04 // Sample one channel list by external trigger
+
+/* Staus of AI FSM */
+#define ME4000_AI_STATUS_IDLE 0x0
+#define ME4000_AI_STATUS_BUSY 0x1
+
+/* Voltages for calibration */
+#define ME4000_AI_GAIN_1_UNI_OFFSET 10.0E-3
+#define ME4000_AI_GAIN_1_UNI_FULLSCALE 9950.0E-3
+#define ME4000_AI_GAIN_1_BI_OFFSET 0.0
+#define ME4000_AI_GAIN_1_BI_FULLSCALE 9950.0E-3
+#define ME4000_AI_GAIN_4_UNI_OFFSET 10.0E-3
+#define ME4000_AI_GAIN_4_UNI_FULLSCALE 2450.0E-3
+#define ME4000_AI_GAIN_4_BI_OFFSET 0.0
+#define ME4000_AI_GAIN_4_BI_FULLSCALE 2450.0E-3
+
+/* Ideal digits for calibration */
+#define ME4000_AI_GAIN_1_UNI_OFFSET_DIGITS (-32702)
+#define ME4000_AI_GAIN_1_UNI_FULLSCALE_DIGITS 32440
+#define ME4000_AI_GAIN_1_BI_OFFSET_DIGITS 0
+#define ME4000_AI_GAIN_1_BI_FULLSCALE_DIGITS 32604
+#define ME4000_AI_GAIN_4_UNI_OFFSET_DIGITS (-32505)
+#define ME4000_AI_GAIN_4_UNI_FULLSCALE_DIGITS 31457
+#define ME4000_AI_GAIN_4_BI_OFFSET_DIGITS 0
+#define ME4000_AI_GAIN_4_BI_FULLSCALE_DIGITS 32113
+
+/*-----------------------------------------------------------------------------
+ Defines for analog output
+ ----------------------------------------------------------------------------*/
+
+/* General stuff */
+#define ME4000_AO_FIFO_COUNT (4 * 1024)
+
+#define ME4000_AO_MIN_TICKS 66
+
+#define ME4000_AO_BUFFER_SIZE (32 * 1024) // Size in bytes
+
+#define ME4000_AO_BUFFER_COUNT ((ME4000_AO_BUFFER_SIZE) / 2) // Size in values
+
+/* Conversion modes for analog output */
+#define ME4000_AO_CONV_MODE_SINGLE 0x0
+#define ME4000_AO_CONV_MODE_WRAPAROUND 0x1
+#define ME4000_AO_CONV_MODE_CONTINUOUS 0x2
+
+/* Trigger setup */
+#define ME4000_AO_TRIGGER_EXT_EDGE_RISING 0x0
+#define ME4000_AO_TRIGGER_EXT_EDGE_FALLING 0x1
+#define ME4000_AO_TRIGGER_EXT_EDGE_BOTH 0x2
+
+/* Status of AO FSM */
+#define ME4000_AO_STATUS_IDLE 0x0
+#define ME4000_AO_STATUS_BUSY 0x1
+
+/*-----------------------------------------------------------------------------
+ Defines for eeprom
+ ----------------------------------------------------------------------------*/
+
+#define ME4000_EEPROM_CMD_READ 0x180
+#define ME4000_EEPROM_CMD_WRITE_ENABLE 0x130
+#define ME4000_EEPROM_CMD_WRITE_DISABLE 0x100
+#define ME4000_EEPROM_CMD_WRITE 0x1400000
+
+#define ME4000_EEPROM_CMD_LENGTH_READ 9
+#define ME4000_EEPROM_CMD_LENGTH_WRITE_ENABLE 9
+#define ME4000_EEPROM_CMD_LENGTH_WRITE_DISABLE 9
+#define ME4000_EEPROM_CMD_LENGTH_WRITE 25
+
+#define ME4000_EEPROM_ADR_DATE_HIGH 0x32
+#define ME4000_EEPROM_ADR_DATE_LOW 0x33
+
+#define ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET 0x34
+#define ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE 0x35
+#define ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET 0x36
+#define ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE 0x37
+#define ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET 0x38
+#define ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE 0x39
+
+#define ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET 0x3A
+#define ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE 0x3B
+#define ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET 0x3C
+#define ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE 0x3D
+#define ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET 0x3E
+#define ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE 0x3F
+
+#define ME4000_EEPROM_ADR_LENGTH 6
+#define ME4000_EEPROM_DATA_LENGTH 16
+
+/*-----------------------------------------------------------------------------
+ Defines for digital I/O
+ ----------------------------------------------------------------------------*/
+
+#define ME4000_DIO_PORT_A 0x0
+#define ME4000_DIO_PORT_B 0x1
+#define ME4000_DIO_PORT_C 0x2
+#define ME4000_DIO_PORT_D 0x3
+
+#define ME4000_DIO_PORT_INPUT 0x0
+#define ME4000_DIO_PORT_OUTPUT 0x1
+#define ME4000_DIO_FIFO_LOW 0x2
+#define ME4000_DIO_FIFO_HIGH 0x3
+
+#define ME4000_DIO_FUNCTION_PATTERN 0x0
+#define ME4000_DIO_FUNCTION_DEMUX 0x1
+#define ME4000_DIO_FUNCTION_MUX 0x2
+
+/*-----------------------------------------------------------------------------
+ Defines for counters
+ ----------------------------------------------------------------------------*/
+
+#define ME4000_CNT_COUNTER_0 0
+#define ME4000_CNT_COUNTER_1 1
+#define ME4000_CNT_COUNTER_2 2
+
+#define ME4000_CNT_MODE_0 0 // Change state if zero crossing
+#define ME4000_CNT_MODE_1 1 // Retriggerable One-Shot
+#define ME4000_CNT_MODE_2 2 // Asymmetrical divider
+#define ME4000_CNT_MODE_3 3 // Symmetrical divider
+#define ME4000_CNT_MODE_4 4 // Counter start by software trigger
+#define ME4000_CNT_MODE_5 5 // Counter start by hardware trigger
+
+/*-----------------------------------------------------------------------------
+ General type definitions
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_user_info {
+ int board_count; // Index of the board after detection
+ unsigned long plx_regbase; // PLX configuration space base address
+ unsigned long me4000_regbase; // Base address of the ME4000
+ unsigned long plx_regbase_size; // PLX register set space
+ unsigned long me4000_regbase_size; // ME4000 register set space
+ unsigned long serial_no; // Serial number of the board
+ unsigned char hw_revision; // Hardware revision of the board
+ unsigned short vendor_id; // Meilhaus vendor id (0x1402)
+ unsigned short device_id; // Device ID
+ int pci_bus_no; // PCI bus number
+ int pci_dev_no; // PCI device number
+ int pci_func_no; // PCI function number
+ char irq; // IRQ assigned from the PCI BIOS
+ int irq_count; // Count of external interrupts
+
+ int driver_version; // Version of the driver release
+
+ int ao_count; // Count of analog output channels
+ int ao_fifo_count; // Count fo analog output fifos
+
+ int ai_count; // Count of analog input channels
+ int ai_sh_count; // Count of sample and hold devices
+ int ai_ex_trig_analog; // Flag to indicate if analogous external trigger is available
+
+ int dio_count; // Count of digital I/O ports
+
+ int cnt_count; // Count of counters
+} me4000_user_info_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for analog output
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_ao_channel_list {
+ unsigned long count;
+ unsigned long *list;
+} me4000_ao_channel_list_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for analog input
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_ai_channel_list {
+ unsigned long count;
+ unsigned long *list;
+} me4000_ai_channel_list_t;
+
+typedef struct me4000_ai_timer {
+ unsigned long pre_chan;
+ unsigned long chan;
+ unsigned long scan_low;
+ unsigned long scan_high;
+} me4000_ai_timer_t;
+
+typedef struct me4000_ai_config {
+ me4000_ai_timer_t timer;
+ me4000_ai_channel_list_t channel_list;
+ int sh;
+} me4000_ai_config_t;
+
+typedef struct me4000_ai_single {
+ int channel;
+ int range;
+ int mode;
+ short value;
+ unsigned long timeout;
+} me4000_ai_single_t;
+
+typedef struct me4000_ai_trigger {
+ int mode;
+ int edge;
+} me4000_ai_trigger_t;
+
+typedef struct me4000_ai_sc {
+ unsigned long value;
+ int reload;
+} me4000_ai_sc_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for eeprom
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_eeprom {
+ unsigned long date;
+ short uni_10_offset;
+ short uni_10_fullscale;
+ short uni_2_5_offset;
+ short uni_2_5_fullscale;
+ short bi_10_offset;
+ short bi_10_fullscale;
+ short bi_2_5_offset;
+ short bi_2_5_fullscale;
+ short diff_10_offset;
+ short diff_10_fullscale;
+ short diff_2_5_offset;
+ short diff_2_5_fullscale;
+} me4000_eeprom_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for digital I/O
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_dio_config {
+ int port;
+ int mode;
+ int function;
+} me4000_dio_config_t;
+
+typedef struct me4000_dio_byte {
+ int port;
+ unsigned char byte;
+} me4000_dio_byte_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for counters
+ ----------------------------------------------------------------------------*/
+
+typedef struct me4000_cnt {
+ int counter;
+ unsigned short value;
+} me4000_cnt_t;
+
+typedef struct me4000_cnt_config {
+ int counter;
+ int mode;
+} me4000_cnt_config_t;
+
+/*-----------------------------------------------------------------------------
+ Type definitions for external interrupt
+ ----------------------------------------------------------------------------*/
+
+typedef struct {
+ int int1_count;
+ int int2_count;
+} me4000_int_type;
+
+/*-----------------------------------------------------------------------------
+ The ioctls of the board
+ ----------------------------------------------------------------------------*/
+
+#define ME4000_IOCTL_MAXNR 50
+#define ME4000_MAGIC 'y'
+#define ME4000_GET_USER_INFO _IOR (ME4000_MAGIC, 0, me4000_user_info_t)
+
+#define ME4000_AO_START _IOW (ME4000_MAGIC, 1, unsigned long)
+#define ME4000_AO_STOP _IO (ME4000_MAGIC, 2)
+#define ME4000_AO_IMMEDIATE_STOP _IO (ME4000_MAGIC, 3)
+#define ME4000_AO_RESET _IO (ME4000_MAGIC, 4)
+#define ME4000_AO_PRELOAD _IO (ME4000_MAGIC, 5)
+#define ME4000_AO_PRELOAD_UPDATE _IO (ME4000_MAGIC, 6)
+#define ME4000_AO_EX_TRIG_ENABLE _IO (ME4000_MAGIC, 7)
+#define ME4000_AO_EX_TRIG_DISABLE _IO (ME4000_MAGIC, 8)
+#define ME4000_AO_EX_TRIG_SETUP _IOW (ME4000_MAGIC, 9, int)
+#define ME4000_AO_TIMER_SET_DIVISOR _IOW (ME4000_MAGIC, 10, unsigned long)
+#define ME4000_AO_ENABLE_DO _IO (ME4000_MAGIC, 11)
+#define ME4000_AO_DISABLE_DO _IO (ME4000_MAGIC, 12)
+#define ME4000_AO_FSM_STATE _IOR (ME4000_MAGIC, 13, int)
+
+#define ME4000_AI_SINGLE _IOR (ME4000_MAGIC, 14, me4000_ai_single_t)
+#define ME4000_AI_START _IOW (ME4000_MAGIC, 15, unsigned long)
+#define ME4000_AI_STOP _IO (ME4000_MAGIC, 16)
+#define ME4000_AI_IMMEDIATE_STOP _IO (ME4000_MAGIC, 17)
+#define ME4000_AI_EX_TRIG_ENABLE _IO (ME4000_MAGIC, 18)
+#define ME4000_AI_EX_TRIG_DISABLE _IO (ME4000_MAGIC, 19)
+#define ME4000_AI_EX_TRIG_SETUP _IOW (ME4000_MAGIC, 20, me4000_ai_trigger_t)
+#define ME4000_AI_CONFIG _IOW (ME4000_MAGIC, 21, me4000_ai_config_t)
+#define ME4000_AI_SC_SETUP _IOW (ME4000_MAGIC, 22, me4000_ai_sc_t)
+#define ME4000_AI_FSM_STATE _IOR (ME4000_MAGIC, 23, int)
+
+#define ME4000_DIO_CONFIG _IOW (ME4000_MAGIC, 24, me4000_dio_config_t)
+#define ME4000_DIO_GET_BYTE _IOR (ME4000_MAGIC, 25, me4000_dio_byte_t)
+#define ME4000_DIO_SET_BYTE _IOW (ME4000_MAGIC, 26, me4000_dio_byte_t)
+#define ME4000_DIO_RESET _IO (ME4000_MAGIC, 27)
+
+#define ME4000_CNT_READ _IOR (ME4000_MAGIC, 28, me4000_cnt_t)
+#define ME4000_CNT_WRITE _IOW (ME4000_MAGIC, 29, me4000_cnt_t)
+#define ME4000_CNT_CONFIG _IOW (ME4000_MAGIC, 30, me4000_cnt_config_t)
+#define ME4000_CNT_RESET _IO (ME4000_MAGIC, 31)
+
+#define ME4000_EXT_INT_DISABLE _IO (ME4000_MAGIC, 32)
+#define ME4000_EXT_INT_ENABLE _IO (ME4000_MAGIC, 33)
+#define ME4000_EXT_INT_COUNT _IOR (ME4000_MAGIC, 34, int)
+
+#define ME4000_AI_OFFSET_ENABLE _IO (ME4000_MAGIC, 35)
+#define ME4000_AI_OFFSET_DISABLE _IO (ME4000_MAGIC, 36)
+#define ME4000_AI_FULLSCALE_ENABLE _IO (ME4000_MAGIC, 37)
+#define ME4000_AI_FULLSCALE_DISABLE _IO (ME4000_MAGIC, 38)
+
+#define ME4000_AI_EEPROM_READ _IOR (ME4000_MAGIC, 39, me4000_eeprom_t)
+#define ME4000_AI_EEPROM_WRITE _IOW (ME4000_MAGIC, 40, me4000_eeprom_t)
+
+#define ME4000_AO_SIMULTANEOUS_EX_TRIG _IO (ME4000_MAGIC, 41)
+#define ME4000_AO_SIMULTANEOUS_SW _IO (ME4000_MAGIC, 42)
+#define ME4000_AO_SIMULTANEOUS_DISABLE _IO (ME4000_MAGIC, 43)
+#define ME4000_AO_SIMULTANEOUS_UPDATE _IOW (ME4000_MAGIC, 44, me4000_ao_channel_list_t)
+
+#define ME4000_AO_SYNCHRONOUS_EX_TRIG _IO (ME4000_MAGIC, 45)
+#define ME4000_AO_SYNCHRONOUS_SW _IO (ME4000_MAGIC, 46)
+#define ME4000_AO_SYNCHRONOUS_DISABLE _IO (ME4000_MAGIC, 47)
+
+#define ME4000_AO_EX_TRIG_TIMEOUT _IOW (ME4000_MAGIC, 48, unsigned long)
+#define ME4000_AO_GET_FREE_BUFFER _IOR (ME4000_MAGIC, 49, unsigned long)
+
+#define ME4000_AI_GET_COUNT_BUFFER _IOR (ME4000_MAGIC, 50, unsigned long)
+
+#endif
diff --git a/drivers/staging/me4000/me4000_firmware.h b/drivers/staging/me4000/me4000_firmware.h
new file mode 100644
index 00000000000..87c23f6757b
--- /dev/null
+++ b/drivers/staging/me4000/me4000_firmware.h
@@ -0,0 +1,10033 @@
+/*
+ This file is copyright by Meilhaus Electronic GmbH 2003.
+ You are not allowed to distribute, sell, modify, reverse engineer or use this
+ code (or parts of it) for any other purpose or under any other conditions
+ than stated below.
+
+ 1) You are allowed to distribute verbatim copies of this file together
+ with device drivers for the Meilhaus ME-4000, board family.
+
+ 2) Derived work (device drivers using this file) can be published 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. Any other license terms have
+ to be agreed by Meilhaus GmbH in written.
+
+ 2) This file is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. Meilhaus is under
+ no means liable for products using this file or parts of it.
+
+ 3) The copyright of this file has to be mentioned in derived work.
+
+ 4) If this license terms are not valid due to any other law
+ or restrictions imposed on you, you are not allowed to use
+ this file in any way at all.
+ */
+
+/* Version 18 of standard firmware */
+static unsigned char xilinx_firm[] = {
+0x00, 0x01, 0xfb, 0xdc, 0x01, 0x01, 0x04, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00,
+0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x99, 0xAA, 0x66, 0x0C, 0x00,
+0x01, 0x80, 0x00, 0x00, 0x00, 0xE0, 0x0C, 0x80, 0x06, 0x80, 0x00, 0x00, 0x00,
+0xF0, 0x0C, 0x80, 0x04, 0x80, 0x00, 0x01, 0xFC, 0xB4, 0x0C, 0x00, 0x03, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x90, 0x0C,
+0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x0C, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x6E, 0x0D, 0x01, 0x49, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xFE, 0x4B, 0x02, 0x3E, 0x00, 0xEA, 0x00, 0xA8, 0x00, 0xA0,
+0x0A, 0x80, 0x2A, 0x00, 0xAE, 0x00, 0xB8, 0x02, 0xA0, 0x02, 0x80, 0x28, 0x00,
+0xAA, 0x00, 0xB8, 0x02, 0x60, 0x02, 0x80, 0x0B, 0x00, 0x26, 0x00, 0xB8, 0x00,
+0xE0, 0x02, 0x80, 0x0B, 0x00, 0x2E, 0x00, 0xB8, 0x00, 0xE0, 0x02, 0x80, 0x0B,
+0x00, 0xAE, 0x00, 0xB8, 0x02, 0x80, 0x0A, 0xFC, 0x23, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x5B, 0x00, 0xF3, 0x04, 0xCC, 0x01, 0xF2, 0x96, 0xC2,
+0xDF, 0x30, 0xBB, 0x43, 0xD0, 0x73, 0xB0, 0x8F, 0xC0, 0x3D, 0x02, 0xFB, 0x48,
+0xFC, 0x13, 0x30, 0x13, 0xC0, 0x4F, 0x02, 0x3F, 0x01, 0xDC, 0x13, 0xB0, 0x4F,
+0xC0, 0x4F, 0x00, 0x3B, 0xC9, 0xCC, 0x04, 0xF2, 0x13, 0xC0, 0xFC, 0x00, 0xFB,
+0xC9, 0x8C, 0x27, 0x30, 0x03, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x08, 0x57, 0x40, 0xE1, 0x08, 0x44, 0x03, 0xD0, 0x09, 0x40, 0x13,
+0x01, 0xD1, 0x04, 0xC4, 0x1B, 0x10, 0x6D, 0x40, 0x3C, 0x02, 0xDD, 0x06, 0xF4,
+0x0F, 0x10, 0x11, 0x40, 0x27, 0x11, 0x57, 0x81, 0xC4, 0x0F, 0xD0, 0xBF, 0x40,
+0x64, 0x00, 0x51, 0x04, 0x44, 0x04, 0xD0, 0x11, 0x50, 0x34, 0x00, 0xD1, 0x00,
+0x54, 0x11, 0x14, 0x19, 0x40, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0x00, 0x37, 0x00, 0xC1, 0x00, 0x04, 0x00, 0xD8, 0x48, 0x44, 0x21, 0x00,
+0xC9, 0x00, 0x14, 0x03, 0xD0, 0xCC, 0x64, 0x33, 0x11, 0xCD, 0x06, 0x34, 0x23,
+0x50, 0x00, 0x00, 0x02, 0x01, 0x8D, 0x00, 0x04, 0x23, 0xD0, 0x0C, 0x42, 0x01,
+0x00, 0xC1, 0x00, 0x14, 0x00, 0xD0, 0x00, 0x44, 0x30, 0x09, 0xCD, 0x44, 0x44,
+0x12, 0x10, 0x00, 0x44, 0x47, 0x88, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA8, 0xB5, 0x01, 0xD1, 0x00, 0x44, 0x0A, 0xD8, 0x09, 0x40, 0x27, 0x00, 0xD1,
+0x40, 0x44, 0x03, 0x50, 0x0D, 0x60, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0x50,
+0x01, 0x40, 0x27, 0x10, 0xD5, 0x00, 0x44, 0x03, 0xCA, 0x0D, 0x40, 0x65, 0x00,
+0xC1, 0x00, 0x44, 0xC6, 0xD0, 0x19, 0x40, 0x30, 0x00, 0xD1, 0x00, 0x54, 0x09,
+0x14, 0x11, 0x40, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8,
+0xE3, 0x00, 0xD3, 0x00, 0x4C, 0x0A, 0xF0, 0x0D, 0xC4, 0xF7, 0x00, 0x9B, 0x40,
+0x5C, 0x03, 0xF2, 0x0D, 0xC6, 0x37, 0x10, 0xDB, 0x00, 0x74, 0x03, 0x70, 0xA1,
+0x81, 0x37, 0x00, 0xCF, 0x03, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0xC7, 0x01, 0x93,
+0x00, 0x5D, 0x0C, 0xF0, 0x31, 0xC0, 0x34, 0x00, 0x5F, 0xC0, 0x0C, 0x07, 0x30,
+0x71, 0x80, 0x03, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D,
+0x08, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0xFF, 0x18, 0xFF, 0x04, 0xAC,
+0x03, 0xB1, 0x0D, 0xC8, 0x3D, 0x00, 0xFF, 0x80, 0x7C, 0x03, 0xB4, 0x13, 0xCA,
+0xFF, 0x00, 0xF7, 0x03, 0xE4, 0x43, 0xF0, 0x0E, 0xC1, 0x0E, 0x00, 0xFF, 0x00,
+0xFC, 0x40, 0xF0, 0x0B, 0xE2, 0x3F, 0x00, 0xFF, 0x83, 0xFD, 0x25, 0xF0, 0x0B,
+0xC0, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x00,
+0xD3, 0x00, 0x4C, 0x0A, 0x30, 0x0D, 0xC0, 0xA4, 0x00, 0xD7, 0x00, 0x5C, 0x03,
+0xF0, 0x0D, 0xC0, 0x35, 0x00, 0xD7, 0x00, 0x0C, 0x03, 0x30, 0x41, 0xC4, 0x35,
+0x00, 0xD3, 0x02, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0x05, 0x00, 0xDF, 0x00, 0x7C,
+0x0E, 0x30, 0x01, 0xC1, 0x37, 0x10, 0xD7, 0x04, 0x4C, 0x0B, 0x30, 0x21, 0xC0,
+0x0B, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xF4, 0x01, 0xF5,
+0x00, 0x44, 0x2E, 0x10, 0x09, 0x40, 0x25, 0x00, 0xD1, 0x00, 0xC4, 0x03, 0x10,
+0x0F, 0xC0, 0x3E, 0x00, 0xF1, 0x00, 0xEC, 0x03, 0x10, 0x11, 0xC0, 0x35, 0x00,
+0xD1, 0x01, 0xDC, 0x07, 0x70, 0x2F, 0xC3, 0x23, 0x06, 0xDD, 0x20, 0x64, 0x02,
+0xB0, 0x38, 0x41, 0x37, 0x00, 0xD1, 0x03, 0x6C, 0x29, 0x50, 0xA9, 0x40, 0x4E,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x22, 0x01, 0xD1, 0x00,
+0x04, 0x29, 0x90, 0x04, 0x40, 0x24, 0x00, 0xD5, 0x00, 0x34, 0x03, 0x50, 0x0D,
+0x40, 0x33, 0x00, 0xCD, 0x00, 0x04, 0x03, 0x5D, 0x00, 0x40, 0x12, 0x20, 0x01,
+0x04, 0x10, 0x0B, 0xD0, 0x1C, 0x42, 0x21, 0x80, 0x0D, 0x40, 0x34, 0x08, 0x90,
+0x30, 0x40, 0x31, 0x10, 0xD5, 0x03, 0x04, 0x05, 0x18, 0x18, 0x44, 0x1F, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x68, 0x00, 0xE5, 0x01, 0x84,
+0x07, 0x98, 0x1B, 0x40, 0x69, 0x80, 0xE1, 0x81, 0x24, 0x07, 0x10, 0x9E, 0x40,
+0x78, 0x80, 0xED, 0x01, 0xA4, 0x07, 0x50, 0x52, 0x61, 0x79, 0x00, 0x21, 0x19,
+0x90, 0x07, 0x51, 0x1C, 0x40, 0x6A, 0x00, 0x6D, 0x41, 0xA4, 0x06, 0xD2, 0x12,
+0x40, 0x7B, 0x00, 0xF1, 0x09, 0xE4, 0x45, 0x54, 0x1A, 0x40, 0x12, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x20, 0x02, 0xC3, 0x88, 0x44, 0x02,
+0xB0, 0x88, 0x40, 0x20, 0x00, 0xD7, 0x08, 0x34, 0x03, 0x70, 0x0C, 0x40, 0x37,
+0x02, 0xDD, 0x00, 0x04, 0x03, 0x71, 0x10, 0xC0, 0x16, 0x02, 0x01, 0x80, 0x1C,
+0xC3, 0xF0, 0x0C, 0x40, 0x21, 0x00, 0xCF, 0x09, 0x3C, 0x91, 0xB0, 0x88, 0xC0,
+0x37, 0x00, 0xC7, 0x10, 0x0C, 0x11, 0x38, 0x84, 0xC1, 0x4B, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xB0, 0x2D, 0x00, 0xFF, 0x02, 0xFC, 0x02, 0x60,
+0x0B, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xDC, 0x43, 0x70, 0x0F, 0xC0, 0x3F, 0x04,
+0xF3, 0x00, 0xFC, 0x0B, 0xB0, 0x02, 0xC0, 0x3F, 0x48, 0xFF, 0x00, 0x7C, 0x2B,
+0xF0, 0x8F, 0xC0, 0x2F, 0x00, 0xFF, 0x20, 0x3C, 0x03, 0x90, 0x09, 0xC0, 0x3F,
+0x00, 0xEE, 0x20, 0x7C, 0x01, 0xD4, 0x01, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA0, 0x27, 0x00, 0xDF, 0x0E, 0x7C, 0x00, 0xC0, 0x0D,
+0xC0, 0x75, 0x00, 0xD3, 0x00, 0x7C, 0x53, 0x70, 0x8D, 0xC6, 0xB4, 0x04, 0xDF,
+0x00, 0x7C, 0x13, 0xB0, 0x00, 0xC0, 0x34, 0x10, 0x07, 0x80, 0x5C, 0x13, 0x30,
+0x5C, 0xC1, 0x04, 0x00, 0x9F, 0x40, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x37, 0x00,
+0x5F, 0x00, 0x4C, 0x01, 0x30, 0x09, 0xC0, 0x47, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x88, 0x29, 0x00, 0xED, 0x04, 0xB4, 0x03, 0xD0, 0x0A, 0x40,
+0x3B, 0x00, 0xE1, 0x00, 0xB4, 0x13, 0xD0, 0x4F, 0x40, 0x3A, 0x11, 0xED, 0x00,
+0xB4, 0x03, 0xD0, 0x02, 0x40, 0x39, 0x00, 0xAD, 0x00, 0x04, 0x03, 0x10, 0x2E,
+0x40, 0x08, 0x08, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0A, 0x40, 0x3B, 0x00, 0xED,
+0x20, 0xC4, 0x01, 0x10, 0x0A, 0x40, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x00, 0x69, 0x00, 0xED, 0x01, 0xB4, 0x06, 0x90, 0x3E, 0x4C, 0x6F,
+0x10, 0xE1, 0x01, 0xB4, 0x17, 0xD0, 0x0E, 0x40, 0x7A, 0x00, 0xED, 0x0D, 0x94,
+0x27, 0xD0, 0x13, 0x41, 0x7A, 0x80, 0x6D, 0x01, 0x94, 0x37, 0x51, 0x5E, 0x40,
+0x6A, 0x04, 0xED, 0x01, 0xB4, 0x07, 0xD1, 0x1A, 0x48, 0x7B, 0x80, 0xAD, 0x01,
+0x84, 0x05, 0x14, 0x1E, 0x42, 0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x28, 0x23, 0x84, 0xCD, 0x00, 0x34, 0x2E, 0xD0, 0x08, 0x40, 0x23, 0x49,
+0xC1, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x32, 0x00, 0xCD, 0x00, 0x36, 0x03,
+0xD0, 0x0C, 0x40, 0x33, 0x11, 0xCD, 0x03, 0x04, 0x03, 0x50, 0x0C, 0x40, 0x70,
+0x00, 0xCD, 0x00, 0x34, 0x6F, 0xD2, 0x0C, 0x40, 0x33, 0x00, 0x8D, 0x44, 0x05,
+0x21, 0x14, 0x1C, 0x40, 0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+0xA8, 0xD9, 0x00, 0x5F, 0x00, 0xFC, 0x01, 0xB0, 0x07, 0xC4, 0xDF, 0x01, 0x53,
+0x00, 0x7C, 0x01, 0x78, 0x05, 0xC0, 0x14, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xB0,
+0x17, 0xC0, 0x9E, 0x01, 0x7F, 0x0E, 0x5C, 0x01, 0x74, 0x05, 0xC8, 0x1E, 0x00,
+0x7F, 0x02, 0xFC, 0x0D, 0xE0, 0x07, 0xC0, 0x17, 0x20, 0x7F, 0x07, 0xCC, 0x05,
+0x10, 0x07, 0xC1, 0x5F, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00,
+0x07, 0x02, 0x1F, 0x00, 0x3C, 0x40, 0xF0, 0x41, 0xC0, 0x07, 0x00, 0x1F, 0x60,
+0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC1, 0x05, 0x10, 0x1F, 0x00, 0x7C, 0x80, 0x91, 0x01, 0xD0, 0x87, 0x01, 0x1F,
+0x30, 0x70, 0x08, 0xF0, 0x41, 0xC0, 0x07, 0x18, 0x1F, 0x40, 0x7D, 0x00, 0xF0,
+0x11, 0xC0, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27,
+0x01, 0x9B, 0x00, 0x4D, 0x02, 0x30, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x74,
+0x02, 0xF0, 0x09, 0xC0, 0x23, 0x40, 0x93, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0,
+0x24, 0x00, 0x9F, 0x00, 0x44, 0x02, 0x70, 0x09, 0xC4, 0x67, 0x02, 0x9D, 0x00,
+0x4C, 0x16, 0xF0, 0x19, 0xC0, 0x27, 0x80, 0x9F, 0x03, 0x4C, 0x22, 0x34, 0x08,
+0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x66, 0x00,
+0x95, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02,
+0xD0, 0x09, 0x40, 0x27, 0x00, 0x91, 0x00, 0x74, 0x06, 0xF0, 0xB8, 0x40, 0x24,
+0x00, 0x8D, 0x08, 0x01, 0x06, 0x30, 0x29, 0xC0, 0x27, 0x21, 0x8D, 0x00, 0x44,
+0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x8D, 0x03, 0x6C, 0x1E, 0x54, 0x29, 0x40,
+0x05, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x81,
+0x00, 0x44, 0x22, 0x10, 0x08, 0x40, 0x35, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x26, 0x00, 0x99, 0x00, 0x74, 0x22, 0xD0, 0x09, 0x60, 0x24, 0x80,
+0xDD, 0x80, 0x54, 0x12, 0x00, 0xA9, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x02,
+0xD0, 0x4D, 0x43, 0x27, 0x00, 0x98, 0x10, 0x04, 0x02, 0x10, 0xA9, 0x40, 0x60,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x85, 0x04,
+0x04, 0x1A, 0x14, 0x08, 0x40, 0x20, 0x20, 0x8D, 0x08, 0x34, 0x12, 0xD0, 0x88,
+0x64, 0x23, 0x01, 0x89, 0x08, 0x34, 0x12, 0xD0, 0x09, 0x40, 0x20, 0x02, 0xDD,
+0x00, 0x14, 0x02, 0x14, 0x08, 0x44, 0x23, 0x00, 0x9D, 0x08, 0x04, 0x02, 0xD8,
+0x08, 0x42, 0x23, 0x02, 0x9D, 0x08, 0x24, 0x22, 0x10, 0x48, 0x40, 0x41, 0x88,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x13, 0x0A, 0x4C,
+0x09, 0x30, 0xA1, 0xC0, 0x85, 0x02, 0x1D, 0x02, 0x7C, 0x28, 0xF0, 0x61, 0xC1,
+0x87, 0x02, 0x19, 0x16, 0x74, 0x00, 0xF0, 0x05, 0xC0, 0x84, 0x00, 0x1F, 0x00,
+0x5C, 0x51, 0x70, 0x41, 0x45, 0x07, 0x10, 0x1F, 0x02, 0x4D, 0x01, 0xF0, 0x01,
+0xC4, 0x87, 0x00, 0x0D, 0x02, 0x4C, 0x88, 0x30, 0x01, 0xC4, 0x74, 0xC0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x2F, 0x00, 0x9F, 0x08, 0xFC, 0x0A,
+0xF0, 0x0B, 0xC0, 0x2B, 0x00, 0xBF, 0x04, 0x7C, 0x22, 0xF0, 0x49, 0xC0, 0x27,
+0x02, 0x93, 0x04, 0x7C, 0x22, 0x70, 0x0B, 0xD0, 0x2F, 0x01, 0xBF, 0x00, 0x6C,
+0x02, 0x70, 0x09, 0xC0, 0x2D, 0x10, 0xBF, 0x04, 0xFC, 0x02, 0xF0, 0x0B, 0xC0,
+0x27, 0x01, 0xBF, 0x84, 0xFC, 0x12, 0xF0, 0x8B, 0xC0, 0x67, 0x60, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x00, 0x93, 0x8C, 0xE8, 0x02, 0xF0,
+0x09, 0xC0, 0x27, 0x02, 0x93, 0x60, 0x7C, 0x52, 0x30, 0xC9, 0xC0, 0x25, 0x00,
+0x9B, 0x00, 0xDC, 0x02, 0xF0, 0x0B, 0xC0, 0x27, 0x00, 0xBF, 0x00, 0xCC, 0x02,
+0xB0, 0x0B, 0xC0, 0x2B, 0x28, 0x9F, 0x40, 0xBC, 0x02, 0xF0, 0x0F, 0xC0, 0x24,
+0x20, 0xBF, 0x40, 0xCC, 0x02, 0x30, 0x0B, 0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00, 0x11, 0x0C, 0x44, 0x49, 0xD0, 0x01,
+0x41, 0x07, 0x00, 0x11, 0x14, 0x74, 0x10, 0x10, 0xC1, 0x48, 0x84, 0x04, 0x11,
+0x10, 0x44, 0x20, 0xD2, 0x01, 0x40, 0x07, 0x01, 0x1D, 0x00, 0x50, 0x08, 0x14,
+0x01, 0x40, 0x17, 0x00, 0x1D, 0x14, 0x64, 0x00, 0xD0, 0x01, 0x40, 0x05, 0x0C,
+0x5D, 0x90, 0x54, 0x00, 0x14, 0x01, 0x50, 0x70, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0x27, 0x40, 0x81, 0x04, 0x34, 0x32, 0xD0, 0x08, 0x40,
+0x27, 0x40, 0x85, 0x04, 0x34, 0x52, 0x10, 0x48, 0x40, 0x21, 0x03, 0x89, 0x08,
+0x14, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x05, 0x9D, 0x00, 0x04, 0x22, 0x12, 0x8C,
+0x42, 0x23, 0x00, 0x8D, 0x04, 0x34, 0x02, 0x50, 0x09, 0x40, 0x23, 0x01, 0x8D,
+0x00, 0x44, 0x02, 0x10, 0x08, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA8, 0x25, 0x04, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x69, 0x60, 0x27,
+0x00, 0x95, 0x00, 0x34, 0x02, 0x10, 0x09, 0x60, 0x21, 0x00, 0x91, 0x00, 0x44,
+0x02, 0xD0, 0x29, 0x40, 0x27, 0x80, 0x9C, 0x02, 0x54, 0x02, 0x10, 0x09, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x64, 0x0A, 0xD0, 0x29, 0x40, 0x27, 0x80, 0x8D, 0x08,
+0x54, 0x12, 0x12, 0x19, 0x40, 0x60, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xA8, 0x27, 0x00, 0x93, 0x00, 0x7C, 0x0E, 0xF0, 0x39, 0xE0, 0x27, 0x21,
+0x97, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xC2, 0x25, 0x00, 0x9B, 0x00, 0x5C, 0x02,
+0xF0, 0x29, 0xC0, 0x27, 0x00, 0x9F, 0x03, 0x4C, 0x02, 0xB0, 0x09, 0xC0, 0x67,
+0x00, 0x9F, 0x24, 0x7C, 0x02, 0xF8, 0x88, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x4C,
+0x02, 0x30, 0x59, 0xC0, 0x14, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x00, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x56, 0xF0, 0x19, 0xC0, 0x67, 0x01, 0x9B,
+0x04, 0x7C, 0x02, 0xF4, 0x08, 0xCC, 0x26, 0x00, 0x8F, 0x00, 0x7C, 0x02, 0xF0,
+0x39, 0xC2, 0x27, 0x00, 0x9F, 0x02, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x01,
+0x9F, 0x05, 0x7C, 0x22, 0xF0, 0x19, 0xC2, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF0, 0x08, 0xC0, 0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08,
+0x05, 0x00, 0x0F, 0x00, 0x5C, 0x08, 0xF0, 0x21, 0xC0, 0x85, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xF0, 0x01, 0xE0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x21,
+0xC1, 0x07, 0x00, 0x1B, 0x06, 0x4C, 0x40, 0xF0, 0x01, 0xC1, 0x04, 0x01, 0x13,
+0x02, 0x7C, 0x00, 0xB0, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x4C, 0x20, 0x31,
+0x21, 0x80, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x18,
+0x00, 0x5D, 0x00, 0xC0, 0x05, 0x70, 0x05, 0x40, 0x10, 0x00, 0x5C, 0x00, 0x74,
+0x01, 0xD0, 0x05, 0xC0, 0x15, 0x00, 0x5D, 0x00, 0x74, 0x45, 0xD0, 0x07, 0xC0,
+0x15, 0x00, 0x61, 0x00, 0xDC, 0x4D, 0x70, 0x07, 0x40, 0xDD, 0x40, 0x51, 0x00,
+0xF4, 0x3D, 0x10, 0x77, 0x40, 0x17, 0x40, 0x71, 0x00, 0x84, 0x0D, 0xF0, 0xA7,
+0xC0, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x22, 0x20,
+0xCD, 0x80, 0x10, 0x0F, 0x50, 0x0C, 0x40, 0x33, 0x80, 0xCC, 0x00, 0x34, 0x03,
+0xD0, 0x0C, 0x00, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x02, 0xD0, 0xBC, 0x40, 0x33,
+0x00, 0xC9, 0x01, 0x24, 0x07, 0x50, 0x0C, 0x40, 0xF0, 0x00, 0xC1, 0x20, 0x34,
+0x07, 0x10, 0x4C, 0x60, 0x33, 0x90, 0xC9, 0x00, 0x04, 0x4F, 0x10, 0x2C, 0x42,
+0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0xCD,
+0x04, 0x84, 0x0B, 0x50, 0x1E, 0x40, 0x3A, 0x03, 0xED, 0x08, 0xB4, 0x03, 0xD0,
+0x8E, 0x40, 0x39, 0xA1, 0xED, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x40, 0x7D, 0x00,
+0xFD, 0x42, 0x90, 0x03, 0x50, 0x18, 0x40, 0xFD, 0x10, 0xE1, 0x04, 0xF4, 0x06,
+0x10, 0x0E, 0x40, 0x7B, 0x00, 0xE9, 0x00, 0xC5, 0x01, 0x90, 0x0C, 0x60, 0x12,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x68, 0x00, 0xEF, 0x07,
+0x94, 0x07, 0x70, 0x1F, 0xC8, 0x7B, 0x00, 0xEF, 0x05, 0xB4, 0x0F, 0xF0, 0x1E,
+0x40, 0x7B, 0x04, 0xED, 0x01, 0xBC, 0x07, 0xF2, 0x1A, 0xC8, 0x7B, 0x24, 0xFB,
+0x01, 0xAC, 0x84, 0x70, 0x1A, 0xC0, 0x78, 0x00, 0xE1, 0x09, 0xB4, 0x06, 0x34,
+0x1E, 0xC4, 0x7F, 0x08, 0x79, 0x01, 0xCC, 0x06, 0x32, 0x16, 0xC0, 0x50, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x25, 0x10, 0xDF, 0x02, 0x7C,
+0x03, 0x70, 0xED, 0xC8, 0xB5, 0x21, 0xDF, 0x00, 0x7C, 0x43, 0xF0, 0x0D, 0xC8,
+0x37, 0x02, 0xDF, 0x88, 0x7C, 0x03, 0xD0, 0x09, 0xC0, 0x33, 0x01, 0x93, 0x80,
+0x7C, 0x01, 0x60, 0x01, 0xC0, 0x17, 0x00, 0xDF, 0x2A, 0x7C, 0x00, 0x60, 0x09,
+0xC0, 0xB7, 0x06, 0x97, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC2, 0x43, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x6F, 0x00, 0xFF, 0x03, 0xC8, 0x21,
+0xE0, 0x3E, 0xC2, 0xFC, 0x12, 0xFF, 0x09, 0xEC, 0x07, 0x30, 0x1F, 0xC0, 0x7F,
+0x02, 0xFB, 0x01, 0xDC, 0x27, 0xF0, 0x9F, 0xC0, 0x7D, 0x04, 0xB3, 0x41, 0xBC,
+0x27, 0xB0, 0x13, 0xC0, 0x7F, 0x00, 0xFF, 0x21, 0xFC, 0x06, 0xF0, 0x1F, 0xC0,
+0x7F, 0x00, 0xFF, 0x01, 0xBC, 0x87, 0x30, 0x1F, 0xC0, 0x0B, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x39, 0x10, 0xFD, 0x04, 0x84, 0x01, 0xF0,
+0x0E, 0xC1, 0x3A, 0x00, 0xED, 0x00, 0xEC, 0x03, 0x15, 0x8E, 0x48, 0x3B, 0x40,
+0xF1, 0x00, 0x84, 0x23, 0xD0, 0xA8, 0x40, 0x3B, 0x20, 0x21, 0x00, 0xB4, 0x29,
+0x10, 0x62, 0x40, 0x3B, 0x00, 0xDF, 0x00, 0x84, 0x02, 0xF0, 0x0E, 0x40, 0x3B,
+0x02, 0xED, 0x08, 0xBC, 0x01, 0xB0, 0x0E, 0x41, 0x57, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0xED, 0x00, 0x86, 0x63, 0xD8, 0x0F,
+0x40, 0x38, 0x80, 0xFD, 0x40, 0x84, 0x23, 0x90, 0x0E, 0x40, 0x33, 0x10, 0xE1,
+0x00, 0xB4, 0x23, 0xD2, 0x22, 0x60, 0x39, 0x00, 0xA5, 0x00, 0xB4, 0x00, 0x12,
+0x02, 0x40, 0x2A, 0x00, 0xED, 0x10, 0x94, 0x02, 0xD0, 0x06, 0x40, 0x3B, 0x00,
+0x6D, 0x00, 0xF4, 0x02, 0x10, 0x06, 0x40, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x06, 0x28, 0x23, 0x00, 0xCD, 0x00, 0x04, 0x06, 0x58, 0x3C, 0x40,
+0x32, 0x00, 0xCD, 0x08, 0x24, 0x03, 0x90, 0x0C, 0x42, 0x33, 0x20, 0xC1, 0x00,
+0x16, 0x03, 0xD0, 0x00, 0x40, 0xB3, 0x00, 0x05, 0x0B, 0x36, 0x01, 0x10, 0x00,
+0x40, 0x03, 0x10, 0xCD, 0x40, 0x04, 0x10, 0x51, 0x00, 0x40, 0x33, 0x00, 0x9D,
+0x12, 0x14, 0xAF, 0x90, 0x50, 0x00, 0x1B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA8, 0x25, 0x01, 0xFF, 0x00, 0x4D, 0x22, 0xD0, 0x3F, 0xC0, 0x3C,
+0x00, 0xFF, 0x00, 0xCC, 0x03, 0xB0, 0x0F, 0xC0, 0x3F, 0x00, 0xF3, 0x00, 0x1C,
+0x02, 0xF0, 0x25, 0xC0, 0xBD, 0x02, 0x57, 0x0B, 0x7C, 0x03, 0x11, 0x09, 0xC0,
+0xF7, 0x02, 0xEF, 0x00, 0x5C, 0x0A, 0xD0, 0x9D, 0x40, 0x3F, 0x00, 0x9F, 0x02,
+0x70, 0x03, 0x10, 0x21, 0xC0, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x0A, 0xF0, 0x4D, 0xC4, 0x37, 0x10,
+0xDF, 0x80, 0x7C, 0x83, 0x70, 0x0D, 0xC8, 0x37, 0x00, 0xD7, 0x80, 0x64, 0x02,
+0xF0, 0x3D, 0xC0, 0x37, 0x48, 0x5A, 0x00, 0x7C, 0x03, 0x70, 0x29, 0xC0, 0x67,
+0x00, 0xD7, 0x00, 0x5C, 0x0A, 0xF0, 0x15, 0xC4, 0x37, 0x20, 0x5F, 0x02, 0x7C,
+0x09, 0xF0, 0x29, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x08, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0x30, 0x0F, 0xC0, 0x3D, 0x00, 0xFF,
+0x00, 0xFE, 0x03, 0xF2, 0x0F, 0xC2, 0x3F, 0x80, 0xFF, 0x00, 0xFC, 0x03, 0xB1,
+0x17, 0xC2, 0x3F, 0x00, 0xF3, 0x01, 0xFC, 0x06, 0xF0, 0x0B, 0xC0, 0x7F, 0x00,
+0xFF, 0x00, 0xCC, 0x02, 0xD0, 0x8F, 0xC0, 0x3F, 0x00, 0x31, 0x00, 0xCC, 0x62,
+0x30, 0x03, 0xC0, 0x03, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20,
+0x56, 0x00, 0xDD, 0x00, 0x34, 0x0E, 0xD0, 0x0D, 0x40, 0x37, 0x80, 0xDD, 0x00,
+0x74, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0xA0, 0xDF, 0x20, 0x74, 0x03, 0x31, 0x9D,
+0xC0, 0x31, 0x00, 0x91, 0x0A, 0x74, 0x0F, 0x78, 0x11, 0x40, 0x87, 0x01, 0xDD,
+0x00, 0x6C, 0x44, 0x70, 0x01, 0x41, 0x37, 0x00, 0x13, 0x0F, 0x14, 0x44, 0x10,
+0x39, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xA6,
+0x02, 0xDD, 0x00, 0x74, 0x0C, 0x90, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x80, 0x74,
+0x03, 0xD2, 0x0D, 0x48, 0x37, 0x00, 0xDD, 0x00, 0x74, 0x03, 0x90, 0x05, 0x40,
+0x37, 0x00, 0x55, 0x82, 0x74, 0x12, 0xD0, 0x19, 0x40, 0x17, 0x02, 0xD9, 0x00,
+0x44, 0x04, 0xD0, 0x09, 0x42, 0x33, 0x00, 0x95, 0x00, 0x44, 0x03, 0x10, 0x19,
+0x41, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00,
+0xCD, 0x00, 0x74, 0x00, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x36, 0x03,
+0xD0, 0x0C, 0x40, 0x33, 0x20, 0xC5, 0x00, 0x34, 0x03, 0x10, 0x88, 0x48, 0x35,
+0x00, 0x45, 0x00, 0x34, 0x00, 0x58, 0x08, 0x60, 0x03, 0x00, 0xDD, 0x00, 0x25,
+0x00, 0x50, 0x00, 0x48, 0x33, 0x40, 0x45, 0x00, 0x44, 0x00, 0x11, 0x08, 0x40,
+0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x26, 0x00, 0xFF,
+0x00, 0x7C, 0x00, 0x10, 0x0F, 0xC0, 0x3D, 0x00, 0xDD, 0x00, 0xF4, 0x03, 0xF0,
+0x0D, 0xC0, 0x3F, 0x00, 0xDD, 0x00, 0x7E, 0x03, 0xB0, 0x05, 0x48, 0x3B, 0x00,
+0xD5, 0x00, 0x7C, 0x02, 0xD0, 0x09, 0xC0, 0x07, 0x00, 0xFF, 0x08, 0x4C, 0x00,
+0xF0, 0x01, 0xC0, 0x3F, 0x00, 0x17, 0x00, 0x4D, 0x00, 0x30, 0x09, 0xC0, 0x03,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x1F, 0x00, 0xFF, 0x00,
+0xFC, 0x02, 0x70, 0x0F, 0xC0, 0x3F, 0x00, 0xEF, 0x80, 0xFC, 0x03, 0xF0, 0x0F,
+0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0x71, 0x43, 0xC0, 0x3D, 0x00, 0x3B,
+0x00, 0xFC, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xDC, 0x00, 0x78,
+0x03, 0xC0, 0x3F, 0x00, 0x33, 0x00, 0xFF, 0x80, 0xF0, 0x0B, 0xC2, 0x17, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0F, 0x04, 0x33, 0x01, 0xC4,
+0x02, 0xB8, 0x0B, 0xC0, 0xBF, 0x01, 0xFB, 0x2C, 0xEC, 0x8E, 0x70, 0x2F, 0xC0,
+0x4F, 0x00, 0xF7, 0x18, 0x8C, 0x24, 0xF0, 0x4F, 0xC1, 0x4F, 0x02, 0xFF, 0x44,
+0xDC, 0x27, 0x30, 0x8F, 0xC0, 0x3F, 0x00, 0xE7, 0x00, 0xEC, 0x04, 0xF0, 0x0F,
+0xC0, 0x6C, 0x00, 0xFB, 0x10, 0x9C, 0x52, 0xF0, 0x13, 0xC0, 0x0C, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x87, 0x00, 0x11, 0x00, 0x6C, 0x02,
+0xF0, 0x09, 0x40, 0xBF, 0x00, 0xF1, 0x02, 0x4C, 0x13, 0x10, 0x8F, 0x40, 0x67,
+0x08, 0xF1, 0x02, 0x44, 0x10, 0xD2, 0x3F, 0xC2, 0x23, 0x08, 0xF1, 0x03, 0x44,
+0x13, 0x04, 0x6F, 0x40, 0xFC, 0x20, 0xF1, 0x0B, 0x44, 0x04, 0xD1, 0x3F, 0xC0,
+0x44, 0x00, 0xD5, 0x43, 0x74, 0x04, 0xD0, 0x15, 0xC0, 0x06, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x03, 0x00, 0x01, 0x00, 0x15, 0x00, 0x92,
+0x08, 0x42, 0x33, 0x03, 0xC9, 0x0C, 0x34, 0x03, 0x50, 0x4C, 0x44, 0x07, 0x80,
+0xC5, 0x20, 0x04, 0x12, 0xD0, 0x0C, 0x42, 0x13, 0x10, 0xC9, 0x02, 0x14, 0x03,
+0x10, 0x2C, 0x40, 0xB1, 0x00, 0xC5, 0x00, 0x07, 0x00, 0x50, 0x2C, 0x40, 0x26,
+0x00, 0xC1, 0x20, 0x34, 0x02, 0xD0, 0x05, 0x40, 0x44, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA8, 0x41, 0x04, 0x01, 0x01, 0x54, 0x0E, 0x50, 0x19,
+0x40, 0x37, 0x00, 0xD1, 0x00, 0x44, 0x03, 0x10, 0x0D, 0x40, 0x47, 0x00, 0xD1,
+0x00, 0x44, 0x0C, 0xD0, 0x0D, 0x40, 0x25, 0x04, 0xD5, 0x00, 0x44, 0x03, 0x18,
+0x0D, 0x08, 0x34, 0x00, 0xD1, 0x00, 0x64, 0x04, 0xD0, 0x0D, 0x40, 0x64, 0x00,
+0xD5, 0x00, 0x74, 0x06, 0xD0, 0x35, 0x40, 0x0E, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xA8, 0xC7, 0x00, 0x13, 0x03, 0x54, 0x0C, 0x90, 0x51, 0xC0,
+0x37, 0x00, 0xDB, 0x00, 0x7C, 0x03, 0x70, 0x0D, 0xC4, 0x43, 0x00, 0xD7, 0x00,
+0x4C, 0x0E, 0xF0, 0x0D, 0x48, 0x97, 0x02, 0xDF, 0x00, 0x5C, 0x03, 0x32, 0x0D,
+0xC0, 0x37, 0x10, 0xD7, 0x00, 0x6E, 0x44, 0xF0, 0x0D, 0xD0, 0x62, 0x00, 0xDB,
+0x00, 0x5C, 0x16, 0xF2, 0x1D, 0xE0, 0x08, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x80, 0x05, 0x00, 0x3F, 0x00, 0x6D, 0x80, 0xF0, 0x03, 0xC0, 0x3F,
+0x00, 0xEF, 0x00, 0xEC, 0x03, 0xF8, 0x0D, 0xC0, 0x2F, 0x80, 0xEB, 0x40, 0xFC,
+0x00, 0xF2, 0x0F, 0xC0, 0x4F, 0x00, 0xEB, 0x00, 0xFC, 0x03, 0xF0, 0x0E, 0xC0,
+0x3B, 0x04, 0xFD, 0x80, 0xDC, 0x40, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xFF, 0x00,
+0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x08, 0x85, 0x00, 0x1B, 0x00, 0x4D, 0x08, 0x30, 0x09, 0xC3, 0x33, 0x00,
+0xDF, 0x00, 0x5C, 0x03, 0x70, 0x0D, 0xC0, 0x85, 0x00, 0xDF, 0x00, 0x4C, 0x0A,
+0x30, 0x0D, 0xC6, 0x16, 0x00, 0xD3, 0x10, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0x36,
+0x00, 0xDF, 0x20, 0x4C, 0x08, 0x70, 0x0C, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7E,
+0x42, 0x70, 0x2D, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0xA0, 0x04, 0x00, 0x11, 0x01, 0x44, 0x4E, 0x00, 0x69, 0x40, 0x3F, 0x10, 0xFD,
+0x00, 0x4C, 0x03, 0x10, 0x0F, 0x40, 0xA4, 0x03, 0xFD, 0x00, 0x44, 0x00, 0x12,
+0x0F, 0x40, 0x24, 0x00, 0xF0, 0x03, 0x54, 0x03, 0xD0, 0x0F, 0x40, 0x7C, 0x04,
+0xED, 0x00, 0x45, 0x04, 0xD0, 0x1F, 0x40, 0x47, 0x00, 0xFD, 0x00, 0x74, 0x0E,
+0x10, 0x0D, 0x43, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0,
+0x42, 0x00, 0x09, 0x24, 0x00, 0x46, 0x90, 0x00, 0x40, 0x33, 0x20, 0xC9, 0x00,
+0x52, 0x02, 0xD0, 0x0C, 0x48, 0xA1, 0x00, 0xCC, 0x00, 0x14, 0x00, 0x10, 0x0C,
+0x48, 0x27, 0x60, 0xC1, 0x01, 0x44, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x04, 0x24, 0x04, 0xD0, 0x8C, 0x49, 0x23, 0x12, 0xCD, 0x00, 0x16, 0x04, 0x51,
+0x0D, 0x41, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x48,
+0x24, 0x21, 0x01, 0x84, 0x07, 0x18, 0x1E, 0x40, 0x7B, 0x00, 0xCD, 0x01, 0x94,
+0x07, 0x90, 0x9E, 0x40, 0x78, 0xA0, 0xED, 0x01, 0xD4, 0x04, 0x14, 0x1E, 0x40,
+0x69, 0x00, 0xE1, 0x11, 0x94, 0x07, 0xC0, 0x1C, 0x40, 0x79, 0x00, 0xED, 0x95,
+0x84, 0x05, 0xD2, 0x1E, 0x40, 0x4B, 0x00, 0xED, 0x09, 0xB6, 0x44, 0x10, 0x1F,
+0x40, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00,
+0x1B, 0x10, 0x0D, 0x21, 0xB0, 0x04, 0xC0, 0x33, 0x00, 0xCF, 0x00, 0x5C, 0x03,
+0xF0, 0x0C, 0xC8, 0x81, 0x00, 0xDE, 0x00, 0x1C, 0x03, 0x30, 0x0C, 0xC0, 0x33,
+0x03, 0xC3, 0x80, 0x1C, 0x83, 0xF0, 0x4C, 0xC0, 0x33, 0x00, 0xCF, 0x00, 0x0C,
+0x40, 0x70, 0x0C, 0xE4, 0x23, 0x22, 0xCF, 0x00, 0x1E, 0x14, 0x70, 0x0C, 0xC0,
+0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x2D, 0x12, 0x7F,
+0x08, 0xFC, 0x03, 0x54, 0x0F, 0xC0, 0x3F, 0x80, 0xFF, 0x02, 0xEC, 0x03, 0x70,
+0x0F, 0xC3, 0x1F, 0x00, 0xFF, 0x08, 0xEC, 0x03, 0xF0, 0x2E, 0xC4, 0x3E, 0x02,
+0xEF, 0x10, 0xF8, 0x23, 0xF0, 0x0F, 0xC1, 0x3E, 0x00, 0xFF, 0x06, 0xDC, 0x01,
+0xF0, 0x0F, 0xC0, 0x2F, 0x08, 0xFF, 0x20, 0xFE, 0x20, 0xF2, 0x0C, 0xC0, 0x0B,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x07, 0x00, 0x03, 0x00,
+0x4C, 0x03, 0xF0, 0x05, 0xC0, 0xB7, 0x01, 0xDB, 0x0E, 0x7C, 0x03, 0xF0, 0x5D,
+0xC1, 0x24, 0x00, 0xDF, 0x86, 0x7C, 0x86, 0x70, 0x3D, 0xC0, 0x16, 0x00, 0xDF,
+0x10, 0x7C, 0x03, 0xF0, 0x4D, 0xC1, 0x36, 0x01, 0xDF, 0x01, 0x4C, 0x00, 0xF0,
+0xAC, 0xC0, 0x24, 0x00, 0xDF, 0x01, 0x4C, 0x06, 0x30, 0x0D, 0xC0, 0x54, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x09, 0x08, 0x21, 0x00, 0x84,
+0x03, 0xD0, 0x0E, 0x40, 0xBB, 0x0D, 0xE1, 0x00, 0x9C, 0x03, 0xD0, 0x4E, 0x50,
+0x38, 0x80, 0xED, 0x12, 0xB4, 0x02, 0x10, 0x0E, 0x40, 0x18, 0x00, 0xED, 0x04,
+0xB0, 0x83, 0xD0, 0x4E, 0x42, 0xB8, 0x82, 0xCD, 0x04, 0xA5, 0x01, 0xD0, 0x4E,
+0x49, 0x29, 0x00, 0xED, 0x00, 0x94, 0x00, 0x11, 0x0E, 0xC0, 0x4A, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x49, 0x04, 0x21, 0x01, 0x84, 0x0D,
+0xD0, 0x16, 0x41, 0x73, 0x01, 0xE9, 0x05, 0x94, 0x07, 0xD0, 0x5E, 0x40, 0x68,
+0x00, 0xED, 0x05, 0xB4, 0x07, 0x50, 0x9C, 0x50, 0x79, 0x80, 0xED, 0x01, 0xB4,
+0x87, 0x58, 0x1E, 0x40, 0x78, 0x00, 0xED, 0x08, 0xA4, 0x04, 0x50, 0x1E, 0x40,
+0x78, 0x00, 0xCD, 0x01, 0x04, 0x06, 0x10, 0x1F, 0x40, 0x0C, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x77, 0x20, 0xD1, 0x04, 0x04, 0x07, 0xD0,
+0x3C, 0x41, 0x33, 0x00, 0xC1, 0x40, 0x14, 0xA7, 0xD8, 0x0C, 0x40, 0xB0, 0x00,
+0xCD, 0x00, 0x34, 0x0B, 0x10, 0x0C, 0x40, 0x71, 0x83, 0xCD, 0x00, 0x34, 0x03,
+0xD9, 0x0D, 0x50, 0x30, 0x00, 0xDD, 0x00, 0x24, 0x4B, 0xD1, 0x0C, 0x48, 0x11,
+0x14, 0xCD, 0x00, 0x16, 0x27, 0x10, 0x0C, 0x40, 0x4A, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x17, 0xA8, 0x5D, 0x40, 0x73, 0x00, 0xCD, 0x0D, 0xF0, 0x07,
+0xC0, 0x17, 0x00, 0x5B, 0x00, 0x5C, 0x01, 0xF0, 0x05, 0xC0, 0x18, 0x02, 0x5F,
+0x00, 0xFC, 0x01, 0x70, 0x05, 0xC0, 0x5D, 0x18, 0x5F, 0x00, 0x7C, 0x01, 0xF0,
+0x05, 0xC0, 0x14, 0x00, 0x5D, 0x80, 0xC5, 0x01, 0xF8, 0x05, 0xC0, 0x5C, 0x00,
+0x5F, 0x00, 0xCC, 0x01, 0x30, 0x67, 0xC0, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x00, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x10, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x00, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xF0, 0x01, 0x40, 0x04, 0x20, 0x1F, 0x82, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x01, 0x00, 0x1F, 0x02, 0x5C, 0x80, 0xF0, 0x21, 0xC0, 0x07, 0x02, 0x1F,
+0x00, 0x7C, 0x8C, 0xF0, 0x01, 0xC1, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x67, 0x02, 0x93, 0x00, 0x4C, 0x0E, 0xF0, 0x39, 0xC0, 0x27,
+0x00, 0x97, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x02, 0x93, 0x00, 0x7C,
+0x42, 0xF0, 0x29, 0xC0, 0x27, 0x00, 0x9F, 0x02, 0x7C, 0x02, 0xB2, 0x09, 0xC2,
+0xE5, 0x00, 0x97, 0x05, 0x4C, 0x02, 0xF0, 0x08, 0xD0, 0x24, 0x00, 0x9F, 0x00,
+0x5E, 0x02, 0xF0, 0x29, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x20, 0xE6, 0x60, 0x91, 0x03, 0x44, 0x06, 0xD0, 0x19, 0x40, 0x27, 0x00,
+0x91, 0x00, 0x5C, 0x02, 0xD0, 0x09, 0x46, 0x27, 0x00, 0x95, 0x00, 0x74, 0x02,
+0xD0, 0x19, 0x40, 0x27, 0x00, 0x9D, 0x03, 0x74, 0x02, 0x10, 0x09, 0x48, 0xE4,
+0x04, 0x91, 0x00, 0x44, 0x26, 0xD1, 0x49, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74,
+0x4E, 0xD2, 0x18, 0xC0, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x24, 0x04, 0xD1, 0x08, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x23, 0x00, 0x95,
+0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x04, 0x99, 0x00, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x27, 0x00, 0x95, 0x02, 0x34, 0x02, 0x90, 0x09, 0x60, 0x25, 0x00,
+0x95, 0x40, 0x46, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x01, 0x9D, 0x00, 0x54, 0x22,
+0xD0, 0x09, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x20, 0x01, 0x81, 0x00, 0x04, 0x13, 0xD0, 0xC8, 0x40, 0x23, 0x11, 0x81, 0x0C,
+0x14, 0x22, 0xD0, 0x48, 0x40, 0x23, 0x00, 0x85, 0x04, 0x34, 0x22, 0xD0, 0x48,
+0x60, 0x23, 0x02, 0x8D, 0x00, 0x34, 0x22, 0x10, 0x88, 0x40, 0x20, 0x08, 0x91,
+0x00, 0x04, 0x06, 0xD0, 0x08, 0x40, 0x20, 0x00, 0x8D, 0x04, 0x34, 0x12, 0xD0,
+0x08, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x82,
+0x02, 0x53, 0x0A, 0x4D, 0x30, 0xF0, 0x45, 0xC1, 0x87, 0x02, 0x17, 0x02, 0x7C,
+0x08, 0xF0, 0xA0, 0xC0, 0x07, 0x08, 0x13, 0x0A, 0x3C, 0x08, 0xF0, 0x01, 0xC0,
+0x87, 0x00, 0x17, 0x14, 0x7C, 0x08, 0xB0, 0x60, 0xC1, 0x05, 0x85, 0x56, 0x14,
+0x44, 0x00, 0xF0, 0x41, 0xD1, 0x04, 0x00, 0x1F, 0x14, 0x5C, 0x00, 0xF0, 0x01,
+0xD0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x90, 0x2F, 0x22,
+0xBF, 0x00, 0xFC, 0x33, 0xF0, 0x4B, 0xC0, 0x27, 0x02, 0x9F, 0x0C, 0xDC, 0x12,
+0xF0, 0x89, 0xC0, 0x2F, 0x30, 0x9F, 0x08, 0xFC, 0x12, 0xF0, 0x89, 0xC8, 0x2F,
+0x01, 0x9F, 0x40, 0x7C, 0x12, 0xF0, 0x49, 0xC2, 0x27, 0x08, 0x9F, 0x00, 0xFC,
+0x02, 0xD0, 0x09, 0xC0, 0x2F, 0x08, 0x9F, 0x00, 0xFC, 0x22, 0xF0, 0x0A, 0xC0,
+0x65, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x01, 0xBF,
+0x00, 0xCC, 0x32, 0xE0, 0x0B, 0xC8, 0x24, 0x00, 0x9F, 0x08, 0x6C, 0x02, 0xE0,
+0x49, 0xC1, 0x2E, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x0B, 0xD8, 0x24, 0x20,
+0xBF, 0x34, 0x7C, 0x22, 0xF0, 0x09, 0xE0, 0x2D, 0x00, 0xB3, 0x00, 0xEC, 0x02,
+0xF0, 0x4B, 0xC1, 0x2C, 0x20, 0x9F, 0x55, 0xF8, 0x02, 0xF0, 0x0A, 0xC0, 0x60,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x05, 0x1D, 0x04,
+0x44, 0xB0, 0xD0, 0x25, 0x41, 0x04, 0x04, 0x1D, 0x08, 0x44, 0x50, 0xD2, 0x41,
+0x44, 0x04, 0x00, 0x17, 0x12, 0x74, 0x40, 0x14, 0x81, 0x68, 0x04, 0x05, 0x1D,
+0x00, 0x74, 0x10, 0x71, 0x21, 0x41, 0x04, 0x00, 0x15, 0x08, 0x44, 0x00, 0xD0,
+0x01, 0x40, 0x05, 0x20, 0x1D, 0x00, 0x74, 0x00, 0xD0, 0x01, 0xC0, 0x72, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x03, 0x8D, 0x15, 0x04,
+0x92, 0xD0, 0xC8, 0x40, 0x20, 0x02, 0x8D, 0x00, 0x24, 0x12, 0xD0, 0x48, 0x41,
+0x22, 0x20, 0x8D, 0x0C, 0x36, 0x02, 0x10, 0x08, 0x40, 0x22, 0x21, 0x8D, 0x00,
+0x30, 0x12, 0xD1, 0xC8, 0x40, 0x31, 0x02, 0x81, 0x00, 0x14, 0x02, 0xD0, 0x08,
+0x40, 0x22, 0x00, 0x8D, 0x80, 0x34, 0x02, 0xD0, 0x09, 0x40, 0x40, 0x88, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x65, 0x00, 0x8D, 0x00, 0x44, 0x02,
+0xD0, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x44, 0x22, 0xD0, 0x09, 0x40, 0x24,
+0x00, 0x95, 0x00, 0x74, 0x42, 0x10, 0x09, 0x40, 0x26, 0x06, 0x9D, 0x00, 0x74,
+0x02, 0x50, 0x08, 0x48, 0x34, 0x08, 0x95, 0x20, 0x46, 0x43, 0xD0, 0x09, 0x40,
+0x67, 0x00, 0x9D, 0x00, 0x76, 0x0E, 0xD0, 0x49, 0x40, 0x62, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x88, 0xE7, 0x04, 0x9F, 0x01, 0x4D, 0x02, 0xF0,
+0x39, 0xE0, 0x24, 0x00, 0x9D, 0x00, 0x6C, 0x02, 0xF0, 0x09, 0xC0, 0x26, 0x04,
+0x9F, 0x00, 0x7C, 0x0A, 0x30, 0x09, 0x40, 0x66, 0x00, 0x9F, 0x20, 0x7C, 0x02,
+0xD0, 0x09, 0x40, 0x25, 0x00, 0x93, 0x00, 0x5D, 0x8A, 0xF0, 0x09, 0xC0, 0xE6,
+0x04, 0x9F, 0x00, 0x7C, 0x0E, 0xF0, 0x08, 0x40, 0x14, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x00, 0x9F, 0x04, 0x7C, 0x66, 0xF3, 0x88,
+0xD1, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC8, 0x27, 0x00, 0x9F,
+0x00, 0x7C, 0x26, 0xF0, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x20, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x8F, 0x00, 0x5C, 0x02, 0xF0, 0x08, 0xC1, 0x25, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC1, 0x53, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x08, 0x85, 0x02, 0x1F, 0x00, 0x4D, 0x08, 0xF8, 0x21, 0xC0,
+0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x00, 0xC4, 0x07, 0x00, 0x1F, 0x00,
+0x7C, 0x08, 0xF0, 0x00, 0xC0, 0x84, 0x00, 0x1F, 0x01, 0x4C, 0x00, 0xF0, 0x01,
+0xC0, 0x02, 0x00, 0x13, 0x00, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1F,
+0x00, 0x7C, 0x40, 0x32, 0x01, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0xA0, 0x1C, 0x02, 0x7D, 0x02, 0xC4, 0x01, 0xD0, 0x37, 0xC0, 0x15,
+0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x48, 0x5F, 0x00, 0x5F, 0x00, 0x74,
+0x01, 0xD0, 0x15, 0x01, 0x14, 0x00, 0x7D, 0x05, 0x45, 0x01, 0xF0, 0x05, 0xC0,
+0x1D, 0x00, 0x7F, 0x20, 0xF4, 0x4D, 0xD0, 0x07, 0x40, 0x54, 0x20, 0x5D, 0x00,
+0xF4, 0x01, 0x34, 0x07, 0xD0, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0xA0, 0x72, 0x80, 0x8D, 0x10, 0x04, 0x03, 0xD0, 0xBC, 0x40, 0x31, 0x00,
+0xDD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x06, 0xCD, 0x00, 0x74, 0x03,
+0xD0, 0x18, 0x60, 0x30, 0x00, 0xCD, 0x00, 0x04, 0x03, 0x90, 0x0C, 0x40, 0xB0,
+0x01, 0xC1, 0x12, 0x34, 0x0B, 0xD0, 0x34, 0x50, 0x70, 0x00, 0xCD, 0x00, 0x34,
+0x03, 0x90, 0x0C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x80, 0x28, 0x01, 0x7D, 0x08, 0x84, 0x43, 0xD0, 0x0E, 0x40, 0x39, 0x00, 0xED,
+0x0C, 0xB4, 0x13, 0xDA, 0xCE, 0x40, 0x1B, 0x00, 0xED, 0x08, 0xB4, 0x13, 0xD1,
+0x0B, 0x40, 0x38, 0x21, 0x0D, 0x01, 0x86, 0x23, 0xD2, 0x4C, 0x40, 0x21, 0x00,
+0x65, 0x10, 0xB0, 0x01, 0xD0, 0x0E, 0x41, 0x38, 0x04, 0xED, 0x00, 0xF4, 0x47,
+0x10, 0x0F, 0x40, 0x16, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10,
+0xF8, 0x00, 0xAF, 0x05, 0x8C, 0x07, 0xD0, 0x16, 0xC0, 0x79, 0x00, 0xEF, 0x05,
+0xBC, 0x0F, 0xF0, 0x1E, 0xC4, 0x7B, 0x20, 0xED, 0x11, 0xB4, 0x87, 0xD0, 0x0F,
+0xC0, 0x78, 0x01, 0x2F, 0x21, 0x8C, 0x57, 0xF0, 0xBE, 0xC4, 0x68, 0x00, 0xE1,
+0x01, 0xB0, 0x05, 0xF0, 0x1C, 0xC4, 0x78, 0x00, 0xEF, 0x01, 0xF8, 0x05, 0xB0,
+0x1E, 0xD0, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35,
+0x00, 0x8F, 0x40, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0xB5, 0x00, 0xDF, 0x00, 0x7C,
+0x03, 0xF1, 0x4D, 0xC1, 0x37, 0x00, 0xD6, 0x44, 0x7C, 0xAB, 0xF0, 0x0D, 0xCC,
+0xB7, 0x06, 0x1F, 0x00, 0x6C, 0x03, 0x60, 0x6D, 0xC0, 0x25, 0x00, 0x5F, 0x00,
+0x7C, 0x00, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x80, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x41, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x4F, 0x00,
+0x23, 0x41, 0xDD, 0x27, 0xF8, 0x8F, 0xC0, 0xFF, 0x04, 0xFB, 0x01, 0xDC, 0x07,
+0xF0, 0x9F, 0xC0, 0x6C, 0x02, 0xFF, 0x01, 0xEC, 0x2F, 0xF2, 0x9B, 0xC2, 0x7F,
+0x42, 0x33, 0x01, 0xCC, 0x07, 0xF0, 0x1F, 0xC0, 0x48, 0x00, 0xB3, 0x89, 0xAE,
+0x25, 0x30, 0x1F, 0xC2, 0x7F, 0x02, 0xFF, 0x01, 0xFC, 0x06, 0xF0, 0x1E, 0xC0,
+0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x09, 0x00, 0x61,
+0x08, 0x85, 0x01, 0xD8, 0x0E, 0x41, 0x3F, 0x00, 0xF1, 0x00, 0x84, 0x03, 0xD2,
+0x0F, 0x54, 0x88, 0x20, 0xE7, 0x00, 0x85, 0x23, 0xD0, 0xCA, 0x40, 0x3B, 0x02,
+0x21, 0x08, 0xAC, 0x03, 0x70, 0x0F, 0x48, 0x28, 0x00, 0xEB, 0x00, 0x8C, 0x01,
+0xB0, 0x4A, 0x40, 0x3B, 0x02, 0xED, 0x00, 0x34, 0x1B, 0xD0, 0x0E, 0x50, 0x54,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x04, 0x21, 0x02,
+0x94, 0xC3, 0xD0, 0x86, 0x40, 0x3B, 0x00, 0xE9, 0x00, 0x94, 0x23, 0xD0, 0x0E,
+0x42, 0x38, 0x90, 0xED, 0x00, 0x84, 0x03, 0xD2, 0x0A, 0x00, 0x3F, 0x04, 0x01,
+0x00, 0x84, 0x23, 0xD0, 0x0E, 0x40, 0x09, 0x00, 0xA1, 0x40, 0x97, 0x01, 0x12,
+0x0E, 0x48, 0x2B, 0x10, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x00, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0xA7, 0x01, 0x01, 0x81, 0x44,
+0x0E, 0xD0, 0x31, 0x40, 0x33, 0x00, 0xC1, 0x00, 0x04, 0x03, 0xD8, 0x0C, 0x40,
+0xB0, 0x08, 0xC5, 0x00, 0x04, 0x13, 0xD0, 0x08, 0x60, 0x33, 0x00, 0x01, 0x00,
+0x24, 0x03, 0x58, 0x0C, 0x50, 0x21, 0x00, 0xC9, 0x00, 0x04, 0x40, 0x12, 0x08,
+0x40, 0x23, 0x01, 0xCD, 0x00, 0x74, 0x9E, 0xD1, 0x8C, 0x40, 0x10, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0xFD, 0x40, 0x33, 0x01, 0x5C, 0x04,
+0xD0, 0x19, 0xC0, 0x3F, 0x00, 0xFB, 0x00, 0xD4, 0x03, 0xF0, 0x0F, 0xC0, 0x74,
+0x00, 0xFE, 0x00, 0xCC, 0x03, 0xF0, 0x09, 0xC0, 0xBB, 0x80, 0x13, 0x00, 0xCC,
+0x03, 0xF0, 0x0F, 0x40, 0x25, 0x00, 0xD3, 0x00, 0x5C, 0x05, 0x10, 0x05, 0xC8,
+0x37, 0x00, 0xDF, 0x00, 0x7C, 0x4B, 0xF0, 0x0D, 0xC0, 0x54, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x08, 0x5F, 0x0A, 0x7C, 0x40, 0xF0,
+0x29, 0xC1, 0x37, 0x00, 0xDF, 0x80, 0x7C, 0x23, 0xF3, 0x0D, 0xC4, 0xC7, 0x00,
+0xC4, 0x80, 0x5C, 0x03, 0xF0, 0x09, 0xC0, 0x37, 0x01, 0x1F, 0x00, 0x7C, 0x03,
+0x70, 0x0C, 0xC0, 0x26, 0x00, 0x5F, 0x02, 0x50, 0x05, 0xF0, 0x0D, 0xC0, 0x27,
+0x00, 0xDE, 0x40, 0x7C, 0x03, 0xF0, 0x2D, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x02, 0x33, 0x20, 0xCC, 0x00, 0x30, 0x0B,
+0xC0, 0x3C, 0x00, 0xFE, 0x00, 0xFE, 0x03, 0xB2, 0x0F, 0xC2, 0x7F, 0x05, 0xFF,
+0x00, 0xCD, 0x83, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0x33, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC2, 0x0E, 0x00, 0x0F, 0x01, 0xCD, 0x01, 0x30, 0x4F, 0xC0, 0x7C, 0x01,
+0xEF, 0x00, 0xCC, 0x07, 0x30, 0x1B, 0xC0, 0x00, 0x22, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x20, 0x76, 0x20, 0x05, 0x04, 0x44, 0x04, 0x10, 0x39, 0x41,
+0x34, 0x00, 0xDD, 0x00, 0x34, 0x03, 0x70, 0x0D, 0x40, 0xA7, 0x80, 0xDD, 0x00,
+0x44, 0x03, 0xD0, 0x0D, 0xC0, 0x35, 0x00, 0x11, 0x03, 0x74, 0x03, 0x72, 0x0D,
+0x48, 0x45, 0x00, 0x1D, 0x05, 0x04, 0x08, 0x52, 0x0C, 0x40, 0x24, 0x00, 0xDD,
+0x00, 0x44, 0x09, 0x10, 0x9C, 0x40, 0x04, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0xA0, 0x14, 0x50, 0x11, 0x00, 0x44, 0x06, 0x10, 0x11, 0x60, 0x36,
+0x10, 0xDD, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x4A, 0x07, 0x80, 0xDD, 0x00, 0x44,
+0x03, 0xD0, 0x09, 0x68, 0x37, 0x00, 0x11, 0x03, 0x74, 0x03, 0xD0, 0x0D, 0x40,
+0x44, 0x00, 0x9D, 0x08, 0x44, 0x20, 0x10, 0x0D, 0x40, 0x35, 0x00, 0xDD, 0x00,
+0x54, 0x13, 0x50, 0x05, 0x41, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x22, 0x00, 0x00, 0x51, 0x00, 0x05, 0x04, 0x14, 0x08, 0x50, 0x32, 0x00,
+0xCD, 0x00, 0x74, 0x03, 0x50, 0x0C, 0x40, 0x03, 0x00, 0xCD, 0x80, 0x04, 0x03,
+0xD0, 0x08, 0x40, 0x34, 0x20, 0x01, 0x00, 0x34, 0x03, 0x52, 0x0C, 0x40, 0x21,
+0x10, 0xCD, 0x00, 0x44, 0x00, 0x50, 0x0C, 0x44, 0x20, 0x00, 0xCD, 0x00, 0x45,
+0x0B, 0x14, 0x0D, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xB0, 0x32, 0x00, 0x11, 0x00, 0x4D, 0x02, 0x30, 0x01, 0xC2, 0x3E, 0x10, 0xDF,
+0x00, 0x74, 0x03, 0x30, 0x0F, 0xC0, 0x17, 0x10, 0xED, 0x00, 0xCC, 0x03, 0xF0,
+0x09, 0x88, 0x3F, 0x40, 0x13, 0x40, 0xFC, 0x03, 0xF0, 0x0F, 0xE0, 0x04, 0x20,
+0x1F, 0x00, 0x4E, 0x00, 0x30, 0x0D, 0xC0, 0x24, 0x00, 0xDF, 0x00, 0x4C, 0x0B,
+0x30, 0x01, 0xC0, 0x00, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8,
+0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x02, 0xF1, 0x0B, 0xCA, 0x3D, 0x00, 0xFF, 0x20,
+0xFC, 0x03, 0x70, 0x0F, 0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B,
+0xC0, 0x39, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x40, 0x0F, 0xC0, 0x0D, 0x00, 0x3F,
+0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC8, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x13, 0xF0,
+0x0F, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x3F,
+0x00, 0xFB, 0x1C, 0xEC, 0x05, 0x30, 0x0B, 0xC0, 0x5F, 0x00, 0xBF, 0x00, 0xEC,
+0x03, 0xB0, 0x0F, 0xC1, 0x3F, 0x00, 0x3B, 0x81, 0xEC, 0x33, 0x70, 0x0F, 0xC0,
+0x4F, 0x00, 0x2F, 0x01, 0xFC, 0x84, 0xF0, 0x4F, 0x80, 0x7C, 0x00, 0x7B, 0x01,
+0xBC, 0x04, 0xF0, 0x13, 0xC2, 0x4E, 0x00, 0xFF, 0x01, 0xFE, 0x00, 0xF0, 0x03,
+0x44, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0xFF, 0x02,
+0xF1, 0x02, 0x44, 0x06, 0x14, 0x19, 0x40, 0x26, 0x00, 0x8D, 0x70, 0x74, 0xAF,
+0x10, 0x1F, 0x40, 0xFF, 0x00, 0x9D, 0x01, 0x74, 0x3B, 0x10, 0xBF, 0x40, 0x77,
+0x00, 0xDD, 0x01, 0x74, 0x07, 0xD0, 0xBF, 0x40, 0x38, 0x05, 0x91, 0x01, 0x74,
+0x04, 0xD0, 0x11, 0x40, 0x47, 0x00, 0xDD, 0x00, 0x76, 0x86, 0xD2, 0x19, 0x40,
+0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x20, 0xC8,
+0x04, 0x64, 0x01, 0x50, 0x08, 0x40, 0x21, 0x00, 0x8D, 0x04, 0x06, 0x03, 0x90,
+0x0C, 0x42, 0xB3, 0x00, 0x81, 0x00, 0x34, 0x13, 0x50, 0x0C, 0x60, 0x33, 0x20,
+0xCD, 0x80, 0x34, 0x02, 0x52, 0x0C, 0x60, 0x30, 0x40, 0x85, 0x40, 0x16, 0x00,
+0xD0, 0x00, 0x42, 0x03, 0x00, 0xC5, 0x80, 0x34, 0x00, 0xD2, 0x00, 0x42, 0x47,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xD1, 0x00,
+0x44, 0x02, 0x50, 0x19, 0x40, 0x26, 0x00, 0x9D, 0x23, 0x74, 0x03, 0x50, 0x0D,
+0x40, 0x37, 0x00, 0x9C, 0x01, 0x34, 0x03, 0x10, 0x0D, 0x00, 0x37, 0x00, 0xDD,
+0x06, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0x30, 0x10, 0x95, 0x00, 0x74, 0x0E, 0xD0,
+0x11, 0x40, 0x67, 0x00, 0xDD, 0x00, 0x74, 0x06, 0xC0, 0x19, 0x40, 0x0F, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x37, 0x00, 0xDB, 0x80, 0x2C,
+0x12, 0x71, 0x11, 0xC1, 0x17, 0x01, 0x1F, 0x03, 0x4C, 0x03, 0xB0, 0x0D, 0xC0,
+0x37, 0x00, 0x13, 0x03, 0x6C, 0x03, 0x72, 0x0D, 0xC8, 0x07, 0x01, 0x1E, 0x00,
+0x7C, 0x01, 0xF0, 0x0C, 0xC0, 0x34, 0x00, 0x55, 0x05, 0x7C, 0x04, 0xD0, 0x31,
+0xC0, 0x47, 0x01, 0xDF, 0xA0, 0x74, 0x04, 0xF0, 0x19, 0xC1, 0x03, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x39, 0x00, 0xEF, 0x00, 0xFC, 0x02,
+0xB0, 0x03, 0xC0, 0x2F, 0x00, 0xBF, 0x80, 0xBC, 0x03, 0xB0, 0x0F, 0xC0, 0x3F,
+0x00, 0x3F, 0x00, 0x7C, 0x03, 0xD0, 0x0F, 0xC0, 0x3F, 0x01, 0xFF, 0x41, 0xFC,
+0x03, 0xF0, 0x0F, 0xC1, 0x3F, 0x00, 0xB3, 0x09, 0xF8, 0x02, 0xF0, 0x03, 0xC0,
+0x0F, 0x00, 0xFF, 0x00, 0xF8, 0x40, 0xF0, 0x09, 0xC1, 0x1F, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xD7, 0x00, 0x7C, 0x03, 0xF0,
+0x29, 0xC0, 0x37, 0x00, 0x1F, 0x22, 0x6C, 0x03, 0x30, 0x8D, 0xC0, 0x37, 0x00,
+0x13, 0x46, 0x7C, 0x03, 0xB2, 0x0D, 0xC4, 0x34, 0x00, 0xDF, 0x02, 0x4C, 0x17,
+0xB0, 0x8D, 0xC2, 0x37, 0x10, 0x9F, 0x80, 0x7E, 0x08, 0xB4, 0x81, 0xC8, 0x27,
+0x11, 0xDF, 0x00, 0x5E, 0x00, 0xF0, 0x29, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x3C, 0x00, 0xF1, 0x00, 0x44, 0x12, 0xD0, 0x09,
+0x40, 0x27, 0x22, 0x9D, 0xA0, 0xC4, 0x4B, 0x50, 0x1F, 0x40, 0x3F, 0x00, 0x1A,
+0x03, 0xF4, 0x03, 0x10, 0x0F, 0x40, 0x74, 0x01, 0xDD, 0x00, 0x44, 0x0B, 0x10,
+0x2F, 0x42, 0x37, 0x00, 0x91, 0x0B, 0x74, 0x02, 0x21, 0x01, 0x40, 0xA7, 0x01,
+0xDD, 0x00, 0x46, 0x1A, 0x90, 0x29, 0xC0, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0xA0, 0x32, 0x00, 0xC5, 0x00, 0x14, 0x13, 0xD0, 0x00, 0x40,
+0x32, 0x02, 0x0D, 0x00, 0x24, 0x1F, 0x10, 0x0C, 0x48, 0x33, 0x00, 0x04, 0x00,
+0x34, 0x03, 0x90, 0x0C, 0x40, 0x43, 0x01, 0x0D, 0xA0, 0x26, 0x88, 0x10, 0x2C,
+0x48, 0x33, 0x00, 0xC4, 0x08, 0x34, 0x00, 0x10, 0x50, 0x48, 0x42, 0x20, 0xC9,
+0x80, 0x24, 0x02, 0xD2, 0x20, 0x40, 0x1E, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x80, 0x70, 0x00, 0xC1, 0x01, 0x84, 0x06, 0xD0, 0x1E, 0x40, 0x6B,
+0x00, 0x6D, 0x01, 0x84, 0x07, 0x50, 0x1E, 0x40, 0x7B, 0x02, 0xAD, 0x29, 0xB4,
+0x07, 0x10, 0x1E, 0x40, 0x4B, 0x00, 0x2D, 0x41, 0xB4, 0x07, 0x10, 0x1E, 0x60,
+0x7B, 0x22, 0xE1, 0x41, 0xF4, 0x04, 0x90, 0x92, 0x40, 0x7B, 0x00, 0xED, 0x01,
+0x84, 0x06, 0x90, 0x12, 0x40, 0x1A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x10, 0x30, 0x00, 0xC7, 0x08, 0x1C, 0x03, 0xD0, 0x04, 0xC0, 0x23, 0x00,
+0xCF, 0x00, 0x2E, 0x03, 0x30, 0x0C, 0xE8, 0x33, 0x02, 0x87, 0x12, 0x3C, 0x03,
+0xB0, 0x0C, 0xC1, 0x03, 0x20, 0x0D, 0x01, 0x2D, 0x16, 0x30, 0x8C, 0xC0, 0x33,
+0x00, 0x87, 0x08, 0x34, 0x06, 0x30, 0x50, 0xC2, 0x13, 0x00, 0xCF, 0x00, 0x3C,
+0x03, 0xF0, 0x84, 0xC0, 0x4A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xB8, 0x3D, 0x00, 0xFC, 0x22, 0xDC, 0x02, 0xF0, 0x0F, 0x80, 0x2F, 0x02, 0xFF,
+0x00, 0x9C, 0x63, 0xF0, 0xAF, 0xC0, 0x33, 0x4A, 0x93, 0x00, 0xFC, 0x03, 0xF0,
+0x0E, 0xC1, 0x0C, 0x92, 0x1F, 0x80, 0x0C, 0x23, 0x74, 0x0F, 0xC0, 0x77, 0x00,
+0xB7, 0x08, 0x7C, 0x02, 0x70, 0x87, 0xE0, 0x3F, 0x00, 0xEF, 0x00, 0xFD, 0x02,
+0xF0, 0x0F, 0xC2, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0,
+0xB7, 0x03, 0xDF, 0x02, 0x7C, 0x02, 0x30, 0x05, 0xC0, 0x37, 0x00, 0x7F, 0x01,
+0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0xB7, 0x86, 0x13, 0x01, 0x5C, 0x03, 0x71, 0x5D,
+0xC0, 0x40, 0x90, 0x13, 0x00, 0x7C, 0x01, 0x38, 0x0D, 0xC4, 0x37, 0x00, 0xD3,
+0x80, 0x7C, 0x02, 0xD0, 0x11, 0xC0, 0x24, 0x80, 0xCF, 0x00, 0x4C, 0x00, 0xF1,
+0x01, 0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x39,
+0x03, 0xED, 0x02, 0xB4, 0x02, 0x10, 0x06, 0x40, 0x2B, 0x00, 0xFD, 0x00, 0x84,
+0x93, 0xD0, 0x2E, 0x42, 0x33, 0x21, 0xA1, 0x00, 0x84, 0x13, 0xD0, 0xCE, 0x68,
+0x39, 0x30, 0xE1, 0x00, 0xB4, 0x03, 0x10, 0xCE, 0x40, 0x3F, 0x19, 0xE1, 0x20,
+0xB4, 0x02, 0xD2, 0x02, 0x44, 0x38, 0x10, 0xED, 0x00, 0x84, 0x00, 0xD0, 0x02,
+0x40, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x00,
+0xED, 0x01, 0x94, 0x07, 0x10, 0x1E, 0x41, 0x7B, 0x08, 0x6D, 0x00, 0xB4, 0x07,
+0xD0, 0x5E, 0x40, 0x7B, 0x01, 0xB1, 0x21, 0xB4, 0x27, 0x50, 0x1C, 0x50, 0x3A,
+0x00, 0xE1, 0x01, 0x94, 0x07, 0x91, 0x9E, 0x44, 0x3B, 0x03, 0xA1, 0x01, 0xB4,
+0x46, 0xD8, 0x13, 0x44, 0x78, 0x00, 0xE5, 0x81, 0x84, 0xC7, 0xD0, 0x1A, 0x40,
+0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x08, 0xCD,
+0x00, 0x34, 0x2E, 0x15, 0x2C, 0x41, 0x23, 0x20, 0xCD, 0x13, 0x04, 0x03, 0xD0,
+0x0C, 0x40, 0x33, 0x00, 0xC1, 0x11, 0x24, 0x03, 0xD0, 0x0C, 0x44, 0x37, 0x00,
+0xC1, 0x00, 0x34, 0x87, 0x90, 0x0C, 0x40, 0x37, 0x00, 0x81, 0x00, 0x34, 0x47,
+0xD0, 0x0C, 0x40, 0x30, 0x00, 0xCD, 0x00, 0x04, 0x87, 0xD0, 0xEC, 0x40, 0x4B,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00, 0x5F, 0x00,
+0xBC, 0x0D, 0x30, 0x07, 0xC0, 0x5F, 0x01, 0x7F, 0x40, 0x7C, 0x01, 0xD0, 0x05,
+0xC0, 0x17, 0x10, 0x73, 0x03, 0x7C, 0x01, 0x71, 0x05, 0xC0, 0x9E, 0xC0, 0x73,
+0x09, 0x9C, 0x05, 0x91, 0x05, 0xC0, 0x17, 0x00, 0x61, 0x00, 0xF4, 0x01, 0xF0,
+0x27, 0x40, 0x1C, 0x80, 0x4F, 0x00, 0xC4, 0x8D, 0xF0, 0x37, 0x40, 0x5F, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C,
+0x48, 0xF0, 0x01, 0xC0, 0x87, 0x20, 0x1F, 0x08, 0x7C, 0x00, 0xF0, 0x01, 0xE0,
+0x07, 0x40, 0x1F, 0x08, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x84, 0x26, 0x1F, 0x8A,
+0x7C, 0x20, 0x70, 0x21, 0xC0, 0x07, 0x00, 0x1F, 0x02, 0x7C, 0x08, 0xF2, 0x01,
+0xC0, 0x87, 0x39, 0x1F, 0x00, 0x7D, 0x40, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x9F, 0x00, 0x5C, 0x06,
+0x30, 0x09, 0xC0, 0x67, 0x00, 0x83, 0x00, 0x0C, 0x02, 0xB2, 0x09, 0xC8, 0x27,
+0x02, 0x9B, 0x05, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x20, 0x91, 0x00, 0x7C,
+0x22, 0xB4, 0x98, 0xC0, 0x25, 0x00, 0x93, 0x40, 0x4C, 0x26, 0x30, 0x09, 0xC1,
+0x67, 0x02, 0x9B, 0x00, 0x0C, 0x02, 0x30, 0x39, 0xC0, 0x43, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x14,
+0x09, 0xC0, 0x21, 0x02, 0x95, 0x00, 0x44, 0x02, 0x30, 0x09, 0xC0, 0x23, 0x00,
+0x90, 0x01, 0x74, 0x02, 0xD0, 0x99, 0x40, 0x27, 0x00, 0x91, 0x04, 0x7C, 0x0E,
+0x10, 0x09, 0x40, 0x2C, 0x00, 0x9B, 0x12, 0x2C, 0x0E, 0x14, 0x99, 0x40, 0xE3,
+0x40, 0x91, 0x00, 0x44, 0x0A, 0x50, 0x39, 0x48, 0x07, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x80, 0x8D, 0x00, 0x54, 0x22, 0x10, 0x09,
+0x60, 0x27, 0x00, 0x91, 0x00, 0x44, 0x02, 0x90, 0x09, 0x44, 0x27, 0x00, 0x99,
+0x00, 0x70, 0x02, 0xD8, 0x09, 0x40, 0x67, 0x00, 0x95, 0x20, 0x76, 0x0A, 0x18,
+0x09, 0x41, 0x25, 0x00, 0x91, 0x08, 0x40, 0x02, 0x10, 0x0D, 0x40, 0x27, 0x04,
+0x91, 0x01, 0x44, 0x47, 0x11, 0x29, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0xA0, 0x01, 0x8D, 0x04, 0x04, 0x02, 0x10, 0x48, 0x40,
+0xA5, 0xA0, 0x85, 0x14, 0x04, 0x02, 0x90, 0x08, 0x40, 0x21, 0x00, 0xC9, 0x00,
+0x34, 0x22, 0xD2, 0x08, 0x40, 0x27, 0x00, 0x85, 0x00, 0x74, 0x02, 0x1A, 0x08,
+0x40, 0x20, 0x02, 0x99, 0x20, 0x24, 0x03, 0x10, 0x0C, 0x40, 0x27, 0x00, 0x81,
+0x01, 0x04, 0x12, 0x50, 0x48, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1D, 0x8A, 0x54, 0x01, 0x31, 0x01, 0xC1, 0x97,
+0x00, 0x13, 0x0A, 0x4C, 0x50, 0xB0, 0x41, 0x41, 0x07, 0x05, 0x1B, 0x00, 0x7C,
+0x58, 0xD0, 0x41, 0x41, 0x17, 0x00, 0x17, 0x20, 0x7E, 0x00, 0xB0, 0x41, 0xC1,
+0xC5, 0x00, 0x13, 0x00, 0x4D, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x0A,
+0x4C, 0x00, 0x33, 0x01, 0xC2, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0xB8, 0x67, 0x02, 0x9F, 0x08, 0xBC, 0x02, 0xD0, 0x0B, 0xC8, 0x2D, 0x01,
+0xBF, 0x00, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x00, 0xA6, 0x00, 0x7C, 0x12,
+0xF0, 0x09, 0xC0, 0x2F, 0x00, 0xBB, 0x00, 0x9C, 0x82, 0xF0, 0x09, 0xC0, 0xA7,
+0x09, 0xBF, 0x60, 0xDC, 0x82, 0xF0, 0x0A, 0xC0, 0x2F, 0x08, 0x97, 0x00, 0xFD,
+0x22, 0xF0, 0x8B, 0xC0, 0x67, 0x48, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x27, 0x05, 0x9F, 0x0C, 0xFC, 0x02, 0xF0, 0x09, 0x40, 0x2F, 0x02, 0x9F,
+0x84, 0xF4, 0xD2, 0x70, 0x4B, 0xC0, 0x2C, 0x00, 0xBF, 0x00, 0x7C, 0x22, 0x70,
+0x4B, 0xC0, 0x2C, 0x00, 0xB7, 0x20, 0xFC, 0x02, 0xF0, 0x0B, 0xC2, 0x64, 0x03,
+0xA5, 0x80, 0xCC, 0x02, 0x71, 0x0B, 0x40, 0x2D, 0x00, 0xBB, 0x20, 0xCC, 0x02,
+0xF0, 0x0B, 0x82, 0x64, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08,
+0x47, 0x05, 0x1D, 0x4C, 0x74, 0x00, 0xC0, 0x01, 0x44, 0x07, 0x20, 0x1D, 0xB4,
+0x74, 0x00, 0x70, 0x81, 0x40, 0x84, 0x00, 0x19, 0x80, 0x74, 0xA0, 0xD0, 0x01,
+0x44, 0x06, 0x00, 0x13, 0x80, 0x5C, 0x00, 0xD0, 0x01, 0x40, 0x84, 0x10, 0x57,
+0x00, 0x4C, 0x00, 0xD0, 0x01, 0xC0, 0x15, 0x20, 0x19, 0x50, 0x6C, 0x00, 0xD0,
+0x01, 0x50, 0x70, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23,
+0x00, 0x8D, 0x04, 0x34, 0x02, 0xD0, 0x88, 0x40, 0x23, 0x00, 0x8D, 0x0C, 0x34,
+0x02, 0x50, 0x08, 0x40, 0x20, 0x02, 0x8D, 0x00, 0x34, 0x02, 0x50, 0x88, 0x48,
+0x26, 0x80, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x88, 0x40, 0xA0, 0x20, 0x85, 0x00,
+0x17, 0x82, 0x50, 0x08, 0x40, 0x21, 0x00, 0x8D, 0x00, 0x24, 0x02, 0xD0, 0x08,
+0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00,
+0x9D, 0x00, 0x74, 0x13, 0xD0, 0x09, 0x40, 0xA7, 0x00, 0x9D, 0x10, 0x74, 0x02,
+0x50, 0x09, 0x40, 0x24, 0x00, 0xD9, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x26,
+0x00, 0x91, 0x06, 0x56, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x10, 0x95, 0x08, 0x44,
+0x06, 0xD8, 0x19, 0x40, 0x25, 0x00, 0x99, 0x00, 0x64, 0x06, 0xD0, 0x19, 0x00,
+0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x2D, 0x00, 0x9F,
+0x00, 0x7C, 0x06, 0xF0, 0x59, 0xC0, 0xA7, 0x02, 0x9F, 0x03, 0x7C, 0x02, 0x70,
+0x09, 0xC4, 0x24, 0x00, 0x9F, 0x05, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x60, 0x01,
+0x9F, 0x00, 0x7C, 0x42, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x97, 0x00, 0x5C, 0x46,
+0x70, 0x59, 0xCE, 0xE5, 0x02, 0x9B, 0x00, 0x6C, 0x4E, 0xF0, 0x19, 0xC1, 0x14,
+0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x25, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x29, 0xC0, 0x67, 0x00, 0x9F, 0x04, 0x7C, 0x02, 0xF0, 0x09,
+0x50, 0x27, 0x24, 0x9F, 0x09, 0x7C, 0x02, 0xF0, 0x09, 0xC4, 0x65, 0x02, 0x9F,
+0x41, 0x78, 0x02, 0xF1, 0x08, 0xD0, 0x27, 0x08, 0x9F, 0x01, 0x78, 0x02, 0xF0,
+0x09, 0xC0, 0x67, 0x80, 0x9E, 0x00, 0x78, 0x02, 0xF1, 0x08, 0xC0, 0x53, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x5C,
+0x00, 0xF8, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x80, 0xC0,
+0x07, 0x00, 0x1F, 0x03, 0x7C, 0x00, 0xD2, 0x00, 0xD0, 0x04, 0x00, 0x1F, 0x12,
+0x4C, 0x40, 0xB0, 0x81, 0xC0, 0x04, 0x00, 0x1F, 0x02, 0x7C, 0x18, 0xF0, 0x21,
+0xC0, 0x07, 0x04, 0x13, 0x00, 0x4C, 0x18, 0x30, 0x01, 0xC0, 0x53, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x5D, 0x00, 0xC4, 0x01,
+0x70, 0x05, 0x40, 0x9F, 0x08, 0x51, 0x00, 0xF4, 0x6D, 0xD0, 0x15, 0x40, 0x9F,
+0x00, 0x7D, 0x10, 0x74, 0x01, 0xD1, 0x15, 0x43, 0x9C, 0x10, 0x7D, 0x00, 0xEC,
+0x11, 0x70, 0x37, 0xC8, 0x16, 0x00, 0x6D, 0x10, 0xC5, 0x01, 0xD0, 0x87, 0x40,
+0x5F, 0x04, 0x61, 0x18, 0xC4, 0x09, 0xB0, 0x07, 0x40, 0x53, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x14, 0x01, 0x50,
+0x0C, 0x48, 0xB3, 0x04, 0xC1, 0x00, 0x36, 0x0E, 0xD0, 0x08, 0x40, 0xB3, 0x00,
+0xCD, 0x01, 0x34, 0x03, 0xD8, 0x1C, 0x44, 0xB2, 0x81, 0xCD, 0x0B, 0x24, 0x03,
+0x50, 0x3C, 0x41, 0x31, 0x00, 0xCD, 0x11, 0x04, 0x0E, 0xD0, 0x2C, 0x40, 0x73,
+0x00, 0xC1, 0x40, 0x04, 0x03, 0x10, 0xAC, 0x61, 0x53, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x01, 0xED, 0x09, 0x84, 0x01, 0x50, 0x0E,
+0x40, 0xFB, 0x40, 0xE1, 0x00, 0xB6, 0x02, 0xD0, 0x0E, 0x40, 0x3B, 0x04, 0xED,
+0x20, 0xB4, 0x93, 0xD0, 0x1E, 0x40, 0xAA, 0x08, 0xFD, 0x01, 0xA4, 0x00, 0x51,
+0x0E, 0x40, 0x3B, 0x02, 0x2D, 0x00, 0x86, 0x0A, 0xD0, 0x0E, 0x60, 0x7B, 0x08,
+0xE1, 0x00, 0x05, 0x87, 0x90, 0x0E, 0x60, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x10, 0x78, 0x01, 0xFF, 0x05, 0x9C, 0x05, 0x70, 0x1E, 0xC0,
+0x7F, 0x00, 0xE3, 0x0F, 0xBC, 0x06, 0xF0, 0x1A, 0x40, 0x7B, 0x00, 0x2D, 0x01,
+0xB4, 0x3F, 0xF0, 0x0C, 0xCC, 0x4A, 0x80, 0xEF, 0x01, 0xAE, 0x04, 0x70, 0x1C,
+0xC0, 0x79, 0x05, 0x2D, 0x01, 0x9C, 0x07, 0xE9, 0x1E, 0xC0, 0x7B, 0x40, 0xE1,
+0x21, 0x8C, 0x05, 0x30, 0x16, 0xC0, 0x53, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xB8, 0x35, 0x00, 0xDF, 0x10, 0x7C, 0x01, 0x70, 0x0D, 0xC0, 0x37,
+0x00, 0xDF, 0x04, 0x7C, 0x02, 0xF2, 0x0D, 0xC4, 0x37, 0x00, 0xDF, 0x00, 0x7C,
+0x83, 0xF1, 0x0D, 0xC2, 0x25, 0x00, 0xCF, 0x40, 0x7C, 0x00, 0x60, 0x0D, 0xC0,
+0xB6, 0x20, 0x1F, 0x00, 0x58, 0x83, 0xFA, 0x09, 0xC0, 0x13, 0x08, 0xCF, 0x00,
+0x74, 0x02, 0xF1, 0x05, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xA2, 0x7F, 0x14, 0xFF, 0x01, 0xFC, 0x11, 0xF0, 0x1F, 0xC0, 0x7F, 0x02,
+0xFF, 0x09, 0xFC, 0x06, 0x30, 0x9F, 0xC0, 0x7E, 0x02, 0xFF, 0x09, 0xFC, 0x07,
+0x70, 0x1F, 0xC8, 0x6F, 0x02, 0xEF, 0x41, 0xDC, 0x24, 0xF0, 0x1E, 0xC0, 0x7C,
+0x00, 0x33, 0x09, 0xF8, 0x07, 0xF0, 0x9F, 0xC0, 0x7F, 0x02, 0xFB, 0x41, 0xCC,
+0x05, 0x30, 0x97, 0xC4, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x88, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x41, 0xD1, 0x0E, 0xC0, 0x39, 0x23, 0xED,
+0x08, 0xB4, 0x02, 0xB0, 0x8E, 0x08, 0x38, 0x00, 0xED, 0x08, 0xDC, 0x23, 0x30,
+0x4E, 0x44, 0x6B, 0x2A, 0xC9, 0xC0, 0x10, 0x20, 0xD0, 0x82, 0x40, 0x39, 0x00,
+0x2D, 0x0C, 0x34, 0x07, 0xD0, 0x04, 0x00, 0x3B, 0x07, 0xE7, 0x08, 0xAC, 0x29,
+0x30, 0xAE, 0xC0, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x79, 0x00, 0xED, 0x00, 0xB4, 0x21, 0xD0, 0x0E, 0x40, 0x1B, 0x24, 0xED, 0x40,
+0x96, 0x02, 0x90, 0x8E, 0x48, 0x29, 0x08, 0x2D, 0x00, 0x90, 0x03, 0x50, 0x0A,
+0x48, 0x0B, 0x07, 0x65, 0x18, 0x94, 0x40, 0xD0, 0x0E, 0x40, 0x31, 0x00, 0x2D,
+0x80, 0xB4, 0x43, 0xD0, 0x0E, 0x48, 0x2B, 0x00, 0x65, 0x00, 0x84, 0x01, 0x90,
+0x82, 0x40, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x33,
+0x00, 0xCD, 0x00, 0x34, 0x0D, 0xD0, 0x2C, 0x40, 0xE1, 0x04, 0xCD, 0x02, 0x34,
+0x02, 0x80, 0x0C, 0x50, 0x21, 0x10, 0xCD, 0x12, 0x14, 0x03, 0x10, 0x08, 0x40,
+0x63, 0x11, 0x49, 0x01, 0x04, 0x0C, 0xC0, 0x00, 0x42, 0x31, 0x00, 0x0D, 0x00,
+0x34, 0x4B, 0xD8, 0x90, 0x42, 0x73, 0x01, 0x45, 0x00, 0x24, 0x2E, 0x14, 0x18,
+0x40, 0x19, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00,
+0xFF, 0x00, 0x3C, 0x0F, 0xF0, 0x2D, 0xC1, 0x83, 0x00, 0xFF, 0x05, 0x5E, 0x03,
+0xB0, 0x08, 0xC0, 0x35, 0x00, 0xCF, 0x81, 0xDC, 0x83, 0x70, 0x09, 0xC2, 0x23,
+0x10, 0xD7, 0x00, 0x5C, 0x00, 0xF0, 0x0D, 0xC0, 0x3D, 0x08, 0x17, 0x18, 0x74,
+0x03, 0xF0, 0x39, 0x68, 0x37, 0x10, 0xD7, 0x00, 0x4C, 0x82, 0xB8, 0x59, 0xC0,
+0x77, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xDF,
+0x40, 0x7C, 0x11, 0xF0, 0x4D, 0xC2, 0x87, 0x00, 0xDF, 0x00, 0x7C, 0x0A, 0xF1,
+0x0D, 0x40, 0xB4, 0x00, 0xDF, 0x01, 0x5C, 0x03, 0x70, 0x0D, 0x82, 0xA7, 0x00,
+0xDC, 0x44, 0x7C, 0x00, 0xF2, 0x0D, 0xC0, 0x33, 0x00, 0x16, 0x20, 0x7C, 0x03,
+0xF0, 0x09, 0xC5, 0x36, 0x00, 0xD7, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC9, 0x07,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xFB, 0x00,
+0xFC, 0x0B, 0x30, 0x0E, 0xC0, 0x2C, 0x00, 0xF3, 0x10, 0xFC, 0x27, 0xF0, 0x09,
+0xC0, 0x38, 0x40, 0x33, 0x05, 0xCC, 0x03, 0xF0, 0x0A, 0xC0, 0x0C, 0x00, 0xF3,
+0xA0, 0xE8, 0xC0, 0x30, 0x13, 0xC0, 0x3F, 0x00, 0x3B, 0x01, 0xCC, 0x05, 0xF0,
+0x03, 0xC2, 0x3D, 0x00, 0xFB, 0x01, 0x7C, 0x42, 0xF0, 0x02, 0x40, 0x04, 0x28,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0xD1, 0x00, 0x74,
+0x02, 0x14, 0x0D, 0x60, 0x64, 0x81, 0xD5, 0x00, 0x74, 0x0E, 0xD0, 0x0D, 0x40,
+0x35, 0x81, 0xD1, 0x23, 0x4C, 0x03, 0x30, 0x0D, 0x40, 0xE5, 0x00, 0xC1, 0x00,
+0x10, 0x20, 0xB0, 0x51, 0x40, 0x37, 0x00, 0x05, 0x43, 0x44, 0x15, 0xD0, 0x11,
+0x43, 0x13, 0x00, 0xD1, 0x00, 0x7C, 0x0E, 0xD1, 0x31, 0x50, 0x04, 0x06, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x32, 0x00, 0xD9, 0x00, 0x74, 0x03,
+0x92, 0x0D, 0x50, 0x44, 0x08, 0xD1, 0x00, 0x74, 0xC3, 0xDA, 0x0D, 0x00, 0x14,
+0x20, 0x11, 0x40, 0x64, 0x03, 0xD0, 0x49, 0x40, 0xC4, 0x00, 0x91, 0x08, 0x74,
+0x40, 0x90, 0x4D, 0x40, 0x37, 0x00, 0x15, 0x14, 0x64, 0x23, 0xD1, 0x19, 0x04,
+0x37, 0x00, 0x91, 0x04, 0x74, 0x04, 0xD9, 0x19, 0x40, 0x05, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0xC1, 0x00, 0x74, 0x01, 0x90,
+0x0C, 0x40, 0x04, 0x00, 0xC5, 0x00, 0x34, 0x01, 0xD0, 0x0C, 0x40, 0x11, 0x10,
+0x01, 0x00, 0x24, 0x03, 0x50, 0x0C, 0x46, 0x05, 0xE1, 0x91, 0x02, 0x54, 0x20,
+0x90, 0x00, 0x40, 0x33, 0x00, 0x15, 0x00, 0x05, 0xB3, 0xD8, 0x00, 0x00, 0x33,
+0xC0, 0x81, 0x40, 0x24, 0x00, 0xD0, 0x08, 0x60, 0x40, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x90, 0x3E, 0x00, 0xFB, 0x00, 0x7C, 0x03, 0xB0, 0x0D,
+0x40, 0x04, 0x00, 0xF1, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x04, 0x00, 0x11,
+0x00, 0xEC, 0x03, 0xF0, 0x09, 0xC0, 0x04, 0x05, 0x13, 0x02, 0x6C, 0x00, 0xB0,
+0x01, 0x40, 0x3F, 0x00, 0x17, 0x00, 0x6C, 0x03, 0xF2, 0xA1, 0xC0, 0x27, 0x00,
+0x43, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC8, 0x05, 0x40, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0x70, 0x0F, 0xC0,
+0x2F, 0x00, 0xFF, 0x00, 0xBC, 0x01, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0x3F, 0x00,
+0xD0, 0x03, 0x30, 0x0B, 0xC0, 0x07, 0x10, 0x3F, 0x80, 0xEC, 0x90, 0xF0, 0x03,
+0xC0, 0x3F, 0x00, 0x3C, 0x00, 0x7C, 0x1B, 0xF0, 0x43, 0xC0, 0x3F, 0x00, 0x7F,
+0x00, 0xDC, 0x02, 0xF0, 0x0B, 0xC8, 0x17, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x80, 0x0F, 0x06, 0xAF, 0x00, 0xEC, 0x02, 0xE0, 0x1E, 0xC0, 0x0F,
+0x05, 0xFB, 0x0C, 0xFC, 0x50, 0x30, 0x43, 0xC0, 0x2C, 0x01, 0x33, 0x00, 0xCC,
+0x03, 0x30, 0x1F, 0xC0, 0x0F, 0x05, 0x23, 0x01, 0xEC, 0x03, 0xB0, 0x13, 0xC0,
+0x3F, 0x01, 0x3B, 0x01, 0xC4, 0x06, 0xB6, 0x83, 0xC0, 0x0D, 0x03, 0x37, 0x00,
+0xAC, 0x27, 0x30, 0x1E, 0xC0, 0x0E, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x10, 0x87, 0x01, 0x9D, 0x01, 0x44, 0x00, 0xD0, 0x0D, 0x40, 0x83, 0x00,
+0xF1, 0x08, 0x74, 0x10, 0x10, 0x09, 0x40, 0xB4, 0x07, 0x55, 0x10, 0x84, 0x2B,
+0x10, 0x41, 0xC3, 0x44, 0x00, 0x11, 0x01, 0xC4, 0x07, 0xB0, 0x15, 0xC0, 0xBD,
+0x12, 0xD1, 0x01, 0x44, 0x42, 0x10, 0xE1, 0x40, 0x90, 0x03, 0x11, 0x23, 0x44,
+0x12, 0x10, 0x11, 0x40, 0x0C, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+0xA0, 0x03, 0x00, 0x8D, 0x80, 0x14, 0x06, 0xC0, 0x0C, 0x40, 0x01, 0x00, 0xC9,
+0x04, 0x36, 0x40, 0x10, 0x64, 0x49, 0x20, 0x09, 0x01, 0x08, 0x04, 0xC3, 0x10,
+0x44, 0x40, 0x13, 0x00, 0x01, 0x00, 0x14, 0x0B, 0x98, 0x08, 0x42, 0x33, 0x95,
+0x15, 0x00, 0x64, 0x13, 0x10, 0x48, 0x48, 0x01, 0x00, 0x05, 0x82, 0x76, 0x11,
+0x11, 0x0C, 0x50, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0,
+0x45, 0x00, 0xDD, 0x22, 0x54, 0x04, 0xD1, 0x0D, 0x40, 0x47, 0x10, 0xD1, 0x00,
+0x74, 0x09, 0x10, 0x0D, 0x40, 0x34, 0x00, 0xD5, 0x10, 0x44, 0x03, 0x10, 0x21,
+0x40, 0x84, 0x00, 0x11, 0x01, 0x54, 0x03, 0x80, 0x0D, 0x42, 0x35, 0x00, 0x15,
+0x10, 0x64, 0x02, 0x10, 0x09, 0x44, 0x25, 0x04, 0xD5, 0x14, 0x54, 0x03, 0x10,
+0x09, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x47,
+0x00, 0x9F, 0x09, 0x7D, 0x04, 0xF0, 0x9D, 0xC0, 0xC7, 0x20, 0xDB, 0x80, 0x7C,
+0x09, 0x31, 0x51, 0xC0, 0x64, 0x02, 0x13, 0x02, 0x4C, 0x03, 0x30, 0x2D, 0xC0,
+0xC7, 0x42, 0x13, 0x01, 0x7C, 0x03, 0xB0, 0x89, 0xC0, 0x37, 0x00, 0x9F, 0x02,
+0x2D, 0x02, 0xB1, 0xB5, 0xC0, 0x85, 0x00, 0x05, 0x03, 0x7C, 0x6F, 0x24, 0x1C,
+0x80, 0x8A, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0D, 0x00,
+0xAF, 0x00, 0xEC, 0x00, 0xF0, 0x0F, 0xC0, 0x0B, 0x10, 0xFF, 0x00, 0xBC, 0x02,
+0xF2, 0x91, 0xC0, 0x7B, 0x00, 0x2F, 0x00, 0xBC, 0x03, 0xF0, 0x57, 0xC0, 0x2D,
+0x00, 0x3E, 0x00, 0xAC, 0x83, 0xF0, 0x0B, 0xC8, 0x3B, 0x00, 0xFB, 0x49, 0xDC,
+0x02, 0xD0, 0x12, 0xC0, 0x1A, 0x40, 0xFB, 0x00, 0xEC, 0x03, 0xF4, 0x5F, 0xC0,
+0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x05, 0x80, 0x9F,
+0x07, 0x6C, 0x02, 0x70, 0x8D, 0xC0, 0x06, 0x00, 0xD3, 0x20, 0x5E, 0x09, 0x38,
+0x00, 0xC0, 0x24, 0x02, 0x5F, 0x00, 0x4C, 0x03, 0x30, 0x0D, 0xC0, 0x93, 0x00,
+0x1F, 0x06, 0x4C, 0x63, 0x30, 0x09, 0xC0, 0x34, 0x20, 0x1B, 0x20, 0x4E, 0x03,
+0xF1, 0x0D, 0xC0, 0x96, 0x0A, 0x17, 0x02, 0x6C, 0x43, 0x30, 0x0D, 0xC0, 0x28,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x44, 0x86, 0xDD, 0xC2,
+0x44, 0xE8, 0x12, 0x1D, 0x40, 0x04, 0x00, 0xF1, 0x00, 0x6C, 0x03, 0x31, 0x01,
+0x40, 0xF4, 0x02, 0xDD, 0x04, 0xC4, 0x03, 0x10, 0x05, 0xC6, 0xE7, 0x81, 0x0F,
+0x40, 0xD0, 0x0B, 0xB1, 0x1D, 0x40, 0x3D, 0x00, 0x41, 0x00, 0x4C, 0x02, 0x70,
+0x09, 0x44, 0x34, 0x12, 0xDB, 0x1B, 0x08, 0x43, 0x10, 0x7D, 0x40, 0x4D, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x02, 0x30, 0x0D, 0x00, 0x04,
+0x06, 0x10, 0x58, 0x50, 0x00, 0x00, 0xC1, 0x00, 0x24, 0x02, 0x90, 0x00, 0x40,
+0x30, 0x00, 0x8D, 0x01, 0x04, 0x27, 0x10, 0x09, 0x40, 0x23, 0x21, 0x09, 0x42,
+0x04, 0x0F, 0x50, 0xF4, 0x48, 0x30, 0x10, 0x41, 0x00, 0x06, 0x02, 0xDA, 0x00,
+0x00, 0x62, 0x40, 0xCC, 0x03, 0x01, 0x07, 0x58, 0x7C, 0x40, 0x0C, 0x20, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4A, 0x00, 0x6D, 0x01, 0x84, 0x07,
+0x12, 0x1F, 0x44, 0x48, 0x00, 0xE1, 0x01, 0x24, 0x04, 0x10, 0x9A, 0x40, 0x78,
+0x80, 0x4D, 0x01, 0x84, 0x27, 0x10, 0x1A, 0x42, 0x59, 0x00, 0x35, 0x01, 0x94,
+0x03, 0xDC, 0x16, 0x60, 0x71, 0x02, 0xE1, 0x01, 0x84, 0x06, 0x50, 0x94, 0x40,
+0x78, 0x83, 0xE9, 0x09, 0xC4, 0x27, 0x50, 0x16, 0x40, 0x35, 0x20, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x82, 0x00, 0x8D, 0x00, 0x4C, 0x23, 0x70,
+0x88, 0xC0, 0x80, 0x42, 0xD3, 0x00, 0x34, 0x02, 0x90, 0x84, 0xC4, 0x30, 0x00,
+0x8D, 0x00, 0x0C, 0x03, 0x30, 0x44, 0x40, 0x33, 0x01, 0x0D, 0x08, 0x0C, 0x13,
+0x50, 0x04, 0x40, 0x30, 0x00, 0x03, 0x08, 0x0C, 0x83, 0xF0, 0xA0, 0xD0, 0x02,
+0x01, 0x07, 0x88, 0x0C, 0x23, 0x70, 0x4C, 0xC0, 0x48, 0x40, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xB8, 0x0D, 0x00, 0xFF, 0x08, 0xDE, 0x03, 0xF4, 0x0F,
+0xC2, 0x0D, 0x00, 0xFF, 0x00, 0xFC, 0x01, 0xF0, 0x8F, 0xC2, 0x3F, 0x00, 0xFF,
+0x40, 0xFC, 0x03, 0xF0, 0x03, 0xC0, 0x1F, 0x00, 0x3F, 0x08, 0xBC, 0x1B, 0x30,
+0x8E, 0xC0, 0x3F, 0x00, 0xA7, 0xA0, 0xFD, 0x02, 0xF0, 0x87, 0xC0, 0x2F, 0x41,
+0xEF, 0x08, 0x7C, 0x23, 0xB0, 0x0D, 0xC4, 0x0B, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA8, 0x0F, 0x00, 0x1F, 0x00, 0x4C, 0x01, 0xE1, 0x09, 0xC0,
+0x07, 0x08, 0xDF, 0x06, 0x5C, 0x03, 0xF0, 0x1D, 0xC0, 0x34, 0x00, 0x93, 0x00,
+0x4C, 0x27, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x1B, 0x00, 0x7C, 0x23, 0xF8, 0x11,
+0xC0, 0x36, 0x03, 0xDB, 0x00, 0x7C, 0x02, 0xF0, 0x1D, 0xC0, 0x24, 0x00, 0x13,
+0x20, 0x4D, 0x03, 0x30, 0x0D, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x98, 0x29, 0x00, 0x6D, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x0B,
+0x00, 0xFD, 0x12, 0x84, 0x02, 0xD0, 0x0F, 0x48, 0x38, 0x00, 0x21, 0x00, 0x04,
+0x33, 0x14, 0x0A, 0x40, 0x3B, 0x40, 0x22, 0x00, 0xB4, 0x13, 0xD0, 0x0A, 0x40,
+0x3C, 0x02, 0xE1, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x52, 0x3D, 0x00, 0xC5, 0x00,
+0x84, 0x02, 0x10, 0x0E, 0x40, 0x4F, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x00, 0xF9, 0x00, 0x8D, 0x01, 0x94, 0x0F, 0xD0, 0x1A, 0x40, 0x5B, 0x08,
+0xED, 0x01, 0x94, 0x07, 0xD0, 0x3E, 0x40, 0x78, 0x40, 0xC1, 0x11, 0xA5, 0x07,
+0x18, 0x1E, 0x40, 0x73, 0x00, 0x21, 0x01, 0xB4, 0x07, 0x50, 0x17, 0x46, 0x79,
+0x01, 0xE9, 0x01, 0xB4, 0x07, 0xD2, 0x1C, 0x70, 0x58, 0x00, 0x21, 0x01, 0x86,
+0x47, 0x10, 0x1E, 0x41, 0x13, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x20, 0xB3, 0x00, 0xCD, 0x00, 0x14, 0x03, 0xD0, 0x0C, 0x40, 0xB7, 0x00, 0xCD,
+0x00, 0x04, 0x17, 0xD8, 0x0C, 0x40, 0x34, 0x00, 0xC1, 0x00, 0x24, 0x03, 0x10,
+0x2C, 0x40, 0xB3, 0x01, 0xC1, 0x07, 0x34, 0x03, 0xD8, 0x2C, 0x40, 0x31, 0x00,
+0xC1, 0x48, 0x74, 0x02, 0xD0, 0x2C, 0x64, 0x71, 0x80, 0xC5, 0x0B, 0x04, 0x9B,
+0x12, 0x3C, 0x60, 0x5B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0,
+0x1F, 0x00, 0x6F, 0x00, 0xDD, 0x0D, 0xF0, 0x05, 0xC0, 0x1F, 0x00, 0x5F, 0x00,
+0xDC, 0x49, 0xF0, 0x07, 0xD0, 0x14, 0x00, 0x73, 0x01, 0x6C, 0x01, 0x30, 0xD7,
+0xC0, 0x9B, 0x40, 0x73, 0x11, 0x7C, 0x01, 0xF0, 0xB7, 0x54, 0x17, 0x00, 0x7B,
+0x02, 0x7C, 0x01, 0xF0, 0x47, 0xC0, 0x5C, 0x09, 0x73, 0x80, 0x8C, 0x05, 0x35,
+0x06, 0xC0, 0x5F, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05,
+0x00, 0x1F, 0x00, 0x6C, 0x98, 0xF2, 0x01, 0xC0, 0x07, 0x04, 0x0F, 0x00, 0x7C,
+0x00, 0xF0, 0x41, 0xC0, 0x07, 0x08, 0x0F, 0x02, 0x5C, 0x80, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x82, 0x7C, 0x80, 0xF0, 0x81, 0xC0, 0x04, 0x00, 0x1F, 0x04,
+0x7C, 0x00, 0xB8, 0x01, 0xC1, 0x07, 0x00, 0x0F, 0x12, 0x7C, 0x00, 0xF0, 0x21,
+0xC5, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x61, 0x04,
+0x93, 0x00, 0x0D, 0x0E, 0x30, 0x19, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x1C, 0x02,
+0xB4, 0x09, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x4D, 0x02, 0xF0, 0x09, 0xC8, 0x27,
+0x02, 0x9F, 0x40, 0x7C, 0x02, 0xF2, 0x89, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x7C,
+0x02, 0x30, 0x09, 0xC8, 0x23, 0x20, 0x9B, 0x01, 0x4D, 0x22, 0x70, 0x19, 0xC2,
+0x41, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x02, 0x95,
+0x02, 0x44, 0x0E, 0x14, 0x09, 0x42, 0x27, 0x00, 0x91, 0x00, 0x44, 0x02, 0x10,
+0x09, 0x48, 0x27, 0x08, 0x91, 0x12, 0x44, 0x42, 0xD0, 0x09, 0x44, 0x67, 0x10,
+0x91, 0x00, 0x74, 0x46, 0xD0, 0x39, 0xE0, 0x25, 0x00, 0x93, 0x00, 0x5C, 0x02,
+0x50, 0x09, 0x40, 0x27, 0x00, 0x91, 0x03, 0x4C, 0x02, 0x10, 0xA9, 0x40, 0x04,
+0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x24, 0x00, 0x91, 0x02,
+0x44, 0x02, 0x90, 0x89, 0x40, 0x27, 0x00, 0x91, 0x00, 0x54, 0x02, 0x10, 0x09,
+0x40, 0x27, 0x00, 0x9D, 0x40, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x20, 0xD5,
+0x00, 0x74, 0x12, 0xD8, 0x0D, 0x45, 0x23, 0x00, 0x95, 0x00, 0x74, 0x02, 0x10,
+0x09, 0x40, 0x27, 0x40, 0x99, 0x88, 0x44, 0x42, 0x50, 0x09, 0x42, 0x71, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x28, 0x20, 0x01, 0x85, 0x04, 0x04,
+0x1B, 0x90, 0x28, 0x40, 0x23, 0x41, 0x81, 0x0C, 0x04, 0x12, 0x10, 0x48, 0x40,
+0x23, 0x01, 0x8D, 0x04, 0x06, 0x12, 0xD0, 0x88, 0x40, 0x23, 0x01, 0xC1, 0x00,
+0x36, 0x02, 0xD0, 0x08, 0x44, 0x23, 0x03, 0x81, 0x00, 0x14, 0x02, 0x50, 0x08,
+0x44, 0x23, 0x02, 0xC9, 0x00, 0x44, 0x22, 0x10, 0x0D, 0x60, 0x50, 0xA8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x86, 0x02, 0x13, 0x00, 0x4C, 0x08,
+0xB0, 0x25, 0xC0, 0x87, 0x02, 0x13, 0x02, 0x5C, 0x28, 0x30, 0xA1, 0xC0, 0x83,
+0x42, 0x1F, 0x0A, 0x44, 0x28, 0xD0, 0x21, 0x00, 0x17, 0x00, 0x1F, 0x40, 0x7C,
+0x50, 0xF0, 0x01, 0x40, 0x87, 0x00, 0x17, 0x00, 0x7C, 0x28, 0x30, 0xE1, 0xC1,
+0x87, 0x45, 0x1B, 0x14, 0x0C, 0x08, 0x70, 0x01, 0xC0, 0x75, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x19, 0xA8, 0x2F, 0x12, 0xBF, 0x08, 0xFC, 0x0A, 0x70,
+0x0B, 0xC2, 0x2F, 0x02, 0x9F, 0x0C, 0xFC, 0x22, 0xF0, 0x8B, 0xC0, 0x2F, 0x02,
+0xB3, 0x08, 0x7C, 0x22, 0xF2, 0x4F, 0xC0, 0x2F, 0x22, 0xBF, 0x00, 0x7C, 0x02,
+0xF0, 0x0A, 0xC0, 0x25, 0x03, 0xB6, 0x00, 0xD8, 0x02, 0xF0, 0x0B, 0xC0, 0x3F,
+0x41, 0xB7, 0x00, 0xDC, 0x12, 0xF4, 0x0F, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x05, 0xBF, 0x04, 0xCC, 0x02, 0xF0, 0x0B,
+0xC0, 0x33, 0x02, 0x93, 0x04, 0x7C, 0xD2, 0xB0, 0xC9, 0xC0, 0x2C, 0x00, 0xB3,
+0x00, 0xCC, 0x22, 0x34, 0x09, 0xC0, 0x28, 0x05, 0xBB, 0x00, 0xDC, 0x02, 0xB0,
+0x0B, 0xC0, 0x27, 0x02, 0xB3, 0x20, 0x5C, 0x8A, 0xF2, 0x49, 0xC2, 0x2D, 0x40,
+0xBE, 0x00, 0xCC, 0x02, 0x30, 0x0A, 0xD0, 0x60, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1C, 0x18, 0x15, 0x01, 0x1D, 0x08, 0x45, 0xC8, 0xD0, 0x01, 0x49,
+0x07, 0x02, 0x11, 0x14, 0x30, 0x10, 0x00, 0xC1, 0x42, 0x84, 0x04, 0x01, 0x10,
+0x44, 0x20, 0x11, 0x41, 0x83, 0x05, 0x20, 0x57, 0x40, 0x5C, 0x08, 0x01, 0x01,
+0x40, 0x03, 0x02, 0x11, 0x00, 0x64, 0x14, 0xD0, 0xD1, 0x41, 0x81, 0x44, 0x55,
+0x00, 0x04, 0x01, 0x50, 0x01, 0x40, 0x70, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x20, 0x31, 0x05, 0x8D, 0x00, 0x34, 0xB2, 0xD0, 0x08, 0x40, 0x23,
+0x00, 0x81, 0x2C, 0x34, 0x52, 0x98, 0x48, 0x48, 0x20, 0x03, 0x81, 0xC8, 0x04,
+0x02, 0x10, 0x49, 0x04, 0x20, 0x10, 0x81, 0x00, 0x14, 0x22, 0xD1, 0x08, 0x40,
+0x23, 0x20, 0x81, 0x00, 0x16, 0x12, 0xD0, 0x08, 0x40, 0x21, 0x4B, 0x8D, 0xC0,
+0x45, 0x02, 0x12, 0x09, 0x40, 0x48, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x25, 0x01, 0x9D, 0x03, 0x74, 0x0A, 0xD2, 0x09, 0x40, 0xA3, 0x40,
+0x91, 0x40, 0x74, 0x02, 0x10, 0x08, 0x40, 0x30, 0x00, 0x91, 0x03, 0x04, 0x02,
+0x10, 0x49, 0x50, 0x26, 0x12, 0x95, 0x00, 0x54, 0x03, 0x50, 0xA9, 0x40, 0x27,
+0x00, 0x91, 0x00, 0x64, 0x12, 0xD0, 0x09, 0x40, 0x25, 0x40, 0x95, 0x08, 0x44,
+0x12, 0x50, 0x09, 0x40, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xA8, 0x67, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC4, 0x27, 0x00, 0x93,
+0x60, 0x7C, 0x02, 0xB0, 0x19, 0xD0, 0x24, 0x40, 0x93, 0x02, 0x44, 0x02, 0x30,
+0x08, 0xC2, 0x24, 0x08, 0x93, 0x02, 0x5C, 0x82, 0xF0, 0x19, 0xC8, 0x27, 0x40,
+0x91, 0x18, 0x5C, 0x06, 0xF0, 0x29, 0xC1, 0x25, 0x00, 0x9F, 0x00, 0x44, 0x02,
+0x20, 0x28, 0xC0, 0x14, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80,
+0x65, 0x00, 0x8F, 0x00, 0x4C, 0x4E, 0xF0, 0x09, 0xC1, 0xE7, 0x30, 0x9F, 0x40,
+0x7C, 0x22, 0xF0, 0x49, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7D, 0x02, 0xF0, 0x09,
+0xC0, 0x65, 0x00, 0x9F, 0x19, 0x7C, 0x02, 0xB0, 0x09, 0xC0, 0x27, 0x10, 0x9F,
+0x01, 0x7C, 0x02, 0xF0, 0x09, 0xC8, 0xE7, 0x40, 0x8B, 0x10, 0x7C, 0x82, 0xF0,
+0x09, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x05,
+0x80, 0x1F, 0x06, 0x4E, 0x08, 0xF0, 0x01, 0xC4, 0x04, 0x80, 0x13, 0x00, 0x7E,
+0x80, 0xF0, 0x01, 0xC0, 0x07, 0x06, 0x1F, 0x12, 0x5C, 0x20, 0xF8, 0x21, 0xC0,
+0x07, 0x94, 0x13, 0x02, 0x3C, 0x00, 0xF0, 0x21, 0xC0, 0x07, 0x00, 0x1B, 0x0A,
+0x7C, 0x00, 0xE1, 0x20, 0xC0, 0x80, 0x04, 0x17, 0x20, 0x4C, 0x00, 0x30, 0x81,
+0xC2, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x1C, 0x00,
+0x7D, 0x00, 0xC4, 0x01, 0x70, 0x57, 0x40, 0x15, 0x80, 0x5B, 0x40, 0x64, 0x01,
+0xB2, 0x05, 0xC2, 0x1F, 0x20, 0x7D, 0x11, 0xC4, 0x25, 0x78, 0x05, 0xE0, 0xDB,
+0x00, 0x7B, 0x04, 0xFC, 0x2D, 0x70, 0x37, 0x44, 0x17, 0x20, 0x53, 0x40, 0x58,
+0x01, 0x70, 0x05, 0xD0, 0x1C, 0x00, 0x71, 0x00, 0xC4, 0x05, 0x14, 0x17, 0x40,
+0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD,
+0x20, 0x06, 0x03, 0x50, 0x3C, 0x40, 0x30, 0x00, 0xC1, 0x00, 0x74, 0x03, 0x50,
+0x0C, 0x60, 0xF3, 0x08, 0xDD, 0x02, 0x14, 0x0F, 0xD1, 0x0C, 0x40, 0x13, 0x02,
+0xC1, 0x03, 0x34, 0x0F, 0x41, 0x4C, 0x60, 0x37, 0x80, 0x81, 0x01, 0x34, 0x03,
+0x90, 0x0C, 0x40, 0x32, 0x00, 0xC5, 0x03, 0x44, 0x1F, 0x50, 0x4C, 0x40, 0x50,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, 0x28, 0x00, 0xAD, 0x00,
+0x86, 0x41, 0x58, 0x1E, 0x60, 0x3D, 0x10, 0xE9, 0x40, 0xB4, 0x33, 0x10, 0x4E,
+0x40, 0x39, 0x08, 0xED, 0x00, 0x84, 0x03, 0x50, 0x4E, 0x40, 0x19, 0x08, 0xE9,
+0x00, 0x94, 0x09, 0x50, 0x26, 0x40, 0x3B, 0x03, 0xA1, 0x40, 0xB6, 0x13, 0x50,
+0x8E, 0x40, 0x08, 0x04, 0xC1, 0x02, 0x84, 0x40, 0x50, 0x0E, 0x40, 0x05, 0x20,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x10, 0x68, 0x00, 0xCD, 0x01, 0x85,
+0x07, 0x70, 0x17, 0xC0, 0x78, 0x01, 0xE1, 0x01, 0xB4, 0x07, 0x50, 0x5E, 0x40,
+0x7B, 0x00, 0xED, 0x01, 0x9C, 0x85, 0xD0, 0x1E, 0x60, 0x7B, 0x00, 0xE1, 0x01,
+0xB4, 0x06, 0x70, 0x1E, 0xC0, 0x7B, 0x40, 0xA3, 0x01, 0xBC, 0x1F, 0xF1, 0x5F,
+0xC0, 0x7A, 0x00, 0xE7, 0x01, 0x8D, 0x07, 0x70, 0x1E, 0xC0, 0x44, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x2D, 0x00, 0x9F, 0x00, 0x7C, 0x01,
+0x70, 0x0D, 0xC0, 0xB7, 0x00, 0xDF, 0x00, 0x6C, 0x43, 0xF1, 0x2D, 0xC1, 0x37,
+0x30, 0xDC, 0x00, 0x7C, 0x81, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C,
+0x02, 0x70, 0x0D, 0xC0, 0xB7, 0x04, 0x9B, 0x00, 0x58, 0x83, 0xFA, 0x0D, 0xCC,
+0x06, 0x00, 0xDF, 0x00, 0x7C, 0x00, 0xB0, 0x0D, 0xC0, 0x43, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6F, 0x00, 0xF3, 0x41, 0xCC, 0x13, 0xF0,
+0x1F, 0xC0, 0xFF, 0x04, 0xFB, 0x91, 0xEC, 0x07, 0x80, 0x9F, 0xC1, 0x5C, 0x08,
+0x7B, 0x89, 0xCC, 0x06, 0x30, 0x1F, 0xC1, 0x5F, 0x00, 0xB3, 0x01, 0xF8, 0xA7,
+0xB0, 0x1F, 0xD0, 0x7C, 0x00, 0xFF, 0x21, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7D,
+0x02, 0x77, 0x01, 0xCC, 0x07, 0xB0, 0x1F, 0xC0, 0x03, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x10, 0xAD, 0x40, 0xA1, 0x30, 0x84, 0x03, 0xD0, 0x0E,
+0x45, 0x3F, 0x00, 0xE1, 0x00, 0x84, 0x63, 0x10, 0x0E, 0x48, 0x0C, 0x02, 0x31,
+0x0C, 0xC5, 0x22, 0x10, 0x0E, 0x43, 0x9B, 0x02, 0xA1, 0x02, 0xB4, 0x01, 0x50,
+0xA2, 0x40, 0x38, 0x80, 0xED, 0x10, 0xB4, 0x03, 0x70, 0x4E, 0x50, 0x18, 0x47,
+0xFB, 0x00, 0xC4, 0x08, 0x14, 0x0A, 0x48, 0x57, 0x60, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x08, 0x28, 0x00, 0x61, 0x08, 0x84, 0x63, 0xD0, 0x86, 0x40,
+0x3B, 0x00, 0xE1, 0x00, 0x24, 0x03, 0x14, 0x0C, 0x50, 0x18, 0x44, 0x61, 0x00,
+0xA4, 0x00, 0x14, 0x0E, 0x40, 0x33, 0x44, 0x21, 0x10, 0xB4, 0x03, 0x11, 0x0E,
+0x40, 0x38, 0x00, 0xED, 0x00, 0xB4, 0x43, 0xD0, 0x0E, 0x44, 0x39, 0x80, 0xF5,
+0x00, 0x84, 0x43, 0x90, 0x0E, 0x40, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x20, 0x23, 0x14, 0x01, 0x20, 0x04, 0x0E, 0xD0, 0x18, 0x40, 0xB3,
+0x04, 0xC1, 0x00, 0x04, 0x03, 0x10, 0x2C, 0x41, 0x40, 0x00, 0x01, 0x03, 0x64,
+0x00, 0x11, 0x2C, 0x40, 0xF3, 0x00, 0x01, 0x12, 0x34, 0x03, 0x50, 0x38, 0x40,
+0x30, 0x00, 0xCD, 0x03, 0x76, 0x07, 0x50, 0x0D, 0x40, 0x54, 0x00, 0x49, 0x0C,
+0x05, 0x0E, 0x10, 0x9C, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x28, 0x25, 0x00, 0x93, 0x01, 0x45, 0x0A, 0xF8, 0x09, 0xC0, 0xBF, 0x40,
+0xF3, 0x00, 0xEC, 0x0F, 0x30, 0x2F, 0xC0, 0x64, 0x00, 0x93, 0x12, 0x6C, 0x03,
+0x30, 0x0E, 0xC0, 0x17, 0x10, 0x13, 0x03, 0x7C, 0x83, 0xB0, 0x18, 0xC0, 0x3C,
+0x20, 0x9F, 0x00, 0xF4, 0x07, 0xF0, 0x5F, 0xC0, 0x75, 0x00, 0x97, 0x22, 0x04,
+0x2F, 0xB0, 0xBC, 0xC0, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x00, 0x87, 0x00, 0x0F, 0x80, 0x7E, 0x00, 0xF0, 0x21, 0xC0, 0x37, 0x00, 0xD7,
+0x80, 0x7C, 0x13, 0x70, 0x0D, 0xC0, 0x87, 0x00, 0x97, 0x02, 0x5C, 0x0A, 0xF0,
+0x0D, 0xE0, 0x17, 0x00, 0x9F, 0x20, 0x3C, 0x08, 0xF0, 0xC1, 0xC8, 0x37, 0x00,
+0x9F, 0x04, 0x7C, 0x03, 0xF1, 0x0D, 0xC0, 0xA7, 0x44, 0xDF, 0x02, 0x7C, 0x88,
+0xF2, 0x0D, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08,
+0x2D, 0x00, 0x9F, 0x00, 0xEC, 0x42, 0xE0, 0x03, 0xE0, 0x3F, 0x00, 0xDF, 0x00,
+0xFC, 0x03, 0xF8, 0x0E, 0xD0, 0x2C, 0x02, 0x3F, 0x10, 0xCD, 0x07, 0x34, 0x0F,
+0xC1, 0x3C, 0x04, 0x3F, 0x00, 0xFC, 0x02, 0xB1, 0x8F, 0xC0, 0x3E, 0x00, 0xBF,
+0x00, 0xCC, 0x03, 0x30, 0x0D, 0xC0, 0x74, 0x40, 0xF7, 0x00, 0xFC, 0x17, 0x30,
+0x0F, 0x00, 0x10, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x20, 0xC6,
+0x08, 0x1D, 0x81, 0x44, 0x44, 0xD0, 0x11, 0x41, 0x37, 0x00, 0xDD, 0x00, 0x74,
+0x03, 0xD0, 0x0D, 0x40, 0xC4, 0x08, 0x19, 0x02, 0x4C, 0x0A, 0x10, 0x0D, 0x40,
+0x84, 0x00, 0x97, 0x03, 0x74, 0x06, 0xB8, 0x1D, 0x00, 0x34, 0x00, 0x8D, 0x01,
+0x54, 0x03, 0x10, 0x0D, 0x40, 0x24, 0x42, 0xD3, 0x09, 0x74, 0x05, 0x10, 0x05,
+0x48, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x64, 0x00,
+0x9D, 0x01, 0x64, 0x04, 0xD0, 0x19, 0x40, 0x37, 0x00, 0xDD, 0x00, 0x54, 0x03,
+0xD0, 0x0D, 0x40, 0x34, 0x00, 0xCD, 0x03, 0x44, 0x19, 0x10, 0x0D, 0x50, 0x14,
+0x00, 0x18, 0x01, 0x74, 0x21, 0x10, 0x01, 0x00, 0x36, 0x00, 0x9D, 0x04, 0x44,
+0x03, 0x10, 0x0D, 0x40, 0x84, 0x40, 0xDD, 0x02, 0x74, 0x03, 0x10, 0x0D, 0x40,
+0x04, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x0D,
+0x01, 0x05, 0x00, 0xD1, 0x08, 0x48, 0x33, 0x80, 0xCD, 0x00, 0x34, 0x03, 0xD0,
+0x0C, 0x40, 0x00, 0x00, 0x8D, 0x00, 0x06, 0x00, 0x10, 0x0D, 0x60, 0x10, 0x10,
+0x85, 0x00, 0x34, 0x00, 0x91, 0x01, 0x40, 0x30, 0x00, 0x9D, 0x80, 0x16, 0x03,
+0x10, 0x0C, 0x50, 0x00, 0x00, 0x81, 0x00, 0x74, 0x00, 0x50, 0x18, 0x50, 0x41,
+0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x26, 0x00, 0x1F, 0x00,
+0x6C, 0x02, 0xF1, 0x01, 0x40, 0x3F, 0x00, 0xDF, 0x00, 0xDC, 0x03, 0xD0, 0x0F,
+0xC0, 0x34, 0x00, 0x5D, 0x00, 0x4C, 0x01, 0x30, 0x0D, 0xC0, 0x34, 0x00, 0x1F,
+0x00, 0x7C, 0x01, 0x11, 0x05, 0xC0, 0x3E, 0x00, 0x9F, 0x00, 0x4C, 0x03, 0x30,
+0x0D, 0xC0, 0x04, 0x00, 0xDF, 0x80, 0x7C, 0x00, 0x31, 0x0D, 0xC0, 0x00, 0xC0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x0F, 0x00, 0x3F, 0x00, 0xFE,
+0x02, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x0F, 0x00, 0x3B, 0x00, 0xDC, 0x00, 0xF0, 0x0F, 0xC4, 0x3F, 0x08, 0x37, 0x00,
+0xBC, 0x00, 0xF2, 0x02, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
+0xC0, 0x0F, 0x00, 0xF7, 0x40, 0xFC, 0x00, 0xB0, 0x0F, 0xC0, 0x16, 0x21, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x5F, 0x00, 0x73, 0x01, 0xCC, 0x07,
+0xF0, 0x1F, 0xC0, 0x3C, 0x01, 0xB3, 0x01, 0xAC, 0x05, 0xF0, 0x4F, 0xC0, 0x4D,
+0x08, 0x3F, 0x03, 0x4C, 0x04, 0xF0, 0x0F, 0xC0, 0x4F, 0x40, 0x33, 0x01, 0xFC,
+0x0C, 0x71, 0x90, 0xC0, 0x4C, 0x00, 0xA3, 0x01, 0xED, 0x04, 0xF0, 0x12, 0xC0,
+0x4F, 0x00, 0x3F, 0x02, 0xCE, 0x26, 0x34, 0x03, 0xC0, 0x0F, 0x08, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x53, 0x00, 0x51, 0x01, 0xEC, 0x07, 0xD0,
+0x1F, 0x40, 0x74, 0x00, 0x95, 0x01, 0x51, 0x06, 0xD0, 0x9F, 0x42, 0x44, 0x00,
+0x1D, 0x00, 0x4C, 0x04, 0xD0, 0x3F, 0x40, 0x47, 0x00, 0x11, 0x01, 0x74, 0x00,
+0x10, 0x45, 0x44, 0x45, 0x00, 0x11, 0x41, 0x44, 0x00, 0xD0, 0x11, 0x40, 0x47,
+0x00, 0x97, 0x82, 0x6C, 0x10, 0x10, 0x11, 0x48, 0x0F, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x11, 0xA0, 0x25, 0x00, 0x81, 0x00, 0x04, 0x03, 0x51, 0x0C,
+0x40, 0xB0, 0x00, 0x45, 0x00, 0x04, 0x01, 0x50, 0x0C, 0x40, 0x21, 0x00, 0x05,
+0x04, 0x24, 0x03, 0xD0, 0x2C, 0x40, 0x07, 0x00, 0x01, 0x00, 0x74, 0x10, 0xD0,
+0x09, 0x40, 0x35, 0x00, 0x95, 0x80, 0x14, 0x50, 0xD1, 0x00, 0x40, 0x01, 0x08,
+0x4D, 0x06, 0x44, 0x02, 0x10, 0x08, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x27, 0x00, 0xC1, 0x00, 0x64, 0x03, 0xD0, 0x0D, 0x40,
+0x34, 0x00, 0x55, 0x06, 0x54, 0x02, 0xD0, 0x0D, 0x40, 0x44, 0x00, 0x0D, 0x81,
+0x44, 0x23, 0xD0, 0x0D, 0x40, 0x07, 0x00, 0x11, 0x04, 0x74, 0x46, 0x10, 0x0D,
+0x40, 0x35, 0x40, 0x15, 0x02, 0x50, 0x06, 0xD0, 0x11, 0x60, 0x07, 0x00, 0x95,
+0x08, 0x45, 0x06, 0x10, 0x11, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA8, 0x73, 0x00, 0x93, 0x02, 0x4C, 0x03, 0xF0, 0x0C, 0xD0, 0x34,
+0x80, 0xC7, 0x03, 0x6C, 0x1B, 0xF0, 0x0C, 0xC0, 0x65, 0x01, 0x9F, 0x01, 0x6C,
+0x4E, 0xF0, 0x0D, 0xC0, 0x83, 0x01, 0x13, 0x00, 0x3C, 0x04, 0x70, 0x3D, 0xC0,
+0xF5, 0x08, 0x87, 0x03, 0x54, 0x44, 0xF0, 0x31, 0xC1, 0x07, 0x11, 0x1F, 0x05,
+0x44, 0x06, 0x30, 0x31, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x07, 0x80, 0xFD, 0x40, 0xBF, 0x00, 0xFC, 0x03, 0xF2, 0x0F, 0xC0, 0x3B, 0x20,
+0xFF, 0x00, 0xE8, 0x96, 0xF0, 0x0F, 0xC0, 0x0F, 0x20, 0x3F, 0x00, 0xFC, 0x06,
+0xE0, 0x0D, 0xC4, 0x4E, 0x02, 0x3F, 0x41, 0xF4, 0x02, 0xF0, 0x2F, 0xC0, 0xBF,
+0x00, 0xBB, 0x02, 0xC4, 0x02, 0xD0, 0x03, 0x41, 0x0F, 0x00, 0x1F, 0x01, 0xFC,
+0x00, 0xF0, 0x03, 0xC4, 0x3F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x08, 0xA5, 0x00, 0x93, 0x02, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x6E, 0x0B, 0x30, 0x0D, 0xC0, 0xA4, 0x80, 0x9F, 0x02, 0x7C, 0x02, 0xF0,
+0x8D, 0xC2, 0x07, 0x02, 0x1E, 0x00, 0x7C, 0x18, 0xF0, 0x0D, 0xC0, 0x36, 0x01,
+0x9F, 0x06, 0x6C, 0x08, 0xF2, 0x81, 0xC8, 0x16, 0x44, 0x83, 0x02, 0x4D, 0x8A,
+0x30, 0x29, 0xC4, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x24, 0x00, 0x91, 0x00, 0x74, 0x03, 0x50, 0x0D, 0x40, 0x3F, 0x00, 0xDD, 0x07,
+0x76, 0x1E, 0xF0, 0xAF, 0x40, 0x44, 0x00, 0x9F, 0x80, 0x74, 0x4F, 0xD0, 0x1F,
+0xC0, 0xC4, 0x00, 0x1F, 0x0C, 0x70, 0x02, 0xF0, 0x0C, 0x40, 0xF0, 0x08, 0x9D,
+0x02, 0x50, 0x02, 0xD2, 0x11, 0x50, 0x54, 0x04, 0x91, 0x09, 0x64, 0x02, 0x34,
+0x39, 0xC0, 0x6C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x22,
+0x00, 0xC1, 0x40, 0x24, 0x03, 0x10, 0x4C, 0x60, 0x33, 0x00, 0x4D, 0x04, 0x34,
+0x1E, 0x10, 0x1C, 0x40, 0x40, 0x00, 0x89, 0x00, 0x36, 0x11, 0xD0, 0x4C, 0x60,
+0x02, 0x04, 0x09, 0x00, 0x34, 0x0C, 0xDA, 0x00, 0x00, 0x82, 0x02, 0x08, 0x00,
+0x14, 0x00, 0xD0, 0x20, 0x40, 0x40, 0x00, 0x09, 0x83, 0x64, 0x32, 0x90, 0xC8,
+0x40, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x7A, 0x40,
+0xE1, 0x01, 0x34, 0x07, 0x50, 0x1E, 0x40, 0x7B, 0x00, 0x6D, 0x81, 0xF6, 0x26,
+0xD0, 0x1C, 0x40, 0x48, 0x00, 0x25, 0x49, 0xB6, 0x25, 0xD0, 0x9E, 0x40, 0x48,
+0x00, 0x2D, 0x01, 0xB4, 0x05, 0xD1, 0x53, 0x40, 0x4A, 0x01, 0x7D, 0x81, 0x94,
+0x24, 0xD8, 0x12, 0x60, 0x4C, 0x80, 0x69, 0x21, 0xA4, 0x24, 0x10, 0x13, 0x40,
+0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0xA2, 0x00, 0x81,
+0x00, 0x2C, 0x23, 0x10, 0x0C, 0xC0, 0x33, 0x00, 0x4F, 0x00, 0x34, 0x22, 0x10,
+0x0C, 0xC1, 0x60, 0x05, 0x89, 0x07, 0x3C, 0x15, 0xF0, 0x8C, 0xC0, 0x03, 0x02,
+0x0F, 0x01, 0x38, 0x46, 0xF0, 0x50, 0xE8, 0x42, 0x10, 0xCD, 0x14, 0x14, 0x23,
+0xF0, 0x80, 0xC0, 0x00, 0x00, 0xCB, 0x10, 0x4C, 0x23, 0xB2, 0x2D, 0xE0, 0x4A,
+0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x2D, 0x00, 0xFF, 0x80,
+0xFC, 0x07, 0x70, 0x1F, 0xC0, 0x3F, 0x00, 0x7F, 0x08, 0xFC, 0x22, 0x70, 0x0D,
+0xD0, 0x27, 0x02, 0xBE, 0x00, 0xFC, 0x23, 0xF0, 0x8F, 0xC0, 0x0F, 0x02, 0x35,
+0x40, 0xFC, 0x03, 0x70, 0x0F, 0xE8, 0x3D, 0x00, 0x7F, 0x00, 0xDC, 0x23, 0xF0,
+0x03, 0xC8, 0x09, 0x02, 0xF7, 0x00, 0xDC, 0x23, 0xD0, 0x83, 0xD0, 0x0B, 0x60,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x67, 0x00, 0x93, 0x00, 0x7C,
+0x23, 0xF0, 0x1D, 0xD0, 0x34, 0x00, 0x57, 0x00, 0x7C, 0x03, 0x30, 0xDC, 0xC0,
+0x65, 0x20, 0x9B, 0x20, 0x6C, 0x04, 0xB0, 0x9D, 0xC0, 0x04, 0x00, 0x1F, 0x80,
+0x7C, 0x07, 0xBC, 0x01, 0xC0, 0x07, 0x00, 0x5F, 0x01, 0x6E, 0x07, 0x39, 0x01,
+0xC0, 0x07, 0x80, 0x5F, 0x00, 0x4C, 0x01, 0x33, 0x09, 0xC0, 0x40, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xAB, 0x00, 0xB4, 0x13,
+0xD0, 0x2C, 0x40, 0x38, 0x11, 0x61, 0x00, 0x8C, 0x02, 0x18, 0x4E, 0x41, 0x28,
+0x30, 0x31, 0x00, 0x84, 0x03, 0x11, 0xCC, 0x40, 0x08, 0x88, 0x2D, 0x00, 0xB4,
+0x03, 0x10, 0x0A, 0x42, 0x3B, 0x80, 0x6D, 0x00, 0x94, 0x03, 0x14, 0x02, 0x40,
+0x0B, 0x00, 0x7D, 0xC0, 0xC4, 0x01, 0xB0, 0x0A, 0x40, 0x4D, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x69, 0x00, 0xA1, 0x03, 0x94, 0x07, 0x52,
+0x5E, 0x60, 0x70, 0x03, 0x65, 0x43, 0xB4, 0x07, 0x90, 0x1E, 0x40, 0x6D, 0x00,
+0xA5, 0x01, 0x84, 0x04, 0x10, 0x1E, 0x40, 0xC9, 0x00, 0x25, 0x01, 0xB4, 0x07,
+0x10, 0x16, 0x44, 0x4B, 0x10, 0xFD, 0x01, 0x94, 0x87, 0x10, 0x16, 0x44, 0x5B,
+0x20, 0xED, 0x01, 0xA4, 0x05, 0x10, 0x1C, 0x64, 0x10, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x16, 0x28, 0x23, 0x04, 0x89, 0x00, 0x34, 0x03, 0xD0, 0x0C,
+0x40, 0x30, 0x00, 0x41, 0x45, 0x30, 0x2E, 0x10, 0x0C, 0x40, 0x30, 0x00, 0xC5,
+0x20, 0x04, 0x1F, 0x10, 0x0C, 0x50, 0xF1, 0x01, 0xCD, 0x48, 0x34, 0x0F, 0x12,
+0x3C, 0x41, 0xF3, 0x00, 0xCD, 0x22, 0x14, 0x13, 0x10, 0x1C, 0x40, 0xF3, 0x0C,
+0xCD, 0x07, 0x24, 0x4F, 0x10, 0x4C, 0x48, 0x59, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x17, 0xA0, 0x9F, 0x00, 0x73, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0,
+0x14, 0x00, 0x77, 0x00, 0xB4, 0x01, 0xB5, 0x05, 0xC0, 0xDD, 0x01, 0x77, 0x08,
+0xEC, 0x0D, 0xB0, 0x05, 0xE0, 0xDD, 0x00, 0x7F, 0x0B, 0xFC, 0x15, 0xB1, 0x37,
+0xC1, 0xDB, 0x16, 0x7F, 0x02, 0xDD, 0x09, 0x30, 0x27, 0xC1, 0x5F, 0x14, 0x7F,
+0x04, 0xE4, 0x1D, 0x10, 0x17, 0x45, 0x5C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x80, 0x05, 0x00, 0x1F, 0x24, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x80, 0x4C, 0x10, 0xF0, 0x21, 0xC0, 0x07, 0x04, 0x12, 0x00, 0x7D,
+0x20, 0xF0, 0x01, 0x00, 0x86, 0x00, 0x1F, 0x00, 0x7C, 0x48, 0xF2, 0x01, 0xC0,
+0x87, 0x00, 0x1F, 0x0A, 0x64, 0x20, 0xF0, 0x01, 0xC1, 0x87, 0x00, 0x1F, 0x40,
+0x5D, 0x00, 0xF4, 0x01, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x00, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0xF0, 0x89, 0xC0, 0x27, 0x00,
+0x93, 0x80, 0x7C, 0x0A, 0x30, 0x19, 0x40, 0x27, 0x00, 0x9F, 0x00, 0x6C, 0x02,
+0xF0, 0x19, 0xC8, 0x26, 0x00, 0x93, 0x01, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x93, 0x10, 0x5C, 0x02, 0xF0, 0x19, 0xC0, 0x24, 0x00, 0x9F, 0x02, 0x6C,
+0x0A, 0x30, 0x58, 0xC4, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x26, 0x00, 0x8D, 0x00, 0xC4, 0x02, 0xD8, 0x1B, 0x40, 0x27, 0x00, 0x95,
+0x01, 0x74, 0x02, 0x50, 0x09, 0x44, 0x27, 0x00, 0x87, 0x00, 0x44, 0x06, 0xD0,
+0x29, 0x44, 0xE3, 0x1C, 0x91, 0x01, 0x74, 0x12, 0xD0, 0x09, 0x4A, 0x67, 0x00,
+0x95, 0x22, 0x74, 0x82, 0xD0, 0x18, 0x40, 0x24, 0x08, 0x9C, 0x03, 0x04, 0x42,
+0x14, 0x19, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0,
+0x24, 0x00, 0xDD, 0x00, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x23, 0x00, 0x91, 0x04,
+0x54, 0x02, 0x10, 0x69, 0x44, 0x27, 0x80, 0x9D, 0x00, 0x44, 0x06, 0xD0, 0x89,
+0x41, 0x27, 0x41, 0xD1, 0x0A, 0x74, 0x02, 0xD2, 0x0D, 0x48, 0x37, 0x02, 0x91,
+0x82, 0x74, 0x02, 0x52, 0x89, 0x00, 0x24, 0x00, 0x8D, 0x00, 0x42, 0x03, 0x10,
+0x09, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x28, 0xA0,
+0x00, 0x9D, 0x02, 0x04, 0x0A, 0xD0, 0x08, 0x40, 0xA3, 0x00, 0x85, 0x20, 0x74,
+0x03, 0x50, 0x08, 0x48, 0x23, 0x00, 0x95, 0x08, 0x04, 0x83, 0xD2, 0x08, 0x40,
+0x23, 0x00, 0x81, 0x00, 0x34, 0x22, 0xD0, 0x88, 0x40, 0x23, 0x00, 0x85, 0x80,
+0x34, 0x22, 0xD0, 0x09, 0x50, 0x30, 0x90, 0xCD, 0x68, 0x45, 0xA2, 0x10, 0x48,
+0x50, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x02, 0x00,
+0x1F, 0x00, 0x4D, 0x04, 0xD0, 0x11, 0xC0, 0x07, 0x05, 0x13, 0x80, 0x5C, 0x80,
+0x30, 0x41, 0xC1, 0x07, 0x20, 0x1F, 0x02, 0x4D, 0x00, 0xF0, 0x41, 0xC1, 0x07,
+0x00, 0x13, 0x80, 0x38, 0x08, 0xF0, 0x21, 0xC0, 0x17, 0x20, 0x13, 0x00, 0x3E,
+0x08, 0x70, 0x01, 0xC0, 0x04, 0x08, 0x1F, 0x16, 0x4C, 0x08, 0x30, 0x05, 0xC0,
+0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA8, 0x7F, 0x00, 0xBF,
+0x01, 0x7C, 0x0E, 0xD0, 0x29, 0xC0, 0x67, 0x10, 0xBF, 0x00, 0xBC, 0x02, 0xF0,
+0x09, 0xC0, 0x2B, 0x00, 0xB7, 0x04, 0x9C, 0x02, 0xF2, 0x09, 0xC0, 0x3F, 0x20,
+0xFF, 0x40, 0xFC, 0x12, 0xD0, 0x4B, 0xC0, 0x2F, 0x10, 0xAF, 0x80, 0xFE, 0x12,
+0xF0, 0x0B, 0xC8, 0x2F, 0x00, 0xBE, 0x44, 0xDC, 0x13, 0xF0, 0x8B, 0xC0, 0x77,
+0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x27, 0x00, 0x9F, 0x42,
+0x7C, 0x36, 0xF0, 0x1B, 0xC1, 0x27, 0x02, 0xBF, 0x00, 0xDC, 0x02, 0xF2, 0x4B,
+0xC1, 0x2F, 0x00, 0xDB, 0x80, 0xCC, 0x02, 0xF0, 0x0B, 0xC8, 0x2F, 0x00, 0xBF,
+0x00, 0xC4, 0x22, 0xF0, 0x09, 0x40, 0x28, 0x00, 0xBE, 0x00, 0x4C, 0x82, 0x30,
+0x0B, 0xC0, 0x2B, 0x08, 0xBF, 0x00, 0xCC, 0x02, 0x30, 0x0B, 0xC0, 0x74, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x47, 0x05, 0x1D, 0xC1, 0x34,
+0x0C, 0xD0, 0x21, 0x40, 0x43, 0x20, 0x1D, 0x00, 0x44, 0x00, 0xD0, 0x01, 0x40,
+0x07, 0x00, 0x1D, 0x70, 0x44, 0x00, 0xD0, 0x81, 0x40, 0x07, 0x00, 0x1D, 0x00,
+0x44, 0x11, 0x72, 0x01, 0x41, 0x04, 0x30, 0x1D, 0x20, 0x54, 0x50, 0x10, 0x01,
+0x40, 0x17, 0x00, 0x1D, 0x00, 0x0C, 0x00, 0x10, 0x01, 0x44, 0x61, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x21, 0x00, 0x8D, 0x00, 0x34, 0x32,
+0xD0, 0x08, 0x40, 0x23, 0x03, 0x8D, 0x00, 0x05, 0x02, 0xD0, 0x08, 0x40, 0x23,
+0x00, 0x89, 0x04, 0x05, 0x02, 0xD0, 0x08, 0x08, 0x33, 0x00, 0x9D, 0x00, 0x05,
+0x12, 0xD8, 0x48, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x14, 0x92, 0x10, 0x08, 0x60,
+0x23, 0x00, 0x8D, 0x00, 0x04, 0x82, 0x10, 0x09, 0x40, 0x4A, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x25, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x27, 0x08, 0xDD, 0x00, 0x44, 0x02, 0xD0, 0x0D, 0x40, 0x67, 0x20,
+0x8D, 0x18, 0x44, 0x02, 0xD0, 0x09, 0x44, 0x66, 0x10, 0x9D, 0x00, 0x44, 0x02,
+0x50, 0x28, 0x54, 0xB4, 0x02, 0x9D, 0x10, 0x55, 0x02, 0x10, 0x09, 0x41, 0x27,
+0x00, 0xDD, 0x00, 0x04, 0x02, 0x90, 0x19, 0x60, 0x63, 0x28, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0xA8, 0xEF, 0x00, 0xBF, 0x0D, 0xFC, 0x82, 0xF2, 0x09,
+0xC0, 0x2F, 0x00, 0x9F, 0x13, 0x4C, 0x02, 0xF0, 0x09, 0xC4, 0xE7, 0x24, 0x9B,
+0x81, 0x44, 0x46, 0xF2, 0x09, 0xC8, 0x67, 0x20, 0x9F, 0x00, 0x4C, 0x02, 0xF0,
+0x09, 0xC0, 0xE4, 0x00, 0x9F, 0x20, 0x54, 0x1A, 0x30, 0x29, 0xC0, 0x27, 0x00,
+0x9F, 0x12, 0x4C, 0x0E, 0x34, 0x59, 0xC0, 0x16, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x80, 0xE5, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x05, 0x6C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x01,
+0x7C, 0x62, 0xE0, 0x09, 0x00, 0x27, 0x00, 0x9F, 0x02, 0x7C, 0x02, 0x72, 0x49,
+0xC0, 0x27, 0x00, 0x9F, 0x03, 0x7C, 0x22, 0xD4, 0x99, 0xC0, 0x27, 0x01, 0x9D,
+0x13, 0x7F, 0xD2, 0x70, 0x09, 0xC1, 0x59, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x85, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xB0, 0x01, 0xD0, 0x06,
+0x00, 0x13, 0x02, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x87, 0x80, 0x1F, 0x02, 0x5C,
+0x88, 0x30, 0x01, 0xC5, 0x85, 0x40, 0x13, 0x30, 0x4C, 0x00, 0xF0, 0x21, 0xC0,
+0x07, 0x01, 0x13, 0x23, 0x5C, 0x08, 0xF0, 0x01, 0xC1, 0x05, 0x14, 0x03, 0x00,
+0x4C, 0x00, 0x21, 0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0xA0, 0x14, 0x00, 0x5D, 0x00, 0x74, 0x01, 0x58, 0x77, 0x40, 0x14, 0x00,
+0x65, 0x02, 0xD8, 0x01, 0xD0, 0x17, 0x40, 0x17, 0x80, 0x5C, 0x00, 0xD4, 0x01,
+0x11, 0x07, 0x01, 0x9D, 0x00, 0x61, 0x02, 0xC4, 0x85, 0x32, 0x05, 0xC0, 0x9D,
+0x40, 0x61, 0x10, 0x48, 0x01, 0xD1, 0x07, 0x40, 0x5F, 0x04, 0x71, 0x00, 0xD4,
+0x81, 0x50, 0x07, 0x48, 0x43, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x10, 0x78, 0x40, 0x30, 0x00, 0x41,
+0x04, 0x24, 0x02, 0xD0, 0xDC, 0x40, 0x33, 0x20, 0xCD, 0x40, 0x14, 0x03, 0x10,
+0x0C, 0x0A, 0xB0, 0x0C, 0xC1, 0x08, 0x05, 0x07, 0xD0, 0x0C, 0x40, 0x71, 0x00,
+0xC1, 0x80, 0x50, 0x83, 0xD0, 0x0C, 0x40, 0x31, 0x00, 0xC1, 0x03, 0x04, 0x2B,
+0x1C, 0x2D, 0x40, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80,
+0x38, 0x01, 0xED, 0x04, 0xB4, 0x27, 0x58, 0x1A, 0x40, 0x78, 0x01, 0xF5, 0x00,
+0x94, 0x02, 0xD8, 0x0A, 0x40, 0x3B, 0x00, 0xED, 0x0C, 0x94, 0x0C, 0x10, 0x1A,
+0x4A, 0x7D, 0x00, 0xE1, 0x20, 0x84, 0x43, 0x00, 0x4E, 0x40, 0x4D, 0x24, 0xF1,
+0x40, 0xA4, 0x03, 0xD0, 0x0E, 0x40, 0x7F, 0x08, 0xE1, 0x82, 0x84, 0x01, 0x10,
+0x06, 0x44, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0xF8,
+0x00, 0xEF, 0x03, 0xBC, 0x07, 0x30, 0x1A, 0xC2, 0x78, 0x01, 0x63, 0x01, 0xAC,
+0x06, 0xF0, 0x1E, 0xC0, 0x7B, 0x00, 0xFD, 0x31, 0x96, 0x04, 0x30, 0x1A, 0x40,
+0x79, 0x00, 0x63, 0x01, 0x8C, 0x07, 0xF0, 0x1E, 0xC1, 0x49, 0x20, 0xE3, 0x01,
+0x9E, 0x17, 0xF2, 0x1E, 0xC8, 0x79, 0x40, 0xF3, 0x01, 0x8D, 0x06, 0x30, 0x1E,
+0xC0, 0x53, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x35, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x08, 0xC0, 0x37, 0x10, 0xCF, 0x00, 0x7C, 0x02,
+0xF1, 0x01, 0xC0, 0x37, 0x00, 0xDD, 0x02, 0x2C, 0x00, 0xF0, 0x08, 0xE0, 0x33,
+0x00, 0x4F, 0x00, 0x7C, 0x01, 0xA2, 0x4D, 0xC0, 0x05, 0x20, 0xCF, 0x20, 0x5C,
+0x1B, 0xF2, 0x09, 0xE0, 0x37, 0x00, 0xDD, 0x00, 0x7C, 0x00, 0xF0, 0x09, 0xC0,
+0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x79, 0x00, 0xE3,
+0x01, 0xCC, 0x13, 0xF8, 0x8F, 0xC0, 0x7D, 0x04, 0x7F, 0x09, 0xCC, 0x06, 0xF0,
+0x9F, 0xC0, 0x7F, 0x02, 0xF7, 0x01, 0x3C, 0x24, 0x70, 0x9B, 0xC0, 0x47, 0x22,
+0xBF, 0x0D, 0xCC, 0x06, 0xB0, 0x9D, 0x41, 0x4F, 0x02, 0xBF, 0x01, 0xCD, 0x4F,
+0x30, 0x9E, 0xC8, 0x7C, 0x12, 0x3B, 0x09, 0xCC, 0x07, 0x34, 0x97, 0xD8, 0x18,
+0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x38, 0x00, 0xE1, 0x18,
+0x84, 0x03, 0xD8, 0x0E, 0x40, 0x38, 0x20, 0xED, 0x0C, 0xAC, 0x02, 0xD0, 0x0A,
+0x44, 0x33, 0x00, 0xCD, 0x08, 0xB4, 0x24, 0x10, 0xCA, 0x08, 0x7B, 0x01, 0x4D,
+0x98, 0x44, 0x43, 0x10, 0x5E, 0x40, 0x03, 0x03, 0xAD, 0x04, 0x94, 0x23, 0x10,
+0x0E, 0x42, 0x29, 0x03, 0x2D, 0x0C, 0xFC, 0x11, 0x10, 0x86, 0x40, 0x54, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7D, 0x00, 0xF1, 0x01, 0x84,
+0x27, 0xD0, 0xC8, 0x40, 0x79, 0x02, 0x7D, 0x00, 0xA6, 0x02, 0x50, 0x0A, 0x48,
+0x3B, 0x80, 0xED, 0x00, 0xF4, 0x00, 0xD0, 0x02, 0x0A, 0x09, 0x08, 0x3D, 0x06,
+0xA6, 0x22, 0x10, 0x0E, 0x44, 0x0B, 0x14, 0xBD, 0x00, 0xC6, 0x03, 0x10, 0x0E,
+0x40, 0x19, 0x10, 0x2D, 0x40, 0xC4, 0x02, 0x12, 0x06, 0x42, 0x60, 0x02, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x31, 0x00, 0xC1, 0x00, 0x04, 0x03,
+0xD8, 0x08, 0x40, 0x30, 0x00, 0xCD, 0x00, 0x24, 0x22, 0xD0, 0x00, 0x40, 0x33,
+0x00, 0xCD, 0x20, 0x34, 0x4C, 0x90, 0x00, 0x40, 0xB2, 0x01, 0x4D, 0x01, 0x24,
+0x85, 0x9A, 0x2D, 0x48, 0xC3, 0x00, 0x8D, 0x10, 0x14, 0x9B, 0x10, 0x28, 0x41,
+0x81, 0x00, 0x8D, 0x08, 0x05, 0x08, 0x10, 0xB8, 0x40, 0x08, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x35, 0x41, 0xD3, 0x01, 0x4D, 0x03, 0xD0,
+0x09, 0xC0, 0x35, 0x00, 0x5F, 0x00, 0x2C, 0x03, 0x70, 0x05, 0xC0, 0x77, 0x04,
+0xFF, 0x11, 0x7C, 0x1C, 0xF0, 0x01, 0xC0, 0x35, 0x08, 0xDF, 0x02, 0x6D, 0x09,
+0x34, 0x0F, 0xC0, 0xC7, 0x20, 0xCD, 0x81, 0xC4, 0x03, 0x30, 0x2D, 0xC0, 0x21,
+0x00, 0xDB, 0x2B, 0x44, 0x0B, 0x30, 0xB9, 0xC0, 0x74, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xDF, 0x00, 0x3C, 0x03, 0xF0, 0x29,
+0xC0, 0x37, 0x00, 0x5F, 0x42, 0x7C, 0x4A, 0xF0, 0x05, 0xC0, 0x27, 0x91, 0xDF,
+0x24, 0x7C, 0x00, 0x70, 0x09, 0xC0, 0x37, 0x0A, 0xDF, 0x02, 0x5C, 0x42, 0x70,
+0xCD, 0xC0, 0x07, 0x04, 0x9F, 0x01, 0x6C, 0x03, 0xF0, 0x25, 0x40, 0x07, 0x01,
+0xDF, 0x02, 0x7C, 0x09, 0xF0, 0x29, 0xC8, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x08, 0x3F, 0x00, 0xFF, 0x00, 0xC8, 0x03, 0x30, 0x1B, 0xC0,
+0x3F, 0x20, 0x7F, 0x41, 0xFC, 0x27, 0x30, 0x46, 0xC0, 0x7E, 0x01, 0xFF, 0x20,
+0xCC, 0x0C, 0x70, 0x03, 0xC0, 0x0F, 0x00, 0xBF, 0x08, 0xF8, 0x05, 0xB4, 0x0F,
+0xC0, 0x0D, 0x08, 0xFF, 0x00, 0xDC, 0x03, 0xF0, 0x0F, 0xC0, 0x2F, 0x10, 0xE7,
+0x01, 0xCC, 0x46, 0xF0, 0x09, 0xC0, 0x07, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x85, 0x20, 0x36, 0x00, 0xDD, 0x00, 0x54, 0x03, 0x50, 0x19, 0x40, 0x37,
+0x00, 0x1D, 0x02, 0x74, 0x0D, 0x10, 0x15, 0x40, 0x24, 0x00, 0xDD, 0x00, 0x44,
+0x0C, 0xD1, 0x19, 0xC0, 0x07, 0x01, 0x9D, 0x02, 0x74, 0x08, 0x90, 0x0D, 0x40,
+0xC4, 0x00, 0x9D, 0x03, 0x6C, 0x03, 0xD2, 0xF5, 0x40, 0x47, 0x00, 0x11, 0x01,
+0x44, 0x02, 0xD0, 0x39, 0x48, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0xA0, 0x34, 0x00, 0xCD, 0x00, 0x54, 0x03, 0x90, 0x8D, 0x41, 0x37, 0x00,
+0x5D, 0x08, 0x74, 0x43, 0x50, 0x0D, 0x40, 0x36, 0x00, 0xC9, 0x00, 0x44, 0xC0,
+0xD8, 0x11, 0x00, 0x07, 0x02, 0x9D, 0x02, 0x36, 0x18, 0x12, 0x0D, 0x40, 0x46,
+0x00, 0x9D, 0x03, 0x60, 0x03, 0xD0, 0x0D, 0x40, 0xE7, 0x00, 0x11, 0x04, 0x44,
+0x9B, 0xD0, 0x11, 0x4D, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x28, 0x30, 0x00, 0xCD, 0x00, 0x14, 0x03, 0x50, 0x04, 0x40, 0x32, 0x00, 0xCD,
+0x00, 0x34, 0x02, 0x56, 0x0C, 0x42, 0x20, 0x80, 0xCD, 0x00, 0x05, 0x10, 0xD0,
+0x18, 0x40, 0x31, 0x09, 0x4D, 0x20, 0x34, 0x22, 0x11, 0x6C, 0x50, 0x02, 0x02,
+0x8D, 0x00, 0x24, 0x03, 0xD2, 0x0C, 0x42, 0x03, 0x80, 0x01, 0x00, 0x04, 0x00,
+0xD0, 0x08, 0x4A, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB0,
+0x3E, 0x08, 0xFF, 0x00, 0xDC, 0x03, 0x30, 0x0D, 0xC0, 0x3F, 0x00, 0x5F, 0x00,
+0x74, 0x03, 0x70, 0x09, 0xC0, 0x36, 0x10, 0xFB, 0x00, 0x4C, 0x50, 0x71, 0x01,
+0x64, 0x07, 0x00, 0x9F, 0x08, 0x7C, 0x00, 0xB0, 0x6F, 0xC0, 0x07, 0xA0, 0x9F,
+0x80, 0xDC, 0x03, 0xF0, 0x0D, 0xC0, 0x07, 0x40, 0x47, 0x80, 0x4E, 0x01, 0xF2,
+0x01, 0xC0, 0x07, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA0, 0x3F,
+0x00, 0xFF, 0x00, 0xFC, 0x03, 0x70, 0x07, 0xC0, 0x3F, 0x00, 0xAF, 0x00, 0xFC,
+0x01, 0xB0, 0x03, 0xC0, 0x2F, 0x04, 0xFC, 0x10, 0xFC, 0x40, 0xF0, 0x03, 0xC0,
+0x8F, 0x08, 0x2F, 0x00, 0xFC, 0x10, 0xD2, 0x8F, 0xC0, 0x0D, 0x01, 0x2E, 0x00,
+0xBC, 0x03, 0xE0, 0x0F, 0xC2, 0x0F, 0x00, 0x3F, 0x00, 0xFD, 0x00, 0xF0, 0x0B,
+0xC2, 0x17, 0x64, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x3F, 0x00,
+0xA3, 0x40, 0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x3F, 0x11, 0xB3, 0x20, 0xFC, 0x26,
+0xB0, 0x9F, 0xD2, 0x2C, 0x00, 0xFF, 0x21, 0xEC, 0x10, 0xB2, 0x8F, 0xC8, 0x3C,
+0x12, 0xFF, 0x04, 0xEC, 0x20, 0x72, 0x0F, 0xC0, 0x7F, 0x02, 0xF3, 0x03, 0xED,
+0x1B, 0xB0, 0x9B, 0xC0, 0x7C, 0x0A, 0xDF, 0x01, 0xFC, 0x1A, 0x34, 0x49, 0xC0,
+0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3F, 0x00, 0xB1,
+0x01, 0x44, 0x82, 0x70, 0x01, 0x02, 0x3F, 0x22, 0x91, 0x00, 0x34, 0x13, 0x10,
+0x4C, 0x48, 0xB4, 0x01, 0xD1, 0x01, 0x54, 0x24, 0xD0, 0x6F, 0x60, 0xBC, 0x01,
+0xFD, 0x09, 0x44, 0x18, 0x10, 0x9F, 0x40, 0x33, 0x01, 0xD1, 0x00, 0x84, 0x1B,
+0x14, 0x48, 0x50, 0x34, 0x21, 0xDD, 0x04, 0x74, 0x12, 0x11, 0x19, 0x40, 0x0D,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x31, 0x00, 0x81, 0x00,
+0x04, 0x02, 0xD0, 0x08, 0x40, 0x33, 0x20, 0xC5, 0x20, 0x14, 0x07, 0x50, 0x0C,
+0x40, 0x81, 0x04, 0xC5, 0x00, 0x04, 0x00, 0xD0, 0x6C, 0x48, 0xB0, 0x01, 0xCD,
+0x00, 0x24, 0x1C, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xC1, 0x04, 0x04, 0x0B, 0x50,
+0x0D, 0x40, 0x30, 0x01, 0xCD, 0x14, 0x34, 0x18, 0x10, 0x81, 0x40, 0x5C, 0x80,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x37, 0x00, 0x91, 0x41, 0x44,
+0x0E, 0x52, 0x11, 0x45, 0x37, 0x10, 0xD5, 0x43, 0x74, 0x07, 0x50, 0x0D, 0x44,
+0x55, 0x00, 0xD5, 0x04, 0x56, 0x88, 0xD0, 0x0C, 0x40, 0x34, 0x00, 0xDD, 0x00,
+0x24, 0x02, 0x13, 0x0D, 0x40, 0x37, 0x80, 0xC1, 0x01, 0x44, 0x03, 0x50, 0x0D,
+0x40, 0x34, 0x00, 0xDD, 0x80, 0x74, 0x06, 0x10, 0x11, 0x40, 0x1D, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x37, 0x00, 0x93, 0x01, 0x4D, 0x04,
+0xF0, 0x11, 0xC4, 0x37, 0xC0, 0xD7, 0x03, 0x7C, 0x07, 0xF0, 0x8D, 0xC0, 0xC5,
+0x00, 0xDF, 0x01, 0x4C, 0x0C, 0xB2, 0x0D, 0x40, 0x34, 0x00, 0xDF, 0x00, 0x6C,
+0x01, 0x70, 0x0D, 0xC0, 0x77, 0x0A, 0xD3, 0x80, 0x6C, 0x03, 0xF0, 0x08, 0xC4,
+0x34, 0x00, 0xDF, 0x00, 0x7C, 0x0E, 0x30, 0x39, 0xC0, 0x82, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x3D, 0x10, 0xEF, 0x00, 0xFC, 0x80, 0x70,
+0x03, 0xC0, 0x3F, 0x00, 0xFB, 0x80, 0xF8, 0x03, 0xB4, 0x0F, 0xC0, 0x1A, 0x00,
+0xFB, 0x00, 0x5C, 0x22, 0xF0, 0x0F, 0xC2, 0x37, 0x30, 0xEF, 0x00, 0x5C, 0x0D,
+0xF3, 0x0F, 0xC0, 0x7F, 0x40, 0xFF, 0x80, 0xDC, 0x03, 0xB0, 0x0B, 0xC0, 0x3F,
+0x20, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x0F, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x0A, 0x93, 0x00, 0x4C, 0x0A, 0xF2, 0x69,
+0xC0, 0x33, 0x20, 0xDF, 0x02, 0x5D, 0x83, 0xF0, 0xCD, 0xC0, 0x84, 0x00, 0xD3,
+0x01, 0x7C, 0x09, 0x70, 0x0D, 0xC0, 0x34, 0x40, 0xD3, 0x84, 0x7C, 0x81, 0x30,
+0x8D, 0xC0, 0x35, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0x70, 0x09, 0xC0, 0x34, 0x00,
+0xDB, 0x00, 0x7C, 0x08, 0xF0, 0x09, 0xC0, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0xA0, 0xF8, 0x02, 0x51, 0x20, 0x44, 0x02, 0xD0, 0x09, 0x45,
+0x3F, 0x00, 0xDD, 0x01, 0x7C, 0x83, 0x10, 0x3D, 0x40, 0x14, 0x08, 0xC0, 0x20,
+0x74, 0x03, 0x12, 0xBF, 0x40, 0xFC, 0x02, 0xF1, 0x00, 0x74, 0x83, 0x10, 0x1F,
+0x40, 0x34, 0x00, 0xD1, 0x00, 0xF4, 0x03, 0x10, 0x09, 0x40, 0x34, 0x80, 0xD1,
+0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x20, 0x30, 0x00, 0x81, 0x12, 0x04, 0x4C, 0xD9, 0x38, 0x40, 0x33,
+0x00, 0xCD, 0x09, 0x54, 0x03, 0x10, 0x2D, 0x40, 0x20, 0x08, 0xC1, 0x00, 0x34,
+0x07, 0x11, 0xAC, 0x48, 0xB1, 0x00, 0xC1, 0x01, 0x34, 0x82, 0x10, 0x1C, 0x41,
+0x36, 0x00, 0xC9, 0x20, 0x74, 0x03, 0x50, 0x08, 0x40, 0x30, 0x00, 0xC1, 0x00,
+0x74, 0x00, 0xD0, 0x01, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x00, 0x70, 0x00, 0xA1, 0x89, 0x84, 0x07, 0xD8, 0x1E, 0x40, 0x7B, 0x02,
+0xFD, 0x09, 0xB4, 0x07, 0x12, 0x1E, 0x40, 0x68, 0x00, 0xE1, 0x81, 0xB4, 0x07,
+0x10, 0x1E, 0x40, 0x79, 0x05, 0xE1, 0x11, 0xB4, 0x27, 0x10, 0x1C, 0x40, 0xFA,
+0x00, 0xE9, 0x81, 0xB4, 0x07, 0x10, 0x1A, 0x40, 0x78, 0x00, 0xE8, 0x0B, 0xB4,
+0x84, 0xD0, 0x1A, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x18, 0x30, 0x00, 0x83, 0x20, 0x0C, 0x41, 0xF0, 0x8C, 0xC4, 0x33, 0x20, 0x4F,
+0x00, 0x1D, 0x23, 0x70, 0x8C, 0xC0, 0x84, 0x40, 0xC3, 0x00, 0x3C, 0x43, 0x74,
+0x0D, 0xC0, 0x31, 0x00, 0xC3, 0x00, 0x3C, 0x00, 0x30, 0x0C, 0xD0, 0x33, 0x00,
+0xCA, 0x08, 0x3C, 0x03, 0x74, 0x0C, 0xD0, 0x34, 0x00, 0xC3, 0x1D, 0x3C, 0x08,
+0xF0, 0x70, 0xC8, 0x4B, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38,
+0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x04, 0x6F, 0x00,
+0xFC, 0xA3, 0x70, 0x0F, 0xE0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x2F,
+0xC1, 0x3E, 0x0D, 0xFF, 0x00, 0xFE, 0x03, 0xF2, 0x0F, 0xC0, 0x3D, 0x00, 0xF7,
+0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xF5, 0x28, 0xFC, 0x00, 0xF0,
+0x83, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37,
+0x01, 0xB3, 0x02, 0x4D, 0x01, 0xF0, 0x05, 0xC0, 0xB7, 0x00, 0xD3, 0x80, 0x6C,
+0x03, 0xF2, 0x0D, 0xC2, 0x17, 0x00, 0xDF, 0x00, 0x7C, 0x00, 0x30, 0x2D, 0xC0,
+0xB4, 0x04, 0xD3, 0x04, 0x7C, 0x86, 0x30, 0x6D, 0xC0, 0x77, 0x00, 0xD3, 0x40,
+0x7C, 0x53, 0xB0, 0x09, 0xC0, 0x37, 0x00, 0xDF, 0x01, 0x44, 0x82, 0xF0, 0x11,
+0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x3D, 0x05,
+0xE1, 0x10, 0x84, 0x01, 0xD0, 0x06, 0x40, 0x3F, 0x04, 0xE5, 0x00, 0x84, 0x03,
+0xD0, 0x0E, 0x40, 0x3B, 0x20, 0xED, 0xA0, 0x9C, 0x02, 0x10, 0x4F, 0x42, 0x3C,
+0x21, 0xE1, 0x0A, 0x9C, 0x03, 0x18, 0x8E, 0x40, 0x3B, 0x00, 0xE1, 0x00, 0xB4,
+0x0B, 0x10, 0x0A, 0x48, 0x3B, 0x00, 0xFD, 0x00, 0x84, 0x02, 0xD0, 0x0A, 0x40,
+0x4C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x42, 0x81,
+0x01, 0x84, 0x07, 0x50, 0x1E, 0x40, 0x7B, 0x00, 0x49, 0x01, 0xA4, 0x47, 0x50,
+0x1E, 0x40, 0x5B, 0x00, 0xED, 0x01, 0x14, 0x05, 0x14, 0x1E, 0x50, 0x7A, 0x40,
+0xE1, 0x21, 0x34, 0x04, 0xD0, 0x9E, 0x60, 0x7B, 0x40, 0xE1, 0x01, 0x34, 0x17,
+0x90, 0x1A, 0x40, 0x7B, 0x00, 0xED, 0x01, 0x84, 0x04, 0xD0, 0x10, 0x40, 0x02,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x33, 0x00, 0x41, 0x0A,
+0x04, 0xC3, 0xC1, 0xBC, 0x44, 0x33, 0x00, 0x5D, 0x01, 0x04, 0x05, 0xD0, 0x08,
+0x40, 0x73, 0x0A, 0x8D, 0x20, 0x14, 0x0F, 0x10, 0x0C, 0x40, 0x32, 0x80, 0xC1,
+0x00, 0x14, 0x03, 0xD0, 0x0C, 0x40, 0x23, 0x00, 0x81, 0x40, 0x34, 0x03, 0x12,
+0x89, 0x42, 0x33, 0x00, 0xCD, 0x00, 0x04, 0x83, 0xD8, 0x1C, 0x40, 0x5A, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x15, 0x00, 0x73, 0x03, 0xCC,
+0x0D, 0xE0, 0x07, 0xC0, 0x17, 0x00, 0x7B, 0x00, 0xEC, 0x05, 0xF0, 0x15, 0xC2,
+0x1F, 0x00, 0x5F, 0x05, 0xDC, 0x61, 0x30, 0x05, 0xC0, 0x16, 0x60, 0x53, 0x80,
+0xF4, 0x01, 0xF1, 0x05, 0xC0, 0x17, 0x00, 0x53, 0x00, 0x7C, 0x01, 0xB0, 0x05,
+0xC0, 0x17, 0x10, 0x5F, 0x00, 0xCC, 0x39, 0xF0, 0x37, 0xC0, 0x5E, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x81, 0x00, 0x0F, 0x04, 0x7C, 0x28,
+0xF1, 0x01, 0xC3, 0x07, 0x10, 0x17, 0x08, 0x7C, 0x04, 0xF0, 0xA1, 0xC0, 0x07,
+0x01, 0x1F, 0x00, 0x1C, 0x00, 0xF0, 0x20, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x5C,
+0x80, 0x34, 0x21, 0xC0, 0x07, 0x02, 0x1F, 0x00, 0x3C, 0x80, 0xF0, 0x01, 0xC0,
+0x07, 0x80, 0x1E, 0x02, 0x7C, 0x00, 0xF0, 0x81, 0xC1, 0x49, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x00, 0x93, 0x08, 0x6C, 0x06, 0xF0,
+0x89, 0xC0, 0x63, 0x00, 0x93, 0x02, 0x4C, 0x02, 0x31, 0x09, 0xD0, 0x24, 0x00,
+0x9B, 0x00, 0x7C, 0x02, 0x34, 0x09, 0xD0, 0x64, 0xC0, 0x93, 0x08, 0x7C, 0x02,
+0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x24,
+0x00, 0x97, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x20, 0x64, 0x40, 0x91, 0x00, 0x44, 0x6E, 0xD2, 0x29,
+0x40, 0x27, 0x02, 0x91, 0x03, 0x04, 0x02, 0x10, 0x39, 0x41, 0x24, 0x08, 0x91,
+0x20, 0x7C, 0x26, 0x11, 0x29, 0x40, 0x24, 0x02, 0x91, 0x02, 0x74, 0x02, 0xD0,
+0x79, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x7C, 0x02, 0xB0, 0x09, 0x40, 0x24, 0x00,
+0x9D, 0x04, 0x74, 0x02, 0xD0, 0x09, 0x42, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x24, 0x02, 0x91, 0x00, 0x64, 0x02, 0xD0, 0x29, 0x40,
+0x27, 0x00, 0x91, 0x10, 0x44, 0x02, 0x10, 0x88, 0x48, 0x20, 0x00, 0x99, 0x04,
+0x74, 0x02, 0x10, 0x09, 0x40, 0x20, 0x00, 0x91, 0x10, 0x74, 0x02, 0x50, 0x49,
+0x40, 0x67, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x50, 0x09, 0x40, 0x64, 0x00, 0x95,
+0x01, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x20, 0x20, 0x41, 0x81, 0x04, 0x04, 0x1A, 0x90, 0x08, 0x40, 0x23,
+0xC1, 0x81, 0x04, 0x45, 0x02, 0x18, 0x08, 0x40, 0x20, 0x01, 0x89, 0x00, 0x34,
+0x12, 0x10, 0x4C, 0x40, 0x20, 0x01, 0x81, 0x04, 0x34, 0x12, 0xD0, 0x48, 0x40,
+0x23, 0x00, 0x8D, 0x00, 0x34, 0x22, 0x90, 0x08, 0x54, 0x20, 0x00, 0x8D, 0x00,
+0x34, 0x12, 0xD0, 0x48, 0x60, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB8, 0x96, 0x02, 0x13, 0x00, 0x6C, 0x08, 0xF0, 0x81, 0x44, 0x87, 0x02,
+0x13, 0x0A, 0x4C, 0x28, 0x30, 0xA1, 0xC0, 0x84, 0x02, 0x1B, 0x00, 0x7C, 0x00,
+0x30, 0xA1, 0x42, 0x84, 0x02, 0x11, 0x00, 0x7C, 0xA8, 0xF0, 0x01, 0xC0, 0x83,
+0x12, 0x1F, 0x0A, 0x7C, 0x58, 0x70, 0xA1, 0xC0, 0x84, 0x02, 0x17, 0x0A, 0x7C,
+0x28, 0xF0, 0x01, 0xC0, 0x77, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB0, 0x27, 0x02, 0xBF, 0x08, 0xF4, 0x0A, 0xF0, 0x8B, 0xC0, 0x27, 0x02, 0xFF,
+0x08, 0xFC, 0x02, 0xF4, 0x0B, 0xC2, 0x2F, 0x02, 0xB7, 0x00, 0xDC, 0x22, 0xF0,
+0x89, 0xC8, 0x27, 0x02, 0x9F, 0x08, 0xFC, 0x22, 0xF0, 0x89, 0xC0, 0x2F, 0x08,
+0xBF, 0x00, 0x5C, 0x92, 0x70, 0x0B, 0xC2, 0x27, 0x00, 0x9F, 0x00, 0xFC, 0x22,
+0xF0, 0x8B, 0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0,
+0x2F, 0x05, 0xB3, 0x84, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x2F, 0x02, 0xB3, 0x04,
+0x5C, 0x02, 0x30, 0x8B, 0xE0, 0x25, 0x00, 0xB7, 0x00, 0xDC, 0x02, 0xF0, 0x4B,
+0xC0, 0x2F, 0x05, 0xBF, 0x04, 0x4C, 0x03, 0xF4, 0x0B, 0xC0, 0x2F, 0x02, 0xDF,
+0x00, 0x4C, 0x52, 0xB0, 0x89, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0x7C, 0x02, 0xE2,
+0x09, 0x00, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07,
+0x01, 0x11, 0x88, 0x74, 0x49, 0xD0, 0x05, 0x41, 0x07, 0x02, 0x15, 0x14, 0x44,
+0x90, 0x11, 0x41, 0x42, 0x87, 0x44, 0x11, 0x00, 0x74, 0x20, 0x72, 0x41, 0xC1,
+0x05, 0x01, 0x1C, 0x08, 0x54, 0x49, 0x10, 0x01, 0x44, 0x07, 0x00, 0x1D, 0x14,
+0x54, 0x10, 0x70, 0x41, 0x40, 0x07, 0x24, 0x1D, 0x00, 0x74, 0x00, 0xD0, 0x01,
+0x42, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x20, 0x05,
+0x81, 0x00, 0x34, 0x32, 0xD0, 0x88, 0x40, 0x23, 0x20, 0x81, 0x2C, 0x44, 0x56,
+0x04, 0x48, 0x40, 0x25, 0x43, 0x85, 0x40, 0x14, 0x02, 0xD0, 0xC8, 0x40, 0x23,
+0x25, 0xCD, 0x00, 0x24, 0x32, 0x10, 0x88, 0x40, 0x33, 0x00, 0x9D, 0x04, 0x04,
+0x52, 0x90, 0x48, 0x44, 0x23, 0x01, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40,
+0x4B, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x91,
+0x01, 0x74, 0x83, 0xD0, 0x89, 0x40, 0x23, 0x00, 0x95, 0x00, 0x44, 0x02, 0x10,
+0x19, 0x40, 0xA7, 0xC0, 0x91, 0x01, 0x74, 0x06, 0x50, 0x09, 0x00, 0x27, 0x08,
+0x99, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x50, 0x02,
+0x58, 0x09, 0x40, 0x27, 0x08, 0x9D, 0x00, 0x74, 0x12, 0xD0, 0x09, 0x43, 0x63,
+0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x24, 0x40, 0x93, 0x05,
+0x7C, 0x0E, 0xF0, 0x39, 0xC0, 0x27, 0x00, 0x93, 0x03, 0x1D, 0x02, 0x10, 0x09,
+0xC8, 0x25, 0x40, 0x97, 0x20, 0x5C, 0x02, 0xF3, 0x09, 0xC0, 0x27, 0x10, 0x9F,
+0x00, 0x6C, 0x02, 0x70, 0x09, 0xC0, 0x67, 0x20, 0x8F, 0x01, 0x49, 0x02, 0xB0,
+0x19, 0xC8, 0x27, 0x10, 0x9F, 0x00, 0x7C, 0x16, 0xF0, 0x29, 0xC0, 0x17, 0x08,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x21, 0x10, 0x9F, 0x20, 0x7C,
+0x12, 0xF0, 0x09, 0xC1, 0x27, 0x00, 0x9F, 0x02, 0x7C, 0x26, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xE0, 0x25, 0x04, 0x9F, 0x00,
+0x5C, 0x02, 0x70, 0x09, 0xC1, 0x27, 0x01, 0x9F, 0x84, 0x6C, 0x02, 0xB0, 0x59,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x59, 0xC0, 0x5B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x13, 0x04, 0x7E, 0x68,
+0xB4, 0x21, 0xD0, 0x04, 0x08, 0x1D, 0x02, 0x6C, 0x00, 0xF0, 0x01, 0xC8, 0x07,
+0x00, 0x1F, 0x08, 0x7C, 0x00, 0xF0, 0x81, 0xC0, 0x07, 0x40, 0x13, 0x00, 0x5C,
+0x08, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x0C, 0x7C, 0x08, 0x30, 0x21, 0xC2, 0x53, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1C, 0x40, 0x71, 0x01, 0xE4, 0x0D, 0x30,
+0x07, 0x41, 0x14, 0x00, 0x7D, 0x0D, 0x44, 0x01, 0x70, 0x07, 0xC0, 0x11, 0x00,
+0x5D, 0x00, 0x76, 0x05, 0x90, 0x07, 0x40, 0x9F, 0x08, 0x61, 0x02, 0x44, 0x01,
+0x70, 0x17, 0xC8, 0x9E, 0x02, 0x5D, 0x00, 0x74, 0x01, 0x52, 0x05, 0x40, 0x17,
+0x01, 0x7D, 0x03, 0x74, 0x01, 0x10, 0x05, 0x44, 0x43, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x72, 0x00, 0x81, 0x09, 0x24, 0x0B, 0x50, 0x2C,
+0x42, 0x30, 0x00, 0xDD, 0x03, 0x24, 0x03, 0xD0, 0x9C, 0x40, 0x33, 0x00, 0x8D,
+0x01, 0x34, 0x22, 0xD0, 0x1C, 0x40, 0x33, 0x00, 0xC1, 0x10, 0x54, 0x83, 0x50,
+0xB4, 0x40, 0x30, 0x00, 0xCD, 0x40, 0x74, 0x03, 0x10, 0x0C, 0x40, 0x72, 0x00,
+0xCD, 0x81, 0x36, 0x83, 0x10, 0x0C, 0x40, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x80, 0x20, 0x05, 0xA1, 0x00, 0xA4, 0x07, 0x50, 0x1E, 0x60,
+0x38, 0x00, 0xAD, 0x04, 0x84, 0x13, 0xD0, 0x0E, 0x48, 0x3B, 0x00, 0xED, 0x80,
+0xB4, 0x03, 0x90, 0x0E, 0x44, 0x6B, 0x10, 0x21, 0x40, 0x84, 0x23, 0x40, 0x1E,
+0x40, 0x3A, 0x00, 0xED, 0x08, 0xB4, 0x13, 0x50, 0x4E, 0x40, 0x3B, 0x10, 0xAC,
+0x00, 0x34, 0x27, 0x10, 0x0E, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x18, 0xE8, 0x00, 0xA1, 0x01, 0xF4, 0x07, 0x70, 0x17, 0xC0, 0x78,
+0x00, 0xEF, 0x03, 0xAC, 0x27, 0xF0, 0x1E, 0xC0, 0x7B, 0x22, 0xED, 0x01, 0xB6,
+0x07, 0xF0, 0x16, 0x82, 0x73, 0x00, 0x03, 0x01, 0x9C, 0x17, 0x60, 0x1E, 0xC0,
+0x78, 0x08, 0xEF, 0x89, 0x3C, 0x17, 0x38, 0xDE, 0xC8, 0x7B, 0x00, 0xAF, 0x01,
+0xBC, 0x27, 0x30, 0x1E, 0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xB8, 0x05, 0x00, 0x9F, 0x00, 0x74, 0x03, 0x30, 0x05, 0xC0, 0x37, 0x08,
+0x8F, 0x00, 0x7C, 0x03, 0x70, 0x01, 0xC0, 0x35, 0x03, 0xDF, 0x00, 0x7C, 0x83,
+0xB1, 0x0D, 0xC0, 0x27, 0x00, 0x1F, 0x00, 0x7C, 0x9B, 0x51, 0x0C, 0xC0, 0x37,
+0x00, 0xDF, 0x02, 0x7C, 0x4B, 0x70, 0x8D, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x7C,
+0x03, 0xF2, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x20, 0x6D, 0x00, 0xF3, 0x01, 0xCC, 0x11, 0xB0, 0x1F, 0xC0, 0xFF, 0x00, 0xFF,
+0x01, 0xCC, 0x47, 0xF0, 0x1B, 0xC0, 0x7F, 0x00, 0xFF, 0x01, 0xBC, 0x07, 0x30,
+0x9F, 0xE0, 0x5C, 0x00, 0x3F, 0x01, 0xF8, 0x2F, 0x38, 0x1F, 0xC8, 0x6E, 0x28,
+0xF3, 0x81, 0xFC, 0x47, 0xFA, 0x9F, 0xC8, 0x6F, 0x00, 0x33, 0x21, 0x7C, 0x27,
+0x30, 0x9F, 0xC4, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00,
+0x29, 0x20, 0xE1, 0x08, 0x84, 0x21, 0x31, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00,
+0x84, 0x03, 0xD0, 0x0A, 0x40, 0x3B, 0x14, 0xED, 0x80, 0x9C, 0x23, 0x70, 0x8A,
+0xC0, 0x28, 0x01, 0x2D, 0x20, 0x9C, 0x03, 0x30, 0x4E, 0x40, 0x0C, 0x12, 0xE1,
+0x18, 0xB4, 0x03, 0x70, 0x0E, 0x40, 0x2F, 0x30, 0x01, 0x00, 0xB4, 0x07, 0xB0,
+0x0C, 0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
+0x00, 0xA1, 0x00, 0x84, 0x01, 0x10, 0x0E, 0x41, 0x3B, 0x00, 0x6D, 0x00, 0x84,
+0x0B, 0x50, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0x10, 0x06, 0x70,
+0x18, 0x10, 0x2D, 0x00, 0x14, 0x43, 0x1D, 0x0E, 0x40, 0x28, 0x44, 0xE5, 0x00,
+0xB4, 0x03, 0xD0, 0x0E, 0x44, 0x2B, 0x02, 0xA9, 0x00, 0xB4, 0x03, 0x10, 0x0E,
+0x40, 0x23, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x01, 0x00,
+0x81, 0x06, 0x05, 0x80, 0x10, 0x08, 0x40, 0x37, 0x00, 0x4D, 0x00, 0x04, 0x87,
+0xD0, 0x00, 0x46, 0x73, 0x08, 0xCD, 0x00, 0x14, 0x93, 0x51, 0x08, 0x40, 0x20,
+0x08, 0x0D, 0x00, 0x14, 0x03, 0x10, 0x0C, 0x40, 0x40, 0x10, 0xD5, 0x80, 0x34,
+0x03, 0x50, 0x0C, 0x60, 0x23, 0x00, 0x89, 0x20, 0x76, 0x13, 0x1C, 0xED, 0x48,
+0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x2D, 0x40, 0x93,
+0x00, 0x44, 0x06, 0x30, 0x09, 0xC0, 0x27, 0x00, 0xBF, 0x00, 0xCD, 0x07, 0xF0,
+0x05, 0xC0, 0xFF, 0x02, 0xDF, 0x00, 0x7C, 0x0B, 0x30, 0x09, 0xC4, 0x34, 0x00,
+0x1F, 0x00, 0xDC, 0x07, 0x30, 0x0D, 0xD0, 0x54, 0x00, 0xF7, 0x01, 0xFC, 0x03,
+0xF0, 0x0F, 0xC0, 0x37, 0x40, 0x1B, 0x00, 0xFC, 0x03, 0x10, 0x3D, 0xC4, 0x77,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x27, 0x00, 0x0F, 0x01,
+0x7C, 0x68, 0x70, 0x29, 0xC0, 0x27, 0x10, 0x9F, 0x00, 0x7C, 0x23, 0xF0, 0x1D,
+0xC8, 0x37, 0x00, 0xDF, 0x01, 0x1C, 0x03, 0x72, 0x25, 0xC0, 0x95, 0x00, 0x1F,
+0x82, 0x1C, 0x03, 0x70, 0x0D, 0xC0, 0x17, 0x00, 0xDB, 0x00, 0x7C, 0x03, 0x70,
+0x0D, 0xC0, 0x37, 0x00, 0x97, 0x00, 0x7C, 0x87, 0xF0, 0x0D, 0xC4, 0x17, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x2F, 0x00, 0x93, 0x00, 0x4C,
+0x02, 0xF0, 0x02, 0xC1, 0x3C, 0x00, 0xF3, 0x02, 0xCC, 0x03, 0xF0, 0x07, 0xC0,
+0x3C, 0x00, 0xFF, 0x03, 0xCC, 0x03, 0x30, 0x82, 0xC0, 0x6C, 0x40, 0x33, 0x00,
+0xFC, 0x43, 0x30, 0x0D, 0xC0, 0x4F, 0x00, 0xF3, 0x00, 0x8D, 0x03, 0x30, 0x0F,
+0xC0, 0x6F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x30, 0x0F, 0xD0, 0x04, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x46, 0x02, 0x11, 0x02, 0x54, 0x06,
+0x90, 0x71, 0x40, 0x34, 0x00, 0x91, 0x00, 0x44, 0x03, 0xD0, 0x20, 0x40, 0x34,
+0x00, 0xCD, 0x00, 0x6C, 0x03, 0x10, 0x25, 0x41, 0x84, 0x06, 0x11, 0x01, 0x74,
+0x03, 0x10, 0x1D, 0xC0, 0x41, 0x00, 0xD1, 0x00, 0x44, 0x03, 0x50, 0x0D, 0x40,
+0x67, 0x00, 0x9D, 0x05, 0x74, 0x03, 0x10, 0x0D, 0xC2, 0x06, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x22, 0x00, 0xD1, 0x02, 0x44, 0x06, 0xD0,
+0x11, 0x40, 0x64, 0x00, 0x81, 0x00, 0x44, 0x03, 0xD8, 0x21, 0x40, 0x34, 0x00,
+0xDD, 0x00, 0x44, 0x07, 0x10, 0x09, 0x40, 0x10, 0x80, 0x11, 0x03, 0x74, 0x03,
+0x90, 0x1D, 0x41, 0x37, 0x01, 0xD1, 0x00, 0x44, 0x03, 0x10, 0x0D, 0x40, 0x37,
+0x01, 0x1D, 0x01, 0x74, 0x03, 0x14, 0x0D, 0x44, 0x04, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xC1, 0x00, 0x14, 0x00, 0x98, 0x08,
+0x40, 0x20, 0x00, 0x81, 0x80, 0x05, 0x03, 0xD0, 0x09, 0x40, 0x30, 0x00, 0xDD,
+0x00, 0x24, 0x03, 0x14, 0x00, 0x50, 0x10, 0x00, 0x01, 0x00, 0x34, 0x03, 0x90,
+0x0C, 0x40, 0x57, 0x00, 0xC1, 0x00, 0x04, 0x03, 0x50, 0x0C, 0x40, 0x33, 0x80,
+0x0D, 0x02, 0x74, 0x03, 0x10, 0x0D, 0x4C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x98, 0x22, 0x40, 0x93, 0x00, 0x4C, 0x02, 0xF1, 0x01, 0x50,
+0x3C, 0x00, 0x43, 0x00, 0xCC, 0x03, 0xF0, 0x05, 0xD0, 0x3C, 0x00, 0xDF, 0x00,
+0x44, 0x03, 0x30, 0x00, 0xC0, 0x04, 0x00, 0x13, 0x00, 0xFC, 0x03, 0xB0, 0x0D,
+0xC0, 0x27, 0x40, 0xF3, 0x00, 0xC4, 0x03, 0x30, 0x0F, 0xC0, 0x27, 0x00, 0x1F,
+0x02, 0xBC, 0x13, 0x30, 0xAD, 0xC2, 0x04, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xB0, 0x0F, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF8, 0x0B, 0xC0, 0x3F,
+0x00, 0x7F, 0x00, 0xFC, 0x03, 0xF0, 0x03, 0x40, 0x3F, 0x00, 0xFF, 0x00, 0xFC,
+0x03, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x74, 0x0B, 0xE0,
+0x0D, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC8, 0x2F, 0x30, 0xBF, 0x04,
+0x7C, 0x0B, 0xF0, 0x4F, 0xC0, 0x17, 0x62, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA0, 0x7F, 0x00, 0x7E, 0x01, 0xFC, 0x07, 0x30, 0x1F, 0x44, 0x3C, 0x05,
+0xF7, 0x00, 0xEC, 0x23, 0xB0, 0x4F, 0xC0, 0x49, 0x00, 0x37, 0x03, 0xFC, 0x03,
+0x32, 0x2F, 0x40, 0x3D, 0x02, 0x23, 0x03, 0xDC, 0x24, 0x78, 0x93, 0xC0, 0x48,
+0x00, 0x23, 0x01, 0xE4, 0x03, 0xB0, 0x17, 0xC0, 0x4C, 0x00, 0xFF, 0x21, 0xCC,
+0x06, 0xE0, 0x03, 0xC0, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x08, 0x7F, 0x00, 0xDD, 0x01, 0xF4, 0x07, 0x10, 0x1F, 0x40, 0xF4, 0x00, 0xF1,
+0x03, 0x84, 0x3B, 0x10, 0x9D, 0xC0, 0x64, 0x00, 0x1D, 0x00, 0xF4, 0x2F, 0x14,
+0x6F, 0x44, 0xBC, 0x03, 0x11, 0x84, 0x4C, 0x00, 0xD0, 0x41, 0xC0, 0x54, 0x48,
+0x51, 0x01, 0x44, 0x2F, 0x10, 0x11, 0x50, 0x44, 0x00, 0xFD, 0xA1, 0x44, 0x04,
+0xD1, 0x09, 0x40, 0x0C, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x33, 0x00, 0x0D, 0x40, 0x34, 0x03, 0x91, 0x0C, 0x40, 0x30, 0x00, 0xC5, 0x22,
+0x24, 0x13, 0x91, 0x0C, 0x40, 0x01, 0x08, 0x0D, 0x84, 0x34, 0x03, 0x90, 0x2C,
+0x40, 0x31, 0x21, 0x01, 0xC0, 0x14, 0x14, 0x50, 0x01, 0x40, 0x32, 0x20, 0x91,
+0x00, 0x04, 0x03, 0x90, 0x0D, 0x40, 0x02, 0x00, 0xCD, 0x00, 0x04, 0x02, 0xD0,
+0x01, 0x42, 0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35,
+0x00, 0xDD, 0x00, 0x74, 0x03, 0x90, 0x0D, 0x40, 0x34, 0x00, 0xD1, 0x60, 0x44,
+0x03, 0x10, 0x0D, 0x40, 0x64, 0x24, 0x1D, 0x01, 0x74, 0x03, 0x92, 0x0D, 0x40,
+0x32, 0x88, 0x01, 0x01, 0x54, 0x04, 0xC0, 0x19, 0x50, 0x94, 0x01, 0x90, 0x08,
+0x44, 0x03, 0xD0, 0x09, 0x40, 0x46, 0x04, 0xDD, 0x00, 0x44, 0x46, 0xD1, 0x31,
+0x40, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x37, 0x00,
+0x9F, 0x04, 0x3C, 0x03, 0x94, 0x0C, 0xD0, 0x34, 0x10, 0xD7, 0x00, 0x6C, 0x03,
+0xB0, 0x0D, 0xC8, 0x45, 0x10, 0x9F, 0x03, 0x7C, 0x03, 0xB0, 0x0D, 0xC0, 0x35,
+0x00, 0x13, 0x11, 0x5C, 0x04, 0x71, 0x30, 0xC0, 0x26, 0x00, 0x13, 0x83, 0x6C,
+0x03, 0xB0, 0x48, 0xC0, 0xC6, 0x00, 0xCF, 0x00, 0x4D, 0x0E, 0xF0, 0x31, 0xD0,
+0x23, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x3D, 0x00, 0xBF,
+0x00, 0xFC, 0x03, 0x70, 0x0F, 0xC0, 0x3B, 0x00, 0xED, 0x40, 0xFC, 0x83, 0xF0,
+0x0E, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x70, 0x0E, 0xC4, 0x3D, 0x00,
+0xBF, 0x00, 0xEC, 0x02, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x7F, 0x00, 0x3C, 0x03,
+0x10, 0x4B, 0xC0, 0x0D, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x09, 0xC0, 0x1E,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x35, 0x20, 0x9F, 0x00,
+0x7C, 0x03, 0xF0, 0x4D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x5C, 0x83, 0x70, 0x0D,
+0xC0, 0x07, 0x00, 0x93, 0x02, 0x7C, 0x03, 0xB0, 0x0D, 0xC0, 0x34, 0x00, 0x9F,
+0x02, 0x5C, 0x02, 0xF0, 0x29, 0xC2, 0xA7, 0x01, 0x93, 0x06, 0x7C, 0x47, 0x30,
+0x49, 0xC0, 0x87, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x01, 0xC4, 0x08, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x20, 0x9D, 0x80, 0x74,
+0x03, 0xD0, 0x4D, 0x60, 0x3F, 0x00, 0xFD, 0x00, 0xC4, 0x83, 0x10, 0x0F, 0x44,
+0xA7, 0x1A, 0x91, 0x00, 0xBC, 0x13, 0xD0, 0x0F, 0x40, 0x3C, 0x00, 0x9D, 0x00,
+0x44, 0x02, 0xD0, 0x19, 0x40, 0x83, 0x01, 0xC1, 0x51, 0xC4, 0x0B, 0x50, 0x09,
+0x40, 0x87, 0x00, 0xDC, 0x00, 0x74, 0x0A, 0xD0, 0x99, 0x40, 0x6D, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x13,
+0xD0, 0x2C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x54, 0x03, 0x58, 0x0C, 0x41, 0x23,
+0x00, 0x81, 0x00, 0x34, 0x13, 0x90, 0x0C, 0x44, 0x30, 0x00, 0x0D, 0x80, 0x14,
+0x00, 0xD1, 0x00, 0x40, 0x82, 0x08, 0xC5, 0x63, 0x14, 0x03, 0x10, 0x3C, 0x40,
+0xC3, 0x03, 0xCD, 0x00, 0x34, 0x16, 0xD0, 0x19, 0x40, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0D, 0x80, 0x78, 0x00, 0xED, 0x81, 0xB4, 0x27, 0xD0,
+0x1E, 0x40, 0x7B, 0x00, 0xCD, 0x89, 0x84, 0x07, 0x18, 0x1E, 0x40, 0x6F, 0x01,
+0x21, 0x01, 0xB4, 0x07, 0xC0, 0x1C, 0x48, 0x78, 0x00, 0xBD, 0x41, 0x84, 0x07,
+0xD0, 0x1A, 0x41, 0x5F, 0x00, 0xE5, 0x01, 0x84, 0x07, 0x50, 0x1E, 0x40, 0x4B,
+0x01, 0xED, 0x21, 0xB4, 0x04, 0xD0, 0x5A, 0x40, 0x3D, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0x8F, 0x08, 0x3C, 0x03, 0xF0, 0x8C,
+0x40, 0x33, 0x00, 0xCF, 0x00, 0x1C, 0x23, 0x70, 0x1C, 0xC0, 0x63, 0x21, 0x83,
+0x02, 0x3E, 0x03, 0xB0, 0x8C, 0xC0, 0x30, 0x00, 0xCF, 0x08, 0x1C, 0x02, 0xF0,
+0x04, 0xC0, 0x33, 0x01, 0x87, 0x04, 0x1C, 0x23, 0x38, 0x0C, 0xC1, 0x03, 0x02,
+0xCF, 0x00, 0x3C, 0xE3, 0xF0, 0x00, 0xC1, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xB8, 0x7D, 0x00, 0xFF, 0x00, 0xFC, 0x87, 0xF0, 0x9F, 0xC0,
+0x3F, 0x00, 0xFF, 0x50, 0xFC, 0x03, 0xF2, 0x8F, 0xC0, 0x2F, 0x42, 0xBF, 0x08,
+0xDC, 0x03, 0xF8, 0x0F, 0xC2, 0x3F, 0x94, 0xFF, 0x40, 0xFC, 0x23, 0xF0, 0x8D,
+0x40, 0x3F, 0x40, 0xBB, 0x00, 0x5C, 0x63, 0xF0, 0x0F, 0xC8, 0x0F, 0x03, 0xFF,
+0x01, 0xFC, 0x03, 0xF0, 0x43, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA0, 0x37, 0x80, 0x9E, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0xC0, 0x37,
+0x02, 0xDF, 0x11, 0x4C, 0x53, 0xF0, 0x0D, 0xC0, 0x07, 0x00, 0x9F, 0x20, 0x4C,
+0x03, 0xF0, 0x4D, 0xC0, 0xF7, 0x01, 0x5B, 0x00, 0x7C, 0x01, 0x72, 0x1D, 0xC0,
+0x24, 0x00, 0xDF, 0x00, 0x4C, 0x03, 0xF0, 0x08, 0xC0, 0x44, 0xC0, 0xDB, 0x01,
+0x4C, 0x01, 0xD0, 0x1D, 0x40, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0x88, 0x39, 0x01, 0xAD, 0x00, 0x34, 0x8B, 0x10, 0x2E, 0x48, 0x3B, 0x31,
+0xED, 0x04, 0xAC, 0x03, 0xD0, 0x2E, 0x40, 0x0B, 0x28, 0x3D, 0x00, 0x84, 0x3B,
+0xD0, 0xAE, 0xC0, 0x39, 0x0A, 0xE1, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x00, 0x38,
+0x00, 0xED, 0x80, 0x84, 0x13, 0xD2, 0x0A, 0x40, 0x08, 0x00, 0xC5, 0x02, 0x94,
+0x01, 0xD0, 0x0F, 0x40, 0x4C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x00, 0x79, 0x02, 0xA5, 0x43, 0xB4, 0x17, 0x10, 0x5E, 0x40, 0x7B, 0x00, 0xED,
+0x01, 0x84, 0x27, 0x58, 0x5E, 0x44, 0x6B, 0x10, 0xAD, 0x11, 0x85, 0x07, 0xD0,
+0x1E, 0x46, 0x73, 0x01, 0xE9, 0x91, 0xB4, 0x87, 0x42, 0x1E, 0x40, 0x7A, 0x00,
+0xFD, 0x01, 0x94, 0x07, 0xD0, 0x0A, 0x41, 0xC8, 0x40, 0xED, 0x05, 0x84, 0x05,
+0xD0, 0x1A, 0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28,
+0x33, 0x00, 0x8D, 0x00, 0x34, 0x03, 0x14, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00,
+0x24, 0x03, 0xD0, 0x0C, 0x40, 0x73, 0x02, 0xCD, 0x03, 0x44, 0x03, 0xD0, 0x0C,
+0x40, 0x31, 0x00, 0xC9, 0x01, 0x34, 0x17, 0xD0, 0x5C, 0x42, 0xF2, 0x00, 0xCD,
+0x80, 0x04, 0x03, 0xD0, 0x38, 0x40, 0x70, 0x41, 0xCD, 0x40, 0x14, 0x63, 0xD0,
+0x3C, 0x49, 0x58, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15,
+0x00, 0x7F, 0x00, 0x3C, 0x01, 0xB0, 0x04, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x4C,
+0x01, 0xF0, 0x04, 0xC0, 0x9F, 0x00, 0x7F, 0x01, 0x44, 0x01, 0xF0, 0x05, 0xC4,
+0x17, 0x00, 0x7B, 0x02, 0xF4, 0x15, 0x70, 0x17, 0xD0, 0x9A, 0x10, 0x7F, 0x10,
+0x5C, 0x01, 0xF0, 0x07, 0xC0, 0x1C, 0x00, 0x5F, 0x00, 0xCC, 0x05, 0xF0, 0x57,
+0xD0, 0x5C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00,
+0x1F, 0x04, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x3C, 0x00,
+0xF0, 0x01, 0xC4, 0x07, 0x00, 0x1D, 0x00, 0x7C, 0x88, 0xF0, 0x01, 0xC0, 0x05,
+0x00, 0x17, 0x10, 0x7C, 0x00, 0xF0, 0x81, 0xC0, 0x05, 0x02, 0x1F, 0x00, 0x75,
+0x00, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x17, 0x80, 0x7C, 0x08, 0xF0, 0x01, 0xC0,
+0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x9F,
+0x00, 0x4C, 0x12, 0x30, 0x29, 0xC2, 0x24, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30,
+0x49, 0xC0, 0x24, 0x06, 0x9F, 0x10, 0x4C, 0x22, 0x30, 0x09, 0xE0, 0x27, 0x00,
+0x97, 0x00, 0x7C, 0x02, 0x32, 0x59, 0xC0, 0x27, 0x26, 0x93, 0x80, 0x7D, 0x0A,
+0xF0, 0x19, 0xC1, 0x67, 0x02, 0x9F, 0x02, 0x7C, 0x02, 0x30, 0x59, 0xC0, 0x43,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x2E, 0x00, 0x8D, 0x00,
+0xC4, 0x1E, 0x10, 0x2B, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x79,
+0x40, 0x65, 0x00, 0x9D, 0x80, 0x68, 0x06, 0x50, 0x09, 0x60, 0x27, 0x00, 0x9D,
+0x00, 0x5C, 0x02, 0xB1, 0x39, 0xC2, 0xE7, 0x00, 0x81, 0x82, 0x6C, 0x1A, 0xD0,
+0x89, 0xC0, 0x25, 0x00, 0xBD, 0x03, 0x34, 0x1A, 0x12, 0x49, 0x40, 0x07, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x20, 0x9D, 0x40, 0x44,
+0x02, 0x10, 0x29, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x18, 0x09, 0x42,
+0x24, 0x00, 0x8D, 0x00, 0x44, 0x82, 0x12, 0x09, 0x40, 0x27, 0x00, 0x95, 0x60,
+0x34, 0x02, 0x58, 0x2D, 0x40, 0xA7, 0x80, 0xD1, 0x98, 0x64, 0x02, 0xD0, 0x09,
+0x40, 0x27, 0x00, 0x9D, 0x40, 0x74, 0x22, 0x14, 0x09, 0x40, 0x63, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x9D, 0x02, 0x04, 0x02,
+0x10, 0x08, 0x40, 0xA0, 0x00, 0x8D, 0x06, 0x34, 0x02, 0x10, 0x08, 0x40, 0x21,
+0x00, 0x8D, 0x08, 0x45, 0x83, 0x5A, 0x88, 0x60, 0x23, 0x82, 0x8D, 0x08, 0x34,
+0x22, 0xD0, 0x88, 0x40, 0x27, 0x00, 0x81, 0x00, 0x24, 0x02, 0xD0, 0x08, 0x40,
+0x31, 0x80, 0xCD, 0x00, 0x74, 0x02, 0x10, 0x48, 0x40, 0x43, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x46, 0x00, 0x1F, 0x00, 0x4D, 0x04, 0x34,
+0x11, 0x50, 0x04, 0x05, 0x0F, 0x00, 0x7C, 0x78, 0x30, 0x41, 0x41, 0x04, 0x00,
+0x1D, 0x02, 0x44, 0x50, 0x31, 0x61, 0x41, 0x87, 0x05, 0x17, 0x42, 0x74, 0x08,
+0x74, 0x20, 0xC0, 0x07, 0x00, 0x13, 0x40, 0x6C, 0x50, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x81, 0x7C, 0x00, 0x30, 0xA1, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x19, 0xB8, 0xA7, 0x00, 0xBF, 0x01, 0x7C, 0x0A, 0xF1, 0x29,
+0xC0, 0x67, 0x00, 0x9F, 0x09, 0x7C, 0x82, 0xF4, 0x09, 0xC0, 0x2F, 0x20, 0xBF,
+0x04, 0x7C, 0x02, 0xF0, 0x49, 0xC0, 0x27, 0x01, 0xFF, 0x24, 0xDC, 0x12, 0x00,
+0x4B, 0xC0, 0x2D, 0x40, 0xAF, 0x00, 0x6C, 0x02, 0xF0, 0x0B, 0xC8, 0x39, 0x00,
+0x9F, 0x22, 0xFC, 0x03, 0xF0, 0x8B, 0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x67, 0x01, 0x93, 0x02, 0xCC, 0x06, 0xF0, 0x1B, 0xC0,
+0x25, 0x02, 0x9B, 0xE0, 0x7C, 0x12, 0xF0, 0x4B, 0xC5, 0x2F, 0x00, 0x93, 0x00,
+0xDC, 0x02, 0x38, 0x89, 0xC0, 0x27, 0x49, 0x93, 0x00, 0x5E, 0x22, 0x30, 0x0B,
+0x40, 0x2C, 0x00, 0xA3, 0x00, 0xCC, 0x12, 0xF0, 0x0A, 0xC0, 0x2F, 0x00, 0xBB,
+0x11, 0xFC, 0x82, 0xE0, 0x0B, 0xD0, 0x74, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1C, 0x08, 0x07, 0x08, 0x0B, 0x01, 0x45, 0x00, 0xD0, 0x01, 0x46, 0x47,
+0x01, 0x1D, 0x9D, 0x74, 0x50, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x11, 0x10, 0x5C,
+0x00, 0x14, 0x81, 0x00, 0x07, 0x25, 0x11, 0x04, 0x5C, 0x10, 0x10, 0x01, 0x51,
+0x04, 0x20, 0x11, 0x00, 0x74, 0x00, 0xD2, 0x05, 0x48, 0x07, 0x10, 0x13, 0x42,
+0x74, 0x00, 0xD0, 0x05, 0x40, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0xA0, 0xA3, 0x00, 0x81, 0x00, 0x04, 0x0A, 0xD0, 0x28, 0x40, 0x23, 0x02,
+0x8D, 0x00, 0x34, 0x32, 0xD0, 0x08, 0x40, 0x21, 0x00, 0x81, 0x04, 0x14, 0x22,
+0x90, 0x08, 0x44, 0x23, 0x03, 0x89, 0x14, 0x54, 0x12, 0x18, 0x48, 0x40, 0x22,
+0x40, 0x81, 0x00, 0x04, 0x22, 0xD0, 0x08, 0x40, 0x23, 0x00, 0x89, 0x00, 0x34,
+0x02, 0xD1, 0x08, 0x40, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x88, 0x25, 0x00, 0x89, 0x04, 0x44, 0x02, 0xD0, 0x0D, 0x40, 0x27, 0x00, 0x9D,
+0x80, 0x74, 0x02, 0xD0, 0x09, 0x00, 0xA7, 0x42, 0x91, 0x02, 0x54, 0x02, 0x98,
+0x09, 0x40, 0x27, 0x00, 0x91, 0x00, 0x54, 0x02, 0x10, 0x0C, 0x40, 0x26, 0x20,
+0x91, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x01, 0x91, 0x00, 0x74, 0x02,
+0xD0, 0x0D, 0x40, 0x60, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28,
+0x25, 0x00, 0xB3, 0x81, 0x4C, 0x02, 0xF0, 0x09, 0xC8, 0x2F, 0x08, 0xBB, 0x80,
+0x7C, 0x02, 0xF1, 0x09, 0x80, 0x65, 0x00, 0x93, 0x00, 0x1C, 0x02, 0x90, 0x09,
+0x48, 0x27, 0x00, 0x9B, 0x03, 0x1C, 0x1A, 0x30, 0x59, 0xC0, 0x22, 0x01, 0x83,
+0xA7, 0x4C, 0x02, 0xD0, 0x29, 0xC4, 0x67, 0x00, 0x9B, 0x80, 0x7C, 0x2A, 0xF0,
+0x29, 0xC0, 0x14, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x25,
+0x00, 0x9F, 0x01, 0x70, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x80, 0x9C, 0xA0, 0x7C,
+0x82, 0xF0, 0x09, 0xC0, 0x67, 0x00, 0x9F, 0x03, 0x7E, 0x02, 0x50, 0x09, 0xC4,
+0x27, 0x00, 0x9F, 0x05, 0x7C, 0x02, 0xF4, 0x49, 0xE0, 0x65, 0x01, 0x9C, 0x44,
+0x5C, 0x42, 0xF0, 0x09, 0x00, 0x67, 0x04, 0x9F, 0x20, 0x7E, 0x06, 0xD0, 0x58,
+0xC1, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x01, 0x00,
+0x1F, 0x00, 0x5C, 0x40, 0xF0, 0x01, 0xE0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00,
+0x31, 0x01, 0xE0, 0x06, 0x11, 0x1F, 0x00, 0x7C, 0x00, 0x90, 0x01, 0xC8, 0x03,
+0x00, 0x1F, 0x00, 0x7C, 0x80, 0xF8, 0x01, 0xC0, 0x86, 0x00, 0x1F, 0x80, 0x5C,
+0x00, 0x60, 0x01, 0xC0, 0x85, 0x00, 0x1F, 0x04, 0x4D, 0x00, 0xF0, 0x21, 0xC0,
+0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x14, 0x00, 0x5D,
+0x00, 0xD4, 0x0D, 0xD8, 0x07, 0x60, 0x17, 0x10, 0x5E, 0x00, 0x74, 0x01, 0x10,
+0x57, 0xE0, 0x9B, 0x80, 0x5D, 0x20, 0xF4, 0x01, 0xB2, 0x05, 0xC0, 0x17, 0x80,
+0x5D, 0x00, 0x7C, 0x01, 0x70, 0x17, 0xC0, 0x1C, 0x00, 0x7D, 0x02, 0xC4, 0x01,
+0xB0, 0x17, 0x40, 0x98, 0x00, 0x7F, 0x03, 0xC4, 0x45, 0xD2, 0x07, 0x48, 0x41,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00,
+0x04, 0x2E, 0x50, 0x08, 0x40, 0x31, 0x80, 0xC9, 0x00, 0x34, 0x03, 0x13, 0x18,
+0x60, 0x32, 0x80, 0xCD, 0x00, 0x34, 0x02, 0x18, 0x0C, 0x40, 0x33, 0x10, 0xCD,
+0x00, 0x34, 0x03, 0xD0, 0x7C, 0x50, 0x20, 0x00, 0xCD, 0x1A, 0x16, 0x0B, 0x10,
+0x04, 0x00, 0xF1, 0x02, 0x8D, 0x00, 0x04, 0x1E, 0xD0, 0x8C, 0x40, 0x40, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0xED, 0x04, 0x94,
+0x02, 0xD0, 0x0A, 0x40, 0x3B, 0x01, 0xED, 0x04, 0x34, 0x07, 0x18, 0x0A, 0x40,
+0x3B, 0x00, 0xED, 0x04, 0x34, 0x02, 0x92, 0x4E, 0x40, 0x3B, 0x01, 0xED, 0x00,
+0xB4, 0x03, 0x50, 0x0E, 0x41, 0x28, 0x10, 0xAD, 0x40, 0x84, 0x04, 0x90, 0x3E,
+0x40, 0x38, 0x00, 0xAD, 0x83, 0x86, 0x03, 0xD0, 0x0A, 0x40, 0x11, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x78, 0x00, 0xEF, 0x03, 0x94, 0x07,
+0x70, 0x1A, 0xC0, 0x79, 0x01, 0xED, 0x05, 0xB4, 0x37, 0x31, 0x1E, 0x40, 0x7A,
+0x08, 0xED, 0x0B, 0xB4, 0x06, 0x34, 0x1E, 0xC0, 0x7B, 0x02, 0xED, 0x85, 0xBC,
+0x27, 0xD8, 0x17, 0xE0, 0x68, 0x00, 0xAF, 0x81, 0x9C, 0x04, 0x78, 0x16, 0xC0,
+0x79, 0x00, 0xEF, 0x01, 0x8C, 0x07, 0xF0, 0x1B, 0xC0, 0x50, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x10, 0xDF, 0x40, 0x7C, 0x03, 0xF0,
+0x09, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x7C, 0x2B, 0xF4, 0x0D, 0xC0, 0x35, 0x00,
+0xDF, 0x00, 0x7C, 0x02, 0x70, 0x0D, 0xC0, 0x35, 0x82, 0xDF, 0x3E, 0x5C, 0x3B,
+0x70, 0x01, 0xE0, 0x25, 0x20, 0x9F, 0x00, 0x3C, 0x00, 0x70, 0x0D, 0xC2, 0x27,
+0x00, 0xC7, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA0, 0x7F, 0x00, 0xEF, 0x09, 0xCC, 0x32, 0xF8, 0x8B,
+0xC0, 0x7C, 0x04, 0xFF, 0x11, 0xFC, 0x07, 0xF0, 0x1B, 0xC8, 0x7F, 0x00, 0xFF,
+0x01, 0xDE, 0x06, 0xF0, 0xBD, 0xC1, 0x74, 0x00, 0xFF, 0x01, 0xFC, 0x07, 0xF0,
+0x1B, 0xC0, 0x6C, 0x00, 0x9B, 0x89, 0xFC, 0x25, 0xF0, 0x17, 0xC0, 0x7C, 0x00,
+0xBB, 0x01, 0xBC, 0x07, 0x38, 0x9F, 0xC0, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x80, 0x39, 0x00, 0xED, 0x1C, 0x84, 0x22, 0xD8, 0x0A, 0xC0,
+0x3A, 0xA0, 0xED, 0x08, 0xB4, 0x03, 0xD0, 0x08, 0x40, 0x13, 0x00, 0xED, 0x00,
+0x8C, 0x12, 0xD0, 0x5E, 0x40, 0x78, 0x02, 0xED, 0x00, 0x9C, 0x43, 0xD0, 0x0B,
+0x60, 0x28, 0x06, 0xAD, 0x05, 0xB4, 0x24, 0xD2, 0x0E, 0xC0, 0x3A, 0x80, 0xA5,
+0x00, 0xB4, 0x09, 0xF2, 0xC2, 0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x08, 0x39, 0x00, 0xFD, 0x81, 0xA4, 0x03, 0xD8, 0x88, 0x40, 0x78,
+0x02, 0xE5, 0x01, 0xB4, 0x03, 0x50, 0x0A, 0x40, 0x3B, 0x02, 0xFD, 0x18, 0x94,
+0x02, 0xD1, 0x4E, 0x54, 0x3A, 0x10, 0xED, 0x00, 0xB4, 0x23, 0xD0, 0x0E, 0x40,
+0x28, 0x00, 0xA9, 0x14, 0xB4, 0x80, 0xD8, 0x86, 0x40, 0x39, 0x00, 0xE1, 0x00,
+0xB4, 0x03, 0x10, 0x0E, 0x40, 0x63, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x04, 0x01, 0xD0, 0x08, 0x64, 0x32, 0x00,
+0xCD, 0x80, 0x34, 0x03, 0xD0, 0x08, 0x60, 0x13, 0x00, 0xCD, 0x81, 0x04, 0x02,
+0xD0, 0x0D, 0x40, 0x36, 0x00, 0xDD, 0x40, 0x54, 0x0F, 0xD1, 0x28, 0x44, 0xE0,
+0x10, 0x8D, 0x40, 0x34, 0x00, 0xD0, 0x88, 0x40, 0x63, 0x00, 0xC5, 0x00, 0x34,
+0x09, 0x52, 0x30, 0x40, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA8, 0x35, 0x00, 0xDF, 0x41, 0x6D, 0x02, 0xD0, 0x0D, 0xC0, 0x34, 0x00, 0xDF,
+0x00, 0xFC, 0x03, 0xF0, 0x09, 0xC8, 0xF7, 0x08, 0xFF, 0x03, 0x54, 0x83, 0xD2,
+0x0F, 0x48, 0x3E, 0x00, 0xFF, 0x08, 0xF4, 0x0B, 0xD0, 0x2D, 0xD0, 0x34, 0x02,
+0x8B, 0x01, 0x7C, 0x00, 0xD0, 0x0C, 0xC0, 0xB5, 0x06, 0x93, 0x00, 0x7C, 0x0A,
+0x10, 0x21, 0xC0, 0x57, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+0x33, 0x00, 0xDF, 0x10, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x29, 0xC4, 0x77, 0x04, 0xDF, 0x04, 0x1C, 0x0A, 0xF0, 0x0D,
+0xC0, 0x35, 0x00, 0xDF, 0x00, 0x5C, 0x03, 0xF0, 0x4D, 0xC0, 0xA7, 0x08, 0x9F,
+0x60, 0x7C, 0x88, 0xF1, 0x2D, 0x40, 0xB6, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0xA1, 0xC8, 0x37, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F,
+0x00, 0xF3, 0x00, 0xFC, 0x12, 0x30, 0x2F, 0xC0, 0x3F, 0x20, 0xF3, 0x40, 0xFC,
+0x03, 0xF0, 0x1F, 0xC0, 0x2C, 0x02, 0xFF, 0x80, 0xFC, 0x87, 0x30, 0x0F, 0xD0,
+0x3C, 0x00, 0xF5, 0x00, 0xCD, 0x43, 0xB0, 0x07, 0xC0, 0x7F, 0x00, 0xBF, 0x00,
+0xCC, 0x80, 0xF0, 0x0F, 0x80, 0x3C, 0x00, 0xB3, 0x04, 0xFC, 0x40, 0xF0, 0x0A,
+0xC1, 0x04, 0x26, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x20,
+0xD1, 0x00, 0x74, 0x06, 0x94, 0x05, 0xC0, 0x35, 0x00, 0xD1, 0x00, 0x74, 0x03,
+0xD0, 0x84, 0x41, 0x25, 0x00, 0xDD, 0x20, 0x74, 0x01, 0x10, 0x0D, 0x40, 0x34,
+0x00, 0xD1, 0x00, 0x44, 0x03, 0xB0, 0x21, 0x40, 0x17, 0x00, 0x9D, 0x23, 0x44,
+0x4C, 0xD0, 0x0D, 0x50, 0x60, 0x84, 0x95, 0x07, 0x74, 0x0C, 0xD0, 0x39, 0x50,
+0x04, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x36, 0xC0, 0xD1,
+0x00, 0x74, 0x02, 0x90, 0x0D, 0x40, 0x33, 0x00, 0xD1, 0x00, 0x74, 0x03, 0xD0,
+0x09, 0x40, 0x34, 0x00, 0xDD, 0x00, 0x64, 0x1B, 0x10, 0x0D, 0x40, 0x34, 0x00,
+0xD5, 0x00, 0x64, 0x03, 0x10, 0x01, 0x40, 0xB7, 0x01, 0x9D, 0x11, 0x44, 0x04,
+0xD0, 0x0D, 0x41, 0x45, 0x00, 0x91, 0x00, 0x74, 0x06, 0x50, 0x11, 0x40, 0x04,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0xC1, 0x00,
+0x34, 0x02, 0x90, 0x08, 0x40, 0x31, 0x00, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x08,
+0x40, 0x11, 0x00, 0xCD, 0x00, 0x34, 0x02, 0x14, 0x4C, 0x40, 0x30, 0x04, 0xC5,
+0x20, 0x04, 0x03, 0xD4, 0x00, 0x44, 0x23, 0x80, 0x8D, 0x30, 0x05, 0x40, 0xD0,
+0x0D, 0x40, 0x25, 0x00, 0x85, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x42, 0x40, 0x81,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0xF3, 0x40, 0x7C,
+0x03, 0x30, 0x0D, 0xC4, 0x3F, 0x00, 0xF3, 0x00, 0xFC, 0x03, 0xF0, 0x2D, 0xC2,
+0xA4, 0x02, 0xFD, 0x00, 0x7C, 0x03, 0x30, 0x0E, 0xC0, 0x3C, 0x01, 0xF7, 0x00,
+0xCC, 0x03, 0x32, 0x05, 0xC2, 0x37, 0x00, 0x9F, 0x00, 0x4C, 0x10, 0xF0, 0x0D,
+0xC0, 0x25, 0x00, 0x51, 0x00, 0x7C, 0x00, 0x70, 0x09, 0xC0, 0x04, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xA8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x01,
+0x78, 0x07, 0xC8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x47, 0xC1, 0x0F,
+0x00, 0xEF, 0x00, 0xFC, 0x01, 0xF0, 0x2F, 0xC0, 0x3F, 0x00, 0xFB, 0x00, 0xFC,
+0x03, 0x30, 0x03, 0xC0, 0x1F, 0x00, 0x3F, 0x00, 0x7C, 0x00, 0xF0, 0x0A, 0x40,
+0x2A, 0x08, 0x7F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x17, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x3F, 0x08, 0xA3, 0x00, 0xFC, 0x33, 0x30,
+0x9B, 0xC0, 0xEF, 0x00, 0xFF, 0x03, 0x9D, 0x27, 0xB0, 0x1F, 0xC0, 0x7C, 0x02,
+0xFB, 0x09, 0xCD, 0x07, 0x70, 0x1F, 0xC8, 0x7A, 0x08, 0xFF, 0x01, 0xFC, 0x07,
+0x31, 0x9F, 0xC0, 0x7F, 0x00, 0xFF, 0x09, 0xFE, 0x27, 0x30, 0x1F, 0xC0, 0x7A,
+0x40, 0xB3, 0x01, 0xFC, 0x00, 0x30, 0x26, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x3B, 0x38, 0xD1, 0x43, 0xF4, 0x13, 0x12, 0x4C,
+0x44, 0x27, 0x11, 0x1C, 0x84, 0x44, 0x10, 0x10, 0x11, 0x50, 0x04, 0x01, 0x11,
+0x04, 0x44, 0xD0, 0x50, 0x11, 0x40, 0x07, 0x05, 0x0D, 0x10, 0x34, 0x40, 0x10,
+0x41, 0x40, 0x07, 0x00, 0x1D, 0x44, 0x5C, 0x10, 0x10, 0x11, 0x40, 0x44, 0x00,
+0x91, 0x01, 0x5C, 0x0C, 0x14, 0x45, 0x40, 0x0F, 0x60, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x11, 0xA0, 0x23, 0x05, 0x81, 0x22, 0x14, 0x33, 0x10, 0x0C, 0x48,
+0x21, 0x01, 0xCD, 0x00, 0x44, 0x13, 0x54, 0x0D, 0x40, 0x31, 0x00, 0xC1, 0x80,
+0x04, 0x03, 0x56, 0x0C, 0x44, 0x33, 0x00, 0xCD, 0x04, 0x34, 0x13, 0x90, 0x4C,
+0x40, 0x33, 0x05, 0xCD, 0x20, 0x34, 0x13, 0x10, 0x0D, 0x40, 0x30, 0x00, 0x01,
+0x01, 0x34, 0x0A, 0xD0, 0x40, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x88, 0x35, 0x40, 0xD1, 0x84, 0x74, 0x03, 0x14, 0x3D, 0x40, 0x27,
+0x20, 0x0D, 0x00, 0x54, 0x00, 0x90, 0x01, 0x42, 0x05, 0x00, 0x01, 0x00, 0x44,
+0x00, 0x54, 0x01, 0x60, 0x07, 0x00, 0x1D, 0x80, 0x70, 0x00, 0x90, 0x01, 0x40,
+0x07, 0x00, 0x1D, 0x20, 0x14, 0x00, 0x18, 0x01, 0x40, 0x04, 0x00, 0x51, 0x01,
+0x74, 0x00, 0xD1, 0x01, 0x40, 0x0F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA0, 0x37, 0x00, 0x93, 0x01, 0x5C, 0x03, 0x30, 0x3D, 0xC0, 0x65, 0x0A,
+0xDF, 0x00, 0x4C, 0x83, 0xF0, 0x0D, 0xC8, 0x35, 0x40, 0xDB, 0x80, 0x08, 0x03,
+0x74, 0x0D, 0xC4, 0x36, 0x10, 0xDF, 0x00, 0x78, 0x03, 0xA0, 0x0D, 0xC0, 0x37,
+0x80, 0xDF, 0x00, 0x74, 0x03, 0x34, 0x0C, 0xC2, 0x36, 0x00, 0x91, 0x01, 0x3C,
+0x15, 0xF0, 0x15, 0xC0, 0x03, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x88, 0x3D, 0x00, 0xFF, 0x21, 0xF4, 0x03, 0xD0, 0x0F, 0xC0, 0x2F, 0x00, 0x3F,
+0x40, 0xE4, 0x00, 0x30, 0x03, 0xC0, 0x0E, 0x00, 0x3F, 0x00, 0xFC, 0x40, 0xF0,
+0x03, 0x00, 0x0F, 0x00, 0x3F, 0x30, 0xFC, 0x80, 0x70, 0x03, 0xC0, 0x0F, 0xA0,
+0x3F, 0x40, 0xDC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x14, 0xFF, 0x00, 0xDC, 0x24,
+0x30, 0x47, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08,
+0x61, 0x10, 0x9B, 0x01, 0x6C, 0x03, 0x34, 0x3D, 0xC0, 0x24, 0x00, 0xD3, 0x50,
+0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x77, 0x00, 0xD3, 0x08, 0x4C, 0x07, 0xB0, 0x4D,
+0xC0, 0x37, 0x00, 0xD7, 0x01, 0x4C, 0x83, 0x30, 0x1D, 0xC1, 0x37, 0x00, 0xDF,
+0x01, 0x7C, 0x97, 0xF0, 0x1D, 0xC0, 0x34, 0x00, 0x93, 0x10, 0x7C, 0x20, 0x30,
+0x25, 0xD0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xB4,
+0x02, 0xD1, 0x20, 0xD4, 0x2B, 0x10, 0x2D, 0x40, 0x64, 0x01, 0x1A, 0x03, 0x3C,
+0x00, 0x14, 0x40, 0x42, 0x87, 0x00, 0x11, 0x01, 0x44, 0x00, 0x10, 0x51, 0xC0,
+0x05, 0x40, 0x15, 0x01, 0x44, 0x04, 0x10, 0x11, 0x40, 0x07, 0x00, 0x1D, 0x21,
+0x74, 0x0C, 0xD0, 0x01, 0x44, 0xC0, 0x04, 0x59, 0x03, 0x74, 0x20, 0x00, 0xB5,
+0x40, 0x0C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x20, 0x30, 0x00,
+0x89, 0x40, 0x44, 0x03, 0x90, 0x2C, 0x41, 0x60, 0x00, 0xC9, 0x02, 0x34, 0x03,
+0x10, 0x1C, 0x40, 0xB7, 0x04, 0xC1, 0x01, 0x14, 0x03, 0x90, 0x2C, 0x40, 0x33,
+0x00, 0xC9, 0x02, 0x54, 0x27, 0x91, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x34,
+0x0B, 0xD0, 0x0C, 0x40, 0xF0, 0x40, 0x89, 0x03, 0x14, 0x0C, 0x10, 0x9C, 0x40,
+0x4C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x78, 0x00, 0xF1,
+0x01, 0x14, 0x07, 0x90, 0x1E, 0x40, 0x68, 0x00, 0x29, 0x11, 0xC4, 0x04, 0x10,
+0x92, 0x48, 0x4B, 0x00, 0x21, 0x03, 0x94, 0x04, 0x12, 0x12, 0x40, 0x4D, 0x20,
+0x29, 0x09, 0x95, 0x0C, 0x50, 0x12, 0x40, 0x4B, 0x20, 0x2C, 0x41, 0xB0, 0x04,
+0xD0, 0x13, 0x40, 0x48, 0x00, 0xA9, 0x29, 0xB4, 0x17, 0x10, 0x1F, 0x40, 0x3C,
+0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x18, 0x20, 0x00, 0x8B, 0x00,
+0x0C, 0x03, 0x30, 0x0C, 0xC0, 0x24, 0x00, 0xCB, 0x88, 0x34, 0x23, 0x31, 0x0C,
+0xC0, 0x37, 0x00, 0xD3, 0x80, 0x5C, 0x23, 0xB0, 0x8C, 0xC0, 0x33, 0x02, 0xCF,
+0x00, 0x1C, 0x23, 0x30, 0x0C, 0xC0, 0x33, 0x00, 0xCE, 0x00, 0x3C, 0x03, 0xF2,
+0x0C, 0xC4, 0x30, 0x00, 0x43, 0x30, 0x1C, 0x03, 0x30, 0x7C, 0xC0, 0x48, 0x40,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x3D, 0x00, 0xFF, 0x00, 0xDC,
+0x4B, 0x50, 0x0F, 0xC0, 0x2F, 0x02, 0x3F, 0x28, 0xFE, 0x00, 0xF2, 0x03, 0x48,
+0x0F, 0x00, 0x3F, 0x00, 0xEC, 0x80, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x37, 0x00,
+0xEC, 0x00, 0xB0, 0x83, 0xC0, 0x0F, 0x00, 0x3F, 0x40, 0xFC, 0x00, 0xF0, 0x02,
+0xC0, 0x4F, 0x40, 0x77, 0x00, 0x3C, 0x13, 0xF2, 0x8D, 0xC0, 0x0B, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x01, 0x9F, 0x00, 0x7C, 0x13,
+0xF0, 0x0D, 0xC0, 0x24, 0x00, 0xDD, 0x00, 0x7C, 0x03, 0xF0, 0x1C, 0xC0, 0x30,
+0x40, 0xD3, 0x00, 0x6F, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x4D,
+0x03, 0xF0, 0x1D, 0xD0, 0x34, 0x00, 0xDF, 0x21, 0x4D, 0x07, 0x24, 0x0D, 0xC0,
+0x33, 0x00, 0x53, 0x00, 0x4C, 0x07, 0x32, 0x15, 0xC0, 0x40, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x39, 0x22, 0xED, 0x00, 0xB4, 0x03, 0xD0,
+0x0F, 0x50, 0x28, 0x00, 0x2D, 0x00, 0xBC, 0x00, 0xD0, 0x02, 0x48, 0x09, 0x00,
+0x21, 0x00, 0x84, 0x00, 0xD2, 0x02, 0x40, 0x0B, 0x00, 0x3D, 0x00, 0x84, 0x00,
+0xD0, 0x03, 0x40, 0x08, 0x00, 0x3D, 0x00, 0xC4, 0x00, 0x10, 0x02, 0x44, 0x0B,
+0x00, 0xE1, 0x20, 0xAC, 0x03, 0xB0, 0x07, 0xC0, 0x4E, 0x68, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x69, 0x10, 0xED, 0x03, 0x94, 0x17, 0xD0, 0x1E,
+0x40, 0x68, 0x04, 0xED, 0x41, 0xB4, 0x07, 0x50, 0x1E, 0x44, 0x7C, 0x20, 0xF9,
+0x81, 0x84, 0x07, 0x50, 0x1E, 0x40, 0x7B, 0x00, 0xE5, 0x01, 0x84, 0x07, 0xD0,
+0x1E, 0x40, 0x79, 0x00, 0xED, 0x01, 0x84, 0x87, 0x18, 0x1E, 0x40, 0x7B, 0x40,
+0x71, 0x01, 0x04, 0x07, 0x10, 0x16, 0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x28, 0x33, 0x00, 0xCD, 0x01, 0x34, 0x03, 0xD0, 0x24, 0x4C,
+0x30, 0x10, 0x0D, 0x00, 0x12, 0x00, 0xD0, 0x00, 0x40, 0x01, 0x10, 0x09, 0xC0,
+0x04, 0x80, 0xD0, 0x00, 0x42, 0x03, 0x08, 0x1D, 0x00, 0x44, 0x00, 0xD0, 0x00,
+0x40, 0x01, 0x00, 0x0D, 0x00, 0x06, 0x00, 0x10, 0x00, 0x40, 0x03, 0x00, 0x51,
+0x03, 0x24, 0xCF, 0x12, 0x34, 0x40, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x17, 0xA0, 0x15, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xD0, 0x27, 0xC0, 0x54,
+0x00, 0x5F, 0x00, 0x74, 0x01, 0x70, 0x05, 0xC4, 0x14, 0x00, 0x4B, 0x00, 0x6C,
+0x01, 0xF0, 0x04, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x4C, 0x01, 0xF0, 0x05, 0xC0,
+0x15, 0x00, 0x5F, 0x00, 0x44, 0x01, 0x30, 0x05, 0xC0, 0x13, 0x00, 0x71, 0x07,
+0xCC, 0x11, 0x14, 0x17, 0x40, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x08, 0x04, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x21, 0xC1, 0x07, 0x00,
+0x3D, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x37, 0x02, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0E,
+0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x40, 0x1F, 0x06, 0x7C,
+0x00, 0xF0, 0xA1, 0xC9, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x21, 0x00, 0x93, 0x00, 0x3C, 0x02, 0xB0, 0x09, 0xC0, 0x24, 0x10, 0x9F,
+0x01, 0x4C, 0x02, 0xF0, 0x19, 0xC0, 0xE7, 0x00, 0x93, 0x00, 0x6C, 0x06, 0xF0,
+0x99, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x34, 0x59, 0xC0, 0x27, 0x00,
+0x9F, 0x05, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x40, 0x9B, 0x00, 0x6C, 0x02,
+0xF0, 0x49, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20,
+0x26, 0x40, 0x91, 0x80, 0x74, 0x42, 0x10, 0xA9, 0x41, 0x24, 0x00, 0x8D, 0x09,
+0x5E, 0x2A, 0xD0, 0x19, 0x40, 0x63, 0x40, 0x91, 0x02, 0x45, 0x1A, 0xD0, 0x69,
+0xC2, 0x26, 0x08, 0x9D, 0x02, 0x44, 0x42, 0x10, 0x39, 0x40, 0x27, 0x00, 0x9D,
+0x02, 0x74, 0x0A, 0xD0, 0x09, 0x48, 0x67, 0x04, 0x91, 0x82, 0x44, 0x86, 0xD0,
+0x69, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x64,
+0x00, 0x91, 0x00, 0x74, 0x02, 0x10, 0x08, 0x40, 0x24, 0x00, 0x9D, 0x00, 0xC4,
+0x42, 0xD0, 0x4B, 0x40, 0x2F, 0x00, 0xB9, 0x03, 0xC4, 0x12, 0xD0, 0x0B, 0x40,
+0x2C, 0x00, 0xBD, 0x00, 0xC4, 0x06, 0x92, 0x0B, 0x44, 0x2F, 0x00, 0xBD, 0xC0,
+0xF4, 0x02, 0xD0, 0x1B, 0x40, 0x2F, 0x41, 0x91, 0x08, 0x64, 0x22, 0xD0, 0x09,
+0x40, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2A, 0x20, 0x01,
+0x81, 0x04, 0x34, 0x12, 0x18, 0x08, 0x50, 0x20, 0x00, 0xBC, 0x00, 0x84, 0x02,
+0xD0, 0x0A, 0x40, 0x6F, 0x00, 0xB9, 0x00, 0x84, 0x02, 0xD0, 0x0A, 0x40, 0x2A,
+0x00, 0xAD, 0x01, 0x84, 0x02, 0x90, 0x1A, 0x40, 0x2B, 0x00, 0xAD, 0x41, 0xB4,
+0x06, 0xD0, 0x0A, 0x40, 0x2B, 0x00, 0x91, 0x00, 0x24, 0x02, 0xD0, 0x48, 0x40,
+0x53, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA0, 0x86, 0x02, 0x13,
+0x00, 0x7C, 0x28, 0x34, 0xA1, 0xC0, 0x84, 0x02, 0x1F, 0x0A, 0x44, 0x28, 0xF0,
+0x01, 0xC0, 0x87, 0x02, 0x1B, 0x0A, 0x4C, 0x28, 0xF0, 0x01, 0xC0, 0x85, 0x02,
+0x1F, 0x0A, 0x4C, 0x28, 0xB3, 0xA1, 0xC0, 0x87, 0x02, 0x1F, 0x0A, 0x7C, 0x28,
+0xF0, 0x01, 0xC0, 0x0F, 0x10, 0x53, 0x00, 0x6C, 0x51, 0xFA, 0xA1, 0xC0, 0x77,
+0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x88, 0x2F, 0x02, 0xBF, 0x08,
+0x7C, 0x22, 0x78, 0x0B, 0xC0, 0x2F, 0x20, 0x9E, 0x00, 0x5D, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x87, 0x00, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F,
+0x00, 0x7D, 0x02, 0x71, 0x09, 0xC0, 0x27, 0x08, 0x9F, 0x20, 0x7C, 0x82, 0xF0,
+0x09, 0xC2, 0x27, 0x00, 0xA7, 0x00, 0xDC, 0x02, 0xF0, 0x8B, 0xC0, 0x67, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x01, 0xB3, 0x14, 0xCC,
+0xB2, 0x30, 0x0F, 0xC0, 0x2D, 0x00, 0xBF, 0x08, 0xCC, 0x02, 0x10, 0x0B, 0xC0,
+0x2F, 0x02, 0xBF, 0x00, 0xCC, 0x02, 0x30, 0x0B, 0xC0, 0x24, 0x00, 0xB3, 0x00,
+0xFC, 0x22, 0xF0, 0x0B, 0xC0, 0x24, 0x00, 0xB3, 0x08, 0xDC, 0x02, 0x30, 0x0B,
+0xC0, 0x2F, 0x00, 0xB3, 0x00, 0xFC, 0x82, 0x30, 0x0B, 0xC0, 0x67, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x0D, 0x11, 0x00, 0x45, 0x30,
+0x10, 0x01, 0x43, 0x04, 0x04, 0x1D, 0x00, 0x04, 0x50, 0x10, 0x01, 0x40, 0x03,
+0x01, 0x1D, 0x10, 0x4C, 0x40, 0x14, 0x01, 0x50, 0x04, 0x05, 0x01, 0x04, 0x74,
+0x10, 0xD0, 0x00, 0x41, 0x00, 0x24, 0x01, 0x40, 0x5C, 0x50, 0x10, 0x01, 0x40,
+0x07, 0x00, 0x11, 0x00, 0x74, 0x00, 0x10, 0x81, 0x40, 0x73, 0x60, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x03, 0x91, 0x20, 0x04, 0x12, 0x90,
+0x49, 0x40, 0x21, 0x80, 0x8D, 0x00, 0x04, 0x12, 0x10, 0x0C, 0x40, 0x23, 0x01,
+0x8D, 0x04, 0x65, 0x02, 0x10, 0x09, 0x40, 0x24, 0x41, 0x81, 0x14, 0x34, 0x12,
+0xD8, 0x48, 0x50, 0x20, 0x00, 0x81, 0x00, 0x14, 0x12, 0x10, 0x08, 0x40, 0x23,
+0x00, 0x89, 0x00, 0x34, 0x02, 0x10, 0x08, 0x48, 0x4B, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x41, 0x91, 0x00, 0x44, 0x03, 0x90, 0x29,
+0x40, 0x24, 0x02, 0x8D, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x8D,
+0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x91, 0x00, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x24, 0x00, 0xD1, 0x00, 0x54, 0x02, 0x10, 0x09, 0x40, 0x37, 0x20,
+0x99, 0x00, 0x74, 0x0A, 0x12, 0x89, 0x40, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x00, 0x25, 0x00, 0x83, 0x89, 0x0C, 0x02, 0xB4, 0x18, 0xC0,
+0x65, 0x20, 0x9F, 0x00, 0x4D, 0x02, 0x34, 0x09, 0xC0, 0x27, 0x80, 0x9F, 0x00,
+0x6C, 0x02, 0x30, 0x08, 0xC0, 0x24, 0x00, 0x93, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x24, 0x40, 0x93, 0x00, 0x5C, 0x02, 0x34, 0x09, 0xC0, 0x27, 0x00, 0x99,
+0x12, 0x7C, 0x02, 0x34, 0x19, 0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x16, 0x08, 0x25, 0x00, 0x9F, 0x41, 0x7C, 0x02, 0x74, 0x29, 0xC0, 0x27,
+0x00, 0x9F, 0x50, 0x7C, 0x42, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x40, 0x97, 0x15,
+0x7E, 0x52, 0xF0, 0x09, 0xE0, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x08, 0x41, 0x40, 0x13, 0x00, 0x7C, 0x10, 0xF0, 0x41, 0xC0, 0x07, 0x00,
+0x1F, 0x08, 0x4C, 0x00, 0x34, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x7C, 0x00,
+0xF0, 0x11, 0xF0, 0x04, 0x00, 0x1F, 0x20, 0x4C, 0x04, 0xD0, 0x01, 0xC0, 0x06,
+0x40, 0x13, 0x40, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x02, 0x0C,
+0x08, 0x14, 0x01, 0xC4, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA0, 0x5C, 0x00, 0x51, 0x00, 0xF4, 0x09, 0xD0, 0x27, 0xC0, 0x15, 0x00, 0x7D,
+0x00, 0xC6, 0x05, 0x50, 0x05, 0x40, 0x5F, 0x04, 0x73, 0x02, 0xB4, 0x29, 0xD1,
+0x07, 0xC2, 0x12, 0x00, 0x7D, 0x45, 0xC4, 0x15, 0xD0, 0x07, 0xC0, 0x14, 0x00,
+0x71, 0x02, 0xCC, 0x01, 0xD0, 0x15, 0x40, 0x9B, 0x08, 0x71, 0x02, 0xD4, 0x0D,
+0x50, 0xF7, 0x40, 0x50, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0,
+0x32, 0x00, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x31, 0x20, 0xCD, 0x00,
+0x64, 0x0F, 0x50, 0x08, 0x44, 0x73, 0x00, 0xC1, 0x04, 0x24, 0x03, 0xD0, 0x04,
+0x40, 0x32, 0x10, 0xCD, 0x01, 0x05, 0x03, 0x50, 0x0D, 0x40, 0x34, 0x00, 0xC1,
+0x06, 0x65, 0x07, 0xD0, 0x98, 0x40, 0x63, 0x03, 0x41, 0x08, 0x04, 0x23, 0x10,
+0x0C, 0x40, 0x52, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x08,
+0x04, 0xE1, 0x00, 0xB4, 0x43, 0x90, 0x0E, 0x40, 0x39, 0x00, 0x7D, 0x00, 0xA5,
+0x0B, 0x50, 0x0E, 0x40, 0x7B, 0x00, 0xE1, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x41,
+0x38, 0x01, 0xED, 0x01, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x38, 0x0A, 0xE1, 0x83,
+0xA4, 0x43, 0xD0, 0x0E, 0x40, 0x1F, 0x00, 0x71, 0x01, 0x14, 0x03, 0x10, 0x12,
+0x58, 0x06, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x60, 0x00,
+0xE3, 0x01, 0xBC, 0x07, 0xD0, 0x1E, 0xC0, 0x79, 0x00, 0xEF, 0x01, 0xA4, 0x06,
+0x70, 0x1E, 0xC0, 0x6B, 0x40, 0xE3, 0x01, 0xB0, 0x05, 0xF0, 0x1E, 0x40, 0x7A,
+0x00, 0xEF, 0x01, 0x8C, 0x07, 0x70, 0x1E, 0xC0, 0x78, 0x05, 0xE3, 0x01, 0xAC,
+0x07, 0xF1, 0x1E, 0xC0, 0x6B, 0x00, 0x63, 0x81, 0x84, 0x07, 0x30, 0x18, 0xC0,
+0x46, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x05, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x35, 0x10, 0x0F, 0x00, 0x5C, 0x02, 0xB0,
+0x0D, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x7C, 0x80, 0xF0, 0x0C, 0xC0, 0x37, 0x04,
+0x5F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xD0, 0xB5, 0x00, 0x9F, 0x00, 0x5C, 0x01,
+0xF0, 0x0D, 0xC0, 0x33, 0x20, 0x4F, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x41,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x4D, 0x00, 0xE7, 0x21,
+0xCC, 0x07, 0xF8, 0x87, 0xC0, 0x7C, 0x02, 0xBF, 0x01, 0xCC, 0x07, 0x30, 0x1F,
+0xC0, 0x7C, 0x00, 0x73, 0x01, 0xEC, 0x05, 0x32, 0x1F, 0xC0, 0x7F, 0x04, 0xF3,
+0x01, 0xFC, 0x04, 0xB0, 0x1F, 0xC0, 0x7F, 0x10, 0xB3, 0x01, 0xCC, 0x07, 0xF0,
+0x1E, 0xC0, 0x3C, 0x00, 0xF3, 0x05, 0xCC, 0x06, 0xF0, 0x13, 0x84, 0x0B, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x8D, 0x10, 0xE1, 0x08, 0x84,
+0x21, 0x78, 0x0E, 0x44, 0x38, 0x00, 0x7D, 0x06, 0xC5, 0x03, 0x10, 0x0E, 0x40,
+0x28, 0x00, 0x71, 0x40, 0x84, 0xE0, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xA1, 0x10,
+0xB4, 0x01, 0x10, 0x0E, 0x40, 0x3B, 0x02, 0xBB, 0x18, 0x8C, 0x0A, 0xD0, 0x8E,
+0x40, 0x19, 0x02, 0xA1, 0x06, 0xAC, 0x03, 0xD0, 0x20, 0x40, 0x57, 0x60, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xE5, 0x00, 0x85, 0x01,
+0x50, 0x87, 0x40, 0x38, 0x8C, 0xAD, 0x00, 0x86, 0x01, 0x90, 0x0F, 0x40, 0x3A,
+0x40, 0xE1, 0x00, 0xC4, 0x01, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xE1, 0x00, 0xF4,
+0x0A, 0x10, 0x0E, 0x40, 0x3F, 0x00, 0x61, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40,
+0x29, 0x42, 0x61, 0x0C, 0x94, 0x43, 0xD0, 0x02, 0x40, 0x23, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x01, 0x00, 0xC1, 0x00, 0x04, 0x01, 0x50,
+0x31, 0x40, 0x70, 0x00, 0x1D, 0x41, 0x02, 0x45, 0x90, 0x3C, 0x50, 0x82, 0x04,
+0x01, 0x10, 0x04, 0x08, 0x10, 0x2C, 0x42, 0x77, 0x01, 0x01, 0x05, 0x30, 0x04,
+0x10, 0xD0, 0x40, 0xB3, 0x04, 0x09, 0x05, 0x06, 0x34, 0xD0, 0x1C, 0x40, 0x91,
+0x00, 0x81, 0x13, 0x34, 0x0E, 0xD0, 0x00, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x80, 0x05, 0x00, 0xD7, 0x00, 0x4C, 0x03, 0x70, 0xE9,
+0xC0, 0x74, 0x00, 0xDF, 0x05, 0x4C, 0x09, 0xB0, 0x0D, 0xC0, 0x16, 0x00, 0x93,
+0x01, 0x4C, 0x07, 0x34, 0x7C, 0x40, 0xBF, 0x00, 0x13, 0x03, 0x3C, 0x03, 0x10,
+0x21, 0xC0, 0x3B, 0x00, 0x53, 0x03, 0x4C, 0x08, 0xF0, 0x3D, 0xC0, 0xB5, 0x02,
+0x43, 0x11, 0x50, 0x0D, 0xF0, 0x09, 0x40, 0x77, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x00, 0x47, 0x00, 0x9F, 0x01, 0x7C, 0x83, 0x70, 0x09, 0xD2,
+0x27, 0x00, 0xDF, 0x04, 0x7C, 0x21, 0x70, 0x8D, 0xC0, 0xB5, 0x02, 0xDF, 0x08,
+0x7C, 0x8B, 0xF2, 0x0D, 0xC0, 0x37, 0x42, 0x9F, 0x00, 0x7C, 0x23, 0x70, 0x29,
+0xC0, 0x77, 0x00, 0x57, 0x02, 0x5C, 0x02, 0xF0, 0xCD, 0xC0, 0xF7, 0x40, 0x5F,
+0x40, 0x2C, 0x0B, 0xF2, 0x01, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x0B, 0x40, 0xE3, 0x00, 0xEC, 0x03, 0xF0, 0x8F, 0xC0, 0x3C,
+0x00, 0xFB, 0x00, 0xCC, 0x02, 0x30, 0x0F, 0xC1, 0x0F, 0x00, 0xBF, 0x09, 0xFC,
+0x40, 0xF0, 0x0F, 0xC1, 0x3C, 0x00, 0x33, 0x05, 0xFC, 0x03, 0xB0, 0x47, 0xC0,
+0x3D, 0x00, 0x73, 0x00, 0xCC, 0x20, 0x30, 0x9F, 0xC0, 0xFF, 0x00, 0xB3, 0x00,
+0xCC, 0x43, 0x32, 0x0B, 0xC4, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x81, 0x20, 0xC6, 0x00, 0x91, 0x00, 0x44, 0x0F, 0xF0, 0x11, 0x60, 0x61, 0x02,
+0x91, 0x02, 0x44, 0x02, 0x10, 0x0D, 0x40, 0x87, 0x04, 0x1D, 0x00, 0x5C, 0x1E,
+0xD1, 0x1D, 0x40, 0x34, 0x08, 0x11, 0x12, 0x74, 0x00, 0x10, 0x71, 0x40, 0x34,
+0x00, 0x11, 0x02, 0x4C, 0x0C, 0x10, 0x0D, 0x40, 0x33, 0x00, 0x11, 0x01, 0x44,
+0x2F, 0x15, 0x19, 0x40, 0x37, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0xA0, 0x46, 0x00, 0xD1, 0x04, 0x64, 0x04, 0xD0, 0x01, 0x40, 0x37, 0x20, 0x19,
+0x00, 0x04, 0x10, 0x10, 0x1D, 0x48, 0x17, 0x10, 0x1D, 0x00, 0x74, 0x05, 0x50,
+0x1D, 0x44, 0x34, 0x40, 0x51, 0x00, 0x74, 0x00, 0x10, 0x00, 0x40, 0x36, 0x00,
+0x81, 0x00, 0x04, 0x01, 0x10, 0x0D, 0x40, 0x37, 0x00, 0xD9, 0x01, 0x64, 0xC3,
+0x10, 0x19, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x00, 0x18, 0x81, 0x00, 0x04, 0x00, 0xD8, 0x08, 0x40, 0x26, 0x80, 0x41, 0x00,
+0x05, 0x04, 0x18, 0x0C, 0x40, 0x23, 0x00, 0x4D, 0x00, 0x34, 0x03, 0xD0, 0x1D,
+0x40, 0x30, 0x00, 0x81, 0x00, 0x74, 0x01, 0x18, 0x08, 0x50, 0x36, 0x00, 0x81,
+0x00, 0x04, 0x02, 0x14, 0x0C, 0x40, 0x37, 0x00, 0x89, 0x00, 0x04, 0x03, 0x10,
+0x00, 0x44, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x06,
+0x00, 0xD3, 0x00, 0x6C, 0x00, 0xF0, 0x05, 0x50, 0x37, 0x00, 0x1B, 0x00, 0x4C,
+0x00, 0x20, 0x0D, 0xC0, 0x13, 0x00, 0x9F, 0x00, 0x7C, 0x00, 0xF0, 0x0D, 0x50,
+0x38, 0x00, 0x53, 0x00, 0x7C, 0x02, 0x30, 0x05, 0xC0, 0x3F, 0x00, 0x53, 0x00,
+0x4C, 0x01, 0x30, 0x0D, 0xC0, 0x37, 0x10, 0x9B, 0x20, 0x6C, 0x81, 0x30, 0xA9,
+0xC0, 0x07, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0F, 0x00,
+0xBF, 0x00, 0xFC, 0x00, 0x70, 0x02, 0xC0, 0x2D, 0x00, 0x3F, 0x00, 0xFC, 0x00,
+0xF0, 0x0E, 0xC0, 0x0F, 0x00, 0x3F, 0x40, 0x9C, 0x02, 0xF0, 0x0B, 0xC0, 0x3F,
+0x00, 0x3F, 0x00, 0xBC, 0x00, 0x78, 0x03, 0xC0, 0x39, 0x00, 0x3E, 0x00, 0xDC,
+0x80, 0xF0, 0x0F, 0xC0, 0x3B, 0x00, 0xA7, 0x00, 0xFE, 0x03, 0xF0, 0x4B, 0xE0,
+0x17, 0x22, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0xDF, 0x00, 0xB3,
+0x08, 0xFC, 0x06, 0x70, 0x9F, 0xC8, 0x7E, 0x12, 0xF3, 0x09, 0xEC, 0x27, 0x11,
+0x1F, 0xC0, 0x7C, 0x00, 0xE3, 0x09, 0xDC, 0x27, 0xF0, 0x1F, 0xC0, 0x7C, 0x40,
+0xF3, 0x09, 0xBC, 0x0F, 0xF8, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0x09, 0x9C, 0x07,
+0xF0, 0x1F, 0xC0, 0x5C, 0x00, 0x33, 0x01, 0xCC, 0x06, 0xF0, 0x1B, 0xC8, 0x0D,
+0x08, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x27, 0x01, 0x91, 0x20,
+0x44, 0x53, 0x10, 0x01, 0x40, 0x06, 0x00, 0x15, 0x00, 0x50, 0x00, 0x50, 0x11,
+0x40, 0x44, 0x08, 0x15, 0x00, 0x04, 0x10, 0xD2, 0x01, 0x41, 0x45, 0x00, 0x11,
+0x80, 0x74, 0x00, 0xD0, 0x11, 0x42, 0x03, 0x25, 0x11, 0x04, 0x64, 0x04, 0xD1,
+0x1F, 0x48, 0x74, 0x40, 0x15, 0x81, 0x54, 0x02, 0xD2, 0x09, 0x42, 0x0F, 0x60,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x37, 0x00, 0xC1, 0x44, 0x14,
+0x13, 0x50, 0x4D, 0x48, 0x37, 0x11, 0xD1, 0x84, 0x46, 0x13, 0x10, 0x0C, 0x62,
+0x30, 0x20, 0xC5, 0x04, 0x14, 0x03, 0xD0, 0x4D, 0x40, 0x30, 0x00, 0xC9, 0x44,
+0x14, 0x13, 0xD0, 0x0C, 0x40, 0x36, 0x10, 0xD5, 0x00, 0x14, 0x03, 0x58, 0x0C,
+0x40, 0x21, 0x00, 0x15, 0x20, 0x14, 0x00, 0xD8, 0x00, 0x40, 0x4F, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x25, 0x10, 0xD1, 0x21, 0x64, 0x07,
+0x10, 0x01, 0x40, 0x07, 0x00, 0x15, 0x00, 0x54, 0x00, 0x50, 0x01, 0x70, 0x04,
+0x00, 0x15, 0x00, 0x54, 0x00, 0xD0, 0x01, 0x40, 0x05, 0x00, 0x19, 0x00, 0x74,
+0x00, 0xD0, 0x01, 0x42, 0x07, 0x00, 0x11, 0x00, 0x64, 0x00, 0xD0, 0x0D, 0x00,
+0x25, 0x00, 0x15, 0x01, 0x54, 0x44, 0xD0, 0x11, 0x41, 0x0F, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x13, 0x03, 0xD3, 0x31, 0x7C, 0x17, 0x70,
+0x0C, 0xC0, 0x37, 0x00, 0xD3, 0x00, 0x0C, 0x03, 0x30, 0x0D, 0xC0, 0x34, 0x30,
+0xD3, 0x00, 0x5C, 0x03, 0xF0, 0x0D, 0x02, 0x34, 0x00, 0xDB, 0x00, 0x7C, 0x03,
+0xD0, 0x0D, 0x40, 0x37, 0x20, 0xC7, 0x40, 0x5C, 0x03, 0xF0, 0x0D, 0xD0, 0x15,
+0x00, 0x06, 0x01, 0x5C, 0x0E, 0xF0, 0x39, 0xC0, 0x09, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0x80, 0x2D, 0x40, 0xDF, 0x00, 0xDC, 0x03, 0xF0, 0x03,
+0xC0, 0x0C, 0x00, 0x3F, 0x80, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x40, 0x3B,
+0x00, 0xEC, 0x00, 0xF0, 0x03, 0x08, 0x0F, 0x00, 0x37, 0x00, 0xFC, 0x00, 0xF0,
+0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xCC, 0x00, 0xD0, 0x0F, 0xC0, 0x3E, 0x81,
+0xBB, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x08, 0xB5, 0x00, 0xDF, 0x00, 0x4D, 0x03, 0x70, 0x8D, 0xC0,
+0x37, 0x01, 0xD3, 0x00, 0x7C, 0x03, 0x30, 0x8D, 0xC0, 0x37, 0x01, 0xD7, 0x00,
+0x4C, 0x03, 0x30, 0x0D, 0xC0, 0x37, 0x01, 0xDF, 0x00, 0x7C, 0x03, 0xB0, 0x0D,
+0xC2, 0x34, 0x00, 0xD7, 0x00, 0x6C, 0x13, 0xB0, 0x0C, 0xC0, 0x24, 0x01, 0x9F,
+0x00, 0x7C, 0x08, 0xF0, 0x21, 0x48, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x24, 0x00, 0xDD, 0x00, 0x44, 0x03, 0x10, 0x11, 0x40, 0x00,
+0x04, 0x0B, 0x00, 0x5C, 0x00, 0xB0, 0x00, 0x40, 0x83, 0x00, 0x1B, 0x00, 0x6E,
+0x00, 0x10, 0x00, 0x40, 0xC3, 0x00, 0x1D, 0x00, 0x5C, 0x00, 0x10, 0x01, 0xE8,
+0x03, 0x00, 0x11, 0x80, 0x44, 0x40, 0x10, 0x0D, 0xC0, 0x20, 0x01, 0x9D, 0x00,
+0x5C, 0x00, 0xD0, 0x11, 0x41, 0x4F, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x20, 0x22, 0x00, 0x9D, 0x00, 0x44, 0x03, 0x50, 0x0C, 0x40, 0xB1, 0x00,
+0xC5, 0x00, 0x14, 0x03, 0x10, 0x1C, 0x40, 0x33, 0x00, 0xD1, 0x00, 0x04, 0x03,
+0x10, 0x0C, 0x48, 0x73, 0x00, 0xC9, 0x00, 0x34, 0x83, 0x90, 0x0C, 0x40, 0x30,
+0x00, 0xC5, 0x00, 0x24, 0x07, 0x80, 0x0C, 0x40, 0xE3, 0x00, 0x4D, 0x05, 0x36,
+0x12, 0xD0, 0x48, 0x40, 0x4F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x08, 0x6A, 0x00, 0xED, 0x09, 0x86, 0x07, 0x10, 0x13, 0x60, 0x4C, 0x00, 0x2D,
+0x01, 0xD4, 0x04, 0x90, 0x12, 0x40, 0x4F, 0x00, 0x38, 0x01, 0xA4, 0x04, 0x1C,
+0x12, 0x40, 0x4B, 0x04, 0x2D, 0x01, 0xD4, 0x04, 0x00, 0x13, 0x40, 0x49, 0x00,
+0x21, 0x01, 0xC4, 0x04, 0x50, 0x1C, 0x40, 0x79, 0x00, 0xED, 0x11, 0x94, 0x07,
+0xD0, 0x9A, 0x40, 0x37, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10,
+0x32, 0x02, 0x0D, 0x08, 0x4C, 0x03, 0x50, 0x0C, 0x40, 0x31, 0x12, 0xD7, 0x00,
+0x1C, 0x03, 0x30, 0x0C, 0x40, 0x33, 0x00, 0xC7, 0x00, 0x04, 0x03, 0x30, 0x0C,
+0xC0, 0x33, 0x00, 0xCF, 0x08, 0x34, 0x13, 0xB0, 0x0D, 0x40, 0x30, 0x02, 0xD7,
+0x00, 0x2C, 0x03, 0xB0, 0x0C, 0xD0, 0x23, 0x02, 0xCF, 0x20, 0x3C, 0x42, 0xF0,
+0x8C, 0xC0, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x2D,
+0x00, 0x7F, 0x08, 0xF8, 0x03, 0xE0, 0x02, 0x80, 0x09, 0x00, 0x3B, 0x00, 0xA8,
+0x20, 0xF2, 0x81, 0xC0, 0x0B, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC8,
+0x07, 0x00, 0x3F, 0x28, 0x7C, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x40,
+0x54, 0x24, 0x20, 0x9D, 0xC0, 0x2C, 0x08, 0xFF, 0x00, 0xFC, 0x23, 0xF0, 0x8F,
+0xC2, 0x0B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x27, 0x00,
+0xDF, 0x00, 0x4C, 0x03, 0xF0, 0x1D, 0xC0, 0x35, 0x00, 0xDE, 0x00, 0x7C, 0x07,
+0x30, 0x1D, 0xC0, 0x34, 0x00, 0xDF, 0x00, 0x3C, 0x03, 0x30, 0x1D, 0xC0, 0x34,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x3C,
+0x03, 0xB0, 0x0D, 0xC4, 0x24, 0x00, 0x5F, 0x00, 0x7C, 0x83, 0x30, 0x0D, 0xC2,
+0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x29, 0x00, 0xFD,
+0x00, 0x84, 0x03, 0xD0, 0x03, 0x40, 0x08, 0x00, 0x2D, 0x00, 0xB4, 0x00, 0x50,
+0x02, 0x00, 0x08, 0x88, 0x2D, 0x00, 0xB4, 0x00, 0x50, 0x02, 0x40, 0x09, 0x00,
+0x2F, 0x00, 0xA4, 0x00, 0xD1, 0x02, 0x48, 0x0B, 0x00, 0x2D, 0x20, 0xB6, 0x00,
+0x18, 0x4E, 0x40, 0x38, 0x20, 0xED, 0x00, 0xF4, 0x01, 0x10, 0x07, 0x40, 0x4C,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0x6D, 0x00,
+0x84, 0x47, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x81, 0xF4, 0x07, 0x18, 0x1F,
+0x48, 0x78, 0x80, 0xED, 0x01, 0xF6, 0x07, 0x13, 0x1F, 0x44, 0x7B, 0x80, 0xED,
+0x01, 0xB4, 0x87, 0x58, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01, 0xF4, 0x07, 0xD8,
+0xDE, 0x40, 0x6A, 0x00, 0xED, 0x01, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x10, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x20, 0x23, 0x00, 0x4C, 0x00, 0x04,
+0x05, 0xD0, 0x00, 0x40, 0x00, 0x00, 0x0D, 0x00, 0x34, 0x00, 0x50, 0x00, 0x40,
+0x00, 0xA0, 0x0D, 0x00, 0x74, 0x00, 0x50, 0x00, 0x40, 0x03, 0x10, 0x05, 0x00,
+0x34, 0x00, 0xD0, 0x00, 0x40, 0x03, 0x00, 0x0D, 0x20, 0x34, 0x00, 0x51, 0x0C,
+0x50, 0x22, 0x00, 0x8D, 0x0F, 0x74, 0x0F, 0x1A, 0x6D, 0x40, 0x58, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x1F, 0x00, 0x7F, 0x10, 0xCC, 0x0D,
+0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0x30, 0x05, 0xD0, 0x14,
+0x00, 0x5F, 0x00, 0x7C, 0x01, 0x30, 0x05, 0xC0, 0x17, 0x00, 0x5D, 0x00, 0x7C,
+0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x3C, 0x01, 0xF0, 0x04, 0xC0,
+0x1A, 0x00, 0x7F, 0x00, 0xFC, 0x0D, 0x34, 0x07, 0xD0, 0x5C, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x00, 0x1F, 0x20, 0x7C, 0x40, 0xF2,
+0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x20, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x8F, 0x00,
+0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0D, 0x00, 0x3D, 0x00, 0xE4, 0x00,
+0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x20, 0xFC, 0x08, 0x90, 0x01, 0xC0, 0x05,
+0x00, 0x1F, 0x00, 0x7C, 0x28, 0xF0, 0x81, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x65, 0x00, 0x9F, 0x40, 0x7C, 0x02, 0xF0, 0x19,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x5C, 0x82, 0xF0, 0x09, 0xC0, 0x27, 0x02, 0x9F,
+0x00, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0xE7, 0x80, 0x9F, 0x00, 0x4D, 0x02, 0x34,
+0x09, 0xC0, 0x27, 0x00, 0x9B, 0x00, 0x7C, 0x06, 0x72, 0x09, 0xC0, 0x24, 0x00,
+0x93, 0x05, 0x7C, 0x42, 0x30, 0x09, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x28, 0x66, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x19, 0x40,
+0x27, 0x00, 0x8D, 0x00, 0x44, 0x02, 0xD8, 0x19, 0x40, 0xE7, 0x20, 0x9D, 0x00,
+0x74, 0x02, 0x10, 0x09, 0x40, 0x27, 0x04, 0x97, 0x20, 0x44, 0x02, 0x30, 0x09,
+0x40, 0x23, 0x00, 0x91, 0x20, 0x70, 0x16, 0x30, 0x0B, 0xD0, 0x24, 0x00, 0x91,
+0x00, 0x74, 0x96, 0x50, 0x39, 0x40, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1C, 0xA0, 0x24, 0x02, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x89, 0x40, 0x6F,
+0x00, 0xBD, 0x00, 0xD4, 0x02, 0xD0, 0xAB, 0x40, 0x2F, 0x00, 0xBD, 0x00, 0xF4,
+0x02, 0x10, 0x0B, 0x60, 0x2F, 0x00, 0xAD, 0x00, 0x84, 0x02, 0x10, 0x0B, 0x40,
+0x2F, 0x80, 0xB9, 0x00, 0xF4, 0x12, 0x10, 0x69, 0x60, 0x36, 0x00, 0xD9, 0x02,
+0x74, 0x06, 0x10, 0x19, 0x41, 0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x28, 0xA0, 0x00, 0x8D, 0x1C, 0x34, 0x22, 0xD0, 0x2A, 0x40, 0xEB, 0x00,
+0xBD, 0x08, 0x84, 0x22, 0xD0, 0x0A, 0x40, 0x2B, 0x00, 0xAD, 0x00, 0xB0, 0x22,
+0x10, 0x8A, 0x40, 0x2B, 0x00, 0xA5, 0x88, 0x84, 0x22, 0x10, 0x0A, 0x40, 0x2F,
+0x02, 0xA1, 0x08, 0xB4, 0x02, 0x14, 0x08, 0x64, 0x24, 0x08, 0x89, 0x00, 0x34,
+0x02, 0x50, 0x09, 0x40, 0x50, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB0, 0x06, 0x00, 0x1F, 0x06, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F,
+0x02, 0x5C, 0x08, 0xD0, 0x01, 0xC0, 0x17, 0x00, 0x1D, 0x8A, 0x7C, 0x08, 0x34,
+0x21, 0xC0, 0x07, 0x00, 0x1D, 0x02, 0x44, 0x08, 0x30, 0x01, 0xC0, 0x87, 0x00,
+0x1B, 0x02, 0xFC, 0x00, 0x70, 0x11, 0xC0, 0x06, 0x40, 0x1B, 0x00, 0x7C, 0x28,
+0x32, 0xA1, 0xD0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0,
+0x6F, 0x00, 0xBF, 0x04, 0xFC, 0x12, 0xF0, 0x19, 0x40, 0x67, 0x00, 0x9F, 0x44,
+0x3C, 0x12, 0xF2, 0x08, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x7C, 0x12, 0xF0, 0x48,
+0xC0, 0x27, 0x00, 0x97, 0x84, 0x7C, 0x12, 0x70, 0x09, 0xC2, 0x27, 0x01, 0x9F,
+0x84, 0x7C, 0x02, 0x70, 0x28, 0xC0, 0x2D, 0x00, 0xB7, 0x00, 0xFC, 0x02, 0xF0,
+0x0B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F,
+0x00, 0x93, 0x2C, 0x7C, 0x02, 0xF0, 0x0B, 0xC0, 0xAB, 0x00, 0x97, 0x00, 0x7C,
+0x02, 0xF0, 0x0B, 0xC0, 0x28, 0x00, 0x9F, 0x00, 0x7C, 0x22, 0xF0, 0x09, 0xC8,
+0x2D, 0x00, 0x93, 0x08, 0x5C, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x02, 0x9F, 0x00,
+0xDC, 0x02, 0xB0, 0x1B, 0xC3, 0x2B, 0x00, 0xBF, 0x60, 0xFC, 0x82, 0x30, 0x0B,
+0xC0, 0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18, 0x54, 0x45,
+0x51, 0x4C, 0x74, 0x40, 0xD0, 0x51, 0x41, 0x47, 0x01, 0x11, 0x14, 0x74, 0x10,
+0xD0, 0x01, 0x40, 0x04, 0x08, 0x1D, 0x05, 0x74, 0x80, 0xD2, 0x41, 0x41, 0x04,
+0x00, 0x11, 0x04, 0x4C, 0x40, 0x10, 0x01, 0xC0, 0x05, 0x00, 0x1D, 0x14, 0x74,
+0x00, 0x10, 0x21, 0x42, 0x07, 0x08, 0x5D, 0x00, 0x74, 0x00, 0x50, 0x05, 0x40,
+0x73, 0x40, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x21, 0x00, 0x81,
+0x04, 0x34, 0x12, 0xD0, 0x08, 0x40, 0x23, 0x01, 0x85, 0x04, 0x34, 0x52, 0xD0,
+0x09, 0x62, 0x21, 0x00, 0x8D, 0x10, 0x34, 0x02, 0xD0, 0x48, 0x40, 0x25, 0x00,
+0x91, 0x04, 0x54, 0x12, 0x50, 0x08, 0x48, 0x23, 0x80, 0x8D, 0x04, 0x14, 0x02,
+0xD2, 0x08, 0x48, 0x23, 0x20, 0x8D, 0x20, 0x74, 0x02, 0x18, 0x08, 0x40, 0x4B,
+0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x25, 0x00, 0x91, 0x00,
+0x74, 0x0A, 0xD0, 0x09, 0x40, 0x23, 0x00, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x09,
+0x00, 0x25, 0x80, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00, 0x91,
+0x00, 0x54, 0x02, 0x10, 0x09, 0x40, 0x25, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10,
+0x0D, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x76, 0x02, 0x50, 0x09, 0x40, 0x63, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x6F, 0x00, 0x93, 0x02, 0x78,
+0x02, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0x97, 0x00, 0x7C, 0x02, 0xF0, 0x08, 0xC0,
+0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0x48, 0x21, 0x40, 0x81, 0x00,
+0x54, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x1C, 0x02, 0xB0, 0x09,
+0xC0, 0xE7, 0x81, 0x9F, 0x02, 0x78, 0x42, 0x32, 0x29, 0xC0, 0x17, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xA5, 0x00, 0x9F, 0x04, 0x7C, 0x26,
+0xF1, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xD0, 0x26,
+0x20, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0x27, 0x08, 0x9F, 0x00, 0x4C,
+0x02, 0xF0, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x80, 0x7C, 0x02, 0xBC, 0x09, 0xC0,
+0x67, 0x01, 0x9F, 0x09, 0x7C, 0x02, 0xF1, 0x49, 0xC0, 0x4B, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x05, 0x00, 0x1F, 0x02, 0x4D, 0x00, 0xF0,
+0x01, 0xC0, 0x06, 0x00, 0x13, 0x00, 0x7E, 0x00, 0x70, 0x01, 0xC0, 0x04, 0x00,
+0x17, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xE2, 0x07, 0x08, 0x1B, 0x00, 0x4C, 0x00,
+0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x40, 0xF0, 0x41, 0xC8, 0x87,
+0x40, 0x17, 0x00, 0x7C, 0x00, 0x34, 0x01, 0x87, 0x40, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x80, 0x54, 0x80, 0x5D, 0x00, 0x44, 0x01, 0x70, 0x45,
+0x40, 0x1C, 0x00, 0x5B, 0x00, 0x74, 0x01, 0x70, 0x07, 0x60, 0x9C, 0x00, 0x51,
+0x00, 0x74, 0x01, 0xD8, 0x05, 0xC0, 0x1F, 0x00, 0x55, 0x00, 0x1E, 0x01, 0x72,
+0x05, 0x40, 0x17, 0x08, 0x53, 0x00, 0xCC, 0x0D, 0xC0, 0x07, 0xC0, 0xDD, 0x01,
+0x70, 0x0A, 0xF0, 0x35, 0x10, 0x17, 0x50, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0xA0, 0x36, 0x10, 0xCD, 0x00, 0x16, 0x03, 0x50, 0x0C, 0x40,
+0x62, 0x00, 0xC1, 0x00, 0x34, 0x03, 0x58, 0x98, 0x48, 0xF3, 0x06, 0xCD, 0x00,
+0x34, 0x03, 0xD2, 0x0D, 0x40, 0xB3, 0x01, 0xC1, 0x00, 0x04, 0x03, 0x50, 0x0C,
+0x40, 0x33, 0x80, 0xC9, 0x00, 0x14, 0x0A, 0x90, 0x34, 0x40, 0xE3, 0x01, 0x81,
+0x02, 0x74, 0x03, 0x90, 0x0C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x88, 0xB8, 0x11, 0xED, 0xA5, 0x96, 0x13, 0x50, 0x5E, 0x40, 0x9C,
+0x01, 0xE9, 0x08, 0xB4, 0x03, 0x50, 0x0B, 0x40, 0x5F, 0x00, 0xE9, 0x04, 0xB4,
+0x13, 0xD8, 0x0E, 0x40, 0x3D, 0x00, 0xF5, 0x00, 0x96, 0x13, 0x50, 0x0E, 0x40,
+0x7F, 0x03, 0xE1, 0x05, 0x90, 0x0B, 0xD0, 0x26, 0x60, 0x6D, 0x00, 0xE1, 0x82,
+0xB4, 0x02, 0x90, 0x1E, 0x41, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0x10, 0xF8, 0x00, 0xFD, 0x07, 0x9C, 0x17, 0x70, 0x1F, 0xC0, 0xFA, 0x01,
+0xE3, 0x01, 0xB4, 0x17, 0x70, 0x1E, 0x50, 0x6B, 0x00, 0xED, 0x05, 0xBC, 0x47,
+0xD0, 0x9E, 0x68, 0x7B, 0x08, 0xEB, 0x01, 0x84, 0x17, 0x70, 0x1E, 0xC0, 0x7B,
+0x00, 0xFB, 0x09, 0x9C, 0x07, 0xF0, 0x1E, 0x80, 0x6B, 0x00, 0xE6, 0x21, 0xFC,
+0x06, 0xB0, 0x1B, 0xC0, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA8, 0x35, 0x00, 0xDF, 0x00, 0x6C, 0x03, 0x70, 0x89, 0xC0, 0x17, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x0C, 0xC0, 0x24, 0x18, 0xD7, 0x00, 0x7C, 0xB3, 0xF0,
+0x4D, 0xC2, 0x23, 0x00, 0xC7, 0x92, 0x7C, 0x4B, 0x70, 0x0D, 0xC0, 0xB3, 0x04,
+0xDB, 0x08, 0x6C, 0x03, 0xF0, 0x0D, 0x80, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x02,
+0x70, 0x01, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+0x79, 0x00, 0xE3, 0x04, 0xCD, 0x53, 0x70, 0x1B, 0xC0, 0x7F, 0x40, 0xF2, 0x01,
+0xDC, 0x67, 0xF0, 0x1B, 0xC0, 0x6F, 0x00, 0xEF, 0x19, 0xCC, 0x07, 0x30, 0x1F,
+0x85, 0x7F, 0x00, 0xF3, 0x11, 0xFC, 0x67, 0x70, 0x1F, 0xC0, 0x7D, 0x00, 0xF7,
+0x01, 0xCD, 0x07, 0xF0, 0x17, 0xC0, 0x7F, 0x00, 0xFF, 0xC1, 0xF4, 0x07, 0xF2,
+0x1B, 0xC4, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x39,
+0x00, 0xE1, 0x00, 0xAC, 0x03, 0x10, 0x0A, 0x40, 0x1B, 0x00, 0xE1, 0x08, 0xDC,
+0xC3, 0x11, 0x0A, 0xC0, 0x09, 0x09, 0xED, 0x00, 0x94, 0x23, 0x50, 0x0E, 0x42,
+0x1B, 0x00, 0xE1, 0x04, 0xDC, 0x03, 0x10, 0x8E, 0x40, 0x38, 0x00, 0xED, 0x00,
+0x84, 0x2B, 0xD0, 0x86, 0x40, 0x2B, 0x06, 0x6D, 0x08, 0xB4, 0x11, 0xD0, 0x4F,
+0xC0, 0x56, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00,
+0xF1, 0x00, 0xC4, 0x23, 0x50, 0x8E, 0x41, 0x3B, 0x00, 0xE1, 0x00, 0xB4, 0x03,
+0x59, 0x8A, 0x41, 0x2A, 0x30, 0xFD, 0x10, 0xE6, 0x03, 0x90, 0x0E, 0x40, 0x3F,
+0x06, 0xE1, 0x20, 0xA6, 0x03, 0x51, 0x0F, 0x40, 0x39, 0x02, 0xED, 0x00, 0xA4,
+0x43, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x02, 0xD2, 0x0A, 0x40,
+0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x25, 0x02, 0xC1,
+0x09, 0x24, 0x07, 0x10, 0x08, 0x60, 0x53, 0x0E, 0xC1, 0x0A, 0x34, 0x07, 0x12,
+0x08, 0x41, 0xA3, 0x20, 0xCD, 0x02, 0x34, 0x1F, 0x50, 0x3C, 0x40, 0x43, 0x00,
+0xD1, 0x0B, 0x14, 0x37, 0x10, 0x3C, 0x40, 0x74, 0x00, 0xCD, 0x05, 0x24, 0x17,
+0xD1, 0x0C, 0x40, 0x23, 0x00, 0x4D, 0x26, 0x34, 0x18, 0xD0, 0x00, 0x42, 0x12,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x25, 0x40, 0xF3, 0x00,
+0xCD, 0x1B, 0x70, 0x2D, 0xC0, 0xB3, 0x00, 0xF3, 0x8A, 0xFC, 0x0B, 0x70, 0x18,
+0xC0, 0x26, 0x04, 0xFE, 0x01, 0xEC, 0x4F, 0xB0, 0x5F, 0xC0, 0x27, 0x40, 0xF3,
+0x00, 0xFC, 0x0B, 0x70, 0x9C, 0xC0, 0xBD, 0x02, 0xE7, 0x06, 0x6C, 0x0F, 0xD0,
+0x05, 0xC0, 0xE7, 0x00, 0x8D, 0x06, 0x7E, 0x00, 0xF0, 0x01, 0xD0, 0x56, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x04, 0xDF, 0x00, 0x7C,
+0x43, 0xF0, 0x0D, 0xC0, 0xB7, 0x00, 0xDF, 0x00, 0x5C, 0x03, 0x70, 0x29, 0xC0,
+0x05, 0x00, 0xDF, 0x00, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0xA7, 0x88, 0xDF, 0x00,
+0x7C, 0x03, 0x72, 0x8D, 0xC0, 0x37, 0x82, 0xDF, 0x00, 0x5C, 0x0B, 0xB0, 0x25,
+0x88, 0xA7, 0x09, 0x9F, 0x02, 0x7C, 0x0C, 0xF0, 0x01, 0xC1, 0x05, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x3F, 0x00, 0xFB, 0x00, 0xFC, 0x03,
+0xF0, 0x0F, 0xC1, 0x5F, 0x08, 0xF3, 0x00, 0xFC, 0x43, 0xF0, 0x03, 0xC2, 0x2C,
+0x0C, 0xFF, 0x10, 0xF8, 0x83, 0xF0, 0x0F, 0xC1, 0x0D, 0x04, 0xFB, 0x90, 0xCC,
+0x03, 0xF1, 0x0F, 0xC0, 0x3F, 0x00, 0xF7, 0x40, 0xE8, 0x03, 0xD0, 0x27, 0xC0,
+0x6F, 0x00, 0x33, 0x00, 0xCC, 0x02, 0xF0, 0x03, 0xC0, 0x13, 0x22, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x85, 0x20, 0x36, 0x08, 0xD1, 0x00, 0x74, 0x83, 0xD0,
+0x09, 0x60, 0x16, 0x0A, 0xD1, 0x00, 0x74, 0x03, 0xD2, 0x15, 0x40, 0x64, 0x00,
+0xDD, 0x00, 0x5C, 0x03, 0xD0, 0x0D, 0x40, 0xC4, 0x04, 0xDD, 0x00, 0x44, 0x03,
+0xD8, 0x0D, 0x40, 0x34, 0x00, 0xD1, 0x00, 0x44, 0x07, 0xC0, 0x25, 0x42, 0xE3,
+0xC0, 0x13, 0x05, 0x44, 0x4E, 0xD0, 0x31, 0x40, 0x17, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xA2, 0x64, 0x20, 0xD9, 0x00, 0x74, 0x03, 0xD0, 0x09,
+0x48, 0x37, 0x04, 0xD1, 0x00, 0x74, 0x03, 0x50, 0x19, 0x41, 0x45, 0x20, 0xDD,
+0x00, 0x74, 0x03, 0x50, 0x0C, 0x40, 0x67, 0x00, 0xDD, 0x00, 0x64, 0x03, 0xD0,
+0x0D, 0x40, 0x36, 0x00, 0xD5, 0x00, 0x76, 0x07, 0xD0, 0x05, 0x40, 0xB7, 0x01,
+0x91, 0x01, 0x44, 0x04, 0xD2, 0x39, 0x42, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x28, 0x20, 0x00, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x08, 0x40,
+0x33, 0x08, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x09, 0x40, 0x40, 0x00, 0xCD, 0x00,
+0x14, 0x03, 0xD0, 0x0C, 0x40, 0x00, 0x00, 0xCD, 0x00, 0x24, 0x03, 0xD0, 0x0D,
+0x40, 0x30, 0x00, 0xD1, 0x00, 0x16, 0x83, 0xD0, 0x04, 0x40, 0x13, 0x10, 0x01,
+0x00, 0x05, 0x00, 0xD0, 0x08, 0x60, 0x43, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xB0, 0x26, 0x00, 0xDB, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0x48, 0x13,
+0x40, 0xD3, 0x80, 0x7C, 0x03, 0xF1, 0x01, 0xD0, 0x04, 0x00, 0xDE, 0x00, 0xFC,
+0x03, 0x72, 0x0F, 0xC4, 0x05, 0x00, 0xFF, 0x00, 0xEC, 0x03, 0xD0, 0x0D, 0xC0,
+0x3E, 0x00, 0xE7, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC4, 0x37, 0x88, 0x11, 0x00,
+0x4C, 0x82, 0xF0, 0x09, 0xC0, 0x01, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xA8, 0x2F, 0x10, 0xFF, 0x00, 0xBC, 0x03, 0xF0, 0x0B, 0xC0, 0x1E, 0x00,
+0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x07, 0xC0, 0x0E, 0x00, 0xFF, 0x00, 0x9C, 0x03,
+0xF0, 0x0F, 0xC8, 0x0B, 0x00, 0xFF, 0x00, 0xDC, 0x03, 0xF0, 0x0E, 0x40, 0x3F,
+0x00, 0xFF, 0x00, 0xEC, 0x01, 0xF0, 0x0B, 0xC2, 0x1F, 0x08, 0x37, 0x00, 0xFC,
+0x00, 0xE1, 0x03, 0xC0, 0x17, 0x22, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA0, 0x2F, 0x00, 0x3B, 0x14, 0xBC, 0x0F, 0x34, 0x1F, 0xC0, 0x7E, 0x02, 0xFF,
+0x09, 0xFC, 0x07, 0xB0, 0x1F, 0xC0, 0x7C, 0x00, 0xF3, 0x09, 0x8C, 0x27, 0x72,
+0x1F, 0xC4, 0x7E, 0x02, 0xFB, 0x29, 0xCC, 0x07, 0xF0, 0x1F, 0xC0, 0x7C, 0x20,
+0xF3, 0x09, 0xCC, 0x27, 0x30, 0x83, 0xC2, 0x7C, 0x02, 0xF3, 0x24, 0xEE, 0x1A,
+0x30, 0x4B, 0xC4, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+0x27, 0x20, 0x01, 0x02, 0x74, 0x13, 0x18, 0x11, 0x40, 0x00, 0x00, 0x1D, 0x80,
+0x74, 0x04, 0x40, 0x11, 0x40, 0x00, 0x04, 0x11, 0x00, 0x44, 0x10, 0x10, 0x40,
+0x40, 0x00, 0x00, 0x11, 0x04, 0x44, 0x04, 0xD0, 0x11, 0x41, 0x44, 0x00, 0x13,
+0x44, 0x44, 0x10, 0x30, 0x65, 0x40, 0x34, 0x00, 0xF5, 0x0B, 0x6E, 0x10, 0x10,
+0x11, 0x40, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x02,
+0x40, 0x01, 0x40, 0x36, 0x03, 0x50, 0x0D, 0x50, 0x30, 0x01, 0xCD, 0x84, 0x34,
+0x03, 0x81, 0x0D, 0x50, 0x30, 0x01, 0xC1, 0x00, 0x24, 0x13, 0xD0, 0x0C, 0x41,
+0x30, 0x01, 0xC1, 0x04, 0x24, 0x03, 0xD0, 0x4D, 0x40, 0x34, 0x00, 0xC9, 0x04,
+0x24, 0x03, 0x10, 0x28, 0x40, 0x31, 0x81, 0xCD, 0x20, 0x04, 0x1A, 0x11, 0x88,
+0x40, 0x45, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x15, 0x00,
+0x11, 0x22, 0x34, 0x03, 0x50, 0x01, 0x44, 0x04, 0x00, 0x1D, 0x00, 0x74, 0x80,
+0x90, 0x01, 0x40, 0x04, 0x00, 0x01, 0x00, 0x24, 0x00, 0x90, 0x01, 0x40, 0x04,
+0x00, 0x01, 0x00, 0x67, 0x00, 0xD0, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x64,
+0x00, 0x10, 0x4D, 0x42, 0x36, 0x08, 0xDD, 0x00, 0x47, 0x04, 0x10, 0x19, 0x41,
+0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x67, 0x40, 0x1B,
+0x01, 0x7C, 0x27, 0x50, 0x0C, 0xC8, 0x34, 0x20, 0xDF, 0x80, 0x3C, 0x03, 0xB4,
+0x0C, 0xC0, 0x34, 0x00, 0xD3, 0x00, 0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00,
+0xD3, 0x00, 0x6C, 0x03, 0xF2, 0x0C, 0x80, 0x30, 0x00, 0xDB, 0x00, 0x6D, 0x03,
+0x34, 0x01, 0xD1, 0x35, 0x00, 0xDF, 0x40, 0x44, 0x04, 0x22, 0x31, 0xC0, 0x01,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x69, 0x01, 0x3F, 0x03,
+0xF8, 0x03, 0xB0, 0x03, 0x80, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0x70, 0x03,
+0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xDD, 0x00, 0x70, 0x03, 0xD0, 0x0D, 0x00, 0x37,
+0x00, 0xDC, 0x00, 0xF0, 0x03, 0xC4, 0x0F, 0x00, 0x3F, 0x00, 0xDC, 0x00, 0xF1,
+0x07, 0xC0, 0x3D, 0x20, 0xF7, 0x00, 0xF4, 0x00, 0xF5, 0x03, 0xC3, 0x1E, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x81, 0x37, 0x0A, 0x4D,
+0x03, 0x30, 0x0D, 0xC0, 0x77, 0x41, 0xD3, 0x05, 0x5C, 0x03, 0x30, 0x8D, 0xC0,
+0x35, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x01,
+0x4C, 0x03, 0x70, 0x0D, 0xC0, 0x34, 0x02, 0xD7, 0x01, 0x7C, 0x03, 0xF0, 0x09,
+0xC0, 0x37, 0x00, 0xDF, 0x10, 0x74, 0x8A, 0x33, 0x21, 0xC4, 0x0B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xB4, 0x00, 0x11, 0x81, 0x44, 0x03,
+0x10, 0x41, 0x44, 0x47, 0x00, 0x11, 0x03, 0x74, 0x00, 0xB0, 0x11, 0x40, 0x04,
+0x00, 0x11, 0x20, 0x74, 0x00, 0x14, 0x01, 0x48, 0x04, 0x00, 0x10, 0x01, 0x44,
+0x44, 0xD0, 0x11, 0x40, 0x44, 0x08, 0x11, 0x01, 0x64, 0x00, 0xD0, 0x0D, 0xC0,
+0x37, 0x10, 0xE0, 0x13, 0x34, 0x04, 0x10, 0x30, 0x00, 0x4F, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x22, 0x00, 0x41, 0x00, 0x25, 0x03, 0x50,
+0x1C, 0x40, 0xB3, 0x00, 0xC9, 0x02, 0x34, 0x43, 0x90, 0x0C, 0x41, 0x35, 0x80,
+0xC1, 0x00, 0x34, 0x03, 0x10, 0x0D, 0x40, 0x36, 0x00, 0xC1, 0x00, 0x34, 0x07,
+0x50, 0x8C, 0x40, 0x71, 0x80, 0xC9, 0x00, 0x74, 0x03, 0xD0, 0x01, 0x40, 0x36,
+0x08, 0xC4, 0x02, 0x34, 0x02, 0x54, 0x28, 0x02, 0x1F, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x80, 0x78, 0x40, 0x61, 0x09, 0xE4, 0x07, 0x10, 0x12,
+0x40, 0x4B, 0x00, 0x29, 0x09, 0xB4, 0x24, 0x90, 0x92, 0x40, 0x48, 0x00, 0x21,
+0x01, 0xF6, 0x24, 0x10, 0x12, 0x40, 0x4A, 0x00, 0x21, 0x01, 0xB4, 0x04, 0xD0,
+0x13, 0x40, 0x4D, 0x08, 0x29, 0x09, 0xA6, 0x04, 0xC0, 0x12, 0x40, 0x7B, 0x30,
+0xE9, 0x01, 0xB4, 0x66, 0x50, 0x12, 0x41, 0x1B, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x10, 0x04, 0x40, 0x45, 0x00, 0x2C, 0x03, 0x70, 0x8C, 0xC0,
+0x33, 0x00, 0xCB, 0x00, 0x1C, 0x23, 0x30, 0x0C, 0xC0, 0x31, 0x90, 0xC3, 0x00,
+0x3C, 0x03, 0x30, 0x0C, 0xC0, 0x32, 0x00, 0xD3, 0x00, 0x34, 0x03, 0x70, 0x0C,
+0xC0, 0x31, 0x00, 0xCE, 0x80, 0x3E, 0x03, 0xF0, 0x00, 0xC0, 0x37, 0x00, 0xC7,
+0x08, 0x3C, 0x22, 0x70, 0x08, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xB0, 0x1D, 0x00, 0x7F, 0x00, 0xDE, 0x03, 0xF0, 0x03, 0x60, 0x0F,
+0x00, 0x37, 0x00, 0xBC, 0x20, 0xF0, 0x02, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xF4,
+0x00, 0xF0, 0x03, 0xC0, 0x0D, 0x00, 0x3F, 0x00, 0xCD, 0x00, 0xF0, 0x02, 0xC0,
+0x0A, 0x00, 0x37, 0x80, 0xEE, 0x04, 0xF0, 0x03, 0xC0, 0x3D, 0x82, 0xF7, 0x38,
+0xBC, 0x22, 0xB0, 0x89, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0x37, 0x40, 0x13, 0x00, 0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x40,
+0xD3, 0x01, 0x0D, 0x03, 0xB0, 0x1C, 0xD0, 0x34, 0x00, 0xDF, 0x00, 0x3C, 0x07,
+0xB4, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x01, 0x0D, 0x07, 0x30, 0x0D, 0xC0, 0x37,
+0x00, 0xDF, 0x01, 0x6D, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x80, 0xDF, 0x04, 0x3C,
+0x00, 0x30, 0x19, 0xC0, 0x54, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x88, 0x39, 0x00, 0x31, 0x00, 0x85, 0x03, 0xD0, 0x02, 0x40, 0x0F, 0x00, 0x31,
+0x00, 0x84, 0x00, 0x30, 0x02, 0x40, 0x08, 0x00, 0x2D, 0x00, 0xB4, 0x00, 0x10,
+0x02, 0x40, 0x0B, 0x00, 0x3D, 0x00, 0xA4, 0x00, 0x70, 0x02, 0x40, 0x0B, 0x00,
+0x37, 0x00, 0x8C, 0x80, 0xD0, 0x0E, 0xC0, 0x39, 0x00, 0xED, 0x14, 0x9C, 0x00,
+0x14, 0x03, 0xC0, 0x4A, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+0x79, 0x00, 0x29, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xE1, 0x01,
+0x94, 0x07, 0x90, 0x1F, 0x40, 0x78, 0x00, 0xED, 0x01, 0xF4, 0x07, 0x10, 0x1E,
+0x40, 0x7B, 0x00, 0xED, 0x01, 0xA4, 0x07, 0x10, 0x1E, 0x40, 0x7B, 0x00, 0xED,
+0x01, 0x84, 0x87, 0x50, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x85, 0x94, 0x06, 0x55,
+0x1B, 0x40, 0x0D, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x77,
+0x02, 0x91, 0x10, 0x04, 0x06, 0xD0, 0x00, 0x40, 0x07, 0x00, 0x01, 0x00, 0x14,
+0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x0C, 0x00, 0x34, 0x00, 0x10, 0x00, 0x40,
+0x03, 0x00, 0x0D, 0x00, 0x24, 0x00, 0x50, 0x01, 0x40, 0x03, 0x10, 0x05, 0x40,
+0x04, 0x00, 0xD0, 0xEC, 0x40, 0x31, 0x00, 0xCD, 0x00, 0x14, 0x0B, 0x50, 0x8C,
+0x40, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x9D, 0x00,
+0x7B, 0x87, 0x6C, 0x41, 0xF1, 0x05, 0xC0, 0x17, 0x00, 0x53, 0x00, 0x5C, 0x01,
+0xB4, 0x05, 0xC8, 0x14, 0x10, 0x5F, 0x00, 0x7C, 0x01, 0x30, 0x05, 0xC4, 0x17,
+0x00, 0x5F, 0x00, 0x44, 0x01, 0x30, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x4C,
+0x01, 0x70, 0x37, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x9E, 0x21, 0x50, 0xB7, 0x40,
+0x5D, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x04, 0x1F,
+0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x40, 0xE8, 0x00, 0x70,
+0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x20, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00,
+0x3F, 0x00, 0xDC, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x00, 0x37, 0x20, 0xDC, 0x00,
+0xF0, 0x01, 0xE0, 0x05, 0x00, 0x1F, 0x00, 0x5E, 0x80, 0x90, 0x01, 0x80, 0x4A,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x26, 0x02, 0x93, 0x00,
+0x5C, 0x02, 0xF0, 0x89, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x7C, 0x16, 0x30, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x93,
+0x00, 0x5C, 0x02, 0xF0, 0x19, 0xC0, 0x27, 0x00, 0x9F, 0x02, 0x7C, 0x02, 0x30,
+0x09, 0xC0, 0x24, 0x10, 0x9F, 0x80, 0x7E, 0x26, 0x30, 0x89, 0xC2, 0x43, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x66, 0x00, 0x91, 0x20, 0x44,
+0x02, 0x90, 0x19, 0x44, 0xA7, 0x00, 0x91, 0x02, 0x34, 0x02, 0x10, 0x09, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x08, 0x50, 0x20, 0x40, 0x91, 0x02,
+0x74, 0x02, 0xD0, 0x19, 0x40, 0x24, 0x00, 0x9F, 0x02, 0x34, 0x02, 0x10, 0x09,
+0x40, 0x24, 0x00, 0x9D, 0x02, 0x74, 0x06, 0x14, 0x39, 0x40, 0x07, 0x00, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x40, 0x91, 0x00, 0x44, 0x02,
+0xD0, 0x09, 0x40, 0x2F, 0x00, 0xB1, 0x00, 0xF4, 0x02, 0x10, 0x0B, 0x40, 0x2F,
+0x00, 0xBD, 0x00, 0xF4, 0x82, 0xD0, 0x0B, 0x40, 0x2C, 0x00, 0xB1, 0x00, 0xF4,
+0x22, 0xD0, 0x4B, 0x40, 0x2E, 0x01, 0xBD, 0x00, 0xF4, 0x02, 0x10, 0x08, 0x40,
+0x24, 0x00, 0x9D, 0x0A, 0x54, 0x03, 0x10, 0x09, 0x40, 0x63, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x41, 0x81, 0x04, 0x05, 0x02, 0x90,
+0x0A, 0x40, 0x6B, 0x00, 0xA1, 0x01, 0xF4, 0x02, 0x15, 0x0E, 0x42, 0x2B, 0x00,
+0xAD, 0x00, 0xB4, 0x82, 0xD0, 0x0B, 0x40, 0x2C, 0x00, 0xA1, 0x01, 0xB6, 0x02,
+0xD0, 0x0A, 0x40, 0x28, 0x00, 0xAD, 0x01, 0xF4, 0x02, 0x14, 0x48, 0x40, 0x20,
+0x02, 0x8D, 0x04, 0x34, 0x12, 0x10, 0x4C, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB0, 0x82, 0x02, 0x13, 0x0A, 0x5C, 0x28, 0xF0, 0x01,
+0xC0, 0x87, 0x42, 0x13, 0x0A, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x87, 0x02, 0x1F,
+0x0A, 0x7C, 0x28, 0xD0, 0xA1, 0xC0, 0x84, 0x02, 0x13, 0x0A, 0x7C, 0x00, 0xF0,
+0xA1, 0xC0, 0x07, 0x00, 0x1F, 0x0A, 0xFC, 0x28, 0x30, 0xA1, 0xD0, 0x84, 0x10,
+0x1F, 0x00, 0x7C, 0x28, 0x30, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0xB8, 0x3F, 0x02, 0xBF, 0x08, 0xFC, 0x02, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x80, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0x80, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x97, 0x00, 0x7C, 0x02, 0xF0, 0x8B, 0xC0, 0x27, 0x21, 0x9F,
+0x08, 0xFC, 0x23, 0xF8, 0x8B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0xA0, 0x2F, 0x05, 0xA3, 0x8C, 0x5C, 0x02, 0x35, 0x0B, 0xC0, 0x2F,
+0x02, 0xBF, 0x00, 0xFC, 0x02, 0x70, 0x0B, 0xE0, 0x25, 0x00, 0x9F, 0x00, 0x4D,
+0x22, 0xF1, 0x09, 0xC0, 0x24, 0x00, 0xBF, 0x08, 0xFC, 0x02, 0xF0, 0x0B, 0xC0,
+0x2E, 0x00, 0xBF, 0x00, 0x7C, 0x02, 0x30, 0xC9, 0xE2, 0x24, 0x80, 0xBF, 0xA0,
+0xC8, 0x83, 0x30, 0x0B, 0xC0, 0x67, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0x08, 0x03, 0x01, 0x11, 0x0C, 0x45, 0x40, 0x10, 0x01, 0x40, 0x03, 0x00,
+0x1D, 0x14, 0x74, 0x00, 0x10, 0x01, 0x40, 0x04, 0x04, 0x1D, 0x10, 0x44, 0x00,
+0xD0, 0x41, 0x41, 0x04, 0x01, 0x0D, 0x04, 0x74, 0x00, 0xD0, 0x01, 0x41, 0x04,
+0x10, 0x0D, 0x54, 0x74, 0x10, 0x50, 0xC1, 0x50, 0x04, 0x24, 0x1D, 0x00, 0x45,
+0x00, 0x10, 0x01, 0x40, 0x73, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA0, 0x23, 0x05, 0x81, 0x04, 0x04, 0x12, 0x10, 0x08, 0x40, 0x23, 0x00, 0x8D,
+0x04, 0x34, 0x02, 0x50, 0x08, 0x40, 0x20, 0x01, 0x8D, 0x00, 0x14, 0x02, 0xD0,
+0x49, 0x50, 0x20, 0x05, 0x8D, 0x04, 0x34, 0x03, 0xD0, 0x08, 0x40, 0x22, 0x00,
+0x8D, 0x04, 0x34, 0x52, 0x50, 0x58, 0x40, 0x21, 0x01, 0x8D, 0xA8, 0x04, 0x82,
+0x10, 0x08, 0x40, 0x43, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8,
+0x25, 0x40, 0x91, 0x02, 0x44, 0x22, 0x10, 0x09, 0x40, 0x37, 0x00, 0x9D, 0x00,
+0x74, 0x02, 0x50, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x56, 0x02, 0xC0, 0x09,
+0x40, 0x24, 0x00, 0xDD, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00, 0xDD,
+0x00, 0x34, 0x02, 0x50, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x40, 0x06, 0x02, 0x14,
+0x49, 0x40, 0x63, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0xA3,
+0x00, 0x93, 0x00, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0x50, 0x08, 0x50, 0x25, 0x08, 0x9F, 0x00, 0x5C, 0x02, 0xF2, 0x09, 0xC8,
+0x24, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x26, 0x00, 0x9D, 0x00,
+0x7C, 0x02, 0x34, 0x09, 0x40, 0x25, 0x00, 0x9D, 0x80, 0x4C, 0x0A, 0x20, 0x09,
+0xC1, 0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x65, 0x02,
+0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xB0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x6C, 0x02, 0xF0, 0x09, 0xC4, 0x27,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x10, 0x64,
+0x02, 0xB0, 0x08, 0xC0, 0x27, 0x00, 0x8F, 0x10, 0x7C, 0x0A, 0xF0, 0x09, 0xC2,
+0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x85, 0x20, 0x13,
+0x40, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x4C, 0x90, 0xE2,
+0x01, 0xC0, 0x07, 0x20, 0x1F, 0x00, 0x6C, 0x00, 0xD0, 0x01, 0xC0, 0x07, 0x00,
+0x1F, 0x08, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x02, 0x13, 0x00, 0x4C, 0x00,
+0xF0, 0x01, 0xC0, 0x05, 0x08, 0x1D, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x50,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x1C, 0x02, 0x51, 0x81,
+0x45, 0x01, 0x70, 0x15, 0x40, 0x5F, 0x01, 0x71, 0x00, 0x84, 0x0D, 0x10, 0x97,
+0x40, 0x17, 0x00, 0x5D, 0x00, 0x70, 0x01, 0x98, 0x04, 0x40, 0x17, 0x00, 0x7D,
+0x00, 0x44, 0x01, 0x70, 0x05, 0x40, 0x57, 0x00, 0x7B, 0x03, 0x44, 0x01, 0xC0,
+0x05, 0x40, 0x17, 0x10, 0x7C, 0x02, 0x74, 0x01, 0x10, 0x07, 0x00, 0x50, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x72, 0x00, 0xD1, 0x00, 0x44,
+0x03, 0x50, 0x88, 0x40, 0x73, 0x40, 0xC5, 0x08, 0x04, 0x0B, 0x50, 0x2C, 0x40,
+0x33, 0x00, 0xDD, 0x00, 0x24, 0x03, 0xD2, 0x0C, 0x44, 0x33, 0x00, 0xCD, 0x10,
+0x25, 0x02, 0x50, 0x1D, 0x40, 0x63, 0x00, 0xC1, 0x0A, 0x25, 0x03, 0xD0, 0x0C,
+0x60, 0x33, 0x00, 0x4D, 0x0B, 0x34, 0x02, 0x50, 0x0C, 0x00, 0x50, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x04, 0xB1, 0x02, 0x84, 0x33,
+0x50, 0x0E, 0x40, 0x5B, 0x00, 0x65, 0x01, 0x84, 0x43, 0x10, 0x0A, 0x41, 0x3B,
+0x01, 0xED, 0x04, 0xB4, 0x23, 0x90, 0x0E, 0x40, 0x3B, 0x10, 0xED, 0x01, 0xA4,
+0x03, 0x50, 0x2E, 0x40, 0x7B, 0x00, 0xE9, 0x21, 0xA6, 0x03, 0xD0, 0x4E, 0x40,
+0x3B, 0x01, 0x69, 0x00, 0xB4, 0x03, 0x58, 0x1C, 0x44, 0x10, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x78, 0x02, 0xE3, 0x01, 0x9C, 0x27, 0x71,
+0x1E, 0xC0, 0x7B, 0x20, 0xF7, 0x01, 0x8D, 0x06, 0x70, 0x1E, 0xC0, 0x7B, 0x00,
+0xED, 0x05, 0xAC, 0x87, 0xD0, 0x3E, 0xC0, 0x7B, 0x02, 0xEF, 0x01, 0xAC, 0x07,
+0x70, 0x1E, 0xC0, 0x7B, 0x00, 0xE3, 0x01, 0xAC, 0x97, 0xF0, 0x9E, 0xE0, 0x7B,
+0x20, 0x6D, 0x21, 0xBC, 0x07, 0x74, 0x1E, 0xC2, 0x50, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xB0, 0xBD, 0x40, 0x9F, 0x06, 0x7C, 0x03, 0x70, 0x0D,
+0xC0, 0x17, 0x00, 0x5B, 0x00, 0x3C, 0x02, 0x70, 0x09, 0xC0, 0x37, 0x04, 0xDF,
+0x02, 0x7C, 0x0B, 0xF0, 0x2D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x5C, 0x03, 0x60,
+0x0D, 0xC0, 0x33, 0x00, 0x9F, 0x00, 0x5C, 0x0B, 0xF0, 0xAD, 0xC0, 0x37, 0x00,
+0x1F, 0x00, 0x3C, 0x5B, 0xB0, 0x09, 0xC2, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xA0, 0x4F, 0x40, 0xB3, 0x03, 0xCC, 0x13, 0xF0, 0x1E, 0xC0,
+0x6C, 0x00, 0xBF, 0x01, 0x8C, 0x06, 0x30, 0x1B, 0xC0, 0x7B, 0x04, 0xF3, 0x13,
+0xCC, 0x0F, 0x30, 0x3F, 0xC0, 0x7F, 0x04, 0xFF, 0x81, 0xFC, 0x87, 0xB0, 0x1F,
+0xC0, 0x7F, 0x00, 0xBF, 0x01, 0xFC, 0x4F, 0xF0, 0x1F, 0xC0, 0x7C, 0x04, 0x7F,
+0x09, 0xCC, 0x06, 0x30, 0x9D, 0xC2, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x88, 0x09, 0x00, 0xA1, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x08,
+0x04, 0x2D, 0x44, 0x84, 0x02, 0x10, 0x0A, 0x40, 0x3B, 0x00, 0xE1, 0x00, 0xC4,
+0x03, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xAD, 0x10, 0xB4, 0x03, 0x10, 0x0E, 0x40,
+0x3B, 0x00, 0xAD, 0x10, 0xBC, 0x23, 0xD0, 0x0E, 0xC0, 0x3A, 0x00, 0x6D, 0x08,
+0x84, 0x03, 0x11, 0x3E, 0x40, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x08, 0x00, 0x11, 0x00, 0x81, 0x00, 0x84, 0x63, 0xD0, 0x0F, 0x40, 0x2A, 0x00,
+0xAD, 0x00, 0xC6, 0x02, 0x10, 0x0A, 0x40, 0xBF, 0x00, 0xF1, 0x02, 0x84, 0x23,
+0x10, 0x0E, 0x40, 0x3B, 0x00, 0x6D, 0x08, 0xF4, 0x03, 0x10, 0x0E, 0x40, 0x3B,
+0x02, 0x6D, 0x08, 0xB4, 0x03, 0xD0, 0x0C, 0x40, 0x38, 0x02, 0xCD, 0x48, 0x86,
+0x03, 0x50, 0x8E, 0x40, 0x23, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x28, 0x13, 0x00, 0x81, 0x42, 0x06, 0x07, 0xD0, 0x4C, 0x40, 0x42, 0x01, 0x0D,
+0x0D, 0x04, 0x0E, 0x10, 0x68, 0x40, 0x73, 0x00, 0xC1, 0x01, 0x04, 0x43, 0x10,
+0x1C, 0x41, 0x33, 0x04, 0x0D, 0x05, 0x34, 0x43, 0x18, 0x38, 0x40, 0x73, 0x00,
+0x1D, 0x05, 0x16, 0x2B, 0xD1, 0x0C, 0x50, 0x30, 0x08, 0x0D, 0x00, 0x40, 0x0B,
+0x58, 0x28, 0x41, 0x1B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8,
+0x21, 0x11, 0xD1, 0x02, 0xCC, 0x07, 0xF0, 0x2C, 0xC0, 0xF6, 0x00, 0xDF, 0x02,
+0x4D, 0x44, 0x34, 0x1D, 0xC0, 0x3F, 0x00, 0xE3, 0x04, 0xC4, 0x07, 0x30, 0x0F,
+0x40, 0x7B, 0x00, 0x1F, 0x03, 0x3C, 0x0B, 0x30, 0x9D, 0x40, 0xB7, 0x04, 0x5F,
+0x03, 0xB4, 0x07, 0xF0, 0x0F, 0x00, 0x3C, 0x00, 0xDF, 0x00, 0x4C, 0x22, 0x72,
+0x3D, 0xC4, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x1D, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x8D, 0xC0, 0x37, 0x22, 0xDF, 0x00, 0x7C, 0x23, 0xF0, 0x8D, 0xC0,
+0x37, 0x02, 0x1F, 0x02, 0x7C, 0x07, 0x70, 0x8D, 0xC0, 0x37, 0x01, 0x5F, 0x40,
+0x7C, 0x43, 0xF0, 0x1D, 0xC0, 0x37, 0x00, 0xDD, 0x02, 0x7C, 0x07, 0x96, 0x1D,
+0x40, 0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x2F, 0x80,
+0xF3, 0x10, 0xCC, 0x03, 0xF0, 0x1F, 0xC0, 0x9C, 0x20, 0x7F, 0x00, 0xCC, 0x51,
+0x70, 0x0F, 0xC0, 0x3F, 0x00, 0xF3, 0x20, 0xCC, 0x03, 0xF0, 0x0F, 0xC4, 0x3F,
+0x80, 0x33, 0x00, 0xFC, 0x03, 0x31, 0x0F, 0xC0, 0x3F, 0x00, 0x7F, 0x00, 0xCC,
+0x03, 0x30, 0x0E, 0xC0, 0x3C, 0x00, 0xFF, 0xA0, 0x4C, 0x83, 0x30, 0x17, 0xC2,
+0x07, 0x24, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x20, 0x46, 0x01, 0xC1,
+0x09, 0x45, 0x03, 0xD0, 0x1D, 0x40, 0xC4, 0x10, 0x1D, 0x5B, 0x04, 0x1F, 0x50,
+0x75, 0x40, 0x33, 0x00, 0xD1, 0x00, 0x44, 0x03, 0xD0, 0x0D, 0x42, 0x37, 0x40,
+0x11, 0x02, 0x74, 0x03, 0x50, 0x0D, 0x48, 0x37, 0x20, 0x1D, 0x02, 0x6C, 0x03,
+0xB0, 0x0D, 0x40, 0x35, 0x10, 0x8D, 0x07, 0x54, 0x03, 0x14, 0x3D, 0x40, 0x87,
+0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x44, 0x00, 0x99, 0x00,
+0x44, 0x03, 0xD0, 0x8D, 0x40, 0x34, 0x00, 0xCD, 0x00, 0x44, 0x03, 0x50, 0x1D,
+0x40, 0x37, 0x00, 0xD1, 0x00, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xD1,
+0x08, 0x74, 0x07, 0x90, 0x0D, 0x40, 0x37, 0x02, 0x9D, 0x00, 0x44, 0x03, 0x10,
+0x0D, 0x40, 0x34, 0x00, 0x1D, 0x01, 0x65, 0x02, 0x10, 0x8D, 0x40, 0x07, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x04, 0x00, 0x91, 0x80, 0x04,
+0x03, 0xD0, 0x0C, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x05, 0x03, 0x50, 0x0C, 0x40,
+0x37, 0x00, 0xD1, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x37, 0x00, 0x81, 0x00,
+0x64, 0x03, 0x98, 0x0C, 0x40, 0x33, 0x00, 0x8D, 0x00, 0x65, 0x03, 0x90, 0x0C,
+0x40, 0x30, 0x00, 0x8D, 0x00, 0x14, 0x03, 0x10, 0x4C, 0x40, 0x43, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB0, 0x0E, 0x00, 0xBB, 0x40, 0xCC, 0x03,
+0xF0, 0x0D, 0xC0, 0x14, 0x00, 0x4F, 0x00, 0x4C, 0x03, 0x70, 0x0D, 0xC0, 0x3F,
+0x00, 0xF3, 0x00, 0xCC, 0x03, 0xF0, 0x0F, 0x40, 0x3F, 0x00, 0x51, 0x00, 0x7C,
+0x03, 0xB0, 0x0D, 0xC0, 0x37, 0x10, 0x5F, 0x40, 0xCC, 0x03, 0x30, 0x0F, 0xC0,
+0x34, 0x00, 0x9F, 0x20, 0xCC, 0x03, 0x30, 0x05, 0xC2, 0x07, 0x40, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC0, 0x0F, 0x00, 0x3F, 0x40, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00,
+0xEF, 0x40, 0xFC, 0x03, 0xF0, 0x0F, 0xE0, 0x3F, 0x00, 0x3F, 0x80, 0xBC, 0x03,
+0x70, 0x0B, 0xC0, 0x3F, 0x10, 0x3F, 0x80, 0xDC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F,
+0x20, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x2F, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA0, 0x7B, 0x00, 0xFF, 0x01, 0xCC, 0x27, 0xE0, 0x1F,
+0xC0, 0x7C, 0x02, 0xFB, 0x01, 0xBE, 0x0F, 0x11, 0x3F, 0xC0, 0x7C, 0x82, 0xF3,
+0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0xFF, 0x00, 0xFB, 0x01, 0xDC, 0x07, 0x30,
+0x9F, 0xC0, 0x5E, 0x02, 0xB3, 0x84, 0xEC, 0x31, 0xF0, 0x1F, 0xE4, 0x7F, 0x00,
+0xFF, 0xC1, 0xEC, 0x24, 0xB0, 0x17, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x08, 0x07, 0x00, 0x1D, 0x10, 0x69, 0x00, 0xF1, 0x11, 0x40,
+0x00, 0x20, 0x11, 0x01, 0x74, 0x00, 0x10, 0x01, 0x40, 0x00, 0x01, 0x17, 0x01,
+0x74, 0x04, 0xD0, 0x11, 0x40, 0x04, 0x20, 0x1D, 0x01, 0x44, 0x84, 0xB0, 0x01,
+0x40, 0x15, 0x01, 0xD5, 0x09, 0x44, 0xB3, 0xD0, 0x1F, 0x42, 0x7F, 0x00, 0xFD,
+0x01, 0x04, 0x10, 0x10, 0x19, 0x40, 0x05, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x11, 0xA0, 0x33, 0x00, 0xDD, 0x84, 0x00, 0x13, 0xD0, 0x0D, 0x40, 0x30,
+0x21, 0xC9, 0x00, 0x30, 0x13, 0x10, 0x4D, 0x40, 0x34, 0x00, 0xC1, 0x00, 0x34,
+0x83, 0xC0, 0x0D, 0x00, 0x30, 0x01, 0xCD, 0x60, 0x40, 0x03, 0x92, 0x4C, 0x40,
+0x20, 0x00, 0x85, 0x00, 0x14, 0x01, 0x50, 0x0C, 0x40, 0x33, 0x80, 0xC5, 0x00,
+0x44, 0x10, 0x91, 0x0D, 0x64, 0x44, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA8, 0x05, 0x00, 0x1D, 0x00, 0x46, 0x80, 0x50, 0x01, 0x40, 0x04, 0x00,
+0x11, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x15, 0x00, 0x74, 0x00,
+0xD0, 0x01, 0x50, 0x04, 0x08, 0x1D, 0x00, 0x54, 0x00, 0x98, 0x01, 0x40, 0x21,
+0x00, 0x94, 0x00, 0x64, 0x11, 0xD0, 0x0D, 0x60, 0x37, 0x00, 0xDD, 0x00, 0x44,
+0x06, 0x10, 0x09, 0x40, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x88, 0x37, 0x00, 0xCF, 0x00, 0x44, 0x03, 0xD1, 0x0C, 0xD0, 0x34, 0x00, 0xDB,
+0x00, 0x74, 0x03, 0x34, 0x0C, 0xD0, 0x30, 0x00, 0xD3, 0x80, 0x7C, 0x03, 0xF1,
+0x0D, 0x40, 0x36, 0x08, 0xDB, 0x00, 0x1C, 0x03, 0xB0, 0x0D, 0xC2, 0xA6, 0x00,
+0x87, 0x01, 0x7D, 0x01, 0xF0, 0x0D, 0x40, 0x37, 0x00, 0xCF, 0x00, 0x2D, 0x04,
+0xB0, 0xD4, 0x40, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80,
+0x0D, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x80, 0xF4, 0x00, 0xF0, 0x03,
+0xC0, 0x0D, 0x00, 0x3D, 0x00, 0xED, 0x40, 0xF0, 0x03, 0xC0, 0x3F, 0x08, 0xFF,
+0x05, 0xCC, 0x03, 0xF0, 0x0F, 0x40, 0x3E, 0x20, 0xFF, 0x00, 0xFE, 0x00, 0xF0,
+0x1B, 0xD0, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35,
+0x04, 0xD3, 0x01, 0x7C, 0x03, 0xF0, 0x0D, 0xC8, 0x34, 0x10, 0xD7, 0x08, 0x6E,
+0xA3, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0xDB, 0x84, 0x7C, 0x83, 0xF0, 0x0D, 0xC0,
+0x37, 0x00, 0xDF, 0x08, 0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0xA6, 0x20, 0x97, 0x24,
+0x6E, 0x09, 0xF0, 0x0D, 0xC0, 0x37, 0x28, 0xDF, 0x20, 0x7C, 0x02, 0x30, 0x2D,
+0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xC4, 0x01,
+0x11, 0x01, 0x74, 0x00, 0xD0, 0x01, 0xD0, 0x06, 0x00, 0x11, 0x01, 0x44, 0x04,
+0x14, 0x51, 0x40, 0x07, 0x30, 0x11, 0x10, 0x5C, 0x00, 0xD9, 0x00, 0xC1, 0x45,
+0x24, 0x0D, 0xAA, 0x64, 0x00, 0x70, 0x41, 0x40, 0x64, 0x00, 0x9B, 0x04, 0x74,
+0x01, 0xD0, 0x0D, 0x48, 0x37, 0x00, 0xDD, 0x04, 0x5C, 0x6E, 0x10, 0x09, 0xC0,
+0x4D, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32, 0x80, 0xC1,
+0x00, 0x34, 0x03, 0xD0, 0x8C, 0x40, 0x34, 0x00, 0xC5, 0x01, 0x44, 0x07, 0x92,
+0x1C, 0x00, 0x33, 0x00, 0xC1, 0x02, 0x34, 0x03, 0xD0, 0x1C, 0x60, 0x73, 0x20,
+0xCD, 0x23, 0x34, 0x27, 0xD0, 0x1D, 0x40, 0xF0, 0x04, 0x81, 0x03, 0x34, 0x01,
+0xD0, 0x0C, 0x40, 0x73, 0x00, 0xCD, 0x05, 0x34, 0x0D, 0x10, 0x08, 0x40, 0x1F,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x4C, 0x00, 0x21, 0x01,
+0xB4, 0x04, 0xD0, 0x13, 0x40, 0x48, 0x00, 0x21, 0x01, 0xC4, 0x04, 0x98, 0x52,
+0x44, 0x4B, 0x00, 0x21, 0x05, 0x94, 0x04, 0xD0, 0x12, 0x68, 0x4B, 0x00, 0x2D,
+0x01, 0xB0, 0x04, 0x50, 0x12, 0x40, 0x79, 0x00, 0xE9, 0x01, 0xB4, 0x07, 0xD0,
+0x1E, 0x40, 0x7B, 0x00, 0xED, 0xA1, 0x94, 0x27, 0x10, 0x9A, 0x40, 0x19, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xC3, 0x00, 0x3C,
+0x03, 0xF0, 0x8C, 0x40, 0x30, 0x20, 0xC7, 0x00, 0x05, 0x23, 0xB0, 0x5C, 0xC4,
+0x33, 0x00, 0xC1, 0x05, 0x3C, 0x03, 0xD0, 0x0C, 0xC0, 0x33, 0x20, 0xCF, 0x88,
+0x3C, 0x03, 0xF2, 0x0D, 0x50, 0xA0, 0x04, 0xC3, 0x00, 0x34, 0x03, 0xF0, 0x8C,
+0xC0, 0x33, 0x06, 0xCF, 0x00, 0x3C, 0x01, 0x30, 0x88, 0xC4, 0x4B, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x0D, 0x00, 0x3F, 0x80, 0xFC, 0x00,
+0xF0, 0x82, 0xC0, 0x0F, 0x00, 0x2E, 0x08, 0xD4, 0x00, 0x71, 0x03, 0xC0, 0x07,
+0x02, 0x17, 0x08, 0xFC, 0x00, 0xF0, 0x01, 0xC0, 0x0D, 0x00, 0x1D, 0x80, 0x64,
+0x00, 0xF0, 0x11, 0xC0, 0x20, 0x02, 0xD8, 0x00, 0x7C, 0x03, 0xF0, 0x1F, 0xC0,
+0x7F, 0x08, 0xFF, 0x01, 0xDC, 0x03, 0xF0, 0x8B, 0xC0, 0x0B, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x35, 0x10, 0xCE, 0x01, 0x6C, 0x03, 0xD0, 0x0C, 0xC0, 0x34, 0x20,
+0xDF, 0x00, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x73, 0x00, 0xD7, 0x00, 0x7C, 0x03,
+0xF0, 0x0D, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x01, 0x70, 0x8D, 0xC0, 0x37,
+0x02, 0xDF, 0x00, 0x7C, 0x07, 0x30, 0x1D, 0xC0, 0x54, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x88, 0x09, 0x00, 0x2D, 0x00, 0xB4, 0x00, 0xC0, 0x02,
+0x40, 0x0B, 0x00, 0x2D, 0x00, 0x84, 0x00, 0xD0, 0x02, 0x40, 0x09, 0x00, 0x2D,
+0x00, 0xB4, 0x00, 0x50, 0x02, 0x40, 0x0B, 0x00, 0x21, 0x00, 0xA4, 0x00, 0xD0,
+0x02, 0x40, 0x3B, 0x00, 0xED, 0x02, 0x9C, 0x1B, 0xF0, 0x4E, 0x48, 0x3B, 0x01,
+0xE9, 0x02, 0xB4, 0x03, 0x10, 0x0A, 0xC0, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x02, 0x79, 0x08, 0xED, 0x01, 0xB4, 0x07, 0xC0, 0x1E, 0x40,
+0x7B, 0x00, 0xFD, 0x01, 0x84, 0x07, 0xD0, 0x1F, 0x40, 0x78, 0x10, 0xE4, 0x01,
+0xB4, 0x07, 0x10, 0x1E, 0x08, 0x7F, 0x00, 0xE5, 0x01, 0xB4, 0x07, 0x40, 0x1E,
+0x60, 0x6B, 0x04, 0xE5, 0x05, 0x94, 0x17, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED,
+0x05, 0xB4, 0x07, 0x10, 0x1E, 0x44, 0x0E, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x28, 0x03, 0x80, 0x0D, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x44, 0x03,
+0x00, 0x0D, 0x00, 0x04, 0x00, 0xD8, 0x01, 0x42, 0x05, 0x00, 0x08, 0x00, 0x34,
+0x80, 0x52, 0x00, 0x40, 0x03, 0x00, 0x01, 0x00, 0x34, 0x00, 0x90, 0x00, 0x40,
+0xE3, 0x00, 0xCD, 0x00, 0x04, 0x06, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xC9, 0x00,
+0x34, 0x0E, 0x1C, 0x08, 0x40, 0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x17, 0xA8, 0x15, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00,
+0x5F, 0x00, 0x45, 0x01, 0xF0, 0x05, 0xC0, 0x14, 0x00, 0x57, 0x00, 0x7C, 0x01,
+0x30, 0x05, 0xC0, 0x17, 0x00, 0x57, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x1F,
+0x00, 0x4F, 0x00, 0xDC, 0x81, 0x78, 0x05, 0xC4, 0x17, 0x00, 0x5F, 0x80, 0xFC,
+0x25, 0x30, 0x47, 0x40, 0x5E, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x00, 0x8F, 0x20, 0x3F, 0x00, 0xFC, 0x00, 0xF2, 0x03, 0xC0, 0x0F, 0x08, 0x3F,
+0x00, 0xDC, 0x00, 0xF1, 0x03, 0xC0, 0x0F, 0x20, 0x3D, 0x00, 0xFC, 0x00, 0xF0,
+0x03, 0xC8, 0x0F, 0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x03, 0x40, 0x87, 0x01,
+0x1F, 0x00, 0x5C, 0x20, 0x70, 0x00, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x20,
+0xF0, 0x01, 0xE0, 0x49, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08,
+0x67, 0x00, 0x9F, 0x08, 0x7C, 0x02, 0xF8, 0x29, 0xC0, 0x27, 0x00, 0x93, 0x04,
+0x7C, 0x02, 0xF0, 0x19, 0xC0, 0x24, 0x20, 0x97, 0x09, 0x4C, 0x02, 0xB0, 0x09,
+0xC0, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x22, 0xF0, 0x59, 0xC0, 0x24, 0x01, 0x9F,
+0x00, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x7C, 0x16, 0xF0,
+0x09, 0xC8, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xA6,
+0x06, 0x9D, 0x20, 0x74, 0x06, 0xD8, 0x39, 0x44, 0x23, 0x20, 0x91, 0x01, 0x74,
+0x06, 0xD0, 0x09, 0x40, 0x24, 0x08, 0x83, 0x01, 0x04, 0x02, 0x10, 0x09, 0x44,
+0x27, 0x00, 0x9D, 0x10, 0x74, 0x06, 0xD0, 0x18, 0x50, 0xE4, 0x00, 0xBD, 0x00,
+0xC4, 0x02, 0xD0, 0x0B, 0x40, 0x2C, 0x01, 0xBD, 0x40, 0x74, 0x0E, 0xD2, 0x09,
+0x42, 0x07, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x08,
+0xBD, 0x00, 0xF4, 0x06, 0xD2, 0x0B, 0x40, 0x2F, 0x00, 0xB1, 0x40, 0xF4, 0x12,
+0x50, 0x8B, 0x40, 0x2C, 0x20, 0xBD, 0x00, 0xE4, 0x02, 0x90, 0x0B, 0x60, 0x2E,
+0x00, 0xB5, 0x01, 0xF4, 0x0A, 0xD0, 0x0B, 0x40, 0x25, 0x00, 0x9D, 0x00, 0x64,
+0x13, 0xD2, 0x09, 0x40, 0x24, 0x80, 0x9D, 0x00, 0x74, 0x43, 0xD0, 0x09, 0x60,
+0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0x28, 0x00, 0xAD,
+0x02, 0xB4, 0x0A, 0xD0, 0x0E, 0x40, 0x2F, 0x00, 0xA1, 0x00, 0xB6, 0x0A, 0xD0,
+0x2A, 0x50, 0x28, 0x02, 0xBD, 0x00, 0xE5, 0x0A, 0x10, 0x0A, 0x60, 0xAB, 0x00,
+0xAD, 0x00, 0xB6, 0x02, 0xD0, 0x2B, 0x62, 0xA1, 0x00, 0x8D, 0x20, 0x04, 0x8A,
+0xD2, 0x28, 0x40, 0x20, 0x88, 0x8D, 0x80, 0x34, 0x22, 0xD0, 0x28, 0x40, 0x43,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xD0, 0x01, 0xC0, 0x87, 0x42, 0x13, 0x00, 0x7E, 0x00, 0x70, 0x01,
+0xC0, 0x84, 0x00, 0x57, 0x00, 0x2C, 0x00, 0xB0, 0x01, 0xC0, 0x06, 0x00, 0x1F,
+0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC2, 0x15, 0x00, 0x1F, 0x01, 0x4D, 0x04, 0xE0,
+0x11, 0xD0, 0x44, 0x00, 0x1D, 0x01, 0x3C, 0x08, 0xF0, 0x00, 0xE2, 0x77, 0xC0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x27, 0x0D, 0x9F, 0x01, 0x7C,
+0x86, 0xF2, 0x09, 0xC0, 0x27, 0x10, 0x9D, 0x00, 0x7C, 0x06, 0xF0, 0x19, 0x44,
+0x27, 0x01, 0x93, 0x00, 0x5C, 0x06, 0xE0, 0x09, 0x40, 0x67, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x19, 0xC8, 0x6E, 0x00, 0xBF, 0x02, 0xF4, 0x0E, 0xF0, 0x39,
+0xC0, 0xA7, 0x08, 0x9F, 0x02, 0xFC, 0x12, 0xF0, 0x1F, 0xC0, 0x67, 0x60, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x00, 0xB3, 0x02, 0xFC, 0x02,
+0xD1, 0x0A, 0xC0, 0x27, 0x10, 0xBE, 0x00, 0xD8, 0x02, 0xF0, 0x0B, 0xC0, 0x27,
+0x02, 0xBF, 0x00, 0x74, 0x02, 0xF0, 0x0B, 0xC0, 0xAF, 0x00, 0xB7, 0x00, 0xDC,
+0x02, 0xC0, 0x2B, 0xC0, 0x2F, 0x00, 0xB3, 0x01, 0xBC, 0x46, 0x30, 0xD9, 0xC0,
+0x6C, 0x01, 0xB3, 0x11, 0xC8, 0x02, 0xF0, 0x09, 0xC0, 0x67, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x05, 0x1B, 0x05, 0x74, 0x14, 0xD0,
+0x01, 0x40, 0x07, 0x04, 0x1D, 0x00, 0x74, 0x54, 0xD0, 0x11, 0x40, 0x07, 0x01,
+0x1D, 0x00, 0x74, 0x54, 0xD0, 0x01, 0xC0, 0x44, 0x00, 0x11, 0x00, 0x44, 0x00,
+0x90, 0x51, 0x40, 0x47, 0x05, 0x11, 0x20, 0x74, 0x14, 0x50, 0x31, 0x40, 0x85,
+0x00, 0x11, 0x02, 0x54, 0x00, 0xD0, 0x50, 0x41, 0x73, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x01, 0x81, 0x00, 0x34, 0x42, 0xD0, 0x08,
+0x40, 0x23, 0x00, 0xCD, 0x00, 0x14, 0x02, 0xD0, 0x48, 0x41, 0x23, 0x21, 0x8C,
+0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x27, 0x20, 0x94, 0x00, 0x14, 0x02, 0x90,
+0x08, 0x40, 0x27, 0x00, 0x81, 0x02, 0x34, 0x52, 0x50, 0xC8, 0x40, 0x20, 0x02,
+0x85, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x40, 0x43, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x99, 0x20, 0x74, 0x02, 0xD0, 0x09, 0x40,
+0x27, 0x10, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x80,
+0x74, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00, 0x91, 0x00, 0x44, 0x02, 0x90, 0x09,
+0x00, 0xA7, 0x01, 0x91, 0x00, 0x70, 0x42, 0x50, 0x08, 0x40, 0x37, 0x00, 0x95,
+0x00, 0x56, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0x08, 0x25, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x00, 0xDC, 0x02, 0xF0, 0x0B, 0xC0, 0x27, 0x00, 0x9D, 0x00, 0xFC,
+0x02, 0xF0, 0x09, 0xC0, 0x2B, 0x00, 0x97, 0x00, 0x5C, 0x02, 0x90, 0x0B, 0xC0,
+0x2F, 0xC0, 0x93, 0x01, 0xFC, 0x2A, 0x71, 0x0B, 0xC8, 0x20, 0x40, 0x97, 0x40,
+0x4C, 0x9E, 0xF0, 0x2B, 0x40, 0x17, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x00, 0x25, 0x04, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xE1, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC4, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF0, 0x09, 0xC4, 0x25, 0x00, 0x9F, 0x20, 0x7C, 0x02, 0xB0, 0x09, 0xC2, 0x67,
+0x00, 0x9F, 0x89, 0x6C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x00, 0x9B, 0x80, 0x7C,
+0x12, 0xF0, 0x09, 0xC0, 0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x08, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x3A, 0x01, 0xD0, 0x06, 0x00, 0x13,
+0x00, 0x6C, 0x00, 0xF2, 0x01, 0xC0, 0x04, 0x80, 0x13, 0x28, 0x7C, 0x00, 0xB2,
+0x01, 0xD0, 0x05, 0x40, 0x13, 0x00, 0x7C, 0x40, 0xF0, 0x01, 0xC2, 0x87, 0x00,
+0x1F, 0x00, 0x0C, 0x08, 0x31, 0x01, 0xD0, 0x04, 0x00, 0x03, 0x00, 0x4D, 0x88,
+0x30, 0x21, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20,
+0xDC, 0x00, 0x5D, 0x40, 0x74, 0x11, 0x15, 0x57, 0xC0, 0x14, 0x10, 0x55, 0x40,
+0x74, 0x01, 0xD0, 0x05, 0x40, 0x14, 0x00, 0x7B, 0x00, 0x74, 0x01, 0x10, 0x05,
+0x40, 0x54, 0x00, 0x6B, 0x02, 0xF4, 0x0D, 0x34, 0x05, 0x40, 0x9B, 0x00, 0x7D,
+0x02, 0x6E, 0x01, 0xB0, 0x05, 0x40, 0x9C, 0x00, 0x7B, 0x1B, 0xC4, 0x05, 0x10,
+0x05, 0xC8, 0x52, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xF6,
+0x82, 0xCD, 0x09, 0x34, 0x03, 0x10, 0x38, 0x40, 0x30, 0x00, 0x81, 0x00, 0x34,
+0x03, 0xC0, 0x0C, 0x40, 0x30, 0x00, 0x45, 0x05, 0x34, 0x03, 0x90, 0x08, 0x40,
+0x32, 0x02, 0xC1, 0x04, 0x34, 0x01, 0x18, 0x0C, 0x40, 0xE3, 0x03, 0x8D, 0x10,
+0x24, 0x03, 0x10, 0x0C, 0x44, 0xA2, 0x01, 0x89, 0x03, 0x24, 0x1B, 0x1D, 0x0C,
+0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x18, 0x80,
+0xAD, 0x44, 0xF4, 0x17, 0x10, 0x1A, 0x44, 0x7C, 0x00, 0xE5, 0x00, 0xB4, 0x12,
+0xD2, 0x5A, 0x40, 0x7C, 0x01, 0xE9, 0x00, 0xF6, 0x17, 0x10, 0x1A, 0x40, 0x2A,
+0x00, 0xE1, 0x00, 0xF4, 0x0F, 0x90, 0x0E, 0x40, 0x3B, 0x01, 0x8D, 0x11, 0xF4,
+0x0B, 0x90, 0x8E, 0x40, 0x28, 0x04, 0xA9, 0x20, 0xA4, 0x0F, 0x10, 0x5E, 0x40,
+0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x78, 0x00, 0xEF,
+0x21, 0xBC, 0x1E, 0x10, 0x1E, 0xC0, 0x78, 0x02, 0xE3, 0x01, 0xBC, 0x07, 0xD2,
+0x5F, 0xC0, 0x78, 0x04, 0xE5, 0x01, 0xBC, 0x97, 0xB0, 0x1A, 0x60, 0x7E, 0x00,
+0xE1, 0x01, 0xBC, 0x07, 0x19, 0x3E, 0xC0, 0x7B, 0x11, 0xAF, 0x01, 0xA6, 0x0E,
+0x30, 0x1C, 0x88, 0x6A, 0x00, 0xAB, 0x01, 0xEC, 0x05, 0x30, 0x3E, 0xC0, 0x50,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x08, 0x9F, 0x00,
+0x3C, 0x02, 0xF0, 0x0D, 0xC8, 0xB1, 0x01, 0xDF, 0x00, 0x7C, 0x22, 0xF0, 0x89,
+0xDA, 0x33, 0x02, 0xDC, 0x00, 0x3C, 0x23, 0xF0, 0x08, 0x80, 0x25, 0x00, 0x9F,
+0x00, 0x3C, 0x03, 0x70, 0x09, 0x80, 0x17, 0x10, 0x9D, 0x00, 0x6C, 0x02, 0xC0,
+0x0D, 0xC0, 0x21, 0x00, 0x8F, 0x00, 0x5C, 0x01, 0xF0, 0x0D, 0xC8, 0x43, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x7B, 0x00, 0xF3, 0x11, 0xCC,
+0x07, 0xB8, 0x0B, 0xC0, 0x7F, 0x04, 0xFF, 0x01, 0xED, 0x07, 0x30, 0x1F, 0xC0,
+0x7F, 0x20, 0xEF, 0x09, 0x4C, 0x27, 0x30, 0x1B, 0xC0, 0x7D, 0x04, 0xFB, 0x01,
+0x9C, 0x07, 0xB0, 0x9E, 0xC2, 0x5D, 0x04, 0xBF, 0x01, 0xFC, 0x07, 0xF0, 0x1F,
+0xC8, 0x6C, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1E, 0xC0, 0x08, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x19, 0x06, 0xF1, 0x40, 0xC4, 0x13,
+0x39, 0x4A, 0x40, 0x3B, 0x01, 0xED, 0x00, 0xC4, 0x02, 0x10, 0x08, 0x48, 0x3B,
+0x01, 0xC7, 0x02, 0x84, 0x77, 0x10, 0x0A, 0x40, 0x3C, 0x00, 0x61, 0x00, 0x84,
+0x03, 0x40, 0x1E, 0x40, 0x39, 0x00, 0xAD, 0x84, 0xA4, 0x13, 0xF0, 0x0E, 0x40,
+0x28, 0x00, 0xE5, 0x08, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x54, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x00, 0xA1, 0x08, 0x84, 0x02, 0x01,
+0x8A, 0x41, 0x3B, 0x10, 0xFD, 0x00, 0x84, 0x43, 0x10, 0x0E, 0x40, 0x3B, 0x20,
+0xED, 0x02, 0x80, 0x17, 0x10, 0x0B, 0x41, 0x29, 0x00, 0xF1, 0x00, 0x94, 0x03,
+0x10, 0x4F, 0x40, 0x1A, 0x00, 0xAD, 0x80, 0xB4, 0x42, 0xD0, 0x1E, 0x40, 0x20,
+0x00, 0xE5, 0x00, 0xB4, 0x01, 0xD0, 0x1F, 0x40, 0x20, 0x01, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x28, 0x03, 0x00, 0x90, 0x02, 0x44, 0x0E, 0x10, 0x3C,
+0x40, 0xB3, 0x02, 0xCD, 0x02, 0x06, 0x0E, 0x00, 0x38, 0x40, 0xF3, 0x01, 0xC9,
+0x08, 0x04, 0x4F, 0x11, 0x68, 0x42, 0xA5, 0x02, 0x01, 0x0B, 0x04, 0x4B, 0x50,
+0x08, 0x41, 0x13, 0x22, 0x8D, 0x81, 0x66, 0x1A, 0x52, 0x0C, 0x44, 0x20, 0x00,
+0xC5, 0x80, 0x74, 0x08, 0xD0, 0x0C, 0x40, 0x18, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0xA8, 0x65, 0x00, 0xD2, 0x01, 0x4C, 0x4F, 0x34, 0x18, 0xC0,
+0x7F, 0x00, 0xDF, 0x03, 0x0C, 0x07, 0x30, 0x3D, 0xC1, 0xBF, 0x04, 0xCD, 0x01,
+0x4D, 0x0B, 0x36, 0x2D, 0xE4, 0xB5, 0x02, 0x93, 0x02, 0x54, 0x42, 0x10, 0x19,
+0xC0, 0x36, 0x00, 0xDD, 0x05, 0x74, 0x0F, 0xD0, 0x0D, 0xD0, 0x34, 0x00, 0x97,
+0x20, 0x7C, 0x02, 0xF2, 0xBD, 0xD5, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0xA7, 0x20, 0x9F, 0x18, 0x7C, 0x03, 0x70, 0x29, 0xC0, 0x37,
+0x01, 0xDE, 0x08, 0x7C, 0x03, 0xF4, 0x4D, 0xC0, 0x37, 0x00, 0xD7, 0x02, 0x7C,
+0x03, 0xF0, 0x09, 0xC0, 0x26, 0x00, 0x97, 0x82, 0x7C, 0x0B, 0x70, 0x8D, 0xE0,
+0x35, 0x00, 0xDF, 0x02, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0x9D, 0x02,
+0x7C, 0x2A, 0xF0, 0x0D, 0xC0, 0xA7, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x0A, 0x2F, 0x00, 0xFF, 0x00, 0xCC, 0x43, 0x70, 0x0F, 0xC1, 0x3C, 0x00,
+0xFF, 0x15, 0xDC, 0x66, 0x30, 0x1B, 0xC0, 0x3F, 0x20, 0xFF, 0x00, 0xCC, 0x03,
+0xF0, 0x9F, 0xC0, 0x3F, 0x00, 0x33, 0x10, 0xFC, 0x03, 0xE0, 0x0B, 0xC0, 0x7F,
+0x10, 0xE3, 0x49, 0xCC, 0x03, 0x30, 0x0F, 0xC0, 0xBF, 0x00, 0xBF, 0x22, 0xFC,
+0x40, 0x30, 0x0F, 0xC0, 0x07, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81,
+0x20, 0x66, 0x00, 0x9D, 0x00, 0x44, 0x83, 0x10, 0x2D, 0x40, 0x34, 0x08, 0xDD,
+0x40, 0x74, 0x02, 0x50, 0x09, 0x44, 0x37, 0x08, 0xDD, 0x03, 0x44, 0x03, 0xD0,
+0x19, 0x68, 0x27, 0x80, 0x15, 0x13, 0x74, 0x47, 0xD2, 0x99, 0xC4, 0x51, 0x28,
+0xD1, 0x03, 0x6C, 0x27, 0xF0, 0x0D, 0x40, 0x27, 0x00, 0x9D, 0x04, 0x7C, 0x2F,
+0x11, 0x0D, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0,
+0x46, 0x04, 0xDD, 0x00, 0x44, 0x12, 0x12, 0x09, 0x41, 0x36, 0x00, 0xDD, 0x00,
+0x74, 0x03, 0x12, 0x8D, 0x42, 0x37, 0x00, 0xDD, 0x01, 0x44, 0x03, 0xD0, 0x0D,
+0x42, 0x37, 0x20, 0x91, 0x01, 0x74, 0x07, 0xD0, 0x09, 0x44, 0x17, 0x02, 0x95,
+0x50, 0x44, 0x02, 0x10, 0x0D, 0x48, 0x36, 0x00, 0x9D, 0x00, 0x74, 0x0A, 0x10,
+0x0D, 0x40, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+0x00, 0xCD, 0x00, 0x05, 0x02, 0x10, 0x08, 0x50, 0x32, 0x08, 0xCD, 0x00, 0x74,
+0x03, 0x50, 0x8C, 0x40, 0x33, 0x00, 0xDD, 0x02, 0x04, 0x13, 0xD0, 0x08, 0x40,
+0x36, 0x00, 0x05, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x61, 0x35, 0x40, 0x45, 0x80,
+0x24, 0x02, 0x98, 0x0C, 0x40, 0x33, 0x00, 0x4D, 0x20, 0x34, 0x00, 0x10, 0x0C,
+0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x26, 0x00,
+0x9F, 0x20, 0x4C, 0x02, 0x34, 0x01, 0xC0, 0x3E, 0x00, 0xDF, 0x00, 0x58, 0x82,
+0x30, 0x09, 0xC0, 0x3F, 0x08, 0xDF, 0x02, 0x84, 0x43, 0xF0, 0x0D, 0x40, 0x27,
+0x00, 0x11, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0x40, 0x17, 0x80, 0x97, 0x80, 0x4C,
+0x02, 0x30, 0x0E, 0x80, 0x17, 0x00, 0x9F, 0x00, 0x7C, 0x00, 0x34, 0x0F, 0xC8,
+0x07, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB0, 0x2F, 0x00, 0xBF,
+0x40, 0xFC, 0x02, 0xB0, 0x07, 0xC0, 0x3D, 0x08, 0xEF, 0x00, 0xFC, 0x02, 0xF0,
+0x4B, 0xC8, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0A, 0xC0, 0x2F, 0x00,
+0x2F, 0x00, 0xFC, 0x03, 0xD0, 0x09, 0xC0, 0x1F, 0x00, 0x7B, 0x00, 0xF8, 0x02,
+0xF0, 0x0F, 0xC2, 0x1F, 0x20, 0x7F, 0x00, 0xDC, 0x00, 0xF0, 0x0F, 0xC0, 0x17,
+0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x6F, 0x00, 0x2F, 0x04,
+0xCC, 0x06, 0x70, 0x43, 0xC1, 0x0F, 0x01, 0xE3, 0x01, 0xCC, 0x10, 0x74, 0x03,
+0xC0, 0x0F, 0x00, 0x33, 0x10, 0xCC, 0x80, 0x30, 0x03, 0xD0, 0x0C, 0x00, 0x33,
+0x04, 0xCC, 0x00, 0x34, 0x43, 0xC8, 0x7E, 0x02, 0xB3, 0x00, 0xFC, 0x53, 0xF0,
+0x12, 0xC0, 0x6D, 0x02, 0xAF, 0x01, 0xFC, 0x06, 0xF0, 0x4B, 0xC0, 0x0F, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0x00, 0x1D, 0xAB, 0x44,
+0x07, 0x10, 0x35, 0x48, 0xD7, 0x02, 0xD1, 0xA1, 0x44, 0x0D, 0x10, 0x35, 0x40,
+0x57, 0x02, 0x51, 0x43, 0x4C, 0x0D, 0x10, 0xB5, 0x40, 0xD4, 0x02, 0x51, 0x03,
+0x44, 0x0D, 0x10, 0x95, 0x40, 0x33, 0x11, 0xD1, 0x03, 0x74, 0x8F, 0xD0, 0x19,
+0x40, 0x27, 0x01, 0x9D, 0x01, 0x74, 0x04, 0xD2, 0x11, 0x40, 0x07, 0x60, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA8, 0x23, 0x00, 0x0D, 0x00, 0x44, 0x03,
+0x50, 0x08, 0x40, 0x21, 0x40, 0xC1, 0x00, 0x14, 0x0A, 0x18, 0x88, 0x40, 0x23,
+0x00, 0x81, 0x00, 0x04, 0x0A, 0x50, 0x08, 0x48, 0x20, 0x00, 0x89, 0x08, 0x06,
+0x0A, 0x10, 0x08, 0x40, 0x33, 0x01, 0x81, 0x02, 0x34, 0x03, 0xD0, 0x08, 0x40,
+0x01, 0x10, 0x85, 0x00, 0x34, 0x02, 0xD0, 0x88, 0x40, 0x47, 0x80, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x25, 0x02, 0x1D, 0xC0, 0x64, 0xC7, 0x10,
+0x05, 0x44, 0x37, 0x02, 0xD1, 0x00, 0x56, 0x08, 0x10, 0x05, 0x40, 0xB7, 0x09,
+0x91, 0x03, 0x64, 0x03, 0x50, 0x09, 0x40, 0x34, 0x00, 0x91, 0x00, 0x44, 0x0E,
+0x10, 0x09, 0x42, 0x37, 0x01, 0x91, 0x00, 0x74, 0x03, 0xD0, 0x19, 0x40, 0x57,
+0x00, 0xDD, 0x01, 0x74, 0x05, 0xD0, 0x19, 0x41, 0x0F, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA8, 0x27, 0x00, 0xDF, 0x5A, 0x0C, 0x0F, 0x70, 0x91,
+0xC0, 0xC7, 0x04, 0xD3, 0x01, 0x5C, 0x24, 0x30, 0x11, 0xC2, 0xC7, 0x00, 0x13,
+0x02, 0x4C, 0x00, 0x70, 0x21, 0xC1, 0xC4, 0x86, 0x13, 0x1B, 0x4C, 0x08, 0x30,
+0x01, 0xC0, 0x36, 0x00, 0x93, 0x00, 0x7C, 0x03, 0xF0, 0x59, 0xC0, 0xE5, 0x00,
+0x9F, 0x07, 0x7C, 0x16, 0xF0, 0x39, 0xC0, 0x0B, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x80, 0x2D, 0x20, 0xBF, 0x00, 0xDC, 0x03, 0xF0, 0x17, 0xC0,
+0x4F, 0x00, 0xFD, 0x02, 0xEC, 0x01, 0xB0, 0x3F, 0xC0, 0x1A, 0x40, 0x6F, 0x00,
+0x9C, 0x0D, 0xB0, 0x07, 0xC0, 0x5B, 0x20, 0x7F, 0x00, 0xFD, 0x01, 0xF0, 0x07,
+0xC2, 0x7F, 0x40, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0x7F,
+0x00, 0xFC, 0x01, 0xF2, 0x03, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x08, 0x25, 0x00, 0xD3, 0x13, 0x4C, 0x23, 0xF0, 0x09, 0xD0, 0xA0,
+0x00, 0xDF, 0x11, 0x1C, 0x0A, 0x70, 0x09, 0xE0, 0x27, 0x00, 0x1F, 0x02, 0x4C,
+0x2A, 0x30, 0x2C, 0xC0, 0xA7, 0x02, 0x83, 0x02, 0x0D, 0x02, 0xF0, 0x2D, 0x41,
+0x74, 0x01, 0xD3, 0x00, 0x4C, 0x03, 0xF0, 0x29, 0xC0, 0x94, 0x00, 0x9F, 0x0E,
+0x4C, 0x0A, 0xF0, 0x29, 0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0xA0, 0x64, 0x01, 0x81, 0x22, 0x44, 0x03, 0xD0, 0xB5, 0x40, 0xE4, 0x02,
+0xCD, 0x02, 0x44, 0x28, 0xD0, 0xAD, 0x41, 0xB7, 0x06, 0x1D, 0x1A, 0x44, 0x07,
+0x12, 0xAD, 0x42, 0xB7, 0x00, 0x91, 0x0B, 0x6C, 0x2A, 0xD0, 0x0D, 0x41, 0xB5,
+0x08, 0xD1, 0x01, 0xC4, 0x83, 0xD0, 0x0D, 0xC0, 0x14, 0x00, 0xD1, 0x01, 0x44,
+0x99, 0xD0, 0x19, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x20, 0xE2, 0x01, 0x01, 0x00, 0x14, 0x13, 0xD0, 0x00, 0x40, 0x00, 0x28, 0xCD,
+0x00, 0x20, 0x24, 0x80, 0x10, 0x40, 0x43, 0x00, 0x0D, 0x01, 0x06, 0x90, 0x10,
+0x90, 0x40, 0x43, 0x04, 0x01, 0x00, 0x24, 0x24, 0xD0, 0x10, 0x40, 0x34, 0x00,
+0x81, 0x80, 0x24, 0x83, 0x90, 0x08, 0x40, 0x20, 0x00, 0x01, 0x02, 0x04, 0x42,
+0xD1, 0x00, 0x43, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+0x6A, 0x00, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x98, 0x43, 0x58, 0x00, 0xED, 0x01,
+0xB4, 0x07, 0xD0, 0x12, 0x40, 0x6B, 0x00, 0x4C, 0x01, 0x04, 0x04, 0x10, 0x1E,
+0x40, 0x63, 0x00, 0xC1, 0x11, 0x84, 0x05, 0xD0, 0x14, 0x50, 0x78, 0x00, 0xE1,
+0x01, 0xA4, 0x07, 0xD0, 0x0B, 0x40, 0x7A, 0x12, 0xB1, 0x01, 0x85, 0x06, 0xD0,
+0x12, 0x48, 0x13, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x22,
+0x00, 0x03, 0x08, 0x1C, 0x03, 0xF0, 0xA8, 0xC8, 0x00, 0x84, 0xCF, 0x00, 0x3C,
+0x83, 0x70, 0x0C, 0x40, 0x13, 0x00, 0xCE, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xCA,
+0x13, 0x10, 0x43, 0x00, 0x24, 0x01, 0xF0, 0xE0, 0xC0, 0x30, 0x40, 0x83, 0x18,
+0x2C, 0x03, 0xF0, 0x88, 0xC0, 0x24, 0x40, 0x47, 0x08, 0x0C, 0x03, 0xF0, 0x00,
+0xC1, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x39, 0x40,
+0xFF, 0x00, 0xFC, 0x03, 0xF1, 0x8B, 0xC0, 0x1F, 0x20, 0xFF, 0x00, 0xCC, 0x03,
+0xF8, 0x07, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x8B, 0xC0, 0x3F,
+0x00, 0xFF, 0x08, 0xFC, 0x01, 0xF0, 0x83, 0xE0, 0x3F, 0x00, 0xAF, 0x00, 0xDD,
+0x43, 0xF0, 0x4F, 0xC0, 0x1D, 0x00, 0x7F, 0x00, 0xFC, 0x01, 0xF0, 0x83, 0xC0,
+0x0B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x67, 0x00, 0x53,
+0x00, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x36, 0x00, 0xD7, 0x00, 0x7C, 0x00, 0xF0,
+0x01, 0xC0, 0x07, 0x00, 0x93, 0x80, 0x7C, 0x07, 0x32, 0x01, 0xC2, 0x44, 0x00,
+0x13, 0x00, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x37, 0x00, 0x93, 0x00, 0x5C, 0x03,
+0xF0, 0x09, 0xC0, 0x57, 0x00, 0x53, 0x80, 0x7C, 0x01, 0x30, 0x19, 0xC0, 0x40,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x98, 0x39, 0x00, 0xE1, 0x00,
+0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x38, 0x08, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0A,
+0x40, 0x23, 0x40, 0xE1, 0x00, 0x36, 0x03, 0x04, 0x0C, 0x40, 0x28, 0x40, 0xE1,
+0x20, 0x04, 0x03, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xE5, 0x00, 0xB4, 0x13, 0xD0,
+0x0A, 0x40, 0x3B, 0x00, 0x61, 0x00, 0xF4, 0x01, 0xB1, 0x02, 0x40, 0x48, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x69, 0x00, 0x61, 0x01, 0xB4,
+0x07, 0xD0, 0x1C, 0x44, 0x78, 0x00, 0xE5, 0x11, 0xB6, 0x07, 0x50, 0x1E, 0x40,
+0x5B, 0x00, 0xE1, 0x01, 0xB4, 0x07, 0x10, 0x16, 0x40, 0x50, 0x00, 0x41, 0x01,
+0x84, 0x07, 0x14, 0x3E, 0x40, 0x7F, 0x00, 0xE1, 0x01, 0x94, 0x07, 0xD0, 0x1A,
+0x40, 0xDF, 0x00, 0x61, 0x01, 0xF4, 0x07, 0x10, 0x18, 0x50, 0x10, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x20, 0x33, 0x00, 0xC1, 0x13, 0x34, 0x01,
+0xD0, 0x9C, 0x40, 0xB0, 0x04, 0x8D, 0x01, 0x36, 0x03, 0xD0, 0x0C, 0x40, 0x33,
+0x00, 0xC1, 0x02, 0x34, 0x07, 0x10, 0x0C, 0x40, 0x30, 0x00, 0xC1, 0x00, 0x04,
+0x03, 0x10, 0x2C, 0x40, 0x63, 0x02, 0xC5, 0x08, 0x34, 0x03, 0xD0, 0xAC, 0x41,
+0xD3, 0x00, 0x41, 0x62, 0x34, 0x85, 0x90, 0x1C, 0x40, 0x58, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x57, 0x04, 0x73, 0x07, 0xBC, 0x09, 0xF0,
+0x07, 0xD0, 0x9E, 0x04, 0x57, 0x00, 0xFC, 0x01, 0xF0, 0x87, 0xE0, 0x1F, 0x00,
+0x73, 0x02, 0xFC, 0x1D, 0x30, 0x17, 0xD1, 0x1C, 0x00, 0x73, 0x00, 0xCD, 0x01,
+0x30, 0x27, 0xC0, 0x17, 0x00, 0x53, 0x01, 0x5C, 0x01, 0xF0, 0x17, 0xC0, 0x1F,
+0x00, 0x63, 0x07, 0xBC, 0x05, 0x30, 0x77, 0xC0, 0x5C, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x40, 0x0F, 0x00, 0x7C, 0x40, 0xF0, 0x01,
+0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F,
+0x00, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x04, 0xF0,
+0x01, 0xC1, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x44,
+0x1F, 0x06, 0x7C, 0x24, 0xF0, 0x41, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x30, 0x08, 0xE0,
+0x20, 0x00, 0x93, 0x00, 0x3C, 0x02, 0x30, 0x08, 0xC0, 0x20, 0x00, 0x83, 0x10,
+0x4C, 0x02, 0xF0, 0x08, 0xC0, 0x24, 0x00, 0x8F, 0x00, 0x0C, 0x02, 0x70, 0x08,
+0xC0, 0x64, 0x00, 0x93, 0x00, 0x3C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F,
+0x08, 0x4C, 0x22, 0x30, 0x59, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x80, 0x44, 0x02, 0x10, 0x09, 0x10, 0x24,
+0x40, 0x91, 0x00, 0x74, 0x02, 0x14, 0x09, 0xD0, 0x24, 0x50, 0x91, 0x40, 0x4D,
+0x02, 0xD0, 0x09, 0x50, 0x24, 0x00, 0x9D, 0x00, 0x45, 0x02, 0x14, 0x09, 0x50,
+0x64, 0x42, 0x91, 0x00, 0x74, 0x06, 0x50, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x01,
+0x54, 0x06, 0x54, 0x29, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00,
+0x91, 0x00, 0x74, 0x02, 0x10, 0x09, 0x00, 0x26, 0x00, 0x99, 0x00, 0x44, 0x03,
+0xD0, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x90, 0x09, 0x40, 0x20,
+0x00, 0x91, 0x00, 0x74, 0x12, 0x10, 0x09, 0x40, 0x37, 0x00, 0x9D, 0x00, 0x44,
+0x42, 0x11, 0x29, 0x40, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x28, 0x20, 0x00, 0x8D, 0x04, 0x05, 0x02, 0x10, 0x48, 0x40, 0x20, 0x01, 0x81,
+0x00, 0x34, 0x12, 0x10, 0x48, 0x44, 0x20, 0x01, 0x89, 0x04, 0x04, 0x12, 0xD0,
+0x48, 0x40, 0x20, 0x01, 0x8D, 0x04, 0x04, 0x12, 0x10, 0x48, 0x40, 0x60, 0x00,
+0x81, 0x04, 0x34, 0x12, 0x50, 0x08, 0x40, 0x23, 0x00, 0x8D, 0x00, 0x54, 0x02,
+0x50, 0x48, 0x40, 0x53, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0,
+0x06, 0x00, 0x1F, 0x00, 0x44, 0x00, 0x34, 0x01, 0x40, 0x04, 0x00, 0x13, 0x00,
+0x7C, 0x00, 0x30, 0x01, 0xC0, 0x06, 0x00, 0x1B, 0x20, 0x4C, 0x00, 0xF0, 0x01,
+0xC0, 0x04, 0x00, 0x1F, 0x00, 0x4C, 0x00, 0x70, 0x01, 0xC0, 0x84, 0x02, 0x13,
+0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x87, 0x02, 0x5F, 0x80, 0x4C, 0x00, 0x32,
+0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA8, 0x2B,
+0x00, 0xBF, 0x28, 0xFD, 0x02, 0xF1, 0x8B, 0xC0, 0x2F, 0x0A, 0xBF, 0x20, 0xFC,
+0x22, 0xF0, 0x8B, 0xC0, 0x2F, 0x02, 0xB7, 0x08, 0xDC, 0x22, 0xF2, 0x8B, 0xC0,
+0x2F, 0x22, 0xBF, 0x08, 0xFC, 0x22, 0xF2, 0x8B, 0xC0, 0x2B, 0x00, 0xBF, 0x08,
+0x7C, 0x22, 0xF0, 0x0B, 0xC0, 0x2B, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF1, 0x8B,
+0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x27, 0x00,
+0x9F, 0x84, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x7C, 0x52,
+0x30, 0x49, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x49, 0xC0, 0x24,
+0x05, 0x9F, 0x04, 0x7C, 0x02, 0xF0, 0x08, 0xC0, 0x2C, 0x02, 0xB3, 0x04, 0xCC,
+0x16, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0xBF, 0x00, 0xBC, 0x02, 0xF2, 0x0B, 0xC0,
+0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18, 0x07, 0x00, 0x1D,
+0x28, 0x74, 0x80, 0xD0, 0x01, 0x40, 0x07, 0x02, 0x11, 0x00, 0x74, 0x00, 0x10,
+0x81, 0x40, 0x87, 0x00, 0x1D, 0x00, 0x74, 0xA0, 0x12, 0x01, 0x40, 0x04, 0x00,
+0x1D, 0x88, 0x74, 0x08, 0xD0, 0x03, 0x40, 0x04, 0x40, 0x11, 0x20, 0x45, 0x00,
+0xD0, 0x01, 0x40, 0x16, 0x14, 0x1D, 0x00, 0x74, 0x00, 0xD0, 0x01, 0x40, 0x73,
+0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x29, 0x00, 0xAD, 0x00,
+0xB4, 0x02, 0xD0, 0x9A, 0x40, 0x6B, 0x00, 0xA1, 0x00, 0xB4, 0x06, 0x10, 0x1A,
+0x40, 0x6B, 0x02, 0xAD, 0x09, 0xB4, 0x06, 0x10, 0x9A, 0x48, 0x68, 0x20, 0xAD,
+0x01, 0xB0, 0x26, 0xD0, 0x9A, 0x40, 0x20, 0x00, 0x81, 0x08, 0x04, 0x0A, 0xD0,
+0x08, 0x40, 0x23, 0x01, 0x8D, 0x80, 0x34, 0x02, 0xD0, 0x18, 0x40, 0x4B, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x65, 0x00, 0xBD, 0x00, 0xF4,
+0x8A, 0xD0, 0x0B, 0x40, 0x2F, 0x00, 0xB1, 0x00, 0xF4, 0x02, 0x10, 0x0B, 0x40,
+0x6F, 0x00, 0xBD, 0x00, 0xF4, 0x02, 0x10, 0x0B, 0x40, 0x6C, 0x00, 0xBD, 0x00,
+0xF4, 0x12, 0xD0, 0x0B, 0x50, 0x24, 0x00, 0x91, 0x04, 0x44, 0x02, 0xD0, 0x09,
+0x40, 0x26, 0x02, 0x9D, 0x02, 0x74, 0x0A, 0xD0, 0x19, 0x40, 0x63, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x26,
+0xF0, 0x29, 0xC8, 0xA7, 0x40, 0x91, 0x00, 0x7C, 0x2A, 0x34, 0x39, 0xC0, 0xA7,
+0x00, 0x9F, 0x0B, 0x7C, 0x0A, 0x34, 0xA9, 0xD0, 0xA4, 0x00, 0x9F, 0x03, 0x7C,
+0x0A, 0xF0, 0x09, 0xC0, 0x64, 0x00, 0x93, 0x00, 0x4C, 0x02, 0xF0, 0x39, 0xC1,
+0xA7, 0x00, 0x9F, 0x82, 0x7C, 0x0E, 0xF0, 0x29, 0xC0, 0x17, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x25, 0x08, 0x9F, 0x00, 0x78, 0x06, 0xF0,
+0x09, 0x80, 0x27, 0x00, 0x9F, 0x09, 0x7C, 0x02, 0xF0, 0x49, 0xC0, 0x27, 0x00,
+0x9F, 0x01, 0x3C, 0x02, 0xF0, 0x08, 0xC0, 0x27, 0x00, 0x9F, 0x09, 0x7C, 0x06,
+0xF0, 0x98, 0xC0, 0x27, 0x01, 0x8F, 0x01, 0x7C, 0x02, 0xF0, 0x89, 0xC0, 0x27,
+0x00, 0x9F, 0x28, 0x7C, 0x66, 0xF0, 0x09, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x0D, 0x00, 0x3F, 0x00, 0xCC, 0x00, 0xF0, 0x03,
+0xC0, 0x0B, 0x00, 0x3F, 0x00, 0xBC, 0x00, 0x70, 0x03, 0xC0, 0x0C, 0x00, 0x3F,
+0x00, 0xFE, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xB0,
+0x03, 0xC0, 0x44, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00,
+0x1F, 0x12, 0x7C, 0x08, 0x30, 0x01, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x80, 0x14, 0x00, 0x5D, 0x20, 0x40, 0x01, 0x70, 0x05, 0x40,
+0x17, 0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x14, 0x00, 0x5D, 0x20,
+0x74, 0x01, 0xD2, 0x05, 0x48, 0x17, 0x00, 0x5D, 0x00, 0x74, 0x01, 0x30, 0x05,
+0xC0, 0x1E, 0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x17, 0x10, 0x7D,
+0x03, 0xF4, 0x4D, 0x50, 0x17, 0x50, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0xA0, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x50, 0x00, 0x40, 0x03,
+0x00, 0x0D, 0x00, 0x34, 0x00, 0x50, 0x00, 0x40, 0x02, 0x00, 0x0D, 0x00, 0x36,
+0x00, 0xD0, 0x00, 0x40, 0x03, 0x00, 0x09, 0x00, 0x30, 0x00, 0x14, 0x00, 0x40,
+0x34, 0x08, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x4D, 0x00,
+0x34, 0x09, 0x10, 0x8C, 0x41, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x88, 0x38, 0x00, 0xCD, 0x01, 0x84, 0x03, 0x50, 0x0E, 0x40, 0x3B, 0x00,
+0xED, 0x00, 0xB4, 0x03, 0xD0, 0x1E, 0x40, 0x3A, 0x00, 0xED, 0x00, 0xB4, 0x03,
+0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0x34, 0x07, 0x10, 0x0E, 0x40, 0x2A,
+0x00, 0xAD, 0x00, 0xB4, 0x42, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0x6D, 0x42, 0xB4,
+0x05, 0x50, 0x1E, 0x40, 0x05, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+0x10, 0x48, 0x00, 0x2F, 0x01, 0x8D, 0x84, 0x70, 0x12, 0xC0, 0x4B, 0x00, 0x2F,
+0x01, 0xBC, 0x04, 0x72, 0x10, 0xD0, 0x4A, 0x08, 0x2D, 0x21, 0xB4, 0x04, 0xF0,
+0x12, 0xC0, 0x4B, 0x00, 0x2F, 0x01, 0xBC, 0x04, 0x30, 0x12, 0xC0, 0x58, 0x00,
+0xAF, 0x01, 0xBC, 0x06, 0xF0, 0x1E, 0xC0, 0x7B, 0x03, 0xEF, 0x01, 0xBC, 0x05,
+0x30, 0x1E, 0xC0, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8,
+0x35, 0x00, 0xDF, 0x00, 0x7E, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC8, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0,
+0x0C, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x4D,
+0x00, 0x3F, 0x01, 0xCC, 0x20, 0xF0, 0x13, 0xC0, 0x4C, 0x00, 0x3F, 0x01, 0xCC,
+0x04, 0xF0, 0x13, 0xC0, 0x4E, 0x00, 0x33, 0x01, 0xCC, 0x84, 0xF0, 0x13, 0xC2,
+0x4F, 0x02, 0x3F, 0x09, 0xFC, 0x04, 0xF0, 0x13, 0xC0, 0x7C, 0x00, 0xBF, 0x01,
+0xFC, 0x07, 0xF0, 0x1E, 0xC0, 0x7C, 0x04, 0x73, 0x01, 0x8C, 0x07, 0x30, 0x17,
+0xC0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x39, 0x08,
+0xED, 0x00, 0x84, 0x03, 0xF0, 0x8E, 0x40, 0x38, 0x00, 0xED, 0x30, 0x94, 0x03,
+0xD0, 0x0E, 0x50, 0x38, 0x42, 0xE1, 0x08, 0x85, 0x23, 0xD0, 0x0E, 0x40, 0x3B,
+0x00, 0xED, 0x08, 0xB4, 0x03, 0xF0, 0x0E, 0x40, 0x08, 0x00, 0xAD, 0x00, 0xB4,
+0x03, 0xF0, 0x0E, 0xC0, 0x3B, 0x00, 0x21, 0x00, 0xAC, 0x12, 0xB0, 0x5E, 0x40,
+0x57, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x2D,
+0x18, 0x84, 0x20, 0xD8, 0x00, 0x40, 0x08, 0x00, 0x3D, 0x00, 0x84, 0x00, 0xD0,
+0x00, 0x40, 0x80, 0x00, 0x01, 0x00, 0x94, 0x00, 0xD0, 0x22, 0x40, 0x8B, 0x20,
+0x2D, 0x08, 0xB4, 0x00, 0xD0, 0x10, 0x40, 0x18, 0x04, 0xAD, 0x00, 0xB4, 0x02,
+0xD0, 0x0F, 0x40, 0x38, 0x00, 0x61, 0x10, 0x84, 0x43, 0x18, 0x4E, 0x40, 0x03,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x31, 0x00, 0xCD, 0x06,
+0x06, 0x0B, 0x50, 0x2C, 0x40, 0x30, 0x00, 0xCD, 0x00, 0x14, 0x0B, 0xD0, 0x0C,
+0x44, 0x30, 0x00, 0xC1, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x02, 0x34, 0x03, 0x50, 0x0C, 0x50, 0x50, 0x00, 0x8D, 0x00, 0x34, 0x02, 0x50,
+0x7C, 0x40, 0xF3, 0x00, 0x81, 0x03, 0x24, 0x16, 0x90, 0x2D, 0x40, 0x13, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x05, 0x00, 0x1F, 0x01, 0x4C,
+0x28, 0xD0, 0x11, 0xD0, 0x44, 0x00, 0x1F, 0x00, 0x4C, 0x04, 0xF0, 0x31, 0xC0,
+0x44, 0x00, 0x13, 0x01, 0x5C, 0x04, 0xF0, 0x11, 0xC0, 0x47, 0x00, 0x1F, 0x01,
+0x7C, 0x04, 0xD0, 0x00, 0xC0, 0x74, 0x00, 0xDF, 0x01, 0x3C, 0x02, 0xD0, 0x0D,
+0xC1, 0xB8, 0x01, 0x43, 0x03, 0x4C, 0x05, 0x30, 0xBD, 0xC0, 0x57, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0x00, 0xDF, 0x20, 0x7D, 0x87,
+0xF0, 0x1D, 0xC1, 0x77, 0x00, 0xDF, 0x00, 0x7C, 0x07, 0xF0, 0x1D, 0xC0, 0x77,
+0x10, 0xDF, 0x01, 0x7C, 0x07, 0xF0, 0x1D, 0xC0, 0x73, 0x00, 0xDF, 0x81, 0x7C,
+0x07, 0xF0, 0x1D, 0xC0, 0x27, 0x10, 0x9F, 0x08, 0x7C, 0x02, 0xF0, 0x0D, 0xC0,
+0x35, 0x44, 0x5F, 0x10, 0x7C, 0x0B, 0xF2, 0x3D, 0xC4, 0x07, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x0F, 0x00, 0x13, 0x00, 0xFC, 0x80, 0x30,
+0x03, 0xC0, 0x0B, 0x00, 0x33, 0x00, 0xBC, 0x40, 0x30, 0x02, 0xC1, 0x0C, 0x08,
+0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x32, 0x10, 0xFC, 0x80,
+0xF0, 0x03, 0xC0, 0x0C, 0x00, 0xEF, 0x09, 0xCC, 0x02, 0x30, 0x0F, 0xC0, 0x3F,
+0x00, 0xB3, 0x00, 0xCC, 0x00, 0x30, 0x5F, 0xC0, 0x10, 0x22, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x85, 0x20, 0x32, 0x00, 0xD1, 0x00, 0x34, 0x03, 0x92, 0x0D,
+0x42, 0x37, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x40, 0x34, 0x00, 0xDD,
+0x00, 0x76, 0x03, 0xD0, 0x0D, 0x42, 0x37, 0x40, 0xD1, 0x00, 0x64, 0x03, 0xD2,
+0x0D, 0xC0, 0x24, 0x08, 0x9D, 0x01, 0x44, 0x02, 0x14, 0x0D, 0x40, 0x37, 0x00,
+0x95, 0x93, 0x14, 0x0C, 0x10, 0x4D, 0x40, 0x15, 0x02, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0xA0, 0x04, 0x00, 0x11, 0x40, 0x74, 0x00, 0x90, 0x01, 0x40,
+0x07, 0x00, 0x11, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x1D, 0x00,
+0x74, 0x00, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x15, 0x00, 0x54, 0x00, 0xD0, 0x01,
+0x40, 0x76, 0x80, 0xD9, 0x00, 0x44, 0x03, 0x18, 0x0D, 0x40, 0x37, 0x00, 0xD1,
+0x21, 0x54, 0x0D, 0x12, 0x0D, 0x48, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x28, 0x34, 0x00, 0xC1, 0x00, 0x34, 0x03, 0x94, 0x0C, 0x40, 0x33,
+0x00, 0xC1, 0x00, 0x34, 0x03, 0x14, 0x0C, 0x40, 0x30, 0x00, 0xCD, 0x00, 0x34,
+0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xC5, 0x00, 0x34, 0x03, 0x90, 0x0C, 0x48,
+0x00, 0x00, 0x8D, 0x00, 0x05, 0x03, 0x10, 0x0C, 0x40, 0x37, 0x20, 0x15, 0x00,
+0x54, 0x02, 0x11, 0x0D, 0x40, 0x41, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xB0, 0x06, 0x00, 0x13, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC8, 0x07, 0x40,
+0x13, 0x00, 0x7C, 0x00, 0x32, 0x01, 0xD0, 0x04, 0x00, 0x1F, 0x00, 0x74, 0x00,
+0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x5C, 0x00, 0xF0, 0x01, 0xD0, 0x04,
+0x10, 0xDF, 0x00, 0x4C, 0x02, 0x30, 0x0D, 0xC0, 0x3B, 0x00, 0x93, 0x00, 0x4C,
+0x02, 0x32, 0x45, 0xC0, 0x00, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xA0, 0x3F, 0x40, 0xFF, 0x80, 0xFC, 0x03, 0x51, 0x0F, 0xC0, 0x3F, 0x00, 0xEF,
+0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC4, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC0, 0x3F, 0x00, 0xFB, 0x00, 0xEC, 0x03, 0xF0, 0x0F, 0xC0, 0x0D, 0x10,
+0xBD, 0x20, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F, 0x40, 0xAF, 0x80, 0xFD, 0x02,
+0xF0, 0x29, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0,
+0x2F, 0x01, 0x73, 0x01, 0xFC, 0x11, 0x34, 0x33, 0xC0, 0x1E, 0x01, 0xB3, 0x14,
+0xCC, 0x07, 0xF0, 0x0B, 0xC0, 0x3C, 0x01, 0xBF, 0x80, 0xCC, 0x27, 0xF0, 0x83,
+0xC0, 0x78, 0x00, 0x23, 0x01, 0xCC, 0xB3, 0xF0, 0x4B, 0xC0, 0x1A, 0x21, 0x73,
+0x01, 0xEC, 0x10, 0xF2, 0x13, 0xC0, 0x3C, 0x05, 0x7F, 0x01, 0xFC, 0x05, 0xF0,
+0x1F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xF7,
+0x00, 0xD1, 0x81, 0x74, 0x25, 0x12, 0x0D, 0x40, 0xD4, 0x02, 0x91, 0x03, 0x44,
+0x87, 0xD0, 0x39, 0x80, 0xFE, 0x02, 0x9D, 0x03, 0x44, 0x13, 0xD0, 0x61, 0x40,
+0x34, 0x44, 0x13, 0x81, 0xD4, 0x23, 0xD0, 0xB9, 0x40, 0xD4, 0x02, 0x91, 0x01,
+0x44, 0x31, 0xD1, 0x11, 0x40, 0xFC, 0x00, 0x9D, 0x81, 0x34, 0x87, 0xD0, 0x1D,
+0x44, 0x0F, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xA3, 0x00,
+0xC1, 0x00, 0x74, 0x01, 0x50, 0x4C, 0x40, 0x16, 0x00, 0xC5, 0x00, 0x04, 0x03,
+0xD0, 0x20, 0x40, 0x30, 0x00, 0x8D, 0x02, 0x04, 0x13, 0xD0, 0x28, 0x40, 0x30,
+0x01, 0x01, 0x00, 0x04, 0x13, 0xD0, 0x08, 0x60, 0x13, 0x00, 0x81, 0x80, 0x24,
+0x42, 0xD2, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x02, 0x50, 0x0C, 0x40,
+0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x75, 0x00, 0xD1,
+0x00, 0x74, 0x01, 0x10, 0x1D, 0x40, 0x34, 0x04, 0x95, 0x00, 0x44, 0x13, 0xD0,
+0x39, 0x60, 0x36, 0x00, 0x9D, 0x00, 0x44, 0x03, 0xD0, 0x01, 0x40, 0x74, 0x00,
+0x59, 0x00, 0x54, 0x03, 0xD0, 0x0D, 0x40, 0x15, 0x00, 0x91, 0x10, 0x44, 0x63,
+0xD0, 0x21, 0x40, 0x36, 0x00, 0x9D, 0x06, 0x74, 0x9B, 0xD8, 0x0D, 0x40, 0x0F,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xA8, 0x23, 0x40, 0x93, 0x40,
+0x3C, 0x3B, 0x71, 0x1D, 0xC0, 0xD2, 0x00, 0x97, 0x00, 0x4C, 0x07, 0xF0, 0x1D,
+0xC0, 0x34, 0x00, 0x8F, 0x00, 0x4D, 0x03, 0xF0, 0x91, 0xD0, 0x34, 0x00, 0x11,
+0x07, 0x4C, 0x03, 0xF0, 0x0C, 0xC0, 0x13, 0x46, 0x53, 0x00, 0x6C, 0x0C, 0xF0,
+0x98, 0xE0, 0x36, 0x00, 0x5F, 0x00, 0x7C, 0x05, 0xE0, 0x0D, 0xC0, 0x0B, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x25, 0x00, 0xBF, 0x45, 0xFC,
+0x05, 0xF0, 0x0F, 0xC0, 0x9F, 0x40, 0xEB, 0x00, 0xFC, 0x03, 0xF0, 0x0E, 0xC0,
+0x3F, 0x10, 0xDF, 0x04, 0xFC, 0x03, 0xF0, 0x0C, 0xC0, 0x3F, 0x40, 0xB7, 0x04,
+0xFC, 0x03, 0xF0, 0x0B, 0xC4, 0x7E, 0x00, 0xFF, 0x00, 0x7C, 0x84, 0xF0, 0x03,
+0x70, 0x35, 0x00, 0xBF, 0x01, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x1F, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x00, 0x93, 0x01, 0x7C, 0x03,
+0xF0, 0x0D, 0xC0, 0x17, 0x00, 0xD3, 0x10, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x34,
+0x00, 0x97, 0x00, 0x4C, 0x03, 0xF0, 0x09, 0xC0, 0x34, 0x00, 0xDB, 0x10, 0x5C,
+0x03, 0xF0, 0x0D, 0xC0, 0x96, 0x84, 0x93, 0x02, 0x7C, 0x08, 0xB4, 0x2D, 0xC0,
+0x37, 0x00, 0xD7, 0x02, 0x7C, 0x02, 0xB0, 0x0D, 0xC0, 0x29, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0, 0xE4, 0x01, 0x91, 0x00, 0x76, 0x05, 0xD0,
+0x0D, 0x40, 0x37, 0x00, 0xD1, 0x00, 0x74, 0x03, 0xF0, 0x0D, 0xC0, 0x3D, 0x01,
+0xD1, 0x00, 0x44, 0x83, 0xDA, 0x0D, 0x40, 0x34, 0x00, 0xCB, 0x82, 0xC4, 0x43,
+0xD1, 0x0D, 0xC0, 0x37, 0x10, 0x8B, 0x1A, 0x76, 0x00, 0x10, 0x05, 0x40, 0x3F,
+0x00, 0x91, 0x00, 0x74, 0x03, 0xB0, 0x1D, 0xC0, 0x4F, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0xA0, 0x22, 0x01, 0x01, 0x00, 0x34, 0x05, 0xD0, 0x0D,
+0x40, 0x33, 0x02, 0x81, 0x02, 0x34, 0x03, 0xD0, 0x08, 0x44, 0x30, 0x00, 0xC5,
+0x00, 0x24, 0x03, 0xD0, 0x04, 0x40, 0x34, 0x00, 0x01, 0x00, 0x14, 0x07, 0xC0,
+0x08, 0x40, 0xF0, 0x20, 0xC1, 0x03, 0x34, 0x00, 0x90, 0x04, 0x48, 0x33, 0x00,
+0x80, 0x00, 0x36, 0x02, 0x50, 0x8C, 0x40, 0x4E, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0D, 0x80, 0x78, 0x20, 0xE1, 0x81, 0xB4, 0x47, 0xD0, 0x1E, 0x60,
+0x5B, 0x10, 0xA1, 0x81, 0xB4, 0x07, 0x50, 0x9B, 0x42, 0x79, 0x00, 0xA1, 0x01,
+0xA4, 0x07, 0xD8, 0x12, 0x40, 0x7C, 0x00, 0xF9, 0x01, 0xA4, 0x07, 0xD0, 0x1A,
+0x40, 0x5E, 0x04, 0xA9, 0x01, 0xB4, 0x05, 0x90, 0x52, 0x40, 0x7B, 0x00, 0xA1,
+0x01, 0xB4, 0x06, 0x90, 0x1E, 0x40, 0x36, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x10, 0x20, 0x00, 0x81, 0x00, 0x34, 0x01, 0xF2, 0x0C, 0xE0, 0x33,
+0x40, 0xC3, 0x00, 0x3C, 0x03, 0xD0, 0x0D, 0xC0, 0x30, 0x00, 0xC6, 0x20, 0x24,
+0x03, 0xD0, 0x4C, 0xC0, 0x30, 0x30, 0x83, 0x58, 0x1C, 0x03, 0xF0, 0x08, 0xC0,
+0x30, 0x00, 0x81, 0x00, 0x34, 0x02, 0xB4, 0x0C, 0xC0, 0x33, 0x40, 0x87, 0x00,
+0x3C, 0x02, 0x70, 0x0C, 0xC4, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3B, 0x02,
+0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0xB3, 0x00, 0xBF, 0x00, 0x5C, 0x03,
+0xF0, 0x03, 0xD0, 0x3F, 0x00, 0xFF, 0x20, 0xDC, 0x03, 0xF0, 0x0E, 0xC0, 0x1F,
+0x00, 0xBF, 0x00, 0xFC, 0x23, 0x70, 0x4B, 0xCA, 0xBF, 0x82, 0xBF, 0x00, 0xFC,
+0x02, 0xF0, 0x0E, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA8, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC2, 0x77, 0x00, 0x93,
+0x80, 0x5C, 0x83, 0x70, 0x09, 0x80, 0xB5, 0x22, 0xD3, 0x00, 0x5C, 0x03, 0xF0,
+0x05, 0xC0, 0x77, 0x20, 0x53, 0x00, 0x7C, 0x33, 0xE0, 0x0D, 0xC0, 0x37, 0x00,
+0xDF, 0x00, 0x78, 0x03, 0xB0, 0x1D, 0xC0, 0x36, 0x81, 0xDF, 0x00, 0x4C, 0x02,
+0xF0, 0x0D, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x98,
+0xB9, 0x10, 0xAD, 0x40, 0x9C, 0x0B, 0xD3, 0x0E, 0x40, 0x13, 0x01, 0xE1, 0x00,
+0x84, 0x03, 0xD0, 0x2A, 0x40, 0x30, 0x11, 0xE1, 0x22, 0xB4, 0x83, 0xD0, 0x0E,
+0x40, 0x3B, 0x00, 0xE1, 0x00, 0xB4, 0x53, 0x80, 0x0A, 0x40, 0xBB, 0x00, 0xED,
+0x00, 0x34, 0x03, 0x10, 0x0E, 0x60, 0x38, 0x08, 0xAD, 0x00, 0x94, 0x02, 0xD0,
+0x0E, 0x40, 0x4F, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79,
+0x05, 0xAD, 0x03, 0xB4, 0x57, 0xD0, 0x1E, 0x40, 0x7B, 0x03, 0xC1, 0x09, 0x96,
+0x47, 0xD0, 0x7C, 0x4C, 0x79, 0x60, 0xE1, 0x05, 0xB6, 0x07, 0xD0, 0x1E, 0x40,
+0x7B, 0x00, 0xE1, 0x83, 0xB4, 0x07, 0xC0, 0xDE, 0x08, 0x7B, 0x01, 0xAD, 0x01,
+0xB4, 0x07, 0x10, 0x1F, 0x40, 0x7A, 0x92, 0xED, 0x43, 0x84, 0x06, 0xD0, 0x1E,
+0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x33, 0x00,
+0x8D, 0x40, 0x14, 0x02, 0xD0, 0x3D, 0x41, 0x23, 0x00, 0xC1, 0x00, 0x04, 0x06,
+0xD0, 0x1C, 0x40, 0x30, 0x00, 0xC1, 0x00, 0x74, 0x03, 0xD0, 0xEC, 0x60, 0x23,
+0x00, 0xC1, 0x07, 0x34, 0x03, 0x91, 0x1C, 0x40, 0xA3, 0x09, 0x8D, 0x00, 0x34,
+0x1F, 0x10, 0x3C, 0x44, 0x30, 0x00, 0x8D, 0x00, 0x14, 0x02, 0xD0, 0x0C, 0x40,
+0x5B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x11, 0x10, 0x6F,
+0x00, 0xBC, 0x21, 0xF0, 0x07, 0xC1, 0x1F, 0x40, 0x53, 0x00, 0x5C, 0x01, 0x72,
+0x17, 0xC2, 0x15, 0x00, 0x52, 0x00, 0x7C, 0x01, 0xF0, 0x37, 0xC0, 0x17, 0x00,
+0x73, 0x23, 0x7C, 0x01, 0xF2, 0x15, 0xC3, 0x9F, 0x01, 0x7F, 0x05, 0xFC, 0x1D,
+0x34, 0x17, 0xC5, 0x16, 0x00, 0x7F, 0x40, 0xCC, 0x81, 0xE0, 0x05, 0xC0, 0x5F,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x87, 0x20, 0x1F, 0x04,
+0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x02, 0x1F, 0x08, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x00, 0xC8, 0x07, 0x42, 0x1F,
+0x02, 0x3C, 0x00, 0xB0, 0x01, 0xC2, 0x03, 0x00, 0x1F, 0x00, 0x3C, 0x00, 0x70,
+0x01, 0xC0, 0x07, 0x00, 0x1B, 0x20, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x4B, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x27, 0x01, 0x9B, 0x01, 0x4C,
+0x22, 0x30, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x01, 0x4C, 0x02, 0xF0, 0x09, 0xD0,
+0x61, 0x00, 0x96, 0x04, 0x7C, 0x02, 0x70, 0x09, 0xC2, 0x24, 0x00, 0x9F, 0x00,
+0x5C, 0x02, 0x78, 0x89, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x7C, 0x02, 0x30, 0x49,
+0xC9, 0x27, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x43, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xEE, 0x00, 0x91, 0x89, 0xC4, 0x06,
+0x10, 0x09, 0x40, 0x6C, 0x00, 0xAD, 0x03, 0x44, 0x02, 0xD0, 0x0B, 0x42, 0x64,
+0x00, 0xB1, 0x07, 0x74, 0x02, 0x10, 0x09, 0x40, 0xA4, 0x82, 0x8D, 0x02, 0x44,
+0x02, 0x10, 0x0B, 0x48, 0x2F, 0x00, 0x91, 0x40, 0x74, 0x02, 0xB0, 0x79, 0x40,
+0x27, 0x00, 0x87, 0x00, 0x2C, 0x02, 0x50, 0x09, 0x40, 0x07, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x04, 0x91, 0x00, 0x44, 0x02, 0x16,
+0x0D, 0x60, 0x24, 0x01, 0x9D, 0x0A, 0x40, 0x02, 0xD0, 0x08, 0x40, 0x24, 0x02,
+0x9D, 0x00, 0x74, 0x02, 0x50, 0x09, 0x40, 0xA4, 0x20, 0x9D, 0x18, 0x54, 0x02,
+0x50, 0x09, 0x41, 0x27, 0x00, 0x91, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x27,
+0x00, 0x98, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x73, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x81, 0x00, 0x04, 0x02, 0x10, 0x88,
+0x40, 0x20, 0x00, 0x8D, 0x00, 0x04, 0x0A, 0xD0, 0x28, 0x40, 0x20, 0x00, 0x89,
+0x00, 0x34, 0x22, 0x50, 0x88, 0x40, 0x20, 0x02, 0x8D, 0x40, 0x00, 0x0A, 0x10,
+0x08, 0x48, 0x23, 0x40, 0x81, 0x00, 0x34, 0x22, 0x98, 0x08, 0x40, 0x23, 0x20,
+0x95, 0xC2, 0x64, 0x0A, 0x10, 0x08, 0x40, 0x53, 0xA0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xB0, 0x46, 0x40, 0x13, 0x00, 0x4C, 0x04, 0x32, 0x21, 0xD0,
+0x44, 0x00, 0x1F, 0x01, 0x4D, 0x00, 0xF0, 0x11, 0xC0, 0x05, 0x15, 0x1F, 0x01,
+0x7C, 0x08, 0x70, 0x61, 0xD1, 0x80, 0x00, 0x1D, 0x00, 0x5C, 0x50, 0x50, 0x11,
+0x40, 0x47, 0x00, 0x53, 0x40, 0x6C, 0x58, 0x30, 0x01, 0xC0, 0x07, 0x05, 0x0F,
+0x00, 0x4D, 0x00, 0x34, 0x01, 0xC4, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0xB8, 0xAF, 0x08, 0xBF, 0x00, 0xFD, 0x0A, 0xF0, 0x4B, 0xC0, 0xAF,
+0x00, 0xBF, 0x02, 0xFC, 0x06, 0xF0, 0x3B, 0xC0, 0x27, 0x00, 0xB3, 0x02, 0x7C,
+0x12, 0xB1, 0x4B, 0x80, 0x2F, 0x01, 0xBF, 0x00, 0x7C, 0x06, 0xF0, 0x2B, 0xC0,
+0xAF, 0x08, 0xBF, 0x00, 0xF8, 0x12, 0xF2, 0x0A, 0xC4, 0x27, 0x00, 0xB7, 0x01,
+0xDC, 0x06, 0xF0, 0x09, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0xA0, 0x6F, 0x00, 0xBF, 0x40, 0xC4, 0x56, 0xF0, 0x09, 0xC0, 0x6F, 0x01,
+0xBF, 0x41, 0x7C, 0x02, 0x30, 0x79, 0xC0, 0x2C, 0x00, 0xFF, 0x31, 0x4C, 0x22,
+0xF0, 0x49, 0xC0, 0x2C, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0xB0, 0x5B, 0xC1, 0x6D,
+0x14, 0xB3, 0x60, 0x4C, 0x52, 0x32, 0x0B, 0xC0, 0x27, 0x28, 0x9F, 0x02, 0x7C,
+0x0A, 0xF0, 0x0B, 0xC6, 0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
+0x08, 0x07, 0x00, 0x1D, 0x00, 0x44, 0x08, 0xD0, 0x01, 0x43, 0x97, 0x00, 0x1D,
+0x02, 0x34, 0x54, 0x52, 0x75, 0x50, 0x84, 0x00, 0x1D, 0x02, 0x54, 0x00, 0x90,
+0x41, 0x11, 0x04, 0x41, 0x11, 0x00, 0x74, 0x9C, 0x10, 0x21, 0x40, 0x84, 0x00,
+0x51, 0x00, 0x54, 0x11, 0x50, 0x05, 0x00, 0x87, 0x10, 0x1D, 0x01, 0x74, 0x04,
+0xD0, 0x01, 0x40, 0x73, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0,
+0xA3, 0x80, 0xDD, 0x00, 0x14, 0x02, 0xD0, 0x08, 0x40, 0xB3, 0x30, 0x8C, 0x02,
+0x34, 0x02, 0x10, 0xC8, 0x40, 0x22, 0x02, 0x8D, 0x00, 0x04, 0x02, 0x50, 0xC8,
+0x40, 0x20, 0x25, 0x80, 0x00, 0x34, 0x62, 0x92, 0x08, 0x60, 0x23, 0x00, 0x95,
+0x00, 0x14, 0x52, 0xD0, 0x08, 0x42, 0x23, 0x82, 0x8D, 0x00, 0x34, 0x02, 0xD0,
+0x08, 0x40, 0x4B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25,
+0x00, 0x9D, 0x22, 0x54, 0x02, 0xD0, 0x69, 0x42, 0x27, 0x00, 0x9D, 0x00, 0x34,
+0x02, 0x50, 0x09, 0x40, 0x26, 0x80, 0x9D, 0x00, 0x54, 0x82, 0x90, 0x08, 0x41,
+0x20, 0x00, 0x91, 0x24, 0x76, 0x02, 0x10, 0x09, 0x40, 0x24, 0x02, 0xD5, 0x48,
+0x14, 0x02, 0x50, 0x09, 0x42, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x1A, 0xD0, 0x09,
+0x40, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00,
+0x8F, 0x82, 0x5D, 0x82, 0xF0, 0x09, 0xC0, 0x27, 0x02, 0x9F, 0x00, 0xFC, 0x02,
+0x30, 0xAB, 0xC0, 0x26, 0x10, 0x9F, 0x00, 0x4C, 0x02, 0xF0, 0x29, 0xC0, 0x24,
+0x00, 0x93, 0x04, 0xFC, 0x02, 0xB0, 0x18, 0xC8, 0x27, 0x40, 0x87, 0x00, 0x5C,
+0x0A, 0x60, 0x29, 0xC0, 0x27, 0x00, 0xBF, 0x24, 0xFC, 0x02, 0xF0, 0x09, 0xC0,
+0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0x25, 0x00, 0x9F,
+0x00, 0x6C, 0x0E, 0xF0, 0x19, 0xC0, 0x27, 0x00, 0x9E, 0x09, 0x7C, 0x0E, 0xF0,
+0x08, 0xC0, 0x25, 0x80, 0x8F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0xA7, 0x14,
+0x9F, 0x20, 0x3C, 0x02, 0x70, 0x59, 0xCA, 0x27, 0x08, 0x9B, 0x11, 0x7C, 0x02,
+0xF8, 0x49, 0xC0, 0x27, 0x80, 0x9F, 0x00, 0x7C, 0x02, 0xF2, 0x09, 0xC0, 0x4B,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xB0, 0x01, 0xC0, 0x87, 0x00, 0x1B, 0x10, 0x7C, 0x00, 0x30, 0x21,
+0xD0, 0x04, 0x02, 0x1F, 0x08, 0x4D, 0x00, 0xF0, 0x01, 0xE0, 0x04, 0x00, 0x17,
+0x10, 0x4C, 0x00, 0xF0, 0x41, 0xC0, 0x02, 0x40, 0x13, 0x02, 0x4C, 0x08, 0xF2,
+0x01, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x43, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x1C, 0x00, 0x5D, 0x00, 0x70,
+0x01, 0x18, 0x05, 0x48, 0x17, 0x00, 0x7C, 0x03, 0x74, 0x01, 0x10, 0x05, 0x50,
+0x54, 0x00, 0x7C, 0x03, 0x44, 0x01, 0xD0, 0x05, 0x40, 0x9C, 0x01, 0x7D, 0x41,
+0x7C, 0x11, 0x70, 0x07, 0xC0, 0xDE, 0x01, 0x70, 0x03, 0x68, 0x01, 0x10, 0x37,
+0x05, 0x14, 0x80, 0x5D, 0x00, 0x74, 0x01, 0xC0, 0x45, 0x40, 0x53, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x22, 0x20, 0x8D, 0x00, 0x30, 0x06,
+0x10, 0x0C, 0x40, 0x23, 0x10, 0x8C, 0x08, 0x36, 0x03, 0x10, 0x0C, 0x40, 0x30,
+0x00, 0x8D, 0x13, 0x24, 0x03, 0xC0, 0x0C, 0x40, 0xB0, 0x00, 0xCD, 0x00, 0x24,
+0x03, 0x50, 0x38, 0x40, 0x20, 0x29, 0xC0, 0x0A, 0x04, 0x03, 0x90, 0x38, 0x01,
+0x31, 0x00, 0xCD, 0x80, 0x36, 0x03, 0xC0, 0x0C, 0x40, 0x53, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x00, 0xED, 0x40, 0xB4, 0x0F, 0x10,
+0x0E, 0x48, 0x3B, 0x00, 0xAD, 0x00, 0xB4, 0x23, 0x10, 0x4C, 0x40, 0x28, 0x00,
+0xAD, 0x00, 0xA4, 0x03, 0xD0, 0x4E, 0x60, 0x38, 0x80, 0xFD, 0x03, 0xA4, 0x23,
+0x50, 0x28, 0x40, 0x3A, 0x00, 0xF1, 0x00, 0x26, 0x23, 0x10, 0x1B, 0x40, 0x38,
+0x00, 0xED, 0x04, 0xB4, 0x13, 0x90, 0x0E, 0x40, 0x07, 0x20, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x10, 0x68, 0x00, 0xEF, 0x01, 0x3C, 0x07, 0x34, 0x3E,
+0xC0, 0x7B, 0x00, 0xAF, 0x81, 0xBC, 0x07, 0x34, 0x7E, 0x40, 0x78, 0x00, 0xAD,
+0x01, 0xA4, 0x1F, 0xF9, 0xBF, 0x40, 0x48, 0x00, 0xE7, 0x01, 0xAC, 0x17, 0x70,
+0x16, 0xE0, 0x68, 0x00, 0xE3, 0x01, 0x8C, 0x57, 0xB0, 0x1E, 0xE0, 0x79, 0x00,
+0xED, 0x03, 0xBE, 0x0F, 0xF0, 0x1E, 0xC4, 0x47, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xB8, 0x25, 0x20, 0xDF, 0x00, 0x7C, 0x03, 0xF1, 0x0D, 0x44,
+0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xD0, 0x0D, 0x40, 0x27, 0x10, 0x8F, 0x00,
+0x5C, 0x4B, 0xF0, 0x6D, 0xD0, 0x07, 0x00, 0x0F, 0x00, 0x7C, 0x83, 0x70, 0x05,
+0xC0, 0x33, 0x08, 0xCF, 0x00, 0x7C, 0x0B, 0x71, 0x0C, 0xC0, 0x37, 0x10, 0xDF,
+0x00, 0x74, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA0, 0x6F, 0x00, 0xF3, 0x09, 0xFC, 0x83, 0x30, 0x9F, 0xC0, 0x7F,
+0x02, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1E, 0x80, 0x7D, 0x00, 0xBF, 0x01, 0xFC,
+0x27, 0x30, 0x1F, 0xC0, 0x7E, 0x22, 0xFF, 0x01, 0xFC, 0x06, 0xF0, 0x1F, 0xC0,
+0x6C, 0x00, 0xFF, 0x01, 0xFC, 0x07, 0xB0, 0x1B, 0xC0, 0x7F, 0x02, 0xEF, 0x09,
+0x8C, 0x07, 0x30, 0x1F, 0xC0, 0x03, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x88, 0x39, 0x00, 0xE1, 0x80, 0xB0, 0x53, 0xB4, 0x0E, 0x46, 0x3B, 0x02,
+0xE1, 0x80, 0xB4, 0x03, 0x70, 0x4E, 0x48, 0x39, 0x00, 0xAD, 0x04, 0xB4, 0x03,
+0x10, 0x0E, 0x41, 0x38, 0x00, 0xED, 0x06, 0xB4, 0x02, 0x90, 0x0E, 0xC4, 0x39,
+0x00, 0x2F, 0x00, 0xF4, 0x83, 0x10, 0x4A, 0x00, 0x3B, 0x08, 0xED, 0x20, 0xAC,
+0x03, 0xF0, 0x0E, 0x40, 0x57, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x29, 0x04, 0xE1, 0x00, 0x30, 0x33, 0x18, 0x0E, 0x60, 0x33, 0xC0, 0xE9,
+0x10, 0xB4, 0x27, 0xD0, 0x1F, 0x72, 0x3B, 0x00, 0xAD, 0x80, 0xB4, 0x03, 0x98,
+0x0C, 0x40, 0x29, 0x20, 0xEC, 0x10, 0xA4, 0x02, 0xD0, 0x0E, 0x40, 0x2A, 0x00,
+0xED, 0x00, 0xB4, 0x03, 0x50, 0x0E, 0x48, 0x3B, 0xA0, 0xFD, 0x11, 0xC4, 0x07,
+0x10, 0x0E, 0x40, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28,
+0x63, 0x00, 0xC1, 0x20, 0x34, 0x8B, 0x90, 0x1C, 0x40, 0xB3, 0x01, 0x49, 0x20,
+0x34, 0x07, 0x50, 0x2C, 0x40, 0x31, 0x00, 0x8D, 0x01, 0x34, 0x03, 0x94, 0x1C,
+0x64, 0x61, 0x00, 0x0D, 0x13, 0x74, 0x82, 0x90, 0x9C, 0x40, 0xF1, 0x00, 0x05,
+0x03, 0x34, 0x03, 0x11, 0x1C, 0x40, 0x33, 0x10, 0xCD, 0x03, 0x04, 0x0B, 0x58,
+0x0C, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x65,
+0x00, 0xC3, 0x04, 0x7C, 0x07, 0x10, 0x1F, 0x40, 0x37, 0x04, 0x8B, 0x01, 0x74,
+0x03, 0xF0, 0x0D, 0xD0, 0x37, 0x00, 0xDF, 0x11, 0xFC, 0x03, 0xB0, 0x2F, 0xC0,
+0x35, 0x11, 0x5F, 0x03, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0xA6, 0x08, 0x9D, 0x04,
+0xFC, 0x17, 0x54, 0x68, 0xC0, 0x37, 0x00, 0xDF, 0xC3, 0x45, 0x13, 0x15, 0x0D,
+0xC0, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x40,
+0xDF, 0x00, 0x7C, 0x13, 0x70, 0x8D, 0xC0, 0x37, 0x00, 0x97, 0x00, 0x7C, 0x23,
+0xF0, 0x4D, 0xD0, 0x27, 0x00, 0xDF, 0x02, 0x7C, 0x03, 0x70, 0x0D, 0x00, 0xB4,
+0x08, 0x5F, 0x80, 0x7C, 0x02, 0xB2, 0x09, 0xC0, 0x27, 0x06, 0x9F, 0x02, 0x3C,
+0x03, 0x50, 0x09, 0xC0, 0x33, 0x00, 0xDE, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0xC0,
+0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x27, 0x00, 0xFF,
+0x90, 0xCD, 0x03, 0xF1, 0x0F, 0xC1, 0x3E, 0x00, 0xBF, 0x01, 0xCE, 0x03, 0x32,
+0x0F, 0xE0, 0x2C, 0x00, 0xBF, 0x01, 0xFC, 0x03, 0xF0, 0x0F, 0xC1, 0x5F, 0x00,
+0x7F, 0x01, 0xFC, 0x23, 0x38, 0x05, 0xE0, 0x2C, 0x01, 0x38, 0x90, 0xFC, 0x03,
+0x30, 0x4B, 0xDD, 0x3D, 0x00, 0xF3, 0x10, 0xCC, 0x43, 0x78, 0x9F, 0xC0, 0x13,
+0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x56, 0x00, 0xDD, 0x49,
+0x44, 0x03, 0x70, 0x0C, 0x40, 0x74, 0x08, 0x9D, 0x00, 0x04, 0x03, 0xB0, 0x0D,
+0xC0, 0x66, 0x80, 0x9D, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0xC0, 0x15, 0x03, 0x1D,
+0x23, 0x5C, 0x02, 0xB0, 0x04, 0x44, 0x25, 0x00, 0x1D, 0x41, 0x74, 0x03, 0x70,
+0x09, 0x40, 0x34, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xD0, 0x1D, 0x40, 0x17, 0x02,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xA4, 0x01, 0xDD, 0x00, 0x44,
+0x07, 0xD0, 0x0D, 0x60, 0x36, 0x02, 0x9D, 0x04, 0x44, 0x03, 0x10, 0x0C, 0x48,
+0x34, 0x02, 0xDD, 0x06, 0x74, 0x03, 0xD0, 0x0D, 0x60, 0x07, 0x00, 0x9D, 0x44,
+0x74, 0x03, 0x93, 0x0D, 0x40, 0xA4, 0x00, 0x9D, 0x01, 0x74, 0x03, 0x10, 0x29,
+0x40, 0x34, 0x00, 0xC0, 0x00, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x07, 0x20, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0xDD, 0x20, 0x04, 0x03,
+0xD0, 0x0D, 0x40, 0x30, 0x80, 0x8D, 0x00, 0x45, 0x03, 0x99, 0x0C, 0x40, 0x30,
+0x80, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x01, 0x00, 0x8D, 0x00, 0x10,
+0x02, 0x90, 0x0C, 0x60, 0x11, 0x00, 0x0D, 0x00, 0x34, 0x03, 0x50, 0x08, 0x40,
+0x30, 0x40, 0xC1, 0x00, 0x24, 0x03, 0xD0, 0x08, 0x40, 0x43, 0xA1, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x26, 0x00, 0xDD, 0x00, 0x44, 0x03, 0xF8,
+0x0D, 0xC0, 0x36, 0x00, 0xDF, 0x40, 0xC6, 0x03, 0x32, 0x0F, 0x50, 0x24, 0x20,
+0x5D, 0x00, 0xBC, 0x03, 0xF0, 0x0F, 0xC0, 0x07, 0x00, 0x9D, 0x00, 0x78, 0x03,
+0x90, 0x0D, 0x40, 0x24, 0x08, 0x1F, 0x00, 0xFC, 0x03, 0x31, 0x05, 0xC0, 0x35,
+0x00, 0xF3, 0x00, 0xCC, 0x03, 0xF0, 0x0D, 0xC0, 0x03, 0xC4, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0xB8, 0x1F, 0x20, 0xFF, 0x00, 0xFC, 0x03, 0x7A, 0x0F,
+0xC0, 0x3F, 0x00, 0x7C, 0x00, 0xFC, 0x03, 0xF3, 0x0F, 0xC0, 0x2F, 0x00, 0x7F,
+0x00, 0xFC, 0x83, 0xF1, 0x0F, 0x80, 0x0D, 0x00, 0x3E, 0x00, 0xDC, 0x82, 0xF0,
+0x0F, 0xC0, 0x1F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x70, 0x07, 0x40, 0x3F, 0x00,
+0xF7, 0x00, 0xFC, 0x03, 0xF8, 0x0B, 0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x80, 0x5F, 0x00, 0x33, 0x8C, 0xCC, 0x10, 0x30, 0x1F, 0xC0,
+0x2F, 0x00, 0x33, 0x00, 0xCC, 0x02, 0x30, 0x1F, 0xE0, 0x7F, 0x00, 0xBB, 0x01,
+0xF4, 0x07, 0x70, 0x0B, 0xC0, 0x7C, 0x05, 0xFF, 0x42, 0xFC, 0x32, 0xF0, 0x4F,
+0xC8, 0x3F, 0x01, 0xFF, 0x01, 0xFC, 0x0C, 0x30, 0x4F, 0xC0, 0x4E, 0x00, 0xB3,
+0x00, 0x7C, 0x73, 0xF0, 0x4F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x08, 0x77, 0x00, 0x11, 0x0E, 0x6C, 0x24, 0x30, 0x1D, 0x40, 0x23,
+0x00, 0x51, 0x03, 0x14, 0x02, 0x50, 0x4D, 0x49, 0x33, 0x10, 0xC1, 0x10, 0x74,
+0x04, 0x10, 0xB9, 0xE0, 0xFE, 0x00, 0xFD, 0x0A, 0x74, 0x22, 0xD0, 0xBF, 0x40,
+0x3F, 0x0B, 0xCD, 0x00, 0x74, 0x00, 0x50, 0x3D, 0x40, 0x44, 0x00, 0x91, 0x0B,
+0xF4, 0x03, 0xD1, 0x1F, 0x40, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0xA0, 0x27, 0x00, 0x41, 0x00, 0x05, 0x00, 0x10, 0x0C, 0x40, 0x23, 0x00,
+0x81, 0x02, 0x04, 0x03, 0x10, 0x4C, 0x40, 0x33, 0x00, 0xC9, 0x00, 0x74, 0x03,
+0x54, 0x04, 0x50, 0x32, 0x20, 0xC5, 0x84, 0x34, 0x12, 0xD0, 0x0C, 0x40, 0x31,
+0x04, 0xCD, 0x00, 0x54, 0x11, 0x10, 0x2C, 0x48, 0x46, 0x80, 0xC1, 0x00, 0x14,
+0x13, 0xD0, 0x2C, 0x40, 0x47, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA8, 0x25, 0x02, 0x51, 0x00, 0x44, 0x08, 0x10, 0x0D, 0x40, 0x27, 0x02, 0x51,
+0x00, 0x54, 0x03, 0x50, 0x0D, 0x48, 0x37, 0x00, 0xD9, 0x03, 0x74, 0x18, 0x14,
+0x15, 0x50, 0x36, 0x00, 0xD9, 0x00, 0x70, 0x22, 0xD0, 0x0D, 0x40, 0x37, 0x20,
+0xDD, 0x00, 0x74, 0x09, 0x50, 0x0D, 0x40, 0x46, 0x40, 0xD1, 0x11, 0x74, 0x03,
+0xD1, 0x0D, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8,
+0x53, 0x01, 0x13, 0x10, 0x44, 0x0C, 0x30, 0x0D, 0xC0, 0x27, 0x40, 0x13, 0x80,
+0x44, 0x06, 0x34, 0x0D, 0x40, 0x37, 0x00, 0xDB, 0x01, 0x3C, 0x09, 0x70, 0x31,
+0x40, 0x36, 0x30, 0xDF, 0x00, 0x78, 0x02, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x7C, 0x0C, 0x30, 0x0D, 0xC0, 0x42, 0x10, 0xD3, 0x01, 0x7C, 0x03, 0xF1,
+0x0D, 0xC0, 0x03, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x7D,
+0x50, 0xEF, 0x10, 0xBC, 0x22, 0x70, 0x0F, 0xC0, 0x2B, 0x00, 0x9F, 0x00, 0xB8,
+0x26, 0xB0, 0x0F, 0x88, 0x3F, 0x00, 0xF7, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0,
+0x3F, 0x00, 0xFF, 0x20, 0xF8, 0x06, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x10,
+0xFC, 0x24, 0xF0, 0x0E, 0xC0, 0x0D, 0x28, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
+0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x08,
+0x1F, 0x00, 0x6C, 0x29, 0x30, 0x0D, 0xC0, 0x27, 0x01, 0xC7, 0x80, 0x4C, 0x03,
+0x34, 0x0D, 0xC0, 0x34, 0x00, 0xDF, 0x02, 0x4E, 0x08, 0x22, 0x05, 0xC8, 0x34,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xDF, 0x00, 0x6D,
+0x09, 0x70, 0x0D, 0xC0, 0x07, 0x00, 0xDF, 0x0A, 0x7C, 0x03, 0xF1, 0x0D, 0xC4,
+0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x24, 0x00, 0xDD,
+0x00, 0x45, 0x03, 0x10, 0x0D, 0x40, 0xA7, 0x00, 0xD1, 0x00, 0x4D, 0x03, 0x10,
+0x0D, 0xC0, 0x76, 0x02, 0xD1, 0x00, 0x45, 0x01, 0xB0, 0x04, 0xC1, 0x3E, 0x00,
+0xFD, 0x00, 0x7C, 0x03, 0xC1, 0x1F, 0xC1, 0x3E, 0x00, 0xDD, 0x00, 0x04, 0x01,
+0x10, 0x0F, 0xC0, 0x45, 0x00, 0xDD, 0x41, 0xF4, 0x83, 0xD0, 0x5F, 0x40, 0x4F,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x22, 0x00, 0x8D, 0x01,
+0x04, 0x07, 0x10, 0x0C, 0x40, 0x32, 0x00, 0x05, 0x00, 0x04, 0x03, 0xD0, 0x0C,
+0x40, 0xF4, 0x00, 0xC5, 0x00, 0x04, 0x06, 0x18, 0x08, 0x40, 0x70, 0x00, 0xCD,
+0x80, 0x34, 0x03, 0xC0, 0x1C, 0x40, 0x30, 0x08, 0xCD, 0xC0, 0x04, 0x01, 0x50,
+0x0C, 0x40, 0x53, 0x00, 0xCD, 0x00, 0x14, 0x03, 0xD0, 0x0C, 0x40, 0x1F, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x68, 0x00, 0x2D, 0x19, 0x04,
+0x07, 0x10, 0x1E, 0x40, 0x6B, 0x00, 0x61, 0x01, 0xA4, 0x27, 0x90, 0x1E, 0x40,
+0x7A, 0x00, 0xE1, 0x01, 0xC4, 0x04, 0x99, 0x9A, 0x40, 0x7A, 0x00, 0xED, 0x81,
+0x94, 0x07, 0xD0, 0x9E, 0x40, 0x7A, 0x00, 0xED, 0x81, 0x84, 0x07, 0x10, 0x1E,
+0x40, 0x49, 0x00, 0x6D, 0x01, 0xB4, 0x27, 0xD0, 0x1E, 0x40, 0x13, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x20, 0x00, 0xDF, 0x00, 0x04, 0x03,
+0x30, 0x0C, 0xC0, 0x22, 0x02, 0x85, 0x08, 0x04, 0x23, 0xF0, 0x0D, 0x40, 0x30,
+0x04, 0xC7, 0x08, 0x04, 0x42, 0x30, 0x00, 0xC0, 0x30, 0x04, 0xCF, 0x00, 0x34,
+0x02, 0xF0, 0x8C, 0xC0, 0x30, 0x00, 0xCF, 0x80, 0x4C, 0x01, 0x70, 0x0C, 0xC0,
+0x13, 0x84, 0xCF, 0x00, 0x1C, 0x17, 0xF0, 0x0C, 0xC0, 0x4B, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x2D, 0x00, 0x7F, 0x00, 0xDD, 0x03, 0xD0,
+0x0F, 0xC0, 0x2F, 0x80, 0x7F, 0x00, 0xDE, 0xA3, 0x70, 0x0F, 0xC8, 0x3F, 0x00,
+0xF7, 0x00, 0xBC, 0x22, 0xF0, 0x0A, 0xC0, 0x3F, 0x00, 0xFF, 0x08, 0xFC, 0x22,
+0xF0, 0xAE, 0xC2, 0x3F, 0x20, 0xFF, 0x08, 0xDC, 0x21, 0xF0, 0x0F, 0xC4, 0x0F,
+0x10, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x2F, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA8, 0x37, 0x00, 0x9F, 0x00, 0x4C, 0x00, 0x31, 0x0D,
+0xC0, 0x3F, 0x00, 0x1F, 0x00, 0x7C, 0x07, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x7C, 0x04, 0x30, 0x15, 0xC0, 0xB5, 0x04, 0xDF, 0x07, 0x6C, 0x03, 0xF0,
+0x5D, 0xC0, 0x36, 0x05, 0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC0, 0x53, 0x00,
+0xD1, 0x40, 0x78, 0x17, 0x34, 0x2D, 0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x98, 0x39, 0x00, 0xED, 0x00, 0x84, 0x02, 0x10, 0x0E, 0x40,
+0x3B, 0x90, 0xAC, 0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x3B, 0x10, 0xED, 0x20,
+0xB4, 0x00, 0x50, 0x0E, 0x40, 0x38, 0x01, 0xCD, 0x12, 0x84, 0x03, 0xD0, 0x0E,
+0x40, 0xB8, 0x00, 0xE7, 0x00, 0x9C, 0x03, 0xD0, 0x6E, 0x40, 0x0B, 0x00, 0xE1,
+0x00, 0xF4, 0x2B, 0x10, 0x0E, 0x40, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x00, 0xE9, 0x00, 0x8D, 0x03, 0x24, 0x05, 0x94, 0x1E, 0x40, 0x7B,
+0x10, 0xEC, 0x03, 0xB4, 0x07, 0x90, 0x1E, 0x40, 0x7B, 0x20, 0xED, 0x01, 0xF6,
+0x07, 0x10, 0x14, 0x41, 0x79, 0x02, 0xED, 0x05, 0x84, 0x07, 0x50, 0xDC, 0x40,
+0x7A, 0x00, 0xED, 0x01, 0x96, 0x05, 0xD0, 0x1E, 0x40, 0x5B, 0x80, 0xE1, 0x41,
+0xB4, 0x17, 0x10, 0x9E, 0x40, 0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x20, 0x63, 0x00, 0xCD, 0x00, 0x05, 0x13, 0x90, 0x0C, 0x40, 0x33, 0x02,
+0xC9, 0x00, 0x34, 0x03, 0x90, 0x0C, 0x42, 0x33, 0x00, 0x4C, 0x08, 0x34, 0x0B,
+0x50, 0x3C, 0x40, 0x30, 0x00, 0xCC, 0x00, 0x04, 0x07, 0xD1, 0x0C, 0x40, 0x32,
+0x20, 0xC5, 0x00, 0x54, 0x0B, 0xD0, 0x0C, 0x44, 0x23, 0x00, 0xC1, 0x07, 0x34,
+0x03, 0x10, 0x0C, 0x40, 0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+0xA8, 0x1D, 0x00, 0x7F, 0x0A, 0xEC, 0x1D, 0xB0, 0x05, 0x40, 0x57, 0x00, 0x7F,
+0x0A, 0x7C, 0x01, 0xB4, 0x05, 0xC0, 0x17, 0x10, 0x7D, 0x02, 0xFC, 0x21, 0x30,
+0x27, 0xC0, 0x15, 0x10, 0x5F, 0x00, 0x4C, 0x15, 0xF0, 0x05, 0xC0, 0x16, 0x80,
+0x5F, 0xC0, 0xDC, 0x01, 0xF1, 0x05, 0xC0, 0x1F, 0x02, 0x73, 0x02, 0x74, 0x01,
+0x30, 0x05, 0xC0, 0x5F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00,
+0x07, 0x00, 0x0F, 0x02, 0x3C, 0x00, 0x70, 0x01, 0xC8, 0x07, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x10, 0x7C, 0x20, 0xF0, 0x41,
+0xC0, 0x03, 0x80, 0x1F, 0x00, 0x5D, 0x00, 0xF0, 0x01, 0xC0, 0x01, 0x80, 0x1F,
+0x02, 0x5C, 0x40, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x1F, 0x08, 0x7C, 0x00, 0xF0,
+0x01, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27,
+0x00, 0x9F, 0x00, 0x4C, 0x22, 0x34, 0x09, 0xC0, 0x23, 0x00, 0x83, 0x00, 0x4C,
+0x02, 0xF0, 0x09, 0xC0, 0x67, 0x00, 0x9F, 0x00, 0x4C, 0xA2, 0xF0, 0x09, 0xC0,
+0x67, 0x00, 0x9B, 0x80, 0x7C, 0x02, 0xD2, 0x89, 0xC0, 0x27, 0x00, 0x93, 0x84,
+0x7C, 0x02, 0xB0, 0x08, 0xC0, 0x64, 0x00, 0x8F, 0x01, 0x6C, 0x02, 0xF0, 0x09,
+0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00,
+0x9D, 0x03, 0x44, 0x06, 0x10, 0x09, 0x40, 0x27, 0x00, 0x95, 0x00, 0x6C, 0x22,
+0xD0, 0x09, 0x40, 0xA7, 0x00, 0x8D, 0x00, 0x6C, 0x06, 0xD0, 0x09, 0x40, 0x27,
+0x00, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x09, 0xC4, 0x27, 0x00, 0x91, 0x03, 0x74,
+0x02, 0x50, 0x09, 0xC0, 0x66, 0x02, 0x9D, 0x09, 0x6C, 0x02, 0xD0, 0x09, 0x40,
+0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D,
+0x04, 0x44, 0x02, 0x19, 0x09, 0x40, 0x27, 0x00, 0x91, 0x00, 0x44, 0x02, 0x58,
+0x09, 0x40, 0x27, 0x05, 0x9D, 0x00, 0x66, 0x02, 0x52, 0x8D, 0x40, 0x27, 0x01,
+0x99, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x26, 0x00, 0x90, 0x02, 0x74, 0x02,
+0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0xC0, 0x44, 0x82, 0xD0, 0x09, 0x40, 0x63,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0xA0, 0x00, 0x8D, 0x04,
+0x04, 0x12, 0x10, 0x08, 0x40, 0x33, 0x01, 0x85, 0x04, 0x24, 0x12, 0xD0, 0x08,
+0x40, 0x23, 0x00, 0x9D, 0x00, 0x04, 0x02, 0xD0, 0x48, 0x40, 0x23, 0x01, 0x81,
+0x04, 0x34, 0x12, 0xD0, 0x08, 0x48, 0x21, 0x01, 0x81, 0x00, 0x34, 0x22, 0x50,
+0x08, 0x4A, 0x22, 0x00, 0x8D, 0x04, 0x26, 0x12, 0xD0, 0x48, 0x48, 0x43, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x5F, 0x0A, 0x4C,
+0x00, 0x31, 0x01, 0x40, 0x87, 0x02, 0x13, 0x00, 0x0C, 0x28, 0x70, 0xA1, 0xC0,
+0x87, 0x02, 0x1F, 0x0A, 0x64, 0x00, 0x70, 0x01, 0xC4, 0x07, 0x00, 0x1B, 0x0A,
+0x74, 0x28, 0xF0, 0x41, 0x41, 0x87, 0x42, 0x13, 0x0A, 0x7C, 0x08, 0xB0, 0x41,
+0xC1, 0x04, 0x00, 0x1F, 0x00, 0x4C, 0x28, 0xF0, 0x01, 0xC0, 0x77, 0xC0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x98, 0x6F, 0x00, 0xBF, 0x28, 0xF5, 0x22,
+0xF0, 0x09, 0xC0, 0x2F, 0x02, 0xBF, 0x28, 0xFC, 0x22, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0xBE, 0x40, 0xBD, 0x02, 0xF0, 0x8B, 0xC0, 0x27, 0x02, 0x9F, 0x08, 0xFC,
+0x22, 0xF0, 0x09, 0xC2, 0x27, 0x02, 0x9F, 0x00, 0xFC, 0x12, 0xF0, 0x09, 0xC0,
+0x2F, 0x00, 0xBF, 0x08, 0x7C, 0x22, 0xF0, 0x89, 0xC0, 0x67, 0x60, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x27, 0x00, 0xBF, 0x14, 0xCC, 0x12, 0xF0,
+0x09, 0xC0, 0x2F, 0x00, 0x93, 0x00, 0xFC, 0x12, 0x70, 0x0B, 0xC0, 0x2F, 0x02,
+0x8F, 0x00, 0xBC, 0x02, 0x32, 0x0B, 0xC0, 0x2C, 0x01, 0x9F, 0x14, 0x4C, 0x32,
+0x30, 0x0B, 0xC0, 0x24, 0x00, 0xB3, 0x08, 0x4C, 0x02, 0xF2, 0x49, 0xC1, 0x2F,
+0x00, 0xBF, 0x00, 0x7C, 0x02, 0x20, 0x0B, 0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0x08, 0x57, 0x05, 0x1D, 0x04, 0x44, 0x20, 0xD0, 0x01,
+0x48, 0x07, 0x04, 0x1B, 0x08, 0x74, 0x50, 0x10, 0x41, 0x40, 0x07, 0x81, 0x1D,
+0x50, 0x74, 0x00, 0x11, 0x81, 0xC0, 0x06, 0x00, 0x1D, 0x04, 0x45, 0x30, 0xB0,
+0x21, 0xC0, 0x06, 0x0C, 0x11, 0x00, 0x44, 0x50, 0xD0, 0x01, 0x40, 0x07, 0x00,
+0x1D, 0x02, 0x74, 0x40, 0x10, 0x01, 0xC0, 0x72, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x14, 0x05, 0x02, 0xD0, 0x08, 0x40,
+0x23, 0x02, 0x81, 0x01, 0x14, 0x32, 0x51, 0x48, 0x41, 0x23, 0x01, 0x8D, 0x05,
+0x74, 0x03, 0x10, 0x08, 0x40, 0x30, 0x02, 0x89, 0x14, 0x04, 0x12, 0x10, 0x88,
+0x40, 0x20, 0x42, 0x81, 0x00, 0x24, 0x12, 0x90, 0x08, 0x40, 0x23, 0x80, 0x8D,
+0x09, 0x34, 0x02, 0x14, 0x08, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA8, 0x25, 0x02, 0x9D, 0x04, 0x44, 0x12, 0xD0, 0x09, 0x40, 0x27,
+0x02, 0x99, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74,
+0x02, 0x10, 0x29, 0x40, 0x24, 0x00, 0x8D, 0x00, 0x44, 0x22, 0x94, 0x09, 0x40,
+0x26, 0x00, 0xD1, 0x00, 0x64, 0x02, 0xD0, 0x09, 0x40, 0xA7, 0x00, 0x9D, 0x08,
+0x74, 0x02, 0x11, 0x09, 0x40, 0x62, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x08, 0x2D, 0x10, 0x9F, 0x01, 0x4C, 0x06, 0xF0, 0x09, 0x40, 0x27, 0x00,
+0x93, 0x01, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x00, 0x9D, 0x00, 0x3C, 0x46,
+0x34, 0x09, 0x50, 0x24, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x24,
+0x00, 0x93, 0x00, 0x6D, 0x6E, 0xF0, 0x09, 0xC0, 0xA7, 0x00, 0x9F, 0x02, 0x78,
+0x02, 0x30, 0x09, 0xC0, 0x14, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x00, 0x65, 0x00, 0x9F, 0x01, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F,
+0x83, 0x7E, 0x0E, 0xF0, 0x09, 0xC0, 0x27, 0x08, 0x9F, 0x49, 0x7C, 0x26, 0xF0,
+0x49, 0xC0, 0x27, 0x08, 0x9F, 0x20, 0x3C, 0x06, 0x71, 0x09, 0xC0, 0x23, 0x00,
+0x9F, 0x00, 0x5C, 0x82, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x01, 0x3C, 0x02,
+0xF0, 0x09, 0xC0, 0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08,
+0x85, 0x00, 0x0F, 0x01, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x01, 0x1F, 0x00,
+0x7E, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x20, 0x1B, 0x00, 0x4F, 0x00, 0xB0, 0x01,
+0xC0, 0x06, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x70, 0x00, 0xC0, 0x07, 0x00, 0x1F,
+0x00, 0x6C, 0x00, 0xF0, 0x01, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0,
+0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x14,
+0x00, 0x7D, 0x00, 0x74, 0x81, 0xD0, 0x05, 0xC0, 0x9D, 0x04, 0x5D, 0x00, 0x7E,
+0x01, 0xD0, 0x15, 0x40, 0x5F, 0x01, 0x51, 0x00, 0x44, 0x01, 0x14, 0x04, 0xD0,
+0x16, 0x00, 0x5D, 0x00, 0x74, 0x01, 0x10, 0x45, 0xC0, 0x14, 0x00, 0x7D, 0x10,
+0x44, 0x01, 0xD0, 0x05, 0x44, 0x17, 0x20, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x04,
+0x40, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00,
+0xCD, 0x00, 0x34, 0x02, 0xDA, 0x0C, 0x48, 0x35, 0x20, 0xCD, 0x00, 0x74, 0x03,
+0xD0, 0x9C, 0x40, 0x33, 0x80, 0xC9, 0x20, 0x10, 0x02, 0x90, 0x8C, 0x40, 0x22,
+0x00, 0xCD, 0x00, 0x36, 0x03, 0x18, 0x08, 0x40, 0x31, 0x00, 0xDD, 0x01, 0x24,
+0x83, 0xD0, 0x0C, 0x40, 0x23, 0x82, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x08, 0x40,
+0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x81, 0xED,
+0x00, 0xB4, 0x43, 0xD9, 0x0E, 0x40, 0x39, 0x00, 0xED, 0x00, 0x94, 0x43, 0xD0,
+0x0E, 0x40, 0x6B, 0x01, 0xF1, 0x05, 0xD4, 0x03, 0x10, 0x0F, 0x50, 0x3A, 0x00,
+0xED, 0x08, 0x34, 0x03, 0x18, 0x0E, 0x40, 0x39, 0x08, 0xED, 0x00, 0xA4, 0x03,
+0xC0, 0x0E, 0x40, 0x3B, 0x80, 0xED, 0x00, 0xB4, 0x13, 0xD0, 0x0E, 0x40, 0x13,
+0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0xF8, 0x00, 0x2F, 0x01,
+0xBC, 0x07, 0xF0, 0x1E, 0xC0, 0x59, 0x00, 0xEF, 0x01, 0xB4, 0x06, 0xF0, 0x1E,
+0xE4, 0xFB, 0x00, 0xEB, 0x11, 0x94, 0x07, 0xB2, 0x1E, 0xD0, 0x7A, 0x00, 0xEF,
+0x15, 0xBC, 0x5F, 0x70, 0x1C, 0xC0, 0x79, 0x00, 0xFF, 0x01, 0xAC, 0x07, 0xE0,
+0x1E, 0xC0, 0x7B, 0x00, 0xEF, 0x01, 0xB4, 0x37, 0xF0, 0x1A, 0xC0, 0x53, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0xDF, 0x00, 0x7C,
+0x03, 0xF0, 0x0D, 0xC4, 0x15, 0x10, 0xDF, 0x00, 0x7C, 0x0A, 0xB0, 0x0D, 0xC0,
+0x03, 0x00, 0xDF, 0x08, 0x6C, 0x03, 0xF2, 0x0C, 0xD0, 0x37, 0x00, 0xDF, 0x20,
+0x7C, 0x03, 0xF4, 0x0D, 0xC0, 0x34, 0x07, 0x5F, 0x00, 0x5C, 0x03, 0xF0, 0x0D,
+0xC8, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x23, 0xF0, 0x0D, 0xC0, 0x43, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x7B, 0x00, 0xF3, 0x01, 0xCC, 0x07,
+0xFA, 0x8F, 0xC0, 0x6F, 0x02, 0xF3, 0x09, 0x8C, 0x0F, 0x30, 0x1F, 0xC0, 0x7F,
+0x00, 0xF3, 0x01, 0xEC, 0x07, 0x30, 0x1E, 0xC0, 0x7C, 0x30, 0xF7, 0x41, 0xCC,
+0x07, 0x70, 0x1F, 0xC4, 0x7C, 0x00, 0xF3, 0x01, 0xDC, 0x47, 0x72, 0x1F, 0xC8,
+0x7B, 0x22, 0xF7, 0xA1, 0xFC, 0x87, 0x32, 0x1B, 0xC2, 0x08, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x39, 0x00, 0x61, 0x40, 0x84, 0x03, 0x78,
+0x0E, 0x44, 0x2B, 0x10, 0xE1, 0x20, 0xAC, 0x03, 0x10, 0x0E, 0x40, 0x3B, 0x00,
+0xF1, 0x00, 0x84, 0x13, 0x50, 0x4E, 0x44, 0x39, 0x00, 0xF1, 0x00, 0xC4, 0x03,
+0x10, 0x0E, 0xC0, 0x3E, 0x02, 0xE1, 0x00, 0x86, 0x03, 0xF0, 0x0E, 0x40, 0x3B,
+0x40, 0xE5, 0x00, 0x34, 0x03, 0x10, 0x0E, 0x40, 0x54, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x25, 0x00, 0x84, 0x03, 0x50, 0x8E,
+0x40, 0x0B, 0x00, 0xC0, 0x20, 0x84, 0x02, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xE1,
+0x02, 0xC4, 0x03, 0x12, 0x0E, 0x60, 0x38, 0x00, 0xE5, 0x00, 0x84, 0x03, 0x10,
+0x0E, 0x40, 0x39, 0x00, 0xE1, 0x00, 0xD4, 0x03, 0x10, 0x0E, 0x40, 0x3F, 0x40,
+0xED, 0x00, 0x34, 0x03, 0x10, 0x08, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x06, 0x28, 0x33, 0x00, 0x41, 0x03, 0x05, 0x1B, 0x50, 0x0C, 0x40,
+0x43, 0x40, 0xC1, 0x02, 0x24, 0x02, 0x10, 0x0C, 0x40, 0x13, 0x00, 0xC1, 0x41,
+0x04, 0x03, 0x51, 0x0C, 0x60, 0x31, 0x00, 0xC1, 0x00, 0x05, 0x03, 0x10, 0x0C,
+0x40, 0x33, 0x00, 0x41, 0x00, 0x04, 0x0B, 0xD0, 0x0C, 0x40, 0x33, 0x02, 0x8D,
+0x42, 0x34, 0x03, 0x14, 0x0C, 0x50, 0x18, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA8, 0xB5, 0x42, 0xD7, 0x06, 0x0C, 0x03, 0x70, 0x0D, 0xC0, 0x27,
+0x04, 0xD3, 0x00, 0x4C, 0x02, 0x34, 0x0D, 0xC0, 0x3F, 0x40, 0xF1, 0x01, 0x0C,
+0x07, 0x30, 0xAC, 0x40, 0x30, 0x00, 0xF7, 0x00, 0xCC, 0x03, 0x30, 0x0D, 0xC0,
+0x3D, 0x00, 0xD3, 0x00, 0xDC, 0x23, 0x70, 0x0D, 0x40, 0xF7, 0x42, 0xDF, 0x02,
+0xFC, 0x03, 0x30, 0x09, 0xC0, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x37, 0x00, 0x9F, 0x10, 0x7C, 0x03, 0x70, 0x0D, 0xC0, 0xA7, 0x00,
+0xDF, 0x01, 0x5C, 0x02, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x08, 0x5C, 0x63,
+0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x36,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x7C,
+0x03, 0xF0, 0x09, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x08, 0x3F, 0x00, 0x33, 0x00, 0xFC, 0x03, 0x30, 0x0F, 0xC0, 0x07, 0x00, 0xF7,
+0x10, 0xFC, 0x02, 0x30, 0x5F, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0x30,
+0x9B, 0xC0, 0x34, 0x00, 0xE3, 0x00, 0xCC, 0x03, 0x30, 0x1D, 0xC0, 0x3F, 0x00,
+0xB3, 0x01, 0xFE, 0x03, 0xF0, 0x0F, 0xCA, 0xBF, 0x00, 0xFE, 0x10, 0xF4, 0x03,
+0x30, 0x5A, 0x80, 0x00, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20,
+0x36, 0x00, 0x95, 0x00, 0x74, 0x07, 0x10, 0x0D, 0x40, 0xC7, 0x04, 0xD1, 0x00,
+0x74, 0x26, 0x10, 0x1D, 0x40, 0x07, 0x00, 0xD9, 0x00, 0x74, 0x03, 0x10, 0x1D,
+0x50, 0x35, 0x00, 0xDB, 0x00, 0x44, 0x03, 0x10, 0x0D, 0x40, 0x37, 0x00, 0x91,
+0x03, 0x76, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x20, 0xDD, 0x09, 0x74, 0x03, 0x10,
+0x09, 0xC0, 0x05, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x32,
+0x00, 0xD1, 0x01, 0x74, 0x23, 0x10, 0x0D, 0x40, 0x63, 0x00, 0xD5, 0x00, 0x34,
+0x03, 0x10, 0x09, 0x40, 0x37, 0x02, 0xDD, 0x00, 0x76, 0x07, 0x10, 0x0D, 0x40,
+0x74, 0x20, 0xD1, 0x00, 0x04, 0x03, 0x10, 0x4D, 0x40, 0x33, 0x28, 0xD1, 0x04,
+0x74, 0x03, 0xD0, 0x0D, 0x40, 0x36, 0x00, 0xDD, 0x00, 0x24, 0x03, 0x00, 0x09,
+0x40, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00,
+0x05, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x03, 0x00, 0xC1, 0x00, 0x34, 0x03,
+0x10, 0x08, 0x40, 0x33, 0x00, 0xC9, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x30,
+0x00, 0xC9, 0x00, 0x05, 0x03, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xC1, 0x00, 0x34,
+0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCC, 0x00, 0x34, 0x23, 0x10, 0x08, 0x40,
+0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x3E, 0x00, 0x03,
+0x00, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x07, 0x00, 0xD7, 0x00, 0xFC, 0x02, 0x14,
+0x09, 0xC0, 0x23, 0x10, 0xFF, 0x00, 0x7C, 0x03, 0x34, 0x0D, 0xC0, 0x34, 0x00,
+0xF3, 0x00, 0xCC, 0x03, 0x30, 0x0D, 0xC0, 0x3F, 0x00, 0xC3, 0x20, 0x74, 0x03,
+0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0xFC, 0x03, 0x30, 0x09, 0xC0, 0x01,
+0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0x3F, 0x00,
+0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0B,
+0x80, 0x0F, 0x00, 0xFA, 0x00, 0xBC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFF,
+0x00, 0xFC, 0x03, 0xF0, 0x0F, 0x80, 0x3F, 0x08, 0xFF, 0x00, 0xB0, 0x03, 0xF0,
+0x0F, 0xC8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x13, 0xF0, 0x0B, 0xC0, 0x15, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xBF, 0x8C, 0xCC,
+0x12, 0x32, 0xCF, 0xC0, 0x5E, 0x22, 0xB3, 0x21, 0xFC, 0x06, 0xF0, 0xCF, 0xC4,
+0x3D, 0x03, 0x23, 0x01, 0xFC, 0x23, 0xF0, 0x13, 0xC0, 0x3F, 0x00, 0xFF, 0x4C,
+0xCC, 0x06, 0xB0, 0x17, 0xD8, 0x5C, 0x00, 0xF7, 0x04, 0xAC, 0x04, 0xB0, 0x4F,
+0xC1, 0x7A, 0x08, 0x3F, 0x01, 0xDC, 0x30, 0xB0, 0x1B, 0xC4, 0x0F, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x77, 0x00, 0xDD, 0x0E, 0x44, 0x26,
+0x10, 0xEF, 0x40, 0x24, 0x01, 0xD1, 0x04, 0x74, 0x05, 0x70, 0x2F, 0x40, 0xBC,
+0x02, 0x91, 0x01, 0xF4, 0x1B, 0x90, 0x40, 0x40, 0xFF, 0x02, 0xFD, 0x08, 0x44,
+0xC3, 0x10, 0x19, 0x40, 0x34, 0x00, 0xF1, 0x01, 0x44, 0x05, 0x10, 0x3F, 0x40,
+0x74, 0x10, 0x1D, 0xA1, 0x34, 0x38, 0xB0, 0x1C, 0x40, 0x07, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x00, 0x8D, 0x04, 0x04, 0x02, 0x10,
+0x4C, 0x40, 0x32, 0x00, 0xC1, 0x10, 0x14, 0x02, 0xD0, 0x6C, 0x48, 0x33, 0x11,
+0x45, 0x00, 0x34, 0x0B, 0xD0, 0x00, 0x41, 0x33, 0x10, 0xC5, 0x44, 0x04, 0x13,
+0x90, 0x08, 0x40, 0x00, 0x05, 0xC9, 0x08, 0x64, 0x01, 0xD0, 0x0C, 0x40, 0x30,
+0x20, 0x05, 0x00, 0x14, 0x00, 0xD0, 0x04, 0x40, 0x47, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xDD, 0x20, 0x44, 0x03, 0x10, 0x0D,
+0x40, 0xA4, 0x0A, 0xD1, 0x04, 0x74, 0x01, 0x50, 0x0D, 0x40, 0x34, 0x40, 0x95,
+0x02, 0x74, 0x03, 0xD1, 0x19, 0x42, 0x37, 0x00, 0xCD, 0x00, 0x44, 0x03, 0x90,
+0x08, 0x40, 0xB4, 0x01, 0xD9, 0x00, 0x64, 0x05, 0xD0, 0x0D, 0x50, 0x36, 0x04,
+0x1D, 0x18, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA8, 0x37, 0x00, 0x9F, 0x09, 0x0C, 0x03, 0x34, 0x0D, 0xC0,
+0xD6, 0x08, 0x93, 0x01, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x10, 0xD7, 0x09,
+0x7C, 0x03, 0xF0, 0x21, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x4C, 0x83, 0xB1, 0x25,
+0xC9, 0x34, 0x40, 0xDB, 0x00, 0x6C, 0x17, 0xF0, 0x0D, 0xC0, 0xA6, 0x00, 0x1F,
+0x02, 0x5C, 0x16, 0xF0, 0x39, 0xC0, 0x03, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x80, 0x3D, 0x00, 0xEF, 0xC1, 0x7C, 0x02, 0xF2, 0x0E, 0xC0, 0x6F,
+0x00, 0xFF, 0x80, 0xFC, 0x8D, 0xF0, 0x0F, 0xC0, 0x3B, 0x00, 0xBB, 0x00, 0xFC,
+0x03, 0xB0, 0x0F, 0xC8, 0x3F, 0x00, 0xFF, 0x10, 0xDD, 0x83, 0x70, 0x0B, 0xC0,
+0x3F, 0x00, 0xF7, 0x00, 0xDC, 0x03, 0x30, 0x0F, 0xC0, 0x3D, 0x00, 0x3F, 0x01,
+0xFC, 0x0E, 0xB4, 0x2F, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x08, 0x35, 0x01, 0x93, 0x40, 0x7C, 0x03, 0x30, 0x8D, 0xC0, 0x35, 0x08,
+0xDF, 0x00, 0x4C, 0x0B, 0xF0, 0x0D, 0xC0, 0x34, 0x88, 0xDF, 0x00, 0x5C, 0x03,
+0x70, 0x25, 0xC0, 0x34, 0x08, 0xDF, 0x00, 0x7C, 0x03, 0x30, 0x2D, 0xE2, 0x27,
+0x00, 0xDF, 0x04, 0x7C, 0x09, 0xF0, 0x0D, 0xC1, 0x25, 0x00, 0x57, 0x00, 0x5C,
+0x02, 0x30, 0x05, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0xA0, 0x34, 0x00, 0xD1, 0x05, 0x74, 0x83, 0x18, 0x1F, 0x40, 0x24, 0x00, 0xDD,
+0x10, 0x44, 0x81, 0xD0, 0x0F, 0xC0, 0x3E, 0x88, 0x9F, 0x00, 0xC4, 0x03, 0x10,
+0x0D, 0x42, 0x3C, 0x00, 0xFD, 0x00, 0x74, 0x03, 0xB0, 0x09, 0x40, 0x77, 0x00,
+0xED, 0x00, 0x36, 0x05, 0x10, 0x6E, 0x40, 0xB4, 0x02, 0x1B, 0x11, 0x4C, 0x03,
+0x40, 0x05, 0xC0, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0,
+0xB2, 0x02, 0x81, 0x00, 0x34, 0x82, 0x10, 0x1C, 0x40, 0x65, 0x02, 0xCD, 0x01,
+0x04, 0x81, 0xD0, 0x0D, 0x40, 0x30, 0x08, 0x0D, 0x00, 0x14, 0x03, 0x52, 0x00,
+0x42, 0x32, 0x20, 0xCD, 0x43, 0x74, 0x02, 0x10, 0x0C, 0x40, 0x67, 0x02, 0xCD,
+0x03, 0x24, 0x03, 0x58, 0x0C, 0x44, 0x31, 0x08, 0x05, 0x01, 0x54, 0x11, 0x10,
+0x04, 0x40, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78,
+0x00, 0xA1, 0x01, 0xB4, 0x06, 0x10, 0x1C, 0x40, 0x68, 0x00, 0xED, 0x01, 0x84,
+0x05, 0xD0, 0x1E, 0x48, 0x7A, 0x00, 0x35, 0x01, 0x84, 0x27, 0x10, 0x96, 0x50,
+0x7A, 0x00, 0xED, 0x19, 0xB4, 0x03, 0x10, 0x1A, 0x40, 0x6B, 0x00, 0xED, 0x01,
+0xF4, 0x05, 0x19, 0x1C, 0x40, 0x7C, 0x00, 0x39, 0x81, 0xA4, 0x24, 0x10, 0x1E,
+0x40, 0x1A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00,
+0xC3, 0x04, 0x34, 0x02, 0x10, 0x0C, 0xC0, 0x31, 0x00, 0xDF, 0x00, 0x0D, 0x01,
+0xF8, 0x0D, 0xC0, 0x30, 0x02, 0x4D, 0x00, 0x5C, 0x07, 0x70, 0x2C, 0xC0, 0x32,
+0x02, 0xCF, 0x00, 0x7C, 0x23, 0x10, 0x08, 0x40, 0x23, 0x00, 0xCF, 0x14, 0x34,
+0x43, 0x70, 0x0C, 0xC0, 0x31, 0x00, 0xC7, 0x00, 0x1E, 0x03, 0x34, 0x04, 0xC2,
+0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x39, 0x42, 0xFF,
+0x00, 0xFC, 0x03, 0xF0, 0x2F, 0xC1, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x01, 0xF0,
+0x0F, 0x81, 0x3F, 0x00, 0xFF, 0x00, 0x7C, 0x2B, 0xB0, 0x0F, 0xC0, 0x3D, 0x04,
+0xFF, 0x10, 0xF4, 0x13, 0xF0, 0x09, 0xC0, 0x2F, 0x00, 0xFF, 0x10, 0x7C, 0x21,
+0x70, 0x0F, 0xC0, 0x1F, 0x10, 0xEF, 0x00, 0xDC, 0x03, 0xF0, 0x07, 0xC0, 0x0B,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00, 0x9F, 0x00,
+0x4C, 0x03, 0xF0, 0x6D, 0xC0, 0x27, 0x10, 0xDF, 0x00, 0x7C, 0x03, 0xB0, 0x0D,
+0xC0, 0x37, 0x05, 0x57, 0x00, 0x5C, 0x37, 0x34, 0x08, 0xC0, 0x36, 0x01, 0xDF,
+0x12, 0x4D, 0x03, 0x70, 0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF2,
+0x4C, 0xC1, 0x66, 0x00, 0x9B, 0x01, 0x4C, 0x01, 0xB0, 0x05, 0xC0, 0x57, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xBD, 0x04, 0x85,
+0x0A, 0xD0, 0x0E, 0x40, 0x2B, 0x00, 0xED, 0x00, 0xB4, 0x01, 0x10, 0x8E, 0x40,
+0x3B, 0x01, 0x6D, 0x00, 0x9C, 0x13, 0x10, 0x0E, 0x40, 0x38, 0x03, 0xE7, 0x04,
+0x84, 0x03, 0xD0, 0x0A, 0x40, 0x2B, 0x08, 0xED, 0x14, 0xB4, 0x03, 0x70, 0x4E,
+0xC2, 0x3A, 0x40, 0x23, 0x00, 0x85, 0x00, 0xB0, 0x0E, 0x40, 0x4B, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x00, 0xED, 0x09, 0xA4, 0x17,
+0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07, 0x90, 0x5E, 0x40, 0x7B,
+0x02, 0xED, 0x31, 0x16, 0x07, 0x10, 0x1F, 0x42, 0x7A, 0x00, 0xE5, 0x01, 0x84,
+0x07, 0xD0, 0x1E, 0x40, 0x6B, 0x00, 0xED, 0x05, 0xB4, 0x07, 0x50, 0xDE, 0x40,
+0x69, 0x00, 0xE9, 0x81, 0x84, 0x87, 0x90, 0x16, 0x40, 0x0F, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x04, 0x03, 0xD0,
+0x0C, 0x40, 0x23, 0x20, 0xDD, 0x40, 0x34, 0x45, 0x10, 0x0C, 0x40, 0x37, 0x08,
+0xCD, 0x06, 0x14, 0x03, 0x10, 0xBC, 0x40, 0x30, 0x00, 0xD5, 0x20, 0x04, 0x07,
+0xD0, 0x18, 0x40, 0x23, 0x00, 0xCD, 0x00, 0x34, 0x01, 0x50, 0x0C, 0x40, 0x53,
+0x30, 0xC1, 0x08, 0x04, 0x0B, 0x90, 0x04, 0x40, 0x4B, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x17, 0x88, 0x15, 0x00, 0x5F, 0x00, 0x6C, 0x41, 0xF0, 0x05,
+0xC0, 0x1F, 0x00, 0x5F, 0x00, 0xBC, 0x4D, 0xB0, 0x05, 0xC0, 0x17, 0x00, 0x6F,
+0x01, 0x5C, 0x01, 0x30, 0x37, 0xC0, 0x16, 0x00, 0x57, 0x80, 0x4C, 0x91, 0xF0,
+0x47, 0xC0, 0x9F, 0x00, 0x5F, 0x00, 0xBC, 0x15, 0x70, 0x04, 0xC0, 0x5D, 0x0C,
+0x7B, 0x03, 0xCC, 0x09, 0xA0, 0x07, 0xC0, 0x5F, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x00, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x40, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xF0, 0x01, 0xC1, 0x07, 0x00, 0x17, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x07, 0x00, 0x0F, 0x02, 0x7C, 0x40, 0x70, 0x21, 0x80, 0x86, 0x00, 0x17,
+0x12, 0x3C, 0x10, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x27, 0x08, 0x8F, 0x40, 0x4D, 0x16, 0xF0, 0x99, 0xC0, 0xE7,
+0x00, 0x93, 0x09, 0x4D, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x5C,
+0x02, 0xF0, 0x29, 0xC0, 0x23, 0x00, 0x97, 0x00, 0x5C, 0x02, 0x34, 0x09, 0xC0,
+0x64, 0x06, 0x93, 0x03, 0x5C, 0xA2, 0x71, 0x99, 0xC0, 0x24, 0x00, 0x9F, 0x01,
+0x7C, 0x06, 0x30, 0x09, 0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x20, 0xA6, 0x00, 0xBD, 0x40, 0xC4, 0x06, 0x70, 0x09, 0x40, 0x63, 0x00,
+0x91, 0x01, 0x44, 0x02, 0x18, 0x09, 0x44, 0x27, 0x00, 0x99, 0x00, 0x44, 0x02,
+0xD0, 0x28, 0x40, 0x24, 0x08, 0x93, 0x20, 0x04, 0x02, 0x90, 0x08, 0x40, 0x60,
+0x00, 0x91, 0x04, 0x44, 0x4E, 0x10, 0x09, 0x50, 0x25, 0x10, 0x9D, 0x06, 0x74,
+0x06, 0x50, 0x09, 0x42, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x24, 0x10, 0x9D, 0x00, 0x44, 0x0A, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x91,
+0x80, 0x44, 0x03, 0x10, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x54, 0x02, 0xD0,
+0x29, 0x40, 0x25, 0x00, 0x95, 0x00, 0x54, 0x02, 0x90, 0x09, 0x40, 0x24, 0x00,
+0x91, 0x00, 0x54, 0x02, 0x50, 0x29, 0x40, 0x24, 0x30, 0x9D, 0x08, 0x74, 0x52,
+0x10, 0x0D, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22,
+0x30, 0x00, 0x8D, 0x02, 0x04, 0x02, 0x58, 0x68, 0x40, 0xA7, 0x00, 0x81, 0x02,
+0x44, 0x0A, 0x10, 0x88, 0x40, 0x23, 0x02, 0x99, 0x00, 0x04, 0x22, 0xD0, 0x89,
+0x40, 0x20, 0x00, 0x89, 0x08, 0x44, 0x22, 0x90, 0x29, 0x40, 0xA4, 0x00, 0x81,
+0x00, 0x04, 0x02, 0x12, 0x08, 0x40, 0x21, 0x00, 0x8D, 0x00, 0x34, 0x22, 0x54,
+0x28, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x30, 0x06,
+0x00, 0x1F, 0x01, 0x4C, 0x04, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x13, 0x00, 0x0C,
+0x00, 0x14, 0x61, 0xC1, 0x87, 0x0D, 0x17, 0x00, 0x5C, 0x58, 0xF1, 0x21, 0xC0,
+0x05, 0x05, 0x07, 0x16, 0x5C, 0x88, 0x30, 0x01, 0xD0, 0x04, 0x40, 0x13, 0x54,
+0x5C, 0x80, 0x78, 0x41, 0xC1, 0x14, 0x10, 0x1F, 0x00, 0x3C, 0x58, 0x30, 0x01,
+0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x38, 0x27, 0x08,
+0xBF, 0x03, 0xFC, 0x0A, 0xF0, 0x99, 0xC0, 0x6F, 0x08, 0xBF, 0x01, 0xFC, 0x06,
+0xF0, 0x49, 0xC0, 0x27, 0x09, 0xB7, 0x00, 0x7C, 0x12, 0xF0, 0x4B, 0xC2, 0x25,
+0x00, 0x97, 0x04, 0xFC, 0x12, 0x70, 0x1B, 0xC0, 0x6F, 0x30, 0x9F, 0x00, 0xFC,
+0x02, 0xF8, 0x09, 0xD2, 0x2B, 0x80, 0xAF, 0x00, 0xFC, 0x12, 0xF0, 0x1B, 0xC0,
+0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2B, 0x00, 0xBF,
+0x13, 0xFC, 0x46, 0xF0, 0x0B, 0xC0, 0xAC, 0x00, 0xBF, 0x00, 0x7C, 0x0A, 0x30,
+0xC9, 0xC0, 0x26, 0x00, 0x9B, 0x00, 0x7C, 0x22, 0xF0, 0x0B, 0xC0, 0x24, 0x05,
+0xBF, 0x0C, 0x49, 0x02, 0xF2, 0x29, 0xC2, 0xAF, 0x00, 0xAF, 0x04, 0xFC, 0x02,
+0xF0, 0x4B, 0xC0, 0x2C, 0x00, 0xBF, 0x00, 0xFC, 0x22, 0xB0, 0x09, 0xC0, 0x67,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00, 0x1D, 0x07,
+0x74, 0x88, 0xD0, 0x51, 0x40, 0x44, 0x20, 0x1D, 0x05, 0x74, 0x04, 0x10, 0xC1,
+0x48, 0x84, 0x04, 0x11, 0x00, 0x74, 0x20, 0xD0, 0x45, 0x53, 0x04, 0x00, 0x1D,
+0x0C, 0x44, 0x40, 0xD0, 0x14, 0x40, 0x47, 0x00, 0x1D, 0x00, 0x74, 0x00, 0x10,
+0x81, 0x40, 0x14, 0x20, 0x5D, 0x20, 0x74, 0x20, 0x14, 0x11, 0x40, 0x73, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x04, 0x34,
+0x02, 0xD0, 0x88, 0x41, 0x20, 0x00, 0x8D, 0x10, 0x34, 0x02, 0x10, 0x48, 0x40,
+0x22, 0x03, 0x89, 0x00, 0x34, 0x02, 0xD1, 0x48, 0x40, 0x20, 0x00, 0x8D, 0x04,
+0x26, 0x12, 0xD0, 0x08, 0x40, 0x23, 0x10, 0x8D, 0x08, 0x34, 0x02, 0xDC, 0x08,
+0x40, 0x20, 0x10, 0x8D, 0x00, 0x34, 0x02, 0x94, 0x48, 0x41, 0x43, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x20, 0x74, 0x82,
+0xD0, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x04, 0x34, 0x02, 0x10, 0x09, 0x40, 0x20,
+0x00, 0x91, 0x10, 0x74, 0x02, 0xD0, 0x88, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x66,
+0x82, 0xD0, 0x89, 0x66, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x51, 0x09, 0x58,
+0x24, 0x00, 0x9D, 0x01, 0x74, 0x2A, 0x10, 0x69, 0x40, 0x63, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x25, 0x00, 0xBF, 0x01, 0x7C, 0x06, 0xF0,
+0x0B, 0xD0, 0x2C, 0x03, 0xBF, 0x00, 0xFC, 0x02, 0x10, 0x09, 0xC0, 0x26, 0x00,
+0x9B, 0x00, 0x7C, 0x02, 0xF0, 0x39, 0xC0, 0x24, 0x00, 0x9D, 0x80, 0x64, 0x22,
+0xF0, 0x3B, 0xC0, 0x2F, 0x08, 0x9D, 0x00, 0x34, 0x4A, 0xF0, 0x09, 0x40, 0xA4,
+0x00, 0x9F, 0x03, 0x70, 0x06, 0xB0, 0x3B, 0xC4, 0x17, 0xA0, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x00, 0x25, 0x00, 0x9F, 0x04, 0x7C, 0x12, 0xF0, 0x09,
+0xC4, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF4, 0x08, 0xC0, 0x27, 0x10, 0x9F,
+0x04, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x40, 0x5C, 0x06, 0xF8,
+0x19, 0xC2, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x22, 0xB0, 0x09, 0x05, 0x27, 0x80,
+0x9E, 0x10, 0x6C, 0x06, 0xF0, 0x19, 0xC0, 0x53, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x13, 0x40, 0x7C, 0x00, 0xB4, 0x81, 0xC0,
+0x07, 0x00, 0x1F, 0x08, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x05, 0x00, 0x13, 0x02,
+0x7C, 0x00, 0xF0, 0xA1, 0xD0, 0x04, 0x00, 0x03, 0x00, 0x7C, 0x00, 0xF2, 0x21,
+0xC0, 0x04, 0x20, 0x13, 0x10, 0x5C, 0x98, 0xF0, 0x01, 0xD0, 0x84, 0x00, 0x1F,
+0x42, 0x2C, 0x00, 0x34, 0x21, 0xD0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0xA0, 0x1C, 0x01, 0x51, 0x01, 0xF4, 0x1D, 0x10, 0x15, 0x40, 0x17,
+0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x14, 0x00, 0x51, 0x00, 0x74,
+0x01, 0xD0, 0x97, 0xC0, 0x14, 0x00, 0x71, 0x03, 0x44, 0x01, 0x70, 0x05, 0x40,
+0x14, 0x00, 0x71, 0x01, 0xC4, 0x05, 0xD0, 0x16, 0x42, 0x1C, 0x00, 0x7D, 0x00,
+0xF4, 0x01, 0x14, 0x05, 0x40, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0xA0, 0x62, 0x00, 0xC1, 0x00, 0x34, 0x1E, 0x10, 0x0D, 0x48, 0x33, 0x00,
+0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x31, 0xC0, 0xC1, 0x00, 0x34, 0x03,
+0xD0, 0x2C, 0x40, 0x32, 0x40, 0xC1, 0x11, 0x14, 0x03, 0x50, 0x0C, 0x40, 0x32,
+0x02, 0x81, 0x00, 0x14, 0x05, 0x90, 0x18, 0x40, 0x60, 0x01, 0xC9, 0x02, 0x24,
+0x03, 0x14, 0x0C, 0x60, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x80, 0x68, 0x00, 0xA1, 0x06, 0xB4, 0x06, 0x10, 0x8E, 0x40, 0x3B, 0x01, 0xAD,
+0x04, 0xB4, 0x13, 0xD0, 0x8E, 0x40, 0x38, 0x81, 0xE1, 0x00, 0xB4, 0x13, 0xD0,
+0x0E, 0x40, 0x78, 0x00, 0xC1, 0x10, 0x84, 0x13, 0x50, 0x5E, 0x40, 0x7A, 0x11,
+0xA1, 0x11, 0x86, 0x09, 0xD0, 0x2C, 0x42, 0xA8, 0x00, 0xED, 0x00, 0x34, 0x0B,
+0x10, 0x5F, 0x60, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10,
+0x68, 0x00, 0xE3, 0x07, 0xBC, 0x06, 0x30, 0x5A, 0xC0, 0xEB, 0x00, 0xEF, 0x03,
+0xB4, 0x0F, 0xF0, 0x1C, 0xC0, 0xF1, 0x00, 0xE1, 0x01, 0xBC, 0x17, 0xF0, 0x17,
+0xC4, 0x72, 0x00, 0xE3, 0x01, 0x9C, 0x17, 0x70, 0x3E, 0xC8, 0xFE, 0x40, 0xE3,
+0x01, 0x9C, 0x05, 0xB0, 0x1A, 0xC0, 0x68, 0x08, 0xED, 0x01, 0xAC, 0x05, 0x30,
+0x3E, 0xC0, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x25,
+0x50, 0x9F, 0x00, 0x3C, 0x02, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x80, 0x7C,
+0x03, 0xF0, 0x0D, 0xC2, 0xB7, 0x0D, 0xDF, 0x00, 0x7C, 0x4B, 0xF0, 0x05, 0xC0,
+0x37, 0x00, 0xDF, 0x00, 0x5C, 0x23, 0x72, 0x0D, 0xD0, 0x25, 0x00, 0xDF, 0x00,
+0x7E, 0x01, 0xF0, 0x09, 0xC4, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF4, 0x0C,
+0xC0, 0x43, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x6F, 0x00,
+0xFF, 0x09, 0xCC, 0x13, 0x30, 0x1F, 0xC0, 0x7B, 0x00, 0xF3, 0x01, 0xCC, 0x27,
+0x30, 0x5F, 0x80, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x47, 0x30, 0x1B, 0xC0, 0x7C,
+0x00, 0xBF, 0x01, 0xCC, 0x07, 0xF0, 0x1E, 0xC0, 0x68, 0x0A, 0xB1, 0x0C, 0xFC,
+0x25, 0xF0, 0x1F, 0xC0, 0x78, 0x42, 0xF3, 0x01, 0xFC, 0x06, 0xF0, 0x1F, 0xC4,
+0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x80, 0x29, 0x00, 0xBD,
+0x18, 0x84, 0x43, 0x11, 0x0A, 0x48, 0x3B, 0x00, 0xA1, 0x10, 0x84, 0x23, 0x10,
+0x0E, 0x48, 0x3B, 0x00, 0xED, 0x00, 0x34, 0x03, 0x10, 0x8B, 0x41, 0x38, 0x00,
+0x7D, 0x00, 0x94, 0x03, 0xD0, 0x4E, 0x40, 0x38, 0x03, 0xA1, 0x04, 0xB4, 0x09,
+0xD0, 0x8E, 0x40, 0x19, 0x02, 0xE1, 0x00, 0xB4, 0x0A, 0xF0, 0x8E, 0x40, 0x54,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0xED, 0x40,
+0xA7, 0x22, 0x14, 0x0A, 0x40, 0x2F, 0x06, 0xB1, 0x08, 0xC4, 0x07, 0x12, 0x4E,
+0x60, 0x3B, 0x00, 0xED, 0x02, 0xB4, 0x03, 0x90, 0x02, 0x50, 0x38, 0x02, 0xAD,
+0x00, 0xA4, 0x03, 0xD0, 0x1F, 0x49, 0x2C, 0x04, 0xE9, 0x88, 0xB4, 0x01, 0xD0,
+0x0A, 0x40, 0x38, 0x80, 0x61, 0x10, 0xB4, 0x01, 0xD0, 0x1F, 0x40, 0x60, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x23, 0x00, 0x8D, 0x00, 0x24,
+0x06, 0x10, 0x09, 0x40, 0x77, 0x00, 0x81, 0x00, 0x04, 0x23, 0x10, 0x0C, 0x60,
+0x33, 0x00, 0xCD, 0x08, 0x34, 0x03, 0x91, 0x00, 0x41, 0x30, 0x00, 0x4D, 0x00,
+0x06, 0x03, 0xD2, 0x3C, 0x40, 0x60, 0x20, 0xC9, 0x00, 0x34, 0x09, 0xD0, 0x08,
+0x40, 0x31, 0x02, 0x01, 0x03, 0x30, 0x07, 0x50, 0x0C, 0x60, 0x18, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00, 0xDF, 0x01, 0x6C, 0x02,
+0x30, 0x0D, 0x40, 0xB7, 0x42, 0xD3, 0x21, 0x4D, 0x03, 0x14, 0x0F, 0xC2, 0x3F,
+0x00, 0xDF, 0x00, 0xF4, 0x03, 0x90, 0x1D, 0xC0, 0x34, 0x00, 0x5F, 0x00, 0xCD,
+0x17, 0xF0, 0x3D, 0xD0, 0xF4, 0x40, 0x9A, 0x00, 0x7C, 0x09, 0xF1, 0x0D, 0xC2,
+0xF0, 0x00, 0xD1, 0x23, 0x74, 0x07, 0xD0, 0x2D, 0x50, 0x74, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xB7, 0x00, 0xDF, 0x00, 0x5C, 0x02, 0xF0,
+0x0D, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x43, 0xF0, 0x0D, 0xC0, 0x37, 0x00,
+0xDF, 0x00, 0x3C, 0x03, 0x72, 0x2D, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03,
+0xF0, 0x0D, 0xC0, 0x37, 0x01, 0x97, 0x22, 0x7C, 0x0D, 0xE0, 0x0D, 0xC0, 0xB7,
+0x04, 0xDF, 0x20, 0x7C, 0x21, 0xF0, 0xCD, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x08, 0x7F, 0x02, 0xFF, 0x00, 0x7C, 0x22, 0xF0, 0x0B,
+0xD0, 0x2C, 0x00, 0xF3, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3E, 0x00, 0xFF,
+0x00, 0xDC, 0x03, 0x30, 0x9B, 0xC0, 0x3F, 0x00, 0x7F, 0x01, 0xEE, 0x03, 0xF0,
+0x0F, 0xC1, 0x3F, 0x00, 0xEF, 0x05, 0xCC, 0x41, 0xF0, 0x0B, 0xC0, 0x3D, 0x00,
+0xFB, 0x10, 0x8C, 0x10, 0x30, 0x0F, 0xC0, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x20, 0xD6, 0x00, 0xDD, 0x09, 0x74, 0x0A, 0xD0, 0x0D, 0x40,
+0x64, 0x22, 0xD1, 0x20, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x00,
+0x74, 0x03, 0x10, 0x09, 0x40, 0x37, 0x00, 0x9D, 0x02, 0x7E, 0x03, 0xD0, 0x0D,
+0x40, 0x27, 0x00, 0xDD, 0x07, 0x44, 0x05, 0xD0, 0x38, 0xC8, 0x76, 0x01, 0x89,
+0x00, 0x54, 0x0C, 0x50, 0x0D, 0x42, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0xA0, 0x24, 0x04, 0x9D, 0x00, 0x74, 0x0B, 0xD2, 0x0D, 0x42, 0x34,
+0x40, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x00, 0x74,
+0x03, 0x10, 0x05, 0x41, 0x37, 0x80, 0x1D, 0x66, 0x74, 0x03, 0xD0, 0x0D, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x64, 0x07, 0xD2, 0x35, 0x40, 0x75, 0x00, 0xD1, 0x00,
+0x44, 0x02, 0x11, 0x0D, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x30, 0x00, 0x8D, 0x20, 0x36, 0x03, 0xD0, 0x08, 0x40, 0x20, 0x00,
+0x81, 0x00, 0x34, 0x03, 0xD2, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03,
+0x18, 0x04, 0x40, 0x33, 0xA0, 0x0D, 0x00, 0x14, 0x03, 0xD2, 0x0C, 0x48, 0x33,
+0x00, 0xCD, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x5A, 0x36, 0x00, 0xD1, 0x00, 0x14,
+0x00, 0x50, 0x0C, 0x40, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x26, 0x00, 0x9F, 0x20, 0x7C, 0x01, 0xF0, 0x09, 0xE8, 0x24, 0x00, 0x93,
+0x40, 0xFC, 0x03, 0xF0, 0x0D, 0x40, 0x3F, 0x00, 0xDF, 0x00, 0xBC, 0x23, 0x34,
+0x01, 0xC0, 0x37, 0x00, 0x1F, 0x00, 0x64, 0x03, 0xF0, 0x0F, 0xC0, 0x27, 0x00,
+0xDF, 0x00, 0x6C, 0x01, 0xF0, 0x09, 0xC0, 0x35, 0x80, 0x5B, 0x80, 0x4E, 0x00,
+0x32, 0x0F, 0xC8, 0x07, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8,
+0x1F, 0x00, 0xBF, 0x00, 0xFC, 0x01, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xAF, 0x20,
+0xBC, 0x03, 0xF0, 0x0F, 0xC8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x03,
+0xC0, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC2, 0x2F, 0x00, 0x3F,
+0x00, 0xDC, 0x00, 0xF0, 0x0A, 0xC0, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x80, 0xF8,
+0x0E, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x7F,
+0x00, 0x3F, 0x00, 0xEC, 0x07, 0x70, 0x03, 0xC0, 0x7D, 0x02, 0xF3, 0x09, 0xFC,
+0x10, 0xF0, 0x0B, 0xC0, 0x3C, 0x01, 0xBF, 0x21, 0xFC, 0x03, 0xF0, 0x0F, 0xC1,
+0x3F, 0x00, 0x3F, 0x18, 0xCD, 0x03, 0x30, 0x1F, 0xC0, 0x0F, 0x00, 0xFB, 0x00,
+0xFC, 0x03, 0xE0, 0x0F, 0xC0, 0x4C, 0x00, 0xF3, 0x00, 0xCC, 0x03, 0x30, 0x0F,
+0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00,
+0x5D, 0x01, 0x44, 0x07, 0x10, 0xB1, 0x40, 0x33, 0x00, 0xC1, 0x04, 0x74, 0x06,
+0xD0, 0x29, 0x41, 0x3D, 0x00, 0xDD, 0x01, 0xF4, 0x07, 0xD0, 0x0E, 0x40, 0x77,
+0x00, 0x1D, 0x82, 0x44, 0x07, 0x10, 0x2F, 0x40, 0x67, 0x00, 0x51, 0x01, 0x74,
+0x07, 0xD0, 0x15, 0x40, 0x44, 0x00, 0x5B, 0x01, 0x44, 0x05, 0x10, 0x1D, 0x40,
+0x04, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x00, 0x0D,
+0x08, 0x04, 0x03, 0x50, 0x14, 0x68, 0x31, 0x01, 0xC1, 0x00, 0x34, 0x20, 0xD0,
+0x6C, 0x40, 0xB1, 0x04, 0xCD, 0x01, 0x34, 0x23, 0xD0, 0x4C, 0x41, 0x31, 0x02,
+0x0D, 0x05, 0x24, 0x03, 0x10, 0x2C, 0x40, 0x23, 0x00, 0x85, 0x00, 0x34, 0x02,
+0x50, 0x08, 0x40, 0x01, 0x00, 0x85, 0x20, 0x04, 0x03, 0x10, 0x0C, 0x40, 0x44,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x35, 0x80, 0x5D, 0x14,
+0x65, 0x03, 0x10, 0x01, 0x40, 0x37, 0x00, 0xD1, 0x00, 0x74, 0x00, 0xD0, 0x0D,
+0x40, 0x35, 0x20, 0xDD, 0x01, 0x74, 0x03, 0xD1, 0x0D, 0x40, 0x37, 0x00, 0x1D,
+0x00, 0x64, 0x43, 0x10, 0x0D, 0x44, 0x67, 0x00, 0xD5, 0x06, 0x74, 0x03, 0xD1,
+0x0D, 0x51, 0x45, 0x40, 0xDD, 0x00, 0x44, 0x03, 0x10, 0x8D, 0x40, 0x0C, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0x37, 0x00, 0x9F, 0x01, 0x6C,
+0x07, 0x70, 0x01, 0xC0, 0x75, 0x40, 0xD3, 0x00, 0x7C, 0x11, 0xF0, 0x0D, 0xC0,
+0x35, 0x00, 0xDF, 0x01, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0x5F, 0x00,
+0x6C, 0x03, 0x30, 0x0D, 0xC0, 0xE7, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x3D,
+0xC0, 0xC1, 0x84, 0xD7, 0x00, 0x4C, 0x07, 0x30, 0x0D, 0xC0, 0x08, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0x6F, 0x00, 0xDC, 0x0B,
+0xF0, 0x0F, 0xC0, 0x7F, 0x02, 0xFF, 0x00, 0xFC, 0x0F, 0xF0, 0x0D, 0xE0, 0x3F,
+0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC6, 0x3F, 0x80, 0x9F, 0x28, 0xDC,
+0x27, 0xF0, 0x0F, 0xC0, 0x2F, 0x40, 0x7B, 0x00, 0xFC, 0x03, 0xF0, 0x96, 0xC0,
+0x0E, 0x00, 0xE3, 0x00, 0xBC, 0x09, 0xF0, 0x1E, 0xC0, 0x1F, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0x9F, 0x02, 0x4C, 0x03, 0xF0,
+0x05, 0xC0, 0x34, 0x00, 0xD3, 0x00, 0x5C, 0x05, 0x70, 0x0D, 0xC8, 0x35, 0x08,
+0xD3, 0x80, 0x7C, 0x07, 0xF1, 0x0D, 0xC2, 0x34, 0x00, 0x5F, 0x00, 0x0C, 0x23,
+0x30, 0x0D, 0xC0, 0xA3, 0x00, 0x97, 0x00, 0x7C, 0x03, 0xB0, 0x29, 0xC0, 0x04,
+0x00, 0xDF, 0x00, 0x4C, 0x03, 0x30, 0x2D, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0x5C, 0x00, 0x34, 0x3F, 0xD0, 0x0D,
+0xC0, 0x74, 0x01, 0xD1, 0x00, 0x44, 0x01, 0xD0, 0x9C, 0x48, 0x7C, 0x01, 0xD1,
+0x00, 0xF4, 0x03, 0xD0, 0x0F, 0x40, 0x3C, 0x01, 0x9D, 0x00, 0x6E, 0x03, 0xB0,
+0x4F, 0x40, 0x27, 0x08, 0xD1, 0x00, 0x74, 0x03, 0x10, 0x4D, 0xC0, 0x04, 0x00,
+0xDD, 0x00, 0x44, 0x93, 0x10, 0x0D, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x20, 0x32, 0x00, 0x0D, 0x00, 0x34, 0x0F, 0x90, 0x08, 0x40,
+0x34, 0x00, 0xC1, 0x00, 0x04, 0x00, 0x50, 0x08, 0x00, 0x31, 0x00, 0xC1, 0x00,
+0x34, 0x03, 0xD8, 0x0C, 0x40, 0x70, 0x00, 0x9D, 0x40, 0x04, 0x04, 0x90, 0x2C,
+0x41, 0x23, 0x00, 0xC5, 0x00, 0x36, 0x03, 0x10, 0x0C, 0x40, 0x42, 0x02, 0xCD,
+0x00, 0x24, 0x02, 0x10, 0x00, 0x40, 0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x00, 0x7A, 0x08, 0xAD, 0x21, 0xB4, 0x07, 0xD2, 0x10, 0x40, 0xF8,
+0x02, 0xE1, 0x0B, 0x94, 0x26, 0xD0, 0x1A, 0x41, 0xF8, 0x00, 0xE0, 0x01, 0xB4,
+0x07, 0xD8, 0x3E, 0x40, 0x78, 0x00, 0x6D, 0x01, 0x84, 0x06, 0x90, 0x1E, 0x40,
+0x63, 0x80, 0xE1, 0x01, 0x34, 0x27, 0x10, 0x1C, 0x40, 0x48, 0x00, 0x4D, 0x01,
+0x24, 0x07, 0x10, 0x14, 0x42, 0x10, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x00, 0x32, 0x00, 0x0F, 0x00, 0x3C, 0x23, 0xF0, 0x0C, 0xC0, 0x30, 0x02,
+0xC3, 0x00, 0x1C, 0x03, 0x70, 0x8C, 0x40, 0x35, 0x00, 0xC1, 0x00, 0x3C, 0x23,
+0xF0, 0x0C, 0xC0, 0x30, 0x00, 0x8F, 0x00, 0x04, 0x11, 0x30, 0x8C, 0xC0, 0xB3,
+0x82, 0xC7, 0x00, 0x3C, 0x02, 0x30, 0x0C, 0xC0, 0x02, 0x00, 0x8F, 0x00, 0x2C,
+0x02, 0x30, 0x2C, 0xC0, 0x48, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xA8, 0x3D, 0x00, 0xBF, 0x00, 0xFE, 0xA3, 0xF0, 0x83, 0xC0, 0x3F, 0x92, 0xFF,
+0x00, 0xEC, 0x83, 0xF0, 0x0F, 0xC0, 0xBF, 0x04, 0xFF, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC0, 0x3F, 0x04, 0x7F, 0x08, 0xBC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00,
+0xFF, 0x00, 0xFC, 0x03, 0x75, 0x8F, 0xD0, 0x0F, 0x00, 0xFF, 0x00, 0x5C, 0x03,
+0xF0, 0x0F, 0xE0, 0x0B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0,
+0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0xD3, 0x01,
+0x0C, 0x04, 0x30, 0x0D, 0xC0, 0xB5, 0x01, 0xDB, 0x00, 0x7C, 0x7B, 0xF0, 0xED,
+0xC1, 0x34, 0x00, 0xDF, 0x00, 0x6C, 0x03, 0xB8, 0x8D, 0xC1, 0x27, 0x00, 0xDF,
+0x01, 0x4C, 0x05, 0x10, 0x0D, 0xC4, 0x04, 0x00, 0xDF, 0x00, 0x4C, 0x03, 0x30,
+0x19, 0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x98, 0x39,
+0x00, 0xED, 0x00, 0xB4, 0x03, 0xD2, 0x0E, 0x40, 0x3B, 0x00, 0xF1, 0x00, 0x85,
+0x02, 0x50, 0x0E, 0x40, 0x33, 0x01, 0xE1, 0x00, 0xB4, 0x03, 0xD0, 0x0C, 0x40,
+0x38, 0x01, 0xCD, 0x00, 0xA4, 0x83, 0x10, 0x4E, 0xC0, 0x2B, 0x00, 0xED, 0x00,
+0x84, 0x03, 0x10, 0x0E, 0x40, 0x08, 0x00, 0xED, 0x80, 0x84, 0x03, 0x10, 0x0E,
+0x40, 0x48, 0x68, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00,
+0xED, 0x01, 0xB4, 0x47, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xE1, 0x81, 0x84, 0x07,
+0x00, 0x1E, 0x41, 0x7B, 0x00, 0xE1, 0x03, 0xB4, 0x97, 0xD8, 0x5E, 0x40, 0x7A,
+0x00, 0xED, 0x01, 0x05, 0x07, 0x14, 0x5E, 0x44, 0x7B, 0x00, 0xC5, 0x01, 0x04,
+0x07, 0x90, 0x1C, 0x40, 0x4A, 0x00, 0xCD, 0x11, 0x04, 0x47, 0x10, 0x1C, 0x40,
+0x12, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x20, 0x33, 0xA0, 0xCD,
+0x1A, 0x34, 0x86, 0xD0, 0x0C, 0x41, 0x23, 0x02, 0xC1, 0x00, 0x04, 0x27, 0x5B,
+0x1D, 0x42, 0x33, 0x40, 0x41, 0x00, 0x34, 0x03, 0xD0, 0x0D, 0x50, 0x32, 0x00,
+0xCD, 0x06, 0x04, 0x07, 0x10, 0x0D, 0x40, 0xB1, 0x00, 0xCD, 0x00, 0x05, 0x07,
+0x94, 0x0C, 0x50, 0xF2, 0x04, 0xCD, 0x00, 0x05, 0x03, 0x14, 0x0C, 0x78, 0x5A,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x17, 0x00, 0x7F, 0x03,
+0x7C, 0x01, 0xF0, 0x77, 0x40, 0x57, 0x40, 0x53, 0x00, 0xCC, 0x05, 0x30, 0x05,
+0xC0, 0x17, 0x00, 0x73, 0xC1, 0x74, 0x01, 0xF0, 0x05, 0xC8, 0x16, 0x10, 0x7F,
+0x02, 0xEC, 0x11, 0xB0, 0x05, 0x40, 0x1F, 0x00, 0x7F, 0x00, 0xCC, 0x15, 0xB0,
+0x07, 0xC0, 0xDA, 0x09, 0x7F, 0x03, 0xCC, 0x05, 0x30, 0x27, 0xC0, 0x5E, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x00, 0x0F, 0x00, 0x74,
+0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x17, 0x01, 0x3C, 0x00, 0xF0, 0x01, 0xC0, 0x05, 0xA0, 0x1B, 0x00,
+0x3E, 0x04, 0x70, 0x01, 0xC0, 0x07, 0x04, 0x1F, 0x00, 0x7C, 0x00, 0x74, 0x01,
+0xC0, 0x85, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xC0, 0x49, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x02,
+0xF0, 0x08, 0xD4, 0x24, 0x00, 0x93, 0x02, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x26,
+0x40, 0x93, 0x00, 0x4C, 0x02, 0xB0, 0x09, 0xD0, 0x24, 0x00, 0x9F, 0x00, 0x4C,
+0x82, 0x30, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x7C, 0x42, 0xF0, 0x08, 0xC0,
+0x24, 0x00, 0x93, 0x10, 0x4C, 0x02, 0x34, 0x09, 0xC1, 0x43, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00, 0x44, 0x06, 0xD0,
+0x09, 0x40, 0x20, 0x00, 0x91, 0x10, 0x74, 0x02, 0xD0, 0x19, 0x48, 0xA4, 0x00,
+0x81, 0x00, 0x44, 0x02, 0x10, 0x29, 0xC0, 0x26, 0x00, 0x9D, 0x00, 0x44, 0x02,
+0xB0, 0x09, 0xC0, 0xA6, 0x00, 0x9D, 0x02, 0x5C, 0x0A, 0xD0, 0x29, 0x40, 0x24,
+0x00, 0x91, 0x02, 0x4C, 0x0A, 0x10, 0x29, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x44, 0x06, 0xD0, 0x09,
+0x48, 0x64, 0x00, 0x91, 0x00, 0x74, 0x06, 0x50, 0x89, 0x40, 0x62, 0x84, 0x99,
+0x00, 0x44, 0x06, 0x10, 0x19, 0x63, 0x64, 0x80, 0x8D, 0x00, 0x44, 0x02, 0x10,
+0x09, 0x42, 0x24, 0x04, 0x91, 0x10, 0x74, 0x42, 0xD0, 0x09, 0x51, 0x24, 0x00,
+0x99, 0x30, 0x44, 0xC3, 0x10, 0x09, 0x41, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x28, 0x20, 0x00, 0x8D, 0x04, 0x04, 0x02, 0xD0, 0x48, 0x40,
+0x34, 0x40, 0x81, 0x00, 0x34, 0x12, 0xD0, 0x4C, 0x40, 0x20, 0x81, 0x99, 0x00,
+0x04, 0x12, 0x10, 0x48, 0x40, 0x20, 0x21, 0x8D, 0x04, 0x06, 0x12, 0x90, 0x4C,
+0x48, 0x20, 0x01, 0x8D, 0x04, 0x14, 0x12, 0xD8, 0x48, 0x60, 0x20, 0x00, 0x89,
+0xC4, 0x04, 0x12, 0x10, 0x48, 0x60, 0x53, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x00, 0x4C, 0x01, 0xF0, 0x01, 0xC0, 0x80,
+0x02, 0x13, 0x0A, 0x74, 0x00, 0x70, 0xA1, 0xC0, 0x86, 0x22, 0x19, 0x00, 0x45,
+0x00, 0x30, 0xA1, 0x40, 0x04, 0x00, 0x1F, 0x0A, 0x4D, 0x00, 0x30, 0xA1, 0x40,
+0x04, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF1, 0x01, 0xC8, 0x14, 0x00, 0x13, 0x00,
+0x4C, 0x00, 0x30, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0xA8, 0x27, 0x00, 0xBF, 0x88, 0xFD, 0x02, 0xF0, 0x8B, 0x80, 0x2F, 0x00,
+0x9F, 0x00, 0xFC, 0xA2, 0xF0, 0x8B, 0xC0, 0x27, 0x42, 0xB7, 0x00, 0x7C, 0x22,
+0xF4, 0x89, 0xC0, 0x27, 0x22, 0xBF, 0x08, 0xFC, 0x22, 0x74, 0x89, 0xD0, 0x2F,
+0x02, 0xBF, 0x08, 0xDC, 0x22, 0xF1, 0x8B, 0xC0, 0x2F, 0x40, 0xB7, 0x28, 0xDD,
+0x22, 0xF0, 0x8B, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA8, 0x27, 0x00, 0x9F, 0x04, 0xFE, 0x02, 0xF0, 0x09, 0xC0, 0x2F, 0x02, 0xBF,
+0x00, 0xDC, 0x52, 0xB0, 0xCA, 0xC8, 0x2E, 0x08, 0xBF, 0xA0, 0xDC, 0x82, 0x32,
+0x4B, 0xC2, 0x6F, 0x01, 0xDF, 0x0C, 0xFC, 0x02, 0x34, 0x0B, 0xC0, 0x26, 0x00,
+0x93, 0x04, 0x5C, 0x52, 0xF0, 0x49, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0x30, 0x49, 0xC0, 0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08,
+0x07, 0x00, 0x1D, 0x08, 0x74, 0x00, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x14,
+0x74, 0x00, 0xD0, 0xC1, 0x40, 0x84, 0x04, 0x1D, 0x00, 0x5C, 0x20, 0x10, 0x41,
+0x43, 0x07, 0x00, 0x1D, 0x0C, 0x74, 0x08, 0x10, 0x01, 0x41, 0x04, 0x42, 0x13,
+0x00, 0x44, 0x00, 0xD0, 0x81, 0x40, 0x04, 0x00, 0x1D, 0x00, 0x7C, 0x20, 0x10,
+0x03, 0x40, 0x73, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21,
+0x00, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x88, 0x40, 0x23, 0x00, 0x8D, 0x04, 0x34,
+0x02, 0x90, 0x48, 0x40, 0x22, 0x03, 0x8D, 0x00, 0x34, 0x02, 0x10, 0xC8, 0x40,
+0x23, 0x02, 0x8D, 0x44, 0x34, 0x22, 0x12, 0x88, 0x48, 0x28, 0x80, 0xA1, 0x09,
+0xB4, 0x06, 0xD0, 0x1A, 0x40, 0x28, 0x00, 0xAD, 0x89, 0xB4, 0x06, 0x10, 0x9A,
+0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00,
+0x9D, 0x00, 0x74, 0x06, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02,
+0xD0, 0x0D, 0x60, 0x24, 0x00, 0x9D, 0x02, 0x74, 0x02, 0x10, 0x09, 0x40, 0x27,
+0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x0D, 0x40, 0xA4, 0x00, 0xB9, 0x00, 0xE4,
+0x02, 0xD0, 0x4B, 0x40, 0x2C, 0x00, 0xBC, 0x40, 0xF4, 0x02, 0x10, 0x8B, 0x40,
+0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00, 0x9F,
+0x00, 0x74, 0x02, 0xF0, 0x19, 0x40, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x6A, 0x90,
+0x09, 0xC0, 0x26, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x22, 0x30, 0x09, 0xD0, 0x60, 0x00, 0x93, 0x0B, 0x7C, 0x0A,
+0xF0, 0x39, 0xD0, 0x64, 0x04, 0x9F, 0x02, 0x7C, 0x0A, 0x34, 0x39, 0xC0, 0x17,
+0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x25, 0x00, 0x9F, 0x20,
+0x7C, 0x42, 0xF0, 0x49, 0xC0, 0x67, 0x02, 0x9F, 0x00, 0x7C, 0x02, 0xD0, 0x98,
+0xC0, 0x27, 0x00, 0x9F, 0x09, 0x1C, 0x02, 0xF4, 0x09, 0xC0, 0x27, 0x80, 0x9F,
+0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x01, 0x87, 0x01, 0x5C, 0x16, 0xF0,
+0x19, 0xC0, 0x67, 0x01, 0x9E, 0x05, 0x5C, 0x02, 0xF0, 0x19, 0xC0, 0x4B, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x4C,
+0x80, 0xF2, 0x01, 0xC2, 0x04, 0x04, 0x1F, 0x00, 0x7C, 0x08, 0x30, 0x01, 0xC0,
+0x07, 0x04, 0x13, 0x00, 0x6C, 0x00, 0xF0, 0x01, 0xD0, 0x04, 0x00, 0x1F, 0x00,
+0x4C, 0x80, 0xB0, 0x01, 0xC0, 0x06, 0x00, 0x17, 0x00, 0x7C, 0x00, 0x70, 0x00,
+0xC0, 0x04, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0xF2, 0x01, 0xC0, 0x43, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x14, 0x20, 0x5D, 0x00, 0xD0, 0x11,
+0x70, 0x05, 0x40, 0x9C, 0x00, 0x7D, 0x11, 0x74, 0x01, 0x00, 0x37, 0xC1, 0x5E,
+0x00, 0x51, 0x05, 0x40, 0x05, 0xD0, 0x17, 0x40, 0x54, 0x00, 0x5D, 0x00, 0x44,
+0x01, 0x30, 0x07, 0x40, 0x14, 0x00, 0x51, 0x00, 0x74, 0x01, 0x50, 0x05, 0x50,
+0x14, 0x10, 0x5D, 0x21, 0x54, 0x01, 0xD0, 0x15, 0x40, 0x53, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x04, 0x0D, 0x50,
+0x0C, 0x40, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x06, 0x10, 0x34, 0x51, 0x71, 0x00,
+0x81, 0x01, 0x34, 0x26, 0xD0, 0x1C, 0x40, 0x60, 0x02, 0xCD, 0x00, 0x04, 0x22,
+0x10, 0x85, 0x40, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x32,
+0x00, 0xC9, 0x01, 0x04, 0x03, 0xD0, 0x1C, 0x60, 0x53, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x88, 0x38, 0x00, 0xED, 0x21, 0x84, 0x03, 0x50, 0x1E,
+0x40, 0x38, 0xA0, 0xED, 0x00, 0x34, 0x0F, 0x10, 0x06, 0x40, 0x7A, 0x44, 0xA1,
+0x01, 0x94, 0x03, 0xD0, 0x1E, 0x41, 0x38, 0x00, 0xCD, 0x09, 0x04, 0x02, 0x10,
+0x06, 0x40, 0x32, 0x00, 0xE9, 0x00, 0xB4, 0x07, 0x50, 0x0A, 0x40, 0x2A, 0x00,
+0xCD, 0x11, 0x94, 0x02, 0xD0, 0x0E, 0x41, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x11, 0x10, 0x78, 0x00, 0xCF, 0x01, 0x85, 0x07, 0x70, 0x1C, 0xD0,
+0x58, 0x00, 0x2F, 0x01, 0xBC, 0x07, 0x34, 0x16, 0xC0, 0x5D, 0x00, 0xA1, 0x01,
+0xBC, 0x07, 0xF0, 0x17, 0xC0, 0x78, 0x00, 0xEE, 0x11, 0x8D, 0x06, 0x39, 0x14,
+0xC0, 0x5A, 0x00, 0x6F, 0x01, 0x3C, 0x05, 0x70, 0x14, 0xC0, 0x5A, 0x00, 0x6D,
+0x01, 0x8C, 0x05, 0xF0, 0x16, 0xC4, 0x47, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA8, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x70, 0x0D, 0xC0, 0x07,
+0x00, 0x1F, 0x00, 0x7C, 0x03, 0x78, 0x01, 0xC8, 0x07, 0x00, 0x8F, 0x00, 0x6C,
+0x03, 0xF0, 0x05, 0xC0, 0x37, 0x00, 0xDF, 0x82, 0x7E, 0x02, 0x74, 0x07, 0xC4,
+0x15, 0x00, 0x57, 0x00, 0x7C, 0x01, 0xB4, 0x01, 0xC0, 0x05, 0x00, 0x5F, 0x20,
+0x6D, 0x00, 0xF0, 0x05, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x20, 0x7D, 0x00, 0xFF, 0x01, 0x8C, 0x13, 0x70, 0x1F, 0xC0, 0x7F, 0x00,
+0xF3, 0x01, 0xCC, 0x07, 0x30, 0x17, 0xC2, 0x6F, 0x10, 0xF2, 0x01, 0xFC, 0x07,
+0xF0, 0x1B, 0xC0, 0x7C, 0x20, 0xF7, 0x81, 0xFC, 0x06, 0xF0, 0x13, 0xC2, 0x79,
+0x00, 0xF3, 0x01, 0xFC, 0x07, 0x30, 0x1F, 0xC8, 0x7F, 0x00, 0xBB, 0x01, 0xCC,
+0x87, 0x30, 0x1B, 0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x18, 0x39, 0x00, 0xED, 0x08, 0x8C, 0x03, 0x10, 0x0E, 0x40, 0x1F, 0x00, 0xE1,
+0x08, 0x84, 0x03, 0x14, 0x02, 0x40, 0x1B, 0x01, 0xE1, 0x00, 0xB4, 0x03, 0xD0,
+0x0A, 0x40, 0x38, 0x00, 0xE1, 0x10, 0xB4, 0x13, 0x10, 0x42, 0x40, 0x38, 0x01,
+0xE1, 0x00, 0x9C, 0x03, 0x10, 0x4A, 0x40, 0x2B, 0x20, 0xA1, 0x00, 0xAC, 0x02,
+0x10, 0x0A, 0x40, 0x54, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x39, 0x00, 0xED, 0x10, 0xA4, 0x23, 0x50, 0x0E, 0x41, 0x3B, 0x44, 0x61, 0x00,
+0x84, 0x03, 0x50, 0x06, 0x40, 0x2B, 0x00, 0xE1, 0x00, 0xB4, 0x23, 0xD0, 0x02,
+0x40, 0x38, 0x00, 0xE5, 0x00, 0x34, 0x02, 0x50, 0x02, 0x60, 0x19, 0x10, 0x61,
+0x00, 0xB4, 0x01, 0x90, 0x06, 0x44, 0x1F, 0x02, 0x01, 0x00, 0x84, 0x01, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x31,
+0x20, 0xCD, 0x03, 0x24, 0x03, 0x10, 0x0C, 0x40, 0x03, 0x00, 0x51, 0x00, 0x04,
+0x4B, 0x50, 0x00, 0x40, 0x03, 0x00, 0xC1, 0x43, 0x36, 0x03, 0xD0, 0x00, 0x40,
+0x30, 0x00, 0xC1, 0x03, 0x34, 0x0B, 0x10, 0x00, 0x40, 0x90, 0x40, 0x41, 0x42,
+0x14, 0x01, 0x90, 0x20, 0x40, 0x83, 0x2E, 0x01, 0x02, 0x24, 0x08, 0x10, 0x00,
+0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00,
+0xDF, 0x03, 0x6D, 0x03, 0x70, 0x3D, 0xC0, 0x67, 0x00, 0xD3, 0x00, 0x4D, 0x0B,
+0x70, 0x0D, 0xC2, 0x37, 0x40, 0x93, 0x01, 0x3C, 0x03, 0xF0, 0x0D, 0xD0, 0x30,
+0x00, 0xF7, 0x23, 0x7C, 0x0A, 0x70, 0x05, 0xC0, 0xA1, 0x00, 0x93, 0x03, 0x7C,
+0x06, 0xB0, 0x3D, 0xC0, 0xF7, 0x00, 0xD3, 0xA3, 0x4D, 0x8F, 0x34, 0x1D, 0xD0,
+0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xDF,
+0x04, 0x5C, 0x0F, 0xF0, 0x0D, 0xC0, 0x37, 0x08, 0x5F, 0x00, 0x3C, 0x03, 0xB0,
+0x09, 0xC0, 0x37, 0x20, 0x9F, 0x08, 0x7C, 0x83, 0xF0, 0x05, 0xC0, 0x37, 0x00,
+0xCF, 0x04, 0x7C, 0x02, 0x70, 0x20, 0xC0, 0x27, 0x04, 0x8F, 0x11, 0x1C, 0x46,
+0x74, 0x19, 0xC1, 0x27, 0x00, 0xD7, 0x01, 0x5C, 0x06, 0xF0, 0x1D, 0xC0, 0x07,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x3F, 0x00, 0xDF, 0x00,
+0xFC, 0x03, 0xF0, 0x0E, 0xC1, 0x0C, 0x08, 0xBF, 0x03, 0x4C, 0x03, 0x30, 0x0E,
+0xD0, 0x14, 0x00, 0xBF, 0x19, 0xCC, 0x17, 0x30, 0x89, 0xC0, 0x34, 0x00, 0xF7,
+0x00, 0xCC, 0x42, 0xF0, 0x05, 0xC0, 0x8E, 0x00, 0x37, 0x08, 0x68, 0x20, 0x30,
+0x07, 0xC0, 0x1F, 0x00, 0x7F, 0x10, 0x7C, 0x41, 0xF0, 0x07, 0xC0, 0x13, 0x22,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x36, 0x00, 0xDD, 0x00, 0x74,
+0x0F, 0xD0, 0x0D, 0xC0, 0x46, 0x00, 0x1D, 0x01, 0x44, 0x27, 0x10, 0x31, 0x40,
+0x04, 0x00, 0x8D, 0x01, 0x44, 0x07, 0x10, 0x01, 0x40, 0x34, 0x00, 0xDB, 0x00,
+0x44, 0x02, 0xD0, 0x19, 0x40, 0x44, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01,
+0x40, 0x07, 0x00, 0x5D, 0x00, 0x74, 0x00, 0xD0, 0x05, 0x40, 0x17, 0x02, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x74, 0x0F,
+0xD0, 0x0D, 0x40, 0x24, 0x01, 0x9D, 0x10, 0x54, 0x03, 0x14, 0x1D, 0x40, 0x24,
+0x20, 0x9D, 0x00, 0x46, 0x03, 0x10, 0x0C, 0x41, 0x36, 0x02, 0xD0, 0x00, 0x44,
+0x02, 0xD8, 0x11, 0x40, 0x27, 0x00, 0x95, 0x00, 0x74, 0x02, 0x50, 0x0D, 0x40,
+0x37, 0x00, 0x98, 0x00, 0x74, 0x03, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x30, 0x80, 0xCD, 0x00, 0x34, 0x03, 0xD0,
+0x0C, 0x50, 0x12, 0x00, 0x0D, 0x00, 0x14, 0x03, 0x10, 0x08, 0x40, 0x10, 0x00,
+0x9D, 0x00, 0x04, 0x03, 0x10, 0x04, 0x48, 0x30, 0x00, 0xC9, 0x00, 0x04, 0x03,
+0xD0, 0x00, 0x40, 0x25, 0x00, 0x81, 0x00, 0x15, 0x02, 0x54, 0x08, 0x40, 0x23,
+0x80, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x43, 0xA0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xB0, 0x36, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x24, 0x00, 0x8F, 0x00, 0x5D, 0x03, 0x14, 0x05, 0xC0, 0x24, 0x20, 0x9E,
+0x00, 0x4D, 0x03, 0x34, 0x09, 0xD0, 0x34, 0x00, 0xF7, 0x00, 0x4D, 0x02, 0xF0,
+0x01, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x7C, 0x00, 0x70, 0x05, 0xC8, 0x17, 0x10,
+0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x01, 0xC0, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0xA8, 0x3F, 0x20, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC0,
+0x0D, 0x00, 0x3F, 0x00, 0xEC, 0x03, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0xBF, 0x00,
+0xFC, 0x03, 0xF0, 0x03, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B,
+0xC0, 0x0E, 0x00, 0x3F, 0x20, 0xEC, 0x00, 0xB0, 0x03, 0xC0, 0x0B, 0x00, 0x3F,
+0x40, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA0, 0x2F, 0x00, 0xBF, 0x00, 0xCC, 0x03, 0xB0, 0x1B, 0xC0, 0x2F,
+0x21, 0xF3, 0x24, 0xEC, 0x25, 0xF0, 0x1F, 0xD0, 0x3C, 0x00, 0xFB, 0x88, 0xCC,
+0x84, 0xB0, 0x4F, 0xC0, 0x7F, 0x22, 0x2F, 0x01, 0xF4, 0x05, 0x30, 0x0B, 0xC1,
+0xEF, 0x00, 0x2F, 0x01, 0xEC, 0x04, 0x30, 0x12, 0xC0, 0x5E, 0x08, 0x2F, 0x01,
+0xCE, 0x0D, 0x30, 0x0B, 0xC0, 0x0D, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x27, 0x10, 0x9D, 0x01, 0x44, 0x0F, 0x10, 0x15, 0x40, 0x67, 0x00,
+0xD1, 0x14, 0x44, 0x02, 0xD0, 0x4D, 0x40, 0xBC, 0x04, 0xF1, 0x0E, 0x44, 0x07,
+0x10, 0xBF, 0x40, 0x37, 0x00, 0x17, 0x94, 0x64, 0x05, 0x10, 0x39, 0x40, 0x37,
+0x11, 0x5D, 0x21, 0x44, 0x05, 0x51, 0x19, 0x40, 0x75, 0x30, 0x1D, 0x21, 0x46,
+0x02, 0x10, 0x11, 0xC0, 0x0D, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+0xA0, 0x23, 0x00, 0x0D, 0x80, 0x05, 0x0B, 0xD8, 0x08, 0x40, 0x23, 0x02, 0xC1,
+0x0C, 0x24, 0x02, 0x50, 0x08, 0x41, 0xB0, 0x81, 0xC9, 0x04, 0x54, 0x07, 0x90,
+0x0C, 0x40, 0x33, 0x11, 0x0D, 0x00, 0x74, 0x00, 0x10, 0x0C, 0x44, 0x31, 0x01,
+0x49, 0x00, 0x24, 0x00, 0x12, 0x0D, 0x44, 0x31, 0x00, 0x1D, 0x40, 0x64, 0x13,
+0x90, 0x08, 0x40, 0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8,
+0x65, 0x00, 0x9D, 0x11, 0x44, 0x03, 0x18, 0x65, 0x40, 0x27, 0x00, 0xD1, 0x00,
+0x42, 0x02, 0xD0, 0x08, 0x40, 0x34, 0x08, 0xC1, 0x00, 0x55, 0x03, 0x10, 0x0D,
+0x40, 0x37, 0x00, 0x9D, 0x11, 0x64, 0x00, 0x1C, 0x0D, 0x40, 0x37, 0x10, 0x5D,
+0x11, 0x44, 0x45, 0x50, 0x89, 0x00, 0x75, 0x00, 0x1D, 0x10, 0x64, 0x43, 0x96,
+0x11, 0x40, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x47,
+0x04, 0x9F, 0x21, 0x44, 0x03, 0xF2, 0x05, 0xC0, 0x33, 0x40, 0xD3, 0x00, 0x6C,
+0x03, 0xF1, 0x0D, 0xC0, 0x34, 0x00, 0xDB, 0x00, 0x54, 0x04, 0xB0, 0x0D, 0xC0,
+0x37, 0x00, 0x1F, 0x01, 0x7C, 0x14, 0x30, 0x09, 0xC0, 0x35, 0x00, 0x5B, 0x01,
+0x2C, 0x0D, 0x30, 0x31, 0x82, 0x77, 0x01, 0x1D, 0x22, 0x64, 0x0F, 0xB1, 0x31,
+0xC1, 0x81, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x2D, 0x00,
+0xAF, 0x00, 0xBC, 0x03, 0xF0, 0x07, 0xC0, 0x3F, 0x02, 0xEF, 0x80, 0xFC, 0x82,
+0xF0, 0x8F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xEC, 0xA0, 0xF0, 0x0F, 0xC2, 0x3F,
+0x10, 0x37, 0x00, 0xEC, 0xA4, 0x70, 0x9B, 0xC0, 0x3F, 0x00, 0x7F, 0x00, 0xFC,
+0x01, 0xF0, 0x13, 0xC0, 0x2F, 0x00, 0x3F, 0x08, 0xDD, 0x27, 0x70, 0x03, 0xC0,
+0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x05, 0x02, 0x13,
+0x10, 0x7E, 0x23, 0xB0, 0x05, 0xC0, 0x37, 0x03, 0xDF, 0x80, 0x7C, 0x03, 0xF1,
+0x09, 0xC0, 0x35, 0x80, 0xDF, 0x08, 0x4C, 0x80, 0x70, 0x0D, 0xC1, 0x37, 0x00,
+0x93, 0x02, 0x5C, 0x08, 0xF8, 0x0D, 0xC2, 0x37, 0x00, 0x5F, 0x0E, 0x78, 0x1B,
+0x70, 0x25, 0xC4, 0xA5, 0x00, 0x53, 0x00, 0x6C, 0x4B, 0x31, 0x09, 0xC4, 0x0B,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xE4, 0x02, 0x91, 0x00,
+0xF4, 0x07, 0x10, 0x05, 0x41, 0x77, 0x00, 0xFD, 0x00, 0x44, 0x02, 0xD0, 0x19,
+0xC8, 0x3E, 0x20, 0xFF, 0x00, 0x00, 0x2C, 0x10, 0x1F, 0x40, 0x37, 0x00, 0x91,
+0x00, 0x04, 0x00, 0xF0, 0x0D, 0x40, 0x37, 0x00, 0x4C, 0x01, 0x44, 0x05, 0xB0,
+0x04, 0x40, 0x24, 0x00, 0x4B, 0x04, 0x24, 0x83, 0x14, 0x71, 0x40, 0x6F, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x40, 0x00, 0x01, 0x00, 0x34,
+0x83, 0x14, 0x3C, 0x41, 0xA3, 0x10, 0xCD, 0x00, 0x14, 0x01, 0xD0, 0x9C, 0x40,
+0x35, 0x08, 0xCD, 0x01, 0x04, 0x08, 0x50, 0xBC, 0x60, 0x32, 0x00, 0x05, 0x00,
+0x14, 0x01, 0xD0, 0x68, 0x40, 0x23, 0x00, 0x49, 0x03, 0x14, 0x8C, 0xD1, 0xB4,
+0x41, 0x31, 0x00, 0x00, 0x00, 0x04, 0x23, 0x10, 0x48, 0x40, 0x0F, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x58, 0x00, 0x61, 0x01, 0xB4, 0x07,
+0x10, 0x16, 0x40, 0x6B, 0x00, 0xED, 0x01, 0x96, 0x06, 0xD0, 0x1E, 0x40, 0x7A,
+0x00, 0xC5, 0x41, 0x84, 0x47, 0x10, 0x1E, 0x68, 0x7B, 0x00, 0xF1, 0x00, 0x84,
+0x05, 0x50, 0x9A, 0x40, 0x7B, 0x02, 0x7D, 0x01, 0xC4, 0x14, 0x90, 0x1A, 0x48,
+0x79, 0x20, 0x39, 0x09, 0x85, 0x27, 0x15, 0x1A, 0x40, 0x3F, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x34, 0x02, 0x43, 0x04, 0x34, 0x03, 0x10,
+0x0C, 0xC0, 0x33, 0x10, 0xDF, 0x00, 0x1C, 0x02, 0xF0, 0x0C, 0xC0, 0x31, 0x00,
+0xCD, 0x00, 0x0C, 0x03, 0x70, 0xCC, 0xC0, 0x37, 0x42, 0x05, 0x00, 0x1C, 0x11,
+0xD0, 0x08, 0xC0, 0x33, 0x00, 0x4B, 0x00, 0x1C, 0x40, 0xF0, 0x8C, 0xC0, 0x31,
+0x02, 0xC3, 0x00, 0x6C, 0x23, 0x30, 0x88, 0xE0, 0x4B, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x38, 0x3D, 0x40, 0x7F, 0x00, 0xBC, 0x03, 0x70, 0x07,
+0xC0, 0x3F, 0x02, 0xFF, 0x00, 0xCC, 0x02, 0xF0, 0x0C, 0xC0, 0xBF, 0x20, 0xDF,
+0x00, 0x3C, 0x03, 0xC0, 0x8F, 0xC8, 0x37, 0x08, 0xFF, 0x8C, 0x7C, 0x01, 0xF0,
+0x09, 0xC0, 0x3F, 0x00, 0xFF, 0x48, 0x1C, 0x11, 0xF0, 0x89, 0xC0, 0x3A, 0x00,
+0xBF, 0x00, 0xFC, 0x23, 0xF2, 0x0F, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0x17, 0x00, 0xDF, 0x01, 0x6C, 0x03, 0xF0, 0x0D, 0xC0,
+0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0C, 0xC4, 0x74, 0x03, 0xD1, 0x0E,
+0x7C, 0x80, 0x70, 0x6D, 0xE0, 0x37, 0x00, 0xD7, 0x00, 0x7C, 0x00, 0x70, 0x1D,
+0xC0, 0x36, 0x00, 0x5B, 0x00, 0x7C, 0x04, 0xB0, 0x05, 0xC0, 0x37, 0x00, 0x97,
+0x00, 0x4C, 0x03, 0x34, 0x01, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x80, 0x19, 0x00, 0xED, 0x00, 0x84, 0x0B, 0xC0, 0x06, 0x40, 0xAB,
+0x20, 0xED, 0x04, 0xB4, 0x02, 0xD0, 0x0E, 0x40, 0x31, 0x00, 0xE1, 0x10, 0xB4,
+0x03, 0xD0, 0xEE, 0xC0, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x00, 0xD0, 0x4E, 0x40,
+0x38, 0x00, 0x61, 0x00, 0xA4, 0x00, 0x10, 0x0E, 0x60, 0x3B, 0x00, 0x2D, 0x00,
+0x8D, 0x03, 0xB0, 0x06, 0x40, 0x4F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x00, 0x79, 0x00, 0xED, 0x01, 0x85, 0x17, 0x50, 0x1E, 0x41, 0x7B, 0x01,
+0xED, 0x09, 0xB4, 0x07, 0x50, 0x1E, 0x40, 0x78, 0x41, 0xE1, 0x05, 0x94, 0x47,
+0x50, 0x1E, 0x02, 0x7B, 0x10, 0xED, 0x01, 0xB4, 0x04, 0xD2, 0xDC, 0x00, 0x7A,
+0x24, 0x6D, 0x01, 0xD6, 0x0D, 0xD8, 0x1E, 0x40, 0x7B, 0x04, 0xE5, 0x01, 0xF4,
+0x07, 0x10, 0x1A, 0x60, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x28, 0x33, 0x00, 0xCD, 0x1A, 0x04, 0x03, 0xD0, 0x14, 0x40, 0x73, 0x02, 0xCD,
+0x00, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x31, 0x00, 0xC1, 0x00, 0x34, 0x13, 0xD0,
+0x0C, 0x48, 0x30, 0x00, 0xDD, 0x01, 0x34, 0x06, 0xD0, 0x8C, 0x40, 0x30, 0x00,
+0x45, 0x08, 0x34, 0x0D, 0xD0, 0x8C, 0x40, 0x73, 0x00, 0xCD, 0x01, 0x04, 0x03,
+0x17, 0x0C, 0x40, 0x5B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0,
+0x1D, 0x06, 0x7D, 0x03, 0x6C, 0x01, 0xF0, 0x17, 0xC0, 0x17, 0x00, 0x5F, 0x00,
+0xF4, 0x2D, 0x70, 0x04, 0xC4, 0x14, 0x10, 0x53, 0x80, 0xFC, 0x0D, 0x71, 0x05,
+0xC0, 0x17, 0x00, 0x7F, 0x07, 0xFC, 0x19, 0xF0, 0x15, 0xC0, 0x56, 0x00, 0x6F,
+0x02, 0xFC, 0x05, 0xF0, 0x27, 0xC8, 0x1F, 0x20, 0x67, 0x07, 0xFC, 0x01, 0x10,
+0x97, 0xC2, 0x5F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x05,
+0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x21, 0xC1, 0x87, 0x00, 0x1F, 0x80, 0x7C,
+0x20, 0xF2, 0x01, 0xC0, 0x07, 0x00, 0x1B, 0x00, 0x7C, 0x08, 0xF0, 0x21, 0xC0,
+0x05, 0x00, 0x1F, 0x04, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x19, 0x50,
+0x6C, 0x18, 0x10, 0x21, 0xC1, 0xC7, 0x08, 0x1B, 0x30, 0x7E, 0x0C, 0xF0, 0x81,
+0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x00,
+0x9F, 0x44, 0x7E, 0x0A, 0xF0, 0x09, 0xD0, 0x64, 0x10, 0x9F, 0x00, 0x7C, 0x06,
+0x30, 0x09, 0xD0, 0x24, 0x80, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0x27,
+0x00, 0x93, 0xC0, 0x4C, 0x42, 0xF0, 0x29, 0xC0, 0x26, 0x00, 0x93, 0x80, 0x5C,
+0x0A, 0xF0, 0x19, 0xC0, 0x65, 0x00, 0x9F, 0x00, 0x5C, 0x26, 0x30, 0x29, 0xC0,
+0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x02, 0x9D,
+0x47, 0x74, 0x06, 0xD0, 0x48, 0x40, 0xEC, 0x10, 0x9D, 0x00, 0x34, 0x26, 0x10,
+0x09, 0xC0, 0x26, 0x10, 0x9D, 0x02, 0x74, 0x1A, 0xD0, 0x09, 0x44, 0x27, 0x00,
+0x91, 0x40, 0x4C, 0x02, 0x78, 0x1B, 0x40, 0x23, 0x00, 0x91, 0x10, 0x44, 0x0E,
+0xD0, 0x08, 0x42, 0x20, 0x10, 0x9B, 0x40, 0x0C, 0x1E, 0x54, 0x09, 0xC0, 0x07,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00,
+0x74, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x02, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x09,
+0x40, 0x24, 0x00, 0x99, 0x10, 0x74, 0x02, 0xD0, 0x29, 0x40, 0x23, 0x00, 0x91,
+0x00, 0x64, 0x02, 0xD1, 0x29, 0x40, 0x27, 0x00, 0x91, 0x01, 0x54, 0x02, 0x50,
+0x4D, 0x40, 0x25, 0x02, 0x94, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x63, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x05, 0x8D, 0x14, 0x34,
+0x02, 0xD0, 0x09, 0x40, 0x20, 0x00, 0x8D, 0x08, 0x74, 0x0A, 0x10, 0x28, 0x40,
+0x22, 0x02, 0x8D, 0x08, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x02, 0x81, 0x08,
+0x04, 0x02, 0xD0, 0x08, 0x40, 0x27, 0x02, 0x91, 0x40, 0x04, 0x02, 0xD2, 0x09,
+0x40, 0x24, 0x00, 0x99, 0x00, 0x46, 0x22, 0x51, 0x48, 0x44, 0x43, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x06, 0x01, 0x1F, 0x04, 0x74, 0xD0,
+0xF0, 0x01, 0xC0, 0x54, 0x10, 0x1F, 0x16, 0x7E, 0x00, 0x34, 0x01, 0x40, 0x84,
+0x05, 0x19, 0x96, 0x7C, 0x00, 0xF0, 0x41, 0xC1, 0x87, 0x00, 0x13, 0x02, 0x6D,
+0x80, 0xD0, 0x11, 0x40, 0x83, 0x40, 0x13, 0x00, 0x54, 0x01, 0x70, 0x05, 0xC0,
+0x15, 0x00, 0x17, 0x00, 0x7C, 0x08, 0x30, 0x05, 0xC0, 0x77, 0xE0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x2F, 0x25, 0xAF, 0x20, 0x7C, 0x02, 0xF0,
+0x0B, 0xC8, 0xAF, 0x00, 0x9D, 0x04, 0xFC, 0x07, 0xF0, 0x1B, 0xC0, 0x27, 0x09,
+0x9F, 0x04, 0xFC, 0x02, 0xF2, 0x09, 0xC2, 0x27, 0x41, 0xBF, 0x04, 0xFC, 0x02,
+0x50, 0x2B, 0xC0, 0x2F, 0x01, 0xBF, 0x00, 0xB4, 0x02, 0xF2, 0x0B, 0xC0, 0x2F,
+0x00, 0xA7, 0x00, 0xBC, 0x12, 0xF4, 0x8B, 0xC0, 0x75, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x05, 0xBF, 0x04, 0xFC, 0x02, 0xF0, 0x0B,
+0xD0, 0x6C, 0x04, 0x91, 0x24, 0xFC, 0x0A, 0xF0, 0x2B, 0xD0, 0x24, 0x00, 0xBF,
+0x00, 0x9E, 0x02, 0xF0, 0x4B, 0xC0, 0x26, 0x00, 0x9F, 0x08, 0x7C, 0x82, 0x34,
+0x5B, 0xD1, 0x24, 0x02, 0xBF, 0x00, 0xEC, 0x02, 0xF2, 0x0B, 0xC0, 0x2E, 0x80,
+0xA7, 0x00, 0xCE, 0x83, 0x30, 0x0B, 0xC0, 0x74, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x00, 0x07, 0x11, 0x1D, 0x08, 0x74, 0x08, 0xD0, 0x01, 0x40,
+0x84, 0x00, 0x11, 0x14, 0x74, 0x04, 0xD0, 0x51, 0x40, 0x84, 0x04, 0x0D, 0x10,
+0x76, 0x00, 0xD1, 0x01, 0x00, 0x04, 0x01, 0x1D, 0x04, 0x74, 0x00, 0x19, 0x21,
+0x40, 0x04, 0x00, 0x19, 0x00, 0x5C, 0x00, 0xD2, 0x01, 0x40, 0x04, 0x10, 0x1D,
+0x00, 0x05, 0x00, 0xB4, 0x01, 0x40, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x21, 0x05, 0x8D, 0x00, 0x34, 0x22, 0xD0, 0x09, 0x40, 0x20,
+0x00, 0x81, 0x0C, 0x34, 0x02, 0xD0, 0x48, 0x40, 0x20, 0x83, 0x8D, 0x08, 0x14,
+0x02, 0xD3, 0x88, 0x00, 0x22, 0x05, 0x8D, 0x04, 0x74, 0x02, 0x10, 0x08, 0x40,
+0x20, 0x10, 0x8D, 0x00, 0x36, 0x82, 0xD0, 0x08, 0x40, 0x22, 0x00, 0x95, 0x00,
+0x54, 0x02, 0x14, 0x0C, 0x40, 0x48, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x2A, 0x25, 0x86, 0x9D, 0x20, 0x74, 0x02, 0xD2, 0x09, 0x40, 0x24, 0x00,
+0x91, 0x20, 0x74, 0x02, 0xD0, 0x1D, 0x40, 0x24, 0x00, 0x9D, 0x40, 0x74, 0x42,
+0xD0, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x02, 0x74, 0x02, 0x10, 0x09, 0x44, 0x24,
+0x01, 0x9D, 0x02, 0x55, 0x0B, 0xD1, 0x89, 0x40, 0xE4, 0x00, 0x9D, 0x03, 0x54,
+0x2A, 0x90, 0x2D, 0x40, 0x60, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x02, 0x25, 0x10, 0x9F, 0x12, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x93,
+0x00, 0xFC, 0x22, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x5C, 0x2A, 0xF0,
+0x09, 0xC2, 0x26, 0x00, 0x9F, 0x00, 0x3E, 0x3A, 0x10, 0x99, 0xC8, 0x24, 0x20,
+0x8F, 0x4B, 0x7C, 0x22, 0xF0, 0x49, 0xC0, 0xA6, 0x80, 0x87, 0x01, 0x54, 0x02,
+0x31, 0x09, 0xE0, 0x14, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08,
+0x25, 0x0C, 0x9F, 0x84, 0x7C, 0x02, 0xF8, 0x09, 0xE0, 0x23, 0x41, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0x10, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0x80, 0x7C, 0x06, 0xF8, 0x19, 0xC4, 0x67, 0x00, 0x9B,
+0x00, 0x7C, 0x02, 0xF0, 0x09, 0xE8, 0x27, 0x88, 0x9F, 0x00, 0x6C, 0x06, 0xD1,
+0x48, 0xD8, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05,
+0x00, 0x1F, 0x82, 0x7C, 0x80, 0xF8, 0x41, 0xD0, 0x06, 0x40, 0x13, 0x00, 0x7C,
+0x00, 0x70, 0x41, 0xC0, 0x06, 0x00, 0x13, 0x00, 0x4D, 0xC8, 0x71, 0x01, 0x41,
+0x06, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC1, 0x07, 0x20, 0x1F, 0x30,
+0x5C, 0x10, 0x70, 0xC1, 0xC8, 0x87, 0x20, 0x1F, 0x10, 0x4C, 0x10, 0x32, 0x41,
+0xC4, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xDC, 0x04,
+0x7D, 0x07, 0x74, 0x15, 0x78, 0x76, 0xC0, 0x1C, 0x00, 0x51, 0x00, 0x74, 0x01,
+0x10, 0x16, 0x45, 0x14, 0x00, 0x71, 0x86, 0xC4, 0x09, 0x12, 0x16, 0x40, 0x17,
+0x00, 0x5D, 0x00, 0x74, 0x01, 0x70, 0x36, 0x40, 0x17, 0x10, 0x7D, 0x00, 0xF0,
+0x0D, 0x12, 0x36, 0x48, 0xDF, 0x02, 0x7D, 0x04, 0x80, 0x15, 0x50, 0x07, 0x50,
+0x40, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xF2, 0x00, 0x8D,
+0x06, 0x34, 0x07, 0x50, 0x18, 0x40, 0x20, 0x00, 0xC1, 0x00, 0x36, 0x23, 0x50,
+0x08, 0x40, 0x32, 0x40, 0xC9, 0x00, 0x04, 0x2F, 0x50, 0xBC, 0x40, 0x33, 0x00,
+0xCD, 0x00, 0x14, 0x03, 0x50, 0x28, 0x40, 0x33, 0x80, 0x4D, 0x0A, 0x34, 0x2F,
+0x50, 0x1C, 0x40, 0xD3, 0x00, 0xC9, 0x00, 0x04, 0x0B, 0x11, 0x0C, 0x40, 0x40,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x80, 0xAD, 0x00,
+0xB4, 0x03, 0x50, 0x02, 0x40, 0x28, 0x00, 0xE1, 0x00, 0xB4, 0x17, 0x18, 0x0E,
+0x40, 0x70, 0x02, 0xE9, 0x01, 0xC4, 0x07, 0x10, 0x0E, 0x40, 0x3B, 0x01, 0xED,
+0x08, 0xB4, 0x03, 0x50, 0x22, 0x40, 0x3B, 0xB0, 0x6D, 0x00, 0xB6, 0x07, 0x11,
+0x06, 0x40, 0x1B, 0x8C, 0xFD, 0x00, 0x85, 0x03, 0x10, 0x0C, 0x40, 0x10, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x78, 0x00, 0xEF, 0x01, 0xBC,
+0x07, 0x70, 0x12, 0xC0, 0x68, 0x00, 0xE3, 0x01, 0xFC, 0x0F, 0x70, 0x1A, 0xD0,
+0x7A, 0x01, 0xE9, 0x01, 0x8C, 0x07, 0x70, 0x1E, 0xE8, 0x7B, 0x03, 0xEF, 0x01,
+0xBC, 0x07, 0x70, 0x12, 0xC0, 0x7B, 0x25, 0x6F, 0x01, 0x9E, 0x06, 0x70, 0x1A,
+0xC0, 0x6B, 0x00, 0xEF, 0x01, 0x8C, 0x06, 0x34, 0x1E, 0xC0, 0x50, 0x60, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x00, 0xDF, 0x00, 0x7C, 0x03,
+0x70, 0x00, 0xC0, 0x21, 0x00, 0xDF, 0x40, 0x7C, 0x03, 0xF2, 0x0C, 0xC0, 0x37,
+0x20, 0xD7, 0x80, 0x7C, 0x01, 0xF2, 0x0D, 0xC0, 0x37, 0x02, 0xDF, 0x10, 0x78,
+0x03, 0x70, 0x01, 0xC2, 0x37, 0x1A, 0x1F, 0x80, 0x3C, 0x02, 0xF0, 0x05, 0xC0,
+0x27, 0x20, 0xDF, 0x00, 0x7C, 0x02, 0xF6, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x5D, 0x00, 0xA3, 0x01, 0xCC, 0x13, 0xF8,
+0x03, 0xC0, 0x6D, 0x00, 0xFF, 0x11, 0xBC, 0x07, 0x20, 0xDB, 0xC0, 0x7C, 0x00,
+0x7F, 0x01, 0xCC, 0x07, 0xF0, 0x9F, 0xD0, 0x7C, 0x00, 0xDF, 0x09, 0xFC, 0x07,
+0xF0, 0x13, 0xC0, 0x7F, 0x20, 0x2F, 0x09, 0xEE, 0x17, 0xF0, 0x1F, 0xC0, 0x5F,
+0x00, 0xFF, 0x01, 0x8C, 0x05, 0x30, 0xDB, 0xC0, 0x18, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x00, 0xA1, 0x00, 0x84, 0x03, 0x78, 0x42,
+0x40, 0x28, 0x02, 0xED, 0x00, 0xB4, 0x13, 0x10, 0x8A, 0x50, 0x38, 0x11, 0x2D,
+0x04, 0x8C, 0x1A, 0xD0, 0x8A, 0x40, 0x38, 0x00, 0xED, 0x05, 0xB4, 0x03, 0x90,
+0x02, 0x40, 0x3B, 0x00, 0x2D, 0x00, 0x9E, 0x03, 0xD0, 0x0E, 0x40, 0x9B, 0x22,
+0xAD, 0x04, 0xAC, 0x01, 0x10, 0xCE, 0x48, 0x55, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0xA1, 0x00, 0x85, 0x23, 0x50, 0x82, 0x43,
+0x29, 0x00, 0xED, 0x00, 0xF4, 0x02, 0x10, 0x4B, 0x48, 0x38, 0x80, 0x6D, 0x80,
+0x84, 0x03, 0xD2, 0x06, 0x00, 0x38, 0x00, 0xED, 0x04, 0xB4, 0x03, 0xD0, 0x02,
+0x40, 0x3B, 0x00, 0x3D, 0x00, 0x84, 0x12, 0xD0, 0x0A, 0x40, 0x9B, 0x00, 0xF5,
+0x10, 0xD4, 0x20, 0x10, 0xC2, 0x44, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x28, 0xC3, 0x00, 0x01, 0x01, 0x00, 0x02, 0x50, 0x30, 0x40, 0x20,
+0x00, 0xCD, 0x00, 0x34, 0x22, 0x10, 0x08, 0x40, 0x30, 0x00, 0x1D, 0x00, 0x04,
+0x4C, 0xD0, 0x00, 0x40, 0x30, 0x00, 0xCD, 0x04, 0x34, 0x43, 0xD0, 0x00, 0x40,
+0x77, 0x00, 0x0D, 0x12, 0x14, 0xC6, 0xD9, 0x8C, 0x40, 0x13, 0x00, 0x8D, 0x23,
+0x05, 0x03, 0x14, 0x24, 0x40, 0x09, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0xE5, 0x41, 0x93, 0x0A, 0x4C, 0x03, 0x70, 0x35, 0xC0, 0x35, 0x00,
+0xFF, 0x00, 0x74, 0x02, 0x34, 0x08, 0xC0, 0x3C, 0x00, 0x9F, 0x00, 0x4C, 0x4E,
+0xF0, 0x09, 0xC0, 0x3C, 0x00, 0xFF, 0x13, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x3F,
+0x01, 0x5F, 0x01, 0x4C, 0x07, 0xF1, 0xBD, 0xC0, 0xB7, 0x00, 0xD7, 0x03, 0x14,
+0x4F, 0x30, 0x94, 0xC0, 0x54, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x08, 0x27, 0x00, 0x9F, 0x88, 0x7C, 0x03, 0x70, 0x21, 0xC0, 0xB7, 0x00, 0xDF,
+0x00, 0x7C, 0x42, 0xF0, 0x29, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x5D, 0x02, 0xF0,
+0x00, 0xC4, 0x37, 0x00, 0xDF, 0x20, 0x7C, 0x03, 0xB0, 0x25, 0xE4, 0x37, 0x00,
+0x5F, 0x01, 0x4D, 0x23, 0xF0, 0x05, 0xC0, 0xF7, 0x00, 0xDF, 0x02, 0x7C, 0x1B,
+0xF0, 0x3D, 0xC0, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08,
+0x27, 0x04, 0xFF, 0x02, 0xFC, 0x03, 0xF0, 0x17, 0xC1, 0x6B, 0x00, 0xF7, 0x00,
+0xFC, 0x07, 0xD0, 0x1B, 0xC0, 0x3C, 0x08, 0x1F, 0x00, 0xCC, 0x02, 0xF0, 0x09,
+0xC0, 0x3D, 0x80, 0xFF, 0x80, 0xCC, 0x03, 0xF8, 0x13, 0xC0, 0x3D, 0x00, 0xF3,
+0x00, 0xFC, 0x26, 0xF0, 0x03, 0xCC, 0x2F, 0x00, 0xF7, 0x10, 0xCC, 0x02, 0x30,
+0x11, 0xC8, 0x04, 0x26, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x66,
+0x00, 0xDD, 0x00, 0x74, 0x03, 0xD0, 0x01, 0x40, 0x17, 0x00, 0xD1, 0x80, 0x74,
+0x07, 0xD0, 0x39, 0x50, 0x34, 0x00, 0x1D, 0x09, 0x44, 0x0C, 0xD0, 0x11, 0x40,
+0x34, 0x80, 0xDD, 0x00, 0x44, 0x03, 0xD8, 0x00, 0xC1, 0x34, 0x40, 0x11, 0x03,
+0x72, 0x0E, 0x70, 0x05, 0x41, 0x23, 0x00, 0xCB, 0x22, 0x44, 0x64, 0x14, 0x39,
+0xC0, 0x06, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x46, 0x0C,
+0x9D, 0x00, 0x74, 0x03, 0xD0, 0x45, 0x41, 0xB7, 0x01, 0xD5, 0x00, 0x74, 0x12,
+0xD0, 0x81, 0x40, 0x36, 0x00, 0xDD, 0x02, 0x44, 0x04, 0xD2, 0x19, 0x41, 0x34,
+0x00, 0xCD, 0x00, 0x44, 0x03, 0xD0, 0x45, 0x40, 0x36, 0x20, 0x51, 0x11, 0x64,
+0x03, 0xD0, 0x19, 0x40, 0x37, 0x00, 0x51, 0x02, 0x44, 0x01, 0x10, 0x41, 0x40,
+0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x8D,
+0x00, 0x34, 0x03, 0xD0, 0x04, 0x40, 0x32, 0x00, 0xC1, 0x00, 0x34, 0x02, 0xD0,
+0x00, 0x40, 0x32, 0x00, 0x8D, 0x00, 0x04, 0x00, 0xD2, 0x00, 0x40, 0x30, 0x00,
+0xCD, 0x10, 0x04, 0x03, 0xD0, 0x04, 0x60, 0x30, 0x00, 0x41, 0x20, 0x34, 0x01,
+0x50, 0x08, 0x40, 0x37, 0x80, 0x09, 0x00, 0x45, 0x00, 0x10, 0x0C, 0x44, 0x42,
+0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x27, 0x00, 0xD7, 0x00, 0x7C, 0x02, 0xF2, 0x01,
+0xD0, 0x36, 0x00, 0x5F, 0x00, 0x45, 0x00, 0xF0, 0x01, 0xD0, 0x3C, 0x20, 0xFD,
+0x00, 0x4D, 0x03, 0xD0, 0x05, 0xC0, 0x3F, 0x10, 0x53, 0x20, 0x74, 0x83, 0xF0,
+0x01, 0xC8, 0x37, 0x80, 0x57, 0x00, 0x4C, 0x00, 0x31, 0x01, 0xC0, 0x04, 0x44,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x2F, 0x00, 0x7F, 0x00, 0xFC,
+0x02, 0xF0, 0x06, 0xC0, 0x1F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x02, 0xC0,
+0x3D, 0x00, 0x3F, 0x00, 0xFD, 0x00, 0xF0, 0x03, 0x82, 0x3F, 0x10, 0xFF, 0x80,
+0xFC, 0x03, 0xF0, 0x07, 0xC0, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x02, 0x70, 0x03,
+0xC0, 0x3F, 0x00, 0x2D, 0x00, 0xFC, 0x00, 0xF2, 0x03, 0x80, 0x14, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xF3, 0x09, 0x8C, 0x07,
+0xF0, 0x1F, 0xC0, 0x7C, 0x00, 0xFF, 0x01, 0xFC, 0x27, 0xF0, 0x9F, 0xC0, 0x7F,
+0x02, 0xFF, 0x09, 0xFC, 0x27, 0xF0, 0x9F, 0xC0, 0x7D, 0x02, 0xEF, 0x01, 0xCC,
+0x07, 0xF0, 0x1E, 0x40, 0x3C, 0x00, 0xF3, 0x00, 0xCC, 0x03, 0xB0, 0x0F, 0xC0,
+0x3C, 0x00, 0xF3, 0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC0, 0x0F, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x47, 0x40, 0x11, 0x00, 0x45, 0x04, 0xD0,
+0x11, 0x52, 0x04, 0x00, 0x0D, 0x00, 0x74, 0x10, 0xD0, 0x01, 0x40, 0x07, 0x01,
+0x1D, 0x04, 0x74, 0x10, 0xD0, 0x40, 0xC0, 0x06, 0x01, 0x1D, 0x81, 0x44, 0x04,
+0xD0, 0x11, 0x40, 0x74, 0x08, 0x51, 0x21, 0x44, 0x07, 0x10, 0x15, 0x42, 0x74,
+0x00, 0xD1, 0x00, 0x44, 0x07, 0x10, 0x19, 0x48, 0x07, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x11, 0xA0, 0x37, 0x00, 0xC1, 0x04, 0x14, 0x03, 0xD0, 0x0D,
+0x60, 0x30, 0x05, 0xCD, 0x14, 0x34, 0x03, 0xD0, 0x4C, 0x40, 0x33, 0x00, 0xC5,
+0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x24, 0x03, 0xD0,
+0x0C, 0x40, 0x32, 0x00, 0x81, 0x00, 0x04, 0x02, 0x50, 0x0C, 0x40, 0x32, 0x00,
+0xC5, 0x00, 0x44, 0x02, 0x14, 0x0C, 0x40, 0x45, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA8, 0x05, 0x00, 0x01, 0x40, 0x54, 0x00, 0xD0, 0x01, 0x60,
+0x04, 0x30, 0x1D, 0x00, 0x74, 0x00, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x20,
+0x74, 0x00, 0xD0, 0x01, 0x40, 0x04, 0x00, 0x1D, 0x00, 0x64, 0x80, 0xC0, 0x01,
+0x40, 0x36, 0x00, 0xD1, 0x00, 0x44, 0x43, 0xD0, 0xAD, 0x40, 0x36, 0x04, 0xC5,
+0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA0, 0x33, 0x00, 0xD3, 0x00, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0x34,
+0x00, 0xDF, 0x80, 0x7C, 0x83, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C,
+0x03, 0xF0, 0x0D, 0x40, 0x37, 0x00, 0xDF, 0x00, 0x6C, 0x03, 0xF0, 0x0D, 0x40,
+0x86, 0x04, 0xD3, 0x09, 0x4C, 0x25, 0xF0, 0x3D, 0xC0, 0x26, 0x00, 0xD7, 0x09,
+0x0D, 0x03, 0x30, 0x09, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x07, 0x88, 0x0D, 0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00,
+0x3F, 0x00, 0xF4, 0x00, 0xF1, 0x03, 0xC8, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00,
+0xA0, 0x03, 0xC8, 0x0F, 0x00, 0x3F, 0x00, 0xDC, 0x00, 0xF1, 0x03, 0xC8, 0x19,
+0x00, 0xCF, 0x21, 0xBC, 0x01, 0x30, 0x16, 0xC2, 0x39, 0x02, 0xFB, 0x00, 0xFC,
+0x13, 0xF0, 0x0F, 0xC0, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x08, 0x35, 0x00, 0xDF, 0x05, 0x7C, 0x03, 0x32, 0x0D, 0xC2, 0x37, 0x00, 0xDF,
+0x00, 0x4C, 0x07, 0xF0, 0x0D, 0xC0, 0x77, 0x00, 0xDF, 0x01, 0x7C, 0x07, 0xF0,
+0x0D, 0xC0, 0x74, 0x00, 0xDF, 0x01, 0x4C, 0x03, 0x30, 0x0D, 0xC0, 0xB5, 0x00,
+0x93, 0x00, 0x4C, 0x0A, 0x70, 0x0D, 0xC2, 0xA4, 0x00, 0xD7, 0x00, 0x4C, 0x02,
+0xF0, 0x09, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x04, 0x10, 0x1D, 0x01, 0x74, 0x00, 0x14, 0xB0, 0x40, 0x07, 0x00, 0x1D, 0x00,
+0x44, 0x04, 0xC1, 0xA1, 0x42, 0x07, 0x00, 0x1D, 0x01, 0x74, 0x84, 0xD0, 0xE1,
+0x40, 0x44, 0x00, 0x0D, 0x00, 0x44, 0x00, 0xB0, 0x00, 0x40, 0x34, 0x00, 0xD1,
+0x80, 0x44, 0x13, 0x10, 0x0D, 0x40, 0x34, 0x10, 0xDD, 0x0A, 0x44, 0x46, 0xD0,
+0x1D, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x30,
+0x00, 0xCD, 0x02, 0x34, 0x03, 0x10, 0x3C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x04,
+0x1B, 0xD0, 0x0C, 0x40, 0x32, 0x00, 0xCD, 0x10, 0x34, 0x03, 0xD0, 0x0D, 0x40,
+0x30, 0x00, 0xCD, 0x00, 0x04, 0x03, 0x50, 0x0C, 0x44, 0x30, 0x00, 0xC1, 0x00,
+0x04, 0x83, 0x14, 0x08, 0x40, 0x12, 0x00, 0xC4, 0x00, 0x04, 0x03, 0xD0, 0x1C,
+0x40, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x48, 0x00,
+0x2D, 0x09, 0xF4, 0x24, 0x10, 0x12, 0x40, 0x4B, 0x00, 0x2D, 0x00, 0x84, 0x24,
+0xD0, 0x12, 0x40, 0x4B, 0x00, 0x2D, 0x41, 0xB4, 0x0C, 0xD0, 0x12, 0x60, 0xC8,
+0x00, 0x2D, 0x01, 0xC4, 0x04, 0xD2, 0x32, 0x40, 0x70, 0x00, 0x61, 0x01, 0x05,
+0x07, 0x10, 0x1C, 0x40, 0x7A, 0x00, 0xED, 0x01, 0x84, 0x07, 0xD1, 0x1A, 0x60,
+0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x30, 0x00, 0xCF,
+0x00, 0x3C, 0x03, 0x30, 0x0C, 0xC3, 0x33, 0x02, 0xCF, 0x08, 0x0C, 0x03, 0xF0,
+0x0C, 0xC2, 0x32, 0x00, 0xCD, 0x00, 0x3C, 0x03, 0xF0, 0x0C, 0xC0, 0x30, 0x00,
+0xCF, 0x00, 0x0C, 0x03, 0x70, 0x0C, 0xC0, 0x31, 0x00, 0xC3, 0x04, 0x0C, 0x03,
+0x70, 0x0C, 0xC0, 0x32, 0x00, 0xD7, 0x00, 0x0D, 0x03, 0xF2, 0x8C, 0x51, 0x48,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x0D, 0x00, 0x3F, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC8, 0x0F, 0x08, 0x3F, 0x04, 0xFC, 0x00, 0xF0, 0x03,
+0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F,
+0x40, 0xBC, 0x00, 0xB0, 0x13, 0xC4, 0x3F, 0x02, 0xFF, 0x00, 0xFE, 0x03, 0xF2,
+0x0F, 0xC0, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0A, 0xC2, 0x0B, 0xE0,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x37, 0x00, 0xDF, 0x01, 0x0D,
+0x07, 0x34, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x01, 0x4C, 0x07, 0x3C, 0x0D, 0xC0,
+0x77, 0x00, 0xD7, 0x01, 0x4D, 0x87, 0x34, 0x1D, 0xC0, 0x75, 0x40, 0xD3, 0x00,
+0x7E, 0x03, 0xF0, 0x1D, 0xC0, 0x24, 0x00, 0xD3, 0x00, 0x4C, 0x03, 0xB8, 0x09,
+0xC0, 0x54, 0x00, 0xDB, 0x00, 0x4D, 0x02, 0xF0, 0x09, 0xC0, 0x41, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x90, 0x08, 0x00, 0x2D, 0x00, 0x84, 0x00,
+0x18, 0x02, 0x40, 0x0B, 0x00, 0x3D, 0x00, 0xD4, 0x00, 0x10, 0x02, 0x40, 0x0F,
+0x00, 0x31, 0x00, 0xC4, 0x00, 0x10, 0x02, 0x40, 0x0C, 0x00, 0x21, 0x00, 0x9C,
+0x80, 0xD0, 0x02, 0x40, 0x39, 0x00, 0xE1, 0x00, 0x84, 0x03, 0x10, 0x0E, 0x42,
+0x38, 0x00, 0xF1, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x4B, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xED, 0x01, 0xC4, 0x87, 0x12,
+0x1E, 0x60, 0x7B, 0x80, 0xE9, 0x01, 0x84, 0x07, 0x10, 0x1E, 0x42, 0x7B, 0x20,
+0xE5, 0x01, 0xA0, 0x07, 0x10, 0x1E, 0x40, 0x7B, 0x00, 0xE9, 0x01, 0x94, 0x07,
+0xD0, 0x1F, 0x40, 0x72, 0x08, 0xC1, 0x01, 0x04, 0x07, 0x10, 0x1C, 0x40, 0x70,
+0x00, 0xE1, 0x01, 0x84, 0x06, 0xD0, 0x1A, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x16, 0x20, 0x03, 0x00, 0x0D, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x03, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x18, 0x00, 0x40, 0x03, 0x00, 0x01,
+0x00, 0x24, 0x00, 0x10, 0x00, 0x40, 0x02, 0x00, 0x09, 0x00, 0x14, 0x00, 0xD0,
+0x00, 0x40, 0x33, 0x40, 0xC1, 0x00, 0x05, 0x03, 0x14, 0x0C, 0x50, 0x30, 0x52,
+0x91, 0x48, 0x04, 0x02, 0xD0, 0x1C, 0x40, 0x5B, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x17, 0x28, 0x15, 0x00, 0x5F, 0x00, 0x4C, 0x01, 0x30, 0x05, 0xC0,
+0x17, 0x00, 0x5F, 0x00, 0x4C, 0x01, 0x30, 0x04, 0xC0, 0x17, 0x10, 0x57, 0x00,
+0x64, 0x01, 0x30, 0x05, 0xC0, 0x17, 0x00, 0x5B, 0x00, 0x5C, 0x01, 0xF0, 0x05,
+0xC0, 0x1E, 0x00, 0x73, 0x02, 0xCC, 0x09, 0x30, 0x07, 0xC0, 0x5C, 0x00, 0x53,
+0x01, 0x4C, 0x01, 0xF2, 0x05, 0xC1, 0x5F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x0D, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x23, 0xC0, 0x0F,
+0x00, 0x3F, 0x20, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xDC,
+0x00, 0xF0, 0x23, 0xC0, 0x0D, 0x20, 0x37, 0x02, 0xDC, 0x00, 0xF0, 0x03, 0xE2,
+0x41, 0x00, 0x0F, 0x10, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x02,
+0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x25, 0x00, 0x9F, 0x05, 0x7C, 0x16, 0xF0, 0x09, 0xC0, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x0A, 0xF0, 0x29, 0xC0, 0x24, 0x01, 0x9F, 0x01, 0x5C, 0x02,
+0xF0, 0x19, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x20, 0x09, 0xC0, 0x27,
+0x20, 0x93, 0x20, 0x0C, 0x02, 0x34, 0x08, 0xC0, 0x24, 0x00, 0x9F, 0x05, 0x4C,
+0x06, 0xF0, 0x09, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x26, 0x00, 0x9D, 0x02, 0x74, 0x02, 0x90, 0x49, 0x48, 0x27, 0x00, 0x9D,
+0x00, 0x74, 0x0A, 0xD9, 0x39, 0x40, 0x24, 0x00, 0x9D, 0x02, 0x74, 0x0A, 0xD0,
+0xD9, 0x40, 0xA7, 0x80, 0x9F, 0x12, 0x34, 0x02, 0xB0, 0x09, 0x40, 0xA7, 0x20,
+0x91, 0x82, 0x44, 0x0A, 0x30, 0x29, 0x40, 0xA4, 0x00, 0x9D, 0x02, 0x44, 0x06,
+0xD0, 0x08, 0xC0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0,
+0x24, 0x00, 0xBD, 0x00, 0xF4, 0x02, 0xD0, 0x0B, 0x40, 0x2F, 0x00, 0xB5, 0x00,
+0xF4, 0x02, 0xD0, 0x0B, 0x60, 0x2C, 0x00, 0xBD, 0x08, 0xF6, 0x06, 0xD0, 0x0B,
+0x40, 0x6F, 0x10, 0xBD, 0x00, 0xF4, 0x02, 0x50, 0x1B, 0x42, 0x27, 0x04, 0x91,
+0x10, 0x64, 0x42, 0x00, 0x09, 0x41, 0x24, 0x84, 0x9D, 0x00, 0x64, 0x22, 0xD0,
+0x89, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x28,
+0x00, 0xAD, 0x01, 0xB4, 0x02, 0x91, 0x0A, 0x40, 0x2B, 0x00, 0xAD, 0x00, 0xB4,
+0x06, 0xD0, 0x0B, 0x42, 0x29, 0x00, 0xAD, 0x01, 0xB4, 0x06, 0xD0, 0x0A, 0x60,
+0x6B, 0x00, 0xA5, 0x00, 0xF4, 0x02, 0xD2, 0x0A, 0x60, 0x23, 0x41, 0x81, 0x04,
+0x24, 0x92, 0x90, 0x48, 0x40, 0x20, 0x01, 0x8D, 0x40, 0x24, 0x02, 0xD0, 0x09,
+0x40, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x06, 0x00,
+0x0F, 0x0A, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x87, 0x12, 0x17, 0x0A, 0x7C, 0x28,
+0xD0, 0xA5, 0xD0, 0x84, 0x02, 0x1D, 0x0A, 0x5C, 0x28, 0xF0, 0xA0, 0xC0, 0x87,
+0x02, 0x1D, 0x00, 0x7C, 0x00, 0x60, 0x03, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x65,
+0x00, 0x32, 0x01, 0xD0, 0x04, 0x00, 0x5F, 0x0A, 0x6C, 0x00, 0xF0, 0x01, 0xC0,
+0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x27, 0x00, 0x9F,
+0x00, 0x7C, 0x02, 0xB0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x26, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xB0, 0x08, 0xC0, 0x2F, 0x02, 0xBF, 0x08, 0xDC, 0x22,
+0x70, 0x8B, 0xC0, 0x2F, 0x02, 0xBF, 0x00, 0xDD, 0x02, 0xF0, 0x0B, 0xC0, 0x77,
+0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x27, 0x00, 0xB3, 0x00,
+0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x24, 0x00, 0xBF, 0x00, 0xCC, 0x02, 0xF0, 0x0A,
+0xC0, 0x2D, 0x02, 0xB7, 0x00, 0xFE, 0x02, 0xF0, 0x8B, 0xC0, 0x2F, 0x00, 0x9F,
+0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x34, 0x00, 0x9F, 0x00, 0x6D, 0x12, 0x30,
+0x49, 0xC1, 0x24, 0x01, 0xB3, 0x00, 0xCC, 0x03, 0xF0, 0x0B, 0xC0, 0x73, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x05, 0x00, 0x11, 0x04, 0x45,
+0x00, 0xD0, 0x01, 0x40, 0x04, 0x00, 0x1D, 0x00, 0x45, 0x50, 0x70, 0x41, 0x40,
+0x04, 0x01, 0x11, 0x10, 0x74, 0x40, 0xD1, 0x01, 0x40, 0x07, 0x05, 0x1D, 0x00,
+0x74, 0x00, 0xD0, 0x01, 0x40, 0x05, 0x00, 0x1D, 0x08, 0x44, 0x00, 0x10, 0x01,
+0x40, 0x0C, 0x12, 0x01, 0x10, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x63, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x25, 0x40, 0x81, 0x14, 0x04, 0x02,
+0xD0, 0x08, 0x40, 0x20, 0x00, 0x9D, 0x00, 0x04, 0x12, 0xD0, 0x48, 0x41, 0x21,
+0x21, 0x85, 0x04, 0x30, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x01, 0xAD, 0x00, 0xB4,
+0x03, 0xD0, 0x0B, 0x40, 0x6A, 0x02, 0xAD, 0x01, 0x84, 0x26, 0x10, 0x1A, 0x40,
+0x68, 0x00, 0x99, 0x04, 0x05, 0x02, 0xD0, 0x0C, 0x40, 0x4B, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0xD1, 0x00, 0x44, 0x02, 0xD0,
+0x09, 0x40, 0x24, 0x80, 0x9D, 0x40, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00,
+0x91, 0x80, 0x74, 0x02, 0xD2, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0xF4, 0x82,
+0xD0, 0x0B, 0x40, 0x2F, 0x00, 0xBD, 0x00, 0xC4, 0x02, 0x10, 0x0B, 0x40, 0x2C,
+0x10, 0x99, 0x01, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0x00, 0x25, 0x00, 0x93, 0x00, 0x48, 0x02, 0xF0, 0x08,
+0xC0, 0x24, 0x00, 0x9F, 0x20, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x00, 0x95,
+0x00, 0x74, 0x02, 0xE0, 0x09, 0x80, 0x27, 0x00, 0x9F, 0x40, 0x7E, 0x02, 0xF0,
+0x09, 0xC0, 0xA6, 0x02, 0x9F, 0x03, 0x4C, 0x2A, 0x34, 0xB9, 0xC0, 0xA4, 0x00,
+0x8B, 0xA0, 0x4C, 0x82, 0xF0, 0x09, 0xC0, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x08, 0x24, 0x00, 0x9F, 0x80, 0x7C, 0x02, 0xF0, 0x09, 0xD0,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x70, 0x09, 0xC8, 0x27, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x25, 0x00, 0x9F, 0x03, 0x5C, 0x06, 0xF0, 0x19, 0xD0, 0x27, 0x40, 0x97,
+0x20, 0x7C, 0x12, 0xF0, 0x09, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x7E, 0x00, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x13, 0x10, 0x7C, 0x00, 0xF2, 0x81, 0xD1, 0x06, 0x00, 0x1F, 0x00, 0x7C,
+0x60, 0xF2, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0,
+0x07, 0x00, 0x03, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xC0, 0x03, 0x00, 0x1F, 0x00,
+0x4D, 0x04, 0xF0, 0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x10, 0x00, 0x7D, 0x00, 0x76, 0x45, 0xD0, 0x07, 0xC0, 0x15, 0x20,
+0x65, 0x00, 0xF4, 0x09, 0xD0, 0x27, 0xD0, 0x16, 0x00, 0x77, 0x00, 0xF4, 0x09,
+0xD2, 0x07, 0x40, 0x1F, 0x00, 0x5D, 0x00, 0x74, 0x01, 0x14, 0x04, 0xC0, 0x15,
+0x00, 0x51, 0x01, 0x74, 0x01, 0xD0, 0x15, 0x40, 0x57, 0x10, 0x7D, 0x41, 0xC4,
+0x01, 0xD0, 0x05, 0x40, 0x43, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA0, 0x32, 0x00, 0xDD, 0x40, 0x34, 0x07, 0xD0, 0x04, 0x40, 0x31, 0x80, 0x49,
+0x00, 0x34, 0x4B, 0xD0, 0x3D, 0x40, 0x36, 0x30, 0xCD, 0x00, 0x34, 0x07, 0xD8,
+0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x31, 0x00,
+0xC1, 0x21, 0x34, 0x03, 0xD0, 0x1C, 0x40, 0x73, 0x00, 0xCD, 0x00, 0x04, 0x07,
+0xD0, 0x0C, 0x40, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80,
+0x38, 0x00, 0x6D, 0x00, 0xB4, 0x03, 0xD0, 0x0A, 0x40, 0x79, 0x02, 0x6D, 0x10,
+0xB6, 0x03, 0xD0, 0x0E, 0x58, 0x2A, 0x00, 0x6D, 0x00, 0xB4, 0x01, 0xD9, 0x02,
+0x40, 0x1B, 0x00, 0xAD, 0x00, 0xB4, 0x07, 0x10, 0x06, 0x40, 0x71, 0x40, 0xE1,
+0x10, 0xB4, 0x02, 0xD0, 0x0E, 0x41, 0x3B, 0x04, 0xED, 0x02, 0x84, 0x43, 0xD0,
+0x0A, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x78,
+0x00, 0xAF, 0x01, 0xB4, 0x07, 0xD0, 0x16, 0xC0, 0x7D, 0x00, 0x6B, 0x01, 0xBC,
+0x06, 0xF0, 0x16, 0xD0, 0x7A, 0x00, 0xAF, 0x01, 0xB4, 0x06, 0xF0, 0x1E, 0xC0,
+0x6B, 0x00, 0x6F, 0x01, 0xB8, 0x07, 0x30, 0x1A, 0xC0, 0x59, 0x00, 0x63, 0x01,
+0xBC, 0x05, 0xF0, 0x16, 0xC0, 0x5B, 0x00, 0xEF, 0x01, 0x8C, 0x07, 0xF0, 0x1E,
+0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00,
+0x1F, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x75, 0x20, 0x57, 0x00, 0x7C, 0x00,
+0xF0, 0x05, 0xD0, 0x27, 0x00, 0x17, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC2, 0x15, 0x00, 0x5F, 0x00, 0x7C,
+0x00, 0xF8, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x7D, 0x00, 0xFF,
+0x01, 0xBC, 0x07, 0xF8, 0x87, 0xC0, 0x7C, 0x00, 0xB3, 0x89, 0xCC, 0x05, 0xA0,
+0x1B, 0xC0, 0x7F, 0x20, 0xF3, 0x01, 0xDC, 0x07, 0x30, 0x1F, 0xC0, 0x7C, 0x00,
+0xF3, 0x01, 0xCC, 0x06, 0xF2, 0x1F, 0xC0, 0x7F, 0x00, 0xBF, 0x01, 0xCC, 0x07,
+0xF0, 0x1B, 0xC0, 0x6C, 0x00, 0xF3, 0x01, 0xFC, 0x05, 0x30, 0x1F, 0xC0, 0x1B,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x00, 0x6D, 0x00,
+0x9C, 0x03, 0x18, 0x0A, 0x40, 0x38, 0x00, 0xA1, 0x00, 0xC4, 0x03, 0x11, 0x0A,
+0x40, 0x2B, 0x00, 0x71, 0x00, 0xC4, 0x02, 0x10, 0x02, 0x40, 0x1C, 0x00, 0xA1,
+0x00, 0x84, 0x0A, 0xD0, 0x06, 0x40, 0x3B, 0x00, 0xAD, 0x00, 0x84, 0x02, 0xD0,
+0x0A, 0x40, 0x28, 0x12, 0xE1, 0x00, 0xB4, 0x00, 0xB0, 0x0E, 0x40, 0x57, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0xAD, 0x00, 0xB4,
+0x03, 0x50, 0x87, 0x40, 0x3C, 0x00, 0xB1, 0x00, 0x84, 0x20, 0x10, 0x02, 0x40,
+0xBF, 0x00, 0xA9, 0x00, 0x84, 0x01, 0x10, 0x0F, 0x40, 0x2A, 0x00, 0x79, 0x02,
+0x84, 0x02, 0xD0, 0x0A, 0x40, 0x1B, 0x00, 0x0D, 0x00, 0x84, 0x01, 0xD0, 0x80,
+0x40, 0x00, 0x00, 0xA1, 0x00, 0xF4, 0x40, 0x10, 0x0E, 0x40, 0x03, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0xF1, 0x00, 0x1D, 0x02, 0x34, 0x43,
+0x10, 0x00, 0x41, 0xB0, 0x04, 0x81, 0x04, 0x04, 0x34, 0x91, 0x38, 0x40, 0x23,
+0x00, 0x09, 0x0D, 0x04, 0x34, 0x10, 0x00, 0x41, 0x42, 0x43, 0x09, 0x20, 0x04,
+0x06, 0xD0, 0x10, 0x40, 0x13, 0x00, 0x0D, 0x12, 0x04, 0x00, 0xD0, 0x00, 0x40,
+0x80, 0x00, 0x01, 0x20, 0x34, 0x84, 0x90, 0x0C, 0x40, 0x0B, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0xB5, 0x00, 0xDF, 0x05, 0x7C, 0x07, 0x50,
+0x24, 0xC0, 0x38, 0x00, 0x93, 0x02, 0x44, 0x0B, 0xB0, 0x05, 0xC0, 0x73, 0x00,
+0xD9, 0x02, 0x44, 0x0B, 0x10, 0x2C, 0xC0, 0xB6, 0x00, 0xCB, 0x00, 0x0C, 0x69,
+0xF1, 0x2D, 0x41, 0x67, 0x00, 0xDF, 0x03, 0x4D, 0x07, 0xF0, 0xBD, 0xD0, 0x74,
+0x40, 0xD3, 0x00, 0x3C, 0x05, 0x30, 0x0D, 0xC0, 0x57, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0x00, 0x37, 0x06, 0x9F, 0x10, 0x5C, 0x23, 0x70, 0x1D,
+0xC0, 0x77, 0x00, 0x9F, 0x03, 0x7C, 0x02, 0x71, 0x85, 0xC0, 0x37, 0x22, 0x97,
+0x02, 0x7C, 0x01, 0xF0, 0x3D, 0xC0, 0x25, 0x00, 0x97, 0x08, 0x7C, 0x01, 0xF0,
+0x05, 0xC1, 0x63, 0x00, 0xDF, 0x81, 0x7C, 0x06, 0xF0, 0x1D, 0xC2, 0x77, 0x14,
+0xDF, 0x03, 0x7C, 0x01, 0xF0, 0x8D, 0xC2, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0x7F, 0x00, 0xCC, 0x0F, 0xF0, 0x07, 0xC0,
+0x3E, 0x00, 0xB3, 0x00, 0xFC, 0x17, 0x32, 0x03, 0xC5, 0x2C, 0x00, 0x73, 0x00,
+0xCE, 0x02, 0x30, 0x13, 0xC0, 0x1C, 0x01, 0x72, 0x00, 0xCC, 0x01, 0x30, 0x0B,
+0xC0, 0x0F, 0x02, 0x73, 0x00, 0xFC, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0xFF,
+0x00, 0xCC, 0x01, 0x30, 0x0F, 0xC0, 0x03, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x81, 0x20, 0x36, 0x00, 0x1D, 0x00, 0x44, 0x03, 0xD0, 0x05, 0x40, 0x34,
+0x20, 0x91, 0x09, 0x74, 0x04, 0x10, 0x10, 0x41, 0x24, 0x00, 0x11, 0x02, 0x44,
+0x00, 0x10, 0x11, 0x40, 0xC4, 0x01, 0x11, 0x00, 0x44, 0x09, 0x10, 0x01, 0xC0,
+0x05, 0x00, 0x51, 0x20, 0x74, 0x00, 0xD0, 0x05, 0x40, 0x17, 0x10, 0xDD, 0x00,
+0x44, 0x05, 0x10, 0x0D, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0xA0, 0x36, 0x00, 0xDD, 0x04, 0x44, 0x02, 0xD8, 0x85, 0x40, 0x36, 0x00,
+0x91, 0x02, 0x14, 0x01, 0x18, 0x15, 0x40, 0x34, 0x81, 0xC9, 0x06, 0x04, 0x03,
+0x10, 0x6D, 0x40, 0x32, 0x80, 0xD5, 0x00, 0x44, 0x00, 0x10, 0x0D, 0x40, 0x27,
+0x00, 0x91, 0x00, 0x74, 0x03, 0xD0, 0x09, 0x40, 0x27, 0x00, 0xCD, 0x86, 0x44,
+0x04, 0x10, 0x1D, 0x40, 0x07, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x30, 0x00, 0x8D, 0x00, 0x05, 0x02, 0xD0, 0x0C, 0x40, 0x36, 0x00, 0x81,
+0x00, 0x34, 0x02, 0x14, 0x0D, 0x50, 0x34, 0x00, 0x80, 0x00, 0x05, 0x02, 0x14,
+0x0D, 0x60, 0x22, 0x40, 0x95, 0xA0, 0x04, 0x00, 0x10, 0x04, 0x40, 0x23, 0x40,
+0x81, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x00, 0xCD, 0x00, 0x04, 0x04,
+0x14, 0x0C, 0x40, 0x43, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x36, 0x00, 0x5F, 0x00, 0x4C, 0x03, 0xF0, 0x05, 0xC0, 0x36, 0x00, 0x93, 0x00,
+0x7C, 0x01, 0x30, 0x01, 0xC0, 0x24, 0x10, 0x5B, 0x80, 0x46, 0x81, 0x30, 0x01,
+0xC0, 0x16, 0x00, 0x57, 0x00, 0x4C, 0x00, 0x30, 0x09, 0xC0, 0x07, 0x00, 0x13,
+0x00, 0x7C, 0x01, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0xDF, 0x00, 0x4D, 0x00, 0x30,
+0x0D, 0xC0, 0x03, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x3F,
+0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x06, 0xC0, 0x39, 0x00, 0xAF, 0x80, 0xFC,
+0x00, 0xF0, 0x0B, 0xC0, 0x2B, 0x80, 0x3F, 0x00, 0xFE, 0x00, 0xF0, 0x02, 0xC0,
+0x0D, 0x00, 0x2B, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0D, 0x00, 0x3F, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xBC, 0x00, 0xF0, 0x0F,
+0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x2F, 0x00,
+0xFF, 0x01, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x5D, 0x00, 0x6F, 0x01, 0xCC, 0x06,
+0xF1, 0x0F, 0xC0, 0x7C, 0x00, 0x33, 0x03, 0xEC, 0x24, 0xB2, 0xCF, 0xC8, 0x3C,
+0x21, 0xFB, 0x84, 0xDC, 0x87, 0xB0, 0x0F, 0x40, 0x5C, 0x02, 0x3F, 0x08, 0xAC,
+0x85, 0xB0, 0x0F, 0xC2, 0x5F, 0x00, 0x37, 0x80, 0xCD, 0x06, 0x90, 0x0B, 0x80,
+0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x00, 0xDD,
+0x01, 0x74, 0x00, 0xD0, 0x3D, 0x42, 0x60, 0x00, 0x1D, 0x01, 0x44, 0x06, 0xD2,
+0x1D, 0x40, 0x7C, 0x00, 0x11, 0x20, 0x44, 0x10, 0x10, 0xAF, 0x40, 0x7C, 0x02,
+0xF1, 0x02, 0x44, 0x07, 0x14, 0x6D, 0x40, 0x04, 0x01, 0x9D, 0x04, 0x54, 0x85,
+0x10, 0x9F, 0x00, 0x47, 0x40, 0x93, 0x8B, 0x44, 0x52, 0x10, 0x09, 0x40, 0x0D,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x03, 0x00, 0xCD, 0x00,
+0x34, 0x00, 0xD0, 0x2C, 0x40, 0x31, 0x00, 0x4D, 0x00, 0x04, 0x02, 0xD0, 0x0C,
+0x60, 0x30, 0x20, 0x10, 0x04, 0x64, 0x10, 0x90, 0x4C, 0x48, 0x30, 0x10, 0xC9,
+0x08, 0x34, 0x03, 0x02, 0x2C, 0x45, 0x12, 0x01, 0x0D, 0x00, 0x24, 0x01, 0xD0,
+0x0C, 0x42, 0x33, 0x10, 0x09, 0x20, 0x04, 0x03, 0x10, 0x00, 0x40, 0x4D, 0x80,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x64, 0x00, 0xDD, 0x00, 0x74,
+0x04, 0xC0, 0x0D, 0x60, 0x24, 0x00, 0x1D, 0x04, 0x45, 0x02, 0xD0, 0x0D, 0x40,
+0x34, 0x08, 0x11, 0x00, 0x64, 0x44, 0x10, 0x0D, 0x48, 0x34, 0x80, 0xD1, 0x00,
+0x64, 0x03, 0x50, 0x0D, 0x40, 0x06, 0x04, 0x8D, 0x11, 0x74, 0x85, 0x54, 0x0D,
+0x42, 0x07, 0x00, 0x55, 0x08, 0x44, 0x02, 0x10, 0x11, 0x41, 0x0D, 0x20, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x66, 0x00, 0xDF, 0x00, 0x78, 0x4E,
+0xE0, 0x0D, 0xC0, 0x25, 0x10, 0x4F, 0x07, 0x4C, 0x22, 0xF0, 0x9D, 0x40, 0x34,
+0x40, 0x13, 0x0D, 0x2C, 0x0C, 0xB2, 0x0D, 0xD0, 0x34, 0x10, 0xDB, 0x00, 0x74,
+0x03, 0x30, 0x0D, 0x50, 0x06, 0x28, 0x9E, 0x01, 0x6C, 0x14, 0xF0, 0x0D, 0xC0,
+0x13, 0x00, 0x1B, 0x03, 0x4C, 0x06, 0x30, 0x19, 0xC0, 0x21, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x2D, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0,
+0x0E, 0xC0, 0x2F, 0x00, 0x7F, 0x00, 0xFC, 0x06, 0xF0, 0x0E, 0xC0, 0x3F, 0x00,
+0xFF, 0x00, 0xDC, 0x02, 0x70, 0x0E, 0xC0, 0x3F, 0x00, 0xEF, 0x00, 0xDC, 0x03,
+0xB0, 0x0F, 0xC2, 0x0D, 0x10, 0xBD, 0x00, 0xDC, 0x01, 0xB4, 0x0F, 0xC0, 0x8F,
+0x50, 0x6B, 0x00, 0xFC, 0x26, 0xF4, 0x0A, 0xC0, 0x1F, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x08, 0x85, 0x02, 0xDF, 0x00, 0x7C, 0x40, 0x30, 0x0D,
+0xC0, 0x37, 0x00, 0x57, 0x02, 0x4C, 0x42, 0xF0, 0x0D, 0xC0, 0x37, 0x02, 0xDF,
+0x00, 0x7C, 0x0A, 0xF0, 0x0D, 0xC4, 0x34, 0x0A, 0xDF, 0x00, 0x5C, 0x23, 0x70,
+0x0D, 0xC1, 0x15, 0x00, 0x13, 0x02, 0x4C, 0x00, 0x50, 0x0D, 0xC9, 0x36, 0x08,
+0x17, 0x12, 0x4D, 0x03, 0xF0, 0x09, 0x82, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0xA0, 0x24, 0x00, 0xDD, 0x60, 0x70, 0x18, 0x10, 0x0F, 0x40,
+0x27, 0x00, 0x51, 0x05, 0x44, 0x4E, 0xD0, 0x0D, 0x40, 0x33, 0x00, 0xCD, 0x00,
+0x74, 0x02, 0xD0, 0xAF, 0x40, 0x38, 0x02, 0xFD, 0x00, 0x34, 0x2B, 0xB0, 0x2E,
+0x40, 0x04, 0x40, 0x11, 0x08, 0x2C, 0x03, 0x10, 0x2F, 0x48, 0x04, 0x02, 0x51,
+0x00, 0x44, 0x13, 0xD0, 0x09, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x20, 0xC0, 0x04, 0xCD, 0x00, 0x34, 0x0E, 0x50, 0x0C, 0x40, 0x13,
+0x00, 0x05, 0x06, 0x05, 0x0E, 0xD0, 0x08, 0x40, 0xF3, 0x04, 0x0D, 0x00, 0x34,
+0x00, 0xD0, 0x0C, 0x60, 0x70, 0x00, 0xCD, 0x07, 0x34, 0x03, 0x10, 0x0C, 0x48,
+0x11, 0x80, 0x04, 0x00, 0x04, 0x00, 0x40, 0x3C, 0x40, 0x90, 0x00, 0x49, 0x02,
+0x44, 0x13, 0xD1, 0x50, 0x44, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x00, 0x58, 0x00, 0xED, 0x01, 0xB4, 0x01, 0x50, 0x1E, 0x40, 0x6B, 0x00,
+0x31, 0x01, 0x84, 0x06, 0xD0, 0x1A, 0x40, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07,
+0xD0, 0x1C, 0x40, 0x78, 0x00, 0xED, 0x31, 0xB4, 0x07, 0x90, 0x1E, 0x40, 0x48,
+0x80, 0xE5, 0x01, 0xE4, 0x04, 0x10, 0x9C, 0x40, 0x4C, 0x01, 0xC9, 0x01, 0x84,
+0x16, 0xD8, 0x9A, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x1A, 0x90, 0x02, 0xCF, 0x00, 0x7C, 0x23, 0x70, 0x0C, 0xC0, 0x33, 0x00, 0x07,
+0x04, 0x0C, 0x02, 0xF0, 0x4C, 0xC0, 0x33, 0x01, 0xCD, 0x00, 0x3C, 0x02, 0xF0,
+0x8C, 0x40, 0x30, 0x02, 0xCF, 0x00, 0x3C, 0x03, 0x30, 0xDD, 0xC0, 0x15, 0x2A,
+0x57, 0x24, 0x0C, 0x61, 0x70, 0x8C, 0xC9, 0x22, 0x90, 0x89, 0x12, 0x0C, 0x03,
+0xF0, 0x00, 0xC1, 0x4B, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38,
+0x3D, 0x08, 0xFF, 0x00, 0xFC, 0x13, 0xB0, 0x0F, 0xC1, 0x2F, 0x00, 0x3F, 0x00,
+0xFC, 0x22, 0xF0, 0x0F, 0xC0, 0x77, 0x00, 0xDF, 0x08, 0xFC, 0x23, 0xF0, 0x2D,
+0x52, 0x3F, 0x20, 0xDF, 0x00, 0x3C, 0x03, 0xF4, 0x0D, 0xC0, 0x07, 0x20, 0xDB,
+0x00, 0x7C, 0x81, 0xF0, 0x8F, 0xC2, 0x0B, 0x81, 0xF7, 0x00, 0xF0, 0x12, 0xF0,
+0x03, 0xC2, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0x1F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0x1F, 0x00, 0x6C, 0x01, 0xF0, 0x0D, 0xC0,
+0xB7, 0x00, 0xDF, 0x08, 0x3C, 0x03, 0x31, 0x1D, 0xC8, 0x07, 0x10, 0x9F, 0x00,
+0x4F, 0x00, 0xF0, 0x4D, 0xC8, 0x10, 0x08, 0x9B, 0x00, 0x4D, 0x83, 0x30, 0x01,
+0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x39, 0x00,
+0xED, 0x00, 0xB4, 0x03, 0xD3, 0x4E, 0x40, 0x2B, 0x00, 0x2D, 0x00, 0x9C, 0x02,
+0xD0, 0x0A, 0x60, 0xBB, 0x10, 0xFC, 0x00, 0x84, 0x03, 0xD0, 0x4E, 0x40, 0xBB,
+0x04, 0xED, 0x0C, 0xB4, 0x03, 0x40, 0x2E, 0x40, 0x0B, 0x00, 0xED, 0x20, 0x84,
+0x00, 0xD0, 0xAE, 0x40, 0x08, 0x00, 0xE7, 0x00, 0xC4, 0x83, 0x12, 0x0F, 0x40,
+0x4C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x59, 0x18, 0xE5,
+0x01, 0xB4, 0x07, 0x50, 0x5E, 0x40, 0x7B, 0x00, 0x2D, 0x01, 0xB4, 0x06, 0x50,
+0x1E, 0x40, 0x7B, 0x01, 0xED, 0x11, 0x84, 0x07, 0xD0, 0xDE, 0x40, 0x7B, 0x01,
+0xED, 0x81, 0xB4, 0x07, 0x00, 0x4E, 0x40, 0x5B, 0x20, 0xED, 0x01, 0x94, 0x04,
+0xD1, 0x5C, 0x50, 0x69, 0x00, 0x85, 0x01, 0x94, 0x0F, 0x10, 0x16, 0x40, 0x12,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0xB3, 0x80, 0xCD, 0x40,
+0x34, 0x27, 0xD0, 0x0C, 0x40, 0x23, 0x11, 0x8D, 0x03, 0x14, 0x07, 0xD0, 0x0C,
+0x40, 0x33, 0x00, 0xCD, 0x01, 0x04, 0x47, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x00, 0x34, 0x83, 0x00, 0x0C, 0x44, 0xA3, 0x02, 0xDD, 0x02, 0x04, 0x05, 0xD0,
+0x0C, 0x44, 0x01, 0x00, 0xC5, 0x07, 0x14, 0x87, 0x10, 0x6C, 0x40, 0x5A, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x1D, 0x04, 0x5F, 0x00, 0xFC,
+0x09, 0xF0, 0x05, 0xC0, 0xDF, 0x01, 0x7F, 0x44, 0x74, 0x45, 0xF8, 0x05, 0xC0,
+0x17, 0x00, 0x7F, 0x02, 0xCD, 0x95, 0xF0, 0x05, 0x40, 0x17, 0x00, 0x5F, 0x80,
+0x3C, 0x01, 0x31, 0x05, 0xC0, 0x5F, 0x00, 0x7F, 0x02, 0x8C, 0xBD, 0xF1, 0x05,
+0xC0, 0x1D, 0x00, 0x67, 0x07, 0x5C, 0x01, 0x36, 0x27, 0xC4, 0x5E, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x05, 0x04, 0x1F, 0x00, 0x7C, 0x80,
+0xF0, 0x01, 0xC0, 0x07, 0x08, 0x1F, 0x10, 0x70, 0x00, 0xF9, 0x01, 0xC4, 0x07,
+0x00, 0x1F, 0x04, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x42, 0x7C,
+0x08, 0xF4, 0x01, 0xC0, 0x07, 0x01, 0x1D, 0x82, 0x7C, 0x00, 0xF0, 0x01, 0xA0,
+0x86, 0x00, 0x16, 0x00, 0x68, 0x08, 0xF2, 0x01, 0xD0, 0x49, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x01, 0x97, 0x00, 0x7C, 0x4E, 0xF8,
+0x09, 0xC0, 0x27, 0x00, 0x93, 0x82, 0x7C, 0x02, 0xF0, 0x09, 0xC8, 0x27, 0x89,
+0x93, 0x80, 0x7C, 0x02, 0x30, 0x19, 0xC0, 0x64, 0x00, 0x9F, 0x00, 0x7C, 0x16,
+0x30, 0x08, 0xC0, 0x24, 0x00, 0x9F, 0x39, 0x4C, 0x02, 0x34, 0x29, 0xD8, 0x24,
+0x40, 0x91, 0x09, 0x4C, 0x0E, 0x34, 0x08, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x20, 0x66, 0x01, 0x9D, 0x00, 0x74, 0x0E, 0xD0, 0x09,
+0x60, 0x23, 0x20, 0x91, 0x03, 0x76, 0x06, 0xD0, 0x09, 0x40, 0xEB, 0x81, 0x8B,
+0x00, 0x6C, 0x02, 0x50, 0x19, 0xD0, 0x64, 0x12, 0x9D, 0x02, 0x74, 0x02, 0xB0,
+0x09, 0xC0, 0x26, 0x00, 0x9D, 0x43, 0x45, 0x2E, 0x10, 0x38, 0x48, 0xA0, 0x11,
+0x91, 0x01, 0x44, 0x02, 0x12, 0x29, 0x40, 0x05, 0x80, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x24, 0x18, 0x9D, 0x00, 0x54, 0x0A, 0xD0, 0x09, 0x40,
+0x27, 0x00, 0x91, 0x10, 0x74, 0x0E, 0xD1, 0x09, 0x48, 0x25, 0x80, 0x91, 0x00,
+0x14, 0x02, 0x10, 0x88, 0x40, 0x24, 0x00, 0x9D, 0x02, 0x54, 0x0A, 0x90, 0x09,
+0x44, 0x24, 0x00, 0x9D, 0x02, 0x44, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x95,
+0x02, 0x25, 0x02, 0x10, 0x49, 0x60, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x22, 0x20, 0x05, 0x8D, 0x00, 0x34, 0x52, 0xD0, 0x08, 0x40, 0xA7,
+0x08, 0x81, 0x00, 0x36, 0x02, 0xDA, 0x08, 0x40, 0x23, 0x00, 0x91, 0x08, 0x04,
+0x22, 0x10, 0x8C, 0x60, 0x22, 0x80, 0x8D, 0x24, 0x34, 0x02, 0x94, 0x58, 0x40,
+0x22, 0x00, 0x8D, 0x0C, 0x44, 0x03, 0x10, 0x0C, 0x40, 0x24, 0x00, 0x85, 0x00,
+0x24, 0x22, 0x10, 0x48, 0x40, 0x41, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB8, 0x06, 0x11, 0x1F, 0x00, 0x5C, 0x10, 0xD0, 0x41, 0x41, 0x07, 0x40,
+0x13, 0x00, 0x76, 0x00, 0xF0, 0x01, 0xC0, 0x47, 0x40, 0x11, 0x02, 0x54, 0x08,
+0x34, 0x61, 0xC1, 0x14, 0x15, 0x1F, 0x8A, 0x7C, 0x00, 0xB4, 0xA1, 0xC4, 0x84,
+0x02, 0x0F, 0x02, 0x4C, 0x00, 0x30, 0x41, 0xC1, 0x04, 0x00, 0x15, 0x14, 0x6C,
+0x09, 0x30, 0xA5, 0xC0, 0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB8, 0x2F, 0x05, 0x9F, 0x00, 0xFC, 0x52, 0xF0, 0x09, 0xC0, 0x6F, 0x20, 0xBF,
+0x00, 0xFC, 0x02, 0xF0, 0x2B, 0xC0, 0xA7, 0x00, 0xBF, 0x04, 0xFC, 0x12, 0xF0,
+0x49, 0x42, 0x25, 0x00, 0x9F, 0x08, 0x7C, 0x02, 0xF4, 0x89, 0xC0, 0x2D, 0x00,
+0xBF, 0x0C, 0xFC, 0x02, 0xF0, 0x09, 0xC0, 0x3F, 0x00, 0xBB, 0x00, 0xDC, 0x12,
+0xF0, 0x8B, 0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA8,
+0x2F, 0x01, 0x9F, 0x00, 0xFC, 0x32, 0xB0, 0x09, 0xC0, 0xA7, 0x20, 0xBF, 0x00,
+0xCD, 0x02, 0xF0, 0x49, 0xC5, 0x6F, 0x00, 0x9B, 0x80, 0x6E, 0x02, 0x79, 0x8B,
+0xC0, 0x2F, 0x01, 0xBB, 0x14, 0xAC, 0x82, 0x30, 0x0B, 0xCC, 0x21, 0x00, 0xBF,
+0x28, 0xCC, 0x82, 0x31, 0x4B, 0xC1, 0x2E, 0x68, 0xA3, 0x00, 0xBC, 0x02, 0xF0,
+0x0F, 0xC0, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07,
+0x05, 0x1D, 0x00, 0x70, 0x31, 0x14, 0x21, 0x40, 0x47, 0x00, 0x1D, 0x00, 0x44,
+0x00, 0xD0, 0x01, 0x00, 0x07, 0x00, 0x5A, 0x30, 0x44, 0xC0, 0xD8, 0x81, 0x40,
+0x07, 0x00, 0x11, 0x04, 0x51, 0x00, 0x10, 0x01, 0xC0, 0x05, 0x04, 0x5D, 0x08,
+0x4C, 0x00, 0x11, 0x01, 0x40, 0x07, 0x30, 0x11, 0x00, 0x64, 0x80, 0xD0, 0x01,
+0x40, 0x63, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x03,
+0x8D, 0x00, 0x34, 0x12, 0x10, 0x88, 0x40, 0x23, 0x00, 0x8D, 0x80, 0x04, 0x82,
+0xD2, 0x08, 0x0A, 0xA3, 0x00, 0x89, 0x04, 0x04, 0x02, 0x50, 0x08, 0x40, 0x23,
+0x02, 0x89, 0x14, 0x14, 0x02, 0x14, 0x08, 0x40, 0x21, 0x00, 0x8D, 0x00, 0x05,
+0x02, 0x18, 0x08, 0x48, 0x27, 0x20, 0x85, 0x00, 0x36, 0x02, 0xD0, 0x08, 0x40,
+0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0xA5, 0x00, 0x9D,
+0x00, 0x74, 0x12, 0x10, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x10, 0x44, 0x02, 0xD0,
+0x09, 0x48, 0x26, 0x20, 0x89, 0x00, 0x44, 0x02, 0xD8, 0x09, 0x40, 0x27, 0x00,
+0x91, 0x00, 0x44, 0x02, 0xD0, 0x09, 0x68, 0x25, 0x10, 0x9D, 0x04, 0x46, 0x02,
+0x99, 0x0D, 0x40, 0x27, 0x00, 0xD5, 0x00, 0x64, 0x22, 0xD0, 0x09, 0x41, 0x63,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x65, 0x00, 0x9D, 0x00,
+0x7C, 0x06, 0x30, 0x09, 0xC0, 0x2F, 0x06, 0x9F, 0x00, 0x4C, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9B, 0x02, 0x65, 0x42, 0x72, 0x09, 0xC2, 0x27, 0x00, 0x9B,
+0x00, 0x54, 0x02, 0x30, 0x09, 0xC0, 0x25, 0x33, 0x9F, 0x21, 0x4C, 0x46, 0x30,
+0x09, 0xC0, 0x22, 0x00, 0x95, 0xA7, 0x7E, 0x82, 0xE0, 0x39, 0xC0, 0x17, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x25, 0x25, 0x9F, 0x80, 0x3C,
+0x06, 0x70, 0x09, 0xE2, 0x27, 0x00, 0x9F, 0x10, 0x7C, 0x26, 0xF0, 0x59, 0xC0,
+0x27, 0x0C, 0x97, 0x02, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x50,
+0x5C, 0x02, 0x32, 0x09, 0xE8, 0x27, 0x10, 0x8F, 0x01, 0x5C, 0x0A, 0x74, 0x09,
+0xC1, 0xA6, 0x00, 0x9B, 0x05, 0x7E, 0x02, 0xF0, 0x59, 0xC0, 0x5B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00, 0x1F, 0x00, 0x6C, 0x40,
+0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x80, 0xB0, 0x01, 0xC0, 0x03,
+0x00, 0x17, 0x02, 0x7C, 0x08, 0xF0, 0x01, 0xC2, 0x00, 0x01, 0x1F, 0x00, 0x4C,
+0x00, 0xB0, 0x81, 0xC1, 0x07, 0x40, 0x17, 0x22, 0x5C, 0x10, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x13, 0x02, 0x4C, 0x40, 0x30, 0x01, 0x82, 0x53, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x9C, 0x00, 0x5D, 0x40, 0xF4, 0x05, 0xD8,
+0x05, 0xC0, 0x15, 0x20, 0x6C, 0x00, 0xF4, 0x49, 0x10, 0x05, 0x40, 0x9F, 0x80,
+0x5B, 0x00, 0x76, 0x01, 0xD0, 0x87, 0x40, 0x9C, 0x00, 0x7D, 0x02, 0x84, 0x01,
+0xF4, 0x27, 0xC0, 0x15, 0x00, 0x71, 0x00, 0x84, 0x89, 0x10, 0x77, 0x40, 0xDF,
+0x00, 0x70, 0x07, 0xC4, 0x01, 0x16, 0x97, 0x40, 0x43, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA8, 0xF2, 0x00, 0xCD, 0x00, 0x34, 0x23, 0xD0, 0x0C,
+0x48, 0x31, 0x00, 0x88, 0x02, 0x36, 0x1F, 0x90, 0x0C, 0x40, 0x13, 0x10, 0xC5,
+0x00, 0x34, 0x03, 0x90, 0x3C, 0x60, 0xB0, 0x00, 0xD5, 0x0B, 0x00, 0x03, 0x91,
+0x3C, 0x44, 0x31, 0x00, 0xC1, 0x01, 0x34, 0x0A, 0x50, 0x14, 0x40, 0xF2, 0x01,
+0xC1, 0x07, 0x24, 0x0B, 0x12, 0x8C, 0x44, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x80, 0x38, 0x04, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40,
+0x39, 0x01, 0x6D, 0x10, 0xB4, 0x04, 0x18, 0x0E, 0x40, 0x1B, 0x00, 0xE1, 0x44,
+0xB4, 0x03, 0xD0, 0x36, 0x40, 0x38, 0x00, 0xED, 0x00, 0x85, 0x03, 0xD4, 0x06,
+0x60, 0x7D, 0x02, 0xE1, 0x02, 0xE6, 0x02, 0x10, 0x06, 0x40, 0xBB, 0x20, 0xE1,
+0x61, 0xE5, 0x8F, 0x50, 0x06, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x18, 0x78, 0x00, 0xEF, 0x01, 0xBC, 0x05, 0xD0, 0x1E, 0xC0, 0xF9,
+0x00, 0x2B, 0x01, 0xBC, 0x04, 0xB1, 0x1E, 0xC0, 0x73, 0x00, 0xE5, 0x35, 0xB4,
+0x2F, 0xB0, 0x1F, 0xD0, 0x78, 0x00, 0xCF, 0x41, 0x8C, 0x05, 0xB4, 0x16, 0xC0,
+0x79, 0x03, 0xF3, 0x01, 0xBD, 0x04, 0x70, 0x16, 0xC0, 0x7B, 0x40, 0x23, 0x01,
+0xAC, 0x07, 0x31, 0x1E, 0xC4, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xB8, 0x35, 0x00, 0xDF, 0x00, 0xFC, 0x01, 0xF0, 0x0D, 0xC0, 0x35, 0x00,
+0x1E, 0x00, 0x3C, 0x00, 0xF0, 0x0D, 0xC0, 0x37, 0x10, 0xDF, 0x4A, 0x7C, 0x1B,
+0xF0, 0x05, 0xC8, 0x07, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF6, 0x05, 0xC6, 0xB5,
+0x01, 0x5E, 0x00, 0x1C, 0x00, 0x50, 0x05, 0xC0, 0x33, 0x00, 0x1F, 0x00, 0x5C,
+0x03, 0xB0, 0x09, 0xC8, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x20, 0x5D, 0x00, 0xF3, 0x01, 0xFC, 0x27, 0xF8, 0x8F, 0xC0, 0x7B, 0x00, 0x3B,
+0x01, 0xFC, 0x04, 0x70, 0x1F, 0xC0, 0x5F, 0x00, 0xFF, 0x09, 0xFE, 0x27, 0xB0,
+0x1B, 0xC0, 0x76, 0x00, 0xFF, 0x01, 0x8C, 0x07, 0x30, 0x93, 0xC4, 0x7F, 0x00,
+0xB3, 0x01, 0xCC, 0x16, 0xF8, 0x97, 0xC0, 0x7B, 0x00, 0xFB, 0x41, 0xF8, 0x04,
+0x34, 0x9B, 0xC0, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00,
+0x19, 0x22, 0xE1, 0x40, 0xB4, 0x81, 0x78, 0x0E, 0x42, 0x3B, 0x00, 0x61, 0x00,
+0xB4, 0x00, 0xD0, 0x0E, 0x44, 0x1B, 0x21, 0xE6, 0x08, 0xF4, 0x23, 0x14, 0x0A,
+0x40, 0x78, 0x00, 0xBD, 0x00, 0x84, 0x23, 0xF0, 0x00, 0x40, 0x3B, 0x01, 0xA1,
+0x24, 0xAC, 0x12, 0xB0, 0x06, 0xC0, 0x3B, 0x06, 0xE1, 0x08, 0xB4, 0x20, 0xB0,
+0x03, 0x48, 0x55, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
+0x04, 0xE1, 0x00, 0xB4, 0x03, 0x58, 0x8E, 0x40, 0x7F, 0x04, 0x21, 0x00, 0xB4,
+0x00, 0x50, 0x0E, 0x40, 0x19, 0x08, 0xEC, 0x42, 0xB4, 0x03, 0x10, 0x02, 0x40,
+0x38, 0x00, 0x6D, 0x00, 0xA4, 0x01, 0x10, 0x02, 0x60, 0x39, 0x24, 0xE1, 0x80,
+0xB4, 0x72, 0x1C, 0x06, 0x46, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x40, 0x50, 0x0A,
+0x42, 0x20, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x25, 0x00,
+0xC1, 0x20, 0x34, 0x08, 0x58, 0x0C, 0x40, 0xF3, 0x00, 0x49, 0x11, 0x34, 0x20,
+0xD8, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x01, 0x34, 0x03, 0x90, 0x01, 0x40, 0x02,
+0x80, 0x0D, 0x00, 0x24, 0x01, 0x90, 0x00, 0x40, 0xF3, 0x00, 0x41, 0x01, 0x34,
+0x06, 0x90, 0x04, 0x40, 0xF1, 0x00, 0xC1, 0x00, 0x36, 0x04, 0x18, 0x39, 0x40,
+0x09, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0xA5, 0x40, 0xD3,
+0x00, 0x7C, 0x6E, 0x70, 0x0D, 0x40, 0xF7, 0x40, 0x0B, 0x07, 0x7C, 0x00, 0x70,
+0x0D, 0xC2, 0x15, 0x00, 0xFF, 0x01, 0xF4, 0x4F, 0x30, 0x0D, 0xC0, 0x24, 0x00,
+0x1F, 0x00, 0x24, 0x02, 0x30, 0x01, 0xC0, 0xF9, 0x00, 0x53, 0xA3, 0x3C, 0x02,
+0x30, 0x04, 0x40, 0x77, 0x08, 0xDF, 0x25, 0x7C, 0x07, 0x50, 0x61, 0xC0, 0x54,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x27, 0x11, 0xDF, 0x00,
+0x7C, 0x0A, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0x57, 0x02, 0x7C, 0x00, 0xF0, 0x0D,
+0xC0, 0x17, 0x00, 0xD7, 0x08, 0x7C, 0x43, 0x70, 0x05, 0xD8, 0x25, 0x10, 0x9F,
+0x00, 0x5C, 0x02, 0xF0, 0x21, 0xC0, 0x37, 0x04, 0xDF, 0x08, 0x68, 0x0A, 0xF9,
+0x25, 0x80, 0x37, 0x01, 0x0E, 0x10, 0x7C, 0x0B, 0xF2, 0x21, 0xC0, 0xB7, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x07, 0x00, 0xF3, 0x00, 0xFC,
+0x00, 0xF0, 0x0E, 0xC0, 0x3E, 0x04, 0x33, 0x00, 0xEC, 0x00, 0xF0, 0x0F, 0xC0,
+0x7F, 0x00, 0xFF, 0x00, 0xEC, 0x03, 0x70, 0x2B, 0xC0, 0x2B, 0x00, 0x3B, 0x20,
+0xFC, 0x00, 0xB0, 0x03, 0xC0, 0x3F, 0x00, 0x23, 0x11, 0xCC, 0x42, 0x76, 0x87,
+0xC0, 0x3C, 0x00, 0x3F, 0x02, 0xC4, 0x07, 0xF0, 0x03, 0xC1, 0x04, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x66, 0x08, 0xD1, 0x40, 0x76, 0x04,
+0xD0, 0x0D, 0x48, 0x35, 0x00, 0x11, 0x00, 0x44, 0x14, 0xD0, 0x0D, 0xC0, 0x27,
+0x80, 0xDD, 0x80, 0x7C, 0x03, 0xD0, 0x11, 0x40, 0xC4, 0x44, 0x91, 0x21, 0x7C,
+0x07, 0xB0, 0x51, 0x40, 0x37, 0x00, 0x11, 0x0B, 0x44, 0x07, 0x10, 0x0D, 0x48,
+0xF0, 0x00, 0x11, 0x03, 0x44, 0x00, 0xD2, 0x31, 0x40, 0x04, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0xA2, 0x46, 0x04, 0xD1, 0x00, 0x74, 0x0E, 0xD0,
+0x0D, 0x40, 0x30, 0x00, 0x11, 0x30, 0x64, 0x04, 0xD0, 0x0D, 0x48, 0x17, 0x01,
+0xDD, 0x00, 0x74, 0x03, 0xD2, 0x0D, 0x40, 0x44, 0x00, 0x91, 0x83, 0x76, 0x46,
+0x90, 0x11, 0x40, 0x37, 0x00, 0x11, 0x02, 0x46, 0x0E, 0x50, 0x05, 0x40, 0x64,
+0x44, 0xD1, 0x20, 0x54, 0x18, 0xD2, 0x39, 0x40, 0x04, 0x08, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x34, 0x02, 0xD0, 0x0C,
+0x40, 0x31, 0x00, 0x51, 0x00, 0x04, 0x00, 0xD0, 0x0C, 0x40, 0x11, 0x00, 0xCD,
+0x00, 0x34, 0x03, 0xD0, 0x0C, 0x70, 0x00, 0x01, 0x81, 0x00, 0x34, 0x02, 0x99,
+0x00, 0x40, 0x37, 0x00, 0x81, 0x20, 0x04, 0x02, 0x10, 0x04, 0x40, 0x24, 0x00,
+0x01, 0x00, 0x14, 0x03, 0xD0, 0x00, 0x52, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x06, 0x00, 0xD3, 0x00, 0x74, 0x02, 0xF0, 0x0D, 0x40,
+0x3C, 0x80, 0x13, 0x00, 0x6C, 0x00, 0xF0, 0x0D, 0x60, 0x17, 0x00, 0xFD, 0x00,
+0xEC, 0x03, 0xF8, 0x00, 0xC0, 0x06, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xB0, 0x81,
+0xC0, 0x3B, 0x40, 0x03, 0x00, 0x4C, 0x02, 0x70, 0x01, 0xC0, 0x24, 0x10, 0xD3,
+0x00, 0x1C, 0x00, 0xF0, 0x09, 0xC4, 0x04, 0x64, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xB8, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC2, 0x3D,
+0x40, 0x7F, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xDC,
+0x03, 0xF0, 0x03, 0x00, 0x0F, 0x2A, 0x3F, 0x00, 0xDC, 0x03, 0x70, 0x03, 0xC0,
+0x3F, 0x00, 0x3F, 0x00, 0xBC, 0x03, 0xF0, 0x07, 0x40, 0x0F, 0x40, 0x37, 0x00,
+0xEC, 0x00, 0xF0, 0x0B, 0xC8, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA8, 0x7F, 0x00, 0x3E, 0x00, 0xFC, 0x04, 0x30, 0x1F, 0xC0, 0x2C, 0x00,
+0xBF, 0x24, 0xCC, 0x03, 0xF0, 0x43, 0xC1, 0x3D, 0x21, 0x3F, 0xA0, 0xDC, 0x13,
+0x30, 0x9E, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0x98, 0x17, 0xF0, 0x1F, 0xC0, 0x4C,
+0x00, 0xFF, 0x03, 0xFC, 0x07, 0xF0, 0x4F, 0xC0, 0x7E, 0x02, 0xFF, 0x00, 0xCC,
+0x03, 0x30, 0x83, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x10, 0x36, 0x05, 0x1D, 0x02, 0x44, 0x00, 0x10, 0x0D, 0x50, 0x24, 0x08, 0x9D,
+0x08, 0xC4, 0x2B, 0x10, 0x39, 0x44, 0x7C, 0x02, 0x9D, 0x01, 0xC4, 0x23, 0x11,
+0x1D, 0x40, 0xFF, 0x01, 0x5D, 0x01, 0xC4, 0x0F, 0xD0, 0x0D, 0x40, 0x44, 0x00,
+0xDD, 0x00, 0x5C, 0x07, 0xD0, 0xBF, 0x40, 0x34, 0x01, 0xF7, 0x03, 0xC4, 0x2F,
+0x10, 0x09, 0x40, 0x0D, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0,
+0x33, 0x00, 0x0D, 0x03, 0x54, 0x00, 0x90, 0x0C, 0x40, 0x21, 0x00, 0x8D, 0x00,
+0x04, 0x83, 0x10, 0x01, 0x60, 0x30, 0x08, 0x05, 0x00, 0x24, 0x03, 0x10, 0x4C,
+0x40, 0x32, 0x06, 0x89, 0x00, 0x05, 0x23, 0xD2, 0x0C, 0x48, 0x00, 0x20, 0xCD,
+0x04, 0x36, 0x03, 0xD0, 0x0C, 0x40, 0x30, 0x01, 0xCD, 0x02, 0x05, 0x03, 0x14,
+0x40, 0x44, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x35,
+0x00, 0x1D, 0x01, 0x44, 0x46, 0x94, 0x0D, 0x40, 0xE5, 0x00, 0x9D, 0x20, 0x44,
+0x03, 0x10, 0x19, 0x40, 0x34, 0x00, 0x1D, 0x01, 0x64, 0x03, 0x11, 0x0D, 0x40,
+0x37, 0x20, 0xDC, 0x10, 0x44, 0x03, 0xD0, 0x8C, 0x40, 0x44, 0x00, 0xDC, 0x00,
+0x54, 0x03, 0xD0, 0x0D, 0x40, 0x34, 0x00, 0xD5, 0x00, 0x44, 0x03, 0x10, 0x49,
+0x40, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x37, 0x00,
+0x1F, 0x01, 0x7C, 0x0C, 0xB0, 0x0D, 0xC0, 0x65, 0x00, 0x9F, 0x80, 0x0C, 0x03,
+0xB4, 0x35, 0xC0, 0x35, 0x00, 0x9F, 0x01, 0x6C, 0x03, 0x34, 0x0D, 0xC2, 0x36,
+0x20, 0xDB, 0x80, 0x5C, 0x03, 0xE0, 0x1D, 0x80, 0x44, 0x04, 0x9F, 0x08, 0x7C,
+0x07, 0xF0, 0x0D, 0xC0, 0x36, 0x00, 0xDD, 0x00, 0x4C, 0x03, 0x30, 0x1D, 0xC0,
+0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0x2F,
+0x00, 0xFC, 0x00, 0x70, 0x0F, 0xC0, 0x2E, 0x00, 0x9F, 0x00, 0xFD, 0x03, 0xB0,
+0x0F, 0xC0, 0x3F, 0x00, 0xAF, 0x00, 0xDC, 0x03, 0xF0, 0x2F, 0xC6, 0x3F, 0x00,
+0x69, 0x08, 0xFC, 0x03, 0xF0, 0x1F, 0xD0, 0x0F, 0x00, 0xBF, 0x00, 0xFC, 0x27,
+0xF1, 0x0E, 0xC4, 0x3F, 0x01, 0xDF, 0x00, 0xBC, 0x03, 0xF0, 0x17, 0xC8, 0x1F,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x04, 0x1F, 0x21,
+0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0xA7, 0x00, 0xD3, 0x00, 0x4C, 0xC3, 0x30, 0x25,
+0xC0, 0x34, 0x00, 0x17, 0x00, 0x7C, 0x13, 0xF0, 0x0D, 0xD0, 0x34, 0x00, 0x9F,
+0x21, 0x6C, 0x43, 0x30, 0x0D, 0xD1, 0x44, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC2, 0x36, 0x00, 0xCF, 0x04, 0x4C, 0x13, 0xF0, 0x0D, 0xC0, 0x8B, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xB4, 0x00, 0x1D, 0x00, 0x34,
+0x12, 0xD0, 0xBD, 0x41, 0x27, 0x04, 0xD1, 0x00, 0xD4, 0x13, 0x10, 0x0C, 0x45,
+0x3C, 0x00, 0x1D, 0x00, 0xE4, 0x03, 0xD2, 0x0D, 0x40, 0x3C, 0x00, 0xDD, 0x00,
+0xC4, 0x07, 0x10, 0x0D, 0x40, 0x04, 0x00, 0xD1, 0x20, 0x74, 0x03, 0xD0, 0x1F,
+0x40, 0x34, 0x00, 0xFD, 0x82, 0xC4, 0x0B, 0xD0, 0x05, 0x40, 0x6F, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x30, 0x00, 0x0D, 0x20, 0x34, 0x00,
+0xD0, 0x1D, 0x40, 0x33, 0x00, 0x94, 0x60, 0x24, 0x03, 0x10, 0x04, 0x40, 0x32,
+0x00, 0x0D, 0x00, 0x74, 0x03, 0xD0, 0x0C, 0x40, 0x32, 0x00, 0xCD, 0x00, 0x24,
+0x23, 0x50, 0x2C, 0x40, 0x03, 0x84, 0xC5, 0x12, 0x34, 0x03, 0xD0, 0x9C, 0x40,
+0x30, 0x00, 0xC9, 0x49, 0x24, 0x27, 0xD0, 0x05, 0x40, 0x1F, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x78, 0x00, 0x2D, 0x21, 0xB4, 0x07, 0xD0,
+0x9E, 0x40, 0x6B, 0x02, 0xA4, 0x01, 0xB4, 0x07, 0x10, 0x1F, 0x40, 0x7A, 0x00,
+0xED, 0x81, 0xA4, 0x07, 0xD0, 0x1F, 0x60, 0x7A, 0x00, 0xC9, 0x03, 0x84, 0x07,
+0x50, 0x1E, 0x40, 0x4B, 0x50, 0xE5, 0x89, 0xB4, 0x17, 0xD1, 0x1C, 0x40, 0x78,
+0x00, 0xED, 0x81, 0xA4, 0x07, 0xD0, 0x9E, 0x40, 0x37, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x18, 0x30, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x8C,
+0xC0, 0x37, 0x08, 0x87, 0x00, 0x6C, 0x13, 0x30, 0x04, 0xC0, 0x32, 0x00, 0x4F,
+0x02, 0x3C, 0x23, 0xF0, 0x0C, 0xC0, 0x32, 0x00, 0xCF, 0x00, 0x2C, 0x03, 0x70,
+0x0D, 0xC0, 0x03, 0x00, 0xC7, 0x08, 0x3C, 0x03, 0xF0, 0x0C, 0xC0, 0x30, 0x00,
+0xCB, 0x00, 0x2C, 0x03, 0xF0, 0x84, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x38, 0x3D, 0x00, 0x3F, 0x00, 0xFC, 0x23, 0xF0, 0x8F, 0xE8,
+0x3F, 0x40, 0xBB, 0x00, 0xDC, 0x03, 0xF0, 0x0E, 0xC0, 0x3D, 0x02, 0xFF, 0x00,
+0xEC, 0x03, 0xF0, 0x0F, 0xC0, 0x3D, 0x24, 0xFF, 0x00, 0xFC, 0x23, 0xB2, 0x0F,
+0xC0, 0x08, 0x02, 0xFB, 0x28, 0xFC, 0x93, 0xF0, 0x0F, 0xD0, 0x3D, 0x00, 0xFF,
+0x00, 0xDD, 0x03, 0xF2, 0x8F, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xB0, 0x37, 0x00, 0x1F, 0x00, 0x7C, 0x02, 0xF1, 0x1D, 0xC0, 0x34,
+0x00, 0x93, 0x00, 0x4C, 0x03, 0x70, 0x05, 0xC4, 0x77, 0x01, 0x9B, 0x00, 0x7C,
+0x4B, 0xE0, 0x1D, 0xC2, 0x35, 0x05, 0xCD, 0x01, 0x4C, 0x1B, 0xF0, 0x0D, 0xC0,
+0x07, 0x00, 0xDF, 0x01, 0x1C, 0x07, 0x70, 0xCD, 0xC0, 0x37, 0x20, 0xDF, 0x0A,
+0x3C, 0x4F, 0x30, 0x09, 0xC0, 0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x80, 0x39, 0x00, 0x2D, 0x00, 0xB4, 0x03, 0x70, 0x0E, 0x40, 0x1C, 0x00,
+0xA1, 0x00, 0xAC, 0x53, 0x10, 0x0E, 0x40, 0xBB, 0x04, 0xE1, 0x00, 0xB4, 0x03,
+0xD0, 0x0E, 0x40, 0x3C, 0x01, 0xE1, 0x00, 0x84, 0x53, 0xD0, 0x0E, 0x40, 0x0B,
+0x00, 0xFD, 0x00, 0x8C, 0x03, 0x10, 0x8E, 0x40, 0x3B, 0x00, 0xE7, 0x10, 0xB4,
+0x13, 0xB0, 0x00, 0xC0, 0x4E, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x00, 0x79, 0x00, 0x6D, 0x01, 0x94, 0x06, 0xD0, 0x1E, 0x40, 0x78, 0x0C, 0xC1,
+0x01, 0x04, 0x27, 0x50, 0x1E, 0x40, 0x73, 0x01, 0xE1, 0x01, 0xB4, 0x27, 0x50,
+0x3E, 0x40, 0x7B, 0x00, 0xE5, 0x01, 0x85, 0x27, 0xD0, 0x1E, 0x43, 0x4B, 0x00,
+0xED, 0x01, 0x84, 0x07, 0x10, 0x5E, 0x40, 0x6B, 0x00, 0xE5, 0x25, 0xB6, 0x37,
+0x10, 0x1A, 0x40, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28,
+0x33, 0x00, 0xCD, 0x01, 0x34, 0x4B, 0x50, 0x0C, 0x60, 0x70, 0x01, 0xC1, 0x01,
+0x24, 0x03, 0x10, 0x0C, 0x41, 0x33, 0x80, 0xC1, 0x10, 0x34, 0x03, 0xD0, 0x18,
+0x40, 0x32, 0x00, 0xC1, 0x00, 0x04, 0x03, 0xD0, 0x09, 0x40, 0xF3, 0x00, 0xCD,
+0x01, 0x04, 0x06, 0x14, 0x0C, 0x40, 0x37, 0x10, 0xC5, 0x80, 0x36, 0x03, 0x90,
+0x41, 0x40, 0x4A, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x15,
+0x00, 0x7F, 0x05, 0xFC, 0x01, 0xF0, 0x05, 0xD0, 0x1C, 0x00, 0x53, 0x41, 0x4C,
+0x01, 0x70, 0x27, 0xC0, 0x17, 0x40, 0x73, 0xC2, 0x7C, 0x01, 0xF0, 0x05, 0xC0,
+0x17, 0x10, 0x7F, 0x00, 0x4C, 0x01, 0xF0, 0x15, 0xC0, 0x5F, 0x01, 0x5F, 0x01,
+0x5D, 0x15, 0x70, 0x04, 0xC2, 0x57, 0x01, 0x47, 0x00, 0x7C, 0x01, 0x30, 0x17,
+0xC1, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x85, 0x00,
+0x1F, 0x01, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x1F, 0x08, 0x3C, 0x00,
+0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x7C, 0x80, 0xF0, 0x01, 0xC0, 0x05,
+0x00, 0x1F, 0x00, 0x7E, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x01, 0x1F, 0x08, 0x5C,
+0x00, 0xF2, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC8,
+0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F,
+0x05, 0x4C, 0x02, 0x36, 0x09, 0xC0, 0xA3, 0x40, 0x83, 0x05, 0x4C, 0x06, 0xB0,
+0x08, 0xC0, 0x26, 0x00, 0x9F, 0x00, 0x74, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00,
+0x9B, 0x00, 0x7C, 0x06, 0xF0, 0x19, 0xC0, 0x24, 0x20, 0x9F, 0x00, 0x7C, 0x26,
+0xF0, 0x09, 0xC0, 0x24, 0x00, 0x9C, 0x00, 0x48, 0x02, 0xF0, 0x09, 0xC8, 0x40,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x64, 0x00, 0x9D, 0x00,
+0x44, 0x02, 0x10, 0x19, 0x40, 0x27, 0x40, 0x91, 0x01, 0x7C, 0x2A, 0x10, 0x09,
+0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0xE0, 0x27, 0x00, 0x91,
+0x10, 0x74, 0x1E, 0xD1, 0x99, 0x40, 0xA4, 0x00, 0x9D, 0x42, 0x5C, 0x02, 0xD0,
+0x09, 0xC0, 0x26, 0x00, 0x95, 0x80, 0x54, 0x1A, 0xD0, 0x09, 0xC0, 0x06, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x02, 0x8D, 0x00, 0x04,
+0x02, 0x18, 0x49, 0x40, 0x27, 0x40, 0x91, 0x00, 0x44, 0x02, 0x90, 0x1D, 0x40,
+0x26, 0x00, 0x95, 0x00, 0x74, 0x22, 0xD0, 0x09, 0x60, 0x23, 0x00, 0x99, 0x01,
+0x74, 0x12, 0xD0, 0x29, 0x40, 0x25, 0x00, 0x9D, 0x04, 0x74, 0x02, 0x50, 0x89,
+0x40, 0x24, 0x00, 0x95, 0x18, 0x54, 0x22, 0xD0, 0x09, 0x40, 0x60, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x8D, 0x04, 0x04, 0x02,
+0x10, 0x0C, 0x40, 0x23, 0x01, 0x81, 0x04, 0x14, 0x13, 0x10, 0x48, 0x40, 0x20,
+0x01, 0x8D, 0x04, 0x36, 0x16, 0xD1, 0x08, 0x42, 0x21, 0x01, 0x81, 0x04, 0x34,
+0x12, 0xD8, 0x08, 0x40, 0x61, 0x80, 0x8D, 0x01, 0x14, 0x02, 0xD0, 0x48, 0x40,
+0x22, 0x30, 0x85, 0x44, 0x16, 0x12, 0xD0, 0x48, 0x40, 0x42, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xA0, 0x96, 0x02, 0x1F, 0x0A, 0x4D, 0x28, 0x30,
+0xA0, 0xC0, 0x87, 0x02, 0x13, 0x0A, 0x44, 0x28, 0xB0, 0x01, 0xC0, 0x06, 0x00,
+0x17, 0x10, 0x7C, 0x00, 0xF0, 0xA0, 0x40, 0x87, 0x02, 0x1B, 0x00, 0x74, 0x00,
+0xF0, 0xA1, 0xC8, 0x05, 0x00, 0x1F, 0x0A, 0x74, 0x00, 0xF0, 0x01, 0xC0, 0x84,
+0x00, 0x17, 0x00, 0x5C, 0x00, 0xF2, 0x21, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0x88, 0x27, 0x00, 0xFF, 0x08, 0xFC, 0x02, 0xF0, 0x09,
+0xC0, 0x2F, 0x02, 0xBF, 0x48, 0x7C, 0x22, 0xF0, 0x8B, 0xC4, 0x27, 0x02, 0xBF,
+0x00, 0x7C, 0x62, 0xF0, 0x0B, 0xC0, 0x27, 0x02, 0xBF, 0x08, 0x7C, 0x22, 0xF0,
+0x0B, 0xD8, 0x2E, 0x00, 0xBF, 0x40, 0xDC, 0x02, 0xF0, 0x89, 0xC2, 0x2F, 0x04,
+0x93, 0x08, 0x7C, 0x22, 0xF2, 0x8B, 0xC1, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1C, 0xA0, 0x2D, 0x00, 0xBF, 0x0C, 0xCC, 0x02, 0x30, 0x0B, 0xC0,
+0x2C, 0x02, 0xB3, 0x00, 0xFC, 0x52, 0x34, 0x4F, 0x80, 0x27, 0x00, 0x9F, 0x00,
+0xF8, 0x22, 0xF0, 0x09, 0xC0, 0x27, 0x25, 0xBF, 0x04, 0xD4, 0x02, 0x70, 0x0A,
+0xC0, 0x2C, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF0, 0x4B, 0xC0, 0x27, 0x00, 0xA3,
+0x80, 0xBC, 0x02, 0xF0, 0x29, 0xC0, 0x61, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x00, 0x07, 0x01, 0x0D, 0x2C, 0x44, 0x41, 0x10, 0x01, 0x41, 0x14,
+0x02, 0x01, 0x14, 0x74, 0x10, 0x13, 0x81, 0x40, 0x87, 0x00, 0x1D, 0x00, 0x74,
+0x20, 0xD0, 0x41, 0x41, 0x06, 0x01, 0x1D, 0x08, 0x44, 0x08, 0x10, 0x01, 0x41,
+0x04, 0x00, 0x1D, 0x14, 0x74, 0x00, 0xC0, 0x81, 0x44, 0x47, 0x05, 0x1B, 0x00,
+0x74, 0x20, 0xD0, 0x11, 0x40, 0x71, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x20, 0x21, 0x05, 0x8D, 0x04, 0x05, 0x12, 0x10, 0x08, 0x40, 0x20, 0x40,
+0x81, 0x04, 0x34, 0x52, 0x10, 0x08, 0x48, 0x22, 0x02, 0x88, 0x08, 0x34, 0x02,
+0xD0, 0x48, 0x40, 0x21, 0x05, 0x8D, 0x01, 0x14, 0x22, 0xD0, 0x08, 0x40, 0x61,
+0x00, 0x8D, 0x04, 0x24, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x00, 0x81, 0x08, 0x34,
+0x02, 0xD0, 0x48, 0x40, 0x4B, 0x88, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x28, 0x25, 0x00, 0x9D, 0x00, 0x04, 0x02, 0x10, 0x09, 0x60, 0x24, 0x01, 0xD1,
+0x00, 0x34, 0x03, 0x10, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x0A, 0x74, 0x02, 0xD0,
+0x19, 0x40, 0x24, 0x00, 0x9D, 0x08, 0x44, 0x02, 0x90, 0x08, 0x50, 0x25, 0x01,
+0x9D, 0x01, 0x74, 0x06, 0xD0, 0x09, 0x40, 0x67, 0x00, 0x98, 0x00, 0x74, 0x02,
+0xD0, 0x09, 0x40, 0x63, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20,
+0x25, 0x00, 0x9F, 0x02, 0x4C, 0x02, 0x30, 0x09, 0xD0, 0xE4, 0x08, 0x93, 0x01,
+0x7C, 0x02, 0x34, 0x69, 0xC8, 0x26, 0x00, 0x9B, 0x03, 0x7C, 0x02, 0xF0, 0x09,
+0xCC, 0x27, 0x00, 0x9F, 0x01, 0x5C, 0x02, 0xF0, 0x19, 0xC0, 0x25, 0x00, 0x9E,
+0x00, 0x74, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x90, 0x00, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x25,
+0x00, 0x9F, 0x09, 0x7C, 0x02, 0xF4, 0x09, 0xC0, 0x67, 0x00, 0x9F, 0x04, 0x7C,
+0x02, 0x70, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x01, 0x7C, 0x82, 0xF0, 0x09, 0xC8,
+0x27, 0x00, 0x8F, 0x00, 0x7C, 0x42, 0x70, 0x49, 0xC0, 0x26, 0x08, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x08,
+0xC0, 0x59, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x01,
+0x1F, 0x00, 0x4C, 0x00, 0xB0, 0x01, 0xC0, 0x84, 0x40, 0x13, 0x10, 0x4C, 0x00,
+0x30, 0x21, 0xC0, 0x07, 0x20, 0x1F, 0x00, 0x7C, 0x80, 0xF0, 0x01, 0xE0, 0x07,
+0x00, 0x1F, 0x00, 0x3C, 0x00, 0xB0, 0x11, 0xC0, 0x04, 0x00, 0x1F, 0x00, 0x7C,
+0x00, 0xF0, 0x11, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0,
+0x51, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x5C, 0x00, 0x5D,
+0x80, 0x44, 0x05, 0x30, 0x07, 0x40, 0x54, 0x40, 0x71, 0x05, 0xC6, 0x29, 0x10,
+0x05, 0x40, 0x17, 0x00, 0x5D, 0x00, 0xF4, 0x09, 0xD0, 0x05, 0xC0, 0x17, 0x00,
+0x7D, 0x0A, 0xF4, 0x01, 0x70, 0x17, 0x40, 0x9C, 0x00, 0x7D, 0x10, 0x5C, 0x01,
+0xD0, 0x17, 0x40, 0x17, 0x00, 0x71, 0x07, 0xC4, 0x19, 0x50, 0x05, 0x48, 0x50,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x72, 0x02, 0xDD, 0x00,
+0x04, 0x03, 0x50, 0x15, 0x49, 0x76, 0x20, 0xC1, 0x02, 0x24, 0x0F, 0x10, 0x0C,
+0x40, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x37, 0xD0, 0x0D, 0x40, 0x33, 0x00, 0xCD,
+0x0B, 0x34, 0x07, 0x50, 0x9C, 0x42, 0xA0, 0x04, 0xCD, 0x05, 0x34, 0x03, 0xD0,
+0x1C, 0x40, 0x37, 0x00, 0x05, 0x04, 0x04, 0x10, 0x10, 0x0C, 0x40, 0x51, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x18, 0x00, 0xED, 0x00, 0x84,
+0x0A, 0x10, 0x2A, 0x40, 0x32, 0x24, 0xE1, 0x01, 0xA4, 0x0A, 0x10, 0x2E, 0x48,
+0x3B, 0x00, 0xED, 0x00, 0xB4, 0x83, 0xD0, 0x4E, 0x40, 0x39, 0x00, 0xAD, 0x00,
+0xB4, 0x09, 0x40, 0x0F, 0x40, 0x18, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E,
+0x49, 0x3B, 0x00, 0x25, 0x00, 0x84, 0x04, 0x50, 0x0E, 0x48, 0x10, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x69, 0x00, 0xEF, 0x01, 0xCC, 0x07,
+0x70, 0x1F, 0xD0, 0x7A, 0x00, 0xA3, 0x01, 0xE4, 0x07, 0x34, 0x1A, 0xC0, 0x7B,
+0x00, 0xED, 0x01, 0xBC, 0x05, 0xF0, 0x7E, 0x41, 0x7B, 0x05, 0xAF, 0x01, 0xB8,
+0x05, 0x70, 0x1E, 0xC0, 0x48, 0x00, 0xEF, 0x01, 0xBC, 0x06, 0xF0, 0x1E, 0xC0,
+0x7F, 0x00, 0xA5, 0x00, 0x8C, 0x06, 0x30, 0x1F, 0xC0, 0x51, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xB0, 0x0D, 0x00, 0x9F, 0x02, 0x7D, 0x1A, 0x74,
+0x6B, 0xC0, 0x35, 0x00, 0x9F, 0x00, 0x5D, 0x1A, 0xF0, 0x09, 0xC0, 0x37, 0x00,
+0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x3C, 0x81,
+0x70, 0x0D, 0xD0, 0x17, 0x08, 0xDF, 0x00, 0x5C, 0x82, 0xF0, 0x0D, 0xC0, 0x37,
+0x00, 0xDA, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x20, 0x4D, 0x00, 0xF7, 0x03, 0xCC, 0x1B, 0x70, 0x3F,
+0xC0, 0x7C, 0x00, 0x73, 0x01, 0xCD, 0x0F, 0x30, 0x1B, 0xC0, 0x7F, 0x00, 0xF3,
+0x01, 0xFC, 0x07, 0x30, 0x1F, 0xC0, 0x7F, 0x04, 0xB3, 0x01, 0xCC, 0x85, 0xF0,
+0x1F, 0xC0, 0x4C, 0x20, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x17, 0xC0, 0x7F, 0x00,
+0x23, 0x01, 0xCC, 0x05, 0xF0, 0x1F, 0xC0, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x00, 0x0D, 0x00, 0xF1, 0x08, 0x84, 0xC3, 0x18, 0x0B, 0x40,
+0x28, 0x00, 0x71, 0x00, 0xC4, 0x22, 0x10, 0x0A, 0x40, 0x3B, 0x00, 0xE1, 0x00,
+0xB4, 0x23, 0x10, 0x0E, 0xC0, 0x39, 0x02, 0xE1, 0x02, 0x84, 0x00, 0x70, 0x07,
+0x40, 0x18, 0x20, 0xED, 0x80, 0xB4, 0x03, 0xD0, 0x02, 0x40, 0x3B, 0x00, 0x25,
+0x0A, 0xAC, 0x28, 0xD0, 0x0E, 0xC0, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x09, 0x00, 0xED, 0x00, 0xC4, 0x23, 0x50, 0x0A, 0x50, 0x28,
+0x00, 0x25, 0x08, 0x84, 0x03, 0x10, 0x0A, 0x40, 0x33, 0x00, 0xE1, 0x00, 0x34,
+0x02, 0x10, 0x0E, 0x40, 0x33, 0x00, 0x41, 0x00, 0xA4, 0x01, 0xD0, 0x0E, 0x40,
+0x88, 0x04, 0xED, 0x00, 0xB4, 0x02, 0xD0, 0x02, 0x40, 0x3F, 0x00, 0xA1, 0x00,
+0x94, 0x03, 0xD0, 0x0E, 0x40, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x28, 0x01, 0x00, 0x89, 0x00, 0x44, 0x0B, 0x10, 0x08, 0x40, 0xE4, 0x01,
+0x05, 0x00, 0x44, 0x02, 0x10, 0x28, 0x40, 0x33, 0x00, 0xC1, 0x11, 0x34, 0x02,
+0x10, 0x0C, 0x68, 0x31, 0x00, 0x41, 0x52, 0x24, 0x00, 0x50, 0x0C, 0x40, 0x50,
+0x00, 0xDD, 0x00, 0x34, 0x02, 0xD0, 0x00, 0x40, 0x73, 0x02, 0x85, 0x00, 0x34,
+0x03, 0xD0, 0x0C, 0x40, 0x19, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA0, 0x25, 0x00, 0xDF, 0x00, 0x4D, 0x0B, 0x50, 0x05, 0xC0, 0x74, 0x40, 0x17,
+0x00, 0x44, 0x03, 0x34, 0x0C, 0xC0, 0x37, 0x00, 0xD3, 0x06, 0x7C, 0x02, 0x30,
+0x0F, 0xC0, 0x3F, 0x00, 0xD3, 0x02, 0x6C, 0x01, 0xF0, 0x1D, 0xC0, 0x44, 0x00,
+0xDF, 0x40, 0x7C, 0x02, 0xF0, 0x05, 0xC0, 0x3F, 0x00, 0x53, 0x00, 0x5C, 0x00,
+0xF0, 0x2F, 0xC0, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08,
+0x87, 0x00, 0xD7, 0x10, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x37, 0x02, 0x1A, 0x02,
+0x7C, 0x02, 0xF1, 0x09, 0xC1, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x00, 0xF0, 0x1D,
+0xC0, 0x37, 0x20, 0x1F, 0x03, 0x5C, 0x01, 0x70, 0x8D, 0xC0, 0x07, 0x28, 0xDF,
+0x02, 0x7C, 0x06, 0xF0, 0x05, 0xCA, 0x37, 0x00, 0x9F, 0x02, 0x2C, 0x0A, 0xF0,
+0x0D, 0xC0, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x0F,
+0x00, 0xFF, 0x00, 0xCC, 0x43, 0x30, 0x0F, 0xC0, 0x74, 0x01, 0x23, 0x01, 0xC4,
+0x03, 0x30, 0x0B, 0xC0, 0x3C, 0x00, 0xFF, 0x00, 0xBC, 0x00, 0x30, 0x0F, 0xC0,
+0x3B, 0x00, 0xB3, 0x00, 0x8E, 0x00, 0x30, 0x0B, 0xC0, 0x0D, 0x00, 0x7B, 0x00,
+0xCC, 0x03, 0x30, 0x07, 0xC0, 0x3F, 0x10, 0x7F, 0x00, 0xCC, 0x0C, 0x30, 0x0F,
+0xC1, 0x03, 0x2A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0xC6, 0x24,
+0x8D, 0x00, 0x44, 0x02, 0x90, 0x19, 0xC0, 0x36, 0x40, 0x11, 0x03, 0x54, 0x0E,
+0x50, 0x09, 0x50, 0x34, 0x00, 0xDD, 0x00, 0x74, 0x4C, 0x10, 0x0D, 0x40, 0x37,
+0x00, 0x01, 0x00, 0x54, 0x0C, 0x51, 0x09, 0x40, 0xC0, 0x00, 0xDB, 0x03, 0x04,
+0x07, 0x10, 0x15, 0xC0, 0x35, 0x00, 0xCD, 0x08, 0x54, 0x06, 0x10, 0x0D, 0x40,
+0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x46, 0x80, 0xDD,
+0x00, 0x44, 0x03, 0x90, 0x18, 0x40, 0x25, 0x00, 0x51, 0x88, 0x54, 0x07, 0x10,
+0x89, 0x40, 0x34, 0x00, 0xD5, 0x00, 0x74, 0x06, 0x10, 0x0D, 0x40, 0x37, 0x00,
+0x91, 0x00, 0x46, 0x45, 0x90, 0x1C, 0x40, 0x44, 0x44, 0xD9, 0x03, 0x44, 0x12,
+0x10, 0x11, 0x60, 0x37, 0x00, 0x5D, 0x00, 0x44, 0x01, 0x10, 0x0D, 0x40, 0x07,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDD, 0x00,
+0x04, 0x03, 0x90, 0x08, 0x40, 0x22, 0x00, 0x41, 0x00, 0x14, 0x02, 0x14, 0x08,
+0x48, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x00, 0x10, 0x0C, 0x40, 0x33, 0x20, 0x41,
+0x00, 0x16, 0x00, 0xD0, 0x04, 0x40, 0x00, 0x40, 0xC9, 0x80, 0x45, 0x02, 0x14,
+0x10, 0x60, 0x31, 0x00, 0x4D, 0x00, 0x14, 0x01, 0x10, 0x0C, 0x40, 0x43, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x00, 0xFF, 0x00, 0xCD,
+0x03, 0x34, 0x0B, 0xC0, 0x25, 0x00, 0x13, 0x00, 0xDC, 0x02, 0x30, 0x09, 0xC0,
+0x34, 0x00, 0xD7, 0x00, 0x7C, 0x02, 0x11, 0x0F, 0xC0, 0x3F, 0x00, 0x53, 0x00,
+0x44, 0x00, 0xB0, 0x0D, 0xC8, 0x05, 0x40, 0x9B, 0x00, 0x4C, 0x03, 0x30, 0x01,
+0xC0, 0x37, 0x00, 0xDF, 0x00, 0x4C, 0x03, 0x30, 0x0D, 0xC0, 0x03, 0x40, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0F, 0x00, 0xBF, 0x00, 0xBC, 0x03,
+0x70, 0x0B, 0xC0, 0x2F, 0x00, 0x3F, 0x00, 0xFE, 0x00, 0xF0, 0x0B, 0xC0, 0x3F,
+0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0x7F, 0x00, 0xFC,
+0x00, 0x70, 0x0F, 0xC0, 0x0F, 0x00, 0xBF, 0x00, 0xF4, 0x03, 0xF1, 0x03, 0xCA,
+0x39, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x17, 0x60, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x2F, 0x00, 0xBF, 0x00, 0xDC, 0x53, 0xF0,
+0x03, 0xC0, 0x0F, 0x00, 0xAF, 0x01, 0xFC, 0x87, 0xF0, 0x1F, 0xD0, 0x0C, 0x00,
+0xFF, 0x01, 0xCC, 0x03, 0xF0, 0x4F, 0xC0, 0x0D, 0x02, 0xB3, 0x01, 0xEC, 0x07,
+0xF0, 0x03, 0xC0, 0x0F, 0x08, 0xEF, 0x01, 0xBC, 0x05, 0xB4, 0x1A, 0xC0, 0x7B,
+0x00, 0x33, 0x04, 0xBC, 0x02, 0x20, 0x0B, 0xC8, 0x0C, 0x08, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x00, 0x1D, 0x00, 0xF4, 0x0B, 0xD0, 0x11,
+0x40, 0x47, 0x00, 0xDD, 0x01, 0x74, 0x07, 0xD0, 0x0D, 0x40, 0x20, 0x01, 0xCC,
+0x10, 0xC4, 0x2B, 0xD0, 0x0D, 0x40, 0x27, 0x00, 0xD1, 0x01, 0x44, 0x03, 0xD0,
+0x11, 0x42, 0x07, 0x00, 0xDD, 0x01, 0x74, 0x07, 0x12, 0x19, 0x40, 0x57, 0x20,
+0x15, 0x83, 0x74, 0x06, 0x51, 0x01, 0x40, 0x0D, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x11, 0xA0, 0x03, 0x00, 0x8D, 0x00, 0x34, 0x03, 0xD0, 0x08, 0x40,
+0x03, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x20, 0x04, 0xCD, 0x04,
+0x05, 0x03, 0xD2, 0x8C, 0x42, 0x23, 0x08, 0xD1, 0x80, 0x34, 0x03, 0xD0, 0x08,
+0x40, 0x63, 0x00, 0xCD, 0x00, 0x34, 0x81, 0x10, 0x0C, 0x40, 0x27, 0x00, 0x81,
+0x08, 0x34, 0x02, 0x19, 0x08, 0x40, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA8, 0x65, 0x00, 0x1D, 0x21, 0x74, 0x03, 0xD0, 0x39, 0x40, 0x47,
+0x00, 0xDD, 0x01, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0xE4, 0x00, 0xCD, 0x20, 0x44,
+0x03, 0xD1, 0x0D, 0x40, 0x63, 0x00, 0xD1, 0x03, 0x54, 0x03, 0x90, 0x19, 0x40,
+0x67, 0x10, 0xDD, 0x04, 0x74, 0x06, 0x11, 0x1D, 0x40, 0x37, 0x00, 0x55, 0x90,
+0x74, 0x06, 0x58, 0x19, 0x42, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA0, 0xE7, 0x00, 0x9F, 0x11, 0x5C, 0x03, 0xF1, 0x19, 0xC0, 0x67, 0x04,
+0xDF, 0x05, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0xC4, 0x00, 0xDF, 0x01, 0x4C, 0x03,
+0xF0, 0x0D, 0xC0, 0x45, 0x40, 0xC3, 0x01, 0x7C, 0x03, 0xF0, 0x39, 0xC1, 0x67,
+0x00, 0xDF, 0x00, 0x3C, 0x0D, 0xB8, 0x39, 0xC0, 0x37, 0x00, 0x53, 0x02, 0x7C,
+0x04, 0x30, 0x11, 0xC0, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0x88, 0x2D, 0x00, 0xBF, 0x80, 0x7C, 0x03, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0xFF,
+0x00, 0xFC, 0x03, 0xF0, 0x8F, 0xC0, 0x2F, 0x00, 0xFF, 0x02, 0xFC, 0x03, 0xF2,
+0x0F, 0xE0, 0x27, 0x80, 0xFF, 0x00, 0xEC, 0x03, 0xF0, 0x09, 0xC0, 0x0F, 0x00,
+0xFF, 0x01, 0xFC, 0x03, 0xF0, 0x03, 0xC0, 0x7F, 0x01, 0x3F, 0x04, 0xBC, 0x02,
+0xF0, 0x01, 0xC1, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08,
+0x05, 0x02, 0x9F, 0x02, 0x7C, 0x03, 0x30, 0x29, 0xC0, 0xA7, 0x00, 0xDF, 0x0A,
+0x6C, 0x03, 0x70, 0x0D, 0xC0, 0x27, 0x00, 0xD3, 0x04, 0x4C, 0x13, 0xF2, 0x8D,
+0xC2, 0xA7, 0x00, 0xD7, 0x03, 0x4C, 0x47, 0xF0, 0x29, 0xC0, 0x24, 0x04, 0xDB,
+0x04, 0x4C, 0x19, 0x70, 0x2D, 0xC5, 0x34, 0x00, 0x57, 0x02, 0x7C, 0x60, 0x74,
+0x01, 0xC0, 0x28, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x24,
+0x00, 0x9D, 0x18, 0xF4, 0x2B, 0x10, 0x01, 0x40, 0x27, 0x00, 0xDD, 0x00, 0x44,
+0x03, 0xD0, 0x8D, 0x40, 0x27, 0x00, 0xD1, 0x02, 0xC4, 0x4B, 0xD0, 0x2F, 0x40,
+0x27, 0x00, 0xD1, 0x80, 0x50, 0x0B, 0xF0, 0x49, 0x00, 0x85, 0x00, 0xDD, 0x41,
+0x6C, 0x4F, 0x10, 0x0D, 0x40, 0x30, 0x02, 0x5B, 0x00, 0x70, 0x0A, 0x10, 0x21,
+0xC0, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x04,
+0x0D, 0x00, 0x34, 0x03, 0x10, 0x00, 0x40, 0x23, 0x00, 0xCD, 0x01, 0x24, 0x03,
+0x50, 0x3D, 0x40, 0x03, 0x00, 0xC5, 0x00, 0x04, 0x03, 0xD0, 0x4C, 0x40, 0x02,
+0x00, 0xC9, 0x00, 0x04, 0x8B, 0xD0, 0x10, 0x40, 0x00, 0x20, 0xCD, 0x02, 0x04,
+0x0B, 0x50, 0x28, 0x40, 0x32, 0x00, 0x0D, 0x07, 0x34, 0x04, 0xD4, 0x19, 0x40,
+0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x58, 0x00, 0x6D,
+0x01, 0xB4, 0x27, 0x14, 0x16, 0x40, 0x7B, 0x00, 0xFD, 0x01, 0x84, 0x87, 0xD0,
+0x1E, 0x40, 0x7B, 0x10, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x48, 0x6B, 0x50,
+0xF9, 0x01, 0x94, 0x87, 0x58, 0x16, 0x50, 0x48, 0x02, 0xFD, 0x11, 0xE4, 0x17,
+0x10, 0x0F, 0x40, 0x7E, 0x8C, 0xA9, 0x01, 0xB4, 0x24, 0x90, 0x12, 0x48, 0x3E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x1A, 0x90, 0x00, 0xCF, 0x00,
+0x3C, 0x03, 0x30, 0x0C, 0xC0, 0x33, 0x00, 0xCF, 0x00, 0x2C, 0x03, 0x70, 0x0C,
+0xC1, 0x03, 0x40, 0xC5, 0x00, 0x0C, 0x23, 0xF0, 0x0C, 0x40, 0x12, 0x02, 0xD7,
+0x00, 0x0C, 0x03, 0xD0, 0x80, 0xC0, 0x30, 0x02, 0xCF, 0x00, 0x04, 0x03, 0x70,
+0x8C, 0xC0, 0x32, 0x00, 0xCF, 0x10, 0x3C, 0x22, 0xF4, 0x88, 0xC9, 0x48, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x1D, 0x00, 0xFF, 0x00, 0xFC,
+0x03, 0xF0, 0x8F, 0xC0, 0x3F, 0x10, 0xFF, 0x08, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x17, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x8F, 0xC8, 0x1F, 0x08, 0xF7, 0x00,
+0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x02, 0xFF, 0x00, 0xFC, 0x13, 0xF0, 0x4F,
+0xE0, 0x3D, 0x00, 0xFE, 0x08, 0xFC, 0x23, 0x74, 0x0F, 0xC0, 0x0B, 0x60, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x08, 0x5F, 0x01, 0x4C, 0x03,
+0x70, 0x09, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC4, 0x17,
+0x00, 0xD7, 0x00, 0x5C, 0x1B, 0xF0, 0x0D, 0xC0, 0x17, 0x00, 0xDF, 0x00, 0x7C,
+0x03, 0x70, 0x0D, 0xC8, 0x37, 0x00, 0xC3, 0x00, 0x2C, 0x03, 0xB0, 0x0D, 0x40,
+0x37, 0x00, 0x9F, 0x40, 0x4C, 0x80, 0x20, 0x09, 0xC2, 0x43, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x82, 0x39, 0x00, 0x6D, 0x00, 0xC4, 0x2B, 0x10,
+0x0E, 0x40, 0x1B, 0x00, 0xE9, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00,
+0xED, 0x00, 0xB4, 0x33, 0xD0, 0x2E, 0x40, 0x3B, 0x00, 0xEF, 0x00, 0xB4, 0x03,
+0xD0, 0x0E, 0x40, 0x3B, 0x20, 0xE1, 0x00, 0x84, 0x03, 0x50, 0x0E, 0x00, 0x3B,
+0x00, 0x8D, 0x00, 0x84, 0x01, 0xB0, 0x02, 0x40, 0x4F, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xCD, 0x03, 0xA5, 0x17, 0x50, 0x1E,
+0x40, 0x7B, 0x00, 0xED, 0x11, 0xB4, 0x07, 0xD0, 0x1E, 0x41, 0x7B, 0x00, 0xED,
+0x01, 0x96, 0x27, 0xD0, 0x1E, 0x40, 0x7B, 0x88, 0xED, 0x01, 0xB4, 0x07, 0xD0,
+0x36, 0x40, 0x73, 0x00, 0xE1, 0x01, 0xA4, 0x07, 0x90, 0x1E, 0x40, 0x7B, 0x00,
+0xED, 0x11, 0x14, 0x44, 0x19, 0x3E, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x28, 0x73, 0x00, 0xCD, 0x01, 0x24, 0x03, 0x10, 0x0C, 0x40,
+0x33, 0x00, 0x49, 0x05, 0x34, 0x03, 0xD0, 0x18, 0x40, 0xF3, 0x00, 0x8D, 0x01,
+0x74, 0x03, 0xD0, 0x0C, 0x40, 0x73, 0x02, 0x45, 0x1A, 0x34, 0x03, 0xD0, 0x5C,
+0x40, 0x77, 0x00, 0x81, 0x00, 0x04, 0x07, 0x50, 0x2C, 0x60, 0xB3, 0x00, 0xCD,
+0x47, 0x14, 0x07, 0x90, 0x1C, 0x40, 0x5B, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x17, 0xA0, 0x1D, 0x00, 0x7F, 0x02, 0x6C, 0x01, 0x70, 0x27, 0xC0, 0x9F,
+0x00, 0x7F, 0x01, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x1F, 0x00, 0x5F, 0x01, 0x5C,
+0x01, 0xF0, 0x05, 0xC0, 0xDF, 0x00, 0x7D, 0x02, 0x7C, 0x81, 0xF1, 0x37, 0xC0,
+0xDF, 0x40, 0x43, 0x00, 0xEC, 0x01, 0xB0, 0x27, 0xC0, 0x1B, 0x01, 0x7F, 0x23,
+0x9D, 0xA5, 0x20, 0xB7, 0xC0, 0x5F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x08, 0x45, 0x02, 0x1F, 0x02, 0x1C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00,
+0x1D, 0x20, 0x7C, 0x00, 0xF2, 0x21, 0xC8, 0x07, 0x06, 0x1F, 0x0A, 0x7C, 0x00,
+0xF0, 0x21, 0xC0, 0x07, 0x04, 0x1F, 0x80, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x87,
+0x06, 0x1F, 0x42, 0x7C, 0x28, 0xB0, 0x41, 0xC0, 0x07, 0x04, 0x1F, 0x00, 0x64,
+0x88, 0xF0, 0x21, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x25, 0x00, 0x9F, 0x19, 0x7C, 0x06, 0x30, 0x08, 0xC5, 0x24, 0x04, 0x9F,
+0x08, 0x74, 0x02, 0xF0, 0x09, 0xC0, 0x23, 0x00, 0x9B, 0x01, 0x7C, 0x02, 0x30,
+0x09, 0xC2, 0x23, 0x80, 0x93, 0x04, 0x4C, 0x02, 0xF0, 0x59, 0xC0, 0x27, 0x00,
+0x93, 0x03, 0x5C, 0x02, 0x71, 0x59, 0xC0, 0xA7, 0x40, 0x83, 0x00, 0x4C, 0x22,
+0x30, 0x28, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20,
+0x64, 0x00, 0x9D, 0x12, 0x74, 0x0A, 0x14, 0x09, 0x50, 0x24, 0x00, 0x97, 0x01,
+0x74, 0x02, 0xD8, 0x49, 0x40, 0x27, 0x40, 0x91, 0x11, 0x74, 0x0A, 0x50, 0x29,
+0x40, 0x27, 0xC0, 0x8B, 0x01, 0x44, 0x4A, 0xD0, 0x09, 0x44, 0xE7, 0x40, 0x91,
+0x86, 0x00, 0x12, 0x20, 0x19, 0x40, 0xE7, 0x10, 0x91, 0x01, 0x44, 0x06, 0x14,
+0x39, 0x41, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x24,
+0x25, 0x9D, 0x00, 0x74, 0x62, 0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74,
+0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x91, 0x08, 0x74, 0x0A, 0x10, 0x09, 0x40,
+0x37, 0x08, 0x91, 0x00, 0x44, 0x82, 0xD0, 0x09, 0x40, 0x27, 0x01, 0x99, 0x00,
+0x50, 0x03, 0x50, 0x0D, 0x40, 0x36, 0x00, 0x99, 0x04, 0x44, 0x03, 0x10, 0x0D,
+0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0x20, 0x05,
+0x8D, 0x14, 0x36, 0x12, 0x10, 0x48, 0x40, 0x20, 0x01, 0x85, 0x80, 0x34, 0x02,
+0xD0, 0x08, 0x40, 0x23, 0x01, 0x81, 0x08, 0x74, 0x12, 0x50, 0x08, 0x40, 0x23,
+0x01, 0x91, 0x00, 0x04, 0x02, 0xD2, 0x48, 0x40, 0x33, 0x01, 0x89, 0x00, 0x44,
+0x02, 0x10, 0x08, 0x44, 0x33, 0x00, 0x89, 0x01, 0x05, 0x93, 0x10, 0x48, 0x50,
+0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x06, 0x01, 0x1F,
+0x04, 0x7C, 0x28, 0x30, 0x01, 0xC0, 0x04, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xD0,
+0xA1, 0xC0, 0x87, 0x02, 0x13, 0x02, 0x7C, 0x28, 0x30, 0xE5, 0xC5, 0x87, 0x02,
+0x11, 0x00, 0x4C, 0x28, 0xF0, 0x01, 0xC0, 0x87, 0x22, 0x1B, 0x00, 0x5C, 0x00,
+0x72, 0x01, 0xC0, 0x07, 0x00, 0x1B, 0x14, 0x4C, 0x00, 0x30, 0xA1, 0xC0, 0x74,
+0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x2F, 0x05, 0xBF, 0x14,
+0x74, 0xA2, 0xF2, 0x8B, 0xC0, 0x2F, 0x22, 0xBF, 0x00, 0x7C, 0x02, 0xF0, 0x0B,
+0xC0, 0x2F, 0x0A, 0xB7, 0x04, 0x7C, 0x22, 0xF0, 0x09, 0xC0, 0x2F, 0x02, 0xBF,
+0x00, 0x7D, 0x02, 0xF0, 0x8F, 0x00, 0x2F, 0x02, 0xB7, 0x80, 0xFC, 0x02, 0x70,
+0x0B, 0xC0, 0x2F, 0x08, 0xF7, 0x00, 0xFD, 0x23, 0xF0, 0x8B, 0xC2, 0x77, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x05, 0xBF, 0x0C, 0xFC,
+0x82, 0x32, 0x09, 0xC0, 0x24, 0x00, 0xB3, 0x00, 0x7C, 0x02, 0xF0, 0x8A, 0xC0,
+0x24, 0x00, 0xBF, 0x00, 0xFC, 0x22, 0x30, 0x4B, 0xC0, 0x26, 0x05, 0xBF, 0x00,
+0xFC, 0x02, 0x30, 0x0B, 0xE0, 0x2F, 0x02, 0xFF, 0x00, 0xCD, 0x02, 0xB0, 0x0F,
+0xC2, 0x2F, 0x48, 0xB3, 0x00, 0xCC, 0x02, 0xF0, 0x0B, 0xC4, 0x74, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01, 0x1D, 0x0C, 0x74, 0x48,
+0x10, 0x05, 0x40, 0x04, 0x02, 0x51, 0x00, 0x74, 0x00, 0xD0, 0x41, 0x48, 0x84,
+0x04, 0x1D, 0x10, 0x74, 0x20, 0x14, 0x41, 0x41, 0x04, 0x01, 0x57, 0x80, 0x74,
+0x40, 0x10, 0x01, 0x60, 0x07, 0x02, 0x1D, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40,
+0x17, 0x50, 0x11, 0x00, 0x45, 0x00, 0xF0, 0x01, 0xC0, 0x62, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x05, 0x8D, 0x05, 0x36, 0x32, 0x14,
+0x88, 0x40, 0x62, 0x60, 0xC1, 0x00, 0x34, 0x02, 0xD0, 0x48, 0x50, 0x20, 0x03,
+0x8D, 0x00, 0x34, 0x02, 0x10, 0xCC, 0x40, 0x22, 0x05, 0xCD, 0x00, 0x36, 0x13,
+0x10, 0x88, 0x40, 0x23, 0x00, 0x8D, 0x00, 0x24, 0x02, 0x94, 0x18, 0x40, 0x23,
+0x00, 0x85, 0x40, 0x14, 0x02, 0xD2, 0x08, 0x40, 0x48, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x04, 0x9D, 0x80, 0x74, 0x02, 0x10, 0x09,
+0x50, 0x26, 0x01, 0x91, 0x01, 0x74, 0x02, 0xD0, 0x09, 0x40, 0xA4, 0x00, 0x9D,
+0x00, 0x74, 0x02, 0x11, 0x09, 0x40, 0x64, 0x10, 0x9D, 0x01, 0x74, 0x02, 0x10,
+0x09, 0x40, 0xE7, 0x10, 0x9D, 0x00, 0x64, 0x12, 0x12, 0x09, 0x40, 0x27, 0x08,
+0xD5, 0x04, 0x44, 0x02, 0xD0, 0x29, 0x40, 0x62, 0x28, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x20, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xC0,
+0x66, 0x00, 0x93, 0x03, 0x7C, 0x02, 0xF0, 0x19, 0xC0, 0xA4, 0x00, 0x9F, 0x01,
+0x7C, 0x02, 0x30, 0x09, 0xC0, 0xA6, 0x04, 0x9F, 0x03, 0x74, 0x02, 0x34, 0x29,
+0x40, 0xA7, 0x00, 0x8F, 0x00, 0x2C, 0x82, 0xB0, 0x29, 0xC0, 0xA3, 0x00, 0x97,
+0x02, 0x5C, 0x06, 0xF0, 0x29, 0xC0, 0x14, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x16, 0x08, 0x65, 0x0A, 0x9F, 0x14, 0x7C, 0x02, 0xF2, 0x48, 0xC0, 0x21,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF2, 0x59, 0xC0, 0x27, 0x00, 0x9F, 0x03, 0x7C,
+0x02, 0xF0, 0x08, 0xC0, 0x27, 0x00, 0x97, 0x80, 0x7C, 0x02, 0xF0, 0x09, 0x82,
+0x27, 0x00, 0x9F, 0x18, 0x5C, 0x02, 0xD0, 0x99, 0xC0, 0xA7, 0x64, 0x9B, 0x00,
+0x7C, 0x8E, 0x78, 0x38, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x08, 0x85, 0x04, 0x1F, 0x08, 0x7C, 0x40, 0xF1, 0x01, 0xC0, 0x07, 0x80,
+0x13, 0x20, 0x7C, 0x00, 0xF2, 0x41, 0xD0, 0x84, 0x00, 0x1F, 0x00, 0x0C, 0x00,
+0x30, 0x01, 0xC2, 0x87, 0x08, 0x1F, 0x02, 0x7E, 0x00, 0xF2, 0x21, 0xF0, 0x04,
+0x0C, 0x1B, 0x80, 0x7C, 0x00, 0x70, 0x01, 0xC9, 0x87, 0x00, 0x07, 0x80, 0x4D,
+0x08, 0x32, 0x01, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0xDC, 0x20, 0x7D, 0x01, 0xF6, 0x1D, 0x70, 0x05, 0x60, 0x17, 0x00, 0x51,
+0x00, 0x74, 0x01, 0xD0, 0x07, 0xC0, 0x16, 0x00, 0x7D, 0x05, 0xCD, 0x19, 0x30,
+0x27, 0x60, 0x17, 0x20, 0x5D, 0x00, 0xFC, 0xA9, 0x72, 0x45, 0x62, 0x1C, 0x11,
+0x71, 0x25, 0xDC, 0x8D, 0x14, 0x27, 0xC0, 0x9D, 0x01, 0x71, 0x89, 0xCC, 0x01,
+0x10, 0x37, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0,
+0xF2, 0x02, 0xCD, 0x02, 0x74, 0x03, 0x52, 0x0C, 0x44, 0x33, 0x00, 0x81, 0x00,
+0x34, 0x03, 0xD0, 0x2D, 0x40, 0x30, 0x00, 0xCD, 0x01, 0x24, 0x1F, 0x10, 0x2C,
+0x49, 0x33, 0x10, 0x8D, 0x00, 0x74, 0x03, 0x51, 0x18, 0x40, 0x30, 0x00, 0x41,
+0x01, 0x34, 0x40, 0x10, 0x0C, 0x40, 0xA3, 0x20, 0xC5, 0x09, 0x20, 0x07, 0x10,
+0x2C, 0x41, 0x40, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38,
+0x00, 0xED, 0x00, 0xB4, 0x01, 0x50, 0x0E, 0x40, 0x33, 0x40, 0xE1, 0x80, 0xB4,
+0x03, 0xD8, 0x0F, 0x41, 0x38, 0x00, 0x6D, 0x01, 0x84, 0x03, 0x10, 0x0E, 0x48,
+0x3B, 0x02, 0xED, 0x40, 0xB4, 0x01, 0x50, 0x1E, 0x48, 0x59, 0x00, 0x61, 0x81,
+0xD4, 0x42, 0x10, 0x06, 0x40, 0x2D, 0x00, 0x61, 0x00, 0x04, 0x46, 0x10, 0x0E,
+0x41, 0x10, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x78, 0x00,
+0x6F, 0x01, 0xB4, 0x07, 0x70, 0x1E, 0x40, 0x7B, 0x08, 0xE1, 0x01, 0xBC, 0x07,
+0xF0, 0x1E, 0x40, 0x78, 0x81, 0xBD, 0x01, 0xEC, 0x05, 0x34, 0x1E, 0x40, 0x7B,
+0x02, 0xEF, 0x01, 0xB4, 0x07, 0x70, 0x1E, 0x40, 0x7C, 0x40, 0x6B, 0x00, 0xBC,
+0x06, 0x30, 0x1A, 0xC0, 0x6B, 0x00, 0xE7, 0x01, 0xAC, 0x07, 0x34, 0x17, 0xC0,
+0x50, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x00, 0xDF,
+0x00, 0x7C, 0x81, 0x70, 0x0D, 0xC8, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x37, 0x04, 0x1F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC8, 0xB7, 0x00,
+0xDF, 0x00, 0x5C, 0x83, 0x72, 0x0C, 0xE0, 0x16, 0x08, 0xDF, 0x00, 0x3C, 0x02,
+0xC4, 0x01, 0xC0, 0x23, 0x00, 0x0F, 0x00, 0x7C, 0x83, 0xF0, 0x01, 0xD0, 0x43,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x7D, 0x00, 0xF3, 0x01,
+0xCC, 0x13, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x1F,
+0xC0, 0x7F, 0x04, 0xF3, 0x01, 0xCC, 0x13, 0x30, 0x17, 0xC0, 0x7C, 0x02, 0xFF,
+0x89, 0xFC, 0x87, 0x30, 0x9F, 0xC0, 0x7F, 0x00, 0x73, 0x01, 0xFC, 0x26, 0xF0,
+0x17, 0xC8, 0x6B, 0x20, 0xBB, 0x01, 0xFC, 0x07, 0xD0, 0x13, 0xC0, 0x1B, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x3D, 0x50, 0x71, 0x20, 0x84,
+0x83, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x2A, 0x48,
+0x3F, 0x00, 0x61, 0x00, 0xD4, 0x08, 0x11, 0x0B, 0xC0, 0x38, 0x00, 0xE9, 0x88,
+0xDC, 0x82, 0x10, 0xCE, 0x40, 0x3B, 0x01, 0x61, 0x00, 0xB4, 0x32, 0xD0, 0x06,
+0x42, 0x3B, 0x12, 0x21, 0x30, 0xB4, 0x02, 0xD0, 0x4A, 0x42, 0x57, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x61, 0x00, 0x84, 0x20,
+0xD0, 0x0E, 0x40, 0x3B, 0x09, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x86, 0x40, 0x3B,
+0x00, 0xB1, 0x00, 0xA4, 0x21, 0x10, 0x0E, 0x40, 0x38, 0x20, 0xED, 0x08, 0xB6,
+0x03, 0x10, 0x0E, 0x49, 0x2B, 0x00, 0x61, 0x10, 0xB4, 0x02, 0xD1, 0x02, 0x40,
+0x2F, 0x00, 0x29, 0x00, 0xB4, 0x03, 0xD0, 0x02, 0x44, 0x23, 0x02, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0xE1, 0x00, 0x01, 0x07, 0x04, 0x00, 0xD0,
+0x0C, 0x40, 0x73, 0x00, 0xCD, 0x03, 0x34, 0x03, 0xD1, 0x00, 0x44, 0x33, 0x00,
+0x11, 0x00, 0x34, 0x00, 0x14, 0x09, 0x50, 0xB6, 0x10, 0xCD, 0x03, 0x34, 0x02,
+0x14, 0x3C, 0x40, 0xA3, 0x40, 0x41, 0x01, 0x34, 0x4A, 0xD0, 0x20, 0x40, 0x23,
+0x02, 0x01, 0x03, 0x34, 0x6F, 0xD0, 0x11, 0x41, 0x0B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA0, 0xC5, 0x00, 0x93, 0x04, 0x47, 0x02, 0xF1, 0x2D,
+0x80, 0xF7, 0x01, 0xDF, 0x07, 0x74, 0x03, 0xF0, 0x01, 0x40, 0x3F, 0x42, 0xD3,
+0x00, 0x6C, 0x02, 0x30, 0x09, 0xC0, 0x3C, 0x00, 0xDF, 0x05, 0x74, 0x02, 0x30,
+0x1D, 0xC4, 0x27, 0x00, 0x53, 0x01, 0x7C, 0x12, 0xF0, 0x25, 0xC0, 0x73, 0x00,
+0xDB, 0x03, 0x7C, 0x0B, 0xF2, 0x69, 0x40, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x08, 0x27, 0x03, 0x9F, 0x00, 0x7E, 0x0A, 0xF0, 0x1D, 0xC0,
+0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x39, 0xC0, 0x77, 0x10, 0xDF, 0x03,
+0x5C, 0x0A, 0xF0, 0x29, 0xC0, 0x35, 0x00, 0xDB, 0x10, 0x54, 0x80, 0xF0, 0x0D,
+0xCD, 0x27, 0x01, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x85, 0xC1, 0xB7, 0x04, 0xDF,
+0x04, 0x7C, 0x02, 0xF0, 0x29, 0xC0, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x08, 0x0B, 0x00, 0x33, 0x00, 0xFC, 0x82, 0xF0, 0x0F, 0xC1, 0x3F,
+0x24, 0xFF, 0x30, 0xFC, 0x03, 0xF2, 0x03, 0xC4, 0x3B, 0x00, 0x73, 0x05, 0x8D,
+0x02, 0x30, 0x03, 0xC2, 0x3C, 0x04, 0xF3, 0x04, 0xFC, 0x00, 0xF1, 0x0E, 0xC0,
+0x06, 0x00, 0x3F, 0x00, 0xFC, 0x02, 0x70, 0x27, 0xC0, 0x3C, 0x40, 0xF3, 0x02,
+0xCC, 0x01, 0xF1, 0x0B, 0xC0, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x81, 0x20, 0xC6, 0x34, 0x91, 0x13, 0x5C, 0x16, 0xD0, 0x0D, 0x40, 0x37, 0x00,
+0xDD, 0x00, 0x74, 0x03, 0xD9, 0x39, 0x40, 0x37, 0x00, 0x51, 0x04, 0x44, 0x0E,
+0x10, 0x71, 0x40, 0x34, 0x00, 0xD3, 0x01, 0x74, 0x0C, 0xD0, 0x0D, 0x40, 0x44,
+0x00, 0x5D, 0x03, 0x34, 0x17, 0x11, 0x34, 0x40, 0xF4, 0x04, 0x81, 0x00, 0x44,
+0x07, 0xD0, 0x59, 0x48, 0x84, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0xA0, 0x46, 0x00, 0x91, 0x01, 0x74, 0x06, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xDD,
+0x04, 0x74, 0x83, 0xD0, 0x19, 0x40, 0x37, 0x00, 0x91, 0x40, 0x44, 0x06, 0x90,
+0x11, 0x40, 0x34, 0x20, 0xD1, 0x00, 0x74, 0x46, 0xD0, 0x1D, 0x40, 0x66, 0x04,
+0x5D, 0x11, 0x74, 0x06, 0x50, 0x25, 0x40, 0x74, 0x00, 0xD1, 0x00, 0x44, 0x0E,
+0xD0, 0x11, 0x40, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x20, 0x00, 0x81, 0x20, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00,
+0x34, 0x03, 0xD0, 0x08, 0x40, 0x33, 0x48, 0x81, 0x00, 0x06, 0x00, 0x90, 0x08,
+0x40, 0x30, 0x00, 0xC1, 0x00, 0x34, 0x02, 0xD0, 0x0C, 0x42, 0x20, 0x00, 0x49,
+0x00, 0x74, 0x02, 0x18, 0x04, 0x40, 0x10, 0x00, 0xC1, 0x20, 0x04, 0x02, 0xD0,
+0x08, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x40, 0x13, 0x40, 0x7E, 0x00, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x20, 0x7E,
+0x03, 0xD0, 0x01, 0xC2, 0x3F, 0x00, 0x13, 0x00, 0x4C, 0x02, 0xB0, 0x01, 0xC0,
+0x3C, 0x00, 0xD3, 0x00, 0x7C, 0x00, 0xF0, 0x0D, 0xC0, 0x06, 0x00, 0x5F, 0x00,
+0x7C, 0x02, 0x70, 0x05, 0xD0, 0x34, 0x10, 0x53, 0x00, 0x4C, 0x00, 0xF2, 0x01,
+0xD0, 0x04, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x2F, 0x10,
+0xBF, 0x00, 0xDE, 0x00, 0xF0, 0x0F, 0xC6, 0x3F, 0x00, 0xFF, 0x80, 0xFC, 0x03,
+0xD0, 0x03, 0xE0, 0x3F, 0x00, 0x2F, 0x00, 0xF4, 0x00, 0x70, 0x03, 0xD0, 0x3F,
+0x00, 0xF7, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0x7F, 0x00, 0xFC,
+0x02, 0xF0, 0x07, 0xC8, 0x3F, 0x00, 0x3F, 0xA0, 0xFD, 0x02, 0xF0, 0x0B, 0xC0,
+0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x3F, 0x00, 0xB3,
+0x00, 0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xCC, 0x03, 0x30,
+0x0A, 0xC0, 0x0C, 0x01, 0x33, 0x00, 0xCC, 0x00, 0xF0, 0x03, 0xC0, 0x0B, 0x00,
+0xFB, 0x06, 0xEC, 0x05, 0x30, 0x4F, 0xC1, 0x2F, 0x00, 0xF3, 0x14, 0xFC, 0x23,
+0xF0, 0x0B, 0xC0, 0x0F, 0x00, 0xF7, 0x04, 0xCC, 0x22, 0x34, 0x03, 0xC0, 0x0C,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x07, 0x10, 0x91, 0x80,
+0x44, 0x00, 0x70, 0x01, 0x40, 0x07, 0x00, 0x9D, 0x00, 0x44, 0x43, 0x10, 0x09,
+0x48, 0x84, 0x00, 0x91, 0x00, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x27, 0x00, 0xF9,
+0x0B, 0x44, 0x55, 0x15, 0x2F, 0x40, 0x6F, 0x00, 0xD1, 0x03, 0x70, 0x3B, 0xD0,
+0x39, 0x40, 0x47, 0x40, 0xF1, 0x00, 0x6C, 0x0A, 0x10, 0x15, 0x40, 0x0D, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x05, 0x01, 0x20, 0x14,
+0x00, 0xD0, 0x00, 0x40, 0x23, 0x00, 0x0D, 0x20, 0x14, 0x13, 0x10, 0x00, 0x40,
+0x01, 0x02, 0x01, 0x20, 0x04, 0x02, 0xD0, 0x08, 0x42, 0x23, 0x00, 0xC1, 0x04,
+0x24, 0x81, 0x10, 0x0C, 0x4A, 0x27, 0x08, 0xCD, 0x00, 0x34, 0x03, 0xD1, 0x88,
+0x40, 0x03, 0x00, 0xC5, 0x08, 0x44, 0xA2, 0x13, 0x08, 0x46, 0x4C, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x05, 0x11, 0x11, 0x04, 0x54, 0x04,
+0xD0, 0x11, 0x41, 0x47, 0x00, 0x1D, 0x11, 0x74, 0x03, 0x10, 0x15, 0x40, 0x41,
+0x00, 0x11, 0x01, 0x44, 0x04, 0xD2, 0x31, 0x4C, 0xE7, 0x00, 0xD1, 0x00, 0x64,
+0x21, 0x10, 0x0D, 0x40, 0x27, 0x01, 0xDD, 0x00, 0x74, 0x03, 0xD0, 0x19, 0x48,
+0x87, 0x00, 0xD1, 0x00, 0x64, 0x46, 0x10, 0x0D, 0x40, 0x0D, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x67, 0x00, 0x93, 0x00, 0x5D, 0x46, 0xF0,
+0x39, 0xC0, 0x47, 0x01, 0x1F, 0x03, 0x5C, 0x03, 0x10, 0x29, 0xE1, 0x45, 0x40,
+0x93, 0x05, 0x4C, 0x0C, 0xD0, 0x19, 0xC0, 0xC7, 0x00, 0xDB, 0x00, 0x6C, 0x17,
+0x30, 0x0D, 0x60, 0x23, 0x40, 0xDF, 0x80, 0x7C, 0x03, 0xF2, 0x09, 0xC0, 0xC7,
+0x00, 0xD7, 0x00, 0x0C, 0x0E, 0x30, 0xB1, 0x81, 0x00, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0x80, 0x69, 0x40, 0x9F, 0x01, 0xEC, 0x00, 0x70, 0x0B,
+0xC0, 0x0F, 0x00, 0xAF, 0x20, 0x8C, 0x03, 0xF0, 0x0B, 0xE2, 0x0E, 0x00, 0xAF,
+0x00, 0xFD, 0x00, 0xF0, 0x01, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xDC, 0x06, 0xF8,
+0x0F, 0xC1, 0x6F, 0x00, 0xF2, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0x40, 0x4F, 0x02,
+0xFF, 0x00, 0xDF, 0x02, 0xF0, 0x07, 0xE0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0x83, 0x00, 0x4D, 0x0A, 0xF0, 0x21, 0xC0,
+0x24, 0x81, 0x1F, 0x02, 0x5C, 0x03, 0x30, 0xA5, 0xC0, 0x44, 0x00, 0x1B, 0x00,
+0x7C, 0x0A, 0x32, 0x29, 0xC9, 0xA6, 0x42, 0xC3, 0x00, 0x5C, 0x01, 0x34, 0x0D,
+0xC0, 0x27, 0x80, 0xD3, 0x08, 0x7C, 0x03, 0x30, 0x49, 0xC0, 0x07, 0x10, 0xDF,
+0x00, 0x4C, 0x22, 0x30, 0x09, 0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x2C, 0x14, 0x91, 0x20, 0x44, 0x2A, 0xD0, 0x89, 0x41, 0x84,
+0x00, 0x1D, 0x09, 0xF0, 0x03, 0x30, 0x85, 0x00, 0x24, 0x00, 0x11, 0x1A, 0x74,
+0x82, 0x30, 0x01, 0x40, 0xA4, 0x00, 0xFB, 0x40, 0x44, 0x01, 0x10, 0x0F, 0x40,
+0x27, 0x00, 0xF1, 0x01, 0xF4, 0x03, 0x50, 0x79, 0x40, 0x03, 0x00, 0xFD, 0x24,
+0x54, 0x02, 0xB0, 0x1C, 0x40, 0x6F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x20, 0x30, 0x08, 0x81, 0x00, 0x20, 0x26, 0xD1, 0x38, 0x40, 0x60, 0x20,
+0x8D, 0x20, 0x34, 0x03, 0x10, 0x39, 0x40, 0x00, 0x00, 0x09, 0x03, 0x16, 0x02,
+0x10, 0x20, 0x40, 0x04, 0x01, 0xC1, 0x00, 0x54, 0x02, 0x10, 0x3C, 0x40, 0x31,
+0x00, 0xC8, 0x01, 0x14, 0x03, 0x90, 0x28, 0x40, 0x13, 0x00, 0xD9, 0x00, 0x06,
+0x03, 0x10, 0x8C, 0x40, 0x5F, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x02, 0x50, 0x00, 0xE1, 0x01, 0xA4, 0x07, 0xD0, 0x16, 0x60, 0x7A, 0x20, 0xED,
+0x01, 0xB4, 0x03, 0x90, 0x1E, 0x40, 0x40, 0x00, 0xE1, 0x41, 0xB6, 0x0D, 0x94,
+0x16, 0x42, 0x4A, 0x00, 0xC9, 0x01, 0x84, 0x05, 0x10, 0x1E, 0x40, 0x7B, 0x00,
+0xE9, 0x01, 0xB4, 0x27, 0xD0, 0x1A, 0x40, 0x5B, 0x00, 0xCD, 0x01, 0x16, 0x26,
+0x90, 0x9A, 0x40, 0x3F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18,
+0x30, 0x02, 0x01, 0x00, 0x0D, 0x01, 0xF0, 0x8D, 0xC0, 0x30, 0x04, 0xCD, 0x30,
+0x7C, 0x23, 0x10, 0x08, 0xC0, 0x00, 0x01, 0x0B, 0x00, 0x7C, 0x0B, 0x30, 0x88,
+0xC0, 0x12, 0x02, 0xC3, 0x00, 0x5C, 0x22, 0x32, 0x0C, 0xC1, 0x23, 0x00, 0xC9,
+0x08, 0x7C, 0x03, 0x30, 0x08, 0xC0, 0x23, 0x00, 0xCF, 0x00, 0x0C, 0x03, 0x30,
+0x04, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x1D,
+0x14, 0x7F, 0x00, 0xDD, 0x01, 0xF2, 0x87, 0xD0, 0x3D, 0x00, 0xFF, 0x08, 0xFC,
+0x13, 0x70, 0x0F, 0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xFC, 0x01, 0x70, 0x0F, 0xC8,
+0x1D, 0x40, 0xFF, 0x10, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0xAB, 0x42, 0xF7, 0x20,
+0xFC, 0x03, 0x70, 0x0B, 0xC8, 0x2F, 0x12, 0xFC, 0x00, 0xFC, 0x02, 0xF0, 0x03,
+0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x27, 0x00,
+0xDF, 0x00, 0x4E, 0x03, 0x31, 0x0D, 0xC0, 0x17, 0x00, 0x5F, 0x01, 0xCC, 0x03,
+0xF0, 0x0D, 0xC0, 0x04, 0x00, 0xD3, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0x1F,
+0x20, 0xDF, 0x06, 0x5C, 0x00, 0xF0, 0x2D, 0xC1, 0xB6, 0x00, 0xD3, 0x00, 0x7C,
+0x03, 0xA8, 0x1D, 0xC0, 0x15, 0x00, 0xDF, 0x06, 0x4D, 0x01, 0x30, 0x1D, 0xC0,
+0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x29, 0x09, 0xED,
+0x20, 0xC4, 0x03, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xFD, 0x00, 0x84, 0x07, 0xD0,
+0x0C, 0x40, 0x08, 0x00, 0xE1, 0x00, 0xB4, 0x03, 0xD8, 0x0E, 0x40, 0x3B, 0x08,
+0xFD, 0x10, 0xAC, 0x00, 0xD0, 0x2E, 0x44, 0x3B, 0x00, 0xE1, 0x02, 0xF4, 0x03,
+0x10, 0x0E, 0x40, 0x18, 0x00, 0xED, 0x16, 0xC4, 0x02, 0xB0, 0x0A, 0xC0, 0x4E,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF9, 0x00, 0xED, 0x81,
+0x84, 0x07, 0x11, 0x1E, 0x48, 0xFB, 0x08, 0xED, 0x11, 0x84, 0x07, 0xD0, 0x1E,
+0x40, 0x48, 0x00, 0xE1, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x41, 0xFB, 0x00, 0xED,
+0x05, 0x94, 0x44, 0xD9, 0x5E, 0x40, 0x73, 0x00, 0xE5, 0x05, 0xB4, 0x07, 0x90,
+0x1C, 0x44, 0x79, 0x00, 0xED, 0x41, 0x84, 0x07, 0x10, 0x14, 0x40, 0x04, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0xB3, 0x04, 0xCD, 0x02, 0x05,
+0x83, 0x12, 0x6C, 0x60, 0x73, 0x10, 0xCD, 0x03, 0x04, 0x03, 0xD0, 0x1C, 0x50,
+0x30, 0x02, 0xC1, 0x09, 0x34, 0x0B, 0xD0, 0x3C, 0x44, 0x73, 0x01, 0xCD, 0x40,
+0x24, 0x04, 0xD8, 0x0C, 0x40, 0x73, 0x80, 0xC5, 0x00, 0x34, 0x03, 0x10, 0x0C,
+0x42, 0x30, 0x00, 0xCD, 0x00, 0x24, 0x02, 0x90, 0x00, 0x50, 0x4A, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x5D, 0x00, 0x7F, 0x00, 0xCC, 0x05,
+0x30, 0x27, 0xC0, 0x1F, 0x00, 0x7F, 0x08, 0x4D, 0x01, 0xF0, 0x17, 0xC1, 0x5C,
+0x40, 0x73, 0x01, 0xFC, 0x01, 0xF0, 0x27, 0x40, 0x5F, 0x00, 0x5F, 0x00, 0xDC,
+0x01, 0xF0, 0x05, 0xC0, 0x56, 0x41, 0x57, 0x00, 0x7C, 0x01, 0xB0, 0x05, 0xC0,
+0x1D, 0x89, 0x5F, 0x00, 0x8C, 0x01, 0x30, 0x07, 0xC0, 0x5C, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x81, 0x08, 0x1F, 0x10, 0x7C, 0x24, 0xF4,
+0xA1, 0xC0, 0x07, 0x04, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC4, 0x47, 0x08,
+0x1F, 0x26, 0x7C, 0x00, 0xF0, 0x41, 0xC2, 0x87, 0x00, 0x0F, 0x00, 0x7C, 0x00,
+0xF2, 0x00, 0xC0, 0x07, 0x00, 0x1B, 0x00, 0x7C, 0x00, 0x70, 0x01, 0xC0, 0x03,
+0x00, 0x1F, 0x00, 0x5C, 0x04, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x83, 0x00, 0x0C, 0x02, 0x30, 0x89,
+0xC0, 0x27, 0x00, 0x9F, 0x01, 0x7C, 0x02, 0xF0, 0x09, 0xD0, 0x60, 0x02, 0x93,
+0x01, 0x7C, 0x46, 0xF0, 0x59, 0xC0, 0x23, 0x00, 0x9B, 0x00, 0x4C, 0x42, 0xB0,
+0x09, 0xC0, 0x22, 0x01, 0x93, 0x00, 0x3C, 0x02, 0x90, 0x49, 0xC0, 0xA7, 0x40,
+0x93, 0x00, 0x4D, 0x02, 0x14, 0x09, 0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x00, 0xE4, 0x21, 0x91, 0x00, 0x44, 0x0E, 0x14, 0x29, 0xC0,
+0x25, 0x02, 0x9D, 0x1B, 0x74, 0x02, 0xD0, 0x09, 0xC0, 0x24, 0x00, 0x95, 0x12,
+0x5C, 0x22, 0xD2, 0x19, 0x40, 0x67, 0x00, 0x91, 0x80, 0x44, 0x02, 0x10, 0x29,
+0x41, 0x64, 0x00, 0x91, 0x00, 0x74, 0x02, 0x50, 0x39, 0x41, 0x67, 0x00, 0x91,
+0x02, 0x44, 0x02, 0x10, 0x09, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x64, 0x00, 0x91, 0x00, 0x44, 0x22, 0x10, 0x09, 0x41, 0x27,
+0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x08, 0x40, 0x24, 0x00, 0x99, 0x08, 0x74,
+0x02, 0xD0, 0x09, 0x40, 0x27, 0x01, 0x99, 0x00, 0x04, 0x82, 0x94, 0x09, 0x40,
+0x26, 0x00, 0x95, 0x00, 0x74, 0x02, 0x50, 0x09, 0x40, 0x27, 0x20, 0x89, 0x42,
+0x44, 0x02, 0x50, 0x09, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x20, 0x01, 0x81, 0x04, 0x04, 0x12, 0x10, 0x08, 0x40, 0x21, 0x82,
+0x8D, 0x10, 0x34, 0x12, 0xD0, 0x58, 0x40, 0x20, 0x01, 0x8D, 0x10, 0x14, 0x42,
+0xD0, 0x78, 0x41, 0x33, 0x06, 0x81, 0x00, 0x04, 0x02, 0x10, 0x48, 0x40, 0x20,
+0x01, 0x85, 0x04, 0x34, 0x52, 0x59, 0x48, 0x40, 0x23, 0x01, 0x89, 0x04, 0x44,
+0x12, 0x50, 0x48, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB8, 0x86, 0x42, 0x03, 0x0A, 0x45, 0x31, 0x30, 0xE1, 0x40, 0x97, 0x04, 0x1F,
+0x08, 0x7C, 0x28, 0xF0, 0xA1, 0xC0, 0x80, 0x02, 0x1B, 0x06, 0x7C, 0x19, 0xF0,
+0x21, 0xC0, 0x87, 0x01, 0x1B, 0x1E, 0x4C, 0x28, 0xB1, 0xA1, 0xC0, 0x06, 0x40,
+0x17, 0x00, 0x7C, 0x20, 0xF0, 0x01, 0x80, 0x07, 0x00, 0x0B, 0x0A, 0x4C, 0x28,
+0x70, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8,
+0x2F, 0x0A, 0xBF, 0x08, 0xFC, 0x0A, 0xF2, 0xCB, 0xC0, 0x2D, 0x00, 0xBF, 0x00,
+0x7C, 0x22, 0xF0, 0x8B, 0xC8, 0x2D, 0x02, 0xB7, 0x14, 0xDC, 0x52, 0xF0, 0x0B,
+0xC2, 0x3F, 0x00, 0x9F, 0x00, 0xFD, 0x83, 0xF0, 0x89, 0xC0, 0x2F, 0x02, 0x9B,
+0x08, 0x7C, 0x02, 0x70, 0x8B, 0xC8, 0x2E, 0x02, 0x97, 0x08, 0xFC, 0x22, 0xB0,
+0x8B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA8, 0x2F,
+0x05, 0xD3, 0x4C, 0xCC, 0x02, 0xF1, 0x0B, 0xC0, 0x2F, 0x02, 0xB3, 0x04, 0xFC,
+0x52, 0x30, 0xCB, 0xC0, 0x2C, 0x00, 0xB3, 0x00, 0xCC, 0x22, 0xF0, 0x4B, 0xC0,
+0x2D, 0x05, 0x9F, 0x0C, 0x5C, 0x02, 0xB0, 0x0B, 0xC0, 0x2C, 0x00, 0xB3, 0x05,
+0x5C, 0x16, 0xB0, 0x0F, 0xC0, 0x2C, 0x00, 0xBF, 0x80, 0xCD, 0x02, 0x31, 0x0B,
+0xC0, 0x64, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01,
+0x11, 0x0C, 0x45, 0x48, 0xD0, 0x01, 0x41, 0x07, 0x02, 0x11, 0x54, 0x74, 0x00,
+0x38, 0xC1, 0xC0, 0x90, 0x04, 0x11, 0x10, 0x44, 0x20, 0xD2, 0x41, 0x41, 0x07,
+0x21, 0x1D, 0x0C, 0x44, 0x40, 0x40, 0x01, 0x41, 0x04, 0x02, 0x1B, 0x00, 0x70,
+0x54, 0x10, 0x01, 0xC0, 0x96, 0x00, 0x03, 0x10, 0x45, 0x20, 0x50, 0x01, 0x40,
+0x71, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x05, 0x81,
+0x04, 0x04, 0x32, 0xD0, 0x88, 0x60, 0x23, 0x00, 0x81, 0x2C, 0x36, 0x02, 0x18,
+0x4C, 0x62, 0x21, 0x4B, 0x80, 0x08, 0x24, 0x02, 0xD0, 0xC8, 0x40, 0x21, 0x2D,
+0x8D, 0x44, 0x74, 0x12, 0x80, 0x88, 0x50, 0x20, 0x00, 0x85, 0x02, 0x14, 0x0A,
+0x50, 0x0C, 0x48, 0x22, 0x12, 0x8D, 0x08, 0x24, 0x02, 0x10, 0x08, 0x40, 0x48,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x91, 0x82,
+0x44, 0x42, 0xD0, 0x0D, 0x40, 0x27, 0x05, 0x91, 0x00, 0x74, 0x02, 0x10, 0x49,
+0x40, 0x25, 0x01, 0xD1, 0x00, 0x64, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x02, 0x8D,
+0x00, 0x64, 0x02, 0x10, 0x08, 0x40, 0x24, 0x01, 0x9D, 0x00, 0x74, 0x02, 0x50,
+0x0D, 0x40, 0x26, 0x00, 0x91, 0x00, 0x64, 0x02, 0x50, 0x29, 0x40, 0x61, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x25, 0x42, 0x93, 0x00, 0x4D,
+0x02, 0xF0, 0x79, 0xC0, 0x67, 0x40, 0x93, 0x11, 0x7C, 0x02, 0x34, 0x39, 0xC1,
+0x25, 0x00, 0x93, 0x10, 0x6D, 0x4E, 0xF0, 0x69, 0xC0, 0xE5, 0x00, 0x9F, 0x00,
+0x7C, 0x8A, 0xB0, 0x09, 0xC0, 0x64, 0x00, 0x97, 0x00, 0x5C, 0x02, 0x70, 0x09,
+0xC0, 0xA6, 0x00, 0x9F, 0x00, 0x6D, 0x1A, 0x30, 0x29, 0xC0, 0x14, 0xA0, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x65, 0x00, 0x9F, 0x20, 0x7C, 0x26,
+0xF0, 0x49, 0xC0, 0x27, 0x00, 0x9F, 0x04, 0x3C, 0x02, 0xF0, 0x19, 0xD0, 0x24,
+0x00, 0x9F, 0x00, 0x4C, 0x26, 0xF0, 0x09, 0xC0, 0x67, 0x84, 0x9F, 0x00, 0x5C,
+0x22, 0x70, 0x09, 0xC0, 0x67, 0x08, 0x9B, 0x00, 0x7C, 0x02, 0x34, 0x09, 0xC0,
+0x67, 0x82, 0x9F, 0x00, 0x5D, 0x02, 0xF0, 0x09, 0xC0, 0x5B, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x01, 0x00, 0x0F, 0x00, 0x4E, 0x48, 0xF2,
+0x41, 0xE4, 0x87, 0x01, 0x1F, 0x08, 0x7C, 0x80, 0x70, 0x00, 0xC0, 0x84, 0x00,
+0x13, 0x01, 0x7C, 0x00, 0xF8, 0x21, 0xC4, 0x87, 0x08, 0x1F, 0x00, 0x5C, 0x08,
+0xF0, 0x01, 0xC0, 0x03, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x41, 0xC0, 0x87,
+0x40, 0x13, 0x00, 0x0C, 0x00, 0xF0, 0xA0, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x1C, 0x00, 0x5D, 0x20, 0xC6, 0x1D, 0x70, 0x27,
+0x40, 0x5F, 0x04, 0x7D, 0x08, 0x74, 0x15, 0xD0, 0x27, 0xC0, 0x14, 0x00, 0x71,
+0x00, 0xDC, 0x09, 0xF0, 0x37, 0x60, 0x9F, 0x00, 0x5D, 0x00, 0x04, 0x01, 0x30,
+0x47, 0x40, 0x17, 0x40, 0x52, 0x00, 0x5C, 0x01, 0xD0, 0x26, 0x40, 0x17, 0x04,
+0x74, 0x82, 0x44, 0x01, 0xD0, 0x05, 0x40, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0xF2, 0x04, 0xCD, 0x00, 0x24, 0x0F, 0x50, 0x8C, 0x40,
+0x77, 0x00, 0xCD, 0x03, 0x34, 0x03, 0xD0, 0x2C, 0x41, 0x36, 0x00, 0xD1, 0x20,
+0x34, 0x47, 0xD2, 0x0C, 0x41, 0xB3, 0x00, 0xCD, 0x00, 0x14, 0x03, 0x50, 0x1C,
+0x40, 0x23, 0x08, 0x88, 0x20, 0x74, 0x03, 0xD0, 0x20, 0x60, 0x63, 0x00, 0x90,
+0x12, 0x05, 0x03, 0xD0, 0x1C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x80, 0xA8, 0x10, 0xED, 0x00, 0xA4, 0x01, 0x50, 0x0E, 0x40, 0x3B,
+0x20, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0B, 0x60, 0x28, 0x00, 0xE1, 0x00, 0x94,
+0x09, 0x10, 0x0E, 0x41, 0x9B, 0x08, 0xCD, 0x04, 0xC4, 0x13, 0x12, 0x06, 0x40,
+0x2B, 0x00, 0xE9, 0x00, 0xB6, 0x03, 0xD0, 0x06, 0x40, 0x63, 0x00, 0xE5, 0x00,
+0x84, 0x02, 0xD0, 0x0E, 0x60, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x18, 0x48, 0x10, 0xFF, 0x01, 0xA5, 0x07, 0x70, 0x1E, 0x40, 0x5B, 0x00,
+0xED, 0x01, 0xBC, 0x87, 0xF0, 0x16, 0xC0, 0x7A, 0x42, 0xE1, 0x01, 0xBC, 0x07,
+0xD0, 0x16, 0x40, 0x7B, 0x00, 0xEF, 0x09, 0x9D, 0x5F, 0x70, 0x16, 0xE4, 0x73,
+0x00, 0xAB, 0x01, 0xBC, 0x07, 0xF0, 0x12, 0x80, 0x7B, 0x00, 0x21, 0x01, 0x8C,
+0x07, 0xF0, 0x1E, 0xD0, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xB8, 0x05, 0x00, 0xDF, 0x16, 0x5C, 0x01, 0x70, 0x0D, 0xC0, 0x17, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xA1, 0x42, 0xD1, 0x37, 0x20, 0x1F, 0x00, 0x7C, 0x01, 0xF0,
+0x05, 0xC0, 0x27, 0x00, 0xDF, 0x08, 0x3C, 0x1B, 0x70, 0x05, 0xC0, 0x37, 0x40,
+0xD3, 0x00, 0x5C, 0x83, 0xF0, 0x0D, 0x80, 0x37, 0x00, 0x5B, 0x20, 0x7C, 0x02,
+0xF0, 0x0C, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20,
+0x4D, 0x00, 0xF7, 0x31, 0xCC, 0x13, 0xF0, 0x97, 0xC0, 0x7C, 0x00, 0xFF, 0x01,
+0xFC, 0x06, 0xB0, 0x9F, 0xC0, 0x7C, 0x00, 0x73, 0x09, 0xFC, 0x27, 0xF0, 0x1F,
+0xC0, 0x7F, 0x00, 0xFF, 0x81, 0xCC, 0x07, 0x70, 0x9F, 0xC0, 0x6C, 0x40, 0xB7,
+0x41, 0xCC, 0x07, 0xB0, 0x1A, 0xC0, 0x6C, 0x20, 0xBF, 0x21, 0xCC, 0x07, 0xF0,
+0x1B, 0xC0, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x0D,
+0x00, 0xEB, 0x00, 0x84, 0x03, 0xD0, 0x8E, 0x40, 0x38, 0x00, 0xED, 0x00, 0xB4,
+0x22, 0xD0, 0xC6, 0x50, 0x28, 0x30, 0x60, 0x18, 0x9C, 0x23, 0xD0, 0x0E, 0xC0,
+0x39, 0x02, 0xED, 0x04, 0x84, 0x13, 0x40, 0x03, 0xC0, 0x2A, 0x00, 0xE5, 0x00,
+0xAC, 0x23, 0x10, 0x0E, 0xC2, 0x2A, 0x00, 0xE9, 0x00, 0x85, 0x42, 0xD0, 0x0E,
+0x40, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+0xE5, 0x10, 0x84, 0x23, 0xD0, 0x06, 0x42, 0x18, 0x04, 0x6D, 0x00, 0xB4, 0x02,
+0xD0, 0x06, 0x42, 0x38, 0x00, 0x61, 0x80, 0xB4, 0x02, 0xD0, 0x8A, 0x40, 0xBB,
+0x00, 0xED, 0x20, 0xC4, 0x4B, 0x42, 0x06, 0x40, 0x32, 0x00, 0xA5, 0x00, 0xA4,
+0x03, 0x90, 0x02, 0x40, 0x28, 0x00, 0xA5, 0x08, 0xA4, 0x03, 0xD0, 0x0A, 0x40,
+0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x01, 0x00, 0xD1,
+0x01, 0x04, 0x02, 0xD0, 0x28, 0x50, 0x80, 0x04, 0x8D, 0x47, 0x34, 0x02, 0xD0,
+0x05, 0x58, 0x34, 0x42, 0x01, 0x91, 0x14, 0xCE, 0xD0, 0x39, 0x40, 0x01, 0x20,
+0xCD, 0x00, 0x04, 0x07, 0x00, 0x00, 0x40, 0x32, 0x40, 0xC5, 0x00, 0x24, 0x03,
+0x10, 0x0C, 0x40, 0x22, 0x00, 0xC9, 0x00, 0x24, 0x0E, 0xD0, 0x8C, 0x40, 0x1B,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x05, 0x06, 0xF5, 0x20,
+0x4C, 0x02, 0xF0, 0xB9, 0xC1, 0xA4, 0x00, 0x1F, 0x05, 0x74, 0x82, 0xB0, 0x09,
+0xC0, 0x74, 0x00, 0x93, 0x03, 0x7C, 0x42, 0xD0, 0x39, 0xC1, 0xB7, 0x00, 0xFF,
+0x00, 0xCC, 0x07, 0x70, 0x05, 0xC0, 0x26, 0x40, 0x85, 0x00, 0xEC, 0x03, 0xB0,
+0x01, 0xC8, 0x24, 0x00, 0x57, 0x80, 0x6C, 0x0E, 0xF0, 0x0D, 0xC0, 0x57, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x07, 0x20, 0xDF, 0x00, 0x7C,
+0x28, 0xF0, 0x21, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x02, 0xF2, 0x19, 0xC0,
+0x27, 0x04, 0x9F, 0x02, 0x7C, 0x00, 0xF0, 0x41, 0xC0, 0x17, 0x00, 0xCF, 0x00,
+0x7D, 0x03, 0xF0, 0x05, 0xC0, 0x23, 0x40, 0x9E, 0x00, 0x7C, 0x03, 0xF0, 0x01,
+0xC0, 0x27, 0x00, 0x5C, 0x00, 0x1C, 0x02, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x0B, 0x00, 0xFB, 0x00, 0xCC, 0x42,
+0xF0, 0x09, 0xC0, 0x2B, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0xF0, 0x01, 0xC0, 0x34,
+0x00, 0xB3, 0x00, 0xB4, 0x00, 0x30, 0x03, 0xC0, 0x3C, 0x00, 0xDF, 0x00, 0xCC,
+0x03, 0xF0, 0x06, 0xC0, 0xEC, 0x00, 0x93, 0x08, 0x0C, 0x03, 0x34, 0x53, 0x40,
+0x38, 0x00, 0xE3, 0xC0, 0xCC, 0x56, 0x31, 0x0F, 0xC0, 0x07, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xC6, 0x01, 0xD1, 0x00, 0x44, 0x14, 0xD0,
+0x39, 0x40, 0x47, 0x01, 0x91, 0x01, 0x74, 0x02, 0xC8, 0x11, 0x50, 0x34, 0x00,
+0x1F, 0x83, 0x74, 0x0C, 0x12, 0x31, 0x44, 0xC4, 0x0C, 0xDF, 0x00, 0x54, 0x03,
+0xF0, 0x25, 0x44, 0x24, 0x00, 0x91, 0x01, 0x45, 0x03, 0xB0, 0x04, 0x40, 0x35,
+0x00, 0xD3, 0x03, 0x54, 0x02, 0x10, 0x0D, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xA0, 0x46, 0x40, 0xD1, 0x00, 0x44, 0x04, 0xD0, 0x11,
+0x40, 0x67, 0x00, 0x11, 0x11, 0x76, 0x06, 0xD1, 0x19, 0x54, 0x34, 0x00, 0x91,
+0x01, 0x76, 0x46, 0x10, 0x39, 0x60, 0x64, 0x10, 0xDD, 0x40, 0x44, 0x03, 0xD0,
+0x25, 0x40, 0x24, 0x18, 0x91, 0x40, 0x54, 0x03, 0x10, 0x0D, 0x40, 0x25, 0x40,
+0xD1, 0x0A, 0x44, 0x02, 0x10, 0x09, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0xC1, 0x40, 0x04, 0x00, 0xD0, 0x00, 0x42,
+0x23, 0x00, 0x01, 0x00, 0x34, 0x02, 0xD0, 0x00, 0x40, 0x20, 0x00, 0x81, 0x00,
+0x34, 0x02, 0x10, 0x00, 0x70, 0x00, 0x00, 0xC5, 0x00, 0x14, 0x03, 0x10, 0x00,
+0x50, 0x20, 0x20, 0x81, 0x00, 0x14, 0x03, 0x90, 0x0C, 0x48, 0x21, 0x00, 0xC9,
+0x80, 0x14, 0x02, 0x10, 0x0C, 0x4C, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x06, 0x00, 0xE3, 0x00, 0x4C, 0x02, 0xD0, 0x01, 0xC2, 0x27,
+0x00, 0x13, 0x00, 0x7E, 0x02, 0xC0, 0x03, 0xC0, 0x3C, 0x40, 0x91, 0x00, 0x7C,
+0x00, 0x38, 0x09, 0xC0, 0x24, 0x00, 0xFC, 0x00, 0xCC, 0x83, 0xD0, 0x05, 0xC0,
+0x24, 0x40, 0x93, 0x40, 0x5C, 0x03, 0x10, 0x09, 0xC0, 0x25, 0x00, 0xC3, 0x80,
+0x4C, 0x02, 0x34, 0x09, 0xC0, 0x07, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xB8, 0x0D, 0x00, 0xF7, 0x00, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x2F, 0x40,
+0xBF, 0x00, 0xFC, 0x02, 0xF0, 0x03, 0xC0, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x00,
+0xF0, 0x03, 0xC4, 0x0F, 0x00, 0xFF, 0x00, 0xB8, 0x03, 0xF0, 0x03, 0xC4, 0x2F,
+0x40, 0xBF, 0x00, 0xEC, 0x03, 0x70, 0x0F, 0xC0, 0x2F, 0x00, 0xF7, 0x00, 0xFC,
+0x02, 0xF0, 0x0F, 0xC0, 0x17, 0xE0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x80, 0x7F, 0x00, 0xBF, 0x20, 0xCC, 0x13, 0x70, 0x1F, 0xC0, 0x7F, 0x02, 0xF3,
+0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC0, 0x7B, 0x00, 0xFF, 0x01, 0x8C, 0x07, 0x30,
+0x1F, 0xC0, 0x7D, 0x00, 0xF3, 0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC0, 0x7F, 0x00,
+0xF3, 0x03, 0xEC, 0x07, 0xB0, 0x16, 0xC0, 0x5C, 0x00, 0x2B, 0x01, 0xEC, 0x05,
+0x30, 0x0B, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+0x37, 0x00, 0x9D, 0x00, 0xEC, 0x0B, 0x10, 0x01, 0x40, 0x07, 0x01, 0x11, 0x00,
+0x44, 0x00, 0x14, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x20, 0x40, 0x00, 0x10, 0x01,
+0x40, 0x04, 0x00, 0x13, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x07, 0x00, 0x11,
+0x84, 0x4C, 0x04, 0x52, 0x1D, 0x40, 0x55, 0x00, 0x11, 0x01, 0x54, 0x03, 0xB4,
+0x01, 0x40, 0x0D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33,
+0x00, 0x8D, 0x00, 0x04, 0x23, 0xD0, 0x0C, 0x60, 0x33, 0x01, 0xC1, 0x00, 0x44,
+0x83, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xDD, 0x00, 0x04, 0x03, 0x10, 0x0D, 0x48,
+0x34, 0x80, 0xC1, 0x00, 0x44, 0x03, 0x10, 0x0C, 0x40, 0x35, 0x00, 0xC1, 0x04,
+0x64, 0x03, 0x10, 0x04, 0x44, 0x16, 0x80, 0x59, 0x00, 0x66, 0x83, 0x5C, 0x00,
+0x44, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00,
+0x9D, 0x21, 0x44, 0x03, 0x91, 0x01, 0x60, 0x03, 0x00, 0x11, 0x00, 0x60, 0x00,
+0x10, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04,
+0x80, 0x19, 0x20, 0x44, 0x00, 0x10, 0x01, 0x40, 0x06, 0x00, 0x11, 0x00, 0x44,
+0x00, 0x50, 0x1D, 0x4C, 0x17, 0x04, 0x51, 0x10, 0x54, 0x0B, 0xDC, 0x11, 0x40,
+0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x00, 0x1F,
+0x33, 0x44, 0x03, 0xD0, 0x0D, 0xC0, 0x37, 0x10, 0xD3, 0x00, 0x4C, 0x03, 0x30,
+0x0D, 0xC0, 0x37, 0x00, 0xDD, 0x00, 0x4D, 0x03, 0x34, 0x0C, 0xC0, 0x30, 0x00,
+0xD3, 0x20, 0x0C, 0x03, 0x10, 0x0D, 0xC0, 0x31, 0x00, 0xD3, 0x00, 0x2C, 0x03,
+0xB0, 0x18, 0xC0, 0x92, 0x00, 0x9B, 0x01, 0x2C, 0x0B, 0x70, 0x59, 0xC2, 0x00,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x10, 0xAF, 0x00,
+0xFC, 0x03, 0x72, 0x03, 0xCB, 0x0F, 0x00, 0x3F, 0x00, 0xDC, 0x00, 0xF0, 0x03,
+0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC8, 0x0E, 0x04, 0x37,
+0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x04, 0x3F, 0x00, 0xFC, 0x00, 0xF0,
+0x0F, 0xC0, 0x8D, 0x10, 0xBF, 0x08, 0xFC, 0x23, 0xB0, 0x09, 0xC0, 0x3F, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x06, 0x1F, 0x00, 0x7C,
+0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xDF, 0x01, 0x7C, 0x43, 0xF0, 0x0D, 0xC0,
+0x34, 0x1B, 0xD3, 0x00, 0x4C, 0x47, 0x30, 0x1D, 0xC0, 0x77, 0x00, 0xD7, 0x01,
+0x7C, 0x47, 0xF0, 0x0D, 0xC0, 0x34, 0x02, 0xDF, 0x00, 0x4D, 0x43, 0x30, 0x0D,
+0xC0, 0x35, 0x00, 0x9F, 0x06, 0x4C, 0x0B, 0x30, 0x01, 0xC0, 0x29, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x74, 0x10, 0x9D, 0x08, 0xF4, 0x03,
+0xD1, 0x21, 0x40, 0x04, 0x00, 0x1D, 0x03, 0x1C, 0x00, 0xD0, 0x81, 0x40, 0xC4,
+0x00, 0x01, 0x00, 0x44, 0x0C, 0x12, 0x31, 0x40, 0x47, 0x00, 0x15, 0x03, 0x74,
+0x04, 0xD0, 0x21, 0x40, 0x44, 0x00, 0x1D, 0x0B, 0x46, 0x40, 0xB2, 0xAD, 0x48,
+0xC4, 0x22, 0x8B, 0x07, 0x6C, 0x0B, 0xA0, 0x91, 0xC0, 0x4C, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0xF2, 0x00, 0x0D, 0x09, 0x74, 0x17, 0xD0,
+0x0C, 0x40, 0x32, 0x00, 0xDD, 0x04, 0x34, 0x0B, 0xD0, 0x2C, 0x40, 0xF0, 0x00,
+0xC1, 0x0C, 0x54, 0x03, 0x14, 0x4C, 0x40, 0x33, 0x00, 0xD9, 0x04, 0x34, 0x0B,
+0xD0, 0x4C, 0x40, 0xB0, 0x20, 0xD9, 0x00, 0x04, 0x0B, 0x10, 0x24, 0x40, 0x53,
+0x00, 0xC1, 0x01, 0x24, 0x22, 0x90, 0x99, 0x40, 0x0F, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x00, 0x6D, 0x01, 0xB4, 0x47, 0xD8, 0x13,
+0x40, 0x4A, 0x00, 0x2D, 0x01, 0xB4, 0x04, 0xD0, 0x12, 0x40, 0x4C, 0x00, 0x21,
+0x01, 0xC4, 0x04, 0x10, 0x12, 0x40, 0x4F, 0x00, 0x2D, 0x08, 0xB4, 0x00, 0xD0,
+0x12, 0x40, 0x48, 0x00, 0x2D, 0x31, 0x84, 0x04, 0x90, 0x9F, 0x44, 0x5E, 0x08,
+0x79, 0x21, 0xA4, 0x0F, 0x90, 0x12, 0x48, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF, 0x00, 0x3C, 0x23, 0xF0, 0x0C, 0xC0,
+0x32, 0x00, 0xCF, 0x00, 0x3C, 0x03, 0xF0, 0x0D, 0xC0, 0x30, 0x00, 0xD3, 0x00,
+0x1C, 0x03, 0x30, 0x0C, 0xC0, 0x37, 0x80, 0xC9, 0x00, 0x3C, 0x03, 0xD0, 0x0D,
+0x40, 0x30, 0x00, 0xDD, 0x00, 0x04, 0x23, 0x30, 0x04, 0xC0, 0x13, 0x14, 0xC3,
+0x00, 0x4C, 0x23, 0xB0, 0x88, 0xC6, 0x4B, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x83, 0xF0, 0x02, 0xC0, 0x0D,
+0x00, 0x3F, 0x00, 0xDC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x02, 0x3F, 0x08, 0x7C,
+0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x36, 0x08, 0xFC, 0x10, 0xF0, 0x01, 0x80,
+0x0F, 0x00, 0x3E, 0x00, 0xBC, 0x84, 0xF9, 0x0F, 0xC8, 0x19, 0x00, 0x7F, 0x00,
+0xFC, 0x23, 0xF0, 0x03, 0xC8, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0x37, 0x10, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00,
+0xDF, 0x00, 0x7C, 0x07, 0x34, 0x1D, 0xD0, 0x30, 0x00, 0xD3, 0x01, 0x4D, 0x03,
+0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x70, 0x1D, 0xD0, 0x34,
+0x00, 0xD7, 0x00, 0x4C, 0x03, 0xF0, 0x1C, 0xD0, 0x54, 0x00, 0xD3, 0x00, 0x4C,
+0x03, 0xD1, 0x09, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x88, 0x39, 0x00, 0x6D, 0x00, 0xB4, 0x2B, 0xD0, 0x02, 0x40, 0x0B, 0x00, 0x2D,
+0x00, 0xF4, 0x00, 0x10, 0x03, 0x40, 0x08, 0x00, 0x31, 0x00, 0x84, 0x00, 0xD0,
+0x02, 0x40, 0x0B, 0x00, 0x2D, 0x00, 0xB4, 0x00, 0xD0, 0x03, 0x40, 0x08, 0x10,
+0x2D, 0x00, 0xA4, 0x00, 0xD0, 0x0E, 0x40, 0x18, 0x40, 0xE1, 0x00, 0x94, 0x03,
+0xD0, 0x0E, 0x40, 0x4F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+0x79, 0x00, 0xED, 0x03, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01,
+0xB4, 0x07, 0x10, 0x1E, 0x40, 0x7C, 0x00, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x1E,
+0x40, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x78, 0x00, 0xED,
+0x01, 0xA5, 0x07, 0xD0, 0x1F, 0x49, 0x58, 0x80, 0xF5, 0x01, 0x84, 0x07, 0xD0,
+0x1E, 0x42, 0x13, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33,
+0x00, 0xDD, 0x01, 0x34, 0x03, 0xD0, 0x01, 0x40, 0x03, 0x00, 0x0D, 0x00, 0x34,
+0x00, 0x10, 0x00, 0x40, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0xD0, 0x00, 0x44,
+0x07, 0x00, 0x0D, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x40, 0x00, 0x00, 0x0D, 0x00,
+0x24, 0x00, 0xD0, 0x5C, 0x44, 0xD0, 0x01, 0xC5, 0x13, 0x14, 0x4F, 0xD8, 0x5D,
+0x40, 0x5B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00,
+0x7F, 0x02, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x01,
+0x30, 0x05, 0xC0, 0x14, 0x50, 0x53, 0x00, 0x4C, 0x01, 0xF0, 0x05, 0xC0, 0x17,
+0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x14, 0x00, 0x5F, 0x00, 0x44,
+0x01, 0xD0, 0x27, 0xC0, 0xDC, 0x00, 0x67, 0x07, 0x8C, 0x01, 0xF0, 0x57, 0x44,
+0x5F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x87, 0x00, 0x1F,
+0x12, 0x7C, 0x00, 0xF2, 0x23, 0xC0, 0x0F, 0x00, 0x3F, 0x02, 0xFC, 0x00, 0xF0,
+0x03, 0xC8, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x23, 0xC0, 0x0F, 0x00,
+0x3F, 0x02, 0xFC, 0x80, 0xF3, 0x23, 0xC0, 0x8F, 0x00, 0x3F, 0x22, 0xDC, 0x00,
+0xF0, 0x01, 0xC0, 0x07, 0x02, 0x1B, 0x00, 0x7C, 0x20, 0xF0, 0x21, 0xC0, 0x4B,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x9F, 0x05,
+0x4C, 0x06, 0xF0, 0x99, 0xC0, 0x24, 0x00, 0x93, 0x05, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x67, 0x40, 0x93, 0x00, 0x7C, 0x02, 0xF0, 0x39, 0xC0, 0x67, 0x40, 0x93,
+0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x03, 0x4C, 0x22, 0xF0,
+0x49, 0xE0, 0xA7, 0x00, 0x9F, 0x00, 0x5E, 0x0A, 0x30, 0x09, 0xC0, 0x40, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xA6, 0x04, 0x9D, 0x12, 0x44,
+0x02, 0xD0, 0x29, 0x41, 0x20, 0x00, 0x91, 0x00, 0x74, 0x0E, 0xD0, 0x19, 0x41,
+0x27, 0x00, 0x91, 0x03, 0x74, 0x02, 0xD0, 0x19, 0x40, 0x67, 0x00, 0x91, 0x02,
+0x74, 0x02, 0xD8, 0x39, 0x40, 0x27, 0x01, 0x9D, 0x00, 0x45, 0x86, 0xD0, 0x39,
+0x40, 0x67, 0x14, 0x97, 0x0A, 0x44, 0x0A, 0x56, 0x49, 0x40, 0x04, 0x08, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x02, 0x9D, 0x00, 0x64, 0x2A,
+0xD0, 0x09, 0x40, 0x2C, 0x08, 0xB1, 0x00, 0xF4, 0x0E, 0xD0, 0x1B, 0x40, 0xAF,
+0x02, 0xB1, 0x03, 0xF4, 0x02, 0xD0, 0x0B, 0x40, 0x2F, 0x02, 0xB1, 0x02, 0xF4,
+0x0A, 0xD1, 0x1B, 0x41, 0x2F, 0x01, 0xA9, 0x00, 0xC6, 0x02, 0x91, 0x09, 0x40,
+0x25, 0x00, 0x9D, 0x42, 0x54, 0x02, 0x15, 0x49, 0x40, 0x60, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x8D, 0x14, 0x25, 0x12, 0xD0,
+0x0A, 0x40, 0x2C, 0x00, 0xE1, 0x80, 0xB4, 0x02, 0xD0, 0x0A, 0x4A, 0x2B, 0x00,
+0xA1, 0x00, 0xB4, 0x06, 0xD0, 0x0E, 0x40, 0x6B, 0x00, 0xA1, 0x00, 0xB4, 0x02,
+0xD2, 0x0A, 0x40, 0x2B, 0x00, 0xED, 0x08, 0x84, 0x02, 0xD2, 0x0C, 0x4A, 0x23,
+0x00, 0x95, 0x00, 0x64, 0x06, 0x58, 0x48, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x04, 0x6C, 0x28, 0xF0, 0xA1,
+0xC8, 0x84, 0x42, 0x13, 0x0A, 0x7C, 0x28, 0xF0, 0xA1, 0xC0, 0x87, 0x02, 0x13,
+0x0A, 0x7C, 0x28, 0xF0, 0xA1, 0xC0, 0x87, 0x02, 0x13, 0x0A, 0x7C, 0x28, 0xD0,
+0xA1, 0xC0, 0x87, 0x02, 0x0F, 0x82, 0xCC, 0x01, 0xF8, 0x01, 0xCA, 0x05, 0x00,
+0x1F, 0x00, 0x5C, 0x28, 0x30, 0xA1, 0xC0, 0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0xB8, 0x27, 0x05, 0xBF, 0x14, 0x5C, 0x22, 0xF0, 0x09, 0xD0,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC8, 0x27, 0x20, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x20, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0x04, 0x7C, 0x02, 0xE0, 0x0B, 0xC0, 0x2B, 0x00, 0xA7,
+0x40, 0xDC, 0x02, 0xF0, 0x8B, 0xD4, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x80, 0x2F, 0x00, 0xBF, 0x14, 0xFC, 0x32, 0x30, 0x0A, 0xC0, 0x24,
+0x00, 0xAF, 0x08, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x2F, 0x02, 0xB3, 0x00, 0xFC,
+0x02, 0xF0, 0x8B, 0xC8, 0x2F, 0x08, 0xBF, 0x00, 0xFC, 0x22, 0x70, 0x0B, 0xC0,
+0x2F, 0x00, 0xB3, 0x28, 0xCE, 0x02, 0xF0, 0x0A, 0xC0, 0x2E, 0x00, 0xB3, 0x00,
+0xFC, 0x02, 0xC1, 0x0B, 0xC2, 0x74, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0x00, 0x07, 0x05, 0x1D, 0x04, 0x74, 0x30, 0x10, 0x01, 0x41, 0x04, 0x04,
+0x1D, 0x20, 0x74, 0x50, 0xD0, 0x41, 0x4C, 0x07, 0x01, 0x11, 0x10, 0x74, 0x40,
+0xD0, 0x01, 0x40, 0x07, 0x05, 0x1D, 0x04, 0x74, 0x10, 0xD0, 0x01, 0x41, 0x07,
+0x04, 0x01, 0x00, 0x44, 0x00, 0xD0, 0x01, 0xC0, 0x16, 0x00, 0x1B, 0x00, 0x74,
+0x00, 0xD0, 0x01, 0x40, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA2, 0x23, 0x21, 0x8D, 0x14, 0x34, 0x12, 0x10, 0x48, 0x40, 0x20, 0x00, 0x8D,
+0x00, 0x34, 0x12, 0xD0, 0x48, 0x41, 0x23, 0x01, 0x81, 0x04, 0x34, 0x02, 0xD0,
+0x08, 0x40, 0x23, 0x01, 0x8D, 0x14, 0x34, 0x12, 0x50, 0x48, 0x40, 0x27, 0x00,
+0x85, 0x00, 0x05, 0x02, 0xD0, 0x08, 0x44, 0x24, 0x00, 0x85, 0x40, 0x34, 0x82,
+0xD1, 0x08, 0x40, 0x48, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8,
+0x25, 0x00, 0x9D, 0x02, 0x74, 0x02, 0x12, 0x09, 0x50, 0x24, 0x20, 0x9D, 0x00,
+0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x40, 0x99, 0x00, 0x74, 0x02, 0xD0, 0x09,
+0x40, 0x27, 0x00, 0xDD, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x20, 0x91,
+0x00, 0x64, 0x82, 0xD1, 0x19, 0x40, 0x26, 0x00, 0x9D, 0x01, 0x74, 0x0A, 0xD8,
+0x09, 0x40, 0x60, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x88, 0x27,
+0x00, 0x9D, 0x01, 0x7C, 0x02, 0x34, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF1, 0x09, 0xC0, 0x27, 0x20, 0x93, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0x40,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x00, 0x93, 0x00,
+0x4C, 0x02, 0xF0, 0x09, 0x80, 0x20, 0x00, 0x97, 0x00, 0x7C, 0x06, 0xF0, 0x49,
+0xCA, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x00,
+0x9F, 0x08, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x40, 0x7C, 0x02,
+0xF0, 0x09, 0xC8, 0x27, 0x00, 0x97, 0x00, 0x7C, 0x02, 0xF1, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC6, 0x27, 0x50, 0x9F, 0x80, 0x5C,
+0x02, 0xF0, 0x09, 0xC0, 0x27, 0x20, 0x9B, 0x00, 0x7E, 0x12, 0xF0, 0x49, 0xD1,
+0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F,
+0x04, 0x3C, 0x40, 0x30, 0x01, 0xD0, 0x06, 0x00, 0x13, 0x00, 0x4D, 0x00, 0xF0,
+0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x11, 0xC0, 0x06, 0x00,
+0x1F, 0x01, 0x7C, 0x20, 0xF0, 0x91, 0xC0, 0x07, 0x04, 0x13, 0x80, 0x7C, 0x40,
+0xF0, 0x11, 0xC4, 0x84, 0x04, 0x1F, 0x10, 0x5C, 0x48, 0xF0, 0x21, 0xC0, 0x53,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x9C, 0x00, 0x7D, 0x12,
+0xF4, 0x01, 0x12, 0x17, 0xC0, 0x14, 0x20, 0x71, 0x0A, 0xEC, 0x01, 0xD0, 0x87,
+0x48, 0x9F, 0x80, 0x7D, 0x00, 0xF4, 0x6D, 0xD0, 0x07, 0xC0, 0x1E, 0x00, 0x7D,
+0x00, 0xF4, 0x29, 0x70, 0x07, 0xC0, 0x99, 0x00, 0x71, 0x81, 0xCC, 0x0D, 0xD1,
+0x16, 0x44, 0x1C, 0x20, 0x7D, 0x02, 0xC4, 0x15, 0xC0, 0x27, 0x40, 0x43, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xF2, 0x03, 0xCD, 0x01, 0x34,
+0x03, 0x10, 0x9D, 0x41, 0x30, 0x00, 0xC1, 0x02, 0x04, 0x13, 0xD0, 0x2C, 0x48,
+0xB7, 0x01, 0xCD, 0x10, 0x34, 0x0B, 0xD0, 0x0C, 0x42, 0x30, 0x01, 0xCD, 0x00,
+0x34, 0x07, 0xD0, 0x1C, 0x40, 0x31, 0x00, 0xD1, 0x08, 0x14, 0x09, 0xD8, 0x9C,
+0x40, 0x31, 0x10, 0x0D, 0x01, 0x14, 0x0F, 0xD0, 0x8D, 0x40, 0x43, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x00, 0xED, 0x00, 0x34, 0x01,
+0x10, 0x0F, 0x40, 0x78, 0x41, 0xF1, 0x01, 0x84, 0x43, 0xD0, 0x0E, 0x41, 0x3B,
+0x10, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x1E, 0x60, 0x38, 0x00, 0xED, 0x10, 0xB4,
+0x01, 0x50, 0x0E, 0x42, 0x39, 0x40, 0x21, 0x00, 0xA4, 0x08, 0xD0, 0x0E, 0x40,
+0x29, 0x00, 0x7D, 0x11, 0x84, 0x01, 0xD0, 0x06, 0x40, 0x13, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x58, 0x08, 0xEF, 0x01, 0xBC, 0x07, 0x30,
+0x1E, 0xC0, 0x7C, 0x05, 0xE3, 0x01, 0x84, 0x07, 0xF0, 0x16, 0xC0, 0x7B, 0x00,
+0xED, 0x01, 0xB4, 0x05, 0xF0, 0x1F, 0x40, 0x58, 0x00, 0xEF, 0x01, 0xBC, 0x07,
+0xF0, 0x1E, 0xC0, 0x7D, 0x00, 0xE3, 0x01, 0x9C, 0x05, 0xF0, 0x0E, 0xC0, 0x69,
+0x10, 0x2F, 0x01, 0x9C, 0x05, 0xF2, 0x1E, 0xC4, 0x53, 0x60, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xBA, 0x15, 0x00, 0xDF, 0x20, 0x7C, 0x02, 0xF4, 0x0D,
+0xC8, 0x35, 0x23, 0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x07, 0x00, 0x9F,
+0x00, 0x7C, 0x01, 0xF0, 0x09, 0xD8, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC4, 0x25, 0x80, 0xDF, 0x00, 0x5C, 0x00, 0xF2, 0x0D, 0xC0, 0x26, 0x00,
+0x8F, 0x20, 0x7C, 0x00, 0xF2, 0x01, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA0, 0x7D, 0x00, 0xFF, 0x01, 0xFC, 0x87, 0xF9, 0x0F, 0xC0,
+0x7D, 0x00, 0xFF, 0x01, 0xFC, 0x25, 0xF0, 0x1E, 0xC0, 0x7C, 0x00, 0xFF, 0x09,
+0xDC, 0x07, 0xF0, 0x17, 0xC0, 0x7F, 0x0A, 0x7F, 0x81, 0xCC, 0x87, 0xF0, 0x17,
+0xC0, 0x5F, 0x22, 0xF3, 0x01, 0xCC, 0x25, 0x30, 0x1A, 0xC0, 0x78, 0x02, 0x23,
+0x01, 0xCC, 0x06, 0xF0, 0x9B, 0xC0, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x88, 0x39, 0x22, 0x6D, 0x00, 0xB4, 0x19, 0xD8, 0x46, 0x40, 0x3B,
+0x05, 0xED, 0x04, 0xB4, 0x83, 0xD0, 0x8E, 0x40, 0x38, 0x00, 0x6D, 0x00, 0xB4,
+0x88, 0xD0, 0x2E, 0x40, 0x3B, 0x00, 0xAD, 0x18, 0x85, 0x0A, 0xD0, 0xAE, 0x40,
+0x1F, 0x03, 0x21, 0x84, 0xC4, 0x01, 0xB0, 0x4A, 0x40, 0xA8, 0x02, 0x2F, 0x00,
+0x94, 0x02, 0xD0, 0x8A, 0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0x00, 0xED, 0x00, 0xB4, 0x81, 0xD0, 0x8A, 0x41, 0x39, 0x20,
+0x6D, 0x90, 0xB4, 0x08, 0xD1, 0x23, 0x40, 0x38, 0x00, 0xED, 0x20, 0x96, 0x23,
+0xD0, 0x0E, 0x40, 0x1B, 0x10, 0xFD, 0x00, 0x84, 0x03, 0xD0, 0x22, 0x40, 0x3B,
+0x60, 0xB1, 0x00, 0xD6, 0x01, 0x11, 0x0E, 0x48, 0x28, 0x00, 0x25, 0x0A, 0x84,
+0x40, 0xD0, 0x8A, 0x41, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x28, 0x05, 0x00, 0x8D, 0x03, 0x74, 0x00, 0xD0, 0x30, 0x44, 0xF3, 0x00, 0x1D,
+0x03, 0x74, 0x02, 0xD0, 0x08, 0x40, 0xC0, 0x00, 0x0D, 0x02, 0x74, 0x0C, 0xD0,
+0x39, 0x00, 0xE7, 0x00, 0x9D, 0x02, 0x44, 0x0E, 0xD0, 0x08, 0x40, 0xE3, 0x00,
+0x81, 0x02, 0x14, 0x08, 0x90, 0x1C, 0x44, 0x20, 0x04, 0x0D, 0x00, 0x56, 0x0C,
+0xD0, 0x28, 0x41, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x28,
+0x25, 0x00, 0x1F, 0x06, 0x7E, 0x02, 0xD8, 0x91, 0xC8, 0xB9, 0x00, 0x1F, 0x01,
+0x7C, 0x16, 0xF0, 0x59, 0xC0, 0x84, 0x04, 0x1D, 0x07, 0x5C, 0x06, 0xF0, 0x19,
+0xC0, 0x27, 0x04, 0x9F, 0x01, 0x4C, 0x06, 0xF0, 0x58, 0xC0, 0x67, 0x02, 0xC3,
+0x00, 0x1C, 0x4D, 0x10, 0x8C, 0xD0, 0xE0, 0x01, 0x17, 0x00, 0x4C, 0x0E, 0xF0,
+0x01, 0xC0, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27,
+0x00, 0x9F, 0x02, 0x7C, 0x82, 0xF0, 0x21, 0xC0, 0x37, 0x00, 0x9F, 0x10, 0x7C,
+0x0A, 0xF0, 0x09, 0xC0, 0x07, 0x08, 0x1F, 0x02, 0x7C, 0x6A, 0xF0, 0x89, 0xC1,
+0xA7, 0x04, 0x9F, 0x10, 0x7C, 0x60, 0xF0, 0x09, 0xC8, 0x87, 0x02, 0x1F, 0x23,
+0x6C, 0x00, 0xF0, 0x8D, 0xC2, 0x27, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x2D, 0x00,
+0x33, 0x10, 0xFC, 0x02, 0x30, 0x0B, 0xE2, 0x3F, 0x04, 0xB3, 0x00, 0xCC, 0x00,
+0x38, 0x0B, 0xC0, 0x2F, 0x04, 0xBF, 0x10, 0xFC, 0x02, 0x30, 0x03, 0xC2, 0x2C,
+0x80, 0x33, 0x00, 0xCC, 0x00, 0x34, 0x03, 0xC0, 0x2C, 0x00, 0x7F, 0x10, 0xCC,
+0x41, 0x31, 0x0F, 0xC0, 0x2D, 0x10, 0x33, 0x00, 0xFC, 0x42, 0x30, 0x0A, 0xC0,
+0x04, 0x24, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xE6, 0x00, 0x91,
+0x05, 0x74, 0x06, 0x12, 0x39, 0x40, 0x37, 0x00, 0x91, 0x81, 0x44, 0x04, 0xB8,
+0x19, 0x44, 0x47, 0x30, 0x9D, 0x43, 0x5C, 0x0E, 0x10, 0x31, 0x40, 0x65, 0x00,
+0x1F, 0x01, 0x44, 0x0C, 0x10, 0x11, 0x40, 0x44, 0x01, 0x5D, 0x02, 0x4C, 0x0C,
+0x70, 0x3D, 0x40, 0xE4, 0x00, 0x95, 0x01, 0x74, 0x0C, 0x12, 0x71, 0x40, 0x04,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xC4, 0x40, 0x11, 0x01,
+0x74, 0x06, 0x14, 0x39, 0x44, 0x37, 0x00, 0x11, 0x03, 0x44, 0x46, 0x1A, 0x11,
+0x41, 0x67, 0x00, 0x9D, 0x43, 0x74, 0x06, 0x10, 0x11, 0x40, 0x44, 0x04, 0x11,
+0x01, 0x44, 0x06, 0x10, 0x19, 0x64, 0x66, 0x00, 0xDD, 0x02, 0x44, 0x45, 0x10,
+0xA5, 0x40, 0x66, 0x20, 0x19, 0x81, 0x74, 0x0E, 0x11, 0x11, 0x54, 0x04, 0x08,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x01, 0x00, 0x34,
+0x02, 0x10, 0x00, 0x68, 0x37, 0x00, 0x81, 0x00, 0x05, 0x02, 0x10, 0x00, 0x40,
+0x63, 0x00, 0x0D, 0x00, 0x16, 0x00, 0x14, 0x08, 0x50, 0x00, 0x40, 0x81, 0x00,
+0x05, 0x02, 0x1C, 0x09, 0x64, 0x02, 0x00, 0x1D, 0x00, 0x45, 0x00, 0x94, 0x0D,
+0x40, 0x02, 0x00, 0x0D, 0x00, 0x34, 0x02, 0x10, 0x00, 0x40, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x06, 0x00, 0x11, 0x00, 0x7C, 0x00,
+0x30, 0x09, 0x60, 0x3F, 0x40, 0x13, 0x00, 0x4C, 0x00, 0x14, 0x01, 0xC0, 0x27,
+0x20, 0x9F, 0x00, 0x7E, 0x82, 0x30, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x4C,
+0x00, 0x30, 0x01, 0xC0, 0x26, 0x00, 0x1F, 0x00, 0x4C, 0x03, 0x30, 0x0D, 0xD0,
+0x27, 0x08, 0x1B, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xD0, 0x04, 0x64, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x2F, 0x00, 0xBF, 0x00, 0xFC, 0x00, 0xF1,
+0x03, 0xC2, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x80, 0xF0, 0x03, 0xC0, 0x0F, 0x00,
+0x3F, 0x00, 0xDC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x08, 0x2F, 0x00, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x0D, 0x00, 0x2F, 0x40, 0xCC, 0x00, 0x59, 0x0F, 0xC8, 0x2D,
+0x00, 0x37, 0x80, 0xFC, 0x02, 0xF4, 0x0B, 0xC8, 0x17, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA0, 0x0F, 0x00, 0x3F, 0x41, 0xEC, 0x02, 0xF0, 0x0F,
+0xC0, 0x2C, 0x00, 0xBF, 0x00, 0xBE, 0x07, 0xF0, 0x03, 0xC1, 0x3E, 0x00, 0xA3,
+0x01, 0xDC, 0x00, 0x30, 0x03, 0xC0, 0x0F, 0x00, 0xAC, 0x01, 0xDC, 0x33, 0x34,
+0x3F, 0xC0, 0x2F, 0x80, 0xA3, 0x01, 0xFC, 0x53, 0xF0, 0x83, 0xC0, 0x4F, 0x00,
+0x33, 0x01, 0xBC, 0x0C, 0x30, 0x13, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x08, 0x27, 0x12, 0x1D, 0x00, 0x44, 0x02, 0xD0, 0x0F, 0x44,
+0x04, 0x14, 0x1D, 0x00, 0x55, 0x07, 0xD0, 0x21, 0x50, 0x3C, 0x00, 0x91, 0x41,
+0x44, 0x02, 0x10, 0x01, 0x40, 0x27, 0x20, 0x9D, 0x11, 0x54, 0x3B, 0x10, 0x4D,
+0x40, 0x27, 0x20, 0x91, 0x10, 0x74, 0x0F, 0xD2, 0x0B, 0x40, 0x07, 0x08, 0x11,
+0x80, 0x74, 0x00, 0x14, 0x05, 0x40, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x03, 0x00, 0x0D, 0x00, 0x05, 0x00, 0xD0, 0x0C, 0x40, 0x20,
+0x08, 0x8D, 0x00, 0x35, 0x02, 0x50, 0x00, 0x40, 0x31, 0x00, 0xC1, 0x00, 0x14,
+0x02, 0x10, 0x08, 0x44, 0x03, 0x00, 0x9D, 0x00, 0x14, 0x03, 0x90, 0x0C, 0x60,
+0x23, 0x00, 0x81, 0x04, 0x34, 0x03, 0xD0, 0x58, 0x48, 0x23, 0x15, 0x81, 0x14,
+0x34, 0x10, 0x10, 0x00, 0x40, 0x47, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x88, 0x65, 0x10, 0x1D, 0x03, 0x44, 0x0C, 0xD0, 0x0D, 0x40, 0x44, 0x00,
+0x1D, 0x01, 0x54, 0x12, 0xD0, 0x00, 0x40, 0x35, 0x00, 0xD1, 0x00, 0x44, 0x06,
+0x14, 0x19, 0x40, 0x47, 0x14, 0x9D, 0x00, 0x54, 0x03, 0x90, 0x0D, 0x40, 0x27,
+0x42, 0x91, 0x20, 0x74, 0x03, 0xD0, 0x1D, 0x40, 0x23, 0x00, 0x91, 0x00, 0x74,
+0x04, 0x10, 0x05, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x88, 0x47, 0x04, 0x1F, 0x01, 0x4C, 0x8E, 0xF1, 0x0D, 0xC8, 0x64, 0x20, 0x0F,
+0x43, 0x7D, 0x07, 0x70, 0x55, 0xC0, 0x35, 0x40, 0xC3, 0x00, 0x5C, 0x14, 0x30,
+0x59, 0xC0, 0xE7, 0x00, 0x8E, 0x00, 0x5C, 0x03, 0xB0, 0x0D, 0xC0, 0x37, 0x20,
+0xD1, 0x20, 0x7C, 0x03, 0xF2, 0x19, 0xC2, 0x47, 0x00, 0x13, 0x81, 0x3C, 0x02,
+0x34, 0x01, 0xC0, 0x0B, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80,
+0x2D, 0x08, 0x3F, 0x00, 0xFC, 0x42, 0xF0, 0x0E, 0xC0, 0x2F, 0x00, 0x3F, 0x00,
+0xFC, 0x03, 0xF0, 0x87, 0xC0, 0x38, 0x00, 0xFF, 0x00, 0xBC, 0x42, 0xF0, 0x0B,
+0xC1, 0x2F, 0x00, 0xBF, 0x04, 0xBC, 0x03, 0x70, 0x0F, 0xC0, 0x7B, 0x20, 0xBF,
+0x00, 0xFC, 0x03, 0xD0, 0x09, 0xC0, 0x4F, 0x02, 0x3F, 0x09, 0xFC, 0x02, 0xF0,
+0x07, 0xC1, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x05,
+0x00, 0x13, 0x02, 0x5D, 0x0A, 0xF0, 0x0D, 0xC0, 0x24, 0x00, 0x93, 0x00, 0x7C,
+0x82, 0x30, 0x27, 0xC0, 0x34, 0x44, 0xD3, 0x00, 0x6C, 0x02, 0xF0, 0x09, 0xC6,
+0x87, 0x04, 0x9F, 0x00, 0x5C, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xD3, 0x20,
+0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x64, 0x00, 0x93, 0x01, 0x7C, 0x02, 0x30, 0x01,
+0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x24, 0x00,
+0x01, 0x00, 0x44, 0x06, 0xD0, 0x2F, 0xC5, 0x26, 0x00, 0x9B, 0x20, 0x74, 0x02,
+0xB0, 0x45, 0x40, 0x7C, 0x40, 0xD1, 0x01, 0x6C, 0x02, 0xD0, 0x29, 0x40, 0x87,
+0x00, 0x9D, 0x00, 0xC4, 0x03, 0x12, 0x0D, 0x40, 0xB7, 0x06, 0x91, 0x0A, 0xC4,
+0x03, 0xD0, 0x0D, 0x50, 0xE4, 0x00, 0x91, 0x03, 0x74, 0x42, 0x10, 0x05, 0x40,
+0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x22, 0x80, 0x01,
+0x12, 0x04, 0x20, 0xD0, 0x3C, 0x41, 0x00, 0x00, 0x81, 0x09, 0x24, 0x03, 0x10,
+0x00, 0x40, 0x30, 0x20, 0x8D, 0x13, 0x24, 0x08, 0x90, 0x20, 0x40, 0x83, 0x00,
+0xCD, 0x00, 0x14, 0x03, 0x50, 0x0C, 0x00, 0x23, 0x00, 0x81, 0x02, 0x04, 0x03,
+0xC0, 0x08, 0x40, 0x90, 0x14, 0x41, 0x12, 0x34, 0x85, 0x10, 0x08, 0x40, 0x1F,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x68, 0x40, 0x21, 0x01,
+0x84, 0x07, 0xD0, 0x1C, 0x40, 0x5A, 0x00, 0xE9, 0x01, 0xF4, 0x07, 0x90, 0x10,
+0x54, 0x70, 0x26, 0xAD, 0x91, 0xA4, 0x05, 0xD0, 0x12, 0x08, 0x6B, 0x02, 0xFD,
+0x01, 0x84, 0x07, 0x10, 0x1E, 0x40, 0x6B, 0x00, 0xB5, 0x01, 0x84, 0x07, 0xD0,
+0x9A, 0x40, 0x58, 0x02, 0x61, 0x81, 0xF4, 0x0D, 0x12, 0x9E, 0x40, 0x13, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x24, 0x02, 0x11, 0x00, 0x1D,
+0x21, 0xF0, 0x0C, 0x40, 0xB4, 0x00, 0xC3, 0x02, 0x3C, 0x03, 0x30, 0x40, 0xC0,
+0x30, 0x02, 0xCF, 0x00, 0x2C, 0x00, 0xB3, 0x84, 0xC0, 0x13, 0x8A, 0xCF, 0x00,
+0x5C, 0x03, 0x70, 0x0C, 0xC0, 0x27, 0x40, 0x83, 0x08, 0x0C, 0x03, 0xF0, 0x0C,
+0xC0, 0x34, 0x02, 0xC3, 0x04, 0x3C, 0x01, 0x30, 0x08, 0xC0, 0x4B, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x2D, 0x00, 0x7F, 0x88, 0xFC, 0x01,
+0xC0, 0x0F, 0xC1, 0x1D, 0x00, 0xFF, 0x00, 0xFC, 0x23, 0xF0, 0x03, 0xC0, 0xBF,
+0x06, 0xF3, 0x08, 0xFC, 0x21, 0xF0, 0x8F, 0xC8, 0x3F, 0xA2, 0xFF, 0x08, 0xFC,
+0x23, 0xF0, 0x0F, 0xC0, 0x3E, 0x02, 0xBB, 0x20, 0xFD, 0x43, 0xF0, 0x0F, 0xC0,
+0x3F, 0x02, 0xFF, 0x00, 0xFC, 0x01, 0xF0, 0x0F, 0xC2, 0x0B, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x2F, 0x00, 0x0F, 0x00, 0x4C, 0x01, 0xF0,
+0x4D, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x03, 0xF8, 0x01, 0xC0, 0xB6, 0x40,
+0xD3, 0x01, 0x7C, 0x81, 0xF2, 0x05, 0xC8, 0x77, 0x00, 0x93, 0x00, 0x6C, 0x23,
+0x30, 0x0D, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x7C, 0x03, 0xF0, 0x29, 0xC0, 0x54,
+0x00, 0x53, 0x00, 0x4C, 0x03, 0xF0, 0x09, 0xC0, 0x56, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0x88, 0x29, 0x00, 0x2D, 0x00, 0x84, 0x03, 0xD0, 0x0E,
+0x41, 0x3B, 0x00, 0x6D, 0x00, 0xB4, 0x03, 0xD0, 0x03, 0x50, 0x38, 0x01, 0xE1,
+0x00, 0x84, 0x03, 0xD1, 0x0E, 0x40, 0x3F, 0x00, 0xA1, 0x00, 0x94, 0x83, 0x10,
+0x0E, 0x40, 0x3B, 0x00, 0xA1, 0x00, 0xB6, 0x13, 0xD0, 0x8A, 0x40, 0x19, 0x00,
+0x61, 0x00, 0x84, 0x03, 0xD2, 0x0E, 0x40, 0x48, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0x3D, 0x01, 0x84, 0x0F, 0xD1, 0x5E, 0x40,
+0x7B, 0x00, 0xED, 0x81, 0xB4, 0x07, 0xD2, 0x12, 0x40, 0x71, 0x00, 0xE1, 0x11,
+0x94, 0x07, 0xD0, 0x16, 0x40, 0x7B, 0x00, 0xB9, 0x43, 0x24, 0x07, 0x50, 0x1E,
+0x40, 0x73, 0x00, 0xED, 0x01, 0xB4, 0x17, 0xD0, 0x1C, 0x41, 0x78, 0x00, 0xE1,
+0x01, 0x84, 0x07, 0xD0, 0x1A, 0x40, 0x0E, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x28, 0x73, 0x10, 0xCD, 0x40, 0x04, 0x0F, 0xD0, 0x0C, 0x40, 0xB3,
+0x00, 0xCD, 0x02, 0x34, 0x03, 0xD0, 0x69, 0x40, 0x37, 0x00, 0xC1, 0x00, 0x06,
+0x27, 0xD0, 0x9D, 0x40, 0x33, 0x00, 0x99, 0x00, 0x14, 0x03, 0x10, 0x0D, 0x40,
+0x77, 0x02, 0x89, 0x08, 0x34, 0x03, 0xD0, 0x6D, 0x42, 0x31, 0x00, 0xD1, 0x00,
+0x44, 0x03, 0xD0, 0x0C, 0x50, 0x48, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x17, 0xA8, 0x5D, 0x01, 0x7F, 0x02, 0xCD, 0x05, 0xF0, 0x05, 0xC0, 0x5F, 0x04,
+0x7D, 0x0B, 0x7C, 0x81, 0xF0, 0x37, 0xC0, 0x15, 0x00, 0x53, 0x00, 0xDC, 0x09,
+0xF0, 0xA7, 0xC0, 0x1F, 0x41, 0x5B, 0x00, 0x6C, 0x01, 0x34, 0x05, 0xC0, 0x17,
+0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x37, 0xE0, 0x14, 0x40, 0x53, 0x00, 0x4D,
+0x01, 0xF0, 0x05, 0xC0, 0x5E, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x00, 0x07, 0x00, 0x1F, 0x12, 0x7C, 0x00, 0xF0, 0x01, 0xCC, 0x07, 0x00, 0x1F,
+0x0A, 0x7C, 0x00, 0xF8, 0x81, 0x40, 0x04, 0x10, 0x1F, 0x02, 0x5C, 0x48, 0xF8,
+0x21, 0xC2, 0x07, 0x01, 0x17, 0x00, 0x7C, 0x00, 0xF1, 0x01, 0xC0, 0x87, 0x40,
+0x17, 0x00, 0x7C, 0x80, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x04,
+0xF0, 0x01, 0xC8, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08,
+0x23, 0x00, 0x9B, 0x00, 0x4E, 0x62, 0xF0, 0x19, 0xC0, 0x27, 0x04, 0x87, 0x04,
+0x4C, 0x82, 0xF0, 0x09, 0xC4, 0x24, 0x10, 0x93, 0x40, 0x7C, 0x02, 0xF2, 0x09,
+0xC0, 0x24, 0x00, 0x9E, 0x80, 0x2C, 0x02, 0x70, 0x09, 0xC0, 0x64, 0x08, 0x93,
+0x05, 0x78, 0x06, 0xF0, 0x09, 0x40, 0x26, 0x00, 0x9F, 0x01, 0x4C, 0x02, 0x30,
+0x39, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26,
+0x00, 0x81, 0x04, 0x44, 0x0A, 0xD0, 0x19, 0x40, 0x27, 0x00, 0x9D, 0x10, 0x44,
+0x02, 0xD0, 0x09, 0xC0, 0x26, 0x40, 0x91, 0x01, 0x74, 0x16, 0xD0, 0x19, 0x40,
+0xA4, 0x00, 0x9D, 0x80, 0x4C, 0x82, 0x10, 0x09, 0x40, 0x24, 0x41, 0x91, 0x01,
+0x74, 0x06, 0xD2, 0x09, 0x40, 0xA4, 0x20, 0x9D, 0x03, 0x44, 0x02, 0x12, 0x08,
+0x40, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x08,
+0x99, 0x00, 0x44, 0x8A, 0xD0, 0x69, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x82,
+0x50, 0x09, 0x40, 0x24, 0x02, 0x99, 0x21, 0x56, 0x12, 0x90, 0x69, 0x42, 0x24,
+0x86, 0x9D, 0x00, 0x64, 0x02, 0x50, 0x09, 0x40, 0x24, 0x02, 0x91, 0x00, 0x74,
+0x22, 0xD0, 0x09, 0x40, 0x67, 0x00, 0xBD, 0x04, 0xC4, 0x02, 0x1C, 0x0F, 0x40,
+0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x01, 0x91,
+0x00, 0x04, 0x82, 0xD0, 0x68, 0x40, 0x23, 0x00, 0x8D, 0x02, 0x04, 0x02, 0xD2,
+0x48, 0x40, 0x30, 0x01, 0xC9, 0x00, 0x34, 0x1A, 0xD8, 0x08, 0x41, 0x20, 0x80,
+0x8D, 0x00, 0x04, 0x22, 0x10, 0x08, 0x50, 0x20, 0x01, 0x81, 0x00, 0x34, 0x12,
+0xD0, 0x48, 0x40, 0x69, 0x00, 0xAD, 0x01, 0x84, 0x06, 0x00, 0x0B, 0x40, 0x40,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x86, 0x22, 0x1B, 0x0A,
+0x45, 0x18, 0xF0, 0x21, 0xC0, 0x87, 0x02, 0x1F, 0x06, 0x4C, 0x00, 0xF0, 0xA1,
+0x50, 0x84, 0x02, 0x1B, 0x00, 0x5C, 0x08, 0xB0, 0x61, 0xD0, 0x84, 0x00, 0x1F,
+0x0A, 0x6C, 0x58, 0x71, 0xA1, 0xC0, 0x84, 0x02, 0x13, 0x0A, 0x7C, 0x00, 0xF0,
+0xA1, 0xC0, 0x83, 0x02, 0x0F, 0x4A, 0x4C, 0x28, 0x30, 0xA2, 0xD0, 0x74, 0xC0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x2F, 0x12, 0xBF, 0x00, 0xFC,
+0x5A, 0xF0, 0x89, 0xC0, 0x2F, 0x02, 0xBF, 0x46, 0xFD, 0x02, 0xF0, 0x8B, 0xC0,
+0x27, 0x22, 0xA7, 0x20, 0xFC, 0x0A, 0xF0, 0x4B, 0xC3, 0x2F, 0x27, 0xAF, 0x00,
+0x5C, 0x12, 0xF0, 0x09, 0xC8, 0x2F, 0x02, 0xBD, 0x00, 0x7C, 0x22, 0xF0, 0x8B,
+0xC0, 0x26, 0x00, 0x9F, 0x00, 0x7D, 0x02, 0xF0, 0x09, 0xC0, 0x67, 0x60, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0, 0x27, 0x05, 0xBF, 0x08, 0xEC, 0x02,
+0x30, 0x0B, 0xC0, 0x24, 0x00, 0xBF, 0x04, 0x7C, 0x02, 0x30, 0xCA, 0xC0, 0x2C,
+0x00, 0x83, 0x40, 0xD0, 0x22, 0xF0, 0x4B, 0xC0, 0x2F, 0x05, 0x8F, 0x88, 0x5C,
+0x82, 0xB0, 0x09, 0xC0, 0x2F, 0x02, 0xB3, 0x00, 0xFC, 0x16, 0xF0, 0x49, 0xD0,
+0x2F, 0x00, 0xBF, 0x00, 0xCC, 0x22, 0x30, 0x0B, 0xC0, 0x60, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x03, 0x01, 0x5D, 0x04, 0x44, 0x48, 0x14,
+0x01, 0x49, 0x04, 0x02, 0x17, 0x14, 0x74, 0x00, 0x14, 0xC1, 0x44, 0x80, 0x04,
+0x11, 0x00, 0x44, 0x20, 0xD2, 0x41, 0x49, 0x07, 0x21, 0x1D, 0x04, 0x44, 0x48,
+0x10, 0x01, 0x40, 0x07, 0x02, 0x11, 0x00, 0x74, 0x00, 0xD2, 0x81, 0x40, 0x16,
+0x04, 0x5D, 0x90, 0x44, 0x00, 0x10, 0x01, 0x40, 0x71, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0xA0, 0x23, 0x05, 0x8D, 0x04, 0x05, 0x32, 0x10, 0x88,
+0x40, 0x20, 0x00, 0x8D, 0x8D, 0x74, 0x02, 0x11, 0x58, 0x40, 0x20, 0x43, 0x81,
+0x40, 0x16, 0x02, 0xD0, 0xC8, 0x40, 0x23, 0x05, 0x8D, 0x24, 0x14, 0x32, 0x90,
+0x08, 0x40, 0x23, 0x00, 0x81, 0x00, 0x34, 0x0A, 0xD0, 0x08, 0x40, 0x21, 0x01,
+0x8D, 0x00, 0x44, 0x02, 0x10, 0x08, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x04, 0x44, 0x42, 0x10, 0x09, 0x40,
+0xA4, 0x01, 0x95, 0x40, 0x74, 0x06, 0x10, 0x09, 0x42, 0x24, 0x00, 0x91, 0x00,
+0x46, 0x03, 0xD0, 0x0D, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x10, 0x09,
+0x40, 0x27, 0x40, 0x91, 0x20, 0x74, 0x02, 0xD0, 0x29, 0x40, 0x24, 0x00, 0x8D,
+0x20, 0x45, 0x02, 0x00, 0x09, 0x40, 0x61, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xA8, 0x27, 0x02, 0x9F, 0x01, 0x44, 0x02, 0x30, 0x09, 0xD0, 0x24,
+0x00, 0x9F, 0x01, 0x3C, 0x02, 0x30, 0x09, 0xF0, 0x24, 0x00, 0x83, 0x01, 0x5C,
+0x1A, 0xD2, 0x39, 0xC5, 0x27, 0x24, 0x9E, 0x00, 0x5E, 0x02, 0xB0, 0x09, 0xC0,
+0x67, 0x40, 0x93, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0xA7, 0x00, 0x9F, 0x02,
+0x4C, 0x02, 0x30, 0x09, 0xC0, 0x14, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x16, 0x80, 0x65, 0x00, 0x9F, 0x00, 0x1C, 0x26, 0xF0, 0x08, 0xC0, 0x67, 0x00,
+0x97, 0x02, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0xDF, 0x82, 0x7C, 0xC2,
+0xF0, 0x49, 0xC0, 0xE7, 0x00, 0x9D, 0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0xE7,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x89, 0xC0, 0x27, 0x00, 0x9F, 0x80, 0x7C,
+0x42, 0xF4, 0x09, 0xC0, 0x53, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x08, 0x05, 0x00, 0x13, 0x00, 0x4C, 0x48, 0xF0, 0x01, 0xD3, 0x04, 0x00, 0x1F,
+0x00, 0x7C, 0x80, 0xF0, 0x81, 0xC0, 0x04, 0x40, 0x13, 0x00, 0x4C, 0x08, 0xF3,
+0x21, 0xC5, 0xC7, 0x00, 0x1F, 0x00, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00,
+0x1B, 0x00, 0x6C, 0x00, 0xF0, 0x01, 0xC0, 0x84, 0x41, 0x13, 0x02, 0x4D, 0x00,
+0xF0, 0x41, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80,
+0x14, 0x00, 0x71, 0x07, 0xC5, 0x0D, 0x70, 0x17, 0x40, 0x14, 0x00, 0x7D, 0x04,
+0x74, 0x01, 0xD0, 0x05, 0x42, 0x58, 0x00, 0x51, 0x00, 0xD4, 0x09, 0xD0, 0x27,
+0x40, 0x1F, 0x00, 0x5D, 0x00, 0x44, 0x01, 0x78, 0x05, 0x40, 0x5F, 0x00, 0x71,
+0x00, 0x74, 0x01, 0xD0, 0x05, 0xC0, 0x1E, 0x00, 0x71, 0x11, 0x84, 0x05, 0xD2,
+0x27, 0x40, 0x53, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32,
+0x00, 0x91, 0x07, 0x24, 0x2F, 0x50, 0x1C, 0x40, 0x30, 0x80, 0x4D, 0x11, 0x34,
+0x03, 0xD0, 0x0D, 0x40, 0x32, 0x10, 0xC9, 0x06, 0x04, 0x07, 0xD0, 0x3C, 0x40,
+0x33, 0x80, 0xDD, 0x00, 0x14, 0x03, 0x50, 0x0C, 0x40, 0x37, 0x86, 0x8D, 0x00,
+0x34, 0x02, 0xD0, 0x0D, 0x40, 0x30, 0x00, 0xC1, 0x00, 0x04, 0x2F, 0xD0, 0x01,
+0x40, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x78, 0x00,
+0x21, 0x24, 0x84, 0x03, 0x50, 0x0E, 0x41, 0x38, 0x02, 0x6D, 0x00, 0xB4, 0x03,
+0xD0, 0x0B, 0x50, 0x28, 0x05, 0x69, 0x10, 0xB4, 0x09, 0xD0, 0x2E, 0x42, 0x3B,
+0x04, 0xFD, 0x00, 0x84, 0x03, 0x51, 0x0E, 0x40, 0x1B, 0x00, 0x25, 0x00, 0xB4,
+0x02, 0xD2, 0x4F, 0x64, 0x7A, 0x20, 0xE1, 0x00, 0x84, 0x03, 0xD0, 0x0A, 0x60,
+0x17, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x78, 0x00, 0x23,
+0x07, 0xAD, 0x05, 0x70, 0x14, 0xC0, 0x78, 0x01, 0xEF, 0x01, 0xBC, 0x07, 0xF0,
+0x9E, 0xC0, 0x68, 0x41, 0xA9, 0x09, 0x8C, 0x07, 0xF3, 0x1E, 0xC0, 0x7B, 0x10,
+0xEF, 0x01, 0x94, 0x17, 0x70, 0x3E, 0x80, 0x7F, 0x00, 0xEF, 0x01, 0xBC, 0x07,
+0xF0, 0x5E, 0x80, 0x7C, 0x00, 0xF1, 0x01, 0x8C, 0x07, 0xF0, 0x16, 0xC0, 0x57,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0xB5, 0x42, 0x0F, 0x00,
+0x7C, 0x01, 0x72, 0x05, 0xC0, 0x77, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x49,
+0xD0, 0x07, 0x0A, 0x17, 0x00, 0x5C, 0x01, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x06, 0x7C, 0x03, 0x70, 0x1D, 0xC0, 0x27, 0x40, 0x5B, 0x00, 0x7C, 0x03, 0xF0,
+0x1C, 0xC0, 0x27, 0x00, 0xDE, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0xFF, 0x00, 0xB3, 0x01, 0xCC,
+0x23, 0xF0, 0x5F, 0xC2, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x07, 0x30, 0x1F, 0xC0,
+0x6C, 0x00, 0xFB, 0x41, 0xC8, 0x27, 0x30, 0x17, 0xC0, 0x5F, 0x20, 0xFF, 0x13,
+0xDC, 0x47, 0xB0, 0x1F, 0xC8, 0x7F, 0x00, 0xBF, 0x01, 0xDC, 0x06, 0x30, 0x1F,
+0xD1, 0x7C, 0x00, 0xFF, 0x81, 0xFC, 0x87, 0xF0, 0x1B, 0xC0, 0x03, 0x08, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x3D, 0x00, 0xA1, 0x0A, 0x84, 0x09,
+0x70, 0x0E, 0x48, 0x3B, 0x04, 0xAD, 0x00, 0xB4, 0x03, 0x10, 0x0F, 0x40, 0x28,
+0x10, 0x61, 0x04, 0xC4, 0x23, 0x10, 0x86, 0x40, 0x3B, 0x0A, 0xED, 0x00, 0xC4,
+0x03, 0xB2, 0x0E, 0x40, 0x3B, 0x00, 0x3D, 0x00, 0x84, 0x02, 0xB0, 0x0E, 0x40,
+0x38, 0x00, 0xAD, 0x88, 0xB4, 0x22, 0xD0, 0x02, 0x40, 0x57, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x39, 0x00, 0x31, 0x00, 0x84, 0x23, 0xD8,
+0x46, 0x40, 0x3B, 0x00, 0xED, 0x02, 0xF4, 0x03, 0x90, 0x2E, 0x40, 0x20, 0x00,
+0xA1, 0x20, 0x86, 0x22, 0x98, 0x2A, 0x40, 0x8B, 0x00, 0xED, 0x00, 0x94, 0x03,
+0x10, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0x94, 0x23, 0x10, 0x0C, 0x40, 0x18,
+0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x41, 0x03, 0x08, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x20, 0x33, 0x04, 0x01, 0x03, 0x45, 0x00, 0x50, 0x01,
+0x40, 0xF3, 0x00, 0x9D, 0x40, 0x36, 0x83, 0x90, 0x0C, 0x40, 0x04, 0x00, 0x01,
+0x20, 0x06, 0x02, 0x90, 0x08, 0x44, 0x23, 0x08, 0xCD, 0x00, 0x04, 0x03, 0x90,
+0x0C, 0x40, 0x33, 0x02, 0x4D, 0x08, 0x04, 0x03, 0x90, 0x1C, 0x40, 0x20, 0x00,
+0xCD, 0x00, 0x74, 0x02, 0xD0, 0x14, 0x40, 0x13, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xA0, 0xBD, 0x40, 0x73, 0x11, 0x4C, 0x0A, 0xF0, 0x09, 0xC0,
+0x3F, 0x10, 0x5F, 0x03, 0x74, 0x83, 0xB4, 0x09, 0x40, 0x2C, 0x00, 0xD3, 0x00,
+0x4C, 0x1A, 0xB0, 0x09, 0xC0, 0x27, 0x00, 0xFF, 0x00, 0xDC, 0x03, 0x30, 0x0F,
+0x40, 0x27, 0x00, 0x5F, 0x00, 0x1C, 0x02, 0x30, 0xBF, 0xC1, 0x34, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x14, 0xC0, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x77, 0x00, 0x5F, 0x06, 0x7C, 0x62, 0xF0, 0x09, 0xC0, 0x37,
+0x01, 0x5F, 0x01, 0x7C, 0x03, 0x70, 0x09, 0xC0, 0x27, 0x00, 0xD7, 0x02, 0x7D,
+0x00, 0x70, 0x01, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF2, 0x0D, 0xC4,
+0x27, 0x00, 0x5F, 0x02, 0x7C, 0x02, 0xF0, 0x0D, 0xE0, 0x37, 0x00, 0xDF, 0x02,
+0x7C, 0x0B, 0xF1, 0x0D, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x3F, 0x00, 0x73, 0x08, 0xCC, 0x00, 0x30, 0x0B, 0xC2, 0x38, 0x00,
+0xF3, 0x00, 0xCC, 0x03, 0x31, 0x1B, 0xC0, 0x2E, 0x00, 0xF3, 0x00, 0xCC, 0x40,
+0xF0, 0x0A, 0xC4, 0x08, 0x00, 0xF3, 0x00, 0xBC, 0x03, 0x30, 0x0F, 0xC0, 0x2F,
+0x00, 0x7F, 0x01, 0x4C, 0x06, 0x30, 0x0E, 0xC8, 0x3C, 0x00, 0x7F, 0x00, 0xFC,
+0x03, 0x30, 0x83, 0xC0, 0x00, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x36, 0x00, 0x51, 0x00, 0x45, 0x0C, 0x11, 0x39, 0x41, 0x34, 0x00, 0xD1,
+0x01, 0x2C, 0x03, 0x50, 0x09, 0x40, 0x44, 0x00, 0xC1, 0x02, 0x7C, 0x0C, 0xD0,
+0x31, 0xC0, 0x46, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x50, 0x0D, 0xC0, 0x65, 0x00,
+0x5D, 0x02, 0x6C, 0x06, 0x14, 0x0D, 0x40, 0x34, 0x00, 0xDD, 0x04, 0x70, 0x07,
+0x10, 0x09, 0x40, 0x04, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA8,
+0x30, 0x40, 0x01, 0x00, 0x64, 0x06, 0x90, 0x11, 0x40, 0x34, 0x00, 0xD1, 0x01,
+0x44, 0x03, 0x18, 0x88, 0x40, 0x24, 0x01, 0xD1, 0x14, 0x44, 0x06, 0xD0, 0x11,
+0x40, 0x44, 0x00, 0xD1, 0x00, 0x54, 0x03, 0x90, 0x0D, 0x40, 0x67, 0x04, 0x49,
+0x06, 0x44, 0x22, 0x10, 0x0D, 0x40, 0x34, 0x22, 0xDD, 0x40, 0x74, 0x0F, 0x10,
+0x0D, 0x40, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30,
+0x00, 0x01, 0x00, 0x05, 0x02, 0x90, 0x08, 0x56, 0x30, 0x40, 0xC1, 0x00, 0x45,
+0x03, 0x50, 0x08, 0x40, 0x20, 0x00, 0x81, 0x00, 0x14, 0x02, 0xD0, 0x00, 0x40,
+0x60, 0x00, 0xC1, 0x00, 0x34, 0x03, 0xD2, 0x0C, 0x40, 0x21, 0x00, 0x4D, 0x00,
+0x24, 0x02, 0x10, 0x0C, 0x00, 0x30, 0x08, 0x8D, 0x00, 0x34, 0x03, 0x10, 0x05,
+0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB0, 0x3E, 0x10,
+0x13, 0x00, 0x4D, 0x02, 0xB0, 0x01, 0x42, 0x34, 0x00, 0x93, 0x20, 0x46, 0x03,
+0x30, 0x0B, 0xC0, 0x26, 0x00, 0x53, 0x00, 0x44, 0x00, 0xF1, 0x09, 0x40, 0x04,
+0x40, 0xE3, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0xC0, 0x27, 0x00, 0x5F, 0x00, 0x4C,
+0x02, 0x30, 0x0D, 0x90, 0x14, 0x00, 0x5F, 0x00, 0x7C, 0x03, 0x30, 0x09, 0xD0,
+0x00, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x98, 0x3F, 0x00, 0x2F,
+0x00, 0xFC, 0x02, 0x70, 0x0B, 0xC4, 0x3F, 0x00, 0xBF, 0x00, 0xBC, 0x03, 0xF0,
+0x0B, 0xC0, 0x0F, 0x00, 0x2F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC2, 0x0F, 0x00,
+0xFF, 0x20, 0xFC, 0x03, 0x70, 0x0F, 0xC0, 0x2D, 0x00, 0x7F, 0x00, 0xFC, 0x02,
+0xF0, 0x0F, 0xC0, 0x3F, 0x08, 0xFF, 0x00, 0xFC, 0x01, 0xF0, 0x03, 0xC0, 0x17,
+0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0xFF, 0x00, 0xFF, 0x09,
+0xFC, 0x32, 0xF0, 0x4F, 0xE1, 0x2D, 0x21, 0xFF, 0x09, 0xFC, 0x00, 0xF0, 0x0F,
+0xC0, 0x3C, 0x00, 0xFF, 0x1C, 0xCC, 0x52, 0xF0, 0x4F, 0xC0, 0x7C, 0x80, 0xFF,
+0x00, 0xCC, 0x13, 0xB0, 0x0F, 0xC0, 0x7C, 0x00, 0xFF, 0x84, 0xBC, 0x05, 0x30,
+0x1F, 0xC0, 0x7C, 0x40, 0xFB, 0x01, 0xCC, 0x04, 0xB0, 0x0B, 0xC0, 0x0C, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xCD, 0x00, 0x74,
+0x3A, 0xD0, 0x3F, 0x40, 0xA7, 0x03, 0xDD, 0x04, 0x74, 0x06, 0xD0, 0x2F, 0x40,
+0xFC, 0x00, 0xFD, 0x06, 0x44, 0x1A, 0xD0, 0xBF, 0x46, 0x74, 0x00, 0xFD, 0x06,
+0xC4, 0x3B, 0x34, 0xAF, 0x40, 0x74, 0x00, 0xFC, 0x02, 0x74, 0x05, 0x10, 0x1D,
+0x40, 0x74, 0x00, 0x91, 0x01, 0x54, 0x03, 0x52, 0x01, 0x40, 0x0D, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x01, 0xCD, 0x00, 0x34, 0x00,
+0xD0, 0x0C, 0x40, 0x03, 0x04, 0xCD, 0x04, 0x34, 0x02, 0xD0, 0x8C, 0x40, 0x32,
+0x02, 0xCD, 0x00, 0x04, 0x40, 0xD1, 0x0C, 0x40, 0x30, 0x00, 0xCD, 0x18, 0x04,
+0x43, 0x10, 0x0C, 0x42, 0x30, 0x00, 0xCD, 0x02, 0x74, 0x03, 0x10, 0x0D, 0x40,
+0x31, 0x00, 0x49, 0x80, 0x04, 0x01, 0x80, 0x08, 0x60, 0x4C, 0x80, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xDD, 0x00, 0x74, 0x0C, 0xD0,
+0x0D, 0x40, 0x47, 0x00, 0xDD, 0x00, 0x74, 0x0E, 0xD0, 0x0D, 0x40, 0x36, 0x00,
+0xDD, 0x00, 0x45, 0x06, 0xD0, 0x0D, 0x40, 0x34, 0x10, 0xDD, 0x00, 0x44, 0x03,
+0x10, 0x0D, 0x40, 0x34, 0x14, 0xDD, 0x00, 0x74, 0x21, 0x10, 0x0D, 0x60, 0x74,
+0x90, 0x11, 0x00, 0x56, 0x01, 0x09, 0x31, 0x40, 0x0D, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x0C, 0xF0, 0x0D,
+0xC0, 0x67, 0x04, 0xDF, 0x00, 0x7C, 0x04, 0xF0, 0x0D, 0x40, 0x36, 0x00, 0xDF,
+0x20, 0x4C, 0x1E, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xDD, 0x00, 0x4C, 0x03, 0x30,
+0x0D, 0xC0, 0x34, 0x00, 0xDF, 0x00, 0x7C, 0x81, 0x31, 0x2C, 0xC0, 0xF0, 0x04,
+0xDB, 0x00, 0x4C, 0x16, 0xA0, 0x31, 0xC0, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x88, 0x3D, 0x00, 0xFF, 0x00, 0x7C, 0x02, 0xF0, 0x0F, 0xC2,
+0x2F, 0x00, 0xFF, 0x00, 0x7C, 0x02, 0xF0, 0x0F, 0xD0, 0x35, 0x00, 0xDF, 0x00,
+0xFC, 0x02, 0xF0, 0x0E, 0xC0, 0x3F, 0x00, 0xEF, 0x00, 0xFC, 0x43, 0xF0, 0x0F,
+0xC4, 0x3F, 0x02, 0xFD, 0x00, 0xF8, 0x01, 0xF4, 0x2F, 0x40, 0x3F, 0x40, 0xFF,
+0x00, 0xFC, 0x67, 0xF0, 0x02, 0xC2, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x08, 0x35, 0x80, 0xDF, 0x00, 0x5C, 0x08, 0x30, 0x0D, 0xC0, 0xA4,
+0x08, 0xDF, 0x00, 0x4C, 0x08, 0x30, 0x5C, 0xC0, 0x34, 0x00, 0xC3, 0x40, 0x4C,
+0x48, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x00, 0x3C, 0x83, 0xF0, 0x0C, 0xC0,
+0x34, 0x04, 0xD7, 0x91, 0x4C, 0x13, 0x74, 0x0D, 0xC5, 0x35, 0x00, 0xDF, 0x84,
+0x4C, 0x05, 0xE0, 0x29, 0x81, 0x09, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x44, 0x04, 0x10, 0x0F, 0x40, 0xE4, 0x02,
+0xDD, 0x00, 0x44, 0x00, 0xB0, 0x2F, 0x40, 0x3D, 0x00, 0xF1, 0x01, 0x44, 0x16,
+0xD0, 0x0F, 0xC0, 0x34, 0x00, 0xF7, 0x04, 0xF4, 0x4B, 0xD0, 0xAF, 0x40, 0xB5,
+0x00, 0xF0, 0x02, 0x04, 0x15, 0x10, 0x3D, 0x44, 0x34, 0x10, 0xC9, 0x80, 0x44,
+0x85, 0x90, 0x31, 0x41, 0x6D, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0x20, 0x30, 0x10, 0xCD, 0x00, 0x04, 0x4E, 0x11, 0x0C, 0x44, 0x40, 0x00, 0xCD,
+0x00, 0x04, 0x00, 0x10, 0x2C, 0x40, 0x30, 0x08, 0xC1, 0x04, 0x24, 0x04, 0xD0,
+0x0C, 0x50, 0x32, 0x00, 0xC1, 0x07, 0x34, 0x07, 0xD0, 0x0C, 0x40, 0xD0, 0x00,
+0xC5, 0x02, 0x00, 0x09, 0x10, 0x14, 0x40, 0x83, 0x41, 0xC1, 0x02, 0x64, 0x00,
+0xD0, 0x18, 0x40, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+0x78, 0x00, 0xED, 0x01, 0x85, 0x07, 0x14, 0x1C, 0x50, 0x78, 0x04, 0xED, 0x01,
+0x85, 0x06, 0x10, 0x1E, 0x40, 0x78, 0x80, 0xE1, 0x11, 0xA4, 0x05, 0xD0, 0x1C,
+0x40, 0x7C, 0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x59, 0x06, 0xE5,
+0x01, 0x84, 0x05, 0x10, 0x9E, 0x40, 0x7A, 0x07, 0xA1, 0x01, 0xA4, 0x06, 0x91,
+0x1A, 0x40, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x18, 0x30,
+0x00, 0xCD, 0x00, 0x1C, 0x43, 0x30, 0x0C, 0xC0, 0x10, 0x00, 0xDF, 0x00, 0x04,
+0x03, 0x10, 0x0D, 0xC0, 0x30, 0x00, 0xC3, 0x00, 0x2C, 0x21, 0xF0, 0x0C, 0xC0,
+0x36, 0x02, 0xC3, 0x00, 0x3C, 0x03, 0xF2, 0x0D, 0xE0, 0x20, 0x00, 0xD7, 0x00,
+0x0C, 0x33, 0x30, 0x8C, 0xC1, 0x23, 0x03, 0x4B, 0x20, 0x2C, 0x20, 0xF0, 0x09,
+0xC0, 0x4B, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x3D, 0x10,
+0xFF, 0x48, 0xFC, 0x23, 0xF8, 0x0F, 0xC0, 0x1F, 0x00, 0xFF, 0x00, 0xFC, 0x03,
+0xF0, 0x0F, 0xC0, 0x3F, 0x10, 0xFF, 0x02, 0x5D, 0x21, 0xF0, 0x0F, 0xC0, 0x3F,
+0x00, 0xF7, 0x10, 0x7C, 0x43, 0xF0, 0x0D, 0xC1, 0x2A, 0x00, 0xFB, 0x02, 0x7C,
+0x21, 0xF2, 0x88, 0x00, 0x28, 0x03, 0x2F, 0x08, 0xDC, 0x22, 0xF2, 0x8B, 0xC4,
+0x09, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x80, 0xDF,
+0x00, 0x7E, 0x01, 0x30, 0x4D, 0xC1, 0x17, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0,
+0xAD, 0xD0, 0x34, 0x01, 0xDF, 0x02, 0x5C, 0x03, 0xF0, 0xCD, 0xC0, 0x37, 0x00,
+0xDF, 0x04, 0x7C, 0x1B, 0xF8, 0x6D, 0xC0, 0x37, 0x00, 0xD3, 0x0E, 0x7C, 0x01,
+0xF0, 0x1D, 0xC0, 0x22, 0x40, 0xCB, 0x00, 0x4C, 0x02, 0xF0, 0x11, 0x40, 0x40,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x39, 0x00, 0xED, 0x00,
+0xF4, 0x03, 0x10, 0x4E, 0x40, 0x3B, 0x00, 0xEC, 0x00, 0xB4, 0x03, 0xD0, 0x8E,
+0x40, 0xB8, 0x05, 0xFD, 0x04, 0x84, 0x03, 0xD0, 0x0E, 0x41, 0x3B, 0x00, 0xED,
+0x0C, 0xB4, 0x53, 0x70, 0xCE, 0x40, 0x3B, 0x00, 0xE5, 0x00, 0xB4, 0x00, 0xD0,
+0x0E, 0x40, 0x28, 0x00, 0xEB, 0x00, 0x84, 0x03, 0xD0, 0x06, 0x40, 0x4C, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xE5, 0x01, 0xB4,
+0x87, 0x92, 0xDE, 0x42, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x5C, 0x40,
+0x78, 0x00, 0xFD, 0x4D, 0x94, 0x07, 0xD0, 0x5E, 0x40, 0x7B, 0x00, 0xED, 0x05,
+0xB4, 0x07, 0xD0, 0x1E, 0x44, 0x7F, 0x00, 0xE1, 0x05, 0xB4, 0x07, 0xD0, 0x1E,
+0x41, 0x6E, 0x80, 0xF9, 0x01, 0x84, 0x07, 0xD0, 0x1C, 0x60, 0x10, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xDD, 0x00, 0x74, 0x43,
+0x94, 0x0C, 0x40, 0xF3, 0x01, 0xCD, 0x00, 0x36, 0x3F, 0xD0, 0x0D, 0x40, 0x30,
+0x10, 0xDD, 0x00, 0x04, 0x47, 0x90, 0x0C, 0x42, 0x33, 0x00, 0xDD, 0x00, 0x74,
+0x03, 0x52, 0x0C, 0x40, 0xB3, 0x02, 0xC5, 0x00, 0x34, 0x00, 0xD0, 0x4C, 0x46,
+0x60, 0xA2, 0xC9, 0x09, 0x44, 0x03, 0xC0, 0x1C, 0x40, 0x58, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x15, 0x08, 0x5F, 0x00, 0xF4, 0x15, 0xB0,
+0x05, 0xC0, 0x9F, 0x01, 0x5F, 0x00, 0xFC, 0x01, 0xF2, 0x05, 0xC0, 0x14, 0x08,
+0x5F, 0x00, 0xDC, 0x19, 0xF3, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x01,
+0xF0, 0x05, 0xC0, 0x5F, 0x20, 0x53, 0x00, 0xFC, 0x15, 0xF0, 0x07, 0xCC, 0x9A,
+0x20, 0x6B, 0x02, 0xCD, 0x09, 0xF0, 0x37, 0xD0, 0x5C, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x0A, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x70, 0x01,
+0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x20, 0x1F,
+0x40, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x70,
+0x21, 0xC0, 0x87, 0x01, 0x1F, 0x02, 0x7E, 0x00, 0xF2, 0x01, 0xC0, 0x07, 0x04,
+0x1F, 0x10, 0x7C, 0x48, 0xB0, 0xE1, 0xC8, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F, 0x80, 0x4C, 0x02, 0x30, 0x09, 0xC0,
+0xA7, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x80, 0x9F, 0x08,
+0x0C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x4C, 0x0E, 0x30, 0x08,
+0xC0, 0x24, 0x00, 0x97, 0x00, 0x7C, 0x86, 0x72, 0x29, 0xCA, 0xA7, 0x08, 0x97,
+0x05, 0x5C, 0x02, 0x30, 0x19, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x20, 0x24, 0x08, 0x9D, 0x20, 0x44, 0x36, 0x04, 0x09, 0x44, 0xE7,
+0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x29, 0x40, 0x25, 0x90, 0x9C, 0x01, 0x44,
+0x0A, 0x14, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x03, 0x45, 0x0A, 0xA4, 0x09, 0x51,
+0xA0, 0x00, 0x90, 0x12, 0x34, 0x26, 0x10, 0x29, 0x40, 0x27, 0x00, 0x99, 0x00,
+0x6C, 0x8A, 0x50, 0x19, 0x41, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x45, 0x02, 0x00, 0x09, 0x40, 0x27, 0x00,
+0x9D, 0x00, 0x40, 0x02, 0xD0, 0x09, 0x00, 0x24, 0x20, 0x9C, 0x10, 0x44, 0x22,
+0x10, 0x09, 0x44, 0x25, 0x00, 0x9D, 0x14, 0x44, 0x42, 0x90, 0x19, 0x40, 0x24,
+0x04, 0x95, 0x00, 0x54, 0x02, 0x40, 0x0D, 0x41, 0x26, 0x00, 0x9D, 0x42, 0x54,
+0x12, 0x10, 0x49, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x20, 0x20, 0x00, 0x8D, 0x00, 0x04, 0x12, 0x11, 0x48, 0x40, 0x33, 0x01, 0x8D,
+0x00, 0x34, 0x12, 0xD0, 0x4D, 0x4C, 0x21, 0x11, 0x8D, 0x04, 0x04, 0x13, 0x10,
+0x48, 0x60, 0x23, 0x00, 0x8D, 0x04, 0x04, 0x12, 0x90, 0x48, 0x44, 0x24, 0x00,
+0x81, 0x84, 0x76, 0x02, 0x1A, 0x08, 0x40, 0x23, 0x88, 0x89, 0x80, 0x24, 0x02,
+0x50, 0x48, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x38,
+0x86, 0x0A, 0x1F, 0x0A, 0x4C, 0x28, 0x30, 0x01, 0xC0, 0x87, 0x02, 0x1F, 0x0A,
+0x7C, 0x00, 0xF0, 0xA1, 0xC0, 0x04, 0x00, 0x1D, 0x0A, 0x4D, 0x28, 0x32, 0x01,
+0xC4, 0x07, 0x00, 0x1F, 0x0A, 0x4C, 0x28, 0x30, 0xA1, 0x40, 0x04, 0x08, 0x17,
+0x4A, 0x5C, 0x00, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x17, 0x00, 0x5C, 0x29, 0x30,
+0xA1, 0xC0, 0x77, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB2, 0x25,
+0x00, 0x9F, 0x40, 0xFC, 0x22, 0xF0, 0x89, 0xC0, 0x2F, 0x02, 0x9F, 0x00, 0xFC,
+0x22, 0xF0, 0x89, 0xC0, 0x27, 0x02, 0x9F, 0x48, 0xFC, 0x22, 0xF0, 0x89, 0xC2,
+0x27, 0x00, 0x9F, 0x08, 0x7C, 0x22, 0x70, 0x89, 0xC0, 0x3B, 0x00, 0x9F, 0x08,
+0xFC, 0x02, 0xF0, 0x0A, 0xC0, 0x2F, 0x00, 0xB7, 0x80, 0xDC, 0x02, 0xF1, 0x8F,
+0xC0, 0x77, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x80, 0x27, 0x00,
+0x9F, 0x08, 0xFC, 0x02, 0x30, 0x09, 0xC0, 0x2C, 0x02, 0x93, 0x00, 0x7C, 0x52,
+0xF0, 0xCB, 0xC0, 0x27, 0x00, 0xBF, 0x00, 0xFC, 0x22, 0xB0, 0x49, 0xC0, 0x27,
+0x00, 0xBF, 0x0C, 0xFC, 0x02, 0xE0, 0x0B, 0xC0, 0x2D, 0x00, 0xB3, 0x04, 0xDC,
+0x02, 0xB0, 0x0B, 0xC0, 0x2A, 0x40, 0xB3, 0x00, 0xBC, 0x03, 0x30, 0x0B, 0xC0,
+0x77, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01, 0x1D,
+0x04, 0x74, 0x49, 0x10, 0x01, 0x44, 0x14, 0x42, 0x01, 0x14, 0x74, 0x00, 0xD0,
+0xC1, 0x4C, 0x87, 0x10, 0x1D, 0x50, 0x74, 0x20, 0x10, 0x01, 0x40, 0x07, 0x00,
+0x1D, 0x0C, 0x74, 0x48, 0xD0, 0x01, 0x45, 0x07, 0x00, 0x11, 0x14, 0x74, 0x00,
+0xD0, 0x05, 0x40, 0x04, 0x00, 0x11, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40, 0x63,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x05, 0x8D, 0x04,
+0x34, 0xB2, 0x14, 0x88, 0x40, 0x20, 0x00, 0x81, 0x04, 0x36, 0x02, 0xD0, 0x48,
+0x48, 0x23, 0x82, 0x8D, 0x08, 0x34, 0x02, 0x14, 0x88, 0x60, 0x23, 0x00, 0x8D,
+0x04, 0x34, 0x32, 0xD0, 0x88, 0x40, 0x27, 0x00, 0x81, 0x0C, 0x36, 0x02, 0x52,
+0x08, 0x40, 0x23, 0x00, 0x81, 0x00, 0x14, 0x02, 0x18, 0x08, 0x40, 0x4B, 0x80,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x9D, 0x00, 0x74,
+0x12, 0x10, 0x09, 0x50, 0x24, 0x01, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x74, 0x0B, 0x10, 0x09, 0x40, 0x27, 0x00, 0xDD, 0x00,
+0x74, 0x02, 0xD8, 0x09, 0x40, 0x27, 0x00, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x09,
+0x40, 0x27, 0x04, 0x91, 0x02, 0x70, 0x12, 0x19, 0x09, 0x40, 0x63, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x24, 0x00, 0x9F, 0x00, 0x78, 0x06,
+0x30, 0x09, 0xC0, 0x64, 0x00, 0x93, 0x00, 0x7C, 0x4E, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xB2, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF2, 0x09, 0xC0, 0x67, 0x40, 0x93, 0x00, 0x7C, 0x42, 0xB0, 0xB9, 0xC0,
+0x27, 0x00, 0x93, 0x00, 0x7C, 0x46, 0x34, 0x19, 0xC0, 0x17, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x3C, 0x06, 0xF0,
+0x08, 0xC0, 0x67, 0x00, 0x9C, 0x00, 0x7C, 0x12, 0xF0, 0x09, 0xC1, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x22, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF0, 0x09, 0xC1, 0x27, 0x02, 0x9F, 0xB0, 0x7C, 0x42, 0xF0, 0x19, 0x02, 0x24,
+0x01, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x99, 0xC1, 0x5B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01,
+0xC0, 0xC7, 0x00, 0x1F, 0x00, 0x4C, 0x08, 0x30, 0x01, 0xC0, 0x04, 0x00, 0x1F,
+0x01, 0x7C, 0x30, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x01, 0x5C, 0x04, 0xF0,
+0x01, 0xC8, 0x86, 0x09, 0x13, 0x08, 0x6D, 0x08, 0xE0, 0x41, 0xC0, 0x84, 0x00,
+0x17, 0x40, 0x6C, 0x10, 0x10, 0xA1, 0xC2, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x00, 0x14, 0x00, 0x5D, 0x80, 0xF4, 0x1D, 0x70, 0x05, 0x40,
+0x5F, 0x20, 0x5D, 0x00, 0x4C, 0x01, 0x10, 0x27, 0x40, 0x14, 0x00, 0x7D, 0x00,
+0xF4, 0x0D, 0xD0, 0x05, 0x40, 0x17, 0x00, 0x7D, 0x01, 0xC4, 0x05, 0x70, 0x27,
+0x40, 0x18, 0x00, 0x71, 0x82, 0xC4, 0x19, 0xD0, 0x16, 0x41, 0x18, 0x01, 0x71,
+0x1B, 0xE4, 0x45, 0x10, 0x07, 0x40, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x1F, 0x58, 0x0C, 0x40, 0x77,
+0x00, 0xC9, 0x00, 0x25, 0x03, 0x14, 0x2C, 0x50, 0x30, 0x00, 0xCD, 0x01, 0x74,
+0x07, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x14, 0x03, 0x50, 0x1C, 0x50,
+0xB0, 0x42, 0xC1, 0x00, 0x04, 0x03, 0xD0, 0x2C, 0x40, 0x50, 0x40, 0xC5, 0x02,
+0x64, 0x07, 0x94, 0x1C, 0x40, 0x40, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x80, 0x38, 0x02, 0xED, 0x08, 0xB4, 0x03, 0x58, 0x0E, 0x40, 0x3B, 0x0C,
+0xED, 0x05, 0x04, 0x07, 0x10, 0x1E, 0x41, 0x38, 0x00, 0x6D, 0x10, 0xB4, 0x03,
+0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x03, 0x84, 0x09, 0x50, 0x36, 0x40, 0x3C,
+0x00, 0xE1, 0x01, 0x84, 0x03, 0xD0, 0x0F, 0x40, 0x1C, 0x00, 0xE1, 0x00, 0xE6,
+0x82, 0x90, 0x16, 0x40, 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x18, 0x78, 0x00, 0xEF, 0x11, 0xBC, 0x05, 0x70, 0x1E, 0xC0, 0x7B, 0x00, 0xEF,
+0x87, 0xAC, 0x87, 0x30, 0x1F, 0xC0, 0x78, 0x00, 0xED, 0x21, 0xBC, 0x07, 0xF0,
+0x1E, 0xC0, 0x7B, 0x00, 0xCF, 0x81, 0x9C, 0x07, 0x78, 0x1F, 0xC0, 0x78, 0x00,
+0xC3, 0x81, 0x8C, 0x07, 0xDA, 0x0A, 0xC4, 0x58, 0x20, 0xE7, 0x21, 0xAE, 0x07,
+0xB1, 0x1B, 0xC4, 0x50, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8,
+0x35, 0x01, 0xDF, 0x06, 0x7E, 0x01, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x16,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x37, 0x20, 0xDF, 0x00, 0x7C, 0x01, 0x70, 0x05, 0xC0, 0x31, 0x00, 0x5F,
+0x00, 0x5C, 0x03, 0xF8, 0x0C, 0xC0, 0x17, 0x00, 0xDF, 0x00, 0x70, 0x02, 0x70,
+0x01, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0xFD,
+0x02, 0xF3, 0x01, 0xFC, 0x23, 0xF0, 0x1F, 0xC0, 0x7F, 0x00, 0xF3, 0x81, 0xFC,
+0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x02, 0xFF, 0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC0,
+0x7F, 0x00, 0xF7, 0x01, 0xCC, 0x27, 0x38, 0x1F, 0xC0, 0x7F, 0x00, 0x73, 0x01,
+0x8C, 0x87, 0xB8, 0x97, 0xC0, 0x5C, 0x00, 0xEF, 0x21, 0xCC, 0x05, 0xF0, 0x17,
+0xC0, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x00,
+0xE1, 0x00, 0xB4, 0x03, 0xD8, 0x0E, 0x40, 0x3B, 0x02, 0xE1, 0x00, 0xB4, 0x03,
+0xD0, 0x82, 0x40, 0x3B, 0x00, 0x7D, 0x08, 0xC4, 0x03, 0x10, 0x0E, 0x40, 0x3B,
+0x00, 0x7D, 0x04, 0x84, 0x01, 0x14, 0x4E, 0x40, 0x3B, 0x01, 0x3B, 0x00, 0x85,
+0x43, 0x10, 0xCE, 0x40, 0x18, 0x01, 0xED, 0x08, 0x94, 0x62, 0xD0, 0x62, 0x40,
+0x54, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x08, 0xE1,
+0x00, 0xB4, 0x23, 0xD8, 0x0E, 0x40, 0x9B, 0x04, 0xE1, 0x00, 0xB4, 0x23, 0xD0,
+0x0E, 0x40, 0x3B, 0x88, 0x6D, 0x00, 0x84, 0x09, 0x10, 0x0E, 0x40, 0x3B, 0x00,
+0xE5, 0x80, 0x94, 0x03, 0x18, 0x0A, 0x4C, 0x3B, 0x10, 0xE1, 0x00, 0xB4, 0x03,
+0x90, 0x0F, 0x44, 0x89, 0x10, 0xED, 0x00, 0x84, 0x00, 0xD0, 0x0A, 0x61, 0x60,
+0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x35, 0x00, 0xC1, 0x40,
+0x34, 0x1A, 0xD0, 0x0C, 0x40, 0x67, 0xC0, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x00,
+0x40, 0x33, 0x80, 0x0D, 0x00, 0x05, 0x02, 0x10, 0x0C, 0x40, 0x33, 0x10, 0x8D,
+0x40, 0x44, 0x00, 0x18, 0x08, 0x40, 0x33, 0x20, 0x01, 0x00, 0x24, 0x03, 0x10,
+0x2C, 0x40, 0x50, 0x10, 0xCD, 0x01, 0x14, 0x0A, 0xD8, 0x20, 0x42, 0x08, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x3D, 0x00, 0xF3, 0x00, 0x7C,
+0x16, 0xD0, 0x0D, 0xC4, 0x47, 0x00, 0xF3, 0x00, 0x7C, 0x0B, 0xD0, 0x01, 0xC0,
+0x37, 0x00, 0x9F, 0x00, 0x4C, 0x04, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0x17, 0x00,
+0x5C, 0x02, 0x30, 0x09, 0x00, 0x37, 0x00, 0x91, 0x00, 0x6C, 0x8B, 0xB0, 0x2C,
+0xC1, 0x50, 0x01, 0xDF, 0x00, 0x40, 0x08, 0xD0, 0x89, 0xC0, 0x74, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02,
+0xF0, 0x0D, 0xC0, 0x07, 0x00, 0xDF, 0x00, 0x7C, 0x43, 0xF0, 0x01, 0xC0, 0x33,
+0x00, 0x1F, 0x02, 0x7C, 0x20, 0xF0, 0x0D, 0xC8, 0x37, 0x00, 0x9F, 0x02, 0x7C,
+0x0A, 0xF0, 0x09, 0xE0, 0xA7, 0x08, 0x9F, 0x42, 0x5C, 0x43, 0xF2, 0x0D, 0xD0,
+0xB7, 0x08, 0xDF, 0x2A, 0x7C, 0x08, 0xF0, 0x29, 0xD0, 0x17, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xF3, 0x00, 0xFC, 0x00, 0xF0,
+0x0F, 0xC0, 0x27, 0x00, 0xF3, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x3F, 0x40,
+0xB3, 0x00, 0x9C, 0x02, 0x30, 0x0F, 0xC0, 0x3F, 0x00, 0x3F, 0x00, 0x7C, 0x02,
+0xB0, 0x03, 0xC0, 0x3F, 0x20, 0xAF, 0x20, 0xDC, 0x03, 0x30, 0x0F, 0xC1, 0x1D,
+0x00, 0xB6, 0x00, 0xCC, 0x42, 0x80, 0x09, 0xC0, 0x07, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x40, 0xD1, 0x00, 0x74, 0x04, 0xD0, 0x0D,
+0x60, 0x67, 0x00, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x39, 0x40, 0x37, 0x00, 0x91,
+0x03, 0x5C, 0x06, 0x10, 0x0D, 0x40, 0x37, 0x00, 0x9D, 0x01, 0x74, 0x46, 0x10,
+0x11, 0x41, 0x67, 0x01, 0x19, 0x01, 0x04, 0x06, 0xB0, 0x3D, 0x40, 0x74, 0x01,
+0x01, 0x45, 0x44, 0x4E, 0x90, 0x19, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0xA0, 0x34, 0x00, 0xD1, 0x00, 0x76, 0x04, 0xD0, 0x0D, 0x4A,
+0x47, 0x04, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x39, 0x40, 0x37, 0x00, 0x91, 0x11,
+0x74, 0x04, 0x10, 0x0D, 0x40, 0x37, 0x00, 0x1D, 0x01, 0x74, 0x04, 0x10, 0x19,
+0x40, 0x77, 0x00, 0x9D, 0x03, 0x40, 0x47, 0x10, 0x8D, 0x01, 0x55, 0x00, 0xD5,
+0x81, 0x44, 0x84, 0x90, 0x11, 0x48, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x00, 0x30, 0x00, 0xC1, 0x00, 0x34, 0x06, 0xD0, 0x0C, 0x40, 0x03,
+0x00, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x00, 0x40, 0x33, 0x00, 0x01, 0x00, 0x14,
+0x00, 0x10, 0x0C, 0x40, 0x33, 0x00, 0x0D, 0x00, 0x34, 0x00, 0x90, 0x08, 0x64,
+0x33, 0x00, 0x89, 0x00, 0x47, 0x01, 0x90, 0x0C, 0x40, 0x30, 0x08, 0xD5, 0x00,
+0x04, 0x00, 0x90, 0x00, 0x44, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x3A, 0x00, 0xF3, 0x00, 0x7C, 0x00, 0xF0, 0x0D, 0x40, 0x07, 0x00,
+0xF3, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0x93, 0x00, 0x5C, 0x00,
+0x30, 0x0D, 0xC0, 0x37, 0x00, 0x1D, 0x00, 0x7C, 0x02, 0x30, 0x01, 0xC0, 0x37,
+0x00, 0x9F, 0x00, 0x5C, 0x03, 0x30, 0x0D, 0xC0, 0x15, 0x08, 0xD7, 0x00, 0x4D,
+0x80, 0xB0, 0x09, 0xC0, 0x07, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xB8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC4, 0x2F, 0x00, 0xFF,
+0x00, 0xFC, 0x03, 0xF2, 0x03, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xDC, 0x02, 0xF0,
+0x0F, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0x70, 0x03, 0xC0, 0x1B, 0x80,
+0x3F, 0x00, 0xFC, 0x01, 0xD0, 0x0E, 0xC0, 0x3F, 0x00, 0xFB, 0x00, 0xFE, 0x02,
+0xF0, 0x0B, 0xC0, 0x17, 0x42, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0,
+0x6F, 0x00, 0xF3, 0x01, 0xFC, 0x40, 0xF0, 0x02, 0xC0, 0x2C, 0x00, 0xB3, 0x40,
+0xEC, 0x02, 0x70, 0x1F, 0xC0, 0x2F, 0x00, 0xFB, 0x10, 0xFC, 0x02, 0x30, 0x03,
+0xC0, 0x68, 0x00, 0xFF, 0x00, 0xCC, 0x07, 0xB0, 0x0F, 0xC0, 0x3E, 0x09, 0xFF,
+0x01, 0xAC, 0x07, 0xF0, 0x4F, 0xC0, 0x7B, 0x00, 0xB3, 0x00, 0xCD, 0x03, 0x34,
+0x0F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x21,
+0x00, 0xD1, 0x10, 0x5C, 0x00, 0xD0, 0x11, 0x40, 0x6C, 0x08, 0x91, 0x0B, 0x58,
+0x00, 0x10, 0x1D, 0xC0, 0xA5, 0x06, 0xC1, 0x12, 0x74, 0x02, 0x10, 0x11, 0xC8,
+0x65, 0x00, 0xCD, 0x00, 0x54, 0x07, 0x10, 0x0D, 0x40, 0x74, 0x12, 0xDD, 0x01,
+0x54, 0x07, 0xD2, 0xBD, 0x40, 0x77, 0x40, 0x91, 0x10, 0x44, 0x0B, 0x10, 0x1D,
+0x00, 0x0F, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0x33, 0x00,
+0xC1, 0x00, 0x34, 0x04, 0xD0, 0x10, 0x40, 0x20, 0x00, 0xD1, 0x00, 0x04, 0x00,
+0x50, 0x0C, 0x40, 0x23, 0x09, 0xC1, 0x84, 0x34, 0x02, 0x12, 0x00, 0x40, 0x20,
+0x00, 0xC1, 0x00, 0x04, 0x03, 0x90, 0x0C, 0x40, 0x30, 0x00, 0xDD, 0x00, 0x04,
+0x03, 0x90, 0x0C, 0x40, 0x35, 0x80, 0x95, 0x84, 0x04, 0x70, 0x14, 0x0C, 0x40,
+0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xD1,
+0x00, 0x74, 0x04, 0xD0, 0x41, 0x40, 0x64, 0x40, 0xD1, 0x08, 0x74, 0x44, 0x10,
+0x0D, 0x40, 0x27, 0x40, 0xD1, 0x00, 0x74, 0x06, 0x10, 0x01, 0x40, 0x26, 0x00,
+0xDD, 0x00, 0x54, 0x83, 0x10, 0x0D, 0x40, 0x34, 0x00, 0x1D, 0x01, 0x54, 0x13,
+0xD0, 0x0D, 0x40, 0x27, 0x40, 0xD5, 0x18, 0x44, 0x02, 0x10, 0x0D, 0x48, 0x0F,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x88, 0x36, 0x00, 0xD3, 0x00,
+0x7C, 0x04, 0xF2, 0x14, 0xD0, 0x64, 0x00, 0x83, 0x80, 0x4C, 0x0E, 0x70, 0x0D,
+0xC0, 0x27, 0x00, 0xDB, 0x00, 0x7C, 0x1E, 0x30, 0x15, 0xD0, 0x24, 0x00, 0xDF,
+0x00, 0x0C, 0x03, 0xB1, 0x0D, 0xC0, 0x36, 0x00, 0xCF, 0x81, 0x4C, 0x03, 0xF0,
+0x0D, 0xC0, 0x33, 0x00, 0x87, 0x03, 0x4C, 0x27, 0x30, 0x0D, 0xC0, 0x03, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xFF, 0x00, 0xDC,
+0x40, 0xF0, 0x07, 0xC0, 0x3F, 0x08, 0xBF, 0x00, 0x9C, 0x02, 0xD0, 0x0F, 0xC0,
+0x21, 0x00, 0xFF, 0x00, 0xBC, 0x02, 0xF0, 0x96, 0xC0, 0x6D, 0x01, 0xEF, 0x00,
+0xFC, 0x03, 0xF0, 0x0E, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xDC, 0x07, 0xF0, 0x0F,
+0xC0, 0x3F, 0x00, 0xFB, 0x01, 0xFC, 0x03, 0xF0, 0x0D, 0xC0, 0x1F, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x35, 0x00, 0xD3, 0x00, 0x74, 0x00,
+0x30, 0x85, 0xC0, 0x25, 0x00, 0xD3, 0x00, 0x7C, 0x08, 0xF0, 0x0D, 0xC0, 0x37,
+0x00, 0xDF, 0x00, 0x4C, 0x3A, 0xD0, 0x05, 0x40, 0x24, 0x20, 0xD3, 0x08, 0x4D,
+0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x00, 0x7C, 0x02, 0x70, 0x0D, 0xC0,
+0x37, 0x00, 0x93, 0x00, 0x4D, 0x03, 0xF0, 0x0D, 0xC0, 0x28, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0xD5, 0x05, 0x74, 0x14, 0x10,
+0x07, 0xC0, 0xB2, 0x00, 0xD1, 0x00, 0x74, 0x28, 0xD0, 0x0D, 0x40, 0x37, 0x00,
+0xF1, 0x00, 0x7C, 0x06, 0xD1, 0x0D, 0x43, 0x25, 0x00, 0xF5, 0x00, 0x54, 0x2F,
+0xD0, 0x0F, 0x40, 0x7C, 0x00, 0x51, 0x11, 0x7C, 0x02, 0x10, 0x1F, 0x40, 0x37,
+0x00, 0xD1, 0x04, 0x2C, 0x2F, 0xD0, 0x0F, 0x50, 0x4C, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0xA0, 0x26, 0x00, 0xC1, 0x01, 0x34, 0x0C, 0x18, 0x10,
+0x40, 0x20, 0x04, 0x81, 0x00, 0x34, 0x06, 0xD8, 0x0C, 0x40, 0x23, 0x00, 0xC9,
+0x40, 0x14, 0x0C, 0xD0, 0x04, 0x70, 0x20, 0x40, 0xC1, 0x00, 0x04, 0x03, 0xD8,
+0x0C, 0x40, 0x71, 0x00, 0xC1, 0x00, 0x34, 0x02, 0x18, 0x1C, 0x40, 0x33, 0x00,
+0x88, 0x80, 0x14, 0x07, 0xD0, 0x0C, 0x40, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0F, 0x80, 0x68, 0x00, 0xE1, 0x01, 0xB4, 0x24, 0x18, 0x3B, 0x40,
+0x62, 0x00, 0xA0, 0x01, 0xB4, 0x45, 0xD8, 0x1E, 0x42, 0x6B, 0x60, 0xE1, 0x03,
+0xA4, 0x26, 0xD0, 0x14, 0x40, 0x6D, 0x00, 0xE5, 0x01, 0x94, 0x07, 0xD0, 0x1E,
+0x40, 0x79, 0x00, 0xE1, 0x01, 0xF4, 0x06, 0x10, 0x1E, 0x40, 0x7F, 0x40, 0x49,
+0x81, 0xB4, 0x47, 0xD0, 0x1E, 0x40, 0x7C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x10, 0x30, 0x08, 0xC3, 0x08, 0x7C, 0x20, 0x30, 0x00, 0x40, 0xA1,
+0x40, 0xC3, 0x00, 0x3C, 0x03, 0xF0, 0x0C, 0xC0, 0x23, 0x00, 0xCF, 0x00, 0x1C,
+0x03, 0xF0, 0x84, 0x42, 0x20, 0x02, 0xC3, 0x00, 0x0C, 0x43, 0xF0, 0x0D, 0x48,
+0x31, 0x44, 0xC3, 0x88, 0x3E, 0x02, 0x71, 0x0C, 0xC1, 0x33, 0x00, 0x0B, 0x00,
+0x1C, 0x01, 0xF0, 0x8C, 0xC0, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x20, 0xC4, 0x8B, 0xC0, 0x1F, 0x02,
+0xFF, 0x00, 0xFC, 0x23, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xF7, 0x10, 0xFC, 0x03,
+0xA0, 0x87, 0xC0, 0x2E, 0x10, 0xFB, 0x00, 0xEC, 0x03, 0xF0, 0x0F, 0xC0, 0x3A,
+0x02, 0x7F, 0x08, 0xDC, 0x22, 0xF4, 0x8F, 0xC0, 0x2F, 0x42, 0xF7, 0x00, 0xCE,
+0x03, 0xF0, 0x0F, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA0, 0x37, 0x00, 0xDF, 0x00, 0x7E, 0x04, 0x30, 0x01, 0xC0, 0x2C, 0x01, 0x93,
+0x00, 0xEC, 0x07, 0x30, 0x0D, 0xC0, 0x26, 0x00, 0xDF, 0x00, 0x1C, 0x02, 0x30,
+0x05, 0xC0, 0x26, 0x00, 0xFF, 0x00, 0x4C, 0x03, 0xF0, 0x8D, 0xE0, 0x37, 0x00,
+0xD3, 0x00, 0x7C, 0x02, 0xF0, 0x1D, 0xC0, 0x34, 0x00, 0x13, 0x81, 0x4C, 0x07,
+0x34, 0x0F, 0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x88,
+0x39, 0x00, 0xED, 0x00, 0xB6, 0x00, 0x12, 0x62, 0xC0, 0x38, 0x04, 0xE1, 0x00,
+0xF4, 0x03, 0x10, 0x0E, 0x40, 0x2B, 0x00, 0xFB, 0x01, 0x84, 0x02, 0x10, 0x06,
+0x40, 0x3B, 0x00, 0xFD, 0x01, 0x85, 0x03, 0xD0, 0x4E, 0x40, 0x3B, 0x00, 0xE1,
+0x40, 0xB4, 0x02, 0xD0, 0x0E, 0x40, 0x38, 0x00, 0xE1, 0x00, 0xAD, 0x03, 0x10,
+0x1E, 0x40, 0x4F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79,
+0x00, 0xED, 0x01, 0xB4, 0x86, 0x12, 0x13, 0x40, 0x60, 0x00, 0xED, 0x21, 0xB4,
+0x0F, 0xD0, 0x1E, 0x40, 0x73, 0x00, 0xE5, 0x05, 0xD4, 0x07, 0xD9, 0x16, 0x41,
+0x6B, 0x00, 0xED, 0x21, 0xA4, 0x07, 0x50, 0x1E, 0x40, 0x72, 0x20, 0xE1, 0x03,
+0xB4, 0x06, 0xD0, 0x1C, 0x40, 0x7E, 0x00, 0x25, 0x03, 0x84, 0x07, 0x10, 0x1E,
+0x40, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x73, 0x02,
+0xCD, 0x00, 0x34, 0x03, 0x10, 0x48, 0x06, 0x52, 0x00, 0xC9, 0x00, 0x34, 0xCF,
+0x90, 0x0C, 0x40, 0x73, 0x00, 0xC9, 0x00, 0x04, 0x13, 0x90, 0x7C, 0x40, 0x23,
+0x00, 0xDD, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x49, 0x01, 0x34,
+0x02, 0xD0, 0x0C, 0x40, 0x70, 0x00, 0xC5, 0x04, 0x24, 0x4B, 0x10, 0x0C, 0x40,
+0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x55, 0x00, 0x5F,
+0x00, 0xFC, 0x49, 0x34, 0x47, 0xD0, 0x5C, 0x41, 0x5F, 0x11, 0xFC, 0x01, 0xF4,
+0x05, 0xC0, 0x57, 0x00, 0x57, 0x00, 0xDC, 0x01, 0xE0, 0x27, 0xE0, 0x17, 0x00,
+0x5F, 0x00, 0x6E, 0x81, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x63, 0x01, 0x3C, 0x15,
+0xF2, 0x05, 0xF0, 0x54, 0x01, 0x77, 0x03, 0xC4, 0x1D, 0x30, 0x05, 0xC0, 0x5F,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x02,
+0x7C, 0xC0, 0xF0, 0x01, 0xC0, 0x85, 0x00, 0x17, 0x00, 0x7C, 0x08, 0x72, 0x01,
+0xC0, 0x07, 0x02, 0x1F, 0x02, 0x7C, 0x00, 0x74, 0x01, 0xC0, 0x07, 0x02, 0x1F,
+0x40, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x17, 0x00, 0x7C, 0x00, 0xF0,
+0x21, 0xE0, 0x07, 0x40, 0x1A, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC8, 0x4B, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x93, 0x02, 0x7C,
+0x02, 0xF0, 0x08, 0xC0, 0x20, 0x00, 0x83, 0x03, 0x6C, 0x06, 0xF0, 0x09, 0xC0,
+0x23, 0x40, 0x91, 0x00, 0x04, 0x26, 0x34, 0x09, 0x00, 0x27, 0x00, 0x9F, 0x00,
+0x68, 0x06, 0xD0, 0x09, 0xE0, 0xE7, 0x08, 0x93, 0x45, 0x4C, 0x06, 0x32, 0x09,
+0xC0, 0x27, 0x08, 0x93, 0x00, 0x7C, 0x22, 0xF0, 0x09, 0xC0, 0x43, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x22, 0x40, 0x91, 0x01, 0x74, 0x82,
+0xD0, 0x09, 0x40, 0xA4, 0x04, 0x91, 0x01, 0x44, 0x36, 0xD0, 0x09, 0x40, 0x27,
+0x00, 0x95, 0x12, 0x6C, 0x0A, 0x10, 0x19, 0x42, 0x27, 0x00, 0x9D, 0x20, 0x44,
+0x06, 0xF0, 0x09, 0x40, 0x63, 0x01, 0x9B, 0x01, 0x44, 0x06, 0xB0, 0x29, 0x44,
+0x23, 0x40, 0x93, 0x0E, 0x5C, 0x1E, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x20, 0x91, 0x00, 0x54, 0x06, 0xD2,
+0x09, 0x40, 0x24, 0x00, 0x91, 0x00, 0x64, 0x02, 0xD0, 0x09, 0x40, 0x25, 0x00,
+0x8D, 0x01, 0x74, 0x02, 0x50, 0x89, 0x64, 0x27, 0x00, 0x9D, 0x00, 0x75, 0x12,
+0xD2, 0x09, 0x00, 0x27, 0x80, 0x91, 0x00, 0x45, 0x12, 0x50, 0x89, 0x41, 0x27,
+0x00, 0x99, 0x00, 0x74, 0x02, 0xD2, 0x09, 0x44, 0x63, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x22, 0x24, 0x00, 0x81, 0x00, 0x34, 0x12, 0xD0, 0x48,
+0x50, 0x20, 0x01, 0x81, 0x84, 0x04, 0x02, 0xD8, 0x08, 0x40, 0x23, 0x01, 0x89,
+0x04, 0x34, 0x13, 0x00, 0x48, 0x60, 0x23, 0x20, 0x8D, 0x04, 0x14, 0x02, 0x50,
+0xC8, 0x40, 0x23, 0x01, 0x89, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x40, 0x27, 0x00,
+0x81, 0x04, 0x34, 0x12, 0xD0, 0x48, 0x48, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xB0, 0x86, 0x02, 0x53, 0x0A, 0x1C, 0x28, 0xF0, 0x05, 0x50,
+0x04, 0x40, 0x13, 0x00, 0x6C, 0x08, 0xF0, 0x01, 0xC4, 0x87, 0x02, 0x1D, 0x0A,
+0x7C, 0x28, 0x50, 0x01, 0xC0, 0x07, 0x00, 0x1D, 0x0A, 0x7C, 0x80, 0xC2, 0x61,
+0x40, 0x07, 0x05, 0x13, 0x00, 0x4C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1B,
+0x8A, 0x38, 0x28, 0xF0, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0xB8, 0x2F, 0x00, 0x9F, 0x00, 0xFC, 0x22, 0xF2, 0x8A, 0xD0, 0x2F,
+0x02, 0xBF, 0x08, 0xFC, 0x62, 0xF0, 0x09, 0xC0, 0x2F, 0x02, 0x97, 0x08, 0xEC,
+0x22, 0xF2, 0x8B, 0xC0, 0x2F, 0x00, 0x9B, 0x08, 0x6C, 0x02, 0xF0, 0x29, 0xCA,
+0x27, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xB0, 0x89, 0xC2, 0x2B, 0x00, 0xA7, 0x08,
+0xDC, 0x22, 0xF0, 0x89, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0xA0, 0x27, 0x00, 0xBF, 0x08, 0xFC, 0x02, 0x30, 0x0B, 0xC0, 0x2C, 0x00,
+0xBF, 0x04, 0xFC, 0x52, 0xB0, 0x0B, 0xC0, 0x27, 0x40, 0xBB, 0x00, 0xC8, 0x22,
+0x34, 0x4B, 0xC0, 0x24, 0x00, 0xBF, 0x0C, 0xDD, 0x02, 0xB0, 0x19, 0xC0, 0x6F,
+0x00, 0xB3, 0x00, 0xFC, 0x02, 0xF0, 0x5B, 0xC0, 0x20, 0x00, 0xB3, 0x00, 0xCC,
+0x22, 0x30, 0x4B, 0xC0, 0x67, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
+0x08, 0x07, 0x01, 0x1D, 0x04, 0x36, 0xC9, 0x10, 0x05, 0xE2, 0x04, 0x02, 0x1D,
+0x00, 0x74, 0x10, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x13, 0x00, 0x54, 0x20, 0x18,
+0x01, 0xE0, 0x06, 0x80, 0x0D, 0x0C, 0x44, 0x00, 0x50, 0x11, 0x40, 0x07, 0x02,
+0x11, 0x00, 0x74, 0x00, 0xD0, 0xA1, 0x40, 0x04, 0x00, 0x11, 0x10, 0x44, 0x20,
+0x10, 0x01, 0x40, 0x73, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0,
+0x23, 0x05, 0x8D, 0x04, 0x34, 0xB2, 0x10, 0x88, 0x40, 0x20, 0x00, 0x8D, 0x08,
+0x34, 0x52, 0xD0, 0x08, 0x42, 0x23, 0x00, 0x85, 0x00, 0x04, 0x02, 0x54, 0x88,
+0x42, 0x22, 0x00, 0x8D, 0x04, 0x14, 0x02, 0x10, 0x68, 0x41, 0x23, 0x00, 0x81,
+0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x26, 0x10, 0x85, 0x48, 0x04, 0x07, 0x14,
+0x88, 0x40, 0x4B, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25,
+0x00, 0x9D, 0x00, 0x74, 0x06, 0x14, 0x09, 0x40, 0x26, 0x04, 0x9D, 0x01, 0x74,
+0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x89, 0x00, 0x54, 0x52, 0x10, 0x09, 0x40,
+0x26, 0x01, 0x9D, 0x00, 0x44, 0x02, 0x52, 0x09, 0x40, 0x27, 0x40, 0x91, 0x08,
+0x74, 0x12, 0xD0, 0x0D, 0x40, 0x66, 0x40, 0x95, 0x04, 0x04, 0x06, 0x10, 0x09,
+0x40, 0x63, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00,
+0x9F, 0x00, 0x74, 0x0E, 0x30, 0x29, 0x50, 0xE4, 0x00, 0x9F, 0x01, 0x7C, 0x46,
+0xF0, 0x09, 0xC0, 0x67, 0x00, 0x97, 0x00, 0x4C, 0x02, 0x50, 0x09, 0x41, 0x26,
+0x80, 0x9D, 0x00, 0x5C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x92, 0x03, 0x7C,
+0x06, 0xF2, 0x09, 0xD0, 0x22, 0x00, 0x97, 0x07, 0x4D, 0x02, 0x30, 0x09, 0xC0,
+0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0x65, 0x02, 0x9F,
+0x10, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x05, 0x9F, 0x00, 0x7C, 0x4E, 0xF0,
+0x09, 0xC0, 0x67, 0x02, 0x97, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0, 0x67, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0x70, 0x09, 0x80, 0x23, 0x00, 0x9F, 0x00, 0x7C, 0x06,
+0xF0, 0x08, 0xC0, 0x25, 0x00, 0x9B, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0x5B,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00,
+0x7C, 0x18, 0x94, 0x31, 0x50, 0x06, 0x40, 0x13, 0x00, 0x7C, 0x20, 0x70, 0x01,
+0xC0, 0x07, 0x00, 0x1D, 0x48, 0x78, 0x48, 0x32, 0x21, 0xC0, 0x07, 0x00, 0x1F,
+0x00, 0x4C, 0x40, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1B, 0x00, 0x7C, 0x00, 0xF0,
+0x41, 0xC0, 0x07, 0x00, 0x03, 0x02, 0x4C, 0x04, 0x30, 0x01, 0xC0, 0x50, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x14, 0x00, 0x7D, 0x04, 0xF4,
+0x01, 0x30, 0x46, 0x40, 0x5C, 0x00, 0x51, 0x11, 0xF4, 0x09, 0x70, 0x55, 0x40,
+0x17, 0x00, 0x7D, 0x00, 0xF4, 0x09, 0x10, 0x14, 0x40, 0x17, 0x00, 0x5D, 0x00,
+0x84, 0x41, 0x70, 0x05, 0x40, 0x1F, 0x01, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x27,
+0x40, 0x17, 0x00, 0x72, 0x00, 0xC4, 0x01, 0x14, 0x05, 0xC1, 0x52, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x03, 0x74, 0x03,
+0x10, 0x1C, 0x60, 0xB0, 0x00, 0xC1, 0x00, 0x34, 0x0B, 0x58, 0x0C, 0x40, 0x37,
+0x00, 0x8D, 0x01, 0x74, 0x09, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xDD, 0x01, 0x14,
+0x8F, 0xD0, 0x0C, 0x40, 0xF3, 0x01, 0x89, 0x00, 0x34, 0x03, 0xD0, 0x24, 0x40,
+0x33, 0x80, 0x49, 0x0D, 0x04, 0x02, 0x12, 0x18, 0x00, 0x50, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x01, 0xA9, 0x00, 0xB4, 0x18, 0x10,
+0x02, 0x40, 0x70, 0x04, 0xE1, 0x00, 0xB4, 0x01, 0x50, 0x0E, 0x40, 0x3A, 0x01,
+0x29, 0x00, 0xA4, 0x00, 0x14, 0x0A, 0x41, 0x3B, 0x00, 0xED, 0x02, 0x84, 0x03,
+0x40, 0x4E, 0x40, 0x2B, 0x00, 0xAD, 0x00, 0xB4, 0x03, 0xD0, 0x06, 0x41, 0x3F,
+0x00, 0x61, 0x00, 0x84, 0x02, 0x10, 0x18, 0x40, 0x16, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x10, 0x78, 0x01, 0xAD, 0x01, 0xBC, 0x0E, 0x30, 0x14,
+0xD0, 0x78, 0x00, 0xE3, 0x41, 0xBE, 0x07, 0x70, 0x1E, 0xC0, 0x7B, 0x01, 0x6D,
+0x01, 0x3C, 0x05, 0x30, 0x1A, 0xC0, 0x7B, 0x00, 0xEF, 0x01, 0x9D, 0x07, 0xD0,
+0x5E, 0xC2, 0x7B, 0x00, 0xAB, 0x01, 0xB4, 0x06, 0xF0, 0x16, 0xC0, 0x7B, 0x00,
+0xF9, 0x01, 0x8D, 0x07, 0x30, 0x1A, 0xC4, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xB8, 0xB5, 0x00, 0xBF, 0x00, 0x7C, 0x00, 0x70, 0x01, 0xC0,
+0x17, 0x00, 0xDF, 0x00, 0x7E, 0x03, 0xC0, 0x0D, 0xC0, 0x77, 0x00, 0x5F, 0x00,
+0xFC, 0x00, 0xF0, 0x09, 0x80, 0x37, 0x00, 0xDF, 0x02, 0x7C, 0x03, 0x70, 0x8D,
+0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x05, 0xC0, 0x37, 0x40, 0xDF,
+0x00, 0x3C, 0x00, 0xF4, 0x09, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xA0, 0xFF, 0x04, 0xB3, 0x01, 0xFC, 0x23, 0x38, 0x03, 0xC0, 0x6C,
+0x00, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0x40, 0x7F, 0x06, 0xF3, 0x01, 0xCC,
+0x85, 0x30, 0x1B, 0xE0, 0x7F, 0x02, 0xAF, 0x03, 0xCC, 0x06, 0xF0, 0x1F, 0xC0,
+0x4F, 0x00, 0xBF, 0x01, 0xFC, 0x07, 0xF0, 0x16, 0xC0, 0x7C, 0x40, 0xFB, 0x81,
+0xFC, 0x06, 0x31, 0x1A, 0xC0, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x88, 0x3D, 0x00, 0xA1, 0x00, 0xB4, 0x13, 0x18, 0x42, 0x00, 0x28, 0x40,
+0xE1, 0x50, 0xB4, 0x01, 0xD0, 0x0E, 0x40, 0x3F, 0x00, 0x6F, 0x00, 0x94, 0x02,
+0x10, 0x0A, 0xC0, 0x3B, 0x00, 0xED, 0x24, 0x84, 0x03, 0xD0, 0x8E, 0x40, 0x1B,
+0x00, 0xAD, 0x00, 0xB4, 0x23, 0xD0, 0x06, 0xC0, 0x38, 0x00, 0xE1, 0x00, 0xB4,
+0x02, 0x10, 0x0A, 0x40, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+0x00, 0x39, 0x00, 0x21, 0x00, 0xB4, 0x22, 0x18, 0x83, 0x40, 0x20, 0x00, 0xE9,
+0x08, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x40, 0x61, 0x00, 0x04, 0x01, 0x90,
+0x0A, 0x40, 0x3B, 0x20, 0xAD, 0x40, 0xA4, 0x03, 0xD0, 0x0E, 0x40, 0x2B, 0x00,
+0xAD, 0x00, 0xB4, 0x02, 0xD0, 0x06, 0x40, 0x3D, 0x00, 0xE1, 0x00, 0x34, 0x0B,
+0x10, 0x0A, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28,
+0x33, 0x00, 0x11, 0x00, 0x34, 0x02, 0x12, 0x20, 0x40, 0x00, 0x00, 0xC9, 0x00,
+0x34, 0x26, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x4D, 0x00, 0x14, 0x00, 0x90, 0x28,
+0x40, 0x71, 0x00, 0xCD, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x02, 0x24, 0x02, 0xD0, 0x04, 0x40, 0x30, 0x10, 0x81, 0x02, 0x34, 0x03, 0x11,
+0x08, 0x40, 0x19, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x3D,
+0x40, 0x93, 0x00, 0xFC, 0x03, 0x14, 0x21, 0xC0, 0xE4, 0x02, 0xDB, 0x01, 0x74,
+0x2A, 0xF0, 0x0C, 0xC0, 0x3F, 0x00, 0x93, 0x00, 0x4C, 0x01, 0xB4, 0x09, 0x40,
+0x37, 0x00, 0x9F, 0x00, 0x6D, 0x01, 0xF0, 0x0F, 0xC0, 0x37, 0x00, 0x8F, 0x13,
+0x7C, 0x02, 0xF0, 0x04, 0xC0, 0x34, 0x00, 0x53, 0x0B, 0x7C, 0x82, 0x30, 0x0D,
+0xC0, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00,
+0x9F, 0x00, 0x7C, 0x20, 0xF0, 0x00, 0xD0, 0xE7, 0x10, 0xD7, 0x00, 0x7C, 0x80,
+0xF0, 0x0D, 0xC0, 0x37, 0x00, 0x17, 0x00, 0x3C, 0x40, 0x70, 0x09, 0xC0, 0x37,
+0x02, 0x9F, 0x00, 0x5C, 0x83, 0xF2, 0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C,
+0x02, 0xF0, 0x05, 0xC0, 0x75, 0x00, 0x47, 0x81, 0x7C, 0x02, 0xF0, 0x0D, 0xC0,
+0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x3F, 0x00, 0xBF,
+0x00, 0x8C, 0x23, 0xB0, 0x03, 0xD1, 0x28, 0x00, 0xB3, 0x05, 0xFC, 0x00, 0xF0,
+0x0F, 0xC0, 0x38, 0x00, 0x6B, 0x00, 0xCC, 0x00, 0xB0, 0x8B, 0xE1, 0x3F, 0x00,
+0xBF, 0x00, 0xCC, 0x01, 0xF0, 0x0F, 0xC0, 0x4F, 0x00, 0xBF, 0x14, 0xDC, 0x0F,
+0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0xF3, 0x00, 0x8C, 0x22, 0x10, 0x9F, 0xC0, 0x07,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x36, 0x00, 0x9D, 0x01,
+0x44, 0x04, 0x90, 0x11, 0x58, 0x44, 0x04, 0x91, 0x00, 0x76, 0x04, 0xD0, 0x0D,
+0xE0, 0x36, 0x00, 0x51, 0x00, 0x44, 0x04, 0x10, 0x09, 0xC0, 0x36, 0x00, 0x9D,
+0x00, 0x6C, 0x47, 0xD0, 0x0D, 0x40, 0x97, 0x02, 0xDD, 0x01, 0x6C, 0x07, 0xD0,
+0x3D, 0xC0, 0x32, 0x00, 0xD1, 0x01, 0x44, 0x04, 0x10, 0x1D, 0xC2, 0x25, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x10, 0x9D, 0x01, 0x44,
+0x03, 0x90, 0x11, 0x40, 0x46, 0x40, 0xD1, 0x00, 0x74, 0x0E, 0xD1, 0x19, 0x42,
+0x34, 0x00, 0xD9, 0x00, 0x44, 0x05, 0x9A, 0x09, 0x40, 0x37, 0x20, 0x8D, 0x08,
+0x46, 0x07, 0xD0, 0x0D, 0x42, 0x17, 0x04, 0x9D, 0x00, 0x54, 0x02, 0xD0, 0x1D,
+0x40, 0x34, 0x00, 0xD1, 0x01, 0x40, 0x02, 0x50, 0x09, 0x40, 0x07, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x8D, 0x00, 0x04, 0x03,
+0x90, 0x10, 0x40, 0x02, 0x00, 0xC1, 0x00, 0x34, 0x00, 0xD2, 0x08, 0x40, 0x32,
+0x00, 0x41, 0x00, 0x04, 0x02, 0x10, 0x08, 0x60, 0x31, 0x00, 0x8D, 0x00, 0x05,
+0x03, 0xD8, 0x0C, 0x40, 0x03, 0x00, 0xDD, 0x00, 0x04, 0x02, 0xD0, 0x0C, 0x48,
+0x36, 0x00, 0xC1, 0x00, 0x04, 0x02, 0x50, 0x08, 0x40, 0x41, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0xB0, 0x3E, 0x00, 0x1F, 0x00, 0x05, 0x03, 0xB0,
+0x01, 0xC0, 0x06, 0x00, 0xD3, 0x00, 0x74, 0x02, 0xF0, 0x09, 0x40, 0x34, 0x00,
+0x4B, 0x00, 0x4C, 0x00, 0xB0, 0x09, 0x44, 0x37, 0x00, 0xBF, 0x00, 0x44, 0x03,
+0xF0, 0x0D, 0xC0, 0x07, 0x00, 0x9F, 0x00, 0x54, 0x03, 0xF0, 0x0D, 0xC0, 0x34,
+0x00, 0xD3, 0x00, 0x4D, 0x02, 0x70, 0x09, 0xC0, 0x07, 0xC0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0x78, 0x02,
+0xC0, 0x0D, 0x00, 0xFF, 0x40, 0xF6, 0x02, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0x7F,
+0x00, 0xFD, 0x00, 0xF0, 0x0B, 0xC8, 0x3E, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC0, 0x1F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x3B, 0x00,
+0xFF, 0x00, 0xFC, 0x02, 0xB0, 0x0B, 0xC0, 0x15, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x7F, 0x02, 0xF3, 0x01, 0xFC, 0x27, 0xF0, 0x1F, 0xC0,
+0x7F, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0x09,
+0xCC, 0x07, 0xF0, 0x3F, 0xC0, 0x7C, 0x02, 0xFF, 0x21, 0xCC, 0x07, 0x30, 0x9F,
+0xC0, 0x78, 0x00, 0xF3, 0x01, 0xFC, 0x22, 0xF0, 0x3F, 0xC0, 0x5E, 0x10, 0xBB,
+0x01, 0xEC, 0x84, 0x38, 0x0B, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x07, 0x00, 0x11, 0x01, 0x74, 0x10, 0xD1, 0x01, 0x40, 0x47,
+0x00, 0x11, 0x04, 0x74, 0x04, 0xD0, 0x11, 0x40, 0x47, 0x00, 0x1D, 0x04, 0x44,
+0x84, 0xD0, 0x01, 0x48, 0x04, 0x01, 0x1D, 0x01, 0x44, 0x04, 0x12, 0x41, 0x40,
+0x44, 0x40, 0x11, 0x01, 0x74, 0x38, 0xD0, 0x0D, 0x40, 0x55, 0x00, 0xD1, 0x01,
+0x54, 0x03, 0xB0, 0x01, 0x40, 0x0D, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0xA0, 0x33, 0x11, 0xC1, 0x00, 0x34, 0x83, 0xD0, 0x4C, 0x41, 0x37, 0x00,
+0xC1, 0x10, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xDD, 0x00, 0x04, 0x03,
+0xD0, 0x4D, 0x40, 0x30, 0x01, 0xD5, 0xA0, 0x64, 0x83, 0x10, 0x4C, 0x40, 0x35,
+0x00, 0xC9, 0x00, 0x34, 0x10, 0xD0, 0x4C, 0x40, 0x30, 0x60, 0xD9, 0x40, 0x24,
+0x01, 0x10, 0x08, 0x44, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA8, 0x05, 0x40, 0x11, 0x00, 0x74, 0x00, 0xD2, 0x01, 0x40, 0x07, 0x00, 0x11,
+0x00, 0x74, 0x00, 0xD1, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x00, 0x44, 0x00, 0xD0,
+0x01, 0x48, 0x04, 0x00, 0x1D, 0x00, 0x64, 0x00, 0x10, 0x01, 0x40, 0x04, 0x20,
+0x19, 0x00, 0x74, 0x0C, 0xD0, 0x1C, 0x40, 0x75, 0x00, 0xD1, 0x01, 0x54, 0x0B,
+0x15, 0x19, 0x41, 0x0D, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0,
+0x37, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x33, 0x00, 0xD3, 0x00,
+0x7C, 0x03, 0xD0, 0x0D, 0xC0, 0x37, 0x00, 0xCF, 0x00, 0x4C, 0x03, 0xF0, 0x0D,
+0xD0, 0x34, 0x00, 0xD7, 0x00, 0x6C, 0x03, 0x30, 0x0D, 0xD0, 0x34, 0x00, 0xDB,
+0x00, 0x7C, 0x0E, 0xE0, 0x1D, 0xC0, 0xC0, 0x04, 0xCB, 0x01, 0x6C, 0x04, 0x10,
+0x19, 0xC0, 0x20, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x0D,
+0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0x40, 0x0F, 0x00, 0x3F, 0x00, 0xFC,
+0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC4,
+0x0F, 0x00, 0x3F, 0x00, 0xDC, 0x00, 0xF1, 0x03, 0xC8, 0x0F, 0x00, 0x37, 0x40,
+0x7C, 0x42, 0xF0, 0x07, 0xC2, 0x1F, 0x00, 0xFF, 0x00, 0xEC, 0xA4, 0xF0, 0x00,
+0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x75, 0x01,
+0xDF, 0x00, 0x7C, 0x03, 0x30, 0x0D, 0xD0, 0x74, 0x00, 0xD3, 0x00, 0x4D, 0x03,
+0xF0, 0x0D, 0xC8, 0x37, 0x40, 0xD3, 0x00, 0x7C, 0x07, 0x30, 0x8D, 0xC1, 0x37,
+0x14, 0xDF, 0x01, 0x4C, 0x23, 0xF0, 0x0D, 0xC0, 0x76, 0x04, 0xD3, 0x40, 0x6C,
+0x28, 0x30, 0x09, 0xC0, 0x37, 0x01, 0xD3, 0x00, 0x7C, 0xC8, 0x20, 0x29, 0xC6,
+0x28, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x04, 0x00, 0x1D,
+0x0F, 0x74, 0x10, 0x10, 0x11, 0x42, 0x04, 0x00, 0x11, 0x0A, 0x44, 0x00, 0xD0,
+0x01, 0x40, 0x07, 0x00, 0x11, 0x13, 0x74, 0x00, 0x10, 0x00, 0x40, 0xC7, 0x10,
+0x0D, 0x00, 0x34, 0x04, 0xD0, 0x31, 0x40, 0x83, 0x00, 0x11, 0xA5, 0x74, 0x08,
+0x10, 0x05, 0x40, 0x37, 0x00, 0xD1, 0x11, 0x74, 0x0E, 0xB0, 0x09, 0x40, 0x4C,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0xB4, 0x00, 0xCD, 0x03,
+0x34, 0x43, 0x10, 0x6C, 0x40, 0x30, 0x00, 0xC1, 0x01, 0x04, 0x03, 0xD0, 0x0C,
+0x40, 0x73, 0x00, 0xC1, 0x00, 0x14, 0x03, 0x10, 0x2C, 0x44, 0x33, 0x00, 0xCD,
+0x00, 0x34, 0x07, 0xD0, 0x7D, 0x40, 0x33, 0x80, 0xC1, 0x81, 0x34, 0x0E, 0xD0,
+0x0C, 0x40, 0xB3, 0x00, 0xC1, 0x11, 0x64, 0x02, 0x10, 0x00, 0x40, 0x0C, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x48, 0x00, 0x2D, 0x01, 0xF4,
+0x04, 0x10, 0x13, 0x48, 0x4C, 0x00, 0x21, 0x01, 0x84, 0x04, 0xD0, 0x12, 0x40,
+0x4B, 0x04, 0x21, 0x03, 0xF4, 0x04, 0x10, 0x12, 0x40, 0x4B, 0x14, 0x2D, 0x01,
+0xB4, 0x04, 0xD0, 0x12, 0x40, 0x4F, 0x40, 0x21, 0x01, 0xB4, 0x05, 0xD0, 0x1E,
+0x40, 0x7F, 0x00, 0x61, 0x01, 0xB4, 0xA7, 0x90, 0x12, 0x40, 0x3C, 0x20, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x30, 0x92, 0xCF, 0x00, 0x3C, 0x03,
+0x30, 0x0C, 0xC1, 0x30, 0x00, 0xD3, 0x10, 0x0C, 0x23, 0xF0, 0x0C, 0xC0, 0x33,
+0x00, 0xC3, 0x00, 0x1C, 0x03, 0x30, 0x0C, 0xC0, 0x33, 0x00, 0xCF, 0x00, 0x1C,
+0x03, 0xF0, 0x0C, 0xC1, 0x33, 0x20, 0xC1, 0x00, 0x3E, 0x23, 0xF4, 0x0C, 0xC0,
+0x33, 0x80, 0xC3, 0x08, 0x7C, 0x63, 0x30, 0x80, 0xD0, 0x48, 0x40, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x0D, 0x00, 0x3F, 0x00, 0xBC, 0x00, 0xF0,
+0x02, 0xC0, 0x0B, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x83, 0xC0, 0x03, 0x00,
+0x1F, 0x40, 0xBC, 0x20, 0xF2, 0x03, 0xC0, 0x0F, 0x00, 0x1F, 0x00, 0x7C, 0x00,
+0xF0, 0x81, 0xC0, 0x07, 0x02, 0x1F, 0x41, 0xFC, 0xA3, 0x20, 0x8F, 0xC8, 0x3B,
+0x00, 0x7F, 0x00, 0xFC, 0x23, 0xF0, 0x07, 0xC0, 0x0B, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x1D, 0xC0, 0x34, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x1D, 0xD0, 0x74, 0x40, 0xD3, 0x00, 0x7C, 0x03, 0xF0,
+0x1D, 0xD0, 0x30, 0x00, 0xC3, 0x00, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x80,
+0xDF, 0x00, 0x7C, 0x00, 0x30, 0x09, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x32, 0x88, 0x09, 0x00, 0x2D, 0x00, 0xB4, 0x00, 0xD0, 0x02, 0x40,
+0x0B, 0x20, 0x2D, 0x00, 0xB4, 0x00, 0xD0, 0x02, 0x40, 0x08, 0x00, 0x2D, 0x00,
+0xB4, 0x00, 0xD0, 0x03, 0x40, 0x0C, 0x00, 0x21, 0x00, 0xB4, 0x00, 0xD0, 0x03,
+0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x83, 0xD0, 0x06, 0x40, 0x3B, 0x20, 0x6D,
+0x40, 0xF4, 0x01, 0x10, 0x02, 0x40, 0x4F, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x00, 0x79, 0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B,
+0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1F, 0x40, 0x7A, 0x00, 0xED, 0x01, 0xB4,
+0x87, 0xD0, 0x1E, 0x40, 0x7A, 0x00, 0xE1, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40,
+0x78, 0x00, 0xF1, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x20, 0xED, 0x51,
+0xB4, 0x87, 0x10, 0x1E, 0x41, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x28, 0x03, 0x00, 0x0D, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x40, 0x03, 0x00,
+0x0D, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x40, 0x02, 0x10, 0x1D, 0x20, 0x34, 0x00,
+0xD0, 0x00, 0x40, 0x02, 0x00, 0x01, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x40, 0x00,
+0x10, 0x01, 0x00, 0x14, 0x9B, 0xD0, 0x04, 0x42, 0x33, 0x00, 0x4D, 0x01, 0x34,
+0x03, 0x11, 0x2C, 0x41, 0x5B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+0xA0, 0x15, 0x00, 0x4F, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC4, 0x13, 0x00, 0x5F,
+0x00, 0x7C, 0x01, 0xF0, 0x05, 0xD0, 0x16, 0x00, 0x5F, 0x00, 0x74, 0x01, 0xF0,
+0x05, 0xC2, 0x16, 0x00, 0x51, 0x00, 0x3C, 0x01, 0xF0, 0x05, 0xC4, 0x14, 0x40,
+0x53, 0x00, 0xCC, 0x09, 0xD1, 0x87, 0x40, 0x1F, 0x00, 0x7D, 0x01, 0xBC, 0x05,
+0x14, 0x27, 0xC0, 0x5F, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08,
+0x0D, 0x08, 0x3F, 0x00, 0xFC, 0x00, 0xF2, 0x03, 0xC4, 0x0F, 0x00, 0x3F, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0D, 0x20, 0x3F, 0x80, 0xFC, 0x00, 0xB0, 0x03,
+0xC0, 0x0D, 0x00, 0x3F, 0x80, 0xFC, 0x00, 0xF2, 0x03, 0xC4, 0x0F, 0x00, 0x3F,
+0x00, 0x65, 0x20, 0xF0, 0x81, 0xC0, 0x07, 0x02, 0x1F, 0x00, 0x7C, 0x38, 0xF0,
+0x01, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25,
+0x02, 0x9F, 0x00, 0x6C, 0x0E, 0xF0, 0x19, 0xC0, 0x27, 0x00, 0x93, 0x05, 0x7C,
+0x02, 0x30, 0x09, 0xC0, 0x67, 0x02, 0x9F, 0x08, 0x6C, 0x82, 0xF0, 0x49, 0xC0,
+0x67, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x19, 0xC8, 0x27, 0x00, 0x93, 0x05,
+0x0C, 0x02, 0x32, 0x09, 0xC2, 0x27, 0x02, 0x9D, 0x04, 0x5C, 0x02, 0x34, 0x09,
+0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xE6, 0x00,
+0x9D, 0x02, 0x44, 0x0E, 0xD8, 0x29, 0x40, 0x27, 0x00, 0x9B, 0x43, 0x34, 0x02,
+0x10, 0x09, 0x40, 0x27, 0x08, 0x9F, 0x02, 0x44, 0x02, 0xE0, 0x29, 0x40, 0xA7,
+0x00, 0x9D, 0x00, 0x74, 0x02, 0xB0, 0x29, 0x40, 0x23, 0x10, 0x8B, 0x01, 0x44,
+0x16, 0x10, 0x09, 0x48, 0xA7, 0x04, 0x8D, 0x00, 0x6C, 0x4E, 0x10, 0x09, 0x48,
+0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x24, 0x00, 0xBD,
+0x50, 0xE6, 0x02, 0xD0, 0x8B, 0x41, 0x6F, 0x08, 0xB5, 0x40, 0xF4, 0x02, 0x10,
+0x0B, 0x40, 0x2F, 0x00, 0xBD, 0x10, 0xC4, 0x06, 0xC0, 0x0B, 0x40, 0x2F, 0x01,
+0xBD, 0x08, 0xF4, 0x06, 0x10, 0x8B, 0x40, 0x2F, 0x00, 0xB1, 0x00, 0x45, 0x22,
+0x18, 0x09, 0x40, 0x27, 0x00, 0xDC, 0x00, 0x64, 0x06, 0x10, 0x09, 0x40, 0x73,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x68, 0x00, 0xAD, 0x00,
+0x86, 0x86, 0xD0, 0x0A, 0x40, 0x2B, 0x80, 0xA1, 0x01, 0xF4, 0x02, 0x10, 0x0A,
+0x40, 0x2B, 0x00, 0xA5, 0x00, 0x84, 0x02, 0x50, 0x1A, 0x40, 0x6B, 0x00, 0xAD,
+0x00, 0xB4, 0x02, 0x90, 0x1A, 0x40, 0x2B, 0x00, 0xB9, 0x00, 0x04, 0x12, 0x14,
+0x08, 0x40, 0x23, 0x00, 0xCD, 0x00, 0x64, 0x02, 0x10, 0x48, 0x40, 0x53, 0xA0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x86, 0x02, 0x1F, 0x00, 0x6C,
+0x28, 0xD0, 0xA1, 0xC0, 0x07, 0x00, 0x15, 0x4A, 0x7C, 0x00, 0x34, 0x01, 0xC0,
+0x07, 0x00, 0x1D, 0x0A, 0x4D, 0x00, 0xD0, 0xA1, 0xC0, 0x87, 0x02, 0x1F, 0x00,
+0x7C, 0x00, 0x30, 0xA1, 0x40, 0x07, 0x00, 0x33, 0x00, 0x4C, 0x28, 0x30, 0xA1,
+0xC0, 0x07, 0x80, 0x1F, 0x00, 0x7C, 0x28, 0x39, 0xA1, 0xC0, 0x77, 0xC0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x82,
+0xF0, 0x09, 0xC0, 0x27, 0x48, 0x9F, 0x00, 0x7C, 0x02, 0xF1, 0x08, 0xC0, 0x27,
+0x08, 0x9F, 0x40, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF2, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0xFC, 0xA2, 0xF0, 0x0B, 0xC0,
+0x2F, 0x00, 0xBF, 0x20, 0xFC, 0x02, 0xF0, 0x8F, 0xC0, 0x67, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0x30,
+0x0B, 0xC2, 0x2C, 0x00, 0xBF, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x2F, 0x28,
+0xBF, 0x00, 0xDC, 0x02, 0x30, 0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xDC, 0x02,
+0xF0, 0x0B, 0x80, 0x2F, 0x10, 0xBF, 0x00, 0xDC, 0x52, 0x30, 0x88, 0xC2, 0x29,
+0x00, 0xB3, 0x00, 0xDC, 0x02, 0xF0, 0x09, 0xC0, 0x67, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01, 0x11, 0x00, 0x74, 0x40, 0x12, 0x01,
+0x49, 0x04, 0x00, 0x1D, 0x14, 0x74, 0x00, 0xD0, 0x01, 0x48, 0x07, 0x20, 0x17,
+0x10, 0x74, 0x00, 0x50, 0x41, 0x41, 0x07, 0x01, 0x1D, 0x80, 0x74, 0x00, 0xD0,
+0x01, 0x49, 0x07, 0x00, 0x1D, 0x00, 0x74, 0x10, 0x10, 0x41, 0x44, 0x07, 0x00,
+0x11, 0x00, 0x5C, 0x81, 0xD2, 0x41, 0x45, 0x73, 0x60, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x00, 0x21, 0x05, 0x81, 0x60, 0x14, 0x12, 0x14, 0x08, 0x40,
+0x20, 0x00, 0x8D, 0x04, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x33, 0x00, 0x8D, 0x00,
+0x14, 0x03, 0x10, 0x48, 0x40, 0x33, 0x85, 0xCD, 0x00, 0x14, 0x03, 0xD0, 0x08,
+0x40, 0x23, 0x00, 0x8D, 0x00, 0x14, 0x52, 0xD0, 0x48, 0x40, 0x21, 0x00, 0x89,
+0x00, 0x14, 0x02, 0xD9, 0x48, 0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x08, 0x25, 0x00, 0x91, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x50, 0x24,
+0x10, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x95, 0x00, 0x74,
+0x02, 0x51, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x0D, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x74, 0x06, 0xD0, 0x89, 0x40, 0xE7, 0x00, 0x99, 0x01,
+0x50, 0x12, 0xD0, 0x09, 0x60, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x20, 0x25, 0x00, 0x93, 0x80, 0x5C, 0x02, 0x31, 0x09, 0xC2, 0x24, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xE0, 0x27, 0x00, 0x9F, 0x40, 0x5C, 0x02,
+0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x80, 0x5C, 0x12, 0xB4, 0x09, 0xC0, 0xE1, 0x40, 0x9B, 0x01, 0x58,
+0x06, 0xF0, 0x09, 0xC4, 0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x08, 0x25, 0x40, 0x9F, 0x00, 0x7C, 0x02, 0xF3, 0x09, 0x40, 0x27, 0x10, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x09, 0x80, 0x27, 0x00, 0x96, 0x00, 0x70, 0x02, 0x70,
+0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0x27, 0x04,
+0x9F, 0xA0, 0x7C, 0x02, 0x20, 0x09, 0xC0, 0x27, 0x00, 0x96, 0x00, 0x5C, 0x42,
+0xF1, 0x49, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08,
+0x05, 0x06, 0x1F, 0x01, 0x6C, 0x10, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1F, 0x00,
+0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC3, 0x04, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x08, 0x13,
+0x00, 0x4C, 0x00, 0xB0, 0x01, 0xC0, 0x05, 0x08, 0x17, 0x00, 0x6C, 0x28, 0xF0,
+0x21, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x5C,
+0x00, 0x7D, 0x11, 0xC4, 0x0D, 0x72, 0x57, 0x40, 0x14, 0x04, 0x7F, 0x41, 0x44,
+0x01, 0xD0, 0x05, 0x40, 0x17, 0x00, 0x7D, 0x20, 0x34, 0x01, 0x72, 0x07, 0xC9,
+0x1E, 0x02, 0x51, 0x00, 0x74, 0x01, 0x70, 0xD7, 0x00, 0x9F, 0x04, 0x51, 0x01,
+0xC4, 0x15, 0x00, 0x05, 0x40, 0x1C, 0x00, 0x71, 0x05, 0xE4, 0x0D, 0xD0, 0x05,
+0x40, 0x53, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xF6, 0x00,
+0x4D, 0x21, 0x64, 0x2F, 0x50, 0x4D, 0x40, 0x20, 0x20, 0xCD, 0x04, 0x04, 0x03,
+0xD0, 0x0C, 0x40, 0x23, 0x00, 0xCD, 0x0D, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0xB0,
+0x00, 0x89, 0x00, 0x34, 0x02, 0x50, 0x2C, 0x40, 0xF3, 0x00, 0x81, 0x89, 0x44,
+0x13, 0x91, 0x0C, 0x40, 0x01, 0x00, 0x85, 0x01, 0x24, 0x0F, 0xD0, 0x0C, 0x42,
+0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0xED,
+0x01, 0x86, 0x01, 0x50, 0x0E, 0x50, 0x38, 0x00, 0xF5, 0x11, 0x84, 0x03, 0xD0,
+0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x1F, 0x40, 0x5A, 0x40,
+0xE9, 0x00, 0xB4, 0x03, 0x50, 0x0E, 0x40, 0x6B, 0x40, 0xE1, 0x01, 0xC6, 0x03,
+0x10, 0x5F, 0x40, 0x2C, 0x08, 0x61, 0x00, 0xA4, 0x03, 0xD2, 0x4E, 0x60, 0x07,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x78, 0x00, 0xEF, 0x01,
+0xAC, 0x07, 0x70, 0x1F, 0xC0, 0x78, 0x20, 0xED, 0x01, 0x85, 0x07, 0xF0, 0x1E,
+0xC6, 0x7B, 0x00, 0xED, 0x01, 0xBC, 0x07, 0xF0, 0x1F, 0xC0, 0x7C, 0x00, 0xEB,
+0x01, 0xBC, 0x07, 0x70, 0x1E, 0xC0, 0x7B, 0x00, 0xE3, 0x01, 0xCC, 0x05, 0xB0,
+0x9E, 0xC0, 0x79, 0x00, 0x65, 0x41, 0xAC, 0x04, 0xF0, 0x5E, 0xC0, 0x47, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0xCF, 0x00, 0x7C,
+0x01, 0x71, 0x0D, 0xC4, 0x37, 0x00, 0xCF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0x40,
+0x37, 0x00, 0xDF, 0x40, 0x7C, 0x03, 0x70, 0x0D, 0xC0, 0x17, 0x10, 0xD7, 0x80,
+0x7C, 0x83, 0x70, 0x0D, 0xC0, 0x23, 0x00, 0xCF, 0x00, 0x7C, 0x01, 0xF0, 0x8D,
+0xC0, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x00, 0xF0, 0x8D, 0xC0, 0x43, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x5D, 0x00, 0xFF, 0x01, 0xCC, 0x13,
+0xF0, 0x5F, 0xC0, 0x7B, 0x62, 0x73, 0x41, 0xBC, 0x07, 0x30, 0x1F, 0xC0, 0x7F,
+0x00, 0xF3, 0x01, 0xFC, 0x27, 0xF0, 0x17, 0xC0, 0x78, 0x00, 0xFB, 0x09, 0xEC,
+0x27, 0x30, 0x1E, 0xC0, 0x78, 0x00, 0xF3, 0x00, 0xFC, 0x07, 0xF0, 0x1F, 0xC0,
+0x4C, 0x00, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x08, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x19, 0x16, 0xED, 0x00, 0x84, 0x01, 0xD0,
+0x06, 0x40, 0x3B, 0x06, 0x65, 0x00, 0xB4, 0x03, 0x10, 0x8E, 0x40, 0x3B, 0x02,
+0x61, 0x08, 0xB4, 0x03, 0xD2, 0x47, 0x40, 0x38, 0x00, 0xE1, 0x08, 0x84, 0x03,
+0x10, 0x0E, 0x40, 0x38, 0x04, 0xE5, 0x08, 0xB4, 0x29, 0xD0, 0x0F, 0x40, 0x29,
+0x02, 0x6D, 0x00, 0xB4, 0x22, 0xD0, 0x0E, 0xC0, 0x56, 0x60, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0xFD, 0x00, 0x84, 0x23, 0xD0, 0x4E,
+0x48, 0x3B, 0x12, 0x60, 0x00, 0xF4, 0x03, 0x10, 0x2E, 0x40, 0x3F, 0x00, 0xE1,
+0x00, 0xB4, 0x03, 0xC1, 0x06, 0x60, 0x9C, 0x00, 0xF1, 0x80, 0xC6, 0x03, 0x10,
+0x87, 0x40, 0xB8, 0x00, 0xE1, 0x08, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x38, 0x00,
+0x6D, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x40, 0x60, 0x08, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x28, 0x01, 0x00, 0xCD, 0x12, 0x44, 0x2C, 0xD0, 0xA8, 0x40,
+0xB3, 0x04, 0x11, 0x03, 0x34, 0x0B, 0x10, 0x0C, 0x40, 0xB3, 0x04, 0x91, 0x03,
+0x34, 0x0B, 0x90, 0x20, 0x40, 0x00, 0x00, 0xC1, 0x02, 0x04, 0x0B, 0x10, 0x08,
+0x41, 0x30, 0x40, 0xC5, 0x01, 0x74, 0x40, 0xD0, 0x1C, 0x40, 0x31, 0x10, 0x4D,
+0x0A, 0x30, 0x02, 0xC1, 0x2D, 0x48, 0x1A, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA0, 0x61, 0x00, 0xCF, 0x00, 0x4C, 0x22, 0xF0, 0x21, 0xC0, 0xF7,
+0x00, 0x93, 0x11, 0x7C, 0x0B, 0x34, 0x5C, 0xC0, 0x33, 0x00, 0x13, 0x01, 0x7C,
+0x23, 0xF0, 0x79, 0xD0, 0x64, 0x01, 0xC3, 0x08, 0x4C, 0x23, 0x30, 0x51, 0xC0,
+0x34, 0x00, 0xD3, 0x00, 0x7C, 0x06, 0xF0, 0x5F, 0xC0, 0x10, 0x20, 0xCF, 0x23,
+0x7C, 0x08, 0xC0, 0xBF, 0x80, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x08, 0x27, 0x20, 0xDF, 0x01, 0x7C, 0x02, 0xF1, 0x21, 0xC8, 0x37, 0x00,
+0x9F, 0x02, 0x7C, 0x23, 0xF1, 0x0D, 0xC0, 0x77, 0x00, 0x1F, 0x1A, 0x7C, 0x07,
+0xF0, 0x29, 0xC8, 0x87, 0x00, 0xDF, 0x01, 0x7C, 0x07, 0xF0, 0x21, 0xC0, 0x87,
+0x00, 0xDF, 0x08, 0x7C, 0x22, 0xF0, 0x0D, 0xC0, 0x37, 0x02, 0x5F, 0x04, 0x7C,
+0x3A, 0xF1, 0x8D, 0xC0, 0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x08, 0x0F, 0x00, 0xF3, 0x00, 0xCC, 0x00, 0x30, 0x03, 0xC1, 0x7C, 0x08, 0x3F,
+0x90, 0xCC, 0x43, 0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0x33, 0x00, 0xCC, 0x07, 0x30,
+0x03, 0xC1, 0x2F, 0x00, 0xFF, 0x00, 0xCC, 0x07, 0xF0, 0x03, 0xC0, 0x3F, 0x00,
+0xFF, 0x12, 0xFC, 0x00, 0x30, 0x0F, 0xC1, 0x7F, 0x01, 0x73, 0x01, 0xCC, 0x00,
+0xF1, 0x0D, 0xC0, 0x14, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20,
+0xE6, 0x09, 0xD0, 0x01, 0x44, 0x04, 0x12, 0x30, 0x42, 0x34, 0x08, 0x9D, 0x03,
+0x4C, 0x03, 0xD0, 0x0D, 0x60, 0x34, 0x00, 0x11, 0x25, 0x04, 0x07, 0x12, 0x39,
+0x40, 0xC7, 0x00, 0xDD, 0x80, 0x6C, 0x03, 0xD0, 0x11, 0x40, 0x87, 0x00, 0xDD,
+0x01, 0x70, 0x0C, 0x10, 0x0D, 0x40, 0x37, 0x00, 0x51, 0x08, 0x7D, 0x4C, 0xD2,
+0x0D, 0x4C, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x66,
+0x00, 0xD1, 0x01, 0x44, 0x06, 0x98, 0x19, 0x40, 0x36, 0x01, 0x9D, 0x11, 0x64,
+0x03, 0xD0, 0x0D, 0x40, 0x74, 0x00, 0x90, 0x01, 0x44, 0x23, 0x10, 0x19, 0x41,
+0x67, 0x04, 0xDD, 0x04, 0x54, 0xA3, 0xD1, 0x19, 0x40, 0x37, 0x04, 0xDD, 0x00,
+0x74, 0x06, 0x18, 0x0D, 0x40, 0x17, 0x00, 0xD1, 0x00, 0x44, 0x04, 0xD0, 0x0D,
+0x58, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x24, 0x00,
+0x91, 0x01, 0x04, 0x02, 0x94, 0x01, 0x50, 0x32, 0x00, 0x8D, 0x00, 0x04, 0x03,
+0xD0, 0x0D, 0x40, 0x34, 0x00, 0x01, 0x00, 0x45, 0x03, 0x10, 0x08, 0x40, 0x23,
+0x00, 0xCD, 0x00, 0x24, 0x03, 0xD0, 0x08, 0x48, 0x33, 0x00, 0xCD, 0x00, 0x34,
+0x02, 0x10, 0x0C, 0x40, 0x37, 0x00, 0x51, 0x00, 0x24, 0x02, 0x90, 0x0C, 0x40,
+0x40, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x00, 0xD3,
+0x00, 0x4C, 0x02, 0xB0, 0x09, 0xC4, 0x36, 0x00, 0x1F, 0x00, 0x6D, 0x03, 0xF0,
+0x0D, 0x40, 0x34, 0x00, 0x93, 0x00, 0x4C, 0x03, 0x30, 0x01, 0xC4, 0x27, 0x00,
+0xDF, 0x00, 0x5C, 0x03, 0xF1, 0x01, 0x40, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02,
+0x34, 0x0F, 0xC0, 0x37, 0x00, 0x53, 0x00, 0x4C, 0x00, 0xF0, 0x0D, 0xC0, 0x04,
+0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x98, 0x2F, 0x00, 0xAF, 0x00,
+0xF4, 0x02, 0x70, 0x0B, 0xC4, 0x3D, 0x10, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
+0x80, 0x3B, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xEF,
+0x00, 0xB8, 0x03, 0xF0, 0x0B, 0xC8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0,
+0x0F, 0xC0, 0x3F, 0x00, 0x7F, 0x00, 0xFC, 0x02, 0xF8, 0x0F, 0xC0, 0x17, 0x24,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x0B, 0x80, 0x33, 0x00, 0xFC,
+0x10, 0x30, 0x0F, 0xC0, 0x3C, 0x00, 0xF3, 0x00, 0xCC, 0x27, 0x30, 0x03, 0xC8,
+0x2C, 0x05, 0xB5, 0x00, 0xCC, 0x02, 0x30, 0x83, 0xC0, 0x2F, 0x03, 0x33, 0x01,
+0xCC, 0x01, 0xF0, 0x1B, 0xC0, 0x2F, 0x01, 0x3F, 0x01, 0xCC, 0x26, 0xB0, 0x0B,
+0xC0, 0x7C, 0x00, 0xBF, 0x14, 0xFC, 0x27, 0x30, 0x4F, 0xC1, 0x0C, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x10, 0x11, 0x0A, 0x74, 0x28,
+0x12, 0x4F, 0x40, 0x7C, 0x10, 0xD5, 0x01, 0x04, 0x02, 0x10, 0x01, 0x50, 0xE4,
+0x08, 0x91, 0x08, 0x54, 0x02, 0x10, 0x0B, 0x40, 0xAF, 0x00, 0x91, 0x00, 0x44,
+0x2C, 0xD0, 0x19, 0x40, 0xE7, 0x00, 0x1D, 0x01, 0x44, 0x02, 0x14, 0x08, 0x40,
+0x74, 0x00, 0x9D, 0x03, 0x74, 0x03, 0x10, 0x3D, 0x40, 0x04, 0x60, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x23, 0x00, 0x01, 0x20, 0x34, 0x00, 0x50,
+0x0C, 0x51, 0x30, 0x00, 0xC1, 0x00, 0x04, 0x02, 0x10, 0x00, 0x40, 0x20, 0x00,
+0x85, 0x00, 0x04, 0x02, 0x14, 0x48, 0x40, 0xB7, 0x20, 0x91, 0x14, 0x16, 0x81,
+0x90, 0x0C, 0x42, 0xB3, 0x00, 0x1D, 0x00, 0x64, 0x02, 0x10, 0x08, 0x40, 0x30,
+0x00, 0x09, 0x01, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x44, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA8, 0x25, 0x00, 0x11, 0x01, 0x74, 0x44, 0x10, 0x8D,
+0x40, 0x34, 0x00, 0xD5, 0x00, 0x44, 0x02, 0x10, 0x01, 0x40, 0x24, 0x01, 0xD1,
+0x20, 0x54, 0x46, 0x10, 0x19, 0x40, 0x27, 0x00, 0x91, 0x01, 0x54, 0x40, 0xD0,
+0x15, 0x40, 0x77, 0x00, 0x1D, 0x11, 0x64, 0x12, 0x10, 0x09, 0x41, 0x74, 0x00,
+0xDD, 0x44, 0x74, 0x23, 0x10, 0x0D, 0x40, 0x1C, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x47, 0x42, 0x11, 0x81, 0x7C, 0x0C, 0x34, 0x1D, 0xC0,
+0x34, 0x00, 0xD3, 0x00, 0x49, 0x03, 0x30, 0x15, 0xD0, 0x24, 0x00, 0x97, 0x80,
+0x4C, 0x06, 0x30, 0x39, 0xC0, 0x63, 0x40, 0x83, 0x01, 0x5D, 0x01, 0xF0, 0x19,
+0xC0, 0x77, 0x00, 0x0F, 0x01, 0x2D, 0x07, 0xB0, 0x29, 0xD0, 0x34, 0x00, 0x9F,
+0x01, 0x7E, 0x06, 0x30, 0x0D, 0xC0, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x88, 0x6D, 0x00, 0x3F, 0x00, 0xBC, 0x00, 0xE2, 0x1E, 0xE1, 0x3F,
+0x00, 0xFF, 0x00, 0xF8, 0x03, 0xF0, 0x4E, 0xE0, 0x6B, 0x00, 0x8F, 0x20, 0x7C,
+0x02, 0xF0, 0x0F, 0xC0, 0x67, 0x22, 0xBF, 0x10, 0xEC, 0x25, 0xF0, 0x0B, 0xC0,
+0x3F, 0x08, 0x3F, 0x00, 0xDC, 0x03, 0xF0, 0x47, 0xC0, 0x3F, 0x00, 0xBF, 0x81,
+0xFE, 0x06, 0xF4, 0x0C, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x08, 0x21, 0x00, 0x13, 0x80, 0x6C, 0x18, 0x32, 0x0D, 0xC0, 0x73, 0x00,
+0xD3, 0x00, 0x7C, 0x03, 0x30, 0x05, 0xC0, 0x24, 0x00, 0x93, 0x00, 0x4C, 0x3A,
+0x34, 0x2D, 0xC0, 0x3C, 0x00, 0x93, 0x00, 0x7C, 0x01, 0x30, 0x0D, 0xC0, 0x77,
+0x00, 0x1F, 0x02, 0x7C, 0x23, 0x30, 0x24, 0xD0, 0x34, 0x00, 0xDF, 0x00, 0x4C,
+0x02, 0xF0, 0x0D, 0xE0, 0x0A, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0xA0, 0x6C, 0x01, 0x91, 0x01, 0x44, 0x0C, 0x10, 0x1D, 0xE4, 0x3F, 0x00, 0xE1,
+0x00, 0x74, 0x07, 0x10, 0x0D, 0x48, 0x24, 0x00, 0xD1, 0x00, 0x6C, 0x0A, 0x12,
+0x0D, 0x48, 0x24, 0x30, 0x9B, 0x00, 0x70, 0x15, 0x11, 0x05, 0x40, 0x34, 0x00,
+0x1D, 0x00, 0x74, 0x07, 0x10, 0xA5, 0x40, 0x34, 0x00, 0xDD, 0x84, 0x44, 0x02,
+0xD0, 0x0F, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20,
+0x40, 0x00, 0x01, 0x00, 0x24, 0x84, 0x10, 0x08, 0x40, 0x33, 0x40, 0xC1, 0x80,
+0x74, 0x07, 0x90, 0x20, 0x41, 0x20, 0x40, 0x81, 0x00, 0x44, 0x03, 0x91, 0x08,
+0x40, 0x21, 0x20, 0x81, 0x02, 0x30, 0x41, 0x16, 0x0C, 0x52, 0x33, 0x00, 0x4D,
+0x00, 0x34, 0x06, 0x10, 0x08, 0x40, 0x30, 0x00, 0x8D, 0x01, 0x44, 0x02, 0xD0,
+0x0C, 0x40, 0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6C,
+0x00, 0x01, 0x11, 0x84, 0x64, 0x10, 0x1E, 0x40, 0x79, 0x40, 0xE1, 0x61, 0xB4,
+0x4E, 0x90, 0x12, 0x50, 0x78, 0x00, 0xA1, 0x11, 0xA4, 0x26, 0x90, 0x0A, 0x40,
+0x69, 0x00, 0xE9, 0x01, 0xB4, 0x06, 0x10, 0x1F, 0x40, 0x5A, 0x00, 0x6D, 0x01,
+0xB4, 0x06, 0x10, 0x1A, 0x40, 0x78, 0x20, 0x8D, 0x01, 0x84, 0x06, 0xD0, 0x1E,
+0x40, 0x19, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x18, 0x20, 0x00,
+0x03, 0x20, 0x6E, 0x20, 0x34, 0x08, 0x41, 0x33, 0x00, 0xC3, 0x00, 0x3C, 0x02,
+0x90, 0x01, 0xC1, 0x20, 0x00, 0x83, 0x00, 0x0C, 0x23, 0xB4, 0x89, 0xC0, 0x31,
+0x09, 0x83, 0x00, 0x3C, 0x00, 0x30, 0x0C, 0xC0, 0x33, 0x00, 0x0F, 0x00, 0x7C,
+0x02, 0x34, 0x08, 0xC0, 0x30, 0x00, 0xCF, 0x08, 0x0D, 0x02, 0xF2, 0x0C, 0xD0,
+0x48, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x2D, 0x40, 0x3F,
+0x00, 0xF6, 0x20, 0xF5, 0x0F, 0xC0, 0x3B, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0x50,
+0x03, 0xC0, 0x3B, 0x02, 0xFF, 0x08, 0xFC, 0xA1, 0x70, 0xCB, 0xE0, 0xBE, 0x00,
+0xBF, 0x00, 0xBC, 0x02, 0xF0, 0x06, 0xC0, 0x3D, 0x00, 0x3F, 0x00, 0xFC, 0x02,
+0xF0, 0x8B, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x0A,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x07, 0x00, 0x13, 0x00,
+0xCC, 0x00, 0x30, 0x59, 0xC8, 0x30, 0x13, 0xF7, 0x00, 0x74, 0x03, 0x70, 0x01,
+0xC0, 0x24, 0x00, 0x9E, 0x00, 0x4C, 0x03, 0x30, 0x2D, 0xC1, 0xAC, 0x00, 0x93,
+0x00, 0x7C, 0x01, 0xC0, 0x1D, 0xC0, 0x34, 0x00, 0x5B, 0x00, 0x7C, 0x02, 0x30,
+0x05, 0xD0, 0x30, 0x00, 0x93, 0x00, 0x7C, 0x07, 0x30, 0x0D, 0xC0, 0x53, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xA9, 0x00, 0x21, 0xC0, 0x84,
+0x02, 0x11, 0x0E, 0xC1, 0x38, 0x04, 0xE1, 0x01, 0xB4, 0x03, 0xD0, 0x0F, 0x40,
+0x38, 0x00, 0xAD, 0x00, 0xBC, 0x03, 0x10, 0x0E, 0x42, 0x20, 0x00, 0xE1, 0xC0,
+0xB4, 0x03, 0xC0, 0x0E, 0xC0, 0x38, 0x00, 0x6D, 0x00, 0xB4, 0x02, 0x50, 0x0C,
+0x40, 0x38, 0x00, 0xA5, 0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x4B, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x69, 0x01, 0x21, 0x01, 0x84, 0x07,
+0x10, 0x18, 0x00, 0x78, 0x01, 0xE5, 0x01, 0xB4, 0x47, 0xD1, 0x12, 0x50, 0x6A,
+0x00, 0x8D, 0x01, 0x04, 0x07, 0x10, 0x1C, 0x48, 0x78, 0x00, 0xA0, 0x01, 0xB4,
+0x05, 0xD0, 0x1F, 0x50, 0x78, 0x00, 0x2D, 0x01, 0xB4, 0x06, 0x18, 0x1E, 0x40,
+0x68, 0x00, 0xE9, 0x01, 0xF4, 0x07, 0x10, 0x1E, 0x40, 0x03, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xD1, 0x53, 0x04, 0x03, 0x10,
+0x0C, 0x50, 0x32, 0x00, 0xC1, 0x00, 0x34, 0x07, 0xD0, 0x0D, 0x40, 0x32, 0x00,
+0xCD, 0x40, 0x34, 0x2B, 0x10, 0x5C, 0x60, 0x30, 0x00, 0x81, 0x00, 0x34, 0x03,
+0xD0, 0x04, 0x40, 0xF2, 0x00, 0x8D, 0x00, 0x34, 0x26, 0x50, 0x7C, 0x42, 0x30,
+0x00, 0xCD, 0x00, 0x34, 0x07, 0x14, 0x0C, 0x40, 0x5B, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x17, 0xA0, 0x1D, 0x00, 0x73, 0x27, 0xCC, 0x0D, 0x34, 0x05,
+0xC8, 0x10, 0x00, 0x57, 0x20, 0x7C, 0x05, 0xF0, 0x27, 0xC1, 0x16, 0x00, 0x5F,
+0x00, 0xCC, 0x05, 0x34, 0x57, 0xD0, 0x14, 0x40, 0x73, 0x00, 0xFC, 0x01, 0xF0,
+0x07, 0xC0, 0x1C, 0x01, 0x6B, 0x00, 0x7C, 0x01, 0x30, 0x77, 0xD0, 0x14, 0x00,
+0x6B, 0x00, 0x7C, 0x01, 0x30, 0x05, 0xC0, 0x5F, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x08, 0x05, 0x40, 0x1F, 0x00, 0x7D, 0x20, 0xF0, 0x01, 0xC0,
+0x05, 0x00, 0x1F, 0x02, 0x7C, 0x00, 0xF2, 0x01, 0xC5, 0x05, 0x00, 0x1F, 0x00,
+0x7C, 0x40, 0xF0, 0x00, 0xC0, 0x03, 0x40, 0x1F, 0x04, 0x7C, 0x20, 0xF0, 0x01,
+0xC0, 0x05, 0x30, 0x1F, 0x01, 0x7C, 0x00, 0xF4, 0x21, 0xC4, 0x07, 0x00, 0x17,
+0x01, 0x7C, 0x20, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x25, 0x00, 0x97, 0x00, 0x4C, 0x4A, 0x30, 0x59, 0xC0, 0xE7,
+0x00, 0x8B, 0x01, 0x6C, 0x02, 0xF0, 0x19, 0x80, 0x24, 0x10, 0x8F, 0x89, 0x4C,
+0x02, 0x38, 0x09, 0xC0, 0x24, 0x00, 0x93, 0x05, 0x7C, 0x02, 0xF0, 0x09, 0xC0,
+0x23, 0x04, 0x93, 0x01, 0x6D, 0x02, 0x30, 0x59, 0x40, 0xA4, 0x00, 0x93, 0x00,
+0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x20, 0x24, 0x00, 0x91, 0x00, 0x44, 0x0A, 0x10, 0x19, 0x40, 0x27, 0x00,
+0x91, 0x03, 0x44, 0x02, 0xD0, 0x19, 0x40, 0x24, 0x00, 0x9D, 0x01, 0x6C, 0x02,
+0x10, 0x09, 0x40, 0x24, 0x00, 0x91, 0x03, 0x74, 0x06, 0xD0, 0x09, 0x40, 0x27,
+0x20, 0x9B, 0x00, 0x2C, 0x12, 0x50, 0x79, 0x50, 0x60, 0x00, 0x9B, 0x00, 0x44,
+0x02, 0xD2, 0x09, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x20, 0x40, 0x95, 0x20, 0x04, 0x0A, 0x56, 0x29, 0x40, 0x27, 0x40, 0x99,
+0xA8, 0x64, 0x06, 0xD8, 0x89, 0x60, 0x25, 0xA0, 0x9D, 0x00, 0x04, 0x02, 0x14,
+0x0D, 0x40, 0x26, 0x00, 0xD1, 0x00, 0x74, 0x06, 0xD8, 0x09, 0x40, 0x77, 0x00,
+0x91, 0x08, 0x66, 0x92, 0x12, 0x08, 0x42, 0x25, 0xA0, 0x99, 0x00, 0x44, 0x02,
+0xD0, 0x09, 0x40, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x20, 0x01, 0x81, 0x04, 0x04, 0x12, 0x50, 0x48, 0x40, 0x23, 0x01, 0x81, 0x04,
+0x00, 0x06, 0xD0, 0x48, 0x50, 0x21, 0x01, 0x8D, 0x04, 0x25, 0x13, 0x10, 0x48,
+0x40, 0x22, 0x11, 0xC1, 0x00, 0x36, 0x12, 0xD0, 0x08, 0x42, 0x23, 0x21, 0x99,
+0x00, 0x64, 0x02, 0x50, 0x48, 0x40, 0x25, 0x00, 0x89, 0x04, 0x05, 0x02, 0xD0,
+0x48, 0x41, 0x53, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x83,
+0x02, 0x07, 0x0A, 0x0C, 0x28, 0x72, 0xA1, 0x40, 0x07, 0x00, 0x5B, 0x00, 0x6C,
+0x28, 0xF0, 0xA1, 0xC0, 0x05, 0x00, 0x1F, 0x0A, 0x4C, 0x28, 0x10, 0xA1, 0x50,
+0x86, 0x02, 0x13, 0x0A, 0x7C, 0x01, 0xD1, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x00,
+0x6D, 0x28, 0x30, 0xA1, 0xC0, 0x05, 0x00, 0x1B, 0x00, 0x4C, 0x08, 0xF0, 0x01,
+0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x3F, 0x02,
+0xBF, 0x08, 0xFD, 0x22, 0xB0, 0x8B, 0xC0, 0x27, 0x42, 0x9F, 0x08, 0xFC, 0x02,
+0xF0, 0x8B, 0xC8, 0x2E, 0x12, 0xBF, 0x48, 0xFC, 0x22, 0xF0, 0x8B, 0xC0, 0x2D,
+0x42, 0xBF, 0x00, 0xFC, 0x22, 0xF0, 0x0A, 0xC0, 0x2F, 0x02, 0xBF, 0x00, 0xBD,
+0x02, 0xF0, 0x8B, 0xC0, 0x2E, 0x00, 0xBF, 0x08, 0xBC, 0x42, 0xF0, 0x09, 0xC0,
+0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x3F, 0x05, 0xB3,
+0x0C, 0xCC, 0x02, 0x30, 0x0B, 0xC0, 0x2F, 0x00, 0xA3, 0x04, 0x8C, 0x02, 0xF0,
+0xCB, 0xC0, 0x2C, 0x00, 0xB3, 0x00, 0xCC, 0x22, 0xF0, 0x4B, 0xC0, 0x24, 0x05,
+0xAF, 0x08, 0xFC, 0x16, 0xF0, 0x09, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xFC, 0x02,
+0xF0, 0xCA, 0xC0, 0x3C, 0x00, 0xF3, 0x00, 0x7C, 0x22, 0xF0, 0x19, 0xC0, 0x67,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01, 0x51, 0x0C,
+0x4C, 0x48, 0x14, 0x01, 0xC1, 0x04, 0x02, 0x11, 0x60, 0x44, 0x10, 0x70, 0xC0,
+0x40, 0x05, 0x00, 0x11, 0x10, 0x44, 0x20, 0xD0, 0x05, 0x40, 0x04, 0x01, 0x1D,
+0x04, 0x74, 0x08, 0xC0, 0x01, 0x40, 0x07, 0x02, 0x1D, 0x00, 0x74, 0x10, 0xD2,
+0xC1, 0x40, 0x04, 0x00, 0x55, 0x00, 0x74, 0x04, 0xD0, 0x01, 0x40, 0x73, 0x60,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x05, 0x81, 0x04, 0x24,
+0x32, 0x10, 0x88, 0x40, 0x21, 0x00, 0x81, 0x08, 0x04, 0x52, 0xD2, 0x48, 0x40,
+0x20, 0x00, 0x81, 0x00, 0x04, 0x06, 0xD0, 0x88, 0x44, 0x20, 0x05, 0x8D, 0x04,
+0x34, 0x22, 0xD8, 0x18, 0x40, 0x63, 0x00, 0x8D, 0x20, 0x34, 0x52, 0xD0, 0x48,
+0x40, 0x20, 0x00, 0x81, 0x08, 0x34, 0x12, 0xD0, 0x28, 0x40, 0x4B, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x65, 0x58, 0x81, 0x00, 0x44, 0x02,
+0x10, 0x09, 0x40, 0x26, 0x00, 0x91, 0x00, 0x45, 0x12, 0x50, 0x08, 0x50, 0x25,
+0x00, 0x91, 0x04, 0x45, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x20, 0x9D, 0x24, 0x74,
+0x83, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x06, 0x74, 0x02, 0xD0, 0x49, 0x41,
+0x24, 0x00, 0x95, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x25, 0x00, 0x93, 0x82, 0x6D, 0x1A, 0x32,
+0x09, 0xC0, 0x25, 0x40, 0x93, 0x00, 0x4C, 0x06, 0xF2, 0x09, 0xC0, 0x24, 0x00,
+0x93, 0x00, 0x4C, 0x06, 0xF0, 0xB9, 0xC0, 0x24, 0x00, 0x9F, 0x06, 0x7C, 0x02,
+0xF0, 0x09, 0xC0, 0xE7, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xD0, 0x24,
+0x02, 0x93, 0x09, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x17, 0xA0, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x16, 0x08, 0x25, 0x00, 0x9F, 0x03, 0x7C, 0x26, 0xF0, 0x09,
+0xC1, 0x21, 0x00, 0x8F, 0x00, 0x7C, 0x46, 0x70, 0x09, 0x40, 0x26, 0x40, 0x9F,
+0x01, 0x7C, 0x0A, 0xF0, 0x18, 0xD0, 0x67, 0x01, 0x9F, 0x00, 0x7C, 0x12, 0xF0,
+0x39, 0xC0, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x19, 0xD0, 0x27, 0x80,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x08, 0x85, 0x00, 0x13, 0x02, 0x4C, 0x00, 0xB0, 0x01, 0xC0,
+0x04, 0x40, 0x13, 0x04, 0x4C, 0x20, 0x30, 0x01, 0xC0, 0x04, 0x80, 0x1F, 0x00,
+0x4C, 0x00, 0x34, 0x01, 0xC0, 0x04, 0x00, 0x13, 0x82, 0x4C, 0x84, 0xB0, 0x01,
+0xC0, 0x07, 0x00, 0x1F, 0x02, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1F,
+0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x00, 0x14, 0x48, 0x51, 0x00, 0xD4, 0x01, 0x34, 0x07, 0x40, 0x14,
+0x00, 0x71, 0x00, 0xC4, 0x01, 0x10, 0x07, 0x50, 0x10, 0x00, 0x5D, 0x10, 0xFC,
+0x11, 0x12, 0x05, 0x40, 0x14, 0x00, 0x71, 0x02, 0xC0, 0x05, 0x30, 0x05, 0x40,
+0x57, 0x04, 0x5D, 0x01, 0xF4, 0x41, 0xD0, 0x07, 0x40, 0x10, 0x00, 0x5D, 0x01,
+0x74, 0x01, 0x10, 0x05, 0x40, 0x53, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA0, 0x36, 0x00, 0xC1, 0x00, 0x44, 0x03, 0x10, 0x2D, 0x40, 0x30, 0x00,
+0x81, 0x00, 0x04, 0x0F, 0xD4, 0x1C, 0x40, 0x30, 0x00, 0xDD, 0x00, 0x04, 0x07,
+0x10, 0x1C, 0x40, 0x30, 0x20, 0xC1, 0x12, 0x00, 0x03, 0x0C, 0x0C, 0x40, 0x23,
+0x00, 0xCD, 0x01, 0x34, 0x01, 0x90, 0x09, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x34,
+0x03, 0x10, 0x0C, 0x40, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x80, 0x30, 0x08, 0xC1, 0x00, 0x94, 0x03, 0x10, 0x02, 0x40, 0x38, 0x00, 0xA1,
+0x02, 0xC4, 0x07, 0xD0, 0x0E, 0x41, 0x38, 0x04, 0xCD, 0x00, 0xB4, 0x05, 0x10,
+0x2C, 0x40, 0x7A, 0x00, 0xF1, 0x01, 0x84, 0x0F, 0x10, 0x0E, 0x40, 0x3B, 0x00,
+0xED, 0x10, 0xB4, 0x01, 0xD0, 0x03, 0x40, 0x28, 0x00, 0xAD, 0x02, 0xB4, 0x07,
+0x10, 0x0E, 0x40, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18,
+0x78, 0x40, 0xE3, 0x01, 0xCC, 0x04, 0x33, 0x12, 0x50, 0x60, 0x20, 0x23, 0x01,
+0x8D, 0x07, 0xF0, 0x1A, 0xC2, 0x78, 0x00, 0xED, 0x01, 0xC8, 0x85, 0x30, 0x1E,
+0xD0, 0x7C, 0x41, 0xE3, 0x01, 0x8D, 0x06, 0x30, 0x1E, 0xC0, 0x7B, 0x00, 0xEF,
+0x01, 0xBC, 0x07, 0xF0, 0x1E, 0xD0, 0x78, 0x00, 0xAD, 0x01, 0xFC, 0x07, 0x34,
+0x1E, 0xC0, 0x47, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0xB5,
+0x05, 0xDF, 0x02, 0x7C, 0x02, 0x70, 0x00, 0xC0, 0x37, 0x00, 0x1C, 0x00, 0x7C,
+0x03, 0x30, 0x29, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x81, 0xF0, 0x0D, 0xC0,
+0x35, 0x02, 0xDF, 0x00, 0x3D, 0x00, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x7D, 0x00,
+0xF3, 0x03, 0xCC, 0x13, 0x30, 0x17, 0xC0, 0x7C, 0x10, 0xF3, 0x01, 0xFC, 0x07,
+0xF0, 0x3F, 0xC0, 0x78, 0x00, 0xF3, 0x01, 0xCC, 0x06, 0x30, 0x1A, 0xC0, 0x7D,
+0x00, 0xFF, 0x01, 0xCC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0x01, 0xFC,
+0x27, 0xF0, 0x1B, 0xD0, 0x6C, 0x00, 0xBF, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0,
+0x0B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x40, 0xF1,
+0x00, 0x86, 0x03, 0x10, 0x02, 0x40, 0x38, 0x02, 0xE1, 0x04, 0xB4, 0x00, 0xD0,
+0x8E, 0x40, 0x38, 0x00, 0xB1, 0x00, 0x84, 0x01, 0x10, 0x8A, 0x43, 0x38, 0x08,
+0xED, 0x02, 0x84, 0x02, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x23,
+0xD0, 0x82, 0x40, 0x28, 0x00, 0xED, 0x08, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x57,
+0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB1, 0x02, 0xE1, 0x00,
+0x84, 0x20, 0x10, 0x00, 0x41, 0x20, 0x00, 0xA9, 0x40, 0xB4, 0x03, 0xD0, 0x08,
+0x40, 0x38, 0x06, 0xA1, 0x00, 0x84, 0x60, 0x10, 0x0B, 0x40, 0x38, 0x04, 0xED,
+0x00, 0x04, 0x00, 0x50, 0x2E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x23, 0xD8,
+0x0E, 0x40, 0x3A, 0x00, 0xA9, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x23, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x35, 0x00, 0xC1, 0x0A, 0x44,
+0x42, 0x10, 0x00, 0x48, 0x30, 0x00, 0x89, 0x00, 0x34, 0x07, 0xD0, 0xB9, 0x40,
+0x70, 0x48, 0x91, 0x01, 0x04, 0x01, 0x10, 0x28, 0x40, 0x30, 0x00, 0xDD, 0x10,
+0x04, 0x24, 0x10, 0x0C, 0x40, 0x33, 0x90, 0xCD, 0x02, 0x34, 0x02, 0xD0, 0x2D,
+0x40, 0x32, 0x00, 0xCD, 0x03, 0x34, 0x83, 0xD2, 0x0C, 0x40, 0x5B, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x25, 0x00, 0xD3, 0x03, 0x4D, 0x0B,
+0x30, 0x10, 0xC0, 0x34, 0x50, 0x9B, 0x00, 0x7C, 0x47, 0xF0, 0x2D, 0xD0, 0x60,
+0x00, 0xD3, 0x05, 0x4D, 0x0E, 0x34, 0x19, 0xD0, 0x7C, 0x00, 0xDF, 0x01, 0x4D,
+0x22, 0x70, 0x0D, 0xC0, 0xB7, 0x02, 0xCF, 0x0A, 0x7C, 0x01, 0xF0, 0xF5, 0xD0,
+0x66, 0x00, 0x9F, 0x09, 0xFC, 0x03, 0xF0, 0x0D, 0xC0, 0x57, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x77, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0x21, 0xC0, 0x37, 0x00, 0x97, 0x00, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x27, 0x00,
+0xDF, 0x00, 0x7C, 0x40, 0xF1, 0x08, 0xC1, 0x37, 0x00, 0xDF, 0x01, 0x7C, 0x02,
+0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC0, 0x25,
+0x02, 0x9F, 0x08, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x08, 0x2F, 0x40, 0xF3, 0x10, 0xDC, 0x04, 0x30, 0x03,
+0xC0, 0xF8, 0x00, 0x33, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC1, 0xAC, 0x40, 0xF3,
+0x00, 0x4C, 0x04, 0xF0, 0x0B, 0xE0, 0x3C, 0x00, 0xBF, 0x00, 0xCC, 0x00, 0xD0,
+0x0F, 0xC0, 0x7F, 0x01, 0xB7, 0x01, 0xCC, 0x03, 0xF0, 0x3F, 0xC0, 0xEC, 0x00,
+0xBF, 0x03, 0xCC, 0x03, 0xF0, 0x0F, 0x40, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0x91, 0x01, 0x74, 0x02, 0x10, 0x71, 0x40,
+0x74, 0x00, 0x11, 0x40, 0x74, 0x03, 0xD0, 0x31, 0x41, 0x24, 0x50, 0xD1, 0x08,
+0x44, 0x00, 0xD0, 0x99, 0x40, 0x34, 0x00, 0x9C, 0x03, 0x44, 0x0C, 0xD0, 0x0D,
+0x48, 0x37, 0x00, 0x9D, 0x09, 0x44, 0x07, 0xD0, 0x1D, 0x40, 0x24, 0x00, 0x8D,
+0x00, 0x45, 0x03, 0xD0, 0x0D, 0x40, 0x17, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0xA0, 0x66, 0x00, 0xD1, 0x08, 0x74, 0x23, 0x90, 0x11, 0x40, 0x34,
+0x80, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x1D, 0x40, 0x34, 0x00, 0x91, 0x00, 0x44,
+0x12, 0xD0, 0x09, 0x40, 0x36, 0x00, 0x5D, 0x01, 0x44, 0x06, 0xD1, 0x0D, 0x40,
+0x37, 0x00, 0xDD, 0x00, 0x74, 0x07, 0xD0, 0x05, 0x41, 0x24, 0x00, 0xDD, 0x00,
+0x44, 0x03, 0xD0, 0x0D, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x00, 0x30, 0x00, 0x81, 0x00, 0x34, 0x02, 0x90, 0x00, 0x42, 0x30, 0xC0,
+0xC1, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x50, 0x30, 0x00, 0x81, 0x00, 0x04, 0x00,
+0xD0, 0x08, 0x48, 0x30, 0x00, 0xCD, 0x00, 0x04, 0x02, 0xD8, 0x0C, 0x42, 0x33,
+0x00, 0xCD, 0x80, 0x35, 0x03, 0xD0, 0x0C, 0x70, 0x20, 0x00, 0xDD, 0x00, 0x04,
+0x03, 0xD0, 0x0C, 0x40, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x2E, 0x00, 0xF3, 0x00, 0x1C, 0x00, 0xB0, 0x01, 0xD0, 0x34, 0x00, 0x93,
+0x00, 0x7C, 0x03, 0xF2, 0x0B, 0xC0, 0x34, 0x00, 0x93, 0x80, 0x4C, 0x80, 0xF0,
+0x09, 0xD0, 0x34, 0x00, 0x9F, 0x00, 0x4D, 0x00, 0xF0, 0x0D, 0xC0, 0x37, 0x20,
+0xD7, 0x00, 0x7C, 0x03, 0xF0, 0x0C, 0xD0, 0x24, 0x00, 0xDF, 0x00, 0x4C, 0x03,
+0xF0, 0x0D, 0xC0, 0x07, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8,
+0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0x70, 0x03, 0xC0, 0x3F, 0x00, 0xBF, 0x00,
+0xFC, 0x03, 0xF0, 0x03, 0xC0, 0x3F, 0x00, 0xBF, 0x40, 0xFC, 0x00, 0xF0, 0x0B,
+0xC0, 0x3F, 0x00, 0xAF, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x3F, 0x20, 0xFF,
+0x00, 0xCC, 0x03, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC8, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x2F,
+0x00, 0xBF, 0x0C, 0xCC, 0x12, 0xF0, 0x1F, 0xC0, 0xBE, 0x09, 0xBF, 0xC0, 0x9D,
+0x40, 0xB0, 0x8F, 0xC0, 0x2F, 0x01, 0xB3, 0x10, 0xDC, 0xE2, 0x30, 0x1F, 0xC0,
+0x3F, 0x01, 0xF3, 0x02, 0xCC, 0x02, 0x33, 0x16, 0xC4, 0x3C, 0x00, 0xEF, 0x01,
+0xCC, 0x33, 0x30, 0x1F, 0xC0, 0x5A, 0x00, 0xFB, 0x01, 0xAC, 0x27, 0xB0, 0x0B,
+0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x07, 0x00,
+0x1D, 0x0E, 0x44, 0x12, 0xD0, 0x4D, 0x40, 0x3C, 0x03, 0x1D, 0x03, 0x44, 0x0F,
+0x10, 0x2F, 0x40, 0x27, 0x05, 0xD1, 0x06, 0x44, 0x12, 0x10, 0x1D, 0x48, 0xBF,
+0x00, 0xF1, 0x06, 0x44, 0x2C, 0x10, 0x05, 0x41, 0xBC, 0x02, 0xDD, 0x01, 0xD4,
+0x0B, 0x10, 0x1D, 0x40, 0x74, 0x00, 0xD1, 0x01, 0x44, 0x03, 0x10, 0x01, 0x40,
+0x0F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0xA3, 0x05, 0x8D,
+0x01, 0x06, 0x62, 0xD0, 0x09, 0x41, 0x30, 0x20, 0x8D, 0x08, 0x15, 0x03, 0x92,
+0xCC, 0x40, 0x43, 0x03, 0xC5, 0x10, 0x34, 0x10, 0x12, 0x0C, 0x42, 0xB2, 0x25,
+0xC1, 0x8C, 0x04, 0x04, 0x50, 0x01, 0x50, 0x30, 0x0C, 0x5D, 0x00, 0x24, 0x33,
+0x10, 0x0C, 0x40, 0x06, 0x00, 0xD9, 0xA0, 0x64, 0x12, 0x90, 0x08, 0x40, 0x4F,
+0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x65, 0x00, 0x1D, 0x01,
+0x44, 0x06, 0xD0, 0x19, 0x50, 0x34, 0x00, 0x9D, 0x03, 0x55, 0x0F, 0x10, 0x0D,
+0x42, 0x67, 0x00, 0xD5, 0x00, 0x64, 0x0C, 0x10, 0x0D, 0x40, 0x37, 0x00, 0xD1,
+0x00, 0x44, 0x04, 0x40, 0x05, 0x40, 0x34, 0x00, 0xDD, 0x80, 0x74, 0x03, 0x10,
+0x0D, 0x40, 0x74, 0x00, 0x59, 0x01, 0x44, 0x03, 0x18, 0x11, 0x41, 0x0F, 0xA0,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x67, 0x04, 0x1F, 0x01, 0x4C,
+0x14, 0xF0, 0x5C, 0xC0, 0x34, 0x00, 0x9F, 0x01, 0x5D, 0x0F, 0xB0, 0x0D, 0xC0,
+0x47, 0x00, 0xD7, 0x00, 0x7C, 0x06, 0x30, 0x0D, 0xE0, 0x37, 0x00, 0xD1, 0x20,
+0x4C, 0x06, 0x60, 0x04, 0xC0, 0x34, 0x00, 0x9F, 0x01, 0x6E, 0x03, 0x30, 0x0C,
+0xC0, 0x76, 0x00, 0xDB, 0x05, 0x2C, 0x03, 0xB0, 0x19, 0x44, 0x23, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x05, 0x00, 0x1F, 0x10, 0xFC, 0x02,
+0xF0, 0x0F, 0xC0, 0x3F, 0x04, 0x3F, 0x40, 0xAC, 0x03, 0xF2, 0x0F, 0xC0, 0x07,
+0x0C, 0xEB, 0x05, 0x1C, 0x02, 0xF0, 0x0F, 0xC8, 0x3F, 0x00, 0xFF, 0x00, 0x3C,
+0x00, 0xB2, 0x0F, 0xC0, 0x3F, 0x00, 0xBF, 0x89, 0x9C, 0x03, 0xF0, 0x5F, 0xC8,
+0x3F, 0x40, 0xF7, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x1F, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0xA5, 0x80, 0x93, 0x00, 0x4C, 0x00, 0xF0,
+0x09, 0xC0, 0x37, 0x00, 0x93, 0x80, 0x6C, 0x0B, 0x3C, 0x0D, 0xC0, 0x04, 0x00,
+0xD3, 0x00, 0x7C, 0x02, 0x30, 0x0D, 0xC0, 0x32, 0x00, 0xDB, 0x00, 0x4C, 0x02,
+0x31, 0x0D, 0xE0, 0x34, 0x10, 0x93, 0x02, 0x4C, 0x03, 0x34, 0x4D, 0xC0, 0x74,
+0x00, 0x93, 0x00, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x24, 0x10, 0x9B, 0x06, 0x44, 0x02, 0xD0, 0x09,
+0x40, 0x3F, 0x00, 0x81, 0x0B, 0x68, 0x07, 0xB0, 0x1F, 0xC0, 0xE4, 0x00, 0xD0,
+0x00, 0x74, 0x02, 0x10, 0x0D, 0x48, 0x3F, 0x00, 0xFB, 0x10, 0x44, 0x02, 0x00,
+0x0D, 0xC0, 0x3F, 0x00, 0x81, 0x81, 0xC4, 0x2B, 0x10, 0x2D, 0x40, 0x70, 0x00,
+0x05, 0x05, 0x6C, 0x2F, 0x10, 0x49, 0xC0, 0x6E, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0xA0, 0x02, 0x00, 0x91, 0x02, 0x24, 0x00, 0xD0, 0x08, 0x64,
+0xF3, 0x00, 0x01, 0x03, 0x20, 0x07, 0x10, 0x5C, 0x48, 0xE4, 0x00, 0xC5, 0x00,
+0x34, 0x00, 0x11, 0x0C, 0x40, 0x31, 0x02, 0xD5, 0x01, 0x04, 0x02, 0x50, 0x14,
+0x40, 0x70, 0x01, 0xC1, 0x00, 0x24, 0x23, 0x90, 0x2C, 0x40, 0x10, 0x00, 0xC1,
+0x01, 0x04, 0x07, 0x50, 0x60, 0x44, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x80, 0x58, 0x00, 0xE9, 0x01, 0xA4, 0x05, 0xD0, 0x1A, 0x60, 0x7B,
+0x04, 0x61, 0x01, 0xE4, 0x07, 0x94, 0x1E, 0x40, 0x78, 0x00, 0xE5, 0x01, 0xB4,
+0x07, 0x10, 0x1E, 0x00, 0xFB, 0x00, 0xED, 0x03, 0x84, 0x07, 0x58, 0x37, 0x41,
+0x79, 0x04, 0xF1, 0x00, 0xA0, 0x07, 0x91, 0x0E, 0x40, 0x78, 0x00, 0xF5, 0x01,
+0xE4, 0x27, 0x18, 0x12, 0x48, 0x3E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x10, 0x10, 0x00, 0xC1, 0x00, 0x24, 0x03, 0xF0, 0x08, 0xC0, 0x37, 0x00,
+0x43, 0x14, 0x2C, 0x43, 0x10, 0x8D, 0xC1, 0x10, 0x04, 0xC7, 0x00, 0x34, 0x21,
+0x30, 0x0C, 0xC0, 0x37, 0x00, 0xD7, 0x88, 0x0C, 0x01, 0x70, 0x00, 0x40, 0x34,
+0x00, 0xC3, 0x18, 0x64, 0x13, 0xB0, 0x8C, 0x40, 0x10, 0x00, 0xC3, 0x00, 0x0C,
+0x42, 0x70, 0x09, 0xC0, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x98, 0x3D, 0x20, 0xF7, 0x00, 0xDC, 0x03, 0xF0, 0x0B, 0xC0, 0x3F, 0x40, 0xEF,
+0x00, 0xFC, 0x23, 0xF5, 0x0F, 0xC4, 0x35, 0x00, 0xFB, 0x00, 0xFC, 0x03, 0xF0,
+0x0F, 0xC0, 0xBF, 0x02, 0xF3, 0x00, 0xFC, 0x01, 0xB0, 0x07, 0xC0, 0x3F, 0x00,
+0xFF, 0x0C, 0xDC, 0x03, 0x70, 0x4E, 0xC0, 0x3F, 0x00, 0xEF, 0x00, 0xFE, 0x83,
+0x70, 0x07, 0xC8, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0,
+0x37, 0x80, 0x5B, 0x00, 0x5C, 0x01, 0x34, 0x09, 0xC0, 0xB7, 0x04, 0xCF, 0x80,
+0x5C, 0x03, 0xF8, 0x4D, 0xC9, 0x37, 0x00, 0xDF, 0x01, 0x4C, 0x01, 0xF0, 0x0D,
+0xC0, 0x37, 0x03, 0xDF, 0x02, 0x7E, 0x03, 0xF0, 0x05, 0xC0, 0xB6, 0x02, 0xDF,
+0x00, 0x5C, 0x5B, 0xF0, 0x1D, 0xC0, 0x36, 0x00, 0xCF, 0x20, 0x4C, 0x03, 0x22,
+0x01, 0xC4, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x1D,
+0x08, 0x63, 0x00, 0xB4, 0x01, 0x10, 0x0A, 0x40, 0xBB, 0x11, 0x6D, 0x00, 0x94,
+0x03, 0x30, 0x6E, 0x48, 0x3B, 0x00, 0xED, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40,
+0x3B, 0x01, 0xED, 0x48, 0xB4, 0x03, 0xD0, 0x0F, 0x40, 0x38, 0x04, 0xAD, 0x00,
+0xB4, 0x0B, 0xD0, 0x0E, 0x40, 0x38, 0x00, 0xED, 0x80, 0xD4, 0x83, 0x10, 0x06,
+0xC0, 0x4E, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x00,
+0xE1, 0x01, 0xB4, 0x47, 0x10, 0x1A, 0x40, 0x7B, 0x00, 0xED, 0x11, 0xD4, 0x47,
+0x50, 0x1E, 0x48, 0x5B, 0x00, 0xED, 0x01, 0xA5, 0x05, 0xD0, 0x1E, 0x40, 0x7B,
+0x00, 0xED, 0x09, 0xB4, 0x07, 0xD2, 0x1E, 0x55, 0x78, 0x00, 0xAD, 0x01, 0xB4,
+0x07, 0xD0, 0x1B, 0x40, 0x7A, 0x00, 0xF5, 0x01, 0x84, 0x06, 0x14, 0x18, 0x40,
+0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x10, 0xC1,
+0x0D, 0x34, 0x07, 0x90, 0x00, 0x40, 0x33, 0x00, 0xCD, 0x03, 0x14, 0x0B, 0x90,
+0x0C, 0x40, 0xF3, 0x04, 0xCD, 0x08, 0x04, 0x07, 0xD0, 0x0C, 0x40, 0x37, 0x20,
+0xCD, 0x00, 0x34, 0x27, 0xD0, 0x4C, 0x40, 0x30, 0x00, 0x8D, 0x04, 0x34, 0x03,
+0xD0, 0x18, 0x40, 0x70, 0x08, 0xCD, 0x01, 0x14, 0x03, 0x10, 0xAD, 0x43, 0x5A,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x1D, 0x04, 0x73, 0x02,
+0xFC, 0x01, 0x30, 0x27, 0xC0, 0x17, 0x10, 0x7F, 0x02, 0xDD, 0xA9, 0x74, 0x05,
+0xC0, 0x9F, 0x00, 0x5F, 0x00, 0xEC, 0x15, 0xF0, 0x05, 0x40, 0x17, 0x80, 0x5F,
+0x00, 0xFC, 0x09, 0xF0, 0x36, 0xC0, 0x14, 0x00, 0x7F, 0x02, 0x7C, 0x01, 0xF9,
+0x15, 0xC2, 0x1E, 0x04, 0x67, 0x81, 0x44, 0x01, 0x10, 0x27, 0xC0, 0x5C, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x47, 0x40, 0x1F, 0x00, 0x7C,
+0x40, 0x70, 0x41, 0xC0, 0x83, 0x00, 0x1F, 0x12, 0x7C, 0x00, 0x74, 0x01, 0xC0,
+0x07, 0x02, 0x1F, 0x00, 0x5C, 0x04, 0xF0, 0x01, 0xC2, 0x87, 0x00, 0x1F, 0x00,
+0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x05, 0x00, 0x1F, 0x0A, 0x7C, 0x00, 0xF0, 0x81,
+0xC0, 0x07, 0x10, 0x1F, 0x08, 0x7C, 0x00, 0xF0, 0x21, 0xC0, 0x4B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x80, 0x93, 0x05, 0x3C, 0x02,
+0x30, 0x09, 0xC0, 0x67, 0x02, 0x83, 0x00, 0x4C, 0x02, 0xB0, 0x28, 0xC0, 0x64,
+0x01, 0x9E, 0x00, 0x78, 0x02, 0x30, 0x09, 0xC0, 0xA7, 0x40, 0x9B, 0x01, 0x7C,
+0x42, 0xF0, 0x59, 0xC0, 0x20, 0x01, 0x93, 0x42, 0x7C, 0x82, 0xF0, 0x39, 0xC0,
+0x27, 0x04, 0x97, 0x08, 0x6C, 0x16, 0x30, 0x89, 0xC0, 0x40, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x91, 0x01, 0x74, 0x02, 0x10,
+0x09, 0xC0, 0xA7, 0x04, 0x91, 0x86, 0x0C, 0x02, 0xB0, 0x09, 0x40, 0x64, 0x00,
+0x9D, 0x00, 0x7C, 0x02, 0x10, 0x09, 0x40, 0xE7, 0x00, 0x91, 0x01, 0x74, 0x02,
+0xD0, 0x49, 0xC0, 0xE6, 0x04, 0x91, 0x20, 0x74, 0x0E, 0xD0, 0x29, 0x40, 0x23,
+0x40, 0x9B, 0x41, 0x44, 0x46, 0x14, 0x39, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA0, 0x20, 0x00, 0x91, 0x00, 0x74, 0x02, 0x10, 0x09,
+0x60, 0x27, 0x00, 0x91, 0x00, 0x65, 0x22, 0x94, 0x09, 0x58, 0x26, 0x00, 0x9D,
+0x00, 0x36, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x91, 0x08, 0x74, 0x02, 0xD0,
+0x09, 0x60, 0x24, 0x00, 0xD1, 0x00, 0x74, 0x22, 0xD0, 0x09, 0x40, 0x67, 0x00,
+0x95, 0x00, 0x04, 0x02, 0x12, 0x29, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x20, 0x81, 0x81, 0x05, 0x34, 0x12, 0x10, 0x08, 0x40,
+0x21, 0x09, 0x81, 0x04, 0x44, 0x12, 0x90, 0x58, 0x40, 0x62, 0x01, 0x8D, 0x04,
+0x14, 0x12, 0x10, 0x08, 0x40, 0x23, 0x01, 0xC1, 0x04, 0x34, 0x12, 0xD0, 0x09,
+0x68, 0x22, 0x01, 0xC1, 0x00, 0x36, 0x12, 0xD0, 0x0C, 0x40, 0x23, 0x08, 0x99,
+0x00, 0x05, 0x22, 0x10, 0x48, 0x50, 0x40, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1D, 0xB0, 0x86, 0x02, 0x11, 0x0A, 0x3C, 0x28, 0x30, 0xA1, 0x40, 0x87,
+0x02, 0x13, 0x40, 0x6C, 0x00, 0xB4, 0xA1, 0xC8, 0x86, 0x02, 0x0F, 0x0A, 0x74,
+0x28, 0x34, 0x01, 0x84, 0x97, 0x02, 0x1B, 0x0A, 0x7C, 0x00, 0xD0, 0xA1, 0xC0,
+0x84, 0x42, 0x13, 0x40, 0x7C, 0x29, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x00,
+0x4C, 0x08, 0x30, 0xA1, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0x98, 0x2F, 0x4A, 0xBF, 0x08, 0xFC, 0x22, 0xD4, 0x0B, 0xC0, 0x27, 0x62,
+0xBF, 0x88, 0xBC, 0x22, 0xF4, 0x89, 0xC0, 0x2D, 0x02, 0xBF, 0x08, 0xFC, 0x22,
+0xF0, 0x09, 0xC4, 0x27, 0x02, 0x9F, 0x08, 0xFC, 0x22, 0xF0, 0x0B, 0xC0, 0x27,
+0x02, 0xBF, 0x40, 0x7C, 0x22, 0xD0, 0x0A, 0xC0, 0x2F, 0x80, 0xBF, 0x00, 0xDE,
+0x92, 0xF0, 0x8B, 0xC0, 0x77, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x27, 0x01, 0xB3, 0x14, 0x7C, 0x32, 0x30, 0x09, 0xD0, 0x2C, 0x40, 0xA3,
+0x00, 0x9C, 0x12, 0x30, 0x4B, 0xC1, 0x2C, 0x03, 0x9F, 0x25, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x2D, 0x01, 0xBF, 0x14, 0x4C, 0x12, 0x70, 0x0B, 0xC0, 0x2F, 0x40,
+0xB3, 0x00, 0xFC, 0x12, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xAB, 0x00, 0x8C, 0x02,
+0xF0, 0x0B, 0xC0, 0x76, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08,
+0x17, 0x0D, 0x11, 0x44, 0x74, 0xB0, 0x10, 0x00, 0x41, 0x04, 0x04, 0x11, 0x08,
+0x44, 0x00, 0x90, 0x41, 0x40, 0x04, 0x03, 0x1D, 0x1A, 0x74, 0x40, 0xD0, 0x01,
+0x40, 0x07, 0x05, 0x1D, 0x04, 0x44, 0x20, 0xD0, 0x01, 0x43, 0x07, 0x04, 0x11,
+0x00, 0x74, 0x50, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x11, 0x40, 0x45, 0x00, 0xD2,
+0x05, 0x40, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23,
+0x03, 0x81, 0x34, 0x34, 0x12, 0x10, 0x48, 0x40, 0x20, 0x02, 0x81, 0x00, 0x54,
+0x27, 0x90, 0x48, 0x41, 0x20, 0x01, 0x8D, 0x04, 0x34, 0x22, 0xD0, 0x08, 0x40,
+0x21, 0x03, 0x8D, 0xB4, 0x04, 0x82, 0x50, 0x48, 0x40, 0x23, 0x02, 0xC5, 0x00,
+0x34, 0x32, 0xD0, 0x08, 0x40, 0x27, 0x80, 0x89, 0x00, 0x24, 0x82, 0xD0, 0x0C,
+0x40, 0x4A, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x40,
+0x91, 0x06, 0x74, 0x02, 0x10, 0x29, 0x40, 0x24, 0x00, 0x91, 0x04, 0x44, 0x02,
+0x90, 0x09, 0x50, 0x24, 0x01, 0x9D, 0x08, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27,
+0x00, 0x9D, 0x00, 0x44, 0x02, 0xD0, 0x0D, 0x48, 0x37, 0x00, 0x95, 0x10, 0x74,
+0x82, 0xD0, 0x8D, 0x44, 0x67, 0x88, 0x91, 0x08, 0x64, 0x82, 0xD0, 0x19, 0x40,
+0x62, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x25, 0x00, 0x93,
+0x82, 0x7C, 0x1E, 0x31, 0x09, 0xC0, 0x24, 0x10, 0x93, 0x06, 0x5C, 0x0A, 0x34,
+0x09, 0xC4, 0x24, 0x01, 0x9E, 0x00, 0x7C, 0x32, 0xF0, 0x09, 0xC0, 0x25, 0x00,
+0x9F, 0x00, 0x4C, 0x1E, 0x70, 0xE9, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x74, 0x02,
+0xF0, 0x09, 0xC0, 0x23, 0x00, 0x9B, 0x04, 0x6E, 0x26, 0xD2, 0x09, 0xC0, 0x16,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xE1, 0x00, 0x9F, 0x00,
+0x7C, 0x16, 0xF6, 0x99, 0xC0, 0x23, 0x28, 0x9F, 0x20, 0x7C, 0x12, 0x70, 0x09,
+0xC5, 0x27, 0x0C, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xE0, 0x27, 0xA0, 0x8F,
+0x00, 0x7D, 0x12, 0xF0, 0x19, 0xC3, 0x27, 0x00, 0x9B, 0x02, 0x7C, 0x42, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x5E, 0x06, 0xF2, 0x08, 0xC0, 0x59, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x02, 0x7C,
+0x00, 0x30, 0x01, 0xC0, 0x06, 0x01, 0x1F, 0x02, 0x6C, 0x00, 0xB0, 0x00, 0xC0,
+0x07, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x07, 0x04, 0x13, 0x00,
+0x7C, 0x08, 0xF0, 0x21, 0xC0, 0x06, 0x41, 0x13, 0x00, 0x4C, 0x00, 0x31, 0x01,
+0xC1, 0x07, 0x20, 0x1F, 0x02, 0x4D, 0x00, 0x70, 0x01, 0xC1, 0x50, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x14, 0x00, 0x7D, 0x02, 0x74, 0x01,
+0x12, 0x05, 0xC0, 0x9C, 0x04, 0x6D, 0x21, 0x04, 0x81, 0x10, 0x57, 0x40, 0x5F,
+0x01, 0x5D, 0x80, 0x74, 0x01, 0xD0, 0x05, 0x42, 0x1F, 0x20, 0x71, 0x08, 0x74,
+0x01, 0xD0, 0x57, 0xC0, 0x1C, 0x01, 0x71, 0x00, 0xC4, 0x05, 0x10, 0x27, 0xC1,
+0x9D, 0x04, 0x41, 0x05, 0xC4, 0xAD, 0x10, 0x07, 0x50, 0x40, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x13, 0x74, 0x03, 0x10,
+0x0D, 0x42, 0x30, 0x10, 0xCD, 0x04, 0x24, 0x02, 0x90, 0x3C, 0x40, 0x73, 0x00,
+0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0xF3, 0x00, 0xC1, 0x00, 0x34, 0x03,
+0xD0, 0x0C, 0x40, 0x34, 0x80, 0x49, 0x50, 0x05, 0x07, 0x10, 0x18, 0x40, 0xD3,
+0x01, 0xC5, 0x01, 0x04, 0x07, 0x50, 0x0C, 0x40, 0x40, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x88, 0x38, 0x02, 0xED, 0x02, 0x34, 0x03, 0x14, 0x4E,
+0x40, 0x38, 0x00, 0xED, 0x02, 0xC4, 0x03, 0x10, 0x0E, 0x42, 0x3B, 0x08, 0xED,
+0x0C, 0xB6, 0x03, 0xD0, 0x0E, 0x40, 0xF3, 0x00, 0xE1, 0x10, 0xB4, 0x03, 0xD0,
+0x1E, 0x40, 0x38, 0x80, 0x69, 0x01, 0x84, 0x45, 0x12, 0x0A, 0x40, 0x19, 0x00,
+0xB1, 0x00, 0xC4, 0x45, 0x10, 0x0A, 0x42, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x10, 0x78, 0x00, 0xEF, 0x01, 0xBC, 0x47, 0x30, 0x5E, 0xC2,
+0x78, 0x10, 0x6F, 0x01, 0xAC, 0x07, 0xB0, 0x1E, 0xC0, 0x7B, 0x00, 0xEF, 0x01,
+0xB4, 0x17, 0xF0, 0x1E, 0x80, 0x7B, 0x40, 0xE3, 0x01, 0xB4, 0x07, 0xF0, 0x17,
+0xD0, 0x70, 0x00, 0xEB, 0x01, 0xCC, 0x07, 0x34, 0x1A, 0xC0, 0x5B, 0x00, 0xE7,
+0x01, 0x8C, 0x07, 0x70, 0x17, 0xC0, 0x50, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA8, 0x35, 0x04, 0xDF, 0x00, 0x7C, 0x33, 0xF0, 0x8D, 0xD0, 0x15,
+0x00, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x05, 0xC4, 0x37, 0x10, 0xDF, 0x06, 0x7C,
+0x53, 0xF0, 0x0D, 0xC4, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x83, 0xF0, 0x05, 0xC0,
+0x35, 0x00, 0xC7, 0x00, 0x7C, 0x01, 0xF0, 0x09, 0xC4, 0x13, 0x00, 0x97, 0x00,
+0x7C, 0x01, 0xF0, 0x01, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xA0, 0x7F, 0x00, 0x7F, 0x21, 0xCC, 0x07, 0xF8, 0xAE, 0xC0, 0x5F, 0x08,
+0xEF, 0x01, 0xCC, 0x07, 0x70, 0x9F, 0xC4, 0x5C, 0x02, 0xF3, 0x0B, 0xCC, 0x47,
+0x31, 0x1F, 0x40, 0x5F, 0x20, 0x7F, 0x01, 0xCC, 0x07, 0xF0, 0x1F, 0xC0, 0x7C,
+0x00, 0xFF, 0x01, 0xFC, 0x07, 0x31, 0x9B, 0xC0, 0x7F, 0x00, 0xEF, 0x01, 0xCF,
+0x36, 0x30, 0xDF, 0xD0, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x88, 0x39, 0x00, 0x7D, 0x10, 0x84, 0x23, 0xD8, 0x4E, 0x04, 0xB8, 0x00, 0xAD,
+0x04, 0x81, 0x03, 0x10, 0xAF, 0x40, 0x1C, 0x02, 0xF1, 0x20, 0xD5, 0x03, 0x14,
+0x0E, 0x40, 0x1A, 0x01, 0x6D, 0x08, 0x85, 0x03, 0xD0, 0x8E, 0x00, 0x39, 0x02,
+0xED, 0x00, 0xA4, 0x11, 0x10, 0x8A, 0x40, 0xBB, 0x01, 0xED, 0x04, 0xDC, 0x20,
+0x10, 0xCA, 0x40, 0x54, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x39, 0x00, 0x6D, 0x00, 0x85, 0x03, 0xD0, 0x8F, 0x40, 0x19, 0x00, 0x6D, 0x40,
+0xC0, 0x03, 0x50, 0x0E, 0x42, 0x18, 0x64, 0xE1, 0x00, 0x80, 0x43, 0x10, 0x0E,
+0x40, 0x3A, 0x08, 0xCD, 0x00, 0x84, 0x03, 0xD0, 0x07, 0x40, 0x18, 0x00, 0xED,
+0x00, 0x34, 0x03, 0x12, 0x0A, 0x48, 0x3B, 0x24, 0xFD, 0x20, 0x84, 0x52, 0x12,
+0xCA, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x73,
+0x12, 0x0D, 0x02, 0x04, 0x4B, 0xD0, 0x2C, 0x40, 0x04, 0x00, 0x0D, 0x08, 0x04,
+0x6F, 0x10, 0x08, 0x40, 0x40, 0x00, 0xC1, 0x40, 0x04, 0x0F, 0x10, 0x0C, 0x40,
+0x22, 0x00, 0x0D, 0x00, 0x04, 0x0F, 0xD2, 0x00, 0x40, 0x21, 0x00, 0xCD, 0x85,
+0x24, 0x00, 0x10, 0x08, 0x40, 0x73, 0x11, 0xCD, 0x00, 0x14, 0x04, 0x10, 0x38,
+0x40, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x3D, 0x00,
+0x9F, 0x00, 0xCC, 0x1F, 0xD0, 0x2F, 0x80, 0x25, 0x00, 0x8F, 0x20, 0x4C, 0x0F,
+0x74, 0x01, 0xD2, 0xE4, 0x00, 0xF3, 0x00, 0xC4, 0x07, 0x30, 0x0D, 0xC0, 0x26,
+0x00, 0x9F, 0x00, 0x4C, 0x0B, 0xF0, 0x39, 0xC1, 0x04, 0x00, 0x4F, 0x47, 0x74,
+0x02, 0x34, 0x09, 0xC0, 0xF3, 0x00, 0xDF, 0x00, 0x44, 0x07, 0x34, 0x21, 0x80,
+0x54, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x21, 0x9F,
+0x10, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0xA5, 0x00, 0x9F, 0x10, 0x7D, 0x03, 0xF0,
+0x09, 0xC0, 0xA7, 0x04, 0xDF, 0x01, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x86, 0x00,
+0x9F, 0x02, 0x7C, 0x23, 0xF0, 0x41, 0xC0, 0x87, 0x00, 0x5F, 0x40, 0x6C, 0x02,
+0xF0, 0x29, 0xC0, 0xB7, 0x00, 0x9F, 0x90, 0x5C, 0x09, 0xF0, 0xC9, 0xC0, 0x37,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x80, 0x3F, 0x00,
+0xFC, 0x03, 0xF0, 0x0F, 0xC1, 0x2F, 0x00, 0x33, 0x89, 0xCC, 0x07, 0x10, 0x03,
+0xC0, 0x0F, 0x00, 0xFF, 0x00, 0xF4, 0x43, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xBF,
+0x00, 0xFC, 0x43, 0xC0, 0x0B, 0xC0, 0x2C, 0x00, 0xFF, 0x00, 0xDC, 0x02, 0xF0,
+0x0B, 0xC0, 0x3F, 0x00, 0xB7, 0x00, 0xFC, 0x07, 0x34, 0x01, 0xC8, 0x07, 0x24,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x80, 0x9D, 0x07, 0x74,
+0x83, 0xD0, 0x0D, 0x42, 0xE7, 0x20, 0x11, 0x87, 0x04, 0x07, 0xB0, 0x31, 0x40,
+0xE7, 0x00, 0xDD, 0x20, 0x64, 0x03, 0xD0, 0x0D, 0x40, 0x46, 0x00, 0x99, 0x01,
+0x74, 0x83, 0x91, 0x30, 0x40, 0xE5, 0x00, 0xDD, 0x01, 0x44, 0x06, 0xD0, 0x39,
+0x40, 0x77, 0x00, 0x91, 0x00, 0x74, 0x02, 0x10, 0x31, 0x44, 0x87, 0x00, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x36, 0x20, 0x9D, 0x01, 0x74, 0x03,
+0xD0, 0x0D, 0x64, 0x47, 0x40, 0x91, 0x00, 0x44, 0x23, 0x50, 0x11, 0x40, 0x67,
+0x04, 0xDD, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0xC7, 0x00, 0x1D, 0x03, 0x74,
+0x03, 0xD0, 0x19, 0x40, 0x47, 0x00, 0x9D, 0x01, 0x54, 0xC4, 0xD0, 0x1D, 0x40,
+0x77, 0x00, 0xD5, 0x01, 0x34, 0x1A, 0x10, 0x31, 0x40, 0x07, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x8D, 0x00, 0x34, 0x03, 0xD0,
+0x0C, 0x60, 0x23, 0x00, 0x81, 0x00, 0x44, 0x03, 0xD4, 0x08, 0x40, 0x23, 0x20,
+0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x03, 0x00, 0x09, 0x00, 0x34, 0x03,
+0x90, 0x09, 0x40, 0x03, 0x00, 0xCD, 0x00, 0x04, 0x00, 0xD0, 0x0C, 0x40, 0x33,
+0x00, 0xC1, 0x00, 0x34, 0x01, 0x10, 0x08, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x3E, 0x00, 0x1D, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
+0xC0, 0x07, 0x08, 0x93, 0x00, 0x4D, 0x03, 0x70, 0x01, 0xC0, 0x07, 0x00, 0xFF,
+0x00, 0xFC, 0x03, 0xF0, 0x0D, 0xC4, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF0,
+0x09, 0xD0, 0x06, 0x00, 0xDF, 0x00, 0x5C, 0x02, 0xF0, 0x09, 0xC0, 0x37, 0x00,
+0x97, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x2F, 0x00, 0x3F, 0x00, 0xBC, 0x03, 0xA0, 0x0B, 0xC0, 0x2F, 0x00, 0xFE, 0x00,
+0xEC, 0x03, 0xF0, 0x0F, 0xC0, 0x0E, 0x00, 0xBA, 0x00, 0xFC, 0x03, 0xB0, 0x0A,
+0xC0, 0x2D, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x03, 0xC2, 0x2F, 0x00, 0xBF,
+0x00, 0xFC, 0x00, 0xF2, 0x0B, 0xC0, 0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA0, 0x2F, 0x40, 0x23, 0x10, 0xCD, 0x00, 0x30, 0x03, 0xC0, 0x4C,
+0x40, 0x33, 0x81, 0xCC, 0x24, 0x30, 0x13, 0xD0, 0x2C, 0x05, 0xF3, 0x09, 0xDC,
+0x00, 0x30, 0x4E, 0xC0, 0x2C, 0x00, 0x3F, 0x01, 0xCD, 0x04, 0xF1, 0x13, 0xC0,
+0x4C, 0x08, 0x33, 0x01, 0xFC, 0x04, 0xB0, 0x13, 0xD4, 0x4C, 0x40, 0xF3, 0x00,
+0xCD, 0x07, 0xF0, 0x4F, 0xC1, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x27, 0x00, 0x51, 0x92, 0x04, 0x08, 0x13, 0x09, 0x40, 0x04, 0x05,
+0x11, 0x10, 0x44, 0x01, 0x10, 0x01, 0x41, 0xA4, 0x05, 0xC1, 0x04, 0x44, 0x2C,
+0x10, 0x3F, 0xC0, 0x64, 0x02, 0x1D, 0x00, 0x64, 0x04, 0xD0, 0x05, 0xC0, 0x04,
+0x20, 0x11, 0x01, 0x74, 0x04, 0x10, 0x01, 0x60, 0x04, 0x00, 0xC1, 0x00, 0x44,
+0x07, 0xD1, 0x2D, 0x40, 0x0C, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+0xA0, 0x27, 0x00, 0x01, 0x05, 0x06, 0x0C, 0x10, 0x00, 0x40, 0x20, 0x01, 0x81,
+0x00, 0x14, 0x02, 0x10, 0x48, 0x48, 0x21, 0x00, 0x81, 0x04, 0x34, 0x00, 0xD4,
+0x8C, 0x44, 0x30, 0x00, 0x8D, 0x00, 0x34, 0x01, 0xD0, 0x00, 0x42, 0x46, 0x20,
+0x0D, 0x01, 0x74, 0x02, 0x10, 0x08, 0x40, 0x20, 0x00, 0xC9, 0x00, 0x24, 0x03,
+0xD0, 0x0C, 0x40, 0x4C, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA8,
+0x25, 0x02, 0x51, 0x44, 0x14, 0x04, 0x14, 0x1D, 0x40, 0x20, 0x00, 0x80, 0x00,
+0x55, 0x03, 0x14, 0x09, 0x40, 0x64, 0x00, 0x51, 0x00, 0x64, 0x0C, 0xC0, 0x1D,
+0x44, 0x76, 0x04, 0x8D, 0x00, 0x74, 0x89, 0xD0, 0x05, 0x50, 0x04, 0x00, 0x15,
+0x00, 0x74, 0x02, 0x10, 0x08, 0x40, 0x20, 0x00, 0x99, 0x00, 0x44, 0x03, 0xD0,
+0x1C, 0x40, 0x0C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x43,
+0x00, 0x13, 0x00, 0x4C, 0x04, 0x30, 0x31, 0xC2, 0x04, 0x00, 0x13, 0x01, 0x5C,
+0x00, 0x30, 0x11, 0xC0, 0xE4, 0x04, 0xD3, 0x04, 0x7C, 0x0C, 0xF0, 0x35, 0xC0,
+0xE4, 0x00, 0x1F, 0x00, 0x5C, 0x00, 0xF0, 0x21, 0xC0, 0x12, 0x00, 0x57, 0x00,
+0x3C, 0x01, 0xB0, 0x01, 0x40, 0x04, 0x00, 0xDB, 0x00, 0x4C, 0x03, 0xF0, 0x1D,
+0xC0, 0x08, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x4D, 0x00,
+0x7F, 0x00, 0xEC, 0x00, 0xF0, 0x0F, 0xC0, 0x0F, 0x12, 0x3F, 0x09, 0xEC, 0x01,
+0xF0, 0x93, 0x80, 0x2F, 0x50, 0xFF, 0x00, 0x5C, 0x00, 0x30, 0x06, 0xC0, 0x25,
+0x00, 0x3F, 0x08, 0xCC, 0x00, 0xF2, 0x07, 0xC4, 0x1F, 0x00, 0x7B, 0x00, 0xFC,
+0x81, 0xF0, 0x83, 0xC0, 0x0F, 0x02, 0xE7, 0x08, 0xFC, 0x03, 0xF0, 0x0F, 0xD4,
+0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x40, 0x33,
+0x00, 0x4C, 0x00, 0x32, 0x31, 0xC0, 0x64, 0x00, 0x9F, 0x01, 0x4C, 0x02, 0xF0,
+0x09, 0xC0, 0x24, 0x00, 0x53, 0x04, 0x6C, 0x88, 0xB0, 0x2D, 0xC0, 0x34, 0x11,
+0x97, 0x05, 0x7C, 0x01, 0x30, 0x41, 0xC0, 0x17, 0x02, 0x5B, 0x10, 0x4C, 0x03,
+0x30, 0x19, 0xC0, 0x64, 0x00, 0x9F, 0x04, 0x4C, 0x03, 0xF0, 0x15, 0xC0, 0x08,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x24, 0x20, 0x41, 0x01,
+0x44, 0x14, 0x10, 0xBD, 0x40, 0x64, 0x00, 0x9D, 0x0B, 0x44, 0x2F, 0xD0, 0xA8,
+0xC2, 0x26, 0x00, 0xD1, 0x82, 0x04, 0x00, 0x10, 0xAD, 0x40, 0xB4, 0x00, 0x91,
+0x03, 0x70, 0x09, 0x11, 0x35, 0x40, 0x97, 0x02, 0x51, 0x13, 0x44, 0x43, 0x10,
+0xB9, 0x40, 0x64, 0x00, 0x9D, 0x02, 0x45, 0x13, 0xD0, 0x15, 0x40, 0x6C, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x20, 0x02, 0x01, 0x1A, 0x20,
+0x00, 0x14, 0x21, 0x40, 0x10, 0x00, 0x4D, 0x00, 0x60, 0x2C, 0xD0, 0x14, 0x40,
+0x34, 0x40, 0xD1, 0x02, 0x24, 0x00, 0xD0, 0x2C, 0x40, 0x00, 0x20, 0x45, 0x02,
+0x30, 0x62, 0x10, 0x19, 0x40, 0x21, 0x00, 0x80, 0x41, 0x04, 0x04, 0x10, 0x04,
+0x40, 0x10, 0x00, 0xCD, 0x00, 0x04, 0x07, 0xD0, 0x08, 0x40, 0x1C, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, 0x31, 0x01, 0xA5, 0x04,
+0x10, 0x1B, 0x40, 0x58, 0x00, 0x6D, 0x01, 0xA4, 0x05, 0xD0, 0x16, 0x40, 0x6A,
+0x00, 0xE1, 0x01, 0x84, 0x24, 0x50, 0x9E, 0x40, 0x58, 0x00, 0x61, 0x01, 0xB6,
+0x06, 0x10, 0x1E, 0x40, 0x6F, 0x00, 0xB1, 0x81, 0xC4, 0x04, 0x10, 0x16, 0x40,
+0x58, 0x00, 0xED, 0x09, 0x84, 0x07, 0xD0, 0x2F, 0x40, 0x74, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x24, 0x01, 0x03, 0x08, 0x24, 0x00, 0x30,
+0x64, 0xC0, 0x30, 0x00, 0xDF, 0x00, 0x2C, 0x02, 0xF0, 0x0C, 0xC1, 0x14, 0x20,
+0x83, 0x00, 0x2C, 0x20, 0xF2, 0x08, 0xD0, 0x10, 0x00, 0xC7, 0x00, 0x3C, 0x03,
+0x30, 0x48, 0xC1, 0x23, 0x10, 0x83, 0x00, 0x0C, 0x02, 0x32, 0x0D, 0xD0, 0x30,
+0x00, 0x8F, 0x00, 0x0D, 0x03, 0xF0, 0x8C, 0xC8, 0x48, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x38, 0x3D, 0x40, 0x3F, 0x00, 0xDC, 0x00, 0xF0, 0x0E,
+0xC0, 0x3F, 0x00, 0xFF, 0x08, 0xDD, 0x03, 0xF2, 0x8E, 0xC4, 0x2F, 0x20, 0xFF,
+0x00, 0xFC, 0x20, 0xB0, 0x0F, 0xC2, 0x1F, 0x02, 0xFF, 0x08, 0xBC, 0x23, 0xF0,
+0x0F, 0xC0, 0x2B, 0x00, 0xA7, 0x00, 0xBC, 0x02, 0xF1, 0x0F, 0xC0, 0x3F, 0x00,
+0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x4E, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0xA0, 0x07, 0x00, 0x13, 0x00, 0x7C, 0x00, 0x34, 0x05, 0xC0,
+0x14, 0x00, 0x5F, 0x01, 0x4C, 0x00, 0xF0, 0x05, 0xC0, 0x34, 0x00, 0xCF, 0x00,
+0x4C, 0x04, 0x30, 0x4C, 0xC0, 0x34, 0x00, 0x5B, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xD0, 0x34, 0x00, 0xD3, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0xDF,
+0x00, 0x0D, 0x03, 0x30, 0x0C, 0xD0, 0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x80, 0x0D, 0x10, 0x21, 0x00, 0xF4, 0x02, 0x10, 0x0E, 0x40, 0x18,
+0x30, 0x6D, 0x00, 0x84, 0x01, 0xD0, 0x06, 0x40, 0x28, 0x00, 0xED, 0x00, 0xAC,
+0x00, 0x90, 0x0E, 0x43, 0x38, 0x48, 0x61, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x42,
+0x38, 0x00, 0xE1, 0x00, 0xB4, 0x01, 0xD0, 0x06, 0x40, 0x1B, 0x00, 0xFD, 0x00,
+0x84, 0x03, 0x10, 0x0E, 0x60, 0x4C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x79, 0x00, 0x21, 0x01, 0xB4, 0x04, 0x10, 0x1E, 0x40, 0x78, 0x00,
+0xED, 0x01, 0x84, 0x06, 0xD0, 0x1E, 0x60, 0x78, 0x00, 0xFD, 0x01, 0x04, 0x40,
+0xD0, 0x1A, 0x40, 0x78, 0x00, 0xE9, 0x21, 0xB6, 0x07, 0xD0, 0x1A, 0x40, 0x78,
+0x00, 0xE1, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01, 0x84,
+0x07, 0x10, 0x17, 0x40, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x28, 0x33, 0x02, 0x81, 0x00, 0x74, 0x27, 0x10, 0x7C, 0x40, 0x30, 0x00, 0xCD,
+0x00, 0x44, 0x03, 0xD0, 0x0C, 0x62, 0x20, 0x01, 0xCD, 0x83, 0x24, 0x07, 0xD0,
+0x2C, 0x40, 0x70, 0x00, 0xC1, 0x00, 0x34, 0x03, 0xD0, 0x0D, 0x42, 0x34, 0x00,
+0xC1, 0x40, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x09, 0x04, 0x03,
+0x15, 0x04, 0x60, 0x48, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20,
+0x19, 0x40, 0x73, 0x42, 0xFC, 0x05, 0x30, 0x57, 0xD0, 0x14, 0x00, 0x5F, 0x00,
+0x4D, 0x01, 0xF0, 0x05, 0xD0, 0x1C, 0x20, 0x7F, 0x05, 0xCC, 0x09, 0x74, 0x27,
+0xC0, 0xDC, 0x03, 0x5B, 0x80, 0x3C, 0x01, 0xF1, 0x05, 0xC0, 0x14, 0x00, 0x53,
+0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x0C, 0x01, 0x30,
+0x27, 0xC0, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x85,
+0x14, 0x0F, 0x24, 0x7C, 0x04, 0xF4, 0x21, 0xC0, 0x07, 0x00, 0x1F, 0x80, 0x7C,
+0x00, 0xF0, 0x01, 0xC0, 0x03, 0x00, 0x1F, 0x10, 0x7C, 0x10, 0x30, 0x61, 0xD0,
+0x07, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xD1, 0x01, 0xC8, 0x07, 0x40, 0x1F, 0x00,
+0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x20, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC1, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x00,
+0x93, 0x01, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0x30, 0x89, 0xC0, 0x24, 0x00, 0x93, 0x04, 0x0C, 0x0A, 0x30, 0x29, 0xC0, 0x22,
+0x70, 0x93, 0x80, 0x7C, 0x06, 0x30, 0x09, 0xC0, 0x64, 0x02, 0x93, 0x05, 0x7C,
+0x02, 0xF0, 0x49, 0xC0, 0x27, 0x02, 0x9F, 0x01, 0x4C, 0x02, 0x30, 0x09, 0xC0,
+0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x10, 0x91,
+0x28, 0x44, 0x02, 0x10, 0x28, 0x40, 0xA4, 0x00, 0x9D, 0x02, 0x74, 0x02, 0x10,
+0x39, 0x40, 0x24, 0x20, 0x81, 0x00, 0x6C, 0x02, 0x10, 0x28, 0x40, 0xA4, 0x00,
+0x91, 0x02, 0x5C, 0x02, 0x10, 0x09, 0x40, 0xE4, 0x08, 0x91, 0x21, 0x74, 0x82,
+0xD0, 0x29, 0x40, 0xE7, 0x00, 0x9D, 0x03, 0x45, 0x02, 0x14, 0x09, 0x40, 0x04,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x46, 0x91, 0x20,
+0x44, 0x02, 0x12, 0x29, 0x40, 0x24, 0x01, 0xBD, 0x04, 0xF4, 0x02, 0x18, 0x0A,
+0x40, 0x24, 0x00, 0x91, 0x80, 0x64, 0x02, 0x19, 0x0D, 0x40, 0x26, 0x00, 0x91,
+0x00, 0xF4, 0x22, 0x1C, 0x0F, 0x40, 0x2C, 0x04, 0xB1, 0x00, 0xF4, 0x06, 0xD0,
+0x0B, 0x40, 0x2F, 0x00, 0x8D, 0x0A, 0x64, 0x02, 0x10, 0x18, 0x40, 0x62, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x24, 0x01, 0x81, 0x04, 0x04,
+0x12, 0x10, 0x48, 0x50, 0x68, 0x00, 0xAD, 0x01, 0xB4, 0x02, 0x10, 0x1A, 0x42,
+0x20, 0x01, 0x91, 0x00, 0x24, 0x12, 0x10, 0x48, 0x40, 0x32, 0x01, 0xA1, 0x01,
+0xD4, 0x03, 0x10, 0x0A, 0x40, 0x28, 0x20, 0xA1, 0x01, 0xB4, 0x02, 0xD0, 0x1A,
+0x40, 0x6B, 0x00, 0x8D, 0x04, 0x25, 0x02, 0x10, 0x58, 0x50, 0x42, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x86, 0x02, 0x53, 0x0A, 0x4D, 0x28,
+0x34, 0xA0, 0x40, 0x84, 0x02, 0x0F, 0x0A, 0x7C, 0x29, 0x30, 0xA2, 0x40, 0x84,
+0x02, 0x13, 0x0A, 0x6C, 0x00, 0x30, 0x05, 0xC0, 0x06, 0x00, 0x13, 0x0A, 0x7C,
+0x00, 0x30, 0xA0, 0xD0, 0x80, 0x02, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0xA1, 0xC0,
+0x8F, 0x02, 0x1F, 0x0A, 0x6C, 0x00, 0x30, 0xA1, 0xC0, 0x76, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x2F, 0x02, 0xBF, 0x08, 0xFC, 0x22, 0xF0,
+0x8B, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF4, 0x09, 0xD0, 0x2F, 0x42,
+0xBF, 0x80, 0xFC, 0x22, 0xF0, 0x8B, 0xC0, 0x29, 0x82, 0x9F, 0x00, 0x5C, 0x02,
+0xF0, 0x09, 0xC0, 0x27, 0x40, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0xBF, 0x08, 0x5C, 0x02, 0xF0, 0x8B, 0xC0, 0x65, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x01, 0xA3, 0x14, 0xFC, 0x32, 0xF0, 0x0B,
+0xD0, 0x2C, 0x00, 0xB3, 0x08, 0xFC, 0x02, 0x30, 0x0B, 0xC0, 0x26, 0x19, 0xB3,
+0x00, 0xCC, 0x06, 0x30, 0x1B, 0xC1, 0x6E, 0x04, 0xBF, 0x00, 0xFC, 0x02, 0x30,
+0x0B, 0xC0, 0x3C, 0x00, 0xF3, 0x00, 0xCC, 0x03, 0x31, 0x0B, 0xC0, 0x2C, 0x02,
+0xBF, 0x00, 0xCC, 0x02, 0xF0, 0x8F, 0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x00, 0x17, 0x45, 0x11, 0x04, 0x74, 0x30, 0xD0, 0x20, 0x41,
+0x14, 0x44, 0x51, 0x00, 0x74, 0x50, 0x10, 0x41, 0x50, 0x04, 0x02, 0x13, 0x00,
+0x6C, 0x28, 0x14, 0x01, 0x40, 0x04, 0x00, 0x5D, 0x04, 0x74, 0x00, 0x10, 0x01,
+0x41, 0x04, 0x04, 0x11, 0x00, 0x44, 0x00, 0x10, 0x45, 0x40, 0x14, 0x01, 0x1D,
+0x12, 0x45, 0x00, 0xD0, 0x81, 0x40, 0x70, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x21, 0x43, 0x81, 0x14, 0x34, 0x12, 0xD0, 0xC8, 0x50, 0x20,
+0x10, 0x81, 0x00, 0x74, 0x16, 0x14, 0x48, 0x41, 0x24, 0x00, 0x81, 0x00, 0x24,
+0x02, 0x90, 0x08, 0x40, 0x22, 0x00, 0x8D, 0x94, 0x74, 0x02, 0x98, 0x49, 0x40,
+0x22, 0x00, 0x91, 0x00, 0x14, 0x02, 0x90, 0x48, 0x41, 0x22, 0x11, 0x8D, 0x0C,
+0x04, 0x02, 0xD0, 0x18, 0x40, 0x48, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x28, 0x25, 0x00, 0x91, 0x10, 0x74, 0x02, 0xD0, 0x49, 0x41, 0x20, 0x00,
+0x91, 0x00, 0x74, 0x02, 0x10, 0x29, 0x40, 0xA4, 0x00, 0x91, 0x00, 0x64, 0x62,
+0x98, 0x19, 0x44, 0x24, 0x02, 0x9D, 0x00, 0x74, 0x02, 0x9C, 0x09, 0x50, 0x22,
+0x00, 0x91, 0x00, 0x54, 0x02, 0x90, 0x08, 0x50, 0x26, 0x00, 0x9D, 0x08, 0x44,
+0x02, 0xD0, 0x08, 0x40, 0x60, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x00, 0x25, 0x00, 0x93, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0, 0xA4, 0x00, 0x93,
+0x02, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0x24, 0x40, 0x93, 0x10, 0x6D, 0x0A, 0xB0,
+0x79, 0xC0, 0x26, 0x10, 0x9F, 0x02, 0x3C, 0x02, 0xB0, 0x08, 0xC2, 0x26, 0x40,
+0x83, 0x00, 0x5C, 0x42, 0xB4, 0x29, 0xC0, 0xA6, 0x00, 0x9F, 0x00, 0x4C, 0x02,
+0xF0, 0x19, 0xC0, 0x14, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08,
+0xE5, 0x00, 0x9F, 0x10, 0x7C, 0xA6, 0xF0, 0x18, 0xD0, 0x27, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF2, 0x09, 0xC0, 0x25, 0x00, 0x97, 0x15, 0x7E, 0x06, 0x70, 0x09,
+0xC0, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x26, 0x72, 0x09, 0xC1, 0x25, 0x00, 0x9F,
+0x00, 0x6D, 0x02, 0x70, 0x09, 0xC0, 0x25, 0x04, 0x9F, 0x10, 0x7E, 0x02, 0xF0,
+0x49, 0xD1, 0x5B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x81,
+0x01, 0x13, 0x02, 0x4C, 0x20, 0x34, 0x81, 0xC0, 0x86, 0x44, 0x13, 0x12, 0x6D,
+0x04, 0xF0, 0x81, 0xC0, 0x04, 0x00, 0x1F, 0x02, 0x4C, 0x88, 0x30, 0x20, 0xC0,
+0x04, 0x08, 0x1F, 0x02, 0x4D, 0x40, 0xF0, 0x01, 0xC0, 0x06, 0x00, 0x13, 0x00,
+0x7C, 0x40, 0xF0, 0x21, 0xD0, 0x84, 0x40, 0x13, 0x08, 0x4C, 0x00, 0xF0, 0x01,
+0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x1C, 0x00,
+0x71, 0x82, 0x44, 0x05, 0x10, 0x17, 0xC0, 0x9C, 0x00, 0x71, 0x02, 0x84, 0x05,
+0xD0, 0x16, 0x40, 0x10, 0x00, 0x7D, 0x00, 0x14, 0x01, 0x14, 0x37, 0x40, 0x9C,
+0x00, 0x7D, 0x03, 0xC4, 0x11, 0xD0, 0x17, 0xC0, 0x1C, 0x00, 0x71, 0x00, 0xB0,
+0x4D, 0xD0, 0x07, 0x40, 0x1C, 0x00, 0x71, 0x01, 0x45, 0x01, 0xD0, 0x17, 0x41,
+0x50, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x32, 0x40, 0x81,
+0x02, 0x24, 0x07, 0x10, 0x0C, 0x40, 0xB0, 0x00, 0xC1, 0x02, 0x04, 0x27, 0xD0,
+0x08, 0x40, 0x30, 0x00, 0x5D, 0x00, 0x04, 0x03, 0x90, 0xB8, 0x51, 0xB0, 0x21,
+0xCD, 0x05, 0x00, 0x07, 0xD0, 0x2C, 0x40, 0x30, 0x00, 0xC1, 0x13, 0x34, 0x0B,
+0xD8, 0x0C, 0x40, 0x30, 0x00, 0x91, 0x03, 0x04, 0x02, 0xD0, 0x2C, 0x40, 0x50,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x28, 0x00, 0x31, 0x01,
+0xA4, 0x06, 0x10, 0x06, 0x40, 0x38, 0x00, 0xE1, 0x01, 0x84, 0x03, 0xD0, 0x0E,
+0x42, 0x38, 0x21, 0xED, 0x00, 0x94, 0x03, 0x90, 0x08, 0x40, 0x18, 0x04, 0xED,
+0x03, 0x84, 0x01, 0xD1, 0x2F, 0x50, 0x38, 0x00, 0x21, 0x10, 0xB4, 0x03, 0xD0,
+0x0E, 0x40, 0x78, 0x00, 0xA1, 0x00, 0x84, 0x02, 0xD0, 0x08, 0x40, 0x14, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x5C, 0x02, 0x63, 0x01, 0xEC,
+0x07, 0x30, 0x1E, 0xD1, 0x7C, 0x00, 0xF3, 0x01, 0x8C, 0x07, 0xF0, 0x1A, 0xD0,
+0xF8, 0x21, 0x3F, 0x01, 0x84, 0x07, 0xB0, 0x16, 0xC0, 0x78, 0x00, 0xFF, 0x21,
+0x8C, 0x07, 0xF0, 0x1E, 0xC0, 0x7C, 0x40, 0x23, 0x01, 0xBC, 0x07, 0xF0, 0x1F,
+0xC0, 0x7C, 0x00, 0x73, 0x01, 0x84, 0x06, 0xF0, 0x1E, 0xD0, 0x54, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x9D, 0x00, 0x1F, 0x80, 0x5D, 0x12,
+0xF0, 0x07, 0xC0, 0x35, 0x08, 0x5F, 0x00, 0x7C, 0x03, 0xF2, 0x00, 0xC0, 0x77,
+0x00, 0x9F, 0x00, 0x3C, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C,
+0x03, 0xF0, 0x0C, 0xC0, 0x35, 0x08, 0x1F, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0,
+0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x01, 0xC0, 0x43, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x7D, 0x00, 0x23, 0x01, 0xCC, 0x3F, 0xF8,
+0x8B, 0xC0, 0x7C, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0xB0, 0x9B, 0xC0, 0x7F, 0x00,
+0xE7, 0x01, 0x8C, 0x87, 0x24, 0x1E, 0xC0, 0x5D, 0x00, 0xF3, 0x01, 0xD4, 0x25,
+0xB0, 0x1F, 0xD8, 0x7C, 0x00, 0x32, 0x01, 0xFC, 0x05, 0xF0, 0x1F, 0xC0, 0x7C,
+0x00, 0x73, 0x01, 0xCC, 0x06, 0xF0, 0x17, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x00, 0x29, 0x00, 0x21, 0x82, 0x84, 0x62, 0x30, 0x47,
+0x40, 0x3C, 0x00, 0xE1, 0x00, 0xBC, 0x02, 0x10, 0xCE, 0x40, 0x3B, 0x00, 0xEB,
+0x00, 0xAC, 0x13, 0x30, 0x0E, 0x40, 0x98, 0x40, 0xE1, 0x08, 0x84, 0x01, 0x14,
+0x4B, 0xC1, 0x3C, 0x00, 0x21, 0x08, 0xB4, 0x08, 0xD0, 0x2E, 0x40, 0x3C, 0x00,
+0xE1, 0x00, 0x84, 0x02, 0xD0, 0x82, 0x40, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x61, 0x00, 0x04, 0x13, 0x50, 0x8A, 0x50,
+0x38, 0x00, 0xE9, 0x00, 0xF4, 0x03, 0x10, 0x0A, 0x60, 0x33, 0x00, 0xB5, 0x00,
+0xA4, 0x83, 0x80, 0x0F, 0x50, 0x3B, 0x00, 0x61, 0x00, 0x94, 0x00, 0x94, 0x0E,
+0x60, 0x38, 0x00, 0x29, 0x00, 0xB4, 0x01, 0xD0, 0x0E, 0x40, 0x38, 0x00, 0xE1,
+0x00, 0x84, 0x02, 0xD0, 0x06, 0x40, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x28, 0x51, 0x00, 0x01, 0x06, 0x05, 0x0A, 0x12, 0xB5, 0x41, 0x30,
+0x00, 0xC9, 0x00, 0x34, 0x02, 0x10, 0x04, 0x60, 0xF3, 0x40, 0x89, 0x03, 0x24,
+0x23, 0x10, 0x1C, 0x40, 0x32, 0x00, 0xD1, 0x00, 0x04, 0x01, 0x90, 0x08, 0x40,
+0x30, 0x00, 0x09, 0x00, 0x34, 0x00, 0xD0, 0x0D, 0x40, 0x30, 0x00, 0xD1, 0x00,
+0x05, 0x02, 0xD0, 0x18, 0x40, 0x13, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0x65, 0x40, 0x13, 0x07, 0x4C, 0x0E, 0x70, 0x09, 0xC0, 0x34, 0x00,
+0xDB, 0x00, 0x7C, 0x03, 0xB0, 0x08, 0xC2, 0x3F, 0x20, 0x07, 0x0D, 0x0C, 0x0A,
+0xB0, 0x5D, 0xC0, 0x73, 0x04, 0xD3, 0x00, 0x5C, 0x02, 0xB0, 0x0D, 0xC0, 0x34,
+0x00, 0x0B, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xD0, 0x34, 0x00, 0x93, 0x05, 0x4C,
+0x03, 0xF0, 0x0C, 0xC1, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x08, 0x27, 0x02, 0x3F, 0x00, 0x7C, 0x02, 0x70, 0x21, 0xC0, 0x27, 0x20, 0x97,
+0x00, 0x5C, 0x07, 0xF0, 0x29, 0xC0, 0x37, 0x06, 0x97, 0x00, 0x7C, 0x42, 0xF0,
+0x0D, 0xC0, 0x35, 0x20, 0x9F, 0x00, 0x7C, 0x00, 0x72, 0x25, 0xC0, 0xA5, 0x00,
+0x13, 0x00, 0x7C, 0x08, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF0, 0x09, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08,
+0x0F, 0x60, 0x73, 0x00, 0xAC, 0x42, 0xB0, 0x03, 0xC0, 0x1C, 0x00, 0xFF, 0x00,
+0xFC, 0x03, 0x30, 0x4B, 0xC0, 0x3E, 0x00, 0x33, 0x05, 0xCC, 0x07, 0x30, 0x4F,
+0x40, 0x37, 0x00, 0xF3, 0x00, 0xEC, 0x02, 0xE0, 0x3F, 0xC0, 0x1C, 0x00, 0x31,
+0x00, 0xCC, 0x01, 0xF0, 0x07, 0x80, 0x5C, 0x00, 0x53, 0x00, 0xCC, 0x07, 0xF0,
+0x3F, 0xE0, 0x00, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xC6,
+0x00, 0x11, 0x22, 0x44, 0x06, 0x10, 0x31, 0x40, 0x14, 0x00, 0x5D, 0x01, 0x34,
+0x07, 0x10, 0x59, 0x42, 0x30, 0x40, 0x91, 0x40, 0x54, 0x03, 0x10, 0x7D, 0x40,
+0xF7, 0x00, 0x9B, 0x01, 0x44, 0x06, 0xD0, 0x05, 0x50, 0x34, 0x00, 0x11, 0x07,
+0x4C, 0x0C, 0xD0, 0x3D, 0x40, 0xD4, 0x02, 0xD1, 0x00, 0x44, 0x02, 0xD0, 0x39,
+0x50, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xC2, 0x00,
+0x01, 0x00, 0x64, 0x13, 0x90, 0x19, 0x41, 0x76, 0x00, 0xDD, 0x88, 0x74, 0x07,
+0x14, 0x09, 0x48, 0x34, 0x00, 0x99, 0x40, 0x46, 0x12, 0x10, 0x0D, 0x48, 0x67,
+0x00, 0xD1, 0x04, 0x64, 0x04, 0xD0, 0x2C, 0x40, 0xB2, 0x01, 0x15, 0x01, 0x64,
+0x05, 0xD0, 0x8D, 0x40, 0x31, 0x04, 0x51, 0x00, 0x44, 0x13, 0xD0, 0x2D, 0x40,
+0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x02, 0x10, 0x00, 0x50, 0x62, 0x00, 0x8D, 0x00, 0x34, 0x07, 0x14,
+0x09, 0x42, 0x34, 0x00, 0x91, 0x00, 0x14, 0x02, 0x10, 0x0C, 0x60, 0x23, 0x40,
+0xC9, 0x00, 0x04, 0x00, 0xD0, 0x0C, 0x40, 0x22, 0x80, 0x05, 0x80, 0x04, 0x00,
+0xD0, 0x08, 0x40, 0x21, 0x00, 0xC1, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x40, 0x40,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x53, 0x00,
+0xEC, 0x03, 0xB2, 0x03, 0xD0, 0x36, 0x00, 0xDF, 0x80, 0x7C, 0x03, 0x14, 0x09,
+0xD0, 0x36, 0x00, 0x92, 0x00, 0x4C, 0x03, 0x34, 0x0D, 0x40, 0x27, 0x10, 0x43,
+0x00, 0x6C, 0x00, 0xF0, 0x0D, 0xD0, 0x16, 0x00, 0x17, 0x00, 0x6C, 0x01, 0xF0,
+0x04, 0xD0, 0x35, 0x00, 0xD3, 0x00, 0x4C, 0x03, 0xF0, 0x09, 0xC0, 0x00, 0xC0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0B, 0x00, 0x3F, 0x00, 0xFC,
+0x02, 0xF1, 0x03, 0xC0, 0x3D, 0x00, 0xFF, 0x00, 0xBC, 0x01, 0xF4, 0x0B, 0xC0,
+0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xFF, 0x00,
+0xB4, 0x00, 0xF0, 0x0F, 0xC0, 0x3D, 0x00, 0x3B, 0x00, 0xFC, 0x00, 0xF0, 0x0F,
+0xC0, 0x3E, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x17, 0x60, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x02,
+0xF0, 0x1F, 0xC8, 0x3F, 0x01, 0xBF, 0x22, 0xFC, 0x0A, 0x30, 0x0B, 0xC0, 0xBF,
+0x05, 0xEF, 0x09, 0xEC, 0x10, 0xB0, 0x3F, 0xC0, 0xBD, 0x00, 0xB3, 0x04, 0xCC,
+0x82, 0x32, 0x2F, 0xC4, 0x2F, 0x40, 0xF2, 0x01, 0xCC, 0x13, 0xF0, 0x12, 0x44,
+0x7A, 0x20, 0x33, 0xCC, 0xEC, 0x06, 0x90, 0x1F, 0x40, 0x0E, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x77, 0x00, 0xDD, 0x01, 0x74, 0x26, 0xD0,
+0x1D, 0x40, 0xBF, 0x05, 0x1D, 0x02, 0x74, 0x38, 0x10, 0xC1, 0x40, 0xBF, 0x00,
+0xDD, 0x00, 0x64, 0x2C, 0x04, 0x4D, 0x40, 0xBF, 0x08, 0x11, 0x14, 0x74, 0x40,
+0x10, 0x6F, 0x40, 0xE7, 0x00, 0xD5, 0x01, 0xC4, 0x0F, 0xD0, 0x19, 0x40, 0x74,
+0x00, 0x01, 0x22, 0x44, 0x06, 0x12, 0x1D, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x31, 0x00, 0xCD, 0x00, 0x34, 0x80, 0xD8, 0x0C,
+0x40, 0xB3, 0x00, 0x8D, 0x26, 0x34, 0x02, 0x10, 0x00, 0x41, 0x33, 0x11, 0xCD,
+0x80, 0x24, 0x02, 0x00, 0x0C, 0x40, 0x31, 0x83, 0x81, 0x8C, 0x04, 0xB2, 0x12,
+0x2C, 0x60, 0x03, 0x42, 0xD5, 0x00, 0x14, 0x23, 0xD0, 0x08, 0x40, 0x33, 0x00,
+0x45, 0x26, 0x64, 0x01, 0x90, 0x0C, 0x40, 0x4E, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x28, 0x35, 0x00, 0xDD, 0x00, 0x74, 0x04, 0xD0, 0x0D, 0x44,
+0x37, 0x00, 0x9D, 0x01, 0x74, 0x04, 0x10, 0x11, 0x44, 0x37, 0x00, 0xDD, 0x00,
+0x66, 0x84, 0x10, 0x0D, 0x40, 0x37, 0x00, 0x91, 0x01, 0x74, 0x06, 0x18, 0x0D,
+0x40, 0x47, 0x00, 0x55, 0x11, 0x54, 0x03, 0xD0, 0x19, 0x43, 0x37, 0x80, 0x11,
+0x18, 0x44, 0x0E, 0x10, 0x0D, 0x42, 0x0C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x20, 0xA8, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x1E, 0xF0, 0x0D, 0xC0, 0x37,
+0x00, 0x9F, 0x87, 0x7C, 0xC4, 0x30, 0x19, 0xC2, 0x37, 0x18, 0xDF, 0x00, 0x6C,
+0x04, 0x30, 0x0D, 0xC4, 0x35, 0x08, 0x13, 0x01, 0x4C, 0x1E, 0x34, 0x0D, 0xC2,
+0x67, 0x40, 0xD7, 0x01, 0x5C, 0x03, 0xF0, 0x19, 0xC0, 0x37, 0x00, 0x95, 0x02,
+0x2C, 0x0E, 0xB0, 0x0D, 0xC0, 0x22, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x07, 0x80, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x82, 0xF0, 0x0F, 0xC0, 0x3F, 0x90,
+0x3F, 0x90, 0xBC, 0x00, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xFF, 0x03, 0x9C, 0x40,
+0x70, 0x0F, 0xC0, 0x37, 0x40, 0x3F, 0x40, 0xFC, 0x00, 0x70, 0x0F, 0xC0, 0x2F,
+0x00, 0xBF, 0x00, 0xEC, 0x03, 0xF0, 0x0B, 0xC0, 0x3C, 0x0C, 0x2F, 0x01, 0xFC,
+0x02, 0xF0, 0x0F, 0xC0, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x08, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0x93,
+0x02, 0x7C, 0x0A, 0x30, 0x01, 0xC0, 0x34, 0x40, 0xD3, 0x04, 0x4E, 0x02, 0xF1,
+0x0D, 0xC0, 0x30, 0x00, 0x13, 0x08, 0x7C, 0x0A, 0xF0, 0x0D, 0xC0, 0x24, 0x00,
+0xD3, 0x22, 0x7C, 0x03, 0x30, 0x29, 0xC0, 0x34, 0x00, 0x13, 0x02, 0x4C, 0x0D,
+0xF0, 0x0D, 0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0,
+0x34, 0x00, 0xDD, 0x00, 0x74, 0x12, 0xD1, 0x0D, 0x00, 0x3F, 0x00, 0x91, 0x80,
+0x74, 0x00, 0x10, 0x01, 0x40, 0x3C, 0x24, 0xDB, 0x02, 0x66, 0x4A, 0xD0, 0x0D,
+0x48, 0xBC, 0x42, 0x1B, 0x8B, 0x74, 0x02, 0xF0, 0x3F, 0xC1, 0x62, 0x01, 0x8A,
+0x04, 0xF0, 0x03, 0xB1, 0xA8, 0x40, 0x30, 0x00, 0x1B, 0x0E, 0x44, 0x0F, 0xD0,
+0x0C, 0x40, 0x6F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32,
+0x00, 0xCD, 0x00, 0x34, 0x00, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x01, 0x00, 0x34,
+0x02, 0x10, 0x08, 0x40, 0xF0, 0x09, 0xD1, 0x81, 0x24, 0x0E, 0xD0, 0x0C, 0x48,
+0x70, 0x00, 0x89, 0x03, 0x74, 0x00, 0xD0, 0x6C, 0x42, 0x02, 0x01, 0xC5, 0x30,
+0x20, 0x07, 0x00, 0xBC, 0x40, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0xD0, 0x0C,
+0x40, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x80, 0x78, 0x00,
+0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0x61, 0x11, 0xB4, 0x07,
+0x10, 0x16, 0x40, 0x78, 0x00, 0xE1, 0x01, 0xA4, 0x25, 0xD0, 0x1E, 0x40, 0x78,
+0x00, 0x61, 0x01, 0xB4, 0x05, 0x50, 0x1E, 0x40, 0x7A, 0x00, 0xED, 0x01, 0xB4,
+0x07, 0x90, 0x0F, 0x40, 0x78, 0x04, 0xE9, 0x01, 0x84, 0x0E, 0xD0, 0x1E, 0x40,
+0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF,
+0x00, 0x3C, 0x01, 0xD0, 0x8C, 0xC0, 0x37, 0x00, 0x43, 0x00, 0x7C, 0x03, 0x10,
+0x8D, 0xD0, 0x34, 0x22, 0xC1, 0x90, 0x04, 0x2B, 0xD8, 0x0D, 0xD0, 0x30, 0x06,
+0xC9, 0x00, 0x3C, 0x01, 0xD0, 0x4D, 0xC0, 0x12, 0x00, 0xC3, 0x04, 0x2C, 0x53,
+0x30, 0x8C, 0x80, 0x30, 0x00, 0xC3, 0xE4, 0x0C, 0x83, 0xF0, 0x0C, 0xC0, 0x4B,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x00,
+0xFC, 0x01, 0xF0, 0x0F, 0xC0, 0x3F, 0x40, 0xFF, 0x00, 0xFC, 0x03, 0xF4, 0x8F,
+0xC0, 0x3F, 0x02, 0xFF, 0x00, 0x5D, 0xA1, 0xF8, 0x0F, 0xC0, 0xBF, 0x00, 0xFF,
+0x80, 0xFC, 0x03, 0xF0, 0x0F, 0xC1, 0x1B, 0x02, 0xFB, 0x00, 0xB0, 0x4B, 0xF0,
+0xCF, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x0B, 0x60,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x80, 0xDF, 0x00, 0x7C,
+0x01, 0x70, 0x0D, 0xC4, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x05, 0x30, 0x0D, 0xC2,
+0xB5, 0x02, 0xCF, 0x00, 0x5D, 0x03, 0x38, 0x1D, 0xC0, 0x35, 0x01, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x6D, 0xC0, 0x10, 0x00, 0xC3, 0x00, 0x6C, 0x13, 0xF0, 0x09,
+0xC0, 0x37, 0xA0, 0xDF, 0x00, 0x4C, 0x03, 0xD0, 0x0C, 0xC0, 0x42, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x88, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x03,
+0xD0, 0x0E, 0x00, 0x3B, 0x13, 0x6C, 0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x3B,
+0x04, 0xED, 0x00, 0x94, 0x03, 0x41, 0x0E, 0x40, 0x38, 0x00, 0xED, 0x00, 0xB4,
+0x01, 0xD0, 0x8F, 0xC0, 0x3A, 0x00, 0xE5, 0x00, 0x84, 0x03, 0xD0, 0x0A, 0x42,
+0x3B, 0x80, 0xCD, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x4C, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79, 0x88, 0xE5, 0x21, 0xB4, 0x47, 0xD0,
+0x1E, 0x44, 0x7B, 0x12, 0xEC, 0x01, 0x34, 0x07, 0x90, 0x1E, 0x40, 0x7B, 0x01,
+0xED, 0x21, 0x14, 0x07, 0x01, 0x1E, 0x4C, 0x79, 0x02, 0xED, 0x01, 0xB4, 0x07,
+0xD8, 0x5F, 0x40, 0x78, 0x00, 0xF5, 0x11, 0xB4, 0x17, 0xD0, 0x3A, 0x40, 0x7B,
+0x00, 0xED, 0x21, 0x84, 0x47, 0xD0, 0x1E, 0x48, 0x12, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x36, 0x0F, 0xD0, 0x0C,
+0x40, 0x33, 0x00, 0xCD, 0x01, 0x34, 0x03, 0x10, 0x9C, 0x40, 0x33, 0x00, 0x8D,
+0xA0, 0x15, 0x07, 0x10, 0x0C, 0x40, 0x30, 0x10, 0xDD, 0x03, 0x34, 0x07, 0xD0,
+0x0C, 0x40, 0xF2, 0x00, 0xC5, 0x01, 0x14, 0x03, 0xD0, 0x08, 0x40, 0x33, 0x80,
+0xDD, 0x0D, 0x04, 0x07, 0xD0, 0x0C, 0x40, 0x5A, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x17, 0xA8, 0x15, 0x08, 0x5F, 0x00, 0xFC, 0x01, 0xF0, 0x05, 0xC0,
+0x17, 0x00, 0x7F, 0x0E, 0xF4, 0x01, 0xB0, 0xA7, 0xC2, 0x15, 0x08, 0x4F, 0x05,
+0xDC, 0x1D, 0x35, 0x05, 0xC4, 0x15, 0x00, 0x7F, 0x85, 0xFC, 0xED, 0xF0, 0x05,
+0xC0, 0x1C, 0x81, 0x77, 0x01, 0x7C, 0x01, 0xF1, 0x06, 0xC0, 0x17, 0x08, 0x7D,
+0x02, 0xCD, 0x05, 0xF0, 0x04, 0xC0, 0x5E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x02, 0x78, 0x04, 0x74, 0x01, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x7D,
+0x40, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x06, 0x7C, 0x00, 0xC0, 0x00, 0xC0,
+0x87, 0x81, 0x1F, 0x10, 0x64, 0x08, 0xF2, 0x21, 0xC1, 0x87, 0x20, 0x1F, 0x02,
+0x7D, 0x08, 0xF0, 0x01, 0xC0, 0x49, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x27, 0x00, 0x9F, 0x00, 0x3C, 0x02, 0x30, 0x09, 0xE0, 0x27, 0x00,
+0x83, 0x00, 0x4C, 0x02, 0xF0, 0x09, 0xC8, 0x26, 0x02, 0x9F, 0x04, 0x0C, 0x02,
+0x34, 0x09, 0xC0, 0x27, 0x01, 0x9C, 0x08, 0x0C, 0x02, 0x30, 0x59, 0xC0, 0xA0,
+0x20, 0x93, 0x00, 0x5C, 0x86, 0xF0, 0x19, 0xC0, 0xA4, 0x00, 0x9F, 0x00, 0x4C,
+0x06, 0xF0, 0x09, 0xD0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x26, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x14, 0x09, 0x40, 0x27, 0x00, 0x91,
+0x00, 0x45, 0x02, 0xD0, 0x09, 0xD0, 0xA4, 0x00, 0x9D, 0x02, 0x6C, 0x42, 0x50,
+0x09, 0x40, 0x27, 0x21, 0x9D, 0x02, 0x45, 0x02, 0x14, 0x29, 0x50, 0xE4, 0x40,
+0x81, 0x13, 0x44, 0x86, 0xD0, 0x89, 0x40, 0x64, 0x08, 0x9D, 0x02, 0x44, 0x1A,
+0xD0, 0x19, 0x40, 0x04, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0,
+0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x23, 0x00, 0x91, 0x08,
+0x44, 0x02, 0xD9, 0x0C, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x65, 0x22, 0x92, 0x09,
+0x44, 0x27, 0x00, 0xDD, 0x02, 0x56, 0x02, 0x50, 0x09, 0x48, 0x34, 0x04, 0x91,
+0xA4, 0x54, 0x2A, 0xD1, 0x29, 0x50, 0xA6, 0x00, 0x9D, 0x0A, 0x64, 0x22, 0xD0,
+0x89, 0x60, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20,
+0x00, 0x8D, 0x00, 0x34, 0x12, 0x10, 0x08, 0x40, 0x23, 0x31, 0x81, 0x04, 0x04,
+0x12, 0xD8, 0x48, 0x4C, 0x20, 0x01, 0x8D, 0x01, 0x24, 0x12, 0x90, 0x08, 0x40,
+0x23, 0x21, 0x8D, 0x24, 0x16, 0x12, 0x50, 0x4C, 0x04, 0x20, 0x01, 0x90, 0x20,
+0x00, 0x12, 0xD0, 0x08, 0x40, 0x22, 0x00, 0x8D, 0x08, 0x24, 0x02, 0xD0, 0x08,
+0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00,
+0x1F, 0x00, 0x74, 0x00, 0x30, 0x01, 0x40, 0x87, 0x0A, 0x53, 0x0A, 0x4C, 0x28,
+0xF0, 0xA1, 0xC2, 0x94, 0x02, 0x1F, 0x0A, 0x6C, 0x00, 0x30, 0xA0, 0xC0, 0x87,
+0x02, 0x1F, 0x0A, 0x5C, 0x28, 0x70, 0xA1, 0x80, 0x04, 0x10, 0x12, 0x00, 0x5C,
+0x00, 0xF0, 0x01, 0xC0, 0x06, 0x00, 0x1D, 0x36, 0x6D, 0x00, 0xF0, 0x01, 0xC0,
+0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x27, 0x00, 0x9F,
+0x00, 0xFC, 0x23, 0xF0, 0x09, 0xC0, 0x27, 0x42, 0xBF, 0x08, 0xFC, 0x22, 0xF0,
+0x8B, 0x40, 0x27, 0x02, 0xBF, 0x20, 0xFD, 0x22, 0x70, 0x09, 0xC0, 0x27, 0x02,
+0xBF, 0x08, 0xE8, 0x22, 0xB0, 0x89, 0xC0, 0x2F, 0x02, 0xBF, 0x00, 0x7C, 0x22,
+0xF3, 0x0B, 0xC0, 0x25, 0x00, 0xBF, 0x04, 0xDC, 0x02, 0xF0, 0x09, 0xC0, 0x77,
+0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x27, 0x00, 0x9F, 0x20,
+0xFC, 0x16, 0x30, 0x09, 0xC0, 0xE7, 0x20, 0xBF, 0x21, 0x6C, 0x13, 0xF0, 0xD9,
+0xC6, 0xEF, 0x08, 0xB3, 0x02, 0xCC, 0x16, 0xF0, 0x09, 0xC0, 0x6F, 0x04, 0xB3,
+0x07, 0x4C, 0x1E, 0xF0, 0x5B, 0xC0, 0x68, 0x00, 0xB3, 0x00, 0xFC, 0x12, 0x34,
+0x0B, 0xC2, 0x2F, 0x20, 0xBF, 0x00, 0xC4, 0x02, 0xB4, 0x0B, 0xC0, 0x77, 0x80,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00, 0x1D, 0x00, 0x74,
+0x28, 0x10, 0x01, 0x4C, 0x47, 0x08, 0x1C, 0x17, 0x45, 0x51, 0xD0, 0xF5, 0x40,
+0xC7, 0x40, 0x11, 0x05, 0x54, 0x08, 0x70, 0x51, 0x41, 0x47, 0x40, 0x11, 0x03,
+0x45, 0x0D, 0xD0, 0x71, 0x51, 0x84, 0x40, 0x15, 0x00, 0x74, 0x00, 0x11, 0x01,
+0x40, 0x07, 0x00, 0x1D, 0x20, 0x44, 0x01, 0x10, 0x01, 0x40, 0x62, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0, 0x23, 0x00, 0x8D, 0x00, 0x34, 0x03,
+0x10, 0x08, 0x40, 0xA3, 0x01, 0x8D, 0x02, 0x04, 0xB2, 0xD0, 0x08, 0x40, 0xA3,
+0x01, 0x81, 0x00, 0x25, 0x0E, 0xC1, 0x08, 0x40, 0x21, 0x04, 0x81, 0x07, 0x24,
+0x32, 0x50, 0x88, 0x40, 0xA2, 0x20, 0x81, 0x40, 0x34, 0x22, 0x50, 0x08, 0x40,
+0x23, 0x00, 0x8D, 0x00, 0x46, 0x03, 0xD1, 0x08, 0x40, 0x4B, 0x80, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x00, 0x74, 0x22, 0x10,
+0x09, 0x40, 0x27, 0x00, 0x9D, 0x14, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x37, 0x00,
+0x91, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x27, 0x80, 0x91, 0x40, 0x64, 0x12,
+0xD8, 0x09, 0x60, 0x26, 0x01, 0x95, 0x02, 0x64, 0x02, 0x58, 0x0D, 0x40, 0x27,
+0x00, 0xDD, 0x04, 0x44, 0x02, 0x50, 0x09, 0x40, 0x62, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0x28, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x0A, 0x34, 0x09,
+0xC0, 0x27, 0x08, 0x9F, 0x42, 0x4C, 0x02, 0xF0, 0x29, 0xC0, 0x27, 0x20, 0x91,
+0x08, 0x6D, 0x0A, 0xF0, 0x09, 0xC0, 0x25, 0x20, 0x93, 0x00, 0x6C, 0x06, 0x70,
+0x09, 0x42, 0xA6, 0xA1, 0x93, 0x22, 0x74, 0x02, 0x78, 0x09, 0xC1, 0x27, 0x00,
+0x9F, 0x06, 0x4D, 0x02, 0xF4, 0x09, 0xC0, 0x17, 0x80, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x00, 0x25, 0x08, 0x9F, 0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x80, 0x7C, 0x22, 0xF0, 0x99, 0xC0, 0x27, 0x00, 0x9F, 0x11,
+0x5C, 0x16, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x8F, 0x13, 0x5C, 0x06, 0xF0, 0x09,
+0xC0, 0x65, 0x80, 0x9F, 0x00, 0x7C, 0x02, 0xB0, 0x09, 0xC1, 0x27, 0x00, 0x9F,
+0x01, 0x7E, 0x22, 0xB4, 0x09, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF8, 0x01, 0xC0, 0x07,
+0x80, 0x13, 0x06, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x47, 0x80, 0x1F, 0x00, 0x4C,
+0x00, 0x70, 0x01, 0xC0, 0x47, 0x10, 0x1F, 0x00, 0x7C, 0x08, 0x34, 0x11, 0xC0,
+0x87, 0x04, 0x13, 0x26, 0x2C, 0x10, 0xF0, 0x01, 0xC0, 0x05, 0x00, 0x1F, 0x04,
+0x7C, 0x48, 0x30, 0x81, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x20, 0x14, 0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x17, 0xC0,
+0x70, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x00, 0x5F, 0x80, 0x6F, 0x46, 0xC5, 0x05,
+0x70, 0x05, 0x40, 0x1F, 0x00, 0x7D, 0x81, 0x74, 0x01, 0x30, 0x47, 0x40, 0x1B,
+0x00, 0x71, 0x03, 0xCC, 0x09, 0x60, 0x37, 0x40, 0x1C, 0xA0, 0x7D, 0x02, 0xB4,
+0x09, 0x10, 0x05, 0x40, 0x43, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x31, 0x10, 0xD1,
+0x03, 0x34, 0x03, 0xD2, 0x0C, 0x48, 0x77, 0x0A, 0xCD, 0x03, 0x04, 0x07, 0xD3,
+0x0C, 0x44, 0x37, 0x00, 0xCD, 0x08, 0x36, 0x03, 0x10, 0x1D, 0x40, 0xB1, 0x60,
+0x01, 0x02, 0x04, 0x23, 0xD0, 0x3C, 0x40, 0x81, 0x04, 0xDD, 0x80, 0x34, 0x0B,
+0x04, 0x1C, 0x60, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80,
+0x38, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x7B, 0x00, 0xE1, 0x02,
+0xB6, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xE5, 0x80, 0x85, 0x08, 0x50, 0x0E,
+0x60, 0x9B, 0x00, 0x6D, 0x40, 0x36, 0x07, 0x18, 0x0E, 0x40, 0x3B, 0x40, 0x21,
+0x10, 0x86, 0x03, 0x50, 0x17, 0x49, 0x08, 0x00, 0xAD, 0x02, 0xB6, 0x03, 0x10,
+0x0E, 0x60, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x78,
+0x00, 0xEF, 0x01, 0xBC, 0x06, 0xD0, 0x1E, 0xC2, 0x71, 0x02, 0x61, 0x01, 0xBC,
+0x3F, 0xF0, 0xFE, 0xC0, 0x5B, 0x00, 0xED, 0x01, 0x8D, 0x05, 0x78, 0x3E, 0x41,
+0x7B, 0x00, 0xED, 0x01, 0xBC, 0x07, 0x30, 0x1E, 0xC2, 0x69, 0x00, 0x63, 0xA0,
+0x8C, 0x07, 0xD1, 0x12, 0xC0, 0x49, 0x00, 0xED, 0x81, 0xBC, 0x06, 0x38, 0x1E,
+0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB0, 0x35, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0xB7, 0x00, 0x5F, 0x00, 0x7C, 0x03,
+0xC0, 0x0D, 0x40, 0x17, 0x00, 0xCF, 0x00, 0x7C, 0x00, 0xF1, 0x2D, 0xC0, 0x37,
+0x20, 0x5F, 0x80, 0x7C, 0xB3, 0xC0, 0x0D, 0xC8, 0x27, 0x00, 0x4F, 0x00, 0x7C,
+0x03, 0xF0, 0x04, 0xC0, 0x17, 0x00, 0x9D, 0x00, 0x3C, 0x00, 0xF1, 0x0D, 0xC8,
+0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x7F, 0x00, 0xFF,
+0x01, 0xFC, 0x13, 0xF8, 0x8F, 0xC0, 0x7F, 0x04, 0xF7, 0x09, 0xCC, 0x87, 0xF0,
+0x1F, 0xC0, 0x7C, 0x00, 0xEB, 0x01, 0xEC, 0x07, 0xF9, 0x9F, 0xC0, 0x7F, 0x00,
+0xFF, 0x09, 0xCC, 0x0F, 0xB1, 0x1F, 0xC0, 0x3B, 0x00, 0x33, 0x01, 0xEE, 0x27,
+0x30, 0x17, 0xC0, 0x4F, 0x00, 0x7F, 0x81, 0xCC, 0x05, 0xC0, 0x9A, 0xC0, 0x1A,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x39, 0x00, 0xED, 0x08,
+0xB4, 0x23, 0xD0, 0x0E, 0x48, 0x3B, 0x01, 0xED, 0x00, 0x84, 0x03, 0xD1, 0x0E,
+0x4E, 0x38, 0x40, 0xE1, 0x00, 0x84, 0x00, 0x78, 0x0E, 0x40, 0x1B, 0x08, 0xFD,
+0x00, 0x84, 0x13, 0x10, 0x0E, 0x42, 0x3B, 0x03, 0xA1, 0x80, 0xBC, 0x03, 0x14,
+0x06, 0x40, 0x0B, 0x08, 0x2D, 0x98, 0x84, 0x20, 0x90, 0x0A, 0x40, 0x54, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0xED, 0x00, 0xB4,
+0x0B, 0xD0, 0x8E, 0x40, 0x3B, 0x28, 0xED, 0x00, 0xA4, 0x03, 0xD0, 0x0E, 0x40,
+0x1A, 0x00, 0xE1, 0x00, 0x84, 0x41, 0xD0, 0x0E, 0x44, 0x1B, 0x00, 0xED, 0x90,
+0xA4, 0xC3, 0x18, 0x86, 0x40, 0xAB, 0x0A, 0x61, 0x08, 0xA4, 0x01, 0x54, 0x06,
+0x40, 0x0B, 0x00, 0x6D, 0x00, 0x84, 0x40, 0xD0, 0x0E, 0x40, 0x22, 0x01, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03,
+0xD0, 0x0C, 0x00, 0x33, 0x10, 0x9D, 0x0B, 0x24, 0x2F, 0xD0, 0x1C, 0x5A, 0x02,
+0x00, 0xC1, 0x40, 0x05, 0x01, 0x50, 0x0C, 0x40, 0x07, 0x00, 0x8D, 0x02, 0x24,
+0x07, 0x1A, 0x08, 0x40, 0x63, 0xC0, 0x41, 0x00, 0x14, 0x01, 0x50, 0x24, 0x40,
+0x13, 0x20, 0x0D, 0x03, 0x05, 0x0C, 0x90, 0x0C, 0x40, 0x08, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00, 0xDF, 0x00, 0x3C, 0x42, 0xD0,
+0x0D, 0xC0, 0x3F, 0x00, 0x9F, 0x00, 0xEC, 0x03, 0xF0, 0x1F, 0xC0, 0x26, 0x00,
+0xC1, 0x00, 0x4C, 0x23, 0xF0, 0x0F, 0xC0, 0x27, 0x00, 0x9F, 0x01, 0xEC, 0x0F,
+0x14, 0x01, 0xE2, 0x77, 0x04, 0x13, 0x02, 0x64, 0x03, 0x50, 0xA5, 0x40, 0x07,
+0x00, 0xDF, 0x03, 0x4C, 0x0F, 0xD0, 0x0D, 0xC2, 0x56, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xDD, 0x00, 0x7C, 0x03, 0xF1, 0x0D,
+0x40, 0x37, 0x20, 0x9F, 0x10, 0x5C, 0x03, 0xF0, 0xCD, 0xC0, 0xA1, 0x10, 0x97,
+0x01, 0x7D, 0x00, 0x70, 0x0D, 0xC0, 0x87, 0x00, 0x1F, 0x04, 0x5C, 0x43, 0x72,
+0x21, 0xE0, 0xA7, 0x80, 0x1F, 0x28, 0x74, 0x03, 0xA0, 0x05, 0xC0, 0x07, 0x00,
+0x9D, 0x04, 0x7C, 0x0B, 0xB0, 0x0D, 0xC0, 0xB7, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xFF, 0x20, 0xFC, 0x02, 0xB0, 0x0F, 0xE0,
+0x3B, 0xA0, 0x1B, 0x00, 0xCE, 0x43, 0x30, 0x0C, 0xC0, 0x24, 0x00, 0xFB, 0x00,
+0xAC, 0x01, 0xB0, 0x0F, 0xC0, 0x2F, 0x00, 0xA3, 0x00, 0xCC, 0x03, 0xF0, 0x0A,
+0xC0, 0x28, 0x10, 0x73, 0x59, 0x8C, 0x03, 0x32, 0x47, 0xC0, 0x0C, 0x00, 0xED,
+0x02, 0xCC, 0x47, 0x30, 0x0F, 0xC0, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x20, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0x90, 0x0D, 0x40, 0x37,
+0x98, 0x11, 0x01, 0x44, 0x03, 0x10, 0x0D, 0x42, 0x64, 0x08, 0xD1, 0x01, 0x6C,
+0x04, 0xB0, 0x0D, 0xC2, 0xE7, 0x04, 0x11, 0x01, 0x44, 0x03, 0xD0, 0x39, 0x44,
+0x64, 0x01, 0x41, 0x01, 0x6C, 0x07, 0x10, 0x24, 0x40, 0x84, 0x02, 0x1D, 0x00,
+0x05, 0x01, 0x10, 0x0D, 0x4E, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0xA0, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0x90, 0x0D, 0x48, 0x37, 0x20,
+0x11, 0x01, 0x04, 0x03, 0x10, 0x0D, 0x60, 0x44, 0x00, 0xD1, 0x11, 0x64, 0x07,
+0x92, 0x0D, 0x42, 0x67, 0x80, 0x11, 0x01, 0x64, 0x83, 0x50, 0x11, 0x41, 0x56,
+0x00, 0x19, 0x00, 0x46, 0x07, 0x10, 0x05, 0x40, 0x04, 0x04, 0x5D, 0x00, 0x44,
+0x1B, 0x14, 0x09, 0x40, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x90, 0x0C, 0x40, 0x33, 0x00, 0x81,
+0x01, 0x04, 0x03, 0x14, 0x0C, 0x60, 0x20, 0x20, 0xC1, 0x00, 0x24, 0x00, 0x92,
+0x0C, 0x60, 0x01, 0x90, 0x01, 0x01, 0x24, 0x03, 0xD0, 0x00, 0x42, 0x22, 0x00,
+0xCD, 0x00, 0x24, 0x03, 0x14, 0x04, 0x40, 0x20, 0x00, 0xCD, 0x00, 0x04, 0x02,
+0x10, 0x08, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x36, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0x40, 0x3F, 0x00, 0x11, 0x20,
+0xC4, 0x03, 0x30, 0x0F, 0xC0, 0x04, 0x20, 0xDB, 0x00, 0x6D, 0x01, 0xB1, 0x0F,
+0x40, 0x27, 0x18, 0x93, 0x00, 0xAC, 0x03, 0x70, 0x01, 0xC0, 0x26, 0x00, 0x5B,
+0x00, 0x4C, 0x01, 0x30, 0x05, 0xE0, 0x04, 0x00, 0x0F, 0x00, 0x4C, 0x03, 0x30,
+0x0D, 0xC2, 0x07, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x3F,
+0x00, 0xFF, 0x00, 0xFC, 0x03, 0x78, 0x0F, 0xC0, 0x3F, 0x10, 0xB7, 0x00, 0xFC,
+0x03, 0xF0, 0x0F, 0xC0, 0x2F, 0x10, 0x7F, 0x00, 0xFC, 0x00, 0x70, 0x0F, 0xC0,
+0x2F, 0x00, 0xBF, 0x00, 0xDC, 0x03, 0xF0, 0x0B, 0xC0, 0x2D, 0x00, 0x73, 0x00,
+0xBC, 0x00, 0xF0, 0x07, 0x00, 0x0F, 0x08, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x0F,
+0xC0, 0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7B, 0x00,
+0x33, 0x00, 0xCC, 0x03, 0x30, 0x0B, 0xC0, 0x2F, 0x00, 0xA3, 0x00, 0x8C, 0x06,
+0xB0, 0x03, 0xC0, 0x68, 0x02, 0x3F, 0x01, 0x8C, 0x04, 0x70, 0x1B, 0xC0, 0x3F,
+0x00, 0x33, 0x0C, 0xCC, 0x04, 0xB0, 0x2B, 0x10, 0x4C, 0x00, 0xF3, 0x01, 0xCC,
+0x02, 0x30, 0x0B, 0xD0, 0x4C, 0x00, 0xB3, 0x00, 0xCC, 0x07, 0xF0, 0x0F, 0xC0,
+0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x14, 0x11,
+0x00, 0xC4, 0x03, 0x11, 0x49, 0x40, 0x6F, 0x00, 0x91, 0x0B, 0x44, 0x84, 0x50,
+0x01, 0x40, 0x24, 0x21, 0x1D, 0x21, 0x44, 0x84, 0x10, 0x19, 0x40, 0x3F, 0x04,
+0x11, 0x02, 0x44, 0x04, 0x10, 0x2F, 0x42, 0x24, 0x10, 0xD1, 0x20, 0x44, 0x02,
+0x10, 0x0C, 0x41, 0x44, 0x00, 0x8B, 0x00, 0x54, 0x07, 0xD0, 0x1D, 0x40, 0x0C,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x37, 0x21, 0x00, 0x00,
+0x04, 0x03, 0x10, 0x08, 0x41, 0x23, 0x00, 0xC1, 0x00, 0x44, 0x02, 0x10, 0x00,
+0x40, 0x20, 0x10, 0x1D, 0x00, 0x05, 0x00, 0x52, 0x08, 0x42, 0x33, 0x82, 0x81,
+0x02, 0x04, 0x00, 0x12, 0x68, 0x60, 0x00, 0x00, 0xD1, 0x40, 0x04, 0x06, 0x50,
+0x58, 0x40, 0x00, 0x00, 0xC1, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x4E, 0x80,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x08, 0x51, 0x01, 0x44,
+0x03, 0x10, 0x09, 0x40, 0x67, 0x40, 0xD1, 0x00, 0x45, 0x00, 0x50, 0x11, 0x50,
+0x34, 0x00, 0x1D, 0x01, 0x44, 0x44, 0x11, 0x19, 0x41, 0x37, 0x00, 0x91, 0x00,
+0x40, 0x04, 0x18, 0x0C, 0x60, 0x40, 0x40, 0xD1, 0x04, 0x44, 0x06, 0x50, 0x41,
+0x40, 0x44, 0x20, 0xD9, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0x0E, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x73, 0x00, 0x13, 0x13, 0x4D, 0x03,
+0x34, 0x01, 0xC0, 0x67, 0x00, 0x93, 0x00, 0x4C, 0x03, 0x30, 0x39, 0xC8, 0x24,
+0x10, 0x0F, 0x03, 0x4C, 0x0C, 0x70, 0x19, 0xC8, 0x37, 0x40, 0x13, 0x04, 0x4C,
+0x18, 0x34, 0x09, 0xC0, 0xE4, 0x00, 0xC3, 0x00, 0x4D, 0x06, 0x70, 0x1D, 0xC0,
+0xC4, 0x00, 0x93, 0x01, 0x6C, 0x03, 0xF0, 0x4D, 0xD0, 0x02, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0xFD, 0x40, 0x2F, 0x00, 0xBC, 0x03, 0xF1,
+0x93, 0xC0, 0x37, 0x00, 0xAF, 0x02, 0xFC, 0x02, 0x70, 0x0D, 0xC0, 0x2F, 0x00,
+0x3F, 0x10, 0xFC, 0x80, 0xF0, 0x03, 0xC8, 0x3F, 0x20, 0x3F, 0x23, 0xFC, 0x00,
+0x70, 0x9D, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xB4, 0x1F, 0xC0, 0x0F,
+0x00, 0xAF, 0x09, 0xDC, 0x03, 0xF0, 0x01, 0xC0, 0x1D, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x00, 0x53, 0x00, 0x6D, 0x03, 0x32, 0x09,
+0xD0, 0x24, 0x00, 0xD3, 0x80, 0x4C, 0x03, 0x34, 0x6D, 0xC0, 0x24, 0x00, 0x13,
+0x42, 0x7C, 0x10, 0x30, 0x29, 0xD1, 0x30, 0x00, 0x83, 0x00, 0x4C, 0x18, 0x30,
+0x09, 0xC0, 0x84, 0x00, 0xD3, 0x00, 0x3C, 0x02, 0xB0, 0x11, 0xC0, 0x04, 0x00,
+0xDB, 0x00, 0x4D, 0x03, 0xF0, 0x0C, 0xC0, 0xA8, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0xA0, 0x24, 0x00, 0xD1, 0x00, 0xC4, 0x43, 0x10, 0x09, 0x40,
+0x10, 0x00, 0xD1, 0x00, 0x04, 0x46, 0x10, 0x2D, 0x50, 0x34, 0x00, 0x13, 0x82,
+0x34, 0x08, 0x10, 0x79, 0x40, 0x7C, 0x04, 0xB5, 0x20, 0x2C, 0x0C, 0xB2, 0xAD,
+0x40, 0xC4, 0x06, 0xD1, 0x01, 0x74, 0x2A, 0x10, 0x08, 0x40, 0x40, 0x00, 0xDB,
+0x00, 0x44, 0x03, 0xD0, 0x01, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x20, 0x30, 0x40, 0x81, 0x21, 0x04, 0x03, 0x14, 0x08, 0x08, 0x20,
+0x89, 0x81, 0x00, 0x06, 0x06, 0x10, 0x01, 0x40, 0x20, 0x00, 0x08, 0x03, 0x34,
+0x0C, 0x18, 0x08, 0x40, 0x70, 0x00, 0x09, 0x00, 0x14, 0x2C, 0x94, 0x8C, 0x40,
+0x02, 0x00, 0xC1, 0x41, 0x34, 0x02, 0x90, 0x0C, 0x40, 0x52, 0x40, 0xC9, 0x00,
+0x05, 0x03, 0xD0, 0x0C, 0x40, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x00, 0x7C, 0x40, 0xF1, 0x19, 0x04, 0x07, 0x10, 0x18, 0x40, 0x68, 0x00,
+0xB1, 0x81, 0xC6, 0x04, 0x10, 0x96, 0x40, 0x6C, 0x40, 0x21, 0x21, 0xB4, 0x44,
+0x18, 0x16, 0x62, 0x78, 0x10, 0x0D, 0x01, 0xB4, 0x04, 0x94, 0x1E, 0x40, 0x6A,
+0x00, 0xE1, 0x50, 0x36, 0x06, 0x10, 0x3E, 0x50, 0x4E, 0x04, 0xE9, 0x01, 0x86,
+0x07, 0xD0, 0x16, 0x60, 0x3C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x18, 0x30, 0x00, 0x83, 0x08, 0x0D, 0x03, 0x10, 0x08, 0xC0, 0x20, 0x40, 0xC3,
+0x00, 0x0D, 0x22, 0x30, 0x04, 0x48, 0x20, 0xB2, 0x09, 0x52, 0x3C, 0x20, 0x34,
+0x88, 0xC0, 0x30, 0x00, 0x0B, 0x00, 0x1C, 0x00, 0x90, 0x0C, 0xC0, 0x86, 0x00,
+0xC3, 0x00, 0x3C, 0x02, 0xB0, 0x00, 0xC0, 0x92, 0x10, 0xCB, 0x04, 0x0C, 0x03,
+0xF0, 0x0C, 0xD0, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38,
+0x3D, 0x00, 0xEF, 0x68, 0xFE, 0x0B, 0xF0, 0x0F, 0xC0, 0xBF, 0x00, 0xFF, 0x00,
+0xFC, 0x00, 0xF0, 0x07, 0xC0, 0x3F, 0x20, 0xBF, 0x00, 0xFC, 0x20, 0xF0, 0x8E,
+0xC0, 0x3B, 0x00, 0xB7, 0x80, 0xAD, 0x22, 0xF0, 0x8F, 0xC0, 0x2D, 0x40, 0xFF,
+0x04, 0xFC, 0x02, 0xE0, 0x0B, 0xE0, 0x09, 0x40, 0xFF, 0x00, 0xFC, 0x03, 0xF0,
+0x07, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37,
+0x00, 0xD7, 0x60, 0x4C, 0x0B, 0x34, 0x01, 0xC0, 0x6F, 0x00, 0x97, 0x00, 0x7C,
+0x03, 0xF0, 0x09, 0xD0, 0x24, 0x00, 0x9F, 0x01, 0x4C, 0x00, 0xF0, 0x01, 0xC0,
+0x37, 0x81, 0x12, 0x08, 0x0C, 0x00, 0x31, 0x4D, 0xC0, 0x24, 0x00, 0xD3, 0x00,
+0x4C, 0x02, 0xB0, 0x1D, 0xD0, 0x54, 0x00, 0xD3, 0xA0, 0x4C, 0x83, 0xF0, 0x0D,
+0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x3D, 0x00,
+0xE1, 0x00, 0x06, 0x13, 0x10, 0x02, 0x40, 0x3B, 0x00, 0xE1, 0x00, 0xB4, 0x02,
+0xD0, 0x0E, 0x42, 0x28, 0x20, 0xA8, 0x00, 0x84, 0x00, 0xD0, 0x0E, 0x40, 0x3F,
+0x05, 0x31, 0x00, 0x84, 0x00, 0xD4, 0x0F, 0x51, 0x2C, 0x00, 0xE1, 0x00, 0x04,
+0x02, 0x14, 0x0C, 0x40, 0x08, 0x40, 0xF1, 0x00, 0x94, 0x03, 0xD0, 0x0A, 0x44,
+0x4F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xC5,
+0x01, 0x84, 0x27, 0x00, 0x1E, 0x40, 0x63, 0x00, 0xED, 0x01, 0xB4, 0x47, 0xD0,
+0x3C, 0x40, 0x68, 0x08, 0xAC, 0x11, 0x84, 0x05, 0xD0, 0x1A, 0x40, 0x7B, 0x43,
+0x29, 0x05, 0xA5, 0x04, 0x98, 0x1E, 0x40, 0x68, 0x80, 0xE1, 0x01, 0x84, 0x07,
+0x10, 0x12, 0x60, 0x5C, 0x00, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x40, 0x07,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x33, 0x10, 0xD1, 0x00,
+0x04, 0x03, 0x10, 0x0C, 0x40, 0x53, 0x22, 0xC9, 0x00, 0x34, 0x0A, 0xD0, 0x15,
+0x40, 0x30, 0x00, 0xC9, 0x82, 0x04, 0x6B, 0xD0, 0x2C, 0x40, 0x33, 0x00, 0xD9,
+0x01, 0x24, 0x03, 0xD0, 0x0C, 0x50, 0xF0, 0x81, 0x91, 0x01, 0x04, 0x07, 0x10,
+0x08, 0x60, 0x20, 0x00, 0xC1, 0x00, 0x14, 0x03, 0xD0, 0x98, 0x40, 0x4B, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x15, 0x00, 0x77, 0x8A, 0x4D,
+0x81, 0x30, 0x76, 0xC0, 0x9F, 0x00, 0x5F, 0x01, 0xFC, 0x0D, 0xF1, 0xB7, 0xC0,
+0x14, 0x20, 0x7F, 0x4B, 0xCC, 0x0D, 0xF0, 0x26, 0xC0, 0x17, 0x10, 0x7B, 0x01,
+0xAC, 0x05, 0x34, 0x05, 0xC2, 0x9C, 0x04, 0x53, 0x01, 0xCC, 0x09, 0x30, 0x07,
+0xC1, 0x1C, 0x00, 0x53, 0x00, 0x4D, 0x01, 0xF2, 0x27, 0xC2, 0x5F, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x05, 0x10, 0x1F, 0x00, 0x3C, 0x00,
+0xF0, 0x01, 0xC1, 0x07, 0x00, 0x17, 0x08, 0x7C, 0x10, 0xF0, 0x21, 0xC0, 0x07,
+0x00, 0x1B, 0x02, 0x7D, 0x08, 0xF0, 0x41, 0xC0, 0x87, 0x00, 0x17, 0x08, 0x5C,
+0x28, 0x70, 0x20, 0xD0, 0x07, 0x40, 0x1F, 0x08, 0x7D, 0x60, 0x70, 0x11, 0xC0,
+0x47, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x00, 0xC1, 0x4B, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x93, 0x00, 0x4C, 0x26, 0x30,
+0x09, 0xC0, 0x24, 0x04, 0x9F, 0x00, 0x7C, 0x16, 0xF0, 0x09, 0xC0, 0x24, 0x00,
+0x9F, 0x04, 0x7C, 0x82, 0xB0, 0x09, 0xC4, 0x26, 0x40, 0x93, 0x04, 0x4C, 0x12,
+0x34, 0x19, 0xC0, 0x24, 0x01, 0x93, 0x08, 0x0C, 0x02, 0x30, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x01, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x20, 0x22, 0x00, 0x91, 0x00, 0x44, 0x02, 0x11, 0x09,
+0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0xA9, 0x41, 0x24, 0x00, 0x9D,
+0x00, 0x34, 0x0A, 0x10, 0x69, 0x40, 0x24, 0x00, 0x91, 0x01, 0x44, 0x16, 0x10,
+0x19, 0xD0, 0x22, 0x00, 0x91, 0x02, 0x45, 0x02, 0x10, 0x09, 0x40, 0x27, 0x20,
+0x9D, 0x09, 0x6C, 0x02, 0xD0, 0x09, 0x50, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x24, 0x40, 0x91, 0x20, 0x44, 0x02, 0x11, 0x09, 0x40,
+0x25, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x0D, 0x50, 0x25, 0x00, 0x9D, 0x00,
+0x74, 0x06, 0x90, 0x09, 0x40, 0x22, 0x02, 0x91, 0x00, 0x64, 0x02, 0x14, 0x49,
+0x48, 0x24, 0x00, 0x91, 0x02, 0x64, 0x22, 0x18, 0x19, 0x40, 0x27, 0x00, 0x8D,
+0x00, 0x65, 0x02, 0xD0, 0x09, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x20, 0x24, 0x00, 0x81, 0x04, 0x24, 0x12, 0x10, 0x49, 0x40, 0x61,
+0x91, 0x8D, 0x04, 0x34, 0x02, 0xC0, 0x48, 0x40, 0x21, 0x00, 0x8D, 0x20, 0x74,
+0x02, 0x00, 0x08, 0x42, 0x20, 0x89, 0x81, 0x44, 0x26, 0x02, 0x18, 0x48, 0x40,
+0x26, 0x40, 0x81, 0x00, 0x24, 0x12, 0x14, 0x58, 0x40, 0x23, 0x00, 0x8D, 0x04,
+0x24, 0x02, 0xD0, 0x48, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB8, 0x86, 0x02, 0x13, 0x0A, 0x4C, 0x28, 0x34, 0xA1, 0xD0, 0x05, 0x00,
+0x1F, 0x00, 0x7C, 0x00, 0xF0, 0xA1, 0xC0, 0x85, 0x02, 0x5F, 0x00, 0x74, 0x01,
+0xB1, 0x01, 0xC8, 0x96, 0x42, 0x13, 0x0A, 0x6D, 0x00, 0x30, 0xA5, 0x40, 0x84,
+0x0A, 0x03, 0x4A, 0x6C, 0x28, 0x30, 0xA1, 0xC0, 0x07, 0x00, 0x1F, 0x0A, 0x6D,
+0x00, 0xF0, 0x01, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB8, 0x2F, 0x10, 0xBF, 0x08, 0x5D, 0x22, 0xF0, 0x8B, 0xC0, 0x3E, 0x02, 0xBF,
+0x08, 0xF4, 0x02, 0xF0, 0x8B, 0xC0, 0x2E, 0x00, 0xAF, 0x00, 0xFC, 0x02, 0xF2,
+0x0B, 0x00, 0x27, 0x02, 0xBF, 0x88, 0xDC, 0x82, 0xF2, 0x8B, 0xC0, 0x3F, 0x00,
+0xBF, 0x00, 0xDC, 0x22, 0xD0, 0x8B, 0xC0, 0x2B, 0x00, 0xBF, 0x08, 0x7C, 0x02,
+0xF0, 0x8B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA8,
+0x3B, 0x00, 0xF2, 0x14, 0xCC, 0x32, 0x34, 0x0B, 0xC0, 0x2C, 0x00, 0x93, 0x00,
+0xCC, 0x02, 0xF0, 0x4B, 0xC1, 0x24, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0x30, 0x0B,
+0xC0, 0xED, 0x00, 0xB3, 0x03, 0xCC, 0x02, 0x30, 0x3B, 0xC0, 0x2C, 0x00, 0xBF,
+0x88, 0xFC, 0x12, 0x30, 0x4A, 0xC1, 0x2C, 0x00, 0xB3, 0x00, 0x4D, 0x02, 0xF0,
+0x09, 0xC0, 0x64, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x05,
+0x05, 0x01, 0x04, 0x04, 0x30, 0x11, 0x21, 0x43, 0x04, 0x08, 0x11, 0x08, 0x44,
+0x00, 0xD0, 0x41, 0x50, 0x04, 0x00, 0x11, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40,
+0xC4, 0x08, 0x41, 0x43, 0x44, 0x01, 0x10, 0x30, 0x40, 0x00, 0x04, 0x1D, 0x00,
+0x5C, 0x51, 0x10, 0x41, 0x42, 0x04, 0x08, 0x0B, 0x12, 0x54, 0x00, 0xD0, 0x81,
+0x40, 0x70, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x25, 0x01,
+0x81, 0x94, 0x05, 0x92, 0x90, 0xCC, 0x40, 0x20, 0x02, 0x91, 0x20, 0x04, 0x02,
+0xD0, 0x48, 0x41, 0x20, 0x00, 0x81, 0x01, 0x74, 0x02, 0x10, 0x0D, 0x40, 0xA1,
+0x09, 0x81, 0x06, 0x04, 0x82, 0x10, 0x68, 0x48, 0x20, 0x00, 0x8D, 0x00, 0x34,
+0x32, 0x10, 0x48, 0x51, 0x20, 0x00, 0x89, 0x0C, 0x04, 0x02, 0xD0, 0x08, 0x40,
+0x48, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x4A, 0x91,
+0x10, 0x44, 0x02, 0x90, 0x39, 0x40, 0x24, 0x40, 0x91, 0x00, 0x44, 0x02, 0xD0,
+0x09, 0x40, 0x24, 0x00, 0x91, 0x40, 0x74, 0x12, 0x10, 0x09, 0x40, 0x24, 0x00,
+0x91, 0x00, 0x45, 0x12, 0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x14, 0x02,
+0x10, 0x69, 0x40, 0x24, 0x20, 0x89, 0x00, 0x54, 0x02, 0xD0, 0x09, 0x40, 0x60,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x21, 0x00, 0x93, 0x00,
+0x4C, 0x02, 0xB0, 0x29, 0xD0, 0xA4, 0x02, 0x83, 0x00, 0x4D, 0x02, 0xF0, 0x09,
+0xC9, 0x24, 0x40, 0x93, 0x03, 0x7C, 0x4E, 0x34, 0x48, 0xC0, 0x25, 0x40, 0x93,
+0x0B, 0x4C, 0x06, 0x24, 0x09, 0xD0, 0x64, 0x02, 0x9F, 0x00, 0x7C, 0x0E, 0x34,
+0x09, 0xC0, 0xA4, 0x24, 0x9B, 0x01, 0x4D, 0x02, 0xF0, 0x09, 0xD0, 0x14, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x65, 0x10, 0x9F, 0x04, 0x3C,
+0x42, 0x70, 0x09, 0xC0, 0x67, 0x00, 0x9F, 0x02, 0x7C, 0x02, 0xF1, 0x48, 0xC0,
+0xE7, 0x00, 0x9F, 0x02, 0x7C, 0x06, 0xF1, 0x09, 0xC8, 0x23, 0x40, 0x9F, 0x01,
+0x7C, 0x06, 0xF0, 0x08, 0xC0, 0x67, 0x00, 0x9F, 0x05, 0x7C, 0x12, 0xF0, 0x19,
+0xC1, 0x27, 0x00, 0x9F, 0x04, 0x7D, 0x02, 0xF0, 0x08, 0xC0, 0x5B, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x13, 0x80, 0x4C, 0x00,
+0x30, 0x00, 0xC0, 0x83, 0x40, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x04,
+0x00, 0x1F, 0x10, 0x7E, 0x08, 0xF2, 0x01, 0xD1, 0x06, 0x01, 0x03, 0x82, 0x4C,
+0x40, 0x31, 0x01, 0xC1, 0xC6, 0x00, 0x13, 0x00, 0x4C, 0x04, 0x30, 0x20, 0xC0,
+0x84, 0x00, 0x1F, 0x00, 0x4D, 0x00, 0xF0, 0x01, 0xC0, 0x50, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x14, 0x04, 0x51, 0x01, 0xC5, 0x09, 0x10,
+0x05, 0xC0, 0x5D, 0x00, 0x51, 0x00, 0x74, 0x01, 0xD0, 0x17, 0x60, 0x14, 0x00,
+0x7D, 0x03, 0xB4, 0x01, 0xD0, 0x27, 0x44, 0x5C, 0x00, 0x5B, 0x11, 0xAC, 0x15,
+0xB1, 0x57, 0xC0, 0x1E, 0x40, 0x70, 0x00, 0xC4, 0x11, 0x14, 0x37, 0x40, 0x10,
+0x00, 0x5D, 0x11, 0x44, 0x01, 0xD0, 0x05, 0x50, 0x50, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x32, 0x40, 0xD1, 0x00, 0x24, 0x07, 0x11, 0x0C,
+0x40, 0x31, 0x04, 0xC1, 0x00, 0x34, 0x07, 0xD0, 0x1C, 0x48, 0x34, 0x00, 0xCD,
+0x02, 0x34, 0x02, 0xD8, 0x2C, 0x60, 0x32, 0x90, 0xC9, 0x21, 0x04, 0x87, 0x58,
+0x0C, 0x42, 0x30, 0x00, 0xC0, 0x04, 0x04, 0x03, 0x10, 0x3C, 0x40, 0x20, 0x00,
+0xCD, 0x00, 0x04, 0x83, 0xD0, 0x0C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x80, 0x3C, 0x20, 0xA1, 0x10, 0xA5, 0x1A, 0x10, 0x0E, 0x40,
+0x31, 0x04, 0xE1, 0x00, 0xB4, 0x0A, 0xD0, 0x04, 0x41, 0x38, 0x01, 0x6D, 0x02,
+0xB6, 0x40, 0xD8, 0x03, 0x40, 0xAA, 0x82, 0xE9, 0x00, 0xA4, 0x00, 0xD0, 0x0E,
+0x40, 0x7A, 0x00, 0xE1, 0x01, 0x84, 0x03, 0x10, 0x0F, 0x41, 0x28, 0x00, 0xED,
+0x00, 0x85, 0x03, 0xD0, 0x0E, 0x40, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x18, 0x78, 0x00, 0xE3, 0x01, 0xAC, 0x16, 0x34, 0x1E, 0xC0, 0x79,
+0x00, 0xE3, 0x01, 0xBC, 0x06, 0xD0, 0x16, 0x40, 0xF8, 0x01, 0x2D, 0x01, 0xB4,
+0x05, 0xF0, 0x16, 0xD0, 0x72, 0x00, 0xAB, 0x01, 0x8C, 0x04, 0x74, 0x9E, 0xC0,
+0x78, 0x00, 0xF3, 0x81, 0xCC, 0x07, 0x34, 0x1E, 0xC0, 0x68, 0x00, 0xAF, 0x01,
+0x84, 0x07, 0xF0, 0x1C, 0xC0, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xB8, 0x35, 0x40, 0x9F, 0x14, 0x5C, 0x22, 0xF0, 0x0D, 0xC0, 0x35, 0x00,
+0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x05, 0xD0, 0x77, 0x00, 0x5F, 0x00, 0x6C, 0x00,
+0xF0, 0x00, 0xD0, 0x25, 0x20, 0x9F, 0x02, 0x3C, 0x00, 0xB1, 0x09, 0xD0, 0x37,
+0x00, 0xDF, 0x00, 0x7D, 0x03, 0xE0, 0x0D, 0xC0, 0x27, 0x00, 0x9F, 0x02, 0x7D,
+0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x20, 0x7D, 0x00, 0xFF, 0x21, 0x8C, 0x06, 0x38, 0x8F, 0xC0, 0x6D, 0x00, 0xF3,
+0x01, 0xFC, 0x06, 0xF0, 0x1F, 0xD0, 0x7C, 0x00, 0x3F, 0x01, 0xFC, 0x06, 0xF0,
+0x13, 0xC0, 0x5F, 0x20, 0xF7, 0x23, 0xCC, 0x04, 0x31, 0x9F, 0xC0, 0x7C, 0x08,
+0xF3, 0x01, 0x8C, 0x07, 0x31, 0x0B, 0xC0, 0x6F, 0x00, 0xEF, 0x03, 0xCC, 0x07,
+0xF2, 0x1F, 0xC2, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00,
+0x39, 0x00, 0xED, 0x00, 0x84, 0x02, 0x38, 0x0F, 0x40, 0x08, 0x40, 0xE1, 0x00,
+0xBC, 0x02, 0xD0, 0x26, 0x40, 0x38, 0x02, 0x6D, 0x10, 0xB4, 0xA0, 0xD0, 0x82,
+0x40, 0x0F, 0x10, 0xE1, 0x04, 0x94, 0x10, 0x10, 0xE6, 0x41, 0x3C, 0x00, 0xF1,
+0x10, 0x84, 0x83, 0x14, 0x8A, 0x40, 0x2B, 0x04, 0xED, 0x08, 0x84, 0x03, 0xD0,
+0x0E, 0x40, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
+0x00, 0xED, 0x00, 0x84, 0x02, 0x90, 0x8E, 0x40, 0x29, 0x00, 0xE1, 0x00, 0xB4,
+0x42, 0xD0, 0x06, 0x40, 0x38, 0x04, 0x2D, 0x00, 0xB4, 0x00, 0xD0, 0x02, 0x40,
+0x2B, 0x02, 0xED, 0x80, 0xC4, 0x00, 0x10, 0x04, 0x40, 0x38, 0x04, 0x61, 0x00,
+0xF4, 0x03, 0x10, 0x8A, 0x41, 0x2B, 0x02, 0xAD, 0x00, 0x84, 0x03, 0xD0, 0x2C,
+0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x31, 0x00,
+0xCD, 0x00, 0x44, 0x02, 0x10, 0x1C, 0x40, 0x00, 0x04, 0xC1, 0x49, 0x34, 0x02,
+0xD0, 0x25, 0x40, 0x70, 0x00, 0x4D, 0x01, 0x34, 0x00, 0xD2, 0x10, 0x40, 0x23,
+0x00, 0xC9, 0x0A, 0x14, 0xC8, 0x14, 0x04, 0x50, 0xF0, 0x00, 0x41, 0x00, 0x34,
+0x0B, 0x10, 0x18, 0x40, 0x23, 0x00, 0x9D, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40,
+0x58, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x35, 0x00, 0xDF,
+0x07, 0xCC, 0x02, 0xB0, 0x4D, 0xC0, 0xE5, 0x00, 0xD3, 0x00, 0x3C, 0x02, 0xF0,
+0x05, 0xD0, 0x3C, 0x00, 0x1F, 0x02, 0x7C, 0x08, 0xF0, 0x21, 0xC1, 0x3F, 0x00,
+0xDF, 0x23, 0x0D, 0x08, 0x30, 0x11, 0xC0, 0xF4, 0x08, 0xD3, 0x00, 0x7C, 0x23,
+0x30, 0x0D, 0xC0, 0xB7, 0x00, 0x9F, 0x00, 0x4D, 0x03, 0xF0, 0x0D, 0xC0, 0x74,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x37, 0x10, 0x9F, 0x00,
+0x7E, 0x02, 0x70, 0x0D, 0xC2, 0x63, 0x10, 0xDF, 0x00, 0x5C, 0x02, 0xF0, 0xC5,
+0xC0, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x10, 0xF0, 0x41, 0xC0, 0x37, 0x00, 0xD7,
+0x10, 0x7C, 0x0C, 0xF0, 0x00, 0xC0, 0x37, 0x04, 0xDF, 0x00, 0x44, 0x0B, 0xF0,
+0x0C, 0xC1, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x1D, 0xC2, 0x07, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xEF, 0x10, 0xCC,
+0x06, 0x30, 0x0F, 0xC0, 0x04, 0x00, 0xF3, 0x00, 0xFE, 0x52, 0x30, 0x05, 0xC0,
+0x3C, 0x00, 0x37, 0x10, 0xFC, 0x80, 0xF0, 0x03, 0xC0, 0x7B, 0x00, 0x93, 0x00,
+0xCC, 0x00, 0xB0, 0x03, 0x40, 0x2C, 0x00, 0xB3, 0x00, 0xCC, 0x83, 0x32, 0x8F,
+0xC2, 0xBC, 0x00, 0xBF, 0x00, 0xCC, 0x03, 0xF0, 0x0E, 0xC0, 0x04, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0x9D, 0x20, 0x44, 0x0A,
+0x10, 0x0C, 0x50, 0xC4, 0x00, 0xD1, 0x00, 0x74, 0x06, 0x50, 0x15, 0x50, 0x35,
+0x00, 0x5D, 0x07, 0x74, 0x0C, 0xD0, 0x11, 0xC0, 0x35, 0x02, 0x81, 0x00, 0x44,
+0x4C, 0x11, 0x31, 0xC0, 0x36, 0x00, 0xD1, 0x02, 0x44, 0x43, 0x10, 0x21, 0x42,
+0x24, 0x00, 0x9D, 0x09, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x04, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x66, 0x00, 0xDD, 0x00, 0x44, 0x28, 0x10,
+0x19, 0x40, 0xE6, 0x00, 0xD1, 0x00, 0x74, 0x02, 0xD0, 0x11, 0x40, 0x36, 0x00,
+0x1D, 0x01, 0x74, 0x44, 0xD0, 0x31, 0x40, 0x17, 0x40, 0xD1, 0x00, 0x44, 0x84,
+0x10, 0x11, 0x02, 0xD3, 0x00, 0xC1, 0x11, 0x06, 0x04, 0x10, 0x29, 0x40, 0x36,
+0x00, 0xDD, 0x00, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x06, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xCD, 0x00, 0x05, 0x00, 0x10, 0x09,
+0x40, 0x02, 0x40, 0xC1, 0x00, 0x34, 0x82, 0x50, 0x00, 0x40, 0x33, 0x08, 0x4D,
+0x40, 0x36, 0x00, 0xD0, 0x00, 0x40, 0x11, 0x80, 0xD1, 0x00, 0x44, 0x00, 0x10,
+0x00, 0x40, 0x33, 0x00, 0xC1, 0x00, 0x06, 0x02, 0x10, 0x08, 0x50, 0x22, 0x00,
+0xCD, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x98, 0x26, 0x00, 0xEF, 0x00, 0x4C, 0x00, 0x34, 0x09, 0xC0,
+0x06, 0x00, 0xD3, 0x00, 0x74, 0x02, 0x70, 0x05, 0xC0, 0x36, 0x00, 0x17, 0x00,
+0x74, 0x00, 0xF2, 0x01, 0xC2, 0x27, 0x20, 0xF3, 0x20, 0x4C, 0x00, 0xB0, 0x03,
+0xD0, 0x07, 0x00, 0x93, 0x00, 0x4C, 0x01, 0x30, 0x09, 0xC0, 0x36, 0x00, 0xBF,
+0x00, 0x4D, 0x03, 0xF0, 0x0D, 0xC0, 0x06, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xB8, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0B, 0xC0, 0x0D,
+0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x07, 0xC0, 0x3D, 0x00, 0x7F, 0x00, 0xFC,
+0x00, 0xD0, 0x03, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xBD, 0x00, 0xF4, 0x03, 0xC2,
+0x3E, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x2D, 0x00, 0xBF, 0x00,
+0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x15, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA0, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x27, 0x30, 0x1F, 0xC8, 0x7F, 0x0A,
+0xFF, 0x01, 0xCC, 0x27, 0xF0, 0x1F, 0xC0, 0x7C, 0x00, 0xF3, 0x09, 0xFC, 0x27,
+0xF0, 0x3F, 0xC0, 0x7F, 0x00, 0xF3, 0x01, 0xCC, 0x27, 0x30, 0x9F, 0xC0, 0x78,
+0x00, 0xFF, 0x09, 0xCC, 0x07, 0xB0, 0x13, 0xC0, 0x7E, 0x00, 0xEF, 0x01, 0xFC,
+0x07, 0x30, 0x1F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x08, 0x77, 0x00, 0xDD, 0x01, 0x74, 0x00, 0x10, 0x11, 0x40, 0x07, 0x01, 0x1D,
+0x01, 0x44, 0x00, 0x90, 0x11, 0x40, 0x04, 0x01, 0x11, 0x00, 0x74, 0x10, 0xD0,
+0x01, 0x40, 0x47, 0x00, 0x11, 0x01, 0x44, 0x00, 0x10, 0x01, 0x48, 0x44, 0x00,
+0x1D, 0x00, 0x44, 0x87, 0x51, 0x11, 0x40, 0x74, 0x00, 0x9D, 0x01, 0x74, 0x13,
+0x10, 0x1D, 0x40, 0x0F, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0,
+0x33, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xDD, 0x00,
+0x04, 0x03, 0xD0, 0x0D, 0x48, 0x34, 0x14, 0xC1, 0x20, 0x34, 0x03, 0xD0, 0x4C,
+0x40, 0x37, 0x00, 0xD9, 0x00, 0x64, 0x03, 0x10, 0x0D, 0x40, 0x31, 0x00, 0xCD,
+0x04, 0x24, 0x03, 0x10, 0x01, 0x48, 0x32, 0x80, 0x8D, 0x00, 0x34, 0x43, 0x19,
+0x0C, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35,
+0x00, 0xDD, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x00, 0x44,
+0x00, 0x90, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x74, 0x80, 0xD0, 0x01, 0x40,
+0x07, 0x00, 0x19, 0x00, 0x64, 0x00, 0x11, 0x01, 0x42, 0x05, 0x08, 0x1D, 0x20,
+0x64, 0x07, 0x50, 0x11, 0x41, 0x34, 0x80, 0x1D, 0x01, 0x34, 0x03, 0x18, 0x0D,
+0x42, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x37, 0x18, 0xCF, 0x00, 0x4C, 0x03,
+0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x33,
+0x00, 0xCB, 0x00, 0x6C, 0x03, 0x30, 0x0C, 0xC0, 0x35, 0x00, 0xDF, 0x00, 0x6D,
+0x07, 0x30, 0x10, 0xC2, 0x36, 0x00, 0x9F, 0x13, 0x7C, 0x03, 0x30, 0x0D, 0xC2,
+0x23, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xFF,
+0x00, 0xFC, 0x40, 0xF2, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFD, 0x00, 0xF0,
+0x03, 0xD2, 0x0F, 0x00, 0x3F, 0x00, 0xFE, 0x00, 0xF0, 0x03, 0xC2, 0x0F, 0x00,
+0x37, 0x00, 0xDC, 0x00, 0xF6, 0x03, 0xC0, 0x0E, 0x20, 0x3F, 0x00, 0xDC, 0x03,
+0xF0, 0x07, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x1F,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0x30, 0x8D, 0xC0, 0x36, 0x00, 0xDF, 0x01, 0x4C, 0x23, 0xF0, 0x0D,
+0xC2, 0x34, 0x04, 0xDF, 0x01, 0x4C, 0x43, 0xF0, 0x0D, 0xE0, 0x37, 0x00, 0xDB,
+0x01, 0x4C, 0x13, 0xF0, 0x8D, 0x80, 0x34, 0x02, 0xD3, 0x18, 0x4C, 0x0E, 0xF0,
+0x01, 0xC0, 0x37, 0x00, 0x93, 0x02, 0x4C, 0x43, 0xF0, 0x0D, 0xC0, 0x2B, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x74,
+0x00, 0x11, 0x01, 0x40, 0x84, 0x00, 0x1D, 0x00, 0x44, 0x00, 0xD0, 0x10, 0x40,
+0x80, 0x00, 0x1D, 0x80, 0x44, 0x9C, 0xD0, 0x51, 0x40, 0xC7, 0x0A, 0x1D, 0x00,
+0x04, 0x48, 0xD0, 0x21, 0x40, 0x44, 0x20, 0x11, 0xA0, 0x2C, 0x02, 0xD0, 0xA5,
+0x40, 0x77, 0x04, 0x91, 0x00, 0x68, 0x07, 0xD0, 0x0D, 0x40, 0x4F, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x74, 0x0F,
+0x10, 0x1C, 0x40, 0x32, 0x02, 0xCD, 0x00, 0x04, 0x43, 0xD0, 0x8C, 0x40, 0xF0,
+0x08, 0xCD, 0x00, 0x04, 0x03, 0xD0, 0x4C, 0x40, 0x73, 0x02, 0xCD, 0x00, 0x04,
+0x0F, 0xD0, 0x0C, 0x40, 0x70, 0x00, 0xD1, 0x00, 0x24, 0x03, 0xD0, 0x04, 0x48,
+0x73, 0x00, 0x88, 0x00, 0x04, 0x27, 0xD0, 0x0C, 0x40, 0x0F, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x00, 0xED, 0x01, 0xF4, 0x64, 0x10,
+0x12, 0x40, 0xC8, 0x00, 0x3D, 0x01, 0x84, 0x04, 0xD0, 0x12, 0x50, 0x48, 0x04,
+0x2D, 0x03, 0x84, 0x04, 0xD0, 0x12, 0x40, 0x4B, 0x02, 0x3D, 0x01, 0x84, 0x04,
+0xD0, 0x33, 0x40, 0x4C, 0x00, 0x31, 0x01, 0xA4, 0x07, 0xD0, 0x16, 0x40, 0x3B,
+0x00, 0xB9, 0x01, 0xA4, 0x07, 0xD0, 0x1E, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF, 0x00, 0x3C, 0x03, 0x30, 0x0C,
+0xC0, 0x32, 0x00, 0xCF, 0x00, 0x0C, 0x03, 0xF0, 0x0C, 0xC0, 0x30, 0x02, 0xDF,
+0x00, 0x0C, 0x03, 0xF0, 0x0C, 0x40, 0x33, 0x00, 0xCF, 0x04, 0x0C, 0x23, 0xF2,
+0x0D, 0x40, 0x30, 0x00, 0xC3, 0x00, 0x2C, 0x0B, 0xF0, 0x00, 0xC0, 0x33, 0x02,
+0x8B, 0x80, 0x0C, 0x23, 0xF0, 0x0C, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x00, 0xBC, 0x00, 0xF0, 0x82, 0x80,
+0x0F, 0x02, 0x2F, 0x00, 0xFC, 0x00, 0xF1, 0x02, 0xC0, 0x0F, 0x08, 0x3F, 0x00,
+0x7C, 0x00, 0xF0, 0x83, 0xC0, 0x0F, 0x08, 0x2F, 0x00, 0x7C, 0x00, 0xF0, 0x03,
+0xD0, 0x0F, 0x00, 0x2F, 0x09, 0xFC, 0x03, 0xF0, 0x83, 0xC4, 0x3B, 0x01, 0xB7,
+0x00, 0xFC, 0x23, 0xF0, 0x0F, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x07, 0x34, 0x0D, 0xC0, 0x77,
+0x40, 0xD3, 0x00, 0x7C, 0x07, 0x34, 0x0D, 0xC0, 0x37, 0x08, 0xDF, 0x00, 0x7C,
+0x07, 0x30, 0x1D, 0xD0, 0x70, 0x00, 0xC3, 0x01, 0x4C, 0x03, 0xF0, 0x0D, 0xC0,
+0x37, 0x20, 0xDF, 0x40, 0x7C, 0x01, 0xF0, 0x04, 0xC0, 0x34, 0x00, 0x9F, 0x00,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x88, 0x39, 0x00, 0xED, 0x00, 0xF4, 0x00, 0x10, 0x02, 0x48, 0x0F, 0x00,
+0x21, 0x00, 0xF4, 0x00, 0x10, 0x02, 0x40, 0x0B, 0x00, 0x2D, 0x00, 0xF4, 0x00,
+0x13, 0x03, 0x40, 0x08, 0x00, 0x25, 0x00, 0x84, 0x00, 0xD0, 0x02, 0x40, 0x0B,
+0x00, 0x2D, 0x00, 0xB4, 0x01, 0xD0, 0x06, 0x40, 0x38, 0x00, 0xA9, 0x00, 0xB4,
+0x03, 0xD0, 0x0E, 0x40, 0x4F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x00, 0x79, 0x00, 0xED, 0x01, 0xB4, 0x07, 0x50, 0x1E, 0x40, 0x7B, 0x00, 0xE1,
+0x01, 0xB4, 0x07, 0x10, 0x1E, 0x00, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07, 0x54,
+0x1E, 0x40, 0x78, 0x00, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00,
+0xED, 0x01, 0xB4, 0x07, 0xD0, 0x12, 0x40, 0x78, 0x80, 0xAD, 0x11, 0xB4, 0x07,
+0xD0, 0x1E, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28,
+0x33, 0x00, 0xCD, 0x00, 0x34, 0x80, 0x50, 0x00, 0x40, 0x03, 0x00, 0x01, 0x00,
+0x34, 0x00, 0x10, 0x00, 0x40, 0x03, 0x00, 0x0D, 0x00, 0x34, 0x00, 0x50, 0x00,
+0x40, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00, 0xD0, 0x00, 0x40, 0x03, 0x00, 0x0D,
+0x00, 0x34, 0x07, 0xD0, 0x6C, 0x40, 0x30, 0x80, 0x89, 0x01, 0x34, 0x03, 0xD0,
+0x0C, 0x40, 0x5B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x28, 0x15,
+0x00, 0x5F, 0x00, 0x7C, 0x01, 0x70, 0x05, 0xC0, 0x17, 0x00, 0x53, 0x00, 0x7C,
+0x01, 0x30, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0x70, 0x05, 0xC0,
+0x14, 0x00, 0x51, 0x00, 0x4D, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00,
+0xBC, 0x95, 0xF0, 0x27, 0xD0, 0x14, 0x00, 0x6F, 0x02, 0x7C, 0x01, 0xD0, 0x05,
+0xC0, 0x5F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00,
+0x1F, 0x00, 0xFC, 0x00, 0x90, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x80, 0xFC, 0x00, 0x90, 0x03, 0xC0, 0x0F,
+0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0x7C,
+0x40, 0xE0, 0x21, 0xC0, 0x07, 0x08, 0x1F, 0x10, 0x74, 0x00, 0xF0, 0x01, 0xC0,
+0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F,
+0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x19, 0xC0, 0x27, 0x01,
+0x9F, 0x00, 0x7C, 0x26, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x06,
+0x70, 0x49, 0xC0, 0xE5, 0x00, 0x9F, 0x00, 0x4C, 0x16, 0xF0, 0x09, 0xC0, 0x43,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00,
+0x74, 0x0A, 0xD0, 0x09, 0x40, 0x27, 0x04, 0x9D, 0x00, 0x74, 0x2E, 0xD0, 0x09,
+0x46, 0xA7, 0x00, 0x9D, 0x03, 0x74, 0x2A, 0xD0, 0x29, 0x40, 0x67, 0x80, 0x9D,
+0x00, 0x74, 0x0A, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x43, 0x74, 0xA2, 0x30,
+0x38, 0x40, 0x24, 0x01, 0x9D, 0x80, 0x6C, 0x0E, 0xD1, 0x09, 0x40, 0x07, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x74,
+0x12, 0xD0, 0x4B, 0x40, 0x6F, 0x00, 0xBD, 0x01, 0xF4, 0x02, 0xD0, 0x1B, 0x40,
+0x6F, 0x00, 0xBD, 0x08, 0xF4, 0x02, 0xD0, 0x8B, 0x40, 0x2F, 0x18, 0xBD, 0x01,
+0xF4, 0x02, 0xD0, 0x1B, 0x41, 0x6F, 0x00, 0xBD, 0x04, 0x64, 0x02, 0x58, 0x09,
+0x40, 0x25, 0x08, 0x9D, 0x00, 0x44, 0x0A, 0xD0, 0x09, 0x40, 0x63, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x8D, 0x00, 0xB4, 0x06,
+0xD0, 0x0A, 0x40, 0x2B, 0x00, 0xAD, 0x00, 0xB4, 0x06, 0xD2, 0x0A, 0x40, 0x6B,
+0x00, 0xAD, 0x01, 0xB4, 0x06, 0xD0, 0x1A, 0x48, 0x6B, 0x20, 0xAD, 0xC0, 0xB4,
+0x06, 0xD0, 0x0A, 0x48, 0x2B, 0x00, 0xAD, 0x01, 0x74, 0x02, 0x10, 0x09, 0x40,
+0x20, 0x00, 0x9D, 0x00, 0x25, 0x22, 0xD0, 0x08, 0x40, 0x43, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x00, 0x7C, 0x28, 0xF0,
+0x01, 0xC2, 0x87, 0x02, 0x1F, 0x00, 0x7C, 0x28, 0xF0, 0x01, 0xC0, 0x87, 0x22,
+0x1F, 0x2A, 0x7C, 0x28, 0xF0, 0xA1, 0xC0, 0x07, 0x00, 0x1D, 0x00, 0x7C, 0x28,
+0xF0, 0xA1, 0x40, 0x07, 0x00, 0x3F, 0x0A, 0x6C, 0x00, 0x72, 0x05, 0xC0, 0x05,
+0x00, 0x1F, 0x00, 0x4C, 0x08, 0xF0, 0x01, 0xC8, 0x77, 0xE0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x19, 0xB8, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF1, 0x09,
+0xCA, 0x27, 0x08, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F,
+0x00, 0x74, 0x82, 0xF1, 0x09, 0xC0, 0x27, 0x08, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0xF8, 0x02, 0x72, 0x0B, 0xC0, 0x27, 0x00,
+0xBF, 0x00, 0x7C, 0x12, 0xF8, 0x09, 0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x27, 0x00, 0x9F, 0x00, 0xFC, 0x22, 0xF0, 0x0B, 0xC6,
+0xAC, 0x18, 0xBF, 0x00, 0xFC, 0x22, 0xB0, 0x0B, 0xC0, 0xAF, 0x20, 0xBF, 0x02,
+0xCC, 0x0A, 0xF0, 0x0B, 0xC0, 0x2C, 0x00, 0xB7, 0x00, 0xFC, 0x0A, 0x30, 0x2B,
+0xC0, 0x2C, 0x20, 0xBF, 0x48, 0xBC, 0x02, 0x30, 0x0F, 0xC0, 0x2F, 0x20, 0x9F,
+0x00, 0xF4, 0x02, 0x30, 0x09, 0xC0, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1C, 0x08, 0x07, 0x00, 0x1D, 0x00, 0x74, 0x14, 0xD0, 0x01, 0x40, 0x44,
+0x00, 0x1D, 0x00, 0x74, 0x14, 0xD0, 0x01, 0x48, 0x47, 0x01, 0x1D, 0x81, 0x44,
+0x94, 0x90, 0x11, 0x52, 0x04, 0x00, 0x11, 0x00, 0x74, 0x04, 0x10, 0x51, 0x40,
+0x04, 0x00, 0x1D, 0x05, 0x74, 0x00, 0x10, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x00,
+0x64, 0x00, 0x14, 0x01, 0x40, 0x63, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA0, 0x23, 0x00, 0x8D, 0x00, 0x34, 0x03, 0xD0, 0x0D, 0x50, 0x21, 0x01,
+0x8D, 0x00, 0x34, 0x03, 0x90, 0x0C, 0x40, 0x23, 0x01, 0xC5, 0x04, 0x15, 0x03,
+0xD0, 0x4D, 0x41, 0x20, 0x00, 0x81, 0x00, 0x34, 0x13, 0x10, 0x08, 0x14, 0x32,
+0x20, 0x8D, 0x00, 0x76, 0x82, 0x50, 0x08, 0x48, 0x23, 0x10, 0x8D, 0x00, 0x34,
+0x02, 0x10, 0x08, 0x40, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA8, 0x25, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x25, 0x00, 0x9D,
+0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x54, 0x02, 0xD0,
+0x0D, 0x40, 0x24, 0x00, 0x91, 0xC0, 0x74, 0x02, 0x12, 0x09, 0x00, 0x24, 0x00,
+0x9D, 0x00, 0x74, 0x12, 0x54, 0x19, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x24, 0x02,
+0x10, 0x09, 0x40, 0x63, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xB0, 0x09, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x5C, 0x02, 0xF0, 0x09,
+0xC0, 0x24, 0x40, 0x95, 0x00, 0x7C, 0x02, 0x34, 0x09, 0xC0, 0x26, 0x00, 0x9F,
+0x00, 0x7C, 0x4E, 0x70, 0x69, 0xC0, 0x27, 0x00, 0x9F, 0x05, 0x7C, 0x02, 0x10,
+0x09, 0x40, 0x17, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x25,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x26, 0x04, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x6C, 0x02, 0xB0, 0x09, 0xC0,
+0x27, 0x20, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC2, 0x25, 0x20, 0x9F, 0x00,
+0x7C, 0x02, 0xB2, 0x09, 0xC0, 0x27, 0x04, 0x9F, 0x04, 0x6C, 0x02, 0xF0, 0x09,
+0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00,
+0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7E, 0x00,
+0x34, 0x01, 0xC0, 0x07, 0x40, 0x1B, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC4, 0x47,
+0x00, 0x1F, 0x00, 0x7C, 0x00, 0x30, 0x41, 0xC2, 0x04, 0x00, 0x13, 0x00, 0x7C,
+0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x10, 0xF0, 0x01, 0xC0,
+0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x14, 0x00, 0x5D,
+0x00, 0xF4, 0x01, 0xD0, 0x04, 0x40, 0x9F, 0x04, 0x5D, 0x01, 0xF4, 0x21, 0x10,
+0x05, 0x00, 0xDF, 0x02, 0x71, 0x88, 0xF0, 0x01, 0xD0, 0x86, 0xC0, 0x19, 0x01,
+0x5D, 0x11, 0xF4, 0x09, 0x10, 0x37, 0x48, 0x14, 0x20, 0x7B, 0x91, 0x74, 0x01,
+0x10, 0xB7, 0x40, 0x1F, 0x00, 0x5D, 0x00, 0xF4, 0x45, 0xD0, 0x05, 0x40, 0x43,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00,
+0x34, 0x43, 0xD0, 0x08, 0x40, 0xF3, 0x00, 0x8D, 0x08, 0x34, 0x03, 0x10, 0x08,
+0x40, 0xF3, 0x20, 0xD0, 0x02, 0x34, 0x13, 0xD0, 0x2C, 0x40, 0x53, 0x00, 0x8D,
+0x40, 0x76, 0x43, 0x14, 0x3D, 0x40, 0x20, 0x00, 0xC1, 0x04, 0x74, 0x02, 0x50,
+0x30, 0x48, 0x43, 0x00, 0xCC, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x43, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x00, 0xED, 0x00, 0xB4,
+0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x07, 0x10, 0x0E, 0x40,
+0x7B, 0x14, 0xE1, 0x40, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x39, 0x00, 0xED, 0x00,
+0xB4, 0x03, 0x12, 0x2E, 0x50, 0x78, 0x00, 0xE9, 0x00, 0xF4, 0xC2, 0x00, 0x02,
+0x41, 0x0B, 0x04, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x13, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x78, 0x00, 0xEF, 0x01, 0xBC, 0x07,
+0xF0, 0x1E, 0xC2, 0x5B, 0x00, 0xEF, 0x01, 0xF4, 0x07, 0x30, 0x1E, 0xC8, 0x7F,
+0x10, 0xE3, 0x01, 0xBC, 0x07, 0xD0, 0x1E, 0xC0, 0x7B, 0x00, 0xEF, 0x01, 0xFC,
+0x07, 0x30, 0x17, 0xC8, 0x78, 0x08, 0xE3, 0x21, 0xBC, 0x07, 0x70, 0x16, 0xC0,
+0x4B, 0x00, 0xEF, 0x21, 0xBC, 0x05, 0xF0, 0x1E, 0xC0, 0x53, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x17, 0x08, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0x40, 0x17, 0x00,
+0xD7, 0x20, 0x7C, 0x01, 0xF0, 0x0D, 0xC4, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x01,
+0xF3, 0x05, 0xC0, 0x32, 0x10, 0x5F, 0x00, 0x7C, 0x03, 0xE0, 0x05, 0xC0, 0x07,
+0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF1, 0x0D, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA0, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x05, 0xF0, 0x1F,
+0xC0, 0x7F, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7C, 0x00, 0xFF,
+0x21, 0xBC, 0x85, 0x30, 0x1F, 0xC0, 0x78, 0x02, 0xF3, 0x01, 0xFC, 0x05, 0xF0,
+0x5F, 0xC0, 0x7F, 0x00, 0xFF, 0x09, 0xFC, 0x16, 0xF0, 0x17, 0xC4, 0x6D, 0x00,
+0xFF, 0x09, 0xF4, 0x27, 0x30, 0x9F, 0xC0, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x80, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x09, 0xD0, 0x0E, 0x40,
+0x3B, 0x00, 0xE1, 0x28, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x38, 0x00, 0xED, 0x08,
+0xB4, 0x03, 0x12, 0x0F, 0x40, 0x38, 0x06, 0xE1, 0x18, 0xB4, 0x43, 0xD0, 0x06,
+0x41, 0x3B, 0x00, 0xED, 0x0A, 0xB4, 0x03, 0xD0, 0x07, 0x40, 0x28, 0x00, 0xED,
+0x08, 0xF4, 0x0B, 0x14, 0x0E, 0x40, 0x57, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x01, 0xD0, 0x8E, 0x40, 0x1F,
+0x00, 0xE1, 0x00, 0xB4, 0x09, 0xD0, 0x8F, 0x40, 0x39, 0x02, 0x6D, 0x02, 0xF4,
+0x09, 0x10, 0x26, 0x40, 0xBC, 0x08, 0xE1, 0x00, 0xB4, 0x01, 0xD0, 0x4E, 0x40,
+0x3B, 0x02, 0xED, 0x80, 0xB4, 0x93, 0xD0, 0x07, 0x40, 0x19, 0x00, 0xED, 0x40,
+0xB4, 0x01, 0x12, 0x0E, 0x40, 0x23, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x08, 0xD0, 0x0C, 0x41, 0x07, 0x01,
+0xC1, 0x01, 0x34, 0x82, 0xD0, 0x2C, 0x4D, 0x65, 0x02, 0x8D, 0x88, 0x74, 0x24,
+0x10, 0x08, 0x40, 0x30, 0x00, 0xC1, 0x02, 0x34, 0x0C, 0xD0, 0x00, 0x40, 0x73,
+0x04, 0x9D, 0x0F, 0x34, 0x02, 0xD0, 0x24, 0x40, 0x00, 0x20, 0xCD, 0x09, 0x74,
+0x00, 0x10, 0x0C, 0x60, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA8, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x36, 0xF0, 0x0D, 0xC0, 0xA7, 0x00, 0xC3,
+0x12, 0x3C, 0x14, 0xF0, 0x2D, 0xC0, 0x85, 0x00, 0x0F, 0x00, 0x7C, 0x02, 0x30,
+0x51, 0x40, 0x74, 0x80, 0xD3, 0x09, 0x74, 0x26, 0xF0, 0x19, 0xC0, 0x33, 0x04,
+0x1E, 0x00, 0x7C, 0x02, 0xF0, 0x14, 0xC0, 0x05, 0x00, 0xDF, 0x01, 0x7C, 0x02,
+0x30, 0x0D, 0xC8, 0x77, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x1D, 0xC8, 0xC7, 0x20, 0xDF, 0x04,
+0x7C, 0x00, 0xF0, 0x1D, 0x00, 0x26, 0x01, 0x1D, 0x80, 0x7C, 0x0A, 0xF0, 0x01,
+0xD0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x0A, 0xF0, 0x09, 0x41, 0x37, 0x20, 0x9F,
+0x00, 0x78, 0x02, 0xC0, 0x15, 0xC0, 0x07, 0x00, 0xDF, 0x00, 0x7C, 0x0A, 0xF0,
+0x0D, 0xC0, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F,
+0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x2C, 0x00, 0xF3, 0x05, 0xEC,
+0x00, 0xB0, 0x5F, 0xC0, 0x0F, 0x00, 0x33, 0x20, 0xCC, 0x02, 0x30, 0x03, 0xC0,
+0x3F, 0x00, 0xFF, 0x04, 0xFC, 0x02, 0xF0, 0x03, 0xC0, 0x3F, 0x20, 0x33, 0x20,
+0xCC, 0x17, 0xF0, 0x17, 0xD1, 0x0C, 0x00, 0xFF, 0x10, 0xFC, 0x00, 0x10, 0x0F,
+0xC2, 0x27, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00,
+0xDD, 0x00, 0x74, 0x06, 0xD1, 0x0C, 0x40, 0x44, 0x08, 0xD1, 0x01, 0x44, 0x04,
+0x10, 0x1D, 0x40, 0x47, 0x01, 0x11, 0x01, 0x44, 0x06, 0x10, 0x31, 0x40, 0xF7,
+0x04, 0xDD, 0x01, 0x74, 0x1E, 0xD0, 0x51, 0x40, 0x37, 0x20, 0x11, 0x03, 0x44,
+0x03, 0xD0, 0xC5, 0x40, 0x44, 0x01, 0xDD, 0x00, 0x74, 0x2C, 0x10, 0x0D, 0x46,
+0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x00, 0xDD,
+0x00, 0x74, 0x06, 0xD0, 0x1D, 0x40, 0x64, 0x04, 0xD1, 0x00, 0x64, 0x0E, 0x10,
+0x0D, 0x40, 0x47, 0x80, 0x91, 0x03, 0x44, 0x0C, 0x10, 0x19, 0x42, 0x77, 0x00,
+0xDD, 0x00, 0x74, 0x04, 0xD0, 0x19, 0x40, 0x37, 0x09, 0x11, 0x01, 0x44, 0x02,
+0xD0, 0x05, 0x40, 0x44, 0x00, 0xDD, 0x00, 0x74, 0x82, 0x40, 0x0D, 0x40, 0x07,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x30, 0x00, 0xCD, 0x00,
+0x34, 0x02, 0xD0, 0x0D, 0x40, 0x20, 0x40, 0xC1, 0x00, 0x44, 0x02, 0x10, 0x0C,
+0x40, 0x23, 0x60, 0x91, 0x00, 0x04, 0x02, 0x16, 0x08, 0x40, 0x33, 0x20, 0xCD,
+0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x37, 0x08, 0x81, 0x20, 0x05, 0x02, 0xD0,
+0x04, 0x40, 0x00, 0x00, 0xCD, 0x00, 0x34, 0x00, 0x50, 0x0C, 0x40, 0x43, 0x20,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x36, 0x00, 0xDF, 0x00, 0x7C,
+0x00, 0xF0, 0x0D, 0xC2, 0x24, 0x00, 0xD3, 0x00, 0x6C, 0x00, 0x30, 0x0D, 0xC0,
+0x07, 0x00, 0x13, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x00, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0x13, 0x40, 0x4C, 0x03, 0xF0, 0x05,
+0xC0, 0x04, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x74, 0x0D, 0xC0, 0x07, 0x40, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02,
+0xF0, 0x0F, 0xC8, 0x2B, 0x08, 0xFF, 0x20, 0xFC, 0x02, 0xF0, 0x0E, 0xC0, 0x2F,
+0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF0, 0x0B, 0xC2, 0x2F, 0x00, 0xFF, 0x00, 0xFC,
+0x02, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x0F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xB0, 0x0F, 0xC0, 0x17, 0x22, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x4F, 0x00, 0x33, 0x01, 0xCC, 0x24, 0x30,
+0x13, 0xC0, 0x2C, 0x02, 0xF3, 0x00, 0x8C, 0x07, 0x30, 0xCF, 0xC0, 0x2C, 0x40,
+0x33, 0x08, 0xCC, 0x23, 0x72, 0xC7, 0xC0, 0xCE, 0x00, 0x33, 0x04, 0xDC, 0x00,
+0x30, 0x13, 0xC0, 0xCF, 0x00, 0x3F, 0x01, 0xED, 0x04, 0x30, 0x13, 0xC0, 0x4C,
+0x00, 0x33, 0x01, 0xCC, 0x04, 0x30, 0x13, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x21, 0x11, 0x00, 0x44, 0x00, 0x10, 0x04,
+0x40, 0x24, 0x09, 0xF1, 0x00, 0x44, 0x03, 0x30, 0x21, 0x40, 0xB0, 0x05, 0x01,
+0x26, 0x05, 0x3B, 0x30, 0xE1, 0x40, 0x05, 0x21, 0x51, 0x0B, 0x44, 0x18, 0x15,
+0x41, 0xC0, 0x23, 0x00, 0x1D, 0x00, 0x44, 0x82, 0x10, 0x01, 0x42, 0x44, 0x00,
+0x11, 0x80, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x11, 0xA0, 0x03, 0x04, 0x11, 0x01, 0x04, 0x12, 0x10, 0x00, 0x40,
+0x00, 0x00, 0xC1, 0x00, 0x64, 0x53, 0x90, 0x3C, 0x48, 0x24, 0x02, 0x01, 0x06,
+0x25, 0x83, 0xD0, 0x05, 0x40, 0x00, 0x00, 0x09, 0x00, 0x34, 0x48, 0x90, 0x00,
+0x41, 0x03, 0x01, 0x89, 0x00, 0x44, 0x00, 0x90, 0x01, 0x40, 0x46, 0x00, 0x89,
+0x00, 0x24, 0x02, 0x10, 0x08, 0x40, 0x45, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA8, 0x05, 0x00, 0x11, 0x40, 0x04, 0x02, 0x10, 0x05, 0x40, 0x04,
+0x12, 0xC1, 0x00, 0x64, 0x03, 0x14, 0x09, 0x40, 0x34, 0x02, 0x11, 0x01, 0x64,
+0x07, 0x10, 0x01, 0x40, 0x45, 0x04, 0x59, 0x20, 0x64, 0x44, 0x92, 0x11, 0x42,
+0x27, 0x00, 0x8C, 0x00, 0x44, 0x02, 0x98, 0x11, 0x00, 0x06, 0x00, 0x89, 0x00,
+0x24, 0x02, 0x10, 0x08, 0x40, 0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA0, 0x37, 0x40, 0x43, 0x00, 0x4C, 0x04, 0x30, 0x21, 0xC1, 0x64, 0x00,
+0xD3, 0x00, 0x2D, 0x03, 0xB0, 0x0D, 0xC4, 0xC0, 0x40, 0x13, 0x00, 0x6C, 0x07,
+0xF2, 0x0D, 0xC0, 0x84, 0x40, 0x5B, 0x81, 0x7C, 0x0C, 0xB1, 0x51, 0xE0, 0x07,
+0x00, 0x1F, 0x00, 0x4C, 0x01, 0xB0, 0x08, 0xC0, 0x12, 0x18, 0x1B, 0x01, 0x6C,
+0x04, 0x30, 0x11, 0xC0, 0x09, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0x88, 0x3D, 0x20, 0x7F, 0x00, 0xFC, 0x24, 0xF0, 0x07, 0xC0, 0x73, 0x00, 0xFF,
+0x00, 0xDC, 0x02, 0xF0, 0x26, 0xC0, 0x0F, 0x30, 0x3F, 0x20, 0x9C, 0x03, 0xF0,
+0x05, 0xC0, 0x0D, 0x00, 0x77, 0x03, 0xDC, 0x00, 0x72, 0x03, 0xC0, 0x2D, 0x02,
+0x3F, 0x08, 0xDC, 0x03, 0x74, 0x0B, 0xC0, 0x1D, 0x18, 0x36, 0x49, 0xDC, 0x24,
+0xF0, 0x93, 0xC0, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08,
+0x75, 0x00, 0x53, 0x10, 0x4C, 0x06, 0x32, 0x01, 0xCA, 0x24, 0x00, 0xD3, 0x00,
+0x4D, 0x03, 0x30, 0x0D, 0xC0, 0x24, 0x00, 0x13, 0x02, 0x6C, 0x02, 0x30, 0x0D,
+0xC1, 0x86, 0x00, 0x4F, 0x50, 0xCC, 0x18, 0x30, 0x01, 0xC8, 0x07, 0x40, 0x93,
+0x05, 0x7C, 0x01, 0xF0, 0x09, 0xC0, 0x14, 0x04, 0x93, 0x11, 0x4C, 0x46, 0x30,
+0x59, 0xC0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x74,
+0x00, 0x51, 0x80, 0x44, 0x06, 0x12, 0x05, 0x40, 0x34, 0x09, 0xF1, 0x00, 0x44,
+0x0B, 0x10, 0xBD, 0x40, 0xA4, 0x02, 0x35, 0x00, 0x44, 0x00, 0x10, 0x7C, 0x40,
+0x04, 0x06, 0x5D, 0x11, 0x2C, 0x08, 0x10, 0x11, 0x00, 0x67, 0x08, 0x9B, 0x23,
+0x34, 0x2B, 0xD0, 0xA9, 0x40, 0x94, 0x04, 0x91, 0x03, 0x44, 0x0E, 0x10, 0x39,
+0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x04, 0x00,
+0x89, 0x00, 0x04, 0x01, 0x10, 0x09, 0x40, 0x60, 0x00, 0xC1, 0x01, 0x04, 0x4B,
+0x14, 0x3C, 0x40, 0xA0, 0x00, 0x11, 0x00, 0x24, 0x03, 0x18, 0x24, 0x40, 0x06,
+0x08, 0x8D, 0x02, 0x14, 0x00, 0x11, 0x10, 0x48, 0x53, 0x02, 0x45, 0x00, 0x34,
+0x00, 0xD0, 0x04, 0x40, 0x61, 0x00, 0x41, 0x02, 0x04, 0x09, 0x10, 0x04, 0x02,
+0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x48, 0x00, 0xB9,
+0x09, 0x84, 0x0D, 0x10, 0x1E, 0x42, 0xF8, 0x00, 0xE1, 0x01, 0xC4, 0x87, 0x14,
+0x1C, 0x41, 0x68, 0x02, 0xA5, 0x01, 0x84, 0x07, 0x10, 0x92, 0x50, 0x48, 0x20,
+0xAD, 0x21, 0x36, 0x84, 0x18, 0x12, 0x40, 0x7B, 0x00, 0x6D, 0x01, 0xB4, 0x06,
+0xD0, 0x97, 0x40, 0x6D, 0x00, 0x61, 0x09, 0x84, 0x25, 0x10, 0x16, 0x40, 0x10,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x00, 0x40, 0x8B, 0x08,
+0x4C, 0x13, 0x30, 0x08, 0xC0, 0x00, 0x42, 0xD3, 0x10, 0x0C, 0x03, 0x30, 0x0C,
+0x40, 0x20, 0x02, 0x83, 0x00, 0x2C, 0x03, 0x12, 0x04, 0xC2, 0x02, 0x00, 0x8F,
+0x08, 0x1C, 0x12, 0x30, 0x00, 0xE5, 0x13, 0x00, 0xC7, 0x00, 0x3C, 0x20, 0xF0,
+0x04, 0xC0, 0x21, 0x00, 0xD3, 0x08, 0x4C, 0x23, 0x30, 0x0D, 0xC0, 0x48, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x0D, 0x00, 0xA7, 0x08, 0xFC,
+0x03, 0xF0, 0x0F, 0xC8, 0x1F, 0x00, 0xFF, 0x80, 0xFD, 0x03, 0xF0, 0x0F, 0xC0,
+0x3F, 0x0A, 0xBE, 0x80, 0xFC, 0x03, 0xF4, 0x03, 0xC2, 0x0F, 0x02, 0xEF, 0x20,
+0xEC, 0x02, 0xF0, 0x83, 0xC0, 0x3F, 0x02, 0xFB, 0x00, 0xFC, 0x02, 0xF1, 0x06,
+0xC0, 0x2A, 0x02, 0xFF, 0x08, 0xFC, 0x23, 0xF0, 0x8F, 0xC0, 0x0B, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x00, 0xCF, 0x00, 0x5C, 0x05,
+0x30, 0x09, 0xC0, 0x24, 0x00, 0xDF, 0x0D, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x27,
+0x00, 0x13, 0x00, 0xCD, 0x03, 0x34, 0x0D, 0xD8, 0x05, 0x10, 0x13, 0x00, 0x7C,
+0x02, 0x70, 0x01, 0xC4, 0x13, 0x00, 0x53, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xD0,
+0x34, 0x00, 0x5F, 0x00, 0x4E, 0x01, 0x30, 0x15, 0xC0, 0x54, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x39, 0x00, 0xED, 0x80, 0x84, 0x01, 0x10,
+0x0E, 0x40, 0x38, 0x00, 0xCD, 0x10, 0x84, 0x02, 0xD0, 0x0E, 0x40, 0x2B, 0x10,
+0x81, 0x04, 0x84, 0x03, 0x10, 0x04, 0xC0, 0x0A, 0x00, 0x21, 0x00, 0xB4, 0x02,
+0x11, 0x06, 0x48, 0x3B, 0x00, 0x61, 0x00, 0xB4, 0x03, 0xD2, 0x0F, 0x40, 0x38,
+0x20, 0x6D, 0x00, 0x84, 0x01, 0x10, 0x06, 0x40, 0x48, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xED, 0x01, 0x94, 0x07, 0x10, 0x1A,
+0x50, 0x68, 0x00, 0xED, 0x05, 0x84, 0x47, 0xD8, 0x1E, 0x40, 0x6F, 0x00, 0xA1,
+0x1D, 0x85, 0x07, 0x10, 0x1E, 0x40, 0xC9, 0x18, 0xE1, 0x01, 0xF4, 0x0E, 0x50,
+0x12, 0x40, 0x5B, 0x00, 0xE1, 0x01, 0xB4, 0x05, 0xD0, 0x1E, 0x42, 0x78, 0x00,
+0xED, 0x01, 0x84, 0x87, 0x10, 0x1E, 0x40, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x28, 0x73, 0x02, 0xDD, 0x00, 0x04, 0x03, 0x10, 0x0C, 0x40,
+0xB0, 0x00, 0xCD, 0x00, 0x04, 0x07, 0xD0, 0x0D, 0x40, 0xA3, 0x01, 0xC1, 0x40,
+0x04, 0x09, 0x10, 0x8D, 0x40, 0x76, 0x00, 0xC1, 0x03, 0x34, 0x0F, 0x10, 0x88,
+0x42, 0x33, 0x00, 0xC1, 0x00, 0x34, 0x07, 0xD0, 0x0C, 0x40, 0x30, 0x00, 0xCD,
+0x00, 0x04, 0x03, 0x10, 0x0C, 0x40, 0x48, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x17, 0xA0, 0x95, 0x00, 0x5F, 0x00, 0x5C, 0x01, 0x34, 0x05, 0xC0, 0x1C,
+0x01, 0x5F, 0x00, 0x4C, 0x01, 0xF0, 0x07, 0xC0, 0xDF, 0x44, 0x73, 0x00, 0xCC,
+0x31, 0x30, 0x17, 0xC2, 0x9D, 0x40, 0x73, 0x07, 0xFC, 0x29, 0x72, 0x16, 0xC0,
+0x17, 0x50, 0x53, 0x20, 0x7C, 0x01, 0xF1, 0x05, 0xC0, 0x14, 0x10, 0x5F, 0x00,
+0x4D, 0x01, 0x34, 0x05, 0xD0, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x08, 0x05, 0x04, 0x1D, 0x00, 0x7C, 0x00, 0xF2, 0x01, 0xC8, 0x03, 0x04,
+0x1F, 0x40, 0x7D, 0x08, 0xF0, 0x01, 0xC0, 0x07, 0x10, 0x1F, 0x20, 0x7C, 0x00,
+0xF2, 0x11, 0xD0, 0x07, 0x04, 0x0F, 0x12, 0x3C, 0x08, 0xF1, 0x41, 0xC0, 0x07,
+0x00, 0x1F, 0x00, 0x7C, 0x20, 0xF0, 0x11, 0xC8, 0x07, 0x00, 0x1F, 0x00, 0x7C,
+0x00, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x25, 0x00, 0x9F, 0x02, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x02, 0x90,
+0x01, 0x7C, 0x02, 0x34, 0x09, 0xC0, 0x24, 0x00, 0x83, 0x00, 0x4C, 0x02, 0x30,
+0x09, 0xC0, 0x64, 0x00, 0x93, 0x05, 0x4C, 0x06, 0x10, 0x09, 0xC8, 0x24, 0x00,
+0x93, 0x00, 0x64, 0x0A, 0x30, 0x09, 0xC0, 0xE4, 0x10, 0x9F, 0x02, 0x4D, 0x0A,
+0x30, 0x59, 0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+0xA6, 0x10, 0x9D, 0x00, 0x45, 0x0A, 0xD0, 0x08, 0xC0, 0x66, 0x00, 0x91, 0x01,
+0x34, 0x1A, 0x12, 0x09, 0x48, 0xA4, 0x02, 0x95, 0x00, 0x44, 0x02, 0x12, 0x99,
+0x51, 0x24, 0x08, 0x91, 0x25, 0x44, 0xA6, 0x10, 0x09, 0x40, 0x20, 0x00, 0x91,
+0x02, 0x04, 0x0A, 0x10, 0x29, 0x50, 0x64, 0x08, 0x9D, 0x42, 0x44, 0x0A, 0x10,
+0x39, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24,
+0x80, 0xBD, 0x00, 0xC4, 0x02, 0xD0, 0x0B, 0x40, 0x24, 0x40, 0x95, 0x08, 0x74,
+0x22, 0x14, 0x09, 0x48, 0xB0, 0x00, 0xD9, 0x04, 0x24, 0x02, 0x14, 0x09, 0x40,
+0x24, 0x42, 0xD1, 0x00, 0x45, 0x42, 0x50, 0x09, 0x52, 0x24, 0x40, 0xA1, 0x00,
+0xF4, 0x02, 0x10, 0x2A, 0x42, 0x2C, 0x00, 0xAD, 0x00, 0xA4, 0x02, 0x10, 0x0B,
+0x42, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x68, 0x00,
+0xED, 0x00, 0x84, 0x06, 0xD0, 0x0B, 0x40, 0x22, 0x01, 0x85, 0x04, 0x74, 0x02,
+0x10, 0x48, 0x40, 0x20, 0x01, 0x8D, 0x04, 0x25, 0x12, 0x10, 0x48, 0x40, 0x60,
+0x20, 0x81, 0x84, 0x05, 0x12, 0x14, 0x08, 0x40, 0x2C, 0x00, 0xA1, 0x01, 0xD4,
+0x02, 0x10, 0x0A, 0x42, 0x68, 0x80, 0xAD, 0x01, 0xA4, 0x06, 0x10, 0x1A, 0x40,
+0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x86, 0x02, 0x1F,
+0x0A, 0x0D, 0x28, 0xF0, 0xA2, 0xC0, 0x94, 0x02, 0x17, 0x0A, 0x7C, 0x28, 0x30,
+0xA5, 0xD0, 0x84, 0x02, 0x1B, 0x0A, 0x2C, 0x28, 0x31, 0xA1, 0xD0, 0x80, 0x22,
+0x13, 0x00, 0x4C, 0x28, 0x70, 0xA1, 0xC0, 0x84, 0x02, 0x13, 0x0A, 0x7C, 0x29,
+0x30, 0xA1, 0xC0, 0x04, 0x00, 0x0F, 0x0A, 0x2C, 0x28, 0x32, 0xA2, 0xC0, 0x77,
+0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x27, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x2F, 0x02, 0x9B, 0x08, 0xEC, 0x02, 0xF4, 0x8B,
+0xC8, 0x2B, 0x02, 0xB7, 0x08, 0xDC, 0x23, 0xF0, 0x8B, 0xC2, 0x2F, 0x00, 0xBF,
+0x68, 0xBC, 0x22, 0xF0, 0x0B, 0xC2, 0x27, 0x00, 0x9F, 0x20, 0x6C, 0x02, 0xF4,
+0x09, 0xC8, 0x27, 0x00, 0x9F, 0x00, 0x5C, 0x02, 0xF4, 0x09, 0xC0, 0x67, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x2F, 0x00, 0xF3, 0x28, 0xDC,
+0x02, 0xF0, 0x09, 0xC0, 0x2F, 0x42, 0xB3, 0x04, 0xCC, 0x02, 0x30, 0xCF, 0xC0,
+0x2B, 0x00, 0xA3, 0x05, 0x4D, 0x16, 0x32, 0x9B, 0xC0, 0xAF, 0x10, 0xB3, 0x05,
+0xDC, 0x36, 0x30, 0x0B, 0xC4, 0x2C, 0x00, 0xB3, 0x00, 0xFC, 0x02, 0xF0, 0x8B,
+0xC0, 0x3C, 0x18, 0xBF, 0x40, 0xFC, 0x22, 0xF0, 0x0B, 0xC0, 0x63, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x01, 0x01, 0x04, 0x44, 0x41,
+0xD0, 0x01, 0x41, 0x07, 0x02, 0x11, 0x14, 0x44, 0x10, 0x10, 0xC0, 0x40, 0x87,
+0x44, 0x11, 0x17, 0x44, 0x5C, 0x14, 0x31, 0x44, 0x47, 0x00, 0x11, 0x22, 0x44,
+0x04, 0x10, 0x55, 0x41, 0x44, 0x05, 0x51, 0x14, 0x74, 0x10, 0xD0, 0x41, 0x50,
+0x04, 0x00, 0x5D, 0x10, 0x74, 0x01, 0xD0, 0x45, 0x41, 0x73, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x21, 0x45, 0x81, 0x04, 0x14, 0x12, 0xD0,
+0x08, 0x40, 0x23, 0x00, 0x81, 0x0C, 0x24, 0x52, 0x10, 0x48, 0x44, 0x23, 0x03,
+0x81, 0x08, 0x04, 0x22, 0x10, 0x68, 0x40, 0x27, 0x01, 0x89, 0x08, 0x34, 0x1A,
+0x14, 0x09, 0x50, 0x24, 0x00, 0x89, 0x24, 0x34, 0x52, 0xD1, 0x48, 0x40, 0x20,
+0x00, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x48, 0x40, 0x43, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x28, 0x21, 0x00, 0x91, 0x00, 0x44, 0x02, 0xD2, 0x09,
+0x40, 0x27, 0x00, 0x91, 0x00, 0x65, 0x02, 0x14, 0x29, 0x40, 0xA7, 0x01, 0x91,
+0x11, 0x44, 0x12, 0x10, 0x09, 0x40, 0x67, 0x00, 0x99, 0x06, 0x64, 0x0A, 0x10,
+0x19, 0x40, 0x24, 0x40, 0x99, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00,
+0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x20, 0x25, 0x00, 0x93, 0x00, 0x5C, 0x0A, 0xF0, 0x09, 0xC0,
+0xA7, 0x01, 0x93, 0x00, 0x6D, 0x06, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x93, 0x01,
+0x4C, 0x0A, 0x30, 0x69, 0xC0, 0x23, 0x24, 0x9B, 0x00, 0x7C, 0x06, 0x32, 0x18,
+0xC0, 0x24, 0x00, 0x9A, 0x02, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x80, 0x9F,
+0x02, 0x7C, 0x0A, 0xF0, 0x29, 0xC0, 0x17, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x16, 0x08, 0x25, 0x10, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x23,
+0x00, 0x8F, 0x00, 0x5C, 0x4E, 0xF0, 0x09, 0xC0, 0x27, 0x44, 0x8F, 0x40, 0x7C,
+0x02, 0xF2, 0x09, 0xC2, 0x27, 0x40, 0x87, 0x01, 0x54, 0xCA, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x97, 0x00, 0x7C, 0x02, 0xF1, 0x09, 0xC0, 0x27, 0x0C, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x53, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x08, 0x05, 0x04, 0x1F, 0x04, 0x4C, 0x08, 0xB4, 0x01, 0xD0, 0x04, 0x01,
+0x13, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x00, 0x00, 0x13, 0x02, 0x4C, 0x08,
+0x30, 0x21, 0xC0, 0x84, 0x00, 0x13, 0x01, 0x0C, 0x00, 0xB4, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x06, 0x4D, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x02, 0x1F, 0x02, 0x4D,
+0x48, 0x34, 0x21, 0xD0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0xDC, 0x00, 0x6D, 0x00, 0xC4, 0x05, 0x30, 0x05, 0x40, 0x1C, 0x00, 0x51,
+0x00, 0xC5, 0x05, 0x10, 0x07, 0x48, 0x1C, 0x00, 0x51, 0x20, 0x44, 0x01, 0x50,
+0x67, 0x40, 0x1C, 0x48, 0x71, 0x10, 0xEC, 0x09, 0x10, 0x15, 0x40, 0x13, 0x00,
+0x7D, 0x83, 0xC4, 0x01, 0x00, 0x17, 0x40, 0x1F, 0x00, 0x7D, 0x00, 0xC4, 0x09,
+0x10, 0x07, 0x40, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0,
+0xF2, 0x02, 0x8D, 0x02, 0x04, 0x07, 0x50, 0x0C, 0x40, 0xB0, 0x40, 0xC5, 0x00,
+0x44, 0x0F, 0x10, 0x8C, 0x40, 0x20, 0x00, 0xC1, 0x00, 0x45, 0x03, 0x18, 0x6C,
+0x44, 0x30, 0x20, 0xC1, 0x01, 0x04, 0x07, 0x10, 0x18, 0x40, 0x33, 0x08, 0xCD,
+0x03, 0x04, 0x05, 0x10, 0x89, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x05, 0x0B, 0x10,
+0x0C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38,
+0x10, 0x2D, 0x04, 0x84, 0x47, 0x50, 0xDF, 0x42, 0x08, 0x04, 0xE5, 0x00, 0x84,
+0x41, 0x10, 0x1E, 0x40, 0x2C, 0x00, 0xF1, 0x00, 0x84, 0x13, 0x50, 0x1E, 0x50,
+0x3C, 0x05, 0x41, 0x20, 0xA4, 0x0B, 0x10, 0x0E, 0x41, 0x3B, 0x00, 0xED, 0x03,
+0x84, 0x0D, 0x11, 0x02, 0x40, 0x0B, 0x00, 0xED, 0x01, 0x84, 0x07, 0x10, 0x1E,
+0x44, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x79, 0x00,
+0xAF, 0x07, 0xCD, 0x07, 0x70, 0x1E, 0xC0, 0x40, 0x40, 0x87, 0x89, 0x8C, 0x04,
+0x34, 0x1E, 0x10, 0x78, 0x40, 0xE3, 0x31, 0xCC, 0x0F, 0x34, 0x1E, 0xC0, 0xE8,
+0x00, 0x63, 0x01, 0x0C, 0x04, 0x34, 0x1A, 0xC0, 0x7B, 0x00, 0xFF, 0x01, 0xCC,
+0x06, 0x34, 0x12, 0xC0, 0x4B, 0x00, 0xFD, 0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC0,
+0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0x1F,
+0x20, 0x7C, 0x03, 0x30, 0x2C, 0xC0, 0x07, 0x00, 0xDB, 0x04, 0x3C, 0x00, 0xF2,
+0x05, 0xC0, 0x37, 0x00, 0xDF, 0x06, 0x7C, 0x5B, 0xB0, 0x88, 0xC0, 0x13, 0x00,
+0x5F, 0x20, 0x7C, 0x00, 0xF0, 0x0F, 0xC0, 0xB7, 0x0D, 0xDF, 0x00, 0xFC, 0x80,
+0xF0, 0x09, 0xC0, 0x07, 0x00, 0xDF, 0x20, 0x7C, 0x01, 0xF0, 0x09, 0xC2, 0x43,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x7D, 0x00, 0x2F, 0x01,
+0xDC, 0x13, 0xF0, 0x3F, 0xC0, 0x4C, 0x10, 0xF7, 0x01, 0xDC, 0x04, 0x30, 0x1F,
+0xC8, 0x6C, 0x00, 0xF3, 0x01, 0xCC, 0x07, 0x31, 0x1B, 0xD0, 0x6D, 0x00, 0x73,
+0x01, 0x9D, 0x04, 0xB2, 0x4F, 0xC0, 0x7C, 0x00, 0xF3, 0x01, 0xDC, 0x05, 0x30,
+0x1F, 0xC0, 0x4C, 0x00, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0x08,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x00, 0x27, 0x00, 0x84,
+0x0A, 0xD0, 0x8F, 0x41, 0x0C, 0x00, 0xE1, 0x00, 0xEC, 0x00, 0x12, 0x4A, 0x40,
+0x08, 0x02, 0xE0, 0x00, 0x84, 0x13, 0xA1, 0x0B, 0x40, 0x38, 0x00, 0x61, 0x08,
+0x84, 0x02, 0x50, 0x0F, 0x40, 0x3C, 0x02, 0xA7, 0x00, 0xC4, 0x21, 0x12, 0x07,
+0x40, 0x08, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x2E, 0x40, 0x57, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0xAD, 0x00, 0x94, 0x23,
+0xD0, 0x0E, 0x40, 0x08, 0x00, 0x85, 0x00, 0x94, 0x40, 0x10, 0x0E, 0x40, 0x3C,
+0x00, 0xE1, 0x08, 0x84, 0x03, 0x80, 0x02, 0x40, 0x29, 0x02, 0x21, 0x00, 0xD4,
+0x00, 0x14, 0x2E, 0x40, 0x38, 0x00, 0x61, 0x00, 0x94, 0x02, 0x10, 0x06, 0x40,
+0x08, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x03, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x35, 0x00, 0x05, 0x00, 0x04, 0x02, 0xD0,
+0x1C, 0x40, 0x00, 0x00, 0xC1, 0x00, 0x24, 0x00, 0x12, 0x31, 0x40, 0x30, 0x00,
+0xC1, 0x00, 0x05, 0x83, 0x90, 0x10, 0x40, 0x10, 0x04, 0x41, 0x61, 0x04, 0x04,
+0x54, 0x9C, 0x44, 0x30, 0x08, 0x95, 0x00, 0x04, 0x00, 0x10, 0x0C, 0x40, 0x00,
+0x00, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x08, 0x40, 0x13, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA0, 0x35, 0x00, 0xFF, 0x00, 0x5C, 0x03, 0xF0, 0x1F,
+0xD0, 0x24, 0x00, 0xD7, 0x00, 0x1C, 0x04, 0x30, 0x8D, 0xD5, 0x60, 0x00, 0xD3,
+0x0A, 0xCC, 0x0B, 0xB0, 0x83, 0xD1, 0x39, 0x48, 0x13, 0x10, 0x5D, 0x02, 0x30,
+0x0D, 0xC4, 0xA4, 0x00, 0xD3, 0x00, 0x5C, 0x09, 0x30, 0x0D, 0xC0, 0x00, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x08, 0x27, 0x00, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x07, 0x02, 0xDF, 0x20, 0x5C, 0x08, 0xF4, 0x2D, 0xC0, 0xE7, 0x40, 0xDF, 0x08,
+0x7C, 0x03, 0xF0, 0x09, 0xC0, 0x37, 0x02, 0x1F, 0x20, 0x7C, 0xA2, 0x74, 0x0D,
+0xC0, 0x37, 0x01, 0xD7, 0x40, 0x7C, 0x11, 0xF0, 0x2D, 0xC0, 0x07, 0x00, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x08, 0x1F, 0x00, 0xB3, 0x00, 0xCC, 0x01, 0xF0, 0x0F, 0xC0, 0x0B,
+0x00, 0xB2, 0x00, 0xCC, 0x00, 0x30, 0x1F, 0xC0, 0x2C, 0x40, 0x97, 0x00, 0x7C,
+0x43, 0x32, 0x53, 0xD0, 0x2E, 0x00, 0x13, 0x00, 0xFC, 0x20, 0x20, 0x1F, 0xC0,
+0x2F, 0x00, 0xFD, 0x00, 0xEC, 0x00, 0xF0, 0x0F, 0xC0, 0x0C, 0x10, 0x72, 0x00,
+0xFC, 0x27, 0xF0, 0x07, 0xC0, 0x03, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x81, 0x00, 0x06, 0x08, 0x11, 0x00, 0x45, 0x0B, 0xD0, 0x0D, 0xC8, 0x45, 0x00,
+0xD1, 0x00, 0x44, 0x04, 0x10, 0xBD, 0x41, 0x64, 0x20, 0x91, 0x08, 0x34, 0x03,
+0x12, 0x09, 0x40, 0x15, 0x00, 0x11, 0x01, 0x7C, 0x00, 0x50, 0x1D, 0x40, 0x77,
+0x00, 0xDD, 0x09, 0x44, 0x04, 0xD0, 0x3D, 0x48, 0xC4, 0x04, 0xD1, 0x00, 0x74,
+0x05, 0xD0, 0xBD, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0xA0, 0x76, 0x00, 0x41, 0x08, 0x44, 0x23, 0xD0, 0x0D, 0x40, 0x47, 0x00, 0xC5,
+0x00, 0x44, 0x0C, 0x10, 0x0D, 0x40, 0xE5, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x12,
+0x00, 0x41, 0x26, 0x00, 0x11, 0x23, 0x34, 0x00, 0xD8, 0x4D, 0x40, 0x27, 0x01,
+0xDD, 0x00, 0x64, 0x44, 0xD0, 0x6C, 0x40, 0x44, 0x80, 0xD5, 0x01, 0x74, 0x03,
+0xD0, 0x0D, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x70, 0x00, 0x41, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x01, 0x00, 0xC5, 0x00,
+0x04, 0x80, 0x14, 0x0C, 0x50, 0x21, 0x00, 0xC1, 0x00, 0x74, 0x83, 0x18, 0x08,
+0x50, 0x31, 0x00, 0x01, 0x00, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x00, 0x04, 0x00, 0xD0, 0x0C, 0x40, 0x00, 0x80, 0x85, 0x01, 0x34, 0x02, 0xD0,
+0x0C, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x36,
+0x00, 0x93, 0x80, 0x4C, 0x81, 0xF0, 0x0F, 0xC0, 0x07, 0x20, 0xB7, 0x00, 0x4D,
+0x00, 0x30, 0x0C, 0x44, 0x25, 0x00, 0xB3, 0x00, 0xFC, 0x03, 0x31, 0x01, 0xC4,
+0x22, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x0D, 0xC2, 0x2F, 0x00, 0x4F, 0x40,
+0x6C, 0x00, 0xF0, 0x0D, 0xC0, 0x04, 0x00, 0x57, 0x00, 0x7C, 0x03, 0xF0, 0x05,
+0xC4, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00,
+0x3F, 0x40, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0xFB, 0x40, 0xFC, 0x00,
+0xF0, 0x0F, 0xC0, 0x2A, 0x00, 0xBF, 0x00, 0xFC, 0x03, 0xF0, 0x03, 0x40, 0x1F,
+0x40, 0x3F, 0x00, 0xD8, 0x00, 0x72, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC,
+0x00, 0xF0, 0x0F, 0xC8, 0x0F, 0x08, 0xFB, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xFF,
+0x01, 0xFC, 0x13, 0x32, 0x8B, 0xC2, 0x2C, 0x09, 0xFF, 0x01, 0xFC, 0x63, 0x30,
+0x4B, 0xC2, 0x7C, 0x00, 0xBF, 0x04, 0xCC, 0x82, 0x30, 0x2F, 0xC1, 0x7C, 0x00,
+0xF3, 0x01, 0xFC, 0x43, 0x30, 0x4F, 0x50, 0x28, 0x00, 0xF3, 0x01, 0xFE, 0x07,
+0xB0, 0x1F, 0xC0, 0x7C, 0x00, 0xF9, 0x01, 0xFC, 0x03, 0xF0, 0x1F, 0xC0, 0x0F,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x77, 0x00, 0xDD, 0x01,
+0xF4, 0x63, 0x10, 0x81, 0x46, 0xE4, 0x0A, 0xDD, 0x41, 0xF4, 0x0B, 0x50, 0x91,
+0x42, 0x74, 0x00, 0x9C, 0x22, 0x44, 0x08, 0x10, 0x2F, 0xC4, 0x34, 0x08, 0xD5,
+0x21, 0xF4, 0x0F, 0x41, 0x9F, 0x40, 0xC4, 0x02, 0xD1, 0x01, 0x74, 0x07, 0x10,
+0x15, 0x40, 0x74, 0x00, 0xD9, 0x01, 0x74, 0x07, 0xD0, 0x1D, 0x40, 0x0F, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x28, 0xCD, 0x80, 0x34,
+0x13, 0x00, 0x08, 0x48, 0x40, 0x20, 0xCD, 0x80, 0x30, 0x03, 0x12, 0x10, 0x40,
+0x30, 0x10, 0x0D, 0x1C, 0x04, 0x76, 0x10, 0x4C, 0x40, 0x33, 0x05, 0xC1, 0x40,
+0x34, 0x83, 0x80, 0x0C, 0x40, 0x20, 0x08, 0xC1, 0x80, 0x34, 0x03, 0x90, 0x0D,
+0x40, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x4F, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xDD, 0x00, 0x74, 0x03,
+0x11, 0x11, 0x40, 0x64, 0x00, 0xDD, 0x40, 0x64, 0x03, 0x10, 0x11, 0x40, 0x34,
+0x20, 0x09, 0x03, 0x04, 0x06, 0x10, 0x0D, 0x44, 0x35, 0x00, 0xD1, 0x00, 0x74,
+0x03, 0x90, 0x0D, 0x40, 0x64, 0x04, 0xD1, 0x00, 0x74, 0x03, 0x50, 0x19, 0x40,
+0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0x00, 0x0F, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x00, 0xDF, 0x00, 0x74, 0x03, 0x30,
+0x31, 0xC0, 0x44, 0x00, 0xDF, 0x40, 0x7C, 0x03, 0x32, 0x19, 0xC0, 0x34, 0x08,
+0x9F, 0x01, 0x4C, 0x04, 0x30, 0x0D, 0xC6, 0x37, 0x00, 0xD1, 0x80, 0x7C, 0x83,
+0xA0, 0x0D, 0xC0, 0x64, 0x00, 0xD3, 0x00, 0x74, 0x03, 0xB0, 0x3D, 0xC1, 0x36,
+0x00, 0xDF, 0x00, 0x7C, 0x03, 0xD0, 0x0D, 0xC0, 0x83, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xFF, 0x00, 0x7C, 0x03, 0xF0, 0x02,
+0xC0, 0x07, 0x00, 0xFF, 0x40, 0xFC, 0x03, 0xF0, 0x00, 0x40, 0x3F, 0x00, 0x9F,
+0x20, 0x7C, 0x80, 0xF1, 0x0F, 0xC0, 0x3E, 0x00, 0xFD, 0x00, 0xFC, 0x03, 0x72,
+0x0F, 0x40, 0x0B, 0x00, 0xFD, 0x00, 0xFC, 0x03, 0xB0, 0x0F, 0x40, 0x3D, 0x00,
+0xFB, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xDF, 0x00, 0x3C, 0x03, 0x30, 0xA9, 0xC0,
+0x04, 0x00, 0xD3, 0x60, 0x2C, 0x63, 0x30, 0x09, 0xC0, 0x34, 0x00, 0x9B, 0x20,
+0x4C, 0x00, 0x30, 0x8C, 0xC0, 0x34, 0x00, 0xD2, 0x00, 0x3C, 0x03, 0x30, 0x0C,
+0xC0, 0x27, 0x00, 0xD7, 0x00, 0x7C, 0x23, 0xF1, 0x2D, 0xC0, 0x37, 0x10, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0xF4, 0x03, 0x10, 0x31, 0x40, 0x24,
+0x00, 0xD1, 0x00, 0xF4, 0x0B, 0x10, 0x09, 0x44, 0x34, 0x00, 0x9D, 0x00, 0x44,
+0x02, 0x12, 0xAF, 0x40, 0x74, 0x20, 0xD1, 0x00, 0xF4, 0x03, 0x10, 0x0F, 0x40,
+0x27, 0x00, 0xD1, 0x80, 0x34, 0x0F, 0xD0, 0x0C, 0x40, 0x37, 0x00, 0xDD, 0x00,
+0xF4, 0x03, 0xD0, 0x0D, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x07, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x14, 0x08, 0x41, 0x20, 0x00,
+0xC1, 0x00, 0x34, 0x0B, 0x10, 0x08, 0x40, 0x30, 0x00, 0x0D, 0x00, 0x04, 0x02,
+0x10, 0x2C, 0x40, 0x34, 0x02, 0xC1, 0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x03,
+0x00, 0xC5, 0x20, 0x34, 0x4F, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x34,
+0x03, 0xD0, 0x0C, 0x40, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x80, 0x78, 0x00, 0xED, 0x01, 0xB4, 0x27, 0x10, 0x1E, 0x40, 0x78, 0x00, 0xE1,
+0x01, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x78, 0x00, 0xED, 0x01, 0x84, 0x05, 0x10,
+0x1E, 0x40, 0xF8, 0x00, 0xE1, 0x01, 0xF4, 0x07, 0x10, 0x1E, 0x40, 0x5B, 0x00,
+0xE1, 0x01, 0xB0, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x07,
+0xD0, 0x1E, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10,
+0x30, 0x00, 0xCF, 0x00, 0x3C, 0x03, 0x30, 0x2D, 0xC0, 0x10, 0x08, 0xC3, 0x08,
+0x7C, 0x03, 0x30, 0x44, 0xC0, 0x30, 0x02, 0x4F, 0x00, 0x0C, 0x03, 0x30, 0x8D,
+0xE0, 0x34, 0x00, 0xC3, 0x08, 0x7C, 0x23, 0x30, 0x0C, 0xC0, 0x13, 0x00, 0xC7,
+0x00, 0x3C, 0x03, 0xF1, 0x0C, 0xC0, 0x33, 0x00, 0xCF, 0x00, 0x3C, 0x03, 0xF0,
+0x0C, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x35,
+0x10, 0xDF, 0x00, 0x7C, 0x0B, 0xC0, 0x0D, 0x40, 0x37, 0x00, 0xDF, 0x00, 0x74,
+0x03, 0xF0, 0x05, 0xC0, 0x37, 0x20, 0xDE, 0x00, 0x7C, 0x03, 0xF0, 0x2D, 0xC0,
+0x37, 0x00, 0xDF, 0x08, 0x7C, 0x83, 0xB4, 0x0D, 0xC1, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00,
+0xDF, 0x00, 0x7C, 0xB3, 0x30, 0x15, 0xC0, 0x34, 0x00, 0xDF, 0x00, 0x7C, 0x4B,
+0xF0, 0x0D, 0xC8, 0x37, 0x28, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0xAD, 0xC0, 0x37,
+0x00, 0xDF, 0x00, 0x7C, 0x53, 0xF0, 0x1D, 0xC4, 0x34, 0x10, 0xD3, 0x00, 0x7C,
+0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xED,
+0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x38, 0x00, 0xED, 0x00, 0xB4, 0x13, 0xD0,
+0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x01, 0xD3, 0x4E, 0x40, 0x3B, 0x00,
+0xED, 0x00, 0xB4, 0x1B, 0xD0, 0x4E, 0x41, 0x18, 0x08, 0xE1, 0x80, 0xB4, 0x03,
+0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x0B, 0xD0, 0x0E, 0x40, 0x4F,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x00, 0xED, 0x01,
+0xB0, 0x17, 0x10, 0x1C, 0x51, 0x58, 0x00, 0xED, 0x01, 0xB4, 0x27, 0xD0, 0x1E,
+0x40, 0x7B, 0x00, 0x6D, 0x21, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED,
+0x01, 0xB4, 0x07, 0xD0, 0x1C, 0x40, 0x70, 0x40, 0xE1, 0x01, 0xB4, 0x07, 0xD0,
+0x1E, 0x41, 0x7B, 0x80, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x13, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x74,
+0x83, 0x10, 0x3C, 0x45, 0xF0, 0x02, 0xCD, 0x00, 0x34, 0x03, 0xD8, 0xBC, 0x40,
+0x33, 0x00, 0xDD, 0x01, 0x34, 0x2B, 0xD1, 0x0D, 0x40, 0x33, 0x00, 0xCD, 0x00,
+0x34, 0x03, 0xD0, 0x0C, 0x40, 0x70, 0x00, 0xD1, 0x80, 0x34, 0x03, 0xD0, 0x7C,
+0x40, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x60, 0x5B, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00, 0x5F, 0xC0, 0x7C, 0x01,
+0x30, 0x17, 0xC0, 0xDC, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x17, 0xC0, 0x17,
+0x00, 0x7F, 0x05, 0xFC, 0x25, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x7C,
+0x01, 0xF0, 0x05, 0xC0, 0x58, 0x01, 0x53, 0x00, 0x7C, 0x01, 0xF0, 0x37, 0xC0,
+0x17, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x5F, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF4,
+0x01, 0xC0, 0x07, 0x04, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC1, 0x06, 0x10,
+0x1F, 0x41, 0x7C, 0x00, 0xE0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00,
+0xF0, 0x01, 0xD0, 0xC7, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x59,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x26, 0xF0, 0x09, 0xC4, 0x27, 0x00, 0x9F,
+0x00, 0x4C, 0x02, 0xF0, 0x99, 0xC0, 0x64, 0x00, 0x9F, 0x40, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x67, 0x00, 0x97, 0x00, 0x4C, 0x02, 0x70, 0x09, 0xC0, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x19, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x76, 0x82, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00,
+0x44, 0x02, 0xD0, 0x69, 0xC0, 0xA4, 0x01, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09,
+0x40, 0xA7, 0x12, 0x91, 0x40, 0x0C, 0x9A, 0x11, 0x09, 0x40, 0x27, 0x00, 0x9D,
+0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x27,
+0x00, 0x9D, 0x40, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x20, 0x44,
+0x82, 0xD0, 0x09, 0x40, 0x24, 0x0A, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40,
+0xA7, 0x00, 0x95, 0x00, 0x44, 0x02, 0x50, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00,
+0x74, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x20, 0x00, 0x8D, 0x00, 0x34, 0x12, 0x10, 0x58, 0x40, 0x23, 0x01,
+0x8D, 0x40, 0x34, 0x16, 0xD0, 0x48, 0x40, 0x23, 0x00, 0x8D, 0x44, 0x04, 0x12,
+0xD0, 0x48, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x34, 0x12, 0xD8, 0x48, 0x40, 0x23,
+0x01, 0x91, 0x00, 0x04, 0x02, 0x10, 0x08, 0x40, 0x23, 0x00, 0x8D, 0x00, 0x34,
+0x12, 0xD0, 0x08, 0x40, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB0, 0x06, 0x00, 0x1F, 0x00, 0x3C, 0x28, 0x30, 0xA1, 0xC0, 0x07, 0x00, 0x1F,
+0x00, 0x74, 0x28, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x0A, 0x4D, 0x28, 0xF1,
+0xA1, 0x40, 0x84, 0x02, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00,
+0x17, 0x00, 0x4D, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00,
+0xF0, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x22, 0xF4, 0x8B, 0xC0, 0x2F, 0x0A, 0x9F, 0x00,
+0x7C, 0x22, 0xF0, 0x8B, 0xC0, 0x27, 0x00, 0xFF, 0x08, 0xFC, 0x22, 0xF0, 0x89,
+0xD0, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x22, 0xF0, 0x89, 0xC0, 0x2F, 0x02, 0x9F,
+0x00, 0x5C, 0x02, 0xF0, 0x0B, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x22, 0xF0,
+0x09, 0xC0, 0x77, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x27,
+0x00, 0x9F, 0x00, 0x7C, 0x1E, 0xF0, 0xDB, 0xC0, 0x67, 0x01, 0x9F, 0x00, 0xFC,
+0x36, 0x34, 0x59, 0xC0, 0x27, 0x00, 0x9F, 0x07, 0x4C, 0x1E, 0xF1, 0x7B, 0xD0,
+0xAC, 0x00, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x59, 0xC0, 0x6F, 0x01, 0x9B, 0x00,
+0xFC, 0x02, 0xF0, 0x08, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00,
+0x1D, 0x00, 0x74, 0x3C, 0xD0, 0xF5, 0x42, 0x87, 0x02, 0x1D, 0x00, 0x74, 0x3C,
+0x10, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x05, 0x44, 0x1D, 0xD0, 0x71, 0x40, 0x44,
+0x01, 0x1D, 0x00, 0x74, 0x08, 0xD0, 0x21, 0x40, 0x97, 0x02, 0x11, 0x00, 0x74,
+0x00, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x00, 0x74, 0x20, 0xD0, 0x01, 0x40,
+0x63, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D,
+0x00, 0x34, 0x12, 0xD0, 0x08, 0x40, 0x23, 0x00, 0x8D, 0x00, 0x34, 0x02, 0x10,
+0x28, 0x40, 0x23, 0x00, 0x8D, 0x06, 0x04, 0x0A, 0xD0, 0x28, 0x40, 0x20, 0x00,
+0x8D, 0x00, 0x34, 0x0A, 0xD0, 0x88, 0x40, 0x23, 0x00, 0x89, 0x00, 0x34, 0x02,
+0xD0, 0x08, 0x40, 0x23, 0x00, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x4B,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x00,
+0x74, 0x02, 0xD0, 0x49, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x69,
+0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x02, 0xD0, 0x0D, 0x40, 0x24, 0x00, 0x9D,
+0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x91, 0x80, 0x74, 0x82, 0xD0,
+0x89, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x63, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0xA7, 0x16, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x39, 0xC0,
+0x27, 0x00, 0x9F, 0x08, 0x4C, 0x06, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC4, 0x23, 0x00, 0x9B, 0x00, 0x7C, 0x02, 0xF0, 0x19,
+0x41, 0x27, 0x20, 0x9D, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x17, 0x80, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x3C, 0x02, 0xF0, 0x19, 0xC0, 0x27,
+0x00, 0x8F, 0x00, 0x7D, 0x16, 0xF1, 0x08, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xCA, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x19, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x74, 0x02, 0xF0, 0x09, 0x80, 0x5B, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0,
+0x21, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC4, 0x07, 0x00,
+0x1F, 0x02, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x80, 0x1F, 0x00, 0x7C, 0x00,
+0xF0, 0x01, 0xC0, 0x87, 0x04, 0x17, 0x00, 0x7C, 0x40, 0xF2, 0x21, 0xC0, 0x04,
+0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0xA0, 0x14, 0x00, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x27,
+0x40, 0x17, 0x00, 0x5D, 0x00, 0xF4, 0x19, 0xD0, 0x05, 0x40, 0x17, 0x00, 0x5D,
+0x00, 0x74, 0x01, 0xD0, 0xC7, 0x40, 0x9F, 0x83, 0x5D, 0x00, 0x74, 0x01, 0xD0,
+0x05, 0x40, 0x5F, 0x01, 0x51, 0x00, 0xF4, 0x01, 0x70, 0x05, 0x40, 0x14, 0x00,
+0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x2C, 0x41,
+0x33, 0x00, 0xCD, 0x00, 0x34, 0x47, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x00,
+0x34, 0x03, 0xD0, 0x2C, 0x40, 0xF3, 0x00, 0xCD, 0x40, 0x34, 0x03, 0xD0, 0x0C,
+0x40, 0x53, 0x08, 0xC5, 0x00, 0x34, 0x00, 0xD0, 0x0C, 0x40, 0x30, 0x00, 0xCD,
+0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0x80, 0x38, 0x00, 0xED, 0x00, 0xB4, 0x13, 0xD0, 0x0E, 0x41, 0x3B,
+0x00, 0xED, 0x00, 0xB4, 0x01, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x04, 0xB4,
+0x13, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40,
+0x1B, 0x00, 0xE1, 0x40, 0xB4, 0x09, 0x50, 0x0F, 0x40, 0x38, 0x00, 0xED, 0x00,
+0xB4, 0x03, 0xD0, 0x0E, 0x42, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x10, 0x78, 0x00, 0xEF, 0x01, 0xBC, 0x17, 0xF0, 0x1E, 0xC0, 0x7B, 0x08,
+0xEF, 0x01, 0xBC, 0x07, 0xF0, 0x1E, 0xC2, 0x7B, 0x00, 0xEF, 0x0D, 0xBC, 0x37,
+0xF0, 0x16, 0xC0, 0x7B, 0x00, 0xED, 0x41, 0xBC, 0x07, 0xF0, 0x1E, 0xC0, 0x5B,
+0x00, 0xE7, 0x01, 0xBC, 0x04, 0xF0, 0x0E, 0xC4, 0x78, 0x00, 0xED, 0x01, 0xBC,
+0x07, 0xF0, 0x1E, 0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xB8, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x53, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x08, 0x7C, 0x03, 0xF0,
+0x05, 0xC4, 0x17, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC8, 0x13, 0x10,
+0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC8, 0x37, 0x08, 0xDF, 0x00, 0x7C, 0x03,
+0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0,
+0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x63, 0xF0, 0x17, 0xC0, 0x7F, 0x00, 0xFF, 0x09,
+0xFC, 0x27, 0xF3, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0x81, 0xF8, 0x47, 0x30, 0x1F,
+0x48, 0x5F, 0x02, 0xFE, 0x21, 0xFC, 0x07, 0xD0, 0x9F, 0x80, 0x5D, 0x00, 0xF3,
+0x09, 0xFC, 0x27, 0xF0, 0x1F, 0xC0, 0x7F, 0x02, 0xFF, 0x09, 0xFC, 0x07, 0xF0,
+0x1F, 0xC0, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x39,
+0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x86, 0x41, 0x3B, 0x00, 0xED, 0x00, 0xB4,
+0x01, 0xC0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x08, 0xB4, 0x03, 0x14, 0x8E, 0x40,
+0x1A, 0x00, 0xE9, 0x00, 0xB4, 0x03, 0xD0, 0x0F, 0x42, 0x1C, 0x05, 0xE5, 0x08,
+0xB4, 0x09, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x8E,
+0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00,
+0xED, 0x00, 0xB4, 0x23, 0x58, 0x06, 0x40, 0x3B, 0x06, 0xED, 0x80, 0xB0, 0x03,
+0xD1, 0x8E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x3B,
+0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0F, 0x44, 0x3D, 0x00, 0xE5, 0x40, 0xB4,
+0x81, 0xD0, 0x0E, 0x40, 0x3B, 0x20, 0xED, 0x40, 0xB4, 0x23, 0xD0, 0x0E, 0x40,
+0x23, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x33, 0x00, 0xCD,
+0x00, 0x34, 0x03, 0xD0, 0x00, 0x40, 0xB3, 0x00, 0xCD, 0x00, 0x74, 0x00, 0x90,
+0x1C, 0x40, 0x37, 0x10, 0xCD, 0x02, 0x74, 0x27, 0x10, 0x08, 0x08, 0x02, 0x00,
+0xC9, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x70, 0x00, 0xC5, 0x40, 0x34, 0x01,
+0xD1, 0x0C, 0x40, 0x33, 0x00, 0xCC, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x40, 0x0B,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00, 0xDF, 0x00,
+0xFC, 0x03, 0x70, 0x19, 0xC0, 0x77, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x2D,
+0xC3, 0x37, 0x00, 0xFF, 0x44, 0xFC, 0x03, 0x31, 0x09, 0x80, 0x27, 0x10, 0xDE,
+0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x45, 0x00, 0xD7, 0x40, 0x78, 0x01, 0xD0,
+0x0D, 0xC1, 0x37, 0x10, 0xDD, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x57, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x20, 0xDF, 0x00, 0x7C,
+0x03, 0xF0, 0x49, 0xC4, 0x37, 0x04, 0xDF, 0x20, 0x7C, 0x0A, 0xF0, 0x0D, 0xC8,
+0x37, 0x10, 0xDF, 0x10, 0x7C, 0x43, 0xF0, 0x29, 0xC4, 0x26, 0x20, 0xDB, 0x80,
+0x7C, 0x03, 0xF2, 0x0D, 0xC0, 0x87, 0x04, 0xDE, 0x00, 0x7C, 0x09, 0xF1, 0x4D,
+0xC0, 0x37, 0x10, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03,
+0xF0, 0x03, 0xC0, 0x3B, 0x00, 0xF3, 0x00, 0xFC, 0x00, 0x30, 0x0F, 0xC1, 0x3F,
+0x08, 0xF3, 0x00, 0x7C, 0x03, 0x30, 0x03, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xBC,
+0x03, 0x34, 0x0F, 0xC0, 0x5F, 0x02, 0xFF, 0x00, 0xFC, 0x05, 0xD0, 0x0F, 0xC4,
+0x3D, 0x00, 0xFF, 0x00, 0xBC, 0x03, 0x30, 0x0F, 0xC4, 0x07, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0xD0,
+0x79, 0x48, 0x37, 0x30, 0xD1, 0x00, 0x74, 0x1C, 0x10, 0x0D, 0x40, 0x37, 0x00,
+0xD1, 0x00, 0x74, 0x03, 0x10, 0x31, 0x40, 0x67, 0x04, 0xDD, 0x00, 0x74, 0x03,
+0x10, 0x0D, 0x40, 0x17, 0x01, 0xDD, 0x40, 0x74, 0x8D, 0xD0, 0x0C, 0x48, 0x34,
+0x00, 0xDD, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x48, 0x87, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x74, 0x03, 0xD0, 0x19,
+0x40, 0x37, 0x00, 0xD1, 0x00, 0x74, 0x06, 0x10, 0x0D, 0x40, 0x37, 0x40, 0xD1,
+0x00, 0x74, 0x03, 0x10, 0x11, 0x48, 0x47, 0x20, 0xDD, 0x00, 0x74, 0x03, 0x90,
+0x0D, 0x40, 0x17, 0x00, 0xDC, 0x00, 0x74, 0x11, 0xD0, 0x0D, 0x42, 0x35, 0x00,
+0xDD, 0x40, 0x74, 0x03, 0x10, 0x0D, 0x40, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD2, 0x08, 0x40,
+0x33, 0x00, 0xC1, 0x80, 0x34, 0x02, 0x15, 0x0C, 0x40, 0x37, 0x20, 0xC1, 0xC0,
+0x34, 0x03, 0x14, 0x08, 0x44, 0x03, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x90, 0x0C,
+0x40, 0x13, 0x00, 0xCD, 0x00, 0x34, 0x01, 0xD0, 0x0D, 0x44, 0x30, 0x00, 0xCD,
+0x00, 0x34, 0x03, 0x10, 0x0C, 0x48, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xB0, 0x36, 0x00, 0xDF, 0x00, 0xFC, 0x03, 0xF0, 0x01, 0xC4, 0x37,
+0x40, 0xD3, 0x00, 0x7C, 0x02, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0xF3, 0x00, 0xFC,
+0x03, 0x30, 0x01, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0xC0,
+0x17, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF8, 0x0D, 0xC0, 0x35, 0x80, 0xDF, 0x00,
+0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x07, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xB8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0x40, 0x3F, 0x20,
+0xFF, 0xC0, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x83,
+0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xF8, 0x03, 0x70, 0x0F, 0xC0, 0x1F,
+0x00, 0xFF, 0x00, 0xFC, 0x01, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x20, 0xFC,
+0x03, 0xF2, 0x0F, 0xC0, 0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA0, 0x7F, 0x00, 0xB3, 0x02, 0xCD, 0x27, 0x30, 0x0B, 0xC0, 0x0C, 0x05, 0x3F,
+0x04, 0xFC, 0x07, 0x30, 0x47, 0xC8, 0x3F, 0x05, 0xFF, 0x04, 0xBC, 0xD3, 0x30,
+0x9B, 0xC0, 0x2C, 0x01, 0x23, 0x89, 0xCC, 0x12, 0xF0, 0x03, 0xC8, 0x2C, 0x02,
+0x33, 0x04, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x7C, 0x18, 0xB3, 0x00, 0xCC, 0x04,
+0xF0, 0x1F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+0x37, 0x11, 0x91, 0x02, 0x44, 0x03, 0x10, 0x1B, 0x50, 0x84, 0x10, 0x1D, 0x0B,
+0x74, 0x07, 0x14, 0xBD, 0x40, 0xF7, 0x00, 0xFD, 0x49, 0xF4, 0x0F, 0x12, 0x48,
+0x50, 0xFC, 0x40, 0x11, 0x84, 0x44, 0x4A, 0xD0, 0x31, 0x44, 0xAC, 0x23, 0x13,
+0x0A, 0x74, 0x03, 0xD1, 0x04, 0x40, 0x34, 0x00, 0xD1, 0x03, 0x45, 0x05, 0xD0,
+0x1D, 0x40, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33,
+0x04, 0x91, 0x8C, 0x34, 0x13, 0x14, 0x08, 0x40, 0x20, 0x00, 0x0D, 0x00, 0x34,
+0x03, 0x10, 0x0C, 0x40, 0x23, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x10, 0x08, 0x40,
+0xA0, 0x00, 0x05, 0x00, 0x04, 0x0A, 0xD2, 0x21, 0x40, 0x20, 0x41, 0x81, 0x00,
+0x34, 0x03, 0xD8, 0x08, 0x60, 0x32, 0x10, 0xC1, 0x82, 0x04, 0x00, 0xD0, 0x0C,
+0x40, 0x47, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x40,
+0x91, 0x01, 0x64, 0x03, 0x10, 0x89, 0x40, 0x64, 0x00, 0x1C, 0x11, 0x74, 0x03,
+0x10, 0x1D, 0x40, 0x37, 0x00, 0xDD, 0x00, 0x74, 0x03, 0x14, 0x09, 0x40, 0x34,
+0x00, 0x15, 0x01, 0x45, 0x42, 0xD0, 0x49, 0x40, 0x20, 0xC2, 0x91, 0x03, 0x74,
+0x03, 0xD0, 0x0D, 0x50, 0x36, 0x40, 0xD1, 0x01, 0x46, 0x07, 0xD0, 0x0D, 0x40,
+0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x37, 0x00, 0x83,
+0x01, 0x6C, 0x03, 0x30, 0x08, 0xC0, 0x44, 0x20, 0x1E, 0x01, 0x7C, 0x03, 0x30,
+0x3D, 0xC0, 0x37, 0x00, 0xDF, 0xC0, 0x7C, 0x03, 0x30, 0x99, 0xC0, 0x24, 0x02,
+0x17, 0x81, 0x4C, 0x02, 0xF1, 0x00, 0xD0, 0x24, 0x00, 0x13, 0x01, 0x7C, 0x03,
+0xF0, 0x0D, 0xE0, 0x36, 0x00, 0x93, 0x01, 0x4C, 0x04, 0xF2, 0x0D, 0xC2, 0x0B,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xBF, 0x00,
+0xDC, 0x03, 0xF0, 0x19, 0xC0, 0x0F, 0x10, 0x3F, 0x00, 0xF4, 0x03, 0xF1, 0x0D,
+0xC0, 0x7F, 0x12, 0xFF, 0x10, 0xBC, 0x03, 0xC0, 0x0B, 0xC0, 0x7F, 0x20, 0x3B,
+0x00, 0xF8, 0x26, 0xE1, 0x03, 0xC0, 0x27, 0x00, 0x14, 0x00, 0xFC, 0x03, 0xF0,
+0x5F, 0xC0, 0xBD, 0x00, 0xEF, 0x00, 0xFC, 0x81, 0xF1, 0x0F, 0xC0, 0x1F, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0x93, 0x04, 0x4C,
+0x13, 0xF0, 0x09, 0xC4, 0x24, 0x00, 0x13, 0x02, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x24, 0x00, 0xDF, 0x40, 0x4C, 0x03, 0xB0, 0x09, 0xC8, 0x20, 0x40, 0x13, 0x02,
+0x6C, 0x0E, 0xB0, 0x03, 0xC0, 0x37, 0x00, 0x93, 0x06, 0x6C, 0x03, 0xD0, 0x08,
+0xC0, 0x34, 0x80, 0x5F, 0x00, 0x7C, 0x00, 0x30, 0x0D, 0xC0, 0x0B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x30, 0x00, 0x91, 0x00, 0x44, 0x0B,
+0xD0, 0x09, 0x50, 0x64, 0x08, 0x91, 0x00, 0x34, 0x2B, 0xD0, 0x0D, 0x40, 0xB4,
+0x02, 0xFD, 0x06, 0xC5, 0x6F, 0x10, 0x49, 0x54, 0xB4, 0x03, 0x10, 0x24, 0x44,
+0x06, 0x10, 0xB9, 0x45, 0x37, 0x00, 0x91, 0x83, 0x44, 0x03, 0xD1, 0xAD, 0x40,
+0xB4, 0x02, 0xDD, 0x00, 0x74, 0x47, 0x10, 0x1D, 0x43, 0x4F, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x72, 0x00, 0xC1, 0x02, 0x44, 0x8B, 0xD0,
+0x68, 0x40, 0x60, 0x00, 0x05, 0x00, 0x34, 0x03, 0xD0, 0x08, 0x40, 0x12, 0x20,
+0xCD, 0x02, 0x04, 0x03, 0x90, 0x09, 0x48, 0xF0, 0x10, 0x11, 0x20, 0x04, 0x4A,
+0x92, 0x10, 0x40, 0x23, 0x20, 0x09, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x36,
+0x10, 0xC5, 0x08, 0x34, 0x04, 0x10, 0x0C, 0x40, 0x1F, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x40, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x9E,
+0x40, 0x68, 0x04, 0x25, 0x01, 0xB4, 0x07, 0xD1, 0x1A, 0x50, 0x58, 0x00, 0xCD,
+0x89, 0x84, 0x07, 0x10, 0x9A, 0x40, 0x78, 0x00, 0x31, 0x29, 0x85, 0x04, 0x10,
+0x12, 0x40, 0x6B, 0x08, 0xA9, 0x01, 0x84, 0x07, 0xD0, 0x16, 0x50, 0x7A, 0x80,
+0xED, 0x41, 0xB4, 0x05, 0x10, 0x1E, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x10, 0x30, 0x04, 0x53, 0x00, 0x0E, 0x03, 0xF0, 0x08, 0xD0,
+0xA4, 0x40, 0x07, 0x08, 0x3C, 0x03, 0xF0, 0x0C, 0xC0, 0x30, 0x02, 0xCF, 0x00,
+0x0C, 0x03, 0xB0, 0x08, 0xC0, 0x30, 0x00, 0x03, 0x4A, 0x6C, 0x02, 0xB0, 0x00,
+0xC0, 0x33, 0x41, 0xCB, 0x10, 0x2C, 0x23, 0xF0, 0x0C, 0xD0, 0x32, 0x02, 0xCF,
+0x00, 0x3C, 0x00, 0x34, 0x0C, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xB8, 0x39, 0x00, 0xFF, 0x00, 0xFD, 0x03, 0xF0, 0x0B, 0xC0, 0x2F,
+0x10, 0x7B, 0x00, 0xFC, 0x03, 0xF8, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC,
+0x03, 0xF0, 0x0B, 0xC4, 0x3B, 0x00, 0x3F, 0x28, 0xFC, 0x00, 0xF0, 0x0F, 0xC0,
+0x3F, 0x00, 0xF7, 0x00, 0xFC, 0x83, 0xF0, 0x0F, 0xD0, 0x3D, 0x00, 0xFF, 0x08,
+0xBC, 0x03, 0xF0, 0x0F, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x49, 0xD0, 0x2C, 0x00,
+0x33, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC8, 0x37, 0x00, 0xDF, 0x04, 0x5C, 0x4F,
+0x30, 0x09, 0xC0, 0xB5, 0x00, 0x13, 0x00, 0x6C, 0x02, 0xF2, 0x01, 0xC0, 0xA7,
+0x01, 0xD3, 0x00, 0x5C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C,
+0x00, 0xF0, 0x0D, 0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x88, 0x39, 0x00, 0xAD, 0x40, 0xB4, 0x03, 0xD0, 0x8C, 0x44, 0x28, 0x00, 0x2B,
+0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xCD, 0x0E, 0x04, 0x03, 0x10,
+0x0E, 0x40, 0x30, 0x02, 0x61, 0x00, 0x86, 0x00, 0xD0, 0x02, 0x44, 0x23, 0x04,
+0xF1, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x10, 0xED, 0x00, 0xB4, 0x01,
+0xD0, 0x0E, 0x40, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+0x79, 0x00, 0xAD, 0x01, 0xB4, 0x07, 0xD0, 0x1A, 0x40, 0x60, 0x00, 0xA1, 0x41,
+0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x05, 0x94, 0x37, 0x10, 0x3B,
+0x40, 0x79, 0x08, 0x29, 0x11, 0x84, 0x06, 0xD0, 0x12, 0x40, 0xFB, 0x00, 0xE1,
+0x81, 0x94, 0x87, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0xED, 0x01, 0xB4, 0x05, 0xD0,
+0x1E, 0x40, 0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33,
+0x10, 0x8D, 0x09, 0x34, 0x03, 0xD0, 0x9C, 0x50, 0x70, 0x00, 0xC9, 0x06, 0x34,
+0x03, 0xD0, 0x3C, 0x40, 0xB3, 0x04, 0xCD, 0x00, 0x04, 0x03, 0x14, 0x1C, 0x40,
+0x30, 0xC0, 0x99, 0x06, 0x05, 0x01, 0xD1, 0x0C, 0x44, 0x73, 0x20, 0xC1, 0x03,
+0x04, 0x03, 0xD1, 0x0D, 0x41, 0x63, 0x00, 0xCD, 0x06, 0x34, 0x07, 0xD0, 0x0C,
+0x40, 0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00,
+0x7F, 0x02, 0x7C, 0x01, 0xF0, 0x04, 0xC0, 0x58, 0x01, 0x73, 0x02, 0x7C, 0x01,
+0xF0, 0x16, 0xC0, 0x9F, 0x10, 0x5F, 0x00, 0x5C, 0x01, 0x30, 0x04, 0xC4, 0x15,
+0x00, 0x7B, 0x00, 0xCC, 0x45, 0xF1, 0x07, 0xC0, 0x17, 0x48, 0x73, 0x05, 0x5C,
+0x01, 0xF0, 0x27, 0xC0, 0x57, 0x00, 0x7F, 0x02, 0xFC, 0x05, 0xF0, 0x05, 0xC0,
+0x5F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F,
+0x00, 0x7C, 0x00, 0xF0, 0x01, 0xD0, 0x07, 0x10, 0x1F, 0x00, 0x7C, 0x00, 0xF0,
+0x81, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x07, 0x00,
+0x17, 0x00, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x10, 0x7C, 0x00,
+0xF0, 0x01, 0xC0, 0x07, 0x12, 0x1F, 0x00, 0x7C, 0x20, 0xF0, 0x01, 0xC0, 0x4B,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x93, 0x11,
+0x4C, 0x22, 0xF0, 0x09, 0xC0, 0x64, 0x00, 0x93, 0x02, 0x7C, 0x02, 0xF0, 0x09,
+0xC1, 0x20, 0x00, 0x83, 0x00, 0x6D, 0x0E, 0xF0, 0x59, 0xC0, 0x20, 0x00, 0x91,
+0x40, 0x4C, 0x02, 0x10, 0x89, 0xC0, 0x24, 0x00, 0x83, 0x08, 0x4C, 0x02, 0xF0,
+0x19, 0xC0, 0x64, 0x01, 0x90, 0x00, 0x7C, 0x02, 0x30, 0x19, 0xC0, 0x43, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xA6, 0x02, 0x91, 0x01, 0x44,
+0x06, 0xD0, 0x39, 0x41, 0x64, 0x10, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x50,
+0x24, 0x40, 0x91, 0x40, 0x44, 0x02, 0xD0, 0x19, 0x44, 0xE4, 0x40, 0x91, 0x01,
+0x04, 0x02, 0x15, 0x08, 0x40, 0x20, 0x00, 0x9B, 0x03, 0x44, 0x02, 0xD0, 0x19,
+0x40, 0x20, 0x20, 0x91, 0x09, 0x34, 0x02, 0x10, 0x19, 0x40, 0x07, 0x00, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x20, 0x44, 0xC1, 0x04, 0x45, 0x02,
+0xD0, 0x49, 0x40, 0x24, 0x01, 0x91, 0x00, 0x74, 0x02, 0xD0, 0x0D, 0x50, 0x34,
+0x10, 0x99, 0x00, 0x65, 0x02, 0xC0, 0x09, 0x40, 0x24, 0x01, 0x95, 0x04, 0x44,
+0x12, 0x51, 0x29, 0x50, 0x24, 0x20, 0x91, 0x00, 0x44, 0x02, 0xD0, 0x49, 0x50,
+0x24, 0x40, 0xDD, 0x80, 0x74, 0x12, 0x10, 0x89, 0x40, 0x63, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x81, 0x04, 0x04, 0x02, 0xD0,
+0x48, 0x40, 0x20, 0x01, 0x81, 0x04, 0x34, 0x02, 0xD0, 0x49, 0x40, 0x20, 0x01,
+0x89, 0x04, 0x04, 0x13, 0xD0, 0x08, 0x40, 0x60, 0x81, 0x85, 0x20, 0x46, 0x12,
+0x50, 0x48, 0x40, 0x24, 0x01, 0xC9, 0x04, 0x04, 0x02, 0xD0, 0x48, 0x40, 0x24,
+0x00, 0x8D, 0x04, 0x74, 0x02, 0x14, 0x08, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB0, 0x86, 0x02, 0x13, 0x0A, 0x4C, 0x29, 0xF0, 0x01,
+0xC0, 0x84, 0x02, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1B,
+0x00, 0x6C, 0x00, 0xD2, 0xA1, 0xC0, 0x04, 0x20, 0x07, 0x2A, 0x4C, 0x28, 0x70,
+0x01, 0xD0, 0x84, 0x42, 0x13, 0x0A, 0x4D, 0x28, 0xF0, 0xA1, 0xC0, 0x84, 0x02,
+0x1F, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0xB8, 0x27, 0x00, 0xBF, 0x08, 0x7C, 0x02, 0xF0, 0x8B, 0xD0,
+0x2F, 0x42, 0xBF, 0x08, 0x7C, 0x02, 0xF0, 0x8B, 0xD0, 0x2F, 0x02, 0x97, 0x08,
+0x7C, 0x22, 0xF0, 0x0A, 0xD0, 0x2F, 0x22, 0xBB, 0x00, 0xFD, 0x22, 0xB0, 0x8B,
+0xD0, 0x2F, 0x02, 0xBF, 0x08, 0x7C, 0x02, 0xF0, 0x8B, 0xC0, 0x2F, 0x10, 0xB3,
+0x08, 0xFC, 0x02, 0xF0, 0x09, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x2F, 0x00, 0xB7, 0x0C, 0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x2C,
+0x02, 0xB3, 0x04, 0x3C, 0x02, 0xF0, 0x49, 0xC0, 0x24, 0x00, 0x9F, 0x01, 0xCC,
+0x16, 0x30, 0x0A, 0xC0, 0x6C, 0x28, 0xBF, 0x00, 0xCC, 0x1E, 0x30, 0x5B, 0xC0,
+0x6F, 0x41, 0xB3, 0x05, 0xCC, 0x02, 0xF0, 0xCB, 0xC0, 0x2C, 0x00, 0xB3, 0x00,
+0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0x08, 0x07, 0x01, 0x11, 0x0C, 0x6C, 0x40, 0xD0, 0x01, 0x40, 0x04, 0x02,
+0x11, 0x00, 0x74, 0x00, 0xD0, 0x81, 0x40, 0x84, 0x10, 0x3D, 0x02, 0x45, 0x08,
+0xB0, 0x51, 0x40, 0x04, 0x00, 0x1D, 0x15, 0x45, 0x14, 0x10, 0x01, 0x40, 0xC3,
+0x15, 0x11, 0x14, 0x44, 0x10, 0xD1, 0xC1, 0x40, 0x04, 0x04, 0x11, 0x00, 0x74,
+0x00, 0xD0, 0x01, 0x40, 0x70, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA0, 0x23, 0x05, 0x85, 0x04, 0x04, 0x12, 0xD0, 0x88, 0x40, 0x70, 0x60, 0x81,
+0x08, 0xB4, 0x02, 0xD0, 0x1A, 0x50, 0x6A, 0x02, 0xAD, 0x02, 0x04, 0x22, 0x10,
+0x08, 0x61, 0xA0, 0x00, 0x8D, 0x81, 0x04, 0x1A, 0x90, 0x38, 0x40, 0x23, 0x42,
+0x81, 0x06, 0x04, 0x52, 0xD1, 0x58, 0x40, 0x20, 0x41, 0xC1, 0x08, 0x34, 0x06,
+0xD0, 0x0C, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8,
+0x21, 0x00, 0x91, 0x10, 0x64, 0x02, 0xD0, 0x89, 0x10, 0x20, 0x01, 0x91, 0x04,
+0x74, 0x02, 0xD0, 0x0B, 0x40, 0x2E, 0x01, 0xBD, 0x00, 0x44, 0x02, 0x90, 0x09,
+0x60, 0x24, 0x00, 0x9D, 0x40, 0x44, 0x02, 0x90, 0x09, 0x40, 0x27, 0x20, 0x91,
+0x04, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x30, 0x00, 0x91, 0x11, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x60, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x25,
+0x00, 0x97, 0x00, 0x4C, 0x02, 0xF0, 0x19, 0xC0, 0x24, 0x00, 0x93, 0x05, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0xA6, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x30, 0x09, 0xD0,
+0x24, 0x20, 0x9F, 0x02, 0x4C, 0x06, 0xB0, 0x29, 0xE0, 0x67, 0x02, 0x93, 0x04,
+0x4D, 0x02, 0xF0, 0x19, 0xD0, 0x64, 0x00, 0x93, 0x03, 0x7C, 0x02, 0xF2, 0x09,
+0xD0, 0x14, 0xA0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x25, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0x01, 0x7C, 0x02,
+0xF0, 0x98, 0xC0, 0x25, 0x00, 0x9F, 0x40, 0x7C, 0x02, 0xF2, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x09, 0x7C, 0x0E, 0x70, 0x89, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x39, 0xC0, 0xE7, 0x00, 0x9F, 0x40, 0x7C, 0x12, 0xF0, 0x09, 0xC0,
+0x53, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x0F,
+0x03, 0x4D, 0x04, 0xF0, 0x11, 0xC0, 0x04, 0x00, 0x13, 0x00, 0x7C, 0x00, 0x30,
+0x11, 0xC0, 0x07, 0x00, 0x13, 0x00, 0x2C, 0x00, 0xF8, 0x01, 0xC1, 0x06, 0x04,
+0x13, 0x00, 0x0C, 0x40, 0xF0, 0x01, 0xC0, 0x04, 0x02, 0x13, 0x02, 0x7C, 0x00,
+0xF0, 0x41, 0xC0, 0x44, 0x02, 0x13, 0x02, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x53,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xDC, 0x00, 0x7D, 0x01,
+0xC4, 0x15, 0x70, 0x16, 0x40, 0x9C, 0x00, 0x51, 0x01, 0x74, 0x01, 0x14, 0x05,
+0x40, 0x57, 0x00, 0x41, 0x00, 0xC4, 0x41, 0xD0, 0x07, 0x40, 0x1C, 0x20, 0x51,
+0x04, 0xC4, 0x09, 0xD1, 0x57, 0x40, 0x14, 0x10, 0x7B, 0x00, 0x74, 0x01, 0xD0,
+0x37, 0x40, 0x1C, 0x00, 0x51, 0x00, 0x45, 0x01, 0xD0, 0x04, 0x40, 0x53, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xE2, 0x04, 0xCD, 0x01, 0x04,
+0x03, 0x50, 0x1C, 0x40, 0xB1, 0x04, 0x81, 0x01, 0x34, 0x03, 0x10, 0x0C, 0x40,
+0x73, 0x00, 0xC1, 0x00, 0x24, 0x13, 0xD0, 0x2D, 0x40, 0x72, 0x00, 0xD1, 0x40,
+0x04, 0x2A, 0x58, 0x7C, 0x40, 0x34, 0x00, 0xD1, 0x00, 0x34, 0x27, 0xD0, 0x0D,
+0x40, 0x30, 0x00, 0x81, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x53, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x04, 0xFD, 0x10, 0x84, 0x03,
+0x50, 0x06, 0x41, 0x29, 0x01, 0xA1, 0x10, 0xB4, 0x05, 0x10, 0x0E, 0x40, 0x53,
+0x04, 0x01, 0x00, 0x84, 0x00, 0xD0, 0x0B, 0x40, 0x4A, 0xC4, 0xA1, 0x00, 0x84,
+0x05, 0xD0, 0x12, 0x40, 0x38, 0x00, 0xE9, 0x00, 0xB4, 0x03, 0xD0, 0x2E, 0x40,
+0x38, 0x00, 0xC1, 0x01, 0x84, 0x03, 0xD0, 0x0E, 0x40, 0x17, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x68, 0x00, 0xEF, 0x01, 0x8C, 0x07, 0x70,
+0x10, 0xC0, 0xFD, 0x40, 0xE3, 0x01, 0xBC, 0x07, 0x30, 0x1E, 0xC0, 0x7B, 0x40,
+0xE3, 0x01, 0xAC, 0x04, 0xD0, 0x1A, 0xC0, 0x42, 0x00, 0xA3, 0x01, 0x8D, 0x02,
+0x78, 0x10, 0xC0, 0x78, 0x04, 0xE3, 0x01, 0xBC, 0x07, 0xF0, 0x1F, 0xC0, 0x7C,
+0x00, 0xE1, 0x01, 0x8C, 0x07, 0xF0, 0x1A, 0xC0, 0x57, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xB8, 0x25, 0x00, 0xCF, 0x00, 0x7C, 0x03, 0x70, 0x01,
+0xD0, 0x26, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC0, 0x17, 0x00, 0x1F,
+0x00, 0x7C, 0x00, 0xF0, 0x09, 0xC0, 0x05, 0x00, 0x8F, 0x02, 0xFC, 0x00, 0xF0,
+0x01, 0xD0, 0xB7, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xD0, 0x37, 0x50,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xA0, 0x6B, 0x00, 0xF3, 0x01, 0xCC, 0x23, 0xB4, 0x13, 0xC0,
+0x6C, 0x20, 0xF3, 0x01, 0xCC, 0x07, 0xF0, 0x16, 0xC0, 0x6C, 0x00, 0xF3, 0x01,
+0xBC, 0x04, 0x30, 0x1F, 0xD0, 0x4D, 0x00, 0xF3, 0x03, 0xCC, 0x24, 0xF0, 0x13,
+0xC0, 0x7F, 0x08, 0xF3, 0x01, 0xDC, 0x06, 0x30, 0x1F, 0xC0, 0x7C, 0x10, 0xF3,
+0x81, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x80, 0xB9, 0x00, 0x71, 0x02, 0x84, 0x03, 0x10, 0x02, 0x40, 0x28,
+0x00, 0xE1, 0x00, 0xAC, 0x01, 0xC0, 0x06, 0xC0, 0x08, 0x00, 0x21, 0x00, 0x84,
+0x08, 0x00, 0x4B, 0x40, 0x08, 0x01, 0xA5, 0x04, 0x94, 0x00, 0xD0, 0x02, 0xC0,
+0x39, 0x00, 0xE5, 0x02, 0xC4, 0x02, 0x50, 0x0E, 0x40, 0x1C, 0x00, 0xE1, 0x14,
+0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x08, 0x09, 0x00, 0xE1, 0x00, 0x84, 0x22, 0x18, 0x02, 0x41, 0x38, 0x00,
+0xA1, 0x10, 0x84, 0x03, 0xD0, 0x26, 0x40, 0x20, 0x00, 0xC1, 0x00, 0x94, 0x00,
+0x10, 0x0A, 0x45, 0x09, 0x20, 0xE1, 0x80, 0x84, 0x08, 0xD8, 0x02, 0x40, 0x33,
+0x00, 0xE1, 0x00, 0x94, 0x02, 0x10, 0x0C, 0x40, 0x38, 0x00, 0xE1, 0x00, 0xB4,
+0x0B, 0xD0, 0x0E, 0x40, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+0x28, 0x13, 0x00, 0x41, 0x00, 0x44, 0x02, 0x14, 0x00, 0x40, 0x20, 0x02, 0x81,
+0x01, 0x24, 0x01, 0xD0, 0x04, 0x40, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x14,
+0x18, 0x40, 0x40, 0x0A, 0x81, 0x53, 0x14, 0x04, 0xD0, 0x30, 0x40, 0x31, 0x20,
+0xC5, 0x02, 0x04, 0x02, 0x50, 0x2C, 0x40, 0x50, 0x00, 0xC1, 0x00, 0x34, 0x23,
+0xD0, 0x0C, 0x40, 0x13, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8,
+0x21, 0x00, 0xD3, 0x02, 0x4C, 0x03, 0x34, 0x01, 0xD0, 0x1C, 0x50, 0x83, 0x03,
+0x4D, 0x02, 0xF0, 0x09, 0xC0, 0x74, 0x40, 0xD3, 0x00, 0x5C, 0x00, 0x30, 0x1D,
+0xC8, 0x45, 0xE0, 0x93, 0x05, 0x0C, 0x12, 0xF0, 0x69, 0xC0, 0x37, 0x00, 0xD3,
+0x02, 0x5C, 0x02, 0x31, 0x0D, 0xC4, 0x74, 0x24, 0xD3, 0x80, 0x7C, 0x07, 0xF0,
+0x0D, 0xC0, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA7,
+0x40, 0xDF, 0x42, 0x7C, 0x03, 0x70, 0x01, 0xC0, 0x97, 0x08, 0x9F, 0x10, 0x5C,
+0x00, 0xF0, 0x09, 0xC0, 0x51, 0x00, 0x1F, 0x00, 0x5C, 0x08, 0xF0, 0x0D, 0xC0,
+0x83, 0x00, 0x9F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x02, 0xF0, 0x75, 0xD0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x0D,
+0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x6F, 0x21,
+0xB3, 0x90, 0xCC, 0x03, 0x30, 0x00, 0xC0, 0x1C, 0x00, 0xDF, 0x00, 0xCC, 0x06,
+0xF0, 0x0B, 0xC0, 0x3C, 0x00, 0xF3, 0x00, 0x8C, 0x04, 0x30, 0x4B, 0xC8, 0x04,
+0x00, 0xBD, 0x05, 0xFC, 0x02, 0x10, 0x03, 0xC1, 0x7B, 0x00, 0x33, 0x19, 0xCC,
+0x02, 0xF0, 0x0A, 0xC0, 0x2C, 0x00, 0xF1, 0x10, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x03, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xE6, 0x40, 0x91,
+0x02, 0x44, 0x07, 0x10, 0x11, 0x40, 0x94, 0x02, 0xDD, 0x00, 0x44, 0x00, 0xD0,
+0x08, 0x40, 0x14, 0x00, 0x01, 0x00, 0x44, 0x00, 0x10, 0x49, 0x40, 0xC4, 0x00,
+0x91, 0x00, 0x64, 0x04, 0x10, 0x11, 0x40, 0x37, 0x12, 0xD5, 0x03, 0x44, 0x06,
+0xD0, 0x11, 0x50, 0xA4, 0x00, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0x40, 0x07,
+0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x26, 0x00, 0xC1, 0x01,
+0x44, 0x07, 0x92, 0x11, 0x40, 0xA4, 0x00, 0xDD, 0x00, 0x44, 0x22, 0x50, 0x11,
+0x40, 0x24, 0x00, 0xD1, 0x00, 0x44, 0x20, 0x14, 0x04, 0x40, 0x44, 0x04, 0x91,
+0x00, 0x74, 0x04, 0xD0, 0x11, 0x44, 0x27, 0x00, 0xC1, 0x00, 0x44, 0x12, 0xD0,
+0x4D, 0x51, 0x70, 0x00, 0xD5, 0x01, 0x74, 0x07, 0xD0, 0x1D, 0x48, 0x07, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xC1, 0x00, 0x04,
+0x07, 0x90, 0x10, 0x50, 0x20, 0x00, 0xCD, 0x00, 0x05, 0x00, 0xD0, 0x00, 0x40,
+0x00, 0x40, 0x01, 0x00, 0x06, 0x00, 0x50, 0x04, 0x40, 0x00, 0x00, 0x81, 0x00,
+0x64, 0x00, 0xD0, 0x00, 0x00, 0x23, 0x40, 0xC5, 0x20, 0x04, 0x02, 0xD0, 0x0C,
+0x48, 0x30, 0x00, 0xC5, 0x00, 0x34, 0x02, 0xD0, 0x0C, 0x40, 0x43, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x26, 0x00, 0xD3, 0x40, 0x4C, 0x03,
+0xB4, 0x01, 0xC0, 0x30, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x70, 0x01, 0xC0, 0x24,
+0x20, 0xD3, 0x00, 0x4D, 0x00, 0x30, 0x01, 0xC0, 0x04, 0x00, 0xAB, 0x00, 0x7C,
+0x00, 0xF4, 0x01, 0xC8, 0x2F, 0x40, 0x03, 0x00, 0x4D, 0x02, 0xF0, 0x0D, 0xC0,
+0x34, 0x00, 0xD7, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0x80, 0x03, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x2F, 0x00, 0xFF, 0x00, 0xBC, 0x01, 0x70,
+0x03, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00,
+0x3F, 0x00, 0xFC, 0x00, 0x91, 0x03, 0xC0, 0x0F, 0x10, 0xBB, 0x00, 0xEC, 0x00,
+0x30, 0x03, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F,
+0x00, 0xFB, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA3, 0x80, 0xC0, 0x0E, 0x02, 0x3A, 0x08, 0xE8, 0x28,
+0xB8, 0xA3, 0xC0, 0x8E, 0x02, 0x3A, 0x08, 0xEC, 0x28, 0xA0, 0x83, 0xE0, 0x8E,
+0x82, 0x3B, 0x0A, 0xEC, 0x28, 0xA8, 0x83, 0xC0, 0x8E, 0x82, 0x3B, 0x0E, 0xE6,
+0x28, 0xA0, 0x83, 0xE0, 0x8E, 0x82, 0x3B, 0x0A, 0xEC, 0x20, 0xB8, 0x83, 0xE0,
+0x0E, 0x82, 0x3A, 0x0A, 0xEE, 0x20, 0xB0, 0x03, 0x8C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x83, 0x22, 0x20, 0x8E, 0x80, 0x3B, 0x02, 0xCA, 0x08, 0xA8,
+0x23, 0xA0, 0x8E, 0x80, 0x3A, 0x02, 0xE8, 0x08, 0xA8, 0x23, 0xE0, 0x8E, 0x00,
+0x13, 0x02, 0xE8, 0x08, 0xA8, 0x23, 0xA0, 0x84, 0x00, 0x3B, 0x02, 0xEC, 0x08,
+0x28, 0x23, 0xE0, 0x8A, 0x00, 0x39, 0x02, 0xE8, 0x08, 0xBA, 0x23, 0x40, 0x84,
+0x80, 0x3B, 0x00, 0xEE, 0x08, 0xA8, 0x03, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x21, 0x40, 0x80, 0x04, 0x01, 0x12, 0x04, 0x40, 0x10, 0x20, 0x41,
+0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80, 0x84, 0x01, 0x12,
+0x06, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x06, 0x48, 0x10, 0x00,
+0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01,
+0x12, 0x04, 0x48, 0x10, 0x20, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x83, 0x00, 0x80, 0x0E, 0x00, 0x1A, 0x00, 0x6A, 0x08, 0xA2, 0x61, 0x80,
+0x86, 0xA0, 0x1A, 0x00, 0x28, 0x08, 0xA8, 0x01, 0x80, 0x06, 0x00, 0x1A, 0x80,
+0x68, 0x08, 0xAA, 0x01, 0x80, 0x86, 0x01, 0x1A, 0x00, 0x68, 0x08, 0xA8, 0x00,
+0x80, 0x86, 0x00, 0x3A, 0x02, 0x68, 0x00, 0xA0, 0x01, 0x80, 0x0E, 0x00, 0x0A,
+0x04, 0x60, 0x00, 0xA0, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA0, 0x12, 0xA0, 0x4E, 0x80, 0x3A, 0x01, 0xEA, 0x04, 0xA0, 0x13, 0xA0, 0x4E,
+0x81, 0x3A, 0x01, 0xE8, 0x04, 0xA8, 0x13, 0xA0, 0xCE, 0x80, 0x3A, 0x01, 0xE8,
+0x34, 0xA8, 0x13, 0xA0, 0xCE, 0x80, 0x3A, 0x01, 0xEA, 0x04, 0xA8, 0x13, 0xA0,
+0x4E, 0x80, 0x2A, 0x01, 0xA8, 0x04, 0xA8, 0x12, 0xA0, 0x4E, 0x80, 0x32, 0x01,
+0xEA, 0x04, 0xA8, 0x03, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3,
+0x02, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x06, 0x00,
+0x18, 0x01, 0x62, 0x00, 0x80, 0x81, 0x00, 0x06, 0x01, 0x18, 0x00, 0x42, 0x00,
+0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x08, 0x60, 0x10, 0x80, 0x01, 0x00, 0x06,
+0x03, 0x18, 0x00, 0x62, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60,
+0x00, 0x80, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x82,
+0x20, 0x04, 0x80, 0x10, 0x00, 0x42, 0x14, 0x00, 0x10, 0x20, 0x84, 0x80, 0x10,
+0x08, 0x42, 0x10, 0x08, 0x11, 0x20, 0x04, 0x80, 0x10, 0x0C, 0x42, 0x08, 0x08,
+0x11, 0x20, 0x04, 0x80, 0x10, 0x00, 0x42, 0x00, 0x08, 0x11, 0x20, 0x04, 0x80,
+0x10, 0x04, 0x42, 0x04, 0x08, 0x01, 0x20, 0x04, 0x80, 0x10, 0x01, 0x42, 0x04,
+0x08, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xF2, 0xA0,
+0x02, 0x03, 0x0A, 0x04, 0x28, 0x1C, 0xAA, 0x50, 0xA0, 0x02, 0x01, 0x0A, 0x06,
+0x2A, 0x10, 0xA0, 0xD0, 0x80, 0x02, 0x01, 0x0A, 0x04, 0x0A, 0x30, 0xA0, 0x50,
+0xA0, 0x02, 0x01, 0x0A, 0x0E, 0x28, 0x10, 0xA0, 0x50, 0x80, 0x82, 0x01, 0x0A,
+0x04, 0x2A, 0x14, 0xA0, 0x40, 0x80, 0x02, 0x01, 0x2A, 0x05, 0x28, 0x3C, 0xA8,
+0x00, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x80, 0xC8,
+0x00, 0xA2, 0x03, 0xA8, 0x2E, 0xA0, 0x32, 0x80, 0xEA, 0x00, 0xAA, 0x03, 0x08,
+0x0C, 0xA0, 0x3A, 0x80, 0x6A, 0x00, 0x82, 0x01, 0x08, 0x0C, 0x20, 0x3A, 0x80,
+0x6A, 0x00, 0x82, 0x03, 0x08, 0x0C, 0xA0, 0x3A, 0x80, 0xEA, 0x01, 0xA2, 0x03,
+0x08, 0x0E, 0xA0, 0x3A, 0x80, 0xE0, 0x00, 0xAA, 0x03, 0x08, 0x1C, 0x20, 0x02,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x08, 0x80,
+0x30, 0x01, 0x20, 0x18, 0x80, 0x00, 0x00, 0xC2, 0x01, 0x08, 0x02, 0x00, 0x04,
+0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x02, 0x00, 0x82,
+0x00, 0x10, 0x06, 0x00, 0x04, 0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x00, 0x44, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x82, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x16, 0x40, 0x18, 0x00, 0x61,
+0x00, 0x04, 0x21, 0x10, 0x04, 0x40, 0x10, 0x00, 0x41, 0x01, 0x06, 0x01, 0x10,
+0x04, 0x40, 0x10, 0x80, 0x41, 0x00, 0x06, 0x01, 0x10, 0x06, 0x40, 0x10, 0x80,
+0x41, 0x00, 0x06, 0x01, 0x10, 0x04, 0x40, 0x10, 0x80, 0x41, 0x00, 0x06, 0x01,
+0x10, 0x04, 0x60, 0x14, 0x00, 0x41, 0x00, 0x04, 0x01, 0x10, 0x82, 0x8C, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x02, 0xA0, 0x06, 0x80, 0x9A, 0x00,
+0x6D, 0x02, 0xA0, 0x01, 0xA0, 0x26, 0x40, 0x9B, 0x00, 0x4A, 0x00, 0xB0, 0x09,
+0x88, 0x26, 0x80, 0x92, 0x00, 0x48, 0x00, 0x80, 0x09, 0xA0, 0x26, 0x40, 0x92,
+0x00, 0x48, 0x00, 0xB0, 0x09, 0x80, 0x26, 0x80, 0x9A, 0x00, 0x4A, 0x02, 0xA8,
+0x09, 0xA0, 0x24, 0x80, 0x9B, 0x00, 0x4A, 0x00, 0xA8, 0x01, 0x8C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x02, 0xC0, 0x06, 0x00, 0x1A, 0x01, 0x68,
+0x00, 0xB0, 0x01, 0xC0, 0x46, 0x80, 0x1A, 0x00, 0x6E, 0x04, 0xA8, 0x01, 0xC0,
+0x06, 0x80, 0x1B, 0x00, 0x6A, 0x00, 0xB0, 0x01, 0xE0, 0x06, 0x80, 0x1B, 0x00,
+0x6E, 0x04, 0xA8, 0x01, 0xC8, 0x06, 0x00, 0x1A, 0x00, 0x6E, 0x00, 0xB0, 0x01,
+0xE0, 0x46, 0x80, 0x1A, 0x00, 0x6E, 0x00, 0xB0, 0x01, 0x8C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA3, 0x42, 0x20, 0x0C, 0x81, 0x31, 0x0C, 0x82, 0x10,
+0x08, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC0, 0x30, 0x08, 0x43, 0x20, 0x0C,
+0x01, 0x30, 0x0C, 0xC2, 0x30, 0x10, 0x43, 0x20, 0x0C, 0x03, 0x30, 0x0C, 0xC0,
+0x30, 0x08, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x0C, 0xC0, 0x10, 0x08, 0x43, 0x00,
+0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x03, 0x8C, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00,
+0x03, 0x00, 0x0C, 0x00, 0x30, 0x01, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x4C, 0x00,
+0x30, 0x01, 0xC0, 0x04, 0x00, 0x03, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x00,
+0x00, 0x03, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x00, 0x00, 0x13, 0x08, 0x08,
+0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x21, 0x40, 0x80, 0x4C, 0x23, 0x32, 0x04, 0xCA, 0x10, 0x20, 0x43,
+0x80, 0x0C, 0x03, 0x32, 0x0C, 0xCA, 0x10, 0x20, 0x43, 0x88, 0x4C, 0x23, 0x32,
+0x05, 0xC8, 0x14, 0x20, 0x43, 0x80, 0x4C, 0x81, 0x32, 0x05, 0xCA, 0x10, 0x20,
+0x43, 0x80, 0x48, 0x03, 0x32, 0x05, 0x88, 0x10, 0x20, 0xD3, 0xA0, 0x0C, 0x03,
+0x32, 0x04, 0xCA, 0x10, 0x20, 0x03, 0x84, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA2, 0x42, 0xA0, 0x06, 0x83, 0x3A, 0x04, 0x6A, 0x10, 0xA8, 0x41, 0xA0,
+0x06, 0x83, 0x1A, 0x0C, 0x4A, 0x30, 0xA8, 0x41, 0xA0, 0x06, 0x81, 0x1A, 0x0C,
+0x4A, 0x30, 0xA8, 0x41, 0x80, 0x0E, 0x83, 0x1A, 0x0C, 0x4A, 0x30, 0x88, 0x41,
+0xA0, 0x06, 0x01, 0x0A, 0x0C, 0x08, 0x10, 0xA8, 0x41, 0xA0, 0x06, 0x83, 0x1A,
+0x04, 0x6A, 0x10, 0xA8, 0x01, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA3, 0x40, 0x00, 0x04, 0x01, 0x18, 0x04, 0xC0, 0x10, 0x00, 0x41, 0x00, 0x04,
+0x01, 0x20, 0x04, 0x40, 0x10, 0x00, 0x42, 0x00, 0x00, 0x01, 0x10, 0x04, 0x40,
+0x10, 0x80, 0x41, 0x00, 0x04, 0x01, 0x10, 0x04, 0x00, 0x10, 0x00, 0x43, 0x00,
+0x00, 0x81, 0x10, 0x04, 0x40, 0x10, 0x00, 0x41, 0x00, 0x0C, 0x01, 0x30, 0x04,
+0x40, 0x10, 0x00, 0x01, 0x8C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3,
+0x4A, 0x20, 0x2C, 0x81, 0x10, 0x0C, 0x82, 0x12, 0x88, 0x41, 0x20, 0x26, 0x81,
+0xB0, 0x04, 0x42, 0x10, 0x08, 0x43, 0x20, 0x26, 0x83, 0x90, 0x04, 0x02, 0x12,
+0x08, 0x41, 0x00, 0x26, 0x81, 0x90, 0x04, 0x42, 0x10, 0x08, 0x43, 0x20, 0x26,
+0x83, 0x90, 0x04, 0x40, 0x10, 0x88, 0xC9, 0x20, 0x0C, 0x81, 0xB0, 0x04, 0x62,
+0x12, 0x88, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x06,
+0x20, 0x1A, 0x00, 0x62, 0x00, 0x88, 0x01, 0xA8, 0x06, 0xA0, 0x1A, 0x80, 0x62,
+0x00, 0x80, 0x01, 0x28, 0x06, 0xA0, 0x1A, 0x80, 0x42, 0x00, 0x0A, 0x01, 0xA0,
+0x06, 0x80, 0x18, 0x00, 0x6A, 0x00, 0x88, 0x01, 0x28, 0x06, 0xA0, 0x1A, 0x80,
+0x6A, 0x80, 0x08, 0x01, 0xA8, 0x06, 0x80, 0x18, 0x80, 0x62, 0x00, 0xA8, 0x01,
+0x88, 0x02, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80,
+0x82, 0x01, 0x0A, 0x06, 0x28, 0x18, 0xA0, 0x60, 0x80, 0x82, 0x01, 0x0A, 0x06,
+0x28, 0x18, 0xA0, 0x60, 0x80, 0x82, 0x01, 0x0A, 0x06, 0x28, 0x18, 0xA0, 0x60,
+0xA0, 0x82, 0x01, 0x2A, 0x06, 0x28, 0x18, 0xA0, 0x60, 0x80, 0x82, 0x01, 0x0A,
+0x06, 0xAA, 0x18, 0xA0, 0x60, 0x80, 0x8A, 0x01, 0x0A, 0x06, 0x28, 0x18, 0xA0,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x80, 0x20,
+0x81, 0x02, 0x84, 0x08, 0x12, 0x20, 0x40, 0x80, 0x20, 0x81, 0x82, 0x04, 0x08,
+0x10, 0x20, 0x40, 0x80, 0x20, 0x01, 0x82, 0x04, 0x4A, 0x12, 0x20, 0x40, 0x80,
+0x20, 0x01, 0x82, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x20, 0x01, 0x82, 0x04,
+0x08, 0x10, 0x20, 0x48, 0x80, 0x00, 0x01, 0x82, 0x04, 0x48, 0x12, 0x20, 0x00,
+0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x62, 0xC0, 0x80, 0x01,
+0x03, 0x06, 0xAC, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0xAE, 0x18,
+0xB0, 0x62, 0xC0, 0x8A, 0x81, 0x2B, 0x06, 0xAC, 0x18, 0xA0, 0x62, 0xC0, 0x8A,
+0x81, 0x29, 0x06, 0xAE, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0xA6,
+0x18, 0xB0, 0x62, 0x60, 0x8A, 0x01, 0x2B, 0x06, 0xAC, 0x18, 0xB0, 0x02, 0x8C,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x62, 0x80, 0x8E, 0x01, 0x3A,
+0x06, 0xEE, 0x18, 0xA4, 0x63, 0x80, 0x8E, 0x81, 0x3A, 0x06, 0xE8, 0x18, 0xB0,
+0x63, 0x80, 0x8E, 0x01, 0x3A, 0x06, 0xEA, 0x18, 0xA8, 0x63, 0x80, 0x8E, 0x81,
+0x3A, 0x06, 0xE0, 0x18, 0xB0, 0x63, 0x80, 0x8E, 0x81, 0x3B, 0x06, 0xE8, 0x18,
+0xA8, 0x63, 0x20, 0x8E, 0x81, 0x3B, 0x06, 0xEA, 0x18, 0xA8, 0x03, 0x8C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x62, 0xC0, 0x8E, 0x01, 0x3A, 0x06,
+0xE8, 0x18, 0xB0, 0x63, 0xC0, 0x8E, 0x01, 0x3A, 0x06, 0xCC, 0x18, 0xA0, 0x63,
+0xC0, 0x8E, 0x01, 0x3B, 0x86, 0xEA, 0x18, 0x30, 0x63, 0xC0, 0x8E, 0x01, 0x3B,
+0x06, 0xCC, 0x18, 0xA0, 0x63, 0xC0, 0x8E, 0x01, 0x3B, 0x06, 0xEC, 0x18, 0xB0,
+0x63, 0xE0, 0x8E, 0x81, 0x3A, 0x06, 0xEE, 0x18, 0xB0, 0x03, 0x88, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x62, 0xA0, 0x8E, 0x81, 0x31, 0x06, 0xC2,
+0x18, 0xA8, 0x63, 0xA0, 0x8E, 0x81, 0x30, 0x06, 0xC2, 0x18, 0x0A, 0x63, 0xA0,
+0x8E, 0x01, 0x10, 0x06, 0xC4, 0x18, 0x30, 0x63, 0x00, 0x8C, 0x21, 0x10, 0x06,
+0xC0, 0x18, 0x08, 0x61, 0xA0, 0x8E, 0xA1, 0x38, 0x86, 0x80, 0x18, 0xA8, 0x63,
+0x00, 0x84, 0x81, 0x38, 0x06, 0xEE, 0x18, 0xA8, 0x03, 0x88, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x04, 0x01, 0x1A, 0x04, 0xE8, 0x10,
+0x20, 0x41, 0x80, 0x04, 0x01, 0x3A, 0x04, 0x48, 0x10, 0xA0, 0x43, 0x80, 0x04,
+0x01, 0x12, 0x04, 0x68, 0x10, 0x20, 0x41, 0x00, 0x04, 0x01, 0x12, 0x04, 0x48,
+0x10, 0x20, 0x43, 0x80, 0x04, 0x01, 0x32, 0x04, 0x68, 0x10, 0x20, 0x41, 0x80,
+0x04, 0x01, 0x32, 0x04, 0x48, 0x10, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x86, 0x01, 0x12, 0x06, 0x6A, 0x18, 0xA0,
+0x60, 0x88, 0x86, 0x81, 0x1A, 0x06, 0x48, 0x18, 0xA8, 0x60, 0x00, 0x82, 0x01,
+0x02, 0x86, 0x48, 0x18, 0xA0, 0x61, 0x80, 0x84, 0x01, 0x1A, 0x06, 0x48, 0x18,
+0xA8, 0x61, 0x88, 0x86, 0x01, 0x1A, 0x06, 0x48, 0x18, 0xA0, 0x61, 0x80, 0x84,
+0x01, 0x18, 0x06, 0x68, 0x18, 0xA0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA2, 0x02, 0xA0, 0x0E, 0x80, 0x3A, 0x00, 0xCA, 0x00, 0x28, 0x03,
+0xA0, 0x0A, 0x80, 0x32, 0x00, 0xC8, 0x00, 0xA8, 0x02, 0xA0, 0x0C, 0x00, 0x32,
+0x00, 0xC8, 0x00, 0xA8, 0x03, 0xA0, 0x0C, 0x00, 0x32, 0x00, 0xC8, 0x00, 0xA8,
+0x03, 0xA0, 0x0C, 0x00, 0x32, 0x00, 0xE8, 0x00, 0x28, 0x03, 0xA0, 0x0C, 0x80,
+0x32, 0x00, 0xCA, 0x00, 0xA8, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA2, 0x42, 0x00, 0x06, 0x01, 0x18, 0x04, 0x40, 0x10, 0x00, 0x41, 0x00,
+0x06, 0x01, 0x10, 0x0C, 0x42, 0x10, 0x80, 0x41, 0x00, 0x04, 0x83, 0x10, 0x0C,
+0x40, 0x10, 0x80, 0xC1, 0x00, 0x04, 0x83, 0x10, 0x04, 0x42, 0x10, 0x80, 0xC1,
+0x00, 0x04, 0x83, 0x10, 0x0C, 0x42, 0x30, 0x00, 0xC0, 0x00, 0x04, 0x03, 0x10,
+0x04, 0x60, 0x10, 0x80, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA2, 0x42, 0x20, 0x04, 0x81, 0x10, 0x04, 0x62, 0x10, 0x88, 0x41, 0x20, 0x04,
+0x81, 0x18, 0x04, 0x62, 0x10, 0x08, 0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x60,
+0x10, 0x08, 0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x08, 0x41, 0x20,
+0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x88, 0x41, 0x20, 0x06, 0x81, 0x18, 0x05,
+0x42, 0x10, 0x08, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2,
+0x42, 0xA0, 0x02, 0x01, 0x0A, 0x0C, 0xA8, 0x30, 0xA8, 0x42, 0xA0, 0x02, 0x03,
+0x2A, 0x04, 0xAA, 0x10, 0xA0, 0xC0, 0xA0, 0x0A, 0x81, 0x2A, 0x84, 0xA0, 0x10,
+0xA0, 0x40, 0xA0, 0x0A, 0x81, 0x2A, 0x0C, 0xAA, 0x10, 0xA0, 0x40, 0xA8, 0x0A,
+0x81, 0x2A, 0x04, 0x2A, 0x10, 0xA8, 0x42, 0xA0, 0x0A, 0x81, 0x2A, 0x0C, 0xA8,
+0x10, 0xA8, 0x00, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+0x80, 0x0A, 0x01, 0x2A, 0x0C, 0xA8, 0x30, 0xA0, 0xC2, 0x80, 0x0A, 0x03, 0x2A,
+0x0C, 0xA8, 0x30, 0xA0, 0xC2, 0x80, 0x0A, 0x01, 0x2A, 0x04, 0xA8, 0x30, 0xA0,
+0xC2, 0x80, 0x0A, 0x01, 0x2A, 0x0C, 0xA8, 0x30, 0xA0, 0xC2, 0x80, 0x0A, 0x01,
+0x2A, 0x04, 0xA8, 0x30, 0xA0, 0x42, 0x80, 0x0A, 0x03, 0x2A, 0x05, 0xA8, 0x30,
+0xA0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00,
+0x42, 0x80, 0x08, 0x00, 0x20, 0x00, 0x80, 0x10, 0x00, 0x02, 0x80, 0x08, 0x00,
+0x20, 0x04, 0x82, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x22, 0x04, 0x80, 0x00,
+0x00, 0x02, 0x20, 0x08, 0x00, 0x20, 0x04, 0x80, 0x00, 0x00, 0x02, 0x20, 0x08,
+0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x60, 0x04, 0x80,
+0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x42, 0x40, 0x00,
+0x01, 0x01, 0x05, 0x04, 0x14, 0x10, 0x40, 0x40, 0x40, 0x01, 0x01, 0x0C, 0x44,
+0x10, 0x10, 0x50, 0x40, 0x00, 0x81, 0x01, 0x04, 0x00, 0x30, 0x00, 0x50, 0x00,
+0x00, 0x81, 0x01, 0x0C, 0x06, 0x10, 0x10, 0x50, 0x40, 0x00, 0x01, 0x01, 0x04,
+0x46, 0x14, 0x10, 0x40, 0x60, 0x44, 0x01, 0x01, 0x04, 0x04, 0x30, 0x10, 0x00,
+0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0xA0, 0x06, 0x80,
+0x1A, 0x00, 0x6E, 0x00, 0xA8, 0x01, 0x80, 0x06, 0x80, 0x1A, 0x00, 0x6A, 0x00,
+0xB8, 0x01, 0xA0, 0x06, 0x80, 0x1A, 0x00, 0x6A, 0x00, 0xA8, 0x01, 0xA0, 0x06,
+0x80, 0x1A, 0x00, 0x68, 0x00, 0xB0, 0x01, 0x80, 0x06, 0x80, 0x1A, 0x00, 0x6A,
+0x00, 0xA8, 0x01, 0xA0, 0x06, 0x80, 0x1B, 0x00, 0x6A, 0x00, 0xA8, 0x01, 0x88,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x02, 0xC0, 0x06, 0x00, 0x12,
+0x00, 0xE8, 0x00, 0xB0, 0x01, 0xC0, 0x06, 0x80, 0x3A, 0x00, 0x4C, 0x00, 0xA0,
+0x03, 0xC0, 0x06, 0x80, 0x13, 0x00, 0x4E, 0x00, 0xB0, 0x01, 0xC0, 0x06, 0x00,
+0x13, 0x00, 0x6E, 0x00, 0xA0, 0x03, 0xC0, 0x06, 0x00, 0x1B, 0x00, 0x4C, 0x00,
+0xB0, 0x01, 0xC0, 0x04, 0x00, 0x3A, 0x00, 0x6E, 0x00, 0xB0, 0x01, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0C, 0x80, 0x11, 0x00,
+0x62, 0x00, 0x08, 0x02, 0x20, 0x0C, 0x80, 0x18, 0x00, 0x42, 0x00, 0x8A, 0x01,
+0x20, 0x0C, 0x02, 0x10, 0x00, 0x44, 0x00, 0x10, 0x01, 0x00, 0x0C, 0x02, 0x10,
+0x00, 0x40, 0x00, 0x80, 0x01, 0x20, 0x0C, 0x00, 0x10, 0x00, 0x40, 0x00, 0x08,
+0x83, 0x00, 0x04, 0x80, 0x18, 0x00, 0xC2, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x90, 0x00, 0x40,
+0x02, 0x00, 0x0B, 0x00, 0x2C, 0x00, 0x90, 0x12, 0x40, 0x02, 0x00, 0x21, 0x00,
+0xA8, 0x01, 0x90, 0x12, 0x40, 0x02, 0x00, 0x21, 0x02, 0xAC, 0x08, 0x90, 0x22,
+0x40, 0x02, 0x00, 0x21, 0x00, 0xAC, 0x05, 0x90, 0x22, 0x40, 0x08, 0x00, 0x2B,
+0x02, 0xA4, 0x00, 0x90, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x8C, 0x00, 0x32, 0x0A, 0xCA, 0x28,
+0x22, 0xA3, 0x80, 0x8C, 0x02, 0x32, 0x06, 0x48, 0x28, 0x28, 0xA2, 0x88, 0x8C,
+0x82, 0x12, 0x00, 0x48, 0x08, 0x20, 0xA1, 0x80, 0x8C, 0x03, 0x32, 0x00, 0x48,
+0x28, 0x28, 0xA2, 0x80, 0x8C, 0x00, 0x22, 0x06, 0x08, 0x38, 0x20, 0xA3, 0x80,
+0x84, 0x82, 0x32, 0x02, 0xCA, 0x08, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xC4, 0xA0, 0x16, 0x83, 0x5A, 0x0C, 0x4A, 0x31, 0xA8,
+0xC5, 0xA0, 0x16, 0x83, 0x5A, 0x0E, 0x68, 0x31, 0xA8, 0x85, 0xA0, 0x16, 0x83,
+0x5A, 0x0C, 0x60, 0x31, 0xA8, 0x85, 0xA0, 0x16, 0x03, 0x5A, 0x0C, 0x6A, 0x31,
+0xA8, 0xC5, 0xA0, 0x16, 0x03, 0x58, 0x0E, 0x28, 0x31, 0xA8, 0xE4, 0x80, 0x12,
+0x82, 0x5A, 0x0C, 0x6A, 0x31, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x90, 0x01, 0x40, 0x06, 0x00, 0x09,
+0x00, 0x64, 0x00, 0x90, 0x00, 0x42, 0x02, 0x00, 0x91, 0x00, 0xA4, 0x00, 0x90,
+0x00, 0x40, 0x02, 0x00, 0x91, 0x00, 0xA4, 0x80, 0x90, 0x08, 0x40, 0x02, 0x00,
+0x31, 0x00, 0xA4, 0x80, 0x80, 0x00, 0x42, 0x0C, 0x00, 0x09, 0x20, 0x64, 0x02,
+0x90, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x22, 0x42, 0x88, 0x18, 0x20, 0x42, 0x80, 0x88, 0x11, 0x22,
+0x06, 0x88, 0x18, 0x20, 0x62, 0x84, 0x88, 0x01, 0x22, 0x06, 0x88, 0x18, 0x20,
+0x60, 0x84, 0x88, 0x01, 0x22, 0x06, 0x88, 0x18, 0x20, 0x62, 0x84, 0x88, 0x21,
+0x26, 0x06, 0x88, 0x18, 0x20, 0x62, 0x80, 0x88, 0x21, 0x22, 0x06, 0x88, 0x18,
+0x20, 0x62, 0x84, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA2, 0x0A, 0x08, 0x2A, 0x20, 0x08, 0x00, 0xA8, 0x02, 0xA2, 0x0A,
+0x84, 0x2A, 0x20, 0xAA, 0x80, 0xA0, 0x02, 0xA6, 0x0A, 0x1C, 0x2A, 0x28, 0xA8,
+0xC0, 0xA0, 0x02, 0xA2, 0x0A, 0x88, 0x2A, 0x20, 0xAA, 0x80, 0xA0, 0x02, 0xA2,
+0x0A, 0x88, 0x2A, 0xA0, 0xAA, 0x80, 0xA9, 0x02, 0xA2, 0x0A, 0x18, 0x28, 0x20,
+0xA8, 0x80, 0xA8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x84, 0x42, 0x10, 0x0A, 0x41, 0xA8, 0x04, 0xA0, 0x12, 0x80, 0x42, 0x10,
+0x2A, 0x41, 0x28, 0x84, 0xA1, 0x10, 0x84, 0x4A, 0x10, 0x2A, 0x61, 0xA8, 0x04,
+0xA1, 0x10, 0x84, 0x4A, 0x18, 0x2A, 0x61, 0xA8, 0x44, 0xA1, 0x10, 0x84, 0x4A,
+0x14, 0x2A, 0x61, 0xA8, 0x04, 0xA1, 0x12, 0x84, 0x4A, 0x10, 0x2A, 0x01, 0xA8,
+0x04, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+0x80, 0x40, 0x81, 0x02, 0x8D, 0x08, 0x14, 0x00, 0x50, 0x80, 0x40, 0x83, 0x02,
+0x05, 0x08, 0x14, 0x20, 0x50, 0x80, 0x40, 0x01, 0x00, 0x05, 0x08, 0x14, 0x20,
+0x50, 0x00, 0x40, 0x01, 0x02, 0x05, 0x08, 0x14, 0x28, 0x50, 0x80, 0x40, 0x01,
+0x02, 0x85, 0x00, 0x14, 0x20, 0x50, 0x00, 0x40, 0x01, 0x00, 0x05, 0x00, 0x14,
+0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0,
+0xCA, 0x00, 0x2B, 0x03, 0xA4, 0x0C, 0x10, 0x32, 0xC0, 0xCA, 0x00, 0x01, 0x03,
+0x0C, 0x0C, 0xB0, 0x32, 0x40, 0xC0, 0x80, 0x21, 0x03, 0x86, 0x0C, 0xA1, 0x32,
+0x00, 0xC8, 0x80, 0x01, 0x03, 0x86, 0x0C, 0xA0, 0x32, 0x40, 0xC8, 0x00, 0x20,
+0x03, 0x86, 0x0C, 0x10, 0x30, 0x60, 0xC8, 0x20, 0x21, 0x03, 0x84, 0x0C, 0xB0,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, 0x4E,
+0x80, 0x3A, 0x09, 0xEE, 0x04, 0xA0, 0x13, 0x80, 0x4E, 0x82, 0x3A, 0x11, 0xEA,
+0x04, 0xB8, 0x13, 0x90, 0x4E, 0x90, 0x3A, 0x21, 0x6A, 0x04, 0xA8, 0x13, 0xA0,
+0x4E, 0x88, 0x3A, 0x21, 0xCA, 0x04, 0xA8, 0x13, 0x10, 0x4C, 0x84, 0x32, 0x01,
+0xE8, 0x04, 0xA8, 0x13, 0xA0, 0x4E, 0x80, 0x3B, 0x01, 0xEA, 0x04, 0xA9, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x10, 0x12, 0x03,
+0x08, 0x8C, 0x20, 0x32, 0x80, 0xC4, 0x08, 0x02, 0x03, 0x08, 0x0C, 0x20, 0x31,
+0x82, 0xC0, 0x18, 0x02, 0x03, 0x08, 0x0C, 0x20, 0x31, 0x80, 0xC0, 0x18, 0x02,
+0x03, 0x08, 0x0C, 0x20, 0x31, 0x82, 0xC0, 0x18, 0x02, 0x03, 0x08, 0x0C, 0x20,
+0x30, 0x86, 0xC0, 0x00, 0x02, 0x23, 0x08, 0x0C, 0x20, 0x31, 0x84, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB,
+0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF,
+0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF,
+0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF,
+0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xDF, 0xD0, 0x6C, 0x43, 0xB3, 0x0D,
+0xED, 0xBF, 0x34, 0xFB, 0xD2, 0xFE, 0xCB, 0xFF, 0x0D, 0xCD, 0xBE, 0x7C, 0xDB,
+0xF0, 0xFF, 0xCB, 0xFF, 0x2F, 0xED, 0xBF, 0x7C, 0xDB, 0xF0, 0xFF, 0xCB, 0xFF,
+0x2F, 0xCD, 0xBE, 0x7C, 0xDB, 0xF0, 0xFF, 0xCB, 0xB7, 0x2F, 0xDF, 0x36, 0x7C,
+0xDB, 0xF0, 0x6D, 0x43, 0xB3, 0x2F, 0xED, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x3F, 0x32, 0xF3, 0xC8, 0xCC, 0x23, 0xF3,
+0xBF, 0xCC, 0xFC, 0x32, 0xFF, 0xCB, 0xFF, 0x23, 0x33, 0xBF, 0xFC, 0x3C, 0xF2,
+0xFF, 0xCB, 0xFF, 0x2F, 0xF3, 0xBF, 0xFC, 0x3C, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F,
+0x33, 0xBF, 0xFC, 0x3C, 0xF2, 0xFF, 0xCB, 0xCF, 0x2F, 0x3F, 0x8F, 0xFC, 0x3C,
+0xF2, 0xF3, 0xC8, 0xCC, 0x2F, 0xF3, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xDC, 0x78, 0x72, 0x63, 0x48, 0xEC, 0x21, 0xB1, 0x9F,
+0xDC, 0x7E, 0x12, 0x7B, 0x48, 0x8C, 0x21, 0xB7, 0x87, 0xC4, 0x7E, 0x12, 0x63,
+0x48, 0x8C, 0x21, 0x37, 0x86, 0xC4, 0x7E, 0x12, 0x63, 0x48, 0x8C, 0x21, 0xB7,
+0x87, 0xC4, 0x7E, 0x12, 0x63, 0x48, 0x8C, 0x21, 0xB1, 0x9F, 0xC4, 0x18, 0x12,
+0x7B, 0x48, 0x8C, 0x27, 0x37, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x0E, 0x02, 0x39, 0x0A, 0xE4, 0x20, 0x90, 0x83,
+0x00, 0x0E, 0x02, 0x39, 0x08, 0xE0, 0x20, 0x80, 0x83, 0x40, 0x0E, 0x02, 0x39,
+0x08, 0xE4, 0x20, 0x90, 0x83, 0x00, 0x0E, 0x02, 0x38, 0x0A, 0xE4, 0x20, 0x80,
+0x83, 0x40, 0x0E, 0x02, 0x38, 0x06, 0xE6, 0x20, 0x90, 0xA3, 0x40, 0x0E, 0x02,
+0x39, 0x08, 0xE4, 0x28, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x20, 0x60, 0x8E, 0x00, 0x3A, 0x02, 0xEA, 0x08, 0xA0, 0x23, 0xA0,
+0x8E, 0x00, 0x3A, 0x02, 0xEA, 0x08, 0xB8, 0x23, 0xA0, 0x8E, 0x00, 0x3A, 0x02,
+0xE8, 0x08, 0xA0, 0x23, 0xA0, 0x8E, 0x80, 0x3A, 0x02, 0xEA, 0x08, 0xA8, 0x23,
+0xA0, 0x8E, 0x80, 0x3A, 0x02, 0xEE, 0x08, 0xA8, 0x23, 0xA0, 0x8E, 0x80, 0x3A,
+0x02, 0xEA, 0x08, 0xA8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x40, 0x80, 0x04, 0x01, 0x12, 0x06, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04,
+0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48,
+0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80,
+0x04, 0x01, 0x12, 0x06, 0x48, 0x10, 0x20, 0x61, 0x80, 0x04, 0x01, 0x12, 0x04,
+0x48, 0x18, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x0E, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x20, 0x06, 0x00,
+0x18, 0x00, 0x62, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00,
+0x80, 0x01, 0x28, 0x06, 0x80, 0x18, 0x02, 0x60, 0x00, 0x88, 0x01, 0x00, 0x06,
+0x80, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60,
+0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x20, 0x4E, 0x00, 0x38, 0x05, 0xE2, 0x04, 0x80, 0x13, 0x20, 0x4E, 0x00, 0x38,
+0x09, 0xE2, 0x04, 0x88, 0x13, 0x20, 0x4E, 0x00, 0x38, 0x01, 0xE0, 0x04, 0x80,
+0x13, 0x20, 0x4E, 0x82, 0x38, 0x05, 0xE2, 0x04, 0x88, 0x12, 0x20, 0x4E, 0x80,
+0x38, 0xA1, 0xE2, 0x04, 0x28, 0x51, 0x20, 0x4E, 0x80, 0x30, 0x01, 0xE2, 0x14,
+0x88, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x80, 0x18, 0x00, 0x60, 0x00, 0x88, 0x01, 0x00, 0x06, 0x80, 0x18, 0x00,
+0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x88, 0x81,
+0x00, 0x06, 0x02, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18,
+0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x08, 0x10, 0x00, 0x60, 0x00, 0x80,
+0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x24,
+0x80, 0x90, 0x01, 0x42, 0x02, 0x08, 0x29, 0x20, 0x24, 0x80, 0x90, 0x02, 0x42,
+0x02, 0x08, 0x11, 0x20, 0x24, 0x80, 0x90, 0x00, 0x42, 0x02, 0x08, 0x09, 0x20,
+0xA4, 0x80, 0x90, 0x01, 0x42, 0x02, 0x08, 0x11, 0x20, 0xA4, 0x80, 0x90, 0x01,
+0x42, 0x04, 0x08, 0x39, 0x20, 0x44, 0x80, 0x18, 0x01, 0x42, 0x06, 0x08, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x12, 0x81,
+0x48, 0x05, 0x22, 0x11, 0x88, 0x44, 0x00, 0x12, 0x81, 0x48, 0x04, 0x20, 0x31,
+0x80, 0x54, 0x20, 0x12, 0x81, 0x48, 0x04, 0x22, 0x11, 0x88, 0xC4, 0x00, 0x12,
+0x03, 0x48, 0x0D, 0x22, 0x11, 0x80, 0x54, 0x20, 0x12, 0x01, 0x48, 0x05, 0x20,
+0x15, 0x88, 0x54, 0x20, 0x52, 0x81, 0x68, 0x0D, 0x22, 0x1D, 0x88, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x30, 0x00, 0xC8, 0x00, 0x00,
+0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xCA, 0x00, 0x20, 0x03, 0xA0, 0x0C, 0x00,
+0x32, 0x00, 0xC0, 0x02, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xCA, 0x00,
+0x28, 0x03, 0x80, 0x0C, 0x80, 0x32, 0x00, 0xCA, 0x00, 0x28, 0x03, 0xA0, 0x0C,
+0x80, 0x72, 0x00, 0xCA, 0x00, 0x28, 0x03, 0x80, 0x1C, 0x80, 0x02, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x20, 0x2C, 0x00, 0x90, 0x00,
+0x00, 0x02, 0x00, 0x78, 0x00, 0x26, 0x00, 0x90, 0x03, 0x60, 0x02, 0x08, 0x03,
+0x00, 0x20, 0x00, 0x90, 0x00, 0x40, 0x02, 0x00, 0x19, 0x00, 0xE2, 0x00, 0x88,
+0x00, 0x80, 0x06, 0x80, 0x00, 0x00, 0xE2, 0x01, 0x88, 0x00, 0x20, 0x00, 0x80,
+0x28, 0x00, 0x02, 0x00, 0x08, 0x00, 0x80, 0x0A, 0x80, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x02, 0x40, 0x08, 0x80, 0x01, 0x00, 0x04,
+0x00, 0x18, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x04, 0x00, 0x10, 0x02, 0x40,
+0x00, 0x82, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x84, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x84, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x03, 0x02, 0x20, 0x06, 0x80, 0x10, 0x00, 0x42, 0x00,
+0x08, 0x01, 0x60, 0x06, 0x80, 0x10, 0x00, 0x66, 0x00, 0x88, 0x01, 0x20, 0x04,
+0x80, 0x10, 0x00, 0x42, 0x00, 0x08, 0x01, 0x40, 0x06, 0x80, 0x19, 0x00, 0x62,
+0x00, 0x98, 0x01, 0x20, 0x06, 0x80, 0x19, 0x00, 0x62, 0x00, 0x88, 0x01, 0x20,
+0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x88, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x08, 0x80, 0x02, 0x00, 0x06, 0x00, 0x19, 0x00, 0x64, 0x00, 0x90,
+0x11, 0x00, 0x06, 0x00, 0x19, 0x01, 0x60, 0x00, 0x80, 0x01, 0x40, 0x06, 0x00,
+0x19, 0x00, 0x64, 0x00, 0x90, 0x11, 0x00, 0x46, 0x00, 0x18, 0x00, 0x64, 0x04,
+0x80, 0x01, 0x40, 0x46, 0x00, 0x18, 0x00, 0x66, 0x00, 0x90, 0x01, 0x40, 0x06,
+0x00, 0x19, 0x00, 0x64, 0x00, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xA2, 0x42, 0x60, 0x0C, 0x01, 0x30, 0x04, 0xC2, 0x10, 0x00, 0x43,
+0x20, 0x0C, 0x01, 0x30, 0x04, 0xC2, 0x10, 0x18, 0x43, 0x20, 0x0C, 0x01, 0x30,
+0x04, 0xC0, 0x10, 0x00, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08,
+0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x43, 0x20, 0x0C, 0x81,
+0x30, 0x04, 0xC2, 0x10, 0x08, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x00, 0x10, 0x00, 0x4C, 0x00, 0x30, 0x00, 0xC0, 0x04, 0x00, 0x03, 0x00,
+0x4C, 0x00, 0x30, 0x00, 0xC0, 0x04, 0x00, 0x03, 0x00, 0x4C, 0x00, 0x30, 0x01,
+0xC0, 0x04, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03,
+0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30,
+0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x00, 0xD0, 0x00, 0x4C, 0x03, 0x30, 0x04, 0xC0, 0x34, 0x00, 0xC3, 0x20, 0x4C,
+0x03, 0x30, 0x0C, 0xC2, 0x34, 0x00, 0x43, 0x00, 0x4C, 0x03, 0x30, 0x0D, 0xC0,
+0x34, 0x00, 0xC3, 0x20, 0x0C, 0x83, 0x30, 0x04, 0xC0, 0x30, 0x08, 0x43, 0x00,
+0x0C, 0x83, 0x30, 0x04, 0xC2, 0x10, 0x00, 0x43, 0x00, 0x0C, 0x01, 0x30, 0x04,
+0xC0, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2,
+0xC2, 0x20, 0x0E, 0x03, 0x10, 0x04, 0x62, 0x30, 0x00, 0xC1, 0x20, 0x06, 0x03,
+0x10, 0x0C, 0x62, 0x30, 0x88, 0x43, 0x20, 0x06, 0x03, 0x18, 0x0C, 0x40, 0x30,
+0x00, 0xC1, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62, 0x30, 0x88, 0x41, 0x20, 0x06,
+0x83, 0x18, 0x04, 0x60, 0x10, 0x88, 0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62,
+0x10, 0x88, 0x01, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x42,
+0x00, 0x06, 0x81, 0x10, 0x04, 0x40, 0x10, 0x08, 0x41, 0x00, 0x0C, 0x81, 0x10,
+0x04, 0xC0, 0x10, 0x80, 0x41, 0x00, 0x04, 0x81, 0x10, 0x04, 0x42, 0x10, 0x08,
+0x41, 0x00, 0x08, 0x01, 0x30, 0x04, 0x40, 0x10, 0x00, 0x43, 0x00, 0x04, 0x01,
+0x30, 0x04, 0x42, 0x10, 0x00, 0x41, 0x00, 0x04, 0x01, 0x10, 0x04, 0x40, 0x10,
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x42, 0x20,
+0x04, 0x81, 0x10, 0x04, 0x62, 0x10, 0x08, 0x41, 0x20, 0x0C, 0x81, 0x10, 0x04,
+0xC2, 0x10, 0x08, 0x41, 0x20, 0x06, 0x81, 0x10, 0x04, 0x42, 0x10, 0x08, 0x41,
+0x20, 0x0C, 0x83, 0x30, 0x04, 0x62, 0x10, 0x08, 0x43, 0x20, 0x06, 0x81, 0x30,
+0x04, 0x62, 0x10, 0x88, 0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x88,
+0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x02, 0x00, 0x08,
+0x80, 0x00, 0x00, 0xA2, 0x00, 0x08, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x02, 0x20, 0x0A, 0x80, 0x20, 0x00, 0x82, 0x00, 0x08, 0x02, 0x00,
+0x08, 0x00, 0x20, 0x00, 0xA2, 0x00, 0x00, 0x02, 0x20, 0x0A, 0x00, 0x20, 0x00,
+0xA0, 0x00, 0x88, 0x02, 0x20, 0x0A, 0x80, 0x28, 0x00, 0xA2, 0x00, 0x88, 0x42,
+0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x60, 0x00, 0x82, 0x01,
+0x08, 0x06, 0x20, 0x18, 0x80, 0x60, 0x00, 0x82, 0x01, 0x08, 0x06, 0x20, 0x18,
+0x80, 0x60, 0x00, 0x82, 0x01, 0x08, 0x06, 0x20, 0x18, 0x80, 0x60, 0x00, 0x82,
+0x01, 0x08, 0x06, 0x20, 0x18, 0x80, 0x60, 0x00, 0x82, 0x01, 0x08, 0x06, 0x20,
+0x18, 0x80, 0x60, 0x00, 0x82, 0x01, 0x28, 0x06, 0x20, 0x18, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x40, 0xA0, 0x00, 0x01, 0x02,
+0x04, 0x08, 0x10, 0x20, 0x41, 0x80, 0x00, 0x01, 0x02, 0x04, 0x48, 0x10, 0x28,
+0x40, 0x80, 0x04, 0x01, 0x02, 0x04, 0x48, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01,
+0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10,
+0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x62, 0xC0, 0x8A, 0x81, 0x2B, 0x06,
+0xAC, 0x18, 0xB8, 0x62, 0xC0, 0x8A, 0x81, 0x2B, 0x06, 0xAC, 0x18, 0xB0, 0x62,
+0xC0, 0x8A, 0x81, 0x2B, 0x06, 0xAE, 0x18, 0xB8, 0x62, 0xC0, 0x8A, 0x01, 0x2B,
+0x06, 0xAC, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0xAC, 0x18, 0xB0,
+0x62, 0xC0, 0x8A, 0x01, 0x29, 0x06, 0xAC, 0x18, 0xB0, 0x02, 0x88, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x62, 0x20, 0x8E, 0x81, 0x38, 0x06, 0xE2,
+0x18, 0x88, 0x63, 0x60, 0x8E, 0x81, 0x38, 0x06, 0xE6, 0x18, 0x88, 0x63, 0x20,
+0x8E, 0x81, 0x38, 0x06, 0xE2, 0x18, 0x88, 0x63, 0x50, 0x8E, 0x81, 0x39, 0x06,
+0xE2, 0x18, 0x98, 0x63, 0x20, 0x8E, 0x81, 0x39, 0x04, 0xE2, 0x18, 0x88, 0x63,
+0x20, 0x8E, 0x81, 0x3A, 0x06, 0xE2, 0x18, 0x88, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x80, 0x62, 0x00, 0x8E, 0x01, 0x3B, 0x06, 0xE4, 0x18,
+0xB0, 0x63, 0x00, 0x8E, 0x01, 0x39, 0x06, 0xE0, 0x18, 0x80, 0x63, 0x40, 0x8E,
+0x01, 0x39, 0x06, 0xEC, 0x18, 0xB0, 0x63, 0x80, 0x8E, 0x01, 0x38, 0x06, 0xE4,
+0x18, 0x80, 0x63, 0x40, 0x8E, 0x01, 0x38, 0x06, 0xE4, 0x18, 0x90, 0x63, 0x40,
+0x0E, 0x01, 0x39, 0x06, 0xE4, 0x18, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0A, 0xA2, 0x62, 0x60, 0x8C, 0x01, 0x30, 0x06, 0xEA, 0x18, 0x80,
+0x63, 0x20, 0x8C, 0x01, 0x30, 0x06, 0xC2, 0x18, 0x18, 0x63, 0xA0, 0x8E, 0x01,
+0x30, 0x06, 0xC0, 0x18, 0x00, 0x63, 0x20, 0x8E, 0x81, 0x30, 0x06, 0xEA, 0x18,
+0x08, 0x63, 0xA0, 0x8E, 0x81, 0x30, 0x06, 0xEA, 0x18, 0xA8, 0x63, 0xA0, 0x8E,
+0x81, 0x3A, 0x06, 0xEA, 0x18, 0xA8, 0x43, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x48, 0x00, 0x24, 0x01, 0x9A, 0x04, 0x48, 0x12, 0x20, 0x49,
+0x80, 0x2E, 0x01, 0x90, 0x04, 0xE8, 0x12, 0x00, 0x49, 0x80, 0x24, 0x01, 0x90,
+0x04, 0x68, 0x12, 0xA0, 0x41, 0x80, 0x2C, 0x01, 0xBA, 0x04, 0x48, 0x10, 0xA0,
+0x43, 0x80, 0x24, 0x01, 0xBA, 0x04, 0x48, 0x10, 0x20, 0x49, 0x80, 0x04, 0x01,
+0x92, 0x04, 0x48, 0x12, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x00, 0x60, 0x00, 0x84, 0x01, 0x10, 0x06, 0x60, 0x18, 0x00, 0x61, 0x20,
+0x86, 0x01, 0x10, 0x06, 0x62, 0x18, 0x00, 0x61, 0x00, 0x86, 0x01, 0x10, 0x06,
+0x40, 0x18, 0x00, 0x61, 0x20, 0x86, 0x81, 0x18, 0x06, 0x60, 0x18, 0x88, 0x61,
+0x00, 0x86, 0x81, 0x58, 0x06, 0x60, 0x18, 0x80, 0x61, 0x00, 0x86, 0x01, 0x18,
+0x06, 0x60, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA2, 0x06, 0x20, 0x1E, 0x00, 0x70, 0x00, 0xC2, 0x01, 0x00, 0x07, 0x20, 0x1E,
+0x00, 0x70, 0x00, 0xC2, 0x01, 0x88, 0x07, 0x20, 0x1C, 0x00, 0x70, 0x00, 0xC0,
+0x01, 0x00, 0x07, 0x20, 0x1C, 0x80, 0x70, 0x00, 0xE2, 0x01, 0x88, 0x07, 0x20,
+0x1E, 0x80, 0x78, 0x00, 0xC2, 0x01, 0x88, 0x07, 0x20, 0x1E, 0x80, 0x78, 0x00,
+0xE2, 0x01, 0x88, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80,
+0x4A, 0x00, 0x26, 0x83, 0x90, 0x04, 0x40, 0x12, 0x08, 0x49, 0x00, 0x26, 0x81,
+0x90, 0x04, 0x40, 0x12, 0x80, 0x49, 0x00, 0x24, 0x81, 0x90, 0x04, 0x42, 0x12,
+0x08, 0x41, 0x00, 0x24, 0x01, 0x90, 0x04, 0x60, 0x10, 0x80, 0x41, 0x00, 0x26,
+0x01, 0x98, 0x04, 0x40, 0x10, 0x80, 0x49, 0x00, 0x06, 0x01, 0x98, 0x04, 0x60,
+0x12, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x42,
+0x20, 0x04, 0x81, 0x18, 0x05, 0x62, 0x10, 0x88, 0x41, 0x20, 0x04, 0x81, 0x18,
+0x04, 0x62, 0x10, 0x08, 0x51, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x88,
+0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x42, 0x10, 0x08, 0x41, 0x20, 0x04, 0x81,
+0x10, 0x04, 0x62, 0x10, 0x08, 0x41, 0x20, 0x04, 0x81, 0x10, 0x04, 0x42, 0x10,
+0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x42, 0x00,
+0x02, 0x81, 0x28, 0x0C, 0xA2, 0x30, 0x88, 0x42, 0x00, 0x02, 0x83, 0x28, 0x0C,
+0xA0, 0x10, 0x80, 0xC0, 0x20, 0x0A, 0x83, 0x28, 0x0C, 0xA2, 0x30, 0x88, 0xC2,
+0x00, 0x0A, 0x03, 0x28, 0x04, 0x22, 0x10, 0x80, 0x40, 0x20, 0x02, 0x01, 0x08,
+0x04, 0xA2, 0x10, 0x88, 0x40, 0x20, 0x02, 0x81, 0x08, 0x04, 0x22, 0x10, 0x88,
+0x00, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x0A,
+0x01, 0x28, 0x05, 0xA0, 0x10, 0x80, 0xC2, 0x00, 0x0A, 0x03, 0x28, 0x0C, 0xA0,
+0x10, 0x80, 0x52, 0x00, 0x0A, 0x01, 0x28, 0x04, 0xA0, 0x10, 0x80, 0xC2, 0x00,
+0x0A, 0x03, 0x28, 0x0C, 0xA0, 0x30, 0x80, 0xC2, 0x00, 0x0A, 0x03, 0x28, 0x0C,
+0x80, 0x30, 0x80, 0xC2, 0x00, 0x0A, 0x03, 0x28, 0x04, 0xA0, 0x30, 0x80, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x20, 0x06, 0x00,
+0x08, 0x00, 0x60, 0x00, 0x80, 0x11, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20, 0x04,
+0x88, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02,
+0x00, 0x08, 0x01, 0x20, 0x04, 0x80, 0x10, 0x00, 0x42, 0x00, 0x08, 0x00, 0x80,
+0x04, 0x80, 0x10, 0x00, 0x42, 0x00, 0x08, 0x01, 0x20, 0x04, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x42, 0x40, 0x00, 0x81, 0x01,
+0x04, 0x04, 0x10, 0x18, 0x40, 0x40, 0x00, 0x83, 0x01, 0x05, 0x04, 0x10, 0x10,
+0x40, 0x40, 0x00, 0x81, 0x01, 0x04, 0x06, 0x10, 0x18, 0x50, 0x40, 0x40, 0x01,
+0x01, 0x0C, 0x04, 0x10, 0x10, 0x40, 0x40, 0x00, 0x01, 0x01, 0x05, 0x84, 0x10,
+0x10, 0x40, 0x40, 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x10, 0x00, 0x88, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x20, 0x06, 0x80, 0x18, 0x00,
+0x62, 0x00, 0x88, 0x01, 0x60, 0x06, 0x80, 0x18, 0x00, 0x66, 0x00, 0x88, 0x01,
+0x20, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x88, 0x01, 0x60, 0x06, 0x80, 0x19,
+0x00, 0x62, 0x00, 0x98, 0x01, 0x20, 0x06, 0x80, 0x19, 0x00, 0x62, 0x00, 0x88,
+0x01, 0x20, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x88, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x00, 0x24, 0x00, 0x99, 0x00, 0x64,
+0x02, 0x10, 0x09, 0x00, 0x2E, 0x00, 0x91, 0x00, 0xE0, 0x00, 0x00, 0x09, 0x40,
+0x26, 0x00, 0x91, 0x00, 0x44, 0x02, 0x10, 0x09, 0x00, 0x2E, 0x00, 0xB8, 0x00,
+0x64, 0x00, 0x80, 0x0B, 0x40, 0x26, 0x00, 0xB8, 0x00, 0x64, 0x02, 0x98, 0x09,
+0x40, 0x26, 0x00, 0x99, 0x00, 0x64, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA2, 0x06, 0x60, 0x14, 0x00, 0x50, 0x00, 0xC2, 0x01,
+0x00, 0x05, 0x20, 0x16, 0x00, 0x50, 0x00, 0x62, 0x01, 0x18, 0x05, 0x20, 0x1C,
+0x00, 0x50, 0x00, 0x40, 0x01, 0x00, 0x05, 0x20, 0x16, 0x80, 0x58, 0x00, 0xC2,
+0x01, 0x88, 0x05, 0x28, 0x1C, 0x80, 0x58, 0x00, 0xC2, 0x01, 0x08, 0x07, 0x20,
+0x1C, 0x80, 0x70, 0x08, 0xC2, 0x01, 0x08, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0A, 0x00, 0x80, 0x00, 0x04, 0x02, 0x10, 0x08, 0xC0, 0x20, 0x00,
+0xA1, 0x00, 0x04, 0x02, 0x10, 0x08, 0x40, 0x20, 0x00, 0x81, 0x00, 0x0C, 0x02,
+0x10, 0x08, 0x40, 0x20, 0x00, 0x81, 0x00, 0x04, 0x02, 0x10, 0x0A, 0xC0, 0x20,
+0x00, 0xA1, 0x00, 0x8C, 0x02, 0x10, 0x08, 0xC0, 0x28, 0x00, 0xE3, 0x00, 0x1C,
+0x02, 0x30, 0x0A, 0xC0, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x20, 0x00, 0xA4, 0x00, 0x90, 0x02, 0xC0, 0x0A, 0x00, 0xA9,
+0x20, 0xAC, 0x00, 0xB0, 0x0A, 0xC2, 0x08, 0x00, 0x29, 0x00, 0xAC, 0x00, 0xB0,
+0x02, 0xC0, 0x0A, 0x00, 0xAB, 0x20, 0xAC, 0x82, 0xB0, 0x06, 0xC0, 0x28, 0x08,
+0xAB, 0x00, 0xAC, 0x82, 0xB0, 0x0A, 0xC0, 0x3A, 0x08, 0xAB, 0x00, 0xAC, 0x02,
+0xB0, 0x0E, 0xC0, 0x28, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xA2, 0xC2, 0x20, 0x06, 0x03, 0x18, 0x0C, 0x62, 0x30, 0x80, 0xE1, 0x20,
+0x06, 0x03, 0x18, 0x0C, 0x62, 0x30, 0x88, 0xC1, 0x20, 0x06, 0x03, 0x18, 0x0C,
+0x60, 0x30, 0x80, 0xC1, 0x20, 0x06, 0x83, 0x18, 0x0E, 0x62, 0x30, 0x88, 0xE1,
+0x20, 0x06, 0x83, 0x18, 0x0C, 0x62, 0x38, 0x80, 0xE1, 0x20, 0x06, 0x83, 0x18,
+0x0E, 0x62, 0x30, 0x88, 0x01, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x80, 0x02, 0x00, 0x04, 0x80, 0x10, 0x00, 0x40, 0x00, 0x08, 0x01, 0x00, 0x04,
+0x80, 0x10, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x10, 0x00, 0x42,
+0x00, 0x08, 0x11, 0x00, 0x44, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x84, 0x00, 0x10, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80,
+0x12, 0x22, 0x06, 0x88, 0x18, 0x20, 0x62, 0x80, 0x88, 0x11, 0x20, 0x06, 0x88,
+0x18, 0x20, 0x62, 0x84, 0x88, 0x01, 0x22, 0x06, 0x88, 0x18, 0x20, 0x62, 0x80,
+0x88, 0x01, 0x22, 0x06, 0x88, 0x18, 0x01, 0x62, 0x84, 0x88, 0x31, 0x20, 0x46,
+0x80, 0x18, 0x20, 0x62, 0x04, 0x80, 0x11, 0x20, 0x46, 0x88, 0x18, 0x01, 0x62,
+0x84, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x02,
+0x02, 0x0A, 0x88, 0x28, 0x20, 0xA2, 0x80, 0x88, 0x22, 0x00, 0x0A, 0x88, 0x28,
+0x00, 0xA0, 0x80, 0x80, 0x02, 0x22, 0x0A, 0x88, 0x28, 0x20, 0xA2, 0x80, 0x88,
+0x02, 0x02, 0x0A, 0x00, 0x28, 0x20, 0xA2, 0x80, 0x80, 0x02, 0x22, 0x0A, 0x02,
+0x28, 0x20, 0xA2, 0x80, 0x80, 0x02, 0x20, 0x0A, 0x88, 0x28, 0x20, 0xA2, 0x00,
+0x88, 0x02, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x04,
+0x42, 0x10, 0x28, 0x01, 0xA0, 0x04, 0x81, 0x12, 0x04, 0x42, 0x10, 0x28, 0x41,
+0xA0, 0x04, 0x81, 0x10, 0x04, 0x4A, 0x10, 0x28, 0x41, 0xA0, 0x04, 0x81, 0x12,
+0x04, 0x4A, 0x10, 0x28, 0x01, 0x20, 0x04, 0x81, 0x10, 0x04, 0x42, 0x10, 0x08,
+0x01, 0xA0, 0x04, 0x81, 0x10, 0x00, 0x42, 0x10, 0x08, 0x41, 0x20, 0x04, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xA0, 0x40,
+0x01, 0x00, 0x05, 0x08, 0x14, 0x00, 0x50, 0x80, 0x40, 0x01, 0x02, 0x05, 0x00,
+0x14, 0x28, 0x50, 0x00, 0x40, 0x01, 0x00, 0x05, 0x00, 0x14, 0x20, 0x50, 0x00,
+0x40, 0x01, 0x00, 0x85, 0x08, 0x34, 0x20, 0x50, 0x80, 0x40, 0x03, 0x02, 0x05,
+0x00, 0x14, 0x20, 0x50, 0x80, 0x40, 0x01, 0x02, 0x05, 0x08, 0x14, 0x20, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0xB2, 0xC0, 0xCA, 0x82,
+0x21, 0x0B, 0xA4, 0x2C, 0x18, 0xB2, 0xC0, 0xCA, 0x02, 0x28, 0x0B, 0x84, 0x2C,
+0xB0, 0xB2, 0x40, 0xC8, 0x82, 0x21, 0x0B, 0x86, 0x2C, 0x80, 0xB2, 0x40, 0xC8,
+0x02, 0x21, 0x0B, 0xAC, 0x2C, 0xB0, 0xB2, 0xC0, 0xCA, 0x02, 0x2B, 0x0B, 0x84,
+0x2C, 0xB0, 0xB2, 0xC0, 0xCA, 0x02, 0x2B, 0x0B, 0xAC, 0x2C, 0xB0, 0x02, 0x88,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x12, 0x20, 0x4E, 0x80, 0x38,
+0x01, 0xEA, 0x04, 0x88, 0x13, 0x60, 0x4E, 0x80, 0x3A, 0x01, 0xE6, 0x04, 0x88,
+0x13, 0x20, 0x4E, 0x80, 0x38, 0x01, 0xE2, 0x04, 0xA8, 0x13, 0x60, 0x4E, 0x00,
+0x39, 0x01, 0xE2, 0x24, 0x98, 0x13, 0x20, 0x4E, 0x82, 0x39, 0x01, 0xE2, 0x04,
+0x88, 0x13, 0x20, 0x4E, 0x82, 0x38, 0x01, 0xE2, 0x04, 0x88, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x02, 0x03, 0x08, 0x0C,
+0x20, 0x30, 0x80, 0xC0, 0x00, 0x02, 0x03, 0x08, 0x0C, 0x20, 0x31, 0x80, 0xC0,
+0x10, 0x02, 0x03, 0x08, 0x0C, 0x20, 0x30, 0x80, 0xC0, 0x08, 0x02, 0x03, 0x08,
+0x0C, 0x20, 0x31, 0x82, 0xC0, 0x18, 0x02, 0x43, 0x08, 0x0C, 0x20, 0x30, 0x86,
+0xC0, 0x00, 0x02, 0x63, 0x08, 0x0C, 0x21, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F,
+0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF,
+0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF,
+0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC,
+0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x34, 0xDB, 0xD0, 0x6C, 0x43, 0xB3, 0x2F, 0xCD, 0x36,
+0xFC, 0xDF, 0xD0, 0x6C, 0x43, 0xFB, 0x0D, 0xCD, 0x36, 0x34, 0xDB, 0xD0, 0x6C,
+0x43, 0xB3, 0x0D, 0xCD, 0x36, 0x34, 0xDB, 0xD0, 0x7E, 0xC3, 0xB7, 0x2F, 0xCD,
+0x36, 0x7C, 0xDB, 0xF0, 0x7F, 0x43, 0xB3, 0x2F, 0xDF, 0x36, 0xFC, 0xFF, 0xD2,
+0x6C, 0xC3, 0xB7, 0x0D, 0xED, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xCC, 0x3C, 0x32, 0xF3, 0xC8, 0xCC, 0x2F, 0x33, 0x8F, 0xFC,
+0x3F, 0x32, 0xF3, 0xC8, 0xFC, 0x23, 0x33, 0x8F, 0xCC, 0x3C, 0x32, 0xF3, 0xC8,
+0xCC, 0x23, 0x33, 0x8F, 0xCC, 0x3C, 0x32, 0xFF, 0xC8, 0xCF, 0x2F, 0x33, 0x8F,
+0xFC, 0x3C, 0xF2, 0xFF, 0xC8, 0xCC, 0x2F, 0x3F, 0x8F, 0xFC, 0xFF, 0x32, 0xF3,
+0xC8, 0xCF, 0x23, 0xF3, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xDC, 0x18, 0x12, 0x63, 0x48, 0x8C, 0x27, 0x31, 0x86, 0xDC, 0x1E,
+0x12, 0x63, 0x48, 0xEC, 0x21, 0x37, 0x86, 0xC4, 0x78, 0x12, 0x63, 0x48, 0x8C,
+0x21, 0x31, 0x86, 0xC4, 0x1E, 0x12, 0x7B, 0xC8, 0x8D, 0x27, 0xB7, 0x87, 0xDC,
+0x7E, 0x72, 0x7B, 0x48, 0x8C, 0x27, 0xB7, 0x9F, 0xDC, 0x7E, 0x12, 0xFB, 0xC9,
+0x8D, 0x27, 0xB7, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x40, 0xE1, 0x0C, 0x85, 0x33, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00,
+0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02,
+0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0xCE, 0x50, 0x08, 0x40, 0x21,
+0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0xE1, 0x0C, 0x85, 0x00, 0x14,
+0x02, 0x50, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x01, 0x02,
+0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x21, 0x40, 0x84, 0x00, 0x11, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00,
+0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08,
+0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84,
+0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
+0x0C, 0x80, 0x33, 0x00, 0x02, 0x04, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00,
+0x02, 0x00, 0x08, 0x00, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10,
+0x20, 0x00, 0x80, 0x00, 0x00, 0xCE, 0x00, 0x08, 0x00, 0x20, 0x40, 0x80, 0x00,
+0x00, 0x02, 0x04, 0x08, 0x00, 0xE0, 0x4C, 0x80, 0x00, 0x01, 0x02, 0x00, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0xCC, 0x40, 0x00, 0x10, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x44, 0x00, 0x10, 0x01, 0x00, 0x04, 0x33, 0x10, 0x00, 0x40, 0x00, 0x00, 0xC1,
+0x0C, 0x04, 0x00, 0x10, 0xCC, 0x40, 0x30, 0x03, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0xC1, 0x0C, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00,
+0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04,
+0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44,
+0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0xCC, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x30, 0x13, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02,
+0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21,
+0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15,
+0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50,
+0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02,
+0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
+0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08,
+0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84,
+0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40,
+0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x00, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03,
+0xE0, 0x0C, 0x80, 0x33, 0x00, 0x02, 0x00, 0x38, 0x03, 0x20, 0x00, 0x80, 0x33,
+0x00, 0x02, 0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x08,
+0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80,
+0x00, 0x00, 0xCE, 0x00, 0x38, 0x43, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x00, 0x00, 0x21, 0x00, 0x84, 0x33, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10,
+0xCE, 0x40, 0x08, 0x00, 0xE1, 0x0C, 0x84, 0x00, 0x10, 0xCE, 0x40, 0x38, 0x03,
+0x21, 0x00, 0x84, 0x33, 0x10, 0xCE, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x33,
+0x10, 0x02, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x40, 0x00, 0x00, 0x81, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x02,
+0x10, 0x00, 0x40, 0x20, 0x00, 0x01, 0x00, 0x04, 0x02, 0x10, 0x08, 0x40, 0x00,
+0x00, 0x81, 0x00, 0x04, 0x02, 0x10, 0x00, 0x40, 0x00, 0x00, 0x81, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x84, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x02, 0x40,
+0x00, 0x00, 0x21, 0x00, 0x04, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x01, 0x00,
+0x84, 0x00, 0x10, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x84, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01,
+0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00,
+0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x30, 0x03, 0x00, 0x00, 0x00,
+0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
+0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85,
+0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02, 0x50,
+0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00,
+0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02,
+0x50, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00,
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08,
+0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10,
+0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00,
+0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00,
+0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02,
+0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20,
+0x40, 0x80, 0x00, 0x01, 0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00,
+0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40,
+0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11,
+0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10,
+0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00,
+0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x10, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x00, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0xCE, 0x54,
+0x08, 0x50, 0x21, 0x40, 0x85, 0x33, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40,
+0x85, 0x00, 0x15, 0x02, 0x54, 0x38, 0x53, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02,
+0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21,
+0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x00, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08,
+0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00,
+0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00,
+0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08,
+0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84,
+0x00, 0x10, 0x02, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x00, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03, 0xE0,
+0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80, 0x33, 0x00,
+0x02, 0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03,
+0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03, 0x20, 0x00, 0x80, 0x33,
+0x00, 0xCE, 0x00, 0x38, 0x43, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02,
+0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10,
+0x02, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x80,
+0x40, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x80, 0x40,
+0x40, 0x00, 0x00, 0x0C, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x22, 0x25, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00,
+0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x05, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x87, 0xE8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00
+};
diff --git a/drivers/staging/me4000/me4610_firmware.h b/drivers/staging/me4000/me4610_firmware.h
new file mode 100644
index 00000000000..c550d99286c
--- /dev/null
+++ b/drivers/staging/me4000/me4610_firmware.h
@@ -0,0 +1,5409 @@
+/*
+ This file is copyright by Meilhaus Electronic GmbH 2003.
+ You are not allowed to distribute, sell, modify, reverse engineer or use this
+ code (or parts of it) for any other purpose or under any other conditions
+ than stated below.
+
+ 1) You are allowed to distribute verbatim copies of this file together
+ with device drivers for the Meilhaus ME-4000, board family.
+
+ 2) Derived work (device drivers using this file) can be published 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. Any other license terms have
+ to be agreed by Meilhaus GmbH in written.
+
+ 2) This file is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. Meilhaus is under
+ no means liable for products using this file or parts of it.
+
+ 3) The copyright of this file has to be mentioned in derived work.
+
+ 4) If this license terms are not valid due to any other law
+ or restrictions imposed on you, you are not allowed to use
+ this file in any way at all.
+ */
+
+/* Version 0 of ME-4610 firmware */
+static unsigned char xilinx_firm_4610[] = {
+0x00, 0x01, 0x11, 0x0c, 0x01, 0x01, 0x04, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00,
+0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x99, 0xAA, 0x66, 0x0C, 0x00,
+0x01, 0x80, 0x00, 0x00, 0x00, 0xE0, 0x0C, 0x80, 0x06, 0x80, 0x00, 0x00, 0x00,
+0xD0, 0x0C, 0x80, 0x04, 0x80, 0x00, 0x01, 0xFC, 0xB4, 0x0C, 0x00, 0x03, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x90, 0x0C,
+0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x0C, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x7C, 0x20, 0x40, 0x58, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x40, 0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x58, 0x80, 0x54, 0x00,
+0x44, 0x01, 0x18, 0x05, 0x60, 0x04, 0x80, 0x01, 0x00, 0x66, 0x00, 0xD8, 0x00,
+0x60, 0x0A, 0x80, 0x2D, 0x00, 0xF6, 0x00, 0xD8, 0x03, 0x60, 0x0A, 0x80, 0x69,
+0x00, 0xC6, 0x01, 0x98, 0x05, 0x20, 0x16, 0xFC, 0x23, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0xFF, 0x00, 0xBF, 0x00, 0xDC, 0x32, 0xF0,
+0x13, 0xC0, 0x4F, 0x00, 0xFB, 0x28, 0xBC, 0x04, 0xB0, 0x17, 0xC0, 0x4E, 0x12,
+0x1B, 0x10, 0xFC, 0x13, 0x30, 0x93, 0xC0, 0x4B, 0x00, 0x1F, 0x01, 0xFC, 0x24,
+0x30, 0xCF, 0xE2, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x08, 0x37, 0x01, 0x9D, 0x06, 0x44, 0x30, 0xD1, 0x11, 0x40, 0x47, 0x00,
+0xFD, 0x0A, 0x74, 0x06, 0x10, 0x09, 0x40, 0x17, 0x09, 0x11, 0x42, 0xF4, 0x0B,
+0x50, 0x49, 0x40, 0x06, 0x0C, 0x1D, 0x00, 0x74, 0x00, 0x10, 0x8F, 0x40, 0x04,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x33, 0x00,
+0x8D, 0x18, 0x05, 0x16, 0xDA, 0x08, 0x40, 0x33, 0x00, 0xCD, 0x40, 0x74, 0x03,
+0x91, 0x0C, 0x40, 0x35, 0x01, 0x0D, 0x20, 0x34, 0xA3, 0x10, 0x48, 0x40, 0x01,
+0x01, 0xCD, 0xA0, 0x74, 0x13, 0xD2, 0x4C, 0x40, 0x44, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x34, 0x00, 0x9D, 0x01, 0x44, 0x86,
+0xD0, 0x39, 0x40, 0x07, 0x00, 0xDD, 0x00, 0x64, 0x8A, 0x10, 0x89, 0x02, 0x37,
+0x00, 0x15, 0x10, 0x74, 0x03, 0x50, 0x19, 0x07, 0x47, 0x20, 0x5D, 0x04, 0x74,
+0xA3, 0xDA, 0x0D, 0x48, 0x0C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA8, 0x77, 0x00, 0x1F, 0x91, 0x4C, 0x86, 0xE0, 0x19, 0xC0, 0x57,
+0x21, 0xDB, 0x00, 0x7C, 0x01, 0xB0, 0x05, 0x80, 0x06, 0x91, 0x1B, 0x0B, 0x7C,
+0x03, 0x31, 0x31, 0xC0, 0x47, 0x01, 0x9F, 0x44, 0x7C, 0x02, 0xD0, 0x0D, 0x60,
+0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D,
+0x02, 0x3E, 0x40, 0xE8, 0x00, 0xF0, 0x0B, 0x40, 0x8F, 0x00, 0xFE, 0x00, 0xF4,
+0x48, 0xF0, 0x0B, 0xC0, 0x1F, 0x80, 0x1A, 0x20, 0xBC, 0x03, 0xE1, 0x0B, 0xC8,
+0x0E, 0x00, 0x3E, 0x01, 0xF8, 0x02, 0x30, 0x0F, 0xD1, 0x1F, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0x9F, 0x00, 0x5C,
+0x46, 0x70, 0x09, 0xC0, 0x37, 0x00, 0xDF, 0x20, 0x7C, 0x21, 0x30, 0x0D, 0xC4,
+0x34, 0x00, 0xDF, 0x00, 0x4C, 0x83, 0xB0, 0x29, 0xC0, 0x84, 0x08, 0x9F, 0x44,
+0x7C, 0x43, 0xF0, 0x0C, 0xC4, 0x0A, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0x9D, 0x00, 0x74, 0x0A, 0x90, 0x09, 0x40,
+0x67, 0x00, 0xF0, 0x80, 0x34, 0x04, 0xB0, 0xB9, 0x40, 0x32, 0x00, 0xD1, 0x41,
+0xC0, 0x03, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x51, 0x00, 0x34, 0x43, 0xD0, 0x3F,
+0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0,
+0x32, 0x10, 0x1D, 0x40, 0x30, 0x00, 0x90, 0x10, 0x40, 0xA3, 0x84, 0xC9, 0x00,
+0x34, 0x00, 0x10, 0x08, 0x40, 0x20, 0x00, 0xC0, 0x21, 0x00, 0x03, 0x90, 0x00,
+0x40, 0x00, 0x00, 0x49, 0x83, 0x04, 0x89, 0xD8, 0x0C, 0x40, 0x1C, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x82, 0x78, 0x02, 0xEC, 0x81,
+0xB4, 0x05, 0x9A, 0x92, 0x60, 0x4B, 0x90, 0xE1, 0xA9, 0xB6, 0x06, 0x90, 0x1A,
+0x60, 0x7A, 0x00, 0xE1, 0x13, 0xA4, 0x07, 0xC0, 0x12, 0x40, 0x4F, 0x00, 0x61,
+0x35, 0xB4, 0x25, 0xC0, 0x9F, 0x61, 0x18, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x10, 0x4D, 0x00, 0x1C, 0xA1, 0x78, 0x80,
+0xE1, 0x33, 0x25, 0xCF, 0x20, 0x3C, 0x23, 0x30, 0x2C, 0xC1, 0x34, 0x08, 0x07,
+0x05, 0x0D, 0x03, 0xB0, 0xC0, 0xE8, 0x10, 0x22, 0xCF, 0x41, 0x3C, 0x17, 0xF2,
+0xDD, 0xD0, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xB2, 0x3D, 0x08, 0xFF, 0x00, 0xFE, 0xA3, 0x80, 0x8F, 0xC2, 0x1B, 0x00, 0xFF,
+0x80, 0xFE, 0x03, 0xF0, 0x0B, 0x40, 0x3F, 0x10, 0x37, 0x08, 0xDC, 0x63, 0xF0,
+0x87, 0xC6, 0x3F, 0x08, 0xDF, 0x00, 0x7C, 0x23, 0xFA, 0x8F, 0xC2, 0x09, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x77, 0x00, 0x57,
+0x00, 0x7C, 0x03, 0xF0, 0x11, 0xC0, 0x35, 0x00, 0xDF, 0x10, 0x5C, 0x01, 0xF0,
+0x18, 0xC0, 0x66, 0x00, 0xD3, 0x00, 0x6C, 0x13, 0xF0, 0x01, 0xC8, 0x17, 0x10,
+0x9F, 0x00, 0x7C, 0x03, 0x32, 0xBD, 0xC5, 0x54, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x98, 0x3D, 0x00, 0x61, 0x80, 0xB6, 0x01, 0xD0,
+0x0A, 0x48, 0x38, 0x00, 0xFD, 0x06, 0x84, 0x03, 0xD2, 0x0A, 0x40, 0x39, 0x40,
+0xF1, 0x80, 0x86, 0x43, 0xD0, 0x0A, 0x48, 0x1B, 0x00, 0xED, 0x00, 0xB4, 0x03,
+0x10, 0x0F, 0x40, 0x48, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x00, 0x79, 0x80, 0xE5, 0x01, 0x94, 0x07, 0xD0, 0x17, 0x40, 0x79, 0x08,
+0xEC, 0x01, 0x94, 0x07, 0xD0, 0x1F, 0x40, 0x7B, 0x00, 0xE1, 0x01, 0x84, 0x07,
+0xD0, 0x1E, 0x60, 0x79, 0x00, 0xAD, 0x11, 0xA4, 0x07, 0x50, 0x1E, 0x40, 0x0C,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x23, 0x00,
+0xC1, 0x00, 0x34, 0x03, 0xD0, 0x0C, 0x42, 0x31, 0x02, 0xCD, 0x00, 0x14, 0x4B,
+0xD1, 0x08, 0x40, 0x31, 0x00, 0xC1, 0x0D, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x73,
+0x01, 0xCD, 0x80, 0x74, 0x0B, 0x50, 0x0C, 0x40, 0x48, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x14, 0x01, 0x77, 0x03, 0xFC, 0x29,
+0xD0, 0x17, 0xC1, 0x5D, 0x00, 0x5F, 0x00, 0x9C, 0x19, 0xD0, 0x07, 0xC0, 0x1E,
+0x00, 0x73, 0x02, 0x4C, 0x01, 0xF0, 0x47, 0xC0, 0x1F, 0x8C, 0x7F, 0x00, 0xFC,
+0x09, 0x72, 0x05, 0x40, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x08, 0x7C, 0x00, 0xD0, 0x11, 0x40, 0x46,
+0x00, 0x0E, 0x40, 0x68, 0x00, 0xF0, 0x01, 0xC0, 0x06, 0x00, 0x1F, 0x42, 0x5C,
+0x00, 0xB2, 0x11, 0xC0, 0x07, 0x00, 0x1B, 0x10, 0x7C, 0x10, 0x82, 0x01, 0xC0,
+0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x27,
+0x00, 0x8F, 0x10, 0x54, 0x0A, 0xF2, 0x09, 0x40, 0x27, 0x00, 0x9B, 0x00, 0x4C,
+0x06, 0xD0, 0x99, 0xC0, 0x27, 0x00, 0x8F, 0x04, 0x5C, 0x82, 0xE0, 0x09, 0xC0,
+0x27, 0x00, 0x97, 0x00, 0x7C, 0x02, 0x30, 0x89, 0xC2, 0x43, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x10, 0x9C, 0x00, 0x54,
+0x02, 0xD0, 0xB9, 0x40, 0xE7, 0x00, 0x9D, 0x00, 0x44, 0x6A, 0x10, 0x19, 0x04,
+0x27, 0x00, 0x9D, 0x02, 0x45, 0x02, 0xC2, 0x09, 0x40, 0x27, 0x00, 0x90, 0x13,
+0x74, 0x22, 0x10, 0x59, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x90, 0x09, 0x40,
+0xE7, 0x00, 0x9D, 0x80, 0x45, 0x02, 0x90, 0x09, 0x41, 0x26, 0x00, 0x9D, 0x02,
+0x44, 0x82, 0x90, 0x09, 0x40, 0x23, 0x00, 0x91, 0x01, 0x74, 0x02, 0x10, 0x09,
+0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x20, 0x02, 0x8D, 0x14, 0x14, 0x56, 0xD0, 0x0C, 0x40, 0x23, 0x08, 0x8D, 0x00,
+0x04, 0x02, 0x10, 0x08, 0x40, 0x23, 0x02, 0x8D, 0x00, 0x04, 0x02, 0xD0, 0x88,
+0x00, 0x23, 0x02, 0x81, 0x00, 0x30, 0x02, 0x14, 0x48, 0x49, 0x43, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x86, 0x00, 0x1F, 0x24,
+0x4C, 0x10, 0xF0, 0x01, 0xC0, 0x07, 0x10, 0x1E, 0x14, 0x4C, 0x00, 0xB0, 0xA1,
+0xC2, 0x83, 0x00, 0x1F, 0x1E, 0x4C, 0x78, 0xF0, 0x21, 0xC0, 0x87, 0x00, 0x17,
+0x0A, 0x3C, 0x81, 0x30, 0x41, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x19, 0xB0, 0x2F, 0x01, 0xBF, 0x94, 0xFC, 0x52, 0xF2, 0x0A,
+0xC8, 0x2F, 0x00, 0x9C, 0x14, 0xFC, 0x02, 0xB0, 0x1F, 0x80, 0x2F, 0x01, 0xBF,
+0x81, 0x70, 0x06, 0xF1, 0x4F, 0xC0, 0x2F, 0x41, 0xBF, 0x01, 0xFC, 0x53, 0xF0,
+0x49, 0x41, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+0x80, 0x23, 0x00, 0x97, 0x08, 0xF0, 0x37, 0x30, 0x0A, 0xC0, 0x2F, 0x20, 0x9F,
+0x0C, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0xA2, 0x00, 0xBF, 0x10, 0x4C, 0x02, 0xF0,
+0x29, 0xC0, 0x25, 0x02, 0xB3, 0x00, 0xFC, 0x02, 0x30, 0x0B, 0xC0, 0x64, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x01, 0x01,
+0x05, 0x74, 0x3D, 0xB0, 0x01, 0x40, 0x17, 0x00, 0x1D, 0x01, 0x74, 0x01, 0xD1,
+0x01, 0x40, 0x04, 0x00, 0x0D, 0x02, 0x51, 0x28, 0x91, 0x01, 0x40, 0x14, 0x11,
+0x11, 0x00, 0x74, 0x00, 0x10, 0x01, 0x48, 0x71, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x04, 0x85, 0x42, 0x34, 0x02, 0x59,
+0x08, 0x40, 0x23, 0x08, 0x8D, 0x02, 0x34, 0x02, 0xD0, 0x09, 0x42, 0x22, 0x10,
+0x8D, 0x00, 0x16, 0x82, 0xD0, 0x09, 0x40, 0x21, 0x00, 0xC5, 0x20, 0x74, 0x02,
+0x11, 0x08, 0x50, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0xA8, 0x21, 0x00, 0x91, 0x04, 0x74, 0x03, 0xD0, 0x39, 0x60, 0x27, 0x08,
+0x9D, 0x00, 0x74, 0x02, 0xD0, 0x8D, 0x42, 0x24, 0x00, 0x9D, 0x00, 0x54, 0x02,
+0xD0, 0x09, 0x40, 0x24, 0x40, 0x95, 0x04, 0x74, 0x02, 0x52, 0x09, 0x40, 0x61,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x25, 0x08,
+0x97, 0x93, 0x78, 0x0A, 0x74, 0x19, 0xC0, 0xE7, 0x00, 0x9F, 0x00, 0x7C, 0x0A,
+0xF0, 0x08, 0xC8, 0xE6, 0x01, 0x9F, 0xB8, 0x5C, 0x02, 0xF0, 0x28, 0xC2, 0x25,
+0x00, 0x97, 0x04, 0x3C, 0x0E, 0x20, 0x09, 0xC4, 0x14, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0x64, 0x02, 0x9F, 0x00, 0x3C, 0x16,
+0xB0, 0x09, 0xC4, 0xE7, 0x00, 0x9F, 0x80, 0x7C, 0x26, 0xF0, 0x09, 0xC0, 0x27,
+0x01, 0x9F, 0x01, 0x68, 0x02, 0xB0, 0x29, 0xC4, 0x27, 0x01, 0x9B, 0x00, 0x7C,
+0x0E, 0xB4, 0x08, 0x40, 0x52, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x08, 0x05, 0x00, 0x13, 0x02, 0x4C, 0x08, 0xF0, 0x61, 0xC0, 0x07,
+0x00, 0x17, 0x00, 0x4C, 0x40, 0xF0, 0x21, 0x40, 0x04, 0x00, 0x03, 0x42, 0x5C,
+0x00, 0x30, 0x21, 0xC0, 0x87, 0x10, 0x1F, 0x00, 0x4C, 0x08, 0xF0, 0x01, 0xD1,
+0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x14,
+0x00, 0x51, 0x00, 0xC4, 0x0D, 0xD0, 0x37, 0x40, 0x1C, 0x02, 0x51, 0x20, 0xCC,
+0x41, 0xD2, 0x07, 0x48, 0x14, 0x00, 0x71, 0x49, 0x44, 0x81, 0x50, 0x05, 0x40,
+0x17, 0x00, 0x7C, 0x82, 0xC4, 0x69, 0xD0, 0x07, 0x40, 0x50, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x60, 0xC1, 0x40, 0x14,
+0xCF, 0xC0, 0xB4, 0x40, 0x72, 0x02, 0xC5, 0x00, 0x24, 0x03, 0xD0, 0x8C, 0x40,
+0x30, 0x10, 0xC1, 0x0B, 0x24, 0x03, 0x10, 0x0C, 0x40, 0x37, 0x00, 0xC9, 0x04,
+0x04, 0x80, 0xD0, 0x30, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x82, 0x3C, 0x22, 0xE1, 0x0D, 0x94, 0x43, 0xD0, 0x12, 0x40,
+0x7E, 0x00, 0xC1, 0x01, 0x84, 0x01, 0xD0, 0x0E, 0x40, 0x7C, 0x43, 0x61, 0x00,
+0xA4, 0x27, 0x50, 0x0E, 0x40, 0x3B, 0x10, 0xAD, 0x21, 0x84, 0x01, 0xD0, 0x23,
+0x44, 0x10, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10,
+0x78, 0x01, 0xE3, 0x91, 0x9D, 0x07, 0xF0, 0x16, 0xC0, 0x4A, 0x00, 0xE7, 0x01,
+0xAD, 0x07, 0xE1, 0x13, 0xC0, 0x78, 0x02, 0xA3, 0x61, 0xFC, 0x37, 0x30, 0x5E,
+0xC1, 0x7B, 0x00, 0xBB, 0x01, 0x8C, 0x06, 0xFA, 0x1B, 0xC0, 0x50, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB0, 0x35, 0x04, 0xDF, 0x40,
+0x6C, 0x03, 0xF3, 0x01, 0xC0, 0x00, 0x20, 0xDF, 0x00, 0x7C, 0x01, 0xD0, 0x05,
+0x90, 0x37, 0x01, 0x1F, 0x00, 0x5C, 0x93, 0xF1, 0xAD, 0x80, 0xB7, 0x03, 0x9C,
+0x40, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA0, 0x7F, 0x00, 0xFF, 0x01, 0xDC, 0x25, 0x30, 0x1F,
+0xC0, 0x7F, 0x00, 0xF7, 0x11, 0xFC, 0x26, 0x10, 0x1F, 0xC0, 0x7F, 0x10, 0x7F,
+0x09, 0xCC, 0x87, 0x30, 0x9F, 0xC0, 0xFC, 0x8A, 0xBF, 0x0D, 0xEC, 0x24, 0xF1,
+0x17, 0xC0, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x88, 0x39, 0x24, 0xED, 0x00, 0xF4, 0x03, 0xB0, 0x4A, 0x48, 0x0B, 0x00, 0xED,
+0x04, 0xB4, 0x21, 0x10, 0x4E, 0x42, 0x7B, 0x01, 0x29, 0x01, 0x84, 0x03, 0xF0,
+0x0E, 0x44, 0x38, 0x00, 0x8D, 0x43, 0x34, 0x21, 0xD0, 0x84, 0x40, 0x57, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x39, 0x00, 0xED,
+0x10, 0x94, 0x01, 0x98, 0x02, 0x40, 0x0B, 0x04, 0xED, 0x80, 0xF4, 0x00, 0x90,
+0x02, 0x41, 0x3B, 0x01, 0x0D, 0x08, 0x94, 0x03, 0x10, 0x0E, 0x48, 0x38, 0x20,
+0x25, 0x02, 0xB4, 0x20, 0xD8, 0x0E, 0x40, 0x23, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x33, 0x00, 0xCD, 0x01, 0x74, 0x42, 0x90,
+0x00, 0x40, 0x03, 0x00, 0xCD, 0x00, 0x34, 0x2D, 0x90, 0x10, 0x40, 0x37, 0x00,
+0x19, 0x00, 0x14, 0x03, 0xD0, 0x2D, 0x40, 0xB0, 0x00, 0x0D, 0x08, 0x34, 0x03,
+0xD0, 0x0C, 0x40, 0x1B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x88, 0x3D, 0x00, 0xFF, 0x01, 0x5C, 0x02, 0xB0, 0xA5, 0xC0, 0x27, 0x90,
+0xF7, 0x00, 0x7C, 0x27, 0xB6, 0xB9, 0xC8, 0x3F, 0x00, 0x9F, 0x20, 0xDC, 0x03,
+0x30, 0xAF, 0xC8, 0x3C, 0x08, 0x8F, 0x01, 0x6C, 0x83, 0xD0, 0x0D, 0xC8, 0x57,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00,
+0xDF, 0x10, 0x7C, 0x28, 0xF0, 0x15, 0xC0, 0xA7, 0x00, 0xDF, 0x00, 0x7C, 0x03,
+0x70, 0x21, 0xC0, 0x77, 0x00, 0x1E, 0x42, 0x25, 0x83, 0xB0, 0x8D, 0xC0, 0x37,
+0x00, 0x1D, 0x02, 0x7C, 0x03, 0xD0, 0x0D, 0xC4, 0x27, 0x00, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x08, 0x3F, 0x28, 0xFB, 0x40, 0xFC, 0x02,
+0x30, 0x37, 0xC0, 0x2F, 0x04, 0xFF, 0x00, 0xFC, 0x16, 0xF0, 0x03, 0xC0, 0x3F,
+0x00, 0x33, 0x00, 0xCC, 0x03, 0x71, 0x0F, 0xE0, 0x3C, 0x0C, 0xBF, 0x20, 0xDC,
+0x03, 0xF2, 0x0B, 0xC2, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA1, 0x00, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x06, 0xB0, 0x05, 0xC0, 0xE7,
+0x00, 0xDD, 0x00, 0x74, 0x0A, 0xD0, 0x11, 0x40, 0x36, 0x00, 0x1B, 0x00, 0x6C,
+0x03, 0x10, 0x0D, 0x40, 0x35, 0x00, 0x1C, 0x03, 0x40, 0x04, 0xD0, 0x35, 0x40,
+0x84, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34,
+0x00, 0xDD, 0x00, 0x74, 0x04, 0x18, 0x0D, 0x40, 0x67, 0x04, 0xDD, 0x00, 0x64,
+0x0A, 0xD0, 0x1B, 0x40, 0x37, 0x00, 0x31, 0x06, 0xC0, 0x03, 0x00, 0x0D, 0x44,
+0x36, 0x00, 0xBD, 0x01, 0x44, 0xA3, 0xD0, 0x64, 0x50, 0x04, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x80, 0xCD, 0x00, 0x36,
+0x00, 0x18, 0x0C, 0x40, 0x01, 0x00, 0xCD, 0x00, 0x34, 0x03, 0xD1, 0x00, 0x42,
+0x36, 0x21, 0x19, 0x24, 0x24, 0x03, 0x15, 0x0C, 0x40, 0x30, 0x00, 0x1D, 0x04,
+0x04, 0xA6, 0xD0, 0x28, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0xB0, 0x3E, 0x08, 0xFB, 0x80, 0x7C, 0x00, 0x14, 0x01, 0x40,
+0x27, 0x08, 0xDF, 0x00, 0x6C, 0x00, 0xF0, 0x01, 0xC2, 0x3F, 0x05, 0x13, 0x16,
+0x8C, 0x03, 0x70, 0x0E, 0xD0, 0x3C, 0x10, 0x1F, 0x1C, 0x5C, 0x01, 0xF0, 0x21,
+0xC0, 0x04, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB0,
+0x3F, 0x00, 0xFF, 0x40, 0xFC, 0x02, 0xF2, 0x03, 0xC0, 0x0F, 0x00, 0xFF, 0x40,
+0xBC, 0x00, 0xF0, 0x03, 0xC0, 0x36, 0x00, 0x1F, 0x14, 0xFC, 0x03, 0xF0, 0x0F,
+0xC4, 0x3F, 0x00, 0x1F, 0x04, 0xFD, 0x10, 0xF2, 0x43, 0x00, 0x17, 0x60, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7D, 0x02, 0xFA, 0x00,
+0xFC, 0x20, 0xB0, 0x0F, 0xC0, 0x3F, 0x20, 0xF7, 0xA0, 0xEC, 0x03, 0x30, 0x4F,
+0xC4, 0x0D, 0x10, 0x33, 0x01, 0xFC, 0x27, 0xF1, 0x33, 0xC0, 0x3E, 0x00, 0x2F,
+0x01, 0x6C, 0x80, 0xF2, 0x03, 0xC4, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x08, 0x37, 0x20, 0xF1, 0x82, 0x34, 0x3A, 0x10, 0x3F,
+0x40, 0xBE, 0x16, 0xF1, 0x89, 0xF4, 0x0F, 0x10, 0x9F, 0xC8, 0x45, 0x32, 0x95,
+0x00, 0x74, 0x11, 0xD1, 0x41, 0x40, 0x3F, 0x20, 0x1D, 0x54, 0x44, 0x04, 0xD0,
+0x01, 0x40, 0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+0x20, 0x33, 0x11, 0xC1, 0x36, 0x74, 0x03, 0x11, 0x2C, 0x44, 0x33, 0x01, 0xC5,
+0x80, 0x34, 0x23, 0x10, 0x0C, 0x40, 0x03, 0x00, 0x01, 0x00, 0x34, 0x13, 0x90,
+0x00, 0x40, 0x32, 0x00, 0xCD, 0x00, 0x24, 0x80, 0xD8, 0x00, 0x40, 0x47, 0x80,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x75, 0x20, 0xD1,
+0x00, 0x74, 0x07, 0x10, 0x0D, 0x40, 0x36, 0x20, 0xD1, 0x00, 0x74, 0x83, 0x10,
+0x0D, 0x40, 0x97, 0x00, 0x94, 0x04, 0x74, 0x21, 0xD0, 0x11, 0x43, 0x3F, 0x00,
+0x1D, 0x10, 0xC0, 0x60, 0xC0, 0x3B, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x40, 0xDB, 0x00, 0x3C, 0x06, 0xB4,
+0x0D, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x6E, 0x03, 0x30, 0x0D, 0xC0, 0x83, 0x00,
+0xD3, 0x80, 0x7C, 0x97, 0xF0, 0x11, 0xC8, 0x36, 0x00, 0xDF, 0x00, 0x6C, 0x00,
+0xF1, 0x31, 0xC0, 0x0B, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x07, 0x80, 0x3D, 0x00, 0xFF, 0x80, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F, 0x20,
+0xDF, 0x00, 0xFA, 0x43, 0xF0, 0x0D, 0xC2, 0x4D, 0x01, 0xFF, 0x01, 0xFC, 0x01,
+0xF0, 0x03, 0xC0, 0x3F, 0x00, 0x3F, 0x09, 0xFC, 0x00, 0xF0, 0x03, 0x40, 0x1F,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x01,
+0xDF, 0x08, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x33, 0x00, 0xDF, 0x40, 0x3C, 0x03,
+0xF0, 0x0D, 0xC0, 0x27, 0x08, 0xDB, 0x00, 0x7C, 0x03, 0x30, 0x21, 0xC0, 0x37,
+0x04, 0xDF, 0x02, 0x4C, 0x00, 0xF0, 0x09, 0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0xF4, 0x09, 0xFD, 0xC1, 0x74, 0x83,
+0x50, 0x3F, 0x44, 0x3F, 0x00, 0xFC, 0x0A, 0xC4, 0x8F, 0xD0, 0x0F, 0x41, 0x34,
+0x00, 0xDD, 0x01, 0x74, 0x81, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x1C, 0x00, 0x44,
+0x12, 0xD0, 0x39, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0xA0, 0x76, 0x00, 0xC9, 0x47, 0x34, 0x03, 0x18, 0x0C, 0x49, 0x33,
+0x00, 0xCD, 0x03, 0x04, 0x2F, 0xD0, 0x5C, 0x40, 0x31, 0x00, 0x49, 0x00, 0x34,
+0x02, 0x10, 0x00, 0x40, 0xF3, 0x00, 0x1D, 0x00, 0x14, 0x04, 0xD0, 0x00, 0x01,
+0x1F, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78,
+0x00, 0xED, 0x01, 0xB4, 0x27, 0x50, 0x9E, 0x40, 0x7B, 0x00, 0xED, 0x35, 0x85,
+0x07, 0xD0, 0x5E, 0x40, 0x69, 0x80, 0xED, 0x03, 0xF4, 0x06, 0x90, 0x92, 0x02,
+0x7B, 0x00, 0x3D, 0x01, 0x96, 0x24, 0xD0, 0x9A, 0x48, 0x13, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x02, 0xCF, 0x08, 0x3C,
+0x03, 0x3A, 0x0C, 0xC1, 0x33, 0x00, 0xCF, 0x0D, 0x2C, 0x03, 0xF0, 0x5C, 0xC0,
+0x11, 0x00, 0x4B, 0x10, 0x3C, 0x06, 0x30, 0x00, 0xC2, 0x33, 0x06, 0xCF, 0x00,
+0x1C, 0x14, 0xF0, 0x00, 0xC1, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xB8, 0x3D, 0x00, 0xFE, 0x00, 0xF8, 0x03, 0xF8, 0x0F, 0xC9,
+0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC1, 0x1C, 0x00, 0xFF, 0x08,
+0x3C, 0x02, 0x75, 0x07, 0xC6, 0x3F, 0x00, 0xFF, 0x00, 0xED, 0x20, 0xF0, 0x0B,
+0xE8, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0,
+0x37, 0x10, 0xDE, 0x44, 0x7C, 0x03, 0x30, 0x5D, 0xC2, 0x34, 0x11, 0xD3, 0x04,
+0x7C, 0x0B, 0xF3, 0x3D, 0xD1, 0x34, 0x00, 0xD3, 0x01, 0x4C, 0x03, 0xF0, 0x01,
+0xD0, 0xB4, 0x07, 0xCE, 0x00, 0x4C, 0x04, 0x32, 0x19, 0xC0, 0x54, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x38, 0x00, 0xED, 0x96,
+0xF4, 0x03, 0xB0, 0x0C, 0x55, 0x38, 0x14, 0xE1, 0x16, 0xB4, 0x5B, 0xD0, 0x4C,
+0x40, 0x20, 0x10, 0xF1, 0x80, 0x84, 0x03, 0xD0, 0x02, 0x40, 0x38, 0x01, 0xED,
+0x00, 0x84, 0x02, 0x11, 0x0B, 0xC0, 0x4A, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x00, 0x78, 0x00, 0xED, 0x01, 0xB4, 0x07, 0x10, 0x1E,
+0x4A, 0x70, 0x13, 0xE1, 0x01, 0xA4, 0x07, 0xD0, 0x5E, 0x40, 0x78, 0x40, 0xE1,
+0x01, 0x84, 0x07, 0xD0, 0x16, 0x43, 0x78, 0x81, 0xFD, 0x01, 0x04, 0x84, 0x18,
+0x1A, 0x40, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x28, 0x23, 0x02, 0xDD, 0x00, 0x34, 0x03, 0x92, 0x0C, 0x40, 0x30, 0x40, 0xC1,
+0x20, 0x34, 0x03, 0xD0, 0x0C, 0x48, 0x30, 0x04, 0xC1, 0x08, 0x04, 0x07, 0xD0,
+0x2C, 0x41, 0x30, 0x00, 0xDD, 0x10, 0x04, 0x0F, 0x18, 0x3C, 0x40, 0x4A, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x55, 0x00, 0x5F,
+0x80, 0xFC, 0x29, 0x30, 0x05, 0xC0, 0x14, 0x00, 0x43, 0x00, 0x7C, 0x01, 0xF0,
+0x05, 0x82, 0x1C, 0x00, 0x73, 0x03, 0xCD, 0x15, 0xF0, 0x37, 0xC0, 0x14, 0x00,
+0x7F, 0x12, 0xCC, 0x15, 0x30, 0x17, 0xC0, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x20, 0x7C, 0x00, 0xF0,
+0x01, 0xC0, 0x07, 0x08, 0x1F, 0x02, 0x7C, 0x00, 0xF0, 0x01, 0xC8, 0x87, 0x00,
+0x1F, 0x10, 0x7C, 0x80, 0xF3, 0x01, 0xC0, 0x07, 0x30, 0x1F, 0x00, 0x7D, 0x10,
+0xF1, 0x81, 0xC1, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x67, 0x00, 0x93, 0x00, 0x4C, 0x02, 0x70, 0x19, 0xC0, 0x27, 0x00,
+0x97, 0x01, 0x5C, 0x26, 0xF0, 0x19, 0xC0, 0x23, 0x00, 0x90, 0x80, 0x7C, 0x02,
+0x30, 0x09, 0xC0, 0xA4, 0x00, 0x9F, 0x05, 0x4C, 0x12, 0xF0, 0x29, 0xC0, 0x43,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xE2, 0x22,
+0x91, 0x00, 0x14, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x91, 0x03, 0x44, 0x8A,
+0xD0, 0x99, 0x44, 0x27, 0x02, 0x91, 0x02, 0x74, 0x82, 0x12, 0x08, 0x42, 0x24,
+0x00, 0x9D, 0x01, 0x44, 0x02, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x44, 0x91, 0x21, 0x54, 0x03,
+0x50, 0x49, 0x41, 0x23, 0x00, 0x95, 0x86, 0x54, 0x0A, 0xD1, 0x09, 0x40, 0x27,
+0x00, 0x95, 0x01, 0x34, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x44,
+0x02, 0xD0, 0x09, 0x41, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x20, 0x24, 0x00, 0xC1, 0x00, 0x54, 0x52, 0x54, 0x08, 0x40, 0x23,
+0x02, 0x81, 0x80, 0x00, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x40, 0x85, 0x01, 0x34,
+0x22, 0x10, 0x89, 0x42, 0x60, 0x01, 0x8D, 0x08, 0x04, 0x12, 0xD0, 0x48, 0x48,
+0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06,
+0x00, 0x13, 0x94, 0x5C, 0x10, 0x74, 0x41, 0xC1, 0x87, 0x05, 0x16, 0x94, 0x5C,
+0x50, 0xF1, 0x45, 0xC1, 0x17, 0x05, 0x17, 0x0A, 0x7C, 0x08, 0x34, 0x20, 0xC0,
+0xC4, 0x02, 0x1F, 0x02, 0x4D, 0x04, 0xF0, 0xB1, 0xC0, 0x77, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x2F, 0x05, 0x9F, 0x34, 0xFC,
+0x52, 0xB0, 0x09, 0xC2, 0x27, 0x01, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0,
+0x2F, 0x00, 0xBB, 0x01, 0xFC, 0x12, 0xF0, 0x4B, 0xD0, 0x67, 0x02, 0xBF, 0x04,
+0xFC, 0x22, 0xF0, 0x9B, 0xC2, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x2F, 0x02, 0xBF, 0x86, 0x0C, 0x16, 0xB0, 0x4B, 0xC0,
+0x27, 0x05, 0xBB, 0x00, 0xDC, 0x82, 0x30, 0x0B, 0xC0, 0x2D, 0x00, 0xBF, 0xC0,
+0x7C, 0x22, 0x30, 0x29, 0xC0, 0x2F, 0x00, 0xB1, 0x02, 0xCC, 0x02, 0xE0, 0x0B,
+0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08,
+0x47, 0x01, 0x1D, 0x01, 0x44, 0x5C, 0x10, 0x01, 0x40, 0x87, 0x01, 0x1D, 0x00,
+0x44, 0x00, 0x14, 0xA1, 0x40, 0x04, 0x00, 0x0D, 0x00, 0x74, 0x00, 0x10, 0x01,
+0x40, 0x07, 0x00, 0x15, 0x04, 0x45, 0x00, 0xD2, 0x01, 0x48, 0x70, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x06,
+0x04, 0x22, 0x92, 0x28, 0x40, 0x23, 0x04, 0x8D, 0x22, 0x04, 0x8A, 0x10, 0x08,
+0x50, 0xA0, 0x00, 0x8D, 0x00, 0x34, 0x12, 0x10, 0x08, 0x60, 0x23, 0x10, 0x81,
+0x20, 0x05, 0x83, 0xD0, 0x09, 0x60, 0x42, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x80, 0x9D, 0x00, 0x45, 0x02, 0x10, 0x09,
+0x60, 0x27, 0x00, 0x9D, 0x00, 0x47, 0x02, 0x10, 0x09, 0x00, 0x24, 0x01, 0x9D,
+0x00, 0x74, 0x02, 0x10, 0xA9, 0x40, 0x27, 0x00, 0x95, 0x14, 0x45, 0x0E, 0xD1,
+0x69, 0x40, 0x62, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0x88, 0x67, 0x02, 0x9F, 0x00, 0x4C, 0x36, 0xB0, 0x09, 0xC8, 0x27, 0x00, 0x9B,
+0x40, 0x5C, 0x02, 0x12, 0x09, 0xC0, 0x24, 0x01, 0x9E, 0x00, 0x7C, 0x02, 0x34,
+0x29, 0xC0, 0x27, 0x00, 0x83, 0x01, 0x4C, 0x0E, 0xF2, 0x29, 0xD0, 0x16, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x65, 0x10, 0x9F,
+0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x50, 0x3C, 0x02, 0xF0,
+0x09, 0xC0, 0x26, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00,
+0x9F, 0x01, 0x7D, 0x02, 0xF0, 0x09, 0xC0, 0x51, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x04, 0x00, 0x03, 0x00, 0x4D, 0x00, 0x50,
+0x01, 0xC0, 0x05, 0x00, 0x03, 0x08, 0x7C, 0x00, 0xF0, 0x01, 0xC1, 0x87, 0x01,
+0x13, 0x00, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x01, 0x01, 0x13, 0x02, 0x4C, 0x00,
+0x30, 0x21, 0xC1, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0xA0, 0xDC, 0x00, 0x75, 0x19, 0x44, 0x01, 0x50, 0x27, 0xC0, 0x16, 0x50,
+0x71, 0x23, 0xF4, 0x21, 0xD0, 0x06, 0x41, 0x1F, 0x20, 0x75, 0x01, 0x44, 0x01,
+0xD0, 0x05, 0x48, 0x1F, 0x18, 0x75, 0x0A, 0x44, 0x01, 0x11, 0x27, 0xC0, 0x52,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x72, 0x81,
+0xC9, 0x03, 0x04, 0x03, 0x10, 0x9C, 0x41, 0x33, 0x00, 0x81, 0x03, 0x34, 0x2B,
+0xD0, 0x2C, 0x40, 0x33, 0x00, 0xC5, 0x11, 0x44, 0x03, 0xD0, 0x0C, 0x40, 0xF1,
+0x80, 0xC9, 0x01, 0x04, 0x03, 0x12, 0x8D, 0x40, 0x52, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x78, 0x04, 0xED, 0x20, 0xC4, 0x03,
+0x50, 0x1A, 0x40, 0x7A, 0x00, 0xE1, 0x00, 0xB0, 0x01, 0xD0, 0x0E, 0x40, 0x7B,
+0x48, 0xE5, 0x11, 0x84, 0x23, 0xC0, 0x8E, 0x40, 0x13, 0x04, 0xED, 0x10, 0xC4,
+0x07, 0x1C, 0x0B, 0x40, 0x16, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x10, 0x7C, 0x00, 0xFB, 0x81, 0x8C, 0x47, 0x74, 0x1E, 0xC0, 0x73,
+0x01, 0xA3, 0x01, 0xBC, 0x06, 0xF0, 0x1E, 0xC0, 0x7B, 0x00, 0x67, 0x81, 0x84,
+0xD7, 0xF0, 0x1E, 0xC1, 0x69, 0x20, 0xBB, 0x01, 0x8D, 0x07, 0x30, 0x1B, 0xC0,
+0x56, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15,
+0x00, 0xD7, 0x00, 0x7C, 0x33, 0xF0, 0x00, 0xC0, 0xB5, 0x20, 0x9F, 0x00, 0x7C,
+0x00, 0xF1, 0x09, 0xC0, 0x33, 0x00, 0x1B, 0x00, 0x75, 0x03, 0xF2, 0x6D, 0xC0,
+0x07, 0x00, 0x97, 0x00, 0x3C, 0x02, 0xF1, 0x01, 0xC0, 0x43, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x5F, 0x00, 0x7F, 0x01, 0xFC,
+0x07, 0x70, 0x1F, 0xC0, 0xFF, 0x44, 0xB3, 0x09, 0x9C, 0x27, 0x70, 0x9F, 0xC0,
+0x7F, 0x00, 0xA3, 0x41, 0xEC, 0x07, 0x31, 0x1D, 0xC0, 0x4F, 0x00, 0xF3, 0x01,
+0xCC, 0x07, 0x30, 0x9B, 0xC0, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x88, 0xB9, 0x00, 0x6D, 0x02, 0xB4, 0x03, 0xB0, 0x0A, 0x60,
+0x3B, 0x00, 0xC1, 0x08, 0xB4, 0x82, 0x10, 0x04, 0x48, 0x3B, 0x00, 0x21, 0x00,
+0x04, 0x37, 0x10, 0x1E, 0xC0, 0x0F, 0x00, 0xFB, 0x18, 0xC4, 0x23, 0xB2, 0xCA,
+0x50, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0x00, 0x6D, 0x08, 0xF4, 0x03, 0x50, 0x0A, 0x40, 0x39, 0x00, 0xA9, 0x80,
+0x94, 0x02, 0x50, 0x0E, 0x60, 0x1B, 0x02, 0x39, 0x00, 0xC4, 0x13, 0x10, 0x0E,
+0x41, 0x0B, 0x00, 0xB1, 0x00, 0xC4, 0x43, 0x50, 0x0A, 0x40, 0x01, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x43, 0x20, 0x0D, 0x80,
+0x34, 0x03, 0x90, 0x00, 0x40, 0x37, 0x08, 0x49, 0x40, 0x34, 0x02, 0x10, 0x00,
+0x44, 0x53, 0x42, 0x09, 0x02, 0x04, 0x03, 0x94, 0x1D, 0x40, 0x01, 0x00, 0x89,
+0x10, 0x04, 0x06, 0xD8, 0x60, 0x40, 0x11, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA8, 0x64, 0x01, 0x9F, 0x00, 0xFC, 0x03, 0x74, 0x01,
+0xC0, 0x3F, 0x00, 0x9B, 0x00, 0x5C, 0x02, 0x50, 0x01, 0xC0, 0x37, 0x08, 0x13,
+0x02, 0xCC, 0x03, 0x30, 0xBF, 0x40, 0x37, 0x00, 0x53, 0x00, 0x4D, 0xAB, 0x50,
+0x09, 0xC1, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x00, 0xA7, 0x00, 0x9F, 0x00, 0x7C, 0x43, 0xF0, 0x21, 0xC0, 0x37, 0x00, 0xD7,
+0x20, 0x7C, 0x08, 0xF0, 0x01, 0xC0, 0x33, 0x00, 0x17, 0x82, 0x5C, 0x43, 0x70,
+0x0D, 0xC0, 0x87, 0x00, 0x5F, 0xC2, 0x7C, 0x03, 0xB0, 0x29, 0x88, 0x06, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x2F, 0x20, 0x2F,
+0x80, 0xD4, 0x03, 0x3C, 0x02, 0xC8, 0x34, 0x00, 0xB3, 0x00, 0xDC, 0x00, 0xF0,
+0x2B, 0xE0, 0x24, 0x20, 0x33, 0x10, 0xF4, 0x03, 0xB0, 0x0F, 0xC0, 0x0C, 0x00,
+0x7F, 0x00, 0xCC, 0x27, 0xF0, 0x09, 0xC0, 0x03, 0x22, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xE6, 0x00, 0x9D, 0x43, 0x06, 0x03, 0x10,
+0x11, 0x40, 0x34, 0x00, 0x81, 0x00, 0x44, 0x14, 0xD0, 0x18, 0xE0, 0x26, 0x00,
+0x11, 0x04, 0x74, 0x03, 0xD0, 0x0D, 0xC0, 0x44, 0x01, 0x47, 0x85, 0x7C, 0x02,
+0xD0, 0x51, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0xA0, 0x44, 0x00, 0x9D, 0x21, 0x40, 0x03, 0x92, 0x39, 0x44, 0x34, 0x00,
+0x91, 0x00, 0x56, 0x06, 0xD2, 0x25, 0x48, 0x74, 0x00, 0x31, 0x84, 0x74, 0x83,
+0xD8, 0x0D, 0x40, 0x4C, 0x00, 0x9D, 0x01, 0x45, 0x02, 0xD0, 0x13, 0x40, 0x07,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00,
+0x8D, 0x20, 0x54, 0x03, 0x12, 0x08, 0x40, 0x30, 0x20, 0xC1, 0x40, 0x16, 0x02,
+0xD0, 0x24, 0x44, 0x32, 0x10, 0x01, 0x00, 0x34, 0x33, 0xD8, 0x0C, 0x45, 0x00,
+0x10, 0x85, 0x00, 0x34, 0x22, 0xD0, 0x00, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x06, 0x08, 0x1F, 0x00, 0xD4, 0x03,
+0x32, 0x09, 0xC2, 0x3C, 0x00, 0x93, 0x2A, 0x54, 0x00, 0xD9, 0x0D, 0x40, 0x04,
+0x00, 0x13, 0x00, 0xFC, 0x9B, 0xB1, 0x0F, 0xC0, 0x04, 0x00, 0x9F, 0x00, 0x4C,
+0x02, 0xF1, 0x01, 0xC0, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xB2, 0x2F, 0x00, 0xBF, 0x00, 0xAD, 0x03, 0xF1, 0x03, 0xC0, 0x3F,
+0x10, 0x7F, 0x04, 0xEC, 0x00, 0xF0, 0x03, 0xC6, 0x0F, 0x40, 0x3F, 0x00, 0x3C,
+0x0B, 0xF0, 0x0F, 0xC0, 0x0D, 0x10, 0xB7, 0x00, 0xFC, 0x12, 0xF8, 0x03, 0xC0,
+0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x2F,
+0x01, 0xBF, 0x08, 0xFC, 0x43, 0x30, 0x8F, 0xC0, 0x3F, 0x05, 0x3F, 0x03, 0xDC,
+0x23, 0xF0, 0x3B, 0xD0, 0x3C, 0x00, 0xFB, 0x00, 0xFC, 0x13, 0x30, 0x13, 0xC0,
+0x7C, 0x10, 0x3D, 0x61, 0xCC, 0x18, 0x30, 0x43, 0xC1, 0x0C, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x87, 0x1D, 0x9D, 0x02, 0xDC,
+0x0F, 0x00, 0x6F, 0x40, 0xBF, 0x01, 0x1D, 0x04, 0xC4, 0x0B, 0x70, 0x0D, 0x40,
+0xFC, 0x00, 0xF1, 0x03, 0xF4, 0xA7, 0x10, 0x11, 0x40, 0x04, 0x08, 0x1D, 0x00,
+0x04, 0xAB, 0x10, 0x29, 0x51, 0x0C, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0xA0, 0x21, 0x82, 0x0D, 0x08, 0x14, 0x03, 0x10, 0x6C, 0x48,
+0x33, 0x14, 0x9D, 0x00, 0x14, 0x33, 0xD2, 0x48, 0x60, 0x30, 0x0A, 0xC9, 0x08,
+0x34, 0x03, 0x10, 0x01, 0x40, 0x30, 0x20, 0x1D, 0x00, 0x04, 0x10, 0x10, 0x40,
+0x42, 0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0,
+0x47, 0x00, 0x9D, 0x03, 0x54, 0x83, 0x14, 0x0D, 0x40, 0x37, 0x00, 0x9D, 0x01,
+0x44, 0x03, 0x50, 0x0C, 0x60, 0x34, 0x10, 0xD0, 0x00, 0x74, 0x03, 0x14, 0x15,
+0x18, 0x24, 0x00, 0x1D, 0x01, 0x44, 0x81, 0x16, 0x01, 0x41, 0x0D, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xA8, 0xC7, 0x00, 0x9F, 0x01,
+0x5C, 0x03, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0x0F, 0x03, 0x5C, 0x83, 0xF0, 0x8D,
+0xC0, 0x30, 0x08, 0xDB, 0x60, 0x3C, 0x03, 0x30, 0x20, 0xC4, 0x34, 0x00, 0x0F,
+0x53, 0x4C, 0x24, 0x30, 0x11, 0xC4, 0x29, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0x80, 0x0D, 0x00, 0xBF, 0x00, 0xDC, 0x03, 0xF1, 0x0D,
+0xC0, 0x3F, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0xD0, 0x1F, 0xC0, 0x3F, 0x00, 0xFF,
+0x50, 0xF0, 0x83, 0xF0, 0x03, 0xC8, 0x8F, 0x00, 0x3F, 0x00, 0xBC, 0xC7, 0xF0,
+0x3D, 0xC0, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
+0x08, 0xA5, 0x00, 0x1F, 0x00, 0x0C, 0x03, 0xF0, 0x0D, 0xC4, 0x35, 0x00, 0x1F,
+0x02, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x7C, 0x03, 0xF0,
+0x05, 0xC0, 0x34, 0x10, 0x1F, 0x00, 0x4C, 0x22, 0x34, 0x2C, 0xC0, 0x28, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x64, 0x04, 0x9D,
+0x00, 0xC4, 0x3B, 0xD0, 0x0F, 0x40, 0x3C, 0x00, 0x9D, 0x00, 0xFC, 0x03, 0xD0,
+0x0D, 0x48, 0x3F, 0x00, 0xF1, 0x03, 0xF4, 0x2B, 0xD0, 0xA5, 0xC0, 0x26, 0x08,
+0x1D, 0x00, 0x44, 0x0F, 0x10, 0x3D, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0xE2, 0x34, 0x0D, 0x40, 0x04, 0x07, 0x90,
+0x0C, 0x44, 0x30, 0x08, 0x8C, 0x00, 0x34, 0x03, 0x90, 0x0C, 0x48, 0x32, 0x00,
+0xC0, 0x01, 0x34, 0x27, 0xD0, 0x20, 0x40, 0x30, 0x04, 0x0D, 0x00, 0x04, 0x00,
+0x10, 0x04, 0x41, 0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0D, 0x02, 0x7A, 0x02, 0x6D, 0x01, 0x84, 0x07, 0xD0, 0x9E, 0x42, 0x78, 0x00,
+0xAD, 0x01, 0x94, 0x07, 0xD0, 0x1E, 0x40, 0x73, 0x02, 0xE5, 0x01, 0xB4, 0x07,
+0xD0, 0x17, 0x40, 0x5B, 0x04, 0x3D, 0x01, 0x84, 0x06, 0x12, 0x92, 0x41, 0x34,
+0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x32, 0x00,
+0x5F, 0x08, 0x0D, 0x03, 0xF0, 0x0C, 0xC0, 0x31, 0x02, 0x8F, 0x08, 0x34, 0x03,
+0xF0, 0x4C, 0xC0, 0x33, 0x0A, 0xC7, 0x10, 0x3C, 0x03, 0xF0, 0xA1, 0xE0, 0x30,
+0x00, 0x5F, 0x00, 0x0C, 0x80, 0x30, 0x50, 0xD0, 0x48, 0x40, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xBA, 0x3D, 0x20, 0xFF, 0x00, 0xFC, 0x03,
+0xF0, 0x0F, 0xC3, 0x3F, 0x00, 0xBF, 0x28, 0xFC, 0x23, 0xF0, 0x0F, 0xC4, 0x3F,
+0x02, 0xDB, 0x10, 0xFC, 0x23, 0xF0, 0x07, 0xE0, 0x3E, 0x80, 0x7F, 0x00, 0xFC,
+0x00, 0xF8, 0x81, 0xC2, 0x0B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA0, 0x57, 0x00, 0xD3, 0x00, 0x7C, 0x6F, 0xB0, 0x5D, 0xE0, 0xB7,
+0x14, 0x1F, 0x00, 0x7C, 0x13, 0xF0, 0x0D, 0xC0, 0xB7, 0x03, 0xD3, 0x15, 0x4C,
+0x53, 0xF0, 0x05, 0xE0, 0x77, 0x00, 0x53, 0x00, 0x7C, 0x01, 0x30, 0x0D, 0xC0,
+0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x98, 0x1D,
+0x00, 0xEB, 0x00, 0xB4, 0x03, 0x18, 0xCF, 0x60, 0xB8, 0x01, 0xED, 0x00, 0xB4,
+0x4B, 0xD0, 0x0E, 0x40, 0x3B, 0x03, 0xC1, 0x04, 0x84, 0x1B, 0xD0, 0x06, 0x40,
+0x1B, 0x20, 0x61, 0x20, 0xF4, 0x03, 0x14, 0x0F, 0x40, 0x4C, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x79, 0x14, 0x61, 0x21, 0x36,
+0x07, 0x18, 0x5E, 0x4C, 0x79, 0x00, 0x6D, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x64,
+0x71, 0x01, 0xE1, 0x41, 0x96, 0x17, 0xD0, 0x16, 0x40, 0x7F, 0x00, 0x65, 0x01,
+0xB6, 0x07, 0x94, 0x1E, 0x42, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x20, 0x33, 0x00, 0xC9, 0x0B, 0x34, 0x83, 0x10, 0x0C, 0x40,
+0x30, 0x00, 0xCD, 0x07, 0x74, 0x03, 0xD0, 0x9C, 0x60, 0x33, 0x40, 0xC1, 0x00,
+0x15, 0x03, 0xD1, 0x1C, 0x42, 0x33, 0x00, 0xC4, 0x06, 0x34, 0x17, 0x90, 0x9C,
+0x40, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8,
+0x1F, 0x00, 0x73, 0x02, 0x7C, 0x01, 0xB0, 0x05, 0xC2, 0x17, 0x00, 0x7F, 0x10,
+0x7C, 0x01, 0xF0, 0x15, 0xC0, 0x13, 0x00, 0x51, 0x00, 0x5C, 0x01, 0xF0, 0x46,
+0xC0, 0x1F, 0x00, 0x77, 0x12, 0xFA, 0x1D, 0xB0, 0xB7, 0xC4, 0x5C, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x00, 0x1F, 0x04,
+0x7C, 0x00, 0xF4, 0x01, 0xC8, 0x07, 0x00, 0x1C, 0x00, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x07, 0x00, 0x1F, 0x00, 0x64, 0x00, 0xF0, 0x01, 0xC4, 0x07, 0x40, 0x1B,
+0x00, 0x7C, 0x08, 0x70, 0x01, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0xE5, 0x04, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0xA0, 0x4C, 0x02, 0x32, 0x09, 0xC8, 0x27, 0x09, 0x93,
+0x00, 0x3C, 0x92, 0x30, 0x19, 0xC1, 0x26, 0x01, 0x9F, 0x00, 0x3C, 0x06, 0x30,
+0x89, 0xC0, 0x41, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x26, 0x10, 0x9D, 0x80, 0x74, 0x32, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D,
+0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x27, 0x09, 0x91, 0x23, 0x74, 0x4E, 0x14,
+0x99, 0x42, 0xA4, 0x04, 0x9D, 0x00, 0x74, 0x0A, 0x10, 0x29, 0x44, 0x04, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x34, 0x00, 0x9D,
+0x00, 0x54, 0x02, 0xC0, 0x09, 0x40, 0x27, 0x00, 0xCD, 0x00, 0x44, 0x02, 0x50,
+0x09, 0x42, 0x25, 0x40, 0x91, 0x18, 0x74, 0x02, 0x90, 0x29, 0x40, 0x26, 0x00,
+0x9D, 0x00, 0x74, 0x22, 0x08, 0x08, 0x40, 0x71, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x28, 0x30, 0x05, 0x8D, 0x54, 0x34, 0x02, 0xD0,
+0x88, 0x40, 0x23, 0x02, 0x8D, 0x88, 0x05, 0x22, 0x10, 0x88, 0x40, 0x23, 0x00,
+0x81, 0x00, 0x30, 0x02, 0x10, 0x08, 0x42, 0x20, 0x00, 0x8D, 0x00, 0x36, 0x23,
+0x10, 0x08, 0x40, 0x50, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB0, 0x06, 0x21, 0x1F, 0x24, 0x5C, 0xD0, 0xF0, 0x61, 0xC5, 0x87, 0x05,
+0x1F, 0x02, 0x4C, 0x58, 0x70, 0x21, 0xC0, 0x05, 0x05, 0x13, 0x34, 0x7C, 0x50,
+0x30, 0x01, 0xC0, 0x86, 0x02, 0x1F, 0x0A, 0x7C, 0x58, 0x34, 0x45, 0xC1, 0x75,
+0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0, 0x2F, 0x05,
+0xBF, 0x34, 0x7C, 0x02, 0xF0, 0x49, 0xC0, 0x27, 0x01, 0xBF, 0x04, 0x7C, 0x12,
+0xF4, 0x4B, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x0B, 0xC0, 0x6B,
+0x00, 0xBF, 0x21, 0xFC, 0x12, 0xF0, 0x4B, 0xC1, 0x67, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x00, 0x93, 0x02, 0xDC, 0x02,
+0xF0, 0x89, 0xC0, 0xA6, 0x15, 0x9B, 0x00, 0x5C, 0x42, 0x30, 0x09, 0xC0, 0x2E,
+0x04, 0xBF, 0x00, 0xDC, 0x02, 0xB2, 0x0B, 0xC0, 0x2F, 0x08, 0x9F, 0x00, 0xCC,
+0xC2, 0x32, 0x0B, 0xD0, 0x60, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1C, 0x18, 0x07, 0x01, 0x1B, 0x60, 0x74, 0xA8, 0xD0, 0xA0, 0x42, 0x84,
+0x00, 0x11, 0x20, 0x74, 0x08, 0x10, 0x41, 0x40, 0x84, 0x00, 0x17, 0x4A, 0x44,
+0x28, 0x10, 0x01, 0x44, 0x07, 0x20, 0x1D, 0x00, 0x44, 0x08, 0x14, 0x01, 0x40,
+0x70, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0, 0xA1,
+0x84, 0x81, 0x02, 0x34, 0x02, 0xD0, 0x48, 0x40, 0x22, 0x01, 0x85, 0x14, 0x34,
+0x52, 0x12, 0x09, 0x61, 0x22, 0x00, 0x8D, 0x00, 0x14, 0x02, 0x10, 0x08, 0x40,
+0x33, 0x80, 0x8D, 0x00, 0x04, 0x02, 0x10, 0x08, 0x62, 0x4A, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x25, 0x00, 0x99, 0x80, 0x74,
+0x02, 0xC0, 0x08, 0x40, 0x26, 0x20, 0x95, 0x02, 0x34, 0x02, 0x10, 0x09, 0x4A,
+0x24, 0x00, 0x95, 0x00, 0x54, 0x02, 0x10, 0x0D, 0x40, 0xA7, 0x00, 0x8D, 0x14,
+0x45, 0x02, 0x10, 0x0D, 0x40, 0x62, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0xA8, 0x27, 0x01, 0x93, 0x87, 0x7C, 0x02, 0xF0, 0x09, 0xC8,
+0x26, 0x08, 0x97, 0x00, 0x5E, 0x02, 0x10, 0x08, 0xC0, 0x26, 0x20, 0x9F, 0x20,
+0x5C, 0x02, 0xB0, 0x59, 0xC0, 0x27, 0x20, 0x9E, 0x23, 0x4C, 0x42, 0x30, 0x49,
+0xC0, 0x16, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80,
+0x61, 0x02, 0x9F, 0x05, 0x7C, 0x02, 0xD0, 0x09, 0xC0, 0x21, 0x40, 0x9B, 0x84,
+0x7C, 0x02, 0xF4, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x6C, 0x42, 0xD4, 0x39,
+0xC0, 0x27, 0x00, 0x9F, 0x21, 0x7C, 0x02, 0xF0, 0x48, 0xC0, 0x49, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x84, 0x04, 0x1F, 0x02,
+0x6C, 0x00, 0xE0, 0x01, 0xC0, 0x04, 0x00, 0x13, 0x80, 0x7C, 0x00, 0x30, 0x01,
+0xC0, 0x05, 0x04, 0x1F, 0x10, 0x4C, 0x00, 0x70, 0x11, 0xC2, 0x07, 0x01, 0x1F,
+0xA2, 0x3C, 0x20, 0x10, 0x41, 0xC2, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0xA0, 0xDC, 0x00, 0x5D, 0x20, 0xD4, 0x65, 0xC0, 0x05,
+0x40, 0x14, 0x00, 0x50, 0x00, 0x74, 0x81, 0x10, 0x05, 0xC0, 0x1C, 0x00, 0x6D,
+0x20, 0x80, 0x0D, 0x70, 0x07, 0x80, 0x1D, 0x10, 0x5D, 0x80, 0xF4, 0x01, 0x10,
+0x37, 0x42, 0x53, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0xA0, 0xF2, 0x02, 0xCD, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x50, 0x30, 0x80, 0xC1,
+0x00, 0x34, 0x03, 0x10, 0x0C, 0x40, 0x31, 0x00, 0xCD, 0x0A, 0x00, 0x0B, 0xD8,
+0x8C, 0x48, 0xB2, 0x00, 0xCC, 0x00, 0x36, 0x93, 0x90, 0x00, 0x44, 0x53, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, 0x38, 0x00, 0xCD,
+0x01, 0x94, 0x00, 0xD0, 0x0E, 0x40, 0x38, 0xC2, 0xE1, 0x04, 0xB4, 0x23, 0x11,
+0x0E, 0x40, 0x38, 0x80, 0x8D, 0x00, 0x85, 0x0B, 0xD8, 0x06, 0x40, 0x09, 0x20,
+0xED, 0x04, 0x34, 0x00, 0x94, 0x0A, 0x41, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x11, 0x10, 0x78, 0x00, 0xEF, 0x0D, 0x84, 0x04, 0xF0,
+0x1E, 0xC1, 0x70, 0x05, 0xE1, 0x0D, 0x34, 0x57, 0x34, 0x3F, 0xC0, 0x79, 0x00,
+0xAF, 0x01, 0x8C, 0x07, 0x70, 0x16, 0xC0, 0x6B, 0x00, 0xEF, 0x0B, 0xBC, 0x07,
+0xB0, 0x16, 0xC0, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA2, 0x15, 0x10, 0xDF, 0x84, 0x5C, 0x00, 0xF0, 0x4D, 0xC0, 0x37, 0x00,
+0xDF, 0x04, 0x7C, 0x1B, 0xF0, 0x6D, 0xC9, 0x37, 0x20, 0x1B, 0x00, 0x7C, 0x00,
+0x78, 0x05, 0xC0, 0x07, 0x10, 0xDF, 0x00, 0x7C, 0x00, 0x74, 0x0D, 0xC0, 0x43,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7D, 0x00,
+0xFF, 0x11, 0x8C, 0x24, 0x70, 0x1F, 0xC5, 0x7C, 0x00, 0xF3, 0x11, 0xFC, 0x07,
+0x30, 0x1F, 0xC0, 0x7F, 0x02, 0xB7, 0x05, 0xFC, 0x07, 0xF8, 0x96, 0xC0, 0x6C,
+0x02, 0xF3, 0x89, 0xCC, 0x07, 0x24, 0x1B, 0xC4, 0x00, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x08, 0x39, 0x20, 0xED, 0x04, 0x84, 0x00,
+0x18, 0x0E, 0x50, 0x38, 0x22, 0xE1, 0x00, 0xB4, 0x23, 0x10, 0x0E, 0x40, 0x3B,
+0x00, 0xA7, 0x00, 0xB4, 0x23, 0xD0, 0x06, 0x48, 0x0D, 0x02, 0xFB, 0x40, 0x85,
+0x00, 0xF0, 0x88, 0xE1, 0x54, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x39, 0x04, 0xED, 0x80, 0xA4, 0x00, 0x58, 0x0C, 0x40, 0x39,
+0x00, 0xE9, 0x00, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x1B, 0x00, 0xA5, 0x04, 0xB4,
+0x03, 0xD0, 0x03, 0x46, 0x08, 0x82, 0xE1, 0x00, 0x84, 0x03, 0x50, 0x0C, 0x40,
+0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x61,
+0x00, 0xCD, 0x41, 0x04, 0x00, 0x10, 0x0C, 0x40, 0x34, 0x00, 0xD1, 0x42, 0x34,
+0x03, 0x12, 0x8C, 0x40, 0x13, 0x00, 0x05, 0x00, 0x34, 0x00, 0xD0, 0xB0, 0x44,
+0x01, 0x00, 0xC9, 0x02, 0x04, 0x41, 0xD0, 0x34, 0x50, 0x10, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x45, 0x20, 0xFF, 0x9A, 0x6C,
+0x00, 0x41, 0x0F, 0xC0, 0x3D, 0x00, 0xFB, 0x00, 0xFC, 0x03, 0x30, 0x1F, 0xC0,
+0x37, 0x00, 0x97, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0x44, 0x00, 0x06, 0xF3, 0x42,
+0x4C, 0x4B, 0x30, 0x25, 0xC0, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x00, 0xA7, 0x01, 0xDF, 0x00, 0x7C, 0x08, 0xF0, 0x0D, 0xC0,
+0x37, 0x20, 0xDF, 0x08, 0x7C, 0x03, 0xF0, 0x0D, 0xC4, 0x37, 0x00, 0x9F, 0x80,
+0x3C, 0x8B, 0xF0, 0x01, 0xC8, 0x87, 0x00, 0xDF, 0x00, 0x3C, 0x00, 0x96, 0x65,
+0xC0, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08,
+0x0F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0xF3, 0x10,
+0x5C, 0x03, 0xE0, 0x0F, 0xC0, 0x2F, 0x02, 0xBF, 0x00, 0xFC, 0x83, 0x30, 0x03,
+0xC1, 0x0D, 0x20, 0xF3, 0x10, 0x7C, 0x07, 0x30, 0x97, 0xC2, 0x13, 0x22, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x20, 0xC6, 0x04, 0xDD, 0x00,
+0x74, 0x0C, 0xD0, 0x0D, 0x50, 0x34, 0x20, 0xD1, 0x00, 0x44, 0x03, 0xD0, 0x0D,
+0x40, 0x27, 0x00, 0x19, 0x01, 0x74, 0x18, 0x00, 0x31, 0xC0, 0x47, 0x01, 0xD1,
+0x00, 0x74, 0x20, 0x10, 0x29, 0x40, 0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xA0, 0x44, 0x00, 0xDD, 0x00, 0x74, 0x44, 0xD0, 0x0C,
+0x40, 0x34, 0x00, 0xD1, 0x00, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x80, 0x1D,
+0x03, 0x74, 0x10, 0x10, 0x11, 0x40, 0x4F, 0x00, 0xF1, 0x00, 0x74, 0x43, 0x19,
+0x09, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x28, 0x20, 0x20, 0xCD, 0x80, 0x24, 0x00, 0xD2, 0x0C, 0x40, 0x30, 0x20, 0xC1,
+0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x33, 0x80, 0x09, 0x00, 0x34, 0x00, 0x10,
+0x00, 0x44, 0x07, 0x40, 0xC1, 0x00, 0x34, 0x02, 0x13, 0x84, 0x40, 0x43, 0xA0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x06, 0x00, 0xEF,
+0x80, 0x7C, 0x80, 0xF0, 0x0F, 0xC0, 0x38, 0x00, 0xF3, 0x00, 0xC5, 0x03, 0xF0,
+0x0F, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x05, 0x00,
+0xF3, 0x00, 0x7C, 0x00, 0x30, 0x09, 0xC8, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x85, 0xA8, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0,
+0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xEC, 0x83, 0xF0, 0x0F, 0xC0, 0x0F, 0x00,
+0x3B, 0x40, 0xFC, 0x00, 0xF0, 0x03, 0xE8, 0x0D, 0x00, 0xFF, 0x00, 0xFC, 0x00,
+0xF0, 0x43, 0xC0, 0x17, 0x21, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA8, 0x3F, 0x04, 0xB3, 0x08, 0xCC, 0x93, 0xF1, 0xCF, 0xC0, 0x3C, 0x42,
+0xF3, 0x00, 0xFC, 0x03, 0x30, 0x13, 0xC0, 0x3D, 0x05, 0xF7, 0x2C, 0xFC, 0x04,
+0xB0, 0x0F, 0xC0, 0x3E, 0x06, 0x3F, 0x04, 0xEC, 0x03, 0xF0, 0x83, 0xC0, 0x0F,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0xBF, 0x00,
+0x1B, 0x04, 0xC4, 0xAF, 0xD0, 0x6F, 0x40, 0xBC, 0x03, 0xF1, 0x84, 0xF4, 0x0F,
+0x10, 0x09, 0xC4, 0x7D, 0x08, 0xD5, 0x08, 0x74, 0x00, 0x50, 0x2F, 0x42, 0x3C,
+0x10, 0x1D, 0x12, 0xC4, 0x87, 0xD0, 0x40, 0x40, 0x07, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x04, 0x81, 0x22, 0x04, 0x03,
+0xD0, 0x2C, 0x44, 0x31, 0x01, 0xC1, 0x18, 0x24, 0x0B, 0x50, 0x04, 0x40, 0x31,
+0x00, 0xC5, 0x00, 0x74, 0x02, 0x10, 0x2C, 0x44, 0x33, 0x01, 0x8D, 0x06, 0x24,
+0x03, 0xD0, 0x00, 0x40, 0x47, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA0, 0x34, 0x30, 0x09, 0x41, 0x46, 0x03, 0xD0, 0x0D, 0x40, 0x35,
+0x00, 0xD1, 0x00, 0x74, 0x03, 0x14, 0x0D, 0x40, 0x35, 0x00, 0xD4, 0x00, 0x74,
+0x22, 0x50, 0x0D, 0x40, 0x35, 0x00, 0xDD, 0x00, 0xC4, 0x03, 0xD0, 0x33, 0x40,
+0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x37,
+0x00, 0x93, 0x03, 0x4C, 0x83, 0xF0, 0x0D, 0xC0, 0x35, 0x20, 0xD3, 0x80, 0x7C,
+0x03, 0x72, 0x91, 0xC8, 0x35, 0x00, 0xD7, 0x80, 0x7C, 0x45, 0xB0, 0x0D, 0xC0,
+0x37, 0x18, 0x1F, 0xA2, 0x6C, 0x03, 0xF0, 0x11, 0xC0, 0x03, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xBF, 0x40, 0xFD,
+0x03, 0xF0, 0x0D, 0xC2, 0x36, 0x00, 0xFF, 0x00, 0xBC, 0x03, 0xF0, 0x03, 0xC1,
+0x3F, 0x00, 0xD9, 0x00, 0xFC, 0x41, 0xF0, 0x0D, 0xC0, 0x3E, 0x08, 0xFC, 0x09,
+0xFC, 0x03, 0xF0, 0x03, 0x80, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x08, 0x31, 0x01, 0x9F, 0x02, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x31, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x35, 0x00, 0xD7, 0x00,
+0x4C, 0x22, 0xB0, 0x0C, 0xC8, 0x34, 0x08, 0x07, 0x00, 0x5C, 0x03, 0x30, 0x21,
+0xC0, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0xFC, 0x0C, 0x9D, 0x00, 0xFC, 0x0F, 0xD0, 0x0F, 0x44, 0x3C, 0x00, 0xF1, 0x00,
+0xF4, 0x07, 0xD0, 0x15, 0xC2, 0x39, 0x08, 0xF0, 0x03, 0x2C, 0x8B, 0xD0, 0x0F,
+0x48, 0x3C, 0x00, 0xD5, 0x10, 0xC4, 0x2F, 0x10, 0x09, 0x40, 0x4C, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x32, 0x00, 0x0D, 0x00,
+0x34, 0x43, 0xD0, 0x0D, 0x40, 0x31, 0x00, 0xC1, 0x00, 0x34, 0x1B, 0xD2, 0x14,
+0x48, 0x32, 0x00, 0xC8, 0x87, 0x04, 0x0D, 0xD0, 0x0C, 0x00, 0x31, 0x00, 0x41,
+0x10, 0x14, 0x23, 0x10, 0x00, 0x40, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x88, 0x78, 0x00, 0x6D, 0x01, 0xB4, 0x67, 0xD0, 0x9E,
+0x40, 0x78, 0x00, 0xE1, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x40, 0x73, 0x48, 0xED,
+0x01, 0xA4, 0x05, 0xD1, 0x1E, 0x40, 0x71, 0x00, 0xE5, 0x01, 0xC4, 0x17, 0x14,
+0x92, 0x40, 0x18, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x10, 0x30, 0x02, 0xCF, 0x0C, 0x34, 0x03, 0xF0, 0x0C, 0x48, 0x31, 0x00, 0xC3,
+0x00, 0x3C, 0x43, 0xF0, 0x04, 0xC1, 0x32, 0x00, 0xCF, 0x10, 0x0C, 0x00, 0xB0,
+0x8C, 0xD0, 0x31, 0xA0, 0x17, 0x22, 0x5C, 0x17, 0x30, 0x50, 0xD0, 0x48, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x3D, 0x0C, 0xFF,
+0x88, 0xDC, 0x83, 0xF0, 0x2F, 0x00, 0x3F, 0x00, 0xDF, 0x00, 0xF4, 0x03, 0xF0,
+0x0F, 0xC0, 0x3D, 0x30, 0xF3, 0x08, 0x7C, 0x01, 0xF0, 0x0F, 0xC0, 0x3E, 0xA0,
+0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x89, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x24, 0x5F, 0x40, 0x7C, 0x6F, 0x30,
+0xBD, 0xC0, 0xF4, 0x05, 0xD3, 0x68, 0x1C, 0x63, 0x70, 0x01, 0xD0, 0x36, 0x01,
+0xDF, 0x49, 0x4C, 0x05, 0x30, 0x4D, 0xC9, 0x37, 0x03, 0x1F, 0x00, 0x4D, 0x63,
+0xF0, 0x11, 0x84, 0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x88, 0x39, 0x01, 0x6D, 0x60, 0x36, 0x13, 0x10, 0x4E, 0x40, 0xB8, 0x01,
+0xE1, 0x0C, 0x84, 0x03, 0x10, 0x07, 0xC0, 0xB8, 0x04, 0xED, 0x84, 0xAC, 0x01,
+0x10, 0x4E, 0x48, 0x3B, 0x04, 0xCD, 0x00, 0x84, 0x03, 0xD0, 0x02, 0x40, 0x48,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x01,
+0xED, 0x03, 0x94, 0x07, 0x18, 0x1E, 0x50, 0x7A, 0x00, 0xC5, 0x01, 0x94, 0x17,
+0x50, 0x12, 0x41, 0x78, 0x00, 0xCD, 0x01, 0xC4, 0x04, 0x92, 0x9E, 0x42, 0x7B,
+0x01, 0x2D, 0x21, 0x84, 0x07, 0xD0, 0x10, 0x40, 0x0D, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03,
+0x15, 0x0C, 0x60, 0x30, 0x00, 0xC1, 0x00, 0x24, 0x03, 0x10, 0x14, 0x41, 0x30,
+0x00, 0xCD, 0x40, 0x24, 0x21, 0x90, 0x0C, 0x40, 0x33, 0x00, 0xCD, 0x04, 0x04,
+0x03, 0xD0, 0x8C, 0x40, 0x49, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x17, 0xA8, 0x15, 0x00, 0x7F, 0x0A, 0x7C, 0x81, 0x38, 0x05, 0xC0, 0x16,
+0x00, 0x53, 0x00, 0x5C, 0x01, 0x70, 0x27, 0xC0, 0x14, 0x00, 0x5F, 0x00, 0xCC,
+0x85, 0xB0, 0x05, 0xC0, 0x17, 0x10, 0x7F, 0x04, 0x4C, 0x01, 0xF0, 0x17, 0xC0,
+0x5D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x07,
+0x08, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x40, 0x1F, 0x00, 0x1C,
+0x00, 0xF0, 0x01, 0xC4, 0x05, 0x80, 0x1F, 0x00, 0x7C, 0x00, 0x74, 0x01, 0xC2,
+0x07, 0x00, 0x1F, 0x02, 0x7C, 0x00, 0xF2, 0x41, 0x80, 0x4A, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x00, 0x9F, 0x40, 0x7C,
+0x06, 0x70, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x08, 0x4C, 0x16, 0x30, 0x39, 0xC0,
+0x24, 0x00, 0x9D, 0x00, 0x74, 0x12, 0xF0, 0x09, 0xC0, 0x23, 0x00, 0x97, 0x08,
+0x5C, 0x06, 0x30, 0x09, 0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x20, 0x66, 0x0E, 0x9D, 0x20, 0x74, 0x0A, 0xD2, 0x09, 0x40,
+0x27, 0x00, 0x9D, 0x03, 0x44, 0x0E, 0x15, 0x08, 0x40, 0x64, 0x20, 0x9D, 0x1B,
+0x70, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x91, 0x11, 0x04, 0xAE, 0x10, 0x09,
+0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0,
+0x24, 0x00, 0xDD, 0x00, 0x74, 0x62, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x8D, 0x02,
+0x44, 0x42, 0x11, 0x09, 0x40, 0x27, 0x09, 0x9D, 0x00, 0x70, 0x42, 0xD2, 0x09,
+0x40, 0x27, 0x00, 0x81, 0x00, 0x54, 0x0A, 0x10, 0x09, 0x40, 0x63, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x20, 0x05, 0x8D, 0x14,
+0x34, 0x02, 0xD0, 0x88, 0x40, 0x23, 0x22, 0x8D, 0x48, 0x04, 0x02, 0x11, 0x09,
+0x40, 0x21, 0x10, 0x8D, 0x08, 0x34, 0x02, 0xD8, 0x08, 0x40, 0x23, 0x40, 0x81,
+0x08, 0x04, 0x92, 0x10, 0x48, 0x48, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x01, 0x1F, 0x04, 0x7C, 0x50, 0x70, 0x60,
+0xC1, 0x83, 0x05, 0x1F, 0x96, 0x4C, 0x50, 0x30, 0xA1, 0xD0, 0x05, 0x05, 0x1F,
+0x16, 0x7C, 0x28, 0xE0, 0xE1, 0xC9, 0x07, 0x15, 0x17, 0x16, 0x5C, 0x04, 0x30,
+0x11, 0xC0, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+0xA8, 0x27, 0x25, 0xBF, 0x34, 0x7E, 0x02, 0xF0, 0x49, 0xC0, 0x27, 0x01, 0x9F,
+0x04, 0x7D, 0x02, 0xF0, 0x1B, 0xC0, 0x26, 0x20, 0x9F, 0x04, 0xBC, 0x07, 0xF0,
+0x19, 0xC0, 0x27, 0x05, 0xBF, 0x04, 0x7C, 0x22, 0xF4, 0xCB, 0xC1, 0x67, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0, 0x2F, 0x03, 0x93,
+0x03, 0xCC, 0x12, 0x70, 0x29, 0xC0, 0xA5, 0x00, 0xBF, 0x00, 0xCC, 0x42, 0x30,
+0x0B, 0xC0, 0x2E, 0x00, 0xB3, 0x00, 0xCC, 0x02, 0xB0, 0x09, 0xC0, 0x24, 0x0B,
+0xB3, 0x40, 0xCC, 0x02, 0x30, 0x09, 0xC0, 0x67, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x47, 0x01, 0x1B, 0x43, 0x68, 0x28, 0x10,
+0x01, 0x40, 0x84, 0x02, 0x1D, 0x0E, 0x45, 0x08, 0x10, 0x01, 0x40, 0x85, 0x02,
+0x11, 0x20, 0x44, 0x00, 0x13, 0x21, 0xC0, 0x46, 0x01, 0x1B, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x44, 0x73, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA2, 0xA3, 0x10, 0x81, 0x06, 0x04, 0x02, 0x50, 0x68, 0x40, 0x21, 0x81,
+0x8D, 0x90, 0x06, 0x02, 0x10, 0x09, 0x40, 0x21, 0x40, 0x81, 0x16, 0x44, 0x02,
+0x90, 0x28, 0x40, 0xA0, 0x01, 0x81, 0x40, 0x05, 0x02, 0x90, 0x08, 0x40, 0x43,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x20,
+0x99, 0x02, 0x66, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x8D, 0x20, 0x46, 0x02,
+0x04, 0x09, 0x40, 0x25, 0x00, 0xC1, 0x00, 0x44, 0x03, 0x18, 0x09, 0x40, 0x27,
+0x20, 0x89, 0x00, 0x44, 0x02, 0x84, 0x69, 0x40, 0x63, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, 0x25, 0x20, 0x93, 0x21, 0x4C, 0x02,
+0x70, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x80, 0x4C, 0x02, 0x32, 0x09, 0xC8, 0x27,
+0x00, 0x93, 0x00, 0x4C, 0x02, 0xB1, 0x09, 0xC4, 0x24, 0x10, 0x93, 0x13, 0x4C,
+0x02, 0xB0, 0x09, 0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x00, 0x21, 0x00, 0x8F, 0x04, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x00, 0x3C, 0x02, 0xF0, 0x89, 0xC0, 0x23, 0x00, 0x9F, 0x00, 0x7D,
+0x26, 0xF1, 0x09, 0xC4, 0x26, 0xA8, 0x9F, 0x03, 0x3C, 0x82, 0x70, 0x09, 0xC0,
+0x53, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05,
+0x04, 0x1F, 0x40, 0x4C, 0x10, 0xF0, 0x00, 0xC0, 0x07, 0x80, 0x13, 0x10, 0x5C,
+0x84, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x1F, 0x20, 0x4C, 0x08, 0x30, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x26, 0x4C, 0x00, 0x30, 0x21, 0xC0, 0x53, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x5C, 0x04, 0x5D, 0x00, 0x84,
+0x01, 0xD0, 0x05, 0x44, 0x17, 0x40, 0x71, 0x83, 0xF4, 0x01, 0xD0, 0x07, 0x40,
+0x14, 0x00, 0x7D, 0x00, 0x84, 0xC5, 0x34, 0x05, 0x40, 0x17, 0x00, 0x7D, 0x01,
+0xC4, 0x1D, 0x50, 0x05, 0x40, 0x53, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0xA0, 0xB2, 0x20, 0xCD, 0x20, 0x24, 0x2B, 0xD1, 0x0C, 0x40,
+0x33, 0x00, 0xC9, 0x08, 0x14, 0x07, 0x52, 0x0D, 0x21, 0x72, 0x80, 0xCD, 0x01,
+0x04, 0x07, 0x10, 0x0D, 0x40, 0x37, 0x00, 0xCD, 0x00, 0x07, 0x4F, 0x50, 0x0C,
+0x46, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x82,
+0x38, 0x00, 0xCD, 0x04, 0xA4, 0x01, 0xD0, 0x4E, 0x40, 0x7B, 0x02, 0xE9, 0x00,
+0xB4, 0x0A, 0xD0, 0x27, 0x48, 0x38, 0x04, 0xED, 0x02, 0x84, 0x03, 0x10, 0x0E,
+0x40, 0x3B, 0x00, 0xED, 0x82, 0xC4, 0x03, 0x50, 0x0E, 0x40, 0x17, 0x08, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x78, 0x00, 0xEF, 0x05,
+0xAD, 0x07, 0xF0, 0x5E, 0xC0, 0x7F, 0x01, 0x69, 0x41, 0x9C, 0x05, 0x70, 0x1E,
+0xE0, 0x7A, 0x00, 0xFE, 0x01, 0xCD, 0x84, 0x30, 0x1E, 0xC0, 0x7B, 0x00, 0xFF,
+0x01, 0xCC, 0x07, 0x70, 0x9E, 0xC2, 0x57, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x00, 0xDF, 0x42, 0x5C, 0x00, 0xF0, 0xAD,
+0xC0, 0x37, 0x00, 0x57, 0x00, 0x7C, 0x02, 0xF0, 0x04, 0xC0, 0x35, 0x00, 0x1F,
+0x00, 0x7C, 0x00, 0xF0, 0x0D, 0xC1, 0x37, 0x02, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x4D, 0xC0, 0x43, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xA0, 0x5F, 0x00, 0xF3, 0x53, 0xFC, 0x26, 0x30, 0x3F, 0xC0, 0xFF, 0x00, 0xFF,
+0x01, 0xCC, 0x07, 0xF0, 0x1B, 0xC0, 0x7F, 0x22, 0xBF, 0x01, 0xCC, 0x07, 0xF0,
+0x1F, 0xC1, 0x7C, 0x00, 0xF3, 0x01, 0xEC, 0x07, 0x30, 0x1F, 0xC1, 0x08, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0xBD, 0x00, 0xE1,
+0x00, 0xB4, 0x0A, 0x10, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x22, 0x80, 0x02, 0xD0,
+0x02, 0x40, 0x3B, 0x00, 0xAD, 0x08, 0x84, 0x23, 0xD2, 0x0E, 0x60, 0x3D, 0x00,
+0xEB, 0x00, 0x04, 0x15, 0x10, 0xDD, 0x40, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x19, 0x00, 0xE1, 0x00, 0xB4, 0x02, 0x94,
+0x0E, 0x40, 0x3B, 0x00, 0x8D, 0x00, 0x84, 0x00, 0xD0, 0x0E, 0x40, 0x3B, 0x80,
+0xED, 0x00, 0x84, 0x41, 0xD0, 0x0E, 0x40, 0x38, 0x00, 0xE1, 0x08, 0x24, 0x12,
+0x10, 0x4E, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x28, 0x07, 0x10, 0xD1, 0x11, 0x36, 0x02, 0x98, 0x0C, 0x40, 0x33, 0x88,
+0x9D, 0x40, 0x04, 0x02, 0xD1, 0x30, 0x40, 0x33, 0x08, 0x1D, 0x00, 0x04, 0x00,
+0xD0, 0x0C, 0x40, 0x31, 0x00, 0x09, 0x05, 0x04, 0x80, 0x18, 0x3C, 0x50, 0x58,
+0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x24, 0x00,
+0xF3, 0x13, 0x7C, 0x02, 0xB0, 0x0F, 0xC0, 0x3F, 0x00, 0x9F, 0x40, 0x4E, 0x02,
+0xF0, 0x29, 0xC1, 0x37, 0x00, 0x5F, 0x00, 0x4C, 0x02, 0xD1, 0x0F, 0x40, 0x3C,
+0x00, 0x13, 0x13, 0x2C, 0x03, 0x30, 0x0F, 0xC1, 0x74, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xA7, 0x00, 0xDF, 0x80, 0x7C, 0x00,
+0x70, 0x0D, 0xC0, 0x37, 0x00, 0x9F, 0x42, 0x3F, 0x02, 0xF0, 0x01, 0xC0, 0x37,
+0x00, 0x5F, 0x82, 0x7C, 0x00, 0xF0, 0x0D, 0xC8, 0x37, 0x10, 0x1F, 0xA2, 0x7C,
+0x02, 0xF5, 0x4D, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x81, 0x09, 0x2F, 0x10, 0xF3, 0x00, 0x44, 0x00, 0xF0, 0x0F, 0xC0, 0x3F,
+0x00, 0x3F, 0x08, 0xCD, 0x00, 0x30, 0x0B, 0xC1, 0x7F, 0x00, 0xFF, 0x00, 0xCC,
+0x00, 0xF0, 0x0F, 0xC0, 0x3B, 0x00, 0x03, 0x02, 0xCC, 0x25, 0x32, 0x0F, 0xC0,
+0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x66,
+0x00, 0xD5, 0x00, 0x44, 0x0C, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0x1D, 0x02, 0x44,
+0x06, 0x50, 0x31, 0x41, 0x37, 0x00, 0x1D, 0x02, 0x44, 0x0C, 0xD0, 0x0D, 0x40,
+0x37, 0x00, 0x11, 0x02, 0x44, 0x44, 0x50, 0x0D, 0x40, 0x07, 0x02, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x46, 0x00, 0xD1, 0x00, 0x54,
+0x06, 0xD8, 0x0D, 0x40, 0x37, 0x00, 0x5D, 0x00, 0x44, 0x44, 0x10, 0x13, 0x40,
+0x37, 0x12, 0x1D, 0x00, 0xE4, 0x06, 0xD0, 0x0F, 0x40, 0x37, 0x00, 0x11, 0x50,
+0x44, 0x83, 0x50, 0x0D, 0x48, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xC5, 0x00, 0x14, 0x02, 0xD8, 0x0C, 0x40,
+0x33, 0x08, 0x4C, 0x00, 0x05, 0x00, 0x50, 0x00, 0x40, 0x33, 0x00, 0x0D, 0x00,
+0x04, 0x00, 0xD0, 0x0C, 0x48, 0x33, 0x00, 0xC1, 0x00, 0x04, 0x10, 0x51, 0x4C,
+0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90,
+0x06, 0x00, 0xF3, 0x40, 0x5C, 0x00, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0x1F, 0x00,
+0x4C, 0x00, 0x32, 0x01, 0xC0, 0x27, 0x00, 0xCF, 0x00, 0x4C, 0x00, 0xF0, 0x0E,
+0xC4, 0x37, 0x00, 0x13, 0x00, 0x4D, 0x60, 0x30, 0xAF, 0xC0, 0x07, 0xC0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x2F, 0x20, 0xFF, 0x00,
+0xEC, 0x00, 0xF1, 0x0F, 0xC0, 0x3F, 0x00, 0x3F, 0x40, 0xFC, 0x00, 0xF0, 0x03,
+0xC2, 0x2F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xE0, 0x3F, 0x00, 0x3F,
+0x40, 0x7C, 0x10, 0xE0, 0x6D, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA8, 0x3F, 0x0B, 0xFF, 0x2C, 0xFC, 0x0A, 0xD0, 0x8F,
+0xC0, 0x4C, 0x00, 0x3F, 0x49, 0xEC, 0x93, 0x30, 0x4F, 0xC0, 0x0F, 0x10, 0x33,
+0x00, 0xFC, 0x24, 0xB0, 0x4F, 0xC0, 0x6C, 0x00, 0xF3, 0x00, 0x8C, 0x03, 0xB1,
+0x03, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x10, 0xBF, 0x01, 0xFD, 0x08, 0x74, 0x8A, 0xD0, 0x6F, 0x44, 0x64, 0x00, 0x19,
+0x00, 0xF4, 0x0F, 0x51, 0xAF, 0x40, 0x27, 0x12, 0x11, 0x41, 0x74, 0x12, 0x10,
+0x9F, 0x40, 0x74, 0x00, 0xF1, 0x42, 0x44, 0x87, 0x10, 0x11, 0x40, 0x0F, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA8, 0xB3, 0x01, 0xCD,
+0x00, 0x36, 0x1A, 0xD0, 0x2C, 0x50, 0x20, 0x00, 0x8D, 0x44, 0x24, 0x0B, 0x11,
+0x0C, 0x40, 0x01, 0x00, 0x05, 0x80, 0x74, 0x90, 0x90, 0x0C, 0x40, 0x35, 0x00,
+0xC1, 0x02, 0x04, 0x07, 0x90, 0x00, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x35, 0x00, 0xDD, 0x00, 0x74, 0x06, 0xD0,
+0x0D, 0x40, 0xE4, 0x00, 0x19, 0x01, 0x74, 0x03, 0x50, 0x0D, 0x60, 0x07, 0x00,
+0x31, 0x01, 0x74, 0x0E, 0x10, 0x0D, 0x00, 0x74, 0x00, 0xD1, 0x00, 0x44, 0x87,
+0x00, 0x11, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA8, 0x37, 0x00, 0xDF, 0x80, 0x7C, 0x8C, 0xF0, 0x0D, 0xC0, 0xC4, 0x30,
+0x9F, 0x01, 0x6C, 0x03, 0x34, 0x0D, 0xC0, 0x07, 0x00, 0x12, 0x05, 0x3C, 0x0E,
+0xB1, 0x0C, 0xC0, 0x60, 0x00, 0xD3, 0x00, 0x4C, 0x80, 0xB0, 0x19, 0xC0, 0x23,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00,
+0xFF, 0x00, 0xFC, 0x02, 0xF2, 0x0E, 0x40, 0x2F, 0x08, 0x3D, 0x40, 0xFC, 0x03,
+0xB0, 0x0F, 0xC0, 0x6B, 0xD1, 0xBF, 0x40, 0xFC, 0x02, 0xF1, 0x0F, 0xC0, 0x2F,
+0x00, 0xEF, 0x10, 0xFD, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x35, 0x08, 0xDF, 0x05, 0x7C, 0x10,
+0x70, 0x0D, 0xC6, 0x25, 0x00, 0x9F, 0xC0, 0x3C, 0x03, 0xF0, 0x0D, 0xC0, 0x37,
+0x09, 0x1F, 0x10, 0x7C, 0x02, 0xF0, 0x4D, 0xC0, 0x06, 0x01, 0xD7, 0x00, 0x0C,
+0x01, 0x30, 0x09, 0xC0, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x3C, 0x20, 0xFD, 0x42, 0x74, 0x0E, 0xD0, 0x0F, 0x50, 0x64,
+0x00, 0x1D, 0x80, 0xF0, 0x13, 0xD0, 0xAF, 0x40, 0xB7, 0x01, 0x9D, 0x23, 0x74,
+0x02, 0xD0, 0x3F, 0x40, 0xA7, 0x80, 0xF1, 0x01, 0x54, 0x01, 0x14, 0x09, 0x41,
+0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x30,
+0x00, 0xCD, 0x02, 0x34, 0x2C, 0x50, 0x0C, 0x48, 0x00, 0x02, 0x09, 0x40, 0x30,
+0x03, 0xD0, 0x1C, 0x40, 0x13, 0x00, 0x0D, 0x0B, 0x34, 0x00, 0x90, 0x3C, 0x4C,
+0xA2, 0x08, 0xCD, 0x41, 0x04, 0x03, 0x51, 0x08, 0x40, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x78, 0x00, 0xED, 0x01, 0xB4,
+0x05, 0xD1, 0x1C, 0x40, 0xC8, 0x00, 0x2D, 0x01, 0xB6, 0x0F, 0xD0, 0x1E, 0x41,
+0x7B, 0x02, 0x2D, 0x01, 0xB4, 0x04, 0xD0, 0x1E, 0x40, 0x7F, 0x00, 0xE1, 0x41,
+0xD4, 0x2F, 0x50, 0x16, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x02, 0x30, 0x08, 0xCF, 0x00, 0x3C, 0x03, 0x70, 0x8C, 0xC0,
+0x01, 0x00, 0x8F, 0x8A, 0x3E, 0x23, 0xF0, 0x0C, 0xC0, 0x13, 0x00, 0x4F, 0x00,
+0x3C, 0x80, 0xF1, 0x0C, 0xC1, 0x32, 0x00, 0xD7, 0x10, 0x0C, 0x23, 0x70, 0x4C,
+0xC0, 0x4B, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28,
+0x3D, 0x24, 0xFF, 0x00, 0xF8, 0x03, 0xF0, 0x0F, 0x80, 0x1F, 0x00, 0xFF, 0x28,
+0xFC, 0x63, 0xF0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7C, 0x03, 0xF0, 0x0F,
+0xE9, 0x3B, 0x00, 0xFF, 0x00, 0xFC, 0x23, 0xB4, 0x0D, 0xE0, 0x0B, 0x60, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0xF7, 0x04, 0xD7, 0x02,
+0x7C, 0x05, 0x30, 0xCD, 0xC0, 0x07, 0x00, 0x9B, 0x00, 0x7C, 0x13, 0xF1, 0xCD,
+0xD0, 0x04, 0x40, 0xD3, 0x01, 0x4D, 0x00, 0xF0, 0x6D, 0xC0, 0x27, 0x80, 0xD7,
+0x02, 0x7C, 0x03, 0x34, 0x18, 0xC4, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0x80, 0x30, 0x00, 0xE1, 0x56, 0xB4, 0x03, 0xB0, 0x8E,
+0x44, 0x2B, 0x00, 0xED, 0x00, 0xB4, 0x33, 0xD0, 0x0F, 0x41, 0x2C, 0x00, 0xE1,
+0x00, 0x84, 0x01, 0xD0, 0x4E, 0x41, 0x3B, 0x80, 0xED, 0x0E, 0xB4, 0x03, 0xB0,
+0x06, 0x40, 0x4C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x00, 0x78, 0x01, 0xED, 0x01, 0x36, 0x05, 0x10, 0x5E, 0x40, 0x7B, 0x18, 0xAD,
+0x01, 0xA4, 0x17, 0xD0, 0x5E, 0x40, 0x7A, 0x00, 0xC1, 0x01, 0xA4, 0x06, 0xD0,
+0x1E, 0x40, 0x5B, 0x04, 0xED, 0x25, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x10, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x33, 0x00, 0xC9,
+0x00, 0x34, 0x43, 0x98, 0x0C, 0x40, 0x33, 0x22, 0xCD, 0x0A, 0x34, 0x03, 0xD0,
+0x0C, 0x40, 0xB2, 0x03, 0xC1, 0x0A, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x73, 0x01,
+0xCD, 0x00, 0x34, 0x03, 0x90, 0x6C, 0x40, 0x58, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x17, 0x28, 0x17, 0x10, 0x5F, 0x00, 0xFC, 0x81, 0x30,
+0x05, 0xE0, 0x5B, 0x00, 0x7B, 0x61, 0x3C, 0x01, 0xF2, 0x05, 0xC0, 0xDE, 0x00,
+0x73, 0x01, 0xEC, 0x05, 0xF0, 0x05, 0xCA, 0x1B, 0x00, 0x5F, 0x00, 0xFC, 0x01,
+0x30, 0x07, 0xD4, 0x5C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x00, 0x05, 0x08, 0x17, 0x00, 0x78, 0x20, 0xF0, 0x01, 0xC6, 0x47, 0x08,
+0x1F, 0x10, 0x7C, 0x00, 0xF0, 0x20, 0xC8, 0x01, 0x00, 0x1F, 0x04, 0x5C, 0x24,
+0xF0, 0x01, 0xC0, 0x07, 0x20, 0x1F, 0x00, 0x7C, 0x04, 0xF1, 0x21, 0xC0, 0x4B,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00,
+0x8F, 0x01, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x02, 0x9B, 0x20, 0x4C, 0x82,
+0xB0, 0x19, 0x80, 0x24, 0x00, 0x91, 0x01, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0xE5,
+0x00, 0x93, 0x00, 0x7C, 0x02, 0x32, 0x09, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x03, 0x45, 0x8E,
+0xD0, 0x09, 0x40, 0xE7, 0x10, 0x80, 0x00, 0x44, 0x06, 0x10, 0x49, 0x50, 0x24,
+0x02, 0x91, 0x02, 0x74, 0x02, 0x10, 0x09, 0x40, 0xA7, 0x00, 0x91, 0x0B, 0x34,
+0x02, 0x14, 0x29, 0x44, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x18, 0x54, 0x2B, 0xD0, 0x09, 0x40, 0x27,
+0x00, 0x98, 0x20, 0x44, 0x52, 0x92, 0x49, 0x48, 0x25, 0x08, 0x95, 0x38, 0x34,
+0x02, 0x00, 0x09, 0x42, 0x27, 0x40, 0x91, 0x00, 0x74, 0x06, 0x1C, 0x2D, 0x40,
+0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20,
+0x00, 0x89, 0x14, 0x14, 0x52, 0xD1, 0x88, 0x40, 0x23, 0x08, 0x91, 0x48, 0x00,
+0x02, 0x00, 0x08, 0x60, 0x21, 0x00, 0x85, 0x04, 0x36, 0x22, 0x14, 0x08, 0x40,
+0x23, 0x00, 0xC1, 0x14, 0x34, 0x56, 0x10, 0x48, 0x41, 0x43, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x06, 0x05, 0x1F, 0x04, 0x5C,
+0x10, 0xF0, 0x61, 0xC1, 0x17, 0x00, 0x1A, 0x02, 0x4C, 0x50, 0xB0, 0xE1, 0xC1,
+0x85, 0x47, 0x17, 0x01, 0x7C, 0x08, 0x20, 0x41, 0xC1, 0x15, 0x00, 0x13, 0x0E,
+0x7C, 0x10, 0x30, 0x41, 0xC0, 0x77, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xB8, 0x27, 0x05, 0x9F, 0x14, 0xEC, 0x52, 0xF0, 0x49, 0xC2,
+0x2F, 0x10, 0xBF, 0x44, 0x7D, 0x02, 0xF0, 0x19, 0xC2, 0x6E, 0x00, 0xBB, 0x08,
+0xFC, 0x12, 0xF0, 0x09, 0xC0, 0x2F, 0x00, 0x9F, 0x81, 0xBC, 0x02, 0xF0, 0x0B,
+0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00,
+0xA7, 0x10, 0xBF, 0x06, 0xCC, 0x46, 0x10, 0x29, 0xC0, 0x2D, 0x00, 0x9F, 0x82,
+0xDC, 0x12, 0xF0, 0x0B, 0xC0, 0x2C, 0x05, 0xB3, 0x00, 0x7C, 0x82, 0x30, 0x4B,
+0xC1, 0x2F, 0x00, 0xB3, 0x00, 0xBC, 0x93, 0x30, 0x0B, 0xC0, 0x77, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x87, 0x00, 0x11, 0x0A,
+0x45, 0x0C, 0xB0, 0xE0, 0x40, 0x07, 0x08, 0x17, 0x00, 0x44, 0x00, 0xD0, 0xA1,
+0x40, 0x84, 0x08, 0x11, 0x00, 0x74, 0x50, 0x10, 0x21, 0x40, 0x17, 0x00, 0x11,
+0x00, 0x74, 0x00, 0x10, 0x01, 0x44, 0x63, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x20, 0xA1, 0x01, 0x85, 0x04, 0x04, 0x52, 0x58, 0x48,
+0x40, 0x23, 0x00, 0x89, 0x00, 0x14, 0x0B, 0xD0, 0x08, 0x40, 0x20, 0x00, 0x85,
+0x80, 0x34, 0x02, 0x10, 0x08, 0x42, 0x25, 0x00, 0xC1, 0x00, 0x34, 0x8A, 0x10,
+0x08, 0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x28, 0x25, 0x00, 0xD1, 0x00, 0x44, 0x03, 0xD1, 0x09, 0x40, 0x27, 0x0C, 0x95,
+0x04, 0x44, 0x02, 0xD0, 0x09, 0x10, 0x24, 0x14, 0x94, 0x04, 0x74, 0x0A, 0x14,
+0x09, 0x40, 0x27, 0x00, 0x91, 0x00, 0x74, 0x12, 0x18, 0x49, 0x40, 0x63, 0x28,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA2, 0x27, 0x10, 0x97,
+0x00, 0x48, 0x1A, 0x70, 0x09, 0xE0, 0xA5, 0x00, 0x9F, 0x93, 0x54, 0x02, 0xF0,
+0x09, 0xC4, 0xE4, 0x40, 0x97, 0x00, 0x7C, 0x02, 0x33, 0x09, 0xC0, 0x67, 0x00,
+0x91, 0x00, 0x7C, 0x06, 0x34, 0x49, 0x42, 0x17, 0x08, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x20, 0x00, 0x9F, 0x90, 0x7C, 0x12, 0xB0,
+0x09, 0xC0, 0x67, 0x09, 0x97, 0x21, 0x7C, 0x02, 0xF0, 0x08, 0xC0, 0x23, 0x11,
+0x9B, 0x00, 0x7C, 0x0A, 0xF0, 0x09, 0xC0, 0x27, 0x41, 0x9F, 0x20, 0x7C, 0x06,
+0xF0, 0x09, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x08, 0x04, 0x00, 0x1F, 0x00, 0x6C, 0x08, 0xF2, 0x01, 0xC0, 0x86, 0x14,
+0x1F, 0x02, 0x4C, 0x40, 0xF0, 0x01, 0xC0, 0x86, 0x03, 0x1F, 0x28, 0x7C, 0x00,
+0xF0, 0x11, 0xC4, 0x04, 0x01, 0x13, 0x10, 0x7C, 0x40, 0x30, 0x21, 0xC0, 0x50,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x14, 0x00,
+0x7D, 0x85, 0xC4, 0x81, 0xD0, 0x05, 0x58, 0xDC, 0x00, 0x5C, 0x00, 0xEC, 0x01,
+0xD0, 0x27, 0x41, 0x1F, 0x10, 0x7D, 0x00, 0x74, 0x01, 0xD0, 0x07, 0x40, 0xD8,
+0x40, 0x73, 0x02, 0xB4, 0x09, 0x15, 0x07, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x32, 0x00, 0xDD, 0x03, 0x74, 0x33,
+0xD0, 0x0C, 0x40, 0x71, 0x00, 0xDD, 0x00, 0x04, 0x0B, 0xD0, 0x2C, 0x41, 0xB2,
+0x00, 0xCC, 0x04, 0x74, 0x03, 0xD0, 0x0C, 0x40, 0x70, 0x00, 0xC1, 0x02, 0x34,
+0x03, 0x90, 0x0C, 0x40, 0x40, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x04, 0x80, 0x38, 0x00, 0xED, 0x00, 0x94, 0x03, 0xD1, 0x9E, 0x40, 0x99,
+0x28, 0xFD, 0x08, 0xA0, 0x03, 0xDA, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB6,
+0x13, 0xD0, 0x1E, 0x50, 0x3C, 0x04, 0xA9, 0x00, 0xF4, 0x03, 0x90, 0x1C, 0x41,
+0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x78,
+0x10, 0xFF, 0x01, 0xBC, 0x07, 0xF1, 0x5E, 0xC1, 0x6B, 0x00, 0xFE, 0x11, 0x8C,
+0x06, 0xC0, 0x12, 0xC0, 0x6A, 0x00, 0xEF, 0x21, 0xBC, 0x47, 0xF0, 0x1C, 0xE2,
+0x58, 0x00, 0xA3, 0x01, 0xBC, 0x07, 0xB0, 0x1E, 0xD0, 0x50, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB0, 0xB5, 0x05, 0x5F, 0x00, 0x6C,
+0x01, 0xF1, 0x2D, 0xC0, 0x06, 0x00, 0xDF, 0x06, 0x7C, 0x00, 0xF0, 0x01, 0xC0,
+0x27, 0x10, 0xDF, 0x00, 0x7C, 0x2B, 0xF0, 0x0D, 0xC0, 0x13, 0x00, 0x17, 0x40,
+0x7C, 0x03, 0x74, 0x0D, 0xD0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x06, 0x28, 0x7D, 0x04, 0x73, 0x01, 0xCD, 0x27, 0x30, 0x1F, 0xC2,
+0x7F, 0x02, 0xF7, 0x01, 0xCC, 0x05, 0xB4, 0x9F, 0xC8, 0x5F, 0x92, 0x6F, 0x09,
+0xDC, 0x07, 0xF0, 0x1F, 0xC0, 0x58, 0x40, 0xB3, 0x09, 0xCC, 0xA5, 0x30, 0x1F,
+0xC0, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x08,
+0x39, 0xA0, 0x61, 0x00, 0xAC, 0x03, 0x10, 0x4E, 0x48, 0x2B, 0x82, 0xE1, 0x00,
+0x84, 0x08, 0x10, 0x06, 0x40, 0x1B, 0x00, 0xED, 0x08, 0x84, 0x03, 0xD0, 0x06,
+0x50, 0x18, 0x02, 0xA1, 0x00, 0x85, 0x33, 0xB0, 0x0A, 0xC8, 0x56, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x39, 0x00, 0xC1, 0x08,
+0x94, 0x43, 0x18, 0x0E, 0x60, 0x2F, 0x84, 0xE5, 0x00, 0x84, 0x00, 0x10, 0x06,
+0x08, 0x1B, 0x00, 0x2D, 0x00, 0x94, 0x43, 0xD0, 0x8E, 0x40, 0x0E, 0x00, 0x81,
+0x80, 0xC4, 0x01, 0x18, 0x0E, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x28, 0x35, 0x00, 0x01, 0x00, 0x50, 0x02, 0x18, 0x0D,
+0x44, 0x63, 0x00, 0xC5, 0x02, 0x04, 0x00, 0x10, 0x00, 0x44, 0x83, 0x00, 0x8D,
+0x02, 0x04, 0x4F, 0xD0, 0x04, 0x40, 0xC2, 0x02, 0x01, 0x00, 0x44, 0x01, 0x90,
+0xA8, 0x40, 0x0A, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xA8, 0x3D, 0x00, 0x93, 0x00, 0x54, 0x28, 0x30, 0x0F, 0xC0, 0x67, 0x00, 0xF7,
+0x00, 0x4C, 0x02, 0x30, 0x09, 0x40, 0x27, 0x00, 0x9F, 0x06, 0xDC, 0x0F, 0xF0,
+0x0C, 0x40, 0x62, 0x08, 0x91, 0x00, 0x4C, 0x03, 0x11, 0x3D, 0xC8, 0x54, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x37, 0x00, 0x9F,
+0x02, 0x64, 0x02, 0xF0, 0x0D, 0xC0, 0x87, 0x28, 0xDA, 0x11, 0x7C, 0x0A, 0x70,
+0x09, 0xC0, 0x87, 0x10, 0xDF, 0x10, 0x7C, 0x03, 0xF0, 0x09, 0xC4, 0x05, 0x04,
+0x9F, 0xC0, 0x6C, 0x03, 0xF0, 0x2D, 0xC2, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x81, 0x08, 0x3F, 0x00, 0xB3, 0x80, 0x7C, 0x00, 0x31,
+0x0F, 0xE0, 0x0C, 0x04, 0xF7, 0x00, 0x7C, 0x02, 0xF0, 0x03, 0x40, 0x2F, 0x04,
+0x37, 0x00, 0xCC, 0x03, 0xF0, 0x0D, 0xC0, 0x0C, 0x40, 0xB2, 0x00, 0xFC, 0x02,
+0x70, 0x05, 0xC1, 0x05, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA1, 0x20, 0x36, 0x00, 0x91, 0x03, 0x74, 0x04, 0x10, 0x0D, 0x48, 0x44, 0x01,
+0xDD, 0x00, 0x74, 0x04, 0xD0, 0x11, 0x40, 0x47, 0x00, 0x4D, 0x00, 0x6C, 0x03,
+0xD0, 0x09, 0x40, 0x44, 0x00, 0x11, 0x07, 0x74, 0x02, 0x10, 0x44, 0x42, 0x84,
+0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x36, 0x00,
+0x11, 0x01, 0x74, 0x04, 0x10, 0x0D, 0x40, 0x64, 0x18, 0xDD, 0x00, 0x74, 0x06,
+0xD0, 0x1B, 0x60, 0xCF, 0x00, 0x1D, 0x58, 0x44, 0x03, 0xD0, 0x1D, 0x70, 0xC4,
+0x00, 0x35, 0x81, 0x74, 0x21, 0x50, 0x0D, 0x40, 0x05, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x01, 0x00, 0x24, 0x02,
+0x10, 0x0C, 0x40, 0x20, 0x00, 0xCD, 0x00, 0x34, 0x02, 0xD0, 0x00, 0x40, 0x02,
+0x20, 0xCD, 0x00, 0x24, 0x03, 0xD0, 0x00, 0x40, 0x04, 0x00, 0x05, 0x00, 0x64,
+0x83, 0x14, 0x08, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x10, 0x3A, 0x08, 0x93, 0x00, 0x7C, 0x00, 0x30, 0x0F, 0x40, 0x04,
+0x10, 0xE7, 0x00, 0x7C, 0x02, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x60, 0xCC,
+0x03, 0xF0, 0x0D, 0xC0, 0x04, 0x00, 0x17, 0x00, 0x7C, 0x00, 0x71, 0x05, 0xC0,
+0x05, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x38, 0x3F,
+0x20, 0xBF, 0x80, 0xFE, 0x02, 0xF0, 0x0F, 0xC0, 0x0B, 0x00, 0xFF, 0x00, 0xFC,
+0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x83, 0xF0, 0x03, 0xC8,
+0x0F, 0x00, 0x3B, 0x00, 0xBC, 0x00, 0xF0, 0x03, 0xC2, 0x17, 0x62, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x7F, 0x02, 0xFB, 0x09, 0xAC,
+0x07, 0xB0, 0x1F, 0xC0, 0x7A, 0x00, 0xFD, 0x21, 0xEC, 0x07, 0xB0, 0x1F, 0xC0,
+0x7A, 0x08, 0xFB, 0x89, 0xCC, 0x07, 0xF2, 0x1F, 0xC0, 0x7D, 0x12, 0xFB, 0x09,
+0xEC, 0x87, 0x33, 0x1E, 0xD2, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x00, 0x07, 0x01, 0x11, 0x04, 0x44, 0x04, 0x30, 0x11, 0x40,
+0x44, 0x00, 0x11, 0x01, 0x40, 0x00, 0x10, 0x40, 0x47, 0x44, 0x00, 0x0D, 0x00,
+0x44, 0x04, 0x10, 0x11, 0xC0, 0x05, 0x39, 0x11, 0x24, 0x44, 0x10, 0xB2, 0x11,
+0x44, 0x0C, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x35, 0x18, 0xD9, 0x60, 0x34, 0x03, 0xD0, 0x0D, 0x40, 0x36, 0x00, 0xD9, 0xA0,
+0x64, 0x53, 0x92, 0x0D, 0x40, 0x33, 0x00, 0xD5, 0x00, 0x44, 0x03, 0x90, 0x0C,
+0x40, 0x36, 0x00, 0xDD, 0x04, 0x34, 0x43, 0x19, 0x0C, 0x40, 0x4C, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA8, 0x07, 0x08, 0x11, 0x00,
+0x44, 0x00, 0xD1, 0x01, 0x40, 0x04, 0x08, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01,
+0x40, 0x05, 0x00, 0x1D, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x05, 0x18, 0x15,
+0x00, 0x14, 0x00, 0x90, 0x01, 0x40, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA0, 0x32, 0x20, 0xCB, 0x20, 0x6C, 0x03, 0xF0, 0x0D,
+0xC0, 0x36, 0x80, 0xCF, 0x00, 0x2C, 0x03, 0xB0, 0x0D, 0xC0, 0x37, 0x08, 0xDB,
+0x00, 0x4C, 0x03, 0xB0, 0x0C, 0x80, 0x36, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x32,
+0x0C, 0xC8, 0x20, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x88, 0x0D, 0x00, 0x3F, 0x80, 0xF8, 0x40, 0x30, 0x03, 0xC3, 0x0D, 0x80, 0x3E,
+0x00, 0xF8, 0x00, 0xF0, 0x03, 0xC0, 0x0E, 0x08, 0x3D, 0x00, 0xF8, 0x00, 0xB0,
+0x03, 0x82, 0x0F, 0x00, 0x3B, 0x30, 0xE8, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x35, 0x00, 0xD7,
+0x00, 0x6C, 0x03, 0x71, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x36, 0x04, 0xDF, 0x00, 0x5C, 0x93, 0x31, 0x0D, 0xC1, 0x34, 0x02,
+0xDF, 0x00, 0x7C, 0x03, 0x70, 0x0D, 0xC1, 0x09, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x84, 0x06, 0x11, 0x40, 0x34, 0x4C, 0x10,
+0x20, 0x41, 0x83, 0x24, 0x10, 0x00, 0x74, 0x04, 0x10, 0xB0, 0x00, 0x04, 0x00,
+0x02, 0x00, 0x04, 0x0C, 0x10, 0x31, 0x42, 0x03, 0x00, 0x0C, 0x03, 0x70, 0x80,
+0x10, 0x21, 0x40, 0x6C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0x20, 0x70, 0x10, 0xC5, 0x80, 0x24, 0x07, 0x40, 0x0C, 0x40, 0x33, 0x01,
+0xC5, 0x00, 0x24, 0x47, 0x50, 0xAC, 0x40, 0x31, 0x08, 0xC4, 0x00, 0x14, 0x0B,
+0x14, 0x3C, 0x00, 0x30, 0x04, 0xCD, 0x00, 0x34, 0x03, 0x98, 0x2C, 0x40, 0x0F,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x4C, 0x0A,
+0x21, 0x09, 0xF4, 0x04, 0x10, 0x12, 0x40, 0x4F, 0x00, 0x25, 0x37, 0xF6, 0x04,
+0x12, 0x12, 0x60, 0x49, 0x02, 0x21, 0x01, 0x84, 0x04, 0x00, 0x12, 0x41, 0x4B,
+0x02, 0x2D, 0x11, 0xB4, 0x24, 0x80, 0x12, 0x42, 0x3E, 0x20, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x30, 0x00, 0xC7, 0x00, 0x2C, 0x23,
+0x51, 0x8C, 0xC0, 0x33, 0x00, 0xCF, 0x08, 0x3C, 0x43, 0x70, 0x0C, 0xC4, 0x31,
+0x06, 0xC7, 0x00, 0x1C, 0x43, 0x30, 0x0C, 0xC0, 0x30, 0x00, 0xCF, 0x00, 0x7C,
+0x03, 0xF0, 0x0C, 0xE4, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x38, 0x09, 0x20, 0x3F, 0x00, 0xF0, 0x00, 0xF0, 0x03, 0xC2, 0x0F,
+0x00, 0x3B, 0x2C, 0xBC, 0x20, 0x70, 0x03, 0xC0, 0x0C, 0x02, 0x3F, 0x00, 0xBC,
+0x20, 0xF8, 0x83, 0xC0, 0x0F, 0x00, 0x1F, 0x00, 0xFC, 0x00, 0x71, 0x11, 0xC8,
+0x09, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x77,
+0x00, 0xC3, 0x40, 0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x00, 0xC7, 0x01, 0x6C,
+0x07, 0x36, 0x0D, 0xC4, 0x70, 0x00, 0xDB, 0x40, 0x6C, 0x03, 0xF0, 0x0C, 0xD0,
+0x34, 0x40, 0xD3, 0x00, 0x7C, 0x03, 0xB0, 0x0D, 0xC0, 0x43, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x98, 0x0D, 0x08, 0x2B, 0x00, 0x84,
+0x00, 0xD2, 0x02, 0x40, 0x0B, 0x00, 0x21, 0x60, 0x84, 0x00, 0x10, 0x02, 0x42,
+0x08, 0x00, 0x31, 0x00, 0x84, 0x00, 0x90, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0xB4, 0x00, 0x10, 0x02, 0x40, 0x4F, 0x68, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0xF9, 0x01, 0xA6, 0x07, 0xD9, 0x1E, 0x40,
+0x7B, 0x00, 0xF5, 0x01, 0xA4, 0x07, 0x10, 0x1E, 0x40, 0x78, 0x10, 0xE9, 0x01,
+0xB4, 0x07, 0xD0, 0x1E, 0x60, 0x78, 0x00, 0xE1, 0x01, 0xD4, 0x07, 0x90, 0x1E,
+0x60, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x20,
+0x03, 0x00, 0x19, 0x00, 0x06, 0x00, 0xD0, 0x00, 0x42, 0x03, 0x00, 0x05, 0x00,
+0x04, 0x00, 0x18, 0x00, 0x50, 0x01, 0x00, 0x01, 0x00, 0x14, 0x00, 0x90, 0x00,
+0x60, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x10, 0x00, 0x40, 0x5B, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x28, 0x15, 0x00, 0x5B, 0x80,
+0x2C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00, 0x57, 0x40, 0x6C, 0x01, 0x30, 0x05,
+0xCA, 0x14, 0x10, 0x5B, 0x00, 0x7C, 0x01, 0xF0, 0x04, 0xC0, 0x10, 0x00, 0x53,
+0x00, 0x7C, 0x01, 0xB0, 0x05, 0xC0, 0x5F, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x00, 0x8D, 0x08, 0x3F, 0x00, 0xFC, 0x08, 0xE0, 0x03,
+0xC0, 0x0F, 0x20, 0x39, 0x20, 0xFC, 0x08, 0xF0, 0x03, 0x00, 0x0E, 0x00, 0x3F,
+0x40, 0xE4, 0x80, 0xC2, 0x03, 0xC0, 0x8F, 0x00, 0x3B, 0x20, 0xFC, 0x00, 0xF0,
+0x03, 0xC0, 0x4B, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x22, 0x30, 0x49, 0xC0, 0x25, 0x00, 0x9F,
+0xC0, 0x7C, 0x02, 0xF1, 0x09, 0x80, 0xE5, 0x08, 0x9F, 0x00, 0x5C, 0x02, 0x70,
+0x09, 0xC0, 0x24, 0x00, 0x97, 0x01, 0x7C, 0x16, 0x30, 0x09, 0x80, 0x41, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xE4, 0x23, 0x9D,
+0x00, 0x45, 0x0A, 0x10, 0x18, 0x80, 0x26, 0x00, 0x9C, 0x11, 0x70, 0x06, 0xD0,
+0x28, 0x40, 0x64, 0x04, 0x8D, 0x80, 0x04, 0x02, 0x00, 0x09, 0x40, 0x64, 0x03,
+0x91, 0x02, 0x74, 0x0E, 0x10, 0x18, 0x40, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x80, 0xBD, 0x80, 0xC4, 0x02, 0x50,
+0x0B, 0x40, 0x2C, 0x01, 0xBC, 0x08, 0xF0, 0x22, 0xD2, 0x0B, 0x41, 0x2D, 0x00,
+0xBD, 0x00, 0xD4, 0x02, 0x42, 0x0B, 0x40, 0x2C, 0x00, 0xB5, 0x0A, 0xF4, 0xC2,
+0x00, 0x4B, 0x40, 0x71, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x29, 0x00, 0xAD, 0x00, 0xD4, 0x03, 0x54, 0x1B, 0x40, 0x6A, 0x20,
+0xAC, 0xA0, 0xB0, 0xA3, 0xD1, 0x8B, 0x40, 0x29, 0x00, 0xBD, 0x68, 0xC4, 0x02,
+0x51, 0x0B, 0x40, 0x28, 0x02, 0xA1, 0x08, 0xB0, 0x22, 0x11, 0x0B, 0x44, 0x51,
+0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x07, 0x08,
+0x1F, 0x80, 0x4C, 0x00, 0x74, 0x01, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x38, 0x08,
+0xF0, 0x20, 0xC0, 0x05, 0x00, 0x1F, 0x22, 0x5C, 0x00, 0x72, 0x01, 0xD0, 0x80,
+0x00, 0x17, 0x02, 0x78, 0x08, 0x34, 0x03, 0xC0, 0x75, 0xC0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x27, 0x05, 0x9F, 0x14, 0x6C, 0x02,
+0xB0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x12, 0xF0, 0x49, 0x80, 0x26,
+0x00, 0x9F, 0x04, 0x7C, 0x02, 0xB0, 0x09, 0xC0, 0x27, 0x01, 0x9F, 0x04, 0x3C,
+0x12, 0xF4, 0x09, 0xC0, 0x66, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1D, 0xA8, 0xAF, 0x00, 0x9F, 0x02, 0xF4, 0x02, 0x30, 0x0B, 0xC0, 0x2B,
+0x00, 0xBF, 0x80, 0xCC, 0x82, 0xF0, 0x0B, 0xD0, 0x2C, 0x00, 0x8B, 0x82, 0x8C,
+0x02, 0xB0, 0x0B, 0xC0, 0x2E, 0x00, 0xAF, 0x00, 0xCD, 0x0A, 0xB0, 0x0A, 0xC0,
+0x64, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x47,
+0x01, 0x0D, 0x05, 0x74, 0x00, 0xB0, 0x01, 0x40, 0x07, 0x08, 0x1D, 0x00, 0x6C,
+0x10, 0xD0, 0x41, 0x40, 0x04, 0x00, 0x11, 0x00, 0x54, 0x00, 0x10, 0x01, 0x40,
+0x00, 0x01, 0x1D, 0x00, 0x45, 0x10, 0x10, 0x01, 0x42, 0x70, 0x60, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA2, 0x21, 0x00, 0x8D, 0x00, 0x34,
+0x02, 0x10, 0x0C, 0x40, 0x23, 0x08, 0x9D, 0xA0, 0x04, 0x42, 0xD0, 0x08, 0x41,
+0x24, 0x00, 0x89, 0x00, 0x64, 0x02, 0x90, 0x09, 0x40, 0x22, 0x04, 0x8D, 0x00,
+0x44, 0x02, 0x90, 0x08, 0x50, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x20, 0x25, 0x10, 0x9D, 0x00, 0x74, 0x03, 0x90, 0x0D, 0x40,
+0x27, 0x00, 0x9D, 0x00, 0x64, 0x02, 0xD0, 0x09, 0x40, 0x24, 0x00, 0x91, 0x00,
+0x74, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x8C, 0x00, 0x44, 0x02, 0x10, 0x09,
+0x40, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28,
+0x25, 0x00, 0x9F, 0x00, 0x3C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x20,
+0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x20, 0x00, 0x9B, 0x00, 0x2C, 0x02, 0xB0, 0x08,
+0xC0, 0x26, 0x00, 0x9E, 0x00, 0x4C, 0x02, 0xB0, 0x09, 0xC0, 0x14, 0x28, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0x25, 0x00, 0x9F, 0x00,
+0x7C, 0x02, 0xF8, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0x00, 0x7C, 0x82, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x58, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC1, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x01, 0x1F, 0x00, 0x4D, 0x10, 0xF0, 0x01,
+0xC0, 0x07, 0x04, 0x17, 0x40, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x17,
+0x00, 0x5C, 0x40, 0x30, 0x81, 0xC0, 0x07, 0x00, 0x17, 0x00, 0x5C, 0x90, 0x34,
+0x01, 0xC0, 0x41, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA0, 0xDC, 0x01, 0x5D, 0x00, 0xC4, 0x05, 0xD0, 0x87, 0x48, 0x5F, 0x04, 0x71,
+0x07, 0xF4, 0x01, 0x10, 0x07, 0x40, 0x1F, 0x02, 0x51, 0x00, 0xC0, 0x11, 0x10,
+0xB7, 0x40, 0x5F, 0x00, 0x70, 0x01, 0x84, 0x01, 0x10, 0x06, 0x40, 0x50, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xB2, 0x08, 0xCD,
+0x00, 0x14, 0x0A, 0xD8, 0x2C, 0x40, 0xB3, 0x00, 0xD4, 0x11, 0x34, 0x07, 0x10,
+0x1D, 0x40, 0xA3, 0x00, 0xD5, 0x00, 0x14, 0x0E, 0x14, 0x1C, 0x40, 0x63, 0x00,
+0xC4, 0x05, 0x14, 0x2B, 0x14, 0x24, 0x40, 0x51, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x39, 0x00, 0xED, 0x01, 0x84, 0x08, 0xD1,
+0x0E, 0x40, 0x7F, 0x00, 0x61, 0x80, 0xB0, 0x0F, 0x10, 0x0E, 0x4D, 0x2F, 0x00,
+0xF1, 0x00, 0x84, 0x02, 0x10, 0x0E, 0x40, 0x6B, 0x04, 0xF5, 0x30, 0x84, 0x03,
+0x14, 0x07, 0x40, 0x04, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x18, 0x59, 0x00, 0xEF, 0x09, 0x9C, 0x05, 0xF1, 0x1A, 0xC0, 0x4B, 0x00,
+0xE7, 0x41, 0xFC, 0x07, 0x34, 0x16, 0xC0, 0x7B, 0x00, 0xE7, 0x77, 0x9C, 0x06,
+0x30, 0x1E, 0xC2, 0x7B, 0x00, 0x67, 0xE1, 0xDC, 0x06, 0x30, 0x16, 0x80, 0x45,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x00,
+0xDF, 0x00, 0x7C, 0x00, 0xF2, 0x01, 0xC4, 0x27, 0x00, 0xDF, 0x00, 0x7C, 0x00,
+0xE0, 0x05, 0xC0, 0x33, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC4, 0x17,
+0x00, 0x5B, 0x00, 0x7C, 0x02, 0xF0, 0x05, 0xC8, 0x43, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x7F, 0x22, 0xFF, 0x11, 0xF8, 0x04,
+0xF0, 0x9F, 0xC0, 0x7F, 0x00, 0xAF, 0x01, 0xDC, 0x86, 0x30, 0x9F, 0xC8, 0x6B,
+0x00, 0xFB, 0x01, 0xCC, 0x07, 0xF0, 0x1B, 0xE4, 0x6F, 0x00, 0xB3, 0x09, 0xC4,
+0x07, 0x30, 0x16, 0xC8, 0x0A, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x00, 0x39, 0x00, 0xED, 0x04, 0xBC, 0x40, 0xD8, 0x8A, 0x40, 0x2B,
+0x01, 0x2D, 0x00, 0x84, 0x22, 0x10, 0x8A, 0x42, 0x2B, 0x00, 0xE1, 0x08, 0x84,
+0x42, 0xD0, 0x02, 0x40, 0x2B, 0x01, 0xBB, 0x0C, 0xC4, 0x13, 0xB0, 0x0E, 0x40,
+0x54, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x19,
+0x30, 0xED, 0x40, 0xB4, 0x01, 0xD0, 0x0A, 0x48, 0x0B, 0x80, 0xED, 0x00, 0xB4,
+0x03, 0x94, 0x86, 0x44, 0x3F, 0x04, 0xE9, 0x00, 0x84, 0x03, 0xD0, 0x8A, 0x41,
+0x2B, 0x24, 0x21, 0x40, 0xD5, 0x00, 0x11, 0x07, 0x40, 0x22, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x83, 0x00, 0xCD, 0x09, 0x36,
+0x85, 0xD0, 0xA0, 0x40, 0xE3, 0x84, 0xCD, 0x0C, 0x74, 0x08, 0x90, 0x01, 0x40,
+0xD3, 0x00, 0xD1, 0x52, 0x04, 0x06, 0xD0, 0x00, 0x48, 0xD3, 0x80, 0x09, 0x03,
+0x14, 0x28, 0x90, 0xAC, 0x40, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xA0, 0xE5, 0x2C, 0xFF, 0x0B, 0x7C, 0x2C, 0xF0, 0x30, 0xC0,
+0x67, 0x01, 0xDF, 0x02, 0x7C, 0x19, 0xB0, 0xD9, 0xC0, 0xA7, 0x02, 0xFB, 0x87,
+0x4F, 0x02, 0xE0, 0x2C, 0x00, 0x07, 0x02, 0xD3, 0x11, 0x5D, 0x0D, 0x31, 0x95,
+0xC0, 0x56, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08,
+0xA7, 0x00, 0xDE, 0x60, 0x5C, 0x00, 0xF0, 0x21, 0xC0, 0x27, 0x00, 0x1F, 0x02,
+0x40, 0x01, 0x70, 0x25, 0xC0, 0x27, 0x20, 0xDF, 0x80, 0x7C, 0xCA, 0xF0, 0x09,
+0xC9, 0x07, 0x00, 0xDF, 0x52, 0x68, 0x41, 0xF0, 0x05, 0xC0, 0xA7, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x09, 0x2F, 0x14, 0xFF, 0x00,
+0xFC, 0x01, 0xF8, 0x03, 0xC1, 0x0E, 0x00, 0xFF, 0x01, 0xCC, 0x43, 0x30, 0x8B,
+0xC0, 0x6C, 0x20, 0xFF, 0x00, 0xCD, 0x06, 0xF0, 0x8F, 0xC8, 0x3C, 0x00, 0x77,
+0x05, 0xFC, 0x07, 0x34, 0x03, 0xC0, 0x15, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x89, 0x20, 0x66, 0x01, 0xDD, 0x00, 0x74, 0x08, 0xD8, 0x31,
+0x40, 0x64, 0x00, 0x8D, 0x05, 0x44, 0x08, 0x50, 0x05, 0x40, 0x34, 0x00, 0xDE,
+0x00, 0x44, 0x62, 0xD0, 0x19, 0x44, 0x90, 0x00, 0x91, 0x04, 0x74, 0x4B, 0x30,
+0x00, 0x40, 0x14, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0xA0, 0x46, 0x00, 0xDD, 0x80, 0x74, 0x00, 0xD0, 0x19, 0x00, 0x46, 0x00, 0x1D,
+0x08, 0x44, 0x08, 0x10, 0x09, 0x41, 0x25, 0x02, 0xD9, 0x00, 0x64, 0x03, 0xD0,
+0x09, 0x40, 0x84, 0x30, 0x95, 0x00, 0x30, 0x20, 0x02, 0x45, 0x40, 0x05, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xCD,
+0x00, 0x34, 0x00, 0xD0, 0x08, 0x44, 0x40, 0x00, 0x0D, 0x00, 0x05, 0x00, 0x50,
+0x00, 0x50, 0x20, 0x10, 0xC5, 0x00, 0x04, 0x01, 0xD0, 0x01, 0x10, 0x04, 0x88,
+0x41, 0x00, 0x34, 0x00, 0x11, 0x0C, 0x40, 0x40, 0xA0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x19, 0x06, 0x00, 0xFF, 0x00, 0x7C, 0x01, 0xD0,
+0x09, 0xC0, 0x06, 0x00, 0x5F, 0x00, 0x0C, 0x03, 0x30, 0x09, 0xC0, 0x24, 0x10,
+0xED, 0x00, 0x4C, 0x03, 0xF0, 0x09, 0xC0, 0x20, 0x20, 0x17, 0x00, 0x7C, 0x00,
+0x34, 0x01, 0xC0, 0x05, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xB8, 0x2D, 0x00, 0xFF, 0x00, 0xFC, 0x01, 0xF0, 0x03, 0xC0, 0x0F, 0x00,
+0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xC4, 0x1F, 0x00, 0xFF, 0x00, 0xFC, 0x01,
+0xF1, 0x03, 0xE0, 0x1F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0x70, 0x0B, 0xD0, 0x17,
+0x24, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x2F, 0x04,
+0xFF, 0x01, 0xEC, 0x52, 0xD0, 0x1F, 0xC0, 0x3E, 0x21, 0x2F, 0x01, 0xFC, 0x13,
+0x30, 0x0D, 0xC0, 0x57, 0x00, 0x8B, 0x21, 0xCE, 0x23, 0xB0, 0x6F, 0xC0, 0xBC,
+0x09, 0x3F, 0x04, 0xCC, 0x93, 0x33, 0x03, 0xC2, 0x0F, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x87, 0x10, 0xDD, 0x00, 0x74, 0x0E,
+0xD8, 0x1D, 0x40, 0x7F, 0x0A, 0x9D, 0x01, 0xF4, 0x2F, 0x10, 0x2F, 0x44, 0x57,
+0x10, 0x91, 0x00, 0x44, 0x33, 0x10, 0x2F, 0x40, 0xBC, 0x01, 0x5D, 0x09, 0xC4,
+0xDB, 0x10, 0x01, 0x40, 0x0F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x03, 0x05, 0xCD, 0x54, 0x34, 0x00, 0xD0, 0x0C, 0x40, 0x33,
+0x00, 0xCD, 0x01, 0x34, 0x03, 0x18, 0x2C, 0x40, 0x14, 0x00, 0xDD, 0x00, 0x15,
+0x13, 0xD0, 0x6C, 0x40, 0xB1, 0x08, 0x8D, 0x00, 0x54, 0x23, 0x10, 0x00, 0x40,
+0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x45,
+0x00, 0xDD, 0x04, 0x74, 0x84, 0xD1, 0x0D, 0x40, 0x37, 0x00, 0xDC, 0x00, 0x74,
+0x03, 0x10, 0x0D, 0x40, 0x17, 0x00, 0x95, 0x00, 0x64, 0x03, 0x50, 0x0D, 0x4A,
+0x35, 0x00, 0xDD, 0x00, 0x54, 0x03, 0x10, 0x11, 0x40, 0x0F, 0x20, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x67, 0x00, 0xDF, 0x20, 0x6C,
+0x14, 0xD0, 0x0D, 0xC0, 0x36, 0x00, 0x5F, 0xE8, 0x7C, 0x03, 0x31, 0x0D, 0xC0,
+0x42, 0x00, 0x8B, 0x40, 0x4C, 0x03, 0xF0, 0x0D, 0x40, 0x35, 0x10, 0x4E, 0x52,
+0x1C, 0x03, 0x14, 0x19, 0xC0, 0x23, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0F, 0x80, 0x05, 0x00, 0xFF, 0x41, 0xFC, 0x02, 0xF2, 0x2F, 0xC1,
+0x3F, 0x0C, 0x7F, 0x01, 0xB0, 0x03, 0xF0, 0x0F, 0xC0, 0x4F, 0x02, 0xB8, 0x40,
+0xD8, 0x03, 0xB0, 0x0F, 0xC0, 0x3E, 0x00, 0xFF, 0x03, 0xEC, 0x23, 0xF4, 0x03,
+0x40, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08,
+0x65, 0x01, 0xD3, 0x00, 0x7C, 0x0C, 0xF0, 0x0D, 0xC8, 0x37, 0x00, 0x5B, 0x00,
+0x4C, 0x43, 0xF0, 0x8D, 0xC0, 0x97, 0x00, 0xDF, 0x08, 0x5C, 0x03, 0xF1, 0x0D,
+0xC0, 0x37, 0x00, 0x5F, 0x00, 0x5C, 0x43, 0xF0, 0x89, 0xC0, 0x2B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x04, 0x00, 0xD1, 0x0B,
+0x74, 0x00, 0xD0, 0x3D, 0x40, 0xBF, 0x24, 0x51, 0x0A, 0xC4, 0x1B, 0xD0, 0xBF,
+0x40, 0x17, 0x06, 0x9C, 0x00, 0xC4, 0x03, 0xD0, 0x0F, 0x04, 0x3C, 0x10, 0xDC,
+0x01, 0x40, 0x0B, 0x10, 0xB9, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x20, 0xA0, 0x00, 0xC1, 0x01, 0x24, 0x02, 0xD0, 0x1C,
+0x40, 0x33, 0x00, 0x09, 0x0B, 0x34, 0x03, 0xD0, 0x1C, 0x60, 0x83, 0x08, 0x88,
+0x01, 0x54, 0x03, 0xD0, 0x0D, 0x40, 0x30, 0x00, 0x4D, 0x13, 0x10, 0x2F, 0x50,
+0x08, 0x40, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
+0x00, 0x78, 0x40, 0xE1, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x49, 0x7B, 0x00, 0xB5,
+0x09, 0xA4, 0x87, 0xD0, 0x5E, 0x40, 0x4B, 0x09, 0xAD, 0x25, 0x80, 0x07, 0xD0,
+0x1C, 0x40, 0x78, 0x00, 0xCD, 0x21, 0xC0, 0x27, 0x00, 0x12, 0x40, 0x3F, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x10, 0x02, 0xC3,
+0x18, 0x3C, 0x23, 0xF8, 0x0C, 0xC0, 0x33, 0x01, 0x8B, 0x08, 0x2C, 0x03, 0xF0,
+0x5C, 0x80, 0x43, 0x01, 0xCF, 0x05, 0x1C, 0x03, 0xF0, 0x4C, 0xC0, 0x31, 0x00,
+0x4F, 0x10, 0x5C, 0x37, 0x70, 0x0C, 0xC0, 0x4B, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x3D, 0x00, 0xFF, 0x08, 0xFC, 0x23, 0xF0,
+0x0F, 0xC8, 0x3B, 0x00, 0xFB, 0x68, 0xDC, 0x23, 0xF0, 0x2F, 0xC1, 0x0F, 0x20,
+0x9F, 0x00, 0x7C, 0x03, 0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0xFF, 0x08, 0x7C, 0xAB,
+0x52, 0x0F, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA8, 0x37, 0x00, 0xDF, 0x00, 0x78, 0x01, 0xF0, 0x0D, 0xC0, 0x36, 0x04,
+0x1F, 0x00, 0x4C, 0x63, 0xF0, 0x4D, 0xC8, 0x06, 0x08, 0x93, 0x00, 0x7C, 0x03,
+0xF1, 0xFD, 0xC0, 0xB6, 0x01, 0x5F, 0x01, 0x6C, 0x0A, 0x30, 0x0D, 0xC0, 0x40,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x90, 0x39, 0x00,
+0xED, 0x80, 0xB4, 0x03, 0xC1, 0x0E, 0xC0, 0x39, 0x01, 0xED, 0x00, 0x84, 0x03,
+0xD1, 0x4E, 0x42, 0x0A, 0x00, 0xA5, 0x00, 0xB4, 0x13, 0xD1, 0x0E, 0x41, 0x38,
+0x0D, 0xED, 0x00, 0x84, 0x02, 0x12, 0x06, 0xC0, 0x4E, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x28, 0xED, 0x21, 0xB0, 0x07,
+0xD9, 0x1E, 0x40, 0x7B, 0x03, 0xAD, 0x01, 0xA4, 0x17, 0xD0, 0x5E, 0x40, 0x4A,
+0x08, 0xE1, 0x21, 0xB4, 0x27, 0xD0, 0x1C, 0x40, 0x7A, 0x02, 0x7D, 0x01, 0xA4,
+0x06, 0x10, 0x1C, 0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x16, 0x00, 0x37, 0x04, 0x9D, 0x41, 0x34, 0x47, 0xD0, 0x08, 0x40, 0x31,
+0x00, 0xCD, 0x08, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x62, 0x80, 0x85, 0x00, 0x34,
+0x03, 0xD0, 0x0C, 0x40, 0x30, 0x00, 0xCD, 0x03, 0x04, 0x02, 0x10, 0x2D, 0x40,
+0x5A, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x28, 0x9F,
+0x00, 0x5D, 0x01, 0xFE, 0x1D, 0xF0, 0x15, 0xE1, 0x16, 0x00, 0x6F, 0x03, 0x6F,
+0x01, 0xF0, 0x05, 0xC0, 0x5A, 0x04, 0x53, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0,
+0x16, 0x00, 0x7F, 0x10, 0x6C, 0x45, 0x30, 0x47, 0xC0, 0x5C, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x05, 0x00, 0x1F, 0x08, 0x7E,
+0x00, 0xF0, 0x01, 0xA0, 0x07, 0x00, 0x1F, 0x04, 0x5E, 0x00, 0xF0, 0x20, 0x08,
+0x07, 0x01, 0x1F, 0x80, 0x7C, 0x00, 0xD0, 0x01, 0xC0, 0x03, 0x20, 0x1D, 0x24,
+0x7C, 0x00, 0xF0, 0x21, 0xD8, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x08, 0x65, 0x00, 0x93, 0xC1, 0x2C, 0x82, 0xE1, 0x19, 0xC0,
+0x25, 0x09, 0x9F, 0x00, 0x4C, 0x92, 0xD0, 0x19, 0xC0, 0x64, 0x10, 0x93, 0x08,
+0x3C, 0x02, 0x40, 0x09, 0xC4, 0x27, 0x00, 0x93, 0x80, 0x7C, 0x02, 0x75, 0x09,
+0xC1, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20,
+0x66, 0x00, 0x91, 0x81, 0x4C, 0x02, 0x10, 0x98, 0x00, 0xA5, 0x00, 0x9D, 0x18,
+0x45, 0x0A, 0xD0, 0xA9, 0x50, 0x24, 0x03, 0x95, 0x00, 0x74, 0x02, 0x13, 0x09,
+0x44, 0x27, 0x00, 0x91, 0x1B, 0x34, 0x06, 0x12, 0x69, 0x50, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x34, 0x82, 0x99, 0x08,
+0x64, 0x06, 0x10, 0x09, 0x00, 0xA4, 0x00, 0x99, 0x00, 0x54, 0x42, 0xD2, 0x09,
+0x45, 0x34, 0x00, 0x91, 0x00, 0x74, 0x02, 0x50, 0x09, 0x40, 0x27, 0x40, 0x91,
+0x00, 0x74, 0x12, 0x51, 0x0D, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x22, 0x30, 0x15, 0xC1, 0x00, 0x04, 0x52, 0x12, 0x19,
+0x42, 0x21, 0x80, 0x8D, 0x40, 0x06, 0x82, 0xD0, 0x08, 0x40, 0x24, 0x00, 0x85,
+0x00, 0x34, 0x22, 0x50, 0x88, 0x40, 0x23, 0x02, 0x81, 0x00, 0x70, 0xD2, 0x10,
+0x48, 0x41, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0x38, 0x07, 0x01, 0x1B, 0x00, 0x6C, 0x10, 0x70, 0x01, 0xC0, 0x05, 0x05, 0x1B,
+0x40, 0x48, 0xD0, 0xF0, 0xE1, 0xC1, 0x04, 0x00, 0x53, 0x0A, 0x7C, 0x58, 0x71,
+0x61, 0xC1, 0x87, 0x05, 0x13, 0x14, 0x38, 0x11, 0x70, 0x41, 0xC0, 0x74, 0xE0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x2D, 0x45, 0xBF,
+0x14, 0xDC, 0x02, 0xB4, 0x0B, 0xC0, 0x27, 0x00, 0xAC, 0x00, 0x7C, 0x02, 0xF0,
+0x19, 0xC0, 0x2B, 0x08, 0xBF, 0x01, 0x7C, 0x12, 0xB1, 0x49, 0xC0, 0x27, 0x11,
+0xAF, 0x00, 0xFC, 0x52, 0xF0, 0x4B, 0xC1, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xA0, 0xBF, 0x00, 0xB3, 0x00, 0xFC, 0x52, 0xF0,
+0x0B, 0xC0, 0x2D, 0x05, 0xB3, 0x00, 0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x2C, 0x00,
+0xBF, 0x80, 0x6C, 0x02, 0x10, 0x09, 0xC0, 0x24, 0x00, 0xBF, 0x00, 0xCC, 0x02,
+0x32, 0x0B, 0xD0, 0x74, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x87, 0x00, 0x1B, 0xA4, 0x74, 0x08, 0xD0, 0x01, 0x40, 0x84, 0x48,
+0x11, 0x20, 0x44, 0x00, 0xD2, 0xA1, 0x40, 0x05, 0x00, 0x1D, 0x00, 0x40, 0x90,
+0x10, 0x41, 0x40, 0x04, 0x01, 0x1D, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x60,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0, 0xA1, 0x21,
+0x81, 0x10, 0x30, 0x02, 0xD0, 0x08, 0x40, 0x21, 0x00, 0xD5, 0x00, 0x04, 0x0B,
+0xD0, 0x0D, 0x40, 0x20, 0x00, 0x8D, 0x80, 0x30, 0x4A, 0x11, 0x28, 0x41, 0xA2,
+0x04, 0x8D, 0x00, 0x05, 0x82, 0x14, 0x08, 0x40, 0x49, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x99, 0x04, 0x74, 0x02,
+0xD0, 0x49, 0x40, 0x26, 0x08, 0x95, 0x00, 0x44, 0x02, 0xC0, 0x09, 0x40, 0x25,
+0x0D, 0x9D, 0x80, 0x14, 0x02, 0x10, 0x08, 0x46, 0x26, 0x00, 0x9D, 0x10, 0x44,
+0x02, 0x10, 0x0D, 0x40, 0x60, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0x20, 0xE5, 0x06, 0x93, 0x40, 0x78, 0x1A, 0xD1, 0x09, 0xC0, 0x25,
+0x00, 0x97, 0x0F, 0x45, 0x02, 0xF0, 0x09, 0xC0, 0xA4, 0x00, 0x8F, 0x81, 0x7E,
+0x02, 0x34, 0x09, 0xD0, 0x26, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0x30, 0x49, 0xC0,
+0x15, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x24,
+0x00, 0x9F, 0xC0, 0x7C, 0x12, 0xF0, 0x09, 0xC8, 0x25, 0x00, 0x9B, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC0, 0x67, 0x00, 0x9F, 0x05, 0x6C, 0x02, 0xF0, 0x09, 0xC0,
+0x25, 0x00, 0x9F, 0x40, 0x7C, 0x02, 0xF0, 0x49, 0xC1, 0x5B, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x10, 0x78,
+0x08, 0xF0, 0x01, 0xC1, 0x01, 0x04, 0x1F, 0x04, 0x7C, 0x90, 0xB0, 0x01, 0xC0,
+0x84, 0x00, 0x1F, 0x10, 0x4C, 0x00, 0xF1, 0x01, 0xC0, 0x07, 0x10, 0x07, 0x10,
+0x3C, 0x04, 0x30, 0x21, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0xDC, 0x01, 0x7D, 0x07, 0x74, 0x01, 0x10, 0x26, 0x40,
+0x1F, 0x19, 0x6D, 0x00, 0xF4, 0x09, 0x10, 0x07, 0x40, 0xDC, 0x02, 0x7D, 0x03,
+0x44, 0x01, 0xD0, 0x05, 0x40, 0x17, 0x00, 0x71, 0x45, 0xF4, 0x41, 0x11, 0x27,
+0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0,
+0xF6, 0x01, 0xCD, 0x03, 0x34, 0x22, 0x58, 0x2C, 0x48, 0x73, 0x00, 0xCC, 0x00,
+0x34, 0x03, 0xD0, 0x0D, 0x40, 0x30, 0x00, 0xCD, 0x0A, 0x32, 0x03, 0xD0, 0x0C,
+0x40, 0x33, 0x80, 0xC5, 0x00, 0x34, 0x04, 0x90, 0xAD, 0x40, 0x40, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0x6D, 0x00,
+0xB4, 0x07, 0x5A, 0x2A, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xB0, 0x07, 0x52, 0x0A,
+0x40, 0x98, 0x00, 0xED, 0x00, 0x84, 0x13, 0xD0, 0x4E, 0x40, 0x7B, 0x81, 0xE1,
+0x00, 0xB4, 0x02, 0x90, 0x04, 0x44, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x18, 0x79, 0x08, 0xEF, 0x01, 0xBC, 0x87, 0x70, 0x1E,
+0xC0, 0x5B, 0x00, 0xEE, 0x01, 0xBC, 0x06, 0xF0, 0x1F, 0xC0, 0x78, 0x00, 0xBF,
+0x01, 0x9C, 0x07, 0xF0, 0xBE, 0xC4, 0x7F, 0x21, 0xE7, 0x01, 0xFC, 0x04, 0xB0,
+0x1E, 0xD0, 0x50, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xB2, 0x35, 0x00, 0x5F, 0x60, 0x3C, 0x03, 0x38, 0x01, 0xC8, 0x07, 0x00, 0xDF,
+0x00, 0x3C, 0x00, 0xB0, 0x05, 0xC0, 0x37, 0x00, 0x9F, 0x20, 0x7C, 0x2B, 0xF0,
+0x6D, 0xC8, 0xB7, 0x20, 0x9D, 0x00, 0x7C, 0x82, 0x71, 0x05, 0xC0, 0x43, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x7D, 0x02, 0xFF,
+0x81, 0xCC, 0x17, 0x71, 0x17, 0xC0, 0x6F, 0x02, 0xFF, 0x81, 0xFC, 0x85, 0xF0,
+0x9F, 0x40, 0x78, 0x02, 0xB3, 0x29, 0xFE, 0x2F, 0xB0, 0x1F, 0xE0, 0xFF, 0x04,
+0x73, 0x09, 0xFC, 0x27, 0xF1, 0x5F, 0xC0, 0x1B, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x19, 0x26, 0x6D, 0x08, 0xAC, 0x83, 0xD0,
+0x22, 0x40, 0x8B, 0x00, 0x2D, 0x00, 0xB4, 0x08, 0xD0, 0x1A, 0x40, 0x98, 0x00,
+0xA1, 0x01, 0xB4, 0x03, 0xD0, 0x0E, 0xC0, 0x39, 0x01, 0xEB, 0x00, 0x34, 0x07,
+0xD0, 0x0A, 0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x48, 0x08, 0x39, 0x18, 0xFD, 0x00, 0xA4, 0x13, 0xD0, 0x02, 0x40, 0x0B, 0x00,
+0xED, 0x10, 0xB4, 0x20, 0xD0, 0x0E, 0x40, 0x2B, 0x40, 0x21, 0x00, 0xB4, 0x83,
+0x91, 0x0E, 0x40, 0x39, 0x10, 0x61, 0x10, 0xB4, 0x02, 0xD0, 0x4E, 0x40, 0x23,
+0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x21, 0x00,
+0x1D, 0x01, 0x26, 0x07, 0xD0, 0x00, 0x40, 0x03, 0x00, 0x0D, 0x03, 0x34, 0x80,
+0xD0, 0x00, 0x40, 0xA3, 0x00, 0x01, 0x01, 0x34, 0x03, 0xD0, 0x0C, 0x48, 0x31,
+0x80, 0x85, 0x00, 0x34, 0x81, 0xD0, 0x29, 0x40, 0x0B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x04, 0x00, 0x9F, 0x01, 0x64, 0x0B,
+0x71, 0x09, 0xC0, 0x27, 0x90, 0x1F, 0x03, 0x7C, 0x02, 0xF0, 0x01, 0xC0, 0x27,
+0x20, 0xD3, 0x11, 0xFC, 0x03, 0xB0, 0x0F, 0xC0, 0x3D, 0x00, 0x81, 0x01, 0x7C,
+0x01, 0xD0, 0x29, 0xC0, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0D, 0x00, 0x87, 0x01, 0x9F, 0x08, 0x7C, 0x23, 0xF0, 0x19, 0xC0, 0x27,
+0x00, 0x1F, 0x32, 0x3E, 0x0A, 0xF0, 0x01, 0x40, 0x14, 0xA1, 0x9F, 0x00, 0x70,
+0x03, 0xD0, 0x0D, 0xC8, 0x35, 0x40, 0x9B, 0x10, 0x74, 0x01, 0xE0, 0x21, 0xC0,
+0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x08, 0x0B,
+0x00, 0xBB, 0x00, 0x8C, 0x43, 0xB0, 0x0B, 0xC4, 0x2B, 0x00, 0xF3, 0x00, 0xFC,
+0x02, 0x32, 0x01, 0xC4, 0x2F, 0x01, 0xBF, 0x40, 0xEC, 0x03, 0xF0, 0x0F, 0xC4,
+0x3B, 0x00, 0x37, 0x05, 0x94, 0x81, 0x33, 0x03, 0x81, 0x04, 0x28, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xC6, 0x21, 0x91, 0x07, 0x44,
+0x83, 0xB0, 0x31, 0x40, 0xE7, 0x00, 0xD1, 0x06, 0x74, 0x04, 0x10, 0x31, 0x48,
+0x77, 0x10, 0x9C, 0x01, 0x74, 0x03, 0x71, 0x0D, 0x40, 0x37, 0x00, 0x11, 0x32,
+0x44, 0x0B, 0x10, 0x31, 0x40, 0x85, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0xA0, 0x64, 0x00, 0x19, 0x01, 0x54, 0x07, 0x90, 0x19, 0x00,
+0x66, 0x00, 0x11, 0x01, 0x74, 0x06, 0x10, 0x13, 0x41, 0x07, 0x00, 0xB9, 0x01,
+0x74, 0x03, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0x55, 0x00, 0x54, 0x47, 0x50, 0x19,
+0x40, 0x05, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x00, 0x00, 0x01, 0x20, 0x14, 0x03, 0x90, 0x08, 0x62, 0x03, 0x00, 0x00, 0x00,
+0x34, 0x02, 0x14, 0x40, 0x40, 0x13, 0x00, 0x8D, 0x04, 0x34, 0x03, 0x50, 0x0C,
+0x40, 0x33, 0x08, 0xC1, 0x00, 0x14, 0x20, 0x10, 0x08, 0x42, 0x41, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x26, 0x08, 0x9B, 0x00,
+0x5E, 0x03, 0xB1, 0x09, 0xC0, 0x27, 0x40, 0xD1, 0x00, 0x7C, 0x02, 0x30, 0x41,
+0xC0, 0x07, 0x10, 0x1F, 0x1C, 0xEC, 0x03, 0xF1, 0x0F, 0xE4, 0x3B, 0x00, 0x57,
+0x00, 0x5C, 0x12, 0x34, 0x01, 0xC0, 0x05, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x45, 0xA8, 0x2F, 0x00, 0xAF, 0x00, 0xEC, 0x03, 0x70, 0x03,
+0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0xC1, 0xC1, 0x0F, 0x04, 0x1F,
+0x04, 0xFC, 0x03, 0x72, 0x0F, 0xC4, 0x3F, 0x00, 0x3F, 0x00, 0x6C, 0x30, 0xF0,
+0x03, 0xC4, 0x17, 0x62, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA0, 0x2D, 0x11, 0xBF, 0x00, 0xFC, 0x13, 0xB2, 0x93, 0xC8, 0x3D, 0x11, 0x13,
+0x08, 0xDC, 0x22, 0x32, 0x4F, 0xC8, 0x0F, 0x20, 0x7B, 0x41, 0xEC, 0x03, 0xF0,
+0x17, 0xC0, 0x3C, 0x00, 0xBF, 0x01, 0xEC, 0x00, 0x30, 0x03, 0xC4, 0x0C, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x47, 0x02, 0x9C,
+0x8C, 0xF4, 0x27, 0x04, 0x09, 0x4C, 0x7D, 0x22, 0x1D, 0x04, 0x74, 0x12, 0x50,
+0xAF, 0x42, 0x07, 0x00, 0x99, 0x81, 0x44, 0x0B, 0xD0, 0x09, 0x40, 0x3C, 0x10,
+0x9D, 0x40, 0x44, 0x00, 0x10, 0x11, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0x21, 0x08, 0x0D, 0x50, 0x34, 0x03, 0x18,
+0x51, 0x44, 0x31, 0x00, 0x0D, 0x20, 0x74, 0x02, 0x10, 0x0C, 0x64, 0x01, 0x00,
+0x89, 0x00, 0x24, 0x0B, 0xD0, 0x01, 0x50, 0x30, 0x00, 0x9D, 0x00, 0x24, 0x00,
+0x10, 0x00, 0x40, 0x4C, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA8, 0x47, 0x80, 0x1D, 0x51, 0x74, 0x03, 0x10, 0x11, 0x40, 0x35, 0x00,
+0x3D, 0x02, 0xF4, 0x02, 0x50, 0x0D, 0x00, 0x4F, 0x08, 0x89, 0x08, 0x44, 0x03,
+0xD2, 0x19, 0x00, 0x3C, 0x00, 0x9D, 0x01, 0x44, 0x04, 0x10, 0x11, 0x42, 0x0C,
+0xA0, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x67, 0x00,
+0x9F, 0x03, 0x7C, 0x03, 0x30, 0x18, 0xCC, 0x35, 0x18, 0x1B, 0x01, 0x5E, 0x06,
+0x20, 0x0D, 0xC0, 0xC7, 0x00, 0xDB, 0x00, 0x6C, 0x03, 0xF0, 0x1C, 0xC0, 0x34,
+0x20, 0xCF, 0x01, 0x6C, 0x84, 0x30, 0x11, 0xC0, 0x00, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x2D, 0x00, 0xBF, 0x80, 0xBC, 0x03,
+0xF0, 0x0B, 0xC0, 0x3E, 0x80, 0x1D, 0x03, 0xFC, 0x26, 0xF0, 0x0F, 0xC0, 0x2F,
+0x00, 0xBF, 0x01, 0xFC, 0x03, 0xF2, 0x0B, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC,
+0x00, 0xF4, 0x09, 0xD0, 0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x08, 0x25, 0x18, 0x93, 0x01, 0x7C, 0xA3, 0xF0, 0x01, 0xC0, 0x77,
+0x00, 0x1B, 0x02, 0x4C, 0x42, 0xF0, 0x0D, 0xC0, 0x87, 0x00, 0x9F, 0x00, 0x7C,
+0x03, 0x30, 0x09, 0x80, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC1,
+0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0, 0x64,
+0x04, 0x91, 0x02, 0xF4, 0x2F, 0xD0, 0x01, 0x40, 0xBF, 0x00, 0x11, 0x80, 0x45,
+0x47, 0xD1, 0x0F, 0x44, 0x27, 0x00, 0x9D, 0x00, 0xF4, 0x03, 0x10, 0x09, 0x40,
+0x3F, 0x00, 0x5D, 0x00, 0x34, 0x44, 0x10, 0x38, 0x58, 0x6C, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0x00, 0x60, 0x08, 0x30, 0x36,
+0x0F, 0xD8, 0x00, 0x40, 0x33, 0x01, 0x09, 0x00, 0x50, 0x0E, 0xD0, 0x9C, 0x22,
+0x43, 0x02, 0x4C, 0x80, 0x34, 0x03, 0x10, 0x00, 0x40, 0x33, 0x00, 0xCD, 0x06,
+0x34, 0x00, 0x14, 0xA0, 0x40, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0F, 0x00, 0x58, 0x02, 0xE9, 0x81, 0xB4, 0x07, 0xD0, 0x1A, 0x40,
+0x7B, 0x00, 0x21, 0x09, 0x84, 0x06, 0xD1, 0x9E, 0x40, 0x5B, 0x00, 0xAD, 0x01,
+0xB4, 0x07, 0x10, 0x1A, 0x40, 0x7B, 0x00, 0xED, 0x41, 0xB4, 0x07, 0x18, 0x9A,
+0x40, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x1A,
+0x30, 0x00, 0x4B, 0x08, 0x3C, 0x03, 0xF0, 0x80, 0xC0, 0x33, 0x00, 0x0B, 0x05,
+0x0C, 0x02, 0xF0, 0x0C, 0xC0, 0x43, 0x01, 0xCF, 0x00, 0x7C, 0x23, 0x34, 0x00,
+0x40, 0x33, 0x00, 0xCF, 0x00, 0x3C, 0x01, 0x30, 0x04, 0xC8, 0x48, 0x68, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x19, 0x00, 0xF0, 0x60,
+0xFC, 0x63, 0xF0, 0x0F, 0xC0, 0x3B, 0x02, 0xFF, 0x08, 0xF0, 0x23, 0xF0, 0x0F,
+0xC4, 0x1F, 0x02, 0xBF, 0x00, 0xFC, 0x83, 0xF0, 0x0B, 0xC0, 0xBF, 0x10, 0xFF,
+0x00, 0xBC, 0x03, 0xF1, 0x0D, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x17, 0x10, 0x53, 0x00, 0x74, 0x5F, 0x34, 0x09,
+0xC0, 0x37, 0x00, 0x1F, 0x00, 0x4C, 0x02, 0x31, 0x9D, 0x80, 0x74, 0x00, 0xD3,
+0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0xB7, 0x82, 0xCF, 0x00, 0x2C, 0x02, 0x30,
+0x15, 0xD0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0x8A, 0x39, 0x00, 0xE1, 0x00, 0x34, 0x13, 0x10, 0x0A, 0x40, 0xBB, 0x03, 0x8D,
+0x80, 0x84, 0x02, 0x12, 0x8C, 0x42, 0x3C, 0x08, 0xA1, 0x00, 0xB4, 0x13, 0xD0,
+0x0A, 0x40, 0x3A, 0x80, 0xED, 0x00, 0x84, 0x03, 0x10, 0x0E, 0x40, 0x4C, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x40, 0x69,
+0x01, 0xB4, 0x17, 0xD0, 0x1E, 0x40, 0x7B, 0x00, 0x6D, 0x11, 0x94, 0x46, 0x90,
+0x5E, 0x40, 0x68, 0x00, 0xE1, 0x01, 0xB4, 0x37, 0x90, 0x1E, 0x40, 0x7B, 0x00,
+0x7D, 0x61, 0xA4, 0x07, 0x14, 0x14, 0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0xB3, 0x00, 0xC9, 0x01, 0x34, 0x03, 0x50,
+0x8C, 0x40, 0x33, 0x00, 0xCD, 0xC3, 0x54, 0x07, 0x90, 0x0C, 0x50, 0x70, 0x01,
+0x81, 0x00, 0x34, 0x03, 0xD0, 0x48, 0x40, 0x36, 0x00, 0x4D, 0x09, 0x04, 0x03,
+0x10, 0x1C, 0x41, 0x58, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x17, 0xA0, 0x1F, 0x20, 0x7B, 0x85, 0x7C, 0x01, 0x78, 0x17, 0xC6, 0x17, 0x08,
+0x7F, 0x03, 0x5C, 0x05, 0xB6, 0x05, 0xC0, 0x5C, 0x01, 0x73, 0x02, 0x7C, 0x01,
+0xB0, 0x37, 0xC1, 0x17, 0x00, 0x7F, 0x09, 0xAC, 0x01, 0x30, 0x77, 0xC0, 0x5C,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x05, 0x24,
+0x17, 0x46, 0x7C, 0x00, 0xA0, 0x01, 0xE0, 0x83, 0x20, 0x1E, 0xA0, 0x6C, 0x00,
+0x70, 0x01, 0xC0, 0x87, 0x00, 0x1F, 0x04, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x06,
+0x00, 0x1F, 0x02, 0x7C, 0x04, 0xF0, 0x01, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0xA1, 0x00, 0x93, 0x08, 0x7C, 0x86,
+0xF0, 0x09, 0xC1, 0x25, 0x08, 0x93, 0x10, 0x4C, 0x02, 0x30, 0x09, 0xC0, 0x67,
+0x00, 0x9F, 0x00, 0x4C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x48,
+0x16, 0x30, 0x49, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x20, 0x26, 0x00, 0x95, 0x03, 0x74, 0x66, 0xD0, 0x09, 0x40, 0x27,
+0x20, 0x91, 0x00, 0x44, 0x0A, 0x10, 0x39, 0x44, 0xA7, 0x02, 0x8D, 0x20, 0x44,
+0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x85, 0x40, 0x44, 0x42, 0x10, 0x49, 0x40,
+0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x34,
+0x00, 0x91, 0x82, 0x74, 0x82, 0xD0, 0x09, 0x40, 0x67, 0x00, 0x81, 0x00, 0x54,
+0x0A, 0x10, 0x49, 0x49, 0xB7, 0x00, 0x9D, 0x00, 0x44, 0x02, 0xD0, 0x09, 0x40,
+0x27, 0x00, 0x91, 0x00, 0x55, 0x03, 0x10, 0x0D, 0x40, 0x63, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0xA5, 0x85, 0x14, 0x34,
+0x82, 0xD0, 0x88, 0x40, 0x33, 0x60, 0x81, 0x4C, 0x04, 0x32, 0x18, 0x08, 0x40,
+0x23, 0x01, 0x9D, 0x02, 0x04, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x01, 0x85, 0x00,
+0x14, 0xD2, 0x10, 0x48, 0x41, 0x43, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xB0, 0x07, 0x01, 0x13, 0x24, 0x7C, 0x50, 0xF0, 0x21, 0xC4,
+0x05, 0x05, 0x13, 0x03, 0x09, 0x0C, 0x30, 0xE1, 0xC1, 0xC7, 0x02, 0x1F, 0x00,
+0x4D, 0x78, 0xF0, 0xA1, 0xC8, 0xC7, 0x0A, 0x53, 0x00, 0x5C, 0x10, 0x32, 0x41,
+0xC0, 0x77, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8,
+0x2B, 0x00, 0xBF, 0x14, 0x7C, 0x02, 0xF0, 0x4B, 0xC0, 0x27, 0x00, 0xBF, 0x0C,
+0xFC, 0x32, 0xF4, 0x19, 0xC2, 0x6F, 0x02, 0xBD, 0x01, 0x7C, 0x06, 0xF0, 0x1B,
+0xC0, 0x67, 0x02, 0xFF, 0x14, 0xE4, 0x52, 0xF4, 0x0B, 0xC0, 0x77, 0x40, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x7F, 0x04, 0xBF, 0x02,
+0xFC, 0x02, 0xF0, 0x29, 0xC0, 0x2D, 0x20, 0x9F, 0x00, 0xFC, 0x0A, 0x30, 0x4B,
+0xC0, 0x2C, 0x00, 0x93, 0x02, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0x24, 0x00, 0xB3,
+0x00, 0xFC, 0x0A, 0x30, 0x0B, 0xC0, 0x74, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x08, 0x17, 0x00, 0x1D, 0x02, 0x74, 0x28, 0xD0, 0x00,
+0x48, 0x87, 0x02, 0x1D, 0x04, 0x5C, 0x10, 0x14, 0xA1, 0x50, 0x04, 0x00, 0x15,
+0x01, 0x74, 0x28, 0x10, 0x01, 0x40, 0x05, 0x00, 0x1B, 0x00, 0x74, 0x10, 0x10,
+0x01, 0xC0, 0x62, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x00, 0x21, 0x20, 0x8D, 0x86, 0x34, 0x02, 0xC0, 0x08, 0x40, 0x23, 0x00, 0x8D,
+0x10, 0x30, 0x12, 0x18, 0x08, 0x40, 0x24, 0x00, 0x81, 0x01, 0x34, 0x02, 0x14,
+0x08, 0x40, 0x20, 0x00, 0x81, 0x00, 0x34, 0x13, 0x10, 0x08, 0x44, 0x48, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0xDD,
+0x0A, 0x74, 0x02, 0xC0, 0x09, 0x40, 0x37, 0x00, 0x9D, 0x02, 0x14, 0x22, 0x10,
+0x09, 0x40, 0x24, 0x00, 0x95, 0x01, 0x34, 0x02, 0x10, 0x49, 0x44, 0x25, 0x00,
+0x99, 0x00, 0x34, 0x06, 0x14, 0x49, 0x40, 0x62, 0x20, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0x0A, 0x25, 0x10, 0x9F, 0x00, 0x7C, 0x02, 0xE0,
+0x29, 0xC1, 0x27, 0x00, 0x9F, 0x02, 0x7C, 0x02, 0x30, 0x08, 0xC6, 0x64, 0x02,
+0xB3, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0x24, 0x00, 0x93, 0x02, 0x7C, 0x06,
+0x30, 0x09, 0xC0, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x16, 0x00, 0xA5, 0x20, 0x9F, 0x21, 0x7C, 0x02, 0xF0, 0x39, 0xC0, 0x27, 0x04,
+0x9F, 0x04, 0x7C, 0x02, 0xF0, 0x09, 0x40, 0x67, 0x00, 0x9F, 0x00, 0x7C, 0x02,
+0xF2, 0x19, 0xC0, 0x23, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF2, 0x08, 0xC0, 0x5B,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00,
+0x1F, 0x04, 0x6C, 0x00, 0x70, 0x21, 0xC0, 0x04, 0x02, 0x1F, 0x02, 0x7C, 0x00,
+0x31, 0x01, 0xC0, 0x04, 0x00, 0x13, 0x40, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x07,
+0x08, 0x13, 0x0A, 0x7C, 0x04, 0x30, 0xC1, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0xDC, 0x0E, 0x7D, 0x06, 0xF4, 0x41,
+0x10, 0x05, 0x80, 0x5E, 0x00, 0x5D, 0x60, 0xF4, 0x6D, 0x10, 0x37, 0x40, 0x1C,
+0x00, 0x51, 0x00, 0x6C, 0x01, 0xD0, 0x05, 0x40, 0x17, 0x00, 0x75, 0x40, 0xF4,
+0x01, 0x10, 0x17, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA0, 0xE2, 0x00, 0xCD, 0x41, 0x24, 0x17, 0x80, 0x0C, 0x58, 0xF0,
+0x20, 0xCD, 0x00, 0x34, 0x0F, 0x90, 0x2C, 0x41, 0x74, 0x04, 0xC1, 0x00, 0x04,
+0x03, 0xD1, 0x0D, 0x40, 0x33, 0x00, 0x81, 0x10, 0x34, 0x03, 0x10, 0x2C, 0x40,
+0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x88, 0x29,
+0x80, 0xED, 0x80, 0xB4, 0x07, 0x94, 0xDE, 0x40, 0x28, 0x20, 0xEC, 0x08, 0x34,
+0x03, 0x90, 0x2C, 0x50, 0x20, 0x04, 0xF1, 0x45, 0xA4, 0x23, 0xD0, 0x0E, 0x40,
+0x3B, 0x00, 0x25, 0x00, 0x34, 0x03, 0x12, 0x0A, 0x40, 0x13, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x79, 0x00, 0xEF, 0x01, 0xAC,
+0x05, 0xB1, 0x5E, 0x41, 0x78, 0x00, 0xEF, 0x05, 0xBC, 0x05, 0xB0, 0x1A, 0xC0,
+0x78, 0x00, 0xF3, 0x43, 0x8C, 0x57, 0xF0, 0x1E, 0xC3, 0x73, 0x00, 0xA3, 0x01,
+0xBC, 0x07, 0x34, 0x12, 0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA8, 0x35, 0x00, 0x5F, 0x40, 0x3C, 0x00, 0x31, 0x4D, 0xC8,
+0x27, 0x08, 0xDF, 0x10, 0x7C, 0x01, 0x70, 0x09, 0xC8, 0x37, 0x40, 0xDF, 0x00,
+0x7C, 0x13, 0xF0, 0xCD, 0xC0, 0xB7, 0x02, 0x1F, 0x00, 0x7C, 0x03, 0xB4, 0x09,
+0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20,
+0x6D, 0x00, 0xFF, 0x01, 0xCC, 0x06, 0xF0, 0x9F, 0xC0, 0x5F, 0x02, 0xFF, 0x09,
+0xCC, 0x27, 0xF0, 0x1B, 0xC0, 0x7D, 0x00, 0xEF, 0x41, 0xCC, 0x87, 0x70, 0x1F,
+0xC0, 0xFC, 0x00, 0xE3, 0x01, 0xCC, 0x07, 0x30, 0x1F, 0xC8, 0x1B, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x29, 0x20, 0xFD, 0x00,
+0xAC, 0x1A, 0xD2, 0xCE, 0x40, 0x2B, 0x00, 0xFD, 0x00, 0x84, 0x04, 0xD0, 0x0F,
+0xC0, 0x20, 0x01, 0xED, 0x25, 0xC4, 0x07, 0x50, 0x0E, 0xC1, 0x3A, 0x20, 0x6B,
+0x00, 0x94, 0x03, 0xB0, 0x0A, 0x40, 0x57, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x08, 0x00, 0x29, 0x00, 0xED, 0x00, 0xB4, 0x02, 0xD2, 0x0E,
+0x60, 0x0B, 0x20, 0xED, 0x00, 0x96, 0x03, 0xD0, 0x02, 0x40, 0x1B, 0x80, 0xFD,
+0x05, 0xC4, 0x03, 0x11, 0x8E, 0x40, 0x38, 0x00, 0xF1, 0x00, 0x84, 0x43, 0x10,
+0x2E, 0x40, 0x23, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x28, 0xF1, 0x04, 0x8D, 0x13, 0x34, 0x02, 0xD0, 0x2D, 0x40, 0x23, 0x00, 0xC9,
+0x03, 0x54, 0x04, 0xD0, 0x00, 0x40, 0xC0, 0x10, 0xCD, 0x04, 0x04, 0x03, 0x58,
+0x3C, 0x41, 0x32, 0x00, 0x59, 0x00, 0x14, 0x07, 0x91, 0x0C, 0x40, 0x0B, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x25, 0x10, 0x1F,
+0x12, 0x7C, 0x02, 0xF0, 0x2F, 0xC0, 0x27, 0x00, 0xFF, 0x05, 0x5C, 0x46, 0xF0,
+0x05, 0xC0, 0x07, 0x01, 0xDF, 0x07, 0xCD, 0x03, 0x32, 0x0F, 0x40, 0x3C, 0x00,
+0x53, 0x00, 0x4C, 0x07, 0x30, 0x25, 0xC0, 0x57, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x27, 0x02, 0x9F, 0x00, 0x64, 0x08, 0xF0,
+0xCD, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0x6C, 0x02, 0xF0, 0x05, 0xC0, 0x87, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xE0, 0x0D, 0xC0, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x03,
+0xF0, 0x01, 0xC2, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x89, 0x09, 0x3F, 0x10, 0x2F, 0x00, 0xCC, 0x80, 0xF0, 0x0F, 0xC0, 0x08, 0x00,
+0xF3, 0x10, 0xFC, 0x20, 0x30, 0x03, 0xC0, 0x0F, 0x04, 0xFF, 0x00, 0xBC, 0x03,
+0x10, 0x0F, 0xC0, 0x3F, 0x10, 0xFF, 0x01, 0x4C, 0x65, 0xF0, 0x97, 0xC0, 0x07,
+0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0xB6, 0x00,
+0x1D, 0x21, 0x54, 0x04, 0xD0, 0x0D, 0x40, 0xC4, 0x00, 0xD1, 0x40, 0x74, 0x00,
+0x10, 0x21, 0x40, 0xC6, 0x01, 0xDD, 0x00, 0x74, 0x03, 0xB0, 0x0D, 0xC0, 0x35,
+0x00, 0xDD, 0x0B, 0x54, 0x00, 0xD0, 0x2D, 0x44, 0x87, 0x02, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x24, 0x14, 0x1D, 0x01, 0x46, 0x06,
+0xD0, 0x0D, 0x40, 0x44, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x10, 0x13, 0x41, 0x4F,
+0x80, 0xDD, 0x00, 0xF4, 0x03, 0x50, 0x0F, 0x40, 0x3F, 0x00, 0x9D, 0x10, 0x44,
+0x03, 0x90, 0x25, 0x40, 0x07, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x22, 0x20, 0x00, 0x8D, 0x80, 0x14, 0x00, 0xD8, 0x0C, 0x40, 0x20,
+0x00, 0xC1, 0x22, 0x34, 0x40, 0x14, 0x00, 0x40, 0x03, 0x00, 0xCD, 0x04, 0x34,
+0x13, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x8D, 0x00, 0x14, 0x07, 0xD0, 0x00, 0x40,
+0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, 0x06,
+0x00, 0x1F, 0x00, 0x4C, 0x02, 0xF0, 0x0F, 0xC0, 0x04, 0x00, 0xF1, 0x02, 0x74,
+0x13, 0x30, 0x01, 0xC0, 0x87, 0x02, 0xFF, 0x10, 0xFC, 0x53, 0x70, 0x0E, 0xC0,
+0x3B, 0x00, 0x9F, 0x00, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x07, 0x60, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xB0, 0x1F, 0x00, 0xBF, 0x80, 0xF8,
+0x00, 0xF0, 0x0F, 0xC2, 0x0F, 0x00, 0xFF, 0x20, 0x7C, 0x00, 0xF0, 0x03, 0xC0,
+0x0E, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xB1, 0x0F, 0xC0, 0x3D, 0x00, 0xBF, 0x00,
+0xFC, 0x83, 0xF0, 0x0F, 0xC0, 0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xFF, 0x09, 0xFC, 0x02, 0x30, 0x4B, 0xC1,
+0x3F, 0x13, 0xFF, 0x00, 0xCC, 0x13, 0x70, 0x83, 0xC0, 0x3C, 0x40, 0xF3, 0x00,
+0xBC, 0x06, 0xB0, 0x0F, 0xC0, 0x2C, 0x17, 0x3B, 0x0C, 0xCC, 0x00, 0xB0, 0x03,
+0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18,
+0x37, 0x01, 0xCD, 0x04, 0x74, 0xEA, 0x10, 0x69, 0xC8, 0xBD, 0x22, 0xFD, 0xDE,
+0xD4, 0x2F, 0x10, 0x01, 0x40, 0xFC, 0x00, 0xD1, 0x02, 0x44, 0x87, 0x10, 0x1F,
+0x40, 0xA5, 0x01, 0x11, 0x0E, 0x44, 0x08, 0x10, 0x01, 0x40, 0x0F, 0x60, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x33, 0x04, 0xCD, 0x00,
+0x34, 0x10, 0x50, 0x00, 0x41, 0x33, 0x09, 0xCD, 0x44, 0x14, 0x03, 0x10, 0x50,
+0x60, 0xB1, 0x00, 0xC5, 0x02, 0x14, 0x82, 0x90, 0x0D, 0x60, 0x34, 0x01, 0xC9,
+0x00, 0x04, 0x08, 0x12, 0x00, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA0, 0x35, 0x00, 0xDD, 0x04, 0x36, 0x0E, 0x54, 0x19,
+0x42, 0x37, 0x00, 0xDD, 0x00, 0x44, 0x03, 0x10, 0x12, 0x40, 0x35, 0x00, 0xD5,
+0x20, 0x55, 0x03, 0x10, 0x0F, 0x40, 0x55, 0x00, 0xC1, 0x18, 0x45, 0x63, 0x10,
+0x11, 0x40, 0x0F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xA8, 0x37, 0x00, 0xDD, 0x00, 0x7C, 0x06, 0x70, 0x31, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x4C, 0x03, 0x30, 0x11, 0x40, 0x35, 0x00, 0xD6, 0x00, 0x7C, 0x02, 0xB0,
+0x0D, 0xC0, 0x64, 0x80, 0x1B, 0x03, 0x4E, 0x07, 0x30, 0x19, 0xC0, 0x2B, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0xFD, 0x20, 0xFF,
+0x81, 0x7E, 0x02, 0xB0, 0x01, 0xC4, 0x3D, 0x00, 0xDF, 0x00, 0xBC, 0x43, 0xB0,
+0x0B, 0xC0, 0x3E, 0x10, 0xFA, 0x00, 0xEC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F, 0x00,
+0xFF, 0x80, 0x7C, 0x01, 0x70, 0x03, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xDF, 0x00, 0x4C, 0x08, 0x38,
+0x21, 0xC0, 0x34, 0x08, 0xD7, 0xC0, 0x4C, 0x03, 0x70, 0x01, 0xD1, 0x30, 0x00,
+0xDF, 0x84, 0x4D, 0x42, 0x32, 0x4D, 0xC0, 0x27, 0x00, 0x1B, 0x12, 0x3C, 0x02,
+0x30, 0x09, 0xC0, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1B, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x6C, 0x82, 0x10, 0x19, 0x41, 0x3C, 0x00,
+0xF1, 0x00, 0xC4, 0x4B, 0xD0, 0x19, 0x40, 0x3C, 0x01, 0xE7, 0x01, 0x04, 0x46,
+0x12, 0x3F, 0xC0, 0x11, 0x00, 0xDD, 0x00, 0x74, 0x1B, 0x10, 0xB9, 0x41, 0x4F,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x32, 0x00,
+0xCD, 0x00, 0x24, 0x00, 0x10, 0x58, 0x40, 0x30, 0x00, 0xD5, 0x00, 0x04, 0x0B,
+0x50, 0x20, 0x40, 0x32, 0x00, 0xC8, 0x2B, 0x04, 0x0A, 0x12, 0x0D, 0x44, 0x23,
+0x10, 0x09, 0x08, 0x34, 0x40, 0x90, 0x18, 0x40, 0x0E, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x7A, 0x00, 0xED, 0x01, 0xA4, 0x05,
+0x10, 0x1E, 0x40, 0x78, 0x00, 0xE1, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x41, 0x78,
+0x80, 0xE5, 0x01, 0xC4, 0x07, 0x10, 0x1E, 0x40, 0x79, 0x00, 0xED, 0x01, 0xB4,
+0x15, 0x90, 0x12, 0x40, 0x37, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x10, 0x32, 0x00, 0xCE, 0x40, 0x2C, 0x21, 0x10, 0x84, 0xC0, 0x34,
+0x02, 0xC7, 0x08, 0x06, 0x03, 0x70, 0x05, 0xC0, 0x32, 0x00, 0xCF, 0x40, 0x0C,
+0x02, 0x30, 0x0C, 0xC1, 0x23, 0x00, 0x0B, 0x04, 0x3C, 0x02, 0xB0, 0x0C, 0xC0,
+0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x3D,
+0x20, 0xFF, 0x80, 0xDD, 0x81, 0xF0, 0x8F, 0xC0, 0x3F, 0x00, 0xFF, 0x20, 0xFE,
+0x03, 0xF0, 0x0F, 0xC0, 0xBD, 0x04, 0xEF, 0x00, 0xFC, 0x03, 0xF5, 0x0F, 0xC0,
+0x1F, 0x00, 0xDF, 0x00, 0x7C, 0x13, 0x72, 0x0F, 0xC0, 0x0B, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x37, 0x20, 0xDF, 0x00, 0x7C,
+0x03, 0x70, 0x0D, 0xC0, 0x37, 0x01, 0xDF, 0x04, 0x7C, 0x13, 0xD1, 0x11, 0xD0,
+0x30, 0x01, 0xD3, 0x08, 0x4C, 0x06, 0x30, 0x5D, 0xC8, 0x20, 0x00, 0x17, 0x00,
+0x5C, 0x00, 0xB4, 0x0D, 0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0x88, 0x38, 0x10, 0xED, 0x20, 0xB6, 0x03, 0xD0, 0x0E, 0x40,
+0xBB, 0x03, 0xED, 0x28, 0xB4, 0x23, 0xD0, 0x0B, 0x40, 0x38, 0x00, 0xE1, 0x00,
+0xAC, 0x02, 0x50, 0xAE, 0x40, 0x38, 0x00, 0xE1, 0x40, 0xB4, 0x01, 0x10, 0x06,
+0x40, 0x4C, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+0x79, 0x80, 0xED, 0x81, 0x94, 0x07, 0xD8, 0x16, 0x40, 0x7B, 0x00, 0xED, 0x09,
+0xB4, 0x27, 0xD0, 0x16, 0x49, 0x78, 0x01, 0xE1, 0x05, 0x94, 0x06, 0x90, 0x5E,
+0x58, 0x6C, 0x40, 0x21, 0x03, 0x34, 0x06, 0x50, 0x1C, 0x40, 0x10, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x23, 0x80, 0x8D, 0x00,
+0x34, 0x07, 0xD8, 0xAC, 0x40, 0x33, 0x10, 0xCD, 0x00, 0x34, 0x03, 0xD0, 0x2C,
+0x40, 0x30, 0x80, 0xC1, 0x00, 0x34, 0x86, 0xD0, 0x0C, 0x40, 0x10, 0x00, 0xC1,
+0x10, 0x74, 0x2F, 0x50, 0x2D, 0x40, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x17, 0xA8, 0x17, 0x01, 0x5F, 0x00, 0xFC, 0x0D, 0x72, 0x17,
+0xCA, 0x17, 0x08, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0x48, 0x14, 0x00, 0x43,
+0x00, 0x54, 0x01, 0xB0, 0x05, 0xC4, 0x1C, 0x01, 0x73, 0x03, 0xDC, 0x2D, 0x70,
+0x47, 0xC0, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x00, 0x05, 0x20, 0x1F, 0x00, 0x7C, 0x60, 0xF8, 0x01, 0xC1, 0x07, 0x00, 0x0F,
+0x00, 0x7C, 0x08, 0xF0, 0x41, 0xC8, 0x03, 0x40, 0x1F, 0x00, 0x64, 0x20, 0x73,
+0x01, 0xC0, 0x07, 0x20, 0x19, 0x02, 0x7C, 0x00, 0xB0, 0x21, 0xD0, 0x4B, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x9F,
+0x00, 0x78, 0x02, 0xF0, 0x89, 0xC2, 0x27, 0x00, 0x9B, 0x00, 0x4C, 0x06, 0xF0,
+0x09, 0xC0, 0x25, 0x01, 0x93, 0x09, 0x5C, 0x02, 0xF0, 0x99, 0xC0, 0x23, 0x00,
+0x97, 0x28, 0x44, 0x82, 0x31, 0x09, 0xC1, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xD0,
+0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x0E, 0xD0, 0x29, 0x40, 0x27, 0x00,
+0x91, 0x03, 0x44, 0x02, 0xD0, 0x39, 0x40, 0x27, 0x00, 0x91, 0x07, 0x44, 0x0A,
+0x10, 0x29, 0x51, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x70, 0x02, 0xD0, 0x0D, 0x40, 0x27, 0x00,
+0x9D, 0x00, 0x44, 0x1A, 0xD0, 0x29, 0x00, 0x27, 0x40, 0x91, 0x02, 0x54, 0x02,
+0xD8, 0x09, 0x41, 0x27, 0x00, 0x85, 0x00, 0x54, 0x02, 0x10, 0x0D, 0x40, 0x70,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x20, 0x00,
+0x8D, 0x00, 0x34, 0x52, 0xD0, 0x4C, 0x41, 0x23, 0x02, 0x8D, 0x08, 0x04, 0x82,
+0xD0, 0xC8, 0x40, 0x23, 0x00, 0x81, 0x14, 0x04, 0x03, 0xD9, 0x48, 0x40, 0x23,
+0x00, 0x81, 0x08, 0x14, 0x82, 0x14, 0x48, 0x41, 0x50, 0xA0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x40, 0x7C, 0x10,
+0xF0, 0x41, 0xC0, 0x87, 0x05, 0x1B, 0x16, 0x4C, 0x50, 0xF0, 0x31, 0xC0, 0x05,
+0x05, 0x03, 0x0E, 0x5C, 0x00, 0xF0, 0x11, 0xC0, 0x87, 0x05, 0x17, 0x16, 0x5D,
+0x51, 0x30, 0x41, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0xB8, 0x2F, 0x0D, 0xBF, 0x34, 0xFC, 0x52, 0xF0, 0x4B, 0xC1, 0x27,
+0x01, 0x9F, 0x04, 0x7D, 0x82, 0xF0, 0xCB, 0x80, 0x27, 0x00, 0x9F, 0x01, 0xBC,
+0x02, 0xF0, 0x88, 0xC0, 0x2F, 0x04, 0xBF, 0x04, 0xEC, 0x52, 0xF8, 0x4B, 0xC1,
+0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0xA7,
+0x00, 0xDF, 0x02, 0x54, 0x1E, 0xF0, 0x2B, 0xC0, 0x25, 0x01, 0x9F, 0x54, 0xFC,
+0x12, 0x30, 0x8B, 0xC0, 0x2E, 0x05, 0xB3, 0x01, 0xCC, 0x02, 0xF0, 0x0B, 0xC0,
+0xA4, 0x00, 0xBF, 0x00, 0xCC, 0x02, 0x32, 0x0B, 0xC0, 0x60, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18, 0x03, 0x20, 0x1D, 0x01, 0x6E,
+0x08, 0x10, 0x85, 0x40, 0x00, 0x05, 0x0D, 0x04, 0x74, 0x80, 0x10, 0x01, 0x50,
+0x84, 0x00, 0x11, 0x00, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x54, 0x01, 0x1D, 0x40,
+0x44, 0x00, 0xBA, 0x05, 0xC0, 0x72, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0xA0, 0x21, 0x81, 0x9D, 0x00, 0x04, 0xB2, 0x58, 0x48, 0x40,
+0x21, 0x02, 0x8D, 0x14, 0x34, 0x0A, 0x12, 0x48, 0x44, 0x20, 0x00, 0x81, 0x22,
+0x04, 0x02, 0xD0, 0x08, 0x50, 0x21, 0x01, 0x8D, 0x00, 0x14, 0x02, 0x10, 0x08,
+0x40, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20,
+0x25, 0x80, 0x9D, 0x00, 0x64, 0x62, 0x58, 0x0D, 0x40, 0x24, 0x00, 0x9C, 0x00,
+0x70, 0x02, 0x00, 0x0C, 0x60, 0x24, 0x40, 0x91, 0x00, 0x45, 0x02, 0xD0, 0x0D,
+0x40, 0x25, 0x22, 0x9D, 0x80, 0x54, 0x2A, 0x90, 0x09, 0x40, 0x62, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x67, 0x00, 0x8D, 0x40,
+0x44, 0x06, 0x68, 0x09, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x3C, 0x02, 0x30, 0x19,
+0xC4, 0x26, 0x00, 0x93, 0x00, 0x4C, 0x02, 0xF0, 0x09, 0x40, 0x25, 0x00, 0x9D,
+0x0F, 0x5C, 0x06, 0x30, 0x29, 0xC0, 0x14, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x80, 0x24, 0x01, 0x9F, 0x04, 0x3C, 0x02, 0xB0, 0x59,
+0xC0, 0x27, 0x08, 0x9F, 0x00, 0x7E, 0x02, 0xF4, 0x49, 0xC0, 0x21, 0x00, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x08, 0xC0, 0x66, 0x00, 0x9F, 0x11, 0x6D, 0x42, 0xF2,
+0x49, 0xC1, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x05, 0x48, 0x1B, 0x00, 0x7C, 0x00, 0xB8, 0x21, 0xC1, 0x07, 0x00, 0x17,
+0x00, 0x4C, 0x00, 0xF0, 0x01, 0xC0, 0x06, 0x00, 0x13, 0x00, 0x5C, 0x20, 0xF0,
+0x11, 0xC0, 0x05, 0x00, 0x07, 0x22, 0x4C, 0x08, 0xE0, 0x21, 0xD0, 0x40, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x14, 0x00, 0x51,
+0x00, 0x74, 0x01, 0xB8, 0x07, 0x40, 0x17, 0x00, 0x51, 0x00, 0xC4, 0x09, 0xD0,
+0x17, 0xC0, 0x14, 0x00, 0x73, 0x81, 0xC4, 0x29, 0xD0, 0x07, 0x40, 0x14, 0x00,
+0x71, 0x02, 0xC0, 0x45, 0xD1, 0x07, 0x40, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xC1, 0x80, 0x34, 0x03, 0x93,
+0x8D, 0x46, 0x33, 0x00, 0xC5, 0x00, 0x14, 0x17, 0xD0, 0x0C, 0x40, 0x22, 0x30,
+0x59, 0x8F, 0x14, 0x02, 0xC8, 0x1C, 0x40, 0x31, 0x80, 0xC5, 0x03, 0x45, 0x0B,
+0xD0, 0x8D, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x88, 0x78, 0x09, 0xE1, 0x00, 0xB4, 0x13, 0x10, 0x0E, 0x40, 0x7B, 0x03,
+0xE4, 0x0D, 0x91, 0x43, 0xD0, 0x28, 0x40, 0x30, 0x00, 0x01, 0x00, 0xA4, 0x01,
+0xD1, 0x0E, 0x41, 0x78, 0x00, 0xE1, 0x02, 0x84, 0x03, 0xD0, 0x04, 0x40, 0x04,
+0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x10, 0x79, 0x04,
+0xE3, 0x0D, 0xB4, 0x0F, 0x90, 0x1E, 0xC0, 0x7B, 0x04, 0xE7, 0x15, 0x9C, 0x07,
+0xF0, 0x16, 0xE0, 0x6A, 0x00, 0x2B, 0x01, 0x9C, 0x04, 0xF0, 0x1E, 0xC0, 0x7D,
+0x00, 0x77, 0x01, 0x8D, 0x07, 0xF0, 0x1E, 0xC4, 0x44, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0x35, 0x23, 0xD7, 0x80, 0x7C, 0x43,
+0xF0, 0x0D, 0xC0, 0xB7, 0x01, 0xDB, 0x04, 0x6C, 0x03, 0xF0, 0x01, 0xC2, 0x27,
+0x40, 0x1F, 0x22, 0x5C, 0x01, 0xF0, 0x08, 0xC0, 0x37, 0x08, 0x5F, 0x00, 0x7C,
+0x01, 0xF2, 0x05, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x20, 0x7D, 0x00, 0xF3, 0x19, 0xF8, 0x27, 0x78, 0x9F, 0xC0, 0x7D,
+0x00, 0xF3, 0x01, 0xBC, 0x06, 0x30, 0x1F, 0xC0, 0x6F, 0x00, 0x63, 0x83, 0xCC,
+0x04, 0xF0, 0x17, 0xC4, 0x78, 0x00, 0xB3, 0x01, 0xCE, 0x25, 0x30, 0x1F, 0xC0,
+0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x39,
+0x1A, 0xEB, 0x38, 0xB4, 0x03, 0x70, 0x0E, 0x40, 0x38, 0x02, 0xE1, 0x00, 0xB4,
+0x80, 0x10, 0x0E, 0x40, 0x3B, 0x01, 0x65, 0x00, 0x84, 0x08, 0xD0, 0x56, 0x40,
+0x39, 0x00, 0xA1, 0x02, 0x84, 0x28, 0x10, 0x62, 0xC0, 0x56, 0x60, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x04, 0xE1, 0x88, 0xB4,
+0x03, 0xD8, 0x06, 0x45, 0x31, 0x40, 0xE9, 0x00, 0xB4, 0x23, 0x90, 0x06, 0x40,
+0x23, 0x80, 0xA9, 0x00, 0x84, 0x00, 0xD0, 0x4C, 0x40, 0x3E, 0x00, 0x05, 0x08,
+0x05, 0x81, 0x10, 0x06, 0x40, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x20, 0x75, 0x00, 0xD8, 0x00, 0x74, 0x07, 0xDA, 0x19, 0x41,
+0x30, 0x00, 0xC9, 0x00, 0x34, 0x01, 0x93, 0x25, 0x40, 0x27, 0x00, 0x1D, 0x00,
+0x04, 0x20, 0xD0, 0x08, 0x40, 0x71, 0x40, 0x45, 0x01, 0x44, 0x80, 0x18, 0x21,
+0x40, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8,
+0x7D, 0x00, 0xF3, 0x01, 0xFC, 0x13, 0xF0, 0x01, 0xC4, 0x3D, 0x00, 0xFB, 0x80,
+0x7E, 0x01, 0xB0, 0x5D, 0xC0, 0x27, 0x00, 0x1B, 0x00, 0x4D, 0x84, 0xF0, 0x09,
+0xC0, 0x7C, 0x04, 0xD5, 0x13, 0x4C, 0x3E, 0x36, 0x29, 0xC0, 0x55, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xDF, 0x40,
+0x7C, 0x43, 0x70, 0x01, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x3E, 0x08, 0x72, 0x01,
+0xC0, 0x37, 0x00, 0x17, 0x02, 0x7C, 0x01, 0xF0, 0x01, 0xC0, 0x37, 0x0C, 0xDA,
+0x04, 0x7C, 0x0A, 0xF0, 0x29, 0x80, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x84, 0x08, 0x3F, 0x00, 0xF3, 0x00, 0xCE, 0x83, 0x30, 0x01,
+0xC0, 0x38, 0x00, 0xF3, 0x00, 0xFE, 0x83, 0x32, 0x1F, 0xC1, 0x2C, 0x10, 0x33,
+0x00, 0xCC, 0x14, 0xF0, 0x0B, 0x80, 0x3B, 0x00, 0x63, 0x08, 0xCC, 0x02, 0xF0,
+0x09, 0xD1, 0x10, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85,
+0x20, 0x36, 0x00, 0xD1, 0x20, 0x44, 0x03, 0x18, 0x11, 0x40, 0x35, 0x00, 0xD1,
+0x00, 0x74, 0x12, 0x50, 0x21, 0xC0, 0x26, 0x00, 0x1B, 0x23, 0x6C, 0x09, 0xD0,
+0x21, 0x00, 0x37, 0x00, 0x91, 0x02, 0x44, 0x04, 0x10, 0x19, 0x40, 0x14, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x10, 0xD1,
+0x00, 0x44, 0x03, 0x10, 0x19, 0x40, 0x34, 0x40, 0xD1, 0x00, 0x54, 0x10, 0x50,
+0x49, 0x40, 0x24, 0x00, 0x31, 0x11, 0x44, 0x00, 0xD0, 0x15, 0x40, 0x37, 0x00,
+0x91, 0x00, 0x44, 0x86, 0x50, 0x19, 0x40, 0x04, 0x08, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x2A, 0x30, 0x00, 0xC1, 0x00, 0x04, 0x83, 0x10,
+0x08, 0x48, 0x31, 0x00, 0xC1, 0x00, 0x34, 0x00, 0x10, 0x01, 0x40, 0x36, 0x80,
+0x19, 0x00, 0x20, 0x01, 0xD0, 0x44, 0x44, 0x33, 0x00, 0x01, 0x60, 0x04, 0x82,
+0x12, 0x08, 0x40, 0x40, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x3C, 0x08, 0xF3, 0x00, 0xC4, 0x03, 0x10, 0x01, 0x40, 0x3C, 0x00,
+0xF3, 0x00, 0x7C, 0x03, 0x70, 0x09, 0xC0, 0x24, 0x00, 0x33, 0x00, 0x4C, 0x00,
+0xF1, 0x4D, 0xC1, 0x37, 0x40, 0x13, 0x00, 0x4D, 0x02, 0x70, 0x01, 0xC0, 0x00,
+0xC4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xA8, 0x3B, 0x00,
+0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xFF, 0x40, 0xF4, 0x00,
+0xF1, 0x03, 0xC8, 0x2F, 0x00, 0x3E, 0x20, 0xFC, 0x81, 0xF0, 0x01, 0xC0, 0x3F,
+0x20, 0x3F, 0x00, 0xFD, 0x00, 0xE0, 0x03, 0xC0, 0x17, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x3B, 0x04, 0xFF, 0xC0, 0xFC, 0x43,
+0xB2, 0x4F, 0xC0, 0x3D, 0x00, 0xEF, 0x04, 0xEC, 0x23, 0xF1, 0x12, 0xC0, 0x35,
+0x03, 0x7B, 0x01, 0xFC, 0x42, 0xB0, 0x13, 0xC0, 0x2E, 0x00, 0xBB, 0x01, 0xEC,
+0x86, 0x30, 0x03, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x08, 0xFF, 0x00, 0xFD, 0x0C, 0xF4, 0x8F, 0xD0, 0x9F, 0x48, 0xFC,
+0x22, 0xDD, 0x03, 0xC4, 0x3B, 0xD2, 0x19, 0x40, 0xB4, 0x01, 0x91, 0xE1, 0x74,
+0x0E, 0x10, 0x05, 0x43, 0x74, 0x00, 0x91, 0x01, 0x44, 0x03, 0x13, 0x11, 0x48,
+0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33,
+0x18, 0xCD, 0x50, 0x34, 0x03, 0xC0, 0x0C, 0x40, 0x32, 0x00, 0xCD, 0x42, 0x24,
+0x13, 0xD2, 0x01, 0x60, 0xB1, 0x00, 0xCD, 0x00, 0x34, 0x02, 0xD0, 0x41, 0x40,
+0x22, 0x00, 0x4D, 0x00, 0x74, 0x04, 0x10, 0x00, 0x40, 0x47, 0x80, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x34, 0x08, 0xDD, 0x00, 0x74,
+0x83, 0xD0, 0x0D, 0x40, 0x36, 0x08, 0xDD, 0x00, 0x44, 0x83, 0xD0, 0x11, 0x48,
+0x34, 0x08, 0x99, 0x00, 0x74, 0x07, 0x51, 0x81, 0x41, 0x34, 0x00, 0xD5, 0x08,
+0x56, 0x91, 0x10, 0x19, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA8, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xA0, 0x0D, 0xC0,
+0x36, 0x20, 0xDF, 0x20, 0x6C, 0x03, 0xF2, 0x38, 0xC8, 0x35, 0x30, 0xDB, 0x08,
+0x7C, 0x02, 0xF0, 0x35, 0x86, 0x62, 0x00, 0xCF, 0x03, 0x3C, 0x07, 0x30, 0x11,
+0xC0, 0x03, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80,
+0x3D, 0x24, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0xFF, 0x00,
+0xFC, 0x03, 0xE0, 0x0B, 0x80, 0x36, 0x00, 0xB5, 0x00, 0xBC, 0x43, 0xB0, 0x17,
+0xC0, 0x7F, 0x0A, 0xFB, 0x00, 0xEC, 0x01, 0xF2, 0x0B, 0xC0, 0x1F, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xD7, 0x04,
+0x7C, 0x03, 0x71, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x5C, 0x03, 0xF0, 0x21,
+0xC0, 0x35, 0x00, 0xD7, 0x00, 0x7C, 0x22, 0xF0, 0x21, 0xC0, 0x27, 0x00, 0x5F,
+0x00, 0x7C, 0x11, 0x30, 0x81, 0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x3C, 0x00, 0xF1, 0x82, 0xF4, 0x8F, 0x18, 0x5E,
+0x44, 0xFF, 0x24, 0xED, 0x02, 0xC4, 0x03, 0xD2, 0x81, 0x41, 0x7C, 0x00, 0x9B,
+0x00, 0x74, 0x0F, 0xC0, 0x00, 0x40, 0x37, 0x00, 0xDC, 0x09, 0x40, 0x09, 0x10,
+0x09, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0xA0, 0xF2, 0x00, 0xC5, 0x01, 0x34, 0x17, 0x51, 0x0C, 0x40, 0xB2, 0x04, 0xCD,
+0x10, 0x14, 0x03, 0xD0, 0x00, 0x40, 0x37, 0x02, 0x05, 0x00, 0x34, 0x0B, 0xC0,
+0x00, 0x4A, 0x33, 0x10, 0x4C, 0x01, 0x14, 0x03, 0x10, 0x00, 0x41, 0x1F, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x78, 0x06, 0xE1,
+0xB1, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x7B, 0x20, 0xED, 0x89, 0x94, 0x07, 0xD0,
+0x1E, 0x42, 0x7A, 0x01, 0xA9, 0x81, 0xB4, 0x87, 0xD0, 0x16, 0x40, 0x6B, 0x00,
+0x6D, 0x31, 0xC0, 0x07, 0x10, 0x12, 0x40, 0x1B, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xC7, 0x08, 0x3C, 0x43, 0x50,
+0x0C, 0xC0, 0x33, 0x00, 0xCF, 0x20, 0x1C, 0x03, 0xF0, 0x40, 0xC0, 0x73, 0x81,
+0xC7, 0x00, 0x3C, 0x32, 0xF0, 0x40, 0xC0, 0x33, 0x00, 0x4F, 0x22, 0x1C, 0x12,
+0x30, 0x84, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xB8, 0x3D, 0x00, 0xFF, 0x40, 0xBC, 0x2B, 0xB1, 0x0F, 0xC0, 0x3F, 0x00,
+0xFF, 0x90, 0xE4, 0x03, 0xF0, 0x0B, 0xC0, 0x3D, 0x00, 0xB7, 0x00, 0xFC, 0x63,
+0xF0, 0x07, 0xC0, 0x2F, 0x02, 0x6F, 0x00, 0x1C, 0x03, 0xF0, 0x8D, 0xC2, 0x0B,
+0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x73, 0x01,
+0xDB, 0x0A, 0x7C, 0x97, 0x39, 0x6D, 0xC1, 0xB7, 0x01, 0xDF, 0x00, 0x5C, 0x4B,
+0x71, 0x18, 0xC0, 0x36, 0x20, 0x9F, 0x20, 0x7C, 0x02, 0xF0, 0x05, 0xC0, 0x32,
+0x00, 0x5B, 0x00, 0x7C, 0x03, 0x36, 0x05, 0xC0, 0x57, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0xB9, 0x05, 0xE1, 0x54, 0xB4, 0x13,
+0x18, 0x2E, 0x60, 0xBB, 0x03, 0xED, 0x04, 0x04, 0x03, 0x10, 0x0E, 0x60, 0x38,
+0x01, 0xA7, 0x00, 0xB4, 0x13, 0xD0, 0x07, 0x42, 0x28, 0x10, 0x61, 0x20, 0xB4,
+0x01, 0x10, 0x0E, 0x40, 0x4B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x00, 0x79, 0x00, 0xE9, 0x05, 0x34, 0x27, 0x12, 0x5E, 0x40, 0x7B,
+0x00, 0xCD, 0x05, 0x94, 0x27, 0x52, 0x1A, 0x64, 0x7A, 0x02, 0xED, 0x01, 0xB4,
+0x0E, 0xD0, 0x1E, 0x40, 0x7A, 0x20, 0x6D, 0x21, 0xF4, 0x07, 0x10, 0x16, 0x40,
+0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x33,
+0x08, 0xC1, 0x00, 0x34, 0x83, 0x10, 0x0C, 0x40, 0x33, 0x10, 0xCD, 0x20, 0x04,
+0x03, 0x10, 0x0C, 0x40, 0x32, 0x00, 0x85, 0x00, 0x34, 0x03, 0xD0, 0x25, 0x41,
+0x20, 0x00, 0x45, 0x08, 0x34, 0x8F, 0x10, 0xEC, 0x40, 0x4B, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA0, 0x15, 0x00, 0x5B, 0x20, 0x7C,
+0x01, 0x35, 0x05, 0xC0, 0x17, 0x00, 0x5F, 0x00, 0x5C, 0x01, 0x70, 0x27, 0xC2,
+0x16, 0x00, 0x7F, 0x22, 0x7C, 0x01, 0xF8, 0x27, 0xD3, 0x16, 0x20, 0x6F, 0x20,
+0xF4, 0x0D, 0x30, 0x17, 0xC2, 0x5F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x02, 0x7C, 0x08, 0xF0, 0x21, 0xC4,
+0x87, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x21, 0xC0, 0x05, 0x00, 0x17, 0x04,
+0x7C, 0x08, 0xF2, 0x01, 0xC0, 0x87, 0x00, 0x1A, 0x02, 0x74, 0x60, 0xF0, 0x01,
+0xC0, 0x4B, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x27, 0x02, 0x9F, 0x09, 0x7C, 0x06, 0xF0, 0x19, 0xC0, 0x67, 0x80, 0x83, 0x08,
+0x5C, 0x02, 0x30, 0x99, 0xC3, 0x23, 0x00, 0x92, 0x00, 0x0C, 0x86, 0x70, 0x09,
+0xC0, 0x21, 0x01, 0x93, 0x04, 0x5C, 0x06, 0x32, 0x08, 0xC2, 0x40, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xE6, 0x00, 0x9D, 0x03,
+0x74, 0x02, 0xD0, 0xA9, 0x41, 0xE3, 0x04, 0x9B, 0x01, 0x44, 0x02, 0x10, 0x09,
+0x40, 0x27, 0x00, 0x81, 0x00, 0xC4, 0x0A, 0xB0, 0x09, 0x40, 0xA4, 0x00, 0x95,
+0x00, 0x04, 0x0E, 0x10, 0x09, 0x40, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x88, 0x24, 0x04, 0x9D, 0x10, 0x74, 0x22, 0xD0, 0x09,
+0x40, 0x27, 0x01, 0x91, 0x00, 0x14, 0x02, 0x14, 0x0D, 0x41, 0x27, 0x41, 0x95,
+0x00, 0x54, 0x12, 0x50, 0x09, 0x40, 0xA5, 0x00, 0x91, 0x00, 0x54, 0x12, 0x14,
+0x89, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x20, 0x20, 0x05, 0x8D, 0x34, 0x36, 0x52, 0xD2, 0x08, 0x40, 0x23, 0x40, 0x89,
+0xC0, 0x04, 0x22, 0x10, 0x08, 0x40, 0xA3, 0x00, 0x95, 0x02, 0x14, 0x03, 0x90,
+0x88, 0x40, 0x20, 0x05, 0x94, 0x00, 0x44, 0x06, 0x10, 0x48, 0x41, 0x41, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x01, 0x1F,
+0x24, 0x7C, 0x91, 0xF0, 0x41, 0xC1, 0x07, 0x05, 0x11, 0x54, 0x5C, 0x58, 0x30,
+0x01, 0xCA, 0x07, 0x05, 0x17, 0x00, 0x5D, 0x04, 0x70, 0x21, 0xC0, 0x05, 0x01,
+0x53, 0x00, 0x5C, 0x00, 0x30, 0x45, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x27, 0x00, 0x9F, 0x54, 0x7C, 0x02, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x7C, 0x12, 0xF2, 0x0B, 0xC0, 0x67, 0x00,
+0xBB, 0x01, 0xEC, 0x0A, 0x70, 0x4B, 0xC8, 0x2F, 0x00, 0xFF, 0x00, 0xAE, 0x52,
+0xF4, 0x0B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x19, 0xA8, 0x6F, 0x04, 0xBF, 0x36, 0xFC, 0x42, 0xF0, 0x0A, 0xC0, 0x2C, 0x00,
+0xBF, 0x90, 0x7F, 0x32, 0xF0, 0x0F, 0xC0, 0xAF, 0x04, 0x9F, 0x02, 0xCD, 0x86,
+0x34, 0x89, 0xC0, 0x2F, 0x00, 0xAF, 0x00, 0xFC, 0x02, 0x30, 0x0B, 0xC0, 0x64,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18, 0x07, 0x00,
+0x1D, 0x02, 0x74, 0x08, 0xD0, 0xA1, 0x52, 0x84, 0x02, 0x1D, 0x02, 0x44, 0x00,
+0x70, 0x05, 0x40, 0xC7, 0x00, 0x1D, 0x01, 0x44, 0x88, 0x10, 0x05, 0x48, 0x04,
+0x00, 0x1D, 0x00, 0x74, 0x00, 0x10, 0x01, 0x40, 0x70, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x04, 0x34, 0x02,
+0xD0, 0x08, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x14, 0x1A, 0xD0, 0x08, 0x62, 0x23,
+0x00, 0x8D, 0x00, 0x04, 0x0A, 0x10, 0x48, 0x40, 0x22, 0x00, 0x8D, 0x00, 0x74,
+0x03, 0x10, 0x08, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x25, 0x00, 0x9D, 0xA0, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x24,
+0x20, 0x9D, 0x00, 0x44, 0x02, 0x50, 0x09, 0x48, 0x27, 0x00, 0x8D, 0x00, 0x44,
+0x02, 0x11, 0x89, 0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x29, 0x40,
+0x60, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27,
+0x10, 0x9F, 0x00, 0x78, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x08, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0x40, 0x2F, 0x00, 0xBE, 0x07, 0x4C, 0x02, 0x31, 0x39, 0xC2,
+0x27, 0x00, 0x9F, 0x00, 0x3C, 0x16, 0x20, 0x09, 0xD0, 0x14, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x24, 0x00, 0x9F, 0x80, 0x7C,
+0x42, 0xF0, 0x08, 0xE0, 0x27, 0x0C, 0x8F, 0x10, 0x7D, 0x02, 0xF0, 0x39, 0xC0,
+0x27, 0x00, 0x9F, 0x02, 0x7C, 0x4A, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x23,
+0x7C, 0x16, 0xF4, 0x59, 0xC0, 0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x08, 0x05, 0x01, 0x1F, 0x00, 0x4C, 0x20, 0x30, 0x41, 0xC0,
+0x04, 0x00, 0x12, 0x00, 0x5C, 0x80, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x13, 0x02,
+0x7C, 0x00, 0xF0, 0x21, 0xC0, 0x07, 0x24, 0x1F, 0x22, 0x5C, 0x00, 0x30, 0x41,
+0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00,
+0xDC, 0x04, 0x7D, 0x00, 0xC4, 0x09, 0xF0, 0x17, 0x44, 0xDD, 0x4C, 0x71, 0x03,
+0x44, 0x01, 0x10, 0x77, 0xC0, 0x55, 0x00, 0x5B, 0x00, 0xB4, 0x11, 0xD0, 0x05,
+0x40, 0x5F, 0x00, 0x7D, 0x03, 0xC4, 0x01, 0x50, 0x36, 0x40, 0x50, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xE2, 0x00, 0xCD, 0x45,
+0x14, 0x0A, 0x10, 0x24, 0x40, 0x70, 0x80, 0x81, 0x00, 0x14, 0x03, 0x10, 0x48,
+0x40, 0x33, 0x00, 0xC5, 0x00, 0x34, 0x02, 0xD0, 0x0D, 0x42, 0xA3, 0x00, 0x8D,
+0x12, 0x14, 0x03, 0x10, 0x8C, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0xED, 0x03, 0x94, 0x05, 0x51, 0x22,
+0x40, 0x61, 0x00, 0x81, 0x10, 0x84, 0x17, 0x14, 0x0A, 0x40, 0xFD, 0x01, 0xED,
+0x04, 0xB4, 0x02, 0xD0, 0x4E, 0x00, 0x2B, 0x04, 0xBD, 0x11, 0x84, 0x03, 0x52,
+0x00, 0x40, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x10, 0x68, 0x00, 0xCF, 0x01, 0x15, 0x04, 0x10, 0x16, 0xE0, 0x78, 0x88, 0xA3,
+0x01, 0xDC, 0x47, 0x30, 0x1E, 0xE8, 0x7F, 0x01, 0xE7, 0x03, 0xBC, 0x06, 0xF0,
+0x1E, 0xC0, 0x6B, 0x00, 0xAF, 0x41, 0xDC, 0x07, 0x32, 0x1E, 0xC0, 0x50, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0x5F,
+0x00, 0x6C, 0x01, 0xF0, 0x01, 0xC2, 0x27, 0x00, 0x9F, 0x20, 0x7E, 0x23, 0xF0,
+0x09, 0xC0, 0x37, 0x12, 0xDB, 0x00, 0x7C, 0x02, 0xF0, 0x8D, 0xC0, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xD0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x6F, 0x40, 0x73, 0x81, 0xE4, 0x04, 0xF1,
+0x17, 0xC0, 0x78, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0xF0, 0x1B, 0xC0, 0x6F, 0x80,
+0xE7, 0x09, 0xCC, 0x07, 0xF0, 0x1F, 0xC2, 0x7C, 0x00, 0xFF, 0x01, 0xFC, 0x07,
+0x30, 0x17, 0xC0, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x88, 0x29, 0x00, 0x61, 0x00, 0x84, 0x10, 0x70, 0x02, 0x40, 0x98, 0x02,
+0xE1, 0x80, 0xB4, 0x03, 0xD0, 0x0A, 0x40, 0x2B, 0x81, 0xE1, 0x00, 0x84, 0x02,
+0xD0, 0x8E, 0xC0, 0x3A, 0x00, 0xED, 0x00, 0xF4, 0x23, 0x18, 0x26, 0x40, 0x54,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x21, 0x00,
+0xE1, 0x00, 0x84, 0x00, 0xD1, 0x08, 0x40, 0x38, 0x00, 0xE1, 0x08, 0xB4, 0x03,
+0xD0, 0x0E, 0x41, 0x2B, 0x30, 0xF5, 0x01, 0x84, 0x03, 0xD0, 0x0F, 0x40, 0x28,
+0x04, 0xAD, 0x00, 0xB4, 0x02, 0x50, 0x26, 0x40, 0x20, 0x01, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x13, 0x00, 0x11, 0x40, 0x04, 0x01,
+0x50, 0x08, 0x4C, 0x10, 0x00, 0xC9, 0x00, 0x34, 0x03, 0xD0, 0x24, 0x40, 0x23,
+0x00, 0xC1, 0x04, 0x04, 0x05, 0xD0, 0x2C, 0x40, 0x22, 0x80, 0x4D, 0x00, 0x36,
+0x0C, 0x50, 0x0C, 0x52, 0x18, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0xA8, 0x25, 0x00, 0x93, 0x00, 0x4C, 0x00, 0xF0, 0x05, 0xC4, 0x14,
+0x00, 0x93, 0x00, 0xFC, 0x03, 0xD0, 0x09, 0xC4, 0x37, 0x00, 0xD7, 0x04, 0x4D,
+0x12, 0xF0, 0x3F, 0xC1, 0x24, 0x00, 0x9F, 0x0A, 0x7C, 0x0C, 0x70, 0x29, 0xC0,
+0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37,
+0x10, 0x9F, 0x82, 0x5C, 0x01, 0xF0, 0x05, 0xC0, 0x03, 0x00, 0x97, 0x80, 0x7E,
+0x03, 0xF0, 0x09, 0xC0, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC1,
+0xA7, 0x00, 0x9F, 0x00, 0x7C, 0x60, 0xB4, 0x29, 0xC0, 0x27, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0A, 0x2B, 0x20, 0x93, 0x80, 0xCC,
+0x00, 0x30, 0x07, 0xC0, 0xAF, 0x00, 0xA3, 0x09, 0x8D, 0x03, 0x32, 0x0F, 0xC1,
+0x77, 0x00, 0xFB, 0x00, 0xCC, 0x02, 0x34, 0x0F, 0x00, 0x2E, 0x00, 0xBF, 0x00,
+0xFC, 0x00, 0x30, 0x09, 0xC0, 0x07, 0x2A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x21, 0x36, 0x00, 0x91, 0x11, 0x14, 0x41, 0x51, 0x95, 0x40,
+0xA7, 0x00, 0x91, 0x02, 0x44, 0x03, 0x10, 0x09, 0x44, 0x67, 0x02, 0xDD, 0x00,
+0x04, 0x02, 0x30, 0x0D, 0x40, 0x27, 0x04, 0x9D, 0x00, 0x34, 0x1C, 0x10, 0xBD,
+0x44, 0x87, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0,
+0x24, 0x10, 0x11, 0x81, 0x64, 0x80, 0x18, 0x05, 0x40, 0x17, 0x00, 0x91, 0x02,
+0x44, 0x03, 0x14, 0x09, 0x40, 0x27, 0x00, 0xCD, 0x00, 0x44, 0x03, 0x10, 0x0D,
+0x40, 0x36, 0x02, 0xDD, 0x00, 0x74, 0x04, 0x10, 0x01, 0x40, 0x07, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x20, 0x00, 0x01, 0x00,
+0x16, 0x80, 0x50, 0x04, 0x40, 0x13, 0x00, 0x01, 0x00, 0x04, 0x03, 0x10, 0x08,
+0x48, 0xB3, 0x20, 0xCD, 0x00, 0x05, 0x02, 0x10, 0x0C, 0x40, 0x33, 0x00, 0xCD,
+0x00, 0x74, 0x00, 0x10, 0x0C, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xB0, 0x26, 0x00, 0x93, 0x00, 0x4C, 0x00, 0x30, 0x09,
+0xC0, 0x27, 0x00, 0xD1, 0x00, 0xCC, 0x03, 0x30, 0x0D, 0xC0, 0x27, 0x08, 0xFB,
+0x00, 0x4C, 0x03, 0x30, 0x0D, 0xC0, 0x16, 0x00, 0x9F, 0x00, 0x7C, 0x00, 0x30,
+0x01, 0xC4, 0x07, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xA8, 0x1F, 0x00, 0xBF, 0x00, 0xFC, 0x01, 0xF0, 0x0B, 0xC0, 0x0F, 0x00, 0x7F,
+0x40, 0xFC, 0x03, 0xF1, 0x07, 0xC0, 0x2F, 0x01, 0xFF, 0x00, 0xFC, 0x01, 0x70,
+0x0E, 0xC0, 0x1F, 0x00, 0x7F, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x17, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x88, 0x7B, 0x22, 0xFB,
+0x29, 0xEC, 0x27, 0xF0, 0x9F, 0xC4, 0x7C, 0x02, 0xEF, 0x09, 0xCC, 0x07, 0x30,
+0x9F, 0xC0, 0x7C, 0x00, 0xE3, 0x01, 0xCC, 0x07, 0xF0, 0x9F, 0xC0, 0x7C, 0x00,
+0xEF, 0x09, 0xCC, 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x07, 0x00, 0x11, 0x04, 0x4C, 0x00, 0xD1,
+0x01, 0x00, 0x04, 0x31, 0x1D, 0x04, 0x44, 0x04, 0x50, 0x41, 0x00, 0x05, 0x05,
+0x11, 0x00, 0x5C, 0x10, 0xD0, 0x41, 0x40, 0x00, 0x25, 0x1D, 0x04, 0x44, 0x00,
+0xD0, 0x01, 0x40, 0x0F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0xA0, 0x35, 0x00, 0xD9, 0x00, 0x24, 0x13, 0x52, 0x4C, 0x42, 0x31, 0x01,
+0xCD, 0x04, 0x44, 0x83, 0x50, 0x0D, 0x0A, 0x30, 0x00, 0xD5, 0x00, 0x04, 0x43,
+0xD0, 0x4C, 0x60, 0x30, 0x00, 0xCD, 0x00, 0x05, 0x03, 0xD0, 0x0C, 0x40, 0x4D,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x07, 0x00,
+0x11, 0x00, 0x40, 0x80, 0xD0, 0x01, 0x40, 0x05, 0x00, 0x1D, 0x00, 0x47, 0x00,
+0x50, 0x01, 0x48, 0x01, 0x40, 0x15, 0x20, 0x74, 0x00, 0xD0, 0x00, 0x48, 0x05,
+0x00, 0x0D, 0x00, 0x54, 0x00, 0xC0, 0x01, 0x40, 0x0F, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x36, 0x00, 0xDB, 0x00, 0x6C, 0x03,
+0xF0, 0x0D, 0xC0, 0x35, 0x00, 0xDF, 0x40, 0x0C, 0x03, 0x70, 0x0D, 0x40, 0x34,
+0x00, 0xD7, 0x00, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0xDF, 0x00, 0x4C,
+0x03, 0xE0, 0x0D, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x80, 0x0D, 0x00, 0x3F, 0x00, 0xDC, 0x40, 0xF3, 0x03, 0xD4, 0x0E,
+0x10, 0x3F, 0x00, 0xF8, 0x40, 0xF0, 0x03, 0xC0, 0x0F, 0x20, 0x3B, 0x00, 0xDC,
+0x00, 0xF1, 0x03, 0xC0, 0x0E, 0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x03, 0xC0,
+0x1F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35,
+0x00, 0xD7, 0x04, 0x7C, 0x03, 0xF0, 0x4D, 0xC0, 0x37, 0x00, 0xD7, 0x60, 0x5C,
+0x07, 0xB0, 0x0D, 0xC0, 0x37, 0x00, 0xD7, 0x00, 0x4C, 0x13, 0xF0, 0x0D, 0xC0,
+0x34, 0x40, 0xD3, 0x04, 0x4C, 0x43, 0xF0, 0x0D, 0xC0, 0xAB, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0, 0x00, 0x06, 0x01, 0x12, 0x74,
+0x14, 0xD0, 0x71, 0x60, 0x07, 0x00, 0x11, 0x00, 0x6C, 0x00, 0x10, 0x00, 0x40,
+0xC7, 0x02, 0x0D, 0x11, 0x6C, 0x18, 0xD2, 0x01, 0x40, 0x04, 0x00, 0x11, 0x12,
+0x6C, 0x00, 0xD0, 0xB1, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x20, 0xF0, 0x10, 0xC5, 0x80, 0x34, 0x03, 0xD1, 0x0D, 0x42,
+0x33, 0x00, 0xDD, 0x00, 0x24, 0x0B, 0x90, 0x0C, 0x40, 0xB3, 0x00, 0xC5, 0x01,
+0x04, 0x0F, 0xD8, 0x0C, 0x40, 0x32, 0x00, 0xC1, 0x01, 0x04, 0x0B, 0xD2, 0x1C,
+0x40, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x02,
+0x4C, 0x00, 0x21, 0x01, 0xB4, 0x04, 0xD9, 0x12, 0x40, 0x4F, 0x02, 0x39, 0x01,
+0xA4, 0x04, 0x10, 0x12, 0x40, 0x4B, 0x04, 0x3D, 0x01, 0xA6, 0x24, 0xD0, 0x12,
+0x68, 0x4A, 0x00, 0x31, 0x01, 0xA4, 0x04, 0xD0, 0x12, 0x53, 0x3C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xC7, 0x00,
+0x3C, 0x03, 0xF0, 0x0C, 0x48, 0x33, 0x10, 0xCF, 0x00, 0x3C, 0x03, 0xB0, 0x0C,
+0x40, 0x33, 0x00, 0xC7, 0x00, 0x0C, 0xA3, 0xF1, 0x0D, 0xCC, 0x32, 0x80, 0xC3,
+0x00, 0x0C, 0x03, 0xF0, 0x0D, 0xC0, 0x49, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x38, 0x0D, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF8, 0x03,
+0x80, 0x0B, 0x08, 0x36, 0x00, 0xBC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F,
+0x00, 0xFC, 0x20, 0xD2, 0x03, 0xC0, 0x0D, 0x10, 0x3F, 0x00, 0xFC, 0x00, 0xFA,
+0x11, 0xC0, 0x09, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xA8, 0x77, 0x20, 0xD7, 0x41, 0x6C, 0x03, 0xF0, 0x0D, 0xC0, 0x74, 0x00, 0xC3,
+0x01, 0x4C, 0x03, 0xF0, 0x0D, 0xC0, 0x33, 0x00, 0xD3, 0x01, 0x4D, 0x03, 0x70,
+0x1D, 0xC0, 0x30, 0x00, 0xD3, 0x01, 0x4C, 0x07, 0x30, 0x1D, 0xD0, 0x40, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x80, 0x0D, 0x48, 0x21,
+0x40, 0x84, 0x00, 0xD0, 0x02, 0x40, 0x09, 0x00, 0x25, 0x00, 0x90, 0x00, 0xD0,
+0x02, 0x40, 0x0B, 0x00, 0x35, 0x00, 0xC4, 0x00, 0x10, 0x02, 0x40, 0x09, 0x00,
+0x2B, 0x40, 0x84, 0x00, 0xB0, 0x03, 0xC0, 0x4E, 0x08, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xF9, 0x01, 0xA4, 0x07, 0xC2,
+0x1F, 0x40, 0x7C, 0x00, 0xF5, 0x01, 0x84, 0x07, 0xD0, 0x1E, 0x40, 0x7F, 0x00,
+0xE1, 0x01, 0x94, 0x07, 0x50, 0x1F, 0x48, 0x7C, 0x80, 0xE1, 0x01, 0xC4, 0x07,
+0x18, 0x1E, 0x48, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x16, 0x28, 0x03, 0x00, 0x09, 0x00, 0x40, 0x00, 0xD8, 0x00, 0x42, 0x01, 0x00,
+0x05, 0x20, 0x14, 0x00, 0xD0, 0x00, 0x40, 0x07, 0x00, 0x05, 0x00, 0x14, 0x00,
+0x50, 0x00, 0x40, 0x05, 0x08, 0x09, 0x00, 0x04, 0x00, 0x98, 0x00, 0x40, 0x5A,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x28, 0x15, 0x00,
+0x5B, 0x00, 0x6C, 0x01, 0xD0, 0x04, 0xC0, 0x14, 0x00, 0x57, 0x00, 0x4C, 0x01,
+0xF0, 0x05, 0xC4, 0x17, 0x00, 0x53, 0x00, 0x1C, 0x01, 0x70, 0x05, 0xC0, 0x14,
+0x08, 0x53, 0x60, 0x4C, 0x01, 0x30, 0x05, 0x40, 0x5C, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x8D, 0x00, 0x37, 0x02, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x08, 0xF0, 0x03, 0xC8, 0x0F,
+0x00, 0x3F, 0x02, 0xE4, 0x08, 0xB0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x80, 0xFD,
+0x00, 0xF0, 0x03, 0xC0, 0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x19, 0x40, 0x24,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x24, 0x00, 0x93, 0x00, 0x7C,
+0x16, 0x30, 0x09, 0xC0, 0x27, 0x40, 0x93, 0x04, 0x78, 0x16, 0xF0, 0x09, 0xC0,
+0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24,
+0x01, 0x9D, 0x00, 0x74, 0x42, 0x14, 0x59, 0xC0, 0x26, 0x00, 0x9D, 0x00, 0x74,
+0x0A, 0xD0, 0x09, 0x40, 0xA4, 0x00, 0x91, 0x9A, 0x74, 0x8E, 0xB2, 0x09, 0x40,
+0x27, 0x10, 0x91, 0x02, 0x64, 0x16, 0xD1, 0x09, 0x40, 0x07, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x6C, 0x80, 0xBD, 0x01, 0xE4,
+0x06, 0x10, 0x4B, 0x40, 0x2D, 0x00, 0xBD, 0x00, 0xF4, 0x0E, 0xD0, 0x0A, 0x40,
+0x2C, 0x04, 0xB1, 0x00, 0xF4, 0x02, 0x10, 0x0B, 0x00, 0x2F, 0x00, 0xB1, 0x10,
+0xF4, 0x02, 0xD0, 0x0B, 0x41, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x28, 0x00, 0xEC, 0x00, 0xB4, 0x02, 0x10, 0x0B, 0x40,
+0x2B, 0x22, 0xAD, 0x08, 0xB4, 0x82, 0xD0, 0x8A, 0x60, 0x28, 0x42, 0xA1, 0x40,
+0xF4, 0x02, 0x90, 0x8A, 0x40, 0x2B, 0x0A, 0xA1, 0x08, 0xA4, 0x02, 0xD0, 0x0A,
+0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8,
+0x06, 0x00, 0x1F, 0x40, 0x6C, 0x00, 0x30, 0x01, 0xC0, 0x85, 0x00, 0x1D, 0x02,
+0x7C, 0x00, 0xF0, 0x21, 0xD0, 0x84, 0x00, 0x13, 0x0A, 0x7C, 0x01, 0x30, 0x21,
+0xC0, 0x87, 0x08, 0x03, 0x22, 0x7C, 0x00, 0xF0, 0x03, 0xE0, 0x77, 0xE0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x27, 0x05, 0x8D, 0x14,
+0x7C, 0x52, 0xF0, 0x48, 0xC1, 0x22, 0x01, 0x9F, 0x04, 0x7C, 0x02, 0xF0, 0x49,
+0xC0, 0x27, 0x01, 0x9F, 0x81, 0x7C, 0x52, 0xF0, 0x48, 0xC0, 0x27, 0x01, 0x9F,
+0x24, 0x3C, 0x52, 0xF0, 0x49, 0xC1, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xA0, 0xAF, 0x00, 0xB7, 0x02, 0xDC, 0x0A, 0xB0, 0x2B,
+0xC0, 0x27, 0x00, 0x9F, 0x02, 0xDC, 0x02, 0x30, 0x89, 0xC0, 0x2F, 0x10, 0xB3,
+0x00, 0xFC, 0x02, 0xF0, 0x29, 0xC0, 0xA7, 0x10, 0xBF, 0x00, 0xCC, 0x02, 0xB0,
+0x0B, 0xC0, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x00, 0x05, 0x01, 0x11, 0x81, 0x44, 0x00, 0x10, 0x41, 0x40, 0x07, 0x05, 0x1D,
+0x00, 0x44, 0x00, 0x50, 0x01, 0x40, 0x07, 0x01, 0x11, 0x00, 0x74, 0x50, 0xD0,
+0x01, 0x40, 0x07, 0x00, 0x1D, 0x00, 0x44, 0x00, 0x50, 0x01, 0x40, 0x63, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x21, 0x01, 0x85,
+0x00, 0x54, 0x12, 0x90, 0x48, 0x40, 0x23, 0x80, 0x8D, 0x04, 0x44, 0x02, 0x10,
+0x48, 0x40, 0x23, 0x44, 0x81, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x23, 0x80,
+0x8D, 0x00, 0x06, 0x02, 0x90, 0x08, 0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x91, 0x00, 0x44, 0x03, 0x08,
+0x09, 0x40, 0x27, 0x00, 0x8C, 0x00, 0x45, 0x82, 0x50, 0x09, 0x42, 0x23, 0x08,
+0x91, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x44, 0x02,
+0xD8, 0x09, 0x40, 0x63, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x20, 0x25, 0x00, 0x97, 0x00, 0x1C, 0x02, 0xB0, 0x09, 0xC4, 0x27, 0x00,
+0x9F, 0x00, 0x5C, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x92, 0x00, 0x7C, 0x02,
+0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x4C, 0x02, 0xB0, 0x09, 0xC8, 0x17,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x88, 0x25, 0x00,
+0x9F, 0x00, 0x7C, 0x02, 0xF8, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x80, 0x7C, 0x02,
+0xF0, 0x09, 0xC2, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x80, 0x7D, 0x42, 0x70, 0x09, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1D, 0x10, 0x7C, 0x10,
+0xD0, 0x01, 0xC0, 0x07, 0x00, 0x1B, 0x00, 0x5C, 0x00, 0x70, 0x01, 0xC0, 0x04,
+0x00, 0x1B, 0x49, 0x7C, 0x40, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x1F, 0x00, 0x7C,
+0x00, 0xB4, 0x41, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xA0, 0xDC, 0x00, 0x7D, 0x23, 0xF4, 0x9D, 0x10, 0x97, 0x40, 0x17,
+0x00, 0x5D, 0x00, 0xB4, 0x21, 0xD0, 0x05, 0x40, 0x1C, 0x00, 0x7D, 0x01, 0xF4,
+0x01, 0xD0, 0x05, 0x40, 0x15, 0x20, 0x7D, 0x02, 0xF4, 0x09, 0x10, 0x07, 0x40,
+0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xB6,
+0x06, 0xDD, 0x0B, 0x34, 0x03, 0x50, 0xAC, 0x40, 0x33, 0x00, 0xCD, 0x80, 0x14,
+0x8F, 0xD0, 0x0C, 0x50, 0x70, 0x80, 0xC9, 0x21, 0x32, 0x27, 0xD0, 0x0C, 0x40,
+0x32, 0x00, 0xDD, 0x12, 0x74, 0x23, 0x10, 0x1C, 0x40, 0x43, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x39, 0x00, 0xED, 0x00, 0xF4,
+0x03, 0x10, 0x0E, 0x40, 0x3B, 0x03, 0xEC, 0x04, 0xB4, 0x0A, 0xC0, 0x5E, 0x40,
+0x38, 0x04, 0xE9, 0x00, 0xB4, 0x03, 0xD0, 0x5F, 0x40, 0x3B, 0x00, 0x2D, 0x10,
+0xB4, 0x03, 0x10, 0x2E, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x18, 0x79, 0x00, 0xEF, 0x01, 0xBC, 0x07, 0x70, 0x1E, 0xC0,
+0x7B, 0x05, 0xEB, 0x89, 0x9C, 0x07, 0x70, 0xBF, 0xC0, 0x78, 0x20, 0x2B, 0x21,
+0xBC, 0x07, 0xF0, 0x3E, 0xC0, 0x7A, 0x05, 0xEF, 0x01, 0xFC, 0x07, 0x31, 0x1E,
+0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8,
+0x15, 0x10, 0x5F, 0x00, 0x3C, 0x03, 0x70, 0x0D, 0x80, 0xB7, 0x01, 0xDF, 0x0C,
+0x7C, 0x00, 0xF0, 0x4D, 0xC0, 0x17, 0x00, 0x1F, 0x20, 0x7C, 0x03, 0xF0, 0x0C,
+0x41, 0x35, 0x08, 0x1F, 0x00, 0x7C, 0x01, 0x70, 0x0D, 0xC0, 0x43, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x7D, 0x00, 0xFF, 0x89,
+0xF8, 0x05, 0x70, 0x1F, 0xC2, 0x7D, 0x00, 0xFB, 0x01, 0xFC, 0x07, 0xF0, 0x1F,
+0xC0, 0x6F, 0x00, 0xF7, 0x01, 0xCE, 0x25, 0x30, 0x1F, 0xC0, 0x7F, 0x04, 0xF3,
+0x01, 0x8C, 0x25, 0x30, 0x1E, 0xC0, 0x18, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x08, 0x39, 0x04, 0xED, 0x08, 0xF4, 0x11, 0x00, 0x0E,
+0x40, 0x3F, 0x00, 0xE0, 0x10, 0xB4, 0x42, 0xD0, 0x8E, 0x41, 0x3B, 0x00, 0xF5,
+0x02, 0x94, 0x0B, 0x50, 0x0E, 0xC0, 0x3B, 0x00, 0x3B, 0x08, 0x85, 0x39, 0xB0,
+0x0A, 0x40, 0x55, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+0x00, 0x39, 0x02, 0xED, 0x08, 0xB0, 0x01, 0xD1, 0x06, 0x40, 0x39, 0x04, 0xE9,
+0x08, 0xB4, 0x02, 0xD0, 0x0E, 0x40, 0x2F, 0x00, 0x71, 0x08, 0xC4, 0x01, 0x90,
+0x0E, 0x40, 0x3F, 0x00, 0xE9, 0x00, 0xC4, 0x00, 0x18, 0x07, 0x40, 0x20, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x21, 0x10, 0x9D,
+0x03, 0x34, 0x00, 0x90, 0x89, 0x40, 0xF2, 0x80, 0xC1, 0x02, 0x34, 0x0C, 0xD0,
+0x1C, 0x60, 0x57, 0x00, 0x05, 0x06, 0x14, 0x0E, 0xD8, 0x2C, 0x40, 0xB1, 0x00,
+0xCD, 0x0A, 0x00, 0xAC, 0x98, 0x00, 0x42, 0x09, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x55, 0xA0, 0xC4, 0x20, 0x1F, 0x52, 0x7C, 0x0A, 0xD0,
+0xA1, 0xC0, 0xFD, 0x80, 0xFB, 0x01, 0x7C, 0x2C, 0xF0, 0x0F, 0xC8, 0xD7, 0x01,
+0x93, 0x11, 0x4C, 0x12, 0xB0, 0x3F, 0x41, 0xBF, 0x00, 0xC9, 0x08, 0x48, 0x0E,
+0x10, 0x91, 0xC0, 0x74, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0D, 0x08, 0x27, 0x20, 0x9F, 0x84, 0x7E, 0x60, 0x70, 0x21, 0xC8, 0x37, 0x09,
+0xDF, 0x00, 0x7C, 0x08, 0xF0, 0x0D, 0xC1, 0xA6, 0x00, 0x9E, 0x40, 0x7E, 0x40,
+0x70, 0x0D, 0xC1, 0x37, 0x22, 0x1B, 0x00, 0x7C, 0x1A, 0xF0, 0x89, 0xC4, 0x97,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x08, 0x0B, 0x84,
+0x33, 0x80, 0xCC, 0x02, 0xF0, 0x03, 0xC0, 0x3E, 0x00, 0xF7, 0x10, 0xF8, 0x00,
+0xF2, 0x0F, 0xC0, 0x1C, 0x04, 0x33, 0x80, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F,
+0x04, 0xFF, 0x00, 0xCC, 0x02, 0xF0, 0x03, 0xC0, 0x04, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x46, 0x08, 0x17, 0x11, 0x4C, 0x06,
+0xD0, 0x11, 0x40, 0x34, 0x00, 0xD1, 0x80, 0x74, 0x04, 0xF0, 0x0C, 0x40, 0x85,
+0x02, 0x11, 0x03, 0x64, 0x06, 0xD0, 0x0D, 0x40, 0x37, 0x08, 0x1D, 0x11, 0x6C,
+0x04, 0xD0, 0x38, 0xC8, 0x06, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0xA0, 0x44, 0x04, 0x11, 0x21, 0x54, 0x06, 0xD8, 0x39, 0x66, 0x32,
+0x00, 0xD5, 0x00, 0x74, 0x0E, 0xD0, 0x0D, 0x40, 0x04, 0x04, 0x31, 0x21, 0x74,
+0x04, 0xD8, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x08, 0x44, 0x06, 0xD0, 0x31, 0x40,
+0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0A, 0x24,
+0x00, 0x85, 0x00, 0x05, 0x00, 0xD2, 0x08, 0x60, 0x30, 0x00, 0xC1, 0x00, 0x34,
+0x02, 0xD0, 0x0D, 0x40, 0x21, 0x20, 0x01, 0x00, 0x34, 0x00, 0xD2, 0x0C, 0x40,
+0x33, 0x00, 0x1D, 0x00, 0x24, 0x02, 0xD0, 0x09, 0x40, 0x42, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x06, 0x00, 0x11, 0x00, 0x5C,
+0x82, 0xF8, 0x01, 0xC0, 0x3E, 0x00, 0xF6, 0x00, 0x7C, 0x02, 0xF0, 0x0F, 0x40,
+0x04, 0x00, 0x13, 0x00, 0x74, 0x00, 0xF0, 0x0F, 0xC0, 0x3F, 0x90, 0x1F, 0x00,
+0x4C, 0x02, 0xF0, 0x01, 0xC0, 0x04, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x85, 0xA8, 0x2F, 0x00, 0xB6, 0x00, 0xCC, 0x02, 0xF8, 0x0B, 0xC0,
+0x3F, 0x00, 0xFE, 0x80, 0xFC, 0x00, 0x70, 0x0F, 0xC0, 0x0B, 0x40, 0x3F, 0x00,
+0xA4, 0x02, 0xF2, 0x0F, 0xC0, 0x3B, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF0, 0x03,
+0xC0, 0x17, 0x61, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8,
+0x7F, 0x40, 0xF3, 0x46, 0xFC, 0x03, 0x30, 0x4F, 0xC0, 0x4F, 0x12, 0x3B, 0x4C,
+0xCC, 0x23, 0x30, 0x4F, 0xC2, 0x0C, 0x80, 0x3F, 0x01, 0xFC, 0x07, 0x71, 0x8F,
+0xC0, 0x0F, 0x08, 0x73, 0x01, 0xFC, 0x00, 0x30, 0x03, 0xC0, 0x0C, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x7D, 0x00, 0xE1, 0x08,
+0xF4, 0xAF, 0x10, 0xBF, 0x40, 0x27, 0x01, 0x5D, 0x08, 0xC4, 0x3B, 0x50, 0x9F,
+0x40, 0x44, 0x00, 0x5D, 0x00, 0xF4, 0x07, 0x10, 0x0F, 0x40, 0x07, 0x00, 0xD5,
+0x81, 0x74, 0x00, 0xB1, 0x01, 0x80, 0x0E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0x20, 0x33, 0x00, 0xC4, 0x04, 0x34, 0x03, 0x55, 0x0C,
+0x40, 0x43, 0x01, 0x8D, 0x44, 0x14, 0x03, 0x50, 0x0C, 0x50, 0x00, 0x00, 0x0D,
+0x80, 0x34, 0x03, 0x10, 0x4C, 0x40, 0x07, 0x00, 0x41, 0x00, 0x34, 0x00, 0xD0,
+0x00, 0x40, 0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA0, 0x35, 0x00, 0xD5, 0x00, 0x70, 0x03, 0x50, 0x0D, 0x40, 0x67, 0x00, 0x5D,
+0x14, 0x54, 0x03, 0x10, 0x0D, 0x00, 0x6C, 0x00, 0x5D, 0x10, 0x74, 0x03, 0x10,
+0x0F, 0x40, 0x6F, 0x00, 0xD5, 0x04, 0x70, 0x06, 0xD0, 0x11, 0x40, 0x0F, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x36, 0x00, 0xD7,
+0x00, 0x7E, 0x03, 0x70, 0x0D, 0xC4, 0x47, 0x00, 0x1B, 0x03, 0x5D, 0x03, 0x70,
+0x0D, 0x80, 0x44, 0x20, 0xDD, 0x00, 0x3C, 0x03, 0x74, 0x0D, 0xC4, 0x47, 0x00,
+0x93, 0x06, 0x78, 0x04, 0x70, 0x51, 0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xFB, 0x00, 0xBC, 0x03, 0xB0,
+0x0F, 0xC0, 0x0F, 0x00, 0x6A, 0x20, 0xEC, 0x03, 0xF0, 0x0F, 0x84, 0x0F, 0x08,
+0xFC, 0x00, 0xFE, 0x03, 0xE0, 0x0F, 0x80, 0x0F, 0x00, 0xBF, 0x01, 0xB8, 0x02,
+0xB0, 0x09, 0xC2, 0x3E, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x08, 0x31, 0x10, 0xD3, 0x40, 0x5C, 0x03, 0xF3, 0x0D, 0xC0, 0x06, 0x00,
+0x9F, 0x02, 0x2C, 0x03, 0x70, 0x4C, 0xC0, 0x26, 0x04, 0xD7, 0x22, 0x7C, 0x13,
+0x30, 0x0D, 0xC0, 0x24, 0x00, 0x9F, 0x02, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x28,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0, 0x34, 0x00,
+0xF1, 0x20, 0xC4, 0x17, 0xD0, 0x4F, 0x40, 0x24, 0x00, 0x5D, 0x40, 0xC0, 0x17,
+0x10, 0x7F, 0x40, 0xE7, 0x00, 0xDD, 0x06, 0x70, 0x03, 0x11, 0xAF, 0x10, 0x24,
+0x00, 0x9D, 0x45, 0x44, 0x46, 0x11, 0x19, 0x11, 0x4C, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x72, 0x40, 0xC9, 0x20, 0x24, 0x03,
+0xD0, 0x6C, 0x40, 0x22, 0x00, 0x08, 0x20, 0x20, 0x03, 0xD0, 0x1C, 0x40, 0xC2,
+0x88, 0x84, 0x20, 0x30, 0x0B, 0x10, 0x0C, 0x40, 0x04, 0x00, 0x8D, 0x21, 0x25,
+0x04, 0x14, 0x11, 0x02, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0F, 0x00, 0x70, 0x04, 0xE9, 0x01, 0xB4, 0x17, 0xD8, 0x1E, 0x40, 0x6A,
+0x08, 0xAD, 0x05, 0xA4, 0x07, 0x90, 0x1E, 0x4A, 0x5B, 0x0A, 0xED, 0x6B, 0x34,
+0x07, 0x81, 0x9E, 0x42, 0x58, 0x00, 0xAD, 0x01, 0xB6, 0x05, 0x10, 0xB6, 0x40,
+0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x18, 0x30,
+0x00, 0xCB, 0x00, 0x2C, 0x03, 0xF0, 0x0C, 0xC0, 0x22, 0x01, 0x9F, 0x00, 0x6C,
+0x03, 0xF0, 0x0C, 0xC0, 0x02, 0x04, 0x87, 0x05, 0x3C, 0x43, 0x20, 0x0D, 0xC0,
+0x10, 0x00, 0xCF, 0x00, 0x6C, 0x01, 0x30, 0x00, 0xC0, 0x48, 0x68, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x7D, 0x00, 0xF7, 0x10, 0xC1,
+0x53, 0xF0, 0x0E, 0xC0, 0x3D, 0x00, 0xBB, 0x04, 0xDC, 0x0B, 0x7A, 0x8F, 0xC1,
+0x3F, 0x08, 0xFF, 0x28, 0xFC, 0x07, 0x72, 0x2F, 0xC0, 0x3F, 0x00, 0xEF, 0x00,
+0x4C, 0x03, 0xF0, 0x07, 0xC0, 0x0B, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0x37, 0x00, 0xDF, 0x03, 0x5C, 0x4F, 0x30, 0x3D, 0xC9,
+0x04, 0x10, 0x5F, 0x40, 0x4C, 0x37, 0x30, 0x2D, 0xC0, 0x56, 0x40, 0xDB, 0x01,
+0x4C, 0x03, 0xB3, 0x2D, 0xC2, 0x14, 0x00, 0x8F, 0x00, 0x4C, 0x00, 0xF0, 0x0D,
+0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x80,
+0x39, 0x01, 0xCD, 0x14, 0x02, 0x13, 0xB0, 0x4C, 0x4A, 0x08, 0x00, 0xCC, 0x00,
+0x84, 0x13, 0xB0, 0x4E, 0x41, 0x1B, 0x00, 0xE1, 0x00, 0x84, 0x0B, 0xD0, 0x0F,
+0x40, 0x18, 0x00, 0xAD, 0x00, 0x84, 0x03, 0xD0, 0x0E, 0xC0, 0x4E, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x02, 0xED, 0x01,
+0x94, 0x17, 0x10, 0x9E, 0x40, 0x79, 0x00, 0xED, 0x01, 0x04, 0x17, 0x10, 0x1E,
+0x40, 0x61, 0x88, 0xE1, 0x21, 0x96, 0x17, 0xD0, 0x9E, 0x44, 0x78, 0x00, 0xBD,
+0x01, 0x85, 0x05, 0xD0, 0x1C, 0x40, 0x11, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x16, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x14, 0x03, 0x90, 0x0C,
+0x40, 0x71, 0x01, 0xCD, 0x88, 0x04, 0x03, 0x90, 0x0C, 0x40, 0x33, 0x00, 0xC1,
+0x3A, 0x14, 0x03, 0xD0, 0x0C, 0x42, 0xF0, 0x04, 0x8D, 0x03, 0x44, 0x0B, 0xD0,
+0x8D, 0x40, 0x5B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+0x20, 0x15, 0x00, 0x5F, 0x00, 0x5C, 0x01, 0x30, 0x05, 0x40, 0xDD, 0x01, 0x7F,
+0xC1, 0x4D, 0x01, 0x31, 0x05, 0xC0, 0x9E, 0x04, 0x71, 0x03, 0x5C, 0x01, 0xB0,
+0x05, 0xC4, 0xDC, 0x01, 0x7F, 0x59, 0xCC, 0x09, 0xF0, 0xB7, 0x40, 0x5D, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x05, 0x00, 0x1F,
+0x00, 0x64, 0x00, 0xF0, 0x21, 0x50, 0x06, 0x20, 0x0B, 0x80, 0x7C, 0x00, 0xF0,
+0x01, 0xC0, 0x86, 0x04, 0x17, 0x00, 0x68, 0x08, 0xA2, 0x01, 0xD0, 0x07, 0x08,
+0x1F, 0x22, 0x7C, 0x48, 0xF0, 0x01, 0xC0, 0x4A, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x65, 0x00, 0x9F, 0x00, 0x6C, 0x82, 0xF0,
+0x09, 0xC0, 0x27, 0x00, 0x97, 0x00, 0x6C, 0x22, 0xF0, 0x49, 0xC4, 0x27, 0x00,
+0x9F, 0x00, 0x7C, 0x0A, 0xD0, 0x29, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x50, 0x02,
+0x30, 0x09, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x20, 0x2C, 0x00, 0x9D, 0x40, 0x74, 0x02, 0xD0, 0xA9, 0x40, 0x27, 0x10,
+0x94, 0x00, 0x44, 0x02, 0xD0, 0x29, 0x04, 0xA7, 0x01, 0x9D, 0x11, 0xF4, 0x4E,
+0xC2, 0x29, 0x50, 0x24, 0x00, 0x8D, 0x04, 0x44, 0x2A, 0x50, 0x09, 0x40, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x02,
+0x9D, 0x00, 0x74, 0x22, 0xD0, 0x09, 0x40, 0x23, 0x00, 0x90, 0x40, 0x64, 0x02,
+0xD0, 0x09, 0x01, 0x26, 0x82, 0x9D, 0x01, 0x74, 0x02, 0xC0, 0x28, 0x40, 0x24,
+0x00, 0x9C, 0x80, 0x54, 0x02, 0x12, 0x29, 0x46, 0x60, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x21, 0x00, 0x8D, 0x48, 0x34, 0x02,
+0xD1, 0x08, 0x40, 0x23, 0x62, 0x81, 0x08, 0x04, 0x0A, 0xD0, 0x08, 0x40, 0x23,
+0x21, 0x8D, 0x20, 0x34, 0x02, 0xD0, 0xC8, 0x40, 0x20, 0x01, 0x8D, 0x80, 0x10,
+0x53, 0x52, 0x48, 0x41, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1D, 0xB8, 0x46, 0x00, 0x1F, 0x36, 0x7C, 0x50, 0xF0, 0x45, 0xC1, 0x87,
+0x00, 0x12, 0x16, 0x6C, 0x50, 0xF1, 0x41, 0x81, 0x46, 0x00, 0x0F, 0x0A, 0x7C,
+0x04, 0xF0, 0x31, 0xC4, 0xC4, 0x02, 0x1F, 0x00, 0x58, 0x10, 0x30, 0x41, 0xE2,
+0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0xA7,
+0x00, 0x9F, 0x24, 0x78, 0x82, 0xF0, 0x09, 0xCA, 0x2F, 0x01, 0xFC, 0x04, 0x7C,
+0x06, 0xF1, 0x09, 0x80, 0x2F, 0x02, 0xBF, 0x01, 0x7C, 0x0A, 0xB0, 0xC9, 0xC0,
+0x6F, 0x02, 0xBF, 0x00, 0xEC, 0x52, 0xF0, 0x4B, 0xD1, 0x77, 0x60, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x6F, 0x00, 0x9F, 0x16, 0xFC,
+0x02, 0x34, 0x4B, 0xC0, 0x24, 0x00, 0x9F, 0x02, 0xFC, 0x22, 0xF0, 0x0B, 0xC0,
+0x2C, 0x60, 0xB3, 0x00, 0xFC, 0x46, 0xF0, 0x0B, 0xC0, 0x24, 0x00, 0xB3, 0x80,
+0xCD, 0x82, 0xF0, 0x0B, 0xC0, 0x77, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x00, 0x87, 0x00, 0x1D, 0x02, 0x74, 0x00, 0x10, 0x01, 0x40,
+0x04, 0x01, 0x0D, 0x8A, 0x74, 0x04, 0xD0, 0xA1, 0x40, 0x04, 0x08, 0x11, 0x00,
+0x74, 0x08, 0xD0, 0x41, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0xD1, 0x01,
+0x42, 0x63, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0,
+0xA1, 0x00, 0x8D, 0x00, 0x34, 0x0A, 0x11, 0x2C, 0x40, 0x20, 0x24, 0x89, 0x40,
+0x34, 0x1A, 0xD0, 0x08, 0x40, 0x20, 0x10, 0x85, 0x00, 0x34, 0x02, 0xD8, 0x08,
+0x61, 0x20, 0x40, 0x95, 0x00, 0x14, 0x06, 0xD0, 0x08, 0x40, 0x4B, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x28, 0x25, 0x00, 0x9D, 0x00,
+0x70, 0x02, 0x12, 0x09, 0x40, 0xA4, 0x0A, 0x9D, 0x20, 0x74, 0x02, 0xD0, 0x09,
+0x10, 0x24, 0x10, 0x95, 0x20, 0x74, 0x82, 0xD0, 0x08, 0x4C, 0x24, 0x04, 0x95,
+0x08, 0x54, 0xA3, 0xD0, 0x09, 0x40, 0x63, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0x2A, 0x25, 0x20, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x09,
+0xD0, 0x64, 0x00, 0x9F, 0x02, 0xFC, 0x02, 0xF0, 0x09, 0xC4, 0xA4, 0x04, 0x97,
+0x00, 0x7C, 0x02, 0xF2, 0x09, 0x50, 0x64, 0x02, 0x87, 0x00, 0x5C, 0x02, 0xF0,
+0x09, 0xC0, 0x17, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x00, 0x25, 0x00, 0x9F, 0x00, 0x7E, 0x02, 0xF0, 0x08, 0xC0, 0x67, 0x20, 0x9F,
+0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC3, 0x27, 0x02, 0x9B, 0x10, 0x7C, 0x82, 0xF0,
+0x09, 0xC0, 0x67, 0x00, 0x9A, 0x00, 0x6C, 0x02, 0xF0, 0x09, 0xC0, 0x5B, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x17,
+0x00, 0x4C, 0x00, 0xB0, 0x01, 0xC8, 0x07, 0x00, 0x13, 0x02, 0x6C, 0x20, 0xF0,
+0x81, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x4C, 0x00, 0x34, 0x01, 0xC0, 0x87, 0x00,
+0x13, 0x04, 0x7C, 0x04, 0x30, 0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x14, 0x04, 0x51, 0x00, 0x2C, 0x01, 0xD0,
+0xA7, 0x48, 0x17, 0x08, 0x51, 0x00, 0x44, 0x01, 0xD0, 0x26, 0x40, 0x5B, 0x20,
+0x7C, 0x83, 0xC4, 0x01, 0x11, 0x07, 0x41, 0x17, 0x00, 0x70, 0x00, 0xF4, 0x01,
+0x10, 0x07, 0x44, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x80, 0x32, 0x00, 0xC5, 0x00, 0x14, 0x27, 0x9A, 0x0C, 0x44, 0x33, 0x00,
+0xC0, 0x00, 0x24, 0x07, 0xD0, 0x2C, 0x40, 0x63, 0x20, 0xCD, 0x00, 0x00, 0x02,
+0x90, 0x5C, 0x40, 0x37, 0x00, 0x81, 0x03, 0x30, 0x03, 0x94, 0x1C, 0x40, 0x43,
+0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x79, 0x00,
+0xE1, 0x01, 0xA5, 0x03, 0xD0, 0x06, 0x40, 0x7B, 0x02, 0xE1, 0x49, 0x84, 0x02,
+0xD0, 0x06, 0x40, 0xBB, 0x80, 0x6D, 0x03, 0x84, 0x46, 0x92, 0x06, 0x40, 0x33,
+0x00, 0xE1, 0x02, 0xB4, 0x07, 0x90, 0x26, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x79, 0x00, 0xF7, 0x09, 0x9C, 0x06,
+0xB0, 0x1E, 0xC0, 0x7F, 0x45, 0xE2, 0x15, 0xAC, 0x07, 0xF0, 0x1A, 0xC0, 0x6B,
+0x20, 0xBF, 0x01, 0x8C, 0x06, 0xA0, 0x1A, 0xC0, 0x7B, 0x05, 0xA3, 0x01, 0xFC,
+0x07, 0xB0, 0x1E, 0xC0, 0x53, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0xB8, 0x31, 0x00, 0xDF, 0x0C, 0x5C, 0x02, 0xF1, 0x01, 0xC0, 0xB7,
+0x01, 0xDF, 0x86, 0x7C, 0x22, 0xF0, 0x09, 0xE0, 0x26, 0x00, 0x1F, 0x00, 0x3C,
+0x02, 0x70, 0x09, 0xC0, 0x37, 0x01, 0xDF, 0x80, 0x7C, 0x02, 0x72, 0x05, 0xC0,
+0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x7D,
+0x00, 0xFF, 0x01, 0xDE, 0x27, 0x70, 0x9B, 0xC0, 0x7F, 0x00, 0xFF, 0x21, 0xDC,
+0x27, 0xF0, 0x1F, 0xC0, 0x6F, 0x00, 0x7B, 0x09, 0xCC, 0x07, 0x30, 0x1F, 0xC0,
+0x7C, 0x26, 0xBF, 0x81, 0xFC, 0x27, 0x31, 0x9F, 0xC0, 0x18, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x39, 0x00, 0xED, 0x00, 0x84,
+0x02, 0xC0, 0x22, 0x42, 0x3B, 0x00, 0xE9, 0x00, 0x80, 0x02, 0xD0, 0x22, 0x40,
+0x3B, 0x00, 0x19, 0x01, 0x94, 0x0A, 0x50, 0x06, 0x40, 0x79, 0x0A, 0xED, 0x00,
+0xB4, 0x33, 0x30, 0x22, 0x40, 0x54, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x88, 0x00, 0x39, 0x00, 0xED, 0x00, 0x94, 0x82, 0x50, 0x02, 0x00,
+0x3B, 0x00, 0xED, 0x08, 0x94, 0x03, 0xD1, 0x0A, 0x40, 0x2B, 0x00, 0x39, 0x10,
+0x24, 0x03, 0xD0, 0x04, 0x40, 0x38, 0x00, 0xAD, 0x00, 0xB4, 0x09, 0x12, 0x0E,
+0x60, 0x61, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20,
+0x21, 0x00, 0xCD, 0x00, 0x04, 0x02, 0xD0, 0x00, 0x40, 0xF3, 0x00, 0xCD, 0x02,
+0x04, 0x02, 0xD0, 0x08, 0x48, 0x73, 0x84, 0x09, 0x01, 0x34, 0x03, 0xD0, 0x04,
+0x64, 0x31, 0x82, 0xCD, 0x00, 0x34, 0x04, 0x11, 0x00, 0x40, 0x09, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x10, 0xFF, 0x00,
+0x54, 0x03, 0x70, 0x09, 0xC0, 0x3F, 0x03, 0xFF, 0x01, 0x5C, 0x03, 0xF0, 0x09,
+0xC8, 0xA7, 0x01, 0x9B, 0x01, 0x64, 0x02, 0xB0, 0x0D, 0xCC, 0xFC, 0x12, 0x9D,
+0x0A, 0x7C, 0x90, 0x33, 0x19, 0xC2, 0x75, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0D, 0x00, 0x37, 0x20, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x29,
+0xC0, 0x37, 0x08, 0xDB, 0x18, 0x7E, 0x02, 0xF2, 0x01, 0x40, 0x37, 0x00, 0x1E,
+0x00, 0x5C, 0x0A, 0x38, 0x05, 0xC0, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x08, 0x74,
+0x81, 0x50, 0x16, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81,
+0x08, 0x3F, 0x10, 0xDF, 0x00, 0xFC, 0x0B, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xDF,
+0x00, 0xFC, 0x07, 0xF1, 0x0A, 0xC0, 0x2C, 0x40, 0x32, 0x01, 0xFC, 0x02, 0xF2,
+0x1A, 0x80, 0x3C, 0x00, 0xB3, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC1, 0x07, 0x26,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0xDD,
+0x00, 0x64, 0x07, 0xD0, 0x19, 0x42, 0x33, 0x00, 0xD1, 0x80, 0x74, 0x07, 0xD0,
+0x39, 0x40, 0x00, 0x00, 0x11, 0x07, 0x74, 0x00, 0xD0, 0x19, 0xC0, 0x37, 0x00,
+0x9B, 0x18, 0x64, 0x0C, 0xD0, 0x31, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x03, 0xD8,
+0x19, 0x40, 0x37, 0x00, 0xD9, 0x00, 0x74, 0x13, 0xD0, 0x11, 0x40, 0xA6, 0x00,
+0x35, 0x08, 0x74, 0x03, 0xC8, 0x49, 0x46, 0x39, 0x00, 0x91, 0x00, 0x60, 0x04,
+0xD0, 0x19, 0x40, 0x07, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x20, 0x30, 0x00, 0xCD, 0x00, 0x24, 0x02, 0xD8, 0x08, 0x40, 0x37, 0x00,
+0xC1, 0x00, 0x34, 0x82, 0xD0, 0x00, 0x40, 0x30, 0x80, 0x05, 0x00, 0x34, 0x02,
+0xD0, 0x00, 0x40, 0x32, 0x01, 0xC9, 0xA0, 0x24, 0x00, 0xD0, 0x00, 0x40, 0x43,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0x36, 0x00,
+0xFF, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x3F, 0x00, 0xFB, 0x00, 0x74, 0x02,
+0xD1, 0x01, 0xC0, 0x24, 0x00, 0x17, 0x04, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x3D,
+0x05, 0x13, 0x40, 0x7C, 0x00, 0xF0, 0x01, 0xC2, 0x07, 0x64, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xB8, 0x2F, 0x00, 0xFF, 0x00, 0xEC, 0x02,
+0xF0, 0x03, 0xCC, 0x3F, 0x00, 0xFB, 0x00, 0xF8, 0x02, 0xF2, 0x03, 0x88, 0x1F,
+0x00, 0x1B, 0x16, 0xFC, 0x01, 0xF0, 0x03, 0xC0, 0x37, 0x00, 0x7F, 0x00, 0xFC,
+0x00, 0xF0, 0x03, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xAA, 0x7B, 0x12, 0xEF, 0x09, 0xEC, 0x07, 0xB0, 0x9E, 0xC0, 0x7A,
+0x00, 0xF7, 0x09, 0xEC, 0x07, 0xF0, 0x3F, 0xC0, 0x7B, 0x00, 0xF7, 0x29, 0xCC,
+0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x00, 0xF3, 0x01, 0xFC, 0xA7, 0xB0, 0x1F, 0xC0,
+0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x07,
+0x00, 0x1D, 0x44, 0x44, 0x04, 0x32, 0x01, 0x40, 0x44, 0x20, 0x11, 0x04, 0x4C,
+0x10, 0x10, 0x01, 0xC0, 0x44, 0x00, 0x11, 0x00, 0x44, 0x10, 0xD0, 0x01, 0x40,
+0x44, 0x10, 0x11, 0x20, 0x74, 0x00, 0x10, 0x11, 0xC0, 0x0E, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x33, 0x11, 0xDD, 0x00, 0x24,
+0x03, 0x91, 0x4D, 0x42, 0x33, 0x00, 0xC5, 0x00, 0x34, 0x43, 0xD0, 0x4C, 0x40,
+0x32, 0x00, 0xC5, 0x44, 0x14, 0x43, 0xD0, 0x0C, 0x62, 0x32, 0x00, 0xC1, 0x80,
+0x34, 0x13, 0x90, 0x0D, 0x42, 0x4D, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x05, 0x00, 0x1D, 0x00, 0x54, 0x00, 0x90, 0x01, 0x40,
+0x05, 0x08, 0x01, 0x00, 0x34, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x05, 0x00,
+0x54, 0x00, 0xDA, 0x01, 0x44, 0x04, 0x40, 0x11, 0x00, 0x34, 0x00, 0x11, 0x01,
+0x40, 0x0F, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0,
+0x37, 0x08, 0xDF, 0x80, 0x6C, 0x83, 0xB0, 0x0D, 0xC0, 0x37, 0x00, 0xD6, 0x00,
+0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x33, 0x00, 0xD7, 0x00, 0x5C, 0x03, 0xE0, 0x0D,
+0xC0, 0x32, 0x00, 0xD3, 0x00, 0x7C, 0x03, 0xB1, 0x0C, 0xC0, 0x21, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0D, 0x00, 0x3F, 0x00,
+0xEC, 0x00, 0x70, 0x03, 0xC8, 0x0E, 0x20, 0x3E, 0x00, 0xCC, 0x00, 0xF0, 0x03,
+0xC0, 0x0C, 0x08, 0x3B, 0x00, 0xEC, 0x00, 0xF2, 0x03, 0xC0, 0x0E, 0x00, 0x3F,
+0x00, 0xE4, 0x00, 0xF0, 0x03, 0xC0, 0x1E, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0A, 0x00, 0x35, 0x20, 0xD7, 0xC8, 0x5C, 0x83, 0xC0, 0x0D,
+0xC0, 0x35, 0x01, 0xD7, 0x00, 0x5C, 0x03, 0xF0, 0x4D, 0xC0, 0x36, 0x00, 0xD7,
+0x00, 0x7C, 0x13, 0x30, 0x4D, 0xC4, 0x36, 0x00, 0xD7, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xD0, 0x28, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0xA0, 0xC4, 0x00, 0x01, 0x83, 0x04, 0x04, 0x10, 0xE0, 0x40, 0x80, 0x00, 0x11,
+0x00, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x07, 0x02, 0x11, 0x00, 0x74, 0x48, 0xB0,
+0x50, 0x40, 0xC7, 0x00, 0x11, 0x00, 0x70, 0x24, 0xD1, 0x01, 0x40, 0x4D, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0xB0, 0x04, 0xC5,
+0x53, 0x14, 0x03, 0x50, 0x0C, 0x42, 0x31, 0x00, 0xC5, 0x00, 0x14, 0x03, 0xD0,
+0x0D, 0x00, 0x32, 0x00, 0xC5, 0x00, 0x34, 0x0F, 0x92, 0x3C, 0x44, 0xB2, 0x09,
+0xC5, 0x00, 0x24, 0x03, 0xD0, 0x0C, 0x40, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0F, 0x08, 0x4C, 0x06, 0x31, 0x01, 0xC4, 0x04, 0x11,
+0x13, 0x40, 0x48, 0x08, 0x25, 0x01, 0x84, 0x04, 0xD0, 0x12, 0x40, 0x4B, 0x00,
+0x21, 0x01, 0xF4, 0x04, 0xD2, 0x92, 0x40, 0x4B, 0x0C, 0x21, 0x01, 0xB4, 0x14,
+0xD0, 0x92, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x10, 0x30, 0x00, 0xC7, 0x08, 0x1C, 0x63, 0x72, 0x0C, 0xC0, 0x31, 0x02,
+0xD5, 0x00, 0x1C, 0x13, 0xF0, 0x4C, 0xC0, 0x32, 0x01, 0xC7, 0x28, 0x3C, 0x23,
+0xB0, 0x8C, 0xC0, 0x32, 0x00, 0xC6, 0x00, 0x3C, 0x63, 0xF2, 0x8C, 0xC0, 0x4A,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x0D, 0x00,
+0x3F, 0x00, 0xBC, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x0A, 0x3B, 0x08, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x08, 0xBC, 0xA0, 0xA0, 0x81, 0xC0, 0x0B,
+0x10, 0x1F, 0x00, 0xFC, 0x30, 0xF0, 0x90, 0xC0, 0x09, 0x60, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37, 0x00, 0xD3, 0x00, 0x7E, 0x03,
+0x70, 0x0D, 0x80, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x30,
+0x00, 0xDA, 0x00, 0x5C, 0x03, 0xF0, 0x0C, 0xC0, 0x30, 0x00, 0xD3, 0x00, 0x7C,
+0x03, 0x34, 0x0D, 0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0x80, 0x0D, 0x08, 0x20, 0x00, 0xB2, 0x00, 0xD1, 0x02, 0x40, 0x0B,
+0x00, 0x2D, 0x00, 0xB4, 0x00, 0x50, 0x02, 0xC0, 0x09, 0x00, 0x21, 0xA0, 0xB4,
+0x00, 0xD0, 0x02, 0xC4, 0x0A, 0x00, 0x2B, 0x80, 0xB4, 0x00, 0x10, 0x02, 0xC0,
+0x4E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x79,
+0x20, 0xE9, 0x01, 0x94, 0x87, 0xD0, 0x1E, 0x60, 0x7B, 0x00, 0xED, 0x01, 0xF4,
+0x07, 0xD0, 0x1F, 0x40, 0x7B, 0x00, 0xE9, 0x01, 0xB4, 0x07, 0xD0, 0x1F, 0x40,
+0x7E, 0x00, 0xE9, 0x21, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x10, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x02, 0x00, 0x09, 0x00, 0x34,
+0x00, 0xD2, 0x01, 0x40, 0x03, 0x00, 0x0D, 0x00, 0x74, 0x00, 0xD0, 0x00, 0x40,
+0x01, 0x80, 0x0D, 0x00, 0x34, 0x80, 0xD0, 0x00, 0x40, 0x02, 0x00, 0x09, 0x00,
+0x36, 0x00, 0x10, 0x00, 0x40, 0x5A, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x17, 0xA0, 0x11, 0x00, 0x5B, 0x00, 0x78, 0x01, 0x70, 0x05, 0xE0,
+0x17, 0x00, 0x5F, 0x00, 0x7E, 0x01, 0xB1, 0x04, 0xC0, 0x16, 0x00, 0x5B, 0x20,
+0x5C, 0x01, 0xF0, 0x05, 0xC4, 0x14, 0x00, 0x5B, 0x20, 0x7C, 0x01, 0x30, 0x05,
+0xC0, 0x5C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88,
+0x8F, 0x40, 0x37, 0x00, 0xFC, 0x00, 0xF0, 0x03, 0xE0, 0x0F, 0x00, 0x3F, 0x00,
+0xFA, 0x00, 0x70, 0x23, 0xC0, 0x0F, 0x00, 0x33, 0x00, 0xF4, 0x08, 0xF0, 0x23,
+0xC0, 0x8F, 0x00, 0x3F, 0x40, 0xF4, 0x08, 0xF0, 0x03, 0xC0, 0x4B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x01, 0x97, 0x00,
+0x7C, 0x16, 0x50, 0x09, 0xC0, 0x27, 0x10, 0x9F, 0xA0, 0x7C, 0x02, 0x33, 0x09,
+0xC2, 0x25, 0x20, 0x93, 0x40, 0x74, 0x02, 0x02, 0x09, 0x54, 0xA4, 0x00, 0x97,
+0x00, 0x7C, 0x06, 0x32, 0x29, 0xC2, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x20, 0xE6, 0x00, 0x91, 0x05, 0x34, 0x86, 0x10, 0x39,
+0x40, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x50, 0x09, 0x10, 0xA0, 0x04, 0x91,
+0x00, 0x34, 0x06, 0xB2, 0x28, 0x40, 0xE0, 0x08, 0x95, 0x00, 0x30, 0x06, 0x51,
+0x08, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA0, 0x24, 0x00, 0xB5, 0x04, 0xF4, 0x02, 0x50, 0x6B, 0x40, 0x2D, 0x00, 0xBD,
+0x80, 0xD4, 0x82, 0x18, 0x0B, 0x41, 0x2C, 0xC0, 0xB1, 0x00, 0xD4, 0x12, 0x10,
+0x2B, 0x40, 0x2D, 0x90, 0xB0, 0x80, 0xF4, 0x22, 0x12, 0x0B, 0x42, 0x60, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x3D, 0x00, 0xA1,
+0x00, 0xF4, 0x02, 0x50, 0x0A, 0x40, 0x28, 0x20, 0xAC, 0x28, 0xB4, 0x22, 0x50,
+0x0A, 0x40, 0x28, 0x00, 0xA1, 0xC8, 0xF4, 0x03, 0xD0, 0x0A, 0x40, 0x2D, 0x00,
+0xA4, 0x00, 0xF4, 0x23, 0x50, 0x0E, 0x40, 0x41, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0x38, 0x06, 0x00, 0x17, 0x80, 0x7C, 0x00, 0x70,
+0x01, 0xC0, 0x07, 0x00, 0x1C, 0x02, 0x7C, 0x08, 0x30, 0x01, 0xC0, 0x05, 0x00,
+0x13, 0x02, 0x5C, 0x00, 0x32, 0xA1, 0xC0, 0x15, 0x00, 0x17, 0x0A, 0x38, 0x08,
+0x30, 0x03, 0xC8, 0x74, 0xE0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB0, 0x25, 0x05, 0x9F, 0x34, 0x7C, 0x02, 0xB0, 0x49, 0xC1, 0x27, 0x00,
+0x9F, 0x04, 0x2C, 0x12, 0xF0, 0x48, 0xC9, 0x27, 0x00, 0x9F, 0x04, 0x7C, 0x52,
+0xB0, 0x19, 0xC0, 0x26, 0x00, 0x9F, 0x01, 0x7C, 0x12, 0xF0, 0x08, 0xC0, 0x77,
+0x40, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x80, 0x2F, 0x00,
+0xBF, 0x08, 0xDC, 0x02, 0xF8, 0x0B, 0xC2, 0x2F, 0x00, 0x8F, 0x02, 0x7C, 0x02,
+0x34, 0x0B, 0xC0, 0x2C, 0x00, 0x93, 0x00, 0xFC, 0x0A, 0x30, 0x0B, 0xC0, 0x2C,
+0x40, 0x83, 0x00, 0xCC, 0x02, 0xB0, 0x0B, 0xC0, 0x74, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x47, 0x01, 0x1D, 0x25, 0x44, 0x00,
+0xD1, 0x41, 0x41, 0x07, 0x00, 0x1D, 0x04, 0x74, 0x80, 0x10, 0x01, 0x42, 0x05,
+0x08, 0x11, 0x00, 0x74, 0x00, 0xB0, 0x01, 0x42, 0x04, 0x00, 0x11, 0x40, 0x44,
+0x00, 0x11, 0x01, 0x40, 0x61, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x31, 0x15, 0x8D, 0x44, 0x10, 0x02, 0xD8, 0x0C, 0x40, 0x23,
+0x00, 0x8D, 0x04, 0x34, 0x42, 0x10, 0x09, 0x40, 0x20, 0x00, 0x81, 0x14, 0x34,
+0x02, 0x10, 0x08, 0x50, 0x20, 0x80, 0x81, 0x20, 0x15, 0x02, 0xD0, 0x09, 0x40,
+0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2A, 0x25,
+0x00, 0x9D, 0x00, 0x44, 0x82, 0xD0, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x00, 0x74,
+0x02, 0x11, 0x09, 0x40, 0x25, 0x20, 0x91, 0x00, 0x74, 0x02, 0x90, 0x08, 0x60,
+0x24, 0x00, 0x91, 0x00, 0x54, 0x02, 0xD0, 0x09, 0x40, 0x61, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x22, 0x25, 0x10, 0x9F, 0x00, 0x5C,
+0x02, 0xD0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x09, 0xC0,
+0x20, 0x08, 0x93, 0x80, 0x7C, 0x02, 0x30, 0x09, 0xC0, 0x20, 0x00, 0x93, 0x00,
+0x5C, 0x82, 0xF0, 0x09, 0xC0, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x16, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x40, 0x9F, 0x00,
+0x7C, 0x02, 0xF0, 0x09, 0xC1, 0x27, 0x04, 0x9F, 0x00, 0x6C, 0x42, 0x30, 0x09,
+0x40, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08,
+0x05, 0x00, 0x17, 0x00, 0x4C, 0x00, 0xF0, 0x41, 0xC4, 0x07, 0x01, 0x17, 0x00,
+0x4C, 0x00, 0x70, 0x01, 0xC3, 0x07, 0x00, 0x1F, 0x00, 0x5C, 0x40, 0xB0, 0x01,
+0xC0, 0x04, 0x00, 0x1F, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC1, 0x51, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1C, 0x02, 0x7D, 0xD8,
+0x44, 0x01, 0x70, 0x27, 0x40, 0x9F, 0x00, 0x51, 0x20, 0x6C, 0x01, 0xD0, 0x76,
+0x42, 0xDF, 0x00, 0x5D, 0x40, 0xEC, 0x0D, 0x11, 0x27, 0x40, 0x1C, 0x00, 0x59,
+0x00, 0xD4, 0x01, 0x14, 0x06, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0x32, 0x00, 0xD5, 0x40, 0x04, 0x26, 0xD0, 0x0C,
+0x40, 0xA3, 0x00, 0xC5, 0x00, 0x44, 0x03, 0x58, 0x0C, 0x48, 0xF3, 0x03, 0xCD,
+0x00, 0x46, 0x07, 0x90, 0x2C, 0x40, 0x32, 0x00, 0xDD, 0x00, 0x40, 0x0F, 0x00,
+0x3C, 0x40, 0x40, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x80, 0x38, 0x20, 0xED, 0x40, 0x85, 0x03, 0x58, 0x0E, 0x68, 0xEF, 0x00, 0xF5,
+0x09, 0xA4, 0x23, 0xD0, 0x06, 0x40, 0x3B, 0x00, 0xFD, 0x45, 0xA4, 0x0B, 0x10,
+0x02, 0x41, 0x2A, 0x04, 0xF9, 0x04, 0x96, 0x0B, 0x12, 0x0E, 0x45, 0x10, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x59, 0x00, 0x77,
+0x01, 0x8C, 0x07, 0xF1, 0x1E, 0x40, 0x6B, 0x00, 0xE7, 0x15, 0x8C, 0x07, 0x70,
+0x16, 0x80, 0x7B, 0x00, 0xEF, 0x01, 0xDC, 0x05, 0xB0, 0x1E, 0xD0, 0x5A, 0x08,
+0xEF, 0x07, 0xCC, 0x06, 0x30, 0x1E, 0xC0, 0x51, 0x60, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x15, 0x00, 0x5F, 0x40, 0x7C, 0x83, 0xF0,
+0x0D, 0xC0, 0x23, 0x00, 0xDB, 0x06, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x37, 0x00,
+0xCF, 0x08, 0x7E, 0x83, 0xF0, 0x60, 0xD5, 0x15, 0x20, 0xDB, 0x06, 0x7C, 0x02,
+0xD0, 0x0C, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x20, 0x7D, 0x0A, 0xFF, 0x01, 0xDC, 0xA7, 0xF0, 0x1F, 0xC0, 0x7F, 0x00,
+0xE7, 0x01, 0x8C, 0x0F, 0xB0, 0x13, 0xC8, 0x7B, 0x00, 0xF3, 0x03, 0xCC, 0x07,
+0x30, 0x1B, 0xD0, 0x78, 0xA2, 0xFB, 0x03, 0xCC, 0x07, 0xF0, 0x1A, 0xC0, 0x18,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x39, 0x00,
+0xEC, 0x18, 0xB4, 0x83, 0xD0, 0x0E, 0x42, 0x3B, 0x28, 0xE1, 0x10, 0x94, 0x03,
+0x50, 0x22, 0x44, 0x3B, 0x06, 0xE5, 0x00, 0xD4, 0x03, 0x50, 0x43, 0x40, 0x28,
+0x02, 0xE1, 0x04, 0x84, 0x13, 0x71, 0x4A, 0x48, 0x54, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x02, 0x39, 0x10, 0xED, 0x00, 0x94, 0x03,
+0xC0, 0x06, 0x40, 0x3B, 0x04, 0xF5, 0x00, 0xE4, 0x43, 0x10, 0x02, 0x40, 0x3F,
+0x00, 0xFD, 0x00, 0xD4, 0x01, 0x50, 0x0A, 0x61, 0x18, 0x84, 0xE1, 0xB0, 0x84,
+0x42, 0xD2, 0x0A, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x28, 0x65, 0x00, 0x8D, 0x00, 0x36, 0x13, 0xD0, 0x39, 0x40, 0xF3,
+0x00, 0xC5, 0x03, 0x34, 0x0B, 0x50, 0xA0, 0x40, 0xF3, 0x00, 0xDD, 0x02, 0x14,
+0x2A, 0x50, 0x38, 0x62, 0x40, 0x04, 0xC9, 0x53, 0x05, 0x04, 0x50, 0x28, 0x40,
+0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xA0, 0xE5,
+0x10, 0x9F, 0x01, 0x5C, 0x43, 0xD0, 0xA1, 0xC4, 0x07, 0x02, 0xF7, 0x01, 0xEC,
+0x07, 0x30, 0xB1, 0xC8, 0xB7, 0x00, 0xFF, 0x01, 0x5E, 0x0E, 0x10, 0x99, 0xC4,
+0x44, 0x00, 0xEB, 0x00, 0x0C, 0x81, 0xF3, 0x3D, 0xC6, 0x54, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x27, 0x06, 0x9F, 0x04, 0x7C,
+0x03, 0xF0, 0x81, 0xC0, 0xA7, 0x10, 0xDA, 0x00, 0x5C, 0x43, 0x78, 0x21, 0x80,
+0x37, 0x0C, 0xD7, 0xB8, 0x78, 0x00, 0xF0, 0x09, 0xC0, 0xA7, 0x40, 0xD7, 0x00,
+0x7C, 0x81, 0x70, 0xAD, 0xC1, 0x37, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x08, 0x0F, 0x00, 0x3B, 0x00, 0xFC, 0x03, 0xF0, 0x0B, 0xC0,
+0x0E, 0x00, 0xF3, 0x10, 0xCC, 0x03, 0xF0, 0x03, 0x40, 0x3E, 0x00, 0xF3, 0x00,
+0xFC, 0x40, 0xF0, 0x0B, 0xC0, 0x0C, 0x00, 0xF7, 0x00, 0xD4, 0x54, 0x30, 0x0F,
+0xC0, 0x04, 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20,
+0xC6, 0x00, 0x11, 0x03, 0x74, 0x03, 0xD0, 0x19, 0x40, 0x60, 0x01, 0xDB, 0x00,
+0x54, 0x03, 0xD0, 0x11, 0x40, 0xD3, 0x00, 0xDB, 0x00, 0x44, 0x0C, 0xD0, 0x18,
+0xC0, 0x83, 0x20, 0xD1, 0x00, 0x54, 0x89, 0x51, 0x4C, 0x50, 0x84, 0x04, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xC6, 0x00, 0x19, 0x03,
+0x74, 0x13, 0xD8, 0x31, 0x40, 0x66, 0x00, 0xC1, 0x80, 0x44, 0x03, 0xD0, 0x11,
+0x40, 0x66, 0x04, 0xD1, 0x00, 0x44, 0xC6, 0x90, 0x1B, 0x40, 0x04, 0x06, 0xF5,
+0x00, 0x40, 0x09, 0x50, 0x45, 0x48, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x81, 0x00, 0x34, 0x83, 0xD0, 0x00,
+0x40, 0x24, 0x00, 0xCD, 0x00, 0x14, 0x03, 0xD0, 0x00, 0x40, 0x27, 0x00, 0xC9,
+0x00, 0x04, 0x82, 0xC2, 0x19, 0x40, 0x02, 0xA0, 0xD1, 0x40, 0x54, 0x02, 0x50,
+0x04, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x18, 0x06, 0x10, 0x1B, 0x00, 0x7C, 0x03, 0xDA, 0x01, 0xC0, 0x26, 0x00, 0xF3,
+0x00, 0xC4, 0x03, 0xF0, 0x01, 0xC4, 0x26, 0x00, 0xF3, 0x00, 0x5D, 0x00, 0xF0,
+0x0B, 0xC0, 0x04, 0x00, 0xE7, 0x00, 0x5C, 0x00, 0x30, 0x09, 0xD0, 0x04, 0x60,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xB8, 0x2F, 0x00, 0xBF,
+0x00, 0xFC, 0x03, 0xD0, 0x0B, 0xC0, 0x2B, 0x00, 0xFB, 0x00, 0xFC, 0x03, 0xE0,
+0x03, 0xC0, 0x2F, 0x00, 0xEF, 0x00, 0xFC, 0x02, 0xF1, 0x0B, 0xC2, 0x0F, 0x00,
+0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0B, 0xC4, 0x17, 0x62, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x6F, 0x00, 0xBF, 0x10, 0xFC, 0x05, 0x30,
+0x16, 0xC8, 0x3F, 0x10, 0xFF, 0x14, 0xFC, 0x00, 0x30, 0x17, 0xC0, 0x2C, 0x00,
+0x63, 0x01, 0xFC, 0x0F, 0x30, 0x4B, 0xC0, 0x5F, 0x00, 0xF3, 0x01, 0xBC, 0x02,
+0xB0, 0x1F, 0xC8, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x67, 0x00, 0xDD, 0x01, 0x74, 0x05, 0x00, 0x19, 0x40, 0xFF, 0x30,
+0xFD, 0x03, 0x74, 0x0D, 0x10, 0x1D, 0x42, 0xE4, 0x00, 0x95, 0x01, 0xF4, 0x13,
+0x12, 0x19, 0x40, 0x77, 0x00, 0xF1, 0x41, 0x74, 0x02, 0x50, 0x11, 0x40, 0x0F,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x00,
+0x8D, 0x40, 0x74, 0x00, 0x00, 0x08, 0x40, 0xB3, 0x00, 0xCD, 0x00, 0x14, 0x08,
+0x14, 0x0D, 0x48, 0xB0, 0x10, 0x84, 0x00, 0x34, 0x13, 0x10, 0x8C, 0x40, 0x23,
+0x00, 0xC1, 0x00, 0x54, 0x02, 0x90, 0x0C, 0x40, 0x4F, 0x80, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA8, 0x35, 0x00, 0x9D, 0x00, 0x74, 0x10,
+0x18, 0x09, 0x40, 0x37, 0x20, 0xDD, 0x00, 0x76, 0x23, 0x10, 0x0D, 0x48, 0x30,
+0x00, 0x91, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x04, 0x23, 0x00, 0xD1, 0x40, 0x74,
+0x06, 0x50, 0x0D, 0x42, 0x0F, 0xA0, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA0, 0x77, 0x00, 0x9F, 0x01, 0x3C, 0x09, 0x30, 0x0D, 0xC2, 0x37,
+0x00, 0xDF, 0x60, 0x5C, 0x13, 0x31, 0x08, 0xC8, 0x64, 0x02, 0xD3, 0x00, 0x7C,
+0x03, 0x34, 0x0D, 0xC0, 0xD7, 0x00, 0xD3, 0x00, 0x7C, 0x17, 0xB2, 0x6D, 0xC0,
+0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x3D,
+0x21, 0x9F, 0x04, 0xFC, 0x45, 0xF4, 0x0B, 0xC2, 0x3F, 0x00, 0xFF, 0x00, 0xFC,
+0x03, 0xF0, 0x2B, 0xD0, 0x3F, 0x40, 0xFD, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x7F, 0x01, 0xFF, 0x80, 0xFC, 0x03, 0xF1, 0x23, 0xC0, 0x1F, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x01, 0x9F, 0x00, 0x5C,
+0x09, 0xB8, 0x0D, 0xC1, 0x34, 0x00, 0xDB, 0x50, 0x7C, 0x01, 0xB0, 0x0D, 0xC0,
+0x27, 0x80, 0x9E, 0x04, 0x0C, 0x03, 0xD0, 0x0D, 0xC4, 0xB7, 0x08, 0xDF, 0x40,
+0x7C, 0x13, 0x32, 0x0D, 0xC2, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x13, 0x80, 0x34, 0x00, 0x9D, 0x00, 0x44, 0x0D, 0xF0, 0x29, 0x40,
+0x3C, 0x00, 0xFD, 0x01, 0x34, 0x0B, 0x10, 0x0D, 0x48, 0x37, 0x80, 0x9F, 0x12,
+0x44, 0x2B, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x11, 0x34, 0x03, 0xB0, 0x1D,
+0x41, 0x6F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20,
+0x30, 0x00, 0x8D, 0x00, 0x14, 0x0C, 0xD0, 0xB4, 0x50, 0x70, 0x01, 0xCD, 0x02,
+0x20, 0x10, 0x92, 0x00, 0x4C, 0x23, 0x00, 0x4D, 0x01, 0x24, 0x23, 0xD0, 0x08,
+0x40, 0x23, 0x00, 0xCD, 0x00, 0x34, 0x08, 0x1C, 0x0C, 0x40, 0x0F, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00, 0xED, 0x01,
+0x84, 0x44, 0x50, 0x1B, 0x40, 0x78, 0x00, 0xED, 0x01, 0x34, 0x06, 0x10, 0x1A,
+0x40, 0x7B, 0x00, 0xB5, 0x09, 0xA6, 0x97, 0xD0, 0x1A, 0x40, 0x6B, 0x00, 0xED,
+0x01, 0xF4, 0x86, 0x90, 0x12, 0x40, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x18, 0x30, 0x04, 0xCF, 0x08, 0x1C, 0x00, 0xDA, 0x08,
+0xC8, 0x30, 0x14, 0xCB, 0x10, 0x2C, 0x20, 0xB0, 0x48, 0xC0, 0x23, 0x02, 0x8D,
+0x00, 0x2C, 0x23, 0xF0, 0x8C, 0x40, 0xA3, 0x00, 0xCF, 0x8C, 0x3E, 0x00, 0x30,
+0x0C, 0xC0, 0x4B, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x38, 0x3D, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xFF,
+0x12, 0xF4, 0x23, 0xF0, 0x0B, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xDD, 0x37, 0xF0,
+0x0F, 0x00, 0x2F, 0x00, 0xDF, 0x29, 0x7E, 0x22, 0xF4, 0x0F, 0xC0, 0x0B, 0x60,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x33, 0x00, 0xD3,
+0x48, 0x7C, 0x00, 0x60, 0x0C, 0xC0, 0xB4, 0x04, 0xDF, 0x04, 0x5C, 0x00, 0xF0,
+0x09, 0xC0, 0x24, 0x00, 0xD7, 0x01, 0x6C, 0x27, 0x30, 0x0D, 0xC0, 0x27, 0x00,
+0xDF, 0x00, 0x7C, 0x00, 0x30, 0x00, 0xC0, 0x40, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x39, 0x00, 0xE1, 0xC0, 0xB4, 0x00, 0xD0,
+0x0A, 0x44, 0x38, 0x00, 0xED, 0x04, 0xB4, 0x02, 0xD0, 0x0A, 0x40, 0x38, 0x00,
+0xED, 0x00, 0x04, 0x13, 0x10, 0x0E, 0x40, 0x2B, 0x00, 0xED, 0x04, 0xB4, 0x02,
+0x50, 0x02, 0x40, 0x4C, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x79, 0x10, 0xE1, 0x05, 0xB4, 0x44, 0xD8, 0x1F, 0x51, 0x78, 0x13,
+0xE9, 0x05, 0x94, 0x25, 0xD0, 0x3A, 0x40, 0xE8, 0x02, 0xAD, 0x01, 0xA4, 0x07,
+0x90, 0x1E, 0x40, 0x6B, 0x04, 0xED, 0x09, 0xF4, 0x0C, 0x10, 0x02, 0x40, 0x10,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x28, 0x33, 0x00,
+0xC1, 0x01, 0x34, 0x16, 0xD0, 0x38, 0x40, 0x30, 0x10, 0xCD, 0x00, 0x34, 0x07,
+0xD0, 0x18, 0x41, 0x70, 0x00, 0x8D, 0x00, 0x04, 0x03, 0x90, 0x9C, 0x40, 0x63,
+0x00, 0xCD, 0x00, 0x34, 0x06, 0x50, 0x8C, 0x40, 0x58, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x15, 0x00, 0x43, 0x11, 0xFC, 0x05,
+0xF0, 0x36, 0xC0, 0x14, 0x20, 0x4F, 0x00, 0xDC, 0x15, 0xF1, 0x27, 0xD4, 0x14,
+0x00, 0x77, 0x1B, 0x6C, 0x01, 0xB5, 0x15, 0xC0, 0x1F, 0x00, 0x5F, 0x00, 0xBC,
+0x01, 0x34, 0x37, 0xC4, 0x5C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x08, 0x05, 0x42, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x21, 0xC0, 0x07,
+0x20, 0x1F, 0x00, 0x70, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C,
+0x08, 0x71, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x22, 0x7C, 0x00, 0xF0, 0x01, 0xC1,
+0x4B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25,
+0x00, 0x93, 0x00, 0x45, 0x06, 0x50, 0x19, 0xD1, 0x24, 0x40, 0x93, 0x08, 0x5C,
+0x42, 0xF0, 0x09, 0x40, 0x22, 0x40, 0x93, 0x02, 0x7C, 0x16, 0xF0, 0x29, 0xC0,
+0x27, 0x00, 0x93, 0x82, 0x7C, 0x06, 0x34, 0x09, 0xC0, 0x43, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x20, 0x00, 0xB1, 0x03, 0x44,
+0x02, 0xD0, 0x29, 0x40, 0x20, 0x13, 0x91, 0x40, 0xC4, 0x02, 0xD0, 0x09, 0x40,
+0x2C, 0x00, 0x91, 0x40, 0xF4, 0x0E, 0xD0, 0x09, 0x40, 0x22, 0x20, 0xB1, 0x83,
+0x74, 0x06, 0x10, 0x09, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x24, 0x40, 0x91, 0x08, 0x54, 0x1B, 0xD0, 0x69, 0x40,
+0x24, 0x00, 0x91, 0x50, 0x50, 0x1A, 0xD0, 0x08, 0x40, 0x27, 0x00, 0x91, 0x00,
+0x74, 0x0A, 0xD8, 0x09, 0x40, 0x27, 0x00, 0x91, 0x40, 0x74, 0x52, 0x10, 0x09,
+0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
+0x21, 0x00, 0x81, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x40, 0x20, 0x00, 0x80, 0x00,
+0x04, 0x02, 0xD0, 0x28, 0x40, 0xA0, 0x00, 0x81, 0x00, 0x34, 0x0A, 0x80, 0x08,
+0x40, 0xA6, 0x00, 0x81, 0x00, 0x74, 0x02, 0x14, 0x08, 0x40, 0x43, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB8, 0x07, 0x00, 0x53, 0x01,
+0x5C, 0x00, 0x70, 0x01, 0xC0, 0x04, 0x05, 0x12, 0x14, 0x5C, 0x04, 0xF0, 0x00,
+0xC0, 0x47, 0x00, 0x13, 0x00, 0x7C, 0x04, 0xF0, 0x11, 0xC0, 0x07, 0x40, 0x53,
+0x81, 0x7C, 0x00, 0x34, 0x01, 0xC0, 0x77, 0xE0, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB8, 0x2F, 0x00, 0xBF, 0x02, 0xFC, 0x02, 0xF0, 0x0B,
+0xC0, 0x27, 0x08, 0x9F, 0x40, 0xFC, 0x0A, 0xF1, 0x1B, 0xC0, 0xEF, 0x00, 0xEF,
+0x00, 0x7C, 0x0E, 0xF0, 0x2B, 0x00, 0x6E, 0x20, 0x9F, 0x82, 0xBC, 0x5A, 0xE0,
+0x0B, 0xC0, 0x77, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xA0, 0x29, 0x00, 0xBF, 0x01, 0xCC, 0x02, 0x34, 0x0B, 0xD0, 0x2C, 0x40, 0xA3,
+0x00, 0xBC, 0x46, 0xB0, 0x09, 0x40, 0x67, 0x00, 0xBB, 0x00, 0xC4, 0x16, 0x24,
+0x5B, 0xC0, 0xA7, 0x10, 0xB3, 0x15, 0xCD, 0x42, 0xB0, 0x0B, 0xC0, 0x74, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0x00, 0x1D,
+0x00, 0x44, 0x00, 0x10, 0x05, 0x40, 0x85, 0x02, 0x11, 0x40, 0x74, 0x08, 0x30,
+0x55, 0x41, 0xC3, 0x01, 0x11, 0x00, 0x54, 0x14, 0x10, 0x01, 0x40, 0x47, 0x08,
+0x11, 0x02, 0x44, 0x08, 0x11, 0x01, 0x40, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x22, 0x21, 0x00, 0x8D, 0x02, 0x14, 0x02, 0x90,
+0x08, 0x68, 0x20, 0x00, 0x81, 0x02, 0x34, 0x02, 0x90, 0x08, 0x40, 0xA3, 0x04,
+0x99, 0x00, 0x04, 0x4A, 0x10, 0x28, 0x40, 0x23, 0x00, 0x81, 0x20, 0x04, 0x52,
+0x91, 0x09, 0x42, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x28, 0x25, 0x00, 0x9D, 0x00, 0x44, 0x02, 0x10, 0x09, 0x64, 0x24, 0x00,
+0x90, 0x00, 0x74, 0x06, 0x10, 0x89, 0x4C, 0x27, 0x00, 0x91, 0x00, 0x14, 0x02,
+0x10, 0x09, 0x40, 0x23, 0x40, 0x91, 0x00, 0x44, 0x02, 0x90, 0x19, 0x40, 0x60,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x65, 0x02,
+0x8F, 0x09, 0x5C, 0x12, 0xB0, 0x18, 0x40, 0x24, 0x00, 0x93, 0x00, 0x7C, 0x4A,
+0xB0, 0x3B, 0xC0, 0x6F, 0x00, 0x9B, 0x00, 0xCC, 0x02, 0x30, 0x19, 0xC0, 0xEF,
+0x01, 0x93, 0x80, 0x4C, 0x02, 0xB0, 0x49, 0xD0, 0x14, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x6D, 0x12,
+0xF0, 0x59, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x70, 0x09, 0xC0, 0x23,
+0x01, 0x9F, 0x02, 0x7C, 0x02, 0xF0, 0x89, 0xC0, 0x67, 0x01, 0x9F, 0x00, 0x7C,
+0x02, 0x71, 0x09, 0xC0, 0x5B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x08, 0x05, 0x10, 0x13, 0x08, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x05,
+0xC1, 0x13, 0x08, 0x1C, 0x10, 0x34, 0x01, 0xC0, 0x07, 0x00, 0x1B, 0x00, 0x7C,
+0x00, 0x30, 0x01, 0xC0, 0x87, 0x00, 0x1F, 0x08, 0x7C, 0x00, 0x31, 0x01, 0xC0,
+0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0xDC,
+0x06, 0x71, 0x00, 0xB0, 0x1D, 0x50, 0x07, 0x42, 0x1B, 0x80, 0x71, 0x01, 0xC4,
+0x0D, 0x10, 0x05, 0x40, 0x17, 0x00, 0x71, 0x02, 0xF4, 0x61, 0xB0, 0x05, 0x40,
+0x17, 0x00, 0x6D, 0x00, 0xF4, 0x01, 0x11, 0x04, 0x40, 0x43, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xE2, 0x00, 0x81, 0x10, 0x34,
+0x1E, 0x18, 0x04, 0x40, 0x23, 0x10, 0x85, 0x51, 0x14, 0x0D, 0x10, 0x0C, 0x40,
+0x33, 0x00, 0xD9, 0x13, 0x34, 0x06, 0x14, 0x1C, 0x40, 0x33, 0x00, 0x8D, 0x10,
+0x74, 0x02, 0x10, 0x08, 0x40, 0x43, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x82, 0x7C, 0x00, 0xA1, 0x00, 0xF4, 0x03, 0x50, 0x06, 0x40,
+0x33, 0x00, 0xA5, 0x01, 0x84, 0x09, 0x11, 0x4E, 0x40, 0x3B, 0x03, 0xE1, 0x02,
+0xB4, 0x33, 0x90, 0x0E, 0x61, 0x3B, 0x09, 0xED, 0x00, 0xB4, 0x02, 0x10, 0x0E,
+0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18,
+0x68, 0x00, 0xA3, 0x01, 0xBC, 0x06, 0x30, 0x16, 0xC0, 0x6B, 0x00, 0xE5, 0x01,
+0x9C, 0x05, 0x30, 0x3E, 0xC0, 0x7B, 0x00, 0xEB, 0x01, 0xBC, 0x07, 0x30, 0x1E,
+0xC0, 0xFB, 0x00, 0xAF, 0x01, 0x3C, 0x01, 0x30, 0x1A, 0xC0, 0x53, 0x60, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x40, 0x9D, 0x00,
+0x3C, 0x02, 0xF0, 0x05, 0xC0, 0x27, 0x00, 0xDB, 0x00, 0x7C, 0x01, 0xF0, 0x0D,
+0xC0, 0x37, 0x00, 0xDF, 0x00, 0x3C, 0x03, 0x70, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x28, 0x6D, 0x00, 0xBB, 0x21, 0xFC, 0x06, 0xF0, 0x17,
+0xC0, 0x6F, 0x00, 0xB3, 0x01, 0xDE, 0x07, 0x31, 0x9E, 0xC8, 0x7C, 0x00, 0xAE,
+0x01, 0xEC, 0x07, 0xF8, 0x9F, 0xC0, 0x78, 0x00, 0xB3, 0x41, 0xCC, 0x06, 0x30,
+0x1B, 0xC0, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x10, 0x29, 0x00, 0xAD, 0x08, 0xB4, 0x03, 0xD0, 0x06, 0x40, 0x3B, 0x08, 0xA1,
+0x00, 0x84, 0x13, 0xB0, 0x0E, 0x40, 0x38, 0x00, 0xED, 0x02, 0x84, 0x03, 0xD0,
+0x0E, 0xC0, 0x3A, 0x02, 0xA1, 0x00, 0x94, 0x02, 0xB0, 0x0E, 0x44, 0x54, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x29, 0x00, 0xAD,
+0x00, 0xB4, 0x02, 0xD0, 0x06, 0x40, 0x23, 0x00, 0xA1, 0x00, 0xD4, 0x01, 0x11,
+0x1F, 0x00, 0x78, 0x00, 0xED, 0x00, 0xA4, 0x03, 0xD0, 0x0E, 0x44, 0x7C, 0x00,
+0x81, 0x00, 0x84, 0x01, 0x50, 0x0B, 0x40, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x21, 0x00, 0x8D, 0x01, 0x34, 0x41, 0xD0,
+0x04, 0x40, 0x03, 0x00, 0x41, 0x00, 0x04, 0x33, 0x90, 0x2C, 0x41, 0x30, 0x20,
+0xCD, 0x0C, 0x04, 0x01, 0xD0, 0x0C, 0x40, 0x32, 0x04, 0xC1, 0x00, 0x54, 0x03,
+0xD0, 0x3C, 0x40, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xA8, 0x25, 0x10, 0xDF, 0x11, 0x7C, 0x8A, 0xF0, 0x8D, 0xC1, 0x27, 0x00,
+0x93, 0x00, 0x5C, 0x05, 0x31, 0x0D, 0xD0, 0x34, 0x01, 0x4F, 0x02, 0x6C, 0x01,
+0xF1, 0x0C, 0xC0, 0xB4, 0x40, 0x93, 0x00, 0x4C, 0xAA, 0x70, 0x29, 0xC0, 0x74,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x37, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x25, 0xC0, 0x37, 0x00, 0x8F, 0x00, 0x7E, 0x01,
+0xF0, 0x0D, 0xC0, 0x37, 0x00, 0xDF, 0x80, 0x7C, 0x09, 0xF0, 0x0D, 0xC0, 0x37,
+0x08, 0xDF, 0x00, 0x7C, 0x02, 0xB0, 0x89, 0xC0, 0x17, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x08, 0x6F, 0x00, 0xAF, 0x00, 0xDC, 0x02,
+0x34, 0x1F, 0x00, 0x6F, 0x00, 0xDF, 0x00, 0xEC, 0x89, 0xF1, 0x0F, 0xC0, 0x3F,
+0x00, 0x7F, 0x00, 0xCC, 0x01, 0x70, 0x4D, 0xD0, 0x3C, 0x00, 0xBF, 0x00, 0xCD,
+0x00, 0x34, 0x0B, 0xC1, 0x07, 0x26, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA1, 0x20, 0x36, 0x10, 0x9D, 0x03, 0x04, 0x02, 0x10, 0x89, 0x43, 0x37,
+0x00, 0xDD, 0x00, 0x44, 0x05, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xDD, 0x03, 0x44,
+0x19, 0x10, 0x0D, 0x42, 0x34, 0x00, 0xCD, 0x02, 0x44, 0x06, 0x10, 0x19, 0x40,
+0x27, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xA6,
+0x01, 0xDD, 0x06, 0x54, 0x02, 0x10, 0x0D, 0x40, 0x27, 0x01, 0x9D, 0x00, 0x60,
+0x03, 0xD0, 0x0D, 0x44, 0x37, 0x00, 0xDD, 0x01, 0x04, 0x85, 0x50, 0x0D, 0x40,
+0x34, 0x10, 0x9D, 0x50, 0x44, 0x06, 0x10, 0x49, 0x40, 0x07, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xCD, 0x00, 0x04,
+0x03, 0x10, 0x04, 0x40, 0x33, 0x00, 0x8D, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40,
+0x33, 0x80, 0xDD, 0xA0, 0x04, 0x03, 0x10, 0x0C, 0x40, 0x30, 0x00, 0x8D, 0xC0,
+0x44, 0x02, 0x10, 0x08, 0x44, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x18, 0x26, 0x00, 0x5F, 0x00, 0x5C, 0x02, 0x30, 0x0D, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x6C, 0x00, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xDF, 0x00,
+0x4C, 0x01, 0x70, 0x09, 0x80, 0x3C, 0x00, 0x1F, 0x00, 0x4C, 0x00, 0x30, 0x09,
+0xC0, 0x07, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8,
+0x1F, 0x00, 0x7F, 0x00, 0xFC, 0x01, 0xF0, 0x0B, 0xC0, 0x1F, 0x00, 0x7F, 0x00,
+0xBC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFD, 0x01, 0xD0, 0x0B,
+0xC0, 0x3F, 0x00, 0x7F, 0x00, 0xBC, 0x02, 0xF0, 0x0A, 0xC4, 0x17, 0x62, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xB3, 0x0C,
+0xDC, 0x00, 0x30, 0x4F, 0xC0, 0x3C, 0x01, 0xF3, 0x18, 0xFC, 0x32, 0x70, 0x17,
+0xC0, 0x7F, 0x00, 0x5B, 0x01, 0x8C, 0x06, 0x32, 0x1A, 0xC2, 0x7E, 0x00, 0x3B,
+0x08, 0xCD, 0x00, 0xB0, 0x03, 0xC2, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x18, 0x37, 0x01, 0x91, 0x8E, 0x44, 0x27, 0x10, 0x3F,
+0x40, 0xBC, 0x40, 0xF5, 0x26, 0x74, 0x38, 0x10, 0x05, 0x44, 0x77, 0x00, 0x53,
+0x01, 0x54, 0x05, 0x52, 0x19, 0x40, 0x55, 0x00, 0x11, 0x06, 0x44, 0x82, 0x10,
+0x01, 0xC0, 0x0E, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0xA0, 0x33, 0x04, 0x81, 0x00, 0x54, 0x03, 0x10, 0x2C, 0x44, 0xB2, 0x05, 0xC1,
+0x00, 0x34, 0x02, 0x50, 0x44, 0x41, 0x31, 0x00, 0x4D, 0x00, 0x54, 0x03, 0x10,
+0x08, 0x40, 0x22, 0x00, 0x89, 0x02, 0x04, 0x21, 0xD0, 0x10, 0x42, 0x4F, 0x80,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x31, 0x00, 0x91,
+0x01, 0x44, 0x07, 0x10, 0x0D, 0x40, 0x36, 0x00, 0xD1, 0x00, 0x74, 0x84, 0x10,
+0x05, 0x41, 0x37, 0x01, 0x51, 0x01, 0x54, 0x09, 0x50, 0x1D, 0x00, 0x35, 0x00,
+0x11, 0x02, 0x44, 0x83, 0x51, 0x11, 0x40, 0x0F, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0x36, 0x00, 0x13, 0x07, 0x10, 0x17, 0x30,
+0x0D, 0xC0, 0x36, 0x08, 0xD3, 0x40, 0x7C, 0x44, 0x50, 0xB1, 0xE0, 0x35, 0x20,
+0x5B, 0x07, 0x5C, 0x0B, 0x30, 0x18, 0x80, 0x36, 0x00, 0x1B, 0x02, 0x4C, 0x28,
+0xF4, 0x19, 0xC0, 0x2B, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0F, 0x80, 0x3D, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF4, 0x0F, 0xC0, 0x39, 0x00,
+0xDF, 0x00, 0x7C, 0x40, 0xF0, 0x13, 0xC0, 0x7F, 0x00, 0x79, 0x10, 0xFC, 0x13,
+0xE0, 0x0F, 0xC0, 0x1F, 0x00, 0x5F, 0x02, 0xBC, 0x04, 0xB0, 0x02, 0xC0, 0x1E,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00,
+0x1F, 0x04, 0x4C, 0x03, 0x70, 0x0C, 0xE1, 0x35, 0x04, 0xD7, 0x08, 0x4C, 0x02,
+0x70, 0x25, 0xC0, 0x37, 0x00, 0x57, 0x02, 0x5C, 0x0B, 0xB0, 0x49, 0xC0, 0x34,
+0x00, 0x5B, 0x00, 0x4C, 0x49, 0x34, 0x09, 0xC0, 0x2B, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA0, 0x34, 0x00, 0x9D, 0x00, 0x44, 0x03,
+0x11, 0x1F, 0xC4, 0xFC, 0x04, 0xF1, 0x00, 0x44, 0x10, 0x10, 0x05, 0x40, 0x70,
+0x00, 0x4B, 0x41, 0x68, 0x2F, 0xB0, 0x2D, 0x40, 0xB0, 0x01, 0x51, 0x00, 0x44,
+0x89, 0x00, 0x19, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x20, 0x32, 0x00, 0x1D, 0x00, 0x34, 0x83, 0x50, 0x1C, 0x40, 0x73,
+0x80, 0xC1, 0x26, 0x64, 0x0E, 0x10, 0x00, 0x48, 0x31, 0x00, 0xC5, 0x03, 0x70,
+0x0F, 0x90, 0x00, 0x48, 0x31, 0x21, 0x59, 0x0F, 0x04, 0x24, 0x10, 0x08, 0x60,
+0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x7A,
+0x80, 0x6D, 0x51, 0x95, 0x47, 0x10, 0x9E, 0x41, 0x70, 0x80, 0xE1, 0x81, 0xA6,
+0x07, 0x14, 0x12, 0x00, 0x78, 0x00, 0x69, 0x05, 0xB4, 0x47, 0x99, 0xDA, 0x40,
+0x5D, 0x00, 0xA1, 0x49, 0x04, 0x26, 0x10, 0x32, 0x41, 0x37, 0x20, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x32, 0x00, 0xCF, 0x20, 0x1C,
+0x03, 0x50, 0x8C, 0x40, 0x33, 0x00, 0xC1, 0x00, 0x2C, 0x13, 0x30, 0x41, 0xC0,
+0x33, 0x24, 0x47, 0x15, 0x3C, 0x03, 0xB0, 0x5C, 0xC8, 0x21, 0x08, 0x8B, 0x05,
+0x0D, 0x08, 0x30, 0x0C, 0xC0, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0xB8, 0x3D, 0x20, 0xFF, 0x00, 0xE8, 0x03, 0xF0, 0xAE, 0xC0,
+0x3F, 0x40, 0xFB, 0x00, 0xDD, 0x03, 0xF1, 0x03, 0xC0, 0x3B, 0x00, 0x45, 0x80,
+0xEC, 0x03, 0xF0, 0x0D, 0xC0, 0x3A, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF4, 0x8F,
+0xC0, 0x0B, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0,
+0x77, 0x20, 0x53, 0x20, 0x7E, 0x83, 0xF0, 0xCD, 0xC0, 0x34, 0x11, 0xDF, 0x44,
+0x5C, 0x01, 0xF0, 0x11, 0xC0, 0x32, 0x00, 0x1B, 0x00, 0x1C, 0x03, 0x70, 0x0D,
+0xC2, 0x36, 0x00, 0xDF, 0x00, 0x4D, 0x03, 0x30, 0x0D, 0xC2, 0x40, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x98, 0x3D, 0x00, 0x61, 0x00,
+0xB4, 0x83, 0x14, 0x0E, 0x40, 0xB8, 0x05, 0xFD, 0x16, 0x84, 0x03, 0xD0, 0x02,
+0x40, 0x38, 0x80, 0x27, 0x40, 0x84, 0x03, 0x11, 0x0E, 0x40, 0x18, 0x00, 0xED,
+0x00, 0x85, 0x03, 0x10, 0x07, 0x40, 0x4C, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0xE1, 0x01, 0xF6, 0x87, 0xD2, 0x4E,
+0x40, 0x7B, 0x00, 0xED, 0x01, 0x94, 0x07, 0xD0, 0x33, 0x40, 0x7B, 0x00, 0x31,
+0x01, 0x94, 0x07, 0x58, 0x1F, 0x41, 0x7A, 0x00, 0xED, 0x01, 0x04, 0x07, 0x54,
+0x1E, 0x40, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x20, 0x33, 0x00, 0xC1, 0x43, 0x36, 0x03, 0x10, 0x0C, 0x40, 0x30, 0x00, 0xDD,
+0x00, 0x44, 0x1F, 0xD0, 0x48, 0x60, 0x21, 0x02, 0x05, 0x01, 0x06, 0x0F, 0x10,
+0x3C, 0x40, 0x72, 0x00, 0xCD, 0x19, 0x04, 0x23, 0x50, 0x2D, 0x40, 0x58, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x17, 0x00, 0x71,
+0x05, 0xFC, 0x49, 0xF0, 0x05, 0xC0, 0x16, 0x00, 0x5F, 0x00, 0xDC, 0x0D, 0xF0,
+0x17, 0xC0, 0x17, 0x00, 0x63, 0x02, 0x9C, 0x6D, 0x70, 0x27, 0xE0, 0x1E, 0x09,
+0x7F, 0x02, 0xCC, 0x25, 0x70, 0x87, 0xC0, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x40, 0x1F, 0x30, 0x7C, 0x10, 0x74,
+0x01, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7E, 0x28, 0xF0, 0x01, 0xC0, 0x06, 0x08,
+0x17, 0x58, 0x7C, 0x00, 0xF0, 0x61, 0xC0, 0x85, 0x00, 0x1E, 0x82, 0x3C, 0x00,
+0x90, 0x21, 0xD0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x30, 0x19, 0xC0, 0x67, 0x01,
+0x9F, 0x01, 0x68, 0x06, 0x32, 0x09, 0xC2, 0x27, 0x00, 0x92, 0x20, 0x5C, 0x06,
+0x70, 0x19, 0xD0, 0x24, 0x00, 0x8A, 0x05, 0x44, 0x02, 0x70, 0x09, 0xC2, 0x40,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00,
+0x9D, 0x11, 0x34, 0x02, 0x10, 0x59, 0x40, 0xE7, 0x00, 0x9D, 0x8B, 0x44, 0x06,
+0x10, 0x09, 0x40, 0x23, 0x00, 0x91, 0x08, 0x44, 0x8A, 0x10, 0x88, 0x40, 0xE4,
+0x20, 0x9D, 0x07, 0x44, 0x0A, 0x50, 0x29, 0x40, 0x04, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x24, 0x00, 0x9D, 0x08, 0x74, 0x12,
+0x50, 0x89, 0x42, 0x27, 0x04, 0x9D, 0x00, 0x74, 0x52, 0x50, 0x09, 0x48, 0x27,
+0x40, 0x9D, 0x90, 0x54, 0xA2, 0x53, 0x0D, 0x61, 0x64, 0x00, 0x98, 0x00, 0x54,
+0x2A, 0x51, 0x39, 0x40, 0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x28, 0x20, 0x00, 0x8D, 0x14, 0x74, 0x52, 0x15, 0x48, 0x41, 0x23,
+0x25, 0xCD, 0x14, 0x14, 0x52, 0x50, 0x08, 0x40, 0x23, 0x00, 0x95, 0x00, 0x04,
+0x02, 0x11, 0x08, 0x60, 0x20, 0x00, 0x8D, 0x08, 0x14, 0x02, 0x50, 0x48, 0x51,
+0x50, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x30, 0x06,
+0x00, 0x1F, 0x04, 0x7C, 0x10, 0x70, 0x41, 0xC8, 0x07, 0x01, 0x1F, 0x04, 0x7C,
+0x10, 0x70, 0x01, 0xC8, 0x07, 0x08, 0x17, 0x00, 0x58, 0x01, 0x72, 0x01, 0xD0,
+0x14, 0x00, 0x0B, 0x16, 0x5C, 0x50, 0x70, 0x41, 0xC0, 0x74, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA8, 0x25, 0x05, 0xBF, 0x34, 0xBC,
+0x02, 0xF6, 0x08, 0xC0, 0x27, 0x05, 0x9F, 0x14, 0xE4, 0x52, 0xB4, 0x4A, 0xC1,
+0x2F, 0x10, 0xAB, 0x00, 0xFC, 0x02, 0xF0, 0x0A, 0xC0, 0x2F, 0x00, 0xBF, 0x04,
+0xED, 0x52, 0xF0, 0x4B, 0xC1, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x27, 0x00, 0xBF, 0x11, 0xBC, 0x02, 0xC4, 0x0B, 0xC0,
+0x6E, 0x01, 0xBF, 0x54, 0xFC, 0x32, 0xF0, 0x09, 0xC8, 0x29, 0x90, 0xB3, 0x00,
+0xAD, 0x02, 0xB0, 0x0B, 0xC0, 0x2C, 0x00, 0xB7, 0x00, 0xCC, 0x12, 0x36, 0x0F,
+0xC0, 0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18,
+0x47, 0x05, 0x1D, 0x87, 0x74, 0x00, 0x10, 0x81, 0x40, 0x07, 0x05, 0x1D, 0x04,
+0x7C, 0x30, 0xD0, 0x05, 0x40, 0x07, 0x80, 0x55, 0x40, 0x44, 0x00, 0x12, 0x05,
+0x54, 0x04, 0x00, 0x11, 0x00, 0x45, 0x28, 0x54, 0x01, 0x40, 0x73, 0x60, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA0, 0x21, 0x00, 0xCD, 0x10,
+0x74, 0x27, 0xC0, 0x0C, 0x40, 0xA3, 0x00, 0x8D, 0x14, 0x34, 0x13, 0xD2, 0x08,
+0x40, 0x27, 0x00, 0x81, 0x00, 0x24, 0x03, 0x90, 0x09, 0x40, 0x24, 0x00, 0x85,
+0x80, 0x04, 0x02, 0x18, 0x08, 0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x20, 0x25, 0x00, 0x9D, 0x02, 0x76, 0x02, 0x10, 0x09,
+0x40, 0x27, 0x00, 0x9D, 0x00, 0x74, 0x02, 0xC2, 0x09, 0x48, 0x27, 0x01, 0x95,
+0x00, 0x44, 0x22, 0x10, 0x09, 0x44, 0xA4, 0x02, 0x91, 0x00, 0x44, 0x22, 0x50,
+0x09, 0x00, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xA8, 0x27, 0x00, 0x9D, 0x01, 0x3C, 0x0A, 0xF0, 0x09, 0xC0, 0x26, 0x08, 0x9F,
+0x40, 0x7A, 0x42, 0xF0, 0xB9, 0xC0, 0x21, 0x80, 0x91, 0x00, 0x2C, 0x02, 0xB0,
+0x19, 0xC0, 0x64, 0x00, 0x97, 0x04, 0x4C, 0x02, 0x30, 0x49, 0xC0, 0x17, 0x28,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x25, 0x20, 0x9F,
+0x04, 0x7C, 0x16, 0xF4, 0x09, 0xC0, 0x27, 0x0C, 0x9F, 0x20, 0x5E, 0x52, 0xF0,
+0x19, 0xC0, 0x27, 0x20, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x89, 0xC1, 0x27, 0x00,
+0x9F, 0x53, 0x7C, 0x02, 0xF0, 0x49, 0xC1, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x05, 0x00, 0x1F, 0x42, 0x7C, 0x00, 0x70,
+0x11, 0xCC, 0x07, 0x00, 0x1B, 0x00, 0x4C, 0x00, 0xF0, 0x21, 0xC0, 0x07, 0x00,
+0x12, 0x30, 0x4C, 0x40, 0x70, 0x01, 0xC0, 0x85, 0x09, 0x0F, 0x8A, 0x5C, 0x00,
+0x34, 0x21, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0xA0, 0x14, 0x00, 0x7D, 0x0A, 0x74, 0x01, 0x10, 0x07, 0x40, 0x9F, 0x00,
+0x71, 0x80, 0xC4, 0x01, 0xD0, 0x05, 0xC0, 0x9F, 0x00, 0x61, 0x41, 0xC5, 0x09,
+0x10, 0x06, 0x42, 0x58, 0x08, 0x7D, 0x21, 0xC4, 0x09, 0x10, 0x07, 0x40, 0x50,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00,
+0xCD, 0x00, 0x34, 0x02, 0xD0, 0x00, 0x48, 0x73, 0x80, 0xC9, 0x11, 0x14, 0x03,
+0xD0, 0x0C, 0x40, 0xB3, 0x06, 0xC1, 0x88, 0x04, 0x03, 0x51, 0x2C, 0x40, 0x31,
+0x02, 0xCD, 0x01, 0x54, 0x43, 0x90, 0x2C, 0x40, 0x53, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, 0x38, 0x01, 0xED, 0x80, 0xF4, 0x03,
+0x14, 0x02, 0x40, 0xFB, 0x00, 0xE1, 0x03, 0x94, 0x03, 0xD0, 0x8E, 0x64, 0x2B,
+0x40, 0xF1, 0x00, 0x84, 0x03, 0x10, 0x0E, 0x44, 0x18, 0x00, 0xAD, 0x00, 0xC4,
+0x03, 0x91, 0x1C, 0x40, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x11, 0x10, 0x78, 0x00, 0xEF, 0x81, 0xB4, 0x07, 0x70, 0x12, 0xCA, 0x7F,
+0x00, 0x4B, 0x01, 0x9D, 0x05, 0xF2, 0x1E, 0xC8, 0x7B, 0x80, 0x62, 0x01, 0x8C,
+0x07, 0x70, 0x1E, 0xE8, 0x69, 0x20, 0xFF, 0x01, 0xDC, 0x85, 0xB0, 0x1E, 0xD0,
+0x47, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA8, 0xB5,
+0x0A, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x01, 0xC0, 0x17, 0x00, 0xDF, 0x00, 0x6C,
+0x03, 0xF0, 0x0D, 0xC0, 0x25, 0x00, 0xCF, 0x00, 0x7C, 0x03, 0xF0, 0x0C, 0x40,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x00, 0x70, 0x09, 0xC2, 0x40, 0x00, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFD, 0x00, 0xFF, 0x01, 0xCC,
+0x87, 0xB0, 0x17, 0x80, 0x5F, 0x00, 0xFF, 0x41, 0xFC, 0x07, 0xF9, 0x9E, 0xC0,
+0x58, 0x00, 0x73, 0x81, 0x8C, 0x86, 0xB0, 0x9E, 0xC0, 0x7D, 0x08, 0xDF, 0x01,
+0xFC, 0x07, 0x34, 0x17, 0xC2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x18, 0x39, 0x00, 0x7D, 0x08, 0x84, 0x23, 0x10, 0x82, 0x40,
+0x1B, 0x00, 0xED, 0x00, 0xB4, 0x01, 0xD0, 0x0E, 0x62, 0x18, 0x01, 0x6B, 0x04,
+0x84, 0x22, 0x10, 0x1C, 0xC0, 0x2A, 0x04, 0x8D, 0x0D, 0xB4, 0x29, 0xB4, 0x07,
+0x40, 0x54, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x39, 0x00, 0xED, 0x00, 0xC4, 0x03, 0x90, 0x02, 0x40, 0x3B, 0x00, 0x6D, 0x00,
+0xB4, 0x01, 0xD0, 0x0F, 0x5A, 0x18, 0x20, 0x71, 0x00, 0xF4, 0x43, 0xD0, 0x4F,
+0x40, 0x2B, 0x00, 0xED, 0x00, 0xB4, 0x01, 0x90, 0x0E, 0x40, 0x00, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x31, 0x80, 0x8D, 0x22,
+0x04, 0x0B, 0x19, 0x08, 0x40, 0x07, 0x00, 0x8D, 0x00, 0x34, 0x08, 0xD1, 0x2C,
+0x40, 0x50, 0x00, 0x49, 0x00, 0x34, 0x4A, 0x51, 0x3C, 0x40, 0xE3, 0x04, 0x0D,
+0x10, 0x34, 0x00, 0x90, 0x28, 0x51, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0xA8, 0x3D, 0x10, 0x1F, 0x01, 0x4C, 0x0B, 0xB0, 0x01,
+0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x1A, 0xF0, 0x2F, 0xC0, 0x30, 0x04, 0xC1,
+0x20, 0x7C, 0x80, 0xF0, 0x0C, 0xCC, 0xA3, 0x00, 0x5D, 0x20, 0x7C, 0x0A, 0x90,
+0x29, 0x48, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x00, 0x37, 0x28, 0x9F, 0x0C, 0x7D, 0x23, 0xF0, 0x01, 0xC0, 0x27, 0x00, 0x1F,
+0x02, 0x7C, 0x4A, 0xF0, 0x0D, 0xC0, 0x27, 0xC0, 0xD7, 0x50, 0x49, 0x0A, 0xA0,
+0xCD, 0x00, 0xA6, 0x00, 0x0F, 0x08, 0x78, 0x12, 0x74, 0x01, 0xC0, 0x07, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x3F, 0x10, 0x2F,
+0x00, 0xEC, 0x47, 0xB0, 0x02, 0xD0, 0x2C, 0x00, 0x33, 0x00, 0xBC, 0x80, 0xB0,
+0x0F, 0xC3, 0x3F, 0x00, 0x7F, 0xC0, 0xEC, 0x80, 0x71, 0x0B, 0xC0, 0x2E, 0x08,
+0x73, 0x00, 0x0D, 0x02, 0x14, 0x0A, 0xD0, 0x11, 0x22, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x85, 0x20, 0x36, 0x00, 0x9D, 0x25, 0x04, 0x27, 0x10,
+0x21, 0x40, 0x64, 0x00, 0x11, 0x05, 0x74, 0x16, 0x12, 0x0D, 0x40, 0x27, 0x10,
+0xD5, 0x01, 0x04, 0x24, 0x10, 0x19, 0x45, 0xE4, 0x01, 0x55, 0x0A, 0x44, 0x06,
+0x54, 0x71, 0x42, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0xA0, 0x34, 0x00, 0x1D, 0x81, 0x64, 0x03, 0x90, 0x05, 0x49, 0xC4, 0x80,
+0x91, 0x01, 0x76, 0x06, 0x90, 0x0D, 0x40, 0xB7, 0x00, 0x55, 0x01, 0x66, 0x8A,
+0x50, 0x1D, 0x60, 0x66, 0x80, 0x55, 0x02, 0x44, 0x06, 0x54, 0x11, 0x40, 0x04,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x30, 0x08,
+0x0D, 0x00, 0x44, 0x03, 0x14, 0x00, 0x40, 0x00, 0x48, 0x81, 0x40, 0x36, 0x02,
+0x10, 0x0C, 0x40, 0x33, 0x00, 0x11, 0x08, 0x44, 0x02, 0x10, 0x4D, 0x60, 0x04,
+0xC0, 0x05, 0x06, 0x04, 0x00, 0x58, 0x00, 0x40, 0x40, 0xA0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x3E, 0x00, 0x1F, 0x00, 0x6C, 0x83,
+0xB0, 0x01, 0xC0, 0x24, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xB0, 0x0D, 0xC8, 0x37,
+0x40, 0x1F, 0x02, 0x6C, 0x02, 0x70, 0xE9, 0xC3, 0x26, 0x80, 0x93, 0x16, 0x4C,
+0x02, 0x70, 0x09, 0xC2, 0x01, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x85, 0xA0, 0x3F, 0x20, 0xBF, 0x00, 0xBC, 0x03, 0xF0, 0x03, 0xC0, 0x2F,
+0x00, 0xBF, 0x40, 0xFC, 0x02, 0xF1, 0x0F, 0xC0, 0x3F, 0x08, 0x2F, 0x00, 0xFC,
+0x02, 0xF0, 0x41, 0xC0, 0x2F, 0x00, 0x3F, 0x04, 0xFC, 0x00, 0xF0, 0x03, 0xC0,
+0x17, 0x22, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F,
+0x00, 0x63, 0x04, 0xCC, 0x32, 0x72, 0x1F, 0xC8, 0x2C, 0x03, 0x72, 0x01, 0xCC,
+0x05, 0x70, 0x0B, 0xC0, 0x3D, 0x00, 0xBB, 0x80, 0xEC, 0x04, 0xD0, 0x9B, 0xD0,
+0x5C, 0x4A, 0xF3, 0x01, 0xCC, 0x12, 0xF1, 0x17, 0xC0, 0x0C, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x7F, 0x00, 0x51, 0x03, 0x44,
+0xB2, 0x12, 0x1F, 0x40, 0x24, 0x13, 0xD1, 0x01, 0x44, 0x07, 0x10, 0x3D, 0x40,
+0xFC, 0x00, 0xB1, 0x03, 0x44, 0x80, 0xD0, 0x45, 0x40, 0x04, 0x01, 0xF1, 0x21,
+0x44, 0x26, 0xD0, 0x1D, 0x40, 0x05, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x11, 0xA0, 0x33, 0x00, 0x55, 0x02, 0x04, 0x12, 0x50, 0x0C, 0x40,
+0x21, 0x01, 0x91, 0x00, 0x16, 0x02, 0x50, 0x88, 0x40, 0x31, 0x02, 0x89, 0x08,
+0x24, 0x00, 0xD8, 0x08, 0x40, 0x30, 0x88, 0xC1, 0x00, 0x14, 0x82, 0xD2, 0x08,
+0x40, 0x44, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA8,
+0x35, 0x00, 0xD5, 0x00, 0x44, 0x82, 0x50, 0x0D, 0x40, 0x25, 0x00, 0xD1, 0x00,
+0x10, 0x22, 0x00, 0x09, 0x40, 0x35, 0x80, 0x95, 0x04, 0x44, 0x06, 0xC0, 0x81,
+0x00, 0x34, 0x04, 0xD1, 0x40, 0x54, 0x12, 0xD0, 0x0C, 0x40, 0x0D, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x33, 0x40, 0xC7, 0x00,
+0x4C, 0x26, 0x71, 0x0D, 0xD0, 0x64, 0x00, 0x83, 0x80, 0x5C, 0x07, 0x70, 0x05,
+0xC0, 0x35, 0x00, 0x9B, 0x00, 0x6C, 0x4C, 0xF0, 0x09, 0xC8, 0x24, 0x00, 0xD3,
+0x00, 0x5C, 0x07, 0xF0, 0x0D, 0xC0, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x10, 0x7B, 0x09, 0xFC, 0x03, 0xB3, 0x0F,
+0xC0, 0x3E, 0x41, 0xBF, 0x00, 0xED, 0x83, 0xF0, 0x9F, 0x82, 0x36, 0x20, 0x9B,
+0x01, 0xFC, 0x00, 0xF0, 0x1F, 0xC0, 0x2F, 0x00, 0xFD, 0x80, 0xEC, 0x02, 0xF2,
+0x8F, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x08, 0x35, 0x12, 0xDF, 0x0A, 0x4D, 0x03, 0xF0, 0x8C, 0xC4, 0x34, 0x00, 0x9F,
+0x00, 0x7C, 0x03, 0xF0, 0x00, 0xC0, 0x73, 0x00, 0x8B, 0x00, 0x5C, 0x08, 0xF0,
+0x09, 0xC0, 0xA7, 0x00, 0xCF, 0x00, 0x7C, 0x42, 0xF2, 0x09, 0xC2, 0x08, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA2, 0x34, 0x00, 0xDD,
+0x80, 0x44, 0x03, 0xD0, 0x0D, 0x40, 0x74, 0x00, 0x9D, 0x00, 0x74, 0x03, 0xD0,
+0x0B, 0x02, 0x3F, 0x00, 0x91, 0x01, 0x44, 0x02, 0xD0, 0x0D, 0x40, 0x67, 0x04,
+0xDD, 0x00, 0x74, 0x02, 0xD2, 0x0D, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32, 0x0C, 0x4C, 0x00, 0x44, 0x03, 0xD0,
+0x0C, 0x51, 0x34, 0x02, 0x4D, 0x00, 0x30, 0x00, 0xD0, 0x08, 0x40, 0x32, 0x00,
+0x81, 0x00, 0x14, 0x00, 0xD0, 0x0D, 0x40, 0x37, 0x00, 0xCD, 0x20, 0x34, 0x2E,
+0xD0, 0x00, 0x50, 0x1C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x04, 0x80, 0x78, 0x00, 0x6D, 0x41, 0x84, 0x46, 0xD0, 0x1E, 0x48, 0x68, 0x00,
+0xED, 0x01, 0xB4, 0x06, 0xD0, 0x1E, 0x42, 0x7B, 0x60, 0xA1, 0x21, 0x84, 0x84,
+0xD0, 0x5E, 0x41, 0x6B, 0x00, 0xEC, 0x81, 0xB4, 0x07, 0xD2, 0x1B, 0x40, 0x18,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00,
+0xCF, 0x00, 0x0C, 0x02, 0xF2, 0x0C, 0xC0, 0x20, 0x00, 0x8F, 0x00, 0x3C, 0x12,
+0xF0, 0x48, 0xC0, 0x33, 0x00, 0x83, 0x10, 0x1C, 0x80, 0xF8, 0x08, 0xE0, 0x33,
+0x00, 0xCF, 0x48, 0x3C, 0x03, 0xF0, 0x09, 0xC0, 0x48, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x7D, 0x00, 0xFF, 0x00, 0xFC, 0x42,
+0xF0, 0x1E, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3F,
+0x00, 0xB7, 0x00, 0xEC, 0x22, 0xF2, 0x4B, 0xC0, 0x3F, 0x00, 0xFE, 0x01, 0xFC,
+0x43, 0xF0, 0x09, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x11, 0xA0, 0x37, 0x00, 0x5F, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x37,
+0x00, 0x9F, 0x00, 0x78, 0x02, 0xF0, 0x85, 0xC0, 0xF0, 0x22, 0xDB, 0x14, 0x74,
+0x00, 0xE0, 0x1C, 0xC0, 0x24, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x09, 0xC0,
+0x57, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0xB9,
+0x00, 0x6D, 0x04, 0xB4, 0x13, 0xD0, 0x4E, 0x40, 0x3B, 0x00, 0xAD, 0x00, 0xB6,
+0x02, 0xD0, 0x4E, 0x50, 0x38, 0x04, 0xA1, 0x00, 0xB4, 0x02, 0xD0, 0x0E, 0x40,
+0x28, 0x00, 0xED, 0x04, 0xB4, 0x03, 0xD0, 0x0A, 0x40, 0x4B, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x89, 0xED, 0x09, 0xB4,
+0x07, 0xD0, 0x9E, 0x40, 0x79, 0x03, 0xAD, 0x01, 0xB4, 0x06, 0xD0, 0x14, 0x62,
+0x78, 0x01, 0xE9, 0x11, 0xB4, 0x04, 0xD0, 0x1F, 0x40, 0x69, 0x88, 0xED, 0x0D,
+0xB4, 0x57, 0xD0, 0x1A, 0x40, 0x0F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0x8D, 0xA0, 0x34, 0x07, 0xD0, 0x0C, 0x40,
+0x73, 0x10, 0x8D, 0x0B, 0x34, 0x2A, 0xD0, 0x2C, 0x40, 0x30, 0x00, 0xC1, 0x01,
+0x34, 0x03, 0xD0, 0xDC, 0x40, 0x21, 0x23, 0xCD, 0x00, 0x34, 0x07, 0xD0, 0x08,
+0x41, 0x4B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8,
+0x11, 0x00, 0x7F, 0x20, 0x7C, 0x11, 0xF0, 0x05, 0xC0, 0x17, 0x24, 0x7F, 0x02,
+0xFC, 0x0D, 0xF0, 0x07, 0xC0, 0x14, 0x00, 0x5B, 0x01, 0xFC, 0x31, 0xF0, 0x07,
+0xD0, 0x9D, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xF0, 0x27, 0xC0, 0x5F, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x87, 0x00, 0x1F, 0x01,
+0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x10, 0x70, 0x40, 0xF0, 0x80,
+0xC0, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF1, 0x01, 0x80, 0x06, 0x28, 0x1F,
+0x80, 0x78, 0x08, 0xF0, 0x01, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x67, 0x00, 0x93, 0x00, 0x7C, 0x26, 0xF0, 0x39,
+0xC0, 0x27, 0x01, 0x9F, 0x00, 0x4D, 0x02, 0x32, 0x09, 0xC3, 0x64, 0x00, 0x8F,
+0x01, 0x4C, 0x02, 0xF1, 0x29, 0xC0, 0x27, 0x01, 0x9F, 0x00, 0x4C, 0x06, 0x30,
+0x09, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x2E, 0x00, 0xB1, 0x03, 0xF4, 0x02, 0xD0, 0x0B, 0x40, 0x6F, 0x00, 0x9D,
+0x00, 0x04, 0x02, 0x10, 0x09, 0x40, 0x24, 0x00, 0x9D, 0x01, 0x44, 0x02, 0xD0,
+0x09, 0x40, 0x67, 0x08, 0xBD, 0x00, 0x84, 0x0E, 0x10, 0x08, 0x40, 0x04, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x02, 0xD1,
+0x08, 0x74, 0x02, 0xD0, 0x09, 0x41, 0x27, 0x00, 0x8D, 0x00, 0x44, 0x02, 0x10,
+0x09, 0x50, 0x24, 0x01, 0x9D, 0x04, 0x44, 0x02, 0xD0, 0x0D, 0x42, 0x27, 0x00,
+0x8D, 0x00, 0x44, 0x1A, 0x10, 0x09, 0x40, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x81, 0x00, 0x34, 0x0A, 0xD0,
+0x08, 0x42, 0xA3, 0x08, 0x8D, 0x02, 0x44, 0x0A, 0x10, 0x68, 0x41, 0x20, 0x05,
+0x8D, 0x14, 0x05, 0x02, 0xD0, 0x28, 0x40, 0xA3, 0x08, 0x8D, 0x02, 0x05, 0x02,
+0x10, 0x29, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1D, 0xB0, 0x56, 0x40, 0x53, 0x01, 0x7C, 0x04, 0xF0, 0x11, 0xC0, 0x47, 0x00,
+0x1F, 0x00, 0x4C, 0x00, 0x34, 0x41, 0xC0, 0x04, 0x01, 0x1F, 0x04, 0x4C, 0x28,
+0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0x01, 0x4C, 0x04, 0x34, 0x01, 0xD0, 0x74,
+0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0xA7, 0x00,
+0xBF, 0x02, 0xFC, 0x0E, 0xF0, 0x29, 0xC0, 0xEF, 0x00, 0xBF, 0x01, 0xFC, 0x06,
+0xF0, 0x1B, 0xC0, 0x27, 0x00, 0xBF, 0x80, 0xFC, 0x06, 0xF0, 0x1B, 0xC0, 0x6F,
+0x08, 0x9F, 0x23, 0xFC, 0x0A, 0xF0, 0x1B, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x6F, 0x00, 0xFB, 0x11, 0xCD, 0x16,
+0xF0, 0x1B, 0xC0, 0x6F, 0x01, 0x93, 0x00, 0x6C, 0x0A, 0x20, 0x59, 0x80, 0x6D,
+0x01, 0xA3, 0x05, 0x0C, 0x02, 0xF0, 0x2B, 0xC8, 0x2B, 0x00, 0x9D, 0x85, 0xCC,
+0x06, 0x30, 0x29, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1C, 0x08, 0x07, 0x00, 0x11, 0x42, 0x44, 0x14, 0xD0, 0x21, 0x40, 0xC7,
+0x03, 0x51, 0x15, 0x64, 0x04, 0x10, 0x30, 0x40, 0x04, 0x00, 0x11, 0x00, 0x54,
+0x00, 0xD0, 0x51, 0x40, 0x57, 0x00, 0x1D, 0x07, 0x44, 0x28, 0x10, 0x11, 0x40,
+0x73, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0xA3,
+0x00, 0x89, 0x00, 0x04, 0x4A, 0xD0, 0x28, 0x42, 0x23, 0x04, 0x81, 0x20, 0x24,
+0x02, 0x10, 0xC8, 0x61, 0xA3, 0x00, 0x81, 0x02, 0x04, 0x02, 0x50, 0x48, 0x60,
+0x33, 0x05, 0x8D, 0x12, 0x14, 0x02, 0xD0, 0x08, 0x40, 0x43, 0x80, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x91, 0x40, 0x44,
+0x02, 0xD0, 0x09, 0x42, 0x27, 0x60, 0x91, 0x08, 0x24, 0x02, 0x10, 0x09, 0x42,
+0x26, 0x00, 0x91, 0x04, 0x54, 0x0A, 0xD0, 0x89, 0x42, 0x27, 0x01, 0x9D, 0x00,
+0x54, 0x06, 0xD0, 0x09, 0x40, 0x63, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0x28, 0x25, 0x00, 0x9B, 0x0E, 0xCC, 0x22, 0xF0, 0x09, 0xC0,
+0x2F, 0x00, 0xB3, 0x03, 0xEC, 0x12, 0x30, 0x1B, 0xC0, 0x27, 0x00, 0x93, 0x00,
+0x4C, 0x06, 0xE0, 0x1B, 0xC0, 0xEF, 0x20, 0xBF, 0x00, 0x5D, 0x02, 0xF0, 0x6B,
+0xC0, 0x17, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00,
+0x25, 0x00, 0x9F, 0x10, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0xA7, 0x00, 0x9F, 0x21,
+0x7C, 0x12, 0xF4, 0x38, 0xD0, 0x21, 0x40, 0x9F, 0x00, 0x7C, 0x0A, 0xF2, 0x09,
+0xC0, 0x67, 0x08, 0x9F, 0x00, 0x2C, 0x82, 0x34, 0x39, 0xC0, 0x53, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x01, 0x01, 0x0F, 0x00,
+0x4D, 0x80, 0x30, 0x81, 0xC0, 0x07, 0x00, 0x1F, 0x02, 0x7C, 0x00, 0xF0, 0x01,
+0xC0, 0x04, 0x10, 0x17, 0x00, 0x4C, 0x08, 0x72, 0x01, 0xD0, 0x04, 0x40, 0x03,
+0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x53, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x20, 0xDC, 0x20, 0x7D, 0x00, 0x44, 0x05, 0x10, 0x07,
+0x40, 0x17, 0x04, 0x5D, 0x00, 0x74, 0x01, 0xD0, 0x05, 0xC0, 0x16, 0x00, 0x41,
+0x11, 0x44, 0x01, 0x10, 0x15, 0x43, 0x14, 0x00, 0x51, 0x00, 0xF0, 0x01, 0xC0,
+0x05, 0x40, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0xA0, 0xE2, 0x00, 0x8D, 0x00, 0x04, 0x07, 0x10, 0x08, 0x42, 0x37, 0x00, 0xCD,
+0x00, 0x30, 0x03, 0xD0, 0x0C, 0x40, 0x32, 0x00, 0x85, 0x01, 0x05, 0x03, 0x50,
+0x0C, 0x40, 0x32, 0x00, 0xC1, 0x80, 0x34, 0x02, 0xC0, 0x0C, 0x40, 0x53, 0x00,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0xB8, 0x00, 0xAD,
+0x00, 0x04, 0x77, 0x14, 0x0E, 0x40, 0x2B, 0x82, 0xED, 0x04, 0xB4, 0x13, 0xD0,
+0x4E, 0x40, 0x2A, 0x00, 0xF5, 0x00, 0xC4, 0x07, 0x50, 0xDE, 0x40, 0x7E, 0x01,
+0xE1, 0x0C, 0xB4, 0x03, 0xD1, 0x4E, 0x40, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x68, 0x00, 0xAF, 0x01, 0x84, 0x06, 0x30,
+0x1A, 0xC0, 0x7B, 0x01, 0xEF, 0x03, 0xBC, 0x0F, 0xF0, 0x5E, 0xC0, 0x6A, 0x00,
+0xE7, 0x01, 0x8C, 0x07, 0x70, 0x1F, 0x80, 0xFA, 0x00, 0xE3, 0x01, 0xBC, 0x06,
+0xF0, 0x3E, 0xC0, 0x53, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xB8, 0x35, 0x00, 0x8F, 0x00, 0x7C, 0x02, 0xC0, 0x0D, 0xC0, 0x27, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xE0, 0x8D, 0xC4, 0x23, 0x00, 0xDB, 0x00, 0x7C, 0x63,
+0xB8, 0x0D, 0xC0, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x43,
+0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x6F, 0x00,
+0xB3, 0x01, 0xFC, 0x87, 0x30, 0x1B, 0x80, 0x7F, 0x02, 0xE3, 0x01, 0x8C, 0x07,
+0x30, 0x1F, 0x40, 0x7C, 0x01, 0xFF, 0x01, 0xEC, 0x07, 0x30, 0x1B, 0xC0, 0x78,
+0x28, 0xF3, 0x21, 0xFC, 0x06, 0x30, 0x1E, 0xC8, 0x08, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x29, 0x40, 0xA1, 0x00, 0xF4, 0x03,
+0x14, 0x0A, 0x40, 0x2B, 0x48, 0xE1, 0x00, 0x84, 0x23, 0x10, 0x8E, 0x40, 0x29,
+0x00, 0xED, 0x00, 0xC4, 0x43, 0xB0, 0x0A, 0xC0, 0x3A, 0x02, 0xE1, 0x00, 0xB4,
+0x0B, 0x10, 0x8E, 0x40, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x21, 0x00, 0xA1, 0x10, 0xB4, 0x02, 0x10, 0x0A, 0x40, 0x3B,
+0x80, 0xF1, 0x01, 0xC4, 0x07, 0x10, 0x1F, 0x40, 0x28, 0x01, 0xCD, 0x00, 0xA4,
+0x03, 0x10, 0x0B, 0x41, 0x3D, 0x00, 0xE1, 0x01, 0xB4, 0x62, 0x14, 0x1F, 0x40,
+0x20, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x13,
+0x00, 0x81, 0x01, 0x34, 0x86, 0x10, 0x0C, 0x40, 0x63, 0x00, 0xC1, 0x07, 0x04,
+0x0B, 0x18, 0x3C, 0x40, 0x21, 0x00, 0xCD, 0x00, 0x04, 0x17, 0x90, 0x3C, 0x43,
+0x67, 0x00, 0xC1, 0x00, 0x34, 0x07, 0x10, 0x1C, 0x40, 0x18, 0x20, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x25, 0x00, 0xD3, 0x03, 0x7C,
+0x13, 0x30, 0x09, 0xC2, 0x77, 0x04, 0xD3, 0x04, 0x45, 0x2B, 0x34, 0x6D, 0xC0,
+0x24, 0x00, 0xDF, 0x11, 0xEC, 0x03, 0x30, 0x3C, 0xC0, 0x65, 0x44, 0xD3, 0x20,
+0x3C, 0x02, 0x30, 0x6D, 0xD0, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x00, 0x37, 0x00, 0xCF, 0x00, 0x7C, 0x03, 0xF0, 0x2D, 0xC0,
+0x27, 0x08, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0xDD, 0x40,
+0x7C, 0x83, 0xF2, 0x0D, 0xC0, 0x26, 0x00, 0xDF, 0x00, 0x7C, 0x0A, 0xF0, 0x4D,
+0xC0, 0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08,
+0x2F, 0x00, 0xBF, 0x10, 0x8C, 0x06, 0x31, 0x0B, 0xD0, 0xB4, 0x00, 0xFF, 0x00,
+0xCC, 0x03, 0xF0, 0x0F, 0xC1, 0xEF, 0x00, 0xFF, 0x85, 0xCC, 0x03, 0x30, 0x4F,
+0xC0, 0xEC, 0x00, 0xF3, 0x00, 0x4C, 0x16, 0x30, 0x0F, 0xC0, 0x04, 0x20, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0xDD, 0x03,
+0x44, 0x02, 0x11, 0x24, 0x40, 0x74, 0x00, 0xDD, 0x40, 0x44, 0x03, 0xD0, 0x0D,
+0x42, 0x67, 0x20, 0xCD, 0x01, 0x44, 0x03, 0x10, 0x19, 0x48, 0x74, 0x20, 0xD1,
+0x00, 0x44, 0x01, 0x00, 0x0D, 0x40, 0x84, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0xA0, 0x26, 0x00, 0xDD, 0x06, 0x44, 0xA3, 0x14, 0x09,
+0x41, 0x34, 0x00, 0xCD, 0x00, 0x64, 0x03, 0xD0, 0x0D, 0x40, 0x27, 0x10, 0xDD,
+0x00, 0x84, 0x03, 0x10, 0x09, 0x40, 0x24, 0x40, 0xC1, 0x00, 0x44, 0x02, 0x10,
+0x0C, 0x40, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x20, 0x00, 0xCD, 0x00, 0x14, 0x02, 0x10, 0x08, 0x40, 0x20, 0x00, 0xCD,
+0x00, 0x05, 0x03, 0xD0, 0x0C, 0x40, 0x23, 0x80, 0xDD, 0x40, 0x04, 0x03, 0x14,
+0x09, 0x50, 0x20, 0x00, 0xC1, 0x40, 0x04, 0x02, 0x16, 0x0C, 0x54, 0x40, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x26, 0x00, 0x1F,
+0x00, 0x4C, 0x03, 0x30, 0x09, 0xCA, 0x24, 0x00, 0xFF, 0x00, 0xEC, 0x03, 0xF0,
+0x0F, 0xC0, 0x27, 0x00, 0xDF, 0x00, 0xCD, 0x03, 0x30, 0x09, 0xC0, 0x24, 0x00,
+0xF3, 0x00, 0x4D, 0x02, 0x30, 0x0F, 0xC0, 0x04, 0x40, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x1F, 0x00, 0x7F, 0x00, 0xED, 0x02, 0xF0,
+0x07, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0E, 0xC0, 0x2F, 0x00,
+0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0A, 0xC0, 0x2F, 0x00, 0xFF, 0x00, 0xFC, 0x01,
+0xF0, 0x0F, 0xC0, 0x17, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA0, 0x7F, 0x00, 0xF7, 0x0C, 0xCC, 0x1B, 0x70, 0x3A, 0xC0, 0xEC, 0x00,
+0xBB, 0x04, 0xFC, 0x03, 0x30, 0x1E, 0xC0, 0x3E, 0x00, 0xA7, 0x01, 0x8C, 0x06,
+0x30, 0x1B, 0xC0, 0x7E, 0x12, 0xBF, 0x04, 0xCC, 0x07, 0xF0, 0x03, 0xC4, 0x0E,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x77, 0x00,
+0xF1, 0x8E, 0xC4, 0x3B, 0x10, 0x49, 0x40, 0x24, 0x00, 0x91, 0x0E, 0xF4, 0x2F,
+0x50, 0x19, 0x40, 0xF4, 0x00, 0x5D, 0x01, 0x44, 0x50, 0x10, 0x19, 0x40, 0x34,
+0x00, 0xC9, 0x14, 0x44, 0x03, 0xD0, 0x19, 0x40, 0x04, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA2, 0x33, 0x20, 0xC5, 0x04, 0x04, 0x13,
+0x50, 0x49, 0x40, 0x30, 0x01, 0x09, 0x10, 0x14, 0x03, 0x12, 0x08, 0x60, 0x32,
+0x02, 0xCD, 0x80, 0x44, 0x10, 0x10, 0x08, 0x40, 0x33, 0x00, 0x8D, 0x0C, 0x04,
+0x03, 0xD0, 0x08, 0x40, 0x47, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0xA8, 0x35, 0x00, 0xD1, 0x00, 0x46, 0x03, 0x10, 0x19, 0x41, 0x70,
+0x00, 0x11, 0x01, 0x74, 0x03, 0x10, 0x19, 0x40, 0x34, 0x00, 0xDD, 0x84, 0x46,
+0x84, 0x10, 0x09, 0x40, 0x35, 0x00, 0x99, 0x00, 0x44, 0x03, 0xD0, 0x19, 0x41,
+0x0D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xA8, 0x36,
+0x08, 0xD7, 0x00, 0x48, 0x03, 0x70, 0x39, 0xC0, 0x44, 0x01, 0x9B, 0x05, 0x5C,
+0x83, 0x30, 0x19, 0xC0, 0x36, 0x80, 0xD7, 0x00, 0x4C, 0x4E, 0x31, 0x08, 0xC0,
+0x37, 0x02, 0x9F, 0x00, 0x4D, 0x07, 0xF0, 0x30, 0xC0, 0x03, 0x20, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x82, 0x3D, 0x10, 0xEF, 0x00, 0xFC,
+0x03, 0xF0, 0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x80, 0xFC, 0x43, 0xF0, 0x0B, 0xC0,
+0x3F, 0xA4, 0xFF, 0x01, 0xFD, 0x03, 0xF0, 0x0F, 0xC2, 0x3E, 0x00, 0xEF, 0x02,
+0xFC, 0x8F, 0xF0, 0x03, 0xC0, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0x70, 0x21, 0xC0,
+0x35, 0x00, 0x97, 0x08, 0x0C, 0x03, 0x70, 0x01, 0xC0, 0x34, 0x02, 0xD7, 0x10,
+0x4C, 0x00, 0xB1, 0x0D, 0xC0, 0x37, 0x04, 0xD3, 0x18, 0x44, 0x03, 0xF0, 0x21,
+0xC0, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x70, 0x00, 0xFD, 0x0F, 0xF4, 0x03, 0xD0, 0x0C, 0x60, 0x34, 0x00, 0x91, 0x03,
+0xC4, 0x4F, 0x30, 0xC0, 0xC0, 0x3C, 0x08, 0xC1, 0x11, 0x2C, 0x00, 0x10, 0x8D,
+0x40, 0xF4, 0x00, 0xD5, 0x00, 0x44, 0x0B, 0xD0, 0xB1, 0x40, 0x4C, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x72, 0x00, 0xCD, 0x03,
+0x74, 0x07, 0x50, 0x08, 0x44, 0x31, 0x00, 0x05, 0x12, 0x14, 0x0B, 0xD0, 0x18,
+0x40, 0xF0, 0x20, 0xC5, 0x00, 0x24, 0x02, 0xD2, 0x00, 0x06, 0xF3, 0x00, 0x89,
+0x01, 0x04, 0x37, 0xD0, 0x90, 0x40, 0x1D, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x82, 0x78, 0x04, 0xED, 0x81, 0xB4, 0x4F, 0xD0, 0x1B,
+0x48, 0x7D, 0x08, 0xE1, 0x09, 0x95, 0x07, 0x00, 0x9B, 0x40, 0x78, 0x00, 0x61,
+0x01, 0xE4, 0x04, 0x10, 0x9A, 0x40, 0x78, 0x06, 0xAD, 0x01, 0x84, 0x07, 0xD9,
+0x1A, 0x48, 0x18, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+0x10, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x03, 0x70, 0x08, 0x40, 0x31, 0x00, 0x57,
+0x00, 0x1C, 0x03, 0xF0, 0x88, 0xC0, 0x30, 0x00, 0xC7, 0x00, 0x2C, 0x00, 0xB0,
+0x00, 0xC0, 0x37, 0x00, 0x8B, 0x0C, 0x0C, 0x03, 0xF0, 0x0C, 0xC0, 0x49, 0x48,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB0, 0x3D, 0x00, 0xFF,
+0x02, 0xFC, 0x4B, 0xF0, 0x8B, 0x80, 0x3A, 0x02, 0xFF, 0x00, 0xAC, 0x63, 0xF1,
+0x8B, 0xD0, 0x3B, 0x00, 0xFF, 0x48, 0xFC, 0x00, 0xF0, 0x0A, 0xC2, 0x3F, 0x00,
+0x97, 0x28, 0xFD, 0x03, 0xF0, 0x8E, 0xC0, 0x09, 0x60, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00, 0xDF, 0x0C, 0x7C, 0x0B, 0xF0,
+0x09, 0xC0, 0x34, 0x00, 0x57, 0x01, 0x4C, 0x1B, 0xF1, 0x09, 0xC0, 0x34, 0x12,
+0xCF, 0x00, 0x4C, 0x03, 0xB0, 0x01, 0xC0, 0x76, 0x90, 0xDB, 0x00, 0x7C, 0x83,
+0x30, 0x05, 0xC0, 0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x88, 0x39, 0x00, 0xED, 0x04, 0xB4, 0x13, 0xD0, 0x0F, 0x44, 0x38, 0x00,
+0xE1, 0x00, 0x84, 0x33, 0xD8, 0x0A, 0x42, 0x38, 0x00, 0xED, 0xA0, 0x84, 0x81,
+0x14, 0x0E, 0x44, 0x39, 0x00, 0xE5, 0x00, 0xB4, 0x03, 0x50, 0x0E, 0x40, 0x48,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x79, 0x00,
+0xED, 0x05, 0xB4, 0x07, 0xD0, 0x1A, 0x54, 0x7C, 0x00, 0x45, 0x01, 0x84, 0x17,
+0xC0, 0x13, 0x48, 0x78, 0x01, 0xEC, 0x01, 0xC5, 0x05, 0x12, 0x16, 0x40, 0x7D,
+0x80, 0xE1, 0xA1, 0xF4, 0x8F, 0x11, 0x1C, 0x60, 0x0C, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x00, 0xCD, 0x00, 0x34, 0x03,
+0xD8, 0x2C, 0x40, 0x30, 0x00, 0xC1, 0x03, 0x04, 0x03, 0xD0, 0x80, 0x40, 0x30,
+0x20, 0xCD, 0x05, 0x04, 0x15, 0x10, 0x0C, 0x40, 0x21, 0x00, 0xC5, 0x08, 0x74,
+0x06, 0x50, 0x2C, 0x41, 0x48, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x17, 0xA8, 0x15, 0x00, 0x5F, 0x00, 0x7C, 0x01, 0xD0, 0x47, 0xC0, 0x98,
+0x00, 0x77, 0x49, 0x4C, 0x01, 0xF0, 0xA7, 0xC8, 0x14, 0x00, 0x7F, 0x07, 0x8C,
+0x15, 0x30, 0x47, 0xC0, 0x55, 0x00, 0x5B, 0x21, 0x7C, 0x01, 0x10, 0x27, 0xD1,
+0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07,
+0x00, 0x1F, 0x82, 0x7C, 0x00, 0xF1, 0x01, 0xC1, 0x07, 0x01, 0x1F, 0xA8, 0x7D,
+0x08, 0xD0, 0x21, 0xD4, 0x87, 0x00, 0x1F, 0x40, 0x7C, 0x00, 0x70, 0x21, 0xC0,
+0x05, 0x02, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x21, 0xC0, 0x4B, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x01, 0x9F, 0x03, 0x3C,
+0x02, 0x30, 0x09, 0xC0, 0x24, 0x08, 0x97, 0x01, 0x7C, 0x12, 0xF2, 0x29, 0xC0,
+0x26, 0x00, 0x9F, 0x08, 0x5C, 0x02, 0x34, 0x09, 0xC0, 0x24, 0x00, 0x8F, 0x09,
+0x4D, 0x02, 0x30, 0x48, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x03, 0x74, 0x0A, 0x10, 0x09, 0x40,
+0x24, 0x00, 0x91, 0x01, 0x74, 0x1A, 0xD0, 0x08, 0x41, 0xE4, 0x01, 0x8D, 0x60,
+0x44, 0x02, 0x12, 0x68, 0x40, 0x24, 0x03, 0x9D, 0x02, 0x44, 0x02, 0x30, 0x29,
+0x50, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0,
+0x24, 0x00, 0x9D, 0x00, 0x74, 0x46, 0x50, 0x08, 0x42, 0x24, 0x00, 0x95, 0x08,
+0x74, 0x82, 0xD0, 0x09, 0x40, 0x27, 0x02, 0x9D, 0x00, 0x54, 0x02, 0x52, 0x0D,
+0x40, 0x24, 0x00, 0x9D, 0x02, 0x44, 0x0A, 0x10, 0x09, 0x40, 0x60, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0xCD, 0x14,
+0x34, 0x52, 0x54, 0x08, 0x40, 0x24, 0x0A, 0xC1, 0x94, 0x30, 0xD2, 0xD0, 0x09,
+0x40, 0x21, 0x00, 0x8D, 0x00, 0x44, 0x02, 0x19, 0x09, 0x70, 0x20, 0x10, 0x8D,
+0x08, 0x04, 0x02, 0x14, 0x4C, 0x41, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1D, 0xB0, 0x07, 0x00, 0x1F, 0x04, 0x7C, 0x10, 0x70, 0x01,
+0xD0, 0x84, 0x00, 0x17, 0x04, 0x78, 0x10, 0xF0, 0x01, 0xC4, 0x07, 0x05, 0x1D,
+0x40, 0x5C, 0x00, 0x30, 0x01, 0xC0, 0x04, 0x00, 0x1F, 0x16, 0x4C, 0x00, 0x30,
+0x41, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+0xB0, 0x27, 0x00, 0x9F, 0x14, 0x7C, 0x52, 0xB1, 0x4B, 0xC1, 0x2B, 0x01, 0xBF,
+0x94, 0x7C, 0x02, 0xF2, 0x0A, 0xC0, 0x26, 0x10, 0xFE, 0x00, 0xBC, 0x53, 0xF0,
+0x0A, 0xC0, 0x2B, 0x15, 0xBF, 0x04, 0xBC, 0x52, 0x70, 0x0B, 0xC0, 0x67, 0x60,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0, 0x2F, 0x00, 0xBF,
+0x01, 0xCC, 0x5E, 0xE0, 0x28, 0xC0, 0xA7, 0x00, 0xB7, 0x09, 0xEC, 0x12, 0x70,
+0x0A, 0xC0, 0x2F, 0x04, 0xAD, 0x00, 0x4C, 0x02, 0x30, 0x0A, 0xC0, 0xAE, 0x00,
+0xBB, 0x00, 0xCD, 0x02, 0xB0, 0x0B, 0xC0, 0x67, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00, 0x1D, 0x0F, 0x44, 0x08, 0xD0,
+0x01, 0x40, 0x07, 0x01, 0x11, 0x0B, 0x44, 0x00, 0x10, 0x01, 0x40, 0x87, 0x00,
+0x19, 0x00, 0x44, 0x10, 0x10, 0x01, 0x40, 0x04, 0x01, 0x11, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x40, 0x73, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0xA0, 0x23, 0x00, 0x8D, 0x10, 0x04, 0x12, 0xD0, 0x48, 0x40, 0x67, 0x00,
+0x85, 0x04, 0x24, 0x0B, 0x50, 0x08, 0x40, 0x33, 0x00, 0x99, 0x00, 0x04, 0x42,
+0x10, 0x09, 0x40, 0x22, 0x01, 0x89, 0x00, 0x24, 0x02, 0x90, 0x08, 0x40, 0x43,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00,
+0x9D, 0x60, 0x44, 0x02, 0xC8, 0x09, 0x41, 0x27, 0x02, 0x91, 0x00, 0x64, 0x02,
+0x10, 0x09, 0x44, 0x27, 0x00, 0x99, 0x00, 0x00, 0x02, 0x11, 0x09, 0x00, 0x64,
+0x00, 0x91, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x63, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x25, 0x00, 0x9F, 0x00, 0x4C, 0x02,
+0xC1, 0x39, 0xC8, 0x67, 0x00, 0x95, 0x51, 0x6C, 0x02, 0x70, 0x79, 0xC0, 0x27,
+0x00, 0x9B, 0x01, 0x4C, 0x0E, 0x30, 0x19, 0xC0, 0x26, 0x00, 0x9B, 0x00, 0x4C,
+0x06, 0xB0, 0x09, 0xC1, 0x17, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0x00, 0x25, 0x00, 0x9F, 0x00, 0x7D, 0x02, 0xF0, 0x29, 0xC0, 0x67,
+0x00, 0x8F, 0x05, 0x1C, 0x02, 0xF0, 0x99, 0xC4, 0x27, 0x24, 0x9B, 0x03, 0x7D,
+0x12, 0xF4, 0x99, 0xC3, 0x27, 0x00, 0x9F, 0x13, 0x7C, 0xD6, 0xF0, 0x49, 0xC1,
+0x53, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x04,
+0x00, 0x0F, 0x04, 0x7C, 0x00, 0xF4, 0x21, 0xC2, 0x04, 0x40, 0x13, 0x00, 0x6C,
+0x40, 0xF0, 0x01, 0xC0, 0x06, 0x00, 0x1F, 0x02, 0x5C, 0x08, 0x31, 0x01, 0xC0,
+0x04, 0x00, 0x1F, 0x00, 0x4C, 0x00, 0x30, 0x01, 0xC0, 0x50, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x20, 0x54, 0x04, 0x7D, 0x00, 0xF4,
+0x61, 0x10, 0x05, 0xC0, 0x12, 0x00, 0x71, 0x07, 0xC4, 0x09, 0xD0, 0x27, 0x40,
+0x1C, 0x00, 0x6D, 0x60, 0x44, 0x01, 0x12, 0x36, 0x41, 0x1C, 0x01, 0x7D, 0x47,
+0xC4, 0x85, 0x50, 0x27, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0xA0, 0x32, 0x80, 0xCD, 0x00, 0x34, 0x0F, 0x10, 0x0C, 0x40,
+0x30, 0x00, 0xC1, 0x07, 0x24, 0x09, 0xD1, 0xC4, 0x40, 0xB3, 0x00, 0x8D, 0x00,
+0x14, 0x03, 0x10, 0x00, 0x48, 0x35, 0x09, 0xDD, 0x03, 0x45, 0xAF, 0x10, 0xAC,
+0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x88,
+0x28, 0x00, 0x6D, 0x82, 0xB4, 0x07, 0x10, 0xDF, 0x40, 0x3A, 0x03, 0xE1, 0x00,
+0x84, 0x03, 0xD0, 0x13, 0x48, 0x39, 0x80, 0x7D, 0x80, 0xD4, 0x13, 0x1C, 0x02,
+0x40, 0x39, 0x10, 0xED, 0x20, 0xC4, 0x03, 0x41, 0x1C, 0x40, 0x10, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x68, 0x00, 0xEF, 0x01,
+0x3C, 0x05, 0x30, 0xDE, 0xC0, 0x7C, 0x00, 0x73, 0x01, 0xAC, 0x07, 0xF0, 0x1E,
+0xC0, 0x5B, 0x00, 0xAF, 0x01, 0x9C, 0x17, 0x30, 0x12, 0xD0, 0x79, 0x90, 0xBF,
+0x01, 0xCC, 0x07, 0x20, 0x1E, 0xC0, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA8, 0x25, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0x31, 0x0D,
+0xC8, 0xB7, 0x05, 0x5F, 0x20, 0x70, 0x03, 0xF1, 0x01, 0xC0, 0x16, 0x00, 0x5F,
+0x80, 0x2C, 0x6B, 0xF0, 0x01, 0xD0, 0x36, 0x00, 0x9F, 0x00, 0x7C, 0x01, 0xF0,
+0x0D, 0xD0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xA0, 0x6F, 0x02, 0xF7, 0x09, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x78, 0x00, 0xFB,
+0x01, 0xFC, 0x07, 0xF0, 0x17, 0xC0, 0x7E, 0x00, 0xBB, 0x01, 0xCC, 0x17, 0xB0,
+0x97, 0xC0, 0x7C, 0x08, 0x7F, 0x01, 0xCC, 0x05, 0xF1, 0x1F, 0xC0, 0x0B, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x29, 0x00, 0x6D,
+0x48, 0xB0, 0x03, 0xD0, 0x4E, 0xC0, 0x3B, 0x01, 0x61, 0x22, 0xB4, 0x8B, 0xD0,
+0x46, 0x40, 0xB8, 0x08, 0x71, 0x00, 0xFC, 0x13, 0x10, 0xC6, 0x40, 0x38, 0x00,
+0x6D, 0x48, 0x84, 0x00, 0xD0, 0x42, 0x40, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x29, 0x20, 0xE5, 0x40, 0xB4, 0x03, 0xD0,
+0x0F, 0x40, 0x3C, 0x10, 0xE9, 0x08, 0xB4, 0x03, 0xD0, 0x07, 0x41, 0x1B, 0x02,
+0xB9, 0x08, 0xA4, 0x73, 0x92, 0x06, 0x41, 0x18, 0x00, 0x2D, 0x00, 0xA4, 0x61,
+0xD0, 0x0E, 0x60, 0x23, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x28, 0x23, 0x00, 0x9D, 0x00, 0x34, 0x02, 0xD0, 0xEC, 0x60, 0xB2, 0x04,
+0x09, 0x01, 0x34, 0x03, 0xD0, 0x10, 0x40, 0x10, 0x00, 0x41, 0x23, 0x36, 0x0F,
+0x12, 0x34, 0x41, 0x20, 0x20, 0x0D, 0x09, 0x60, 0x04, 0xD0, 0x00, 0x40, 0x1B,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xA8, 0x25, 0x00,
+0x97, 0x00, 0x74, 0x02, 0xF0, 0x0F, 0xC0, 0x3C, 0x00, 0x9B, 0x02, 0x7C, 0x03,
+0xF0, 0x05, 0x80, 0x37, 0x00, 0x4B, 0x05, 0xEC, 0x07, 0xB0, 0x34, 0xD0, 0x04,
+0x80, 0xDF, 0x01, 0x6D, 0x06, 0xD0, 0x0D, 0x48, 0x57, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x27, 0x00, 0x1F, 0x00, 0x7C, 0x02,
+0xF0, 0x0D, 0xC0, 0x37, 0x08, 0x97, 0x0E, 0x74, 0x0B, 0xE0, 0x01, 0xA0, 0x36,
+0x10, 0x5F, 0x02, 0x5C, 0x13, 0xF0, 0x05, 0xC0, 0x87, 0x0A, 0xDF, 0x02, 0x5C,
+0x02, 0xF0, 0x0D, 0xC8, 0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x81, 0x08, 0xAF, 0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x0F, 0xC0, 0x3E,
+0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF1, 0x07, 0xC8, 0x17, 0x20, 0x3B, 0x18, 0xCC,
+0x03, 0xB2, 0x07, 0xD0, 0x0E, 0x00, 0xBF, 0x01, 0xFC, 0x02, 0x30, 0x23, 0xC1,
+0x07, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x26,
+0x20, 0x1D, 0x01, 0x44, 0x04, 0xD0, 0x0C, 0xC0, 0x36, 0x00, 0x1D, 0x01, 0x74,
+0x0F, 0xD0, 0x31, 0x42, 0xD7, 0x00, 0x5D, 0x52, 0x04, 0x03, 0x10, 0x35, 0x40,
+0x44, 0x04, 0x1D, 0x03, 0x74, 0x8C, 0x10, 0x21, 0x40, 0x87, 0x02, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x26, 0x80, 0x9D, 0x31, 0x64,
+0x0C, 0xD0, 0x0D, 0x40, 0x36, 0x00, 0x9D, 0x01, 0x74, 0x07, 0x50, 0x15, 0x41,
+0x77, 0x00, 0x5D, 0x00, 0x47, 0x03, 0x90, 0x1D, 0x41, 0x64, 0x00, 0x5D, 0x94,
+0x74, 0x46, 0x10, 0x2D, 0x48, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x20, 0x00, 0x0D, 0x00, 0x04, 0x02, 0xD0, 0x0D, 0x40,
+0x32, 0x00, 0x8D, 0x20, 0x34, 0x83, 0xD0, 0x00, 0x40, 0x23, 0x00, 0x4D, 0x00,
+0x46, 0x03, 0x10, 0x04, 0x40, 0x20, 0x00, 0x8D, 0x00, 0x26, 0x82, 0x1C, 0x00,
+0x40, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+0x24, 0x00, 0x9F, 0x80, 0x6C, 0x00, 0xF1, 0x0F, 0xC0, 0x3E, 0x00, 0x9F, 0x00,
+0x7C, 0x03, 0x70, 0x05, 0xC4, 0x17, 0x00, 0x1B, 0x00, 0xCC, 0x03, 0xB4, 0x05,
+0xC0, 0x04, 0x00, 0x4F, 0x00, 0x7C, 0x02, 0x30, 0x01, 0xC4, 0x07, 0x40, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB0, 0x2F, 0x00, 0xBE, 0x00,
+0xFC, 0x02, 0xF0, 0x0E, 0xC0, 0x3F, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xF0, 0x02,
+0xC0, 0x3F, 0x20, 0x7F, 0x40, 0xFC, 0x03, 0xF0, 0x06, 0xC0, 0x2F, 0x00, 0x3F,
+0x00, 0xFC, 0x00, 0xF2, 0x03, 0xE0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xBF, 0x01, 0xEC, 0x32, 0xF2, 0xC7,
+0xC8, 0x5F, 0x02, 0x33, 0xA1, 0xFC, 0x07, 0x30, 0x6B, 0xC8, 0x3F, 0x08, 0xB3,
+0x00, 0xEC, 0x04, 0x10, 0x1B, 0xC8, 0x1F, 0x03, 0xFD, 0x09, 0xCC, 0x82, 0x32,
+0x1F, 0xC6, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x08, 0x7F, 0x00, 0xDD, 0x81, 0x74, 0x32, 0xD2, 0xC5, 0x40, 0x07, 0x11, 0xD1,
+0x01, 0xF4, 0x07, 0x10, 0x69, 0x48, 0xFF, 0x00, 0x95, 0x03, 0x74, 0x04, 0x10,
+0x1D, 0x40, 0x97, 0x01, 0xED, 0x04, 0x44, 0x0E, 0x10, 0x1F, 0x40, 0x0F, 0x60,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33, 0x00, 0xCD,
+0x00, 0x24, 0x03, 0xD0, 0x44, 0x40, 0x37, 0x01, 0xC5, 0x01, 0x14, 0x83, 0x10,
+0x28, 0x40, 0x33, 0x0A, 0x01, 0x08, 0x74, 0x00, 0x10, 0x0C, 0x40, 0x93, 0x00,
+0xCD, 0x00, 0x14, 0x22, 0x1A, 0x0C, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x88, 0x35, 0x00, 0xDD, 0x01, 0x74, 0x82, 0xD0,
+0x65, 0x40, 0x27, 0x00, 0xD0, 0x01, 0x74, 0x03, 0x50, 0x0D, 0x42, 0x37, 0x08,
+0x95, 0x20, 0x74, 0x04, 0x10, 0x1D, 0x42, 0x37, 0x09, 0xDC, 0x00, 0x54, 0x13,
+0x10, 0x0D, 0x40, 0x0F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xA8, 0x37, 0x00, 0xDF, 0x05, 0x6C, 0x02, 0xF0, 0x05, 0xC0, 0xB3, 0x01,
+0xD7, 0x21, 0x3C, 0x03, 0x34, 0x1D, 0xC0, 0x37, 0x10, 0x93, 0x80, 0x28, 0x0C,
+0x32, 0x1D, 0xC1, 0x57, 0x00, 0xDF, 0x80, 0x5C, 0x86, 0x31, 0x0D, 0xC0, 0x0B,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00,
+0xFE, 0x00, 0xFC, 0x23, 0xF1, 0x0F, 0xC0, 0xBF, 0x40, 0xFF, 0x00, 0xFC, 0x03,
+0xA0, 0x3B, 0xC0, 0x37, 0x04, 0xBF, 0x23, 0xF0, 0x00, 0xF0, 0x0F, 0xC1, 0x1F,
+0x00, 0xFF, 0x00, 0x2C, 0x02, 0xF0, 0x0F, 0xC4, 0x1F, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xD7, 0x00, 0x7C, 0x07,
+0x70, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x80, 0x7C, 0x43, 0x34, 0x0D, 0xC0, 0x33,
+0x42, 0x13, 0x00, 0x4C, 0x00, 0xF0, 0x0D, 0xC0, 0xB7, 0x08, 0xC3, 0x00, 0x4C,
+0x43, 0x70, 0x0D, 0xC1, 0x0B, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0xA0, 0x34, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x40, 0xB4,
+0x08, 0xDA, 0x01, 0x74, 0x07, 0x00, 0x4D, 0x46, 0xBF, 0x00, 0xB1, 0x00, 0x44,
+0x48, 0xD0, 0x2D, 0x40, 0x77, 0x04, 0xD1, 0x00, 0x40, 0x0F, 0x10, 0x3D, 0x40,
+0x6F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x32,
+0x00, 0xC1, 0x00, 0x20, 0x02, 0x10, 0x9C, 0x40, 0x60, 0x26, 0xC5, 0x01, 0x24,
+0x27, 0x10, 0x08, 0x00, 0xF3, 0x00, 0x89, 0x01, 0x35, 0x44, 0xD0, 0x2C, 0x40,
+0x33, 0x00, 0xC5, 0x29, 0x04, 0x2F, 0x90, 0xBC, 0x42, 0x0F, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x00, 0xE1, 0x01, 0xB6,
+0x06, 0x10, 0x14, 0x58, 0x68, 0x10, 0xED, 0x51, 0x34, 0x07, 0x10, 0x1A, 0x42,
+0x7B, 0x10, 0x89, 0x01, 0x94, 0x04, 0xD0, 0x1E, 0x40, 0x5B, 0xC2, 0xE5, 0x03,
+0x84, 0x06, 0x90, 0x1E, 0x40, 0x77, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xC7, 0x00, 0x7E, 0x02, 0x70, 0x04, 0xC0,
+0x20, 0x82, 0xC7, 0x80, 0x2C, 0x13, 0x38, 0x0C, 0xE0, 0x33, 0x00, 0x0B, 0x90,
+0x1C, 0x30, 0xF0, 0x0C, 0xC0, 0xB7, 0xA0, 0xC7, 0x80, 0x0C, 0x03, 0xF0, 0x0C,
+0xC0, 0x4B, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8,
+0x79, 0xC0, 0xFF, 0x00, 0xF4, 0x02, 0xF8, 0x07, 0xC8, 0x2B, 0x08, 0xFB, 0x08,
+0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xB7, 0x10, 0xEC, 0xA0, 0xF0, 0x0F,
+0xC0, 0x3F, 0x00, 0xFB, 0x01, 0x7E, 0x23, 0x70, 0x1D, 0xC1, 0x0B, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00, 0xDF, 0x00,
+0x7C, 0x83, 0xF0, 0x8D, 0x80, 0x27, 0x00, 0xDF, 0x40, 0x7E, 0x83, 0xF0, 0x89,
+0x40, 0x37, 0x03, 0x9F, 0x00, 0x6E, 0x00, 0xF0, 0x0D, 0xC0, 0x17, 0x10, 0xD3,
+0x00, 0x7E, 0x02, 0xF0, 0x0D, 0xC0, 0x40, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x1B, 0xD0, 0x0E,
+0x40, 0x2B, 0x00, 0xED, 0x00, 0xB6, 0x0B, 0xD0, 0x4A, 0x44, 0x3B, 0x02, 0x8D,
+0x04, 0x84, 0x80, 0xD0, 0x0E, 0x40, 0x93, 0x01, 0xE1, 0x04, 0xB4, 0x82, 0xD8,
+0x4C, 0x40, 0x4D, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x00, 0x79, 0x02, 0xED, 0x01, 0x94, 0x07, 0xD0, 0x1E, 0x60, 0x6B, 0x24, 0xED,
+0x01, 0xB4, 0x97, 0xD0, 0x5E, 0x62, 0x7B, 0x18, 0x2D, 0x01, 0xA4, 0xC4, 0xD2,
+0x1E, 0x41, 0xFB, 0x00, 0xE1, 0x0D, 0xB4, 0x2F, 0xD1, 0x1E, 0x40, 0x10, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33, 0x10, 0x4D,
+0x07, 0x74, 0x07, 0xD0, 0x38, 0x49, 0xE3, 0x20, 0xCD, 0x05, 0x34, 0x03, 0xD0,
+0x1C, 0x40, 0x33, 0x80, 0xCD, 0x00, 0x04, 0x0F, 0xD0, 0x74, 0x40, 0x63, 0x40,
+0xC1, 0x00, 0x34, 0x07, 0xD0, 0x0C, 0x40, 0x59, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00, 0x7F, 0x10, 0x7C, 0x41, 0xF0,
+0x17, 0xC0, 0xDF, 0x00, 0x7F, 0x04, 0x3C, 0x01, 0xF0, 0x05, 0xC0, 0x17, 0x00,
+0x7F, 0x11, 0xAC, 0x05, 0xF0, 0x27, 0xC8, 0xDF, 0x08, 0x53, 0x80, 0x7C, 0x01,
+0xF1, 0x04, 0xC0, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x00, 0x87, 0x08, 0x1F, 0x80, 0x78, 0x00, 0xF0, 0x81, 0xC8, 0x87, 0x00,
+0x1C, 0x00, 0x7C, 0x08, 0xF0, 0x81, 0x82, 0x02, 0x00, 0x0F, 0x00, 0x7C, 0x10,
+0xF0, 0x21, 0xC0, 0x03, 0x00, 0x1F, 0x02, 0x74, 0x00, 0xF0, 0x01, 0xC8, 0x4B,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x67, 0x02,
+0x9F, 0x00, 0x7C, 0x06, 0x30, 0x49, 0xC0, 0x67, 0x04, 0x9F, 0xC8, 0x7C, 0x02,
+0x31, 0x19, 0xC0, 0x27, 0x00, 0x93, 0x00, 0x4D, 0x8A, 0x30, 0x49, 0xC0, 0x67,
+0x04, 0x93, 0x08, 0x4C, 0x22, 0x30, 0x09, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0xEE, 0x00, 0x9D, 0x40, 0xF0, 0x06,
+0x10, 0x0B, 0x40, 0xA7, 0x02, 0x9D, 0x01, 0xF4, 0x0A, 0x10, 0x9B, 0x40, 0x27,
+0x01, 0x9B, 0x80, 0x44, 0x06, 0x10, 0x29, 0x44, 0x2F, 0x00, 0xB1, 0x03, 0x84,
+0x02, 0x10, 0x0B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x24, 0x04, 0x9D, 0x80, 0x70, 0x22, 0x10, 0x09, 0x40, 0x27,
+0x00, 0x9D, 0x00, 0x74, 0x42, 0x10, 0x09, 0x40, 0x27, 0x00, 0x91, 0x08, 0x44,
+0x43, 0x14, 0x29, 0x40, 0x27, 0x02, 0x80, 0x00, 0x44, 0xC2, 0x10, 0x09, 0x40,
+0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20,
+0x18, 0x8D, 0x42, 0x34, 0x0A, 0x14, 0x28, 0x44, 0xB3, 0x00, 0x8D, 0x00, 0x36,
+0x02, 0x11, 0x28, 0x40, 0x23, 0x45, 0x89, 0x14, 0x04, 0x02, 0x10, 0x08, 0x40,
+0xA3, 0x00, 0x81, 0x02, 0x04, 0x02, 0x10, 0x08, 0x40, 0x50, 0xA0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x46, 0x00, 0x1F, 0x00, 0x7C,
+0x04, 0x12, 0x11, 0xC2, 0x07, 0x10, 0x1F, 0x00, 0x7C, 0x04, 0x34, 0x11, 0xC0,
+0x07, 0x01, 0x13, 0x04, 0x4C, 0x00, 0x32, 0x01, 0xC0, 0x47, 0x40, 0x53, 0x01,
+0x4C, 0x04, 0x34, 0x11, 0xD0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0xB8, 0xA7, 0x00, 0xBF, 0x01, 0xFC, 0x8E, 0xF0, 0x3B, 0xC0,
+0x7F, 0x20, 0xBE, 0x00, 0x7C, 0x0A, 0xF0, 0x3B, 0xC0, 0x27, 0x00, 0xF7, 0x00,
+0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0xEF, 0x00, 0x9C, 0x23, 0xFD, 0x0A, 0xF0, 0x29,
+0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0,
+0x6B, 0x00, 0x93, 0x82, 0xFC, 0x16, 0xF0, 0x7B, 0xC1, 0x2C, 0x00, 0xB3, 0x00,
+0xFC, 0x06, 0xF0, 0x7B, 0xC1, 0x6C, 0x01, 0xBE, 0x81, 0xCC, 0x02, 0xF0, 0x0B,
+0xD0, 0xEC, 0x01, 0xBF, 0x07, 0xFC, 0x16, 0xF0, 0x1B, 0xC0, 0x60, 0x00, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x87, 0x00, 0x51, 0x05,
+0x74, 0x54, 0xD0, 0x31, 0x40, 0x40, 0x05, 0x11, 0x00, 0x74, 0x00, 0xD1, 0x31,
+0x44, 0x05, 0x00, 0x1D, 0x0A, 0x44, 0x01, 0xD0, 0x01, 0x40, 0x44, 0x20, 0x1D,
+0x03, 0x74, 0x28, 0xD2, 0x01, 0x48, 0x70, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA0, 0xA3, 0x40, 0x85, 0x44, 0x36, 0x0A, 0xD8, 0x49,
+0x40, 0x22, 0x00, 0x81, 0x21, 0x34, 0x0A, 0xD1, 0x48, 0x40, 0xA0, 0x00, 0x8D,
+0xA0, 0x04, 0x02, 0xD1, 0x08, 0x60, 0xA2, 0x11, 0xCD, 0x06, 0x34, 0x82, 0xD0,
+0x28, 0x40, 0x48, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0xA8, 0x25, 0x80, 0x95, 0x01, 0x74, 0x82, 0xD0, 0x19, 0x41, 0x22, 0x40, 0x91,
+0x00, 0x74, 0x03, 0xD0, 0x09, 0x40, 0x25, 0x00, 0x9D, 0x00, 0x44, 0x02, 0xD0,
+0x09, 0x41, 0x26, 0x05, 0x9D, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40, 0x60, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00, 0xB7,
+0x00, 0xFC, 0x06, 0xF2, 0x0A, 0xD0, 0xAE, 0x10, 0x93, 0x0B, 0x7C, 0x02, 0xF0,
+0x0B, 0xC0, 0x24, 0x20, 0x9F, 0x03, 0x4C, 0x8E, 0xF0, 0x08, 0xC0, 0xEE, 0x00,
+0xBF, 0x00, 0x7C, 0x06, 0xF0, 0x08, 0xD0, 0x14, 0x20, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x00, 0x9B, 0x00, 0x7C, 0x0E, 0xF0,
+0x09, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x39, 0xC0, 0x27, 0x0C,
+0x8F, 0x49, 0x7D, 0x12, 0xF1, 0x49, 0xC0, 0x25, 0x00, 0x9F, 0x00, 0x7C, 0x52,
+0xF0, 0x09, 0x81, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x08, 0x01, 0x01, 0x13, 0x02, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x04, 0x00,
+0x1B, 0x08, 0x7C, 0x80, 0xF0, 0x01, 0xC0, 0x04, 0x00, 0x17, 0x88, 0x7C, 0x00,
+0xF1, 0x21, 0xC0, 0x05, 0x00, 0x1B, 0x04, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x43,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xDC, 0x00,
+0x50, 0x00, 0x74, 0x01, 0x10, 0x05, 0x42, 0x5C, 0x02, 0x51, 0x00, 0xF4, 0x05,
+0xD0, 0x15, 0x41, 0x1C, 0x00, 0x51, 0x81, 0xF4, 0x05, 0xD0, 0x07, 0x41, 0x14,
+0x04, 0x71, 0x40, 0xF4, 0x0D, 0xD0, 0x27, 0x40, 0x53, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0xE2, 0x00, 0xC9, 0x00, 0x34, 0x07,
+0x90, 0x9C, 0x40, 0x20, 0x22, 0x89, 0x20, 0x34, 0x06, 0xD0, 0x0D, 0x40, 0xB0,
+0x0A, 0x85, 0x01, 0x34, 0x23, 0xD0, 0x08, 0x43, 0x73, 0x00, 0x89, 0x00, 0x34,
+0x0E, 0xD0, 0xA8, 0x40, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0x80, 0xA8, 0x00, 0xE9, 0x04, 0x34, 0x0E, 0x90, 0xCA, 0x50, 0x38,
+0x01, 0xE1, 0x00, 0xB4, 0x0A, 0xD0, 0x0E, 0x70, 0x48, 0x00, 0xE1, 0x00, 0xB4,
+0x00, 0xD0, 0x02, 0x40, 0x7A, 0x00, 0x61, 0x00, 0xB4, 0x42, 0xD1, 0x0A, 0x60,
+0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x68,
+0x00, 0xEB, 0x07, 0xBC, 0x07, 0xB0, 0x1C, 0xC0, 0xD8, 0x00, 0xEB, 0x01, 0xBC,
+0x06, 0xF0, 0x5F, 0xC0, 0x58, 0x00, 0xE7, 0x01, 0xBC, 0x04, 0xF1, 0x16, 0xC2,
+0x73, 0x00, 0xEB, 0x07, 0xBC, 0x06, 0xF0, 0x1A, 0xC0, 0x47, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x25, 0x40, 0xD7, 0x00, 0x7C,
+0x02, 0x74, 0x09, 0xC0, 0x17, 0x00, 0xDE, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xC0,
+0x03, 0x00, 0xDF, 0x00, 0x7C, 0x00, 0xF0, 0x04, 0xC6, 0x35, 0x02, 0x5F, 0x00,
+0x7C, 0x02, 0xFA, 0x09, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA0, 0x7F, 0x00, 0xF3, 0x01, 0xDC, 0x47, 0x30, 0x1F, 0xC2,
+0x78, 0x00, 0xF3, 0x01, 0xFC, 0x07, 0x30, 0x1B, 0x41, 0x4D, 0x00, 0xF1, 0x09,
+0xCC, 0x06, 0xE0, 0x16, 0xE0, 0x6C, 0x01, 0xE3, 0x01, 0xCC, 0x07, 0x30, 0x9B,
+0xC2, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88,
+0xB9, 0x10, 0xE1, 0x10, 0x84, 0x02, 0x12, 0x0B, 0x41, 0x38, 0x20, 0xE1, 0x00,
+0xB4, 0x02, 0x10, 0x0A, 0x40, 0x08, 0x01, 0xE1, 0x08, 0x84, 0x00, 0xD1, 0x0E,
+0xD0, 0x2C, 0x41, 0x61, 0x00, 0xC4, 0x02, 0x10, 0x8A, 0x40, 0x57, 0x60, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xF9, 0x01,
+0x94, 0x03, 0x14, 0x8E, 0x40, 0x1C, 0x00, 0xE1, 0x00, 0x34, 0x03, 0x90, 0x0A,
+0x40, 0x08, 0x00, 0xF9, 0x00, 0xA4, 0x00, 0xD0, 0x8E, 0x41, 0x28, 0x13, 0xE1,
+0x00, 0xD4, 0x23, 0x90, 0x0A, 0x44, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x04, 0x28, 0x23, 0x00, 0xC9, 0x02, 0x06, 0x06, 0x10, 0x09,
+0x42, 0x10, 0x00, 0xC1, 0x06, 0x34, 0x02, 0x90, 0x08, 0x40, 0x00, 0x00, 0xC9,
+0x01, 0x26, 0x4C, 0xD0, 0x0C, 0x42, 0x20, 0x04, 0x41, 0x00, 0x14, 0x81, 0x90,
+0x08, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA8, 0x25, 0x00, 0xDB, 0x00, 0x5C, 0x03, 0x30, 0x1D, 0xC0, 0x74, 0x48, 0xD3,
+0x13, 0x7C, 0x02, 0xB4, 0x1D, 0xC0, 0x05, 0x00, 0xCB, 0x01, 0x6C, 0x46, 0xF0,
+0x1D, 0xE0, 0x74, 0x00, 0xD3, 0x40, 0x1D, 0x06, 0xB0, 0x0D, 0xC0, 0x57, 0x20,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x40, 0xD7,
+0x00, 0x7C, 0x22, 0xF0, 0x49, 0xD0, 0x37, 0x02, 0xDF, 0x00, 0x7C, 0x0A, 0x70,
+0x8D, 0xD0, 0x07, 0x00, 0xD7, 0x0C, 0x5D, 0x00, 0xF0, 0x05, 0xC9, 0x35, 0x02,
+0x4F, 0x00, 0x64, 0x22, 0x74, 0x29, 0xC0, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x2F, 0x00, 0xFF, 0x10, 0x4C, 0x0B, 0xF0,
+0x0F, 0xC0, 0x5C, 0x00, 0xFF, 0x80, 0xEC, 0x0E, 0xF0, 0x8C, 0xC0, 0x04, 0x00,
+0xFF, 0x08, 0xCC, 0x00, 0xF0, 0x87, 0xC0, 0x7E, 0x20, 0xF3, 0x08, 0xCC, 0x02,
+0x33, 0x2F, 0xC6, 0x13, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x81, 0x00, 0x26, 0x00, 0xDD, 0x00, 0x44, 0x87, 0xD0, 0x19, 0xC0, 0xF6, 0x00,
+0xCD, 0x09, 0x44, 0x00, 0xD2, 0x19, 0x40, 0x44, 0x04, 0xDC, 0x20, 0x6C, 0x04,
+0x90, 0x04, 0x40, 0x21, 0x00, 0xD3, 0x02, 0x44, 0x02, 0x10, 0x19, 0x40, 0x17,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x82,
+0xCD, 0x00, 0x44, 0x03, 0xD0, 0x4D, 0x50, 0xB4, 0x02, 0xDD, 0x00, 0x64, 0x03,
+0xD8, 0x09, 0x40, 0x44, 0x20, 0xDD, 0x00, 0x44, 0x06, 0xD0, 0x05, 0x44, 0x24,
+0x01, 0xD0, 0x10, 0x44, 0x03, 0x10, 0x0D, 0x41, 0x07, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0xCD, 0x00, 0x04, 0x02,
+0xD0, 0x0C, 0x40, 0x12, 0x00, 0xDD, 0x00, 0x04, 0x03, 0xD0, 0x08, 0x40, 0x00,
+0x00, 0xCD, 0x00, 0x26, 0x00, 0x90, 0x0D, 0x40, 0x35, 0x40, 0x41, 0x00, 0x05,
+0x02, 0x1C, 0x04, 0x44, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xB0, 0x16, 0x00, 0xFF, 0x40, 0x4C, 0x02, 0xF0, 0x09, 0x40, 0x14,
+0x20, 0xDF, 0x00, 0x6C, 0x03, 0xD0, 0x0D, 0xC4, 0x04, 0x08, 0xDF, 0x00, 0x4C,
+0x00, 0xF0, 0x0D, 0xC0, 0x26, 0x10, 0x53, 0x00, 0x4C, 0x03, 0x30, 0x0D, 0xC2,
+0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x1F,
+0x00, 0xEF, 0x00, 0xFC, 0x02, 0xF0, 0x0B, 0xC0, 0x1D, 0x00, 0xFF, 0x00, 0xFC,
+0x01, 0xF0, 0x0B, 0xD0, 0x0F, 0x00, 0xEF, 0x00, 0xFC, 0x00, 0xF0, 0x0F, 0xC0,
+0x2F, 0x00, 0x77, 0x40, 0xFC, 0x01, 0xF0, 0x07, 0xC0, 0x17, 0x22, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x7F, 0x00, 0xEF, 0x09, 0xDC,
+0x06, 0xF2, 0x1F, 0xC0, 0x7D, 0x00, 0xE3, 0x01, 0xDC, 0x12, 0x30, 0x13, 0xC0,
+0x4E, 0x10, 0xB3, 0x00, 0xDC, 0x32, 0x70, 0x2B, 0xC0, 0xBC, 0x00, 0xB3, 0x20,
+0xFC, 0x10, 0x30, 0x02, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0x18, 0x77, 0x00, 0xDD, 0x04, 0x44, 0x06, 0x10, 0x1D, 0x40,
+0x74, 0x00, 0xD1, 0x01, 0x44, 0x0E, 0x10, 0x11, 0x40, 0x74, 0x00, 0x51, 0x43,
+0x44, 0xB2, 0x10, 0xA1, 0x40, 0xBC, 0x03, 0x11, 0x32, 0x74, 0x26, 0x50, 0x11,
+0x40, 0x0C, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0,
+0x33, 0x00, 0xCD, 0x04, 0x14, 0x03, 0x58, 0x0C, 0x40, 0x27, 0x00, 0xD5, 0x00,
+0x17, 0x08, 0x10, 0x01, 0x60, 0x06, 0x08, 0x81, 0x28, 0x16, 0x12, 0xD8, 0x40,
+0x40, 0x30, 0x00, 0x05, 0x86, 0x34, 0x00, 0x18, 0x08, 0x60, 0x4E, 0x80, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x35, 0x00, 0xDD, 0x04,
+0x54, 0x07, 0x10, 0x0D, 0x46, 0x26, 0x00, 0xD5, 0x11, 0x44, 0x0C, 0x12, 0x11,
+0x40, 0x74, 0x00, 0x91, 0x01, 0x44, 0x46, 0x18, 0x10, 0x40, 0x36, 0x00, 0x15,
+0x01, 0x74, 0x43, 0x52, 0x19, 0x41, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x08, 0xDF, 0x00, 0x1E, 0x06, 0x70, 0xD5,
+0xC0, 0xD3, 0x00, 0xC7, 0x03, 0x5C, 0x0C, 0x30, 0x30, 0xC4, 0x52, 0x04, 0x92,
+0x07, 0x5D, 0x04, 0x70, 0x39, 0xC0, 0x34, 0x00, 0x97, 0x61, 0x7C, 0x8D, 0x30,
+0x39, 0xC0, 0x2A, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0x80, 0x3D, 0x30, 0xFF, 0x01, 0xEC, 0x02, 0xF0, 0x0F, 0xC0, 0x7D, 0x02, 0xFB,
+0x00, 0xFC, 0x02, 0xF0, 0x03, 0xC0, 0x1F, 0x00, 0x6F, 0x20, 0xBC, 0x00, 0xF0,
+0x03, 0xD0, 0x3D, 0x00, 0x3B, 0x20, 0xFC, 0x24, 0xF1, 0x0B, 0xC0, 0x1F, 0x00,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x35, 0x00, 0xDF,
+0x00, 0x5C, 0x03, 0xB0, 0x49, 0xC0, 0xA5, 0x00, 0xDB, 0x02, 0x4C, 0x00, 0xF0,
+0x21, 0xC0, 0x17, 0x02, 0xD7, 0x05, 0x6C, 0x02, 0xF1, 0x09, 0xC0, 0x37, 0x44,
+0x93, 0x02, 0x6C, 0x0B, 0xF0, 0x29, 0xC4, 0x2B, 0x20, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0xDD, 0x4D, 0x40, 0x0F, 0x15,
+0x38, 0x40, 0x24, 0x10, 0x91, 0x00, 0x2C, 0x44, 0xD1, 0xB1, 0x44, 0x54, 0x10,
+0xD1, 0x01, 0x74, 0xB2, 0xD2, 0x01, 0x4A, 0xFF, 0x00, 0x90, 0x30, 0x34, 0x83,
+0xD1, 0x08, 0x40, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0xA0, 0x32, 0x00, 0xDD, 0x00, 0x14, 0x26, 0x10, 0x9C, 0x48, 0x31, 0x00,
+0xCC, 0x08, 0x25, 0x02, 0xD0, 0x10, 0x40, 0x11, 0x00, 0x85, 0x02, 0x34, 0x00,
+0xD0, 0x08, 0x42, 0x36, 0x00, 0x85, 0x25, 0x24, 0x00, 0xD0, 0xB0, 0x41, 0x0D,
+0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x7A, 0x00,
+0xFD, 0x01, 0xC4, 0x1E, 0x18, 0x9F, 0x40, 0x7C, 0x10, 0xF5, 0x41, 0xB4, 0x07,
+0xD0, 0x12, 0x00, 0x58, 0x00, 0xA0, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x00, 0x73,
+0x04, 0xE5, 0x01, 0xB4, 0x04, 0xD1, 0x16, 0x00, 0x34, 0x20, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF, 0x00, 0x1C, 0x02,
+0x30, 0x8C, 0xC0, 0xB1, 0x00, 0xCF, 0x00, 0x2C, 0x03, 0xF0, 0xE0, 0xC3, 0x11,
+0x00, 0x87, 0x00, 0x28, 0x01, 0xF0, 0x04, 0xC0, 0x32, 0x30, 0x47, 0x00, 0x2C,
+0x03, 0xF0, 0x00, 0xC0, 0x49, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xA0, 0x3D, 0x00, 0xFF, 0x00, 0xBC, 0x12, 0x70, 0x8E, 0xC0, 0x3B,
+0x02, 0xFB, 0x88, 0xEC, 0x23, 0xF0, 0x82, 0xC0, 0x19, 0x00, 0xBB, 0x00, 0xFC,
+0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x20, 0x7B, 0x40, 0xFC, 0x23, 0xF0, 0x8F, 0xC0,
+0x09, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x37,
+0x00, 0x9F, 0x00, 0x3C, 0x06, 0x70, 0x0D, 0xE0, 0x35, 0x00, 0xDF, 0x00, 0x44,
+0x01, 0xB2, 0x05, 0xC2, 0x13, 0x00, 0xCB, 0x00, 0x6C, 0x05, 0x72, 0x0D, 0xC2,
+0xB7, 0x03, 0xDD, 0x00, 0x6C, 0x00, 0xF0, 0x15, 0x80, 0x40, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x98, 0x39, 0x10, 0xEC, 0x00, 0xB4,
+0x82, 0x10, 0x0E, 0x52, 0x38, 0x00, 0x6D, 0x00, 0x94, 0x03, 0x90, 0x06, 0x40,
+0x1B, 0x00, 0xE1, 0x00, 0xC5, 0x01, 0x10, 0x0E, 0x48, 0x3B, 0x05, 0xED, 0x00,
+0x84, 0x00, 0x90, 0x0E, 0x40, 0x4C, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x00, 0x79, 0x20, 0xAC, 0x91, 0xB4, 0x06, 0xD0, 0x1F, 0x48,
+0x79, 0x20, 0xFD, 0x01, 0xB4, 0x47, 0x90, 0x1E, 0x60, 0x5B, 0x00, 0xE9, 0x01,
+0xA4, 0x07, 0x50, 0x1E, 0x41, 0x7B, 0x00, 0xCD, 0x03, 0xB4, 0x07, 0xD8, 0x14,
+0x64, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x20,
+0x33, 0x00, 0xCD, 0x01, 0x34, 0x40, 0xD0, 0x5C, 0x40, 0x31, 0x00, 0xCD, 0x05,
+0x34, 0x03, 0x98, 0x24, 0x40, 0x93, 0x08, 0xC1, 0x08, 0x04, 0x03, 0x10, 0x2C,
+0x41, 0x33, 0x88, 0xDD, 0x00, 0x14, 0x1F, 0x90, 0x2C, 0x40, 0x58, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x17, 0x00, 0x5F, 0x01,
+0xFC, 0x09, 0xF0, 0x07, 0x40, 0x1D, 0x00, 0x7F, 0x01, 0xFC, 0x01, 0xB0, 0x77,
+0xC0, 0x5B, 0x00, 0x6B, 0x01, 0xEC, 0x29, 0x70, 0x07, 0xC0, 0x17, 0x00, 0x7F,
+0x08, 0xFC, 0x01, 0xF0, 0x47, 0x40, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x00, 0x1F, 0xC2, 0x7C, 0x00, 0x00, 0xA1,
+0x80, 0x06, 0x01, 0x1C, 0x08, 0x58, 0x00, 0xC3, 0x01, 0x88, 0x07, 0x02, 0x1F,
+0x42, 0x7C, 0x20, 0xF0, 0x01, 0xC0, 0x87, 0x20, 0x1F, 0x40, 0x60, 0x20, 0xB0,
+0x01, 0xD0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x25, 0x00, 0x9F, 0x03, 0x7C, 0x12, 0xF9, 0x09, 0xC8, 0x25, 0x00, 0x9F,
+0x04, 0x1C, 0x56, 0x31, 0x89, 0xC3, 0x27, 0x04, 0x97, 0x05, 0x40, 0x06, 0xF0,
+0x09, 0xC0, 0x27, 0x01, 0x9F, 0x00, 0x4C, 0x82, 0xF3, 0x39, 0xC1, 0x43, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D,
+0x03, 0x74, 0x0A, 0xD8, 0x48, 0x40, 0x24, 0x10, 0x8D, 0x00, 0x44, 0x06, 0x14,
+0x19, 0x44, 0xE7, 0x81, 0x9B, 0x12, 0x44, 0x0E, 0xD0, 0x09, 0x40, 0x67, 0x20,
+0x9D, 0x0E, 0x44, 0x02, 0x78, 0x39, 0x40, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x0B, 0x98,
+0x09, 0x40, 0x25, 0x00, 0x9D, 0x02, 0x56, 0x02, 0x50, 0x09, 0x48, 0x67, 0x00,
+0x95, 0x00, 0x54, 0x1A, 0xD0, 0x0D, 0x60, 0x27, 0x00, 0xDD, 0x00, 0x44, 0x02,
+0x50, 0x29, 0x40, 0x73, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x14, 0x28, 0x20, 0x00, 0xCD, 0x00, 0x34, 0x02, 0xD0, 0x09, 0x40, 0x20, 0x00,
+0x8D, 0x80, 0x14, 0xD2, 0x50, 0x0C, 0x40, 0x23, 0x00, 0x81, 0x00, 0x10, 0x52,
+0xD0, 0x48, 0x61, 0x33, 0x0D, 0x8D, 0x14, 0x14, 0x02, 0x50, 0x48, 0x41, 0x53,
+0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x30, 0x04, 0x00,
+0x1F, 0x00, 0x7C, 0x00, 0x90, 0x01, 0xC0, 0x05, 0x00, 0x1F, 0x80, 0x5C, 0x10,
+0x70, 0x01, 0xC0, 0x07, 0x20, 0x14, 0x14, 0x4D, 0x10, 0xF0, 0x41, 0xC0, 0x07,
+0x01, 0x1F, 0x04, 0x4D, 0x50, 0x70, 0x41, 0xE2, 0x77, 0xC0, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0, 0x27, 0x00, 0xBF, 0x94, 0xFC, 0x02,
+0xC0, 0x0E, 0x40, 0x3F, 0x00, 0xAF, 0x80, 0xEC, 0x02, 0xB0, 0x0B, 0xC0, 0x2F,
+0x00, 0xBF, 0x00, 0xEC, 0x52, 0xF0, 0x4B, 0x41, 0x27, 0x05, 0xBF, 0x14, 0xEC,
+0x02, 0x70, 0x0B, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA0, 0x27, 0x00, 0xBF, 0x08, 0xFC, 0x02, 0x79, 0x0A, 0xC0, 0x25,
+0x00, 0xBF, 0x00, 0xCC, 0x06, 0xB1, 0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xDD,
+0x12, 0xF0, 0x99, 0xC0, 0x6D, 0x03, 0xB9, 0x0D, 0xF8, 0x02, 0x30, 0x0B, 0xC8,
+0x60, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x18, 0x07,
+0x00, 0x1D, 0x41, 0x74, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x1D, 0x00, 0x44,
+0x28, 0x10, 0x01, 0x40, 0x07, 0x00, 0x1D, 0x40, 0x44, 0x10, 0xD0, 0xB1, 0x40,
+0xC4, 0x03, 0x11, 0x0F, 0x74, 0x00, 0x10, 0x01, 0x50, 0x70, 0x60, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x23, 0x00, 0x8D, 0x04, 0x74,
+0x02, 0xD4, 0x08, 0x40, 0x21, 0x20, 0x9D, 0x00, 0x17, 0x02, 0x90, 0x08, 0x40,
+0x23, 0x00, 0x9D, 0x00, 0x36, 0x62, 0xD0, 0x48, 0x40, 0x23, 0x00, 0x89, 0x00,
+0x34, 0x02, 0x14, 0x08, 0x48, 0x49, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0xA0, 0x25, 0x00, 0x9D, 0x80, 0x74, 0x42, 0x12, 0x09, 0x44,
+0x24, 0x00, 0x9D, 0x40, 0x52, 0x46, 0x00, 0x09, 0x41, 0x27, 0x00, 0x9D, 0x00,
+0x74, 0x8E, 0xD0, 0x09, 0x61, 0x24, 0x00, 0x91, 0x10, 0x74, 0x02, 0x10, 0x09,
+0x40, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8,
+0x26, 0x00, 0x9D, 0x00, 0x78, 0x0A, 0xF2, 0x08, 0xC0, 0x25, 0x80, 0x9F, 0x04,
+0x5C, 0x0A, 0xB2, 0x09, 0xC2, 0x27, 0x08, 0x9F, 0x19, 0x7C, 0x02, 0xF0, 0x39,
+0xC0, 0x25, 0x20, 0x9A, 0x03, 0x7E, 0x16, 0x20, 0x09, 0xE5, 0x15, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x25, 0x00, 0x9F, 0x00,
+0x7C, 0x12, 0xF0, 0x29, 0xC0, 0xA6, 0x00, 0x9F, 0x28, 0x2C, 0x02, 0xF0, 0x09,
+0xC0, 0x27, 0x00, 0x9F, 0x90, 0x4C, 0x02, 0xF0, 0x48, 0xC4, 0x27, 0x00, 0x9F,
+0x89, 0x7E, 0x22, 0xF2, 0x08, 0xE0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x05, 0x00, 0x1F, 0x04, 0x7C, 0x18, 0xB2, 0x41,
+0xC0, 0x04, 0x20, 0x1F, 0x06, 0x4C, 0x28, 0xF2, 0x61, 0xC0, 0x05, 0x02, 0x1F,
+0x02, 0x6C, 0x08, 0xB0, 0x21, 0xC2, 0x07, 0x00, 0x1F, 0x12, 0x1C, 0x08, 0x30,
+0x21, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0xA0, 0x14, 0x00, 0x7D, 0x11, 0xB0, 0x0D, 0x10, 0x17, 0x58, 0x14, 0x00, 0x6D,
+0x03, 0x45, 0x05, 0xD0, 0x17, 0x44, 0x9F, 0x02, 0x6D, 0x00, 0xC0, 0x01, 0x10,
+0x05, 0x40, 0x9F, 0x02, 0x7D, 0x80, 0x44, 0x01, 0x10, 0x27, 0x00, 0x50, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD,
+0x00, 0x34, 0x8A, 0x90, 0xAC, 0x04, 0x30, 0x00, 0x45, 0x02, 0x12, 0x06, 0xD1,
+0x2C, 0x40, 0x91, 0x00, 0xCD, 0x22, 0x24, 0x17, 0x90, 0x0C, 0x40, 0x37, 0xA2,
+0xCD, 0x08, 0x16, 0xA7, 0x10, 0x4C, 0x50, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x38, 0x00, 0x6D, 0x00, 0xF4, 0x0A, 0x10,
+0x0E, 0x40, 0x38, 0x00, 0x6D, 0x10, 0xB4, 0x03, 0xD0, 0x0E, 0x61, 0x1B, 0x80,
+0xFD, 0x30, 0xA0, 0x47, 0x90, 0x4E, 0x40, 0x3B, 0xA0, 0x6D, 0x01, 0x84, 0x03,
+0x50, 0x2C, 0x40, 0x04, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0x10, 0x78, 0x00, 0xEF, 0x01, 0xBC, 0x06, 0xB0, 0x1E, 0xC0, 0x78, 0x20,
+0x6F, 0x01, 0x9C, 0x07, 0xF0, 0x1E, 0xE0, 0x59, 0x00, 0xEF, 0x01, 0xE8, 0x07,
+0xB0, 0xBE, 0xC0, 0x7B, 0x20, 0xFF, 0x21, 0x1C, 0x07, 0x34, 0x1E, 0xC0, 0x44,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00,
+0xDF, 0x00, 0x3C, 0x02, 0xF0, 0x0D, 0xC0, 0x37, 0x10, 0x4F, 0x00, 0x4D, 0x83,
+0xF0, 0x0D, 0xE0, 0x17, 0x00, 0xCF, 0x00, 0x5C, 0x03, 0x70, 0x6D, 0xC4, 0x17,
+0x08, 0x5E, 0x40, 0x7C, 0x03, 0xB0, 0x09, 0xC0, 0x43, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7D, 0x00, 0xFF, 0x01, 0xFC, 0x07,
+0x30, 0x17, 0xC0, 0x7D, 0x00, 0x7F, 0x01, 0xDC, 0x27, 0xF1, 0x9F, 0xC0, 0x5F,
+0x00, 0xEF, 0x01, 0xEC, 0x85, 0xB0, 0x9F, 0x00, 0x5F, 0x02, 0xF3, 0x4D, 0xC8,
+0x07, 0x20, 0x1F, 0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0x18, 0x39, 0x00, 0x6D, 0x42, 0xB4, 0x12, 0x10, 0x0E, 0x40, 0x38,
+0x00, 0x29, 0x44, 0x80, 0x03, 0xD0, 0x0E, 0x40, 0x1B, 0x00, 0x6D, 0x02, 0x94,
+0x01, 0xD0, 0x0E, 0x43, 0x1A, 0x00, 0xE1, 0x18, 0x84, 0x53, 0x10, 0x07, 0x41,
+0x55, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
+0x00, 0xED, 0x00, 0xF4, 0x02, 0x18, 0x2E, 0x50, 0xB9, 0x00, 0x6D, 0xB2, 0x80,
+0x43, 0xD0, 0x0E, 0x42, 0x1B, 0x04, 0xED, 0x18, 0x95, 0x01, 0x90, 0x0E, 0x42,
+0x3A, 0x30, 0xE1, 0x44, 0xB5, 0x03, 0x1C, 0x0F, 0x40, 0x00, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x30, 0x00, 0x8D, 0x00, 0x34,
+0x0A, 0x18, 0x0C, 0x58, 0x31, 0x08, 0x49, 0x01, 0x04, 0x07, 0xD0, 0x08, 0x40,
+0xD3, 0x00, 0x4D, 0x03, 0x04, 0x9C, 0xD0, 0x1D, 0x48, 0x02, 0x80, 0x91, 0x01,
+0x34, 0x13, 0x10, 0x30, 0x00, 0x11, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0xA8, 0x35, 0x00, 0x9F, 0x00, 0x74, 0x0B, 0x30, 0x2D, 0xC0,
+0x31, 0x00, 0xCF, 0x02, 0x4D, 0x23, 0xF2, 0x0D, 0xC0, 0xD7, 0x00, 0xCF, 0x09,
+0x5C, 0x1A, 0xB0, 0x3F, 0x40, 0x26, 0x20, 0x91, 0x02, 0x7C, 0x02, 0x30, 0x2D,
+0xC0, 0x54, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+0x37, 0x00, 0x1F, 0x01, 0x7C, 0x43, 0xF0, 0x0D, 0x40, 0x36, 0x00, 0xDB, 0x02,
+0x7C, 0x03, 0xF0, 0x6D, 0xC4, 0x17, 0x01, 0xDF, 0x00, 0x74, 0x00, 0xD0, 0x0D,
+0xC1, 0x26, 0x00, 0x1F, 0x02, 0x4C, 0x02, 0xF1, 0x4D, 0xC0, 0x07, 0x00, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x3F, 0x08, 0x3F, 0x00,
+0xFC, 0x02, 0xF0, 0x0F, 0xC0, 0x3D, 0x08, 0x77, 0x00, 0xCC, 0x03, 0xE0, 0x9F,
+0xD0, 0x1C, 0x00, 0xF9, 0x00, 0x8D, 0x02, 0xB0, 0x0F, 0xC0, 0x24, 0x00, 0x9F,
+0x10, 0x48, 0x82, 0xD0, 0x07, 0xC0, 0x13, 0x22, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x85, 0x20, 0x36, 0x00, 0x1D, 0x03, 0x74, 0x86, 0xD2, 0x3C,
+0x41, 0x34, 0x00, 0x51, 0x21, 0x44, 0x03, 0xD0, 0x5C, 0x40, 0x54, 0x08, 0xDD,
+0x43, 0x44, 0x4E, 0x10, 0x0D, 0x40, 0x64, 0x00, 0x1D, 0x07, 0x6C, 0xA2, 0xD2,
+0x01, 0x40, 0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0xA0, 0x34, 0x00, 0x9D, 0x01, 0x74, 0x07, 0xD0, 0x1D, 0x40, 0x35, 0x00, 0x55,
+0x03, 0x45, 0x07, 0xD2, 0x0D, 0x42, 0x55, 0x04, 0x9D, 0x81, 0x54, 0x06, 0x90,
+0x0D, 0x50, 0xC4, 0x00, 0x1D, 0x01, 0x54, 0x03, 0xD0, 0x89, 0x41, 0x07, 0x08,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x30, 0x00, 0x0D,
+0x00, 0x34, 0x07, 0xD0, 0x09, 0x40, 0x34, 0x00, 0x51, 0x00, 0x04, 0x03, 0xD0,
+0x04, 0x40, 0x10, 0x00, 0x4D, 0x00, 0x04, 0x00, 0x18, 0x0C, 0x40, 0x00, 0x00,
+0x1D, 0x00, 0x36, 0x83, 0xD0, 0x00, 0x40, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xB1, 0x36, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0,
+0x0D, 0xC0, 0x35, 0x00, 0x57, 0x00, 0x48, 0x03, 0xF0, 0x0D, 0x40, 0x34, 0x10,
+0x5B, 0x00, 0x48, 0x02, 0xB0, 0x0F, 0xC0, 0x24, 0x00, 0x9F, 0x00, 0x5C, 0x03,
+0xF0, 0x01, 0xC8, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xA0, 0x3F, 0x00, 0xBF, 0x00, 0xB4, 0x00, 0xF0, 0x0A, 0xC0, 0x3F, 0x20,
+0x6F, 0x00, 0xFC, 0x03, 0xE0, 0x0F, 0xC0, 0x2F, 0x00, 0x7E, 0x00, 0xFC, 0x02,
+0xF0, 0x0F, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xEC, 0x03, 0xF0, 0x03, 0xC0, 0x17,
+0x21, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x7F, 0x00,
+0xEF, 0x09, 0xCC, 0x27, 0xF2, 0x1F, 0xC0, 0x7C, 0x00, 0xFF, 0x01, 0xBC, 0x27,
+0xF0, 0x3F, 0xC0, 0x7F, 0x00, 0xEE, 0x09, 0xCC, 0x07, 0x31, 0x1E, 0xC0, 0x7C,
+0x00, 0xF3, 0x09, 0xFC, 0x07, 0x30, 0x1F, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x47, 0x10, 0x1D, 0x44, 0x44, 0x10,
+0xD0, 0x11, 0x40, 0x44, 0x00, 0x1D, 0x01, 0x74, 0x00, 0xD2, 0x01, 0x48, 0x47,
+0x00, 0x1D, 0x44, 0x44, 0x04, 0x50, 0x11, 0x40, 0x44, 0x00, 0x11, 0x84, 0x74,
+0x04, 0x14, 0x11, 0x40, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x11, 0xA0, 0x33, 0x00, 0xDD, 0x00, 0x14, 0x03, 0xD0, 0x0D, 0x40, 0x30,
+0x08, 0xCC, 0x80, 0x36, 0x13, 0xD0, 0x4C, 0x40, 0x33, 0x00, 0xCD, 0x00, 0x04,
+0x03, 0x11, 0x0C, 0x40, 0x30, 0x00, 0xC1, 0x80, 0x74, 0x03, 0x18, 0x0C, 0x40,
+0x44, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x05,
+0x00, 0x1D, 0x00, 0x54, 0x80, 0xD0, 0x01, 0x40, 0x04, 0x18, 0x1D, 0x00, 0x74,
+0x00, 0xD0, 0x01, 0x40, 0x07, 0x00, 0x0D, 0x00, 0x45, 0x00, 0x50, 0x01, 0x40,
+0x04, 0x00, 0x11, 0x60, 0x76, 0x00, 0x10, 0x01, 0x40, 0x0C, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x37, 0x00, 0xDF, 0x20, 0x5C,
+0x03, 0xF2, 0x0D, 0xD0, 0x34, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0,
+0x37, 0x00, 0xDF, 0x00, 0x4C, 0x83, 0x30, 0x0C, 0xC0, 0x30, 0x00, 0xD3, 0x00,
+0x3C, 0x83, 0x31, 0x0D, 0xC0, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x80, 0x0D, 0x00, 0x3F, 0x00, 0xEC, 0x00, 0xF0, 0x03, 0xC0,
+0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x00, 0xF2, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0xB0,
+0xFC, 0x00, 0xF2, 0x03, 0xD0, 0x0F, 0x00, 0x3F, 0x80, 0xFC, 0x00, 0xF0, 0x03,
+0xD1, 0x1F, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+0x35, 0x00, 0xDF, 0x01, 0x4C, 0x03, 0x30, 0x0D, 0xC0, 0x34, 0x00, 0xD3, 0x80,
+0x4C, 0x23, 0x34, 0x8D, 0xC0, 0x74, 0x00, 0xDF, 0x00, 0x4C, 0x03, 0x30, 0x0D,
+0xC0, 0x34, 0x01, 0xD3, 0x00, 0x4C, 0x83, 0xF0, 0x0D, 0xC0, 0x0B, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x04, 0x00, 0x0D, 0x00,
+0x40, 0x40, 0x10, 0x10, 0x50, 0x04, 0x00, 0x1A, 0x05, 0x44, 0x00, 0x10, 0x11,
+0xC0, 0x86, 0x00, 0x1D, 0x03, 0x04, 0x04, 0x10, 0x11, 0x40, 0x85, 0x08, 0x11,
+0x11, 0x6E, 0x2C, 0xD0, 0x30, 0x40, 0x4F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x07, 0xA8, 0x72, 0x02, 0xCD, 0x00, 0x06, 0x07, 0x00, 0x9C,
+0x40, 0x70, 0x80, 0xC1, 0x01, 0x20, 0x87, 0x10, 0x0C, 0x42, 0x30, 0x04, 0xCD,
+0x20, 0x04, 0x23, 0x1A, 0x1C, 0x40, 0x30, 0x00, 0xC1, 0x81, 0x24, 0x07, 0xD0,
+0x3C, 0x40, 0x1F, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x80, 0x48, 0x02, 0x3D, 0x01, 0x84, 0x04, 0x10, 0x92, 0x40, 0x48, 0x00, 0x39,
+0x01, 0xE4, 0x04, 0x10, 0x33, 0x40, 0x4A, 0x20, 0x2D, 0x91, 0x85, 0x14, 0x18,
+0x13, 0x41, 0x49, 0x00, 0x21, 0x01, 0xA4, 0x44, 0xD0, 0x12, 0x41, 0x1B, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF,
+0x80, 0x44, 0x23, 0x34, 0x0C, 0xC0, 0x30, 0x26, 0xC3, 0x00, 0x2D, 0x23, 0x30,
+0x0C, 0x40, 0x30, 0x20, 0xCF, 0x44, 0x0E, 0x03, 0x34, 0x0C, 0xC0, 0x30, 0x40,
+0xD3, 0x08, 0x25, 0x03, 0xF0, 0x0C, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x0D, 0x08, 0x3F, 0x80, 0xFD, 0x00, 0xF0,
+0x02, 0xC0, 0x0B, 0x80, 0x2F, 0x00, 0xDC, 0x20, 0xF0, 0x82, 0xE0, 0x0F, 0x02,
+0x3F, 0x00, 0xBC, 0x10, 0xF0, 0x03, 0xC0, 0x0B, 0x00, 0x3F, 0x00, 0x5E, 0x00,
+0xF0, 0x13, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0xA0, 0x33, 0x00, 0xD7, 0x00, 0x7C, 0x83, 0xF0, 0x1D, 0xC0, 0x34, 0x00,
+0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x00, 0xD3, 0x00, 0x1C, 0x03,
+0x30, 0x0D, 0xC0, 0x33, 0x00, 0xD3, 0x00, 0x7E, 0x03, 0xF0, 0x1D, 0xC0, 0x54,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x09, 0x20,
+0x21, 0x20, 0xB4, 0x00, 0xD0, 0x02, 0x40, 0x08, 0x10, 0x2D, 0x40, 0xB4, 0x00,
+0xD0, 0x02, 0x40, 0x0B, 0x00, 0x21, 0x00, 0x84, 0x00, 0x52, 0x02, 0x40, 0x0B,
+0x00, 0x21, 0x00, 0xB6, 0x00, 0xD1, 0x02, 0x40, 0x48, 0x60, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x79, 0x00, 0xE5, 0xC1, 0xB4, 0x07,
+0xD8, 0x1F, 0x40, 0x78, 0x00, 0xED, 0x01, 0xB4, 0x07, 0xD0, 0x1E, 0x4A, 0x7B,
+0x88, 0xE1, 0x01, 0x94, 0x07, 0x94, 0x1E, 0x40, 0x7F, 0x00, 0xE9, 0x01, 0xB4,
+0x87, 0xD2, 0x1E, 0x52, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x28, 0x03, 0x00, 0x01, 0x00, 0x34, 0x00, 0xD9, 0x00, 0x56, 0x00,
+0x08, 0x0D, 0x80, 0x76, 0x00, 0xD0, 0x00, 0x44, 0x03, 0x00, 0x01, 0x40, 0x04,
+0x00, 0xD0, 0x00, 0x48, 0x03, 0x08, 0x09, 0x00, 0x34, 0x00, 0xD0, 0x00, 0x40,
+0x48, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x11,
+0x00, 0x57, 0x00, 0x3C, 0x01, 0xF0, 0x05, 0xC0, 0x10, 0x00, 0x5F, 0x00, 0x7C,
+0x01, 0xF0, 0x04, 0xC0, 0x17, 0x40, 0x43, 0x00, 0x1C, 0x01, 0xB4, 0x05, 0xC0,
+0x17, 0x00, 0x5B, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC0, 0x5C, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x0F, 0x00, 0x3F, 0x00, 0xFC,
+0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xF4, 0x00, 0xF0, 0x03, 0xC4,
+0x8F, 0x00, 0x3F, 0x00, 0xFD, 0x08, 0x70, 0x23, 0xC0, 0x8F, 0x40, 0x37, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x93, 0x09, 0x7C, 0x26, 0x30, 0x19, 0xC0,
+0x67, 0x00, 0x93, 0x08, 0x7C, 0x0A, 0x31, 0x19, 0xC8, 0x66, 0x02, 0x9F, 0x80,
+0x6C, 0x02, 0x34, 0x09, 0xC0, 0x67, 0x40, 0x92, 0x05, 0x7C, 0x02, 0xF0, 0x09,
+0xC0, 0x43, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20,
+0x26, 0x00, 0x91, 0x01, 0x74, 0x02, 0x51, 0x19, 0x40, 0x27, 0x00, 0x91, 0x01,
+0x74, 0x02, 0x10, 0x89, 0x40, 0x64, 0x01, 0x9D, 0x00, 0x44, 0x12, 0x10, 0x39,
+0x48, 0x23, 0x02, 0x91, 0x01, 0x74, 0x0E, 0xD0, 0x09, 0x40, 0x07, 0x00, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x01, 0xB1, 0x80,
+0xF4, 0x02, 0x10, 0x8B, 0x40, 0x2F, 0x01, 0xB1, 0x00, 0xF4, 0x02, 0x10, 0x0B,
+0x40, 0x2E, 0x20, 0xBD, 0x00, 0xC4, 0x02, 0x10, 0x8B, 0x40, 0x2F, 0x80, 0xB5,
+0x00, 0xF4, 0x52, 0xD0, 0x0B, 0x40, 0x63, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x20, 0x2C, 0x00, 0xA1, 0x02, 0xF4, 0x0A, 0x50, 0x0A,
+0x40, 0x2F, 0x00, 0xA1, 0x00, 0xB4, 0x0A, 0x04, 0x1A, 0x40, 0x2A, 0x00, 0xBD,
+0x00, 0x85, 0x02, 0x18, 0x0E, 0x40, 0x2B, 0x00, 0xA5, 0x02, 0xB4, 0x02, 0xD0,
+0x0A, 0x40, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D,
+0xB0, 0x06, 0x00, 0x13, 0x00, 0x7C, 0x00, 0x30, 0x01, 0xC8, 0x07, 0x40, 0x13,
+0x00, 0x7C, 0x00, 0x30, 0x01, 0xC0, 0x06, 0x00, 0x0F, 0x40, 0x4C, 0x00, 0x32,
+0x01, 0xC2, 0x17, 0x40, 0x17, 0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC0, 0x77, 0xC0,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x27, 0x40, 0x9F,
+0x01, 0x7C, 0x86, 0xF0, 0x08, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x06, 0xF2,
+0x49, 0x41, 0x25, 0x20, 0x9F, 0x14, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00,
+0x9B, 0x01, 0x7C, 0x02, 0xF0, 0x08, 0xC0, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F, 0x00, 0xBF, 0x00, 0xCC, 0x02, 0xF0,
+0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0x30, 0x0A, 0xC0, 0x2B, 0x20,
+0xAF, 0x42, 0x8D, 0x02, 0x30, 0x0B, 0xC0, 0x28, 0x00, 0xB3, 0x02, 0xCC, 0x02,
+0xF0, 0x0A, 0xC0, 0x64, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1C, 0x08, 0x07, 0x00, 0x1D, 0x15, 0x44, 0x54, 0xD0, 0x01, 0x48, 0x07, 0x00,
+0x1D, 0x00, 0x74, 0x14, 0x10, 0x51, 0x41, 0x07, 0x00, 0x1D, 0x81, 0x44, 0x00,
+0x50, 0x01, 0x48, 0x04, 0x10, 0x15, 0x01, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x71,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00,
+0x8D, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x48, 0x23, 0x00, 0x8D, 0x00, 0x34, 0x42,
+0x10, 0x08, 0x40, 0x23, 0xA0, 0x8D, 0x00, 0x44, 0x03, 0x10, 0x08, 0x52, 0x20,
+0x00, 0xD1, 0x04, 0x04, 0x02, 0xD0, 0x09, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x00, 0x44, 0x02,
+0xD0, 0x09, 0x40, 0x27, 0x10, 0x9D, 0x00, 0x74, 0x02, 0x14, 0x09, 0x44, 0x27,
+0x00, 0x8D, 0x00, 0x44, 0x82, 0x50, 0x09, 0x46, 0x24, 0x00, 0x95, 0x00, 0x44,
+0x02, 0xD0, 0x09, 0x40, 0x61, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x05, 0x28, 0x25, 0x00, 0xBF, 0x00, 0xCD, 0x82, 0xF0, 0x09, 0xC0, 0x27,
+0x00, 0x9F, 0x00, 0xFC, 0x02, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x4C,
+0x02, 0x30, 0x09, 0xC0, 0x20, 0x08, 0xA3, 0x00, 0x4D, 0x02, 0xF0, 0x09, 0xC0,
+0x14, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x25,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC2, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x82, 0xF0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x53, 0x00, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x02, 0x1F, 0x00, 0x4C,
+0x00, 0xF0, 0x01, 0xC0, 0x07, 0x02, 0x1F, 0x00, 0x7C, 0x00, 0x70, 0x01, 0xD0,
+0x04, 0x40, 0x13, 0x00, 0x4C, 0x10, 0x30, 0x01, 0xC0, 0x07, 0x40, 0x13, 0x00,
+0x7C, 0x04, 0x30, 0x01, 0xC1, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x20, 0x14, 0x00, 0x5D, 0x20, 0x44, 0x01, 0xD1, 0x05, 0x40,
+0x17, 0x10, 0x5D, 0x01, 0x70, 0x01, 0xD0, 0x07, 0x40, 0xDC, 0x00, 0x71, 0x81,
+0x94, 0x01, 0x50, 0x16, 0x41, 0x1F, 0x00, 0x51, 0x00, 0xF4, 0x05, 0x11, 0x26,
+0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0,
+0x62, 0x00, 0xDD, 0x08, 0x04, 0x07, 0xD0, 0x88, 0x48, 0x33, 0x00, 0x8D, 0x80,
+0x74, 0x03, 0x50, 0x04, 0x40, 0xA0, 0x06, 0xC9, 0x11, 0x06, 0x01, 0x10, 0x4C,
+0x48, 0x33, 0x0C, 0xC1, 0x80, 0x34, 0x05, 0x90, 0x18, 0x44, 0x50, 0x00, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x38, 0x00, 0xED, 0x08,
+0x84, 0x53, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xED, 0x10, 0xB4, 0x43, 0xD0, 0x1F,
+0x40, 0x5C, 0x20, 0xF9, 0x50, 0xD4, 0x80, 0x50, 0x0A, 0x40, 0x1F, 0x20, 0xE1,
+0x08, 0xF4, 0x47, 0x91, 0x2B, 0x40, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x10, 0x78, 0x00, 0xFF, 0x05, 0x8C, 0x07, 0xF0, 0x1E,
+0xC0, 0x7B, 0x00, 0xEF, 0x01, 0xBC, 0x87, 0x70, 0x1E, 0xC0, 0x48, 0x00, 0xEB,
+0x01, 0x8C, 0x07, 0x30, 0x12, 0xC0, 0x7B, 0x00, 0xA3, 0x81, 0xBC, 0x07, 0xB4,
+0x1A, 0xC0, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xB8, 0x35, 0x10, 0xDF, 0x00, 0x7C, 0x23, 0xF1, 0x0D, 0xC0, 0x37, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x0F, 0xC0, 0x06, 0x00, 0xD7, 0x00, 0x78, 0x02, 0xF0,
+0x01, 0xC0, 0x37, 0x00, 0x9D, 0x00, 0x3C, 0x03, 0x70, 0x09, 0xC0, 0x43, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x7F, 0x00, 0xBF,
+0x00, 0xFC, 0x06, 0x30, 0x9F, 0xC0, 0x7F, 0x00, 0xE3, 0x01, 0x8C, 0x47, 0x30,
+0x17, 0xC0, 0x4F, 0x00, 0x3F, 0x01, 0x9C, 0x04, 0x70, 0x16, 0xC4, 0x5C, 0x00,
+0xEF, 0x01, 0xCC, 0x07, 0xF0, 0x1B, 0xC2, 0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x15, 0x98, 0x39, 0x04, 0xAD, 0x0C, 0xB4, 0x02, 0x11,
+0x8E, 0x40, 0x3B, 0x10, 0xE1, 0x00, 0x84, 0x23, 0x10, 0x0E, 0x40, 0x0B, 0x10,
+0x6D, 0x0A, 0x85, 0x60, 0x55, 0x86, 0xC0, 0x9A, 0x10, 0xED, 0x00, 0x84, 0x03,
+0xD0, 0x0A, 0x44, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x39, 0x00, 0xAD, 0x08, 0xF4, 0x02, 0x10, 0x8E, 0x40, 0x3F, 0x04,
+0xE1, 0x10, 0xE4, 0x03, 0x10, 0x0E, 0x41, 0x0B, 0x00, 0x2D, 0x10, 0x94, 0x00,
+0xD0, 0x07, 0x41, 0x3A, 0x00, 0xBD, 0x0A, 0xA4, 0x03, 0xD0, 0x0A, 0x41, 0x23,
+0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x33, 0x00,
+0x8D, 0x03, 0x74, 0x0A, 0x10, 0x5C, 0x40, 0xE3, 0x00, 0xC1, 0x41, 0x24, 0x0E,
+0x10, 0x1D, 0x40, 0x83, 0x02, 0x5D, 0x03, 0x04, 0x04, 0xD0, 0x14, 0x40, 0x72,
+0x10, 0x9D, 0x01, 0x24, 0x0B, 0xD1, 0x18, 0x40, 0x1B, 0x20, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x00, 0xDF, 0x89, 0x7C, 0x03,
+0x30, 0x2D, 0xC0, 0x77, 0x40, 0xD3, 0x01, 0x6C, 0x46, 0x34, 0x19, 0xC0, 0x83,
+0x00, 0x5F, 0x41, 0x1C, 0x08, 0xF0, 0xB1, 0xC0, 0x76, 0x04, 0xDF, 0x11, 0x2C,
+0x02, 0xF0, 0x1D, 0xC2, 0x77, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x37, 0x00, 0xDF, 0x08, 0x78, 0x17, 0xF0, 0x8D, 0xC0, 0x37,
+0x00, 0xDF, 0x10, 0x5C, 0x02, 0xF0, 0x0D, 0xC1, 0x07, 0x04, 0xDF, 0x00, 0x7C,
+0x48, 0x60, 0x01, 0xC4, 0x37, 0x00, 0xDF, 0x00, 0x5C, 0x0F, 0xF0, 0x2D, 0xC1,
+0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F,
+0x06, 0xF3, 0x04, 0xFC, 0x0B, 0x30, 0x9F, 0xC8, 0x3F, 0x04, 0xFF, 0x80, 0xCC,
+0x56, 0xF0, 0x0F, 0xD0, 0x0C, 0x00, 0x73, 0x10, 0xCC, 0x00, 0xB0, 0x03, 0xC0,
+0x2F, 0x04, 0xB2, 0x03, 0xC8, 0x43, 0x30, 0x0F, 0xC0, 0x07, 0x24, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x72, 0x40, 0x91, 0x01, 0x74,
+0x06, 0x10, 0x1D, 0x44, 0x37, 0x08, 0xCD, 0x40, 0x44, 0x06, 0xD0, 0x3D, 0x40,
+0x44, 0x30, 0xDF, 0xC0, 0x45, 0x04, 0x10, 0x71, 0x44, 0x63, 0x10, 0xD1, 0x01,
+0x44, 0x17, 0xB0, 0x0D, 0x40, 0x27, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0xA0, 0x36, 0x00, 0x91, 0x80, 0x74, 0x02, 0x10, 0x0D, 0x40,
+0x37, 0x00, 0xDD, 0x04, 0x44, 0x02, 0xD0, 0x19, 0x41, 0x46, 0x00, 0x11, 0x00,
+0x44, 0x0C, 0x9A, 0x15, 0x42, 0x77, 0x00, 0xD5, 0x00, 0x77, 0x07, 0x00, 0x49,
+0x41, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x34, 0x00, 0x81, 0x00, 0x34, 0x02, 0x14, 0x0C, 0x40, 0x33, 0x00, 0xDD, 0x00,
+0x06, 0x03, 0xD0, 0x0C, 0x40, 0x44, 0x28, 0x45, 0x00, 0x04, 0x00, 0x10, 0x04,
+0x40, 0x33, 0x60, 0x85, 0x00, 0x34, 0x03, 0x90, 0x04, 0x40, 0x43, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0xD3, 0x00,
+0x7C, 0x03, 0x10, 0x0D, 0xC0, 0x37, 0x20, 0xDF, 0x00, 0x4D, 0x02, 0xF0, 0x0D,
+0xC0, 0x04, 0x00, 0x01, 0x80, 0x4C, 0x00, 0xB4, 0x05, 0xC0, 0x27, 0x00, 0x97,
+0x00, 0x7C, 0x03, 0x30, 0x09, 0xC0, 0x07, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0xBF, 0x00, 0xBC, 0x02, 0xF1, 0x0F,
+0xC0, 0x2B, 0x10, 0xFF, 0x00, 0xFC, 0x02, 0xF0, 0x0F, 0x80, 0x0F, 0x20, 0x7F,
+0x00, 0xFD, 0x00, 0xF0, 0x07, 0xC0, 0x2F, 0x00, 0xBB, 0x40, 0xCC, 0x83, 0xF0,
+0x07, 0xC4, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0xA0, 0x7F, 0x00, 0xEF, 0x01, 0x8C, 0x07, 0x70, 0x1B, 0xD0, 0x28, 0x01, 0xA7,
+0x01, 0xFC, 0x32, 0x30, 0x1A, 0xC0, 0x3C, 0x00, 0xB3, 0x14, 0xEC, 0x12, 0x30,
+0x8B, 0xC0, 0x3D, 0x0C, 0xBF, 0x08, 0xCC, 0x02, 0xF1, 0x0F, 0xC0, 0x0F, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x77, 0x00, 0x9D,
+0x01, 0x44, 0x06, 0x10, 0x11, 0x42, 0x64, 0x00, 0x51, 0x01, 0x44, 0x0A, 0x10,
+0x19, 0x40, 0xFC, 0x12, 0x91, 0x02, 0x44, 0x3A, 0x10, 0x49, 0x40, 0xBC, 0x00,
+0x9D, 0x00, 0x44, 0x2A, 0xD0, 0x0D, 0x44, 0x0F, 0x60, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x31, 0x00, 0xDD, 0x00, 0x44, 0x85, 0x50,
+0x04, 0x48, 0x00, 0x82, 0xD5, 0x00, 0x14, 0x18, 0x50, 0x09, 0x40, 0x32, 0x00,
+0x85, 0x00, 0x34, 0x40, 0x50, 0x88, 0x42, 0x31, 0x24, 0x09, 0x06, 0x04, 0x00,
+0xD0, 0x0C, 0x40, 0x4F, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0xA0, 0x37, 0x00, 0xDD, 0x11, 0x45, 0x05, 0x10, 0x11, 0x44, 0x44, 0x00,
+0xD1, 0x03, 0x04, 0x8C, 0x11, 0x89, 0x40, 0x36, 0x80, 0x94, 0x41, 0x14, 0x04,
+0x50, 0x19, 0x40, 0x34, 0x00, 0x0D, 0x11, 0x44, 0x0C, 0xD0, 0x0D, 0x20, 0x0F,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x37, 0x00,
+0xCF, 0x01, 0x0C, 0x04, 0x70, 0x10, 0x40, 0x44, 0x20, 0xC7, 0x03, 0x5C, 0x0E,
+0x70, 0x40, 0xD0, 0x32, 0x08, 0x17, 0xA3, 0x7C, 0x96, 0x71, 0x11, 0xC0, 0x35,
+0x10, 0x1F, 0x03, 0x4E, 0x0E, 0xF8, 0x0D, 0xC0, 0x0B, 0x20, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x3D, 0x00, 0xFF, 0x80, 0xFC, 0x00,
+0xF0, 0x03, 0xC0, 0x2B, 0x00, 0x7F, 0x00, 0x7C, 0x02, 0xF2, 0x0B, 0xC0, 0x3D,
+0x60, 0x9B, 0x00, 0xEC, 0x02, 0xB0, 0x00, 0xC0, 0x3F, 0x00, 0xBF, 0xA0, 0xFF,
+0x02, 0xF0, 0x0D, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x2A, 0x08, 0x35, 0x00, 0xDF, 0x03, 0x4C, 0x01, 0x30, 0x05, 0xC0, 0x07,
+0x24, 0xD3, 0x04, 0x5C, 0x02, 0x30, 0x21, 0xC0, 0x36, 0x01, 0x17, 0x00, 0x5C,
+0x82, 0xF0, 0x29, 0xC0, 0x76, 0x04, 0x13, 0x02, 0x7C, 0x06, 0x30, 0x0D, 0xC2,
+0xA9, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x34,
+0x08, 0xDC, 0x01, 0x46, 0x05, 0x10, 0x41, 0x48, 0x27, 0x00, 0x51, 0x81, 0x44,
+0x02, 0x10, 0x19, 0xC4, 0xBE, 0x00, 0x9B, 0x00, 0x44, 0x02, 0xD1, 0x09, 0x48,
+0xBC, 0x00, 0x11, 0x80, 0x74, 0x22, 0x10, 0x0F, 0x40, 0x4C, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x32, 0x08, 0xCD, 0x00, 0x06,
+0x33, 0x10, 0x04, 0x40, 0x23, 0x02, 0x49, 0x02, 0x14, 0x00, 0x10, 0x2C, 0x51,
+0x33, 0x00, 0x14, 0x00, 0x10, 0x00, 0xD0, 0x00, 0x40, 0xB2, 0x00, 0x81, 0x80,
+0x34, 0x00, 0x11, 0x0C, 0x48, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0D, 0x08, 0x7A, 0x00, 0xFD, 0x01, 0x84, 0x07, 0x11, 0x12, 0x40,
+0x7B, 0x10, 0x79, 0x11, 0x94, 0x07, 0x10, 0x1F, 0x41, 0x7B, 0x00, 0x6C, 0x01,
+0x94, 0x07, 0xD8, 0x1E, 0x40, 0x70, 0x42, 0xE1, 0x01, 0xB4, 0x07, 0x5C, 0x1E,
+0x40, 0x37, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10,
+0x32, 0x00, 0xCF, 0x00, 0x04, 0x21, 0x12, 0x84, 0xC0, 0x33, 0x01, 0xCB, 0x00,
+0x1C, 0x21, 0x30, 0x4C, 0xC0, 0x33, 0x00, 0xC7, 0xE8, 0x1C, 0x81, 0xF0, 0x24,
+0xC0, 0x32, 0x02, 0xC3, 0x00, 0x7C, 0x11, 0x30, 0x0C, 0xC0, 0x4B, 0x40, 0x08,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x3D, 0x00, 0xFF, 0x00,
+0xFC, 0x81, 0xF0, 0x83, 0xC0, 0x3F, 0x00, 0xF7, 0x00, 0xEC, 0x03, 0xF0, 0x0F,
+0xCC, 0x3A, 0x00, 0xFB, 0x00, 0xEC, 0x03, 0xF0, 0x0F, 0xC0, 0xBF, 0x02, 0xFF,
+0x48, 0xFC, 0x01, 0xB0, 0x0F, 0xC0, 0x08, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0xA2, 0x37, 0x20, 0xDF, 0x00, 0x4C, 0x03, 0xF0, 0x05,
+0xC2, 0x13, 0x00, 0x57, 0x00, 0x7C, 0x01, 0xF0, 0x1D, 0xC0, 0x36, 0x00, 0x5F,
+0x40, 0x7C, 0x01, 0x70, 0x15, 0xC0, 0x34, 0x01, 0x53, 0x01, 0x4D, 0x01, 0x10,
+0x0D, 0xC4, 0x43, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0x98, 0x39, 0x08, 0xED, 0x00, 0x84, 0x01, 0xD0, 0x02, 0x40, 0x3B, 0x00, 0x61,
+0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3A, 0x04, 0xED, 0x00, 0xB4, 0x03, 0xD0,
+0x07, 0x50, 0xBC, 0x00, 0xF1, 0x00, 0xC4, 0x03, 0x10, 0x4E, 0x40, 0x4F, 0x60,
+0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x79, 0x00, 0xFD,
+0x11, 0xA6, 0x05, 0xD0, 0x16, 0x40, 0x5B, 0x04, 0x65, 0x01, 0xB4, 0x05, 0xD0,
+0x0A, 0x50, 0x7A, 0x93, 0x6D, 0x01, 0xB4, 0x05, 0x50, 0x1E, 0x40, 0x78, 0x41,
+0xE5, 0x03, 0x84, 0x07, 0x10, 0x9E, 0x40, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x16, 0x20, 0x33, 0x00, 0x4D, 0x12, 0x06, 0xBD, 0xD0,
+0x20, 0x40, 0x33, 0x00, 0x41, 0x01, 0x74, 0x47, 0xD0, 0xEC, 0x40, 0x32, 0x80,
+0xCD, 0x0A, 0x34, 0x2B, 0xD0, 0x0C, 0x40, 0x34, 0x00, 0xC5, 0x00, 0x04, 0x8B,
+0x10, 0x0C, 0x40, 0x5B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x17, 0xA8, 0x17, 0x00, 0x6F, 0x02, 0xEC, 0x09, 0xF2, 0x07, 0xC0, 0x1B, 0x0A,
+0x77, 0x07, 0xFC, 0x15, 0xF0, 0x06, 0xC0, 0x16, 0x00, 0x7F, 0x21, 0xF4, 0x2D,
+0x78, 0x87, 0xC1, 0x14, 0x00, 0x77, 0x00, 0xCC, 0x39, 0x30, 0x05, 0xC0, 0x5F,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x05, 0x00,
+0x1F, 0x82, 0x7D, 0x00, 0xF3, 0x01, 0x01, 0x07, 0x00, 0x1F, 0x10, 0x7C, 0x00,
+0xC0, 0x21, 0xC0, 0x05, 0x20, 0x1F, 0x10, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07,
+0x00, 0x19, 0x04, 0x7C, 0x08, 0xF4, 0x01, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x25, 0x00, 0x9F, 0x04, 0x5C, 0x0E,
+0xF0, 0x49, 0xC4, 0x24, 0x08, 0x9B, 0x00, 0x4D, 0x02, 0x30, 0x99, 0x02, 0x67,
+0x01, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x97, 0x80, 0x3C,
+0x0E, 0x70, 0x49, 0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00, 0x44, 0x1A, 0xD0, 0x78, 0x44, 0x24,
+0x10, 0x81, 0x00, 0x44, 0x02, 0x10, 0x29, 0x44, 0xA4, 0x08, 0x9D, 0x00, 0x74,
+0x82, 0xD1, 0x09, 0x40, 0x67, 0x00, 0x91, 0x80, 0x74, 0x06, 0x10, 0x09, 0x40,
+0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xA0, 0x24,
+0x00, 0x9D, 0x00, 0x54, 0x02, 0xD0, 0x0D, 0x44, 0x34, 0x20, 0x99, 0x08, 0x44,
+0x02, 0x10, 0x09, 0x60, 0x27, 0x04, 0xDD, 0x00, 0x74, 0x02, 0xD0, 0x09, 0x40,
+0x27, 0x01, 0x95, 0x00, 0x74, 0x42, 0x50, 0x09, 0x40, 0x73, 0x00, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x28, 0x20, 0x00, 0xCD, 0x00, 0x04,
+0x02, 0xD0, 0x09, 0x48, 0x20, 0x05, 0x81, 0x00, 0x04, 0x52, 0x10, 0x0C, 0x40,
+0x21, 0x15, 0x8D, 0x14, 0x34, 0x52, 0xD0, 0x48, 0x41, 0x33, 0x05, 0x81, 0x14,
+0x34, 0x52, 0x10, 0x48, 0x40, 0x53, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x00, 0x5C, 0x00, 0xF0, 0x01, 0xC0,
+0x04, 0x01, 0x1B, 0x00, 0x4C, 0x10, 0x34, 0x01, 0xC0, 0x07, 0x21, 0x1F, 0x06,
+0x7C, 0x10, 0xF0, 0x41, 0xC8, 0x07, 0x01, 0x17, 0x04, 0x7C, 0x10, 0x70, 0x01,
+0xC4, 0x77, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xA0,
+0x27, 0x00, 0xAF, 0x00, 0xFC, 0x02, 0xF2, 0x0B, 0xD0, 0x2F, 0x00, 0xBF, 0x00,
+0xFC, 0x52, 0xF0, 0x0A, 0xC0, 0x26, 0x00, 0xBF, 0x10, 0xFC, 0x52, 0xF0, 0x4B,
+0xC1, 0x27, 0x05, 0xBF, 0x14, 0xFC, 0x52, 0xF0, 0x69, 0xC3, 0x67, 0x20, 0x0E,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x25, 0x00, 0xBF, 0x00,
+0xCC, 0x02, 0xF0, 0x0B, 0xC0, 0x6F, 0x60, 0xB3, 0x00, 0x7C, 0x26, 0xF0, 0x0A,
+0xC0, 0x2D, 0x00, 0x93, 0x02, 0x7C, 0x52, 0x30, 0x39, 0xC1, 0xAF, 0x00, 0x9F,
+0x09, 0xCC, 0x06, 0xF0, 0x5B, 0xE0, 0x63, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1C, 0x18, 0x07, 0x00, 0x5D, 0x00, 0x44, 0x00, 0xD0, 0x01,
+0x40, 0x07, 0x00, 0x11, 0x00, 0x74, 0x2C, 0xD0, 0x01, 0x40, 0x04, 0x00, 0x11,
+0x01, 0x74, 0x18, 0x10, 0x21, 0x40, 0x47, 0x09, 0x1D, 0x0B, 0x44, 0x00, 0xD0,
+0x01, 0x40, 0x73, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x20, 0x21, 0x00, 0x8D, 0x00, 0x04, 0x02, 0xD0, 0x08, 0x40, 0xA3, 0x00, 0x85,
+0x01, 0x34, 0x12, 0xD0, 0x09, 0x40, 0xA3, 0x80, 0x81, 0x26, 0x34, 0x42, 0x14,
+0x08, 0x40, 0xA3, 0x00, 0x8D, 0x04, 0x04, 0x0A, 0xD0, 0x68, 0x41, 0x4B, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x25, 0x00, 0x9D,
+0x00, 0x46, 0x06, 0xD3, 0x19, 0x40, 0x27, 0x04, 0x95, 0x04, 0x76, 0x12, 0xD2,
+0x49, 0x40, 0x24, 0xC0, 0x91, 0x02, 0x74, 0x82, 0x00, 0x09, 0x41, 0x27, 0x00,
+0x9D, 0x02, 0x44, 0x02, 0xD2, 0x09, 0x48, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27, 0x00, 0x8F, 0x02, 0x44, 0x16, 0xF2,
+0x39, 0xC1, 0xA7, 0x00, 0x97, 0x02, 0x7C, 0x16, 0xF2, 0x09, 0xC0, 0x25, 0x00,
+0x93, 0xC2, 0x7C, 0x12, 0x30, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x09, 0x4D, 0x6E,
+0xD8, 0x09, 0x48, 0x17, 0x28, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x80, 0x25, 0x00, 0x9F, 0x02, 0x7D, 0x02, 0xF0, 0x09, 0xC0, 0x63, 0x02,
+0x9B, 0xA0, 0x7C, 0x02, 0xF1, 0x19, 0xC0, 0x27, 0x20, 0x9F, 0x05, 0x7C, 0x16,
+0xF0, 0x59, 0xC0, 0x27, 0x00, 0x8F, 0x01, 0x7C, 0x46, 0xF0, 0x09, 0xC0, 0x4B,
+0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x05, 0x00,
+0x1F, 0x04, 0x6C, 0x08, 0xF0, 0x01, 0xC0, 0x87, 0x00, 0x1F, 0x00, 0x7C, 0x08,
+0xF0, 0x01, 0xD0, 0x00, 0x00, 0x17, 0x00, 0x7C, 0x08, 0xF0, 0x21, 0xC2, 0x04,
+0x04, 0x1F, 0x02, 0x4C, 0x08, 0x30, 0x01, 0xC0, 0x40, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x14, 0x00, 0x7D, 0x02, 0xC4, 0x45,
+0xC2, 0x07, 0x00, 0x1F, 0x20, 0x7D, 0x21, 0x7C, 0x01, 0xD0, 0x16, 0x58, 0x1C,
+0x00, 0x5D, 0x00, 0x74, 0x01, 0xD1, 0x05, 0xC0, 0x1E, 0x04, 0x5D, 0x00, 0xC4,
+0x89, 0x10, 0x05, 0x50, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0xA0, 0x32, 0x00, 0x8D, 0x8B, 0x24, 0x06, 0xC8, 0xCC, 0x00, 0x53,
+0x04, 0x0C, 0x05, 0x34, 0x03, 0xD1, 0xD4, 0x40, 0x40, 0x00, 0xC5, 0x00, 0x74,
+0x03, 0xD0, 0x0C, 0x60, 0x72, 0x00, 0xCD, 0x00, 0x04, 0x0B, 0x15, 0x8C, 0x40,
+0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x38,
+0x00, 0xAD, 0x00, 0x84, 0x02, 0xD0, 0x0A, 0x40, 0xBB, 0x80, 0x2D, 0x82, 0x94,
+0x03, 0xD0, 0x07, 0x40, 0x88, 0x00, 0xED, 0x24, 0xB4, 0x23, 0xD0, 0x1F, 0x40,
+0x3A, 0x00, 0xFD, 0x80, 0x04, 0x07, 0x12, 0x1E, 0x40, 0x04, 0x20, 0x02, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x10, 0x79, 0x00, 0xAF, 0x01, 0xAC,
+0x06, 0xF0, 0x1A, 0xC8, 0x5B, 0x00, 0x2F, 0x01, 0xB0, 0x07, 0xF0, 0x12, 0xCA,
+0x78, 0x00, 0xE7, 0xA3, 0xBC, 0x87, 0xF0, 0x7F, 0xC4, 0x5A, 0x00, 0xFF, 0x0F,
+0x89, 0x07, 0x32, 0x1F, 0xC0, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0x8F, 0x00, 0x5C, 0x00, 0xF0, 0x09, 0xC0,
+0x37, 0x00, 0x1F, 0x80, 0x7C, 0x03, 0xF0, 0x05, 0xC0, 0x17, 0x10, 0xDF, 0x00,
+0x7C, 0x0B, 0xF0, 0x2D, 0xC4, 0x37, 0x00, 0xDF, 0xA4, 0x7C, 0x02, 0xF0, 0x0D,
+0xC0, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+0x7D, 0x00, 0xBF, 0x01, 0xCC, 0x26, 0xF0, 0x9B, 0xC0, 0x6F, 0x02, 0x33, 0x09,
+0xDC, 0xEF, 0x73, 0x17, 0xC8, 0x5C, 0x22, 0xFD, 0x09, 0xFC, 0x0F, 0xF1, 0x3F,
+0xC0, 0x7F, 0x02, 0xF7, 0x81, 0xDC, 0x05, 0x10, 0x9B, 0xC0, 0x00, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x39, 0x00, 0xAD, 0x48,
+0x85, 0x22, 0xD0, 0x0A, 0x00, 0x3B, 0x00, 0x21, 0xC0, 0x84, 0xE3, 0x10, 0x86,
+0x41, 0x98, 0x00, 0xED, 0x18, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00, 0xE1,
+0x00, 0xF4, 0x11, 0x12, 0xCB, 0x40, 0x55, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x2D, 0x10, 0x84, 0x2A, 0xD8, 0x0A,
+0x61, 0x2B, 0x60, 0x31, 0x50, 0x94, 0x23, 0x51, 0x06, 0x50, 0x3A, 0x98, 0xED,
+0x08, 0xB4, 0x23, 0xD0, 0x0E, 0x41, 0x1B, 0x00, 0xE1, 0x00, 0x94, 0x43, 0x99,
+0x0F, 0x44, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+0x20, 0x31, 0x00, 0x0D, 0x47, 0x04, 0x00, 0xD8, 0x58, 0x40, 0xB3, 0x02, 0x01,
+0x53, 0x04, 0x07, 0x58, 0x34, 0x40, 0x12, 0x80, 0xCD, 0x41, 0x24, 0x33, 0xD0,
+0x3C, 0x40, 0x23, 0x50, 0xC1, 0x42, 0x34, 0x46, 0x98, 0x0C, 0x40, 0x11, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8, 0x35, 0x10, 0x9D,
+0x00, 0x4C, 0x02, 0xD0, 0x19, 0xC0, 0x93, 0x40, 0x13, 0x01, 0xDC, 0x0B, 0x70,
+0x05, 0xC0, 0x06, 0x00, 0xFF, 0x03, 0xFC, 0x0B, 0xF8, 0x3F, 0xC4, 0x27, 0x00,
+0xF3, 0x0F, 0x5C, 0x02, 0xB4, 0x0D, 0x40, 0x55, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0xDF, 0x00, 0x7C, 0x22, 0xF0,
+0x09, 0xC0, 0x37, 0x01, 0x9F, 0x00, 0x7C, 0x13, 0x90, 0x45, 0xC0, 0x05, 0x00,
+0xDF, 0x10, 0x74, 0x03, 0xF0, 0x4D, 0xC0, 0x87, 0x00, 0xDF, 0x00, 0x7C, 0x00,
+0x70, 0x0D, 0x88, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x84, 0x08, 0x3E, 0x00, 0xBF, 0x00, 0xFC, 0x02, 0xC0, 0x03, 0xC8, 0x1F, 0x00,
+0x3B, 0x02, 0x7C, 0x03, 0xF0, 0x07, 0xC0, 0x18, 0x00, 0xFA, 0x00, 0xAC, 0x03,
+0xB0, 0x0F, 0xC8, 0x06, 0x10, 0xEF, 0x00, 0xDC, 0x02, 0xF0, 0x0F, 0x80, 0x13,
+0x22, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x20, 0x36, 0x00,
+0x9D, 0x01, 0x74, 0x05, 0xD0, 0x11, 0x40, 0x37, 0x00, 0xD1, 0x83, 0x74, 0x03,
+0xD0, 0x14, 0x40, 0x94, 0x00, 0xD1, 0x00, 0x74, 0x03, 0x10, 0x0D, 0x40, 0xC4,
+0x04, 0xDD, 0x00, 0x44, 0x1C, 0xD2, 0x0D, 0x42, 0x17, 0x00, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x34, 0x00, 0x9D, 0x01, 0x74, 0x06,
+0xD0, 0x69, 0x40, 0x27, 0x00, 0x19, 0x10, 0x74, 0x03, 0xD0, 0x35, 0x60, 0x14,
+0x00, 0xD5, 0x00, 0x64, 0x03, 0xD0, 0x0C, 0x60, 0x65, 0x00, 0xDD, 0x20, 0x54,
+0x04, 0xD8, 0x09, 0x40, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x28, 0x30, 0x00, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x08, 0x40, 0x33,
+0x00, 0x00, 0x20, 0x34, 0x83, 0xD0, 0x05, 0x40, 0x10, 0x00, 0xC5, 0x00, 0x34,
+0x03, 0x10, 0x0C, 0x60, 0x20, 0x00, 0xCD, 0x00, 0x06, 0x00, 0xD8, 0x08, 0x40,
+0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x36,
+0x00, 0x1F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x27, 0x00, 0x1B, 0x20, 0xFC,
+0x03, 0xF2, 0x05, 0xD0, 0x14, 0x10, 0xD7, 0x00, 0xEC, 0x03, 0xB0, 0x0F, 0xC0,
+0x04, 0x10, 0xFF, 0x20, 0x5C, 0x02, 0xF0, 0x0D, 0xC8, 0x03, 0xC0, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xA8, 0x3F, 0x00, 0x2F, 0x00, 0xFC,
+0x80, 0xF1, 0x0B, 0xC0, 0x3B, 0x00, 0x2F, 0x00, 0xFC, 0x03, 0xF0, 0x0E, 0xC0,
+0x1F, 0x20, 0xFB, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x2F, 0x20, 0xFF, 0x00,
+0xFC, 0x00, 0xF0, 0x0F, 0xE0, 0x17, 0x21, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x03, 0xA0, 0x5F, 0x40, 0xB3, 0x00, 0xFC, 0x12, 0xF0, 0x17, 0xC0,
+0x7F, 0x00, 0x73, 0x81, 0xFC, 0x10, 0xF1, 0xC3, 0xC0, 0x2C, 0x02, 0x33, 0x81,
+0xCC, 0x23, 0x30, 0x0F, 0xC0, 0x48, 0x10, 0xBF, 0x20, 0xFC, 0x05, 0x30, 0x1F,
+0xC0, 0x0C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+0x77, 0x08, 0x91, 0x4B, 0x74, 0x2E, 0xD2, 0x19, 0x00, 0x7F, 0x00, 0x51, 0x01,
+0x74, 0x2C, 0xD0, 0xE1, 0x40, 0xA4, 0x01, 0x11, 0x01, 0xC4, 0x1B, 0x51, 0xBB,
+0x48, 0x64, 0x00, 0x8D, 0x4E, 0x74, 0x07, 0x10, 0x0F, 0x48, 0x04, 0x60, 0x0C,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x23, 0x00, 0x81, 0x40,
+0x34, 0x02, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x81, 0x00, 0x34, 0x00, 0xD0, 0x09,
+0x40, 0xA0, 0x80, 0x15, 0x00, 0x04, 0x1B, 0x10, 0x0C, 0x40, 0x00, 0x00, 0x8D,
+0x10, 0x34, 0x82, 0x10, 0x0C, 0x40, 0x44, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0xA8, 0x25, 0x20, 0xD1, 0x00, 0x74, 0x02, 0xD0, 0x0D,
+0x40, 0x37, 0x00, 0x91, 0x82, 0x74, 0x04, 0xD0, 0x09, 0x48, 0x25, 0x84, 0x11,
+0x01, 0x45, 0x07, 0x53, 0x89, 0x40, 0x64, 0x00, 0x9D, 0x40, 0x34, 0x43, 0x10,
+0x0D, 0x40, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x88, 0x23, 0x00, 0xD3, 0x08, 0x7C, 0x02, 0xF0, 0x0D, 0x44, 0x33, 0x40, 0xD3,
+0x00, 0x7C, 0x0C, 0xF0, 0x88, 0xC0, 0x64, 0x40, 0x13, 0x81, 0x4C, 0x05, 0x30,
+0x1D, 0x90, 0x44, 0x00, 0x9E, 0x40, 0x7C, 0x2D, 0x34, 0x0D, 0xC0, 0x00, 0x20,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0xAD, 0x00, 0xBF,
+0x81, 0xFC, 0x13, 0xD0, 0x4B, 0x48, 0x3F, 0x00, 0xFF, 0x09, 0x7C, 0x00, 0xF0,
+0x1B, 0xC0, 0x6E, 0x2A, 0x3E, 0x10, 0xBC, 0x83, 0xF0, 0x09, 0xC4, 0x2F, 0x28,
+0xBF, 0x00, 0xF4, 0x03, 0xF1, 0x0F, 0xC0, 0x1F, 0x00, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25, 0x02, 0xD3, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x37, 0x02, 0x93, 0x02, 0x7C, 0x00, 0x34, 0x09, 0xE0, 0x24, 0x20,
+0x1B, 0x01, 0x7C, 0x03, 0x30, 0x0D, 0xC8, 0x04, 0x44, 0xD3, 0x00, 0x4C, 0x02,
+0xF0, 0x0D, 0xC5, 0x08, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x13, 0xA0, 0x24, 0x00, 0xD1, 0x00, 0x74, 0x03, 0xD0, 0x0D, 0xC0, 0x35, 0x02,
+0x95, 0x00, 0x74, 0x04, 0x10, 0x0B, 0x42, 0x64, 0x04, 0x01, 0x03, 0x5C, 0xAF,
+0x51, 0x18, 0xC0, 0xE6, 0x18, 0xD1, 0x01, 0x6C, 0x03, 0xD0, 0x6D, 0x40, 0x4C,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA0, 0x12, 0x04,
+0x81, 0x00, 0x34, 0x03, 0xD0, 0x00, 0x40, 0x33, 0x00, 0x81, 0x00, 0x34, 0x10,
+0x12, 0x00, 0x01, 0x64, 0x88, 0x09, 0x00, 0x34, 0x0F, 0x51, 0xBC, 0x41, 0x81,
+0x10, 0x85, 0x11, 0x04, 0x82, 0xD2, 0x2D, 0x42, 0x1C, 0x00, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x82, 0xA1, 0x21, 0xB4, 0x16,
+0xD0, 0x1A, 0x40, 0x73, 0x08, 0xA5, 0x01, 0xB4, 0x04, 0x18, 0x92, 0x40, 0x68,
+0x08, 0x29, 0x01, 0x14, 0x27, 0x52, 0x1E, 0x64, 0x6F, 0x00, 0xA5, 0x29, 0xA4,
+0x06, 0xD0, 0x1E, 0x40, 0x18, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x10, 0x20, 0x00, 0xC3, 0x08, 0x3C, 0x02, 0xF0, 0x08, 0x42, 0x33,
+0x02, 0x83, 0x00, 0x34, 0x48, 0x30, 0x08, 0x40, 0x20, 0x01, 0x0B, 0x00, 0x3C,
+0x43, 0x70, 0x0C, 0xC0, 0x01, 0x04, 0x87, 0x50, 0x0A, 0x02, 0xF0, 0x0D, 0xC0,
+0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB8, 0x29,
+0x40, 0xFF, 0x08, 0xFC, 0x12, 0xF0, 0x0B, 0xC0, 0x7D, 0x08, 0xBF, 0x00, 0xFC,
+0x00, 0xD0, 0x0E, 0x52, 0x2B, 0x00, 0x37, 0x00, 0xFC, 0x0B, 0xF0, 0x0F, 0xE0,
+0x3E, 0x10, 0x9B, 0x00, 0xFC, 0x22, 0xF0, 0x1F, 0xC0, 0x0B, 0x60, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x77, 0x00, 0x93, 0x00, 0x7C,
+0x23, 0x30, 0x09, 0xC0, 0x37, 0x00, 0xDF, 0x80, 0xFC, 0x00, 0xF0, 0x09, 0xC0,
+0x06, 0x10, 0x93, 0x80, 0x3C, 0x08, 0x34, 0x4D, 0xE1, 0x07, 0x08, 0x9F, 0x01,
+0x4C, 0x02, 0xF0, 0x0D, 0xD0, 0x54, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xA1, 0x04, 0xB4, 0x13, 0x10, 0x0A, 0x40,
+0xBB, 0x28, 0xEC, 0x20, 0xB4, 0x82, 0xD0, 0x6E, 0x48, 0x08, 0x00, 0xA1, 0x00,
+0xB4, 0x02, 0x50, 0x0E, 0x4A, 0x3B, 0x00, 0xBD, 0x40, 0xBC, 0x02, 0xD0, 0x4E,
+0x40, 0x48, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+0xED, 0x00, 0xE9, 0x09, 0x34, 0x0F, 0x10, 0x1A, 0x40, 0x7B, 0x01, 0xAD, 0x01,
+0xB4, 0x04, 0xD0, 0x18, 0x40, 0x48, 0x00, 0xA1, 0x01, 0xB4, 0x07, 0x90, 0x1E,
+0x40, 0x6B, 0x10, 0xED, 0x01, 0xA4, 0x06, 0xD0, 0x9E, 0x50, 0x0C, 0x00, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0xE3, 0x00, 0xC9, 0x88,
+0x34, 0x07, 0x10, 0x28, 0x41, 0x33, 0x00, 0x8D, 0x23, 0x34, 0x07, 0xD0, 0x0D,
+0x40, 0x14, 0x02, 0xC1, 0x01, 0x34, 0xCB, 0xD0, 0x0C, 0x40, 0x73, 0x04, 0xCD,
+0x00, 0x34, 0x02, 0xD0, 0x0D, 0x50, 0x48, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x17, 0xA8, 0xDD, 0x20, 0x5B, 0x21, 0x7C, 0x05, 0x34, 0x07,
+0xC0, 0x17, 0x00, 0x7F, 0x03, 0xFC, 0x01, 0xF1, 0x07, 0xC0, 0x5C, 0x40, 0x73,
+0x05, 0xBC, 0x1D, 0xB0, 0x05, 0xC4, 0xDF, 0x21, 0x5F, 0x00, 0xEC, 0x01, 0xF0,
+0x05, 0xC0, 0x5C, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+0x00, 0x87, 0x41, 0x17, 0x00, 0x7C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1F,
+0x08, 0x6C, 0x30, 0xF0, 0x31, 0xD0, 0x45, 0x00, 0x1F, 0x01, 0x7C, 0x00, 0x70,
+0x21, 0xC0, 0x87, 0x10, 0x1F, 0x00, 0x7E, 0x00, 0xF0, 0x21, 0xC8, 0x4B, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x27, 0x00, 0x8F,
+0x80, 0x4C, 0x02, 0x34, 0x09, 0xC0, 0x24, 0x00, 0x9F, 0x10, 0x4C, 0x02, 0xF0,
+0x09, 0xC0, 0x66, 0x01, 0x9B, 0x01, 0x4C, 0x02, 0xB0, 0x19, 0xC0, 0x27, 0x00,
+0x9F, 0x04, 0x7C, 0x82, 0x30, 0x09, 0xC0, 0x40, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0xBD, 0x00, 0x85, 0x02, 0x10,
+0x08, 0xC0, 0x2C, 0x00, 0x9D, 0x00, 0x54, 0x0A, 0xD2, 0x29, 0x40, 0xE4, 0x20,
+0x81, 0x4F, 0x54, 0x02, 0xB0, 0xD9, 0x46, 0xA7, 0x1E, 0x9D, 0x00, 0x34, 0x02,
+0x10, 0x6B, 0x40, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0xA0, 0x24, 0x80, 0x9D, 0x00, 0x44, 0x62, 0x10, 0x09, 0x40, 0x24, 0x00,
+0x8D, 0x00, 0x40, 0x2A, 0xD0, 0x19, 0x60, 0x26, 0x00, 0xD1, 0x20, 0x44, 0x2A,
+0x80, 0x09, 0x20, 0x37, 0x00, 0x9D, 0x00, 0x74, 0x02, 0x10, 0x09, 0x40, 0x60,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x10,
+0x8D, 0x02, 0x04, 0x02, 0x10, 0x29, 0x40, 0x20, 0x00, 0x8D, 0x02, 0x14, 0x52,
+0xD0, 0x48, 0x41, 0x20, 0x0D, 0x91, 0x20, 0x54, 0x52, 0x98, 0x48, 0x49, 0x23,
+0x00, 0x8D, 0x95, 0x76, 0x0A, 0x10, 0x08, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0, 0x06, 0x00, 0x1F, 0x01, 0x4C, 0x84,
+0x30, 0x01, 0xD0, 0x44, 0x00, 0x1D, 0x00, 0x4C, 0x10, 0xF0, 0x45, 0xD0, 0x12,
+0x01, 0x13, 0x00, 0x4C, 0x90, 0xB0, 0x41, 0xC0, 0x07, 0x00, 0x1F, 0x24, 0x7C,
+0x00, 0x34, 0x10, 0xD0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0xB8, 0x3B, 0x10, 0xBF, 0x03, 0xFC, 0x0A, 0xC0, 0x1F, 0xC0, 0xA5,
+0x00, 0xFF, 0x01, 0xFC, 0x02, 0xF0, 0x4B, 0xC3, 0x2F, 0x45, 0xBF, 0x00, 0xFC,
+0x52, 0x80, 0x0B, 0xC0, 0x2F, 0x00, 0xBF, 0x14, 0xFC, 0x06, 0xF0, 0x69, 0xC1,
+0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x2F,
+0x00, 0x9F, 0x07, 0xCC, 0x86, 0x34, 0x29, 0xC0, 0x6C, 0x04, 0x8F, 0x00, 0xFC,
+0x06, 0xF0, 0x5F, 0xC0, 0x6C, 0x05, 0xBB, 0x40, 0xCC, 0x06, 0x30, 0x1B, 0xC2,
+0x2C, 0x08, 0xF3, 0x05, 0x4C, 0x0A, 0xF0, 0x7B, 0xC0, 0x64, 0x00, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00, 0x1D, 0x01, 0x44,
+0x80, 0x10, 0x11, 0x50, 0x84, 0x00, 0x1D, 0x21, 0x74, 0x20, 0xD0, 0x50, 0xC1,
+0x42, 0x01, 0x11, 0x00, 0x44, 0x6D, 0x50, 0x01, 0x50, 0x04, 0x00, 0x01, 0x55,
+0x44, 0x05, 0xD0, 0x61, 0x40, 0x70, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x02, 0x05, 0x0A, 0x10, 0x08, 0x40,
+0x22, 0x00, 0x8D, 0x14, 0x34, 0x02, 0xD0, 0xC8, 0x40, 0x20, 0x05, 0x85, 0x00,
+0x05, 0x92, 0x58, 0x88, 0x40, 0x60, 0x40, 0x81, 0x08, 0x04, 0x82, 0xD0, 0x88,
+0x40, 0x42, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA8,
+0x25, 0x80, 0x8D, 0x01, 0x44, 0x12, 0x10, 0x08, 0x40, 0x26, 0x00, 0x9D, 0x80,
+0x74, 0x22, 0xD0, 0x09, 0x50, 0x26, 0x20, 0x95, 0x08, 0x04, 0x02, 0x58, 0x09,
+0x40, 0x34, 0x02, 0x91, 0x00, 0x45, 0x22, 0xD0, 0x09, 0x40, 0x62, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x67, 0x00, 0xBF, 0x80,
+0x4C, 0x06, 0x30, 0x1B, 0xC0, 0x26, 0x00, 0xBF, 0x00, 0x7C, 0x02, 0xF0, 0x49,
+0xC0, 0x64, 0x00, 0x97, 0x00, 0x4C, 0x86, 0x72, 0x09, 0xCA, 0x64, 0x20, 0x93,
+0x21, 0xCC, 0x0E, 0xF0, 0x09, 0xD0, 0x16, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x02, 0x9F, 0x00, 0x7C, 0x42, 0xF0, 0x49,
+0xC0, 0x25, 0x04, 0x9F, 0x03, 0x7C, 0x06, 0xF0, 0x58, 0xD0, 0x27, 0x02, 0x93,
+0x20, 0x7C, 0x22, 0xF0, 0x08, 0xC0, 0x67, 0x00, 0x8F, 0x09, 0x7C, 0x02, 0xD0,
+0x09, 0xC0, 0x51, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+0x08, 0x05, 0x00, 0x13, 0x00, 0x7C, 0x00, 0xF0, 0x21, 0xC0, 0x07, 0x40, 0x13,
+0x02, 0x4D, 0x00, 0x32, 0x21, 0xF0, 0x00, 0x00, 0x13, 0x44, 0x4C, 0x20, 0x34,
+0x41, 0xC0, 0x04, 0x0A, 0x13, 0x00, 0x4C, 0x00, 0xF0, 0x81, 0xC6, 0x50, 0x20,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x5C, 0x00, 0x51,
+0x00, 0xB4, 0x01, 0xD0, 0x05, 0x40, 0x1F, 0x80, 0x51, 0x00, 0xC4, 0x09, 0x50,
+0x27, 0x50, 0x1D, 0x00, 0x61, 0xD2, 0xC4, 0x05, 0x20, 0x07, 0x40, 0x18, 0x00,
+0x75, 0x08, 0x6C, 0x01, 0xD0, 0x17, 0xD0, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x62, 0x00, 0xC9, 0x00, 0x34, 0x02, 0xD0,
+0x0C, 0x40, 0x23, 0x08, 0xC1, 0x00, 0x04, 0x4A, 0x10, 0x3C, 0x49, 0x30, 0x00,
+0xC0, 0x01, 0x05, 0x17, 0x19, 0x28, 0x40, 0x30, 0x84, 0xC1, 0x01, 0x04, 0x03,
+0xD0, 0x19, 0x40, 0x50, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0x80, 0xFC, 0x00, 0xE9, 0x04, 0xB4, 0x42, 0xD0, 0x4E, 0x40, 0xFB, 0x00,
+0xF5, 0x25, 0x84, 0x46, 0x50, 0x6E, 0x68, 0x69, 0x21, 0x21, 0x20, 0x84, 0x01,
+0x18, 0x06, 0x41, 0x38, 0x00, 0xE5, 0x10, 0xA6, 0x13, 0xD0, 0x0E, 0x40, 0x12,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0x68, 0x00,
+0xEB, 0x07, 0xBC, 0x06, 0xF0, 0x3E, 0xC0, 0x6B, 0x00, 0xE1, 0x03, 0x8C, 0x06,
+0x32, 0x72, 0x40, 0x28, 0x41, 0x23, 0x01, 0x84, 0x07, 0x32, 0x10, 0xC0, 0x78,
+0x00, 0xE3, 0x01, 0x8C, 0x0F, 0xF0, 0x10, 0xC0, 0x50, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x31, 0x40, 0xD7, 0x00, 0x7C, 0x02,
+0xF0, 0x0D, 0xC0, 0x33, 0x00, 0xDB, 0x00, 0x3C, 0x02, 0xF0, 0x01, 0xD8, 0x27,
+0x02, 0x0F, 0x20, 0x3C, 0x00, 0xF0, 0x01, 0xD2, 0x33, 0x10, 0x5F, 0x12, 0x7C,
+0x03, 0xF0, 0x0D, 0xC0, 0x43, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA2, 0x6F, 0x00, 0xFF, 0x01, 0xCC, 0x07, 0xF0, 0x1E, 0xC0, 0x6C,
+0x00, 0xEF, 0x01, 0xCC, 0x07, 0x32, 0x1F, 0xC0, 0x78, 0x10, 0x23, 0x01, 0x8C,
+0x05, 0x30, 0x13, 0xC0, 0x7F, 0x08, 0x7F, 0x01, 0xBC, 0x07, 0x30, 0x1F, 0xC0,
+0x0B, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x88, 0x29,
+0x00, 0xED, 0x00, 0x84, 0x03, 0xD2, 0x0E, 0x40, 0xA8, 0x00, 0xED, 0x08, 0x84,
+0x03, 0xB0, 0x2F, 0x40, 0x28, 0x01, 0x21, 0x80, 0x94, 0x00, 0x52, 0x02, 0x40,
+0x3B, 0x0A, 0x6D, 0x04, 0xB4, 0x03, 0x10, 0x0E, 0x40, 0x57, 0x20, 0x06, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0xED, 0x01, 0x84,
+0x03, 0xD0, 0x1F, 0x40, 0x28, 0x00, 0xFD, 0x01, 0x84, 0x22, 0x10, 0x8E, 0x40,
+0x2C, 0x10, 0x39, 0x08, 0x84, 0x03, 0x10, 0x02, 0x40, 0x3B, 0x00, 0x2D, 0x00,
+0xF4, 0x07, 0x10, 0x06, 0x40, 0x63, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x04, 0x28, 0x23, 0x01, 0xCD, 0x00, 0x04, 0x07, 0xD0, 0x0C, 0x41,
+0x20, 0x00, 0xCD, 0x00, 0x06, 0x45, 0x90, 0x1C, 0x40, 0x20, 0x00, 0x09, 0x01,
+0x16, 0x19, 0x50, 0x90, 0x40, 0xB3, 0x00, 0x5D, 0x00, 0x34, 0x6F, 0x10, 0x0C,
+0x40, 0x1B, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA8,
+0xA5, 0x00, 0xDF, 0x04, 0x4C, 0x12, 0xF0, 0x0D, 0xD0, 0x24, 0x00, 0xDF, 0x00,
+0x4D, 0x12, 0x30, 0x1B, 0xC0, 0x3C, 0x41, 0x1B, 0x05, 0x4C, 0x01, 0x34, 0x01,
+0xC0, 0x47, 0x12, 0x9F, 0x00, 0x7C, 0x0F, 0x36, 0x01, 0xC8, 0x57, 0x20, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xB7, 0x00, 0xDF, 0x40,
+0x7C, 0x02, 0xF0, 0x8D, 0xC0, 0x33, 0x10, 0xDF, 0x00, 0x7C, 0x02, 0xF0, 0x80,
+0xC0, 0xA7, 0x00, 0x17, 0x40, 0x7C, 0x08, 0xF1, 0x00, 0xC0, 0xD7, 0x00, 0x1F,
+0x40, 0x7C, 0x03, 0xF0, 0x0D, 0xCC, 0x27, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x08, 0x6F, 0x00, 0xEF, 0x00, 0x8C, 0x0E, 0x30, 0x0F,
+0xC0, 0x2C, 0x00, 0xF3, 0x00, 0xCC, 0x02, 0xF0, 0x33, 0xC4, 0x0C, 0x00, 0x33,
+0x00, 0xBC, 0x09, 0x30, 0x03, 0xC0, 0x1C, 0x00, 0xBF, 0x00, 0xCC, 0x03, 0x30,
+0x0B, 0xD0, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81,
+0x20, 0xD6, 0x10, 0xDD, 0x40, 0x44, 0x4A, 0x10, 0x0D, 0x40, 0xF5, 0x50, 0xD1,
+0x00, 0x44, 0x02, 0xD0, 0x31, 0x42, 0x01, 0x08, 0x11, 0x23, 0x74, 0x0D, 0x10,
+0x51, 0xC0, 0xB6, 0x00, 0x1D, 0x61, 0x44, 0x03, 0x11, 0x2D, 0x40, 0x04, 0x02,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0, 0xA4, 0x01, 0xDD,
+0x00, 0x44, 0x02, 0x10, 0x0C, 0x40, 0x24, 0x02, 0xC1, 0x20, 0x44, 0x03, 0xD0,
+0x0D, 0x40, 0xB4, 0x90, 0x19, 0x51, 0x74, 0x09, 0x10, 0x11, 0x00, 0x14, 0x02,
+0x1D, 0x03, 0x05, 0x83, 0x10, 0x24, 0x40, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0xCD, 0x00, 0x04, 0x02, 0x14,
+0x0C, 0x40, 0x11, 0x00, 0xC1, 0x00, 0x04, 0x03, 0xD0, 0x04, 0x40, 0x25, 0x00,
+0x01, 0x00, 0x34, 0x01, 0x14, 0x00, 0x60, 0x32, 0x00, 0x1D, 0x00, 0x04, 0x03,
+0x10, 0x0C, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xB0, 0x26, 0x00, 0xEF, 0x00, 0x4D, 0x01, 0x30, 0x0F, 0xC0, 0x24, 0x00,
+0xF3, 0x00, 0x45, 0x02, 0xF0, 0x0D, 0xC0, 0x04, 0x00, 0x13, 0x00, 0x7C, 0x01,
+0x30, 0x01, 0xC0, 0x14, 0x00, 0x3F, 0x00, 0xCC, 0x03, 0x34, 0x0D, 0xC8, 0x04,
+0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x1F, 0x00,
+0xFF, 0x00, 0xFC, 0x81, 0xF0, 0x0F, 0xC0, 0x1F, 0x00, 0xFF, 0x00, 0xBC, 0x01,
+0xE2, 0x07, 0x98, 0x0F, 0x40, 0x3F, 0x40, 0xFC, 0x01, 0xF0, 0x03, 0xC0, 0x3F,
+0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0xFB, 0x10, 0x9C, 0x07,
+0xF0, 0x1F, 0xC0, 0x4F, 0x00, 0xBF, 0x01, 0xFC, 0x05, 0xF0, 0x17, 0xC8, 0x2E,
+0x10, 0xBF, 0x04, 0xFC, 0x03, 0x30, 0x1F, 0xC0, 0x7F, 0x08, 0xB6, 0x00, 0xFC,
+0x27, 0x70, 0x02, 0xC0, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x08, 0x77, 0x00, 0xFD, 0x03, 0x44, 0x06, 0x10, 0x1D, 0x40, 0x47,
+0x00, 0xDD, 0x01, 0x74, 0x00, 0x10, 0x1D, 0x40, 0xE4, 0x02, 0x1D, 0x04, 0xF4,
+0x5B, 0x10, 0x01, 0x40, 0x47, 0x08, 0x9D, 0x01, 0x74, 0x03, 0xD0, 0x19, 0x40,
+0x0C, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA0, 0x33,
+0x00, 0xCD, 0x00, 0x14, 0x03, 0xD0, 0x0C, 0x40, 0x03, 0x00, 0x8D, 0x40, 0x74,
+0x51, 0x90, 0x05, 0x48, 0x02, 0x00, 0x0D, 0x12, 0x34, 0x1B, 0x10, 0x4C, 0x49,
+0x33, 0x00, 0x0D, 0x02, 0x34, 0x13, 0xD0, 0x00, 0x40, 0x4E, 0x80, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x00, 0xDD, 0x20, 0x40,
+0x07, 0x10, 0x0D, 0x40, 0x67, 0x00, 0xDD, 0x23, 0x74, 0x81, 0x14, 0x1D, 0x41,
+0x44, 0x00, 0x1D, 0x01, 0x74, 0x03, 0x14, 0x01, 0x40, 0x07, 0x08, 0x9D, 0x51,
+0x74, 0x03, 0xD0, 0x19, 0x41, 0x0C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x88, 0x37, 0x00, 0xDF, 0x00, 0x54, 0x1F, 0xF0, 0x0D, 0xC0,
+0x47, 0x00, 0x9F, 0x01, 0x7C, 0x19, 0xF0, 0x14, 0xC0, 0xC6, 0x00, 0x9F, 0x07,
+0x74, 0x03, 0x30, 0x0D, 0xC0, 0x37, 0x00, 0x17, 0x01, 0x7C, 0x03, 0x79, 0x39,
+0xC0, 0x22, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80,
+0x3C, 0x00, 0xEF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0xFF, 0x40,
+0xFC, 0x00, 0xF0, 0x0F, 0xC0, 0x27, 0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x03,
+0xC4, 0x0F, 0x30, 0x1F, 0x20, 0xFE, 0xA7, 0xF0, 0x0B, 0x40, 0x1F, 0x00, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x35, 0x00, 0xDF, 0x00,
+0x7C, 0x03, 0x30, 0x0D, 0xC0, 0x07, 0x00, 0x1F, 0x02, 0x5C, 0x49, 0xB0, 0x25,
+0xC0, 0x06, 0x00, 0x9B, 0x00, 0x4E, 0x03, 0xF0, 0x0D, 0xC0, 0x34, 0x00, 0x17,
+0x02, 0x4C, 0x13, 0xF2, 0x29, 0xC5, 0x29, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x13, 0xA0, 0x34, 0x00, 0xFD, 0x00, 0x34, 0x07, 0x10, 0x0D,
+0xC0, 0x07, 0x00, 0xDD, 0x05, 0x04, 0x1D, 0x10, 0x0D, 0x40, 0x64, 0x00, 0x11,
+0x00, 0xEC, 0x63, 0xD0, 0x71, 0x40, 0x84, 0x0B, 0x11, 0x01, 0x44, 0x43, 0xD0,
+0x18, 0xC0, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+0xA0, 0x32, 0x00, 0xCD, 0x00, 0x34, 0x3B, 0x10, 0x0C, 0x40, 0x03, 0x00, 0xCD,
+0x00, 0x14, 0x0B, 0x94, 0x00, 0x42, 0x62, 0x00, 0x89, 0x80, 0x54, 0x07, 0xD0,
+0x4C, 0x40, 0xF1, 0x10, 0x85, 0x00, 0x04, 0x03, 0xD0, 0xB0, 0x40, 0x0D, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x78, 0x80, 0xED,
+0x41, 0xB4, 0x07, 0x10, 0x1E, 0x40, 0x49, 0x30, 0xED, 0xC9, 0x94, 0x06, 0x10,
+0x17, 0x00, 0x78, 0x00, 0xF0, 0x49, 0xB4, 0x07, 0xD0, 0x13, 0x40, 0x48, 0x00,
+0xE1, 0x11, 0x84, 0x07, 0xD0, 0x16, 0x40, 0x3E, 0x20, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0xCF, 0x00, 0x3C, 0x01, 0x30,
+0x8C, 0x40, 0x03, 0x00, 0xCF, 0x00, 0x5C, 0x33, 0xB0, 0x00, 0xC0, 0x32, 0x04,
+0x5B, 0x80, 0x14, 0x03, 0xF2, 0x0C, 0xD0, 0x30, 0x03, 0x46, 0x08, 0x0D, 0x03,
+0xF0, 0x00, 0xC0, 0x49, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xB0, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x01, 0xF0, 0x0D, 0xC2, 0x37, 0x00,
+0xCF, 0x00, 0x6C, 0xA3, 0xF0, 0x0C, 0xC0, 0x37, 0x00, 0xDF, 0x20, 0x6C, 0x43,
+0xF0, 0x80, 0xC0, 0x03, 0x0A, 0xDF, 0x08, 0x7C, 0x23, 0xF0, 0x8D, 0xC0, 0x09,
+0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xA0, 0x37, 0x00,
+0xDF, 0x1E, 0x7C, 0x03, 0x30, 0x0D, 0xC4, 0x07, 0x00, 0xDF, 0x00, 0x5C, 0x01,
+0xF0, 0x15, 0xC0, 0x14, 0x00, 0xDF, 0x00, 0x4C, 0x4F, 0x71, 0x0D, 0xC8, 0x34,
+0x10, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x05, 0xC4, 0x40, 0x00, 0x0E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x03,
+0x10, 0x0E, 0x48, 0x0B, 0x10, 0xED, 0x00, 0x84, 0x02, 0xD0, 0x0E, 0x40, 0x38,
+0x08, 0xFD, 0x80, 0x04, 0x03, 0x12, 0x02, 0x40, 0x08, 0x04, 0xED, 0x00, 0xB4,
+0x03, 0xD0, 0x06, 0x60, 0x4C, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x03, 0x00, 0x79, 0x00, 0xED, 0x01, 0xF4, 0x07, 0x14, 0x1E, 0x40, 0x4B,
+0x00, 0xED, 0x01, 0x94, 0x07, 0xD0, 0x17, 0x50, 0x58, 0x00, 0xED, 0x01, 0x85,
+0x07, 0x50, 0x1F, 0x40, 0x78, 0x00, 0xED, 0x01, 0xB4, 0x87, 0xD0, 0x1C, 0x40,
+0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x33,
+0x00, 0xCD, 0x00, 0x34, 0x4F, 0x90, 0x0C, 0x48, 0xC3, 0x83, 0xCD, 0x12, 0x04,
+0x4B, 0xD0, 0x7C, 0x40, 0xB0, 0x0C, 0xCD, 0x02, 0x04, 0x03, 0x10, 0x01, 0x40,
+0x00, 0x00, 0xCD, 0x88, 0x30, 0x22, 0xD0, 0x1C, 0x40, 0x58, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x15, 0x00, 0x5F, 0x00, 0xBC,
+0x49, 0x30, 0x05, 0xC2, 0x9F, 0x00, 0x6F, 0x02, 0x9C, 0x09, 0xF0, 0x27, 0xC8,
+0x1C, 0x00, 0x7F, 0x00, 0x4C, 0x01, 0x70, 0x05, 0xD0, 0x14, 0x00, 0x7D, 0x21,
+0x7C, 0x05, 0xD0, 0x27, 0x40, 0x5C, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x12, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x70, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x00, 0x7C, 0x08, 0xF0, 0x81, 0xC0, 0x07, 0x00, 0x1F, 0x18,
+0x7C, 0x00, 0xF0, 0x23, 0xC0, 0x8F, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0xA1,
+0xD1, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08,
+0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0x34, 0x09, 0xC0, 0x27, 0x00, 0x9F, 0x08,
+0x6C, 0x26, 0x71, 0x09, 0xC0, 0x27, 0x00, 0x9E, 0x00, 0x4C, 0x16, 0xF0, 0x09,
+0xC0, 0x25, 0x20, 0x93, 0x38, 0x78, 0x0E, 0xF2, 0x18, 0xC0, 0x40, 0x20, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26, 0x00, 0x9D, 0x00,
+0x74, 0x02, 0x11, 0x09, 0x40, 0x27, 0x00, 0x9D, 0x40, 0x44, 0x06, 0x11, 0x09,
+0x44, 0x27, 0x00, 0x9D, 0x80, 0x44, 0x8E, 0xD1, 0x29, 0x40, 0x20, 0x04, 0x91,
+0x01, 0x74, 0x06, 0xD0, 0x89, 0x41, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x00, 0x74, 0x12, 0x1C, 0x09,
+0x40, 0x27, 0x00, 0x9D, 0x00, 0x64, 0x42, 0x40, 0x09, 0x42, 0x37, 0x80, 0x8D,
+0x00, 0x44, 0x02, 0xD0, 0x19, 0x41, 0x2D, 0x40, 0x91, 0x00, 0x74, 0x42, 0xD0,
+0x09, 0x40, 0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x20, 0x00, 0x8D, 0x14, 0x74, 0x02, 0x10, 0x08, 0x40, 0x23, 0x00, 0x8D,
+0x00, 0x44, 0x02, 0x10, 0x08, 0x40, 0x23, 0x05, 0x8D, 0x34, 0x04, 0x52, 0xD0,
+0x0A, 0x40, 0x2C, 0x20, 0x81, 0x14, 0x34, 0x02, 0xD0, 0x48, 0x51, 0x50, 0xA0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x30, 0x06, 0x00, 0x1F,
+0x04, 0x7C, 0x00, 0x30, 0x01, 0xC8, 0x07, 0x00, 0x1F, 0x00, 0x6C, 0x00, 0x70,
+0x01, 0xC0, 0x07, 0x21, 0x1F, 0x04, 0x4C, 0x11, 0xF0, 0x01, 0xC0, 0x0D, 0x00,
+0x13, 0xC4, 0x7C, 0x00, 0xF0, 0x41, 0xC0, 0x74, 0xC0, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x19, 0xB0, 0x27, 0x00, 0x9F, 0x00, 0xBC, 0x03, 0xF0,
+0x09, 0xC0, 0x2F, 0x00, 0xEF, 0x80, 0xFC, 0x52, 0xF0, 0x0A, 0xC0, 0x2F, 0x00,
+0xBF, 0x14, 0x7D, 0x52, 0xF0, 0x48, 0xC5, 0x27, 0x00, 0xBF, 0x40, 0xFC, 0x52,
+0xF0, 0x0B, 0xC0, 0x67, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0xA0, 0x27, 0x00, 0x9F, 0x01, 0xFC, 0x02, 0xB0, 0x09, 0xC0, 0x27, 0x60,
+0xB3, 0x00, 0x9C, 0x0A, 0x70, 0x09, 0xC0, 0x3D, 0x00, 0x93, 0x02, 0xCC, 0xC6,
+0xF0, 0x2B, 0xC2, 0x2F, 0x00, 0xBF, 0x80, 0xCC, 0x0A, 0xD0, 0x0B, 0xC0, 0x67,
+0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x08, 0x07, 0x00,
+0x1D, 0x0A, 0x74, 0x00, 0x10, 0x01, 0x40, 0x07, 0x00, 0x11, 0x00, 0x44, 0x04,
+0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x10, 0xD0, 0x01, 0x40, 0x07,
+0x00, 0x1D, 0x00, 0x44, 0x00, 0xD0, 0x01, 0x40, 0x73, 0x60, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x8D, 0x00, 0x74, 0x02,
+0x90, 0x08, 0x40, 0x27, 0x00, 0x81, 0x00, 0x54, 0x02, 0x52, 0x09, 0x40, 0xA1,
+0x00, 0x81, 0x22, 0x04, 0x42, 0xD2, 0x08, 0x40, 0x23, 0x00, 0x8D, 0x02, 0x04,
+0x02, 0xD0, 0x08, 0x40, 0x4B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0xA8, 0x25, 0x00, 0x9D, 0x00, 0x74, 0x06, 0x10, 0x09, 0x40, 0x27,
+0x00, 0x91, 0x00, 0x44, 0x1A, 0x12, 0x29, 0x42, 0x24, 0x40, 0x91, 0x80, 0x45,
+0x82, 0xD0, 0x09, 0x40, 0x27, 0x08, 0x9D, 0x00, 0x44, 0x03, 0xD0, 0x29, 0x40,
+0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x27,
+0x00, 0x9F, 0x00, 0x7C, 0x02, 0xB0, 0x09, 0xC4, 0xE3, 0x04, 0x93, 0x02, 0x5C,
+0x0E, 0x70, 0x08, 0xC0, 0xE5, 0x04, 0x92, 0x1B, 0x48, 0x02, 0xE0, 0x09, 0xC0,
+0x27, 0x00, 0x9F, 0x19, 0x4D, 0x06, 0xF0, 0x09, 0xC0, 0x17, 0x28, 0x0E, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x25, 0x00, 0x9F, 0x00, 0x7C,
+0x02, 0xF0, 0x09, 0xC4, 0x67, 0x02, 0x9F, 0x00, 0x7C, 0x06, 0xF0, 0x09, 0xC0,
+0x27, 0x01, 0x8F, 0x21, 0x7C, 0x82, 0xF0, 0x09, 0xC0, 0x27, 0x10, 0x8F, 0x01,
+0x7C, 0x12, 0xF0, 0x09, 0xC0, 0x4B, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x1F, 0x00, 0x6C, 0x08, 0xF0, 0x01, 0xC0,
+0x07, 0x00, 0x1F, 0x00, 0x7C, 0x40, 0x31, 0x21, 0xC8, 0x87, 0x00, 0x1E, 0x02,
+0x7C, 0x00, 0x32, 0x81, 0x81, 0x04, 0x04, 0x1F, 0x80, 0x4C, 0x00, 0x34, 0x01,
+0xC0, 0x43, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0,
+0x14, 0x00, 0x5D, 0x00, 0x84, 0x01, 0xD0, 0x05, 0x40, 0x17, 0x10, 0x6D, 0x80,
+0xB4, 0x05, 0x10, 0x05, 0x40, 0x13, 0x00, 0x5D, 0x00, 0xF4, 0x01, 0x10, 0x27,
+0x40, 0xDC, 0x00, 0x5D, 0x05, 0xC4, 0x61, 0x12, 0x07, 0x40, 0x53, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32, 0x00, 0xCD, 0x00,
+0x24, 0x05, 0xD0, 0x0C, 0x40, 0x33, 0x00, 0x8D, 0x0C, 0x34, 0x0F, 0x14, 0x0C,
+0x40, 0x33, 0x02, 0xCD, 0x00, 0x34, 0x1F, 0x50, 0x2C, 0x44, 0xD0, 0x20, 0x8D,
+0x00, 0x04, 0x0F, 0x10, 0x2C, 0x41, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x05, 0x80, 0x38, 0x00, 0xED, 0x01, 0x84, 0x0B, 0xD0, 0x0E,
+0x40, 0x3B, 0x80, 0xAD, 0x00, 0xF4, 0x43, 0x10, 0x0E, 0x40, 0x2B, 0x00, 0xED,
+0x48, 0xB4, 0x47, 0x50, 0x1E, 0x50, 0x38, 0x04, 0xED, 0x00, 0x84, 0x05, 0x10,
+0x2E, 0x40, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0x10, 0x78, 0x00, 0xCF, 0x01, 0xAC, 0x05, 0xF0, 0x1E, 0xC4, 0x7B, 0x10, 0xAF,
+0x01, 0xBC, 0x07, 0x30, 0x1E, 0xC0, 0x7B, 0x00, 0xEF, 0x8D, 0xFC, 0x07, 0x70,
+0x17, 0xC0, 0x78, 0x08, 0xEE, 0x01, 0xCD, 0x07, 0x30, 0x1E, 0xC0, 0x47, 0x40,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x35, 0x00, 0xDF,
+0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC4, 0x37, 0x00, 0x9F, 0x00, 0x7C, 0x03, 0xF0,
+0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x42, 0x7C, 0x03, 0xB4, 0x0D, 0xC0, 0x37, 0x00,
+0xCF, 0x00, 0x7C, 0x01, 0xF0, 0x05, 0xC8, 0x43, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x7F, 0x00, 0xFF, 0x01, 0xFC, 0x85, 0xF0,
+0x1F, 0xC0, 0x7F, 0x02, 0x2F, 0x09, 0x8C, 0x05, 0xF0, 0x9F, 0xC2, 0x6D, 0x02,
+0xFB, 0x09, 0xFC, 0x07, 0x30, 0x1F, 0xC0, 0x7F, 0x20, 0xFF, 0x01, 0xFC, 0x07,
+0x30, 0x1F, 0xC0, 0x0A, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x88, 0x39, 0x00, 0xED, 0x00, 0xB4, 0x03, 0xD0, 0x0E, 0x40, 0x3B, 0x00,
+0x2D, 0x10, 0x84, 0x01, 0x12, 0x0E, 0x40, 0x38, 0x04, 0xE9, 0x00, 0x84, 0x11,
+0x10, 0x06, 0x40, 0x3B, 0x00, 0xED, 0x00, 0xA4, 0x11, 0x18, 0x0A, 0x40, 0x54,
+0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00,
+0xED, 0x00, 0xB4, 0x01, 0xD0, 0x0E, 0x40, 0x39, 0x20, 0x3D, 0x00, 0xC5, 0x01,
+0xD0, 0x0F, 0x09, 0x29, 0x00, 0xED, 0x40, 0x96, 0x83, 0x14, 0x06, 0x40, 0x3B,
+0x02, 0xED, 0x00, 0xF4, 0x83, 0x10, 0x0E, 0x41, 0x22, 0x00, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x33, 0x00, 0xCD, 0x40, 0x34, 0x03,
+0xD0, 0x0C, 0x64, 0xB3, 0x04, 0x0D, 0x07, 0x04, 0x0C, 0x90, 0x3C, 0x40, 0x70,
+0x00, 0xCD, 0x03, 0x04, 0x02, 0x10, 0xA1, 0x44, 0x73, 0x00, 0xCD, 0x02, 0x64,
+0x24, 0x10, 0x10, 0x40, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x15, 0xA8, 0x35, 0x00, 0xDF, 0x00, 0x7C, 0x07, 0xF0, 0x0D, 0xC0, 0x77,
+0x14, 0x9F, 0x03, 0x0C, 0x4E, 0xF0, 0x9D, 0xC0, 0xF5, 0x00, 0xFF, 0x12, 0x78,
+0x00, 0x30, 0x39, 0x40, 0x73, 0x01, 0xDD, 0x10, 0x7C, 0x02, 0x14, 0x1D, 0xC0,
+0x56, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x37,
+0x00, 0xDF, 0x00, 0x7C, 0x22, 0xF0, 0x0D, 0xC0, 0x37, 0x08, 0x9F, 0x02, 0x7C,
+0x08, 0x70, 0x0D, 0xC0, 0x27, 0x00, 0xDB, 0x04, 0x7C, 0x0A, 0xF0, 0x09, 0xC4,
+0x37, 0x00, 0xDF, 0x30, 0x6C, 0x82, 0xF0, 0x6D, 0xC0, 0xA7, 0x00, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x3F, 0x00, 0xFF, 0x80, 0xFC,
+0x83, 0xF0, 0x0F, 0xC0, 0x3F, 0x08, 0xBF, 0x00, 0xDC, 0x42, 0x70, 0x0F, 0xC0,
+0x3D, 0x04, 0xDF, 0x40, 0x78, 0x00, 0xE0, 0x03, 0x01, 0x3C, 0x24, 0xF2, 0x80,
+0xFC, 0x00, 0x30, 0x09, 0xE0, 0x17, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x81, 0x00, 0x36, 0x00, 0xDD, 0x00, 0x74, 0x1F, 0xD0, 0x0D, 0xC0,
+0x35, 0x00, 0x8D, 0x41, 0x46, 0x16, 0x10, 0x0C, 0x46, 0x24, 0x20, 0xDD, 0x00,
+0x74, 0x0E, 0xD0, 0x19, 0xC1, 0xF6, 0x01, 0xD1, 0x00, 0x74, 0x04, 0x30, 0x41,
+0x40, 0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA0,
+0x34, 0x80, 0xDD, 0x00, 0x74, 0x07, 0xD0, 0x0D, 0x48, 0x35, 0x10, 0x9D, 0x03,
+0x54, 0x06, 0x50, 0x0D, 0x40, 0x25, 0x00, 0xDD, 0x00, 0x54, 0x0C, 0xD0, 0x19,
+0x60, 0x75, 0x10, 0xD5, 0x04, 0x74, 0x06, 0x10, 0x85, 0x40, 0x05, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x80, 0xCD, 0x00,
+0x34, 0x03, 0xD0, 0x0C, 0x42, 0x31, 0x00, 0xDD, 0x20, 0x44, 0x00, 0x18, 0x0D,
+0x40, 0x30, 0x00, 0xCD, 0x00, 0x34, 0x00, 0xD0, 0x09, 0x48, 0x27, 0x80, 0xC5,
+0x00, 0x34, 0x02, 0x93, 0x00, 0x40, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xB0, 0x36, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D,
+0xC0, 0x35, 0x00, 0x9F, 0x00, 0x54, 0x02, 0x70, 0x0D, 0xC0, 0x25, 0x20, 0xFD,
+0x00, 0x5C, 0x00, 0xF0, 0x01, 0xC0, 0x35, 0x80, 0xD7, 0x80, 0x7C, 0x02, 0x24,
+0x01, 0xC0, 0x07, 0xC4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+0xB8, 0x3F, 0x10, 0xFF, 0x20, 0xFC, 0x03, 0xF0, 0x0F, 0xC4, 0x3D, 0x00, 0xBF,
+0x80, 0xF4, 0x02, 0xF2, 0x0E, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x02, 0xF0,
+0x0B, 0xC0, 0x2E, 0x40, 0xFB, 0x00, 0xBC, 0x02, 0x70, 0x03, 0xC8, 0x17, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA0, 0x5F, 0x00, 0x7F,
+0x41, 0xFC, 0x85, 0xF0, 0x1B, 0xC0, 0x5C, 0x02, 0xAF, 0x14, 0xCC, 0x04, 0xF0,
+0xC3, 0xC0, 0x0C, 0x04, 0xB3, 0x10, 0xCC, 0x0C, 0x30, 0x8B, 0xC0, 0x3F, 0x00,
+0xB3, 0x14, 0xCC, 0x53, 0x30, 0x0B, 0xC0, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x57, 0x00, 0x9D, 0x01, 0x74, 0x05, 0xD1,
+0x15, 0x44, 0x14, 0x21, 0xFD, 0x03, 0x44, 0x10, 0xD0, 0xE1, 0x00, 0x84, 0x01,
+0xAB, 0x06, 0x44, 0x00, 0x10, 0xE9, 0x40, 0x77, 0x00, 0xB5, 0x06, 0xD4, 0x0F,
+0x10, 0x09, 0x40, 0x04, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0xA0, 0x33, 0x00, 0x8D, 0x00, 0x34, 0x02, 0xD0, 0x09, 0x40, 0x20, 0x20,
+0xCD, 0x00, 0x16, 0x40, 0xD2, 0x01, 0x50, 0x04, 0x44, 0x81, 0x10, 0x05, 0x10,
+0x10, 0x00, 0x40, 0x33, 0x00, 0xC1, 0x10, 0x04, 0x03, 0xD0, 0x48, 0x41, 0x44,
+0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xA8, 0x35, 0x01,
+0x9D, 0x04, 0x74, 0x02, 0xD0, 0x85, 0x40, 0x24, 0x00, 0xDD, 0x00, 0x55, 0x04,
+0xD0, 0x01, 0x46, 0x64, 0x00, 0x99, 0x48, 0x44, 0x04, 0x10, 0x31, 0x48, 0x37,
+0x00, 0xC5, 0x00, 0x54, 0x03, 0xD0, 0x09, 0x40, 0x0C, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0x01, 0xDF, 0x01, 0x7C, 0x27,
+0xF0, 0x0D, 0xD0, 0x74, 0x12, 0x8F, 0x00, 0x5C, 0x44, 0xF0, 0x20, 0xC1, 0xC0,
+0x00, 0x93, 0x00, 0x4C, 0x14, 0x34, 0x1D, 0xC0, 0x37, 0x00, 0x93, 0x80, 0x4C,
+0x03, 0xF4, 0x39, 0xD0, 0x08, 0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x07, 0x80, 0x6D, 0x00, 0xBF, 0x01, 0xF8, 0x07, 0xF0, 0x0F, 0xC8, 0x3F,
+0x00, 0xF8, 0x10, 0xEC, 0x00, 0xF0, 0x23, 0xC0, 0x0F, 0x00, 0xBF, 0x00, 0xFC,
+0x40, 0xF0, 0x0F, 0xC0, 0x3B, 0x10, 0x9F, 0x09, 0xB8, 0x83, 0x30, 0x3B, 0xC0,
+0x1F, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x25,
+0x00, 0x9F, 0x40, 0x7C, 0x02, 0xF0, 0x0D, 0xC0, 0x27, 0x00, 0xDF, 0x80, 0x4C,
+0x00, 0x32, 0x01, 0xD0, 0x8C, 0x00, 0x93, 0x00, 0x4C, 0x00, 0xF0, 0x25, 0xC0,
+0x34, 0x00, 0xD3, 0x04, 0x4D, 0x03, 0xF0, 0x28, 0xC0, 0x0B, 0x20, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA0, 0x24, 0x00, 0x9C, 0x00, 0x70,
+0x02, 0xD0, 0x0C, 0x60, 0x67, 0x00, 0xDD, 0x03, 0x40, 0x2C, 0x10, 0x03, 0x40,
+0x64, 0x00, 0x91, 0x0F, 0x6D, 0x08, 0x91, 0xB5, 0x40, 0xBC, 0x40, 0xD5, 0x13,
+0xC4, 0x03, 0xC0, 0x49, 0x40, 0x4F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0xA0, 0x22, 0x20, 0x4D, 0x80, 0x34, 0x02, 0xC0, 0x04, 0x48,
+0x63, 0x00, 0x8D, 0x01, 0x24, 0x04, 0x10, 0x08, 0x42, 0x40, 0x00, 0x91, 0x01,
+0x44, 0x04, 0xD1, 0x18, 0x40, 0xB0, 0x04, 0xC1, 0x02, 0x04, 0x03, 0xD0, 0x08,
+0x40, 0x1F, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80,
+0x68, 0x00, 0xED, 0x21, 0xB4, 0x06, 0xD0, 0x16, 0x40, 0x6B, 0x06, 0xED, 0x11,
+0xA5, 0x44, 0x14, 0x98, 0x50, 0x6C, 0x04, 0xE1, 0x09, 0xA4, 0x04, 0x90, 0x1E,
+0x40, 0x78, 0x02, 0xE5, 0x21, 0x84, 0x07, 0xD1, 0x16, 0x40, 0x13, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x10, 0x30, 0x00, 0x8F, 0x00,
+0x3C, 0x02, 0xF0, 0x04, 0x40, 0x23, 0x0A, 0xCF, 0x00, 0x6C, 0x00, 0x32, 0x88,
+0xC8, 0x80, 0x40, 0xC3, 0x08, 0x0C, 0x40, 0xF2, 0x8D, 0xD1, 0x30, 0x02, 0xC3,
+0x00, 0x0D, 0x03, 0xF0, 0x04, 0xC0, 0x4B, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xB8, 0x3D, 0x00, 0xBF, 0x80, 0xF0, 0x02, 0xF0, 0x07,
+0xC0, 0x2F, 0x0A, 0xFF, 0x02, 0xDC, 0x00, 0xF0, 0x8B, 0xD0, 0x3B, 0x42, 0xFF,
+0x08, 0xF4, 0x00, 0xB0, 0x8F, 0xC0, 0x3B, 0x02, 0xFF, 0x00, 0xFC, 0x43, 0xF0,
+0x87, 0xC0, 0x0B, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+0xA0, 0x67, 0x00, 0xD3, 0x20, 0x7C, 0x07, 0x34, 0x05, 0xC0, 0x70, 0x00, 0x93,
+0x06, 0x5C, 0x00, 0xF0, 0x81, 0xD0, 0x00, 0x10, 0x93, 0x86, 0x4D, 0x04, 0x30,
+0x0D, 0xC0, 0x37, 0x00, 0xD3, 0x04, 0x0D, 0x13, 0x31, 0x05, 0xC0, 0x54, 0x00,
+0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x88, 0x29, 0x00, 0xE1,
+0x00, 0xB4, 0x03, 0x10, 0x06, 0xC0, 0x3A, 0x10, 0xE1, 0x00, 0x84, 0x02, 0xD0,
+0x43, 0x40, 0x29, 0x00, 0xEB, 0x08, 0x84, 0x01, 0x51, 0x0E, 0x40, 0x3B, 0x01,
+0xF1, 0x08, 0x94, 0x43, 0x10, 0x0F, 0xC0, 0x4A, 0x20, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6D, 0x00, 0xA1, 0x01, 0xF6, 0x06, 0x10,
+0x16, 0x40, 0x6C, 0x10, 0xF0, 0x01, 0xB4, 0x04, 0xD0, 0x3A, 0x40, 0x4C, 0x00,
+0xC1, 0x01, 0xC6, 0x04, 0x10, 0x3E, 0x40, 0x73, 0x02, 0xE9, 0x01, 0x84, 0x03,
+0x10, 0x1E, 0x40, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x12, 0x28, 0x63, 0x00, 0x81, 0x04, 0x36, 0x16, 0x10, 0x14, 0x44, 0x22, 0x02,
+0xC1, 0x00, 0x24, 0x0B, 0xD1, 0x0D, 0x41, 0x30, 0x08, 0xC9, 0x00, 0x04, 0x1F,
+0x50, 0x1D, 0x40, 0x33, 0x10, 0xD9, 0x00, 0x15, 0x03, 0x10, 0xEC, 0x40, 0x4A,
+0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xA8, 0x1D, 0x01,
+0x73, 0x80, 0xFC, 0x05, 0x33, 0xE7, 0xCC, 0xDC, 0x40, 0x53, 0xC0, 0xBC, 0x15,
+0xF1, 0x27, 0xD0, 0x1C, 0x08, 0x53, 0x00, 0xCD, 0x05, 0x32, 0x17, 0xC0, 0x17,
+0x40, 0x5B, 0x00, 0x4C, 0x01, 0x30, 0x37, 0xC0, 0x5C, 0x20, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x07, 0x54, 0x1F, 0x00, 0x7C, 0x20,
+0xF0, 0x01, 0xC0, 0x07, 0x24, 0x1F, 0x02, 0x5C, 0x48, 0xF0, 0x01, 0xC0, 0x03,
+0x00, 0x1F, 0x00, 0x7C, 0x20, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x17, 0x20, 0x7C,
+0x80, 0xF0, 0x00, 0xC0, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x08, 0x27, 0x00, 0x9F, 0x00, 0x7C, 0x02, 0xF0, 0x09, 0xC0, 0x24,
+0x00, 0x9F, 0x05, 0x4C, 0x0E, 0x30, 0x09, 0xC0, 0x64, 0x20, 0x8A, 0x01, 0x6C,
+0x02, 0xF0, 0x09, 0xC8, 0x60, 0x00, 0x93, 0x00, 0x4C, 0x22, 0xF0, 0x89, 0xC2,
+0x40, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x26,
+0x00, 0x9D, 0x00, 0x70, 0x02, 0xD0, 0x09, 0x40, 0x25, 0x00, 0x8C, 0x00, 0x44,
+0x12, 0x10, 0x09, 0x40, 0x65, 0x08, 0x9B, 0x01, 0x6C, 0x02, 0xD0, 0xA9, 0x41,
+0xE4, 0x01, 0x91, 0x02, 0x45, 0x06, 0xD0, 0x19, 0x40, 0x04, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xA0, 0x24, 0x00, 0x9D, 0x20, 0x70,
+0x03, 0xD0, 0x0C, 0x40, 0x34, 0x00, 0x9C, 0x10, 0x44, 0x02, 0x14, 0x09, 0x40,
+0x24, 0x02, 0x9D, 0x48, 0x65, 0x12, 0xD2, 0x09, 0x40, 0x24, 0x42, 0x91, 0x14,
+0x44, 0x82, 0xD0, 0x0D, 0x44, 0x60, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0xA0, 0x10, 0x8D, 0x02, 0x34, 0x0A, 0xD0, 0x28, 0x40,
+0x21, 0x10, 0x9D, 0x14, 0x46, 0x02, 0x18, 0x48, 0x45, 0x21, 0x45, 0xCD, 0x14,
+0x24, 0x02, 0xD0, 0x48, 0x71, 0x20, 0x85, 0x81, 0x14, 0x04, 0x52, 0xD0, 0x48,
+0x41, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xB0,
+0x06, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0xD0, 0x00, 0x40, 0x04, 0x10, 0x1F, 0x04,
+0x4C, 0x00, 0x30, 0x41, 0xC4, 0x14, 0x21, 0x1F, 0x44, 0x6C, 0x00, 0xF1, 0x41,
+0xC0, 0x04, 0x01, 0x13, 0xC4, 0x4C, 0x10, 0xF0, 0x41, 0xD0, 0x74, 0xC0, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB8, 0x7B, 0x00, 0xFF, 0x01,
+0xBC, 0x06, 0xF0, 0x1B, 0xC0, 0x2F, 0x05, 0xAE, 0x00, 0xFD, 0x52, 0xF1, 0x4F,
+0xC1, 0x2F, 0x45, 0xBB, 0x14, 0xBC, 0x52, 0xF0, 0x4B, 0xC1, 0x27, 0x40, 0xBF,
+0x14, 0x7C, 0x02, 0xF2, 0x4B, 0xC1, 0x67, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x19, 0xA0, 0xA7, 0x00, 0x93, 0x02, 0x4C, 0x02, 0x30, 0x28,
+0xC0, 0xAF, 0x00, 0xAF, 0x01, 0xDC, 0x0A, 0xF0, 0x39, 0xC0, 0xED, 0x05, 0xB3,
+0x03, 0xDC, 0x02, 0x32, 0x5B, 0xC1, 0x2C, 0x00, 0xB3, 0x01, 0xCC, 0x06, 0x30,
+0x6A, 0xC0, 0x60, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
+0x08, 0x47, 0x01, 0x1B, 0x01, 0x6C, 0x14, 0xB0, 0x51, 0x40, 0x47, 0x00, 0x1D,
+0x02, 0x45, 0x04, 0xD1, 0x10, 0x40, 0xC0, 0x00, 0x11, 0x01, 0x45, 0x14, 0x10,
+0x75, 0xC0, 0x07, 0x10, 0x11, 0x05, 0x54, 0x00, 0x10, 0x61, 0x40, 0x70, 0x20,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x23, 0x00, 0x81,
+0x20, 0x04, 0x42, 0x10, 0x08, 0x40, 0x23, 0x08, 0x8D, 0x02, 0x14, 0x12, 0xD0,
+0x28, 0x40, 0x21, 0x00, 0x85, 0x02, 0x14, 0x46, 0x10, 0x08, 0x49, 0x21, 0x00,
+0x81, 0x12, 0x04, 0x0A, 0x10, 0x28, 0x40, 0x40, 0x80, 0x0E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0xA8, 0x21, 0x00, 0x89, 0x00, 0x24, 0x42, 0x90,
+0x09, 0x40, 0x27, 0x00, 0x9D, 0x04, 0x44, 0x12, 0xD0, 0x19, 0x40, 0xA4, 0x00,
+0x95, 0x00, 0x44, 0x02, 0x10, 0x09, 0x40, 0x27, 0x00, 0x90, 0x04, 0x54, 0x02,
+0x10, 0x39, 0x40, 0x60, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x05, 0xA8, 0x2F, 0x02, 0xB3, 0x00, 0xCC, 0x0A, 0x30, 0x0B, 0xC0, 0xA7, 0x04,
+0x9F, 0x01, 0x5C, 0x02, 0xF0, 0x29, 0xC8, 0x25, 0x40, 0x97, 0x00, 0x5C, 0x0A,
+0x34, 0x09, 0xC8, 0x25, 0x40, 0x93, 0x00, 0x4D, 0x02, 0x34, 0x29, 0xD0, 0x14,
+0x20, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x80, 0x65, 0x00,
+0x9F, 0x03, 0x7C, 0x0A, 0xE0, 0x09, 0xC0, 0xA7, 0x00, 0x8F, 0x00, 0x7C, 0x02,
+0xF0, 0x08, 0xC4, 0x27, 0x01, 0x8B, 0x45, 0x7C, 0x02, 0xF0, 0x98, 0xE0, 0x21,
+0x00, 0x9F, 0x00, 0x3C, 0x02, 0xF0, 0x09, 0xC0, 0x53, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x05, 0x00, 0x13, 0x00, 0x4D, 0x08,
+0xF0, 0x01, 0xC0, 0x04, 0x00, 0x13, 0x10, 0x6C, 0x00, 0xF0, 0x01, 0xD0, 0x04,
+0x40, 0x13, 0x00, 0x6C, 0x00, 0x30, 0x01, 0xC0, 0x04, 0x04, 0x03, 0x80, 0x7C,
+0x00, 0x34, 0x20, 0xC0, 0x50, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x14, 0xA0, 0x14, 0x10, 0x51, 0x00, 0x44, 0x01, 0xD0, 0x05, 0x40, 0x54,
+0x01, 0x75, 0x02, 0xC4, 0x05, 0xD0, 0x05, 0x50, 0xD8, 0x40, 0x75, 0x00, 0xC4,
+0x11, 0x10, 0x47, 0x50, 0x1C, 0x00, 0x71, 0x00, 0x74, 0x01, 0x10, 0x15, 0x40,
+0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA0, 0x32,
+0x00, 0xC1, 0x00, 0x04, 0x03, 0xD0, 0x0C, 0x40, 0x20, 0x00, 0xC1, 0x0A, 0x24,
+0x26, 0xD0, 0x0C, 0x44, 0xF0, 0x86, 0xC4, 0x09, 0x65, 0x07, 0x50, 0x0C, 0x00,
+0xF0, 0x00, 0xC5, 0x20, 0x34, 0x02, 0x10, 0x1C, 0x40, 0x50, 0x00, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x3C, 0x01, 0xF1, 0x04, 0x84,
+0xA3, 0xD0, 0x1F, 0x40, 0x78, 0x00, 0x25, 0x00, 0x84, 0x00, 0xD0, 0x4E, 0x40,
+0x28, 0x00, 0x65, 0x00, 0x85, 0x13, 0x50, 0x0A, 0x40, 0x90, 0x00, 0xA5, 0x00,
+0xB0, 0x02, 0x10, 0x0F, 0x41, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x15, 0x10, 0x78, 0x00, 0xE3, 0x07, 0x8C, 0x17, 0xF0, 0x7E, 0xD0,
+0x6C, 0x00, 0xA3, 0x01, 0xAC, 0x05, 0xF0, 0x3E, 0xC1, 0x68, 0x00, 0x77, 0x01,
+0xED, 0x0F, 0x74, 0x13, 0x84, 0x48, 0x00, 0xA7, 0x01, 0x3C, 0x06, 0x30, 0x1E,
+0xC0, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8,
+0x31, 0x40, 0xCF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC0, 0x3F, 0x00, 0x9F, 0x00,
+0xFD, 0x00, 0xF0, 0x2D, 0xC0, 0x27, 0x02, 0x5D, 0x00, 0x7C, 0x03, 0x90, 0x01,
+0xC0, 0x07, 0x40, 0x1B, 0x00, 0x7C, 0x02, 0xF0, 0x0D, 0xD0, 0x43, 0x60, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA0, 0x7F, 0x04, 0xF3, 0x01,
+0xCC, 0x27, 0x3C, 0x1F, 0xC0, 0x7B, 0x00, 0x37, 0x01, 0xDC, 0x06, 0x72, 0x1F,
+0xC0, 0x6D, 0x00, 0xF7, 0x81, 0xCC, 0x06, 0x31, 0x1B, 0xC0, 0x4C, 0x10, 0xE3,
+0x01, 0xCC, 0x06, 0xF0, 0x1F, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x15, 0x88, 0x39, 0x00, 0xE1, 0x00, 0xAC, 0x23, 0x18, 0x4E,
+0x40, 0x3B, 0x00, 0x21, 0x04, 0x84, 0x80, 0xD0, 0x4E, 0x40, 0x2C, 0x00, 0x61,
+0x02, 0x8C, 0x02, 0x10, 0x0A, 0x40, 0x09, 0x00, 0xAB, 0x00, 0x94, 0x02, 0xD0,
+0x0E, 0x40, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x00, 0x79, 0x00, 0xE1, 0x11, 0x84, 0x07, 0x12, 0x1E, 0x40, 0x3B, 0x00, 0x05,
+0x00, 0x90, 0x00, 0x50, 0x0E, 0x44, 0x09, 0x04, 0x3D, 0x10, 0x84, 0x03, 0x10,
+0x02, 0x41, 0x0A, 0x00, 0xA1, 0x00, 0x84, 0x02, 0xD0, 0x2E, 0x40, 0x03, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x28, 0x33, 0x40, 0xC1,
+0x10, 0x24, 0x03, 0x11, 0x8C, 0x40, 0x33, 0x00, 0x01, 0x00, 0x04, 0x0C, 0xD0,
+0x8C, 0x40, 0x80, 0x01, 0x09, 0x40, 0x24, 0x0F, 0x11, 0x11, 0x44, 0x03, 0x00,
+0x09, 0x00, 0x14, 0x02, 0xD0, 0x0C, 0x40, 0x13, 0x20, 0x0C, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1D, 0xA8, 0x35, 0x00, 0xD3, 0x00, 0x0C, 0x03, 0x30,
+0x3D, 0xC0, 0x37, 0x00, 0x87, 0x00, 0x5C, 0x1E, 0x70, 0x1F, 0xC0, 0x4D, 0x00,
+0x9F, 0x00, 0xCD, 0x13, 0x34, 0x09, 0xC0, 0x06, 0x08, 0xD3, 0x00, 0x4C, 0x03,
+0xF3, 0x0D, 0xC4, 0x57, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x37, 0x00, 0xDF, 0x00, 0x7C, 0x03, 0xF0, 0x0D, 0xC1, 0x37, 0x00,
+0x1F, 0x08, 0x7C, 0x40, 0xF0, 0x0D, 0xC4, 0x83, 0x00, 0x47, 0x00, 0x5C, 0x00,
+0xF0, 0x01, 0xC0, 0x85, 0x10, 0xCF, 0x00, 0x3C, 0x03, 0xF0, 0x8D, 0xC4, 0x07,
+0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x3F, 0x00,
+0xFF, 0x00, 0xCC, 0x03, 0x30, 0x0F, 0xC0, 0x3F, 0x00, 0xB3, 0x40, 0xEC, 0x00,
+0x30, 0x0D, 0xC0, 0x4D, 0x00, 0xB3, 0x02, 0xCC, 0x43, 0x10, 0x01, 0x40, 0x04,
+0x00, 0xBF, 0x01, 0xCC, 0x16, 0x30, 0x0F, 0xC0, 0x03, 0x22, 0x0C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x36, 0x00, 0xCD, 0x00, 0x44, 0x03,
+0x14, 0x0D, 0x44, 0x73, 0x02, 0x91, 0x01, 0x04, 0x04, 0x14, 0x0D, 0x50, 0x04,
+0x86, 0x51, 0x02, 0x6C, 0x3C, 0x50, 0x31, 0x40, 0xC5, 0x01, 0x1D, 0x01, 0x44,
+0x02, 0xB0, 0x09, 0x40, 0x07, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0xA0, 0x34, 0x00, 0xDD, 0x00, 0x44, 0x03, 0x10, 0x0D, 0x40, 0x37,
+0x00, 0x11, 0x01, 0x64, 0x06, 0x10, 0x0C, 0x4A, 0x04, 0x00, 0x95, 0x00, 0x04,
+0x02, 0x50, 0x39, 0x40, 0x45, 0x10, 0xDD, 0x04, 0x40, 0x03, 0x11, 0x1D, 0x40,
+0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30,
+0x00, 0xDD, 0x00, 0x45, 0x03, 0x10, 0x0C, 0x40, 0x37, 0x40, 0x01, 0x00, 0x44,
+0x00, 0x10, 0x0C, 0x40, 0x01, 0x80, 0x41, 0x00, 0x24, 0x00, 0x40, 0x00, 0x40,
+0x01, 0x00, 0xCD, 0x00, 0x05, 0x03, 0x80, 0x0C, 0x40, 0x43, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB0, 0x3A, 0x10, 0xEF, 0x00, 0x8C,
+0x03, 0x30, 0x0F, 0x40, 0x37, 0x00, 0x13, 0x00, 0x6C, 0x00, 0x38, 0x0F, 0xD0,
+0x04, 0x00, 0x95, 0x00, 0x0D, 0x03, 0x61, 0x01, 0x80, 0x05, 0x20, 0x9F, 0x00,
+0x4D, 0x02, 0x30, 0x0D, 0xC0, 0x03, 0xC0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x05, 0xB8, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0,
+0x3F, 0x20, 0x3F, 0x00, 0xFC, 0x00, 0xF1, 0x0F, 0xC0, 0x0E, 0x00, 0x2E, 0x00,
+0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x00, 0xFC, 0x02, 0xF1, 0x0F,
+0xC0, 0x17, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1,
+0x82, 0xC0, 0x0E, 0x02, 0x3B, 0x08, 0xE0, 0x28, 0xB0, 0x83, 0xE0, 0x0E, 0x82,
+0x38, 0x08, 0xEC, 0x20, 0x90, 0x83, 0xC8, 0x0E, 0x02, 0x1B, 0x08, 0xEC, 0x28,
+0xA8, 0x83, 0xA0, 0x0E, 0x02, 0x3A, 0x08, 0xCC, 0x20, 0x98, 0x03, 0x8C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x22, 0xA0, 0x8E, 0xA0,
+0x3A, 0x02, 0xEA, 0x08, 0xA0, 0x23, 0x20, 0x8E, 0xA0, 0x3B, 0x02, 0xEA, 0x08,
+0xA8, 0x23, 0xA0, 0x8E, 0xA0, 0x32, 0x02, 0x4A, 0x08, 0xA8, 0x23, 0x88, 0x8E,
+0x80, 0x3A, 0x02, 0xCA, 0x08, 0xA8, 0x03, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x18,
+0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04,
+0x01, 0x12, 0x04, 0x48, 0x18, 0x20, 0x41, 0xA0, 0x04, 0x01, 0x12, 0x04, 0x48,
+0x10, 0x20, 0x01, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x21, 0x00, 0x80, 0x02, 0x80, 0x1A, 0x00, 0x68, 0x00, 0xA0, 0x01, 0xA0, 0x0E,
+0x20, 0x1A, 0x00, 0x68, 0x00, 0xA0, 0x01, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x28,
+0x10, 0xA8, 0x01, 0x88, 0x06, 0x80, 0x1A, 0x00, 0x68, 0x00, 0x88, 0x01, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x12, 0xA0, 0x4E,
+0x80, 0x3A, 0x01, 0xEA, 0x14, 0xA0, 0x13, 0xA0, 0x4A, 0x80, 0x3A, 0x01, 0xEA,
+0x04, 0xA8, 0x13, 0xA0, 0x4E, 0x82, 0x3A, 0x01, 0xEA, 0x04, 0xA0, 0x13, 0x80,
+0x4A, 0x80, 0x3A, 0x01, 0xEA, 0x0C, 0xA8, 0x03, 0x8C, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60,
+0x00, 0x88, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00,
+0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00,
+0x60, 0x00, 0x80, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xA3, 0x20, 0x20, 0x04, 0x80, 0x10, 0x01, 0x42, 0x00, 0x08, 0x11, 0x20,
+0x04, 0x80, 0x10, 0x01, 0x42, 0x04, 0x08, 0x11, 0x20, 0xC0, 0x80, 0x10, 0x01,
+0x42, 0x00, 0x00, 0x11, 0x00, 0x04, 0x80, 0x10, 0x01, 0x42, 0x04, 0x08, 0x01,
+0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xD2, 0xA0,
+0x02, 0x01, 0x0A, 0x05, 0x2A, 0x10, 0xA8, 0x50, 0x80, 0x02, 0x01, 0x0A, 0x07,
+0x2A, 0x1C, 0xA8, 0x50, 0xA0, 0x42, 0x83, 0x0A, 0x05, 0x2A, 0x10, 0xA0, 0x50,
+0x88, 0x02, 0x01, 0x0A, 0x05, 0x2A, 0x3C, 0xA0, 0x00, 0x8C, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x30, 0x80, 0xC8, 0x00, 0xAA, 0x03,
+0xA8, 0x0E, 0x20, 0x38, 0x80, 0xE0, 0x00, 0xAA, 0x07, 0x08, 0x1E, 0xA0, 0x32,
+0x80, 0xCA, 0x00, 0x22, 0x03, 0xA8, 0x0C, 0xA0, 0x3A, 0xA0, 0xCA, 0x00, 0x2A,
+0x03, 0xA8, 0x0C, 0x20, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x21, 0x72, 0x00, 0x48, 0x20, 0x18, 0x80, 0x22, 0x00, 0x00, 0x00,
+0x08, 0x40, 0x20, 0x08, 0x02, 0x00, 0x08, 0x80, 0x00, 0x00, 0x82, 0x00, 0x20,
+0x00, 0x20, 0x04, 0x80, 0x00, 0x08, 0x42, 0x00, 0x18, 0x00, 0x20, 0x08, 0x00,
+0x82, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x16,
+0x40, 0x18, 0x00, 0x41, 0x00, 0x04, 0x01, 0x1A, 0x04, 0x40, 0x10, 0x20, 0x41,
+0x80, 0x04, 0x01, 0x10, 0x04, 0x40, 0x10, 0x00, 0x61, 0x00, 0x04, 0x01, 0x10,
+0x04, 0x08, 0x10, 0x00, 0x41, 0x00, 0x04, 0x01, 0x10, 0x82, 0x8C, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x02, 0xA0, 0x06, 0x80, 0x9A,
+0x00, 0x6A, 0x02, 0x28, 0x09, 0xA0, 0x24, 0x00, 0x9B, 0x00, 0x48, 0x02, 0xA8,
+0x01, 0xA0, 0x06, 0x00, 0x1A, 0x00, 0x6A, 0x00, 0xB8, 0x09, 0xA0, 0x06, 0xA0,
+0x1B, 0x00, 0x6A, 0x00, 0xA8, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA3, 0x00, 0xC0, 0x46, 0x00, 0x1A, 0x00, 0x6C, 0x00, 0xBC,
+0x01, 0x90, 0x46, 0x00, 0x1B, 0x00, 0x6C, 0x00, 0xA8, 0x01, 0xC0, 0x06, 0x20,
+0x1B, 0x80, 0x6C, 0x04, 0xA0, 0x01, 0xE8, 0x46, 0x00, 0x1A, 0x00, 0x6C, 0x00,
+0x32, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2,
+0x42, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x43, 0x20, 0x08, 0x81,
+0x30, 0x04, 0xC2, 0x10, 0x18, 0x43, 0x28, 0x0C, 0x01, 0x30, 0x04, 0xC2, 0x30,
+0x08, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x03, 0x8C, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x0C, 0x00,
+0x30, 0x00, 0xC0, 0x04, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0x80, 0x00,
+0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x08,
+0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x80, 0x0C, 0x83, 0x32, 0x04, 0xC8, 0x34,
+0x28, 0x43, 0x80, 0x0C, 0x83, 0x32, 0x04, 0xC8, 0x10, 0x20, 0x43, 0x80, 0x0C,
+0x01, 0x32, 0x04, 0xC8, 0x10, 0x28, 0x43, 0x80, 0x0C, 0x83, 0x32, 0x04, 0xC8,
+0x10, 0x20, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA3, 0x42, 0xA0, 0x06, 0x83, 0x1A, 0x04, 0x6A, 0x30, 0xA8, 0x41, 0xA0, 0x06,
+0x83, 0x1A, 0x04, 0x6A, 0x10, 0xA8, 0x41, 0xA0, 0x06, 0x81, 0x1A, 0x04, 0x6A,
+0x30, 0xA8, 0x41, 0x80, 0x0E, 0x83, 0x0A, 0x04, 0x6A, 0x10, 0xA8, 0x01, 0x8C,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x42, 0x00, 0x04,
+0x01, 0x30, 0x04, 0x40, 0x10, 0x00, 0x41, 0x00, 0x0C, 0x01, 0x30, 0x04, 0xC0,
+0x10, 0x00, 0x41, 0x00, 0x04, 0x01, 0x10, 0x04, 0x40, 0x10, 0x00, 0x43, 0x00,
+0x00, 0x01, 0x30, 0x04, 0x40, 0x10, 0x00, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x4A, 0x20, 0x06, 0x81, 0x30, 0x04, 0x62,
+0x12, 0x08, 0x4B, 0x20, 0x06, 0x81, 0xB0, 0x04, 0x62, 0x12, 0x88, 0x41, 0x20,
+0x26, 0x81, 0x18, 0x04, 0x62, 0x10, 0x08, 0x43, 0x00, 0x06, 0x81, 0x30, 0x04,
+0x62, 0x12, 0x88, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x23, 0x06, 0xA0, 0x1A, 0x00, 0x62, 0x00, 0xAA, 0x01, 0x20, 0x04, 0xA0,
+0x18, 0x00, 0x62, 0x00, 0x8A, 0x01, 0xA0, 0x06, 0xA0, 0x1A, 0x80, 0x6A, 0x80,
+0xAA, 0x01, 0x20, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0xAA, 0x01, 0xA8, 0x02,
+0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x60, 0x80,
+0x82, 0x01, 0x2A, 0x06, 0x28, 0x18, 0xA0, 0x60, 0x80, 0x82, 0x01, 0x0A, 0x06,
+0x28, 0x18, 0xA0, 0x60, 0x00, 0x82, 0x01, 0x0A, 0x06, 0x28, 0x18, 0xA0, 0x60,
+0xA0, 0x82, 0x01, 0x0A, 0x06, 0x28, 0x18, 0xA0, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x48, 0x12, 0x20, 0x49, 0xA0, 0x00, 0x01, 0x92, 0x04, 0x48, 0x12, 0x28, 0x41,
+0x80, 0x20, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x88, 0x00, 0x01, 0x02,
+0x04, 0x08, 0x12, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA3, 0x62, 0xC0, 0x8A, 0x01, 0x01, 0x06, 0xAC, 0x18, 0xB0, 0x63,
+0xC0, 0x8A, 0x01, 0x2B, 0x06, 0x8C, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2A,
+0x06, 0xAC, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0x8C, 0x18, 0xB0,
+0x02, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x62,
+0xA0, 0x8E, 0x01, 0x3B, 0x06, 0xEA, 0x18, 0xA8, 0x63, 0xA0, 0x8E, 0x81, 0x3A,
+0x06, 0x68, 0x18, 0x88, 0x63, 0xA0, 0x8E, 0x81, 0x3A, 0x06, 0xEA, 0x18, 0x98,
+0x63, 0x20, 0x8E, 0x81, 0x3B, 0x06, 0xCA, 0x18, 0x88, 0x03, 0x8C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x62, 0x80, 0x8E, 0x01, 0x3A,
+0x06, 0xEC, 0x18, 0xA0, 0x61, 0xC0, 0x8E, 0x01, 0x3A, 0x06, 0xE8, 0x18, 0xA0,
+0x63, 0xE0, 0x8E, 0x01, 0x1B, 0x06, 0xE0, 0x18, 0xA0, 0x63, 0xC0, 0x8E, 0x01,
+0x3A, 0x06, 0xEE, 0x18, 0xB0, 0x03, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xA2, 0x62, 0xA0, 0x8E, 0x81, 0x32, 0x06, 0xEA, 0x18, 0x08,
+0x63, 0xA0, 0x8E, 0xA1, 0x38, 0x86, 0xEA, 0x18, 0x28, 0x61, 0x20, 0x8E, 0x81,
+0x32, 0x86, 0xE8, 0x18, 0xA8, 0x63, 0xA0, 0x8E, 0xA1, 0x30, 0x06, 0xEA, 0x18,
+0xA8, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x40, 0x80, 0x04, 0x01, 0x1A, 0x84, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01,
+0x32, 0x04, 0x48, 0x10, 0x22, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10,
+0x20, 0x41, 0x88, 0x04, 0x01, 0x3A, 0x04, 0x48, 0x10, 0x20, 0x01, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x86, 0x81,
+0x1A, 0x06, 0x68, 0x18, 0xA0, 0x61, 0x80, 0x86, 0x81, 0x18, 0x06, 0x68, 0x18,
+0xA0, 0x61, 0x80, 0x84, 0x01, 0x1A, 0x06, 0x68, 0x18, 0xA8, 0x61, 0x80, 0x86,
+0x81, 0x1A, 0x06, 0x6A, 0x18, 0xA0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xA2, 0x02, 0xA0, 0x0E, 0x80, 0x3A, 0x00, 0xCA, 0x00,
+0x22, 0x03, 0xA0, 0x0C, 0x80, 0x32, 0x00, 0xCA, 0x00, 0x28, 0x03, 0x80, 0x0E,
+0x80, 0x2A, 0x00, 0xEA, 0x00, 0xA8, 0x03, 0xA0, 0x0E, 0x80, 0x3A, 0x00, 0xE8,
+0x00, 0xA8, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA2, 0x42, 0x00, 0x06, 0x01, 0x08, 0x04, 0x40, 0x10, 0x08, 0x41, 0x00, 0x04,
+0x01, 0x00, 0x0C, 0x40, 0x10, 0x80, 0x41, 0x00, 0x06, 0x01, 0x18, 0x04, 0x60,
+0x10, 0x80, 0x41, 0x00, 0x04, 0x01, 0x18, 0x04, 0x60, 0x10, 0x80, 0x01, 0x88,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x42, 0x20, 0x04,
+0x81, 0x10, 0x04, 0x22, 0x10, 0x88, 0x51, 0x20, 0x06, 0x81, 0x18, 0x05, 0x62,
+0x10, 0x08, 0x41, 0x00, 0x04, 0x81, 0x10, 0x04, 0x42, 0x10, 0x0A, 0x41, 0x20,
+0x06, 0x81, 0x10, 0x04, 0x40, 0x10, 0x08, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x42, 0xA0, 0x02, 0x01, 0x0A, 0x0C, 0xAA,
+0x30, 0xA8, 0xC2, 0xA0, 0x0A, 0x03, 0x2A, 0x04, 0xAA, 0x30, 0xA8, 0x42, 0xA0,
+0x02, 0x81, 0x0A, 0x04, 0x2A, 0x10, 0xA0, 0xC0, 0xA0, 0x02, 0x21, 0x0A, 0x04,
+0x28, 0x10, 0xA8, 0x00, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0x80, 0x0A, 0x03, 0x2A, 0x0C, 0xA8, 0x10, 0xA0, 0x52, 0x80,
+0x0A, 0x03, 0x2A, 0x05, 0xA8, 0x30, 0xA0, 0xC2, 0x80, 0x0A, 0x01, 0x2A, 0x0C,
+0xA8, 0x30, 0xA0, 0xC2, 0x80, 0x0A, 0x03, 0x2A, 0x0C, 0xA8, 0x10, 0xA0, 0x02,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x42, 0x00, 0x08, 0x00, 0x20, 0x00, 0x88, 0x01, 0x00, 0x02, 0x00, 0x08, 0x80,
+0x20, 0x00, 0x88, 0x10, 0x00, 0x42, 0x20, 0x08, 0x01, 0x20, 0x04, 0x82, 0x00,
+0x00, 0x42, 0x00, 0x08, 0x01, 0x20, 0x04, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x42, 0x40, 0x00, 0x01, 0x01, 0x04,
+0x04, 0x10, 0x10, 0x41, 0x40, 0x44, 0x01, 0x01, 0x04, 0x04, 0x14, 0x10, 0x40,
+0x40, 0x00, 0x01, 0x01, 0x04, 0x00, 0x10, 0x10, 0x50, 0x40, 0x00, 0x01, 0x01,
+0x04, 0x04, 0x10, 0x10, 0x00, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xA2, 0x02, 0xE0, 0x06, 0x80, 0x1B, 0x00, 0x68, 0x00, 0xA8, 0x01,
+0xA0, 0x06, 0x80, 0x1B, 0x00, 0x6E, 0x00, 0xA8, 0x01, 0x80, 0x06, 0x80, 0x1A,
+0x00, 0x6E, 0x00, 0xB8, 0x01, 0xA0, 0x06, 0x80, 0x1B, 0x00, 0x6A, 0x00, 0xA8,
+0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x02,
+0xC0, 0x06, 0x00, 0x3B, 0x00, 0x6C, 0x00, 0xA0, 0x01, 0xC0, 0x06, 0x00, 0x3A,
+0x00, 0x68, 0x00, 0xB0, 0x01, 0xC0, 0x06, 0x00, 0x1A, 0x00, 0x6C, 0x00, 0xA0,
+0x03, 0xC0, 0x06, 0x00, 0x3A, 0x00, 0x4C, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0C, 0x80, 0x18,
+0x00, 0xC2, 0x00, 0x08, 0x01, 0x28, 0x0C, 0x80, 0x18, 0x80, 0xC0, 0x00, 0x08,
+0x03, 0x20, 0x0C, 0x82, 0x38, 0x00, 0xC2, 0x00, 0x88, 0x01, 0x20, 0x0C, 0x80,
+0x18, 0x00, 0xC2, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x10, 0x00, 0xC0, 0x02, 0x00,
+0x63, 0x00, 0x2C, 0x00, 0x10, 0x00, 0xC2, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00,
+0x10, 0x00, 0xC0, 0x02, 0x00, 0x21, 0x00, 0x2C, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x80, 0x8C, 0x82, 0x32, 0x0A, 0xC8, 0x08, 0x20, 0x21, 0x80, 0x8C, 0x82,
+0x32, 0x02, 0x88, 0x28, 0x20, 0xA3, 0x80, 0x8C, 0x02, 0x22, 0x0A, 0xC8, 0x28,
+0x28, 0xA3, 0x80, 0x8C, 0x82, 0x32, 0x0A, 0xC8, 0x08, 0x20, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xA0, 0x16, 0x83,
+0x5A, 0x0C, 0x6A, 0x31, 0xA0, 0xC4, 0xA0, 0x16, 0x83, 0x5A, 0x0C, 0x6A, 0x31,
+0xA8, 0xC5, 0xA0, 0x16, 0x83, 0x4A, 0x0C, 0x6A, 0x31, 0xA8, 0xE5, 0xA0, 0x16,
+0x83, 0x5A, 0x0C, 0x6A, 0x31, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x10, 0x01, 0x40, 0x02,
+0x08, 0x21, 0x00, 0x64, 0x00, 0x10, 0x00, 0x40, 0x04, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x91, 0x00, 0x24, 0x00, 0x00, 0x00, 0x40,
+0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x22, 0x46, 0x88, 0x18, 0x21, 0x62, 0x80, 0x8A, 0x01, 0x26, 0x06,
+0x88, 0x18, 0x20, 0x62, 0x80, 0x88, 0x11, 0x22, 0x46, 0x88, 0x18, 0x21, 0x62,
+0x84, 0x88, 0x01, 0x22, 0x46, 0x88, 0x18, 0x21, 0x62, 0x84, 0x88, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x0A,
+0x08, 0x2A, 0x20, 0xAA, 0x80, 0x88, 0x02, 0xA2, 0x0A, 0x08, 0x2A, 0x20, 0xAA,
+0x00, 0xAA, 0x02, 0xA2, 0x0A, 0x88, 0x28, 0x20, 0xAA, 0x80, 0xA0, 0x02, 0xA6,
+0x0A, 0x08, 0x2A, 0x20, 0xAA, 0x80, 0xA8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0x42, 0x10, 0x0A, 0x41, 0x28,
+0x44, 0xA1, 0x10, 0x8C, 0x4A, 0x10, 0x2A, 0x41, 0x28, 0x04, 0xA1, 0x10, 0x04,
+0x42, 0x10, 0x0A, 0x41, 0x28, 0x84, 0x81, 0x10, 0x84, 0x4A, 0x10, 0x0A, 0x41,
+0x20, 0x04, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x50, 0x80, 0x40, 0x01, 0x02, 0x05, 0x00, 0x14, 0x00, 0x50, 0x80,
+0x40, 0x01, 0x02, 0x05, 0x00, 0x14, 0x00, 0x50, 0x80, 0x40, 0x01, 0x02, 0x05,
+0x08, 0x14, 0x20, 0x50, 0x80, 0x40, 0x01, 0x02, 0x05, 0x08, 0x14, 0x20, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0,
+0xCA, 0x20, 0x2B, 0x03, 0x8C, 0x0C, 0x30, 0x32, 0x40, 0xC0, 0x00, 0x01, 0x03,
+0x88, 0x0C, 0x30, 0x32, 0xC0, 0xCA, 0x00, 0x2B, 0x03, 0xAC, 0x0C, 0xB0, 0x32,
+0x40, 0xC0, 0x00, 0x2B, 0x03, 0xAC, 0x0C, 0xB0, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA4, 0x4E, 0x80, 0x3A, 0x01,
+0xEA, 0x04, 0xB8, 0x13, 0xA0, 0x4E, 0x80, 0x3B, 0x41, 0xEA, 0x04, 0xA8, 0x13,
+0xA0, 0x4E, 0x84, 0x3B, 0x01, 0xEA, 0x04, 0xB8, 0x13, 0xA0, 0x4E, 0x80, 0x3B,
+0x01, 0xE2, 0x44, 0xA8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xC4, 0x10, 0x12, 0x23, 0x08, 0x8C, 0x21, 0x30, 0x80, 0xC0,
+0x10, 0x02, 0x23, 0x08, 0x0C, 0x21, 0x30, 0x84, 0xC4, 0x18, 0x12, 0x43, 0x48,
+0x8C, 0x21, 0x31, 0x82, 0xC0, 0x18, 0x12, 0xA3, 0x48, 0x8C, 0x21, 0x31, 0x84,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
+0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB,
+0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF,
+0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xB4, 0xDF, 0xD0, 0x6C, 0x43, 0xB3, 0x0D, 0xCD, 0xBE,
+0x7C, 0xDB, 0xD0, 0x6C, 0x43, 0xFB, 0x0D, 0xED, 0x37, 0x34, 0xDB, 0xD0, 0x7E,
+0x43, 0xB3, 0x0D, 0xCD, 0xBE, 0x7C, 0xDB, 0xD0, 0x6C, 0x43, 0xB3, 0x0D, 0xED,
+0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xCC, 0x3F, 0x32, 0xF3, 0xC8, 0xCC, 0x23, 0x33, 0xBF, 0xFC, 0x3C, 0x32, 0xF3,
+0xC8, 0xFC, 0x23, 0xF3, 0x8F, 0xCC, 0x3C, 0x32, 0xFF, 0xC8, 0xCC, 0x23, 0x33,
+0xBF, 0xFC, 0x3C, 0x32, 0xF3, 0xC8, 0xCC, 0x23, 0xF3, 0x8F, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x78, 0x72, 0x7B,
+0x48, 0xEC, 0x27, 0x31, 0x86, 0xC4, 0x78, 0x12, 0x7B, 0x48, 0x8C, 0x27, 0xB1,
+0x9F, 0xDC, 0x7E, 0x72, 0xE3, 0xC9, 0xED, 0x27, 0xB7, 0x87, 0xC4, 0x7E, 0x72,
+0x7B, 0xC8, 0xED, 0x27, 0x37, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x8E, 0x02, 0x39, 0x08, 0xE4, 0x20,
+0x80, 0x83, 0x40, 0x0E, 0x02, 0x39, 0x08, 0xE4, 0x20, 0x90, 0x83, 0x40, 0x0E,
+0x02, 0x39, 0x08, 0xE0, 0x20, 0x90, 0x83, 0x40, 0x8E, 0x02, 0x39, 0x0A, 0xE0,
+0x28, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x20, 0xA0, 0x8E, 0x81, 0x3A, 0x02, 0xEA, 0x08, 0xA8, 0x23, 0xA0, 0x8E,
+0x80, 0x3A, 0x02, 0xEA, 0x08, 0xA8, 0x23, 0xA0, 0x8E, 0x80, 0x3A, 0x02, 0xEA,
+0x08, 0xAA, 0x23, 0xA0, 0x8E, 0x81, 0x3A, 0x06, 0xEA, 0x18, 0xB8, 0x03, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x04,
+0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48,
+0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x10, 0x20, 0x41, 0x80,
+0x84, 0x01, 0x12, 0x06, 0x48, 0x18, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x18, 0x00, 0x60,
+0x00, 0x88, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x20,
+0x06, 0x00, 0x18, 0x00, 0x62, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00,
+0x62, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x20, 0x4E, 0x80, 0x38, 0x01, 0xE2, 0x04, 0x88, 0x93, 0x20,
+0x4E, 0x80, 0x38, 0x01, 0xE2, 0x04, 0x88, 0x13, 0x20, 0x4A, 0x80, 0x38, 0x01,
+0xE2, 0x04, 0x88, 0x13, 0x20, 0x4E, 0x80, 0x38, 0x01, 0xE2, 0x04, 0x88, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00,
+0x60, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01,
+0x00, 0x06, 0x00, 0x18, 0x08, 0x60, 0x28, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x64, 0x80, 0x10, 0x01,
+0x42, 0x0A, 0x08, 0x31, 0x20, 0x44, 0x80, 0x10, 0x01, 0x42, 0x0C, 0x08, 0x09,
+0x20, 0x44, 0x80, 0x90, 0x00, 0x42, 0x04, 0x08, 0x11, 0x20, 0x64, 0x80, 0x90,
+0x00, 0x42, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xD4, 0x20, 0x52, 0x81, 0x48, 0x05, 0x22, 0x11, 0x80, 0x54,
+0x20, 0x52, 0x81, 0x48, 0x05, 0x22, 0x15, 0x88, 0x44, 0x00, 0x52, 0x81, 0x48,
+0x04, 0x20, 0x15, 0x88, 0x54, 0x20, 0x52, 0x81, 0x48, 0x0C, 0x20, 0x11, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x30,
+0x00, 0xC8, 0x00, 0x28, 0x03, 0xA0, 0x3C, 0x20, 0x30, 0x00, 0xCA, 0x00, 0x00,
+0x03, 0xA0, 0x0C, 0x80, 0x32, 0x00, 0xCA, 0x00, 0x28, 0x03, 0xA0, 0x0C, 0x80,
+0x32, 0x00, 0xCA, 0x00, 0x28, 0x03, 0xA0, 0x04, 0x00, 0x02, 0x08, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x28, 0x00, 0x08,
+0x00, 0x20, 0x0E, 0x80, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x18, 0x80,
+0x18, 0x00, 0x02, 0x00, 0x88, 0x01, 0x60, 0x00, 0x80, 0x00, 0x00, 0x22, 0x00,
+0x88, 0x01, 0x20, 0x0A, 0x08, 0x02, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x03, 0x02, 0x40, 0x08, 0x00, 0x01, 0x00, 0x04, 0x20, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x02, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03,
+0x02, 0x20, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x98, 0x01, 0x20, 0x06, 0x80,
+0x10, 0x00, 0x62, 0x00, 0x88, 0x01, 0x20, 0x06, 0x80, 0x18, 0x00, 0x66, 0x00,
+0x88, 0x01, 0x20, 0x06, 0x80, 0x18, 0x00, 0x66, 0x00, 0x88, 0x01, 0x0C, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x02, 0x40, 0x06, 0x00,
+0x19, 0x00, 0x64, 0x04, 0x80, 0x01, 0x40, 0x06, 0x00, 0x18, 0x00, 0x64, 0x00,
+0x90, 0x11, 0x00, 0x06, 0x00, 0x19, 0x01, 0x60, 0x00, 0x90, 0x01, 0x40, 0x06,
+0x00, 0x19, 0x01, 0x62, 0x00, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0xA2, 0x42, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10,
+0x08, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x43, 0x28, 0x0C,
+0x81, 0x30, 0x04, 0xC2, 0x10, 0x08, 0x43, 0x20, 0x0C, 0x81, 0x30, 0x04, 0xC2,
+0x10, 0x18, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x00, 0x00, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x0C,
+0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0,
+0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x04, 0x00, 0x03, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x0C,
+0x01, 0x30, 0x04, 0xC0, 0x30, 0x08, 0x43, 0x00, 0x0C, 0x01, 0x30, 0x04, 0xC0,
+0x10, 0x00, 0xC3, 0x20, 0x0C, 0x01, 0x30, 0x0C, 0xC2, 0x10, 0x00, 0x43, 0x00,
+0x0C, 0x01, 0x30, 0x0C, 0xC2, 0x34, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x42, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62,
+0x30, 0x88, 0x41, 0x20, 0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x88, 0xC1, 0x20,
+0x06, 0x81, 0x18, 0x0C, 0x62, 0x10, 0x88, 0x41, 0x20, 0x06, 0x81, 0x18, 0x0C,
+0x60, 0x10, 0x88, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x80, 0x42, 0x00, 0x04, 0x01, 0x10, 0x04, 0x40, 0x10, 0x00, 0x43, 0x00,
+0x04, 0x01, 0x10, 0x04, 0x40, 0x10, 0x00, 0x41, 0x00, 0x0C, 0x01, 0x10, 0x04,
+0xC0, 0x10, 0x00, 0x41, 0x00, 0x04, 0x01, 0x10, 0x04, 0xC0, 0x10, 0x80, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x42, 0x20,
+0x06, 0x81, 0x18, 0x04, 0x62, 0x10, 0x08, 0x43, 0x20, 0x06, 0x81, 0x18, 0x04,
+0x62, 0x10, 0x88, 0x41, 0x20, 0x0C, 0x81, 0x18, 0x04, 0xC2, 0x10, 0x88, 0x41,
+0x20, 0x06, 0x81, 0x18, 0x04, 0xC0, 0x30, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x02, 0x20, 0x0A, 0x80, 0x28, 0x00,
+0xA2, 0x00, 0x00, 0x02, 0x20, 0x0A, 0x80, 0x28, 0x00, 0xA2, 0x00, 0x88, 0x02,
+0x00, 0x08, 0x80, 0x28, 0x00, 0x80, 0x00, 0x88, 0x02, 0x20, 0x0A, 0x80, 0x28,
+0x80, 0x80, 0x00, 0x00, 0x42, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x00, 0x60, 0x00, 0x82, 0x01, 0x08, 0x06, 0x20, 0x18, 0x80, 0x60,
+0x00, 0x82, 0x01, 0x08, 0x06, 0x20, 0x18, 0x80, 0x60, 0x00, 0x82, 0x01, 0x08,
+0x06, 0x20, 0x18, 0x80, 0x60, 0x00, 0x82, 0x01, 0x08, 0x06, 0x20, 0x18, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x40,
+0x80, 0x00, 0x01, 0x12, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x81, 0x02,
+0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x48, 0x10, 0x20,
+0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x62, 0xC0, 0x8A, 0x01, 0x2B,
+0x06, 0xAC, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0xAC, 0x18, 0xB0,
+0x62, 0xC0, 0x8A, 0x01, 0x2B, 0x06, 0xAC, 0x18, 0xB0, 0x62, 0xC0, 0x8A, 0x01,
+0x2B, 0x06, 0xAC, 0x18, 0xB0, 0x02, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x62, 0x20, 0x8E, 0x81, 0x38, 0x06, 0xE2, 0x18, 0x98,
+0x63, 0x20, 0x8E, 0x81, 0x38, 0x06, 0xE2, 0x18, 0x88, 0x63, 0x40, 0x8E, 0x81,
+0x38, 0x06, 0xE6, 0x18, 0x88, 0x63, 0x20, 0x8E, 0x81, 0x38, 0x86, 0xE6, 0x18,
+0x88, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80,
+0x62, 0x40, 0x8E, 0x01, 0x39, 0x06, 0xE0, 0x18, 0xA0, 0x63, 0x40, 0x8E, 0x01,
+0x39, 0x06, 0xE4, 0x18, 0x90, 0x63, 0x00, 0x8E, 0x01, 0x39, 0x06, 0xE0, 0x18,
+0x90, 0x63, 0x40, 0x8E, 0x01, 0x39, 0x06, 0xE0, 0x18, 0x80, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xA2, 0x62, 0xA0, 0x8E, 0x81,
+0x3A, 0x06, 0xE8, 0x18, 0x88, 0x63, 0xA0, 0x8E, 0xA1, 0x3A, 0x06, 0xEA, 0x18,
+0xA8, 0x63, 0x20, 0x8C, 0x81, 0x3A, 0x06, 0xC2, 0x18, 0xA8, 0x63, 0xA0, 0x8E,
+0x81, 0x3A, 0x06, 0xC2, 0x18, 0x18, 0x43, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x00, 0x48, 0x80, 0x04, 0x01, 0x12, 0x04, 0x48, 0x12,
+0x20, 0x4B, 0x80, 0x24, 0x01, 0x12, 0x04, 0x48, 0x12, 0x20, 0x41, 0x80, 0x0E,
+0x01, 0x12, 0x04, 0xE8, 0x10, 0x20, 0x41, 0x80, 0x04, 0x01, 0x12, 0x04, 0xE8,
+0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0x00, 0x60, 0x00, 0x86, 0x01, 0x18, 0x06, 0x60, 0x18, 0x88, 0x61, 0x00, 0x86,
+0x01, 0x18, 0x06, 0x60, 0x18, 0x80, 0x61, 0x20, 0x86, 0x01, 0x18, 0x06, 0x62,
+0x18, 0x80, 0x61, 0x00, 0x86, 0x01, 0x18, 0x06, 0x62, 0x18, 0x00, 0x01, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x06, 0x20, 0x1E,
+0x80, 0x70, 0x00, 0xE2, 0x01, 0x08, 0x07, 0x20, 0x1E, 0x80, 0x70, 0x00, 0xE2,
+0x01, 0x88, 0x07, 0x20, 0x1E, 0x80, 0x78, 0x00, 0xC2, 0x01, 0x88, 0x07, 0x20,
+0x1E, 0x80, 0x78, 0x00, 0xC2, 0x01, 0x88, 0x03, 0x88, 0x0A, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x4A, 0x00, 0x06, 0x01, 0x10, 0x04, 0x60,
+0x12, 0x00, 0x49, 0x00, 0x26, 0x01, 0x10, 0x04, 0x60, 0x12, 0x80, 0x41, 0x00,
+0x06, 0x01, 0x18, 0x04, 0x40, 0x10, 0x80, 0x41, 0x00, 0x06, 0x01, 0x18, 0x04,
+0x40, 0x12, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x80, 0x42, 0x20, 0x04, 0x81, 0x18, 0x04, 0x42, 0x10, 0x88, 0x41, 0x20,
+0x44, 0x81, 0x18, 0x04, 0x42, 0x10, 0x08, 0x41, 0x20, 0x04, 0x81, 0x10, 0x04,
+0x62, 0x10, 0x08, 0x41, 0x20, 0x04, 0x81, 0x10, 0x04, 0x62, 0x10, 0x08, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x42, 0x20,
+0x02, 0x83, 0x28, 0x04, 0x22, 0x30, 0x80, 0x42, 0x20, 0x02, 0x83, 0x28, 0x04,
+0x22, 0x10, 0x88, 0x40, 0x00, 0x02, 0x81, 0x08, 0x0C, 0xA0, 0x10, 0x88, 0x40,
+0x20, 0x02, 0x81, 0x08, 0x0C, 0xA0, 0x10, 0x80, 0x00, 0x88, 0x0A, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0x0A, 0x03, 0x28, 0x0C,
+0xA0, 0x30, 0x80, 0xC2, 0x00, 0x4A, 0x01, 0x28, 0x0C, 0xA0, 0x30, 0x80, 0xC2,
+0x00, 0x0A, 0x03, 0x28, 0x0C, 0xA0, 0x30, 0x80, 0xC2, 0x00, 0x0A, 0x03, 0x28,
+0x0C, 0xA0, 0x10, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x10, 0x00, 0x06, 0x00, 0x08, 0x01, 0x20, 0x00, 0x80, 0x10,
+0x00, 0x02, 0x00, 0x08, 0x01, 0x20, 0x04, 0x80, 0x10, 0x00, 0x42, 0x00, 0x08,
+0x00, 0x20, 0x04, 0x80, 0x10, 0x00, 0x42, 0x00, 0x08, 0x00, 0x20, 0x04, 0x88,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2, 0x42,
+0x40, 0x40, 0x01, 0x01, 0x04, 0x00, 0x14, 0x10, 0x40, 0x40, 0x00, 0x01, 0x01,
+0x04, 0x04, 0x10, 0x10, 0x40, 0x40, 0x00, 0x01, 0x01, 0x05, 0x04, 0x10, 0x10,
+0x40, 0x40, 0x00, 0x01, 0x01, 0x05, 0x04, 0x10, 0x10, 0x00, 0x88, 0x0A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x20, 0x06, 0x80, 0x18,
+0x00, 0x66, 0x00, 0x98, 0x01, 0x20, 0x06, 0x80, 0x18, 0x00, 0x62, 0x00, 0x88,
+0x01, 0x60, 0x06, 0x80, 0x18, 0x00, 0x66, 0x00, 0x88, 0x01, 0x20, 0x06, 0x80,
+0x18, 0x00, 0x66, 0x00, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x02, 0x80, 0x02, 0x40, 0x26, 0x00, 0x99, 0x00, 0x64, 0x02, 0x80,
+0x0B, 0x40, 0x26, 0x00, 0x99, 0x00, 0x64, 0x00, 0x90, 0x01, 0x00, 0x0E, 0x00,
+0x98, 0x00, 0xE0, 0x00, 0x90, 0x01, 0x40, 0x06, 0x80, 0x99, 0x00, 0xE0, 0x00,
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xA2,
+0x06, 0x20, 0x1C, 0x80, 0x70, 0x00, 0xC2, 0x01, 0x88, 0x05, 0x20, 0x1C, 0x82,
+0x70, 0x00, 0xC2, 0x01, 0x08, 0x07, 0x20, 0x16, 0x00, 0x70, 0x00, 0x62, 0x01,
+0x08, 0x07, 0x28, 0x1C, 0x00, 0x70, 0x00, 0x62, 0x01, 0x18, 0x01, 0x88, 0x0A,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x80, 0x00, 0x0C, 0x02,
+0x30, 0x0E, 0xC0, 0x20, 0x00, 0xE1, 0x00, 0x0C, 0x02, 0x30, 0x0A, 0xC0, 0x20,
+0x00, 0x83, 0x00, 0x04, 0x02, 0x30, 0x08, 0x40, 0x20, 0x00, 0x83, 0x00, 0x0C,
+0x02, 0x30, 0x0A, 0x40, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xAC, 0x02, 0xB0, 0x0A, 0xC0, 0x2A,
+0x08, 0xAB, 0x00, 0xAC, 0x02, 0xB0, 0x0A, 0xC0, 0x28, 0x00, 0xA3, 0x20, 0x8C,
+0x02, 0xB0, 0x0A, 0xC2, 0x28, 0x00, 0xA3, 0x00, 0x8C, 0x82, 0xB0, 0x1E, 0xC2,
+0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xA2, 0xC2, 0x20, 0x06, 0x83, 0x18, 0x0E, 0x62, 0x30, 0x88, 0xE1, 0x20, 0x06,
+0x83, 0x18, 0x0E, 0x62, 0x30, 0x88, 0xC1, 0x20, 0x06, 0x83, 0x18, 0x0C, 0x62,
+0x30, 0x88, 0xC1, 0x20, 0x06, 0x03, 0x18, 0x1E, 0x62, 0x30, 0x88, 0x01, 0x88,
+0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x00, 0x44,
+0x00, 0x10, 0x00, 0x40, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x08, 0x40,
+0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x12, 0x22, 0x06, 0x88, 0x18, 0x01, 0x62,
+0x80, 0x88, 0x11, 0x20, 0x06, 0x88, 0x18, 0x01, 0x62, 0x84, 0x88, 0x11, 0x22,
+0x46, 0x88, 0x18, 0x20, 0x62, 0x84, 0x88, 0x11, 0x22, 0x46, 0x08, 0x18, 0x40,
+0x62, 0x84, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0xA2, 0x02, 0x22, 0x0A, 0x88, 0x28, 0x20, 0xA2, 0x00, 0x80, 0x02, 0x20,
+0x0A, 0x88, 0x28, 0x20, 0xA2, 0x00, 0x88, 0x02, 0x02, 0x0A, 0x88, 0x28, 0x20,
+0xA0, 0x80, 0x88, 0x02, 0x22, 0x0A, 0x08, 0x28, 0x20, 0xA0, 0x40, 0x80, 0x02,
+0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x04,
+0x42, 0x00, 0x28, 0x41, 0x20, 0x04, 0x81, 0x12, 0x04, 0x42, 0x10, 0x0A, 0x41,
+0x20, 0x04, 0x81, 0x10, 0x04, 0x42, 0x10, 0x08, 0x41, 0xA0, 0x04, 0x81, 0x10,
+0x04, 0x42, 0x00, 0x08, 0x00, 0xA0, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x80, 0x40, 0x01, 0x00, 0x05,
+0x08, 0x14, 0x00, 0x50, 0x80, 0x40, 0x01, 0x00, 0x05, 0x08, 0x14, 0x20, 0x50,
+0x80, 0x40, 0x01, 0x02, 0x05, 0x00, 0x14, 0x20, 0x50, 0x80, 0x40, 0x01, 0x02,
+0x6D, 0x00, 0x94, 0x28, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0xA2, 0xB2, 0xC0, 0xCA, 0x02, 0x21, 0x0B, 0xAC, 0x2C, 0x10, 0xB2,
+0xC0, 0xCA, 0x02, 0x23, 0x0B, 0xAC, 0x2C, 0xB0, 0xB2, 0xC0, 0xCA, 0x02, 0x2A,
+0x0B, 0x84, 0x2C, 0xB0, 0xB2, 0xC0, 0xCA, 0x02, 0x2A, 0x2B, 0x84, 0x6C, 0xB0,
+0x02, 0x88, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x12,
+0x20, 0x4E, 0x80, 0x38, 0x01, 0xE2, 0x04, 0x98, 0x13, 0x20, 0x4E, 0x80, 0x38,
+0x01, 0xE2, 0x04, 0x80, 0x13, 0x60, 0x4E, 0x80, 0x39, 0x01, 0xE6, 0x04, 0x88,
+0x13, 0x20, 0x4E, 0x80, 0x38, 0x09, 0xE6, 0x00, 0x89, 0x03, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x10, 0x02, 0x23, 0x08,
+0x8C, 0x21, 0x30, 0x80, 0xC0, 0x10, 0x02, 0x43, 0x08, 0x8C, 0x21, 0x31, 0x84,
+0xC4, 0x08, 0x12, 0x63, 0x08, 0x8C, 0x20, 0x31, 0x86, 0xC4, 0x18, 0x12, 0x23,
+0x08, 0x8C, 0x20, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF,
+0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF,
+0xCB, 0xFF, 0x2F, 0xFF, 0xBF, 0xFC, 0xFF, 0xF2, 0xFF, 0xCB, 0xFF, 0x2F, 0xFF,
+0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xDB, 0xD0, 0xEC,
+0xCB, 0xB7, 0x0D, 0xED, 0x37, 0xFC, 0xDF, 0xD0, 0x6C, 0xC3, 0xB7, 0x0D, 0xED,
+0x37, 0x34, 0xDB, 0xD0, 0x6C, 0x43, 0xB3, 0x0D, 0xCD, 0x36, 0x34, 0xDB, 0xD0,
+0xEC, 0xCB, 0xB7, 0x2F, 0xED, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x3C, 0x32, 0xF3, 0xCB, 0xCF, 0x23, 0xF3,
+0x8F, 0xFC, 0x3F, 0x32, 0xF3, 0xC8, 0xCF, 0x23, 0xF3, 0x8F, 0xCC, 0x3C, 0x32,
+0xF3, 0xC8, 0xCC, 0x23, 0x33, 0x8F, 0xCC, 0x3C, 0x32, 0xF3, 0xCB, 0xCF, 0x2F,
+0xF3, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xDC, 0x78, 0x12, 0xFB, 0xC9, 0xED, 0x27, 0xB1, 0x87, 0xDC, 0x7E, 0x12,
+0xE3, 0xC9, 0xED, 0x27, 0xB7, 0x9F, 0xDC, 0x1E, 0x72, 0xFB, 0x49, 0xEC, 0x21,
+0xB7, 0x9F, 0xDC, 0x7E, 0x72, 0xFB, 0x49, 0xEC, 0x21, 0x37, 0x86, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x21, 0x00,
+0x85, 0x33, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0xCE,
+0x50, 0x30, 0x43, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x38, 0x43, 0xE1,
+0x0C, 0x85, 0x00, 0x14, 0xCE, 0x50, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02,
+0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20,
+0x00, 0x80, 0x00, 0x00, 0x02, 0x04, 0x08, 0x00, 0x20, 0x40, 0x80, 0x00, 0x00,
+0x02, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x21, 0x40, 0x84, 0x00, 0x11, 0x02, 0x44, 0x08, 0x10, 0x21,
+0x40, 0x84, 0x00, 0x11, 0x02, 0x44, 0x08, 0x10, 0x21, 0x40, 0x84, 0x00, 0x11,
+0x02, 0x44, 0x08, 0x10, 0x21, 0x40, 0x84, 0x00, 0x11, 0x02, 0x44, 0x18, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+0x00, 0x80, 0x33, 0x00, 0x02, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01,
+0xCE, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x02, 0x00, 0x38, 0x03,
+0xE0, 0x4C, 0x80, 0x00, 0x01, 0xCE, 0x00, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0xCC, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x33, 0x10, 0x00, 0x40, 0x30, 0x03,
+0x01, 0x00, 0x04, 0x33, 0x10, 0xCC, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0xCC, 0x40, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40,
+0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10,
+0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00,
+0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x01, 0xCC, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x33, 0x01, 0x00, 0x04, 0x30,
+0x13, 0x00, 0x40, 0x00, 0x33, 0x01, 0xCC, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x01, 0xCC, 0x04, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x00, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x38,
+0x53, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85,
+0x33, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x00, 0x54,
+0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x86, 0x04, 0x08, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x21, 0x00, 0x84,
+0x00, 0x10, 0x02, 0x40, 0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40,
+0x08, 0x00, 0x21, 0x00, 0x04, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0x84, 0x00, 0x10, 0x86, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0xE0, 0x0C, 0x80, 0x00, 0x00, 0xCE, 0x00,
+0x08, 0x00, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03, 0xE0, 0x0C,
+0x80, 0x00, 0x00, 0xCE, 0x00, 0x08, 0x00, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE,
+0x00, 0x08, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0x84, 0x33, 0x10, 0x02, 0x40, 0x38, 0x03, 0x21, 0x00, 0x84, 0x33, 0x10, 0xCE,
+0x40, 0x38, 0x03, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x81, 0x00, 0x04, 0x00,
+0x10, 0x08, 0x40, 0x00, 0x00, 0x81, 0x00, 0x04, 0x02, 0x10, 0x08, 0x40, 0x00,
+0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x84, 0x00, 0x10, 0x00, 0x40, 0x08, 0x00, 0x01,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x00, 0x33, 0x00,
+0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02,
+0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21,
+0x00, 0x85, 0x00, 0x14, 0x02, 0x50, 0x08, 0x40, 0x21, 0x00, 0x85, 0x00, 0x14,
+0x02, 0x50, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20,
+0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x01,
+0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x10, 0x21, 0x40, 0x84, 0x00, 0x11,
+0x02, 0x44, 0x08, 0x10, 0x21, 0x40, 0x84, 0x00, 0x11, 0x02, 0x44, 0x08, 0x10,
+0x21, 0x40, 0x84, 0x00, 0x11, 0x02, 0x44, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00,
+0x02, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00,
+0x20, 0x00, 0x80, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00,
+0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10,
+0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x00, 0x04, 0x00,
+0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40,
+0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
+0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00,
+0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00,
+0x10, 0x01, 0x40, 0x04, 0x00, 0x11, 0x00, 0x44, 0x00, 0x10, 0x01, 0x40, 0x04,
+0x00, 0x11, 0x00, 0x44, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85,
+0x00, 0x15, 0x02, 0x54, 0x08, 0x50, 0x21, 0x40, 0x85, 0x33, 0x15, 0x02, 0x54,
+0x08, 0x50, 0x21, 0x40, 0x85, 0x00, 0x15, 0x02, 0x54, 0x08, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x20, 0x40, 0x80,
+0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04,
+0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+0x80, 0x00, 0x01, 0x02, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40,
+0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00,
+0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02,
+0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x08, 0x00, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0x02, 0x00, 0x38, 0x03, 0x20, 0x00,
+0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE,
+0x00, 0x38, 0x03, 0xE0, 0x0C, 0x80, 0x33, 0x00, 0xCE, 0x00, 0x38, 0x43, 0x20,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x21, 0x00,
+0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02,
+0x40, 0x08, 0x00, 0x21, 0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x00, 0x21,
+0x00, 0x84, 0x00, 0x10, 0x02, 0x40, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00,
+0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04,
+0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01,
+0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10,
+0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
+0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
+0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
+0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x80,
+0x40, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xC2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x80, 0x40,
+0x40, 0x00, 0x00, 0x0C, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
+0x00, 0x80, 0x00, 0x00, 0xA4, 0x07, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
+0xC0, 0x0C, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0C, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x05, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x87, 0x5A, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00
+};
diff --git a/drivers/staging/slicoss/Kconfig b/drivers/staging/slicoss/Kconfig
new file mode 100644
index 00000000000..d2993d339bc
--- /dev/null
+++ b/drivers/staging/slicoss/Kconfig
@@ -0,0 +1,14 @@
+config SLICOSS
+ tristate "Alacritech Gigabit IS-NIC support"
+ depends on PCI && X86 && NETDEV_1000
+ default n
+ help
+ This driver supports Alacritech's IS-NIC gigabit ethernet cards.
+
+ This includes the following devices:
+ Mojave cards (single port PCI Gigabit) both copper and fiber
+ Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
+ Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
+
+ To compile this driver as a module, choose M here: the module
+ will be called slicoss.
diff --git a/drivers/staging/slicoss/Makefile b/drivers/staging/slicoss/Makefile
new file mode 100644
index 00000000000..7bc9e9b9d3a
--- /dev/null
+++ b/drivers/staging/slicoss/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SLICOSS) += slicoss.o
diff --git a/drivers/staging/slicoss/README b/drivers/staging/slicoss/README
new file mode 100644
index 00000000000..2d5b1127ce5
--- /dev/null
+++ b/drivers/staging/slicoss/README
@@ -0,0 +1,19 @@
+This driver is supposed to support:
+
+ Mojave cards (single port PCI Gigabit) both copper and fiber
+ Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
+ Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
+
+The driver was actually tested on Oasis and Kalahari cards.
+
+TODO:
+ - move firmware loading to request_firmware()
+ - remove direct memory access of structures
+ - any remaining sparse and checkpatch.pl warnings
+ - any netdev recommended changes
+
+Please send patches to:
+ Greg Kroah-Hartman <gregkh@suse.de>
+and Cc: Lior Dotan <liodot@gmail.com> and Christopher Harrer
+<charrer@alacritech.com> as well as they are also able to test out any
+changes.
diff --git a/drivers/staging/slicoss/gbdownload.h b/drivers/staging/slicoss/gbdownload.h
new file mode 100644
index 00000000000..794432bd1d7
--- /dev/null
+++ b/drivers/staging/slicoss/gbdownload.h
@@ -0,0 +1,8215 @@
+#define MOJAVE_UCODE_VERS_STRING "1.2"
+#define MOJAVE_UCODE_VERS_DATE "2006/03/27 15:12:22"
+#define MOJAVE_UCODE_HOSTIF_ID 3
+
+static s32 MNumSections = 0x2;
+static u32 MSectionSize[] =
+{
+ 0x00008000, 0x00010000,
+};
+
+static u32 MSectionStart[] =
+{
+ 0x00000000, 0x00008000,
+};
+
+static u8 MojaveUCode[2][65536] =
+{
+ {
+ 0x12, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00,
+ 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40,
+ 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x1f, 0xe9, 0x18, 0x31, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe9,
+ 0x80, 0xb2, 0x01, 0x00, 0x0f, 0x00, 0x40, 0xe9, 0x80, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x16, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x16, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x0f, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1c, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x11, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x22, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x22, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xdd, 0x81, 0x01, 0x00, 0x2b, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x3c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x27, 0x00, 0x14, 0xbc,
+ 0x80, 0x32, 0x00, 0x00, 0x14, 0x01, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0xb7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb5, 0xb3, 0x01, 0x00,
+ 0xd9, 0x00, 0x00, 0x40, 0xb3, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xb6, 0xd3, 0x01, 0x00, 0x32, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xe8, 0x80, 0x88, 0x01, 0x00, 0xb8, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00, 0x3c, 0x00, 0x22, 0x50,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00,
+ 0xa5, 0xa5, 0x00, 0xa6, 0xb4, 0xa7, 0x01, 0x00, 0x3c, 0x00, 0xa2, 0x50,
+ 0xb5, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x3c, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0xfd, 0x93, 0x01, 0x00, 0x41, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x20, 0xf5, 0xcf, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfa,
+ 0xb3, 0x33, 0x01, 0x00, 0xa5, 0xa5, 0x00, 0xda, 0xb5, 0xab, 0x01, 0x00,
+ 0x99, 0x00, 0xa2, 0x50, 0xb5, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xfd, 0x93, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x44, 0xb3, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xd7, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xed, 0x8b, 0x01, 0x00,
+ 0xd5, 0x00, 0x00, 0x46, 0xb3, 0x33, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0xb1, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xda, 0xef, 0x8b, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda,
+ 0xe3, 0x8f, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x48, 0xb3, 0x33, 0x01, 0x00,
+ 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda,
+ 0xd7, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xf1, 0xdb, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xda, 0xe9, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xe9, 0xe3, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4b, 0xb3, 0x33, 0x01, 0x00,
+ 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xd7, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4c, 0xb3, 0x33, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xda, 0xeb, 0xdb, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4e,
+ 0xb3, 0x33, 0x01, 0x00, 0x03, 0x00, 0x00, 0xda, 0x81, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x81, 0xe0, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda,
+ 0xb5, 0xdb, 0x01, 0x00, 0x5c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0xda, 0xb5, 0xcf, 0x01, 0x00, 0x00, 0xf0, 0x00, 0xa7,
+ 0xb4, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x81, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd8, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x50,
+ 0xb3, 0x33, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xb5, 0x8b, 0x01, 0x00,
+ 0x62, 0x00, 0x26, 0x4c, 0xb5, 0x63, 0x00, 0x00, 0x01, 0x00, 0x00, 0xda,
+ 0xb5, 0xcf, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xdf, 0xb1, 0x01, 0x00,
+ 0xd5, 0x00, 0x00, 0x52, 0xb3, 0x33, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda,
+ 0x4b, 0x89, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xdf, 0xf7, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xef, 0xdf, 0x8b, 0x01, 0x00, 0x69, 0x00, 0x22, 0x40,
+ 0xdf, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xfd, 0x93, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xda, 0xd7, 0xe5, 0x01, 0x00, 0xf8, 0x00, 0x00, 0xda,
+ 0xb3, 0x8b, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd9, 0xd7, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd9,
+ 0xd5, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb5, 0xf3, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0xda, 0x7b, 0x89, 0x01, 0x00, 0x00, 0x01, 0x00, 0x40,
+ 0xdd, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x5d, 0xb3, 0x33, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xda, 0xe7, 0x8b, 0x01, 0x00, 0x8a, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xe7, 0xe3, 0x01, 0x00, 0x00, 0x01, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xe7, 0x97, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0xd7, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x5e,
+ 0xb3, 0x33, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, 0xe5, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xe5, 0xe3, 0x01, 0x00, 0x08, 0x01, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, 0xb5, 0x8f, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf7, 0xb5, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xd7, 0xb1, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xe5, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0xd7, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0xdd, 0x9b, 0x01, 0x00,
+ 0x96, 0x00, 0x22, 0xf5, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, 0xd5, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf6, 0xeb, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5,
+ 0xd7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xea, 0xd4, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf7, 0xe3, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1,
+ 0xd7, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x00, 0xee, 0xdd, 0xcb, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xee, 0xd5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xe9, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xd7, 0xb1, 0x01, 0x00,
+ 0xd5, 0x00, 0x00, 0x4a, 0xb3, 0x33, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda,
+ 0xdd, 0x89, 0x01, 0x00, 0xb7, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x3c, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0xd7, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x93, 0x01, 0x00,
+ 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x01, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa6,
+ 0xd6, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xdf, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa6, 0xd6, 0xb1, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0x4b, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0x99, 0x01, 0x00,
+ 0x02, 0x04, 0x00, 0x40, 0xdd, 0x99, 0x01, 0x00, 0xb7, 0x00, 0x13, 0xbc,
+ 0x80, 0x32, 0x00, 0x00, 0x02, 0x08, 0x00, 0x40, 0xdd, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x01, 0x00, 0xb8, 0x00, 0x95, 0xe8,
+ 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42,
+ 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0xb8, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0xb8, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x81, 0xb0, 0x01, 0x00, 0xca, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0xc8, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0xd4, 0x00, 0x1f, 0xfd,
+ 0xf9, 0x33, 0x00, 0x00, 0xc7, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48,
+ 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x19, 0xb1, 0x01, 0x00, 0xcf, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00,
+ 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0xd3, 0x00, 0xa2, 0xff,
+ 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0xd8, 0x00, 0x06, 0xfe, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xb3, 0xe3, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfa, 0xb3, 0xc3, 0x00, 0x00,
+ 0xda, 0x00, 0x00, 0x42, 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xeb, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x84, 0x96, 0x80, 0xb2, 0x00, 0x00,
+ 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40,
+ 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0x81, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xb5, 0xeb, 0x01, 0x00, 0xe4, 0x00, 0x84, 0x96,
+ 0x80, 0x32, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x40, 0xb5, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xb5, 0x83, 0x01, 0x00, 0xde, 0x00, 0xa2, 0x41,
+ 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2d, 0x81, 0x01, 0x00,
+ 0x26, 0x01, 0x00, 0x41, 0x2d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xb3, 0xc3, 0x01, 0x00, 0xda, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xda, 0xb5, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x81, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd9, 0xb9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xb8, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xb9, 0xeb, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xb8, 0x97, 0x01, 0x00, 0x15, 0x00, 0x00, 0xdc,
+ 0xb9, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x81, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xdb, 0x81, 0xb0, 0x01, 0x00, 0x27, 0x01, 0x00, 0x42,
+ 0x2d, 0x11, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, 0x2d, 0x11, 0x01, 0x00,
+ 0x28, 0x01, 0x00, 0x40, 0x2d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x2d, 0x91, 0x01, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x25, 0x01, 0x00, 0x40, 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2d, 0x81, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x81, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0x84, 0x96, 0x80, 0x32, 0x01, 0x00, 0xff, 0x00, 0xa0, 0xdc,
+ 0xb9, 0x6b, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x41, 0x2d, 0x91, 0x00, 0x00,
+ 0xf8, 0x00, 0x00, 0x41, 0x2d, 0x81, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x40,
+ 0xb3, 0x33, 0x01, 0x00, 0x00, 0x00, 0x90, 0xda, 0x8b, 0xb0, 0x00, 0x00,
+ 0x11, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x44,
+ 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0xa3, 0x44, 0x89, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x89, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0xb0, 0x01, 0x00,
+ 0xd9, 0x00, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xb5, 0xf3, 0x01, 0x00, 0x0c, 0x01, 0xa0, 0xda, 0x8b, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0xc0, 0x01, 0x00, 0x08, 0x01, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00, 0x10, 0x00, 0x00, 0x45,
+ 0x8a, 0xf4, 0x01, 0x00, 0x12, 0x01, 0x90, 0x44, 0x8a, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x45,
+ 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, 0x8b, 0xe0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x40, 0xf9, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x40,
+ 0xb3, 0xcf, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00,
+ 0x1c, 0x01, 0x40, 0xda, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x41, 0xda,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00,
+ 0x16, 0x01, 0x9f, 0xda, 0x81, 0x32, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x91, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x1e, 0x01, 0x9f, 0x94,
+ 0x80, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0x94, 0x92, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xb5, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xb4, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xb3, 0xc3, 0x01, 0x00,
+ 0x1d, 0x01, 0xa2, 0x41, 0x91, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x2b, 0xb1, 0x01, 0x00, 0x29, 0x01, 0x00, 0x51, 0x93, 0xb0, 0x00, 0x00,
+ 0x29, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00, 0x29, 0x01, 0x00, 0x49,
+ 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x93, 0xb0, 0x01, 0x00,
+ 0x29, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x12, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x15, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x18, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0xb0, 0x01, 0x00, 0x44, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x50, 0x01, 0x22, 0x4b,
+ 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1,
+ 0x7e, 0xb1, 0x01, 0x00, 0x51, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x4e, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x80, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00,
+ 0xf3, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xa5, 0xb3, 0x01, 0x00, 0xaf, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00,
+ 0x5f, 0x01, 0x22, 0xcc, 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51,
+ 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb,
+ 0xa3, 0xc9, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xe1, 0xb1, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0x68, 0x01, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00,
+ 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xbc, 0xb3, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8,
+ 0xa9, 0xb3, 0x01, 0x00, 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x80, 0xf4, 0x01, 0x00, 0x78, 0x01, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x88, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x91, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd2, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe1, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x80, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf1, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf2, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x77, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x1a, 0x00,
+ 0x5a, 0x01, 0x51, 0x40, 0x81, 0xb2, 0x1a, 0x00, 0x5a, 0x01, 0x52, 0x40,
+ 0x81, 0xb2, 0x1a, 0x00, 0x5a, 0x01, 0x55, 0x40, 0x81, 0xb2, 0x1a, 0x00,
+ 0x5a, 0x01, 0x56, 0x40, 0x81, 0xb2, 0x1a, 0x00, 0x55, 0x01, 0x91, 0x81,
+ 0x80, 0x30, 0x1a, 0x00, 0x5a, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x1a, 0x00,
+ 0x55, 0x01, 0x91, 0x82, 0x80, 0x30, 0x1a, 0x00, 0x5a, 0x01, 0x46, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0xb5, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x81, 0xc0, 0x01, 0x00, 0x94, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x49, 0xd1, 0x01, 0x00, 0x9c, 0x01, 0x22, 0x40,
+ 0xe1, 0x6d, 0x00, 0x00, 0x98, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0x41, 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xbf, 0xb3, 0x01, 0x00, 0x55, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x49, 0xc1, 0x01, 0x00, 0xb7, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x42, 0xff, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0xff, 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4,
+ 0x80, 0xcc, 0x01, 0x00, 0xac, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00, 0xaa, 0x01, 0xa2, 0x4c,
+ 0x81, 0x50, 0x00, 0x00, 0xb6, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00,
+ 0xb1, 0x01, 0x22, 0x41, 0xa5, 0x6f, 0x00, 0x00, 0x55, 0x01, 0xa2, 0xe0,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x88, 0x94, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x44,
+ 0xe0, 0xb1, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00,
+ 0xb1, 0x01, 0x00, 0x5b, 0x89, 0x90, 0x00, 0x00, 0xb0, 0x9f, 0x00, 0xa0,
+ 0x9e, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xba, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xc4, 0x01, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40,
+ 0x80, 0xce, 0x01, 0x00, 0xc3, 0x01, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xc4, 0x01, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53,
+ 0x6f, 0x93, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x52, 0x6f, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xc7, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xd1, 0x01, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89,
+ 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0xd0, 0x01, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd1, 0x01, 0x55, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6f, 0x93, 0x01, 0x00,
+ 0xf3, 0x9f, 0x00, 0x53, 0x6f, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00, 0xda, 0x01, 0x22, 0xde,
+ 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xd5, 0x01, 0xa2, 0x44,
+ 0x81, 0x6c, 0x00, 0x00, 0x55, 0x01, 0x00, 0x43, 0xbf, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf8,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x40, 0xe1, 0xb1, 0x00, 0x00,
+ 0xe2, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x08, 0x00, 0x00, 0xdd,
+ 0x81, 0xf4, 0x01, 0x00, 0xe7, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, 0xed, 0x01, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x58, 0x01, 0x00, 0xde, 0xa1, 0xb3, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x02, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x07, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x57, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2,
+ 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00,
+ 0xf7, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00, 0xf6, 0x01, 0x84, 0x41,
+ 0x81, 0x40, 0x00, 0x00, 0xfa, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00, 0xf1, 0x01, 0x00, 0x41,
+ 0xa1, 0xc1, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x5a, 0x01, 0x00, 0xdd,
+ 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, 0xb1, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00,
+ 0xc5, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0xa3, 0x9b, 0x01, 0x00, 0x58, 0x01, 0x00, 0xde, 0xa1, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0x81, 0x90, 0x01, 0x00, 0x55, 0x01, 0xa2, 0xba, 0x80, 0x04, 0x00, 0x00,
+ 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00, 0x04, 0x02, 0xa8, 0xb1,
+ 0x80, 0x30, 0x00, 0x00, 0x57, 0x01, 0x00, 0x40, 0xe0, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x68, 0x02, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0x4d, 0x83, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe5, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf5, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf9, 0xb3, 0x01, 0x00, 0x15, 0x02, 0x22, 0x40, 0x8f, 0x6f, 0x00, 0x00,
+ 0x75, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0xc7,
+ 0x83, 0x30, 0x01, 0x00, 0x7d, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x5d, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xed,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xf0, 0xb1, 0x01, 0x00,
+ 0xe0, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xab, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xba, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb,
+ 0xf0, 0xb1, 0x01, 0x00, 0x29, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0x90, 0x01, 0x00, 0x2b, 0x02, 0xb9, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00,
+ 0x2d, 0x02, 0xba, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x81, 0x90, 0x01, 0x00, 0x2f, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x81, 0x90, 0x01, 0x00, 0x31, 0x02, 0xbc, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00,
+ 0x33, 0x02, 0xbd, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x81, 0x90, 0x01, 0x00, 0x35, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x81, 0x90, 0x01, 0x00, 0x37, 0x02, 0xbf, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00,
+ 0x39, 0x02, 0xc8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x81, 0x90, 0x01, 0x00, 0x3b, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x81, 0x90, 0x01, 0x00, 0x3d, 0x02, 0xca, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00,
+ 0x3f, 0x02, 0xcb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x81, 0x90, 0x01, 0x00, 0x41, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x81, 0x90, 0x01, 0x00, 0x43, 0x02, 0xcd, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00,
+ 0x45, 0x02, 0xce, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x81, 0x90, 0x01, 0x00, 0x47, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0xaf, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00,
+ 0xf7, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x63, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x60, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5c, 0x02, 0x49, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x65, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x5c, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1,
+ 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4,
+ 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99,
+ 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7,
+ 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x81, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x85, 0x02, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00,
+ 0x8a, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x95, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x95, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00,
+ 0x98, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9e, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xbc, 0x02, 0x00, 0x42,
+ 0xa5, 0x63, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x94, 0x02, 0x22, 0x44,
+ 0xa5, 0x53, 0x00, 0x00, 0x91, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00,
+ 0x5a, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xbc, 0x02, 0x00, 0xde,
+ 0xa1, 0x33, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xbf, 0xb3, 0x01, 0x00, 0x55, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0x63, 0xb1, 0x01, 0x00, 0x9b, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x54,
+ 0xa5, 0x33, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00,
+ 0xa9, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0x46,
+ 0x83, 0x30, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8,
+ 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb,
+ 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8,
+ 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x62, 0xdd, 0x01, 0x00, 0xb9, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7,
+ 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb,
+ 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00,
+ 0xb8, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc,
+ 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0xc7, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xc6, 0x02, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0xcb, 0x02, 0x80, 0xa5,
+ 0x80, 0x32, 0x00, 0x00, 0xcc, 0x02, 0x00, 0xa5, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xcd, 0x02, 0x80, 0xa5,
+ 0x80, 0x32, 0x00, 0x00, 0x80, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xd6, 0x02, 0x20, 0x4f, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xd6, 0x02, 0x20, 0x4b, 0x81, 0x6c, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xd6, 0x02, 0x20, 0x47,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x03, 0x90, 0x00, 0x41,
+ 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x14, 0x2f, 0x4c, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xda, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0xa5, 0x80, 0xc8, 0x01, 0x00, 0xdd, 0x02, 0xa2, 0xa5,
+ 0x80, 0x6c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe0, 0x02, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe3, 0x02, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x70, 0x00, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe6, 0x02, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00,
+ 0xe8, 0x02, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, 0x40, 0x68, 0x00, 0x90,
+ 0x20, 0xa9, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x21, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x23, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x25, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x26, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x27, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x02, 0x01, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0x04, 0x03, 0x00, 0x40,
+ 0x80, 0x98, 0x01, 0x00, 0x06, 0x05, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x08, 0x07, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe0, 0xb1, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x40, 0x85, 0x30, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xff, 0x02, 0xa2, 0xf8, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x22, 0xf0,
+ 0x82, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x21, 0x91, 0x01, 0x00,
+ 0xd0, 0x14, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x0c,
+ 0x85, 0x30, 0x01, 0x00, 0x30, 0x03, 0x00, 0x4d, 0x85, 0x10, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x4e, 0x85, 0x10, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x4f,
+ 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x4f, 0x85, 0x10, 0x01, 0x00,
+ 0x39, 0x03, 0x00, 0x0c, 0x85, 0x30, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x43,
+ 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x03, 0x22, 0xf0, 0x9e, 0x6e, 0x00, 0x00,
+ 0x39, 0x03, 0x00, 0x4d, 0x85, 0x10, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x42,
+ 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x03, 0x22, 0xf0, 0x9e, 0x6e, 0x00, 0x00,
+ 0x39, 0x03, 0x00, 0x4e, 0x85, 0x10, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x41,
+ 0x81, 0xb0, 0x01, 0x00, 0x11, 0x03, 0xa2, 0xf0, 0x9e, 0x6e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x20, 0x95, 0x01, 0x00, 0x03, 0x00, 0x00, 0x90, 0x20, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x21, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x89, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x17, 0x85, 0x30, 0x01, 0x00, 0x30, 0x03, 0x00, 0x58,
+ 0x85, 0x10, 0x01, 0x00, 0x30, 0x03, 0x00, 0x59, 0x85, 0x10, 0x01, 0x00,
+ 0xd0, 0x14, 0x20, 0x4f, 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x5a,
+ 0x85, 0x10, 0x01, 0x00, 0x39, 0x03, 0x00, 0x17, 0x85, 0x30, 0x01, 0x00,
+ 0xd8, 0x14, 0x20, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x23, 0x03, 0x22, 0xf0,
+ 0x9e, 0x6e, 0x00, 0x00, 0x39, 0x03, 0x00, 0x58, 0x85, 0x10, 0x01, 0x00,
+ 0xd8, 0x14, 0x20, 0x41, 0x81, 0xb0, 0x01, 0x00, 0x23, 0x03, 0x22, 0xf0,
+ 0x9e, 0x6e, 0x00, 0x00, 0x39, 0x03, 0x00, 0x59, 0x85, 0x10, 0x01, 0x00,
+ 0xd8, 0x14, 0x20, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x27, 0x03, 0xa2, 0xf0,
+ 0x9e, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x90, 0x20, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x20, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0xe0, 0x01, 0x00,
+ 0x2f, 0x03, 0xa2, 0x42, 0x21, 0x7d, 0x00, 0x00, 0xa5, 0xa5, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x44, 0x84, 0x30, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x2f, 0x03, 0xa2, 0xf0, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x89, 0xe0, 0x01, 0x00, 0xe0, 0x00, 0x80, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x70, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x87, 0xb4, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, 0x36, 0x03, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x41, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x70, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xf1, 0xb1, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x87, 0xb4, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, 0x3f, 0x03, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x87, 0xb0, 0x01, 0x00,
+ 0x42, 0x03, 0xa2, 0x41, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf2,
+ 0x86, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf1, 0x86, 0xf4, 0x01, 0x00,
+ 0x41, 0x03, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x84, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00, 0x49, 0x03, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xf5, 0x9f, 0x00, 0x47, 0x98, 0x30, 0x01, 0x00,
+ 0x00, 0x08, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, 0x47, 0x03, 0x00, 0x5c,
+ 0x8f, 0x80, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x58, 0x15, 0x2d, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0,
+ 0x88, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45,
+ 0x82, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x82, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, 0x64, 0x03, 0x22, 0x5f,
+ 0x8d, 0x6c, 0x00, 0x00, 0x55, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x53, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0x85, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43,
+ 0x86, 0xd8, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00,
+ 0x60, 0x03, 0x00, 0x41, 0x83, 0xe0, 0x00, 0x00, 0x5e, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00,
+ 0xd0, 0x14, 0x2f, 0x46, 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42,
+ 0x60, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45,
+ 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00,
+ 0x00, 0x04, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0x6f, 0x03, 0xa0, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0x6d, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x41, 0x8e, 0xc0, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40,
+ 0xa3, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0xb0, 0x01, 0x00,
+ 0x60, 0x15, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0x40, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x41, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x40, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0xa3, 0x55, 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa3, 0xc1, 0x01, 0x00, 0x73, 0x03, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x7e, 0x03, 0xa2, 0x41,
+ 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x44, 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x08, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x16, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43,
+ 0x62, 0x99, 0x01, 0x00, 0x88, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x8a, 0x03, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x8b, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x83, 0x03, 0xa2, 0x41,
+ 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x0f, 0x00, 0xbc,
+ 0x80, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ },
+ {
+ 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80,
+ 0x80, 0x32, 0x00, 0x00, 0xe6, 0x89, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2,
+ 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00,
+ 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81,
+ 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xe6, 0x89, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42,
+ 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48,
+ 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53,
+ 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00,
+ 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x1b, 0x84, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x1b, 0x84, 0x05, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0xe1, 0x80, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0xde, 0xb2, 0x01, 0x00, 0x77, 0x00, 0x00, 0x40, 0x4b, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x9b, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, 0xde, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x06, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x05, 0x18, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x09, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x50, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7b, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe0, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x10, 0x84, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x84, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x1a, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x71, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x00, 0x00, 0x97,
+ 0x80, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2e, 0xb1, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x2e, 0xdd, 0x01, 0x00, 0x90, 0x01, 0x00, 0x40,
+ 0x93, 0x98, 0x01, 0x00, 0x29, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x5c, 0x81, 0x00, 0x40, 0xaf, 0x33, 0x01, 0x00, 0x61, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x49, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x77, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x00, 0x00,
+ 0x71, 0x80, 0x51, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x80, 0x52, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x73, 0x80, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x74, 0x80, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x91, 0x81,
+ 0x80, 0x30, 0x00, 0x00, 0x5a, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x55, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00, 0x5a, 0x01, 0x46, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00,
+ 0x5a, 0x01, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x49,
+ 0xfd, 0x83, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x4a, 0xfd, 0x83, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb,
+ 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00,
+ 0x7c, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00,
+ 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x84, 0x80, 0xa2, 0x41,
+ 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04,
+ 0x80, 0x94, 0x00, 0x00, 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03,
+ 0x02, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xcb, 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc,
+ 0xf3, 0x83, 0x01, 0x00, 0x8e, 0x80, 0xa2, 0x41, 0x97, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcb, 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb,
+ 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00,
+ 0x95, 0x80, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc6, 0x02, 0x00, 0x20,
+ 0x42, 0x31, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0xcb, 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41,
+ 0x8b, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x9b, 0x80, 0xa8, 0xb1, 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x9d, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00,
+ 0xa3, 0x80, 0x14, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6,
+ 0x83, 0xf4, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00,
+ 0x7f, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6,
+ 0x81, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00,
+ 0x7f, 0x80, 0x1f, 0x5c, 0x97, 0x53, 0x00, 0x00, 0x9e, 0x83, 0x1d, 0xc6,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x43, 0x81, 0xf0, 0x01, 0x00,
+ 0xa9, 0x80, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00, 0x05, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xda, 0x81, 0x00, 0xca, 0x63, 0xb3, 0x00, 0x00, 0x2d, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x14, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00,
+ 0x1e, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, 0x0d, 0x81, 0x00, 0x40,
+ 0x85, 0xb0, 0x00, 0x00, 0x14, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00,
+ 0xf0, 0x80, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0x91, 0x81, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x3d, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x8d, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0d, 0x81, 0x00, 0x40,
+ 0x85, 0xb0, 0x00, 0x00, 0xdd, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0x6a, 0x84, 0x00, 0xca, 0x9b, 0xb3, 0x00, 0x00, 0x46, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x4e, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x55, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x56, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x57, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x58, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x59, 0x81, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x59, 0x81, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00,
+ 0xce, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x83, 0x00, 0xbb,
+ 0xab, 0xb3, 0x00, 0x00, 0xdb, 0x81, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00,
+ 0xd3, 0x80, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xdf, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xdc, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xda, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0x77, 0xb3, 0x00, 0x00,
+ 0x15, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, 0x1c, 0x81, 0x00, 0x4e,
+ 0x61, 0xb1, 0x00, 0x00, 0x0d, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00,
+ 0x15, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, 0x0d, 0x81, 0x00, 0xbb,
+ 0x85, 0xb0, 0x00, 0x00, 0xf0, 0x80, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00,
+ 0xe2, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca,
+ 0x4d, 0xb3, 0x00, 0x00, 0x64, 0x82, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0x8f, 0x82, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xc8, 0x14, 0x2e, 0xbb,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2,
+ 0xa0, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00,
+ 0x75, 0x80, 0x00, 0xca, 0xa7, 0x33, 0x01, 0x00, 0x02, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00,
+ 0x4e, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x4e, 0x01, 0x00, 0x4c,
+ 0x93, 0x30, 0x01, 0x00, 0x08, 0x84, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xe8, 0x80, 0x22, 0x42,
+ 0x8f, 0x6f, 0x00, 0x00, 0xea, 0x80, 0x22, 0x41, 0x8f, 0x6f, 0x00, 0x00,
+ 0xec, 0x80, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xee, 0x80, 0x1f, 0xca,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00,
+ 0x6a, 0x84, 0x00, 0x42, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xcd, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x41, 0x8f, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40,
+ 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00,
+ 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0xc6, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00,
+ 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0x10, 0x00, 0x2f, 0x9c,
+ 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40, 0x39, 0x33, 0x01, 0x00,
+ 0x18, 0x00, 0x2f, 0x9b, 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40,
+ 0x37, 0x33, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x9a, 0x89, 0xb0, 0x01, 0x00,
+ 0x07, 0x81, 0x00, 0x40, 0x35, 0x33, 0x01, 0x00, 0x08, 0x00, 0x2f, 0x99,
+ 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40, 0x33, 0x33, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xae, 0x47, 0xc9, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40,
+ 0xe1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0xae, 0x63, 0xdd, 0x01, 0x00, 0x02, 0x81, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xff, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x02, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x69, 0x93, 0x01, 0x00, 0x6a, 0x84, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00,
+ 0x05, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x81, 0xa2, 0x40,
+ 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0xe1, 0xd1, 0x01, 0x00, 0x0d, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x11, 0x81, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x0e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0x11, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x6a, 0x84, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x16, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x16, 0x81, 0x00, 0xbb,
+ 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x60, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x17, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00,
+ 0x6a, 0x84, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x19, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x1f, 0x81, 0x00, 0xbb, 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0x21, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00,
+ 0x6a, 0x84, 0x60, 0x40, 0x95, 0x83, 0x00, 0x00, 0x02, 0x00, 0x2d, 0xf0,
+ 0x84, 0xb0, 0x01, 0x00, 0x22, 0x81, 0x36, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x23, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00,
+ 0x25, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0x63, 0xb1, 0x01, 0x00, 0x27, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x41,
+ 0x43, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0xca, 0x95, 0xcb, 0x01, 0x00,
+ 0x22, 0x81, 0x00, 0x41, 0x85, 0xc0, 0x00, 0x00, 0x2f, 0x81, 0xa2, 0x42,
+ 0x67, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00,
+ 0x2f, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x65, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0xca, 0x69, 0x97, 0x01, 0x00, 0x6a, 0x84, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x34, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x6a, 0x84, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0x6a, 0x84, 0x20, 0x43,
+ 0x95, 0x6f, 0x00, 0x00, 0x6a, 0x84, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00,
+ 0x6a, 0x84, 0x22, 0x40, 0x65, 0x6f, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x6f,
+ 0xdb, 0x91, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x35, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x93, 0x01, 0x00,
+ 0x42, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x95, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xc3, 0xb1, 0x01, 0x00, 0x45, 0x81, 0x22, 0x5b, 0x95, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x49, 0x81, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00,
+ 0x1b, 0xf5, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00, 0x4a, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x7f, 0xb3, 0x01, 0x00, 0x26, 0x01, 0x00, 0xca,
+ 0xc5, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00,
+ 0x6a, 0x84, 0x00, 0xca, 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca,
+ 0x95, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xc7, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x5f,
+ 0x95, 0x7f, 0x00, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca,
+ 0xc7, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00,
+ 0x6a, 0x84, 0x00, 0xca, 0xcb, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca,
+ 0xcd, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x42, 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40,
+ 0x48, 0xc9, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x5e, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x60, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00,
+ 0x62, 0x81, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x61, 0x81, 0xa2, 0x4f,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00,
+ 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00,
+ 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0x75, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x72, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0x7e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0x7a, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x21, 0xb3, 0x01, 0x00, 0x7e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0x7e, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x7f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x87, 0x81, 0x22, 0x43,
+ 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x84, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0x8c, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0x89, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x8c, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00,
+ 0x8f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40,
+ 0x08, 0xb1, 0x00, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00,
+ 0x92, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0xa1, 0x81, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00,
+ 0xb0, 0x81, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb8, 0x81, 0x22, 0x4a, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x87, 0x90, 0x01, 0x00, 0x9c, 0x81, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, 0x9e, 0x81, 0x22, 0x4f,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00,
+ 0xa0, 0x81, 0x22, 0x4e, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x87, 0x90, 0x01, 0x00, 0xb8, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x81, 0x22, 0x42,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00,
+ 0x1c, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xab, 0x81, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, 0xad, 0x81, 0x22, 0x44,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00,
+ 0xaf, 0x81, 0x22, 0x43, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x87, 0x90, 0x01, 0x00, 0xb8, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x81, 0x22, 0x42,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbc, 0x81, 0x22, 0x4b,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xaf, 0xb3, 0x01, 0x00, 0xc5, 0x81, 0x22, 0x40, 0x87, 0x7c, 0x00, 0x00,
+ 0xc5, 0x81, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xae, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb3, 0x01, 0x00,
+ 0xc4, 0x81, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00, 0xc5, 0x81, 0x00, 0x0b,
+ 0x7d, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x7d, 0xb3, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xa5, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xca, 0xa7, 0x33, 0x01, 0x00,
+ 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0x41,
+ 0x82, 0xdc, 0x01, 0x00, 0xca, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0xcc, 0x81, 0x9f, 0x85,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xd1, 0x81, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00, 0xd1, 0x81, 0xa2, 0x49,
+ 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00,
+ 0xd4, 0x81, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00, 0xd4, 0x81, 0xa2, 0x4a,
+ 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00,
+ 0xd6, 0x81, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00, 0xd8, 0x81, 0x42, 0x40,
+ 0xf1, 0x33, 0x00, 0x00, 0x04, 0x81, 0x00, 0x40, 0x68, 0x97, 0x00, 0x00,
+ 0x6a, 0x84, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xbb,
+ 0xb1, 0xb3, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2,
+ 0xa0, 0x8b, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40,
+ 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44,
+ 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x43,
+ 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa5, 0xc3, 0x01, 0x00, 0xf8, 0x81, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00,
+ 0xf8, 0x81, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xe7, 0x81, 0xa2, 0x50,
+ 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb,
+ 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0xf5, 0x81, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf4, 0x81, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0xe7, 0x81, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00,
+ 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x41,
+ 0xb3, 0x73, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, 0xb5, 0xf3, 0x01, 0x00,
+ 0xd8, 0x00, 0x00, 0x41, 0xb3, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9,
+ 0xb3, 0xfb, 0x01, 0x00, 0x00, 0x30, 0x00, 0xa6, 0xb8, 0xb3, 0x01, 0x00,
+ 0xf2, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x42,
+ 0x2d, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xeb, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x81, 0xb0, 0x01, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x09, 0x82, 0x10, 0xda, 0xb5, 0x6b, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x41,
+ 0x2d, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x91, 0x01, 0x00,
+ 0x28, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40,
+ 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0x81, 0x01, 0x00,
+ 0x06, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x26, 0x01, 0x00, 0x42,
+ 0x2d, 0x01, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x26, 0x01, 0x00, 0x42, 0x2d, 0x11, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40,
+ 0x2d, 0x11, 0x01, 0x00, 0x15, 0x82, 0x04, 0x40, 0x2d, 0x01, 0x00, 0x00,
+ 0x25, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x11, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x28, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x25, 0x01, 0x00, 0x42, 0x2d, 0x01, 0x01, 0x00, 0xf2, 0x00, 0x00, 0x40,
+ 0xb9, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2d, 0x81, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x41, 0x2d, 0x81, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x18, 0xb1, 0x01, 0x00, 0x1f, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x29, 0x82, 0xa2, 0x54,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x30, 0x82, 0xa2, 0x06,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x07, 0x91, 0xb0, 0x01, 0x00, 0xe1, 0x80, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x39, 0x82, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x3a, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xf5, 0xb1, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x42,
+ 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00,
+ 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00,
+ 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x8f, 0xb0, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x48, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda,
+ 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x91, 0xc0, 0x01, 0x00,
+ 0x45, 0x82, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x16, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x91, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda, 0x8f, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda, 0xfd, 0xb1, 0x01, 0x00,
+ 0x6f, 0x82, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x82, 0x22, 0x45,
+ 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x08, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfe, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6d, 0x82, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0x72, 0x82, 0x22, 0x20,
+ 0xb5, 0x6f, 0x00, 0x00, 0x6f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdb, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x72, 0x82, 0x22, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x6f, 0x82, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x04, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x46, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x48, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x97, 0xb0, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00, 0x85, 0x82, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00,
+ 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa7, 0x82, 0x22, 0x45,
+ 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00,
+ 0x96, 0x82, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x83, 0xb0, 0x01, 0x00, 0x99, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x98, 0x82, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00, 0xe1, 0x80, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x9f, 0x82, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xa0, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xa7, 0x82, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00,
+ 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0xa7, 0x82, 0xa2, 0xfa,
+ 0xb4, 0x6f, 0x00, 0x00, 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00,
+ 0xaa, 0x82, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0xa7, 0x82, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00,
+ 0x04, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00,
+ 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb4, 0xb3, 0x01, 0x00,
+ 0xb8, 0x82, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0xfc, 0x15, 0x20, 0x20,
+ 0xe1, 0xb1, 0x01, 0x00, 0xbd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdb, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbd, 0x82, 0x22, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0xba, 0x82, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x04, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xc2, 0x82, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x08, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a,
+ 0xb4, 0x8b, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a,
+ 0xb4, 0xf7, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd8, 0x82, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00, 0xd9, 0x82, 0x00, 0x50,
+ 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb5, 0xb3, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0xe7, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06,
+ 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0xea, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00,
+ 0xed, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0x00, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0xf3, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x83, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00,
+ 0xff, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70,
+ 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00,
+ 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6,
+ 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00,
+ 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73,
+ 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00,
+ 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf7, 0xb1, 0x01, 0x00, 0x0d, 0x83, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47,
+ 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0x16, 0x83, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41,
+ 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00,
+ 0x33, 0x83, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40,
+ 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00,
+ 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75,
+ 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00,
+ 0x3d, 0x83, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x4c, 0x83, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x42, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x89, 0xa4, 0x01, 0x00, 0x4c, 0x83, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x3f, 0x83, 0xaa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x4c, 0x83, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x53, 0x83, 0xa3, 0x53,
+ 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00,
+ 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x58, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6,
+ 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00,
+ 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x5d, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x1f, 0x83, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75,
+ 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78,
+ 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00,
+ 0x13, 0x83, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x9d, 0x83, 0xa2, 0x4b, 0xb7, 0x6f, 0x00, 0x00,
+ 0x9d, 0x83, 0xa2, 0x41, 0x2f, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x9c, 0x83, 0x22, 0x40,
+ 0x8f, 0x6c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xfe, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xdb, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x9c, 0x83, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x7c, 0x16, 0x20, 0xf6,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x31, 0xb3, 0x01, 0x00,
+ 0x80, 0x83, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51,
+ 0xfd, 0x93, 0x01, 0x00, 0x82, 0x83, 0x22, 0x40, 0x8f, 0x7c, 0x00, 0x00,
+ 0x86, 0x83, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00, 0x84, 0x83, 0x22, 0x42,
+ 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xfd, 0x93, 0x01, 0x00,
+ 0x86, 0x83, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53,
+ 0xfd, 0x93, 0x01, 0x00, 0x9a, 0x83, 0x22, 0x51, 0xfd, 0x7f, 0x00, 0x00,
+ 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x95, 0x83, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x48, 0x96, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x4b,
+ 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x99, 0x83, 0x22, 0x40,
+ 0xb5, 0x6f, 0x00, 0x00, 0x9d, 0x83, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xfe,
+ 0x7f, 0xd9, 0x01, 0x00, 0x9d, 0x83, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x41, 0x99, 0xb3, 0x01, 0x00, 0xa8, 0x83, 0x22, 0x44,
+ 0x81, 0x6c, 0x00, 0x00, 0xb0, 0x83, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00,
+ 0xaa, 0x83, 0x22, 0x4c, 0x81, 0x6c, 0x00, 0x00, 0xb4, 0x83, 0x22, 0x50,
+ 0x81, 0x6c, 0x00, 0x00, 0xb5, 0x83, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00,
+ 0xb7, 0x83, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00, 0xbc, 0x83, 0x22, 0x5c,
+ 0x81, 0x6c, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xbc, 0x09, 0xb0, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca,
+ 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf3, 0x83, 0x01, 0x00, 0xae, 0x83, 0xa2, 0x42,
+ 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00,
+ 0x6a, 0x84, 0x22, 0xca, 0x07, 0x14, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x45,
+ 0xf3, 0x93, 0x00, 0x00, 0x6a, 0x84, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00,
+ 0x6a, 0x84, 0x80, 0xca, 0x05, 0x30, 0x00, 0x00, 0x6a, 0x84, 0x22, 0x01,
+ 0x80, 0x30, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00,
+ 0x5c, 0x01, 0x00, 0xbc, 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
+ 0xb1, 0xb3, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xca, 0x81, 0x88, 0x01, 0x00, 0x6a, 0x84, 0xa2, 0x40,
+ 0x74, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00,
+ 0xb9, 0x83, 0xa8, 0xb1, 0x82, 0x30, 0x00, 0x00, 0xb8, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xbf, 0x83, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xca, 0x83, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a,
+ 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0xc8, 0x83, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xca, 0x83, 0x56, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00,
+ 0xf3, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xcf, 0x83, 0xa2, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xda, 0x83, 0x91, 0x81,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00,
+ 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0xd8, 0x83, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xda, 0x83, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x41,
+ 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, 0x5c, 0x01, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40, 0x8d, 0xb0, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x90, 0xb0, 0x01, 0x00,
+ 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00,
+ 0x6a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa6,
+ 0x80, 0xb0, 0x01, 0x00, 0xec, 0x83, 0x22, 0x40, 0x82, 0x6c, 0x00, 0x00,
+ 0xf0, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x47, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00,
+ 0xf5, 0x83, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, 0xe7, 0x83, 0xa2, 0x41,
+ 0x93, 0x50, 0x00, 0x00, 0xe5, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf5, 0x9f, 0x00, 0x47, 0x80, 0x30, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, 0xf0, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x50, 0xb3, 0x01, 0x00,
+ 0xfb, 0x83, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6,
+ 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0xfe, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x50, 0xd3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x4e, 0xd3, 0x01, 0x00, 0x5e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6c, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00, 0xf0, 0x83, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x07, 0x84, 0x22, 0xa7, 0x8f, 0x6c, 0x00, 0x00,
+ 0x49, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x09, 0x84, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xac, 0x94, 0x2e, 0x43,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x0d, 0x84, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, 0xa3, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x60, 0x15, 0x00, 0x40,
+ 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x40, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x41,
+ 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0x13, 0x84, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00, 0x49, 0x84, 0xa2, 0x41,
+ 0x01, 0x7d, 0x00, 0x00, 0x21, 0x84, 0x22, 0x58, 0x73, 0x7d, 0x00, 0x00,
+ 0x78, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x1c, 0x84, 0xa8, 0xb1,
+ 0x9c, 0x30, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x0e, 0x10, 0xc9, 0x00, 0x00, 0x21, 0x84, 0x33, 0xc4,
+ 0x81, 0x30, 0x00, 0x00, 0x24, 0x84, 0xa1, 0xad, 0x9d, 0x20, 0x00, 0x00,
+ 0x1b, 0x84, 0x13, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4e,
+ 0x5a, 0x83, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00,
+ 0x2c, 0x84, 0x22, 0xab, 0x80, 0x04, 0x00, 0x00, 0x2a, 0x84, 0xa2, 0x40,
+ 0x01, 0x7d, 0x00, 0x00, 0x2c, 0x84, 0x22, 0x5f, 0x57, 0x7d, 0x00, 0x00,
+ 0x21, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x84, 0x22, 0x5e,
+ 0x57, 0x7d, 0x00, 0x00, 0x84, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x31, 0x84, 0x22, 0x54, 0x73, 0x7d, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x2c, 0x84, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00,
+ 0xfa, 0x85, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00, 0x5c, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x33, 0x84, 0xa2, 0x5f, 0x59, 0x27, 0x00, 0x00,
+ 0x35, 0x84, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00, 0x3c, 0x84, 0xa2, 0x5e,
+ 0x73, 0x7d, 0x00, 0x00, 0x46, 0x84, 0x22, 0x5c, 0x73, 0x7d, 0x00, 0x00,
+ 0x47, 0x84, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x36, 0x84, 0xa8, 0xb1, 0x36, 0x30, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x38, 0x84, 0xa8, 0xb1,
+ 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x02, 0x88, 0x01, 0x00,
+ 0x29, 0x86, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x47, 0x84, 0x34, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x3d, 0x84, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, 0x44, 0x84, 0x52, 0x21,
+ 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41, 0x2f, 0xc3, 0x01, 0x00,
+ 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x01, 0xf0, 0x01, 0x00, 0x87, 0x84, 0x00, 0x34, 0x13, 0x84, 0x00, 0x00,
+ 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00, 0xe5, 0x84, 0x00, 0x43,
+ 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x47, 0x84, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x13, 0x4e,
+ 0x5a, 0x93, 0x00, 0x00, 0xe6, 0x89, 0xa2, 0x48, 0xfd, 0x7f, 0x00, 0x00,
+ 0x4e, 0x84, 0x22, 0x59, 0x73, 0x7d, 0x00, 0x00, 0x79, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x4a, 0x84, 0x28, 0xb1, 0x7e, 0x31, 0x00, 0x00,
+ 0x4b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x52, 0x84, 0x21, 0xac,
+ 0x9c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x1f, 0xc3, 0x01, 0x00,
+ 0x04, 0x00, 0xa0, 0x5f, 0x9d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x58, 0x91, 0x01, 0x00, 0x56, 0x84, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00,
+ 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x53, 0x84, 0xa8, 0xb1,
+ 0x7e, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcf, 0x11, 0xc9, 0x00, 0x00,
+ 0x5c, 0x84, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, 0x5c, 0x84, 0x22, 0x44,
+ 0x93, 0x7f, 0x00, 0x00, 0x58, 0x84, 0x42, 0xa5, 0x80, 0x30, 0x00, 0x00,
+ 0x5b, 0x84, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, 0x71, 0x84, 0x1a, 0x40,
+ 0x93, 0x93, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x9a, 0x80, 0xa2, 0x40, 0x73, 0x7d, 0x00, 0x00, 0x9b, 0x89, 0x22, 0x44,
+ 0x21, 0x6f, 0x00, 0x00, 0x92, 0x89, 0x22, 0x40, 0x65, 0x7d, 0x00, 0x00,
+ 0xa0, 0x89, 0xa2, 0x5b, 0x73, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49,
+ 0x33, 0x7d, 0x00, 0x00, 0x66, 0x84, 0x22, 0x48, 0x33, 0x7d, 0x00, 0x00,
+ 0xff, 0x01, 0x00, 0x99, 0x80, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x98, 0x2f, 0x40, 0x33, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe0, 0xc1, 0x01, 0x00, 0x69, 0x84, 0x22, 0x40,
+ 0xaf, 0x6f, 0x00, 0x00, 0x69, 0x84, 0x22, 0x40, 0x81, 0x6f, 0x00, 0x00,
+ 0xef, 0x89, 0x1f, 0xa5, 0x82, 0x6f, 0x00, 0x00, 0x49, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x62, 0xb1, 0x01, 0x00, 0x1b, 0x84, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x6c, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6f, 0x84, 0x33, 0x40,
+ 0x1f, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00,
+ 0x73, 0x84, 0xa0, 0xce, 0x81, 0x50, 0x00, 0x00, 0x85, 0x84, 0xa0, 0xcd,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xb1, 0x81, 0xb0, 0x01, 0x00, 0x85, 0x84, 0x22, 0xb5,
+ 0x81, 0x14, 0x00, 0x00, 0x80, 0x15, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x77, 0x84, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb4,
+ 0x65, 0x97, 0x01, 0x00, 0xd0, 0x15, 0x2e, 0x40, 0x69, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x44, 0x93, 0x83, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2,
+ 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xb1, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5,
+ 0xf1, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x80, 0x84, 0xa8, 0xa1,
+ 0xe0, 0x31, 0x00, 0x00, 0x5c, 0x84, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00,
+ 0x5c, 0x84, 0xa2, 0x41, 0x67, 0x6f, 0x00, 0x00, 0x5c, 0x84, 0x00, 0x6f,
+ 0xdb, 0x91, 0x00, 0x00, 0x85, 0x84, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x5c, 0x84, 0x1a, 0x40, 0x93, 0x83, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09,
+ 0x46, 0xc9, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00,
+ 0x90, 0x84, 0xa6, 0x42, 0x13, 0x60, 0x00, 0x00, 0x3f, 0x97, 0x00, 0x95,
+ 0x03, 0x30, 0x01, 0x00, 0x8b, 0x84, 0x45, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x75, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x8c, 0x84, 0xa8, 0xb1,
+ 0x0c, 0x30, 0x00, 0x00, 0x46, 0x97, 0x1d, 0x10, 0x94, 0x30, 0x01, 0x00,
+ 0x91, 0x84, 0x00, 0x58, 0x1f, 0x90, 0x00, 0x00, 0x38, 0x97, 0x00, 0x95,
+ 0x03, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0,
+ 0x2e, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x98, 0x84, 0x23, 0x4b, 0xe4, 0x6d, 0x00, 0x00, 0x98, 0x84, 0x22, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00,
+ 0x22, 0x00, 0x2f, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x9b, 0x84, 0x83, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x9d, 0x84, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x47, 0xc1, 0x01, 0x00, 0xa2, 0x84, 0x22, 0x55, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x43, 0xd1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x97, 0xe0, 0x01, 0x00,
+ 0xa3, 0x84, 0x00, 0x4b, 0x44, 0xc1, 0x00, 0x00, 0x12, 0x00, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x28, 0xf0, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0x2a, 0xb0, 0x01, 0x00, 0xc0, 0x28, 0x3c, 0x46, 0x0d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x44, 0x95, 0xb0, 0x01, 0x00, 0xaf, 0x84, 0xa2, 0xf8,
+ 0x0e, 0x30, 0x00, 0x00, 0xbf, 0x84, 0x22, 0x41, 0x95, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xab, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xac, 0x84, 0xa2, 0xf8, 0x16, 0x6c, 0x00, 0x00,
+ 0xac, 0x84, 0xa2, 0xf8, 0x10, 0x6c, 0x00, 0x00, 0xac, 0x84, 0xa2, 0xf0,
+ 0x1a, 0x6c, 0x00, 0x00, 0xbd, 0x84, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0xb4, 0x84, 0x47, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xb8, 0x84, 0xa2, 0xf3, 0x74, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0xe6, 0x95, 0x01, 0x00, 0xbd, 0x84, 0x1f, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x96, 0xb0, 0x01, 0x00,
+ 0x3f, 0x00, 0x1f, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0xbb, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xbd, 0x84, 0x47, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xc5, 0x84, 0x1f, 0x41, 0x2d, 0xc3, 0x00, 0x00,
+ 0xc3, 0x84, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x62, 0xb1, 0x01, 0x00,
+ 0xc1, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc3, 0x84, 0x47, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xec, 0x84, 0x1f, 0x41, 0x2d, 0xc3, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07,
+ 0x16, 0x30, 0x01, 0x00, 0xd3, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00,
+ 0xcb, 0x84, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xd2, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00,
+ 0xff, 0x96, 0x00, 0x5f, 0x01, 0x10, 0x01, 0x00, 0xd1, 0x84, 0x22, 0x40,
+ 0x95, 0x6c, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xdb, 0x84, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xdb, 0x84, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0xd8, 0x84, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42,
+ 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xde, 0x84, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00,
+ 0x66, 0x8b, 0x00, 0x45, 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6,
+ 0x96, 0xb0, 0x01, 0x00, 0xe2, 0x84, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00,
+ 0xf5, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x4b,
+ 0x8f, 0xb0, 0x00, 0x00, 0x0b, 0x97, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00,
+ 0xe7, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x50, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xe9, 0x84, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x17, 0xb0, 0x01, 0x00, 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00,
+ 0xee, 0x07, 0x2e, 0x47, 0x97, 0x90, 0x01, 0x00, 0xff, 0x84, 0x22, 0x17,
+ 0x96, 0x04, 0x00, 0x00, 0xfd, 0x84, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0xfd, 0x84, 0x23, 0xa2, 0x02, 0x6c, 0x00, 0x00, 0x74, 0x96, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x0c, 0x00, 0x2d, 0x00, 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00,
+ 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00,
+ 0x1c, 0x85, 0x00, 0x5c, 0x17, 0x90, 0x00, 0x00, 0x11, 0x85, 0x22, 0x43,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00,
+ 0x0a, 0x85, 0x22, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0xe0, 0xc9, 0x01, 0x00, 0x06, 0x85, 0x45, 0x42, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x07, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x1d, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6,
+ 0x80, 0x88, 0x01, 0x00, 0x0e, 0x85, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00,
+ 0x11, 0x85, 0x00, 0xf2, 0x3a, 0xb0, 0x00, 0x00, 0xf7, 0x85, 0xa2, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1c, 0x85, 0x22, 0x4a,
+ 0x2f, 0x7c, 0x00, 0x00, 0x1c, 0x85, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00,
+ 0x0a, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2,
+ 0x86, 0x88, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x43, 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42,
+ 0x81, 0xe0, 0x01, 0x00, 0x1c, 0x85, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00,
+ 0xf7, 0x85, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x1c, 0x85, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3,
+ 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x41, 0x47, 0xc3, 0x01, 0x00,
+ 0x22, 0x85, 0x22, 0xa1, 0x09, 0x6c, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x1f, 0x85, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00,
+ 0x5b, 0x85, 0xa3, 0x92, 0x03, 0x6c, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x40,
+ 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00,
+ 0x15, 0x8a, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x28, 0x85, 0x22, 0x5c,
+ 0x17, 0x7c, 0x00, 0x00, 0x29, 0x85, 0x00, 0x00, 0x2a, 0xb0, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x02, 0x00, 0x00, 0x08,
+ 0x80, 0xc8, 0x01, 0x00, 0x2d, 0x85, 0xa2, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0xf8, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x49, 0x85, 0x00, 0x5e,
+ 0x17, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00,
+ 0xf8, 0x97, 0x00, 0x4c, 0x03, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46,
+ 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x36, 0x85, 0xa8, 0x54, 0x17, 0x10, 0x00, 0x00, 0x49, 0x85, 0x00, 0x5e,
+ 0x17, 0x90, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00,
+ 0x48, 0x85, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01,
+ 0x8c, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x03, 0xb0, 0x01, 0x00,
+ 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46,
+ 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x09,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x49, 0x85, 0x28, 0x54, 0x17, 0x10, 0x00, 0x00, 0x45, 0x85, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00,
+ 0x4b, 0x85, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56,
+ 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00,
+ 0x4e, 0x85, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x17, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x56, 0x85, 0x22, 0x43,
+ 0x2f, 0x7c, 0x00, 0x00, 0x16, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0xe4, 0xb1, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0x59, 0x85, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00,
+ 0xb9, 0x94, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x5d, 0x85, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xf4, 0x85, 0x00, 0x41,
+ 0x43, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x5f, 0x85, 0x35, 0x01,
+ 0x86, 0x30, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x66, 0x85, 0x28, 0xb1, 0x30, 0x30, 0x00, 0x00, 0x60, 0x85, 0x22, 0x4d,
+ 0x75, 0x7d, 0x00, 0x00, 0xe4, 0x85, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0xf3, 0x85, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x66, 0x85, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, 0x6f, 0x85, 0xa2, 0x40,
+ 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x2c, 0xb0, 0x01, 0x00, 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00,
+ 0x60, 0x85, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x74, 0x85, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00,
+ 0x60, 0x85, 0xa3, 0x0b, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40,
+ 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40,
+ 0x39, 0xb0, 0x01, 0x00, 0x7c, 0x85, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x08, 0x12, 0xc8, 0x01, 0x00, 0xde, 0x07, 0x00, 0x40,
+ 0x25, 0x98, 0x01, 0x00, 0x7f, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x30, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x20, 0x01,
+ 0xe0, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00,
+ 0x84, 0x85, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x36, 0xb0, 0x01, 0x00, 0x8f, 0x85, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x8b, 0x85, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x88, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xeb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x44, 0xc9, 0x01, 0x00, 0x9e, 0x85, 0x22, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19,
+ 0x62, 0xdd, 0x01, 0x00, 0x95, 0x85, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x33, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00,
+ 0x0c, 0x00, 0x2d, 0x4c, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x37, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00,
+ 0x84, 0x85, 0x00, 0x45, 0x1f, 0x80, 0x00, 0x00, 0xa0, 0x85, 0xa3, 0x12,
+ 0x36, 0x6c, 0x00, 0x00, 0xa1, 0x85, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x68, 0x12, 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19,
+ 0x62, 0xdd, 0x01, 0x00, 0xa4, 0x85, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00,
+ 0xca, 0x85, 0x22, 0x14, 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x33, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00,
+ 0x0c, 0x00, 0x2d, 0x14, 0x12, 0xc0, 0x01, 0x00, 0xc3, 0x85, 0xa2, 0x14,
+ 0x36, 0x50, 0x00, 0x00, 0xb4, 0x85, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xb2, 0x85, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xaf, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x2b, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x37, 0x98, 0x01, 0x00, 0xb9, 0x85, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, 0xc4, 0x85, 0x22, 0x1b,
+ 0x02, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x15, 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0xc0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc4, 0x85, 0x00, 0x03,
+ 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2a, 0xc0, 0x01, 0x00,
+ 0x84, 0x85, 0xa2, 0x40, 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x39, 0xc0, 0x01, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x12, 0xb0, 0x01, 0x00, 0x84, 0x85, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0xd0, 0x85, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0xcd, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xeb, 0x95, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0xd4, 0x85, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17,
+ 0x98, 0x88, 0x01, 0x00, 0xd7, 0x85, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00, 0xda, 0x85, 0x22, 0x43,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00,
+ 0x16, 0x00, 0x20, 0x1d, 0xe4, 0xb1, 0x01, 0x00, 0xdc, 0x85, 0xa3, 0x40,
+ 0x27, 0x6c, 0x00, 0x00, 0xde, 0x85, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00,
+ 0x00, 0x84, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13,
+ 0x16, 0x94, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00,
+ 0x15, 0x8a, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00,
+ 0xb9, 0x94, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xf3, 0x85, 0x22, 0x13, 0x82, 0x6c, 0x00, 0x00,
+ 0x40, 0x00, 0x3d, 0x43, 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, 0xee, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00,
+ 0xf0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xea, 0x85, 0x00, 0x41,
+ 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0x74, 0x96, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x01, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0e, 0xf4, 0x01, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07,
+ 0x16, 0x30, 0x01, 0x00, 0x05, 0x86, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00,
+ 0x03, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x04, 0x86, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x0d, 0x86, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0d, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0x0a, 0x86, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42,
+ 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00,
+ 0x13, 0x86, 0x22, 0x3a, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8e, 0xb0, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x17, 0x86, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40,
+ 0x01, 0xb0, 0x00, 0x00, 0x51, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x38, 0x97, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, 0x28, 0x20, 0x00, 0xa6,
+ 0x96, 0xb0, 0x01, 0x00, 0x20, 0x86, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00,
+ 0xf5, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x4c,
+ 0x8f, 0xb0, 0x00, 0x00, 0x22, 0x86, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x43, 0xc1, 0x01, 0x00, 0x24, 0x86, 0x85, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1,
+ 0x2a, 0xc8, 0x01, 0x00, 0x0b, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe7, 0x94, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x2e, 0x86, 0x46, 0x47,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x2f, 0x86, 0xa8, 0x1b, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x1e, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x54, 0x86, 0x01, 0xfb,
+ 0x08, 0x30, 0x00, 0x00, 0xa7, 0x86, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x14, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00,
+ 0x0b, 0x96, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x4a, 0x86, 0x22, 0x41,
+ 0x81, 0x6c, 0x00, 0x00, 0x3e, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x49, 0x86, 0x22, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00,
+ 0x42, 0x86, 0xa6, 0x5f, 0x0f, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x00, 0x40,
+ 0x05, 0x30, 0x01, 0x00, 0x47, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40,
+ 0x05, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x52, 0x86, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x52, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0x4f, 0x86, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42,
+ 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00,
+ 0x56, 0x86, 0x21, 0x04, 0x80, 0x20, 0x00, 0x00, 0x57, 0x86, 0x00, 0x40,
+ 0x10, 0xc9, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00,
+ 0x76, 0x86, 0x00, 0x43, 0x81, 0xb0, 0x00, 0x00, 0x7a, 0x86, 0x00, 0xfb,
+ 0x22, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00,
+ 0x66, 0x8b, 0x00, 0x4e, 0x8f, 0xb0, 0x00, 0x00, 0x72, 0x86, 0x00, 0x5a,
+ 0x8f, 0xb0, 0x00, 0x00, 0x5f, 0x86, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00,
+ 0xa8, 0x8a, 0x00, 0x53, 0x81, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x56,
+ 0x81, 0xb0, 0x00, 0x00, 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x66, 0x8b, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x65, 0x86, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x64, 0x86, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x66, 0x8b, 0x00, 0x53, 0x8f, 0xb0, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x54,
+ 0x8f, 0xb0, 0x00, 0x00, 0x6e, 0x86, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x68, 0x86, 0xa2, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x5d,
+ 0x8f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x80, 0xd0, 0x01, 0x00, 0x6c, 0x86, 0xa0, 0x91,
+ 0x81, 0x6c, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00,
+ 0x25, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x70, 0x86, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00,
+ 0x66, 0x8b, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x66, 0x8b, 0xa0, 0x0a,
+ 0xe4, 0x6d, 0x00, 0x00, 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x66, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00,
+ 0xa8, 0x8a, 0xa0, 0x42, 0x83, 0x6c, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x54,
+ 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00,
+ 0x83, 0x86, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0x95, 0x86, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00,
+ 0x90, 0x86, 0xa2, 0x54, 0xfd, 0x7f, 0x00, 0x00, 0x88, 0x86, 0x22, 0x55,
+ 0xfd, 0x7f, 0x00, 0x00, 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x80, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x86, 0x22, 0x53,
+ 0xfd, 0x7f, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b,
+ 0x80, 0xf4, 0x01, 0x00, 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x90, 0x86, 0x22, 0x43, 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b,
+ 0x80, 0x88, 0x01, 0x00, 0x80, 0x86, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00,
+ 0x7c, 0x96, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x91, 0x86, 0x43, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x94, 0x86, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00,
+ 0x86, 0x86, 0x1b, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x41,
+ 0x31, 0xc3, 0x01, 0x00, 0x90, 0x95, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00,
+ 0x99, 0x86, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00,
+ 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x07, 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c,
+ 0xe0, 0x99, 0x01, 0x00, 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xa0, 0x86, 0x30, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xa8, 0x8a, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x14, 0xb0, 0x01, 0x00, 0xb1, 0x86, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00,
+ 0xad, 0x86, 0x22, 0x40, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x1f, 0x90, 0x01, 0x00, 0xaf, 0x86, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x1f, 0x90, 0x01, 0x00, 0xb1, 0x86, 0x22, 0x42,
+ 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00,
+ 0xb1, 0x86, 0x47, 0x1b, 0x2c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x41, 0x41, 0xc3, 0x01, 0x00,
+ 0xe0, 0x86, 0x23, 0x92, 0x15, 0x6c, 0x00, 0x00, 0xe0, 0x86, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0xe4, 0x86, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x27, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x0a, 0x24, 0xc8, 0x01, 0x00,
+ 0xc7, 0x95, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0xde, 0x86, 0x22, 0x08,
+ 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x12, 0x24, 0xcc, 0x01, 0x00, 0xba, 0x86, 0xaa, 0x41,
+ 0x27, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00,
+ 0xda, 0x86, 0x26, 0x40, 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0,
+ 0xa2, 0xc9, 0x01, 0x00, 0xc7, 0x86, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00,
+ 0xd3, 0x86, 0x00, 0x41, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xcc, 0x86, 0xa2, 0x44,
+ 0x23, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xcf, 0x86, 0xa8, 0x42,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa3, 0xc1, 0x01, 0x00, 0xc5, 0x86, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0xda, 0x86, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd7, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0xee, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0,
+ 0x2a, 0xc8, 0x01, 0x00, 0xed, 0x86, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00,
+ 0xaa, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe4, 0x86, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x92, 0x25, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x31, 0xb0, 0x01, 0x00, 0xe4, 0x86, 0x22, 0x08,
+ 0x2e, 0x30, 0x00, 0x00, 0xed, 0x86, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00,
+ 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0xec, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0x6b, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xff, 0x89, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01,
+ 0x80, 0xce, 0x01, 0x00, 0x01, 0x87, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0xf6, 0x86, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0xf6, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xf6, 0x86, 0xa3, 0x07,
+ 0x03, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0xf9, 0x86, 0xa3, 0x40, 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01,
+ 0xf0, 0xcd, 0x01, 0x00, 0xfb, 0x86, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x0e, 0xcc, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xff, 0x86, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x08, 0xb0, 0x01, 0x00, 0xa0, 0x01, 0x2d, 0x40,
+ 0x00, 0xc0, 0x01, 0x00, 0xe7, 0x88, 0x22, 0x0f, 0x42, 0x05, 0x00, 0x00,
+ 0x12, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x0d, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x0a, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x12, 0x87, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0xd1, 0x87, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x54, 0x29, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x42, 0x00, 0x00, 0x03,
+ 0x0a, 0xc8, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08,
+ 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0xfe, 0x7f, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x23, 0x87, 0x20, 0x94,
+ 0x15, 0x6c, 0x00, 0x00, 0x24, 0x87, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00, 0x3d, 0x87, 0x22, 0x01,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x2a, 0x87, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00,
+ 0x2b, 0x87, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0x37, 0x87, 0x22, 0x40,
+ 0x03, 0x6c, 0x00, 0x00, 0x37, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x5f, 0x87, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x34, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0x39, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5f, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x42, 0x87, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00,
+ 0x43, 0x87, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12,
+ 0x1a, 0xb0, 0x01, 0x00, 0x46, 0x87, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x11, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x4a, 0x87, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x7d, 0x87, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00,
+ 0x50, 0x87, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x54, 0x87, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x56, 0x87, 0x22, 0x42,
+ 0x23, 0x6c, 0x00, 0x00, 0x5f, 0x87, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x57, 0x87, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x5d, 0x87, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00,
+ 0xfb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x7d, 0x87, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x7c, 0x87, 0xa2, 0x0d,
+ 0x0e, 0x50, 0x00, 0x00, 0x6b, 0x87, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x69, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x66, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x70, 0x87, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x24, 0x87, 0x00, 0x4c,
+ 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00,
+ 0x24, 0x87, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x79, 0x87, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0x24, 0x87, 0x00, 0x03,
+ 0x0c, 0xb0, 0x00, 0x00, 0x24, 0x87, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00,
+ 0x04, 0x00, 0x2e, 0x14, 0x0a, 0xd0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05,
+ 0x48, 0xcd, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00,
+ 0x0c, 0x00, 0x2a, 0xf2, 0xe0, 0xb1, 0x01, 0x00, 0x83, 0x87, 0x22, 0x40,
+ 0x31, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6,
+ 0x80, 0xce, 0x01, 0x00, 0x87, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x43, 0xc1, 0x01, 0x00, 0x89, 0x87, 0x22, 0x0b,
+ 0xed, 0x6d, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa,
+ 0x94, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xb0, 0x01, 0x00, 0x91, 0x87, 0x22, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00,
+ 0x91, 0x87, 0xa0, 0x46, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xc0, 0x01, 0x00, 0x95, 0x87, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2,
+ 0x42, 0x31, 0x00, 0x00, 0x98, 0x87, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0xa2, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x82, 0xb0, 0x01, 0x00, 0x9b, 0x87, 0xa0, 0x41,
+ 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00,
+ 0xa0, 0x87, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xa0, 0x87, 0xa0, 0x43,
+ 0x89, 0x6c, 0x00, 0x00, 0xa0, 0x87, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00,
+ 0xa0, 0x87, 0xa0, 0x41, 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00,
+ 0x98, 0x87, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0xa9, 0x87, 0x22, 0x48,
+ 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x48, 0x90, 0x88, 0x01, 0x00, 0xa7, 0x87, 0x90, 0x48,
+ 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x93, 0xa4, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x14, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0xf0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, 0xe0, 0xcd, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00,
+ 0xaf, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xbc, 0x87, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xb9, 0x87, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xb6, 0x87, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xbc, 0x87, 0x87, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xfb, 0x95, 0x00, 0x41, 0x23, 0x40, 0x01, 0x00,
+ 0xbe, 0x87, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x52, 0x89, 0x00, 0x17,
+ 0x10, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0xc1, 0x87, 0xa0, 0x07, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xc5, 0x87, 0x90, 0xf2,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14,
+ 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xcf, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xcc, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17,
+ 0x10, 0xdc, 0x01, 0x00, 0x52, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x90, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd5, 0x87, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4,
+ 0x0c, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x1b, 0x88, 0x22, 0x01,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0xea, 0x87, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00,
+ 0xeb, 0x87, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xfd, 0x87, 0x22, 0x40,
+ 0x03, 0x6c, 0x00, 0x00, 0xf7, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x37, 0x88, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xf9, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x37, 0x88, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xff, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0x0b, 0x88, 0x23, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00,
+ 0x37, 0x88, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d,
+ 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x13, 0x88, 0x22, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x37, 0x88, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14,
+ 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x37, 0x88, 0x00, 0x1a,
+ 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x20, 0x88, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00,
+ 0x21, 0x88, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12,
+ 0x1a, 0xb0, 0x01, 0x00, 0x24, 0x88, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x11, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x28, 0x88, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x54, 0x88, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00,
+ 0x54, 0x88, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x2f, 0x88, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x37, 0x88, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x30, 0x88, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0xfb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x53, 0x88, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x42, 0x88, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x40, 0x88, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x3d, 0x88, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x04, 0xb0, 0x01, 0x00, 0x47, 0x88, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00,
+ 0xe4, 0x87, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f,
+ 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x87, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x50, 0x88, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0xe4, 0x87, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xe4, 0x87, 0x00, 0x0d,
+ 0x18, 0xc0, 0x00, 0x00, 0x71, 0x88, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50,
+ 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d,
+ 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00,
+ 0x66, 0x88, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xc0, 0x01, 0x00, 0x64, 0x88, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00,
+ 0x04, 0x80, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x48, 0xc1, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x18,
+ 0x90, 0xb0, 0x01, 0x00, 0x6e, 0x88, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, 0x6c, 0x88, 0xa2, 0x41,
+ 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00,
+ 0x76, 0x88, 0x42, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x41, 0x3d, 0xc3, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e,
+ 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d, 0x82, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x80, 0xc0, 0x01, 0x00, 0x80, 0x88, 0xa0, 0x41, 0x80, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30, 0x81, 0x84, 0x01, 0x00,
+ 0x84, 0x88, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x93, 0xa4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x19,
+ 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x16, 0xc0, 0x01, 0x00,
+ 0x8a, 0x88, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e, 0x32, 0xc0, 0x01, 0x00,
+ 0x8f, 0x88, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00, 0x8e, 0x88, 0xa0, 0x1c,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e, 0x98, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00, 0x0c, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x9d, 0x88, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x9b, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x98, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x1a,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0xa3, 0x88, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xb1, 0x88, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0xad, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xaa, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0xfb, 0x95, 0x00, 0x41, 0x23, 0x40, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x17, 0xf0, 0x01, 0x00, 0xb6, 0x88, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xc1, 0x88, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xbe, 0x88, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, 0xde, 0x88, 0x22, 0x40,
+ 0x15, 0x6c, 0x00, 0x00, 0xc9, 0x88, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00, 0xc8, 0x88, 0x22, 0x9f,
+ 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00,
+ 0x6b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x3f, 0xc3, 0x01, 0x00, 0x4e, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xcc, 0x88, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+ 0x3e, 0xc0, 0x01, 0x00, 0xde, 0x88, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00,
+ 0xcf, 0x88, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x3c, 0xb0, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x1e, 0x24, 0x30, 0x01, 0x00,
+ 0xd4, 0x88, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x10, 0xc0, 0x01, 0x00,
+ 0x37, 0x88, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd1, 0x88, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6,
+ 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04,
+ 0xe0, 0x31, 0x00, 0x00, 0x3d, 0x99, 0x00, 0x1f, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0x4e, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe3, 0x88, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00,
+ 0xe4, 0x88, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x3d, 0x99, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0xef, 0x88, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xef, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xec, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf4, 0x88, 0x22, 0x07,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xf7, 0x88, 0x20, 0x94,
+ 0x15, 0x6c, 0x00, 0x00, 0xf8, 0x88, 0x00, 0x94, 0xe1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xfb, 0x88, 0x22, 0x40,
+ 0x31, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x89, 0xa8, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00,
+ 0x0e, 0x89, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, 0x0f, 0x89, 0x68, 0x07,
+ 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, 0x1a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00,
+ 0x14, 0x89, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x45, 0x89, 0x22, 0x0d,
+ 0x14, 0x6c, 0x00, 0x00, 0x1a, 0x89, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x89, 0x00, 0x0d,
+ 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20,
+ 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00,
+ 0x20, 0x89, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0x27, 0x89, 0x00, 0x41,
+ 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x21, 0x89, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x43,
+ 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x44, 0x89, 0xa2, 0x0d,
+ 0x0e, 0x50, 0x00, 0x00, 0x33, 0x89, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x31, 0x89, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x2e, 0x89, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x38, 0x89, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x09, 0x89, 0x00, 0x4c,
+ 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00,
+ 0x09, 0x89, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x41, 0x89, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0x09, 0x89, 0x00, 0x03,
+ 0x0c, 0xb0, 0x00, 0x00, 0x09, 0x89, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00,
+ 0x4e, 0x89, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x4e, 0x89, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4b, 0x89, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x41,
+ 0x23, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0xb0, 0x01, 0x00,
+ 0x52, 0x89, 0x00, 0x40, 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe0, 0xb1, 0x01, 0x00,
+ 0x57, 0x89, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88,
+ 0x1c, 0xcc, 0x01, 0x00, 0x6b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x4e, 0x99, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x3d, 0x99, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00,
+ 0x66, 0x89, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x64, 0x89, 0x22, 0x42,
+ 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x65, 0x89, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0xff, 0x89, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0x6e, 0x89, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x6e, 0x89, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0x6b, 0x89, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x66, 0x96, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xce, 0x99, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x01, 0x00, 0xa8, 0x8a, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00,
+ 0xa8, 0x00, 0x2d, 0x43, 0x19, 0x80, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x8e, 0xf4, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00, 0x7d, 0x89, 0x22, 0x48,
+ 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x7d, 0x89, 0x1f, 0xf0,
+ 0x24, 0x6c, 0x00, 0x00, 0x7c, 0x89, 0x23, 0x41, 0x8f, 0x6c, 0x00, 0x00,
+ 0xa8, 0x8a, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x48,
+ 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0x82, 0x89, 0x22, 0x0a,
+ 0x90, 0x40, 0x00, 0x00, 0x21, 0x99, 0x00, 0x40, 0x91, 0x30, 0x01, 0x00,
+ 0xa8, 0x8a, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0xb0, 0x00, 0x2d, 0x45,
+ 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x89, 0x22, 0xf0, 0x2c, 0x30, 0x00, 0x00,
+ 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf3,
+ 0x82, 0xe0, 0x01, 0x00, 0x88, 0x89, 0xa3, 0x41, 0x2c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0xf0,
+ 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x82, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00, 0xa8, 0x8a, 0x20, 0x4c,
+ 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41, 0x98, 0xe8, 0x01, 0x00,
+ 0xa8, 0x8a, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00, 0xff, 0x89, 0x22, 0x0a,
+ 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00,
+ 0xff, 0x89, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x49,
+ 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00,
+ 0x96, 0x89, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x13, 0x80, 0x00, 0x40,
+ 0x80, 0xdc, 0x01, 0x00, 0x97, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x97, 0x89, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0xb1, 0x01, 0x00,
+ 0x99, 0x89, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00, 0x9d, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x5f, 0x84, 0x22, 0x40, 0x57, 0x7d, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00, 0x9d, 0x89, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x49, 0x84, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xa0, 0x89, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00,
+ 0xc9, 0x89, 0x1d, 0x40, 0x80, 0x32, 0x00, 0x00, 0xba, 0x89, 0x22, 0x40,
+ 0xaf, 0x6f, 0x00, 0x00, 0xba, 0x89, 0x22, 0x5b, 0x81, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5d, 0x73, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xa6, 0x89, 0xa8, 0xb1, 0x94, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x62, 0xb1, 0x01, 0x00, 0xa9, 0x89, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xab, 0x89, 0x43, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb9, 0x89, 0x22, 0x57,
+ 0x73, 0x7d, 0x00, 0x00, 0x77, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xad, 0x89, 0xa8, 0xb1, 0x94, 0x30, 0x00, 0x00, 0x77, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xaf, 0x89, 0xa8, 0xb1, 0x96, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x62, 0xb1, 0x01, 0x00, 0xb2, 0x89, 0xa8, 0x4a, 0x80, 0x33, 0x00, 0x00,
+ 0xb7, 0x89, 0x22, 0x5f, 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0xb5, 0x89, 0xa8, 0x4b, 0xac, 0x33, 0x00, 0x00,
+ 0x00, 0x00, 0x1b, 0xa5, 0x82, 0xb3, 0x01, 0x00, 0xba, 0x89, 0x00, 0xbe,
+ 0x83, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb3, 0x01, 0x00,
+ 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0xc7, 0x89, 0xa2, 0x40, 0x86, 0x04, 0x00, 0x00,
+ 0x1b, 0x84, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x40,
+ 0x88, 0x88, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0xc3, 0x89, 0x52, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x89, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x48,
+ 0x47, 0x31, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x05, 0x47, 0x31, 0x01, 0x00,
+ 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00,
+ 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xd0, 0x89, 0x22, 0x54,
+ 0x81, 0x7c, 0x00, 0x00, 0xcb, 0x89, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0xb4, 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0xde, 0x89, 0x0f, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00,
+ 0xe3, 0x89, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44,
+ 0x88, 0xcc, 0x01, 0x00, 0xd6, 0x89, 0x99, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00, 0xd8, 0x89, 0x9b, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xd0, 0x01, 0x00,
+ 0xda, 0x89, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00, 0xe3, 0x89, 0x00, 0x40,
+ 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00,
+ 0xe3, 0x89, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x58,
+ 0x47, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x43,
+ 0x86, 0x88, 0x01, 0x00, 0x1b, 0x84, 0x26, 0x05, 0x47, 0x31, 0x00, 0x00,
+ 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb, 0x81, 0xc8, 0x01, 0x00,
+ 0xe9, 0x89, 0x22, 0x40, 0xf2, 0x7f, 0x00, 0x00, 0x81, 0x80, 0x00, 0x6f,
+ 0x97, 0x33, 0x01, 0x00, 0xeb, 0x89, 0x22, 0x40, 0x73, 0x7d, 0x00, 0x00,
+ 0x9b, 0x80, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xe6, 0x89, 0x22, 0x59,
+ 0x73, 0x7d, 0x00, 0x00, 0x79, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xe6, 0x89, 0x28, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xec, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0xc0, 0x95, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd6, 0x97, 0xb0, 0x01, 0x00, 0xf4, 0x89, 0x22, 0x5d,
+ 0x73, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xf2, 0x89, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x7f, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xc5, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf7, 0x89, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0xf9, 0x89, 0x43, 0x5f, 0x7f, 0x13, 0x00, 0x00, 0x26, 0x01, 0x00, 0xbf,
+ 0xc5, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x7f, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x7f, 0x93, 0x01, 0x00, 0x75, 0x98, 0x00, 0xbf,
+ 0xc5, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x06, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x06, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x03, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x62, 0x95, 0x22, 0x02,
+ 0x80, 0x32, 0x00, 0x00, 0x07, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x62, 0x95, 0x1a, 0x02,
+ 0x68, 0x97, 0x00, 0x00, 0x11, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x11, 0x8a, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0e, 0x8a, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x6c, 0x95, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x12, 0x8a, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x6c, 0x95, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00, 0x1c, 0x8a, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x1c, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x19, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x6f, 0x84, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0x1d, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00,
+ 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0x56, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x6d, 0x8a, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41,
+ 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x29, 0x00, 0x00, 0x40,
+ 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x51, 0x8a, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x32, 0x8a, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x84, 0x89, 0x01, 0x00, 0x39, 0x8a, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00,
+ 0x51, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x6e, 0x8a, 0x1c, 0xf0, 0x18, 0x30, 0x01, 0x00,
+ 0x51, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x48, 0x8a, 0xa0, 0x48, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a,
+ 0x42, 0xc9, 0x01, 0x00, 0x42, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a,
+ 0x62, 0xdd, 0x01, 0x00, 0x3f, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x6e, 0x8a, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00,
+ 0x43, 0x8a, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x10,
+ 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00,
+ 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x1a,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00,
+ 0x4c, 0x8a, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00, 0x5d, 0x8a, 0x22, 0x41,
+ 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00,
+ 0x59, 0x8a, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1b, 0xb0, 0x01, 0x00, 0x30, 0x8a, 0x00, 0x41, 0x17, 0xb0, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00, 0x30, 0x8a, 0x83, 0x41,
+ 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x30, 0x8a, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00, 0x68, 0x8a, 0x23, 0x40,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x65, 0x8a, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x62, 0x8a, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x6e, 0x8a, 0x00, 0xf8,
+ 0x18, 0x30, 0x01, 0x00, 0x66, 0x8a, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, 0x6b, 0x8a, 0xa0, 0xaa,
+ 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00,
+ 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x0c,
+ 0x7e, 0x89, 0x01, 0x00, 0x80, 0x8a, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00,
+ 0x76, 0x8a, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x40,
+ 0x62, 0x99, 0x01, 0x00, 0x76, 0x8a, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x76, 0x8a, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x72, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x8a, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00,
+ 0x77, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x8a, 0x22, 0x49,
+ 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54,
+ 0x77, 0x7d, 0x01, 0x00, 0x7b, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00,
+ 0x80, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55,
+ 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00,
+ 0x6f, 0x84, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x88, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x8b, 0x8a, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0xab, 0x27, 0xb3, 0x01, 0x00,
+ 0x6f, 0x84, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x84, 0x22, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x84, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00,
+ 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x34, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x97, 0x8a, 0x22, 0x40,
+ 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x35, 0x82, 0x00, 0x40,
+ 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0xff, 0x81, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xdb, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a,
+ 0xb4, 0x8b, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a,
+ 0xb4, 0xf7, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6f, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x40, 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00,
+ 0xae, 0x8a, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xd1, 0x8d, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x05, 0x8e, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x37, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x76, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x9f, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xaf, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xae, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x6f, 0x8f, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x6f, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x6f, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x9b, 0x8f, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xb9, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb9, 0x8f, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xb9, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe1, 0x8f, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0xf2, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xf2, 0x8f, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xf4, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xfc, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x0d, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0xfd, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x0d, 0x90, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x0e, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x6d, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x6d, 0x8f, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x6d, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x0f, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x0f, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x0f, 0x90, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x16, 0x90, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x18, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x24, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x8d, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x95, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xa3, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xa6, 0x90, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x73, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x91, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x20, 0x47,
+ 0xe6, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00,
+ 0x6e, 0x8b, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xbe, 0x90, 0x00, 0x49,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf7, 0x90, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfd, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x0b, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x27, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x86, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xe6, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xe6, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfe, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x27, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x87, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x86, 0x91, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x1b, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x1b, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x1b, 0x92, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x00, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x26, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x26, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x26, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x26, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x4d, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x4d, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xaf, 0x92, 0x00, 0x40, 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x1e, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xd3, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xe6, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x3d, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x31, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x3d, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x31, 0x92, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x31, 0x92, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd5, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd5, 0x92, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xd5, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xef, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xef, 0x92, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x19, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x18, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x19, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x18, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x92, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xec, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xec, 0x92, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xec, 0x92, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0xec, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xec, 0x92, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xfe, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xf2, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xb8, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x5f, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5f, 0x94, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x5f, 0x94, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5f, 0x94, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x5f, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x5f, 0x94, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7f, 0x94, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7f, 0x94, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xae, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xae, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6b, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xb6, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xb6, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x0a, 0x8a, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00,
+ 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0x21, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xca, 0x8d, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xca, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xc7, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x13, 0x86, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0xcb, 0x8d, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00,
+ 0x13, 0x86, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x05, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x0a, 0x8a, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xe0, 0xb1, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x06, 0x07, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b,
+ 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34,
+ 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00,
+ 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0xf4, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0xfc, 0x8d, 0x20, 0x4b,
+ 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0xf9, 0x8d, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x03, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xff, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x08, 0x8e, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x0b, 0x8e, 0xa2, 0x4c, 0xfd, 0x7f, 0x00, 0x00,
+ 0x0c, 0x8e, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00, 0x0d, 0x8e, 0x20, 0xf0,
+ 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x56, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x70, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x13, 0x8e, 0xa8, 0x44,
+ 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x62, 0xb1, 0x01, 0x00,
+ 0x1b, 0x8e, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x86, 0xe4, 0x01, 0x00,
+ 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x23, 0x8e, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x26, 0x8e, 0x22, 0x44,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x45, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00, 0x68, 0x01, 0x20, 0xa2,
+ 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x2a, 0x8e, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43,
+ 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x2f, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5c, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x41,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x3a, 0x8e, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x3e, 0x8e, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00,
+ 0x86, 0x00, 0x2f, 0x49, 0x19, 0x80, 0x01, 0x00, 0x3e, 0x8e, 0xa2, 0xf2,
+ 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xe7, 0x91, 0x01, 0x00, 0x41, 0x8e, 0xa2, 0x46,
+ 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x45, 0x8e, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46,
+ 0x19, 0x80, 0x01, 0x00, 0x45, 0x8e, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe7, 0x91, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x34, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x16, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00,
+ 0x70, 0x8e, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x58, 0x8e, 0x22, 0x0a,
+ 0x16, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0,
+ 0x84, 0x30, 0x00, 0x00, 0xe7, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00,
+ 0x57, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0x4d, 0x8e, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00,
+ 0x70, 0x8e, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43,
+ 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, 0xe7, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x70, 0x8e, 0x22, 0x41, 0x15, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00, 0x64, 0x8e, 0xa0, 0x43,
+ 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xee, 0x97, 0x00, 0x47,
+ 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x5f, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x6c, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x20, 0x98, 0x00, 0x51,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x78, 0x8e, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00,
+ 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x7d, 0x8e, 0x22, 0x45,
+ 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00,
+ 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x82, 0x8e, 0x22, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x02, 0x30, 0x00, 0x00, 0x90, 0x8e, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00,
+ 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x21, 0x99, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0x99, 0x8e, 0xa2, 0x44,
+ 0x81, 0x6c, 0x00, 0x00, 0x97, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x8a, 0x96, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xbd, 0x8e, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0x99, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbd, 0x8e, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01,
+ 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x78, 0x8e, 0x22, 0x4a,
+ 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x69, 0x96, 0x00, 0xf3,
+ 0x94, 0x30, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00,
+ 0x00, 0x8c, 0x01, 0x00, 0xcf, 0x8d, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00,
+ 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x8e, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00,
+ 0xb4, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x8a, 0x96, 0x00, 0x40,
+ 0x3b, 0x30, 0x01, 0x00, 0xb8, 0x8e, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb8, 0x8e, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x50, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0,
+ 0x38, 0xb0, 0x01, 0x00, 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x40, 0x00, 0x2d, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x14, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x81, 0xd0, 0x01, 0x00, 0xcb, 0x8e, 0x20, 0x94,
+ 0x81, 0x6c, 0x00, 0x00, 0xb5, 0x97, 0x00, 0x94, 0xe5, 0x31, 0x01, 0x00,
+ 0xcc, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x97, 0x00, 0x40,
+ 0xe4, 0x31, 0x01, 0x00, 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00,
+ 0xcc, 0x8e, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0xdc, 0x8e, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xd6, 0x8e, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xd3, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xfb, 0x95, 0x00, 0x43,
+ 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0xe4, 0x8e, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xe0, 0x8e, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00,
+ 0xe1, 0x8e, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x04, 0xb0, 0x01, 0x00, 0xe3, 0x8e, 0x20, 0x02, 0x36, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x01, 0x00, 0xe7, 0x8e, 0x00, 0x02,
+ 0xf0, 0xb1, 0x00, 0x00, 0xe6, 0x8e, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00,
+ 0xe7, 0x8e, 0x68, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01,
+ 0x04, 0xb0, 0x01, 0x00, 0xe9, 0x8e, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x01, 0x1f, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0xeb, 0x8e, 0xa8, 0x13,
+ 0xe0, 0x31, 0x00, 0x00, 0x22, 0x8f, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00, 0x12, 0x8f, 0xa2, 0x02,
+ 0x02, 0x50, 0x00, 0x00, 0xf9, 0x8e, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xf8, 0x8e, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xf4, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x2d, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00,
+ 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2f, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x13, 0x8f, 0x22, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0x06, 0x8f, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x1f, 0x80, 0x01, 0x00, 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x05, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x02, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x38, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2d, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xe1, 0xc1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x4a,
+ 0xf1, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x8f, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x38, 0xc0, 0x01, 0x00, 0x1d, 0x8f, 0x22, 0x06,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x1b, 0x8f, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x8f, 0x0d,
+ 0x42, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x10, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x37, 0x98, 0x01, 0x00, 0xcf, 0x8e, 0x00, 0xa1, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0xcf, 0x8e, 0x00, 0x02,
+ 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01,
+ 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0x27, 0x8f, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x46,
+ 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00,
+ 0x26, 0x8f, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x8f, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x2a, 0x8f, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xfb, 0x95, 0x00, 0x10, 0x48, 0x31, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x34, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x31, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x01, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x39, 0x8f, 0x90, 0xf2,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x32, 0x00, 0x00, 0xa6,
+ 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00,
+ 0x42, 0x8f, 0x22, 0x49, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x00, 0xf0, 0x00, 0x0c, 0x18, 0x8c, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x4c,
+ 0x95, 0x30, 0x01, 0x00, 0x52, 0x8f, 0x00, 0x00, 0x92, 0xb0, 0x00, 0x00,
+ 0x49, 0x8f, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x1e,
+ 0x94, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x96, 0xb0, 0x01, 0x00,
+ 0x72, 0x98, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, 0x48, 0x8f, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x5b, 0x8f, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00,
+ 0x52, 0x8f, 0x00, 0x00, 0x92, 0xb0, 0x00, 0x00, 0x49, 0x8f, 0x43, 0x48,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00,
+ 0x4e, 0x8f, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0x4a, 0x8f, 0x22, 0x48,
+ 0x77, 0x7d, 0x00, 0x00, 0x51, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x62, 0xb1, 0x01, 0x00, 0x5a, 0x8f, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x4e, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x1b, 0x00, 0x92, 0xb0, 0x01, 0x00, 0x57, 0x8f, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0xcc, 0x95, 0x00, 0xf8, 0x00, 0x30, 0x01, 0x00, 0x54, 0x8f, 0xa2, 0x41,
+ 0x3b, 0x50, 0x00, 0x00, 0x5b, 0x8f, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x1e, 0x00, 0x8c, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x5b, 0x8f, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x1b, 0x47, 0x19, 0x80, 0x01, 0x00, 0x5e, 0x8f, 0x22, 0x5f,
+ 0x01, 0x6c, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xaa, 0x8a, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x65, 0x8f, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x65, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x62, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x65, 0x8f, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x07, 0x94, 0x89, 0x01, 0x00, 0x6b, 0x8f, 0x85, 0xca,
+ 0x94, 0x30, 0x00, 0x00, 0x4b, 0x99, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00, 0x72, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x20, 0x98, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0x80, 0x01, 0x00, 0xcf, 0x8d, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00,
+ 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x72, 0x8f, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb5, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x78, 0x8f, 0x90, 0x4c,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x7a, 0x8f, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00,
+ 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2,
+ 0x80, 0xb0, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x81, 0x8f, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x81, 0xc0, 0x01, 0x00, 0x82, 0x8f, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00,
+ 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x88, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x94, 0x8f, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x08, 0x94, 0xdc, 0x01, 0x00, 0x72, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x92, 0x8f, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x08, 0x00, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x94, 0x8f, 0x43, 0x48,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00,
+ 0x9a, 0x8f, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0x95, 0x8f, 0x22, 0x48,
+ 0x77, 0x7d, 0x00, 0x00, 0xcc, 0x95, 0x1b, 0x08, 0x00, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x1b, 0x47,
+ 0x19, 0x80, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x63, 0xf3, 0x84, 0xc8, 0x01, 0x00, 0x9f, 0x8f, 0xa0, 0x43,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0xaa, 0x8f, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x44,
+ 0x83, 0x70, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xcf, 0x8d, 0x1f, 0xf0,
+ 0x24, 0x6c, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00,
+ 0xaa, 0x8a, 0x23, 0x41, 0x83, 0x6c, 0x00, 0x00, 0xaa, 0x8a, 0x00, 0x47,
+ 0x81, 0xb0, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x00, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xee, 0x97, 0x00, 0x47, 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x8e, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x7e, 0x8e, 0xa2, 0x40,
+ 0x8f, 0x7c, 0x00, 0x00, 0xb8, 0x8f, 0x22, 0x47, 0x8f, 0x7c, 0x00, 0x00,
+ 0x7e, 0x8e, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, 0x27, 0x90, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x5d, 0x05, 0xb4, 0x01, 0x00,
+ 0x37, 0x00, 0x2d, 0xf3, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x8e, 0xb0, 0x01, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00,
+ 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x86, 0xdc, 0x01, 0x00,
+ 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0xce, 0x94, 0x00, 0x4a,
+ 0xf0, 0x31, 0x01, 0x00, 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xc6, 0x8f, 0xa2, 0x50, 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xc9, 0x8f, 0xa0, 0x43,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x37, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x22, 0x47,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, 0x0c, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x8f, 0x84, 0x01, 0x00, 0xde, 0x8f, 0x22, 0x47,
+ 0x0c, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00,
+ 0xde, 0x8f, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xd7, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd4, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xd7, 0x8f, 0x42, 0x40, 0x05, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d,
+ 0x69, 0x93, 0x01, 0x00, 0xdc, 0x8f, 0x23, 0x41, 0x0d, 0x6c, 0x00, 0x00,
+ 0xb9, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x05,
+ 0x48, 0x31, 0x01, 0x00, 0xaa, 0x8a, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8d, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0x20, 0x98, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xa2, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x84, 0xb0, 0x01, 0x00, 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xf2, 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0xed, 0x8f, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00,
+ 0x2c, 0x01, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0xed, 0x8f, 0xa3, 0x40,
+ 0x82, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00,
+ 0xef, 0x8f, 0x20, 0x4c, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x85, 0xc0, 0x01, 0x00, 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00,
+ 0xa2, 0x00, 0x20, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40,
+ 0x87, 0x30, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x80, 0xc0, 0x01, 0x00, 0x20, 0x98, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x46,
+ 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x62, 0xf2, 0x96, 0xcc, 0x01, 0x00, 0xcf, 0x8d, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x20, 0x98, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00,
+ 0xf5, 0x97, 0x00, 0x46, 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00,
+ 0x86, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2,
+ 0x80, 0xcc, 0x01, 0x00, 0xcf, 0x8d, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x47,
+ 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x5f, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00,
+ 0x13, 0x90, 0x90, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xcf, 0x8d, 0x22, 0x40, 0xe5, 0x6d, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41,
+ 0xe5, 0xc1, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40,
+ 0x87, 0x30, 0x01, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x23, 0x90, 0x80, 0xf3, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x38, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00,
+ 0x34, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x84, 0xcc, 0x01, 0x00, 0x30, 0x90, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x42, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00,
+ 0x32, 0x90, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x62, 0xb1, 0x01, 0x00, 0x33, 0x90, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x35, 0x90, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00,
+ 0x35, 0x00, 0x2d, 0xf0, 0x28, 0xb0, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43,
+ 0xe7, 0xe1, 0x01, 0x00, 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00,
+ 0xe0, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2b, 0xb0, 0x01, 0x00, 0x04, 0x98, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x16, 0xc0, 0x01, 0x00, 0x47, 0x90, 0xa0, 0x14,
+ 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf8, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00,
+ 0x10, 0x50, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x50, 0x90, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00,
+ 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x50, 0x90, 0xa4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x01, 0x00, 0x6e, 0x43, 0x86, 0x98, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30,
+ 0x81, 0x30, 0x01, 0x00, 0x54, 0x90, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x5b, 0x90, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0x17, 0xc0, 0x01, 0x00, 0x5a, 0x90, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x41, 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x61, 0x90, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00,
+ 0xa0, 0x00, 0x20, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46,
+ 0x19, 0x10, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50,
+ 0x17, 0xf0, 0x01, 0x00, 0x66, 0x90, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x68, 0x90, 0x22, 0x43,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00,
+ 0x3e, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0x6f, 0x90, 0x24, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x81, 0xc0, 0x01, 0x00,
+ 0x70, 0x90, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00, 0x02, 0x00, 0x62, 0x40,
+ 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x76, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x80, 0x90, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x08,
+ 0x94, 0xdc, 0x01, 0x00, 0x72, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x7b, 0x90, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x84, 0x90, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x80, 0x90, 0x43, 0x48, 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08,
+ 0x62, 0xdd, 0x01, 0x00, 0x81, 0x90, 0xa8, 0x40, 0x05, 0x30, 0x00, 0x00,
+ 0x35, 0x00, 0x1b, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x84, 0xc8, 0x01, 0x00, 0x87, 0x90, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xe7, 0x91, 0x01, 0x00, 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00,
+ 0x27, 0x90, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x75, 0x8e, 0x22, 0x4a,
+ 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00, 0x9f, 0x8e, 0x22, 0x06,
+ 0x90, 0x6c, 0x00, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00,
+ 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50, 0xe7, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00, 0xa1, 0x90, 0xa0, 0x43,
+ 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xcc, 0x94, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xa3, 0x90, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x9f, 0x8e, 0x1a, 0x5d,
+ 0x69, 0x93, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x6b, 0xfb, 0x84, 0xc8, 0x01, 0x00, 0xae, 0x90, 0xa0, 0x43,
+ 0x85, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x12, 0xc8, 0x01, 0x00, 0xb1, 0x90, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0xce, 0x94, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb4, 0x90, 0x42, 0x05,
+ 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x11, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0xa3, 0x8f, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xad, 0x8f, 0x00, 0xf0,
+ 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xbf, 0x90, 0x47, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0xc4, 0x90, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x6b, 0x84, 0x1f, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xbe, 0x90, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x1f, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xc6, 0x90, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00,
+ 0x46, 0x97, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0xd0, 0x90, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0xcd, 0x90, 0x00, 0x50,
+ 0x43, 0xc1, 0x00, 0x00, 0xdc, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00,
+ 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0xda, 0x90, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0xe2, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00,
+ 0xe6, 0x90, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x1f, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x62, 0xb1, 0x01, 0x00, 0xea, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xef, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0xed, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96,
+ 0x97, 0xb0, 0x01, 0x00, 0xf5, 0x90, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00,
+ 0xf5, 0x90, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xf0, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xaf, 0x97, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xfb, 0x90, 0x22, 0xf3, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x42,
+ 0x81, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x42,
+ 0x19, 0x80, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0x20, 0x98, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xc9, 0x96, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x40,
+ 0x95, 0x6c, 0x00, 0x00, 0x06, 0x91, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x40,
+ 0x95, 0x30, 0x01, 0x00, 0x11, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0xff, 0x89, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x23, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x14, 0x91, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0xc0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00,
+ 0x18, 0x91, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x19, 0x98, 0x00, 0x43,
+ 0x61, 0x31, 0x01, 0x00, 0xda, 0x94, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00,
+ 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x20, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x1d, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa1, 0x97, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x24, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00,
+ 0x2b, 0x91, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00,
+ 0x2c, 0x91, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45,
+ 0x1f, 0x90, 0x01, 0x00, 0x87, 0x91, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x87, 0x91, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x3f, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x3b, 0x91, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x38, 0x91, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x96, 0x00, 0x15,
+ 0x94, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x42, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x43, 0x91, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6f, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15,
+ 0x98, 0xc8, 0x01, 0x00, 0x6f, 0x91, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00,
+ 0x4b, 0x91, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b,
+ 0x99, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00,
+ 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0, 0x22, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41, 0xe7, 0xe1, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x47,
+ 0xe7, 0xb5, 0x01, 0x00, 0x5c, 0x91, 0x23, 0x0b, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x02, 0xd0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x00,
+ 0x2a, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x61, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01,
+ 0x80, 0xce, 0x01, 0x00, 0x6d, 0x91, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x98, 0xd0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x74, 0x91, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x15, 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01,
+ 0xe4, 0xcd, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00,
+ 0xf8, 0x97, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00, 0x79, 0x91, 0x22, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x7a, 0x91, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00,
+ 0xda, 0x94, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x82, 0x91, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x7f, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x85, 0x91, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xba, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a,
+ 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00,
+ 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0,
+ 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15,
+ 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00, 0x5b, 0x97, 0x00, 0x40,
+ 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xcb, 0x91, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0xa1, 0x91, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xa1, 0x91, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9d, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xc4, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0xb2, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x21, 0x97, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x74, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xbf, 0x91, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xa8, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xae, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xe2, 0x95, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0xaf, 0x91, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb1, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x21, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x70, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xb5, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xbb, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xbc, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbe, 0x91, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xc0, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc7, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xc8, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xca, 0x91, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xbf, 0x8d, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xd2, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xce, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xd6, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xd7, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xdc, 0x91, 0x03, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0xdd, 0x91, 0x00, 0x41, 0x87, 0xb0, 0x00, 0x00,
+ 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xe1, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xe4, 0x91, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x80, 0x01, 0x00, 0xba, 0x8d, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xea, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfb, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbf, 0x8d, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xf6, 0x91, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfe, 0x91, 0xa2, 0x40,
+ 0xe5, 0x6d, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13,
+ 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00,
+ 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0c, 0x92, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, 0x98, 0x50, 0x00, 0x00,
+ 0x0c, 0x92, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x09, 0x92, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15, 0x10, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01,
+ 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00,
+ 0x8e, 0x91, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0x20, 0x98, 0x00, 0x09,
+ 0x80, 0x30, 0x01, 0x00, 0x8e, 0x91, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0xea, 0x96, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0x2c, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00,
+ 0xdc, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x48,
+ 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x21, 0x92, 0xa8, 0x40,
+ 0x13, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x27, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x26, 0x92, 0x00, 0x40,
+ 0x13, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x3f, 0x92, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x87, 0x42,
+ 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00,
+ 0xba, 0x8d, 0x00, 0x40, 0xe7, 0x91, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x3d, 0x92, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x51, 0x95, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0x3d, 0x92, 0x22, 0x00,
+ 0x80, 0x32, 0x00, 0x00, 0x38, 0x92, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x3d, 0x92, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0xf2,
+ 0x02, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x3e, 0x92, 0x00, 0x40,
+ 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x44, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x43, 0x92, 0xa2, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x44, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xce, 0x92, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x4c, 0x92, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x49, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xce, 0x92, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x52, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x4d,
+ 0x81, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x96, 0xb0, 0x01, 0x00, 0x60, 0x92, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x92, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x61, 0x92, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x65, 0x92, 0x47, 0xf2, 0x12, 0x30, 0x00, 0x00,
+ 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x6a, 0x92, 0x22, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0x6b, 0x84, 0x1f, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x64, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0xe7, 0x91, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x09, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x72, 0x92, 0xa8, 0x40,
+ 0xe1, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x76, 0x92, 0x47, 0x05,
+ 0x48, 0x31, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x7e, 0x92, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x7c, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b,
+ 0x16, 0xdc, 0x01, 0x00, 0x51, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x96, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xff, 0x96, 0x00, 0x5f,
+ 0x01, 0x10, 0x01, 0x00, 0x80, 0x92, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x88, 0x92, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x80, 0x92, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x80, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x00, 0x98, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0xe1, 0xb1, 0x01, 0x00,
+ 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xa0, 0x92, 0x30, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00,
+ 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x81, 0x01, 0x00, 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00,
+ 0xd1, 0x99, 0x00, 0x5f, 0x95, 0x04, 0x01, 0x00, 0x55, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xaa, 0x92, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00,
+ 0xa8, 0x92, 0x43, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x41,
+ 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0xb8, 0x95, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xbb, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00,
+ 0xb4, 0x92, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x62, 0xb1, 0x01, 0x00, 0xb8, 0x92, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb5, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x62, 0xb1, 0x01, 0x00, 0xb8, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x22, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0xf5, 0x97, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00, 0xdc, 0x96, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0x52, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xcc, 0x92, 0x22, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0x51, 0x95, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00,
+ 0xcc, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xc7, 0x92, 0xa2, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xcc, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00,
+ 0x74, 0x96, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xf5, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, 0xdc, 0x96, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0xd1, 0x92, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00,
+ 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0x91, 0x01, 0x00, 0x20, 0x98, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00,
+ 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdc, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x20, 0x98, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe5, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x47,
+ 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07, 0x84, 0x94, 0x01, 0x00,
+ 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xcc, 0x95, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a,
+ 0x2c, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00, 0x01, 0x93, 0x26, 0x47,
+ 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x01, 0x93, 0x23, 0x4b, 0x0c, 0x6c, 0x00, 0x00, 0x33, 0x98, 0x00, 0x4b,
+ 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x16, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0xb0, 0x01, 0x00,
+ 0x33, 0x98, 0x00, 0x4b, 0x04, 0x50, 0x01, 0x00, 0x02, 0x93, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x33, 0x98, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00,
+ 0x08, 0x93, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x06, 0x93, 0x84, 0x48,
+ 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x08, 0x93, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x02, 0xb0, 0x01, 0x00, 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x09, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00,
+ 0x16, 0x93, 0x22, 0x06, 0x14, 0x50, 0x00, 0x00, 0x24, 0x97, 0x00, 0x45,
+ 0x1f, 0x00, 0x01, 0x00, 0xf5, 0x92, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x12, 0x93, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf5, 0x92, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x1c, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x22, 0x93, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x26, 0x93, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x26, 0x93, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x34, 0x93, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x2c, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x30, 0x93, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x31, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00,
+ 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x16,
+ 0xe4, 0xb1, 0x00, 0x00, 0x46, 0x93, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xf4, 0x98, 0x00, 0x40,
+ 0x95, 0x30, 0x01, 0x00, 0x47, 0x93, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x08,
+ 0x80, 0x30, 0x01, 0x00, 0x3f, 0x93, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00,
+ 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x40, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x54, 0x93, 0x20, 0x16,
+ 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x51, 0x93, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x2c, 0xd0, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x5b, 0x93, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00, 0x5c, 0x93, 0x00, 0x0a,
+ 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00,
+ 0x5b, 0x97, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0x64, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x60, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x73, 0x93, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00,
+ 0x74, 0x93, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08,
+ 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x6b, 0x93, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x74, 0x93, 0x00, 0x5c,
+ 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00,
+ 0xe2, 0x95, 0x00, 0x40, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x78, 0x93, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x80, 0x93, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x80, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x7c, 0x93, 0xa8, 0x46, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x85, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x8b, 0x93, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x8f, 0x93, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x8f, 0x93, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0xa4, 0x93, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x95, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xa0, 0x93, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x99, 0x93, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00,
+ 0x9d, 0x93, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a,
+ 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00,
+ 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa1, 0x93, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15,
+ 0xe4, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00,
+ 0xa7, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf4, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xb4, 0x93, 0x22, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0xb1, 0x93, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xac, 0x93, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00,
+ 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0xb0, 0x93, 0x22, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x58, 0x01, 0x2d, 0x00,
+ 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0, 0x10, 0xb0, 0x01, 0x00,
+ 0x3f, 0x91, 0x00, 0xf0, 0x2c, 0xb0, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x41,
+ 0x95, 0x30, 0x01, 0x00, 0xbb, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0xb9, 0x93, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xf4, 0x93, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00,
+ 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00,
+ 0xcb, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0xc4, 0x93, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0,
+ 0x22, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x84, 0xb0, 0x01, 0x00, 0xce, 0x93, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xd3, 0x93, 0x22, 0x40,
+ 0x1b, 0x6c, 0x00, 0x00, 0xf8, 0x97, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00,
+ 0xdb, 0x93, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x80, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00,
+ 0xd9, 0x93, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0xea, 0x93, 0x00, 0x5e,
+ 0x17, 0x90, 0x00, 0x00, 0xde, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x84, 0xd0, 0x01, 0x00, 0xe3, 0x93, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00,
+ 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xea, 0x93, 0x22, 0x40,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0xc0, 0x01, 0x00,
+ 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00,
+ 0xe8, 0x93, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xeb, 0x93, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00,
+ 0xf2, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x11,
+ 0x00, 0x8c, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x8e, 0xb0, 0x01, 0x00, 0xb3, 0x96, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x05, 0x94, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x01, 0x94, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x94, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x1a, 0xd0, 0x01, 0x00, 0x0d, 0x94, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xf4, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0x15, 0x94, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x38, 0x93, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00,
+ 0xf4, 0x98, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0x10, 0x94, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0xbb, 0x93, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0x13, 0x94, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x19, 0x94, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00,
+ 0xf4, 0x95, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00, 0x27, 0x94, 0x26, 0x47,
+ 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x27, 0x94, 0x23, 0x4b, 0x0c, 0x6c, 0x00, 0x00, 0x33, 0x98, 0x00, 0x4b,
+ 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x16, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0xb0, 0x01, 0x00,
+ 0x33, 0x98, 0x00, 0x4b, 0x04, 0x50, 0x01, 0x00, 0x28, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x33, 0x98, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00,
+ 0x2d, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, 0xda, 0x94, 0x00, 0x01,
+ 0x8c, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00,
+ 0x34, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x30, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x3d, 0x94, 0x22, 0x06,
+ 0x14, 0x50, 0x00, 0x00, 0x24, 0x97, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00,
+ 0x1b, 0x94, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x39, 0x94, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x1b, 0x94, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x42, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x48, 0x94, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x4b, 0x94, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00,
+ 0x59, 0x94, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x51, 0x94, 0xa2, 0x16,
+ 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00,
+ 0x55, 0x94, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x56, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00,
+ 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00,
+ 0xba, 0x8d, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00, 0x35, 0x93, 0xa2, 0x16,
+ 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x95, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00,
+ 0x49, 0x93, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x63, 0x94, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x66, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x74, 0x96, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00,
+ 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x68, 0x94, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x20, 0x98, 0x00, 0x45,
+ 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xfe, 0x91, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x7a, 0x94, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00,
+ 0x73, 0x94, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x62, 0xb1, 0x01, 0x00, 0x77, 0x94, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x74, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x62, 0xb1, 0x01, 0x00, 0x77, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08,
+ 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00,
+ 0xb6, 0x96, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00,
+ 0xbf, 0x95, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, 0x8c, 0x94, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x88, 0x94, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0x74, 0x96, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08,
+ 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00,
+ 0xf4, 0x95, 0x00, 0x10, 0x32, 0x30, 0x01, 0x00, 0x49, 0x93, 0x00, 0x40,
+ 0x13, 0xb0, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x9c, 0x94, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x95, 0x94, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x99, 0x94, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x96, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00,
+ 0x99, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0x89, 0x17, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00,
+ 0xb3, 0x96, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00,
+ 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xab, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x3f, 0x91, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00,
+ 0x87, 0x91, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0xb3, 0x94, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00,
+ 0xef, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x4a,
+ 0x1f, 0x10, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0xf4, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x49, 0x93, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00,
+ 0xfe, 0x91, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x37, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x33, 0xc3, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x94, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x9f, 0x48, 0x03, 0xd0, 0x00, 0x00, 0xc1, 0x94, 0x9c, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x4c, 0x03, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x01, 0x34, 0xc3, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x11,
+ 0x10, 0xc1, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x40, 0x43, 0xc1, 0x00, 0x00,
+ 0xc6, 0x94, 0x00, 0x50, 0x43, 0xc1, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa1,
+ 0x42, 0xc9, 0x01, 0x00, 0xca, 0x94, 0x22, 0x40, 0xe5, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x40, 0xe5, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x41, 0x23, 0xd0, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x50,
+ 0x43, 0xd1, 0x00, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0, 0xb1, 0x01, 0x00,
+ 0xd0, 0x95, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00, 0x00, 0x80, 0x00, 0x43,
+ 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd7, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01, 0xe0, 0xc1, 0x01, 0x00,
+ 0xe1, 0x94, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xfb, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe3, 0x94, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x47,
+ 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0,
+ 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xf8, 0x94, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x4b, 0x95, 0xa2, 0x4c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xf8, 0x94, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xfb, 0x94, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46,
+ 0x8f, 0xb0, 0x01, 0x00, 0xf1, 0x94, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xf3, 0x94, 0x22, 0xf0,
+ 0x3a, 0x6c, 0x00, 0x00, 0x48, 0x95, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f,
+ 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x49, 0x95, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xf7, 0x94, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xfa, 0x94, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0xff, 0x94, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x08, 0x95, 0x23, 0xf0,
+ 0x02, 0x6c, 0x00, 0x00, 0x05, 0x95, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00,
+ 0x4a, 0x95, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x4a, 0x95, 0xa2, 0x41,
+ 0x03, 0x6c, 0x00, 0x00, 0x04, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x52,
+ 0x8f, 0xb0, 0x01, 0x00, 0x4a, 0x95, 0x1f, 0x12, 0x84, 0x50, 0x00, 0x00,
+ 0x4a, 0x95, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00, 0xf8, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x33, 0x95, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x25, 0x95, 0x22, 0xf0, 0x14, 0x30, 0x00, 0x00,
+ 0x11, 0x95, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x22, 0x95, 0x03, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0x10, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49,
+ 0x8f, 0xb0, 0x01, 0x00, 0x16, 0x95, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00,
+ 0x19, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x15, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, 0x18, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xd0, 0x01, 0x00,
+ 0x1f, 0x95, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00, 0x1e, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x21, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x24, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44,
+ 0x8f, 0xb0, 0x01, 0x00, 0x2e, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x2b, 0x95, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x2b, 0x95, 0xa2, 0xf2,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x2d, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x2b, 0x95, 0xa0, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0x29, 0x95, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00,
+ 0x32, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x28, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x3c, 0x95, 0xa2, 0xf0,
+ 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00,
+ 0x39, 0x95, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40,
+ 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00,
+ 0x2b, 0x95, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x29, 0x95, 0x20, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0x2b, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x40, 0x95, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x3f, 0x95, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x45, 0x95, 0x22, 0x0a,
+ 0x02, 0x6c, 0x00, 0x00, 0x19, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x44, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00,
+ 0x47, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00,
+ 0x4d, 0x95, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x41,
+ 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x42, 0x95, 0xb0, 0x00, 0x00,
+ 0x4d, 0x95, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x4c,
+ 0x95, 0xb0, 0x00, 0x00, 0xf5, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x50, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00,
+ 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3,
+ 0x84, 0xb0, 0x01, 0x00, 0x55, 0x95, 0xa2, 0xf3, 0x96, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x2a, 0x41,
+ 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41, 0x85, 0xe0, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00, 0x5b, 0x95, 0x22, 0x5a,
+ 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00,
+ 0x5c, 0x95, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0xa0, 0xa5, 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0xf0,
+ 0x8c, 0xb0, 0x00, 0x00, 0x69, 0x95, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x66, 0x95, 0xa2, 0x4b,
+ 0x19, 0x7c, 0x00, 0x00, 0x67, 0x95, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x32, 0x96, 0x00, 0x07,
+ 0x10, 0x30, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x6b, 0x95, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0xb8, 0x95, 0x00, 0x40,
+ 0x81, 0x30, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x32, 0x96, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00,
+ 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x32, 0x96, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0x74, 0x95, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x77, 0x95, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x85, 0x95, 0x13, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00,
+ 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x0f,
+ 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x5f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x4e, 0xb0, 0x01, 0x00, 0x12, 0x86, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00,
+ 0x82, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x86, 0x95, 0x44, 0x07, 0x96, 0x30, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xc2,
+ 0x24, 0xb0, 0x01, 0x00, 0x90, 0x95, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00,
+ 0x8a, 0x95, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x91, 0x95, 0x22, 0x12,
+ 0x48, 0x7f, 0x00, 0x00, 0x51, 0x98, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00,
+ 0x90, 0x95, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4,
+ 0x24, 0xb0, 0x01, 0x00, 0x91, 0x95, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00,
+ 0x51, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x9e, 0x95, 0x0b, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00, 0x9b, 0x95, 0x22, 0x50,
+ 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x51, 0x97, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, 0xd1, 0x99, 0x00, 0x12,
+ 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x90, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42, 0x10, 0xf4, 0x01, 0x00,
+ 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08,
+ 0x8a, 0x88, 0x01, 0x00, 0xa1, 0x95, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00,
+ 0xa4, 0x95, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x91, 0x95, 0x10, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00,
+ 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x51, 0x97, 0x00, 0xf2,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xaf, 0x95, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0xb3, 0x95, 0xa8, 0x05, 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0f,
+ 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42, 0x84, 0x88, 0x01, 0x00,
+ 0xbc, 0x95, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0xbd, 0x95, 0x00, 0x42,
+ 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6a, 0xb1, 0x01, 0x00,
+ 0xbd, 0x95, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42,
+ 0x48, 0x93, 0x01, 0x00, 0xbf, 0x95, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc4, 0x95, 0x28, 0xb1,
+ 0x2c, 0x30, 0x00, 0x00, 0xc0, 0x95, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x95, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xc4, 0x95, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xcb, 0x95, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00,
+ 0xc7, 0x95, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x24, 0x11, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcd, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xd1, 0x95, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xd7, 0x95, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x92, 0x48,
+ 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xdb, 0x95, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00, 0xd7, 0x95, 0x22, 0x4c,
+ 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40, 0x91, 0xb0, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xdb, 0x95, 0xa8, 0xb1,
+ 0x90, 0x30, 0x00, 0x00, 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b,
+ 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x92, 0x49, 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41,
+ 0x00, 0xec, 0x00, 0x00, 0xe8, 0x95, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x00, 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0xe4, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41,
+ 0x00, 0xec, 0x00, 0x00, 0xf1, 0x95, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00,
+ 0xcc, 0x95, 0x00, 0x00, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0xed, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xf6, 0x95, 0x83, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00,
+ 0x24, 0x00, 0x2d, 0x01, 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0,
+ 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x11, 0x10, 0xc1, 0x00, 0x00,
+ 0xff, 0x95, 0x00, 0x40, 0x43, 0xc1, 0x00, 0x00, 0xff, 0x95, 0x00, 0x50,
+ 0x43, 0xc1, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x96, 0x22, 0x40, 0xf5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x43, 0xd1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0xe5, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49,
+ 0x1f, 0x90, 0x01, 0x00, 0x07, 0x96, 0x22, 0x11, 0x1e, 0x7c, 0x00, 0x00,
+ 0x09, 0x96, 0xa0, 0xf0, 0x16, 0x40, 0x00, 0x00, 0x09, 0x96, 0x00, 0x41,
+ 0x17, 0xc0, 0x00, 0x00, 0x09, 0x96, 0xa0, 0xf4, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41,
+ 0x23, 0xd0, 0x00, 0x00, 0xff, 0x95, 0x00, 0x52, 0x43, 0xd1, 0x00, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x0c, 0x96, 0x30, 0x47,
+ 0x17, 0x04, 0x00, 0x00, 0x0f, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x90, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0x13, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x14, 0x96, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0xdb, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1e, 0x96, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00,
+ 0x01, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00,
+ 0x40, 0x97, 0x3e, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00,
+ 0x31, 0x96, 0x00, 0x3b, 0xe7, 0xb1, 0x00, 0x00, 0x1e, 0x96, 0x30, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x28, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x24, 0x96, 0xa2, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41,
+ 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x4a, 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43,
+ 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00,
+ 0x35, 0x96, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00, 0xdb, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x41, 0x96, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00,
+ 0x3d, 0x96, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f,
+ 0x96, 0xf4, 0x01, 0x00, 0x3a, 0x96, 0x31, 0x5f, 0x97, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x6a, 0xb1, 0x01, 0x00, 0x3d, 0x96, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x49, 0x96, 0xa2, 0x3b,
+ 0x89, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0x4a, 0x96, 0x18, 0x4a,
+ 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00, 0x4f, 0x96, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x51, 0x96, 0x00, 0x05,
+ 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x52, 0x96, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x55, 0x96, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00,
+ 0xdb, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x59, 0x96, 0x22, 0x45,
+ 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xd9, 0x99, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00,
+ 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3,
+ 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0x61, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5a, 0x96, 0xa2, 0x3b,
+ 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd1, 0x99, 0x00, 0x12,
+ 0x94, 0x30, 0x01, 0x00, 0x32, 0x96, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a,
+ 0xe6, 0xc9, 0x01, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b,
+ 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44,
+ 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf2, 0x02, 0x30, 0x00, 0x00, 0x51, 0x95, 0x00, 0x10,
+ 0x32, 0x30, 0x01, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00,
+ 0x78, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x36, 0xb0, 0x01, 0x00, 0x88, 0x96, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x81, 0x96, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, 0x7c, 0x96, 0x00, 0x5c,
+ 0x01, 0x80, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x46, 0xc9, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xaf, 0x96, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x68, 0x08, 0x38, 0x96, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41,
+ 0x82, 0xcc, 0x01, 0x00, 0x8d, 0x96, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x11, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00,
+ 0xae, 0x96, 0x26, 0x46, 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x12, 0xc8, 0x01, 0x00, 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00,
+ 0xad, 0x96, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x9f, 0x96, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0xac, 0x96, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0xaa, 0x96, 0xa2, 0x41,
+ 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xa5, 0x96, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x13, 0xc0, 0x01, 0x00, 0x9a, 0x96, 0x00, 0x50,
+ 0x49, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x1a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xae, 0x96, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x5c,
+ 0x01, 0x00, 0x01, 0x00, 0xaf, 0x96, 0x00, 0x41, 0x3b, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5f,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x8c, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00,
+ 0xbb, 0x96, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, 0x14, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8, 0x0c, 0xb0, 0x01, 0x00,
+ 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00,
+ 0xc8, 0x96, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x96, 0xb0, 0x01, 0x00,
+ 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x20, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0xb3, 0x96, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42,
+ 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0xce, 0x96, 0xa2, 0xa5,
+ 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00,
+ 0xd1, 0x96, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00,
+ 0xd6, 0x96, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00,
+ 0xdb, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x0b, 0x00, 0x80, 0x00,
+ 0xe4, 0xf5, 0x01, 0x00, 0xd0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0xe7, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd0, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0xf6, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00, 0xfe, 0x96, 0x9f, 0x41,
+ 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5, 0x85, 0xcc, 0x01, 0x00,
+ 0x2d, 0x00, 0xa0, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0x5e, 0x01, 0x2d, 0x00,
+ 0x80, 0xb0, 0x01, 0x00, 0x03, 0x97, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0x04, 0x97, 0x00, 0x41,
+ 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00,
+ 0x05, 0x97, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x0a, 0x97, 0xa2, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0x1f, 0x97, 0x9c, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x14, 0x97, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e,
+ 0x98, 0xf4, 0x01, 0x00, 0x13, 0x97, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0x13, 0x97, 0xa2, 0x8a,
+ 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4,
+ 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x1e, 0x97, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00,
+ 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3,
+ 0x3a, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04,
+ 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0,
+ 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0x2b, 0x97, 0x22, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x35, 0x97, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x01, 0x96, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x3b, 0x97, 0x45, 0x42,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x3c, 0x97, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x01, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x42, 0x97, 0x45, 0x42, 0x61, 0x31, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x43, 0x97, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00, 0x02, 0x00, 0x00, 0x09,
+ 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x4d, 0x97, 0x46, 0x42,
+ 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a, 0x62, 0xc9, 0x01, 0x00,
+ 0x4e, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x97, 0xf0, 0x01, 0x00,
+ 0x52, 0x97, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5a, 0x97, 0x22, 0xf3,
+ 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x94, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x57, 0x97, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00, 0x6a, 0x97, 0x82, 0x41,
+ 0x23, 0x40, 0x00, 0x00, 0x5f, 0x97, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x20, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x65, 0x97, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x62, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x6a, 0x97, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x43,
+ 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00,
+ 0x6c, 0x97, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00, 0x6d, 0x97, 0x00, 0x06,
+ 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x04, 0xb0, 0x01, 0x00,
+ 0x6f, 0x97, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x04, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00,
+ 0x74, 0x97, 0x26, 0x47, 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xc0, 0x01, 0x00, 0x74, 0x97, 0x23, 0x4b, 0x04, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x04, 0xb0, 0x01, 0x00, 0x33, 0x98, 0x00, 0x05,
+ 0x48, 0x31, 0x01, 0x00, 0x9e, 0x97, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0x78, 0x97, 0xa2, 0x02, 0x2a, 0x50, 0x00, 0x00, 0x9e, 0x97, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x7a, 0x97, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00,
+ 0x83, 0x97, 0x00, 0x02, 0x16, 0xc0, 0x00, 0x00, 0x82, 0x97, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x82, 0x97, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x7e, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x24, 0x97, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x9e, 0x97, 0x22, 0x15,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x9d, 0x97, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, 0x8f, 0x97, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x8f, 0x97, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x97, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00,
+ 0x2f, 0x00, 0x2f, 0x5c, 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0xe7, 0x91, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00,
+ 0x5c, 0x97, 0x20, 0x15, 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08,
+ 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x9a, 0x97, 0xa8, 0x46,
+ 0x1f, 0x10, 0x00, 0x00, 0x5c, 0x97, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x5c, 0x97, 0x00, 0x02, 0x10, 0xc0, 0x00, 0x00, 0xa0, 0x97, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x08, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0xa7, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x27, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0xb0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x41,
+ 0xa3, 0x41, 0x01, 0x00, 0xab, 0x97, 0x00, 0x41, 0x27, 0xd0, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb2, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x98, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06,
+ 0x16, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00,
+ 0xba, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x6c, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00,
+ 0xc3, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43,
+ 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00,
+ 0xc3, 0x97, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0xe4, 0x97, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00,
+ 0xd0, 0x97, 0xa2, 0x06, 0x14, 0x6c, 0x00, 0x00, 0xcd, 0x97, 0x22, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0xc8, 0x97, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x31, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0x48, 0x19, 0x80, 0x01, 0x00, 0x8b, 0x00, 0x20, 0x45,
+ 0xe7, 0x91, 0x01, 0x00, 0xd0, 0x97, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, 0xd0, 0x97, 0xa0, 0x48,
+ 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43,
+ 0xfc, 0xc9, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0xdb, 0x97, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0x17, 0xc0, 0x01, 0x00, 0xda, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xdf, 0x97, 0x64, 0xf0,
+ 0x82, 0xb0, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xdf, 0x97, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe5, 0xb1, 0x01, 0x00, 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00,
+ 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06,
+ 0x30, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00,
+ 0xbc, 0x00, 0x2d, 0x46, 0x19, 0x90, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2,
+ 0xe4, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30,
+ 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x4a, 0x19, 0xfc, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00,
+ 0xed, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xe4, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x1b, 0xe0, 0xb1, 0x00, 0x00,
+ 0xf2, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c,
+ 0x7e, 0x89, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x4c, 0x95, 0x60, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x4a, 0x18, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15,
+ 0xe0, 0xb1, 0x00, 0x00, 0xfd, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xe8, 0x5f, 0x17, 0x90, 0x01, 0x00, 0x70, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x7a, 0x01, 0x2e, 0xfe, 0x92, 0xb0, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0xf6, 0x16, 0xb0, 0x01, 0x00, 0x0a, 0x98, 0x22, 0x43,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xa6, 0x2a, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x6e, 0x06,
+ 0x82, 0xc8, 0x01, 0x00, 0x0e, 0x98, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x4c,
+ 0x83, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00,
+ 0x0f, 0x98, 0x42, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x66, 0x9e,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x41, 0x3d, 0xc3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x49, 0x98, 0xf4, 0x01, 0x00,
+ 0x18, 0x98, 0x26, 0x30, 0x93, 0x04, 0x00, 0x00, 0x18, 0x98, 0x90, 0x4c,
+ 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00,
+ 0xff, 0xff, 0x80, 0x49, 0xec, 0xa9, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, 0x1d, 0x98, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x2a, 0x98, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00,
+ 0x29, 0x98, 0xa2, 0x40, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x97, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0x29, 0x98, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x26, 0x98, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00,
+ 0x2d, 0x98, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43,
+ 0x19, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02,
+ 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x13, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x08, 0xe0, 0xb1, 0x00, 0x00, 0x38, 0x98, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xf0, 0x98, 0xf4, 0x01, 0x00, 0x41, 0x98, 0x20, 0x4c,
+ 0x84, 0x6c, 0x00, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x41, 0x98, 0x20, 0xf2, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14,
+ 0x98, 0xd0, 0x01, 0x00, 0x46, 0x98, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x80, 0xe0, 0x01, 0x00, 0x49, 0x98, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14,
+ 0xe0, 0xb1, 0x01, 0x00, 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x6e, 0xf3, 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42,
+ 0x82, 0xc0, 0x00, 0x00, 0x4f, 0x98, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0,
+ 0x82, 0xec, 0x00, 0x00, 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00,
+ 0x52, 0x98, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x4b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x50, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x56, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x5b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x60, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x65, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x6b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x70, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x75, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x7a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x72, 0x98, 0x43, 0x57, 0x61, 0x31, 0x00, 0x00, 0x7e, 0x98, 0xa2, 0x57,
+ 0x73, 0x7d, 0x00, 0x00, 0x7e, 0x98, 0xa2, 0x40, 0x81, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x4a,
+ 0x62, 0xdd, 0x01, 0x00, 0x76, 0x98, 0xa8, 0x4a, 0x80, 0x33, 0x00, 0x00,
+ 0x7b, 0x98, 0x22, 0x5f, 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x79, 0x98, 0xa8, 0x4b, 0xac, 0x33, 0x00, 0x00,
+ 0x00, 0x00, 0x1b, 0xa5, 0x82, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbe,
+ 0x83, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0x82, 0x98, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x7e, 0x98, 0x22, 0x57, 0x77, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x9b, 0x20, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x82, 0x98, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x9b, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xa8, 0x00, 0x2d, 0x1c, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0,
+ 0x8a, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00,
+ 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00,
+ 0x97, 0x98, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xbe, 0x00, 0x2f, 0xab,
+ 0x83, 0xb0, 0x01, 0x00, 0xff, 0x98, 0x00, 0x14, 0x82, 0x50, 0x01, 0x00,
+ 0x9c, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9c, 0x98, 0x22, 0xf2,
+ 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x9c, 0x98, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xff, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0x30,
+ 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00, 0xc6, 0x98, 0x23, 0xf0,
+ 0x84, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x42, 0x88, 0xf4, 0x01, 0x00,
+ 0xc6, 0x98, 0x20, 0x50, 0x89, 0x6c, 0x00, 0x00, 0xb5, 0x98, 0xa3, 0x92,
+ 0x87, 0x6c, 0x00, 0x00, 0xa5, 0x98, 0x00, 0x44, 0x10, 0xc9, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0a, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x09,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x08, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x07, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x07,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x07, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, 0xb6, 0x98, 0x00, 0x44,
+ 0x10, 0xc9, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0f, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0e, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0d,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00,
+ 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b,
+ 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00,
+ 0xbf, 0x00, 0x2d, 0x43, 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3,
+ 0x80, 0xe0, 0x01, 0x00, 0xcb, 0x98, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00,
+ 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x84, 0xb0, 0x01, 0x00, 0xcf, 0x98, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00,
+ 0x9c, 0x00, 0x20, 0x42, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00,
+ 0x9c, 0x00, 0x20, 0x42, 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xf3, 0x82, 0x88, 0x01, 0x00, 0xd5, 0x98, 0x23, 0x41,
+ 0x80, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x89, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x9f, 0x41, 0x24, 0xec, 0x00, 0x00, 0xdf, 0x98, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x42, 0x38, 0xec, 0x00, 0x00,
+ 0xdf, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xe1, 0x98, 0xa3, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xe5, 0x98, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0xb4, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f,
+ 0x13, 0x94, 0x01, 0x00, 0xe5, 0x98, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0xee, 0x98, 0x9f, 0x41, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00,
+ 0xef, 0x98, 0x00, 0x41, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf1, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x08, 0x80, 0x32, 0x01, 0x00,
+ 0xf8, 0x98, 0xa2, 0x40, 0x95, 0x6c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00,
+ 0xa0, 0x98, 0x2f, 0x40, 0x11, 0xb0, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41,
+ 0x89, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf8, 0x3e, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x9f, 0x12, 0xe0, 0xed, 0x00, 0x00, 0xc8, 0x00, 0x20, 0xab,
+ 0xe1, 0xb1, 0x01, 0x00, 0xcc, 0x00, 0xa0, 0x1f, 0xe0, 0xb1, 0x01, 0x00,
+ 0x01, 0x99, 0xa3, 0x5f, 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe7, 0xc1, 0x01, 0x00, 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x15, 0x99, 0x22, 0xf2, 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43,
+ 0x84, 0xf4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00,
+ 0xb8, 0x00, 0x2d, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40,
+ 0x86, 0xc0, 0x01, 0x00, 0x09, 0x99, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00,
+ 0x0a, 0x99, 0xa2, 0x40, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41,
+ 0x87, 0xb0, 0x01, 0x00, 0x0e, 0x99, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x84, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44,
+ 0x84, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x62, 0x40, 0x88, 0xc0, 0x01, 0x00, 0x14, 0x99, 0x1f, 0x44,
+ 0x80, 0x32, 0x00, 0x00, 0x18, 0x99, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00,
+ 0x18, 0x99, 0x62, 0x41, 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41,
+ 0x86, 0xe4, 0x01, 0x00, 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x62, 0x41, 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xbc, 0x00, 0x2e, 0x43, 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x86, 0xc0, 0x01, 0x00, 0x1e, 0x99, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x43, 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43,
+ 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00,
+ 0x40, 0x01, 0xe2, 0x40, 0x87, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44,
+ 0x81, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf2, 0x2e, 0xb0, 0x01, 0x00,
+ 0x9c, 0x00, 0x2d, 0xf0, 0x86, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0xba, 0x00, 0x2d, 0xf0, 0x98, 0xb0, 0x01, 0x00,
+ 0x2b, 0x99, 0xa2, 0x12, 0x98, 0x6c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0xf2,
+ 0x98, 0xb0, 0x01, 0x00, 0x2b, 0x99, 0xa0, 0xf2, 0x98, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0x82, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x2d, 0x12, 0x86, 0xd0, 0x01, 0x00,
+ 0x2e, 0x99, 0xa3, 0x41, 0xe0, 0x6d, 0x00, 0x00, 0x2f, 0x99, 0x00, 0xf0,
+ 0x84, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0xb0, 0x01, 0x00,
+ 0x80, 0x00, 0x2d, 0x43, 0x84, 0xd0, 0x01, 0x00, 0x32, 0x99, 0x9f, 0x42,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x34, 0x99, 0xa3, 0x42, 0x14, 0x6c, 0x00, 0x00, 0x35, 0x99, 0x00, 0x0a,
+ 0x0c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x0c, 0xb0, 0x01, 0x00,
+ 0x37, 0x99, 0xa0, 0x17, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x17,
+ 0x0c, 0xb0, 0x01, 0x00, 0x3c, 0x99, 0x22, 0x40, 0x0d, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa0, 0x0a, 0x0c, 0xec, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0,
+ 0x82, 0xf4, 0x01, 0x00, 0x3c, 0x99, 0xa0, 0x41, 0x0c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0xd0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x41, 0x87, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0x48, 0x99, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x05, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x04, 0xe6, 0xb1, 0x01, 0x00, 0x52, 0x99, 0x22, 0x49,
+ 0x1f, 0x7c, 0x00, 0x00, 0x42, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x1f, 0x80, 0x01, 0x00, 0xaa, 0x97, 0x00, 0x40,
+ 0x8d, 0xb0, 0x00, 0x00, 0x58, 0x99, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x96, 0xb0, 0x01, 0x00, 0x72, 0x98, 0x00, 0x08,
+ 0x94, 0x30, 0x01, 0x00, 0x57, 0x99, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0xaa, 0x97, 0x00, 0x46, 0x87, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0x58, 0x99, 0x43, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x99, 0x28, 0x40,
+ 0x87, 0x30, 0x00, 0x00, 0x59, 0x99, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0xaa, 0x97, 0x1b, 0x46, 0x87, 0xb0, 0x00, 0x00, 0x60, 0x99, 0x22, 0x5f,
+ 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00,
+ 0x5e, 0x99, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0xb0, 0x01, 0x00,
+ 0xb1, 0x99, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00, 0x07, 0x00, 0x00, 0x49,
+ 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03, 0x06, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xd0,
+ 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00,
+ 0x65, 0x99, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x05,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x48, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xc0, 0x01, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0x6e, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00, 0xb6, 0x99, 0x00, 0x40,
+ 0x49, 0x31, 0x01, 0x00, 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x74, 0x99, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x00, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x78, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x7c, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00,
+ 0xba, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x86, 0x99, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x68, 0xb1, 0x01, 0x00, 0x8a, 0x99, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00,
+ 0xc3, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x39, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x33, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x3f, 0xb3, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40,
+ 0x29, 0x9b, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40, 0x25, 0x9b, 0x01, 0x00,
+ 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x2b, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5, 0x3c, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c,
+ 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x59, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xb3, 0x01, 0x00,
+ 0xa7, 0x99, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xa7, 0x99, 0xa2, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0xa8, 0x99, 0x00, 0x40, 0x1d, 0xb3, 0x00, 0x00,
+ 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6,
+ 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6, 0x3a, 0xb3, 0x01, 0x00,
+ 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00, 0xb4, 0x05, 0x00, 0x40,
+ 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x4d, 0xb3, 0x01, 0x00,
+ 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x8a,
+ 0x15, 0x9b, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5e, 0x57, 0xb5, 0x01, 0x00, 0x18, 0x00, 0x00, 0x4b,
+ 0x20, 0xe4, 0x01, 0x00, 0x06, 0x00, 0x00, 0x4b, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x43, 0x00, 0x4b, 0x96, 0xc8, 0x01, 0x00, 0x18, 0x00, 0x00, 0x10,
+ 0x20, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b, 0x20, 0x94, 0x01, 0x00,
+ 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xb7, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0xa9, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0xbb, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0xbf, 0x99, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xbf, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6,
+ 0x82, 0xb1, 0x01, 0x00, 0xc5, 0x99, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x90, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0xca, 0x99, 0x85, 0x41,
+ 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xce, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x80, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x9c, 0x4b, 0x82, 0x89, 0x01, 0x00,
+ 0xd1, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x80, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x9c, 0xa6, 0x82, 0xb1, 0x01, 0x00,
+ 0xd4, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b,
+ 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x9c, 0xc2, 0x24, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b,
+ 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x80, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b,
+ 0x94, 0x89, 0x01, 0x00, 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0xdf, 0x99, 0x80, 0xa5, 0x80, 0x32, 0x00, 0x00,
+ 0xe0, 0x99, 0x00, 0xa5, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x81, 0xc0, 0x01, 0x00, 0xe1, 0x99, 0x80, 0xa5, 0x80, 0x32, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xea, 0x99, 0x20, 0x4f,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xea, 0x99, 0x20, 0x4b, 0x81, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xea, 0x99, 0x20, 0x47, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x82, 0xdc, 0x01, 0x00, 0x03, 0x90, 0x00, 0x41, 0x20, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x4c,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0xee, 0x99, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x64, 0x00, 0x00, 0xa5,
+ 0x80, 0xc8, 0x01, 0x00, 0xf1, 0x99, 0xa2, 0xa5, 0x80, 0x6c, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0xf4, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0xf7, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0xfa, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xfc, 0x99, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x40, 0x68, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00,
+ 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x21, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x22, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x23, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x25, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x26, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x27, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x40, 0x85, 0x30, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x02, 0x01, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00,
+ 0x04, 0x03, 0x00, 0x40, 0x80, 0x98, 0x01, 0x00, 0x06, 0x05, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x08, 0x07, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00,
+ 0x30, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xff, 0x02, 0xa2, 0xf8, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x22, 0xf0,
+ 0x82, 0x6c, 0x00, 0x00, 0xff, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x1e, 0x9a, 0x00, 0x40,
+ 0x10, 0xc9, 0x00, 0x00, 0x24, 0x9a, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x9a, 0x00, 0x05,
+ 0x81, 0xb0, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x31, 0x9a, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0x33, 0x9a, 0x00, 0x44,
+ 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1,
+ 0xf0, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x25, 0x9a, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x22, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0x2d, 0x9a, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x00, 0xc2,
+ 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00,
+ 0x29, 0x9a, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb,
+ 0x81, 0xc8, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00,
+ 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00,
+ 0xb6, 0x9f, 0x41, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb9, 0x9f, 0x22, 0x40,
+ 0x7b, 0x6f, 0x00, 0x00, 0xb6, 0x9f, 0x19, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4,
+ 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00, 0x08, 0x14, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0xb0, 0x9f, 0x00, 0x4d, 0x9a, 0xcc, 0x01, 0x00,
+ 0xc2, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xc1, 0x01, 0x00, 0xc0, 0x9f, 0xa2, 0x41, 0x9b, 0x50, 0x00, 0x00,
+ 0xc6, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x52, 0x49,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xfd, 0x93, 0x01, 0x00,
+ 0xc9, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x51, 0x4a,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0xfd, 0x93, 0x01, 0x00,
+ 0xc9, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xd9, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00, 0xd1, 0x9f, 0x00, 0x40,
+ 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x10, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe3,
+ 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x45, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x48, 0x4f,
+ 0x40, 0xb1, 0x01, 0x00, 0xd9, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x19, 0x9a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x35, 0x9a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x10, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00,
+ },
+};
diff --git a/drivers/staging/slicoss/gbrcvucode.h b/drivers/staging/slicoss/gbrcvucode.h
new file mode 100644
index 00000000000..4fa5a4c23e5
--- /dev/null
+++ b/drivers/staging/slicoss/gbrcvucode.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1997-2002 Alacritech, Inc. All rights reserved
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+#define GB_RCVUCODE_VERS_STRING "1.2"
+#define GB_RCVUCODE_VERS_DATE "2006/03/27 15:12:15"
+
+static u32 GBRcvUCodeLen = 512;
+
+static u8 GBRcvUCode[2560] =
+{
+0x47, 0x75, 0x01, 0x00, 0x04, 0xa0, 0x13, 0x01, 0x00, 0x1c, 0xb7, 0x5b, 0x09,
+0x30, 0x00, 0xb6, 0x5f, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x18, 0x3b,
+0x78, 0x3a, 0x00, 0x1c, 0xa2, 0x77, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x70,
+0x18, 0xb3, 0x7b, 0xa9, 0xaa, 0x1e, 0xb4, 0x7b, 0x01, 0x0c, 0x1c, 0xb5, 0x7b,
+0x1d, 0x06, 0x1c, 0x00, 0x00, 0x40, 0x64, 0x08, 0x0c, 0x31, 0x56, 0x70, 0x04,
+0x0c, 0x31, 0x56, 0x80, 0x04, 0x0c, 0x31, 0x4a, 0x90, 0x04, 0x0c, 0x31, 0x46,
+0xa0, 0x00, 0x09, 0x25, 0x51, 0xc0, 0x04, 0x0c, 0x31, 0x4e, 0xb0, 0x00, 0xe9,
+0x24, 0x51, 0xc0, 0x04, 0xcc, 0xb3, 0x00, 0x1c, 0x1c, 0xeb, 0x2d, 0x01, 0x00,
+0x1c, 0x06, 0x56, 0x42, 0xd4, 0x08, 0x07, 0x9d, 0x00, 0x00, 0x1c, 0x7b, 0xb7,
+0x02, 0x00, 0x10, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x06, 0x56, 0x5a, 0xc0, 0x04,
+0xa0, 0x30, 0x6c, 0x03, 0x00, 0xac, 0x30, 0x6d, 0x03, 0x00, 0xcd, 0x03, 0x3a,
+0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0x60, 0x8e, 0x41, 0x54, 0x09, 0x29,
+0x25, 0x6d, 0x03, 0x00, 0x80, 0x8e, 0x41, 0x54, 0x09, 0x8c, 0x30, 0x8d, 0x00,
+0x04, 0x47, 0x1c, 0x01, 0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x00, 0x00,
+0x60, 0x00, 0x04, 0x47, 0x1c, 0x61, 0xc0, 0x04, 0x47, 0x1c, 0x6d, 0x03, 0x00,
+0x6c, 0x30, 0x01, 0x00, 0x1c, 0x4d, 0x34, 0x02, 0x00, 0x1c, 0x7b, 0xb7, 0x02,
+0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xc8, 0x83, 0x37, 0x00, 0x1c, 0x80,
+0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x60, 0x00, 0x04, 0xa0, 0x0f, 0x40, 0x54,
+0x09, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x7b, 0xfb, 0xf2, 0x00, 0x1c, 0xcc, 0x33,
+0x0d, 0x00, 0x1c, 0xb4, 0x7b, 0xfd, 0x03, 0x1c, 0x80, 0x0e, 0x40, 0x54, 0x09,
+0xe0, 0xfb, 0x05, 0x00, 0x1c, 0x00, 0x00, 0xa0, 0x03, 0x00, 0xb3, 0x0f, 0x41,
+0x54, 0x09, 0x00, 0x00, 0xe8, 0x70, 0x04, 0x00, 0x00, 0xe8, 0x80, 0x04, 0x00,
+0x00, 0xa0, 0x93, 0x00, 0x61, 0x76, 0xa1, 0xc3, 0x04, 0xc0, 0x8d, 0x41, 0x54,
+0x09, 0xe0, 0x7b, 0x00, 0xc0, 0x1f, 0xa0, 0xfd, 0xc1, 0x01, 0x00, 0xcc, 0x33,
+0x05, 0x00, 0x1c, 0xd4, 0x03, 0x00, 0x3c, 0x1c, 0xd4, 0xd3, 0x1b, 0x00, 0x1c,
+0xc0, 0xd3, 0x52, 0x00, 0x1c, 0x00, 0x00, 0x74, 0x13, 0x04, 0x8e, 0x8e, 0x42,
+0x54, 0x09, 0x5b, 0x80, 0x76, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00,
+0x00, 0x90, 0x01, 0x00, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54,
+0x09, 0xc0, 0x03, 0xfc, 0x7f, 0x1c, 0xa0, 0x01, 0x9c, 0x01, 0x00, 0x00, 0x00,
+0xa0, 0x01, 0x00, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xc0, 0x03, 0xfc, 0x03, 0x1c,
+0xf5, 0x77, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0xf6, 0x05, 0x1c, 0xa0, 0x0f, 0x41,
+0x54, 0x09, 0xb3, 0x0f, 0x41, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0xa0,
+0x0f, 0x41, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00, 0x1c, 0xb5, 0x02, 0x02, 0x00,
+0x1c, 0x53, 0x0f, 0x42, 0x54, 0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e,
+0x42, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x00, 0x1c,
+0xa0, 0x3d, 0xa6, 0x11, 0x04, 0x00, 0x00, 0xa8, 0x11, 0x04, 0xd4, 0xd3, 0x52,
+0x00, 0x1c, 0xb5, 0x3e, 0xae, 0x01, 0x00, 0x20, 0xfb, 0xfd, 0xff, 0x1f, 0x80,
+0x2c, 0x84, 0x03, 0x00, 0xb9, 0x3a, 0x9a, 0x01, 0x00, 0x75, 0x3b, 0x02, 0x00,
+0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xdb, 0x83, 0x16, 0x00, 0x1c, 0xc7, 0x1d,
+0x1d, 0xc1, 0x04, 0xb9, 0x3b, 0x89, 0xc1, 0x04, 0x8b, 0x2c, 0x01, 0x00, 0x1c,
+0x6b, 0x2c, 0x31, 0xc1, 0x04, 0x00, 0x00, 0x74, 0x11, 0x00, 0xcb, 0x2c, 0x75,
+0xc1, 0x04, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x54,
+0xd0, 0x02, 0x00, 0x1c, 0x49, 0x25, 0xad, 0x01, 0x00, 0xab, 0x2c, 0x7d, 0xc1,
+0x04, 0xa7, 0x1d, 0x6d, 0x03, 0x00, 0xcc, 0x33, 0x09, 0x00, 0x1c, 0xeb, 0x2d,
+0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09,
+0xae, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xd4, 0x07, 0xfc,
+0x03, 0x1c, 0x99, 0x3a, 0x02, 0x00, 0x1c, 0xbb, 0x38, 0x02, 0x00, 0x1c, 0x00,
+0x38, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xf8, 0x01, 0x04, 0xdb, 0x3b, 0x7e, 0x00,
+0x1c, 0xc7, 0x1d, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0x0a, 0x06, 0x1c, 0x27, 0x1d,
+0x01, 0x00, 0x1c, 0xb3, 0x0f, 0x41, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09,
+0x53, 0x0f, 0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42,
+0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09, 0xa0,
+0x0f, 0x41, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00, 0x1c, 0x53, 0x0f, 0x42, 0x54,
+0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f,
+0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09,
+0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42,
+0x54, 0x09, 0x00, 0x3d, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x54, 0x12, 0x00, 0xcb,
+0x2c, 0x01, 0x00, 0x1c, 0x75, 0x3b, 0x02, 0x00, 0x1c, 0xa7, 0x1c, 0x01, 0x00,
+0x10, 0xa6, 0x7b, 0xf1, 0x05, 0x1c, 0x00, 0x00, 0x88, 0xc2, 0x04, 0xa6, 0x7b,
+0xf1, 0x05, 0x1c, 0x00, 0x00, 0xa0, 0xc2, 0x04, 0xcb, 0x2f, 0x05, 0x00, 0x1c,
+0x60, 0x2c, 0x00, 0x00, 0x1c, 0xc7, 0x1c, 0xe1, 0x02, 0x00, 0x53, 0x0f, 0x42,
+0x54, 0x09, 0xc0, 0x83, 0xf1, 0x32, 0x1c, 0x00, 0x00, 0x5c, 0x02, 0x04, 0x46,
+0x7a, 0xda, 0x05, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0xc0, 0x83, 0xf1, 0x32,
+0x1c, 0x00, 0x00, 0x64, 0x02, 0x04, 0x40, 0xfa, 0x15, 0x00, 0x1c, 0x00, 0x00,
+0xa0, 0x02, 0x04, 0x46, 0x7a, 0xda, 0x05, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09,
+0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41,
+0x54, 0x09, 0xb3, 0x7b, 0x01, 0xc0, 0x1f, 0x74, 0x0e, 0x40, 0x54, 0x09, 0xc0,
+0x03, 0x9c, 0x00, 0x1c, 0x80, 0x00, 0xf0, 0x02, 0x00, 0x00, 0x00, 0xf0, 0x02,
+0x04, 0x00, 0x00, 0xc4, 0x12, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xd4, 0xd3,
+0x2b, 0x00, 0x1c, 0xd4, 0xd3, 0x52, 0x00, 0x1c, 0x80, 0x76, 0x95, 0x13, 0x04,
+0x00, 0x00, 0xf8, 0x02, 0x00, 0xa6, 0x7b, 0xa9, 0x03, 0x10, 0xc7, 0x9c, 0x00,
+0x00, 0x1c, 0x80, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x02, 0x04, 0x00,
+0x00, 0x6c, 0xc3, 0x04, 0xab, 0x2d, 0xf1, 0x12, 0x05, 0x07, 0x1d, 0xcd, 0xc2,
+0x04, 0x8b, 0x2d, 0x01, 0x00, 0x1c, 0x69, 0x25, 0x01, 0x00, 0x1c, 0xa6, 0x7b,
+0xa9, 0x03, 0x10, 0xcb, 0x2f, 0x09, 0x00, 0x1c, 0x60, 0x2c, 0x00, 0x00, 0x1c,
+0x00, 0x00, 0x60, 0x03, 0x00, 0x53, 0x0f, 0x42, 0x54, 0x09, 0x46, 0x7a, 0xda,
+0x05, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x40, 0xfa, 0x15, 0x00, 0x1c, 0x00,
+0x00, 0x28, 0x03, 0x04, 0x46, 0x7a, 0xda, 0x05, 0x1c, 0xb5, 0x0f, 0x41, 0x54,
+0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x73, 0xec, 0x42, 0x03, 0x04, 0x60, 0x2c,
+0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x03, 0x00, 0xc7, 0x1c, 0x01, 0x00, 0x1c,
+0x00, 0x00, 0x40, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xc0, 0xd7, 0x22,
+0x00, 0x1c, 0x75, 0x56, 0x96, 0x13, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0xe7,
+0x1c, 0x5d, 0x03, 0x04, 0xe7, 0x9c, 0x00, 0x00, 0x1c, 0xa6, 0x7b, 0xa9, 0x03,
+0x10, 0x80, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x10, 0x03, 0x04, 0x00, 0x00,
+0x6c, 0xc3, 0x04, 0xb9, 0x7b, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xa0, 0xc3, 0x04,
+0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x01, 0x04, 0x1c, 0xc7, 0x9f, 0x80,
+0x03, 0x1c, 0x00, 0x00, 0xa0, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb,
+0x2f, 0x0d, 0x04, 0x1c, 0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00, 0xa0, 0xc3,
+0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x00, 0x1d, 0x00, 0x00,
+0xa0, 0xc3, 0x04, 0x00, 0x00, 0xa0, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c,
+0xc0, 0x1d, 0xf0, 0xd3, 0x08, 0x27, 0x9d, 0xf8, 0x03, 0x00, 0xa0, 0xee, 0x56,
+0xd4, 0x00, 0xfb, 0x75, 0x19, 0x14, 0x04, 0x20, 0x7b, 0x06, 0x00, 0x1c, 0xc0,
+0x1c, 0x2c, 0x04, 0x00, 0x00, 0x00, 0xc4, 0xd3, 0x08, 0x00, 0x00, 0x10, 0xf4,
+0x00, 0xc0, 0xef, 0xf2, 0x00, 0x1c, 0x20, 0x25, 0x6c, 0x14, 0x04, 0x60, 0xb7,
+0xe6, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x15, 0x00, 0xcc, 0xb3, 0xfc, 0x03, 0x1c,
+0xcc, 0x33, 0x05, 0x02, 0x1c, 0x00, 0x00, 0x1c, 0xc5, 0x04, 0x60, 0xb7, 0x1e,
+0x05, 0x04, 0x00, 0x00, 0x1c, 0x15, 0x04, 0x00, 0x00, 0x6c, 0xc4, 0x04, 0xc0,
+0x1d, 0xac, 0xf3, 0x04, 0x00, 0x00, 0x78, 0xc4, 0x04, 0x07, 0x9d, 0x00, 0x00,
+0x1c, 0x1b, 0x74, 0x0d, 0xf4, 0x04, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xe0, 0x7b,
+0x00, 0xfc, 0x1f, 0x39, 0x7f, 0x02, 0x00, 0x1c, 0x07, 0x1d, 0xb1, 0xc3, 0x04,
+0xa6, 0x7b, 0xc1, 0x03, 0x1c, 0x00, 0x00, 0x78, 0xc4, 0x04, 0xe0, 0x1c, 0x00,
+0x00, 0x1c, 0x00, 0x00, 0xb8, 0x03, 0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb,
+0x2f, 0x01, 0x10, 0x1d, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0x00, 0x00, 0xc0, 0x03,
+0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x18, 0x1d, 0xc7, 0x9f,
+0x00, 0x0b, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xfb, 0x75, 0x01, 0x00, 0x1c,
+0x07, 0x1d, 0x01, 0x00, 0x1c, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01,
+0x02, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xa0, 0x1c, 0x00, 0x00, 0x1c, 0xa0,
+0xee, 0xb6, 0x03, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x09, 0x04,
+0x1c, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xcc, 0xb3,
+0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02, 0x1c, 0x00, 0x00, 0x1c, 0xc5, 0x04,
+0x00, 0x00, 0x88, 0x34, 0x05, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x15,
+0x02, 0x1c, 0x47, 0x9d, 0x64, 0xc4, 0x04, 0x00, 0x00, 0x88, 0x44, 0x00, 0x80,
+0x1d, 0x8c, 0x54, 0x04, 0x87, 0x1d, 0x9d, 0x04, 0x00, 0xce, 0x76, 0x01, 0x00,
+0x1c, 0xef, 0x76, 0xad, 0xc4, 0x04, 0xa4, 0x77, 0x9d, 0x24, 0x09, 0xe4, 0x76,
+0x01, 0x00, 0x1c, 0xc4, 0x76, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xa8, 0x54, 0x04,
+0xd7, 0x76, 0x01, 0x50, 0x18, 0xf6, 0x76, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00,
+0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0xcc, 0x30, 0x51, 0xc5, 0x04, 0xeb,
+0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c, 0xc0, 0x59, 0x01, 0x00,
+0x1c, 0xf5, 0x77, 0x39, 0xc5, 0x04, 0xe0, 0x30, 0xec, 0x04, 0x00, 0x00, 0x4c,
+0xc0, 0x04, 0x00, 0x20, 0x4c, 0x04, 0x05, 0x00, 0x00, 0x00, 0xf8, 0x04, 0x00,
+0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x09, 0x02, 0x1c, 0xeb, 0x2d, 0xc5,
+0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x19, 0x02, 0x1c, 0xeb,
+0x2d, 0xc5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x0d, 0x02,
+0x1c, 0xeb, 0x2d, 0xc5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33,
+0x11, 0x02, 0x1c, 0xeb, 0x2d, 0xc5, 0xc4, 0x04, 0x00, 0x7b, 0x00, 0x80, 0x1c,
+0xae, 0x77, 0x51, 0x05, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xd3, 0x8b, 0x00,
+0xfc, 0x1f, 0x60, 0x7a, 0x3c, 0x00, 0x1c, 0x60, 0x4c, 0xd0, 0x04, 0x00, 0xc0,
+0x2f, 0x20, 0x05, 0x1f, 0xe0, 0x30, 0xc0, 0x04, 0x00, 0x80, 0x25, 0xc0, 0x04,
+0x00, 0xb5, 0x5b, 0xc1, 0x04, 0x04, 0x69, 0x26, 0x01, 0x00, 0x1c, 0x6a, 0x2b,
+0x01, 0x00, 0x1c, 0x80, 0x1d, 0x00, 0x00, 0x1c, 0xa9, 0x25, 0x51, 0x05, 0x00,
+0xee, 0x30, 0x00, 0x00, 0x1c, 0xaf, 0x77, 0x11, 0x05, 0x00, 0xb4, 0x5f, 0x01,
+0x40, 0x18, 0x07, 0x9d, 0x54, 0x55, 0x04, 0xb7, 0x76, 0x01, 0x00, 0x1c, 0x96,
+0x76, 0x01, 0x00, 0x1c, 0x47, 0x1d, 0x01, 0x00, 0x1c, 0xa4, 0x33, 0x01, 0x60,
+0x18, 0xa4, 0x2f, 0x01, 0x60, 0x18, 0x64, 0x77, 0x01, 0x60, 0x18, 0x24, 0x77,
+0x01, 0x60, 0x18, 0x44, 0x77, 0x01, 0x00, 0x1c, 0x64, 0x88, 0x03, 0x00, 0x1c,
+0xa4, 0x3f, 0x01, 0x00, 0x1c, 0xa4, 0x3b, 0x01, 0x00, 0x1c, 0x53, 0x77, 0x01,
+0x00, 0x1c, 0xd3, 0xcf, 0x3b, 0x00, 0x1c, 0x53, 0x4f, 0x02, 0x00, 0x1c, 0xd3,
+0xcf, 0x00, 0x00, 0x1f, 0xda, 0xcf, 0x0b, 0x00, 0x1c, 0xd5, 0x57, 0x0f, 0x00,
+0x1c, 0xd3, 0xd3, 0x37, 0x00, 0x1c, 0xd4, 0x53, 0x0f, 0x00, 0x1c, 0xe0, 0x29,
+0x00, 0x00, 0x1c, 0xf5, 0xd5, 0xc0, 0x05, 0x00, 0x00, 0x00, 0xac, 0x55, 0x04,
+0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00,
+0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xf5, 0x55, 0x01, 0x00, 0x1c, 0x00,
+0x00, 0xc4, 0x55, 0x04, 0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53, 0x01, 0x00,
+0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xcb, 0x2f,
+0x01, 0x18, 0x10, 0xcb, 0x2f, 0x01, 0x10, 0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10,
+0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f, 0x01, 0x20, 0x10, 0xcb, 0x2f, 0x01,
+0x00, 0x10, 0xcb, 0x2f, 0x01, 0x28, 0x10, 0x89, 0x25, 0x6d, 0xc2, 0x04, 0x00,
+0x00, 0x04, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3,
+0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc2, 0x04, 0x00, 0x00,
+0x04, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04,
+0x00, 0x00, 0x6c, 0xc3, 0x04, 0x40, 0x1c, 0x68, 0xc0, 0x04, 0x40, 0x1c, 0x98,
+0xc0, 0x04, 0xa7, 0x77, 0x6d, 0xc3, 0x04, 0x00, 0x00, 0xc0, 0xc0, 0x04, 0x27,
+0x1d, 0xed, 0xc0, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3,
+0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00,
+0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6,
+0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00,
+0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c,
+0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04,
+};
diff --git a/drivers/staging/slicoss/oasisdbgdownload.h b/drivers/staging/slicoss/oasisdbgdownload.h
new file mode 100644
index 00000000000..519e00797d4
--- /dev/null
+++ b/drivers/staging/slicoss/oasisdbgdownload.h
@@ -0,0 +1,6850 @@
+#define OASIS_UCODE_VERS_STRING "1.2"
+#define OASIS_UCODE_VERS_DATE "2006/03/27 15:11:22"
+#define OASIS_UCODE_HOSTIF_ID 3
+
+static s32 ONumSections = 0x2;
+static u32 OSectionSize[] =
+{
+ 0x00004000, 0x00010000,
+};
+
+static u32 OSectionStart[] =
+{
+ 0x00000000, 0x00008000,
+};
+
+static u8 OasisUCode[2][65536] =
+{
+ {
+ 0x15, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00,
+ 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40,
+ 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x98, 0x18, 0x31, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x41, 0x98,
+ 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x0e, 0x00, 0x40, 0x98,
+ 0x80, 0x94, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x19, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x19, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1f, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x12, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x25, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x25, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x14, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xdd, 0x81, 0x01, 0x00, 0x12, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x33, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x00, 0x14, 0xbc,
+ 0x80, 0x32, 0x00, 0x00, 0xfe, 0x00, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xfd, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00,
+ 0x33, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x89, 0xb0, 0x01, 0x00, 0x32, 0x00, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00,
+ 0x99, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x20, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xe0, 0xb3, 0x01, 0x00, 0x39, 0x00, 0x98, 0xee,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x80, 0xb0, 0x01, 0x00,
+ 0x3b, 0x00, 0x80, 0xf3, 0xde, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0xfd, 0x93, 0x01, 0x00, 0x3e, 0x00, 0x83, 0xf3, 0x80, 0x32, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0xf3, 0x80, 0x88, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40,
+ 0x2e, 0xdd, 0x01, 0x00, 0x00, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x43, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0x24, 0xb1, 0x01, 0x00, 0x7c, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00,
+ 0x45, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xe8,
+ 0x80, 0x88, 0x01, 0x00, 0x7c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, 0xee, 0x8b, 0x01, 0x00,
+ 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf0,
+ 0x80, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x81, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8,
+ 0x80, 0x88, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xf0, 0xd6, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xf0,
+ 0xf0, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xf8, 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00,
+ 0x3c, 0x02, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd6, 0xb1, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, 0x1e, 0x00, 0x00, 0xf0,
+ 0x82, 0xf4, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xf8, 0x80, 0xd8, 0x01, 0x00,
+ 0x64, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x81, 0xd0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, 0x80, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd8, 0xb1, 0x01, 0x00, 0x68, 0x00, 0x22, 0xfa, 0x80, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x81, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40,
+ 0x80, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xde, 0xb1, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa,
+ 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, 0x80, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd6, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x18, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa,
+ 0xd6, 0xe5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x03, 0x00, 0x00, 0xfb,
+ 0x7a, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdc, 0xb1, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x00, 0x00, 0x7c, 0x00, 0x95, 0xe8,
+ 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42,
+ 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x7c, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x85, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0x8c, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0x98, 0x00, 0x1f, 0xfd,
+ 0xf9, 0x33, 0x00, 0x00, 0x8b, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48,
+ 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x19, 0xb1, 0x01, 0x00, 0x93, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00,
+ 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0x97, 0x00, 0xa2, 0xff,
+ 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0xfd, 0x7f, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xce, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0xfd, 0x7f, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x9a, 0x13, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x01, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x9a, 0x13, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x29, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x67, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xfd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xfd, 0x83, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0x80, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00, 0xe2, 0x00, 0x00, 0x40,
+ 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x46, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x40, 0x2b, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x46, 0x88, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x94, 0x8c, 0xb0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x46, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40,
+ 0x80, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0xf0, 0x01, 0x00,
+ 0xc9, 0x00, 0x82, 0x41, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfd, 0x83, 0x01, 0x00,
+ 0xd4, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44,
+ 0x80, 0xb2, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x08, 0x83, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x44,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0x30, 0x00, 0x08, 0x83, 0x98, 0x01, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40,
+ 0x89, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0x80, 0xb2, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x94, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40,
+ 0x80, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x80, 0x43, 0x89, 0xb0, 0x01, 0x00,
+ 0x03, 0x84, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x88, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x96,
+ 0x80, 0xb2, 0x00, 0x00, 0xdf, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40,
+ 0x25, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xe0, 0x01, 0x00,
+ 0xdd, 0x00, 0x00, 0x44, 0x82, 0x14, 0x01, 0x00, 0x00, 0x00, 0x90, 0x94,
+ 0x8a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x89, 0xd0, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00,
+ 0xec, 0x00, 0x08, 0x41, 0x80, 0x32, 0x00, 0x00, 0xed, 0x00, 0x00, 0x94,
+ 0x24, 0xb1, 0x00, 0x00, 0x10, 0x00, 0x00, 0x94, 0x24, 0xf5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xf2, 0x00, 0xa0, 0x44,
+ 0x89, 0x50, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xef, 0x00, 0x20, 0x44,
+ 0x89, 0x50, 0x00, 0x00, 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42,
+ 0x89, 0xd0, 0x00, 0x00, 0xf7, 0x00, 0xa0, 0xfa, 0x8a, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xf5, 0x00, 0xa3, 0x42,
+ 0x89, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x45, 0x8a, 0xf4, 0x01, 0x00, 0xfc, 0x00, 0x90, 0x44,
+ 0x8a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x45, 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50,
+ 0x8b, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0x00, 0x30, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x08, 0x83, 0x14, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0x2a, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0xf9, 0x9b, 0x01, 0x00, 0xdd, 0x00, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x40, 0x94, 0x80, 0xb2, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44,
+ 0x2b, 0x41, 0x01, 0x00, 0x00, 0x00, 0x41, 0x94, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x2b, 0xc1, 0x01, 0x00, 0x04, 0x01, 0x9f, 0x94, 0x80, 0x32, 0x00, 0x00,
+ 0x02, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x01, 0x00, 0x51,
+ 0x93, 0xb0, 0x00, 0x00, 0x10, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00,
+ 0x10, 0x01, 0x00, 0x49, 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x93, 0xb0, 0x01, 0x00, 0x10, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x12, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x71, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x72, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x73, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x74, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x76, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x77, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x78, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x79, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x7a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x7d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7e, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0xb0, 0x01, 0x00, 0x3b, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x47, 0x01, 0x22, 0x4b,
+ 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1,
+ 0x7e, 0xb1, 0x01, 0x00, 0x48, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x45, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x80, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x18, 0x00, 0x00, 0xaa, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x43, 0x97, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0xaa,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00,
+ 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00, 0x5a, 0x01, 0x22, 0xcc,
+ 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe1, 0xb1, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x62, 0xdd, 0x01, 0x00, 0x63, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbc, 0xb3, 0x01, 0x00,
+ 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7,
+ 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0x80, 0xf4, 0x01, 0x00, 0x73, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00,
+ 0x86, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x10, 0xb1, 0x00, 0x00, 0x87, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x88, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc4, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x82, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x83, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xb8, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x28, 0x00, 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00,
+ 0xd5, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xd6, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x28, 0x00, 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00,
+ 0x72, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x28, 0x00, 0x55, 0x01, 0x51, 0x49,
+ 0xfd, 0x93, 0x28, 0x00, 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x2a, 0x00,
+ 0x55, 0x01, 0x55, 0x49, 0xfd, 0x83, 0x2a, 0x00, 0x55, 0x01, 0x56, 0x4a,
+ 0xfd, 0x83, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x2a, 0x00,
+ 0x55, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x82,
+ 0x80, 0x30, 0x2a, 0x00, 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0xb3, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0x92, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xd1, 0x01, 0x00, 0x9a, 0x01, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x96, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x50, 0x01, 0x00, 0x41,
+ 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0xb3, 0x01, 0x00,
+ 0x50, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00,
+ 0xb5, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x42, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x42, 0xff,
+ 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xff,
+ 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4, 0x80, 0xcc, 0x01, 0x00,
+ 0xaa, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x85, 0xc0, 0x01, 0x00, 0xa8, 0x01, 0xa2, 0x4c, 0x81, 0x50, 0x00, 0x00,
+ 0xb4, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x01, 0x22, 0x41,
+ 0xa5, 0x6f, 0x00, 0x00, 0x50, 0x01, 0xa2, 0xe0, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x88, 0x94, 0x01, 0x00, 0x55, 0x01, 0x00, 0x44, 0xe0, 0xb1, 0x00, 0x00,
+ 0xb1, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x5b,
+ 0x89, 0x90, 0x00, 0x00, 0xa8, 0x9f, 0x00, 0xa0, 0x9e, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0xbe, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0xb9, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x43,
+ 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x40, 0xf8, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40,
+ 0xe1, 0xb1, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xcb, 0x01, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00,
+ 0xd1, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x53, 0x01, 0x00, 0xde,
+ 0xa1, 0xb3, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe5, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x52, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0xa1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0xdb, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00,
+ 0xda, 0x01, 0x84, 0x41, 0x81, 0x40, 0x00, 0x00, 0xde, 0x01, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00,
+ 0xd5, 0x01, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0xda, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3,
+ 0xa7, 0xcb, 0x01, 0x00, 0xf8, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x53, 0x01, 0x00, 0xde,
+ 0xa1, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0x81, 0x90, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xba,
+ 0x80, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00,
+ 0xe8, 0x01, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x52, 0x01, 0x00, 0x40,
+ 0xe0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00,
+ 0x6b, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x4d,
+ 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xe5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf9, 0xb3, 0x01, 0x00, 0xf9, 0x01, 0x22, 0x40,
+ 0x8f, 0x6f, 0x00, 0x00, 0x78, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x60, 0x02, 0x00, 0xc7, 0x83, 0x30, 0x01, 0x00, 0x80, 0x02, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe8, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xed, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xba,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xf0, 0xb1, 0x01, 0x00,
+ 0x0c, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0x90, 0x01, 0x00, 0x0e, 0x02, 0xb9, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00, 0x10, 0x02, 0xba, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x81, 0x90, 0x01, 0x00,
+ 0x12, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x81, 0x90, 0x01, 0x00, 0x14, 0x02, 0xbc, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00, 0x16, 0x02, 0xbd, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x81, 0x90, 0x01, 0x00,
+ 0x18, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x81, 0x90, 0x01, 0x00, 0x1a, 0x02, 0xbf, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00, 0x1c, 0x02, 0xc8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0x90, 0x01, 0x00,
+ 0x1e, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x81, 0x90, 0x01, 0x00, 0x20, 0x02, 0xca, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00, 0x22, 0x02, 0xcb, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x81, 0x90, 0x01, 0x00,
+ 0x24, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x81, 0x90, 0x01, 0x00, 0x26, 0x02, 0xcd, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00, 0x28, 0x02, 0xce, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0x90, 0x01, 0x00,
+ 0x2a, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x81, 0x90, 0x01, 0x00, 0x2c, 0x02, 0xf0, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x81, 0x90, 0x01, 0x00, 0x2e, 0x02, 0xf1, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x81, 0x90, 0x01, 0x00,
+ 0x30, 0x02, 0xf2, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x81, 0x90, 0x01, 0x00, 0x32, 0x02, 0xf3, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x81, 0x90, 0x01, 0x00, 0x34, 0x02, 0xf4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0x90, 0x01, 0x00,
+ 0x36, 0x02, 0xf5, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x81, 0x90, 0x01, 0x00, 0x38, 0x02, 0xf6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x56, 0x81, 0x90, 0x01, 0x00, 0x3a, 0x02, 0xf7, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0x90, 0x01, 0x00,
+ 0x3c, 0x02, 0xf8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x81, 0x90, 0x01, 0x00, 0x3e, 0x02, 0xf9, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x59, 0x81, 0x90, 0x01, 0x00, 0x40, 0x02, 0xfa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x81, 0x90, 0x01, 0x00,
+ 0x42, 0x02, 0xfb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x81, 0x90, 0x01, 0x00, 0x44, 0x02, 0xfc, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x81, 0x90, 0x01, 0x00, 0x46, 0x02, 0xfd, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x81, 0x90, 0x01, 0x00,
+ 0x48, 0x02, 0xfe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x81, 0x90, 0x01, 0x00, 0x4a, 0x02, 0xff, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00,
+ 0xdb, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x66, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x63, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5f, 0x02, 0x49, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x68, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x5f, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1,
+ 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4,
+ 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99,
+ 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7,
+ 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x84, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x88, 0x02, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00,
+ 0x8d, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00,
+ 0x9b, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x42,
+ 0xa5, 0x63, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x97, 0x02, 0x22, 0x44,
+ 0xa5, 0x53, 0x00, 0x00, 0x94, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xe8, 0x02, 0x00, 0xde,
+ 0xa1, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xbf, 0xb3, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0x63, 0xb1, 0x01, 0x00, 0x9e, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x54,
+ 0xa5, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00,
+ 0xac, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x46,
+ 0x83, 0x30, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8,
+ 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb,
+ 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xbd, 0x02, 0x00, 0x40,
+ 0x10, 0xc9, 0x00, 0x00, 0xc3, 0x02, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcb, 0x02, 0x00, 0x05,
+ 0x81, 0xb0, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd0, 0x02, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x44,
+ 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1,
+ 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0xc4, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x00, 0xc2,
+ 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00,
+ 0xc8, 0x02, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd4, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xe2, 0x02, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8,
+ 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3,
+ 0xf1, 0xb1, 0x01, 0x00, 0xe1, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc,
+ 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0xfa, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf9, 0x02, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x41,
+ 0x99, 0xb3, 0x01, 0x00, 0x0a, 0x03, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00,
+ 0x12, 0x03, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x0c, 0x03, 0x22, 0x4c,
+ 0x81, 0x6c, 0x00, 0x00, 0x16, 0x03, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00,
+ 0x17, 0x03, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x19, 0x03, 0x22, 0x58,
+ 0x81, 0x6c, 0x00, 0x00, 0x1e, 0x03, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
+ 0x09, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xf3, 0x83, 0x01, 0x00, 0x10, 0x03, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x22, 0xca,
+ 0x07, 0x14, 0x00, 0x00, 0xdd, 0x9f, 0x00, 0x45, 0xf3, 0x93, 0x00, 0x00,
+ 0xdd, 0x9f, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xdd, 0x9f, 0x80, 0xca,
+ 0x05, 0x30, 0x00, 0x00, 0xdd, 0x9f, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00,
+ 0xdd, 0x9f, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc,
+ 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca,
+ 0x81, 0x88, 0x01, 0x00, 0xdd, 0x9f, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00,
+ 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x1b, 0x03, 0xa8, 0xb1,
+ 0x82, 0x30, 0x00, 0x00, 0x1a, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdd, 0x9f, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x22, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x2d, 0x03, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40,
+ 0x80, 0xce, 0x01, 0x00, 0x2b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x2d, 0x03, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x32, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x3d, 0x03, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89,
+ 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x3b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3d, 0x03, 0x55, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xb5, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00,
+ 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x30, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x90, 0x00, 0xf8,
+ 0x80, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf2, 0x88, 0xe4, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x4d, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x50, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x53, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0x55, 0x03, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x80, 0x40, 0x20, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x8f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00,
+ 0x5a, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x47,
+ 0x8e, 0xc8, 0x01, 0x00, 0x58, 0x03, 0x00, 0x5c, 0x8f, 0x80, 0x00, 0x00,
+ 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x58, 0x15, 0x2d, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, 0x82, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x82, 0x94, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8d, 0xc0, 0x01, 0x00, 0x74, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00,
+ 0x65, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x63, 0x03, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43, 0x86, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00, 0x70, 0x03, 0x00, 0x41,
+ 0x83, 0xe0, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00, 0xd0, 0x14, 0x2f, 0x46,
+ 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42, 0x60, 0x99, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x07, 0x00, 0x00, 0x45, 0x80, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x85, 0x03, 0xa0, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x83, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x8e, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0x00, 0x39, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x8b, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x44,
+ 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00,
+ 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x39, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00,
+ 0x95, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x97, 0x03, 0x22, 0x5a,
+ 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x98, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x90, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6,
+ 0x90, 0xb0, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0x8a, 0xb0, 0x01, 0x00, 0x80, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0xac, 0x03, 0x22, 0x40,
+ 0x82, 0x6c, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x58, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8d, 0xc0, 0x01, 0x00, 0xb5, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00,
+ 0xa7, 0x03, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0xa5, 0x03, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0xa6, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x9f, 0x00, 0x47,
+ 0x80, 0x30, 0x01, 0x00, 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00,
+ 0xb0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x50, 0xb3, 0x01, 0x00, 0xbb, 0x03, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00,
+ 0xbe, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6,
+ 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x50, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x4e, 0xd3, 0x01, 0x00, 0x6e, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x82, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00,
+ 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc7, 0x03, 0x22, 0xa7,
+ 0x8f, 0x6c, 0x00, 0x00, 0x5a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc4, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa0, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xca,
+ 0xa7, 0x33, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x03, 0x22, 0x42,
+ 0x75, 0x6f, 0x00, 0x00, 0xd8, 0x03, 0x22, 0x41, 0x75, 0x6f, 0x00, 0x00,
+ 0xda, 0x03, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xdc, 0x03, 0x1f, 0xca,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x42, 0x75, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xcd, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x41, 0x75, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40,
+ 0x75, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0xc6, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, 0x75, 0xb3, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x45, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00,
+ 0x45, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x45, 0x01, 0x00, 0x4c,
+ 0x93, 0x30, 0x01, 0x00, 0xec, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0xa0, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40,
+ 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44,
+ 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43,
+ 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa5, 0xc3, 0x01, 0x00, 0x0b, 0x04, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00,
+ 0x0b, 0x04, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xfa, 0x03, 0xa2, 0x50,
+ 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb,
+ 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0x08, 0x04, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x07, 0x04, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0xfa, 0x03, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00,
+ 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xff, 0xff, 0x00, 0x94, 0xb4, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd9,
+ 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xdd, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x94,
+ 0xb4, 0xb3, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x27, 0xb1, 0x01, 0x00, 0x06, 0xc0, 0x00, 0x40, 0x2d, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x02, 0xc4, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x40, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x05, 0x82, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2d, 0x04, 0x80, 0x94,
+ 0x80, 0x32, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x28, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x40,
+ 0x2d, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x31, 0x04, 0x00, 0x12,
+ 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x4b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x50, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x56, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x5b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x60, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x65, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x6b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x70, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x75, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x7a, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x59, 0x04, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x82, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x84, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x86, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x88, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x8c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8e, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x90, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x92, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x94, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x96, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x98, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9a, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x9e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa0, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa2, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xa4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa6, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa8, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xaa, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xac, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xae, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xb0, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb2, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xb6, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb8, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xba, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xbc, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xbe, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x82, 0x04, 0x85, 0x41,
+ 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00,
+ 0x87, 0x04, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x90, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xb1, 0x01, 0x00,
+ 0xff, 0xff, 0xf0, 0x4b, 0x82, 0x89, 0x01, 0x00, 0x93, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x80, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0xf0, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x96, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0xf0, 0xc2, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b, 0x92, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x80, 0xa6,
+ 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x94, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x88, 0x94, 0x01, 0x00, 0xa6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xad, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xa6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xb0, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x62, 0xb1, 0x01, 0x00, 0xb1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb8, 0x04, 0x22, 0x4b, 0x89, 0x7c, 0x00, 0x00, 0xb6, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xb6, 0x04, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xc1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xc6, 0x04, 0x22, 0x4b,
+ 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xc4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xc1, 0x04, 0xa2, 0x41,
+ 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x99, 0xe0, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x4c,
+ 0x88, 0x94, 0x00, 0x00, 0xd6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xdd, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xe0, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x62, 0xb1, 0x01, 0x00, 0xe1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xe8, 0x04, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0xe6, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x04, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xf1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xf6, 0x04, 0x22, 0x4a,
+ 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xf4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xf1, 0x04, 0xa2, 0x41,
+ 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x00, 0x05, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x12, 0x05, 0x1d, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x10, 0x05, 0xa2, 0x40,
+ 0x86, 0x04, 0x00, 0x00, 0xde, 0x9f, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50,
+ 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00,
+ 0x0c, 0x05, 0x52, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x05, 0x00, 0x40,
+ 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0x30, 0x05, 0x00, 0x05,
+ 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x1b, 0x00, 0xde, 0x9f, 0x00, 0x41,
+ 0xe1, 0xc1, 0x1a, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x1b, 0x00,
+ 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x1a, 0x00, 0x14, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x1a, 0x00, 0x00, 0x82, 0x00, 0xb3, 0x67, 0xdf, 0x1b, 0x00,
+ 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x1b, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x1b, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0x27, 0x05, 0x0f, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40,
+ 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0x1f, 0x05, 0x99, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00,
+ 0x21, 0x05, 0x9b, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x89, 0xd0, 0x01, 0x00, 0x23, 0x05, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00,
+ 0x30, 0x05, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x89, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x58, 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00,
+ 0x6f, 0x00, 0x00, 0x43, 0x86, 0x88, 0x01, 0x00, 0xde, 0x9f, 0x26, 0x05,
+ 0x47, 0x31, 0x00, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x07,
+ 0x91, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x97, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x44, 0x05, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0x45, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0x10, 0x04, 0x00, 0x42,
+ 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xf5, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda,
+ 0xf7, 0xf5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x8f, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48,
+ 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x91, 0xc0, 0x01, 0x00, 0x50, 0x05, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda,
+ 0x8f, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x7a, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x78, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0x7d, 0x05, 0x22, 0x20, 0xb5, 0x6f, 0x00, 0x00, 0x7a, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x1f, 0x00,
+ 0x7d, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x1e, 0x00, 0x7a, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x1f, 0x00,
+ 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x1e, 0x00, 0x54, 0x16, 0x00, 0x40,
+ 0x47, 0x99, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x46, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x97, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda,
+ 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00,
+ 0x90, 0x05, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40,
+ 0xa5, 0x9b, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb,
+ 0x85, 0x30, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb8, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x05, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xaa, 0x05, 0xa2, 0x41,
+ 0x83, 0x50, 0x00, 0x00, 0xa9, 0x05, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb0, 0x05, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xb1, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x05, 0xa2, 0xfa,
+ 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00,
+ 0xb8, 0x05, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42,
+ 0xb3, 0x43, 0x01, 0x00, 0xbb, 0x05, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00,
+ 0xb8, 0x05, 0x42, 0x40, 0x81, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x67, 0x93, 0x21, 0x00, 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x20, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0xdb, 0x9f, 0x00, 0x40,
+ 0x49, 0x31, 0x21, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x21, 0x00,
+ 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0x00, 0x00, 0x6e, 0xfa,
+ 0x8e, 0xb0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xb4, 0xb3, 0x01, 0x00, 0xc9, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0xfc, 0x15, 0x20, 0x20, 0xe1, 0xb1, 0x01, 0x00, 0xce, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x24, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x25, 0x00,
+ 0xce, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x24, 0x00, 0xcb, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x24, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x25, 0x00,
+ 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x24, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x25, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x25, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd3, 0x05, 0x22, 0x50,
+ 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x4a, 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x4a, 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe9, 0x05, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00,
+ 0xea, 0x05, 0x00, 0x50, 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xb5, 0xb3, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0xfc, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06,
+ 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0xff, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00,
+ 0x02, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x08, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00,
+ 0x14, 0x06, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70,
+ 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00,
+ 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6,
+ 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00,
+ 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73,
+ 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00,
+ 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf7, 0xb1, 0x01, 0x00, 0x25, 0x06, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47,
+ 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0x2e, 0x06, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41,
+ 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00,
+ 0x4b, 0x06, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40,
+ 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00,
+ 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75,
+ 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00,
+ 0x55, 0x06, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x5a, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x89, 0xa4, 0x01, 0x00, 0x64, 0x06, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x57, 0x06, 0xaa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x6b, 0x06, 0xa3, 0x53,
+ 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00,
+ 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x70, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6,
+ 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00,
+ 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x75, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x37, 0x06, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75,
+ 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78,
+ 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00,
+ 0x2b, 0x06, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x7c, 0x16, 0x20, 0xf6, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x31, 0xb3, 0x01, 0x00, 0x9d, 0x06, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0xfd, 0x93, 0x01, 0x00, 0x9f, 0x06, 0x22, 0x40,
+ 0x8f, 0x7c, 0x00, 0x00, 0xa3, 0x06, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00,
+ 0xa1, 0x06, 0x22, 0x42, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0xfd, 0x93, 0x01, 0x00, 0xa3, 0x06, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0xfd, 0x93, 0x01, 0x00, 0xb7, 0x06, 0x22, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb2, 0x06, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x4b, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb6, 0x06, 0x22, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0xba, 0x06, 0x00, 0x54,
+ 0xfd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0xfe, 0x7f, 0xd9, 0x01, 0x00, 0xba, 0x06, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe7, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc4, 0x06, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xe9, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4,
+ 0x0c, 0xc8, 0x01, 0x00, 0xea, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x0a, 0x07, 0x22, 0x01,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0xd9, 0x06, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00,
+ 0xda, 0x06, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xec, 0x06, 0x22, 0x40,
+ 0x03, 0x6c, 0x00, 0x00, 0xe6, 0x06, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x23, 0x07, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x23, 0x07, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xee, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0xfa, 0x06, 0x23, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00,
+ 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d,
+ 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x02, 0x07, 0x22, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14,
+ 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x23, 0x07, 0x00, 0x1a,
+ 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x0f, 0x07, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00,
+ 0x10, 0x07, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x12,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, 0x16, 0x94, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x17, 0x07, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x40, 0x07, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00,
+ 0x40, 0x07, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x07, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x23, 0x07, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x1f, 0x07, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x3f, 0x07, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x2e, 0x07, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x2c, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x29, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x04, 0xb0, 0x01, 0x00, 0x33, 0x07, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00,
+ 0xd3, 0x06, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f,
+ 0x0f, 0x80, 0x01, 0x00, 0xd3, 0x06, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x3c, 0x07, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0xd3, 0x06, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x0d,
+ 0x18, 0xc0, 0x00, 0x00, 0x5f, 0x07, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50,
+ 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d,
+ 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00,
+ 0x52, 0x07, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xc0, 0x01, 0x00, 0x50, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x96, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x18, 0x90, 0xb0, 0x01, 0x00, 0x5c, 0x07, 0xa0, 0xfc,
+ 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00,
+ 0x5a, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x80, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x2d, 0x00,
+ 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x48, 0xc1, 0x2d, 0x00, 0x64, 0x07, 0x43, 0x30, 0x3d, 0x07, 0x2c, 0x00,
+ 0x00, 0x00, 0x00, 0x9e, 0x85, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x41,
+ 0x3d, 0xc3, 0x2d, 0x00, 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x2d, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d,
+ 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x80, 0xc0, 0x01, 0x00, 0x6e, 0x07, 0xa0, 0x41,
+ 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30,
+ 0x81, 0x84, 0x01, 0x00, 0x72, 0x07, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x93, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x19, 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e,
+ 0x16, 0xc0, 0x01, 0x00, 0x78, 0x07, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e,
+ 0x32, 0xc0, 0x01, 0x00, 0x7d, 0x07, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00,
+ 0x7c, 0x07, 0xa0, 0x1c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e,
+ 0x98, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00,
+ 0x0c, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x8b, 0x07, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x89, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x86, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x1a, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00,
+ 0x91, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x07, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x9b, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x98, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xeb, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xa1, 0x07, 0x90, 0xf2,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14,
+ 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xac, 0x07, 0x22, 0xf2, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xa9, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00,
+ 0xc9, 0x07, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00, 0xb4, 0x07, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00,
+ 0xb3, 0x07, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88,
+ 0x1c, 0xcc, 0x01, 0x00, 0xe4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x3f, 0xc3, 0x01, 0x00, 0xe6, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb7, 0x07, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x3e, 0xc0, 0x01, 0x00, 0xc9, 0x07, 0x22, 0x40,
+ 0x15, 0x6c, 0x00, 0x00, 0xba, 0x07, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x3c, 0xb0, 0x01, 0x00, 0xe5, 0x9f, 0x00, 0x1e,
+ 0x24, 0x30, 0x01, 0x00, 0xbf, 0x07, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a,
+ 0x10, 0xc0, 0x01, 0x00, 0x23, 0x07, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00,
+ 0xe4, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe5, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xbc, 0x07, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0xe8, 0x9f, 0x00, 0x1f,
+ 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00,
+ 0xe6, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x07, 0xa2, 0x41,
+ 0x87, 0x7c, 0x00, 0x00, 0xcf, 0x07, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1f, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0xe8, 0x9f, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00,
+ 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x07, 0x00, 0xbc, 0x80, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00,
+ },
+ {
+ 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80,
+ 0x80, 0x32, 0x00, 0x00, 0xe4, 0x87, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2,
+ 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00,
+ 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81,
+ 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xe4, 0x87, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42,
+ 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48,
+ 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53,
+ 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00,
+ 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xc6, 0x82, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xc6, 0x82, 0x05, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0xde, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0x9b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00,
+ 0x48, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44,
+ 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x24, 0xb1, 0x01, 0x00, 0x00, 0x0c, 0x00, 0xee,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x97, 0xf0, 0x01, 0x00,
+ 0x44, 0x80, 0xa2, 0x43, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x06, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x05, 0x10, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x02, 0x09, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x60, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x88, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa0, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb9, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb1, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x91, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00,
+ 0x99, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x3c, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x90, 0x06, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x2f, 0x81, 0x01, 0x00,
+ 0xa2, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x9e, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xc6, 0x82, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x00, 0x00,
+ 0x6c, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0xb4,
+ 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x18, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x55, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7d, 0x80, 0x22, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x7a, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x80, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x80, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x40, 0x05, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00, 0xc1, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x96, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x96, 0x80, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x93, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00,
+ 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xd0, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd5, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x01, 0x00, 0x41,
+ 0x81, 0xc0, 0x00, 0x00, 0x55, 0x01, 0x51, 0x49, 0xfd, 0x93, 0x00, 0x00,
+ 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x00, 0x00, 0x55, 0x01, 0x55, 0x49,
+ 0xfd, 0x83, 0x00, 0x00, 0x55, 0x01, 0x56, 0x4a, 0xfd, 0x83, 0x00, 0x00,
+ 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x00, 0x00, 0x55, 0x01, 0x45, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00,
+ 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0xb4, 0x80, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40,
+ 0x91, 0x6f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00,
+ 0xc1, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00,
+ 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0xc9, 0x80, 0xa2, 0x42,
+ 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04,
+ 0x80, 0x94, 0x00, 0x00, 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03,
+ 0x02, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xcb, 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc,
+ 0xf3, 0x83, 0x01, 0x00, 0xd3, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcb, 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb,
+ 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00,
+ 0xda, 0x80, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf9, 0x02, 0x00, 0x20,
+ 0x42, 0x31, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0xcb, 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41,
+ 0x8b, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xe0, 0x80, 0xa8, 0xb1, 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xe2, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00,
+ 0xe8, 0x80, 0x14, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6,
+ 0x83, 0xf4, 0x01, 0x00, 0x22, 0x83, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00,
+ 0xc4, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6,
+ 0x81, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00,
+ 0xc4, 0x80, 0x1f, 0x5c, 0x97, 0x53, 0x00, 0x00, 0x6d, 0x82, 0x1e, 0xc6,
+ 0x81, 0x32, 0x00, 0x00, 0xf2, 0x80, 0x22, 0x48, 0xfd, 0x7f, 0x00, 0x00,
+ 0xf2, 0x80, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00, 0xf2, 0x80, 0x22, 0x48,
+ 0x81, 0x6c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x84, 0xcc, 0x01, 0x00,
+ 0xf2, 0x80, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0xc6, 0x8f, 0x06, 0x00, 0x00,
+ 0xc4, 0x80, 0x1e, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x43,
+ 0x81, 0xf0, 0x01, 0x00, 0xf6, 0x80, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00,
+ 0x44, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7e, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x39, 0x82, 0x00, 0xca, 0x63, 0xb3, 0x00, 0x00,
+ 0x75, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x81, 0x00, 0x4d,
+ 0x83, 0xb0, 0x00, 0x00, 0x60, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00,
+ 0x4c, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0x55, 0x81, 0x00, 0x4c,
+ 0x83, 0xb0, 0x00, 0x00, 0x2e, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00,
+ 0xf8, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x86, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0xf4, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x4c, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0x9b, 0xb3, 0x00, 0x00,
+ 0x90, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x94, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x9b, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x9c, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x9d, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x9e, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x9f, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x9f, 0x81, 0x00, 0x41,
+ 0x81, 0xb0, 0x00, 0x00, 0x2d, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xae, 0x82, 0x00, 0xbb, 0xab, 0xb3, 0x00, 0x00, 0x3a, 0x82, 0x00, 0xca,
+ 0xcf, 0xb3, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0xe8, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca,
+ 0x77, 0xb3, 0x00, 0x00, 0x56, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00,
+ 0x5e, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, 0x4c, 0x81, 0x00, 0xbb,
+ 0x85, 0xb0, 0x00, 0x00, 0x56, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00,
+ 0x4c, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x2e, 0x81, 0x00, 0xbb,
+ 0x85, 0xb0, 0x00, 0x00, 0x20, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0xca, 0x4d, 0xb3, 0x00, 0x00, 0x70, 0x05, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0x26, 0x81, 0x22, 0x42, 0x8f, 0x6f, 0x00, 0x00, 0x28, 0x81, 0x22, 0x41,
+ 0x8f, 0x6f, 0x00, 0x00, 0x2a, 0x81, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00,
+ 0x2c, 0x81, 0x1f, 0xca, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xc9, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x42, 0x8f, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xcd, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x41,
+ 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00,
+ 0x22, 0x83, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6,
+ 0xc6, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40,
+ 0x8f, 0xb3, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x2f, 0x9c, 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40,
+ 0x39, 0x33, 0x01, 0x00, 0x18, 0x00, 0x2f, 0x9b, 0x89, 0xb0, 0x01, 0x00,
+ 0x46, 0x81, 0x00, 0x40, 0x37, 0x33, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x9a,
+ 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40, 0x35, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x2f, 0x99, 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40,
+ 0x33, 0x33, 0x01, 0x00, 0x00, 0x80, 0x00, 0xae, 0x47, 0xc9, 0x01, 0x00,
+ 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40,
+ 0xe1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0xae, 0x63, 0xdd, 0x01, 0x00, 0x41, 0x81, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x3e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x69, 0x93, 0x01, 0x00, 0x22, 0x83, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00,
+ 0x44, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x43, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4b, 0x81, 0xa2, 0x40,
+ 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0xe1, 0xd1, 0x01, 0x00, 0x4c, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x52, 0x81, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x4d, 0x81, 0x22, 0x5c, 0x77, 0x7d, 0x00, 0x00,
+ 0xc4, 0x80, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4d, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00,
+ 0x52, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x22, 0x83, 0x17, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x57, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00,
+ 0x57, 0x81, 0x00, 0xbb, 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x60, 0xb1, 0x01, 0x00, 0xc4, 0x80, 0xa2, 0x41, 0x76, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x59, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00,
+ 0x22, 0x83, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5b, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x61, 0x81, 0x00, 0xbb, 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0x65, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00,
+ 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0xc4, 0x80, 0x22, 0x40,
+ 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x60, 0x40, 0x95, 0x83, 0x00, 0x00,
+ 0x02, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0xc4, 0x80, 0x22, 0x40,
+ 0x85, 0x6c, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x40, 0x85, 0x7c, 0x00, 0x00,
+ 0xc4, 0x80, 0xa2, 0x4e, 0x77, 0x7d, 0x00, 0x00, 0x69, 0x81, 0x36, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00,
+ 0x6a, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x62, 0xb1, 0x01, 0x00, 0x6c, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0x6e, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x74, 0x81, 0x22, 0x41, 0x43, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0xca,
+ 0x95, 0xcb, 0x01, 0x00, 0x68, 0x81, 0x00, 0x41, 0x85, 0xc0, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0x40, 0xe1, 0xb1, 0x00, 0x00, 0x77, 0x81, 0xa2, 0x42,
+ 0x67, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00,
+ 0x77, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x65, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0xca, 0x69, 0x97, 0x01, 0x00, 0x22, 0x83, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x7c, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x22, 0x83, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0xc4, 0x80, 0x20, 0x43,
+ 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00,
+ 0x22, 0x83, 0x22, 0x40, 0x65, 0x6f, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x48,
+ 0xdb, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00,
+ 0x85, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x35, 0x80, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x95, 0x93, 0x01, 0x00, 0x8c, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xc3, 0xb1, 0x01, 0x00, 0x8f, 0x81, 0x22, 0x5b,
+ 0x95, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00,
+ 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca,
+ 0x95, 0x9b, 0x01, 0x00, 0x0d, 0x01, 0x00, 0xca, 0xc5, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca,
+ 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xc7, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x22, 0x5f, 0x95, 0x7f, 0x00, 0x00,
+ 0x0d, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x95, 0x83, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca, 0xc7, 0xb1, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca,
+ 0xcb, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0xcd, 0xb1, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x42,
+ 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40, 0x48, 0xc9, 0x01, 0x00,
+ 0x22, 0x83, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xa4, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0xa6, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00, 0xa8, 0x81, 0x9f, 0x85,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x83, 0x84, 0x01, 0x00,
+ 0xdd, 0x81, 0x22, 0x30, 0x83, 0x6c, 0x00, 0x00, 0xa7, 0x81, 0xa2, 0x4f,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00,
+ 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00,
+ 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0xbd, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xba, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0xcf, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0xc2, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x21, 0xb3, 0x01, 0x00, 0xcf, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0xcf, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x18, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x41, 0x82, 0x88, 0x01, 0x00, 0x00, 0x77, 0x00, 0x41,
+ 0x82, 0x8c, 0x01, 0x00, 0x01, 0x02, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x18, 0x00, 0x00, 0x41,
+ 0x82, 0xdc, 0x01, 0x00, 0xcd, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0xd0, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0xd8, 0x81, 0x22, 0x43,
+ 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xd5, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0xf3, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0xda, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0xf3, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x21, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x83, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00,
+ 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x83, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00,
+ 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x11, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0xec, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xef, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x40, 0x13, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x41, 0x2e, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00, 0xf6, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x08, 0xb1, 0x00, 0x00,
+ 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, 0xf9, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00,
+ 0x08, 0x82, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x17, 0x82, 0x22, 0x44,
+ 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x4a,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00,
+ 0x03, 0x82, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0x90, 0x01, 0x00, 0x05, 0x82, 0x22, 0x4f, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x07, 0x82, 0x22, 0x4e,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00,
+ 0x1f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x1c, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x12, 0x82, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0x90, 0x01, 0x00, 0x14, 0x82, 0x22, 0x44, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x16, 0x82, 0x22, 0x43,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00,
+ 0x1f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x23, 0x82, 0x22, 0x4b, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xb8, 0x80, 0x00, 0xca,
+ 0xa7, 0x33, 0x01, 0x00, 0x41, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x29, 0x82, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00,
+ 0x2b, 0x82, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x30, 0x82, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00,
+ 0x30, 0x82, 0xa2, 0x49, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xfd, 0x93, 0x01, 0x00, 0x33, 0x82, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00,
+ 0x33, 0x82, 0xa2, 0x4a, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xfd, 0x93, 0x01, 0x00, 0x35, 0x82, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00,
+ 0x37, 0x82, 0x42, 0x40, 0xf1, 0x33, 0x00, 0x00, 0x43, 0x81, 0x00, 0x40,
+ 0x68, 0x97, 0x00, 0x00, 0x22, 0x83, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0xbb, 0xb1, 0xb3, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x18, 0xb1, 0x01, 0x00, 0x40, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x4a, 0x82, 0xa2, 0x54,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x51, 0x82, 0xa2, 0x06,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x80, 0x16, 0x2e, 0x06,
+ 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x57, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00,
+ 0x5a, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x60, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00,
+ 0x6c, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0xc4, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x42, 0x99, 0xb3, 0x01, 0x00,
+ 0x78, 0x82, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x80, 0x82, 0x22, 0x48,
+ 0x81, 0x6c, 0x00, 0x00, 0x7a, 0x82, 0x22, 0x4c, 0x81, 0x6c, 0x00, 0x00,
+ 0x85, 0x82, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00, 0x86, 0x82, 0x22, 0x54,
+ 0x81, 0x6c, 0x00, 0x00, 0x88, 0x82, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00,
+ 0x8d, 0x82, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x09, 0xb0, 0x01, 0x00,
+ 0x22, 0x83, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf3, 0x83, 0x01, 0x00,
+ 0x7e, 0x82, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x05, 0xb0, 0x01, 0x00, 0x22, 0x83, 0x22, 0xca, 0x07, 0x14, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0x46, 0xf3, 0x93, 0x00, 0x00, 0x22, 0x83, 0x20, 0x43,
+ 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x80, 0xca, 0x05, 0x30, 0x00, 0x00,
+ 0x22, 0x83, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x48,
+ 0xdb, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00,
+ 0x57, 0x01, 0x00, 0xbc, 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
+ 0xb1, 0xb3, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xca, 0x81, 0x88, 0x01, 0x00, 0x22, 0x83, 0xa2, 0x40,
+ 0x74, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00,
+ 0x8a, 0x82, 0xa8, 0xb1, 0x82, 0x30, 0x00, 0x00, 0x89, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x90, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x9b, 0x82, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a,
+ 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x99, 0x82, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x82, 0x56, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xa0, 0x82, 0xa2, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xab, 0x82, 0x91, 0x81,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00,
+ 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0xa9, 0x82, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xab, 0x82, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41,
+ 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, 0x57, 0x01, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xb2, 0x82, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0xac, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xb6, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40,
+ 0xa3, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x60, 0x15, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0x40, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x40, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42,
+ 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0xbc, 0x82, 0xa0, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xbc, 0x82, 0x00, 0x50,
+ 0x85, 0xc0, 0x00, 0x00, 0x01, 0x83, 0xa2, 0x41, 0x01, 0x7d, 0x00, 0x00,
+ 0xcf, 0x82, 0x22, 0x58, 0x73, 0x7d, 0x00, 0x00, 0x78, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xc7, 0x82, 0xa8, 0xb1, 0x9c, 0x30, 0x00, 0x00,
+ 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5e, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0xc0, 0x00, 0xa6, 0x1e, 0xa4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e,
+ 0x10, 0xc9, 0x00, 0x00, 0xcf, 0x82, 0x33, 0xc4, 0x81, 0x30, 0x00, 0x00,
+ 0xd2, 0x82, 0xa1, 0xad, 0x9d, 0x20, 0x00, 0x00, 0xc6, 0x82, 0x13, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4e, 0x5a, 0x83, 0x01, 0x00,
+ 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x40, 0x05, 0x6c, 0x00, 0x00, 0xdd, 0x82, 0x22, 0xab,
+ 0x80, 0x04, 0x00, 0x00, 0xdb, 0x82, 0xa2, 0x40, 0x01, 0x7d, 0x00, 0x00,
+ 0xdd, 0x82, 0x22, 0x5f, 0x57, 0x7d, 0x00, 0x00, 0x0f, 0x88, 0x00, 0x5f,
+ 0x1f, 0xb4, 0x00, 0x00, 0xdd, 0x82, 0x22, 0x5e, 0x57, 0x7d, 0x00, 0x00,
+ 0x7d, 0x88, 0x00, 0x5f, 0x1f, 0xb4, 0x00, 0x00, 0xe3, 0x82, 0x22, 0x54,
+ 0x73, 0x7d, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xdd, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x1f, 0xb4, 0x01, 0x00, 0xf4, 0x84, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00,
+ 0x92, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe5, 0x82, 0xa2, 0x5f,
+ 0x59, 0x27, 0x00, 0x00, 0xe7, 0x82, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00,
+ 0xee, 0x82, 0xa2, 0x5e, 0x73, 0x7d, 0x00, 0x00, 0xfa, 0x82, 0x22, 0x5c,
+ 0x73, 0x7d, 0x00, 0x00, 0xfb, 0x82, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xe8, 0x82, 0xa8, 0xb1,
+ 0x36, 0x30, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xea, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0x01, 0x00, 0x34, 0x85, 0x17, 0x5f, 0x1f, 0xb4, 0x00, 0x00,
+ 0xfb, 0x82, 0x34, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xef, 0x82, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00,
+ 0xf7, 0x82, 0x52, 0x21, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41,
+ 0x2f, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x1f, 0xb4, 0x01, 0x00,
+ 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x01, 0xf0, 0x01, 0x00, 0x4f, 0x83, 0x00, 0x34, 0x13, 0x84, 0x00, 0x00,
+ 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x1f, 0xb4, 0x01, 0x00, 0xc2, 0x83, 0x00, 0x43, 0x01, 0xf0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xfb, 0x82, 0x33, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4e, 0x5a, 0x7f, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x4e, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00,
+ 0xc6, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0xe4, 0x87, 0xa2, 0x48,
+ 0xfd, 0x7f, 0x00, 0x00, 0x05, 0x83, 0x02, 0xe6, 0x81, 0x32, 0x00, 0x00,
+ 0x06, 0x83, 0x83, 0xe5, 0x81, 0x32, 0x00, 0x00, 0x8e, 0x82, 0x00, 0x42,
+ 0x97, 0xb3, 0x00, 0x00, 0x9e, 0x82, 0x00, 0x42, 0x97, 0xb3, 0x00, 0x00,
+ 0x09, 0x83, 0x22, 0x46, 0xf3, 0x7f, 0x00, 0x00, 0x0c, 0x83, 0xa2, 0x41,
+ 0xf3, 0x7f, 0x00, 0x00, 0xc6, 0x80, 0x00, 0x42, 0x97, 0x33, 0x01, 0x00,
+ 0x0c, 0x83, 0x22, 0x44, 0xf3, 0x7f, 0x00, 0x00, 0x0c, 0x83, 0xa2, 0x41,
+ 0xf3, 0x7f, 0x00, 0x00, 0xc6, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xac, 0x80, 0x32, 0x00, 0x00, 0x11, 0x83, 0x22, 0x5a,
+ 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x0e, 0x83, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcf,
+ 0x11, 0xc9, 0x00, 0x00, 0x17, 0x83, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00,
+ 0x17, 0x83, 0x22, 0x44, 0x93, 0x7f, 0x00, 0x00, 0x13, 0x83, 0x42, 0xa5,
+ 0x80, 0x30, 0x00, 0x00, 0x16, 0x83, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00,
+ 0x38, 0x83, 0x1a, 0x40, 0x93, 0x93, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xdf, 0x80, 0xa2, 0x40, 0x73, 0x7d, 0x00, 0x00,
+ 0xdf, 0x87, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00, 0xd6, 0x87, 0x22, 0x40,
+ 0x65, 0x7d, 0x00, 0x00, 0x00, 0x05, 0xa2, 0x5b, 0x73, 0x7d, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x49, 0x33, 0x7d, 0x00, 0x00, 0x21, 0x83, 0x22, 0x48,
+ 0x33, 0x7d, 0x00, 0x00, 0xff, 0x01, 0x00, 0x99, 0x80, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x98, 0x2f, 0x40,
+ 0x33, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xc1, 0x01, 0x00,
+ 0x01, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x82, 0x00, 0x40,
+ 0x8b, 0xb3, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x1f, 0x90, 0x01, 0x00, 0xc6, 0x82, 0x00, 0x5f, 0x1f, 0x80, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x62, 0xb1, 0x01, 0x00,
+ 0xc6, 0x82, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x2c, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f,
+ 0x1f, 0x7c, 0x00, 0x00, 0x32, 0x83, 0x33, 0x40, 0x1f, 0x30, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x4e, 0x5a, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x4e,
+ 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00, 0xc6, 0x82, 0x13, 0x4e,
+ 0x5a, 0x93, 0x00, 0x00, 0x3a, 0x83, 0xa0, 0xce, 0x81, 0x50, 0x00, 0x00,
+ 0x4d, 0x83, 0xa0, 0xcd, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5,
+ 0x9c, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x81, 0xb0, 0x01, 0x00,
+ 0x4d, 0x83, 0x22, 0xb5, 0x81, 0x14, 0x00, 0x00, 0x80, 0x15, 0x2f, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x3e, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0xb4, 0x65, 0x97, 0x01, 0x00, 0xd0, 0x15, 0x2e, 0x40,
+ 0x69, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x83, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0xa2,
+ 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xb1, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5,
+ 0xf1, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x48, 0x83, 0xa8, 0xa1,
+ 0xe0, 0x31, 0x00, 0x00, 0x17, 0x83, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00,
+ 0x17, 0x83, 0xa2, 0x41, 0x67, 0x6f, 0x00, 0x00, 0x17, 0x83, 0x00, 0x6f,
+ 0xdb, 0x91, 0x00, 0x00, 0x4d, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x17, 0x83, 0x1a, 0x40, 0x93, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x01, 0x6c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09, 0x46, 0xc9, 0x01, 0x00,
+ 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x5c, 0x83, 0xa6, 0x42,
+ 0x13, 0x60, 0x00, 0x00, 0x95, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00,
+ 0x57, 0x83, 0x61, 0x40, 0x81, 0x32, 0x00, 0x00, 0x75, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x58, 0x83, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00,
+ 0xa3, 0x96, 0x71, 0x10, 0x94, 0x30, 0x01, 0x00, 0x5d, 0x83, 0x00, 0x58,
+ 0x1f, 0x90, 0x00, 0x00, 0x87, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00,
+ 0x80, 0x04, 0x00, 0x17, 0x96, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x4a, 0xc1, 0x00, 0x17, 0x96, 0xd8, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xee, 0x07, 0x00, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x68, 0x83, 0x23, 0x4b, 0xe4, 0x6d, 0x00, 0x00,
+ 0x68, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0x90, 0x01, 0x00, 0x22, 0x00, 0x2f, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x6b, 0x83, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x6d, 0x83, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x47, 0xc1, 0x01, 0x00, 0x72, 0x83, 0x22, 0x55,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0xd1, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xfa, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x97, 0xe0, 0x01, 0x00, 0x73, 0x83, 0x00, 0x4b, 0x44, 0xc1, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6,
+ 0x02, 0xcc, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x28, 0xf0,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa2, 0x2a, 0xb0, 0x01, 0x00, 0xc0, 0x28, 0x3c, 0x46,
+ 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x44, 0x95, 0xb0, 0x01, 0x00,
+ 0x7f, 0x83, 0xa2, 0xf8, 0x0e, 0x30, 0x00, 0x00, 0x8f, 0x83, 0x22, 0x41,
+ 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x50, 0x49, 0xc1, 0x01, 0x00,
+ 0x7b, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7c, 0x83, 0xa2, 0xf8,
+ 0x16, 0x6c, 0x00, 0x00, 0x7c, 0x83, 0xa2, 0xf8, 0x10, 0x6c, 0x00, 0x00,
+ 0x7c, 0x83, 0xa2, 0xf0, 0x1a, 0x6c, 0x00, 0x00, 0x8d, 0x83, 0x22, 0x58,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00,
+ 0x84, 0x83, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x88, 0x83, 0xa2, 0xf3,
+ 0x74, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xe6, 0x95, 0x01, 0x00,
+ 0x8d, 0x83, 0x75, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x96, 0xb0, 0x01, 0x00, 0x3f, 0x00, 0x75, 0xf3, 0x0c, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x8b, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x8d, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, 0x95, 0x83, 0x77, 0x41,
+ 0x2d, 0xc3, 0x00, 0x00, 0x93, 0x83, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x62, 0xb1, 0x01, 0x00, 0x91, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x93, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd3, 0x83, 0x77, 0x41,
+ 0x2d, 0xc3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00,
+ 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0xa6, 0x83, 0x22, 0x41,
+ 0x81, 0x6c, 0x00, 0x00, 0x9b, 0x83, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa5, 0x83, 0x22, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x48, 0x96, 0x00, 0x5f, 0x01, 0x10, 0x01, 0x00,
+ 0xa1, 0x83, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00,
+ 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00,
+ 0x01, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0xb5, 0x83, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb5, 0x83, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0xb0, 0x83, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x4b, 0xe1, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xb9, 0x83, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00, 0x69, 0x89, 0x00, 0x45,
+ 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00,
+ 0xbf, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0x34, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x55, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x4b,
+ 0x8f, 0xb0, 0x00, 0x00, 0x57, 0x96, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00,
+ 0xa9, 0x93, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0x00, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x01, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x50,
+ 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xce, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10,
+ 0x62, 0xc9, 0x01, 0x00, 0xd0, 0x83, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x2e, 0x47,
+ 0x97, 0x90, 0x01, 0x00, 0xe6, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00,
+ 0xe4, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xe4, 0x83, 0x23, 0xa2,
+ 0x02, 0x6c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x00,
+ 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00, 0x03, 0x84, 0x00, 0x5c,
+ 0x17, 0x90, 0x00, 0x00, 0xf8, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0xf1, 0x83, 0x22, 0x5f,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0xed, 0x83, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0xee, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x72, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6, 0x80, 0x88, 0x01, 0x00,
+ 0xf5, 0x83, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00, 0xf8, 0x83, 0x00, 0xf2,
+ 0x3a, 0xb0, 0x00, 0x00, 0xf1, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x03, 0x88, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x84, 0x22, 0x4a, 0x2f, 0x7c, 0x00, 0x00,
+ 0x03, 0x84, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00, 0x0a, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2, 0x86, 0x88, 0x01, 0x00,
+ 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00, 0x05, 0x00, 0x00, 0x43,
+ 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42, 0x81, 0xe0, 0x01, 0x00,
+ 0x03, 0x84, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00, 0xf1, 0x84, 0xa2, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x03, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x05, 0x84, 0x69, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3,
+ 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x79, 0x41, 0x47, 0xc3, 0x01, 0x00,
+ 0x04, 0x00, 0xa0, 0xa1, 0x09, 0x6c, 0x00, 0x00, 0x0c, 0x84, 0x22, 0xa1,
+ 0x09, 0x6c, 0x00, 0x00, 0x27, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x08, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0x46, 0x84, 0xa3, 0x92,
+ 0x03, 0x6c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x80, 0xb2, 0x01, 0x00, 0x03, 0x88, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x13, 0x84, 0x22, 0x5c, 0x17, 0x7c, 0x00, 0x00, 0x14, 0x84, 0x00, 0x00,
+ 0x2a, 0xb0, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x08, 0x80, 0xc8, 0x01, 0x00, 0x18, 0x84, 0xa2, 0x43,
+ 0x2f, 0x7c, 0x00, 0x00, 0x58, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x34, 0x84, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01,
+ 0x8c, 0xcc, 0x01, 0x00, 0x58, 0x97, 0x00, 0x4c, 0x03, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00,
+ 0x2c, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x21, 0x84, 0xa8, 0x54, 0x17, 0x10, 0x00, 0x00,
+ 0x34, 0x84, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x2a, 0xc8, 0x01, 0x00, 0x33, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x03, 0xb0, 0x01, 0x00, 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x09, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x34, 0x84, 0x28, 0x54, 0x17, 0x10, 0x00, 0x00,
+ 0x30, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43,
+ 0x61, 0x31, 0x01, 0x00, 0x36, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17,
+ 0x98, 0x88, 0x01, 0x00, 0x39, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x3a, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x41, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0x16, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xe4, 0xb1, 0x01, 0x00,
+ 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x44, 0x84, 0xa2, 0x5f,
+ 0x2f, 0x7c, 0x00, 0x00, 0x80, 0x93, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x03, 0x88, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x48, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0xee, 0x84, 0x00, 0x41, 0x43, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x27, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x4b, 0x84, 0x35, 0x01,
+ 0x86, 0x30, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x54, 0x84, 0x28, 0xb1, 0x30, 0x30, 0x00, 0x00, 0x4c, 0x84, 0x22, 0x4d,
+ 0x75, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00,
+ 0xdb, 0x84, 0xa7, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x43, 0xc3, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00,
+ 0xed, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x54, 0x84, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0x5e, 0x84, 0xa7, 0x40,
+ 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x2c, 0xb0, 0x01, 0x00, 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00,
+ 0x4c, 0x84, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x63, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00,
+ 0x4c, 0x84, 0xa3, 0x0b, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40,
+ 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x03, 0x48, 0x6d, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40, 0x39, 0xb0, 0x01, 0x00,
+ 0x6d, 0x84, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x22, 0x00, 0x00, 0x08,
+ 0x12, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x16, 0x30, 0x6c, 0x00, 0x00,
+ 0xde, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x70, 0x84, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x20, 0x01, 0xe0, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40,
+ 0x37, 0x98, 0x01, 0x00, 0x75, 0x84, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, 0x80, 0x84, 0x82, 0x41,
+ 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x7c, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x79, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xed, 0x94, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x91, 0x84, 0x22, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x23, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x0b, 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x88, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x4c,
+ 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x37, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00, 0x75, 0x84, 0x00, 0x45,
+ 0x1f, 0x80, 0x00, 0x00, 0x93, 0x84, 0xa3, 0x12, 0x36, 0x6c, 0x00, 0x00,
+ 0x94, 0x84, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12,
+ 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x97, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0xbf, 0x84, 0x22, 0x14,
+ 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x14,
+ 0x12, 0xc0, 0x01, 0x00, 0xb7, 0x84, 0xa2, 0x14, 0x36, 0x50, 0x00, 0x00,
+ 0xa7, 0x84, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xa5, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xa2, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x2b, 0x80, 0x01, 0x00, 0x04, 0x00, 0x22, 0x50, 0x2b, 0x6c, 0x00, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0xad, 0x84, 0x23, 0x01,
+ 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00,
+ 0xb8, 0x84, 0x22, 0x1b, 0x02, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0xe0, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0xb4, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb8, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x2a, 0xc0, 0x01, 0x00, 0x75, 0x84, 0xa2, 0x40, 0x25, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x39, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x13,
+ 0x38, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x12, 0xb0, 0x01, 0x00, 0x75, 0x84, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xc6, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19,
+ 0x62, 0xdd, 0x01, 0x00, 0xc3, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xed, 0x94, 0x00, 0x40,
+ 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0xca, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56,
+ 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00,
+ 0xcd, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x17, 0x90, 0x01, 0x00, 0xd0, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00, 0x16, 0x00, 0x20, 0x1d,
+ 0xe4, 0xb1, 0x01, 0x00, 0xd2, 0x84, 0xa3, 0x40, 0x27, 0x6c, 0x00, 0x00,
+ 0xd4, 0x84, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0b,
+ 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13, 0x16, 0x94, 0x01, 0x00,
+ 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40,
+ 0x0f, 0x6c, 0x00, 0x00, 0x03, 0x88, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00,
+ 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00,
+ 0x03, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x03,
+ 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d,
+ 0x61, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, 0xe0, 0x84, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00,
+ 0xe2, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xed, 0x84, 0x22, 0x13,
+ 0x82, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x83, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00,
+ 0xe8, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x62, 0xb1, 0x01, 0x00, 0xea, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xe4, 0x84, 0x00, 0x41, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00,
+ 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41,
+ 0x89, 0x30, 0x01, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00,
+ 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x03, 0x88, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x80, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00,
+ 0x05, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00,
+ 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x05, 0x85, 0x22, 0x41,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x85, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x04, 0x85, 0x22, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00,
+ 0x06, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0x14, 0x85, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x14, 0x85, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0x0f, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x4b, 0xe1, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00,
+ 0x19, 0x85, 0x22, 0x3a, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8e, 0xb0, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x1e, 0x85, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40,
+ 0x01, 0xb0, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x35, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x87, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00,
+ 0x2b, 0x85, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0x55, 0x97, 0x00, 0x4b,
+ 0x95, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x4c, 0x8f, 0xb0, 0x00, 0x00,
+ 0x2d, 0x85, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x43, 0xc1, 0x01, 0x00, 0x2f, 0x85, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6,
+ 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1, 0x2a, 0xc8, 0x01, 0x00,
+ 0x57, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x41,
+ 0x81, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x39, 0x85, 0x64, 0x47, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x3a, 0x85, 0xa8, 0x1b,
+ 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x74, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa0, 0x05,
+ 0x03, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x09, 0x03, 0x6c, 0x00, 0x00,
+ 0x08, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x6b, 0x85, 0x01, 0xfb,
+ 0x08, 0x30, 0x00, 0x00, 0xd5, 0x85, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x14, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00,
+ 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x5c, 0x85, 0x22, 0x41,
+ 0x81, 0x6c, 0x00, 0x00, 0x4b, 0x85, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5b, 0x85, 0x22, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00,
+ 0x51, 0x85, 0xa6, 0x5f, 0x0f, 0x00, 0x00, 0x00, 0x2b, 0x94, 0x00, 0x40,
+ 0x05, 0x30, 0x01, 0x00, 0x0a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x58, 0x85, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x26, 0x96, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, 0x08, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0x69, 0x85, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x69, 0x85, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0x66, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0x6d, 0x85, 0x21, 0x04,
+ 0x80, 0x20, 0x00, 0x00, 0x6e, 0x85, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00,
+ 0xa1, 0x88, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00, 0x9c, 0x85, 0x00, 0x43,
+ 0x81, 0xb0, 0x00, 0x00, 0xa0, 0x85, 0x00, 0xfb, 0x22, 0xb0, 0x00, 0x00,
+ 0xa1, 0x88, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x69, 0x89, 0x00, 0x4e,
+ 0x8f, 0xb0, 0x00, 0x00, 0x91, 0x85, 0x00, 0x5a, 0x8f, 0xb0, 0x00, 0x00,
+ 0x76, 0x85, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x53,
+ 0x81, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x56, 0x81, 0xb0, 0x00, 0x00,
+ 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x3c, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0a,
+ 0x8a, 0x30, 0x01, 0x00, 0x3d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x11, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0xf2,
+ 0x8a, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x69, 0x89, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x84, 0x85, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x83, 0x85, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x69, 0x89, 0x00, 0x53, 0x8f, 0xb0, 0x00, 0x00, 0x69, 0x89, 0x00, 0x54,
+ 0x8f, 0xb0, 0x00, 0x00, 0x8d, 0x85, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x87, 0x85, 0xa2, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x69, 0x89, 0x00, 0x5d,
+ 0x8f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x80, 0xd0, 0x01, 0x00, 0x8b, 0x85, 0xa0, 0x91,
+ 0x81, 0x6c, 0x00, 0x00, 0x69, 0x89, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00,
+ 0x25, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x85, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00,
+ 0x69, 0x89, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x3c, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0a,
+ 0x8a, 0x30, 0x01, 0x00, 0x3d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0xf2, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x69, 0x89, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00, 0xa1, 0x88, 0xa0, 0x42,
+ 0x83, 0x6c, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x54, 0x81, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x23, 0x40,
+ 0x0f, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x20, 0xaa, 0x0f, 0x6c, 0x00, 0x00,
+ 0x09, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07,
+ 0x16, 0x88, 0x01, 0x00, 0xae, 0x85, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x1c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xed, 0x87, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0xc0, 0x85, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00,
+ 0xbb, 0x85, 0xa2, 0x54, 0xfd, 0x7f, 0x00, 0x00, 0xb3, 0x85, 0x22, 0x55,
+ 0xfd, 0x7f, 0x00, 0x00, 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0xaa, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x53,
+ 0xfd, 0x7f, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b,
+ 0x80, 0xf4, 0x01, 0x00, 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0xbb, 0x85, 0x22, 0x43, 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b,
+ 0x80, 0x88, 0x01, 0x00, 0xaa, 0x85, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00,
+ 0x7c, 0x96, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbc, 0x85, 0x46, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xbf, 0x85, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00,
+ 0xb1, 0x85, 0x1e, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41,
+ 0x31, 0xc3, 0x01, 0x00, 0x79, 0x94, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00,
+ 0xc4, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00,
+ 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c, 0xe0, 0x99, 0x01, 0x00,
+ 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0xcc, 0x85, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x91, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xa1, 0x88, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x14, 0xb0, 0x01, 0x00, 0xe0, 0x85, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0x87, 0x6c, 0x00, 0x00, 0xdc, 0x85, 0x22, 0x40,
+ 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x1f, 0x90, 0x01, 0x00,
+ 0xde, 0x85, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x1f, 0x90, 0x01, 0x00, 0xe0, 0x85, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x09, 0x7c, 0x00, 0x00, 0xe1, 0x85, 0x66, 0x1b, 0x2c, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x76, 0x41,
+ 0x41, 0xc3, 0x01, 0x00, 0x13, 0x86, 0x23, 0x92, 0x15, 0x6c, 0x00, 0x00,
+ 0x13, 0x86, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x19, 0x86, 0x22, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x0a,
+ 0x24, 0xc8, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00,
+ 0x11, 0x86, 0x22, 0x08, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa3, 0xc1, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x12, 0x24, 0xcc, 0x01, 0x00,
+ 0xea, 0x85, 0xaa, 0x41, 0x27, 0x40, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x49,
+ 0x27, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00,
+ 0x0b, 0x86, 0x26, 0x40, 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0,
+ 0xa2, 0xc9, 0x01, 0x00, 0xf8, 0x85, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00,
+ 0x04, 0x86, 0x00, 0x41, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xfd, 0x85, 0xa2, 0x44,
+ 0x23, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x86, 0xa8, 0x42,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa3, 0xc1, 0x01, 0x00, 0xf6, 0x85, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x0b, 0x86, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x08, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00,
+ 0x17, 0x00, 0x00, 0xd0, 0x2a, 0xc8, 0x01, 0x00, 0x24, 0x86, 0x00, 0x17,
+ 0x10, 0xb0, 0x00, 0x00, 0x04, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x19, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb9, 0x94, 0x00, 0x92,
+ 0x25, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x31, 0xb0, 0x01, 0x00,
+ 0x0b, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00,
+ 0x8a, 0x30, 0x01, 0x00, 0x19, 0x86, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x24, 0x86, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6,
+ 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x78, 0x98, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00, 0x04, 0x00, 0x1c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa0, 0x9f,
+ 0x13, 0x6c, 0x00, 0x00, 0x23, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0x27, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xed, 0x87, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01,
+ 0x80, 0xce, 0x01, 0x00, 0x38, 0x86, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x2d, 0x86, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0x2d, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x2d, 0x86, 0xa3, 0x07,
+ 0x03, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x30, 0x86, 0xa3, 0x40, 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01,
+ 0xf0, 0xcd, 0x01, 0x00, 0x32, 0x86, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x0e, 0xcc, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x36, 0x86, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x03, 0x48, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x08, 0xb0, 0x01, 0x00,
+ 0xa0, 0x01, 0x2d, 0x40, 0x00, 0xc0, 0x01, 0x00, 0x19, 0x87, 0x22, 0x0f,
+ 0x42, 0x05, 0x00, 0x00, 0x4b, 0x86, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x46, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x43, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x4b, 0x86, 0x22, 0x07,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0xc0, 0x06, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x54, 0x29, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x14, 0x80, 0xce, 0x01, 0x00,
+ 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x42, 0x00, 0x00, 0x03,
+ 0x0a, 0xc8, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00,
+ 0x10, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08,
+ 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0xfe, 0x7f, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa2,
+ 0x86, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00,
+ 0x79, 0x86, 0x22, 0x01, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44,
+ 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x66, 0x86, 0xa3, 0x07,
+ 0x02, 0x6c, 0x00, 0x00, 0x67, 0x86, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x68, 0x07, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x02, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00,
+ 0x73, 0x86, 0x22, 0x40, 0x03, 0x6c, 0x00, 0x00, 0x73, 0x86, 0x22, 0x42,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x99, 0x86, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x70, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x75, 0x86, 0xa8, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x99, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44,
+ 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x7e, 0x86, 0xa3, 0x12,
+ 0x0e, 0x6c, 0x00, 0x00, 0x7f, 0x86, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x12, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d,
+ 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00,
+ 0x14, 0x99, 0x00, 0x08, 0x98, 0x30, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08,
+ 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x87, 0x86, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0xb9, 0x86, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00,
+ 0x8d, 0x86, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x92, 0x86, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x25, 0x98, 0x01, 0x00, 0x94, 0x86, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x99, 0x86, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x95, 0x86, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0xb9, 0x86, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0xb8, 0x86, 0xa2, 0x0d,
+ 0x0e, 0x50, 0x00, 0x00, 0xa5, 0x86, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xa3, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xa0, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0xab, 0x86, 0xa2, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x60, 0x86, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x60, 0x86, 0x23, 0x07,
+ 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0xb5, 0x86, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x60, 0x86, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0x60, 0x86, 0x00, 0x0d,
+ 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x2e, 0x14, 0x0a, 0xd0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x05, 0x48, 0xcd, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa4, 0x86, 0x06, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00, 0x0c, 0x00, 0x2a, 0xf2,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc1, 0x86, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6, 0x80, 0xce, 0x01, 0x00,
+ 0xc5, 0x86, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x43, 0xc1, 0x01, 0x00, 0xc7, 0x86, 0x22, 0x0b, 0xed, 0x6d, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa1,
+ 0x46, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0xfa, 0x94, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45,
+ 0x95, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xb0, 0x01, 0x00, 0xd1, 0x86, 0x22, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00,
+ 0xd1, 0x86, 0xa0, 0x46, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xc0, 0x01, 0x00, 0xd5, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2,
+ 0x42, 0x31, 0x00, 0x00, 0xd8, 0x86, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0xa2, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x82, 0xb0, 0x01, 0x00, 0xdb, 0x86, 0xa0, 0x41,
+ 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00,
+ 0xe0, 0x86, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xe0, 0x86, 0xa0, 0x43,
+ 0x89, 0x6c, 0x00, 0x00, 0xe0, 0x86, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00,
+ 0xe0, 0x86, 0xa0, 0x41, 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00,
+ 0xd8, 0x86, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0xed, 0x86, 0x22, 0x48,
+ 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x48, 0x90, 0x88, 0x01, 0x00, 0xe7, 0x86, 0x90, 0x48,
+ 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x93, 0xa4, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x43, 0x80, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa2, 0x80, 0xc0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40,
+ 0x42, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x14, 0x99, 0x00, 0x17,
+ 0x98, 0x30, 0x01, 0x00, 0xff, 0x07, 0x00, 0x17, 0x7e, 0x89, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x14, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05,
+ 0xe0, 0xcd, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0xf7, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x02, 0x87, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44,
+ 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00,
+ 0x01, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xfe, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x05, 0x87, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x06, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x85, 0x87, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00,
+ 0x0d, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x09, 0x87, 0xa0, 0x07, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00,
+ 0x0d, 0x87, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x17, 0x87, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x14, 0x87, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, 0x85, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x21, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x21, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x1e, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x26, 0x87, 0x22, 0x07,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x2b, 0x87, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x18,
+ 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x30, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x52,
+ 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x15, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x3f, 0x87, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00,
+ 0x40, 0x87, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12,
+ 0x1a, 0xb0, 0x01, 0x00, 0x14, 0x99, 0x00, 0x08, 0x98, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x47, 0x87, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x79, 0x87, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00,
+ 0x4d, 0x87, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x52, 0x87, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x25, 0x98, 0x01, 0x00, 0x54, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x59, 0x87, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x55, 0x87, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x78, 0x87, 0xa2, 0x0d,
+ 0x0e, 0x50, 0x00, 0x00, 0x65, 0x87, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x63, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x60, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03,
+ 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x6b, 0x87, 0xa2, 0x5f,
+ 0x0f, 0x7c, 0x00, 0x00, 0x39, 0x87, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x39, 0x87, 0x23, 0x07,
+ 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x75, 0x87, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x39, 0x87, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0x39, 0x87, 0x00, 0x0d,
+ 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x83, 0x87, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x83, 0x87, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x80, 0x87, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x17, 0x10, 0xb0, 0x01, 0x00, 0x85, 0x87, 0x00, 0x40,
+ 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x9f, 0x13, 0x6c, 0x00, 0x00,
+ 0x8c, 0x87, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88,
+ 0x1c, 0xcc, 0x01, 0x00, 0x27, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8d, 0x98, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x78, 0x98, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x03, 0x88, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00,
+ 0x98, 0x87, 0x22, 0x50, 0x01, 0x6c, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x12, 0x95, 0x00, 0x07,
+ 0x16, 0x30, 0x01, 0x00, 0xa3, 0x87, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00,
+ 0x9e, 0x87, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xa2, 0x87, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x0e, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xb0, 0x87, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb0, 0x87, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00,
+ 0xad, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00,
+ 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00,
+ 0xa1, 0x88, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x43,
+ 0x19, 0x80, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x8e, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x90, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x43, 0x8f, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0xa3, 0x43, 0x91, 0x6c, 0x00, 0x00, 0xc1, 0x87, 0x22, 0x48,
+ 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xc1, 0x87, 0x1f, 0xf0,
+ 0x24, 0x6c, 0x00, 0x00, 0xc0, 0x87, 0x23, 0x41, 0x8f, 0x6c, 0x00, 0x00,
+ 0xa1, 0x88, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x48,
+ 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0xc6, 0x87, 0x22, 0x0a,
+ 0x90, 0x40, 0x00, 0x00, 0x58, 0x98, 0x00, 0x40, 0x91, 0x30, 0x01, 0x00,
+ 0xa1, 0x88, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0xb0, 0x00, 0x2d, 0x45,
+ 0x81, 0xb0, 0x01, 0x00, 0xd2, 0x87, 0x22, 0xf0, 0x2c, 0x30, 0x00, 0x00,
+ 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf3,
+ 0x82, 0xe0, 0x01, 0x00, 0xcc, 0x87, 0xa3, 0x41, 0x2c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0xf0,
+ 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x82, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00, 0xa1, 0x88, 0x20, 0x4c,
+ 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41, 0x98, 0xe8, 0x01, 0x00,
+ 0xa1, 0x88, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00, 0xed, 0x87, 0x22, 0x0a,
+ 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00,
+ 0xed, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x49,
+ 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00,
+ 0xda, 0x87, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x13, 0x80, 0x00, 0x40,
+ 0x80, 0xdc, 0x01, 0x00, 0xdb, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0xdb, 0x87, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0xb1, 0x01, 0x00,
+ 0xdd, 0x87, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00, 0xe1, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x1a, 0x83, 0x22, 0x40, 0x57, 0x7d, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00, 0xe1, 0x87, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x01, 0x83, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00, 0xe7, 0x87, 0x22, 0x46,
+ 0xf3, 0x7f, 0x00, 0x00, 0xe7, 0x87, 0xa2, 0x41, 0xf3, 0x7f, 0x00, 0x00,
+ 0xc6, 0x80, 0x00, 0x42, 0x97, 0x33, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb,
+ 0x81, 0xc8, 0x01, 0x00, 0xea, 0x87, 0x22, 0x40, 0xf2, 0x7f, 0x00, 0x00,
+ 0xc6, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00, 0xec, 0x87, 0x22, 0x40,
+ 0x73, 0x7d, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00,
+ 0xe4, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x87, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xf4, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xf1, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x2e, 0x94, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0xf5, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x2e, 0x94, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00,
+ 0xff, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xff, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xfc, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x3e, 0x94, 0x22, 0x02,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x88, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x3e, 0x94, 0x1a, 0x02,
+ 0x68, 0x97, 0x00, 0x00, 0x0a, 0x88, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x0a, 0x88, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x07, 0x88, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x2f, 0x83, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x0b, 0x88, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40,
+ 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00,
+ 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40,
+ 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x0e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0c, 0x55, 0x6f, 0x00, 0x00,
+ 0x29, 0x00, 0x00, 0x40, 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x12, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07,
+ 0x16, 0x88, 0x01, 0x00, 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x23, 0xb0, 0x01, 0x00, 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x43, 0x88, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x22, 0x88, 0x60, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x84, 0x89, 0x01, 0x00, 0x2b, 0x88, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00,
+ 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x60, 0x88, 0x70, 0xf0, 0x18, 0x30, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x0c, 0x82, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x41,
+ 0x0e, 0x6c, 0x00, 0x00, 0x43, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x3a, 0x88, 0xa0, 0x48,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x34, 0x88, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x31, 0x88, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x60, 0x88, 0x00, 0xf8,
+ 0x18, 0x30, 0x01, 0x00, 0x35, 0x88, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x34, 0x94, 0x01, 0x00, 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x1a, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a,
+ 0x62, 0xdd, 0x01, 0x00, 0x3e, 0x88, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x35, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00,
+ 0x4f, 0x88, 0x22, 0x41, 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xc0, 0x01, 0x00, 0x4b, 0x88, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x12, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x1f, 0x88, 0x00, 0x41,
+ 0x17, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00,
+ 0x1f, 0x88, 0x83, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x17, 0xb0, 0x01, 0x00, 0x1f, 0x88, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00,
+ 0x5a, 0x88, 0x23, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00,
+ 0x57, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00,
+ 0x54, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x60, 0x88, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00, 0x58, 0x88, 0xa2, 0x41,
+ 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00,
+ 0x5d, 0x88, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xb0, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00,
+ 0x56, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x0c,
+ 0x7e, 0x89, 0x01, 0x00, 0x79, 0x88, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00,
+ 0x6c, 0x88, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0c, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x40,
+ 0x62, 0x99, 0x01, 0x00, 0x6c, 0x88, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x68, 0x88, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x74, 0x88, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0x2a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0c,
+ 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00,
+ 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00,
+ 0x6d, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x88, 0x22, 0x49,
+ 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54,
+ 0x77, 0x7d, 0x00, 0x00, 0x74, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00,
+ 0x79, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55,
+ 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00,
+ 0x2f, 0x83, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x81, 0x88, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x84, 0x88, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xab, 0x27, 0xb3, 0x01, 0x00,
+ 0x2f, 0x83, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x2f, 0x83, 0x22, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0x2f, 0x83, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00,
+ 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x90, 0x88, 0x22, 0x40,
+ 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x40, 0x05, 0x00, 0x40,
+ 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x55, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a,
+ 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a,
+ 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xf2, 0x0e, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02,
+ 0x80, 0x32, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0xab, 0x88, 0x22, 0x50,
+ 0x81, 0x6c, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x04,
+ 0x8a, 0x14, 0x01, 0x00, 0x04, 0x00, 0x20, 0x48, 0x09, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x20, 0x57, 0x81, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, 0xb1, 0x88, 0x00, 0x4b,
+ 0x10, 0xc9, 0x00, 0x00, 0xe1, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x16, 0x8c, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x99, 0x8c, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xc8, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8e, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdc, 0x8c, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x95, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x95, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x95, 0x8d, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xb5, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x0c, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8e, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x21, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x2c, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x3e, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x2d, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x40, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x34, 0x8e, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x93, 0x8d, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x93, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x93, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x42, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x42, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x42, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x49, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x4b, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x58, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xbe, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xc6, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xda, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x93, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xc2, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x02, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf2,
+ 0x0e, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0x07, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x08, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x47, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x04,
+ 0x8a, 0x14, 0x01, 0x00, 0x04, 0x00, 0x20, 0x4e, 0x09, 0x6c, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x47, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x06, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, 0x7a, 0x89, 0x00, 0x4b,
+ 0x10, 0xc9, 0x00, 0x00, 0xf6, 0x8e, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x36, 0x8f, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x47, 0x8f, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6a, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x64, 0x8f, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x71, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x3a, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x3a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x3a, 0x8f, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00,
+ 0x3a, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4d,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x45, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x47, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x64, 0x8f, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x81, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x81, 0x90, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xc6, 0x8b, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x81, 0x90, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0xac, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xac, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xbb, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xbb, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x40,
+ 0x09, 0xb0, 0x00, 0x00, 0x4e, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x40, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x4e, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x57, 0x91, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x57, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x40, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x40, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x45, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xab, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xab, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xc6, 0x8b, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x8e, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x5a, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x5a, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x5a, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x77, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x96, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x96, 0x92, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x96, 0x92, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xbf, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xbd, 0x92, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xbf, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xbd, 0x92, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x67, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x74, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x74, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x74, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x62, 0x90, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7d, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x93, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x93, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x0f, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x53, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x16, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x16, 0x93, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x44, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x44, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x44, 0x93, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x47, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x67, 0x93, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x47, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x67, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x93, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x93, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x71, 0x8f, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x71, 0x8f, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0xf8, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00,
+ 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd8, 0x8b, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xd8, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd5, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x1a, 0x85, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0xd9, 0x8b, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00,
+ 0x1a, 0x85, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00,
+ 0x05, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, 0xf8, 0x87, 0x00, 0x04,
+ 0xe6, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb1, 0x01, 0x00, 0x78, 0x98, 0x00, 0x06,
+ 0x07, 0x40, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b,
+ 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34,
+ 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00,
+ 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x05, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0x0d, 0x8c, 0x20, 0x4b,
+ 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x0a, 0x8c, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x14, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x10, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x09, 0x97, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x14, 0x80, 0x00, 0x03,
+ 0x98, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x98, 0x6c, 0x00, 0x00,
+ 0x1b, 0x8c, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1e, 0x8c, 0xa2, 0x4c,
+ 0xfd, 0x7f, 0x00, 0x00, 0x1f, 0x8c, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00,
+ 0x20, 0x8c, 0x20, 0xf0, 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x56, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0x80, 0xcc, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x43,
+ 0x81, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x2b, 0x8c, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x46,
+ 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x43,
+ 0xf0, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x62, 0xb1, 0x01, 0x00, 0x34, 0x8c, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x86, 0xe4, 0x01, 0x00, 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x3c, 0x8c, 0x22, 0x43,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00,
+ 0x3f, 0x8c, 0x22, 0x44, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00,
+ 0x68, 0x01, 0x20, 0xa2, 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x43, 0x8c, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x48, 0x8c, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x5c, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf2,
+ 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x8c, 0xa2, 0x49,
+ 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x59, 0x8c, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0x86, 0x00, 0x2f, 0x49,
+ 0x19, 0x80, 0x01, 0x00, 0x59, 0x8c, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xe7, 0x91, 0x01, 0x00, 0x5c, 0x8c, 0xa2, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x60, 0x8c, 0x00, 0x40,
+ 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46, 0x19, 0x80, 0x01, 0x00,
+ 0x60, 0x8c, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe7, 0x91, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x4e, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00,
+ 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x0c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x16, 0x88, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00, 0x90, 0x8c, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x76, 0x8c, 0x22, 0x0a, 0x16, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x15, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00, 0x75, 0x8c, 0xa0, 0x43,
+ 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x13, 0xb0, 0x01, 0x00,
+ 0x6b, 0x8c, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00, 0x90, 0x8c, 0x22, 0x0a,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x08, 0x12, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x15, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x90, 0x8c, 0x22, 0x41,
+ 0x15, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00,
+ 0x83, 0x8c, 0xa0, 0x43, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x06, 0x10, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0x4e, 0x97, 0x00, 0x47,
+ 0x61, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x2b, 0x94, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x8c, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x7f, 0x8c, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x80, 0x97, 0x00, 0x51,
+ 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3,
+ 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00,
+ 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0x9d, 0x8c, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3,
+ 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00,
+ 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00,
+ 0xa4, 0x8c, 0x22, 0x45, 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0,
+ 0x8c, 0x6c, 0x00, 0x00, 0x90, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf3,
+ 0x84, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf3, 0x84, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3e, 0x43, 0x85, 0xe0, 0x01, 0x00, 0xab, 0x8c, 0x22, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x02, 0x30, 0x00, 0x00, 0xb9, 0x8c, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00,
+ 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x58, 0x98, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0xc2, 0x8c, 0xa2, 0x44,
+ 0x81, 0x6c, 0x00, 0x00, 0xc0, 0x8c, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xb6, 0x95, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xea, 0x8c, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0xc2, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xea, 0x8c, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01,
+ 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x8f, 0x95, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x9d, 0x8c, 0x22, 0x4a,
+ 0x80, 0x32, 0x00, 0x00, 0xce, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3,
+ 0x94, 0x30, 0x01, 0x00, 0x04, 0x00, 0x20, 0x43, 0x97, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00, 0x00, 0x8c, 0x01, 0x00,
+ 0xdd, 0x8b, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0, 0x8c, 0x6c, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00,
+ 0xdc, 0x8c, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00, 0xe1, 0x8c, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xb6, 0x95, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00,
+ 0xe5, 0x8c, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe5, 0x8c, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x50, 0x00, 0x2d, 0x10,
+ 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00,
+ 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x2d, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x14, 0xb0, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x46,
+ 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40, 0x10, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x81, 0xd0, 0x01, 0x00, 0x12, 0x97, 0x00, 0x40, 0xe4, 0x31, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00, 0xf6, 0x8c, 0xa8, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0x08, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x10, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x8d, 0x82, 0x41,
+ 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x01, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xfe, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00,
+ 0x0c, 0x8d, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x08, 0x8d, 0xa3, 0x01,
+ 0x0c, 0x6c, 0x00, 0x00, 0x09, 0x8d, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, 0x0b, 0x8d, 0x20, 0x02,
+ 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x01, 0x00,
+ 0x0f, 0x8d, 0x00, 0x02, 0xe0, 0xb1, 0x00, 0x00, 0x0e, 0x8d, 0xa3, 0x01,
+ 0x0c, 0x6c, 0x00, 0x00, 0x0f, 0x8d, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x02,
+ 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x14, 0x8d, 0xa8, 0x13,
+ 0xe0, 0x31, 0x00, 0x00, 0x51, 0x8d, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00, 0x3c, 0x8d, 0xa2, 0x02,
+ 0x02, 0x50, 0x00, 0x00, 0x22, 0x8d, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x21, 0x8d, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x1d, 0x8d, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x2d, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00,
+ 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2f, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x3e, 0x8d, 0x22, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x8d, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x2f, 0x8d, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x2c, 0x8d, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x38, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x94, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2d, 0xf0, 0x96, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x4a, 0xf1, 0xb1, 0x01, 0x00,
+ 0x44, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x39, 0x8d, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00,
+ 0x3e, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x38, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x4c, 0x8d, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x33, 0xc0, 0x01, 0x00, 0x4a, 0x8d, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x8f, 0x0d,
+ 0x42, 0x31, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5c, 0xe1, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xf0,
+ 0x6a, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x10, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x37, 0x98, 0x01, 0x00, 0xfa, 0x8c, 0x00, 0xa1, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0xfa, 0x8c, 0x00, 0x02,
+ 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01,
+ 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0x58, 0x8d, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02,
+ 0x02, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, 0x0c, 0x6c, 0x00, 0x00,
+ 0x37, 0x00, 0x2d, 0x46, 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3,
+ 0x80, 0xf4, 0x01, 0x00, 0x57, 0x8d, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00,
+ 0x5e, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x5b, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x0d, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x65, 0x8d, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x62, 0x8d, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x60, 0x01, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00,
+ 0x6a, 0x8d, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00,
+ 0x32, 0x00, 0x00, 0xa6, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x2a, 0x94, 0x01, 0x00, 0x6d, 0x8d, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00, 0x72, 0x8d, 0x28, 0x40,
+ 0x05, 0x30, 0x00, 0x00, 0x6e, 0x8d, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0x75, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x62, 0xb1, 0x01, 0x00, 0x80, 0x8d, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x72, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00,
+ 0x92, 0xb0, 0x01, 0x00, 0x7d, 0x8d, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x48,
+ 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0xf8, 0x00, 0x30, 0x01, 0x00, 0x7a, 0x8d, 0xa2, 0x41,
+ 0x3b, 0x50, 0x00, 0x00, 0x81, 0x8d, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x1e, 0x00, 0x8c, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x81, 0x8d, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x1d, 0x47, 0x19, 0x80, 0x01, 0x00, 0x84, 0x8d, 0x22, 0x5f,
+ 0x01, 0x6c, 0x00, 0x00, 0x87, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xa7, 0x88, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x8b, 0x8d, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x8b, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x88, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x8b, 0x8d, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x07, 0x94, 0x89, 0x01, 0x00, 0x91, 0x8d, 0x85, 0xca,
+ 0x94, 0x30, 0x00, 0x00, 0x87, 0x98, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00, 0xb4, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x80, 0x97, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0x80, 0x01, 0x00, 0xdd, 0x8b, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00,
+ 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x98, 0x8d, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x12, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x9e, 0x8d, 0x90, 0x4c,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0xa0, 0x8d, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00,
+ 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2,
+ 0x80, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xaa, 0x8d, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xae, 0x8d, 0x45, 0x48,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00,
+ 0xb4, 0x8d, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0xaf, 0x8d, 0x22, 0x48,
+ 0x77, 0x7d, 0x00, 0x00, 0xc3, 0x94, 0x1d, 0x08, 0x00, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x8b, 0x1d, 0x47,
+ 0x19, 0x80, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x84, 0xc8, 0x01, 0x00, 0xba, 0x8d, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf3, 0x9e, 0x06, 0x00, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x82, 0xcc, 0x01, 0x00, 0xc8, 0x8d, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00,
+ 0xdd, 0x8b, 0x22, 0x44, 0x83, 0x70, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x24, 0x6c, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43,
+ 0xe7, 0xe1, 0x01, 0x00, 0xdd, 0x8b, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00,
+ 0x87, 0x98, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00, 0xa7, 0x88, 0x23, 0x41,
+ 0x83, 0x6c, 0x00, 0x00, 0xa7, 0x88, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42,
+ 0xe6, 0x6d, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x00, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x00, 0xbe, 0x06, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x4e, 0x97, 0x00, 0x47, 0x61, 0x31, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x8e, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0,
+ 0x14, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xa5, 0x8c, 0xa2, 0x40, 0x8f, 0x7c, 0x00, 0x00, 0xdb, 0x8d, 0x22, 0x47,
+ 0x8f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x48, 0x19, 0x7c, 0x00, 0x00,
+ 0xa5, 0x8c, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, 0x04, 0x00, 0x22, 0x46,
+ 0x8f, 0x7c, 0x00, 0x00, 0x5d, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x5d,
+ 0x05, 0xb4, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf3, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x8e, 0xb0, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x47,
+ 0x7e, 0x89, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x86, 0xdc, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x8c, 0x93, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xef, 0x8d, 0xa2, 0x50, 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0x47, 0x7e, 0x89, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0xf4, 0x8d, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00,
+ 0xdd, 0x8b, 0x22, 0x47, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47,
+ 0x0c, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8f, 0x84, 0x01, 0x00,
+ 0x09, 0x8e, 0x22, 0x47, 0x0c, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43,
+ 0x81, 0xe0, 0x01, 0x00, 0x09, 0x8e, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x02, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xff, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x02, 0x8e, 0x42, 0x40,
+ 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x07, 0x8e, 0x23, 0x41,
+ 0x0d, 0x6c, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x87, 0x98, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xa7, 0x88, 0x00, 0x48,
+ 0x81, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x84, 0xb0, 0x01, 0x00,
+ 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf2,
+ 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x1a, 0x8e, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x1a, 0x8e, 0xa3, 0x40, 0x82, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00, 0x1c, 0x8e, 0x20, 0x4c,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00,
+ 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x42,
+ 0xe6, 0xb1, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x09, 0x97, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x80, 0xc0, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0,
+ 0x80, 0x6c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x8b, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2,
+ 0x96, 0xcc, 0x01, 0x00, 0xdd, 0x8b, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0x55, 0x97, 0x00, 0x46,
+ 0x95, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdd, 0x8b, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xcc, 0x01, 0x00,
+ 0xdd, 0x8b, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4a,
+ 0x81, 0x30, 0x01, 0x00, 0x55, 0x97, 0x00, 0x47, 0x95, 0x30, 0x01, 0x00,
+ 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2b, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0xdd, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46,
+ 0x19, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x46, 0x8e, 0x90, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xdd, 0x8b, 0x22, 0x40,
+ 0xe5, 0x6d, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x41, 0xe5, 0xc1, 0x00, 0x00,
+ 0x09, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x56, 0x8e, 0x80, 0xf3,
+ 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x81, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3,
+ 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6e, 0x8e, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x84, 0xcc, 0x01, 0x00,
+ 0x66, 0x8e, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x68, 0x8e, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x69, 0x8e, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x62, 0xb1, 0x01, 0x00, 0x6b, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00,
+ 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0,
+ 0x28, 0xb0, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf3, 0x84, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf3, 0x84, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3e, 0x43,
+ 0x85, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00,
+ 0xe0, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2b, 0xb0, 0x01, 0x00, 0x64, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x16, 0xc0, 0x01, 0x00, 0x7f, 0x8e, 0xa0, 0x14,
+ 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf8, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00,
+ 0x10, 0x50, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x88, 0x8e, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00,
+ 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x88, 0x8e, 0xa4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x01, 0x00, 0x6e, 0x43, 0x86, 0x98, 0x01, 0x00, 0xa8, 0x97, 0x00, 0x30,
+ 0x81, 0x30, 0x01, 0x00, 0x8c, 0x8e, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x93, 0x8e, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0x17, 0xc0, 0x01, 0x00, 0x92, 0x8e, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x41, 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x99, 0x8e, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00,
+ 0xa0, 0x00, 0x20, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46,
+ 0x19, 0x10, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50,
+ 0x17, 0xf0, 0x01, 0x00, 0x9e, 0x8e, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xa0, 0x8e, 0x22, 0x43,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0xaa, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xae, 0x8e, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0xaf, 0x8e, 0xa8, 0x40,
+ 0x05, 0x30, 0x00, 0x00, 0x35, 0x00, 0x1d, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x63, 0xf3, 0x84, 0xc8, 0x01, 0x00, 0xb5, 0x8e, 0xa0, 0x43,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf3,
+ 0x9e, 0x06, 0x00, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45, 0xe7, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0xe7, 0x91, 0x01, 0x00, 0x80, 0x97, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3,
+ 0x94, 0x30, 0x01, 0x00, 0x5d, 0x8e, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00,
+ 0xce, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00,
+ 0x97, 0x8c, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xce, 0x8c, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x90, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc8, 0x8c, 0x22, 0x06,
+ 0x90, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00,
+ 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50,
+ 0xe7, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00,
+ 0xd5, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x89, 0x93, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd7, 0x8e, 0x42, 0x05,
+ 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0xc8, 0x8c, 0x1a, 0x5d, 0x69, 0x93, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00,
+ 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x6b, 0xfb,
+ 0x84, 0xc8, 0x01, 0x00, 0xe4, 0x8e, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00,
+ 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x12, 0xc8, 0x01, 0x00,
+ 0xe7, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x8c, 0x93, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xea, 0x8e, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d,
+ 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf3, 0x9e, 0x06, 0x00, 0x00, 0x11, 0x00, 0x63, 0xf3,
+ 0x82, 0xcc, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x41, 0x80, 0x32, 0x00, 0x00,
+ 0xbf, 0x8d, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xcd, 0x8d, 0x00, 0xf0,
+ 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xf7, 0x8e, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0xfc, 0x8e, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x27, 0x83, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf6, 0x8e, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x75, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xfe, 0x8e, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00,
+ 0xa3, 0x96, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x08, 0x8f, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0x05, 0x8f, 0x00, 0x50,
+ 0x43, 0xc1, 0x00, 0x00, 0x14, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00,
+ 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0x12, 0x8f, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x1a, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00,
+ 0x1e, 0x8f, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x62, 0xb1, 0x01, 0x00, 0x22, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x27, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x25, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96,
+ 0x97, 0xb0, 0x01, 0x00, 0x2d, 0x8f, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00,
+ 0x2d, 0x8f, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0x27, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x28, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x09, 0x97, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x34, 0x8f, 0x22, 0xf3,
+ 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00,
+ 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x97, 0x00, 0x52,
+ 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0x80, 0x97, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00,
+ 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0xff, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0xc6, 0x8b, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, 0x24, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x42, 0x8f, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00,
+ 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0x4e, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x4e, 0x8f, 0xa2, 0x16,
+ 0x80, 0x32, 0x00, 0x00, 0xed, 0x87, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x23, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, 0x51, 0x8f, 0x83, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2a, 0xc0, 0x01, 0x00, 0x58, 0x97, 0x00, 0x08,
+ 0x80, 0x30, 0x01, 0x00, 0x55, 0x8f, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00,
+ 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x98, 0x93, 0x00, 0x40,
+ 0x8d, 0x30, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x5d, 0x8f, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x5a, 0x8f, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x61, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00,
+ 0x69, 0x8f, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00,
+ 0x6a, 0x8f, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f,
+ 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0,
+ 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0xdc, 0x8f, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44,
+ 0x19, 0x90, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x47, 0xe7, 0x7d, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x84, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x84, 0x8f, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x80, 0x8f, 0xa2, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41,
+ 0x89, 0x30, 0x01, 0x00, 0x7d, 0x8f, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00,
+ 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x87, 0x8f, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x88, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc0, 0x8f, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00,
+ 0xc0, 0x8f, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x7e, 0x89, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x44, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x93, 0x8f, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x15,
+ 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b, 0x99, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x0b,
+ 0x99, 0x6c, 0x00, 0x00, 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0,
+ 0x22, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41,
+ 0xe7, 0xe1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0xf2, 0x98, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a,
+ 0x99, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x00, 0x98, 0x6c, 0x00, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x11,
+ 0x8a, 0x30, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x47, 0xe7, 0xb5, 0x01, 0x00, 0xab, 0x8f, 0x23, 0x0b,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xc1, 0x00, 0x00, 0x01,
+ 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x02, 0xd0, 0x01, 0x00, 0x58, 0x97, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xb2, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x05,
+ 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00,
+ 0xbe, 0x8f, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40,
+ 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0xd0, 0x01, 0x00,
+ 0x58, 0x97, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40,
+ 0x03, 0x98, 0x01, 0x00, 0xc8, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x15,
+ 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, 0xe4, 0xcd, 0x01, 0x00,
+ 0xc1, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x20, 0x0b, 0xe5, 0x6d, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x58, 0x97, 0x00, 0x00,
+ 0x2a, 0x40, 0x01, 0x00, 0xcd, 0x8f, 0x22, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xce, 0x8f, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00, 0x98, 0x93, 0x00, 0x40,
+ 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00,
+ 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xd6, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xd3, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xfa, 0x96, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0xd9, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xdc, 0x8f, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f,
+ 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0xb0, 0x01, 0x00, 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00,
+ 0x28, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0,
+ 0x26, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00,
+ 0xb8, 0x96, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x26, 0x90, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0xfa, 0x8f, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xfa, 0x8f, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xf6, 0x8f, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x14, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x1f, 0x90, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x0d, 0x90, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x54, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1a, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x03, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x90, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00,
+ 0x0a, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0c, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40,
+ 0x05, 0xb0, 0x00, 0x00, 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x49, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x10, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x16, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x17, 0x90, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x19, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x1b, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x22, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x23, 0x90, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x25, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0,
+ 0x14, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00,
+ 0x2f, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x2b, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x33, 0x90, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00,
+ 0x34, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a, 0x84, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x3a, 0x90, 0x03, 0x1e, 0x80, 0x32, 0x00, 0x00, 0x3b, 0x90, 0x00, 0x41,
+ 0x87, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x26, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x40, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x43, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x80, 0x01, 0x00, 0xc6, 0x8b, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x4b, 0x90, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x2f, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xcd, 0x8b, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x57, 0x90, 0x22, 0x40,
+ 0xe7, 0x6d, 0x00, 0x00, 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x62, 0x90, 0xa2, 0x40, 0xe5, 0x6d, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06,
+ 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0,
+ 0x80, 0x32, 0x00, 0x00, 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0xcd, 0x8b, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xec, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x97, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x70, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15,
+ 0x98, 0x50, 0x00, 0x00, 0x70, 0x90, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00,
+ 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x6d, 0x90, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15,
+ 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01,
+ 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00,
+ 0xe6, 0x8f, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0x80, 0x97, 0x00, 0x09,
+ 0x80, 0x30, 0x01, 0x00, 0xe6, 0x8f, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0x26, 0x96, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0xc6, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x2c, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xc6, 0x8b, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00, 0x16, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x55, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x8a, 0x90, 0xa8, 0x40, 0x13, 0x30, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x90, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf0,
+ 0x84, 0x30, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x26, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xad, 0x90, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0xc6, 0x8b, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00,
+ 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40,
+ 0xe7, 0x91, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xab, 0x90, 0x22, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x17, 0x94, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0xab, 0x90, 0x22, 0x00,
+ 0x80, 0x32, 0x00, 0x00, 0xa6, 0x90, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xab, 0x90, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0xf2,
+ 0x02, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xac, 0x90, 0x00, 0x40,
+ 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xb2, 0x90, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xb1, 0x90, 0xa2, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb2, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x51, 0x91, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xba, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xb7, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x51, 0x91, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc1, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xc1, 0x90, 0xa2, 0x16,
+ 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x96, 0xb0, 0x01, 0x00,
+ 0xd2, 0x90, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x4b, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xce, 0x90, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd3, 0x90, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xd7, 0x90, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0xdc, 0x90, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x27, 0x83, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd6, 0x90, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0x04, 0x00, 0x75, 0x09, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0xe4, 0x90, 0xa8, 0x40, 0xe1, 0x31, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0xe8, 0x90, 0x65, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xf0, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0xee, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00,
+ 0x2f, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0d, 0x91, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x48, 0x96, 0x00, 0x5f,
+ 0x01, 0x10, 0x01, 0x00, 0xf4, 0x90, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xfe, 0x90, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x31, 0x03, 0x6c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xf4, 0x90, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0xf4, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x60, 0x97, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x4d,
+ 0x97, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0xe1, 0xb1, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07,
+ 0x16, 0x88, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00,
+ 0x19, 0x91, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00,
+ 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00,
+ 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00, 0x93, 0x04, 0x00, 0x5f,
+ 0x95, 0x04, 0x01, 0x00, 0x70, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x27, 0x91, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x23, 0x91, 0x46, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x26, 0x91, 0xa2, 0x40, 0x31, 0x6f, 0x00, 0x00,
+ 0x04, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41,
+ 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0xa5, 0x94, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00,
+ 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x3a, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x3a, 0x91, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x32, 0x91, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x37, 0x91, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x77, 0x7d, 0x00, 0x00, 0x33, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x37, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x74, 0x00, 0x22, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x55, 0x97, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x16, 0x96, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0xc1, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x4e, 0x91, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40,
+ 0xe7, 0x31, 0x01, 0x00, 0x4e, 0x91, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00,
+ 0x49, 0x91, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x4e, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2,
+ 0x94, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00,
+ 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x55, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x16, 0x96, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x55, 0x91, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47,
+ 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x91, 0x01, 0x00,
+ 0x80, 0x97, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x16, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xce, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x80, 0x97, 0x00, 0x45,
+ 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x09, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x6d, 0x91, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x6d, 0x91, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00,
+ 0x09, 0x97, 0x00, 0x47, 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07,
+ 0x84, 0x94, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00,
+ 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00,
+ 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00,
+ 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a,
+ 0x2c, 0x50, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0x9b, 0x97, 0x00, 0x06,
+ 0x04, 0x30, 0x01, 0x00, 0x8a, 0x91, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0x88, 0x91, 0x84, 0x48, 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x8a, 0x91, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, 0x98, 0x93, 0x00, 0x01,
+ 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0xc0, 0x01, 0x00, 0x98, 0x91, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0x73, 0x96, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0x83, 0x91, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x94, 0x91, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x83, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x1b, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x9e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xa4, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0xa8, 0x91, 0x22, 0x44,
+ 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00,
+ 0xa8, 0x91, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb7, 0x91, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0xaf, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xb3, 0x91, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb4, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00,
+ 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16,
+ 0xe4, 0xb1, 0x00, 0x00, 0xcd, 0x91, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x2a, 0xb0, 0x01, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0xbd, 0x91, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, 0xce, 0x91, 0x22, 0x40,
+ 0x2d, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00,
+ 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xd1, 0x01, 0x00, 0x58, 0x97, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00,
+ 0xc6, 0x91, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43,
+ 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xc7, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07,
+ 0x16, 0x14, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15,
+ 0x1a, 0x50, 0x00, 0x00, 0xdc, 0x91, 0x20, 0x16, 0x1a, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xd9, 0x91, 0xa8, 0x46,
+ 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x16,
+ 0x80, 0x32, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40,
+ 0x23, 0xb0, 0x01, 0x00, 0xe6, 0x91, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00,
+ 0xe7, 0x91, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x02, 0xb0, 0x01, 0x00, 0xb8, 0x96, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xf0, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xec, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x92, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00,
+ 0x05, 0x92, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0xf8, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x1b, 0x98, 0x01, 0x00, 0x05, 0x92, 0x00, 0x5c, 0x11, 0x80, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5f, 0x1b, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x08,
+ 0x98, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x98, 0xc0, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x0b, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0xa3, 0x43, 0x23, 0x6c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40,
+ 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x0b, 0x92, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0x90, 0x01, 0x00, 0x13, 0x92, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x13, 0x92, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x92, 0xa8, 0x46,
+ 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x18, 0x92, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x1e, 0x92, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x22, 0x92, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f,
+ 0x81, 0x30, 0x01, 0x00, 0x22, 0x92, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08,
+ 0x00, 0x8c, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x38, 0x92, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x29, 0x92, 0xa2, 0x16,
+ 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00,
+ 0x34, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x2d, 0x92, 0xa2, 0xf3,
+ 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41,
+ 0x85, 0xe0, 0x01, 0x00, 0x31, 0x92, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08,
+ 0xe4, 0xf5, 0x01, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x35, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00,
+ 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16,
+ 0xe4, 0xb1, 0x00, 0x00, 0x3b, 0x92, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00,
+ 0x4e, 0x92, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0x48, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x41, 0x92, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00,
+ 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0x45, 0x92, 0x22, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00,
+ 0x58, 0x01, 0x2d, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x40,
+ 0x11, 0x6c, 0x00, 0x00, 0x84, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa3, 0x91, 0x03, 0x6c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x41,
+ 0x95, 0x30, 0x01, 0x00, 0x57, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x57, 0x92, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x55, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x94, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00,
+ 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0x6a, 0x92, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x63, 0x92, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x22, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x84, 0xb0, 0x01, 0x00, 0x6d, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x80, 0xb0, 0x01, 0x00, 0x72, 0x92, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00,
+ 0x58, 0x97, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00, 0x7b, 0x92, 0x22, 0x40,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00,
+ 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, 0x78, 0x92, 0xa8, 0x11,
+ 0xe0, 0x31, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00,
+ 0x8a, 0x92, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x7e, 0x92, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x84, 0xd0, 0x01, 0x00, 0x83, 0x92, 0x22, 0x40,
+ 0x1b, 0x6c, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00,
+ 0x8a, 0x92, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x12, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1,
+ 0x62, 0xdd, 0x01, 0x00, 0x88, 0x92, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x92, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x05,
+ 0x48, 0x31, 0x01, 0x00, 0x92, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0xff, 0x07, 0x00, 0x11, 0x00, 0x8c, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00,
+ 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x8e, 0xb0, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0x0c, 0x47, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00,
+ 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x20, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xa8, 0x92, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xa4, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xaa, 0x92, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x1a, 0xd0, 0x01, 0x00, 0xb1, 0x92, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0xba, 0x92, 0x27, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0xbd, 0x91, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00,
+ 0x25, 0x98, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x80, 0xb2, 0x01, 0x00, 0xb5, 0x92, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x57, 0x92, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0xb8, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0xbf, 0x92, 0x00, 0x4a,
+ 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0xf9, 0x94, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x9b, 0x97, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, 0xcc, 0x92, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x02, 0xb0, 0x01, 0x00, 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0xd3, 0x92, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xcf, 0x92, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0xc0, 0x01, 0x00, 0xdc, 0x92, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0x73, 0x96, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0xc5, 0x92, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xd8, 0x92, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xc5, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x08, 0x00, 0x2d, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe1, 0x92, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xe7, 0x92, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xea, 0x92, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f,
+ 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xf9, 0x92, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xf1, 0x92, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08,
+ 0x2a, 0xb0, 0x01, 0x00, 0xf5, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf6, 0x92, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15,
+ 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00,
+ 0xb8, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xf9, 0x94, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x10,
+ 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x08, 0x93, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0b, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x9f, 0x95, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x0d, 0x93, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0x80, 0x97, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00,
+ 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45,
+ 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00,
+ 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01,
+ 0x2c, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x26, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x26, 0x93, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x1e, 0x93, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x23, 0x93, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x77, 0x7d, 0x00, 0x00, 0x1f, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x23, 0x93, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16,
+ 0xe0, 0xb1, 0x01, 0x00, 0xec, 0x95, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00,
+ 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x97, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0xae, 0x94, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00,
+ 0x3d, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x3d, 0x93, 0xa2, 0x16,
+ 0x80, 0x32, 0x00, 0x00, 0x39, 0x93, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x15,
+ 0x94, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x09, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00,
+ 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4f,
+ 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0xf9, 0x94, 0x00, 0x10,
+ 0x32, 0x30, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x52, 0x93, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x52, 0x93, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00,
+ 0x4a, 0x93, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x62, 0xb1, 0x01, 0x00, 0x4f, 0x93, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x77, 0x7d, 0x00, 0x00, 0x4b, 0x93, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00,
+ 0x4f, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x04, 0x00, 0x0c, 0x47, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x00, 0xa0, 0x91, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x64, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x60, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x84, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00,
+ 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x84, 0x8f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x01,
+ 0x14, 0x6c, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x72, 0x93, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00,
+ 0x77, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x48,
+ 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00,
+ 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x97, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f,
+ 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0xf9, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x46,
+ 0xe7, 0x7d, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x37, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x33, 0xc3, 0x01, 0x00, 0x36, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0xd2, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x86, 0x93, 0x85, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x48, 0x03, 0xd0, 0x00, 0x00,
+ 0x88, 0x93, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x4c,
+ 0x03, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x34, 0xc3, 0x01, 0x00,
+ 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xf0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0xf0, 0xb1, 0x01, 0x00, 0xcb, 0x94, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x43, 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x95, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0xa5,
+ 0x8a, 0x30, 0x01, 0x00, 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0xf0,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00,
+ 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0xa3, 0x93, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x2f, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xa5, 0x93, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0xce, 0x97, 0x00, 0x47,
+ 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0,
+ 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xba, 0x93, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x94, 0xa2, 0x4c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xba, 0x93, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xbd, 0x93, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46,
+ 0x8f, 0xb0, 0x01, 0x00, 0xb3, 0x93, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xb5, 0x93, 0x22, 0xf0,
+ 0x3a, 0x6c, 0x00, 0x00, 0x0c, 0x94, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f,
+ 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x0d, 0x94, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xb9, 0x93, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xbc, 0x93, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0xc1, 0x93, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0xcc, 0x93, 0x23, 0xf0,
+ 0x02, 0x6c, 0x00, 0x00, 0xb0, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc9, 0x93, 0xa2, 0xf0,
+ 0x80, 0x32, 0x00, 0x00, 0x0e, 0x94, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00,
+ 0x0e, 0x94, 0xa2, 0x41, 0x03, 0x6c, 0x00, 0x00, 0xc8, 0x93, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x52, 0x8f, 0xb0, 0x01, 0x00, 0x0e, 0x94, 0x1f, 0x12,
+ 0x84, 0x50, 0x00, 0x00, 0x0e, 0x94, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00,
+ 0xba, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xf7, 0x93, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xe9, 0x93, 0x22, 0xf0,
+ 0x14, 0x30, 0x00, 0x00, 0xd5, 0x93, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00,
+ 0xe6, 0x93, 0x03, 0x1e, 0x80, 0x32, 0x00, 0x00, 0xd4, 0x93, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0xda, 0x93, 0x22, 0x0a,
+ 0x02, 0x6c, 0x00, 0x00, 0xdd, 0x93, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xd9, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00,
+ 0xdc, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x82, 0xd0, 0x01, 0x00, 0xe3, 0x93, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00,
+ 0xe2, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0xe5, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0xe8, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0xf2, 0x93, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0xef, 0x93, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00,
+ 0xef, 0x93, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40,
+ 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00,
+ 0xf1, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00,
+ 0xef, 0x93, 0xa0, 0x91, 0x03, 0x6c, 0x00, 0x00, 0xed, 0x93, 0x22, 0x43,
+ 0x3d, 0x7c, 0x00, 0x00, 0xf6, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x28, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x94, 0xa2, 0xf0, 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44,
+ 0x8f, 0xb0, 0x01, 0x00, 0xfd, 0x93, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49,
+ 0x8f, 0xb0, 0x01, 0x00, 0xef, 0x93, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xed, 0x93, 0x20, 0x91, 0x03, 0x6c, 0x00, 0x00, 0xef, 0x93, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x94, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00,
+ 0x03, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00,
+ 0x09, 0x94, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0xdd, 0x93, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x08, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56,
+ 0x8f, 0xb0, 0x01, 0x00, 0x0b, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48,
+ 0x8f, 0xb0, 0x01, 0x00, 0x11, 0x94, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00,
+ 0x11, 0x94, 0x00, 0x41, 0x95, 0xb0, 0x00, 0x00, 0x11, 0x94, 0x00, 0x42,
+ 0x95, 0xb0, 0x00, 0x00, 0x11, 0x94, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00,
+ 0x11, 0x94, 0x00, 0x4c, 0x95, 0xb0, 0x00, 0x00, 0x30, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x4a, 0x8a, 0x30, 0x01, 0x00,
+ 0x55, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x16, 0x94, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00, 0x1c, 0x94, 0xa2, 0xf3,
+ 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00,
+ 0x2d, 0x00, 0x2a, 0x41, 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41,
+ 0x85, 0xe0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00,
+ 0x22, 0x94, 0x22, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0x90, 0x01, 0x00, 0x23, 0x94, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41,
+ 0x85, 0xc0, 0x01, 0x00, 0x26, 0x94, 0xa0, 0xa5, 0x85, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x12, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0xa0, 0xa5,
+ 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x78, 0x98, 0x00, 0xf0, 0x8c, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x3b, 0x94, 0x22, 0x40,
+ 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf0,
+ 0x98, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x98, 0x6c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x0c, 0x98, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07,
+ 0x98, 0x6c, 0x00, 0x00, 0x38, 0x94, 0xa2, 0x4b, 0x19, 0x7c, 0x00, 0x00,
+ 0x39, 0x94, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x3d, 0x95, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00,
+ 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x3d, 0x94, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0xa5, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00,
+ 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07,
+ 0x96, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c, 0x96, 0xf4, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, 0x3d, 0x95, 0x00, 0x07,
+ 0x10, 0x30, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x0f, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x96, 0xf4, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c,
+ 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00,
+ 0x3d, 0x95, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0x54, 0x94, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x57, 0x94, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x69, 0x94, 0x13, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00,
+ 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f,
+ 0x5f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x5f, 0x7c, 0x00, 0x00,
+ 0x1f, 0x00, 0x00, 0x0f, 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a,
+ 0x5f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x5f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x4e, 0xb0, 0x01, 0x00, 0x19, 0x85, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x44, 0x5f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00, 0x66, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x40, 0x05, 0x6c, 0x00, 0x00, 0x15, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x6c, 0x94, 0x60, 0x07, 0x96, 0x30, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x70, 0xc2,
+ 0x24, 0xb0, 0x01, 0x00, 0x79, 0x94, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00,
+ 0x70, 0x94, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x7a, 0x94, 0x22, 0x12,
+ 0x48, 0x7f, 0x00, 0x00, 0x58, 0x04, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x17, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x8a, 0xb0, 0x01, 0x00, 0x02, 0x99, 0x00, 0x5f,
+ 0x8b, 0x10, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00,
+ 0x79, 0x94, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4,
+ 0x24, 0xb0, 0x01, 0x00, 0x7a, 0x94, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00,
+ 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x17, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x12, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x89, 0x94, 0x0b, 0xf0,
+ 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00,
+ 0x86, 0x94, 0x22, 0x50, 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xae, 0x96, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00,
+ 0x93, 0x04, 0x00, 0x12, 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a,
+ 0x1f, 0x90, 0x01, 0x00, 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42,
+ 0x10, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08,
+ 0x8a, 0x88, 0x01, 0x00, 0x8d, 0x94, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00,
+ 0x90, 0x94, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x7a, 0x94, 0x10, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xae, 0x96, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x9c, 0x94, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa7,
+ 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xa0, 0x94, 0xa8, 0x05,
+ 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x0f, 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42,
+ 0x84, 0x88, 0x01, 0x00, 0xaa, 0x94, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0xab, 0x94, 0x00, 0x42, 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x6a, 0xb1, 0x01, 0x00, 0xab, 0x94, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x42, 0x48, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42,
+ 0x48, 0x93, 0x01, 0x00, 0xae, 0x94, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xb4, 0x94, 0x28, 0xb1,
+ 0x2c, 0x30, 0x00, 0x00, 0xaf, 0x94, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x95, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xb4, 0x94, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xbf, 0x94, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00,
+ 0xb9, 0x94, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x15, 0x00, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5c,
+ 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, 0x11, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x08, 0x48, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0x24,
+ 0x11, 0x84, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x00,
+ 0x48, 0x06, 0x00, 0x00, 0x04, 0x00, 0x1f, 0xbb, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc8, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xcc, 0x94, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xd4, 0x94, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x90, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x49,
+ 0x80, 0x32, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00,
+ 0x20, 0x00, 0x92, 0x48, 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xd8, 0x94, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00,
+ 0xd4, 0x94, 0x22, 0x4c, 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40,
+ 0x91, 0xb0, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xd8, 0x94, 0xa8, 0xb1, 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x48, 0x80, 0x32, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x92, 0x49,
+ 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x83, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x00, 0xec, 0x00, 0x00,
+ 0xea, 0x94, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x00,
+ 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x49, 0xc1, 0x01, 0x00,
+ 0xe4, 0x94, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x83, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x00, 0xec, 0x00, 0x00,
+ 0xf6, 0x94, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x00,
+ 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x49, 0xc1, 0x01, 0x00,
+ 0xf0, 0x94, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xfb, 0x94, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, 0x24, 0x00, 0x2d, 0x01,
+ 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00,
+ 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x2f, 0xf2,
+ 0x0c, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x20, 0x01, 0x14, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x60, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x95, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x0b, 0xe8, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x60, 0x17, 0x3d, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x10, 0x00, 0x80, 0xa1, 0x16, 0xe4, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x07, 0x16, 0x6c, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0b, 0x8a, 0xe4, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x0d, 0x8a, 0x14, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x17, 0x95, 0x30, 0x47, 0x17, 0x04, 0x00, 0x00,
+ 0x1a, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x90, 0x42,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00,
+ 0x1e, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x1f, 0x95, 0x40, 0x07,
+ 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x29, 0x95, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00, 0x01, 0x97, 0x3f, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40,
+ 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00,
+ 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00, 0x3c, 0x95, 0x00, 0x3b,
+ 0xe7, 0xb1, 0x00, 0x00, 0x29, 0x95, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x33, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0x2f, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x42,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41, 0x81, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x4a,
+ 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41, 0x95, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07, 0x92, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x11, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43,
+ 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41,
+ 0xe6, 0x7d, 0x00, 0x00, 0x44, 0x95, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00,
+ 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x52, 0x95, 0x22, 0x45,
+ 0x95, 0x7c, 0x00, 0x00, 0x4d, 0x95, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x0f, 0x96, 0xf4, 0x01, 0x00, 0x49, 0x95, 0x31, 0x5f,
+ 0x97, 0x04, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4b, 0x48, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x6a, 0xb1, 0x01, 0x00, 0x4d, 0x95, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00,
+ 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3,
+ 0x88, 0xb0, 0x01, 0x00, 0x5b, 0x95, 0xa2, 0x3b, 0x89, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6,
+ 0x92, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x44, 0x7f, 0x00, 0x00,
+ 0x5c, 0x95, 0x18, 0x4a, 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x3f, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x16, 0x00, 0x00, 0x12, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x4b,
+ 0x8a, 0x14, 0x01, 0x00, 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5f, 0x5f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5e,
+ 0x5f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x2f, 0x7e, 0xd9, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x68, 0x95, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x6a, 0x95, 0x00, 0x05,
+ 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x5f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x08, 0x4e, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x6d, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x33, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x07, 0x8a, 0x30, 0x01, 0x00,
+ 0x72, 0x95, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x76, 0x95, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4a,
+ 0x44, 0x7f, 0x00, 0x00, 0x9b, 0x04, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00,
+ 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45,
+ 0x97, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x20, 0xaa,
+ 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x82, 0x95, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x78, 0x95, 0xa2, 0x3b, 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08,
+ 0x94, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x4a, 0x46, 0xc9, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x08, 0x96, 0x88, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x93, 0x04, 0x00, 0x12, 0x94, 0x30, 0x01, 0x00,
+ 0x3d, 0x95, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a,
+ 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a, 0xe6, 0xc9, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x4a, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b,
+ 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44,
+ 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf2,
+ 0x02, 0x30, 0x00, 0x00, 0x17, 0x94, 0x00, 0x10, 0x32, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00,
+ 0xa3, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x36, 0xb0, 0x01, 0x00, 0xb4, 0x95, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0xac, 0x95, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x00, 0xb0, 0x01, 0x00, 0xa7, 0x95, 0x00, 0x5c, 0x01, 0x80, 0x00, 0x00,
+ 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x46, 0xc9, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe2, 0x95, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x68, 0x08,
+ 0x38, 0x96, 0x01, 0x00, 0x3a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41,
+ 0x82, 0xcc, 0x01, 0x00, 0xb9, 0x95, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x11, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x48, 0x3b, 0x6c, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00, 0xe0, 0x95, 0x26, 0x46,
+ 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x12, 0xc8, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x98, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4c,
+ 0x42, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00, 0xdf, 0x95, 0x22, 0x41,
+ 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x22, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0xd1, 0x95, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0xde, 0x95, 0x22, 0x41,
+ 0x05, 0x50, 0x00, 0x00, 0xdc, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd7, 0x95, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x13, 0xc0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x50, 0x49, 0xc1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x1a, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xe0, 0x95, 0x22, 0x40,
+ 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0x5c, 0x01, 0x00, 0x01, 0x00, 0xe2, 0x95, 0x00, 0x41,
+ 0x3b, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00,
+ 0xb0, 0x00, 0x2f, 0x5f, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0,
+ 0x8c, 0xc0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0xa3, 0xf0, 0x8c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x8c, 0xb0, 0x01, 0x00, 0xf1, 0x95, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x14, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8,
+ 0x0c, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b,
+ 0xe0, 0xb1, 0x01, 0x00, 0xfe, 0x95, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x96, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00,
+ 0x18, 0x00, 0x20, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b,
+ 0xe0, 0xb1, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42,
+ 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x05, 0x96, 0xa2, 0xa5,
+ 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00,
+ 0x08, 0x96, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00,
+ 0x0d, 0x96, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00,
+ 0x12, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00,
+ 0x13, 0x96, 0x00, 0x40, 0x1f, 0x80, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0xe4, 0xf5, 0x01, 0x00, 0x1e, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0xe1, 0x6d, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d,
+ 0x05, 0x90, 0x00, 0x00, 0x23, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0x33, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x82, 0x0c, 0x80, 0x32, 0x00, 0x00,
+ 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3,
+ 0x84, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00,
+ 0x3d, 0x96, 0x9f, 0x41, 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5,
+ 0x85, 0xcc, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x42, 0xe6, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0xa3, 0xa5, 0x97, 0x6c, 0x00, 0x00, 0xd4, 0x00, 0x3d, 0x41,
+ 0x85, 0xe0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0xf2, 0x98, 0xe4, 0x01, 0x00,
+ 0x44, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5a,
+ 0x99, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x99, 0x80, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x00, 0x98, 0x6c, 0x00, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x21, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x00, 0x6a, 0x06, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x00,
+ 0x80, 0xb0, 0x01, 0x00, 0x4f, 0x96, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0x50, 0x96, 0x00, 0x41,
+ 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00,
+ 0x51, 0x96, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x56, 0x96, 0xa2, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0x6b, 0x96, 0x9c, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x60, 0x96, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e,
+ 0x98, 0xf4, 0x01, 0x00, 0x5f, 0x96, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0x5f, 0x96, 0xa2, 0x8a,
+ 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4,
+ 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x6a, 0x96, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00,
+ 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3,
+ 0x3a, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x0c, 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07,
+ 0x96, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04,
+ 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0,
+ 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0x7a, 0x96, 0x22, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x84, 0x96, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x95,
+ 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03,
+ 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x8f, 0x96, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x90, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x62, 0xc9, 0x01, 0x00, 0x92, 0x96, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x95, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x9d, 0x96, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9e, 0x96, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0xa0, 0x96, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46,
+ 0x0d, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x09, 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0xaa, 0x96, 0x63, 0x42, 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a,
+ 0x62, 0xc9, 0x01, 0x00, 0xab, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0xf3, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x97, 0xf0, 0x01, 0x00, 0xaf, 0x96, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb7, 0x96, 0x22, 0xf3, 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3,
+ 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00,
+ 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb4, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00,
+ 0xc7, 0x96, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0xbc, 0x96, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xc2, 0x96, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xbf, 0x96, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0xb0, 0x01, 0x00, 0xc7, 0x96, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xe1, 0x94, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0xc9, 0x96, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00,
+ 0xca, 0x96, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x04, 0xb0, 0x01, 0x00, 0xcc, 0x96, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x04, 0xb0, 0x01, 0x00, 0x9b, 0x97, 0x00, 0x05,
+ 0x48, 0x31, 0x01, 0x00, 0xf7, 0x96, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0xd0, 0x96, 0xa2, 0x02, 0x2a, 0x50, 0x00, 0x00, 0xf7, 0x96, 0xa2, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0xd2, 0x96, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00,
+ 0xdb, 0x96, 0x00, 0x02, 0x16, 0xc0, 0x00, 0x00, 0xda, 0x96, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xda, 0x96, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xd6, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x73, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0xf7, 0x96, 0x22, 0x15,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0xf6, 0x96, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, 0xe7, 0x96, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0xe7, 0x96, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe3, 0x96, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x32, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0x2f, 0x00, 0x2f, 0x5c,
+ 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0xb9, 0x96, 0x20, 0x15,
+ 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0xf3, 0x96, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0xb9, 0x96, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xb9, 0x96, 0x00, 0x02,
+ 0x10, 0xc0, 0x00, 0x00, 0xf9, 0x96, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0x01, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40,
+ 0x27, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xb0, 0x01, 0x00,
+ 0xc3, 0x94, 0x00, 0x41, 0xa3, 0x41, 0x01, 0x00, 0x05, 0x97, 0x00, 0x41,
+ 0x27, 0xd0, 0x00, 0x00, 0x36, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x14, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x0e, 0x97, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x64, 0x97, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06,
+ 0x16, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00,
+ 0x18, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x6c, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40,
+ 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00,
+ 0x21, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43,
+ 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00,
+ 0x21, 0x97, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x44, 0x97, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00,
+ 0x2f, 0x97, 0xa2, 0x06, 0x14, 0x6c, 0x00, 0x00, 0x2c, 0x97, 0x22, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0x26, 0x97, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x31, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00,
+ 0x8b, 0x00, 0x2d, 0x48, 0x19, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45,
+ 0xe7, 0x7d, 0x00, 0x00, 0x8b, 0x00, 0x20, 0x45, 0xe7, 0x91, 0x01, 0x00,
+ 0x2f, 0x97, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00, 0x08, 0x00, 0x00, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0x2f, 0x97, 0xa0, 0x48, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00,
+ 0xa8, 0x97, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x3a, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00,
+ 0x39, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x3e, 0x97, 0x64, 0xf0, 0x82, 0xb0, 0x00, 0x00,
+ 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x3e, 0x97, 0xa2, 0xf2,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe5, 0xb1, 0x01, 0x00,
+ 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06, 0x30, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49,
+ 0x19, 0x7c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0x46, 0x19, 0x90, 0x01, 0x00,
+ 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00,
+ 0xa8, 0x97, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x4a,
+ 0x19, 0xfc, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0x17, 0xc0, 0x01, 0x00, 0x4d, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xe4, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x1b,
+ 0xe0, 0xb1, 0x00, 0x00, 0x52, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0xf0, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x4c,
+ 0x95, 0x60, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4a, 0x18, 0x94, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01,
+ 0xf0, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, 0x5d, 0x97, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x5f, 0x17, 0x90, 0x01, 0x00,
+ 0x70, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x7a, 0x01, 0x2e, 0xfe,
+ 0x92, 0xb0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0xf6, 0x16, 0xb0, 0x01, 0x00,
+ 0x6a, 0x97, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x45, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6, 0x2a, 0xb0, 0x01, 0x00,
+ 0x28, 0x00, 0x6e, 0x06, 0x82, 0xc8, 0x01, 0x00, 0x6e, 0x97, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x6e, 0x4c, 0x83, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x92, 0xc0, 0x01, 0x00, 0x6f, 0x97, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x9e, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41,
+ 0x3d, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00,
+ 0x06, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x49,
+ 0x98, 0xf4, 0x01, 0x00, 0x78, 0x97, 0x26, 0x30, 0x93, 0x04, 0x00, 0x00,
+ 0x78, 0x97, 0x90, 0x4c, 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x93, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x80, 0x49, 0xec, 0xa9, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01,
+ 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00,
+ 0x7d, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x20,
+ 0x81, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x81, 0x6c, 0x00, 0x00,
+ 0x8f, 0x97, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00, 0x8c, 0x97, 0xa2, 0x40,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x97, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x8c, 0x97, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00,
+ 0x88, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x25, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00, 0x92, 0x97, 0xa2, 0x5f,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43, 0x19, 0x7c, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00, 0x25, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00,
+ 0x97, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0xa0, 0x97, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xb4, 0x05, 0x00, 0x02,
+ 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02,
+ 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x13, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x08, 0xe0, 0xb1, 0x00, 0x00, 0xa5, 0x97, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0xb0, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xf0, 0x98, 0xf4, 0x01, 0x00, 0xb1, 0x97, 0x20, 0x4c,
+ 0x84, 0x6c, 0x00, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xb1, 0x97, 0x20, 0xf2, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14,
+ 0x98, 0xd0, 0x01, 0x00, 0xb6, 0x97, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x84, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x30,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x80, 0xe0, 0x01, 0x00,
+ 0xba, 0x97, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14, 0xe0, 0xb1, 0x01, 0x00,
+ 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xf3,
+ 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42, 0x82, 0xc0, 0x00, 0x00,
+ 0xc0, 0x97, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x82, 0xec, 0x00, 0x00,
+ 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x37, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00,
+ 0x02, 0x99, 0x00, 0x05, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcb, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x1c,
+ 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x8a, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00, 0xd9, 0x97, 0x9c, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0xbe, 0x00, 0x2f, 0xab, 0x83, 0xb0, 0x01, 0x00, 0x35, 0x98, 0x00, 0x14,
+ 0x82, 0x50, 0x01, 0x00, 0xde, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xde, 0x97, 0x22, 0xf2, 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xde, 0x97, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xbe, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x35, 0x98, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x9c, 0x00, 0x2d, 0x30, 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0,
+ 0x84, 0xb0, 0x01, 0x00, 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00,
+ 0xf2, 0x97, 0x23, 0xf0, 0x84, 0x6c, 0x00, 0x00, 0xe6, 0x97, 0x23, 0x92,
+ 0x87, 0x6c, 0x00, 0x00, 0xc9, 0x04, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00,
+ 0xe8, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x94, 0xb0, 0x01, 0x00, 0x60, 0x89, 0x00, 0x4a, 0x94, 0x98, 0x01, 0x00,
+ 0xe8, 0x97, 0x68, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40,
+ 0xbd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xb0, 0xb1, 0x01, 0x00,
+ 0xbf, 0x00, 0x2d, 0x42, 0xb2, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3,
+ 0x80, 0xe0, 0x01, 0x00, 0xed, 0x97, 0xd4, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0xda, 0x84, 0xc0, 0x01, 0x00, 0xf7, 0x97, 0x23, 0x40,
+ 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00,
+ 0xf7, 0x97, 0x00, 0x40, 0x84, 0xb0, 0x00, 0x00, 0xbf, 0x00, 0x2d, 0x43,
+ 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, 0x80, 0xe0, 0x01, 0x00,
+ 0xf7, 0x97, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00,
+ 0xfb, 0x97, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00, 0x9c, 0x00, 0x20, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x82, 0x88, 0x01, 0x00, 0x01, 0x98, 0x23, 0x41, 0x80, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x89, 0x0c,
+ 0x80, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x86, 0x0c, 0x80, 0x32, 0x00, 0x00,
+ 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x41, 0x24, 0xec, 0x00, 0x00,
+ 0x0d, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x42,
+ 0x38, 0xec, 0x00, 0x00, 0x0d, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x0f, 0x98, 0xa3, 0xf0,
+ 0x3a, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x13, 0x98, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0xb4, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f,
+ 0x13, 0x94, 0x01, 0x00, 0x13, 0x98, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x27, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x42,
+ 0x8a, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x1f, 0x98, 0x9f, 0x41, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00,
+ 0x20, 0x98, 0x00, 0x41, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x22, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0xa7, 0x08, 0x80, 0x32, 0x01, 0x00, 0x32, 0x04, 0x00, 0x40,
+ 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00,
+ 0x2c, 0x98, 0xa2, 0x40, 0x95, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00,
+ 0xa0, 0x98, 0x2f, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41,
+ 0x89, 0xb0, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00,
+ 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf8,
+ 0x3e, 0xec, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x12, 0xe0, 0xed, 0x00, 0x00,
+ 0xc8, 0x00, 0x20, 0xab, 0xe1, 0xb1, 0x01, 0x00, 0xcc, 0x00, 0xa0, 0x1f,
+ 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00,
+ 0x38, 0x98, 0xa3, 0x5f, 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe7, 0xc1, 0x01, 0x00, 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x4c, 0x98, 0x22, 0xf2, 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43,
+ 0x84, 0xf4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00,
+ 0xb8, 0x00, 0x2d, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40,
+ 0x86, 0xc0, 0x01, 0x00, 0x40, 0x98, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00,
+ 0x41, 0x98, 0xa2, 0x40, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41,
+ 0x87, 0xb0, 0x01, 0x00, 0x45, 0x98, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x84, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44,
+ 0x84, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x62, 0x40, 0x88, 0xc0, 0x01, 0x00, 0x4b, 0x98, 0x1f, 0x44,
+ 0x80, 0x32, 0x00, 0x00, 0x4f, 0x98, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00,
+ 0x4f, 0x98, 0x62, 0x41, 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41,
+ 0x86, 0xe4, 0x01, 0x00, 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x62, 0x41, 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xbc, 0x00, 0x2e, 0x43, 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x86, 0xc0, 0x01, 0x00, 0x55, 0x98, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x43, 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43,
+ 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00,
+ 0x40, 0x01, 0xe2, 0x40, 0x87, 0x98, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05,
+ 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00,
+ 0x88, 0x00, 0x2d, 0x44, 0x81, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf2,
+ 0x2e, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0xf0, 0x86, 0xb0, 0x01, 0x00,
+ 0x90, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xba, 0x00, 0x2d, 0xf0,
+ 0x98, 0xb0, 0x01, 0x00, 0x64, 0x98, 0xa2, 0x12, 0x98, 0x6c, 0x00, 0x00,
+ 0xbc, 0x00, 0x2d, 0xf2, 0x98, 0xb0, 0x01, 0x00, 0x64, 0x98, 0xa0, 0xf2,
+ 0x98, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x82, 0xb0, 0x01, 0x00,
+ 0x9c, 0x00, 0x20, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x2d, 0x12,
+ 0x86, 0xd0, 0x01, 0x00, 0x67, 0x98, 0xa3, 0x41, 0xe0, 0x6d, 0x00, 0x00,
+ 0x68, 0x98, 0x00, 0xf0, 0x84, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x84, 0xb0, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x43, 0x84, 0xd0, 0x01, 0x00,
+ 0x6b, 0x98, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x6d, 0x98, 0xa3, 0x42, 0x14, 0x6c, 0x00, 0x00,
+ 0x6e, 0x98, 0x00, 0x0a, 0x0c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x0c, 0xb0, 0x01, 0x00, 0x70, 0x98, 0xa0, 0x17, 0x0c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x17, 0x0c, 0xb0, 0x01, 0x00, 0x75, 0x98, 0x22, 0x40,
+ 0x0d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x0c, 0xec, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0xf0, 0x82, 0xf4, 0x01, 0x00, 0x75, 0x98, 0xa0, 0x41,
+ 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x01, 0x00,
+ 0x29, 0x00, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x22, 0x03,
+ 0x80, 0x32, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, 0x87, 0x94, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d,
+ 0x05, 0x90, 0x00, 0x00, 0x84, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c,
+ 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x05, 0x00, 0x2a, 0x0c,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, 0xe6, 0xb1, 0x01, 0x00,
+ 0x3e, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08,
+ 0x8a, 0x30, 0x01, 0x00, 0x8f, 0x98, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x95, 0x98, 0x28, 0x40,
+ 0x87, 0x30, 0x00, 0x00, 0x90, 0x98, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x04, 0x97, 0x1d, 0x46,
+ 0x87, 0xb0, 0x00, 0x00, 0x98, 0x98, 0x22, 0x5f, 0x11, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00, 0x96, 0x98, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x4c,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x9b, 0x98, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0xb0, 0x01, 0x00,
+ 0xef, 0x98, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00, 0x07, 0x00, 0x00, 0x49,
+ 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03, 0x06, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xd0,
+ 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00,
+ 0xa2, 0x98, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x05,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0xab, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00, 0xf5, 0x98, 0x00, 0x40,
+ 0x49, 0x31, 0x01, 0x00, 0x02, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xb2, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x97, 0x2e, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0xb6, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xba, 0x98, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0xba, 0x94, 0x20, 0x41,
+ 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xc4, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x68, 0xb1, 0x01, 0x00,
+ 0xc8, 0x98, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x80, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x39, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x33, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x3f, 0xb3, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40, 0x25, 0x9b, 0x01, 0x00,
+ 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x2b, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5, 0x3c, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c,
+ 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x59, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xb3, 0x01, 0x00,
+ 0xe4, 0x98, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xe4, 0x98, 0xa2, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0xe5, 0x98, 0x00, 0x40, 0x1d, 0xb3, 0x00, 0x00,
+ 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6,
+ 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6, 0x3a, 0xb3, 0x01, 0x00,
+ 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00, 0xb4, 0x05, 0x00, 0x40,
+ 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x4d, 0xb3, 0x01, 0x00,
+ 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x8a,
+ 0x15, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x87, 0xb3, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5e,
+ 0x57, 0xb5, 0x01, 0x00, 0x18, 0x00, 0x00, 0x4b, 0x20, 0xe4, 0x01, 0x00,
+ 0x06, 0x00, 0x00, 0x4b, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x43, 0x00, 0x4b,
+ 0x96, 0xc8, 0x01, 0x00, 0x18, 0x00, 0x00, 0x10, 0x20, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x20, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x57,
+ 0x21, 0x90, 0x01, 0x00, 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xf6, 0x98, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x00, 0xa9, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xfa, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0xfe, 0x98, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xfe, 0x98, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x99, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x88, 0x94, 0x01, 0x00,
+ 0x08, 0x99, 0x6a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x0b, 0x99, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x62, 0xb1, 0x01, 0x00, 0x0c, 0x99, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x13, 0x99, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0x11, 0x99, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0x11, 0x99, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x98, 0xf4, 0x01, 0x00,
+ 0x04, 0x00, 0xa2, 0x5f, 0x99, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00,
+ 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x41, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xb2, 0x9f, 0x22, 0x40, 0x7b, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xc6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00,
+ 0x08, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xa8, 0x9f, 0x00, 0x4d,
+ 0x9a, 0xcc, 0x01, 0x00, 0xbb, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0xb9, 0x9f, 0xa2, 0x41,
+ 0x9b, 0x50, 0x00, 0x00, 0xbf, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x49, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x4a, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40,
+ 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00,
+ 0xca, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d,
+ 0x10, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe3, 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4,
+ 0x45, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x48, 0x4f, 0x40, 0xb1, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb,
+ 0x81, 0xc8, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00,
+ 0x55, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x18, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x43, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x23, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x27, 0x83, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8d, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x78, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x87, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x95, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x0a, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb1, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x19, 0x99, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00,
+ },
+};
diff --git a/drivers/staging/slicoss/oasisdownload.h b/drivers/staging/slicoss/oasisdownload.h
new file mode 100644
index 00000000000..6438c23d754
--- /dev/null
+++ b/drivers/staging/slicoss/oasisdownload.h
@@ -0,0 +1,6848 @@
+#define OASIS_UCODE_VERS_STRING "1.2"
+#define OASIS_UCODE_VERS_DATE "2006/03/27 15:10:37"
+#define OASIS_UCODE_HOSTIF_ID 3
+
+static s32 ONumSections = 0x2;
+static u32 OSectionSize[] = {
+ 0x00004000, 0x00010000,
+};
+
+static u32 OSectionStart[] = {
+ 0x00000000, 0x00008000,
+};
+
+static u8 OasisUCode[2][65536] =
+{
+ {
+ 0x15, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00,
+ 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40,
+ 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x98, 0x18, 0x31, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x41, 0x98,
+ 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x0e, 0x00, 0x40, 0x98,
+ 0x80, 0x94, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x19, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x19, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1f, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x12, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x25, 0x00, 0x29, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x25, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x14, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xdd, 0x81, 0x01, 0x00, 0x12, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x33, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x00, 0x14, 0xbc,
+ 0x80, 0x32, 0x00, 0x00, 0xfe, 0x00, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00,
+ 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xfd, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00,
+ 0x33, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x89, 0xb0, 0x01, 0x00, 0x32, 0x00, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00,
+ 0x99, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x20, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xe0, 0xb3, 0x01, 0x00, 0x39, 0x00, 0x98, 0xee,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x80, 0xb0, 0x01, 0x00,
+ 0x3b, 0x00, 0x80, 0xf3, 0xde, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0xfd, 0x93, 0x01, 0x00, 0x3e, 0x00, 0x83, 0xf3, 0x80, 0x32, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0xf3, 0x80, 0x88, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40,
+ 0x2e, 0xdd, 0x01, 0x00, 0x00, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x43, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0x24, 0xb1, 0x01, 0x00, 0x7c, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00,
+ 0x45, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xe8,
+ 0x80, 0x88, 0x01, 0x00, 0x7c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, 0xee, 0x8b, 0x01, 0x00,
+ 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf0,
+ 0x80, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x81, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8,
+ 0x80, 0x88, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xf0, 0xd6, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xf0,
+ 0xf0, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xf8, 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00,
+ 0x3c, 0x02, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd6, 0xb1, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, 0x1e, 0x00, 0x00, 0xf0,
+ 0x82, 0xf4, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xf8, 0x80, 0xd8, 0x01, 0x00,
+ 0x64, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x81, 0xd0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, 0x80, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd8, 0xb1, 0x01, 0x00, 0x68, 0x00, 0x22, 0xfa, 0x80, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x81, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40,
+ 0x80, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xde, 0xb1, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa,
+ 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, 0x80, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xd6, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40,
+ 0xd5, 0x99, 0x01, 0x00, 0x18, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa,
+ 0xd6, 0xe5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x03, 0x00, 0x00, 0xfb,
+ 0x7a, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdc, 0xb1, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x00, 0x00, 0x7c, 0x00, 0x95, 0xe8,
+ 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42,
+ 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x7c, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x85, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0x8c, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0x98, 0x00, 0x1f, 0xfd,
+ 0xf9, 0x33, 0x00, 0x00, 0x8b, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48,
+ 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x19, 0xb1, 0x01, 0x00, 0x93, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00,
+ 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0x97, 0x00, 0xa2, 0xff,
+ 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0xfd, 0x7f, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xce, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0xfd, 0x7f, 0x01, 0x00,
+ 0x00, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x9a, 0x13, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x01, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x9a, 0x13, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x29, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x67, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xfd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xfd, 0x83, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0x80, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00, 0xe2, 0x00, 0x00, 0x40,
+ 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x46, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x40, 0x2b, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x46, 0x88, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x94, 0x8c, 0xb0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x46, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40,
+ 0x80, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0xf0, 0x01, 0x00,
+ 0xc9, 0x00, 0x82, 0x41, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfd, 0x83, 0x01, 0x00,
+ 0xd4, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44,
+ 0x80, 0xb2, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x08, 0x83, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x44,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0x30, 0x00, 0x08, 0x83, 0x98, 0x01, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40,
+ 0x89, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0x80, 0xb2, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x94, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40,
+ 0x80, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x80, 0x43, 0x89, 0xb0, 0x01, 0x00,
+ 0x03, 0x84, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x88, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x96,
+ 0x80, 0xb2, 0x00, 0x00, 0xdf, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40,
+ 0x25, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xe0, 0x01, 0x00,
+ 0xdd, 0x00, 0x00, 0x44, 0x82, 0x14, 0x01, 0x00, 0x00, 0x00, 0x90, 0x94,
+ 0x8a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x89, 0xd0, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00,
+ 0xec, 0x00, 0x08, 0x41, 0x80, 0x32, 0x00, 0x00, 0xed, 0x00, 0x00, 0x94,
+ 0x24, 0xb1, 0x00, 0x00, 0x10, 0x00, 0x00, 0x94, 0x24, 0xf5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xf2, 0x00, 0xa0, 0x44,
+ 0x89, 0x50, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xef, 0x00, 0x20, 0x44,
+ 0x89, 0x50, 0x00, 0x00, 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42,
+ 0x89, 0xd0, 0x00, 0x00, 0xf7, 0x00, 0xa0, 0xfa, 0x8a, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xf5, 0x00, 0xa3, 0x42,
+ 0x89, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x45, 0x8a, 0xf4, 0x01, 0x00, 0xfc, 0x00, 0x90, 0x44,
+ 0x8a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x45, 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50,
+ 0x8b, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0x00, 0x30, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x08, 0x83, 0x14, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x94, 0x2a, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0xf9, 0x9b, 0x01, 0x00, 0xdd, 0x00, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x40, 0x94, 0x80, 0xb2, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44,
+ 0x2b, 0x41, 0x01, 0x00, 0x00, 0x00, 0x41, 0x94, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x2b, 0xc1, 0x01, 0x00, 0x04, 0x01, 0x9f, 0x94, 0x80, 0x32, 0x00, 0x00,
+ 0x02, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x01, 0x00, 0x51,
+ 0x93, 0xb0, 0x00, 0x00, 0x10, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00,
+ 0x10, 0x01, 0x00, 0x49, 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x93, 0xb0, 0x01, 0x00, 0x10, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x12, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x71, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x72, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x73, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x74, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x76, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x77, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x78, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x79, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x7a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x7d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7e, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x01, 0xb0, 0x01, 0x00, 0x3b, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x47, 0x01, 0x22, 0x4b,
+ 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1,
+ 0x7e, 0xb1, 0x01, 0x00, 0x48, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x45, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x80, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x18, 0x00, 0x00, 0xaa, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x43, 0x97, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0xaa,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00,
+ 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00, 0x5a, 0x01, 0x22, 0xcc,
+ 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe1, 0xb1, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20,
+ 0x62, 0xdd, 0x01, 0x00, 0x63, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbc, 0xb3, 0x01, 0x00,
+ 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7,
+ 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0x80, 0xf4, 0x01, 0x00, 0x73, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00,
+ 0x86, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x10, 0xb1, 0x00, 0x00, 0x87, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x88, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc4, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x82, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x83, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xb8, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x28, 0x00, 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00,
+ 0xd5, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xd6, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x28, 0x00, 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00,
+ 0x72, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x28, 0x00, 0x55, 0x01, 0x51, 0x49,
+ 0xfd, 0x93, 0x28, 0x00, 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x2a, 0x00,
+ 0x55, 0x01, 0x55, 0x49, 0xfd, 0x83, 0x2a, 0x00, 0x55, 0x01, 0x56, 0x4a,
+ 0xfd, 0x83, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x2a, 0x00,
+ 0x55, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x82,
+ 0x80, 0x30, 0x2a, 0x00, 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0xb3, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0x92, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xd1, 0x01, 0x00, 0x9a, 0x01, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x96, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x50, 0x01, 0x00, 0x41,
+ 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0xb3, 0x01, 0x00,
+ 0x50, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00,
+ 0xb5, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x42, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x42, 0xff,
+ 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xff,
+ 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4, 0x80, 0xcc, 0x01, 0x00,
+ 0xaa, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x85, 0xc0, 0x01, 0x00, 0xa8, 0x01, 0xa2, 0x4c, 0x81, 0x50, 0x00, 0x00,
+ 0xb4, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x01, 0x22, 0x41,
+ 0xa5, 0x6f, 0x00, 0x00, 0x50, 0x01, 0xa2, 0xe0, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, 0x80, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x88, 0x94, 0x01, 0x00, 0x55, 0x01, 0x00, 0x44, 0xe0, 0xb1, 0x00, 0x00,
+ 0xb1, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x5b,
+ 0x89, 0x90, 0x00, 0x00, 0xa8, 0x9f, 0x00, 0xa0, 0x9e, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0xbe, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0xb9, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x43,
+ 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x40, 0xf8, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40,
+ 0xe1, 0xb1, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xcb, 0x01, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00,
+ 0xd1, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x53, 0x01, 0x00, 0xde,
+ 0xa1, 0xb3, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe5, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x52, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0xa1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0xdb, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00,
+ 0xda, 0x01, 0x84, 0x41, 0x81, 0x40, 0x00, 0x00, 0xde, 0x01, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00,
+ 0xd5, 0x01, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0xda, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3,
+ 0xa7, 0xcb, 0x01, 0x00, 0xf8, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x53, 0x01, 0x00, 0xde,
+ 0xa1, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0x81, 0x90, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xba,
+ 0x80, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00,
+ 0xe8, 0x01, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x52, 0x01, 0x00, 0x40,
+ 0xe0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00,
+ 0x6b, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x4d,
+ 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xe5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf9, 0xb3, 0x01, 0x00, 0xf9, 0x01, 0x22, 0x40,
+ 0x8f, 0x6f, 0x00, 0x00, 0x78, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x60, 0x02, 0x00, 0xc7, 0x83, 0x30, 0x01, 0x00, 0x80, 0x02, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe8, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xed, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xba,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xf0, 0xb1, 0x01, 0x00,
+ 0x0c, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0x90, 0x01, 0x00, 0x0e, 0x02, 0xb9, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00, 0x10, 0x02, 0xba, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x81, 0x90, 0x01, 0x00,
+ 0x12, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x81, 0x90, 0x01, 0x00, 0x14, 0x02, 0xbc, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00, 0x16, 0x02, 0xbd, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x81, 0x90, 0x01, 0x00,
+ 0x18, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x81, 0x90, 0x01, 0x00, 0x1a, 0x02, 0xbf, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00, 0x1c, 0x02, 0xc8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0x90, 0x01, 0x00,
+ 0x1e, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x81, 0x90, 0x01, 0x00, 0x20, 0x02, 0xca, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00, 0x22, 0x02, 0xcb, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x81, 0x90, 0x01, 0x00,
+ 0x24, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x81, 0x90, 0x01, 0x00, 0x26, 0x02, 0xcd, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00, 0x28, 0x02, 0xce, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0x90, 0x01, 0x00,
+ 0x2a, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x81, 0x90, 0x01, 0x00, 0x2c, 0x02, 0xf0, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x81, 0x90, 0x01, 0x00, 0x2e, 0x02, 0xf1, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x81, 0x90, 0x01, 0x00,
+ 0x30, 0x02, 0xf2, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x81, 0x90, 0x01, 0x00, 0x32, 0x02, 0xf3, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0x81, 0x90, 0x01, 0x00, 0x34, 0x02, 0xf4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0x90, 0x01, 0x00,
+ 0x36, 0x02, 0xf5, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x81, 0x90, 0x01, 0x00, 0x38, 0x02, 0xf6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x56, 0x81, 0x90, 0x01, 0x00, 0x3a, 0x02, 0xf7, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0x90, 0x01, 0x00,
+ 0x3c, 0x02, 0xf8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x81, 0x90, 0x01, 0x00, 0x3e, 0x02, 0xf9, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x59, 0x81, 0x90, 0x01, 0x00, 0x40, 0x02, 0xfa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x81, 0x90, 0x01, 0x00,
+ 0x42, 0x02, 0xfb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x81, 0x90, 0x01, 0x00, 0x44, 0x02, 0xfc, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x81, 0x90, 0x01, 0x00, 0x46, 0x02, 0xfd, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x81, 0x90, 0x01, 0x00,
+ 0x48, 0x02, 0xfe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x81, 0x90, 0x01, 0x00, 0x4a, 0x02, 0xff, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00,
+ 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00,
+ 0xdb, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x66, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x63, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5f, 0x02, 0x49, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x68, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x5f, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1,
+ 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4,
+ 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99,
+ 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5,
+ 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7,
+ 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x84, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x88, 0x02, 0x00, 0x40,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00,
+ 0x8d, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00,
+ 0x9b, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x42,
+ 0xa5, 0x63, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x97, 0x02, 0x22, 0x44,
+ 0xa5, 0x53, 0x00, 0x00, 0x94, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xe8, 0x02, 0x00, 0xde,
+ 0xa1, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xbf, 0xb3, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde,
+ 0x63, 0xb1, 0x01, 0x00, 0x9e, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x54,
+ 0xa5, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00,
+ 0xac, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x46,
+ 0x83, 0x30, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8,
+ 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb,
+ 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xbd, 0x02, 0x00, 0x40,
+ 0x10, 0xc9, 0x00, 0x00, 0xc3, 0x02, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcb, 0x02, 0x00, 0x05,
+ 0x81, 0xb0, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd0, 0x02, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x44,
+ 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1,
+ 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0xc4, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x00, 0xc2,
+ 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00,
+ 0xc8, 0x02, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd4, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xe2, 0x02, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8,
+ 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3,
+ 0xf1, 0xb1, 0x01, 0x00, 0xe1, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc,
+ 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0xfa, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf9, 0x02, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x41,
+ 0x99, 0xb3, 0x01, 0x00, 0x0a, 0x03, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00,
+ 0x12, 0x03, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x0c, 0x03, 0x22, 0x4c,
+ 0x81, 0x6c, 0x00, 0x00, 0x16, 0x03, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00,
+ 0x17, 0x03, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x19, 0x03, 0x22, 0x58,
+ 0x81, 0x6c, 0x00, 0x00, 0x1e, 0x03, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
+ 0x09, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xf3, 0x83, 0x01, 0x00, 0x10, 0x03, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x22, 0xca,
+ 0x07, 0x14, 0x00, 0x00, 0xdd, 0x9f, 0x00, 0x45, 0xf3, 0x93, 0x00, 0x00,
+ 0xdd, 0x9f, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xdd, 0x9f, 0x80, 0xca,
+ 0x05, 0x30, 0x00, 0x00, 0xdd, 0x9f, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00,
+ 0xdd, 0x9f, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc,
+ 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca,
+ 0x81, 0x88, 0x01, 0x00, 0xdd, 0x9f, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00,
+ 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x1b, 0x03, 0xa8, 0xb1,
+ 0x82, 0x30, 0x00, 0x00, 0x1a, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdd, 0x9f, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x22, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x2d, 0x03, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40,
+ 0x80, 0xce, 0x01, 0x00, 0x2b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x2d, 0x03, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x32, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x3d, 0x03, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89,
+ 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00,
+ 0x3b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3d, 0x03, 0x55, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xb5, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00,
+ 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x30, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x90, 0x00, 0xf8,
+ 0x80, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf2, 0x88, 0xe4, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x4d, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x50, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x23, 0x91, 0x01, 0x00, 0x53, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0x55, 0x03, 0x1f, 0x91,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x80, 0x40, 0x20, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x8f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00,
+ 0x5a, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x47,
+ 0x8e, 0xc8, 0x01, 0x00, 0x58, 0x03, 0x00, 0x5c, 0x8f, 0x80, 0x00, 0x00,
+ 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x58, 0x15, 0x2d, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, 0x82, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x82, 0x94, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8d, 0xc0, 0x01, 0x00, 0x74, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00,
+ 0x65, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x63, 0x03, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43, 0x86, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00, 0x70, 0x03, 0x00, 0x41,
+ 0x83, 0xe0, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00, 0xd0, 0x14, 0x2f, 0x46,
+ 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42, 0x60, 0x99, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x07, 0x00, 0x00, 0x45, 0x80, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x85, 0x03, 0xa0, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x83, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x8e, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0x00, 0x39, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x8b, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x44,
+ 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00,
+ 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x39, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00,
+ 0x95, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x97, 0x03, 0x22, 0x5a,
+ 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x98, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x90, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6,
+ 0x90, 0xb0, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0x8a, 0xb0, 0x01, 0x00, 0x80, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0xac, 0x03, 0x22, 0x40,
+ 0x82, 0x6c, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x58, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x8d, 0xc0, 0x01, 0x00, 0xb5, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00,
+ 0xa7, 0x03, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0xa5, 0x03, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0xa6, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x9f, 0x00, 0x47,
+ 0x80, 0x30, 0x01, 0x00, 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00,
+ 0xb0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x50, 0xb3, 0x01, 0x00, 0xbb, 0x03, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00,
+ 0xbe, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6,
+ 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x50, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x4e, 0xd3, 0x01, 0x00, 0x6e, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x82, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00,
+ 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc7, 0x03, 0x22, 0xa7,
+ 0x8f, 0x6c, 0x00, 0x00, 0x5a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xc4, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa0, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xca,
+ 0xa7, 0x33, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x03, 0x22, 0x42,
+ 0x75, 0x6f, 0x00, 0x00, 0xd8, 0x03, 0x22, 0x41, 0x75, 0x6f, 0x00, 0x00,
+ 0xda, 0x03, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xdc, 0x03, 0x1f, 0xca,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x42, 0x75, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xcd, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x41, 0x75, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40,
+ 0x75, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0xc6, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, 0x75, 0xb3, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x45, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00,
+ 0x45, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x45, 0x01, 0x00, 0x4c,
+ 0x93, 0x30, 0x01, 0x00, 0xec, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2,
+ 0xa0, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40,
+ 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44,
+ 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43,
+ 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xa5, 0xc3, 0x01, 0x00, 0x0b, 0x04, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00,
+ 0x0b, 0x04, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xfa, 0x03, 0xa2, 0x50,
+ 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb,
+ 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00,
+ 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00,
+ 0x08, 0x04, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x07, 0x04, 0xa2, 0xf2,
+ 0x80, 0x30, 0x00, 0x00, 0xfa, 0x03, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00,
+ 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00,
+ 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xff, 0xff, 0x00, 0x94, 0xb4, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd9,
+ 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00,
+ 0xdd, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x94,
+ 0xb4, 0xb3, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x27, 0xb1, 0x01, 0x00, 0x06, 0xc0, 0x00, 0x40, 0x2d, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x02, 0xc4, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x40, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x05, 0x82, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00,
+ 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2d, 0x04, 0x80, 0x94,
+ 0x80, 0x32, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x28, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x40,
+ 0x2d, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x31, 0x04, 0x00, 0x12,
+ 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x4b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x50, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x56, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x5b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x60, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x65, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x6b, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x70, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x75, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x7a, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x59, 0x04, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x82, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x84, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x86, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x88, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x8c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8e, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x90, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x92, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x94, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x96, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x98, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9a, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0x9e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa0, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa2, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xa4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa6, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa8, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xaa, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xac, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xae, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xb0, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb2, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xb6, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb8, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x00, 0xba, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00,
+ 0x00, 0xbc, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xbe, 0x80, 0x40,
+ 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x82, 0x04, 0x85, 0x41,
+ 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00,
+ 0x87, 0x04, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x90, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xb1, 0x01, 0x00,
+ 0xff, 0xff, 0xf0, 0x4b, 0x82, 0x89, 0x01, 0x00, 0x93, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x80, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0xf0, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x96, 0x04, 0x60, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0xf0, 0xc2, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b, 0x92, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x80, 0xa6,
+ 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x94, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x88, 0x94, 0x01, 0x00, 0xa6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xad, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xa6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xb0, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x62, 0xb1, 0x01, 0x00, 0xb1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xb8, 0x04, 0x22, 0x4b, 0x89, 0x7c, 0x00, 0x00, 0xb6, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xb6, 0x04, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xc1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xc6, 0x04, 0x22, 0x4b,
+ 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xc4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xc1, 0x04, 0xa2, 0x41,
+ 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x99, 0xe0, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x4c,
+ 0x88, 0x94, 0x00, 0x00, 0xd6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xdd, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xe0, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x62, 0xb1, 0x01, 0x00, 0xe1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xe8, 0x04, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0xe6, 0x04, 0x22, 0x4f,
+ 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x04, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xf1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xf6, 0x04, 0x22, 0x4a,
+ 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xf4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xf1, 0x04, 0xa2, 0x41,
+ 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x00, 0x05, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x12, 0x05, 0x1d, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x10, 0x05, 0xa2, 0x40,
+ 0x86, 0x04, 0x00, 0x00, 0xde, 0x9f, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50,
+ 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00,
+ 0x0c, 0x05, 0x52, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x05, 0x00, 0x40,
+ 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0x30, 0x05, 0x00, 0x05,
+ 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x1b, 0x00, 0xde, 0x9f, 0x00, 0x41,
+ 0xe1, 0xc1, 0x1a, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x1b, 0x00,
+ 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x1a, 0x00, 0x14, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x1a, 0x00, 0x00, 0x82, 0x00, 0xb3, 0x67, 0xdf, 0x1b, 0x00,
+ 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x1b, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x1b, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0x27, 0x05, 0x0f, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40,
+ 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00,
+ 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0x1f, 0x05, 0x99, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00,
+ 0x21, 0x05, 0x9b, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x89, 0xd0, 0x01, 0x00, 0x23, 0x05, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00,
+ 0x30, 0x05, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x89, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x58, 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00,
+ 0x6f, 0x00, 0x00, 0x43, 0x86, 0x88, 0x01, 0x00, 0xde, 0x9f, 0x26, 0x05,
+ 0x47, 0x31, 0x00, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00,
+ 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x07,
+ 0x91, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x97, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x44, 0x05, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0x45, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0x10, 0x04, 0x00, 0x42,
+ 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xf5, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda,
+ 0xf7, 0xf5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x8f, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48,
+ 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x91, 0xc0, 0x01, 0x00, 0x50, 0x05, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda,
+ 0x8f, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda,
+ 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x7a, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x78, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0x7d, 0x05, 0x22, 0x20, 0xb5, 0x6f, 0x00, 0x00, 0x7a, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x1f, 0x00,
+ 0x7d, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x1e, 0x00, 0x7a, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x1f, 0x00,
+ 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x1e, 0x00, 0x54, 0x16, 0x00, 0x40,
+ 0x47, 0x99, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x46, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00,
+ 0x48, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x97, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda,
+ 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00,
+ 0x90, 0x05, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40,
+ 0xa5, 0x9b, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb,
+ 0x85, 0x30, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb8, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x05, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xaa, 0x05, 0xa2, 0x41,
+ 0x83, 0x50, 0x00, 0x00, 0xa9, 0x05, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb0, 0x05, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00,
+ 0xb1, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xb3, 0x9b, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x05, 0xa2, 0xfa,
+ 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00,
+ 0xb8, 0x05, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42,
+ 0xb3, 0x43, 0x01, 0x00, 0xbb, 0x05, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00,
+ 0xb8, 0x05, 0x42, 0x40, 0x81, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x67, 0x93, 0x21, 0x00, 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x20, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0xdb, 0x9f, 0x00, 0x40,
+ 0x49, 0x31, 0x21, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x21, 0x00,
+ 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0x00, 0x00, 0x6e, 0xfa,
+ 0x8e, 0xb0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xb4, 0xb3, 0x01, 0x00, 0xc9, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0xfc, 0x15, 0x20, 0x20, 0xe1, 0xb1, 0x01, 0x00, 0xce, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x24, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x25, 0x00,
+ 0xce, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x24, 0x00, 0xcb, 0x05, 0x42, 0x40,
+ 0x81, 0x32, 0x24, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x25, 0x00,
+ 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x24, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x25, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x25, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd3, 0x05, 0x22, 0x50,
+ 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x4a, 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x4a, 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe9, 0x05, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00,
+ 0xea, 0x05, 0x00, 0x50, 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xb5, 0xb3, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0xfc, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06,
+ 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0xff, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00,
+ 0x02, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x08, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00,
+ 0x14, 0x06, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70,
+ 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00,
+ 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6,
+ 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00,
+ 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73,
+ 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00,
+ 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf7, 0xb1, 0x01, 0x00, 0x25, 0x06, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47,
+ 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0x2e, 0x06, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41,
+ 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00,
+ 0x4b, 0x06, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40,
+ 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00,
+ 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75,
+ 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00,
+ 0x55, 0x06, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x5a, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x89, 0xa4, 0x01, 0x00, 0x64, 0x06, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00,
+ 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x57, 0x06, 0xaa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00,
+ 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x6b, 0x06, 0xa3, 0x53,
+ 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00,
+ 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x70, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6,
+ 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00,
+ 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41,
+ 0x80, 0xce, 0x01, 0x00, 0x75, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42,
+ 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00,
+ 0x37, 0x06, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75,
+ 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78,
+ 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00,
+ 0x2b, 0x06, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00,
+ 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0xa2, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x7c, 0x16, 0x20, 0xf6, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x31, 0xb3, 0x01, 0x00, 0x9d, 0x06, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x51, 0xfd, 0x93, 0x01, 0x00, 0x9f, 0x06, 0x22, 0x40,
+ 0x8f, 0x7c, 0x00, 0x00, 0xa3, 0x06, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00,
+ 0xa1, 0x06, 0x22, 0x42, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0xfd, 0x93, 0x01, 0x00, 0xa3, 0x06, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x53, 0xfd, 0x93, 0x01, 0x00, 0xb7, 0x06, 0x22, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb2, 0x06, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x4b, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xb6, 0x06, 0x22, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0xba, 0x06, 0x00, 0x54,
+ 0xfd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0xfe, 0x7f, 0xd9, 0x01, 0x00, 0xba, 0x06, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe7, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc4, 0x06, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xe9, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4,
+ 0x0c, 0xc8, 0x01, 0x00, 0xea, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x0a, 0x07, 0x22, 0x01,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0xd9, 0x06, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00,
+ 0xda, 0x06, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xec, 0x06, 0x22, 0x40,
+ 0x03, 0x6c, 0x00, 0x00, 0xe6, 0x06, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x23, 0x07, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x23, 0x07, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0xee, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00,
+ 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0xfa, 0x06, 0x23, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00,
+ 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d,
+ 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x02, 0x07, 0x22, 0x1a,
+ 0x02, 0x50, 0x00, 0x00, 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14,
+ 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x23, 0x07, 0x00, 0x1a,
+ 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x0f, 0x07, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00,
+ 0x10, 0x07, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x12,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, 0x16, 0x94, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x17, 0x07, 0xa8, 0x5c,
+ 0x1f, 0x10, 0x00, 0x00, 0x40, 0x07, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00,
+ 0x40, 0x07, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x07, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00,
+ 0x23, 0x07, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x1f, 0x07, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x3f, 0x07, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x2e, 0x07, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x2c, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x29, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x04, 0xb0, 0x01, 0x00, 0x33, 0x07, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00,
+ 0xd3, 0x06, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f,
+ 0x0f, 0x80, 0x01, 0x00, 0xd3, 0x06, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x3c, 0x07, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0xd3, 0x06, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x0d,
+ 0x18, 0xc0, 0x00, 0x00, 0x5f, 0x07, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00,
+ 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50,
+ 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d,
+ 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00,
+ 0x52, 0x07, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x91, 0xc0, 0x01, 0x00, 0x50, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0x96, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x18, 0x90, 0xb0, 0x01, 0x00, 0x5c, 0x07, 0xa0, 0xfc,
+ 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00,
+ 0x5a, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x80, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x2d, 0x00,
+ 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x48, 0xc1, 0x2d, 0x00, 0x64, 0x07, 0x43, 0x30, 0x3d, 0x07, 0x2c, 0x00,
+ 0x00, 0x00, 0x00, 0x9e, 0x85, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x41,
+ 0x3d, 0xc3, 0x2d, 0x00, 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x2d, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d,
+ 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x80, 0xc0, 0x01, 0x00, 0x6e, 0x07, 0xa0, 0x41,
+ 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30,
+ 0x81, 0x84, 0x01, 0x00, 0x72, 0x07, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x93, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x19, 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e,
+ 0x16, 0xc0, 0x01, 0x00, 0x78, 0x07, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e,
+ 0x32, 0xc0, 0x01, 0x00, 0x7d, 0x07, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00,
+ 0x7c, 0x07, 0xa0, 0x1c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e,
+ 0x98, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00,
+ 0x0c, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x8b, 0x07, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x89, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x86, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x1a, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00,
+ 0x91, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x07, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x9b, 0x07, 0x22, 0xf2,
+ 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x98, 0x07, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xeb, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xa1, 0x07, 0x90, 0xf2,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14,
+ 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xac, 0x07, 0x22, 0xf2, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xa9, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00,
+ 0xc9, 0x07, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00, 0xb4, 0x07, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00,
+ 0xb3, 0x07, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88,
+ 0x1c, 0xcc, 0x01, 0x00, 0xe4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x3f, 0xc3, 0x01, 0x00, 0xe6, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb7, 0x07, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x3e, 0xc0, 0x01, 0x00, 0xc9, 0x07, 0x22, 0x40,
+ 0x15, 0x6c, 0x00, 0x00, 0xba, 0x07, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x3c, 0xb0, 0x01, 0x00, 0xe5, 0x9f, 0x00, 0x1e,
+ 0x24, 0x30, 0x01, 0x00, 0xbf, 0x07, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a,
+ 0x10, 0xc0, 0x01, 0x00, 0x23, 0x07, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00,
+ 0xe4, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe5, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xbc, 0x07, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0xe8, 0x9f, 0x00, 0x1f,
+ 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00,
+ 0xe6, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x07, 0xa2, 0x41,
+ 0x87, 0x7c, 0x00, 0x00, 0xcf, 0x07, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1f, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0xe8, 0x9f, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00,
+ 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x07, 0x00, 0xbc, 0x80, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00,
+ },
+ {
+ 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80,
+ 0x80, 0x32, 0x00, 0x00, 0x0e, 0x87, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2,
+ 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00,
+ 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81,
+ 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x0e, 0x87, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42,
+ 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00,
+ 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48,
+ 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53,
+ 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00,
+ 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52,
+ 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00,
+ 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xaf, 0x82, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xaf, 0x82, 0x05, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0xde, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40,
+ 0x9b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00,
+ 0x48, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44,
+ 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x24, 0xb1, 0x01, 0x00, 0x00, 0x0c, 0x00, 0xee,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x97, 0xf0, 0x01, 0x00,
+ 0x44, 0x80, 0xa2, 0x43, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xfd, 0x93, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00,
+ 0xd0, 0x14, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x00, 0x06, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x05, 0x10, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00,
+ 0x02, 0x09, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0xf5, 0x99, 0x01, 0x00, 0x60, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x88, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa0, 0x03, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xa2, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x9a, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x91, 0xb3, 0x01, 0x00, 0xe0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x27, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x90, 0x06, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x2f, 0x81, 0x01, 0x00, 0x8d, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xe5, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xdd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x00, 0x00,
+ 0x6c, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0xb4,
+ 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x18, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x40, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7d, 0x80, 0x22, 0x40,
+ 0x97, 0x6c, 0x00, 0x00, 0x7a, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x80, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x80, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58,
+ 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x40, 0x05, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00, 0xc1, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x96, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x96, 0x80, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00,
+ 0x93, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00,
+ 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48,
+ 0xb2, 0xcb, 0x01, 0x00, 0xd0, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x02, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd5, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x01, 0x00, 0x41,
+ 0x81, 0xc0, 0x00, 0x00, 0x55, 0x01, 0x51, 0x48, 0xfd, 0x93, 0x00, 0x00,
+ 0x55, 0x01, 0x52, 0x48, 0xfd, 0x93, 0x00, 0x00, 0x55, 0x01, 0x55, 0x49,
+ 0xfd, 0x83, 0x00, 0x00, 0x55, 0x01, 0x56, 0x4a, 0xfd, 0x83, 0x00, 0x00,
+ 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x00, 0x00, 0x55, 0x01, 0x45, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00,
+ 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00,
+ 0xb4, 0x80, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00, 0xbf, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x98, 0xb0, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0xc7, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04, 0x80, 0x94, 0x00, 0x00,
+ 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03, 0x02, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb,
+ 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xf3, 0x83, 0x01, 0x00,
+ 0xd1, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb,
+ 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xd8, 0x80, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xf9, 0x02, 0x00, 0x20, 0x42, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x80, 0xcb,
+ 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41, 0x8b, 0xb3, 0x01, 0x00,
+ 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xde, 0x80, 0xa8, 0xb1,
+ 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xe0, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00, 0xe6, 0x80, 0x14, 0xc6,
+ 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6, 0x83, 0xf4, 0x01, 0x00,
+ 0xf4, 0x82, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00, 0xc2, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6, 0x81, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00, 0xc2, 0x80, 0x1f, 0x5c,
+ 0x97, 0x53, 0x00, 0x00, 0x58, 0x82, 0x1e, 0xc6, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x2f, 0x43, 0x81, 0xf0, 0x01, 0x00, 0xec, 0x80, 0x00, 0x40,
+ 0x10, 0xc9, 0x00, 0x00, 0x39, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x6a, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x24, 0x82, 0x00, 0xca,
+ 0x63, 0xb3, 0x00, 0x00, 0x61, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x48, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, 0x52, 0x81, 0x00, 0x4e,
+ 0x61, 0xb1, 0x00, 0x00, 0x41, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00,
+ 0x48, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, 0x24, 0x81, 0x00, 0x40,
+ 0x85, 0xb0, 0x00, 0x00, 0xe3, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0x71, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0xdf, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x41, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00,
+ 0xf0, 0x03, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca,
+ 0x9b, 0xb3, 0x00, 0x00, 0x7b, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x7f, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x86, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x87, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00,
+ 0x88, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x89, 0x81, 0x00, 0x40,
+ 0xc1, 0xb1, 0x00, 0x00, 0x8a, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00,
+ 0x8a, 0x81, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x18, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x97, 0x82, 0x00, 0xbb, 0xab, 0xb3, 0x00, 0x00,
+ 0x25, 0x82, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x26, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0x77, 0xb3, 0x00, 0x00, 0x49, 0x81, 0x00, 0x4d,
+ 0x83, 0xb0, 0x00, 0x00, 0x50, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00,
+ 0x41, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x49, 0x81, 0x00, 0x4c,
+ 0x83, 0xb0, 0x00, 0x00, 0x41, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00,
+ 0x24, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x16, 0x81, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, 0x4d, 0xb3, 0x00, 0x00,
+ 0x70, 0x05, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x40,
+ 0x49, 0xb1, 0x00, 0x00, 0x1c, 0x81, 0x22, 0x42, 0x8f, 0x6f, 0x00, 0x00,
+ 0x1e, 0x81, 0x22, 0x41, 0x8f, 0x6f, 0x00, 0x00, 0x20, 0x81, 0x1e, 0xca,
+ 0x81, 0x32, 0x00, 0x00, 0x22, 0x81, 0x1f, 0xca, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x42,
+ 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xcd, 0xb1, 0x01, 0x00,
+ 0xf4, 0x82, 0x00, 0x41, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xcf, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00,
+ 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00,
+ 0xf4, 0x82, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x10, 0x00, 0x2f, 0x9c, 0x89, 0xb0, 0x01, 0x00,
+ 0x3b, 0x81, 0x00, 0x40, 0x39, 0x33, 0x01, 0x00, 0x18, 0x00, 0x2f, 0x9b,
+ 0x89, 0xb0, 0x01, 0x00, 0x3b, 0x81, 0x00, 0x40, 0x37, 0x33, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x9a, 0x89, 0xb0, 0x01, 0x00, 0x3b, 0x81, 0x00, 0x40,
+ 0x35, 0x33, 0x01, 0x00, 0x08, 0x00, 0x2f, 0x99, 0x89, 0xb0, 0x01, 0x00,
+ 0x3b, 0x81, 0x00, 0x40, 0x33, 0x33, 0x01, 0x00, 0x00, 0x80, 0x00, 0xae,
+ 0x47, 0xc9, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xae,
+ 0x63, 0xdd, 0x01, 0x00, 0x36, 0x81, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x33, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x81, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x69, 0x93, 0x01, 0x00,
+ 0xf4, 0x82, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0x39, 0x81, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x38, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x40, 0x81, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, 0xe1, 0xd1, 0x01, 0x00,
+ 0x41, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x62, 0xb1, 0x01, 0x00, 0x45, 0x81, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x42, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0x63, 0xb1, 0x01, 0x00, 0x45, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xf4, 0x82, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4a, 0x81, 0x00, 0x40,
+ 0x81, 0xb0, 0x00, 0x00, 0x4a, 0x81, 0x00, 0xbb, 0x81, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x60, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0x4b, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x4d, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x53, 0x81, 0x00, 0xbb,
+ 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40, 0x87, 0xb0, 0x01, 0x00,
+ 0x55, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00, 0xf4, 0x82, 0x60, 0x40,
+ 0x95, 0x83, 0x00, 0x00, 0x02, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x56, 0x81, 0x36, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x62, 0xb1, 0x01, 0x00, 0x57, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00, 0x59, 0x81, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00,
+ 0x5b, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xf4, 0x82, 0x22, 0x41, 0x43, 0x51, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0xca, 0x95, 0xcb, 0x01, 0x00, 0x56, 0x81, 0x00, 0x41,
+ 0x85, 0xc0, 0x00, 0x00, 0x63, 0x81, 0xa2, 0x42, 0x67, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00, 0x63, 0x81, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00, 0x00, 0x00, 0x1a, 0xca,
+ 0x69, 0x97, 0x01, 0x00, 0xf4, 0x82, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x68, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x82, 0x1a, 0x44,
+ 0x93, 0x93, 0x00, 0x00, 0xf4, 0x82, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00,
+ 0xf4, 0x82, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00, 0xf4, 0x82, 0x22, 0x40,
+ 0x65, 0x6f, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00,
+ 0x85, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x35, 0x80, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x95, 0x93, 0x01, 0x00, 0x77, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e,
+ 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0xc3, 0xb1, 0x01, 0x00, 0x7a, 0x81, 0x22, 0x5b,
+ 0x95, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00,
+ 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca,
+ 0x95, 0x9b, 0x01, 0x00, 0x0d, 0x01, 0x00, 0xca, 0xc5, 0x31, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca,
+ 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca,
+ 0xc7, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x22, 0x5f, 0x95, 0x7f, 0x00, 0x00,
+ 0x0d, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x95, 0x83, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca, 0xc7, 0xb1, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca,
+ 0xcb, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, 0xcd, 0xb1, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x42,
+ 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40, 0x48, 0xc9, 0x01, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x8f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x91, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00, 0x93, 0x81, 0x9f, 0x85,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x83, 0x84, 0x01, 0x00,
+ 0xc8, 0x81, 0x22, 0x30, 0x83, 0x6c, 0x00, 0x00, 0x92, 0x81, 0xa2, 0x4f,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00,
+ 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00,
+ 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0xa8, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xa5, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0xba, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6,
+ 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00,
+ 0xad, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x21, 0xb3, 0x01, 0x00, 0xba, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0xba, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x18, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x41, 0x82, 0x88, 0x01, 0x00, 0x00, 0x77, 0x00, 0x41,
+ 0x82, 0x8c, 0x01, 0x00, 0x01, 0x02, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x18, 0x00, 0x00, 0x41,
+ 0x82, 0xdc, 0x01, 0x00, 0xb8, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0xbb, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00,
+ 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0xc3, 0x81, 0x22, 0x43,
+ 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xc0, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00,
+ 0xde, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0xc5, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0xde, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x21, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x83, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00,
+ 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x83, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00,
+ 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x11, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00,
+ 0xd7, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0xda, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x40, 0x13, 0x00, 0x41,
+ 0x08, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x41, 0x2e, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00, 0xe1, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x08, 0xb1, 0x00, 0x00,
+ 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, 0xe4, 0x81, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00,
+ 0xf3, 0x81, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x02, 0x82, 0x22, 0x44,
+ 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00,
+ 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x4a,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00,
+ 0xee, 0x81, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0x90, 0x01, 0x00, 0xf0, 0x81, 0x22, 0x4f, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0xf2, 0x81, 0x22, 0x4e,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00,
+ 0x0a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x1c, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xfd, 0x81, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x87, 0x90, 0x01, 0x00, 0xff, 0x81, 0x22, 0x44, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x01, 0x82, 0x22, 0x43,
+ 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00,
+ 0x0a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x82, 0x22, 0x4b, 0x83, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xb8, 0x80, 0x00, 0xca,
+ 0xa7, 0x33, 0x01, 0x00, 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x14, 0x82, 0xa2, 0x5e,
+ 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00,
+ 0x16, 0x82, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x1b, 0x82, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00,
+ 0x1b, 0x82, 0xa2, 0x49, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xfd, 0x93, 0x01, 0x00, 0x1e, 0x82, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00,
+ 0x1e, 0x82, 0xa2, 0x4a, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xfd, 0x93, 0x01, 0x00, 0x20, 0x82, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40,
+ 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00,
+ 0x22, 0x82, 0x42, 0x40, 0xf1, 0x33, 0x00, 0x00, 0x38, 0x81, 0x00, 0x40,
+ 0x68, 0x97, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xbb, 0xb1, 0xb3, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x18, 0xb1, 0x01, 0x00, 0x2b, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x35, 0x82, 0xa2, 0x54,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x3c, 0x82, 0xa2, 0x06,
+ 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x80, 0x16, 0x2e, 0x06,
+ 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x42, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40,
+ 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00,
+ 0x45, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40,
+ 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00,
+ 0x4b, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00,
+ 0x57, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x42,
+ 0x99, 0xb3, 0x01, 0x00, 0x62, 0x82, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00,
+ 0x6a, 0x82, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x64, 0x82, 0x22, 0x4c,
+ 0x81, 0x6c, 0x00, 0x00, 0x6e, 0x82, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00,
+ 0x6f, 0x82, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x71, 0x82, 0x22, 0x58,
+ 0x81, 0x6c, 0x00, 0x00, 0x76, 0x82, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
+ 0x09, 0xb0, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xf3, 0x83, 0x01, 0x00, 0x68, 0x82, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xf4, 0x82, 0x22, 0xca,
+ 0x07, 0x14, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x46, 0xf3, 0x93, 0x00, 0x00,
+ 0xf4, 0x82, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xf4, 0x82, 0x80, 0xca,
+ 0x05, 0x30, 0x00, 0x00, 0xf4, 0x82, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc,
+ 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca,
+ 0x81, 0x88, 0x01, 0x00, 0xf4, 0x82, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00,
+ 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x73, 0x82, 0xa8, 0xb1,
+ 0x82, 0x30, 0x00, 0x00, 0x72, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00,
+ 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x79, 0x82, 0xa2, 0x41,
+ 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x84, 0x82, 0x91, 0x82,
+ 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00,
+ 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0x82, 0x82, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x84, 0x82, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53,
+ 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41,
+ 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x89, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x94, 0x82, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40,
+ 0x80, 0xce, 0x01, 0x00, 0x92, 0x82, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x94, 0x82, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40,
+ 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00,
+ 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53,
+ 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00,
+ 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40,
+ 0x99, 0xb3, 0x01, 0x00, 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00,
+ 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x9b, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xac, 0x94, 0x2e, 0x43,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x9f, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, 0xa3, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x60, 0x15, 0x00, 0x40,
+ 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x40, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x57, 0x41, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42, 0x81, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, 0xa5, 0x82, 0xa0, 0x42,
+ 0x81, 0x6c, 0x00, 0x00, 0xa5, 0x82, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00,
+ 0xdd, 0x82, 0xa2, 0x41, 0x01, 0x7d, 0x00, 0x00, 0xb5, 0x82, 0x22, 0x58,
+ 0x73, 0x7d, 0x00, 0x00, 0x78, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xb0, 0x82, 0xa8, 0xb1, 0x9c, 0x30, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45,
+ 0x9d, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0xc9, 0x00, 0x00,
+ 0xb5, 0x82, 0x33, 0xc4, 0x81, 0x30, 0x00, 0x00, 0xb8, 0x82, 0xa1, 0xad,
+ 0x9d, 0x20, 0x00, 0x00, 0xaf, 0x82, 0x13, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x13, 0x4e, 0x5a, 0x83, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45,
+ 0x9d, 0xe0, 0x01, 0x00, 0xc0, 0x82, 0x22, 0xab, 0x80, 0x04, 0x00, 0x00,
+ 0xbe, 0x82, 0xa2, 0x40, 0x01, 0x7d, 0x00, 0x00, 0xc0, 0x82, 0x22, 0x5f,
+ 0x57, 0x7d, 0x00, 0x00, 0x36, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc0, 0x82, 0x22, 0x5e, 0x57, 0x7d, 0x00, 0x00, 0x99, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x82, 0x22, 0x54, 0x73, 0x7d, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc0, 0x82, 0xa8, 0xb1,
+ 0x00, 0x30, 0x00, 0x00, 0x8a, 0x84, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00,
+ 0xca, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x82, 0xa2, 0x5f,
+ 0x59, 0x27, 0x00, 0x00, 0xc9, 0x82, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00,
+ 0xd0, 0x82, 0xa2, 0x5e, 0x73, 0x7d, 0x00, 0x00, 0xda, 0x82, 0x22, 0x5c,
+ 0x73, 0x7d, 0x00, 0x00, 0xdb, 0x82, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xca, 0x82, 0xa8, 0xb1,
+ 0x36, 0x30, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xcc, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0x01, 0x00, 0xb9, 0x84, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xdb, 0x82, 0x34, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xd1, 0x82, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00,
+ 0xd8, 0x82, 0x52, 0x21, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41,
+ 0x2f, 0xc3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x01, 0xf0, 0x01, 0x00, 0x11, 0x83, 0x00, 0x34,
+ 0x13, 0x84, 0x00, 0x00, 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00,
+ 0x6f, 0x83, 0x00, 0x43, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xdb, 0x82, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0x0e, 0x87, 0xa2, 0x48,
+ 0xfd, 0x7f, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xac, 0x80, 0x32, 0x00, 0x00,
+ 0xe3, 0x82, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xe0, 0x82, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0xcf, 0x11, 0xc9, 0x00, 0x00, 0xe9, 0x82, 0xa2, 0x40,
+ 0x93, 0x7f, 0x00, 0x00, 0xe9, 0x82, 0x22, 0x44, 0x93, 0x7f, 0x00, 0x00,
+ 0xe5, 0x82, 0x42, 0xa5, 0x80, 0x30, 0x00, 0x00, 0xe8, 0x82, 0xa2, 0x40,
+ 0x93, 0x7f, 0x00, 0x00, 0xfb, 0x82, 0x1a, 0x40, 0x93, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xdd, 0x80, 0xa2, 0x40,
+ 0x73, 0x7d, 0x00, 0x00, 0x09, 0x87, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00,
+ 0x00, 0x87, 0x22, 0x40, 0x65, 0x7d, 0x00, 0x00, 0x00, 0x05, 0xa2, 0x5b,
+ 0x73, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49, 0x33, 0x7d, 0x00, 0x00,
+ 0xf3, 0x82, 0x22, 0x48, 0x33, 0x7d, 0x00, 0x00, 0xff, 0x01, 0x00, 0x99,
+ 0x80, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xe0, 0x01, 0x00,
+ 0xa8, 0x98, 0x2f, 0x40, 0x33, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe0, 0xc1, 0x01, 0x00, 0xdd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x62, 0xb1, 0x01, 0x00,
+ 0xaf, 0x82, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf6, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x82, 0x33, 0x40, 0x1f, 0x30, 0x00, 0x00,
+ 0xaf, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0xfd, 0x82, 0xa0, 0xce,
+ 0x81, 0x50, 0x00, 0x00, 0x0f, 0x83, 0xa0, 0xcd, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1,
+ 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x83, 0x22, 0xb5, 0x81, 0x14, 0x00, 0x00,
+ 0x80, 0x15, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x01, 0x83, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb4, 0x65, 0x97, 0x01, 0x00,
+ 0xd0, 0x15, 0x2e, 0x40, 0x69, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44,
+ 0x93, 0x83, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xf1, 0xb1, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0x0a, 0x83, 0xa8, 0xa1, 0xe0, 0x31, 0x00, 0x00,
+ 0xe9, 0x82, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00, 0xe9, 0x82, 0xa2, 0x41,
+ 0x67, 0x6f, 0x00, 0x00, 0xe9, 0x82, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00,
+ 0x0f, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe9, 0x82, 0x1a, 0x40,
+ 0x93, 0x83, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09, 0x46, 0xc9, 0x01, 0x00,
+ 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x1a, 0x83, 0xa6, 0x42,
+ 0x13, 0x60, 0x00, 0x00, 0x12, 0x94, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00,
+ 0x15, 0x83, 0x61, 0x40, 0x81, 0x32, 0x00, 0x00, 0x75, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x16, 0x83, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00,
+ 0x1f, 0x94, 0x71, 0x10, 0x94, 0x30, 0x01, 0x00, 0x1b, 0x83, 0x00, 0x58,
+ 0x1f, 0x90, 0x00, 0x00, 0x05, 0x94, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00,
+ 0xee, 0x07, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x22, 0x83, 0x23, 0x4b,
+ 0xe4, 0x6d, 0x00, 0x00, 0x22, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x22, 0x00, 0x2f, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x25, 0x83, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x26, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x27, 0x83, 0x85, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x47, 0xc1, 0x01, 0x00,
+ 0x2c, 0x83, 0x22, 0x55, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x43, 0xd1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x97, 0xe0, 0x01, 0x00, 0x2d, 0x83, 0x00, 0x4b,
+ 0x44, 0xc1, 0x00, 0x00, 0x12, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa1,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x28, 0xf0, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x2a, 0xb0, 0x01, 0x00,
+ 0xc0, 0x28, 0x3c, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x44,
+ 0x95, 0xb0, 0x01, 0x00, 0x39, 0x83, 0xa2, 0xf8, 0x0e, 0x30, 0x00, 0x00,
+ 0x49, 0x83, 0x22, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0x35, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x36, 0x83, 0xa2, 0xf8, 0x16, 0x6c, 0x00, 0x00, 0x36, 0x83, 0xa2, 0xf8,
+ 0x10, 0x6c, 0x00, 0x00, 0x36, 0x83, 0xa2, 0xf0, 0x1a, 0x6c, 0x00, 0x00,
+ 0x47, 0x83, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0x3e, 0x83, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x42, 0x83, 0xa2, 0xf3, 0x74, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xe6, 0x95, 0x01, 0x00, 0x47, 0x83, 0x75, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x96, 0xb0, 0x01, 0x00, 0x3f, 0x00, 0x75, 0xf3,
+ 0x0c, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x45, 0x83, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x47, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x4f, 0x83, 0x77, 0x41, 0x2d, 0xc3, 0x00, 0x00, 0x4d, 0x83, 0x22, 0x58,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x62, 0xb1, 0x01, 0x00, 0x4b, 0x83, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x4d, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x7c, 0x83, 0x77, 0x41, 0x2d, 0xc3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00,
+ 0x5d, 0x83, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x55, 0x83, 0x22, 0x42,
+ 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x5c, 0x83, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0xcc, 0x93, 0x00, 0x5f,
+ 0x01, 0x10, 0x01, 0x00, 0x5b, 0x83, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00,
+ 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0x65, 0x83, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x65, 0x83, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0x62, 0x83, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x68, 0x83, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x45,
+ 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00,
+ 0x6c, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x4b,
+ 0x95, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x4b, 0x8f, 0xb0, 0x00, 0x00,
+ 0xd8, 0x93, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00, 0xb4, 0x91, 0x00, 0x40,
+ 0x81, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x50,
+ 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x77, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10,
+ 0x62, 0xc9, 0x01, 0x00, 0x79, 0x83, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x2e, 0x47,
+ 0x97, 0x90, 0x01, 0x00, 0x8f, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00,
+ 0x8d, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x8d, 0x83, 0x23, 0xa2,
+ 0x02, 0x6c, 0x00, 0x00, 0x41, 0x93, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x00,
+ 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00, 0xac, 0x83, 0x00, 0x5c,
+ 0x17, 0x90, 0x00, 0x00, 0xa1, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x9a, 0x83, 0x22, 0x5f,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x96, 0x83, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x97, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x72, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6, 0x80, 0x88, 0x01, 0x00,
+ 0x9e, 0x83, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00, 0xa1, 0x83, 0x00, 0xf2,
+ 0x3a, 0xb0, 0x00, 0x00, 0x87, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xac, 0x83, 0x22, 0x4a, 0x2f, 0x7c, 0x00, 0x00,
+ 0xac, 0x83, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00, 0x0a, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2, 0x86, 0x88, 0x01, 0x00,
+ 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00, 0x05, 0x00, 0x00, 0x43,
+ 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42, 0x81, 0xe0, 0x01, 0x00,
+ 0xac, 0x83, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00, 0x87, 0x84, 0xa2, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x83, 0x69, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x09, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x79, 0x41, 0x47, 0xc3, 0x01, 0x00, 0xb2, 0x83, 0x22, 0xa1,
+ 0x09, 0x6c, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xaf, 0x83, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0xeb, 0x83, 0xa3, 0x92,
+ 0x03, 0x6c, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x2a, 0x87, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0xb8, 0x83, 0x22, 0x5c, 0x17, 0x7c, 0x00, 0x00,
+ 0xb9, 0x83, 0x00, 0x00, 0x2a, 0xb0, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x2a, 0xc8, 0x01, 0x00, 0x02, 0x00, 0x00, 0x08, 0x80, 0xc8, 0x01, 0x00,
+ 0xbd, 0x83, 0xa2, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0xcc, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd9, 0x83, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x4c,
+ 0x03, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00,
+ 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01,
+ 0xf0, 0xcd, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xc6, 0x83, 0xa8, 0x54,
+ 0x17, 0x10, 0x00, 0x00, 0xd9, 0x83, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0xd8, 0x83, 0x22, 0x43,
+ 0x2f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x03, 0xb0, 0x01, 0x00, 0xed, 0x94, 0x00, 0x43,
+ 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00,
+ 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01,
+ 0xf0, 0xcd, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x09, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xd9, 0x83, 0x28, 0x54,
+ 0x17, 0x10, 0x00, 0x00, 0xd5, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xdb, 0x83, 0x22, 0x50,
+ 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00, 0xde, 0x83, 0xa2, 0x41,
+ 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xdf, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd4, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe6, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x16, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d,
+ 0xe4, 0xb1, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00,
+ 0xe9, 0x83, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x90, 0x91, 0x00, 0x01,
+ 0x38, 0x43, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x83, 0xa2, 0x4b,
+ 0xfd, 0x7f, 0x00, 0x00, 0x84, 0x84, 0x00, 0x41, 0x43, 0xc3, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0xef, 0x83, 0x35, 0x01, 0x86, 0x30, 0x00, 0x00,
+ 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xf6, 0x83, 0x28, 0xb1,
+ 0x30, 0x30, 0x00, 0x00, 0xf0, 0x83, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00,
+ 0x74, 0x84, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x43, 0xc3, 0x01, 0x00, 0x83, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xf6, 0x83, 0xa8, 0xb1,
+ 0x12, 0x30, 0x00, 0x00, 0xff, 0x83, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0xb0, 0x01, 0x00,
+ 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00, 0xf0, 0x83, 0xaa, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x04, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00, 0xf0, 0x83, 0xa3, 0x0b,
+ 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x1b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40, 0x39, 0xb0, 0x01, 0x00,
+ 0x0c, 0x84, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x22, 0x00, 0x00, 0x08,
+ 0x12, 0xc8, 0x01, 0x00, 0xde, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00,
+ 0x0f, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x20, 0x01, 0xe0, 0xb1, 0x01, 0x00,
+ 0xee, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0x14, 0x84, 0x23, 0x01,
+ 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00,
+ 0x1f, 0x84, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x1b, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x18, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb8, 0x92, 0x00, 0x43,
+ 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00,
+ 0x2e, 0x84, 0x22, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x25, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x4c,
+ 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x37, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00, 0x14, 0x84, 0x00, 0x45,
+ 0x1f, 0x80, 0x00, 0x00, 0x30, 0x84, 0xa3, 0x12, 0x36, 0x6c, 0x00, 0x00,
+ 0x31, 0x84, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12,
+ 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x34, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x5a, 0x84, 0x22, 0x14,
+ 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x14,
+ 0x12, 0xc0, 0x01, 0x00, 0x53, 0x84, 0xa2, 0x14, 0x36, 0x50, 0x00, 0x00,
+ 0x44, 0x84, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x42, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x3f, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x2b, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00,
+ 0x49, 0x84, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x36, 0xb0, 0x01, 0x00, 0x54, 0x84, 0x22, 0x1b, 0x02, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15,
+ 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x50, 0x84, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x54, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x2a, 0xc0, 0x01, 0x00, 0x14, 0x84, 0xa2, 0x40,
+ 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x39, 0xc0, 0x01, 0x00,
+ 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00,
+ 0x14, 0x84, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0x60, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19,
+ 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb8, 0x92, 0x00, 0x40,
+ 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x64, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56,
+ 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00,
+ 0x67, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x17, 0x90, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00, 0x16, 0x00, 0x20, 0x1d,
+ 0xe4, 0xb1, 0x01, 0x00, 0x6c, 0x84, 0xa3, 0x40, 0x27, 0x6c, 0x00, 0x00,
+ 0x6e, 0x84, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0b,
+ 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13, 0x16, 0x94, 0x01, 0x00,
+ 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x2a, 0x87, 0xa2, 0x5f,
+ 0x2f, 0x7c, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x90, 0x91, 0x00, 0x01,
+ 0x38, 0x43, 0x01, 0x00, 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00,
+ 0x76, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x62, 0xb1, 0x01, 0x00, 0x78, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x83, 0x84, 0x22, 0x13, 0x82, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
+ 0x62, 0xb1, 0x01, 0x00, 0x7e, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, 0x80, 0x84, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x7a, 0x84, 0x00, 0x41, 0x83, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6,
+ 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x2a, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0x01, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00,
+ 0x95, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x93, 0x84, 0x22, 0x42,
+ 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x94, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0x9d, 0x84, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x9d, 0x84, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0x9a, 0x84, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0xa3, 0x84, 0x22, 0x3a,
+ 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0xb0, 0x01, 0x00,
+ 0x7b, 0x88, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xa7, 0x84, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00,
+ 0x1e, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x05, 0x94, 0x00, 0x95,
+ 0x03, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0,
+ 0x2e, 0xb0, 0x01, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00,
+ 0xb0, 0x84, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x4b,
+ 0x95, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x4c, 0x8f, 0xb0, 0x00, 0x00,
+ 0xb2, 0x84, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x43, 0xc1, 0x01, 0x00, 0xb4, 0x84, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6,
+ 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1, 0x2a, 0xc8, 0x01, 0x00,
+ 0xd8, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb4, 0x91, 0x00, 0x41,
+ 0x81, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0xbe, 0x84, 0x64, 0x47, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xbf, 0x84, 0xa8, 0x1b,
+ 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x74, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0xe4, 0x84, 0x01, 0xfb, 0x08, 0x30, 0x00, 0x00,
+ 0x37, 0x85, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa,
+ 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0xb0, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07,
+ 0x16, 0x30, 0x01, 0x00, 0xda, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00,
+ 0xce, 0x84, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xd9, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00, 0xd2, 0x84, 0xa6, 0x5f,
+ 0x0f, 0x00, 0x00, 0x00, 0x2c, 0x92, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00,
+ 0xd7, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x0c, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x84, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x0f, 0xb0, 0x00, 0x00, 0xe2, 0x84, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00,
+ 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe2, 0x84, 0x22, 0x20,
+ 0x85, 0x6c, 0x00, 0x00, 0xdf, 0x84, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0xe6, 0x84, 0x21, 0x04,
+ 0x80, 0x20, 0x00, 0x00, 0xe7, 0x84, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00,
+ 0xbd, 0x87, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00, 0x06, 0x85, 0x00, 0x43,
+ 0x81, 0xb0, 0x00, 0x00, 0x0a, 0x85, 0x00, 0xfb, 0x22, 0xb0, 0x00, 0x00,
+ 0xbd, 0x87, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x4e,
+ 0x8f, 0xb0, 0x00, 0x00, 0x02, 0x85, 0x00, 0x5a, 0x8f, 0xb0, 0x00, 0x00,
+ 0xef, 0x84, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x53,
+ 0x81, 0xb0, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x56, 0x81, 0xb0, 0x00, 0x00,
+ 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x7b, 0x88, 0xa0, 0x0a,
+ 0xe4, 0x6d, 0x00, 0x00, 0xf5, 0x84, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xf4, 0x84, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x53,
+ 0x8f, 0xb0, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00,
+ 0xfe, 0x84, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0xf8, 0x84, 0xa2, 0x0a,
+ 0xe4, 0x6d, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x5d, 0x8f, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x80, 0xd0, 0x01, 0x00, 0xfc, 0x84, 0xa0, 0x91, 0x81, 0x6c, 0x00, 0x00,
+ 0x7b, 0x88, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00, 0x25, 0x00, 0x00, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x85, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x54,
+ 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x32, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x7b, 0x88, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00, 0xbd, 0x87, 0xa0, 0x42,
+ 0x83, 0x6c, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x54, 0x81, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, 0x13, 0x85, 0x22, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0xc6, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0x14, 0x87, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0x25, 0x85, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x85, 0xa2, 0x54,
+ 0xfd, 0x7f, 0x00, 0x00, 0x18, 0x85, 0x22, 0x55, 0xfd, 0x7f, 0x00, 0x00,
+ 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x10, 0x85, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x10, 0x85, 0x22, 0x53, 0xfd, 0x7f, 0x00, 0x00,
+ 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b, 0x80, 0xf4, 0x01, 0x00,
+ 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x20, 0x85, 0x22, 0x43,
+ 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x80, 0x88, 0x01, 0x00,
+ 0x10, 0x85, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00, 0x7c, 0x96, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x21, 0x85, 0x46, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x24, 0x85, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00, 0x16, 0x85, 0x1e, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, 0x31, 0xc3, 0x01, 0x00,
+ 0x5d, 0x92, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00, 0x29, 0x85, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x33, 0x93, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x14, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c, 0xe0, 0x99, 0x01, 0x00,
+ 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0x30, 0x85, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa1,
+ 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00,
+ 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0xbd, 0x87, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0xb0, 0x01, 0x00,
+ 0x41, 0x85, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00, 0x3d, 0x85, 0x22, 0x40,
+ 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x1f, 0x90, 0x01, 0x00,
+ 0x3f, 0x85, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x1f, 0x90, 0x01, 0x00, 0x41, 0x85, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x41, 0x85, 0x66, 0x1b,
+ 0x2c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x13, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x76, 0x41, 0x41, 0xc3, 0x01, 0x00, 0x70, 0x85, 0x23, 0x92,
+ 0x15, 0x6c, 0x00, 0x00, 0x70, 0x85, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x74, 0x85, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0,
+ 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x0a, 0x24, 0xc8, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40,
+ 0x0f, 0x30, 0x01, 0x00, 0x6e, 0x85, 0x22, 0x08, 0x40, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x12,
+ 0x24, 0xcc, 0x01, 0x00, 0x4a, 0x85, 0xaa, 0x41, 0x27, 0x40, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00, 0x6a, 0x85, 0x26, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00,
+ 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00, 0x10, 0x00, 0x00, 0x10,
+ 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00,
+ 0x57, 0x85, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00, 0x63, 0x85, 0x00, 0x41,
+ 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42, 0x44, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0x5c, 0x85, 0xa2, 0x44, 0x23, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x5f, 0x85, 0xa8, 0x42, 0xe0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00,
+ 0x55, 0x85, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x6a, 0x85, 0x22, 0x40,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x67, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40,
+ 0x25, 0x98, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x2a, 0xc8, 0x01, 0x00,
+ 0x7d, 0x85, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00, 0x7e, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x74, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x94, 0x92, 0x00, 0x92, 0x25, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x31, 0xb0, 0x01, 0x00, 0x74, 0x85, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00,
+ 0x7d, 0x85, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6,
+ 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0xc6, 0x95, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x7c, 0x85, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88,
+ 0x1c, 0xcc, 0x01, 0x00, 0xf5, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x14, 0x87, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00,
+ 0x91, 0x85, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0x86, 0x85, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x85, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x85, 0xa3, 0x07, 0x03, 0x6c, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x89, 0x85, 0xa3, 0x40,
+ 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00,
+ 0x8b, 0x85, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40,
+ 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x0e, 0xcc, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x8f, 0x85, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x08, 0xb0, 0x01, 0x00, 0xa0, 0x01, 0x2d, 0x40, 0x00, 0xc0, 0x01, 0x00,
+ 0x5b, 0x86, 0x22, 0x0f, 0x42, 0x05, 0x00, 0x00, 0xa2, 0x85, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x9d, 0x85, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9a, 0x85, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xa2, 0x85, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0xc0, 0x06, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x54,
+ 0x29, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x0e, 0xb0, 0x01, 0x00, 0x42, 0x00, 0x00, 0x03, 0x0a, 0xc8, 0x01, 0x00,
+ 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, 0xd6, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08, 0x10, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00,
+ 0xcb, 0x85, 0x22, 0x01, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44,
+ 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xb8, 0x85, 0xa3, 0x07,
+ 0x02, 0x6c, 0x00, 0x00, 0xb9, 0x85, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x68, 0x07, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x02, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00,
+ 0xc5, 0x85, 0x22, 0x40, 0x03, 0x6c, 0x00, 0x00, 0xc5, 0x85, 0x22, 0x42,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0xe9, 0x85, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xc2, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0xc7, 0x85, 0xa8, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xe9, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44,
+ 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xd0, 0x85, 0xa3, 0x12,
+ 0x0e, 0x6c, 0x00, 0x00, 0xd1, 0x85, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x12, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d,
+ 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00,
+ 0xd8, 0x85, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x07, 0x86, 0x22, 0x0d,
+ 0x14, 0x6c, 0x00, 0x00, 0xde, 0x85, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0xe2, 0x85, 0x00, 0x0d,
+ 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20,
+ 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00,
+ 0xe4, 0x85, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0xe9, 0x85, 0x00, 0x41,
+ 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe5, 0x85, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x07, 0x86, 0x22, 0x0d,
+ 0x14, 0x50, 0x00, 0x00, 0x06, 0x86, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00,
+ 0xf5, 0x85, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xf3, 0x85, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xf0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0xfa, 0x85, 0x1f, 0xf0,
+ 0x0e, 0x30, 0x00, 0x00, 0xb2, 0x85, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0xb2, 0x85, 0x23, 0x07,
+ 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x03, 0x86, 0xa8, 0x46,
+ 0x1f, 0x10, 0x00, 0x00, 0xb2, 0x85, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00,
+ 0xb2, 0x85, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x2e, 0x14,
+ 0x0a, 0xd0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, 0x48, 0xcd, 0x01, 0x00,
+ 0xfe, 0x7f, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x2a, 0xf2,
+ 0xe0, 0xb1, 0x01, 0x00, 0x0d, 0x86, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6, 0x80, 0xce, 0x01, 0x00,
+ 0x11, 0x86, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x43, 0xc1, 0x01, 0x00, 0x13, 0x86, 0x22, 0x0b, 0xed, 0x6d, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa1,
+ 0x46, 0xc9, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, 0x94, 0x88, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6,
+ 0x0e, 0xb0, 0x01, 0x00, 0x1b, 0x86, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00,
+ 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00, 0x1b, 0x86, 0xa0, 0x46,
+ 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00,
+ 0x1f, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2, 0x42, 0x31, 0x00, 0x00,
+ 0x22, 0x86, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa2,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x89, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x82, 0xb0, 0x01, 0x00, 0x25, 0x86, 0xa0, 0x41, 0x90, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, 0x2a, 0x86, 0x22, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x2a, 0x86, 0xa0, 0x43, 0x89, 0x6c, 0x00, 0x00,
+ 0x2a, 0x86, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00, 0x2a, 0x86, 0xa0, 0x41,
+ 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00, 0x22, 0x86, 0xa2, 0x41,
+ 0x95, 0x50, 0x00, 0x00, 0x33, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00, 0xff, 0xff, 0x00, 0x48,
+ 0x90, 0x88, 0x01, 0x00, 0x31, 0x86, 0x90, 0x48, 0x92, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x93, 0xa4, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x14,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x05, 0xe0, 0xcd, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x39, 0x86, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x44, 0x86, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0x43, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x40, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x47, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00,
+ 0xcc, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc0, 0x86, 0x00, 0x17,
+ 0x10, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x2f, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x4b, 0x86, 0xa0, 0x07,
+ 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x17, 0xf0, 0x01, 0x00, 0x4f, 0x86, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x59, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x56, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00,
+ 0xc0, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x63, 0x86, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x63, 0x86, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x60, 0x86, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x68, 0x86, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f,
+ 0xe1, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0x6d, 0x86, 0x22, 0x40,
+ 0x31, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x72, 0x86, 0xa8, 0x40,
+ 0x23, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4,
+ 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00,
+ 0x80, 0x86, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, 0x81, 0x86, 0x68, 0x07,
+ 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, 0x1a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08,
+ 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00,
+ 0x86, 0x86, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0xb5, 0x86, 0x22, 0x0d,
+ 0x14, 0x6c, 0x00, 0x00, 0x8c, 0x86, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0x90, 0x86, 0x00, 0x0d,
+ 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20,
+ 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00,
+ 0x92, 0x86, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0x97, 0x86, 0x00, 0x41,
+ 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x93, 0x86, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0d,
+ 0x14, 0x50, 0x00, 0x00, 0xb4, 0x86, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00,
+ 0xa3, 0x86, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xa1, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x9e, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0xa8, 0x86, 0x1f, 0xf0,
+ 0x0e, 0x30, 0x00, 0x00, 0x7b, 0x86, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x7b, 0x86, 0x23, 0x07,
+ 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00,
+ 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xb1, 0x86, 0xa8, 0x46,
+ 0x1f, 0x10, 0x00, 0x00, 0x7b, 0x86, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00,
+ 0x7b, 0x86, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, 0xbe, 0x86, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10,
+ 0x48, 0xc1, 0x01, 0x00, 0xbe, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xbb, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x10, 0xb0, 0x01, 0x00, 0xc0, 0x86, 0x00, 0x40, 0x2b, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc5, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0xf5, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xd7, 0x95, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00,
+ 0x2a, 0x87, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x0e, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07,
+ 0x16, 0x30, 0x01, 0x00, 0xd4, 0x86, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00,
+ 0xd2, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xd3, 0x86, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xdc, 0x86, 0xa2, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xdc, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0xd9, 0x86, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x33, 0x93, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42,
+ 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0xbd, 0x87, 0xa2, 0x5f,
+ 0x81, 0x6c, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x43, 0x19, 0x80, 0x01, 0x00,
+ 0x37, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3,
+ 0x8e, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00,
+ 0xeb, 0x86, 0x22, 0x48, 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00,
+ 0xeb, 0x86, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, 0xea, 0x86, 0x23, 0x41,
+ 0x8f, 0x6c, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00,
+ 0xbd, 0x87, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00,
+ 0xf0, 0x86, 0x22, 0x0a, 0x90, 0x40, 0x00, 0x00, 0xaa, 0x95, 0x00, 0x40,
+ 0x91, 0x30, 0x01, 0x00, 0xbd, 0x87, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0xb0, 0x00, 0x2d, 0x45, 0x81, 0xb0, 0x01, 0x00, 0xfc, 0x86, 0x22, 0xf0,
+ 0x2c, 0x30, 0x00, 0x00, 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00,
+ 0xac, 0x00, 0x2d, 0xf3, 0x82, 0xe0, 0x01, 0x00, 0xf6, 0x86, 0xa3, 0x41,
+ 0x2c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00,
+ 0x98, 0x00, 0x2d, 0xf0, 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0,
+ 0x82, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00,
+ 0xbd, 0x87, 0x20, 0x4c, 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41,
+ 0x98, 0xe8, 0x01, 0x00, 0xbd, 0x87, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00,
+ 0x14, 0x87, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c,
+ 0x7e, 0x89, 0x01, 0x00, 0x14, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xbd, 0x87, 0x00, 0x49, 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6,
+ 0x80, 0xb0, 0x01, 0x00, 0x04, 0x87, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00,
+ 0x13, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x05, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00,
+ 0x05, 0x87, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x08, 0xb1, 0x01, 0x00, 0x07, 0x87, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00,
+ 0x0b, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xec, 0x82, 0x22, 0x40,
+ 0x57, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00,
+ 0x0b, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0xdd, 0x82, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0xcb, 0x81, 0xc8, 0x01, 0x00, 0x11, 0x87, 0x22, 0x40,
+ 0xf2, 0x7f, 0x00, 0x00, 0xc4, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00,
+ 0x13, 0x87, 0x22, 0x40, 0x73, 0x7d, 0x00, 0x00, 0xde, 0x80, 0x00, 0x41,
+ 0x8b, 0xb3, 0x00, 0x00, 0x0e, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x1b, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x1b, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x18, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x2f, 0x92, 0x22, 0x02,
+ 0x80, 0x32, 0x00, 0x00, 0x1c, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x2f, 0x92, 0x1a, 0x02,
+ 0x68, 0x97, 0x00, 0x00, 0x26, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x26, 0x87, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x23, 0x87, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x39, 0x92, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x27, 0x87, 0x42, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x39, 0x92, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00, 0x31, 0x87, 0x9c, 0x0f,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x31, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x2e, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xf9, 0x82, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0x32, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00,
+ 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0x56, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x82, 0x87, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41,
+ 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x29, 0x00, 0x00, 0x40,
+ 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d,
+ 0x42, 0xc9, 0x01, 0x00, 0x66, 0x87, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x47, 0x87, 0x60, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x84, 0x89, 0x01, 0x00, 0x4e, 0x87, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00,
+ 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x83, 0x87, 0x70, 0xf0, 0x18, 0x30, 0x01, 0x00,
+ 0x66, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x70, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x5d, 0x87, 0xa0, 0x48, 0x23, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a,
+ 0x42, 0xc9, 0x01, 0x00, 0x57, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a,
+ 0x62, 0xdd, 0x01, 0x00, 0x54, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x83, 0x87, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00,
+ 0x58, 0x87, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x10,
+ 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00,
+ 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x1a,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00,
+ 0x61, 0x87, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00, 0x72, 0x87, 0x22, 0x41,
+ 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00,
+ 0x6e, 0x87, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1b, 0xb0, 0x01, 0x00, 0x45, 0x87, 0x00, 0x41, 0x17, 0xb0, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00, 0x45, 0x87, 0x83, 0x41,
+ 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00,
+ 0x45, 0x87, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00, 0x7d, 0x87, 0x23, 0x40,
+ 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x7a, 0x87, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x77, 0x87, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x83, 0x87, 0x00, 0xf8,
+ 0x18, 0x30, 0x01, 0x00, 0x7b, 0x87, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, 0x80, 0x87, 0xa0, 0xaa,
+ 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00,
+ 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x0c,
+ 0x7e, 0x89, 0x01, 0x00, 0x95, 0x87, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00,
+ 0x8b, 0x87, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x40,
+ 0x62, 0x99, 0x01, 0x00, 0x8b, 0x87, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x8b, 0x87, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x87, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x90, 0x87, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00,
+ 0x8c, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x95, 0x87, 0x22, 0x49,
+ 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54,
+ 0x77, 0x7d, 0x01, 0x00, 0x90, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00,
+ 0x95, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55,
+ 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00,
+ 0xf9, 0x82, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x9d, 0x87, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xa0, 0x87, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xab, 0x27, 0xb3, 0x01, 0x00,
+ 0xf9, 0x82, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xf9, 0x82, 0x22, 0x51,
+ 0xfd, 0x7f, 0x00, 0x00, 0xf9, 0x82, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00,
+ 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xac, 0x87, 0x22, 0x40,
+ 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00,
+ 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x40, 0x05, 0x00, 0x40,
+ 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda,
+ 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00,
+ 0x20, 0x04, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a,
+ 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a,
+ 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xf9, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x20, 0x40, 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00,
+ 0xc3, 0x87, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xe6, 0x8a, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x1a, 0x8b, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x4c, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x8b, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb4, 0x8b, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xc4, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8b, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x73, 0x8c, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x73, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x73, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x93, 0x8c, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xb1, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xd9, 0x8c, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0xea, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xea, 0x8c, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xec, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xf4, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x05, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0xf5, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x05, 0x8d, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x06, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xfc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x71, 0x8c, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8c, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41,
+ 0x09, 0xb0, 0x00, 0x00, 0x07, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x07, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x07, 0x8d, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x0e, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x10, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x1c, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x7b, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x83, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xb8, 0x8b, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x94, 0x8d, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x88, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x7f, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x20, 0x47,
+ 0xe6, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00,
+ 0x83, 0x88, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xac, 0x8d, 0x00, 0x49,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe5, 0x8d, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xeb, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xf9, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x15, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x75, 0x8e, 0x00, 0x44,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x74, 0x8e, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd4, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd4, 0x8e, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xec, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x45,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x41, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x15, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x75, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x8e, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x09, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x09, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x09, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xee, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x2c, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x14, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x14, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x2c, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3b, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x9d, 0x8f, 0x00, 0x40, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x0c, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xc1, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xc1, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd4, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x2b, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x1f, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x2b, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1f, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8f, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xc3, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4b,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xc3, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0xc3, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4c,
+ 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xdd, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xdd, 0x8f, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfa, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xfa, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xce, 0x8f, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xda, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0xe0, 0x8e, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x8f, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x36, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x36, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x36, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x36, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00,
+ 0x36, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x36, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x45, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x56, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x56, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x43,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x42,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x85, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x85, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x42, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x8d, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x8d, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00,
+ 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48,
+ 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20,
+ 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x1f, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00,
+ 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0xee, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xdf, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0xdf, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xdc, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xa3, 0x84, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00,
+ 0xe0, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00,
+ 0xa3, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x05, 0x00, 0x2e, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x1f, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x06, 0x07, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b,
+ 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34,
+ 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00,
+ 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x09, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0x11, 0x8b, 0x20, 0x4b,
+ 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x0e, 0x8b, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x18, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x14, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x83, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x1d, 0x8b, 0x44, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x20, 0x8b, 0xa2, 0x4c, 0xfd, 0x7f, 0x00, 0x00,
+ 0x21, 0x8b, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00, 0x22, 0x8b, 0x20, 0xf0,
+ 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x56, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x70, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x28, 0x8b, 0xa8, 0x44,
+ 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0xf1, 0x99, 0x01, 0x00, 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x62, 0xb1, 0x01, 0x00,
+ 0x30, 0x8b, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x86, 0xe4, 0x01, 0x00,
+ 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x38, 0x8b, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x3b, 0x8b, 0x22, 0x44,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x45, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00, 0x68, 0x01, 0x20, 0xa2,
+ 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x3f, 0x8b, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43,
+ 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x44, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5c, 0x00, 0x2e, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x83, 0x94, 0x00, 0x41,
+ 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x4f, 0x8b, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x53, 0x8b, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00,
+ 0x86, 0x00, 0x2f, 0x49, 0x19, 0x80, 0x01, 0x00, 0x53, 0x8b, 0xa2, 0xf2,
+ 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xe7, 0x91, 0x01, 0x00, 0x56, 0x8b, 0xa2, 0x46,
+ 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x5a, 0x8b, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46,
+ 0x19, 0x80, 0x01, 0x00, 0x5a, 0x8b, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0xe7, 0x91, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x34, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x16, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00,
+ 0x85, 0x8b, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x6d, 0x8b, 0x22, 0x0a,
+ 0x16, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0,
+ 0x84, 0x30, 0x00, 0x00, 0x70, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00,
+ 0x6c, 0x8b, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0x62, 0x8b, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00,
+ 0x85, 0x8b, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43,
+ 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, 0x70, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x85, 0x8b, 0x22, 0x41, 0x15, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00, 0x79, 0x8b, 0xa0, 0x43,
+ 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x47,
+ 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x2c, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x81, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x75, 0x8b, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x51,
+ 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x8d, 0x8b, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00,
+ 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x92, 0x8b, 0x22, 0x45,
+ 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00,
+ 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x97, 0x8b, 0x22, 0x48,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x02, 0x30, 0x00, 0x00, 0xa5, 0x8b, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00,
+ 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41,
+ 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0xaa, 0x95, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0xae, 0x8b, 0xa2, 0x44,
+ 0x81, 0x6c, 0x00, 0x00, 0xac, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x57, 0x93, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xd2, 0x8b, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0xae, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd2, 0x8b, 0xa2, 0x08,
+ 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00,
+ 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01,
+ 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00,
+ 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x8d, 0x8b, 0x22, 0x4a,
+ 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x36, 0x93, 0x00, 0xf3,
+ 0x94, 0x30, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00,
+ 0x00, 0x8c, 0x01, 0x00, 0xe4, 0x8a, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0,
+ 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00,
+ 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x8b, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00,
+ 0xc9, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x57, 0x93, 0x00, 0x40,
+ 0x3b, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xcd, 0x8b, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x5f,
+ 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x50, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0,
+ 0x38, 0xb0, 0x01, 0x00, 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x40, 0x00, 0x2d, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x14, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x52, 0x81, 0xd0, 0x01, 0x00, 0x89, 0x94, 0x00, 0x40,
+ 0xe4, 0x31, 0x01, 0x00, 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00,
+ 0xde, 0x8b, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, 0xce, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd6, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xec, 0x8b, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0xe9, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xe6, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x44, 0xc9, 0x01, 0x00, 0xf4, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xf0, 0x8b, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, 0xf1, 0x8b, 0x00, 0x06,
+ 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00,
+ 0xf3, 0x8b, 0x20, 0x02, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x04, 0xb0, 0x01, 0x00, 0xf7, 0x8b, 0x00, 0x02, 0xe0, 0xb1, 0x00, 0x00,
+ 0xf6, 0x8b, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, 0xf7, 0x8b, 0x00, 0x06,
+ 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0x02, 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b,
+ 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0xfc, 0x8b, 0xa8, 0x13, 0xe0, 0x31, 0x00, 0x00, 0x33, 0x8c, 0x22, 0x02,
+ 0x14, 0x50, 0x00, 0x00, 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00,
+ 0x23, 0x8c, 0xa2, 0x02, 0x02, 0x50, 0x00, 0x00, 0x0a, 0x8c, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x09, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x05, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x44, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0,
+ 0x38, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x38, 0x00, 0x2f, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x24, 0x8c, 0x22, 0x01,
+ 0x14, 0x6c, 0x00, 0x00, 0x17, 0x8c, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x20, 0x00, 0x2d, 0x03,
+ 0x48, 0xb1, 0x01, 0x00, 0x16, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x13, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x38, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00,
+ 0x38, 0x00, 0x2d, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0xe1, 0xc1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x4a, 0xf1, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x00, 0x05,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00,
+ 0x20, 0x8c, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x24, 0x8c, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0xc0, 0x01, 0x00,
+ 0x2e, 0x8c, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x33, 0xc0, 0x01, 0x00, 0x2c, 0x8c, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00,
+ 0x04, 0x00, 0x8f, 0x0d, 0x42, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8,
+ 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0xe2, 0x8b, 0x00, 0xa1,
+ 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00,
+ 0xe2, 0x8b, 0x00, 0x02, 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c,
+ 0xe0, 0xb1, 0x01, 0x00, 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00,
+ 0x4e, 0x00, 0x20, 0x01, 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x8c, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00,
+ 0x37, 0x00, 0x2d, 0x46, 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3,
+ 0x80, 0xf4, 0x01, 0x00, 0x37, 0x8c, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00,
+ 0x3e, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00,
+ 0x3b, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x45, 0x8c, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x42, 0x8c, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x60, 0x01, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00,
+ 0x4a, 0x8c, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00,
+ 0x32, 0x00, 0x00, 0xa6, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x2a, 0x94, 0x01, 0x00, 0x4d, 0x8c, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00, 0x52, 0x8c, 0x28, 0x40,
+ 0x05, 0x30, 0x00, 0x00, 0x4e, 0x8c, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0x55, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x62, 0xb1, 0x01, 0x00, 0x5e, 0x8c, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x52, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00,
+ 0x92, 0xb0, 0x01, 0x00, 0x5b, 0x8c, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x99, 0x92, 0x00, 0xf8,
+ 0x00, 0x30, 0x01, 0x00, 0x58, 0x8c, 0xa2, 0x41, 0x3b, 0x50, 0x00, 0x00,
+ 0x5f, 0x8c, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, 0xff, 0x07, 0x00, 0x1e,
+ 0x00, 0x8c, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x5f, 0x8c, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x47,
+ 0x19, 0x80, 0x01, 0x00, 0x62, 0x8c, 0x22, 0x5f, 0x01, 0x6c, 0x00, 0x00,
+ 0xd4, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbf, 0x87, 0x00, 0x00,
+ 0x80, 0xb0, 0x00, 0x00, 0x69, 0x8c, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x69, 0x8c, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x66, 0x8c, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x69, 0x8c, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x94, 0x89, 0x01, 0x00, 0x6f, 0x8c, 0x85, 0xca, 0x94, 0x30, 0x00, 0x00,
+ 0xd4, 0x95, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f,
+ 0x1e, 0x8c, 0x01, 0x00, 0xe0, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf4, 0x94, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x47,
+ 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x80, 0x01, 0x00,
+ 0xe4, 0x8a, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x76, 0x8c, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x94, 0x00, 0x40,
+ 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50,
+ 0x17, 0xf0, 0x01, 0x00, 0x7c, 0x8c, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x7e, 0x8c, 0x22, 0x43,
+ 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00,
+ 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x88, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x8c, 0x8c, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x92, 0x8c, 0x28, 0x40,
+ 0x05, 0x30, 0x00, 0x00, 0x8d, 0x8c, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0x99, 0x92, 0x1d, 0x08, 0x00, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x1d, 0x47, 0x19, 0x80, 0x00, 0x00,
+ 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x84, 0xc8, 0x01, 0x00, 0x97, 0x8c, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, 0xa2, 0x8c, 0xa2, 0x41,
+ 0x9e, 0x06, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x44, 0x83, 0x70, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43,
+ 0xe7, 0xe1, 0x01, 0x00, 0xe4, 0x8a, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00,
+ 0xd4, 0x95, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00, 0xbf, 0x87, 0x23, 0x41,
+ 0x83, 0x6c, 0x00, 0x00, 0xbf, 0x87, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x28, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x47,
+ 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8e, 0xb0, 0x01, 0x00,
+ 0x90, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x93, 0x8b, 0xa2, 0x40, 0x8f, 0x7c, 0x00, 0x00,
+ 0xb0, 0x8c, 0x22, 0x47, 0x8f, 0x7c, 0x00, 0x00, 0x93, 0x8b, 0x00, 0x48,
+ 0x19, 0x90, 0x00, 0x00, 0x1f, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x36, 0x00, 0x2d, 0x5d, 0x05, 0xb4, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf3,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x8e, 0xb0, 0x01, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x86, 0xdc, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x9b, 0x91, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00,
+ 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0xbe, 0x8c, 0xa2, 0x50,
+ 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x63, 0x41,
+ 0x81, 0xc0, 0x01, 0x00, 0xc1, 0x8c, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x20, 0x47,
+ 0xe6, 0xb1, 0x01, 0x00, 0xe4, 0x8a, 0x22, 0x47, 0x80, 0x32, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x47, 0x0c, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x8f, 0x84, 0x01, 0x00, 0xd6, 0x8c, 0x22, 0x47, 0x0c, 0x6c, 0x00, 0x00,
+ 0x58, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xd6, 0x8c, 0x1f, 0xf0,
+ 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xcf, 0x8c, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xcc, 0x8c, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xcf, 0x8c, 0x42, 0x40, 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00,
+ 0xd4, 0x8c, 0x23, 0x41, 0x0d, 0x6c, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xd4, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00,
+ 0xbf, 0x87, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x40,
+ 0x8f, 0x6c, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x84, 0xb0, 0x01, 0x00,
+ 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf2,
+ 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0xe5, 0x8c, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x40,
+ 0x81, 0x98, 0x01, 0x00, 0xe5, 0x8c, 0xa3, 0x40, 0x82, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00, 0xe7, 0x8c, 0x20, 0x4c,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00,
+ 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x42,
+ 0xe6, 0xb1, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x83, 0x94, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00,
+ 0xb0, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0,
+ 0x80, 0xc0, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2,
+ 0x96, 0xcc, 0x01, 0x00, 0xe4, 0x8a, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x46,
+ 0x95, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xe4, 0x8a, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xcc, 0x01, 0x00,
+ 0xe4, 0x8a, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x4a,
+ 0x81, 0x30, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x47, 0x95, 0x30, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x0b, 0x8d, 0x90, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, 0x81, 0x98, 0x01, 0x00,
+ 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xe4, 0x8a, 0x22, 0x40,
+ 0xe5, 0x6d, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41, 0xe5, 0xc1, 0x00, 0x00,
+ 0x83, 0x94, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x8d, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x1b, 0x8d, 0x80, 0xf3,
+ 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x81, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x5c,
+ 0x1f, 0x90, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40,
+ 0xe5, 0x99, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x8d, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x84, 0xcc, 0x01, 0x00,
+ 0x28, 0x8d, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x2a, 0x8d, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x2b, 0x8d, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x62, 0xb1, 0x01, 0x00, 0x2d, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00,
+ 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0,
+ 0x28, 0xb0, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00, 0xe0, 0xb1, 0x01, 0x00,
+ 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2b, 0xb0, 0x01, 0x00,
+ 0xd8, 0x94, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x16, 0xc0, 0x01, 0x00, 0x3f, 0x8d, 0xa0, 0x14, 0x16, 0x44, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf8, 0xb1, 0x01, 0x00,
+ 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00, 0x10, 0x50, 0x00, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x48, 0x8d, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b,
+ 0x16, 0xc8, 0x01, 0x00, 0x48, 0x8d, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x01, 0x00, 0x6e, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00,
+ 0x4c, 0x8d, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x53, 0x8d, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00,
+ 0x52, 0x8d, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41,
+ 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x59, 0x8d, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00, 0xa0, 0x00, 0x20, 0xf2,
+ 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46, 0x19, 0x10, 0x00, 0x00,
+ 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b,
+ 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00,
+ 0x5e, 0x8d, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x60, 0x8d, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20,
+ 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x62, 0x40,
+ 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40,
+ 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00,
+ 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x6a, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x6e, 0x8d, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08,
+ 0x62, 0xdd, 0x01, 0x00, 0x6f, 0x8d, 0xa8, 0x40, 0x05, 0x30, 0x00, 0x00,
+ 0x35, 0x00, 0x1d, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x84, 0xc8, 0x01, 0x00, 0x75, 0x8d, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0xe7, 0x91, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00,
+ 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00,
+ 0x1f, 0x8d, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x8a, 0x8b, 0x22, 0x4a,
+ 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb,
+ 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00, 0xb4, 0x8b, 0x22, 0x06,
+ 0x90, 0x6c, 0x00, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00,
+ 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0,
+ 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50, 0xe7, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00, 0x8f, 0x8d, 0xa0, 0x43,
+ 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x99, 0x91, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x91, 0x8d, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0xb4, 0x8b, 0x1a, 0x5d,
+ 0x69, 0x93, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00,
+ 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0,
+ 0x94, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x6b, 0xfb, 0x84, 0xc8, 0x01, 0x00, 0x9c, 0x8d, 0xa0, 0x43,
+ 0x85, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3,
+ 0x12, 0xc8, 0x01, 0x00, 0x9f, 0x8d, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x9b, 0x91, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa2, 0x8d, 0x42, 0x05,
+ 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x11, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00,
+ 0x9b, 0x8c, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xa5, 0x8c, 0x00, 0xf0,
+ 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xad, 0x8d, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42,
+ 0x13, 0xf0, 0x01, 0x00, 0xb2, 0x8d, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0xf5, 0x82, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xac, 0x8d, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x75, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0xb4, 0x8d, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00,
+ 0x1f, 0x94, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0xbe, 0x8d, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00,
+ 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0xbb, 0x8d, 0x00, 0x50,
+ 0x43, 0xc1, 0x00, 0x00, 0xca, 0x8d, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00,
+ 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0xc8, 0x8d, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0xd0, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00,
+ 0xd4, 0x8d, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3,
+ 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x62, 0xb1, 0x01, 0x00, 0xd8, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xdd, 0x8d, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0xdb, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96,
+ 0x97, 0xb0, 0x01, 0x00, 0xe3, 0x8d, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00,
+ 0xe3, 0x8d, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0xde, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x83, 0x94, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xe9, 0x8d, 0x22, 0xf3, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x42,
+ 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x42,
+ 0x19, 0x80, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0xf4, 0x94, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x96, 0x93, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x40,
+ 0x95, 0x6c, 0x00, 0x00, 0xf4, 0x8d, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x40,
+ 0x95, 0x30, 0x01, 0x00, 0xff, 0x8d, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x14, 0x87, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x23, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x02, 0x8e, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0xc0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00,
+ 0x06, 0x8e, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0xed, 0x94, 0x00, 0x43,
+ 0x61, 0x31, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00,
+ 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x0e, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x0b, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x75, 0x94, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x12, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00,
+ 0x19, 0x8e, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00,
+ 0x1a, 0x8e, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45,
+ 0x1f, 0x90, 0x01, 0x00, 0x75, 0x8e, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00,
+ 0x75, 0x8e, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x2d, 0x8e, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x29, 0x8e, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x26, 0x8e, 0xa2, 0x41,
+ 0x19, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x93, 0x00, 0x15,
+ 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x8e, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x31, 0x8e, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x5d, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15,
+ 0x98, 0xc8, 0x01, 0x00, 0x5d, 0x8e, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00,
+ 0x39, 0x8e, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b,
+ 0x99, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00,
+ 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0, 0x22, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41, 0xe7, 0xe1, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x47,
+ 0xe7, 0xb5, 0x01, 0x00, 0x4a, 0x8e, 0x23, 0x0b, 0x81, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x02, 0xd0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x00,
+ 0x2a, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01,
+ 0x80, 0xce, 0x01, 0x00, 0x5b, 0x8e, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x98, 0xd0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x62, 0x8e, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x15, 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01,
+ 0xe4, 0xcd, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00,
+ 0xcc, 0x94, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00, 0x67, 0x8e, 0x22, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x68, 0x8e, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00,
+ 0xa7, 0x91, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x70, 0x8e, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x6d, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x73, 0x8e, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xcf, 0x8a, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x75, 0x8e, 0x00, 0x4a,
+ 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00,
+ 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0,
+ 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15,
+ 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00, 0x34, 0x94, 0x00, 0x40,
+ 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xb9, 0x8e, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b,
+ 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00,
+ 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0x8f, 0x8e, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x8f, 0x8e, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xb2, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0xa0, 0x8e, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xee, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x41, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xad, 0x8e, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x96, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x9c, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xaf, 0x92, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x9d, 0x8e, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x9f, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0xee, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x3d, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xa3, 0x8e, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xa9, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xaa, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xac, 0x8e, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xae, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xb5, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xb6, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x8e, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xd4, 0x8a, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0xc0, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xbc, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xc4, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40,
+ 0x11, 0x30, 0x01, 0x00, 0xc5, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xca, 0x8e, 0x03, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0xcb, 0x8e, 0x00, 0x41, 0x87, 0xb0, 0x00, 0x00,
+ 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0xcf, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0xd2, 0x8e, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x80, 0x01, 0x00, 0xcf, 0x8a, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00,
+ 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xd8, 0x8e, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x84, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd4, 0x8a, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xe4, 0x8e, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xec, 0x8e, 0xa2, 0x40,
+ 0xe5, 0x6d, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13,
+ 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00,
+ 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xfa, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, 0x98, 0x50, 0x00, 0x00,
+ 0xfa, 0x8e, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xf7, 0x8e, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15, 0x10, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01,
+ 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00,
+ 0x7c, 0x8e, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x09,
+ 0x80, 0x30, 0x01, 0x00, 0x7c, 0x8e, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0xb7, 0x93, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0x2c, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00,
+ 0xa9, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x48,
+ 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x8f, 0xa8, 0x40,
+ 0x13, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x15, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x40,
+ 0x13, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00,
+ 0x08, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x2d, 0x8f, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x87, 0x42,
+ 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00,
+ 0xcf, 0x8a, 0x00, 0x40, 0xe7, 0x91, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x2b, 0x8f, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00,
+ 0x1e, 0x92, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0x2b, 0x8f, 0x22, 0x00,
+ 0x80, 0x32, 0x00, 0x00, 0x26, 0x8f, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x8f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0xf2,
+ 0x02, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x2c, 0x8f, 0x00, 0x40,
+ 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x32, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x31, 0x8f, 0xa2, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x32, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xbc, 0x8f, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x3a, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x37, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xbc, 0x8f, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x40, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x4d,
+ 0x81, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x96, 0xb0, 0x01, 0x00, 0x4e, 0x8f, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4b, 0x8f, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x8f, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x53, 0x8f, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00,
+ 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x58, 0x8f, 0x22, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0xf5, 0x82, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x52, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0xe7, 0x91, 0x01, 0x00, 0x04, 0x00, 0x75, 0x09, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x60, 0x8f, 0xa8, 0x40,
+ 0xe1, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x64, 0x8f, 0x65, 0x05,
+ 0x48, 0x31, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x6c, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x6a, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b,
+ 0x16, 0xdc, 0x01, 0x00, 0x1e, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x84, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xcc, 0x93, 0x00, 0x5f,
+ 0x01, 0x10, 0x01, 0x00, 0x6e, 0x8f, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x76, 0x8f, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52,
+ 0x95, 0x30, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x6e, 0x8f, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x6e, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00,
+ 0xd4, 0x94, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0xe1, 0xb1, 0x01, 0x00,
+ 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07,
+ 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x8e, 0x8f, 0x30, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00,
+ 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b,
+ 0xe6, 0x81, 0x01, 0x00, 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00,
+ 0x93, 0x04, 0x00, 0x5f, 0x95, 0x04, 0x01, 0x00, 0x22, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x98, 0x8f, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00,
+ 0x96, 0x8f, 0x46, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41,
+ 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x0f, 0xb0, 0x01, 0x00, 0x85, 0x92, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xa9, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00,
+ 0xa2, 0x8f, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x62, 0xb1, 0x01, 0x00, 0xa6, 0x8f, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xa3, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x62, 0xb1, 0x01, 0x00, 0xa6, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x22, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0xc9, 0x94, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0x40, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xba, 0x8f, 0x22, 0x47,
+ 0xe7, 0x7d, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00,
+ 0xba, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xb5, 0x8f, 0xa2, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xba, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00,
+ 0x41, 0x93, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc9, 0x94, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x5c,
+ 0x1f, 0x10, 0x01, 0x00, 0xbf, 0x8f, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00,
+ 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe7, 0x91, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa9, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00,
+ 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0,
+ 0x84, 0x30, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xf4, 0x94, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd3, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x47,
+ 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07, 0x84, 0x94, 0x01, 0x00,
+ 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x99, 0x92, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a,
+ 0x2c, 0x50, 0x00, 0x00, 0x07, 0x95, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00,
+ 0xea, 0x8f, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xe8, 0x8f, 0x84, 0x48,
+ 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0xea, 0x8f, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x02, 0xb0, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xeb, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00,
+ 0xf8, 0x8f, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, 0xf1, 0x93, 0x00, 0x45,
+ 0x1f, 0x00, 0x01, 0x00, 0xe3, 0x8f, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0xf4, 0x8f, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe3, 0x8f, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xfe, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x08, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x08, 0x90, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x16, 0x90, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x0e, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x12, 0x90, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x13, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00,
+ 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16,
+ 0xe4, 0xb1, 0x00, 0x00, 0x28, 0x90, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x7d, 0x95, 0x00, 0x40,
+ 0x95, 0x30, 0x01, 0x00, 0x29, 0x90, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01,
+ 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x08,
+ 0x80, 0x30, 0x01, 0x00, 0x21, 0x90, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00,
+ 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x22, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x36, 0x90, 0x20, 0x16,
+ 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x33, 0x90, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x2c, 0xd0, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x23, 0xb0, 0x01, 0x00,
+ 0x3d, 0x90, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00, 0x3e, 0x90, 0x00, 0x0a,
+ 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00,
+ 0x34, 0x94, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x42, 0xc9, 0x01, 0x00, 0x46, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x42, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x55, 0x90, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00,
+ 0x56, 0x90, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08,
+ 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x4d, 0x90, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x56, 0x90, 0x00, 0x5c,
+ 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00,
+ 0xaf, 0x92, 0x00, 0x40, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x5a, 0x90, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x62, 0x90, 0x22, 0x46,
+ 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x62, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x5e, 0x90, 0xa8, 0x46, 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x67, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x6d, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x71, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00,
+ 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x71, 0x90, 0xa2, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x86, 0x90, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x77, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x82, 0x90, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0x7b, 0x90, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00,
+ 0x7f, 0x90, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a,
+ 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00,
+ 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x83, 0x90, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15,
+ 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00,
+ 0x89, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xd6, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x96, 0x90, 0x22, 0x47,
+ 0x1f, 0x7c, 0x00, 0x00, 0x93, 0x90, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x8e, 0x90, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00,
+ 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0x92, 0x90, 0x22, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x58, 0x01, 0x2d, 0x00,
+ 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0, 0x10, 0xb0, 0x01, 0x00,
+ 0x2d, 0x8e, 0x00, 0xf0, 0x2c, 0xb0, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x41,
+ 0x95, 0x30, 0x01, 0x00, 0x9d, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0x9b, 0x90, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xd6, 0x90, 0x00, 0x05,
+ 0x48, 0xb1, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00,
+ 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6,
+ 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00,
+ 0xad, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0xa6, 0x90, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0,
+ 0x22, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x84, 0xb0, 0x01, 0x00, 0xb0, 0x90, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xb5, 0x90, 0x22, 0x40,
+ 0x1b, 0x6c, 0x00, 0x00, 0xcc, 0x94, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00,
+ 0xbd, 0x90, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x80, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00,
+ 0xbb, 0x90, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0xcc, 0x90, 0x00, 0x5e,
+ 0x17, 0x90, 0x00, 0x00, 0xc0, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x84, 0xd0, 0x01, 0x00, 0xc5, 0x90, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00,
+ 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xcc, 0x90, 0x22, 0x40,
+ 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0xc0, 0x01, 0x00,
+ 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f,
+ 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00,
+ 0xca, 0x90, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0xcd, 0x90, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x99, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00,
+ 0xd4, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x11,
+ 0x00, 0x8c, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e,
+ 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x8e, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xe7, 0x90, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe3, 0x90, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xe9, 0x90, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x1a, 0xd0, 0x01, 0x00, 0xef, 0x90, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x7d, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xf7, 0x90, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x1a, 0x90, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00,
+ 0x7d, 0x95, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0xf2, 0x90, 0x22, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0xf5, 0x90, 0x23, 0x0d,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00,
+ 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00,
+ 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00,
+ 0xc1, 0x92, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15,
+ 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x07, 0x95, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, 0x04, 0x91, 0xa2, 0x44,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x02, 0xb0, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x0b, 0x91, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x07, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x10, 0xc0, 0x01, 0x00, 0x14, 0x91, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00,
+ 0xf1, 0x93, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0xfd, 0x90, 0x22, 0x5c,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x10, 0x91, 0xa8, 0x5c,
+ 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0xfd, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x08, 0x00, 0x2d, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x41,
+ 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x19, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x1f, 0x91, 0x22, 0x09,
+ 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00,
+ 0x22, 0x91, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x4f,
+ 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x30, 0x91, 0x22, 0x4a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x28, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x2c, 0x91, 0x22, 0x42,
+ 0x19, 0x7c, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00,
+ 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16,
+ 0xe4, 0xb1, 0x00, 0x00, 0x17, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xc1, 0x92, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x10,
+ 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x3a, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x3d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x41, 0x93, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b,
+ 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x3f, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a,
+ 0x81, 0x30, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00,
+ 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x45,
+ 0x1f, 0x90, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x01,
+ 0x2c, 0xb0, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x51, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x4a, 0x91, 0x37, 0x5c,
+ 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00,
+ 0x4e, 0x91, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x4b, 0x91, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00,
+ 0x4e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x14, 0x87, 0x17, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00,
+ 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0x83, 0x93, 0x00, 0x47,
+ 0x1f, 0x10, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2b, 0x90, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x47,
+ 0x1f, 0x10, 0x01, 0x00, 0x63, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00,
+ 0x5f, 0x91, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02,
+ 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00,
+ 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x41, 0x93, 0x00, 0x15,
+ 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00,
+ 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00,
+ 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0xc1, 0x92, 0x00, 0x10,
+ 0x32, 0x30, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00,
+ 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x73, 0x91, 0xa2, 0x08,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0xc0, 0x01, 0x00, 0x6c, 0x91, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, 0x70, 0x91, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x6d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x70, 0x91, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00,
+ 0x82, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x7e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88,
+ 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x2d, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40,
+ 0x13, 0x30, 0x01, 0x00, 0x2d, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x75, 0x8e, 0x00, 0x44,
+ 0x19, 0x90, 0x00, 0x00, 0x8a, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, 0xdd, 0x8f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00,
+ 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x01,
+ 0x2c, 0xb0, 0x00, 0x00, 0xc1, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x2b, 0x90, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x45,
+ 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x37, 0xc3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x33, 0xc3, 0x01, 0x00, 0x36, 0x00, 0x00, 0x01,
+ 0x02, 0xcc, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x96, 0x91, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x48,
+ 0x03, 0xd0, 0x00, 0x00, 0x98, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x9f, 0x4c, 0x03, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
+ 0x34, 0xc3, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0, 0xb1, 0x01, 0x00,
+ 0x9d, 0x92, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00, 0x00, 0x80, 0x00, 0x43,
+ 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xa4, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40,
+ 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01, 0xe0, 0xc1, 0x01, 0x00,
+ 0xae, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x84, 0x95, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xb0, 0x91, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x47,
+ 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00,
+ 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0,
+ 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xc5, 0x91, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x18, 0x92, 0xa2, 0x4c,
+ 0x1f, 0x7c, 0x00, 0x00, 0xc5, 0x91, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xc8, 0x91, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46,
+ 0x8f, 0xb0, 0x01, 0x00, 0xbe, 0x91, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00,
+ 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc0, 0x91, 0x22, 0xf0,
+ 0x3a, 0x6c, 0x00, 0x00, 0x15, 0x92, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f,
+ 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x16, 0x92, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xc4, 0x91, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xc7, 0x91, 0x22, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0xcc, 0x91, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0xd5, 0x91, 0x23, 0xf0,
+ 0x02, 0x6c, 0x00, 0x00, 0xd2, 0x91, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00,
+ 0x17, 0x92, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x17, 0x92, 0xa2, 0x41,
+ 0x03, 0x6c, 0x00, 0x00, 0xd1, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x52,
+ 0x8f, 0xb0, 0x01, 0x00, 0x17, 0x92, 0x1f, 0x12, 0x84, 0x50, 0x00, 0x00,
+ 0x17, 0x92, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00, 0xc5, 0x91, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x00, 0x92, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0xf2, 0x91, 0x22, 0xf0, 0x14, 0x30, 0x00, 0x00,
+ 0xde, 0x91, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0xef, 0x91, 0x03, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0xdd, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49,
+ 0x8f, 0xb0, 0x01, 0x00, 0xe3, 0x91, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00,
+ 0xe6, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, 0xe5, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xd0, 0x01, 0x00,
+ 0xec, 0x91, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00, 0xeb, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0xee, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0xf1, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44,
+ 0x8f, 0xb0, 0x01, 0x00, 0xfb, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0xf8, 0x91, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0xf8, 0x91, 0xa2, 0xf2,
+ 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0xfa, 0x91, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0xf8, 0x91, 0xa0, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0xf6, 0x91, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00,
+ 0xff, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x28, 0x00, 0x80, 0x40,
+ 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00,
+ 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x09, 0x92, 0xa2, 0xf0,
+ 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00,
+ 0x06, 0x92, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40,
+ 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00,
+ 0xf8, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xf6, 0x91, 0x20, 0x91,
+ 0x03, 0x6c, 0x00, 0x00, 0xf8, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x0d, 0x92, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x0c, 0x92, 0xa2, 0x40,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x12, 0x92, 0x22, 0x0a,
+ 0x02, 0x6c, 0x00, 0x00, 0xe6, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00,
+ 0x11, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00,
+ 0x14, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00,
+ 0x1a, 0x92, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x41,
+ 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x42, 0x95, 0xb0, 0x00, 0x00,
+ 0x1a, 0x92, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x4c,
+ 0x95, 0xb0, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x1d, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b,
+ 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00,
+ 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3,
+ 0x84, 0xb0, 0x01, 0x00, 0x22, 0x92, 0xa2, 0xf3, 0x96, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x2a, 0x41,
+ 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41, 0x85, 0xe0, 0x01, 0x00,
+ 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00, 0x28, 0x92, 0x22, 0x5a,
+ 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00,
+ 0x29, 0x92, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x85, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0xa0, 0xa5, 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xc6, 0x95, 0x00, 0xf0,
+ 0x8c, 0xb0, 0x00, 0x00, 0x36, 0x92, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x33, 0x92, 0xa2, 0x4b,
+ 0x19, 0x7c, 0x00, 0x00, 0x34, 0x92, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0xff, 0x92, 0x00, 0x07,
+ 0x10, 0x30, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x38, 0x92, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x85, 0x92, 0x00, 0x40,
+ 0x81, 0x30, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b,
+ 0x19, 0x90, 0x01, 0x00, 0xff, 0x92, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00,
+ 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0xff, 0x92, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x05, 0xb0, 0x01, 0x00, 0x41, 0x92, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x44, 0x92, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x52, 0x92, 0x13, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00,
+ 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x0f,
+ 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x5f, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x4e, 0xb0, 0x01, 0x00, 0xa2, 0x84, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00,
+ 0x4f, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x97, 0xb0, 0x01, 0x00, 0x53, 0x92, 0x60, 0x07, 0x96, 0x30, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x70, 0xc2,
+ 0x24, 0xb0, 0x01, 0x00, 0x5d, 0x92, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00,
+ 0x57, 0x92, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x5e, 0x92, 0x22, 0x12,
+ 0x48, 0x7f, 0x00, 0x00, 0x58, 0x04, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00,
+ 0x5d, 0x92, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4,
+ 0x24, 0xb0, 0x01, 0x00, 0x5e, 0x92, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00,
+ 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x6b, 0x92, 0x0b, 0xf0, 0x84, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00, 0x68, 0x92, 0x22, 0x50,
+ 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x2a, 0x94, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, 0x93, 0x04, 0x00, 0x12,
+ 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x90, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b,
+ 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42, 0x10, 0xf4, 0x01, 0x00,
+ 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08,
+ 0x8a, 0x88, 0x01, 0x00, 0x6e, 0x92, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00,
+ 0x71, 0x92, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x5e, 0x92, 0x10, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00,
+ 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2a, 0x94, 0x00, 0xf2,
+ 0x96, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x7c, 0x92, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x68, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x80, 0x92, 0xa8, 0x05, 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0f,
+ 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42, 0x84, 0x88, 0x01, 0x00,
+ 0x89, 0x92, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0x8a, 0x92, 0x00, 0x42,
+ 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6a, 0xb1, 0x01, 0x00,
+ 0x8a, 0x92, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42,
+ 0x48, 0x93, 0x01, 0x00, 0x8c, 0x92, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x91, 0x92, 0x28, 0xb1,
+ 0x2c, 0x30, 0x00, 0x00, 0x8d, 0x92, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x95, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x91, 0x92, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40,
+ 0x61, 0x99, 0x01, 0x00, 0x98, 0x92, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00,
+ 0x94, 0x92, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x24, 0x11, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x9a, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x9e, 0x92, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xa4, 0x92, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf8,
+ 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x92, 0x48,
+ 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00,
+ 0xa8, 0x92, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00, 0xa4, 0x92, 0x22, 0x4c,
+ 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40, 0x91, 0xb0, 0x00, 0x00,
+ 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xa8, 0x92, 0xa8, 0xb1,
+ 0x90, 0x30, 0x00, 0x00, 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b,
+ 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x92, 0x49, 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41,
+ 0x00, 0xec, 0x00, 0x00, 0xb5, 0x92, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x00, 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0xb1, 0x92, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00,
+ 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41,
+ 0x00, 0xec, 0x00, 0x00, 0xbe, 0x92, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00,
+ 0x99, 0x92, 0x00, 0x00, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x49, 0xc1, 0x01, 0x00, 0xba, 0x92, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xc3, 0x92, 0x83, 0x1e,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00,
+ 0x24, 0x00, 0x2d, 0x01, 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0,
+ 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00,
+ 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x60, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xca, 0x92, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x0b, 0xe8, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x16, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x60, 0x17, 0x3d, 0x43,
+ 0x9d, 0xe0, 0x01, 0x00, 0x10, 0x00, 0x80, 0xa1, 0x16, 0xe4, 0x01, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0xd9, 0x92, 0x30, 0x47,
+ 0x17, 0x04, 0x00, 0x00, 0xdc, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x90, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0xe0, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41,
+ 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0xe1, 0x92, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0xeb, 0x92, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00,
+ 0x01, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00,
+ 0x40, 0x97, 0x3e, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e,
+ 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00,
+ 0xfe, 0x92, 0x00, 0x3b, 0xe7, 0xb1, 0x00, 0x00, 0xeb, 0x92, 0x30, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xf5, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00,
+ 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xf1, 0x92, 0xa2, 0x0b,
+ 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d,
+ 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41,
+ 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x4a, 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40,
+ 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07,
+ 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43,
+ 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00,
+ 0x02, 0x93, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x0e, 0x93, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00,
+ 0x0a, 0x93, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f,
+ 0x96, 0xf4, 0x01, 0x00, 0x07, 0x93, 0x31, 0x5f, 0x97, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x6a, 0xb1, 0x01, 0x00, 0x0a, 0x93, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3,
+ 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x16, 0x93, 0xa2, 0x3b,
+ 0x89, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0x17, 0x93, 0x18, 0x4a,
+ 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00, 0x1c, 0x93, 0x22, 0x5a,
+ 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x1e, 0x93, 0x00, 0x05,
+ 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1f, 0x93, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x22, 0x93, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00,
+ 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x26, 0x93, 0x22, 0x45,
+ 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x9b, 0x04, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41,
+ 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00,
+ 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3,
+ 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00,
+ 0x2e, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x27, 0x93, 0xa2, 0x3b,
+ 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x93, 0x04, 0x00, 0x12,
+ 0x94, 0x30, 0x01, 0x00, 0xff, 0x92, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a,
+ 0xe6, 0xc9, 0x01, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b,
+ 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00,
+ 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44,
+ 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0xf2, 0x02, 0x30, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x10,
+ 0x32, 0x30, 0x01, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40,
+ 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00,
+ 0x45, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x36, 0xb0, 0x01, 0x00, 0x55, 0x93, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x62, 0xb1, 0x01, 0x00, 0x4e, 0x93, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, 0x49, 0x93, 0x00, 0x5c,
+ 0x01, 0x80, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06,
+ 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x46, 0xc9, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x7c, 0x93, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x68, 0x08, 0x38, 0x96, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41,
+ 0x82, 0xcc, 0x01, 0x00, 0x5a, 0x93, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c,
+ 0x11, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00,
+ 0x7b, 0x93, 0x26, 0x46, 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+ 0x12, 0xc8, 0x01, 0x00, 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00,
+ 0x7a, 0x93, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x6c, 0x93, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x79, 0x93, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x77, 0x93, 0xa2, 0x41,
+ 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x72, 0x93, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03,
+ 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x13, 0xc0, 0x01, 0x00, 0x67, 0x93, 0x00, 0x50,
+ 0x49, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x1a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x7b, 0x93, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x99, 0x92, 0x00, 0x5c,
+ 0x01, 0x00, 0x01, 0x00, 0x7c, 0x93, 0x00, 0x41, 0x3b, 0xd0, 0x00, 0x00,
+ 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5f,
+ 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x8c, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00,
+ 0x88, 0x93, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, 0x14, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8, 0x0c, 0xb0, 0x01, 0x00,
+ 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x95, 0x93, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x96, 0xb0, 0x01, 0x00,
+ 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x20, 0x4a,
+ 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x80, 0x93, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42,
+ 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x9b, 0x93, 0xa2, 0xa5,
+ 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00,
+ 0x9e, 0x93, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41,
+ 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00,
+ 0xa3, 0x93, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00,
+ 0xa8, 0x93, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x0b, 0x00, 0x80, 0x00,
+ 0xe4, 0xf5, 0x01, 0x00, 0x9d, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0xb4, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9d, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00,
+ 0xc3, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00,
+ 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00, 0xcb, 0x93, 0x9f, 0x41,
+ 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5, 0x85, 0xcc, 0x01, 0x00,
+ 0x2d, 0x00, 0xa0, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0x5e, 0x01, 0x2d, 0x00,
+ 0x80, 0xb0, 0x01, 0x00, 0xd0, 0x93, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0xd1, 0x93, 0x00, 0x41,
+ 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00,
+ 0xd2, 0x93, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0xd7, 0x93, 0xa2, 0x40,
+ 0x1f, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15,
+ 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0xec, 0x93, 0x9c, 0x17,
+ 0x80, 0x32, 0x00, 0x00, 0xe1, 0x93, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e,
+ 0x98, 0xf4, 0x01, 0x00, 0xe0, 0x93, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0xe0, 0x93, 0xa2, 0x8a,
+ 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4,
+ 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00,
+ 0xeb, 0x93, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00,
+ 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3,
+ 0x3a, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04,
+ 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0,
+ 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0xf8, 0x93, 0x22, 0x45,
+ 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10,
+ 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x02, 0x94, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0x0c, 0x94, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0d, 0x94, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x62, 0xc9, 0x01, 0x00,
+ 0x0f, 0x94, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03,
+ 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00,
+ 0x19, 0x94, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x1a, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x1c, 0x94, 0xa8, 0x00,
+ 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00,
+ 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00, 0x02, 0x00, 0x00, 0x09,
+ 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x97, 0xe0, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x26, 0x94, 0x63, 0x42,
+ 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a, 0x62, 0xc9, 0x01, 0x00,
+ 0x27, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x97, 0xf0, 0x01, 0x00,
+ 0x2b, 0x94, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x33, 0x94, 0x22, 0xf3,
+ 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x94, 0x88, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00, 0x00, 0x00, 0x75, 0x55,
+ 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x40, 0x81, 0xb2, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00, 0x43, 0x94, 0x82, 0x41,
+ 0x23, 0x40, 0x00, 0x00, 0x38, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x20, 0x80, 0x00, 0x10,
+ 0x42, 0xc9, 0x01, 0x00, 0x3e, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x3b, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00,
+ 0x43, 0x94, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x43,
+ 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00,
+ 0x45, 0x94, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00, 0x46, 0x94, 0x00, 0x06,
+ 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x04, 0xb0, 0x01, 0x00,
+ 0x48, 0x94, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x04, 0xb0, 0x01, 0x00, 0x07, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00,
+ 0x72, 0x94, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, 0x4c, 0x94, 0xa2, 0x02,
+ 0x2a, 0x50, 0x00, 0x00, 0x72, 0x94, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00,
+ 0x4e, 0x94, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00, 0x57, 0x94, 0x00, 0x02,
+ 0x16, 0xc0, 0x00, 0x00, 0x56, 0x94, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00,
+ 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x56, 0x94, 0x22, 0x40,
+ 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x52, 0x94, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xf1, 0x93, 0x00, 0x5c,
+ 0x1f, 0x00, 0x01, 0x00, 0x72, 0x94, 0x22, 0x15, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, 0x71, 0x94, 0xa2, 0x02,
+ 0x1a, 0x50, 0x00, 0x00, 0x63, 0x94, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00,
+ 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x1f, 0x80, 0x01, 0x00, 0x63, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x5f, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0x2f, 0x00, 0x2f, 0x5c,
+ 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00,
+ 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x35, 0x94, 0x20, 0x15,
+ 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4,
+ 0x62, 0xdd, 0x01, 0x00, 0x6e, 0x94, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00,
+ 0x35, 0x94, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x35, 0x94, 0x00, 0x02,
+ 0x10, 0xc0, 0x00, 0x00, 0x74, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00,
+ 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x7b, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x40, 0x27, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0xb0, 0x01, 0x00, 0x99, 0x92, 0x00, 0x41, 0xa3, 0x41, 0x01, 0x00,
+ 0x7f, 0x94, 0x00, 0x41, 0x27, 0xd0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x86, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd8, 0x94, 0x00, 0x40,
+ 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06, 0x16, 0xc0, 0x01, 0x00,
+ 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00, 0x8e, 0x94, 0xa0, 0xf0,
+ 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0,
+ 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40, 0x87, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00, 0x97, 0x94, 0x22, 0x4a,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00,
+ 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x97, 0x94, 0xa4, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0xb8, 0x94, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0xa4, 0x94, 0xa2, 0x06,
+ 0x14, 0x6c, 0x00, 0x00, 0xa1, 0x94, 0x22, 0x48, 0x19, 0x7c, 0x00, 0x00,
+ 0x9c, 0x94, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x31, 0xc0, 0x01, 0x00,
+ 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x48,
+ 0x19, 0x80, 0x01, 0x00, 0x8b, 0x00, 0x20, 0x45, 0xe7, 0x91, 0x01, 0x00,
+ 0xa4, 0x94, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00, 0x08, 0x00, 0x00, 0x43,
+ 0x86, 0x98, 0x01, 0x00, 0xa4, 0x94, 0xa0, 0x48, 0x17, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40,
+ 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00,
+ 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xe5, 0xb1, 0x01, 0x00, 0xaf, 0x94, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab,
+ 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00,
+ 0xae, 0x94, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0xb3, 0x94, 0x64, 0xf0, 0x82, 0xb0, 0x00, 0x00,
+ 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb3, 0x94, 0xa2, 0xf2,
+ 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe5, 0xb1, 0x01, 0x00,
+ 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06, 0x30, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0x46,
+ 0x19, 0x90, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00,
+ 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43,
+ 0xfc, 0xc9, 0x01, 0x00, 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x4a, 0x19, 0xfc, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2,
+ 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, 0xc1, 0x94, 0xa0, 0xf0,
+ 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0xe4, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x1b, 0xe0, 0xb1, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00,
+ 0x00, 0x00, 0xa6, 0x4c, 0x95, 0x60, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4a,
+ 0x18, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40,
+ 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00,
+ 0xd1, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x5f,
+ 0x17, 0x90, 0x01, 0x00, 0x70, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x7a, 0x01, 0x2e, 0xfe, 0x92, 0xb0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0xf6,
+ 0x16, 0xb0, 0x01, 0x00, 0xde, 0x94, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6,
+ 0x2a, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x6e, 0x06, 0x82, 0xc8, 0x01, 0x00,
+ 0xe2, 0x94, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
+ 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x4c, 0x83, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, 0xe3, 0x94, 0x43, 0x30,
+ 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x66, 0x9e, 0x83, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x92, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x49, 0x98, 0xf4, 0x01, 0x00, 0xec, 0x94, 0x26, 0x30,
+ 0x93, 0x04, 0x00, 0x00, 0xec, 0x94, 0x90, 0x4c, 0x92, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x80, 0x49,
+ 0xec, 0xa9, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15,
+ 0xe0, 0xb1, 0x00, 0x00, 0xf1, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xfe, 0x94, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00, 0xfd, 0x94, 0xa2, 0x40,
+ 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x90, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x97, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0xfd, 0x94, 0x28, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xfa, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00, 0x01, 0x95, 0xa2, 0x5f,
+ 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43, 0x19, 0x7c, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54,
+ 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19,
+ 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02, 0xf0, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x13,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x08,
+ 0xe0, 0xb1, 0x00, 0x00, 0x0c, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf0,
+ 0x98, 0xf4, 0x01, 0x00, 0x15, 0x95, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00,
+ 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x15, 0x95, 0x20, 0xf2,
+ 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00,
+ 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14, 0x98, 0xd0, 0x01, 0x00,
+ 0x1a, 0x95, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c,
+ 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x80, 0xe0, 0x01, 0x00,
+ 0x1d, 0x95, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14, 0xe0, 0xb1, 0x01, 0x00,
+ 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xf3,
+ 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42, 0x82, 0xc0, 0x00, 0x00,
+ 0x23, 0x95, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x82, 0xec, 0x00, 0x00,
+ 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10,
+ 0x48, 0xb1, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x2a, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xa8, 0x00, 0x2d, 0x1c, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0,
+ 0x8a, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00,
+ 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00,
+ 0x37, 0x95, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xbe, 0x00, 0x2f, 0xab,
+ 0x83, 0xb0, 0x01, 0x00, 0x88, 0x95, 0x00, 0x14, 0x82, 0x50, 0x01, 0x00,
+ 0x3c, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3c, 0x95, 0x22, 0xf2,
+ 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x3c, 0x95, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x40,
+ 0x47, 0x99, 0x01, 0x00, 0x88, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0x30,
+ 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00,
+ 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00, 0x4f, 0x95, 0x23, 0xf0,
+ 0x84, 0x6c, 0x00, 0x00, 0x44, 0x95, 0x23, 0x92, 0x87, 0x6c, 0x00, 0x00,
+ 0xc9, 0x04, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00, 0x46, 0x95, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00,
+ 0x60, 0x89, 0x00, 0x4a, 0x94, 0x98, 0x01, 0x00, 0x46, 0x95, 0x68, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xb0, 0xb1, 0x01, 0x00,
+ 0xbf, 0x00, 0x2d, 0x42, 0xb2, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3,
+ 0x80, 0xe0, 0x01, 0x00, 0x4a, 0x95, 0xd4, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0xda, 0x84, 0xc0, 0x01, 0x00, 0x54, 0x95, 0x23, 0x40,
+ 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00,
+ 0x54, 0x95, 0x00, 0x40, 0x84, 0xb0, 0x00, 0x00, 0xbf, 0x00, 0x2d, 0x43,
+ 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, 0x80, 0xe0, 0x01, 0x00,
+ 0x54, 0x95, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d,
+ 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00,
+ 0x58, 0x95, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00, 0x9c, 0x00, 0x20, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00,
+ 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x42,
+ 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3,
+ 0x82, 0x88, 0x01, 0x00, 0x5e, 0x95, 0x23, 0x41, 0x80, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x89, 0x0c,
+ 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x41,
+ 0x24, 0xec, 0x00, 0x00, 0x68, 0x95, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x9f, 0x42, 0x38, 0xec, 0x00, 0x00, 0x68, 0x95, 0xa6, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x6a, 0x95, 0xa3, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00,
+ 0x6e, 0x95, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0xb4, 0x00, 0x20, 0x1d,
+ 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f, 0x13, 0x94, 0x01, 0x00,
+ 0x6e, 0x95, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x20, 0x1d,
+ 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12, 0xe0, 0xb1, 0x01, 0x00,
+ 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xe0, 0xb1, 0x01, 0x00,
+ 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x77, 0x95, 0x9f, 0x41,
+ 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8c, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00, 0x78, 0x95, 0x00, 0x41,
+ 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00,
+ 0xc6, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7a, 0x95, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x00, 0xa2, 0x08, 0x80, 0x32, 0x01, 0x00, 0x81, 0x95, 0xa2, 0x40,
+ 0x95, 0x6c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00,
+ 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x2f, 0x40,
+ 0x11, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x9f, 0xf8, 0x3e, 0xec, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x12,
+ 0xe0, 0xed, 0x00, 0x00, 0xc8, 0x00, 0x20, 0xab, 0xe1, 0xb1, 0x01, 0x00,
+ 0xcc, 0x00, 0xa0, 0x1f, 0xe0, 0xb1, 0x01, 0x00, 0x8a, 0x95, 0xa3, 0x5f,
+ 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe7, 0xc1, 0x01, 0x00,
+ 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x9e, 0x95, 0x22, 0xf2,
+ 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43, 0x84, 0xf4, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x42,
+ 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40, 0x86, 0xc0, 0x01, 0x00,
+ 0x92, 0x95, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00, 0x93, 0x95, 0xa2, 0x40,
+ 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41, 0x87, 0xb0, 0x01, 0x00,
+ 0x97, 0x95, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xd0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2,
+ 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44, 0x84, 0xf4, 0x01, 0x00,
+ 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40,
+ 0x88, 0xc0, 0x01, 0x00, 0x9d, 0x95, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00,
+ 0xa1, 0x95, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00, 0xa1, 0x95, 0x62, 0x41,
+ 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41, 0x86, 0xe4, 0x01, 0x00,
+ 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0x41,
+ 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00,
+ 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbc, 0x00, 0x2e, 0x43,
+ 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x86, 0xc0, 0x01, 0x00,
+ 0xa7, 0x95, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00,
+ 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00, 0x40, 0x01, 0xe2, 0x40,
+ 0x87, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x81, 0xb0, 0x01, 0x00,
+ 0x90, 0x00, 0x2d, 0xf2, 0x2e, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0xf0,
+ 0x86, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00,
+ 0xba, 0x00, 0x2d, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xb4, 0x95, 0xa2, 0x12,
+ 0x98, 0x6c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0xf2, 0x98, 0xb0, 0x01, 0x00,
+ 0xb4, 0x95, 0xa0, 0xf2, 0x98, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
+ 0x82, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x41, 0xe0, 0xb1, 0x01, 0x00,
+ 0xb4, 0x00, 0x2d, 0x12, 0x86, 0xd0, 0x01, 0x00, 0xb7, 0x95, 0xa3, 0x41,
+ 0xe0, 0x6d, 0x00, 0x00, 0xb8, 0x95, 0x00, 0xf0, 0x84, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x41, 0x84, 0xb0, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x43,
+ 0x84, 0xd0, 0x01, 0x00, 0xbb, 0x95, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xbd, 0x95, 0xa3, 0x42,
+ 0x14, 0x6c, 0x00, 0x00, 0xbe, 0x95, 0x00, 0x0a, 0x0c, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x0c, 0xb0, 0x01, 0x00, 0xc0, 0x95, 0xa0, 0x17,
+ 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x17, 0x0c, 0xb0, 0x01, 0x00,
+ 0xc5, 0x95, 0x22, 0x40, 0x0d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a,
+ 0x0c, 0xec, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0, 0x82, 0xf4, 0x01, 0x00,
+ 0xc5, 0x95, 0xa0, 0x41, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf0,
+ 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00,
+ 0x9d, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03,
+ 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41,
+ 0x87, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45,
+ 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00,
+ 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, 0xd1, 0x95, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00,
+ 0x05, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04,
+ 0xe6, 0xb1, 0x01, 0x00, 0xd7, 0x95, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0xdc, 0x95, 0x28, 0x40,
+ 0x87, 0x30, 0x00, 0x00, 0xd8, 0x95, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00,
+ 0x7e, 0x94, 0x1d, 0x46, 0x87, 0xb0, 0x00, 0x00, 0xdf, 0x95, 0x22, 0x5f,
+ 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00,
+ 0xdd, 0x95, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x14, 0x2f, 0x4c, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xe2, 0x95, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x49, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x1f, 0xb0, 0x01, 0x00, 0x35, 0x96, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x49, 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03,
+ 0x06, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00,
+ 0x20, 0x00, 0x00, 0xd0, 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x93, 0xc0, 0x01, 0x00, 0xe9, 0x95, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00,
+ 0x00, 0x00, 0x2e, 0x05, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40,
+ 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xf2, 0x95, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00,
+ 0x3b, 0x96, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xc8, 0x92, 0x00, 0x40,
+ 0x81, 0x32, 0x01, 0x00, 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xf9, 0x95, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x00, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0xfd, 0x95, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05,
+ 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x01, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00,
+ 0x64, 0x00, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40,
+ 0xe7, 0xb1, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00,
+ 0xba, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x0b, 0x96, 0xa2, 0x41,
+ 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x68, 0xb1, 0x01, 0x00, 0x0f, 0x96, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00,
+ 0x80, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x39, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x33, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x3f, 0xb3, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40,
+ 0x25, 0x9b, 0x01, 0x00, 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x2d, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40,
+ 0x2b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5,
+ 0x3c, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x2c, 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x59, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x53, 0xb3, 0x01, 0x00, 0x2b, 0x96, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00,
+ 0x2b, 0x96, 0xa2, 0x51, 0xfd, 0x7f, 0x00, 0x00, 0x2c, 0x96, 0x00, 0x40,
+ 0x1d, 0xb3, 0x00, 0x00, 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00,
+ 0x00, 0xc0, 0x00, 0xa6, 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6,
+ 0x3a, 0xb3, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00,
+ 0xb4, 0x05, 0x00, 0x40, 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x4d, 0xb3, 0x01, 0x00, 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00,
+ 0x01, 0x01, 0x00, 0x8a, 0x15, 0x9b, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6,
+ 0x56, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5e, 0x57, 0xb5, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x4b, 0x20, 0xe4, 0x01, 0x00, 0x06, 0x00, 0x00, 0x4b,
+ 0x96, 0xe4, 0x01, 0x00, 0x00, 0x43, 0x00, 0x4b, 0x96, 0xc8, 0x01, 0x00,
+ 0x18, 0x00, 0x00, 0x10, 0x20, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x20, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x57, 0x21, 0x90, 0x01, 0x00,
+ 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0xf1, 0xb1, 0x01, 0x00, 0x3c, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0xa9, 0x00, 0x40,
+ 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00,
+ 0x40, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40,
+ 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x44, 0x96, 0xa8, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0x44, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00,
+ 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88,
+ 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x41, 0x40,
+ 0x81, 0x32, 0x00, 0x00, 0xb2, 0x9f, 0x22, 0x40, 0x7b, 0x6f, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1,
+ 0xc6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00,
+ 0x08, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xa8, 0x9f, 0x00, 0x4d,
+ 0x9a, 0xcc, 0x01, 0x00, 0xbb, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0xb9, 0x9f, 0xa2, 0x41,
+ 0x9b, 0x50, 0x00, 0x00, 0xbf, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x49, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a,
+ 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x51, 0x4a, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40,
+ 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0,
+ 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00,
+ 0xca, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d,
+ 0x10, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xe3, 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4,
+ 0x45, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00,
+ 0x00, 0x00, 0x48, 0x4f, 0x40, 0xb1, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb,
+ 0x81, 0xc8, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00,
+ 0x40, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x05, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x18, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x38, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x80, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xaf, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0xd7, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x5d, 0x92, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x33, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x92, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0xd0, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x9a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+ 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40,
+ 0x81, 0xb2, 0x00, 0x00,
+ },
+};
diff --git a/drivers/staging/slicoss/oasisrcvucode.h b/drivers/staging/slicoss/oasisrcvucode.h
new file mode 100644
index 00000000000..5b3531f04cb
--- /dev/null
+++ b/drivers/staging/slicoss/oasisrcvucode.h
@@ -0,0 +1,205 @@
+#define OASIS_RCVUCODE_VERS_STRING "1.2"
+#define OASIS_RCVUCODE_VERS_DATE "2006/03/27 15:10:28"
+
+static u32 OasisRcvUCodeLen = 512;
+
+static u8 OasisRcvUCode[2560] =
+{
+0x47, 0x75, 0x01, 0x00, 0x04, 0xa0, 0x13, 0x01, 0x00, 0x1c, 0xb7, 0x5b, 0x09,
+0x30, 0x00, 0xb6, 0x5f, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x18, 0x3b,
+0x78, 0x3a, 0x00, 0x1c, 0xa2, 0x77, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x70,
+0x18, 0xad, 0x7b, 0xf1, 0xff, 0x1c, 0xb3, 0x7b, 0xa9, 0xaa, 0x1e, 0xb4, 0x7b,
+0x01, 0x0c, 0x1c, 0xb5, 0x7b, 0x0d, 0x06, 0x1c, 0x00, 0x00, 0x30, 0x64, 0x08,
+0x0c, 0x31, 0x5a, 0x70, 0x04, 0x0c, 0x31, 0x5a, 0x80, 0x04, 0x0c, 0x31, 0x4e,
+0x90, 0x04, 0x0c, 0x31, 0x4a, 0xa0, 0x00, 0x09, 0x25, 0x55, 0xc0, 0x04, 0x0c,
+0x31, 0x52, 0xb0, 0x00, 0xe9, 0x24, 0x55, 0xc0, 0x04, 0xcc, 0xb3, 0x00, 0x1c,
+0x1c, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0x06, 0x56, 0x32, 0xd4, 0x08, 0x07, 0x9d,
+0x00, 0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x10, 0xa0, 0x0f, 0x31, 0x54, 0x09,
+0x06, 0x56, 0x5e, 0xc0, 0x04, 0xa0, 0x30, 0x54, 0x03, 0x00, 0xac, 0x30, 0x55,
+0x03, 0x00, 0xcd, 0x03, 0x3a, 0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0x60,
+0x8e, 0x31, 0x54, 0x09, 0x29, 0x25, 0x55, 0x03, 0x00, 0x80, 0x8e, 0x31, 0x54,
+0x09, 0x8c, 0x30, 0x91, 0x00, 0x04, 0x47, 0x1c, 0x01, 0x00, 0x1c, 0xa0, 0x0f,
+0x31, 0x54, 0x09, 0x00, 0x00, 0x64, 0x00, 0x04, 0x47, 0x1c, 0x65, 0xc0, 0x04,
+0x47, 0x1c, 0x55, 0x03, 0x00, 0x6c, 0x30, 0x01, 0x00, 0x1c, 0x4d, 0x34, 0x02,
+0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xc8,
+0x83, 0x37, 0x00, 0x1c, 0x80, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x64, 0x00,
+0x04, 0xa0, 0x0f, 0x30, 0x54, 0x09, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x7b, 0xfb,
+0xf2, 0x00, 0x1c, 0xcc, 0x33, 0x0d, 0x00, 0x1c, 0xb4, 0x7b, 0xfd, 0x03, 0x1c,
+0x80, 0x0e, 0x30, 0x54, 0x09, 0xe0, 0xfb, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x8c,
+0x03, 0x00, 0xb3, 0x0f, 0x31, 0x54, 0x09, 0x00, 0x00, 0xec, 0x70, 0x04, 0x00,
+0x00, 0xec, 0x80, 0x04, 0x00, 0x00, 0x8c, 0x93, 0x00, 0x61, 0x76, 0x8d, 0xc3,
+0x04, 0xc0, 0x8d, 0x31, 0x54, 0x09, 0xe0, 0x7b, 0x00, 0xc0, 0x1f, 0xa0, 0xfd,
+0xc5, 0x01, 0x00, 0xcc, 0x33, 0x05, 0x00, 0x1c, 0xd4, 0x03, 0x00, 0x3c, 0x1c,
+0xd4, 0xd3, 0x1b, 0x00, 0x1c, 0xc0, 0xd3, 0x52, 0x00, 0x1c, 0x00, 0x00, 0x5c,
+0x13, 0x04, 0x8e, 0x8e, 0x32, 0x54, 0x09, 0x5b, 0x80, 0x5e, 0x13, 0x04, 0x00,
+0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x94, 0x01, 0x00, 0xa0, 0x0f, 0x31, 0x54,
+0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xc0, 0x03, 0xfc, 0x7f, 0x1c, 0xa0, 0x01,
+0xa0, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0xa0, 0x0f, 0x31, 0x54, 0x09,
+0xc0, 0x03, 0xfc, 0x03, 0x1c, 0xf5, 0x77, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0xe6,
+0x05, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xb3, 0x0f, 0x31, 0x54, 0x09, 0xb5,
+0x02, 0x02, 0x00, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0x7a, 0x7e, 0x02, 0x00,
+0x1c, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0x53, 0x0f, 0x32, 0x54, 0x09, 0xaf, 0x03,
+0x01, 0x00, 0x1c, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c,
+0x00, 0x00, 0x02, 0x00, 0x1c, 0xa0, 0x3d, 0xaa, 0x11, 0x04, 0x00, 0x00, 0xac,
+0x11, 0x04, 0xd4, 0xd3, 0x52, 0x00, 0x1c, 0xb5, 0x3e, 0xb2, 0x01, 0x00, 0x20,
+0xfb, 0xfd, 0xff, 0x1f, 0x80, 0x2c, 0x6c, 0x03, 0x00, 0xb9, 0x3a, 0x9e, 0x01,
+0x00, 0x75, 0x3b, 0x02, 0x00, 0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xdb, 0x83,
+0x16, 0x00, 0x1c, 0xc7, 0x1d, 0x21, 0xc1, 0x04, 0xb9, 0x3b, 0x8d, 0xc1, 0x04,
+0x8b, 0x2c, 0x01, 0x00, 0x1c, 0x6b, 0x2c, 0x35, 0xc1, 0x04, 0x00, 0x00, 0x78,
+0x11, 0x00, 0xcb, 0x2c, 0x79, 0xc1, 0x04, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0,
+0x0f, 0x31, 0x54, 0x09, 0x54, 0xd0, 0x02, 0x00, 0x1c, 0x49, 0x25, 0xb1, 0x01,
+0x00, 0xab, 0x2c, 0x81, 0xc1, 0x04, 0xa7, 0x1d, 0x55, 0x03, 0x00, 0xcc, 0x33,
+0x09, 0x00, 0x1c, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c,
+0xa0, 0x0f, 0x31, 0x54, 0x09, 0xae, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31,
+0x54, 0x09, 0xd4, 0x07, 0xfc, 0x03, 0x1c, 0x99, 0x3a, 0x02, 0x00, 0x1c, 0xbb,
+0x38, 0x02, 0x00, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0x01,
+0x04, 0xdb, 0x3b, 0x7e, 0x00, 0x1c, 0xc7, 0x1d, 0x01, 0x00, 0x1c, 0x26, 0x7a,
+0xfa, 0x05, 0x1c, 0x27, 0x1d, 0x01, 0x00, 0x1c, 0xb3, 0x0f, 0x31, 0x54, 0x09,
+0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32,
+0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53,
+0x0f, 0x32, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00,
+0x1c, 0x53, 0x0f, 0x32, 0x54, 0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e,
+0x32, 0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09,
+0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53, 0x0f, 0x32,
+0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x00, 0x3d, 0x02, 0x00, 0x1c, 0x00,
+0x00, 0x58, 0x12, 0x00, 0xcb, 0x2c, 0x01, 0x00, 0x1c, 0x75, 0x3b, 0x02, 0x00,
+0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xcb, 0x2f, 0x05, 0x00, 0x1c, 0x60, 0x2c,
+0x00, 0x00, 0x1c, 0xc7, 0x1c, 0xc9, 0x02, 0x00, 0xa0, 0x0f, 0x31, 0x54, 0x09,
+0x53, 0x07, 0x02, 0x00, 0x1c, 0x46, 0x7a, 0xca, 0x05, 0x1c, 0x7a, 0x0e, 0x32,
+0x54, 0x09, 0x40, 0xfa, 0x19, 0x00, 0x1c, 0x00, 0x00, 0x88, 0x02, 0x04, 0x46,
+0x7a, 0xca, 0x05, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54,
+0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xb3, 0x7b,
+0x01, 0xc0, 0x1f, 0x74, 0x0e, 0x30, 0x54, 0x09, 0xc0, 0x03, 0x9c, 0x00, 0x1c,
+0x80, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x04, 0x00, 0x00, 0xac,
+0x12, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xd4, 0xd3, 0x2b, 0x00, 0x1c, 0xd4,
+0xd3, 0x52, 0x00, 0x1c, 0x80, 0x76, 0x7d, 0x13, 0x04, 0x00, 0x00, 0xe0, 0x02,
+0x00, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0xc7, 0x9c, 0x00, 0x00, 0x1c, 0x80, 0x2c,
+0x00, 0x00, 0x1c, 0x00, 0x00, 0x6c, 0x02, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04,
+0xab, 0x2d, 0xd9, 0x12, 0x05, 0x07, 0x1d, 0xb5, 0xc2, 0x04, 0x8b, 0x2d, 0x01,
+0x00, 0x1c, 0x69, 0x25, 0x01, 0x00, 0x1c, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0xcb,
+0x2f, 0x09, 0x00, 0x1c, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x48, 0x03,
+0x00, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x46, 0x7a, 0xca, 0x05, 0x1c, 0x7a, 0x0e,
+0x32, 0x54, 0x09, 0x40, 0xfa, 0x19, 0x00, 0x1c, 0x00, 0x00, 0x10, 0x03, 0x04,
+0x46, 0x7a, 0xca, 0x05, 0x1c, 0xb5, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31,
+0x54, 0x09, 0x73, 0xec, 0x2a, 0x03, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0x00,
+0x00, 0x28, 0x03, 0x00, 0xc7, 0x1c, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x28, 0x13,
+0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xc0, 0xd7, 0x22, 0x00, 0x1c, 0x75, 0x56,
+0x7e, 0x13, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0xe7, 0x1c, 0x45, 0x03, 0x04,
+0xe7, 0x9c, 0x00, 0x00, 0x1c, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0x80, 0x2c, 0x00,
+0x00, 0x1c, 0x00, 0x00, 0xf8, 0x02, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0xb9,
+0x7b, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07,
+0x1c, 0xcb, 0x2f, 0x01, 0x04, 0x1c, 0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00,
+0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x0d, 0x04, 0x1c,
+0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00, 0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0x00,
+0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x00, 0x1d, 0xa6, 0x7b, 0x95, 0x03, 0x1c, 0xc7,
+0x9c, 0x8c, 0xc3, 0x04, 0x00, 0x00, 0x8c, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00,
+0x1c, 0xc0, 0x1d, 0xdc, 0xd3, 0x08, 0x27, 0x9d, 0xe4, 0x03, 0x00, 0xa0, 0xee,
+0x46, 0xd4, 0x00, 0xfb, 0x75, 0x09, 0x14, 0x04, 0x20, 0x7b, 0x06, 0x00, 0x1c,
+0xc0, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0xb0, 0xd3, 0x08, 0x00, 0x00, 0x00,
+0xf4, 0x00, 0xc0, 0xef, 0xf2, 0x00, 0x1c, 0x20, 0x25, 0x5c, 0x14, 0x04, 0x60,
+0xb7, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x15, 0x00, 0xcc, 0xb3, 0xfc, 0x03,
+0x1c, 0xcc, 0x33, 0x05, 0x02, 0x1c, 0x00, 0x00, 0x0c, 0xc5, 0x04, 0x60, 0xb7,
+0x0e, 0x05, 0x04, 0x00, 0x00, 0x0c, 0x15, 0x04, 0x00, 0x00, 0x5c, 0xc4, 0x04,
+0xc0, 0x1d, 0x98, 0xf3, 0x04, 0x00, 0x00, 0x68, 0xc4, 0x04, 0x07, 0x9d, 0x00,
+0x00, 0x1c, 0x1b, 0x74, 0xfd, 0xf3, 0x04, 0xa6, 0x7b, 0xf1, 0x03, 0x1c, 0xa0,
+0x0f, 0x69, 0x54, 0x09, 0xe0, 0x7b, 0x00, 0xfc, 0x1f, 0x39, 0x7f, 0x02, 0x00,
+0x1c, 0x07, 0x1d, 0x9d, 0xc3, 0x04, 0xa6, 0x7b, 0xad, 0x03, 0x1c, 0x00, 0x00,
+0x68, 0xc4, 0x04, 0xe0, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xa4, 0x03, 0x04,
+0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x10, 0x1d, 0x00, 0x00, 0xac,
+0xc3, 0x04, 0x00, 0x00, 0xac, 0x03, 0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb,
+0x2f, 0x01, 0x18, 0x1d, 0xc7, 0x9f, 0x00, 0x0b, 0x1c, 0x00, 0x00, 0xac, 0xc3,
+0x04, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xcc, 0xb3,
+0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02, 0x1c, 0x00, 0x00, 0xac, 0xc3, 0x04,
+0xa0, 0x1c, 0x00, 0x00, 0x1c, 0xa0, 0xee, 0xa2, 0x03, 0x04, 0xcb, 0xaf, 0xfc,
+0x07, 0x1c, 0xcb, 0x2f, 0x09, 0x04, 0x1c, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x00,
+0x00, 0xac, 0xc3, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02,
+0x1c, 0x00, 0x00, 0x0c, 0xc5, 0x04, 0x00, 0x00, 0x78, 0x34, 0x05, 0xcc, 0xb3,
+0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x15, 0x02, 0x1c, 0x47, 0x9d, 0x54, 0xc4, 0x04,
+0x00, 0x00, 0x78, 0x44, 0x00, 0x80, 0x1d, 0x7c, 0x54, 0x04, 0x87, 0x1d, 0x8d,
+0x04, 0x00, 0xce, 0x76, 0x01, 0x00, 0x1c, 0xef, 0x76, 0x9d, 0xc4, 0x04, 0xa4,
+0x77, 0x8d, 0x24, 0x09, 0xe4, 0x76, 0x01, 0x00, 0x1c, 0xc4, 0x76, 0x01, 0x00,
+0x1c, 0x00, 0x00, 0x98, 0x54, 0x04, 0xd7, 0x76, 0x01, 0x50, 0x18, 0xf6, 0x76,
+0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10,
+0xcc, 0x30, 0x45, 0xc5, 0x04, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01,
+0x00, 0x1c, 0xc0, 0x59, 0x01, 0x00, 0x1c, 0xf5, 0x77, 0x29, 0xc5, 0x04, 0xe0,
+0x30, 0xdc, 0x04, 0x00, 0x00, 0x4c, 0xb0, 0x04, 0x00, 0x20, 0x4c, 0xf4, 0x04,
+0x00, 0x00, 0x00, 0xe8, 0x04, 0x00, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33,
+0x09, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c,
+0xcc, 0x33, 0x19, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc,
+0x03, 0x1c, 0xcc, 0x33, 0x0d, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc,
+0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x11, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4,
+0x04, 0x00, 0x7b, 0x00, 0x80, 0x1c, 0xae, 0x77, 0x45, 0x05, 0x00, 0x00, 0x00,
+0x04, 0xc0, 0x04, 0xd3, 0x8b, 0x00, 0xfc, 0x1f, 0x60, 0x7a, 0x3c, 0x00, 0x1c,
+0x60, 0x4c, 0xc0, 0x04, 0x00, 0xc0, 0x2f, 0x20, 0x05, 0x1f, 0xe0, 0x30, 0xb0,
+0x04, 0x00, 0x80, 0x25, 0xb0, 0x04, 0x00, 0xb5, 0x5b, 0xb1, 0x04, 0x04, 0x69,
+0x26, 0x01, 0x00, 0x1c, 0x6a, 0x2b, 0x01, 0x00, 0x1c, 0x80, 0x1d, 0x00, 0x00,
+0x1c, 0xa9, 0x25, 0x45, 0x05, 0x00, 0xee, 0x30, 0x00, 0x00, 0x1c, 0xaf, 0x77,
+0x01, 0x05, 0x00, 0x00, 0x00, 0xac, 0x24, 0x04, 0xb4, 0x5f, 0x01, 0x40, 0x18,
+0x07, 0x9d, 0x48, 0x55, 0x04, 0xb7, 0x76, 0x01, 0x00, 0x1c, 0x96, 0x76, 0x01,
+0x00, 0x1c, 0x47, 0x1d, 0x01, 0x00, 0x1c, 0xa4, 0x33, 0x01, 0x60, 0x18, 0xa4,
+0x2f, 0x01, 0x60, 0x18, 0x64, 0x77, 0x01, 0x60, 0x18, 0x24, 0x77, 0x01, 0x60,
+0x18, 0x44, 0x77, 0x01, 0x00, 0x1c, 0x64, 0x88, 0x03, 0x00, 0x1c, 0xa4, 0x3f,
+0x01, 0x00, 0x1c, 0xa4, 0x3b, 0x01, 0x00, 0x1c, 0x53, 0x7b, 0x00, 0xc0, 0x1c,
+0xd3, 0xcf, 0x1b, 0x00, 0x1c, 0x53, 0x4f, 0x02, 0x00, 0x1c, 0xda, 0xcf, 0x00,
+0xc0, 0x1f, 0xd5, 0x57, 0x0f, 0x00, 0x1c, 0xd3, 0xd3, 0x37, 0x00, 0x1c, 0xd4,
+0x53, 0x0f, 0x00, 0x1c, 0xe0, 0x29, 0x00, 0x00, 0x1c, 0xf5, 0xd5, 0xb0, 0x05,
+0x00, 0x00, 0x00, 0x9c, 0x55, 0x04, 0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53,
+0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04,
+0xf5, 0x55, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xb4, 0x55, 0x04, 0x77, 0x56, 0x01,
+0x00, 0x1c, 0x56, 0x53, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00,
+0x00, 0x04, 0xc0, 0x04, 0xcb, 0x2f, 0x01, 0x18, 0x10, 0xcb, 0x2f, 0x01, 0x10,
+0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f,
+0x01, 0x20, 0x10, 0xcb, 0x2f, 0x01, 0x28, 0x10, 0xcb, 0x2f, 0x01, 0x00, 0x10,
+0x89, 0x25, 0x61, 0xc2, 0x04, 0x00, 0x00, 0xec, 0xc2, 0x04, 0x00, 0x00, 0x54,
+0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00,
+0x00, 0x60, 0xc2, 0x04, 0x00, 0x00, 0xec, 0xc2, 0x04, 0x00, 0x00, 0x54, 0xc3,
+0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x40, 0x1c,
+0x6c, 0xc0, 0x04, 0x40, 0x1c, 0x9c, 0xc0, 0x04, 0xa7, 0x77, 0x55, 0xc3, 0x04,
+0x00, 0x00, 0xc4, 0xc0, 0x04, 0x27, 0x1d, 0xf1, 0xc0, 0x04, 0x00, 0x00, 0x54,
+0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00,
+0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6,
+0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00,
+0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c,
+0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04,
+};
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
new file mode 100644
index 00000000000..0d5dc24c0b7
--- /dev/null
+++ b/drivers/staging/slicoss/slic.h
@@ -0,0 +1,598 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slic.h
+ *
+ * This is the base set of header definitions for the SLICOSS driver.
+ */
+#ifndef __SLIC_DRIVER_H__
+#define __SLIC_DRIVER_H__
+
+
+struct slic_spinlock {
+ spinlock_t lock;
+ unsigned long flags;
+};
+
+#define SLIC_RSPQ_PAGES_GB 10
+#define SLIC_RSPQ_BUFSINPAGE (PAGE_SIZE / SLIC_RSPBUF_SIZE)
+
+struct slic_rspqueue {
+ u32 offset;
+ u32 pageindex;
+ u32 num_pages;
+ struct slic_rspbuf *rspbuf;
+ u32 *vaddr[SLIC_RSPQ_PAGES_GB];
+ dma_addr_t paddr[SLIC_RSPQ_PAGES_GB];
+};
+
+#define SLIC_RCVQ_EXPANSION 1
+#define SLIC_RCVQ_ENTRIES (256 * SLIC_RCVQ_EXPANSION)
+#define SLIC_RCVQ_MINENTRIES (SLIC_RCVQ_ENTRIES / 2)
+#define SLIC_RCVQ_MAX_PROCESS_ISR ((SLIC_RCVQ_ENTRIES * 4))
+#define SLIC_RCVQ_RCVBUFSIZE 2048
+#define SLIC_RCVQ_FILLENTRIES (16 * SLIC_RCVQ_EXPANSION)
+#define SLIC_RCVQ_FILLTHRESH (SLIC_RCVQ_ENTRIES - SLIC_RCVQ_FILLENTRIES)
+
+struct slic_rcvqueue {
+ struct sk_buff *head;
+ struct sk_buff *tail;
+ u32 count;
+ u32 size;
+ u32 errors;
+};
+
+struct slic_rcvbuf_info {
+ u32 id;
+ u32 starttime;
+ u32 stoptime;
+ u32 slicworld;
+ u32 lasttime;
+ u32 lastid;
+};
+/*
+ SLIC Handle structure. Used to restrict handle values to
+ 32 bits by using an index rather than an address.
+ Simplifies ucode in 64-bit systems
+*/
+struct slic_handle_word {
+ union {
+ struct {
+ ushort index;
+ ushort bottombits; /* to denote num bufs to card */
+ } parts;
+ u32 whole;
+ } handle;
+};
+
+struct slic_handle {
+ struct slic_handle_word token; /* token passed between host and card*/
+ ushort type;
+ void *address; /* actual address of the object*/
+ ushort offset;
+ struct slic_handle *other_handle;
+ struct slic_handle *next;
+};
+
+#define SLIC_HANDLE_FREE 0x0000
+#define SLIC_HANDLE_DATA 0x0001
+#define SLIC_HANDLE_CMD 0x0002
+#define SLIC_HANDLE_CONTEXT 0x0003
+#define SLIC_HANDLE_TEAM 0x0004
+
+#define handle_index handle.parts.index
+#define handle_bottom handle.parts.bottombits
+#define handle_token handle.whole
+
+#define SLIC_HOSTCMD_SIZE 512
+
+struct slic_hostcmd {
+ struct slic_host64_cmd cmd64;
+ u32 type;
+ struct sk_buff *skb;
+ u32 paddrl;
+ u32 paddrh;
+ u32 busy;
+ u32 cmdsize;
+ ushort numbufs;
+ struct slic_handle *pslic_handle;/* handle associated with command */
+ struct slic_hostcmd *next;
+ struct slic_hostcmd *next_all;
+};
+
+#define SLIC_CMDQ_CMDSINPAGE (PAGE_SIZE / SLIC_HOSTCMD_SIZE)
+#define SLIC_CMD_DUMB 3
+#define SLIC_CMDQ_INITCMDS 256
+#define SLIC_CMDQ_MAXCMDS 256
+#define SLIC_CMDQ_MAXOUTSTAND SLIC_CMDQ_MAXCMDS
+#define SLIC_CMDQ_MAXPAGES (SLIC_CMDQ_MAXCMDS / SLIC_CMDQ_CMDSINPAGE)
+#define SLIC_CMDQ_INITPAGES (SLIC_CMDQ_INITCMDS / SLIC_CMDQ_CMDSINPAGE)
+
+struct slic_cmdqmem {
+ int pagecnt;
+ u32 *pages[SLIC_CMDQ_MAXPAGES];
+ dma_addr_t dma_pages[SLIC_CMDQ_MAXPAGES];
+};
+
+struct slic_cmdqueue {
+ struct slic_hostcmd *head;
+ struct slic_hostcmd *tail;
+ int count;
+ struct slic_spinlock lock;
+};
+
+#ifdef STATUS_SUCCESS
+#undef STATUS_SUCCESS
+#endif
+
+#define STATUS_SUCCESS 0
+#define STATUS_PENDING 0
+#define STATUS_FAILURE -1
+#define STATUS_ERROR -2
+#define STATUS_NOT_SUPPORTED -3
+#define STATUS_BUFFER_TOO_SHORT -4
+
+#define SLIC_MAX_CARDS 32
+#define SLIC_MAX_PORTS 4 /* Max # of ports per card */
+#if SLIC_DUMP_ENABLED
+/*
+Dump buffer size
+
+This cannot be bigger than the max DMA size the card supports,
+given the current code structure in the host and ucode.
+Mojave supports 16K, Oasis supports 16K-1, so
+just set this at 15K, shouldnt make that much of a diff.
+*/
+#define DUMP_BUF_SIZE 0x3C00
+#endif
+
+
+struct mcast_address {
+ unsigned char address[6];
+ struct mcast_address *next;
+};
+
+#define CARD_DOWN 0x00000000
+#define CARD_UP 0x00000001
+#define CARD_FAIL 0x00000002
+#define CARD_DIAG 0x00000003
+#define CARD_SLEEP 0x00000004
+
+#define ADAPT_DOWN 0x00
+#define ADAPT_UP 0x01
+#define ADAPT_FAIL 0x02
+#define ADAPT_RESET 0x03
+#define ADAPT_SLEEP 0x04
+
+#define ADAPT_FLAGS_BOOTTIME 0x0001
+#define ADAPT_FLAGS_IS64BIT 0x0002
+#define ADAPT_FLAGS_PENDINGLINKDOWN 0x0004
+#define ADAPT_FLAGS_FIBERMEDIA 0x0008
+#define ADAPT_FLAGS_LOCKS_ALLOCED 0x0010
+#define ADAPT_FLAGS_INT_REGISTERED 0x0020
+#define ADAPT_FLAGS_LOAD_TIMER_SET 0x0040
+#define ADAPT_FLAGS_STATS_TIMER_SET 0x0080
+#define ADAPT_FLAGS_RESET_TIMER_SET 0x0100
+
+#define LINK_DOWN 0x00
+#define LINK_CONFIG 0x01
+#define LINK_UP 0x02
+
+#define LINK_10MB 0x00
+#define LINK_100MB 0x01
+#define LINK_AUTOSPEED 0x02
+#define LINK_1000MB 0x03
+#define LINK_10000MB 0x04
+
+#define LINK_HALFD 0x00
+#define LINK_FULLD 0x01
+#define LINK_AUTOD 0x02
+
+#define MAC_DIRECTED 0x00000001
+#define MAC_BCAST 0x00000002
+#define MAC_MCAST 0x00000004
+#define MAC_PROMISC 0x00000008
+#define MAC_LOOPBACK 0x00000010
+#define MAC_ALLMCAST 0x00000020
+
+#define SLIC_DUPLEX(x) ((x == LINK_FULLD) ? "FDX" : "HDX")
+#define SLIC_SPEED(x) ((x == LINK_100MB) ? "100Mb" : ((x == LINK_1000MB) ?\
+ "1000Mb" : " 10Mb"))
+#define SLIC_LINKSTATE(x) ((x == LINK_DOWN) ? "Down" : "Up ")
+#define SLIC_ADAPTER_STATE(x) ((x == ADAPT_UP) ? "UP" : "Down")
+#define SLIC_CARD_STATE(x) ((x == CARD_UP) ? "UP" : "Down")
+
+struct slic_iface_stats {
+ /*
+ * Stats
+ */
+ u64 xmt_bytes;
+ u64 xmt_ucast;
+ u64 xmt_mcast;
+ u64 xmt_bcast;
+ u64 xmt_errors;
+ u64 xmt_discards;
+ u64 xmit_collisions;
+ u64 xmit_excess_xmit_collisions;
+ u64 rcv_bytes;
+ u64 rcv_ucast;
+ u64 rcv_mcast;
+ u64 rcv_bcast;
+ u64 rcv_errors;
+ u64 rcv_discards;
+};
+
+struct sliccp_stats {
+ u64 xmit_tcp_segs;
+ u64 xmit_tcp_bytes;
+ u64 rcv_tcp_segs;
+ u64 rcv_tcp_bytes;
+};
+
+struct slicnet_stats {
+ struct sliccp_stats tcp;
+ struct slic_iface_stats iface;
+};
+
+#define SLIC_LOADTIMER_PERIOD 1
+#define SLIC_INTAGG_DEFAULT 200
+#define SLIC_LOAD_0 0
+#define SLIC_INTAGG_0 0
+#define SLIC_LOAD_1 8000
+#define SLIC_LOAD_2 10000
+#define SLIC_LOAD_3 12000
+#define SLIC_LOAD_4 14000
+#define SLIC_LOAD_5 16000
+#define SLIC_INTAGG_1 50
+#define SLIC_INTAGG_2 100
+#define SLIC_INTAGG_3 150
+#define SLIC_INTAGG_4 200
+#define SLIC_INTAGG_5 250
+#define SLIC_LOAD_1GB 3000
+#define SLIC_LOAD_2GB 6000
+#define SLIC_LOAD_3GB 12000
+#define SLIC_LOAD_4GB 24000
+#define SLIC_LOAD_5GB 48000
+#define SLIC_INTAGG_1GB 50
+#define SLIC_INTAGG_2GB 75
+#define SLIC_INTAGG_3GB 100
+#define SLIC_INTAGG_4GB 100
+#define SLIC_INTAGG_5GB 100
+
+struct ether_header {
+ unsigned char ether_dhost[6];
+ unsigned char ether_shost[6];
+ ushort ether_type;
+};
+
+struct sliccard {
+ uint busnumber;
+ uint slotnumber;
+ uint state;
+ uint cardnum;
+ uint card_size;
+ uint adapters_activated;
+ uint adapters_allocated;
+ uint adapters_sleeping;
+ uint gennumber;
+ u32 events;
+ u32 loadlevel_current;
+ u32 load;
+ uint reset_in_progress;
+ u32 pingstatus;
+ u32 bad_pingstatus;
+ struct timer_list loadtimer;
+ u32 loadtimerset;
+ uint config_set;
+ struct slic_config config;
+ struct dentry *debugfs_dir;
+ struct dentry *debugfs_cardinfo;
+ struct adapter *master;
+ struct adapter *adapter[SLIC_MAX_PORTS];
+ struct sliccard *next;
+ u32 error_interrupts;
+ u32 error_rmiss_interrupts;
+ u32 rcv_interrupts;
+ u32 xmit_interrupts;
+ u32 num_isrs;
+ u32 false_interrupts;
+ u32 max_isr_rcvs;
+ u32 max_isr_xmits;
+ u32 rcv_interrupt_yields;
+ u32 tx_packets;
+#if SLIC_DUMP_ENABLED
+ u32 dumpstatus; /* Result of dump UPR */
+ void *cmdbuffer;
+
+ ulong cmdbuffer_phys;
+ u32 cmdbuffer_physl;
+ u32 cmdbuffer_physh;
+
+ u32 dump_count;
+ struct task_struct *dump_task_id;
+ u32 dump_wait_count;
+ uint dumpthread_running; /* has a dump thread been init'd */
+ uint dump_requested; /* 0 no, 1 = reqstd 2=curr 3=done */
+ u32 dumptime_start;
+ u32 dumptime_complete;
+ u32 dumptime_delta;
+ void *dumpbuffer;
+ ulong dumpbuffer_phys;
+ u32 dumpbuffer_physl;
+ u32 dumpbuffer_physh;
+ wait_queue_head_t dump_wq;
+ struct file *dumphandle;
+ mm_segment_t dumpfile_fs;
+#endif
+ u32 debug_ix;
+ ushort reg_type[32];
+ ushort reg_offset[32];
+ u32 reg_value[32];
+ u32 reg_valueh[32];
+};
+
+#define NUM_CFG_SPACES 2
+#define NUM_CFG_REGS 64
+#define NUM_CFG_REG_ULONGS (NUM_CFG_REGS / sizeof(u32))
+
+struct physcard {
+ struct adapter *adapter[SLIC_MAX_PORTS];
+ struct physcard *next;
+ uint adapters_allocd;
+
+ /* the following is not currently needed
+ u32 bridge_busnum;
+ u32 bridge_cfg[NUM_CFG_SPACES][NUM_CFG_REG_ULONGS];
+ */
+};
+
+struct base_driver {
+ struct slic_spinlock driver_lock;
+ u32 num_slic_cards;
+ u32 num_slic_ports;
+ u32 num_slic_ports_active;
+ u32 dynamic_intagg;
+ struct sliccard *slic_card;
+ struct physcard *phys_card;
+ uint cardnuminuse[SLIC_MAX_CARDS];
+};
+
+struct slic_shmem {
+ volatile u32 isr;
+ volatile u32 linkstatus;
+ volatile struct slic_stats inicstats;
+};
+
+struct slic_reg_params {
+ u32 linkspeed;
+ u32 linkduplex;
+ u32 fail_on_bad_eeprom;
+};
+
+struct slic_upr {
+ uint adapter;
+ u32 upr_request;
+ u32 upr_data;
+ u32 upr_data_h;
+ u32 upr_buffer;
+ u32 upr_buffer_h;
+ struct slic_upr *next;
+};
+
+struct slic_ifevents {
+ uint oflow802;
+ uint uflow802;
+ uint Tprtoflow;
+ uint rcvearly;
+ uint Bufov;
+ uint Carre;
+ uint Longe;
+ uint Invp;
+ uint Crc;
+ uint Drbl;
+ uint Code;
+ uint IpHlen;
+ uint IpLen;
+ uint IpCsum;
+ uint TpCsum;
+ uint TpHlen;
+};
+
+struct adapter {
+ void *ifp;
+ struct sliccard *card;
+ uint port;
+ struct physcard *physcard;
+ uint physport;
+ uint cardindex;
+ uint card_size;
+ uint chipid;
+ struct net_device *netdev;
+ struct net_device *next_netdevice;
+ struct slic_spinlock adapter_lock;
+ struct slic_spinlock reset_lock;
+ struct pci_dev *pcidev;
+ uint busnumber;
+ uint slotnumber;
+ uint functionnumber;
+ ushort vendid;
+ ushort devid;
+ ushort subsysid;
+ u32 irq;
+ void __iomem *memorybase;
+ u32 memorylength;
+ u32 drambase;
+ u32 dramlength;
+ uint queues_initialized;
+ uint allocated;
+ uint activated;
+ u32 intrregistered;
+ uint isp_initialized;
+ uint gennumber;
+ u32 curaddrupper;
+ struct slic_shmem *pshmem;
+ dma_addr_t phys_shmem;
+ u32 isrcopy;
+ __iomem struct slic_regs *slic_regs;
+ unsigned char state;
+ unsigned char linkstate;
+ unsigned char linkspeed;
+ unsigned char linkduplex;
+ uint flags;
+ unsigned char macaddr[6];
+ unsigned char currmacaddr[6];
+ u32 macopts;
+ ushort devflags_prev;
+ u64 mcastmask;
+ struct mcast_address *mcastaddrs;
+ struct slic_upr *upr_list;
+ uint upr_busy;
+ struct timer_list pingtimer;
+ u32 pingtimerset;
+ struct timer_list statstimer;
+ u32 statstimerset;
+ struct timer_list loadtimer;
+ u32 loadtimerset;
+ struct dentry *debugfs_entry;
+ struct slic_spinlock upr_lock;
+ struct slic_spinlock bit64reglock;
+ struct slic_rspqueue rspqueue;
+ struct slic_rcvqueue rcvqueue;
+ struct slic_cmdqueue cmdq_free;
+ struct slic_cmdqueue cmdq_done;
+ struct slic_cmdqueue cmdq_all;
+ struct slic_cmdqmem cmdqmem;
+ /*
+ * SLIC Handles
+ */
+ struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1]; /* Object handles*/
+ struct slic_handle *pfree_slic_handles; /* Free object handles*/
+ struct slic_spinlock handle_lock; /* Object handle list lock*/
+ ushort slic_handle_ix;
+
+ u32 xmitq_full;
+ u32 all_reg_writes;
+ u32 icr_reg_writes;
+ u32 isr_reg_writes;
+ u32 error_interrupts;
+ u32 error_rmiss_interrupts;
+ u32 rx_errors;
+ u32 rcv_drops;
+ u32 rcv_interrupts;
+ u32 xmit_interrupts;
+ u32 linkevent_interrupts;
+ u32 upr_interrupts;
+ u32 num_isrs;
+ u32 false_interrupts;
+ u32 tx_packets;
+ u32 xmit_completes;
+ u32 tx_drops;
+ u32 rcv_broadcasts;
+ u32 rcv_multicasts;
+ u32 rcv_unicasts;
+ u32 max_isr_rcvs;
+ u32 max_isr_xmits;
+ u32 rcv_interrupt_yields;
+ u32 intagg_period;
+ struct inicpm_state *inicpm_info;
+ void *pinicpm_info;
+ struct slic_reg_params reg_params;
+ struct slic_ifevents if_events;
+ struct slic_stats inicstats_prev;
+ struct slicnet_stats slic_stats;
+ struct net_device_stats stats;
+};
+
+#if SLIC_DUMP_ENABLED
+#define SLIC_DUMP_REQUESTED 1
+#define SLIC_DUMP_IN_PROGRESS 2
+#define SLIC_DUMP_DONE 3
+
+/****************************************************************************
+ *
+ * Microcode crash information structure. This
+ * structure is written out to the card's SRAM when the microcode panic's.
+ *
+ ****************************************************************************/
+struct slic_crash_info {
+ ushort cpu_id;
+ ushort crash_pc;
+};
+
+#define CRASH_INFO_OFFSET 0x155C
+
+#endif
+
+#define UPDATE_STATS(largestat, newstat, oldstat) \
+{ \
+ if ((newstat) < (oldstat)) \
+ (largestat) += ((newstat) + (0xFFFFFFFF - oldstat + 1)); \
+ else \
+ (largestat) += ((newstat) - (oldstat)); \
+}
+
+#define UPDATE_STATS_GB(largestat, newstat, oldstat) \
+{ \
+ (largestat) += ((newstat) - (oldstat)); \
+}
+
+#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \
+{ \
+ _Result = TRUE; \
+ if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \
+ _Result = FALSE; \
+ if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \
+ _Result = FALSE; \
+}
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+#define SLIC_GET_ADDR_LOW(_addr) (u32)((u64)(_addr) & \
+ 0x00000000FFFFFFFF)
+#define SLIC_GET_ADDR_HIGH(_addr) (u32)(((u64)(_addr) >> 32) & \
+ 0x00000000FFFFFFFF)
+#else
+#define SLIC_GET_ADDR_LOW(_addr) (u32)_addr
+#define SLIC_GET_ADDR_HIGH(_addr) (u32)0
+#endif
+
+#define FLUSH TRUE
+#define DONT_FLUSH FALSE
+
+#define SIOCSLICDUMPCARD (SIOCDEVPRIVATE+9)
+#define SIOCSLICSETINTAGG (SIOCDEVPRIVATE+10)
+#define SIOCSLICTRACEDUMP (SIOCDEVPRIVATE+11)
+
+#endif /* __SLIC_DRIVER_H__ */
diff --git a/drivers/staging/slicoss/slic_os.h b/drivers/staging/slicoss/slic_os.h
new file mode 100644
index 00000000000..46c678440d2
--- /dev/null
+++ b/drivers/staging/slicoss/slic_os.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+ *
+ * Copyright (c)2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slic_os.h
+ *
+ * These are the Linux-specific definitions required for the SLICOSS
+ * driver, which should allow for greater portability to other OSes.
+ */
+#ifndef _SLIC_OS_SPECIFIC_H_
+#define _SLIC_OS_SPECIFIC_H_
+
+#define FALSE (0)
+#define TRUE (1)
+
+#define SLIC_SECS_TO_JIFFS(x) ((x) * HZ)
+#define SLIC_MS_TO_JIFFIES(x) (SLIC_SECS_TO_JIFFS((x)) / 1000)
+
+#ifdef DEBUG_REGISTER_TRACE
+#define WRITE_REG(reg, value, flush) \
+ { \
+ adapter->card->reg_type[adapter->card->debug_ix] = 0; \
+ adapter->card->reg_offset[adapter->card->debug_ix] = \
+ ((unsigned char *)(&reg)) - \
+ ((unsigned char *)adapter->slic_regs); \
+ adapter->card->reg_value[adapter->card->debug_ix++] = value; \
+ if (adapter->card->debug_ix == 32) \
+ adapter->card->debug_ix = 0; \
+ slic_reg32_write((&reg), (value), (flush)); \
+ }
+#define WRITE_REG64(a, reg, value, regh, valh, flush) \
+ { \
+ adapter->card->reg_type[adapter->card->debug_ix] = 1; \
+ adapter->card->reg_offset[adapter->card->debug_ix] = \
+ ((unsigned char *)(&reg)) - \
+ ((unsigned char *)adapter->slic_regs); \
+ adapter->card->reg_value[adapter->card->debug_ix] = value; \
+ adapter->card->reg_valueh[adapter->card->debug_ix++] = valh; \
+ if (adapter->card->debug_ix == 32) \
+ adapter->card->debug_ix = 0; \
+ slic_reg64_write((a), (&reg), (value), (&regh), (valh), \
+ (flush));\
+ }
+#else
+#define WRITE_REG(reg, value, flush) \
+ slic_reg32_write((&reg), (value), (flush))
+#define WRITE_REG64(a, reg, value, regh, valh, flush) \
+ slic_reg64_write((a), (&reg), (value), (&regh), (valh), (flush))
+#endif
+
+#endif /* _SLIC_OS_SPECIFIC_H_ */
+
diff --git a/drivers/staging/slicoss/slicbuild.h b/drivers/staging/slicoss/slicbuild.h
new file mode 100644
index 00000000000..ae05e043d07
--- /dev/null
+++ b/drivers/staging/slicoss/slicbuild.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slicbuild.h
+ *
+ * The following contains the compiler directive switches used for
+ * different SLIC build options. They can all be set in the Makefile
+ * but the defaults are defined here.
+ */
+#ifndef _SLIC_BUILD_H_
+#define _SLIC_BUILD_H_
+
+#ifndef SLIC_PRODUCTION_BUILD
+#define SLIC_PRODUCTION_BUILD 1
+#endif
+#ifndef SLIC_FAILURE_RESET
+#define SLIC_FAILURE_RESET 1
+#endif
+#define DBG 1
+#ifndef SLIC_ASSERT_ENABLED
+#define SLIC_ASSERT_ENABLED 1
+#endif
+#ifndef SLIC_MCAST_ENABLED
+#define SLIC_MCAST_ENABLED 1
+#endif
+#ifndef SLIC_GET_STATS_ENABLED
+#define SLIC_GET_STATS_ENABLED 1
+#endif
+#ifndef SLIC_GET_STATS_TIMER_ENABLED
+#define SLIC_GET_STATS_TIMER_ENABLED 0
+#endif
+#ifndef SLIC_PING_TIMER_ENABLED
+#define SLIC_PING_TIMER_ENABLED 1
+#endif
+#ifndef SLIC_IOCTL_SUPPORT_ENABLED
+#define SLIC_IOCTL_SUPPORT_ENABLED 1
+#endif
+#ifndef ATK_DEBUG
+#define ATK_DEBUG 1
+#endif
+#ifndef SLIC_POWER_MANAGEMENT_ENABLED
+#define SLIC_POWER_MANAGEMENT_ENABLED 0
+#endif
+#ifndef SLIC_INTERRUPT_PROCESS_LIMIT
+#define SLIC_INTERRUPT_PROCESS_LIMIT 1
+#endif
+#ifndef LINUX_FREES_ADAPTER_RESOURCES
+#define LINUX_FREES_ADAPTER_RESOURCES 1
+#endif
+#ifndef SLIC_OFFLOAD_IP_CHECKSUM
+#define SLIC_OFFLOAD_IP_CHECKSUM 1
+#endif
+#ifndef SLIC_POWER_MANAGEMENT_ENABLED
+#define SLIC_POWER_MANAGEMENT_ENABLED 0
+#endif
+#ifndef STATS_TIMER_INTERVAL
+#define STATS_TIMER_INTERVAL 2
+#endif
+#ifndef PING_TIMER_INTERVAL
+#define PING_TIMER_INTERVAL 1
+#endif
+
+#endif /* _SLIC_BUILD_H_ */
diff --git a/drivers/staging/slicoss/slicdbg.h b/drivers/staging/slicoss/slicdbg.h
new file mode 100644
index 00000000000..c54e44fb1f6
--- /dev/null
+++ b/drivers/staging/slicoss/slicdbg.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slicdbg.h
+ *
+ * All debug and assertion-based definitions and macros are included
+ * in this file for the SLICOSS driver.
+ */
+#ifndef _SLIC_DEBUG_H_
+#define _SLIC_DEBUG_H_
+
+#ifdef SLIC_DEFAULT_LOG_LEVEL
+#else
+#define SLICLEVEL KERN_DEBUG
+#endif
+#define SLIC_DISPLAY printk
+#define DBG_ERROR(n, args...) SLIC_DISPLAY(KERN_EMERG n, ##args)
+
+#define SLIC_DEBUG_MESSAGE 1
+#if SLIC_DEBUG_MESSAGE
+/*#define DBG_MSG(n, args...) SLIC_DISPLAY(SLICLEVEL n, ##args)*/
+#define DBG_MSG(n, args...)
+#else
+#define DBG_MSG(n, args...)
+#endif
+
+#ifdef ASSERT
+#undef ASSERT
+#endif
+
+#if SLIC_ASSERT_ENABLED
+#ifdef CONFIG_X86_64
+#define VALID_ADDRESS(p) (1)
+#else
+#define VALID_ADDRESS(p) (((u32)(p) & 0x80000000) || ((u32)(p) == 0))
+#endif
+#ifndef ASSERT
+#define ASSERT(a) \
+ { \
+ if (!(a)) { \
+ DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n",\
+ __FILE__, __func__, __LINE__); \
+ slic_assert_fail(); \
+ } \
+ }
+#endif
+#ifndef ASSERTMSG
+#define ASSERTMSG(a,msg) \
+ { \
+ if (!(a)) { \
+ DBG_ERROR("ASSERT() Failure: file %s, function %s"\
+ "line %d: %s\n",\
+ __FILE__, __func__, __LINE__, (msg)); \
+ slic_assert_fail(); \
+ } \
+ }
+#endif
+#else
+#ifndef ASSERT
+#define ASSERT(a)
+#endif
+#ifndef ASSERTMSG
+#define ASSERTMSG(a, msg)
+#endif
+#endif /* SLIC_ASSERT_ENABLED */
+
+#endif /* _SLIC_DEBUG_H_ */
diff --git a/drivers/staging/slicoss/slicdump.h b/drivers/staging/slicoss/slicdump.h
new file mode 100644
index 00000000000..92a9b44bcad
--- /dev/null
+++ b/drivers/staging/slicoss/slicdump.h
@@ -0,0 +1,278 @@
+/*
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * NO LICENSE TO ANY ALACRITECH PATENT CLAIM IS GRANTED BY ANY COPYRIGHT
+ * LICENSE TO THIS OR OTHER SOFTWARE. THIS SOFTWARE MAY BE COVERED BY
+ * ALACRITECH PATENTS INCLUDING BUT NOT LIMITED TO U.S. PATENT NOS. 6,226,680,
+ * 6,247,060, 6,334,153, 6,389,479, 6,393,487, 6,427,171, 6,427,173
+ * and 6,434,620.
+ * THIS SOFTWARE IS NOT SUBJECT TO THE GNU GENERAL PUBLIC LICENSE (GPL).
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either
+ * expressed or implied, of Alacritech, Inc.
+ */
+#ifndef _SLIC_DUMP_H_
+#define _SLIC_DUMP_H_
+
+#define DEBUG_SUCCESS 0
+
+/***********************************************************************
+ *
+ * Utility processor register locations
+ *
+ **********************************************************************/
+#define UTILITY_RESET 0x0
+#define UTILITY_ISP_ADDR 0x4 /* Interrupt status Pointer */
+#define UTILITY_ISR_ADDR 0x8 /* Interrupt status Register */
+#define UTILITY_ICR_ADDR 0xc /* Interrupt Control Register */
+#define UTILITY_CPR_ADDR 0x10 /* Command Pointer Register */
+#define UTILITY_DPR_ADDR 0x14 /* Data Pointer Register */
+#define UTILITY_DMP_TRQ 0x18 /* Dump queue onto ALU for analyser */
+#define UTILITY_UPP_ADDR 0x1c /* Bits 63-32 of cmd/data pointer */
+
+/***********************************************************************
+ *
+ * INIC status register bits
+ *
+ ***********************************************************************/
+#define SLIC_ISR_CC 0x10000000 /* Command complete - synchronous */
+#define SLIC_ISR_ERR 0x01000000 /* Command Error - synchronous */
+#define SLIC_ISR_CMD_MASK 0x11000000 /* Command status mask */
+#define SLIC_ISR_TPH 0x00080000 /* Transmit processor halted - async */
+#define SLIC_ISR_RPH 0x00040000 /* Receive processor halted - async */
+
+/***********************************************************************
+ *
+ * INIC Control register values
+ *
+ ***********************************************************************/
+#define SLIC_ICR_OFF 0 /* Interrupts disabled */
+#define SLIC_ICR_ON 1 /* Interrupts enabled */
+#define SLIC_ICR_MASK 2 /* Interrupts masked */
+
+#define WRITE_DREG(reg, value, flush) \
+{ \
+ writel((value), (reg)); \
+ if ((flush)) { \
+ mb(); \
+ } \
+}
+
+/************************************************************************
+ *
+ * Command Format
+ *
+ * Each command contains a command byte which is defined as follows:
+ *
+ * bits: 7-3 2 1-0
+ * ----------------------------------------------
+ * command Alt. Proc Processor
+ *
+ ************************************************************************/
+
+/*
+ * Macro to create the command byte given the command, Alt. Proc, and
+ * Processor values. Note that the macro assumes that the values are
+ * preshifted. That is, the values for alt. proc are 0 for transmit and
+ * 4 for receive.
+ */
+#define COMMAND_BYTE(command, alt_proc, proc) ((command) | (alt_proc) | (proc))
+
+/*
+ * Command values
+ */
+#define CMD_HALT 0x0 /* Send a halt to the INIC */
+#define CMD_RUN 0x8 /* Start the halted INIC */
+#define CMD_STEP 0x10 /* Single step the inic */
+#define CMD_BREAK 0x18 /* Set a breakpoint - 8 byte command */
+#define CMD_RESET_BREAK 0x20 /* Reset a breakpoint - 8 byte cmd */
+#define CMD_DUMP 0x28 /* Dump INIC memory - 8 byte command */
+#define CMD_LOAD 0x30 /* Load INIC memory - 8 byte command */
+#define CMD_MAP 0x38 /* Map out a ROM instruction - 8 BC */
+#define CMD_CAM_OPS 0x38 /* perform ops on specific CAM */
+#define CMD_XMT 0x40 /* Transmit frame */
+#define CMD_RCV 0x48 /* Receive frame */
+
+/*
+ * Alt. Proc values
+ *
+ * When the proc value is set to the utility processor, the Alt. Proc
+ * specifies which processor handles the debugging.
+ */
+#define ALT_PROC_TRANSMIT 0x0
+#define ALT_PROC_RECEIVE 0x4
+
+/*
+ * Proc values
+ */
+#define PROC_INVALID 0x0
+#define PROC_NONE 0x0 /* Gigabit use */
+#define PROC_TRANSMIT 0x1
+#define PROC_RECEIVE 0x2
+#define PROC_UTILITY 0x3
+
+/******************************************************************
+ *
+ * 8 byte command structure definitions
+ *
+ ******************************************************************/
+
+/*
+ * Break and Reset Break command structure
+ */
+struct BREAK {
+ unsigned char command; /* Command word defined above */
+ unsigned char resvd;
+ ushort count; /* Number of executions before break */
+ u32 addr; /* Address of break point */
+};
+
+/*
+ * Dump and Load command structure
+ */
+struct dump_cmd {
+ unsigned char cmd; /* Command word defined above */
+ unsigned char desc; /* Descriptor values - defined below */
+ ushort count; /* number of 4 byte words to be transferred */
+ u32 addr; /* start address of dump or load */
+};
+
+/*
+ * Receive or Transmit a frame.
+ */
+struct RCV_OR_XMT_FRAME {
+ unsigned char command; /* Command word defined above */
+ unsigned char MacId; /* Mac ID of interface - transmit only */
+ ushort count; /* Length of frame in bytes */
+ u32 pad; /* not used */
+};
+
+/*
+ * Values of desc field in DUMP_OR_LOAD structure
+ */
+#define DESC_RFILE 0x0 /* Register file */
+#define DESC_SRAM 0x1 /* SRAM */
+#define DESC_DRAM 0x2 /* DRAM */
+#define DESC_QUEUE 0x3 /* queues */
+#define DESC_REG 0x4 /* General registers (pc, status, etc) */
+#define DESC_SENSE 0x5 /* Sense register */
+
+/* Descriptor field definitions for CMD_DUMP_CAM */
+#define DUMP_CAM_A 0
+#define DUMP_CAM_B 1 /* unused at present */
+#define DUMP_CAM_C 2
+#define DUMP_CAM_D 3
+#define SEARCH_CAM_A 4
+#define SEARCH_CAM_C 5
+
+/*
+ * Map command to replace a command in ROM with a command in WCS
+ */
+struct MAP {
+ unsigned char command; /* Command word defined above */
+ unsigned char not_used[3];
+ ushort map_to; /* Instruction address in WCS */
+ ushort map_out; /* Instruction address in ROM */
+};
+
+/*
+ * Misc definitions
+ */
+#define SLIC_MAX_QUEUE 32 /* Total # of queues on the INIC (0-31)*/
+#define SLIC_4MAX_REG 512 /* Total # of 4-port file-registers */
+#define SLIC_1MAX_REG 384 /* Total # of file-registers */
+#define SLIC_GBMAX_REG 1024 /* Total # of Gbit file-registers */
+#define SLIC_NUM_REG 32 /* non-file-registers = NUM_REG in tm-simba.h */
+#define SLIC_GB_CAMA_SZE 32
+#define SLIC_GB_CAMB_SZE 16
+#define SLIC_GB_CAMAB_SZE 32
+#define SLIC_GB_CAMC_SZE 16
+#define SLIC_GB_CAMD_SZE 16
+#define SLIC_GB_CAMCD_SZE 32
+
+/*
+ * Coredump header structure
+ */
+struct CORE_Q {
+ u32 queueOff; /* Offset of queue */
+ u32 queuesize; /* size of queue */
+};
+
+#define DRIVER_NAME_SIZE 32
+
+struct sliccore_hdr {
+ unsigned char driver_version[DRIVER_NAME_SIZE]; /* Driver version string */
+ u32 RcvRegOff; /* Offset of receive registers */
+ u32 RcvRegsize; /* size of receive registers */
+ u32 XmtRegOff; /* Offset of transmit registers */
+ u32 XmtRegsize; /* size of transmit registers */
+ u32 FileRegOff; /* Offset of register file */
+ u32 FileRegsize; /* size of register file */
+ u32 SramOff; /* Offset of Sram */
+ u32 Sramsize; /* size of Sram */
+ u32 DramOff; /* Offset of Dram */
+ u32 Dramsize; /* size of Dram */
+ CORE_Q queues[SLIC_MAX_QUEUE]; /* size and offsets of queues */
+ u32 CamAMOff; /* Offset of CAM A contents */
+ u32 CamASize; /* Size of Cam A */
+ u32 CamBMOff; /* Offset of CAM B contents */
+ u32 CamBSize; /* Size of Cam B */
+ u32 CamCMOff; /* Offset of CAM C contents */
+ u32 CamCSize; /* Size of Cam C */
+ u32 CamDMOff; /* Offset of CAM D contents */
+ u32 CamDSize; /* Size of Cam D */
+};
+
+/*
+ * definitions needed for our kernel-mode gdb stub.
+ */
+/***********************************************************************
+ *
+ * Definitions & Typedefs
+ *
+ **********************************************************************/
+#define BUFMAX 0x20000 /* 128k - size of input/output buffer */
+#define BUFMAXP2 5 /* 2**5 (32) 4K pages */
+
+#define IOCTL_SIMBA_BREAK _IOW('s', 0, unsigned long)
+/* #define IOCTL_SIMBA_INIT _IOW('s', 1, unsigned long) */
+#define IOCTL_SIMBA_KILL_TGT_PROC _IOW('s', 2, unsigned long)
+
+/***********************************************************************
+ *
+ * Global variables
+ *
+ ***********************************************************************/
+
+#define THREADRECEIVE 1 /* bit 0 of StoppedThreads */
+#define THREADTRANSMIT 2 /* bit 1 of StoppedThreads */
+#define THREADBOTH 3 /* bit 0 and 1.. */
+
+#endif /* _SLIC_DUMP_H */
diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h
new file mode 100644
index 00000000000..d03e90b0675
--- /dev/null
+++ b/drivers/staging/slicoss/slichw.h
@@ -0,0 +1,845 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slichw.h
+ *
+ * This header file contains definitions that are common to our hardware.
+ */
+#ifndef __SLICHW_H__
+#define __SLICHW_H__
+
+#define PCI_VENDOR_ID_ALACRITECH 0x139A
+#define SLIC_1GB_DEVICE_ID 0x0005
+#define SLIC_2GB_DEVICE_ID 0x0007 /*Oasis Device ID */
+
+#define SLIC_1GB_CICADA_SUBSYS_ID 0x0008
+
+#define SLIC_NBR_MACS 4
+
+#define SLIC_RCVBUF_SIZE 2048
+#define SLIC_RCVBUF_HEADSIZE 34
+#define SLIC_RCVBUF_TAILSIZE 0
+#define SLIC_RCVBUF_DATASIZE (SLIC_RCVBUF_SIZE - (SLIC_RCVBUF_HEADSIZE +\
+ SLIC_RCVBUF_TAILSIZE))
+
+#define VGBSTAT_XPERR 0x40000000
+#define VGBSTAT_XERRSHFT 25
+#define VGBSTAT_XCSERR 0x23
+#define VGBSTAT_XUFLOW 0x22
+#define VGBSTAT_XHLEN 0x20
+#define VGBSTAT_NETERR 0x01000000
+#define VGBSTAT_NERRSHFT 16
+#define VGBSTAT_NERRMSK 0x1ff
+#define VGBSTAT_NCSERR 0x103
+#define VGBSTAT_NUFLOW 0x102
+#define VGBSTAT_NHLEN 0x100
+#define VGBSTAT_LNKERR 0x00000080
+#define VGBSTAT_LERRMSK 0xff
+#define VGBSTAT_LDEARLY 0x86
+#define VGBSTAT_LBOFLO 0x85
+#define VGBSTAT_LCODERR 0x84
+#define VGBSTAT_LDBLNBL 0x83
+#define VGBSTAT_LCRCERR 0x82
+#define VGBSTAT_LOFLO 0x81
+#define VGBSTAT_LUFLO 0x80
+#define IRHDDR_FLEN_MSK 0x0000ffff
+#define IRHDDR_SVALID 0x80000000
+#define IRHDDR_ERR 0x10000000
+#define VRHSTAT_802OE 0x80000000
+#define VRHSTAT_TPOFLO 0x10000000
+#define VRHSTATB_802UE 0x80000000
+#define VRHSTATB_RCVE 0x40000000
+#define VRHSTATB_BUFF 0x20000000
+#define VRHSTATB_CARRE 0x08000000
+#define VRHSTATB_LONGE 0x02000000
+#define VRHSTATB_PREA 0x01000000
+#define VRHSTATB_CRC 0x00800000
+#define VRHSTATB_DRBL 0x00400000
+#define VRHSTATB_CODE 0x00200000
+#define VRHSTATB_TPCSUM 0x00100000
+#define VRHSTATB_TPHLEN 0x00080000
+#define VRHSTATB_IPCSUM 0x00040000
+#define VRHSTATB_IPLERR 0x00020000
+#define VRHSTATB_IPHERR 0x00010000
+#define SLIC_MAX64_BCNT 23
+#define SLIC_MAX32_BCNT 26
+#define IHCMD_XMT_REQ 0x01
+#define IHFLG_IFSHFT 2
+#define SLIC_RSPBUF_SIZE 32
+
+#define SLIC_RESET_MAGIC 0xDEAD
+#define ICR_INT_OFF 0
+#define ICR_INT_ON 1
+#define ICR_INT_MASK 2
+
+#define ISR_ERR 0x80000000
+#define ISR_RCV 0x40000000
+#define ISR_CMD 0x20000000
+#define ISR_IO 0x60000000
+#define ISR_UPC 0x10000000
+#define ISR_LEVENT 0x08000000
+#define ISR_RMISS 0x02000000
+#define ISR_UPCERR 0x01000000
+#define ISR_XDROP 0x00800000
+#define ISR_UPCBSY 0x00020000
+#define ISR_EVMSK 0xffff0000
+#define ISR_PINGMASK 0x00700000
+#define ISR_PINGDSMASK 0x00710000
+#define ISR_UPCMASK 0x11000000
+#define SLIC_WCS_START 0x80000000
+#define SLIC_WCS_COMPARE 0x40000000
+#define SLIC_RCVWCS_BEGIN 0x40000000
+#define SLIC_RCVWCS_FINISH 0x80000000
+#define SLIC_PM_MAXPATTERNS 6
+#define SLIC_PM_PATTERNSIZE 128
+#define SLIC_PMCAPS_WAKEONLAN 0x00000001
+#define MIICR_REG_PCR 0x00000000
+#define MIICR_REG_4 0x00040000
+#define MIICR_REG_9 0x00090000
+#define MIICR_REG_16 0x00100000
+#define PCR_RESET 0x8000
+#define PCR_POWERDOWN 0x0800
+#define PCR_SPEED_100 0x2000
+#define PCR_SPEED_1000 0x0040
+#define PCR_AUTONEG 0x1000
+#define PCR_AUTONEG_RST 0x0200
+#define PCR_DUPLEX_FULL 0x0100
+#define PSR_LINKUP 0x0004
+
+#define PAR_ADV100FD 0x0100
+#define PAR_ADV100HD 0x0080
+#define PAR_ADV10FD 0x0040
+#define PAR_ADV10HD 0x0020
+#define PAR_ASYMPAUSE 0x0C00
+#define PAR_802_3 0x0001
+
+#define PAR_ADV1000XFD 0x0020
+#define PAR_ADV1000XHD 0x0040
+#define PAR_ASYMPAUSE_FIBER 0x0180
+
+#define PGC_ADV1000FD 0x0200
+#define PGC_ADV1000HD 0x0100
+#define SEEQ_LINKFAIL 0x4000
+#define SEEQ_SPEED 0x0080
+#define SEEQ_DUPLEX 0x0040
+#define TDK_DUPLEX 0x0800
+#define TDK_SPEED 0x0400
+#define MRV_REG16_XOVERON 0x0068
+#define MRV_REG16_XOVEROFF 0x0008
+#define MRV_SPEED_1000 0x8000
+#define MRV_SPEED_100 0x4000
+#define MRV_SPEED_10 0x0000
+#define MRV_FULLDUPLEX 0x2000
+#define MRV_LINKUP 0x0400
+
+#define GIG_LINKUP 0x0001
+#define GIG_FULLDUPLEX 0x0002
+#define GIG_SPEED_MASK 0x000C
+#define GIG_SPEED_1000 0x0008
+#define GIG_SPEED_100 0x0004
+#define GIG_SPEED_10 0x0000
+
+#define MCR_RESET 0x80000000
+#define MCR_CRCEN 0x40000000
+#define MCR_FULLD 0x10000000
+#define MCR_PAD 0x02000000
+#define MCR_RETRYLATE 0x01000000
+#define MCR_BOL_SHIFT 21
+#define MCR_IPG1_SHIFT 14
+#define MCR_IPG2_SHIFT 7
+#define MCR_IPG3_SHIFT 0
+#define GMCR_RESET 0x80000000
+#define GMCR_GBIT 0x20000000
+#define GMCR_FULLD 0x10000000
+#define GMCR_GAPBB_SHIFT 14
+#define GMCR_GAPR1_SHIFT 7
+#define GMCR_GAPR2_SHIFT 0
+#define GMCR_GAPBB_1000 0x60
+#define GMCR_GAPR1_1000 0x2C
+#define GMCR_GAPR2_1000 0x40
+#define GMCR_GAPBB_100 0x70
+#define GMCR_GAPR1_100 0x2C
+#define GMCR_GAPR2_100 0x40
+#define XCR_RESET 0x80000000
+#define XCR_XMTEN 0x40000000
+#define XCR_PAUSEEN 0x20000000
+#define XCR_LOADRNG 0x10000000
+#define RCR_RESET 0x80000000
+#define RCR_RCVEN 0x40000000
+#define RCR_RCVALL 0x20000000
+#define RCR_RCVBAD 0x10000000
+#define RCR_CTLEN 0x08000000
+#define RCR_ADDRAEN 0x02000000
+#define GXCR_RESET 0x80000000
+#define GXCR_XMTEN 0x40000000
+#define GXCR_PAUSEEN 0x20000000
+#define GRCR_RESET 0x80000000
+#define GRCR_RCVEN 0x40000000
+#define GRCR_RCVALL 0x20000000
+#define GRCR_RCVBAD 0x10000000
+#define GRCR_CTLEN 0x08000000
+#define GRCR_ADDRAEN 0x02000000
+#define GRCR_HASHSIZE_SHIFT 17
+#define GRCR_HASHSIZE 14
+
+#define SLIC_EEPROM_ID 0xA5A5
+#define SLIC_SRAM_SIZE2GB (64 * 1024)
+#define SLIC_SRAM_SIZE1GB (32 * 1024)
+#define SLIC_HOSTID_DEFAULT 0xFFFF /* uninitialized hostid */
+#define SLIC_NBR_MACS 4
+
+#ifndef FALSE
+#define FALSE 0
+#else
+#undef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#else
+#undef TRUE
+#define TRUE 1
+#endif
+
+struct slic_rcvbuf {
+ unsigned char pad1[6];
+ ushort pad2;
+ u32 pad3;
+ u32 pad4;
+ u32 buffer;
+ u32 length;
+ u32 status;
+ u32 pad5;
+ ushort pad6;
+ unsigned char data[SLIC_RCVBUF_DATASIZE];
+};
+
+ struct slic_hddr_wds {
+ union {
+ struct {
+ u32 frame_status;
+ u32 frame_status_b;
+ u32 time_stamp;
+ u32 checksum;
+ } hdrs_14port;
+ struct {
+ u32 frame_status;
+ ushort ByteCnt;
+ ushort TpChksum;
+ ushort CtxHash;
+ ushort MacHash;
+ u32 BufLnk;
+ } hdrs_gbit;
+ } u0;
+};
+
+#define frame_status14 u0.hdrs_14port.frame_status
+#define frame_status_b14 u0.hdrs_14port.frame_status_b
+#define frame_statusGB u0.hdrs_gbit.frame_status
+
+struct slic_host64sg {
+ u32 paddrl;
+ u32 paddrh;
+ u32 length;
+};
+
+struct slic_host64_cmd {
+ u32 hosthandle;
+ u32 RSVD;
+ unsigned char command;
+ unsigned char flags;
+ union {
+ ushort rsv1;
+ ushort rsv2;
+ } u0;
+ union {
+ struct {
+ u32 totlen;
+ struct slic_host64sg bufs[SLIC_MAX64_BCNT];
+ } slic_buffers;
+ } u;
+};
+
+struct slic_rspbuf {
+ u32 hosthandle;
+ u32 pad0;
+ u32 pad1;
+ u32 status;
+ u32 pad2[4];
+
+};
+
+struct slic_regs {
+ u32 slic_reset; /* Reset Register */
+ u32 pad0;
+
+ u32 slic_icr; /* Interrupt Control Register */
+ u32 pad2;
+#define SLIC_ICR 0x0008
+
+ u32 slic_isp; /* Interrupt status pointer */
+ u32 pad1;
+#define SLIC_ISP 0x0010
+
+ u32 slic_isr; /* Interrupt status */
+ u32 pad3;
+#define SLIC_ISR 0x0018
+
+ u32 slic_hbar; /* Header buffer address reg */
+ u32 pad4;
+ /* 31-8 - phy addr of set of contiguous hdr buffers
+ 7-0 - number of buffers passed
+ Buffers are 256 bytes long on 256-byte boundaries. */
+#define SLIC_HBAR 0x0020
+#define SLIC_HBAR_CNT_MSK 0x000000FF
+
+ u32 slic_dbar; /* Data buffer handle & address reg */
+ u32 pad5;
+
+ /* 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. */
+#define SLIC_DBAR 0x0028
+#define SLIC_DBAR_SIZE 2048
+
+ u32 slic_cbar; /* Xmt Cmd buf addr regs.*/
+ /* 1 per XMT interface
+ 31-5 - phy addr of host command buffer
+ 4-0 - length of cmd in multiples of 32 bytes
+ Buffers are 32 bytes up to 512 bytes long */
+#define SLIC_CBAR 0x0030
+#define SLIC_CBAR_LEN_MSK 0x0000001F
+#define SLIC_CBAR_ALIGN 0x00000020
+
+ u32 slic_wcs; /* write control store*/
+#define SLIC_WCS 0x0034
+#define SLIC_WCS_START 0x80000000 /*Start the SLIC (Jump to WCS)*/
+#define SLIC_WCS_COMPARE 0x40000000 /* Compare with value in WCS*/
+
+ u32 slic_rbar; /* Response buffer address reg.*/
+ u32 pad7;
+ /*31-8 - phy addr of set of contiguous response buffers
+ 7-0 - number of buffers passed
+ Buffers are 32 bytes long on 32-byte boundaries.*/
+#define SLIC_RBAR 0x0038
+#define SLIC_RBAR_CNT_MSK 0x000000FF
+#define SLIC_RBAR_SIZE 32
+
+ u32 slic_stats; /* read statistics (UPR) */
+ u32 pad8;
+#define SLIC_RSTAT 0x0040
+
+ u32 slic_rlsr; /* read link status */
+ u32 pad9;
+#define SLIC_LSTAT 0x0048
+
+ u32 slic_wmcfg; /* Write Mac Config */
+ u32 pad10;
+#define SLIC_WMCFG 0x0050
+
+ u32 slic_wphy; /* Write phy register */
+ u32 pad11;
+#define SLIC_WPHY 0x0058
+
+ u32 slic_rcbar; /*Rcv Cmd buf addr reg*/
+ u32 pad12;
+#define SLIC_RCBAR 0x0060
+
+ u32 slic_rconfig; /* Read SLIC Config*/
+ u32 pad13;
+#define SLIC_RCONFIG 0x0068
+
+ u32 slic_intagg; /* Interrupt aggregation time*/
+ u32 pad14;
+#define SLIC_INTAGG 0x0070
+
+ u32 slic_wxcfg; /* Write XMIT config reg*/
+ u32 pad16;
+#define SLIC_WXCFG 0x0078
+
+ u32 slic_wrcfg; /* Write RCV config reg*/
+ u32 pad17;
+#define SLIC_WRCFG 0x0080
+
+ u32 slic_wraddral; /* Write rcv addr a low*/
+ u32 pad18;
+#define SLIC_WRADDRAL 0x0088
+
+ u32 slic_wraddrah; /* Write rcv addr a high*/
+ u32 pad19;
+#define SLIC_WRADDRAH 0x0090
+
+ u32 slic_wraddrbl; /* Write rcv addr b low*/
+ u32 pad20;
+#define SLIC_WRADDRBL 0x0098
+
+ u32 slic_wraddrbh; /* Write rcv addr b high*/
+ u32 pad21;
+#define SLIC_WRADDRBH 0x00a0
+
+ u32 slic_mcastlow; /* Low bits of mcast mask*/
+ u32 pad22;
+#define SLIC_MCASTLOW 0x00a8
+
+ u32 slic_mcasthigh; /* High bits of mcast mask*/
+ u32 pad23;
+#define SLIC_MCASTHIGH 0x00b0
+
+ u32 slic_ping; /* Ping the card*/
+ u32 pad24;
+#define SLIC_PING 0x00b8
+
+ u32 slic_dump_cmd; /* Dump command */
+ u32 pad25;
+#define SLIC_DUMP_CMD 0x00c0
+
+ u32 slic_dump_data; /* Dump data pointer */
+ u32 pad26;
+#define SLIC_DUMP_DATA 0x00c8
+
+ u32 slic_pcistatus; /* Read card's pci_status register */
+ u32 pad27;
+#define SLIC_PCISTATUS 0x00d0
+
+ u32 slic_wrhostid; /* Write hostid field */
+ u32 pad28;
+#define SLIC_WRHOSTID 0x00d8
+#define SLIC_RDHOSTID_1GB 0x1554
+#define SLIC_RDHOSTID_2GB 0x1554
+
+ u32 slic_low_power; /* Put card in a low power state */
+ u32 pad29;
+#define SLIC_LOW_POWER 0x00e0
+
+ u32 slic_quiesce; /* force slic into quiescent state
+ before soft reset */
+ u32 pad30;
+#define SLIC_QUIESCE 0x00e8
+
+ u32 slic_reset_iface; /* reset interface queues */
+ u32 pad31;
+#define SLIC_RESET_IFACE 0x00f0
+
+ u32 slic_addr_upper; /* Bits 63-32 for host i/f addrs */
+ u32 pad32;
+#define SLIC_ADDR_UPPER 0x00f8 /*Register is only written when it has changed*/
+
+ u32 slic_hbar64; /* 64 bit Header buffer address reg */
+ u32 pad33;
+#define SLIC_HBAR64 0x0100
+
+ u32 slic_dbar64; /* 64 bit Data buffer handle & address reg */
+ u32 pad34;
+#define SLIC_DBAR64 0x0108
+
+ u32 slic_cbar64; /* 64 bit Xmt Cmd buf addr regs. */
+ u32 pad35;
+#define SLIC_CBAR64 0x0110
+
+ u32 slic_rbar64; /* 64 bit Response buffer address reg.*/
+ u32 pad36;
+#define SLIC_RBAR64 0x0118
+
+ u32 slic_rcbar64; /* 64 bit Rcv Cmd buf addr reg*/
+ u32 pad37;
+#define SLIC_RCBAR64 0x0120
+
+ u32 slic_stats64; /*read statistics (64 bit UPR)*/
+ u32 pad38;
+#define SLIC_RSTAT64 0x0128
+
+ u32 slic_rcv_wcs; /*Download Gigabit RCV sequencer ucode*/
+ u32 pad39;
+#define SLIC_RCV_WCS 0x0130
+#define SLIC_RCVWCS_BEGIN 0x40000000
+#define SLIC_RCVWCS_FINISH 0x80000000
+
+ u32 slic_wrvlanid; /* Write VlanId field */
+ u32 pad40;
+#define SLIC_WRVLANID 0x0138
+
+ u32 slic_read_xf_info; /* Read Transformer info */
+ u32 pad41;
+#define SLIC_READ_XF_INFO 0x0140
+
+ u32 slic_write_xf_info; /* Write Transformer info */
+ u32 pad42;
+#define SLIC_WRITE_XF_INFO 0x0148
+
+ u32 RSVD1; /* TOE Only */
+ u32 pad43;
+
+ u32 RSVD2; /* TOE Only */
+ u32 pad44;
+
+ u32 RSVD3; /* TOE Only */
+ u32 pad45;
+
+ u32 RSVD4; /* TOE Only */
+ u32 pad46;
+
+ u32 slic_ticks_per_sec; /* Write card ticks per second */
+ u32 pad47;
+#define SLIC_TICKS_PER_SEC 0x0170
+
+};
+
+enum UPR_REQUEST {
+ SLIC_UPR_STATS,
+ SLIC_UPR_RLSR,
+ SLIC_UPR_WCFG,
+ SLIC_UPR_RCONFIG,
+ SLIC_UPR_RPHY,
+ SLIC_UPR_ENLB,
+ SLIC_UPR_ENCT,
+ SLIC_UPR_PDWN,
+ SLIC_UPR_PING,
+ SLIC_UPR_DUMP,
+};
+
+struct inicpm_wakepattern {
+ u32 patternlength;
+ unsigned char pattern[SLIC_PM_PATTERNSIZE];
+ unsigned char mask[SLIC_PM_PATTERNSIZE];
+};
+
+struct inicpm_state {
+ u32 powercaps;
+ u32 powerstate;
+ u32 wake_linkstatus;
+ u32 wake_magicpacket;
+ u32 wake_framepattern;
+ struct inicpm_wakepattern wakepattern[SLIC_PM_MAXPATTERNS];
+};
+
+struct slicpm_packet_pattern {
+ u32 priority;
+ u32 reserved;
+ u32 masksize;
+ u32 patternoffset;
+ u32 patternsize;
+ u32 patternflags;
+};
+
+enum slicpm_power_state {
+ slicpm_state_unspecified = 0,
+ slicpm_state_d0,
+ slicpm_state_d1,
+ slicpm_state_d2,
+ slicpm_state_d3,
+ slicpm_state_maximum
+};
+
+struct slicpm_wakeup_capabilities {
+ enum slicpm_power_state min_magic_packet_wakeup;
+ enum slicpm_power_state min_pattern_wakeup;
+ enum slicpm_power_state min_link_change_wakeup;
+};
+
+struct slic_pnp_capabilities {
+ u32 flags;
+ struct slicpm_wakeup_capabilities wakeup_capabilities;
+};
+
+struct xmt_stats {
+ u32 xmit_tcp_bytes;
+ u32 xmit_tcp_segs;
+ u32 xmit_bytes;
+ u32 xmit_collisions;
+ u32 xmit_unicasts;
+ u32 xmit_other_error;
+ u32 xmit_excess_collisions;
+};
+
+struct rcv_stats {
+ u32 rcv_tcp_bytes;
+ u32 rcv_tcp_segs;
+ u32 rcv_bytes;
+ u32 rcv_unicasts;
+ u32 rcv_other_error;
+ u32 rcv_drops;
+};
+
+struct xmt_statsgb {
+ u64 xmit_tcp_bytes;
+ u64 xmit_tcp_segs;
+ u64 xmit_bytes;
+ u64 xmit_collisions;
+ u64 xmit_unicasts;
+ u64 xmit_other_error;
+ u64 xmit_excess_collisions;
+};
+
+struct rcv_statsgb {
+ u64 rcv_tcp_bytes;
+ u64 rcv_tcp_segs;
+ u64 rcv_bytes;
+ u64 rcv_unicasts;
+ u64 rcv_other_error;
+ u64 rcv_drops;
+};
+
+struct slic_stats {
+ union {
+ struct {
+ struct xmt_stats xmt100;
+ struct rcv_stats rcv100;
+ } stats_100;
+ struct {
+ struct xmt_statsgb xmtGB;
+ struct rcv_statsgb rcvGB;
+ } stats_GB;
+ } u;
+};
+
+#define xmit_tcp_segs100 u.stats_100.xmt100.xmit_tcp_segs
+#define xmit_tcp_bytes100 u.stats_100.xmt100.xmit_tcp_bytes
+#define xmit_bytes100 u.stats_100.xmt100.xmit_bytes
+#define xmit_collisions100 u.stats_100.xmt100.xmit_collisions
+#define xmit_unicasts100 u.stats_100.xmt100.xmit_unicasts
+#define xmit_other_error100 u.stats_100.xmt100.xmit_other_error
+#define xmit_excess_collisions100 u.stats_100.xmt100.xmit_excess_collisions
+#define rcv_tcp_segs100 u.stats_100.rcv100.rcv_tcp_segs
+#define rcv_tcp_bytes100 u.stats_100.rcv100.rcv_tcp_bytes
+#define rcv_bytes100 u.stats_100.rcv100.rcv_bytes
+#define rcv_unicasts100 u.stats_100.rcv100.rcv_unicasts
+#define rcv_other_error100 u.stats_100.rcv100.rcv_other_error
+#define rcv_drops100 u.stats_100.rcv100.rcv_drops
+#define xmit_tcp_segs_gb u.stats_GB.xmtGB.xmit_tcp_segs
+#define xmit_tcp_bytes_gb u.stats_GB.xmtGB.xmit_tcp_bytes
+#define xmit_bytes_gb u.stats_GB.xmtGB.xmit_bytes
+#define xmit_collisions_gb u.stats_GB.xmtGB.xmit_collisions
+#define xmit_unicasts_gb u.stats_GB.xmtGB.xmit_unicasts
+#define xmit_other_error_gb u.stats_GB.xmtGB.xmit_other_error
+#define xmit_excess_collisions_gb u.stats_GB.xmtGB.xmit_excess_collisions
+
+#define rcv_tcp_segs_gb u.stats_GB.rcvGB.rcv_tcp_segs
+#define rcv_tcp_bytes_gb u.stats_GB.rcvGB.rcv_tcp_bytes
+#define rcv_bytes_gb u.stats_GB.rcvGB.rcv_bytes
+#define rcv_unicasts_gb u.stats_GB.rcvGB.rcv_unicasts
+#define rcv_other_error_gb u.stats_GB.rcvGB.rcv_other_error
+#define rcv_drops_gb u.stats_GB.rcvGB.rcv_drops
+
+struct slic_config_mac {
+ unsigned char macaddrA[6];
+};
+
+#define ATK_FRU_FORMAT 0x00
+#define VENDOR1_FRU_FORMAT 0x01
+#define VENDOR2_FRU_FORMAT 0x02
+#define VENDOR3_FRU_FORMAT 0x03
+#define VENDOR4_FRU_FORMAT 0x04
+#define NO_FRU_FORMAT 0xFF
+
+struct atk_fru {
+ unsigned char assembly[6];
+ unsigned char revision[2];
+ unsigned char serial[14];
+ unsigned char pad[3];
+};
+
+struct vendor1_fru {
+ unsigned char commodity;
+ unsigned char assembly[4];
+ unsigned char revision[2];
+ unsigned char supplier[2];
+ unsigned char date[2];
+ unsigned char sequence[3];
+ unsigned char pad[13];
+};
+
+struct vendor2_fru {
+ unsigned char part[8];
+ unsigned char supplier[5];
+ unsigned char date[3];
+ unsigned char sequence[4];
+ unsigned char pad[7];
+};
+
+struct vendor3_fru {
+ unsigned char assembly[6];
+ unsigned char revision[2];
+ unsigned char serial[14];
+ unsigned char pad[3];
+};
+
+struct vendor4_fru {
+ unsigned char number[8];
+ unsigned char part[8];
+ unsigned char version[8];
+ unsigned char pad[3];
+};
+
+union oemfru {
+ struct vendor1_fru vendor1_fru;
+ struct vendor2_fru vendor2_fru;
+ struct vendor3_fru vendor3_fru;
+ struct vendor4_fru vendor4_fru;
+};
+
+/*
+ SLIC EEPROM structure for Mojave
+*/
+struct slic_eeprom {
+ ushort Id; /* 00 EEPROM/FLASH Magic code 'A5A5'*/
+ ushort EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/
+ ushort FlashSize; /* 02 Flash size */
+ ushort EepromSize; /* 03 EEPROM Size */
+ ushort VendorId; /* 04 Vendor ID */
+ ushort DeviceId; /* 05 Device ID */
+ unsigned char RevisionId; /* 06 Revision ID */
+ unsigned char ClassCode[3]; /* 07 Class Code */
+ unsigned char DbgIntPin; /* 08 Debug Interrupt pin */
+ unsigned char NetIntPin0; /* Network Interrupt Pin */
+ unsigned char MinGrant; /* 09 Minimum grant */
+ unsigned char MaxLat; /* Maximum Latency */
+ ushort PciStatus; /* 10 PCI Status */
+ ushort SubSysVId; /* 11 Subsystem Vendor Id */
+ ushort SubSysId; /* 12 Subsystem ID */
+ ushort DbgDevId; /* 13 Debug Device Id */
+ ushort DramRomFn; /* 14 Dram/Rom function */
+ ushort DSize2Pci; /* 15 DRAM size to PCI (bytes * 64K) */
+ ushort RSize2Pci; /* 16 ROM extension size to PCI (bytes * 4k) */
+ unsigned char NetIntPin1;/* 17 Network Interface Pin 1
+ (simba/leone only) */
+ unsigned char NetIntPin2; /*Network Interface Pin 2 (simba/leone only)*/
+ union {
+ unsigned char NetIntPin3;/*18 Network Interface Pin 3
+ (simba only)*/
+ unsigned char FreeTime;/*FreeTime setting (leone/mojave only) */
+ } u1;
+ unsigned char TBIctl; /* 10-bit interface control (Mojave only) */
+ ushort DramSize; /* 19 DRAM size (bytes * 64k) */
+ union {
+ struct {
+ /* Mac Interface Specific portions */
+ struct slic_config_mac MacInfo[SLIC_NBR_MACS];
+ } mac; /* MAC access for all boards */
+ struct {
+ /* use above struct for MAC access */
+ struct slic_config_mac pad[SLIC_NBR_MACS - 1];
+ ushort DeviceId2; /* Device ID for 2nd
+ PCI function */
+ unsigned char IntPin2; /* Interrupt pin for
+ 2nd PCI function */
+ unsigned char ClassCode2[3]; /* Class Code for 2nd
+ PCI function */
+ } mojave; /* 2nd function access for gigabit board */
+ } u2;
+ ushort CfgByte6; /* Config Byte 6 */
+ ushort PMECapab; /* Power Mgment capabilities */
+ ushort NwClkCtrls; /* NetworkClockControls */
+ unsigned char FruFormat; /* Alacritech FRU format type */
+ struct atk_fru AtkFru; /* Alacritech FRU information */
+ unsigned char OemFruFormat; /* optional OEM FRU format type */
+ union oemfru OemFru; /* optional OEM FRU information */
+ unsigned char Pad[4]; /* Pad to 128 bytes - includes 2 cksum bytes
+ *(if OEM FRU info exists) and two unusable
+ * bytes at the end */
+};
+
+/* SLIC EEPROM structure for Oasis */
+struct oslic_eeprom {
+ ushort Id; /* 00 EEPROM/FLASH Magic code 'A5A5' */
+ ushort EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/
+ ushort FlashConfig0; /* 02 Flash Config for SPI device 0 */
+ ushort FlashConfig1; /* 03 Flash Config for SPI device 1 */
+ ushort VendorId; /* 04 Vendor ID */
+ ushort DeviceId; /* 05 Device ID (function 0) */
+ unsigned char RevisionId; /* 06 Revision ID */
+ unsigned char ClassCode[3]; /* 07 Class Code for PCI function 0 */
+ unsigned char IntPin1; /* 08 Interrupt pin for PCI function 1*/
+ unsigned char ClassCode2[3]; /* 09 Class Code for PCI function 1 */
+ unsigned char IntPin2; /* 10 Interrupt pin for PCI function 2*/
+ unsigned char IntPin0; /* Interrupt pin for PCI function 0*/
+ unsigned char MinGrant; /* 11 Minimum grant */
+ unsigned char MaxLat; /* Maximum Latency */
+ ushort SubSysVId; /* 12 Subsystem Vendor Id */
+ ushort SubSysId; /* 13 Subsystem ID */
+ ushort FlashSize; /* 14 Flash size (bytes / 4K) */
+ ushort DSize2Pci; /* 15 DRAM size to PCI (bytes / 64K) */
+ ushort RSize2Pci; /* 16 Flash (ROM extension) size to
+ PCI (bytes / 4K) */
+ ushort DeviceId1; /* 17 Device Id (function 1) */
+ ushort DeviceId2; /* 18 Device Id (function 2) */
+ ushort CfgByte6; /* 19 Device Status Config Bytes 6-7 */
+ ushort PMECapab; /* 20 Power Mgment capabilities */
+ unsigned char MSICapab; /* 21 MSI capabilities */
+ unsigned char ClockDivider; /* Clock divider */
+ ushort PciStatusLow; /* 22 PCI Status bits 15:0 */
+ ushort PciStatusHigh; /* 23 PCI Status bits 31:16 */
+ ushort DramConfigLow; /* 24 DRAM Configuration bits 15:0 */
+ ushort DramConfigHigh; /* 25 DRAM Configuration bits 31:16 */
+ ushort DramSize; /* 26 DRAM size (bytes / 64K) */
+ ushort GpioTbiCtl;/* 27 GPIO/TBI controls for functions 1/0 */
+ ushort EepromSize; /* 28 EEPROM Size */
+ struct slic_config_mac MacInfo[2]; /* 29 MAC addresses (2 ports) */
+ unsigned char FruFormat; /* 35 Alacritech FRU format type */
+ struct atk_fru AtkFru; /* Alacritech FRU information */
+ unsigned char OemFruFormat; /* optional OEM FRU format type */
+ union oemfru OemFru; /* optional OEM FRU information */
+ unsigned char Pad[4]; /* Pad to 128 bytes - includes 2 checksum bytes
+ * (if OEM FRU info exists) and two unusable
+ * bytes at the end
+ */
+};
+
+#define MAX_EECODE_SIZE sizeof(struct slic_eeprom)
+#define MIN_EECODE_SIZE 0x62 /* code size without optional OEM FRU stuff */
+
+/* SLIC CONFIG structure
+
+ This structure lives in the CARD structure and is valid for all
+ board types. It is filled in from the appropriate EEPROM structure
+ by SlicGetConfigData().
+*/
+struct slic_config {
+ bool EepromValid; /* Valid EEPROM flag (checksum good?) */
+ ushort DramSize; /* DRAM size (bytes / 64K) */
+ struct slic_config_mac MacInfo[SLIC_NBR_MACS]; /* MAC addresses */
+ unsigned char FruFormat; /* Alacritech FRU format type */
+ struct atk_fru AtkFru; /* Alacritech FRU information */
+ unsigned char OemFruFormat; /* optional OEM FRU format type */
+ union {
+ struct vendor1_fru vendor1_fru;
+ struct vendor2_fru vendor2_fru;
+ struct vendor3_fru vendor3_fru;
+ struct vendor4_fru vendor4_fru;
+ } OemFru;
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/staging/slicoss/slicinc.h b/drivers/staging/slicoss/slicinc.h
new file mode 100644
index 00000000000..71288c4f7be
--- /dev/null
+++ b/drivers/staging/slicoss/slicinc.h
@@ -0,0 +1,185 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved.
+ *
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slicinc.h
+ *
+ * This file contains all other include files and prototype definitions
+ * for the SLICOSS driver.
+ */
+#ifndef _SLIC_INCLUDE_H_
+#define _SLIC_INCLUDE_H_
+
+#include "slic_os.h"
+#include "slicdbg.h"
+#include "slichw.h"
+#include "slic.h"
+
+static int slic_entry_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *ent);
+static void slic_entry_remove(struct pci_dev *pcidev);
+
+static void slic_init_driver(void);
+static int slic_entry_open(struct net_device *dev);
+static int slic_entry_halt(struct net_device *dev);
+static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static void slic_xmit_fail(struct adapter *adapter,
+ struct sk_buff *skb,
+ void *cmd,
+ u32 skbtype,
+ u32 status);
+static void slic_config_pci(struct pci_dev *pcidev);
+static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter);
+
+static inline void slic_reg32_write(void __iomem *reg, u32 value, uint flush);
+static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg,
+ u32 value, void __iomem *regh, u32 paddrh, uint flush);
+
+#if SLIC_GET_STATS_ENABLED
+static struct net_device_stats *slic_get_stats(struct net_device *dev);
+#endif
+
+static int slic_mac_set_address(struct net_device *dev, void *ptr);
+static void slic_rcv_handler(struct adapter *adapter);
+static void slic_link_event_handler(struct adapter *adapter);
+static void slic_xmit_complete(struct adapter *adapter);
+static void slic_upr_request_complete(struct adapter *adapter, u32 isr);
+static int slic_rspqueue_init(struct adapter *adapter);
+static int slic_rspqueue_reset(struct adapter *adapter);
+static void slic_rspqueue_free(struct adapter *adapter);
+static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter);
+static void slic_cmdqmem_init(struct adapter *adapter);
+static void slic_cmdqmem_free(struct adapter *adapter);
+static u32 *slic_cmdqmem_addpage(struct adapter *adapter);
+static int slic_cmdq_init(struct adapter *adapter);
+static void slic_cmdq_free(struct adapter *adapter);
+static void slic_cmdq_reset(struct adapter *adapter);
+static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page);
+static void slic_cmdq_getdone(struct adapter *adapter);
+static void slic_cmdq_putdone_irq(struct adapter *adapter,
+ struct slic_hostcmd *cmd);
+static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter);
+static int slic_rcvqueue_init(struct adapter *adapter);
+static int slic_rcvqueue_reset(struct adapter *adapter);
+static int slic_rcvqueue_fill(struct adapter *adapter);
+static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb);
+static void slic_rcvqueue_free(struct adapter *adapter);
+static void slic_rcv_handle_error(struct adapter *adapter,
+ struct slic_rcvbuf *rcvbuf);
+static void slic_adapter_set_hwaddr(struct adapter *adapter);
+static int slic_card_init(struct sliccard *card, struct adapter *adapter);
+static void slic_intagg_set(struct adapter *adapter, u32 value);
+static int slic_card_download(struct adapter *adapter);
+static u32 slic_card_locate(struct adapter *adapter);
+
+static void slic_if_stop_queue(struct adapter *adapter);
+static void slic_if_start_queue(struct adapter *adapter);
+static int slic_if_init(struct adapter *adapter);
+static int slic_adapter_allocresources(struct adapter *adapter);
+static void slic_adapter_freeresources(struct adapter *adapter);
+static void slic_link_config(struct adapter *adapter, u32 linkspeed,
+ u32 linkduplex);
+static void slic_unmap_mmio_space(struct adapter *adapter);
+static void slic_card_cleanup(struct sliccard *card);
+static void slic_init_cleanup(struct adapter *adapter);
+static void slic_soft_reset(struct adapter *adapter);
+static bool slic_mac_filter(struct adapter *adapter,
+ struct ether_header *ether_frame);
+static void slic_mac_address_config(struct adapter *adapter);
+static void slic_mac_config(struct adapter *adapter);
+static void slic_mcast_set_mask(struct adapter *adapter);
+static int slic_mcast_add_list(struct adapter *adapter, char *address);
+static unsigned char slic_mcast_get_mac_hash(char *macaddr);
+static void slic_mcast_set_bit(struct adapter *adapter, char *address);
+static void slic_config_set(struct adapter *adapter, bool linkchange);
+static void slic_config_clear(struct adapter *adapter);
+static void slic_config_get(struct adapter *adapter, u32 config,
+ u32 configh);
+static void slic_timer_load_check(ulong context);
+static void slic_timer_ping(ulong dev);
+static void slic_assert_fail(void);
+static ushort slic_eeprom_cksum(char *m, int len);
+/* upr */
+static void slic_upr_start(struct adapter *adapter);
+static void slic_link_upr_complete(struct adapter *adapter, u32 Isr);
+static int slic_upr_request(struct adapter *adapter,
+ u32 upr_request,
+ u32 upr_data,
+ u32 upr_data_h,
+ u32 upr_buffer,
+ u32 upr_buffer_h);
+static int slic_upr_queue_request(struct adapter *adapter,
+ u32 upr_request,
+ u32 upr_data,
+ u32 upr_data_h,
+ u32 upr_buffer,
+ u32 upr_buffer_h);
+static void slic_mcast_set_list(struct net_device *dev);
+static void slic_mcast_init_crc32(void);
+
+#if SLIC_DUMP_ENABLED
+static int slic_dump_thread(void *context);
+static uint slic_init_dump_thread(struct sliccard *card);
+static unsigned char slic_get_dump_index(char *path);
+static u32 slic_dump_card(struct sliccard *card, bool resume);
+static u32 slic_dump_halt(struct sliccard *card, unsigned char proc);
+static u32 slic_dump_reg(struct sliccard *card, unsigned char proc);
+static u32 slic_dump_data(struct sliccard *card, u32 addr,
+ ushort count, unsigned char desc);
+static u32 slic_dump_queue(struct sliccard *card, u32 buf_phys,
+ u32 buf_physh, u32 queue);
+static u32 slic_dump_load_queue(struct sliccard *card, u32 data,
+ u32 queue);
+static u32 slic_dump_cam(struct sliccard *card, u32 addr,
+ u32 count, unsigned char desc);
+
+static u32 slic_dump_resume(struct sliccard *card, unsigned char proc);
+static u32 slic_dump_send_cmd(struct sliccard *card, u32 cmd_phys,
+ u32 cmd_physh, u32 buf_phys,
+ u32 buf_physh);
+
+#define create_file(x) STATUS_SUCCESS
+#define write_file(w, x, y, z) STATUS_SUCCESS
+#define close_file(x) STATUS_SUCCESS
+#define read_file(w, x, y, z) STATUS_SUCCESS
+#define open_file(x) STATUS_SUCCESS
+
+/* PAGE_SIZE * 16 */
+#define DUMP_PAGE_SIZE 0xFFFF
+#define DUMP_PAGE_SIZE_HALF 0x7FFE
+#endif
+
+#endif /* _SLIC_INCLUDE_H_ */
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
new file mode 100644
index 00000000000..b61ac4b2db9
--- /dev/null
+++ b/drivers/staging/slicoss/slicoss.c
@@ -0,0 +1,5936 @@
+/**************************************************************************
+ *
+ * Copyright 2000-2006 Alacritech, Inc. All rights reserved.
+ *
+ * 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, 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.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: slicoss.c
+ *
+ * The SLICOSS driver for Alacritech's IS-NIC products.
+ *
+ * This driver is supposed to support:
+ *
+ * Mojave cards (single port PCI Gigabit) both copper and fiber
+ * Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
+ * Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
+ *
+ * The driver was acutally tested on Oasis and Kalahari cards.
+ *
+ *
+ * NOTE: This is the standard, non-accelerated version of Alacritech's
+ * IS-NIC driver.
+ */
+
+#include <linux/version.h>
+
+#define SLIC_DUMP_ENABLED 0
+#define KLUDGE_FOR_4GB_BOUNDARY 1
+#define DEBUG_MICROCODE 1
+#define SLIC_PRODUCTION_BUILD 1
+#define SLIC_FAILURE_RESET 1
+#define DBG 1
+#define SLIC_ASSERT_ENABLED 1
+#define SLIC_GET_STATS_ENABLED 1
+#define SLIC_GET_STATS_TIMER_ENABLED 0
+#define SLIC_PING_TIMER_ENABLED 1
+#define SLIC_POWER_MANAGEMENT_ENABLED 0
+#define SLIC_INTERRUPT_PROCESS_LIMIT 1
+#define LINUX_FREES_ADAPTER_RESOURCES 1
+#define SLIC_OFFLOAD_IP_CHECKSUM 1
+#define STATS_TIMER_INTERVAL 2
+#define PING_TIMER_INTERVAL 1
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <asm/unaligned.h>
+
+#include <linux/ethtool.h>
+#define SLIC_ETHTOOL_SUPPORT 1
+
+#include <linux/uaccess.h>
+#include "slicinc.h"
+#include "gbdownload.h"
+#include "gbrcvucode.h"
+#include "oasisrcvucode.h"
+
+#ifdef DEBUG_MICROCODE
+#include "oasisdbgdownload.h"
+#else
+#include "oasisdownload.h"
+#endif
+
+#if SLIC_DUMP_ENABLED
+#include "slicdump.h"
+#endif
+
+#define SLIC_POWER_MANAGEMENT 0
+
+static uint slic_first_init = 1;
+static char *slic_banner = "Alacritech SLIC Technology(tm) Server "\
+ "and Storage Accelerator (Non-Accelerated)\n";
+
+static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00";
+static char *slic_product_name = "SLIC Technology(tm) Server "\
+ "and Storage Accelerator (Non-Accelerated)";
+static char *slic_vendor = "Alacritech, Inc.";
+
+static int slic_debug = 1;
+static int debug = -1;
+static struct net_device *head_netdevice;
+
+static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL };
+static int intagg_delay = 100;
+static u32 dynamic_intagg;
+static int errormsg;
+static int goodmsg;
+static unsigned int rcv_count;
+static struct dentry *slic_debugfs;
+
+#define DRV_NAME "slicoss"
+#define DRV_VERSION "2.0.1"
+#define DRV_AUTHOR "Alacritech, Inc. Engineering"
+#define DRV_DESCRIPTION "Alacritech SLIC Techonology(tm) "\
+ "Non-Accelerated Driver"
+#define DRV_COPYRIGHT "Copyright 2000-2006 Alacritech, Inc. "\
+ "All rights reserved."
+#define PFX DRV_NAME " "
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_param(dynamic_intagg, int, 0);
+MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
+module_param(intagg_delay, int, 0);
+MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
+
+static struct pci_device_id slic_pci_tbl[] __devinitdata = {
+ {PCI_VENDOR_ID_ALACRITECH,
+ SLIC_1GB_DEVICE_ID,
+ PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_ALACRITECH,
+ SLIC_2GB_DEVICE_ID,
+ PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
+
+#define SLIC_GET_SLIC_HANDLE(_adapter, _pslic_handle) \
+{ \
+ spin_lock_irqsave(&_adapter->handle_lock.lock, \
+ _adapter->handle_lock.flags); \
+ _pslic_handle = _adapter->pfree_slic_handles; \
+ if (_pslic_handle) { \
+ ASSERT(_pslic_handle->type == SLIC_HANDLE_FREE); \
+ _adapter->pfree_slic_handles = _pslic_handle->next; \
+ } \
+ spin_unlock_irqrestore(&_adapter->handle_lock.lock, \
+ _adapter->handle_lock.flags); \
+}
+
+#define SLIC_FREE_SLIC_HANDLE(_adapter, _pslic_handle) \
+{ \
+ _pslic_handle->type = SLIC_HANDLE_FREE; \
+ spin_lock_irqsave(&_adapter->handle_lock.lock, \
+ _adapter->handle_lock.flags); \
+ _pslic_handle->next = _adapter->pfree_slic_handles; \
+ _adapter->pfree_slic_handles = _pslic_handle; \
+ spin_unlock_irqrestore(&_adapter->handle_lock.lock, \
+ _adapter->handle_lock.flags); \
+}
+
+static void slic_debug_init(void);
+static void slic_debug_cleanup(void);
+static void slic_debug_adapter_create(struct adapter *adapter);
+static void slic_debug_adapter_destroy(struct adapter *adapter);
+static void slic_debug_card_create(struct sliccard *card);
+static void slic_debug_card_destroy(struct sliccard *card);
+
+static inline void slic_reg32_write(void __iomem *reg, u32 value, uint flush)
+{
+ writel(value, reg);
+ if (flush)
+ mb();
+}
+
+static inline void slic_reg64_write(struct adapter *adapter,
+ void __iomem *reg,
+ u32 value,
+ void __iomem *regh, u32 paddrh, uint flush)
+{
+ spin_lock_irqsave(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+ if (paddrh != adapter->curaddrupper) {
+ adapter->curaddrupper = paddrh;
+ writel(paddrh, regh);
+ }
+ writel(value, reg);
+ if (flush)
+ mb();
+ spin_unlock_irqrestore(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+}
+
+static void slic_init_driver(void)
+{
+ if (slic_first_init) {
+ DBG_MSG("slicoss: %s slic_first_init set jiffies[%lx]\n",
+ __func__, jiffies);
+ slic_first_init = 0;
+ spin_lock_init(&slic_global.driver_lock.lock);
+ slic_debug_init();
+ }
+}
+
+static void slic_dbg_macaddrs(struct adapter *adapter)
+{
+ DBG_MSG(" (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+ DBG_MSG(" (%s) mac %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ adapter->netdev->name, adapter->macaddr[0],
+ adapter->macaddr[1], adapter->macaddr[2],
+ adapter->macaddr[3], adapter->macaddr[4], adapter->macaddr[5]);
+ return;
+}
+
+#ifdef DEBUG_REGISTER_TRACE
+static void slic_dbg_register_trace(struct adapter *adapter,
+ struct sliccard *card)
+{
+ uint i;
+
+ DBG_ERROR("Dump Register Write Trace: curr_ix == %d\n", card->debug_ix);
+ for (i = 0; i < 32; i++) {
+ DBG_ERROR("%2d %d %4x %x %x\n",
+ i, card->reg_type[i], card->reg_offset[i],
+ card->reg_value[i], card->reg_valueh[i]);
+ }
+}
+}
+#endif
+
+static void slic_init_adapter(struct net_device *netdev,
+ struct pci_dev *pcidev,
+ const struct pci_device_id *pci_tbl_entry,
+ void __iomem *memaddr, int chip_idx)
+{
+ ushort index;
+ struct slic_handle *pslic_handle;
+ struct adapter *adapter = (struct adapter *)netdev_priv(netdev);
+/*
+ DBG_MSG("slicoss: %s (%s)\n netdev [%p]\n adapter[%p]\n "
+ "pcidev [%p]\n", __func__, netdev->name, netdev, adapter, pcidev);*/
+/* adapter->pcidev = pcidev;*/
+ adapter->vendid = pci_tbl_entry->vendor;
+ adapter->devid = pci_tbl_entry->device;
+ adapter->subsysid = pci_tbl_entry->subdevice;
+ adapter->busnumber = pcidev->bus->number;
+ adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F);
+ adapter->functionnumber = (pcidev->devfn & 0x7);
+ adapter->memorylength = pci_resource_len(pcidev, 0);
+ adapter->slic_regs = (__iomem struct slic_regs *)memaddr;
+ adapter->irq = pcidev->irq;
+/* adapter->netdev = netdev;*/
+ adapter->next_netdevice = head_netdevice;
+ head_netdevice = netdev;
+ adapter->chipid = chip_idx;
+ adapter->port = 0; /*adapter->functionnumber;*/
+ adapter->cardindex = adapter->port;
+ adapter->memorybase = memaddr;
+ spin_lock_init(&adapter->upr_lock.lock);
+ spin_lock_init(&adapter->bit64reglock.lock);
+ spin_lock_init(&adapter->adapter_lock.lock);
+ spin_lock_init(&adapter->reset_lock.lock);
+ spin_lock_init(&adapter->handle_lock.lock);
+
+ adapter->card_size = 1;
+ /*
+ Initialize slic_handle array
+ */
+ ASSERT(SLIC_CMDQ_MAXCMDS <= 0xFFFF);
+ /*
+ Start with 1. 0 is an invalid host handle.
+ */
+ for (index = 1, pslic_handle = &adapter->slic_handles[1];
+ index < SLIC_CMDQ_MAXCMDS; index++, pslic_handle++) {
+
+ pslic_handle->token.handle_index = index;
+ pslic_handle->type = SLIC_HANDLE_FREE;
+ pslic_handle->next = adapter->pfree_slic_handles;
+ adapter->pfree_slic_handles = pslic_handle;
+ }
+/*
+ DBG_MSG(".........\nix[%d] phandle[%p] pfree[%p] next[%p]\n",
+ index, pslic_handle, adapter->pfree_slic_handles, pslic_handle->next);*/
+ adapter->pshmem = (struct slic_shmem *)
+ pci_alloc_consistent(adapter->pcidev,
+ sizeof(struct slic_shmem *),
+ &adapter->
+ phys_shmem);
+/*
+ DBG_MSG("slicoss: %s (%s)\n pshmem [%p]\n phys_shmem[%p]\n"\
+ "slic_regs [%p]\n", __func__, netdev->name, adapter->pshmem,
+ (void *)adapter->phys_shmem, adapter->slic_regs);
+*/
+ ASSERT(adapter->pshmem);
+
+ memset(adapter->pshmem, 0, sizeof(struct slic_shmem));
+
+ return;
+}
+
+static int __devinit slic_entry_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *pci_tbl_entry)
+{
+ static int cards_found;
+ static int did_version;
+ int err;
+ struct net_device *netdev;
+ struct adapter *adapter;
+ void __iomem *memmapped_ioaddr = NULL;
+ u32 status = 0;
+ ulong mmio_start = 0;
+ ulong mmio_len = 0;
+ struct sliccard *card = NULL;
+
+ DBG_MSG("slicoss: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n",
+ __func__, jiffies, smp_processor_id());
+
+ slic_global.dynamic_intagg = dynamic_intagg;
+
+ err = pci_enable_device(pcidev);
+
+ DBG_MSG("Call pci_enable_device(%p) status[%x]\n", pcidev, err);
+ if (err)
+ return err;
+
+ if (slic_debug > 0 && did_version++ == 0) {
+ printk(slic_banner);
+ printk(slic_proc_version);
+ }
+
+ err = pci_set_dma_mask(pcidev, DMA_64BIT_MASK);
+ if (!err) {
+ DBG_MSG("pci_set_dma_mask(DMA_64BIT_MASK) successful\n");
+ } else {
+ err = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
+ if (err) {
+ DBG_MSG
+ ("No usable DMA configuration, aborting err[%x]\n",
+ err);
+ return err;
+ }
+ DBG_MSG("pci_set_dma_mask(DMA_32BIT_MASK) successful\n");
+ }
+
+ DBG_MSG("Call pci_request_regions\n");
+
+ err = pci_request_regions(pcidev, DRV_NAME);
+ if (err) {
+ DBG_MSG("pci_request_regions FAILED err[%x]\n", err);
+ return err;
+ }
+
+ DBG_MSG("call pci_set_master\n");
+ pci_set_master(pcidev);
+
+ DBG_MSG("call alloc_etherdev\n");
+ netdev = alloc_etherdev(sizeof(struct adapter));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_out_exit_slic_probe;
+ }
+ DBG_MSG("alloc_etherdev for slic netdev[%p]\n", netdev);
+
+ SET_NETDEV_DEV(netdev, &pcidev->dev);
+
+ pci_set_drvdata(pcidev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pcidev = pcidev;
+
+ mmio_start = pci_resource_start(pcidev, 0);
+ mmio_len = pci_resource_len(pcidev, 0);
+
+ DBG_MSG("slicoss: call ioremap(mmio_start[%lx], mmio_len[%lx])\n",
+ mmio_start, mmio_len);
+
+/* memmapped_ioaddr = (u32)ioremap_nocache(mmio_start, mmio_len);*/
+ memmapped_ioaddr = ioremap(mmio_start, mmio_len);
+ DBG_MSG("slicoss: %s MEMMAPPED_IOADDR [%p]\n", __func__,
+ memmapped_ioaddr);
+ if (!memmapped_ioaddr) {
+ DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
+ __func__, mmio_len, mmio_start);
+ goto err_out_free_mmio_region;
+ }
+
+ DBG_MSG
+ ("slicoss: %s found Alacritech SLICOSS PCI, MMIO at %p, "\
+ "start[%lx] len[%lx], IRQ %d.\n",
+ __func__, memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq);
+
+ slic_config_pci(pcidev);
+
+ slic_init_driver();
+
+ slic_init_adapter(netdev,
+ pcidev, pci_tbl_entry, memmapped_ioaddr, cards_found);
+
+ status = slic_card_locate(adapter);
+ if (status) {
+ DBG_ERROR("%s cannot locate card\n", __func__);
+ goto err_out_free_mmio_region;
+ }
+
+ card = adapter->card;
+
+ if (!adapter->allocated) {
+ card->adapters_allocated++;
+ adapter->allocated = 1;
+ }
+
+ DBG_MSG("slicoss: %s card: %p\n", __func__,
+ adapter->card);
+ DBG_MSG("slicoss: %s card->adapter[%d] == [%p]\n", __func__,
+ (uint) adapter->port, adapter);
+ DBG_MSG("slicoss: %s card->adapters_allocated [%d]\n", __func__,
+ card->adapters_allocated);
+ DBG_MSG("slicoss: %s card->adapters_activated [%d]\n", __func__,
+ card->adapters_activated);
+
+ status = slic_card_init(card, adapter);
+
+ if (status != STATUS_SUCCESS) {
+ card->state = CARD_FAIL;
+ adapter->state = ADAPT_FAIL;
+ adapter->linkstate = LINK_DOWN;
+ DBG_ERROR("slic_card_init FAILED status[%x]\n", status);
+ } else {
+ slic_adapter_set_hwaddr(adapter);
+ }
+
+ netdev->base_addr = (unsigned long)adapter->memorybase;
+ netdev->irq = adapter->irq;
+ netdev->open = slic_entry_open;
+ netdev->stop = slic_entry_halt;
+ netdev->hard_start_xmit = slic_xmit_start;
+ netdev->do_ioctl = slic_ioctl;
+ netdev->set_mac_address = slic_mac_set_address;
+#if SLIC_GET_STATS_ENABLED
+ netdev->get_stats = slic_get_stats;
+#endif
+ netdev->set_multicast_list = slic_mcast_set_list;
+
+ slic_debug_adapter_create(adapter);
+
+ strcpy(netdev->name, "eth%d");
+ err = register_netdev(netdev);
+ if (err) {
+ DBG_ERROR("Cannot register net device, aborting.\n");
+ goto err_out_unmap;
+ }
+
+ DBG_MSG
+ ("slicoss: addr 0x%lx, irq %d, MAC addr "\
+ "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ mmio_start, /*pci_resource_start(pcidev, 0), */ pcidev->irq,
+ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
+ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+
+ cards_found++;
+ DBG_MSG("slicoss: %s EXIT status[%x] jiffies[%lx] cpu %d\n",
+ __func__, status, jiffies, smp_processor_id());
+
+ return status;
+
+err_out_unmap:
+ iounmap(memmapped_ioaddr);
+
+err_out_free_mmio_region:
+ release_mem_region(mmio_start, mmio_len);
+
+err_out_exit_slic_probe:
+ pci_release_regions(pcidev);
+ DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __func__, jiffies,
+ smp_processor_id());
+
+ return -ENODEV;
+}
+
+static int slic_entry_open(struct net_device *dev)
+{
+ struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+ struct sliccard *card = adapter->card;
+ u32 locked = 0;
+ int status;
+
+ ASSERT(adapter);
+ ASSERT(card);
+ DBG_MSG
+ ("slicoss: %s adapter->activated[%d] card->adapters[%x] "\
+ "allocd[%x]\n", __func__, adapter->activated,
+ card->adapters_activated,
+ card->adapters_allocated);
+ DBG_MSG
+ ("slicoss: %s (%s): [jiffies[%lx] cpu %d] dev[%p] adapt[%p] "\
+ "port[%d] card[%p]\n",
+ __func__, adapter->netdev->name, jiffies, smp_processor_id(),
+ adapter->netdev, adapter, adapter->port, card);
+
+ netif_stop_queue(adapter->netdev);
+
+ spin_lock_irqsave(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+ locked = 1;
+ if (!adapter->activated) {
+ card->adapters_activated++;
+ slic_global.num_slic_ports_active++;
+ adapter->activated = 1;
+ }
+ status = slic_if_init(adapter);
+
+ if (status != STATUS_SUCCESS) {
+ if (adapter->activated) {
+ card->adapters_activated--;
+ slic_global.num_slic_ports_active--;
+ adapter->activated = 0;
+ }
+ if (locked) {
+ spin_unlock_irqrestore(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+ locked = 0;
+ }
+ return status;
+ }
+ DBG_MSG("slicoss: %s set card->master[%p] adapter[%p]\n", __func__,
+ card->master, adapter);
+ if (!card->master)
+ card->master = adapter;
+#if SLIC_DUMP_ENABLED
+ if (!(card->dumpthread_running))
+ init_waitqueue_head(&card->dump_wq);
+#endif
+
+ if (locked) {
+ spin_unlock_irqrestore(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+ locked = 0;
+ }
+#if SLIC_DUMP_ENABLED
+ if (!(card->dumpthread_running)) {
+ DBG_MSG("attempt to initialize dump thread\n");
+ status = slic_init_dump_thread(card);
+ /*
+ Even if the dump thread fails, we will continue at this point
+ */
+ }
+#endif
+
+ return STATUS_SUCCESS;
+}
+
+static void __devexit slic_entry_remove(struct pci_dev *pcidev)
+{
+ struct net_device *dev = pci_get_drvdata(pcidev);
+ u32 mmio_start = 0;
+ uint mmio_len = 0;
+ struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+ struct sliccard *card;
+
+ ASSERT(adapter);
+ DBG_MSG("slicoss: %s ENTER dev[%p] adapter[%p]\n", __func__, dev,
+ adapter);
+ slic_adapter_freeresources(adapter);
+ slic_unmap_mmio_space(adapter);
+ DBG_MSG("slicoss: %s unregister_netdev\n", __func__);
+ unregister_netdev(dev);
+
+ mmio_start = pci_resource_start(pcidev, 0);
+ mmio_len = pci_resource_len(pcidev, 0);
+
+ DBG_MSG("slicoss: %s rel_region(0) start[%x] len[%x]\n", __func__,
+ mmio_start, mmio_len);
+ release_mem_region(mmio_start, mmio_len);
+
+ DBG_MSG("slicoss: %s iounmap dev->base_addr[%x]\n", __func__,
+ (uint) dev->base_addr);
+ iounmap((void __iomem *)dev->base_addr);
+ ASSERT(adapter->card);
+ card = adapter->card;
+ ASSERT(card->adapters_allocated);
+ card->adapters_allocated--;
+ adapter->allocated = 0;
+ DBG_MSG
+ ("slicoss: %s init[%x] alloc[%x] card[%p] adapter[%p]\n",
+ __func__, card->adapters_activated, card->adapters_allocated,
+ card, adapter);
+ if (!card->adapters_allocated) {
+ struct sliccard *curr_card = slic_global.slic_card;
+ if (curr_card == card) {
+ slic_global.slic_card = card->next;
+ } else {
+ while (curr_card->next != card)
+ curr_card = curr_card->next;
+ ASSERT(curr_card);
+ curr_card->next = card->next;
+ }
+ ASSERT(slic_global.num_slic_cards);
+ slic_global.num_slic_cards--;
+ slic_card_cleanup(card);
+ }
+ DBG_MSG("slicoss: %s deallocate device\n", __func__);
+ kfree(dev);
+ pci_release_regions(pcidev);
+ DBG_MSG("slicoss: %s EXIT\n", __func__);
+}
+
+static int slic_entry_halt(struct net_device *dev)
+{
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct sliccard *card = adapter->card;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ spin_lock_irqsave(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+ ASSERT(card);
+ DBG_MSG("slicoss: %s (%s) ENTER\n", __func__, dev->name);
+ DBG_MSG("slicoss: %s (%s) actvtd[%d] alloc[%d] state[%x] adapt[%p]\n",
+ __func__, dev->name, card->adapters_activated,
+ card->adapters_allocated, card->state, adapter);
+ slic_if_stop_queue(adapter);
+ adapter->state = ADAPT_DOWN;
+ adapter->linkstate = LINK_DOWN;
+ adapter->upr_list = NULL;
+ adapter->upr_busy = 0;
+ adapter->devflags_prev = 0;
+ DBG_MSG("slicoss: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n",
+ __func__, dev->name, adapter, adapter->state);
+ ASSERT(card->adapter[adapter->cardindex] == adapter);
+ WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
+ adapter->all_reg_writes++;
+ adapter->icr_reg_writes++;
+ slic_config_clear(adapter);
+ DBG_MSG("slicoss: %s (%s) dev[%p] adapt[%p] card[%p]\n",
+ __func__, dev->name, dev, adapter, card);
+ if (adapter->activated) {
+ card->adapters_activated--;
+ slic_global.num_slic_ports_active--;
+ adapter->activated = 0;
+ }
+#ifdef AUTOMATIC_RESET
+ WRITE_REG(slic_regs->slic_reset_iface, 0, FLUSH);
+#endif
+ /*
+ * Reset the adapter's rsp, cmd, and rcv queues
+ */
+ slic_cmdq_reset(adapter);
+ slic_rspqueue_reset(adapter);
+ slic_rcvqueue_reset(adapter);
+
+#ifdef AUTOMATIC_RESET
+ if (!card->adapters_activated) {
+
+#if SLIC_DUMP_ENABLED
+ if (card->dumpthread_running) {
+ uint status;
+ DBG_MSG("attempt to terminate dump thread pid[%x]\n",
+ card->dump_task_id);
+ status = kill_proc(card->dump_task_id->pid, SIGKILL, 1);
+
+ if (!status) {
+ int count = 10 * 100;
+ while (card->dumpthread_running && --count) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ }
+
+ if (!count) {
+ DBG_MSG
+ ("slicmon thread cleanup FAILED \
+ pid[%x]\n",
+ card->dump_task_id->pid);
+ }
+ }
+ }
+#endif
+ DBG_MSG("slicoss: %s (%s) initiate CARD_HALT\n", __func__,
+ dev->name);
+
+ slic_card_init(card, adapter);
+ }
+#endif
+
+ DBG_MSG("slicoss: %s (%s) EXIT\n", __func__, dev->name);
+ DBG_MSG("slicoss: %s EXIT\n", __func__);
+ spin_unlock_irqrestore(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+ return STATUS_SUCCESS;
+}
+
+static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ ASSERT(rq);
+/*
+ DBG_MSG("slicoss: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev);
+*/
+ switch (cmd) {
+ case SIOCSLICSETINTAGG:
+ {
+ struct adapter *adapter = (struct adapter *)
+ netdev_priv(dev);
+ u32 data[7];
+ u32 intagg;
+
+ if (copy_from_user(data, rq->ifr_data, 28)) {
+ DBG_ERROR
+ ("copy_from_user FAILED getting initial \
+ params\n");
+ return -EFAULT;
+ }
+ intagg = data[0];
+ printk(KERN_EMERG
+ "%s: set interrupt aggregation to %d\n",
+ __func__, intagg);
+ slic_intagg_set(adapter, intagg);
+ return 0;
+ }
+#ifdef SLIC_USER_REQUEST_DUMP_ENABLED
+ case SIOCSLICDUMPCARD:
+ {
+ struct adapter *adapter = (struct adapter *)
+ dev->priv;
+ struct sliccard *card;
+
+ ASSERT(adapter);
+ ASSERT(adapter->card)
+ card = adapter->card;
+
+ DBG_IOCTL("slic_ioctl SIOCSLIC_DUMP_CARD\n");
+
+ if (card->dump_requested == SLIC_DUMP_DONE) {
+ printk(SLICLEVEL
+ "SLIC Card dump to be overwritten\n");
+ card->dump_requested = SLIC_DUMP_REQUESTED;
+ } else if ((card->dump_requested == SLIC_DUMP_REQUESTED)
+ || (card->dump_requested ==
+ SLIC_DUMP_IN_PROGRESS)) {
+ printk(SLICLEVEL
+ "SLIC Card dump Requested but already \
+ in progress... ignore\n");
+ } else {
+ printk(SLICLEVEL
+ "SLIC Card #%d Dump Requested\n",
+ card->cardnum);
+ card->dump_requested = SLIC_DUMP_REQUESTED;
+ }
+ return 0;
+ }
+#endif
+
+#ifdef SLIC_TRACE_DUMP_ENABLED
+ case SIOCSLICTRACEDUMP:
+ {
+ ulong data[7];
+ ulong value;
+
+ DBG_IOCTL("slic_ioctl SIOCSLIC_TRACE_DUMP\n");
+
+ if (copy_from_user(data, rq->ifr_data, 28)) {
+ PRINT_ERROR
+ ("slic: copy_from_user FAILED getting \
+ initial simba param\n");
+ return -EFAULT;
+ }
+
+ value = data[0];
+ if (tracemon_request == SLIC_DUMP_DONE) {
+ PRINT_ERROR
+ ("ATK Diagnostic Trace Dump Requested\n");
+ tracemon_request = SLIC_DUMP_REQUESTED;
+ tracemon_request_type = value;
+ tracemon_timestamp = jiffies;
+ } else if ((tracemon_request == SLIC_DUMP_REQUESTED) ||
+ (tracemon_request ==
+ SLIC_DUMP_IN_PROGRESS)) {
+ PRINT_ERROR
+ ("ATK Diagnostic Trace Dump Requested but \
+ already in progress... ignore\n");
+ } else {
+ PRINT_ERROR
+ ("ATK Diagnostic Trace Dump Requested\n");
+ tracemon_request = SLIC_DUMP_REQUESTED;
+ tracemon_request_type = value;
+ tracemon_timestamp = jiffies;
+ }
+ return 0;
+ }
+#endif
+#if SLIC_ETHTOOL_SUPPORT
+ case SIOCETHTOOL:
+ {
+ struct adapter *adapter = (struct adapter *)
+ netdev_priv(dev);
+ struct ethtool_cmd data;
+ struct ethtool_cmd ecmd;
+
+ ASSERT(adapter);
+/* DBG_MSG("slicoss: %s SIOCETHTOOL\n", __func__); */
+ if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
+ return -EFAULT;
+
+ if (ecmd.cmd == ETHTOOL_GSET) {
+ data.supported =
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_MII);
+ data.port = PORT_MII;
+ data.transceiver = XCVR_INTERNAL;
+ data.phy_address = 0;
+ if (adapter->linkspeed == LINK_100MB)
+ data.speed = SPEED_100;
+ else if (adapter->linkspeed == LINK_10MB)
+ data.speed = SPEED_10;
+ else
+ data.speed = 0;
+
+ if (adapter->linkduplex == LINK_FULLD)
+ data.duplex = DUPLEX_FULL;
+ else
+ data.duplex = DUPLEX_HALF;
+
+ data.autoneg = AUTONEG_ENABLE;
+ data.maxtxpkt = 1;
+ data.maxrxpkt = 1;
+ if (copy_to_user
+ (rq->ifr_data, &data, sizeof(data)))
+ return -EFAULT;
+
+ } else if (ecmd.cmd == ETHTOOL_SSET) {
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (adapter->linkspeed == LINK_100MB)
+ data.speed = SPEED_100;
+ else if (adapter->linkspeed == LINK_10MB)
+ data.speed = SPEED_10;
+ else
+ data.speed = 0;
+
+ if (adapter->linkduplex == LINK_FULLD)
+ data.duplex = DUPLEX_FULL;
+ else
+ data.duplex = DUPLEX_HALF;
+
+ data.autoneg = AUTONEG_ENABLE;
+ data.maxtxpkt = 1;
+ data.maxrxpkt = 1;
+ if ((ecmd.speed != data.speed) ||
+ (ecmd.duplex != data.duplex)) {
+ u32 speed;
+ u32 duplex;
+
+ if (ecmd.speed == SPEED_10) {
+ speed = 0;
+ SLIC_DISPLAY
+ ("%s: slic ETHTOOL set \
+ link speed==10MB",
+ dev->name);
+ } else {
+ speed = PCR_SPEED_100;
+ SLIC_DISPLAY
+ ("%s: slic ETHTOOL set \
+ link speed==100MB",
+ dev->name);
+ }
+ if (ecmd.duplex == DUPLEX_FULL) {
+ duplex = PCR_DUPLEX_FULL;
+ SLIC_DISPLAY
+ (": duplex==FULL\n");
+ } else {
+ duplex = 0;
+ SLIC_DISPLAY
+ (": duplex==HALF\n");
+ }
+ slic_link_config(adapter,
+ speed, duplex);
+ slic_link_event_handler(adapter);
+ }
+ }
+ return 0;
+ }
+#endif
+ default:
+/* DBG_MSG("slicoss: %s UNSUPPORTED[%x]\n", __func__, cmd); */
+ return -EOPNOTSUPP;
+ }
+}
+
+#define XMIT_FAIL_LINK_STATE 1
+#define XMIT_FAIL_ZERO_LENGTH 2
+#define XMIT_FAIL_HOSTCMD_FAIL 3
+
+static void slic_xmit_build_request(struct adapter *adapter,
+ struct slic_hostcmd *hcmd, struct sk_buff *skb)
+{
+ struct slic_host64_cmd *ihcmd;
+ ulong phys_addr;
+
+ ihcmd = &hcmd->cmd64;
+
+ ihcmd->flags = (adapter->port << IHFLG_IFSHFT);
+ ihcmd->command = IHCMD_XMT_REQ;
+ ihcmd->u.slic_buffers.totlen = skb->len;
+ phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ ihcmd->u.slic_buffers.bufs[0].paddrl = SLIC_GET_ADDR_LOW(phys_addr);
+ ihcmd->u.slic_buffers.bufs[0].paddrh = SLIC_GET_ADDR_HIGH(phys_addr);
+ ihcmd->u.slic_buffers.bufs[0].length = skb->len;
+#if defined(CONFIG_X86_64)
+ hcmd->cmdsize = (u32) ((((u64)&ihcmd->u.slic_buffers.bufs[1] -
+ (u64) hcmd) + 31) >> 5);
+#elif defined(CONFIG_X86)
+ hcmd->cmdsize = ((((u32) &ihcmd->u.slic_buffers.bufs[1] -
+ (u32) hcmd) + 31) >> 5);
+#else
+ Stop Compilation;
+#endif
+}
+
+#define NORMAL_ETHFRAME 0
+
+static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sliccard *card;
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct slic_hostcmd *hcmd = NULL;
+ u32 status = 0;
+ u32 skbtype = NORMAL_ETHFRAME;
+ void *offloadcmd = NULL;
+
+ card = adapter->card;
+ ASSERT(card);
+/*
+ DBG_ERROR("xmit_start (%s) ENTER skb[%p] len[%d] linkstate[%x] state[%x]\n",
+ adapter->netdev->name, skb, skb->len, adapter->linkstate,
+ adapter->state);
+*/
+ if ((adapter->linkstate != LINK_UP) ||
+ (adapter->state != ADAPT_UP) || (card->state != CARD_UP)) {
+ status = XMIT_FAIL_LINK_STATE;
+ goto xmit_fail;
+
+ } else if (skb->len == 0) {
+ status = XMIT_FAIL_ZERO_LENGTH;
+ goto xmit_fail;
+ }
+
+ if (skbtype == NORMAL_ETHFRAME) {
+ hcmd = slic_cmdq_getfree(adapter);
+ if (!hcmd) {
+ adapter->xmitq_full = 1;
+ status = XMIT_FAIL_HOSTCMD_FAIL;
+ goto xmit_fail;
+ }
+ ASSERT(hcmd->pslic_handle);
+ ASSERT(hcmd->cmd64.hosthandle ==
+ hcmd->pslic_handle->token.handle_token);
+ hcmd->skb = skb;
+ hcmd->busy = 1;
+ hcmd->type = SLIC_CMD_DUMB;
+ if (skbtype == NORMAL_ETHFRAME)
+ slic_xmit_build_request(adapter, hcmd, skb);
+ }
+ adapter->stats.tx_packets++;
+ adapter->stats.tx_bytes += skb->len;
+
+#ifdef DEBUG_DUMP
+ if (adapter->kill_card) {
+ struct slic_host64_cmd ihcmd;
+
+ ihcmd = &hcmd->cmd64;
+
+ ihcmd->flags |= 0x40;
+ adapter->kill_card = 0; /* only do this once */
+ }
+#endif
+ if (hcmd->paddrh == 0) {
+ WRITE_REG(adapter->slic_regs->slic_cbar,
+ (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH);
+ } else {
+ WRITE_REG64(adapter,
+ adapter->slic_regs->slic_cbar64,
+ (hcmd->paddrl | hcmd->cmdsize),
+ adapter->slic_regs->slic_addr_upper,
+ hcmd->paddrh, DONT_FLUSH);
+ }
+xmit_done:
+ return 0;
+xmit_fail:
+ slic_xmit_fail(adapter, skb, offloadcmd, skbtype, status);
+ goto xmit_done;
+}
+
+static void slic_xmit_fail(struct adapter *adapter,
+ struct sk_buff *skb,
+ void *cmd, u32 skbtype, u32 status)
+{
+ if (adapter->xmitq_full)
+ slic_if_stop_queue(adapter);
+ if ((cmd == NULL) && (status <= XMIT_FAIL_HOSTCMD_FAIL)) {
+ switch (status) {
+ case XMIT_FAIL_LINK_STATE:
+ DBG_ERROR
+ ("(%s) reject xmit skb[%p: %x] linkstate[%s] \
+ adapter[%s:%d] card[%s:%d]\n",
+ adapter->netdev->name, skb, skb->pkt_type,
+ SLIC_LINKSTATE(adapter->linkstate),
+ SLIC_ADAPTER_STATE(adapter->state), adapter->state,
+ SLIC_CARD_STATE(adapter->card->state),
+ adapter->card->state);
+ break;
+ case XMIT_FAIL_ZERO_LENGTH:
+ DBG_ERROR
+ ("xmit_start skb->len == 0 skb[%p] type[%x]!!!! \n",
+ skb, skb->pkt_type);
+ break;
+ case XMIT_FAIL_HOSTCMD_FAIL:
+ DBG_ERROR
+ ("xmit_start skb[%p] type[%x] No host commands \
+ available !!!! \n",
+ skb, skb->pkt_type);
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+ dev_kfree_skb(skb);
+ adapter->stats.tx_dropped++;
+}
+
+static void slic_rcv_handle_error(struct adapter *adapter,
+ struct slic_rcvbuf *rcvbuf)
+{
+ struct slic_hddr_wds *hdr = (struct slic_hddr_wds *)rcvbuf->data;
+
+ if (adapter->devid != SLIC_1GB_DEVICE_ID) {
+ if (hdr->frame_status14 & VRHSTAT_802OE)
+ adapter->if_events.oflow802++;
+ if (hdr->frame_status14 & VRHSTAT_TPOFLO)
+ adapter->if_events.Tprtoflow++;
+ if (hdr->frame_status_b14 & VRHSTATB_802UE)
+ adapter->if_events.uflow802++;
+ if (hdr->frame_status_b14 & VRHSTATB_RCVE) {
+ adapter->if_events.rcvearly++;
+ adapter->stats.rx_fifo_errors++;
+ }
+ if (hdr->frame_status_b14 & VRHSTATB_BUFF) {
+ adapter->if_events.Bufov++;
+ adapter->stats.rx_over_errors++;
+ }
+ if (hdr->frame_status_b14 & VRHSTATB_CARRE) {
+ adapter->if_events.Carre++;
+ adapter->stats.tx_carrier_errors++;
+ }
+ if (hdr->frame_status_b14 & VRHSTATB_LONGE)
+ adapter->if_events.Longe++;
+ if (hdr->frame_status_b14 & VRHSTATB_PREA)
+ adapter->if_events.Invp++;
+ if (hdr->frame_status_b14 & VRHSTATB_CRC) {
+ adapter->if_events.Crc++;
+ adapter->stats.rx_crc_errors++;
+ }
+ if (hdr->frame_status_b14 & VRHSTATB_DRBL)
+ adapter->if_events.Drbl++;
+ if (hdr->frame_status_b14 & VRHSTATB_CODE)
+ adapter->if_events.Code++;
+ if (hdr->frame_status_b14 & VRHSTATB_TPCSUM)
+ adapter->if_events.TpCsum++;
+ if (hdr->frame_status_b14 & VRHSTATB_TPHLEN)
+ adapter->if_events.TpHlen++;
+ if (hdr->frame_status_b14 & VRHSTATB_IPCSUM)
+ adapter->if_events.IpCsum++;
+ if (hdr->frame_status_b14 & VRHSTATB_IPLERR)
+ adapter->if_events.IpLen++;
+ if (hdr->frame_status_b14 & VRHSTATB_IPHERR)
+ adapter->if_events.IpHlen++;
+ } else {
+ if (hdr->frame_statusGB & VGBSTAT_XPERR) {
+ u32 xerr = hdr->frame_statusGB >> VGBSTAT_XERRSHFT;
+
+ if (xerr == VGBSTAT_XCSERR)
+ adapter->if_events.TpCsum++;
+ if (xerr == VGBSTAT_XUFLOW)
+ adapter->if_events.Tprtoflow++;
+ if (xerr == VGBSTAT_XHLEN)
+ adapter->if_events.TpHlen++;
+ }
+ if (hdr->frame_statusGB & VGBSTAT_NETERR) {
+ u32 nerr =
+ (hdr->
+ frame_statusGB >> VGBSTAT_NERRSHFT) &
+ VGBSTAT_NERRMSK;
+ if (nerr == VGBSTAT_NCSERR)
+ adapter->if_events.IpCsum++;
+ if (nerr == VGBSTAT_NUFLOW)
+ adapter->if_events.IpLen++;
+ if (nerr == VGBSTAT_NHLEN)
+ adapter->if_events.IpHlen++;
+ }
+ if (hdr->frame_statusGB & VGBSTAT_LNKERR) {
+ u32 lerr = hdr->frame_statusGB & VGBSTAT_LERRMSK;
+
+ if (lerr == VGBSTAT_LDEARLY)
+ adapter->if_events.rcvearly++;
+ if (lerr == VGBSTAT_LBOFLO)
+ adapter->if_events.Bufov++;
+ if (lerr == VGBSTAT_LCODERR)
+ adapter->if_events.Code++;
+ if (lerr == VGBSTAT_LDBLNBL)
+ adapter->if_events.Drbl++;
+ if (lerr == VGBSTAT_LCRCERR)
+ adapter->if_events.Crc++;
+ if (lerr == VGBSTAT_LOFLO)
+ adapter->if_events.oflow802++;
+ if (lerr == VGBSTAT_LUFLO)
+ adapter->if_events.uflow802++;
+ }
+ }
+ return;
+}
+
+#define TCP_OFFLOAD_FRAME_PUSHFLAG 0x10000000
+#define M_FAST_PATH 0x0040
+
+static void slic_rcv_handler(struct adapter *adapter)
+{
+ struct sk_buff *skb;
+ struct slic_rcvbuf *rcvbuf;
+ u32 frames = 0;
+
+ while ((skb = slic_rcvqueue_getnext(adapter))) {
+ u32 rx_bytes;
+
+ ASSERT(skb->head);
+ rcvbuf = (struct slic_rcvbuf *)skb->head;
+ adapter->card->events++;
+ if (rcvbuf->status & IRHDDR_ERR) {
+ adapter->rx_errors++;
+ slic_rcv_handle_error(adapter, rcvbuf);
+ slic_rcvqueue_reinsert(adapter, skb);
+ continue;
+ }
+
+ if (!slic_mac_filter(adapter, (struct ether_header *)
+ rcvbuf->data)) {
+#if 0
+ DBG_MSG
+ ("slicoss: %s (%s) drop frame due to mac filter\n",
+ __func__, adapter->netdev->name);
+#endif
+ slic_rcvqueue_reinsert(adapter, skb);
+ continue;
+ }
+ skb_pull(skb, SLIC_RCVBUF_HEADSIZE);
+ rx_bytes = (rcvbuf->length & IRHDDR_FLEN_MSK);
+ skb_put(skb, rx_bytes);
+ adapter->stats.rx_packets++;
+ adapter->stats.rx_bytes += rx_bytes;
+#if SLIC_OFFLOAD_IP_CHECKSUM
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+#endif
+
+ skb->dev = adapter->netdev;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ netif_rx(skb);
+
+ ++frames;
+#if SLIC_INTERRUPT_PROCESS_LIMIT
+ if (frames >= SLIC_RCVQ_MAX_PROCESS_ISR) {
+ adapter->rcv_interrupt_yields++;
+ break;
+ }
+#endif
+ }
+ adapter->max_isr_rcvs = max(adapter->max_isr_rcvs, frames);
+}
+
+static void slic_xmit_complete(struct adapter *adapter)
+{
+ struct slic_hostcmd *hcmd;
+ struct slic_rspbuf *rspbuf;
+ u32 frames = 0;
+ struct slic_handle_word slic_handle_word;
+
+ do {
+ rspbuf = slic_rspqueue_getnext(adapter);
+ if (!rspbuf)
+ break;
+ adapter->xmit_completes++;
+ adapter->card->events++;
+ /*
+ Get the complete host command buffer
+ */
+ slic_handle_word.handle_token = rspbuf->hosthandle;
+ ASSERT(slic_handle_word.handle_index);
+ ASSERT(slic_handle_word.handle_index <= SLIC_CMDQ_MAXCMDS);
+ hcmd =
+ (struct slic_hostcmd *)
+ adapter->slic_handles[slic_handle_word.handle_index].
+ address;
+/* hcmd = (struct slic_hostcmd *) rspbuf->hosthandle; */
+ ASSERT(hcmd);
+ ASSERT(hcmd->pslic_handle ==
+ &adapter->slic_handles[slic_handle_word.handle_index]);
+/*
+ DBG_ERROR("xmit_complete (%s) hcmd[%p] hosthandle[%x]\n",
+ adapter->netdev->name, hcmd, hcmd->cmd64.hosthandle);
+ DBG_ERROR(" skb[%p] len %d hcmdtype[%x]\n", hcmd->skb,
+ hcmd->skb->len, hcmd->type);
+*/
+ if (hcmd->type == SLIC_CMD_DUMB) {
+ if (hcmd->skb)
+ dev_kfree_skb_irq(hcmd->skb);
+ slic_cmdq_putdone_irq(adapter, hcmd);
+ }
+ rspbuf->status = 0;
+ rspbuf->hosthandle = 0;
+ frames++;
+ } while (1);
+ adapter->max_isr_xmits = max(adapter->max_isr_xmits, frames);
+}
+
+static irqreturn_t slic_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ u32 isr;
+
+ if ((adapter->pshmem) && (adapter->pshmem->isr)) {
+ WRITE_REG(adapter->slic_regs->slic_icr, ICR_INT_MASK, FLUSH);
+ isr = adapter->isrcopy = adapter->pshmem->isr;
+ adapter->pshmem->isr = 0;
+ adapter->num_isrs++;
+ switch (adapter->card->state) {
+ case CARD_UP:
+ if (isr & ~ISR_IO) {
+ if (isr & ISR_ERR) {
+ adapter->error_interrupts++;
+ if (isr & ISR_RMISS) {
+ int count;
+ int pre_count;
+ int errors;
+
+ struct slic_rcvqueue *rcvq =
+ &adapter->rcvqueue;
+
+ adapter->
+ error_rmiss_interrupts++;
+ if (!rcvq->errors)
+ rcv_count = rcvq->count;
+ pre_count = rcvq->count;
+ errors = rcvq->errors;
+
+ while (rcvq->count <
+ SLIC_RCVQ_FILLTHRESH) {
+ count =
+ slic_rcvqueue_fill
+ (adapter);
+ if (!count)
+ break;
+ }
+ DBG_MSG
+ ("(%s): [%x] ISR_RMISS \
+ initial[%x] pre[%x] \
+ errors[%x] \
+ post_count[%x]\n",
+ adapter->netdev->name,
+ isr, rcv_count, pre_count,
+ errors, rcvq->count);
+ } else if (isr & ISR_XDROP) {
+ DBG_ERROR
+ ("isr & ISR_ERR [%x] \
+ ISR_XDROP \n",
+ isr);
+ } else {
+ DBG_ERROR
+ ("isr & ISR_ERR [%x]\n",
+ isr);
+ }
+ }
+
+ if (isr & ISR_LEVENT) {
+ /*DBG_MSG("%s (%s) ISR_LEVENT \n",
+ __func__, adapter->netdev->name);*/
+ adapter->linkevent_interrupts++;
+ slic_link_event_handler(adapter);
+ }
+
+ if ((isr & ISR_UPC) ||
+ (isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
+ adapter->upr_interrupts++;
+ slic_upr_request_complete(adapter, isr);
+ }
+ }
+
+ if (isr & ISR_RCV) {
+ adapter->rcv_interrupts++;
+ slic_rcv_handler(adapter);
+ }
+
+ if (isr & ISR_CMD) {
+ adapter->xmit_interrupts++;
+ slic_xmit_complete(adapter);
+ }
+ break;
+
+ case CARD_DOWN:
+ if ((isr & ISR_UPC) ||
+ (isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
+ adapter->upr_interrupts++;
+ slic_upr_request_complete(adapter, isr);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ adapter->isrcopy = 0;
+ adapter->all_reg_writes += 2;
+ adapter->isr_reg_writes++;
+ WRITE_REG(adapter->slic_regs->slic_isr, 0, FLUSH);
+ } else {
+ adapter->false_interrupts++;
+ }
+ return IRQ_HANDLED;
+}
+
+/*
+ * slic_link_event_handler -
+ *
+ * Initiate a link configuration sequence. The link configuration begins
+ * by issuing a READ_LINK_STATUS command to the Utility Processor on the
+ * SLIC. Since the command finishes asynchronously, the slic_upr_comlete
+ * routine will follow it up witha UP configuration write command, which
+ * will also complete asynchronously.
+ *
+ */
+static void slic_link_event_handler(struct adapter *adapter)
+{
+ int status;
+ struct slic_shmem *pshmem;
+
+ if (adapter->state != ADAPT_UP) {
+ /* Adapter is not operational. Ignore. */
+ return;
+ }
+
+ pshmem = (struct slic_shmem *)adapter->phys_shmem;
+
+#if defined(CONFIG_X86_64)
+/*
+ DBG_MSG("slic_event_handler pshmem->linkstatus[%x] pshmem[%p]\n \
+ &linkstatus[%p] &isr[%p]\n", adapter->pshmem->linkstatus, pshmem,
+ &pshmem->linkstatus, &pshmem->isr);
+*/
+ status = slic_upr_request(adapter,
+ SLIC_UPR_RLSR,
+ SLIC_GET_ADDR_LOW(&pshmem->linkstatus),
+ SLIC_GET_ADDR_HIGH(&pshmem->linkstatus),
+ 0, 0);
+#elif defined(CONFIG_X86)
+ status = slic_upr_request(adapter, SLIC_UPR_RLSR,
+ (u32) &pshmem->linkstatus, /* no 4GB wrap guaranteed */
+ 0, 0, 0);
+#else
+ Stop compilation;
+#endif
+ ASSERT((status == STATUS_SUCCESS) || (status == STATUS_PENDING));
+}
+
+static void slic_init_cleanup(struct adapter *adapter)
+{
+ DBG_MSG("slicoss: %s ENTER adapter[%p] ", __func__, adapter);
+ if (adapter->intrregistered) {
+ DBG_MSG("FREE_IRQ ");
+ adapter->intrregistered = 0;
+ free_irq(adapter->netdev->irq, adapter->netdev);
+
+ }
+ if (adapter->pshmem) {
+ DBG_MSG("FREE_SHMEM ");
+ DBG_MSG("adapter[%p] port %d pshmem[%p] FreeShmem ",
+ adapter, adapter->port, (void *) adapter->pshmem);
+ pci_free_consistent(adapter->pcidev,
+ sizeof(struct slic_shmem *),
+ adapter->pshmem, adapter->phys_shmem);
+ adapter->pshmem = NULL;
+ adapter->phys_shmem = (dma_addr_t) NULL;
+ }
+#if SLIC_GET_STATS_TIMER_ENABLED
+ if (adapter->statstimerset) {
+ DBG_MSG("statstimer ");
+ adapter->statstimerset = 0;
+ del_timer(&adapter->statstimer);
+ }
+#endif
+#if !SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED
+/*#if SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED*/
+ if (adapter->pingtimerset) {
+ DBG_MSG("pingtimer ");
+ adapter->pingtimerset = 0;
+ del_timer(&adapter->pingtimer);
+ }
+#endif
+ slic_rspqueue_free(adapter);
+ slic_cmdq_free(adapter);
+ slic_rcvqueue_free(adapter);
+
+ DBG_MSG("\n");
+}
+
+#if SLIC_GET_STATS_ENABLED
+static struct net_device_stats *slic_get_stats(struct net_device *dev)
+{
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct net_device_stats *stats;
+
+ ASSERT(adapter);
+ stats = &adapter->stats;
+ stats->collisions = adapter->slic_stats.iface.xmit_collisions;
+ stats->rx_errors = adapter->slic_stats.iface.rcv_errors;
+ stats->tx_errors = adapter->slic_stats.iface.xmt_errors;
+ stats->rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
+ stats->tx_heartbeat_errors = 0;
+ stats->tx_aborted_errors = 0;
+ stats->tx_window_errors = 0;
+ stats->tx_fifo_errors = 0;
+ stats->rx_frame_errors = 0;
+ stats->rx_length_errors = 0;
+ return &adapter->stats;
+}
+#endif
+
+/*
+ * Allocate a mcast_address structure to hold the multicast address.
+ * Link it in.
+ */
+static int slic_mcast_add_list(struct adapter *adapter, char *address)
+{
+ struct mcast_address *mcaddr, *mlist;
+ bool equaladdr;
+
+ /* Check to see if it already exists */
+ mlist = adapter->mcastaddrs;
+ while (mlist) {
+ ETHER_EQ_ADDR(mlist->address, address, equaladdr);
+ if (equaladdr)
+ return STATUS_SUCCESS;
+ mlist = mlist->next;
+ }
+
+ /* Doesn't already exist. Allocate a structure to hold it */
+ mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC);
+ if (mcaddr == NULL)
+ return 1;
+
+ memcpy(mcaddr->address, address, 6);
+
+ mcaddr->next = adapter->mcastaddrs;
+ adapter->mcastaddrs = mcaddr;
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Functions to obtain the CRC corresponding to the destination mac address.
+ * This is a standard ethernet CRC in that it is a 32-bit, reflected CRC using
+ * the polynomial:
+ * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 +
+ * x^4 + x^2 + x^1.
+ *
+ * After the CRC for the 6 bytes is generated (but before the value is
+ * complemented),
+ * we must then transpose the value and return bits 30-23.
+ *
+ */
+static u32 slic_crc_table[256]; /* Table of CRCs for all possible byte values */
+static u32 slic_crc_init; /* Is table initialized */
+
+/*
+ * Contruct the CRC32 table
+ */
+static void slic_mcast_init_crc32(void)
+{
+ u32 c; /* CRC shit reg */
+ u32 e = 0; /* Poly X-or pattern */
+ int i; /* counter */
+ int k; /* byte being shifted into crc */
+
+ static int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 };
+
+ for (i = 0; i < sizeof(p) / sizeof(int); i++)
+ e |= 1L << (31 - p[i]);
+
+ for (i = 1; i < 256; i++) {
+ c = i;
+ for (k = 8; k; k--)
+ c = c & 1 ? (c >> 1) ^ e : c >> 1;
+ slic_crc_table[i] = c;
+ }
+}
+
+/*
+ * Return the MAC hast as described above.
+ */
+static unsigned char slic_mcast_get_mac_hash(char *macaddr)
+{
+ u32 crc;
+ char *p;
+ int i;
+ unsigned char machash = 0;
+
+ if (!slic_crc_init) {
+ slic_mcast_init_crc32();
+ slic_crc_init = 1;
+ }
+
+ crc = 0xFFFFFFFF; /* Preload shift register, per crc-32 spec */
+ for (i = 0, p = macaddr; i < 6; ++p, ++i)
+ crc = (crc >> 8) ^ slic_crc_table[(crc ^ *p) & 0xFF];
+
+ /* Return bits 1-8, transposed */
+ for (i = 1; i < 9; i++)
+ machash |= (((crc >> i) & 1) << (8 - i));
+
+ return machash;
+}
+
+static void slic_mcast_set_bit(struct adapter *adapter, char *address)
+{
+ unsigned char crcpoly;
+
+ /* Get the CRC polynomial for the mac address */
+ crcpoly = slic_mcast_get_mac_hash(address);
+
+ /* We only have space on the SLIC for 64 entries. Lop
+ * off the top two bits. (2^6 = 64)
+ */
+ crcpoly &= 0x3F;
+
+ /* OR in the new bit into our 64 bit mask. */
+ adapter->mcastmask |= (u64) 1 << crcpoly;
+}
+
+static void slic_mcast_set_list(struct net_device *dev)
+{
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ int status = STATUS_SUCCESS;
+ int i;
+ char *addresses;
+ struct dev_mc_list *mc_list = dev->mc_list;
+ int mc_count = dev->mc_count;
+
+ ASSERT(adapter);
+
+ for (i = 1; i <= mc_count; i++) {
+ addresses = (char *) &mc_list->dmi_addr;
+ if (mc_list->dmi_addrlen == 6) {
+ status = slic_mcast_add_list(adapter, addresses);
+ if (status != STATUS_SUCCESS)
+ break;
+ } else {
+ status = -EINVAL;
+ break;
+ }
+ slic_mcast_set_bit(adapter, addresses);
+ mc_list = mc_list->next;
+ }
+
+ DBG_MSG("%s a->devflags_prev[%x] dev->flags[%x] status[%x]\n",
+ __func__, adapter->devflags_prev, dev->flags, status);
+ if (adapter->devflags_prev != dev->flags) {
+ adapter->macopts = MAC_DIRECTED;
+ if (dev->flags) {
+ if (dev->flags & IFF_BROADCAST)
+ adapter->macopts |= MAC_BCAST;
+ if (dev->flags & IFF_PROMISC)
+ adapter->macopts |= MAC_PROMISC;
+ if (dev->flags & IFF_ALLMULTI)
+ adapter->macopts |= MAC_ALLMCAST;
+ if (dev->flags & IFF_MULTICAST)
+ adapter->macopts |= MAC_MCAST;
+ }
+ adapter->devflags_prev = dev->flags;
+ DBG_MSG("%s call slic_config_set adapter->macopts[%x]\n",
+ __func__, adapter->macopts);
+ slic_config_set(adapter, TRUE);
+ } else {
+ if (status == STATUS_SUCCESS)
+ slic_mcast_set_mask(adapter);
+ }
+ return;
+}
+
+static void slic_mcast_set_mask(struct adapter *adapter)
+{
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ DBG_MSG("%s ENTER (%s) macopts[%x] mask[%llx]\n", __func__,
+ adapter->netdev->name, (uint) adapter->macopts,
+ adapter->mcastmask);
+
+ if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) {
+ /* Turn on all multicast addresses. We have to do this for
+ * promiscuous mode as well as ALLMCAST mode. It saves the
+ * Microcode from having to keep state about the MAC
+ * configuration.
+ */
+/* DBG_MSG("slicoss: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n\
+ SLUT MODE!!!\n",__func__); */
+ WRITE_REG(slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH);
+ WRITE_REG(slic_regs->slic_mcasthigh, 0xFFFFFFFF, FLUSH);
+/* DBG_MSG("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n",
+ _func__, adapter->netdev->name); */
+ } else {
+ /* Commit our multicast mast to the SLIC by writing to the
+ * multicast address mask registers
+ */
+ DBG_MSG("%s (%s) WRITE mcastlow[%x] mcasthigh[%x]\n",
+ __func__, adapter->netdev->name,
+ ((ulong) (adapter->mcastmask & 0xFFFFFFFF)),
+ ((ulong) ((adapter->mcastmask >> 32) & 0xFFFFFFFF)));
+
+ WRITE_REG(slic_regs->slic_mcastlow,
+ (u32) (adapter->mcastmask & 0xFFFFFFFF), FLUSH);
+ WRITE_REG(slic_regs->slic_mcasthigh,
+ (u32) ((adapter->mcastmask >> 32) & 0xFFFFFFFF),
+ FLUSH);
+ }
+}
+
+static void slic_timer_ping(ulong dev)
+{
+ struct adapter *adapter;
+ struct sliccard *card;
+
+ ASSERT(dev);
+ adapter = (struct adapter *)((struct net_device *) dev)->priv;
+ ASSERT(adapter);
+ card = adapter->card;
+ ASSERT(card);
+#if !SLIC_DUMP_ENABLED
+/*#if SLIC_DUMP_ENABLED*/
+ if ((adapter->state == ADAPT_UP) && (card->state == CARD_UP)) {
+ int status;
+
+ if (card->pingstatus != ISR_PINGMASK) {
+ if (errormsg++ < 5) {
+ DBG_MSG
+ ("%s (%s) CARD HAS CRASHED PING_status == \
+ %x ERRORMSG# %d\n",
+ __func__, adapter->netdev->name,
+ card->pingstatus, errormsg);
+ }
+ /* ASSERT(card->pingstatus == ISR_PINGMASK); */
+ } else {
+ if (goodmsg++ < 5) {
+ DBG_MSG
+ ("slicoss: %s (%s) PING_status == %x \
+ GOOD!!!!!!!! msg# %d\n",
+ __func__, adapter->netdev->name,
+ card->pingstatus, errormsg);
+ }
+ }
+ card->pingstatus = 0;
+ status = slic_upr_request(adapter, SLIC_UPR_PING, 0, 0, 0, 0);
+
+ ASSERT(status == 0);
+ } else {
+ DBG_MSG("slicoss %s (%s) adapter[%p] NOT UP!!!!\n",
+ __func__, adapter->netdev->name, adapter);
+ }
+#endif
+ adapter->pingtimer.expires =
+ jiffies + SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL);
+ add_timer(&adapter->pingtimer);
+}
+
+static void slic_if_stop_queue(struct adapter *adapter)
+{
+ netif_stop_queue(adapter->netdev);
+}
+
+static void slic_if_start_queue(struct adapter *adapter)
+{
+ netif_start_queue(adapter->netdev);
+}
+
+/*
+ * slic_if_init
+ *
+ * Perform initialization of our slic interface.
+ *
+ */
+static int slic_if_init(struct adapter *adapter)
+{
+ struct sliccard *card = adapter->card;
+ struct net_device *dev = adapter->netdev;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ struct slic_shmem *pshmem;
+ int status = 0;
+
+ ASSERT(card);
+ DBG_MSG("slicoss: %s (%s) ENTER states[%d:%d:%d:%d] flags[%x]\n",
+ __func__, adapter->netdev->name,
+ adapter->queues_initialized, adapter->state, adapter->linkstate,
+ card->state, dev->flags);
+
+ /* adapter should be down at this point */
+ if (adapter->state != ADAPT_DOWN) {
+ DBG_ERROR("slic_if_init adapter->state != ADAPT_DOWN\n");
+ return -EIO;
+ }
+ ASSERT(adapter->linkstate == LINK_DOWN);
+
+ adapter->devflags_prev = dev->flags;
+ adapter->macopts = MAC_DIRECTED;
+ if (dev->flags) {
+ DBG_MSG("slicoss: %s (%s) Set MAC options: ", __func__,
+ adapter->netdev->name);
+ if (dev->flags & IFF_BROADCAST) {
+ adapter->macopts |= MAC_BCAST;
+ DBG_MSG("BCAST ");
+ }
+ if (dev->flags & IFF_PROMISC) {
+ adapter->macopts |= MAC_PROMISC;
+ DBG_MSG("PROMISC ");
+ }
+ if (dev->flags & IFF_ALLMULTI) {
+ adapter->macopts |= MAC_ALLMCAST;
+ DBG_MSG("ALL_MCAST ");
+ }
+ if (dev->flags & IFF_MULTICAST) {
+ adapter->macopts |= MAC_MCAST;
+ DBG_MSG("MCAST ");
+ }
+ DBG_MSG("\n");
+ }
+ status = slic_adapter_allocresources(adapter);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR
+ ("slic_if_init: slic_adapter_allocresources FAILED %x\n",
+ status);
+ slic_adapter_freeresources(adapter);
+ return status;
+ }
+
+ if (!adapter->queues_initialized) {
+ DBG_MSG("slicoss: %s call slic_rspqueue_init\n", __func__);
+ if (slic_rspqueue_init(adapter))
+ return -ENOMEM;
+ DBG_MSG
+ ("slicoss: %s call slic_cmdq_init adapter[%p] port %d \n",
+ __func__, adapter, adapter->port);
+ if (slic_cmdq_init(adapter))
+ return -ENOMEM;
+ DBG_MSG
+ ("slicoss: %s call slic_rcvqueue_init adapter[%p] \
+ port %d \n", __func__, adapter, adapter->port);
+ if (slic_rcvqueue_init(adapter))
+ return -ENOMEM;
+ adapter->queues_initialized = 1;
+ }
+ DBG_MSG("slicoss: %s disable interrupts(slic)\n", __func__);
+
+ WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
+ mdelay(1);
+
+ if (!adapter->isp_initialized) {
+ pshmem = (struct slic_shmem *)adapter->phys_shmem;
+
+ spin_lock_irqsave(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+
+#if defined(CONFIG_X86_64)
+ WRITE_REG(slic_regs->slic_addr_upper,
+ SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH);
+ WRITE_REG(slic_regs->slic_isp,
+ SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH);
+#elif defined(CONFIG_X86)
+ WRITE_REG(slic_regs->slic_addr_upper, (u32) 0, DONT_FLUSH);
+ WRITE_REG(slic_regs->slic_isp, (u32) &pshmem->isr, FLUSH);
+#else
+ Stop Compilations
+#endif
+ spin_unlock_irqrestore(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+ adapter->isp_initialized = 1;
+ }
+
+ adapter->state = ADAPT_UP;
+ if (!card->loadtimerset) {
+ init_timer(&card->loadtimer);
+ card->loadtimer.expires =
+ jiffies + SLIC_SECS_TO_JIFFS(SLIC_LOADTIMER_PERIOD);
+ card->loadtimer.data = (ulong) card;
+ card->loadtimer.function = &slic_timer_load_check;
+ add_timer(&card->loadtimer);
+
+ card->loadtimerset = 1;
+ }
+#if SLIC_GET_STATS_TIMER_ENABLED
+ if (!adapter->statstimerset) {
+ DBG_MSG("slicoss: %s start getstats_timer(slic)\n",
+ __func__);
+ init_timer(&adapter->statstimer);
+ adapter->statstimer.expires =
+ jiffies + SLIC_SECS_TO_JIFFS(STATS_TIMER_INTERVAL);
+ adapter->statstimer.data = (ulong) adapter->netdev;
+ adapter->statstimer.function = &slic_timer_get_stats;
+ add_timer(&adapter->statstimer);
+ adapter->statstimerset = 1;
+ }
+#endif
+#if !SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED
+/*#if SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED*/
+ if (!adapter->pingtimerset) {
+ DBG_MSG("slicoss: %s start card_ping_timer(slic)\n",
+ __func__);
+ init_timer(&adapter->pingtimer);
+ adapter->pingtimer.expires =
+ jiffies + SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL);
+ adapter->pingtimer.data = (ulong) dev;
+ adapter->pingtimer.function = &slic_timer_ping;
+ add_timer(&adapter->pingtimer);
+ adapter->pingtimerset = 1;
+ adapter->card->pingstatus = ISR_PINGMASK;
+ }
+#endif
+
+ /*
+ * clear any pending events, then enable interrupts
+ */
+ DBG_MSG("slicoss: %s ENABLE interrupts(slic)\n", __func__);
+ adapter->isrcopy = 0;
+ adapter->pshmem->isr = 0;
+ WRITE_REG(slic_regs->slic_isr, 0, FLUSH);
+ WRITE_REG(slic_regs->slic_icr, ICR_INT_ON, FLUSH);
+
+ DBG_MSG("slicoss: %s call slic_link_config(slic)\n", __func__);
+ slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD);
+ slic_link_event_handler(adapter);
+
+ DBG_MSG("slicoss: %s EXIT\n", __func__);
+ return STATUS_SUCCESS;
+}
+
+static void slic_unmap_mmio_space(struct adapter *adapter)
+{
+#if LINUX_FREES_ADAPTER_RESOURCES
+ if (adapter->slic_regs)
+ iounmap(adapter->slic_regs);
+ adapter->slic_regs = NULL;
+#endif
+}
+
+static int slic_adapter_allocresources(struct adapter *adapter)
+{
+ if (!adapter->intrregistered) {
+ int retval;
+
+ DBG_MSG
+ ("slicoss: %s AllocAdaptRsrcs adapter[%p] shmem[%p] \
+ phys_shmem[%p] dev->irq[%x] %x\n",
+ __func__, adapter, adapter->pshmem,
+ (void *)adapter->phys_shmem, adapter->netdev->irq,
+ NR_IRQS);
+
+ spin_unlock_irqrestore(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+
+ retval = request_irq(adapter->netdev->irq,
+ &slic_interrupt,
+ IRQF_SHARED,
+ adapter->netdev->name, adapter->netdev);
+
+ spin_lock_irqsave(&slic_global.driver_lock.lock,
+ slic_global.driver_lock.flags);
+
+ if (retval) {
+ DBG_ERROR("slicoss: request_irq (%s) FAILED [%x]\n",
+ adapter->netdev->name, retval);
+ return retval;
+ }
+ adapter->intrregistered = 1;
+ DBG_MSG
+ ("slicoss: %s AllocAdaptRsrcs adapter[%p] shmem[%p] \
+ pshmem[%p] dev->irq[%x]\n",
+ __func__, adapter, adapter->pshmem,
+ (void *)adapter->pshmem, adapter->netdev->irq);
+ }
+ return STATUS_SUCCESS;
+}
+
+static void slic_config_pci(struct pci_dev *pcidev)
+{
+ u16 pci_command;
+ u16 new_command;
+
+ pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
+ DBG_MSG("slicoss: %s PCI command[%4.4x]\n", __func__, pci_command);
+
+ new_command = pci_command | PCI_COMMAND_MASTER
+ | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_INVALIDATE
+ | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK;
+ if (pci_command != new_command) {
+ DBG_MSG("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n",
+ __func__, pci_command, new_command);
+ pci_write_config_word(pcidev, PCI_COMMAND, new_command);
+ }
+}
+
+static void slic_adapter_freeresources(struct adapter *adapter)
+{
+ DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter);
+ slic_init_cleanup(adapter);
+ memset(&adapter->stats, 0, sizeof(struct net_device_stats));
+ adapter->error_interrupts = 0;
+ adapter->rcv_interrupts = 0;
+ adapter->xmit_interrupts = 0;
+ adapter->linkevent_interrupts = 0;
+ adapter->upr_interrupts = 0;
+ adapter->num_isrs = 0;
+ adapter->xmit_completes = 0;
+ adapter->rcv_broadcasts = 0;
+ adapter->rcv_multicasts = 0;
+ adapter->rcv_unicasts = 0;
+ DBG_MSG("slicoss: %s EXIT\n", __func__);
+}
+
+/*
+ * slic_link_config
+ *
+ * Write phy control to configure link duplex/speed
+ *
+ */
+static void slic_link_config(struct adapter *adapter,
+ u32 linkspeed, u32 linkduplex)
+{
+ u32 speed;
+ u32 duplex;
+ u32 phy_config;
+ u32 phy_advreg;
+ u32 phy_gctlreg;
+
+ if (adapter->state != ADAPT_UP) {
+ DBG_MSG
+ ("%s (%s) ADAPT Not up yet, Return! speed[%x] duplex[%x]\n",
+ __func__, adapter->netdev->name, linkspeed,
+ linkduplex);
+ return;
+ }
+ DBG_MSG("slicoss: %s (%s) slic_link_config: speed[%x] duplex[%x]\n",
+ __func__, adapter->netdev->name, linkspeed, linkduplex);
+
+ ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
+ || (adapter->devid == SLIC_2GB_DEVICE_ID));
+
+ if (linkspeed > LINK_1000MB)
+ linkspeed = LINK_AUTOSPEED;
+ if (linkduplex > LINK_AUTOD)
+ linkduplex = LINK_AUTOD;
+
+ if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) {
+ if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) {
+ /* We've got a fiber gigabit interface, and register
+ * 4 is different in fiber mode than in copper mode
+ */
+
+ /* advertise FD only @1000 Mb */
+ phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD));
+ /* enable PAUSE frames */
+ phy_advreg |= PAR_ASYMPAUSE_FIBER;
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_advreg,
+ FLUSH);
+
+ if (linkspeed == LINK_AUTOSPEED) {
+ /* reset phy, enable auto-neg */
+ phy_config =
+ (MIICR_REG_PCR |
+ (PCR_RESET | PCR_AUTONEG |
+ PCR_AUTONEG_RST));
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+ } else { /* forced 1000 Mb FD*/
+ /* power down phy to break link
+ this may not work) */
+ phy_config = (MIICR_REG_PCR | PCR_POWERDOWN);
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+ /* wait, Marvell says 1 sec,
+ try to get away with 10 ms */
+ mdelay(10);
+
+ /* disable auto-neg, set speed/duplex,
+ soft reset phy, powerup */
+ phy_config =
+ (MIICR_REG_PCR |
+ (PCR_RESET | PCR_SPEED_1000 |
+ PCR_DUPLEX_FULL));
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+ }
+ } else { /* copper gigabit */
+
+ /* Auto-Negotiate or 1000 Mb must be auto negotiated
+ * We've got a copper gigabit interface, and
+ * register 4 is different in copper mode than
+ * in fiber mode
+ */
+ if (linkspeed == LINK_AUTOSPEED) {
+ /* advertise 10/100 Mb modes */
+ phy_advreg =
+ (MIICR_REG_4 |
+ (PAR_ADV100FD | PAR_ADV100HD | PAR_ADV10FD
+ | PAR_ADV10HD));
+ } else {
+ /* linkspeed == LINK_1000MB -
+ don't advertise 10/100 Mb modes */
+ phy_advreg = MIICR_REG_4;
+ }
+ /* enable PAUSE frames */
+ phy_advreg |= PAR_ASYMPAUSE;
+ /* required by the Cicada PHY */
+ phy_advreg |= PAR_802_3;
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_advreg,
+ FLUSH);
+ /* advertise FD only @1000 Mb */
+ phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD));
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_gctlreg,
+ FLUSH);
+
+ if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
+ /* if a Marvell PHY
+ enable auto crossover */
+ phy_config =
+ (MIICR_REG_16 | (MRV_REG16_XOVERON));
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+
+ /* reset phy, enable auto-neg */
+ phy_config =
+ (MIICR_REG_PCR |
+ (PCR_RESET | PCR_AUTONEG |
+ PCR_AUTONEG_RST));
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+ } else { /* it's a Cicada PHY */
+ /* enable and restart auto-neg (don't reset) */
+ phy_config =
+ (MIICR_REG_PCR |
+ (PCR_AUTONEG | PCR_AUTONEG_RST));
+ WRITE_REG(adapter->slic_regs->slic_wphy,
+ phy_config, FLUSH);
+ }
+ }
+ } else {
+ /* Forced 10/100 */
+ if (linkspeed == LINK_10MB)
+ speed = 0;
+ else
+ speed = PCR_SPEED_100;
+ if (linkduplex == LINK_HALFD)
+ duplex = 0;
+ else
+ duplex = PCR_DUPLEX_FULL;
+
+ if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
+ /* if a Marvell PHY
+ disable auto crossover */
+ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF));
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_config,
+ FLUSH);
+ }
+
+ /* power down phy to break link (this may not work) */
+ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex));
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_config, FLUSH);
+
+ /* wait, Marvell says 1 sec, try to get away with 10 ms */
+ mdelay(10);
+
+ if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
+ /* if a Marvell PHY
+ disable auto-neg, set speed,
+ soft reset phy, powerup */
+ phy_config =
+ (MIICR_REG_PCR | (PCR_RESET | speed | duplex));
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_config,
+ FLUSH);
+ } else { /* it's a Cicada PHY */
+ /* disable auto-neg, set speed, powerup */
+ phy_config = (MIICR_REG_PCR | (speed | duplex));
+ WRITE_REG(adapter->slic_regs->slic_wphy, phy_config,
+ FLUSH);
+ }
+ }
+
+ DBG_MSG
+ ("slicoss: %s (%s) EXIT slic_link_config : state[%d] \
+ phy_config[%x]\n", __func__, adapter->netdev->name, adapter->state,
+ phy_config);
+}
+
+static void slic_card_cleanup(struct sliccard *card)
+{
+ DBG_MSG("slicoss: %s ENTER\n", __func__);
+
+#if SLIC_DUMP_ENABLED
+ if (card->dumpbuffer) {
+ card->dumpbuffer_phys = 0;
+ card->dumpbuffer_physl = 0;
+ card->dumpbuffer_physh = 0;
+ kfree(card->dumpbuffer);
+ card->dumpbuffer = NULL;
+ }
+ if (card->cmdbuffer) {
+ card->cmdbuffer_phys = 0;
+ card->cmdbuffer_physl = 0;
+ card->cmdbuffer_physh = 0;
+ kfree(card->cmdbuffer);
+ card->cmdbuffer = NULL;
+ }
+#endif
+
+ if (card->loadtimerset) {
+ card->loadtimerset = 0;
+ del_timer(&card->loadtimer);
+ }
+
+ slic_debug_card_destroy(card);
+
+ kfree(card);
+ DBG_MSG("slicoss: %s EXIT\n", __func__);
+}
+
+static int slic_card_download_gbrcv(struct adapter *adapter)
+{
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ u32 codeaddr;
+ unsigned char *instruction = NULL;
+ u32 rcvucodelen = 0;
+
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+ instruction = (unsigned char *)&OasisRcvUCode[0];
+ rcvucodelen = OasisRcvUCodeLen;
+ break;
+ case SLIC_1GB_DEVICE_ID:
+ instruction = (unsigned char *)&GBRcvUCode[0];
+ rcvucodelen = GBRcvUCodeLen;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ /* start download */
+ WRITE_REG(slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH);
+
+ /* download the rcv sequencer ucode */
+ for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) {
+ /* write out instruction address */
+ WRITE_REG(slic_regs->slic_rcv_wcs, codeaddr, FLUSH);
+
+ /* write out the instruction data low addr */
+ WRITE_REG(slic_regs->slic_rcv_wcs,
+ (u32) *(u32 *) instruction, FLUSH);
+ instruction += 4;
+
+ /* write out the instruction data high addr */
+ WRITE_REG(slic_regs->slic_rcv_wcs, (u32) *instruction,
+ FLUSH);
+ instruction += 1;
+ }
+
+ /* download finished */
+ WRITE_REG(slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH);
+
+ return 0;
+}
+
+static int slic_card_download(struct adapter *adapter)
+{
+ u32 section;
+ int thissectionsize;
+ int codeaddr;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ u32 *instruction = NULL;
+ u32 *lastinstruct = NULL;
+ u32 *startinstruct = NULL;
+ unsigned char *nextinstruct;
+ u32 baseaddress;
+ u32 failure;
+ u32 i;
+ u32 numsects = 0;
+ u32 sectsize[3];
+ u32 sectstart[3];
+
+/* DBG_MSG ("slicoss: %s (%s) adapter[%p] card[%p] devid[%x] \
+ jiffies[%lx] cpu %d\n", __func__, adapter->netdev->name, adapter,
+ adapter->card, adapter->devid,jiffies, smp_processor_id()); */
+
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+/* DBG_MSG ("slicoss: %s devid==SLIC_2GB_DEVICE_ID sections[%x]\n",
+ __func__, (uint) ONumSections); */
+ numsects = ONumSections;
+ for (i = 0; i < numsects; i++) {
+ sectsize[i] = OSectionSize[i];
+ sectstart[i] = OSectionStart[i];
+ }
+ break;
+ case SLIC_1GB_DEVICE_ID:
+/* DBG_MSG ("slicoss: %s devid==SLIC_1GB_DEVICE_ID sections[%x]\n",
+ __func__, (uint) MNumSections); */
+ numsects = MNumSections;
+ for (i = 0; i < numsects; i++) {
+ sectsize[i] = MSectionSize[i];
+ sectstart[i] = MSectionStart[i];
+ }
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ ASSERT(numsects <= 3);
+
+ for (section = 0; section < numsects; section++) {
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+ instruction = (u32 *) &OasisUCode[section][0];
+ baseaddress = sectstart[section];
+ thissectionsize = sectsize[section] >> 3;
+ lastinstruct =
+ (u32 *) &OasisUCode[section][sectsize[section] -
+ 8];
+ break;
+ case SLIC_1GB_DEVICE_ID:
+ instruction = (u32 *) &MojaveUCode[section][0];
+ baseaddress = sectstart[section];
+ thissectionsize = sectsize[section] >> 3;
+ lastinstruct =
+ (u32 *) &MojaveUCode[section][sectsize[section]
+ - 8];
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ baseaddress = sectstart[section];
+ thissectionsize = sectsize[section] >> 3;
+
+ for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
+ startinstruct = instruction;
+ nextinstruct = ((unsigned char *)instruction) + 8;
+ /* Write out instruction address */
+ WRITE_REG(slic_regs->slic_wcs, baseaddress + codeaddr,
+ FLUSH);
+ /* Write out instruction to low addr */
+ WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH);
+#ifdef CONFIG_X86_64
+ instruction = (u32 *)((unsigned char *)instruction + 4);
+#else
+ instruction++;
+#endif
+ /* Write out instruction to high addr */
+ WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH);
+#ifdef CONFIG_X86_64
+ instruction = (u32 *)((unsigned char *)instruction + 4);
+#else
+ instruction++;
+#endif
+ }
+ }
+
+ for (section = 0; section < numsects; section++) {
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+ instruction = (u32 *)&OasisUCode[section][0];
+ break;
+ case SLIC_1GB_DEVICE_ID:
+ instruction = (u32 *)&MojaveUCode[section][0];
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ baseaddress = sectstart[section];
+ if (baseaddress < 0x8000)
+ continue;
+ thissectionsize = sectsize[section] >> 3;
+
+/* DBG_MSG ("slicoss: COMPARE secton[%x] baseaddr[%x] sectnsize[%x]\n",
+ (uint)section,baseaddress,thissectionsize);*/
+
+ for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
+ /* Write out instruction address */
+ WRITE_REG(slic_regs->slic_wcs,
+ SLIC_WCS_COMPARE | (baseaddress + codeaddr),
+ FLUSH);
+ /* Write out instruction to low addr */
+ WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH);
+#ifdef CONFIG_X86_64
+ instruction = (u32 *)((unsigned char *)instruction + 4);
+#else
+ instruction++;
+#endif
+ /* Write out instruction to high addr */
+ WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH);
+#ifdef CONFIG_X86_64
+ instruction = (u32 *)((unsigned char *)instruction + 4);
+#else
+ instruction++;
+#endif
+ /* Check SRAM location zero. If it is non-zero. Abort.*/
+ failure = readl((u32 __iomem *)&slic_regs->slic_reset);
+ if (failure) {
+ DBG_MSG
+ ("slicoss: %s FAILURE EXIT codeaddr[%x] \
+ thissectionsize[%x] failure[%x]\n",
+ __func__, codeaddr, thissectionsize,
+ failure);
+
+ return -EIO;
+ }
+ }
+ }
+/* DBG_MSG ("slicoss: Compare done\n");*/
+
+ /* Everything OK, kick off the card */
+ mdelay(10);
+ WRITE_REG(slic_regs->slic_wcs, SLIC_WCS_START, FLUSH);
+
+ /* stall for 20 ms, long enough for ucode to init card
+ and reach mainloop */
+ mdelay(20);
+
+ DBG_MSG("slicoss: %s (%s) EXIT adapter[%p] card[%p]\n",
+ __func__, adapter->netdev->name, adapter, adapter->card);
+
+ return STATUS_SUCCESS;
+}
+
+static void slic_adapter_set_hwaddr(struct adapter *adapter)
+{
+ struct sliccard *card = adapter->card;
+
+/* DBG_MSG ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n",
+ __func__, card->config_set, adapter->port, adapter->physport,
+ adapter->functionnumber);
+
+ slic_dbg_macaddrs(adapter); */
+
+ if ((adapter->card) && (card->config_set)) {
+ memcpy(adapter->macaddr,
+ card->config.MacInfo[adapter->functionnumber].macaddrA,
+ sizeof(struct slic_config_mac));
+/* DBG_MSG ("%s AFTER copying from config.macinfo into currmacaddr\n",
+ __func__);
+ slic_dbg_macaddrs(adapter);*/
+ if (!(adapter->currmacaddr[0] || adapter->currmacaddr[1] ||
+ adapter->currmacaddr[2] || adapter->currmacaddr[3] ||
+ adapter->currmacaddr[4] || adapter->currmacaddr[5])) {
+ memcpy(adapter->currmacaddr, adapter->macaddr, 6);
+ }
+ if (adapter->netdev) {
+ memcpy(adapter->netdev->dev_addr, adapter->currmacaddr,
+ 6);
+ }
+ }
+/* DBG_MSG ("%s EXIT port %d\n", __func__, adapter->port);
+ slic_dbg_macaddrs(adapter); */
+}
+
+static void slic_intagg_set(struct adapter *adapter, u32 value)
+{
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ WRITE_REG(slic_regs->slic_intagg, value, FLUSH);
+ adapter->card->loadlevel_current = value;
+}
+
+static int slic_card_init(struct sliccard *card, struct adapter *adapter)
+{
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ struct slic_eeprom *peeprom;
+ struct oslic_eeprom *pOeeprom;
+ dma_addr_t phys_config;
+ u32 phys_configh;
+ u32 phys_configl;
+ u32 i = 0;
+ struct slic_shmem *pshmem;
+ int status;
+ uint macaddrs = card->card_size;
+ ushort eecodesize;
+ ushort dramsize;
+ ushort ee_chksum;
+ ushort calc_chksum;
+ struct slic_config_mac *pmac;
+ unsigned char fruformat;
+ unsigned char oemfruformat;
+ struct atk_fru *patkfru;
+ union oemfru *poemfru;
+
+ DBG_MSG
+ ("slicoss: %s ENTER card[%p] adapter[%p] card->state[%x] \
+ size[%d]\n", __func__, card, adapter, card->state, card->card_size);
+
+ /* Reset everything except PCI configuration space */
+ slic_soft_reset(adapter);
+
+ /* Download the microcode */
+ status = slic_card_download(adapter);
+
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("SLIC download failed bus %d slot %d\n",
+ (uint) adapter->busnumber,
+ (uint) adapter->slotnumber);
+ return status;
+ }
+
+ if (!card->config_set) {
+ peeprom = pci_alloc_consistent(adapter->pcidev,
+ sizeof(struct slic_eeprom),
+ &phys_config);
+
+ phys_configl = SLIC_GET_ADDR_LOW(phys_config);
+ phys_configh = SLIC_GET_ADDR_HIGH(phys_config);
+
+ DBG_MSG("slicoss: %s Eeprom info adapter [%p]\n "
+ "size [%x]\n peeprom [%p]\n "
+ "phys_config [%p]\n phys_configl[%x]\n "
+ "phys_configh[%x]\n",
+ __func__, adapter,
+ (u32)sizeof(struct slic_eeprom),
+ peeprom, (void *) phys_config, phys_configl,
+ phys_configh);
+ if (!peeprom) {
+ DBG_ERROR
+ ("SLIC eeprom read failed to get memory bus %d \
+ slot %d\n",
+ (uint) adapter->busnumber,
+ (uint) adapter->slotnumber);
+ return -ENOMEM;
+ } else {
+ memset(peeprom, 0, sizeof(struct slic_eeprom));
+ }
+ WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
+ mdelay(1);
+ pshmem = (struct slic_shmem *)adapter->phys_shmem;
+
+ spin_lock_irqsave(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+ WRITE_REG(slic_regs->slic_addr_upper, 0, DONT_FLUSH);
+ WRITE_REG(slic_regs->slic_isp,
+ SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH);
+ spin_unlock_irqrestore(&adapter->bit64reglock.lock,
+ adapter->bit64reglock.flags);
+
+ slic_config_get(adapter, phys_configl, phys_configh);
+
+ for (;;) {
+ if (adapter->pshmem->isr) {
+ DBG_MSG("%s shmem[%p] shmem->isr[%x]\n",
+ __func__, adapter->pshmem,
+ adapter->pshmem->isr);
+
+ if (adapter->pshmem->isr & ISR_UPC) {
+ adapter->pshmem->isr = 0;
+ WRITE_REG64(adapter,
+ slic_regs->slic_isp,
+ 0,
+ slic_regs->slic_addr_upper,
+ 0, FLUSH);
+ WRITE_REG(slic_regs->slic_isr, 0,
+ FLUSH);
+
+ slic_upr_request_complete(adapter, 0);
+ break;
+ } else {
+ adapter->pshmem->isr = 0;
+ WRITE_REG(slic_regs->slic_isr, 0,
+ FLUSH);
+ }
+ } else {
+ mdelay(1);
+ i++;
+ if (i > 5000) {
+ DBG_ERROR
+ ("SLIC: %d config data fetch timed\
+ out!\n", adapter->port);
+ DBG_MSG("%s shmem[%p] shmem->isr[%x]\n",
+ __func__, adapter->pshmem,
+ adapter->pshmem->isr);
+ WRITE_REG64(adapter,
+ slic_regs->slic_isp, 0,
+ slic_regs->slic_addr_upper,
+ 0, FLUSH);
+ return -EINVAL;
+ }
+ }
+ }
+
+ switch (adapter->devid) {
+ /* Oasis card */
+ case SLIC_2GB_DEVICE_ID:
+ /* extract EEPROM data and pointers to EEPROM data */
+ pOeeprom = (struct oslic_eeprom *) peeprom;
+ eecodesize = pOeeprom->EecodeSize;
+ dramsize = pOeeprom->DramSize;
+ pmac = pOeeprom->MacInfo;
+ fruformat = pOeeprom->FruFormat;
+ patkfru = &pOeeprom->AtkFru;
+ oemfruformat = pOeeprom->OemFruFormat;
+ poemfru = &pOeeprom->OemFru;
+ macaddrs = 2;
+ /* Minor kludge for Oasis card
+ get 2 MAC addresses from the
+ EEPROM to ensure that function 1
+ gets the Port 1 MAC address */
+ break;
+ default:
+ /* extract EEPROM data and pointers to EEPROM data */
+ eecodesize = peeprom->EecodeSize;
+ dramsize = peeprom->DramSize;
+ pmac = peeprom->u2.mac.MacInfo;
+ fruformat = peeprom->FruFormat;
+ patkfru = &peeprom->AtkFru;
+ oemfruformat = peeprom->OemFruFormat;
+ poemfru = &peeprom->OemFru;
+ break;
+ }
+
+ card->config.EepromValid = FALSE;
+
+ /* see if the EEPROM is valid by checking it's checksum */
+ if ((eecodesize <= MAX_EECODE_SIZE) &&
+ (eecodesize >= MIN_EECODE_SIZE)) {
+
+ ee_chksum =
+ *(u16 *) ((char *) peeprom + (eecodesize - 2));
+ /*
+ calculate the EEPROM checksum
+ */
+ calc_chksum =
+ ~slic_eeprom_cksum((char *) peeprom,
+ (eecodesize - 2));
+ /*
+ if the ucdoe chksum flag bit worked,
+ we wouldn't need this shit
+ */
+ if (ee_chksum == calc_chksum)
+ card->config.EepromValid = TRUE;
+ }
+ /* copy in the DRAM size */
+ card->config.DramSize = dramsize;
+
+ /* copy in the MAC address(es) */
+ for (i = 0; i < macaddrs; i++) {
+ memcpy(&card->config.MacInfo[i],
+ &pmac[i], sizeof(struct slic_config_mac));
+ }
+/* DBG_MSG ("%s EEPROM Checksum Good? %d MacAddress\n",__func__,
+ card->config.EepromValid); */
+
+ /* copy the Alacritech FRU information */
+ card->config.FruFormat = fruformat;
+ memcpy(&card->config.AtkFru, patkfru,
+ sizeof(struct atk_fru));
+
+ pci_free_consistent(adapter->pcidev,
+ sizeof(struct slic_eeprom),
+ peeprom, phys_config);
+ DBG_MSG
+ ("slicoss: %s adapter%d [%p] size[%x] FREE peeprom[%p] \
+ phys_config[%p]\n",
+ __func__, adapter->port, adapter,
+ (u32) sizeof(struct slic_eeprom), peeprom,
+ (void *) phys_config);
+
+ if ((!card->config.EepromValid) &&
+ (adapter->reg_params.fail_on_bad_eeprom)) {
+ WRITE_REG64(adapter,
+ slic_regs->slic_isp,
+ 0, slic_regs->slic_addr_upper, 0, FLUSH);
+ DBG_ERROR
+ ("unsupported CONFIGURATION EEPROM invalid\n");
+ return -EINVAL;
+ }
+
+ card->config_set = 1;
+ }
+
+ if (slic_card_download_gbrcv(adapter)) {
+ DBG_ERROR("%s unable to download GB receive microcode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (slic_global.dynamic_intagg) {
+ DBG_MSG
+ ("Dynamic Interrupt Aggregation[ENABLED]: slic%d \
+ SET intagg to %d\n",
+ card->cardnum, 0);
+ slic_intagg_set(adapter, 0);
+ } else {
+ slic_intagg_set(adapter, intagg_delay);
+ DBG_MSG
+ ("Dynamic Interrupt Aggregation[DISABLED]: slic%d \
+ SET intagg to %d\n",
+ card->cardnum, intagg_delay);
+ }
+
+ /*
+ * Initialize ping status to "ok"
+ */
+ card->pingstatus = ISR_PINGMASK;
+
+#if SLIC_DUMP_ENABLED
+ if (!card->dumpbuffer) {
+ card->dumpbuffer = kmalloc(DUMP_PAGE_SIZE, GFP_ATOMIC);
+
+ ASSERT(card->dumpbuffer);
+ if (card->dumpbuffer == NULL)
+ return -ENOMEM;
+ }
+ /*
+ * Smear the shared memory structure and then obtain
+ * the PHYSICAL address of this structure
+ */
+ memset(card->dumpbuffer, 0, DUMP_PAGE_SIZE);
+ card->dumpbuffer_phys = virt_to_bus(card->dumpbuffer);
+ card->dumpbuffer_physh = SLIC_GET_ADDR_HIGH(card->dumpbuffer_phys);
+ card->dumpbuffer_physl = SLIC_GET_ADDR_LOW(card->dumpbuffer_phys);
+
+ /*
+ * Allocate COMMAND BUFFER
+ */
+ if (!card->cmdbuffer) {
+ card->cmdbuffer = kmalloc(sizeof(struct dump_cmd), GFP_ATOMIC);
+
+ ASSERT(card->cmdbuffer);
+ if (card->cmdbuffer == NULL)
+ return -ENOMEM;
+ }
+ /*
+ * Smear the shared memory structure and then obtain
+ * the PHYSICAL address of this structure
+ */
+ memset(card->cmdbuffer, 0, sizeof(struct dump_cmd));
+ card->cmdbuffer_phys = virt_to_bus(card->cmdbuffer);
+ card->cmdbuffer_physh = SLIC_GET_ADDR_HIGH(card->cmdbuffer_phys);
+ card->cmdbuffer_physl = SLIC_GET_ADDR_LOW(card->cmdbuffer_phys);
+#endif
+
+ /*
+ * Lastly, mark our card state as up and return success
+ */
+ card->state = CARD_UP;
+ card->reset_in_progress = 0;
+ DBG_MSG("slicoss: %s EXIT card[%p] adapter[%p] card->state[%x]\n",
+ __func__, card, adapter, card->state);
+
+ return STATUS_SUCCESS;
+}
+
+static u32 slic_card_locate(struct adapter *adapter)
+{
+ struct sliccard *card = slic_global.slic_card;
+ struct physcard *physcard = slic_global.phys_card;
+ ushort card_hostid;
+ u16 __iomem *hostid_reg;
+ uint i;
+ uint rdhostid_offset = 0;
+
+ DBG_MSG("slicoss: %s adapter[%p] slot[%x] bus[%x] port[%x]\n",
+ __func__, adapter, adapter->slotnumber, adapter->busnumber,
+ adapter->port);
+
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+ rdhostid_offset = SLIC_RDHOSTID_2GB;
+ break;
+ case SLIC_1GB_DEVICE_ID:
+ rdhostid_offset = SLIC_RDHOSTID_1GB;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ hostid_reg =
+ (u16 __iomem *) (((u8 __iomem *) (adapter->slic_regs)) +
+ rdhostid_offset);
+ DBG_MSG("slicoss: %s *hostid_reg[%p] == ", __func__, hostid_reg);
+
+ /* read the 16 bit hostid from SRAM */
+ card_hostid = (ushort) readw(hostid_reg);
+ DBG_MSG(" card_hostid[%x]\n", card_hostid);
+
+ /* Initialize a new card structure if need be */
+ if (card_hostid == SLIC_HOSTID_DEFAULT) {
+ card = kzalloc(sizeof(struct sliccard), GFP_KERNEL);
+ if (card == NULL)
+ return -ENOMEM;
+
+ card->next = slic_global.slic_card;
+ slic_global.slic_card = card;
+#if DBG
+ if (adapter->devid == SLIC_2GB_DEVICE_ID) {
+ DBG_MSG
+ ("SLICOSS ==> Initialize 2 Port Gigabit Server \
+ and Storage Accelerator\n");
+ } else {
+ DBG_MSG
+ ("SLICOSS ==> Initialize 1 Port Gigabit Server \
+ and Storage Accelerator\n");
+ }
+#endif
+ card->busnumber = adapter->busnumber;
+ card->slotnumber = adapter->slotnumber;
+
+ /* Find an available cardnum */
+ for (i = 0; i < SLIC_MAX_CARDS; i++) {
+ if (slic_global.cardnuminuse[i] == 0) {
+ slic_global.cardnuminuse[i] = 1;
+ card->cardnum = i;
+ break;
+ }
+ }
+ slic_global.num_slic_cards++;
+ DBG_MSG("\nCARDNUM == %d Total %d Card[%p]\n\n",
+ card->cardnum, slic_global.num_slic_cards, card);
+
+ slic_debug_card_create(card);
+ } else {
+ DBG_MSG
+ ("slicoss: %s CARD already allocated, find the \
+ correct card\n", __func__);
+ /* Card exists, find the card this adapter belongs to */
+ while (card) {
+ DBG_MSG
+ ("slicoss: %s card[%p] slot[%x] bus[%x] \
+ adaptport[%p] hostid[%x] cardnum[%x]\n",
+ __func__, card, card->slotnumber,
+ card->busnumber, card->adapter[adapter->port],
+ card_hostid, card->cardnum);
+
+ if (card->cardnum == card_hostid)
+ break;
+ card = card->next;
+ }
+ }
+
+ ASSERT(card);
+ if (!card)
+ return STATUS_FAILURE;
+ /* Put the adapter in the card's adapter list */
+ ASSERT(card->adapter[adapter->port] == NULL);
+ if (!card->adapter[adapter->port]) {
+ card->adapter[adapter->port] = adapter;
+ adapter->card = card;
+ }
+
+ card->card_size = 1; /* one port per *logical* card */
+
+ while (physcard) {
+ for (i = 0; i < SLIC_MAX_PORTS; i++) {
+ if (!physcard->adapter[i])
+ continue;
+ else
+ break;
+ }
+ ASSERT(i != SLIC_MAX_PORTS);
+ if (physcard->adapter[i]->slotnumber == adapter->slotnumber)
+ break;
+ physcard = physcard->next;
+ }
+ if (!physcard) {
+ /* no structure allocated for this physical card yet */
+ physcard = kmalloc(sizeof(struct physcard *), GFP_ATOMIC);
+ ASSERT(physcard);
+ memset(physcard, 0, sizeof(struct physcard *));
+
+ DBG_MSG
+ ("\n%s Allocate a PHYSICALcard:\n PHYSICAL_Card[%p]\n\
+ LogicalCard [%p]\n adapter [%p]\n",
+ __func__, physcard, card, adapter);
+
+ physcard->next = slic_global.phys_card;
+ slic_global.phys_card = physcard;
+ physcard->adapters_allocd = 1;
+ } else {
+ physcard->adapters_allocd++;
+ }
+ /* Note - this is ZERO relative */
+ adapter->physport = physcard->adapters_allocd - 1;
+
+ ASSERT(physcard->adapter[adapter->physport] == NULL);
+ physcard->adapter[adapter->physport] = adapter;
+ adapter->physcard = physcard;
+ DBG_MSG(" PHYSICAL_Port %d Logical_Port %d\n", adapter->physport,
+ adapter->port);
+
+ return 0;
+}
+
+static void slic_soft_reset(struct adapter *adapter)
+{
+ if (adapter->card->state == CARD_UP) {
+ DBG_MSG("slicoss: %s QUIESCE adapter[%p] card[%p] devid[%x]\n",
+ __func__, adapter, adapter->card, adapter->devid);
+ WRITE_REG(adapter->slic_regs->slic_quiesce, 0, FLUSH);
+ mdelay(1);
+ }
+/* DBG_MSG ("slicoss: %s (%s) adapter[%p] card[%p] devid[%x]\n",
+ __func__, adapter->netdev->name, adapter, adapter->card,
+ adapter->devid); */
+
+ WRITE_REG(adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, FLUSH);
+ mdelay(1);
+}
+
+static void slic_config_set(struct adapter *adapter, bool linkchange)
+{
+ u32 value;
+ u32 RcrReset;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ DBG_MSG("slicoss: %s (%s) slic_interface_enable[%p](%d)\n",
+ __func__, adapter->netdev->name, adapter,
+ adapter->cardindex);
+
+ if (linkchange) {
+ /* Setup MAC */
+ slic_mac_config(adapter);
+ RcrReset = GRCR_RESET;
+ } else {
+ slic_mac_address_config(adapter);
+ RcrReset = 0;
+ }
+
+ if (adapter->linkduplex == LINK_FULLD) {
+ /* setup xmtcfg */
+ value = (GXCR_RESET | /* Always reset */
+ GXCR_XMTEN | /* Enable transmit */
+ GXCR_PAUSEEN); /* Enable pause */
+
+ DBG_MSG("slicoss: FDX adapt[%p] set xmtcfg to [%x]\n", adapter,
+ value);
+ WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH);
+
+ /* Setup rcvcfg last */
+ value = (RcrReset | /* Reset, if linkchange */
+ GRCR_CTLEN | /* Enable CTL frames */
+ GRCR_ADDRAEN | /* Address A enable */
+ GRCR_RCVBAD | /* Rcv bad frames */
+ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
+ } else {
+ /* setup xmtcfg */
+ value = (GXCR_RESET | /* Always reset */
+ GXCR_XMTEN); /* Enable transmit */
+
+ DBG_MSG("slicoss: HDX adapt[%p] set xmtcfg to [%x]\n", adapter,
+ value);
+ WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH);
+
+ /* Setup rcvcfg last */
+ value = (RcrReset | /* Reset, if linkchange */
+ GRCR_ADDRAEN | /* Address A enable */
+ GRCR_RCVBAD | /* Rcv bad frames */
+ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
+ }
+
+ if (adapter->state != ADAPT_DOWN) {
+ /* Only enable receive if we are restarting or running */
+ value |= GRCR_RCVEN;
+ }
+
+ if (adapter->macopts & MAC_PROMISC)
+ value |= GRCR_RCVALL;
+
+ DBG_MSG("slicoss: adapt[%p] set rcvcfg to [%x]\n", adapter, value);
+ WRITE_REG(slic_regs->slic_wrcfg, value, FLUSH);
+}
+
+/*
+ * Turn off RCV and XMT, power down PHY
+ */
+static void slic_config_clear(struct adapter *adapter)
+{
+ u32 value;
+ u32 phy_config;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ /* Setup xmtcfg */
+ value = (GXCR_RESET | /* Always reset */
+ GXCR_PAUSEEN); /* Enable pause */
+
+ WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH);
+
+ value = (GRCR_RESET | /* Always reset */
+ GRCR_CTLEN | /* Enable CTL frames */
+ GRCR_ADDRAEN | /* Address A enable */
+ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
+
+ WRITE_REG(slic_regs->slic_wrcfg, value, FLUSH);
+
+ /* power down phy */
+ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN));
+ WRITE_REG(slic_regs->slic_wphy, phy_config, FLUSH);
+}
+
+static void slic_config_get(struct adapter *adapter, u32 config,
+ u32 config_h)
+{
+ int status;
+
+ status = slic_upr_request(adapter,
+ SLIC_UPR_RCONFIG,
+ (u32) config, (u32) config_h, 0, 0);
+ ASSERT(status == 0);
+}
+
+static void slic_mac_address_config(struct adapter *adapter)
+{
+ u32 value;
+ u32 value2;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ value = *(u32 *) &adapter->currmacaddr[2];
+ value = ntohl(value);
+ WRITE_REG(slic_regs->slic_wraddral, value, FLUSH);
+ WRITE_REG(slic_regs->slic_wraddrbl, value, FLUSH);
+
+ value2 = (u32) ((adapter->currmacaddr[0] << 8 |
+ adapter->currmacaddr[1]) & 0xFFFF);
+
+ WRITE_REG(slic_regs->slic_wraddrah, value2, FLUSH);
+ WRITE_REG(slic_regs->slic_wraddrbh, value2, FLUSH);
+
+ DBG_MSG("%s value1[%x] value2[%x] Call slic_mcast_set_mask\n",
+ __func__, value, value2);
+ slic_dbg_macaddrs(adapter);
+
+ /* Write our multicast mask out to the card. This is done */
+ /* here in addition to the slic_mcast_addr_set routine */
+ /* because ALL_MCAST may have been enabled or disabled */
+ slic_mcast_set_mask(adapter);
+}
+
+static void slic_mac_config(struct adapter *adapter)
+{
+ u32 value;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+
+ /* Setup GMAC gaps */
+ if (adapter->linkspeed == LINK_1000MB) {
+ value = ((GMCR_GAPBB_1000 << GMCR_GAPBB_SHIFT) |
+ (GMCR_GAPR1_1000 << GMCR_GAPR1_SHIFT) |
+ (GMCR_GAPR2_1000 << GMCR_GAPR2_SHIFT));
+ } else {
+ value = ((GMCR_GAPBB_100 << GMCR_GAPBB_SHIFT) |
+ (GMCR_GAPR1_100 << GMCR_GAPR1_SHIFT) |
+ (GMCR_GAPR2_100 << GMCR_GAPR2_SHIFT));
+ }
+
+ /* enable GMII */
+ if (adapter->linkspeed == LINK_1000MB)
+ value |= GMCR_GBIT;
+
+ /* enable fullduplex */
+ if ((adapter->linkduplex == LINK_FULLD)
+ || (adapter->macopts & MAC_LOOPBACK)) {
+ value |= GMCR_FULLD;
+ }
+
+ /* write mac config */
+ WRITE_REG(slic_regs->slic_wmcfg, value, FLUSH);
+
+ /* setup mac addresses */
+ slic_mac_address_config(adapter);
+}
+
+static bool slic_mac_filter(struct adapter *adapter,
+ struct ether_header *ether_frame)
+{
+ u32 opts = adapter->macopts;
+ u32 *dhost4 = (u32 *)&ether_frame->ether_dhost[0];
+ u16 *dhost2 = (u16 *)&ether_frame->ether_dhost[4];
+ bool equaladdr;
+
+ if (opts & MAC_PROMISC) {
+ DBG_MSG("slicoss: %s (%s) PROMISCUOUS. Accept frame\n",
+ __func__, adapter->netdev->name);
+ return TRUE;
+ }
+
+ if ((*dhost4 == 0xFFFFFFFF) && (*dhost2 == 0xFFFF)) {
+ if (opts & MAC_BCAST) {
+ adapter->rcv_broadcasts++;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ if (ether_frame->ether_dhost[0] & 0x01) {
+ if (opts & MAC_ALLMCAST) {
+ adapter->rcv_multicasts++;
+ adapter->stats.multicast++;
+ return TRUE;
+ }
+ if (opts & MAC_MCAST) {
+ struct mcast_address *mcaddr = adapter->mcastaddrs;
+
+ while (mcaddr) {
+ ETHER_EQ_ADDR(mcaddr->address,
+ ether_frame->ether_dhost,
+ equaladdr);
+ if (equaladdr) {
+ adapter->rcv_multicasts++;
+ adapter->stats.multicast++;
+ return TRUE;
+ }
+ mcaddr = mcaddr->next;
+ }
+ return FALSE;
+ } else {
+ return FALSE;
+ }
+ }
+ if (opts & MAC_DIRECTED) {
+ adapter->rcv_unicasts++;
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+static int slic_mac_set_address(struct net_device *dev, void *ptr)
+{
+ struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct sockaddr *addr = ptr;
+
+ DBG_MSG("%s ENTER (%s)\n", __func__, adapter->netdev->name);
+
+ if (netif_running(dev))
+ return -EBUSY;
+ if (!adapter)
+ return -EBUSY;
+ DBG_MSG("slicoss: %s (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ __func__, adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
+ DBG_MSG("slicoss: %s (%s) new %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ __func__, adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+
+ slic_config_set(adapter, TRUE);
+ return 0;
+}
+
+/*
+ * slic_timer_get_stats
+ *
+ * Timer function used to suck the statistics out of the card every
+ * 50 seconds or whatever STATS_TIMER_INTERVAL is set to.
+ *
+ */
+#if SLIC_GET_STATS_TIMER_ENABLED
+static void slic_timer_get_stats(ulong dev)
+{
+ struct adapter *adapter;
+ struct sliccard *card;
+ struct slic_shmem *pshmem;
+
+ ASSERT(dev);
+ adapter = (struct adapter *)((struct net_device *)dev)->priv;
+ ASSERT(adapter);
+ card = adapter->card;
+ ASSERT(card);
+
+ if ((card->state == CARD_UP) &&
+ (adapter->state == ADAPT_UP) && (adapter->linkstate == LINK_UP)) {
+ pshmem = (struct slic_shmem *)adapter->phys_shmem;
+#ifdef CONFIG_X86_64
+ slic_upr_request(adapter,
+ SLIC_UPR_STATS,
+ SLIC_GET_ADDR_LOW(&pshmem->inicstats),
+ SLIC_GET_ADDR_HIGH(&pshmem->inicstats), 0, 0);
+#elif defined(CONFIG_X86)
+ slic_upr_request(adapter,
+ SLIC_UPR_STATS,
+ (u32) &pshmem->inicstats, 0, 0, 0);
+#else
+ Stop compilation;
+#endif
+ } else {
+/* DBG_MSG ("slicoss: %s adapter[%p] linkstate[%x] NOT UP!\n",
+ __func__, adapter, adapter->linkstate); */
+ }
+ adapter->statstimer.expires = jiffies +
+ SLIC_SECS_TO_JIFFS(STATS_TIMER_INTERVAL);
+ add_timer(&adapter->statstimer);
+}
+#endif
+static void slic_timer_load_check(ulong cardaddr)
+{
+ struct sliccard *card = (struct sliccard *)cardaddr;
+ struct adapter *adapter = card->master;
+ u32 load = card->events;
+ u32 level = 0;
+
+ if ((adapter) && (adapter->state == ADAPT_UP) &&
+ (card->state == CARD_UP) && (slic_global.dynamic_intagg)) {
+ if (adapter->devid == SLIC_1GB_DEVICE_ID) {
+ if (adapter->linkspeed == LINK_1000MB)
+ level = 100;
+ else {
+ if (load > SLIC_LOAD_5)
+ level = SLIC_INTAGG_5;
+ else if (load > SLIC_LOAD_4)
+ level = SLIC_INTAGG_4;
+ else if (load > SLIC_LOAD_3)
+ level = SLIC_INTAGG_3;
+ else if (load > SLIC_LOAD_2)
+ level = SLIC_INTAGG_2;
+ else if (load > SLIC_LOAD_1)
+ level = SLIC_INTAGG_1;
+ else
+ level = SLIC_INTAGG_0;
+ }
+ if (card->loadlevel_current != level) {
+ card->loadlevel_current = level;
+ WRITE_REG(adapter->slic_regs->slic_intagg,
+ level, FLUSH);
+ }
+ } else {
+ if (load > SLIC_LOAD_5)
+ level = SLIC_INTAGG_5;
+ else if (load > SLIC_LOAD_4)
+ level = SLIC_INTAGG_4;
+ else if (load > SLIC_LOAD_3)
+ level = SLIC_INTAGG_3;
+ else if (load > SLIC_LOAD_2)
+ level = SLIC_INTAGG_2;
+ else if (load > SLIC_LOAD_1)
+ level = SLIC_INTAGG_1;
+ else
+ level = SLIC_INTAGG_0;
+ if (card->loadlevel_current != level) {
+ card->loadlevel_current = level;
+ WRITE_REG(adapter->slic_regs->slic_intagg,
+ level, FLUSH);
+ }
+ }
+ }
+ card->events = 0;
+ card->loadtimer.expires =
+ jiffies + SLIC_SECS_TO_JIFFS(SLIC_LOADTIMER_PERIOD);
+ add_timer(&card->loadtimer);
+}
+
+static void slic_assert_fail(void)
+{
+ u32 cpuid;
+ u32 curr_pid;
+ cpuid = smp_processor_id();
+ curr_pid = current->pid;
+
+ DBG_ERROR("%s CPU # %d ---- PID # %d\n", __func__, cpuid, curr_pid);
+}
+
+static int slic_upr_queue_request(struct adapter *adapter,
+ u32 upr_request,
+ u32 upr_data,
+ u32 upr_data_h,
+ u32 upr_buffer, u32 upr_buffer_h)
+{
+ struct slic_upr *upr;
+ struct slic_upr *uprqueue;
+
+ upr = kmalloc(sizeof(struct slic_upr), GFP_ATOMIC);
+ if (!upr) {
+ DBG_MSG("%s COULD NOT ALLOCATE UPR MEM\n", __func__);
+
+ return -ENOMEM;
+ }
+ upr->adapter = adapter->port;
+ upr->upr_request = upr_request;
+ upr->upr_data = upr_data;
+ upr->upr_buffer = upr_buffer;
+ upr->upr_data_h = upr_data_h;
+ upr->upr_buffer_h = upr_buffer_h;
+ upr->next = NULL;
+ if (adapter->upr_list) {
+ uprqueue = adapter->upr_list;
+
+ while (uprqueue->next)
+ uprqueue = uprqueue->next;
+ uprqueue->next = upr;
+ } else {
+ adapter->upr_list = upr;
+ }
+ return STATUS_SUCCESS;
+}
+
+static int slic_upr_request(struct adapter *adapter,
+ u32 upr_request,
+ u32 upr_data,
+ u32 upr_data_h,
+ u32 upr_buffer, u32 upr_buffer_h)
+{
+ int status;
+
+ spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
+ status = slic_upr_queue_request(adapter,
+ upr_request,
+ upr_data,
+ upr_data_h, upr_buffer, upr_buffer_h);
+ if (status != STATUS_SUCCESS) {
+ spin_unlock_irqrestore(&adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+ return status;
+ }
+ slic_upr_start(adapter);
+ spin_unlock_irqrestore(&adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+ return STATUS_PENDING;
+}
+
+static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
+{
+ struct sliccard *card = adapter->card;
+ struct slic_upr *upr;
+
+/* if (card->dump_requested) {
+ DBG_MSG("ENTER slic_upr_request_complete Dump in progress ISR[%x]\n",
+ isr);
+ } */
+ spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
+ upr = adapter->upr_list;
+ if (!upr) {
+ ASSERT(0);
+ spin_unlock_irqrestore(&adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+ return;
+ }
+ adapter->upr_list = upr->next;
+ upr->next = NULL;
+ adapter->upr_busy = 0;
+ ASSERT(adapter->port == upr->adapter);
+ switch (upr->upr_request) {
+ case SLIC_UPR_STATS:
+ {
+#if SLIC_GET_STATS_ENABLED
+ struct slic_stats *slicstats =
+ (struct slic_stats *) &adapter->pshmem->inicstats;
+ struct slic_stats *newstats = slicstats;
+ struct slic_stats *old = &adapter->inicstats_prev;
+ struct slicnet_stats *stst = &adapter->slic_stats;
+#endif
+ if (isr & ISR_UPCERR) {
+ DBG_ERROR
+ ("SLIC_UPR_STATS command failed isr[%x]\n",
+ isr);
+
+ break;
+ }
+#if SLIC_GET_STATS_ENABLED
+/* DBG_MSG ("slicoss: %s rcv %lx:%lx:%lx:%lx:%lx %lx %lx "
+ "xmt %lx:%lx:%lx:%lx:%lx %lx %lx\n",
+ __func__,
+ slicstats->rcv_unicasts100,
+ slicstats->rcv_bytes100,
+ slicstats->rcv_bytes100,
+ slicstats->rcv_tcp_bytes100,
+ slicstats->rcv_tcp_segs100,
+ slicstats->rcv_other_error100,
+ slicstats->rcv_drops100,
+ slicstats->xmit_unicasts100,
+ slicstats->xmit_bytes100,
+ slicstats->xmit_bytes100,
+ slicstats->xmit_tcp_bytes100,
+ slicstats->xmit_tcp_segs100,
+ slicstats->xmit_other_error100,
+ slicstats->xmit_collisions100);*/
+ UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs,
+ newstats->xmit_tcp_segs_gb,
+ old->xmit_tcp_segs_gb);
+
+ UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes,
+ newstats->xmit_tcp_bytes_gb,
+ old->xmit_tcp_bytes_gb);
+
+ UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs,
+ newstats->rcv_tcp_segs_gb,
+ old->rcv_tcp_segs_gb);
+
+ UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes,
+ newstats->rcv_tcp_bytes_gb,
+ old->rcv_tcp_bytes_gb);
+
+ UPDATE_STATS_GB(stst->iface.xmt_bytes,
+ newstats->xmit_bytes_gb,
+ old->xmit_bytes_gb);
+
+ UPDATE_STATS_GB(stst->iface.xmt_ucast,
+ newstats->xmit_unicasts_gb,
+ old->xmit_unicasts_gb);
+
+ UPDATE_STATS_GB(stst->iface.rcv_bytes,
+ newstats->rcv_bytes_gb,
+ old->rcv_bytes_gb);
+
+ UPDATE_STATS_GB(stst->iface.rcv_ucast,
+ newstats->rcv_unicasts_gb,
+ old->rcv_unicasts_gb);
+
+ UPDATE_STATS_GB(stst->iface.xmt_errors,
+ newstats->xmit_collisions_gb,
+ old->xmit_collisions_gb);
+
+ UPDATE_STATS_GB(stst->iface.xmt_errors,
+ newstats->xmit_excess_collisions_gb,
+ old->xmit_excess_collisions_gb);
+
+ UPDATE_STATS_GB(stst->iface.xmt_errors,
+ newstats->xmit_other_error_gb,
+ old->xmit_other_error_gb);
+
+ UPDATE_STATS_GB(stst->iface.rcv_errors,
+ newstats->rcv_other_error_gb,
+ old->rcv_other_error_gb);
+
+ UPDATE_STATS_GB(stst->iface.rcv_discards,
+ newstats->rcv_drops_gb,
+ old->rcv_drops_gb);
+
+ if (newstats->rcv_drops_gb > old->rcv_drops_gb) {
+ adapter->rcv_drops +=
+ (newstats->rcv_drops_gb -
+ old->rcv_drops_gb);
+ }
+ memcpy(old, newstats, sizeof(struct slic_stats));
+#endif
+ break;
+ }
+ case SLIC_UPR_RLSR:
+ slic_link_upr_complete(adapter, isr);
+ break;
+ case SLIC_UPR_RCONFIG:
+ break;
+ case SLIC_UPR_RPHY:
+ ASSERT(0);
+ break;
+ case SLIC_UPR_ENLB:
+ ASSERT(0);
+ break;
+ case SLIC_UPR_ENCT:
+ ASSERT(0);
+ break;
+ case SLIC_UPR_PDWN:
+ ASSERT(0);
+ break;
+ case SLIC_UPR_PING:
+ card->pingstatus |= (isr & ISR_PINGDSMASK);
+ break;
+#if SLIC_DUMP_ENABLED
+ case SLIC_UPR_DUMP:
+ card->dumpstatus |= (isr & ISR_UPCMASK);
+ break;
+#endif
+ default:
+ ASSERT(0);
+ }
+ kfree(upr);
+ slic_upr_start(adapter);
+ spin_unlock_irqrestore(&adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+}
+
+static void slic_upr_start(struct adapter *adapter)
+{
+ struct slic_upr *upr;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+/*
+ char * ptr1;
+ char * ptr2;
+ uint cmdoffset;
+*/
+ upr = adapter->upr_list;
+ if (!upr)
+ return;
+ if (adapter->upr_busy)
+ return;
+ adapter->upr_busy = 1;
+
+ switch (upr->upr_request) {
+ case SLIC_UPR_STATS:
+ if (upr->upr_data_h == 0) {
+ WRITE_REG(slic_regs->slic_stats, upr->upr_data, FLUSH);
+ } else {
+ WRITE_REG64(adapter,
+ slic_regs->slic_stats64,
+ upr->upr_data,
+ slic_regs->slic_addr_upper,
+ upr->upr_data_h, FLUSH);
+ }
+ break;
+
+ case SLIC_UPR_RLSR:
+ WRITE_REG64(adapter,
+ slic_regs->slic_rlsr,
+ upr->upr_data,
+ slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH);
+ break;
+
+ case SLIC_UPR_RCONFIG:
+ DBG_MSG("%s SLIC_UPR_RCONFIG!!!!\n", __func__);
+ DBG_MSG("WRITE_REG64 adapter[%p]\n"
+ " a->slic_regs[%p] slic_regs[%p]\n"
+ " &slic_rconfig[%p] &slic_addr_upper[%p]\n"
+ " upr[%p]\n"
+ " uprdata[%x] uprdatah[%x]\n",
+ adapter, adapter->slic_regs, slic_regs,
+ &slic_regs->slic_rconfig, &slic_regs->slic_addr_upper,
+ upr, upr->upr_data, upr->upr_data_h);
+ WRITE_REG64(adapter,
+ slic_regs->slic_rconfig,
+ upr->upr_data,
+ slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH);
+ break;
+#if SLIC_DUMP_ENABLED
+ case SLIC_UPR_DUMP:
+#if 0
+ DBG_MSG("%s SLIC_UPR_DUMP!!!!\n", __func__);
+ DBG_MSG("WRITE_REG64 adapter[%p]\n"
+ " upr_buffer[%x] upr_bufferh[%x]\n"
+ " upr_data[%x] upr_datah[%x]\n"
+ " cmdbuff[%p] cmdbuffP[%p]\n"
+ " dumpbuff[%p] dumpbuffP[%p]\n",
+ adapter, upr->upr_buffer, upr->upr_buffer_h,
+ upr->upr_data, upr->upr_data_h,
+ adapter->card->cmdbuffer,
+ (void *)adapter->card->cmdbuffer_phys,
+ adapter->card->dumpbuffer, (
+ void *)adapter->card->dumpbuffer_phys);
+
+ ptr1 = (char *)slic_regs;
+ ptr2 = (char *)(&slic_regs->slic_dump_cmd);
+ cmdoffset = ptr2 - ptr1;
+ DBG_MSG("slic_dump_cmd register offset [%x]\n", cmdoffset);
+#endif
+ if (upr->upr_buffer || upr->upr_buffer_h) {
+ WRITE_REG64(adapter,
+ slic_regs->slic_dump_data,
+ upr->upr_buffer,
+ slic_regs->slic_addr_upper,
+ upr->upr_buffer_h, FLUSH);
+ }
+ WRITE_REG64(adapter,
+ slic_regs->slic_dump_cmd,
+ upr->upr_data,
+ slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH);
+ break;
+#endif
+ case SLIC_UPR_PING:
+ WRITE_REG(slic_regs->slic_ping, 1, FLUSH);
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
+{
+ u32 linkstatus = adapter->pshmem->linkstatus;
+ uint linkup;
+ unsigned char linkspeed;
+ unsigned char linkduplex;
+
+ DBG_MSG("%s: %s ISR[%x] linkstatus[%x]\n adapter[%p](%d)\n",
+ __func__, adapter->netdev->name, isr, linkstatus, adapter,
+ adapter->cardindex);
+
+ if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
+ struct slic_shmem *pshmem;
+
+ pshmem = (struct slic_shmem *)adapter->phys_shmem;
+#if defined(CONFIG_X86_64)
+ slic_upr_queue_request(adapter,
+ SLIC_UPR_RLSR,
+ SLIC_GET_ADDR_LOW(&pshmem->linkstatus),
+ SLIC_GET_ADDR_HIGH(&pshmem->linkstatus),
+ 0, 0);
+#elif defined(CONFIG_X86)
+ slic_upr_queue_request(adapter,
+ SLIC_UPR_RLSR,
+ (u32) &pshmem->linkstatus,
+ SLIC_GET_ADDR_HIGH(pshmem), 0, 0);
+#else
+ Stop Compilation;
+#endif
+ return;
+ }
+ if (adapter->state != ADAPT_UP)
+ return;
+
+ ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
+ || (adapter->devid == SLIC_2GB_DEVICE_ID));
+
+ linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN;
+ if (linkstatus & GIG_SPEED_1000) {
+ linkspeed = LINK_1000MB;
+ DBG_MSG("slicoss: %s (%s) GIGABIT Speed==1000MB ",
+ __func__, adapter->netdev->name);
+ } else if (linkstatus & GIG_SPEED_100) {
+ linkspeed = LINK_100MB;
+ DBG_MSG("slicoss: %s (%s) GIGABIT Speed==100MB ", __func__,
+ adapter->netdev->name);
+ } else {
+ linkspeed = LINK_10MB;
+ DBG_MSG("slicoss: %s (%s) GIGABIT Speed==10MB ", __func__,
+ adapter->netdev->name);
+ }
+ if (linkstatus & GIG_FULLDUPLEX) {
+ linkduplex = LINK_FULLD;
+ DBG_MSG(" Duplex == FULL\n");
+ } else {
+ linkduplex = LINK_HALFD;
+ DBG_MSG(" Duplex == HALF\n");
+ }
+
+ if ((adapter->linkstate == LINK_DOWN) && (linkup == LINK_DOWN)) {
+ DBG_MSG("slicoss: %s (%s) physport(%d) link still down\n",
+ __func__, adapter->netdev->name, adapter->physport);
+ return;
+ }
+
+ /* link up event, but nothing has changed */
+ if ((adapter->linkstate == LINK_UP) &&
+ (linkup == LINK_UP) &&
+ (adapter->linkspeed == linkspeed) &&
+ (adapter->linkduplex == linkduplex)) {
+ DBG_MSG("slicoss: %s (%s) port(%d) link still up\n",
+ __func__, adapter->netdev->name, adapter->physport);
+ return;
+ }
+
+ /* link has changed at this point */
+
+ /* link has gone from up to down */
+ if (linkup == LINK_DOWN) {
+ adapter->linkstate = LINK_DOWN;
+ DBG_MSG("slicoss: %s %d LinkDown!\n", __func__,
+ adapter->physport);
+ return;
+ }
+
+ /* link has gone from down to up */
+ adapter->linkspeed = linkspeed;
+ adapter->linkduplex = linkduplex;
+
+ if (adapter->linkstate != LINK_UP) {
+ /* setup the mac */
+ DBG_MSG("%s call slic_config_set\n", __func__);
+ slic_config_set(adapter, TRUE);
+ adapter->linkstate = LINK_UP;
+ DBG_MSG("\n(%s) Link UP: CALL slic_if_start_queue",
+ adapter->netdev->name);
+ slic_if_start_queue(adapter);
+ }
+#if 1
+ switch (linkspeed) {
+ case LINK_1000MB:
+ DBG_MSG
+ ("\n(%s) LINK UP!: GIGABIT SPEED == 1000MB duplex[%x]\n",
+ adapter->netdev->name, adapter->linkduplex);
+ break;
+ case LINK_100MB:
+ DBG_MSG("\n(%s) LINK UP!: SPEED == 100MB duplex[%x]\n",
+ adapter->netdev->name, adapter->linkduplex);
+ break;
+ default:
+ DBG_MSG("\n(%s) LINK UP!: SPEED == 10MB duplex[%x]\n",
+ adapter->netdev->name, adapter->linkduplex);
+ break;
+ }
+#endif
+}
+
+/*
+ * this is here to checksum the eeprom, there is some ucode bug
+ * which prevens us from using the ucode result.
+ * remove this once ucode is fixed.
+ */
+static ushort slic_eeprom_cksum(char *m, int len)
+{
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);\
+ }
+
+ u16 *w;
+ u32 sum = 0;
+ u32 byte_swapped = 0;
+ u32 w_int;
+
+ union {
+ char c[2];
+ ushort s;
+ } s_util;
+
+ union {
+ ushort s[2];
+ int l;
+ } l_util;
+
+ l_util.l = 0;
+ s_util.s = 0;
+
+ w = (u16 *)m;
+#ifdef CONFIG_X86_64
+ w_int = (u32) ((ulong) w & 0x00000000FFFFFFFF);
+#else
+ w_int = (u32) (w);
+#endif
+ if ((1 & w_int) && (len > 0)) {
+ REDUCE;
+ sum <<= 8;
+ s_util.c[0] = *(unsigned char *)w;
+ w = (u16 *)((char *)w + 1);
+ len--;
+ byte_swapped = 1;
+ }
+
+ /* Unroll the loop to make overhead from branches &c small. */
+ while ((len -= 32) >= 0) {
+ sum += w[0];
+ sum += w[1];
+ sum += w[2];
+ sum += w[3];
+ sum += w[4];
+ sum += w[5];
+ sum += w[6];
+ sum += w[7];
+ sum += w[8];
+ sum += w[9];
+ sum += w[10];
+ sum += w[11];
+ sum += w[12];
+ sum += w[13];
+ sum += w[14];
+ sum += w[15];
+ w = (u16 *)((ulong) w + 16); /* verify */
+ }
+ len += 32;
+ while ((len -= 8) >= 0) {
+ sum += w[0];
+ sum += w[1];
+ sum += w[2];
+ sum += w[3];
+ w = (u16 *)((ulong) w + 4); /* verify */
+ }
+ len += 8;
+ if (len != 0 || byte_swapped != 0) {
+ REDUCE;
+ while ((len -= 2) >= 0)
+ sum += *w++; /* verify */
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ byte_swapped = 0;
+ if (len == -1) {
+ s_util.c[1] = *(char *) w;
+ sum += s_util.s;
+ len = 0;
+ } else {
+ len = -1;
+ }
+
+ } else if (len == -1) {
+ s_util.c[0] = *(char *) w;
+ }
+
+ if (len == -1) {
+ s_util.c[1] = 0;
+ sum += s_util.s;
+ }
+ }
+ REDUCE;
+ return (ushort) sum;
+}
+
+static int slic_rspqueue_init(struct adapter *adapter)
+{
+ int i;
+ struct slic_rspqueue *rspq = &adapter->rspqueue;
+ __iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ u32 paddrh = 0;
+
+ DBG_MSG("slicoss: %s (%s) ENTER adapter[%p]\n", __func__,
+ adapter->netdev->name, adapter);
+ ASSERT(adapter->state == ADAPT_DOWN);
+ memset(rspq, 0, sizeof(struct slic_rspqueue));
+
+ rspq->num_pages = SLIC_RSPQ_PAGES_GB;
+
+ for (i = 0; i < rspq->num_pages; i++) {
+ rspq->vaddr[i] =
+ pci_alloc_consistent(adapter->pcidev, PAGE_SIZE,
+ &rspq->paddr[i]);
+ if (!rspq->vaddr[i]) {
+ DBG_ERROR
+ ("rspqueue_init_failed pci_alloc_consistent\n");
+ slic_rspqueue_free(adapter);
+ return STATUS_FAILURE;
+ }
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) rspq->vaddr[i] & 0xFFFFF000) ==
+ (u32) rspq->vaddr[i]);
+ ASSERT(((u32) rspq->paddr[i] & 0xFFFFF000) ==
+ (u32) rspq->paddr[i]);
+#endif
+ memset(rspq->vaddr[i], 0, PAGE_SIZE);
+/* DBG_MSG("slicoss: %s UPLOAD RSPBUFF Page pageix[%x] paddr[%p] "
+ "vaddr[%p]\n",
+ __func__, i, (void *)rspq->paddr[i], rspq->vaddr[i]); */
+
+ if (paddrh == 0) {
+ WRITE_REG(slic_regs->slic_rbar,
+ (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE),
+ DONT_FLUSH);
+ } else {
+ WRITE_REG64(adapter,
+ slic_regs->slic_rbar64,
+ (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE),
+ slic_regs->slic_addr_upper,
+ paddrh, DONT_FLUSH);
+ }
+ }
+ rspq->offset = 0;
+ rspq->pageindex = 0;
+ rspq->rspbuf = (struct slic_rspbuf *)rspq->vaddr[0];
+ DBG_MSG("slicoss: %s (%s) EXIT adapter[%p]\n", __func__,
+ adapter->netdev->name, adapter);
+ return STATUS_SUCCESS;
+}
+
+static int slic_rspqueue_reset(struct adapter *adapter)
+{
+ struct slic_rspqueue *rspq = &adapter->rspqueue;
+
+ DBG_MSG("slicoss: %s (%s) ENTER adapter[%p]\n", __func__,
+ adapter->netdev->name, adapter);
+ ASSERT(adapter->state == ADAPT_DOWN);
+ ASSERT(rspq);
+
+ DBG_MSG("slicoss: Nothing to do. rspq[%p]\n"
+ " offset[%x]\n"
+ " pageix[%x]\n"
+ " rspbuf[%p]\n",
+ rspq, rspq->offset, rspq->pageindex, rspq->rspbuf);
+
+ DBG_MSG("slicoss: %s (%s) EXIT adapter[%p]\n", __func__,
+ adapter->netdev->name, adapter);
+ return STATUS_SUCCESS;
+}
+
+static void slic_rspqueue_free(struct adapter *adapter)
+{
+ int i;
+ struct slic_rspqueue *rspq = &adapter->rspqueue;
+
+ DBG_MSG("slicoss: %s adapter[%p] port %d rspq[%p] FreeRSPQ\n",
+ __func__, adapter, adapter->physport, rspq);
+ for (i = 0; i < rspq->num_pages; i++) {
+ if (rspq->vaddr[i]) {
+ DBG_MSG
+ ("slicoss: pci_free_consistent rspq->vaddr[%p] \
+ paddr[%p]\n",
+ rspq->vaddr[i], (void *) rspq->paddr[i]);
+ pci_free_consistent(adapter->pcidev, PAGE_SIZE,
+ rspq->vaddr[i], rspq->paddr[i]);
+ }
+ rspq->vaddr[i] = NULL;
+ rspq->paddr[i] = 0;
+ }
+ rspq->offset = 0;
+ rspq->pageindex = 0;
+ rspq->rspbuf = NULL;
+}
+
+static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
+{
+ struct slic_rspqueue *rspq = &adapter->rspqueue;
+ struct slic_rspbuf *buf;
+
+ if (!(rspq->rspbuf->status))
+ return NULL;
+
+ buf = rspq->rspbuf;
+#ifndef CONFIG_X86_64
+ ASSERT((buf->status & 0xFFFFFFE0) == 0);
+#endif
+ ASSERT(buf->hosthandle);
+ if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) {
+ rspq->rspbuf++;
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) rspq->rspbuf & 0xFFFFFFE0) ==
+ (u32) rspq->rspbuf);
+#endif
+ } else {
+ ASSERT(rspq->offset == SLIC_RSPQ_BUFSINPAGE);
+ WRITE_REG64(adapter,
+ adapter->slic_regs->slic_rbar64,
+ (rspq->
+ paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE),
+ adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH);
+ rspq->pageindex = (++rspq->pageindex) % rspq->num_pages;
+ rspq->offset = 0;
+ rspq->rspbuf = (struct slic_rspbuf *)
+ rspq->vaddr[rspq->pageindex];
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) rspq->rspbuf & 0xFFFFF000) ==
+ (u32) rspq->rspbuf);
+#endif
+ }
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) buf & 0xFFFFFFE0) == (u32) buf);
+#endif
+ return buf;
+}
+
+static void slic_cmdqmem_init(struct adapter *adapter)
+{
+ struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
+
+ memset(cmdqmem, 0, sizeof(struct slic_cmdqmem));
+}
+
+static void slic_cmdqmem_free(struct adapter *adapter)
+{
+ struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
+ int i;
+
+ DBG_MSG("slicoss: (%s) adapter[%p] port %d rspq[%p] Free CMDQ Memory\n",
+ __func__, adapter, adapter->physport, cmdqmem);
+ for (i = 0; i < SLIC_CMDQ_MAXPAGES; i++) {
+ if (cmdqmem->pages[i]) {
+ DBG_MSG("slicoss: %s Deallocate page CmdQPage[%p]\n",
+ __func__, (void *) cmdqmem->pages[i]);
+ pci_free_consistent(adapter->pcidev,
+ PAGE_SIZE,
+ (void *) cmdqmem->pages[i],
+ cmdqmem->dma_pages[i]);
+ }
+ }
+ memset(cmdqmem, 0, sizeof(struct slic_cmdqmem));
+}
+
+static u32 *slic_cmdqmem_addpage(struct adapter *adapter)
+{
+ struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
+ u32 *pageaddr;
+
+ if (cmdqmem->pagecnt >= SLIC_CMDQ_MAXPAGES)
+ return NULL;
+ pageaddr = pci_alloc_consistent(adapter->pcidev,
+ PAGE_SIZE,
+ &cmdqmem->dma_pages[cmdqmem->pagecnt]);
+ if (!pageaddr)
+ return NULL;
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
+#endif
+ cmdqmem->pages[cmdqmem->pagecnt] = pageaddr;
+ cmdqmem->pagecnt++;
+ return pageaddr;
+}
+
+static int slic_cmdq_init(struct adapter *adapter)
+{
+ int i;
+ u32 *pageaddr;
+
+ DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter);
+ ASSERT(adapter->state == ADAPT_DOWN);
+ memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
+ memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
+ memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
+ spin_lock_init(&adapter->cmdq_all.lock.lock);
+ spin_lock_init(&adapter->cmdq_free.lock.lock);
+ spin_lock_init(&adapter->cmdq_done.lock.lock);
+ slic_cmdqmem_init(adapter);
+ adapter->slic_handle_ix = 1;
+ for (i = 0; i < SLIC_CMDQ_INITPAGES; i++) {
+ pageaddr = slic_cmdqmem_addpage(adapter);
+#ifndef CONFIG_X86_64
+ ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
+#endif
+ if (!pageaddr) {
+ slic_cmdq_free(adapter);
+ return STATUS_FAILURE;
+ }
+ slic_cmdq_addcmdpage(adapter, pageaddr);
+ }
+ adapter->slic_handle_ix = 1;
+ DBG_MSG("slicoss: %s reset slic_handle_ix to ONE\n", __func__);
+
+ return STATUS_SUCCESS;
+}
+
+static void slic_cmdq_free(struct adapter *adapter)
+{
+ struct slic_hostcmd *cmd;
+
+ DBG_MSG("slicoss: %s adapter[%p] port %d FreeCommandsFrom CMDQ\n",
+ __func__, adapter, adapter->physport);
+ cmd = adapter->cmdq_all.head;
+ while (cmd) {
+ if (cmd->busy) {
+ struct sk_buff *tempskb;
+
+ tempskb = cmd->skb;
+ if (tempskb) {
+ cmd->skb = NULL;
+ dev_kfree_skb_irq(tempskb);
+ }
+ }
+ cmd = cmd->next_all;
+ }
+ memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
+ memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
+ memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
+ slic_cmdqmem_free(adapter);
+}
+
+static void slic_cmdq_reset(struct adapter *adapter)
+{
+ struct slic_hostcmd *hcmd;
+ struct sk_buff *skb;
+ u32 outstanding;
+
+ DBG_MSG("%s ENTER adapter[%p]\n", __func__, adapter);
+ spin_lock_irqsave(&adapter->cmdq_free.lock.lock,
+ adapter->cmdq_free.lock.flags);
+ spin_lock_irqsave(&adapter->cmdq_done.lock.lock,
+ adapter->cmdq_done.lock.flags);
+ outstanding = adapter->cmdq_all.count - adapter->cmdq_done.count;
+ outstanding -= adapter->cmdq_free.count;
+ hcmd = adapter->cmdq_all.head;
+ while (hcmd) {
+ if (hcmd->busy) {
+ skb = hcmd->skb;
+ ASSERT(skb);
+ DBG_MSG("slicoss: %s hcmd[%p] skb[%p] ", __func__,
+ hcmd, skb);
+ hcmd->busy = 0;
+ hcmd->skb = NULL;
+ DBG_MSG(" Free SKB\n");
+ dev_kfree_skb_irq(skb);
+ }
+ hcmd = hcmd->next_all;
+ }
+ adapter->cmdq_free.count = 0;
+ adapter->cmdq_free.head = NULL;
+ adapter->cmdq_free.tail = NULL;
+ adapter->cmdq_done.count = 0;
+ adapter->cmdq_done.head = NULL;
+ adapter->cmdq_done.tail = NULL;
+ adapter->cmdq_free.head = adapter->cmdq_all.head;
+ hcmd = adapter->cmdq_all.head;
+ while (hcmd) {
+ adapter->cmdq_free.count++;
+ hcmd->next = hcmd->next_all;
+ hcmd = hcmd->next_all;
+ }
+ if (adapter->cmdq_free.count != adapter->cmdq_all.count) {
+ DBG_ERROR("%s free_count %d != all count %d\n", __func__,
+ adapter->cmdq_free.count, adapter->cmdq_all.count);
+ }
+ spin_unlock_irqrestore(&adapter->cmdq_done.lock.lock,
+ adapter->cmdq_done.lock.flags);
+ spin_unlock_irqrestore(&adapter->cmdq_free.lock.lock,
+ adapter->cmdq_free.lock.flags);
+ DBG_MSG("%s EXIT adapter[%p]\n", __func__, adapter);
+}
+
+static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page)
+{
+ struct slic_hostcmd *cmd;
+ struct slic_hostcmd *prev;
+ struct slic_hostcmd *tail;
+ struct slic_cmdqueue *cmdq;
+ int cmdcnt;
+ void *cmdaddr;
+ ulong phys_addr;
+ u32 phys_addrl;
+ u32 phys_addrh;
+ struct slic_handle *pslic_handle;
+
+ cmdaddr = page;
+ cmd = (struct slic_hostcmd *)cmdaddr;
+/* DBG_MSG("CMDQ Page addr[%p] ix[%d] pfree[%p]\n", cmdaddr, slic_handle_ix,
+ adapter->pfree_slic_handles); */
+ cmdcnt = 0;
+
+ phys_addr = virt_to_bus((void *)page);
+ phys_addrl = SLIC_GET_ADDR_LOW(phys_addr);
+ phys_addrh = SLIC_GET_ADDR_HIGH(phys_addr);
+
+ prev = NULL;
+ tail = cmd;
+ while ((cmdcnt < SLIC_CMDQ_CMDSINPAGE) &&
+ (adapter->slic_handle_ix < 256)) {
+ /* Allocate and initialize a SLIC_HANDLE for this command */
+ SLIC_GET_SLIC_HANDLE(adapter, pslic_handle);
+ if (pslic_handle == NULL)
+ ASSERT(0);
+ ASSERT(pslic_handle ==
+ &adapter->slic_handles[pslic_handle->token.
+ handle_index]);
+ pslic_handle->type = SLIC_HANDLE_CMD;
+ pslic_handle->address = (void *) cmd;
+ pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
+ pslic_handle->other_handle = NULL;
+ pslic_handle->next = NULL;
+
+ cmd->pslic_handle = pslic_handle;
+ cmd->cmd64.hosthandle = pslic_handle->token.handle_token;
+ cmd->busy = FALSE;
+ cmd->paddrl = phys_addrl;
+ cmd->paddrh = phys_addrh;
+ cmd->next_all = prev;
+ cmd->next = prev;
+ prev = cmd;
+ phys_addrl += SLIC_HOSTCMD_SIZE;
+ cmdaddr += SLIC_HOSTCMD_SIZE;
+
+ cmd = (struct slic_hostcmd *)cmdaddr;
+ cmdcnt++;
+ }
+
+ cmdq = &adapter->cmdq_all;
+ cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */
+ tail->next_all = cmdq->head;
+ ASSERT(VALID_ADDRESS(prev));
+ cmdq->head = prev;
+ cmdq = &adapter->cmdq_free;
+ spin_lock_irqsave(&cmdq->lock.lock, cmdq->lock.flags);
+ cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */
+ tail->next = cmdq->head;
+ ASSERT(VALID_ADDRESS(prev));
+ cmdq->head = prev;
+ spin_unlock_irqrestore(&cmdq->lock.lock, cmdq->lock.flags);
+}
+
+static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter)
+{
+ struct slic_cmdqueue *cmdq = &adapter->cmdq_free;
+ struct slic_hostcmd *cmd = NULL;
+
+lock_and_retry:
+ spin_lock_irqsave(&cmdq->lock.lock, cmdq->lock.flags);
+retry:
+ cmd = cmdq->head;
+ if (cmd) {
+ cmdq->head = cmd->next;
+ cmdq->count--;
+ spin_unlock_irqrestore(&cmdq->lock.lock, cmdq->lock.flags);
+ } else {
+ slic_cmdq_getdone(adapter);
+ cmd = cmdq->head;
+ if (cmd) {
+ goto retry;
+ } else {
+ u32 *pageaddr;
+
+ spin_unlock_irqrestore(&cmdq->lock.lock,
+ cmdq->lock.flags);
+ pageaddr = slic_cmdqmem_addpage(adapter);
+ if (pageaddr) {
+ slic_cmdq_addcmdpage(adapter, pageaddr);
+ goto lock_and_retry;
+ }
+ }
+ }
+ return cmd;
+}
+
+static void slic_cmdq_getdone(struct adapter *adapter)
+{
+ struct slic_cmdqueue *done_cmdq = &adapter->cmdq_done;
+ struct slic_cmdqueue *free_cmdq = &adapter->cmdq_free;
+
+ ASSERT(free_cmdq->head == NULL);
+ spin_lock_irqsave(&done_cmdq->lock.lock, done_cmdq->lock.flags);
+ ASSERT(VALID_ADDRESS(done_cmdq->head));
+
+ free_cmdq->head = done_cmdq->head;
+ free_cmdq->count = done_cmdq->count;
+ done_cmdq->head = NULL;
+ done_cmdq->tail = NULL;
+ done_cmdq->count = 0;
+ spin_unlock_irqrestore(&done_cmdq->lock.lock, done_cmdq->lock.flags);
+}
+
+static void slic_cmdq_putdone_irq(struct adapter *adapter,
+ struct slic_hostcmd *cmd)
+{
+ struct slic_cmdqueue *cmdq = &adapter->cmdq_done;
+
+ spin_lock(&cmdq->lock.lock);
+ cmd->busy = 0;
+ ASSERT(VALID_ADDRESS(cmdq->head));
+ cmd->next = cmdq->head;
+ ASSERT(VALID_ADDRESS(cmd));
+ cmdq->head = cmd;
+ cmdq->count++;
+ if ((adapter->xmitq_full) && (cmdq->count > 10))
+ netif_wake_queue(adapter->netdev);
+ spin_unlock(&cmdq->lock.lock);
+}
+
+static int slic_rcvqueue_init(struct adapter *adapter)
+{
+ int i, count;
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+
+ DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter);
+ ASSERT(adapter->state == ADAPT_DOWN);
+ rcvq->tail = NULL;
+ rcvq->head = NULL;
+ rcvq->size = SLIC_RCVQ_ENTRIES;
+ rcvq->errors = 0;
+ rcvq->count = 0;
+ i = (SLIC_RCVQ_ENTRIES / SLIC_RCVQ_FILLENTRIES);
+ count = 0;
+ while (i) {
+ count += slic_rcvqueue_fill(adapter);
+ i--;
+ }
+ if (rcvq->count < SLIC_RCVQ_MINENTRIES) {
+ slic_rcvqueue_free(adapter);
+ return STATUS_FAILURE;
+ }
+ DBG_MSG("slicoss: %s EXIT adapter[%p]\n", __func__, adapter);
+ return STATUS_SUCCESS;
+}
+
+static int slic_rcvqueue_reset(struct adapter *adapter)
+{
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+
+ DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter);
+ ASSERT(adapter->state == ADAPT_DOWN);
+ ASSERT(rcvq);
+
+ DBG_MSG("slicoss: Nothing to do. rcvq[%p]\n"
+ " count[%x]\n"
+ " head[%p]\n"
+ " tail[%p]\n",
+ rcvq, rcvq->count, rcvq->head, rcvq->tail);
+
+ DBG_MSG("slicoss: %s EXIT adapter[%p]\n", __func__, adapter);
+ return STATUS_SUCCESS;
+}
+
+static void slic_rcvqueue_free(struct adapter *adapter)
+{
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+ struct sk_buff *skb;
+
+ while (rcvq->head) {
+ skb = rcvq->head;
+ rcvq->head = rcvq->head->next;
+ dev_kfree_skb(skb);
+ }
+ rcvq->tail = NULL;
+ rcvq->head = NULL;
+ rcvq->count = 0;
+}
+
+static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter)
+{
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+ struct sk_buff *skb;
+ struct slic_rcvbuf *rcvbuf;
+ int count;
+
+ if (rcvq->count) {
+ skb = rcvq->head;
+ rcvbuf = (struct slic_rcvbuf *)skb->head;
+ ASSERT(rcvbuf);
+
+ if (rcvbuf->status & IRHDDR_SVALID) {
+ rcvq->head = rcvq->head->next;
+ skb->next = NULL;
+ rcvq->count--;
+ } else {
+ skb = NULL;
+ }
+ } else {
+ DBG_ERROR("RcvQ Empty!! adapter[%p] rcvq[%p] count[%x]\n",
+ adapter, rcvq, rcvq->count);
+ skb = NULL;
+ }
+ while (rcvq->count < SLIC_RCVQ_FILLTHRESH) {
+ count = slic_rcvqueue_fill(adapter);
+ if (!count)
+ break;
+ }
+ if (skb)
+ rcvq->errors = 0;
+ return skb;
+}
+
+static int slic_rcvqueue_fill(struct adapter *adapter)
+{
+ void *paddr;
+ u32 paddrl;
+ u32 paddrh;
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+ int i = 0;
+
+ while (i < SLIC_RCVQ_FILLENTRIES) {
+ struct slic_rcvbuf *rcvbuf;
+ struct sk_buff *skb;
+#ifdef KLUDGE_FOR_4GB_BOUNDARY
+retry_rcvqfill:
+#endif
+ skb = alloc_skb(SLIC_RCVQ_RCVBUFSIZE, GFP_ATOMIC);
+ if (skb) {
+ paddr = (void *)pci_map_single(adapter->pcidev,
+ skb->data,
+ SLIC_RCVQ_RCVBUFSIZE,
+ PCI_DMA_FROMDEVICE);
+ paddrl = SLIC_GET_ADDR_LOW(paddr);
+ paddrh = SLIC_GET_ADDR_HIGH(paddr);
+
+ skb->len = SLIC_RCVBUF_HEADSIZE;
+ rcvbuf = (struct slic_rcvbuf *)skb->head;
+ rcvbuf->status = 0;
+ skb->next = NULL;
+#ifdef KLUDGE_FOR_4GB_BOUNDARY
+ if (paddrl == 0) {
+ DBG_ERROR
+ ("%s: LOW 32bits PHYSICAL ADDRESS == 0 "
+ "skb[%p] PROBLEM\n"
+ " skbdata[%p]\n"
+ " skblen[%x]\n"
+ " paddr[%p]\n"
+ " paddrl[%x]\n"
+ " paddrh[%x]\n", __func__, skb,
+ skb->data, skb->len, paddr, paddrl,
+ paddrh);
+ DBG_ERROR(" rcvq->head[%p]\n"
+ " rcvq->tail[%p]\n"
+ " rcvq->count[%x]\n",
+ rcvq->head, rcvq->tail, rcvq->count);
+ DBG_ERROR("SKIP THIS SKB!!!!!!!!\n");
+ goto retry_rcvqfill;
+ }
+#else
+ if (paddrl == 0) {
+ DBG_ERROR
+ ("\n\n%s: LOW 32bits PHYSICAL ADDRESS == 0 "
+ "skb[%p] GIVE TO CARD ANYWAY\n"
+ " skbdata[%p]\n"
+ " paddr[%p]\n"
+ " paddrl[%x]\n"
+ " paddrh[%x]\n", __func__, skb,
+ skb->data, paddr, paddrl, paddrh);
+ }
+#endif
+ if (paddrh == 0) {
+ WRITE_REG(adapter->slic_regs->slic_hbar,
+ (u32) paddrl, DONT_FLUSH);
+ } else {
+ WRITE_REG64(adapter,
+ adapter->slic_regs->slic_hbar64,
+ (u32) paddrl,
+ adapter->slic_regs->slic_addr_upper,
+ (u32) paddrh, DONT_FLUSH);
+ }
+ if (rcvq->head)
+ rcvq->tail->next = skb;
+ else
+ rcvq->head = skb;
+ rcvq->tail = skb;
+ rcvq->count++;
+ i++;
+ } else {
+ DBG_ERROR
+ ("%s slic_rcvqueue_fill could only get [%d] "
+ "skbuffs\n",
+ adapter->netdev->name, i);
+ break;
+ }
+ }
+ return i;
+}
+
+static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb)
+{
+ struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
+ void *paddr;
+ u32 paddrl;
+ u32 paddrh;
+ struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head;
+
+ ASSERT(skb->len == SLIC_RCVBUF_HEADSIZE);
+
+ paddr = (void *)pci_map_single(adapter->pcidev, skb->head,
+ SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
+ rcvbuf->status = 0;
+ skb->next = NULL;
+
+ paddrl = SLIC_GET_ADDR_LOW(paddr);
+ paddrh = SLIC_GET_ADDR_HIGH(paddr);
+
+ if (paddrl == 0) {
+ DBG_ERROR
+ ("%s: LOW 32bits PHYSICAL ADDRESS == 0 skb[%p] PROBLEM\n"
+ " skbdata[%p]\n" " skblen[%x]\n"
+ " paddr[%p]\n" " paddrl[%x]\n"
+ " paddrh[%x]\n", __func__, skb, skb->data,
+ skb->len, paddr, paddrl, paddrh);
+ DBG_ERROR(" rcvq->head[%p]\n"
+ " rcvq->tail[%p]\n"
+ " rcvq->count[%x]\n", rcvq->head, rcvq->tail,
+ rcvq->count);
+ }
+ if (paddrh == 0) {
+ WRITE_REG(adapter->slic_regs->slic_hbar, (u32) paddrl,
+ DONT_FLUSH);
+ } else {
+ WRITE_REG64(adapter,
+ adapter->slic_regs->slic_hbar64,
+ paddrl,
+ adapter->slic_regs->slic_addr_upper,
+ paddrh, DONT_FLUSH);
+ }
+ if (rcvq->head)
+ rcvq->tail->next = skb;
+ else
+ rcvq->head = skb;
+ rcvq->tail = skb;
+ rcvq->count++;
+ return rcvq->count;
+}
+
+static int slic_debug_card_show(struct seq_file *seq, void *v)
+{
+#ifdef MOOKTODO
+ int i;
+ struct sliccard *card = seq->private;
+ struct slic_config *config = &card->config;
+ unsigned char *fru = (unsigned char *)(&card->config.atk_fru);
+ unsigned char *oemfru = (unsigned char *)(&card->config.OemFru);
+#endif
+
+ seq_printf(seq, "driver_version : %s", slic_proc_version);
+ seq_printf(seq, "Microcode versions: \n");
+ seq_printf(seq, " Gigabit (gb) : %s %s\n",
+ MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE);
+ seq_printf(seq, " Gigabit Receiver : %s %s\n",
+ GB_RCVUCODE_VERS_STRING, GB_RCVUCODE_VERS_DATE);
+ seq_printf(seq, "Vendor : %s\n", slic_vendor);
+ seq_printf(seq, "Product Name : %s\n", slic_product_name);
+#ifdef MOOKTODO
+ seq_printf(seq, "VendorId : %4.4X\n",
+ config->VendorId);
+ seq_printf(seq, "DeviceId : %4.4X\n",
+ config->DeviceId);
+ seq_printf(seq, "RevisionId : %2.2x\n",
+ config->RevisionId);
+ seq_printf(seq, "Bus # : %d\n", card->busnumber);
+ seq_printf(seq, "Device # : %d\n", card->slotnumber);
+ seq_printf(seq, "Interfaces : %d\n", card->card_size);
+ seq_printf(seq, " Initialized : %d\n",
+ card->adapters_activated);
+ seq_printf(seq, " Allocated : %d\n",
+ card->adapters_allocated);
+ ASSERT(card->card_size <= SLIC_NBR_MACS);
+ for (i = 0; i < card->card_size; i++) {
+ seq_printf(seq,
+ " MAC%d : %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+ i, config->macinfo[i].macaddrA[0],
+ config->macinfo[i].macaddrA[1],
+ config->macinfo[i].macaddrA[2],
+ config->macinfo[i].macaddrA[3],
+ config->macinfo[i].macaddrA[4],
+ config->macinfo[i].macaddrA[5]);
+ }
+ seq_printf(seq, " IF Init State Duplex/Speed irq\n");
+ seq_printf(seq, " -------------------------------\n");
+ for (i = 0; i < card->adapters_allocated; i++) {
+ struct adapter *adapter;
+
+ adapter = card->adapter[i];
+ if (adapter) {
+ seq_printf(seq,
+ " %d %d %s %s %s 0x%X\n",
+ adapter->physport, adapter->state,
+ SLIC_LINKSTATE(adapter->linkstate),
+ SLIC_DUPLEX(adapter->linkduplex),
+ SLIC_SPEED(adapter->linkspeed),
+ (uint) adapter->irq);
+ }
+ }
+ seq_printf(seq, "Generation # : %4.4X\n", card->gennumber);
+ seq_printf(seq, "RcvQ max entries : %4.4X\n",
+ SLIC_RCVQ_ENTRIES);
+ seq_printf(seq, "Ping Status : %8.8X\n",
+ card->pingstatus);
+ seq_printf(seq, "Minimum grant : %2.2x\n",
+ config->MinGrant);
+ seq_printf(seq, "Maximum Latency : %2.2x\n", config->MaxLat);
+ seq_printf(seq, "PciStatus : %4.4x\n",
+ config->Pcistatus);
+ seq_printf(seq, "Debug Device Id : %4.4x\n",
+ config->DbgDevId);
+ seq_printf(seq, "DRAM ROM Function : %4.4x\n",
+ config->DramRomFn);
+ seq_printf(seq, "Network interface Pin 1 : %2.2x\n",
+ config->NetIntPin1);
+ seq_printf(seq, "Network interface Pin 2 : %2.2x\n",
+ config->NetIntPin1);
+ seq_printf(seq, "Network interface Pin 3 : %2.2x\n",
+ config->NetIntPin1);
+ seq_printf(seq, "PM capabilities : %4.4X\n",
+ config->PMECapab);
+ seq_printf(seq, "Network Clock Controls : %4.4X\n",
+ config->NwClkCtrls);
+
+ switch (config->FruFormat) {
+ case ATK_FRU_FORMAT:
+ {
+ seq_printf(seq,
+ "Vendor : Alacritech, Inc.\n");
+ seq_printf(seq,
+ "Assembly # : %c%c%c%c%c%c\n",
+ fru[0], fru[1], fru[2], fru[3], fru[4],
+ fru[5]);
+ seq_printf(seq,
+ "Revision # : %c%c\n",
+ fru[6], fru[7]);
+
+ if (config->OEMFruFormat == VENDOR4_FRU_FORMAT) {
+ seq_printf(seq,
+ "Serial # : "
+ "%c%c%c%c%c%c%c%c%c%c%c%c\n",
+ fru[8], fru[9], fru[10],
+ fru[11], fru[12], fru[13],
+ fru[16], fru[17], fru[18],
+ fru[19], fru[20], fru[21]);
+ } else {
+ seq_printf(seq,
+ "Serial # : "
+ "%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+ fru[8], fru[9], fru[10],
+ fru[11], fru[12], fru[13],
+ fru[14], fru[15], fru[16],
+ fru[17], fru[18], fru[19],
+ fru[20], fru[21]);
+ }
+ break;
+ }
+
+ default:
+ {
+ seq_printf(seq,
+ "Vendor : Alacritech, Inc.\n");
+ seq_printf(seq,
+ "Serial # : Empty FRU\n");
+ break;
+ }
+ }
+
+ switch (config->OEMFruFormat) {
+ case VENDOR1_FRU_FORMAT:
+ {
+ seq_printf(seq, "FRU Information:\n");
+ seq_printf(seq, " Commodity # : %c\n",
+ oemfru[0]);
+ seq_printf(seq,
+ " Assembly # : %c%c%c%c\n",
+ oemfru[1], oemfru[2], oemfru[3], oemfru[4]);
+ seq_printf(seq,
+ " Revision # : %c%c\n",
+ oemfru[5], oemfru[6]);
+ seq_printf(seq,
+ " Supplier # : %c%c\n",
+ oemfru[7], oemfru[8]);
+ seq_printf(seq,
+ " Date : %c%c\n",
+ oemfru[9], oemfru[10]);
+ seq_sprintf(seq,
+ " Sequence # : %c%c%c\n",
+ oemfru[11], oemfru[12], oemfru[13]);
+ break;
+ }
+
+ case VENDOR2_FRU_FORMAT:
+ {
+ seq_printf(seq, "FRU Information:\n");
+ seq_printf(seq,
+ " Part # : "
+ "%c%c%c%c%c%c%c%c\n",
+ oemfru[0], oemfru[1], oemfru[2],
+ oemfru[3], oemfru[4], oemfru[5],
+ oemfru[6], oemfru[7]);
+ seq_printf(seq,
+ " Supplier # : %c%c%c%c%c\n",
+ oemfru[8], oemfru[9], oemfru[10],
+ oemfru[11], oemfru[12]);
+ seq_printf(seq,
+ " Date : %c%c%c\n",
+ oemfru[13], oemfru[14], oemfru[15]);
+ seq_sprintf(seq,
+ " Sequence # : %c%c%c%c\n",
+ oemfru[16], oemfru[17], oemfru[18],
+ oemfru[19]);
+ break;
+ }
+
+ case VENDOR3_FRU_FORMAT:
+ {
+ seq_printf(seq, "FRU Information:\n");
+ }
+
+ case VENDOR4_FRU_FORMAT:
+ {
+ seq_printf(seq, "FRU Information:\n");
+ seq_printf(seq,
+ " FRU Number : "
+ "%c%c%c%c%c%c%c%c\n",
+ oemfru[0], oemfru[1], oemfru[2],
+ oemfru[3], oemfru[4], oemfru[5],
+ oemfru[6], oemfru[7]);
+ seq_sprintf(seq,
+ " Part Number : "
+ "%c%c%c%c%c%c%c%c\n",
+ oemfru[8], oemfru[9], oemfru[10],
+ oemfru[11], oemfru[12], oemfru[13],
+ oemfru[14], oemfru[15]);
+ seq_printf(seq,
+ " EC Level : "
+ "%c%c%c%c%c%c%c%c\n",
+ oemfru[16], oemfru[17], oemfru[18],
+ oemfru[19], oemfru[20], oemfru[21],
+ oemfru[22], oemfru[23]);
+ break;
+ }
+
+ default:
+ break;
+ }
+#endif
+
+ return 0;
+}
+
+static int slic_debug_adapter_show(struct seq_file *seq, void *v)
+{
+ struct adapter *adapter = seq->private;
+
+ if ((adapter->netdev) && (adapter->netdev->name)) {
+ seq_printf(seq, "info: interface : %s\n",
+ adapter->netdev->name);
+ }
+ seq_printf(seq, "info: status : %s\n",
+ SLIC_LINKSTATE(adapter->linkstate));
+ seq_printf(seq, "info: port : %d\n",
+ adapter->physport);
+ seq_printf(seq, "info: speed : %s\n",
+ SLIC_SPEED(adapter->linkspeed));
+ seq_printf(seq, "info: duplex : %s\n",
+ SLIC_DUPLEX(adapter->linkduplex));
+ seq_printf(seq, "info: irq : 0x%X\n",
+ (uint) adapter->irq);
+ seq_printf(seq, "info: Interrupt Agg Delay: %d usec\n",
+ adapter->card->loadlevel_current);
+ seq_printf(seq, "info: RcvQ max entries : %4.4X\n",
+ SLIC_RCVQ_ENTRIES);
+ seq_printf(seq, "info: RcvQ current : %4.4X\n",
+ adapter->rcvqueue.count);
+ seq_printf(seq, "rx stats: packets : %8.8lX\n",
+ adapter->stats.rx_packets);
+ seq_printf(seq, "rx stats: bytes : %8.8lX\n",
+ adapter->stats.rx_bytes);
+ seq_printf(seq, "rx stats: broadcasts : %8.8X\n",
+ adapter->rcv_broadcasts);
+ seq_printf(seq, "rx stats: multicasts : %8.8X\n",
+ adapter->rcv_multicasts);
+ seq_printf(seq, "rx stats: unicasts : %8.8X\n",
+ adapter->rcv_unicasts);
+ seq_printf(seq, "rx stats: errors : %8.8X\n",
+ (u32) adapter->slic_stats.iface.rcv_errors);
+ seq_printf(seq, "rx stats: Missed errors : %8.8X\n",
+ (u32) adapter->slic_stats.iface.rcv_discards);
+ seq_printf(seq, "rx stats: drops : %8.8X\n",
+ (u32) adapter->rcv_drops);
+ seq_printf(seq, "tx stats: packets : %8.8lX\n",
+ adapter->stats.tx_packets);
+ seq_printf(seq, "tx stats: bytes : %8.8lX\n",
+ adapter->stats.tx_bytes);
+ seq_printf(seq, "tx stats: errors : %8.8X\n",
+ (u32) adapter->slic_stats.iface.xmt_errors);
+ seq_printf(seq, "rx stats: multicasts : %8.8lX\n",
+ adapter->stats.multicast);
+ seq_printf(seq, "tx stats: collision errors : %8.8X\n",
+ (u32) adapter->slic_stats.iface.xmit_collisions);
+ seq_printf(seq, "perf: Max rcv frames/isr : %8.8X\n",
+ adapter->max_isr_rcvs);
+ seq_printf(seq, "perf: Rcv interrupt yields : %8.8X\n",
+ adapter->rcv_interrupt_yields);
+ seq_printf(seq, "perf: Max xmit complete/isr : %8.8X\n",
+ adapter->max_isr_xmits);
+ seq_printf(seq, "perf: error interrupts : %8.8X\n",
+ adapter->error_interrupts);
+ seq_printf(seq, "perf: error rmiss interrupts : %8.8X\n",
+ adapter->error_rmiss_interrupts);
+ seq_printf(seq, "perf: rcv interrupts : %8.8X\n",
+ adapter->rcv_interrupts);
+ seq_printf(seq, "perf: xmit interrupts : %8.8X\n",
+ adapter->xmit_interrupts);
+ seq_printf(seq, "perf: link event interrupts : %8.8X\n",
+ adapter->linkevent_interrupts);
+ seq_printf(seq, "perf: UPR interrupts : %8.8X\n",
+ adapter->upr_interrupts);
+ seq_printf(seq, "perf: interrupt count : %8.8X\n",
+ adapter->num_isrs);
+ seq_printf(seq, "perf: false interrupts : %8.8X\n",
+ adapter->false_interrupts);
+ seq_printf(seq, "perf: All register writes : %8.8X\n",
+ adapter->all_reg_writes);
+ seq_printf(seq, "perf: ICR register writes : %8.8X\n",
+ adapter->icr_reg_writes);
+ seq_printf(seq, "perf: ISR register writes : %8.8X\n",
+ adapter->isr_reg_writes);
+ seq_printf(seq, "ifevents: overflow 802 errors : %8.8X\n",
+ adapter->if_events.oflow802);
+ seq_printf(seq, "ifevents: transport overflow errors: %8.8X\n",
+ adapter->if_events.Tprtoflow);
+ seq_printf(seq, "ifevents: underflow errors : %8.8X\n",
+ adapter->if_events.uflow802);
+ seq_printf(seq, "ifevents: receive early : %8.8X\n",
+ adapter->if_events.rcvearly);
+ seq_printf(seq, "ifevents: buffer overflows : %8.8X\n",
+ adapter->if_events.Bufov);
+ seq_printf(seq, "ifevents: carrier errors : %8.8X\n",
+ adapter->if_events.Carre);
+ seq_printf(seq, "ifevents: Long : %8.8X\n",
+ adapter->if_events.Longe);
+ seq_printf(seq, "ifevents: invalid preambles : %8.8X\n",
+ adapter->if_events.Invp);
+ seq_printf(seq, "ifevents: CRC errors : %8.8X\n",
+ adapter->if_events.Crc);
+ seq_printf(seq, "ifevents: dribble nibbles : %8.8X\n",
+ adapter->if_events.Drbl);
+ seq_printf(seq, "ifevents: Code violations : %8.8X\n",
+ adapter->if_events.Code);
+ seq_printf(seq, "ifevents: TCP checksum errors : %8.8X\n",
+ adapter->if_events.TpCsum);
+ seq_printf(seq, "ifevents: TCP header short errors : %8.8X\n",
+ adapter->if_events.TpHlen);
+ seq_printf(seq, "ifevents: IP checksum errors : %8.8X\n",
+ adapter->if_events.IpCsum);
+ seq_printf(seq, "ifevents: IP frame incompletes : %8.8X\n",
+ adapter->if_events.IpLen);
+ seq_printf(seq, "ifevents: IP headers shorts : %8.8X\n",
+ adapter->if_events.IpHlen);
+
+ return 0;
+}
+static int slic_debug_adapter_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, slic_debug_adapter_show, inode->i_private);
+}
+
+static int slic_debug_card_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, slic_debug_card_show, inode->i_private);
+}
+
+static const struct file_operations slic_debug_adapter_fops = {
+ .owner = THIS_MODULE,
+ .open = slic_debug_adapter_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations slic_debug_card_fops = {
+ .owner = THIS_MODULE,
+ .open = slic_debug_card_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void slic_debug_adapter_create(struct adapter *adapter)
+{
+ struct dentry *d;
+ char name[7];
+ struct sliccard *card = adapter->card;
+
+ if (!card->debugfs_dir)
+ return;
+
+ sprintf(name, "port%d", adapter->port);
+ d = debugfs_create_file(name, S_IRUGO,
+ card->debugfs_dir, adapter,
+ &slic_debug_adapter_fops);
+ if (!d || IS_ERR(d))
+ pr_info(PFX "%s: debugfs create failed\n", name);
+ else
+ adapter->debugfs_entry = d;
+}
+
+static void slic_debug_adapter_destroy(struct adapter *adapter)
+{
+ if (adapter->debugfs_entry) {
+ debugfs_remove(adapter->debugfs_entry);
+ adapter->debugfs_entry = NULL;
+ }
+}
+
+static void slic_debug_card_create(struct sliccard *card)
+{
+ struct dentry *d;
+ char name[IFNAMSIZ];
+
+ snprintf(name, sizeof(name), "slic%d", card->cardnum);
+ d = debugfs_create_dir(name, slic_debugfs);
+ if (!d || IS_ERR(d))
+ pr_info(PFX "%s: debugfs create dir failed\n",
+ name);
+ else {
+ card->debugfs_dir = d;
+ d = debugfs_create_file("cardinfo", S_IRUGO,
+ slic_debugfs, card,
+ &slic_debug_card_fops);
+ if (!d || IS_ERR(d))
+ pr_info(PFX "%s: debugfs create failed\n",
+ name);
+ else
+ card->debugfs_cardinfo = d;
+ }
+}
+
+static void slic_debug_card_destroy(struct sliccard *card)
+{
+ int i;
+
+ for (i = 0; i < card->card_size; i++) {
+ struct adapter *adapter;
+
+ adapter = card->adapter[i];
+ if (adapter)
+ slic_debug_adapter_destroy(adapter);
+ }
+ if (card->debugfs_cardinfo) {
+ debugfs_remove(card->debugfs_cardinfo);
+ card->debugfs_cardinfo = NULL;
+ }
+ if (card->debugfs_dir) {
+ debugfs_remove(card->debugfs_dir);
+ card->debugfs_dir = NULL;
+ }
+}
+
+static void slic_debug_init(void)
+{
+ struct dentry *ent;
+
+ ent = debugfs_create_dir("slic", NULL);
+ if (!ent || IS_ERR(ent)) {
+ pr_info(PFX "debugfs create directory failed\n");
+ return;
+ }
+
+ slic_debugfs = ent;
+}
+
+static void slic_debug_cleanup(void)
+{
+ if (slic_debugfs) {
+ debugfs_remove(slic_debugfs);
+ slic_debugfs = NULL;
+ }
+}
+
+/*=============================================================================
+ =============================================================================
+ === ===
+ === SLIC DUMP MANAGEMENT SECTION ===
+ === ===
+ === ===
+ === Dump routines ===
+ === ===
+ === ===
+ =============================================================================
+ ============================================================================*/
+
+#if SLIC_DUMP_ENABLED
+
+#include <stdarg.h>
+
+void *slic_dump_handle; /* thread handle */
+
+/*
+ * These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static int slic_dump_seek(struct file *SLIChandle, u32 file_offset)
+{
+ if (SLIChandle->f_pos != file_offset) {
+ /*DBG_MSG("slic_dump_seek now needed [%x : %x]\n",
+ (u32)SLIChandle->f_pos, (u32)file_offset); */
+ if (SLIChandle->f_op->llseek) {
+ if (SLIChandle->f_op->
+ llseek(SLIChandle, file_offset, 0) != file_offset)
+ return 0;
+ } else {
+ SLIChandle->f_pos = file_offset;
+ }
+ }
+ return 1;
+}
+
+static int slic_dump_write(struct sliccard *card,
+ const void *addr, int size, u32 file_offset)
+{
+ int r = 1;
+ u32 result = 0;
+ struct file *SLIChandle = card->dumphandle;
+
+#ifdef HISTORICAL /* legacy */
+ down(&SLIChandle->f_dentry->d_inode->i_sem);
+#endif
+ if (size) {
+ slic_dump_seek(SLIChandle, file_offset);
+
+ result =
+ SLIChandle->f_op->write(SLIChandle, addr, size,
+ &SLIChandle->f_pos);
+
+ r = result == size;
+ }
+
+ card->dumptime_complete = jiffies;
+ card->dumptime_delta = card->dumptime_complete - card->dumptime_start;
+ card->dumptime_start = jiffies;
+
+#ifdef HISTORICAL
+ up(&SLIChandle->f_dentry->d_inode->i_sem);
+#endif
+ if (!r) {
+ DBG_ERROR("%s: addr[%p] size[%x] result[%x] file_offset[%x]\n",
+ __func__, addr, size, result, file_offset);
+ }
+ return r;
+}
+
+static uint slic_init_dump_thread(struct sliccard *card)
+{
+ card->dump_task_id = kthread_run(slic_dump_thread, (void *)card, 0);
+
+/* DBG_MSG("create slic_dump_thread dump_pid[%x]\n", card->dump_pid); */
+ if (IS_ERR(card->dump_task_id)) {
+ DBG_MSG("create slic_dump_thread FAILED \n");
+ return STATUS_FAILURE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static int slic_dump_thread(void *context)
+{
+ struct sliccard *card = (struct sliccard *)context;
+ struct adapter *adapter;
+ struct adapter *dump_adapter = NULL;
+ u32 dump_complete = 0;
+ u32 delay = SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL);
+ struct slic_regs *pregs;
+ u32 i;
+ struct slic_upr *upr, *uprnext;
+ u32 dump_card;
+
+ ASSERT(card);
+
+ card->dumpthread_running = 1;
+
+#ifdef HISTORICAL
+ lock_kernel();
+ /*
+ * This thread doesn't need any user-level access,
+ * so get rid of all our resources
+ */
+ exit_files(current); /* daemonize doesn't do exit_files */
+ current->files = init_task.files;
+ atomic_inc(&current->files->count);
+#endif
+
+ daemonize("%s", "slicmon");
+
+ /* Setup a nice name */
+ strcpy(current->comm, "slicmon");
+ DBG_ERROR
+ ("slic_dump_thread[slicmon] daemon is alive card[%p] pid[%x]\n",
+ card, card->dump_task_id->pid);
+
+ /*
+ * Send me a signal to get me to die (for debugging)
+ */
+ do {
+ /*
+ * If card state is not set to up, skip
+ */
+ if (card->state != CARD_UP) {
+ if (card->adapters_activated)
+ goto wait;
+ else
+ goto end_thread;
+ }
+ /*
+ * Check the results of our last ping.
+ */
+ dump_card = 0;
+#ifdef SLIC_FAILURE_DUMP
+ if (card->pingstatus != ISR_PINGMASK) {
+ DBG_MSG
+ ("\n[slicmon] CARD #%d TIMED OUT - status "
+ "%x: DUMP THE CARD!\n",
+ card->cardnum, card->pingstatus);
+ dump_card = 1;
+ }
+#else
+ /*
+ * Cause a card RESET instead?
+ */
+ if (card->pingstatus != ISR_PINGMASK) {
+ /* todo. do we want to reset the card in production */
+ /* DBG_MSG("\n[slicmon] CARD #%d TIMED OUT - "
+ status %x: RESET THE CARD!\n", card->cardnum,
+ card->pingstatus); */
+ DBG_ERROR
+ ("\n[slicmon] CARD #%d TIMED OUT - status %x: "
+ "DUMP THE CARD!\n",
+ card->cardnum, card->pingstatus);
+ dump_card = 1;
+ }
+#endif
+ if ((dump_card)
+ || (card->dump_requested == SLIC_DUMP_REQUESTED)) {
+ if (card->dump_requested == SLIC_DUMP_REQUESTED) {
+ DBG_ERROR
+ ("[slicmon]: Dump card Requested: Card %x\n",
+ card->cardnum);
+ }
+ if (card->pingstatus != ISR_PINGMASK) {
+ ushort cpuid = 0;
+ ushort crashpc = 0;
+
+ if (card->adapter[0]) {
+ if ((card->adapter[0])->memorylength >=
+ CRASH_INFO_OFFSET +
+ sizeof(slic_crash_info)) {
+ char *crashptr;
+ p_slic_crash_info crashinfo;
+
+ crashptr =
+ ((char *)card->adapter[0]->
+ slic_regs) +
+ CRASH_INFO_OFFSET;
+ crashinfo =
+ (p_slic_crash_info)
+ crashptr;
+ cpuid = crashinfo->cpu_id;
+ crashpc = crashinfo->crash_pc;
+ }
+ }
+ DBG_ERROR
+ ("[slicmon]: Dump card: Card %x crashed "
+ "and failed to answer PING. "
+ "CPUID[%x] PC[%x]\n ",
+ card->cardnum, cpuid, crashpc);
+ }
+
+ card->dump_requested = SLIC_DUMP_IN_PROGRESS;
+
+ /*
+ * Set the card state to DOWN and the adapter states
+ * to RESET.They will check this in SimbaCheckForHang
+ * and initiate interface reset (which in turn will
+ * reinitialize the card).
+ */
+ card->state = CARD_DOWN;
+
+ for (i = 0; i < card->card_size; i++) {
+ adapter = card->adapter[i];
+ if (adapter) {
+ slic_if_stop_queue(adapter);
+
+ if (adapter->state == ADAPT_UP) {
+ adapter->state = ADAPT_RESET;
+ adapter->linkstate = LINK_DOWN;
+ DBG_ERROR
+ ("[slicmon]: SLIC Card[%d] "
+ "Port[%d] adapter[%p] "
+ "down\n",
+ (uint) card->cardnum,
+ (uint) i, adapter);
+ }
+#if SLIC_GET_STATS_TIMER_ENABLED
+ /* free stats timer */
+ if (adapter->statstimerset) {
+ adapter->statstimerset = 0;
+ del_timer(&adapter->statstimer);
+ }
+#endif
+ }
+ }
+
+ for (i = 0; i < card->card_size; i++) {
+ adapter = card->adapter[i];
+ if ((adapter) && (adapter->activated)) {
+ pregs = adapter->slic_regs;
+ dump_adapter = adapter;
+
+ /*
+ * If the dump status is zero, then
+ * the utility processor has crashed.
+ * If this is the case, any pending
+ * utilityprocessor requests will not
+ * complete and our dump commands will
+ * not be issued.
+ *
+ * To avoid this we will clear any
+ * pending utility processor requests
+ * now.
+ */
+ if (!card->pingstatus) {
+ spin_lock_irqsave(
+ &adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+ upr = adapter->upr_list;
+ while (upr) {
+ uprnext = upr->next;
+ kfree(upr);
+ upr = uprnext;
+ }
+ adapter->upr_list = 0;
+ adapter->upr_busy = 0;
+ spin_unlock_irqrestore(
+ &adapter->upr_lock.lock,
+ adapter->upr_lock.flags);
+ }
+
+ slic_dump_card(card, FALSE);
+ dump_complete = 1;
+ }
+
+ if (dump_complete) {
+ DBG_ERROR("SLIC Dump Complete\n");
+ /* Only dump the card one time */
+ break;
+ }
+ }
+
+ if (dump_adapter) {
+ DBG_ERROR
+ ("slic dump completed. "
+ "Reenable interfaces\n");
+ slic_card_init(card, dump_adapter);
+
+ /*
+ * Reenable the adapters that were reset
+ */
+ for (i = 0; i < card->card_size; i++) {
+ adapter = card->adapter[i];
+ if (adapter) {
+ if (adapter->state ==
+ ADAPT_RESET) {
+ DBG_ERROR
+ ("slicdump: SLIC "
+ "Card[%d] Port[%d] adapter[%p] "
+ "bring UP\n",
+ (uint) card->
+ cardnum, (uint) i,
+ adapter);
+ adapter->state =
+ ADAPT_DOWN;
+ adapter->linkstate =
+ LINK_DOWN;
+ slic_entry_open
+ (adapter->netdev);
+ }
+ }
+ }
+
+ card->dump_requested = SLIC_DUMP_DONE;
+ }
+ } else {
+ /* if pingstatus != ISR_PINGMASK) || dump_requested...ELSE
+ * We received a valid ping response.
+ * Clear the Pingstatus field, find a valid adapter
+ * structure and send another ping.
+ */
+ for (i = 0; i < card->card_size; i++) {
+ adapter = card->adapter[i];
+ if (adapter && (adapter->state == ADAPT_UP)) {
+ card->pingstatus = 0;
+ slic_upr_request(adapter, SLIC_UPR_PING,
+ 0, 0, 0, 0);
+ break; /* Only issue one per card */
+ }
+ }
+ }
+wait:
+ SLIC_INTERRUPTIBLE_SLEEP_ON_TIMEOUT(card->dump_wq, delay);
+ } while (!signal_pending(current));
+
+end_thread:
+/* DBG_MSG("[slicmon] slic_dump_thread card[%p] pid[%x] ENDING\n",
+ card, card->dump_pid); */
+ card->dumpthread_running = 0;
+
+ return 0;
+}
+
+/*
+ * Read a single byte from our dump index file. This
+ * value is used as our suffix for our dump path. The
+ * value is incremented and written back to the file
+ */
+static unsigned char slic_get_dump_index(char *path)
+{
+ unsigned char index = 0;
+#ifdef SLIC_DUMP_INDEX_SUPPORT
+ u32 status;
+ void *FileHandle;
+ u32 offset;
+
+ offset = 0;
+
+ /*
+ * Open the index file. If one doesn't exist, create it
+ */
+ status = create_file(&FileHandle);
+
+ if (status != STATUS_SUCCESS)
+ return (unsigned char) 0;
+
+ status = read_file(FileHandle, &index, 1, &offset);
+
+ index++;
+
+ status = write_file(FileHandle, &index, 1, &offset);
+
+ close_file(FileHandle);
+#else
+ index = 0;
+#endif
+ return index;
+}
+
+static struct file *slic_dump_open_file(struct sliccard *card)
+{
+ struct file *SLIChandle = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *inode = NULL;
+ char SLICfile[50];
+
+ card->dumpfile_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+
+ memset(SLICfile, 0, sizeof(SLICfile));
+ sprintf(SLICfile, "/var/tmp/slic%d-dump-%d", card->cardnum,
+ (uint) card->dump_count);
+ card->dump_count++;
+
+ SLIChandle =
+ filp_open(SLICfile, O_CREAT | O_RDWR | O_SYNC | O_LARGEFILE, 0666);
+
+ DBG_MSG("[slicmon]: Dump Card #%d to file: %s \n", card->cardnum,
+ SLICfile);
+
+/* DBG_MSG("[slicmon] filp_open %s SLIChandle[%p]\n", SLICfile, SLIChandle);*/
+
+ if (IS_ERR(SLIChandle))
+ goto end_slicdump;
+
+ dentry = SLIChandle->f_dentry;
+ inode = dentry->d_inode;
+
+/* DBG_MSG("[slicmon] inode[%p] i_nlink[%x] i_mode[%x] i_op[%p] i_fop[%p]\n"
+ "f_op->write[%p]\n",
+ inode, inode->i_nlink, inode->i_mode, inode->i_op,
+ inode->i_fop, SLIChandle->f_op->write); */
+ if (inode->i_nlink > 1)
+ goto close_slicdump; /* multiple links - don't dump */
+#ifdef HISTORICAL
+ if (!S_ISREG(inode->i_mode))
+ goto close_slicdump;
+#endif
+ if (!inode->i_op || !inode->i_fop)
+ goto close_slicdump;
+
+ if (!SLIChandle->f_op->write)
+ goto close_slicdump;
+
+ /*
+ * If we got here we have SUCCESSFULLY OPENED the dump file
+ */
+/* DBG_MSG("opened %s SLIChandle[%p]\n", SLICfile, SLIChandle); */
+ return SLIChandle;
+
+close_slicdump:
+ DBG_MSG("[slicmon] slic_dump_open_file failed close SLIChandle[%p]\n",
+ SLIChandle);
+ filp_close(SLIChandle, NULL);
+
+end_slicdump:
+ set_fs(card->dumpfile_fs);
+
+ return NULL;
+}
+
+static void slic_dump_close_file(struct sliccard *card)
+{
+
+/* DBG_MSG("[slicmon] slic_dump_CLOSE_file close SLIChandle[%p]\n",
+ card->dumphandle); */
+
+ filp_close(card->dumphandle, NULL);
+
+ set_fs(card->dumpfile_fs);
+}
+
+static u32 slic_dump_card(struct sliccard *card, bool resume)
+{
+ struct adapter *adapter = card->master;
+ u32 status;
+ u32 queue;
+ u32 len, offset;
+ u32 sram_size, dram_size, regs;
+ struct sliccore_hdr corehdr;
+ u32 file_offset;
+ char *namestr;
+ u32 i;
+ u32 max_queues = 0;
+ u32 result;
+
+ card->dumphandle = slic_dump_open_file(card);
+
+ if (card->dumphandle == NULL) {
+ DBG_MSG("[slicmon] Cant create Dump file - dump failed\n");
+ return -ENOMEM;
+ }
+ if (!card->dumpbuffer) {
+ DBG_MSG("[slicmon] Insufficient memory for dump\n");
+ return -ENOMEM;
+ }
+ if (!card->cmdbuffer) {
+ DBG_MSG("[slicmon] Insufficient cmd memory for dump\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Write the file version to the core header.
+ */
+ namestr = slic_proc_version;
+ for (i = 0; i < (DRIVER_NAME_SIZE - 1); i++, namestr++) {
+ if (!namestr)
+ break;
+ corehdr.driver_version[i] = *namestr;
+ }
+ corehdr.driver_version[i] = 0;
+
+ file_offset = sizeof(struct sliccore_hdr);
+
+ /*
+ * Issue the following debug commands to the SLIC:
+ * - Halt both receive and transmit
+ * - Dump receive registers
+ * - Dump transmit registers
+ * - Dump sram
+ * - Dump dram
+ * - Dump queues
+ */
+ DBG_MSG("slicDump HALT Receive Processor\n");
+ card->dumptime_start = jiffies;
+
+ status = slic_dump_halt(card, PROC_RECEIVE);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR
+ ("Cant halt receive sequencer - dump failed status[%x]\n",
+ status);
+ goto done;
+ }
+
+ DBG_MSG("slicDump HALT Transmit Processor\n");
+ status = slic_dump_halt(card, PROC_TRANSMIT);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("Cant halt transmit sequencer - dump failed\n");
+ goto done;
+ }
+
+ /* Dump receive regs */
+ status = slic_dump_reg(card, PROC_RECEIVE);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("Cant dump receive registers - dump failed\n");
+ goto done;
+ }
+
+ DBG_MSG("slicDump Write Receive REGS len[%x] offset[%x]\n",
+ (SLIC_NUM_REG * 4), file_offset);
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, SLIC_NUM_REG * 4,
+ file_offset);
+ if (!result) {
+ DBG_ERROR
+ ("Cant write rcv registers to dump file - dump failed\n");
+ goto done;
+ }
+
+ corehdr.RcvRegOff = file_offset;
+ corehdr.RcvRegsize = SLIC_NUM_REG * 4;
+ file_offset += SLIC_NUM_REG * 4;
+
+ /* Dump transmit regs */
+ status = slic_dump_reg(card, PROC_TRANSMIT);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("Cant dump transmit registers - dump failed\n");
+ goto done;
+ }
+
+ DBG_MSG("slicDump Write XMIT REGS len[%x] offset[%x]\n",
+ (SLIC_NUM_REG * 4), file_offset);
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, SLIC_NUM_REG * 4,
+ file_offset);
+ if (!result) {
+ DBG_ERROR
+ ("Cant write xmt registers to dump file - dump failed\n");
+ goto done;
+ }
+
+ corehdr.XmtRegOff = file_offset;
+ corehdr.XmtRegsize = SLIC_NUM_REG * 4;
+ file_offset += SLIC_NUM_REG * 4;
+
+ regs = SLIC_GBMAX_REG;
+
+ corehdr.FileRegOff = file_offset;
+ corehdr.FileRegsize = regs * 4;
+
+ for (offset = 0; regs;) {
+ len = MIN(regs, 16); /* Can only xfr 16 regs at a time */
+
+ status = slic_dump_data(card, offset, (ushort) len, DESC_RFILE);
+
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("Cant dump register file - dump failed\n");
+ goto done;
+ }
+
+ DBG_MSG("slicDump Write RegisterFile len[%x] offset[%x]\n",
+ (len * 4), file_offset);
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, len * 4,
+ file_offset);
+ if (!result) {
+ DBG_ERROR
+ ("Cant write register file to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+
+ file_offset += len * 4;
+ offset += len;
+ regs -= len;
+ }
+
+ dram_size = card->config.DramSize * 0x10000;
+
+ switch (adapter->devid) {
+ case SLIC_2GB_DEVICE_ID:
+ sram_size = SLIC_SRAM_SIZE2GB;
+ break;
+ case SLIC_1GB_DEVICE_ID:
+ sram_size = SLIC_SRAM_SIZE1GB;
+ break;
+ default:
+ sram_size = 0;
+ ASSERT(0);
+ break;
+ }
+
+ corehdr.SramOff = file_offset;
+ corehdr.Sramsize = sram_size;
+
+ for (offset = 0; sram_size;) {
+ len = MIN(sram_size, DUMP_BUF_SIZE);
+ status = slic_dump_data(card, offset, (ushort) len, DESC_SRAM);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR
+ ("[slicmon] Cant dump SRAM at offset %x - "
+ "dump failed\n", (uint) offset);
+ goto done;
+ }
+
+ DBG_MSG("[slicmon] slicDump Write SRAM len[%x] offset[%x]\n",
+ len, file_offset);
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, len, file_offset);
+ if (!result) {
+ DBG_ERROR
+ ("[slicmon] Cant write SRAM to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+
+ file_offset += len;
+ offset += len;
+ sram_size -= len;
+ }
+
+ corehdr.DramOff = file_offset;
+ corehdr.Dramsize = dram_size;
+
+ for (offset = 0; dram_size;) {
+ len = MIN(dram_size, DUMP_BUF_SIZE);
+
+ status = slic_dump_data(card, offset, (ushort) len, DESC_DRAM);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR
+ ("[slicmon] Cant dump dram at offset %x - "
+ "dump failed\n", (uint) offset);
+ goto done;
+ }
+
+ DBG_MSG("slicDump Write DRAM len[%x] offset[%x]\n", len,
+ file_offset);
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, len, file_offset);
+ if (!result) {
+ DBG_ERROR
+ ("[slicmon] Cant write DRAM to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+
+ file_offset += len;
+ offset += len;
+ dram_size -= len;
+ }
+
+ max_queues = SLIC_MAX_QUEUE;
+
+ for (queue = 0; queue < max_queues; queue++) {
+ u32 *qarray = (u32 *) card->dumpbuffer;
+ u32 qarray_physl = card->dumpbuffer_physl;
+ u32 qarray_physh = card->dumpbuffer_physh;
+ u32 qstart;
+ u32 qdelta;
+ u32 qtotal = 0;
+
+ DBG_MSG("[slicmon] Start Dump of QUEUE #0x%x\n", (uint) queue);
+
+ for (offset = 0; offset < (DUMP_BUF_SIZE >> 2); offset++) {
+ qstart = jiffies;
+ qdelta = 0;
+
+ status = slic_dump_queue(card,
+ qarray_physl,
+ qarray_physh, queue);
+ qarray_physl += 4;
+
+ if (status != STATUS_SUCCESS)
+ break;
+
+ if (jiffies > qstart) {
+ qdelta = jiffies - qstart;
+ qtotal += qdelta;
+ }
+ }
+
+ if (offset)
+ qdelta = qtotal / offset;
+ else
+ qdelta = 0;
+
+/* DBG_MSG(" slicDump Write QUEUE #0x%x len[%x] offset[%x] "
+ "avgjiffs[%x]\n", queue, (offset*4), file_offset, qdelta); */
+
+ result =
+ slic_dump_write(card, card->dumpbuffer, offset * 4,
+ file_offset);
+
+ if (!result) {
+ DBG_ERROR
+ ("[slicmon] Cant write QUEUES to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+
+ corehdr.queues[queue].queueOff = file_offset;
+ corehdr.queues[queue].queuesize = offset * 4;
+ file_offset += offset * 4;
+
+/* DBG_MSG(" Reload QUEUE #0x%x elements[%x]\n", (uint)queue, offset);*/
+ /*
+ * Fill the queue back up
+ */
+ for (i = 0; i < offset; i++) {
+ qstart = jiffies;
+ qdelta = 0;
+
+ status = slic_dump_load_queue(card, qarray[i], queue);
+ if (status != STATUS_SUCCESS)
+ break;
+
+ if (jiffies > qstart) {
+ qdelta = jiffies - qstart;
+ qtotal += qdelta;
+ }
+ }
+
+ if (offset)
+ qdelta = qtotal / offset;
+ else
+ qdelta = 0;
+
+/* DBG_MSG(" Reload DONE avgjiffs[%x]\n", qdelta); */
+
+ resume = 1;
+ }
+
+ len = SLIC_GB_CAMAB_SZE * 4;
+ status = slic_dump_cam(card, 0, len, DUMP_CAM_A);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("[slicmon] Can't dump CAM_A - dump failed\n");
+ goto done;
+ }
+
+ result = slic_dump_write(card, card->dumpbuffer, len, file_offset);
+ if (result) {
+ DBG_ERROR
+ ("[slicmon] Can't write CAM_A data to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+ corehdr.CamAMOff = file_offset;
+ corehdr.CamASize = len;
+ file_offset += len;
+
+ len = SLIC_GB_CAMCD_SZE * 4;
+ status = slic_dump_cam(card, 0, len, DUMP_CAM_C);
+ if (status) {
+ DBG_ERROR("[slicmon] Can't dump CAM_C - dump failed\n");
+ goto done;
+ }
+
+ result = slic_dump_write(card, card->dumpbuffer, len, file_offset);
+ if (result) {
+ DBG_ERROR
+ ("[slicmon] Can't write CAM_C data to dump file - "
+ "dump failed\n");
+ goto done;
+ }
+ corehdr.CamCMOff = file_offset;
+ corehdr.CamCSize = len;
+ file_offset += len;
+
+done:
+ /*
+ * Write out the core header
+ */
+ file_offset = 0;
+ DBG_MSG("[slicmon] Write CoreHeader len[%x] offset[%x]\n",
+ (uint) sizeof(struct sliccore_hdr), file_offset);
+
+ result =
+ slic_dump_write(card, &corehdr, sizeof(struct sliccore_hdr),
+ file_offset);
+ DBG_MSG("[slicmon] corehdr xoff[%x] xsz[%x]\n"
+ " roff[%x] rsz[%x] fileoff[%x] filesz[%x]\n"
+ " sramoff[%x] sramsz[%x], dramoff[%x] dramsz[%x]\n"
+ " corehdr_offset[%x]\n", corehdr.XmtRegOff,
+ corehdr.XmtRegsize, corehdr.RcvRegOff, corehdr.RcvRegsize,
+ corehdr.FileRegOff, corehdr.FileRegsize, corehdr.SramOff,
+ corehdr.Sramsize, corehdr.DramOff, corehdr.Dramsize,
+ (uint) sizeof(struct sliccore_hdr));
+ for (i = 0; i < max_queues; i++) {
+ DBG_MSG("[slicmon] QUEUE 0x%x offset[%x] size[%x]\n",
+ (uint) i, corehdr.queues[i].queueOff,
+ corehdr.queues[i].queuesize);
+
+ }
+
+ slic_dump_close_file(card);
+
+ if (resume) {
+ DBG_MSG("slicDump RESTART RECEIVE and XMIT PROCESSORS\n\n");
+ slic_dump_resume(card, PROC_RECEIVE);
+ slic_dump_resume(card, PROC_TRANSMIT);
+ }
+
+ return status;
+}
+
+static u32 slic_dump_halt(struct sliccard *card, unsigned char proc)
+{
+ unsigned char *cmd = card->cmdbuffer;
+
+ *cmd = COMMAND_BYTE(CMD_HALT, 0, proc);
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh, 0, 0);
+}
+
+static u32 slic_dump_resume(struct sliccard *card, unsigned char proc)
+{
+ unsigned char *cmd = card->cmdbuffer;
+
+ *cmd = COMMAND_BYTE(CMD_RUN, 0, proc);
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh, 0, 0);
+}
+
+static u32 slic_dump_reg(struct sliccard *card, unsigned char proc)
+{
+ struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer;
+
+ dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, proc);
+ dump->desc = DESC_REG;
+ dump->count = 0;
+ dump->addr = 0;
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh,
+ card->dumpbuffer_physl,
+ card->dumpbuffer_physh);
+}
+
+static u32 slic_dump_data(struct sliccard *card,
+ u32 addr, ushort count, unsigned char desc)
+{
+ struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer;
+
+ dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, PROC_RECEIVE);
+ dump->desc = desc;
+ dump->count = count;
+ dump->addr = addr;
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh,
+ card->dumpbuffer_physl,
+ card->dumpbuffer_physh);
+}
+
+static u32 slic_dump_queue(struct sliccard *card,
+ u32 addr, u32 buf_physh, u32 queue)
+{
+ struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer;
+
+ dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, PROC_RECEIVE);
+ dump->desc = DESC_QUEUE;
+ dump->count = 1;
+ dump->addr = queue;
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh,
+ addr, card->dumpbuffer_physh);
+}
+
+static u32 slic_dump_load_queue(struct sliccard *card, u32 data,
+ u32 queue)
+{
+ struct dump_cmd *load = (struct dump_cmd *) card->cmdbuffer;
+
+ load->cmd = COMMAND_BYTE(CMD_LOAD, 0, PROC_RECEIVE);
+ load->desc = DESC_QUEUE;
+ load->count = (ushort) queue;
+ load->addr = data;
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh, 0, 0);
+}
+
+static u32 slic_dump_cam(struct sliccard *card,
+ u32 addr, u32 count, unsigned char desc)
+{
+ struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer;
+
+ dump->cmd = COMMAND_BYTE(CMD_CAM_OPS, 0, PROC_NONE);
+ dump->desc = desc;
+ dump->count = count;
+ dump->addr = 0;
+
+ return slic_dump_send_cmd(card,
+ card->cmdbuffer_physl,
+ card->cmdbuffer_physh,
+ addr, card->dumpbuffer_physh);
+}
+
+static u32 slic_dump_send_cmd(struct sliccard *card,
+ u32 cmd_physl,
+ u32 cmd_physh,
+ u32 buf_physl, u32 buf_physh)
+{
+ ulong timeout = SLIC_MS_TO_JIFFIES(500); /* 500 msec */
+ u32 attempts = 5;
+ u32 delay = SLIC_MS_TO_JIFFIES(10); /* 10 msec */
+ struct adapter *adapter = card->master;
+
+ ASSERT(adapter);
+ do {
+ /*
+ * Zero the Dumpstatus field of the adapter structure
+ */
+ card->dumpstatus = 0;
+ /*
+ * Issue the dump command via a utility processor request.
+ *
+ * Kludge: We use the Informationbuffer parameter to hold
+ * the buffer address
+ */
+ slic_upr_request(adapter, SLIC_UPR_DUMP, cmd_physl, cmd_physh,
+ buf_physl, buf_physh);
+
+ timeout += jiffies;
+ /*
+ * Spin until completion or timeout.
+ */
+ while (!card->dumpstatus) {
+ int num_sleeps = 0;
+
+ if (jiffies > timeout) {
+ /*
+ * Complete the timed-out DUMP UPR request.
+ */
+ slic_upr_request_complete(adapter, 0);
+ DBG_ERROR
+ ("%s: TIMED OUT num_sleeps[%x] "
+ "status[%x]\n",
+ __func__, num_sleeps, STATUS_FAILURE);
+
+ return STATUS_FAILURE;
+ }
+ num_sleeps++;
+ SLIC_INTERRUPTIBLE_SLEEP_ON_TIMEOUT(card->dump_wq,
+ delay);
+ }
+
+ if (card->dumpstatus & ISR_UPCERR) {
+ /*
+ * Error (or queue empty)
+ */
+/* DBG_ERROR("[slicmon] %s: DUMP_STATUS & ISR_UPCERR status[%x]\n",
+ __func__, STATUS_FAILURE); */
+
+ return STATUS_FAILURE;
+ } else if (card->dumpstatus & ISR_UPCBSY) {
+ /*
+ * Retry
+ */
+ DBG_ERROR("%s: ISR_UPCBUSY attempt[%x]\n", __func__,
+ attempts);
+
+ attempts--;
+ } else {
+ /*
+ * success
+ */
+ return STATUS_SUCCESS;
+ }
+
+ } while (attempts);
+
+ DBG_ERROR("%s: GAVE UP AFTER SEVERAL ATTEMPTS status[%x]\n",
+ __func__, STATUS_FAILURE);
+
+ /*
+ * Gave up after several attempts
+ */
+ return STATUS_FAILURE;
+}
+
+#endif
+/*=============================================================================
+ =============================================================================
+ === ===
+ === *** END **** END **** END **** END *** ===
+ === SLIC DUMP MANAGEMENT SECTION ===
+ === ===
+ === ===
+ === ===
+ =============================================================================
+ ============================================================================*/
+
+/******************************************************************************/
+/**************** MODULE INITIATION / TERMINATION FUNCTIONS ***************/
+/******************************************************************************/
+
+static struct pci_driver slic_driver = {
+ .name = DRV_NAME,
+ .id_table = slic_pci_tbl,
+ .probe = slic_entry_probe,
+ .remove = slic_entry_remove,
+#if SLIC_POWER_MANAGEMENT_ENABLED
+ .suspend = slicpm_suspend,
+ .resume = slicpm_resume,
+#endif
+/* .shutdown = slic_shutdown, MOOK_INVESTIGATE */
+};
+
+static int __init slic_module_init(void)
+{
+ struct pci_device_id *pcidev;
+ int ret;
+
+/* DBG_MSG("slicoss: %s ENTER cpu %d\n", __func__, smp_processor_id()); */
+
+ slic_init_driver();
+
+ if (debug >= 0 && slic_debug != debug)
+ printk(SLICLEVEL "slicoss: debug level is %d.\n", debug);
+ if (debug >= 0)
+ slic_debug = debug;
+
+ pcidev = (struct pci_device_id *)slic_driver.id_table;
+/* DBG_MSG("slicoss: %s call pci_module_init jiffies[%lx] cpu #%d\n",
+ __func__, jiffies, smp_processor_id()); */
+
+ ret = pci_register_driver(&slic_driver);
+
+/* DBG_MSG("slicoss: %s EXIT after call pci_module_init jiffies[%lx] "
+ "cpu #%d status[%x]\n",__func__, jiffies,
+ smp_processor_id(), ret); */
+
+ return ret;
+}
+
+static void __exit slic_module_cleanup(void)
+{
+/* DBG_MSG("slicoss: %s ENTER\n", __func__); */
+ pci_unregister_driver(&slic_driver);
+ slic_debug_cleanup();
+/* DBG_MSG("slicoss: %s EXIT\n", __func__); */
+}
+
+module_init(slic_module_init);
+module_exit(slic_module_cleanup);
diff --git a/drivers/staging/staging.c b/drivers/staging/staging.c
new file mode 100644
index 00000000000..233e589c093
--- /dev/null
+++ b/drivers/staging/staging.c
@@ -0,0 +1,19 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int __init staging_init(void)
+{
+ return 0;
+}
+
+static void __exit staging_exit(void)
+{
+}
+
+module_init(staging_init);
+module_exit(staging_exit);
+
+MODULE_AUTHOR("Greg Kroah-Hartman");
+MODULE_DESCRIPTION("Staging Core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sxg/Kconfig b/drivers/staging/sxg/Kconfig
new file mode 100644
index 00000000000..1ae35080660
--- /dev/null
+++ b/drivers/staging/sxg/Kconfig
@@ -0,0 +1,10 @@
+config SXG
+ tristate "Alacritech SLIC Technology Non-Accelerated 10Gbe support"
+ depends on PCI && NETDEV_10000
+ default n
+ help
+ This driver supports the Alacritech SLIC Technology Non-Accelerated
+ 10Gbe network cards.
+
+ To compile this driver as a module, choose
+ M here: the module will be called sxg.
diff --git a/drivers/staging/sxg/Makefile b/drivers/staging/sxg/Makefile
new file mode 100644
index 00000000000..ec48faa7b3e
--- /dev/null
+++ b/drivers/staging/sxg/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SXG) += sxg.o
diff --git a/drivers/staging/sxg/README b/drivers/staging/sxg/README
new file mode 100644
index 00000000000..4d1ddbe4c33
--- /dev/null
+++ b/drivers/staging/sxg/README
@@ -0,0 +1,13 @@
+This is the rough cut at a driver for the Alacritech SLIC Technology
+Non-Accelerated 10Gbe network driver.
+
+TODO:
+ - lindent the code
+ - remove typedefs
+ - remove wrappers
+ - checkpatch.pl cleanups
+ - new functionality that the card needs
+
+Please send patches to:
+ Greg Kroah-Hartman <gregkh@suse.de>
+for any cleanups that you do to this driver.
diff --git a/drivers/staging/sxg/saharadbgdownload.h b/drivers/staging/sxg/saharadbgdownload.h
new file mode 100644
index 00000000000..d8865ba0504
--- /dev/null
+++ b/drivers/staging/sxg/saharadbgdownload.h
@@ -0,0 +1,4854 @@
+#define SAHARA_UCODE_VERS_STRING "$Revision: 1.1 $"
+#define SAHARA_UCODE_VERS_DATE "$Date: 2008/06/27 12:58:27 $"
+#define SAHARA_UCODE_HOSTIF_ID 3
+
+static u32 SNumSections = 0x2;
+static u32 SSectionSize[] =
+{
+ 0x0000e274, 0x0000000c,
+};
+
+static u32 SSectionStart[] =
+{
+ 0x00000000, 0x00001fff,
+};
+
+static unsigned char SaharaUCode[2][57972] =
+{
+{
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x4d, 0x29, 0x3a,
+ 0x00, 0x00, 0xb2, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x40, 0x2b, 0x92,
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x98, 0x1e, 0x80, 0xe9, 0x9a,
+ 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x01, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x02, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x02, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x02, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x03, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x03, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x03, 0x92,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x03, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x5f, 0x3f, 0x00, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x42, 0xff, 0xfc, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x80, 0xfd, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x8a, 0x11, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0xfd, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x80, 0xfd, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x01, 0x32,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x84, 0x82, 0x4d, 0x28, 0x1a,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5f, 0x0a, 0xf6, 0x94,
+ 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0e, 0x80, 0x18, 0x92,
+ 0x00, 0x00, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x20, 0x92,
+ 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x21, 0x92,
+ 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x21, 0x92,
+ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x85, 0x21, 0x90,
+ 0x00, 0x00, 0x4b, 0x03, 0x00, 0x00, 0x00, 0xec, 0x02, 0xc0, 0x22, 0x92,
+ 0x00, 0x00, 0x43, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x40, 0x18, 0x9d,
+ 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8b, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x90, 0x72,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x00, 0xe9, 0xb6,
+ 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x1e, 0xc0, 0xe7, 0x9a,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x13, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x08, 0xb8, 0x01, 0x00, 0x94,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb3, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0xb0, 0x03, 0xb2, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x17, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x69, 0x05, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x0a, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0xb2,
+ 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x18, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x57, 0x00, 0x80, 0x01, 0x00, 0x80, 0x12, 0x81, 0xfc, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2b, 0xbc,
+ 0x02, 0x00, 0x57, 0x00, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x5a, 0x00, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc0, 0xb0, 0xbc,
+ 0x00, 0x00, 0x60, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x5c, 0x00, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6,
+ 0x00, 0x00, 0x60, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x34,
+ 0x00, 0x00, 0xfa, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x54, 0x00, 0x03, 0x01, 0x00, 0xb0, 0x02, 0x40, 0x18, 0xbd,
+ 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xa3, 0x40, 0x01, 0x99,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x16, 0x32,
+ 0x00, 0x00, 0x67, 0x00, 0x03, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x80, 0xbd,
+ 0x00, 0x00, 0x76, 0x00, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39,
+ 0x76, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x6b, 0x00, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x22, 0xb2,
+ 0x00, 0x00, 0x65, 0x00, 0x04, 0x01, 0x00, 0x80, 0x82, 0x85, 0x80, 0xbc,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x63, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x8b, 0x80, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xb8, 0xff, 0x85, 0x30,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x21, 0xff, 0x38,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x4d, 0x80, 0x3a,
+ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x0d, 0x80, 0x3a,
+ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x12, 0x80, 0x2d, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x48, 0x41, 0x80, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x86, 0x98, 0x67, 0xc0, 0x82, 0x3a,
+ 0x00, 0x00, 0x63, 0x00, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x62, 0x8b, 0x80, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x12, 0x80, 0x2d, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x08, 0x80, 0x70, 0x32,
+ 0x00, 0x00, 0x7c, 0x00, 0x90, 0x99, 0x86, 0x2c, 0x28, 0xde, 0x82, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x18, 0xc0, 0x82, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x08, 0xc5, 0x82, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc5, 0x82, 0xbc,
+ 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x8b, 0x80, 0x94,
+ 0x08, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x40, 0x01, 0x99,
+ 0x08, 0x00, 0x38, 0x03, 0x0c, 0x00, 0x00, 0xf8, 0x53, 0x40, 0x01, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x3d, 0x32,
+ 0x00, 0x00, 0x7e, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x62, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0x3a, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0x3a, 0x80, 0xbc,
+ 0x00, 0x90, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x0d, 0x80, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32,
+ 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x0d, 0x80, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2,
+ 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x08, 0x00, 0x37, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x08, 0x80, 0x72, 0x32,
+ 0x00, 0x00, 0x96, 0x00, 0x9f, 0x00, 0x00, 0x5c, 0x08, 0x00, 0x72, 0xb2,
+ 0x87, 0x00, 0x95, 0x00, 0x80, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x85, 0xb0,
+ 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd8, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x88, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0x9e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x52, 0x7d, 0x80, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x9a, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x0f, 0x97, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x85, 0xb0,
+ 0x10, 0x00, 0xa5, 0x00, 0x87, 0x00, 0x00, 0x78, 0x79, 0x21, 0x16, 0xb8,
+ 0x01, 0x00, 0xa5, 0x00, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0x87, 0x00, 0xaf, 0x00, 0x87, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0xb0,
+ 0x00, 0x00, 0xa4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x12, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd8, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x88, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0xaf, 0x00, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc0, 0x85, 0xb6,
+ 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x98, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0xad, 0x00, 0x80, 0x01, 0x00, 0x80, 0xd2, 0xc1, 0x82, 0xb6,
+ 0x00, 0x00, 0xaf, 0x00, 0x80, 0x01, 0x00, 0x80, 0x72, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xa8, 0x42, 0x3d, 0x72, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x18, 0x99, 0xb1, 0xf2, 0xc0, 0x7c, 0x30,
+ 0x00, 0x00, 0xd6, 0x00, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0xc1, 0x82, 0xb6,
+ 0x00, 0x00, 0xa9, 0x00, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x80, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x80, 0xc2, 0xcd, 0x85, 0x30,
+ 0x00, 0x00, 0xc6, 0x00, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0x30,
+ 0x80, 0x00, 0xc6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0xa0, 0x00, 0xc6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0x00, 0x00, 0xbd, 0x00, 0x80, 0x01, 0x00, 0x80, 0x62, 0x80, 0xfc, 0xb6,
+ 0x87, 0x00, 0xbd, 0x00, 0x87, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0xb0,
+ 0x00, 0x00, 0xb9, 0x00, 0x04, 0x00, 0x00, 0x80, 0x12, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xbd, 0x00, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xbd, 0x00, 0x80, 0x01, 0x00, 0x80, 0x72, 0xc1, 0x85, 0xb6,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x61, 0x16, 0x38,
+ 0x00, 0x00, 0xc4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xb8, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0x52, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0xc4, 0x00, 0x80, 0x00, 0x00, 0x80, 0x72, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0x02, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0xd2, 0xc1, 0x85, 0xb6,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0xe1, 0x16, 0x38,
+ 0x00, 0x00, 0xc4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xc8, 0xc1, 0x82, 0x94,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x04, 0x32,
+ 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa8, 0xc1, 0x82, 0x94,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x17, 0x38,
+ 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0xd6, 0x00, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x89, 0x8d, 0x72, 0x30,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa9, 0xdc, 0x17, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x90, 0x37,
+ 0x00, 0x00, 0xd6, 0x00, 0x80, 0x00, 0x86, 0x80, 0x22, 0x24, 0x7c, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0xd2, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7,
+ 0x00, 0x00, 0xdd, 0x00, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0xe4, 0x00, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0xe0, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0xc0, 0xf4, 0x00, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x78, 0x09, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x29, 0xc1, 0x72, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0x20, 0x90, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0xc0, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0xff, 0x00, 0x80, 0x01, 0x00, 0x80, 0xa2, 0xc1, 0x82, 0xb6,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x57, 0x00, 0x80, 0x97,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0xa0, 0x04, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x81, 0x80, 0x34,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x45, 0x90, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x12, 0x00, 0x28, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x11, 0x01, 0xf0, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x59, 0xc0, 0x6e, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x78, 0x19, 0xc0, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x4e, 0x04, 0x01, 0xec, 0x06, 0xbd, 0x97, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf4, 0x1e, 0x40, 0xef, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x09, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0xc0, 0x29, 0x37,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x17, 0x3d, 0x90, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0xf4, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x83, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x2b, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x3d, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0xa4, 0x01, 0x80, 0x38, 0x00, 0x80, 0x22, 0xc0, 0x72, 0xb6,
+ 0x00, 0x00, 0x27, 0x01, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0x2c, 0x01, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x85, 0x30,
+ 0x00, 0x00, 0x89, 0x01, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x28, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xcd, 0x85, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x72, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x72, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x52, 0xbd, 0x82, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x30, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x80, 0x82, 0x32,
+ 0x00, 0x00, 0x3d, 0x01, 0x06, 0x00, 0x00, 0x80, 0x62, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x28, 0x80, 0x72, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x64, 0x01, 0x04, 0x38, 0x00, 0x78, 0xd9, 0xc5, 0x72, 0xb0,
+ 0x00, 0x00, 0x41, 0x01, 0x80, 0x01, 0x00, 0x80, 0x02, 0x80, 0x97, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x43, 0x01, 0x80, 0x01, 0x00, 0x80, 0x12, 0x80, 0x97, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x92, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3c, 0xb8, 0x1c, 0x17, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x28, 0xc0, 0x83, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x2c, 0x08, 0xc0, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xb8, 0xe0, 0x83, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x29, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x63, 0x01, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x78, 0xa0, 0x81, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0x3c,
+ 0x00, 0x00, 0x51, 0x01, 0x06, 0x3a, 0x00, 0x80, 0xb2, 0x5c, 0x83, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x89, 0xc1, 0x72, 0x37,
+ 0x07, 0x00, 0x50, 0x01, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x04, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x54, 0x01, 0x00, 0x3a, 0x00, 0x2c, 0x07, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x2c, 0xd7, 0xe0, 0x72, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x64, 0x83, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x73, 0x01, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a,
+ 0x00, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0xd7, 0x10, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0xf4,
+ 0x00, 0x00, 0x61, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc,
+ 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a,
+ 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x19, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32,
+ 0x07, 0x00, 0x66, 0x01, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x02, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0xa7, 0xa0, 0x81, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x73, 0x01, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x60, 0x83, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a,
+ 0x00, 0x00, 0x70, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0xd7, 0x10, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0xf4,
+ 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x09, 0x80, 0x73, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x08, 0x89, 0x80, 0x73, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x86, 0x32,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x8c, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x7f, 0x01, 0x29, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0xb2,
+ 0x00, 0x00, 0x82, 0x01, 0x28, 0x10, 0x00, 0x8c, 0x07, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x83, 0x01, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x8c, 0xf7, 0xe0, 0x82, 0x3a,
+ 0x00, 0x00, 0x82, 0x01, 0x28, 0x18, 0x00, 0x80, 0x07, 0x40, 0x90, 0xb2,
+ 0x00, 0x00, 0x83, 0x01, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x84, 0x27, 0xe4, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x85, 0x30,
+ 0x00, 0x00, 0x87, 0x01, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x83, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2c, 0xb4,
+ 0x00, 0x00, 0x89, 0x01, 0xf2, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x8a, 0x01, 0xf0, 0x01, 0x00, 0x08, 0x38, 0x81, 0x80, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf4, 0x1e, 0x40, 0xef, 0x3c,
+ 0x00, 0x00, 0x93, 0x01, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x3b, 0x32,
+ 0x00, 0x00, 0x8e, 0x01, 0xb9, 0x00, 0x00, 0x78, 0xc9, 0x3b, 0x3a, 0xbc,
+ 0x00, 0x00, 0x92, 0x01, 0x02, 0x00, 0x00, 0x80, 0x82, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0xe2, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0xf0, 0x0e, 0x00, 0x3a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xba, 0x83, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xbd, 0x97, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0xf4, 0xbd,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x97, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0e, 0x80, 0x83, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x22, 0x7a, 0xe8, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xe8, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xc0, 0x29, 0x37,
+ 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0xe8, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0xe8, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x08, 0x80, 0x72, 0x32,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x54, 0xa8, 0x5c, 0x16, 0x38,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x2c, 0xa8, 0xdc, 0x16, 0x38,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x88, 0x4d, 0x85, 0x3a,
+ 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x38, 0x00, 0x14, 0xa9, 0x9c, 0x87, 0xd9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x72, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x30, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x18, 0x80, 0x72, 0xbc,
+ 0x00, 0x00, 0xbb, 0x01, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x78, 0xc0, 0x29, 0x37,
+ 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x88, 0x4d, 0x86, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x77, 0xa0, 0x81, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0xd6, 0x01, 0x04, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xd8, 0x60, 0x86, 0x3a,
+ 0x00, 0x00, 0xca, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0xd2, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xd0, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xcb, 0x01, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0xd4, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a,
+ 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xdc, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xd7, 0x01, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0xe8, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x84, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0x40, 0x85, 0x3a,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x40, 0x88, 0xcd, 0x74, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x28, 0x00, 0x84, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32,
+ 0x14, 0x00, 0xe8, 0x01, 0x04, 0x00, 0x00, 0x1c, 0x88, 0x0d, 0x84, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x61, 0x85, 0x3a,
+ 0x80, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xd8, 0x60, 0x86, 0x3a,
+ 0x00, 0x00, 0xd2, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0xea, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc,
+ 0x00, 0x00, 0xec, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a,
+ 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0xc0, 0x82, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb8, 0x60, 0x85, 0x3c,
+ 0x04, 0x00, 0xf2, 0x01, 0x81, 0x00, 0x00, 0x60, 0x88, 0xcd, 0x74, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0xf8, 0xa0, 0x75, 0x3c,
+ 0x00, 0x00, 0xf3, 0x01, 0x00, 0x08, 0x00, 0x74, 0x08, 0x80, 0x75, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0xf8, 0xa0, 0x75, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x08, 0xa1, 0x82, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xf2, 0x60, 0x2a, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x08, 0x00, 0x75, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x7c, 0x08, 0x80, 0x75, 0x32,
+ 0x09, 0x00, 0xf9, 0x01, 0x04, 0x1a, 0x00, 0x70, 0x88, 0xcd, 0x74, 0xb0,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x4c, 0x87, 0xcd, 0x74, 0x31,
+ 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x88, 0x4d, 0x86, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x40, 0x86, 0x3a,
+ 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x82, 0xd2,
+ 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0x01, 0x02, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2,
+ 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xcd, 0x85, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe8, 0xa1, 0x82, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0xc0, 0x82, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x08, 0xe1, 0x81, 0x3a,
+ 0x00, 0x00, 0x0b, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x58, 0x07, 0x40, 0x87, 0x32,
+ 0x00, 0x00, 0x0a, 0x02, 0x8f, 0x01, 0x00, 0x74, 0x18, 0x40, 0x87, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x0d, 0x02, 0x00, 0x04, 0x00, 0x58, 0xf7, 0xa0, 0x86, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0xa0, 0x86, 0x3a,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x58, 0x87, 0x8d, 0x97, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0x40, 0x85, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x50, 0x07, 0x80, 0x84, 0x32,
+ 0x00, 0x00, 0x11, 0x02, 0x04, 0x01, 0x00, 0x80, 0x72, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x4c, 0xc7, 0xe1, 0x74, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x78, 0xa0, 0x84, 0x3a,
+ 0x00, 0x00, 0x14, 0x02, 0x90, 0x01, 0x00, 0x78, 0xf9, 0xa1, 0x86, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0x80, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x58, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x58, 0xa1, 0x86, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x60, 0x85, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x86, 0x32,
+ 0x00, 0x00, 0x1a, 0x02, 0x12, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x84, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x57, 0x21, 0x80, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x57, 0x61, 0x86, 0x3a,
+ 0x00, 0x00, 0x1f, 0x02, 0x12, 0x00, 0x00, 0x4c, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x80, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0xc0, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x19, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x80, 0x3a,
+ 0x07, 0x00, 0x27, 0x02, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x02, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x77, 0xa0, 0x81, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0x3c,
+ 0x00, 0x00, 0x41, 0x02, 0x04, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x60, 0x83, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a,
+ 0x00, 0x00, 0x32, 0x02, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x00, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x3d, 0x02, 0x06, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x3a, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x34, 0x02, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x35, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x34, 0x02, 0x67, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x35, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0xc0, 0x00, 0x32,
+ 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0x25, 0x02, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x48, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x43, 0x02, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92,
+ 0x00, 0x00, 0x4b, 0x02, 0x04, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x43, 0x02, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x00, 0x00, 0x4f, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x89, 0x80, 0x71, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x71, 0x32,
+ 0x00, 0x00, 0x53, 0x02, 0x90, 0x19, 0x00, 0x04, 0xe9, 0x5c, 0x90, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x19, 0x40, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x80, 0x86, 0x32,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x8c, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x8c, 0x07, 0x40, 0x85, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x07, 0x45, 0x90, 0x30,
+ 0x00, 0x00, 0x5a, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc,
+ 0x00, 0x00, 0x5b, 0x02, 0x00, 0x12, 0x00, 0x84, 0x27, 0xe4, 0x82, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x5f, 0x02, 0x27, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0x5f, 0x02, 0x04, 0x00, 0x00, 0x80, 0x42, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x5b, 0x02, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2c, 0xb4,
+ 0x00, 0x00, 0x64, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x03, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x67, 0x02, 0x04, 0x01, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc,
+ 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2,
+ 0x00, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a,
+ 0x08, 0x00, 0x00, 0x00, 0xc6, 0x01, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x81, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x45, 0x81, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xa4, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x72, 0x02, 0x04, 0x06, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x06, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0xc4, 0x07, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x3a,
+ 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x03, 0xb8, 0x00, 0x00, 0x09, 0xc0, 0x6e, 0xbd,
+ 0x77, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x0d, 0x90, 0x3a,
+ 0x2e, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x2b, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x37, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x38, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x86, 0x02, 0x04, 0x00, 0x00, 0x80, 0x52, 0x40, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x40, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x05, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34,
+ 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x04, 0x01, 0x14, 0x59, 0xc0, 0x6e, 0xd7,
+ 0x02, 0x00, 0x8f, 0x02, 0x04, 0xb8, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc,
+ 0x08, 0x00, 0x8a, 0x11, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0xec, 0x06, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x91, 0x02, 0xb5, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x80, 0xa0, 0x36, 0x0b, 0x6a, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x85, 0x2f, 0x30,
+ 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x81, 0xd2,
+ 0x00, 0x00, 0xa1, 0x02, 0x80, 0x00, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0xb8, 0x00, 0x14, 0x09, 0xc0, 0x6e, 0xd2,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xa4, 0x02, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x02, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2f, 0xb6,
+ 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x20, 0x00, 0x8a, 0x11, 0x04, 0x39, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x00, 0x14, 0x09, 0x00, 0x6e, 0xd2,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x20, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2,
+ 0x1b, 0x00, 0xaf, 0x02, 0x38, 0x01, 0x00, 0x10, 0x09, 0x00, 0x36, 0xb2,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x79, 0x0b, 0x14, 0x38,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x50, 0x01, 0x14, 0xa9, 0x5b, 0x91, 0xd9,
+ 0x00, 0x00, 0xbe, 0x02, 0x38, 0x28, 0x00, 0x18, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0xb6, 0x02, 0x04, 0x21, 0x01, 0x08, 0x69, 0x24, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x03, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xba, 0x02, 0x02, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0xb9, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x04, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x05, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0xbd, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x0a, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x0b, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xc1, 0x02, 0x04, 0x21, 0x01, 0x08, 0x69, 0x24, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x03, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xc3, 0x02, 0x02, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc,
+ 0x04, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xc5, 0x02, 0x9f, 0x31, 0x01, 0x0c, 0x69, 0x24, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc9, 0x02, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0xc8, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x20, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x21, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xcd, 0x02, 0x04, 0x00, 0x00, 0x80, 0x32, 0xa4, 0x90, 0xbc,
+ 0x00, 0x00, 0xcc, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x22, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x23, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xcf, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x20, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x21, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x8a, 0x11, 0x0c, 0x00, 0x00, 0xf8, 0x63, 0x40, 0x01, 0xb9,
+ 0x10, 0x00, 0xd4, 0x02, 0xc5, 0x01, 0x00, 0xcc, 0x02, 0x20, 0x15, 0x98,
+ 0x08, 0x00, 0x38, 0x03, 0x0c, 0x00, 0x00, 0xf8, 0x43, 0x40, 0x01, 0xb9,
+ 0x10, 0x00, 0x00, 0x00, 0xc5, 0x01, 0x00, 0xcc, 0x02, 0x20, 0x15, 0x38,
+ 0x00, 0x00, 0x7e, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x08, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xfa, 0x85, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xfa, 0x85, 0xbc,
+ 0x00, 0x00, 0xdf, 0x02, 0x36, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x0e, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0xa9, 0xdb, 0x85, 0x39,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x8c, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x94, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x98, 0x28, 0x80, 0x6e, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x38, 0x22, 0x14, 0x37,
+ 0x00, 0x00, 0xeb, 0x02, 0x04, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x14, 0x08, 0x80, 0x6e, 0x32,
+ 0x05, 0x00, 0xee, 0x02, 0x00, 0x30, 0x02, 0x00, 0x78, 0xe1, 0x6e, 0x99,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x78, 0x09, 0xc0, 0x6e, 0x32,
+ 0x05, 0x00, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00, 0x77, 0xa1, 0x97, 0x39,
+ 0x00, 0x00, 0xf0, 0x02, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x14, 0x10, 0xf4, 0x02, 0x04, 0x00, 0x00, 0x80, 0xa2, 0x0d, 0x72, 0xb0,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x02, 0xf2,
+ 0x0d, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x09, 0x00, 0x80, 0x52, 0xbd, 0x72, 0xbc,
+ 0x00, 0x00, 0xfb, 0x02, 0x33, 0x15, 0x00, 0xa4, 0x02, 0xc0, 0x72, 0xb2,
+ 0x00, 0x00, 0x33, 0x03, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6,
+ 0x01, 0x01, 0x08, 0x0a, 0x00, 0x28, 0x00, 0x80, 0xc2, 0x0d, 0x74, 0x3c,
+ 0x00, 0x00, 0x33, 0x03, 0x0b, 0x31, 0x00, 0x7c, 0x08, 0x00, 0x75, 0xb2,
+ 0x00, 0x00, 0x33, 0x03, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc,
+ 0x00, 0x00, 0xfc, 0x02, 0x00, 0x38, 0x00, 0x88, 0x18, 0x00, 0x75, 0x9c,
+ 0x00, 0x00, 0x33, 0x03, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x08, 0x00, 0x75, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x08, 0x00, 0x75, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x74, 0x38, 0xa2, 0x75, 0x37,
+ 0x00, 0x00, 0x01, 0x03, 0x83, 0x1b, 0x00, 0x78, 0x08, 0xc0, 0x74, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0xf2, 0x02, 0x80, 0x01, 0x00, 0x80, 0x42, 0x80, 0x87, 0xb6,
+ 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x84, 0xd2,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x87, 0xd2,
+ 0x00, 0x00, 0x15, 0x03, 0x9f, 0x78, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x0a, 0x03, 0x9f, 0x99, 0x01, 0x64, 0x88, 0x1b, 0x87, 0xbc,
+ 0x00, 0x00, 0x16, 0x03, 0x9f, 0x68, 0x01, 0x64, 0x88, 0x5b, 0x86, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0xa4, 0x02, 0xc0, 0x72, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xa4, 0xb2, 0x5b, 0x2a, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x02, 0x78, 0x09, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x17, 0x03, 0x08, 0x01, 0x00, 0x04, 0xe8, 0xa5, 0x75, 0xbc,
+ 0x0f, 0x00, 0x33, 0x03, 0x0b, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2,
+ 0x00, 0x00, 0x15, 0x03, 0x04, 0xa1, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc,
+ 0x00, 0x00, 0x9d, 0x05, 0x9f, 0x98, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x9d, 0x05, 0x06, 0xb1, 0x01, 0x80, 0x82, 0x5b, 0x87, 0xbc,
+ 0x00, 0x00, 0x32, 0x03, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x30, 0x03, 0x02, 0xd4, 0x01, 0x80, 0x92, 0xfb, 0x6e, 0xbc,
+ 0x15, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x16, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x1c, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x28, 0x72, 0x61, 0x80, 0xb9,
+ 0x00, 0x00, 0x1a, 0x03, 0x04, 0xa1, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc,
+ 0x00, 0x00, 0x21, 0x03, 0x06, 0xa8, 0x01, 0x80, 0x82, 0x5b, 0x80, 0xbc,
+ 0x00, 0x00, 0x1e, 0x03, 0x04, 0xa9, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x31, 0x03, 0x04, 0xa9, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc,
+ 0x00, 0x00, 0x31, 0x03, 0x04, 0x01, 0x00, 0x80, 0x12, 0x40, 0x80, 0xbc,
+ 0x13, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x31, 0x03, 0x9f, 0xa0, 0x01, 0x78, 0x29, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x31, 0x03, 0x02, 0x01, 0x00, 0x80, 0x12, 0xa0, 0x97, 0xbc,
+ 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2c, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x27, 0x03, 0x02, 0x00, 0x00, 0x80, 0xa2, 0x60, 0x80, 0xbc,
+ 0x06, 0x00, 0x9d, 0x05, 0x2c, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2,
+ 0x00, 0xc0, 0x29, 0x03, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0,
+ 0x06, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x29, 0x03, 0x04, 0x00, 0x00, 0x80, 0xa2, 0x60, 0x80, 0xbc,
+ 0x09, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x2b, 0x03, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x07, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x02, 0x00, 0x9d, 0x05, 0x38, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2,
+ 0x00, 0x00, 0x2f, 0x03, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0xbc,
+ 0x1f, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x1e, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x01, 0x92,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x92, 0xd2,
+ 0x0d, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xf2,
+ 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x10, 0x00, 0x8a, 0x11, 0x2a, 0x00, 0x00, 0xcc, 0x02, 0x20, 0x15, 0xb8,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2,
+ 0x1d, 0x00, 0x49, 0x03, 0x80, 0x01, 0x00, 0x78, 0x09, 0xe0, 0x00, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x1d, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc,
+ 0x14, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xa8, 0x05, 0x28, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x83, 0x40, 0x01, 0x39,
+ 0x35, 0x00, 0x54, 0x03, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x81, 0xd2,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2,
+ 0x2b, 0x00, 0x9d, 0x05, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x00, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x5a, 0x03, 0x1d, 0x41, 0x02, 0x5c, 0xf8, 0x01, 0x68, 0xb4,
+ 0x41, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x91,
+ 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0xc0, 0x85, 0xd7,
+ 0x10, 0x00, 0x00, 0x00, 0xd0, 0x2c, 0x02, 0x00, 0xa9, 0xdb, 0x85, 0x39,
+ 0x00, 0x00, 0xe1, 0x02, 0x12, 0x01, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x64, 0x03, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2,
+ 0x2f, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x65, 0x03, 0x06, 0xa9, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x70, 0x03, 0x04, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x08, 0x89, 0x9b, 0x90, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x08, 0x89, 0x9b, 0x90, 0x3a,
+ 0x00, 0x00, 0x70, 0x03, 0x9f, 0x88, 0x01, 0x08, 0x89, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x04, 0xf9, 0xba, 0x6e, 0x37,
+ 0x00, 0x00, 0x6c, 0x03, 0x02, 0x00, 0x00, 0x80, 0x12, 0xa4, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x80, 0x90, 0x37,
+ 0x00, 0x00, 0x70, 0x03, 0x02, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x90, 0xbc,
+ 0x30, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x70, 0x03, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x12, 0x70, 0x03, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0,
+ 0x31, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34,
+ 0x08, 0xc0, 0x74, 0x02, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x81, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2,
+ 0x2b, 0x00, 0x9d, 0x05, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x00, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x89, 0x4d, 0x81, 0xd7,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x8a, 0x03, 0x04, 0x20, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x25, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x24, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x93, 0x03, 0x04, 0x01, 0x00, 0xd8, 0x1e, 0x80, 0xed, 0xbc,
+ 0x00, 0x00, 0x8c, 0x03, 0xb7, 0x00, 0x00, 0xd8, 0x0e, 0xc0, 0xed, 0xb2,
+ 0x00, 0x00, 0x8f, 0x03, 0x04, 0x01, 0x00, 0x80, 0x42, 0x3b, 0xee, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1e, 0x00, 0xee, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0xd0, 0x0e, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x93, 0x03, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x93, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x93, 0x03, 0x04, 0x01, 0x00, 0xb0, 0x1e, 0x00, 0xeb, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x86, 0xcc, 0x02, 0x80, 0x6c, 0x32,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x97, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6,
+ 0x35, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x99, 0x03, 0x04, 0x01, 0x00, 0x80, 0x42, 0xc5, 0x2c, 0xbc,
+ 0x00, 0x00, 0x9a, 0x03, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x12, 0xc0, 0x2c, 0x3a,
+ 0x00, 0x00, 0x95, 0x03, 0x04, 0x01, 0x00, 0x00, 0x19, 0x00, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x86, 0xc8, 0x06, 0xc0, 0x2c, 0x32,
+ 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x40, 0x01, 0x99,
+ 0x00, 0x00, 0x9f, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x55, 0x01, 0x80, 0xb2, 0x1b, 0x2b, 0xbc,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa3, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x55, 0x01, 0x80, 0xb2, 0x1b, 0x2b, 0xbc,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xad, 0x03, 0x04, 0x00, 0x00, 0x28, 0x09, 0x80, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0xad, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xb0, 0x03, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39,
+ 0xb0, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xb0, 0x03, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x99,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0f, 0x00, 0x00, 0x32,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc2, 0x03, 0x8b, 0x01, 0x00, 0xa0, 0x12, 0x00, 0x2a, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc5, 0x03, 0x06, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2a, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc8, 0x03, 0x85, 0x01, 0x00, 0x9c, 0x12, 0xc0, 0x29, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0b, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x13, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x06, 0x32,
+ 0x0f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x14, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x18, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x1d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x04, 0x32,
+ 0x1e, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x1f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32,
+ 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x1b, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x1c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x00, 0x32,
+ 0x16, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x1a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x19, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x64, 0x02, 0x39,
+ 0x00, 0x00, 0xfb, 0x03, 0x85, 0x01, 0x00, 0x00, 0x19, 0x00, 0x90, 0xba,
+ 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x32,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf3, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe3, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb3, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa3, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x83, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x63, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x53, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x43, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x33, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x13, 0x40, 0x01, 0x39,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x23, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x80, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f, 0x80, 0xfc, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x32,
+ 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x40, 0x38, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xd2, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x13, 0x04, 0x04, 0x01, 0x00, 0xd0, 0x12, 0x00, 0x2d, 0xbc,
+ 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xe4, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x12, 0x00, 0x2d, 0x3a,
+ 0x4c, 0x00, 0x1a, 0x04, 0x02, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x2d, 0xbc,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xae, 0x0d, 0x02, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x86, 0xcc, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x86, 0xcc, 0x07, 0x80, 0x00, 0x3a,
+ 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x40, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x29, 0x40, 0x90, 0x3a,
+ 0x00, 0x00, 0x26, 0x04, 0x12, 0x00, 0x00, 0x78, 0x09, 0xc0, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x97, 0xb6,
+ 0x1d, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x78, 0xe9, 0xe5, 0x00, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x45, 0x90, 0x30,
+ 0x00, 0x00, 0x24, 0x04, 0x02, 0x01, 0x00, 0x80, 0xc2, 0x82, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x2c, 0x04, 0x8e, 0x01, 0x00, 0x80, 0x02, 0x40, 0x28, 0xb2,
+ 0x00, 0x00, 0x26, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2,
+ 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x36, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x80, 0x97, 0x34,
+ 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32,
+ 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x80, 0x97, 0x34,
+ 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32,
+ 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x3b, 0x04, 0x12, 0x01, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x3b, 0x04, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x3e, 0x04, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x3d, 0x04, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2,
+ 0x02, 0x00, 0x39, 0x04, 0x04, 0x01, 0x00, 0x78, 0x09, 0x24, 0x17, 0xb8,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x64, 0x16, 0x38,
+ 0x00, 0x00, 0x39, 0x04, 0x04, 0x01, 0x00, 0x80, 0x02, 0x81, 0x97, 0xbc,
+ 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x36, 0x32,
+ 0xfe, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x44, 0x04, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x47, 0x04, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x46, 0x04, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x02, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x06, 0x00, 0x59, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x09, 0x64, 0x16, 0x98,
+ 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x97, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92,
+ 0x33, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x11, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x39, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92,
+ 0x5a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x90, 0x3a,
+ 0x0d, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98,
+ 0x0d, 0x00, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98,
+ 0x0d, 0x00, 0x97, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98,
+ 0x00, 0x00, 0xa3, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xad, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d,
+ 0x00, 0x00, 0xb3, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xbd, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc7, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d,
+ 0x00, 0x00, 0xd8, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x92,
+ 0xd8, 0x00, 0xf5, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xdc, 0x0f, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xed, 0x04, 0x00, 0x00, 0x00, 0x78, 0x39, 0x40, 0x90, 0x97,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xec, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0xef, 0x04, 0x00, 0x00, 0x00, 0xe8, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xd4, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x85, 0x05, 0x00, 0x00, 0x00, 0xdc, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x15, 0x05, 0x00, 0x00, 0x00, 0x50, 0x1f, 0x24, 0x16, 0x98,
+ 0x00, 0x00, 0x27, 0x05, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x92,
+ 0x0d, 0x00, 0x32, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98,
+ 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x89, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x45, 0x90, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc,
+ 0x3f, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x00, 0xb0,
+ 0x02, 0x00, 0x80, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x6b, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0xb0, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0xb0, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x34,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39,
+ 0xb0, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x99,
+ 0x00, 0x00, 0x91, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x02, 0x00, 0x91, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x31,
+ 0x00, 0x00, 0x8d, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x2b, 0xbc,
+ 0xf1, 0x0f, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x92,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x02, 0x00, 0x98, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x9b, 0x04, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x1b, 0xe4, 0xb0, 0x32,
+ 0x00, 0x00, 0xb0, 0x03, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa1, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb2,
+ 0x1f, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x80, 0x11, 0x40, 0x00, 0x99,
+ 0x00, 0x00, 0xa0, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc,
+ 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0xfc, 0xb6,
+ 0x00, 0x00, 0xa7, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32,
+ 0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32,
+ 0x0a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xc8, 0x0f, 0x81, 0xfc, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x72, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0xe2, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x00, 0x90, 0x3c,
+ 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb6, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32,
+ 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32,
+ 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x0f, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0xc0, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32,
+ 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0e, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32,
+ 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xac, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0xca, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32,
+ 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32,
+ 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x0f, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x48, 0x0f, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5,
+ 0x00, 0x00, 0xd5, 0x04, 0x04, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x90, 0x32,
+ 0x12, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x40, 0x90, 0x9c,
+ 0x00, 0x00, 0xdb, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32,
+ 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32,
+ 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5,
+ 0x00, 0x00, 0xe5, 0x04, 0x04, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x90, 0x32,
+ 0x11, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0x40, 0x90, 0x9c,
+ 0x00, 0x00, 0xeb, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x0e, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x88, 0x0e, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x40, 0x90, 0x37,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xa4, 0x97, 0x9a,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xbc, 0x0e, 0x80, 0xee, 0x9d,
+ 0x00, 0x00, 0xf2, 0x04, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0x00, 0x32,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x1e, 0x40, 0x90, 0x9c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x90, 0x37,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x86, 0xc0, 0x07, 0x40, 0x90, 0x92,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x38,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xfa, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x24, 0xf6, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f, 0x80, 0xfc, 0x34,
+ 0x40, 0x80, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0f, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x79, 0x01, 0x00, 0x34,
+ 0x02, 0x00, 0xfc, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32,
+ 0x1f, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x40, 0x00, 0x99,
+ 0xea, 0x05, 0x05, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x0f, 0x00, 0x15, 0x32,
+ 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x37, 0x32,
+ 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x36, 0x32,
+ 0x98, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x0b, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x4f, 0x80, 0xfc, 0x95,
+ 0x36, 0x23, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x0f, 0x80, 0x14, 0x32,
+ 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x37, 0x32,
+ 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x36, 0x32,
+ 0x98, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x4f, 0x80, 0xfc, 0x34,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x8f, 0x4d, 0x90, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x60, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x7a, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa9, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x12, 0x05, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6f, 0x80, 0xfc, 0x34,
+ 0x00, 0x00, 0x14, 0x05, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0x90, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x5f, 0x80, 0xfc, 0x34,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x17, 0x05, 0x04, 0x01, 0x00, 0x80, 0x32, 0x40, 0x90, 0xb0,
+ 0x80, 0x01, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x8d, 0xfc, 0x91,
+ 0x00, 0x00, 0x19, 0x05, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0x90, 0xb6,
+ 0x00, 0x00, 0x1a, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x7f, 0x80, 0xfc, 0x95,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7f, 0x80, 0xfc, 0x34,
+ 0x00, 0x00, 0x1c, 0x05, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb6,
+ 0x00, 0x00, 0x1d, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x80, 0xfc, 0x95,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x80, 0xfc, 0x34,
+ 0x00, 0x00, 0x20, 0x05, 0x80, 0x00, 0x00, 0x80, 0x22, 0x40, 0x90, 0xb6,
+ 0xf1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x22, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x1f, 0x81, 0xfc, 0x95,
+ 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x1f, 0x81, 0xfc, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x02, 0xf5, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x03, 0x00, 0x00, 0x78, 0x09, 0x00, 0xf5, 0xbd,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xe2, 0x25, 0xf5, 0xb5,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x1f, 0x24, 0x16, 0x38,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x50, 0x1f, 0x00, 0xf5, 0x9c,
+ 0x80, 0x01, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0xfc, 0xb0,
+ 0x00, 0x00, 0x2b, 0x05, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0xf5, 0x3a,
+ 0x8c, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x80, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xec, 0x03, 0x40, 0x90, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc,
+ 0x00, 0x00, 0x34, 0x05, 0xb2, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xe4, 0x6e, 0x3a,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x69, 0x05, 0x17, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0xb2,
+ 0x06, 0x00, 0x3f, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x32,
+ 0x00, 0xc0, 0xd3, 0x0e, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x46, 0x05, 0x04, 0x19, 0x86, 0x80, 0x02, 0x80, 0x6c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x12, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc1, 0x08, 0x00, 0x04, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x15, 0x86, 0x2c, 0x09, 0xc0, 0x6c, 0x32,
+ 0x00, 0x00, 0x4c, 0x05, 0x22, 0x1d, 0x86, 0xc8, 0x06, 0xc0, 0x92, 0xb2,
+ 0x00, 0x00, 0x4c, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc2, 0x48, 0x00, 0x04, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x16, 0x86, 0x2c, 0x09, 0xc0, 0x6c, 0x32,
+ 0x00, 0x00, 0x4c, 0x05, 0x21, 0x1d, 0x86, 0xc8, 0x06, 0xc0, 0x92, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x54, 0x05, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xd3, 0x0e, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xdc,
+ 0x00, 0x00, 0x52, 0x05, 0x80, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x54, 0x05, 0x81, 0x00, 0x00, 0xf8, 0x22, 0x80, 0x2f, 0xb4,
+ 0x00, 0x00, 0x54, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x54, 0x05, 0x82, 0x00, 0x00, 0xf8, 0x12, 0x80, 0x2f, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x0a, 0x32,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0xc0, 0x69, 0x05, 0x18, 0x00, 0x00, 0x00, 0xa9, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x86, 0x04, 0x19, 0x80, 0x6c, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x01, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x0c, 0xf7, 0x7f, 0x90, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x86, 0x80, 0x72, 0x82, 0x6c, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xa8, 0x42, 0x80, 0x6c, 0x37,
+ 0x00, 0x00, 0x78, 0x05, 0x12, 0x00, 0x70, 0x38, 0x02, 0x00, 0x7c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3c, 0x02, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x30, 0x02, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x34, 0x02, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x6b, 0x05, 0x02, 0x01, 0x00, 0x80, 0xb2, 0x82, 0x2a, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32,
+ 0x06, 0x00, 0x3f, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x00, 0x00, 0x39, 0x05, 0x04, 0x03, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x80, 0x2f, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0xa2, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x7a, 0x05, 0x04, 0x03, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x83, 0x05, 0x00, 0x10, 0x86, 0xc8, 0x46, 0x80, 0x2a, 0x96,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xc8, 0x46, 0x80, 0x2a, 0x36,
+ 0x00, 0x00, 0x7e, 0x05, 0x80, 0x00, 0x00, 0x80, 0x12, 0x80, 0x2f, 0xb6,
+ 0x03, 0x00, 0x80, 0x05, 0x22, 0x00, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb2,
+ 0x00, 0x00, 0x80, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x83, 0x05, 0x80, 0x00, 0x00, 0x80, 0x22, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35,
+ 0x00, 0xc0, 0xd3, 0x0e, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3c,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x80, 0x2f, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0xa2, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x05, 0x04, 0x01, 0x00, 0x80, 0xa2, 0xc0, 0xed, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0e, 0x80, 0x02, 0x32,
+ 0x40, 0x7e, 0x05, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0e, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x0e, 0x80, 0x07, 0x32,
+ 0x64, 0x00, 0x8f, 0x05, 0x00, 0x00, 0x00, 0xcc, 0x0e, 0x00, 0x36, 0x92,
+ 0x64, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xed, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0e, 0x40, 0x00, 0x32,
+ 0xa0, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0e, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x0e, 0xc0, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0e, 0x80, 0x02, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x33, 0x7b, 0xec, 0x39,
+ 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6e, 0xc0, 0xec, 0x37,
+ 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xd8, 0x0e, 0xc0, 0xed, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x1c, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xbc,
+ 0x2b, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x3d, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x35, 0x00, 0x9c, 0x05, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x89, 0xcd, 0x81, 0x3c,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x1c, 0x01, 0x14, 0x59, 0xe4, 0x6e, 0xd9,
+ 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x81, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x18, 0x01, 0x80, 0x92, 0xc0, 0x6e, 0xbc,
+ 0x2b, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x18, 0x01, 0x14, 0x79, 0xe0, 0x6e, 0xd9,
+ 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x81, 0x3a,
+ 0xe1, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xea, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xf3, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xfc, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x05, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x0e, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x17, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x20, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x29, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x32, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x3b, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x44, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x4d, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x56, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x5f, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x68, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x71, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x7a, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x83, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x8c, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x95, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x9e, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xa7, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xb0, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xb9, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xc2, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xcb, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xd4, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xdd, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xe6, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xef, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0xf8, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x01, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x0a, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x13, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x1c, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x25, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x2e, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x37, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x40, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x49, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x00, 0x00, 0x57, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x52, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x57, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x5c, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x61, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x66, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x6b, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x70, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x75, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x7a, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x7f, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x84, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x89, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x8e, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x93, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x98, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x9d, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a,
+ 0x00, 0x00, 0x5f, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x71, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x3b, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x79, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x86, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7d, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7d, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xb8, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x86, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x01, 0x92,
+ 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x47, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xa3, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x02, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8f, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xa0, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xa0, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xcc, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x02, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x31, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xab, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf3, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xb4, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe5, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xe8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92,
+ 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2e, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x22, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0x22, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xef, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92,
+ 0x00, 0x00, 0xef, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92,
+ 0x08, 0x00, 0xa1, 0x03, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99,
+ 0x08, 0x00, 0x9d, 0x03, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x08, 0x00, 0xa7, 0x07, 0x1d, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xa1, 0x03, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94,
+ 0x08, 0x00, 0xa1, 0x03, 0x00, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x0f, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x35,
+ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0xb4, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37,
+ 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0xb7, 0x07, 0xb7, 0x10, 0x02, 0xe0, 0x06, 0x80, 0x97, 0xb2,
+ 0x00, 0x00, 0xba, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0xbb, 0x07, 0x00, 0x00, 0x00, 0xc8, 0xff, 0x80, 0xfc, 0x94,
+ 0x00, 0x00, 0xbc, 0x07, 0x9f, 0x99, 0x00, 0x80, 0x82, 0x1b, 0xee, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0xe0, 0x0e, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x1c, 0x09, 0x00, 0x6e, 0x32,
+ 0x40, 0x00, 0xc1, 0x07, 0x06, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x91, 0xbc,
+ 0x00, 0x40, 0xc2, 0x07, 0x00, 0x18, 0x02, 0xe0, 0xa6, 0xcd, 0x2c, 0x92,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x18, 0x02, 0xe0, 0xa6, 0xcd, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x80, 0x03, 0x32,
+ 0x00, 0x00, 0xc5, 0x07, 0x80, 0xd7, 0x01, 0x80, 0x32, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0x00, 0x92, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x18, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x24, 0x09, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x28, 0x09, 0x80, 0x6e, 0x32,
+ 0x00, 0x00, 0xd3, 0x07, 0x80, 0x0e, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xb6,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xec, 0x06, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x01, 0x92, 0x3a,
+ 0x00, 0x00, 0xcf, 0x07, 0x80, 0xd6, 0x01, 0x80, 0x42, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32,
+ 0x00, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32,
+ 0x28, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x1c, 0xd9, 0xc1, 0x91, 0x34,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32,
+ 0x00, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32,
+ 0x34, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xec, 0x06, 0x00, 0x36, 0x32,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x92, 0x3a,
+ 0x00, 0x00, 0xd9, 0x07, 0x80, 0xd6, 0x01, 0x80, 0x42, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x86, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32,
+ 0x04, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32,
+ 0x14, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x1c, 0xd9, 0xc1, 0x91, 0x34,
+ 0x00, 0x86, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32,
+ 0x04, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32,
+ 0x20, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0xec, 0x86, 0xcd, 0x91, 0x3a,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0xe8, 0x86, 0x24, 0x90, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0xe0, 0x96, 0x24, 0x14, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x80, 0x91, 0x32,
+ 0x00, 0x00, 0xe3, 0x07, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0x00, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xc9, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0xec, 0x06, 0x80, 0x83, 0x32,
+ 0x01, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0xf9, 0x07, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x2c, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xff, 0x07, 0x80, 0xd7, 0x01, 0x2c, 0x09, 0xc0, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x01, 0xec, 0x06, 0x40, 0xed, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32,
+ 0x00, 0x00, 0x02, 0x08, 0x80, 0x01, 0x00, 0x80, 0x62, 0xc0, 0x92, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xaa, 0x07, 0x04, 0x06, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xaa, 0x07, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34,
+ 0x3b, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x0f, 0x08, 0x12, 0x01, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x1e, 0x08, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x12, 0x08, 0x12, 0x01, 0x00, 0x60, 0x02, 0x80, 0x2c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x14, 0x08, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a,
+ 0x00, 0x00, 0x17, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0xaa, 0x07, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6,
+ 0x3b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x14, 0x08, 0x80, 0x6e, 0x32,
+ 0x00, 0x00, 0x12, 0x08, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0x10, 0x08, 0x12, 0x00, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x78, 0xe1, 0x6e, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78, 0xca, 0xe9, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x32,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c,
+ 0x00, 0x00, 0x82, 0x08, 0x04, 0xb0, 0x00, 0xe0, 0xd6, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x50, 0x08, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0x34, 0x08, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe0, 0x38, 0xb2,
+ 0x00, 0x00, 0x41, 0x08, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2,
+ 0x00, 0x00, 0x39, 0x08, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x5c, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x3b, 0x08, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x3f, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x3a, 0x08, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x46, 0x08, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba,
+ 0x00, 0x00, 0x45, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0xe0, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xf0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x81, 0x83, 0x35,
+ 0x00, 0x00, 0x28, 0x08, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35,
+ 0x08, 0xa0, 0x28, 0x08, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2,
+ 0x00, 0x00, 0x58, 0x08, 0x28, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba,
+ 0x00, 0x00, 0x5b, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x58, 0x08, 0x1d, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0x58, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x5c, 0x08, 0x04, 0xa0, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x6e, 0x08, 0x00, 0x98, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x92,
+ 0x00, 0x00, 0x62, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x5f, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x62, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x5e, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xe0, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0xe8, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xf0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x6a, 0x08, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35,
+ 0x08, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0x74, 0x08, 0x2a, 0x5d, 0x01, 0xec, 0x06, 0x80, 0xee, 0xb2,
+ 0x00, 0x00, 0x71, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x74, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94,
+ 0x10, 0x04, 0x77, 0x08, 0x37, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0xb1,
+ 0x3b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34,
+ 0x08, 0x00, 0x00, 0x00, 0xca, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x7d, 0x08, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x7c, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xc2, 0x00, 0x03, 0xbc,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x67, 0xa1, 0x73, 0x39,
+ 0x30, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xd2, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x2a, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0xb4,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x8a, 0x08, 0x1d, 0x00, 0x00, 0x38, 0x18, 0x81, 0x83, 0xb5,
+ 0x00, 0x00, 0x8a, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x8d, 0x08, 0x04, 0x06, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34,
+ 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2,
+ 0x00, 0x00, 0x90, 0x08, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x5c, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x92, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xae, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x95, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x35,
+ 0x00, 0x00, 0xac, 0x08, 0x04, 0x00, 0x00, 0x80, 0x02, 0x61, 0x80, 0xbc,
+ 0x00, 0x00, 0xa4, 0x08, 0x80, 0xb8, 0x00, 0x00, 0x09, 0xc0, 0x6e, 0xb2,
+ 0x40, 0x00, 0x9c, 0x08, 0x04, 0x00, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc,
+ 0x80, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc,
+ 0x00, 0x00, 0x9c, 0x08, 0x02, 0xb0, 0x00, 0x80, 0x82, 0x1b, 0x84, 0xbc,
+ 0x00, 0x00, 0xa4, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0xd6, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x56, 0xc0, 0x6e, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x86, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb7, 0x01, 0x78, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0xe0, 0x06, 0x00, 0x86, 0x32,
+ 0x40, 0x00, 0xae, 0x08, 0x04, 0x00, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xfa,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x00, 0x00, 0x3c, 0x18, 0x20, 0x84, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xb0, 0x00, 0x3c, 0x88, 0xdb, 0x83, 0xbe,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x01, 0x78, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf7, 0x20, 0x78, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x78, 0x01, 0xe0, 0xf6, 0x20, 0x86, 0x3a,
+ 0x00, 0x00, 0x25, 0x08, 0x00, 0x00, 0x00, 0x04, 0xf8, 0x60, 0x80, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6,
+ 0x2e, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xc2, 0x00, 0x03, 0xbc,
+ 0x10, 0x00, 0x00, 0x00, 0xd4, 0x18, 0x00, 0x80, 0x67, 0xa1, 0x73, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32,
+ 0x30, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xb8, 0x08, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xbb, 0x08, 0x00, 0xd0, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0xbb, 0x08, 0x04, 0xd1, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x26, 0xc0, 0x6e, 0x34,
+ 0x00, 0x00, 0xbd, 0x08, 0x80, 0x00, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc0, 0x08, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x92, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0xc0, 0x08, 0x04, 0xc9, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x34,
+ 0x10, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x9a, 0x01, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0xaa, 0x07, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0xc7, 0x08, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x9a,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x97, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x0c, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x77, 0x10, 0x00, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xd4, 0x08, 0x23, 0x29, 0x02, 0x04, 0x09, 0x80, 0x6e, 0xb2,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x08, 0x00, 0xd8, 0x08, 0x1d, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9,
+ 0x00, 0x00, 0xd8, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xdc, 0x08, 0x9d, 0x01, 0x00, 0x80, 0x07, 0xc0, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x07, 0xc0, 0x91, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x80, 0x07, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x07, 0x40, 0x90, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x87, 0x8d, 0x85, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x80, 0x07, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0xe3, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x30, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x12, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x78, 0x09, 0x80, 0x6e, 0x32,
+ 0x00, 0x00, 0xaa, 0x07, 0xdc, 0xd1, 0x01, 0xe8, 0x06, 0x80, 0x97, 0x92,
+ 0x12, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x18, 0x09, 0x40, 0x81, 0xf2,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x80, 0x2f, 0xb6,
+ 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0xaa, 0x07, 0x35, 0x01, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0xf6, 0x08, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x47, 0x10, 0x00, 0x98, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xff, 0x08, 0x80, 0x00, 0x00, 0x80, 0x42, 0x81, 0x2f, 0xb6,
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x2f, 0xd2,
+ 0x00, 0x00, 0xff, 0x08, 0x08, 0x5b, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x34, 0x00, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0x32,
+ 0x00, 0x00, 0x06, 0x09, 0x80, 0x01, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x0d, 0x09, 0x08, 0xc9, 0x01, 0xe8, 0x06, 0xbb, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x32, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x01, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0d, 0x09, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x0d, 0x09, 0x08, 0xd1, 0x01, 0xe8, 0x06, 0xbb, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x32, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x01, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x17, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x13, 0x09, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2,
+ 0x00, 0x00, 0x16, 0x09, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a,
+ 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x97, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xdb, 0x79, 0x01, 0x60, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x5c, 0x10, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32,
+ 0x00, 0x00, 0x1f, 0x09, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xaa, 0x07, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x9f, 0x41, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x2d, 0x09, 0x9f, 0x98, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0x2b, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0xaa, 0x07, 0x31, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0x34,
+ 0x3a, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x47, 0x10, 0x00, 0x98, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0xd5, 0x41, 0x01, 0xe0, 0x06, 0x40, 0x81, 0x92,
+ 0x00, 0x00, 0xaa, 0x07, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x78, 0x09, 0x80, 0x6e, 0x32,
+ 0x00, 0x00, 0x35, 0x09, 0x04, 0xd4, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0x80, 0x97, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0xe6, 0x25, 0x6e, 0x3a,
+ 0x00, 0x00, 0x60, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xaa, 0x07, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x00, 0x80, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32,
+ 0x02, 0x00, 0x3f, 0x09, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc,
+ 0x00, 0x00, 0x41, 0x09, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x41, 0x09, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0xfc, 0xb6,
+ 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf5, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x42, 0xbd, 0x97, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x99, 0xb1, 0xf2, 0xc0, 0x7c, 0x30,
+ 0x00, 0xc0, 0x48, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa2, 0x00, 0x2d, 0x37,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x99, 0xe1, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x4d, 0x09, 0x04, 0x01, 0x00, 0x78, 0x19, 0x80, 0x97, 0xbc,
+ 0x02, 0x00, 0x59, 0x09, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x48, 0xd6, 0x01, 0x00, 0x78, 0xc9, 0xcd, 0x2c, 0x32,
+ 0x00, 0x00, 0x51, 0x09, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x80, 0x97, 0xb2,
+ 0x00, 0x00, 0x53, 0x09, 0x12, 0x08, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x54, 0x09, 0x12, 0x18, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x55, 0x09, 0x12, 0x10, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xa6, 0x54, 0x01, 0xec, 0x06, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x94,
+ 0x00, 0x20, 0x00, 0x4c, 0xd6, 0x01, 0x00, 0x78, 0xc9, 0xcd, 0x2c, 0x32,
+ 0x00, 0x00, 0x5a, 0x09, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x80, 0x97, 0xb2,
+ 0x00, 0x00, 0x5c, 0x09, 0x12, 0x08, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x5d, 0x09, 0x12, 0x30, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x5e, 0x09, 0x12, 0x38, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x5f, 0x09, 0x12, 0x40, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x60, 0x09, 0x12, 0x48, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x61, 0x09, 0x12, 0x10, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x62, 0x09, 0x12, 0x18, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x63, 0x09, 0x12, 0x20, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x64, 0x09, 0x12, 0x28, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xa6, 0x54, 0x01, 0xec, 0x06, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32,
+ 0x03, 0x00, 0xa2, 0x07, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0x6b, 0x09, 0x00, 0x00, 0x00, 0x14, 0x08, 0x80, 0x3d, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32,
+ 0x00, 0x00, 0x6e, 0x09, 0x04, 0x00, 0x00, 0xdc, 0x53, 0x60, 0x3d, 0xb3,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39,
+ 0x6a, 0x09, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x74, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x14, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x10, 0x00, 0x82, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0xa2, 0x07, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6,
+ 0x2c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x7d, 0x09, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x29, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x23, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x3c, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x8c, 0x09, 0x38, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2,
+ 0x00, 0x00, 0x8c, 0x09, 0x1e, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8f, 0x09, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x00, 0x82, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0xc0, 0x99, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2,
+ 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x01, 0x0e, 0x00, 0x30, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xfa,
+ 0x00, 0x00, 0xa2, 0x09, 0x38, 0x01, 0x00, 0x2c, 0xf8, 0x01, 0x0b, 0xb4,
+ 0x00, 0x00, 0xa2, 0x09, 0x02, 0x0d, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xc8, 0xc1, 0x82, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xa7, 0x09, 0x27, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x2c, 0xe8, 0xc0, 0x82, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0xd5, 0x40, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32,
+ 0x08, 0x00, 0xb0, 0x10, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xf9,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xab, 0x09, 0x23, 0x19, 0x00, 0x00, 0x07, 0x80, 0x81, 0xb2,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xad, 0x09, 0x1d, 0x21, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0xb0, 0x09, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xb0, 0x09, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x80, 0x2d, 0xbc,
+ 0x10, 0x00, 0xb6, 0x09, 0x2c, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0xb9,
+ 0x00, 0x00, 0xb8, 0x09, 0x8e, 0x39, 0x00, 0x00, 0x07, 0xc0, 0x82, 0xb2,
+ 0x00, 0x00, 0xb8, 0x09, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x92,
+ 0x00, 0x00, 0xb8, 0x09, 0x8e, 0x39, 0x00, 0x00, 0xb7, 0xc1, 0x82, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x32,
+ 0x00, 0x00, 0xba, 0x09, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xc0, 0x09, 0x04, 0x01, 0x00, 0x80, 0x12, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0xb8, 0x09, 0x9f, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc8, 0x09, 0x1e, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xa4, 0x07, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0xce, 0x09, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x1c, 0x40, 0x02, 0x80, 0x06, 0xc0, 0x85, 0xb2,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x2c, 0x10, 0xd6, 0x01, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2,
+ 0x00, 0x00, 0xa1, 0x03, 0xd2, 0x01, 0x00, 0x94, 0x1e, 0x40, 0xe9, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xee, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x51, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x21, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0xe4, 0x09, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xe1, 0x09, 0x9e, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa4, 0x07, 0x2a, 0x31, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xb2,
+ 0x18, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39,
+ 0xa4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x0c, 0x00, 0xeb, 0x09, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0xeb, 0x09, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x00, 0x92,
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xee, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x25, 0x0a, 0x38, 0x00, 0x00, 0xa4, 0x08, 0x80, 0x82, 0xb2,
+ 0x00, 0x00, 0x25, 0x0a, 0x04, 0x28, 0x01, 0x04, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x01, 0x04, 0xa8, 0x5b, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x20, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x0a, 0x0a, 0x08, 0x01, 0x00, 0x28, 0x18, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0xa6, 0x20, 0x00, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0xfb, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x20, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x3d, 0x00, 0x0c, 0x07, 0x80, 0x83, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x08, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a,
+ 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x66, 0x0a, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x6c, 0x18, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x38, 0x01, 0xe0, 0x06, 0x40, 0x80, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x6c, 0x18, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x11, 0x0a, 0x9f, 0x01, 0x00, 0x04, 0x68, 0x60, 0x80, 0xbc,
+ 0x00, 0x00, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x18, 0x20, 0x00, 0x9c,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x14, 0x0a, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x00, 0x18, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x0d, 0x0a, 0x02, 0x01, 0x00, 0x80, 0x62, 0x60, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35,
+ 0x00, 0xa0, 0x0d, 0x0a, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x1f, 0x0a, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x1f, 0x0a, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xa0, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35,
+ 0x00, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x80, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x27, 0x0a, 0x00, 0x18, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x2a, 0x0a, 0x00, 0x50, 0x01, 0x3c, 0xa8, 0x5b, 0x80, 0x9c,
+ 0x00, 0x00, 0xa4, 0x07, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x2f, 0x0a, 0x3e, 0x51, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0xf8, 0xf2, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32,
+ 0x00, 0x00, 0x2f, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x4c, 0x0f, 0x60, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x7b, 0x0a, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x3a, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x0f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0xc0, 0x3e, 0x0a, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x0f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc,
+ 0x00, 0x00, 0x42, 0x0a, 0x2f, 0x20, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x4a, 0x0a, 0x1f, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x45, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x83, 0xbc,
+ 0x00, 0x00, 0x4a, 0x0a, 0x00, 0x50, 0x01, 0xe8, 0xf6, 0x60, 0x80, 0x9c,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x4f, 0x0a, 0x2a, 0xa9, 0x01, 0xe0, 0x06, 0x00, 0x92, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x4f, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x4b, 0x0a, 0x04, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x52, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32,
+ 0x00, 0xc0, 0x61, 0x0a, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x18, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x82, 0xb6,
+ 0x00, 0x00, 0x58, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x18, 0x00, 0x5a, 0x0a, 0x2e, 0x49, 0x01, 0xe0, 0xe6, 0xa0, 0x82, 0xb9,
+ 0x00, 0x00, 0x5b, 0x0a, 0x00, 0x5e, 0x01, 0xec, 0x76, 0x00, 0x00, 0x94,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x20, 0x80, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x1b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x0c, 0x00, 0xa1, 0x03, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x85, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x9e, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x80, 0x85, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6,
+ 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x67, 0x0a, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x6e, 0x0a, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0x6e, 0x0a, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x72, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0x2f, 0xb6,
+ 0x2a, 0x00, 0x78, 0x0a, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x75, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x78, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x78, 0x0a, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xa2, 0x07, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x85, 0xbc,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x9e, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x80, 0x85, 0x92,
+ 0x00, 0x00, 0xa4, 0x07, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x80, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x12, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xce, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x86, 0x0a, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8f, 0x0a, 0x3f, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0xb2,
+ 0x00, 0x00, 0x8f, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0xf8, 0xf2, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0xda, 0x0a, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c,
+ 0x00, 0x00, 0xb0, 0x0a, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0x9b, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0xae, 0x0a, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0xa7, 0x0a, 0x28, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0xa5, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xa1, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xa5, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0xa5, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xa3, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x16, 0x20, 0x6e, 0x3c,
+ 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xac, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xa7, 0x0a, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xfa,
+ 0x00, 0x00, 0x90, 0x0a, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0xbc, 0x0a, 0x28, 0x00, 0x00, 0x80, 0x08, 0x40, 0x00, 0xb2,
+ 0x00, 0x00, 0xba, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xb6, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xba, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0xba, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xb8, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x16, 0x20, 0x6e, 0x3c,
+ 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2,
+ 0x00, 0x00, 0xe0, 0x0a, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc0, 0x0a, 0x04, 0x21, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0xc6, 0x0a, 0x2a, 0x11, 0x00, 0xe0, 0xd6, 0xe0, 0x86, 0xba,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0xc6, 0x0a, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xc2, 0x0a, 0x9f, 0x01, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x08, 0x00, 0xca, 0x0a, 0x23, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xce, 0x0a, 0x1d, 0x18, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0xb2,
+ 0x00, 0x00, 0xce, 0x0a, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xd3, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0xd2, 0x0a, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x19, 0x20, 0x6e, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xe2, 0xa5, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0xe4, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0xe5, 0x0a, 0xc9, 0x01, 0x00, 0x14, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xef, 0x0a, 0x28, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xee, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xea, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xee, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0xee, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xec, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2,
+ 0x00, 0x20, 0x00, 0x80, 0xdf, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xf3, 0x0a, 0x3d, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2,
+ 0x00, 0x00, 0xf3, 0x0a, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x81, 0x2f, 0xf5,
+ 0x08, 0x00, 0xb0, 0x10, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xf9,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xf8, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xfd, 0x0a, 0x29, 0x08, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0xb2,
+ 0x00, 0x00, 0x02, 0x0b, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x02, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0xff, 0x0a, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x01, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xfe, 0x0a, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x9c,
+ 0x2a, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x05, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x12, 0xa0, 0x82, 0xbc,
+ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0xa9, 0x60, 0x80, 0xd9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x15, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x20, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x60, 0x80, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x08, 0x80, 0x82, 0xf2,
+ 0x00, 0x00, 0x21, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x20, 0x80, 0x3a,
+ 0x00, 0x00, 0x26, 0x0b, 0x04, 0x00, 0x00, 0x28, 0x68, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x81, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x2e, 0x0b, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0x2e, 0x0b, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x04, 0x08, 0x80, 0x86, 0xb2,
+ 0x00, 0x00, 0x3c, 0x0b, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x28, 0x09, 0x80, 0x80, 0xb2,
+ 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0x34, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x3a, 0x10, 0x00, 0x00, 0x00, 0x78, 0x38, 0x80, 0x87, 0xf5,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0xa5, 0x02, 0x23, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x32, 0x80, 0x2f, 0x35,
+ 0x3c, 0x00, 0xa5, 0x02, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x3f, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x41, 0x0b, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x00, 0x82, 0x4b, 0x0b, 0x00, 0x00, 0x00, 0x08, 0xa8, 0x8d, 0x80, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x5c, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa8, 0x8d, 0x80, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2,
+ 0x00, 0x00, 0x53, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x4f, 0x0b, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x53, 0x0b, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x53, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x51, 0x0b, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a,
+ 0x00, 0x00, 0xa4, 0x07, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x39, 0x10, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39,
+ 0x00, 0x10, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x6a, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xc3, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x6e, 0x0b, 0x1d, 0x21, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x71, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x71, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x74, 0x0b, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0xa4, 0x03, 0xca, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x7e, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x7a, 0x0b, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x7e, 0x0b, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x7e, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x7c, 0x0b, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x80, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x86, 0xbc,
+ 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x87, 0x0b, 0x33, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2,
+ 0x00, 0x00, 0x87, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6,
+ 0x00, 0x00, 0x87, 0x0b, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc,
+ 0x00, 0x00, 0x87, 0x0b, 0x9f, 0xf8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xe0, 0x06, 0xc0, 0x87, 0x32,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39,
+ 0x00, 0x00, 0x8d, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8d, 0x0b, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34,
+ 0x3b, 0x00, 0x8d, 0x0b, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x9d, 0x0b, 0x27, 0x09, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0xb2,
+ 0x00, 0xc0, 0x95, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x20, 0x80, 0xa4, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x92,
+ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x98, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x40, 0x88, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x40, 0x88, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x40, 0x00, 0x80, 0xca, 0x39, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0xa1, 0x0b, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa1, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0xae, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xee, 0x10, 0x00, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x08, 0x80, 0x82, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xb6, 0x0b, 0x00, 0x50, 0x01, 0x3c, 0xa8, 0x5b, 0x80, 0x9c,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0xee, 0x0b, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c,
+ 0x00, 0x00, 0xd4, 0x0b, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0xc5, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0xcd, 0x0b, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xcb, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc6, 0x0b, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xd2, 0x0b, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba,
+ 0x00, 0x00, 0xd1, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xba, 0x0b, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0xdb, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xd5, 0x0b, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8,
+ 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba,
+ 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0xe6, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb9, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0xec, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xeb, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xba, 0x0b, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0xf6, 0x0b, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a,
+ 0x00, 0xc0, 0xf7, 0x0b, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc,
+ 0x00, 0x00, 0xfb, 0x0b, 0x2f, 0x20, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xff, 0x0b, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0xfe, 0x0b, 0x9f, 0x31, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x07, 0x0c, 0x00, 0x50, 0x01, 0xe8, 0xf6, 0x60, 0x80, 0x9c,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x06, 0x0c, 0x9f, 0x31, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x06, 0x00, 0x92, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x0c, 0x0c, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x08, 0x0c, 0x04, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x14, 0x0c, 0x23, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xba,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x1c, 0x0c, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0x1c, 0x0c, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x20, 0x0c, 0x29, 0x31, 0x01, 0x0c, 0x09, 0x00, 0x6e, 0xb2,
+ 0x2a, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x27, 0x0e, 0x00, 0x0c, 0x02, 0x00, 0x09, 0x80, 0x6e, 0xf2,
+ 0x00, 0x00, 0x24, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x02, 0xe4, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x27, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x18, 0x09, 0x40, 0x81, 0xb2,
+ 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x0c, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x27, 0x0e, 0x00, 0x0c, 0x02, 0x00, 0x09, 0x80, 0x6e, 0xf2,
+ 0x00, 0x00, 0xa4, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x90, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x78, 0x0b, 0x16, 0x38,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x78, 0x0b, 0x16, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa8, 0x00, 0x2d, 0x37,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x88, 0x0d, 0x8b, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xb4, 0x08, 0x80, 0x6e, 0x32,
+ 0x00, 0x00, 0x45, 0x0c, 0x04, 0x31, 0x01, 0x90, 0x08, 0x00, 0x6e, 0xb2,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a,
+ 0x18, 0x00, 0x43, 0x0c, 0x86, 0x41, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0x3f, 0x78, 0xb0,
+ 0x00, 0x00, 0x3c, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc,
+ 0xb7, 0x00, 0x3c, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0x30,
+ 0x00, 0x00, 0x58, 0x0c, 0x00, 0x00, 0x00, 0x04, 0xd8, 0x62, 0x80, 0x9c,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x1b, 0x89, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a,
+ 0x18, 0x00, 0x4e, 0x0c, 0x86, 0x41, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0x3f, 0x78, 0xb0,
+ 0x00, 0x00, 0x47, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc,
+ 0xb7, 0x00, 0x47, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x51, 0x0c, 0x28, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x04, 0xd8, 0x62, 0x80, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x40, 0x80, 0xb2,
+ 0x00, 0x00, 0x55, 0x0c, 0x02, 0x01, 0x00, 0x90, 0x18, 0x20, 0x89, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x47, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc,
+ 0xb7, 0x00, 0x47, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x58, 0x0c, 0x04, 0x00, 0x00, 0x90, 0x18, 0x20, 0x89, 0xba,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x04, 0x48, 0x62, 0x80, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x90, 0x00, 0x00, 0xb4, 0x48, 0x62, 0x8b, 0xba,
+ 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x08, 0x1e, 0xff, 0xb8,
+ 0x00, 0x00, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x22, 0x80, 0x9a,
+ 0x00, 0x00, 0x89, 0x0c, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a,
+ 0x18, 0x00, 0x87, 0x0c, 0x86, 0x40, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0xb0,
+ 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x08, 0x1e, 0xff, 0xb8,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x00, 0x67, 0x0c, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x72, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2,
+ 0x20, 0x80, 0x64, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb8, 0x1b, 0x80, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xf7, 0x01, 0x0b, 0x34,
+ 0x00, 0x00, 0x81, 0x0c, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xb7, 0x01, 0x70, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0x93, 0x0c, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x1b, 0x89, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x5a, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc,
+ 0xb7, 0x00, 0x5a, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92,
+ 0x27, 0x00, 0x8c, 0x0c, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x78, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0xa2, 0x97, 0xbc,
+ 0x00, 0x00, 0x8e, 0x0c, 0x23, 0x55, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0xb2,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x90, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc7, 0x01, 0x70, 0x34,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x08, 0x00, 0x97, 0x0c, 0x23, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x99, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x9c, 0x0c, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x9c, 0x0c, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xa0, 0x0c, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0xa4, 0x03, 0xca, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0xad, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x18, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x82, 0xb6,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x01, 0xec, 0x66, 0x00, 0x00, 0x34,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0xe0, 0xe6, 0xa0, 0x82, 0x39,
+ 0x1b, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x20, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0xb6, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x02, 0xf2,
+ 0x00, 0x00, 0xbd, 0x0c, 0x00, 0x00, 0x00, 0x5c, 0x08, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0xbd, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2,
+ 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x20, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xc2, 0x0c, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc6, 0x0c, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x85, 0xb2,
+ 0x00, 0x00, 0xc6, 0x0c, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x80, 0x06, 0xc0, 0x85, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1c, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x4c, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92,
+ 0x00, 0x00, 0x1a, 0x0d, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x22, 0x0d, 0x1f, 0x20, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x1a, 0x0d, 0x04, 0x30, 0x01, 0x08, 0x89, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0xd2, 0x0c, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xd0, 0x0c, 0x00, 0x50, 0x01, 0x48, 0x08, 0x80, 0x6e, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x61, 0x80, 0x3c,
+ 0x00, 0x00, 0xeb, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x21, 0x80, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x80, 0x90, 0xb2,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x30, 0x01, 0x48, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0xd6, 0x0c, 0x00, 0x50, 0x01, 0x04, 0xa8, 0x5b, 0x80, 0x9c,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x3a,
+ 0x00, 0x00, 0xe8, 0x0c, 0x07, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x38,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xe1, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe8, 0x0c, 0x07, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8,
+ 0x05, 0x00, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x98,
+ 0x00, 0x00, 0xeb, 0x0c, 0x04, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xba,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x04, 0x28, 0x61, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x21, 0x80, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0xf4, 0x0c, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x38, 0x1a, 0xff, 0xb8,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x60, 0x80, 0x39,
+ 0x18, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x8c, 0xe6, 0xa1, 0x97, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x80, 0x84, 0x32,
+ 0x00, 0x82, 0x00, 0x00, 0xd6, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x28, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0xfe, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0xed, 0x0c, 0x12, 0x01, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39,
+ 0x00, 0x00, 0x0d, 0x0d, 0x80, 0x00, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6,
+ 0x00, 0x10, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x10, 0x00, 0x88, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x38,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0xeb, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x22, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x05, 0x00, 0x1d, 0x0d, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x98,
+ 0x00, 0x00, 0x22, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x1a, 0x0d, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0xb4, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37,
+ 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x2b, 0x0d, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x20, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0xa2, 0xcd, 0x2c, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x30, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xa2, 0x07, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x39, 0x0d, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x28, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0x43, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2,
+ 0x00, 0x00, 0xed, 0x0c, 0x12, 0x01, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x46, 0x0d, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x02, 0xf2,
+ 0x00, 0x00, 0x2b, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x02, 0xf2,
+ 0x00, 0x00, 0x4f, 0x0d, 0x9a, 0x01, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0xb4,
+ 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x34,
+ 0x2d, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa9, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x5a, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x56, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x5a, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x5a, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x58, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x5c, 0x0d, 0x04, 0x98, 0x01, 0x64, 0x88, 0x1b, 0x87, 0xbc,
+ 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x80, 0x6e, 0xf2,
+ 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x30, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x6c, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x68, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x6c, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x6c, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x6a, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0xa4, 0x07, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x36, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7d, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x79, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x7d, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x7d, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x7b, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x88, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x86, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x82, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x86, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0x86, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0x84, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x30, 0x00, 0x88, 0x0d, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x93, 0x0d, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x58, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xa2, 0x07, 0x08, 0x59, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0x9c, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0x3a,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x81, 0x2f, 0xf4,
+ 0x00, 0x00, 0x9f, 0x0d, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc,
+ 0x18, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x19, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6,
+ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x20, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xad, 0x0d, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x34,
+ 0x00, 0xc0, 0xad, 0x0d, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xad, 0x0d, 0x9f, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0xb2, 0x0d, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2,
+ 0x00, 0x00, 0xb2, 0x0d, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x34, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xa4, 0x07, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0x2f, 0xb6,
+ 0x2a, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0xc0, 0xbc, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x20, 0x00, 0x80, 0xdf, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0x38, 0x88, 0x1b, 0x16, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0xde, 0x48, 0x01, 0x28, 0x88, 0x04, 0x6e, 0x30,
+ 0x00, 0x00, 0xc1, 0x0d, 0x80, 0x5f, 0x01, 0x80, 0x72, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0xc3, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94,
+ 0x00, 0x00, 0xc3, 0x0d, 0x80, 0x5f, 0x01, 0x80, 0x62, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xa9, 0x81, 0x92, 0x34,
+ 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4,
+ 0x00, 0x00, 0xc6, 0x0d, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc9, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc9, 0x0d, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0xa4, 0x07, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x2a, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0xc0, 0xd2, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2,
+ 0x00, 0x82, 0x00, 0x00, 0xd6, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32,
+ 0x1d, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0x78, 0x09, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x10, 0x00, 0xa0, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0c, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0xf0, 0xe1, 0x0d, 0x1d, 0x40, 0x02, 0x00, 0xa8, 0x0d, 0x68, 0xb1,
+ 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x1e, 0x40, 0x02, 0x84, 0x06, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0,
+ 0x00, 0x00, 0xde, 0x0d, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0xa2, 0x0d, 0x80, 0xb2,
+ 0x00, 0x00, 0xda, 0x0d, 0xa6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xe1, 0x0d, 0xb5, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x80, 0xa0, 0x36, 0x0b, 0x6a, 0x35,
+ 0x00, 0x00, 0xe6, 0x0d, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe9, 0x01, 0x00, 0x34,
+ 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0xeb, 0x0d, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x39, 0x0b, 0x2e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xf3, 0x81, 0x97, 0x34,
+ 0x00, 0x00, 0xf1, 0x0d, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x30, 0x30,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xa4, 0x03, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x33, 0x0b, 0x2f, 0x32,
+ 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x97, 0x32,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x29, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xff, 0x0d, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x2f, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x2c, 0x32,
+ 0xd9, 0x02, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0x46, 0x03, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xf1, 0x0d, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x18, 0x0e, 0x02, 0x00, 0x00, 0x80, 0xa2, 0x42, 0x80, 0xbc,
+ 0x00, 0x00, 0x18, 0x0e, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0x18, 0x0e, 0x1f, 0x40, 0x02, 0x08, 0xb9, 0xbf, 0x68, 0xb0,
+ 0x00, 0x00, 0x08, 0x0e, 0x80, 0x41, 0x02, 0x80, 0xe2, 0x81, 0x68, 0xb6,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x61, 0x80, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0xd2, 0x21, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x41, 0x02, 0x88, 0xe6, 0x21, 0x91, 0x79,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x19, 0xa0, 0x90, 0x3a,
+ 0x00, 0x00, 0x18, 0x0e, 0x06, 0x01, 0x00, 0x80, 0xd2, 0xff, 0x90, 0xbc,
+ 0x00, 0x00, 0x0c, 0x0e, 0x2c, 0x41, 0x02, 0x78, 0xf9, 0x81, 0x68, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x81, 0x97, 0x34,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0xc0, 0x85, 0xd7,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x29, 0x1a, 0xff, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb9, 0x1b, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x88, 0x16, 0xa0, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x27, 0x24, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x8a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x58, 0xf2, 0xc1, 0x38, 0x74,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x23, 0x0e, 0x1e, 0x01, 0x00, 0x34, 0x79, 0x61, 0x80, 0xb9,
+ 0x00, 0x00, 0x8a, 0x11, 0x38, 0x00, 0x00, 0x54, 0x1f, 0x40, 0xf5, 0xba,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x40, 0x02, 0x00, 0x09, 0x40, 0x68, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb9, 0x3f, 0x90, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x26, 0x24, 0x6e, 0x3a,
+ 0x08, 0x00, 0x8a, 0x11, 0x1e, 0x00, 0x00, 0x00, 0x09, 0xa4, 0xfe, 0xb8,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x90, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x90, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x90, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xd2, 0x21, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x18, 0x00, 0x00, 0x00, 0x1e, 0x41, 0x02, 0x84, 0xe6, 0x61, 0x93, 0x79,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x01, 0x80, 0x82, 0xdb, 0x90, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0xdb, 0x90, 0x7c,
+ 0x00, 0x00, 0x2d, 0x0e, 0x06, 0x21, 0x01, 0x80, 0x82, 0x1b, 0x90, 0xbc,
+ 0x26, 0x00, 0x2e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x92,
+ 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x92, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x92, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x2f, 0xa0, 0x01, 0x78, 0x89, 0x1b, 0x92, 0x7a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x78, 0x89, 0x9b, 0x97, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0xf9, 0xba, 0x6e, 0x37,
+ 0x00, 0x00, 0x39, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x97, 0xbc,
+ 0x00, 0x00, 0x39, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x97, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xf2, 0x80, 0x2f, 0x74,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0x32,
+ 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x89, 0xd2,
+ 0x00, 0x00, 0x42, 0x0e, 0x08, 0x5d, 0x01, 0xec, 0x16, 0x40, 0x89, 0xbc,
+ 0x00, 0x00, 0x42, 0x0e, 0x0b, 0x5d, 0x01, 0xec, 0x06, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x42, 0x0e, 0x80, 0x00, 0x00, 0x80, 0x42, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x78, 0x89, 0x1b, 0x87, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x92, 0xa1, 0x97, 0xbc,
+ 0x00, 0x00, 0x47, 0x0e, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x86, 0xbc,
+ 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x3f, 0x11, 0x33, 0x01, 0x00, 0xf8, 0x82, 0x80, 0x2f, 0xb4,
+ 0x00, 0x00, 0x3f, 0x11, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc,
+ 0x00, 0x00, 0x3f, 0x11, 0x9f, 0xf8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xe0, 0x06, 0xc0, 0x87, 0x32,
+ 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x00, 0x00, 0x80, 0x02, 0x80, 0x91, 0xbc,
+ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x50, 0x01, 0x14, 0xa9, 0x9b, 0x91, 0xd9,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x14, 0x89, 0x0d, 0x6e, 0x37,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x01, 0x14, 0x89, 0x5b, 0x91, 0xd2,
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x2d, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x21, 0x01, 0x80, 0x82, 0x9b, 0x91, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x78, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x97, 0xbc,
+ 0x00, 0x00, 0x71, 0x0e, 0x04, 0x21, 0x01, 0x30, 0x69, 0x24, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa9, 0x9b, 0x91, 0x3a,
+ 0x00, 0x00, 0x66, 0x0e, 0x1f, 0x40, 0x02, 0x24, 0x09, 0x40, 0x68, 0xb2,
+ 0x00, 0x00, 0x5c, 0x0e, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x41, 0x92, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb9, 0x7f, 0x92, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3c,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xa4, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x08, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x99, 0xa4, 0xfe, 0xd8,
+ 0x08, 0x00, 0x5c, 0x0e, 0x12, 0x01, 0x00, 0x68, 0x92, 0xa4, 0xfe, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xbc,
+ 0x00, 0x00, 0x6b, 0x0e, 0x38, 0x50, 0x01, 0x78, 0x09, 0x80, 0x6e, 0xb2,
+ 0x00, 0x00, 0x6b, 0x0e, 0x04, 0x28, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x28, 0x01, 0x78, 0xe9, 0x25, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x01, 0x00, 0x78, 0x69, 0xa4, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a,
+ 0x00, 0x00, 0x6e, 0x0e, 0x38, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0xb2,
+ 0x00, 0x00, 0x6f, 0x0e, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x77, 0x0e, 0x38, 0x51, 0x01, 0x00, 0xa9, 0x9b, 0x91, 0xba,
+ 0x00, 0x00, 0x75, 0x0e, 0x04, 0x41, 0x02, 0x08, 0xb9, 0xff, 0x68, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x41, 0x02, 0x80, 0xe2, 0xc1, 0x68, 0xb6,
+ 0x00, 0x00, 0x72, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92,
+ 0x00, 0x00, 0x84, 0x0e, 0x9f, 0x31, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0xbc,
+ 0x00, 0x00, 0x84, 0x0e, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x81, 0x0e, 0x04, 0x28, 0x01, 0x04, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x50, 0x01, 0x80, 0xa2, 0x5b, 0x90, 0xbc,
+ 0x00, 0x00, 0x7f, 0x0e, 0x9f, 0x01, 0x00, 0x00, 0x19, 0x24, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x24, 0x00, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8e, 0x0e, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xbc,
+ 0x00, 0x00, 0x84, 0x0e, 0x04, 0x41, 0x02, 0x08, 0xb9, 0xff, 0x68, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x41, 0x02, 0x80, 0xe2, 0xc1, 0x68, 0xb6,
+ 0x00, 0x00, 0x81, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92,
+ 0x00, 0x00, 0x88, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x22, 0x24, 0x90, 0xbc,
+ 0x00, 0x00, 0x8e, 0x0e, 0x80, 0x40, 0x02, 0x80, 0xf2, 0xc1, 0x68, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x8c, 0xb6, 0xc1, 0x68, 0x35,
+ 0x00, 0x00, 0x8e, 0x0e, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2,
+ 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8,
+ 0x00, 0x00, 0x81, 0x0e, 0x04, 0x01, 0x00, 0x00, 0x29, 0x24, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x0b, 0x16, 0x38,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x0b, 0x16, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x42, 0xe4, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa9, 0x00, 0x2d, 0x37,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x4d, 0x90, 0x3a,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x82, 0x0d, 0x91, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x12, 0xa4, 0x2a, 0x3a,
+ 0x00, 0x00, 0x99, 0x0e, 0x80, 0x40, 0x02, 0x80, 0xe2, 0x01, 0x7c, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x78, 0xb9, 0x3f, 0x7c, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3a,
+ 0x00, 0x00, 0x9b, 0x0e, 0x9f, 0x01, 0x00, 0x10, 0x19, 0x00, 0x91, 0xbc,
+ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x94, 0x0e, 0x04, 0x01, 0x00, 0x80, 0x42, 0xe4, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc9, 0x24, 0x90, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0xa4, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x18, 0x00, 0xa5, 0x0e, 0x1f, 0x41, 0x02, 0x78, 0x88, 0xcd, 0x68, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a,
+ 0x00, 0x00, 0xa8, 0x0e, 0x80, 0x01, 0x00, 0x80, 0x62, 0x80, 0x87, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0xff, 0x68, 0xb0,
+ 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92,
+ 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x38, 0x1a, 0xff, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x40, 0x02, 0x04, 0xb8, 0xff, 0x68, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb8, 0x1b, 0x80, 0x3a,
+ 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xb6, 0x0e, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xb3, 0x0e, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0xb6, 0x0e, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb0, 0x0e, 0x9f, 0x01, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x68, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x70, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0xa9, 0x60, 0x81, 0xd9,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xa0, 0x81, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xc1, 0x0e, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xc1, 0x0e, 0x1b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x62, 0xe0, 0x83, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35,
+ 0x00, 0xa0, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0x72,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0x32,
+ 0xee, 0xff, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x86, 0x8d, 0x2f, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xb3, 0xe4, 0x39, 0x32,
+ 0x00, 0x00, 0xcd, 0x0e, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe3, 0xa5, 0x03, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x33, 0x0b, 0x2f, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0x76,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xe3, 0xa5, 0x03, 0x79,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xd8, 0x0e, 0x20, 0x00, 0x01, 0x2c, 0x09, 0xc0, 0x6e, 0xb2,
+ 0x00, 0x00, 0xd9, 0x0e, 0x00, 0x16, 0x86, 0xcc, 0x06, 0xc0, 0x92, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x86, 0xcc, 0x06, 0xc0, 0x92, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0x62, 0x8e, 0x92, 0x52,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xdf, 0x0e, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x80, 0x97, 0xbc,
+ 0xdf, 0x0e, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb1,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x38, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x02, 0x00, 0x30, 0x32,
+ 0x00, 0x00, 0x22, 0x0f, 0x04, 0x00, 0x00, 0x24, 0xd8, 0x01, 0x30, 0xb6,
+ 0xe4, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x4d, 0x82, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0xdf, 0x0e, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xec, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x48, 0x05, 0x30, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf7, 0x0e, 0x32, 0x0f, 0x01, 0xbc, 0x08, 0xc0, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x32,
+ 0x00, 0x00, 0xf0, 0x0e, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0xf6, 0x0e, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0x20, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x87, 0xa0, 0xea, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0xea, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x26, 0x01, 0x6e, 0x35,
+ 0x00, 0x00, 0xfb, 0x0e, 0x80, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x8b, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0e, 0x82, 0x32,
+ 0x00, 0xe0, 0x03, 0x0f, 0x12, 0x01, 0x00, 0x48, 0xa2, 0x0d, 0x90, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32,
+ 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0x00, 0x82, 0x37,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x60, 0x38, 0x32,
+ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa4, 0x17, 0x38,
+ 0x00, 0x00, 0x09, 0x0f, 0x80, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x8b, 0xb6,
+ 0x00, 0x00, 0x0a, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf3, 0x41, 0x90, 0x34,
+ 0x00, 0x00, 0x0f, 0x0f, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x30, 0x30,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xa4, 0x03, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xce, 0x2c, 0x32,
+ 0x00, 0xe0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x0d, 0x90, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x32,
+ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa4, 0x17, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x10, 0x01, 0x80, 0x22, 0x01, 0x6e, 0xb6,
+ 0x00, 0x00, 0x18, 0x0f, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x20, 0x0f, 0x1d, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0xb2,
+ 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37,
+ 0x20, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x37, 0x8b, 0xea, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0xea, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x32,
+ 0xee, 0xff, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0xee, 0xff, 0x8a, 0x11, 0x04, 0x11, 0x01, 0x80, 0x82, 0x0d, 0x6e, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x4d, 0x0d, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x2b, 0x0f, 0x12, 0x00, 0x00, 0x4c, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x2c, 0x0f, 0x12, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x02, 0x90, 0x3a,
+ 0x00, 0x00, 0x28, 0x0f, 0x04, 0x01, 0x00, 0x04, 0x19, 0x40, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x3b, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x35, 0x0f, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x3a, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc,
+ 0x00, 0x00, 0x35, 0x0f, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x34, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x88, 0x1c, 0x83, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x00, 0x18, 0xc8, 0x20, 0x72, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x20, 0x88, 0x01, 0x82, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32,
+ 0x00, 0x00, 0xa3, 0x0f, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c,
+ 0x00, 0x00, 0x67, 0x0f, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0x58, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2,
+ 0x00, 0x00, 0x60, 0x0f, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x5e, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x59, 0x0f, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x65, 0x0f, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba,
+ 0x00, 0x00, 0x64, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x4d, 0x0f, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x6e, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x68, 0x0f, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2,
+ 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8,
+ 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x00, 0x00, 0x86, 0x0f, 0x1f, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba,
+ 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2,
+ 0x00, 0x00, 0x79, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x92,
+ 0x00, 0x00, 0x86, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x4c, 0x0f, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc,
+ 0x00, 0x00, 0x84, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x83, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x4d, 0x0f, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e,
+ 0x00, 0x00, 0x89, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xa7, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x21, 0x01, 0x80, 0x82, 0x5b, 0x8a, 0xbc,
+ 0x00, 0x00, 0x8d, 0x0f, 0x2f, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0xba,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x06, 0x00, 0x92, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x92, 0x0f, 0x23, 0x21, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xb2,
+ 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0xe0, 0x06, 0x80, 0x82, 0xb2,
+ 0x00, 0x00, 0x9c, 0x0f, 0x04, 0x21, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x9a, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x99, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x2a, 0x19, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x72,
+ 0x00, 0x00, 0xa1, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x75,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0x3c,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32,
+ 0xee, 0x05, 0xaf, 0x0f, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0xf5, 0xbc,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xb1, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0x09, 0x92,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x09, 0x32,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x87, 0xcd, 0x00, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x60, 0xc0, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x2a, 0x3a,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x97, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x19, 0x40, 0x90, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x52, 0x82, 0x2a, 0x3a,
+ 0x00, 0x08, 0xb1, 0x0f, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2a, 0xbc,
+ 0x00, 0x00, 0xc2, 0x0f, 0x06, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x20, 0xb2,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x87, 0xcd, 0x00, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x07, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2a, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36,
+ 0x00, 0x00, 0xbb, 0x0f, 0x04, 0x01, 0x00, 0x04, 0x19, 0x40, 0x90, 0xbc,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0e, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x80, 0x97, 0xb2,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x89, 0x0d, 0x90, 0x36,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x89, 0x4d, 0x92, 0x3c,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x4d, 0x92, 0x36,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x89, 0x4d, 0x92, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x18, 0x9b, 0x81, 0xb2, 0xe4, 0x78, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x9b, 0x8d, 0xb7, 0xe4, 0x78, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0e, 0x80, 0x97, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x59, 0x00, 0x90, 0x36,
+ 0x00, 0x00, 0xc4, 0x0f, 0x95, 0x01, 0x00, 0x80, 0x22, 0x24, 0x90, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xec, 0x0f, 0x04, 0x01, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb2, 0x45, 0x28, 0x30,
+ 0x00, 0x00, 0xdd, 0x0f, 0x86, 0x01, 0x00, 0x08, 0x09, 0x80, 0x2f, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x40, 0x81, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0xdc, 0x0f, 0x04, 0x07, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc,
+ 0x00, 0x00, 0xe7, 0x0f, 0xc3, 0x07, 0x01, 0xec, 0xb6, 0xe4, 0x6e, 0x9a,
+ 0x00, 0x00, 0xe7, 0x0f, 0x00, 0x06, 0x01, 0xec, 0xb6, 0xe4, 0x6e, 0x9a,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x52, 0x80, 0x90, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x05, 0x80, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x92, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xfa, 0x92, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xfa, 0x92, 0xbc,
+ 0x44, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0xd2,
+ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x92, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0x32,
+ 0x00, 0x00, 0xec, 0x0f, 0x04, 0x01, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6,
+ 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x00, 0x00, 0x9c, 0xb2, 0x45, 0x28, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x22, 0x80, 0x97, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0xe8, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0xc0, 0xe8, 0x32,
+ 0x02, 0x00, 0xf1, 0x0f, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32,
+ 0x00, 0x00, 0xf6, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xf9, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6,
+ 0x00, 0x00, 0x00, 0x10, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6,
+ 0x00, 0x00, 0xfd, 0x0f, 0xb0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x10, 0xb0, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0xb7,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30,
+ 0x00, 0x00, 0x08, 0x10, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x69, 0x81, 0x97, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x0b, 0x00, 0x7c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0e, 0x10, 0xb0, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32,
+ 0x00, 0x00, 0x13, 0x10, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x16, 0x10, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x0d, 0x40, 0xd0, 0x34,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6,
+ 0x00, 0x00, 0x1d, 0x10, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6,
+ 0x00, 0x00, 0x1a, 0x10, 0xb0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x0d, 0x40, 0xd0, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x1d, 0x10, 0xb0, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30,
+ 0x00, 0x00, 0x25, 0x10, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x69, 0x81, 0x97, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x0b, 0x00, 0x7c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x41, 0x02, 0x80, 0x06, 0xc0, 0x92, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x92, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x92, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x92, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x52,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x80, 0x87, 0x35,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x87, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3c,
+ 0x08, 0x00, 0x00, 0x00, 0xd2, 0x01, 0x00, 0x78, 0xe9, 0xe5, 0x83, 0x39,
+ 0x18, 0x00, 0x8a, 0x11, 0x1f, 0x41, 0x02, 0x84, 0xe6, 0xa1, 0x97, 0xb9,
+ 0x00, 0x00, 0x43, 0x10, 0x36, 0x51, 0x01, 0xe8, 0x16, 0xe0, 0x83, 0xbc,
+ 0x00, 0x00, 0x43, 0x10, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x45, 0x10, 0x38, 0x21, 0x01, 0xe0, 0x06, 0x40, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x40, 0x80, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x92, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x40, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x41, 0x01, 0xe0, 0x06, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x74,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x3d, 0x00, 0x0c, 0x07, 0x80, 0x83, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0x72,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x57, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x01, 0xec, 0x06, 0x80, 0x92, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2,
+ 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x19, 0xa0, 0x2c, 0xd9,
+ 0x00, 0x00, 0x60, 0x10, 0x9d, 0x11, 0x02, 0x0c, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x61, 0x10, 0x00, 0xf0, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x63, 0x10, 0x2c, 0xcd, 0x01, 0x18, 0x09, 0x80, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xc9, 0xc1, 0x90, 0x34,
+ 0x00, 0x00, 0x67, 0x10, 0x3b, 0x29, 0x02, 0x04, 0x09, 0x80, 0x6e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0xd6, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x56, 0xc0, 0x6e, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xb9, 0xc1, 0x90, 0x34,
+ 0x00, 0x00, 0x77, 0x10, 0x00, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2,
+ 0x00, 0x00, 0x6b, 0x10, 0x9d, 0x01, 0x00, 0x80, 0x17, 0xe0, 0x90, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x07, 0xc0, 0x91, 0x32,
+ 0x00, 0x00, 0x6e, 0x10, 0x00, 0x38, 0x00, 0x80, 0x07, 0x00, 0xee, 0x92,
+ 0x00, 0x00, 0x6e, 0x10, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc0, 0x91, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0xe0, 0x06, 0x00, 0x86, 0x32,
+ 0x00, 0x00, 0x71, 0x10, 0x39, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xd9, 0xc9, 0x01, 0xe8, 0x06, 0x80, 0x91, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc8, 0x11, 0x00, 0x80, 0x07, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x74, 0x10, 0x3b, 0x21, 0x00, 0x80, 0x07, 0x00, 0x86, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x60, 0x18, 0x00, 0x86, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x78, 0x01, 0xe0, 0x16, 0x20, 0x86, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x80, 0x07, 0x00, 0x85, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x7b, 0x10, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x29, 0x00, 0x6e, 0x36,
+ 0x00, 0x00, 0x7b, 0x10, 0x02, 0x00, 0x00, 0x80, 0xe2, 0xa5, 0x90, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x78, 0x49, 0x21, 0x6e, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3f,
+ 0x00, 0x00, 0x82, 0x10, 0x04, 0x20, 0x02, 0x08, 0x89, 0x9b, 0x90, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x58, 0xb8, 0x9b, 0x90, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x49, 0xa1, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x9f, 0x88, 0x01, 0x80, 0x82, 0x9b, 0x97, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x01, 0xe0, 0x06, 0x80, 0x97, 0x72,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x02, 0x58, 0xb8, 0x9b, 0x90, 0x76,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8b, 0x10, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x89, 0x10, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8b, 0x10, 0xca, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x92,
+ 0x15, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0xe9, 0x65, 0x17, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x35,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x88, 0x1c, 0x83, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x00, 0x18, 0xc8, 0x20, 0x72, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x62, 0xa0, 0x82, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x20, 0x88, 0x01, 0x82, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x85, 0xd2,
+ 0x00, 0x00, 0xa6, 0x10, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6,
+ 0x00, 0x00, 0xa2, 0x10, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xa6, 0x10, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4,
+ 0x00, 0x00, 0xa6, 0x10, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95,
+ 0x00, 0x00, 0xa4, 0x10, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30,
+ 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x7a,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0x70,
+ 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x74,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x80, 0xa8, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0x70,
+ 0x00, 0x00, 0xb7, 0x10, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0xba, 0x10, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34,
+ 0x3b, 0x00, 0xba, 0x10, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xba, 0x10, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x80, 0x2f, 0xb6,
+ 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0xbd, 0x10, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x94,
+ 0x00, 0x00, 0xbd, 0x10, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x80, 0x2f, 0xb6,
+ 0x34, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x34,
+ 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0x70,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0x70,
+ 0x3a, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0x74,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39,
+ 0xee, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x71,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0xf2,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0x72,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xcd, 0x10, 0x04, 0x38, 0x01, 0x78, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x11, 0x00, 0x00, 0x07, 0x80, 0x82, 0x32,
+ 0x00, 0x00, 0xd1, 0x10, 0x2e, 0x19, 0x00, 0x00, 0x07, 0x80, 0x97, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe9, 0x81, 0x92, 0x34,
+ 0x00, 0x00, 0xd5, 0x10, 0x27, 0x31, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x28, 0xe9, 0x80, 0x92, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xe7, 0xa0, 0x92, 0x79,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x90, 0xd2,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2,
+ 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9,
+ 0x00, 0x00, 0xdf, 0x10, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0xda, 0x10, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5,
+ 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x0a, 0x91, 0x39,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x0b, 0x91, 0x39,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x59, 0x0a, 0x91, 0x39,
+ 0x09, 0x00, 0xe5, 0x10, 0xf1, 0x01, 0x00, 0x10, 0x69, 0x0b, 0x91, 0xb9,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x24, 0x86, 0xa8, 0x82, 0x8d, 0x6c, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe0, 0x07, 0x00, 0x91, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe0, 0x07, 0x40, 0x91, 0x32,
+ 0x00, 0x80, 0xeb, 0x10, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2a, 0xbc,
+ 0x00, 0x00, 0xec, 0x10, 0xe1, 0x24, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x92,
+ 0x03, 0x00, 0x00, 0x00, 0xe1, 0x24, 0x86, 0xc8, 0x86, 0x8d, 0x2a, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf4, 0x10, 0x04, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x28, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35,
+ 0x00, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2,
+ 0x00, 0x00, 0xf6, 0x10, 0x80, 0x39, 0x00, 0x80, 0xe2, 0x80, 0x6e, 0xb6,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x38, 0x00, 0x80, 0xf2, 0x80, 0x6e, 0xb6,
+ 0x00, 0xe0, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0,
+ 0x00, 0xe0, 0xfd, 0x10, 0x04, 0x38, 0x00, 0x78, 0x89, 0x8d, 0x6e, 0xb0,
+ 0x10, 0x00, 0xfd, 0x10, 0x9f, 0x01, 0x00, 0xf8, 0xe2, 0xa5, 0x2f, 0xb9,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0xee, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x00, 0x18, 0x09, 0x00, 0x6e, 0x72,
+ 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0x92,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa9, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0x7c,
+ 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xbc, 0x00, 0x14, 0x28, 0x80, 0x6e, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35,
+ 0x08, 0xa0, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0x72,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x90, 0xd2,
+ 0x00, 0x00, 0x0f, 0x11, 0x33, 0xcd, 0x01, 0xbc, 0x08, 0x80, 0x6e, 0xb2,
+ 0x00, 0x00, 0x4e, 0x11, 0x00, 0x00, 0x00, 0x28, 0x29, 0x22, 0xee, 0xdc,
+ 0x00, 0x00, 0x14, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x14, 0x11, 0x04, 0xb8, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x14, 0x11, 0x9f, 0x71, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xa9, 0x24, 0xee, 0x3c,
+ 0x00, 0x00, 0x4e, 0x11, 0x00, 0x00, 0x00, 0x28, 0x19, 0x80, 0x92, 0xdf,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x28, 0x11, 0x06, 0x80, 0x01, 0x80, 0x82, 0x9b, 0x90, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x90, 0xbc,
+ 0xee, 0x05, 0x20, 0x11, 0x06, 0x0c, 0x02, 0x80, 0x82, 0x8d, 0x6e, 0xbc,
+ 0x00, 0x90, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x1a, 0x11, 0xb8, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x18, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x03, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x78, 0x49, 0x40, 0x3c, 0x37,
+ 0x00, 0x00, 0x2d, 0x11, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x9a,
+ 0x60, 0x89, 0x20, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x23, 0x11, 0xb8, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0,
+ 0x00, 0x00, 0x21, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x03, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x2d, 0x11, 0xa8, 0x00, 0x00, 0x08, 0x19, 0x8f, 0x90, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xa1, 0x89, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x30, 0x11, 0x06, 0x00, 0x00, 0x80, 0x72, 0xa2, 0x90, 0xbc,
+ 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0xc0, 0x89, 0x32,
+ 0x00, 0x00, 0x36, 0x11, 0x04, 0x79, 0x01, 0x80, 0x82, 0x1b, 0x87, 0xbc,
+ 0x00, 0x00, 0x34, 0x11, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x92, 0x81, 0x2f, 0x75,
+ 0x00, 0x00, 0x3c, 0x11, 0x80, 0x00, 0x00, 0x80, 0x52, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x3c, 0x11, 0xd5, 0x41, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x92,
+ 0x00, 0x00, 0x39, 0x11, 0x3c, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0xb2,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0xc0, 0x8b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2f, 0x72,
+ 0x00, 0x00, 0x3d, 0x11, 0x9f, 0x41, 0x01, 0x80, 0x82, 0x1b, 0x87, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x00, 0x00, 0xd9, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x72, 0x80, 0x2f, 0x74,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x87, 0xd2,
+ 0x00, 0x00, 0x47, 0x11, 0x9f, 0xd8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x47, 0x11, 0x9f, 0xe0, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x47, 0x11, 0x9f, 0xb0, 0x01, 0x80, 0xd2, 0x21, 0x6e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70,
+ 0x00, 0x00, 0x49, 0x11, 0x06, 0x68, 0x01, 0x80, 0x82, 0x5b, 0x87, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0xe0, 0x06, 0x40, 0x87, 0x32,
+ 0x00, 0x00, 0x4b, 0x11, 0x37, 0xb0, 0x01, 0xe0, 0x06, 0x40, 0x87, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0x80, 0x2f, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x01, 0xe0, 0x06, 0x80, 0x84, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x72,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x08, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc,
+ 0x00, 0x00, 0x5b, 0x11, 0x04, 0xc1, 0x01, 0x84, 0x02, 0x00, 0x6e, 0xb2,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe8, 0x86, 0x8d, 0x92, 0x37,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x01, 0xe8, 0x86, 0x8d, 0x92, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x2c, 0x89, 0x8d, 0x6e, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x01, 0x2c, 0xa9, 0xdb, 0x92, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x29, 0xc0, 0x92, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x19, 0xfb, 0x92, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x29, 0x80, 0x92, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa9, 0xe4, 0x92, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x6f, 0xcc, 0x01, 0xe8, 0x26, 0xfb, 0x92, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x02, 0x80, 0x92, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x06, 0x40, 0x28, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x6f, 0xcc, 0x01, 0xe8, 0x86, 0xcd, 0x2a, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xbc, 0x08, 0x00, 0x6e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xbc, 0x88, 0xdb, 0x8b, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0xbc, 0x88, 0xdb, 0x8b, 0x3a,
+ 0x00, 0x00, 0x6a, 0x11, 0x9f, 0x00, 0x00, 0xbc, 0x88, 0xe1, 0x8b, 0xbc,
+ 0x00, 0x00, 0x6a, 0x11, 0x04, 0x0c, 0x02, 0x40, 0xa8, 0xdb, 0x8b, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x04, 0x88, 0x1b, 0x84, 0x3e,
+ 0x00, 0x00, 0x69, 0x11, 0x04, 0xb1, 0x00, 0x80, 0x82, 0x5b, 0x80, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xc2, 0x80, 0x2f, 0x74,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0x7c,
+ 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x8b, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39,
+ 0xee, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x71,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xd9, 0x4a, 0x91, 0x39,
+ 0x39, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x09, 0x45, 0x91, 0x30,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0x4d, 0x91, 0x36,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0xcd, 0x93, 0x3c,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0xcd, 0x93, 0x36,
+ 0x07, 0x00, 0x79, 0x11, 0xf3, 0x01, 0x00, 0x40, 0x89, 0xcd, 0x93, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x18, 0x9b, 0x81, 0x02, 0xe5, 0x78, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xe3, 0x18, 0x9b, 0x8d, 0x07, 0xe5, 0x78, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xd9, 0x4a, 0x91, 0x39,
+ 0x3a, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x09, 0x45, 0x91, 0x30,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0x4d, 0x91, 0x36,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0xcd, 0x93, 0x3c,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0xcd, 0x93, 0x36,
+ 0x07, 0x00, 0x84, 0x11, 0xf3, 0x01, 0x00, 0x40, 0x89, 0xcd, 0x93, 0xb0,
+ 0x00, 0x00, 0x8a, 0x11, 0x80, 0x19, 0x9b, 0x81, 0x02, 0xe5, 0x78, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0xe3, 0x18, 0x9b, 0x8d, 0x07, 0xe5, 0x78, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0xb4, 0x0f, 0x40, 0xfb, 0x94,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x0f, 0x40, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x28, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x0f, 0x00, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0f, 0x40, 0x18, 0x32,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x5f, 0xca, 0xf9, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0xc0, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32,
+ 0x41, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32,
+ 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0f, 0x80, 0x2a, 0x32,
+ 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x98, 0x11, 0x97, 0x12, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x01, 0x84, 0x12, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x36, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x80, 0x2a, 0x32,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0xc0, 0xfa, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xfa, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0xfa, 0x32,
+ 0x00, 0x00, 0xac, 0x11, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xfa, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xfb, 0x32,
+ 0x01, 0x00, 0xcf, 0x11, 0x04, 0x01, 0x00, 0xb4, 0x8f, 0x4d, 0xfb, 0xb0,
+ 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xcd, 0xb0, 0x32,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x5b, 0xca, 0xb0, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x2b, 0xfe, 0xb0, 0x32,
+ 0x00, 0x00, 0xaa, 0x11, 0x12, 0x01, 0x00, 0x80, 0x02, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0xbe, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x01, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x80, 0x3f, 0x52,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x16, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x80, 0x90, 0x32,
+ 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32,
+ 0xb9, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0x0d, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0x0d, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0xfa, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0xfa, 0x32,
+ 0x00, 0x00, 0xc9, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39,
+ 0x00, 0x00, 0xc0, 0x11, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35,
+ 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x40, 0x90, 0x92,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39,
+ 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x04, 0x6b, 0x41, 0x90, 0x94,
+ 0x00, 0x00, 0xc4, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0xc5, 0x11, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2,
+ 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x38,
+ 0x00, 0x00, 0xc9, 0x11, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0xc8, 0x11, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x02, 0x00, 0xc4, 0x11, 0x04, 0x01, 0x00, 0xbc, 0x0f, 0x24, 0x17, 0xb8,
+ 0x06, 0x00, 0xc2, 0x11, 0x04, 0x00, 0x00, 0xbc, 0x0f, 0x64, 0x16, 0xb8,
+ 0x00, 0x00, 0xbd, 0x11, 0x04, 0x00, 0x00, 0x80, 0x22, 0xc0, 0xfb, 0xbc,
+ 0x20, 0x00, 0xc4, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfb, 0xbc,
+ 0x00, 0x00, 0xd7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0xd1, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0xf9, 0x3a,
+ 0x00, 0x00, 0xb7, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xf8, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xfc, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x32,
+ 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xde, 0x11, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0xde, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0xe0, 0x11, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x7e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0xfa, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32,
+ 0x00, 0x00, 0xad, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0xb3, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xcb, 0xc1, 0xb0, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0xb0, 0xd2,
+ 0x00, 0x00, 0xeb, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xb2,
+ 0x00, 0x00, 0xef, 0x11, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2,
+ 0x02, 0x00, 0xf2, 0x11, 0x04, 0x01, 0x00, 0xb4, 0x8f, 0x4d, 0xfb, 0xb0,
+ 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x1f, 0x40, 0xfb, 0x35,
+ 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, 0x34,
+ 0x00, 0x00, 0xeb, 0x11, 0x00, 0x00, 0x00, 0x0c, 0x8b, 0xc1, 0xb0, 0x94,
+ 0x00, 0x00, 0xbb, 0x12, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0xfa, 0x92,
+ 0x00, 0x00, 0xad, 0x12, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0xfa, 0xd2,
+ 0x00, 0x00, 0xf9, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0xb4, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0xbd, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xb0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x12, 0x00, 0x2a, 0x3a,
+ 0x00, 0x00, 0xff, 0x11, 0x04, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xba, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x0c, 0x12, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0xfa, 0xb2,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x0e, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x1b, 0x12, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0xd2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x3c, 0x32,
+ 0x00, 0x00, 0x08, 0x12, 0x8e, 0x01, 0x00, 0x80, 0x02, 0x40, 0x28, 0xb2,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x8f, 0x4d, 0xfa, 0x3a,
+ 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32,
+ 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x08, 0x00, 0x10, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32,
+ 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x0b, 0x00, 0x14, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32,
+ 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x27, 0x00, 0x18, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32,
+ 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x20, 0x00, 0x1d, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0xc0, 0xf9, 0x32,
+ 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0xfa, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x5a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x3a,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xac, 0x8f, 0xcd, 0xf9, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x12, 0x00, 0x2b, 0x3a,
+ 0x0f, 0x00, 0x2b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x2b, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3e, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x02, 0xc0, 0xf9, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x3a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x3a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x3d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3d, 0x32,
+ 0x00, 0x00, 0x36, 0x12, 0x84, 0x01, 0x00, 0xb0, 0x12, 0x00, 0x2b, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x02, 0xc0, 0xf9, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x73, 0x3e, 0x00, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x3a,
+ 0x70, 0x00, 0x3b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0xc0, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0xc0, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0xc0, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0xfa, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x73, 0x7e, 0xfa, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32,
+ 0x00, 0x00, 0x44, 0x12, 0x85, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x0e, 0x00, 0x53, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x4d, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x3f, 0xc0, 0xf9, 0x9a,
+ 0x1c, 0x00, 0x4d, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc,
+ 0x02, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x8f, 0xcd, 0xf9, 0xda,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x37, 0x32,
+ 0x00, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x0e, 0x00, 0x5b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x57, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x9a,
+ 0x26, 0x00, 0x57, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0f, 0x40, 0x29, 0x32,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x56, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x29, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x18, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, 0x32,
+ 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32,
+ 0x6b, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x80, 0x2a, 0x32,
+ 0x00, 0x00, 0x6b, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x29, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0x3e, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0x3e, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34,
+ 0x00, 0x00, 0x6c, 0x12, 0x00, 0x00, 0x00, 0x88, 0x0f, 0x40, 0x2b, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x28, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x0f, 0x00, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0f, 0x80, 0x2a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0xc0, 0xf9, 0x32,
+ 0x71, 0x12, 0x97, 0x12, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x36, 0x92,
+ 0x07, 0x00, 0x74, 0x12, 0x04, 0x00, 0x00, 0x80, 0x82, 0x4d, 0x29, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x1f, 0x00, 0xfa, 0x3a,
+ 0x00, 0x00, 0x68, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x80, 0x2a, 0x92,
+ 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x36, 0x32,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x84, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x1f, 0x00, 0x7a, 0x12, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x29, 0xbc,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x8f, 0xcd, 0xfa, 0x3a,
+ 0x00, 0x00, 0x76, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x12, 0xc0, 0x29, 0x9a,
+ 0x00, 0x00, 0x3a, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x30, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x82, 0x12, 0x04, 0x00, 0x00, 0x80, 0x52, 0x8a, 0xfa, 0xbc,
+ 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32,
+ 0x82, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa3, 0x3e, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xa3, 0x3e, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34,
+ 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x02, 0xc0, 0xfa, 0x32,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0x40, 0x2f, 0x32,
+ 0x00, 0x00, 0x8b, 0x12, 0x04, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc,
+ 0x00, 0x00, 0x8a, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x2f, 0xb2,
+ 0x00, 0x00, 0x87, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2c, 0x92,
+ 0x00, 0x00, 0x87, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2c, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2d, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xfb, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2f, 0x32,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x02, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x80, 0x3f, 0x52,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x28, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xf8, 0x32,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0xc0, 0x2b, 0x32,
+ 0x00, 0x00, 0xa0, 0x12, 0x04, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc,
+ 0x00, 0x00, 0x9f, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2b, 0xb2,
+ 0x00, 0x00, 0x9c, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x28, 0x92,
+ 0x00, 0x00, 0x9c, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x36, 0x92,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x29, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xf9, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2a, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2b, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xfb, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x00, 0xfb, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xb1, 0x12, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x40, 0x90, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x80, 0x90, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x07, 0x40, 0x90, 0x52,
+ 0x00, 0x00, 0xb3, 0x12, 0x12, 0x00, 0x00, 0x48, 0xf2, 0x01, 0x00, 0xb4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0x32,
+ 0x00, 0x00, 0xb5, 0x12, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0f, 0x40, 0xfb, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32,
+ 0x00, 0x00, 0xad, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0xb3, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xcb, 0xc1, 0xb0, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0xc4, 0x12, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0xb0, 0xd2,
+ 0x00, 0x00, 0xbe, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xb2,
+ 0x00, 0x00, 0xc2, 0x12, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2,
+ 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39,
+ 0x00, 0x00, 0xc8, 0x12, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0x37,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30,
+ 0x00, 0x00, 0xd8, 0x12, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6,
+ 0x00, 0x00, 0xcd, 0x12, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0xce, 0x12, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2,
+ 0x00, 0x00, 0xd1, 0x12, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2,
+ 0x00, 0x00, 0xd0, 0x12, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2,
+ 0x0d, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0x80, 0x02, 0xe4, 0x16, 0xb8,
+ 0x02, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0xbc, 0x0f, 0x24, 0x17, 0xb8,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0x64, 0x16, 0x38,
+ 0x00, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0x80, 0x22, 0xc0, 0xfb, 0xbc,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32,
+ 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54,
+ 0x00, 0x00, 0xdc, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+},
+{
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90,
+},
+};
diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c
new file mode 100644
index 00000000000..6ccbee875ab
--- /dev/null
+++ b/drivers/staging/sxg/sxg.c
@@ -0,0 +1,3624 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2000-2008 Alacritech, Inc. All rights reserved.
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: sxg.c
+ *
+ * The SXG driver for Alacritech's 10Gbe products.
+ *
+ * NOTE: This is the standard, non-accelerated version of Alacritech's
+ * IS-NIC driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mii.h>
+
+#define SLIC_DUMP_ENABLED 0
+#define SLIC_GET_STATS_ENABLED 0
+#define LINUX_FREES_ADAPTER_RESOURCES 1
+#define SXG_OFFLOAD_IP_CHECKSUM 0
+#define SXG_POWER_MANAGEMENT_ENABLED 0
+#define VPCI 0
+#define DBG 1
+#define ATK_DEBUG 1
+
+#include "sxg_os.h"
+#include "sxghw.h"
+#include "sxghif.h"
+#include "sxg.h"
+#include "sxgdbg.h"
+
+#include "sxgphycode.h"
+#include "saharadbgdownload.h"
+
+static int sxg_allocate_buffer_memory(p_adapter_t adapter, u32 Size,
+ SXG_BUFFER_TYPE BufferType);
+static void sxg_allocate_rcvblock_complete(p_adapter_t adapter, void *RcvBlock,
+ dma_addr_t PhysicalAddress,
+ u32 Length);
+static void sxg_allocate_sgl_buffer_complete(p_adapter_t adapter,
+ PSXG_SCATTER_GATHER SxgSgl,
+ dma_addr_t PhysicalAddress,
+ u32 Length);
+
+static void sxg_mcast_init_crc32(void);
+
+static int sxg_entry_open(p_net_device dev);
+static int sxg_entry_halt(p_net_device dev);
+static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd);
+static int sxg_send_packets(struct sk_buff *skb, p_net_device dev);
+static int sxg_transmit_packet(p_adapter_t adapter, struct sk_buff *skb);
+static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl);
+
+static void sxg_handle_interrupt(p_adapter_t adapter);
+static int sxg_process_isr(p_adapter_t adapter, u32 MessageId);
+static u32 sxg_process_event_queue(p_adapter_t adapter, u32 RssId);
+static void sxg_complete_slow_send(p_adapter_t adapter);
+static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event);
+static void sxg_process_rcv_error(p_adapter_t adapter, u32 ErrorStatus);
+static bool sxg_mac_filter(p_adapter_t adapter,
+ p_ether_header EtherHdr, ushort length);
+
+#if SLIC_GET_STATS_ENABLED
+static struct net_device_stats *sxg_get_stats(p_net_device dev);
+#endif
+
+static int sxg_mac_set_address(p_net_device dev, void *ptr);
+
+static void sxg_adapter_set_hwaddr(p_adapter_t adapter);
+
+static void sxg_unmap_mmio_space(p_adapter_t adapter);
+static void sxg_mcast_set_mask(p_adapter_t adapter);
+
+static int sxg_initialize_adapter(p_adapter_t adapter);
+static void sxg_stock_rcv_buffers(p_adapter_t adapter);
+static void sxg_complete_descriptor_blocks(p_adapter_t adapter,
+ unsigned char Index);
+static int sxg_initialize_link(p_adapter_t adapter);
+static int sxg_phy_init(p_adapter_t adapter);
+static void sxg_link_event(p_adapter_t adapter);
+static SXG_LINK_STATE sxg_get_link_state(p_adapter_t adapter);
+static void sxg_link_state(p_adapter_t adapter, SXG_LINK_STATE LinkState);
+static int sxg_write_mdio_reg(p_adapter_t adapter,
+ u32 DevAddr, u32 RegAddr, u32 Value);
+static int sxg_read_mdio_reg(p_adapter_t adapter,
+ u32 DevAddr, u32 RegAddr, u32 *pValue);
+static void sxg_mcast_set_list(p_net_device dev);
+
+#define XXXTODO 0
+
+static unsigned int sxg_first_init = 1;
+static char *sxg_banner =
+ "Alacritech SLIC Technology(tm) Server and Storage 10Gbe Accelerator (Non-Accelerated)\n";
+
+static int sxg_debug = 1;
+static int debug = -1;
+static p_net_device head_netdevice = NULL;
+
+static sxgbase_driver_t sxg_global = {
+ .dynamic_intagg = 1,
+};
+static int intagg_delay = 100;
+static u32 dynamic_intagg = 0;
+
+#define DRV_NAME "sxg"
+#define DRV_VERSION "1.0.1"
+#define DRV_AUTHOR "Alacritech, Inc. Engineering"
+#define DRV_DESCRIPTION "Alacritech SLIC Techonology(tm) Non-Accelerated 10Gbe Driver"
+#define DRV_COPYRIGHT "Copyright 2000-2008 Alacritech, Inc. All rights reserved."
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_LICENSE("GPL");
+
+module_param(dynamic_intagg, int, 0);
+MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
+module_param(intagg_delay, int, 0);
+MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
+
+static struct pci_device_id sxg_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(SXG_VENDOR_ID, SXG_DEVICE_ID)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, sxg_pci_tbl);
+
+/***********************************************************************
+************************************************************************
+************************************************************************
+************************************************************************
+************************************************************************/
+
+static inline void sxg_reg32_write(void __iomem *reg, u32 value, bool flush)
+{
+ writel(value, reg);
+ if (flush)
+ mb();
+}
+
+static inline void sxg_reg64_write(p_adapter_t adapter, void __iomem *reg,
+ u64 value, u32 cpu)
+{
+ u32 value_high = (u32) (value >> 32);
+ u32 value_low = (u32) (value & 0x00000000FFFFFFFF);
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->Bit64RegLock, flags);
+ writel(value_high, (void __iomem *)(&adapter->UcodeRegs[cpu].Upper));
+ writel(value_low, reg);
+ spin_unlock_irqrestore(&adapter->Bit64RegLock, flags);
+}
+
+static void sxg_init_driver(void)
+{
+ if (sxg_first_init) {
+ DBG_ERROR("sxg: %s sxg_first_init set jiffies[%lx]\n",
+ __FUNCTION__, jiffies);
+ sxg_first_init = 0;
+ spin_lock_init(&sxg_global.driver_lock);
+ }
+}
+
+static void sxg_dbg_macaddrs(p_adapter_t adapter)
+{
+ DBG_ERROR(" (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+ DBG_ERROR(" (%s) mac %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ adapter->netdev->name, adapter->macaddr[0],
+ adapter->macaddr[1], adapter->macaddr[2],
+ adapter->macaddr[3], adapter->macaddr[4],
+ adapter->macaddr[5]);
+ return;
+}
+
+// SXG Globals
+static SXG_DRIVER SxgDriver;
+
+#ifdef ATKDBG
+static sxg_trace_buffer_t LSxgTraceBuffer;
+#endif /* ATKDBG */
+static sxg_trace_buffer_t *SxgTraceBuffer = NULL;
+
+/*
+ * sxg_download_microcode
+ *
+ * Download Microcode to Sahara adapter
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * UcodeSel - microcode file selection
+ *
+ * Return
+ * int
+ */
+static bool sxg_download_microcode(p_adapter_t adapter, SXG_UCODE_SEL UcodeSel)
+{
+ PSXG_HW_REGS HwRegs = adapter->HwRegs;
+ u32 Section;
+ u32 ThisSectionSize;
+ u32 *Instruction = NULL;
+ u32 BaseAddress, AddressOffset, Address;
+// u32 Failure;
+ u32 ValueRead;
+ u32 i;
+ u32 numSections = 0;
+ u32 sectionSize[16];
+ u32 sectionStart[16];
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DnldUcod",
+ adapter, 0, 0, 0);
+ DBG_ERROR("sxg: %s ENTER\n", __FUNCTION__);
+
+ switch (UcodeSel) {
+ case SXG_UCODE_SAHARA: // Sahara operational ucode
+ numSections = SNumSections;
+ for (i = 0; i < numSections; i++) {
+ sectionSize[i] = SSectionSize[i];
+ sectionStart[i] = SSectionStart[i];
+ }
+ break;
+ default:
+ printk(KERN_ERR KBUILD_MODNAME
+ ": Woah, big error with the microcode!\n");
+ break;
+ }
+
+ DBG_ERROR("sxg: RESET THE CARD\n");
+ // First, reset the card
+ WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH);
+
+ // Download each section of the microcode as specified in
+ // its download file. The *download.c file is generated using
+ // the saharaobjtoc facility which converts the metastep .obj
+ // file to a .c file which contains a two dimentional array.
+ for (Section = 0; Section < numSections; Section++) {
+ DBG_ERROR("sxg: SECTION # %d\n", Section);
+ switch (UcodeSel) {
+ case SXG_UCODE_SAHARA:
+ Instruction = (u32 *) & SaharaUCode[Section][0];
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ BaseAddress = sectionStart[Section];
+ ThisSectionSize = sectionSize[Section] / 12; // Size in instructions
+ for (AddressOffset = 0; AddressOffset < ThisSectionSize;
+ AddressOffset++) {
+ Address = BaseAddress + AddressOffset;
+ ASSERT((Address & ~MICROCODE_ADDRESS_MASK) == 0);
+ // Write instruction bits 31 - 0
+ WRITE_REG(HwRegs->UcodeDataLow, *Instruction, FLUSH);
+ // Write instruction bits 63-32
+ WRITE_REG(HwRegs->UcodeDataMiddle, *(Instruction + 1),
+ FLUSH);
+ // Write instruction bits 95-64
+ WRITE_REG(HwRegs->UcodeDataHigh, *(Instruction + 2),
+ FLUSH);
+ // Write instruction address with the WRITE bit set
+ WRITE_REG(HwRegs->UcodeAddr,
+ (Address | MICROCODE_ADDRESS_WRITE), FLUSH);
+ // Sahara bug in the ucode download logic - the write to DataLow
+ // for the next instruction could get corrupted. To avoid this,
+ // write to DataLow again for this instruction (which may get
+ // corrupted, but it doesn't matter), then increment the address
+ // and write the data for the next instruction to DataLow. That
+ // write should succeed.
+ WRITE_REG(HwRegs->UcodeDataLow, *Instruction, TRUE);
+ // Advance 3 u32S to start of next instruction
+ Instruction += 3;
+ }
+ }
+ // Now repeat the entire operation reading the instruction back and
+ // checking for parity errors
+ for (Section = 0; Section < numSections; Section++) {
+ DBG_ERROR("sxg: check SECTION # %d\n", Section);
+ switch (UcodeSel) {
+ case SXG_UCODE_SAHARA:
+ Instruction = (u32 *) & SaharaUCode[Section][0];
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ BaseAddress = sectionStart[Section];
+ ThisSectionSize = sectionSize[Section] / 12; // Size in instructions
+ for (AddressOffset = 0; AddressOffset < ThisSectionSize;
+ AddressOffset++) {
+ Address = BaseAddress + AddressOffset;
+ // Write the address with the READ bit set
+ WRITE_REG(HwRegs->UcodeAddr,
+ (Address | MICROCODE_ADDRESS_READ), FLUSH);
+ // Read it back and check parity bit.
+ READ_REG(HwRegs->UcodeAddr, ValueRead);
+ if (ValueRead & MICROCODE_ADDRESS_PARITY) {
+ DBG_ERROR("sxg: %s PARITY ERROR\n",
+ __FUNCTION__);
+
+ return (FALSE); // Parity error
+ }
+ ASSERT((ValueRead & MICROCODE_ADDRESS_MASK) == Address);
+ // Read the instruction back and compare
+ READ_REG(HwRegs->UcodeDataLow, ValueRead);
+ if (ValueRead != *Instruction) {
+ DBG_ERROR("sxg: %s MISCOMPARE LOW\n",
+ __FUNCTION__);
+ return (FALSE); // Miscompare
+ }
+ READ_REG(HwRegs->UcodeDataMiddle, ValueRead);
+ if (ValueRead != *(Instruction + 1)) {
+ DBG_ERROR("sxg: %s MISCOMPARE MIDDLE\n",
+ __FUNCTION__);
+ return (FALSE); // Miscompare
+ }
+ READ_REG(HwRegs->UcodeDataHigh, ValueRead);
+ if (ValueRead != *(Instruction + 2)) {
+ DBG_ERROR("sxg: %s MISCOMPARE HIGH\n",
+ __FUNCTION__);
+ return (FALSE); // Miscompare
+ }
+ // Advance 3 u32S to start of next instruction
+ Instruction += 3;
+ }
+ }
+
+ // Everything OK, Go.
+ WRITE_REG(HwRegs->UcodeAddr, MICROCODE_ADDRESS_GO, FLUSH);
+
+ // Poll the CardUp register to wait for microcode to initialize
+ // Give up after 10,000 attemps (500ms).
+ for (i = 0; i < 10000; i++) {
+ udelay(50);
+ READ_REG(adapter->UcodeRegs[0].CardUp, ValueRead);
+ if (ValueRead == 0xCAFE) {
+ DBG_ERROR("sxg: %s BOO YA 0xCAFE\n", __FUNCTION__);
+ break;
+ }
+ }
+ if (i == 10000) {
+ DBG_ERROR("sxg: %s TIMEOUT\n", __FUNCTION__);
+
+ return (FALSE); // Timeout
+ }
+ // Now write the LoadSync register. This is used to
+ // synchronize with the card so it can scribble on the memory
+ // that contained 0xCAFE from the "CardUp" step above
+ if (UcodeSel == SXG_UCODE_SAHARA) {
+ WRITE_REG(adapter->UcodeRegs[0].LoadSync, 0, FLUSH);
+ }
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDnldUcd",
+ adapter, 0, 0, 0);
+ DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+
+ return (TRUE);
+}
+
+/*
+ * sxg_allocate_resources - Allocate memory and locks
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * int
+ */
+static int sxg_allocate_resources(p_adapter_t adapter)
+{
+ int status;
+ u32 i;
+ u32 RssIds, IsrCount;
+// PSXG_XMT_RING XmtRing;
+// PSXG_RCV_RING RcvRing;
+
+ DBG_ERROR("%s ENTER\n", __FUNCTION__);
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocRes",
+ adapter, 0, 0, 0);
+
+ // Windows tells us how many CPUs it plans to use for
+ // RSS
+ RssIds = SXG_RSS_CPU_COUNT(adapter);
+ IsrCount = adapter->MsiEnabled ? RssIds : 1;
+
+ DBG_ERROR("%s Setup the spinlocks\n", __FUNCTION__);
+
+ // Allocate spinlocks and initialize listheads first.
+ spin_lock_init(&adapter->RcvQLock);
+ spin_lock_init(&adapter->SglQLock);
+ spin_lock_init(&adapter->XmtZeroLock);
+ spin_lock_init(&adapter->Bit64RegLock);
+ spin_lock_init(&adapter->AdapterLock);
+
+ DBG_ERROR("%s Setup the lists\n", __FUNCTION__);
+
+ InitializeListHead(&adapter->FreeRcvBuffers);
+ InitializeListHead(&adapter->FreeRcvBlocks);
+ InitializeListHead(&adapter->AllRcvBlocks);
+ InitializeListHead(&adapter->FreeSglBuffers);
+ InitializeListHead(&adapter->AllSglBuffers);
+
+ // Mark these basic allocations done. This flags essentially
+ // tells the SxgFreeResources routine that it can grab spinlocks
+ // and reference listheads.
+ adapter->BasicAllocations = TRUE;
+ // Main allocation loop. Start with the maximum supported by
+ // the microcode and back off if memory allocation
+ // fails. If we hit a minimum, fail.
+
+ for (;;) {
+ DBG_ERROR("%s Allocate XmtRings size[%lx]\n", __FUNCTION__,
+ (sizeof(SXG_XMT_RING) * 1));
+
+ // Start with big items first - receive and transmit rings. At the moment
+ // I'm going to keep the ring size fixed and adjust the number of
+ // TCBs if we fail. Later we might consider reducing the ring size as well..
+ adapter->XmtRings = pci_alloc_consistent(adapter->pcidev,
+ sizeof(SXG_XMT_RING) *
+ 1,
+ &adapter->PXmtRings);
+ DBG_ERROR("%s XmtRings[%p]\n", __FUNCTION__, adapter->XmtRings);
+
+ if (!adapter->XmtRings) {
+ goto per_tcb_allocation_failed;
+ }
+ memset(adapter->XmtRings, 0, sizeof(SXG_XMT_RING) * 1);
+
+ DBG_ERROR("%s Allocate RcvRings size[%lx]\n", __FUNCTION__,
+ (sizeof(SXG_RCV_RING) * 1));
+ adapter->RcvRings =
+ pci_alloc_consistent(adapter->pcidev,
+ sizeof(SXG_RCV_RING) * 1,
+ &adapter->PRcvRings);
+ DBG_ERROR("%s RcvRings[%p]\n", __FUNCTION__, adapter->RcvRings);
+ if (!adapter->RcvRings) {
+ goto per_tcb_allocation_failed;
+ }
+ memset(adapter->RcvRings, 0, sizeof(SXG_RCV_RING) * 1);
+ break;
+
+ per_tcb_allocation_failed:
+ // an allocation failed. Free any successful allocations.
+ if (adapter->XmtRings) {
+ pci_free_consistent(adapter->pcidev,
+ sizeof(SXG_XMT_RING) * 4096,
+ adapter->XmtRings,
+ adapter->PXmtRings);
+ adapter->XmtRings = NULL;
+ }
+ if (adapter->RcvRings) {
+ pci_free_consistent(adapter->pcidev,
+ sizeof(SXG_RCV_RING) * 4096,
+ adapter->RcvRings,
+ adapter->PRcvRings);
+ adapter->RcvRings = NULL;
+ }
+ // Loop around and try again....
+ }
+
+ DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __FUNCTION__);
+ // Initialize rcv zero and xmt zero rings
+ SXG_INITIALIZE_RING(adapter->RcvRingZeroInfo, SXG_RCV_RING_SIZE);
+ SXG_INITIALIZE_RING(adapter->XmtRingZeroInfo, SXG_XMT_RING_SIZE);
+
+ // Sanity check receive data structure format
+ ASSERT((adapter->ReceiveBufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
+ (adapter->ReceiveBufferSize == SXG_RCV_JUMBO_BUFFER_SIZE));
+ ASSERT(sizeof(SXG_RCV_DESCRIPTOR_BLOCK) ==
+ SXG_RCV_DESCRIPTOR_BLOCK_SIZE);
+
+ // Allocate receive data buffers. We allocate a block of buffers and
+ // a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK
+ for (i = 0; i < SXG_INITIAL_RCV_DATA_BUFFERS;
+ i += SXG_RCV_DESCRIPTORS_PER_BLOCK) {
+ sxg_allocate_buffer_memory(adapter,
+ SXG_RCV_BLOCK_SIZE(adapter->
+ ReceiveBufferSize),
+ SXG_BUFFER_TYPE_RCV);
+ }
+ // NBL resource allocation can fail in the 'AllocateComplete' routine, which
+ // doesn't return status. Make sure we got the number of buffers we requested
+ if (adapter->FreeRcvBufferCount < SXG_INITIAL_RCV_DATA_BUFFERS) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF6",
+ adapter, adapter->FreeRcvBufferCount, SXG_MAX_ENTRIES,
+ 0);
+ return (STATUS_RESOURCES);
+ }
+
+ DBG_ERROR("%s Allocate EventRings size[%lx]\n", __FUNCTION__,
+ (sizeof(SXG_EVENT_RING) * RssIds));
+
+ // Allocate event queues.
+ adapter->EventRings = pci_alloc_consistent(adapter->pcidev,
+ sizeof(SXG_EVENT_RING) *
+ RssIds,
+ &adapter->PEventRings);
+
+ if (!adapter->EventRings) {
+ // Caller will call SxgFreeAdapter to clean up above allocations
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF8",
+ adapter, SXG_MAX_ENTRIES, 0, 0);
+ status = STATUS_RESOURCES;
+ goto per_tcb_allocation_failed;
+ }
+ memset(adapter->EventRings, 0, sizeof(SXG_EVENT_RING) * RssIds);
+
+ DBG_ERROR("%s Allocate ISR size[%x]\n", __FUNCTION__, IsrCount);
+ // Allocate ISR
+ adapter->Isr = pci_alloc_consistent(adapter->pcidev,
+ IsrCount, &adapter->PIsr);
+ if (!adapter->Isr) {
+ // Caller will call SxgFreeAdapter to clean up above allocations
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF9",
+ adapter, SXG_MAX_ENTRIES, 0, 0);
+ status = STATUS_RESOURCES;
+ goto per_tcb_allocation_failed;
+ }
+ memset(adapter->Isr, 0, sizeof(u32) * IsrCount);
+
+ DBG_ERROR("%s Allocate shared XMT ring zero index location size[%lx]\n",
+ __FUNCTION__, sizeof(u32));
+
+ // Allocate shared XMT ring zero index location
+ adapter->XmtRingZeroIndex = pci_alloc_consistent(adapter->pcidev,
+ sizeof(u32),
+ &adapter->
+ PXmtRingZeroIndex);
+ if (!adapter->XmtRingZeroIndex) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF10",
+ adapter, SXG_MAX_ENTRIES, 0, 0);
+ status = STATUS_RESOURCES;
+ goto per_tcb_allocation_failed;
+ }
+ memset(adapter->XmtRingZeroIndex, 0, sizeof(u32));
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlcResS",
+ adapter, SXG_MAX_ENTRIES, 0, 0);
+
+ DBG_ERROR("%s EXIT\n", __FUNCTION__);
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_config_pci -
+ *
+ * Set up PCI Configuration space
+ *
+ * Arguments -
+ * pcidev - A pointer to our adapter structure
+ *
+ */
+static void sxg_config_pci(struct pci_dev *pcidev)
+{
+ u16 pci_command;
+ u16 new_command;
+
+ pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
+ DBG_ERROR("sxg: %s PCI command[%4.4x]\n", __FUNCTION__, pci_command);
+ // Set the command register
+ new_command = pci_command | (PCI_COMMAND_MEMORY | // Memory Space Enable
+ PCI_COMMAND_MASTER | // Bus master enable
+ PCI_COMMAND_INVALIDATE | // Memory write and invalidate
+ PCI_COMMAND_PARITY | // Parity error response
+ PCI_COMMAND_SERR | // System ERR
+ PCI_COMMAND_FAST_BACK); // Fast back-to-back
+ if (pci_command != new_command) {
+ DBG_ERROR("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n",
+ __FUNCTION__, pci_command, new_command);
+ pci_write_config_word(pcidev, PCI_COMMAND, new_command);
+ }
+}
+
+static int sxg_entry_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *pci_tbl_entry)
+{
+ static int did_version = 0;
+ int err;
+ struct net_device *netdev;
+ p_adapter_t adapter;
+ void __iomem *memmapped_ioaddr;
+ u32 status = 0;
+ ulong mmio_start = 0;
+ ulong mmio_len = 0;
+
+ DBG_ERROR("sxg: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n",
+ __FUNCTION__, jiffies, smp_processor_id());
+
+ // Initialize trace buffer
+#ifdef ATKDBG
+ SxgTraceBuffer = &LSxgTraceBuffer;
+ SXG_TRACE_INIT(SxgTraceBuffer, TRACE_NOISY);
+#endif
+
+ sxg_global.dynamic_intagg = dynamic_intagg;
+
+ err = pci_enable_device(pcidev);
+
+ DBG_ERROR("Call pci_enable_device(%p) status[%x]\n", pcidev, err);
+ if (err) {
+ return err;
+ }
+
+ if (sxg_debug > 0 && did_version++ == 0) {
+ printk(KERN_INFO "%s\n", sxg_banner);
+ printk(KERN_INFO "%s\n", DRV_VERSION);
+ }
+
+ if (!(err = pci_set_dma_mask(pcidev, DMA_64BIT_MASK))) {
+ DBG_ERROR("pci_set_dma_mask(DMA_64BIT_MASK) successful\n");
+ } else {
+ if ((err = pci_set_dma_mask(pcidev, DMA_32BIT_MASK))) {
+ DBG_ERROR
+ ("No usable DMA configuration, aborting err[%x]\n",
+ err);
+ return err;
+ }
+ DBG_ERROR("pci_set_dma_mask(DMA_32BIT_MASK) successful\n");
+ }
+
+ DBG_ERROR("Call pci_request_regions\n");
+
+ err = pci_request_regions(pcidev, DRV_NAME);
+ if (err) {
+ DBG_ERROR("pci_request_regions FAILED err[%x]\n", err);
+ return err;
+ }
+
+ DBG_ERROR("call pci_set_master\n");
+ pci_set_master(pcidev);
+
+ DBG_ERROR("call alloc_etherdev\n");
+ netdev = alloc_etherdev(sizeof(adapter_t));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_out_exit_sxg_probe;
+ }
+ DBG_ERROR("alloc_etherdev for slic netdev[%p]\n", netdev);
+
+ SET_NETDEV_DEV(netdev, &pcidev->dev);
+
+ pci_set_drvdata(pcidev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pcidev = pcidev;
+
+ mmio_start = pci_resource_start(pcidev, 0);
+ mmio_len = pci_resource_len(pcidev, 0);
+
+ DBG_ERROR("sxg: call ioremap(mmio_start[%lx], mmio_len[%lx])\n",
+ mmio_start, mmio_len);
+
+ memmapped_ioaddr = ioremap(mmio_start, mmio_len);
+ DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __FUNCTION__,
+ memmapped_ioaddr);
+ if (!memmapped_ioaddr) {
+ DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
+ __FUNCTION__, mmio_len, mmio_start);
+ goto err_out_free_mmio_region;
+ }
+
+ DBG_ERROR
+ ("sxg: %s found Alacritech SXG PCI, MMIO at %p, start[%lx] len[%lx], IRQ %d.\n",
+ __func__, memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq);
+
+ adapter->HwRegs = (void *)memmapped_ioaddr;
+ adapter->base_addr = memmapped_ioaddr;
+
+ mmio_start = pci_resource_start(pcidev, 2);
+ mmio_len = pci_resource_len(pcidev, 2);
+
+ DBG_ERROR("sxg: call ioremap(mmio_start[%lx], mmio_len[%lx])\n",
+ mmio_start, mmio_len);
+
+ memmapped_ioaddr = ioremap(mmio_start, mmio_len);
+ DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __func__,
+ memmapped_ioaddr);
+ if (!memmapped_ioaddr) {
+ DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
+ __FUNCTION__, mmio_len, mmio_start);
+ goto err_out_free_mmio_region;
+ }
+
+ DBG_ERROR("sxg: %s found Alacritech SXG PCI, MMIO at %p, "
+ "start[%lx] len[%lx], IRQ %d.\n", __func__,
+ memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq);
+
+ adapter->UcodeRegs = (void *)memmapped_ioaddr;
+
+ adapter->State = SXG_STATE_INITIALIZING;
+ // Maintain a list of all adapters anchored by
+ // the global SxgDriver structure.
+ adapter->Next = SxgDriver.Adapters;
+ SxgDriver.Adapters = adapter;
+ adapter->AdapterID = ++SxgDriver.AdapterID;
+
+ // Initialize CRC table used to determine multicast hash
+ sxg_mcast_init_crc32();
+
+ adapter->JumboEnabled = FALSE;
+ adapter->RssEnabled = FALSE;
+ if (adapter->JumboEnabled) {
+ adapter->FrameSize = JUMBOMAXFRAME;
+ adapter->ReceiveBufferSize = SXG_RCV_JUMBO_BUFFER_SIZE;
+ } else {
+ adapter->FrameSize = ETHERMAXFRAME;
+ adapter->ReceiveBufferSize = SXG_RCV_DATA_BUFFER_SIZE;
+ }
+
+// status = SXG_READ_EEPROM(adapter);
+// if (!status) {
+// goto sxg_init_bad;
+// }
+
+ DBG_ERROR("sxg: %s ENTER sxg_config_pci\n", __FUNCTION__);
+ sxg_config_pci(pcidev);
+ DBG_ERROR("sxg: %s EXIT sxg_config_pci\n", __FUNCTION__);
+
+ DBG_ERROR("sxg: %s ENTER sxg_init_driver\n", __FUNCTION__);
+ sxg_init_driver();
+ DBG_ERROR("sxg: %s EXIT sxg_init_driver\n", __FUNCTION__);
+
+ adapter->vendid = pci_tbl_entry->vendor;
+ adapter->devid = pci_tbl_entry->device;
+ adapter->subsysid = pci_tbl_entry->subdevice;
+ adapter->busnumber = pcidev->bus->number;
+ adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F);
+ adapter->functionnumber = (pcidev->devfn & 0x7);
+ adapter->memorylength = pci_resource_len(pcidev, 0);
+ adapter->irq = pcidev->irq;
+ adapter->next_netdevice = head_netdevice;
+ head_netdevice = netdev;
+// adapter->chipid = chip_idx;
+ adapter->port = 0; //adapter->functionnumber;
+ adapter->cardindex = adapter->port;
+
+ // Allocate memory and other resources
+ DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __FUNCTION__);
+ status = sxg_allocate_resources(adapter);
+ DBG_ERROR("sxg: %s EXIT sxg_allocate_resources status %x\n",
+ __FUNCTION__, status);
+ if (status != STATUS_SUCCESS) {
+ goto err_out_unmap;
+ }
+
+ DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __FUNCTION__);
+ if (sxg_download_microcode(adapter, SXG_UCODE_SAHARA)) {
+ DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n",
+ __FUNCTION__);
+ sxg_adapter_set_hwaddr(adapter);
+ } else {
+ adapter->state = ADAPT_FAIL;
+ adapter->linkstate = LINK_DOWN;
+ DBG_ERROR("sxg_download_microcode FAILED status[%x]\n", status);
+ }
+
+ netdev->base_addr = (unsigned long)adapter->base_addr;
+ netdev->irq = adapter->irq;
+ netdev->open = sxg_entry_open;
+ netdev->stop = sxg_entry_halt;
+ netdev->hard_start_xmit = sxg_send_packets;
+ netdev->do_ioctl = sxg_ioctl;
+#if XXXTODO
+ netdev->set_mac_address = sxg_mac_set_address;
+#if SLIC_GET_STATS_ENABLED
+ netdev->get_stats = sxg_get_stats;
+#endif
+ netdev->set_multicast_list = sxg_mcast_set_list;
+#endif
+
+ strcpy(netdev->name, "eth%d");
+// strcpy(netdev->name, pci_name(pcidev));
+ if ((err = register_netdev(netdev))) {
+ DBG_ERROR("Cannot register net device, aborting. %s\n",
+ netdev->name);
+ goto err_out_unmap;
+ }
+
+ DBG_ERROR
+ ("sxg: %s addr 0x%lx, irq %d, MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+ netdev->name, netdev->base_addr, pcidev->irq, netdev->dev_addr[0],
+ netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3],
+ netdev->dev_addr[4], netdev->dev_addr[5]);
+
+//sxg_init_bad:
+ ASSERT(status == FALSE);
+// sxg_free_adapter(adapter);
+
+ DBG_ERROR("sxg: %s EXIT status[%x] jiffies[%lx] cpu %d\n", __FUNCTION__,
+ status, jiffies, smp_processor_id());
+ return status;
+
+ err_out_unmap:
+ iounmap((void *)memmapped_ioaddr);
+
+ err_out_free_mmio_region:
+ release_mem_region(mmio_start, mmio_len);
+
+ err_out_exit_sxg_probe:
+
+ DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __FUNCTION__, jiffies,
+ smp_processor_id());
+
+ return -ENODEV;
+}
+
+/***********************************************************************
+ * LINE BASE Interrupt routines..
+ ***********************************************************************/
+/*
+ *
+ * sxg_disable_interrupt
+ *
+ * DisableInterrupt Handler
+ *
+ * Arguments:
+ *
+ * adapter: Our adapter structure
+ *
+ * Return Value:
+ * None.
+ */
+static void sxg_disable_interrupt(p_adapter_t adapter)
+{
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DisIntr",
+ adapter, adapter->InterruptsEnabled, 0, 0);
+ // For now, RSS is disabled with line based interrupts
+ ASSERT(adapter->RssEnabled == FALSE);
+ ASSERT(adapter->MsiEnabled == FALSE);
+ //
+ // Turn off interrupts by writing to the icr register.
+ //
+ WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE);
+
+ adapter->InterruptsEnabled = 0;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDisIntr",
+ adapter, adapter->InterruptsEnabled, 0, 0);
+}
+
+/*
+ *
+ * sxg_enable_interrupt
+ *
+ * EnableInterrupt Handler
+ *
+ * Arguments:
+ *
+ * adapter: Our adapter structure
+ *
+ * Return Value:
+ * None.
+ */
+static void sxg_enable_interrupt(p_adapter_t adapter)
+{
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "EnIntr",
+ adapter, adapter->InterruptsEnabled, 0, 0);
+ // For now, RSS is disabled with line based interrupts
+ ASSERT(adapter->RssEnabled == FALSE);
+ ASSERT(adapter->MsiEnabled == FALSE);
+ //
+ // Turn on interrupts by writing to the icr register.
+ //
+ WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE);
+
+ adapter->InterruptsEnabled = 1;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XEnIntr",
+ adapter, 0, 0, 0);
+}
+
+/*
+ *
+ * sxg_isr - Process an line-based interrupt
+ *
+ * Arguments:
+ * Context - Our adapter structure
+ * QueueDefault - Output parameter to queue to default CPU
+ * TargetCpus - Output bitmap to schedule DPC's
+ *
+ * Return Value:
+ * TRUE if our interrupt
+ */
+static irqreturn_t sxg_isr(int irq, void *dev_id)
+{
+ p_net_device dev = (p_net_device) dev_id;
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+// u32 CpuMask = 0, i;
+
+ adapter->Stats.NumInts++;
+ if (adapter->Isr[0] == 0) {
+ // The SLIC driver used to experience a number of spurious interrupts
+ // due to the delay associated with the masking of the interrupt
+ // (we'd bounce back in here). If we see that again with Sahara,
+ // add a READ_REG of the Icr register after the WRITE_REG below.
+ adapter->Stats.FalseInts++;
+ return IRQ_NONE;
+ }
+ //
+ // Move the Isr contents and clear the value in
+ // shared memory, and mask interrupts
+ //
+ adapter->IsrCopy[0] = adapter->Isr[0];
+ adapter->Isr[0] = 0;
+ WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE);
+// ASSERT(adapter->IsrDpcsPending == 0);
+#if XXXTODO // RSS Stuff
+ // If RSS is enabled and the ISR specifies
+ // SXG_ISR_EVENT, then schedule DPC's
+ // based on event queues.
+ if (adapter->RssEnabled && (adapter->IsrCopy[0] & SXG_ISR_EVENT)) {
+ for (i = 0;
+ i < adapter->RssSystemInfo->ProcessorInfo.RssCpuCount;
+ i++) {
+ PSXG_EVENT_RING EventRing = &adapter->EventRings[i];
+ PSXG_EVENT Event =
+ &EventRing->Ring[adapter->NextEvent[i]];
+ unsigned char Cpu =
+ adapter->RssSystemInfo->RssIdToCpu[i];
+ if (Event->Status & EVENT_STATUS_VALID) {
+ adapter->IsrDpcsPending++;
+ CpuMask |= (1 << Cpu);
+ }
+ }
+ }
+ // Now, either schedule the CPUs specified by the CpuMask,
+ // or queue default
+ if (CpuMask) {
+ *QueueDefault = FALSE;
+ } else {
+ adapter->IsrDpcsPending = 1;
+ *QueueDefault = TRUE;
+ }
+ *TargetCpus = CpuMask;
+#endif
+ //
+ // There are no DPCs in Linux, so call the handler now
+ //
+ sxg_handle_interrupt(adapter);
+
+ return IRQ_HANDLED;
+}
+
+static void sxg_handle_interrupt(p_adapter_t adapter)
+{
+// unsigned char RssId = 0;
+ u32 NewIsr;
+
+ if (adapter->Stats.RcvNoBuffer < 5) {
+ DBG_ERROR("Enter sxg_handle_interrupt ISR[%x]\n",
+ adapter->IsrCopy[0]);
+ }
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr",
+ adapter, adapter->IsrCopy[0], 0, 0);
+ // For now, RSS is disabled with line based interrupts
+ ASSERT(adapter->RssEnabled == FALSE);
+ ASSERT(adapter->MsiEnabled == FALSE);
+ ASSERT(adapter->IsrCopy[0]);
+/////////////////////////////
+
+ // Always process the event queue.
+ sxg_process_event_queue(adapter,
+ (adapter->RssEnabled ? /*RssId */ 0 : 0));
+
+#if XXXTODO // RSS stuff
+ if (--adapter->IsrDpcsPending) {
+ // We're done.
+ ASSERT(adapter->RssEnabled);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DPCsPend",
+ adapter, 0, 0, 0);
+ return;
+ }
+#endif
+ //
+ // Last (or only) DPC processes the ISR and clears the interrupt.
+ //
+ NewIsr = sxg_process_isr(adapter, 0);
+ //
+ // Reenable interrupts
+ //
+ adapter->IsrCopy[0] = 0;
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr",
+ adapter, NewIsr, 0, 0);
+
+ if (adapter->Stats.RcvNoBuffer < 5) {
+ DBG_ERROR
+ ("Exit sxg_handle_interrupt2 after enabling interrupt\n");
+ }
+
+ WRITE_REG(adapter->UcodeRegs[0].Isr, NewIsr, TRUE);
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt",
+ adapter, 0, 0, 0);
+}
+
+/*
+ *
+ * sxg_process_isr - Process an interrupt. Called from the line-based and
+ * message based interrupt DPC routines
+ *
+ * Arguments:
+ * adapter - Our adapter structure
+ * Queue - The ISR that needs processing
+ *
+ * Return Value:
+ * None
+ */
+static int sxg_process_isr(p_adapter_t adapter, u32 MessageId)
+{
+ u32 Isr = adapter->IsrCopy[MessageId];
+ u32 NewIsr = 0;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ProcIsr",
+ adapter, Isr, 0, 0);
+
+ // Error
+ if (Isr & SXG_ISR_ERR) {
+ if (Isr & SXG_ISR_PDQF) {
+ adapter->Stats.PdqFull++;
+ DBG_ERROR("%s: SXG_ISR_ERR PDQF!!\n", __FUNCTION__);
+ }
+ // No host buffer
+ if (Isr & SXG_ISR_RMISS) {
+ // There is a bunch of code in the SLIC driver which
+ // attempts to process more receive events per DPC
+ // if we start to fall behind. We'll probably
+ // need to do something similar here, but hold
+ // off for now. I don't want to make the code more
+ // complicated than strictly needed.
+ adapter->Stats.RcvNoBuffer++;
+ if (adapter->Stats.RcvNoBuffer < 5) {
+ DBG_ERROR("%s: SXG_ISR_ERR RMISS!!\n",
+ __FUNCTION__);
+ }
+ }
+ // Card crash
+ if (Isr & SXG_ISR_DEAD) {
+ // Set aside the crash info and set the adapter state to RESET
+ adapter->CrashCpu =
+ (unsigned char)((Isr & SXG_ISR_CPU) >>
+ SXG_ISR_CPU_SHIFT);
+ adapter->CrashLocation = (ushort) (Isr & SXG_ISR_CRASH);
+ adapter->Dead = TRUE;
+ DBG_ERROR("%s: ISR_DEAD %x, CPU: %d\n", __FUNCTION__,
+ adapter->CrashLocation, adapter->CrashCpu);
+ }
+ // Event ring full
+ if (Isr & SXG_ISR_ERFULL) {
+ // Same issue as RMISS, really. This means the
+ // host is falling behind the card. Need to increase
+ // event ring size, process more events per interrupt,
+ // and/or reduce/remove interrupt aggregation.
+ adapter->Stats.EventRingFull++;
+ DBG_ERROR("%s: SXG_ISR_ERR EVENT RING FULL!!\n",
+ __FUNCTION__);
+ }
+ // Transmit drop - no DRAM buffers or XMT error
+ if (Isr & SXG_ISR_XDROP) {
+ adapter->Stats.XmtDrops++;
+ adapter->Stats.XmtErrors++;
+ DBG_ERROR("%s: SXG_ISR_ERR XDROP!!\n", __FUNCTION__);
+ }
+ }
+ // Slowpath send completions
+ if (Isr & SXG_ISR_SPSEND) {
+ sxg_complete_slow_send(adapter);
+ }
+ // Dump
+ if (Isr & SXG_ISR_UPC) {
+ ASSERT(adapter->DumpCmdRunning); // Maybe change when debug is added..
+ adapter->DumpCmdRunning = FALSE;
+ }
+ // Link event
+ if (Isr & SXG_ISR_LINK) {
+ sxg_link_event(adapter);
+ }
+ // Debug - breakpoint hit
+ if (Isr & SXG_ISR_BREAK) {
+ // At the moment AGDB isn't written to support interactive
+ // debug sessions. When it is, this interrupt will be used
+ // to signal AGDB that it has hit a breakpoint. For now, ASSERT.
+ ASSERT(0);
+ }
+ // Heartbeat response
+ if (Isr & SXG_ISR_PING) {
+ adapter->PingOutstanding = FALSE;
+ }
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XProcIsr",
+ adapter, Isr, NewIsr, 0);
+
+ return (NewIsr);
+}
+
+/*
+ *
+ * sxg_process_event_queue - Process our event queue
+ *
+ * Arguments:
+ * - adapter - Adapter structure
+ * - RssId - The event queue requiring processing
+ *
+ * Return Value:
+ * None.
+ */
+static u32 sxg_process_event_queue(p_adapter_t adapter, u32 RssId)
+{
+ PSXG_EVENT_RING EventRing = &adapter->EventRings[RssId];
+ PSXG_EVENT Event = &EventRing->Ring[adapter->NextEvent[RssId]];
+ u32 EventsProcessed = 0, Batches = 0;
+ u32 num_skbs = 0;
+ struct sk_buff *skb;
+#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
+ struct sk_buff *prev_skb = NULL;
+ struct sk_buff *IndicationList[SXG_RCV_ARRAYSIZE];
+ u32 Index;
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+#endif
+ u32 ReturnStatus = 0;
+
+ ASSERT((adapter->State == SXG_STATE_RUNNING) ||
+ (adapter->State == SXG_STATE_PAUSING) ||
+ (adapter->State == SXG_STATE_PAUSED) ||
+ (adapter->State == SXG_STATE_HALTING));
+ // We may still have unprocessed events on the queue if
+ // the card crashed. Don't process them.
+ if (adapter->Dead) {
+ return (0);
+ }
+ // In theory there should only be a single processor that
+ // accesses this queue, and only at interrupt-DPC time. So
+ // we shouldn't need a lock for any of this.
+ while (Event->Status & EVENT_STATUS_VALID) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event",
+ Event, Event->Code, Event->Status,
+ adapter->NextEvent);
+ switch (Event->Code) {
+ case EVENT_CODE_BUFFERS:
+ ASSERT(!(Event->CommandIndex & 0xFF00)); // SXG_RING_INFO Head & Tail == unsigned char
+ //
+ sxg_complete_descriptor_blocks(adapter,
+ Event->CommandIndex);
+ //
+ break;
+ case EVENT_CODE_SLOWRCV:
+ --adapter->RcvBuffersOnCard;
+ if ((skb = sxg_slow_receive(adapter, Event))) {
+ u32 rx_bytes;
+#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
+ // Add it to our indication list
+ SXG_ADD_RCV_PACKET(adapter, skb, prev_skb,
+ IndicationList, num_skbs);
+ // In Linux, we just pass up each skb to the protocol above at this point,
+ // there is no capability of an indication list.
+#else
+// CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE);
+ rx_bytes = Event->Length; // (rcvbuf->length & IRHDDR_FLEN_MSK);
+ skb_put(skb, rx_bytes);
+ adapter->stats.rx_packets++;
+ adapter->stats.rx_bytes += rx_bytes;
+#if SXG_OFFLOAD_IP_CHECKSUM
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+#endif
+ skb->dev = adapter->netdev;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ netif_rx(skb);
+#endif
+ }
+ break;
+ default:
+ DBG_ERROR("%s: ERROR Invalid EventCode %d\n",
+ __FUNCTION__, Event->Code);
+// ASSERT(0);
+ }
+ // See if we need to restock card receive buffers.
+ // There are two things to note here:
+ // First - This test is not SMP safe. The
+ // adapter->BuffersOnCard field is protected via atomic interlocked calls, but
+ // we do not protect it with respect to these tests. The only way to do that
+ // is with a lock, and I don't want to grab a lock every time we adjust the
+ // BuffersOnCard count. Instead, we allow the buffer replenishment to be off
+ // once in a while. The worst that can happen is the card is given one
+ // more-or-less descriptor block than the arbitrary value we've chosen.
+ // No big deal
+ // In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard is adjusted.
+ // Second - We expect this test to rarely evaluate to true. We attempt to
+ // refill descriptor blocks as they are returned to us
+ // (sxg_complete_descriptor_blocks), so The only time this should evaluate
+ // to true is when sxg_complete_descriptor_blocks failed to allocate
+ // receive buffers.
+ if (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
+ sxg_stock_rcv_buffers(adapter);
+ }
+ // It's more efficient to just set this to zero.
+ // But clearing the top bit saves potential debug info...
+ Event->Status &= ~EVENT_STATUS_VALID;
+ // Advanct to the next event
+ SXG_ADVANCE_INDEX(adapter->NextEvent[RssId], EVENT_RING_SIZE);
+ Event = &EventRing->Ring[adapter->NextEvent[RssId]];
+ EventsProcessed++;
+ if (EventsProcessed == EVENT_RING_BATCH) {
+ // Release a batch of events back to the card
+ WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
+ EVENT_RING_BATCH, FALSE);
+ EventsProcessed = 0;
+ // If we've processed our batch limit, break out of the
+ // loop and return SXG_ISR_EVENT to arrange for us to
+ // be called again
+ if (Batches++ == EVENT_BATCH_LIMIT) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
+ TRACE_NOISY, "EvtLimit", Batches,
+ adapter->NextEvent, 0, 0);
+ ReturnStatus = SXG_ISR_EVENT;
+ break;
+ }
+ }
+ }
+#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
+ //
+ // Indicate any received dumb-nic frames
+ //
+ SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs);
+#endif
+ //
+ // Release events back to the card.
+ //
+ if (EventsProcessed) {
+ WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
+ EventsProcessed, FALSE);
+ }
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XPrcEvnt",
+ Batches, EventsProcessed, adapter->NextEvent, num_skbs);
+
+ return (ReturnStatus);
+}
+
+/*
+ * sxg_complete_slow_send - Complete slowpath or dumb-nic sends
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+
+ * Return
+ * None
+ */
+static void sxg_complete_slow_send(p_adapter_t adapter)
+{
+ PSXG_XMT_RING XmtRing = &adapter->XmtRings[0];
+ PSXG_RING_INFO XmtRingInfo = &adapter->XmtRingZeroInfo;
+ u32 *ContextType;
+ PSXG_CMD XmtCmd;
+
+ // NOTE - This lock is dropped and regrabbed in this loop.
+ // This means two different processors can both be running
+ // through this loop. Be *very* careful.
+ spin_lock(&adapter->XmtZeroLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnds",
+ adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
+
+ while (XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) {
+ // Locate the current Cmd (ring descriptor entry), and
+ // associated SGL, and advance the tail
+ SXG_RETURN_CMD(XmtRing, XmtRingInfo, XmtCmd, ContextType);
+ ASSERT(ContextType);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
+ XmtRingInfo->Head, XmtRingInfo->Tail, XmtCmd, 0);
+ // Clear the SGL field.
+ XmtCmd->Sgl = 0;
+
+ switch (*ContextType) {
+ case SXG_SGL_DUMB:
+ {
+ struct sk_buff *skb;
+ // Dumb-nic send. Command context is the dumb-nic SGL
+ skb = (struct sk_buff *)ContextType;
+ // Complete the send
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
+ TRACE_IMPORTANT, "DmSndCmp", skb, 0,
+ 0, 0);
+ ASSERT(adapter->Stats.XmtQLen);
+ adapter->Stats.XmtQLen--; // within XmtZeroLock
+ adapter->Stats.XmtOk++;
+ // Now drop the lock and complete the send back to
+ // Microsoft. We need to drop the lock because
+ // Microsoft can come back with a chimney send, which
+ // results in a double trip in SxgTcpOuput
+ spin_unlock(&adapter->XmtZeroLock);
+ SXG_COMPLETE_DUMB_SEND(adapter, skb);
+ // and reacquire..
+ spin_lock(&adapter->XmtZeroLock);
+ }
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+ spin_unlock(&adapter->XmtZeroLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
+ adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
+}
+
+/*
+ * sxg_slow_receive
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * Event - Receive event
+ *
+ * Return
+ * skb
+ */
+static struct sk_buff *sxg_slow_receive(p_adapter_t adapter, PSXG_EVENT Event)
+{
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+ struct sk_buff *Packet;
+
+ RcvDataBufferHdr = (PSXG_RCV_DATA_BUFFER_HDR) Event->HostHandle;
+ ASSERT(RcvDataBufferHdr);
+ ASSERT(RcvDataBufferHdr->State == SXG_BUFFER_ONCARD);
+ ASSERT(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr) ==
+ RcvDataBufferHdr->VirtualAddress);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event,
+ RcvDataBufferHdr, RcvDataBufferHdr->State,
+ RcvDataBufferHdr->VirtualAddress);
+ // Drop rcv frames in non-running state
+ switch (adapter->State) {
+ case SXG_STATE_RUNNING:
+ break;
+ case SXG_STATE_PAUSING:
+ case SXG_STATE_PAUSED:
+ case SXG_STATE_HALTING:
+ goto drop;
+ default:
+ ASSERT(0);
+ goto drop;
+ }
+
+ // Change buffer state to UPSTREAM
+ RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM;
+ if (Event->Status & EVENT_STATUS_RCVERR) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvError",
+ Event, Event->Status, Event->HostHandle, 0);
+ // XXXTODO - Remove this print later
+ DBG_ERROR("SXG: Receive error %x\n", *(u32 *)
+ SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr));
+ sxg_process_rcv_error(adapter, *(u32 *)
+ SXG_RECEIVE_DATA_LOCATION
+ (RcvDataBufferHdr));
+ goto drop;
+ }
+#if XXXTODO // VLAN stuff
+ // If there's a VLAN tag, extract it and validate it
+ if (((p_ether_header) (SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)))->
+ EtherType == ETHERTYPE_VLAN) {
+ if (SxgExtractVlanHeader(adapter, RcvDataBufferHdr, Event) !=
+ STATUS_SUCCESS) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY,
+ "BadVlan", Event,
+ SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
+ Event->Length, 0);
+ goto drop;
+ }
+ }
+#endif
+ //
+ // Dumb-nic frame. See if it passes our mac filter and update stats
+ //
+ if (!sxg_mac_filter(adapter, (p_ether_header)
+ SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
+ Event->Length)) {
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvFiltr",
+ Event, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
+ Event->Length, 0);
+ goto drop;
+ }
+
+ Packet = RcvDataBufferHdr->SxgDumbRcvPacket;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumbRcv",
+ RcvDataBufferHdr, Packet, Event->Length, 0);
+ //
+ // Lastly adjust the receive packet length.
+ //
+ SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event);
+
+ return (Packet);
+
+ drop:
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DropRcv",
+ RcvDataBufferHdr, Event->Length, 0, 0);
+ adapter->Stats.RcvDiscards++;
+ spin_lock(&adapter->RcvQLock);
+ SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
+ spin_unlock(&adapter->RcvQLock);
+ return (NULL);
+}
+
+/*
+ * sxg_process_rcv_error - process receive error and update
+ * stats
+ *
+ * Arguments:
+ * adapter - Adapter structure
+ * ErrorStatus - 4-byte receive error status
+ *
+ * Return Value:
+ * None
+ */
+static void sxg_process_rcv_error(p_adapter_t adapter, u32 ErrorStatus)
+{
+ u32 Error;
+
+ adapter->Stats.RcvErrors++;
+
+ if (ErrorStatus & SXG_RCV_STATUS_TRANSPORT_ERROR) {
+ Error = ErrorStatus & SXG_RCV_STATUS_TRANSPORT_MASK;
+ switch (Error) {
+ case SXG_RCV_STATUS_TRANSPORT_CSUM:
+ adapter->Stats.TransportCsum++;
+ break;
+ case SXG_RCV_STATUS_TRANSPORT_UFLOW:
+ adapter->Stats.TransportUflow++;
+ break;
+ case SXG_RCV_STATUS_TRANSPORT_HDRLEN:
+ adapter->Stats.TransportHdrLen++;
+ break;
+ }
+ }
+ if (ErrorStatus & SXG_RCV_STATUS_NETWORK_ERROR) {
+ Error = ErrorStatus & SXG_RCV_STATUS_NETWORK_MASK;
+ switch (Error) {
+ case SXG_RCV_STATUS_NETWORK_CSUM:
+ adapter->Stats.NetworkCsum++;
+ break;
+ case SXG_RCV_STATUS_NETWORK_UFLOW:
+ adapter->Stats.NetworkUflow++;
+ break;
+ case SXG_RCV_STATUS_NETWORK_HDRLEN:
+ adapter->Stats.NetworkHdrLen++;
+ break;
+ }
+ }
+ if (ErrorStatus & SXG_RCV_STATUS_PARITY) {
+ adapter->Stats.Parity++;
+ }
+ if (ErrorStatus & SXG_RCV_STATUS_LINK_ERROR) {
+ Error = ErrorStatus & SXG_RCV_STATUS_LINK_MASK;
+ switch (Error) {
+ case SXG_RCV_STATUS_LINK_PARITY:
+ adapter->Stats.LinkParity++;
+ break;
+ case SXG_RCV_STATUS_LINK_EARLY:
+ adapter->Stats.LinkEarly++;
+ break;
+ case SXG_RCV_STATUS_LINK_BUFOFLOW:
+ adapter->Stats.LinkBufOflow++;
+ break;
+ case SXG_RCV_STATUS_LINK_CODE:
+ adapter->Stats.LinkCode++;
+ break;
+ case SXG_RCV_STATUS_LINK_DRIBBLE:
+ adapter->Stats.LinkDribble++;
+ break;
+ case SXG_RCV_STATUS_LINK_CRC:
+ adapter->Stats.LinkCrc++;
+ break;
+ case SXG_RCV_STATUS_LINK_OFLOW:
+ adapter->Stats.LinkOflow++;
+ break;
+ case SXG_RCV_STATUS_LINK_UFLOW:
+ adapter->Stats.LinkUflow++;
+ break;
+ }
+ }
+}
+
+/*
+ * sxg_mac_filter
+ *
+ * Arguments:
+ * adapter - Adapter structure
+ * pether - Ethernet header
+ * length - Frame length
+ *
+ * Return Value:
+ * TRUE if the frame is to be allowed
+ */
+static bool sxg_mac_filter(p_adapter_t adapter, p_ether_header EtherHdr,
+ ushort length)
+{
+ bool EqualAddr;
+
+ if (SXG_MULTICAST_PACKET(EtherHdr)) {
+ if (SXG_BROADCAST_PACKET(EtherHdr)) {
+ // broadcast
+ if (adapter->MacFilter & MAC_BCAST) {
+ adapter->Stats.DumbRcvBcastPkts++;
+ adapter->Stats.DumbRcvBcastBytes += length;
+ adapter->Stats.DumbRcvPkts++;
+ adapter->Stats.DumbRcvBytes += length;
+ return (TRUE);
+ }
+ } else {
+ // multicast
+ if (adapter->MacFilter & MAC_ALLMCAST) {
+ adapter->Stats.DumbRcvMcastPkts++;
+ adapter->Stats.DumbRcvMcastBytes += length;
+ adapter->Stats.DumbRcvPkts++;
+ adapter->Stats.DumbRcvBytes += length;
+ return (TRUE);
+ }
+ if (adapter->MacFilter & MAC_MCAST) {
+ PSXG_MULTICAST_ADDRESS MulticastAddrs =
+ adapter->MulticastAddrs;
+ while (MulticastAddrs) {
+ ETHER_EQ_ADDR(MulticastAddrs->Address,
+ EtherHdr->ether_dhost,
+ EqualAddr);
+ if (EqualAddr) {
+ adapter->Stats.
+ DumbRcvMcastPkts++;
+ adapter->Stats.
+ DumbRcvMcastBytes += length;
+ adapter->Stats.DumbRcvPkts++;
+ adapter->Stats.DumbRcvBytes +=
+ length;
+ return (TRUE);
+ }
+ MulticastAddrs = MulticastAddrs->Next;
+ }
+ }
+ }
+ } else if (adapter->MacFilter & MAC_DIRECTED) {
+ // Not broadcast or multicast. Must be directed at us or
+ // the card is in promiscuous mode. Either way, consider it
+ // ours if MAC_DIRECTED is set
+ adapter->Stats.DumbRcvUcastPkts++;
+ adapter->Stats.DumbRcvUcastBytes += length;
+ adapter->Stats.DumbRcvPkts++;
+ adapter->Stats.DumbRcvBytes += length;
+ return (TRUE);
+ }
+ if (adapter->MacFilter & MAC_PROMISC) {
+ // Whatever it is, keep it.
+ adapter->Stats.DumbRcvPkts++;
+ adapter->Stats.DumbRcvBytes += length;
+ return (TRUE);
+ }
+ adapter->Stats.RcvDiscards++;
+ return (FALSE);
+}
+
+static int sxg_register_interrupt(p_adapter_t adapter)
+{
+ if (!adapter->intrregistered) {
+ int retval;
+
+ DBG_ERROR
+ ("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x] %x\n",
+ __FUNCTION__, adapter, adapter->netdev->irq, NR_IRQS);
+
+ spin_unlock_irqrestore(&sxg_global.driver_lock,
+ sxg_global.flags);
+
+ retval = request_irq(adapter->netdev->irq,
+ &sxg_isr,
+ IRQF_SHARED,
+ adapter->netdev->name, adapter->netdev);
+
+ spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
+
+ if (retval) {
+ DBG_ERROR("sxg: request_irq (%s) FAILED [%x]\n",
+ adapter->netdev->name, retval);
+ return (retval);
+ }
+ adapter->intrregistered = 1;
+ adapter->IntRegistered = TRUE;
+ // Disable RSS with line-based interrupts
+ adapter->MsiEnabled = FALSE;
+ adapter->RssEnabled = FALSE;
+ DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n",
+ __FUNCTION__, adapter, adapter->netdev->irq);
+ }
+ return (STATUS_SUCCESS);
+}
+
+static void sxg_deregister_interrupt(p_adapter_t adapter)
+{
+ DBG_ERROR("sxg: %s ENTER adapter[%p]\n", __FUNCTION__, adapter);
+#if XXXTODO
+ slic_init_cleanup(adapter);
+#endif
+ memset(&adapter->stats, 0, sizeof(struct net_device_stats));
+ adapter->error_interrupts = 0;
+ adapter->rcv_interrupts = 0;
+ adapter->xmit_interrupts = 0;
+ adapter->linkevent_interrupts = 0;
+ adapter->upr_interrupts = 0;
+ adapter->num_isrs = 0;
+ adapter->xmit_completes = 0;
+ adapter->rcv_broadcasts = 0;
+ adapter->rcv_multicasts = 0;
+ adapter->rcv_unicasts = 0;
+ DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+}
+
+/*
+ * sxg_if_init
+ *
+ * Perform initialization of our slic interface.
+ *
+ */
+static int sxg_if_init(p_adapter_t adapter)
+{
+ p_net_device dev = adapter->netdev;
+ int status = 0;
+
+ DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d:%d] flags[%x]\n",
+ __FUNCTION__, adapter->netdev->name,
+ adapter->queues_initialized, adapter->state,
+ adapter->linkstate, dev->flags);
+
+ /* adapter should be down at this point */
+ if (adapter->state != ADAPT_DOWN) {
+ DBG_ERROR("sxg_if_init adapter->state != ADAPT_DOWN\n");
+ return (-EIO);
+ }
+ ASSERT(adapter->linkstate == LINK_DOWN);
+
+ adapter->devflags_prev = dev->flags;
+ adapter->macopts = MAC_DIRECTED;
+ if (dev->flags) {
+ DBG_ERROR("sxg: %s (%s) Set MAC options: ", __FUNCTION__,
+ adapter->netdev->name);
+ if (dev->flags & IFF_BROADCAST) {
+ adapter->macopts |= MAC_BCAST;
+ DBG_ERROR("BCAST ");
+ }
+ if (dev->flags & IFF_PROMISC) {
+ adapter->macopts |= MAC_PROMISC;
+ DBG_ERROR("PROMISC ");
+ }
+ if (dev->flags & IFF_ALLMULTI) {
+ adapter->macopts |= MAC_ALLMCAST;
+ DBG_ERROR("ALL_MCAST ");
+ }
+ if (dev->flags & IFF_MULTICAST) {
+ adapter->macopts |= MAC_MCAST;
+ DBG_ERROR("MCAST ");
+ }
+ DBG_ERROR("\n");
+ }
+ status = sxg_register_interrupt(adapter);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("sxg_if_init: sxg_register_interrupt FAILED %x\n",
+ status);
+ sxg_deregister_interrupt(adapter);
+ return (status);
+ }
+
+ adapter->state = ADAPT_UP;
+
+ /*
+ * clear any pending events, then enable interrupts
+ */
+ DBG_ERROR("sxg: %s ENABLE interrupts(slic)\n", __FUNCTION__);
+
+ return (STATUS_SUCCESS);
+}
+
+static int sxg_entry_open(p_net_device dev)
+{
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+ int status;
+
+ ASSERT(adapter);
+ DBG_ERROR("sxg: %s adapter->activated[%d]\n", __FUNCTION__,
+ adapter->activated);
+ DBG_ERROR
+ ("sxg: %s (%s): [jiffies[%lx] cpu %d] dev[%p] adapt[%p] port[%d]\n",
+ __FUNCTION__, adapter->netdev->name, jiffies, smp_processor_id(),
+ adapter->netdev, adapter, adapter->port);
+
+ netif_stop_queue(adapter->netdev);
+
+ spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
+ if (!adapter->activated) {
+ sxg_global.num_sxg_ports_active++;
+ adapter->activated = 1;
+ }
+ // Initialize the adapter
+ DBG_ERROR("sxg: %s ENTER sxg_initialize_adapter\n", __FUNCTION__);
+ status = sxg_initialize_adapter(adapter);
+ DBG_ERROR("sxg: %s EXIT sxg_initialize_adapter status[%x]\n",
+ __FUNCTION__, status);
+
+ if (status == STATUS_SUCCESS) {
+ DBG_ERROR("sxg: %s ENTER sxg_if_init\n", __FUNCTION__);
+ status = sxg_if_init(adapter);
+ DBG_ERROR("sxg: %s EXIT sxg_if_init status[%x]\n", __FUNCTION__,
+ status);
+ }
+
+ if (status != STATUS_SUCCESS) {
+ if (adapter->activated) {
+ sxg_global.num_sxg_ports_active--;
+ adapter->activated = 0;
+ }
+ spin_unlock_irqrestore(&sxg_global.driver_lock,
+ sxg_global.flags);
+ return (status);
+ }
+ DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __FUNCTION__);
+
+ // Enable interrupts
+ SXG_ENABLE_ALL_INTERRUPTS(adapter);
+
+ DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+
+ spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
+ return STATUS_SUCCESS;
+}
+
+static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
+{
+ p_net_device dev = pci_get_drvdata(pcidev);
+ u32 mmio_start = 0;
+ unsigned int mmio_len = 0;
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+
+ ASSERT(adapter);
+ DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __FUNCTION__, dev,
+ adapter);
+ sxg_deregister_interrupt(adapter);
+ sxg_unmap_mmio_space(adapter);
+ DBG_ERROR("sxg: %s unregister_netdev\n", __FUNCTION__);
+ unregister_netdev(dev);
+
+ mmio_start = pci_resource_start(pcidev, 0);
+ mmio_len = pci_resource_len(pcidev, 0);
+
+ DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __FUNCTION__,
+ mmio_start, mmio_len);
+ release_mem_region(mmio_start, mmio_len);
+
+ DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __FUNCTION__,
+ (unsigned int)dev->base_addr);
+ iounmap((char *)dev->base_addr);
+
+ DBG_ERROR("sxg: %s deallocate device\n", __FUNCTION__);
+ kfree(dev);
+ DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+}
+
+static int sxg_entry_halt(p_net_device dev)
+{
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+
+ spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
+ DBG_ERROR("sxg: %s (%s) ENTER\n", __FUNCTION__, dev->name);
+
+ netif_stop_queue(adapter->netdev);
+ adapter->state = ADAPT_DOWN;
+ adapter->linkstate = LINK_DOWN;
+ adapter->devflags_prev = 0;
+ DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n",
+ __FUNCTION__, dev->name, adapter, adapter->state);
+
+ DBG_ERROR("sxg: %s (%s) EXIT\n", __FUNCTION__, dev->name);
+ DBG_ERROR("sxg: %s EXIT\n", __FUNCTION__);
+ spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
+ return (STATUS_SUCCESS);
+}
+
+static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd)
+{
+ ASSERT(rq);
+// DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __FUNCTION__, cmd, rq, dev);
+ switch (cmd) {
+ case SIOCSLICSETINTAGG:
+ {
+// p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+ u32 data[7];
+ u32 intagg;
+
+ if (copy_from_user(data, rq->ifr_data, 28)) {
+ DBG_ERROR
+ ("copy_from_user FAILED getting initial params\n");
+ return -EFAULT;
+ }
+ intagg = data[0];
+ printk(KERN_EMERG
+ "%s: set interrupt aggregation to %d\n",
+ __FUNCTION__, intagg);
+ return 0;
+ }
+
+ default:
+// DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __FUNCTION__, cmd);
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+#define NORMAL_ETHFRAME 0
+
+/*
+ *
+ * sxg_send_packets - Send a skb packet
+ *
+ * Arguments:
+ * skb - The packet to send
+ * dev - Our linux net device that refs our adapter
+ *
+ * Return:
+ * 0 regardless of outcome XXXTODO refer to e1000 driver
+ */
+static int sxg_send_packets(struct sk_buff *skb, p_net_device dev)
+{
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+ u32 status = STATUS_SUCCESS;
+
+ DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__,
+ skb);
+ // Check the adapter state
+ switch (adapter->State) {
+ case SXG_STATE_INITIALIZING:
+ case SXG_STATE_HALTED:
+ case SXG_STATE_SHUTDOWN:
+ ASSERT(0); // unexpected
+ // fall through
+ case SXG_STATE_RESETTING:
+ case SXG_STATE_SLEEP:
+ case SXG_STATE_BOOTDIAG:
+ case SXG_STATE_DIAG:
+ case SXG_STATE_HALTING:
+ status = STATUS_FAILURE;
+ break;
+ case SXG_STATE_RUNNING:
+ if (adapter->LinkState != SXG_LINK_UP) {
+ status = STATUS_FAILURE;
+ }
+ break;
+ default:
+ ASSERT(0);
+ status = STATUS_FAILURE;
+ }
+ if (status != STATUS_SUCCESS) {
+ goto xmit_fail;
+ }
+ // send a packet
+ status = sxg_transmit_packet(adapter, skb);
+ if (status == STATUS_SUCCESS) {
+ goto xmit_done;
+ }
+
+ xmit_fail:
+ // reject & complete all the packets if they cant be sent
+ if (status != STATUS_SUCCESS) {
+#if XXXTODO
+// sxg_send_packets_fail(adapter, skb, status);
+#else
+ SXG_DROP_DUMB_SEND(adapter, skb);
+ adapter->stats.tx_dropped++;
+#endif
+ }
+ DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __FUNCTION__,
+ status);
+
+ xmit_done:
+ return 0;
+}
+
+/*
+ * sxg_transmit_packet
+ *
+ * This function transmits a single packet.
+ *
+ * Arguments -
+ * adapter - Pointer to our adapter structure
+ * skb - The packet to be sent
+ *
+ * Return -
+ * STATUS of send
+ */
+static int sxg_transmit_packet(p_adapter_t adapter, struct sk_buff *skb)
+{
+ PSCATTER_GATHER_LIST pSgl;
+ PSXG_SCATTER_GATHER SxgSgl;
+ void *SglBuffer;
+ u32 SglBufferLength;
+
+ // The vast majority of work is done in the shared
+ // sxg_dumb_sgl routine.
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSend",
+ adapter, skb, 0, 0);
+
+ // Allocate a SGL buffer
+ SXG_GET_SGL_BUFFER(adapter, SxgSgl);
+ if (!SxgSgl) {
+ adapter->Stats.NoSglBuf++;
+ adapter->Stats.XmtErrors++;
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "SndPktF1",
+ adapter, skb, 0, 0);
+ return (STATUS_RESOURCES);
+ }
+ ASSERT(SxgSgl->adapter == adapter);
+ SglBuffer = SXG_SGL_BUFFER(SxgSgl);
+ SglBufferLength = SXG_SGL_BUF_SIZE;
+ SxgSgl->VlanTag.VlanTci = 0;
+ SxgSgl->VlanTag.VlanTpid = 0;
+ SxgSgl->Type = SXG_SGL_DUMB;
+ SxgSgl->DumbPacket = skb;
+ pSgl = NULL;
+
+ // Call the common sxg_dumb_sgl routine to complete the send.
+ sxg_dumb_sgl(pSgl, SxgSgl);
+ // Return success sxg_dumb_sgl (or something later) will complete it.
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_dumb_sgl
+ *
+ * Arguments:
+ * pSgl -
+ * SxgSgl - SXG_SCATTER_GATHER
+ *
+ * Return Value:
+ * None.
+ */
+static void sxg_dumb_sgl(PSCATTER_GATHER_LIST pSgl, PSXG_SCATTER_GATHER SxgSgl)
+{
+ p_adapter_t adapter = SxgSgl->adapter;
+ struct sk_buff *skb = SxgSgl->DumbPacket;
+ // For now, all dumb-nic sends go on RSS queue zero
+ PSXG_XMT_RING XmtRing = &adapter->XmtRings[0];
+ PSXG_RING_INFO XmtRingInfo = &adapter->XmtRingZeroInfo;
+ PSXG_CMD XmtCmd = NULL;
+// u32 Index = 0;
+ u32 DataLength = skb->len;
+// unsigned int BufLen;
+// u32 SglOffset;
+ u64 phys_addr;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
+ pSgl, SxgSgl, 0, 0);
+
+ // Set aside a pointer to the sgl
+ SxgSgl->pSgl = pSgl;
+
+ // Sanity check that our SGL format is as we expect.
+ ASSERT(sizeof(SXG_X64_SGE) == sizeof(SCATTER_GATHER_ELEMENT));
+ // Shouldn't be a vlan tag on this frame
+ ASSERT(SxgSgl->VlanTag.VlanTci == 0);
+ ASSERT(SxgSgl->VlanTag.VlanTpid == 0);
+
+ // From here below we work with the SGL placed in our
+ // buffer.
+
+ SxgSgl->Sgl.NumberOfElements = 1;
+
+ // Grab the spinlock and acquire a command
+ spin_lock(&adapter->XmtZeroLock);
+ SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
+ if (XmtCmd == NULL) {
+ // Call sxg_complete_slow_send to see if we can
+ // free up any XmtRingZero entries and then try again
+ spin_unlock(&adapter->XmtZeroLock);
+ sxg_complete_slow_send(adapter);
+ spin_lock(&adapter->XmtZeroLock);
+ SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
+ if (XmtCmd == NULL) {
+ adapter->Stats.XmtZeroFull++;
+ goto abortcmd;
+ }
+ }
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
+ XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
+ // Update stats
+ adapter->Stats.DumbXmtPkts++;
+ adapter->Stats.DumbXmtBytes += DataLength;
+#if XXXTODO // Stats stuff
+ if (SXG_MULTICAST_PACKET(EtherHdr)) {
+ if (SXG_BROADCAST_PACKET(EtherHdr)) {
+ adapter->Stats.DumbXmtBcastPkts++;
+ adapter->Stats.DumbXmtBcastBytes += DataLength;
+ } else {
+ adapter->Stats.DumbXmtMcastPkts++;
+ adapter->Stats.DumbXmtMcastBytes += DataLength;
+ }
+ } else {
+ adapter->Stats.DumbXmtUcastPkts++;
+ adapter->Stats.DumbXmtUcastBytes += DataLength;
+ }
+#endif
+ // Fill in the command
+ // Copy out the first SGE to the command and adjust for offset
+ phys_addr =
+ pci_map_single(adapter->pcidev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ XmtCmd->Buffer.FirstSgeAddress = SXG_GET_ADDR_HIGH(phys_addr);
+ XmtCmd->Buffer.FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress << 32;
+ XmtCmd->Buffer.FirstSgeAddress =
+ XmtCmd->Buffer.FirstSgeAddress | SXG_GET_ADDR_LOW(phys_addr);
+// XmtCmd->Buffer.FirstSgeAddress = SxgSgl->Sgl.Elements[Index].Address;
+// XmtCmd->Buffer.FirstSgeAddress.LowPart += MdlOffset;
+ XmtCmd->Buffer.FirstSgeLength = DataLength;
+ // Set a pointer to the remaining SGL entries
+// XmtCmd->Sgl = SxgSgl->PhysicalAddress;
+ // Advance the physical address of the SxgSgl structure to
+ // the second SGE
+// SglOffset = (u32)((u32 *)(&SxgSgl->Sgl.Elements[Index+1]) -
+// (u32 *)SxgSgl);
+// XmtCmd->Sgl.LowPart += SglOffset;
+ XmtCmd->Buffer.SgeOffset = 0;
+ // Note - TotalLength might be overwritten with MSS below..
+ XmtCmd->Buffer.TotalLength = DataLength;
+ XmtCmd->SgEntries = 1; //(ushort)(SxgSgl->Sgl.NumberOfElements - Index);
+ XmtCmd->Flags = 0;
+ //
+ // Advance transmit cmd descripter by 1.
+ // NOTE - See comments in SxgTcpOutput where we write
+ // to the XmtCmd register regarding CPU ID values and/or
+ // multiple commands.
+ //
+ //
+ WRITE_REG(adapter->UcodeRegs[0].XmtCmd, 1, TRUE);
+ //
+ //
+ adapter->Stats.XmtQLen++; // Stats within lock
+ spin_unlock(&adapter->XmtZeroLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
+ XmtCmd, pSgl, SxgSgl, 0);
+ return;
+
+ abortcmd:
+ // NOTE - Only jump to this label AFTER grabbing the
+ // XmtZeroLock, and DO NOT DROP IT between the
+ // command allocation and the following abort.
+ if (XmtCmd) {
+ SXG_ABORT_CMD(XmtRingInfo);
+ }
+ spin_unlock(&adapter->XmtZeroLock);
+
+// failsgl:
+ // Jump to this label if failure occurs before the
+ // XmtZeroLock is grabbed
+ adapter->Stats.XmtErrors++;
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal",
+ pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail);
+
+ SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket); // SxgSgl->DumbPacket is the skb
+}
+
+/***************************************************************
+ * Link management functions
+ ***************************************************************/
+
+/*
+ * sxg_initialize_link - Initialize the link stuff
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * status
+ */
+static int sxg_initialize_link(p_adapter_t adapter)
+{
+ PSXG_HW_REGS HwRegs = adapter->HwRegs;
+ u32 Value;
+ u32 ConfigData;
+ u32 MaxFrame;
+ int status;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitLink",
+ adapter, 0, 0, 0);
+
+ // Reset PHY and XGXS module
+ WRITE_REG(HwRegs->LinkStatus, LS_SERDES_POWER_DOWN, TRUE);
+
+ // Reset transmit configuration register
+ WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_RESET, TRUE);
+
+ // Reset receive configuration register
+ WRITE_REG(HwRegs->RcvConfig, RCV_CONFIG_RESET, TRUE);
+
+ // Reset all MAC modules
+ WRITE_REG(HwRegs->MacConfig0, AXGMAC_CFG0_SUB_RESET, TRUE);
+
+ // Link address 0
+ // XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f)
+ // is stored with the first nibble (0a) in the byte 0
+ // of the Mac address. Possibly reverse?
+ Value = *(u32 *) adapter->MacAddr;
+ WRITE_REG(HwRegs->LinkAddress0Low, Value, TRUE);
+ // also write the MAC address to the MAC. Endian is reversed.
+ WRITE_REG(HwRegs->MacAddressLow, ntohl(Value), TRUE);
+ Value = (*(u16 *) & adapter->MacAddr[4] & 0x0000FFFF);
+ WRITE_REG(HwRegs->LinkAddress0High, Value | LINK_ADDRESS_ENABLE, TRUE);
+ // endian swap for the MAC (put high bytes in bits [31:16], swapped)
+ Value = ntohl(Value);
+ WRITE_REG(HwRegs->MacAddressHigh, Value, TRUE);
+ // Link address 1
+ WRITE_REG(HwRegs->LinkAddress1Low, 0, TRUE);
+ WRITE_REG(HwRegs->LinkAddress1High, 0, TRUE);
+ // Link address 2
+ WRITE_REG(HwRegs->LinkAddress2Low, 0, TRUE);
+ WRITE_REG(HwRegs->LinkAddress2High, 0, TRUE);
+ // Link address 3
+ WRITE_REG(HwRegs->LinkAddress3Low, 0, TRUE);
+ WRITE_REG(HwRegs->LinkAddress3High, 0, TRUE);
+
+ // Enable MAC modules
+ WRITE_REG(HwRegs->MacConfig0, 0, TRUE);
+
+ // Configure MAC
+ WRITE_REG(HwRegs->MacConfig1, (AXGMAC_CFG1_XMT_PAUSE | // Allow sending of pause
+ AXGMAC_CFG1_XMT_EN | // Enable XMT
+ AXGMAC_CFG1_RCV_PAUSE | // Enable detection of pause
+ AXGMAC_CFG1_RCV_EN | // Enable receive
+ AXGMAC_CFG1_SHORT_ASSERT | // short frame detection
+ AXGMAC_CFG1_CHECK_LEN | // Verify frame length
+ AXGMAC_CFG1_GEN_FCS | // Generate FCS
+ AXGMAC_CFG1_PAD_64), // Pad frames to 64 bytes
+ TRUE);
+
+ // Set AXGMAC max frame length if jumbo. Not needed for standard MTU
+ if (adapter->JumboEnabled) {
+ WRITE_REG(HwRegs->MacMaxFrameLen, AXGMAC_MAXFRAME_JUMBO, TRUE);
+ }
+ // AMIIM Configuration Register -
+ // The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion
+ // (bottom bits) of this register is used to determine the
+ // MDC frequency as specified in the A-XGMAC Design Document.
+ // This value must not be zero. The following value (62 or 0x3E)
+ // is based on our MAC transmit clock frequency (MTCLK) of 312.5 MHz.
+ // Given a maximum MDIO clock frequency of 2.5 MHz (see the PHY spec),
+ // we get: 312.5/(2*(X+1)) < 2.5 ==> X = 62.
+ // This value happens to be the default value for this register,
+ // so we really don't have to do this.
+ WRITE_REG(HwRegs->MacAmiimConfig, 0x0000003E, TRUE);
+
+ // Power up and enable PHY and XAUI/XGXS/Serdes logic
+ WRITE_REG(HwRegs->LinkStatus,
+ (LS_PHY_CLR_RESET |
+ LS_XGXS_ENABLE |
+ LS_XGXS_CTL | LS_PHY_CLK_EN | LS_ATTN_ALARM), TRUE);
+ DBG_ERROR("After Power Up and enable PHY in sxg_initialize_link\n");
+
+ // Per information given by Aeluros, wait 100 ms after removing reset.
+ // It's not enough to wait for the self-clearing reset bit in reg 0 to clear.
+ mdelay(100);
+
+ // Verify the PHY has come up by checking that the Reset bit has cleared.
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ PHY_PMA_CONTROL1, // PMA/PMD control register
+ &Value);
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+ if (Value & PMA_CONTROL1_RESET) // reset complete if bit is 0
+ return (STATUS_FAILURE);
+
+ // The SERDES should be initialized by now - confirm
+ READ_REG(HwRegs->LinkStatus, Value);
+ if (Value & LS_SERDES_DOWN) // verify SERDES is initialized
+ return (STATUS_FAILURE);
+
+ // The XAUI link should also be up - confirm
+ if (!(Value & LS_XAUI_LINK_UP)) // verify XAUI link is up
+ return (STATUS_FAILURE);
+
+ // Initialize the PHY
+ status = sxg_phy_init(adapter);
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+
+ // Enable the Link Alarm
+ status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ LASI_CONTROL, // LASI control register
+ LASI_CTL_LS_ALARM_ENABLE); // enable link alarm bit
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+
+ // XXXTODO - temporary - verify bit is set
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ LASI_CONTROL, // LASI control register
+ &Value);
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+ if (!(Value & LASI_CTL_LS_ALARM_ENABLE)) {
+ DBG_ERROR("Error! LASI Control Alarm Enable bit not set!\n");
+ }
+ // Enable receive
+ MaxFrame = adapter->JumboEnabled ? JUMBOMAXFRAME : ETHERMAXFRAME;
+ ConfigData = (RCV_CONFIG_ENABLE |
+ RCV_CONFIG_ENPARSE |
+ RCV_CONFIG_RCVBAD |
+ RCV_CONFIG_RCVPAUSE |
+ RCV_CONFIG_TZIPV6 |
+ RCV_CONFIG_TZIPV4 |
+ RCV_CONFIG_HASH_16 |
+ RCV_CONFIG_SOCKET | RCV_CONFIG_BUFSIZE(MaxFrame));
+ WRITE_REG(HwRegs->RcvConfig, ConfigData, TRUE);
+
+ WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_ENABLE, TRUE);
+
+ // Mark the link as down. We'll get a link event when it comes up.
+ sxg_link_state(adapter, SXG_LINK_DOWN);
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInitLnk",
+ adapter, 0, 0, 0);
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_phy_init - Initialize the PHY
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * status
+ */
+static int sxg_phy_init(p_adapter_t adapter)
+{
+ u32 Value;
+ PPHY_UCODE p;
+ int status;
+
+ DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ // Read a register to identify the PHY type
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ 0xC205, // PHY ID register (?)
+ &Value); // XXXTODO - add def
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+
+ if (Value == 0x0012) { // 0x0012 == AEL2005C PHY(?) - XXXTODO - add def
+ DBG_ERROR
+ ("AEL2005C PHY detected. Downloading PHY microcode.\n");
+
+ // Initialize AEL2005C PHY and download PHY microcode
+ for (p = PhyUcode; p->Addr != 0xFFFF; p++) {
+ if (p->Addr == 0) {
+ // if address == 0, data == sleep time in ms
+ mdelay(p->Data);
+ } else {
+ // write the given data to the specified address
+ status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ p->Addr, // PHY address
+ p->Data); // PHY data
+ if (status != STATUS_SUCCESS)
+ return (STATUS_FAILURE);
+ }
+ }
+ }
+ DBG_ERROR("EXIT %s\n", __FUNCTION__);
+
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_link_event - Process a link event notification from the card
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * None
+ */
+static void sxg_link_event(p_adapter_t adapter)
+{
+ PSXG_HW_REGS HwRegs = adapter->HwRegs;
+ SXG_LINK_STATE LinkState;
+ int status;
+ u32 Value;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt",
+ adapter, 0, 0, 0);
+ DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ // Check the Link Status register. We should have a Link Alarm.
+ READ_REG(HwRegs->LinkStatus, Value);
+ if (Value & LS_LINK_ALARM) {
+ // We got a Link Status alarm. First, pause to let the
+ // link state settle (it can bounce a number of times)
+ mdelay(10);
+
+ // Now clear the alarm by reading the LASI status register.
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ LASI_STATUS, // LASI status register
+ &Value);
+ if (status != STATUS_SUCCESS) {
+ DBG_ERROR("Error reading LASI Status MDIO register!\n");
+ sxg_link_state(adapter, SXG_LINK_DOWN);
+// ASSERT(0);
+ }
+ ASSERT(Value & LASI_STATUS_LS_ALARM);
+
+ // Now get and set the link state
+ LinkState = sxg_get_link_state(adapter);
+ sxg_link_state(adapter, LinkState);
+ DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n",
+ ((LinkState == SXG_LINK_UP) ? "UP" : "DOWN"));
+ } else {
+ // XXXTODO - Assuming Link Attention is only being generated for the
+ // Link Alarm pin (and not for a XAUI Link Status change), then it's
+ // impossible to get here. Yet we've gotten here twice (under extreme
+ // conditions - bouncing the link up and down many times a second).
+ // Needs further investigation.
+ DBG_ERROR("SXG: sxg_link_event: Can't get here!\n");
+ DBG_ERROR("SXG: Link Status == 0x%08X.\n", Value);
+// ASSERT(0);
+ }
+ DBG_ERROR("EXIT %s\n", __FUNCTION__);
+
+}
+
+/*
+ * sxg_get_link_state - Determine if the link is up or down
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * Link State
+ */
+static SXG_LINK_STATE sxg_get_link_state(p_adapter_t adapter)
+{
+ int status;
+ u32 Value;
+
+ DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "GetLink",
+ adapter, 0, 0, 0);
+
+ // Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if
+ // the following 3 bits (from 3 different MDIO registers) are all true.
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, // PHY PMA/PMD module
+ PHY_PMA_RCV_DET, // PMA/PMD Receive Signal Detect register
+ &Value);
+ if (status != STATUS_SUCCESS)
+ goto bad;
+
+ // If PMA/PMD receive signal detect is 0, then the link is down
+ if (!(Value & PMA_RCV_DETECT))
+ return (SXG_LINK_DOWN);
+
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS, // PHY PCS module
+ PHY_PCS_10G_STATUS1, // PCS 10GBASE-R Status 1 register
+ &Value);
+ if (status != STATUS_SUCCESS)
+ goto bad;
+
+ // If PCS is not locked to receive blocks, then the link is down
+ if (!(Value & PCS_10B_BLOCK_LOCK))
+ return (SXG_LINK_DOWN);
+
+ status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS, // PHY XS module
+ PHY_XS_LANE_STATUS, // XS Lane Status register
+ &Value);
+ if (status != STATUS_SUCCESS)
+ goto bad;
+
+ // If XS transmit lanes are not aligned, then the link is down
+ if (!(Value & XS_LANE_ALIGN))
+ return (SXG_LINK_DOWN);
+
+ // All 3 bits are true, so the link is up
+ DBG_ERROR("EXIT %s\n", __FUNCTION__);
+
+ return (SXG_LINK_UP);
+
+ bad:
+ // An error occurred reading an MDIO register. This shouldn't happen.
+ DBG_ERROR("Error reading an MDIO register!\n");
+ ASSERT(0);
+ return (SXG_LINK_DOWN);
+}
+
+static void sxg_indicate_link_state(p_adapter_t adapter,
+ SXG_LINK_STATE LinkState)
+{
+ if (adapter->LinkState == SXG_LINK_UP) {
+ DBG_ERROR("%s: LINK now UP, call netif_start_queue\n",
+ __FUNCTION__);
+ netif_start_queue(adapter->netdev);
+ } else {
+ DBG_ERROR("%s: LINK now DOWN, call netif_stop_queue\n",
+ __FUNCTION__);
+ netif_stop_queue(adapter->netdev);
+ }
+}
+
+/*
+ * sxg_link_state - Set the link state and if necessary, indicate.
+ * This routine the central point of processing for all link state changes.
+ * Nothing else in the driver should alter the link state or perform
+ * link state indications
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * LinkState - The link state
+ *
+ * Return
+ * None
+ */
+static void sxg_link_state(p_adapter_t adapter, SXG_LINK_STATE LinkState)
+{
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "LnkINDCT",
+ adapter, LinkState, adapter->LinkState, adapter->State);
+
+ DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ // Hold the adapter lock during this routine. Maybe move
+ // the lock to the caller.
+ spin_lock(&adapter->AdapterLock);
+ if (LinkState == adapter->LinkState) {
+ // Nothing changed..
+ spin_unlock(&adapter->AdapterLock);
+ DBG_ERROR("EXIT #0 %s\n", __FUNCTION__);
+ return;
+ }
+ // Save the adapter state
+ adapter->LinkState = LinkState;
+
+ // Drop the lock and indicate link state
+ spin_unlock(&adapter->AdapterLock);
+ DBG_ERROR("EXIT #1 %s\n", __FUNCTION__);
+
+ sxg_indicate_link_state(adapter, LinkState);
+}
+
+/*
+ * sxg_write_mdio_reg - Write to a register on the MDIO bus
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * DevAddr - MDIO device number being addressed
+ * RegAddr - register address for the specified MDIO device
+ * Value - value to write to the MDIO register
+ *
+ * Return
+ * status
+ */
+static int sxg_write_mdio_reg(p_adapter_t adapter,
+ u32 DevAddr, u32 RegAddr, u32 Value)
+{
+ PSXG_HW_REGS HwRegs = adapter->HwRegs;
+ u32 AddrOp; // Address operation (written to MIIM field reg)
+ u32 WriteOp; // Write operation (written to MIIM field reg)
+ u32 Cmd; // Command (written to MIIM command reg)
+ u32 ValueRead;
+ u32 Timeout;
+
+// DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
+ adapter, 0, 0, 0);
+
+ // Ensure values don't exceed field width
+ DevAddr &= 0x001F; // 5-bit field
+ RegAddr &= 0xFFFF; // 16-bit field
+ Value &= 0xFFFF; // 16-bit field
+
+ // Set MIIM field register bits for an MIIM address operation
+ AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
+ (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
+ (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
+ (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
+
+ // Set MIIM field register bits for an MIIM write operation
+ WriteOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
+ (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
+ (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
+ (MIIM_OP_WRITE << AXGMAC_AMIIM_FIELD_OP_SHIFT) | Value;
+
+ // Set MIIM command register bits to execute an MIIM command
+ Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
+
+ // Reset the command register command bit (in case it's not 0)
+ WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
+
+ // MIIM write to set the address of the specified MDIO register
+ WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
+
+ // Write to MIIM Command Register to execute to address operation
+ WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
+
+ // Poll AMIIM Indicator register to wait for completion
+ Timeout = SXG_LINK_TIMEOUT;
+ do {
+ udelay(100); // Timeout in 100us units
+ READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
+ if (--Timeout == 0) {
+ return (STATUS_FAILURE);
+ }
+ } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
+
+ // Reset the command register command bit
+ WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
+
+ // MIIM write to set up an MDIO write operation
+ WRITE_REG(HwRegs->MacAmiimField, WriteOp, TRUE);
+
+ // Write to MIIM Command Register to execute the write operation
+ WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
+
+ // Poll AMIIM Indicator register to wait for completion
+ Timeout = SXG_LINK_TIMEOUT;
+ do {
+ udelay(100); // Timeout in 100us units
+ READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
+ if (--Timeout == 0) {
+ return (STATUS_FAILURE);
+ }
+ } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
+
+// DBG_ERROR("EXIT %s\n", __FUNCTION__);
+
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_read_mdio_reg - Read a register on the MDIO bus
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * DevAddr - MDIO device number being addressed
+ * RegAddr - register address for the specified MDIO device
+ * pValue - pointer to where to put data read from the MDIO register
+ *
+ * Return
+ * status
+ */
+static int sxg_read_mdio_reg(p_adapter_t adapter,
+ u32 DevAddr, u32 RegAddr, u32 *pValue)
+{
+ PSXG_HW_REGS HwRegs = adapter->HwRegs;
+ u32 AddrOp; // Address operation (written to MIIM field reg)
+ u32 ReadOp; // Read operation (written to MIIM field reg)
+ u32 Cmd; // Command (written to MIIM command reg)
+ u32 ValueRead;
+ u32 Timeout;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
+ adapter, 0, 0, 0);
+// DBG_ERROR("ENTER %s\n", __FUNCTION__);
+
+ // Ensure values don't exceed field width
+ DevAddr &= 0x001F; // 5-bit field
+ RegAddr &= 0xFFFF; // 16-bit field
+
+ // Set MIIM field register bits for an MIIM address operation
+ AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
+ (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
+ (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
+ (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
+
+ // Set MIIM field register bits for an MIIM read operation
+ ReadOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
+ (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
+ (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
+ (MIIM_OP_READ << AXGMAC_AMIIM_FIELD_OP_SHIFT);
+
+ // Set MIIM command register bits to execute an MIIM command
+ Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
+
+ // Reset the command register command bit (in case it's not 0)
+ WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
+
+ // MIIM write to set the address of the specified MDIO register
+ WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
+
+ // Write to MIIM Command Register to execute to address operation
+ WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
+
+ // Poll AMIIM Indicator register to wait for completion
+ Timeout = SXG_LINK_TIMEOUT;
+ do {
+ udelay(100); // Timeout in 100us units
+ READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
+ if (--Timeout == 0) {
+ return (STATUS_FAILURE);
+ }
+ } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
+
+ // Reset the command register command bit
+ WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
+
+ // MIIM write to set up an MDIO register read operation
+ WRITE_REG(HwRegs->MacAmiimField, ReadOp, TRUE);
+
+ // Write to MIIM Command Register to execute the read operation
+ WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
+
+ // Poll AMIIM Indicator register to wait for completion
+ Timeout = SXG_LINK_TIMEOUT;
+ do {
+ udelay(100); // Timeout in 100us units
+ READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
+ if (--Timeout == 0) {
+ return (STATUS_FAILURE);
+ }
+ } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
+
+ // Read the MDIO register data back from the field register
+ READ_REG(HwRegs->MacAmiimField, *pValue);
+ *pValue &= 0xFFFF; // data is in the lower 16 bits
+
+// DBG_ERROR("EXIT %s\n", __FUNCTION__);
+
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * Allocate a mcast_address structure to hold the multicast address.
+ * Link it in.
+ */
+static int sxg_mcast_add_list(p_adapter_t adapter, char *address)
+{
+ p_mcast_address_t mcaddr, mlist;
+ bool equaladdr;
+
+ /* Check to see if it already exists */
+ mlist = adapter->mcastaddrs;
+ while (mlist) {
+ ETHER_EQ_ADDR(mlist->address, address, equaladdr);
+ if (equaladdr) {
+ return (STATUS_SUCCESS);
+ }
+ mlist = mlist->next;
+ }
+
+ /* Doesn't already exist. Allocate a structure to hold it */
+ mcaddr = kmalloc(sizeof(mcast_address_t), GFP_ATOMIC);
+ if (mcaddr == NULL)
+ return 1;
+
+ memcpy(mcaddr->address, address, 6);
+
+ mcaddr->next = adapter->mcastaddrs;
+ adapter->mcastaddrs = mcaddr;
+
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * Functions to obtain the CRC corresponding to the destination mac address.
+ * This is a standard ethernet CRC in that it is a 32-bit, reflected CRC using
+ * the polynomial:
+ * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1.
+ *
+ * After the CRC for the 6 bytes is generated (but before the value is complemented),
+ * we must then transpose the value and return bits 30-23.
+ *
+ */
+static u32 sxg_crc_table[256]; /* Table of CRC's for all possible byte values */
+static u32 sxg_crc_init; /* Is table initialized */
+
+/*
+ * Contruct the CRC32 table
+ */
+static void sxg_mcast_init_crc32(void)
+{
+ u32 c; /* CRC shit reg */
+ u32 e = 0; /* Poly X-or pattern */
+ int i; /* counter */
+ int k; /* byte being shifted into crc */
+
+ static int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 };
+
+ for (i = 0; i < sizeof(p) / sizeof(int); i++) {
+ e |= 1L << (31 - p[i]);
+ }
+
+ for (i = 1; i < 256; i++) {
+ c = i;
+ for (k = 8; k; k--) {
+ c = c & 1 ? (c >> 1) ^ e : c >> 1;
+ }
+ sxg_crc_table[i] = c;
+ }
+}
+
+/*
+ * Return the MAC hast as described above.
+ */
+static unsigned char sxg_mcast_get_mac_hash(char *macaddr)
+{
+ u32 crc;
+ char *p;
+ int i;
+ unsigned char machash = 0;
+
+ if (!sxg_crc_init) {
+ sxg_mcast_init_crc32();
+ sxg_crc_init = 1;
+ }
+
+ crc = 0xFFFFFFFF; /* Preload shift register, per crc-32 spec */
+ for (i = 0, p = macaddr; i < 6; ++p, ++i) {
+ crc = (crc >> 8) ^ sxg_crc_table[(crc ^ *p) & 0xFF];
+ }
+
+ /* Return bits 1-8, transposed */
+ for (i = 1; i < 9; i++) {
+ machash |= (((crc >> i) & 1) << (8 - i));
+ }
+
+ return (machash);
+}
+
+static void sxg_mcast_set_bit(p_adapter_t adapter, char *address)
+{
+ unsigned char crcpoly;
+
+ /* Get the CRC polynomial for the mac address */
+ crcpoly = sxg_mcast_get_mac_hash(address);
+
+ /* We only have space on the SLIC for 64 entries. Lop
+ * off the top two bits. (2^6 = 64)
+ */
+ crcpoly &= 0x3F;
+
+ /* OR in the new bit into our 64 bit mask. */
+ adapter->MulticastMask |= (u64) 1 << crcpoly;
+}
+
+static void sxg_mcast_set_list(p_net_device dev)
+{
+#if XXXTODO
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+ int status = STATUS_SUCCESS;
+ int i;
+ char *addresses;
+ struct dev_mc_list *mc_list = dev->mc_list;
+ int mc_count = dev->mc_count;
+
+ ASSERT(adapter);
+
+ for (i = 1; i <= mc_count; i++) {
+ addresses = (char *)&mc_list->dmi_addr;
+ if (mc_list->dmi_addrlen == 6) {
+ status = sxg_mcast_add_list(adapter, addresses);
+ if (status != STATUS_SUCCESS) {
+ break;
+ }
+ } else {
+ status = -EINVAL;
+ break;
+ }
+ sxg_mcast_set_bit(adapter, addresses);
+ mc_list = mc_list->next;
+ }
+
+ DBG_ERROR("%s a->devflags_prev[%x] dev->flags[%x] status[%x]\n",
+ __FUNCTION__, adapter->devflags_prev, dev->flags, status);
+ if (adapter->devflags_prev != dev->flags) {
+ adapter->macopts = MAC_DIRECTED;
+ if (dev->flags) {
+ if (dev->flags & IFF_BROADCAST) {
+ adapter->macopts |= MAC_BCAST;
+ }
+ if (dev->flags & IFF_PROMISC) {
+ adapter->macopts |= MAC_PROMISC;
+ }
+ if (dev->flags & IFF_ALLMULTI) {
+ adapter->macopts |= MAC_ALLMCAST;
+ }
+ if (dev->flags & IFF_MULTICAST) {
+ adapter->macopts |= MAC_MCAST;
+ }
+ }
+ adapter->devflags_prev = dev->flags;
+ DBG_ERROR("%s call sxg_config_set adapter->macopts[%x]\n",
+ __FUNCTION__, adapter->macopts);
+ sxg_config_set(adapter, TRUE);
+ } else {
+ if (status == STATUS_SUCCESS) {
+ sxg_mcast_set_mask(adapter);
+ }
+ }
+#endif
+ return;
+}
+
+static void sxg_mcast_set_mask(p_adapter_t adapter)
+{
+ PSXG_UCODE_REGS sxg_regs = adapter->UcodeRegs;
+
+ DBG_ERROR("%s ENTER (%s) macopts[%x] mask[%llx]\n", __FUNCTION__,
+ adapter->netdev->name, (unsigned int)adapter->MacFilter,
+ adapter->MulticastMask);
+
+ if (adapter->MacFilter & (MAC_ALLMCAST | MAC_PROMISC)) {
+ /* Turn on all multicast addresses. We have to do this for promiscuous
+ * mode as well as ALLMCAST mode. It saves the Microcode from having
+ * to keep state about the MAC configuration.
+ */
+// DBG_ERROR("sxg: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n SLUT MODE!!!\n",__FUNCTION__);
+ WRITE_REG(sxg_regs->McastLow, 0xFFFFFFFF, FLUSH);
+ WRITE_REG(sxg_regs->McastHigh, 0xFFFFFFFF, FLUSH);
+// DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n",__FUNCTION__, adapter->netdev->name);
+
+ } else {
+ /* Commit our multicast mast to the SLIC by writing to the multicast
+ * address mask registers
+ */
+ DBG_ERROR("%s (%s) WRITE mcastlow[%lx] mcasthigh[%lx]\n",
+ __FUNCTION__, adapter->netdev->name,
+ ((ulong) (adapter->MulticastMask & 0xFFFFFFFF)),
+ ((ulong)
+ ((adapter->MulticastMask >> 32) & 0xFFFFFFFF)));
+
+ WRITE_REG(sxg_regs->McastLow,
+ (u32) (adapter->MulticastMask & 0xFFFFFFFF), FLUSH);
+ WRITE_REG(sxg_regs->McastHigh,
+ (u32) ((adapter->
+ MulticastMask >> 32) & 0xFFFFFFFF), FLUSH);
+ }
+}
+
+static void sxg_unmap_mmio_space(p_adapter_t adapter)
+{
+#if LINUX_FREES_ADAPTER_RESOURCES
+// if (adapter->Regs) {
+// iounmap(adapter->Regs);
+// }
+// adapter->slic_regs = NULL;
+#endif
+}
+
+#if XXXTODO
+/*
+ * SxgFreeResources - Free everything allocated in SxgAllocateResources
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * none
+ */
+void SxgFreeResources(p_adapter_t adapter)
+{
+ u32 RssIds, IsrCount;
+ PTCP_OBJECT TcpObject;
+ u32 i;
+ BOOLEAN TimerCancelled;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FreeRes",
+ adapter, adapter->MaxTcbs, 0, 0);
+
+ RssIds = SXG_RSS_CPU_COUNT(adapter);
+ IsrCount = adapter->MsiEnabled ? RssIds : 1;
+
+ if (adapter->BasicAllocations == FALSE) {
+ // No allocations have been made, including spinlocks,
+ // or listhead initializations. Return.
+ return;
+ }
+
+ if (!(IsListEmpty(&adapter->AllRcvBlocks))) {
+ SxgFreeRcvBlocks(adapter);
+ }
+ if (!(IsListEmpty(&adapter->AllSglBuffers))) {
+ SxgFreeSglBuffers(adapter);
+ }
+ // Free event queues.
+ if (adapter->EventRings) {
+ pci_free_consistent(adapter->pcidev,
+ sizeof(SXG_EVENT_RING) * RssIds,
+ adapter->EventRings, adapter->PEventRings);
+ }
+ if (adapter->Isr) {
+ pci_free_consistent(adapter->pcidev,
+ sizeof(u32) * IsrCount,
+ adapter->Isr, adapter->PIsr);
+ }
+ if (adapter->XmtRingZeroIndex) {
+ pci_free_consistent(adapter->pcidev,
+ sizeof(u32),
+ adapter->XmtRingZeroIndex,
+ adapter->PXmtRingZeroIndex);
+ }
+ if (adapter->IndirectionTable) {
+ pci_free_consistent(adapter->pcidev,
+ SXG_MAX_RSS_TABLE_SIZE,
+ adapter->IndirectionTable,
+ adapter->PIndirectionTable);
+ }
+
+ SXG_FREE_PACKET_POOL(adapter->PacketPoolHandle);
+ SXG_FREE_BUFFER_POOL(adapter->BufferPoolHandle);
+
+ // Unmap register spaces
+ SxgUnmapResources(adapter);
+
+ // Deregister DMA
+ if (adapter->DmaHandle) {
+ SXG_DEREGISTER_DMA(adapter->DmaHandle);
+ }
+ // Deregister interrupt
+ SxgDeregisterInterrupt(adapter);
+
+ // Possibly free system info (5.2 only)
+ SXG_RELEASE_SYSTEM_INFO(adapter);
+
+ SxgDiagFreeResources(adapter);
+
+ SxgFreeMCastAddrs(adapter);
+
+ if (SXG_TIMER_ALLOCATED(adapter->ResetTimer)) {
+ SXG_CANCEL_TIMER(adapter->ResetTimer, TimerCancelled);
+ SXG_FREE_TIMER(adapter->ResetTimer);
+ }
+ if (SXG_TIMER_ALLOCATED(adapter->RssTimer)) {
+ SXG_CANCEL_TIMER(adapter->RssTimer, TimerCancelled);
+ SXG_FREE_TIMER(adapter->RssTimer);
+ }
+ if (SXG_TIMER_ALLOCATED(adapter->OffloadTimer)) {
+ SXG_CANCEL_TIMER(adapter->OffloadTimer, TimerCancelled);
+ SXG_FREE_TIMER(adapter->OffloadTimer);
+ }
+
+ adapter->BasicAllocations = FALSE;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFreeRes",
+ adapter, adapter->MaxTcbs, 0, 0);
+}
+#endif
+
+/*
+ * sxg_allocate_complete -
+ *
+ * This routine is called when a memory allocation has completed.
+ *
+ * Arguments -
+ * p_adapter_t - Our adapter structure
+ * VirtualAddress - Memory virtual address
+ * PhysicalAddress - Memory physical address
+ * Length - Length of memory allocated (or 0)
+ * Context - The type of buffer allocated
+ *
+ * Return
+ * None.
+ */
+static void sxg_allocate_complete(p_adapter_t adapter,
+ void *VirtualAddress,
+ dma_addr_t PhysicalAddress,
+ u32 Length, SXG_BUFFER_TYPE Context)
+{
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocCmp",
+ adapter, VirtualAddress, Length, Context);
+ ASSERT(adapter->AllocationsPending);
+ --adapter->AllocationsPending;
+
+ switch (Context) {
+
+ case SXG_BUFFER_TYPE_RCV:
+ sxg_allocate_rcvblock_complete(adapter,
+ VirtualAddress,
+ PhysicalAddress, Length);
+ break;
+ case SXG_BUFFER_TYPE_SGL:
+ sxg_allocate_sgl_buffer_complete(adapter, (PSXG_SCATTER_GATHER)
+ VirtualAddress,
+ PhysicalAddress, Length);
+ break;
+ }
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocCmp",
+ adapter, VirtualAddress, Length, Context);
+}
+
+/*
+ * sxg_allocate_buffer_memory - Shared memory allocation routine used for
+ * synchronous and asynchronous buffer allocations
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * Size - block size to allocate
+ * BufferType - Type of buffer to allocate
+ *
+ * Return
+ * int
+ */
+static int sxg_allocate_buffer_memory(p_adapter_t adapter,
+ u32 Size, SXG_BUFFER_TYPE BufferType)
+{
+ int status;
+ void *Buffer;
+ dma_addr_t pBuffer;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocMem",
+ adapter, Size, BufferType, 0);
+ // Grab the adapter lock and check the state.
+ // If we're in anything other than INITIALIZING or
+ // RUNNING state, fail. This is to prevent
+ // allocations in an improper driver state
+ spin_lock(&adapter->AdapterLock);
+
+ // Increment the AllocationsPending count while holding
+ // the lock. Pause processing relies on this
+ ++adapter->AllocationsPending;
+ spin_unlock(&adapter->AdapterLock);
+
+ // At initialization time allocate resources synchronously.
+ Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer);
+ if (Buffer == NULL) {
+ spin_lock(&adapter->AdapterLock);
+ // Decrement the AllocationsPending count while holding
+ // the lock. Pause processing relies on this
+ --adapter->AllocationsPending;
+ spin_unlock(&adapter->AdapterLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlcMemF1",
+ adapter, Size, BufferType, 0);
+ return (STATUS_RESOURCES);
+ }
+ sxg_allocate_complete(adapter, Buffer, pBuffer, Size, BufferType);
+ status = STATUS_SUCCESS;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocMem",
+ adapter, Size, BufferType, status);
+ return (status);
+}
+
+/*
+ * sxg_allocate_rcvblock_complete - Complete a receive descriptor block allocation
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * RcvBlock - receive block virtual address
+ * PhysicalAddress - Physical address
+ * Length - Memory length
+ *
+ * Return
+ *
+ */
+static void sxg_allocate_rcvblock_complete(p_adapter_t adapter,
+ void *RcvBlock,
+ dma_addr_t PhysicalAddress,
+ u32 Length)
+{
+ u32 i;
+ u32 BufferSize = adapter->ReceiveBufferSize;
+ u64 Paddr;
+ PSXG_RCV_BLOCK_HDR RcvBlockHdr;
+ unsigned char *RcvDataBuffer;
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+ PSXG_RCV_DESCRIPTOR_BLOCK RcvDescriptorBlock;
+ PSXG_RCV_DESCRIPTOR_BLOCK_HDR RcvDescriptorBlockHdr;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlRcvBlk",
+ adapter, RcvBlock, Length, 0);
+ if (RcvBlock == NULL) {
+ goto fail;
+ }
+ memset(RcvBlock, 0, Length);
+ ASSERT((BufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
+ (BufferSize == SXG_RCV_JUMBO_BUFFER_SIZE));
+ ASSERT(Length == SXG_RCV_BLOCK_SIZE(BufferSize));
+ // First, initialize the contained pool of receive data
+ // buffers. This initialization requires NBL/NB/MDL allocations,
+ // If any of them fail, free the block and return without
+ // queueing the shared memory
+ RcvDataBuffer = RcvBlock;
+#if 0
+ for (i = 0, Paddr = *PhysicalAddress;
+ i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
+ i++, Paddr.LowPart += BufferSize, RcvDataBuffer += BufferSize)
+#endif
+ for (i = 0, Paddr = PhysicalAddress;
+ i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
+ i++, Paddr += BufferSize, RcvDataBuffer += BufferSize) {
+ //
+ RcvDataBufferHdr =
+ (PSXG_RCV_DATA_BUFFER_HDR) (RcvDataBuffer +
+ SXG_RCV_DATA_BUFFER_HDR_OFFSET
+ (BufferSize));
+ RcvDataBufferHdr->VirtualAddress = RcvDataBuffer;
+ RcvDataBufferHdr->PhysicalAddress = Paddr;
+ RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; // For FREE macro assertion
+ RcvDataBufferHdr->Size =
+ SXG_RCV_BUFFER_DATA_SIZE(BufferSize);
+
+ SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr);
+ if (RcvDataBufferHdr->SxgDumbRcvPacket == NULL)
+ goto fail;
+
+ }
+
+ // Place this entire block of memory on the AllRcvBlocks queue so it can be
+ // free later
+ RcvBlockHdr =
+ (PSXG_RCV_BLOCK_HDR) ((unsigned char *)RcvBlock +
+ SXG_RCV_BLOCK_HDR_OFFSET(BufferSize));
+ RcvBlockHdr->VirtualAddress = RcvBlock;
+ RcvBlockHdr->PhysicalAddress = PhysicalAddress;
+ spin_lock(&adapter->RcvQLock);
+ adapter->AllRcvBlockCount++;
+ InsertTailList(&adapter->AllRcvBlocks, &RcvBlockHdr->AllList);
+ spin_unlock(&adapter->RcvQLock);
+
+ // Now free the contained receive data buffers that we initialized above
+ RcvDataBuffer = RcvBlock;
+ for (i = 0, Paddr = PhysicalAddress;
+ i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
+ i++, Paddr += BufferSize, RcvDataBuffer += BufferSize) {
+ RcvDataBufferHdr = (PSXG_RCV_DATA_BUFFER_HDR) (RcvDataBuffer +
+ SXG_RCV_DATA_BUFFER_HDR_OFFSET
+ (BufferSize));
+ spin_lock(&adapter->RcvQLock);
+ SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
+ spin_unlock(&adapter->RcvQLock);
+ }
+
+ // Locate the descriptor block and put it on a separate free queue
+ RcvDescriptorBlock =
+ (PSXG_RCV_DESCRIPTOR_BLOCK) ((unsigned char *)RcvBlock +
+ SXG_RCV_DESCRIPTOR_BLOCK_OFFSET
+ (BufferSize));
+ RcvDescriptorBlockHdr =
+ (PSXG_RCV_DESCRIPTOR_BLOCK_HDR) ((unsigned char *)RcvBlock +
+ SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET
+ (BufferSize));
+ RcvDescriptorBlockHdr->VirtualAddress = RcvDescriptorBlock;
+ RcvDescriptorBlockHdr->PhysicalAddress = Paddr;
+ spin_lock(&adapter->RcvQLock);
+ SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter, RcvDescriptorBlockHdr);
+ spin_unlock(&adapter->RcvQLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlRBlk",
+ adapter, RcvBlock, Length, 0);
+ return;
+ fail:
+ // Free any allocated resources
+ if (RcvBlock) {
+ RcvDataBuffer = RcvBlock;
+ for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
+ i++, RcvDataBuffer += BufferSize) {
+ RcvDataBufferHdr =
+ (PSXG_RCV_DATA_BUFFER_HDR) (RcvDataBuffer +
+ SXG_RCV_DATA_BUFFER_HDR_OFFSET
+ (BufferSize));
+ SXG_FREE_RCV_PACKET(RcvDataBufferHdr);
+ }
+ pci_free_consistent(adapter->pcidev,
+ Length, RcvBlock, PhysicalAddress);
+ }
+ DBG_ERROR("%s: OUT OF RESOURCES\n", __FUNCTION__);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "RcvAFail",
+ adapter, adapter->FreeRcvBufferCount,
+ adapter->FreeRcvBlockCount, adapter->AllRcvBlockCount);
+ adapter->Stats.NoMem++;
+}
+
+/*
+ * sxg_allocate_sgl_buffer_complete - Complete a SGL buffer allocation
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * SxgSgl - SXG_SCATTER_GATHER buffer
+ * PhysicalAddress - Physical address
+ * Length - Memory length
+ *
+ * Return
+ *
+ */
+static void sxg_allocate_sgl_buffer_complete(p_adapter_t adapter,
+ PSXG_SCATTER_GATHER SxgSgl,
+ dma_addr_t PhysicalAddress,
+ u32 Length)
+{
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlSglCmp",
+ adapter, SxgSgl, Length, 0);
+ spin_lock(&adapter->SglQLock);
+ adapter->AllSglBufferCount++;
+ memset(SxgSgl, 0, sizeof(SXG_SCATTER_GATHER));
+ SxgSgl->PhysicalAddress = PhysicalAddress; /* *PhysicalAddress; */
+ SxgSgl->adapter = adapter; // Initialize backpointer once
+ InsertTailList(&adapter->AllSglBuffers, &SxgSgl->AllList);
+ spin_unlock(&adapter->SglQLock);
+ SxgSgl->State = SXG_BUFFER_BUSY;
+ SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlSgl",
+ adapter, SxgSgl, Length, 0);
+}
+
+static unsigned char temp_mac_address[6] =
+ { 0x00, 0xab, 0xcd, 0xef, 0x12, 0x69 };
+
+static void sxg_adapter_set_hwaddr(p_adapter_t adapter)
+{
+// DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n", __FUNCTION__,
+// card->config_set, adapter->port, adapter->physport, adapter->functionnumber);
+//
+// sxg_dbg_macaddrs(adapter);
+
+ memcpy(adapter->macaddr, temp_mac_address, sizeof(SXG_CONFIG_MAC));
+// DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n", __FUNCTION__);
+// sxg_dbg_macaddrs(adapter);
+ if (!(adapter->currmacaddr[0] ||
+ adapter->currmacaddr[1] ||
+ adapter->currmacaddr[2] ||
+ adapter->currmacaddr[3] ||
+ adapter->currmacaddr[4] || adapter->currmacaddr[5])) {
+ memcpy(adapter->currmacaddr, adapter->macaddr, 6);
+ }
+ if (adapter->netdev) {
+ memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6);
+ }
+// DBG_ERROR ("%s EXIT port %d\n", __FUNCTION__, adapter->port);
+ sxg_dbg_macaddrs(adapter);
+
+}
+
+static int sxg_mac_set_address(p_net_device dev, void *ptr)
+{
+#if XXXTODO
+ p_adapter_t adapter = (p_adapter_t) netdev_priv(dev);
+ struct sockaddr *addr = ptr;
+
+ DBG_ERROR("%s ENTER (%s)\n", __FUNCTION__, adapter->netdev->name);
+
+ if (netif_running(dev)) {
+ return -EBUSY;
+ }
+ if (!adapter) {
+ return -EBUSY;
+ }
+ DBG_ERROR("sxg: %s (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ __FUNCTION__, adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
+ DBG_ERROR("sxg: %s (%s) new %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ __FUNCTION__, adapter->netdev->name, adapter->currmacaddr[0],
+ adapter->currmacaddr[1], adapter->currmacaddr[2],
+ adapter->currmacaddr[3], adapter->currmacaddr[4],
+ adapter->currmacaddr[5]);
+
+ sxg_config_set(adapter, TRUE);
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+/************* SXG DRIVER FUNCTIONS (below) ********************************/
+/*****************************************************************************/
+
+/*
+ * sxg_initialize_adapter - Initialize adapter
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * int
+ */
+static int sxg_initialize_adapter(p_adapter_t adapter)
+{
+ u32 RssIds, IsrCount;
+ u32 i;
+ int status;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitAdpt",
+ adapter, 0, 0, 0);
+
+ RssIds = 1; // XXXTODO SXG_RSS_CPU_COUNT(adapter);
+ IsrCount = adapter->MsiEnabled ? RssIds : 1;
+
+ // Sanity check SXG_UCODE_REGS structure definition to
+ // make sure the length is correct
+ ASSERT(sizeof(SXG_UCODE_REGS) == SXG_REGISTER_SIZE_PER_CPU);
+
+ // Disable interrupts
+ SXG_DISABLE_ALL_INTERRUPTS(adapter);
+
+ // Set MTU
+ ASSERT((adapter->FrameSize == ETHERMAXFRAME) ||
+ (adapter->FrameSize == JUMBOMAXFRAME));
+ WRITE_REG(adapter->UcodeRegs[0].LinkMtu, adapter->FrameSize, TRUE);
+
+ // Set event ring base address and size
+ WRITE_REG64(adapter,
+ adapter->UcodeRegs[0].EventBase, adapter->PEventRings, 0);
+ WRITE_REG(adapter->UcodeRegs[0].EventSize, EVENT_RING_SIZE, TRUE);
+
+ // Per-ISR initialization
+ for (i = 0; i < IsrCount; i++) {
+ u64 Addr;
+ // Set interrupt status pointer
+ Addr = adapter->PIsr + (i * sizeof(u32));
+ WRITE_REG64(adapter, adapter->UcodeRegs[i].Isp, Addr, i);
+ }
+
+ // XMT ring zero index
+ WRITE_REG64(adapter,
+ adapter->UcodeRegs[0].SPSendIndex,
+ adapter->PXmtRingZeroIndex, 0);
+
+ // Per-RSS initialization
+ for (i = 0; i < RssIds; i++) {
+ // Release all event ring entries to the Microcode
+ WRITE_REG(adapter->UcodeRegs[i].EventRelease, EVENT_RING_SIZE,
+ TRUE);
+ }
+
+ // Transmit ring base and size
+ WRITE_REG64(adapter,
+ adapter->UcodeRegs[0].XmtBase, adapter->PXmtRings, 0);
+ WRITE_REG(adapter->UcodeRegs[0].XmtSize, SXG_XMT_RING_SIZE, TRUE);
+
+ // Receive ring base and size
+ WRITE_REG64(adapter,
+ adapter->UcodeRegs[0].RcvBase, adapter->PRcvRings, 0);
+ WRITE_REG(adapter->UcodeRegs[0].RcvSize, SXG_RCV_RING_SIZE, TRUE);
+
+ // Populate the card with receive buffers
+ sxg_stock_rcv_buffers(adapter);
+
+ // Initialize checksum offload capabilities. At the moment
+ // we always enable IP and TCP receive checksums on the card.
+ // Depending on the checksum configuration specified by the
+ // user, we can choose to report or ignore the checksum
+ // information provided by the card.
+ WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum,
+ SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE);
+
+ // Initialize the MAC, XAUI
+ DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __FUNCTION__);
+ status = sxg_initialize_link(adapter);
+ DBG_ERROR("sxg: %s EXIT sxg_initialize_link status[%x]\n", __FUNCTION__,
+ status);
+ if (status != STATUS_SUCCESS) {
+ return (status);
+ }
+ // Initialize Dead to FALSE.
+ // SlicCheckForHang or SlicDumpThread will take it from here.
+ adapter->Dead = FALSE;
+ adapter->PingOutstanding = FALSE;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInit",
+ adapter, 0, 0, 0);
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_fill_descriptor_block - Populate a descriptor block and give it to
+ * the card. The caller should hold the RcvQLock
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * RcvDescriptorBlockHdr - Descriptor block to fill
+ *
+ * Return
+ * status
+ */
+static int sxg_fill_descriptor_block(p_adapter_t adapter,
+ PSXG_RCV_DESCRIPTOR_BLOCK_HDR
+ RcvDescriptorBlockHdr)
+{
+ u32 i;
+ PSXG_RING_INFO RcvRingInfo = &adapter->RcvRingZeroInfo;
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+ PSXG_RCV_DESCRIPTOR_BLOCK RcvDescriptorBlock;
+ PSXG_CMD RingDescriptorCmd;
+ PSXG_RCV_RING RingZero = &adapter->RcvRings[0];
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FilBlk",
+ adapter, adapter->RcvBuffersOnCard,
+ adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
+
+ ASSERT(RcvDescriptorBlockHdr);
+
+ // If we don't have the resources to fill the descriptor block,
+ // return failure
+ if ((adapter->FreeRcvBufferCount < SXG_RCV_DESCRIPTORS_PER_BLOCK) ||
+ SXG_RING_FULL(RcvRingInfo)) {
+ adapter->Stats.NoMem++;
+ return (STATUS_FAILURE);
+ }
+ // Get a ring descriptor command
+ SXG_GET_CMD(RingZero,
+ RcvRingInfo, RingDescriptorCmd, RcvDescriptorBlockHdr);
+ ASSERT(RingDescriptorCmd);
+ RcvDescriptorBlockHdr->State = SXG_BUFFER_ONCARD;
+ RcvDescriptorBlock =
+ (PSXG_RCV_DESCRIPTOR_BLOCK) RcvDescriptorBlockHdr->VirtualAddress;
+
+ // Fill in the descriptor block
+ for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; i++) {
+ SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
+ ASSERT(RcvDataBufferHdr);
+ SXG_REINIATIALIZE_PACKET(RcvDataBufferHdr->SxgDumbRcvPacket);
+ RcvDataBufferHdr->State = SXG_BUFFER_ONCARD;
+ RcvDescriptorBlock->Descriptors[i].VirtualAddress =
+ (void *)RcvDataBufferHdr;
+ RcvDescriptorBlock->Descriptors[i].PhysicalAddress =
+ RcvDataBufferHdr->PhysicalAddress;
+ }
+ // Add the descriptor block to receive descriptor ring 0
+ RingDescriptorCmd->Sgl = RcvDescriptorBlockHdr->PhysicalAddress;
+
+ // RcvBuffersOnCard is not protected via the receive lock (see
+ // sxg_process_event_queue) We don't want to grap a lock every time a
+ // buffer is returned to us, so we use atomic interlocked functions
+ // instead.
+ adapter->RcvBuffersOnCard += SXG_RCV_DESCRIPTORS_PER_BLOCK;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DscBlk",
+ RcvDescriptorBlockHdr,
+ RingDescriptorCmd, RcvRingInfo->Head, RcvRingInfo->Tail);
+
+ WRITE_REG(adapter->UcodeRegs[0].RcvCmd, 1, true);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFilBlk",
+ adapter, adapter->RcvBuffersOnCard,
+ adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * sxg_stock_rcv_buffers - Stock the card with receive buffers
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ *
+ * Return
+ * None
+ */
+static void sxg_stock_rcv_buffers(p_adapter_t adapter)
+{
+ PSXG_RCV_DESCRIPTOR_BLOCK_HDR RcvDescriptorBlockHdr;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "StockBuf",
+ adapter, adapter->RcvBuffersOnCard,
+ adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
+ // First, see if we've got less than our minimum threshold of
+ // receive buffers, there isn't an allocation in progress, and
+ // we haven't exceeded our maximum.. get another block of buffers
+ // None of this needs to be SMP safe. It's round numbers.
+ if ((adapter->FreeRcvBufferCount < SXG_MIN_RCV_DATA_BUFFERS) &&
+ (adapter->AllRcvBlockCount < SXG_MAX_RCV_BLOCKS) &&
+ (adapter->AllocationsPending == 0)) {
+ sxg_allocate_buffer_memory(adapter,
+ SXG_RCV_BLOCK_SIZE(adapter->
+ ReceiveBufferSize),
+ SXG_BUFFER_TYPE_RCV);
+ }
+ // Now grab the RcvQLock lock and proceed
+ spin_lock(&adapter->RcvQLock);
+ while (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
+ PLIST_ENTRY _ple;
+
+ // Get a descriptor block
+ RcvDescriptorBlockHdr = NULL;
+ if (adapter->FreeRcvBlockCount) {
+ _ple = RemoveHeadList(&adapter->FreeRcvBlocks);
+ RcvDescriptorBlockHdr =
+ container_of(_ple, SXG_RCV_DESCRIPTOR_BLOCK_HDR,
+ FreeList);
+ adapter->FreeRcvBlockCount--;
+ RcvDescriptorBlockHdr->State = SXG_BUFFER_BUSY;
+ }
+
+ if (RcvDescriptorBlockHdr == NULL) {
+ // Bail out..
+ adapter->Stats.NoMem++;
+ break;
+ }
+ // Fill in the descriptor block and give it to the card
+ if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) ==
+ STATUS_FAILURE) {
+ // Free the descriptor block
+ SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
+ RcvDescriptorBlockHdr);
+ break;
+ }
+ }
+ spin_unlock(&adapter->RcvQLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFilBlks",
+ adapter, adapter->RcvBuffersOnCard,
+ adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
+}
+
+/*
+ * sxg_complete_descriptor_blocks - Return descriptor blocks that have been
+ * completed by the microcode
+ *
+ * Arguments -
+ * adapter - A pointer to our adapter structure
+ * Index - Where the microcode is up to
+ *
+ * Return
+ * None
+ */
+static void sxg_complete_descriptor_blocks(p_adapter_t adapter,
+ unsigned char Index)
+{
+ PSXG_RCV_RING RingZero = &adapter->RcvRings[0];
+ PSXG_RING_INFO RcvRingInfo = &adapter->RcvRingZeroInfo;
+ PSXG_RCV_DESCRIPTOR_BLOCK_HDR RcvDescriptorBlockHdr;
+ PSXG_CMD RingDescriptorCmd;
+
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlks",
+ adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
+
+ // Now grab the RcvQLock lock and proceed
+ spin_lock(&adapter->RcvQLock);
+ ASSERT(Index != RcvRingInfo->Tail);
+ while (RcvRingInfo->Tail != Index) {
+ //
+ // Locate the current Cmd (ring descriptor entry), and
+ // associated receive descriptor block, and advance
+ // the tail
+ //
+ SXG_RETURN_CMD(RingZero,
+ RcvRingInfo,
+ RingDescriptorCmd, RcvDescriptorBlockHdr);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlk",
+ RcvRingInfo->Head, RcvRingInfo->Tail,
+ RingDescriptorCmd, RcvDescriptorBlockHdr);
+
+ // Clear the SGL field
+ RingDescriptorCmd->Sgl = 0;
+ // Attempt to refill it and hand it right back to the
+ // card. If we fail to refill it, free the descriptor block
+ // header. The card will be restocked later via the
+ // RcvBuffersOnCard test
+ if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) ==
+ STATUS_FAILURE) {
+ SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
+ RcvDescriptorBlockHdr);
+ }
+ }
+ spin_unlock(&adapter->RcvQLock);
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XCRBlks",
+ adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
+}
+
+static struct pci_driver sxg_driver = {
+ .name = DRV_NAME,
+ .id_table = sxg_pci_tbl,
+ .probe = sxg_entry_probe,
+ .remove = sxg_entry_remove,
+#if SXG_POWER_MANAGEMENT_ENABLED
+ .suspend = sxgpm_suspend,
+ .resume = sxgpm_resume,
+#endif
+/* .shutdown = slic_shutdown, MOOK_INVESTIGATE */
+};
+
+static int __init sxg_module_init(void)
+{
+ sxg_init_driver();
+
+ if (debug >= 0)
+ sxg_debug = debug;
+
+ return pci_register_driver(&sxg_driver);
+}
+
+static void __exit sxg_module_cleanup(void)
+{
+ pci_unregister_driver(&sxg_driver);
+}
+
+module_init(sxg_module_init);
+module_exit(sxg_module_cleanup);
diff --git a/drivers/staging/sxg/sxg.h b/drivers/staging/sxg/sxg.h
new file mode 100644
index 00000000000..844ca56f280
--- /dev/null
+++ b/drivers/staging/sxg/sxg.h
@@ -0,0 +1,773 @@
+/**************************************************************************
+ *
+ * Copyright © 2000-2008 Alacritech, Inc. All rights reserved.
+ *
+ * $Id: sxg.h,v 1.3 2008/07/24 17:25:08 chris Exp $
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: sxg.h
+ *
+ * This is the base set of header definitions for the SXG driver.
+ */
+#ifndef __SXG_DRIVER_H__
+#define __SXG_DRIVER_H__
+
+#define p_net_device struct net_device *
+// SXG_STATS - Probably move these to someplace where
+// the slicstat (sxgstat?) program can get them.
+typedef struct _SXG_STATS {
+ // Xmt
+ u32 XmtNBL; // Offload send NBL count
+ u64 DumbXmtBytes; // Dumbnic send bytes
+ u64 SlowXmtBytes; // Slowpath send bytes
+ u64 FastXmtBytes; // Fastpath send bytes
+ u64 DumbXmtPkts; // Dumbnic send packets
+ u64 SlowXmtPkts; // Slowpath send packets
+ u64 FastXmtPkts; // Fastpath send packets
+ u64 DumbXmtUcastPkts; // directed packets
+ u64 DumbXmtMcastPkts; // Multicast packets
+ u64 DumbXmtBcastPkts; // OID_GEN_BROADCAST_FRAMES_RCV
+ u64 DumbXmtUcastBytes; // OID_GEN_DIRECTED_BYTES_XMIT
+ u64 DumbXmtMcastBytes; // OID_GEN_MULTICAST_BYTES_XMIT
+ u64 DumbXmtBcastBytes; // OID_GEN_BROADCAST_BYTES_XMIT
+ u64 XmtErrors; // OID_GEN_XMIT_ERROR
+ u64 XmtDiscards; // OID_GEN_XMIT_DISCARDS
+ u64 XmtOk; // OID_GEN_XMIT_OK
+ u64 XmtQLen; // OID_GEN_TRANSMIT_QUEUE_LENGTH
+ u64 XmtZeroFull; // Transmit ring zero full
+ // Rcv
+ u32 RcvNBL; // Offload recieve NBL count
+ u64 DumbRcvBytes; // dumbnic recv bytes
+ u64 DumbRcvUcastBytes; // OID_GEN_DIRECTED_BYTES_RCV
+ u64 DumbRcvMcastBytes; // OID_GEN_MULTICAST_BYTES_RCV
+ u64 DumbRcvBcastBytes; // OID_GEN_BROADCAST_BYTES_RCV
+ u64 SlowRcvBytes; // Slowpath recv bytes
+ u64 FastRcvBytes; // Fastpath recv bytes
+ u64 DumbRcvPkts; // OID_GEN_DIRECTED_FRAMES_RCV
+ u64 DumbRcvTcpPkts; // See SxgCollectStats
+ u64 DumbRcvUcastPkts; // directed packets
+ u64 DumbRcvMcastPkts; // Multicast packets
+ u64 DumbRcvBcastPkts; // OID_GEN_BROADCAST_FRAMES_RCV
+ u64 SlowRcvPkts; // OID_GEN_DIRECTED_FRAMES_RCV
+ u64 RcvErrors; // OID_GEN_RCV_ERROR
+ u64 RcvDiscards; // OID_GEN_RCV_DISCARDS
+ u64 RcvNoBuffer; // OID_GEN_RCV_NO_BUFFER
+ u64 PdqFull; // Processed Data Queue Full
+ u64 EventRingFull; // Event ring full
+ // Verbose stats
+ u64 MaxSends; // Max sends outstanding
+ u64 NoSglBuf; // SGL buffer allocation failure
+ u64 SglFail; // NDIS SGL failure
+ u64 SglAsync; // NDIS SGL failure
+ u64 NoMem; // Memory allocation failure
+ u64 NumInts; // Interrupts
+ u64 FalseInts; // Interrupt with ISR == 0
+ u64 XmtDrops; // No sahara DRAM buffer for xmt
+ // Sahara receive status
+ u64 TransportCsum; // SXG_RCV_STATUS_TRANSPORT_CSUM
+ u64 TransportUflow; // SXG_RCV_STATUS_TRANSPORT_UFLOW
+ u64 TransportHdrLen; // SXG_RCV_STATUS_TRANSPORT_HDRLEN
+ u64 NetworkCsum; // SXG_RCV_STATUS_NETWORK_CSUM:
+ u64 NetworkUflow; // SXG_RCV_STATUS_NETWORK_UFLOW:
+ u64 NetworkHdrLen; // SXG_RCV_STATUS_NETWORK_HDRLEN:
+ u64 Parity; // SXG_RCV_STATUS_PARITY
+ u64 LinkParity; // SXG_RCV_STATUS_LINK_PARITY:
+ u64 LinkEarly; // SXG_RCV_STATUS_LINK_EARLY:
+ u64 LinkBufOflow; // SXG_RCV_STATUS_LINK_BUFOFLOW:
+ u64 LinkCode; // SXG_RCV_STATUS_LINK_CODE:
+ u64 LinkDribble; // SXG_RCV_STATUS_LINK_DRIBBLE:
+ u64 LinkCrc; // SXG_RCV_STATUS_LINK_CRC:
+ u64 LinkOflow; // SXG_RCV_STATUS_LINK_OFLOW:
+ u64 LinkUflow; // SXG_RCV_STATUS_LINK_UFLOW:
+} SXG_STATS, *PSXG_STATS;
+
+
+/****************************************************************************
+ * DUMB-NIC Send path definitions
+ ****************************************************************************/
+
+#define SXG_COMPLETE_DUMB_SEND(_pAdapt, _skb) { \
+ ASSERT(_skb); \
+ dev_kfree_skb_irq(_skb); \
+}
+
+#define SXG_DROP_DUMB_SEND(_pAdapt, _skb) { \
+ ASSERT(_skb); \
+ dev_kfree_skb(_skb); \
+}
+
+// Locate current receive header buffer location. Use this
+// instead of RcvDataHdr->VirtualAddress since the data
+// may have been offset by SXG_ADVANCE_MDL_OFFSET
+#define SXG_RECEIVE_DATA_LOCATION(_RcvDataHdr) (_RcvDataHdr)->skb->data
+
+/************************************************************************
+ * Dumb-NIC receive processing
+ ************************************************************************/
+// Define an SXG_PACKET as an NDIS_PACKET
+#define PSXG_PACKET struct sk_buff *
+// Indications array size
+#define SXG_RCV_ARRAYSIZE 64
+
+#define SXG_ALLOCATE_RCV_PACKET(_pAdapt, _RcvDataBufferHdr) { \
+ struct sk_buff * skb; \
+ skb = alloc_skb(2048, GFP_ATOMIC); \
+ if (skb) { \
+ (_RcvDataBufferHdr)->skb = skb; \
+ skb->next = NULL; \
+ } else { \
+ (_RcvDataBufferHdr)->skb = NULL; \
+ } \
+}
+
+#define SXG_FREE_RCV_PACKET(_RcvDataBufferHdr) { \
+ if((_RcvDataBufferHdr)->skb) { \
+ dev_kfree_skb((_RcvDataBufferHdr)->skb); \
+ } \
+}
+
+// Macro to add a NDIS_PACKET to an indication array
+// If we fill up our array of packet pointers, then indicate this
+// block up now and start on a new one.
+#define SXG_ADD_RCV_PACKET(_pAdapt, _Packet, _PrevPacket, _IndicationList, _NumPackets) { \
+ (_IndicationList)[_NumPackets] = (_Packet); \
+ (_NumPackets)++; \
+ if((_NumPackets) == SXG_RCV_ARRAYSIZE) { \
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \
+ (_NumPackets), 0, 0, 0); \
+ netif_rx((_IndicationList),(_NumPackets)); \
+ (_NumPackets) = 0; \
+ } \
+}
+
+#define SXG_INDICATE_PACKETS(_pAdapt, _IndicationList, _NumPackets) { \
+ if(_NumPackets) { \
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \
+ (_NumPackets), 0, 0, 0); \
+ netif_rx((_IndicationList),(_NumPackets)); \
+ (_NumPackets) = 0; \
+ } \
+}
+
+#define SXG_REINIATIALIZE_PACKET(_Packet) \
+ {} /*_NdisReinitializePacket(_Packet)*/ /* this is not necessary with an skb */
+
+// Definitions to initialize Dumb-nic Receive NBLs
+#define SXG_RCV_PACKET_BUFFER_HDR(_Packet) (((PSXG_RCV_NBL_RESERVED)((_Packet)->MiniportReservedEx))->RcvDataBufferHdr)
+
+#define SXG_RCV_SET_CHECKSUM_INFO(_Packet, _Cpi) \
+ NDIS_PER_PACKET_INFO_FROM_PACKET((_Packet), TcpIpChecksumPacketInfo) = (PVOID)(_Cpi)
+
+#define SXG_RCV_SET_TOEPLITZ(_Packet, _Toeplitz, _Type, _Function) { \
+ NDIS_PACKET_SET_HASH_VALUE((_Packet), (_Toeplitz)); \
+ NDIS_PACKET_SET_HASH_TYPE((_Packet), (_Type)); \
+ NDIS_PACKET_SET_HASH_FUNCTION((_Packet), (_Function)); \
+}
+
+#define SXG_RCV_SET_VLAN_INFO(_Packet, _VlanId, _Priority) { \
+ NDIS_PACKET_8021Q_INFO _Packet8021qInfo; \
+ _Packet8021qInfo.TagHeader.VlanId = (_VlanId); \
+ _Packet8021qInfo.TagHeader.UserPriority = (_Priority); \
+ NDIS_PER_PACKET_INFO_FROM_PACKET((_Packet), Ieee8021QNetBufferListInfo) = \
+ _Packet8021qInfo.Value; \
+}
+
+#define SXG_ADJUST_RCV_PACKET(_Packet, _RcvDataBufferHdr, _Event) { \
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbRcv", \
+ (_RcvDataBufferHdr), (_Packet), \
+ (_Event)->Status, 0); \
+ ASSERT((_Event)->Length <= (_RcvDataBufferHdr)->Size); \
+ Packet->len = (_Event)->Length; \
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros to free a receive data buffer and receive data descriptor block
+///////////////////////////////////////////////////////////////////////////////
+// NOTE - Lock must be held with RCV macros
+#define SXG_GET_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \
+ PLIST_ENTRY _ple; \
+ _Hdr = NULL; \
+ if((_pAdapt)->FreeRcvBufferCount) { \
+ ASSERT(!(IsListEmpty(&(_pAdapt)->FreeRcvBuffers))); \
+ _ple = RemoveHeadList(&(_pAdapt)->FreeRcvBuffers); \
+ (_Hdr) = container_of(_ple, SXG_RCV_DATA_BUFFER_HDR, FreeList); \
+ (_pAdapt)->FreeRcvBufferCount--; \
+ ASSERT((_Hdr)->State == SXG_BUFFER_FREE); \
+ } \
+}
+
+#define SXG_FREE_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \
+ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RtnDHdr", \
+ (_Hdr), (_pAdapt)->FreeRcvBufferCount, \
+ (_Hdr)->State, (_Hdr)->VirtualAddress); \
+/* SXG_RESTORE_MDL_OFFSET(_Hdr); */ \
+ (_pAdapt)->FreeRcvBufferCount++; \
+ ASSERT(((_pAdapt)->AllRcvBlockCount * SXG_RCV_DESCRIPTORS_PER_BLOCK) >= (_pAdapt)->FreeRcvBufferCount); \
+ ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \
+ (_Hdr)->State = SXG_BUFFER_FREE; \
+ InsertTailList(&(_pAdapt)->FreeRcvBuffers, &((_Hdr)->FreeList)); \
+}
+
+#define SXG_FREE_RCV_DESCRIPTOR_BLOCK(_pAdapt, _Hdr) { \
+ ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \
+ (_Hdr)->State = SXG_BUFFER_FREE; \
+ (_pAdapt)->FreeRcvBlockCount++; \
+ ASSERT((_pAdapt)->AllRcvBlockCount >= (_pAdapt)->FreeRcvBlockCount); \
+ InsertTailList(&(_pAdapt)->FreeRcvBlocks, &(_Hdr)->FreeList); \
+}
+
+// SGL macros
+#define SXG_FREE_SGL_BUFFER(_pAdapt, _Sgl, _NB) { \
+ spin_lock(&(_pAdapt)->SglQLock); \
+ (_pAdapt)->FreeSglBufferCount++; \
+ ASSERT((_pAdapt)->AllSglBufferCount >= (_pAdapt)->FreeSglBufferCount);\
+ ASSERT(!((_Sgl)->State & SXG_BUFFER_FREE)); \
+ (_Sgl)->State = SXG_BUFFER_FREE; \
+ InsertTailList(&(_pAdapt)->FreeSglBuffers, &(_Sgl)->FreeList); \
+ spin_unlock(&(_pAdapt)->SglQLock); \
+}
+
+// Get an SGL buffer from the free queue. The first part of this macro
+// attempts to keep ahead of buffer depletion by allocating more when
+// we hit a minimum threshold. Note that we don't grab the lock
+// until after that. We're dealing with round numbers here, so we don't need to,
+// and not grabbing it avoids a possible double-trip.
+#define SXG_GET_SGL_BUFFER(_pAdapt, _Sgl) { \
+ PLIST_ENTRY _ple; \
+ if ((_pAdapt->FreeSglBufferCount < SXG_MIN_SGL_BUFFERS) && \
+ (_pAdapt->AllSglBufferCount < SXG_MAX_SGL_BUFFERS) && \
+ (_pAdapt->AllocationsPending == 0)) { \
+ sxg_allocate_buffer_memory(_pAdapt, \
+ (sizeof(SXG_SCATTER_GATHER) + SXG_SGL_BUF_SIZE),\
+ SXG_BUFFER_TYPE_SGL); \
+ } \
+ _Sgl = NULL; \
+ spin_lock(&(_pAdapt)->SglQLock); \
+ if((_pAdapt)->FreeSglBufferCount) { \
+ ASSERT(!(IsListEmpty(&(_pAdapt)->FreeSglBuffers))); \
+ _ple = RemoveHeadList(&(_pAdapt)->FreeSglBuffers); \
+ (_Sgl) = container_of(_ple, SXG_SCATTER_GATHER, FreeList); \
+ (_pAdapt)->FreeSglBufferCount--; \
+ ASSERT((_Sgl)->State == SXG_BUFFER_FREE); \
+ (_Sgl)->State = SXG_BUFFER_BUSY; \
+ (_Sgl)->pSgl = NULL; \
+ } \
+ spin_unlock(&(_pAdapt)->SglQLock); \
+}
+
+//
+// SXG_MULTICAST_ADDRESS
+//
+// Linked list of multicast addresses.
+typedef struct _SXG_MULTICAST_ADDRESS {
+ unsigned char Address[6];
+ struct _SXG_MULTICAST_ADDRESS *Next;
+} SXG_MULTICAST_ADDRESS, *PSXG_MULTICAST_ADDRESS;
+
+// Structure to maintain chimney send and receive buffer queues.
+// This structure maintains NET_BUFFER_LIST queues that are
+// given to us via the Chimney MiniportTcpOffloadSend and
+// MiniportTcpOffloadReceive routines. This structure DOES NOT
+// manage our data buffer queue
+typedef struct _SXG_BUFFER_QUEUE {
+ u32 Type; // Slow or fast - See below
+ u32 Direction; // Xmt or Rcv
+ u32 Bytes; // Byte count
+ u32 * Head; // Send queue head
+ u32 * Tail; // Send queue tail
+// PNET_BUFFER_LIST NextNBL; // Short cut - next NBL
+// PNET_BUFFER NextNB; // Short cut - next NB
+} SXG_BUFFER_QUEUE, *PSXG_BUFFER_QUEUE;
+
+#define SXG_SLOW_SEND_BUFFER 0
+#define SXG_FAST_SEND_BUFFER 1
+#define SXG_RECEIVE_BUFFER 2
+
+#define SXG_INIT_BUFFER(_Buffer, _Type) { \
+ (_Buffer)->Type = (_Type); \
+ if((_Type) == SXG_RECEIVE_BUFFER) { \
+ (_Buffer)->Direction = 0; \
+ } else { \
+ (_Buffer)->Direction = NDIS_SG_LIST_WRITE_TO_DEVICE; \
+ } \
+ (_Buffer)->Bytes = 0; \
+ (_Buffer)->Head = NULL; \
+ (_Buffer)->Tail = NULL; \
+}
+
+
+#define SXG_RSS_CPU_COUNT(_pAdapt) \
+ ((_pAdapt)->RssEnabled ? NR_CPUS : 1)
+
+/****************************************************************************
+ * DRIVER and ADAPTER structures
+ ****************************************************************************/
+
+// Adapter states - These states closely match the adapter states
+// documented in the DDK (with a few exceptions).
+typedef enum _SXG_STATE {
+ SXG_STATE_INITIALIZING, // Initializing
+ SXG_STATE_BOOTDIAG, // Boot-Diagnostic mode
+ SXG_STATE_PAUSING, // Pausing
+ SXG_STATE_PAUSED, // Paused
+ SXG_STATE_RUNNING, // Running
+ SXG_STATE_RESETTING, // Reset in progress
+ SXG_STATE_SLEEP, // Sleeping
+ SXG_STATE_DIAG, // Diagnostic mode
+ SXG_STATE_HALTING, // Halting
+ SXG_STATE_HALTED, // Down or not-initialized
+ SXG_STATE_SHUTDOWN // shutdown
+} SXG_STATE, *PSXG_STATE;
+
+// Link state
+typedef enum _SXG_LINK_STATE {
+ SXG_LINK_DOWN,
+ SXG_LINK_UP
+} SXG_LINK_STATE, *PSXG_LINK_STATE;
+
+// Link initialization timeout in 100us units
+#define SXG_LINK_TIMEOUT 100000 // 10 Seconds - REDUCE!
+
+
+// Microcode file selection codes
+typedef enum _SXG_UCODE_SEL {
+ SXG_UCODE_SAHARA, // Sahara ucode
+ SXG_UCODE_SDIAGCPU, // Sahara CPU diagnostic ucode
+ SXG_UCODE_SDIAGSYS // Sahara system diagnostic ucode
+} SXG_UCODE_SEL;
+
+
+#define SXG_DISABLE_ALL_INTERRUPTS(_padapt) sxg_disable_interrupt(_padapt)
+#define SXG_ENABLE_ALL_INTERRUPTS(_padapt) sxg_enable_interrupt(_padapt)
+
+// This probably lives in a proto.h file. Move later
+#define SXG_MULTICAST_PACKET(_pether) ((_pether)->ether_dhost[0] & 0x01)
+#define SXG_BROADCAST_PACKET(_pether) ((*(u32 *)(_pether)->ether_dhost == 0xFFFFFFFF) && \
+ (*(u16 *)&(_pether)->ether_dhost[4] == 0xFFFF))
+
+// For DbgPrints
+#define SXG_ID DPFLTR_IHVNETWORK_ID
+#define SXG_ERROR DPFLTR_ERROR_LEVEL
+
+//
+// SXG_DRIVER structure -
+//
+// contains information about the sxg driver. There is only
+// one of these, and it is defined as a global.
+typedef struct _SXG_DRIVER {
+ struct _adapter_t *Adapters; // Linked list of adapters
+ ushort AdapterID; // Maintain unique adapter ID
+} SXG_DRIVER, *PSXG_DRIVER;
+
+#ifdef STATUS_SUCCESS
+#undef STATUS_SUCCESS
+#endif
+
+#define STATUS_SUCCESS 0
+#define STATUS_PENDING 0
+#define STATUS_FAILURE -1
+#define STATUS_ERROR -2
+#define STATUS_NOT_SUPPORTED -3
+#define STATUS_BUFFER_TOO_SHORT -4
+#define STATUS_RESOURCES -5
+
+#define SLIC_MAX_CARDS 32
+#define SLIC_MAX_PORTS 4 /* Max # of ports per card */
+#if SLIC_DUMP_ENABLED
+// Dump buffer size
+//
+// This cannot be bigger than the max DMA size the card supports,
+// given the current code structure in the host and ucode.
+// Mojave supports 16K, Oasis supports 16K-1, so
+// just set this at 15K, shouldnt make that much of a diff.
+#define DUMP_BUF_SIZE 0x3C00
+#endif
+
+#define MIN(a, b) ((u32)(a) < (u32)(b) ? (a) : (b))
+#define MAX(a, b) ((u32)(a) > (u32)(b) ? (a) : (b))
+
+typedef struct _mcast_address_t
+{
+ unsigned char address[6];
+ struct _mcast_address_t *next;
+} mcast_address_t, *p_mcast_address_t;
+
+#define CARD_DOWN 0x00000000
+#define CARD_UP 0x00000001
+#define CARD_FAIL 0x00000002
+#define CARD_DIAG 0x00000003
+#define CARD_SLEEP 0x00000004
+
+#define ADAPT_DOWN 0x00
+#define ADAPT_UP 0x01
+#define ADAPT_FAIL 0x02
+#define ADAPT_RESET 0x03
+#define ADAPT_SLEEP 0x04
+
+#define ADAPT_FLAGS_BOOTTIME 0x0001
+#define ADAPT_FLAGS_IS64BIT 0x0002
+#define ADAPT_FLAGS_PENDINGLINKDOWN 0x0004
+#define ADAPT_FLAGS_FIBERMEDIA 0x0008
+#define ADAPT_FLAGS_LOCKS_ALLOCED 0x0010
+#define ADAPT_FLAGS_INT_REGISTERED 0x0020
+#define ADAPT_FLAGS_LOAD_TIMER_SET 0x0040
+#define ADAPT_FLAGS_STATS_TIMER_SET 0x0080
+#define ADAPT_FLAGS_RESET_TIMER_SET 0x0100
+
+#define LINK_DOWN 0x00
+#define LINK_CONFIG 0x01
+#define LINK_UP 0x02
+
+#define LINK_10MB 0x00
+#define LINK_100MB 0x01
+#define LINK_AUTOSPEED 0x02
+#define LINK_1000MB 0x03
+#define LINK_10000MB 0x04
+
+#define LINK_HALFD 0x00
+#define LINK_FULLD 0x01
+#define LINK_AUTOD 0x02
+
+#define MAC_DIRECTED 0x00000001
+#define MAC_BCAST 0x00000002
+#define MAC_MCAST 0x00000004
+#define MAC_PROMISC 0x00000008
+#define MAC_LOOPBACK 0x00000010
+#define MAC_ALLMCAST 0x00000020
+
+#define SLIC_DUPLEX(x) ((x==LINK_FULLD) ? "FDX" : "HDX")
+#define SLIC_SPEED(x) ((x==LINK_100MB) ? "100Mb" : ((x==LINK_1000MB) ? "1000Mb" : " 10Mb"))
+#define SLIC_LINKSTATE(x) ((x==LINK_DOWN) ? "Down" : "Up ")
+#define SLIC_ADAPTER_STATE(x) ((x==ADAPT_UP) ? "UP" : "Down")
+#define SLIC_CARD_STATE(x) ((x==CARD_UP) ? "UP" : "Down")
+
+
+typedef struct _ether_header
+{
+ unsigned char ether_dhost[6];
+ unsigned char ether_shost[6];
+ ushort ether_type;
+} ether_header, *p_ether_header;
+
+
+#define NUM_CFG_SPACES 2
+#define NUM_CFG_REGS 64
+
+typedef struct _physcard_t
+{
+ struct _adapter_t *adapter[SLIC_MAX_PORTS];
+ struct _physcard_t *next;
+ unsigned int adapters_allocd;
+} physcard_t, *p_physcard_t;
+
+typedef struct _sxgbase_driver
+{
+ spinlock_t driver_lock;
+ unsigned long flags; /* irqsave for spinlock */
+ u32 num_sxg_cards;
+ u32 num_sxg_ports;
+ u32 num_sxg_ports_active;
+ u32 dynamic_intagg;
+ p_physcard_t phys_card;
+} sxgbase_driver_t;
+
+
+typedef struct _adapter_t
+{
+ void * ifp;
+ unsigned int port;
+ p_physcard_t physcard;
+ unsigned int physport;
+ unsigned int cardindex;
+ unsigned int card_size;
+ unsigned int chipid;
+ unsigned int busnumber;
+ unsigned int slotnumber;
+ unsigned int functionnumber;
+ ushort vendid;
+ ushort devid;
+ ushort subsysid;
+ u32 irq;
+
+ void * sxg_adapter;
+ u32 nBusySend;
+
+ void __iomem * base_addr;
+ u32 memorylength;
+ u32 drambase;
+ u32 dramlength;
+ unsigned int queues_initialized;
+ unsigned int allocated;
+ unsigned int activated;
+ u32 intrregistered;
+ unsigned int isp_initialized;
+ unsigned int gennumber;
+ u32 curaddrupper;
+ u32 isrcopy;
+ unsigned char state;
+ unsigned char linkstate;
+ unsigned char linkspeed;
+ unsigned char linkduplex;
+ unsigned int flags;
+ unsigned char macaddr[6];
+ unsigned char currmacaddr[6];
+ u32 macopts;
+ ushort devflags_prev;
+ u64 mcastmask;
+ p_mcast_address_t mcastaddrs;
+ struct timer_list pingtimer;
+ u32 pingtimerset;
+ struct timer_list statstimer;
+ u32 statstimerset;
+ struct timer_list vpci_timer;
+ u32 vpci_timerset;
+ struct timer_list loadtimer;
+ u32 loadtimerset;
+
+ u32 xmitq_full;
+ u32 all_reg_writes;
+ u32 icr_reg_writes;
+ u32 isr_reg_writes;
+ u32 error_interrupts;
+ u32 error_rmiss_interrupts;
+ u32 rx_errors;
+ u32 rcv_drops;
+ u32 rcv_interrupts;
+ u32 xmit_interrupts;
+ u32 linkevent_interrupts;
+ u32 upr_interrupts;
+ u32 num_isrs;
+ u32 false_interrupts;
+ u32 tx_packets;
+ u32 xmit_completes;
+ u32 tx_drops;
+ u32 rcv_broadcasts;
+ u32 rcv_multicasts;
+ u32 rcv_unicasts;
+ u32 max_isr_rcvs;
+ u32 max_isr_xmits;
+ u32 rcv_interrupt_yields;
+ u32 intagg_period;
+ struct net_device_stats stats;
+ u32 * MiniportHandle; // Our miniport handle
+ SXG_STATE State; // Adapter state
+ SXG_LINK_STATE LinkState; // Link state
+ u64 LinkSpeed; // Link Speed
+ u32 PowerState; // NDIS power state
+ struct _adapter_t *Next; // Linked list
+ ushort AdapterID; // 1..n
+ unsigned char MacAddr[6]; // Our permanent HW mac address
+ unsigned char CurrMacAddr[6]; // Our Current mac address
+ p_net_device netdev;
+ p_net_device next_netdevice;
+ struct pci_dev * pcidev;
+
+ PSXG_MULTICAST_ADDRESS MulticastAddrs; // Multicast list
+ u64 MulticastMask; // Multicast mask
+ u32 * InterruptHandle; // Register Interrupt handle
+ u32 InterruptLevel; // From Resource list
+ u32 InterruptVector; // From Resource list
+ spinlock_t AdapterLock; /* Serialize access adapter routines */
+ spinlock_t Bit64RegLock; /* For writing 64-bit addresses */
+ PSXG_HW_REGS HwRegs; // Sahara HW Register Memory (BAR0/1)
+ PSXG_UCODE_REGS UcodeRegs; // Microcode Register Memory (BAR2/3)
+ PSXG_TCB_REGS TcbRegs; // Same as Ucode regs - See sxghw.h
+ ushort ResetDpcCount; // For timeout
+ ushort RssDpcCount; // For timeout
+ ushort VendorID; // Vendor ID
+ ushort DeviceID; // Device ID
+ ushort SubSystemID; // Sub-System ID
+ ushort FrameSize; // Maximum frame size
+ u32 * DmaHandle; // NDIS DMA handle
+ u32 * PacketPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out
+ u32 * BufferPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out
+ u32 MacFilter; // NDIS MAC Filter
+ ushort IpId; // For slowpath
+ PSXG_EVENT_RING EventRings; // Host event rings. 1/CPU to 16 max
+ dma_addr_t PEventRings; // Physical address
+ u32 NextEvent[SXG_MAX_RSS]; // Current location in ring
+ dma_addr_t PTcbBuffers; // TCB Buffers - physical address
+ dma_addr_t PTcbCompBuffers; // TCB Composite Buffers - phys addr
+ PSXG_XMT_RING XmtRings; // Transmit rings
+ dma_addr_t PXmtRings; // Transmit rings - physical address
+ SXG_RING_INFO XmtRingZeroInfo; // Transmit ring 0 info
+ spinlock_t XmtZeroLock; /* Transmit ring 0 lock */
+ u32 * XmtRingZeroIndex; // Shared XMT ring 0 index
+ dma_addr_t PXmtRingZeroIndex; // Shared XMT ring 0 index - physical
+ LIST_ENTRY FreeProtocolHeaders;// Free protocol headers
+ u32 FreeProtoHdrCount; // Count
+ void * ProtocolHeaders; // Block of protocol header
+ dma_addr_t PProtocolHeaders; // Block of protocol headers - phys
+
+ PSXG_RCV_RING RcvRings; // Receive rings
+ dma_addr_t PRcvRings; // Receive rings - physical address
+ SXG_RING_INFO RcvRingZeroInfo; // Receive ring 0 info
+
+ u32 * Isr; // Interrupt status register
+ dma_addr_t PIsr; // ISR - physical address
+ u32 IsrCopy[SXG_MAX_RSS]; // Copy of ISR
+ ushort InterruptsEnabled; // Bitmask of enabled vectors
+ unsigned char * IndirectionTable; // RSS indirection table
+ dma_addr_t PIndirectionTable; // Physical address
+ ushort RssTableSize; // From NDIS_RECEIVE_SCALE_PARAMETERS
+ ushort HashKeySize; // From NDIS_RECEIVE_SCALE_PARAMETERS
+ unsigned char HashSecretKey[40]; // rss key
+ u32 HashInformation;
+ // Receive buffer queues
+ spinlock_t RcvQLock; /* Receive Queue Lock */
+ LIST_ENTRY FreeRcvBuffers; // Free SXG_DATA_BUFFER queue
+ LIST_ENTRY FreeRcvBlocks; // Free SXG_RCV_DESCRIPTOR_BLOCK Q
+ LIST_ENTRY AllRcvBlocks; // All SXG_RCV_BLOCKs
+ ushort FreeRcvBufferCount; // Number of free rcv data buffers
+ ushort FreeRcvBlockCount; // # of free rcv descriptor blocks
+ ushort AllRcvBlockCount; // Number of total receive blocks
+ ushort ReceiveBufferSize; // SXG_RCV_DATA/JUMBO_BUFFER_SIZE only
+ u32 AllocationsPending; // Receive allocation pending
+ u32 RcvBuffersOnCard; // SXG_DATA_BUFFERS owned by card
+ // SGL buffers
+ spinlock_t SglQLock; /* SGL Queue Lock */
+ LIST_ENTRY FreeSglBuffers; // Free SXG_SCATTER_GATHER
+ LIST_ENTRY AllSglBuffers; // All SXG_SCATTER_GATHER
+ ushort FreeSglBufferCount; // Number of free SGL buffers
+ ushort AllSglBufferCount; // Number of total SGL buffers
+ u32 CurrentTime; // Tick count
+ u32 FastpathConnections;// # of fastpath connections
+ // Various single-bit flags:
+ u32 BasicAllocations:1; // Locks and listheads
+ u32 IntRegistered:1; // Interrupt registered
+ u32 PingOutstanding:1; // Ping outstanding to card
+ u32 Dead:1; // Card dead
+ u32 DumpDriver:1; // OID_SLIC_DRIVER_DUMP request
+ u32 DumpCard:1; // OID_SLIC_CARD_DUMP request
+ u32 DumpCmdRunning:1; // Dump command in progress
+ u32 DebugRunning:1; // AGDB debug in progress
+ u32 JumboEnabled:1; // Jumbo frames enabled
+ u32 MsiEnabled:1; // MSI interrupt enabled
+ u32 RssEnabled:1; // RSS Enabled
+ u32 FailOnBadEeprom:1; // Fail on Bad Eeprom
+ u32 DiagStart:1; // Init adapter for diagnostic start
+ // Stats
+ u32 PendingRcvCount; // Outstanding rcv indications
+ u32 PendingXmtCount; // Outstanding send requests
+ SXG_STATS Stats; // Statistics
+ u32 ReassBufs; // Number of reassembly buffers
+ // Card Crash Info
+ ushort CrashLocation; // Microcode crash location
+ unsigned char CrashCpu; // Sahara CPU ID
+ // Diagnostics
+ // PDIAG_CMD DiagCmds; // List of free diagnostic commands
+ // PDIAG_BUFFER DiagBuffers; // List of free diagnostic buffers
+ // PDIAG_REQ DiagReqQ; // List of outstanding (asynchronous) diag requests
+ // u32 DiagCmdTimeout; // Time out for diag cmds (seconds) XXXTODO - replace with SXG_PARAM var?
+ // unsigned char DiagDmaDesc[DMA_CPU_CTXS]; // Free DMA descriptors bit field (32 CPU ctx * 8 DMA ctx)
+
+ /////////////////////////////////////////////////////////////////////
+ // Put preprocessor-conditional fields at the end so we don't
+ // have to recompile sxgdbg everytime we reconfigure the driver
+ /////////////////////////////////////////////////////////////////////
+ void * PendingSetRss; // Pending RSS parameter change
+ u32 IPv4HdrSize; // Shared 5.2/6.0 encap param
+ unsigned char * InterruptInfo; // Allocated by us during AddDevice
+#if defined(CONFIG_X86)
+ u32 AddrUpper; // Upper 32 bits of 64-bit register
+#endif
+ //#if SXG_FAILURE_DUMP
+ // NDIS_EVENT DumpThreadEvent; // syncronize dump thread
+ // BOOLEAN DumpThreadRunning; // termination flag
+ // PSXG_DUMP_CMD DumpBuffer; // 68k - Cmd and Buffer
+ // dma_addr_t PDumpBuffer; // Physical address
+ //#endif // SXG_FAILURE_DUMP
+
+} adapter_t, *p_adapter_t;
+
+#if SLIC_DUMP_ENABLED
+#define SLIC_DUMP_REQUESTED 1
+#define SLIC_DUMP_IN_PROGRESS 2
+#define SLIC_DUMP_DONE 3
+
+/****************************************************************************
+ *
+ * Microcode crash information structure. This
+ * structure is written out to the card's SRAM when the microcode panic's.
+ *
+ ****************************************************************************/
+typedef struct _slic_crash_info {
+ ushort cpu_id;
+ ushort crash_pc;
+} slic_crash_info, *p_slic_crash_info;
+
+#define CRASH_INFO_OFFSET 0x155C
+
+#endif
+
+#define UPDATE_STATS(largestat, newstat, oldstat) \
+{ \
+ if ((newstat) < (oldstat)) \
+ (largestat) += ((newstat) + (0xFFFFFFFF - oldstat + 1)); \
+ else \
+ (largestat) += ((newstat) - (oldstat)); \
+}
+
+#define UPDATE_STATS_GB(largestat, newstat, oldstat) \
+{ \
+ (largestat) += ((newstat) - (oldstat)); \
+}
+
+#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \
+{ \
+ _Result = TRUE; \
+ if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \
+ _Result = FALSE; \
+ if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \
+ _Result = FALSE; \
+}
+
+#define ETHERMAXFRAME 1514
+#define JUMBOMAXFRAME 9014
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+#define SXG_GET_ADDR_LOW(_addr) (u32)((u64)(_addr) & 0x00000000FFFFFFFF)
+#define SXG_GET_ADDR_HIGH(_addr) (u32)(((u64)(_addr) >> 32) & 0x00000000FFFFFFFF)
+#else
+#define SXG_GET_ADDR_LOW(_addr) (u32)_addr
+#define SXG_GET_ADDR_HIGH(_addr) (u32)0
+#endif
+
+#define FLUSH TRUE
+#define DONT_FLUSH FALSE
+
+#define SIOCSLICDUMPCARD SIOCDEVPRIVATE+9
+#define SIOCSLICSETINTAGG SIOCDEVPRIVATE+10
+#define SIOCSLICTRACEDUMP SIOCDEVPRIVATE+11
+
+#endif /* __SXG_DRIVER_H__ */
diff --git a/drivers/staging/sxg/sxg_os.h b/drivers/staging/sxg/sxg_os.h
new file mode 100644
index 00000000000..26fb0ffafa5
--- /dev/null
+++ b/drivers/staging/sxg/sxg_os.h
@@ -0,0 +1,154 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2000-2008 Alacritech, Inc. All rights reserved.
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: sxg_os.h
+ *
+ * These are the Linux-specific definitions required for the SLICOSS
+ * driver, which should allow for greater portability to other OSes.
+ */
+#ifndef _SLIC_OS_SPECIFIC_H_
+#define _SLIC_OS_SPECIFIC_H_
+
+#define FALSE (0)
+#define TRUE (1)
+
+
+typedef struct _LIST_ENTRY {
+ struct _LIST_ENTRY *nle_flink;
+ struct _LIST_ENTRY *nle_blink;
+} list_entry, LIST_ENTRY, *PLIST_ENTRY;
+
+#define InitializeListHead(l) \
+ (l)->nle_flink = (l)->nle_blink = (l)
+
+#define IsListEmpty(h) \
+ ((h)->nle_flink == (h))
+
+#define RemoveEntryList(e) \
+ do { \
+ list_entry *b; \
+ list_entry *f; \
+ \
+ f = (e)->nle_flink; \
+ b = (e)->nle_blink; \
+ b->nle_flink = f; \
+ f->nle_blink = b; \
+ } while (0)
+
+/* These two have to be inlined since they return things. */
+
+static __inline PLIST_ENTRY
+RemoveHeadList(list_entry *l)
+{
+ list_entry *f;
+ list_entry *e;
+
+ e = l->nle_flink;
+ f = e->nle_flink;
+ l->nle_flink = f;
+ f->nle_blink = l;
+
+ return (e);
+}
+
+static __inline PLIST_ENTRY
+RemoveTailList(list_entry *l)
+{
+ list_entry *b;
+ list_entry *e;
+
+ e = l->nle_blink;
+ b = e->nle_blink;
+ l->nle_blink = b;
+ b->nle_flink = l;
+
+ return (e);
+}
+
+
+#define InsertTailList(l, e) \
+ do { \
+ list_entry *b; \
+ \
+ b = (l)->nle_blink; \
+ (e)->nle_flink = (l); \
+ (e)->nle_blink = b; \
+ b->nle_flink = (e); \
+ (l)->nle_blink = (e); \
+ } while (0)
+
+#define InsertHeadList(l, e) \
+ do { \
+ list_entry *f; \
+ \
+ f = (l)->nle_flink; \
+ (e)->nle_flink = f; \
+ (e)->nle_blink = l; \
+ f->nle_blink = (e); \
+ (l)->nle_flink = (e); \
+ } while (0)
+
+
+#define ATK_DEBUG 1
+
+#if ATK_DEBUG
+#define SLIC_TIMESTAMP(value) { \
+ struct timeval timev; \
+ do_gettimeofday(&timev); \
+ value = timev.tv_sec*1000000 + timev.tv_usec; \
+}
+#else
+#define SLIC_TIMESTAMP(value)
+#endif
+
+
+/****************** SXG DEFINES *****************************************/
+
+#ifdef ATKDBG
+#define SXG_TIMESTAMP(value) { \
+ struct timeval timev; \
+ do_gettimeofday(&timev); \
+ value = timev.tv_sec*1000000 + timev.tv_usec; \
+}
+#else
+#define SXG_TIMESTAMP(value)
+#endif
+
+#define WRITE_REG(reg,value,flush) sxg_reg32_write((&reg), (value), (flush))
+#define WRITE_REG64(a,reg,value,cpu) sxg_reg64_write((a),(&reg),(value),(cpu))
+#define READ_REG(reg,value) (value) = readl((void __iomem *)(&reg))
+
+#endif /* _SLIC_OS_SPECIFIC_H_ */
+
diff --git a/drivers/staging/sxg/sxgdbg.h b/drivers/staging/sxg/sxgdbg.h
new file mode 100644
index 00000000000..cfb6c7c77a9
--- /dev/null
+++ b/drivers/staging/sxg/sxgdbg.h
@@ -0,0 +1,190 @@
+/**************************************************************************
+ *
+ * Copyright © 2000-2008 Alacritech, Inc. All rights reserved.
+ *
+ * $Id: sxgdbg.h,v 1.1 2008/06/27 12:49:28 mook Exp $
+ *
+ * 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, 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 ALACRITECH, INC. ``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 ALACRITECH, INC. 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of Alacritech, Inc.
+ *
+ **************************************************************************/
+
+/*
+ * FILENAME: sxgdbg.h
+ *
+ * All debug and assertion-based definitions and macros are included
+ * in this file for the SXGOSS driver.
+ */
+#ifndef _SXG_DEBUG_H_
+#define _SXG_DEBUG_H_
+
+#define ATKDBG 1
+#define ATK_TRACE_ENABLED 1
+
+#define DBG_ERROR(n, args...) printk(KERN_EMERG n, ##args)
+
+#ifdef ASSERT
+#undef ASSERT
+#endif
+
+#ifdef SXG_ASSERT_ENABLED
+#ifndef ASSERT
+#define ASSERT(a) \
+ { \
+ if (!(a)) { \
+ DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n",\
+ __FILE__, __FUNCTION__, __LINE__); \
+ } \
+ }
+#endif
+#else
+#ifndef ASSERT
+#define ASSERT(a)
+#endif
+#endif /* SXG_ASSERT_ENABLED */
+
+
+#ifdef ATKDBG
+/*
+ * Global for timer granularity; every driver must have an instance
+ * of this initialized to 0
+ */
+
+extern ulong ATKTimerDiv;
+
+/*
+ * trace_entry_t -
+ *
+ * This structure defines an entry in the trace buffer. The
+ * first few fields mean the same from entry to entry, while
+ * the meaning of last several fields change to suit the
+ * needs of the trace entry. Typically they are function call
+ * parameters.
+ */
+typedef struct _trace_entry_s {
+ char name[8]; /* 8 character name - like 's'i'm'b'a'r'c'v' */
+ u32 time; /* Current clock tic */
+ unsigned char cpu; /* Current CPU */
+ unsigned char irql; /* Current IRQL */
+ unsigned char driver; /* The driver which added the trace call */
+ unsigned char pad2; /* pad to 4 byte boundary - will probably get used */
+ u32 arg1; /* Caller arg1 */
+ u32 arg2; /* Caller arg2 */
+ u32 arg3; /* Caller arg3 */
+ u32 arg4; /* Caller arg4 */
+} trace_entry_t, *ptrace_entry_t;
+
+/*
+ * Driver types for driver field in trace_entry_t
+ */
+#define TRACE_SXG 1
+#define TRACE_VPCI 2
+#define TRACE_SLIC 3
+
+#define TRACE_ENTRIES 1024
+
+typedef struct _sxg_trace_buffer_t
+{
+ unsigned int size; /* aid for windbg extension */
+ unsigned int in; /* Where to add */
+ unsigned int level; /* Current Trace level */
+ spinlock_t lock; /* For MP tracing */
+ trace_entry_t entries[TRACE_ENTRIES];/* The circular buffer */
+} sxg_trace_buffer_t;
+
+/*
+ * The trace levels
+ *
+ * XXX At the moment I am only defining critical, important, and noisy.
+ * I am leaving room for more if anyone wants them.
+ */
+#define TRACE_NONE 0 /* For trace level - if no tracing wanted */
+#define TRACE_CRITICAL 1 /* minimal tracing - only critical stuff */
+#define TRACE_IMPORTANT 5 /* more tracing - anything important */
+#define TRACE_NOISY 10 /* Everything in the world */
+
+
+/**********************************************************************
+ *
+ * The macros themselves -
+ *
+ *********************************************************************/
+#if ATK_TRACE_ENABLED
+#define SXG_TRACE_INIT(buffer, tlevel) \
+{ \
+ memset((buffer), 0, sizeof(sxg_trace_buffer_t)); \
+ (buffer)->level = (tlevel); \
+ (buffer)->size = TRACE_ENTRIES; \
+ spin_lock_init(&(buffer)->lock); \
+}
+#else
+#define SXG_TRACE_INIT(buffer, tlevel)
+#endif
+
+/*
+ * The trace macro. This is active only if ATK_TRACE_ENABLED is set.
+ */
+#if ATK_TRACE_ENABLED
+#define SXG_TRACE(tdriver, buffer, tlevel, tname, a1, a2, a3, a4) { \
+ if ((buffer) && ((buffer)->level >= (tlevel))) { \
+ unsigned int trace_irql = 0; /* ?????? FIX THIS */ \
+ unsigned int trace_len; \
+ ptrace_entry_t trace_entry; \
+ struct timeval timev; \
+ \
+ spin_lock(&(buffer)->lock); \
+ trace_entry = &(buffer)->entries[(buffer)->in]; \
+ do_gettimeofday(&timev); \
+ \
+ memset(trace_entry->name, 0, 8); \
+ trace_len = strlen(tname); \
+ trace_len = trace_len > 8 ? 8 : trace_len; \
+ memcpy(trace_entry->name, (tname), trace_len); \
+ trace_entry->time = timev.tv_usec; \
+ trace_entry->cpu = (unsigned char)(smp_processor_id() & 0xFF); \
+ trace_entry->driver = (tdriver); \
+ trace_entry->irql = trace_irql; \
+ trace_entry->arg1 = (ulong)(a1); \
+ trace_entry->arg2 = (ulong)(a2); \
+ trace_entry->arg3 = (ulong)(a3); \
+ trace_entry->arg4 = (ulong)(a4); \
+ \
+ (buffer)->in++; \
+ if ((buffer)->in == TRACE_ENTRIES) \
+ (buffer)->in = 0; \
+ \
+ spin_unlock(&(buffer)->lock); \
+ } \
+}
+#else
+#define SXG_TRACE(tdriver, buffer, tlevel, tname, a1, a2, a3, a4)
+#endif
+
+#endif
+
+#endif /* _SXG_DEBUG_H_ */
diff --git a/drivers/staging/sxg/sxghif.h b/drivers/staging/sxg/sxghif.h
new file mode 100644
index 00000000000..ed26ceaa131
--- /dev/null
+++ b/drivers/staging/sxg/sxghif.h
@@ -0,0 +1,861 @@
+/*
+ * Copyright © 1997-2007 Alacritech, Inc. All rights reserved
+ *
+ * $Id: sxghif.h,v 1.5 2008/07/24 19:18:22 chris Exp $
+ *
+ * sxghif.h:
+ *
+ * This file contains structures and definitions for the
+ * Alacritech Sahara host interface
+ */
+
+/*******************************************************************************
+ * UCODE Registers
+ *******************************************************************************/
+typedef struct _SXG_UCODE_REGS {
+ // Address 0 - 0x3F = Command codes 0-15 for TCB 0. Excode 0
+ u32 Icr; // Code = 0 (extended), ExCode = 0 - Int control
+ u32 RsvdReg1; // Code = 1 - TOE -NA
+ u32 RsvdReg2; // Code = 2 - TOE -NA
+ u32 RsvdReg3; // Code = 3 - TOE -NA
+ u32 RsvdReg4; // Code = 4 - TOE -NA
+ u32 RsvdReg5; // Code = 5 - TOE -NA
+ u32 CardUp; // Code = 6 - Microcode initialized when 1
+ u32 RsvdReg7; // Code = 7 - TOE -NA
+ u32 CodeNotUsed[8]; // Codes 8-15 not used. ExCode = 0
+ // This brings us to ExCode 1 at address 0x40 = Interrupt status pointer
+ u32 Isp; // Code = 0 (extended), ExCode = 1
+ u32 PadEx1[15]; // Codes 1-15 not used with extended codes
+ // ExCode 2 = Interrupt Status Register
+ u32 Isr; // Code = 0 (extended), ExCode = 2
+ u32 PadEx2[15];
+ // ExCode 3 = Event base register. Location of event rings
+ u32 EventBase; // Code = 0 (extended), ExCode = 3
+ u32 PadEx3[15];
+ // ExCode 4 = Event ring size
+ u32 EventSize; // Code = 0 (extended), ExCode = 4
+ u32 PadEx4[15];
+ // ExCode 5 = TCB Buffers base address
+ u32 TcbBase; // Code = 0 (extended), ExCode = 5
+ u32 PadEx5[15];
+ // ExCode 6 = TCB Composite Buffers base address
+ u32 TcbCompBase; // Code = 0 (extended), ExCode = 6
+ u32 PadEx6[15];
+ // ExCode 7 = Transmit ring base address
+ u32 XmtBase; // Code = 0 (extended), ExCode = 7
+ u32 PadEx7[15];
+ // ExCode 8 = Transmit ring size
+ u32 XmtSize; // Code = 0 (extended), ExCode = 8
+ u32 PadEx8[15];
+ // ExCode 9 = Receive ring base address
+ u32 RcvBase; // Code = 0 (extended), ExCode = 9
+ u32 PadEx9[15];
+ // ExCode 10 = Receive ring size
+ u32 RcvSize; // Code = 0 (extended), ExCode = 10
+ u32 PadEx10[15];
+ // ExCode 11 = Read EEPROM Config
+ u32 Config; // Code = 0 (extended), ExCode = 11
+ u32 PadEx11[15];
+ // ExCode 12 = Multicast bits 31:0
+ u32 McastLow; // Code = 0 (extended), ExCode = 12
+ u32 PadEx12[15];
+ // ExCode 13 = Multicast bits 63:32
+ u32 McastHigh; // Code = 0 (extended), ExCode = 13
+ u32 PadEx13[15];
+ // ExCode 14 = Ping
+ u32 Ping; // Code = 0 (extended), ExCode = 14
+ u32 PadEx14[15];
+ // ExCode 15 = Link MTU
+ u32 LinkMtu; // Code = 0 (extended), ExCode = 15
+ u32 PadEx15[15];
+ // ExCode 16 = Download synchronization
+ u32 LoadSync; // Code = 0 (extended), ExCode = 16
+ u32 PadEx16[15];
+ // ExCode 17 = Upper DRAM address bits on 32-bit systems
+ u32 Upper; // Code = 0 (extended), ExCode = 17
+ u32 PadEx17[15];
+ // ExCode 18 = Slowpath Send Index Address
+ u32 SPSendIndex; // Code = 0 (extended), ExCode = 18
+ u32 PadEx18[15];
+ u32 RsvdXF; // Code = 0 (extended), ExCode = 19
+ u32 PadEx19[15];
+ // ExCode 20 = Aggregation
+ u32 Aggregation; // Code = 0 (extended), ExCode = 20
+ u32 PadEx20[15];
+ // ExCode 21 = Receive MDL push timer
+ u32 PushTicks; // Code = 0 (extended), ExCode = 21
+ u32 PadEx21[15];
+ // ExCode 22 = TOE NA
+ u32 AckFrequency; // Code = 0 (extended), ExCode = 22
+ u32 PadEx22[15];
+ // ExCode 23 = TOE NA
+ u32 RsvdReg23;
+ u32 PadEx23[15];
+ // ExCode 24 = TOE NA
+ u32 RsvdReg24;
+ u32 PadEx24[15];
+ // ExCode 25 = TOE NA
+ u32 RsvdReg25; // Code = 0 (extended), ExCode = 25
+ u32 PadEx25[15];
+ // ExCode 26 = Receive checksum requirements
+ u32 ReceiveChecksum; // Code = 0 (extended), ExCode = 26
+ u32 PadEx26[15];
+ // ExCode 27 = RSS Requirements
+ u32 Rss; // Code = 0 (extended), ExCode = 27
+ u32 PadEx27[15];
+ // ExCode 28 = RSS Table
+ u32 RssTable; // Code = 0 (extended), ExCode = 28
+ u32 PadEx28[15];
+ // ExCode 29 = Event ring release entries
+ u32 EventRelease; // Code = 0 (extended), ExCode = 29
+ u32 PadEx29[15];
+ // ExCode 30 = Number of receive bufferlist commands on ring 0
+ u32 RcvCmd; // Code = 0 (extended), ExCode = 30
+ u32 PadEx30[15];
+ // ExCode 31 = slowpath transmit command - Data[31:0] = 1
+ u32 XmtCmd; // Code = 0 (extended), ExCode = 31
+ u32 PadEx31[15];
+ // ExCode 32 = Dump command
+ u32 DumpCmd; // Code = 0 (extended), ExCode = 32
+ u32 PadEx32[15];
+ // ExCode 33 = Debug command
+ u32 DebugCmd; // Code = 0 (extended), ExCode = 33
+ u32 PadEx33[15];
+ // There are 128 possible extended commands - each of account for 16
+ // words (including the non-relevent base command codes 1-15).
+ // Pad for the remainder of these here to bring us to the next CPU
+ // base. As extended codes are added, reduce the first array value in
+ // the following field
+ u32 PadToNextCpu[94][16]; // 94 = 128 - 34 (34 = Excodes 0 - 33)
+} SXG_UCODE_REGS, *PSXG_UCODE_REGS;
+
+// Interrupt control register (0) values
+#define SXG_ICR_DISABLE 0x00000000
+#define SXG_ICR_ENABLE 0x00000001
+#define SXG_ICR_MASK 0x00000002
+#define SXG_ICR_MSGID_MASK 0xFFFF0000
+#define SXG_ICR_MSGID_SHIFT 16
+#define SXG_ICR(_MessageId, _Data) \
+ ((((_MessageId) << SXG_ICR_MSGID_SHIFT) & \
+ SXG_ICR_MSGID_MASK) | (_Data))
+
+// The Microcode supports up to 16 RSS queues
+#define SXG_MAX_RSS 16
+#define SXG_MAX_RSS_TABLE_SIZE 256 // 256-byte max
+
+#define SXG_RSS_TCP6 0x00000001 // RSS TCP over IPv6
+#define SXG_RSS_TCP4 0x00000002 // RSS TCP over IPv4
+#define SXG_RSS_LEGACY 0x00000004 // Line-base interrupts
+#define SXG_RSS_TABLE_SIZE 0x0000FF00 // Table size mask
+#define SXG_RSS_TABLE_SHIFT 8
+#define SXG_RSS_BASE_CPU 0x00FF0000 // Base CPU (not used)
+#define SXG_RSS_BASE_SHIFT 16
+
+#define SXG_RCV_IP_CSUM_ENABLED 0x00000001 // ExCode 26 (ReceiveChecksum)
+#define SXG_RCV_TCP_CSUM_ENABLED 0x00000002 // ExCode 26 (ReceiveChecksum)
+
+#define SXG_XMT_CPUID_SHIFT 16
+
+#if VPCI
+#define SXG_CHECK_FOR_HANG_TIME 3000
+#else
+#define SXG_CHECK_FOR_HANG_TIME 5
+#endif
+
+/*
+ * TCB registers - This is really the same register memory area as UCODE_REGS
+ * above, but defined differently. Bits 17:06 of the address define the TCB,
+ * which means each TCB area occupies 0x40 (64) bytes, or 16 u32S. What really
+ * is happening is that these registers occupy the "PadEx[15]" areas in the
+ * SXG_UCODE_REGS definition above
+ */
+typedef struct _SXG_TCB_REGS {
+ u32 ExCode; /* Extended codes - see SXG_UCODE_REGS */
+ u32 Xmt; /* Code = 1 - # of Xmt descriptors added to ring */
+ u32 Rcv; /* Code = 2 - # of Rcv descriptors added to ring */
+ u32 Rsvd1; /* Code = 3 - TOE NA */
+ u32 Rsvd2; /* Code = 4 - TOE NA */
+ u32 Rsvd3; /* Code = 5 - TOE NA */
+ u32 Invalid; /* Code = 6 - Reserved for "CardUp" see above */
+ u32 Rsvd4; /* Code = 7 - TOE NA */
+ u32 Rsvd5; /* Code = 8 - TOE NA */
+ u32 Pad[7]; /* Codes 8-15 - Not used. */
+} SXG_TCB_REGS, *PSXG_TCB_REGS;
+
+/***************************************************************************
+ * ISR Format
+ * 31 0
+ * _______________________________________
+ * | | | | | | | | |
+ * |____|____|____|____|____|____|____|____|
+ * ^^^^ ^^^^ ^^^^ ^^^^ \ /
+ * ERR --|||| |||| |||| |||| -----------------
+ * EVENT ---||| |||| |||| |||| |
+ * ----|| |||| |||| |||| |-- Crash Address
+ * UPC -----| |||| |||| ||||
+ * LEVENT -------|||| |||| ||||
+ * PDQF --------||| |||| ||||
+ * RMISS ---------|| |||| ||||
+ * BREAK ----------| |||| ||||
+ * HBEATOK ------------|||| ||||
+ * NOHBEAT -------------||| ||||
+ * ERFULL --------------|| ||||
+ * XDROP ---------------| ||||
+ * -----------------||||
+ * -----------------||||--\
+ * ||---|-CpuId of crash
+ * |----/
+ ***************************************************************************/
+#define SXG_ISR_ERR 0x80000000 // Error
+#define SXG_ISR_EVENT 0x40000000 // Event ring event
+#define SXG_ISR_NONE1 0x20000000 // Not used
+#define SXG_ISR_UPC 0x10000000 // Dump/debug command complete
+#define SXG_ISR_LINK 0x08000000 // Link event
+#define SXG_ISR_PDQF 0x04000000 // Processed data queue full
+#define SXG_ISR_RMISS 0x02000000 // Drop - no host buf
+#define SXG_ISR_BREAK 0x01000000 // Breakpoint hit
+#define SXG_ISR_PING 0x00800000 // Heartbeat response
+#define SXG_ISR_DEAD 0x00400000 // Card crash
+#define SXG_ISR_ERFULL 0x00200000 // Event ring full
+#define SXG_ISR_XDROP 0x00100000 // XMT Drop - no DRAM bufs or XMT err
+#define SXG_ISR_SPSEND 0x00080000 // Slow send complete
+#define SXG_ISR_CPU 0x00070000 // Dead CPU mask
+#define SXG_ISR_CPU_SHIFT 16 // Dead CPU shift
+#define SXG_ISR_CRASH 0x0000FFFF // Crash address mask
+
+/***************************************************************************
+ *
+ * Event Ring entry
+ *
+ ***************************************************************************/
+/*
+ * 31 15 0
+ * .___________________.___________________.
+ * |<------------ Pad 0 ------------>|
+ * |_________|_________|_________|_________|0 0x00
+ * |<------------ Pad 1 ------------>|
+ * |_________|_________|_________|_________|4 0x04
+ * |<------------ Pad 2 ------------>|
+ * |_________|_________|_________|_________|8 0x08
+ * |<----------- Event Word 0 ------------>|
+ * |_________|_________|_________|_________|12 0x0c
+ * |<----------- Event Word 1 ------------>|
+ * |_________|_________|_________|_________|16 0x10
+ * |<------------- Toeplitz ------------>|
+ * |_________|_________|_________|_________|20 0x14
+ * |<----- Length ---->|<------ TCB Id --->|
+ * |_________|_________|_________|_________|24 0x18
+ * |<----- Status ---->|Evnt Code|Flsh Code|
+ * |_________|_________|_________|_________|28 0x1c
+ * ^ ^^^^ ^^^^
+ * |- VALID |||| ||||- RBUFC
+ * |||| |||-- SLOWR
+ * |||| ||--- UNUSED
+ * |||| |---- FASTC
+ * ||||------ FASTR
+ * |||-------
+ * ||--------
+ * |---------
+ *
+ * Slowpath status:
+ * _______________________________________
+ * |<----- Status ---->|Evnt Code|Flsh Code|
+ * |_________|Cmd Index|_________|_________|28 0x1c
+ * ^^^ ^^^^
+ * ||| ||||- ISTCPIP6
+ * ||| |||-- IPONLY
+ * ||| ||--- RCVERR
+ * ||| |---- IPCBAD
+ * |||------ TCPCBAD
+ * ||------- ISTCPIP
+ * |-------- SCERR
+ *
+ */
+#pragma pack(push, 1)
+typedef struct _SXG_EVENT {
+ u32 Pad[1]; // not used
+ u32 SndUna; // SndUna value
+ u32 Resid; // receive MDL resid
+ union {
+ void * HostHandle; // Receive host handle
+ u32 Rsvd1; // TOE NA
+ struct {
+ u32 NotUsed;
+ u32 Rsvd2; // TOE NA
+ } Flush;
+ };
+ u32 Toeplitz; // RSS Toeplitz hash
+ union {
+ ushort Rsvd3; // TOE NA
+ ushort HdrOffset; // Slowpath
+ };
+ ushort Length; //
+ unsigned char Rsvd4; // TOE NA
+ unsigned char Code; // Event code
+ unsigned char CommandIndex; // New ring index
+ unsigned char Status; // Event status
+} SXG_EVENT, *PSXG_EVENT;
+#pragma pack(pop)
+
+// Event code definitions
+#define EVENT_CODE_BUFFERS 0x01 // Receive buffer list command (ring 0)
+#define EVENT_CODE_SLOWRCV 0x02 // Slowpath receive
+#define EVENT_CODE_UNUSED 0x04 // Was slowpath commands complete
+
+// Status values
+#define EVENT_STATUS_VALID 0x80 // Entry valid
+
+// Slowpath status
+#define EVENT_STATUS_ERROR 0x40 // Completed with error. Index in next byte
+#define EVENT_STATUS_TCPIP4 0x20 // TCPIPv4 frame
+#define EVENT_STATUS_TCPBAD 0x10 // Bad TCP checksum
+#define EVENT_STATUS_IPBAD 0x08 // Bad IP checksum
+#define EVENT_STATUS_RCVERR 0x04 // Slowpath receive error
+#define EVENT_STATUS_IPONLY 0x02 // IP frame
+#define EVENT_STATUS_TCPIP6 0x01 // TCPIPv6 frame
+#define EVENT_STATUS_TCPIP 0x21 // Combination of v4 and v6
+
+// Event ring
+// Size must be power of 2, between 128 and 16k
+#define EVENT_RING_SIZE 4096 // ??
+#define EVENT_RING_BATCH 16 // Hand entries back 16 at a time.
+#define EVENT_BATCH_LIMIT 256 // Stop processing events after 256 (16 * 16)
+
+typedef struct _SXG_EVENT_RING {
+ SXG_EVENT Ring[EVENT_RING_SIZE];
+}SXG_EVENT_RING, *PSXG_EVENT_RING;
+
+/***************************************************************************
+ *
+ * TCB Buffers
+ *
+ ***************************************************************************/
+// Maximum number of TCBS supported by hardware/microcode
+#define SXG_MAX_TCB 4096
+// Minimum TCBs before we fail initialization
+#define SXG_MIN_TCB 512
+// TCB Hash
+// The bucket is determined by bits 11:4 of the toeplitz if we support 4k
+// offloaded connections, 10:4 if we support 2k and so on.
+#define SXG_TCB_BUCKET_SHIFT 4
+#define SXG_TCB_PER_BUCKET 16
+#define SXG_TCB_BUCKET_MASK 0xFF0 // Bucket portion of TCB ID
+#define SXG_TCB_ELEMENT_MASK 0x00F // Element within bucket
+#define SXG_TCB_BUCKETS 256 // 256 * 16 = 4k
+
+#define SXG_TCB_BUFFER_SIZE 512 // ASSERT format is correct
+
+#define SXG_TCB_RCVQ_SIZE 736
+
+#define SXG_TCB_COMPOSITE_BUFFER_SIZE 1024
+
+#define SXG_LOCATE_TCP_FRAME_HDR(_TcpObject, _IPv6) \
+ (((_TcpObject)->VlanId) ? \
+ ((_IPv6) ? /* Vlan frame header = yes */ \
+ &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.SxgTcp : \
+ &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.SxgTcp) : \
+ ((_IPv6) ? /* Vlan frame header = No */ \
+ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.SxgTcp : \
+ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp.SxgTcp))
+
+#define SXG_LOCATE_IP_FRAME_HDR(_TcpObject) \
+ (_TcpObject)->VlanId ? \
+ &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.Ip : \
+ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp.Ip
+
+#define SXG_LOCATE_IP6_FRAME_HDR(_TcpObject) \
+ (_TcpObject)->VlanId ? \
+ &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.Ip : \
+ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.Ip
+
+
+#if DBG
+// Horrible kludge to distinguish dumb-nic, slowpath, and
+// fastpath traffic. Decrement the HopLimit by one
+// for slowpath, two for fastpath. This assumes the limit is measurably
+// greater than two, which I think is reasonable.
+// Obviously this is DBG only. Maybe remove later, or #if 0 so we
+// can set it when needed
+#define SXG_DBG_HOP_LIMIT(_TcpObject, _FastPath) { \
+ PIPV6_HDR _Ip6FrameHdr; \
+ if((_TcpObject)->IPv6) { \
+ _Ip6FrameHdr = SXG_LOCATE_IP6_FRAME_HDR((_TcpObject)); \
+ if(_FastPath) { \
+ _Ip6FrameHdr->HopLimit = (_TcpObject)->Cached.TtlOrHopLimit - 2; \
+ } else { \
+ _Ip6FrameHdr->HopLimit = (_TcpObject)->Cached.TtlOrHopLimit - 1; \
+ } \
+ } \
+}
+#else
+// Do nothing with free build
+#define SXG_DBG_HOP_LIMIT(_TcpObject, _FastPath)
+#endif
+
+/***************************************************************************
+ * Receive and transmit rings
+ ***************************************************************************/
+#define SXG_MAX_RING_SIZE 256
+#define SXG_XMT_RING_SIZE 128 // Start with 128
+#define SXG_RCV_RING_SIZE 128 // Start with 128
+#define SXG_MAX_ENTRIES 4096
+
+// Structure and macros to manage a ring
+typedef struct _SXG_RING_INFO {
+ unsigned char Head; // Where we add entries - Note unsigned char:RING_SIZE
+ unsigned char Tail; // Where we pull off completed entries
+ ushort Size; // Ring size - Must be multiple of 2
+ void * Context[SXG_MAX_RING_SIZE]; // Shadow ring
+} SXG_RING_INFO, *PSXG_RING_INFO;
+
+#define SXG_INITIALIZE_RING(_ring, _size) { \
+ (_ring).Head = 0; \
+ (_ring).Tail = 0; \
+ (_ring).Size = (_size); \
+}
+#define SXG_ADVANCE_INDEX(_index, _size) ((_index) = ((_index) + 1) & ((_size) - 1))
+#define SXG_PREVIOUS_INDEX(_index, _size) (((_index) - 1) &((_size) - 1))
+#define SXG_RING_EMPTY(_ring) ((_ring)->Head == (_ring)->Tail)
+#define SXG_RING_FULL(_ring) ((((_ring)->Head + 1) & ((_ring)->Size - 1)) == (_ring)->Tail)
+#define SXG_RING_ADVANCE_HEAD(_ring) SXG_ADVANCE_INDEX((_ring)->Head, ((_ring)->Size))
+#define SXG_RING_RETREAT_HEAD(_ring) ((_ring)->Head = \
+ SXG_PREVIOUS_INDEX((_ring)->Head, (_ring)->Size))
+#define SXG_RING_ADVANCE_TAIL(_ring) { \
+ ASSERT((_ring)->Tail != (_ring)->Head); \
+ SXG_ADVANCE_INDEX((_ring)->Tail, ((_ring)->Size)); \
+}
+// Set cmd to the next available ring entry, set the shadow context
+// entry and advance the ring.
+// The appropriate lock must be held when calling this macro
+#define SXG_GET_CMD(_ring, _ringinfo, _cmd, _context) { \
+ if(SXG_RING_FULL(_ringinfo)) { \
+ (_cmd) = NULL; \
+ } else { \
+ (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Head]; \
+ (_ringinfo)->Context[(_ringinfo)->Head] = (void *)(_context);\
+ SXG_RING_ADVANCE_HEAD(_ringinfo); \
+ } \
+}
+
+// Abort the previously allocated command by retreating the head.
+// NOTE - The appopriate lock MUST NOT BE DROPPED between the SXG_GET_CMD
+// and SXG_ABORT_CMD calls.
+#define SXG_ABORT_CMD(_ringinfo) { \
+ ASSERT(!(SXG_RING_EMPTY(_ringinfo))); \
+ SXG_RING_RETREAT_HEAD(_ringinfo); \
+ (_ringinfo)->Context[(_ringinfo)->Head] = NULL; \
+}
+
+// For the given ring, return a pointer to the tail cmd and context,
+// clear the context and advance the tail
+#define SXG_RETURN_CMD(_ring, _ringinfo, _cmd, _context) { \
+ (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Tail]; \
+ (_context) = (_ringinfo)->Context[(_ringinfo)->Tail]; \
+ (_ringinfo)->Context[(_ringinfo)->Tail] = NULL; \
+ SXG_RING_ADVANCE_TAIL(_ringinfo); \
+}
+
+/***************************************************************************
+ *
+ * Host Command Buffer - commands to INIC via the Cmd Rings
+ *
+ ***************************************************************************/
+/*
+ * 31 15 0
+ * .___________________.___________________.
+ * |<-------------- Sgl Low -------------->|
+ * |_________|_________|_________|_________|0 0x00
+ * |<-------------- Sgl High ------------->|
+ * |_________|_________|_________|_________|4 0x04
+ * |<------------- Sge 0 Low ----------->|
+ * |_________|_________|_________|_________|8 0x08
+ * |<------------- Sge 0 High ----------->|
+ * |_________|_________|_________|_________|12 0x0c
+ * |<------------ Sge 0 Length ---------->|
+ * |_________|_________|_________|_________|16 0x10
+ * |<----------- Window Update ----------->|
+ * |<-------- SP 1st SGE offset ---------->|
+ * |_________|_________|_________|_________|20 0x14
+ * |<----------- Total Length ------------>|
+ * |_________|_________|_________|_________|24 0x18
+ * |<----- LCnt ------>|<----- Flags ----->|
+ * |_________|_________|_________|_________|28 0x1c
+ */
+#pragma pack(push, 1)
+typedef struct _SXG_CMD {
+ dma_addr_t Sgl; // Physical address of SGL
+ union {
+ struct {
+ dma64_addr_t FirstSgeAddress;// Address of first SGE
+ u32 FirstSgeLength; // Length of first SGE
+ union {
+ u32 Rsvd1; // TOE NA
+ u32 SgeOffset; // Slowpath - 2nd SGE offset
+ u32 Resid; // MDL completion - clobbers update
+ };
+ union {
+ u32 TotalLength; // Total transfer length
+ u32 Mss; // LSO MSS
+ };
+ } Buffer;
+ };
+ union {
+ struct {
+ unsigned char Flags:4; // slowpath flags
+ unsigned char IpHl:4; // Ip header length (>>2)
+ unsigned char MacLen; // Mac header len
+ } CsumFlags;
+ struct {
+ ushort Flags:4; // slowpath flags
+ ushort TcpHdrOff:7; // TCP
+ ushort MacLen:5; // Mac header len
+ } LsoFlags;
+ ushort Flags; // flags
+ };
+ union {
+ ushort SgEntries; // SG entry count including first sge
+ struct {
+ unsigned char Status; // Copied from event status
+ unsigned char NotUsed;
+ } Status;
+ };
+} SXG_CMD, *PSXG_CMD;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct _VLAN_HDR {
+ ushort VlanTci;
+ ushort VlanTpid;
+} VLAN_HDR, *PVLAN_HDR;
+#pragma pack(pop)
+
+/*
+ * Slowpath Flags:
+ *
+ *
+ * LSS Flags:
+ * .---
+ * /.--- TCP Large segment send
+ * //.---
+ * ///.---
+ * 3 1 1 ////
+ * 1 5 0 ||||
+ * .___________________.____________vvvv.
+ * | |MAC | TCP | |
+ * | LCnt |hlen|hdroff|Flgs|
+ * |___________________|||||||||||||____|
+ *
+ *
+ * Checksum Flags
+ *
+ * .---
+ * /.---
+ * //.--- Checksum TCP
+ * ///.--- Checksum IP
+ * 3 1 //// No bits - normal send
+ * 1 5 7 ||||
+ * .___________________._______________vvvv.
+ * | | Offload | IP | |
+ * | LCnt |MAC hlen |Hlen|Flgs|
+ * |___________________|____|____|____|____|
+ *
+ */
+// Slowpath CMD flags
+#define SXG_SLOWCMD_CSUM_IP 0x01 // Checksum IP
+#define SXG_SLOWCMD_CSUM_TCP 0x02 // Checksum TCP
+#define SXG_SLOWCMD_LSO 0x04 // Large segment send
+
+typedef struct _SXG_XMT_RING {
+ SXG_CMD Descriptors[SXG_XMT_RING_SIZE];
+} SXG_XMT_RING, *PSXG_XMT_RING;
+
+typedef struct _SXG_RCV_RING {
+ SXG_CMD Descriptors[SXG_RCV_RING_SIZE];
+} SXG_RCV_RING, *PSXG_RCV_RING;
+
+/***************************************************************************
+ * Share memory buffer types - Used to identify asynchronous
+ * shared memory allocation
+ ***************************************************************************/
+typedef enum {
+ SXG_BUFFER_TYPE_RCV, // Receive buffer
+ SXG_BUFFER_TYPE_SGL // SGL buffer
+} SXG_BUFFER_TYPE;
+
+// State for SXG buffers
+#define SXG_BUFFER_FREE 0x01
+#define SXG_BUFFER_BUSY 0x02
+#define SXG_BUFFER_ONCARD 0x04
+#define SXG_BUFFER_UPSTREAM 0x08
+
+/***************************************************************************
+ * Receive data buffers
+ *
+ * Receive data buffers are given to the Sahara card 128 at a time.
+ * This is accomplished by filling in a "receive descriptor block"
+ * with 128 "receive descriptors". Each descriptor consists of
+ * a physical address, which the card uses as the address to
+ * DMA data into, and a virtual address, which is given back
+ * to the host in the "HostHandle" portion of an event.
+ * The receive descriptor data structure is defined below
+ * as SXG_RCV_DATA_DESCRIPTOR, and the corresponding block
+ * is defined as SXG_RCV_DESCRIPTOR_BLOCK.
+ *
+ * This receive descriptor block is given to the card by filling
+ * in the Sgl field of a SXG_CMD entry from pAdapt->RcvRings[0]
+ * with the physical address of the receive descriptor block.
+ *
+ * Both the receive buffers and the receive descriptor blocks
+ * require additional data structures to maintain them
+ * on a free queue and contain other information associated with them.
+ * Those data structures are defined as the SXG_RCV_DATA_BUFFER_HDR
+ * and SXG_RCV_DESCRIPTOR_BLOCK_HDR respectively.
+ *
+ * Since both the receive buffers and the receive descriptor block
+ * must be accessible by the card, both must be allocated out of
+ * shared memory. To ensure that we always have a descriptor
+ * block available for every 128 buffers, we allocate all of
+ * these resources together in a single block. This entire
+ * block is managed by a SXG_RCV_BLOCK_HDR, who's sole purpose
+ * is to maintain address information so that the entire block
+ * can be free later.
+ *
+ * Further complicating matters is the fact that the receive
+ * buffers must be variable in length in order to accomodate
+ * jumbo frame configurations. We configure the buffer
+ * length so that the buffer and it's corresponding SXG_RCV_DATA_BUFFER_HDR
+ * structure add up to an even boundary. Then we place the
+ * remaining data structures after 128 of them as shown in
+ * the following diagram:
+ *
+ * _________________________________________
+ * | |
+ * | Variable length receive buffer #1 |
+ * |_________________________________________|
+ * | |
+ * | SXG_RCV_DATA_BUFFER_HDR #1 |
+ * |_________________________________________| <== Even 2k or 10k boundary
+ * | |
+ * | ... repeat 2-128 .. |
+ * |_________________________________________|
+ * | |
+ * | SXG_RCV_DESCRIPTOR_BLOCK |
+ * | Contains SXG_RCV_DATA_DESCRIPTOR * 128 |
+ * |_________________________________________|
+ * | |
+ * | SXG_RCV_DESCRIPTOR_BLOCK_HDR |
+ * |_________________________________________|
+ * | |
+ * | SXG_RCV_BLOCK_HDR |
+ * |_________________________________________|
+ *
+ * Memory consumption:
+ * Non-jumbo:
+ * Buffers and SXG_RCV_DATA_BUFFER_HDR = 2k * 128 = 256k
+ * + SXG_RCV_DESCRIPTOR_BLOCK = 2k
+ * + SXG_RCV_DESCRIPTOR_BLOCK_HDR = ~32
+ * + SXG_RCV_BLOCK_HDR = ~32
+ * => Total = ~258k/block
+ *
+ * Jumbo:
+ * Buffers and SXG_RCV_DATA_BUFFER_HDR = 10k * 128 = 1280k
+ * + SXG_RCV_DESCRIPTOR_BLOCK = 2k
+ * + SXG_RCV_DESCRIPTOR_BLOCK_HDR = ~32
+ * + SXG_RCV_BLOCK_HDR = ~32
+ * => Total = ~1282k/block
+ *
+ ***************************************************************************/
+#define SXG_RCV_DATA_BUFFERS 4096 // Amount to give to the card
+#define SXG_INITIAL_RCV_DATA_BUFFERS 8192 // Initial pool of buffers
+#define SXG_MIN_RCV_DATA_BUFFERS 2048 // Minimum amount and when to get more
+#define SXG_MAX_RCV_BLOCKS 128 // = 16384 receive buffers
+
+// Receive buffer header
+typedef struct _SXG_RCV_DATA_BUFFER_HDR {
+ dma_addr_t PhysicalAddress; // Buffer physical address
+ // Note - DO NOT USE the VirtualAddress field to locate data.
+ // Use the sxg.h:SXG_RECEIVE_DATA_LOCATION macro instead.
+ void *VirtualAddress; // Start of buffer
+ LIST_ENTRY FreeList; // Free queue of buffers
+ struct _SXG_RCV_DATA_BUFFER_HDR *Next; // Fastpath data buffer queue
+ u32 Size; // Buffer size
+ u32 ByteOffset; // See SXG_RESTORE_MDL_OFFSET
+ unsigned char State; // See SXG_BUFFER state above
+ unsigned char Status; // Event status (to log PUSH)
+ struct sk_buff * skb; // Double mapped (nbl and pkt)
+} SXG_RCV_DATA_BUFFER_HDR, *PSXG_RCV_DATA_BUFFER_HDR;
+
+// SxgSlowReceive uses the PACKET (skb) contained
+// in the SXG_RCV_DATA_BUFFER_HDR when indicating dumb-nic data
+#define SxgDumbRcvPacket skb
+
+#define SXG_RCV_DATA_HDR_SIZE 256 // Space for SXG_RCV_DATA_BUFFER_HDR
+#define SXG_RCV_DATA_BUFFER_SIZE 2048 // Non jumbo = 2k including HDR
+#define SXG_RCV_JUMBO_BUFFER_SIZE 10240 // jumbo = 10k including HDR
+
+// Receive data descriptor
+typedef struct _SXG_RCV_DATA_DESCRIPTOR {
+ union {
+ struct sk_buff * VirtualAddress; // Host handle
+ u64 ForceTo8Bytes; // Force x86 to 8-byte boundary
+ };
+ dma_addr_t PhysicalAddress;
+} SXG_RCV_DATA_DESCRIPTOR, *PSXG_RCV_DATA_DESCRIPTOR;
+
+// Receive descriptor block
+#define SXG_RCV_DESCRIPTORS_PER_BLOCK 128
+#define SXG_RCV_DESCRIPTOR_BLOCK_SIZE 2048 // For sanity check
+typedef struct _SXG_RCV_DESCRIPTOR_BLOCK {
+ SXG_RCV_DATA_DESCRIPTOR Descriptors[SXG_RCV_DESCRIPTORS_PER_BLOCK];
+} SXG_RCV_DESCRIPTOR_BLOCK, *PSXG_RCV_DESCRIPTOR_BLOCK;
+
+// Receive descriptor block header
+typedef struct _SXG_RCV_DESCRIPTOR_BLOCK_HDR {
+ void * VirtualAddress; // Start of 2k buffer
+ dma_addr_t PhysicalAddress; // ..and it's physical address
+ LIST_ENTRY FreeList; // Free queue of descriptor blocks
+ unsigned char State; // See SXG_BUFFER state above
+} SXG_RCV_DESCRIPTOR_BLOCK_HDR, *PSXG_RCV_DESCRIPTOR_BLOCK_HDR;
+
+// Receive block header
+typedef struct _SXG_RCV_BLOCK_HDR {
+ void * VirtualAddress; // Start of virtual memory
+ dma_addr_t PhysicalAddress; // ..and it's physical address
+ LIST_ENTRY AllList; // Queue of all SXG_RCV_BLOCKS
+} SXG_RCV_BLOCK_HDR, *PSXG_RCV_BLOCK_HDR;
+
+// Macros to determine data structure offsets into receive block
+#define SXG_RCV_BLOCK_SIZE(_Buffersize) \
+ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \
+ (sizeof(SXG_RCV_DESCRIPTOR_BLOCK)) + \
+ (sizeof(SXG_RCV_DESCRIPTOR_BLOCK_HDR)) + \
+ (sizeof(SXG_RCV_BLOCK_HDR)))
+#define SXG_RCV_BUFFER_DATA_SIZE(_Buffersize) \
+ ((_Buffersize) - SXG_RCV_DATA_HDR_SIZE)
+#define SXG_RCV_DATA_BUFFER_HDR_OFFSET(_Buffersize) \
+ ((_Buffersize) - SXG_RCV_DATA_HDR_SIZE)
+#define SXG_RCV_DESCRIPTOR_BLOCK_OFFSET(_Buffersize) \
+ ((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK)
+#define SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET(_Buffersize) \
+ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \
+ (sizeof(SXG_RCV_DESCRIPTOR_BLOCK)))
+#define SXG_RCV_BLOCK_HDR_OFFSET(_Buffersize) \
+ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \
+ (sizeof(SXG_RCV_DESCRIPTOR_BLOCK)) + \
+ (sizeof(SXG_RCV_DESCRIPTOR_BLOCK_HDR)))
+
+// Use the miniport reserved portion of the NBL to locate
+// our SXG_RCV_DATA_BUFFER_HDR structure.
+typedef struct _SXG_RCV_NBL_RESERVED {
+ PSXG_RCV_DATA_BUFFER_HDR RcvDataBufferHdr;
+ void * Available;
+} SXG_RCV_NBL_RESERVED, *PSXG_RCV_NBL_RESERVED;
+
+#define SXG_RCV_NBL_BUFFER_HDR(_NBL) (((PSXG_RCV_NBL_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(_NBL))->RcvDataBufferHdr)
+
+/***************************************************************************
+ * Scatter gather list buffer
+ ***************************************************************************/
+#define SXG_INITIAL_SGL_BUFFERS 8192 // Initial pool of SGL buffers
+#define SXG_MIN_SGL_BUFFERS 2048 // Minimum amount and when to get more
+#define SXG_MAX_SGL_BUFFERS 16384 // Maximum to allocate (note ADAPT:ushort)
+
+
+// Self identifying structure type
+typedef enum _SXG_SGL_TYPE {
+ SXG_SGL_DUMB, // Dumb NIC SGL
+ SXG_SGL_SLOW, // Slowpath protocol header - see below
+ SXG_SGL_CHIMNEY // Chimney offload SGL
+} SXG_SGL_TYPE, PSXG_SGL_TYPE;
+
+// Note - the description below is Microsoft specific
+//
+// The following definition specifies the amount of shared memory to allocate
+// for the SCATTER_GATHER_LIST portion of the SXG_SCATTER_GATHER data structure.
+// The following considerations apply when setting this value:
+// - First, the Sahara card is designed to read the Microsoft SGL structure
+// straight out of host memory. This means that the SGL must reside in
+// shared memory. If the length here is smaller than the SGL for the
+// NET_BUFFER, then NDIS will allocate its own buffer. The buffer
+// that NDIS allocates is not in shared memory, so when this happens,
+// the SGL will need to be copied to a set of SXG_SCATTER_GATHER buffers.
+// In other words.. we don't want this value to be too small.
+// - On the other hand.. we're allocating up to 16k of these things. If
+// we make this too big, we start to consume a ton of memory..
+// At the moment, I'm going to limit the number of SG entries to 150.
+// If each entry maps roughly 4k, then this should cover roughly 600kB
+// NET_BUFFERs. Furthermore, since each entry is 24 bytes, the total
+// SGE portion of the structure consumes 3600 bytes, which should allow
+// the entire SXG_SCATTER_GATHER structure to reside comfortably within
+// a 4k block, providing the remaining fields stay under 500 bytes.
+//
+// So with 150 entries, the SXG_SCATTER_GATHER structure becomes roughly
+// 4k. At 16k of them, that amounts to 64M of shared memory. A ton, but
+// manageable.
+#define SXG_SGL_ENTRIES 150
+
+// The ucode expects an NDIS SGL structure that
+// is formatted for an x64 system. When running
+// on an x64 system, we can simply hand the NDIS SGL
+// to the card directly. For x86 systems we must reconstruct
+// the SGL. The following structure defines an x64
+// formatted SGL entry
+typedef struct _SXG_X64_SGE {
+ dma64_addr_t Address; // same as wdm.h
+ u32 Length; // same as wdm.h
+ u32 CompilerPad;// The compiler pads to 8-bytes
+ u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
+} SXG_X64_SGE, *PSXG_X64_SGE;
+
+typedef struct _SCATTER_GATHER_ELEMENT {
+ dma64_addr_t Address; // same as wdm.h
+ u32 Length; // same as wdm.h
+ u32 CompilerPad;// The compiler pads to 8-bytes
+ u64 Reserved; // u32 * in wdm.h. Force to 8 bytes
+} SCATTER_GATHER_ELEMENT, *PSCATTER_GATHER_ELEMENT;
+
+
+typedef struct _SCATTER_GATHER_LIST {
+ u32 NumberOfElements;
+ u32 * Reserved;
+ SCATTER_GATHER_ELEMENT Elements[];
+} SCATTER_GATHER_LIST, *PSCATTER_GATHER_LIST;
+
+// The card doesn't care about anything except elements, so
+// we can leave the u32 * reserved field alone in the following
+// SGL structure. But redefine from wdm.h:SCATTER_GATHER_LIST so
+// we can specify SXG_X64_SGE and define a fixed number of elements
+typedef struct _SXG_X64_SGL {
+ u32 NumberOfElements;
+ u32 * Reserved;
+ SXG_X64_SGE Elements[SXG_SGL_ENTRIES];
+} SXG_X64_SGL, *PSXG_X64_SGL;
+
+typedef struct _SXG_SCATTER_GATHER {
+ SXG_SGL_TYPE Type; // FIRST! Dumb-nic or offload
+ void * adapter; // Back pointer to adapter
+ LIST_ENTRY FreeList; // Free SXG_SCATTER_GATHER blocks
+ LIST_ENTRY AllList; // All SXG_SCATTER_GATHER blocks
+ dma_addr_t PhysicalAddress;// physical address
+ unsigned char State; // See SXG_BUFFER state above
+ unsigned char CmdIndex; // Command ring index
+ struct sk_buff * DumbPacket; // Associated Packet
+ u32 Direction; // For asynchronous completions
+ u32 CurOffset; // Current SGL offset
+ u32 SglRef; // SGL reference count
+ VLAN_HDR VlanTag; // VLAN tag to be inserted into SGL
+ PSCATTER_GATHER_LIST pSgl; // SGL Addr. Possibly &Sgl
+ SXG_X64_SGL Sgl; // SGL handed to card
+} SXG_SCATTER_GATHER, *PSXG_SCATTER_GATHER;
+
+#if defined(CONFIG_X86_64)
+#define SXG_SGL_BUFFER(_SxgSgl) (&_SxgSgl->Sgl)
+#define SXG_SGL_BUF_SIZE sizeof(SXG_X64_SGL)
+#elif defined(CONFIG_X86)
+// Force NDIS to give us it's own buffer so we can reformat to our own
+#define SXG_SGL_BUFFER(_SxgSgl) NULL
+#define SXG_SGL_BUF_SIZE 0
+#else
+ Stop Compilation;
+#endif
+
diff --git a/drivers/staging/sxg/sxghw.h b/drivers/staging/sxg/sxghw.h
new file mode 100644
index 00000000000..8f4f6effdd9
--- /dev/null
+++ b/drivers/staging/sxg/sxghw.h
@@ -0,0 +1,734 @@
+/*
+ * Copyright © 1997-2007 Alacritech, Inc. All rights reserved
+ *
+ * $Id: sxghw.h,v 1.2 2008/07/24 17:24:23 chris Exp $
+ *
+ * sxghw.h:
+ *
+ * This file contains structures and definitions for the
+ * Alacritech Sahara hardware
+ */
+
+
+/*******************************************************************************
+ * Configuration space
+ *******************************************************************************/
+// PCI Vendor ID
+#define SXG_VENDOR_ID 0x139A // Alacritech's Vendor ID
+
+// PCI Device ID
+#define SXG_DEVICE_ID 0x0009 // Sahara Device ID
+
+//
+// Subsystem IDs.
+//
+// The subsystem ID value is broken into bit fields as follows:
+// Bits [15:12] - Function
+// Bits [11:8] - OEM and/or operating system.
+// Bits [7:0] - Base SID.
+//
+// SSID field (bit) masks
+#define SSID_BASE_MASK 0x00FF // Base subsystem ID mask
+#define SSID_OEM_MASK 0x0F00 // Subsystem OEM mask
+#define SSID_FUNC_MASK 0xF000 // Subsystem function mask
+
+// Base SSID's
+#define SSID_SAHARA_PROTO 0x0018 // 100022 Sahara prototype (XenPak) board
+#define SSID_SAHARA_FIBER 0x0019 // 100023 Sahara 1-port fiber board
+#define SSID_SAHARA_COPPER 0x001A // 100024 Sahara 1-port copper board
+
+// Useful SSID macros
+#define SSID_BASE(ssid) ((ssid) & SSID_BASE_MASK) // isolate base SSID bits
+#define SSID_OEM(ssid) ((ssid) & SSID_OEM_MASK) // isolate SSID OEM bits
+#define SSID_FUNC(ssid) ((ssid) & SSID_FUNC_MASK) // isolate SSID function bits
+
+/*******************************************************************************
+ * HW Register Space
+ *******************************************************************************/
+#define SXG_HWREG_MEMSIZE 0x4000 // 16k
+
+#pragma pack(push, 1)
+typedef struct _SXG_HW_REGS {
+ u32 Reset; // Write 0xdead to invoke soft reset
+ u32 Pad1; // No register defined at offset 4
+ u32 InterruptMask0; // Deassert legacy interrupt on function 0
+ u32 InterruptMask1; // Deassert legacy interrupt on function 1
+ u32 UcodeDataLow; // Store microcode instruction bits 31-0
+ u32 UcodeDataMiddle; // Store microcode instruction bits 63-32
+ u32 UcodeDataHigh; // Store microcode instruction bits 95-64
+ u32 UcodeAddr; // Store microcode address - See flags below
+ u32 PadTo0x80[24]; // Pad to Xcv configuration registers
+ u32 MacConfig0; // 0x80 - AXGMAC Configuration Register 0
+ u32 MacConfig1; // 0x84 - AXGMAC Configuration Register 1
+ u32 MacConfig2; // 0x88 - AXGMAC Configuration Register 2
+ u32 MacConfig3; // 0x8C - AXGMAC Configuration Register 3
+ u32 MacAddressLow; // 0x90 - AXGMAC MAC Station Address - octets 1-4
+ u32 MacAddressHigh; // 0x94 - AXGMAC MAC Station Address - octets 5-6
+ u32 MacReserved1[2]; // 0x98 - AXGMAC Reserved
+ u32 MacMaxFrameLen; // 0xA0 - AXGMAC Maximum Frame Length
+ u32 MacReserved2[2]; // 0xA4 - AXGMAC Reserved
+ u32 MacRevision; // 0xAC - AXGMAC Revision Level Register
+ u32 MacReserved3[4]; // 0xB0 - AXGMAC Reserved
+ u32 MacAmiimCmd; // 0xC0 - AXGMAC AMIIM Command Register
+ u32 MacAmiimField; // 0xC4 - AXGMAC AMIIM Field Register
+ u32 MacAmiimConfig; // 0xC8 - AXGMAC AMIIM Configuration Register
+ u32 MacAmiimLink; // 0xCC - AXGMAC AMIIM Link Fail Vector Register
+ u32 MacAmiimIndicator; // 0xD0 - AXGMAC AMIIM Indicator Registor
+ u32 PadTo0x100[11]; // 0xD4 - 0x100 - Pad
+ u32 XmtConfig; // 0x100 - Transmit Configuration Register
+ u32 RcvConfig; // 0x104 - Receive Configuration Register 1
+ u32 LinkAddress0Low; // 0x108 - Link address 0
+ u32 LinkAddress0High; // 0x10C - Link address 0
+ u32 LinkAddress1Low; // 0x110 - Link address 1
+ u32 LinkAddress1High; // 0x114 - Link address 1
+ u32 LinkAddress2Low; // 0x118 - Link address 2
+ u32 LinkAddress2High; // 0x11C - Link address 2
+ u32 LinkAddress3Low; // 0x120 - Link address 3
+ u32 LinkAddress3High; // 0x124 - Link address 3
+ u32 ToeplitzKey[10]; // 0x128 - 0x150 - Toeplitz key
+ u32 SocketKey[10]; // 0x150 - 0x178 - Socket Key
+ u32 LinkStatus; // 0x178 - Link status
+ u32 ClearStats; // 0x17C - Clear Stats
+ u32 XmtErrorsLow; // 0x180 - Transmit stats - errors
+ u32 XmtErrorsHigh; // 0x184 - Transmit stats - errors
+ u32 XmtFramesLow; // 0x188 - Transmit stats - frame count
+ u32 XmtFramesHigh; // 0x18C - Transmit stats - frame count
+ u32 XmtBytesLow; // 0x190 - Transmit stats - byte count
+ u32 XmtBytesHigh; // 0x194 - Transmit stats - byte count
+ u32 XmtTcpSegmentsLow; // 0x198 - Transmit stats - TCP segments
+ u32 XmtTcpSegmentsHigh; // 0x19C - Transmit stats - TCP segments
+ u32 XmtTcpBytesLow; // 0x1A0 - Transmit stats - TCP bytes
+ u32 XmtTcpBytesHigh; // 0x1A4 - Transmit stats - TCP bytes
+ u32 RcvErrorsLow; // 0x1A8 - Receive stats - errors
+ u32 RcvErrorsHigh; // 0x1AC - Receive stats - errors
+ u32 RcvFramesLow; // 0x1B0 - Receive stats - frame count
+ u32 RcvFramesHigh; // 0x1B4 - Receive stats - frame count
+ u32 RcvBytesLow; // 0x1B8 - Receive stats - byte count
+ u32 RcvBytesHigh; // 0x1BC - Receive stats - byte count
+ u32 RcvTcpSegmentsLow; // 0x1C0 - Receive stats - TCP segments
+ u32 RcvTcpSegmentsHigh; // 0x1C4 - Receive stats - TCP segments
+ u32 RcvTcpBytesLow; // 0x1C8 - Receive stats - TCP bytes
+ u32 RcvTcpBytesHigh; // 0x1CC - Receive stats - TCP bytes
+ u32 PadTo0x200[12]; // 0x1D0 - 0x200 - Pad
+ u32 Software[1920]; // 0x200 - 0x2000 - Software defined (not used)
+ u32 MsixTable[1024]; // 0x2000 - 0x3000 - MSIX Table
+ u32 MsixBitArray[1024]; // 0x3000 - 0x4000 - MSIX Pending Bit Array
+} SXG_HW_REGS, *PSXG_HW_REGS;
+#pragma pack(pop)
+
+// Microcode Address Flags
+#define MICROCODE_ADDRESS_GO 0x80000000 // Start microcode
+#define MICROCODE_ADDRESS_WRITE 0x40000000 // Store microcode
+#define MICROCODE_ADDRESS_READ 0x20000000 // Read microcode
+#define MICROCODE_ADDRESS_PARITY 0x10000000 // Parity error detected
+#define MICROCODE_ADDRESS_MASK 0x00001FFF // Address bits
+
+// Link Address Registers
+#define LINK_ADDRESS_ENABLE 0x80000000 // Applied to link address high
+
+// Microsoft register space size
+#define SXG_UCODEREG_MEMSIZE 0x40000 // 256k
+
+// Sahara microcode register address format. The command code,
+// extended command code, and associated processor are encoded in
+// the address bits as follows
+#define SXG_ADDRESS_CODE_SHIFT 2 // Base command code
+#define SXG_ADDRESS_CODE_MASK 0x0000003C
+#define SXG_ADDRESS_EXCODE_SHIFT 6 // Extended (or sub) command code
+#define SXG_ADDRESS_EXCODE_MASK 0x00001FC0
+#define SXG_ADDRESS_CPUID_SHIFT 13 // CPU
+#define SXG_ADDRESS_CPUID_MASK 0x0003E000
+#define SXG_REGISTER_SIZE_PER_CPU 0x00002000 // Used to sanity check UCODE_REGS structure
+
+// Sahara receive sequencer status values
+#define SXG_RCV_STATUS_ATTN 0x80000000 // Attention
+#define SXG_RCV_STATUS_TRANSPORT_MASK 0x3F000000 // Transport mask
+#define SXG_RCV_STATUS_TRANSPORT_ERROR 0x20000000 // Transport error
+#define SXG_RCV_STATUS_TRANSPORT_CSUM 0x23000000 // Transport cksum error
+#define SXG_RCV_STATUS_TRANSPORT_UFLOW 0x22000000 // Transport underflow
+#define SXG_RCV_STATUS_TRANSPORT_HDRLEN 0x20000000 // Transport header length
+#define SXG_RCV_STATUS_TRANSPORT_FLAGS 0x10000000 // Transport flags detected
+#define SXG_RCV_STATUS_TRANSPORT_OPTS 0x08000000 // Transport options detected
+#define SXG_RCV_STATUS_TRANSPORT_SESS_MASK 0x07000000 // Transport DDP
+#define SXG_RCV_STATUS_TRANSPORT_DDP 0x06000000 // Transport DDP
+#define SXG_RCV_STATUS_TRANSPORT_iSCSI 0x05000000 // Transport iSCSI
+#define SXG_RCV_STATUS_TRANSPORT_NFS 0x04000000 // Transport NFS
+#define SXG_RCV_STATUS_TRANSPORT_FTP 0x03000000 // Transport FTP
+#define SXG_RCV_STATUS_TRANSPORT_HTTP 0x02000000 // Transport HTTP
+#define SXG_RCV_STATUS_TRANSPORT_SMB 0x01000000 // Transport SMB
+#define SXG_RCV_STATUS_NETWORK_MASK 0x00FF0000 // Network mask
+#define SXG_RCV_STATUS_NETWORK_ERROR 0x00800000 // Network error
+#define SXG_RCV_STATUS_NETWORK_CSUM 0x00830000 // Network cksum error
+#define SXG_RCV_STATUS_NETWORK_UFLOW 0x00820000 // Network underflow error
+#define SXG_RCV_STATUS_NETWORK_HDRLEN 0x00800000 // Network header length
+#define SXG_RCV_STATUS_NETWORK_OFLOW 0x00400000 // Network overflow detected
+#define SXG_RCV_STATUS_NETWORK_MCAST 0x00200000 // Network multicast detected
+#define SXG_RCV_STATUS_NETWORK_OPTIONS 0x00100000 // Network options detected
+#define SXG_RCV_STATUS_NETWORK_OFFSET 0x00080000 // Network offset detected
+#define SXG_RCV_STATUS_NETWORK_FRAGMENT 0x00040000 // Network fragment detected
+#define SXG_RCV_STATUS_NETWORK_TRANS_MASK 0x00030000 // Network transport type mask
+#define SXG_RCV_STATUS_NETWORK_UDP 0x00020000 // UDP
+#define SXG_RCV_STATUS_NETWORK_TCP 0x00010000 // TCP
+#define SXG_RCV_STATUS_IPONLY 0x00008000 // IP-only not TCP
+#define SXG_RCV_STATUS_PKT_PRI 0x00006000 // Receive priority
+#define SXG_RCV_STATUS_PKT_PRI_SHFT 13 // Receive priority shift
+#define SXG_RCV_STATUS_PARITY 0x00001000 // MAC Receive RAM parity error
+#define SXG_RCV_STATUS_ADDRESS_MASK 0x00000F00 // Link address detection mask
+#define SXG_RCV_STATUS_ADDRESS_D 0x00000B00 // Link address D
+#define SXG_RCV_STATUS_ADDRESS_C 0x00000A00 // Link address C
+#define SXG_RCV_STATUS_ADDRESS_B 0x00000900 // Link address B
+#define SXG_RCV_STATUS_ADDRESS_A 0x00000800 // Link address A
+#define SXG_RCV_STATUS_ADDRESS_BCAST 0x00000300 // Link address broadcast
+#define SXG_RCV_STATUS_ADDRESS_MCAST 0x00000200 // Link address multicast
+#define SXG_RCV_STATUS_ADDRESS_CMCAST 0x00000100 // Link control multicast
+#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
+#define SXG_RCV_STATUS_LINK_ERROR 0x00000080 // Link error
+#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask
+#define SXG_RCV_STATUS_LINK_PARITY 0x00000087 // RcvMacQ parity error
+#define SXG_RCV_STATUS_LINK_EARLY 0x00000086 // Data early
+#define SXG_RCV_STATUS_LINK_BUFOFLOW 0x00000085 // Buffer overflow
+#define SXG_RCV_STATUS_LINK_CODE 0x00000084 // Link code error
+#define SXG_RCV_STATUS_LINK_DRIBBLE 0x00000083 // Dribble nibble
+#define SXG_RCV_STATUS_LINK_CRC 0x00000082 // CRC error
+#define SXG_RCV_STATUS_LINK_OFLOW 0x00000081 // Link overflow
+#define SXG_RCV_STATUS_LINK_UFLOW 0x00000080 // Link underflow
+#define SXG_RCV_STATUS_LINK_8023 0x00000020 // 802.3
+#define SXG_RCV_STATUS_LINK_SNAP 0x00000010 // Snap
+#define SXG_RCV_STATUS_LINK_VLAN 0x00000008 // VLAN
+#define SXG_RCV_STATUS_LINK_TYPE_MASK 0x00000007 // Network type mask
+#define SXG_RCV_STATUS_LINK_CONTROL 0x00000003 // Control packet
+#define SXG_RCV_STATUS_LINK_IPV6 0x00000002 // IPv6 packet
+#define SXG_RCV_STATUS_LINK_IPV4 0x00000001 // IPv4 packet
+
+/***************************************************************************
+ * Sahara receive and transmit configuration registers
+ ***************************************************************************/
+#define RCV_CONFIG_RESET 0x80000000 // RcvConfig register reset
+#define RCV_CONFIG_ENABLE 0x40000000 // Enable the receive logic
+#define RCV_CONFIG_ENPARSE 0x20000000 // Enable the receive parser
+#define RCV_CONFIG_SOCKET 0x10000000 // Enable the socket detector
+#define RCV_CONFIG_RCVBAD 0x08000000 // Receive all bad frames
+#define RCV_CONFIG_CONTROL 0x04000000 // Receive all control frames
+#define RCV_CONFIG_RCVPAUSE 0x02000000 // Enable pause transmit when attn
+#define RCV_CONFIG_TZIPV6 0x01000000 // Include TCP port w/ IPv6 toeplitz
+#define RCV_CONFIG_TZIPV4 0x00800000 // Include TCP port w/ IPv4 toeplitz
+#define RCV_CONFIG_FLUSH 0x00400000 // Flush buffers
+#define RCV_CONFIG_PRIORITY_MASK 0x00300000 // Priority level
+#define RCV_CONFIG_HASH_MASK 0x00030000 // Hash depth
+#define RCV_CONFIG_HASH_8 0x00000000 // Hash depth 8
+#define RCV_CONFIG_HASH_16 0x00010000 // Hash depth 16
+#define RCV_CONFIG_HASH_4 0x00020000 // Hash depth 4
+#define RCV_CONFIG_HASH_2 0x00030000 // Hash depth 2
+#define RCV_CONFIG_BUFLEN_MASK 0x0000FFF0 // Buffer length bits 15:4. ie multiple of 16.
+#define RCV_CONFIG_SKT_DIS 0x00000008 // Disable socket detection on attn
+// Macro to determine RCV_CONFIG_BUFLEN based on maximum frame size.
+// We add 18 bytes for Sahara receive status and padding, plus 4 bytes for CRC,
+// and round up to nearest 16 byte boundary
+#define RCV_CONFIG_BUFSIZE(_MaxFrame) ((((_MaxFrame) + 22) + 15) & RCV_CONFIG_BUFLEN_MASK)
+
+#define XMT_CONFIG_RESET 0x80000000 // XmtConfig register reset
+#define XMT_CONFIG_ENABLE 0x40000000 // Enable transmit logic
+#define XMT_CONFIG_MAC_PARITY 0x20000000 // Inhibit MAC RAM parity error
+#define XMT_CONFIG_BUF_PARITY 0x10000000 // Inhibit D2F buffer parity error
+#define XMT_CONFIG_MEM_PARITY 0x08000000 // Inhibit 1T SRAM parity error
+#define XMT_CONFIG_INVERT_PARITY 0x04000000 // Invert MAC RAM parity
+#define XMT_CONFIG_INITIAL_IPID 0x0000FFFF // Initial IPID
+
+/***************************************************************************
+ * A-XGMAC Registers - Occupy 0x80 - 0xD4 of the SXG_HW_REGS
+ *
+ * Full register descriptions can be found in axgmac.pdf
+ ***************************************************************************/
+// A-XGMAC Configuration Register 0
+#define AXGMAC_CFG0_SUB_RESET 0x80000000 // Sub module reset
+#define AXGMAC_CFG0_RCNTRL_RESET 0x00400000 // Receive control reset
+#define AXGMAC_CFG0_RFUNC_RESET 0x00200000 // Receive function reset
+#define AXGMAC_CFG0_TCNTRL_RESET 0x00040000 // Transmit control reset
+#define AXGMAC_CFG0_TFUNC_RESET 0x00020000 // Transmit function reset
+#define AXGMAC_CFG0_MII_RESET 0x00010000 // MII Management reset
+
+// A-XGMAC Configuration Register 1
+#define AXGMAC_CFG1_XMT_PAUSE 0x80000000 // Allow the sending of Pause frames
+#define AXGMAC_CFG1_XMT_EN 0x40000000 // Enable transmit
+#define AXGMAC_CFG1_RCV_PAUSE 0x20000000 // Allow the detection of Pause frames
+#define AXGMAC_CFG1_RCV_EN 0x10000000 // Enable receive
+#define AXGMAC_CFG1_XMT_STATE 0x04000000 // Current transmit state - READ ONLY
+#define AXGMAC_CFG1_RCV_STATE 0x01000000 // Current receive state - READ ONLY
+#define AXGMAC_CFG1_XOFF_SHORT 0x00001000 // Only pause for 64 slot on XOFF
+#define AXGMAC_CFG1_XMG_FCS1 0x00000400 // Delay transmit FCS 1 4-byte word
+#define AXGMAC_CFG1_XMG_FCS2 0x00000800 // Delay transmit FCS 2 4-byte words
+#define AXGMAC_CFG1_XMG_FCS3 0x00000C00 // Delay transmit FCS 3 4-byte words
+#define AXGMAC_CFG1_RCV_FCS1 0x00000100 // Delay receive FCS 1 4-byte word
+#define AXGMAC_CFG1_RCV_FCS2 0x00000200 // Delay receive FCS 2 4-byte words
+#define AXGMAC_CFG1_RCV_FCS3 0x00000300 // Delay receive FCS 3 4-byte words
+#define AXGMAC_CFG1_PKT_OVERRIDE 0x00000080 // Per-packet override enable
+#define AXGMAC_CFG1_SWAP 0x00000040 // Byte swap enable
+#define AXGMAC_CFG1_SHORT_ASSERT 0x00000020 // ASSERT srdrpfrm on short frame (<64)
+#define AXGMAC_CFG1_RCV_STRICT 0x00000010 // RCV only 802.3AE when CLEAR
+#define AXGMAC_CFG1_CHECK_LEN 0x00000008 // Verify frame length
+#define AXGMAC_CFG1_GEN_FCS 0x00000004 // Generate FCS
+#define AXGMAC_CFG1_PAD_MASK 0x00000003 // Mask for pad bits
+#define AXGMAC_CFG1_PAD_64 0x00000001 // Pad frames to 64 bytes
+#define AXGMAC_CFG1_PAD_VLAN 0x00000002 // Detect VLAN and pad to 68 bytes
+#define AXGMAC_CFG1_PAD_68 0x00000003 // Pad to 68 bytes
+
+// A-XGMAC Configuration Register 2
+#define AXGMAC_CFG2_GEN_PAUSE 0x80000000 // Generate single pause frame (test)
+#define AXGMAC_CFG2_LF_MANUAL 0x08000000 // Manual link fault sequence
+#define AXGMAC_CFG2_LF_AUTO 0x04000000 // Auto link fault sequence
+#define AXGMAC_CFG2_LF_REMOTE 0x02000000 // Remote link fault (READ ONLY)
+#define AXGMAC_CFG2_LF_LOCAL 0x01000000 // Local link fault (READ ONLY)
+#define AXGMAC_CFG2_IPG_MASK 0x001F0000 // Inter packet gap
+#define AXGMAC_CFG2_IPG_SHIFT 16
+#define AXGMAC_CFG2_PAUSE_XMT 0x00008000 // Pause transmit module
+#define AXGMAC_CFG2_IPG_EXTEN 0x00000020 // Enable IPG extension algorithm
+#define AXGMAC_CFG2_IPGEX_MASK 0x0000001F // IPG extension
+
+// A-XGMAC Configuration Register 3
+#define AXGMAC_CFG3_RCV_DROP 0xFFFF0000 // Receive frame drop filter
+#define AXGMAC_CFG3_RCV_DONT_CARE 0x0000FFFF // Receive frame don't care filter
+
+// A-XGMAC Station Address Register - Octets 1-4
+#define AXGMAC_SARLOW_OCTET_ONE 0xFF000000 // First octet
+#define AXGMAC_SARLOW_OCTET_TWO 0x00FF0000 // Second octet
+#define AXGMAC_SARLOW_OCTET_THREE 0x0000FF00 // Third octet
+#define AXGMAC_SARLOW_OCTET_FOUR 0x000000FF // Fourth octet
+
+// A-XGMAC Station Address Register - Octets 5-6
+#define AXGMAC_SARHIGH_OCTET_FIVE 0xFF000000 // Fifth octet
+#define AXGMAC_SARHIGH_OCTET_SIX 0x00FF0000 // Sixth octet
+
+// A-XGMAC Maximum frame length register
+#define AXGMAC_MAXFRAME_XMT 0x3FFF0000 // Maximum transmit frame length
+#define AXGMAC_MAXFRAME_XMT_SHIFT 16
+#define AXGMAC_MAXFRAME_RCV 0x0000FFFF // Maximum receive frame length
+// This register doesn't need to be written for standard MTU.
+// For jumbo, I'll just statically define the value here. This
+// value sets the receive byte count to 9036 (0x234C) and the
+// transmit WORD count to 2259 (0x8D3). These values include 22
+// bytes of padding beyond the jumbo MTU of 9014
+#define AXGMAC_MAXFRAME_JUMBO 0x08D3234C
+
+// A-XGMAC Revision level
+#define AXGMAC_REVISION_MASK 0x0000FFFF // Revision level
+
+// A-XGMAC AMIIM Command Register
+#define AXGMAC_AMIIM_CMD_START 0x00000008 // Command start
+#define AXGMAC_AMIIM_CMD_MASK 0x00000007 // Command
+#define AXGMAC_AMIIM_CMD_LEGACY_WRITE 1 // 10/100/1000 Mbps Phy Write
+#define AXGMAC_AMIIM_CMD_LEGACY_READ 2 // 10/100/1000 Mbps Phy Read
+#define AXGMAC_AMIIM_CMD_MONITOR_SINGLE 3 // Monitor single PHY
+#define AXGMAC_AMIIM_CMD_MONITOR_MULTIPLE 4 // Monitor multiple contiguous PHYs
+#define AXGMAC_AMIIM_CMD_10G_OPERATION 5 // Present AMIIM Field Reg
+#define AXGMAC_AMIIM_CMD_CLEAR_LINK_FAIL 6 // Clear Link Fail Bit in MIIM
+
+// A-XGMAC AMIIM Field Register
+#define AXGMAC_AMIIM_FIELD_ST 0xC0000000 // 2-bit ST field
+#define AXGMAC_AMIIM_FIELD_ST_SHIFT 30
+#define AXGMAC_AMIIM_FIELD_OP 0x30000000 // 2-bit OP field
+#define AXGMAC_AMIIM_FIELD_OP_SHIFT 28
+#define AXGMAC_AMIIM_FIELD_PORT_ADDR 0x0F800000 // Port address field (hstphyadx in spec)
+#define AXGMAC_AMIIM_FIELD_PORT_SHIFT 23
+#define AXGMAC_AMIIM_FIELD_DEV_ADDR 0x007C0000 // Device address field (hstregadx in spec)
+#define AXGMAC_AMIIM_FIELD_DEV_SHIFT 18
+#define AXGMAC_AMIIM_FIELD_TA 0x00030000 // 2-bit TA field
+#define AXGMAC_AMIIM_FIELD_TA_SHIFT 16
+#define AXGMAC_AMIIM_FIELD_DATA 0x0000FFFF // Data field
+
+// Values for the AXGMAC_AMIIM_FIELD_OP field in the A-XGMAC AMIIM Field Register
+#define MIIM_OP_ADDR 0 // MIIM Address set operation
+#define MIIM_OP_WRITE 1 // MIIM Write register operation
+#define MIIM_OP_READ 2 // MIIM Read register operation
+#define MIIM_OP_ADDR_SHIFT (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT)
+
+// Values for the AXGMAC_AMIIM_FIELD_PORT_ADDR field in the A-XGMAC AMIIM Field Register
+#define MIIM_PORT_NUM 1 // All Sahara MIIM modules use port 1
+
+// Values for the AXGMAC_AMIIM_FIELD_DEV_ADDR field in the A-XGMAC AMIIM Field Register
+#define MIIM_DEV_PHY_PMA 1 // PHY PMA/PMD module MIIM device number
+#define MIIM_DEV_PHY_PCS 3 // PHY PCS module MIIM device number
+#define MIIM_DEV_PHY_XS 4 // PHY XS module MIIM device number
+#define MIIM_DEV_XGXS 5 // XGXS MIIM device number
+
+// Values for the AXGMAC_AMIIM_FIELD_TA field in the A-XGMAC AMIIM Field Register
+#define MIIM_TA_10GB 2 // set to 2 for 10 GB operation
+
+// A-XGMAC AMIIM Configuration Register
+#define AXGMAC_AMIIM_CFG_NOPREAM 0x00000080 // Bypass preamble of mngmt frame
+#define AXGMAC_AMIIM_CFG_HALF_CLOCK 0x0000007F // half-clock duration of MDC output
+
+// A-XGMAC AMIIM Indicator Register
+#define AXGMAC_AMIIM_INDC_LINK 0x00000010 // Link status from legacy PHY or MMD
+#define AXGMAC_AMIIM_INDC_MPHY 0x00000008 // Multiple phy operation in progress
+#define AXGMAC_AMIIM_INDC_SPHY 0x00000004 // Single phy operation in progress
+#define AXGMAC_AMIIM_INDC_MON 0x00000002 // Single or multiple monitor cmd
+#define AXGMAC_AMIIM_INDC_BUSY 0x00000001 // Set until cmd operation complete
+
+// Link Status and Control Register
+#define LS_PHY_CLR_RESET 0x80000000 // Clear reset signal to PHY
+#define LS_SERDES_POWER_DOWN 0x40000000 // Power down the Sahara Serdes
+#define LS_XGXS_ENABLE 0x20000000 // Enable the XAUI XGXS logic
+#define LS_XGXS_CTL 0x10000000 // Hold XAUI XGXS logic reset until Serdes is up
+#define LS_SERDES_DOWN 0x08000000 // When 0, XAUI Serdes is up and initialization is complete
+#define LS_TRACE_DOWN 0x04000000 // When 0, Trace Serdes is up and initialization is complete
+#define LS_PHY_CLK_25MHZ 0x02000000 // Set PHY clock to 25 MHz (else 156.125 MHz)
+#define LS_PHY_CLK_EN 0x01000000 // Enable clock to PHY
+#define LS_XAUI_LINK_UP 0x00000010 // XAUI link is up
+#define LS_XAUI_LINK_CHNG 0x00000008 // XAUI link status has changed
+#define LS_LINK_ALARM 0x00000004 // Link alarm pin
+#define LS_ATTN_CTRL_MASK 0x00000003 // Mask link attention control bits
+#define LS_ATTN_ALARM 0x00000000 // 00 => Attn on link alarm
+#define LS_ATTN_ALARM_OR_STAT_CHNG 0x00000001 // 01 => Attn on link alarm or status change
+#define LS_ATTN_STAT_CHNG 0x00000002 // 10 => Attn on link status change
+#define LS_ATTN_NONE 0x00000003 // 11 => no Attn
+
+// Link Address High Registers
+#define LINK_ADDR_ENABLE 0x80000000 // Enable this link address
+
+
+/***************************************************************************
+ * XGXS XAUI XGMII Extender registers
+ *
+ * Full register descriptions can be found in mxgxs.pdf
+ ***************************************************************************/
+// XGXS Register Map
+#define XGXS_ADDRESS_CONTROL1 0x0000 // XS Control 1
+#define XGXS_ADDRESS_STATUS1 0x0001 // XS Status 1
+#define XGXS_ADDRESS_DEVID_LOW 0x0002 // XS Device ID (low)
+#define XGXS_ADDRESS_DEVID_HIGH 0x0003 // XS Device ID (high)
+#define XGXS_ADDRESS_SPEED 0x0004 // XS Speed ability
+#define XGXS_ADDRESS_DEV_LOW 0x0005 // XS Devices in package
+#define XGXS_ADDRESS_DEV_HIGH 0x0006 // XS Devices in package
+#define XGXS_ADDRESS_STATUS2 0x0008 // XS Status 2
+#define XGXS_ADDRESS_PKGID_lOW 0x000E // XS Package Identifier
+#define XGXS_ADDRESS_PKGID_HIGH 0x000F // XS Package Identifier
+#define XGXS_ADDRESS_LANE_STATUS 0x0018 // 10G XGXS Lane Status
+#define XGXS_ADDRESS_TEST_CTRL 0x0019 // 10G XGXS Test Control
+#define XGXS_ADDRESS_RESET_LO1 0x8000 // Vendor-Specific Reset Lo 1
+#define XGXS_ADDRESS_RESET_LO2 0x8001 // Vendor-Specific Reset Lo 2
+#define XGXS_ADDRESS_RESET_HI1 0x8002 // Vendor-Specific Reset Hi 1
+#define XGXS_ADDRESS_RESET_HI2 0x8003 // Vendor-Specific Reset Hi 2
+
+// XS Control 1 register bit definitions
+#define XGXS_CONTROL1_RESET 0x8000 // Reset - self clearing
+#define XGXS_CONTROL1_LOOPBACK 0x4000 // Enable loopback
+#define XGXS_CONTROL1_SPEED1 0x2000 // 0 = unspecified, 1 = 10Gb+
+#define XGXS_CONTROL1_LOWPOWER 0x0400 // 1 = Low power mode
+#define XGXS_CONTROL1_SPEED2 0x0040 // Same as SPEED1 (?)
+#define XGXS_CONTROL1_SPEED 0x003C // Everything reserved except zero (?)
+
+// XS Status 1 register bit definitions
+#define XGXS_STATUS1_FAULT 0x0080 // Fault detected
+#define XGXS_STATUS1_LINK 0x0004 // 1 = Link up
+#define XGXS_STATUS1_LOWPOWER 0x0002 // 1 = Low power supported
+
+// XS Speed register bit definitions
+#define XGXS_SPEED_10G 0x0001 // 1 = 10G capable
+
+// XS Devices register bit definitions
+#define XGXS_DEVICES_DTE 0x0020 // DTE XS Present
+#define XGXS_DEVICES_PHY 0x0010 // PHY XS Present
+#define XGXS_DEVICES_PCS 0x0008 // PCS Present
+#define XGXS_DEVICES_WIS 0x0004 // WIS Present
+#define XGXS_DEVICES_PMD 0x0002 // PMD/PMA Present
+#define XGXS_DEVICES_CLAUSE22 0x0001 // Clause 22 registers present
+
+// XS Devices High register bit definitions
+#define XGXS_DEVICES_VENDOR2 0x8000 // Vendor specific device 2
+#define XGXS_DEVICES_VENDOR1 0x4000 // Vendor specific device 1
+
+// XS Status 2 register bit definitions
+#define XGXS_STATUS2_DEV_MASK 0xC000 // Device present mask
+#define XGXS_STATUS2_DEV_RESPOND 0x8000 // Device responding
+#define XGXS_STATUS2_XMT_FAULT 0x0800 // Transmit fault
+#define XGXS_STATUS2_RCV_FAULT 0x0400 // Receive fault
+
+// XS Package ID High register bit definitions
+#define XGXS_PKGID_HIGH_ORG 0xFC00 // Organizationally Unique
+#define XGXS_PKGID_HIGH_MFG 0x03F0 // Manufacturer Model
+#define XGXS_PKGID_HIGH_REV 0x000F // Revision Number
+
+// XS Lane Status register bit definitions
+#define XGXS_LANE_PHY 0x1000 // PHY/DTE lane alignment status
+#define XGXS_LANE_PATTERN 0x0800 // Pattern testing ability
+#define XGXS_LANE_LOOPBACK 0x0400 // PHY loopback ability
+#define XGXS_LANE_SYNC3 0x0008 // Lane 3 sync
+#define XGXS_LANE_SYNC2 0x0004 // Lane 2 sync
+#define XGXS_LANE_SYNC1 0x0002 // Lane 1 sync
+#define XGXS_LANE_SYNC0 0x0001 // Lane 0 sync
+
+// XS Test Control register bit definitions
+#define XGXS_TEST_PATTERN_ENABLE 0x0004 // Test pattern enabled
+#define XGXS_TEST_PATTERN_MASK 0x0003 // Test patterns
+#define XGXS_TEST_PATTERN_RSVD 0x0003 // Test pattern - reserved
+#define XGXS_TEST_PATTERN_MIX 0x0002 // Test pattern - mixed
+#define XGXS_TEST_PATTERN_LOW 0x0001 // Test pattern - low
+#define XGXS_TEST_PATTERN_HIGH 0x0001 // Test pattern - high
+
+/***************************************************************************
+ * External MDIO Bus Registers
+ *
+ * Full register descriptions can be found in PHY/XENPAK/IEEE specs
+ ***************************************************************************/
+// LASI (Link Alarm Status Interrupt) Registers (located in MIIM_DEV_PHY_PMA device)
+#define LASI_RX_ALARM_CONTROL 0x9000 // LASI RX_ALARM Control
+#define LASI_TX_ALARM_CONTROL 0x9001 // LASI TX_ALARM Control
+#define LASI_CONTROL 0x9002 // LASI Control
+#define LASI_RX_ALARM_STATUS 0x9003 // LASI RX_ALARM Status
+#define LASI_TX_ALARM_STATUS 0x9004 // LASI TX_ALARM Status
+#define LASI_STATUS 0x9005 // LASI Status
+
+// LASI_CONTROL bit definitions
+#define LASI_CTL_RX_ALARM_ENABLE 0x0004 // Enable RX_ALARM interrupts
+#define LASI_CTL_TX_ALARM_ENABLE 0x0002 // Enable TX_ALARM interrupts
+#define LASI_CTL_LS_ALARM_ENABLE 0x0001 // Enable Link Status interrupts
+
+// LASI_STATUS bit definitions
+#define LASI_STATUS_RX_ALARM 0x0004 // RX_ALARM status
+#define LASI_STATUS_TX_ALARM 0x0002 // TX_ALARM status
+#define LASI_STATUS_LS_ALARM 0x0001 // Link Status
+
+// PHY registers - PMA/PMD (device 1)
+#define PHY_PMA_CONTROL1 0x0000 // PMA/PMD Control 1
+#define PHY_PMA_STATUS1 0x0001 // PMA/PMD Status 1
+#define PHY_PMA_RCV_DET 0x000A // PMA/PMD Receive Signal Detect
+ // other PMA/PMD registers exist and can be defined as needed
+
+// PHY registers - PCS (device 3)
+#define PHY_PCS_CONTROL1 0x0000 // PCS Control 1
+#define PHY_PCS_STATUS1 0x0001 // PCS Status 1
+#define PHY_PCS_10G_STATUS1 0x0020 // PCS 10GBASE-R Status 1
+ // other PCS registers exist and can be defined as needed
+
+// PHY registers - XS (device 4)
+#define PHY_XS_CONTROL1 0x0000 // XS Control 1
+#define PHY_XS_STATUS1 0x0001 // XS Status 1
+#define PHY_XS_LANE_STATUS 0x0018 // XS Lane Status
+ // other XS registers exist and can be defined as needed
+
+// PHY_PMA_CONTROL1 register bit definitions
+#define PMA_CONTROL1_RESET 0x8000 // PMA/PMD reset
+
+// PHY_PMA_RCV_DET register bit definitions
+#define PMA_RCV_DETECT 0x0001 // PMA/PMD receive signal detect
+
+// PHY_PCS_10G_STATUS1 register bit definitions
+#define PCS_10B_BLOCK_LOCK 0x0001 // PCS 10GBASE-R locked to receive blocks
+
+// PHY_XS_LANE_STATUS register bit definitions
+#define XS_LANE_ALIGN 0x1000 // XS transmit lanes aligned
+
+// PHY Microcode download data structure
+typedef struct _PHY_UCODE {
+ ushort Addr;
+ ushort Data;
+} PHY_UCODE, *PPHY_UCODE;
+
+
+/*****************************************************************************
+ * Transmit Sequencer Command Descriptor definitions
+ *****************************************************************************/
+
+// This descriptor must be placed in GRAM. The address of this descriptor
+// (along with a couple of control bits) is pushed onto the PxhCmdQ or PxlCmdQ
+// (Proxy high or low command queue). This data is read by the Proxy Sequencer,
+// which pushes it onto the XmtCmdQ, which is (eventually) read by the Transmit
+// Sequencer, causing a packet to be transmitted. Not all fields are valid for
+// all commands - see the Sahara spec for details. Note that this structure is
+// only valid when compiled on a little endian machine.
+#pragma pack(push, 1)
+typedef struct _XMT_DESC {
+ ushort XmtLen; // word 0, bits [15:0] - transmit length
+ unsigned char XmtCtl; // word 0, bits [23:16] - transmit control byte
+ unsigned char Cmd; // word 0, bits [31:24] - transmit command plus misc.
+ u32 XmtBufId; // word 1, bits [31:0] - transmit buffer ID
+ unsigned char TcpStrt; // word 2, bits [7:0] - byte address of TCP header
+ unsigned char IpStrt; // word 2, bits [15:8] - byte address of IP header
+ ushort IpCkSum; // word 2, bits [31:16] - partial IP checksum
+ ushort TcpCkSum; // word 3, bits [15:0] - partial TCP checksum
+ ushort Rsvd1; // word 3, bits [31:16] - PAD
+ u32 Rsvd2; // word 4, bits [31:0] - PAD
+ u32 Rsvd3; // word 5, bits [31:0] - PAD
+ u32 Rsvd4; // word 6, bits [31:0] - PAD
+ u32 Rsvd5; // word 7, bits [31:0] - PAD
+} XMT_DESC, *PXMT_DESC;
+#pragma pack(pop)
+
+// XMT_DESC Cmd byte definitions
+ // command codes
+#define XMT_DESC_CMD_RAW_SEND 0 // raw send descriptor
+#define XMT_DESC_CMD_CSUM_INSERT 1 // checksum insert descriptor
+#define XMT_DESC_CMD_FORMAT 2 // format descriptor
+#define XMT_DESC_CMD_PRIME 3 // prime descriptor
+#define XMT_DESC_CMD_CODE_SHFT 6 // comand code shift (shift to bits [31:30] in word 0)
+ // shifted command codes
+#define XMT_RAW_SEND (XMT_DESC_CMD_RAW_SEND << XMT_DESC_CMD_CODE_SHFT)
+#define XMT_CSUM_INSERT (XMT_DESC_CMD_CSUM_INSERT << XMT_DESC_CMD_CODE_SHFT)
+#define XMT_FORMAT (XMT_DESC_CMD_FORMAT << XMT_DESC_CMD_CODE_SHFT)
+#define XMT_PRIME (XMT_DESC_CMD_PRIME << XMT_DESC_CMD_CODE_SHFT)
+
+// XMT_DESC Control Byte (XmtCtl) definitions
+// NOTE: These bits do not work on Sahara (Rev A)!
+#define XMT_CTL_PAUSE_FRAME 0x80 // current frame is a pause control frame (for statistics)
+#define XMT_CTL_CONTROL_FRAME 0x40 // current frame is a control frame (for statistics)
+#define XMT_CTL_PER_PKT_QUAL 0x20 // per packet qualifier
+#define XMT_CTL_PAD_MODE_NONE 0x00 // do not pad frame
+#define XMT_CTL_PAD_MODE_64 0x08 // pad frame to 64 bytes
+#define XMT_CTL_PAD_MODE_VLAN_68 0x10 // pad frame to 64 bytes, and VLAN frames to 68 bytes
+#define XMT_CTL_PAD_MODE_68 0x18 // pad frame to 68 bytes
+#define XMT_CTL_GEN_FCS 0x04 // generate FCS (CRC) for this frame
+#define XMT_CTL_DELAY_FCS_0 0x00 // do not delay FCS calcution
+#define XMT_CTL_DELAY_FCS_1 0x01 // delay FCS calculation by 1 (4-byte) word
+#define XMT_CTL_DELAY_FCS_2 0x02 // delay FCS calculation by 2 (4-byte) words
+#define XMT_CTL_DELAY_FCS_3 0x03 // delay FCS calculation by 3 (4-byte) words
+
+// XMT_DESC XmtBufId definition
+#define XMT_BUF_ID_SHFT 8 // The Xmt buffer ID is formed by dividing
+ // the buffer (DRAM) address by 256 (or << 8)
+
+/*****************************************************************************
+ * Receiver Sequencer Definitions
+ *****************************************************************************/
+
+// Receive Event Queue (queues 3 - 6) bit definitions
+#define RCV_EVTQ_RBFID_MASK 0x0000FFFF // bit mask for the Receive Buffer ID
+
+// Receive Buffer ID definition
+#define RCV_BUF_ID_SHFT 5 // The Rcv buffer ID is formed by dividing
+ // the buffer (DRAM) address by 32 (or << 5)
+
+// Format of the 18 byte Receive Buffer returned by the
+// Receive Sequencer for received packets
+#pragma pack(push, 1)
+typedef struct _RCV_BUF_HDR {
+ u32 Status; // Status word from Rcv Seq Parser
+ ushort Length; // Rcv packet byte count
+ union {
+ ushort TcpCsum; // TCP checksum
+ struct {
+ unsigned char TcpCsumL; // lower 8 bits of the TCP checksum
+ unsigned char LinkHash; // Link hash (multicast frames only)
+ };
+ };
+ ushort SktHash; // Socket hash
+ unsigned char TcpHdrOffset; // TCP header offset into packet
+ unsigned char IpHdrOffset; // IP header offset into packet
+ u32 TpzHash; // Toeplitz hash
+ ushort Reserved; // Reserved
+} RCV_BUF_HDR, *PRCV_BUF_HDR;
+#pragma pack(pop)
+
+
+/*****************************************************************************
+ * Queue definitions
+ *****************************************************************************/
+
+// Ingress (read only) queue numbers
+#define PXY_BUF_Q 0 // Proxy Buffer Queue
+#define HST_EVT_Q 1 // Host Event Queue
+#define XMT_BUF_Q 2 // Transmit Buffer Queue
+#define SKT_EVL_Q 3 // RcvSqr Socket Event Low Priority Queue
+#define RCV_EVL_Q 4 // RcvSqr Rcv Event Low Priority Queue
+#define SKT_EVH_Q 5 // RcvSqr Socket Event High Priority Queue
+#define RCV_EVH_Q 6 // RcvSqr Rcv Event High Priority Queue
+#define DMA_RSP_Q 7 // Dma Response Queue - one per CPU context
+// Local (read/write) queue numbers
+#define LOCAL_A_Q 8 // Spare local Queue
+#define LOCAL_B_Q 9 // Spare local Queue
+#define LOCAL_C_Q 10 // Spare local Queue
+#define FSM_EVT_Q 11 // Finite-State-Machine Event Queue
+#define SBF_PAL_Q 12 // System Buffer Physical Address (low) Queue
+#define SBF_PAH_Q 13 // System Buffer Physical Address (high) Queue
+#define SBF_VAL_Q 14 // System Buffer Virtual Address (low) Queue
+#define SBF_VAH_Q 15 // System Buffer Virtual Address (high) Queue
+// Egress (write only) queue numbers
+#define H2G_CMD_Q 16 // Host to GlbRam DMA Command Queue
+#define H2D_CMD_Q 17 // Host to DRAM DMA Command Queue
+#define G2H_CMD_Q 18 // GlbRam to Host DMA Command Queue
+#define G2D_CMD_Q 19 // GlbRam to DRAM DMA Command Queue
+#define D2H_CMD_Q 20 // DRAM to Host DMA Command Queue
+#define D2G_CMD_Q 21 // DRAM to GlbRam DMA Command Queue
+#define D2D_CMD_Q 22 // DRAM to DRAM DMA Command Queue
+#define PXL_CMD_Q 23 // Low Priority Proxy Command Queue
+#define PXH_CMD_Q 24 // High Priority Proxy Command Queue
+#define RSQ_CMD_Q 25 // Receive Sequencer Command Queue
+#define RCV_BUF_Q 26 // Receive Buffer Queue
+
+// Bit definitions for the Proxy Command queues (PXL_CMD_Q and PXH_CMD_Q)
+#define PXY_COPY_EN 0x00200000 // enable copy of xmt descriptor to xmt command queue
+#define PXY_SIZE_16 0x00000000 // copy 16 bytes
+#define PXY_SIZE_32 0x00100000 // copy 32 bytes
+
+/*****************************************************************************
+ * SXG EEPROM/Flash Configuration Definitions
+ *****************************************************************************/
+#pragma pack(push, 1)
+
+//
+typedef struct _HW_CFG_DATA {
+ ushort Addr;
+ union {
+ ushort Data;
+ ushort Checksum;
+ };
+} HW_CFG_DATA, *PHW_CFG_DATA;
+
+//
+#define NUM_HW_CFG_ENTRIES ((128/sizeof(HW_CFG_DATA)) - 4)
+
+// MAC address
+typedef struct _SXG_CONFIG_MAC {
+ unsigned char MacAddr[6]; // MAC Address
+} SXG_CONFIG_MAC, *PSXG_CONFIG_MAC;
+
+//
+typedef struct _ATK_FRU {
+ unsigned char PartNum[6];
+ unsigned char Revision[2];
+ unsigned char Serial[14];
+} ATK_FRU, *PATK_FRU;
+
+// OEM FRU Format types
+#define ATK_FRU_FORMAT 0x0000
+#define CPQ_FRU_FORMAT 0x0001
+#define DELL_FRU_FORMAT 0x0002
+#define HP_FRU_FORMAT 0x0003
+#define IBM_FRU_FORMAT 0x0004
+#define EMC_FRU_FORMAT 0x0005
+#define NO_FRU_FORMAT 0xFFFF
+
+// EEPROM/Flash Format
+typedef struct _SXG_CONFIG {
+ //
+ // Section 1 (128 bytes)
+ //
+ ushort MagicWord; // EEPROM/FLASH Magic code 'A5A5'
+ ushort SpiClks; // SPI bus clock dividers
+ HW_CFG_DATA HwCfg[NUM_HW_CFG_ENTRIES];
+ //
+ //
+ //
+ ushort Version; // EEPROM format version
+ SXG_CONFIG_MAC MacAddr[4]; // space for 4 MAC addresses
+ ATK_FRU AtkFru; // FRU information
+ ushort OemFruFormat; // OEM FRU format type
+ unsigned char OemFru[76]; // OEM FRU information (optional)
+ ushort Checksum; // Checksum of section 2
+ // CS info XXXTODO
+} SXG_CONFIG, *PSXG_CONFIG;
+#pragma pack(pop)
+
+/*****************************************************************************
+ * Miscellaneous Hardware definitions
+ *****************************************************************************/
+
+// Sahara (ASIC level) defines
+#define SAHARA_GRAM_SIZE 0x020000 // GRAM size - 128 KB
+#define SAHARA_DRAM_SIZE 0x200000 // DRAM size - 2 MB
+#define SAHARA_QRAM_SIZE 0x004000 // QRAM size - 16K entries (64 KB)
+#define SAHARA_WCS_SIZE 0x002000 // WCS - 8K instructions (x 108 bits)
+
+// Arabia (board level) defines
+#define FLASH_SIZE 0x080000 // 512 KB (4 Mb)
+#define EEPROM_SIZE_XFMR 512 // true EEPROM size (bytes), including xfmr area
+#define EEPROM_SIZE_NO_XFMR 256 // EEPROM size excluding xfmr area
diff --git a/drivers/staging/sxg/sxgphycode.h b/drivers/staging/sxg/sxgphycode.h
new file mode 100644
index 00000000000..26b36c81eb1
--- /dev/null
+++ b/drivers/staging/sxg/sxgphycode.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 1997-2008 Alacritech, Inc. All rights reserved
+ *
+ * sxgphycode.h:
+ *
+ * This file PHY microcode and register initialization data.
+ */
+
+/**********************************************************************
+ * PHY Microcode
+ *
+ * The following contains both PHY microcode and PHY register
+ * initialization data. It is specific to both the PHY and the
+ * type of transceiver.
+ *
+ **********************************************************************/
+
+/*
+ * Download for AEL2005C PHY with SR/LR transceiver (10GBASE-SR or 10GBASE-LR)
+ */
+static PHY_UCODE PhyUcode[] = {
+ /*
+ * NOTE: An address of 0 is a special case. When the download routine
+ * sees an address of 0, it does not write to the PHY. Instead, it
+ * delays the download. The length of the delay (in ms) is given in
+ * the data field.
+ *
+ * Delays are required at certain points.
+ */
+
+ /*
+ * Platform-specific MDIO Patches:
+ * (include patches for 10G RX polarity flip, 50Mhz Synth, etc)
+ */
+ /* Addr, Data */
+ {0xc017, 0xfeb0}, /* flip RX_LOS polarity (mandatory */
+ /* patch for SFP+ applications) */
+ {0xC001, 0x0428}, /* flip RX serial polarity */
+
+ {0xc013, 0xf341}, /* invert lxmit clock (mandatory patch) */
+ {0xc210, 0x8000}, /* reset datapath (mandatory patch) */
+ {0xc210, 0x8100}, /* reset datapath (mandatory patch) */
+ {0xc210, 0x8000}, /* reset datapath (mandatory patch) */
+ {0xc210, 0x0000}, /* reset datapath (mandatory patch) */
+ {0x0000, 0x0032}, /* wait for 50ms for datapath reset to */
+ /* complete. (mandatory patch) */
+
+ /* Configure the LED's */
+ {0xc214, 0x0099}, /* configure the LED drivers */
+ {0xc216, 0x5f5f}, /* configure the Activity LED */
+ {0xc217, 0x33ff}, /* configure the Link LED */
+
+ /* Transceiver-specific MDIO Patches: */
+ {0xc010, 0x448a}, /* (bit 14) mask out high BER input from the */
+ /* LOS signal in 1.000A */
+ /* (mandatory patch for SR code)*/
+ {0xc003, 0x0181}, /* (bit 7) enable the CDR inc setting in */
+ /* 1.C005 (mandatory patch for SR code) */
+
+ /* Transceiver-specific Microcontroller Initialization: */
+ {0xc04a, 0x5200}, /* activate microcontroller and pause */
+ {0x0000, 0x0032}, /* wait 50ms for microcontroller before */
+ /* writing in code. */
+
+ /* code block starts here: */
+ {0xcc00, 0x2009},
+ {0xcc01, 0x3009},
+ {0xcc02, 0x27ff},
+ {0xcc03, 0x300f},
+ {0xcc04, 0x200c},
+ {0xcc05, 0x300c},
+ {0xcc06, 0x20c4},
+ {0xcc07, 0x3c04},
+ {0xcc08, 0x6437},
+ {0xcc09, 0x20c4},
+ {0xcc0a, 0x3c04},
+ {0xcc0b, 0x6437},
+ {0xcc0c, 0x25c4},
+ {0xcc0d, 0x3c54},
+ {0xcc0e, 0x6724},
+ {0xcc0f, 0x25c4},
+ {0xcc10, 0x3c54},
+ {0xcc11, 0x6724},
+ {0xcc12, 0x2042},
+ {0xcc13, 0x3012},
+ {0xcc14, 0x1002},
+ {0xcc15, 0x2482},
+ {0xcc16, 0x3012},
+ {0xcc17, 0x1002},
+ {0xcc18, 0x2a32},
+ {0xcc19, 0x3002},
+ {0xcc1a, 0x1002},
+ {0xcc1b, 0x200d},
+ {0xcc1c, 0x304d},
+ {0xcc1d, 0x2862},
+ {0xcc1e, 0x3012},
+ {0xcc1f, 0x1002},
+ {0xcc20, 0x2982},
+ {0xcc21, 0x3002},
+ {0xcc22, 0x1002},
+ {0xcc23, 0x628f},
+ {0xcc24, 0x20a4},
+ {0xcc25, 0x3004},
+ {0xcc26, 0x6438},
+ {0xcc27, 0x20a4},
+ {0xcc28, 0x3004},
+ {0xcc29, 0x6438},
+ {0xcc2a, 0x2015},
+ {0xcc2b, 0x3005},
+ {0xcc2c, 0x5853},
+ {0xcc2d, 0x2bd2},
+ {0xcc2e, 0x3002},
+ {0xcc2f, 0x1342},
+ {0xcc30, 0x200c},
+ {0xcc31, 0x300c},
+ {0xcc32, 0x2ff7},
+ {0xcc33, 0x30f7},
+ {0xcc34, 0x20c4},
+ {0xcc35, 0x3c04},
+ {0xcc36, 0x6724},
+ {0xcc37, 0x20c4},
+ {0xcc38, 0x3c04},
+ {0xcc39, 0x6724},
+ {0xcc3a, 0x2d32},
+ {0xcc3b, 0x3002},
+ {0xcc3c, 0x1002},
+ {0xcc3d, 0x2008},
+ {0xcc3e, 0x3008},
+ {0xcc3f, 0x5c83},
+ {0xcc40, 0x2d52},
+ {0xcc41, 0x3002},
+ {0xcc42, 0x1352},
+ {0xcc43, 0x2008},
+ {0xcc44, 0x3008},
+ {0xcc45, 0x5c83},
+ {0xcc46, 0x2d32},
+ {0xcc47, 0x3002},
+ {0xcc48, 0x1352},
+ {0xcc49, 0x201c},
+ {0xcc4a, 0x300c},
+ {0xcc4b, 0x200d},
+ {0xcc4c, 0x310d},
+ {0xcc4d, 0x2862},
+ {0xcc4e, 0x3012},
+ {0xcc4f, 0x1002},
+ {0xcc50, 0x2ed2},
+ {0xcc51, 0x3002},
+ {0xcc52, 0x1342},
+ {0xcc53, 0x6f72},
+ {0xcc54, 0x1002},
+ {0xcc55, 0x628f},
+ {0xcc56, 0x2514},
+ {0xcc57, 0x3c64},
+ {0xcc58, 0x6436},
+ {0xcc59, 0x2514},
+ {0xcc5a, 0x3c64},
+ {0xcc5b, 0x6436},
+ {0xcc5c, 0x2fa4},
+ {0xcc5d, 0x3cd4},
+ {0xcc5e, 0x6624},
+ {0xcc5f, 0x2fa4},
+ {0xcc60, 0x3cd4},
+ {0xcc61, 0x6624},
+ {0xcc62, 0x2f45},
+ {0xcc63, 0x3015},
+ {0xcc64, 0x5653},
+ {0xcc65, 0x2eb2},
+ {0xcc66, 0x3002},
+ {0xcc67, 0x13d2},
+ {0xcc68, 0x2ed2},
+ {0xcc69, 0x3002},
+ {0xcc6a, 0x1002},
+ {0xcc6b, 0x6f72},
+ {0xcc6c, 0x1002},
+ {0xcc6d, 0x628f},
+ {0xcc6e, 0x2602},
+ {0xcc6f, 0x3012},
+ {0xcc70, 0x1002},
+ {0xcc71, 0x200d},
+ {0xcc72, 0x320d},
+ {0xcc73, 0x2862},
+ {0xcc74, 0x3012},
+ {0xcc75, 0x1002},
+ {0xcc76, 0x25c4},
+ {0xcc77, 0x3c54},
+ {0xcc78, 0x6437},
+ {0xcc79, 0x25c4},
+ {0xcc7a, 0x3c54},
+ {0xcc7b, 0x6437},
+ {0xcc7c, 0x20c4},
+ {0xcc7d, 0x3c04},
+ {0xcc7e, 0x6724},
+ {0xcc7f, 0x20c4},
+ {0xcc80, 0x3c04},
+ {0xcc81, 0x6724},
+ {0xcc82, 0x6f72},
+ {0xcc83, 0x1002},
+ {0xcc84, 0x628f},
+ {0xcc85, 0x26f2},
+ {0xcc86, 0x3012},
+ {0xcc87, 0x1002},
+ {0xcc88, 0xc503},
+ {0xcc89, 0xd5d5},
+ {0xcc8a, 0xc600},
+ {0xcc8b, 0x2a6d},
+ {0xcc8c, 0xc601},
+ {0xcc8d, 0x2a4c},
+ {0xcc8e, 0xc602},
+ {0xcc8f, 0x0111},
+ {0xcc90, 0xc60c},
+ {0xcc91, 0x5900},
+ {0xcc92, 0xc710},
+ {0xcc93, 0x0700},
+ {0xcc94, 0xc718},
+ {0xcc95, 0x0700},
+ {0xcc96, 0xc720},
+ {0xcc97, 0x4700},
+ {0xcc98, 0xc801},
+ {0xcc99, 0x7f50},
+ {0xcc9a, 0xc802},
+ {0xcc9b, 0x7760},
+ {0xcc9c, 0xc803},
+ {0xcc9d, 0x7fce},
+ {0xcc9e, 0xc804},
+ {0xcc9f, 0x5700},
+ {0xcca0, 0xc805},
+ {0xcca1, 0x5f11},
+ {0xcca2, 0xc806},
+ {0xcca3, 0x4751},
+ {0xcca4, 0xc807},
+ {0xcca5, 0x57e1},
+ {0xcca6, 0xc808},
+ {0xcca7, 0x2700},
+ {0xcca8, 0xc809},
+ {0xcca9, 0x0000},
+ {0xccaa, 0xc821},
+ {0xccab, 0x0002},
+ {0xccac, 0xc822},
+ {0xccad, 0x0014},
+ {0xccae, 0xc832},
+ {0xccaf, 0x1186},
+ {0xccb0, 0xc847},
+ {0xccb1, 0x1e02},
+ {0xccb2, 0xc013},
+ {0xccb3, 0xf341},
+ {0xccb4, 0xc01a},
+ {0xccb5, 0x0446},
+ {0xccb6, 0xc024},
+ {0xccb7, 0x1000},
+ {0xccb8, 0xc025},
+ {0xccb9, 0x0a00},
+ {0xccba, 0xc026},
+ {0xccbb, 0x0c0c},
+ {0xccbc, 0xc027},
+ {0xccbd, 0x0c0c},
+ {0xccbe, 0xc029},
+ {0xccbf, 0x00a0},
+ {0xccc0, 0xc030},
+ {0xccc1, 0x0a00},
+ {0xccc2, 0xc03c},
+ {0xccc3, 0x001c},
+ {0xccc4, 0xc005},
+ {0xccc5, 0x7a06},
+ {0xccc6, 0x0000},
+ {0xccc7, 0x0000},
+ {0xccc8, 0x628f},
+ {0xccc9, 0x26f2},
+ {0xccca, 0x3012},
+ {0xcccb, 0x1002},
+ {0xcccc, 0xc620},
+ {0xcccd, 0x0000},
+ {0xccce, 0xc621},
+ {0xcccf, 0x003f},
+ {0xccd0, 0xc622},
+ {0xccd1, 0x0000},
+ {0xccd2, 0xc623},
+ {0xccd3, 0x0000},
+ {0xccd4, 0xc624},
+ {0xccd5, 0x0000},
+ {0xccd6, 0xc625},
+ {0xccd7, 0x0000},
+ {0xccd8, 0xc627},
+ {0xccd9, 0x0000},
+ {0xccda, 0xc628},
+ {0xccdb, 0x0000},
+ {0xccdc, 0xc62c},
+ {0xccdd, 0x0000},
+ {0xccde, 0x0000},
+ {0xccdf, 0x0000},
+ {0xcce0, 0x628f},
+ {0xcce1, 0xd019},
+ {0xcce2, 0x26f2},
+ {0xcce3, 0x3012},
+ {0xcce4, 0x1002},
+ {0xcce5, 0xc210},
+ {0xcce6, 0x8000},
+ {0xcce7, 0xc210},
+ {0xcce8, 0x8010},
+ {0xcce9, 0xc210},
+ {0xccea, 0x8000},
+ {0xcceb, 0xc210},
+ {0xccec, 0x0000},
+ {0xcced, 0x0000},
+ {0xccee, 0x0000},
+ {0xccef, 0x8221},
+ {0xccf0, 0x2752},
+ {0xccf1, 0x3012},
+ {0xccf2, 0x1002},
+ {0xccf3, 0x6f72},
+ {0xccf4, 0x1002},
+ {0xccf5, 0x2806},
+ {0xccf6, 0x3006},
+ {0xccf7, 0x2007},
+ {0xccf8, 0x3cc7},
+ {0xccf9, 0xe161},
+ {0xccfa, 0xc171},
+ {0xccfb, 0x6134},
+ {0xccfc, 0x6135},
+ {0xccfd, 0x5453},
+ {0xccfe, 0x2858},
+ {0xccff, 0x3018},
+ {0xcd00, 0x1348},
+ {0xcd01, 0x6524},
+ {0xcd02, 0x27b8},
+ {0xcd03, 0x3018},
+ {0xcd04, 0x1008},
+ {0xcd05, 0x1002},
+ {0xcd06, 0x628f},
+ {0xcd07, 0x5dd3},
+ {0xcd08, 0x2906},
+ {0xcd09, 0x3016},
+ {0xcd0a, 0x1306},
+ {0xcd0b, 0x2ff7},
+ {0xcd0c, 0x30f7},
+ {0xcd0d, 0x60b7},
+ {0xcd0e, 0xdffd},
+ {0xcd0f, 0x0008},
+ {0xcd10, 0x6f72},
+ {0xcd11, 0x1002},
+ {0xcd12, 0x0000},
+ {0xcdff, 0x0a01},
+ /* end of code block */
+
+ /* Unpause the microcontroller to start program */
+ {0xca00, 0x0080},
+ {0xca12, 0x0000},
+ {0x0000, 0x000A}, /* wait 10ms just to be safe */
+ {0xffff, 0xffff} /* table terminator */
+};
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
new file mode 100644
index 00000000000..7426235ccc4
--- /dev/null
+++ b/drivers/staging/usbip/Kconfig
@@ -0,0 +1,36 @@
+config USB_IP_COMMON
+ tristate "USB IP support (EXPERIMENTAL)"
+ depends on USB && EXPERIMENTAL
+ default N
+ ---help---
+ This enables pushing USB packets over IP to allow remote
+ machines access to USB devices directly. For more details,
+ and links to the userspace utility programs to let this work
+ properly, see http://usbip.naist.jp/
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbip_common_mod.
+
+ If unsure, say N.
+
+config USB_IP_VHCI_HCD
+ tristate "USB IP client driver"
+ depends on USB_IP_COMMON
+ default N
+ ---help---
+ This enables the USB IP host controller driver which will
+ run on the client machine.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vhci_hcd.
+
+config USB_IP_HOST
+ tristate "USB IP host driver"
+ depends on USB_IP_COMMON
+ default N
+ ---help---
+ This enables the USB IP device driver which will run on the
+ host machine.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbip.
diff --git a/drivers/staging/usbip/Makefile b/drivers/staging/usbip/Makefile
new file mode 100644
index 00000000000..179f4211f96
--- /dev/null
+++ b/drivers/staging/usbip/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_USB_IP_COMMON) += usbip_common_mod.o
+usbip_common_mod-objs := usbip_common.o usbip_event.o
+
+obj-$(CONFIG_USB_IP_VHCI_HCD) += vhci-hcd.o
+vhci-hcd-objs := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
+
+obj-$(CONFIG_USB_IP_HOST) += usbip.o
+usbip-objs := stub_dev.o stub_main.o stub_rx.o stub_tx.o
+
+ifeq ($(CONFIG_USB_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/staging/usbip/README b/drivers/staging/usbip/README
new file mode 100644
index 00000000000..c11be573548
--- /dev/null
+++ b/drivers/staging/usbip/README
@@ -0,0 +1,6 @@
+TODO:
+ - more discussion about the protocol
+ - testing
+ - review of the userspace interface
+
+Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
new file mode 100644
index 00000000000..f541a3a83bd
--- /dev/null
+++ b/drivers/staging/usbip/stub.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/net.h>
+
+struct stub_device {
+ struct usb_interface *interface;
+ struct list_head list;
+
+ struct usbip_device ud;
+ __u32 devid;
+
+ /*
+ * stub_priv preserves private data of each urb.
+ * It is allocated as stub_priv_cache and assigned to urb->context.
+ *
+ * stub_priv is always linked to any one of 3 lists;
+ * priv_init: linked to this until the comletion of a urb.
+ * priv_tx : linked to this after the completion of a urb.
+ * priv_free: linked to this after the sending of the result.
+ *
+ * Any of these list operations should be locked by priv_lock.
+ */
+ spinlock_t priv_lock;
+ struct list_head priv_init;
+ struct list_head priv_tx;
+ struct list_head priv_free;
+
+ /* see comments for unlinking in stub_rx.c */
+ struct list_head unlink_tx;
+ struct list_head unlink_free;
+
+
+ wait_queue_head_t tx_waitq;
+};
+
+/* private data into urb->priv */
+struct stub_priv {
+ unsigned long seqnum;
+ struct list_head list;
+ struct stub_device *sdev;
+ struct urb *urb;
+
+ int unlinking;
+};
+
+struct stub_unlink {
+ unsigned long seqnum;
+ struct list_head list;
+ __u32 status;
+};
+
+
+extern struct kmem_cache *stub_priv_cache;
+
+
+/*-------------------------------------------------------------------------*/
+/* prototype declarations */
+
+/* stub_tx.c */
+void stub_complete(struct urb *);
+void stub_tx_loop(struct usbip_task *);
+
+/* stub_dev.c */
+extern struct usb_driver stub_driver;
+
+/* stub_rx.c */
+void stub_rx_loop(struct usbip_task *);
+void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);
+
+/* stub_main.c */
+int match_busid(char *busid);
+void stub_device_cleanup_urbs(struct stub_device *sdev);
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
new file mode 100644
index 00000000000..ee455a087ea
--- /dev/null
+++ b/drivers/staging/usbip/stub_dev.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "stub.h"
+
+
+
+static int stub_probe(struct usb_interface *interface,
+ const struct usb_device_id *id);
+static void stub_disconnect(struct usb_interface *interface);
+
+
+/*
+ * Define device IDs here if you want to explicitly limit exportable devices.
+ * In the most cases, wild card matching will be ok because driver binding can
+ * be changed dynamically by a userland program.
+ */
+static struct usb_device_id stub_table[] = {
+#if 0
+ /* just an example */
+ { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */
+ { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */
+ { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */
+ { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */
+ { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */
+ { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */
+ { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */
+ { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */
+ { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */
+ { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */
+ { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */
+ { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */
+#endif
+ /* magic for wild card */
+ { .driver_info = 1 },
+ { 0, } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, stub_table);
+
+struct usb_driver stub_driver = {
+ .name = "usbip",
+ .probe = stub_probe,
+ .disconnect = stub_disconnect,
+ .id_table = stub_table,
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Define sysfs entries for a usbip-bound device */
+
+
+/*
+ * usbip_status shows status of usbip as long as this driver is bound to the
+ * target device.
+ */
+static ssize_t show_status(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct stub_device *sdev = dev_get_drvdata(dev);
+ int status;
+
+ if (!sdev) {
+ dev_err(dev, "sdev is null\n");
+ return -ENODEV;
+ }
+
+ spin_lock(&sdev->ud.lock);
+ status = sdev->ud.status;
+ spin_unlock(&sdev->ud.lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", status);
+}
+static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL);
+
+/*
+ * usbip_sockfd gets a socket descriptor of an established TCP connection that
+ * is used to transfer usbip requests by kernel threads. -1 is a magic number
+ * by which usbip connection is finished.
+ */
+static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stub_device *sdev = dev_get_drvdata(dev);
+ int sockfd = 0;
+ struct socket *socket;
+
+ if (!sdev) {
+ dev_err(dev, "sdev is null\n");
+ return -ENODEV;
+ }
+
+ sscanf(buf, "%d", &sockfd);
+
+ if (sockfd != -1) {
+ dev_info(dev, "stub up\n");
+
+ spin_lock(&sdev->ud.lock);
+
+ if (sdev->ud.status != SDEV_ST_AVAILABLE) {
+ dev_err(dev, "not ready\n");
+ spin_unlock(&sdev->ud.lock);
+ return -EINVAL;
+ }
+
+ socket = sockfd_to_socket(sockfd);
+ if (!socket) {
+ spin_unlock(&sdev->ud.lock);
+ return -EINVAL;
+ }
+
+#if 0
+ setnodelay(socket);
+ setkeepalive(socket);
+ setreuse(socket);
+#endif
+
+ sdev->ud.tcp_socket = socket;
+
+ spin_unlock(&sdev->ud.lock);
+
+ usbip_start_threads(&sdev->ud);
+
+ spin_lock(&sdev->ud.lock);
+ sdev->ud.status = SDEV_ST_USED;
+ spin_unlock(&sdev->ud.lock);
+
+ } else {
+ dev_info(dev, "stub down\n");
+
+ spin_lock(&sdev->ud.lock);
+ if (sdev->ud.status != SDEV_ST_USED) {
+ spin_unlock(&sdev->ud.lock);
+ return -EINVAL;
+ }
+ spin_unlock(&sdev->ud.lock);
+
+ usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
+ }
+
+ return count;
+}
+static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd);
+
+static int stub_add_files(struct device *dev)
+{
+ int err = 0;
+
+ err = device_create_file(dev, &dev_attr_usbip_status);
+ if (err)
+ goto err_status;
+
+ err = device_create_file(dev, &dev_attr_usbip_sockfd);
+ if (err)
+ goto err_sockfd;
+
+ err = device_create_file(dev, &dev_attr_usbip_debug);
+ if (err)
+ goto err_debug;
+
+ return 0;
+
+err_debug:
+ device_remove_file(dev, &dev_attr_usbip_sockfd);
+
+err_sockfd:
+ device_remove_file(dev, &dev_attr_usbip_status);
+
+err_status:
+ return err;
+}
+
+static void stub_remove_files(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_usbip_status);
+ device_remove_file(dev, &dev_attr_usbip_sockfd);
+ device_remove_file(dev, &dev_attr_usbip_debug);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Event handler functions called by an event handler thread */
+
+static void stub_shutdown_connection(struct usbip_device *ud)
+{
+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+
+ /*
+ * When removing an exported device, kernel panic sometimes occurred
+ * and then EIP was sk_wait_data of stub_rx thread. Is this because
+ * sk_wait_data returned though stub_rx thread was already finished by
+ * step 1?
+ */
+ if (ud->tcp_socket) {
+ udbg("shutdown tcp_socket %p\n", ud->tcp_socket);
+ kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+ }
+
+ /* 1. stop threads */
+ usbip_stop_threads(ud);
+
+ /* 2. close the socket */
+ /*
+ * tcp_socket is freed after threads are killed.
+ * So usbip_xmit do not touch NULL socket.
+ */
+ if (ud->tcp_socket) {
+ sock_release(ud->tcp_socket);
+ ud->tcp_socket = NULL;
+ }
+
+ /* 3. free used data */
+ stub_device_cleanup_urbs(sdev);
+
+ /* 4. free stub_unlink */
+ {
+ unsigned long flags;
+ struct stub_unlink *unlink, *tmp;
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
+ list_del(&unlink->list);
+ kfree(unlink);
+ }
+
+ list_for_each_entry_safe(unlink, tmp,
+ &sdev->unlink_free, list) {
+ list_del(&unlink->list);
+ kfree(unlink);
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ }
+}
+
+static void stub_device_reset(struct usbip_device *ud)
+{
+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+ struct usb_device *udev = interface_to_usbdev(sdev->interface);
+ int ret;
+
+ udbg("device reset");
+ ret = usb_lock_device_for_reset(udev, sdev->interface);
+ if (ret < 0) {
+ dev_err(&udev->dev, "lock for reset\n");
+
+ spin_lock(&ud->lock);
+ ud->status = SDEV_ST_ERROR;
+ spin_unlock(&ud->lock);
+
+ return;
+ }
+
+ /* try to reset the device */
+ ret = usb_reset_device(udev);
+
+ usb_unlock_device(udev);
+
+ spin_lock(&ud->lock);
+ if (ret) {
+ dev_err(&udev->dev, "device reset\n");
+ ud->status = SDEV_ST_ERROR;
+
+ } else {
+ dev_info(&udev->dev, "device reset\n");
+ ud->status = SDEV_ST_AVAILABLE;
+
+ }
+ spin_unlock(&ud->lock);
+
+ return;
+}
+
+static void stub_device_unusable(struct usbip_device *ud)
+{
+ spin_lock(&ud->lock);
+ ud->status = SDEV_ST_ERROR;
+ spin_unlock(&ud->lock);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * stub_device_alloc - allocate a new stub_device struct
+ * @interface: usb_interface of a new device
+ *
+ * Allocates and initializes a new stub_device struct.
+ */
+static struct stub_device *stub_device_alloc(struct usb_interface *interface)
+{
+ struct stub_device *sdev;
+ int busnum = interface_to_busnum(interface);
+ int devnum = interface_to_devnum(interface);
+
+ dev_dbg(&interface->dev, "allocating stub device");
+
+ /* yes, it's a new device */
+ sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL);
+ if (!sdev) {
+ dev_err(&interface->dev, "no memory for stub_device\n");
+ return NULL;
+ }
+
+ sdev->interface = interface;
+
+ /*
+ * devid is defined with devnum when this driver is first allocated.
+ * devnum may change later if a device is reset. However, devid never
+ * changes during a usbip connection.
+ */
+ sdev->devid = (busnum << 16) | devnum;
+
+ usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop);
+ usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop);
+
+ sdev->ud.side = USBIP_STUB;
+ sdev->ud.status = SDEV_ST_AVAILABLE;
+ /* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */
+ spin_lock_init(&sdev->ud.lock);
+ sdev->ud.tcp_socket = NULL;
+
+ INIT_LIST_HEAD(&sdev->priv_init);
+ INIT_LIST_HEAD(&sdev->priv_tx);
+ INIT_LIST_HEAD(&sdev->priv_free);
+ INIT_LIST_HEAD(&sdev->unlink_free);
+ INIT_LIST_HEAD(&sdev->unlink_tx);
+ /* sdev->priv_lock = SPIN_LOCK_UNLOCKED; */
+ spin_lock_init(&sdev->priv_lock);
+
+ init_waitqueue_head(&sdev->tx_waitq);
+
+ sdev->ud.eh_ops.shutdown = stub_shutdown_connection;
+ sdev->ud.eh_ops.reset = stub_device_reset;
+ sdev->ud.eh_ops.unusable = stub_device_unusable;
+
+ usbip_start_eh(&sdev->ud);
+
+ udbg("register new interface\n");
+ return sdev;
+}
+
+static int stub_device_free(struct stub_device *sdev)
+{
+ if (!sdev)
+ return -EINVAL;
+
+ kfree(sdev);
+ udbg("kfree udev ok\n");
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * If a usb device has multiple active interfaces, this driver is bound to all
+ * the active interfaces. However, usbip exports *a* usb device (i.e., not *an*
+ * active interface). Currently, a userland program must ensure that it
+ * looks at the usbip's sysfs entries of only the first active interface.
+ *
+ * TODO: use "struct usb_device_driver" to bind a usb device.
+ * However, it seems it is not fully supported in mainline kernel yet
+ * (2.6.19.2).
+ */
+static int stub_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct stub_device *sdev = NULL;
+ char *udev_busid = interface->dev.parent->bus_id;
+ int err = 0;
+
+ dev_dbg(&interface->dev, "Enter\n");
+
+ /* check we should claim or not by busid_table */
+ if (match_busid(udev_busid)) {
+ dev_info(&interface->dev,
+ "this device %s is not in match_busid table. skip!\n",
+ udev_busid);
+
+ /*
+ * Return value should be ENODEV or ENOXIO to continue trying
+ * other matched drivers by the driver core.
+ * See driver_probe_device() in driver/base/dd.c
+ */
+ return -ENODEV;
+ }
+
+ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
+ udbg("this device %s is a usb hub device. skip!\n",
+ udev_busid);
+ return -ENODEV;
+ }
+
+ if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
+ udbg("this device %s is attached on vhci_hcd. skip!\n",
+ udev_busid);
+ return -ENODEV;
+ }
+
+ /* ok. this is my device. */
+ sdev = stub_device_alloc(interface);
+ if (!sdev)
+ return -ENOMEM;
+
+ dev_info(&interface->dev, "USB/IP Stub: register a new interface "
+ "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
+ interface->cur_altsetting->desc.bInterfaceNumber);
+
+ /* set private data to usb_interface */
+ usb_set_intfdata(interface, sdev);
+
+ err = stub_add_files(&interface->dev);
+ if (err) {
+ dev_err(&interface->dev, "create sysfs files for %s\n",
+ udev_busid);
+ return err;
+ }
+
+ return 0;
+}
+
+
+/*
+ * called in usb_disconnect() or usb_deregister()
+ * but only if actconfig(active configuration) exists
+ */
+static void stub_disconnect(struct usb_interface *interface)
+{
+ struct stub_device *sdev = usb_get_intfdata(interface);
+
+ udbg("Enter\n");
+
+ /* get stub_device */
+ if (!sdev) {
+ err(" could not get device from inteface data");
+ /* BUG(); */
+ return;
+ }
+
+ usb_set_intfdata(interface, NULL);
+
+
+ /*
+ * NOTE:
+ * rx/tx threads are invoked for each usb_device.
+ */
+ stub_remove_files(&interface->dev);
+
+ /* 1. shutdown the current connection */
+ usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED);
+
+ /* 2. wait for the stop of the event handler */
+ usbip_stop_eh(&sdev->ud);
+
+ /* 3. free sdev */
+ stub_device_free(sdev);
+
+
+ udbg("bye\n");
+}
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
new file mode 100644
index 00000000000..c665d7f1ca9
--- /dev/null
+++ b/drivers/staging/usbip/stub_main.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+
+#include "usbip_common.h"
+#include "stub.h"
+
+/* Version Information */
+#define DRIVER_VERSION "1.0"
+#define DRIVER_AUTHOR "Takahiro Hirofuchi"
+#define DRIVER_DESC "Stub Driver for USB/IP"
+
+/* stub_priv is allocated from stub_priv_cache */
+struct kmem_cache *stub_priv_cache;
+
+/*-------------------------------------------------------------------------*/
+
+/* Define sysfs entries for the usbip driver */
+
+
+/*
+ * busid_tables defines matching busids that usbip can grab. A user can change
+ * dynamically what device is locally used and what device is exported to a
+ * remote host.
+ */
+#define MAX_BUSID 16
+static char busid_table[MAX_BUSID][BUS_ID_SIZE];
+static spinlock_t busid_table_lock;
+
+
+int match_busid(char *busid)
+{
+ int i;
+
+ spin_lock(&busid_table_lock);
+
+ for (i = 0; i < MAX_BUSID; i++)
+ if (busid_table[i][0])
+ if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) {
+ /* already registerd */
+ spin_unlock(&busid_table_lock);
+ return 0;
+ }
+
+ spin_unlock(&busid_table_lock);
+
+ return 1;
+}
+
+static ssize_t show_match_busid(struct device_driver *drv, char *buf)
+{
+ int i;
+ char *out = buf;
+
+ spin_lock(&busid_table_lock);
+
+ for (i = 0; i < MAX_BUSID; i++)
+ if (busid_table[i][0])
+ out += sprintf(out, "%s ", busid_table[i]);
+
+ spin_unlock(&busid_table_lock);
+
+ out += sprintf(out, "\n");
+
+ return out - buf;
+}
+
+static int add_match_busid(char *busid)
+{
+ int i;
+
+ if (!match_busid(busid))
+ return 0;
+
+ spin_lock(&busid_table_lock);
+
+ for (i = 0; i < MAX_BUSID; i++)
+ if (!busid_table[i][0]) {
+ strncpy(busid_table[i], busid, BUS_ID_SIZE);
+ spin_unlock(&busid_table_lock);
+ return 0;
+ }
+
+ spin_unlock(&busid_table_lock);
+
+ return -1;
+}
+
+static int del_match_busid(char *busid)
+{
+ int i;
+
+ spin_lock(&busid_table_lock);
+
+ for (i = 0; i < MAX_BUSID; i++)
+ if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) {
+ /* found */
+ memset(busid_table[i], 0, BUS_ID_SIZE);
+ spin_unlock(&busid_table_lock);
+ return 0;
+ }
+
+ spin_unlock(&busid_table_lock);
+
+ return -1;
+}
+
+static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
+ size_t count)
+{
+ int len;
+ char busid[BUS_ID_SIZE];
+
+ if (count < 5)
+ return -EINVAL;
+
+ /* strnlen() does not include \0 */
+ len = strnlen(buf + 4, BUS_ID_SIZE);
+
+ /* busid needs to include \0 termination */
+ if (!(len < BUS_ID_SIZE))
+ return -EINVAL;
+
+ strncpy(busid, buf + 4, BUS_ID_SIZE);
+
+
+ if (!strncmp(buf, "add ", 4)) {
+ if (add_match_busid(busid) < 0)
+ return -ENOMEM;
+ else {
+ udbg("add busid %s\n", busid);
+ return count;
+ }
+ } else if (!strncmp(buf, "del ", 4)) {
+ if (del_match_busid(busid) < 0)
+ return -ENODEV;
+ else {
+ udbg("del busid %s\n", busid);
+ return count;
+ }
+ } else
+ return -EINVAL;
+}
+
+static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid,
+ store_match_busid);
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Cleanup functions used to free private data */
+
+static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
+{
+ struct stub_priv *priv, *tmp;
+
+ list_for_each_entry_safe(priv, tmp, listhead, list) {
+ list_del(&priv->list);
+ return priv;
+ }
+
+ return NULL;
+}
+
+static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
+{
+ unsigned long flags;
+ struct stub_priv *priv;
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ priv = stub_priv_pop_from_listhead(&sdev->priv_init);
+ if (priv) {
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return priv;
+ }
+
+ priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
+ if (priv) {
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return priv;
+ }
+
+ priv = stub_priv_pop_from_listhead(&sdev->priv_free);
+ if (priv) {
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return priv;
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return NULL;
+}
+
+void stub_device_cleanup_urbs(struct stub_device *sdev)
+{
+ struct stub_priv *priv;
+
+ udbg("free sdev %p\n", sdev);
+
+ while ((priv = stub_priv_pop(sdev))) {
+ struct urb *urb = priv->urb;
+
+ udbg(" free urb %p\n", urb);
+ usb_kill_urb(urb);
+
+ kmem_cache_free(stub_priv_cache, priv);
+
+ if (urb->transfer_buffer != NULL)
+ kfree(urb->transfer_buffer);
+
+ if (urb->setup_packet != NULL)
+ kfree(urb->setup_packet);
+
+ usb_free_urb(urb);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int __init usb_stub_init(void)
+{
+ int ret;
+
+ stub_priv_cache = kmem_cache_create("stub_priv",
+ sizeof(struct stub_priv), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+
+ if (!stub_priv_cache) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": create stub_priv_cache error\n");
+ return -ENOMEM;
+ }
+
+ ret = usb_register(&stub_driver);
+ if (ret) {
+ printk(KERN_ERR KBUILD_MODNAME ": usb_register failed %d\n",
+ ret);
+ goto error_usb_register;
+ }
+
+ printk(KERN_INFO KBUILD_MODNAME ":"
+ DRIVER_DESC ":" DRIVER_VERSION "\n");
+
+ memset(busid_table, 0, sizeof(busid_table));
+ spin_lock_init(&busid_table_lock);
+
+ ret = driver_create_file(&stub_driver.drvwrap.driver,
+ &driver_attr_match_busid);
+
+ if (ret) {
+ printk(KERN_ERR KBUILD_MODNAME ": create driver sysfs\n");
+ goto error_create_file;
+ }
+
+ return ret;
+error_create_file:
+ usb_deregister(&stub_driver);
+error_usb_register:
+ kmem_cache_destroy(stub_priv_cache);
+ return ret;
+}
+
+static void __exit usb_stub_exit(void)
+{
+ driver_remove_file(&stub_driver.drvwrap.driver,
+ &driver_attr_match_busid);
+
+ /*
+ * deregister() calls stub_disconnect() for all devices. Device
+ * specific data is cleared in stub_disconnect().
+ */
+ usb_deregister(&stub_driver);
+
+ kmem_cache_destroy(stub_priv_cache);
+}
+
+module_init(usb_stub_init);
+module_exit(usb_stub_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
new file mode 100644
index 00000000000..36ce898fced
--- /dev/null
+++ b/drivers/staging/usbip/stub_rx.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "stub.h"
+#include "../../usb/core/hcd.h"
+
+
+static int is_clear_halt_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ return (req->bRequest == USB_REQ_CLEAR_FEATURE) &&
+ (req->bRequestType == USB_RECIP_ENDPOINT) &&
+ (req->wValue == USB_ENDPOINT_HALT);
+}
+
+static int is_set_interface_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ return (req->bRequest == USB_REQ_SET_INTERFACE) &&
+ (req->bRequestType == USB_RECIP_INTERFACE);
+}
+
+static int is_set_configuration_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ return (req->bRequest == USB_REQ_SET_CONFIGURATION) &&
+ (req->bRequestType == USB_RECIP_DEVICE);
+}
+
+static int is_reset_device_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+ __u16 value;
+ __u16 index;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+ value = le16_to_cpu(req->wValue);
+ index = le16_to_cpu(req->wIndex);
+
+ if ((req->bRequest == USB_REQ_SET_FEATURE) &&
+ (req->bRequestType == USB_RT_PORT) &&
+ (value = USB_PORT_FEAT_RESET)) {
+ dbg_stub_rx("reset_device_cmd, port %u\n", index);
+ return 1;
+ } else
+ return 0;
+}
+
+static int tweak_clear_halt_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+ int target_endp;
+ int target_dir;
+ int target_pipe;
+ int ret;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ /*
+ * The stalled endpoint is specified in the wIndex value. The endpoint
+ * of the urb is the target of this clear_halt request (i.e., control
+ * endpoint).
+ */
+ target_endp = le16_to_cpu(req->wIndex) & 0x000f;
+
+ /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */
+ target_dir = le16_to_cpu(req->wIndex) & 0x0080;
+
+ if (target_dir)
+ target_pipe = usb_rcvctrlpipe(urb->dev, target_endp);
+ else
+ target_pipe = usb_sndctrlpipe(urb->dev, target_endp);
+
+ ret = usb_clear_halt(urb->dev, target_pipe);
+ if (ret < 0)
+ uinfo("clear_halt error: devnum %d endp %d, %d\n",
+ urb->dev->devnum, target_endp, ret);
+ else
+ uinfo("clear_halt done: devnum %d endp %d\n",
+ urb->dev->devnum, target_endp);
+
+ return ret;
+}
+
+static int tweak_set_interface_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+ __u16 alternate;
+ __u16 interface;
+ int ret;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+ alternate = le16_to_cpu(req->wValue);
+ interface = le16_to_cpu(req->wIndex);
+
+ dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate);
+
+ ret = usb_set_interface(urb->dev, interface, alternate);
+ if (ret < 0)
+ uinfo("set_interface error: inf %u alt %u, %d\n",
+ interface, alternate, ret);
+ else
+ uinfo("set_interface done: inf %u alt %u\n",
+ interface,
+ alternate);
+
+ return ret;
+}
+
+static int tweak_set_configuration_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+ __u16 config;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+ config = le16_to_cpu(req->wValue);
+
+ /*
+ * I have never seen a multi-config device. Very rare.
+ * For most devices, this will be called to choose a default
+ * configuration only once in an initialization phase.
+ *
+ * set_configuration may change a device configuration and its device
+ * drivers will be unbound and assigned for a new device configuration.
+ * This means this usbip driver will be also unbound when called, then
+ * eventually reassigned to the device as far as driver matching
+ * condition is kept.
+ *
+ * Unfortunatelly, an existing usbip connection will be dropped
+ * due to this driver unbinding. So, skip here.
+ * A user may need to set a special configuration value before
+ * exporting the device.
+ */
+ uinfo("set_configuration (%d) to %s\n", config, urb->dev->dev.bus_id);
+ uinfo("but, skip!\n");
+
+ return 0;
+ /* return usb_driver_set_configuration(urb->dev, config); */
+}
+
+static int tweak_reset_device_cmd(struct urb *urb)
+{
+ struct usb_ctrlrequest *req;
+ __u16 value;
+ __u16 index;
+ int ret;
+
+ req = (struct usb_ctrlrequest *) urb->setup_packet;
+ value = le16_to_cpu(req->wValue);
+ index = le16_to_cpu(req->wIndex);
+
+ uinfo("reset_device (port %d) to %s\n", index, urb->dev->dev.bus_id);
+
+ /* all interfaces should be owned by usbip driver, so just reset it. */
+ ret = usb_lock_device_for_reset(urb->dev, NULL);
+ if (ret < 0) {
+ dev_err(&urb->dev->dev, "lock for reset\n");
+ return ret;
+ }
+
+ /* try to reset the device */
+ ret = usb_reset_device(urb->dev);
+ if (ret < 0)
+ dev_err(&urb->dev->dev, "device reset\n");
+
+ usb_unlock_device(urb->dev);
+
+ return ret;
+}
+
+/*
+ * clear_halt, set_interface, and set_configuration require special tricks.
+ */
+static void tweak_special_requests(struct urb *urb)
+{
+ if (!urb || !urb->setup_packet)
+ return;
+
+ if (usb_pipetype(urb->pipe) != PIPE_CONTROL)
+ return;
+
+ if (is_clear_halt_cmd(urb))
+ /* tweak clear_halt */
+ tweak_clear_halt_cmd(urb);
+
+ else if (is_set_interface_cmd(urb))
+ /* tweak set_interface */
+ tweak_set_interface_cmd(urb);
+
+ else if (is_set_configuration_cmd(urb))
+ /* tweak set_configuration */
+ tweak_set_configuration_cmd(urb);
+
+ else if (is_reset_device_cmd(urb))
+ tweak_reset_device_cmd(urb);
+ else
+ dbg_stub_rx("no need to tweak\n");
+}
+
+/*
+ * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb().
+ * By unlinking the urb asynchronously, stub_rx can continuously
+ * process coming urbs. Even if the urb is unlinked, its completion
+ * handler will be called and stub_tx will send a return pdu.
+ *
+ * See also comments about unlinking strategy in vhci_hcd.c.
+ */
+static int stub_recv_cmd_unlink(struct stub_device *sdev,
+ struct usbip_header *pdu)
+{
+ struct list_head *listhead = &sdev->priv_init;
+ struct list_head *ptr;
+ unsigned long flags;
+
+ struct stub_priv *priv;
+
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) {
+ priv = list_entry(ptr, struct stub_priv, list);
+ if (priv->seqnum == pdu->u.cmd_unlink.seqnum) {
+ int ret;
+
+ dev_info(&priv->urb->dev->dev, "unlink urb %p\n",
+ priv->urb);
+
+ /*
+ * This matched urb is not completed yet (i.e., be in
+ * flight in usb hcd hardware/driver). Now we are
+ * cancelling it. The unlinking flag means that we are
+ * now not going to return the normal result pdu of a
+ * submission request, but going to return a result pdu
+ * of the unlink request.
+ */
+ priv->unlinking = 1;
+
+ /*
+ * In the case that unlinking flag is on, prev->seqnum
+ * is changed from the seqnum of the cancelling urb to
+ * the seqnum of the unlink request. This will be used
+ * to make the result pdu of the unlink request.
+ */
+ priv->seqnum = pdu->base.seqnum;
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ /*
+ * usb_unlink_urb() is now out of spinlocking to avoid
+ * spinlock recursion since stub_complete() is
+ * sometimes called in this context but not in the
+ * interrupt context. If stub_complete() is executed
+ * before we call usb_unlink_urb(), usb_unlink_urb()
+ * will return an error value. In this case, stub_tx
+ * will return the result pdu of this unlink request
+ * though submission is completed and actual unlinking
+ * is not executed. OK?
+ */
+ /* In the above case, urb->status is not -ECONNRESET,
+ * so a driver in a client host will know the failure
+ * of the unlink request ?
+ */
+ ret = usb_unlink_urb(priv->urb);
+ if (ret != -EINPROGRESS)
+ dev_err(&priv->urb->dev->dev,
+ "failed to unlink a urb %p, ret %d\n",
+ priv->urb, ret);
+ return 0;
+ }
+ }
+
+ dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum);
+
+ /*
+ * The urb of the unlink target is not found in priv_init queue. It was
+ * already completed and its results is/was going to be sent by a
+ * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only
+ * return the completeness of this unlink request to vhci_hcd.
+ */
+ stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0);
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+
+ return 0;
+}
+
+static int valid_request(struct stub_device *sdev, struct usbip_header *pdu)
+{
+ struct usbip_device *ud = &sdev->ud;
+
+ if (pdu->base.devid == sdev->devid) {
+ spin_lock(&ud->lock);
+ if (ud->status == SDEV_ST_USED) {
+ /* A request is valid. */
+ spin_unlock(&ud->lock);
+ return 1;
+ }
+ spin_unlock(&ud->lock);
+ }
+
+ return 0;
+}
+
+static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
+ struct usbip_header *pdu)
+{
+ struct stub_priv *priv;
+ struct usbip_device *ud = &sdev->ud;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC);
+ if (!priv) {
+ dev_err(&sdev->interface->dev, "alloc stub_priv\n");
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+ return NULL;
+ }
+
+ memset(priv, 0, sizeof(struct stub_priv));
+
+ priv->seqnum = pdu->base.seqnum;
+ priv->sdev = sdev;
+
+ /*
+ * After a stub_priv is linked to a list_head,
+ * our error handler can free allocated data.
+ */
+ list_add_tail(&priv->list, &sdev->priv_init);
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ return priv;
+}
+
+
+static struct usb_host_endpoint *get_ep_from_epnum(struct usb_device *udev,
+ int epnum0)
+{
+ struct usb_host_config *config;
+ int i = 0, j = 0;
+ struct usb_host_endpoint *ep = NULL;
+ int epnum;
+ int found = 0;
+
+ if (epnum0 == 0)
+ return &udev->ep0;
+
+ config = udev->actconfig;
+ if (!config)
+ return NULL;
+
+ for (i = 0; i < config->desc.bNumInterfaces; i++) {
+ struct usb_host_interface *setting;
+
+ setting = config->interface[i]->cur_altsetting;
+
+ for (j = 0; j < setting->desc.bNumEndpoints; j++) {
+ ep = &setting->endpoint[j];
+ epnum = (ep->desc.bEndpointAddress & 0x7f);
+
+ if (epnum == epnum0) {
+ /* uinfo("found epnum %d\n", epnum0); */
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ return ep;
+ else
+ return NULL;
+}
+
+
+static int get_pipe(struct stub_device *sdev, int epnum, int dir)
+{
+ struct usb_device *udev = interface_to_usbdev(sdev->interface);
+ struct usb_host_endpoint *ep;
+ struct usb_endpoint_descriptor *epd = NULL;
+
+ ep = get_ep_from_epnum(udev, epnum);
+ if (!ep) {
+ dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
+ epnum);
+ BUG();
+ }
+
+ epd = &ep->desc;
+
+
+#if 0
+ /* epnum 0 is always control */
+ if (epnum == 0) {
+ if (dir == USBIP_DIR_OUT)
+ return usb_sndctrlpipe(udev, 0);
+ else
+ return usb_rcvctrlpipe(udev, 0);
+ }
+#endif
+
+ if (usb_endpoint_xfer_control(epd)) {
+ if (dir == USBIP_DIR_OUT)
+ return usb_sndctrlpipe(udev, epnum);
+ else
+ return usb_rcvctrlpipe(udev, epnum);
+ }
+
+ if (usb_endpoint_xfer_bulk(epd)) {
+ if (dir == USBIP_DIR_OUT)
+ return usb_sndbulkpipe(udev, epnum);
+ else
+ return usb_rcvbulkpipe(udev, epnum);
+ }
+
+ if (usb_endpoint_xfer_int(epd)) {
+ if (dir == USBIP_DIR_OUT)
+ return usb_sndintpipe(udev, epnum);
+ else
+ return usb_rcvintpipe(udev, epnum);
+ }
+
+ if (usb_endpoint_xfer_isoc(epd)) {
+ if (dir == USBIP_DIR_OUT)
+ return usb_sndisocpipe(udev, epnum);
+ else
+ return usb_rcvisocpipe(udev, epnum);
+ }
+
+ /* NOT REACHED */
+ dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum);
+ return 0;
+}
+
+static void stub_recv_cmd_submit(struct stub_device *sdev,
+ struct usbip_header *pdu)
+{
+ int ret;
+ struct stub_priv *priv;
+ struct usbip_device *ud = &sdev->ud;
+ struct usb_device *udev = interface_to_usbdev(sdev->interface);
+ int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction);
+
+
+ priv = stub_priv_alloc(sdev, pdu);
+ if (!priv)
+ return;
+
+ /* setup a urb */
+ if (usb_pipeisoc(pipe))
+ priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets,
+ GFP_KERNEL);
+ else
+ priv->urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (!priv->urb) {
+ dev_err(&sdev->interface->dev, "malloc urb\n");
+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+ return;
+ }
+
+ /* set priv->urb->transfer_buffer */
+ if (pdu->u.cmd_submit.transfer_buffer_length > 0) {
+ priv->urb->transfer_buffer =
+ kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
+ GFP_KERNEL);
+ if (!priv->urb->transfer_buffer) {
+ dev_err(&sdev->interface->dev, "malloc x_buff\n");
+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+ return;
+ }
+ }
+
+ /* set priv->urb->setup_packet */
+ priv->urb->setup_packet = kzalloc(8, GFP_KERNEL);
+ if (!priv->urb->setup_packet) {
+ dev_err(&sdev->interface->dev, "allocate setup_packet\n");
+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+ return;
+ }
+ memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8);
+
+ /* set other members from the base header of pdu */
+ priv->urb->context = (void *) priv;
+ priv->urb->dev = udev;
+ priv->urb->pipe = pipe;
+ priv->urb->complete = stub_complete;
+
+ usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0);
+
+
+ if (usbip_recv_xbuff(ud, priv->urb) < 0)
+ return;
+
+ if (usbip_recv_iso(ud, priv->urb) < 0)
+ return;
+
+ /* no need to submit an intercepted request, but harmless? */
+ tweak_special_requests(priv->urb);
+
+ /* urb is now ready to submit */
+ ret = usb_submit_urb(priv->urb, GFP_KERNEL);
+
+ if (ret == 0)
+ dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum);
+ else {
+ dev_err(&sdev->interface->dev, "submit_urb error, %d\n", ret);
+ usbip_dump_header(pdu);
+ usbip_dump_urb(priv->urb);
+
+ /*
+ * Pessimistic.
+ * This connection will be discarded.
+ */
+ usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
+ }
+
+ dbg_stub_rx("Leave\n");
+ return;
+}
+
+/* recv a pdu */
+static void stub_rx_pdu(struct usbip_device *ud)
+{
+ int ret;
+ struct usbip_header pdu;
+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+ struct device *dev = &sdev->interface->dev;
+
+ dbg_stub_rx("Enter\n");
+
+ memset(&pdu, 0, sizeof(pdu));
+
+ /* 1. receive a pdu header */
+ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+ if (ret != sizeof(pdu)) {
+ dev_err(dev, "recv a header, %d\n", ret);
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+ return;
+ }
+
+ usbip_header_correct_endian(&pdu, 0);
+
+ if (dbg_flag_stub_rx)
+ usbip_dump_header(&pdu);
+
+ if (!valid_request(sdev, &pdu)) {
+ dev_err(dev, "recv invalid request\n");
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+ return;
+ }
+
+ switch (pdu.base.command) {
+ case USBIP_CMD_UNLINK:
+ stub_recv_cmd_unlink(sdev, &pdu);
+ break;
+
+ case USBIP_CMD_SUBMIT:
+ stub_recv_cmd_submit(sdev, &pdu);
+ break;
+
+ default:
+ /* NOTREACHED */
+ dev_err(dev, "unknown pdu\n");
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+ return;
+ }
+
+}
+
+void stub_rx_loop(struct usbip_task *ut)
+{
+ struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
+
+ while (1) {
+ if (signal_pending(current)) {
+ dbg_stub_rx("signal caught!\n");
+ break;
+ }
+
+ if (usbip_event_happend(ud))
+ break;
+
+ stub_rx_pdu(ud);
+ }
+}
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
new file mode 100644
index 00000000000..d5563cd980b
--- /dev/null
+++ b/drivers/staging/usbip/stub_tx.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "stub.h"
+
+
+static void stub_free_priv_and_urb(struct stub_priv *priv)
+{
+ struct urb *urb = priv->urb;
+
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
+ list_del(&priv->list);
+ kmem_cache_free(stub_priv_cache, priv);
+ usb_free_urb(urb);
+}
+
+/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */
+void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
+ __u32 status)
+{
+ struct stub_unlink *unlink;
+
+ unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC);
+ if (!unlink) {
+ dev_err(&sdev->interface->dev, "alloc stub_unlink\n");
+ usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC);
+ return;
+ }
+
+ unlink->seqnum = seqnum;
+ unlink->status = status;
+
+ list_add_tail(&unlink->list, &sdev->unlink_tx);
+}
+
+/**
+ * stub_complete - completion handler of a usbip urb
+ * @urb: pointer to the urb completed
+ * @regs:
+ *
+ * When a urb has completed, the USB core driver calls this function mostly in
+ * the interrupt context. To return the result of a urb, the completed urb is
+ * linked to the pending list of returning.
+ *
+ */
+void stub_complete(struct urb *urb)
+{
+ struct stub_priv *priv = (struct stub_priv *) urb->context;
+ struct stub_device *sdev = priv->sdev;
+ unsigned long flags;
+
+ dbg_stub_tx("complete! status %d\n", urb->status);
+
+
+ switch (urb->status) {
+ case 0:
+ /* OK */
+ break;
+ case -ENOENT:
+ uinfo("stopped by a call of usb_kill_urb() because of"
+ "cleaning up a virtual connection\n");
+ return;
+ case -ECONNRESET:
+ uinfo("unlinked by a call of usb_unlink_urb()\n");
+ break;
+ case -EPIPE:
+ uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe));
+ break;
+ case -ESHUTDOWN:
+ uinfo("device removed?\n");
+ break;
+ default:
+ uinfo("urb completion with non-zero status %d\n", urb->status);
+ }
+
+ /* link a urb to the queue of tx. */
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ if (priv->unlinking) {
+ stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
+ stub_free_priv_and_urb(priv);
+ } else
+ list_move_tail(&priv->list, &sdev->priv_tx);
+
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ /* wake up tx_thread */
+ wake_up(&sdev->tx_waitq);
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* fill PDU */
+
+static inline void setup_base_pdu(struct usbip_header_basic *base,
+ __u32 command, __u32 seqnum)
+{
+ base->command = command;
+ base->seqnum = seqnum;
+ base->devid = 0;
+ base->ep = 0;
+ base->direction = 0;
+}
+
+static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb)
+{
+ struct stub_priv *priv = (struct stub_priv *) urb->context;
+
+ setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum);
+
+ usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1);
+}
+
+static void setup_ret_unlink_pdu(struct usbip_header *rpdu,
+ struct stub_unlink *unlink)
+{
+ setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum);
+
+ rpdu->u.ret_unlink.status = unlink->status;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* send RET_SUBMIT */
+
+static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev)
+{
+ unsigned long flags;
+ struct stub_priv *priv, *tmp;
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) {
+ list_move_tail(&priv->list, &sdev->priv_free);
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return priv;
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ return NULL;
+}
+
+static int stub_send_ret_submit(struct stub_device *sdev)
+{
+ unsigned long flags;
+ struct stub_priv *priv, *tmp;
+
+ struct msghdr msg;
+ struct kvec iov[3];
+ size_t txsize;
+
+ size_t total_size = 0;
+
+ while ((priv = dequeue_from_priv_tx(sdev)) != NULL) {
+ int ret;
+ struct urb *urb = priv->urb;
+ struct usbip_header pdu_header;
+ void *iso_buffer = NULL;
+
+ txsize = 0;
+ memset(&pdu_header, 0, sizeof(pdu_header));
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov, 0, sizeof(iov));
+
+ dbg_stub_tx("setup txdata urb %p\n", urb);
+
+
+ /* 1. setup usbip_header */
+ setup_ret_submit_pdu(&pdu_header, urb);
+ usbip_header_correct_endian(&pdu_header, 1);
+
+ iov[0].iov_base = &pdu_header;
+ iov[0].iov_len = sizeof(pdu_header);
+ txsize += sizeof(pdu_header);
+
+ /* 2. setup transfer buffer */
+ if (usb_pipein(urb->pipe) && urb->actual_length > 0) {
+ iov[1].iov_base = urb->transfer_buffer;
+ iov[1].iov_len = urb->actual_length;
+ txsize += urb->actual_length;
+ }
+
+ /* 3. setup iso_packet_descriptor */
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+ ssize_t len = 0;
+
+ iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
+ if (!iso_buffer) {
+ usbip_event_add(&sdev->ud,
+ SDEV_EVENT_ERROR_MALLOC);
+ return -1;
+ }
+
+ iov[2].iov_base = iso_buffer;
+ iov[2].iov_len = len;
+ txsize += len;
+ }
+
+ ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
+ 3, txsize);
+ if (ret != txsize) {
+ dev_err(&sdev->interface->dev,
+ "sendmsg failed!, retval %d for %zd\n",
+ ret, txsize);
+ kfree(iso_buffer);
+ usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+ return -1;
+ }
+
+ kfree(iso_buffer);
+ dbg_stub_tx("send txdata\n");
+
+ total_size += txsize;
+ }
+
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
+ stub_free_priv_and_urb(priv);
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ return total_size;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* send RET_UNLINK */
+
+static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev)
+{
+ unsigned long flags;
+ struct stub_unlink *unlink, *tmp;
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
+ list_move_tail(&unlink->list, &sdev->unlink_free);
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+ return unlink;
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ return NULL;
+}
+
+
+static int stub_send_ret_unlink(struct stub_device *sdev)
+{
+ unsigned long flags;
+ struct stub_unlink *unlink, *tmp;
+
+ struct msghdr msg;
+ struct kvec iov[1];
+ size_t txsize;
+
+ size_t total_size = 0;
+
+ while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) {
+ int ret;
+ struct usbip_header pdu_header;
+
+ txsize = 0;
+ memset(&pdu_header, 0, sizeof(pdu_header));
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov, 0, sizeof(iov));
+
+ dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum);
+
+ /* 1. setup usbip_header */
+ setup_ret_unlink_pdu(&pdu_header, unlink);
+ usbip_header_correct_endian(&pdu_header, 1);
+
+ iov[0].iov_base = &pdu_header;
+ iov[0].iov_len = sizeof(pdu_header);
+ txsize += sizeof(pdu_header);
+
+ ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
+ 1, txsize);
+ if (ret != txsize) {
+ dev_err(&sdev->interface->dev,
+ "sendmsg failed!, retval %d for %zd\n",
+ ret, txsize);
+ usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+ return -1;
+ }
+
+
+ dbg_stub_tx("send txdata\n");
+
+ total_size += txsize;
+ }
+
+
+ spin_lock_irqsave(&sdev->priv_lock, flags);
+
+ list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) {
+ list_del(&unlink->list);
+ kfree(unlink);
+ }
+
+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+ return total_size;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+void stub_tx_loop(struct usbip_task *ut)
+{
+ struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+
+ while (1) {
+ if (signal_pending(current)) {
+ dbg_stub_tx("signal catched\n");
+ break;
+ }
+
+ if (usbip_event_happend(ud))
+ break;
+
+ /*
+ * send_ret_submit comes earlier than send_ret_unlink. stub_rx
+ * looks at only priv_init queue. If the completion of a URB is
+ * earlier than the receive of CMD_UNLINK, priv is moved to
+ * priv_tx queue and stub_rx does not find the target priv. In
+ * this case, vhci_rx receives the result of the submit request
+ * and then receives the result of the unlink request. The
+ * result of the submit is given back to the usbcore as the
+ * completion of the unlink request. The request of the
+ * unlink is ignored. This is ok because a driver who calls
+ * usb_unlink_urb() understands the unlink was too late by
+ * getting the status of the given-backed URB which has the
+ * status of usb_submit_urb().
+ */
+ if (stub_send_ret_submit(sdev) < 0)
+ break;
+
+ if (stub_send_ret_unlink(sdev) < 0)
+ break;
+
+ wait_event_interruptible(sdev->tx_waitq,
+ (!list_empty(&sdev->priv_tx) ||
+ !list_empty(&sdev->unlink_tx)));
+ }
+}
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
new file mode 100644
index 00000000000..e64918f42ff
--- /dev/null
+++ b/drivers/staging/usbip/usbip_common.c
@@ -0,0 +1,997 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include "usbip_common.h"
+
+/* version information */
+#define DRIVER_VERSION "1.0"
+#define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi _at_ users.sourceforge.net>"
+#define DRIVER_DESC "usbip common driver"
+
+/*-------------------------------------------------------------------------*/
+/* debug routines */
+
+#ifdef CONFIG_USB_DEBUG
+unsigned long usbip_debug_flag = 0xffffffff;
+#else
+unsigned long usbip_debug_flag;
+#endif
+EXPORT_SYMBOL_GPL(usbip_debug_flag);
+
+
+/* FIXME */
+struct device_attribute dev_attr_usbip_debug;
+EXPORT_SYMBOL_GPL(dev_attr_usbip_debug);
+
+
+static ssize_t show_flag(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%lx\n", usbip_debug_flag);
+}
+
+static ssize_t store_flag(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long flag;
+
+ sscanf(buf, "%lx", &flag);
+ usbip_debug_flag = flag;
+
+ return count;
+}
+DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag);
+
+static void usbip_dump_buffer(char *buff, int bufflen)
+{
+ int i;
+
+ if (bufflen > 128) {
+ for (i = 0; i < 128; i++) {
+ if (i%24 == 0)
+ printk(" ");
+ printk("%02x ", (unsigned char) buff[i]);
+ if (i%4 == 3)
+ printk("| ");
+ if (i%24 == 23)
+ printk("\n");
+ }
+ printk("... (%d byte)\n", bufflen);
+ return;
+ }
+
+ for (i = 0; i < bufflen; i++) {
+ if (i%24 == 0)
+ printk(" ");
+ printk("%02x ", (unsigned char) buff[i]);
+ if (i%4 == 3)
+ printk("| ");
+ if (i%24 == 23)
+ printk("\n");
+ }
+ printk("\n");
+
+}
+
+static void usbip_dump_pipe(unsigned int p)
+{
+ unsigned char type = usb_pipetype(p);
+ unsigned char ep = usb_pipeendpoint(p);
+ unsigned char dev = usb_pipedevice(p);
+ unsigned char dir = usb_pipein(p);
+
+ printk("dev(%d) ", dev);
+ printk("ep(%d) ", ep);
+ printk("%s ", dir ? "IN" : "OUT");
+
+ switch (type) {
+ case PIPE_ISOCHRONOUS:
+ printk("%s ", "ISO");
+ break;
+ case PIPE_INTERRUPT:
+ printk("%s ", "INT");
+ break;
+ case PIPE_CONTROL:
+ printk("%s ", "CTL");
+ break;
+ case PIPE_BULK:
+ printk("%s ", "BLK");
+ break;
+ default:
+ printk("ERR");
+ }
+
+ printk("\n");
+
+}
+
+static void usbip_dump_usb_device(struct usb_device *udev)
+{
+ struct device *dev = &udev->dev;
+ int i;
+
+ dev_dbg(dev, " devnum(%d) devpath(%s)",
+ udev->devnum, udev->devpath);
+
+ switch (udev->speed) {
+ case USB_SPEED_HIGH:
+ printk(" SPD_HIGH");
+ break;
+ case USB_SPEED_FULL:
+ printk(" SPD_FULL");
+ break;
+ case USB_SPEED_LOW:
+ printk(" SPD_LOW");
+ break;
+ case USB_SPEED_UNKNOWN:
+ printk(" SPD_UNKNOWN");
+ break;
+ default:
+ printk(" SPD_ERROR");
+ }
+
+ printk(" tt %p, ttport %d", udev->tt, udev->ttport);
+ printk("\n");
+
+ dev_dbg(dev, " ");
+ for (i = 0; i < 16; i++)
+ printk(" %2u", i);
+ printk("\n");
+
+ dev_dbg(dev, " toggle0(IN) :");
+ for (i = 0; i < 16; i++)
+ printk(" %2u", (udev->toggle[0] & (1 << i)) ? 1 : 0);
+ printk("\n");
+
+ dev_dbg(dev, " toggle1(OUT):");
+ for (i = 0; i < 16; i++)
+ printk(" %2u", (udev->toggle[1] & (1 << i)) ? 1 : 0);
+ printk("\n");
+
+
+ dev_dbg(dev, " epmaxp_in :");
+ for (i = 0; i < 16; i++) {
+ if (udev->ep_in[i])
+ printk(" %2u",
+ le16_to_cpu(udev->ep_in[i]->desc.wMaxPacketSize));
+ }
+ printk("\n");
+
+ dev_dbg(dev, " epmaxp_out :");
+ for (i = 0; i < 16; i++) {
+ if (udev->ep_out[i])
+ printk(" %2u",
+ le16_to_cpu(udev->ep_out[i]->desc.wMaxPacketSize));
+ }
+ printk("\n");
+
+ dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus);
+
+ dev_dbg(dev, "descriptor %p, config %p, actconfig %p, "
+ "rawdescriptors %p\n", &udev->descriptor, udev->config,
+ udev->actconfig, udev->rawdescriptors);
+
+ dev_dbg(dev, "have_langid %d, string_langid %d\n",
+ udev->have_langid, udev->string_langid);
+
+ dev_dbg(dev, "maxchild %d, children %p\n",
+ udev->maxchild, udev->children);
+}
+
+static void usbip_dump_request_type(__u8 rt)
+{
+ switch (rt & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ printk("DEVICE");
+ break;
+ case USB_RECIP_INTERFACE:
+ printk("INTERF");
+ break;
+ case USB_RECIP_ENDPOINT:
+ printk("ENDPOI");
+ break;
+ case USB_RECIP_OTHER:
+ printk("OTHER ");
+ break;
+ default:
+ printk("------");
+ }
+}
+
+static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
+{
+ if (!cmd) {
+ printk(" %s : null pointer\n", __FUNCTION__);
+ return;
+ }
+
+ printk(" ");
+ printk("bRequestType(%02X) ", cmd->bRequestType);
+ printk("bRequest(%02X) " , cmd->bRequest);
+ printk("wValue(%04X) ", cmd->wValue);
+ printk("wIndex(%04X) ", cmd->wIndex);
+ printk("wLength(%04X) ", cmd->wLength);
+
+ printk("\n ");
+
+ if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+ printk("STANDARD ");
+ switch (cmd->bRequest) {
+ case USB_REQ_GET_STATUS:
+ printk("GET_STATUS");
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ printk("CLEAR_FEAT");
+ break;
+ case USB_REQ_SET_FEATURE:
+ printk("SET_FEAT ");
+ break;
+ case USB_REQ_SET_ADDRESS:
+ printk("SET_ADDRRS");
+ break;
+ case USB_REQ_GET_DESCRIPTOR:
+ printk("GET_DESCRI");
+ break;
+ case USB_REQ_SET_DESCRIPTOR:
+ printk("SET_DESCRI");
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ printk("GET_CONFIG");
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ printk("SET_CONFIG");
+ break;
+ case USB_REQ_GET_INTERFACE:
+ printk("GET_INTERF");
+ break;
+ case USB_REQ_SET_INTERFACE:
+ printk("SET_INTERF");
+ break;
+ case USB_REQ_SYNCH_FRAME:
+ printk("SYNC_FRAME");
+ break;
+ default:
+ printk("REQ(%02X) ", cmd->bRequest);
+ }
+
+ printk(" ");
+ usbip_dump_request_type(cmd->bRequestType);
+
+ } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ printk("CLASS ");
+
+ else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR)
+ printk("VENDOR ");
+
+ else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED)
+ printk("RESERVED");
+
+ printk("\n");
+}
+
+void usbip_dump_urb(struct urb *urb)
+{
+ struct device *dev;
+
+ if (!urb) {
+ printk(KERN_DEBUG KBUILD_MODNAME
+ ":%s: urb: null pointer!!\n", __func__);
+ return;
+ }
+
+ if (!urb->dev) {
+ printk(KERN_DEBUG KBUILD_MODNAME
+ ":%s: urb->dev: null pointer!!\n", __func__);
+ return;
+ }
+ dev = &urb->dev->dev;
+
+ dev_dbg(dev, " urb :%p\n", urb);
+ dev_dbg(dev, " dev :%p\n", urb->dev);
+
+ usbip_dump_usb_device(urb->dev);
+
+ dev_dbg(dev, " pipe :%08x ", urb->pipe);
+
+ usbip_dump_pipe(urb->pipe);
+
+ dev_dbg(dev, " status :%d\n", urb->status);
+ dev_dbg(dev, " transfer_flags :%08X\n", urb->transfer_flags);
+ dev_dbg(dev, " transfer_buffer :%p\n", urb->transfer_buffer);
+ dev_dbg(dev, " transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+ dev_dbg(dev, " actual_length :%d\n", urb->actual_length);
+ dev_dbg(dev, " setup_packet :%p\n", urb->setup_packet);
+
+ if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL)
+ usbip_dump_usb_ctrlrequest(
+ (struct usb_ctrlrequest *)urb->setup_packet);
+
+ dev_dbg(dev, " start_frame :%d\n", urb->start_frame);
+ dev_dbg(dev, " number_of_packets :%d\n", urb->number_of_packets);
+ dev_dbg(dev, " interval :%d\n", urb->interval);
+ dev_dbg(dev, " error_count :%d\n", urb->error_count);
+ dev_dbg(dev, " context :%p\n", urb->context);
+ dev_dbg(dev, " complete :%p\n", urb->complete);
+}
+EXPORT_SYMBOL_GPL(usbip_dump_urb);
+
+void usbip_dump_header(struct usbip_header *pdu)
+{
+ udbg("BASE: cmd %u seq %u devid %u dir %u ep %u\n",
+ pdu->base.command,
+ pdu->base.seqnum,
+ pdu->base.devid,
+ pdu->base.direction,
+ pdu->base.ep);
+
+ switch (pdu->base.command) {
+ case USBIP_CMD_SUBMIT:
+ udbg("CMD_SUBMIT: x_flags %u x_len %u sf %u #p %u iv %u\n",
+ pdu->u.cmd_submit.transfer_flags,
+ pdu->u.cmd_submit.transfer_buffer_length,
+ pdu->u.cmd_submit.start_frame,
+ pdu->u.cmd_submit.number_of_packets,
+ pdu->u.cmd_submit.interval);
+ break;
+ case USBIP_CMD_UNLINK:
+ udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum);
+ break;
+ case USBIP_RET_SUBMIT:
+ udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n",
+ pdu->u.ret_submit.status,
+ pdu->u.ret_submit.actual_length,
+ pdu->u.ret_submit.start_frame,
+ pdu->u.ret_submit.error_count);
+ case USBIP_RET_UNLINK:
+ udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status);
+ break;
+ default:
+ /* NOT REACHED */
+ udbg("UNKNOWN\n");
+ }
+}
+EXPORT_SYMBOL_GPL(usbip_dump_header);
+
+
+/*-------------------------------------------------------------------------*/
+/* thread routines */
+
+int usbip_thread(void *param)
+{
+ struct usbip_task *ut = param;
+
+ if (!ut)
+ return -EINVAL;
+
+ lock_kernel();
+ daemonize(ut->name);
+ allow_signal(SIGKILL);
+ ut->thread = current;
+ unlock_kernel();
+
+ /* srv.rb must wait for rx_thread starting */
+ complete(&ut->thread_done);
+
+ /* start of while loop */
+ ut->loop_ops(ut);
+
+ /* end of loop */
+ ut->thread = NULL;
+
+ complete_and_exit(&ut->thread_done, 0);
+}
+
+void usbip_start_threads(struct usbip_device *ud)
+{
+ /*
+ * threads are invoked per one device (per one connection).
+ */
+ kernel_thread(usbip_thread, (void *)&ud->tcp_rx, 0);
+ kernel_thread(usbip_thread, (void *)&ud->tcp_tx, 0);
+
+ /* confirm threads are starting */
+ wait_for_completion(&ud->tcp_rx.thread_done);
+ wait_for_completion(&ud->tcp_tx.thread_done);
+}
+EXPORT_SYMBOL_GPL(usbip_start_threads);
+
+void usbip_stop_threads(struct usbip_device *ud)
+{
+ /* kill threads related to this sdev, if v.c. exists */
+ if (ud->tcp_rx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+ wait_for_completion(&ud->tcp_rx.thread_done);
+ udbg("rx_thread for ud %p has finished\n", ud);
+ }
+
+ if (ud->tcp_tx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+ wait_for_completion(&ud->tcp_tx.thread_done);
+ udbg("tx_thread for ud %p has finished\n", ud);
+ }
+}
+EXPORT_SYMBOL_GPL(usbip_stop_threads);
+
+void usbip_task_init(struct usbip_task *ut, char *name,
+ void (*loop_ops)(struct usbip_task *))
+{
+ ut->thread = NULL;
+ init_completion(&ut->thread_done);
+ ut->name = name;
+ ut->loop_ops = loop_ops;
+}
+EXPORT_SYMBOL_GPL(usbip_task_init);
+
+
+/*-------------------------------------------------------------------------*/
+/* socket routines */
+
+ /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */
+int usbip_xmit(int send, struct socket *sock, char *buf,
+ int size, int msg_flags)
+{
+ int result;
+ struct msghdr msg;
+ struct kvec iov;
+ int total = 0;
+
+ /* for blocks of if (dbg_flag_xmit) */
+ char *bp = buf;
+ int osize = size;
+
+ dbg_xmit("enter\n");
+
+ if (!sock || !buf || !size) {
+ printk(KERN_ERR "%s: invalid arg, sock %p buff %p size %d\n",
+ __func__, sock, buf, size);
+ return -EINVAL;
+ }
+
+
+ if (dbg_flag_xmit) {
+ if (send) {
+ if (!in_interrupt())
+ printk(KERN_DEBUG "%-10s:", current->comm);
+ else
+ printk(KERN_DEBUG "interupt :");
+
+ printk("%s: sending... , sock %p, buf %p, "
+ "size %d, msg_flags %d\n", __func__,
+ sock, buf, size, msg_flags);
+ usbip_dump_buffer(buf, size);
+ }
+ }
+
+
+ do {
+ sock->sk->sk_allocation = GFP_NOIO;
+ iov.iov_base = buf;
+ iov.iov_len = size;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = msg_flags | MSG_NOSIGNAL;
+
+ if (send)
+ result = kernel_sendmsg(sock, &msg, &iov, 1, size);
+ else
+ result = kernel_recvmsg(sock, &msg, &iov, 1, size,
+ MSG_WAITALL);
+
+ if (result <= 0) {
+ udbg("usbip_xmit: %s sock %p buf %p size %u ret %d"
+ " total %d\n",
+ send ? "send" : "receive", sock, buf,
+ size, result, total);
+ goto err;
+ }
+
+ size -= result;
+ buf += result;
+ total += result;
+
+ } while (size > 0);
+
+
+ if (dbg_flag_xmit) {
+ if (!send) {
+ if (!in_interrupt())
+ printk(KERN_DEBUG "%-10s:", current->comm);
+ else
+ printk(KERN_DEBUG "interupt :");
+
+ printk("usbip_xmit: receiving....\n");
+ usbip_dump_buffer(bp, osize);
+ printk("usbip_xmit: received, osize %d ret %d size %d "
+ "total %d\n", osize, result, size,
+ total);
+ }
+
+ if (send)
+ printk("usbip_xmit: send, total %d\n", total);
+ }
+
+ return total;
+
+err:
+ return result;
+}
+EXPORT_SYMBOL_GPL(usbip_xmit);
+
+
+/* now a usrland utility should set options. */
+#if 0
+int setquickack(struct socket *socket)
+{
+ mm_segment_t oldfs;
+ int val = 1;
+ int ret;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK,
+ (char __user *) &val, sizeof(ret));
+ set_fs(oldfs);
+
+ return ret;
+}
+
+int setnodelay(struct socket *socket)
+{
+ mm_segment_t oldfs;
+ int val = 1;
+ int ret;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY,
+ (char __user *) &val, sizeof(ret));
+ set_fs(oldfs);
+
+ return ret;
+}
+
+int setkeepalive(struct socket *socket)
+{
+ mm_segment_t oldfs;
+ int val = 1;
+ int ret;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
+ (char __user *) &val, sizeof(ret));
+ set_fs(oldfs);
+
+ return ret;
+}
+
+void setreuse(struct socket *socket)
+{
+ socket->sk->sk_reuse = 1;
+}
+#endif
+
+struct socket *sockfd_to_socket(unsigned int sockfd)
+{
+ struct socket *socket;
+ struct file *file;
+ struct inode *inode;
+
+ file = fget(sockfd);
+ if (!file) {
+ printk(KERN_ERR "%s: invalid sockfd\n", __func__);
+ return NULL;
+ }
+
+ inode = file->f_dentry->d_inode;
+
+ if (!inode || !S_ISSOCK(inode->i_mode))
+ return NULL;
+
+ socket = SOCKET_I(inode);
+
+ return socket;
+}
+EXPORT_SYMBOL_GPL(sockfd_to_socket);
+
+
+
+/*-------------------------------------------------------------------------*/
+/* pdu routines */
+
+/* there may be more cases to tweak the flags. */
+static unsigned int tweak_transfer_flags(unsigned int flags)
+{
+
+ if (flags & URB_NO_TRANSFER_DMA_MAP)
+ /*
+ * vhci_hcd does not provide DMA-mapped I/O. The upper
+ * driver does not need to set this flag. The remote
+ * usbip.ko does not still perform DMA-mapped I/O for
+ * DMA-caplable host controllers. So, clear this flag.
+ */
+ flags &= ~URB_NO_TRANSFER_DMA_MAP;
+
+ if (flags & URB_NO_SETUP_DMA_MAP)
+ flags &= ~URB_NO_SETUP_DMA_MAP;
+
+ return flags;
+}
+
+static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
+ int pack)
+{
+ struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit;
+
+ /*
+ * Some members are not still implemented in usbip. I hope this issue
+ * will be discussed when usbip is ported to other operating systems.
+ */
+ if (pack) {
+ /* vhci_tx.c */
+ spdu->transfer_flags =
+ tweak_transfer_flags(urb->transfer_flags);
+ spdu->transfer_buffer_length = urb->transfer_buffer_length;
+ spdu->start_frame = urb->start_frame;
+ spdu->number_of_packets = urb->number_of_packets;
+ spdu->interval = urb->interval;
+ } else {
+ /* stub_rx.c */
+ urb->transfer_flags = spdu->transfer_flags;
+
+ urb->transfer_buffer_length = spdu->transfer_buffer_length;
+ urb->start_frame = spdu->start_frame;
+ urb->number_of_packets = spdu->number_of_packets;
+ urb->interval = spdu->interval;
+ }
+}
+
+static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
+ int pack)
+{
+ struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;
+
+ if (pack) {
+ /* stub_tx.c */
+
+ rpdu->status = urb->status;
+ rpdu->actual_length = urb->actual_length;
+ rpdu->start_frame = urb->start_frame;
+ rpdu->error_count = urb->error_count;
+ } else {
+ /* vhci_rx.c */
+
+ urb->status = rpdu->status;
+ urb->actual_length = rpdu->actual_length;
+ urb->start_frame = rpdu->start_frame;
+ urb->error_count = rpdu->error_count;
+ }
+}
+
+
+void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
+ int pack)
+{
+ switch (cmd) {
+ case USBIP_CMD_SUBMIT:
+ usbip_pack_cmd_submit(pdu, urb, pack);
+ break;
+ case USBIP_RET_SUBMIT:
+ usbip_pack_ret_submit(pdu, urb, pack);
+ break;
+ default:
+ err("unknown command");
+ /* NOTREACHED */
+ /* BUG(); */
+ }
+}
+EXPORT_SYMBOL_GPL(usbip_pack_pdu);
+
+
+static void correct_endian_basic(struct usbip_header_basic *base, int send)
+{
+ if (send) {
+ base->command = cpu_to_be32(base->command);
+ base->seqnum = cpu_to_be32(base->seqnum);
+ base->devid = cpu_to_be32(base->devid);
+ base->direction = cpu_to_be32(base->direction);
+ base->ep = cpu_to_be32(base->ep);
+ } else {
+ base->command = be32_to_cpu(base->command);
+ base->seqnum = be32_to_cpu(base->seqnum);
+ base->devid = be32_to_cpu(base->devid);
+ base->direction = be32_to_cpu(base->direction);
+ base->ep = be32_to_cpu(base->ep);
+ }
+}
+
+static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu,
+ int send)
+{
+ if (send) {
+ pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags);
+
+ cpu_to_be32s(&pdu->transfer_buffer_length);
+ cpu_to_be32s(&pdu->start_frame);
+ cpu_to_be32s(&pdu->number_of_packets);
+ cpu_to_be32s(&pdu->interval);
+ } else {
+ pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags);
+
+ be32_to_cpus(&pdu->transfer_buffer_length);
+ be32_to_cpus(&pdu->start_frame);
+ be32_to_cpus(&pdu->number_of_packets);
+ be32_to_cpus(&pdu->interval);
+ }
+}
+
+static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu,
+ int send)
+{
+ if (send) {
+ cpu_to_be32s(&pdu->status);
+ cpu_to_be32s(&pdu->actual_length);
+ cpu_to_be32s(&pdu->start_frame);
+ cpu_to_be32s(&pdu->error_count);
+ } else {
+ be32_to_cpus(&pdu->status);
+ be32_to_cpus(&pdu->actual_length);
+ be32_to_cpus(&pdu->start_frame);
+ be32_to_cpus(&pdu->error_count);
+ }
+}
+
+static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu,
+ int send)
+{
+ if (send)
+ pdu->seqnum = cpu_to_be32(pdu->seqnum);
+ else
+ pdu->seqnum = be32_to_cpu(pdu->seqnum);
+}
+
+static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu,
+ int send)
+{
+ if (send)
+ cpu_to_be32s(&pdu->status);
+ else
+ be32_to_cpus(&pdu->status);
+}
+
+void usbip_header_correct_endian(struct usbip_header *pdu, int send)
+{
+ __u32 cmd = 0;
+
+ if (send)
+ cmd = pdu->base.command;
+
+ correct_endian_basic(&pdu->base, send);
+
+ if (!send)
+ cmd = pdu->base.command;
+
+ switch (cmd) {
+ case USBIP_CMD_SUBMIT:
+ correct_endian_cmd_submit(&pdu->u.cmd_submit, send);
+ break;
+ case USBIP_RET_SUBMIT:
+ correct_endian_ret_submit(&pdu->u.ret_submit, send);
+ break;
+ case USBIP_CMD_UNLINK:
+ correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send);
+ break;
+ case USBIP_RET_UNLINK:
+ correct_endian_ret_unlink(&pdu->u.ret_unlink, send);
+ break;
+ default:
+ /* NOTREACHED */
+ err("unknown command in pdu header: %d", cmd);
+ /* BUG(); */
+ }
+}
+EXPORT_SYMBOL_GPL(usbip_header_correct_endian);
+
+static void usbip_iso_pakcet_correct_endian(
+ struct usbip_iso_packet_descriptor *iso,
+ int send)
+{
+ /* does not need all members. but copy all simply. */
+ if (send) {
+ iso->offset = cpu_to_be32(iso->offset);
+ iso->length = cpu_to_be32(iso->length);
+ iso->status = cpu_to_be32(iso->status);
+ iso->actual_length = cpu_to_be32(iso->actual_length);
+ } else {
+ iso->offset = be32_to_cpu(iso->offset);
+ iso->length = be32_to_cpu(iso->length);
+ iso->status = be32_to_cpu(iso->status);
+ iso->actual_length = be32_to_cpu(iso->actual_length);
+ }
+}
+
+static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,
+ struct usb_iso_packet_descriptor *uiso, int pack)
+{
+ if (pack) {
+ iso->offset = uiso->offset;
+ iso->length = uiso->length;
+ iso->status = uiso->status;
+ iso->actual_length = uiso->actual_length;
+ } else {
+ uiso->offset = iso->offset;
+ uiso->length = iso->length;
+ uiso->status = iso->status;
+ uiso->actual_length = iso->actual_length;
+ }
+}
+
+
+/* must free buffer */
+void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
+{
+ void *buff;
+ struct usbip_iso_packet_descriptor *iso;
+ int np = urb->number_of_packets;
+ ssize_t size = np * sizeof(*iso);
+ int i;
+
+ buff = kzalloc(size, GFP_KERNEL);
+ if (!buff)
+ return NULL;
+
+ for (i = 0; i < np; i++) {
+ iso = buff + (i * sizeof(*iso));
+
+ usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1);
+ usbip_iso_pakcet_correct_endian(iso, 1);
+ }
+
+ *bufflen = size;
+
+ return buff;
+}
+EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu);
+
+/* some members of urb must be substituted before. */
+int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
+{
+ void *buff;
+ struct usbip_iso_packet_descriptor *iso;
+ int np = urb->number_of_packets;
+ int size = np * sizeof(*iso);
+ int i;
+ int ret;
+
+ if (!usb_pipeisoc(urb->pipe))
+ return 0;
+
+ /* my Bluetooth dongle gets ISO URBs which are np = 0 */
+ if (np == 0) {
+ /* uinfo("iso np == 0\n"); */
+ /* usbip_dump_urb(urb); */
+ return 0;
+ }
+
+ buff = kzalloc(size, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0);
+ if (ret != size) {
+ dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n",
+ ret);
+ kfree(buff);
+
+ if (ud->side == USBIP_STUB)
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+ else
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+
+ return -EPIPE;
+ }
+
+ for (i = 0; i < np; i++) {
+ iso = buff + (i * sizeof(*iso));
+
+ usbip_iso_pakcet_correct_endian(iso, 0);
+ usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
+ }
+
+
+ kfree(buff);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_recv_iso);
+
+
+/* some members of urb must be substituted before. */
+int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
+{
+ int ret;
+ int size;
+
+ if (ud->side == USBIP_STUB) {
+ /* stub_rx.c */
+ /* the direction of urb must be OUT. */
+ if (usb_pipein(urb->pipe))
+ return 0;
+
+ size = urb->transfer_buffer_length;
+ } else {
+ /* vhci_rx.c */
+ /* the direction of urb must be IN. */
+ if (usb_pipeout(urb->pipe))
+ return 0;
+
+ size = urb->actual_length;
+ }
+
+ /* no need to recv xbuff */
+ if (!(size > 0))
+ return 0;
+
+ ret = usbip_xmit(0, ud->tcp_socket, (char *)urb->transfer_buffer,
+ size, 0);
+ if (ret != size) {
+ dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret);
+ if (ud->side == USBIP_STUB) {
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+ } else {
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+ return -EPIPE;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_recv_xbuff);
+
+
+/*-------------------------------------------------------------------------*/
+
+static int __init usbip_common_init(void)
+{
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "" DRIVER_VERSION);
+
+ return 0;
+}
+
+static void __exit usbip_common_exit(void)
+{
+ return;
+}
+
+
+
+
+module_init(usbip_common_init);
+module_exit(usbip_common_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
new file mode 100644
index 00000000000..b0186b76637
--- /dev/null
+++ b/drivers/staging/usbip/usbip_common.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __VHCI_COMMON_H
+#define __VHCI_COMMON_H
+
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <asm/byteorder.h>
+#include <net/sock.h>
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * define macros to print messages
+ */
+
+/**
+ * udbg - print debug messages if CONFIG_USB_DEBUG is defined
+ * @fmt:
+ * @args:
+ */
+
+#ifdef CONFIG_USB_DEBUG
+
+#define udbg(fmt, args...) \
+ do { \
+ printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \
+ (in_interrupt() ? "interrupt" : (current)->comm),\
+ __FILE__, __LINE__, __func__, ##args); \
+ } while (0)
+
+#else /* CONFIG_USB_DEBUG */
+
+#define udbg(fmt, args...) do { } while (0)
+
+#endif /* CONFIG_USB_DEBUG */
+
+
+enum {
+ usbip_debug_xmit = (1 << 0),
+ usbip_debug_sysfs = (1 << 1),
+ usbip_debug_urb = (1 << 2),
+ usbip_debug_eh = (1 << 3),
+
+ usbip_debug_stub_cmp = (1 << 8),
+ usbip_debug_stub_dev = (1 << 9),
+ usbip_debug_stub_rx = (1 << 10),
+ usbip_debug_stub_tx = (1 << 11),
+
+ usbip_debug_vhci_rh = (1 << 8),
+ usbip_debug_vhci_hc = (1 << 9),
+ usbip_debug_vhci_rx = (1 << 10),
+ usbip_debug_vhci_tx = (1 << 11),
+ usbip_debug_vhci_sysfs = (1 << 12)
+};
+
+#define dbg_flag_xmit (usbip_debug_flag & usbip_debug_xmit)
+#define dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh)
+#define dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc)
+#define dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx)
+#define dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx)
+#define dbg_flag_vhci_sysfs (usbip_debug_flag & usbip_debug_vhci_sysfs)
+#define dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx)
+#define dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx)
+
+extern unsigned long usbip_debug_flag;
+extern struct device_attribute dev_attr_usbip_debug;
+
+#define dbg_with_flag(flag, fmt, args...) \
+ do { \
+ if (flag & usbip_debug_flag) \
+ udbg(fmt , ##args); \
+ } while (0)
+
+#define dbg_sysfs(fmt, args...) \
+ dbg_with_flag(usbip_debug_sysfs, fmt , ##args)
+#define dbg_xmit(fmt, args...) \
+ dbg_with_flag(usbip_debug_xmit, fmt , ##args)
+#define dbg_urb(fmt, args...) \
+ dbg_with_flag(usbip_debug_urb, fmt , ##args)
+#define dbg_eh(fmt, args...) \
+ dbg_with_flag(usbip_debug_eh, fmt , ##args)
+
+#define dbg_vhci_rh(fmt, args...) \
+ dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args)
+#define dbg_vhci_hc(fmt, args...) \
+ dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args)
+#define dbg_vhci_rx(fmt, args...) \
+ dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args)
+#define dbg_vhci_tx(fmt, args...) \
+ dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args)
+#define dbg_vhci_sysfs(fmt, args...) \
+ dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args)
+
+#define dbg_stub_cmp(fmt, args...) \
+ dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args)
+#define dbg_stub_rx(fmt, args...) \
+ dbg_with_flag(usbip_debug_stub_rx, fmt , ##args)
+#define dbg_stub_tx(fmt, args...) \
+ dbg_with_flag(usbip_debug_stub_tx, fmt , ##args)
+
+
+/**
+ * uerr - print error messages
+ * @fmt:
+ * @args:
+ */
+#define uerr(fmt, args...) \
+ do { \
+ printk(KERN_ERR "%-10s: ***ERROR*** (%s,%d) %s: " fmt, \
+ (in_interrupt() ? "interrupt" : (current)->comm),\
+ __FILE__, __LINE__, __func__, ##args); \
+ } while (0)
+
+/**
+ * uinfo - print information messages
+ * @fmt:
+ * @args:
+ */
+#define uinfo(fmt, args...) \
+ do { \
+ printk(KERN_INFO "usbip: " fmt , ## args); \
+ } while (0)
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB/IP request headers.
+ * Currently, we define 4 request types:
+ *
+ * - CMD_SUBMIT transfers a USB request, corresponding to usb_submit_urb().
+ * (client to server)
+ * - RET_RETURN transfers the result of CMD_SUBMIT.
+ * (server to client)
+ * - CMD_UNLINK transfers an unlink request of a pending USB request.
+ * (client to server)
+ * - RET_UNLINK transfers the result of CMD_UNLINK.
+ * (server to client)
+ *
+ * Note: The below request formats are based on the USB subsystem of Linux. Its
+ * details will be defined when other implementations come.
+ *
+ *
+ */
+
+/*
+ * A basic header followed by other additional headers.
+ */
+struct usbip_header_basic {
+#define USBIP_CMD_SUBMIT 0x0001
+#define USBIP_CMD_UNLINK 0x0002
+#define USBIP_RET_SUBMIT 0x0003
+#define USBIP_RET_UNLINK 0x0004
+ __u32 command;
+
+ /* sequencial number which identifies requests.
+ * incremented per connections */
+ __u32 seqnum;
+
+ /* devid is used to specify a remote USB device uniquely instead
+ * of busnum and devnum in Linux. In the case of Linux stub_driver,
+ * this value is ((busnum << 16) | devnum) */
+ __u32 devid;
+
+#define USBIP_DIR_OUT 0
+#define USBIP_DIR_IN 1
+ __u32 direction;
+ __u32 ep; /* endpoint number */
+} __attribute__ ((packed));
+
+/*
+ * An additional header for a CMD_SUBMIT packet.
+ */
+struct usbip_header_cmd_submit {
+ /* these values are basically the same as in a URB. */
+
+ /* the same in a URB. */
+ __u32 transfer_flags;
+
+ /* set the following data size (out),
+ * or expected reading data size (in) */
+ __s32 transfer_buffer_length;
+
+ /* it is difficult for usbip to sync frames (reserved only?) */
+ __s32 start_frame;
+
+ /* the number of iso descriptors that follows this header */
+ __s32 number_of_packets;
+
+ /* the maximum time within which this request works in a host
+ * controller of a server side */
+ __s32 interval;
+
+ /* set setup packet data for a CTRL request */
+ unsigned char setup[8];
+} __attribute__ ((packed));
+
+/*
+ * An additional header for a RET_SUBMIT packet.
+ */
+struct usbip_header_ret_submit {
+ __s32 status;
+ __s32 actual_length; /* returned data length */
+ __s32 start_frame; /* ISO and INT */
+ __s32 number_of_packets; /* ISO only */
+ __s32 error_count; /* ISO only */
+} __attribute__ ((packed));
+
+/*
+ * An additional header for a CMD_UNLINK packet.
+ */
+struct usbip_header_cmd_unlink {
+ __u32 seqnum; /* URB's seqnum which will be unlinked */
+} __attribute__ ((packed));
+
+
+/*
+ * An additional header for a RET_UNLINK packet.
+ */
+struct usbip_header_ret_unlink {
+ __s32 status;
+} __attribute__ ((packed));
+
+
+/* the same as usb_iso_packet_descriptor but packed for pdu */
+struct usbip_iso_packet_descriptor {
+ __u32 offset;
+ __u32 length; /* expected length */
+ __u32 actual_length;
+ __u32 status;
+} __attribute__ ((packed));
+
+
+/*
+ * All usbip packets use a common header to keep code simple.
+ */
+struct usbip_header {
+ struct usbip_header_basic base;
+
+ union {
+ struct usbip_header_cmd_submit cmd_submit;
+ struct usbip_header_ret_submit ret_submit;
+ struct usbip_header_cmd_unlink cmd_unlink;
+ struct usbip_header_ret_unlink ret_unlink;
+ } u;
+} __attribute__ ((packed));
+
+
+
+
+/*-------------------------------------------------------------------------*/
+
+
+int usbip_xmit(int, struct socket *, char *, int, int);
+int usbip_sendmsg(struct socket *, struct msghdr *, int);
+
+
+static inline int interface_to_busnum(struct usb_interface *interface)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ return udev->bus->busnum;
+}
+
+static inline int interface_to_devnum(struct usb_interface *interface)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ return udev->devnum;
+}
+
+static inline int interface_to_infnum(struct usb_interface *interface)
+{
+ return interface->cur_altsetting->desc.bInterfaceNumber;
+}
+
+#if 0
+int setnodelay(struct socket *);
+int setquickack(struct socket *);
+int setkeepalive(struct socket *socket);
+void setreuse(struct socket *);
+#endif
+
+struct socket *sockfd_to_socket(unsigned int);
+int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss);
+
+void usbip_dump_urb(struct urb *purb);
+void usbip_dump_header(struct usbip_header *pdu);
+
+
+struct usbip_device;
+
+struct usbip_task {
+ struct task_struct *thread;
+ struct completion thread_done;
+ char *name;
+ void (*loop_ops)(struct usbip_task *);
+};
+
+enum usbip_side {
+ USBIP_VHCI,
+ USBIP_STUB,
+};
+
+enum usbip_status {
+ /* sdev is available. */
+ SDEV_ST_AVAILABLE = 0x01,
+ /* sdev is now used. */
+ SDEV_ST_USED,
+ /* sdev is unusable because of a fatal error. */
+ SDEV_ST_ERROR,
+
+ /* vdev does not connect a remote device. */
+ VDEV_ST_NULL,
+ /* vdev is used, but the USB address is not assigned yet */
+ VDEV_ST_NOTASSIGNED,
+ VDEV_ST_USED,
+ VDEV_ST_ERROR
+};
+
+/* a common structure for stub_device and vhci_device */
+struct usbip_device {
+ enum usbip_side side;
+
+ enum usbip_status status;
+
+ /* lock for status */
+ spinlock_t lock;
+
+ struct socket *tcp_socket;
+
+ struct usbip_task tcp_rx;
+ struct usbip_task tcp_tx;
+
+ /* event handler */
+#define USBIP_EH_SHUTDOWN (1 << 0)
+#define USBIP_EH_BYE (1 << 1)
+#define USBIP_EH_RESET (1 << 2)
+#define USBIP_EH_UNUSABLE (1 << 3)
+
+#define SDEV_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE)
+#define SDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define SDEV_EVENT_ERROR_TCP (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define SDEV_EVENT_ERROR_SUBMIT (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define SDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
+
+#define VDEV_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_BYE)
+#define VDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define VDEV_EVENT_ERROR_TCP (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define VDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
+
+ unsigned long event;
+ struct usbip_task eh;
+ wait_queue_head_t eh_waitq;
+
+ struct eh_ops {
+ void (*shutdown)(struct usbip_device *);
+ void (*reset)(struct usbip_device *);
+ void (*unusable)(struct usbip_device *);
+ } eh_ops;
+};
+
+
+void usbip_task_init(struct usbip_task *ut, char *,
+ void (*loop_ops)(struct usbip_task *));
+
+void usbip_start_threads(struct usbip_device *ud);
+void usbip_stop_threads(struct usbip_device *ud);
+int usbip_thread(void *param);
+
+void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
+ int pack);
+
+void usbip_header_correct_endian(struct usbip_header *pdu, int send);
+/* some members of urb must be substituted before. */
+int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
+/* some members of urb must be substituted before. */
+int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
+void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+
+
+/* usbip_event.c */
+void usbip_start_eh(struct usbip_device *ud);
+void usbip_stop_eh(struct usbip_device *ud);
+void usbip_event_add(struct usbip_device *ud, unsigned long event);
+int usbip_event_happend(struct usbip_device *ud);
+
+
+#endif
diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c
new file mode 100644
index 00000000000..4318553ab20
--- /dev/null
+++ b/drivers/staging/usbip/usbip_event.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+
+static int event_handler(struct usbip_device *ud)
+{
+ dbg_eh("enter\n");
+
+ /*
+ * Events are handled by only this thread.
+ */
+ while (usbip_event_happend(ud)) {
+ dbg_eh("pending event %lx\n", ud->event);
+
+ /*
+ * NOTE: shutdown must come first.
+ * Shutdown the device.
+ */
+ if (ud->event & USBIP_EH_SHUTDOWN) {
+ ud->eh_ops.shutdown(ud);
+
+ ud->event &= ~USBIP_EH_SHUTDOWN;
+
+ break;
+ }
+
+ /* Stop the error handler. */
+ if (ud->event & USBIP_EH_BYE)
+ return -1;
+
+ /* Reset the device. */
+ if (ud->event & USBIP_EH_RESET) {
+ ud->eh_ops.reset(ud);
+
+ ud->event &= ~USBIP_EH_RESET;
+
+ break;
+ }
+
+ /* Mark the device as unusable. */
+ if (ud->event & USBIP_EH_UNUSABLE) {
+ ud->eh_ops.unusable(ud);
+
+ ud->event &= ~USBIP_EH_UNUSABLE;
+
+ break;
+ }
+
+ /* NOTREACHED */
+ printk(KERN_ERR "%s: unknown event\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void event_handler_loop(struct usbip_task *ut)
+{
+ struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
+
+ while (1) {
+ if (signal_pending(current)) {
+ dbg_eh("signal catched!\n");
+ break;
+ }
+
+ if (event_handler(ud) < 0)
+ break;
+
+ wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud));
+ dbg_eh("wakeup\n");
+ }
+}
+
+void usbip_start_eh(struct usbip_device *ud)
+{
+ struct usbip_task *eh = &ud->eh;
+
+ init_waitqueue_head(&ud->eh_waitq);
+ ud->event = 0;
+
+ usbip_task_init(eh, "usbip_eh", event_handler_loop);
+
+ kernel_thread(usbip_thread, (void *)eh, 0);
+
+ wait_for_completion(&eh->thread_done);
+}
+EXPORT_SYMBOL_GPL(usbip_start_eh);
+
+void usbip_stop_eh(struct usbip_device *ud)
+{
+ struct usbip_task *eh = &ud->eh;
+
+ wait_for_completion(&eh->thread_done);
+ dbg_eh("usbip_eh has finished\n");
+}
+EXPORT_SYMBOL_GPL(usbip_stop_eh);
+
+void usbip_event_add(struct usbip_device *ud, unsigned long event)
+{
+ spin_lock(&ud->lock);
+
+ ud->event |= event;
+
+ wake_up(&ud->eh_waitq);
+
+ spin_unlock(&ud->lock);
+}
+EXPORT_SYMBOL_GPL(usbip_event_add);
+
+int usbip_event_happend(struct usbip_device *ud)
+{
+ int happend = 0;
+
+ spin_lock(&ud->lock);
+
+ if (ud->event != 0)
+ happend = 1;
+
+ spin_unlock(&ud->lock);
+
+ return happend;
+}
+EXPORT_SYMBOL_GPL(usbip_event_happend);
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
new file mode 100644
index 00000000000..5e375173bbc
--- /dev/null
+++ b/drivers/staging/usbip/vhci.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/platform_device.h>
+#include "../../usb/core/hcd.h"
+
+
+struct vhci_device {
+ struct usb_device *udev;
+
+ /*
+ * devid specifies a remote usb device uniquely instead
+ * of combination of busnum and devnum.
+ */
+ __u32 devid;
+
+ /* speed of a remote device */
+ enum usb_device_speed speed;
+
+ /* vhci root-hub port to which this device is attached */
+ __u32 rhport;
+
+ struct usbip_device ud;
+
+
+ /* lock for the below link lists */
+ spinlock_t priv_lock;
+
+ /* vhci_priv is linked to one of them. */
+ struct list_head priv_tx;
+ struct list_head priv_rx;
+
+ /* vhci_unlink is linked to one of them */
+ struct list_head unlink_tx;
+ struct list_head unlink_rx;
+
+ /* vhci_tx thread sleeps for this queue */
+ wait_queue_head_t waitq_tx;
+};
+
+
+/* urb->hcpriv, use container_of() */
+struct vhci_priv {
+ unsigned long seqnum;
+ struct list_head list;
+
+ struct vhci_device *vdev;
+ struct urb *urb;
+};
+
+
+struct vhci_unlink {
+ /* seqnum of this request */
+ unsigned long seqnum;
+
+ struct list_head list;
+
+ /* seqnum of the unlink target */
+ unsigned long unlink_seqnum;
+};
+
+/*
+ * The number of ports is less than 16 ?
+ * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value
+ * would be 31 because the event_bits[1] of struct usb_hub is defined as
+ * unsigned long in hub.h
+ */
+#define VHCI_NPORTS 8
+
+/* for usb_bus.hcpriv */
+struct vhci_hcd {
+ spinlock_t lock;
+
+ u32 port_status[VHCI_NPORTS];
+
+ unsigned resuming:1;
+ unsigned long re_timeout;
+
+ atomic_t seqnum;
+
+ /*
+ * NOTE:
+ * wIndex shows the port number and begins from 1.
+ * But, the index of this array begins from 0.
+ */
+ struct vhci_device vdev[VHCI_NPORTS];
+
+ /* vhci_device which has not been assiged its address yet */
+ int pending_port;
+};
+
+
+extern struct vhci_hcd *the_controller;
+extern struct attribute_group dev_attr_group;
+
+
+/*-------------------------------------------------------------------------*/
+/* prototype declaration */
+
+/* vhci_hcd.c */
+void rh_port_connect(int rhport, enum usb_device_speed speed);
+void rh_port_disconnect(int rhport);
+void vhci_rx_loop(struct usbip_task *ut);
+void vhci_tx_loop(struct usbip_task *ut);
+
+#define hardware (&the_controller->pdev.dev)
+
+static inline struct vhci_device *port_to_vdev(__u32 port)
+{
+ return &the_controller->vdev[port];
+}
+
+static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd)
+{
+ return (struct vhci_hcd *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci)
+{
+ return container_of((void *) vhci, struct usb_hcd, hcd_priv);
+}
+
+static inline struct device *vhci_dev(struct vhci_hcd *vhci)
+{
+ return vhci_to_hcd(vhci)->self.controller;
+}
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
new file mode 100644
index 00000000000..5b5a2e348ec
--- /dev/null
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -0,0 +1,1275 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+#define DRIVER_VERSION "1.0"
+#define DRIVER_AUTHOR "Takahiro Hirofuchi"
+#define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP"
+#define DRIVER_LICENCE "GPL"
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENCE);
+
+
+
+/*
+ * TODO
+ * - update root hub emulation
+ * - move the emulation code to userland ?
+ * porting to other operating systems
+ * minimize kernel code
+ * - add suspend/resume code
+ * - clean up everything
+ */
+
+
+/* See usb gadget dummy hcd */
+
+
+static int vhci_hub_status(struct usb_hcd *hcd, char *buff);
+static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buff, u16 wLength);
+static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags);
+static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+static int vhci_start(struct usb_hcd *vhci_hcd);
+static void vhci_stop(struct usb_hcd *hcd);
+static int vhci_get_frame_number(struct usb_hcd *hcd);
+
+static const char driver_name[] = "vhci_hcd";
+static const char driver_desc[] = "USB/IP Virtual Host Contoroller";
+
+struct vhci_hcd *the_controller;
+
+static const char *bit_desc[] = {
+ "CONNECTION", /*0*/
+ "ENABLE", /*1*/
+ "SUSPEND", /*2*/
+ "OVER_CURRENT", /*3*/
+ "RESET", /*4*/
+ "R5", /*5*/
+ "R6", /*6*/
+ "R7", /*7*/
+ "POWER", /*8*/
+ "LOWSPEED", /*9*/
+ "HIGHSPEED", /*10*/
+ "PORT_TEST", /*11*/
+ "INDICATOR", /*12*/
+ "R13", /*13*/
+ "R14", /*14*/
+ "R15", /*15*/
+ "C_CONNECTION", /*16*/
+ "C_ENABLE", /*17*/
+ "C_SUSPEND", /*18*/
+ "C_OVER_CURRENT", /*19*/
+ "C_RESET", /*20*/
+ "R21", /*21*/
+ "R22", /*22*/
+ "R23", /*23*/
+ "R24", /*24*/
+ "R25", /*25*/
+ "R26", /*26*/
+ "R27", /*27*/
+ "R28", /*28*/
+ "R29", /*29*/
+ "R30", /*30*/
+ "R31", /*31*/
+};
+
+
+static void dump_port_status(u32 status)
+{
+ int i = 0;
+
+ printk(KERN_DEBUG "status %08x:", status);
+ for (i = 0; i < 32; i++) {
+ if (status & (1 << i))
+ printk(" %s", bit_desc[i]);
+ }
+
+ printk("\n");
+}
+
+
+
+void rh_port_connect(int rhport, enum usb_device_speed speed)
+{
+ unsigned long flags;
+
+ dbg_vhci_rh("rh_port_connect %d\n", rhport);
+
+ spin_lock_irqsave(&the_controller->lock, flags);
+
+ the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
+ | (1 << USB_PORT_FEAT_C_CONNECTION);
+
+ switch (speed) {
+ case USB_SPEED_HIGH:
+ the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED;
+ break;
+ case USB_SPEED_LOW:
+ the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED;
+ break;
+ default:
+ break;
+ }
+
+ /* spin_lock(&the_controller->vdev[rhport].ud.lock);
+ * the_controller->vdev[rhport].ud.status = VDEV_CONNECT;
+ * spin_unlock(&the_controller->vdev[rhport].ud.lock); */
+
+ the_controller->pending_port = rhport;
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+
+ usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
+}
+
+void rh_port_disconnect(int rhport)
+{
+ unsigned long flags;
+
+ dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
+
+ spin_lock_irqsave(&the_controller->lock, flags);
+ /* stop_activity(dum, driver); */
+ the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
+ the_controller->port_status[rhport] |=
+ (1 << USB_PORT_FEAT_C_CONNECTION);
+
+
+ /* not yet complete the disconnection
+ * spin_lock(&vdev->ud.lock);
+ * vdev->ud.status = VHC_ST_DISCONNECT;
+ * spin_unlock(&vdev->ud.lock); */
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+}
+
+
+
+/*----------------------------------------------------------------------*/
+
+#define PORT_C_MASK \
+ ((USB_PORT_STAT_C_CONNECTION \
+ | USB_PORT_STAT_C_ENABLE \
+ | USB_PORT_STAT_C_SUSPEND \
+ | USB_PORT_STAT_C_OVERCURRENT \
+ | USB_PORT_STAT_C_RESET) << 16)
+
+/*
+ * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without
+ * suspend/resume support. But, it is modified to provide multiple ports.
+ *
+ * @buf: a bitmap to show which port status has been changed.
+ * bit 0: reserved or used for another purpose?
+ * bit 1: the status of port 0 has been changed.
+ * bit 2: the status of port 1 has been changed.
+ * ...
+ * bit 7: the status of port 6 has been changed.
+ * bit 8: the status of port 7 has been changed.
+ * ...
+ * bit 15: the status of port 14 has been changed.
+ *
+ * So, the maximum number of ports is 31 ( port 0 to port 30) ?
+ *
+ * The return value is the actual transfered length in byte. If nothing has
+ * been changed, return 0. In the case that the number of ports is less than or
+ * equal to 6 (VHCI_NPORTS==7), return 1.
+ *
+ */
+static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
+{
+ struct vhci_hcd *vhci;
+ unsigned long flags;
+ int retval = 0;
+
+ /* the enough buffer is allocated according to USB_MAXCHILDREN */
+ unsigned long *event_bits = (unsigned long *) buf;
+ int rhport;
+ int changed = 0;
+
+
+ *event_bits = 0;
+
+ vhci = hcd_to_vhci(hcd);
+
+ spin_lock_irqsave(&vhci->lock, flags);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ dbg_vhci_rh("hw accessible flag in on?\n");
+ goto done;
+ }
+
+ /* check pseudo status register for each port */
+ for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
+ if ((vhci->port_status[rhport] & PORT_C_MASK)) {
+ /* The status of a port has been changed, */
+ dbg_vhci_rh("port %d is changed\n", rhport);
+
+ *event_bits |= 1 << (rhport + 1);
+ changed = 1;
+ }
+ }
+
+ uinfo("changed %d\n", changed);
+
+ if (hcd->state == HC_STATE_SUSPENDED)
+ usb_hcd_resume_root_hub(hcd);
+
+ if (changed)
+ retval = 1 + (VHCI_NPORTS / 8);
+ else
+ retval = 0;
+
+done:
+ spin_unlock_irqrestore(&vhci->lock, flags);
+ return retval;
+}
+
+/* See hub_configure in hub.c */
+static inline void hub_descriptor(struct usb_hub_descriptor *desc)
+{
+ memset(desc, 0, sizeof(*desc));
+ desc->bDescriptorType = 0x29;
+ desc->bDescLength = 9;
+ desc->wHubCharacteristics = (__force __u16)
+ (__constant_cpu_to_le16(0x0001));
+ desc->bNbrPorts = VHCI_NPORTS;
+ desc->bitmap[0] = 0xff;
+ desc->bitmap[1] = 0xff;
+}
+
+static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+{
+ struct vhci_hcd *dum;
+ int retval = 0;
+ unsigned long flags;
+ int rhport;
+
+ u32 prev_port_status[VHCI_NPORTS];
+
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ return -ETIMEDOUT;
+
+ /*
+ * NOTE:
+ * wIndex shows the port number and begins from 1.
+ */
+ dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
+ wIndex);
+ if (wIndex > VHCI_NPORTS)
+ printk(KERN_ERR "%s: invalid port number %d\n", __func__, wIndex);
+ rhport = ((__u8)(wIndex & 0x00ff)) - 1;
+
+ dum = hcd_to_vhci(hcd);
+
+ spin_lock_irqsave(&dum->lock, flags);
+
+ /* store old status and compare now and old later */
+ if (dbg_flag_vhci_rh) {
+ int i = 0;
+ for (i = 0; i < VHCI_NPORTS; i++)
+ prev_port_status[i] = dum->port_status[i];
+ }
+
+ switch (typeReq) {
+ case ClearHubFeature:
+ dbg_vhci_rh(" ClearHubFeature\n");
+ break;
+ case ClearPortFeature:
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
+ /* 20msec signaling */
+ dum->resuming = 1;
+ dum->re_timeout =
+ jiffies + msecs_to_jiffies(20);
+ }
+ break;
+ case USB_PORT_FEAT_POWER:
+ dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_POWER\n");
+ dum->port_status[rhport] = 0;
+ /* dum->address = 0; */
+ /* dum->hdev = 0; */
+ dum->resuming = 0;
+ break;
+ case USB_PORT_FEAT_C_RESET:
+ dbg_vhci_rh(" ClearPortFeature: "
+ "USB_PORT_FEAT_C_RESET\n");
+ switch (dum->vdev[rhport].speed) {
+ case USB_SPEED_HIGH:
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_HIGH_SPEED;
+ break;
+ case USB_SPEED_LOW:
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_LOW_SPEED;
+ break;
+ default:
+ break;
+ }
+ default:
+ dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue);
+ dum->port_status[rhport] &= ~(1 << wValue);
+ }
+ break;
+ case GetHubDescriptor:
+ dbg_vhci_rh(" GetHubDescriptor\n");
+ hub_descriptor((struct usb_hub_descriptor *) buf);
+ break;
+ case GetHubStatus:
+ dbg_vhci_rh(" GetHubStatus\n");
+ *(__le32 *) buf = __constant_cpu_to_le32(0);
+ break;
+ case GetPortStatus:
+ dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
+ if (wIndex > VHCI_NPORTS || wIndex < 1) {
+ printk(KERN_ERR "%s: invalid port number %d\n",
+ __func__, wIndex);
+ retval = -EPIPE;
+ }
+
+ /* we do no care of resume. */
+
+ /* whoever resets or resumes must GetPortStatus to
+ * complete it!!
+ * */
+ if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
+ printk(KERN_ERR "%s: not yet\n", __func__);
+ dum->port_status[rhport] |=
+ (1 << USB_PORT_FEAT_C_SUSPEND);
+ dum->port_status[rhport] &=
+ ~(1 << USB_PORT_FEAT_SUSPEND);
+ dum->resuming = 0;
+ dum->re_timeout = 0;
+ /* if (dum->driver && dum->driver->resume) {
+ * spin_unlock (&dum->lock);
+ * dum->driver->resume (&dum->gadget);
+ * spin_lock (&dum->lock);
+ * } */
+ }
+
+ if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
+ 0 && time_after(jiffies, dum->re_timeout)) {
+ dum->port_status[rhport] |=
+ (1 << USB_PORT_FEAT_C_RESET);
+ dum->port_status[rhport] &=
+ ~(1 << USB_PORT_FEAT_RESET);
+ dum->re_timeout = 0;
+
+ if (dum->vdev[rhport].ud.status ==
+ VDEV_ST_NOTASSIGNED) {
+ dbg_vhci_rh(" enable rhport %d (status %u)\n",
+ rhport,
+ dum->vdev[rhport].ud.status);
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_ENABLE;
+ }
+#if 0
+ if (dum->driver) {
+
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_ENABLE;
+ /* give it the best speed we agree on */
+ dum->gadget.speed = dum->driver->speed;
+ dum->gadget.ep0->maxpacket = 64;
+ switch (dum->gadget.speed) {
+ case USB_SPEED_HIGH:
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_HIGH_SPEED;
+ break;
+ case USB_SPEED_LOW:
+ dum->gadget.ep0->maxpacket = 8;
+ dum->port_status[rhport] |=
+ USB_PORT_STAT_LOW_SPEED;
+ break;
+ default:
+ dum->gadget.speed = USB_SPEED_FULL;
+ break;
+ }
+ }
+#endif
+
+ }
+ ((u16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]);
+ ((u16 *) buf)[1] =
+ cpu_to_le16(dum->port_status[rhport] >> 16);
+
+ dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0],
+ ((u16 *)buf)[1]);
+ break;
+ case SetHubFeature:
+ dbg_vhci_rh(" SetHubFeature\n");
+ retval = -EPIPE;
+ break;
+ case SetPortFeature:
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ dbg_vhci_rh(" SetPortFeature: "
+ "USB_PORT_FEAT_SUSPEND\n");
+ printk(KERN_ERR "%s: not yet\n", __func__);
+#if 0
+ dum->port_status[rhport] |=
+ (1 << USB_PORT_FEAT_SUSPEND);
+ if (dum->driver->suspend) {
+ spin_unlock(&dum->lock);
+ dum->driver->suspend(&dum->gadget);
+ spin_lock(&dum->lock);
+ }
+#endif
+ break;
+ case USB_PORT_FEAT_RESET:
+ dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_RESET\n");
+ /* if it's already running, disconnect first */
+ if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) {
+ dum->port_status[rhport] &=
+ ~(USB_PORT_STAT_ENABLE |
+ USB_PORT_STAT_LOW_SPEED |
+ USB_PORT_STAT_HIGH_SPEED);
+#if 0
+ if (dum->driver) {
+ dev_dbg(hardware, "disconnect\n");
+ stop_activity(dum, dum->driver);
+ }
+#endif
+
+ /* FIXME test that code path! */
+ }
+ /* 50msec reset signaling */
+ dum->re_timeout = jiffies + msecs_to_jiffies(50);
+
+ /* FALLTHROUGH */
+ default:
+ dbg_vhci_rh(" SetPortFeature: default %d\n", wValue);
+ dum->port_status[rhport] |= (1 << wValue);
+ }
+ break;
+
+ default:
+ printk(KERN_ERR "%s: default: no such request\n", __func__);
+ /* dev_dbg (hardware,
+ * "hub control req%04x v%04x i%04x l%d\n",
+ * typeReq, wValue, wIndex, wLength); */
+
+ /* "protocol stall" on error */
+ retval = -EPIPE;
+ }
+
+ if (dbg_flag_vhci_rh) {
+ printk(KERN_DEBUG "port %d\n", rhport);
+ dump_port_status(prev_port_status[rhport]);
+ dump_port_status(dum->port_status[rhport]);
+ }
+ dbg_vhci_rh(" bye\n");
+
+ spin_unlock_irqrestore(&dum->lock, flags);
+
+ return retval;
+}
+
+
+
+/*----------------------------------------------------------------------*/
+
+static struct vhci_device *get_vdev(struct usb_device *udev)
+{
+ int i;
+
+ if (!udev)
+ return NULL;
+
+ for (i = 0; i < VHCI_NPORTS; i++)
+ if (the_controller->vdev[i].udev == udev)
+ return port_to_vdev(i);
+
+ return NULL;
+}
+
+static void vhci_tx_urb(struct urb *urb)
+{
+ struct vhci_device *vdev = get_vdev(urb->dev);
+ struct vhci_priv *priv;
+ unsigned long flag;
+
+ if (!vdev) {
+ err("could not get virtual device");
+ /* BUG(); */
+ return;
+ }
+
+ spin_lock_irqsave(&vdev->priv_lock, flag);
+
+ priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
+ if (!priv) {
+ dev_err(&urb->dev->dev, "malloc vhci_priv\n");
+ spin_unlock_irqrestore(&vdev->priv_lock, flag);
+ usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
+ return;
+ }
+
+ priv->seqnum = atomic_inc_return(&the_controller->seqnum);
+ if (priv->seqnum == 0xffff)
+ uinfo("seqnum max\n");
+
+ priv->vdev = vdev;
+ priv->urb = urb;
+
+ urb->hcpriv = (void *) priv;
+
+
+ list_add_tail(&priv->list, &vdev->priv_tx);
+
+ wake_up(&vdev->waitq_tx);
+ spin_unlock_irqrestore(&vdev->priv_lock, flag);
+}
+
+static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ struct device *dev = &urb->dev->dev;
+ int ret = 0;
+ unsigned long flags;
+
+ dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
+ hcd, urb, mem_flags);
+
+ /* patch to usb_sg_init() is in 2.5.60 */
+ BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
+
+ spin_lock_irqsave(&the_controller->lock, flags);
+
+ /* check HC is active or not */
+ if (!HC_IS_RUNNING(hcd->state)) {
+ dev_err(dev, "HC is not running\n");
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ return -ENODEV;
+ }
+
+ if (urb->status != -EINPROGRESS) {
+ dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ return urb->status;
+ }
+
+ ret = usb_hcd_link_urb_to_ep(hcd, urb);
+ if (ret)
+ goto no_need_unlink;
+
+ /*
+ * The enumelation process is as follows;
+ *
+ * 1. Get_Descriptor request to DevAddrs(0) EndPoint(0)
+ * to get max packet length of default pipe
+ *
+ * 2. Set_Address request to DevAddr(0) EndPoint(0)
+ *
+ */
+
+ if (usb_pipedevice(urb->pipe) == 0) {
+ __u8 type = usb_pipetype(urb->pipe);
+ struct usb_ctrlrequest *ctrlreq =
+ (struct usb_ctrlrequest *) urb->setup_packet;
+ struct vhci_device *vdev =
+ port_to_vdev(the_controller->pending_port);
+
+ if (type != PIPE_CONTROL || !ctrlreq) {
+ dev_err(dev, "invalid request to devnum 0\n");
+ ret = EINVAL;
+ goto no_need_xmit;
+ }
+
+ switch (ctrlreq->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ /* set_address may come when a device is reset */
+ dev_info(dev, "SetAddress Request (%d) to port %d\n",
+ ctrlreq->wValue, vdev->rhport);
+
+ vdev->udev = urb->dev;
+
+ spin_lock(&vdev->ud.lock);
+ vdev->ud.status = VDEV_ST_USED;
+ spin_unlock(&vdev->ud.lock);
+
+ if (urb->status == -EINPROGRESS) {
+ /* This request is successfully completed. */
+ /* If not -EINPROGRESS, possibly unlinked. */
+ urb->status = 0;
+ }
+
+ goto no_need_xmit;
+
+ case USB_REQ_GET_DESCRIPTOR:
+ if (ctrlreq->wValue == (USB_DT_DEVICE << 8))
+ dbg_vhci_hc("Not yet?: "
+ "Get_Descriptor to device 0 "
+ "(get max pipe size)\n");
+
+ /* FIXME: reference count? (usb_get_dev()) */
+ vdev->udev = urb->dev;
+ goto out;
+
+ default:
+ /* NOT REACHED */
+ dev_err(dev, "invalid request to devnum 0 bRequest %u, "
+ "wValue %u\n", ctrlreq->bRequest,
+ ctrlreq->wValue);
+ ret = -EINVAL;
+ goto no_need_xmit;
+ }
+
+ }
+
+out:
+ vhci_tx_urb(urb);
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+
+ return 0;
+
+no_need_xmit:
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+no_need_unlink:
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+
+ return 0;
+}
+
+/*
+ * vhci_rx gives back the urb after receiving the reply of the urb. If an
+ * unlink pdu is sent or not, vhci_rx receives a normal return pdu and gives
+ * back its urb. For the driver unlinking the urb, the content of the urb is
+ * not important, but the calling to its completion handler is important; the
+ * completion of unlinking is notified by the completion handler.
+ *
+ *
+ * CLIENT SIDE
+ *
+ * - When vhci_hcd receives RET_SUBMIT,
+ *
+ * - case 1a). the urb of the pdu is not unlinking.
+ * - normal case
+ * => just give back the urb
+ *
+ * - case 1b). the urb of the pdu is unlinking.
+ * - usbip.ko will return a reply of the unlinking request.
+ * => give back the urb now and go to case 2b).
+ *
+ * - When vhci_hcd receives RET_UNLINK,
+ *
+ * - case 2a). a submit request is still pending in vhci_hcd.
+ * - urb was really pending in usbip.ko and urb_unlink_urb() was
+ * completed there.
+ * => free a pending submit request
+ * => notify unlink completeness by giving back the urb
+ *
+ * - case 2b). a submit request is *not* pending in vhci_hcd.
+ * - urb was already given back to the core driver.
+ * => do not give back the urb
+ *
+ *
+ * SERVER SIDE
+ *
+ * - When usbip receives CMD_UNLINK,
+ *
+ * - case 3a). the urb of the unlink request is now in submission.
+ * => do usb_unlink_urb().
+ * => after the unlink is completed, send RET_UNLINK.
+ *
+ * - case 3b). the urb of the unlink request is not in submission.
+ * - may be already completed or never be received
+ * => send RET_UNLINK
+ *
+ */
+static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+ unsigned long flags;
+ struct vhci_priv *priv;
+ struct vhci_device *vdev;
+
+ uinfo("vhci_hcd: dequeue a urb %p\n", urb);
+
+
+ spin_lock_irqsave(&the_controller->lock, flags);
+
+ priv = urb->hcpriv;
+ if (!priv) {
+ /* URB was never linked! or will be soon given back by
+ * vhci_rx. */
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ return 0;
+ }
+
+ {
+ int ret = 0;
+ ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+ if (ret) {
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ return 0;
+ }
+ }
+
+ /* send unlink request here? */
+ vdev = priv->vdev;
+
+ if (!vdev->ud.tcp_socket) {
+ /* tcp connection is closed */
+ unsigned long flags2;
+
+ spin_lock_irqsave(&vdev->priv_lock, flags2);
+
+ uinfo("vhci_hcd: device %p seems to be disconnected\n", vdev);
+ list_del(&priv->list);
+ kfree(priv);
+ urb->hcpriv = NULL;
+
+ spin_unlock_irqrestore(&vdev->priv_lock, flags2);
+
+ } else {
+ /* tcp connection is alive */
+ unsigned long flags2;
+ struct vhci_unlink *unlink;
+
+ spin_lock_irqsave(&vdev->priv_lock, flags2);
+
+ /* setup CMD_UNLINK pdu */
+ unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
+ if (!unlink) {
+ uerr("malloc vhci_unlink\n");
+ spin_unlock_irqrestore(&vdev->priv_lock, flags2);
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
+ return -ENOMEM;
+ }
+
+ unlink->seqnum = atomic_inc_return(&the_controller->seqnum);
+ if (unlink->seqnum == 0xffff)
+ uinfo("seqnum max\n");
+
+ unlink->unlink_seqnum = priv->seqnum;
+
+ uinfo("vhci_hcd: device %p seems to be still connected\n",
+ vdev);
+
+ /* send cmd_unlink and try to cancel the pending URB in the
+ * peer */
+ list_add_tail(&unlink->list, &vdev->unlink_tx);
+ wake_up(&vdev->waitq_tx);
+
+ spin_unlock_irqrestore(&vdev->priv_lock, flags2);
+ }
+
+
+ /*
+ * If tcp connection is alive, we have sent CMD_UNLINK.
+ * vhci_rx will receive RET_UNLINK and give back the URB.
+ * Otherwise, we give back it here.
+ */
+ if (!vdev->ud.tcp_socket) {
+ /* tcp connection is closed */
+ uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb);
+
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+ urb->status);
+ spin_lock_irqsave(&the_controller->lock, flags);
+ }
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+
+ dbg_vhci_hc("leave\n");
+ return 0;
+}
+
+
+static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
+{
+ struct vhci_unlink *unlink, *tmp;
+
+ spin_lock(&vdev->priv_lock);
+
+ list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+ list_del(&unlink->list);
+ kfree(unlink);
+ }
+
+ list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
+ list_del(&unlink->list);
+ kfree(unlink);
+ }
+
+ spin_unlock(&vdev->priv_lock);
+}
+
+/*
+ * The important thing is that only one context begins cleanup.
+ * This is why error handling and cleanup become simple.
+ * We do not want to consider race condition as possible.
+ */
+static void vhci_shutdown_connection(struct usbip_device *ud)
+{
+ struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+ /* need this? see stub_dev.c */
+ if (ud->tcp_socket) {
+ udbg("shutdown tcp_socket %p\n", ud->tcp_socket);
+ kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+ }
+
+ usbip_stop_threads(&vdev->ud);
+ uinfo("stop threads\n");
+
+ /* active connection is closed */
+ if (vdev->ud.tcp_socket != NULL) {
+ sock_release(vdev->ud.tcp_socket);
+ vdev->ud.tcp_socket = NULL;
+ }
+ uinfo("release socket\n");
+
+ vhci_device_unlink_cleanup(vdev);
+
+ /*
+ * rh_port_disconnect() is a trigger of ...
+ * usb_disable_device():
+ * disable all the endpoints for a USB device.
+ * usb_disable_endpoint():
+ * disable endpoints. pending urbs are unlinked(dequeued).
+ *
+ * NOTE: After calling rh_port_disconnect(), the USB device drivers of a
+ * deteched device should release used urbs in a cleanup function(i.e.
+ * xxx_disconnect()). Therefore, vhci_hcd does not need to release
+ * pushed urbs and their private data in this function.
+ *
+ * NOTE: vhci_dequeue() must be considered carefully. When shutdowning
+ * a connection, vhci_shutdown_connection() expects vhci_dequeue()
+ * gives back pushed urbs and frees their private data by request of
+ * the cleanup function of a USB driver. When unlinking a urb with an
+ * active connection, vhci_dequeue() does not give back the urb which
+ * is actually given back by vhci_rx after receiving its return pdu.
+ *
+ */
+ rh_port_disconnect(vdev->rhport);
+
+ uinfo("disconnect device\n");
+}
+
+
+static void vhci_device_reset(struct usbip_device *ud)
+{
+ struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+ spin_lock(&ud->lock);
+
+ vdev->speed = 0;
+ vdev->devid = 0;
+
+ ud->tcp_socket = NULL;
+
+ ud->status = VDEV_ST_NULL;
+
+ spin_unlock(&ud->lock);
+}
+
+static void vhci_device_unusable(struct usbip_device *ud)
+{
+ spin_lock(&ud->lock);
+
+ ud->status = VDEV_ST_ERROR;
+
+ spin_unlock(&ud->lock);
+}
+
+static void vhci_device_init(struct vhci_device *vdev)
+{
+ memset(vdev, 0, sizeof(*vdev));
+
+ usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop);
+ usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop);
+
+ vdev->ud.side = USBIP_VHCI;
+ vdev->ud.status = VDEV_ST_NULL;
+ /* vdev->ud.lock = SPIN_LOCK_UNLOCKED; */
+ spin_lock_init(&vdev->ud.lock);
+
+ INIT_LIST_HEAD(&vdev->priv_rx);
+ INIT_LIST_HEAD(&vdev->priv_tx);
+ INIT_LIST_HEAD(&vdev->unlink_tx);
+ INIT_LIST_HEAD(&vdev->unlink_rx);
+ /* vdev->priv_lock = SPIN_LOCK_UNLOCKED; */
+ spin_lock_init(&vdev->priv_lock);
+
+ init_waitqueue_head(&vdev->waitq_tx);
+
+ vdev->ud.eh_ops.shutdown = vhci_shutdown_connection;
+ vdev->ud.eh_ops.reset = vhci_device_reset;
+ vdev->ud.eh_ops.unusable = vhci_device_unusable;
+
+ usbip_start_eh(&vdev->ud);
+}
+
+
+/*----------------------------------------------------------------------*/
+
+static int vhci_start(struct usb_hcd *hcd)
+{
+ struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ int rhport;
+ int err = 0;
+
+ dbg_vhci_hc("enter vhci_start\n");
+
+
+ /* initialize private data of usb_hcd */
+
+ for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
+ struct vhci_device *vdev = &vhci->vdev[rhport];
+ vhci_device_init(vdev);
+ vdev->rhport = rhport;
+ }
+
+ atomic_set(&vhci->seqnum, 0);
+ spin_lock_init(&vhci->lock);
+
+
+
+ hcd->power_budget = 0; /* no limit */
+ hcd->state = HC_STATE_RUNNING;
+ hcd->uses_new_polling = 1;
+
+
+ /* vhci_hcd is now ready to be controlled through sysfs */
+ err = sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
+ if (err) {
+ uerr("create sysfs files\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void vhci_stop(struct usb_hcd *hcd)
+{
+ struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ int rhport = 0;
+
+ dbg_vhci_hc("stop VHCI controller\n");
+
+
+ /* 1. remove the userland interface of vhci_hcd */
+ sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
+
+ /* 2. shutdown all the ports of vhci_hcd */
+ for (rhport = 0 ; rhport < VHCI_NPORTS; rhport++) {
+ struct vhci_device *vdev = &vhci->vdev[rhport];
+
+ usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
+ usbip_stop_eh(&vdev->ud);
+ }
+
+
+ uinfo("vhci_stop done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static int vhci_get_frame_number(struct usb_hcd *hcd)
+{
+ uerr("Not yet implemented\n");
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+/* FIXME: suspend/resume */
+static int vhci_bus_suspend(struct usb_hcd *hcd)
+{
+ struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+
+ dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+ spin_lock_irq(&vhci->lock);
+ /* vhci->rh_state = DUMMY_RH_SUSPENDED;
+ * set_link_state(vhci); */
+ hcd->state = HC_STATE_SUSPENDED;
+ spin_unlock_irq(&vhci->lock);
+
+ return 0;
+}
+
+static int vhci_bus_resume(struct usb_hcd *hcd)
+{
+ struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ int rc = 0;
+
+ dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+ spin_lock_irq(&vhci->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ rc = -ESHUTDOWN;
+ } else {
+ /* vhci->rh_state = DUMMY_RH_RUNNING;
+ * set_link_state(vhci);
+ * if (!list_empty(&vhci->urbp_list))
+ * mod_timer(&vhci->timer, jiffies); */
+ hcd->state = HC_STATE_RUNNING;
+ }
+ spin_unlock_irq(&vhci->lock);
+ return rc;
+
+ return 0;
+}
+
+#else
+
+#define vhci_bus_suspend NULL
+#define vhci_bus_resume NULL
+#endif
+
+
+
+static struct hc_driver vhci_hc_driver = {
+ .description = driver_name,
+ .product_desc = driver_desc,
+ .hcd_priv_size = sizeof(struct vhci_hcd),
+
+ .flags = HCD_USB2,
+
+ .start = vhci_start,
+ .stop = vhci_stop,
+
+ .urb_enqueue = vhci_urb_enqueue,
+ .urb_dequeue = vhci_urb_dequeue,
+
+ .get_frame_number = vhci_get_frame_number,
+
+ .hub_status_data = vhci_hub_status,
+ .hub_control = vhci_hub_control,
+ .bus_suspend = vhci_bus_suspend,
+ .bus_resume = vhci_bus_resume,
+};
+
+static int vhci_hcd_probe(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+ int ret;
+
+ uinfo("proving...\n");
+
+ dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
+
+ /* will be removed */
+ if (pdev->dev.dma_mask) {
+ dev_info(&pdev->dev, "vhci_hcd DMA not supported\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Allocate and initialize hcd.
+ * Our private data is also allocated automatically.
+ */
+ hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, pdev->dev.bus_id);
+ if (!hcd) {
+ uerr("create hcd failed\n");
+ return -ENOMEM;
+ }
+
+
+ /* this is private data for vhci_hcd */
+ the_controller = hcd_to_vhci(hcd);
+
+ /*
+ * Finish generic HCD structure initialization and register.
+ * Call the driver's reset() and start() routines.
+ */
+ ret = usb_add_hcd(hcd, 0, 0);
+ if (ret != 0) {
+ uerr("usb_add_hcd failed %d\n", ret);
+ usb_put_hcd(hcd);
+ the_controller = NULL;
+ return ret;
+ }
+
+
+ dbg_vhci_hc("bye\n");
+ return 0;
+}
+
+
+static int vhci_hcd_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+
+ hcd = platform_get_drvdata(pdev);
+ if (!hcd)
+ return 0;
+
+ /*
+ * Disconnects the root hub,
+ * then reverses the effects of usb_add_hcd(),
+ * invoking the HCD's stop() methods.
+ */
+ usb_remove_hcd(hcd);
+ usb_put_hcd(hcd);
+ the_controller = NULL;
+
+
+ return 0;
+}
+
+
+
+#ifdef CONFIG_PM
+
+/* what should happen for USB/IP under suspend/resume? */
+static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct usb_hcd *hcd;
+ int rhport = 0;
+ int connected = 0;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ hcd = platform_get_drvdata(pdev);
+
+ spin_lock(&the_controller->lock);
+
+ for (rhport = 0; rhport < VHCI_NPORTS; rhport++)
+ if (the_controller->port_status[rhport] &
+ USB_PORT_STAT_CONNECTION)
+ connected += 1;
+
+ spin_unlock(&the_controller->lock);
+
+ if (connected > 0) {
+ uinfo("We have %d active connection%s. Do not suspend.\n",
+ connected, (connected == 1 ? "" : "s"));
+ ret = -EBUSY;
+ } else {
+ uinfo("suspend vhci_hcd");
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ }
+
+ return ret;
+}
+
+static int vhci_hcd_resume(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ hcd = platform_get_drvdata(pdev);
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ usb_hcd_poll_rh_status(hcd);
+
+ return 0;
+}
+
+#else
+
+#define vhci_hcd_suspend NULL
+#define vhci_hcd_resume NULL
+
+#endif
+
+
+static struct platform_driver vhci_driver = {
+ .probe = vhci_hcd_probe,
+ .remove = __devexit_p(vhci_hcd_remove),
+ .suspend = vhci_hcd_suspend,
+ .resume = vhci_hcd_resume,
+ .driver = {
+ .name = (char *) driver_name,
+ .owner = THIS_MODULE,
+ },
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * The VHCI 'device' is 'virtual'; not a real plug&play hardware.
+ * We need to add this virtual device as a platform device arbitrarily:
+ * 1. platform_device_register()
+ */
+static void the_pdev_release(struct device *dev)
+{
+ return;
+}
+
+static struct platform_device the_pdev = {
+ /* should be the same name as driver_name */
+ .name = (char *) driver_name,
+ .id = -1,
+ .dev = {
+ /* .driver = &vhci_driver, */
+ .release = the_pdev_release,
+ },
+};
+
+static int __init vhci_init(void)
+{
+ int ret;
+
+ dbg_vhci_hc("enter\n");
+ if (usb_disabled())
+ return -ENODEV;
+
+ printk(KERN_INFO KBUILD_MODNAME ": %s, %s\n", driver_name,
+ DRIVER_VERSION);
+
+ ret = platform_driver_register(&vhci_driver);
+ if (ret < 0)
+ goto err_driver_register;
+
+ ret = platform_device_register(&the_pdev);
+ if (ret < 0)
+ goto err_platform_device_register;
+
+ dbg_vhci_hc("bye\n");
+ return ret;
+
+ /* error occurred */
+err_platform_device_register:
+ platform_driver_unregister(&vhci_driver);
+
+err_driver_register:
+ dbg_vhci_hc("bye\n");
+ return ret;
+}
+module_init(vhci_init);
+
+static void __exit vhci_cleanup(void)
+{
+ dbg_vhci_hc("enter\n");
+
+ platform_device_unregister(&the_pdev);
+ platform_driver_unregister(&vhci_driver);
+
+ dbg_vhci_hc("bye\n");
+}
+module_exit(vhci_cleanup);
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
new file mode 100644
index 00000000000..933ccaf50af
--- /dev/null
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+
+/* get URB from transmitted urb queue */
+static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
+ __u32 seqnum)
+{
+ struct vhci_priv *priv, *tmp;
+ struct urb *urb = NULL;
+ int status;
+
+ spin_lock(&vdev->priv_lock);
+
+ list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
+ if (priv->seqnum == seqnum) {
+ urb = priv->urb;
+ status = urb->status;
+
+ dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
+ urb, priv, seqnum);
+
+ /* TODO: fix logic here to improve indent situtation */
+ if (status != -EINPROGRESS) {
+ if (status == -ENOENT ||
+ status == -ECONNRESET)
+ dev_info(&urb->dev->dev,
+ "urb %p was unlinked "
+ "%ssynchronuously.\n", urb,
+ status == -ENOENT ? "" : "a");
+ else
+ dev_info(&urb->dev->dev,
+ "urb %p may be in a error, "
+ "status %d\n", urb, status);
+ }
+
+ list_del(&priv->list);
+ kfree(priv);
+ urb->hcpriv = NULL;
+
+ break;
+ }
+ }
+
+ spin_unlock(&vdev->priv_lock);
+
+ return urb;
+}
+
+static void vhci_recv_ret_submit(struct vhci_device *vdev,
+ struct usbip_header *pdu)
+{
+ struct usbip_device *ud = &vdev->ud;
+ struct urb *urb;
+
+
+ urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
+
+
+ if (!urb) {
+ uerr("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
+ uinfo("max seqnum %d\n", atomic_read(&the_controller->seqnum));
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+ return;
+ }
+
+
+ /* unpack the pdu to a urb */
+ usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
+
+
+ /* recv transfer buffer */
+ if (usbip_recv_xbuff(ud, urb) < 0)
+ return;
+
+
+ /* recv iso_packet_descriptor */
+ if (usbip_recv_iso(ud, urb) < 0)
+ return;
+
+
+ if (dbg_flag_vhci_rx)
+ usbip_dump_urb(urb);
+
+
+ dbg_vhci_rx("now giveback urb %p\n", urb);
+
+ spin_lock(&the_controller->lock);
+ usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+ spin_unlock(&the_controller->lock);
+
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+
+
+ dbg_vhci_rx("Leave\n");
+
+ return;
+}
+
+
+static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
+ struct usbip_header *pdu)
+{
+ struct vhci_unlink *unlink, *tmp;
+
+ spin_lock(&vdev->priv_lock);
+
+ list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
+ uinfo("unlink->seqnum %lu\n", unlink->seqnum);
+ if (unlink->seqnum == pdu->base.seqnum) {
+ dbg_vhci_rx("found pending unlink, %lu\n",
+ unlink->seqnum);
+ list_del(&unlink->list);
+
+ spin_unlock(&vdev->priv_lock);
+ return unlink;
+ }
+ }
+
+ spin_unlock(&vdev->priv_lock);
+
+ return NULL;
+}
+
+
+static void vhci_recv_ret_unlink(struct vhci_device *vdev,
+ struct usbip_header *pdu)
+{
+ struct vhci_unlink *unlink;
+ struct urb *urb;
+
+ usbip_dump_header(pdu);
+
+ unlink = dequeue_pending_unlink(vdev, pdu);
+ if (!unlink) {
+ uinfo("cannot find the pending unlink %u\n", pdu->base.seqnum);
+ return;
+ }
+
+ urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+ if (!urb) {
+ /*
+ * I get the result of a unlink request. But, it seems that I
+ * already received the result of its submit result and gave
+ * back the URB.
+ */
+ uinfo("the urb (seqnum %d) was already given backed\n",
+ pdu->base.seqnum);
+ } else {
+ dbg_vhci_rx("now giveback urb %p\n", urb);
+
+ /* If unlink is succeed, status is -ECONNRESET */
+ urb->status = pdu->u.ret_unlink.status;
+ uinfo("%d\n", urb->status);
+
+ spin_lock(&the_controller->lock);
+ usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+ spin_unlock(&the_controller->lock);
+
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+ urb->status);
+ }
+
+ kfree(unlink);
+
+ return;
+}
+
+/* recv a pdu */
+static void vhci_rx_pdu(struct usbip_device *ud)
+{
+ int ret;
+ struct usbip_header pdu;
+ struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+
+ dbg_vhci_rx("Enter\n");
+
+ memset(&pdu, 0, sizeof(pdu));
+
+
+ /* 1. receive a pdu header */
+ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+ if (ret != sizeof(pdu)) {
+ uerr("receiving pdu failed! size is %d, should be %d\n",
+ ret, sizeof(pdu));
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+ return;
+ }
+
+ usbip_header_correct_endian(&pdu, 0);
+
+ if (dbg_flag_vhci_rx)
+ usbip_dump_header(&pdu);
+
+ switch (pdu.base.command) {
+ case USBIP_RET_SUBMIT:
+ vhci_recv_ret_submit(vdev, &pdu);
+ break;
+ case USBIP_RET_UNLINK:
+ vhci_recv_ret_unlink(vdev, &pdu);
+ break;
+ default:
+ /* NOTREACHED */
+ uerr("unknown pdu %u\n", pdu.base.command);
+ usbip_dump_header(&pdu);
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+void vhci_rx_loop(struct usbip_task *ut)
+{
+ struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
+
+
+ while (1) {
+ if (signal_pending(current)) {
+ dbg_vhci_rx("signal catched!\n");
+ break;
+ }
+
+
+ if (usbip_event_happend(ud))
+ break;
+
+ vhci_rx_pdu(ud);
+ }
+}
+
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
new file mode 100644
index 00000000000..24c2851a8f8
--- /dev/null
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+#include <linux/in.h>
+
+/* TODO: refine locking ?*/
+
+/* Sysfs entry to show port status */
+static ssize_t show_status(struct device *dev, struct device_attribute *attr,
+ char *out)
+{
+ char *s = out;
+ int i = 0;
+
+ if (!the_controller || !out)
+ BUG();
+
+ spin_lock(&the_controller->lock);
+
+ /*
+ * output example:
+ * prt sta spd dev socket local_busid
+ * 000 004 000 000 c5a7bb80 1-2.3
+ * 001 004 000 000 d8cee980 2-3.4
+ *
+ * IP address can be retrieved from a socket pointer address by looking
+ * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
+ * port number and its peer IP address.
+ */
+ out += sprintf(out, "prt sta spd bus dev socket "
+ "local_busid\n");
+
+ for (i = 0; i < VHCI_NPORTS; i++) {
+ struct vhci_device *vdev = port_to_vdev(i);
+
+ spin_lock(&vdev->ud.lock);
+
+ out += sprintf(out, "%03u %03u ", i, vdev->ud.status);
+
+ if (vdev->ud.status == VDEV_ST_USED) {
+ out += sprintf(out, "%03u %08x ",
+ vdev->speed, vdev->devid);
+ out += sprintf(out, "%16p ", vdev->ud.tcp_socket);
+ out += sprintf(out, "%s", vdev->udev->dev.bus_id);
+
+ } else
+ out += sprintf(out, "000 000 000 0000000000000000 0-0");
+
+ out += sprintf(out, "\n");
+
+ spin_unlock(&vdev->ud.lock);
+ }
+
+ spin_unlock(&the_controller->lock);
+
+ return out - s;
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+/* Sysfs entry to shutdown a virtual connection */
+static int vhci_port_disconnect(__u32 rhport)
+{
+ struct vhci_device *vdev;
+
+ dbg_vhci_sysfs("enter\n");
+
+ /* lock */
+ spin_lock(&the_controller->lock);
+
+ vdev = port_to_vdev(rhport);
+
+ spin_lock(&vdev->ud.lock);
+ if (vdev->ud.status == VDEV_ST_NULL) {
+ uerr("not connected %d\n", vdev->ud.status);
+
+ /* unlock */
+ spin_unlock(&vdev->ud.lock);
+ spin_unlock(&the_controller->lock);
+
+ return -EINVAL;
+ }
+
+ /* unlock */
+ spin_unlock(&vdev->ud.lock);
+ spin_unlock(&the_controller->lock);
+
+ usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
+
+ return 0;
+}
+
+static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ __u32 rhport = 0;
+
+ sscanf(buf, "%u", &rhport);
+
+ /* check rhport */
+ if (rhport >= VHCI_NPORTS) {
+ uerr("invalid port %u\n", rhport);
+ return -EINVAL;
+ }
+
+ err = vhci_port_disconnect(rhport);
+ if (err < 0)
+ return -EINVAL;
+
+ dbg_vhci_sysfs("Leave\n");
+ return count;
+}
+static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
+
+/* Sysfs entry to establish a virtual connection */
+static int valid_args(__u32 rhport, enum usb_device_speed speed)
+{
+ /* check rhport */
+ if ((rhport < 0) || (rhport >= VHCI_NPORTS)) {
+ uerr("port %u\n", rhport);
+ return -EINVAL;
+ }
+
+ /* check speed */
+ switch (speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ case USB_SPEED_HIGH:
+ case USB_SPEED_VARIABLE:
+ break;
+ default:
+ uerr("speed %d\n", speed);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * To start a new USB/IP attachment, a userland program needs to setup a TCP
+ * connection and then write its socket descriptor with remote device
+ * information into this sysfs file.
+ *
+ * A remote device is virtually attached to the root-hub port of @rhport with
+ * @speed. @devid is embedded into a request to specify the remote device in a
+ * server host.
+ *
+ * write() returns 0 on success, else negative errno.
+ */
+static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct vhci_device *vdev;
+ struct socket *socket;
+ int sockfd = 0;
+ __u32 rhport = 0, devid = 0, speed = 0;
+
+ /*
+ * @rhport: port number of vhci_hcd
+ * @sockfd: socket descriptor of an established TCP connection
+ * @devid: unique device identifier in a remote host
+ * @speed: usb device speed in a remote host
+ */
+ sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed);
+
+ dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
+ rhport, sockfd, devid, speed);
+
+
+ /* check received parameters */
+ if (valid_args(rhport, speed) < 0)
+ return -EINVAL;
+
+ /* check sockfd */
+ socket = sockfd_to_socket(sockfd);
+ if (!socket)
+ return -EINVAL;
+
+ /* now need lock until setting vdev status as used */
+
+ /* begin a lock */
+ spin_lock(&the_controller->lock);
+
+ vdev = port_to_vdev(rhport);
+
+ spin_lock(&vdev->ud.lock);
+
+ if (vdev->ud.status != VDEV_ST_NULL) {
+ /* end of the lock */
+ spin_unlock(&vdev->ud.lock);
+ spin_unlock(&the_controller->lock);
+
+ uerr("port %d already used\n", rhport);
+ return -EINVAL;
+ }
+
+ uinfo("rhport(%u) sockfd(%d) devid(%u) speed(%u)\n",
+ rhport, sockfd, devid, speed);
+
+ vdev->devid = devid;
+ vdev->speed = speed;
+ vdev->ud.tcp_socket = socket;
+ vdev->ud.status = VDEV_ST_NOTASSIGNED;
+
+ spin_unlock(&vdev->ud.lock);
+ spin_unlock(&the_controller->lock);
+ /* end the lock */
+
+ /*
+ * this function will sleep, so should be out of the lock. but, it's ok
+ * because we already marked vdev as being used. really?
+ */
+ usbip_start_threads(&vdev->ud);
+
+ rh_port_connect(rhport, speed);
+
+ return count;
+}
+static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach);
+
+static struct attribute *dev_attrs[] = {
+ &dev_attr_status.attr,
+ &dev_attr_detach.attr,
+ &dev_attr_attach.attr,
+ &dev_attr_usbip_debug.attr,
+ NULL,
+};
+
+struct attribute_group dev_attr_group = {
+ .attrs = dev_attrs,
+};
diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
new file mode 100644
index 00000000000..1f552a95f48
--- /dev/null
+++ b/drivers/staging/usbip/vhci_tx.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+
+static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb)
+{
+ struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv);
+ struct vhci_device *vdev = priv->vdev;
+
+ dbg_vhci_tx("URB, local devnum %u, remote devid %u\n",
+ usb_pipedevice(urb->pipe), vdev->devid);
+
+ pdup->base.command = USBIP_CMD_SUBMIT;
+ pdup->base.seqnum = priv->seqnum;
+ pdup->base.devid = vdev->devid;
+ if (usb_pipein(urb->pipe))
+ pdup->base.direction = USBIP_DIR_IN;
+ else
+ pdup->base.direction = USBIP_DIR_OUT;
+ pdup->base.ep = usb_pipeendpoint(urb->pipe);
+
+ usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1);
+
+ if (urb->setup_packet)
+ memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8);
+}
+
+static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
+{
+ unsigned long flags;
+ struct vhci_priv *priv, *tmp;
+
+ spin_lock_irqsave(&vdev->priv_lock, flags);
+
+ list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
+ list_move_tail(&priv->list, &vdev->priv_rx);
+ spin_unlock_irqrestore(&vdev->priv_lock, flags);
+ return priv;
+ }
+
+ spin_unlock_irqrestore(&vdev->priv_lock, flags);
+
+ return NULL;
+}
+
+
+
+static int vhci_send_cmd_submit(struct vhci_device *vdev)
+{
+ struct vhci_priv *priv = NULL;
+
+ struct msghdr msg;
+ struct kvec iov[3];
+ size_t txsize;
+
+ size_t total_size = 0;
+
+ while ((priv = dequeue_from_priv_tx(vdev)) != NULL) {
+ int ret;
+ struct urb *urb = priv->urb;
+ struct usbip_header pdu_header;
+ void *iso_buffer = NULL;
+
+ txsize = 0;
+ memset(&pdu_header, 0, sizeof(pdu_header));
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov, 0, sizeof(iov));
+
+ dbg_vhci_tx("setup txdata urb %p\n", urb);
+
+
+ /* 1. setup usbip_header */
+ setup_cmd_submit_pdu(&pdu_header, urb);
+ usbip_header_correct_endian(&pdu_header, 1);
+
+ iov[0].iov_base = &pdu_header;
+ iov[0].iov_len = sizeof(pdu_header);
+ txsize += sizeof(pdu_header);
+
+ /* 2. setup transfer buffer */
+ if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) {
+ iov[1].iov_base = urb->transfer_buffer;
+ iov[1].iov_len = urb->transfer_buffer_length;
+ txsize += urb->transfer_buffer_length;
+ }
+
+ /* 3. setup iso_packet_descriptor */
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+ ssize_t len = 0;
+
+ iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
+ if (!iso_buffer) {
+ usbip_event_add(&vdev->ud,
+ SDEV_EVENT_ERROR_MALLOC);
+ return -1;
+ }
+
+ iov[2].iov_base = iso_buffer;
+ iov[2].iov_len = len;
+ txsize += len;
+ }
+
+ ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize);
+ if (ret != txsize) {
+ uerr("sendmsg failed!, retval %d for %zd\n", ret,
+ txsize);
+ kfree(iso_buffer);
+ usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
+ return -1;
+ }
+
+ kfree(iso_buffer);
+ dbg_vhci_tx("send txdata\n");
+
+ total_size += txsize;
+ }
+
+ return total_size;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
+{
+ unsigned long flags;
+ struct vhci_unlink *unlink, *tmp;
+
+ spin_lock_irqsave(&vdev->priv_lock, flags);
+
+ list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+ list_move_tail(&unlink->list, &vdev->unlink_rx);
+ spin_unlock_irqrestore(&vdev->priv_lock, flags);
+ return unlink;
+ }
+
+ spin_unlock_irqrestore(&vdev->priv_lock, flags);
+
+ return NULL;
+}
+
+static int vhci_send_cmd_unlink(struct vhci_device *vdev)
+{
+ struct vhci_unlink *unlink = NULL;
+
+ struct msghdr msg;
+ struct kvec iov[3];
+ size_t txsize;
+
+ size_t total_size = 0;
+
+ while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) {
+ int ret;
+ struct usbip_header pdu_header;
+
+ txsize = 0;
+ memset(&pdu_header, 0, sizeof(pdu_header));
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov, 0, sizeof(iov));
+
+ dbg_vhci_tx("setup cmd unlink, %lu \n", unlink->seqnum);
+
+
+ /* 1. setup usbip_header */
+ pdu_header.base.command = USBIP_CMD_UNLINK;
+ pdu_header.base.seqnum = unlink->seqnum;
+ pdu_header.base.devid = vdev->devid;
+ pdu_header.base.ep = 0;
+ pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum;
+
+ usbip_header_correct_endian(&pdu_header, 1);
+
+ iov[0].iov_base = &pdu_header;
+ iov[0].iov_len = sizeof(pdu_header);
+ txsize += sizeof(pdu_header);
+
+ ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize);
+ if (ret != txsize) {
+ uerr("sendmsg failed!, retval %d for %zd\n", ret,
+ txsize);
+ usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
+ return -1;
+ }
+
+
+ dbg_vhci_tx("send txdata\n");
+
+ total_size += txsize;
+ }
+
+ return total_size;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+void vhci_tx_loop(struct usbip_task *ut)
+{
+ struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
+ struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+ while (1) {
+ if (signal_pending(current)) {
+ uinfo("vhci_tx signal catched\n");
+ break;
+ }
+
+ if (vhci_send_cmd_submit(vdev) < 0)
+ break;
+
+ if (vhci_send_cmd_unlink(vdev) < 0)
+ break;
+
+ wait_event_interruptible(vdev->waitq_tx,
+ (!list_empty(&vdev->priv_tx) ||
+ !list_empty(&vdev->unlink_tx)));
+
+ dbg_vhci_tx("pending urbs ?, now wake up\n");
+ }
+}
diff --git a/drivers/staging/winbond/Kconfig b/drivers/staging/winbond/Kconfig
new file mode 100644
index 00000000000..10d72bec88a
--- /dev/null
+++ b/drivers/staging/winbond/Kconfig
@@ -0,0 +1,7 @@
+config W35UND
+ tristate "Winbond driver"
+ depends on MAC80211 && WLAN_80211 && EXPERIMENTAL && !4KSTACKS
+ default n
+ ---help---
+ This is highly experimental driver for winbond wifi card on some Kohjinsha notebooks
+ Check http://code.google.com/p/winbondport/ for new version
diff --git a/drivers/staging/winbond/Makefile b/drivers/staging/winbond/Makefile
new file mode 100644
index 00000000000..29c98bf1bc9
--- /dev/null
+++ b/drivers/staging/winbond/Makefile
@@ -0,0 +1,18 @@
+ DRIVER_DIR=./linux
+
+w35und-objs := $(DRIVER_DIR)/wbusb.o $(DRIVER_DIR)/wb35reg.o $(DRIVER_DIR)/wb35rx.o $(DRIVER_DIR)/wb35tx.o \
+ mds.o \
+ mlmetxrx.o \
+ mto.o \
+ phy_calibration.o \
+ reg.o \
+ rxisr.o \
+ sme_api.o \
+ wbhal.o \
+ wblinux.o \
+
+
+obj-$(CONFIG_W35UND) += w35und.o
+
+
+
diff --git a/drivers/staging/winbond/README b/drivers/staging/winbond/README
new file mode 100644
index 00000000000..707b6b354dc
--- /dev/null
+++ b/drivers/staging/winbond/README
@@ -0,0 +1,10 @@
+TODO:
+ - sparse cleanups
+ - checkpatch cleanups
+ - kerneldoc cleanups
+ - remove typedefs
+ - remove unused ioctls
+ - use cfg80211 for regulatory stuff
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
+Pavel Machek <pavel@suse.cz>
diff --git a/drivers/staging/winbond/adapter.h b/drivers/staging/winbond/adapter.h
new file mode 100644
index 00000000000..609701d21cf
--- /dev/null
+++ b/drivers/staging/winbond/adapter.h
@@ -0,0 +1,23 @@
+//
+// ADAPTER.H -
+// Windows NDIS global variable 'Adapter' typedef
+//
+#define MAX_ANSI_STRING 40
+typedef struct WB32_ADAPTER
+{
+ u32 AdapterIndex; // 20060703.4 Add for using pAdapterContext global Adapter point
+
+ WB_LOCALDESCRIPT sLocalPara; // Myself connected parameters
+ PWB_BSSDESCRIPTION asBSSDescriptElement;
+
+ MLME_FRAME sMlmeFrame; // connect to peerSTA parameters
+
+ MTO_PARAMETERS sMtoPara; // MTO_struct ...
+ hw_data_t sHwData; //For HAL
+ MDS Mds;
+
+ WBLINUX WbLinux;
+ struct iw_statistics iw_stats;
+
+ u8 LinkName[MAX_ANSI_STRING];
+} WB32_ADAPTER, ADAPTER, *PWB32_ADAPTER, *PADAPTER;
diff --git a/drivers/staging/winbond/bss_f.h b/drivers/staging/winbond/bss_f.h
new file mode 100644
index 00000000000..c957bc94f08
--- /dev/null
+++ b/drivers/staging/winbond/bss_f.h
@@ -0,0 +1,59 @@
+//
+// BSS descriptor DataBase management global function
+//
+
+void vBSSdescriptionInit(PWB32_ADAPTER Adapter);
+void vBSSfoundList(PWB32_ADAPTER Adapter);
+u8 boChanFilter(PWB32_ADAPTER Adapter, u8 ChanNo);
+u16 wBSSallocateEntry(PWB32_ADAPTER Adapter);
+u16 wBSSGetEntry(PWB32_ADAPTER Adapter);
+void vSimpleHouseKeeping(PWB32_ADAPTER Adapter);
+u16 wBSShouseKeeping(PWB32_ADAPTER Adapter);
+void ClearBSSdescpt(PWB32_ADAPTER Adapter, u16 i);
+u16 wBSSfindBssID(PWB32_ADAPTER Adapter, u8 *pbBssid);
+u16 wBSSfindDedicateCandidate(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid, u8 *pbBssid);
+u16 wBSSfindMACaddr(PWB32_ADAPTER Adapter, u8 *pbMacAddr);
+u16 wBSSsearchMACaddr(PWB32_ADAPTER Adapter, u8 *pbMacAddr, u8 band);
+u16 wBSSaddScanData(PWB32_ADAPTER, u16, psRXDATA);
+u16 wBSSUpdateScanData(PWB32_ADAPTER Adapter, u16 wBssIdx, psRXDATA psRcvData);
+u16 wBSScreateIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData);
+void DesiredRate2BSSdescriptor(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData,
+ u8 *pBasicRateSet, u8 BasicRateCount,
+ u8 *pOperationRateSet, u8 OperationRateCount);
+void DesiredRate2InfoElement(PWB32_ADAPTER Adapter, u8 *addr, u16 *iFildOffset,
+ u8 *pBasicRateSet, u8 BasicRateCount,
+ u8 *pOperationRateSet, u8 OperationRateCount);
+void BSSAddIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData);
+unsigned char boCmpMacAddr( PUCHAR, PUCHAR );
+unsigned char boCmpSSID(struct SSID_Element *psSSID1, struct SSID_Element *psSSID2);
+u16 wBSSfindSSID(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid);
+u16 wRoamingQuery(PWB32_ADAPTER Adapter);
+void vRateToBitmap(PWB32_ADAPTER Adapter, u16 index);
+u8 bRateToBitmapIndex(PWB32_ADAPTER Adapter, u8 bRate);
+u8 bBitmapToRate(u8 i);
+unsigned char boIsERPsta(PWB32_ADAPTER Adapter, u16 i);
+unsigned char boCheckConnect(PWB32_ADAPTER Adapter);
+unsigned char boCheckSignal(PWB32_ADAPTER Adapter);
+void AddIBSSIe(PWB32_ADAPTER Adapter,PWB_BSSDESCRIPTION psDesData );//added by ws for WPA_None06/01/04
+void BssScanUpToDate(PWB32_ADAPTER Adapter);
+void BssUpToDate(PWB32_ADAPTER Adapter);
+void RateSort(u8 *RateArray, u8 num, u8 mode);
+void RateReSortForSRate(PWB32_ADAPTER Adapter, u8 *RateArray, u8 num);
+void Assemble_IE(PWB32_ADAPTER Adapter, u16 wBssIdx);
+void SetMaxTxRate(PWB32_ADAPTER Adapter);
+
+void CreateWpaIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
+ struct Association_Request_Frame_Body* msgBody, u16 iMSindex); //added by WS 05/14/05
+
+#ifdef _WPA2_
+void CreateRsnIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
+ struct Association_Request_Frame_Body* msgBody, u16 iMSindex);//added by WS 05/14/05
+
+u16 SearchPmkid(PWB32_ADAPTER Adapter, struct Management_Frame* msgHeader,
+ struct PMKID_Information_Element * AssoReq_PMKID );
+#endif
+
+
+
+
+
diff --git a/drivers/staging/winbond/bssdscpt.h b/drivers/staging/winbond/bssdscpt.h
new file mode 100644
index 00000000000..97150a2655f
--- /dev/null
+++ b/drivers/staging/winbond/bssdscpt.h
@@ -0,0 +1,156 @@
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// bssdscpt.c
+// BSS descriptor data base
+// history :
+//
+// Description:
+// BSS descriptor data base will store the information of the stations at the
+// surrounding environment. The first entry( psBSS(0) ) will not be used and the
+// second one( psBSS(1) ) will be used for the broadcast address.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//#define MAX_ACC_RSSI_COUNT 10
+#define MAX_ACC_RSSI_COUNT 6
+
+///////////////////////////////////////////////////////////////////////////
+//
+// BSS Description set Element , to store scan received Beacon information
+//
+// Our's differs slightly from the specs. The specify a PHY_Parameter_Set.
+// Since we're only doing a DS design right now, we just have a DS structure.
+//////////////////////////////////////////////////////////////////////////////
+typedef struct BSSDescriptionElement
+{
+ u32 SlotValid;
+ u32 PowerSaveMode;
+ RXLAYER1 RxLayer1;
+
+ u8 abPeerAddress[ MAC_ADDR_LENGTH + 2 ]; // peer MAC Address associated with this session. 6-OCTET value
+ u32 dwBgScanStamp; // BgScan Sequence Counter stamp, record psROAM->dwScanCounter.
+
+ u16 Beacon_Period;
+ u16 wATIM_Window;
+
+ u8 abBssID[ MAC_ADDR_LENGTH + 2 ]; // 6B
+
+ u8 bBssType;
+ u8 DTIM_Period; // 1 octet usually from TIM element, if present
+ u8 boInTimerHandler;
+ u8 boERP; // analysis ERP or (extended) supported rate element
+
+ u8 Timestamp[8];
+ u8 BasicRate[32];
+ u8 OperationalRate[32];
+ u32 dwBasicRateBitmap; //bit map, retrieve from SupportedRateSet
+ u32 dwOperationalRateBitmap; //bit map, retrieve from SupportedRateSet and
+ // ExtendedSupportedRateSet
+ // For RSSI calculating
+ u32 HalRssi[MAX_ACC_RSSI_COUNT]; // Encode. It must use MACRO of HAL to get the LNA and AGC data
+ u32 HalRssiIndex;
+
+ ////From beacon/probe response
+ struct SSID_Element SSID; // 34B
+ u8 reserved_1[ 2 ];
+
+ struct Capability_Information_Element CapabilityInformation; // 2B
+ u8 reserved_2[ 2 ];
+
+ struct CF_Parameter_Set_Element CF_Parameter_Set; // 8B
+ struct IBSS_Parameter_Set_Element IBSS_Parameter_Set; // 4B
+ struct TIM_Element TIM_Element_Set; // 256B
+
+ struct DS_Parameter_Set_Element DS_Parameter_Set; // 3B
+ u8 reserved_3;
+
+ struct ERP_Information_Element ERP_Information_Set; // 3B
+ u8 reserved_4;
+
+ struct Supported_Rates_Element SupportedRateSet; // 10B
+ u8 reserved_5[2];
+
+ struct Extended_Supported_Rates_Element ExtendedSupportedRateSet; // 257B
+ u8 reserved_6[3];
+
+ u8 band;
+ u8 reserved_7[3];
+
+ // for MLME module
+ u16 wState; // the current state of the system
+ u16 wIndex; // THIS BSS element entry index
+
+ void* psAdapter; // pointer to THIS Adapter
+ OS_TIMER nTimer; // MLME timer
+
+ // Authentication
+ u16 wAuthAlgo; // peer MAC MLME use Auth algorithm, default OPEN_AUTH
+ u16 wAuthSeqNum; // current local MAC sendout AuthReq sequence number
+
+ u8 auth_challengeText[128];
+
+ ////For XP:
+ u32 ies_len; // information element length
+ u8 ies[256]; // information element
+
+ ////For WPA
+ u8 RsnIe_Type[2]; //added by ws for distinguish WPA and WPA2 05/14/04
+ u8 RsnIe_len;
+ u8 Rsn_Num;
+
+ // to record the rsn cipher suites,addded by ws 09/05/04
+ SUITE_SELECTOR group_cipher; // 4B
+ SUITE_SELECTOR pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT];
+ SUITE_SELECTOR auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT];
+
+ u16 pairwise_key_cipher_suite_count;
+ u16 auth_key_mgt_suite_count;
+
+ u8 pairwise_key_cipher_suite_selected;
+ u8 auth_key_mgt_suite_selected;
+ u8 reserved_8[2];
+
+ struct RSN_Capability_Element rsn_capabilities; // 2B
+ u8 reserved_9[2];
+
+ //to record the rsn cipher suites for WPA2
+ #ifdef _WPA2_
+ u32 pre_auth; //added by WS for distinguish for 05/04/04
+ SUITE_SELECTOR wpa2_group_cipher; // 4B
+ SUITE_SELECTOR wpa2_pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT];
+ SUITE_SELECTOR wpa2_auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT];
+
+ u16 wpa2_pairwise_key_cipher_suite_count;
+ u16 wpa2_auth_key_mgt_suite_count;
+
+ u8 wpa2_pairwise_key_cipher_suite_selected;
+ u8 wpa2_auth_key_mgt_suite_selected;
+ u8 reserved_10[2];
+
+ struct RSN_Capability_Element wpa2_rsn_capabilities; // 2B
+ u8 reserved_11[2];
+ #endif //endif _WPA2_
+
+ //For Replay protection
+// u8 PairwiseTSC[6];
+// u8 GroupTSC[6];
+
+ ////For up-to-date
+ u32 ScanTimeStamp; //for the decision whether the station/AP(may exist at
+ //different channels) has left. It must be detected by
+ //scanning. Local device may connected or disconnected.
+ u32 BssTimeStamp; //Only for the decision whether the station/AP(exist in
+ //the same channel, and no scanning) if local device has
+ //connected successfully.
+
+ // 20061108 Add for storing WPS_IE. [E id][Length][OUI][Data]
+ u8 WPS_IE_Data[MAX_IE_APPEND_SIZE];
+ u16 WPS_IE_length;
+ u16 WPS_IE_length_tmp; // For verify there is an WPS_IE in Beacon or probe response
+
+} WB_BSSDESCRIPTION, *PWB_BSSDESCRIPTION;
+
+#define wBSSConnectedSTA(Adapter) \
+ ((u16)(Adapter)->sLocalPara.wConnectedSTAindex)
+
+#define psBSS(i) (&(Adapter->asBSSDescriptElement[(i)]))
+
+
diff --git a/drivers/staging/winbond/ds_tkip.h b/drivers/staging/winbond/ds_tkip.h
new file mode 100644
index 00000000000..29e5055b45a
--- /dev/null
+++ b/drivers/staging/winbond/ds_tkip.h
@@ -0,0 +1,33 @@
+// Rotation functions on 32 bit values
+#define ROL32( A, n ) \
+ ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
+
+#define ROR32( A, n ) ROL32( (A), 32-(n) )
+
+
+typedef struct tkip
+{
+ u32 K0, K1; // Key
+ union
+ {
+ struct // Current state
+ {
+ u32 L;
+ u32 R;
+ };
+ u8 LR[8];
+ };
+ union
+ {
+ u32 M; // Message accumulator (single word)
+ u8 Mb[4];
+ };
+ s32 bytes_in_M; // # bytes in M
+} tkip_t;
+
+//void _append_data( PUCHAR pData, u16 size, tkip_t *p );
+void Mds_MicGet( void* Adapter, void* pRxLayer1, PUCHAR pKey, PUCHAR pMic );
+void Mds_MicFill( void* Adapter, void* pDes, PUCHAR XmitBufAddress );
+
+
+
diff --git a/drivers/staging/winbond/gl_80211.h b/drivers/staging/winbond/gl_80211.h
new file mode 100644
index 00000000000..1806d817496
--- /dev/null
+++ b/drivers/staging/winbond/gl_80211.h
@@ -0,0 +1,125 @@
+
+#ifndef __GL_80211_H__
+#define __GL_80211_H__
+
+/****************** CONSTANT AND MACRO SECTION ******************************/
+
+/* BSS Type */
+enum {
+ WLAN_BSSTYPE_INFRASTRUCTURE = 0,
+ WLAN_BSSTYPE_INDEPENDENT,
+ WLAN_BSSTYPE_ANY_BSS,
+};
+
+
+
+/* Preamble_Type, see <SFS-802.11G-MIB-203> */
+typedef enum preamble_type {
+ WLAN_PREAMBLE_TYPE_SHORT,
+ WLAN_PREAMBLE_TYPE_LONG,
+} preamble_type_e;
+
+
+/* Slot_Time_Type, see <SFS-802.11G-MIB-208> */
+typedef enum slot_time_type {
+ WLAN_SLOT_TIME_TYPE_LONG,
+ WLAN_SLOT_TIME_TYPE_SHORT,
+} slot_time_type_e;
+
+/*--------------------------------------------------------------------------*/
+/* Encryption Mode */
+typedef enum {
+ WEP_DISABLE = 0,
+ WEP_64,
+ WEP_128,
+
+ ENCRYPT_DISABLE,
+ ENCRYPT_WEP,
+ ENCRYPT_WEP_NOKEY,
+ ENCRYPT_TKIP,
+ ENCRYPT_TKIP_NOKEY,
+ ENCRYPT_CCMP,
+ ENCRYPT_CCMP_NOKEY,
+} encryption_mode_e;
+
+typedef enum _WLAN_RADIO {
+ WLAN_RADIO_ON,
+ WLAN_RADIO_OFF,
+ WLAN_RADIO_MAX, // not a real type, defined as an upper bound
+} WLAN_RADIO;
+
+typedef struct _WLAN_RADIO_STATUS {
+ WLAN_RADIO HWStatus;
+ WLAN_RADIO SWStatus;
+} WLAN_RADIO_STATUS;
+
+//----------------------------------------------------------------------------
+// 20041021 1.1.81.1000 ybjiang
+// add for radio notification
+typedef
+void (*RADIO_NOTIFICATION_HANDLER)(
+ void *Data,
+ void *RadioStatusBuffer,
+ u32 RadioStatusBufferLen
+ );
+
+typedef struct _WLAN_RADIO_NOTIFICATION
+{
+ RADIO_NOTIFICATION_HANDLER RadioChangeHandler;
+ void *Data;
+} WLAN_RADIO_NOTIFICATION;
+
+//----------------------------------------------------------------------------
+// 20041102 1.1.91.1000 ybjiang
+// add for OID_802_11_CUST_REGION_CAPABILITIES and OID_802_11_OID_REGION
+typedef enum _WLAN_REGION_CODE
+{
+ WLAN_REGION_UNKNOWN,
+ WLAN_REGION_EUROPE,
+ WLAN_REGION_JAPAN,
+ WLAN_REGION_USA,
+ WLAN_REGION_FRANCE,
+ WLAN_REGION_SPAIN,
+ WLAN_REGION_ISRAEL,
+ WLAN_REGION_MAX, // not a real type, defined as an upper bound
+} WLAN_REGION_CODE;
+
+#define REGION_NAME_MAX_LENGTH 256
+
+typedef struct _WLAN_REGION_CHANNELS
+{
+ u32 Length;
+ u32 NameLength;
+ u8 Name[REGION_NAME_MAX_LENGTH];
+ WLAN_REGION_CODE Code;
+ u32 Frequency[1];
+} WLAN_REGION_CHANNELS;
+
+typedef struct _WLAN_REGION_CAPABILITIES
+{
+ u32 NumberOfItems;
+ WLAN_REGION_CHANNELS Region[1];
+} WLAN_REGION_CAPABILITIES;
+
+typedef struct _region_name_map {
+ WLAN_REGION_CODE region;
+ u8 *name;
+ u32 *channels;
+} region_name_map;
+
+/*--------------------------------------------------------------------------*/
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
+
+// TODO: 0627 kevin
+#define MIC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
+#define MICSTR "%02X %02X %02X %02X %02X %02X %02X %02X"
+
+#define MICKEY2STR(a) MIC2STR(a)
+#define MICKEYSTR MICSTR
+
+
+#endif /* __GL_80211_H__ */
+/*** end of file ***/
+
+
diff --git a/drivers/staging/winbond/ioctls.h b/drivers/staging/winbond/ioctls.h
new file mode 100644
index 00000000000..e8b35dc7e32
--- /dev/null
+++ b/drivers/staging/winbond/ioctls.h
@@ -0,0 +1,678 @@
+//============================================================================
+// IOCTLS.H -
+//
+// Description:
+// Define the IOCTL codes.
+//
+// Revision history:
+// --------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2004 Winbond Electronics Corp. All rights reserved.
+//=============================================================================
+
+#ifndef _IOCTLS_H
+#define _IOCTLS_H
+
+// PD43 Keep it - Used with the Win33 application
+// #include <winioctl.h>
+
+//========================================================
+// 20040108 ADD the follow for test
+//========================================================
+#define INFORMATION_LENGTH sizeof(unsigned int)
+
+#define WB32_IOCTL_INDEX 0x0900 //­×§ďĽHŤKŹŰŽe//
+
+#define Wb32_RegisterRead CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 0, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_RegisterWrite CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_SendPacket CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 2, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_QuerySendResult CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_SetFragmentThreshold CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_SetLinkStatus CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_SetBulkIn CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb32_LoopbackTest CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_EEPromRead CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_EEPromWrite CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 9, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_FlashReadData CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 10, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_FlashWrite CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 11, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_FlashWriteBurst CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 12, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_TxBurstStart CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 13, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_TxBurstStop CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 14, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define Wb35_TxBurstStatus CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB32_IOCTL_INDEX + 15, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// For IOCTL interface
+//================================================
+#define LINKNAME_STRING "\\DosDevices\\W35UND"
+#define NTDEVICE_STRING "\\Device\\W35UND"
+#define APPLICATION_LINK "\\\\.\\W35UND"
+
+#define WB_IOCTL_INDEX 0x0800
+#define WB_IOCTL_TS_INDEX WB_IOCTL_INDEX + 60
+#define WB_IOCTL_DUT_INDEX WB_IOCTL_TS_INDEX + 40
+
+//=============================================================================
+// IOCTLS defined for DUT (Device Under Test)
+
+// IOCTL_WB_802_11_DUT_MAC_ADDRESS
+// Query: Return the dot11StationID
+// Set : Set the dot11StationID. Demo only.
+//
+#define IOCTL_WB_802_11_DUT_MAC_ADDRESS CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_BSS_DESCRIPTION
+// Query: Return the info. of the current connected BSS.
+// Set : None.
+//
+#define IOCTL_WB_802_11_DUT_BSS_DESCRIPTION CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 2, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_TX_RATE
+// Query: Return the current transmission rate.
+// Set : Set the transmission rate of the Tx packets.
+//
+#define IOCTL_WB_802_11_DUT_TX_RATE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_CURRENT_STA_STATE
+// Query: Return the current STA state. (WB_STASTATE type)
+// Set : None.
+//
+#define IOCTL_WB_802_11_DUT_CURRENT_STA_STATE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+/////////// 10/31/02' Added /////////////////////
+
+// IOCTL_WB_802_11_DUT_START_IBSS_REQUEST
+// Query: None.
+// Set : Start a new IBSS
+//
+#define IOCTL_WB_802_11_DUT_START_IBSS_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_JOIN_REQUEST
+// Query: None.
+// Set : Synchronize with the selected BSS
+//
+#define IOCTL_WB_802_11_DUT_JOIN_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_AUTHEN_REQUEST
+// Query: None.
+// Set : Authenticate with the BSS
+//
+#define IOCTL_WB_802_11_DUT_AUTHEN_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST
+// Query: None.
+// Set : DeAuthenticate withe the BSS
+//
+#define IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_ASSOC_REQUEST
+// Query: None.
+// Set : Associate withe the BSS
+//
+#define IOCTL_WB_802_11_DUT_ASSOC_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 9, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_REASSOC_REQUEST
+// Query: None.
+// Set : ReAssociate withe the BSS
+//
+#define IOCTL_WB_802_11_DUT_REASSOC_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 10, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+
+// IOCTL_WB_802_11_DUT_DISASSOC_REQUEST
+// Query: None.
+// Set : DisAssociate withe the BSS
+//
+#define IOCTL_WB_802_11_DUT_DISASSOC_REQUEST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 11, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_FRAG_THRESHOLD
+// Query: Return the dot11FragmentThreshold
+// Set : Set the dot11FragmentThreshold
+//
+#define IOCTL_WB_802_11_DUT_FRAG_THRESHOLD CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 12, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_RTS_THRESHOLD
+// Query: Return the dot11RTSThreshold
+// Set : Set the dot11RTSThresold
+//
+#define IOCTL_WB_802_11_DUT_RTS_THRESHOLD CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 13, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_WEP_KEYMODE
+// Query: Get the WEP key mode.
+// Set : Set the WEP key mode: disable/64 bits/128 bits
+//
+#define IOCTL_WB_802_11_DUT_WEP_KEYMODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 14, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_WEP_KEYVALUE
+// Query: None.
+// Set : fill in the WEP key value
+//
+#define IOCTL_WB_802_11_DUT_WEP_KEYVALUE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 15, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_RESET
+// Query: None.
+// Set : Reset S/W and H/W
+//
+#define IOCTL_WB_802_11_DUT_RESET CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 16, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_POWER_SAVE
+// Query: None.
+// Set : Set Power Save Mode
+//
+#define IOCTL_WB_802_11_DUT_POWER_SAVE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 17, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN
+// Query: None.
+// Set :
+//
+#define IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 18, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_BSSID_LIST
+// Query: Return the BSS info of BSSs in the last scanning process
+// Set : None.
+//
+#define IOCTL_WB_802_11_DUT_BSSID_LIST CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 19, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_STATISTICS
+// Query: Return the statistics of Tx/Rx.
+// Set : None.
+//
+#define IOCTL_WB_802_11_DUT_STATISTICS CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 20, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_ACCEPT_BEACON
+// Query: Return the current mode to accept beacon or not.
+// Set : Enable or disable allowing the HW-MAC to pass the beacon to the SW-MAC
+// Arguments: unsigned char
+//
+#define IOCTL_WB_802_11_DUT_ACCEPT_BEACON CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 21, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_ROAMING
+// Query: Return the roaming function status
+// Set : Enable/Disable the roaming function.
+#define IOCTL_WB_802_11_DUT_ROAMING CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 22, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_DTO
+// Query: Return the DTO(Data Throughput Optimization)
+// function status (TRUE or FALSE)
+// Set : Enable/Disable the DTO function.
+//
+#define IOCTL_WB_802_11_DUT_DTO CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 23, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY
+// Query: Return the antenna diversity status. (TRUE/ON or FALSE/OFF)
+// Set : Enable/Disable the antenna diversity.
+//
+#define IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 24, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+//-------------- new added for a+b+g ---------------------
+// IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE
+// Query: Return the MAC operation mode. (MODE_802_11_BG, MODE_802_11_A,
+// MODE_802_11_ABG, MODE_802_11_BG_IBSS)
+// Set : Set the MAC operation mode.
+//
+#define IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 25, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED
+// Query: Return the current tx rate which follows the definition in spec. (for
+// example, 5.5M => 0x0b)
+// Set : None
+//
+#define IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 26, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_PREAMBLE_MODE
+// Query: Return the preamble mode. (auto or long)
+// Set : Set the preamble mode.
+//
+#define IOCTL_WB_802_11_DUT_PREAMBLE_MODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 27, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_SLOT_TIME_MODE
+// Query: Return the slot time mode. (auto or long)
+// Set : Set the slot time mode.
+//
+#define IOCTL_WB_802_11_DUT_SLOT_TIME_MODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 28, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+//------------------------------------------------------------------
+
+// IOCTL_WB_802_11_DUT_ADVANCE_STATUS
+// Query:
+// Set : NONE
+//
+#define IOCTL_WB_802_11_DUT_ADVANCE_STATUS CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 29, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_TX_RATE_MODE
+// Query: Return the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX)
+// Set : Set the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX)
+//
+#define IOCTL_WB_802_11_DUT_TX_RATE_MODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 30, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_DTO_PARA
+// Query: Return the DTO parameters
+// Set : Set the DTO parameters
+//
+#define IOCTL_WB_802_11_DUT_DTO_PARA CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 31, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_EVENT_LOG
+// Query: Return event log
+// Set : Reset event log
+//
+#define IOCTL_WB_802_11_DUT_EVENT_LOG CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 32, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_CWMIN
+// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS)
+// Set : Set CWMin value
+//
+#define IOCTL_WB_802_11_DUT_CWMIN CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 33, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_DUT_CWMAX
+// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS)
+// Set : Set CWMax value
+//
+#define IOCTL_WB_802_11_DUT_CWMAX CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_DUT_INDEX + 34, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+
+//==========================================================
+// IOCTLs for Testing
+
+// IOCTL_WB_802_11_TS_SET_CXX_REG
+// Query: None
+// Set : Write the value to one of Cxx register.
+//
+#define IOCTL_WB_802_11_TS_SET_CXX_REG CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 0, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_TS_GET_CXX_REG
+// Query: Return the value of the Cxx register.
+// Set : Write the reg no. (0x00, 0x04, 0x08 etc)
+//
+#define IOCTL_WB_802_11_TS_GET_CXX_REG CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_TS_SET_DXX_REG
+// Query: None
+// Set : Write the value to one of Dxx register.
+//
+#define IOCTL_WB_802_11_TS_SET_DXX_REG CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 2, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// IOCTL_WB_802_11_TS_GET_DXX_REG
+// Query: Return the value of the Dxx register.
+// Set : Write the reg no. (0x00, 0x04, 0x08 etc)
+//
+#define IOCTL_WB_802_11_TS_GET_DXX_REG CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+//============================================================
+// [TS]
+
+#define IOCTL_WB_802_11_TS_TX_RATE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_CURRENT_CHANNEL CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_ENABLE_SEQNO CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_ENALBE_ACKEDPACKET CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_INHIBIT_CRC CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_RESET_RCV_COUNTER CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 9, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_SET_TX_TRIGGER CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 10, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_FAILED_TX_COUNT CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 11, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// [TS1]
+#define IOCTL_WB_802_11_TS_TX_POWER CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 12, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_MODE_ENABLE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 13, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_MODE_DISABLE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 14, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_ANTENNA CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 15, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_ADAPTER_INFO CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 16, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_MAC_ADDRESS CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 17, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_BSSID CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 18, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_RF_PARAMETER CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 19, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_FILTER CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 20, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_CALIBRATION CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 21, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_BSS_MODE CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 22, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_SET_SSID CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 23, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_IBSS_CHANNEL CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 24, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+// set/query the slot time value(short or long slot time)
+#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 25, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 25, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#define IOCTL_WB_802_11_TS_RX_STATISTICS CTL_CODE( \
+ FILE_DEVICE_UNKNOWN, \
+ WB_IOCTL_TS_INDEX + 26, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+#endif // #ifndef _IOCTLS_H
+
+
diff --git a/drivers/staging/winbond/linux/common.h b/drivers/staging/winbond/linux/common.h
new file mode 100644
index 00000000000..6b00bad74f7
--- /dev/null
+++ b/drivers/staging/winbond/linux/common.h
@@ -0,0 +1,143 @@
+//
+// common.h
+//
+// This file contains the OS dependant definition and function.
+// Every OS has this file individual.
+//
+
+#define DebugUsbdStatusInformation( _A )
+
+#ifndef COMMON_DEF
+#define COMMON_DEF
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/kernel.h> //need for kernel alert
+#include <linux/autoconf.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h> //memory allocate
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>//need for init and exit modules marco
+#include <linux/ctype.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+#include <net/iw_handler.h>
+#include <linux/skbuff.h>
+
+
+//#define DEBUG_ENABLED 1
+
+
+
+//===============================================================
+// Common type definition
+//===============================================================
+
+typedef u8* PUCHAR;
+typedef s8* PCHAR;
+typedef u8* PBOOLEAN;
+typedef u16* PUSHORT;
+typedef u32* PULONG;
+typedef s16* PSHORT;
+
+
+//===========================================
+#define IGNORE 2
+#define SUCCESS 1
+#define FAILURE 0
+
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+// PD43 20021108
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define STATUS_MEDIA_CONNECT 1
+#define STATUS_MEDIA_DISCONNECT 0
+
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+
+typedef struct urb * PURB;
+
+
+
+//==================================================================================================
+// Common function definition
+//==================================================================================================
+#ifndef abs
+#define abs(_T) ((_T) < 0 ? -_T : _T)
+#endif
+#define DEBUG_ENABLED
+#define ETH_LENGTH_OF_ADDRESS 6
+#ifdef DEBUG_ENABLED
+#define WBDEBUG( _M ) printk _M
+#else
+#define WBDEBUG( _M ) 0
+#endif
+
+#define OS_DISCONNECTED 0
+#define OS_CONNECTED 1
+
+
+#define OS_EVENT_INDICATE( _A, _B, _F )
+#define OS_PMKID_STATUS_EVENT( _A )
+
+
+/* Uff, no, longs are not atomic on all architectures Linux
+ * supports. This should really use atomic_t */
+
+#define OS_ATOMIC u32
+#define OS_ATOMIC_READ( _A, _V ) _V
+#define OS_ATOMIC_INC( _A, _V ) EncapAtomicInc( _A, (void*)_V )
+#define OS_ATOMIC_DEC( _A, _V ) EncapAtomicDec( _A, (void*)_V )
+#define OS_MEMORY_CLEAR( _A, _S ) memset( (PUCHAR)_A,0,_S)
+#define OS_MEMORY_COMPARE( _A, _B, _S ) (memcmp(_A,_B,_S)? 0 : 1) // Definition is reverse with Ndis 1: the same 0: different
+
+
+#define OS_SPIN_LOCK spinlock_t
+#define OS_SPIN_LOCK_ALLOCATE( _S ) spin_lock_init( _S );
+#define OS_SPIN_LOCK_FREE( _S )
+#define OS_SPIN_LOCK_ACQUIRED( _S ) spin_lock_irq( _S )
+#define OS_SPIN_LOCK_RELEASED( _S ) spin_unlock_irq( _S );
+
+#define OS_TIMER struct timer_list
+#define OS_TIMER_INITIAL( _T, _F, _P ) \
+{ \
+ init_timer( _T ); \
+ (_T)->function = (void *)_F##_1a; \
+ (_T)->data = (unsigned long)_P; \
+}
+
+// _S : Millisecond
+// 20060420 At least 1 large than jiffies
+#define OS_TIMER_SET( _T, _S ) \
+{ \
+ (_T)->expires = jiffies + ((_S*HZ+999)/1000);\
+ add_timer( _T ); \
+}
+#define OS_TIMER_CANCEL( _T, _B ) del_timer_sync( _T )
+#define OS_TIMER_GET_SYS_TIME( _T ) (*_T=jiffies)
+
+
+#endif // COMMON_DEF
+
diff --git a/drivers/staging/winbond/linux/sysdef.h b/drivers/staging/winbond/linux/sysdef.h
new file mode 100644
index 00000000000..d46d63e5c67
--- /dev/null
+++ b/drivers/staging/winbond/linux/sysdef.h
@@ -0,0 +1,73 @@
+
+
+//
+// Winbond WLAN System Configuration defines
+//
+
+//=====================================================================
+// Current directory is Linux
+// The definition WB_LINUX is a keyword for this OS
+//=====================================================================
+#ifndef SYS_DEF_H
+#define SYS_DEF_H
+#define WB_LINUX
+#define WB_LINUX_WPA_PSK
+
+
+//#define _IBSS_BEACON_SEQ_STICK_
+#define _USE_FALLBACK_RATE_
+//#define ANTDIV_DEFAULT_ON
+
+#define _WPA2_ // 20061122 It's needed for current Linux driver
+
+
+#ifndef _WPA_PSK_DEBUG
+#undef _WPA_PSK_DEBUG
+#endif
+
+// debug print options, mark what debug you don't need
+
+#ifdef FULL_DEBUG
+#define _PE_STATE_DUMP_
+#define _PE_TX_DUMP_
+#define _PE_RX_DUMP_
+#define _PE_OID_DUMP_
+#define _PE_DTO_DUMP_
+#define _PE_REG_DUMP_
+#define _PE_USB_INI_DUMP_
+#endif
+
+
+
+#include "common.h" // Individual file depends on OS
+
+#include "../wb35_ver.h"
+#include "../mac_structures.h"
+#include "../ds_tkip.h"
+#include "../localpara.h"
+#include "../sme_s.h"
+#include "../scan_s.h"
+#include "../mds_s.h"
+#include "../mlme_s.h"
+#include "../bssdscpt.h"
+#include "../sme_api.h"
+#include "../gl_80211.h"
+#include "../mto.h"
+#include "../wblinux_s.h"
+#include "../wbhal_s.h"
+
+
+#include "../adapter.h"
+
+#include "../mlme_mib.h"
+#include "../mds_f.h"
+#include "../bss_f.h"
+#include "../mlmetxrx_f.h"
+#include "../mto_f.h"
+#include "../wbhal_f.h"
+#include "../wblinux_f.h"
+// Kernel Timer resolution, NDIS is 10ms, 10000us
+#define MIN_TIMEOUT_VAL (10) //ms
+
+
+#endif
diff --git a/drivers/staging/winbond/linux/wb35reg.c b/drivers/staging/winbond/linux/wb35reg.c
new file mode 100644
index 00000000000..2c0b454e8ca
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg.c
@@ -0,0 +1,747 @@
+#include "sysdef.h"
+
+extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency);
+
+// TRUE : read command process successfully
+// FALSE : register not support
+// RegisterNo : start base
+// pRegisterData : data point
+// NumberOfData : number of register data
+// Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
+// NO_INCREMENT - Function will write data into the same register
+unsigned char
+Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PURB pUrb = NULL;
+ PREG_QUEUE pRegQueue = NULL;
+ u16 UrbSize;
+ struct usb_ctrlrequest *dr;
+ u16 i, DataSize = NumberOfData*4;
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ // Trying to use burst write function if use new hardware
+ UrbSize = sizeof(REG_QUEUE) + DataSize + sizeof(struct usb_ctrlrequest);
+ OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+ pUrb = wb_usb_alloc_urb(0);
+ if( pUrb && pRegQueue ) {
+ pRegQueue->DIRECT = 2;// burst write register
+ pRegQueue->INDEX = RegisterNo;
+ pRegQueue->pBuffer = (PULONG)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ memcpy( pRegQueue->pBuffer, pRegisterData, DataSize );
+ //the function for reversing register data from little endian to big endian
+ for( i=0; i<NumberOfData ; i++ )
+ pRegQueue->pBuffer[i] = cpu_to_le32( pRegQueue->pBuffer[i] );
+
+ dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE) + DataSize);
+ dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
+ dr->bRequest = 0x04; // USB or vendor-defined request code, burst mode
+ dr->wValue = cpu_to_le16( Flag ); // 0: Register number auto-increment, 1: No auto increment
+ dr->wIndex = cpu_to_le16( RegisterNo );
+ dr->wLength = cpu_to_le16( DataSize );
+ pRegQueue->Next = NULL;
+ pRegQueue->pUsbReq = dr;
+ pRegQueue->pUrb = pUrb;
+
+ OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ if (pWb35Reg->pRegFirst == NULL)
+ pWb35Reg->pRegFirst = pRegQueue;
+ else
+ pWb35Reg->pRegLast->Next = pRegQueue;
+ pWb35Reg->pRegLast = pRegQueue;
+
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ // Start EP0VM
+ Wb35Reg_EP0VM_start(pHwData);
+
+ return TRUE;
+ } else {
+ if (pUrb)
+ usb_free_urb(pUrb);
+ if (pRegQueue)
+ kfree(pRegQueue);
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void
+Wb35Reg_Update(phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ switch (RegisterNo) {
+ case 0x3b0: pWb35Reg->U1B0 = RegisterValue; break;
+ case 0x3bc: pWb35Reg->U1BC_LEDConfigure = RegisterValue; break;
+ case 0x400: pWb35Reg->D00_DmaControl = RegisterValue; break;
+ case 0x800: pWb35Reg->M00_MacControl = RegisterValue; break;
+ case 0x804: pWb35Reg->M04_MulticastAddress1 = RegisterValue; break;
+ case 0x808: pWb35Reg->M08_MulticastAddress2 = RegisterValue; break;
+ case 0x824: pWb35Reg->M24_MacControl = RegisterValue; break;
+ case 0x828: pWb35Reg->M28_MacControl = RegisterValue; break;
+ case 0x82c: pWb35Reg->M2C_MacControl = RegisterValue; break;
+ case 0x838: pWb35Reg->M38_MacControl = RegisterValue; break;
+ case 0x840: pWb35Reg->M40_MacControl = RegisterValue; break;
+ case 0x844: pWb35Reg->M44_MacControl = RegisterValue; break;
+ case 0x848: pWb35Reg->M48_MacControl = RegisterValue; break;
+ case 0x84c: pWb35Reg->M4C_MacStatus = RegisterValue; break;
+ case 0x860: pWb35Reg->M60_MacControl = RegisterValue; break;
+ case 0x868: pWb35Reg->M68_MacControl = RegisterValue; break;
+ case 0x870: pWb35Reg->M70_MacControl = RegisterValue; break;
+ case 0x874: pWb35Reg->M74_MacControl = RegisterValue; break;
+ case 0x878: pWb35Reg->M78_ERPInformation = RegisterValue; break;
+ case 0x87C: pWb35Reg->M7C_MacControl = RegisterValue; break;
+ case 0x880: pWb35Reg->M80_MacControl = RegisterValue; break;
+ case 0x884: pWb35Reg->M84_MacControl = RegisterValue; break;
+ case 0x888: pWb35Reg->M88_MacControl = RegisterValue; break;
+ case 0x898: pWb35Reg->M98_MacControl = RegisterValue; break;
+ case 0x100c: pWb35Reg->BB0C = RegisterValue; break;
+ case 0x102c: pWb35Reg->BB2C = RegisterValue; break;
+ case 0x1030: pWb35Reg->BB30 = RegisterValue; break;
+ case 0x103c: pWb35Reg->BB3C = RegisterValue; break;
+ case 0x1048: pWb35Reg->BB48 = RegisterValue; break;
+ case 0x104c: pWb35Reg->BB4C = RegisterValue; break;
+ case 0x1050: pWb35Reg->BB50 = RegisterValue; break;
+ case 0x1054: pWb35Reg->BB54 = RegisterValue; break;
+ case 0x1058: pWb35Reg->BB58 = RegisterValue; break;
+ case 0x105c: pWb35Reg->BB5C = RegisterValue; break;
+ case 0x1060: pWb35Reg->BB60 = RegisterValue; break;
+ }
+}
+
+// TRUE : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ int ret = -1;
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ RegisterValue = cpu_to_le32(RegisterValue);
+
+ // update the register by send usb message------------------------------------
+ pWb35Reg->SyncIoPause = 1;
+
+ // 20060717.5 Wait until EP0VM stop
+ while (pWb35Reg->EP0vm_state != VM_STOP)
+ OS_SLEEP(10000);
+
+ // Sync IoCallDriver
+ pWb35Reg->EP0vm_state = VM_RUNNING;
+ ret = usb_control_msg( pHwData->WbUsb.udev,
+ usb_sndctrlpipe( pHwData->WbUsb.udev, 0 ),
+ 0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x0,RegisterNo, &RegisterValue, 4, HZ*100 );
+ pWb35Reg->EP0vm_state = VM_STOP;
+ pWb35Reg->SyncIoPause = 0;
+
+ Wb35Reg_EP0VM_start(pHwData);
+
+ if (ret < 0) {
+ #ifdef _PE_REG_DUMP_
+ WBDEBUG(("EP0 Write register usb message sending error\n"));
+ #endif
+
+ pHwData->SurpriseRemove = 1; // 20060704.2
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// TRUE : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ struct usb_ctrlrequest *dr;
+ PURB pUrb = NULL;
+ PREG_QUEUE pRegQueue = NULL;
+ u16 UrbSize;
+
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ // update the register by send urb request------------------------------------
+ UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+ OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+ pUrb = wb_usb_alloc_urb(0);
+ if (pUrb && pRegQueue) {
+ pRegQueue->DIRECT = 1;// burst write register
+ pRegQueue->INDEX = RegisterNo;
+ pRegQueue->VALUE = cpu_to_le32(RegisterValue);
+ pRegQueue->RESERVED_VALID = FALSE;
+ dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
+ dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
+ dr->wValue = cpu_to_le16(0x0);
+ dr->wIndex = cpu_to_le16(RegisterNo);
+ dr->wLength = cpu_to_le16(4);
+
+ // Enter the sending queue
+ pRegQueue->Next = NULL;
+ pRegQueue->pUsbReq = dr;
+ pRegQueue->pUrb = pUrb;
+
+ OS_SPIN_LOCK_ACQUIRED(&pWb35Reg->EP0VM_spin_lock );
+ if (pWb35Reg->pRegFirst == NULL)
+ pWb35Reg->pRegFirst = pRegQueue;
+ else
+ pWb35Reg->pRegLast->Next = pRegQueue;
+ pWb35Reg->pRegLast = pRegQueue;
+
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ // Start EP0VM
+ Wb35Reg_EP0VM_start(pHwData);
+
+ return TRUE;
+ } else {
+ if (pUrb)
+ usb_free_urb(pUrb);
+ kfree(pRegQueue);
+ return FALSE;
+ }
+}
+
+//This command will be executed with a user defined value. When it completes,
+//this value is useful. For example, hal_set_current_channel will use it.
+// TRUE : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue,
+ PCHAR pValue, s8 Len)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ struct usb_ctrlrequest *dr;
+ PURB pUrb = NULL;
+ PREG_QUEUE pRegQueue = NULL;
+ u16 UrbSize;
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ // update the register by send urb request------------------------------------
+ UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+ OS_MEMORY_ALLOC((void* *) &pRegQueue, UrbSize );
+ pUrb = wb_usb_alloc_urb(0);
+ if (pUrb && pRegQueue) {
+ pRegQueue->DIRECT = 1;// burst write register
+ pRegQueue->INDEX = RegisterNo;
+ pRegQueue->VALUE = cpu_to_le32(RegisterValue);
+ //NOTE : Users must guarantee the size of value will not exceed the buffer size.
+ memcpy(pRegQueue->RESERVED, pValue, Len);
+ pRegQueue->RESERVED_VALID = TRUE;
+ dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
+ dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
+ dr->wValue = cpu_to_le16(0x0);
+ dr->wIndex = cpu_to_le16(RegisterNo);
+ dr->wLength = cpu_to_le16(4);
+
+ // Enter the sending queue
+ pRegQueue->Next = NULL;
+ pRegQueue->pUsbReq = dr;
+ pRegQueue->pUrb = pUrb;
+ OS_SPIN_LOCK_ACQUIRED (&pWb35Reg->EP0VM_spin_lock );
+ if( pWb35Reg->pRegFirst == NULL )
+ pWb35Reg->pRegFirst = pRegQueue;
+ else
+ pWb35Reg->pRegLast->Next = pRegQueue;
+ pWb35Reg->pRegLast = pRegQueue;
+
+ OS_SPIN_LOCK_RELEASED ( &pWb35Reg->EP0VM_spin_lock );
+
+ // Start EP0VM
+ Wb35Reg_EP0VM_start(pHwData);
+ return TRUE;
+ } else {
+ if (pUrb)
+ usb_free_urb(pUrb);
+ kfree(pRegQueue);
+ return FALSE;
+ }
+}
+
+// TRUE : read command process successfully
+// FALSE : register not support
+// pRegisterValue : It must be a resident buffer due to asynchronous read register.
+unsigned char
+Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PULONG pltmp = pRegisterValue;
+ int ret = -1;
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ // Read the register by send usb message------------------------------------
+
+ pWb35Reg->SyncIoPause = 1;
+
+ // 20060717.5 Wait until EP0VM stop
+ while (pWb35Reg->EP0vm_state != VM_STOP)
+ OS_SLEEP(10000);
+
+ pWb35Reg->EP0vm_state = VM_RUNNING;
+ ret = usb_control_msg( pHwData->WbUsb.udev,
+ usb_rcvctrlpipe(pHwData->WbUsb.udev, 0),
+ 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+ 0x0, RegisterNo, pltmp, 4, HZ*100 );
+
+ *pRegisterValue = cpu_to_le32(*pltmp);
+
+ pWb35Reg->EP0vm_state = VM_STOP;
+
+ Wb35Reg_Update( pHwData, RegisterNo, *pRegisterValue );
+ pWb35Reg->SyncIoPause = 0;
+
+ Wb35Reg_EP0VM_start( pHwData );
+
+ if (ret < 0) {
+ #ifdef _PE_REG_DUMP_
+ WBDEBUG(("EP0 Read register usb message sending error\n"));
+ #endif
+
+ pHwData->SurpriseRemove = 1; // 20060704.2
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// TRUE : read command process successfully
+// FALSE : register not support
+// pRegisterValue : It must be a resident buffer due to asynchronous read register.
+unsigned char
+Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ struct usb_ctrlrequest * dr;
+ PURB pUrb;
+ PREG_QUEUE pRegQueue;
+ u16 UrbSize;
+
+ // Module shutdown
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+
+ // update the variable by send Urb to read register ------------------------------------
+ UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+ OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+ pUrb = wb_usb_alloc_urb(0);
+ if( pUrb && pRegQueue )
+ {
+ pRegQueue->DIRECT = 0;// read register
+ pRegQueue->INDEX = RegisterNo;
+ pRegQueue->pBuffer = pRegisterValue;
+ dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+ dr->bRequestType = USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN;
+ dr->bRequest = 0x01; // USB or vendor-defined request code, burst mode
+ dr->wValue = cpu_to_le16(0x0);
+ dr->wIndex = cpu_to_le16 (RegisterNo);
+ dr->wLength = cpu_to_le16 (4);
+
+ // Enter the sending queue
+ pRegQueue->Next = NULL;
+ pRegQueue->pUsbReq = dr;
+ pRegQueue->pUrb = pUrb;
+ OS_SPIN_LOCK_ACQUIRED ( &pWb35Reg->EP0VM_spin_lock );
+ if( pWb35Reg->pRegFirst == NULL )
+ pWb35Reg->pRegFirst = pRegQueue;
+ else
+ pWb35Reg->pRegLast->Next = pRegQueue;
+ pWb35Reg->pRegLast = pRegQueue;
+
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ // Start EP0VM
+ Wb35Reg_EP0VM_start( pHwData );
+
+ return TRUE;
+ } else {
+ if (pUrb)
+ usb_free_urb( pUrb );
+ kfree(pRegQueue);
+ return FALSE;
+ }
+}
+
+
+void
+Wb35Reg_EP0VM_start( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Reg->RegFireCount) == 1) {
+ pWb35Reg->EP0vm_state = VM_RUNNING;
+ Wb35Reg_EP0VM(pHwData);
+ } else
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+}
+
+void
+Wb35Reg_EP0VM(phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PURB pUrb;
+ struct usb_ctrlrequest *dr;
+ PULONG pBuffer;
+ int ret = -1;
+ PREG_QUEUE pRegQueue;
+
+
+ if (pWb35Reg->SyncIoPause)
+ goto cleanup;
+
+ if (pHwData->SurpriseRemove)
+ goto cleanup;
+
+ // Get the register data and send to USB through Irp
+ OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ pRegQueue = pWb35Reg->pRegFirst;
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ if (!pRegQueue)
+ goto cleanup;
+
+ // Get an Urb, send it
+ pUrb = (PURB)pRegQueue->pUrb;
+
+ dr = pRegQueue->pUsbReq;
+ pUrb = pRegQueue->pUrb;
+ pBuffer = pRegQueue->pBuffer;
+ if (pRegQueue->DIRECT == 1) // output
+ pBuffer = &pRegQueue->VALUE;
+
+ usb_fill_control_urb( pUrb, pHwData->WbUsb.udev,
+ REG_DIRECTION(pHwData->WbUsb.udev,pRegQueue),
+ (PUCHAR)dr,pBuffer,cpu_to_le16(dr->wLength),
+ Wb35Reg_EP0VM_complete, (void*)pHwData);
+
+ pWb35Reg->EP0vm_state = VM_RUNNING;
+
+ ret = wb_usb_submit_urb( pUrb );
+
+ if (ret < 0) {
+#ifdef _PE_REG_DUMP_
+ WBDEBUG(("EP0 Irp sending error\n"));
+#endif
+ goto cleanup;
+ }
+
+ return;
+
+ cleanup:
+ pWb35Reg->EP0vm_state = VM_STOP;
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+}
+
+
+void
+Wb35Reg_EP0VM_complete(PURB pUrb)
+{
+ phw_data_t pHwData = (phw_data_t)pUrb->context;
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PREG_QUEUE pRegQueue;
+
+
+ // Variable setting
+ pWb35Reg->EP0vm_state = VM_COMPLETED;
+ pWb35Reg->EP0VM_status = pUrb->status;
+
+ if (pHwData->SurpriseRemove) { // Let WbWlanHalt to handle surprise remove
+ pWb35Reg->EP0vm_state = VM_STOP;
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+ } else {
+ // Complete to send, remove the URB from the first
+ OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ pRegQueue = pWb35Reg->pRegFirst;
+ if (pRegQueue == pWb35Reg->pRegLast)
+ pWb35Reg->pRegLast = NULL;
+ pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ if (pWb35Reg->EP0VM_status) {
+#ifdef _PE_REG_DUMP_
+ WBDEBUG(("EP0 IoCompleteRoutine return error\n"));
+ DebugUsbdStatusInformation( pWb35Reg->EP0VM_status );
+#endif
+ pWb35Reg->EP0vm_state = VM_STOP;
+ pHwData->SurpriseRemove = 1;
+ } else {
+ // Success. Update the result
+
+ // Start the next send
+ Wb35Reg_EP0VM(pHwData);
+ }
+
+ kfree(pRegQueue);
+ }
+
+ usb_free_urb(pUrb);
+}
+
+
+void
+Wb35Reg_destroy(phw_data_t pHwData)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PURB pUrb;
+ PREG_QUEUE pRegQueue;
+
+
+ Uxx_power_off_procedure(pHwData);
+
+ // Wait for Reg operation completed
+ do {
+ OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
+ } while (pWb35Reg->EP0vm_state != VM_STOP);
+ OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
+
+ // Release all the data in RegQueue
+ OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+ pRegQueue = pWb35Reg->pRegFirst;
+ while (pRegQueue) {
+ if (pRegQueue == pWb35Reg->pRegLast)
+ pWb35Reg->pRegLast = NULL;
+ pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
+
+ pUrb = pRegQueue->pUrb;
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+ if (pUrb) {
+ usb_free_urb(pUrb);
+ kfree(pRegQueue);
+ } else {
+ #ifdef _PE_REG_DUMP_
+ WBDEBUG(("EP0 queue release error\n"));
+ #endif
+ }
+ OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+
+ pRegQueue = pWb35Reg->pRegFirst;
+ }
+ OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+ // Free resource
+ OS_SPIN_LOCK_FREE( &pWb35Reg->EP0VM_spin_lock );
+}
+
+//====================================================================================
+// The function can be run in passive-level only.
+//====================================================================================
+unsigned char Wb35Reg_initial(phw_data_t pHwData)
+{
+ PWB35REG pWb35Reg=&pHwData->Wb35Reg;
+ u32 ltmp;
+ u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval;
+
+ // Spin lock is acquired for read and write IRP command
+ OS_SPIN_LOCK_ALLOCATE( &pWb35Reg->EP0VM_spin_lock );
+
+ // Getting RF module type from EEPROM ------------------------------------
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x080d0000 ); // Start EEPROM access + Read + address(0x0d)
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+
+ //Update RF module type and determine the PHY type by inf or EEPROM
+ pWb35Reg->EEPROMPhyType = (u8)( ltmp & 0xff );
+ // 0 V MAX2825, 1 V MAX2827, 2 V MAX2828, 3 V MAX2829
+ // 16V AL2230, 17 - AL7230, 18 - AL2230S
+ // 32 Reserved
+ // 33 - W89RF242(TxVGA 0~19), 34 - W89RF242(TxVGA 0~34)
+ if (pWb35Reg->EEPROMPhyType != RF_DECIDE_BY_INF) {
+ if( (pWb35Reg->EEPROMPhyType == RF_MAXIM_2825) ||
+ (pWb35Reg->EEPROMPhyType == RF_MAXIM_2827) ||
+ (pWb35Reg->EEPROMPhyType == RF_MAXIM_2828) ||
+ (pWb35Reg->EEPROMPhyType == RF_MAXIM_2829) ||
+ (pWb35Reg->EEPROMPhyType == RF_MAXIM_V1) ||
+ (pWb35Reg->EEPROMPhyType == RF_AIROHA_2230) ||
+ (pWb35Reg->EEPROMPhyType == RF_AIROHA_2230S) ||
+ (pWb35Reg->EEPROMPhyType == RF_AIROHA_7230) ||
+ (pWb35Reg->EEPROMPhyType == RF_WB_242) ||
+ (pWb35Reg->EEPROMPhyType == RF_WB_242_1))
+ pHwData->phy_type = pWb35Reg->EEPROMPhyType;
+ }
+
+ // Power On procedure running. The relative parameter will be set according to phy_type
+ Uxx_power_on_procedure( pHwData );
+
+ // Reading MAC address
+ Uxx_ReadEthernetAddress( pHwData );
+
+ // Read VCO trim for RF parameter
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08200000 );
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &VCO_trim );
+
+ // Read Antenna On/Off of software flag
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08210000 );
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &SoftwareSet );
+
+ // Read TXVGA
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08100000 );
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &TxVga );
+
+ // Get Scan interval setting from EEPROM offset 0x1c
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x081d0000 );
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &Region_ScanInterval );
+
+ // Update Ethernet address
+ memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS );
+
+ // Update software variable
+ pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff);
+ TxVga &= 0x000000ff;
+ pHwData->PowerIndexFromEEPROM = (u8)TxVga;
+ pHwData->VCO_trim = (u8)VCO_trim & 0xff;
+ if (pHwData->VCO_trim == 0xff)
+ pHwData->VCO_trim = 0x28;
+
+ pWb35Reg->EEPROMRegion = (u8)(Region_ScanInterval>>8); // 20060720
+ if( pWb35Reg->EEPROMRegion<1 || pWb35Reg->EEPROMRegion>6 )
+ pWb35Reg->EEPROMRegion = REGION_AUTO;
+
+ //For Get Tx VGA from EEPROM 20060315.5 move here
+ GetTxVgaFromEEPROM( pHwData );
+
+ // Set Scan Interval
+ pHwData->Scan_Interval = (u8)(Region_ScanInterval & 0xff) * 10;
+ if ((pHwData->Scan_Interval == 2550) || (pHwData->Scan_Interval < 10)) // Is default setting 0xff * 10
+ pHwData->Scan_Interval = SCAN_MAX_CHNL_TIME;
+
+ // Initial register
+ RFSynthesizer_initial(pHwData);
+
+ BBProcessor_initial(pHwData); // Async write, must wait until complete
+
+ Wb35Reg_phy_calibration(pHwData);
+
+ Mxx_initial(pHwData);
+ Dxx_initial(pHwData);
+
+ if (pHwData->SurpriseRemove)
+ return FALSE;
+ else
+ return TRUE; // Initial fail
+}
+
+//===================================================================================
+// CardComputeCrc --
+//
+// Description:
+// Runs the AUTODIN II CRC algorithm on buffer Buffer of length, Length.
+//
+// Arguments:
+// Buffer - the input buffer
+// Length - the length of Buffer
+//
+// Return Value:
+// The 32-bit CRC value.
+//
+// Note:
+// This is adapted from the comments in the assembly language
+// version in _GENREQ.ASM of the DWB NE1000/2000 driver.
+//==================================================================================
+u32
+CardComputeCrc(PUCHAR Buffer, u32 Length)
+{
+ u32 Crc, Carry;
+ u32 i, j;
+ u8 CurByte;
+
+ Crc = 0xffffffff;
+
+ for (i = 0; i < Length; i++) {
+
+ CurByte = Buffer[i];
+
+ for (j = 0; j < 8; j++) {
+
+ Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
+ Crc <<= 1;
+ CurByte >>= 1;
+
+ if (Carry) {
+ Crc =(Crc ^ 0x04c11db6) | Carry;
+ }
+ }
+ }
+
+ return Crc;
+}
+
+
+//==================================================================
+// BitReverse --
+// Reverse the bits in the input argument, dwData, which is
+// regarded as a string of bits with the length, DataLength.
+//
+// Arguments:
+// dwData :
+// DataLength :
+//
+// Return:
+// The converted value.
+//==================================================================
+u32 BitReverse( u32 dwData, u32 DataLength)
+{
+ u32 HalfLength, i, j;
+ u32 BitA, BitB;
+
+ if ( DataLength <= 0) return 0; // No conversion is done.
+ dwData = dwData & (0xffffffff >> (32 - DataLength));
+
+ HalfLength = DataLength / 2;
+ for ( i = 0, j = DataLength-1 ; i < HalfLength; i++, j--)
+ {
+ BitA = GetBit( dwData, i);
+ BitB = GetBit( dwData, j);
+ if (BitA && !BitB) {
+ dwData = ClearBit( dwData, i);
+ dwData = SetBit( dwData, j);
+ } else if (!BitA && BitB) {
+ dwData = SetBit( dwData, i);
+ dwData = ClearBit( dwData, j);
+ } else
+ {
+ // Do nothing since these two bits are of the save values.
+ }
+ }
+
+ return dwData;
+}
+
+void Wb35Reg_phy_calibration( phw_data_t pHwData )
+{
+ u32 BB3c, BB54;
+
+ if ((pHwData->phy_type == RF_WB_242) ||
+ (pHwData->phy_type == RF_WB_242_1)) {
+ phy_calibration_winbond ( pHwData, 2412 ); // Sync operation
+ Wb35Reg_ReadSync( pHwData, 0x103c, &BB3c );
+ Wb35Reg_ReadSync( pHwData, 0x1054, &BB54 );
+
+ pHwData->BB3c_cal = BB3c;
+ pHwData->BB54_cal = BB54;
+
+ RFSynthesizer_initial(pHwData);
+ BBProcessor_initial(pHwData); // Async operation
+
+ Wb35Reg_WriteSync( pHwData, 0x103c, BB3c );
+ Wb35Reg_WriteSync( pHwData, 0x1054, BB54 );
+ }
+}
+
+
diff --git a/drivers/staging/winbond/linux/wb35reg_f.h b/drivers/staging/winbond/linux/wb35reg_f.h
new file mode 100644
index 00000000000..38e2906b51a
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg_f.h
@@ -0,0 +1,56 @@
+//====================================
+// Interface function declare
+//====================================
+unsigned char Wb35Reg_initial( phw_data_t pHwData );
+void Uxx_power_on_procedure( phw_data_t pHwData );
+void Uxx_power_off_procedure( phw_data_t pHwData );
+void Uxx_ReadEthernetAddress( phw_data_t pHwData );
+void Dxx_initial( phw_data_t pHwData );
+void Mxx_initial( phw_data_t pHwData );
+void RFSynthesizer_initial( phw_data_t pHwData );
+//void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, s8 Channel );
+void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel );
+void BBProcessor_initial( phw_data_t pHwData );
+void BBProcessor_RateChanging( phw_data_t pHwData, u8 rate ); // 20060613.1
+//void RF_RateChanging( phw_data_t pHwData, u8 rate ); // 20060626.5.c Add
+u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex );
+u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetMaxim2825Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetAiroha2230Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetAiroha7230Power( phw_data_t, u8 index );
+u8 RFSynthesizer_SetWinbond242Power( phw_data_t, u8 index );
+void GetTxVgaFromEEPROM( phw_data_t pHwData );
+void EEPROMTxVgaAdjust( phw_data_t pHwData ); // 20060619.5 Add
+
+#define RFWriteControlData( _A, _V ) Wb35Reg_Write( _A, 0x0864, _V )
+
+void Wb35Reg_destroy( phw_data_t pHwData );
+
+unsigned char Wb35Reg_Read( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
+unsigned char Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
+unsigned char Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
+unsigned char Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
+unsigned char Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData,
+ u16 RegisterNo,
+ u32 RegisterValue,
+ PCHAR pValue,
+ s8 Len);
+unsigned char Wb35Reg_BurstWrite( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag );
+
+void Wb35Reg_EP0VM( phw_data_t pHwData );
+void Wb35Reg_EP0VM_start( phw_data_t pHwData );
+void Wb35Reg_EP0VM_complete( PURB pUrb );
+
+u32 BitReverse( u32 dwData, u32 DataLength);
+
+void CardGetMulticastBit( u8 Address[MAC_ADDR_LENGTH], u8 *Byte, u8 *Value );
+u32 CardComputeCrc( PUCHAR Buffer, u32 Length );
+
+void Wb35Reg_phy_calibration( phw_data_t pHwData );
+void Wb35Reg_Update( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
+unsigned char adjust_TXVGA_for_iq_mag( phw_data_t pHwData );
+
+
diff --git a/drivers/staging/winbond/linux/wb35reg_s.h b/drivers/staging/winbond/linux/wb35reg_s.h
new file mode 100644
index 00000000000..a7595b1e733
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg_s.h
@@ -0,0 +1,170 @@
+//=======================================================================================
+/*
+ HAL setting function
+
+ ========================================
+ |Uxx| |Dxx| |Mxx| |BB| |RF|
+ ========================================
+ | |
+ Wb35Reg_Read Wb35Reg_Write
+
+ ----------------------------------------
+ WbUsb_CallUSBDASync supplied By WbUsb module
+*/
+//=======================================================================================
+
+#define GetBit( dwData, i) ( dwData & (0x00000001 << i))
+#define SetBit( dwData, i) ( dwData | (0x00000001 << i))
+#define ClearBit( dwData, i) ( dwData & ~(0x00000001 << i))
+
+#define IGNORE_INCREMENT 0
+#define AUTO_INCREMENT 0
+#define NO_INCREMENT 1
+#define REG_DIRECTION(_x,_y) ((_y)->DIRECT ==0 ? usb_rcvctrlpipe(_x,0) : usb_sndctrlpipe(_x,0))
+#define REG_BUF_SIZE(_x) ((_x)->bRequest== 0x04 ? cpu_to_le16((_x)->wLength) : 4)
+
+// 20060613.2 Add the follow definition
+#define BB48_DEFAULT_AL2230_11B 0x0033447c
+#define BB4C_DEFAULT_AL2230_11B 0x0A00FEFF
+#define BB48_DEFAULT_AL2230_11G 0x00332C1B
+#define BB4C_DEFAULT_AL2230_11G 0x0A00FEFF
+
+
+#define BB48_DEFAULT_WB242_11B 0x00292315 //backoff 2dB
+#define BB4C_DEFAULT_WB242_11B 0x0800FEFF //backoff 2dB
+//#define BB48_DEFAULT_WB242_11B 0x00201B11 //backoff 4dB
+//#define BB4C_DEFAULT_WB242_11B 0x0600FF00 //backoff 4dB
+#define BB48_DEFAULT_WB242_11G 0x00453B24
+#define BB4C_DEFAULT_WB242_11G 0x0E00FEFF
+
+//====================================
+// Default setting for Mxx
+//====================================
+#define DEFAULT_CWMIN 31 //(M2C) CWmin. Its value is in the range 0-31.
+#define DEFAULT_CWMAX 1023 //(M2C) CWmax. Its value is in the range 0-1023.
+#define DEFAULT_AID 1 //(M34) AID. Its value is in the range 1-2007.
+
+#ifdef _USE_FALLBACK_RATE_
+#define DEFAULT_RATE_RETRY_LIMIT 2 //(M38) as named
+#else
+#define DEFAULT_RATE_RETRY_LIMIT 7 //(M38) as named
+#endif
+
+#define DEFAULT_LONG_RETRY_LIMIT 7 //(M38) LongRetryLimit. Its value is in the range 0-15.
+#define DEFAULT_SHORT_RETRY_LIMIT 7 //(M38) ShortRetryLimit. Its value is in the range 0-15.
+#define DEFAULT_PIFST 25 //(M3C) PIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_EIFST 354 //(M3C) EIFS Time. Its value is in the range 0-1048575.
+#define DEFAULT_DIFST 45 //(M3C) DIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_SIFST 5 //(M3C) SIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_OSIFST 10 //(M3C) Original SIFS Time. Its value is in the range 0-15.
+#define DEFAULT_ATIMWD 0 //(M40) ATIM Window. Its value is in the range 0-65535.
+#define DEFAULT_SLOT_TIME 20 //(M40) ($) SlotTime. Its value is in the range 0-255.
+#define DEFAULT_MAX_TX_MSDU_LIFE_TIME 512 //(M44) MaxTxMSDULifeTime. Its value is in the range 0-4294967295.
+#define DEFAULT_BEACON_INTERVAL 500 //(M48) Beacon Interval. Its value is in the range 0-65535.
+#define DEFAULT_PROBE_DELAY_TIME 200 //(M48) Probe Delay Time. Its value is in the range 0-65535.
+#define DEFAULT_PROTOCOL_VERSION 0 //(M4C)
+#define DEFAULT_MAC_POWER_STATE 2 //(M4C) 2: MAC at power active
+#define DEFAULT_DTIM_ALERT_TIME 0
+
+
+typedef struct _REG_QUEUE
+{
+ struct urb *pUrb;
+ void* pUsbReq;
+ void* Next;
+ union
+ {
+ u32 VALUE;
+ PULONG pBuffer;
+ };
+ u8 RESERVED[4];// space reserved for communication
+
+ u16 INDEX; // For storing the register index
+ u8 RESERVED_VALID; //Indicate whether the RESERVED space is valid at this command.
+ u8 DIRECT; // 0:In 1:Out
+
+} REG_QUEUE, *PREG_QUEUE;
+
+//====================================
+// Internal variable for module
+//====================================
+#define MAX_SQ3_FILTER_SIZE 5
+typedef struct _WB35REG
+{
+ //============================
+ // Register Bank backup
+ //============================
+ u32 U1B0; //bit16 record the h/w radio on/off status
+ u32 U1BC_LEDConfigure;
+ u32 D00_DmaControl;
+ u32 M00_MacControl;
+ union {
+ struct {
+ u32 M04_MulticastAddress1;
+ u32 M08_MulticastAddress2;
+ };
+ u8 Multicast[8]; // contents of card multicast registers
+ };
+
+ u32 M24_MacControl;
+ u32 M28_MacControl;
+ u32 M2C_MacControl;
+ u32 M38_MacControl;
+ u32 M3C_MacControl; // 20060214 backup only
+ u32 M40_MacControl;
+ u32 M44_MacControl; // 20060214 backup only
+ u32 M48_MacControl; // 20060214 backup only
+ u32 M4C_MacStatus;
+ u32 M60_MacControl; // 20060214 backup only
+ u32 M68_MacControl; // 20060214 backup only
+ u32 M70_MacControl; // 20060214 backup only
+ u32 M74_MacControl; // 20060214 backup only
+ u32 M78_ERPInformation;//930206.2.b
+ u32 M7C_MacControl; // 20060214 backup only
+ u32 M80_MacControl; // 20060214 backup only
+ u32 M84_MacControl; // 20060214 backup only
+ u32 M88_MacControl; // 20060214 backup only
+ u32 M98_MacControl; // 20060214 backup only
+
+ //[20040722 WK]
+ //Baseband register
+ u32 BB0C; // Used for LNA calculation
+ u32 BB2C; //
+ u32 BB30; //11b acquisition control register
+ u32 BB3C;
+ u32 BB48; // 20051221.1.a 20060613.1 Fix OBW issue of 11b/11g rate
+ u32 BB4C; // 20060613.1 Fix OBW issue of 11b/11g rate
+ u32 BB50; //mode control register
+ u32 BB54;
+ u32 BB58; //IQ_ALPHA
+ u32 BB5C; // For test
+ u32 BB60; // for WTO read value
+
+ //-------------------
+ // VM
+ //-------------------
+ OS_SPIN_LOCK EP0VM_spin_lock; // 4B
+ u32 EP0VM_status;//$$
+ PREG_QUEUE pRegFirst;
+ PREG_QUEUE pRegLast;
+ OS_ATOMIC RegFireCount;
+
+ // Hardware status
+ u8 EP0vm_state;
+ u8 mac_power_save;
+ u8 EEPROMPhyType; // 0 ~ 15 for Maxim (0 Ä„V MAX2825, 1 Ä„V MAX2827, 2 Ä„V MAX2828, 3 Ä„V MAX2829),
+ // 16 ~ 31 for Airoha (16 Ä„V AL2230, 11 - AL7230)
+ // 32 ~ Reserved
+ // 33 ~ 47 For WB242 ( 33 - WB242, 34 - WB242 with new Txvga 0.5 db step)
+ // 48 ~ 255 ARE RESERVED.
+ u8 EEPROMRegion; //Region setting in EEPROM
+
+ u32 SyncIoPause; // If user use the Sync Io to access Hw, then pause the async access
+
+ u8 LNAValue[4]; //Table for speed up running
+ u32 SQ3_filter[MAX_SQ3_FILTER_SIZE];
+ u32 SQ3_index;
+
+} WB35REG, *PWB35REG;
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx.c b/drivers/staging/winbond/linux/wb35rx.c
new file mode 100644
index 00000000000..26157eb3d5a
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx.c
@@ -0,0 +1,337 @@
+//============================================================================
+// Copyright (c) 1996-2002 Winbond Electronic Corporation
+//
+// Module Name:
+// Wb35Rx.c
+//
+// Abstract:
+// Processing the Rx message from down layer
+//
+//============================================================================
+#include "sysdef.h"
+
+
+void Wb35Rx_start(phw_data_t pHwData)
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+ // Allow only one thread to run into the Wb35Rx() function
+ if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Rx->RxFireCounter) == 1) {
+ pWb35Rx->EP3vm_state = VM_RUNNING;
+ Wb35Rx(pHwData);
+ } else
+ OS_ATOMIC_DEC(pHwData->Adapter, &pWb35Rx->RxFireCounter);
+}
+
+// This function cannot reentrain
+void Wb35Rx( phw_data_t pHwData )
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+ PUCHAR pRxBufferAddress;
+ PURB pUrb = (PURB)pWb35Rx->RxUrb;
+ int retv;
+ u32 RxBufferId;
+
+ //
+ // Issuing URB
+ //
+ do {
+ if (pHwData->SurpriseRemove || pHwData->HwStop)
+ break;
+
+ if (pWb35Rx->rx_halt)
+ break;
+
+ // Get RxBuffer's ID
+ RxBufferId = pWb35Rx->RxBufferId;
+ if (!pWb35Rx->RxOwner[RxBufferId]) {
+ // It's impossible to run here.
+ #ifdef _PE_RX_DUMP_
+ WBDEBUG(("Rx driver fifo unavailable\n"));
+ #endif
+ break;
+ }
+
+ // Update buffer point, then start to bulkin the data from USB
+ pWb35Rx->RxBufferId++;
+ pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
+
+ pWb35Rx->CurrentRxBufferId = RxBufferId;
+
+ if (1 != OS_MEMORY_ALLOC((void* *)&pWb35Rx->pDRx, MAX_USB_RX_BUFFER)) {
+ printk("w35und: Rx memory alloc failed\n");
+ break;
+ }
+ pRxBufferAddress = pWb35Rx->pDRx;
+
+ usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
+ usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
+ pRxBufferAddress, MAX_USB_RX_BUFFER,
+ Wb35Rx_Complete, pHwData);
+
+ pWb35Rx->EP3vm_state = VM_RUNNING;
+
+ retv = wb_usb_submit_urb(pUrb);
+
+ if (retv != 0) {
+ printk("Rx URB sending error\n");
+ break;
+ }
+ return;
+ } while(FALSE);
+
+ // VM stop
+ pWb35Rx->EP3vm_state = VM_STOP;
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
+}
+
+void Wb35Rx_Complete(PURB pUrb)
+{
+ phw_data_t pHwData = pUrb->context;
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+ PUCHAR pRxBufferAddress;
+ u32 SizeCheck;
+ u16 BulkLength;
+ u32 RxBufferId;
+ R00_DESCRIPTOR R00;
+
+ // Variable setting
+ pWb35Rx->EP3vm_state = VM_COMPLETED;
+ pWb35Rx->EP3VM_status = pUrb->status;//Store the last result of Irp
+
+ do {
+ RxBufferId = pWb35Rx->CurrentRxBufferId;
+
+ pRxBufferAddress = pWb35Rx->pDRx;
+ BulkLength = (u16)pUrb->actual_length;
+
+ // The IRP is completed
+ pWb35Rx->EP3vm_state = VM_COMPLETED;
+
+ if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
+ break;
+
+ if (pWb35Rx->rx_halt)
+ break;
+
+ // Start to process the data only in successful condition
+ pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
+ R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+
+ // The URB is completed, check the result
+ if (pWb35Rx->EP3VM_status != 0) {
+ #ifdef _PE_USB_STATE_DUMP_
+ WBDEBUG(("EP3 IoCompleteRoutine return error\n"));
+ DebugUsbdStatusInformation( pWb35Rx->EP3VM_status );
+ #endif
+ pWb35Rx->EP3vm_state = VM_STOP;
+ break;
+ }
+
+ // 20060220 For recovering. check if operating in single USB mode
+ if (!HAL_USB_MODE_BURST(pHwData)) {
+ SizeCheck = R00.R00_receive_byte_count; //20060926 anson's endian
+ if ((SizeCheck & 0x03) > 0)
+ SizeCheck -= 4;
+ SizeCheck = (SizeCheck + 3) & ~0x03;
+ SizeCheck += 12; // 8 + 4 badbeef
+ if ((BulkLength > 1600) ||
+ (SizeCheck > 1600) ||
+ (BulkLength != SizeCheck) ||
+ (BulkLength == 0)) { // Add for fail Urb
+ pWb35Rx->EP3vm_state = VM_STOP;
+ pWb35Rx->Ep3ErrorCount2++;
+ }
+ }
+
+ // Indicating the receiving data
+ pWb35Rx->ByteReceived += BulkLength;
+ pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
+
+ if (!pWb35Rx->RxOwner[ RxBufferId ])
+ Wb35Rx_indicate(pHwData);
+
+ kfree(pWb35Rx->pDRx);
+ // Do the next receive
+ Wb35Rx(pHwData);
+ return;
+
+ } while(FALSE);
+
+ pWb35Rx->RxOwner[ RxBufferId ] = 1; // Set the owner to hardware
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
+ pWb35Rx->EP3vm_state = VM_STOP;
+}
+
+//=====================================================================================
+unsigned char Wb35Rx_initial(phw_data_t pHwData)
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+ // Initial the Buffer Queue
+ Wb35Rx_reset_descriptor( pHwData );
+
+ pWb35Rx->RxUrb = wb_usb_alloc_urb(0);
+ return (!!pWb35Rx->RxUrb);
+}
+
+void Wb35Rx_stop(phw_data_t pHwData)
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+ // Canceling the Irp if already sends it out.
+ if (pWb35Rx->EP3vm_state == VM_RUNNING) {
+ usb_unlink_urb( pWb35Rx->RxUrb ); // Only use unlink, let Wb35Rx_destroy to free them
+ #ifdef _PE_RX_DUMP_
+ WBDEBUG(("EP3 Rx stop\n"));
+ #endif
+ }
+}
+
+// Needs process context
+void Wb35Rx_destroy(phw_data_t pHwData)
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+ do {
+ OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
+ } while (pWb35Rx->EP3vm_state != VM_STOP);
+ OS_SLEEP(10000); // Delay for waiting function exit 940623.1.b
+
+ if (pWb35Rx->RxUrb)
+ usb_free_urb( pWb35Rx->RxUrb );
+ #ifdef _PE_RX_DUMP_
+ WBDEBUG(("Wb35Rx_destroy OK\n"));
+ #endif
+}
+
+void Wb35Rx_reset_descriptor( phw_data_t pHwData )
+{
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+ u32 i;
+
+ pWb35Rx->ByteReceived = 0;
+ pWb35Rx->RxProcessIndex = 0;
+ pWb35Rx->RxBufferId = 0;
+ pWb35Rx->EP3vm_state = VM_STOP;
+ pWb35Rx->rx_halt = 0;
+
+ // Initial the Queue. The last buffer is reserved for used if the Rx resource is unavailable.
+ for( i=0; i<MAX_USB_RX_BUFFER_NUMBER; i++ )
+ pWb35Rx->RxOwner[i] = 1;
+}
+
+void Wb35Rx_adjust(PDESCRIPTOR pRxDes)
+{
+ PULONG pRxBufferAddress;
+ u32 DecryptionMethod;
+ u32 i;
+ u16 BufferSize;
+
+ DecryptionMethod = pRxDes->R01.R01_decryption_method;
+ pRxBufferAddress = pRxDes->buffer_address[0];
+ BufferSize = pRxDes->buffer_size[0];
+
+ // Adjust the last part of data. Only data left
+ BufferSize -= 4; // For CRC-32
+ if (DecryptionMethod)
+ BufferSize -= 4;
+ if (DecryptionMethod == 3) // For CCMP
+ BufferSize -= 4;
+
+ // Adjust the IV field which after 802.11 header and ICV field.
+ if (DecryptionMethod == 1) // For WEP
+ {
+ for( i=6; i>0; i-- )
+ pRxBufferAddress[i] = pRxBufferAddress[i-1];
+ pRxDes->buffer_address[0] = pRxBufferAddress + 1;
+ BufferSize -= 4; // 4 byte for IV
+ }
+ else if( DecryptionMethod ) // For TKIP and CCMP
+ {
+ for (i=7; i>1; i--)
+ pRxBufferAddress[i] = pRxBufferAddress[i-2];
+ pRxDes->buffer_address[0] = pRxBufferAddress + 2;//Update the descriptor, shift 8 byte
+ BufferSize -= 8; // 8 byte for IV + ICV
+ }
+ pRxDes->buffer_size[0] = BufferSize;
+}
+
+extern void packet_came(char *pRxBufferAddress, int PacketSize);
+
+
+u16 Wb35Rx_indicate(phw_data_t pHwData)
+{
+ DESCRIPTOR RxDes;
+ PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+ PUCHAR pRxBufferAddress;
+ u16 PacketSize;
+ u16 stmp, BufferSize, stmp2 = 0;
+ u32 RxBufferId;
+
+ // Only one thread be allowed to run into the following
+ do {
+ RxBufferId = pWb35Rx->RxProcessIndex;
+ if (pWb35Rx->RxOwner[ RxBufferId ]) //Owner by VM
+ break;
+
+ pWb35Rx->RxProcessIndex++;
+ pWb35Rx->RxProcessIndex %= MAX_USB_RX_BUFFER_NUMBER;
+
+ pRxBufferAddress = pWb35Rx->pDRx;
+ BufferSize = pWb35Rx->RxBufferSize[ RxBufferId ];
+
+ // Parse the bulkin buffer
+ while (BufferSize >= 4) {
+ if ((cpu_to_le32(*(PULONG)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
+ break;
+
+ // Get the R00 R01 first
+ RxDes.R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+ PacketSize = (u16)RxDes.R00.R00_receive_byte_count;
+ RxDes.R01.value = le32_to_cpu(*((PULONG)(pRxBufferAddress+4)));
+ // For new DMA 4k
+ if ((PacketSize & 0x03) > 0)
+ PacketSize -= 4;
+
+ // Basic check for Rx length. Is length valid?
+ if (PacketSize > MAX_PACKET_SIZE) {
+ #ifdef _PE_RX_DUMP_
+ WBDEBUG(("Serious ERROR : Rx data size too long, size =%d\n", PacketSize));
+ #endif
+
+ pWb35Rx->EP3vm_state = VM_STOP;
+ pWb35Rx->Ep3ErrorCount2++;
+ break;
+ }
+
+ // Start to process Rx buffer
+// RxDes.Descriptor_ID = RxBufferId; // Due to synchronous indicate, the field doesn't necessary to use.
+ BufferSize -= 8; //subtract 8 byte for 35's USB header length
+ pRxBufferAddress += 8;
+
+ RxDes.buffer_address[0] = pRxBufferAddress;
+ RxDes.buffer_size[0] = PacketSize;
+ RxDes.buffer_number = 1;
+ RxDes.buffer_start_index = 0;
+ RxDes.buffer_total_size = RxDes.buffer_size[0];
+ Wb35Rx_adjust(&RxDes);
+
+ packet_came(pRxBufferAddress, PacketSize);
+
+ // Move RxBuffer point to the next
+ stmp = PacketSize + 3;
+ stmp &= ~0x03; // 4n alignment
+ pRxBufferAddress += stmp;
+ BufferSize -= stmp;
+ stmp2 += stmp;
+ }
+
+ // Reclaim resource
+ pWb35Rx->RxOwner[ RxBufferId ] = 1;
+ } while(TRUE);
+
+ return stmp2;
+}
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx_f.h b/drivers/staging/winbond/linux/wb35rx_f.h
new file mode 100644
index 00000000000..daa3e73042b
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx_f.h
@@ -0,0 +1,17 @@
+//====================================
+// Interface function declare
+//====================================
+void Wb35Rx_reset_descriptor( phw_data_t pHwData );
+unsigned char Wb35Rx_initial( phw_data_t pHwData );
+void Wb35Rx_destroy( phw_data_t pHwData );
+void Wb35Rx_stop( phw_data_t pHwData );
+u16 Wb35Rx_indicate( phw_data_t pHwData );
+void Wb35Rx_adjust( PDESCRIPTOR pRxDes );
+void Wb35Rx_start( phw_data_t pHwData );
+
+void Wb35Rx( phw_data_t pHwData );
+void Wb35Rx_Complete( PURB pUrb );
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx_s.h b/drivers/staging/winbond/linux/wb35rx_s.h
new file mode 100644
index 00000000000..53b831fdeb7
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx_s.h
@@ -0,0 +1,48 @@
+//============================================================================
+// wb35rx.h --
+//============================================================================
+
+// Definition for this module used
+#define MAX_USB_RX_BUFFER 4096 // This parameter must be 4096 931130.4.f
+
+#define MAX_USB_RX_BUFFER_NUMBER ETHERNET_RX_DESCRIPTORS // Maximum 254, 255 is RESERVED ID
+#define RX_INTERFACE 0 // Interface 1
+#define RX_PIPE 2 // Pipe 3
+#define MAX_PACKET_SIZE 1600 //1568 // 8 + 1532 + 4 + 24(IV EIV MIC ICV CRC) for check DMA data 931130.4.g
+#define RX_END_TAG 0x0badbeef
+
+
+//====================================
+// Internal variable for module
+//====================================
+typedef struct _WB35RX
+{
+ u32 ByteReceived;// For calculating throughput of BulkIn
+ OS_ATOMIC RxFireCounter;// Does Wb35Rx module fire?
+
+ u8 RxBuffer[ MAX_USB_RX_BUFFER_NUMBER ][ ((MAX_USB_RX_BUFFER+3) & ~0x03 ) ];
+ u16 RxBufferSize[ ((MAX_USB_RX_BUFFER_NUMBER+1) & ~0x01) ];
+ u8 RxOwner[ ((MAX_USB_RX_BUFFER_NUMBER+3) & ~0x03 ) ];//Ownership of buffer 0: SW 1:HW
+
+ u32 RxProcessIndex;//The next index to process
+ u32 RxBufferId;
+ u32 EP3vm_state;
+
+ u32 rx_halt; // For VM stopping
+
+ u16 MoreDataSize;
+ u16 PacketSize;
+
+ u32 CurrentRxBufferId; // For complete routine usage
+ u32 Rx3UrbCancel;
+
+ u32 LastR1; // For RSSI reporting
+ struct urb * RxUrb;
+ u32 Ep3ErrorCount2; // 20060625.1 Usbd for Rx DMA error count
+
+ int EP3VM_status;
+ PUCHAR pDRx;
+
+} WB35RX, *PWB35RX;
+
+
diff --git a/drivers/staging/winbond/linux/wb35tx.c b/drivers/staging/winbond/linux/wb35tx.c
new file mode 100644
index 00000000000..cf19c3bc524
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx.c
@@ -0,0 +1,313 @@
+//============================================================================
+// Copyright (c) 1996-2002 Winbond Electronic Corporation
+//
+// Module Name:
+// Wb35Tx.c
+//
+// Abstract:
+// Processing the Tx message and put into down layer
+//
+//============================================================================
+#include "sysdef.h"
+
+
+unsigned char
+Wb35Tx_get_tx_buffer(phw_data_t pHwData, PUCHAR *pBuffer )
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ *pBuffer = pWb35Tx->TxBuffer[0];
+ return TRUE;
+}
+
+void Wb35Tx_start(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ // Allow only one thread to run into function
+ if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Tx->TxFireCounter) == 1) {
+ pWb35Tx->EP4vm_state = VM_RUNNING;
+ Wb35Tx(pHwData);
+ } else
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+}
+
+
+void Wb35Tx(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+ PADAPTER Adapter = pHwData->Adapter;
+ PUCHAR pTxBufferAddress;
+ PMDS pMds = &Adapter->Mds;
+ struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
+ int retv;
+ u32 SendIndex;
+
+
+ if (pHwData->SurpriseRemove || pHwData->HwStop)
+ goto cleanup;
+
+ if (pWb35Tx->tx_halt)
+ goto cleanup;
+
+ // Ownership checking
+ SendIndex = pWb35Tx->TxSendIndex;
+ if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
+ goto cleanup;
+
+ pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
+ //
+ // Issuing URB
+ //
+ usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
+ usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
+ pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
+ Wb35Tx_complete, pHwData);
+
+ pWb35Tx->EP4vm_state = VM_RUNNING;
+ retv = wb_usb_submit_urb( pUrb );
+ if (retv<0) {
+ printk("EP4 Tx Irp sending error\n");
+ goto cleanup;
+ }
+
+ // Check if driver needs issue Irp for EP2
+ pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
+ if (pWb35Tx->TxFillCount > 12)
+ Wb35Tx_EP2VM_start( pHwData );
+
+ pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
+ return;
+
+ cleanup:
+ pWb35Tx->EP4vm_state = VM_STOP;
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+}
+
+
+void Wb35Tx_complete(struct urb * pUrb)
+{
+ phw_data_t pHwData = pUrb->context;
+ PADAPTER Adapter = (PADAPTER)pHwData->Adapter;
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+ PMDS pMds = &Adapter->Mds;
+
+ printk("wb35: tx complete\n");
+ // Variable setting
+ pWb35Tx->EP4vm_state = VM_COMPLETED;
+ pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
+ pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
+ pWb35Tx->TxSendIndex++;
+ pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
+
+ do {
+ if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
+ break;
+
+ if (pWb35Tx->tx_halt)
+ break;
+
+ // The URB is completed, check the result
+ if (pWb35Tx->EP4VM_status != 0) {
+ printk("URB submission failed\n");
+ pWb35Tx->EP4vm_state = VM_STOP;
+ break; // Exit while(FALSE);
+ }
+
+ Mds_Tx(Adapter);
+ Wb35Tx(pHwData);
+ return;
+ } while(FALSE);
+
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+ pWb35Tx->EP4vm_state = VM_STOP;
+}
+
+void Wb35Tx_reset_descriptor( phw_data_t pHwData )
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ pWb35Tx->TxSendIndex = 0;
+ pWb35Tx->tx_halt = 0;
+}
+
+unsigned char Wb35Tx_initial(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ pWb35Tx->Tx4Urb = wb_usb_alloc_urb(0);
+ if (!pWb35Tx->Tx4Urb)
+ return FALSE;
+
+ pWb35Tx->Tx2Urb = wb_usb_alloc_urb(0);
+ if (!pWb35Tx->Tx2Urb)
+ {
+ usb_free_urb( pWb35Tx->Tx4Urb );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//======================================================
+void Wb35Tx_stop(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ // Trying to canceling the Trp of EP2
+ if (pWb35Tx->EP2vm_state == VM_RUNNING)
+ usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("EP2 Tx stop\n"));
+ #endif
+
+ // Trying to canceling the Irp of EP4
+ if (pWb35Tx->EP4vm_state == VM_RUNNING)
+ usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("EP4 Tx stop\n"));
+ #endif
+}
+
+//======================================================
+void Wb35Tx_destroy(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ // Wait for VM stop
+ do {
+ OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
+ } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
+ OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
+
+ if (pWb35Tx->Tx4Urb)
+ usb_free_urb( pWb35Tx->Tx4Urb );
+
+ if (pWb35Tx->Tx2Urb)
+ usb_free_urb( pWb35Tx->Tx2Urb );
+
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("Wb35Tx_destroy OK\n"));
+ #endif
+}
+
+void Wb35Tx_CurrentTime(phw_data_t pHwData, u32 TimeCount)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+ unsigned char Trigger = FALSE;
+
+ if (pWb35Tx->TxTimer > TimeCount)
+ Trigger = TRUE;
+ else if (TimeCount > (pWb35Tx->TxTimer+500))
+ Trigger = TRUE;
+
+ if (Trigger) {
+ pWb35Tx->TxTimer = TimeCount;
+ Wb35Tx_EP2VM_start( pHwData );
+ }
+}
+
+void Wb35Tx_EP2VM_start(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+ // Allow only one thread to run into function
+ if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Tx->TxResultCount ) == 1) {
+ pWb35Tx->EP2vm_state = VM_RUNNING;
+ Wb35Tx_EP2VM( pHwData );
+ }
+ else
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+}
+
+
+void Wb35Tx_EP2VM(phw_data_t pHwData)
+{
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+ struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
+ PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
+ int retv;
+
+ do {
+ if (pHwData->SurpriseRemove || pHwData->HwStop)
+ break;
+
+ if (pWb35Tx->tx_halt)
+ break;
+
+ //
+ // Issuing URB
+ //
+ usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
+ pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
+
+ pWb35Tx->EP2vm_state = VM_RUNNING;
+ retv = wb_usb_submit_urb( pUrb );
+
+ if(retv < 0) {
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("EP2 Tx Irp sending error\n"));
+ #endif
+ break;
+ }
+
+ return;
+
+ } while(FALSE);
+
+ pWb35Tx->EP2vm_state = VM_STOP;
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+}
+
+
+void Wb35Tx_EP2VM_complete(struct urb * pUrb)
+{
+ phw_data_t pHwData = pUrb->context;
+ T02_DESCRIPTOR T02, TSTATUS;
+ PADAPTER Adapter = (PADAPTER)pHwData->Adapter;
+ PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+ PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
+ u32 i;
+ u16 InterruptInLength;
+
+
+ // Variable setting
+ pWb35Tx->EP2vm_state = VM_COMPLETED;
+ pWb35Tx->EP2VM_status = pUrb->status;
+
+ do {
+ // For Linux 2.4. Interrupt will always trigger
+ if( pHwData->SurpriseRemove || pHwData->HwStop ) // Let WbWlanHalt to handle surprise remove
+ break;
+
+ if( pWb35Tx->tx_halt )
+ break;
+
+ //The Urb is completed, check the result
+ if (pWb35Tx->EP2VM_status != 0) {
+ WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
+ pWb35Tx->EP2vm_state= VM_STOP;
+ break; // Exit while(FALSE);
+ }
+
+ // Update the Tx result
+ InterruptInLength = pUrb->actual_length;
+ // Modify for minimum memory access and DWORD alignment.
+ T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
+ InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
+ InterruptInLength >>= 2; // InterruptInLength/4
+ for (i=1; i<=InterruptInLength; i++) {
+ T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
+
+ TSTATUS.value = T02.value; //20061009 anson's endian
+ Mds_SendComplete( Adapter, &TSTATUS );
+ T02.value = cpu_to_le32(pltmp[i]) >> 8;
+ }
+
+ return;
+ } while(FALSE);
+
+ OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+ pWb35Tx->EP2vm_state = VM_STOP;
+}
+
diff --git a/drivers/staging/winbond/linux/wb35tx_f.h b/drivers/staging/winbond/linux/wb35tx_f.h
new file mode 100644
index 00000000000..7705a8454dc
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx_f.h
@@ -0,0 +1,20 @@
+//====================================
+// Interface function declare
+//====================================
+unsigned char Wb35Tx_initial( phw_data_t pHwData );
+void Wb35Tx_destroy( phw_data_t pHwData );
+unsigned char Wb35Tx_get_tx_buffer( phw_data_t pHwData, PUCHAR *pBuffer );
+
+void Wb35Tx_EP2VM( phw_data_t pHwData );
+void Wb35Tx_EP2VM_start( phw_data_t pHwData );
+void Wb35Tx_EP2VM_complete( PURB purb );
+
+void Wb35Tx_start( phw_data_t pHwData );
+void Wb35Tx_stop( phw_data_t pHwData );
+void Wb35Tx( phw_data_t pHwData );
+void Wb35Tx_complete( PURB purb );
+void Wb35Tx_reset_descriptor( phw_data_t pHwData );
+
+void Wb35Tx_CurrentTime( phw_data_t pHwData, u32 TimeCount );
+
+
diff --git a/drivers/staging/winbond/linux/wb35tx_s.h b/drivers/staging/winbond/linux/wb35tx_s.h
new file mode 100644
index 00000000000..ac432573676
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx_s.h
@@ -0,0 +1,47 @@
+//====================================
+// IS89C35 Tx related definition
+//====================================
+#define TX_INTERFACE 0 // Interface 1
+#define TX_PIPE 3 // endpoint 4
+#define TX_INTERRUPT 1 // endpoint 2
+#define MAX_INTERRUPT_LENGTH 64 // It must be 64 for EP2 hardware
+
+
+
+//====================================
+// Internal variable for module
+//====================================
+
+
+typedef struct _WB35TX
+{
+ // For Tx buffer
+ u8 TxBuffer[ MAX_USB_TX_BUFFER_NUMBER ][ MAX_USB_TX_BUFFER ];
+
+ // For Interrupt pipe
+ u8 EP2_buf[MAX_INTERRUPT_LENGTH];
+
+ OS_ATOMIC TxResultCount;// For thread control of EP2 931130.4.m
+ OS_ATOMIC TxFireCounter;// For thread control of EP4 931130.4.n
+ u32 ByteTransfer;
+
+ u32 TxSendIndex;// The next index of Mds array to be sent
+ u32 EP2vm_state; // for EP2vm state
+ u32 EP4vm_state; // for EP4vm state
+ u32 tx_halt; // Stopping VM
+
+ struct urb * Tx4Urb;
+ struct urb * Tx2Urb;
+
+ int EP2VM_status;
+ int EP4VM_status;
+
+ u32 TxFillCount; // 20060928
+ u32 TxTimer; // 20060928 Add if sending packet not great than 13
+
+} WB35TX, *PWB35TX;
+
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wbusb.c b/drivers/staging/winbond/linux/wbusb.c
new file mode 100644
index 00000000000..cbad5fb0595
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2008 Pavel Machek <pavel@suse.cz>
+ *
+ * Distribute under GPLv2.
+ */
+#include "sysdef.h"
+#include <net/mac80211.h>
+
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+
+//============================================================
+// vendor ID and product ID can into here for others
+//============================================================
+static struct usb_device_id Id_Table[] =
+{
+ {USB_DEVICE( 0x0416, 0x0035 )},
+ {USB_DEVICE( 0x18E8, 0x6201 )},
+ {USB_DEVICE( 0x18E8, 0x6206 )},
+ {USB_DEVICE( 0x18E8, 0x6217 )},
+ {USB_DEVICE( 0x18E8, 0x6230 )},
+ {USB_DEVICE( 0x18E8, 0x6233 )},
+ {USB_DEVICE( 0x1131, 0x2035 )},
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, Id_Table);
+
+static struct usb_driver wb35_driver = {
+ .name = "w35und",
+ .probe = wb35_probe,
+ .disconnect = wb35_disconnect,
+ .id_table = Id_Table,
+};
+
+static const struct ieee80211_rate wbsoft_rates[] = {
+ { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+};
+
+static const struct ieee80211_channel wbsoft_channels[] = {
+ { .center_freq = 2412},
+};
+
+int wbsoft_enabled;
+struct ieee80211_hw *my_dev;
+PADAPTER my_adapter;
+
+static int wbsoft_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ printk("wbsoft_add interface called\n");
+ return 0;
+}
+
+static void wbsoft_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ printk("wbsoft_remove interface called\n");
+}
+
+static int wbsoft_nop(void)
+{
+ printk("wbsoft_nop called\n");
+ return 0;
+}
+
+static void wbsoft_configure_filter(struct ieee80211_hw *dev,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ unsigned int bit_nr, new_flags;
+ u32 mc_filter[2];
+ int i;
+
+ new_flags = 0;
+
+ if (*total_flags & FIF_PROMISC_IN_BSS) {
+ new_flags |= FIF_PROMISC_IN_BSS;
+ mc_filter[1] = mc_filter[0] = ~0;
+ } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {
+ new_flags |= FIF_ALLMULTI;
+ mc_filter[1] = mc_filter[0] = ~0;
+ } else {
+ mc_filter[1] = mc_filter[0] = 0;
+ for (i = 0; i < mc_count; i++) {
+ if (!mclist)
+ break;
+ printk("Should call ether_crc here\n");
+ //bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+ bit_nr = 0;
+
+ bit_nr &= 0x3F;
+ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+ mclist = mclist->next;
+ }
+ }
+
+ dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
+ *total_flags = new_flags;
+}
+
+static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ char *buffer = kmalloc(skb->len, GFP_ATOMIC);
+ printk("Sending frame %d bytes\n", skb->len);
+ memcpy(buffer, skb->data, skb->len);
+ if (1 == MLMESendFrame(my_adapter, buffer, skb->len, FRAME_TYPE_802_11_MANAGEMENT))
+ printk("frame sent ok (%d bytes)?\n", skb->len);
+ return NETDEV_TX_OK;
+}
+
+
+static int wbsoft_start(struct ieee80211_hw *dev)
+{
+ wbsoft_enabled = 1;
+ printk("wbsoft_start called\n");
+ return 0;
+}
+
+static int wbsoft_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+ ChanInfo ch;
+ printk("wbsoft_config called\n");
+
+ ch.band = 1;
+ ch.ChanNo = 1; /* Should use channel_num, or something, as that is already pre-translated */
+
+
+ hal_set_current_channel(&my_adapter->sHwData, ch);
+ hal_set_beacon_period(&my_adapter->sHwData, conf->beacon_int);
+// hal_set_cap_info(&my_adapter->sHwData, ?? );
+// hal_set_ssid(phw_data_t pHwData, PUCHAR pssid, u8 ssid_len); ??
+ hal_set_accept_broadcast(&my_adapter->sHwData, 1);
+ hal_set_accept_promiscuous(&my_adapter->sHwData, 1);
+ hal_set_accept_multicast(&my_adapter->sHwData, 1);
+ hal_set_accept_beacon(&my_adapter->sHwData, 1);
+ hal_set_radio_mode(&my_adapter->sHwData, 0);
+ //hal_set_antenna_number( phw_data_t pHwData, u8 number )
+ //hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex)
+
+
+// hal_start_bss(&my_adapter->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ??
+
+//void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
+// u8 length, unsigned char basic_rate_set)
+
+ return 0;
+}
+
+static int wbsoft_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ printk("wbsoft_config_interface called\n");
+ return 0;
+}
+
+static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
+{
+ printk("wbsoft_get_tsf called\n");
+ return 0;
+}
+
+static const struct ieee80211_ops wbsoft_ops = {
+ .tx = wbsoft_tx,
+ .start = wbsoft_start, /* Start can be pretty much empty as we do WbWLanInitialize() during probe? */
+ .stop = wbsoft_nop,
+ .add_interface = wbsoft_add_interface,
+ .remove_interface = wbsoft_remove_interface,
+ .config = wbsoft_config,
+ .config_interface = wbsoft_config_interface,
+ .configure_filter = wbsoft_configure_filter,
+ .get_stats = wbsoft_nop,
+ .get_tx_stats = wbsoft_nop,
+ .get_tsf = wbsoft_get_tsf,
+// conf_tx: hal_set_cwmin()/hal_set_cwmax;
+};
+
+struct wbsoft_priv {
+};
+
+
+int __init wb35_init(void)
+{
+ printk("[w35und]driver init\n");
+ return usb_register(&wb35_driver);
+}
+
+void __exit wb35_exit(void)
+{
+ printk("[w35und]driver exit\n");
+ usb_deregister( &wb35_driver );
+}
+
+module_init(wb35_init);
+module_exit(wb35_exit);
+
+// Usb kernel subsystem will call this function when a new device is plugged into.
+int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
+{
+ PADAPTER Adapter;
+ PWBLINUX pWbLinux;
+ PWBUSB pWbUsb;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ int i, ret = -1;
+ u32 ltmp;
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ usb_get_dev(udev);
+
+ printk("[w35und]wb35_probe ->\n");
+
+ do {
+ for (i=0; i<(sizeof(Id_Table)/sizeof(struct usb_device_id)); i++ ) {
+ if ((udev->descriptor.idVendor == Id_Table[i].idVendor) &&
+ (udev->descriptor.idProduct == Id_Table[i].idProduct)) {
+ printk("[w35und]Found supported hardware\n");
+ break;
+ }
+ }
+ if ((i == (sizeof(Id_Table)/sizeof(struct usb_device_id)))) {
+ #ifdef _PE_USB_INI_DUMP_
+ WBDEBUG(("[w35und] This is not the one we are interested about\n"));
+ #endif
+ return -ENODEV;
+ }
+
+ // 20060630.2 Check the device if it already be opened
+ ret = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
+ 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+ 0x0, 0x400, &ltmp, 4, HZ*100 );
+ if( ret < 0 )
+ break;
+
+ ltmp = cpu_to_le32(ltmp);
+ if (ltmp) // Is already initialized?
+ break;
+
+
+ Adapter = kzalloc(sizeof(ADAPTER), GFP_KERNEL);
+
+ my_adapter = Adapter;
+ pWbLinux = &Adapter->WbLinux;
+ pWbUsb = &Adapter->sHwData.WbUsb;
+ pWbUsb->udev = udev;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+
+ if (endpoint[2].wMaxPacketSize == 512) {
+ printk("[w35und] Working on USB 2.0\n");
+ pWbUsb->IsUsb20 = 1;
+ }
+
+ if (!WbWLanInitialize(Adapter)) {
+ printk("[w35und]WbWLanInitialize fail\n");
+ break;
+ }
+
+ {
+ struct wbsoft_priv *priv;
+ struct ieee80211_hw *dev;
+ int res;
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
+
+ if (!dev) {
+ printk("w35und: ieee80211 alloc failed\n" );
+ BUG();
+ }
+
+ my_dev = dev;
+
+ SET_IEEE80211_DEV(dev, &udev->dev);
+ {
+ phw_data_t pHwData = &Adapter->sHwData;
+ unsigned char dev_addr[MAX_ADDR_LEN];
+ hal_get_permanent_address(pHwData, dev_addr);
+ SET_IEEE80211_PERM_ADDR(dev, dev_addr);
+ }
+
+
+ dev->extra_tx_headroom = 12; /* FIXME */
+ dev->flags = 0;
+
+ dev->channel_change_time = 1000;
+// dev->max_rssi = 100;
+
+ dev->queues = 1;
+
+ static struct ieee80211_supported_band band;
+
+ band.channels = wbsoft_channels;
+ band.n_channels = ARRAY_SIZE(wbsoft_channels);
+ band.bitrates = wbsoft_rates;
+ band.n_bitrates = ARRAY_SIZE(wbsoft_rates);
+
+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band;
+#if 0
+ wbsoft_modes[0].num_channels = 1;
+ wbsoft_modes[0].channels = wbsoft_channels;
+ wbsoft_modes[0].mode = MODE_IEEE80211B;
+ wbsoft_modes[0].num_rates = ARRAY_SIZE(wbsoft_rates);
+ wbsoft_modes[0].rates = wbsoft_rates;
+
+ res = ieee80211_register_hwmode(dev, &wbsoft_modes[0]);
+ BUG_ON(res);
+#endif
+
+ res = ieee80211_register_hw(dev);
+ BUG_ON(res);
+ }
+
+ usb_set_intfdata( intf, Adapter );
+
+ printk("[w35und] _probe OK\n");
+ return 0;
+
+ } while(FALSE);
+
+ return -ENOMEM;
+}
+
+void packet_came(char *pRxBufferAddress, int PacketSize)
+{
+ struct sk_buff *skb;
+ struct ieee80211_rx_status rx_status = {0};
+
+ if (!wbsoft_enabled)
+ return;
+
+ skb = dev_alloc_skb(PacketSize);
+ if (!skb) {
+ printk("Not enough memory for packet, FIXME\n");
+ return;
+ }
+
+ memcpy(skb_put(skb, PacketSize),
+ pRxBufferAddress,
+ PacketSize);
+
+/*
+ rx_status.rate = 10;
+ rx_status.channel = 1;
+ rx_status.freq = 12345;
+ rx_status.phymode = MODE_IEEE80211B;
+*/
+
+ ieee80211_rx_irqsafe(my_dev, skb, &rx_status);
+}
+
+unsigned char
+WbUsb_initial(phw_data_t pHwData)
+{
+ return 1;
+}
+
+
+void
+WbUsb_destroy(phw_data_t pHwData)
+{
+}
+
+int wb35_open(struct net_device *netdev)
+{
+ PADAPTER Adapter = (PADAPTER)netdev->priv;
+ phw_data_t pHwData = &Adapter->sHwData;
+
+ netif_start_queue(netdev);
+
+ //TODO : put here temporarily
+ hal_set_accept_broadcast(pHwData, 1); // open accept broadcast
+
+ return 0;
+}
+
+int wb35_close(struct net_device *netdev)
+{
+ netif_stop_queue(netdev);
+ return 0;
+}
+
+void wb35_disconnect(struct usb_interface *intf)
+{
+ PWBLINUX pWbLinux;
+ PADAPTER Adapter = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+
+ pWbLinux = &Adapter->WbLinux;
+
+ // Card remove
+ WbWlanHalt(Adapter);
+
+}
+
+
diff --git a/drivers/staging/winbond/linux/wbusb_f.h b/drivers/staging/winbond/linux/wbusb_f.h
new file mode 100644
index 00000000000..cae29e107e1
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb_f.h
@@ -0,0 +1,34 @@
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Copyright (c) 1996-2004 Winbond Electronic Corporation
+//
+// Module Name:
+// wbusb_f.h
+//
+// Abstract:
+// Linux driver.
+//
+// Author:
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+int wb35_open(struct net_device *netdev);
+int wb35_close(struct net_device *netdev);
+unsigned char WbUsb_initial(phw_data_t pHwData);
+void WbUsb_destroy(phw_data_t pHwData);
+unsigned char WbWLanInitialize(PADAPTER Adapter);
+#define WbUsb_Stop( _A )
+
+int wb35_probe(struct usb_interface *intf,const struct usb_device_id *id_table);
+void wb35_disconnect(struct usb_interface *intf);
+
+
+#define wb_usb_submit_urb(_A) usb_submit_urb(_A, GFP_ATOMIC)
+#define wb_usb_alloc_urb(_A) usb_alloc_urb(_A, GFP_ATOMIC)
+
+#define WbUsb_CheckForHang( _P )
+#define WbUsb_DetectStart( _P, _I )
+
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wbusb_s.h b/drivers/staging/winbond/linux/wbusb_s.h
new file mode 100644
index 00000000000..d5c1d53de70
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb_s.h
@@ -0,0 +1,42 @@
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Copyright (c) 1996-2004 Winbond Electronic Corporation
+//
+// Module Name:
+// wbusb_s.h
+//
+// Abstract:
+// Linux driver.
+//
+// Author:
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#define OS_SLEEP( _MT ) { set_current_state(TASK_INTERRUPTIBLE); \
+ schedule_timeout( _MT*HZ/1000000 ); }
+
+
+//---------------------------------------------------------------------------
+// RW_CONTEXT --
+//
+// Used to track driver-generated io irps
+//---------------------------------------------------------------------------
+typedef struct _RW_CONTEXT
+{
+ void* pHwData;
+ PURB pUrb;
+ void* pCallBackFunctionParameter;
+} RW_CONTEXT, *PRW_CONTEXT;
+
+
+
+
+#define DRIVER_AUTHOR "Original by: Jeff Lee<YY_Lee@issc.com.tw> Adapted to 2.6.x by Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>"
+#define DRIVER_DESC "IS89C35 802.11bg WLAN USB Driver"
+
+
+
+typedef struct _WBUSB {
+ u32 IsUsb20;
+ struct usb_device *udev;
+ u32 DetectCount;
+} WBUSB, *PWBUSB;
diff --git a/drivers/staging/winbond/localpara.h b/drivers/staging/winbond/localpara.h
new file mode 100644
index 00000000000..268cf916ab4
--- /dev/null
+++ b/drivers/staging/winbond/localpara.h
@@ -0,0 +1,275 @@
+//=============================================================
+// LocalPara.h -
+//=============================================================
+//Define the local ability
+
+#define LOCAL_DEFAULT_BEACON_PERIOD 100 //ms
+#define LOCAL_DEFAULT_ATIM_WINDOW 0
+#define LOCAL_DEFAULT_ERP_CAPABILITY 0x0431 //0x0001: ESS
+ //0x0010: Privacy
+ //0x0020: short preamble
+ //0x0400: short slot time
+#define LOCAL_DEFAULT_LISTEN_INTERVAL 5
+
+//#define LOCAL_DEFAULT_24_CHANNEL_NUM 11 // channel 1..11
+#define LOCAL_DEFAULT_24_CHANNEL_NUM 13 // channel 1..13
+#define LOCAL_DEFAULT_5_CHANNEL_NUM 8 // channel 36..64
+
+#define LOCAL_USA_24_CHANNEL_NUM 11
+#define LOCAL_USA_5_CHANNEL_NUM 12
+#define LOCAL_EUROPE_24_CHANNEL_NUM 13
+#define LOCAL_EUROPE_5_CHANNEL_NUM 19
+#define LOCAL_JAPAN_24_CHANNEL_NUM 14
+#define LOCAL_JAPAN_5_CHANNEL_NUM 11
+#define LOCAL_UNKNOWN_24_CHANNEL_NUM 14
+#define LOCAL_UNKNOWN_5_CHANNEL_NUM 34 //not include 165
+
+
+#define psLOCAL (&(Adapter->sLocalPara))
+
+#define MODE_802_11_BG 0
+#define MODE_802_11_A 1
+#define MODE_802_11_ABG 2
+#define MODE_802_11_BG_IBSS 3
+#define MODE_802_11_B 4
+#define MODE_AUTO 255
+
+#define BAND_TYPE_DSSS 0
+#define BAND_TYPE_OFDM_24 1
+#define BAND_TYPE_OFDM_5 2
+
+//refer Bitmap2RateValue table
+#define LOCAL_ALL_SUPPORTED_RATES_BITMAP 0x130c1a66 //the bitmap value of all the H/W supported rates
+ //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+#define LOCAL_OFDM_SUPPORTED_RATES_BITMAP 0x130c1240 //the bitmap value of all the H/W supported rates
+ //except to non-OFDM rates
+ //6, 9, 12, 18, 24, 36, 48, 54
+
+#define LOCAL_11B_SUPPORTED_RATE_BITMAP 0x826
+#define LOCAL_11B_BASIC_RATE_BITMAP 0x826
+#define LOCAL_11B_OPERATION_RATE_BITMAP 0x826
+#define LOCAL_11G_BASIC_RATE_BITMAP 0x826 //1, 2, 5.5, 11
+#define LOCAL_11G_OPERATION_RATE_BITMAP 0x130c1240 //6, 9, 12, 18, 24, 36, 48, 54
+#define LOCAL_11A_BASIC_RATE_BITMAP 0x01001040 //6, 12, 24
+#define LOCAL_11A_OPERATION_RATE_BITMAP 0x120c0200 //9, 18, 36, 48, 54
+
+
+
+#define PWR_ACTIVE 0
+#define PWR_SAVE 1
+#define PWR_TX_IDLE_CYCLE 6
+
+//bPreambleMode and bSlotTimeMode
+#define AUTO_MODE 0
+#define LONG_MODE 1
+
+//Region definition
+#define REGION_AUTO 0xff
+#define REGION_UNKNOWN 0
+#define REGION_EUROPE 1 //ETSI
+#define REGION_JAPAN 2 //MKK
+#define REGION_USA 3 //FCC
+#define REGION_FRANCE 4 //FRANCE
+#define REGION_SPAIN 5 //SPAIN
+#define REGION_ISRAEL 6 //ISRAEL
+//#define REGION_CANADA 7 //IC
+
+#define MAX_BSS_DESCRIPT_ELEMENT 32
+#define MAX_PMKID_CandidateList 16
+
+//High byte : Event number, low byte : reason
+//Event definition
+//-- SME/MLME event
+#define EVENT_RCV_DEAUTH 0x0100
+#define EVENT_JOIN_FAIL 0x0200
+#define EVENT_AUTH_FAIL 0x0300
+#define EVENT_ASSOC_FAIL 0x0400
+#define EVENT_LOST_SIGNAL 0x0500
+#define EVENT_BSS_DESCRIPT_LACK 0x0600
+#define EVENT_COUNTERMEASURE 0x0700
+#define EVENT_JOIN_FILTER 0x0800
+//-- TX/RX event
+#define EVENT_RX_BUFF_UNAVAILABLE 0x4100
+
+#define EVENT_CONNECT 0x8100
+#define EVENT_DISCONNECT 0x8200
+#define EVENT_SCAN_REQ 0x8300
+
+//Reason of Event
+#define EVENT_REASON_FILTER_BASIC_RATE 0x0001
+#define EVENT_REASON_FILTER_PRIVACY 0x0002
+#define EVENT_REASON_FILTER_AUTH_MODE 0x0003
+#define EVENT_REASON_TIMEOUT 0x00ff
+
+// 20061108 WPS IE buffer
+#define MAX_IE_APPEND_SIZE 256 + 4 // Due to [E id][Length][OUI][Data] may 257 bytes
+
+typedef struct _EVENTLOG
+{
+ u16 Count; //Total count from start
+ u16 index; //Buffer index, 0 ~ 63
+ u32 EventValue[64]; //BYTE 3~2 : count, BYTE 1 : Event, BYTE 0 : reason
+} Event_Log, *pEvent_Log;
+
+typedef struct _ChanInfo
+{
+ u8 band;
+ u8 ChanNo;
+} ChanInfo, *pChanInfo;
+
+typedef struct _CHAN_LIST
+{
+ u16 Count;
+ ChanInfo Channel[50]; // 100B
+} CHAN_LIST, *psCHAN_LIST;
+
+typedef struct _RadioOff
+{
+ u8 boHwRadioOff;
+ u8 boSwRadioOff;
+} RadioOff, *psRadioOff;
+
+//===========================================================================
+typedef struct LOCAL_PARA
+{
+ u8 PermanentAddress[ MAC_ADDR_LENGTH + 2 ]; // read from EPROM, manufacture set for each NetCard
+ u8 ThisMacAddress[ MAC_ADDR_LENGTH + 2 ]; // the driver will use actually.
+
+ u32 MTUsize; // Ind to Uplayer, Max transmission unit size
+
+ u8 region_INF; //region setting from INF
+ u8 region; //real region setting of the device
+ u8 Reserved_1[2];
+
+ //// power-save variables
+ u8 iPowerSaveMode; // 0 indicates it is on, 1 indicates it is off
+ u8 ShutDowned;
+ u8 ATIMmode;
+ u8 ExcludeUnencrypted;
+
+ u16 CheckCountForPS; //Unit ime count for the decision to enter PS mode
+ u8 boHasTxActivity; //tx activity has occurred
+ u8 boMacPsValid; //Power save mode obtained from H/W is valid or not
+
+ //// Rate
+ u8 TxRateMode; // Initial, input from Registry, may be updated by GUI
+ //Tx Rate Mode: auto(DTO on), max, 1M, 2M, ..
+ u8 CurrentTxRate; // The current Tx rate
+ u8 CurrentTxRateForMng; // The current Tx rate for management frames
+ // It will be decided before connection succeeds.
+ u8 CurrentTxFallbackRate;
+
+ //for Rate handler
+ u8 BRateSet[32]; //basic rate set
+ u8 SRateSet[32]; //support rate set
+
+ u8 NumOfBRate;
+ u8 NumOfSRate;
+ u8 NumOfDsssRateInSRate; //number of DSSS rates in supported rate set
+ u8 reserved1;
+
+ u32 dwBasicRateBitmap; //bit map of basic rates
+ u32 dwSupportRateBitmap; //bit map of all support rates including
+ //basic and operational rates
+
+ ////For SME/MLME handler
+ u16 wOldSTAindex; // valid when boHandover=TRUE, store old connected STA index
+ u16 wConnectedSTAindex; // Index of peerly connected AP or IBSS in
+ // the descriptionset.
+ u16 Association_ID; // The Association ID in the (Re)Association
+ // Response frame.
+ u16 ListenInterval; // The listen interval when SME invoking MLME_
+ // (Re)Associate_Request().
+
+ RadioOff RadioOffStatus;
+ u8 Reserved0[2];
+
+ u8 boMsRadioOff; // Ndis demands to be true when set Disassoc. OID and be false when set SSID OID.
+ u8 boAntennaDiversity; //TRUE/ON or FALSE/OFF
+ u8 bAntennaNo; //which antenna
+ u8 bConnectFlag; //the connect status flag for roaming task
+
+ u8 RoamStatus;
+ u8 reserved7[3];
+
+ ChanInfo CurrentChan; //Current channel no. and channel band. It may be changed by scanning.
+ u8 boHandover; // Roaming, Hnadover to other AP.
+ u8 boCCAbusy;
+
+ u16 CWMax; // It may not be the real value that H/W used
+ u8 CWMin; // 255: set according to 802.11 spec.
+ u8 reserved2;
+
+ //11G:
+ u8 bMacOperationMode; // operation in 802.11b or 802.11g
+ u8 bSlotTimeMode; //AUTO, s32
+ u8 bPreambleMode; //AUTO, s32
+ u8 boNonERPpresent;
+
+ u8 boProtectMechanism; // H/W will take the necessary action based on this variable
+ u8 boShortPreamble; // H/W will take the necessary action based on this variable
+ u8 boShortSlotTime; // H/W will take the necessary action based on this variable
+ u8 reserved_3;
+
+ u32 RSN_IE_Bitmap; //added by WS
+ u32 RSN_OUI_Type; //added by WS
+
+ //For the BSSID
+ u8 HwBssid[MAC_ADDR_LENGTH + 2];
+ u32 HwBssidValid;
+
+ //For scan list
+ u8 BssListCount; //Total count of valid descriptor indexes
+ u8 boReceiveUncorrectInfo; //important settings in beacon/probe resp. have been changed
+ u8 NoOfJoinerInIbss;
+ u8 reserved_4;
+
+ u8 BssListIndex[ (MAX_BSS_DESCRIPT_ELEMENT+3) & ~0x03 ]; //Store the valid descriptor indexes obtained from scannings
+ u8 JoinerInIbss[ (MAX_BSS_DESCRIPT_ELEMENT+3) & ~0x03 ]; //save the BssDescriptor index in this
+ //IBSS. The index 0 is local descriptor
+ //(psLOCAL->wConnectedSTAindex).
+ //If CONNECTED : NoOfJoinerInIbss >=2
+ // else : NoOfJoinerInIbss <=1
+
+ //// General Statistics, count at Rx_handler or Tx_callback interrupt handler
+ u64 GS_XMIT_OK; // Good Frames Transmitted
+ u64 GS_RCV_OK; // Good Frames Received
+ u32 GS_RCV_ERROR; // Frames received with crc error
+ u32 GS_XMIT_ERROR; // Bad Frames Transmitted
+ u32 GS_RCV_NO_BUFFER; // Receive Buffer underrun
+ u32 GS_XMIT_ONE_COLLISION; // one collision
+ u32 GS_XMIT_MORE_COLLISIONS;// more collisions
+
+ //================================================================
+ // Statistics (no matter whether it had done successfully) -wkchen
+ //================================================================
+ u32 _NumRxMSDU;
+ u32 _NumTxMSDU;
+ u32 _dot11WEPExcludedCount;
+ u32 _dot11WEPUndecryptableCount;
+ u32 _dot11FrameDuplicateCount;
+
+ ChanInfo IbssChanSetting; // 2B. Start IBSS Channel setting by registry or WWU.
+ u8 reserved_5[2]; //It may not be used after considering RF type,
+ //region and modulation type.
+
+ CHAN_LIST sSupportChanList; // 86B. It will be obtained according to RF type and region
+ u8 reserved_6[2]; //two variables are for wep key error detection added by ws 02/02/04
+
+ u32 bWepKeyError;
+ u32 bToSelfPacketReceived;
+ u32 WepKeyDetectTimerCount;
+
+ Event_Log EventLog;
+
+ u16 SignalLostTh;
+ u16 SignalRoamTh;
+
+ // 20061108 WPS IE Append
+ u8 IE_Append_data[MAX_IE_APPEND_SIZE];
+ u16 IE_Append_size;
+ u16 reserved_7;
+
+} WB_LOCALDESCRIPT, *PWB_LOCALDESCRIPT;
+
+
diff --git a/drivers/staging/winbond/mac_structures.h b/drivers/staging/winbond/mac_structures.h
new file mode 100644
index 00000000000..031d2cb6cd6
--- /dev/null
+++ b/drivers/staging/winbond/mac_structures.h
@@ -0,0 +1,670 @@
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// MAC_Structures.h
+//
+// This file contains the definitions and data structures used by SW-MAC.
+//
+// Revision Histoy
+//=================
+// 0.1 2002 UN00
+// 0.2 20021004 PD43 CCLiu6
+// 20021018 PD43 CCLiu6
+// Add enum_TxRate type
+// Modify enum_STAState type
+// 0.3 20021023 PE23 CYLiu update MAC session struct
+// 20021108
+// 20021122 PD43 Austin
+// Deleted some unused.
+// 20021129 PD43 Austin
+// 20030617 increase the 802.11g definition
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef _MAC_Structures_H_
+#define _MAC_Structures_H_
+
+
+//=========================================================
+// Some miscellaneous definitions
+//-----
+#define MAX_CHANNELS 30
+#define MAC_ADDR_LENGTH 6
+#define MAX_WEP_KEY_SIZE 16 // 128 bits
+#define MAX_802_11_FRAGMENT_NUMBER 10 // By spec
+
+//========================================================
+// 802.11 Frame define
+//-----
+#define MASK_PROTOCOL_VERSION_TYPE 0x0F
+#define MASK_FRAGMENT_NUMBER 0x000F
+#define SEQUENCE_NUMBER_SHIFT 4
+#define DIFFER_11_TO_3 18
+#define DOT_11_MAC_HEADER_SIZE 24
+#define DOT_11_SNAP_SIZE 6
+#define DOT_11_DURATION_OFFSET 2
+#define DOT_11_SEQUENCE_OFFSET 22 //Sequence control offset
+#define DOT_11_TYPE_OFFSET 30 //The start offset of 802.11 Frame//
+#define DOT_11_DATA_OFFSET 24
+#define DOT_11_DA_OFFSET 4
+#define DOT_3_TYPE_ARP 0x80F3
+#define DOT_3_TYPE_IPX 0x8137
+#define DOT_3_TYPE_OFFSET 12
+
+
+#define ETHERNET_HEADER_SIZE 14
+#define MAX_ETHERNET_PACKET_SIZE 1514
+
+
+//----- management : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
+#define MAC_SUBTYPE_MNGMNT_ASSOC_REQUEST 0x00
+#define MAC_SUBTYPE_MNGMNT_ASSOC_RESPONSE 0x10
+#define MAC_SUBTYPE_MNGMNT_REASSOC_REQUEST 0x20
+#define MAC_SUBTYPE_MNGMNT_REASSOC_RESPONSE 0x30
+#define MAC_SUBTYPE_MNGMNT_PROBE_REQUEST 0x40
+#define MAC_SUBTYPE_MNGMNT_PROBE_RESPONSE 0x50
+#define MAC_SUBTYPE_MNGMNT_BEACON 0x80
+#define MAC_SUBTYPE_MNGMNT_ATIM 0x90
+#define MAC_SUBTYPE_MNGMNT_DISASSOCIATION 0xA0
+#define MAC_SUBTYPE_MNGMNT_AUTHENTICATION 0xB0
+#define MAC_SUBTYPE_MNGMNT_DEAUTHENTICATION 0xC0
+
+//----- control : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
+#define MAC_SUBTYPE_CONTROL_PSPOLL 0xA4
+#define MAC_SUBTYPE_CONTROL_RTS 0xB4
+#define MAC_SUBTYPE_CONTROL_CTS 0xC4
+#define MAC_SUBTYPE_CONTROL_ACK 0xD4
+#define MAC_SUBTYPE_CONTROL_CFEND 0xE4
+#define MAC_SUBTYPE_CONTROL_CFEND_CFACK 0xF4
+
+//----- data : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
+#define MAC_SUBTYPE_DATA 0x08
+#define MAC_SUBTYPE_DATA_CFACK 0x18
+#define MAC_SUBTYPE_DATA_CFPOLL 0x28
+#define MAC_SUBTYPE_DATA_CFACK_CFPOLL 0x38
+#define MAC_SUBTYPE_DATA_NULL 0x48
+#define MAC_SUBTYPE_DATA_CFACK_NULL 0x58
+#define MAC_SUBTYPE_DATA_CFPOLL_NULL 0x68
+#define MAC_SUBTYPE_DATA_CFACK_CFPOLL_NULL 0x78
+
+//----- Frame Type of Bits (2, 3)
+#define MAC_TYPE_MANAGEMENT 0x00
+#define MAC_TYPE_CONTROL 0x04
+#define MAC_TYPE_DATA 0x08
+
+//----- definitions for Management Frame Element ID (1 BYTE)
+#define ELEMENT_ID_SSID 0
+#define ELEMENT_ID_SUPPORTED_RATES 1
+#define ELEMENT_ID_FH_PARAMETER_SET 2
+#define ELEMENT_ID_DS_PARAMETER_SET 3
+#define ELEMENT_ID_CF_PARAMETER_SET 4
+#define ELEMENT_ID_TIM 5
+#define ELEMENT_ID_IBSS_PARAMETER_SET 6
+// 7~15 reserverd
+#define ELEMENT_ID_CHALLENGE_TEXT 16
+// 17~31 reserved for challenge text extension
+// 32~255 reserved
+//-- 11G --
+#define ELEMENT_ID_ERP_INFORMATION 42
+#define ELEMENT_ID_EXTENDED_SUPPORTED_RATES 50
+
+//-- WPA --
+
+#define ELEMENT_ID_RSN_WPA 221
+#ifdef _WPA2_
+#define ELEMENT_ID_RSN_WPA2 48
+#endif //endif WPA2
+
+#define WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT ((u16) 6)
+#define WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT ((u16) 2)
+
+#ifdef WB_LINUX
+#define UNALIGNED
+#endif
+
+//========================================================
+typedef enum enum_PowerManagementMode
+{
+ ACTIVE = 0,
+ POWER_SAVE
+} WB_PM_Mode, *PWB_PM_MODE;
+
+//===================================================================
+// Reason Code (Table 18): indicate the reason of DisAssoc, DeAuthen
+// length of ReasonCode is 2 Octs.
+//===================================================================
+#define REASON_REASERED 0
+#define REASON_UNSPECIDIED 1
+#define REASON_PREAUTH_INVALID 2
+#define DEAUTH_REASON_LEFT_BSS 3
+#define DISASS_REASON_AP_INACTIVE 4
+#define DISASS_REASON_AP_BUSY 5
+#define REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define REASON_CLASS3_FRAME_FROM_NONASSO_STA 7
+#define DISASS_REASON_LEFT_BSS 8
+#define REASON_NOT_AUTH_YET 9
+//802.11i define
+#define REASON_INVALID_IE 13
+#define REASON_MIC_ERROR 14
+#define REASON_4WAY_HANDSHAKE_TIMEOUT 15
+#define REASON_GROUPKEY_UPDATE_TIMEOUT 16
+#define REASON_IE_DIFF_4WAY_ASSOC 17
+#define REASON_INVALID_MULTICAST_CIPHER 18
+#define REASON_INVALID_UNICAST_CIPHER 19
+#define REASON_INVALID_AKMP 20
+#define REASON_UNSUPPORTED_RSNIE_VERSION 21
+#define REASON_INVALID_RSNIE_CAPABILITY 22
+#define REASON_802_1X_AUTH_FAIL 23
+#define REASON_CIPHER_REJECT_PER_SEC_POLICY 14
+
+/*
+//===========================================================
+// enum_MMPDUResultCode --
+// Status code (2 Octs) in the MMPDU's frame body. Table.19
+//
+//===========================================================
+enum enum_MMPDUResultCode
+{
+// SUCCESS = 0, // Redefined
+ UNSPECIFIED_FAILURE = 1,
+
+ // 2 - 9 Reserved
+
+ NOT_SUPPROT_CAPABILITIES = 10,
+
+ //REASSOCIATION_DENIED
+ //
+ REASSOC_DENIED_UNABLE_CFM_ASSOC_EXIST = 11,
+
+ //ASSOCIATION_DENIED_NOT_IN_STANDARD
+ //
+ ASSOC_DENIED_REASON_NOT_IN_STANDARD = 12,
+ PEER_NOT_SUPPORT_AUTH_ALGORITHM = 13,
+ AUTH_SEQNUM_OUT_OF_EXPECT = 14,
+ AUTH_REJECT_REASON_CHALLENGE_FAIL = 15,
+ AUTH_REJECT_REASON_WAIT_TIMEOUT = 16,
+ ASSOC_DENIED_REASON_AP_BUSY = 17,
+ ASSOC_DENIED_REASON_NOT_SUPPORT_BASIC_RATE = 18
+} WB_MMPDURESULTCODE, *PWB_MMPDURESULTCODE;
+*/
+
+//===========================================================
+// enum_TxRate --
+// Define the transmission constants based on W89C32 MAC
+// target specification.
+//===========================================================
+typedef enum enum_TxRate
+{
+ TXRATE_1M = 0,
+ TXRATE_2MLONG = 2,
+ TXRATE_2MSHORT = 3,
+ TXRATE_55MLONG = 4,
+ TXRATE_55MSHORT = 5,
+ TXRATE_11MLONG = 6,
+ TXRATE_11MSHORT = 7,
+ TXRATE_AUTO = 255 // PD43 20021108
+} WB_TXRATE, *PWB_TXRATE;
+
+
+#define RATE_BITMAP_1M 1
+#define RATE_BITMAP_2M 2
+#define RATE_BITMAP_5dot5M 5
+#define RATE_BITMAP_6M 6
+#define RATE_BITMAP_9M 9
+#define RATE_BITMAP_11M 11
+#define RATE_BITMAP_12M 12
+#define RATE_BITMAP_18M 18
+#define RATE_BITMAP_22M 22
+#define RATE_BITMAP_24M 24
+#define RATE_BITMAP_33M 17
+#define RATE_BITMAP_36M 19
+#define RATE_BITMAP_48M 25
+#define RATE_BITMAP_54M 28
+
+#define RATE_AUTO 0
+#define RATE_1M 2
+#define RATE_2M 4
+#define RATE_5dot5M 11
+#define RATE_6M 12
+#define RATE_9M 18
+#define RATE_11M 22
+#define RATE_12M 24
+#define RATE_18M 36
+#define RATE_22M 44
+#define RATE_24M 48
+#define RATE_33M 66
+#define RATE_36M 72
+#define RATE_48M 96
+#define RATE_54M 108
+#define RATE_MAX 255
+
+//CAPABILITY
+#define CAPABILITY_ESS_BIT 0x0001
+#define CAPABILITY_IBSS_BIT 0x0002
+#define CAPABILITY_CF_POLL_BIT 0x0004
+#define CAPABILITY_CF_POLL_REQ_BIT 0x0008
+#define CAPABILITY_PRIVACY_BIT 0x0010
+#define CAPABILITY_SHORT_PREAMBLE_BIT 0x0020
+#define CAPABILITY_PBCC_BIT 0x0040
+#define CAPABILITY_CHAN_AGILITY_BIT 0x0080
+#define CAPABILITY_SHORT_SLOT_TIME_BIT 0x0400
+#define CAPABILITY_DSSS_OFDM_BIT 0x2000
+
+
+struct Capability_Information_Element
+{
+ union
+ {
+ u16 __attribute__ ((packed)) wValue;
+ #ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
+ struct _Capability
+ {
+ //-- 11G --
+ u8 Reserved3 : 2;
+ u8 DSSS_OFDM : 1;
+ u8 Reserved2 : 2;
+ u8 Short_Slot_Time : 1;
+ u8 Reserved1 : 2;
+ u8 Channel_Agility : 1;
+ u8 PBCC : 1;
+ u8 ShortPreamble : 1;
+ u8 CF_Privacy : 1;
+ u8 CF_Poll_Request : 1;
+ u8 CF_Pollable : 1;
+ u8 IBSS : 1;
+ u8 ESS : 1;
+ } __attribute__ ((packed)) Capability;
+ #else
+ struct _Capability
+ {
+ u8 ESS : 1;
+ u8 IBSS : 1;
+ u8 CF_Pollable : 1;
+ u8 CF_Poll_Request : 1;
+ u8 CF_Privacy : 1;
+ u8 ShortPreamble : 1;
+ u8 PBCC : 1;
+ u8 Channel_Agility : 1;
+ u8 Reserved1 : 2;
+ //-- 11G --
+ u8 Short_Slot_Time : 1;
+ u8 Reserved2 : 2;
+ u8 DSSS_OFDM : 1;
+ u8 Reserved3 : 2;
+ } __attribute__ ((packed)) Capability;
+ #endif
+ }__attribute__ ((packed)) ;
+}__attribute__ ((packed));
+
+struct FH_Parameter_Set_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 Dwell_Time[2];
+ u8 Hop_Set;
+ u8 Hop_Pattern;
+ u8 Hop_Index;
+};
+
+struct DS_Parameter_Set_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 Current_Channel;
+};
+
+struct Supported_Rates_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 SupportedRates[8];
+}__attribute__ ((packed));
+
+struct SSID_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 SSID[32];
+}__attribute__ ((packed)) ;
+
+struct CF_Parameter_Set_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 CFP_Count;
+ u8 CFP_Period;
+ u8 CFP_MaxDuration[2]; // in Time Units
+ u8 CFP_DurRemaining[2]; // in time units
+};
+
+struct TIM_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 DTIM_Count;
+ u8 DTIM_Period;
+ u8 Bitmap_Control;
+ u8 Partial_Virtual_Bitmap[251];
+};
+
+struct IBSS_Parameter_Set_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 ATIM_Window[2];
+};
+
+struct Challenge_Text_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 Challenge_Text[253];
+};
+
+struct PHY_Parameter_Set_Element
+{
+// int aSlotTime;
+// int aSifsTime;
+ s32 aCCATime;
+ s32 aRxTxTurnaroundTime;
+ s32 aTxPLCPDelay;
+ s32 RxPLCPDelay;
+ s32 aRxTxSwitchTime;
+ s32 aTxRampOntime;
+ s32 aTxRampOffTime;
+ s32 aTxRFDelay;
+ s32 aRxRFDelay;
+ s32 aAirPropagationTime;
+ s32 aMACProcessingDelay;
+ s32 aPreambleLength;
+ s32 aPLCPHeaderLength;
+ s32 aMPDUDurationFactor;
+ s32 aMPDUMaxLength;
+// int aCWmin;
+// int aCWmax;
+};
+
+//-- 11G --
+struct ERP_Information_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ #ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
+ u8 Reserved:5; //20060926 add by anson
+ u8 Barker_Preamble_Mode:1;
+ u8 Use_Protection:1;
+ u8 NonERP_Present:1;
+ #else
+ u8 NonERP_Present:1;
+ u8 Use_Protection:1;
+ u8 Barker_Preamble_Mode:1;
+ u8 Reserved:5;
+ #endif
+};
+
+struct Extended_Supported_Rates_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u8 ExtendedSupportedRates[255];
+}__attribute__ ((packed));
+
+//WPA(802.11i draft 3.0)
+#define VERSION_WPA 1
+#ifdef _WPA2_
+#define VERSION_WPA2 1
+#endif //end def _WPA2_
+#define OUI_WPA 0x00F25000 //WPA2.0 OUI=00:50:F2, the MSB is reserved for suite type
+#ifdef _WPA2_
+#define OUI_WPA2 0x00AC0F00 // for wpa2 change to 0x00ACOF04 by Ws 26/04/04
+#endif //end def _WPA2_
+
+#define OUI_WPA_ADDITIONAL 0x01
+#define WLAN_MIN_RSN_WPA_LENGTH 6 //added by ws 09/10/04
+#ifdef _WPA2_
+#define WLAN_MIN_RSN_WPA2_LENGTH 2 // Fix to 2 09/14/05
+#endif //end def _WPA2_
+
+#define oui_wpa (u32)(OUI_WPA|OUI_WPA_ADDITIONAL)
+
+#define WPA_OUI_BIG ((u32) 0x01F25000)//added by ws 09/23/04
+#define WPA_OUI_LITTLE ((u32) 0x01F25001)//added by ws 09/23/04
+
+#define WPA_WPS_OUI cpu_to_le32(0x04F25000) // 20061108 For WPS. It's little endian. Big endian is 0x0050F204
+
+//-----WPA2-----
+#ifdef _WPA2_
+#define WPA2_OUI_BIG ((u32)0x01AC0F00)
+#define WPA2_OUI_LITTLE ((u32)0x01AC0F01)
+#endif //end def _WPA2_
+
+//Authentication suite
+#define OUI_AUTH_WPA_NONE 0x00 //for WPA_NONE
+#define OUI_AUTH_8021X 0x01
+#define OUI_AUTH_PSK 0x02
+//Cipher suite
+#define OUI_CIPHER_GROUP_KEY 0x00 //added by ws 05/21/04
+#define OUI_CIPHER_WEP_40 0x01
+#define OUI_CIPHER_TKIP 0x02
+#define OUI_CIPHER_CCMP 0x04
+#define OUI_CIPHER_WEP_104 0x05
+
+typedef struct _SUITE_SELECTOR_
+{
+ union
+ {
+ u8 Value[4];
+ struct _SUIT_
+ {
+ u8 OUI[3];
+ u8 Type;
+ }SuitSelector;
+ };
+}SUITE_SELECTOR;
+
+//-- WPA --
+struct RSN_Information_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ UNALIGNED SUITE_SELECTOR OuiWPAAdditional;//WPA version 2.0 additional field, and should be 00:50:F2:01
+ u16 Version;
+ SUITE_SELECTOR GroupKeySuite;
+ u16 PairwiseKeySuiteCount;
+ SUITE_SELECTOR PairwiseKeySuite[1];
+}__attribute__ ((packed));
+struct RSN_Auth_Sub_Information_Element
+{
+ u16 AuthKeyMngtSuiteCount;
+ SUITE_SELECTOR AuthKeyMngtSuite[1];
+}__attribute__ ((packed));
+
+//-- WPA2 --
+struct RSN_Capability_Element
+{
+ union
+ {
+ u16 __attribute__ ((packed)) wValue;
+ #ifdef _BIG_ENDIAN_ //20060927 add by anson's endian
+ struct _RSN_Capability
+ {
+ u16 __attribute__ ((packed)) Reserved2 : 8; // 20051201
+ u16 __attribute__ ((packed)) Reserved1 : 2;
+ u16 __attribute__ ((packed)) GTK_Replay_Counter : 2;
+ u16 __attribute__ ((packed)) PTK_Replay_Counter : 2;
+ u16 __attribute__ ((packed)) No_Pairwise : 1;
+ u16 __attribute__ ((packed)) Pre_Auth : 1;
+ }__attribute__ ((packed)) RSN_Capability;
+ #else
+ struct _RSN_Capability
+ {
+ u16 __attribute__ ((packed)) Pre_Auth : 1;
+ u16 __attribute__ ((packed)) No_Pairwise : 1;
+ u16 __attribute__ ((packed)) PTK_Replay_Counter : 2;
+ u16 __attribute__ ((packed)) GTK_Replay_Counter : 2;
+ u16 __attribute__ ((packed)) Reserved1 : 2;
+ u16 __attribute__ ((packed)) Reserved2 : 8; // 20051201
+ }__attribute__ ((packed)) RSN_Capability;
+ #endif
+
+ }__attribute__ ((packed)) ;
+}__attribute__ ((packed)) ;
+
+#ifdef _WPA2_
+typedef struct _PMKID
+{
+ u8 pValue[16];
+}PMKID;
+
+struct WPA2_RSN_Information_Element
+{
+ u8 Element_ID;
+ u8 Length;
+ u16 Version;
+ SUITE_SELECTOR GroupKeySuite;
+ u16 PairwiseKeySuiteCount;
+ SUITE_SELECTOR PairwiseKeySuite[1];
+
+}__attribute__ ((packed));
+
+struct WPA2_RSN_Auth_Sub_Information_Element
+{
+ u16 AuthKeyMngtSuiteCount;
+ SUITE_SELECTOR AuthKeyMngtSuite[1];
+}__attribute__ ((packed));
+
+
+struct PMKID_Information_Element
+{
+ u16 PMKID_Count;
+ PMKID pmkid [16] ;
+}__attribute__ ((packed));
+
+#endif //enddef _WPA2_
+//============================================================
+// MAC Frame structure (different type) and subfield structure
+//============================================================
+struct MAC_frame_control
+{
+ u8 mac_frame_info; // a combination of the [Protocol Version, Control Type, Control Subtype]
+ #ifdef _BIG_ENDIAN_ //20060927 add by anson's endian
+ u8 order:1;
+ u8 WEP:1;
+ u8 more_data:1;
+ u8 pwr_mgt:1;
+ u8 retry:1;
+ u8 more_frag:1;
+ u8 from_ds:1;
+ u8 to_ds:1;
+ #else
+ u8 to_ds:1;
+ u8 from_ds:1;
+ u8 more_frag:1;
+ u8 retry:1;
+ u8 pwr_mgt:1;
+ u8 more_data:1;
+ u8 WEP:1;
+ u8 order:1;
+ #endif
+} __attribute__ ((packed));
+
+struct Management_Frame {
+ struct MAC_frame_control frame_control; // 2B, ToDS,FromDS,MoreFrag,MoreData,Order=0
+ u16 duration;
+ u8 DA[MAC_ADDR_LENGTH]; // Addr1
+ u8 SA[MAC_ADDR_LENGTH]; // Addr2
+ u8 BSSID[MAC_ADDR_LENGTH]; // Addr3
+ u16 Sequence_Control;
+ // Management Frame Body <= 325 bytes
+ // FCS 4 bytes
+}__attribute__ ((packed));
+
+// SW-MAC don't Tx/Rx Control-Frame, HW-MAC do it.
+struct Control_Frame {
+ struct MAC_frame_control frame_control; // ToDS,FromDS,MoreFrag,Retry,MoreData,WEP,Order=0
+ u16 duration;
+ u8 RA[MAC_ADDR_LENGTH];
+ u8 TA[MAC_ADDR_LENGTH];
+ u16 FCS;
+}__attribute__ ((packed));
+
+struct Data_Frame {
+ struct MAC_frame_control frame_control;
+ u16 duration;
+ u8 Addr1[MAC_ADDR_LENGTH];
+ u8 Addr2[MAC_ADDR_LENGTH];
+ u8 Addr3[MAC_ADDR_LENGTH];
+ u16 Sequence_Control;
+ u8 Addr4[MAC_ADDR_LENGTH]; // only exist when ToDS=FromDS=1
+ // Data Frame Body <= 2312
+ // FCS
+}__attribute__ ((packed));
+
+struct Disassociation_Frame_Body
+{
+ u16 reasonCode;
+}__attribute__ ((packed));
+
+struct Association_Request_Frame_Body
+{
+ u16 capability_information;
+ u16 listenInterval;
+ u8 Current_AP_Address[MAC_ADDR_LENGTH];//for reassociation only
+ // SSID (2+32 bytes)
+ // Supported_Rates (2+8 bytes)
+}__attribute__ ((packed));
+
+struct Association_Response_Frame_Body
+{
+ u16 capability_information;
+ u16 statusCode;
+ u16 Association_ID;
+ struct Supported_Rates_Element supportedRates;
+}__attribute__ ((packed));
+
+/*struct Reassociation_Request_Frame_Body
+{
+ u16 capability_information;
+ u16 listenInterval;
+ u8 Current_AP_Address[MAC_ADDR_LENGTH];
+ // SSID (2+32 bytes)
+ // Supported_Rates (2+8 bytes)
+};*/
+// eliminated by WS 07/22/04 comboined with associateion request frame.
+
+struct Reassociation_Response_Frame_Body
+{
+ u16 capability_information;
+ u16 statusCode;
+ u16 Association_ID;
+ struct Supported_Rates_Element supportedRates;
+}__attribute__ ((packed));
+
+struct Deauthentication_Frame_Body
+{
+ u16 reasonCode;
+}__attribute__ ((packed));
+
+
+struct Probe_Response_Frame_Body
+{
+ u16 Timestamp;
+ u16 Beacon_Interval;
+ u16 Capability_Information;
+ // SSID
+ // Supported_Rates
+ // PHY parameter Set (DS Parameters)
+ // CF parameter Set
+ // IBSS parameter Set
+}__attribute__ ((packed));
+
+struct Authentication_Frame_Body
+{
+ u16 algorithmNumber;
+ u16 sequenceNumber;
+ u16 statusCode;
+ // NB: don't include ChallengeText in this structure
+ // struct Challenge_Text_Element sChallengeTextElement; // wkchen added
+}__attribute__ ((packed));
+
+
+#endif // _MAC_Structure_H_
+
+
diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c
new file mode 100644
index 00000000000..8ce6389c413
--- /dev/null
+++ b/drivers/staging/winbond/mds.c
@@ -0,0 +1,630 @@
+#include "os_common.h"
+
+void
+Mds_reset_descriptor(PADAPTER Adapter)
+{
+ PMDS pMds = &Adapter->Mds;
+
+ pMds->TxPause = 0;
+ pMds->TxThreadCount = 0;
+ pMds->TxFillIndex = 0;
+ pMds->TxDesIndex = 0;
+ pMds->ScanTxPause = 0;
+ memset(pMds->TxOwner, 0, ((MAX_USB_TX_BUFFER_NUMBER + 3) & ~0x03));
+}
+
+unsigned char
+Mds_initial(PADAPTER Adapter)
+{
+ PMDS pMds = &Adapter->Mds;
+
+ pMds->TxPause = FALSE;
+ pMds->TxRTSThreshold = DEFAULT_RTSThreshold;
+ pMds->TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
+
+ vRxTimerInit(Adapter);//for WPA countermeasure
+
+ return hal_get_tx_buffer( &Adapter->sHwData, &pMds->pTxBuffer );
+}
+
+void
+Mds_Destroy(PADAPTER Adapter)
+{
+ vRxTimerStop(Adapter);
+}
+
+void
+Mds_Tx(PADAPTER Adapter)
+{
+ phw_data_t pHwData = &Adapter->sHwData;
+ PMDS pMds = &Adapter->Mds;
+ DESCRIPTOR TxDes;
+ PDESCRIPTOR pTxDes = &TxDes;
+ PUCHAR XmitBufAddress;
+ u16 XmitBufSize, PacketSize, stmp, CurrentSize, FragmentThreshold;
+ u8 FillIndex, TxDesIndex, FragmentCount, FillCount;
+ unsigned char BufferFilled = FALSE, MICAdd = 0;
+
+
+ if (pMds->TxPause)
+ return;
+ if (!hal_driver_init_OK(pHwData))
+ return;
+
+ //Only one thread can be run here
+ if (!OS_ATOMIC_INC( Adapter, &pMds->TxThreadCount) == 1)
+ goto cleanup;
+
+ // Start to fill the data
+ do {
+ FillIndex = pMds->TxFillIndex;
+ if (pMds->TxOwner[FillIndex]) { // Is owned by software 0:Yes 1:No
+#ifdef _PE_TX_DUMP_
+ WBDEBUG(("[Mds_Tx] Tx Owner is H/W.\n"));
+#endif
+ break;
+ }
+
+ XmitBufAddress = pMds->pTxBuffer + (MAX_USB_TX_BUFFER * FillIndex); //Get buffer
+ XmitBufSize = 0;
+ FillCount = 0;
+ do {
+ PacketSize = Adapter->sMlmeFrame.len;
+ if (!PacketSize)
+ break;
+
+ //For Check the buffer resource
+ FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
+ //931130.5.b
+ FragmentCount = PacketSize/FragmentThreshold + 1;
+ stmp = PacketSize + FragmentCount*32 + 8;//931130.5.c 8:MIC
+ if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER) {
+ printk("[Mds_Tx] Excess max tx buffer.\n");
+ break; // buffer is not enough
+ }
+
+
+ //
+ // Start transmitting
+ //
+ BufferFilled = TRUE;
+
+ /* Leaves first u8 intact */
+ memset((PUCHAR)pTxDes + 1, 0, sizeof(DESCRIPTOR) - 1);
+
+ TxDesIndex = pMds->TxDesIndex;//Get the current ID
+ pTxDes->Descriptor_ID = TxDesIndex;
+ pMds->TxDesFrom[ TxDesIndex ] = 2;//Storing the information of source comming from
+ pMds->TxDesIndex++;
+ pMds->TxDesIndex %= MAX_USB_TX_DESCRIPTOR;
+
+ MLME_GetNextPacket( Adapter, pTxDes );
+
+ // Copy header. 8byte USB + 24byte 802.11Hdr. Set TxRate, Preamble type
+ Mds_HeaderCopy( Adapter, pTxDes, XmitBufAddress );
+
+ // For speed up Key setting
+ if (pTxDes->EapFix) {
+#ifdef _PE_TX_DUMP_
+ WBDEBUG(("35: EPA 4th frame detected. Size = %d\n", PacketSize));
+#endif
+ pHwData->IsKeyPreSet = 1;
+ }
+
+ // Copy (fragment) frame body, and set USB, 802.11 hdr flag
+ CurrentSize = Mds_BodyCopy(Adapter, pTxDes, XmitBufAddress);
+
+ // Set RTS/CTS and Normal duration field into buffer
+ Mds_DurationSet(Adapter, pTxDes, XmitBufAddress);
+
+ //
+ // Calculation MIC from buffer which maybe fragment, then fill into temporary address 8 byte
+ // 931130.5.e
+ if (MICAdd)
+ Mds_MicFill( Adapter, pTxDes, XmitBufAddress );
+
+ //Shift to the next address
+ XmitBufSize += CurrentSize;
+ XmitBufAddress += CurrentSize;
+
+#ifdef _IBSS_BEACON_SEQ_STICK_
+ if ((XmitBufAddress[ DOT_11_DA_OFFSET+8 ] & 0xfc) != MAC_SUBTYPE_MNGMNT_PROBE_REQUEST) // +8 for USB hdr
+#endif
+ pMds->TxToggle = TRUE;
+
+ // Get packet to transmit completed, 1:TESTSTA 2:MLME 3: Ndis data
+ MLME_SendComplete(Adapter, 0, TRUE);
+
+ // Software TSC count 20060214
+ pMds->TxTsc++;
+ if (pMds->TxTsc == 0)
+ pMds->TxTsc_2++;
+
+ FillCount++; // 20060928
+ } while (HAL_USB_MODE_BURST(pHwData)); // End of multiple MSDU copy loop. FALSE = single TRUE = multiple sending
+
+ // Move to the next one, if necessary
+ if (BufferFilled) {
+ // size setting
+ pMds->TxBufferSize[ FillIndex ] = XmitBufSize;
+
+ // 20060928 set Tx count
+ pMds->TxCountInBuffer[FillIndex] = FillCount;
+
+ // Set owner flag
+ pMds->TxOwner[FillIndex] = 1;
+
+ pMds->TxFillIndex++;
+ pMds->TxFillIndex %= MAX_USB_TX_BUFFER_NUMBER;
+ BufferFilled = FALSE;
+ } else
+ break;
+
+ if (!PacketSize) // No more pk for transmitting
+ break;
+
+ } while(TRUE);
+
+ //
+ // Start to send by lower module
+ //
+ if (!pHwData->IsKeyPreSet)
+ Wb35Tx_start(pHwData);
+
+ cleanup:
+ OS_ATOMIC_DEC( Adapter, &pMds->TxThreadCount );
+}
+
+void
+Mds_SendComplete(PADAPTER Adapter, PT02_DESCRIPTOR pT02)
+{
+ PMDS pMds = &Adapter->Mds;
+ phw_data_t pHwData = &Adapter->sHwData;
+ u8 PacketId = (u8)pT02->T02_Tx_PktID;
+ unsigned char SendOK = TRUE;
+ u8 RetryCount, TxRate;
+
+ if (pT02->T02_IgnoreResult) // Don't care the result
+ return;
+ if (pT02->T02_IsLastMpdu) {
+ //TODO: DTO -- get the retry count and fragment count
+ // Tx rate
+ TxRate = pMds->TxRate[ PacketId ][ 0 ];
+ RetryCount = (u8)pT02->T02_MPDU_Cnt;
+ if (pT02->value & FLAG_ERROR_TX_MASK) {
+ SendOK = FALSE;
+
+ if (pT02->T02_transmit_abort || pT02->T02_out_of_MaxTxMSDULiftTime) {
+ //retry error
+ pHwData->dto_tx_retry_count += (RetryCount+1);
+ //[for tx debug]
+ if (RetryCount<7)
+ pHwData->tx_retry_count[RetryCount] += RetryCount;
+ else
+ pHwData->tx_retry_count[7] += RetryCount;
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count));
+ #endif
+ MTO_SetTxCount(Adapter, TxRate, RetryCount);
+ }
+ pHwData->dto_tx_frag_count += (RetryCount+1);
+
+ //[for tx debug]
+ if (pT02->T02_transmit_abort_due_to_TBTT)
+ pHwData->tx_TBTT_start_count++;
+ if (pT02->T02_transmit_without_encryption_due_to_wep_on_false)
+ pHwData->tx_WepOn_false_count++;
+ if (pT02->T02_discard_due_to_null_wep_key)
+ pHwData->tx_Null_key_count++;
+ } else {
+ if (pT02->T02_effective_transmission_rate)
+ pHwData->tx_ETR_count++;
+ MTO_SetTxCount(Adapter, TxRate, RetryCount);
+ }
+
+ // Clear send result buffer
+ pMds->TxResult[ PacketId ] = 0;
+ } else
+ pMds->TxResult[ PacketId ] |= ((u16)(pT02->value & 0x0ffff));
+}
+
+void
+Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
+{
+ PMDS pMds = &Adapter->Mds;
+ PUCHAR src_buffer = pDes->buffer_address[0];//931130.5.g
+ PT00_DESCRIPTOR pT00;
+ PT01_DESCRIPTOR pT01;
+ u16 stmp;
+ u8 i, ctmp1, ctmp2, ctmpf;
+ u16 FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
+
+
+ stmp = pDes->buffer_total_size;
+ //
+ // Set USB header 8 byte
+ //
+ pT00 = (PT00_DESCRIPTOR)TargetBuffer;
+ TargetBuffer += 4;
+ pT01 = (PT01_DESCRIPTOR)TargetBuffer;
+ TargetBuffer += 4;
+
+ pT00->value = 0;// Clear
+ pT01->value = 0;// Clear
+
+ pT00->T00_tx_packet_id = pDes->Descriptor_ID;// Set packet ID
+ pT00->T00_header_length = 24;// Set header length
+ pT01->T01_retry_abort_ebable = 1;//921013 931130.5.h
+
+ // Key ID setup
+ pT01->T01_wep_id = 0;
+
+ FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; //Do not fragment
+ // Copy full data, the 1'st buffer contain all the data 931130.5.j
+ memcpy( TargetBuffer, src_buffer, DOT_11_MAC_HEADER_SIZE );// Copy header
+ pDes->buffer_address[0] = src_buffer + DOT_11_MAC_HEADER_SIZE;
+ pDes->buffer_total_size -= DOT_11_MAC_HEADER_SIZE;
+ pDes->buffer_size[0] = pDes->buffer_total_size;
+
+ // Set fragment threshold
+ FragmentThreshold -= (DOT_11_MAC_HEADER_SIZE + 4);
+ pDes->FragmentThreshold = FragmentThreshold;
+
+ // Set more frag bit
+ TargetBuffer[1] |= 0x04;// Set more frag bit
+
+ //
+ // Set tx rate
+ //
+ stmp = *(PUSHORT)(TargetBuffer+30); // 2n alignment address
+
+ //Use basic rate
+ ctmp1 = ctmpf = CURRENT_TX_RATE_FOR_MNG;
+
+ pDes->TxRate = ctmp1;
+ #ifdef _PE_TX_DUMP_
+ WBDEBUG(("Tx rate =%x\n", ctmp1));
+ #endif
+
+ pT01->T01_modulation_type = (ctmp1%3) ? 0 : 1;
+
+ for( i=0; i<2; i++ ) {
+ if( i == 1 )
+ ctmp1 = ctmpf;
+
+ pMds->TxRate[pDes->Descriptor_ID][i] = ctmp1; // backup the ta rate and fall back rate
+
+ if( ctmp1 == 108) ctmp2 = 7;
+ else if( ctmp1 == 96 ) ctmp2 = 6; // Rate convert for USB
+ else if( ctmp1 == 72 ) ctmp2 = 5;
+ else if( ctmp1 == 48 ) ctmp2 = 4;
+ else if( ctmp1 == 36 ) ctmp2 = 3;
+ else if( ctmp1 == 24 ) ctmp2 = 2;
+ else if( ctmp1 == 18 ) ctmp2 = 1;
+ else if( ctmp1 == 12 ) ctmp2 = 0;
+ else if( ctmp1 == 22 ) ctmp2 = 3;
+ else if( ctmp1 == 11 ) ctmp2 = 2;
+ else if( ctmp1 == 4 ) ctmp2 = 1;
+ else ctmp2 = 0; // if( ctmp1 == 2 ) or default
+
+ if( i == 0 )
+ pT01->T01_transmit_rate = ctmp2;
+ else
+ pT01->T01_fall_back_rate = ctmp2;
+ }
+
+ //
+ // Set preamble type
+ //
+ if ((pT01->T01_modulation_type == 0) && (pT01->T01_transmit_rate == 0)) // RATE_1M
+ pDes->PreambleMode = WLAN_PREAMBLE_TYPE_LONG;
+ else
+ pDes->PreambleMode = CURRENT_PREAMBLE_MODE;
+ pT01->T01_plcp_header_length = pDes->PreambleMode; // Set preamble
+
+}
+
+// The function return the 4n size of usb pk
+u16
+Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
+{
+ PT00_DESCRIPTOR pT00;
+ PMDS pMds = &Adapter->Mds;
+ PUCHAR buffer, src_buffer, pctmp;
+ u16 Size = 0;
+ u16 SizeLeft, CopySize, CopyLeft, stmp;
+ u8 buf_index, FragmentCount = 0;
+
+
+ // Copy fragment body
+ buffer = TargetBuffer; // shift 8B usb + 24B 802.11
+ SizeLeft = pDes->buffer_total_size;
+ buf_index = pDes->buffer_start_index;
+
+ pT00 = (PT00_DESCRIPTOR)buffer;
+ while (SizeLeft) {
+ pT00 = (PT00_DESCRIPTOR)buffer;
+ CopySize = SizeLeft;
+ if (SizeLeft > pDes->FragmentThreshold) {
+ CopySize = pDes->FragmentThreshold;
+ pT00->T00_frame_length = 24 + CopySize;//Set USB length
+ } else
+ pT00->T00_frame_length = 24 + SizeLeft;//Set USB length
+
+ SizeLeft -= CopySize;
+
+ // 1 Byte operation
+ pctmp = (PUCHAR)( buffer + 8 + DOT_11_SEQUENCE_OFFSET );
+ *pctmp &= 0xf0;
+ *pctmp |= FragmentCount;//931130.5.m
+ if( !FragmentCount )
+ pT00->T00_first_mpdu = 1;
+
+ buffer += 32; // 8B usb + 24B 802.11 header
+ Size += 32;
+
+ // Copy into buffer
+ stmp = CopySize + 3;
+ stmp &= ~0x03;//4n Alignment
+ Size += stmp;// Current 4n offset of mpdu
+
+ while (CopySize) {
+ // Copy body
+ src_buffer = pDes->buffer_address[buf_index];
+ CopyLeft = CopySize;
+ if (CopySize >= pDes->buffer_size[buf_index]) {
+ CopyLeft = pDes->buffer_size[buf_index];
+
+ // Get the next buffer of descriptor
+ buf_index++;
+ buf_index %= MAX_DESCRIPTOR_BUFFER_INDEX;
+ } else {
+ PUCHAR pctmp = pDes->buffer_address[buf_index];
+ pctmp += CopySize;
+ pDes->buffer_address[buf_index] = pctmp;
+ pDes->buffer_size[buf_index] -= CopySize;
+ }
+
+ memcpy(buffer, src_buffer, CopyLeft);
+ buffer += CopyLeft;
+ CopySize -= CopyLeft;
+ }
+
+ // 931130.5.n
+ if (pMds->MicAdd) {
+ if (!SizeLeft) {
+ pMds->MicWriteAddress[ pMds->MicWriteIndex ] = buffer - pMds->MicAdd;
+ pMds->MicWriteSize[ pMds->MicWriteIndex ] = pMds->MicAdd;
+ pMds->MicAdd = 0;
+ }
+ else if( SizeLeft < 8 ) //931130.5.p
+ {
+ pMds->MicAdd = SizeLeft;
+ pMds->MicWriteAddress[ pMds->MicWriteIndex ] = buffer - ( 8 - SizeLeft );
+ pMds->MicWriteSize[ pMds->MicWriteIndex ] = 8 - SizeLeft;
+ pMds->MicWriteIndex++;
+ }
+ }
+
+ // Does it need to generate the new header for next mpdu?
+ if (SizeLeft) {
+ buffer = TargetBuffer + Size; // Get the next 4n start address
+ memcpy( buffer, TargetBuffer, 32 );//Copy 8B USB +24B 802.11
+ pT00 = (PT00_DESCRIPTOR)buffer;
+ pT00->T00_first_mpdu = 0;
+ }
+
+ FragmentCount++;
+ }
+
+ pT00->T00_last_mpdu = 1;
+ pT00->T00_IsLastMpdu = 1;
+ buffer = (PUCHAR)pT00 + 8; // +8 for USB hdr
+ buffer[1] &= ~0x04; // Clear more frag bit of 802.11 frame control
+ pDes->FragmentCount = FragmentCount; // Update the correct fragment number
+ return Size;
+}
+
+
+void
+Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
+{
+ PT00_DESCRIPTOR pT00;
+ PT01_DESCRIPTOR pT01;
+ u16 Duration, NextBodyLen, OffsetSize;
+ u8 Rate, i;
+ unsigned char CTS_on = FALSE, RTS_on = FALSE;
+ PT00_DESCRIPTOR pNextT00;
+ u16 BodyLen;
+ unsigned char boGroupAddr = FALSE;
+
+
+ OffsetSize = pDes->FragmentThreshold + 32 + 3;
+ OffsetSize &= ~0x03;
+ Rate = pDes->TxRate >> 1;
+ if (!Rate)
+ Rate = 1;
+
+ pT00 = (PT00_DESCRIPTOR)buffer;
+ pT01 = (PT01_DESCRIPTOR)(buffer+4);
+ pNextT00 = (PT00_DESCRIPTOR)(buffer+OffsetSize);
+
+ if( buffer[ DOT_11_DA_OFFSET+8 ] & 0x1 ) // +8 for USB hdr
+ boGroupAddr = TRUE;
+
+ //========================================
+ // Set RTS/CTS mechanism
+ //========================================
+ if (!boGroupAddr)
+ {
+ //NOTE : If the protection mode is enabled and the MSDU will be fragmented,
+ // the tx rates of MPDUs will all be DSSS rates. So it will not use
+ // CTS-to-self in this case. CTS-To-self will only be used when without
+ // fragmentation. -- 20050112
+ BodyLen = (u16)pT00->T00_frame_length; //include 802.11 header
+ BodyLen += 4; //CRC
+
+ if( BodyLen >= CURRENT_RTS_THRESHOLD )
+ RTS_on = TRUE; // Using RTS
+ else
+ {
+ if( pT01->T01_modulation_type ) // Is using OFDM
+ {
+ if( CURRENT_PROTECT_MECHANISM ) // Is using protect
+ CTS_on = TRUE; // Using CTS
+ }
+ }
+ }
+
+ if( RTS_on || CTS_on )
+ {
+ if( pT01->T01_modulation_type) // Is using OFDM
+ {
+ //CTS duration
+ // 2 SIFS + DATA transmit time + 1 ACK
+ // ACK Rate : 24 Mega bps
+ // ACK frame length = 14 bytes
+ Duration = 2*DEFAULT_SIFSTIME +
+ 2*PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
+ ((BodyLen*8 + 22 + Rate*4 - 1)/(Rate*4))*Tsym +
+ ((112 + 22 + 95)/96)*Tsym;
+ }
+ else //DSSS
+ {
+ //CTS duration
+ // 2 SIFS + DATA transmit time + 1 ACK
+ // Rate : ?? Mega bps
+ // ACK frame length = 14 bytes
+ if( pT01->T01_plcp_header_length ) //long preamble
+ Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
+ else
+ Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
+
+ Duration += ( ((BodyLen + 14)*8 + Rate-1) / Rate +
+ DEFAULT_SIFSTIME*2 );
+ }
+
+ if( RTS_on )
+ {
+ if( pT01->T01_modulation_type ) // Is using OFDM
+ {
+ //CTS + 1 SIFS + CTS duration
+ //CTS Rate : 24 Mega bps
+ //CTS frame length = 14 bytes
+ Duration += (DEFAULT_SIFSTIME +
+ PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
+ ((112 + 22 + 95)/96)*Tsym);
+ }
+ else
+ {
+ //CTS + 1 SIFS + CTS duration
+ //CTS Rate : ?? Mega bps
+ //CTS frame length = 14 bytes
+ if( pT01->T01_plcp_header_length ) //long preamble
+ Duration += LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
+ else
+ Duration += SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
+
+ Duration += ( ((112 + Rate-1) / Rate) + DEFAULT_SIFSTIME );
+ }
+ }
+
+ // Set the value into USB descriptor
+ pT01->T01_add_rts = RTS_on ? 1 : 0;
+ pT01->T01_add_cts = CTS_on ? 1 : 0;
+ pT01->T01_rts_cts_duration = Duration;
+ }
+
+ //=====================================
+ // Fill the more fragment descriptor
+ //=====================================
+ if( boGroupAddr )
+ Duration = 0;
+ else
+ {
+ for( i=pDes->FragmentCount-1; i>0; i-- )
+ {
+ NextBodyLen = (u16)pNextT00->T00_frame_length;
+ NextBodyLen += 4; //CRC
+
+ if( pT01->T01_modulation_type )
+ {
+ //OFDM
+ // data transmit time + 3 SIFS + 2 ACK
+ // Rate : ??Mega bps
+ // ACK frame length = 14 bytes, tx rate = 24M
+ Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION * 3;
+ Duration += (((NextBodyLen*8 + 22 + Rate*4 - 1)/(Rate*4)) * Tsym +
+ (((2*14)*8 + 22 + 95)/96)*Tsym +
+ DEFAULT_SIFSTIME*3);
+ }
+ else
+ {
+ //DSSS
+ // data transmit time + 2 ACK + 3 SIFS
+ // Rate : ??Mega bps
+ // ACK frame length = 14 bytes
+ //TODO :
+ if( pT01->T01_plcp_header_length ) //long preamble
+ Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
+ else
+ Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
+
+ Duration += ( ((NextBodyLen + (2*14))*8 + Rate-1) / Rate +
+ DEFAULT_SIFSTIME*3 );
+ }
+
+ ((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
+
+ //----20061009 add by anson's endian
+ pNextT00->value = cpu_to_le32(pNextT00->value);
+ pT01->value = cpu_to_le32( pT01->value );
+ //----end 20061009 add by anson's endian
+
+ buffer += OffsetSize;
+ pT01 = (PT01_DESCRIPTOR)(buffer+4);
+ if (i != 1) //The last fragment will not have the next fragment
+ pNextT00 = (PT00_DESCRIPTOR)(buffer+OffsetSize);
+ }
+
+ //=====================================
+ // Fill the last fragment descriptor
+ //=====================================
+ if( pT01->T01_modulation_type )
+ {
+ //OFDM
+ // 1 SIFS + 1 ACK
+ // Rate : 24 Mega bps
+ // ACK frame length = 14 bytes
+ Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION;
+ //The Tx rate of ACK use 24M
+ Duration += (((112 + 22 + 95)/96)*Tsym + DEFAULT_SIFSTIME );
+ }
+ else
+ {
+ // DSSS
+ // 1 ACK + 1 SIFS
+ // Rate : ?? Mega bps
+ // ACK frame length = 14 bytes(112 bits)
+ if( pT01->T01_plcp_header_length ) //long preamble
+ Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
+ else
+ Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
+
+ Duration += ( (112 + Rate-1)/Rate + DEFAULT_SIFSTIME );
+ }
+ }
+
+ ((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
+ pT00->value = cpu_to_le32(pT00->value);
+ pT01->value = cpu_to_le32(pT01->value);
+ //--end 20061009 add
+
+}
+
+void MDS_EthernetPacketReceive( PADAPTER Adapter, PRXLAYER1 pRxLayer1 )
+{
+ OS_RECEIVE_PACKET_INDICATE( Adapter, pRxLayer1 );
+}
+
+
diff --git a/drivers/staging/winbond/mds_f.h b/drivers/staging/winbond/mds_f.h
new file mode 100644
index 00000000000..651188be106
--- /dev/null
+++ b/drivers/staging/winbond/mds_f.h
@@ -0,0 +1,33 @@
+unsigned char Mds_initial( PADAPTER Adapter );
+void Mds_Destroy( PADAPTER Adapter );
+void Mds_Tx( PADAPTER Adapter );
+void Mds_HeaderCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
+u16 Mds_BodyCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
+void Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
+void Mds_SendComplete( PADAPTER Adapter, PT02_DESCRIPTOR pT02 );
+void Mds_MpduProcess( PADAPTER Adapter, PDESCRIPTOR pRxDes );
+void Mds_reset_descriptor( PADAPTER Adapter );
+extern void DataDmp(u8 *pdata, u32 len, u32 offset);
+
+
+void vRxTimerInit(PWB32_ADAPTER Adapter);
+void vRxTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
+void RxTimerHandler_1a( PADAPTER Adapter);
+void vRxTimerStop(PWB32_ADAPTER Adapter);
+void RxTimerHandler( void* SystemSpecific1,
+ PWB32_ADAPTER Adapter,
+ void* SystemSpecific2,
+ void* SystemSpecific3);
+
+
+// For Asynchronous indicating. The routine collocates with USB.
+void Mds_MsduProcess( PWB32_ADAPTER Adapter, PRXLAYER1 pRxLayer1, u8 SlotIndex);
+
+// For data frame sending 20060802
+u16 MDS_GetPacketSize( PADAPTER Adapter );
+void MDS_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
+void MDS_GetNextPacketComplete( PADAPTER Adapter, PDESCRIPTOR pDes );
+void MDS_SendResult( PADAPTER Adapter, u8 PacketId, unsigned char SendOK );
+void MDS_EthernetPacketReceive( PADAPTER Adapter, PRXLAYER1 pRxLayer1 );
+
+
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
new file mode 100644
index 00000000000..4738279d5f3
--- /dev/null
+++ b/drivers/staging/winbond/mds_s.h
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+#define MAX_USB_TX_DESCRIPTOR 15 // IS89C35 ability
+#define MAX_USB_TX_BUFFER_NUMBER 4 // Virtual pre-buffer number of MAX_USB_TX_BUFFER
+#define MAX_USB_TX_BUFFER 4096 // IS89C35 ability 4n alignment is required for hardware
+
+#define MDS_EVENT_INDICATE( _A, _B, _F ) OS_EVENT_INDICATE( _A, _B, _F )
+#define AUTH_REQUEST_PAIRWISE_ERROR 0 // _F flag setting
+#define AUTH_REQUEST_GROUP_ERROR 1 // _F flag setting
+
+// For variable setting
+#define CURRENT_BSS_TYPE psBSS(psLOCAL->wConnectedSTAindex)->bBssType
+#define CURRENT_WEP_MODE psSME->_dot11PrivacyInvoked
+#define CURRENT_BSSID psBSS(psLOCAL->wConnectedSTAindex)->abBssID
+#define CURRENT_DESIRED_WPA_ENABLE ((psSME->bDesiredAuthMode==WPA_AUTH)||(psSME->bDesiredAuthMode==WPAPSK_AUTH))
+#ifdef _WPA2_
+#define CURRENT_DESIRED_WPA2_ENABLE ((psSME->bDesiredAuthMode==WPA2_AUTH)||(psSME->bDesiredAuthMode==WPA2PSK_AUTH))
+#endif //end def _WPA2_
+#define CURRENT_PAIRWISE_KEY_OK psSME->pairwise_key_ok
+//[20040712 WS]
+#define CURRENT_GROUP_KEY_OK psSME->group_key_ok
+#define CURRENT_PAIRWISE_KEY psSME->tx_mic_key
+#define CURRENT_GROUP_KEY psSME->group_tx_mic_key
+#define CURRENT_ENCRYPT_STATUS psSME->encrypt_status
+#define CURRENT_WEP_ID Adapter->sSmePara._dot11WEPDefaultKeyID
+#define CURRENT_CONTROL_PORT_BLOCK ( psSME->wpa_ok!=1 || (Adapter->Mds.boCounterMeasureBlock==1 && (CURRENT_ENCRYPT_STATUS==ENCRYPT_TKIP)) )
+#define CURRENT_FRAGMENT_THRESHOLD (Adapter->Mds.TxFragmentThreshold & ~0x1)
+#define CURRENT_PREAMBLE_MODE psLOCAL->boShortPreamble?WLAN_PREAMBLE_TYPE_SHORT:WLAN_PREAMBLE_TYPE_LONG
+#define CURRENT_LINK_ON OS_LINK_STATUS
+#define CURRENT_TX_RATE Adapter->sLocalPara.CurrentTxRate
+#define CURRENT_FALL_BACK_TX_RATE Adapter->sLocalPara.CurrentTxFallbackRate
+#define CURRENT_TX_RATE_FOR_MNG Adapter->sLocalPara.CurrentTxRateForMng
+#define CURRENT_PROTECT_MECHANISM psLOCAL->boProtectMechanism
+#define CURRENT_RTS_THRESHOLD Adapter->Mds.TxRTSThreshold
+
+#define MIB_GS_XMIT_OK_INC Adapter->sLocalPara.GS_XMIT_OK++
+#define MIB_GS_RCV_OK_INC Adapter->sLocalPara.GS_RCV_OK++
+#define MIB_GS_XMIT_ERROR_INC Adapter->sLocalPara.GS_XMIT_ERROR
+
+//---------- TX -----------------------------------
+#define ETHERNET_TX_DESCRIPTORS MAX_USB_TX_BUFFER_NUMBER
+
+//---------- RX ------------------------------------
+#define ETHERNET_RX_DESCRIPTORS 8 //It's not necessary to allocate more than 2 in sync indicate
+
+//================================================================
+// Configration default value
+//================================================================
+#define DEFAULT_MULTICASTLISTMAX 32 // standard
+#define DEFAULT_TX_BURSTLENGTH 3 // 32 Longwords
+#define DEFAULT_RX_BURSTLENGTH 3 // 32 Longwords
+#define DEFAULT_TX_THRESHOLD 0 // Full Packet
+#define DEFAULT_RX_THRESHOLD 0 // Full Packet
+#define DEFAULT_MAXTXRATE 6 // 11 Mbps (Long)
+#define DEFAULT_CHANNEL 3 // Chennel 3
+#define DEFAULT_RTSThreshold 2347 // Disable RTS
+//#define DEFAULT_PME 1 // Enable
+#define DEFAULT_PME 0 // Disable
+#define DEFAULT_SIFSTIME 10
+#define DEFAULT_ACKTIME_1ML 304 // 148+44+112 911220 by LCC
+#define DEFAULT_ACKTIME_2ML 248 // 148+44+56 911220 by LCC
+#define DEFAULT_FRAGMENT_THRESHOLD 2346 // No fragment
+#define DEFAULT_PREAMBLE_LENGTH 72
+#define DEFAULT_PLCPHEADERTIME_LENGTH 24
+
+/*------------------------------------------------------------------------
+ 0.96 sec since time unit of the R03 for the current, W89C32 is about 60ns
+ instead of 960 ns. This shall be fixed in the future W89C32
+ -------------------------------------------------------------------------*/
+#define DEFAULT_MAX_RECEIVE_TIME 16440000
+
+#define RX_BUF_SIZE 2352 // 600 // For 301 must be multiple of 8
+#define MAX_RX_DESCRIPTORS 18 // Rx Layer 2
+#define MAX_BUFFER_QUEUE 8 // The value is always equal 8 due to NDIS_PACKET's MiniportReserved field size
+
+
+// For brand-new rx system
+#define MDS_ID_IGNORE ETHERNET_RX_DESCRIPTORS
+
+// For Tx Packet status classify
+#define PACKET_FREE_TO_USE 0
+#define PACKET_COME_FROM_NDIS 0x08
+#define PACKET_COME_FROM_MLME 0x80
+#define PACKET_SEND_COMPLETE 0xff
+
+typedef struct _MDS
+{
+ // For Tx usage
+ u8 TxOwner[ ((MAX_USB_TX_BUFFER_NUMBER + 3) & ~0x03) ];
+ PUCHAR pTxBuffer;
+ u16 TxBufferSize[ ((MAX_USB_TX_BUFFER_NUMBER + 1) & ~0x01) ];
+ u8 TxDesFrom[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ];//931130.4.u // 1: MLME 2: NDIS control 3: NDIS data
+ u8 TxCountInBuffer[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ]; // 20060928
+
+ u8 TxFillIndex;//the next index of TxBuffer can be used
+ u8 TxDesIndex;//The next index of TxDes can be used
+ u8 ScanTxPause; //data Tx pause because the scanning is progressing, but probe request Tx won't.
+ u8 TxPause;//For pause the Mds_Tx modult
+
+ OS_ATOMIC TxThreadCount;//For thread counting 931130.4.v
+//950301 delete due to HW
+// OS_ATOMIC TxConcurrentCount;//931130.4.w
+
+ u16 TxResult[ ((MAX_USB_TX_DESCRIPTOR + 1) & ~0x01) ];//Collect the sending result of Mpdu
+
+ u8 MicRedundant[8]; // For tmp use
+ PUCHAR MicWriteAddress[2]; //The start address to fill the Mic, use 2 point due to Mic maybe fragment
+
+ u16 MicWriteSize[2]; //931130.4.x
+
+ u16 MicAdd; // If want to add the Mic, this variable equal to 8
+ u16 MicWriteIndex;//The number of MicWriteAddress 931130.4.y
+
+ u8 TxRate[ ((MAX_USB_TX_DESCRIPTOR+1)&~0x01) ][2]; // [0] current tx rate, [1] fall back rate
+ u8 TxInfo[ ((MAX_USB_TX_DESCRIPTOR+1)&~0x01) ]; //Store information for callback function
+
+ //WKCHEN added for scanning mechanism
+ u8 TxToggle; //It is TRUE if there are tx activities in some time interval
+ u8 Reserved_[3];
+
+ //---------- for Tx Parameter
+ u16 TxFragmentThreshold; // For frame body only
+ u16 TxRTSThreshold;
+
+ u32 MaxReceiveTime;//911220.3 Add
+
+ // depend on OS,
+ u32 MulticastListNo;
+ u32 PacketFilter; // Setting by NDIS, the current packet filter in use.
+ u8 MulticastAddressesArray[DEFAULT_MULTICASTLISTMAX][MAC_ADDR_LENGTH];
+
+ //COUNTERMEASURE
+ u8 bMICfailCount;
+ u8 boCounterMeasureBlock;
+ u8 reserved_4[2];
+
+ //NDIS_MINIPORT_TIMER nTimer;
+ OS_TIMER nTimer;
+
+ u32 TxTsc; // 20060214
+ u32 TxTsc_2; // 20060214
+
+} MDS, *PMDS;
+
+
+typedef struct _RxBuffer
+{
+ PUCHAR pBufferAddress; // Pointer the received data buffer.
+ u16 BufferSize;
+ u8 RESERVED;
+ u8 BufferIndex;// Only 1 byte
+} RXBUFFER, *PRXBUFFER;
+
+//
+// Reveive Layer 1 Format.
+//----------------------------
+typedef struct _RXLAYER1
+{
+ u16 SequenceNumber; // The sequence number of the last received packet.
+ u16 BufferTotalSize;
+
+ u32 InUsed;
+ u32 DecryptionMethod; // The desired defragment number of the next incoming packet.
+
+ u8 DeFragmentNumber;
+ u8 FrameType;
+ u8 TypeEncapsulated;
+ u8 BufferNumber;
+
+ u32 FirstFrameArrivedTime;
+
+ RXBUFFER BufferQueue[ MAX_BUFFER_QUEUE ];
+
+ u8 LastFrameType; // 20061004 for fix intel 3945 's bug
+ u8 RESERVED[3]; //@@ anson
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // For brand-new Rx system
+ u8 ReservedBuffer[ 2400 ];//If Buffer ID is reserved one, it must copy the data into this area
+ PUCHAR ReservedBufferPoint;// Point to the next availabe address of reserved buffer
+
+}RXLAYER1, * PRXLAYER1;
+
+
diff --git a/drivers/staging/winbond/mlme_mib.h b/drivers/staging/winbond/mlme_mib.h
new file mode 100644
index 00000000000..89759739cba
--- /dev/null
+++ b/drivers/staging/winbond/mlme_mib.h
@@ -0,0 +1,84 @@
+//============================================================================
+// MLMEMIB.H -
+//
+// Description:
+// Get and Set some of MLME MIB attributes.
+//
+// Revision history:
+// --------------------------------------------------------------------------
+// 20030117 PD43 Austin Liu
+// Initial release
+//
+// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
+//============================================================================
+
+#ifndef _MLME_MIB_H
+#define _MLME_MIB_H
+
+//============================================================================
+// MLMESetExcludeUnencrypted --
+//
+// Description:
+// Set the dot11ExcludeUnencrypted value.
+//
+// Arguments:
+// Adapter - The pointer to the miniport adapter context.
+// ExUnencrypted - unsigned char type. The value to be set.
+//
+// Return values:
+// None.
+//============================================================================
+#define MLMESetExcludeUnencrypted(Adapter, ExUnencrypted) \
+{ \
+ (Adapter)->sLocalPara.ExcludeUnencrypted = ExUnencrypted; \
+}
+
+//============================================================================
+// MLMEGetExcludeUnencrypted --
+//
+// Description:
+// Get the dot11ExcludeUnencrypted value.
+//
+// Arguments:
+// Adapter - The pointer to the miniport adapter context.
+//
+// Return values:
+// unsigned char type. The current dot11ExcludeUnencrypted value.
+//============================================================================
+#define MLMEGetExcludeUnencrypted(Adapter) ((unsigned char) (Adapter)->sLocalPara.ExcludeUnencrypted)
+
+//============================================================================
+// MLMESetMaxReceiveLifeTime --
+//
+// Description:
+// Set the dot11MaxReceiveLifeTime value.
+//
+// Arguments:
+// Adapter - The pointer to the miniport adapter context.
+// ReceiveLifeTime- u32 type. The value to be set.
+//
+// Return values:
+// None.
+//============================================================================
+#define MLMESetMaxReceiveLifeTime(Adapter, ReceiveLifeTime) \
+{ \
+ (Adapter)->Mds.MaxReceiveTime = ReceiveLifeTime; \
+}
+
+//============================================================================
+// MLMESetMaxReceiveLifeTime --
+//
+// Description:
+// Get the dot11MaxReceiveLifeTime value.
+//
+// Arguments:
+// Adapter - The pointer to the miniport adapter context.
+//
+// Return values:
+// u32 type. The current dot11MaxReceiveLifeTime value.
+//============================================================================
+#define MLMEGetMaxReceiveLifeTime(Adapter) ((u32) (Adapter)->Mds.MaxReceiveTime)
+
+#endif
+
+
diff --git a/drivers/staging/winbond/mlme_s.h b/drivers/staging/winbond/mlme_s.h
new file mode 100644
index 00000000000..58094f61c03
--- /dev/null
+++ b/drivers/staging/winbond/mlme_s.h
@@ -0,0 +1,195 @@
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Mlme.h
+// Define the related definitions of MLME module
+// history -- 01/14/03' created
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#define AUTH_REJECT_REASON_CHALLENGE_FAIL 1
+
+//====== the state of MLME module
+#define INACTIVE 0x0
+#define IDLE_SCAN 0x1
+
+//====== the state of MLME/ESS module
+#define STATE_1 0x2
+#define AUTH_REQ 0x3
+#define AUTH_WEP 0x4
+#define STATE_2 0x5
+#define ASSOC_REQ 0x6
+#define STATE_3 0x7
+
+//====== the state of MLME/IBSS module
+#define IBSS_JOIN_SYNC 0x8
+#define IBSS_AUTH_REQ 0x9
+#define IBSS_AUTH_CHANLGE 0xa
+#define IBSS_AUTH_WEP 0xb
+#define IBSS_AUTH_IND 0xc
+#define IBSS_STATE_2 0xd
+
+
+
+//=========================================
+//depend on D5C(MAC timing control 03 register): MaxTxMSDULifeTime default 0x80000us
+#define AUTH_FAIL_TIMEOUT 550
+#define ASSOC_FAIL_TIMEOUT 550
+#define REASSOC_FAIL_TIMEOUT 550
+
+
+
+//
+// MLME task global CONSTANTS, STRUCTURE, variables
+//
+
+
+/////////////////////////////////////////////////////////////
+// enum_ResultCode --
+// Result code returned from MLME to SME.
+//
+/////////////////////////////////////////////////////////////
+// PD43 20030829 Modifiled
+//#define SUCCESS 0
+#define MLME_SUCCESS 0 //follow spec.
+#define INVALID_PARAMETERS 1 //Not following spec.
+#define NOT_SUPPPORTED 2
+#define TIMEOUT 3
+#define TOO_MANY_SIMULTANEOUS_REQUESTS 4
+#define REFUSED 5
+#define BSS_ALREADY_STARTED_OR_JOINED 6
+#define TRANSMIT_FRAME_FAIL 7
+#define NO_BSS_FOUND 8
+#define RETRY 9
+#define GIVE_UP 10
+
+
+#define OPEN_AUTH 0
+#define SHARE_AUTH 1
+#define ANY_AUTH 2
+#define WPA_AUTH 3 //for WPA
+#define WPAPSK_AUTH 4
+#define WPANONE_AUTH 5
+///////////////////////////////////////////// added by ws 04/19/04
+#ifdef _WPA2_
+#define WPA2_AUTH 6//for WPA2
+#define WPA2PSK_AUTH 7
+#endif //end def _WPA2_
+
+//////////////////////////////////////////////////////////////////
+//define the msg type of MLME module
+//////////////////////////////////////////////////////////////////
+//--------------------------------------------------------
+//from SME
+
+#define MLMEMSG_AUTH_REQ 0x0b
+#define MLMEMSG_DEAUTH_REQ 0x0c
+#define MLMEMSG_ASSOC_REQ 0x0d
+#define MLMEMSG_REASSOC_REQ 0x0e
+#define MLMEMSG_DISASSOC_REQ 0x0f
+#define MLMEMSG_START_IBSS_REQ 0x10
+#define MLMEMSG_IBSS_NET_CFM 0x11
+
+//from RX :
+#define MLMEMSG_RCV_MLMEFRAME 0x20
+#define MLMEMSG_RCV_ASSOCRSP 0x22
+#define MLMEMSG_RCV_REASSOCRSP 0x24
+#define MLMEMSG_RCV_DISASSOC 0x2b
+#define MLMEMSG_RCV_AUTH 0x2c
+#define MLMEMSG_RCV_DEAUTH 0x2d
+
+
+//from TX callback
+#define MLMEMSG_TX_CALLBACK 0x40
+#define MLMEMSG_ASSOCREQ_CALLBACK 0x41
+#define MLMEMSG_REASSOCREQ_CALLBACK 0x43
+#define MLMEMSG_DISASSOC_CALLBACK 0x4a
+#define MLMEMSG_AUTH_CALLBACK 0x4c
+#define MLMEMSG_DEAUTH_CALLBACK 0x4d
+
+//#define MLMEMSG_JOIN_FAIL 4
+//#define MLMEMSG_AUTHEN_FAIL 18
+#define MLMEMSG_TIMEOUT 0x50
+
+///////////////////////////////////////////////////////////////////////////
+//Global data structures
+#define MAX_NUM_TX_MMPDU 2
+#define MAX_MMPDU_SIZE 1512
+#define MAX_NUM_RX_MMPDU 6
+
+
+///////////////////////////////////////////////////////////////////////////
+//MACRO
+#define boMLME_InactiveState(_AA_) (_AA_->wState==INACTIVE)
+#define boMLME_IdleScanState(_BB_) (_BB_->wState==IDLE_SCAN)
+#define boMLME_FoundSTAinfo(_CC_) (_CC_->wState>=IDLE_SCAN)
+
+typedef struct _MLME_FRAME
+{
+ //NDIS_PACKET MLME_Packet;
+ PCHAR pMMPDU;
+ u16 len;
+ u8 DataType;
+ u8 IsInUsed;
+
+ OS_SPIN_LOCK MLMESpinLock;
+
+ u8 TxMMPDU[MAX_NUM_TX_MMPDU][MAX_MMPDU_SIZE];
+ u8 TxMMPDUInUse[ (MAX_NUM_TX_MMPDU+3) & ~0x03 ];
+
+ u16 wNumTxMMPDU;
+ u16 wNumTxMMPDUDiscarded;
+
+ u8 RxMMPDU[MAX_NUM_RX_MMPDU][MAX_MMPDU_SIZE];
+ u8 SaveRxBufSlotInUse[ (MAX_NUM_RX_MMPDU+3) & ~0x03 ];
+
+ u16 wNumRxMMPDU;
+ u16 wNumRxMMPDUDiscarded;
+
+ u16 wNumRxMMPDUInMLME; // Number of the Rx MMPDU
+ u16 reserved_1; // in MLME.
+ // excluding the discarded
+} MLME_FRAME, *psMLME_FRAME;
+
+typedef struct _AUTHREQ {
+
+ u8 peerMACaddr[MAC_ADDR_LENGTH];
+ u16 wAuthAlgorithm;
+
+} MLME_AUTHREQ_PARA, *psMLME_AUTHREQ_PARA;
+
+struct _Reason_Code {
+
+ u8 peerMACaddr[MAC_ADDR_LENGTH];
+ u16 wReasonCode;
+};
+typedef struct _Reason_Code MLME_DEAUTHREQ_PARA, *psMLME_DEAUTHREQ_PARA;
+typedef struct _Reason_Code MLME_DISASSOCREQ_PARA, *psMLME_DISASSOCREQ_PARA;
+
+typedef struct _ASSOCREQ {
+ u8 PeerSTAAddr[MAC_ADDR_LENGTH];
+ u16 CapabilityInfo;
+ u16 ListenInterval;
+
+}__attribute__ ((packed)) MLME_ASSOCREQ_PARA, *psMLME_ASSOCREQ_PARA;
+
+typedef struct _REASSOCREQ {
+ u8 NewAPAddr[MAC_ADDR_LENGTH];
+ u16 CapabilityInfo;
+ u16 ListenInterval;
+
+}__attribute__ ((packed)) MLME_REASSOCREQ_PARA, *psMLME_REASSOCREQ_PARA;
+
+typedef struct _MLMECALLBACK {
+
+ u8 *psFramePtr;
+ u8 bResult;
+
+} MLME_TXCALLBACK, *psMLME_TXCALLBACK;
+
+typedef struct _RXDATA
+{
+ s32 FrameLength;
+ u8 __attribute__ ((packed)) *pbFramePtr;
+
+}__attribute__ ((packed)) RXDATA, *psRXDATA;
+
+
diff --git a/drivers/staging/winbond/mlmetxrx.c b/drivers/staging/winbond/mlmetxrx.c
new file mode 100644
index 00000000000..46b091e9679
--- /dev/null
+++ b/drivers/staging/winbond/mlmetxrx.c
@@ -0,0 +1,150 @@
+//============================================================================
+// Module Name:
+// MLMETxRx.C
+//
+// Description:
+// The interface between MDS (MAC Data Service) and MLME.
+//
+// Revision History:
+// --------------------------------------------------------------------------
+// 200209 UN20 Jennifer Xu
+// Initial Release
+// 20021108 PD43 Austin Liu
+// 20030117 PD43 Austin Liu
+// Deleted MLMEReturnPacket and MLMEProcThread()
+//
+// Copyright (c) 1996-2002 Winbond Electronics Corp. All Rights Reserved.
+//============================================================================
+#include "os_common.h"
+
+void MLMEResetTxRx(PWB32_ADAPTER Adapter)
+{
+ s32 i;
+
+ // Reset the interface between MDS and MLME
+ for (i = 0; i < MAX_NUM_TX_MMPDU; i++)
+ Adapter->sMlmeFrame.TxMMPDUInUse[i] = FALSE;
+ for (i = 0; i < MAX_NUM_RX_MMPDU; i++)
+ Adapter->sMlmeFrame.SaveRxBufSlotInUse[i] = FALSE;
+
+ Adapter->sMlmeFrame.wNumRxMMPDUInMLME = 0;
+ Adapter->sMlmeFrame.wNumRxMMPDUDiscarded = 0;
+ Adapter->sMlmeFrame.wNumRxMMPDU = 0;
+ Adapter->sMlmeFrame.wNumTxMMPDUDiscarded = 0;
+ Adapter->sMlmeFrame.wNumTxMMPDU = 0;
+ Adapter->sLocalPara.boCCAbusy = FALSE;
+ Adapter->sLocalPara.iPowerSaveMode = PWR_ACTIVE; // Power active
+}
+
+//=============================================================================
+// Function:
+// MLMEGetMMPDUBuffer()
+//
+// Description:
+// Return the pointer to an available data buffer with
+// the size MAX_MMPDU_SIZE for a MMPDU.
+//
+// Arguments:
+// Adapter - pointer to the miniport adapter context.
+//
+// Return value:
+// NULL : No available data buffer available
+// Otherwise: Pointer to the data buffer
+//=============================================================================
+
+/* FIXME: Should this just be replaced with kmalloc() and kfree()? */
+u8 *MLMEGetMMPDUBuffer(PWB32_ADAPTER Adapter)
+{
+ s32 i;
+ u8 *returnVal;
+
+ for (i = 0; i< MAX_NUM_TX_MMPDU; i++) {
+ if (Adapter->sMlmeFrame.TxMMPDUInUse[i] == FALSE)
+ break;
+ }
+ if (i >= MAX_NUM_TX_MMPDU) return NULL;
+
+ returnVal = (u8 *)&(Adapter->sMlmeFrame.TxMMPDU[i]);
+ Adapter->sMlmeFrame.TxMMPDUInUse[i] = TRUE;
+
+ return returnVal;
+}
+
+//=============================================================================
+u8 MLMESendFrame(PWB32_ADAPTER Adapter, u8 *pMMPDU, u16 len, u8 DataType)
+/* DataType : FRAME_TYPE_802_11_MANAGEMENT, FRAME_TYPE_802_11_MANAGEMENT_CHALLENGE,
+ FRAME_TYPE_802_11_DATA */
+{
+ if (Adapter->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
+ Adapter->sMlmeFrame.wNumTxMMPDUDiscarded++;
+ return FALSE;
+ }
+ Adapter->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
+
+ // Keep information for sending
+ Adapter->sMlmeFrame.pMMPDU = pMMPDU;
+ Adapter->sMlmeFrame.DataType = DataType;
+ // len must be the last setting due to QUERY_SIZE_SECOND of Mds
+ Adapter->sMlmeFrame.len = len;
+ Adapter->sMlmeFrame.wNumTxMMPDU++;
+
+ // H/W will enter power save by set the register. S/W don't send null frame
+ //with PWRMgt bit enbled to enter power save now.
+
+ // Transmit NDIS packet
+ Mds_Tx(Adapter);
+ return TRUE;
+}
+
+void
+MLME_GetNextPacket(PADAPTER Adapter, PDESCRIPTOR pDes)
+{
+#define DESCRIPTOR_ADD_BUFFER( _D, _A, _S ) \
+{\
+ _D->InternalUsed = _D->buffer_start_index + _D->buffer_number; \
+ _D->InternalUsed %= MAX_DESCRIPTOR_BUFFER_INDEX; \
+ _D->buffer_address[ _D->InternalUsed ] = _A; \
+ _D->buffer_size[ _D->InternalUsed ] = _S; \
+ _D->buffer_total_size += _S; \
+ _D->buffer_number++;\
+}
+
+ DESCRIPTOR_ADD_BUFFER( pDes, Adapter->sMlmeFrame.pMMPDU, Adapter->sMlmeFrame.len );
+ pDes->Type = Adapter->sMlmeFrame.DataType;
+}
+
+void MLMEfreeMMPDUBuffer(PWB32_ADAPTER Adapter, PCHAR pData)
+{
+ int i;
+
+ // Reclaim the data buffer
+ for (i = 0; i < MAX_NUM_TX_MMPDU; i++) {
+ if (pData == (PCHAR)&(Adapter->sMlmeFrame.TxMMPDU[i]))
+ break;
+ }
+ if (Adapter->sMlmeFrame.TxMMPDUInUse[i])
+ Adapter->sMlmeFrame.TxMMPDUInUse[i] = FALSE;
+ else {
+ // Something wrong
+ // PD43 Add debug code here???
+ }
+}
+
+void
+MLME_SendComplete(PADAPTER Adapter, u8 PacketID, unsigned char SendOK)
+{
+ MLME_TXCALLBACK TxCallback;
+
+ // Reclaim the data buffer
+ Adapter->sMlmeFrame.len = 0;
+ MLMEfreeMMPDUBuffer( Adapter, Adapter->sMlmeFrame.pMMPDU );
+
+
+ TxCallback.bResult = MLME_SUCCESS;
+
+ // Return resource
+ Adapter->sMlmeFrame.IsInUsed = PACKET_FREE_TO_USE;
+}
+
+
+
diff --git a/drivers/staging/winbond/mlmetxrx_f.h b/drivers/staging/winbond/mlmetxrx_f.h
new file mode 100644
index 00000000000..d74e225be21
--- /dev/null
+++ b/drivers/staging/winbond/mlmetxrx_f.h
@@ -0,0 +1,52 @@
+//================================================================
+// MLMETxRx.H --
+//
+// Functions defined in MLMETxRx.c.
+//
+// Copyright (c) 2002 Winbond Electrics Corp. All Rights Reserved.
+//================================================================
+#ifndef _MLMETXRX_H
+#define _MLMETXRX_H
+
+void
+MLMEProcThread(
+ PWB32_ADAPTER Adapter
+ );
+
+void MLMEResetTxRx( PWB32_ADAPTER Adapter);
+
+u8 *
+MLMEGetMMPDUBuffer(
+ PWB32_ADAPTER Adapter
+ );
+
+void MLMEfreeMMPDUBuffer( PWB32_ADAPTER Adapter, PCHAR pData);
+
+void MLME_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
+u8 MLMESendFrame( PWB32_ADAPTER Adapter,
+ u8 *pMMPDU,
+ u16 len,
+ u8 DataType);
+
+void
+MLME_SendComplete( PWB32_ADAPTER Adapter, u8 PacketID, unsigned char SendOK );
+
+void
+MLMERcvFrame(
+ PWB32_ADAPTER Adapter,
+ PRXBUFFER pRxBufferArray,
+ u8 NumOfBuffer,
+ u8 ReturnSlotIndex
+ );
+
+void
+MLMEReturnPacket(
+ PWB32_ADAPTER Adapter,
+ PUCHAR pRxBufer
+ );
+#ifdef _IBSS_BEACON_SEQ_STICK_
+s8 SendBCNullData(PWB32_ADAPTER Adapter, u16 wIdx);
+#endif
+
+#endif
+
diff --git a/drivers/staging/winbond/mto.c b/drivers/staging/winbond/mto.c
new file mode 100644
index 00000000000..2ef60e5120c
--- /dev/null
+++ b/drivers/staging/winbond/mto.c
@@ -0,0 +1,1229 @@
+//============================================================================
+// MTO.C -
+//
+// Description:
+// MAC Throughput Optimization for W89C33 802.11g WLAN STA.
+//
+// The following MIB attributes or internal variables will be affected
+// while the MTO is being executed:
+// dot11FragmentationThreshold,
+// dot11RTSThreshold,
+// transmission rate and PLCP preamble type,
+// CCA mode,
+// antenna diversity.
+//
+// Revision history:
+// --------------------------------------------------------------------------
+// 20031227 UN20 Pete Chao
+// First draft
+// 20031229 Turbo copy from PD43
+// 20040210 Kevin revised
+// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
+//============================================================================
+
+// LA20040210_DTO kevin
+#include "os_common.h"
+
+// Declare SQ3 to rate and fragmentation threshold table
+// Declare fragmentation thresholds table
+#define MTO_MAX_SQ3_LEVELS 14
+#define MTO_MAX_FRAG_TH_LEVELS 5
+#define MTO_MAX_DATA_RATE_LEVELS 12
+
+u16 MTO_Frag_Th_Tbl[MTO_MAX_FRAG_TH_LEVELS] =
+{
+ 256, 384, 512, 768, 1536
+};
+
+u8 MTO_SQ3_Level[MTO_MAX_SQ3_LEVELS] =
+{
+ 0, 26, 30, 32, 34, 35, 37, 42, 44, 46, 54, 62, 78, 81
+};
+u8 MTO_SQ3toRate[MTO_MAX_SQ3_LEVELS] =
+{
+ 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+u8 MTO_SQ3toFrag[MTO_MAX_SQ3_LEVELS] =
+{
+ 0, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+// One Exchange Time table
+//
+u16 MTO_One_Exchange_Time_Tbl_l[MTO_MAX_FRAG_TH_LEVELS][MTO_MAX_DATA_RATE_LEVELS] =
+{
+ { 2554, 1474, 822, 0, 0, 636, 0, 0, 0, 0, 0, 0},
+ { 3578, 1986, 1009, 0, 0, 729, 0, 0, 0, 0, 0, 0},
+ { 4602, 2498, 1195, 0, 0, 822, 0, 0, 0, 0, 0, 0},
+ { 6650, 3522, 1567, 0, 0, 1009, 0, 0, 0, 0, 0, 0},
+ {12794, 6594, 2684, 0, 0, 1567, 0, 0, 0, 0, 0, 0}
+};
+
+u16 MTO_One_Exchange_Time_Tbl_s[MTO_MAX_FRAG_TH_LEVELS][MTO_MAX_DATA_RATE_LEVELS] =
+{
+ { 0, 1282, 630, 404, 288, 444, 232, 172, 144, 116, 100, 96},
+ { 0, 1794, 817, 572, 400, 537, 316, 228, 188, 144, 124, 116},
+ { 0, 2306, 1003, 744, 516, 630, 400, 288, 228, 172, 144, 136},
+ { 0, 3330, 1375, 1084, 744, 817, 572, 400, 316, 228, 188, 172},
+ { 0, 6402, 2492, 2108, 1424, 1375, 1084, 740, 572, 400, 316, 284}
+};
+
+#define MTO_ONE_EXCHANGE_TIME(preamble_type, frag_th_lvl, data_rate_lvl) \
+ (preamble_type) ? MTO_One_Exchange_Time_Tbl_s[frag_th_lvl][data_rate_lvl] : \
+ MTO_One_Exchange_Time_Tbl_l[frag_th_lvl][data_rate_lvl]
+
+// Declare data rate table
+//The following table will be changed at anytime if the opration rate supported by AP don't
+//match the table
+u8 MTO_Data_Rate_Tbl[MTO_MAX_DATA_RATE_LEVELS] =
+{
+ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+};
+
+//The Stardard_Data_Rate_Tbl and Level2PerTbl table is used to indirectly retreive PER
+//information from Rate_PER_TBL
+//The default settings is AP can support full rate set.
+static u8 Stardard_Data_Rate_Tbl[MTO_MAX_DATA_RATE_LEVELS] =
+{
+ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+};
+static u8 Level2PerTbl[MTO_MAX_DATA_RATE_LEVELS] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+//How many kind of tx rate can be supported by AP
+//DTO will change Rate between MTO_Data_Rate_Tbl[0] and MTO_Data_Rate_Tbl[MTO_DataRateAvailableLevel-1]
+static u8 MTO_DataRateAvailableLevel = MTO_MAX_DATA_RATE_LEVELS;
+//Smoothed PER table for each different RATE based on packet length of 1514
+static int Rate_PER_TBL[91][MTO_MAX_DATA_RATE_LEVELS] = {
+// 1M 2M 5.5M 11M 6M 9M 12M 18M 24M 36M 48M 54M
+/* 0% */{ 93, 177, 420, 538, 690, 774, 1001, 1401, 1768, 2358, 2838, 3039},
+/* 1% */{ 92, 176, 416, 533, 683, 767, 992, 1389, 1752, 2336, 2811, 3010},
+/* 2% */{ 91, 174, 412, 528, 675, 760, 983, 1376, 1735, 2313, 2783, 2979},
+/* 3% */{ 90, 172, 407, 523, 667, 753, 973, 1363, 1719, 2290, 2755, 2948},
+/* 4% */{ 90, 170, 403, 518, 659, 746, 964, 1350, 1701, 2266, 2726, 2916},
+/* 5% */{ 89, 169, 398, 512, 651, 738, 954, 1336, 1684, 2242, 2696, 2884},
+/* 6% */{ 88, 167, 394, 507, 643, 731, 944, 1322, 1666, 2217, 2665, 2851},
+/* 7% */{ 87, 165, 389, 502, 635, 723, 935, 1308, 1648, 2192, 2634, 2817},
+/* 8% */{ 86, 163, 384, 497, 626, 716, 924, 1294, 1629, 2166, 2602, 2782},
+/* 9% */{ 85, 161, 380, 491, 618, 708, 914, 1279, 1611, 2140, 2570, 2747},
+/* 10% */{ 84, 160, 375, 486, 609, 700, 904, 1265, 1591, 2113, 2537, 2711},
+/* 11% */{ 83, 158, 370, 480, 600, 692, 894, 1250, 1572, 2086, 2503, 2675},
+/* 12% */{ 82, 156, 365, 475, 592, 684, 883, 1234, 1552, 2059, 2469, 2638},
+/* 13% */{ 81, 154, 360, 469, 583, 676, 872, 1219, 1532, 2031, 2435, 2600},
+/* 14% */{ 80, 152, 355, 464, 574, 668, 862, 1204, 1512, 2003, 2400, 2562},
+/* 15% */{ 79, 150, 350, 458, 565, 660, 851, 1188, 1492, 1974, 2365, 2524},
+/* 16% */{ 78, 148, 345, 453, 556, 652, 840, 1172, 1471, 1945, 2329, 2485},
+/* 17% */{ 77, 146, 340, 447, 547, 643, 829, 1156, 1450, 1916, 2293, 2446},
+/* 18% */{ 76, 144, 335, 441, 538, 635, 818, 1140, 1429, 1887, 2256, 2406},
+/* 19% */{ 75, 143, 330, 436, 529, 627, 807, 1124, 1408, 1857, 2219, 2366},
+/* 20% */{ 74, 141, 325, 430, 520, 618, 795, 1107, 1386, 1827, 2182, 2326},
+/* 21% */{ 73, 139, 320, 424, 510, 610, 784, 1091, 1365, 1797, 2145, 2285},
+/* 22% */{ 72, 137, 314, 418, 501, 601, 772, 1074, 1343, 1766, 2107, 2244},
+/* 23% */{ 71, 135, 309, 412, 492, 592, 761, 1057, 1321, 1736, 2069, 2203},
+/* 24% */{ 70, 133, 304, 407, 482, 584, 749, 1040, 1299, 1705, 2031, 2161},
+/* 25% */{ 69, 131, 299, 401, 473, 575, 738, 1023, 1277, 1674, 1992, 2120},
+/* 26% */{ 68, 129, 293, 395, 464, 566, 726, 1006, 1254, 1642, 1953, 2078},
+/* 27% */{ 67, 127, 288, 389, 454, 557, 714, 989, 1232, 1611, 1915, 2035},
+/* 28% */{ 66, 125, 283, 383, 445, 549, 703, 972, 1209, 1579, 1876, 1993},
+/* 29% */{ 65, 123, 278, 377, 436, 540, 691, 955, 1187, 1548, 1836, 1951},
+/* 30% */{ 64, 121, 272, 371, 426, 531, 679, 937, 1164, 1516, 1797, 1908},
+/* 31% */{ 63, 119, 267, 365, 417, 522, 667, 920, 1141, 1484, 1758, 1866},
+/* 32% */{ 62, 117, 262, 359, 407, 513, 655, 902, 1118, 1453, 1719, 1823},
+/* 33% */{ 61, 115, 256, 353, 398, 504, 643, 885, 1095, 1421, 1679, 1781},
+/* 34% */{ 60, 113, 251, 347, 389, 495, 631, 867, 1072, 1389, 1640, 1738},
+/* 35% */{ 59, 111, 246, 341, 379, 486, 619, 850, 1049, 1357, 1600, 1695},
+/* 36% */{ 58, 108, 240, 335, 370, 477, 607, 832, 1027, 1325, 1561, 1653},
+/* 37% */{ 57, 106, 235, 329, 361, 468, 595, 815, 1004, 1293, 1522, 1610},
+/* 38% */{ 56, 104, 230, 323, 351, 459, 584, 797, 981, 1261, 1483, 1568},
+/* 39% */{ 55, 102, 224, 317, 342, 450, 572, 780, 958, 1230, 1443, 1526},
+/* 40% */{ 54, 100, 219, 311, 333, 441, 560, 762, 935, 1198, 1404, 1484},
+/* 41% */{ 53, 98, 214, 305, 324, 432, 548, 744, 912, 1166, 1366, 1442},
+/* 42% */{ 52, 96, 209, 299, 315, 423, 536, 727, 889, 1135, 1327, 1400},
+/* 43% */{ 51, 94, 203, 293, 306, 414, 524, 709, 866, 1104, 1289, 1358},
+/* 44% */{ 50, 92, 198, 287, 297, 405, 512, 692, 844, 1072, 1250, 1317},
+/* 45% */{ 49, 90, 193, 281, 288, 396, 500, 675, 821, 1041, 1212, 1276},
+/* 46% */{ 48, 88, 188, 275, 279, 387, 488, 657, 799, 1011, 1174, 1236},
+/* 47% */{ 47, 86, 183, 269, 271, 378, 476, 640, 777, 980, 1137, 1195},
+/* 48% */{ 46, 84, 178, 262, 262, 369, 464, 623, 754, 949, 1100, 1155},
+/* 49% */{ 45, 82, 173, 256, 254, 360, 452, 606, 732, 919, 1063, 1116},
+/* 50% */{ 44, 80, 168, 251, 245, 351, 441, 589, 710, 889, 1026, 1076},
+/* 51% */{ 43, 78, 163, 245, 237, 342, 429, 572, 689, 860, 990, 1038},
+/* 52% */{ 42, 76, 158, 239, 228, 333, 417, 555, 667, 830, 955, 999},
+/* 53% */{ 41, 74, 153, 233, 220, 324, 406, 538, 645, 801, 919, 961},
+/* 54% */{ 40, 72, 148, 227, 212, 315, 394, 522, 624, 773, 884, 924},
+/* 55% */{ 39, 70, 143, 221, 204, 307, 383, 505, 603, 744, 850, 887},
+/* 56% */{ 38, 68, 138, 215, 196, 298, 371, 489, 582, 716, 816, 851},
+/* 57% */{ 37, 67, 134, 209, 189, 289, 360, 473, 562, 688, 783, 815},
+/* 58% */{ 36, 65, 129, 203, 181, 281, 349, 457, 541, 661, 750, 780},
+/* 59% */{ 35, 63, 124, 197, 174, 272, 338, 441, 521, 634, 717, 745},
+/* 60% */{ 34, 61, 120, 192, 166, 264, 327, 425, 501, 608, 686, 712},
+/* 61% */{ 33, 59, 115, 186, 159, 255, 316, 409, 482, 582, 655, 678},
+/* 62% */{ 32, 57, 111, 180, 152, 247, 305, 394, 462, 556, 624, 646},
+/* 63% */{ 31, 55, 107, 174, 145, 238, 294, 379, 443, 531, 594, 614},
+/* 64% */{ 30, 53, 102, 169, 138, 230, 283, 364, 425, 506, 565, 583},
+/* 65% */{ 29, 52, 98, 163, 132, 222, 273, 349, 406, 482, 536, 553},
+/* 66% */{ 28, 50, 94, 158, 125, 214, 262, 334, 388, 459, 508, 523},
+/* 67% */{ 27, 48, 90, 152, 119, 206, 252, 320, 370, 436, 481, 495},
+/* 68% */{ 26, 46, 86, 147, 113, 198, 242, 306, 353, 413, 455, 467},
+/* 69% */{ 26, 44, 82, 141, 107, 190, 231, 292, 336, 391, 429, 440},
+/* 70% */{ 25, 43, 78, 136, 101, 182, 221, 278, 319, 370, 405, 414},
+/* 71% */{ 24, 41, 74, 130, 95, 174, 212, 265, 303, 350, 381, 389},
+/* 72% */{ 23, 39, 71, 125, 90, 167, 202, 252, 287, 329, 358, 365},
+/* 73% */{ 22, 37, 67, 119, 85, 159, 192, 239, 271, 310, 335, 342},
+/* 74% */{ 21, 36, 63, 114, 80, 151, 183, 226, 256, 291, 314, 320},
+/* 75% */{ 20, 34, 60, 109, 75, 144, 174, 214, 241, 273, 294, 298},
+/* 76% */{ 19, 32, 57, 104, 70, 137, 164, 202, 227, 256, 274, 278},
+/* 77% */{ 18, 31, 53, 99, 66, 130, 155, 190, 213, 239, 256, 259},
+/* 78% */{ 17, 29, 50, 94, 62, 122, 146, 178, 200, 223, 238, 241},
+/* 79% */{ 16, 28, 47, 89, 58, 115, 138, 167, 187, 208, 222, 225},
+/* 80% */{ 16, 26, 44, 84, 54, 109, 129, 156, 175, 194, 206, 209},
+/* 81% */{ 15, 24, 41, 79, 50, 102, 121, 146, 163, 180, 192, 194},
+/* 82% */{ 14, 23, 39, 74, 47, 95, 113, 136, 151, 167, 178, 181},
+/* 83% */{ 13, 21, 36, 69, 44, 89, 105, 126, 140, 155, 166, 169},
+/* 84% */{ 12, 20, 33, 64, 41, 82, 97, 116, 130, 144, 155, 158},
+/* 85% */{ 11, 19, 31, 60, 39, 76, 89, 107, 120, 134, 145, 149},
+/* 86% */{ 11, 17, 29, 55, 36, 70, 82, 98, 110, 125, 136, 140},
+/* 87% */{ 10, 16, 26, 51, 34, 64, 75, 90, 102, 116, 128, 133},
+/* 88% */{ 9, 14, 24, 46, 32, 58, 68, 81, 93, 108, 121, 128},
+/* 89% */{ 8, 13, 22, 42, 31, 52, 61, 74, 86, 102, 116, 124},
+/* 90% */{ 7, 12, 21, 37, 29, 46, 54, 66, 79, 96, 112, 121}
+};
+
+#define RSSIBUF_NUM 10
+#define RSSI2RATE_SIZE 9
+
+static TXRETRY_REC TxRateRec={MTO_MAX_DATA_RATE_LEVELS - 1, 0}; //new record=>TxRateRec
+static int TxRetryRate;
+//static int SQ3, BSS_PK_CNT, NIDLESLOT, SLOT_CNT, INTERF_CNT, GAP_CNT, DS_EVM;
+static s32 RSSIBuf[RSSIBUF_NUM]={-70, -70, -70, -70, -70, -70, -70, -70, -70, -70};
+static s32 RSSISmoothed=-700;
+static int RSSIBufIndex=0;
+static u8 max_rssi_rate;
+static int rate_tbl[13] = {0,1,2,5,11,6,9,12,18,24,36,48,54};
+//[WKCHEN]static core_data_t *pMTOcore_data=NULL;
+
+static int TotalTxPkt = 0;
+static int TotalTxPktRetry = 0;
+static int TxPktPerAnt[3] = {0,0,0};
+static int RXRSSIANT[3] ={-70,-70,-70};
+static int TxPktRetryPerAnt[3] = {0,0,0};
+//static int TxDominateFlag=FALSE;
+static u8 old_antenna[4]={1 ,0 ,1 ,0};
+static int retryrate_rec[MTO_MAX_DATA_RATE_LEVELS];//this record the retry rate at different data rate
+
+static int PeriodTotalTxPkt = 0;
+static int PeriodTotalTxPktRetry = 0;
+
+typedef struct
+{
+ s32 RSSI;
+ u8 TxRate;
+}RSSI2RATE;
+
+static RSSI2RATE RSSI2RateTbl[RSSI2RATE_SIZE] =
+{
+ {-740, 108}, // 54M
+ {-760, 96}, // 48M
+ {-820, 72}, // 36M
+ {-850, 48}, // 24M
+ {-870, 36}, // 18M
+ {-890, 24}, // 12M
+ {-900, 12}, // 6M
+ {-920, 11}, // 5.5M
+ {-950, 4}, // 2M
+};
+static u8 untogglecount;
+static u8 last_rate_ant; //this is used for antenna backoff-hh
+
+u8 boSparseTxTraffic = FALSE;
+
+void MTO_Init(MTO_FUNC_INPUT);
+void AntennaToggleInitiator(MTO_FUNC_INPUT);
+void AntennaToggleState(MTO_FUNC_INPUT);
+void TxPwrControl(MTO_FUNC_INPUT);
+void GetFreshAntennaData(MTO_FUNC_INPUT);
+void TxRateReductionCtrl(MTO_FUNC_INPUT);
+/** 1.1.31.1000 Turbo modify */
+//void MTO_SetDTORateRange(int type);
+void MTO_SetDTORateRange(MTO_FUNC_INPUT, u8 *pRateArray, u8 ArraySize);
+void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index);
+void MTO_TxFailed(MTO_FUNC_INPUT);
+void SmoothRSSI(s32 new_rssi);
+void hal_get_dto_para(MTO_FUNC_INPUT, char *buffer);
+u8 CalcNewRate(MTO_FUNC_INPUT, u8 old_rate, u32 retry_cnt, u32 tx_frag_cnt);
+u8 GetMaxRateLevelFromRSSI(void);
+u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT);
+int Divide(int a, int b);
+void multiagc(MTO_FUNC_INPUT, u8 high_gain_mode);
+
+//===========================================================================
+// MTO_Init --
+//
+// Description:
+// Set DTO Tx Rate Scope because different AP could have different Rate set.
+// After our staion join with AP, LM core will call this function to initialize
+// Tx Rate table.
+//
+// Arguments:
+// pRateArray - The pointer to the Tx Rate Array by the following order
+// - 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+// - DTO won't check whether rate order is invalid or not
+// ArraySize - The array size to indicate how many tx rate we can choose
+//
+// sample code:
+// {
+// u8 RateArray[4] = {2, 4, 11, 22};
+// MTO_SetDTORateRange(RateArray, 4);
+// }
+//
+// Return Value:
+// None
+//============================================================================
+void MTO_SetDTORateRange(MTO_FUNC_INPUT,u8 *pRateArray, u8 ArraySize)
+{
+ u8 i, j=0;
+
+ for(i=0;i<ArraySize;i++)
+ {
+ if(pRateArray[i] == 22)
+ break;
+ }
+ if(i < ArraySize) //we need adjust the order of rate list because 11Mbps rate exists
+ {
+ for(;i>0;i--)
+ {
+ if(pRateArray[i-1] <= 11)
+ break;
+ pRateArray[i] = pRateArray[i-1];
+ }
+ pRateArray[i] = 22;
+ MTO_OFDM_RATE_LEVEL() = i;
+ }
+ else
+ {
+ for(i=0; i<ArraySize; i++)
+ {
+ if (pRateArray[i] >= 12)
+ break;
+ }
+ MTO_OFDM_RATE_LEVEL() = i;
+ }
+
+ for(i=0;i<ArraySize;i++)
+ {
+ MTO_Data_Rate_Tbl[i] = pRateArray[i];
+ for(;j<MTO_MAX_DATA_RATE_LEVELS;j++)
+ {
+ if(Stardard_Data_Rate_Tbl[j] == pRateArray[i])
+ break;
+ }
+ Level2PerTbl[i] = j;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[MTO]:Op Rate[%d]: %d\n",i, MTO_Data_Rate_Tbl[i]));
+ #endif
+ }
+ MTO_DataRateAvailableLevel = ArraySize;
+ if( MTO_DATA().RatePolicy ) // 0 means that no registry setting
+ {
+ if( MTO_DATA().RatePolicy == 1 )
+ TxRateRec.tx_rate = 0; //ascent
+ else
+ TxRateRec.tx_rate = MTO_DataRateAvailableLevel -1 ; //descent
+ }
+ else
+ {
+ if( MTO_INITTXRATE_MODE )
+ TxRateRec.tx_rate = 0; //ascent
+ else
+ TxRateRec.tx_rate = MTO_DataRateAvailableLevel -1 ; //descent
+ }
+ TxRateRec.tx_retry_rate = 0;
+ //set default rate for initial use
+ MTO_RATE_LEVEL() = TxRateRec.tx_rate;
+ MTO_FALLBACK_RATE_LEVEL() = MTO_RATE_LEVEL();
+}
+
+//===========================================================================
+// MTO_Init --
+//
+// Description:
+// Initialize MTO parameters.
+//
+// This function should be invoked during system initialization.
+//
+// Arguments:
+// Adapter - The pointer to the Miniport Adapter Context
+//
+// Return Value:
+// None
+//============================================================================
+void MTO_Init(MTO_FUNC_INPUT)
+{
+ int i;
+ //WBDEBUG(("[MTO] -> MTO_Init()\n"));
+ //[WKCHEN]pMTOcore_data = pcore_data;
+// 20040510 Turbo add for global variable
+ MTO_TMR_CNT() = 0;
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
+ MTO_TX_RATE_REDUCTION_STATE() = RATE_CHGSTATE_IDLE;
+ MTO_BACKOFF_TMR() = 0;
+ MTO_LAST_RATE() = 11;
+ MTO_CO_EFFICENT() = 0;
+
+ //MTO_TH_FIXANT() = MTO_DEFAULT_TH_FIXANT;
+ MTO_TH_CNT() = MTO_DEFAULT_TH_CNT;
+ MTO_TH_SQ3() = MTO_DEFAULT_TH_SQ3;
+ MTO_TH_IDLE_SLOT() = MTO_DEFAULT_TH_IDLE_SLOT;
+ MTO_TH_PR_INTERF() = MTO_DEFAULT_TH_PR_INTERF;
+
+ MTO_TMR_AGING() = MTO_DEFAULT_TMR_AGING;
+ MTO_TMR_PERIODIC() = MTO_DEFAULT_TMR_PERIODIC;
+
+ //[WKCHEN]MTO_CCA_MODE_SETUP()= (u8) hal_get_cca_mode(MTO_HAL());
+ //[WKCHEN]MTO_CCA_MODE() = MTO_CCA_MODE_SETUP();
+
+ //MTO_PREAMBLE_TYPE() = MTO_PREAMBLE_LONG;
+ MTO_PREAMBLE_TYPE() = MTO_PREAMBLE_SHORT; // for test
+
+ MTO_ANT_SEL() = hal_get_antenna_number(MTO_HAL());
+ MTO_ANT_MAC() = MTO_ANT_SEL();
+ MTO_CNT_ANT(0) = 0;
+ MTO_CNT_ANT(1) = 0;
+ MTO_SQ_ANT(0) = 0;
+ MTO_SQ_ANT(1) = 0;
+ MTO_ANT_DIVERSITY() = MTO_ANTENNA_DIVERSITY_ON;
+ //CardSet_AntennaDiversity(Adapter, MTO_ANT_DIVERSITY());
+ //PLMESetAntennaDiversity( Adapter, MTO_ANT_DIVERSITY());
+
+ MTO_AGING_TIMEOUT() = 0;//MTO_TMR_AGING() / MTO_TMR_PERIODIC();
+
+ // The following parameters should be initialized to the values set by user
+ //
+ //MTO_RATE_LEVEL() = 10;
+ MTO_RATE_LEVEL() = 0;
+ MTO_FALLBACK_RATE_LEVEL() = MTO_RATE_LEVEL();
+ MTO_FRAG_TH_LEVEL() = 4;
+ /** 1.1.23.1000 Turbo modify from -1 to +1
+ MTO_RTS_THRESHOLD() = MTO_FRAG_TH() - 1;
+ MTO_RTS_THRESHOLD_SETUP() = MTO_FRAG_TH() - 1;
+ */
+ MTO_RTS_THRESHOLD() = MTO_FRAG_TH() + 1;
+ MTO_RTS_THRESHOLD_SETUP() = MTO_FRAG_TH() + 1;
+ // 1.1.23.1000 Turbo add for mto change preamble from 0 to 1
+ MTO_RATE_CHANGE_ENABLE() = 1;
+ MTO_FRAG_CHANGE_ENABLE() = 0; // 1.1.29.1000 Turbo add don't support frag
+ //The default valud of ANTDIV_DEFAULT_ON will be decided by EEPROM
+ //#ifdef ANTDIV_DEFAULT_ON
+ //MTO_ANT_DIVERSITY_ENABLE() = 1;
+ //#else
+ //MTO_ANT_DIVERSITY_ENABLE() = 0;
+ //#endif
+ MTO_POWER_CHANGE_ENABLE() = 1;
+ MTO_PREAMBLE_CHANGE_ENABLE()= 1;
+ MTO_RTS_CHANGE_ENABLE() = 0; // 1.1.29.1000 Turbo add don't support frag
+ // 20040512 Turbo add
+ //old_antenna[0] = 1;
+ //old_antenna[1] = 0;
+ //old_antenna[2] = 1;
+ //old_antenna[3] = 0;
+ for (i=0;i<MTO_MAX_DATA_RATE_LEVELS;i++)
+ retryrate_rec[i]=5;
+
+ MTO_TXFLOWCOUNT() = 0;
+ //--------- DTO threshold parameters -------------
+ //MTOPARA_PERIODIC_CHECK_CYCLE() = 50;
+ MTOPARA_PERIODIC_CHECK_CYCLE() = 10;
+ MTOPARA_RSSI_TH_FOR_ANTDIV() = 10;
+ MTOPARA_TXCOUNT_TH_FOR_CALC_RATE() = 50;
+ MTOPARA_TXRATE_INC_TH() = 10;
+ MTOPARA_TXRATE_DEC_TH() = 30;
+ MTOPARA_TXRATE_EQ_TH() = 40;
+ MTOPARA_TXRATE_BACKOFF() = 12;
+ MTOPARA_TXRETRYRATE_REDUCE() = 6;
+ if ( MTO_TXPOWER_FROM_EEPROM == 0xff)
+ {
+ switch( MTO_HAL()->phy_type)
+ {
+ case RF_AIROHA_2230:
+ case RF_AIROHA_2230S: // 20060420 Add this
+ MTOPARA_TXPOWER_INDEX() = 46; // MAX-8 // @@ Only for AL 2230
+ break;
+ case RF_AIROHA_7230:
+ MTOPARA_TXPOWER_INDEX() = 49;
+ break;
+ case RF_WB_242:
+ MTOPARA_TXPOWER_INDEX() = 10;
+ break;
+ case RF_WB_242_1:
+ MTOPARA_TXPOWER_INDEX() = 24; // ->10 20060316.1 modify
+ break;
+ }
+ }
+ else //follow the setting from EEPROM
+ MTOPARA_TXPOWER_INDEX() = MTO_TXPOWER_FROM_EEPROM;
+ hal_set_rf_power(MTO_HAL(), (u8)MTOPARA_TXPOWER_INDEX());
+ //------------------------------------------------
+
+ // For RSSI turning 20060808.4 Cancel load from EEPROM
+ MTO_DATA().RSSI_high = -41;
+ MTO_DATA().RSSI_low = -60;
+}
+
+//---------------------------------------------------------------------------//
+static u32 DTO_Rx_Info[13][3];
+static u32 DTO_RxCRCFail_Info[13][3];
+static u32 AntennaToggleBkoffTimer=5;
+typedef struct{
+ int RxRate;
+ int RxRatePkts;
+ int index;
+}RXRATE_ANT;
+RXRATE_ANT RxRatePeakAnt[3];
+
+#define ANT0 0
+#define ANT1 1
+#define OLD_ANT 2
+
+void SearchPeakRxRate(int index)
+{
+ int i;
+ RxRatePeakAnt[index].RxRatePkts=0;
+ //Find out the best rx rate which is used on different antenna
+ for(i=1;i<13;i++)
+ {
+ if(DTO_Rx_Info[i][index] > (u32) RxRatePeakAnt[index].RxRatePkts)
+ {
+ RxRatePeakAnt[index].RxRatePkts = DTO_Rx_Info[i][index];
+ RxRatePeakAnt[index].RxRate = rate_tbl[i];
+ RxRatePeakAnt[index].index = i;
+ }
+ }
+}
+
+void ResetDTO_RxInfo(int index, MTO_FUNC_INPUT)
+{
+ int i;
+
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("ResetDTOrx\n"));
+ #endif
+
+ for(i=0;i<13;i++)
+ DTO_Rx_Info[i][index] = MTO_HAL()->rx_ok_count[i];
+
+ for(i=0;i<13;i++)
+ DTO_RxCRCFail_Info[i][index] = MTO_HAL()->rx_err_count[i];
+
+ TotalTxPkt = 0;
+ TotalTxPktRetry = 0;
+}
+
+void GetDTO_RxInfo(int index, MTO_FUNC_INPUT)
+{
+ int i;
+
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("GetDTOrx\n"));
+ #endif
+
+ //PDEBUG(("[MTO]:DTO_Rx_Info[%d]=%d, rx_ok_count=%d\n", index, DTO_Rx_Info[0][index], phw_data->rx_ok_count[0]));
+ for(i=0;i<13;i++)
+ DTO_Rx_Info[i][index] = abs(MTO_HAL()->rx_ok_count[i] - DTO_Rx_Info[i][index]);
+ if(DTO_Rx_Info[0][index]==0) DTO_Rx_Info[0][index] = 1;
+
+ for(i=0;i<13;i++)
+ DTO_RxCRCFail_Info[i][index] = MTO_HAL()->rx_err_count[i] - DTO_RxCRCFail_Info[i][index];
+
+ TxPktPerAnt[index] = TotalTxPkt;
+ TxPktRetryPerAnt[index] = TotalTxPktRetry;
+ TotalTxPkt = 0;
+ TotalTxPktRetry = 0;
+}
+
+void OutputDebugInfo(int index1, int index2)
+{
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:Total Rx (%d)\t\t(%d) \n ", DTO_Rx_Info[0][index1], DTO_Rx_Info[0][index2]));
+ WBDEBUG(("[HHDTO]:RECEIVE RSSI: (%d)\t\t(%d) \n ", RXRSSIANT[index1], RXRSSIANT[index2]));
+ WBDEBUG(("[HHDTO]:TX packet correct rate: (%d)%%\t\t(%d)%% \n ",Divide(TxPktPerAnt[index1]*100,TxPktRetryPerAnt[index1]), Divide(TxPktPerAnt[index2]*100,TxPktRetryPerAnt[index2])));
+ #endif
+ {
+ int tmp1, tmp2;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:Total Tx (%d)\t\t(%d) \n ", TxPktPerAnt[index1], TxPktPerAnt[index2]));
+ WBDEBUG(("[HHDTO]:Total Tx retry (%d)\t\t(%d) \n ", TxPktRetryPerAnt[index1], TxPktRetryPerAnt[index2]));
+ #endif
+ tmp1 = TxPktPerAnt[index1] + DTO_Rx_Info[0][index1];
+ tmp2 = TxPktPerAnt[index2] + DTO_Rx_Info[0][index2];
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:Total Tx+RX (%d)\t\t(%d) \n ", tmp1, tmp2));
+ #endif
+ }
+}
+
+unsigned char TxDominate(int index)
+{
+ int tmp;
+
+ tmp = TxPktPerAnt[index] + DTO_Rx_Info[0][index];
+
+ if(Divide(TxPktPerAnt[index]*100, tmp) > 40)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+unsigned char CmpTxRetryRate(int index1, int index2)
+{
+ int tx_retry_rate1, tx_retry_rate2;
+ tx_retry_rate1 = Divide((TxPktRetryPerAnt[index1] - TxPktPerAnt[index1])*100, TxPktRetryPerAnt[index1]);
+ tx_retry_rate2 = Divide((TxPktRetryPerAnt[index2] - TxPktPerAnt[index2])*100, TxPktRetryPerAnt[index2]);
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[MTO]:TxRetry Ant0: (%d%%) Ant1: (%d%%) \n ", tx_retry_rate1, tx_retry_rate2));
+ #endif
+
+ if(tx_retry_rate1 > tx_retry_rate2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void GetFreshAntennaData(MTO_FUNC_INPUT)
+{
+ u8 x;
+
+ x = hal_get_antenna_number(MTO_HAL());
+ //hal_get_bss_pk_cnt(MTO_HAL());
+ //hal_get_est_sq3(MTO_HAL(), 1);
+ old_antenna[0] = x;
+ //if this is the function for timer
+ ResetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
+ if(AntennaToggleBkoffTimer)
+ AntennaToggleBkoffTimer--;
+ if (abs(last_rate_ant-MTO_RATE_LEVEL())>1) //backoff timer reset
+ AntennaToggleBkoffTimer=0;
+
+ if (MTO_ANT_DIVERSITY() != MTO_ANTENNA_DIVERSITY_ON ||
+ MTO_ANT_DIVERSITY_ENABLE() != 1)
+ AntennaToggleBkoffTimer=1;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:**last data rate=%d,now data rate=%d**antenna toggle timer=%d",last_rate_ant,MTO_RATE_LEVEL(),AntennaToggleBkoffTimer));
+ #endif
+ last_rate_ant=MTO_RATE_LEVEL();
+ if(AntennaToggleBkoffTimer==0)
+ {
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT0;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:===state is starting==for antenna toggle==="));
+ #endif
+ }
+ else
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
+
+ if ((MTO_BACKOFF_TMR()!=0)&&(MTO_RATE_LEVEL()>MTO_DataRateAvailableLevel - 3))
+ {
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:===the data rate is %d (good)and will not toogle ===",MTO_DATA_RATE()>>1));
+ #endif
+ }
+
+
+}
+
+int WB_PCR[2]; //packet correct rate
+
+void AntennaToggleState(MTO_FUNC_INPUT)
+{
+ int decideantflag = 0;
+ u8 x;
+ s32 rssi;
+
+ if(MTO_ANT_DIVERSITY_ENABLE() != 1)
+ return;
+ x = hal_get_antenna_number(MTO_HAL());
+ switch(MTO_TOGGLE_STATE())
+ {
+
+ //Missing.....
+ case TOGGLE_STATE_IDLE:
+ case TOGGLE_STATE_BKOFF:
+ break;;
+
+ case TOGGLE_STATE_WAIT0://========
+ GetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
+ sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
+ RXRSSIANT[x] = rssi;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO] **wait0==== Collecting Ant%d--rssi=%d\n", x,RXRSSIANT[x]));
+ #endif
+
+ //change antenna and reset the data at changed antenna
+ x = (~x) & 0x01;
+ MTO_ANT_SEL() = x;
+ hal_set_antenna_number(MTO_HAL(), MTO_ANT_SEL());
+ LOCAL_ANTENNA_NO() = x;
+
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT1;//go to wait1
+ ResetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
+ break;
+ case TOGGLE_STATE_WAIT1://=====wait1
+ //MTO_CNT_ANT(x) = hal_get_bss_pk_cnt(MTO_HAL());
+ //RXRSSIANT[x] = hal_get_rssi(MTO_HAL());
+ sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
+ RXRSSIANT[x] = rssi;
+ GetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO] **wait1==== Collecting Ant%d--rssi=%d\n", x,RXRSSIANT[x]));
+ #endif
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_MAKEDESISION;
+ break;
+ case TOGGLE_STATE_MAKEDESISION:
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:Ant--0-----------------1---\n"));
+ OutputDebugInfo(ANT0,ANT1);
+ #endif
+ //PDEBUG(("[HHDTO] **decision====\n "));
+
+ //=====following is the decision produrce
+ //
+ // first: compare the rssi if difference >10
+ // select the larger one
+ // ,others go to second
+ // second: comapre the tx+rx packet count if difference >100
+ // use larger total packets antenna
+ // third::compare the tx PER if packets>20
+ // if difference >5% using the bigger one
+ //
+ // fourth:compare the RX PER if packets>20
+ // if PER difference <5%
+ // using old antenna
+ //
+ //
+ if (abs(RXRSSIANT[ANT0]-RXRSSIANT[ANT1]) > MTOPARA_RSSI_TH_FOR_ANTDIV())//====rssi_th
+ {
+ if (RXRSSIANT[ANT0]>RXRSSIANT[ANT1])
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT0;
+ }
+ else
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT1;
+ }
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("Select antenna by RSSI\n"));
+ #endif
+ }
+ else if (abs(TxPktPerAnt[ANT0] + DTO_Rx_Info[0][ANT0]-TxPktPerAnt[ANT1]-DTO_Rx_Info[0][ANT1])<50)//=====total packet_th
+ {
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("Total tx/rx is close\n"));
+ #endif
+ if (TxDominate(ANT0) && TxDominate(ANT1))
+ {
+ if ((TxPktPerAnt[ANT0]>10) && (TxPktPerAnt[ANT1]>10))//====tx packet_th
+ {
+ WB_PCR[ANT0]=Divide(TxPktPerAnt[ANT0]*100,TxPktRetryPerAnt[ANT0]);
+ WB_PCR[ANT1]=Divide(TxPktPerAnt[ANT1]*100,TxPktRetryPerAnt[ANT1]);
+ if (abs(WB_PCR[ANT0]-WB_PCR[ANT1])>5)// tx PER_th
+ {
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("Decide by Tx correct rate\n"));
+ #endif
+ if (WB_PCR[ANT0]>WB_PCR[ANT1])
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT0;
+ }
+ else
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT1;
+ }
+ }
+ else
+ {
+ decideantflag=0;
+ untogglecount++;
+ MTO_ANT_MAC() = old_antenna[0];
+ }
+ }
+ else
+ {
+ decideantflag=0;
+ MTO_ANT_MAC() = old_antenna[0];
+ }
+ }
+ else if ((DTO_Rx_Info[0][ANT0]>10)&&(DTO_Rx_Info[0][ANT1]>10))//rx packet th
+ {
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("Decide by Rx\n"));
+ #endif
+ if (abs(DTO_Rx_Info[0][ANT0] - DTO_Rx_Info[0][ANT1])>50)
+ {
+ if (DTO_Rx_Info[0][ANT0] > DTO_Rx_Info[0][ANT1])
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT0;
+ }
+ else
+ {
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT1;
+ }
+ }
+ else
+ {
+ decideantflag=0;
+ untogglecount++;
+ MTO_ANT_MAC() = old_antenna[0];
+ }
+ }
+ else
+ {
+ decideantflag=0;
+ MTO_ANT_MAC() = old_antenna[0];
+ }
+ }
+ else if ((TxPktPerAnt[ANT0]+DTO_Rx_Info[0][ANT0])>(TxPktPerAnt[ANT1]+DTO_Rx_Info[0][ANT1]))//use more packekts
+ {
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("decide by total tx/rx : ANT 0\n"));
+ #endif
+
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT0;
+ }
+ else
+ {
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("decide by total tx/rx : ANT 1\n"));
+ #endif
+ decideantflag=1;
+ MTO_ANT_MAC() = ANT1;
+
+ }
+ //this is force ant toggle
+ if (decideantflag==1)
+ untogglecount=0;
+
+ untogglecount=untogglecount%4;
+ if (untogglecount==3) //change antenna
+ MTO_ANT_MAC() = ((~old_antenna[0]) & 0x1);
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:==================untoggle-count=%d",untogglecount));
+ #endif
+
+
+
+
+ //PDEBUG(("[HHDTO] **********************************DTO ENABLE=%d",MTO_ANT_DIVERSITY_ENABLE()));
+ if(MTO_ANT_DIVERSITY_ENABLE() == 1)
+ {
+ MTO_ANT_SEL() = MTO_ANT_MAC();
+ hal_set_antenna_number(MTO_HAL(), MTO_ANT_SEL());
+ LOCAL_ANTENNA_NO() = MTO_ANT_SEL();
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO] ==decision==*******antflag=%d******************selected antenna=%d\n",decideantflag,MTO_ANT_SEL()));
+ #endif
+ }
+ if (decideantflag)
+ {
+ old_antenna[3]=old_antenna[2];//store antenna info
+ old_antenna[2]=old_antenna[1];
+ old_antenna[1]=old_antenna[0];
+ old_antenna[0]= MTO_ANT_MAC();
+ }
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:**old antenna=[%d][%d][%d][%d]\n",old_antenna[0],old_antenna[1],old_antenna[2],old_antenna[3]));
+ #endif
+ if (old_antenna[0]!=old_antenna[1])
+ AntennaToggleBkoffTimer=0;
+ else if (old_antenna[1]!=old_antenna[2])
+ AntennaToggleBkoffTimer=1;
+ else if (old_antenna[2]!=old_antenna[3])
+ AntennaToggleBkoffTimer=2;
+ else
+ AntennaToggleBkoffTimer=4;
+
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTO]:**back off timer=%d",AntennaToggleBkoffTimer));
+ #endif
+
+ ResetDTO_RxInfo(MTO_ANT_MAC(), MTO_FUNC_INPUT_DATA);
+ if (AntennaToggleBkoffTimer==0 && decideantflag)
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT0;
+ else
+ MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
+ break;
+ }
+
+}
+
+void multiagc(MTO_FUNC_INPUT, u8 high_gain_mode )
+{
+ s32 rssi;
+ hw_data_t *pHwData = MTO_HAL();
+
+ sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
+
+ if( (RF_WB_242 == pHwData->phy_type) ||
+ (RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
+ {
+ if (high_gain_mode==1)
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x06C43440);
+ Wb35Reg_Write( pHwData, 0x100C, 0xF2F32232 ); // 940916 0xf8f52230 );
+ Wb35Reg_Write( pHwData, 0x1020, 0x04cb3440 ); // 940915 0x06C43440
+ }
+ else if (high_gain_mode==0)
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xEEEE000D);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x06c41440);
+ Wb35Reg_Write( pHwData, 0x100C, 0xEEEE000D );
+ Wb35Reg_Write( pHwData, 0x1020, 0x04cb1440 ); // 940915 0x06c41440
+ }
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[HHDTOAGC] **rssi=%d, high gain mode=%d", rssi, high_gain_mode));
+ #endif
+ }
+}
+
+void TxPwrControl(MTO_FUNC_INPUT)
+{
+ s32 rssi;
+ hw_data_t *pHwData = MTO_HAL();
+
+ sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
+ if( (RF_WB_242 == pHwData->phy_type) ||
+ (RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
+ {
+ static u8 high_gain_mode; //this is for winbond RF switch LNA
+ //using different register setting
+
+ if (high_gain_mode==1)
+ {
+ if( rssi > MTO_DATA().RSSI_high )
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x05541640);
+ high_gain_mode=0;
+ }
+ else
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xf8f51830);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x05543E40);
+ high_gain_mode=1;
+ }
+ }
+ else //if (high_gain_mode==0)
+ {
+ if( rssi < MTO_DATA().RSSI_low )
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xf8f51830);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x05543E40);
+ high_gain_mode=1;
+ }
+ else
+ {
+ //hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
+ //hw_set_dxx_reg(phw_data, 0x20, 0x05541640);
+ high_gain_mode=0;
+ }
+ }
+
+ // Always high gain 20051014. Using the initial value only.
+ multiagc(MTO_FUNC_INPUT_DATA, high_gain_mode);
+ }
+}
+
+
+u8 CalcNewRate(MTO_FUNC_INPUT, u8 old_rate, u32 retry_cnt, u32 tx_frag_cnt)
+{
+ int i;
+ u8 new_rate;
+ u32 retry_rate;
+ int TxThrouput1, TxThrouput2, TxThrouput3, BestThroupht;
+
+ if(tx_frag_cnt < MTOPARA_TXCOUNT_TH_FOR_CALC_RATE()) //too few packets transmit
+ {
+ return 0xff;
+ }
+ retry_rate = Divide(retry_cnt * 100, tx_frag_cnt);
+
+ if(retry_rate > 90) retry_rate = 90; //always truncate to 90% due to lookup table size
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("##### Current level =%d, Retry count =%d, Frag count =%d\n",
+ old_rate, retry_cnt, tx_frag_cnt));
+ WBDEBUG(("*##* Retry rate =%d, throughput =%d\n",
+ retry_rate, Rate_PER_TBL[retry_rate][old_rate]));
+ WBDEBUG(("TxRateRec.tx_rate =%d, Retry rate = %d, throughput = %d\n",
+ TxRateRec.tx_rate, TxRateRec.tx_retry_rate,
+ Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]]));
+ WBDEBUG(("old_rate-1 =%d, Retry rate = %d, throughput = %d\n",
+ old_rate-1, retryrate_rec[old_rate-1],
+ Rate_PER_TBL[retryrate_rec[old_rate-1]][old_rate-1]));
+ WBDEBUG(("old_rate+1 =%d, Retry rate = %d, throughput = %d\n",
+ old_rate+1, retryrate_rec[old_rate+1],
+ Rate_PER_TBL[retryrate_rec[old_rate+1]][old_rate+1]));
+ #endif
+
+ //following is for record the retry rate at the different data rate
+ if (abs(retry_rate-retryrate_rec[old_rate])<50)//---the per TH
+ retryrate_rec[old_rate] = retry_rate; //update retry rate
+ else
+ {
+ for (i=0;i<MTO_DataRateAvailableLevel;i++) //reset all retry rate
+ retryrate_rec[i]=0;
+ retryrate_rec[old_rate] = retry_rate;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("Reset retry rate table\n"));
+ #endif
+ }
+
+ if(TxRateRec.tx_rate > old_rate) //Decrease Tx Rate
+ {
+ TxThrouput1 = Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]];
+ TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
+ if(TxThrouput1 > TxThrouput2)
+ {
+ new_rate = TxRateRec.tx_rate;
+ BestThroupht = TxThrouput1;
+ }
+ else
+ {
+ new_rate = old_rate;
+ BestThroupht = TxThrouput2;
+ }
+ if((old_rate > 0) &&(retry_rate>MTOPARA_TXRATE_DEC_TH())) //Min Rate
+ {
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate-1]][Level2PerTbl[old_rate-1]];
+ if(BestThroupht < TxThrouput3)
+ {
+ new_rate = old_rate - 1;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("--------\n"));
+ #endif
+ BestThroupht = TxThrouput3;
+ }
+ }
+ }
+ else if(TxRateRec.tx_rate < old_rate) //Increase Tx Rate
+ {
+ TxThrouput1 = Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]];
+ TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
+ if(TxThrouput1 > TxThrouput2)
+ {
+ new_rate = TxRateRec.tx_rate;
+ BestThroupht = TxThrouput1;
+ }
+ else
+ {
+ new_rate = old_rate;
+ BestThroupht = TxThrouput2;
+ }
+ if ((old_rate < MTO_DataRateAvailableLevel - 1)&&(retry_rate<MTOPARA_TXRATE_INC_TH()))
+ {
+ //TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
+ if (retryrate_rec[old_rate+1] > MTOPARA_TXRETRYRATE_REDUCE())
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]-MTOPARA_TXRETRYRATE_REDUCE()][Level2PerTbl[old_rate+1]];
+ else
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
+ if(BestThroupht < TxThrouput3)
+ {
+ new_rate = old_rate + 1;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("++++++++++\n"));
+ #endif
+ BestThroupht = TxThrouput3;
+ }
+ }
+ }
+ else //Tx Rate no change
+ {
+ TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
+ new_rate = old_rate;
+ BestThroupht = TxThrouput2;
+
+ if (retry_rate <MTOPARA_TXRATE_EQ_TH()) //th for change higher rate
+ {
+ if(old_rate < MTO_DataRateAvailableLevel - 1)
+ {
+ //TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
+ if (retryrate_rec[old_rate+1] > MTOPARA_TXRETRYRATE_REDUCE())
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]-MTOPARA_TXRETRYRATE_REDUCE()][Level2PerTbl[old_rate+1]];
+ else
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
+ if(BestThroupht < TxThrouput3)
+ {
+ new_rate = old_rate + 1;
+ BestThroupht = TxThrouput3;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("=++++++++++\n"));
+ #endif
+ }
+ }
+ }
+ else
+ if(old_rate > 0) //Min Rate
+ {
+ TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate-1]][Level2PerTbl[old_rate-1]];
+ if(BestThroupht < TxThrouput3)
+ {
+ new_rate = old_rate - 1;
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("=--------\n"));
+ #endif
+ BestThroupht = TxThrouput3;
+ }
+ }
+ }
+
+ if (!LOCAL_IS_IBSS_MODE())
+ {
+ max_rssi_rate = GetMaxRateLevelFromRSSI();
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[MTO]:RSSI2Rate=%d\n", MTO_Data_Rate_Tbl[max_rssi_rate]));
+ #endif
+ if(new_rate > max_rssi_rate)
+ new_rate = max_rssi_rate;
+ }
+
+ //save new rate;
+ TxRateRec.tx_rate = old_rate;
+ TxRateRec.tx_retry_rate = (u8) retry_rate;
+ TxRetryRate = retry_rate;
+ return new_rate;
+}
+
+void SmoothRSSI(s32 new_rssi)
+{
+ RSSISmoothed = RSSISmoothed + new_rssi - RSSIBuf[RSSIBufIndex];
+ RSSIBuf[RSSIBufIndex] = new_rssi;
+ RSSIBufIndex = (RSSIBufIndex + 1) % 10;
+}
+
+u8 GetMaxRateLevelFromRSSI(void)
+{
+ u8 i;
+ u8 TxRate;
+
+ for(i=0;i<RSSI2RATE_SIZE;i++)
+ {
+ if(RSSISmoothed > RSSI2RateTbl[i].RSSI)
+ break;
+ }
+ #ifdef _PE_DTO_DUMP_
+ WBDEBUG(("[MTO]:RSSI=%d\n", Divide(RSSISmoothed, 10)));
+ #endif
+ if(i < RSSI2RATE_SIZE)
+ TxRate = RSSI2RateTbl[i].TxRate;
+ else
+ TxRate = 2; //divided by 2 = 1Mbps
+
+ for(i=MTO_DataRateAvailableLevel-1;i>0;i--)
+ {
+ if(TxRate >=MTO_Data_Rate_Tbl[i])
+ break;
+ }
+ return i;
+}
+
+//===========================================================================
+// Description:
+// If we enable DTO, we will ignore the tx count with different tx rate from
+// DTO rate. This is because when we adjust DTO tx rate, there could be some
+// packets in the tx queue with previous tx rate
+void MTO_SetTxCount(MTO_FUNC_INPUT, u8 tx_rate, u8 index)
+{
+ MTO_TXFLOWCOUNT()++;
+ if ((MTO_ENABLE==1) && (MTO_RATE_CHANGE_ENABLE()==1))
+ {
+ if(tx_rate == MTO_DATA_RATE())
+ {
+ if (index == 0)
+ {
+ if (boSparseTxTraffic)
+ MTO_HAL()->dto_tx_frag_count += MTOPARA_PERIODIC_CHECK_CYCLE();
+ else
+ MTO_HAL()->dto_tx_frag_count += 1;
+ }
+ else
+ {
+ if (index<8)
+ {
+ MTO_HAL()->dto_tx_retry_count += index;
+ MTO_HAL()->dto_tx_frag_count += (index+1);
+ }
+ else
+ {
+ MTO_HAL()->dto_tx_retry_count += 7;
+ MTO_HAL()->dto_tx_frag_count += 7;
+ }
+ }
+ }
+ else if(MTO_DATA_RATE()>48 && tx_rate ==48)
+ {//ALFRED
+ if (index<3) //for reduciing data rate scheme ,
+ //do not calcu different data rate
+ //3 is the reducing data rate at retry
+ {
+ MTO_HAL()->dto_tx_retry_count += index;
+ MTO_HAL()->dto_tx_frag_count += (index+1);
+ }
+ else
+ {
+ MTO_HAL()->dto_tx_retry_count += 3;
+ MTO_HAL()->dto_tx_frag_count += 3;
+ }
+
+ }
+ }
+ else
+ {
+ MTO_HAL()->dto_tx_retry_count += index;
+ MTO_HAL()->dto_tx_frag_count += (index+1);
+ }
+ TotalTxPkt ++;
+ TotalTxPktRetry += (index+1);
+
+ PeriodTotalTxPkt ++;
+ PeriodTotalTxPktRetry += (index+1);
+}
+
+u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT)
+{
+ return MTO_DATA_FALLBACK_RATE();
+}
+
+
+//===========================================================================
+// MTO_TxFailed --
+//
+// Description:
+// Failure of transmitting a packet indicates that certain MTO parmeters
+// may need to be adjusted. This function is called when NIC just failed
+// to transmit a packet or when MSDULifeTime expired.
+//
+// Arguments:
+// Adapter - The pointer to the Miniport Adapter Context
+//
+// Return Value:
+// None
+//============================================================================
+void MTO_TxFailed(MTO_FUNC_INPUT)
+{
+ return;
+}
+
+int Divide(int a, int b)
+{
+ if (b==0) b=1;
+ return a/b;
+}
+
+
diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h
new file mode 100644
index 00000000000..f47936f46d1
--- /dev/null
+++ b/drivers/staging/winbond/mto.h
@@ -0,0 +1,265 @@
+//==================================================================
+// MTO.H
+//
+// Revision history
+//=================================
+// 20030110 UN20 Pete Chao
+// Initial Release
+//
+// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
+//==================================================================
+#ifndef __MTO_H__
+#define __MTO_H__
+
+#define MTO_DEFAULT_TH_CNT 5
+#define MTO_DEFAULT_TH_SQ3 112 //OLD IS 13 reference JohnXu
+#define MTO_DEFAULT_TH_IDLE_SLOT 15
+#define MTO_DEFAULT_TH_PR_INTERF 30
+#define MTO_DEFAULT_TMR_AGING 25 // unit: slot time 10 reference JohnXu
+#define MTO_DEFAULT_TMR_PERIODIC 5 // unit: slot time
+
+#define MTO_ANTENNA_DIVERSITY_OFF 0
+#define MTO_ANTENNA_DIVERSITY_ON 1
+
+// LA20040210_DTO kevin
+//#define MTO_PREAMBLE_LONG 0
+//#define MTO_PREAMBLE_SHORT 1
+#define MTO_PREAMBLE_LONG WLAN_PREAMBLE_TYPE_LONG
+#define MTO_PREAMBLE_SHORT WLAN_PREAMBLE_TYPE_SHORT
+
+typedef enum {
+ TOGGLE_STATE_IDLE = 0,
+ TOGGLE_STATE_WAIT0 = 1,
+ TOGGLE_STATE_WAIT1 = 2,
+ TOGGLE_STATE_MAKEDESISION = 3,
+ TOGGLE_STATE_BKOFF = 4
+} TOGGLE_STATE;
+
+typedef enum {
+ RATE_CHGSTATE_IDLE = 0,
+ RATE_CHGSTATE_CALCULATE = 1,
+ RATE_CHGSTATE_BACKOFF = 2
+} TX_RATE_REDUCTION_STATE;
+
+//============================================================================
+// struct _MTOParameters --
+//
+// Defines the parameters used in the MAC Throughput Optimization algorithm
+//============================================================================
+typedef struct _MTO_PARAMETERS
+{
+ u8 Th_Fixant;
+ u8 Th_Cnt;
+ u8 Th_SQ3;
+ u8 Th_IdleSlot;
+
+ u16 Tmr_Aging;
+ u8 Th_PrInterf;
+ u8 Tmr_Periodic;
+
+ //--------- wkchen added -------------
+ u32 TxFlowCount; //to judge what kind the tx flow(sparse or busy) is
+ //------------------------------------------------
+
+ //--------- DTO threshold parameters -------------
+ u16 DTO_PeriodicCheckCycle;
+ u16 DTO_RssiThForAntDiv;
+
+ u16 DTO_TxCountThForCalcNewRate;
+ u16 DTO_TxRateIncTh;
+
+ u16 DTO_TxRateDecTh;
+ u16 DTO_TxRateEqTh;
+
+ u16 DTO_TxRateBackOff;
+ u16 DTO_TxRetryRateReduce;
+
+ u16 DTO_TxPowerIndex; //0 ~ 31
+ u16 reserved_1;
+ //------------------------------------------------
+
+ u8 PowerChangeEnable;
+ u8 AntDiversityEnable;
+ u8 Ant_mac;
+ u8 Ant_div;
+
+ u8 CCA_Mode;
+ u8 CCA_Mode_Setup;
+ u8 Preamble_Type;
+ u8 PreambleChangeEnable;
+
+ u8 DataRateLevel;
+ u8 DataRateChangeEnable;
+ u8 FragThresholdLevel;
+ u8 FragThresholdChangeEnable;
+
+ u16 RTSThreshold;
+ u16 RTSThreshold_Setup;
+
+ u32 AvgIdleSlot;
+ u32 Pr_Interf;
+ u32 AvgGapBtwnInterf;
+
+ u8 RTSChangeEnable;
+ u8 Ant_sel;
+ u8 aging_timeout;
+ u8 reserved_2;
+
+ u32 Cnt_Ant[2];
+ u32 SQ_Ant[2];
+
+// 20040510 remove from globe vairable
+ u32 TmrCnt;
+ u32 BackoffTmr;
+ TOGGLE_STATE ToggleState;
+ TX_RATE_REDUCTION_STATE TxRateReductionState;
+
+ u8 Last_Rate;
+ u8 Co_efficent;
+ u8 FallbackRateLevel;
+ u8 OfdmRateLevel;
+
+ u8 RatePolicy;
+ u8 reserved_3[3];
+
+ // For RSSI turning
+ s32 RSSI_high;
+ s32 RSSI_low;
+
+} MTO_PARAMETERS, *PMTO_PARAMETERS;
+
+
+#define MTO_FUNC_INPUT PWB32_ADAPTER Adapter
+#define MTO_FUNC_INPUT_DATA Adapter
+#define MTO_DATA() (Adapter->sMtoPara)
+#define MTO_HAL() (&Adapter->sHwData)
+#define MTO_SET_PREAMBLE_TYPE(x) // 20040511 Turbo mark LM_PREAMBLE_TYPE(&pcore_data->lm_data) = (x)
+#define MTO_ENABLE (Adapter->sLocalPara.TxRateMode == RATE_AUTO)
+#define MTO_TXPOWER_FROM_EEPROM (Adapter->sHwData.PowerIndexFromEEPROM)
+#define LOCAL_ANTENNA_NO() (Adapter->sLocalPara.bAntennaNo)
+#define LOCAL_IS_CONNECTED() (Adapter->sLocalPara.wConnectedSTAindex != 0)
+#define LOCAL_IS_IBSS_MODE() (Adapter->asBSSDescriptElement[Adapter->sLocalPara.wConnectedSTAindex].bBssType == IBSS_NET)
+#define MTO_INITTXRATE_MODE (Adapter->sHwData.SoftwareSet&0x2) //bit 1
+// 20040510 Turbo add
+#define MTO_TMR_CNT() MTO_DATA().TmrCnt
+#define MTO_TOGGLE_STATE() MTO_DATA().ToggleState
+#define MTO_TX_RATE_REDUCTION_STATE() MTO_DATA().TxRateReductionState
+#define MTO_BACKOFF_TMR() MTO_DATA().BackoffTmr
+#define MTO_LAST_RATE() MTO_DATA().Last_Rate
+#define MTO_CO_EFFICENT() MTO_DATA().Co_efficent
+
+#define MTO_TH_CNT() MTO_DATA().Th_Cnt
+#define MTO_TH_SQ3() MTO_DATA().Th_SQ3
+#define MTO_TH_IDLE_SLOT() MTO_DATA().Th_IdleSlot
+#define MTO_TH_PR_INTERF() MTO_DATA().Th_PrInterf
+
+#define MTO_TMR_AGING() MTO_DATA().Tmr_Aging
+#define MTO_TMR_PERIODIC() MTO_DATA().Tmr_Periodic
+
+#define MTO_POWER_CHANGE_ENABLE() MTO_DATA().PowerChangeEnable
+#define MTO_ANT_DIVERSITY_ENABLE() Adapter->sLocalPara.boAntennaDiversity
+#define MTO_ANT_MAC() MTO_DATA().Ant_mac
+#define MTO_ANT_DIVERSITY() MTO_DATA().Ant_div
+#define MTO_CCA_MODE() MTO_DATA().CCA_Mode
+#define MTO_CCA_MODE_SETUP() MTO_DATA().CCA_Mode_Setup
+#define MTO_PREAMBLE_TYPE() MTO_DATA().Preamble_Type
+#define MTO_PREAMBLE_CHANGE_ENABLE() MTO_DATA().PreambleChangeEnable
+
+#define MTO_RATE_LEVEL() MTO_DATA().DataRateLevel
+#define MTO_FALLBACK_RATE_LEVEL() MTO_DATA().FallbackRateLevel
+#define MTO_OFDM_RATE_LEVEL() MTO_DATA().OfdmRateLevel
+#define MTO_RATE_CHANGE_ENABLE() MTO_DATA().DataRateChangeEnable
+#define MTO_FRAG_TH_LEVEL() MTO_DATA().FragThresholdLevel
+#define MTO_FRAG_CHANGE_ENABLE() MTO_DATA().FragThresholdChangeEnable
+#define MTO_RTS_THRESHOLD() MTO_DATA().RTSThreshold
+#define MTO_RTS_CHANGE_ENABLE() MTO_DATA().RTSChangeEnable
+#define MTO_RTS_THRESHOLD_SETUP() MTO_DATA().RTSThreshold_Setup
+
+#define MTO_AVG_IDLE_SLOT() MTO_DATA().AvgIdleSlot
+#define MTO_PR_INTERF() MTO_DATA().Pr_Interf
+#define MTO_AVG_GAP_BTWN_INTERF() MTO_DATA().AvgGapBtwnInterf
+
+#define MTO_ANT_SEL() MTO_DATA().Ant_sel
+#define MTO_CNT_ANT(x) MTO_DATA().Cnt_Ant[(x)]
+#define MTO_SQ_ANT(x) MTO_DATA().SQ_Ant[(x)]
+#define MTO_AGING_TIMEOUT() MTO_DATA().aging_timeout
+
+
+#define MTO_TXFLOWCOUNT() MTO_DATA().TxFlowCount
+//--------- DTO threshold parameters -------------
+#define MTOPARA_PERIODIC_CHECK_CYCLE() MTO_DATA().DTO_PeriodicCheckCycle
+#define MTOPARA_RSSI_TH_FOR_ANTDIV() MTO_DATA().DTO_RssiThForAntDiv
+#define MTOPARA_TXCOUNT_TH_FOR_CALC_RATE() MTO_DATA().DTO_TxCountThForCalcNewRate
+#define MTOPARA_TXRATE_INC_TH() MTO_DATA().DTO_TxRateIncTh
+#define MTOPARA_TXRATE_DEC_TH() MTO_DATA().DTO_TxRateDecTh
+#define MTOPARA_TXRATE_EQ_TH() MTO_DATA().DTO_TxRateEqTh
+#define MTOPARA_TXRATE_BACKOFF() MTO_DATA().DTO_TxRateBackOff
+#define MTOPARA_TXRETRYRATE_REDUCE() MTO_DATA().DTO_TxRetryRateReduce
+#define MTOPARA_TXPOWER_INDEX() MTO_DATA().DTO_TxPowerIndex
+//------------------------------------------------
+
+
+extern u8 MTO_Data_Rate_Tbl[];
+extern u16 MTO_Frag_Th_Tbl[];
+
+#define MTO_DATA_RATE() MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
+#define MTO_DATA_FALLBACK_RATE() MTO_Data_Rate_Tbl[MTO_FALLBACK_RATE_LEVEL()] //next level
+#define MTO_FRAG_TH() MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
+
+typedef struct {
+ u8 tx_rate;
+ u8 tx_retry_rate;
+} TXRETRY_REC;
+
+typedef struct _STATISTICS_INFO {
+ u32 Rate54M;
+ u32 Rate48M;
+ u32 Rate36M;
+ u32 Rate24M;
+ u32 Rate18M;
+ u32 Rate12M;
+ u32 Rate9M;
+ u32 Rate6M;
+ u32 Rate11MS;
+ u32 Rate11ML;
+ u32 Rate55MS;
+ u32 Rate55ML;
+ u32 Rate2MS;
+ u32 Rate2ML;
+ u32 Rate1M;
+ u32 Rate54MOK;
+ u32 Rate48MOK;
+ u32 Rate36MOK;
+ u32 Rate24MOK;
+ u32 Rate18MOK;
+ u32 Rate12MOK;
+ u32 Rate9MOK;
+ u32 Rate6MOK;
+ u32 Rate11MSOK;
+ u32 Rate11MLOK;
+ u32 Rate55MSOK;
+ u32 Rate55MLOK;
+ u32 Rate2MSOK;
+ u32 Rate2MLOK;
+ u32 Rate1MOK;
+ u32 SQ3;
+ s32 RSSIAVG;
+ s32 RSSIMAX;
+ s32 TXRATE;
+ s32 TxRetryRate;
+ s32 BSS_PK_CNT;
+ s32 NIDLESLOT;
+ s32 SLOT_CNT;
+ s32 INTERF_CNT;
+ s32 GAP_CNT;
+ s32 DS_EVM;
+ s32 RcvBeaconNum;
+ s32 RXRATE;
+ s32 RxBytes;
+ s32 TxBytes;
+ s32 Antenna;
+} STATISTICS_INFO, *PSTATISTICS_INFO;
+
+#endif //__MTO_H__
+
+
diff --git a/drivers/staging/winbond/mto_f.h b/drivers/staging/winbond/mto_f.h
new file mode 100644
index 00000000000..30b3df2ccb3
--- /dev/null
+++ b/drivers/staging/winbond/mto_f.h
@@ -0,0 +1,7 @@
+extern void MTO_Init(PWB32_ADAPTER);
+extern void MTO_PeriodicTimerExpired(PWB32_ADAPTER);
+extern void MTO_SetDTORateRange(PWB32_ADAPTER, u8 *, u8);
+extern u8 MTO_GetTxRate(MTO_FUNC_INPUT, u32 fpdu_len);
+extern u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT);
+extern void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index);
+
diff --git a/drivers/staging/winbond/os_common.h b/drivers/staging/winbond/os_common.h
new file mode 100644
index 00000000000..e24ff41e871
--- /dev/null
+++ b/drivers/staging/winbond/os_common.h
@@ -0,0 +1,2 @@
+#include "linux/sysdef.h"
+
diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c
new file mode 100644
index 00000000000..272a65066ab
--- /dev/null
+++ b/drivers/staging/winbond/phy_calibration.c
@@ -0,0 +1,1759 @@
+/*
+ * phy_302_calibration.c
+ *
+ * Copyright (C) 2002, 2005 Winbond Electronics Corp.
+ *
+ * modification history
+ * ---------------------------------------------------------------------------
+ * 0.01.001, 2003-04-16, Kevin created
+ *
+ */
+
+/****************** INCLUDE FILES SECTION ***********************************/
+#include "os_common.h"
+#include "phy_calibration.h"
+
+
+/****************** DEBUG CONSTANT AND MACRO SECTION ************************/
+
+/****************** LOCAL CONSTANT AND MACRO SECTION ************************/
+#define LOOP_TIMES 20
+#define US 1000//MICROSECOND
+
+#define AG_CONST 0.6072529350
+#define FIXED(X) ((s32)((X) * 32768.0))
+#define DEG2RAD(X) 0.017453 * (X)
+
+/****************** LOCAL TYPE DEFINITION SECTION ***************************/
+typedef s32 fixed; /* 16.16 fixed-point */
+
+static const fixed Angles[]=
+{
+ FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)),
+ FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)),
+ FIXED(DEG2RAD(0.895174)),FIXED(DEG2RAD(0.447614)),FIXED(DEG2RAD(0.223811)),
+ FIXED(DEG2RAD(0.111906)),FIXED(DEG2RAD(0.055953)),FIXED(DEG2RAD(0.027977))
+};
+
+/****************** LOCAL FUNCTION DECLARATION SECTION **********************/
+//void _phy_rf_write_delay(hw_data_t *phw_data);
+//void phy_init_rf(hw_data_t *phw_data);
+
+/****************** FUNCTION DEFINITION SECTION *****************************/
+
+s32 _s13_to_s32(u32 data)
+{
+ u32 val;
+
+ val = (data & 0x0FFF);
+
+ if ((data & BIT(12)) != 0)
+ {
+ val |= 0xFFFFF000;
+ }
+
+ return ((s32) val);
+}
+
+u32 _s32_to_s13(s32 data)
+{
+ u32 val;
+
+ if (data > 4095)
+ {
+ data = 4095;
+ }
+ else if (data < -4096)
+ {
+ data = -4096;
+ }
+
+ val = data & 0x1FFF;
+
+ return val;
+}
+
+/****************************************************************************/
+s32 _s4_to_s32(u32 data)
+{
+ s32 val;
+
+ val = (data & 0x0007);
+
+ if ((data & BIT(3)) != 0)
+ {
+ val |= 0xFFFFFFF8;
+ }
+
+ return val;
+}
+
+u32 _s32_to_s4(s32 data)
+{
+ u32 val;
+
+ if (data > 7)
+ {
+ data = 7;
+ }
+ else if (data < -8)
+ {
+ data = -8;
+ }
+
+ val = data & 0x000F;
+
+ return val;
+}
+
+/****************************************************************************/
+s32 _s5_to_s32(u32 data)
+{
+ s32 val;
+
+ val = (data & 0x000F);
+
+ if ((data & BIT(4)) != 0)
+ {
+ val |= 0xFFFFFFF0;
+ }
+
+ return val;
+}
+
+u32 _s32_to_s5(s32 data)
+{
+ u32 val;
+
+ if (data > 15)
+ {
+ data = 15;
+ }
+ else if (data < -16)
+ {
+ data = -16;
+ }
+
+ val = data & 0x001F;
+
+ return val;
+}
+
+/****************************************************************************/
+s32 _s6_to_s32(u32 data)
+{
+ s32 val;
+
+ val = (data & 0x001F);
+
+ if ((data & BIT(5)) != 0)
+ {
+ val |= 0xFFFFFFE0;
+ }
+
+ return val;
+}
+
+u32 _s32_to_s6(s32 data)
+{
+ u32 val;
+
+ if (data > 31)
+ {
+ data = 31;
+ }
+ else if (data < -32)
+ {
+ data = -32;
+ }
+
+ val = data & 0x003F;
+
+ return val;
+}
+
+/****************************************************************************/
+s32 _s9_to_s32(u32 data)
+{
+ s32 val;
+
+ val = data & 0x00FF;
+
+ if ((data & BIT(8)) != 0)
+ {
+ val |= 0xFFFFFF00;
+ }
+
+ return val;
+}
+
+u32 _s32_to_s9(s32 data)
+{
+ u32 val;
+
+ if (data > 255)
+ {
+ data = 255;
+ }
+ else if (data < -256)
+ {
+ data = -256;
+ }
+
+ val = data & 0x01FF;
+
+ return val;
+}
+
+/****************************************************************************/
+s32 _floor(s32 n)
+{
+ if (n > 0)
+ {
+ n += 5;
+ }
+ else
+ {
+ n -= 5;
+ }
+
+ return (n/10);
+}
+
+/****************************************************************************/
+// The following code is sqare-root function.
+// sqsum is the input and the output is sq_rt;
+// The maximum of sqsum = 2^27 -1;
+u32 _sqrt(u32 sqsum)
+{
+ u32 sq_rt;
+
+ int g0, g1, g2, g3, g4;
+ int seed;
+ int next;
+ int step;
+
+ g4 = sqsum / 100000000;
+ g3 = (sqsum - g4*100000000) /1000000;
+ g2 = (sqsum - g4*100000000 - g3*1000000) /10000;
+ g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) /100;
+ g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
+
+ next = g4;
+ step = 0;
+ seed = 0;
+ while (((seed+1)*(step+1)) <= next)
+ {
+ step++;
+ seed++;
+ }
+
+ sq_rt = seed * 10000;
+ next = (next-(seed*step))*100 + g3;
+
+ step = 0;
+ seed = 2 * seed * 10;
+ while (((seed+1)*(step+1)) <= next)
+ {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 1000;
+ next = (next - seed * step) * 100 + g2;
+ seed = (seed + step) * 10;
+ step = 0;
+ while (((seed+1)*(step+1)) <= next)
+ {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 100;
+ next = (next - seed * step) * 100 + g1;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed+1)*(step+1)) <= next)
+ {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 10;
+ next = (next - seed* step) * 100 + g0;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed+1)*(step+1)) <= next)
+ {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step;
+
+ return sq_rt;
+}
+
+/****************************************************************************/
+void _sin_cos(s32 angle, s32 *sin, s32 *cos)
+{
+ fixed X, Y, TargetAngle, CurrAngle;
+ unsigned Step;
+
+ X=FIXED(AG_CONST); // AG_CONST * cos(0)
+ Y=0; // AG_CONST * sin(0)
+ TargetAngle=abs(angle);
+ CurrAngle=0;
+
+ for (Step=0; Step < 12; Step++)
+ {
+ fixed NewX;
+
+ if(TargetAngle > CurrAngle)
+ {
+ NewX=X - (Y >> Step);
+ Y=(X >> Step) + Y;
+ X=NewX;
+ CurrAngle += Angles[Step];
+ }
+ else
+ {
+ NewX=X + (Y >> Step);
+ Y=-(X >> Step) + Y;
+ X=NewX;
+ CurrAngle -= Angles[Step];
+ }
+ }
+
+ if (angle > 0)
+ {
+ *cos = X;
+ *sin = Y;
+ }
+ else
+ {
+ *cos = X;
+ *sin = -Y;
+ }
+}
+
+
+void _reset_rx_cal(hw_data_t *phw_data)
+{
+ u32 val;
+
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ val &= 0xFFFF0000;
+ }
+ else // 2nd-cut
+ {
+ val &= 0x000003FF;
+ }
+
+ hw_set_dxx_reg(phw_data, 0x54, val);
+}
+
+
+// ************for winbond calibration*********
+//
+
+//
+//
+// *********************************************
+void _rxadc_dc_offset_cancellation_winbond(hw_data_t *phw_data, u32 frequency)
+{
+ u32 reg_agc_ctrl3;
+ u32 reg_a_acq_ctrl;
+ u32 reg_b_acq_ctrl;
+ u32 val;
+
+ PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
+ phy_init_rf(phw_data);
+
+ // set calibration channel
+ if( (RF_WB_242 == phw_data->phy_type) ||
+ (RF_WB_242_1 == phw_data->phy_type) ) // 20060619.5 Add
+ {
+ if ((frequency >= 2412) && (frequency <= 2484))
+ {
+ // w89rf242 change frequency to 2390Mhz
+ PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
+ phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
+
+ }
+ }
+ else
+ {
+
+ }
+
+ // reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel
+ hw_get_dxx_reg(phw_data, 0x5C, &val);
+ val &= ~(0x03FF);
+ hw_set_dxx_reg(phw_data, 0x5C, val);
+
+ // reset the TX and RX IQ calibration data
+ hw_set_dxx_reg(phw_data, 0x3C, 0);
+ hw_set_dxx_reg(phw_data, 0x54, 0);
+
+ hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
+
+ // a. Disable AGC
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
+ reg_agc_ctrl3 &= ~BIT(2);
+ reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
+ val |= MASK_AGC_FIX_GAIN;
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
+
+ // b. Turn off BB RX
+ hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, &reg_a_acq_ctrl);
+ reg_a_acq_ctrl |= MASK_AMER_OFF_REG;
+ hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl);
+
+ hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, &reg_b_acq_ctrl);
+ reg_b_acq_ctrl |= MASK_BMER_OFF_REG;
+ hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl);
+
+ // c. Make sure MAC is in receiving mode
+ // d. Turn ON ADC calibration
+ // - ADC calibrator is triggered by this signal rising from 0 to 1
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
+ val &= ~MASK_ADC_DC_CAL_STR;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
+
+ val |= MASK_ADC_DC_CAL_STR;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
+ pa_stall_execution(US); // *MUST* wait for a while
+
+ // e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]"
+#ifdef _DEBUG
+ hw_get_dxx_reg(phw_data, REG_OFFSET_READ, &val);
+ PHY_DEBUG(("[CAL] REG_OFFSET_READ = 0x%08X\n", val));
+
+ PHY_DEBUG(("[CAL] ** adc_dc_cal_i = %d (0x%04X)\n",
+ _s9_to_s32(val&0x000001FF), val&0x000001FF));
+ PHY_DEBUG(("[CAL] ** adc_dc_cal_q = %d (0x%04X)\n",
+ _s9_to_s32((val&0x0003FE00)>>9), (val&0x0003FE00)>>9));
+#endif
+
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
+ val &= ~MASK_ADC_DC_CAL_STR;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
+
+ // f. Turn on BB RX
+ //hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, &reg_a_acq_ctrl);
+ reg_a_acq_ctrl &= ~MASK_AMER_OFF_REG;
+ hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl);
+
+ //hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, &reg_b_acq_ctrl);
+ reg_b_acq_ctrl &= ~MASK_BMER_OFF_REG;
+ hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl);
+
+ // g. Enable AGC
+ //hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val);
+ reg_agc_ctrl3 |= BIT(2);
+ reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+}
+
+////////////////////////////////////////////////////////
+void _txidac_dc_offset_cancellation_winbond(hw_data_t *phw_data)
+{
+ u32 reg_agc_ctrl3;
+ u32 reg_mode_ctrl;
+ u32 reg_dc_cancel;
+ s32 iqcal_image_i;
+ s32 iqcal_image_q;
+ u32 sqsum;
+ s32 mag_0;
+ s32 mag_1;
+ s32 fix_cancel_dc_i = 0;
+ u32 val;
+ int loop;
+
+ PHY_DEBUG(("[CAL] -> [2]_txidac_dc_offset_cancellation()\n"));
+
+ // a. Set to "TX calibration mode"
+
+ //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
+ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
+ //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
+ phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
+ //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
+ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
+ //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
+ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
+ //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
+ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
+
+ hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
+
+ // a. Disable AGC
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
+ reg_agc_ctrl3 &= ~BIT(2);
+ reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
+ val |= MASK_AGC_FIX_GAIN;
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
+
+ // b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+
+ PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
+ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
+
+ // mode=2, tone=0
+ //reg_mode_ctrl |= (MASK_CALIB_START|2);
+
+ // mode=2, tone=1
+ //reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2));
+
+ // mode=2, tone=2
+ reg_mode_ctrl |= (MASK_CALIB_START|2|(2<<2));
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
+ PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
+
+ for (loop = 0; loop < LOOP_TIMES; loop++)
+ {
+ PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
+
+ // c.
+ // reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel
+ reg_dc_cancel &= ~(0x03FF);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
+ mag_0 = (s32) _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
+ mag_0, iqcal_image_i, iqcal_image_q));
+
+ // d.
+ reg_dc_cancel |= (1 << CANCEL_DC_I_SHIFT);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
+ mag_1 = (s32) _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
+ mag_1, iqcal_image_i, iqcal_image_q));
+
+ // e. Calculate the correct DC offset cancellation value for I
+ if (mag_0 != mag_1)
+ {
+ fix_cancel_dc_i = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
+ }
+ else
+ {
+ if (mag_0 == mag_1)
+ {
+ PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n"));
+ }
+
+ fix_cancel_dc_i = 0;
+ }
+
+ PHY_DEBUG(("[CAL] ** fix_cancel_dc_i = %d (0x%04X)\n",
+ fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i)));
+
+ if ((abs(mag_1-mag_0)*6) > mag_0)
+ {
+ break;
+ }
+ }
+
+ if ( loop >= 19 )
+ fix_cancel_dc_i = 0;
+
+ reg_dc_cancel &= ~(0x03FF);
+ reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT);
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+
+ // g.
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+}
+
+///////////////////////////////////////////////////////
+void _txqdac_dc_offset_cacellation_winbond(hw_data_t *phw_data)
+{
+ u32 reg_agc_ctrl3;
+ u32 reg_mode_ctrl;
+ u32 reg_dc_cancel;
+ s32 iqcal_image_i;
+ s32 iqcal_image_q;
+ u32 sqsum;
+ s32 mag_0;
+ s32 mag_1;
+ s32 fix_cancel_dc_q = 0;
+ u32 val;
+ int loop;
+
+ PHY_DEBUG(("[CAL] -> [3]_txqdac_dc_offset_cacellation()\n"));
+ //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
+ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
+ //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
+ phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
+ //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
+ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
+ //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
+ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
+ //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
+ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
+
+ hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
+
+ // a. Disable AGC
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
+ reg_agc_ctrl3 &= ~BIT(2);
+ reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
+ val |= MASK_AGC_FIX_GAIN;
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
+
+ // a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
+
+ //reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
+ reg_mode_ctrl &= ~(MASK_IQCAL_MODE);
+ reg_mode_ctrl |= (MASK_CALIB_START|3);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
+ PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
+
+ for (loop = 0; loop < LOOP_TIMES; loop++)
+ {
+ PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
+
+ // b.
+ // reset cancel_dc_q[4:0] in register DC_Cancel
+ reg_dc_cancel &= ~(0x001F);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+ pa_stall_execution(US);
+
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
+ mag_0 = _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
+ mag_0, iqcal_image_i, iqcal_image_q));
+
+ // c.
+ reg_dc_cancel |= (1 << CANCEL_DC_Q_SHIFT);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ pa_stall_execution(US);
+
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+ pa_stall_execution(US);
+
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
+ mag_1 = _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
+ mag_1, iqcal_image_i, iqcal_image_q));
+
+ // d. Calculate the correct DC offset cancellation value for I
+ if (mag_0 != mag_1)
+ {
+ fix_cancel_dc_q = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
+ }
+ else
+ {
+ if (mag_0 == mag_1)
+ {
+ PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n"));
+ }
+
+ fix_cancel_dc_q = 0;
+ }
+
+ PHY_DEBUG(("[CAL] ** fix_cancel_dc_q = %d (0x%04X)\n",
+ fix_cancel_dc_q, _s32_to_s5(fix_cancel_dc_q)));
+
+ if ((abs(mag_1-mag_0)*6) > mag_0)
+ {
+ break;
+ }
+ }
+
+ if ( loop >= 19 )
+ fix_cancel_dc_q = 0;
+
+ reg_dc_cancel &= ~(0x001F);
+ reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT);
+ hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
+ PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
+
+
+ // f.
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+}
+
+//20060612.1.a 20060718.1 Modify
+u8 _tx_iq_calibration_loop_winbond(hw_data_t *phw_data,
+ s32 a_2_threshold,
+ s32 b_2_threshold)
+{
+ u32 reg_mode_ctrl;
+ s32 iq_mag_0_tx;
+ s32 iqcal_tone_i0;
+ s32 iqcal_tone_q0;
+ s32 iqcal_tone_i;
+ s32 iqcal_tone_q;
+ u32 sqsum;
+ s32 rot_i_b;
+ s32 rot_q_b;
+ s32 tx_cal_flt_b[4];
+ s32 tx_cal[4];
+ s32 tx_cal_reg[4];
+ s32 a_2, b_2;
+ s32 sin_b, sin_2b;
+ s32 cos_b, cos_2b;
+ s32 divisor;
+ s32 temp1, temp2;
+ u32 val;
+ u16 loop;
+ s32 iqcal_tone_i_avg,iqcal_tone_q_avg;
+ u8 verify_count;
+ int capture_time;
+
+ PHY_DEBUG(("[CAL] -> _tx_iq_calibration_loop()\n"));
+ PHY_DEBUG(("[CAL] ** a_2_threshold = %d\n", a_2_threshold));
+ PHY_DEBUG(("[CAL] ** b_2_threshold = %d\n", b_2_threshold));
+
+ verify_count = 0;
+
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
+
+ loop = LOOP_TIMES;
+
+ while (loop > 0)
+ {
+ PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+
+ iqcal_tone_i_avg=0;
+ iqcal_tone_q_avg=0;
+ if( !hw_set_dxx_reg(phw_data, 0x3C, 0x00) ) // 20060718.1 modify
+ return 0;
+ for(capture_time=0;capture_time<10;capture_time++)
+ {
+ // a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
+ // enable "IQ alibration Mode II"
+ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
+ reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+ reg_mode_ctrl |= (MASK_CALIB_START|0x02);
+ reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ // b.
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
+ pa_stall_execution(US);
+
+ iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF);
+ iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n",
+ iqcal_tone_i0, iqcal_tone_q0));
+
+ sqsum = iqcal_tone_i0*iqcal_tone_i0 +
+ iqcal_tone_q0*iqcal_tone_q0;
+ iq_mag_0_tx = (s32) _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] ** iq_mag_0_tx=%d\n", iq_mag_0_tx));
+
+ // c. Set "calib_start" to 0x0
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ // d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to
+ // enable "IQ alibration Mode II"
+ //hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+ reg_mode_ctrl |= (MASK_CALIB_START|0x03);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ // e.
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
+ pa_stall_execution(US);
+
+ iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
+ iqcal_tone_i, iqcal_tone_q));
+ if( capture_time == 0)
+ {
+ continue;
+ }
+ else
+ {
+ iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time;
+ iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time;
+ }
+ }
+
+ iqcal_tone_i = iqcal_tone_i_avg;
+ iqcal_tone_q = iqcal_tone_q_avg;
+
+
+ rot_i_b = (iqcal_tone_i * iqcal_tone_i0 +
+ iqcal_tone_q * iqcal_tone_q0) / 1024;
+ rot_q_b = (iqcal_tone_i * iqcal_tone_q0 * (-1) +
+ iqcal_tone_q * iqcal_tone_i0) / 1024;
+ PHY_DEBUG(("[CAL] ** rot_i_b = %d, rot_q_b = %d\n",
+ rot_i_b, rot_q_b));
+
+ // f.
+ divisor = ((iq_mag_0_tx * iq_mag_0_tx * 2)/1024 - rot_i_b) * 2;
+
+ if (divisor == 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n"));
+ PHY_DEBUG(("[CAL] ** divisor=0 to calculate EPS and THETA !!\n"));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+ break;
+ }
+
+ a_2 = (rot_i_b * 32768) / divisor;
+ b_2 = (rot_q_b * (-32768)) / divisor;
+ PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2));
+ PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2));
+
+ phw_data->iq_rsdl_gain_tx_d2 = a_2;
+ phw_data->iq_rsdl_phase_tx_d2 = b_2;
+
+ //if ((abs(a_2) < 150) && (abs(b_2) < 100))
+ //if ((abs(a_2) < 200) && (abs(b_2) < 200))
+ if ((abs(a_2) < a_2_threshold) && (abs(b_2) < b_2_threshold))
+ {
+ verify_count++;
+
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n"));
+ PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+
+ if (verify_count > 2)
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION (EPS,THETA) OK !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ return 0;
+ }
+
+ continue;
+ }
+ else
+ {
+ verify_count = 0;
+ }
+
+ _sin_cos(b_2, &sin_b, &cos_b);
+ _sin_cos(b_2*2, &sin_2b, &cos_2b);
+ PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b));
+ PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b));
+
+ if (cos_2b == 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n"));
+ PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n"));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+ break;
+ }
+
+ // 1280 * 32768 = 41943040
+ temp1 = (41943040/cos_2b)*cos_b;
+
+ //temp2 = (41943040/cos_2b)*sin_b*(-1);
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ temp2 = (41943040/cos_2b)*sin_b*(-1);
+ }
+ else // 2nd-cut
+ {
+ temp2 = (41943040*4/cos_2b)*sin_b*(-1);
+ }
+
+ tx_cal_flt_b[0] = _floor(temp1/(32768+a_2));
+ tx_cal_flt_b[1] = _floor(temp2/(32768+a_2));
+ tx_cal_flt_b[2] = _floor(temp2/(32768-a_2));
+ tx_cal_flt_b[3] = _floor(temp1/(32768-a_2));
+ PHY_DEBUG(("[CAL] ** tx_cal_flt_b[0] = %d\n", tx_cal_flt_b[0]));
+ PHY_DEBUG(("[CAL] tx_cal_flt_b[1] = %d\n", tx_cal_flt_b[1]));
+ PHY_DEBUG(("[CAL] tx_cal_flt_b[2] = %d\n", tx_cal_flt_b[2]));
+ PHY_DEBUG(("[CAL] tx_cal_flt_b[3] = %d\n", tx_cal_flt_b[3]));
+
+ tx_cal[2] = tx_cal_flt_b[2];
+ tx_cal[2] = tx_cal[2] +3;
+ tx_cal[1] = tx_cal[2];
+ tx_cal[3] = tx_cal_flt_b[3] - 128;
+ tx_cal[0] = -tx_cal[3]+1;
+
+ PHY_DEBUG(("[CAL] tx_cal[0] = %d\n", tx_cal[0]));
+ PHY_DEBUG(("[CAL] tx_cal[1] = %d\n", tx_cal[1]));
+ PHY_DEBUG(("[CAL] tx_cal[2] = %d\n", tx_cal[2]));
+ PHY_DEBUG(("[CAL] tx_cal[3] = %d\n", tx_cal[3]));
+
+ //if ((tx_cal[0] == 0) && (tx_cal[1] == 0) &&
+ // (tx_cal[2] == 0) && (tx_cal[3] == 0))
+ //{
+ // PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n"));
+ // PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION COMPLETE !!\n"));
+ // PHY_DEBUG(("[CAL] ******************************************\n"));
+ // return 0;
+ //}
+
+ // g.
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
+ tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28);
+ tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24);
+ tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20);
+ tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val));
+ tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
+ tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
+ tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
+ tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
+
+ }
+
+ PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3]));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ if (((tx_cal_reg[0]==7) || (tx_cal_reg[0]==(-8))) &&
+ ((tx_cal_reg[3]==7) || (tx_cal_reg[3]==(-8))))
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ break;
+ }
+ }
+ else // 2nd-cut
+ {
+ if (((tx_cal_reg[0]==31) || (tx_cal_reg[0]==(-32))) &&
+ ((tx_cal_reg[3]==31) || (tx_cal_reg[3]==(-32))))
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ break;
+ }
+ }
+
+ tx_cal[0] = tx_cal[0] + tx_cal_reg[0];
+ tx_cal[1] = tx_cal[1] + tx_cal_reg[1];
+ tx_cal[2] = tx_cal[2] + tx_cal_reg[2];
+ tx_cal[3] = tx_cal[3] + tx_cal_reg[3];
+ PHY_DEBUG(("[CAL] ** apply tx_cal[0] = %d\n", tx_cal[0]));
+ PHY_DEBUG(("[CAL] apply tx_cal[1] = %d\n", tx_cal[1]));
+ PHY_DEBUG(("[CAL] apply tx_cal[2] = %d\n", tx_cal[2]));
+ PHY_DEBUG(("[CAL] apply tx_cal[3] = %d\n", tx_cal[3]));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ val &= 0x0000FFFF;
+ val |= ((_s32_to_s4(tx_cal[0]) << 28)|
+ (_s32_to_s4(tx_cal[1]) << 24)|
+ (_s32_to_s4(tx_cal[2]) << 20)|
+ (_s32_to_s4(tx_cal[3]) << 16));
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val));
+ return 0;
+ }
+ else // 2nd-cut
+ {
+ val &= 0x000003FF;
+ val |= ((_s32_to_s5(tx_cal[0]) << 27)|
+ (_s32_to_s6(tx_cal[1]) << 21)|
+ (_s32_to_s6(tx_cal[2]) << 15)|
+ (_s32_to_s5(tx_cal[3]) << 10));
+ hw_set_dxx_reg(phw_data, 0x3C, val);
+ PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION = 0x%08X\n", val));
+ return 0;
+ }
+
+ // i. Set "calib_start" to 0x0
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+
+ loop--;
+ }
+
+ return 1;
+}
+
+void _tx_iq_calibration_winbond(hw_data_t *phw_data)
+{
+ u32 reg_agc_ctrl3;
+#ifdef _DEBUG
+ s32 tx_cal_reg[4];
+
+#endif
+ u32 reg_mode_ctrl;
+ u32 val;
+ u8 result;
+
+ PHY_DEBUG(("[CAL] -> [4]_tx_iq_calibration()\n"));
+
+ //0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
+ phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
+ //0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
+ phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); // 20060612.1.a 0x1905D6);
+ //0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
+ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); //0x24C60A (high temperature)
+ //0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
+ phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); // 20060612.1.a 0x06890C);
+ //0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
+ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
+ //; [BB-chip]: Calibration (6f).Send test pattern
+ //; [BB-chip]: Calibration (6g). Search RXGCL optimal value
+ //; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table
+ //phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
+
+ OS_SLEEP(30000); // 20060612.1.a 30ms delay. Add the follow 2 lines
+ //To adjust TXVGA to fit iq_mag_0 range from 1250 ~ 1750
+ adjust_TXVGA_for_iq_mag( phw_data );
+
+ // a. Disable AGC
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
+ reg_agc_ctrl3 &= ~BIT(2);
+ reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+
+ hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
+ val |= MASK_AGC_FIX_GAIN;
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
+
+ result = _tx_iq_calibration_loop_winbond(phw_data, 150, 100);
+
+ if (result > 0)
+ {
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ val &= 0x0000FFFF;
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ val &= 0x000003FF;
+ hw_set_dxx_reg(phw_data, 0x3C, val);
+ }
+
+ result = _tx_iq_calibration_loop_winbond(phw_data, 300, 200);
+
+ if (result > 0)
+ {
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ val &= 0x0000FFFF;
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ val &= 0x000003FF;
+ hw_set_dxx_reg(phw_data, 0x3C, val);
+ }
+
+ result = _tx_iq_calibration_loop_winbond(phw_data, 500, 400);
+ if (result > 0)
+ {
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ val &= 0x0000FFFF;
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ val &= 0x000003FF;
+ hw_set_dxx_reg(phw_data, 0x3C, val);
+ }
+
+
+ result = _tx_iq_calibration_loop_winbond(phw_data, 700, 500);
+
+ if (result > 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_tx_iq_calibration> **************\n"));
+ PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION FAILURE !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ val &= 0x0000FFFF;
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ val &= 0x000003FF;
+ hw_set_dxx_reg(phw_data, 0x3C, val);
+ }
+ }
+ }
+ }
+ }
+
+ // i. Set "calib_start" to 0x0
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+
+ // g. Enable AGC
+ //hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val);
+ reg_agc_ctrl3 |= BIT(2);
+ reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
+ hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
+
+#ifdef _DEBUG
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
+ tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28);
+ tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24);
+ tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20);
+ tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16);
+ }
+ else // 2nd-cut
+ {
+ hw_get_dxx_reg(phw_data, 0x3C, &val);
+ PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val));
+ tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
+ tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
+ tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
+ tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
+
+ }
+
+ PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2]));
+ PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3]));
+#endif
+
+
+ // for test - BEN
+ // RF Control Override
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+u8 _rx_iq_calibration_loop_winbond(hw_data_t *phw_data, u16 factor, u32 frequency)
+{
+ u32 reg_mode_ctrl;
+ s32 iqcal_tone_i;
+ s32 iqcal_tone_q;
+ s32 iqcal_image_i;
+ s32 iqcal_image_q;
+ s32 rot_tone_i_b;
+ s32 rot_tone_q_b;
+ s32 rot_image_i_b;
+ s32 rot_image_q_b;
+ s32 rx_cal_flt_b[4];
+ s32 rx_cal[4];
+ s32 rx_cal_reg[4];
+ s32 a_2, b_2;
+ s32 sin_b, sin_2b;
+ s32 cos_b, cos_2b;
+ s32 temp1, temp2;
+ u32 val;
+ u16 loop;
+
+ u32 pwr_tone;
+ u32 pwr_image;
+ u8 verify_count;
+
+ s32 iqcal_tone_i_avg,iqcal_tone_q_avg;
+ s32 iqcal_image_i_avg,iqcal_image_q_avg;
+ u16 capture_time;
+
+ PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration_loop()\n"));
+ PHY_DEBUG(("[CAL] ** factor = %d\n", factor));
+
+
+// RF Control Override
+ hw_get_cxx_reg(phw_data, 0x80, &val);
+ val |= BIT(19);
+ hw_set_cxx_reg(phw_data, 0x80, val);
+
+// RF_Ctrl
+ hw_get_cxx_reg(phw_data, 0xE4, &val);
+ val |= BIT(0);
+ hw_set_cxx_reg(phw_data, 0xE4, val);
+ PHY_DEBUG(("[CAL] ** RF_CTRL(0xE4) = 0x%08X", val));
+
+ hw_set_dxx_reg(phw_data, 0x58, 0x44444444); // IQ_Alpha
+
+ // b.
+
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
+
+ verify_count = 0;
+
+ //for (loop = 0; loop < 1; loop++)
+ //for (loop = 0; loop < LOOP_TIMES; loop++)
+ loop = LOOP_TIMES;
+ while (loop > 0)
+ {
+ PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+ iqcal_tone_i_avg=0;
+ iqcal_tone_q_avg=0;
+ iqcal_image_i_avg=0;
+ iqcal_image_q_avg=0;
+ capture_time=0;
+
+ for(capture_time=0; capture_time<10; capture_time++)
+ {
+ // i. Set "calib_start" to 0x0
+ reg_mode_ctrl &= ~MASK_CALIB_START;
+ if( !hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl) )//20060718.1 modify
+ return 0;
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US);
+
+ reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+ reg_mode_ctrl |= (MASK_CALIB_START|0x1);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+ pa_stall_execution(US); //Should be read out after 450us
+
+ // c.
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
+
+ iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
+ iqcal_tone_i, iqcal_tone_q));
+
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+ PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
+
+ iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+ iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n",
+ iqcal_image_i, iqcal_image_q));
+ if( capture_time == 0)
+ {
+ continue;
+ }
+ else
+ {
+ iqcal_image_i_avg=( iqcal_image_i_avg*(capture_time-1) +iqcal_image_i)/capture_time;
+ iqcal_image_q_avg=( iqcal_image_q_avg*(capture_time-1) +iqcal_image_q)/capture_time;
+ iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time;
+ iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time;
+ }
+ }
+
+
+ iqcal_image_i = iqcal_image_i_avg;
+ iqcal_image_q = iqcal_image_q_avg;
+ iqcal_tone_i = iqcal_tone_i_avg;
+ iqcal_tone_q = iqcal_tone_q_avg;
+
+ // d.
+ rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i +
+ iqcal_tone_q * iqcal_tone_q) / 1024;
+ rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) +
+ iqcal_tone_q * iqcal_tone_i) / 1024;
+ rot_image_i_b = (iqcal_image_i * iqcal_tone_i -
+ iqcal_image_q * iqcal_tone_q) / 1024;
+ rot_image_q_b = (iqcal_image_i * iqcal_tone_q +
+ iqcal_image_q * iqcal_tone_i) / 1024;
+
+ PHY_DEBUG(("[CAL] ** rot_tone_i_b = %d\n", rot_tone_i_b));
+ PHY_DEBUG(("[CAL] ** rot_tone_q_b = %d\n", rot_tone_q_b));
+ PHY_DEBUG(("[CAL] ** rot_image_i_b = %d\n", rot_image_i_b));
+ PHY_DEBUG(("[CAL] ** rot_image_q_b = %d\n", rot_image_q_b));
+
+ // f.
+ if (rot_tone_i_b == 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n"));
+ PHY_DEBUG(("[CAL] ** rot_tone_i_b=0 to calculate EPS and THETA !!\n"));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+ break;
+ }
+
+ a_2 = (rot_image_i_b * 32768) / rot_tone_i_b -
+ phw_data->iq_rsdl_gain_tx_d2;
+ b_2 = (rot_image_q_b * 32768) / rot_tone_i_b -
+ phw_data->iq_rsdl_phase_tx_d2;
+
+ PHY_DEBUG(("[CAL] ** iq_rsdl_gain_tx_d2 = %d\n", phw_data->iq_rsdl_gain_tx_d2));
+ PHY_DEBUG(("[CAL] ** iq_rsdl_phase_tx_d2= %d\n", phw_data->iq_rsdl_phase_tx_d2));
+ PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2));
+ PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2));
+
+ _sin_cos(b_2, &sin_b, &cos_b);
+ _sin_cos(b_2*2, &sin_2b, &cos_2b);
+ PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b));
+ PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b));
+
+ if (cos_2b == 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n"));
+ PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n"));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+ break;
+ }
+
+ // 1280 * 32768 = 41943040
+ temp1 = (41943040/cos_2b)*cos_b;
+
+ //temp2 = (41943040/cos_2b)*sin_b*(-1);
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ temp2 = (41943040/cos_2b)*sin_b*(-1);
+ }
+ else // 2nd-cut
+ {
+ temp2 = (41943040*4/cos_2b)*sin_b*(-1);
+ }
+
+ rx_cal_flt_b[0] = _floor(temp1/(32768+a_2));
+ rx_cal_flt_b[1] = _floor(temp2/(32768-a_2));
+ rx_cal_flt_b[2] = _floor(temp2/(32768+a_2));
+ rx_cal_flt_b[3] = _floor(temp1/(32768-a_2));
+
+ PHY_DEBUG(("[CAL] ** rx_cal_flt_b[0] = %d\n", rx_cal_flt_b[0]));
+ PHY_DEBUG(("[CAL] rx_cal_flt_b[1] = %d\n", rx_cal_flt_b[1]));
+ PHY_DEBUG(("[CAL] rx_cal_flt_b[2] = %d\n", rx_cal_flt_b[2]));
+ PHY_DEBUG(("[CAL] rx_cal_flt_b[3] = %d\n", rx_cal_flt_b[3]));
+
+ rx_cal[0] = rx_cal_flt_b[0] - 128;
+ rx_cal[1] = rx_cal_flt_b[1];
+ rx_cal[2] = rx_cal_flt_b[2];
+ rx_cal[3] = rx_cal_flt_b[3] - 128;
+ PHY_DEBUG(("[CAL] ** rx_cal[0] = %d\n", rx_cal[0]));
+ PHY_DEBUG(("[CAL] rx_cal[1] = %d\n", rx_cal[1]));
+ PHY_DEBUG(("[CAL] rx_cal[2] = %d\n", rx_cal[2]));
+ PHY_DEBUG(("[CAL] rx_cal[3] = %d\n", rx_cal[3]));
+
+ // e.
+ pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q);
+ pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor;
+
+ PHY_DEBUG(("[CAL] ** pwr_tone = %d\n", pwr_tone));
+ PHY_DEBUG(("[CAL] ** pwr_image = %d\n", pwr_image));
+
+ if (pwr_tone > pwr_image)
+ {
+ verify_count++;
+
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *************\n"));
+ PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count));
+ PHY_DEBUG(("[CAL] ******************************************\n"));
+
+ if (verify_count > 2)
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION OK !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ return 0;
+ }
+
+ continue;
+ }
+ // g.
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12);
+ rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8);
+ rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4);
+ rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F));
+ }
+ else // 2nd-cut
+ {
+ rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
+ rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
+ rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
+ rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
+ }
+
+ PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3]));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ if (((rx_cal_reg[0]==7) || (rx_cal_reg[0]==(-8))) &&
+ ((rx_cal_reg[3]==7) || (rx_cal_reg[3]==(-8))))
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ break;
+ }
+ }
+ else // 2nd-cut
+ {
+ if (((rx_cal_reg[0]==31) || (rx_cal_reg[0]==(-32))) &&
+ ((rx_cal_reg[3]==31) || (rx_cal_reg[3]==(-32))))
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
+ PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ break;
+ }
+ }
+
+ rx_cal[0] = rx_cal[0] + rx_cal_reg[0];
+ rx_cal[1] = rx_cal[1] + rx_cal_reg[1];
+ rx_cal[2] = rx_cal[2] + rx_cal_reg[2];
+ rx_cal[3] = rx_cal[3] + rx_cal_reg[3];
+ PHY_DEBUG(("[CAL] ** apply rx_cal[0] = %d\n", rx_cal[0]));
+ PHY_DEBUG(("[CAL] apply rx_cal[1] = %d\n", rx_cal[1]));
+ PHY_DEBUG(("[CAL] apply rx_cal[2] = %d\n", rx_cal[2]));
+ PHY_DEBUG(("[CAL] apply rx_cal[3] = %d\n", rx_cal[3]));
+
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ val &= 0x0000FFFF;
+ val |= ((_s32_to_s4(rx_cal[0]) << 12)|
+ (_s32_to_s4(rx_cal[1]) << 8)|
+ (_s32_to_s4(rx_cal[2]) << 4)|
+ (_s32_to_s4(rx_cal[3])));
+ hw_set_dxx_reg(phw_data, 0x54, val);
+ }
+ else // 2nd-cut
+ {
+ val &= 0x000003FF;
+ val |= ((_s32_to_s5(rx_cal[0]) << 27)|
+ (_s32_to_s6(rx_cal[1]) << 21)|
+ (_s32_to_s6(rx_cal[2]) << 15)|
+ (_s32_to_s5(rx_cal[3]) << 10));
+ hw_set_dxx_reg(phw_data, 0x54, val);
+
+ if( loop == 3 )
+ return 0;
+ }
+ PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val));
+
+ loop--;
+ }
+
+ return 1;
+}
+
+//////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////
+void _rx_iq_calibration_winbond(hw_data_t *phw_data, u32 frequency)
+{
+// figo 20050523 marked thsi flag for can't compile for relesase
+#ifdef _DEBUG
+ s32 rx_cal_reg[4];
+ u32 val;
+#endif
+
+ u8 result;
+
+ PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration()\n"));
+// a. Set RFIC to "RX calibration mode"
+ //; ----- Calibration (7). RX path IQ imbalance calibration loop
+ // 0x01 0xFFBFC2 ; 3FEFF ; Calibration (7a). enable RX IQ calibration loop circuits
+ phy_set_rf_data(phw_data, 1, (1<<24)|0xEFBFC2);
+ // 0x0B 0x1A01D6 ; 06817 ; Calibration (7b). enable RX I/Q cal loop SW1 circuit
+ phy_set_rf_data(phw_data, 11, (11<<24)|0x1A05D6);
+ //0x05 0x24848A ; 09212 ; Calibration (7c). setting TX-VGA gain (TXGCH) to 2 --> to be optimized
+ phy_set_rf_data(phw_data, 5, (5<<24)| phw_data->txvga_setting_for_cal);
+ //0x06 0x06840C ; 01A10 ; Calibration (7d). RXGCH=00; RXGCL=010 000 (RXVGA) --> to be optimized
+ phy_set_rf_data(phw_data, 6, (6<<24)|0x06834C);
+ //0x00 0xFFF1C0 ; 3F7C7 ; Calibration (7e). turn on IQ imbalance/Test mode
+ phy_set_rf_data(phw_data, 0, (0<<24)|0xFFF1C0);
+
+ // ; [BB-chip]: Calibration (7f). Send test pattern
+ // ; [BB-chip]: Calibration (7g). Search RXGCL optimal value
+ // ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table
+
+ result = _rx_iq_calibration_loop_winbond(phw_data, 12589, frequency);
+
+ if (result > 0)
+ {
+ _reset_rx_cal(phw_data);
+ result = _rx_iq_calibration_loop_winbond(phw_data, 7943, frequency);
+
+ if (result > 0)
+ {
+ _reset_rx_cal(phw_data);
+ result = _rx_iq_calibration_loop_winbond(phw_data, 5011, frequency);
+
+ if (result > 0)
+ {
+ PHY_DEBUG(("[CAL] ** <_rx_iq_calibration> **************\n"));
+ PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION FAILURE !!\n"));
+ PHY_DEBUG(("[CAL] **************************************\n"));
+ _reset_rx_cal(phw_data);
+ }
+ }
+ }
+
+#ifdef _DEBUG
+ hw_get_dxx_reg(phw_data, 0x54, &val);
+ PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
+
+ if (phw_data->revision == 0x2002) // 1st-cut
+ {
+ rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12);
+ rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8);
+ rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4);
+ rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F));
+ }
+ else // 2nd-cut
+ {
+ rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
+ rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
+ rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
+ rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
+ }
+
+ PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2]));
+ PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3]));
+#endif
+
+}
+
+////////////////////////////////////////////////////////////////////////
+void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency)
+{
+ u32 reg_mode_ctrl;
+ u32 iq_alpha;
+
+ PHY_DEBUG(("[CAL] -> phy_calibration_winbond()\n"));
+
+ // 20040701 1.1.25.1000 kevin
+ hw_get_cxx_reg(phw_data, 0x80, &mac_ctrl);
+ hw_get_cxx_reg(phw_data, 0xE4, &rf_ctrl);
+ hw_get_dxx_reg(phw_data, 0x58, &iq_alpha);
+
+
+
+ _rxadc_dc_offset_cancellation_winbond(phw_data, frequency);
+ //_txidac_dc_offset_cancellation_winbond(phw_data);
+ //_txqdac_dc_offset_cacellation_winbond(phw_data);
+
+ _tx_iq_calibration_winbond(phw_data);
+ _rx_iq_calibration_winbond(phw_data, frequency);
+
+ //------------------------------------------------------------------------
+ hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
+ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE|MASK_CALIB_START); // set when finish
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+
+ // i. Set RFIC to "Normal mode"
+ hw_set_cxx_reg(phw_data, 0x80, mac_ctrl);
+ hw_set_cxx_reg(phw_data, 0xE4, rf_ctrl);
+ hw_set_dxx_reg(phw_data, 0x58, iq_alpha);
+
+
+ //------------------------------------------------------------------------
+ phy_init_rf(phw_data);
+
+}
+
+//===========================
+void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value )
+{
+ u32 ltmp=0;
+
+ switch( pHwData->phy_type )
+ {
+ case RF_MAXIM_2825:
+ case RF_MAXIM_V1: // 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331)
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
+ break;
+
+ case RF_MAXIM_2827:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
+ break;
+
+ case RF_MAXIM_2828:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
+ break;
+
+ case RF_MAXIM_2829:
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
+ break;
+
+ case RF_AIROHA_2230:
+ case RF_AIROHA_2230S: // 20060420 Add this
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( value, 20 );
+ break;
+
+ case RF_AIROHA_7230:
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1: // 20060619.5 Add
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( value, 24 );
+ break;
+ }
+
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+}
+
+// 20060717 modify as Bruce's mail
+unsigned char adjust_TXVGA_for_iq_mag(hw_data_t *phw_data)
+{
+ int init_txvga = 0;
+ u32 reg_mode_ctrl;
+ u32 val;
+ s32 iqcal_tone_i0;
+ s32 iqcal_tone_q0;
+ u32 sqsum;
+ s32 iq_mag_0_tx;
+ u8 reg_state;
+ int current_txvga;
+
+
+ reg_state = 0;
+ for( init_txvga=0; init_txvga<10; init_txvga++)
+ {
+ current_txvga = ( 0x24C40A|(init_txvga<<6) );
+ phy_set_rf_data(phw_data, 5, ((5<<24)|current_txvga) );
+ phw_data->txvga_setting_for_cal = current_txvga;
+
+ //pa_stall_execution(30000);//Sleep(30);
+ OS_SLEEP(30000); // 20060612.1.a
+
+ if( !hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl) ) // 20060718.1 modify
+ return FALSE;
+
+ PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
+
+ // a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
+ // enable "IQ alibration Mode II"
+ reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
+ reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+ reg_mode_ctrl |= (MASK_CALIB_START|0x02);
+ reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2);
+ hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+ PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+
+ //pa_stall_execution(US);
+ OS_SLEEP(1); // 20060612.1.a
+
+ //pa_stall_execution(300);//Sleep(30);
+ OS_SLEEP(300); // 20060612.1.a
+
+ // b.
+ hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+
+ PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
+ //pa_stall_execution(US);
+ //pa_stall_execution(300);//Sleep(30);
+ OS_SLEEP(300); // 20060612.1.a
+
+ iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF);
+ iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13);
+ PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n",
+ iqcal_tone_i0, iqcal_tone_q0));
+
+ sqsum = iqcal_tone_i0*iqcal_tone_i0 + iqcal_tone_q0*iqcal_tone_q0;
+ iq_mag_0_tx = (s32) _sqrt(sqsum);
+ PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx));
+
+ if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 )
+ break;
+ else if(iq_mag_0_tx > 1750)
+ {
+ init_txvga=-2;
+ continue;
+ }
+ else
+ continue;
+
+ }
+
+ if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+
diff --git a/drivers/staging/winbond/phy_calibration.h b/drivers/staging/winbond/phy_calibration.h
new file mode 100644
index 00000000000..b6a65d31301
--- /dev/null
+++ b/drivers/staging/winbond/phy_calibration.h
@@ -0,0 +1,101 @@
+// 20031229 Turbo add
+#define REG_AGC_CTRL1 0x1000
+#define REG_AGC_CTRL2 0x1004
+#define REG_AGC_CTRL3 0x1008
+#define REG_AGC_CTRL4 0x100C
+#define REG_AGC_CTRL5 0x1010
+#define REG_AGC_CTRL6 0x1014
+#define REG_AGC_CTRL7 0x1018
+#define REG_AGC_CTRL8 0x101C
+#define REG_AGC_CTRL9 0x1020
+#define REG_AGC_CTRL10 0x1024
+#define REG_CCA_CTRL 0x1028
+#define REG_A_ACQ_CTRL 0x102C
+#define REG_B_ACQ_CTRL 0x1030
+#define REG_A_TXRX_CTRL 0x1034
+#define REG_B_TXRX_CTRL 0x1038
+#define REG_A_TX_COEF3 0x103C
+#define REG_A_TX_COEF2 0x1040
+#define REG_A_TX_COEF1 0x1044
+#define REG_B_TX_COEF2 0x1048
+#define REG_B_TX_COEF1 0x104C
+#define REG_MODE_CTRL 0x1050
+#define REG_CALIB_DATA 0x1054
+#define REG_IQ_ALPHA 0x1058
+#define REG_DC_CANCEL 0x105C
+#define REG_WTO_READ 0x1060
+#define REG_OFFSET_READ 0x1064
+#define REG_CALIB_READ1 0x1068
+#define REG_CALIB_READ2 0x106C
+#define REG_A_FREQ_EST 0x1070
+
+
+
+
+// 20031101 Turbo add
+#define MASK_AMER_OFF_REG BIT(31)
+
+#define MASK_BMER_OFF_REG BIT(31)
+
+#define MASK_LNA_FIX_GAIN (BIT(3)|BIT(4))
+#define MASK_AGC_FIX BIT(1)
+
+#define MASK_AGC_FIX_GAIN 0xFF00
+
+#define MASK_ADC_DC_CAL_STR BIT(10)
+#define MASK_CALIB_START BIT(4)
+#define MASK_IQCAL_TONE_SEL (BIT(3)|BIT(2))
+#define MASK_IQCAL_MODE (BIT(1)|BIT(0))
+
+#define MASK_TX_CAL_0 0xF0000000
+#define TX_CAL_0_SHIFT 28
+#define MASK_TX_CAL_1 0x0F000000
+#define TX_CAL_1_SHIFT 24
+#define MASK_TX_CAL_2 0x00F00000
+#define TX_CAL_2_SHIFT 20
+#define MASK_TX_CAL_3 0x000F0000
+#define TX_CAL_3_SHIFT 16
+#define MASK_RX_CAL_0 0x0000F000
+#define RX_CAL_0_SHIFT 12
+#define MASK_RX_CAL_1 0x00000F00
+#define RX_CAL_1_SHIFT 8
+#define MASK_RX_CAL_2 0x000000F0
+#define RX_CAL_2_SHIFT 4
+#define MASK_RX_CAL_3 0x0000000F
+#define RX_CAL_3_SHIFT 0
+
+#define MASK_CANCEL_DC_I 0x3E0
+#define CANCEL_DC_I_SHIFT 5
+#define MASK_CANCEL_DC_Q 0x01F
+#define CANCEL_DC_Q_SHIFT 0
+
+// LA20040210 kevin
+//#define MASK_ADC_DC_CAL_I(x) (((x)&0x1FE00)>>9)
+//#define MASK_ADC_DC_CAL_Q(x) ((x)&0x1FF)
+#define MASK_ADC_DC_CAL_I(x) (((x)&0x0003FE00)>>9)
+#define MASK_ADC_DC_CAL_Q(x) ((x)&0x000001FF)
+
+// LA20040210 kevin (Turbo has wrong definition)
+//#define MASK_IQCAL_TONE_I 0x7FFC000
+//#define SHIFT_IQCAL_TONE_I(x) ((x)>>13)
+//#define MASK_IQCAL_TONE_Q 0x1FFF
+//#define SHIFT_IQCAL_TONE_Q(x) ((x)>>0)
+#define MASK_IQCAL_TONE_I 0x00001FFF
+#define SHIFT_IQCAL_TONE_I(x) ((x)>>0)
+#define MASK_IQCAL_TONE_Q 0x03FFE000
+#define SHIFT_IQCAL_TONE_Q(x) ((x)>>13)
+
+// LA20040210 kevin (Turbo has wrong definition)
+//#define MASK_IQCAL_IMAGE_I 0x7FFC000
+//#define SHIFT_IQCAL_IMAGE_I(x) ((x)>>13)
+//#define MASK_IQCAL_IMAGE_Q 0x1FFF
+//#define SHIFT_IQCAL_IMAGE_Q(x) ((x)>>0)
+
+//#define MASK_IQCAL_IMAGE_I 0x00001FFF
+//#define SHIFT_IQCAL_IMAGE_I(x) ((x)>>0)
+//#define MASK_IQCAL_IMAGE_Q 0x03FFE000
+//#define SHIFT_IQCAL_IMAGE_Q(x) ((x)>>13)
+
+void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value );
+#define phy_init_rf( _A ) //RFSynthesizer_initial( _A )
+
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
new file mode 100644
index 00000000000..b475c7a7c42
--- /dev/null
+++ b/drivers/staging/winbond/reg.c
@@ -0,0 +1,2683 @@
+#include "os_common.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Original Phy.h
+//*****************************************************************************
+
+/*****************************************************************************
+; For MAXIM2825/6/7 Ver. 331 or more
+; Edited by Tiger, Sep-17-2003
+; revised by Ben, Sep-18-2003
+
+0x00 0x000a2
+0x01 0x21cc0
+;0x02 0x13802
+0x02 0x1383a
+
+;channe1 01 ; 0x03 0x30142 ; 0x04 0x0b333;
+;channe1 02 ;0x03 0x32141 ;0x04 0x08444;
+;channe1 03 ;0x03 0x32143 ;0x04 0x0aeee;
+;channe1 04 ;0x03 0x32142 ;0x04 0x0b333;
+;channe1 05 ;0x03 0x31141 ;0x04 0x08444;
+;channe1 06 ;
+0x03 0x31143;
+0x04 0x0aeee;
+;channe1 07 ;0x03 0x31142 ;0x04 0x0b333;
+;channe1 08 ;0x03 0x33141 ;0x04 0x08444;
+;channe1 09 ;0x03 0x33143 ;0x04 0x0aeee;
+;channe1 10 ;0x03 0x33142 ;0x04 0x0b333;
+;channe1 11 ;0x03 0x30941 ;0x04 0x08444;
+;channe1 12 ;0x03 0x30943 ;0x04 0x0aeee;
+;channe1 13 ;0x03 0x30942 ;0x04 0x0b333;
+
+0x05 0x28986
+0x06 0x18008
+0x07 0x38400
+0x08 0x05100; 100 Hz DC
+;0x08 0x05900; 30 KHz DC
+0x09 0x24f08
+0x0a 0x17e00, 0x17ea0
+0x0b 0x37d80
+0x0c 0x0c900 // 0x0ca00 (lager power 9db than 0x0c000), 0x0c000
+*****************************************************************************/
+// MAX2825 (pure b/g)
+u32 max2825_rf_data[] =
+{
+ (0x00<<18)|0x000a2,
+ (0x01<<18)|0x21cc0,
+ (0x02<<18)|0x13806,
+ (0x03<<18)|0x30142,
+ (0x04<<18)|0x0b333,
+ (0x05<<18)|0x289A6,
+ (0x06<<18)|0x18008,
+ (0x07<<18)|0x38000,
+ (0x08<<18)|0x05100,
+ (0x09<<18)|0x24f08,
+ (0x0A<<18)|0x14000,
+ (0x0B<<18)|0x37d80,
+ (0x0C<<18)|0x0c100 // 11a: 0x0c300, 11g: 0x0c100
+};
+
+u32 max2825_channel_data_24[][3] =
+{
+ {(0x03<<18)|0x30142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 01
+ {(0x03<<18)|0x32141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 02
+ {(0x03<<18)|0x32143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 03
+ {(0x03<<18)|0x32142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 04
+ {(0x03<<18)|0x31141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 05
+ {(0x03<<18)|0x31143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 06
+ {(0x03<<18)|0x31142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 07
+ {(0x03<<18)|0x33141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 08
+ {(0x03<<18)|0x33143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 09
+ {(0x03<<18)|0x33142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 10
+ {(0x03<<18)|0x30941, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 11
+ {(0x03<<18)|0x30943, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 12
+ {(0x03<<18)|0x30942, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 13
+ {(0x03<<18)|0x32941, (0x04<<18)|0x09999, (0x05<<18)|0x289A6} // 14 (2484MHz) hhmodify
+};
+
+u32 max2825_power_data_24[] = {(0x0C<<18)|0x0c000, (0x0C<<18)|0x0c100};
+
+/****************************************************************************/
+// MAX2827 (a/b/g)
+u32 max2827_rf_data[] =
+{
+ (0x00<<18)|0x000a2,
+ (0x01<<18)|0x21cc0,
+ (0x02<<18)|0x13806,
+ (0x03<<18)|0x30142,
+ (0x04<<18)|0x0b333,
+ (0x05<<18)|0x289A6,
+ (0x06<<18)|0x18008,
+ (0x07<<18)|0x38000,
+ (0x08<<18)|0x05100,
+ (0x09<<18)|0x24f08,
+ (0x0A<<18)|0x14000,
+ (0x0B<<18)|0x37d80,
+ (0x0C<<18)|0x0c100 // 11a: 0x0c300, 11g: 0x0c100
+};
+
+u32 max2827_channel_data_24[][3] =
+{
+ {(0x03<<18)|0x30142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 01
+ {(0x03<<18)|0x32141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 02
+ {(0x03<<18)|0x32143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 03
+ {(0x03<<18)|0x32142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 04
+ {(0x03<<18)|0x31141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 05
+ {(0x03<<18)|0x31143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 06
+ {(0x03<<18)|0x31142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 07
+ {(0x03<<18)|0x33141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 08
+ {(0x03<<18)|0x33143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 09
+ {(0x03<<18)|0x33142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 10
+ {(0x03<<18)|0x30941, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 11
+ {(0x03<<18)|0x30943, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 12
+ {(0x03<<18)|0x30942, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 13
+ {(0x03<<18)|0x32941, (0x04<<18)|0x09999, (0x05<<18)|0x289A6} // 14 (2484MHz) hhmodify
+};
+
+u32 max2827_channel_data_50[][3] =
+{
+ {(0x03<<18)|0x33cc3, (0x04<<18)|0x08ccc, (0x05<<18)|0x2A9A6}, // channel 36
+ {(0x03<<18)|0x302c0, (0x04<<18)|0x08000, (0x05<<18)|0x2A9A6}, // channel 40
+ {(0x03<<18)|0x302c2, (0x04<<18)|0x0b333, (0x05<<18)|0x2A9A6}, // channel 44
+ {(0x03<<18)|0x322c1, (0x04<<18)|0x09999, (0x05<<18)|0x2A9A6}, // channel 48
+ {(0x03<<18)|0x312c1, (0x04<<18)|0x0a666, (0x05<<18)|0x2A9A6}, // channel 52
+ {(0x03<<18)|0x332c3, (0x04<<18)|0x08ccc, (0x05<<18)|0x2A9A6}, // channel 56
+ {(0x03<<18)|0x30ac0, (0x04<<18)|0x08000, (0x05<<18)|0x2A9A6}, // channel 60
+ {(0x03<<18)|0x30ac2, (0x04<<18)|0x0b333, (0x05<<18)|0x2A9A6} // channel 64
+};
+
+u32 max2827_power_data_24[] = {(0x0C<<18)|0x0C000, (0x0C<<18)|0x0D600, (0x0C<<18)|0x0C100};
+u32 max2827_power_data_50[] = {(0x0C<<18)|0x0C400, (0x0C<<18)|0x0D500, (0x0C<<18)|0x0C300};
+
+/****************************************************************************/
+// MAX2828 (a/b/g)
+u32 max2828_rf_data[] =
+{
+ (0x00<<18)|0x000a2,
+ (0x01<<18)|0x21cc0,
+ (0x02<<18)|0x13806,
+ (0x03<<18)|0x30142,
+ (0x04<<18)|0x0b333,
+ (0x05<<18)|0x289A6,
+ (0x06<<18)|0x18008,
+ (0x07<<18)|0x38000,
+ (0x08<<18)|0x05100,
+ (0x09<<18)|0x24f08,
+ (0x0A<<18)|0x14000,
+ (0x0B<<18)|0x37d80,
+ (0x0C<<18)|0x0c100 // 11a: 0x0c300, 11g: 0x0c100
+};
+
+u32 max2828_channel_data_24[][3] =
+{
+ {(0x03<<18)|0x30142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 01
+ {(0x03<<18)|0x32141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 02
+ {(0x03<<18)|0x32143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 03
+ {(0x03<<18)|0x32142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 04
+ {(0x03<<18)|0x31141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 05
+ {(0x03<<18)|0x31143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 06
+ {(0x03<<18)|0x31142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 07
+ {(0x03<<18)|0x33141, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 08
+ {(0x03<<18)|0x33143, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 09
+ {(0x03<<18)|0x33142, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 10
+ {(0x03<<18)|0x30941, (0x04<<18)|0x08444, (0x05<<18)|0x289A6}, // channe1 11
+ {(0x03<<18)|0x30943, (0x04<<18)|0x0aeee, (0x05<<18)|0x289A6}, // channe1 12
+ {(0x03<<18)|0x30942, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channe1 13
+ {(0x03<<18)|0x32941, (0x04<<18)|0x09999, (0x05<<18)|0x289A6} // 14 (2484MHz) hhmodify
+};
+
+u32 max2828_channel_data_50[][3] =
+{
+ {(0x03<<18)|0x33cc3, (0x04<<18)|0x08ccc, (0x05<<18)|0x289A6}, // channel 36
+ {(0x03<<18)|0x302c0, (0x04<<18)|0x08000, (0x05<<18)|0x289A6}, // channel 40
+ {(0x03<<18)|0x302c2, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6}, // channel 44
+ {(0x03<<18)|0x322c1, (0x04<<18)|0x09999, (0x05<<18)|0x289A6}, // channel 48
+ {(0x03<<18)|0x312c1, (0x04<<18)|0x0a666, (0x05<<18)|0x289A6}, // channel 52
+ {(0x03<<18)|0x332c3, (0x04<<18)|0x08ccc, (0x05<<18)|0x289A6}, // channel 56
+ {(0x03<<18)|0x30ac0, (0x04<<18)|0x08000, (0x05<<18)|0x289A6}, // channel 60
+ {(0x03<<18)|0x30ac2, (0x04<<18)|0x0b333, (0x05<<18)|0x289A6} // channel 64
+};
+
+u32 max2828_power_data_24[] = {(0x0C<<18)|0x0c000, (0x0C<<18)|0x0c100};
+u32 max2828_power_data_50[] = {(0x0C<<18)|0x0c000, (0x0C<<18)|0x0c100};
+
+/****************************************************************************/
+// LA20040728 kevin
+// MAX2829 (a/b/g)
+u32 max2829_rf_data[] =
+{
+ (0x00<<18)|0x000a2,
+ (0x01<<18)|0x23520,
+ (0x02<<18)|0x13802,
+ (0x03<<18)|0x30142,
+ (0x04<<18)|0x0b333,
+ (0x05<<18)|0x28906,
+ (0x06<<18)|0x18008,
+ (0x07<<18)|0x3B500,
+ (0x08<<18)|0x05100,
+ (0x09<<18)|0x24f08,
+ (0x0A<<18)|0x14000,
+ (0x0B<<18)|0x37d80,
+ (0x0C<<18)|0x0F300 //TXVGA=51, (MAX-6 dB)
+};
+
+u32 max2829_channel_data_24[][3] =
+{
+ {(3<<18)|0x30142, (4<<18)|0x0b333, (5<<18)|0x289C6}, // 01 (2412MHz)
+ {(3<<18)|0x32141, (4<<18)|0x08444, (5<<18)|0x289C6}, // 02 (2417MHz)
+ {(3<<18)|0x32143, (4<<18)|0x0aeee, (5<<18)|0x289C6}, // 03 (2422MHz)
+ {(3<<18)|0x32142, (4<<18)|0x0b333, (5<<18)|0x289C6}, // 04 (2427MHz)
+ {(3<<18)|0x31141, (4<<18)|0x08444, (5<<18)|0x289C6}, // 05 (2432MHz)
+ {(3<<18)|0x31143, (4<<18)|0x0aeee, (5<<18)|0x289C6}, // 06 (2437MHz)
+ {(3<<18)|0x31142, (4<<18)|0x0b333, (5<<18)|0x289C6}, // 07 (2442MHz)
+ {(3<<18)|0x33141, (4<<18)|0x08444, (5<<18)|0x289C6}, // 08 (2447MHz)
+ {(3<<18)|0x33143, (4<<18)|0x0aeee, (5<<18)|0x289C6}, // 09 (2452MHz)
+ {(3<<18)|0x33142, (4<<18)|0x0b333, (5<<18)|0x289C6}, // 10 (2457MHz)
+ {(3<<18)|0x30941, (4<<18)|0x08444, (5<<18)|0x289C6}, // 11 (2462MHz)
+ {(3<<18)|0x30943, (4<<18)|0x0aeee, (5<<18)|0x289C6}, // 12 (2467MHz)
+ {(3<<18)|0x30942, (4<<18)|0x0b333, (5<<18)|0x289C6}, // 13 (2472MHz)
+ {(3<<18)|0x32941, (4<<18)|0x09999, (5<<18)|0x289C6}, // 14 (2484MHz) hh-modify
+};
+
+u32 max2829_channel_data_50[][4] =
+{
+ {36, (3<<18)|0x33cc3, (4<<18)|0x08ccc, (5<<18)|0x2A946}, // 36 (5.180GHz)
+ {40, (3<<18)|0x302c0, (4<<18)|0x08000, (5<<18)|0x2A946}, // 40 (5.200GHz)
+ {44, (3<<18)|0x302c2, (4<<18)|0x0b333, (5<<18)|0x2A946}, // 44 (5.220GHz)
+ {48, (3<<18)|0x322c1, (4<<18)|0x09999, (5<<18)|0x2A946}, // 48 (5.240GHz)
+ {52, (3<<18)|0x312c1, (4<<18)|0x0a666, (5<<18)|0x2A946}, // 52 (5.260GHz)
+ {56, (3<<18)|0x332c3, (4<<18)|0x08ccc, (5<<18)|0x2A946}, // 56 (5.280GHz)
+ {60, (3<<18)|0x30ac0, (4<<18)|0x08000, (5<<18)|0x2A946}, // 60 (5.300GHz)
+ {64, (3<<18)|0x30ac2, (4<<18)|0x0b333, (5<<18)|0x2A946}, // 64 (5.320GHz)
+
+ {100, (3<<18)|0x30ec0, (4<<18)|0x08000, (5<<18)|0x2A9C6}, // 100 (5.500GHz)
+ {104, (3<<18)|0x30ec2, (4<<18)|0x0b333, (5<<18)|0x2A9C6}, // 104 (5.520GHz)
+ {108, (3<<18)|0x32ec1, (4<<18)|0x09999, (5<<18)|0x2A9C6}, // 108 (5.540GHz)
+ {112, (3<<18)|0x31ec1, (4<<18)|0x0a666, (5<<18)|0x2A9C6}, // 112 (5.560GHz)
+ {116, (3<<18)|0x33ec3, (4<<18)|0x08ccc, (5<<18)|0x2A9C6}, // 116 (5.580GHz)
+ {120, (3<<18)|0x301c0, (4<<18)|0x08000, (5<<18)|0x2A9C6}, // 120 (5.600GHz)
+ {124, (3<<18)|0x301c2, (4<<18)|0x0b333, (5<<18)|0x2A9C6}, // 124 (5.620GHz)
+ {128, (3<<18)|0x321c1, (4<<18)|0x09999, (5<<18)|0x2A9C6}, // 128 (5.640GHz)
+ {132, (3<<18)|0x311c1, (4<<18)|0x0a666, (5<<18)|0x2A9C6}, // 132 (5.660GHz)
+ {136, (3<<18)|0x331c3, (4<<18)|0x08ccc, (5<<18)|0x2A9C6}, // 136 (5.680GHz)
+ {140, (3<<18)|0x309c0, (4<<18)|0x08000, (5<<18)|0x2A9C6}, // 140 (5.700GHz)
+
+ {149, (3<<18)|0x329c2, (4<<18)|0x0b333, (5<<18)|0x2A9C6}, // 149 (5.745GHz)
+ {153, (3<<18)|0x319c1, (4<<18)|0x09999, (5<<18)|0x2A9C6}, // 153 (5.765GHz)
+ {157, (3<<18)|0x339c1, (4<<18)|0x0a666, (5<<18)|0x2A9C6}, // 157 (5.785GHz)
+ {161, (3<<18)|0x305c3, (4<<18)|0x08ccc, (5<<18)|0x2A9C6}, // 161 (5.805GHz)
+
+ // Japan
+ { 184, (3<<18)|0x308c2, (4<<18)|0x0b333, (5<<18)|0x2A946}, // 184 (4.920GHz)
+ { 188, (3<<18)|0x328c1, (4<<18)|0x09999, (5<<18)|0x2A946}, // 188 (4.940GHz)
+ { 192, (3<<18)|0x318c1, (4<<18)|0x0a666, (5<<18)|0x2A946}, // 192 (4.960GHz)
+ { 196, (3<<18)|0x338c3, (4<<18)|0x08ccc, (5<<18)|0x2A946}, // 196 (4.980GHz)
+ { 8, (3<<18)|0x324c1, (4<<18)|0x09999, (5<<18)|0x2A946}, // 8 (5.040GHz)
+ { 12, (3<<18)|0x314c1, (4<<18)|0x0a666, (5<<18)|0x2A946}, // 12 (5.060GHz)
+ { 16, (3<<18)|0x334c3, (4<<18)|0x08ccc, (5<<18)|0x2A946}, // 16 (5.080GHz)
+ { 34, (3<<18)|0x31cc2, (4<<18)|0x0b333, (5<<18)|0x2A946}, // 34 (5.170GHz)
+ { 38, (3<<18)|0x33cc1, (4<<18)|0x09999, (5<<18)|0x2A946}, // 38 (5.190GHz)
+ { 42, (3<<18)|0x302c1, (4<<18)|0x0a666, (5<<18)|0x2A946}, // 42 (5.210GHz)
+ { 46, (3<<18)|0x322c3, (4<<18)|0x08ccc, (5<<18)|0x2A946}, // 46 (5.230GHz)
+};
+
+/*****************************************************************************
+; For MAXIM2825/6/7 Ver. 317 or less
+; Edited by Tiger, Sep-17-2003 for 2.4Ghz channels
+; Updated by Tiger, Sep-22-2003 for 5.0Ghz channels
+; Corrected by Tiger, Sep-23-2003, for 0x03 and 0x04 of 5.0Ghz channels
+
+0x00 0x00080
+0x01 0x214c0
+0x02 0x13802
+
+;2.4GHz Channels
+;channe1 01 (2.412GHz); 0x03 0x30143 ;0x04 0x0accc
+;channe1 02 (2.417GHz); 0x03 0x32140 ;0x04 0x09111
+;channe1 03 (2.422GHz); 0x03 0x32142 ;0x04 0x0bbbb
+;channe1 04 (2.427GHz); 0x03 0x32143 ;0x04 0x0accc
+;channe1 05 (2.432GHz); 0x03 0x31140 ;0x04 0x09111
+;channe1 06 (2.437GHz); 0x03 0x31142 ;0x04 0x0bbbb
+;channe1 07 (2.442GHz); 0x03 0x31143 ;0x04 0x0accc
+;channe1 08 (2.447GHz); 0x03 0x33140 ;0x04 0x09111
+;channe1 09 (2.452GHz); 0x03 0x33142 ;0x04 0x0bbbb
+;channe1 10 (2.457GHz); 0x03 0x33143 ;0x04 0x0accc
+;channe1 11 (2.462GHz); 0x03 0x30940 ;0x04 0x09111
+;channe1 12 (2.467GHz); 0x03 0x30942 ;0x04 0x0bbbb
+;channe1 13 (2.472GHz); 0x03 0x30943 ;0x04 0x0accc
+
+;5.0Ghz Channels
+;channel 36 (5.180GHz); 0x03 0x33cc0 ;0x04 0x0b333
+;channel 40 (5.200GHz); 0x03 0x302c0 ;0x04 0x08000
+;channel 44 (5.220GHz); 0x03 0x302c2 ;0x04 0x0b333
+;channel 48 (5.240GHz); 0x03 0x322c1 ;0x04 0x09999
+;channel 52 (5.260GHz); 0x03 0x312c1 ;0x04 0x0a666
+;channel 56 (5.280GHz); 0x03 0x332c3 ;0x04 0x08ccc
+;channel 60 (5.300GHz); 0x03 0x30ac0 ;0x04 0x08000
+;channel 64 (5.320GHz); 0x03 0x30ac2 ;0x04 0x08333
+
+;2.4GHz band ;0x05 0x28986;
+;5.0GHz band
+0x05 0x2a986
+
+0x06 0x18008
+0x07 0x38400
+0x08 0x05108
+0x09 0x27ff8
+0x0a 0x14000
+0x0b 0x37f99
+0x0c 0x0c000
+*****************************************************************************/
+u32 maxim_317_rf_data[] =
+{
+ (0x00<<18)|0x000a2,
+ (0x01<<18)|0x214c0,
+ (0x02<<18)|0x13802,
+ (0x03<<18)|0x30143,
+ (0x04<<18)|0x0accc,
+ (0x05<<18)|0x28986,
+ (0x06<<18)|0x18008,
+ (0x07<<18)|0x38400,
+ (0x08<<18)|0x05108,
+ (0x09<<18)|0x27ff8,
+ (0x0A<<18)|0x14000,
+ (0x0B<<18)|0x37f99,
+ (0x0C<<18)|0x0c000
+};
+
+u32 maxim_317_channel_data_24[][3] =
+{
+ {(0x03<<18)|0x30143, (0x04<<18)|0x0accc, (0x05<<18)|0x28986}, // channe1 01
+ {(0x03<<18)|0x32140, (0x04<<18)|0x09111, (0x05<<18)|0x28986}, // channe1 02
+ {(0x03<<18)|0x32142, (0x04<<18)|0x0bbbb, (0x05<<18)|0x28986}, // channe1 03
+ {(0x03<<18)|0x32143, (0x04<<18)|0x0accc, (0x05<<18)|0x28986}, // channe1 04
+ {(0x03<<18)|0x31140, (0x04<<18)|0x09111, (0x05<<18)|0x28986}, // channe1 05
+ {(0x03<<18)|0x31142, (0x04<<18)|0x0bbbb, (0x05<<18)|0x28986}, // channe1 06
+ {(0x03<<18)|0x31143, (0x04<<18)|0x0accc, (0x05<<18)|0x28986}, // channe1 07
+ {(0x03<<18)|0x33140, (0x04<<18)|0x09111, (0x05<<18)|0x28986}, // channe1 08
+ {(0x03<<18)|0x33142, (0x04<<18)|0x0bbbb, (0x05<<18)|0x28986}, // channe1 09
+ {(0x03<<18)|0x33143, (0x04<<18)|0x0accc, (0x05<<18)|0x28986}, // channe1 10
+ {(0x03<<18)|0x30940, (0x04<<18)|0x09111, (0x05<<18)|0x28986}, // channe1 11
+ {(0x03<<18)|0x30942, (0x04<<18)|0x0bbbb, (0x05<<18)|0x28986}, // channe1 12
+ {(0x03<<18)|0x30943, (0x04<<18)|0x0accc, (0x05<<18)|0x28986} // channe1 13
+};
+
+u32 maxim_317_channel_data_50[][3] =
+{
+ {(0x03<<18)|0x33cc0, (0x04<<18)|0x0b333, (0x05<<18)|0x2a986}, // channel 36
+ {(0x03<<18)|0x302c0, (0x04<<18)|0x08000, (0x05<<18)|0x2a986}, // channel 40
+ {(0x03<<18)|0x302c3, (0x04<<18)|0x0accc, (0x05<<18)|0x2a986}, // channel 44
+ {(0x03<<18)|0x322c1, (0x04<<18)|0x09666, (0x05<<18)|0x2a986}, // channel 48
+ {(0x03<<18)|0x312c2, (0x04<<18)|0x09999, (0x05<<18)|0x2a986}, // channel 52
+ {(0x03<<18)|0x332c0, (0x04<<18)|0x0b333, (0x05<<18)|0x2a99e}, // channel 56
+ {(0x03<<18)|0x30ac0, (0x04<<18)|0x08000, (0x05<<18)|0x2a99e}, // channel 60
+ {(0x03<<18)|0x30ac3, (0x04<<18)|0x0accc, (0x05<<18)|0x2a99e} // channel 64
+};
+
+u32 maxim_317_power_data_24[] = {(0x0C<<18)|0x0c000, (0x0C<<18)|0x0c100};
+u32 maxim_317_power_data_50[] = {(0x0C<<18)|0x0c000, (0x0C<<18)|0x0c100};
+
+/*****************************************************************************
+;;AL2230 MP (Mass Production Version)
+;;RF Registers Setting for Airoha AL2230 silicon after June 1st, 2004
+;;Updated by Tiger Huang (June 1st, 2004)
+;;20-bit length and LSB first
+
+;;Ch01 (2412MHz) ;0x00 0x09EFC ;0x01 0x8CCCC;
+;;Ch02 (2417MHz) ;0x00 0x09EFC ;0x01 0x8CCCD;
+;;Ch03 (2422MHz) ;0x00 0x09E7C ;0x01 0x8CCCC;
+;;Ch04 (2427MHz) ;0x00 0x09E7C ;0x01 0x8CCCD;
+;;Ch05 (2432MHz) ;0x00 0x05EFC ;0x01 0x8CCCC;
+;;Ch06 (2437MHz) ;0x00 0x05EFC ;0x01 0x8CCCD;
+;;Ch07 (2442MHz) ;0x00 0x05E7C ;0x01 0x8CCCC;
+;;Ch08 (2447MHz) ;0x00 0x05E7C ;0x01 0x8CCCD;
+;;Ch09 (2452MHz) ;0x00 0x0DEFC ;0x01 0x8CCCC;
+;;Ch10 (2457MHz) ;0x00 0x0DEFC ;0x01 0x8CCCD;
+;;Ch11 (2462MHz) ;0x00 0x0DE7C ;0x01 0x8CCCC;
+;;Ch12 (2467MHz) ;0x00 0x0DE7C ;0x01 0x8CCCD;
+;;Ch13 (2472MHz) ;0x00 0x03EFC ;0x01 0x8CCCC;
+;;Ch14 (2484Mhz) ;0x00 0x03E7C ;0x01 0x86666;
+
+0x02 0x401D8; RXDCOC BW 100Hz for RXHP low
+;;0x02 0x481DC; RXDCOC BW 30Khz for RXHP low
+
+0x03 0xCFFF0
+0x04 0x23800
+0x05 0xA3B72
+0x06 0x6DA01
+0x07 0xE1688
+0x08 0x11600
+0x09 0x99E02
+0x0A 0x5DDB0
+0x0B 0xD9900
+0x0C 0x3FFBD
+0x0D 0xB0000
+0x0F 0xF00A0
+
+;RF Calibration for Airoha AL2230
+;Edit by Ben Chang (01/30/04)
+;Updated by Tiger Huang (03/03/04)
+0x0f 0xf00a0 ; Initial Setting
+0x0f 0xf00b0 ; Activate TX DCC
+0x0f 0xf02a0 ; Activate Phase Calibration
+0x0f 0xf00e0 ; Activate Filter RC Calibration
+0x0f 0xf00a0 ; Restore Initial Setting
+*****************************************************************************/
+
+u32 al2230_rf_data[] =
+{
+ (0x00<<20)|0x09EFC,
+ (0x01<<20)|0x8CCCC,
+ (0x02<<20)|0x40058,// 20060627 Anson 0x401D8,
+ (0x03<<20)|0xCFFF0,
+ (0x04<<20)|0x24100,// 20060627 Anson 0x23800,
+ (0x05<<20)|0xA3B2F,// 20060627 Anson 0xA3B72
+ (0x06<<20)|0x6DA01,
+ (0x07<<20)|0xE3628,// 20060627 Anson 0xE1688,
+ (0x08<<20)|0x11600,
+ (0x09<<20)|0x9DC02,// 20060627 Anosn 0x97602,//0x99E02, //0x9AE02
+ (0x0A<<20)|0x5ddb0, // 941206 For QCOM interference 0x588b0,//0x5DDB0, 940601 adj 0x5aa30 for bluetooth
+ (0x0B<<20)|0xD9900,
+ (0x0C<<20)|0x3FFBD,
+ (0x0D<<20)|0xB0000,
+ (0x0F<<20)|0xF01A0 // 20060627 Anson 0xF00A0
+};
+
+u32 al2230s_rf_data[] =
+{
+ (0x00<<20)|0x09EFC,
+ (0x01<<20)|0x8CCCC,
+ (0x02<<20)|0x40058,// 20060419 0x401D8,
+ (0x03<<20)|0xCFFF0,
+ (0x04<<20)|0x24100,// 20060419 0x23800,
+ (0x05<<20)|0xA3B2F,// 20060419 0xA3B72,
+ (0x06<<20)|0x6DA01,
+ (0x07<<20)|0xE3628,// 20060419 0xE1688,
+ (0x08<<20)|0x11600,
+ (0x09<<20)|0x9DC02,// 20060419 0x97602,//0x99E02, //0x9AE02
+ (0x0A<<20)|0x5DDB0,// 941206 For QCOM interference 0x588b0,//0x5DDB0, 940601 adj 0x5aa30 for bluetooth
+ (0x0B<<20)|0xD9900,
+ (0x0C<<20)|0x3FFBD,
+ (0x0D<<20)|0xB0000,
+ (0x0F<<20)|0xF01A0 // 20060419 0xF00A0
+};
+
+u32 al2230_channel_data_24[][2] =
+{
+ {(0x00<<20)|0x09EFC, (0x01<<20)|0x8CCCC}, // channe1 01
+ {(0x00<<20)|0x09EFC, (0x01<<20)|0x8CCCD}, // channe1 02
+ {(0x00<<20)|0x09E7C, (0x01<<20)|0x8CCCC}, // channe1 03
+ {(0x00<<20)|0x09E7C, (0x01<<20)|0x8CCCD}, // channe1 04
+ {(0x00<<20)|0x05EFC, (0x01<<20)|0x8CCCC}, // channe1 05
+ {(0x00<<20)|0x05EFC, (0x01<<20)|0x8CCCD}, // channe1 06
+ {(0x00<<20)|0x05E7C, (0x01<<20)|0x8CCCC}, // channe1 07
+ {(0x00<<20)|0x05E7C, (0x01<<20)|0x8CCCD}, // channe1 08
+ {(0x00<<20)|0x0DEFC, (0x01<<20)|0x8CCCC}, // channe1 09
+ {(0x00<<20)|0x0DEFC, (0x01<<20)|0x8CCCD}, // channe1 10
+ {(0x00<<20)|0x0DE7C, (0x01<<20)|0x8CCCC}, // channe1 11
+ {(0x00<<20)|0x0DE7C, (0x01<<20)|0x8CCCD}, // channe1 12
+ {(0x00<<20)|0x03EFC, (0x01<<20)|0x8CCCC}, // channe1 13
+ {(0x00<<20)|0x03E7C, (0x01<<20)|0x86666} // channe1 14
+};
+
+// Current setting. u32 airoha_power_data_24[] = {(0x09<<20)|0x90202, (0x09<<20)|0x96602, (0x09<<20)|0x97602};
+#define AIROHA_TXVGA_LOW_INDEX 31 // Index for 0x90202
+#define AIROHA_TXVGA_MIDDLE_INDEX 12 // Index for 0x96602
+#define AIROHA_TXVGA_HIGH_INDEX 8 // Index for 0x97602 1.0.24.0 1.0.28.0
+/*
+u32 airoha_power_data_24[] =
+{
+ 0x9FE02, // Max - 0 dB
+ 0x9BE02, // Max - 1 dB
+ 0x9DE02, // Max - 2 dB
+ 0x99E02, // Max - 3 dB
+ 0x9EE02, // Max - 4 dB
+ 0x9AE02, // Max - 5 dB
+ 0x9CE02, // Max - 6 dB
+ 0x98E02, // Max - 7 dB
+ 0x97602, // Max - 8 dB
+ 0x93602, // Max - 9 dB
+ 0x95602, // Max - 10 dB
+ 0x91602, // Max - 11 dB
+ 0x96602, // Max - 12 dB
+ 0x92602, // Max - 13 dB
+ 0x94602, // Max - 14 dB
+ 0x90602, // Max - 15 dB
+ 0x97A02, // Max - 16 dB
+ 0x93A02, // Max - 17 dB
+ 0x95A02, // Max - 18 dB
+ 0x91A02, // Max - 19 dB
+ 0x96A02, // Max - 20 dB
+ 0x92A02, // Max - 21 dB
+ 0x94A02, // Max - 22 dB
+ 0x90A02, // Max - 23 dB
+ 0x97202, // Max - 24 dB
+ 0x93202, // Max - 25 dB
+ 0x95202, // Max - 26 dB
+ 0x91202, // Max - 27 dB
+ 0x96202, // Max - 28 dB
+ 0x92202, // Max - 29 dB
+ 0x94202, // Max - 30 dB
+ 0x90202 // Max - 31 dB
+};
+*/
+
+// 20040927 1.1.69.1000 ybjiang
+// from John
+u32 al2230_txvga_data[][2] =
+{
+ //value , index
+ {0x090202, 0},
+ {0x094202, 2},
+ {0x092202, 4},
+ {0x096202, 6},
+ {0x091202, 8},
+ {0x095202, 10},
+ {0x093202, 12},
+ {0x097202, 14},
+ {0x090A02, 16},
+ {0x094A02, 18},
+ {0x092A02, 20},
+ {0x096A02, 22},
+ {0x091A02, 24},
+ {0x095A02, 26},
+ {0x093A02, 28},
+ {0x097A02, 30},
+ {0x090602, 32},
+ {0x094602, 34},
+ {0x092602, 36},
+ {0x096602, 38},
+ {0x091602, 40},
+ {0x095602, 42},
+ {0x093602, 44},
+ {0x097602, 46},
+ {0x090E02, 48},
+ {0x098E02, 49},
+ {0x094E02, 50},
+ {0x09CE02, 51},
+ {0x092E02, 52},
+ {0x09AE02, 53},
+ {0x096E02, 54},
+ {0x09EE02, 55},
+ {0x091E02, 56},
+ {0x099E02, 57},
+ {0x095E02, 58},
+ {0x09DE02, 59},
+ {0x093E02, 60},
+ {0x09BE02, 61},
+ {0x097E02, 62},
+ {0x09FE02, 63}
+};
+
+//--------------------------------
+// For Airoha AL7230, 2.4Ghz band
+// Edit by Tiger, (March, 9, 2005)
+// 24bit, MSB first
+
+//channel independent registers:
+u32 al7230_rf_data_24[] =
+{
+ (0x00<<24)|0x003790,
+ (0x01<<24)|0x133331,
+ (0x02<<24)|0x841FF2,
+ (0x03<<24)|0x3FDFA3,
+ (0x04<<24)|0x7FD784,
+ (0x05<<24)|0x802B55,
+ (0x06<<24)|0x56AF36,
+ (0x07<<24)|0xCE0207,
+ (0x08<<24)|0x6EBC08,
+ (0x09<<24)|0x221BB9,
+ (0x0A<<24)|0xE0000A,
+ (0x0B<<24)|0x08071B,
+ (0x0C<<24)|0x000A3C,
+ (0x0D<<24)|0xFFFFFD,
+ (0x0E<<24)|0x00000E,
+ (0x0F<<24)|0x1ABA8F
+};
+
+u32 al7230_channel_data_24[][2] =
+{
+ {(0x00<<24)|0x003790, (0x01<<24)|0x133331}, // channe1 01
+ {(0x00<<24)|0x003790, (0x01<<24)|0x1B3331}, // channe1 02
+ {(0x00<<24)|0x003790, (0x01<<24)|0x033331}, // channe1 03
+ {(0x00<<24)|0x003790, (0x01<<24)|0x0B3331}, // channe1 04
+ {(0x00<<24)|0x0037A0, (0x01<<24)|0x133331}, // channe1 05
+ {(0x00<<24)|0x0037A0, (0x01<<24)|0x1B3331}, // channe1 06
+ {(0x00<<24)|0x0037A0, (0x01<<24)|0x033331}, // channe1 07
+ {(0x00<<24)|0x0037A0, (0x01<<24)|0x0B3331}, // channe1 08
+ {(0x00<<24)|0x0037B0, (0x01<<24)|0x133331}, // channe1 09
+ {(0x00<<24)|0x0037B0, (0x01<<24)|0x1B3331}, // channe1 10
+ {(0x00<<24)|0x0037B0, (0x01<<24)|0x033331}, // channe1 11
+ {(0x00<<24)|0x0037B0, (0x01<<24)|0x0B3331}, // channe1 12
+ {(0x00<<24)|0x0037C0, (0x01<<24)|0x133331}, // channe1 13
+ {(0x00<<24)|0x0037C0, (0x01<<24)|0x066661} // channel 14
+};
+
+//channel independent registers:
+u32 al7230_rf_data_50[] =
+{
+ (0x00<<24)|0x0FF520,
+ (0x01<<24)|0x000001,
+ (0x02<<24)|0x451FE2,
+ (0x03<<24)|0x5FDFA3,
+ (0x04<<24)|0x6FD784,
+ (0x05<<24)|0x853F55,
+ (0x06<<24)|0x56AF36,
+ (0x07<<24)|0xCE0207,
+ (0x08<<24)|0x6EBC08,
+ (0x09<<24)|0x221BB9,
+ (0x0A<<24)|0xE0600A,
+ (0x0B<<24)|0x08044B,
+ (0x0C<<24)|0x00143C,
+ (0x0D<<24)|0xFFFFFD,
+ (0x0E<<24)|0x00000E,
+ (0x0F<<24)|0x12BACF //5Ghz default state
+};
+
+u32 al7230_channel_data_5[][4] =
+{
+ //channel dependent registers: 0x00, 0x01 and 0x04
+ //11J ===========
+ {184, (0x00<<24)|0x0FF520, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 184
+ {188, (0x00<<24)|0x0FF520, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 188
+ {192, (0x00<<24)|0x0FF530, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 192
+ {196, (0x00<<24)|0x0FF530, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 196
+ {8, (0x00<<24)|0x0FF540, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 008
+ {12, (0x00<<24)|0x0FF540, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 012
+ {16, (0x00<<24)|0x0FF550, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 016
+ {34, (0x00<<24)|0x0FF560, (0x01<<24)|0x055551, (0x04<<24)|0x77F784}, // channel 034
+ {38, (0x00<<24)|0x0FF570, (0x01<<24)|0x100001, (0x04<<24)|0x77F784}, // channel 038
+ {42, (0x00<<24)|0x0FF570, (0x01<<24)|0x1AAAA1, (0x04<<24)|0x77F784}, // channel 042
+ {46, (0x00<<24)|0x0FF570, (0x01<<24)|0x055551, (0x04<<24)|0x77F784}, // channel 046
+ //11 A/H =========
+ {36, (0x00<<24)|0x0FF560, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 036
+ {40, (0x00<<24)|0x0FF570, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 040
+ {44, (0x00<<24)|0x0FF570, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 044
+ {48, (0x00<<24)|0x0FF570, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 048
+ {52, (0x00<<24)|0x0FF580, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 052
+ {56, (0x00<<24)|0x0FF580, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 056
+ {60, (0x00<<24)|0x0FF580, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 060
+ {64, (0x00<<24)|0x0FF590, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 064
+ {100, (0x00<<24)|0x0FF5C0, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 100
+ {104, (0x00<<24)|0x0FF5C0, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 104
+ {108, (0x00<<24)|0x0FF5C0, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 108
+ {112, (0x00<<24)|0x0FF5D0, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 112
+ {116, (0x00<<24)|0x0FF5D0, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 116
+ {120, (0x00<<24)|0x0FF5D0, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 120
+ {124, (0x00<<24)|0x0FF5E0, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 124
+ {128, (0x00<<24)|0x0FF5E0, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 128
+ {132, (0x00<<24)|0x0FF5E0, (0x01<<24)|0x0AAAA1, (0x04<<24)|0x77F784}, // channel 132
+ {136, (0x00<<24)|0x0FF5F0, (0x01<<24)|0x155551, (0x04<<24)|0x77F784}, // channel 136
+ {140, (0x00<<24)|0x0FF5F0, (0x01<<24)|0x000001, (0x04<<24)|0x67F784}, // channel 140
+ {149, (0x00<<24)|0x0FF600, (0x01<<24)|0x180001, (0x04<<24)|0x77F784}, // channel 149
+ {153, (0x00<<24)|0x0FF600, (0x01<<24)|0x02AAA1, (0x04<<24)|0x77F784}, // channel 153
+ {157, (0x00<<24)|0x0FF600, (0x01<<24)|0x0D5551, (0x04<<24)|0x77F784}, // channel 157
+ {161, (0x00<<24)|0x0FF610, (0x01<<24)|0x180001, (0x04<<24)|0x77F784}, // channel 161
+ {165, (0x00<<24)|0x0FF610, (0x01<<24)|0x02AAA1, (0x04<<24)|0x77F784} // channel 165
+};
+
+//; RF Calibration <=== Register 0x0F
+//0x0F 0x1ABA8F; start from 2.4Ghz default state
+//0x0F 0x9ABA8F; TXDC compensation
+//0x0F 0x3ABA8F; RXFIL adjustment
+//0x0F 0x1ABA8F; restore 2.4Ghz default state
+
+//;TXVGA Mapping Table <=== Register 0x0B
+u32 al7230_txvga_data[][2] =
+{
+ {0x08040B, 0}, //TXVGA=0;
+ {0x08041B, 1}, //TXVGA=1;
+ {0x08042B, 2}, //TXVGA=2;
+ {0x08043B, 3}, //TXVGA=3;
+ {0x08044B, 4}, //TXVGA=4;
+ {0x08045B, 5}, //TXVGA=5;
+ {0x08046B, 6}, //TXVGA=6;
+ {0x08047B, 7}, //TXVGA=7;
+ {0x08048B, 8}, //TXVGA=8;
+ {0x08049B, 9}, //TXVGA=9;
+ {0x0804AB, 10}, //TXVGA=10;
+ {0x0804BB, 11}, //TXVGA=11;
+ {0x0804CB, 12}, //TXVGA=12;
+ {0x0804DB, 13}, //TXVGA=13;
+ {0x0804EB, 14}, //TXVGA=14;
+ {0x0804FB, 15}, //TXVGA=15;
+ {0x08050B, 16}, //TXVGA=16;
+ {0x08051B, 17}, //TXVGA=17;
+ {0x08052B, 18}, //TXVGA=18;
+ {0x08053B, 19}, //TXVGA=19;
+ {0x08054B, 20}, //TXVGA=20;
+ {0x08055B, 21}, //TXVGA=21;
+ {0x08056B, 22}, //TXVGA=22;
+ {0x08057B, 23}, //TXVGA=23;
+ {0x08058B, 24}, //TXVGA=24;
+ {0x08059B, 25}, //TXVGA=25;
+ {0x0805AB, 26}, //TXVGA=26;
+ {0x0805BB, 27}, //TXVGA=27;
+ {0x0805CB, 28}, //TXVGA=28;
+ {0x0805DB, 29}, //TXVGA=29;
+ {0x0805EB, 30}, //TXVGA=30;
+ {0x0805FB, 31}, //TXVGA=31;
+ {0x08060B, 32}, //TXVGA=32;
+ {0x08061B, 33}, //TXVGA=33;
+ {0x08062B, 34}, //TXVGA=34;
+ {0x08063B, 35}, //TXVGA=35;
+ {0x08064B, 36}, //TXVGA=36;
+ {0x08065B, 37}, //TXVGA=37;
+ {0x08066B, 38}, //TXVGA=38;
+ {0x08067B, 39}, //TXVGA=39;
+ {0x08068B, 40}, //TXVGA=40;
+ {0x08069B, 41}, //TXVGA=41;
+ {0x0806AB, 42}, //TXVGA=42;
+ {0x0806BB, 43}, //TXVGA=43;
+ {0x0806CB, 44}, //TXVGA=44;
+ {0x0806DB, 45}, //TXVGA=45;
+ {0x0806EB, 46}, //TXVGA=46;
+ {0x0806FB, 47}, //TXVGA=47;
+ {0x08070B, 48}, //TXVGA=48;
+ {0x08071B, 49}, //TXVGA=49;
+ {0x08072B, 50}, //TXVGA=50;
+ {0x08073B, 51}, //TXVGA=51;
+ {0x08074B, 52}, //TXVGA=52;
+ {0x08075B, 53}, //TXVGA=53;
+ {0x08076B, 54}, //TXVGA=54;
+ {0x08077B, 55}, //TXVGA=55;
+ {0x08078B, 56}, //TXVGA=56;
+ {0x08079B, 57}, //TXVGA=57;
+ {0x0807AB, 58}, //TXVGA=58;
+ {0x0807BB, 59}, //TXVGA=59;
+ {0x0807CB, 60}, //TXVGA=60;
+ {0x0807DB, 61}, //TXVGA=61;
+ {0x0807EB, 62}, //TXVGA=62;
+ {0x0807FB, 63}, //TXVGA=63;
+};
+//--------------------------------
+
+
+//; W89RF242 RFIC SPI programming initial data
+//; Winbond WLAN 11g RFIC BB-SPI register -- version FA5976A rev 1.3b
+//; Update Date: Ocotber 3, 2005 by PP10 Hsiang-Te Ho
+//;
+//; Version 1.3b revision items: (Oct. 1, 2005 by HTHo) for FA5976A
+u32 w89rf242_rf_data[] =
+{
+ (0x00<<24)|0xF86100, // 20060721 0xF86100, //; 3E184; MODA (0x00) -- Normal mode ; calibration off
+ (0x01<<24)|0xEFFFC2, //; 3BFFF; MODB (0x01) -- turn off RSSI, and other circuits are turned on
+ (0x02<<24)|0x102504, //; 04094; FSET (0x02) -- default 20MHz crystal ; Icmp=1.5mA
+ (0x03<<24)|0x026286, //; 0098A; FCHN (0x03) -- default CH7, 2442MHz
+ (0x04<<24)|0x000208, // 20060612.1.a 0x0002C8, // 20050818 // 20050816 0x000388
+ //; 02008; FCAL (0x04) -- XTAL Freq Trim=001000 (socket board#1); FA5976AYG_v1.3C
+ (0x05<<24)|0x24C60A, // 20060612.1.a 0x24C58A, // 941003 0x24C48A, // 20050818.2 0x24848A, // 20050818 // 20050816 0x24C48A
+ //; 09316; GANA (0x05) -- TX VGA default (TXVGA=0x18(12)) & TXGPK=110 ; FA5976A_1.3D
+ (0x06<<24)|0x3432CC, // 941003 0x26C34C, // 20050818 0x06B40C
+ //; 0D0CB; GANB (0x06) -- RXDC(DC offset) on; LNA=11; RXVGA=001011(11) ; RXFLSW=11(010001); RXGPK=00; RXGCF=00; -50dBm input
+ (0x07<<24)|0x0C68CE, // 20050818.2 0x0C66CE, // 20050818 // 20050816 0x0C68CE
+ //; 031A3; FILT (0x07) -- TX/RX filter with auto-tuning; TFLBW=011; RFLBW=100
+ (0x08<<24)|0x100010, //; 04000; TCAL (0x08) -- //for LO
+ (0x09<<24)|0x004012, // 20060612.1.a 0x6E4012, // 0x004012,
+ //; 1B900; RCALA (0x09) -- FASTS=11; HPDE=01 (100nsec); SEHP=1 (select B0 pin=RXHP); RXHP=1 (Turn on RXHP function)(FA5976A_1.3C)
+ (0x0A<<24)|0x704014, //; 1C100; RCALB (0x0A)
+ (0x0B<<24)|0x18BDD6, // 941003 0x1805D6, // 20050818.2 0x1801D6, // 20050818 // 20050816 0x1805D6
+ //; 062F7; IQCAL (0x0B) -- Turn on LO phase tuner=0111 & RX-LO phase = 0111; FA5976A_1.3B (2005/09/29)
+ (0x0C<<24)|0x575558, // 20050818.2 0x555558, // 20050818 // 20050816 0x575558
+ //; 15D55 ; IBSA (0x0C) -- IFPre =11 ; TC5376A_v1.3A for corner
+ (0x0D<<24)|0x55545A, // 20060612.1.a 0x55555A,
+ //; 15555 ; IBSB (0x0D)
+ (0x0E<<24)|0x5557DC, // 20060612.1.a 0x55555C, // 941003 0x5557DC,
+ //; 1555F ; IBSC (0x0E) -- IRLNA & IRLNB (PTAT & Const current)=01/01; FA5976B_1.3F (2005/11/25)
+ (0x10<<24)|0x000C20, // 941003 0x000020, // 20050818
+ //; 00030 ; TMODA (0x10) -- LNA_gain_step=0011 ; LNA=15/16dB
+ (0x11<<24)|0x0C0022, // 941003 0x030022 // 20050818.2 0x030022 // 20050818 // 20050816 0x0C0022
+ //; 03000 ; TMODB (0x11) -- Turn ON RX-Q path Test Switch; To improve IQ path group delay (FA5976A_1.3C)
+ (0x12<<24)|0x000024 // 20060612.1.a 0x001824 // 941003 add
+ //; TMODC (0x12) -- Turn OFF Tempearure sensor
+};
+
+u32 w89rf242_channel_data_24[][2] =
+{
+ {(0x03<<24)|0x025B06, (0x04<<24)|0x080408}, // channe1 01
+ {(0x03<<24)|0x025C46, (0x04<<24)|0x080408}, // channe1 02
+ {(0x03<<24)|0x025D86, (0x04<<24)|0x080408}, // channe1 03
+ {(0x03<<24)|0x025EC6, (0x04<<24)|0x080408}, // channe1 04
+ {(0x03<<24)|0x026006, (0x04<<24)|0x080408}, // channe1 05
+ {(0x03<<24)|0x026146, (0x04<<24)|0x080408}, // channe1 06
+ {(0x03<<24)|0x026286, (0x04<<24)|0x080408}, // channe1 07
+ {(0x03<<24)|0x0263C6, (0x04<<24)|0x080408}, // channe1 08
+ {(0x03<<24)|0x026506, (0x04<<24)|0x080408}, // channe1 09
+ {(0x03<<24)|0x026646, (0x04<<24)|0x080408}, // channe1 10
+ {(0x03<<24)|0x026786, (0x04<<24)|0x080408}, // channe1 11
+ {(0x03<<24)|0x0268C6, (0x04<<24)|0x080408}, // channe1 12
+ {(0x03<<24)|0x026A06, (0x04<<24)|0x080408}, // channe1 13
+ {(0x03<<24)|0x026D06, (0x04<<24)|0x080408} // channe1 14
+};
+
+u32 w89rf242_power_data_24[] = {(0x05<<24)|0x24C48A, (0x05<<24)|0x24C48A, (0x05<<24)|0x24C48A};
+
+// 20060315.6 Enlarge for new scale
+// 20060316.6 20060619.2.a add mapping array
+u32 w89rf242_txvga_old_mapping[][2] =
+{
+ {0, 0} , // New <-> Old
+ {1, 1} ,
+ {2, 2} ,
+ {3, 3} ,
+ {4, 4} ,
+ {6, 5} ,
+ {8, 6 },
+ {10, 7 },
+ {12, 8 },
+ {14, 9 },
+ {16, 10},
+ {18, 11},
+ {20, 12},
+ {22, 13},
+ {24, 14},
+ {26, 15},
+ {28, 16},
+ {30, 17},
+ {32, 18},
+ {34, 19},
+
+
+};
+
+// 20060619.3 modify from Bruce's mail
+u32 w89rf242_txvga_data[][5] =
+{
+ //low gain mode
+ { (0x05<<24)|0x24C00A, 0, 0x00292315, 0x0800FEFF, 0x52523131 },// ; min gain
+ { (0x05<<24)|0x24C80A, 1, 0x00292315, 0x0800FEFF, 0x52523131 },
+ { (0x05<<24)|0x24C04A, 2, 0x00292315, 0x0800FEFF, 0x52523131 },// (default) +14dBm (ANT)
+ { (0x05<<24)|0x24C84A, 3, 0x00292315, 0x0800FEFF, 0x52523131 },
+
+ //TXVGA=0x10
+ { (0x05<<24)|0x24C40A, 4, 0x00292315, 0x0800FEFF, 0x60603838 },
+ { (0x05<<24)|0x24C40A, 5, 0x00262114, 0x0700FEFF, 0x65653B3B },
+
+ //TXVGA=0x11
+ { (0x05<<24)|0x24C44A, 6, 0x00241F13, 0x0700FFFF, 0x58583333 },
+ { (0x05<<24)|0x24C44A, 7, 0x00292315, 0x0800FEFF, 0x5E5E3737 },
+
+ //TXVGA=0x12
+ { (0x05<<24)|0x24C48A, 8, 0x00262114, 0x0700FEFF, 0x53533030 },
+ { (0x05<<24)|0x24C48A, 9, 0x00241F13, 0x0700FFFF, 0x59593434 },
+
+ //TXVGA=0x13
+ { (0x05<<24)|0x24C4CA, 10, 0x00292315, 0x0800FEFF, 0x52523030 },
+ { (0x05<<24)|0x24C4CA, 11, 0x00262114, 0x0700FEFF, 0x56563232 },
+
+ //TXVGA=0x14
+ { (0x05<<24)|0x24C50A, 12, 0x00292315, 0x0800FEFF, 0x54543131 },
+ { (0x05<<24)|0x24C50A, 13, 0x00262114, 0x0700FEFF, 0x58583434 },
+
+ //TXVGA=0x15
+ { (0x05<<24)|0x24C54A, 14, 0x00292315, 0x0800FEFF, 0x54543131 },
+ { (0x05<<24)|0x24C54A, 15, 0x00262114, 0x0700FEFF, 0x59593434 },
+
+ //TXVGA=0x16
+ { (0x05<<24)|0x24C58A, 16, 0x00292315, 0x0800FEFF, 0x55553131 },
+ { (0x05<<24)|0x24C58A, 17, 0x00292315, 0x0800FEFF, 0x5B5B3535 },
+
+ //TXVGA=0x17
+ { (0x05<<24)|0x24C5CA, 18, 0x00262114, 0x0700FEFF, 0x51512F2F },
+ { (0x05<<24)|0x24C5CA, 19, 0x00241F13, 0x0700FFFF, 0x55553131 },
+
+ //TXVGA=0x18
+ { (0x05<<24)|0x24C60A, 20, 0x00292315, 0x0800FEFF, 0x4F4F2E2E },
+ { (0x05<<24)|0x24C60A, 21, 0x00262114, 0x0700FEFF, 0x53533030 },
+
+ //TXVGA=0x19
+ { (0x05<<24)|0x24C64A, 22, 0x00292315, 0x0800FEFF, 0x4E4E2D2D },
+ { (0x05<<24)|0x24C64A, 23, 0x00262114, 0x0700FEFF, 0x53533030 },
+
+ //TXVGA=0x1A
+ { (0x05<<24)|0x24C68A, 24, 0x00292315, 0x0800FEFF, 0x50502E2E },
+ { (0x05<<24)|0x24C68A, 25, 0x00262114, 0x0700FEFF, 0x55553131 },
+
+ //TXVGA=0x1B
+ { (0x05<<24)|0x24C6CA, 26, 0x00262114, 0x0700FEFF, 0x53533030 },
+ { (0x05<<24)|0x24C6CA, 27, 0x00292315, 0x0800FEFF, 0x5A5A3434 },
+
+ //TXVGA=0x1C
+ { (0x05<<24)|0x24C70A, 28, 0x00292315, 0x0800FEFF, 0x55553131 },
+ { (0x05<<24)|0x24C70A, 29, 0x00292315, 0x0800FEFF, 0x5D5D3636 },
+
+ //TXVGA=0x1D
+ { (0x05<<24)|0x24C74A, 30, 0x00292315, 0x0800FEFF, 0x5F5F3737 },
+ { (0x05<<24)|0x24C74A, 31, 0x00262114, 0x0700FEFF, 0x65653B3B },
+
+ //TXVGA=0x1E
+ { (0x05<<24)|0x24C78A, 32, 0x00292315, 0x0800FEFF, 0x66663B3B },
+ { (0x05<<24)|0x24C78A, 33, 0x00262114, 0x0700FEFF, 0x70704141 },
+
+ //TXVGA=0x1F
+ { (0x05<<24)|0x24C7CA, 34, 0x00292315, 0x0800FEFF, 0x72724242 }
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+//=============================================================================================================
+// Uxx_ReadEthernetAddress --
+//
+// Routine Description:
+// Reads in the Ethernet address from the IC.
+//
+// Arguments:
+// pHwData - The pHwData structure
+//
+// Return Value:
+//
+// The address is stored in EthernetIDAddr.
+//=============================================================================================================
+void
+Uxx_ReadEthernetAddress( phw_data_t pHwData )
+{
+ u32 ltmp;
+
+ // Reading Ethernet address from EEPROM and set into hardware due to MAC address maybe change.
+ // Only unplug and plug again can make hardware read EEPROM again. 20060727
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08000000 ); // Start EEPROM access + Read + address(0x0d)
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+ *(PUSHORT)pHwData->PermanentMacAddress = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08010000 ); // Start EEPROM access + Read + address(0x0d)
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+ *(PUSHORT)(pHwData->PermanentMacAddress + 2) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08020000 ); // Start EEPROM access + Read + address(0x0d)
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+ *(PUSHORT)(pHwData->PermanentMacAddress + 4) = cpu_to_le16((u16)ltmp); //20060926 anson's endian
+ *(PUSHORT)(pHwData->PermanentMacAddress + 6) = 0;
+ Wb35Reg_WriteSync( pHwData, 0x03e8, cpu_to_le32(*(PULONG)pHwData->PermanentMacAddress) ); //20060926 anson's endian
+ Wb35Reg_WriteSync( pHwData, 0x03ec, cpu_to_le32(*(PULONG)(pHwData->PermanentMacAddress+4)) ); //20060926 anson's endian
+}
+
+
+//===============================================================================================================
+// CardGetMulticastBit --
+// Description:
+// For a given multicast address, returns the byte and bit in the card multicast registers that it hashes to.
+// Calls CardComputeCrc() to determine the CRC value.
+// Arguments:
+// Address - the address
+// Byte - the byte that it hashes to
+// Value - will have a 1 in the relevant bit
+// Return Value:
+// None.
+//==============================================================================================================
+void CardGetMulticastBit( u8 Address[ETH_LENGTH_OF_ADDRESS],
+ u8 *Byte, u8 *Value )
+{
+ u32 Crc;
+ u32 BitNumber;
+
+ // First compute the CRC.
+ Crc = CardComputeCrc(Address, ETH_LENGTH_OF_ADDRESS);
+
+ // The computed CRC is bit0~31 from left to right
+ //At first we should do right shift 25bits, and read 7bits by using '&', 2^7=128
+ BitNumber = (u32) ((Crc >> 26) & 0x3f);
+
+ *Byte = (u8) (BitNumber >> 3);// 900514 original (BitNumber / 8)
+ *Value = (u8) ((u8)1 << (BitNumber % 8));
+}
+
+void Uxx_power_on_procedure( phw_data_t pHwData )
+{
+ u32 ltmp, loop;
+
+ if( pHwData->phy_type <= RF_MAXIM_V1 )
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xffffff38 );
+ else
+ {
+ Wb35Reg_WriteSync( pHwData, 0x03f4, 0xFF5807FF );// 20060721 For NEW IC 0xFF5807FF
+
+ // 20060511.1 Fix the following 4 steps for Rx of RF 2230 initial fail
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0x80 );// regulator on only
+ OS_SLEEP(10000); // Modify 20051221.1.b
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xb8 );// REG_ON RF_RSTN on, and
+ OS_SLEEP(10000); // Modify 20051221.1.b
+
+ ltmp = 0x4968;
+ if( (pHwData->phy_type == RF_WB_242) ||
+ (RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
+ ltmp = 0x4468;
+ Wb35Reg_WriteSync( pHwData, 0x03d0, ltmp );
+
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xa0 );// PLL_PD REF_PD set to 0
+
+ OS_SLEEP(20000); // Modify 20051221.1.b
+ Wb35Reg_ReadSync( pHwData, 0x03d0, &ltmp );
+ loop = 500; // Wait for 5 second 20061101
+ while( !(ltmp & 0x20) && loop-- )
+ {
+ OS_SLEEP(10000); // Modify 20051221.1.b
+ if( !Wb35Reg_ReadSync( pHwData, 0x03d0, &ltmp ) )
+ break;
+ }
+
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xe0 );// MLK_EN
+ }
+
+ Wb35Reg_WriteSync( pHwData, 0x03b0, 1 );// Reset hardware first
+ OS_SLEEP(10000); // Add this 20051221.1.b
+
+ // Set burst write delay
+ Wb35Reg_WriteSync( pHwData, 0x03f8, 0x7ff );
+}
+
+void Set_ChanIndep_RfData_al7230_24( phw_data_t pHwData, u32 *pltmp ,char number)
+{
+ u8 i;
+
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = al7230_rf_data_24[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (24 << 24) | (al7230_rf_data_24[i]&0xffffff);
+ }
+}
+
+void Set_ChanIndep_RfData_al7230_50( phw_data_t pHwData, u32 *pltmp, char number)
+{
+ u8 i;
+
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = al7230_rf_data_50[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (24 << 24) | (al7230_rf_data_50[i]&0xffffff);
+ }
+}
+
+
+//=============================================================================================================
+// RFSynthesizer_initial --
+//=============================================================================================================
+void
+RFSynthesizer_initial(phw_data_t pHwData)
+{
+ u32 altmp[32];
+ PULONG pltmp = altmp;
+ u32 ltmp;
+ u8 number=0x00; // The number of register vale
+ u8 i;
+
+ //
+ // bit[31] SPI Enable.
+ // 1=perform synthesizer program operation. This bit will
+ // cleared automatically after the operation is completed.
+ // bit[30] SPI R/W Control
+ // 0=write, 1=read
+ // bit[29:24] SPI Data Format Length
+ // bit[17:4 ] RF Data bits.
+ // bit[3 :0 ] RF address.
+ switch( pHwData->phy_type )
+ {
+ case RF_MAXIM_2825:
+ case RF_MAXIM_V1: // 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331)
+ number = sizeof(max2825_rf_data)/sizeof(max2825_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = max2825_rf_data[i];// Backup Rf parameter
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2825_rf_data[i], 18);
+ }
+ break;
+
+ case RF_MAXIM_2827:
+ number = sizeof(max2827_rf_data)/sizeof(max2827_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = max2827_rf_data[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2827_rf_data[i], 18);
+ }
+ break;
+
+ case RF_MAXIM_2828:
+ number = sizeof(max2828_rf_data)/sizeof(max2828_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = max2828_rf_data[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2828_rf_data[i], 18);
+ }
+ break;
+
+ case RF_MAXIM_2829:
+ number = sizeof(max2829_rf_data)/sizeof(max2829_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = max2829_rf_data[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2829_rf_data[i], 18);
+ }
+ break;
+
+ case RF_AIROHA_2230:
+ number = sizeof(al2230_rf_data)/sizeof(al2230_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = al2230_rf_data[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( al2230_rf_data[i], 20);
+ }
+ break;
+
+ case RF_AIROHA_2230S:
+ number = sizeof(al2230s_rf_data)/sizeof(al2230s_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ pHwData->phy_para[i] = al2230s_rf_data[i];
+ pltmp[i] = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( al2230s_rf_data[i], 20);
+ }
+ break;
+
+ case RF_AIROHA_7230:
+
+ //Start to fill RF parameters, PLL_ON should be pulled low.
+ Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000000 );
+#ifdef _PE_STATE_DUMP_
+ WBDEBUG(("* PLL_ON low\n"));
+#endif
+
+ number = sizeof(al7230_rf_data_24)/sizeof(al7230_rf_data_24[0]);
+ Set_ChanIndep_RfData_al7230_24(pHwData, pltmp, number);
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1: // 20060619.5 Add
+ number = sizeof(w89rf242_rf_data)/sizeof(w89rf242_rf_data[0]);
+ for( i=0; i<number; i++ )
+ {
+ ltmp = w89rf242_rf_data[i];
+ if( i == 4 ) // Update the VCO trim from EEPROM
+ {
+ ltmp &= ~0xff0; // Mask bit4 ~bit11
+ ltmp |= pHwData->VCO_trim<<4;
+ }
+
+ pHwData->phy_para[i] = ltmp;
+ pltmp[i] = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( ltmp, 24);
+ }
+ break;
+ }
+
+ pHwData->phy_number = number;
+
+ // The 16 is the maximum capability of hardware. Here use 12
+ if( number > 12 ) {
+ //Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 12, NO_INCREMENT );
+ for( i=0; i<12; i++ ) // For Al2230
+ Wb35Reg_WriteSync( pHwData, 0x0864, pltmp[i] );
+
+ pltmp += 12;
+ number -= 12;
+ }
+
+ // Write to register. number must less and equal than 16
+ for( i=0; i<number; i++ )
+ Wb35Reg_WriteSync( pHwData, 0x864, pltmp[i] );
+
+ // 20060630.1 Calibration only 1 time
+ if( pHwData->CalOneTime )
+ return;
+ pHwData->CalOneTime = 1;
+
+ switch( pHwData->phy_type )
+ {
+ case RF_AIROHA_2230:
+
+ // 20060511.1 --- Modifying the follow step for Rx issue-----------------
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( (0x07<<20)|0xE168E, 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(10000);
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( al2230_rf_data[7], 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(10000);
+
+ case RF_AIROHA_2230S: // 20060420 Add this
+
+ // 20060511.1 --- Modifying the follow step for Rx issue-----------------
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0x80 );// regulator on only
+ OS_SLEEP(10000); // Modify 20051221.1.b
+
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xa0 );// PLL_PD REF_PD set to 0
+ OS_SLEEP(10000); // Modify 20051221.1.b
+
+ Wb35Reg_WriteSync( pHwData, 0x03d4, 0xe0 );// MLK_EN
+ Wb35Reg_WriteSync( pHwData, 0x03b0, 1 );// Reset hardware first
+ OS_SLEEP(10000); // Add this 20051221.1.b
+ //------------------------------------------------------------------------
+
+ // The follow code doesn't use the burst-write mode
+ //phy_set_rf_data(phw_data, 0x0F, (0x0F<<20) | 0xF01A0); //Raise Initial Setting
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( (0x0F<<20) | 0xF01A0, 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ ltmp = pHwData->Wb35Reg.BB5C & 0xfffff000;
+ Wb35Reg_WriteSync( pHwData, 0x105c, ltmp );
+ pHwData->Wb35Reg.BB50 |= 0x13;//(MASK_IQCAL_MODE|MASK_CALIB_START);//20060315.1 modify
+ Wb35Reg_WriteSync( pHwData, 0x1050, pHwData->Wb35Reg.BB50);
+ OS_SLEEP(5000);
+
+ //phy_set_rf_data(phw_data, 0x0F, (0x0F<<20) | 0xF01B0); //Activate Filter Cal.
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( (0x0F<<20) | 0xF01B0, 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+
+ //phy_set_rf_data(phw_data, 0x0F, (0x0F<<20) | 0xF01e0); //Activate TX DCC
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( (0x0F<<20) | 0xF01E0, 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+
+ //phy_set_rf_data(phw_data, 0x0F, (0x0F<<20) | 0xF01A0); //Resotre Initial Setting
+ ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( (0x0F<<20) | 0xF01A0, 20);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+// //Force TXI(Q)P(N) to normal control
+ Wb35Reg_WriteSync( pHwData, 0x105c, pHwData->Wb35Reg.BB5C );
+ pHwData->Wb35Reg.BB50 &= ~0x13;//(MASK_IQCAL_MODE|MASK_CALIB_START);
+ Wb35Reg_WriteSync( pHwData, 0x1050, pHwData->Wb35Reg.BB50);
+ break;
+
+ case RF_AIROHA_7230:
+
+ //RF parameters have filled completely, PLL_ON should be
+ //pulled high
+ Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 );
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("* PLL_ON high\n"));
+ #endif
+
+ //2.4GHz
+ //ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x1ABA8F;
+ //Wb35Reg_WriteSync pHwData, 0x0864, ltmp );
+ //OS_SLEEP(1000); // Sleep 1 ms
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x9ABA8F;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x3ABA8F;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x1ABA8F;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+
+ //5GHz
+ Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000000 );
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("* PLL_ON low\n"));
+ #endif
+
+ number = sizeof(al7230_rf_data_50)/sizeof(al7230_rf_data_50[0]);
+ Set_ChanIndep_RfData_al7230_50(pHwData, pltmp, number);
+ // Write to register. number must less and equal than 16
+ for( i=0; i<number; i++ )
+ Wb35Reg_WriteSync( pHwData, 0x0864, pltmp[i] );
+ OS_SLEEP(5000);
+
+ Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 );
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("* PLL_ON high\n"));
+ #endif
+
+ //ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x12BACF;
+ //Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x9ABA8F;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x3ABA8F;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x12BACF;
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000);
+
+ //Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 );
+ //WBDEBUG(("* PLL_ON high\n"));
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1: // 20060619.5 Add
+
+ //
+ // ; Version 1.3B revision items: for FA5976A , October 3, 2005 by HTHo
+ //
+ ltmp = pHwData->Wb35Reg.BB5C & 0xfffff000;
+ Wb35Reg_WriteSync( pHwData, 0x105c, ltmp );
+ Wb35Reg_WriteSync( pHwData, 0x1058, 0 );
+ pHwData->Wb35Reg.BB50 |= 0x3;//(MASK_IQCAL_MODE|MASK_CALIB_START);//20060630
+ Wb35Reg_WriteSync( pHwData, 0x1050, pHwData->Wb35Reg.BB50);
+
+ //----- Calibration (1). VCO frequency calibration
+ //Calibration (1a.0). Synthesizer reset (HTHo corrected 2005/05/10)
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x0F<<24) | 0x00101E, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP( 5000 ); // Sleep 5ms
+ //Calibration (1a). VCO frequency calibration mode ; waiting 2msec VCO calibration time
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFE69c0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP( 2000 ); // Sleep 2ms
+
+ //----- Calibration (2). TX baseband Gm-C filter auto-tuning
+ //Calibration (2a). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xF8EBC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (2b.0). TX filter auto-tuning BW: TFLBW=101 (TC5376A default)
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x07<<24) | 0x0C68CE, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (2b). send TX reset signal (HTHo corrected May 10, 2005)
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x0F<<24) | 0x00201E, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (2c). turn-on TX Gm-C filter auto-tuning
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFCEBC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP( 150 ); // Sleep 150 us
+ //turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xF8EBC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //----- Calibration (3). RX baseband Gm-C filter auto-tuning
+ //Calibration (3a). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (3b.0). RX filter auto-tuning BW: RFLBW=100 (TC5376A+corner default; July 26, 2005)
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x07<<24) | 0x0C68CE, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (3b). send RX reset signal (HTHo corrected May 10, 2005)
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x0F<<24) | 0x00401E, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (3c). turn-on RX Gm-C filter auto-tuning
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFEEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP( 150 ); // Sleep 150 us
+ //Calibration (3e). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //----- Calibration (4). TX LO leakage calibration
+ //Calibration (4a). TX LO leakage calibration
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFD6BC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP( 150 ); // Sleep 150 us
+
+ //----- Calibration (5). RX DC offset calibration
+ //Calibration (5a). turn off ENCAL signal and set to RX SW DC caliration mode
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5b). turn off AGC servo-loop & RSSI
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x01<<24) | 0xEBFFC2, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //; for LNA=11 --------
+ //Calibration (5c-h). RX DC offset current bias ON; & LNA=11; RXVGA=111111
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x06<<24) | 0x343FCC, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5d). turn on RX DC offset cal function; and waiting 2 msec cal time
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFF6DC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(2000); // Sleep 2ms
+ //Calibration (5f). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //; for LNA=10 --------
+ //Calibration (5c-m). RX DC offset current bias ON; & LNA=10; RXVGA=111111
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x06<<24) | 0x342FCC, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5d). turn on RX DC offset cal function; and waiting 2 msec cal time
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFF6DC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(2000); // Sleep 2ms
+ //Calibration (5f). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //; for LNA=01 --------
+ //Calibration (5c-m). RX DC offset current bias ON; & LNA=01; RXVGA=111111
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x06<<24) | 0x341FCC, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5d). turn on RX DC offset cal function; and waiting 2 msec cal time
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFF6DC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(2000); // Sleep 2ms
+ //Calibration (5f). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //; for LNA=00 --------
+ //Calibration (5c-l). RX DC offset current bias ON; & LNA=00; RXVGA=111111
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x06<<24) | 0x340FCC, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5d). turn on RX DC offset cal function; and waiting 2 msec cal time
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFF6DC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(2000); // Sleep 2ms
+ //Calibration (5f). turn off ENCAL signal
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xFAEDC0, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ //Calibration (5g). turn on AGC servo-loop
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x01<<24) | 0xEFFFC2, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+
+ //; ----- Calibration (7). Switch RF chip to normal mode
+ //0x00 0xF86100 ; 3E184 ; Switch RF chip to normal mode
+// OS_SLEEP(10000); // @@ 20060721
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( (0x00<<24) | 0xF86100, 24);
+ Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
+ OS_SLEEP(5000); // Sleep 5 ms
+
+// //write back
+// Wb35Reg_WriteSync( pHwData, 0x105c, pHwData->Wb35Reg.BB5C );
+// pHwData->Wb35Reg.BB50 &= ~0x13;//(MASK_IQCAL_MODE|MASK_CALIB_START); // 20060315.1 fix
+// Wb35Reg_WriteSync( pHwData, 0x1050, pHwData->Wb35Reg.BB50);
+// OS_SLEEP(1000); // Sleep 1 ms
+ break;
+ }
+}
+
+void BBProcessor_AL7230_2400( phw_data_t pHwData)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 pltmp[12];
+
+ pltmp[0] = 0x16A8337A; // 0x16a5215f; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9AFF9AA6; // 0x9aff9ca6; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55D00A04; // 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xFFF72031; // 0xFfFf2138; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0C = 0xFFF72031;
+ pltmp[4] = 0x0FacDCC5; // 0x1010 AGC_Ctrl5 // 20050927 0x0FacDCB7
+ pltmp[5] = 0x00CAA333; // 0x00eaa333; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xF2211111; // 0x11111111; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x06443440; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0xA8002A79; // 0xa9002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000528; // 20050927 0x40000228
+ pltmp[11] = 0x232D7F30; // 0x23457f30;// 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x232D7F30;
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002c54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002c54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x00332C1B; // 0x00453B24; // 0x1048 11b TX RC filter
+ pltmp[7] = 0x0A00FEFF; // 0x0E00FEFF; // 0x104c 11b TX RC filter
+ pltmp[8] = 0x2B106208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x2B106208;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x52524242; // 0x64645252; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x52524242;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+}
+
+void BBProcessor_AL7230_5000( phw_data_t pHwData)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 pltmp[12];
+
+ pltmp[0] = 0x16AA6678; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9AFFA0B2; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55D00A04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xEFFF233E; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0C = 0xEFFF233E;
+ pltmp[4] = 0x0FacDCC5; // 0x1010 AGC_Ctrl5 // 20050927 0x0FacDCB7
+ pltmp[5] = 0x00CAA333; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xF2432111; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x05C43440; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000528; // 20050927 0x40000228
+ pltmp[11] = 0x232FDF30;// 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x232FDF30;
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x80002C7C; // 0x1030 B_ACQ_Ctrl
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x00332C1B; // 0x1048 11b TX RC filter
+ pltmp[7] = 0x0A00FEFF; // 0x104c 11b TX RC filter
+ pltmp[8] = 0x2B107208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x2B107208;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x52524242; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x52524242;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+}
+
+//=============================================================================================================
+// BBProcessorPowerupInit --
+//
+// Description:
+// Initialize the Baseband processor.
+//
+// Arguments:
+// pHwData - Handle of the USB Device.
+//
+// Return values:
+// None.
+//=============================================================================================================
+void
+BBProcessor_initial( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 i, pltmp[12];
+
+ switch( pHwData->phy_type )
+ {
+ case RF_MAXIM_V1: // Initializng the Winbond 2nd BB(with Phy board (v1) + Maxim 331)
+
+ pltmp[0] = 0x16F47E77; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9AFFAEA4; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55D00A04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xEFFF1A34; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0C = 0xEFFF1A34;
+ pltmp[4] = 0x0FABE0B7; // 0x1010 AGC_Ctrl5
+ pltmp[5] = 0x00CAA332; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xF6632111; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04CC3640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = (pHwData->phy_type==3) ? 0x40000a28 : 0x40000228; // 0x1028 MAXIM_331(b31=0) + WBRF_V1(b11=1) : MAXIM_331(b31=0) + WBRF_V2(b11=0)
+ pltmp[11] = 0x232FDF30; // 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x232FDF30; //Modify for 33's 1.0.95.xxx version, antenna 1
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B6C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x00453B24; // 0x1048 11b TX RC filter
+ pltmp[7] = 0x0E00FEFF; // 0x104c 11b TX RC filter
+ pltmp[8] = 0x27106208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106208;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x64646464; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x64646464;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ //------------------------------------------------------------------
+ //[20040722 WK]
+ //Only for baseband version 2
+// case RF_MAXIM_317:
+ case RF_MAXIM_2825:
+ case RF_MAXIM_2827:
+ case RF_MAXIM_2828:
+
+ pltmp[0] = 0x16b47e77; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9affaea4; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xefff1a34; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0C = 0xefff1a34;
+ pltmp[4] = 0x0fabe0b7; // 0x1010 AGC_Ctrl5
+ pltmp[5] = 0x00caa332; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xf6632111; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04CC3640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000528; // 0x40000128; Modify for 33's 1.0.95
+ pltmp[11] = 0x232fdf30; // 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x232fdf30; //Modify for 33's 1.0.95.xxx version, antenna 1
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B6C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x00453B24; // 0x1048 11b TX RC filter
+ pltmp[7] = 0x0D00FDFF; // 0x104c 11b TX RC filter
+ pltmp[8] = 0x27106208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106208;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x64646464; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x64646464;
+ pltmp[11] = 0xAA28C000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ case RF_MAXIM_2829:
+
+ pltmp[0] = 0x16b47e77; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9affaea4; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xf4ff1632; // 0xefff1a34; // 0x100c AGC_Ctrl4 Modify for 33's 1.0.95
+ pWb35Reg->BB0C = 0xf4ff1632; // 0xefff1a34; Modify for 33's 1.0.95
+ pltmp[4] = 0x0fabe0b7; // 0x1010 AGC_Ctrl5
+ pltmp[5] = 0x00caa332; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xf8632112; // 0xf6632111; // 0x1018 AGC_Ctrl7 Modify for 33's 1.0.95
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04CC3640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000528; // 0x40000128; modify for 33's 1.0.95
+ pltmp[11] = 0x232fdf30; // 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x232fdf30; //Modify for 33's 1.0.95.xxx version, antenna 1
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5b2c8769; // 0x5B6C8769; // 0x1038 B_TXRX_Ctrl Modify for 33's 1.0.95
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x002c2617; // 0x00453B24; // 0x1048 11b TX RC filter Modify for 33's 1.0.95
+ pltmp[7] = 0x0800feff; // 0x0D00FDFF; // 0x104c 11b TX RC filter Modify for 33's 1.0.95
+ pltmp[8] = 0x27106208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106208;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x64644a4a; // 0x64646464; // 0x1058 IQ_Alpha Modify for 33's 1.0.95
+ pWb35Reg->BB58 = 0x64646464;
+ pltmp[11] = 0xAA28C000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ case RF_AIROHA_2230:
+
+ pltmp[0] = 0X16764A77; // 0x1000 AGC_Ctrl1 //0x16765A77
+ pltmp[1] = 0x9affafb2; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xFFFd203c; // 0xFFFb203a; // 0x100c AGC_Ctrl4 Modify for 33's 1.0.95.xxx version
+ pWb35Reg->BB0C = 0xFFFd203c;
+ pltmp[4] = 0X0FBFDCc5; // 0X0FBFDCA0; // 0x1010 AGC_Ctrl5 //0x0FB2E0B7 Modify for 33's 1.0.95.xxx version
+ pltmp[5] = 0x00caa332; // 0x00caa333; // 0x1014 AGC_Ctrl6 Modify for 33's 1.0.95.xxx version
+ pltmp[6] = 0XF6632111; // 0XF1632112; // 0x1018 AGC_Ctrl7 //0xf6632112 Modify for 33's 1.0.95.xxx version
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04C43640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0X40000528; //0x40000228
+ pltmp[11] = 0x232dfF30; // 0x232A9F30; // 0x102c A_ACQ_Ctrl //0x232a9730
+ pWb35Reg->BB2C = 0x232dfF30; //Modify for 33's 1.0.95.xxx version, antenna 1
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl //0x5B6C8769
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = BB48_DEFAULT_AL2230_11G; // 0x1048 11b TX RC filter 20060613.2
+ pWb35Reg->BB48 = BB48_DEFAULT_AL2230_11G; // 20051221 ch14 20060613.2
+ pltmp[7] = BB4C_DEFAULT_AL2230_11G; // 0x104c 11b TX RC filter 20060613.2
+ pWb35Reg->BB4C = BB4C_DEFAULT_AL2230_11G; // 20060613.1 20060613.2
+ pltmp[8] = 0x27106200; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106200;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x52524242; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x52524242;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ case RF_AIROHA_2230S: // 20060420 Add this
+
+ pltmp[0] = 0X16764A77; // 0x1000 AGC_Ctrl1 //0x16765A77
+ pltmp[1] = 0x9affafb2; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xFFFd203c; // 0xFFFb203a; // 0x100c AGC_Ctrl4 Modify for 33's 1.0.95.xxx version
+ pWb35Reg->BB0C = 0xFFFd203c;
+ pltmp[4] = 0X0FBFDCc5; // 0X0FBFDCA0; // 0x1010 AGC_Ctrl5 //0x0FB2E0B7 Modify for 33's 1.0.95.xxx version
+ pltmp[5] = 0x00caa332; // 0x00caa333; // 0x1014 AGC_Ctrl6 Modify for 33's 1.0.95.xxx version
+ pltmp[6] = 0XF6632111; // 0XF1632112; // 0x1018 AGC_Ctrl7 //0xf6632112 Modify for 33's 1.0.95.xxx version
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04C43640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0X40000528; //0x40000228
+ pltmp[11] = 0x232dfF30; // 0x232A9F30; // 0x102c A_ACQ_Ctrl //0x232a9730
+ pWb35Reg->BB2C = 0x232dfF30; //Modify for 33's 1.0.95.xxx version, antenna 1
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl //0x5B6C8769
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = BB48_DEFAULT_AL2230_11G; // 0x1048 11b TX RC filter 20060613.2
+ pWb35Reg->BB48 = BB48_DEFAULT_AL2230_11G; // 20051221 ch14 20060613.2
+ pltmp[7] = BB4C_DEFAULT_AL2230_11G; // 0x104c 11b TX RC filter 20060613.2
+ pWb35Reg->BB4C = BB4C_DEFAULT_AL2230_11G; // 20060613.1
+ pltmp[8] = 0x27106200; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106200;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x52523232; // 20060419 0x52524242; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x52523232; // 20060419 0x52524242;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ case RF_AIROHA_7230:
+/*
+ pltmp[0] = 0x16a84a77; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9affafb2; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55d00a04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xFFFb203a; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0c = 0xFFFb203a;
+ pltmp[4] = 0x0FBFDCB7; // 0x1010 AGC_Ctrl5
+ pltmp[5] = 0x00caa333; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0xf6632112; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04C43640; // 0x1020 AGC_Ctrl9
+ pltmp[9] = 0x00002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000228;
+ pltmp[11] = 0x232A9F30;// 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2c = 0x232A9F30;
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = 0x00000000; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3c = 0x00000000;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = 0x00453B24; // 0x1048 11b TX RC filter
+ pltmp[7] = 0x0E00FEFF; // 0x104c 11b TX RC filter
+ pltmp[8] = 0x27106200; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106200;
+ pltmp[9] = 0; // 0x1054
+ pWb35Reg->BB54 = 0x00000000;
+ pltmp[10] = 0x64645252; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x64645252;
+ pltmp[11] = 0xAA0AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+*/
+ BBProcessor_AL7230_2400( pHwData );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1: // 20060619.5 Add
+
+ pltmp[0] = 0x16A8525D; // 0x1000 AGC_Ctrl1
+ pltmp[1] = 0x9AFF9ABA; // 0x1004 AGC_Ctrl2
+ pltmp[2] = 0x55D00A04; // 0x1008 AGC_Ctrl3
+ pltmp[3] = 0xEEE91C32; // 0x100c AGC_Ctrl4
+ pWb35Reg->BB0C = 0xEEE91C32;
+ pltmp[4] = 0x0FACDCC5; // 0x1010 AGC_Ctrl5
+ pltmp[5] = 0x000AA344; // 0x1014 AGC_Ctrl6
+ pltmp[6] = 0x22222221; // 0x1018 AGC_Ctrl7
+ pltmp[7] = 0x0FA3F0ED; // 0x101c AGC_Ctrl8
+ pltmp[8] = 0x04CC3440; // 20051018 0x03CB3440; // 0x1020 AGC_Ctrl9 20051014 0x03C33440
+ pltmp[9] = 0xA9002A79; // 0x1024 AGC_Ctrl10
+ pltmp[10] = 0x40000528; // 0x1028
+ pltmp[11] = 0x23457F30; // 0x102c A_ACQ_Ctrl
+ pWb35Reg->BB2C = 0x23457F30;
+ Wb35Reg_BurstWrite( pHwData, 0x1000, pltmp, 12, AUTO_INCREMENT );
+
+ pltmp[0] = 0x00002C54; // 0x1030 B_ACQ_Ctrl
+ pWb35Reg->BB30 = 0x00002C54;
+ pltmp[1] = 0x00C0D6C5; // 0x1034 A_TXRX_Ctrl
+ pltmp[2] = 0x5B2C8769; // 0x1038 B_TXRX_Ctrl
+ pltmp[3] = pHwData->BB3c_cal; // 0x103c 11a TX LS filter
+ pWb35Reg->BB3C = pHwData->BB3c_cal;
+ pltmp[4] = 0x00003F29; // 0x1040 11a TX LS filter
+ pltmp[5] = 0x0EFEFBFE; // 0x1044 11a TX LS filter
+ pltmp[6] = BB48_DEFAULT_WB242_11G; // 0x1048 11b TX RC filter 20060613.2
+ pWb35Reg->BB48 = BB48_DEFAULT_WB242_11G; // 20060613.1 20060613.2
+ pltmp[7] = BB4C_DEFAULT_WB242_11G; // 0x104c 11b TX RC filter 20060613.2
+ pWb35Reg->BB4C = BB4C_DEFAULT_WB242_11G; // 20060613.1 20060613.2
+ pltmp[8] = 0x27106208; // 0x1050 MODE_Ctrl
+ pWb35Reg->BB50 = 0x27106208;
+ pltmp[9] = pHwData->BB54_cal; // 0x1054
+ pWb35Reg->BB54 = pHwData->BB54_cal;
+ pltmp[10] = 0x52523131; // 0x1058 IQ_Alpha
+ pWb35Reg->BB58 = 0x52523131;
+ pltmp[11] = 0xAA0AC000; // 20060825 0xAA2AC000; // 0x105c DC_Cancel
+ Wb35Reg_BurstWrite( pHwData, 0x1030, pltmp, 12, AUTO_INCREMENT );
+
+ Wb35Reg_Write( pHwData, 0x1070, 0x00000045 );
+ break;
+ }
+
+ // Fill the LNA table
+ pWb35Reg->LNAValue[0] = (u8)(pWb35Reg->BB0C & 0xff);
+ pWb35Reg->LNAValue[1] = 0;
+ pWb35Reg->LNAValue[2] = (u8)((pWb35Reg->BB0C & 0xff00)>>8);
+ pWb35Reg->LNAValue[3] = 0;
+
+ // Fill SQ3 table
+ for( i=0; i<MAX_SQ3_FILTER_SIZE; i++ )
+ pWb35Reg->SQ3_filter[i] = 0x2f; // half of Bit 0 ~ 6
+}
+
+void set_tx_power_per_channel_max2829( phw_data_t pHwData, ChanInfo Channel)
+{
+ RFSynthesizer_SetPowerIndex( pHwData, 100 ); // 20060620.1 Modify
+}
+
+void set_tx_power_per_channel_al2230( phw_data_t pHwData, ChanInfo Channel )
+{
+ u8 index = 100;
+
+ if (pHwData->TxVgaFor24[Channel.ChanNo - 1] != 0xff) // 20060620.1 Add
+ index = pHwData->TxVgaFor24[Channel.ChanNo - 1];
+
+ RFSynthesizer_SetPowerIndex( pHwData, index );
+}
+
+void set_tx_power_per_channel_al7230( phw_data_t pHwData, ChanInfo Channel)
+{
+ u8 i, index = 100;
+
+ switch ( Channel.band )
+ {
+ case BAND_TYPE_DSSS:
+ case BAND_TYPE_OFDM_24:
+ {
+ if (pHwData->TxVgaFor24[Channel.ChanNo - 1] != 0xff)
+ index = pHwData->TxVgaFor24[Channel.ChanNo - 1];
+ }
+ break;
+ case BAND_TYPE_OFDM_5:
+ {
+ for (i =0; i<35; i++)
+ {
+ if (Channel.ChanNo == pHwData->TxVgaFor50[i].ChanNo)
+ {
+ if (pHwData->TxVgaFor50[i].TxVgaValue != 0xff)
+ index = pHwData->TxVgaFor50[i].TxVgaValue;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ RFSynthesizer_SetPowerIndex( pHwData, index );
+}
+
+void set_tx_power_per_channel_wb242( phw_data_t pHwData, ChanInfo Channel)
+{
+ u8 index = 100;
+
+ switch ( Channel.band )
+ {
+ case BAND_TYPE_DSSS:
+ case BAND_TYPE_OFDM_24:
+ {
+ if (pHwData->TxVgaFor24[Channel.ChanNo - 1] != 0xff)
+ index = pHwData->TxVgaFor24[Channel.ChanNo - 1];
+ }
+ break;
+ case BAND_TYPE_OFDM_5:
+ break;
+ }
+ RFSynthesizer_SetPowerIndex( pHwData, index );
+}
+
+//=============================================================================================================
+// RFSynthesizer_SwitchingChannel --
+//
+// Description:
+// Swithch the RF channel.
+//
+// Arguments:
+// pHwData - Handle of the USB Device.
+// Channel - The channel no.
+//
+// Return values:
+// None.
+//=============================================================================================================
+void
+RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 pltmp[16]; // The 16 is the maximum capability of hardware
+ u32 count, ltmp;
+ u8 i, j, number;
+ u8 ChnlTmp;
+
+ switch( pHwData->phy_type )
+ {
+ case RF_MAXIM_2825:
+ case RF_MAXIM_V1: // 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331)
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 13
+ {
+ for( i=0; i<3; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2825_channel_data_24[Channel.ChanNo-1][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ RFSynthesizer_SetPowerIndex( pHwData, 100 );
+ break;
+
+ case RF_MAXIM_2827:
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 13
+ {
+ for( i=0; i<3; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2827_channel_data_24[Channel.ChanNo-1][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ else if( Channel.band == BAND_TYPE_OFDM_5 ) // channel 36 ~ 64
+ {
+ ChnlTmp = (Channel.ChanNo - 36) / 4;
+ for( i=0; i<3; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2827_channel_data_50[ChnlTmp][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ RFSynthesizer_SetPowerIndex( pHwData, 100 );
+ break;
+
+ case RF_MAXIM_2828:
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 13
+ {
+ for( i=0; i<3; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2828_channel_data_24[Channel.ChanNo-1][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ else if( Channel.band == BAND_TYPE_OFDM_5 ) // channel 36 ~ 64
+ {
+ ChnlTmp = (Channel.ChanNo - 36) / 4;
+ for ( i = 0; i < 3; i++)
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2828_channel_data_50[ChnlTmp][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ RFSynthesizer_SetPowerIndex( pHwData, 100 );
+ break;
+
+ case RF_MAXIM_2829:
+
+ if( Channel.band <= BAND_TYPE_OFDM_24)
+ {
+ for( i=0; i<3; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2829_channel_data_24[Channel.ChanNo-1][i], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ else if( Channel.band == BAND_TYPE_OFDM_5 )
+ {
+ count = sizeof(max2829_channel_data_50) / sizeof(max2829_channel_data_50[0]);
+
+ for( i=0; i<count; i++ )
+ {
+ if( max2829_channel_data_50[i][0] == Channel.ChanNo )
+ {
+ for( j=0; j<3; j++ )
+ pltmp[j] = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2829_channel_data_50[i][j+1], 18);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+
+ if( (max2829_channel_data_50[i][3] & 0x3FFFF) == 0x2A946 )
+ {
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( (5<<18)|0x2A906, 18);
+ Wb35Reg_Write( pHwData, 0x0864, ltmp );
+ }
+ else // 0x2A9C6
+ {
+ ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( (5<<18)|0x2A986, 18);
+ Wb35Reg_Write( pHwData, 0x0864, ltmp );
+ }
+ }
+ }
+ }
+ set_tx_power_per_channel_max2829( pHwData, Channel );
+ break;
+
+ case RF_AIROHA_2230:
+ case RF_AIROHA_2230S: // 20060420 Add this
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 14
+ {
+ for( i=0; i<2; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( al2230_channel_data_24[Channel.ChanNo-1][i], 20);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 2, NO_INCREMENT );
+ }
+ set_tx_power_per_channel_al2230( pHwData, Channel );
+ break;
+
+ case RF_AIROHA_7230:
+
+ //Start to fill RF parameters, PLL_ON should be pulled low.
+ //Wb35Reg_Write( pHwData, 0x03dc, 0x00000000 );
+ //WBDEBUG(("* PLL_ON low\n"));
+
+ //Channel independent registers
+ if( Channel.band != pHwData->band)
+ {
+ if (Channel.band <= BAND_TYPE_OFDM_24)
+ {
+ //Update BB register
+ BBProcessor_AL7230_2400(pHwData);
+
+ number = sizeof(al7230_rf_data_24)/sizeof(al7230_rf_data_24[0]);
+ Set_ChanIndep_RfData_al7230_24(pHwData, pltmp, number);
+ }
+ else
+ {
+ //Update BB register
+ BBProcessor_AL7230_5000(pHwData);
+
+ number = sizeof(al7230_rf_data_50)/sizeof(al7230_rf_data_50[0]);
+ Set_ChanIndep_RfData_al7230_50(pHwData, pltmp, number);
+ }
+
+ // Write to register. number must less and equal than 16
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, number, NO_INCREMENT );
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("Band changed\n"));
+ #endif
+ }
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 14
+ {
+ for( i=0; i<2; i++ )
+ pltmp[i] = (1 << 31) | (0 << 30) | (24 << 24) | (al7230_channel_data_24[Channel.ChanNo-1][i]&0xffffff);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 2, NO_INCREMENT );
+ }
+ else if( Channel.band == BAND_TYPE_OFDM_5 )
+ {
+ //Update Reg12
+ if ((Channel.ChanNo > 64) && (Channel.ChanNo <= 165))
+ {
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x00143c;
+ Wb35Reg_Write( pHwData, 0x0864, ltmp );
+ }
+ else //reg12 = 0x00147c at Channel 4920 ~ 5320
+ {
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x00147c;
+ Wb35Reg_Write( pHwData, 0x0864, ltmp );
+ }
+
+ count = sizeof(al7230_channel_data_5) / sizeof(al7230_channel_data_5[0]);
+
+ for (i=0; i<count; i++)
+ {
+ if (al7230_channel_data_5[i][0] == Channel.ChanNo)
+ {
+ for( j=0; j<3; j++ )
+ pltmp[j] = (1 << 31) | (0 << 30) | (24 << 24) | ( al7230_channel_data_5[i][j+1]&0xffffff);
+ Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, 3, NO_INCREMENT );
+ }
+ }
+ }
+ set_tx_power_per_channel_al7230(pHwData, Channel);
+ break;
+
+ case RF_WB_242:
+ case RF_WB_242_1: // 20060619.5 Add
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 ) // channel 1 ~ 14
+ {
+ ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( w89rf242_channel_data_24[Channel.ChanNo-1][0], 24);
+ Wb35Reg_Write( pHwData, 0x864, ltmp );
+ }
+ set_tx_power_per_channel_wb242(pHwData, Channel);
+ break;
+ }
+
+ if( Channel.band <= BAND_TYPE_OFDM_24 )
+ {
+ // BB: select 2.4 GHz, bit[12-11]=00
+ pWb35Reg->BB50 &= ~(BIT(11)|BIT(12));
+ Wb35Reg_Write( pHwData, 0x1050, pWb35Reg->BB50 ); // MODE_Ctrl
+ // MAC: select 2.4 GHz, bit[5]=0
+ pWb35Reg->M78_ERPInformation &= ~BIT(5);
+ Wb35Reg_Write( pHwData, 0x0878, pWb35Reg->M78_ERPInformation );
+ // enable 11b Baseband
+ pWb35Reg->BB30 &= ~BIT(31);
+ Wb35Reg_Write( pHwData, 0x1030, pWb35Reg->BB30 );
+ }
+ else if( (Channel.band == BAND_TYPE_OFDM_5) )
+ {
+ // BB: select 5 GHz
+ pWb35Reg->BB50 &= ~(BIT(11)|BIT(12));
+ if (Channel.ChanNo <=64 )
+ pWb35Reg->BB50 |= BIT(12); // 10-5.25GHz
+ else if ((Channel.ChanNo >= 100) && (Channel.ChanNo <= 124))
+ pWb35Reg->BB50 |= BIT(11); // 01-5.48GHz
+ else if ((Channel.ChanNo >=128) && (Channel.ChanNo <= 161))
+ pWb35Reg->BB50 |= (BIT(12)|BIT(11)); // 11-5.775GHz
+ else //Chan 184 ~ 196 will use bit[12-11] = 10 in version sh-src-1.2.25
+ pWb35Reg->BB50 |= BIT(12);
+ Wb35Reg_Write( pHwData, 0x1050, pWb35Reg->BB50 ); // MODE_Ctrl
+
+ //(1) M78 should alway use 2.4G setting when using RF_AIROHA_7230
+ //(2) BB30 has been updated previously.
+ if (pHwData->phy_type != RF_AIROHA_7230)
+ {
+ // MAC: select 5 GHz, bit[5]=1
+ pWb35Reg->M78_ERPInformation |= BIT(5);
+ Wb35Reg_Write( pHwData, 0x0878, pWb35Reg->M78_ERPInformation );
+
+ // disable 11b Baseband
+ pWb35Reg->BB30 |= BIT(31);
+ Wb35Reg_Write( pHwData, 0x1030, pWb35Reg->BB30 );
+ }
+ }
+}
+
+//Set the tx power directly from DUT GUI, not from the EEPROM. Return the current setting
+u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex )
+{
+ u32 Band = pHwData->band;
+ u8 index=0;
+
+ if( pHwData->power_index == PowerIndex ) // 20060620.1 Add
+ return PowerIndex;
+
+ if (RF_MAXIM_2825 == pHwData->phy_type)
+ {
+ // Channel 1 - 13
+ index = RFSynthesizer_SetMaxim2825Power( pHwData, PowerIndex );
+ }
+ else if (RF_MAXIM_2827 == pHwData->phy_type)
+ {
+ if( Band <= BAND_TYPE_OFDM_24 ) // Channel 1 - 13
+ index = RFSynthesizer_SetMaxim2827_24Power( pHwData, PowerIndex );
+ else// if( Band == BAND_TYPE_OFDM_5 ) // Channel 36 - 64
+ index = RFSynthesizer_SetMaxim2827_50Power( pHwData, PowerIndex );
+ }
+ else if (RF_MAXIM_2828 == pHwData->phy_type)
+ {
+ if( Band <= BAND_TYPE_OFDM_24 ) // Channel 1 - 13
+ index = RFSynthesizer_SetMaxim2828_24Power( pHwData, PowerIndex );
+ else// if( Band == BAND_TYPE_OFDM_5 ) // Channel 36 - 64
+ index = RFSynthesizer_SetMaxim2828_50Power( pHwData, PowerIndex );
+ }
+ else if( RF_AIROHA_2230 == pHwData->phy_type )
+ {
+ //Power index: 0 ~ 63 // Channel 1 - 14
+ index = RFSynthesizer_SetAiroha2230Power( pHwData, PowerIndex );
+ index = (u8)al2230_txvga_data[index][1];
+ }
+ else if( RF_AIROHA_2230S == pHwData->phy_type ) // 20060420 Add this
+ {
+ //Power index: 0 ~ 63 // Channel 1 - 14
+ index = RFSynthesizer_SetAiroha2230Power( pHwData, PowerIndex );
+ index = (u8)al2230_txvga_data[index][1];
+ }
+ else if( RF_AIROHA_7230 == pHwData->phy_type )
+ {
+ //Power index: 0 ~ 63
+ index = RFSynthesizer_SetAiroha7230Power( pHwData, PowerIndex );
+ index = (u8)al7230_txvga_data[index][1];
+ }
+ else if( (RF_WB_242 == pHwData->phy_type) ||
+ (RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
+ {
+ //Power index: 0 ~ 19 for original. New range is 0 ~ 33
+ index = RFSynthesizer_SetWinbond242Power( pHwData, PowerIndex );
+ index = (u8)w89rf242_txvga_data[index][1];
+ }
+
+ pHwData->power_index = index; // Backup current
+ return index;
+}
+
+//-- Sub function
+u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ if( index > 1 ) index = 1;
+ PowerData = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2828_power_data_24[index], 18);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return index;
+}
+//--
+u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ if( index > 1 ) index = 1;
+ PowerData = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2828_power_data_50[index], 18);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return index;
+}
+//--
+u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ if( index > 1 ) index = 1;
+ PowerData = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2827_power_data_24[index], 18);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return index;
+}
+//--
+u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ if( index > 1 ) index = 1;
+ PowerData = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2827_power_data_50[index], 18);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return index;
+}
+//--
+u8 RFSynthesizer_SetMaxim2825Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ if( index > 1 ) index = 1;
+ PowerData = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( max2825_power_data_24[index], 18);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return index;
+}
+//--
+u8 RFSynthesizer_SetAiroha2230Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ u8 i,count;
+
+ count = sizeof(al2230_txvga_data) / sizeof(al2230_txvga_data[0]);
+ for (i=0; i<count; i++)
+ {
+ if (al2230_txvga_data[i][1] >= index)
+ break;
+ }
+ if (i == count)
+ i--;
+
+ PowerData = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( al2230_txvga_data[i][0], 20);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return i;
+}
+//--
+u8 RFSynthesizer_SetAiroha7230Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ u8 i,count;
+
+ //PowerData = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( airoha_power_data_24[index], 20);
+ count = sizeof(al7230_txvga_data) / sizeof(al7230_txvga_data[0]);
+ for (i=0; i<count; i++)
+ {
+ if (al7230_txvga_data[i][1] >= index)
+ break;
+ }
+ if (i == count)
+ i--;
+ PowerData = (1 << 31) | (0 << 30) | (24 << 24) | (al7230_txvga_data[i][0]&0xffffff);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return i;
+}
+
+u8 RFSynthesizer_SetWinbond242Power( phw_data_t pHwData, u8 index )
+{
+ u32 PowerData;
+ u8 i,count;
+
+ count = sizeof(w89rf242_txvga_data) / sizeof(w89rf242_txvga_data[0]);
+ for (i=0; i<count; i++)
+ {
+ if (w89rf242_txvga_data[i][1] >= index)
+ break;
+ }
+ if (i == count)
+ i--;
+
+ // Set TxVga into RF
+ PowerData = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( w89rf242_txvga_data[i][0], 24);
+ Wb35Reg_Write( pHwData, 0x0864, PowerData );
+
+ // Update BB48 BB4C BB58 for high precision txvga
+ Wb35Reg_Write( pHwData, 0x1048, w89rf242_txvga_data[i][2] );
+ Wb35Reg_Write( pHwData, 0x104c, w89rf242_txvga_data[i][3] );
+ Wb35Reg_Write( pHwData, 0x1058, w89rf242_txvga_data[i][4] );
+
+// Rf vga 0 ~ 3 for temperature compensate. It will affect the scan Bss.
+// The i value equals to 8 or 7 usually. So It's not necessary to setup this RF register.
+// if( i <= 3 )
+// PowerData = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( 0x000024, 24 );
+// else
+// PowerData = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( 0x001824, 24 );
+// Wb35Reg_Write( pHwData, 0x0864, PowerData );
+ return i;
+}
+
+//===========================================================================================================
+// Dxx_initial --
+// Mxx_initial --
+ //
+// Routine Description:
+// Initial the hardware setting and module variable
+ //
+//===========================================================================================================
+void Dxx_initial( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ // Old IC:Single mode only.
+ // New IC: operation decide by Software set bit[4]. 1:multiple 0: single
+ pWb35Reg->D00_DmaControl = 0xc0000004; //Txon, Rxon, multiple Rx for new 4k DMA
+ //Txon, Rxon, single Rx for old 8k ASIC
+ if( !HAL_USB_MODE_BURST( pHwData ) )
+ pWb35Reg->D00_DmaControl = 0xc0000000;//Txon, Rxon, single Rx for new 4k DMA
+
+ Wb35Reg_WriteSync( pHwData, 0x0400, pWb35Reg->D00_DmaControl );
+}
+
+void Mxx_initial( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 tmp;
+ u32 pltmp[11];
+ u16 i;
+
+
+ //======================================================
+ // Initial Mxx register
+ //======================================================
+
+ // M00 bit set
+#ifdef _IBSS_BEACON_SEQ_STICK_
+ pWb35Reg->M00_MacControl = 0; // Solve beacon sequence number stop by software
+#else
+ pWb35Reg->M00_MacControl = 0x80000000; // Solve beacon sequence number stop by hardware
+#endif
+
+ // M24 disable enter power save, BB RxOn and enable NAV attack
+ pWb35Reg->M24_MacControl = 0x08040042;
+ pltmp[0] = pWb35Reg->M24_MacControl;
+
+ pltmp[1] = 0; // Skip M28, because no initialize value is required.
+
+ // M2C CWmin and CWmax setting
+ pHwData->cwmin = DEFAULT_CWMIN;
+ pHwData->cwmax = DEFAULT_CWMAX;
+ pWb35Reg->M2C_MacControl = DEFAULT_CWMIN << 10;
+ pWb35Reg->M2C_MacControl |= DEFAULT_CWMAX;
+ pltmp[2] = pWb35Reg->M2C_MacControl;
+
+ // M30 BSSID
+ pltmp[3] = *(PULONG)pHwData->bssid;
+
+ // M34
+ pHwData->AID = DEFAULT_AID;
+ tmp = *(PUSHORT)(pHwData->bssid+4);
+ tmp |= DEFAULT_AID << 16;
+ pltmp[4] = tmp;
+
+ // M38
+ pWb35Reg->M38_MacControl = (DEFAULT_RATE_RETRY_LIMIT<<8) | (DEFAULT_LONG_RETRY_LIMIT << 4) | DEFAULT_SHORT_RETRY_LIMIT;
+ pltmp[5] = pWb35Reg->M38_MacControl;
+
+ // M3C
+ tmp = (DEFAULT_PIFST << 26) | (DEFAULT_EIFST << 16) | (DEFAULT_DIFST << 8) | (DEFAULT_SIFST << 4) | DEFAULT_OSIFST ;
+ pWb35Reg->M3C_MacControl = tmp;
+ pltmp[6] = tmp;
+
+ // M40
+ pHwData->slot_time_select = DEFAULT_SLOT_TIME;
+ tmp = (DEFAULT_ATIMWD << 16) | DEFAULT_SLOT_TIME;
+ pWb35Reg->M40_MacControl = tmp;
+ pltmp[7] = tmp;
+
+ // M44
+ tmp = DEFAULT_MAX_TX_MSDU_LIFE_TIME << 10; // *1024
+ pWb35Reg->M44_MacControl = tmp;
+ pltmp[8] = tmp;
+
+ // M48
+ pHwData->BeaconPeriod = DEFAULT_BEACON_INTERVAL;
+ pHwData->ProbeDelay = DEFAULT_PROBE_DELAY_TIME;
+ tmp = (DEFAULT_BEACON_INTERVAL << 16) | DEFAULT_PROBE_DELAY_TIME;
+ pWb35Reg->M48_MacControl = tmp;
+ pltmp[9] = tmp;
+
+ //M4C
+ pWb35Reg->M4C_MacStatus = (DEFAULT_PROTOCOL_VERSION << 30) | (DEFAULT_MAC_POWER_STATE << 28) | (DEFAULT_DTIM_ALERT_TIME << 24);
+ pltmp[10] = pWb35Reg->M4C_MacStatus;
+
+ // Burst write
+ //Wb35Reg_BurstWrite( pHwData, 0x0824, pltmp, 11, AUTO_INCREMENT );
+ for( i=0; i<11; i++ )
+ Wb35Reg_WriteSync( pHwData, 0x0824 + i*4, pltmp[i] );
+
+ // M60
+ Wb35Reg_WriteSync( pHwData, 0x0860, 0x12481248 );
+ pWb35Reg->M60_MacControl = 0x12481248;
+
+ // M68
+ Wb35Reg_WriteSync( pHwData, 0x0868, 0x00050900 ); // 20051018 0x000F0F00 ); // 940930 0x00131300
+ pWb35Reg->M68_MacControl = 0x00050900;
+
+ // M98
+ Wb35Reg_WriteSync( pHwData, 0x0898, 0xffff8888 );
+ pWb35Reg->M98_MacControl = 0xffff8888;
+}
+
+
+void Uxx_power_off_procedure( phw_data_t pHwData )
+{
+ // SW, PMU reset and turn off clock
+ Wb35Reg_WriteSync( pHwData, 0x03b0, 3 );
+ Wb35Reg_WriteSync( pHwData, 0x03f0, 0xf9 );
+}
+
+//Decide the TxVga of every channel
+void GetTxVgaFromEEPROM( phw_data_t pHwData )
+{
+ u32 i, j, ltmp;
+ u16 Value[MAX_TXVGA_EEPROM];
+ PUCHAR pctmp;
+ u8 ctmp=0;
+
+ // Get the entire TxVga setting in EEPROM
+ for( i=0; i<MAX_TXVGA_EEPROM; i++ )
+ {
+ Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08100000 + 0x00010000*i );
+ Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+ Value[i] = (u16)( ltmp & 0xffff ); // Get 16 bit available
+ Value[i] = cpu_to_le16( Value[i] ); // [7:0]2412 [7:0]2417 ....
+ }
+
+ // Adjust the filed which fills with reserved value.
+ pctmp = (PUCHAR)Value;
+ for( i=0; i<(MAX_TXVGA_EEPROM*2); i++ )
+ {
+ if( pctmp[i] != 0xff )
+ ctmp = pctmp[i];
+ else
+ pctmp[i] = ctmp;
+ }
+
+ // Adjust WB_242 to WB_242_1 TxVga scale
+ if( pHwData->phy_type == RF_WB_242 )
+ {
+ for( i=0; i<4; i++ ) // Only 2412 2437 2462 2484 case must be modified
+ {
+ for( j=0; j<(sizeof(w89rf242_txvga_old_mapping)/sizeof(w89rf242_txvga_old_mapping[0])); j++ )
+ {
+ if( pctmp[i] < (u8)w89rf242_txvga_old_mapping[j][1] )
+ {
+ pctmp[i] = (u8)w89rf242_txvga_old_mapping[j][0];
+ break;
+ }
+ }
+
+ if( j == (sizeof(w89rf242_txvga_old_mapping)/sizeof(w89rf242_txvga_old_mapping[0])) )
+ pctmp[i] = (u8)w89rf242_txvga_old_mapping[j-1][0];
+ }
+ }
+
+ // 20060621 Add
+ memcpy( pHwData->TxVgaSettingInEEPROM, pctmp, MAX_TXVGA_EEPROM*2 ); //MAX_TXVGA_EEPROM is u16 count
+ EEPROMTxVgaAdjust( pHwData );
+}
+
+// This function will affect the TxVga parameter in HAL. If hal_set_current_channel
+// or RFSynthesizer_SetPowerIndex be called, new TxVga will take effect.
+// TxVgaSettingInEEPROM of sHwData is an u8 array point to EEPROM contain for IS89C35
+// This function will use default TxVgaSettingInEEPROM data to calculate new TxVga.
+void EEPROMTxVgaAdjust( phw_data_t pHwData ) // 20060619.5 Add
+{
+ PUCHAR pTxVga = pHwData->TxVgaSettingInEEPROM;
+ s16 i, stmp;
+
+ //-- 2.4G -- 20060704.2 Request from Tiger
+ //channel 1 ~ 5
+ stmp = pTxVga[1] - pTxVga[0];
+ for( i=0; i<5; i++ )
+ pHwData->TxVgaFor24[i] = pTxVga[0] + stmp*i/4;
+ //channel 6 ~ 10
+ stmp = pTxVga[2] - pTxVga[1];
+ for( i=5; i<10; i++ )
+ pHwData->TxVgaFor24[i] = pTxVga[1] + stmp*(i-5)/4;
+ //channel 11 ~ 13
+ stmp = pTxVga[3] - pTxVga[2];
+ for( i=10; i<13; i++ )
+ pHwData->TxVgaFor24[i] = pTxVga[2] + stmp*(i-10)/2;
+ //channel 14
+ pHwData->TxVgaFor24[13] = pTxVga[3];
+
+ //-- 5G --
+ if( pHwData->phy_type == RF_AIROHA_7230 )
+ {
+ //channel 184
+ pHwData->TxVgaFor50[0].ChanNo = 184;
+ pHwData->TxVgaFor50[0].TxVgaValue = pTxVga[4];
+ //channel 196
+ pHwData->TxVgaFor50[3].ChanNo = 196;
+ pHwData->TxVgaFor50[3].TxVgaValue = pTxVga[5];
+ //interpolate
+ pHwData->TxVgaFor50[1].ChanNo = 188;
+ pHwData->TxVgaFor50[2].ChanNo = 192;
+ stmp = pTxVga[5] - pTxVga[4];
+ pHwData->TxVgaFor50[2].TxVgaValue = pTxVga[5] - stmp/3;
+ pHwData->TxVgaFor50[1].TxVgaValue = pTxVga[5] - stmp*2/3;
+
+ //channel 16
+ pHwData->TxVgaFor50[6].ChanNo = 16;
+ pHwData->TxVgaFor50[6].TxVgaValue = pTxVga[6];
+ pHwData->TxVgaFor50[4].ChanNo = 8;
+ pHwData->TxVgaFor50[4].TxVgaValue = pTxVga[6];
+ pHwData->TxVgaFor50[5].ChanNo = 12;
+ pHwData->TxVgaFor50[5].TxVgaValue = pTxVga[6];
+
+ //channel 36
+ pHwData->TxVgaFor50[8].ChanNo = 36;
+ pHwData->TxVgaFor50[8].TxVgaValue = pTxVga[7];
+ pHwData->TxVgaFor50[7].ChanNo = 34;
+ pHwData->TxVgaFor50[7].TxVgaValue = pTxVga[7];
+ pHwData->TxVgaFor50[9].ChanNo = 38;
+ pHwData->TxVgaFor50[9].TxVgaValue = pTxVga[7];
+
+ //channel 40
+ pHwData->TxVgaFor50[10].ChanNo = 40;
+ pHwData->TxVgaFor50[10].TxVgaValue = pTxVga[8];
+ //channel 48
+ pHwData->TxVgaFor50[14].ChanNo = 48;
+ pHwData->TxVgaFor50[14].TxVgaValue = pTxVga[9];
+ //interpolate
+ pHwData->TxVgaFor50[11].ChanNo = 42;
+ pHwData->TxVgaFor50[12].ChanNo = 44;
+ pHwData->TxVgaFor50[13].ChanNo = 46;
+ stmp = pTxVga[9] - pTxVga[8];
+ pHwData->TxVgaFor50[13].TxVgaValue = pTxVga[9] - stmp/4;
+ pHwData->TxVgaFor50[12].TxVgaValue = pTxVga[9] - stmp*2/4;
+ pHwData->TxVgaFor50[11].TxVgaValue = pTxVga[9] - stmp*3/4;
+
+ //channel 52
+ pHwData->TxVgaFor50[15].ChanNo = 52;
+ pHwData->TxVgaFor50[15].TxVgaValue = pTxVga[10];
+ //channel 64
+ pHwData->TxVgaFor50[18].ChanNo = 64;
+ pHwData->TxVgaFor50[18].TxVgaValue = pTxVga[11];
+ //interpolate
+ pHwData->TxVgaFor50[16].ChanNo = 56;
+ pHwData->TxVgaFor50[17].ChanNo = 60;
+ stmp = pTxVga[11] - pTxVga[10];
+ pHwData->TxVgaFor50[17].TxVgaValue = pTxVga[11] - stmp/3;
+ pHwData->TxVgaFor50[16].TxVgaValue = pTxVga[11] - stmp*2/3;
+
+ //channel 100
+ pHwData->TxVgaFor50[19].ChanNo = 100;
+ pHwData->TxVgaFor50[19].TxVgaValue = pTxVga[12];
+ //channel 112
+ pHwData->TxVgaFor50[22].ChanNo = 112;
+ pHwData->TxVgaFor50[22].TxVgaValue = pTxVga[13];
+ //interpolate
+ pHwData->TxVgaFor50[20].ChanNo = 104;
+ pHwData->TxVgaFor50[21].ChanNo = 108;
+ stmp = pTxVga[13] - pTxVga[12];
+ pHwData->TxVgaFor50[21].TxVgaValue = pTxVga[13] - stmp/3;
+ pHwData->TxVgaFor50[20].TxVgaValue = pTxVga[13] - stmp*2/3;
+
+ //channel 128
+ pHwData->TxVgaFor50[26].ChanNo = 128;
+ pHwData->TxVgaFor50[26].TxVgaValue = pTxVga[14];
+ //interpolate
+ pHwData->TxVgaFor50[23].ChanNo = 116;
+ pHwData->TxVgaFor50[24].ChanNo = 120;
+ pHwData->TxVgaFor50[25].ChanNo = 124;
+ stmp = pTxVga[14] - pTxVga[13];
+ pHwData->TxVgaFor50[25].TxVgaValue = pTxVga[14] - stmp/4;
+ pHwData->TxVgaFor50[24].TxVgaValue = pTxVga[14] - stmp*2/4;
+ pHwData->TxVgaFor50[23].TxVgaValue = pTxVga[14] - stmp*3/4;
+
+ //channel 140
+ pHwData->TxVgaFor50[29].ChanNo = 140;
+ pHwData->TxVgaFor50[29].TxVgaValue = pTxVga[15];
+ //interpolate
+ pHwData->TxVgaFor50[27].ChanNo = 132;
+ pHwData->TxVgaFor50[28].ChanNo = 136;
+ stmp = pTxVga[15] - pTxVga[14];
+ pHwData->TxVgaFor50[28].TxVgaValue = pTxVga[15] - stmp/3;
+ pHwData->TxVgaFor50[27].TxVgaValue = pTxVga[15] - stmp*2/3;
+
+ //channel 149
+ pHwData->TxVgaFor50[30].ChanNo = 149;
+ pHwData->TxVgaFor50[30].TxVgaValue = pTxVga[16];
+ //channel 165
+ pHwData->TxVgaFor50[34].ChanNo = 165;
+ pHwData->TxVgaFor50[34].TxVgaValue = pTxVga[17];
+ //interpolate
+ pHwData->TxVgaFor50[31].ChanNo = 153;
+ pHwData->TxVgaFor50[32].ChanNo = 157;
+ pHwData->TxVgaFor50[33].ChanNo = 161;
+ stmp = pTxVga[17] - pTxVga[16];
+ pHwData->TxVgaFor50[33].TxVgaValue = pTxVga[17] - stmp/4;
+ pHwData->TxVgaFor50[32].TxVgaValue = pTxVga[17] - stmp*2/4;
+ pHwData->TxVgaFor50[31].TxVgaValue = pTxVga[17] - stmp*3/4;
+ }
+
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG((" TxVgaFor24 : \n"));
+ DataDmp((u8 *)pHwData->TxVgaFor24, 14 ,0);
+ WBDEBUG((" TxVgaFor50 : \n"));
+ DataDmp((u8 *)pHwData->TxVgaFor50, 70 ,0);
+ #endif
+}
+
+void BBProcessor_RateChanging( phw_data_t pHwData, u8 rate ) // 20060613.1
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ unsigned char Is11bRate;
+
+ Is11bRate = (rate % 6) ? 1 : 0;
+ switch( pHwData->phy_type )
+ {
+ case RF_AIROHA_2230:
+ case RF_AIROHA_2230S: // 20060420 Add this
+ if( Is11bRate )
+ {
+ if( (pWb35Reg->BB48 != BB48_DEFAULT_AL2230_11B) &&
+ (pWb35Reg->BB4C != BB4C_DEFAULT_AL2230_11B) )
+ {
+ Wb35Reg_Write( pHwData, 0x1048, BB48_DEFAULT_AL2230_11B );
+ Wb35Reg_Write( pHwData, 0x104c, BB4C_DEFAULT_AL2230_11B );
+ }
+ }
+ else
+ {
+ if( (pWb35Reg->BB48 != BB48_DEFAULT_AL2230_11G) &&
+ (pWb35Reg->BB4C != BB4C_DEFAULT_AL2230_11G) )
+ {
+ Wb35Reg_Write( pHwData, 0x1048, BB48_DEFAULT_AL2230_11G );
+ Wb35Reg_Write( pHwData, 0x104c, BB4C_DEFAULT_AL2230_11G );
+ }
+ }
+ break;
+
+ case RF_WB_242: // 20060623 The fix only for old TxVGA setting
+ if( Is11bRate )
+ {
+ if( (pWb35Reg->BB48 != BB48_DEFAULT_WB242_11B) &&
+ (pWb35Reg->BB4C != BB4C_DEFAULT_WB242_11B) )
+ {
+ pWb35Reg->BB48 = BB48_DEFAULT_WB242_11B;
+ pWb35Reg->BB4C = BB4C_DEFAULT_WB242_11B;
+ Wb35Reg_Write( pHwData, 0x1048, BB48_DEFAULT_WB242_11B );
+ Wb35Reg_Write( pHwData, 0x104c, BB4C_DEFAULT_WB242_11B );
+ }
+ }
+ else
+ {
+ if( (pWb35Reg->BB48 != BB48_DEFAULT_WB242_11G) &&
+ (pWb35Reg->BB4C != BB4C_DEFAULT_WB242_11G) )
+ {
+ pWb35Reg->BB48 = BB48_DEFAULT_WB242_11G;
+ pWb35Reg->BB4C = BB4C_DEFAULT_WB242_11G;
+ Wb35Reg_Write( pHwData, 0x1048, BB48_DEFAULT_WB242_11G );
+ Wb35Reg_Write( pHwData, 0x104c, BB4C_DEFAULT_WB242_11G );
+ }
+ }
+ break;
+ }
+}
+
+
+
+
+
+
+
diff --git a/drivers/staging/winbond/rxisr.c b/drivers/staging/winbond/rxisr.c
new file mode 100644
index 00000000000..18e942c9b82
--- /dev/null
+++ b/drivers/staging/winbond/rxisr.c
@@ -0,0 +1,30 @@
+#include "os_common.h"
+
+void vRxTimerInit(PWB32_ADAPTER Adapter)
+{
+ OS_TIMER_INITIAL(&(Adapter->Mds.nTimer), (void*) RxTimerHandler, (void*) Adapter);
+}
+
+void vRxTimerStart(PWB32_ADAPTER Adapter, int timeout_value)
+{
+ if (timeout_value<MIN_TIMEOUT_VAL)
+ timeout_value=MIN_TIMEOUT_VAL;
+
+ OS_TIMER_SET( &(Adapter->Mds.nTimer), timeout_value );
+}
+
+void vRxTimerStop(PWB32_ADAPTER Adapter)
+{
+ OS_TIMER_CANCEL( &(Adapter->Mds.nTimer), 0 );
+}
+
+void RxTimerHandler_1a( PADAPTER Adapter)
+{
+ RxTimerHandler(NULL, Adapter, NULL, NULL);
+}
+
+void RxTimerHandler(void* SystemSpecific1, PWB32_ADAPTER Adapter,
+ void* SystemSpecific2, void* SystemSpecific3)
+{
+ WARN_ON(1);
+}
diff --git a/drivers/staging/winbond/scan_s.h b/drivers/staging/winbond/scan_s.h
new file mode 100644
index 00000000000..1d1b0c4fec1
--- /dev/null
+++ b/drivers/staging/winbond/scan_s.h
@@ -0,0 +1,115 @@
+//
+// SCAN task global CONSTANTS, STRUCTURES, variables
+//
+
+//////////////////////////////////////////////////////////////////////////
+//define the msg type of SCAN module
+#define SCANMSG_SCAN_REQ 0x01
+#define SCANMSG_BEACON 0x02
+#define SCANMSG_PROBE_RESPONSE 0x03
+#define SCANMSG_TIMEOUT 0x04
+#define SCANMSG_TXPROBE_FAIL 0x05
+#define SCANMSG_ENABLE_BGSCAN 0x06
+#define SCANMSG_STOP_SCAN 0x07
+
+// BSS Type =>conform to
+// IBSS : ToDS/FromDS = 00
+// Infrastructure : ToDS/FromDS = 01
+#define IBSS_NET 0
+#define ESS_NET 1
+#define ANYBSS_NET 2
+
+// Scan Type
+#define ACTIVE_SCAN 0
+#define PASSIVE_SCAN 1
+
+///////////////////////////////////////////////////////////////////////////
+//Global data structures, Initial Scan & Background Scan
+typedef struct _SCAN_REQ_PARA //mandatory parameters for SCAN request
+{
+ u32 ScanType; //passive/active scan
+
+ CHAN_LIST sChannelList; // 86B
+ u8 reserved_1[2];
+
+ struct SSID_Element sSSID; // 34B. scan only for this SSID
+ u8 reserved_2[2];
+
+} SCAN_REQ_PARA, *psSCAN_REQ_PARA;
+
+typedef struct _SCAN_PARAMETERS
+{
+ u16 wState;
+ u16 iCurrentChannelIndex;
+
+ SCAN_REQ_PARA sScanReq;
+
+ u8 BSSID[MAC_ADDR_LENGTH + 2]; //scan only for this BSSID
+
+ u32 BssType; //scan only for this BSS type
+
+ //struct SSID_Element sSSID; //scan only for this SSID
+ u16 ProbeDelay;
+ u16 MinChannelTime;
+
+ u16 MaxChannelTime;
+ u16 reserved_1;
+
+ s32 iBgScanPeriod; // XP: 5 sec
+
+ u8 boBgScan; // Wb: enable BG scan, For XP, this value must be FALSE
+ u8 boFastScan; // Wb: reserved
+ u8 boCCAbusy; // Wb: HWMAC CCA busy status
+ u8 reserved_2;
+
+ //NDIS_MINIPORT_TIMER nTimer;
+ OS_TIMER nTimer;
+
+ u32 ScanTimeStamp; //Increase 1 per background scan(1 minute)
+ u32 BssTimeStamp; //Increase 1 per connect status check
+ u32 RxNumPerAntenna[2]; //
+
+ u8 AntennaToggle; //
+ u8 boInTimerHandler;
+ u8 boTimerActive; // Wb: reserved
+ u8 boSave;
+
+ u32 BScanEnable; // Background scan enable. Default is On
+
+} SCAN_PARAMETERS, *psSCAN_PARAMETERS;
+
+// Encapsulate 'Adapter' data structure
+#define psSCAN (&(Adapter->sScanPara))
+#define psSCANREQ (&(Adapter->sScanPara.sScanReq))
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// scan.h
+// Define the related definitions of scan module
+// history -- 01/14/03' created
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//Define the state of scan module
+#define SCAN_INACTIVE 0
+#define WAIT_PROBE_DELAY 1
+#define WAIT_RESPONSE_MIN 2
+#define WAIT_RESPONSE_MAX_ACTIVE 3
+#define WAIT_BEACON_MAX_PASSIVE 4
+#define SCAN_COMPLETE 5
+#define BG_SCAN 6
+#define BG_SCANNING 7
+
+
+// The value will load from EEPROM
+// If 0xff is set in EEPOM, the driver will use SCAN_MAX_CHNL_TIME instead.
+// The definition is in WbHal.h
+// #define SCAN_MAX_CHNL_TIME (50)
+
+
+
+// static functions
+
+//static void ScanTimerHandler(PWB32_ADAPTER Adapter);
+//static void vScanTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
+//static void vScanTimerStop(PWB32_ADAPTER Adapter);
+
diff --git a/drivers/staging/winbond/sme_api.c b/drivers/staging/winbond/sme_api.c
new file mode 100644
index 00000000000..40e93b7600e
--- /dev/null
+++ b/drivers/staging/winbond/sme_api.c
@@ -0,0 +1,13 @@
+//------------------------------------------------------------------------------------
+// sme_api.c
+//
+// Copyright(C) 2002 Winbond Electronics Corp.
+//
+//
+//------------------------------------------------------------------------------------
+#include "os_common.h"
+
+s8 sme_get_rssi(void *pcore_data, s32 *prssi)
+{
+ BUG();
+}
diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h
new file mode 100644
index 00000000000..016b225ca4a
--- /dev/null
+++ b/drivers/staging/winbond/sme_api.h
@@ -0,0 +1,265 @@
+/*
+ * sme_api.h
+ *
+ * Copyright(C) 2002 Winbond Electronics Corp.
+ *
+ * modification history
+ * ---------------------------------------------------------------------------
+ * 1.00.001, 2003-04-21, Kevin created
+ * 1.00.002, 2003-05-14, PD43 & PE20 modified
+ *
+ */
+
+#ifndef __SME_API_H__
+#define __SME_API_H__
+
+/****************** INCLUDE FILES SECTION ***********************************/
+//#include "GL\gl_core.h"
+
+/****************** CONSTANT AND MACRO SECTION ******************************/
+#define _INLINE __inline
+
+#define MEDIA_STATE_DISCONNECTED 0
+#define MEDIA_STATE_CONNECTED 1
+
+//ARRAY CHECK
+#define MAX_POWER_TO_DB 32
+
+/****************** TYPE DEFINITION SECTION *********************************/
+
+/****************** EXPORTED FUNCTION DECLARATION SECTION *******************/
+
+// OID_802_11_BSSID
+s8 sme_get_bssid(void *pcore_data, u8 *pbssid);
+s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid);//Not use
+s8 sme_set_desired_bssid(void *pcore_data, u8 *pbssid);
+
+// OID_802_11_SSID
+s8 sme_get_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);
+s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);// Not use
+s8 sme_set_desired_ssid(void *pcore_data, u8 *pssid, u8 ssid_len);
+
+// OID_802_11_INFRASTRUCTURE_MODE
+s8 sme_get_bss_type(void *pcore_data, u8 *pbss_type);
+s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type);//Not use
+s8 sme_set_desired_bss_type(void *pcore_data, u8 bss_type);
+
+// OID_802_11_FRAGMENTATION_THRESHOLD
+s8 sme_get_fragment_threshold(void *pcore_data, u32 *pthreshold);
+s8 sme_set_fragment_threshold(void *pcore_data, u32 threshold);
+
+// OID_802_11_RTS_THRESHOLD
+s8 sme_get_rts_threshold(void *pcore_data, u32 *pthreshold);
+s8 sme_set_rts_threshold(void *pcore_data, u32 threshold);
+
+// OID_802_11_RSSI
+s8 sme_get_rssi(void *pcore_data, s32 *prssi);
+
+// OID_802_11_CONFIGURATION
+s8 sme_get_beacon_period(void *pcore_data, u16 *pbeacon_period);
+s8 sme_set_beacon_period(void *pcore_data, u16 beacon_period);
+
+s8 sme_get_atim_window(void *pcore_data, u16 *patim_window);
+s8 sme_set_atim_window(void *pcore_data, u16 atim_window);
+
+s8 sme_get_current_channel(void *pcore_data, u8 *pcurrent_channel);
+s8 sme_get_current_band(void *pcore_data, u8 *pcurrent_band);
+s8 sme_set_current_channel(void *pcore_data, u8 current_channel);
+
+// OID_802_11_BSSID_LIST
+s8 sme_get_scan_bss_count(void *pcore_data, u8 *pcount);
+s8 sme_get_scan_bss(void *pcore_data, u8 index, void **ppbss);
+
+s8 sme_get_connected_bss(void *pcore_data, void **ppbss_now);
+
+// OID_802_11_AUTHENTICATION_MODE
+s8 sme_get_auth_mode(void *pcore_data, u8 *pauth_mode);
+s8 sme_set_auth_mode(void *pcore_data, u8 auth_mode);
+
+// OID_802_11_WEP_STATUS / OID_802_11_ENCRYPTION_STATUS
+s8 sme_get_wep_mode(void *pcore_data, u8 *pwep_mode);
+s8 sme_set_wep_mode(void *pcore_data, u8 wep_mode);
+//s8 sme_get_encryption_status(void *pcore_data, u8 *pstatus);
+//s8 sme_set_encryption_status(void *pcore_data, u8 status);
+
+// ???????????????????????????????????????
+
+// OID_GEN_VENDOR_ID
+// OID_802_3_PERMANENT_ADDRESS
+s8 sme_get_permanent_mac_addr(void *pcore_data, u8 *pmac_addr);
+
+// OID_802_3_CURRENT_ADDRESS
+s8 sme_get_current_mac_addr(void *pcore_data, u8 *pmac_addr);
+
+// OID_802_11_NETWORK_TYPE_IN_USE
+s8 sme_get_network_type_in_use(void *pcore_data, u8 *ptype);
+s8 sme_set_network_type_in_use(void *pcore_data, u8 type);
+
+// OID_802_11_SUPPORTED_RATES
+s8 sme_get_supported_rate(void *pcore_data, u8 *prates);
+
+// OID_802_11_ADD_WEP
+//12/29/03' wkchen
+s8 sme_set_add_wep(void *pcore_data, u32 key_index, u32 key_len,
+ u8 *Address, u8 *key);
+
+// OID_802_11_REMOVE_WEP
+s8 sme_set_remove_wep(void *pcre_data, u32 key_index);
+
+// OID_802_11_DISASSOCIATE
+s8 sme_set_disassociate(void *pcore_data);
+
+// OID_802_11_POWER_MODE
+s8 sme_get_power_mode(void *pcore_data, u8 *pmode);
+s8 sme_set_power_mode(void *pcore_data, u8 mode);
+
+// OID_802_11_BSSID_LIST_SCAN
+s8 sme_set_bssid_list_scan(void *pcore_data, void *pscan_para);
+
+// OID_802_11_RELOAD_DEFAULTS
+s8 sme_set_reload_defaults(void *pcore_data, u8 reload_type);
+
+
+// The following SME API functions are used for WPA
+//
+// Mandatory OIDs for WPA
+//
+
+// OID_802_11_ADD_KEY
+//s8 sme_set_add_key(void *pcore_data, NDIS_802_11_KEY *pkey);
+
+// OID_802_11_REMOVE_KEY
+//s8 sme_set_remove_key(void *pcore_data, NDIS_802_11_REMOVE_KEY *pkey);
+
+// OID_802_11_ASSOCIATION_INFORMATION
+//s8 sme_set_association_information(void *pcore_data,
+// NDIS_802_11_ASSOCIATION_INFORMATION *pinfo);
+
+// OID_802_11_TEST
+//s8 sme_set_test(void *pcore_data, NDIS_802_11_TEST *ptest_data);
+
+//--------------------------------------------------------------------------//
+/*
+// The left OIDs
+
+// OID_802_11_NETWORK_TYPES_SUPPORTED
+// OID_802_11_TX_POWER_LEVEL
+// OID_802_11_RSSI_TRIGGER
+// OID_802_11_NUMBER_OF_ANTENNAS
+// OID_802_11_RX_ANTENNA_SELECTED
+// OID_802_11_TX_ANTENNA_SELECTED
+// OID_802_11_STATISTICS
+// OID_802_11_DESIRED_RATES
+// OID_802_11_PRIVACY_FILTER
+
+*/
+
+/*------------------------- none-standard ----------------------------------*/
+s8 sme_get_connect_status(void *pcore_data, u8 *pstatus);
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+//s8 sme_get_scan_type(void *pcore_data, u8 *pscan_type);
+//s8 sme_set_scan_type(void *pcore_data, u8 scan_type);
+
+//s8 sme_get_scan_channel_list(void *pcore_data, u8 *pscan_type);
+//s8 sme_set_scan_channel_list(void *pcore_data, u8 scan_type);
+
+
+void sme_get_encryption_status(void *pcore_data, u8 *EncryptStatus);
+void sme_set_encryption_status(void *pcore_data, u8 EncryptStatus);
+s8 sme_add_key(void *pcore_data,
+ u32 key_index,
+ u8 key_len,
+ u8 key_type,
+ u8 *key_bssid,
+ //u8 *key_rsc,
+ u8 *ptx_tsc,
+ u8 *prx_tsc,
+ u8 *key_material);
+void sme_remove_default_key(void *pcore_data, int index);
+void sme_remove_mapping_key(void *pcore_data, u8 *pmac_addr);
+void sme_clear_all_mapping_key(void *pcore_data);
+void sme_clear_all_default_key(void *pcore_data);
+
+
+
+s8 sme_set_preamble_mode(void *pcore_data, u8 mode);
+s8 sme_get_preamble_mode(void *pcore_data, u8 *mode);
+s8 sme_get_preamble_type(void *pcore_data, u8 *type);
+s8 sme_set_slottime_mode(void *pcore_data, u8 mode);
+s8 sme_get_slottime_mode(void *pcore_data, u8 *mode);
+s8 sme_get_slottime_type(void *pcore_data, u8 *type);
+s8 sme_set_txrate_policy(void *pcore_data, u8 policy);
+s8 sme_get_txrate_policy(void *pcore_data, u8 *policy);
+s8 sme_get_cwmin_value(void *pcore_data, u8 *cwmin);
+s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax);
+s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff);
+s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff);
+s8 sme_get_radio_mode(void *pcore_data, psRadioOff pRadioOffData);
+s8 sme_set_radio_mode(void *pcore_data, RadioOff RadioOffData);
+
+void sme_get_tx_power_level(void *pcore_data, u32 *TxPower);
+u8 sme_set_tx_power_level(void *pcore_data, u32 TxPower);
+void sme_get_antenna_count(void *pcore_data, u32 *AntennaCount);
+void sme_get_rx_antenna(void *pcore_data, u32 *RxAntenna);
+u8 sme_set_rx_antenna(void *pcore_data, u32 RxAntenna);
+void sme_get_tx_antenna(void *pcore_data, u32 *TxAntenna);
+s8 sme_set_tx_antenna(void *pcore_data, u32 TxAntenna);
+s8 sme_set_IBSS_chan(void *pcore_data, ChanInfo chan);
+
+//20061108 WPS
+s8 sme_set_IE_append(void *pcore_data, PUCHAR buffer, u16 buf_len);
+
+
+
+
+//================== Local functions ======================
+//#ifdef _HSINCHU
+//void drv_translate_rssi(); // HW RSSI bit -> NDIS RSSI representation
+//void drv_translate_bss_description(); // Local bss desc -> NDIS bss desc
+//void drv_translate_channel(u8 NetworkType, u8 ChannelNumber, u32 *freq); // channel number -> channel /freq.
+//#endif _HSINCHU
+//
+static const u32 PowerDbToMw[] =
+{
+ 56, //mW, MAX - 0, 17.5 dbm
+ 40, //mW, MAX - 1, 16.0 dbm
+ 30, //mW, MAX - 2, 14.8 dbm
+ 20, //mW, MAX - 3, 13.0 dbm
+ 15, //mW, MAX - 4, 11.8 dbm
+ 12, //mW, MAX - 5, 10.6 dbm
+ 9, //mW, MAX - 6, 9.4 dbm
+ 7, //mW, MAX - 7, 8.3 dbm
+ 5, //mW, MAX - 8, 6.4 dbm
+ 4, //mW, MAX - 9, 5.3 dbm
+ 3, //mW, MAX - 10, 4.0 dbm
+ 2, //mW, MAX - 11, ? dbm
+ 2, //mW, MAX - 12, ? dbm
+ 2, //mW, MAX - 13, ? dbm
+ 2, //mW, MAX - 14, ? dbm
+ 2, //mW, MAX - 15, ? dbm
+ 2, //mW, MAX - 16, ? dbm
+ 2, //mW, MAX - 17, ? dbm
+ 2, //mW, MAX - 18, ? dbm
+ 1, //mW, MAX - 19, ? dbm
+ 1, //mW, MAX - 20, ? dbm
+ 1, //mW, MAX - 21, ? dbm
+ 1, //mW, MAX - 22, ? dbm
+ 1, //mW, MAX - 23, ? dbm
+ 1, //mW, MAX - 24, ? dbm
+ 1, //mW, MAX - 25, ? dbm
+ 1, //mW, MAX - 26, ? dbm
+ 1, //mW, MAX - 27, ? dbm
+ 1, //mW, MAX - 28, ? dbm
+ 1, //mW, MAX - 29, ? dbm
+ 1, //mW, MAX - 30, ? dbm
+ 1 //mW, MAX - 31, ? dbm
+};
+
+
+
+
+
+#endif /* __SME_API_H__ */
+
+
diff --git a/drivers/staging/winbond/sme_s.h b/drivers/staging/winbond/sme_s.h
new file mode 100644
index 00000000000..dfd2fbc4ede
--- /dev/null
+++ b/drivers/staging/winbond/sme_s.h
@@ -0,0 +1,228 @@
+//
+// SME_S.H -
+// SME task global CONSTANTS, STRUCTURES, variables
+//
+
+//////////////////////////////////////////////////////////////////////////
+//define the msg type of SME module
+// 0x00~0x1F : MSG from GUI dispatch
+// 0x20~0x3F : MSG from MLME
+// 0x40~0x5F : MSG from SCAN
+// 0x60~0x6F : MSG from TX/RX
+// 0x70~0x7F : MSG from ROAMING
+// 0x80~0x8F : MSG from ISR
+// 0x90 : MSG TimeOut
+
+// from GUI
+#define SMEMSG_SCAN_REQ 0x01
+//#define SMEMSG_PASSIVE_SCAN_REQ 0x02
+#define SMEMSG_JOIN_REQ 0x03
+#define SMEMSG_START_IBSS 0x04
+#define SMEMSG_DISCONNECT_REQ 0x05
+#define SMEMSG_AUTHEN_REQ 0x06
+#define SMEMSG_DEAUTHEN_REQ 0x07
+#define SMEMSG_ASSOC_REQ 0x08
+#define SMEMSG_REASSOC_REQ 0x09
+#define SMEMSG_DISASSOC_REQ 0x0a
+#define SMEMSG_POWERSAVE_REQ 0x0b
+
+
+// from MLME
+#define SMEMSG_AUTHEN_CFM 0x21
+#define SMEMSG_AUTHEN_IND 0x22
+#define SMEMSG_ASSOC_CFM 0x23
+#define SMEMSG_DEAUTHEN_IND 0x24
+#define SMEMSG_DISASSOC_IND 0x25
+// from SCAN
+#define SMEMSG_SCAN_CFM 0x41
+#define SMEMSG_START_IBSS_CFM 0x42
+// from MTO, function call to set SME parameters
+
+// 0x60~0x6F : MSG from TX/RX
+//#define SMEMSG_IBSS_JOIN_UPDATE_BSSID 0x61
+#define SMEMSG_COUNTERMEASURE_MICFAIL_TIMEOUT 0x62
+#define SMEMSG_COUNTERMEASURE_BLOCK_TIMEOUT 0x63
+// from ROAMING
+#define SMEMSG_HANDOVER_JOIN_REQ 0x71
+#define SMEMSG_END_ROAMING 0x72
+#define SMEMSG_SCAN_JOIN_REQ 0x73
+// from ISR
+#define SMEMSG_TSF_SYNC_IND 0x81
+// from TimeOut
+#define SMEMSG_TIMEOUT 0x91
+
+
+
+#define MAX_PMKID_Accunt 16
+//@added by ws 04/22/05
+#define Cipher_Disabled 0
+#define Cipher_Wep 1
+#define Cipher_Tkip 2
+#define Cipher_Ccmp 4
+
+
+///////////////////////////////////////////////////////////////////////////
+//Constants
+
+///////////////////////////////////////////////////////////////////////////
+//Global data structures
+
+#define NUMOFWEPENTRIES 64
+
+typedef enum _WEPKeyMode
+{
+ WEPKEY_DISABLED = 0,
+ WEPKEY_64 = 1,
+ WEPKEY_128 = 2
+
+} WEPKEYMODE, *pWEPKEYMODE;
+
+#ifdef _WPA2_
+
+typedef struct _BSSInfo
+{
+ u8 PreAuthBssID[6];
+ PMKID pmkid_value;
+}BSSID_Info;
+
+typedef struct _PMKID_Table //added by ws 05/05/04
+{
+ u32 Length;
+ u32 BSSIDInfoCount;
+ BSSID_Info BSSIDInfo[16];
+
+} PMKID_Table;
+
+#endif //end def _WPA2_
+
+#define MAX_BASIC_RATE_SET 15
+#define MAX_OPT_RATE_SET MAX_BASIC_RATE_SET
+
+
+typedef struct _SME_PARAMETERS
+{
+ u16 wState;
+ u8 boDUTmode;
+ u8 bDesiredPowerSave;
+
+ // SME timer and timeout value
+ //NDIS_MINIPORT_TIMER nTimer;
+ OS_TIMER nTimer;
+
+ u8 boInTimerHandler;
+ u8 boAuthRetryActive;
+ u8 reserved_0[2];
+
+ u32 AuthenRetryTimerVal; // NOTE: Assoc don't fail timeout
+ u32 JoinFailTimerVal; // 10*Beacon-Interval
+
+ //Rates
+ u8 BSSBasicRateSet[(MAX_BASIC_RATE_SET + 3) & ~0x03 ]; // BSS basic rate set
+ u8 OperationalRateSet[(MAX_OPT_RATE_SET + 3) & ~0x03 ]; // Operational rate set
+
+ u8 NumOfBSSBasicRate;
+ u8 NumOfOperationalRate;
+ u8 reserved_1[2];
+
+ u32 BasicRateBitmap;
+ u32 OpRateBitmap;
+
+ // System parameters Set by GUI
+ //-------------------- start IBSS parameter ---------------------------//
+ u32 boStartIBSS; //Start IBSS toggle
+
+ u16 wBeaconPeriod;
+ u16 wATIM_Window;
+
+ ChanInfo IbssChan; // 2B //channel setting when start IBSS
+ u8 reserved_2[2];
+
+ // Join related
+ u16 wDesiredJoinBSS; // BSS index which desire to join
+ u8 boJoinReq; //Join request toggle
+ u8 bDesiredBSSType; //for Join request
+
+ u16 wCapabilityInfo; // Used when invoking the MLME_Associate_request().
+ u16 wNonERPcapabilityInfo;
+
+ struct SSID_Element sDesiredSSID; // 34 B
+ u8 reserved_3[2];
+
+ u8 abDesiredBSSID[MAC_ADDR_LENGTH + 2];
+
+ u8 bJoinScanCount; // the time of scan-join action need to do
+ u8 bDesiredAuthMode; // AUTH_OPEN_SYSTEM or AUTH_SHARED_KEY
+ u8 reserved_4[2];
+
+ // Encryption parameters
+ u8 _dot11PrivacyInvoked;
+ u8 _dot11PrivacyOptionImplemented;
+ u8 reserved_5[2];
+
+ //@ ws added
+ u8 DesiredEncrypt;
+ u8 encrypt_status; //ENCRYPT_DISABLE, ENCRYPT_WEP, ENCRYPT_WEP_NOKEY, ENCRYPT_TKIP, ...
+ u8 key_length;
+ u8 pairwise_key_ok;
+
+ u8 group_key_ok;
+ u8 wpa_ok; // indicate the control port of 802.1x is open or close
+ u8 pairwise_key_type;
+ u8 group_key_type;
+
+ u32 _dot11WEPDefaultKeyID;
+
+ u8 tx_mic_key[8]; // TODO: 0627 kevin-TKIP
+ u8 rx_mic_key[8]; // TODO: 0627 kevin-TKIP
+ u8 group_tx_mic_key[8];
+ u8 group_rx_mic_key[8];
+
+// #ifdef _WPA_
+ u8 AssocReqVarIE[200];
+ u8 AssocRespVarIE[200];
+
+ u16 AssocReqVarLen;
+ u16 AssocRespVarLen;
+ u8 boReassoc; //use assoc. or reassoc.
+ u8 reserved_6[3];
+ u16 AssocRespCapability;
+ u16 AssocRespStatus;
+// #endif
+
+ #ifdef _WPA2_
+ u8 PmkIdTable[256];
+ u32 PmkidTableIndex;
+ #endif //end def _WPA2_
+
+} SME_PARAMETERS, *PSME_PARAMETERS;
+
+#define psSME (&(Adapter->sSmePara))
+
+#define wSMEGetCurrentSTAState(Adapter) ((u16)(Adapter)->sSmePara.wState)
+
+
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// SmeModule.h
+// Define the related definitions of SME module
+// history -- 01/14/03' created
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//Define the state of SME module
+#define DISABLED 0
+#define INIT_SCAN 1
+#define SCAN_READY 2
+#define START_IBSS 3
+#define JOIN_PENDING 4
+#define JOIN_CFM 5
+#define AUTHENTICATE_PENDING 6
+#define AUTHENTICATED 7
+#define CONNECTED 8
+//#define EAP_STARTING 9
+//#define EAPOL_AUTHEN_PENDING 10
+//#define SECURE_CONNECTED 11
+
+
+// Static function
+
diff --git a/drivers/staging/winbond/wb35_ver.h b/drivers/staging/winbond/wb35_ver.h
new file mode 100644
index 00000000000..2433bc07300
--- /dev/null
+++ b/drivers/staging/winbond/wb35_ver.h
@@ -0,0 +1,30 @@
+//
+// Only define one of follow
+//
+
+#ifdef WB_WIN
+ #define VER_FILEVERSION 1,00,47,00
+ #define VER_FILEVERSION_STR "1.00.47.00"
+ #define WB32_DRIVER_MAJOR_VERSION 0x0100
+ #define WB32_DRIVER_MINOR_VERSION 0x4700
+#endif
+
+#ifdef WB_CE
+ #define VER_FILEVERSION 2,00,47,00
+ #define VER_FILEVERSION_STR "2.00.47.00"
+ #define WB32_DRIVER_MAJOR_VERSION 0x0200
+ #define WB32_DRIVER_MINOR_VERSION 0x4700
+#endif
+
+#ifdef WB_LINUX
+ #define VER_FILEVERSION 3,00,47,00
+ #define VER_FILEVERSION_STR "3.00.47.00"
+ #define WB32_DRIVER_MAJOR_VERSION 0x0300
+ #define WB32_DRIVER_MINOR_VERSION 0x4700
+#endif
+
+
+
+
+
+
diff --git a/drivers/staging/winbond/wbhal.c b/drivers/staging/winbond/wbhal.c
new file mode 100644
index 00000000000..daf44224755
--- /dev/null
+++ b/drivers/staging/winbond/wbhal.c
@@ -0,0 +1,878 @@
+#include "os_common.h"
+
+void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
+{
+ if( pHwData->SurpriseRemove ) return;
+
+ memcpy( current_address, pHwData->CurrentMacAddress, ETH_LENGTH_OF_ADDRESS );
+}
+
+void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
+{
+ u32 ltmp[2];
+
+ if( pHwData->SurpriseRemove ) return;
+
+ memcpy( pHwData->CurrentMacAddress, current_address, ETH_LENGTH_OF_ADDRESS );
+
+ ltmp[0]= cpu_to_le32( *(PULONG)pHwData->CurrentMacAddress );
+ ltmp[1]= cpu_to_le32( *(PULONG)(pHwData->CurrentMacAddress + 4) ) & 0xffff;
+
+ Wb35Reg_BurstWrite( pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT );
+}
+
+void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address )
+{
+ if( pHwData->SurpriseRemove ) return;
+
+ memcpy( pethernet_address, pHwData->PermanentMacAddress, 6 );
+}
+
+u8 hal_init_hardware(phw_data_t pHwData, PWB32_ADAPTER Adapter)
+{
+ u16 SoftwareSet;
+ pHwData->Adapter = Adapter;
+
+ // Initial the variable
+ pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME; // Setting Rx maximum MSDU life time
+ pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; // Setting default fragment threshold
+
+ if (WbUsb_initial(pHwData)) {
+ pHwData->InitialResource = 1;
+ if( Wb35Reg_initial(pHwData)) {
+ pHwData->InitialResource = 2;
+ if (Wb35Tx_initial(pHwData)) {
+ pHwData->InitialResource = 3;
+ if (Wb35Rx_initial(pHwData)) {
+ pHwData->InitialResource = 4;
+ OS_TIMER_INITIAL( &pHwData->LEDTimer, hal_led_control, pHwData );
+ OS_TIMER_SET( &pHwData->LEDTimer, 1000 ); // 20060623
+
+ //
+ // For restrict to vendor's hardware
+ //
+ SoftwareSet = hal_software_set( pHwData );
+
+ #ifdef Vendor2
+ // Try to make sure the EEPROM contain
+ SoftwareSet >>= 8;
+ if( SoftwareSet != 0x82 )
+ return FALSE;
+ #endif
+
+ Wb35Rx_start( pHwData );
+ Wb35Tx_EP2VM_start( pHwData );
+
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ pHwData->SurpriseRemove = 1;
+ return FALSE;
+}
+
+
+void hal_halt(phw_data_t pHwData, void *ppa_data)
+{
+ switch( pHwData->InitialResource )
+ {
+ case 4:
+ case 3: OS_TIMER_CANCEL( &pHwData->LEDTimer, &cancel );
+ OS_SLEEP(100000); // Wait for Timer DPC exit 940623.2
+ Wb35Rx_destroy( pHwData ); // Release the Rx
+ case 2: Wb35Tx_destroy( pHwData ); // Release the Tx
+ case 1: Wb35Reg_destroy( pHwData ); // Release the Wb35 Regisster resources
+ WbUsb_destroy( pHwData );// Release the WbUsb
+ }
+}
+
+//---------------------------------------------------------------------------------------------------
+void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
+ u8 length, unsigned char basic_rate_set)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 tmp, tmp1;
+ u8 Rate[12]={ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
+ u8 SupportedRate[16];
+ u8 i, j, k, Count1, Count2, Byte;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ if (basic_rate_set) {
+ pWb35Reg->M28_MacControl &= ~0x000fff00;
+ tmp1 = 0x00000100;
+ } else {
+ pWb35Reg->M28_MacControl &= ~0xfff00000;
+ tmp1 = 0x00100000;
+ }
+
+ tmp = 0;
+ for (i=0; i<length; i++) {
+ Byte = pbss_rates[i] & 0x7f;
+ for (j=0; j<12; j++) {
+ if( Byte == Rate[j] )
+ break;
+ }
+
+ if (j < 12)
+ tmp |= (tmp1<<j);
+ }
+
+ pWb35Reg->M28_MacControl |= tmp;
+ Wb35Reg_Write( pHwData, 0x0828, pWb35Reg->M28_MacControl );
+
+ // 930206.2.c M78 setting
+ j = k = Count1 = Count2 = 0;
+ memset( SupportedRate, 0, 16 );
+ tmp = 0x00100000;
+ tmp1 = 0x00000100;
+ for (i=0; i<12; i++) { // Get the supported rate
+ if (tmp & pWb35Reg->M28_MacControl) {
+ SupportedRate[j] = Rate[i];
+
+ if (tmp1 & pWb35Reg->M28_MacControl)
+ SupportedRate[j] |= 0x80;
+
+ if (k)
+ Count2++;
+ else
+ Count1++;
+
+ j++;
+ }
+
+ if (i==4 && k==0) {
+ if( !(pWb35Reg->M28_MacControl & 0x000ff000) ) // if basic rate in 11g domain)
+ {
+ k = 1;
+ j = 8;
+ }
+ }
+
+ tmp <<= 1;
+ tmp1 <<= 1;
+ }
+
+ // Fill data into support rate until buffer full
+ //---20060926 add by anson's endian
+ for (i=0; i<4; i++)
+ *(PULONG)(SupportedRate+(i<<2)) = cpu_to_le32( *(PULONG)(SupportedRate+(i<<2)) );
+ //--- end 20060926 add by anson's endian
+ Wb35Reg_BurstWrite( pHwData,0x087c, (PULONG)SupportedRate, 4, AUTO_INCREMENT );
+ pWb35Reg->M7C_MacControl = ((PULONG)SupportedRate)[0];
+ pWb35Reg->M80_MacControl = ((PULONG)SupportedRate)[1];
+ pWb35Reg->M84_MacControl = ((PULONG)SupportedRate)[2];
+ pWb35Reg->M88_MacControl = ((PULONG)SupportedRate)[3];
+
+ // Fill length
+ tmp = Count1<<28 | Count2<<24;
+ pWb35Reg->M78_ERPInformation &= ~0xff000000;
+ pWb35Reg->M78_ERPInformation |= tmp;
+ Wb35Reg_Write( pHwData, 0x0878, pWb35Reg->M78_ERPInformation );
+}
+
+
+//---------------------------------------------------------------------------------------------------
+void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period )
+{
+ u32 tmp;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ pHwData->BeaconPeriod = beacon_period;
+ tmp = pHwData->BeaconPeriod << 16;
+ tmp |= pHwData->ProbeDelay;
+ Wb35Reg_Write( pHwData, 0x0848, tmp );
+}
+
+
+void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove )
+ return;
+
+ printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
+
+ RFSynthesizer_SwitchingChannel( pHwData, channel );// Switch channel
+ pHwData->Channel = channel.ChanNo;
+ pHwData->band = channel.band;
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band));
+ #endif
+ pWb35Reg->M28_MacControl &= ~0xff; // Clean channel information field
+ pWb35Reg->M28_MacControl |= channel.ChanNo;
+ Wb35Reg_WriteWithCallbackValue( pHwData, 0x0828, pWb35Reg->M28_MacControl,
+ (PCHAR)&channel, sizeof(ChanInfo));
+}
+//---------------------------------------------------------------------------------------------------
+void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel )
+{
+ hal_set_current_channel_ex( pHwData, channel );
+}
+//---------------------------------------------------------------------------------------------------
+void hal_get_current_channel( phw_data_t pHwData, ChanInfo *channel )
+{
+ channel->ChanNo = pHwData->Channel;
+ channel->band = pHwData->band;
+}
+//---------------------------------------------------------------------------------------------------
+void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ pWb35Reg->M00_MacControl &= ~0x02000000;//The HW value
+
+ if (enable)
+ pWb35Reg->M00_MacControl |= 0x02000000;//The HW value
+
+ Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
+}
+
+//for wep key error detection, we need to accept broadcast packets to be received temporary.
+void hal_set_accept_promiscuous( phw_data_t pHwData, u8 enable)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if (pHwData->SurpriseRemove) return;
+ if (enable) {
+ pWb35Reg->M00_MacControl |= 0x00400000;
+ Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
+ } else {
+ pWb35Reg->M00_MacControl&=~0x00400000;
+ Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
+ }
+}
+
+void hal_set_accept_multicast( phw_data_t pHwData, u8 enable )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ pWb35Reg->M00_MacControl &= ~0x01000000;//The HW value
+ if (enable) pWb35Reg->M00_MacControl |= 0x01000000;//The HW value
+ Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
+}
+
+void hal_set_accept_beacon( phw_data_t pHwData, u8 enable )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ // 20040108 debug
+ if( !enable )//Due to SME and MLME are not suitable for 35
+ return;
+
+ pWb35Reg->M00_MacControl &= ~0x04000000;//The HW value
+ if( enable )
+ pWb35Reg->M00_MacControl |= 0x04000000;//The HW value
+
+ Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
+}
+//---------------------------------------------------------------------------------------------------
+void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u8 Byte, Bit;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ //Erases and refills the card multicast registers. Used when an address
+ // has been deleted and all bits must be recomputed.
+ pWb35Reg->M04_MulticastAddress1 = 0;
+ pWb35Reg->M08_MulticastAddress2 = 0;
+
+ while( number )
+ {
+ number--;
+ CardGetMulticastBit( (address+(number*ETH_LENGTH_OF_ADDRESS)), &Byte, &Bit);
+ pWb35Reg->Multicast[Byte] |= Bit;
+ }
+
+ // Updating register
+ Wb35Reg_BurstWrite( pHwData, 0x0804, (PULONG)pWb35Reg->Multicast, 2, AUTO_INCREMENT );
+}
+//---------------------------------------------------------------------------------------------------
+u8 hal_get_accept_beacon( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return 0;
+
+ if( pWb35Reg->M00_MacControl & 0x04000000 )
+ return 1;
+ else
+ return 0;
+}
+
+unsigned char hal_reset_hardware( phw_data_t pHwData, void* ppa )
+{
+ // Not implement yet
+ return TRUE;
+}
+
+void hal_stop( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ pHwData->Wb35Rx.rx_halt = 1;
+ Wb35Rx_stop( pHwData );
+
+ pHwData->Wb35Tx.tx_halt = 1;
+ Wb35Tx_stop( pHwData );
+
+ pWb35Reg->D00_DmaControl &= ~0xc0000000;//Tx Off, Rx Off
+ Wb35Reg_Write( pHwData, 0x0400, pWb35Reg->D00_DmaControl );
+
+ WbUsb_Stop( pHwData ); // 20051230 Add.4
+}
+
+unsigned char hal_idle(phw_data_t pHwData)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ PWBUSB pWbUsb = &pHwData->WbUsb;
+
+ if( !pHwData->SurpriseRemove && ( pWbUsb->DetectCount || pWb35Reg->EP0vm_state!=VM_STOP ) )
+ return FALSE;
+
+ return TRUE;
+}
+//---------------------------------------------------------------------------------------------------
+void hal_set_cwmin( phw_data_t pHwData, u8 cwin_min )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ pHwData->cwmin = cwin_min;
+ pWb35Reg->M2C_MacControl &= ~0x7c00; //bit 10 ~ 14
+ pWb35Reg->M2C_MacControl |= (pHwData->cwmin<<10);
+ Wb35Reg_Write( pHwData, 0x082c, pWb35Reg->M2C_MacControl );
+}
+
+s32 hal_get_rssi( phw_data_t pHwData, u32 *HalRssiArry, u8 Count )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ R01_DESCRIPTOR r01;
+ s32 ltmp = 0, tmp;
+ u8 i;
+
+ if( pHwData->SurpriseRemove ) return -200;
+ if( Count > MAX_ACC_RSSI_COUNT ) // Because the TS may use this funtion
+ Count = MAX_ACC_RSSI_COUNT;
+
+ // RSSI = C1 + C2 * (agc_state[7:0] + offset_map(lna_state[1:0]))
+ // C1 = -195, C2 = 0.66 = 85/128
+ for (i=0; i<Count; i++)
+ {
+ r01.value = HalRssiArry[i];
+ tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
+ ltmp += tmp;
+ }
+ ltmp /= Count;
+ if( pHwData->phy_type == RF_AIROHA_2230 ) ltmp -= 5; // 10;
+ if( pHwData->phy_type == RF_AIROHA_2230S ) ltmp -= 5; // 10; 20060420 Add this
+
+ //if( ltmp < -200 ) ltmp = -200;
+ if( ltmp < -110 ) ltmp = -110;// 1.0.24.0 For NJRC
+
+ return ltmp;
+}
+//----------------------------------------------------------------------------------------------------
+s32 hal_get_rssi_bss( phw_data_t pHwData, u16 idx, u8 Count )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ R01_DESCRIPTOR r01;
+ s32 ltmp = 0, tmp;
+ u8 i, j;
+ PADAPTER Adapter = pHwData->Adapter;
+// u32 *HalRssiArry = psBSS(idx)->HalRssi;
+
+ if( pHwData->SurpriseRemove ) return -200;
+ if( Count > MAX_ACC_RSSI_COUNT ) // Because the TS may use this funtion
+ Count = MAX_ACC_RSSI_COUNT;
+
+ // RSSI = C1 + C2 * (agc_state[7:0] + offset_map(lna_state[1:0]))
+ // C1 = -195, C2 = 0.66 = 85/128
+#if 0
+ for (i=0; i<Count; i++)
+ {
+ r01.value = HalRssiArry[i];
+ tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
+ ltmp += tmp;
+ }
+#else
+ if (psBSS(idx)->HalRssiIndex == 0)
+ psBSS(idx)->HalRssiIndex = MAX_ACC_RSSI_COUNT;
+ j = (u8)psBSS(idx)->HalRssiIndex-1;
+
+ for (i=0; i<Count; i++)
+ {
+ r01.value = psBSS(idx)->HalRssi[j];
+ tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
+ ltmp += tmp;
+ if (j == 0)
+ {
+ j = MAX_ACC_RSSI_COUNT;
+ }
+ j--;
+ }
+#endif
+ ltmp /= Count;
+ if( pHwData->phy_type == RF_AIROHA_2230 ) ltmp -= 5; // 10;
+ if( pHwData->phy_type == RF_AIROHA_2230S ) ltmp -= 5; // 10; 20060420 Add this
+
+ //if( ltmp < -200 ) ltmp = -200;
+ if( ltmp < -110 ) ltmp = -110;// 1.0.24.0 For NJRC
+
+ return ltmp;
+}
+
+//---------------------------------------------------------------------------
+void hal_led_control_1a( phw_data_t pHwData )
+{
+ hal_led_control( NULL, pHwData, NULL, NULL );
+}
+
+void hal_led_control( void* S1, phw_data_t pHwData, void* S3, void* S4 )
+{
+ PADAPTER Adapter = pHwData->Adapter;
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+ u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
+ u8 LEDgray[20] = { 0,3,4,6,8,10,11,12,13,14,15,14,13,12,11,10,8,6,4,2 };
+ u8 LEDgray2[30] = { 7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,15,14,13,12,11,10,9,8 };
+ u32 TimeInterval = 500, ltmp, ltmp2;
+ ltmp=0;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ if( pHwData->LED_control ) {
+ ltmp2 = pHwData->LED_control & 0xff;
+ if( ltmp2 == 5 ) // 5 is WPS mode
+ {
+ TimeInterval = 100;
+ ltmp2 = (pHwData->LED_control>>8) & 0xff;
+ switch( ltmp2 )
+ {
+ case 1: // [0.2 On][0.1 Off]...
+ pHwData->LED_Blinking %= 3;
+ ltmp = 0x1010; // Led 1 & 0 Green and Red
+ if( pHwData->LED_Blinking == 2 ) // Turn off
+ ltmp = 0;
+ break;
+ case 2: // [0.1 On][0.1 Off]...
+ pHwData->LED_Blinking %= 2;
+ ltmp = 0x0010; // Led 0 red color
+ if( pHwData->LED_Blinking ) // Turn off
+ ltmp = 0;
+ break;
+ case 3: // [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]...
+ pHwData->LED_Blinking %= 15;
+ ltmp = 0x0010; // Led 0 red color
+ if( (pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking%2) ) // Turn off 0.6 sec
+ ltmp = 0;
+ break;
+ case 4: // [300 On][ off ]
+ ltmp = 0x1000; // Led 1 Green color
+ if( pHwData->LED_Blinking >= 3000 )
+ ltmp = 0; // led maybe on after 300sec * 32bit counter overlap.
+ break;
+ }
+ pHwData->LED_Blinking++;
+
+ pWb35Reg->U1BC_LEDConfigure = ltmp;
+ if( LEDSet != 7 ) // Only 111 mode has 2 LEDs on PCB.
+ {
+ pWb35Reg->U1BC_LEDConfigure |= (ltmp &0xff)<<8; // Copy LED result to each LED control register
+ pWb35Reg->U1BC_LEDConfigure |= (ltmp &0xff00)>>8;
+ }
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+ }
+ }
+ else if( pHwData->CurrentRadioSw || pHwData->CurrentRadioHw ) // If radio off
+ {
+ if( pWb35Reg->U1BC_LEDConfigure & 0x1010 )
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x1010;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+ }
+ }
+ else
+ {
+ switch( LEDSet )
+ {
+ case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
+ if( !pHwData->LED_LinkOn ) // Blink only if not Link On
+ {
+ // Blinking if scanning is on progress
+ if( pHwData->LED_Scanning )
+ {
+ if( pHwData->LED_Blinking == 0 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 On
+ pHwData->LED_Blinking = 1;
+ TimeInterval = 300;
+ }
+ else
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ pHwData->LED_Blinking = 0;
+ TimeInterval = 300;
+ }
+ }
+ else
+ {
+ //Turn Off LED_0
+ if( pWb35Reg->U1BC_LEDConfigure & 0x10 )
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ }
+ }
+ }
+ else
+ {
+ // Turn On LED_0
+ if( (pWb35Reg->U1BC_LEDConfigure & 0x10) == 0 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ }
+ }
+ break;
+
+ case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
+ if( !pHwData->LED_LinkOn ) // Blink only if not Link On
+ {
+ // Blinking if scanning is on progress
+ if( pHwData->LED_Scanning )
+ {
+ if( pHwData->LED_Blinking == 0 )
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0xf;
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 On
+ pHwData->LED_Blinking = 1;
+ TimeInterval = 300;
+ }
+ else
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x1f;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ pHwData->LED_Blinking = 0;
+ TimeInterval = 300;
+ }
+ }
+ else
+ {
+ // 20060901 Gray blinking if in disconnect state and not scanning
+ ltmp = pWb35Reg->U1BC_LEDConfigure;
+ pWb35Reg->U1BC_LEDConfigure &= ~0x1f;
+ if( LEDgray2[(pHwData->LED_Blinking%30)] )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ pWb35Reg->U1BC_LEDConfigure |= LEDgray2[ (pHwData->LED_Blinking%30) ];
+ }
+ pHwData->LED_Blinking++;
+ if( pWb35Reg->U1BC_LEDConfigure != ltmp )
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ TimeInterval = 100;
+ }
+ }
+ else
+ {
+ // Turn On LED_0
+ if( (pWb35Reg->U1BC_LEDConfigure & 0x10) == 0 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
+ }
+ }
+ break;
+
+ case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing
+ if( !pHwData->LED_LinkOn ) // Blink only if not Link On
+ {
+ // Blinking if scanning is on progress
+ if( pHwData->LED_Scanning )
+ {
+ if( pHwData->LED_Blinking == 0 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x1000;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
+ pHwData->LED_Blinking = 1;
+ TimeInterval = 300;
+ }
+ else
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x1000;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 Off
+ pHwData->LED_Blinking = 0;
+ TimeInterval = 300;
+ }
+ }
+ else
+ {
+ //Turn Off LED_1
+ if( pWb35Reg->U1BC_LEDConfigure & 0x1000 )
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x1000;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 Off
+ }
+ }
+ }
+ else
+ {
+ // Is transmitting/receiving ??
+ if( (OS_CURRENT_RX_BYTE( Adapter ) != pHwData->RxByteCountLast ) ||
+ (OS_CURRENT_TX_BYTE( Adapter ) != pHwData->TxByteCountLast ) )
+ {
+ if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x3000 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x3000;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
+ }
+
+ // Update variable
+ pHwData->RxByteCountLast = OS_CURRENT_RX_BYTE( Adapter );
+ pHwData->TxByteCountLast = OS_CURRENT_TX_BYTE( Adapter );
+ TimeInterval = 200;
+ }
+ else
+ {
+ // Turn On LED_1 and blinking if transmitting/receiving
+ if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x1000 )
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x3000;
+ pWb35Reg->U1BC_LEDConfigure |= 0x1000;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
+ }
+ }
+ }
+ break;
+
+ default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active
+ if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x3000 )
+ {
+ pWb35Reg->U1BC_LEDConfigure |= 0x3000;// LED_1 is always on and event enable
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+ }
+
+ if( pHwData->LED_Blinking )
+ {
+ // Gray blinking
+ pWb35Reg->U1BC_LEDConfigure &= ~0x0f;
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ pWb35Reg->U1BC_LEDConfigure |= LEDgray[ (pHwData->LED_Blinking-1)%20 ];
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+
+ pHwData->LED_Blinking += 2;
+ if( pHwData->LED_Blinking < 40 )
+ TimeInterval = 100;
+ else
+ {
+ pHwData->LED_Blinking = 0; // Stop blinking
+ pWb35Reg->U1BC_LEDConfigure &= ~0x0f;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+ }
+ break;
+ }
+
+ if( pHwData->LED_LinkOn )
+ {
+ if( !(pWb35Reg->U1BC_LEDConfigure & 0x10) ) // Check the LED_0
+ {
+ //Try to turn ON LED_0 after gray blinking
+ pWb35Reg->U1BC_LEDConfigure |= 0x10;
+ pHwData->LED_Blinking = 1; //Start blinking
+ TimeInterval = 50;
+ }
+ }
+ else
+ {
+ if( pWb35Reg->U1BC_LEDConfigure & 0x10 ) // Check the LED_0
+ {
+ pWb35Reg->U1BC_LEDConfigure &= ~0x10;
+ Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
+ }
+ }
+ break;
+ }
+
+ //20060828.1 Active send null packet to avoid AP disconnect
+ if( pHwData->LED_LinkOn )
+ {
+ pHwData->NullPacketCount += TimeInterval;
+ if( pHwData->NullPacketCount >= DEFAULT_NULL_PACKET_COUNT )
+ {
+ pHwData->NullPacketCount = 0;
+ }
+ }
+ }
+
+ pHwData->time_count += TimeInterval;
+ Wb35Tx_CurrentTime( pHwData, pHwData->time_count ); // 20060928 add
+ OS_TIMER_SET( &pHwData->LEDTimer, TimeInterval ); // 20060623.1
+}
+
+
+void hal_set_phy_type( phw_data_t pHwData, u8 PhyType )
+{
+ pHwData->phy_type = PhyType;
+}
+
+void hal_get_phy_type( phw_data_t pHwData, u8 *PhyType )
+{
+ *PhyType = pHwData->phy_type;
+}
+
+void hal_reset_counter( phw_data_t pHwData )
+{
+ pHwData->dto_tx_retry_count = 0;
+ pHwData->dto_tx_frag_count = 0;
+ memset( pHwData->tx_retry_count, 0, 8);
+}
+
+void hal_set_radio_mode( phw_data_t pHwData, unsigned char radio_off)
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return;
+
+ if (radio_off) //disable Baseband receive off
+ {
+ pHwData->CurrentRadioSw = 1; // off
+ pWb35Reg->M24_MacControl &= 0xffffffbf;
+ }
+ else
+ {
+ pHwData->CurrentRadioSw = 0; // on
+ pWb35Reg->M24_MacControl |= 0x00000040;
+ }
+ Wb35Reg_Write( pHwData, 0x0824, pWb35Reg->M24_MacControl );
+}
+
+u8 hal_get_antenna_number( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if ((pWb35Reg->BB2C & BIT(11)) == 0)
+ return 0;
+ else
+ return 1;
+}
+
+void hal_set_antenna_number( phw_data_t pHwData, u8 number )
+{
+
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if (number == 1) {
+ pWb35Reg->BB2C |= BIT(11);
+ } else {
+ pWb35Reg->BB2C &= ~BIT(11);
+ }
+ Wb35Reg_Write( pHwData, 0x102c, pWb35Reg->BB2C );
+#ifdef _PE_STATE_DUMP_
+ WBDEBUG(("Current antenna number : %d\n", number));
+#endif
+}
+
+//----------------------------------------------------------------------------------------------------
+//0 : radio on; 1: radio off
+u8 hal_get_hw_radio_off( phw_data_t pHwData )
+{
+ PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+ if( pHwData->SurpriseRemove ) return 1;
+
+ //read the bit16 of register U1B0
+ Wb35Reg_Read( pHwData, 0x3b0, &pWb35Reg->U1B0 );
+ if ((pWb35Reg->U1B0 & 0x00010000)) {
+ pHwData->CurrentRadioHw = 1;
+ return 1;
+ } else {
+ pHwData->CurrentRadioHw = 0;
+ return 0;
+ }
+}
+
+unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue )
+{
+ if( number < 0x1000 )
+ number += 0x1000;
+ return Wb35Reg_ReadSync( pHwData, number, pValue );
+}
+
+unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value )
+{
+ unsigned char ret;
+
+ if( number < 0x1000 )
+ number += 0x1000;
+ ret = Wb35Reg_WriteSync( pHwData, number, value );
+ return ret;
+}
+
+void hal_scan_status_indicate(phw_data_t pHwData, unsigned char IsOnProgress)
+{
+ if( pHwData->SurpriseRemove ) return;
+ pHwData->LED_Scanning = IsOnProgress ? 1 : 0;
+}
+
+void hal_system_power_change(phw_data_t pHwData, u32 PowerState)
+{
+ if( PowerState != 0 )
+ {
+ pHwData->SurpriseRemove = 1;
+ if( pHwData->WbUsb.IsUsb20 )
+ hal_stop( pHwData );
+ }
+ else
+ {
+ if( !pHwData->WbUsb.IsUsb20 )
+ hal_stop( pHwData );
+ }
+}
+
+void hal_surprise_remove( phw_data_t pHwData )
+{
+ PADAPTER Adapter = pHwData->Adapter;
+ if (OS_ATOMIC_INC( Adapter, &pHwData->SurpriseRemoveCount ) == 1) {
+ #ifdef _PE_STATE_DUMP_
+ WBDEBUG(("Calling hal_surprise_remove\n"));
+ #endif
+ OS_STOP( Adapter );
+ }
+}
+
+void hal_rate_change( phw_data_t pHwData ) // Notify the HAL rate is changing 20060613.1
+{
+ PADAPTER Adapter = pHwData->Adapter;
+ u8 rate = CURRENT_TX_RATE;
+
+ BBProcessor_RateChanging( pHwData, rate );
+}
+
+void hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex)
+{
+ RFSynthesizer_SetPowerIndex( pHwData, PowerIndex );
+}
+
+unsigned char hal_set_LED(phw_data_t pHwData, u32 Mode) // 20061108 for WPS led control
+{
+ pHwData->LED_Blinking = 0;
+ pHwData->LED_control = Mode;
+ OS_TIMER_SET( &pHwData->LEDTimer, 10 ); // 20060623
+ return TRUE;
+}
+
diff --git a/drivers/staging/winbond/wbhal_f.h b/drivers/staging/winbond/wbhal_f.h
new file mode 100644
index 00000000000..fe25f97af72
--- /dev/null
+++ b/drivers/staging/winbond/wbhal_f.h
@@ -0,0 +1,122 @@
+//=====================================================================
+// Device related include
+//=====================================================================
+#ifdef WB_LINUX
+ #include "linux/wbusb_f.h"
+ #include "linux/wb35reg_f.h"
+ #include "linux/wb35tx_f.h"
+ #include "linux/wb35rx_f.h"
+#else
+ #include "wbusb_f.h"
+ #include "wb35reg_f.h"
+ #include "wb35tx_f.h"
+ #include "wb35rx_f.h"
+#endif
+
+//====================================================================================
+// Function declaration
+//====================================================================================
+void hal_remove_mapping_key( phw_data_t pHwData, PUCHAR pmac_addr );
+void hal_remove_default_key( phw_data_t pHwData, u32 index );
+unsigned char hal_set_mapping_key( phw_data_t Adapter, PUCHAR pmac_addr, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
+unsigned char hal_set_default_key( phw_data_t Adapter, u8 index, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
+void hal_clear_all_default_key( phw_data_t pHwData );
+void hal_clear_all_group_key( phw_data_t pHwData );
+void hal_clear_all_mapping_key( phw_data_t pHwData );
+void hal_clear_all_key( phw_data_t pHwData );
+void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
+void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
+void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address );
+unsigned char hal_init_hardware( phw_data_t pHwData, PADAPTER Adapter );
+void hal_set_power_save_mode( phw_data_t pHwData, unsigned char power_save, unsigned char wakeup, unsigned char dtim );
+void hal_get_power_save_mode( phw_data_t pHwData, PBOOLEAN pin_pwr_save );
+void hal_set_slot_time( phw_data_t pHwData, u8 type );
+#define hal_set_atim_window( _A, _ATM )
+void hal_set_rates( phw_data_t pHwData, PUCHAR pbss_rates, u8 length, unsigned char basic_rate_set );
+#define hal_set_basic_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, TRUE )
+#define hal_set_op_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, FALSE )
+void hal_start_bss( phw_data_t pHwData, u8 mac_op_mode );
+void hal_join_request( phw_data_t pHwData, u8 bss_type ); // 0:BSS STA 1:IBSS STA//
+void hal_stop_sync_bss( phw_data_t pHwData );
+void hal_resume_sync_bss( phw_data_t pHwData);
+void hal_set_aid( phw_data_t pHwData, u16 aid );
+void hal_set_bssid( phw_data_t pHwData, PUCHAR pbssid );
+void hal_get_bssid( phw_data_t pHwData, PUCHAR pbssid );
+void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period );
+void hal_set_listen_interval( phw_data_t pHwData, u16 listen_interval );
+void hal_set_cap_info( phw_data_t pHwData, u16 capability_info );
+void hal_set_ssid( phw_data_t pHwData, PUCHAR pssid, u8 ssid_len );
+void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel );
+void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel );
+void hal_get_current_channel( phw_data_t pHwData, ChanInfo *channel );
+void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable );
+void hal_set_accept_multicast( phw_data_t pHwData, u8 enable );
+void hal_set_accept_beacon( phw_data_t pHwData, u8 enable );
+void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number );
+u8 hal_get_accept_beacon( phw_data_t pHwData );
+void hal_stop( phw_data_t pHwData );
+void hal_halt( phw_data_t pHwData, void *ppa_data );
+void hal_start_tx0( phw_data_t pHwData );
+void hal_set_phy_type( phw_data_t pHwData, u8 PhyType );
+void hal_get_phy_type( phw_data_t pHwData, u8 *PhyType );
+unsigned char hal_reset_hardware( phw_data_t pHwData, void* ppa );
+void hal_set_cwmin( phw_data_t pHwData, u8 cwin_min );
+#define hal_get_cwmin( _A ) ( (_A)->cwmin )
+void hal_set_cwmax( phw_data_t pHwData, u16 cwin_max );
+#define hal_get_cwmax( _A ) ( (_A)->cwmax )
+void hal_set_rsn_wpa( phw_data_t pHwData, u32 * RSN_IE_Bitmap , u32 * RSN_OUI_type , unsigned char bDesiredAuthMode);
+//s32 hal_get_rssi( phw_data_t pHwData, u32 HalRssi );
+s32 hal_get_rssi( phw_data_t pHwData, u32 *HalRssiArry, u8 Count );
+s32 hal_get_rssi_bss( phw_data_t pHwData, u16 idx, u8 Count );
+void hal_set_connect_info( phw_data_t pHwData, unsigned char boConnect );
+u8 hal_get_est_sq3( phw_data_t pHwData, u8 Count );
+void hal_led_control_1a( phw_data_t pHwData );
+void hal_led_control( void* S1, phw_data_t pHwData, void* S3, void* S4 );
+void hal_set_rf_power( phw_data_t pHwData, u8 PowerIndex ); // 20060621 Modify
+void hal_reset_counter( phw_data_t pHwData );
+void hal_set_radio_mode( phw_data_t pHwData, unsigned char boValue);
+void hal_descriptor_indicate( phw_data_t pHwData, PDESCRIPTOR pDes );
+u8 hal_get_antenna_number( phw_data_t pHwData );
+void hal_set_antenna_number( phw_data_t pHwData, u8 number );
+u32 hal_get_bss_pk_cnt( phw_data_t pHwData );
+#define hal_get_region_from_EEPROM( _A ) ( (_A)->Wb35Reg.EEPROMRegion )
+void hal_set_accept_promiscuous ( phw_data_t pHwData, u8 enable);
+#define hal_get_tx_buffer( _A, _B ) Wb35Tx_get_tx_buffer( _A, _B )
+u8 hal_get_hw_radio_off ( phw_data_t pHwData );
+#define hal_software_set( _A ) (_A->SoftwareSet)
+#define hal_driver_init_OK( _A ) (_A->IsInitOK)
+#define hal_rssi_boundary_high( _A ) (_A->RSSI_high)
+#define hal_rssi_boundary_low( _A ) (_A->RSSI_low)
+#define hal_scan_interval( _A ) (_A->Scan_Interval)
+void hal_scan_status_indicate( phw_data_t pHwData, u8 status); // 0: complete, 1: in progress
+void hal_system_power_change( phw_data_t pHwData, u32 PowerState ); // 20051230 -=D0 1=D1 ..
+void hal_surprise_remove( phw_data_t pHwData );
+
+#define PHY_DEBUG( msg, args... )
+
+
+
+void hal_rate_change( phw_data_t pHwData ); // Notify the HAL rate is changing 20060613.1
+unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue );
+unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value );
+#define hal_get_time_count( _P ) (_P->time_count/10) // return 100ms count
+#define hal_detect_error( _P ) (_P->WbUsb.DetectCount)
+unsigned char hal_set_LED( phw_data_t pHwData, u32 Mode ); // 20061108 for WPS led control
+
+//-------------------------------------------------------------------------
+// The follow function is unused for IS89C35
+//-------------------------------------------------------------------------
+#define hal_disable_interrupt(_A)
+#define hal_enable_interrupt(_A)
+#define hal_get_interrupt_type( _A)
+#define hal_get_clear_interrupt(_A)
+#define hal_ibss_disconnect(_A) hal_stop_sync_bss(_A)
+#define hal_join_request_stop(_A)
+unsigned char hal_idle( phw_data_t pHwData );
+#define pa_stall_execution( _A ) //OS_SLEEP( 1 )
+#define hw_get_cxx_reg( _A, _B, _C )
+#define hw_set_cxx_reg( _A, _B, _C )
+#define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (PULONG)_C )
+#define hw_set_dxx_reg( _A, _B, _C ) hal_set_dxx_reg( _A, _B, (u32)_C )
+
+
diff --git a/drivers/staging/winbond/wbhal_s.h b/drivers/staging/winbond/wbhal_s.h
new file mode 100644
index 00000000000..5b862ff357b
--- /dev/null
+++ b/drivers/staging/winbond/wbhal_s.h
@@ -0,0 +1,615 @@
+//[20040722 WK]
+#define HAL_LED_SET_MASK 0x001c //20060901 Extend
+#define HAL_LED_SET_SHIFT 2
+
+//supported RF type
+#define RF_MAXIM_2825 0
+#define RF_MAXIM_2827 1
+#define RF_MAXIM_2828 2
+#define RF_MAXIM_2829 3
+#define RF_MAXIM_V1 15
+#define RF_AIROHA_2230 16
+#define RF_AIROHA_7230 17
+#define RF_AIROHA_2230S 18 // 20060420 Add this
+// #define RF_RFMD_2959 32 // 20060626 Remove all about RFMD
+#define RF_WB_242 33
+#define RF_WB_242_1 34 // 20060619.5 Add
+#define RF_DECIDE_BY_INF 255
+
+//----------------------------------------------------------------
+// The follow define connect to upper layer
+// User must modify for connection between HAL and upper layer
+//----------------------------------------------------------------
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+//================================================================================================
+// Common define
+//================================================================================================
+#define HAL_USB_MODE_BURST( _H ) (_H->SoftwareSet & 0x20 ) // Bit 5 20060901 Modify
+
+// Scan interval
+#define SCAN_MAX_CHNL_TIME (50)
+
+// For TxL2 Frame typr recognise
+#define FRAME_TYPE_802_3_DATA 0
+#define FRAME_TYPE_802_11_MANAGEMENT 1
+#define FRAME_TYPE_802_11_MANAGEMENT_CHALLENGE 2
+#define FRAME_TYPE_802_11_CONTROL 3
+#define FRAME_TYPE_802_11_DATA 4
+#define FRAME_TYPE_PROMISCUOUS 5
+
+// The follow definition is used for convert the frame--------------------
+#define DOT_11_SEQUENCE_OFFSET 22 //Sequence control offset
+#define DOT_3_TYPE_OFFSET 12
+#define DOT_11_MAC_HEADER_SIZE 24
+#define DOT_11_SNAP_SIZE 6
+#define DOT_11_TYPE_OFFSET 30 //The start offset of 802.11 Frame. Type encapsulatuin.
+#define DEFAULT_SIFSTIME 10
+#define DEFAULT_FRAGMENT_THRESHOLD 2346 // No fragment
+#define DEFAULT_MSDU_LIFE_TIME 0xffff
+
+#define LONG_PREAMBLE_PLUS_PLCPHEADER_TIME (144+48)
+#define SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME (72+24)
+#define PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION (16+4+6)
+#define Tsym 4
+
+// Frame Type of Bits (2, 3)---------------------------------------------
+#define MAC_TYPE_MANAGEMENT 0x00
+#define MAC_TYPE_CONTROL 0x04
+#define MAC_TYPE_DATA 0x08
+#define MASK_FRAGMENT_NUMBER 0x000F
+#define SEQUENCE_NUMBER_SHIFT 4
+
+#define HAL_WOL_TYPE_WAKEUP_FRAME 0x01
+#define HAL_WOL_TYPE_MAGIC_PACKET 0x02
+
+// 20040106 ADDED
+#define HAL_KEYTYPE_WEP40 0
+#define HAL_KEYTYPE_WEP104 1
+#define HAL_KEYTYPE_TKIP 2 // 128 bit key
+#define HAL_KEYTYPE_AES_CCMP 3 // 128 bit key
+
+// For VM state
+enum {
+ VM_STOP = 0,
+ VM_RUNNING,
+ VM_COMPLETED
+};
+
+// Be used for 802.11 mac header
+typedef struct _MAC_FRAME_CONTROL {
+ u8 mac_frame_info; // this is a combination of the protovl version, type and subtype
+ u8 to_ds:1;
+ u8 from_ds:1;
+ u8 more_frag:1;
+ u8 retry:1;
+ u8 pwr_mgt:1;
+ u8 more_data:1;
+ u8 WEP:1;
+ u8 order:1;
+} MAC_FRAME_CONTROL, *PMAC_FRAME_CONTROL;
+
+//-----------------------------------------------------
+// Normal Key table format
+//-----------------------------------------------------
+// The order of KEY index is MAPPING_KEY_START_INDEX > GROUP_KEY_START_INDEX
+#define MAX_KEY_TABLE 24 // 24 entry for storing key data
+#define GROUP_KEY_START_INDEX 4
+#define MAPPING_KEY_START_INDEX 8
+typedef struct _KEY_TABLE
+{
+ u32 DW0_Valid:1;
+ u32 DW0_NullKey:1;
+ u32 DW0_Security_Mode:2;//0:WEP 40 bit 1:WEP 104 bit 2:TKIP 128 bit 3:CCMP 128 bit
+ u32 DW0_WEPON:1;
+ u32 DW0_RESERVED:11;
+ u32 DW0_Address1:16;
+
+ u32 DW1_Address2;
+
+ u32 DW2_RxSequenceCount1;
+
+ u32 DW3_RxSequenceCount2:16;
+ u32 DW3_RESERVED:16;
+
+ u32 DW4_TxSequenceCount1;
+
+ u32 DW5_TxSequenceCount2:16;
+ u32 DW5_RESERVED:16;
+
+} KEY_TABLE, *PKEY_TABLE;
+
+//--------------------------------------------------------
+// Descriptor
+//--------------------------------------------------------
+#define MAX_DESCRIPTOR_BUFFER_INDEX 8 // Have to multiple of 2
+//#define FLAG_ERROR_TX_MASK cpu_to_le32(0x000000bf) //20061009 marked by anson's endian
+#define FLAG_ERROR_TX_MASK 0x000000bf //20061009 anson's endian
+//#define FLAG_ERROR_RX_MASK 0x00000c3f
+//#define FLAG_ERROR_RX_MASK cpu_to_le32(0x0000083f) //20061009 marked by anson's endian
+ //Don't care replay error,
+ //it is handled by S/W
+#define FLAG_ERROR_RX_MASK 0x0000083f //20060926 anson's endian
+
+#define FLAG_BAND_RX_MASK 0x10000000 //Bit 28
+
+typedef struct _R00_DESCRIPTOR
+{
+ union
+ {
+ u32 value;
+ #ifdef _BIG_ENDIAN_ //20060926 anson's endian
+ struct
+ {
+ u32 R00_packet_or_buffer_status:1;
+ u32 R00_packet_in_fifo:1;
+ u32 R00_RESERVED:2;
+ u32 R00_receive_byte_count:12;
+ u32 R00_receive_time_index:16;
+ };
+ #else
+ struct
+ {
+ u32 R00_receive_time_index:16;
+ u32 R00_receive_byte_count:12;
+ u32 R00_RESERVED:2;
+ u32 R00_packet_in_fifo:1;
+ u32 R00_packet_or_buffer_status:1;
+ };
+ #endif
+ };
+} R00_DESCRIPTOR, *PR00_DESCRIPTOR;
+
+typedef struct _T00_DESCRIPTOR
+{
+ union
+ {
+ u32 value;
+ #ifdef _BIG_ENDIAN_ //20061009 anson's endian
+ struct
+ {
+ u32 T00_first_mpdu:1; // for hardware use
+ u32 T00_last_mpdu:1; // for hardware use
+ u32 T00_IsLastMpdu:1;// 0: not 1:Yes for software used
+ u32 T00_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
+ u32 T00_RESERVED_ID:2;//3 bit ID reserved
+ u32 T00_tx_packet_id:4;//930519.4.e 930810.3.c
+ u32 T00_RESERVED:4;
+ u32 T00_header_length:6;
+ u32 T00_frame_length:12;
+ };
+ #else
+ struct
+ {
+ u32 T00_frame_length:12;
+ u32 T00_header_length:6;
+ u32 T00_RESERVED:4;
+ u32 T00_tx_packet_id:4;//930519.4.e 930810.3.c
+ u32 T00_RESERVED_ID:2;//3 bit ID reserved
+ u32 T00_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
+ u32 T00_IsLastMpdu:1;// 0: not 1:Yes for software used
+ u32 T00_last_mpdu:1; // for hardware use
+ u32 T00_first_mpdu:1; // for hardware use
+ };
+ #endif
+ };
+} T00_DESCRIPTOR, *PT00_DESCRIPTOR;
+
+typedef struct _R01_DESCRIPTOR
+{
+ union
+ {
+ u32 value;
+ #ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
+ struct
+ {
+ u32 R01_RESERVED:3;
+ u32 R01_mod_type:1;
+ u32 R01_pre_type:1;
+ u32 R01_data_rate:3;
+ u32 R01_AGC_state:8;
+ u32 R01_LNA_state:2;
+ u32 R01_decryption_method:2;
+ u32 R01_mic_error:1;
+ u32 R01_replay:1;
+ u32 R01_broadcast_frame:1;
+ u32 R01_multicast_frame:1;
+ u32 R01_directed_frame:1;
+ u32 R01_receive_frame_antenna_selection:1;
+ u32 R01_frame_receive_during_atim_window:1;
+ u32 R01_protocol_version_error:1;
+ u32 R01_authentication_frame_icv_error:1;
+ u32 R01_null_key_to_authentication_frame:1;
+ u32 R01_icv_error:1;
+ u32 R01_crc_error:1;
+ };
+ #else
+ struct
+ {
+ u32 R01_crc_error:1;
+ u32 R01_icv_error:1;
+ u32 R01_null_key_to_authentication_frame:1;
+ u32 R01_authentication_frame_icv_error:1;
+ u32 R01_protocol_version_error:1;
+ u32 R01_frame_receive_during_atim_window:1;
+ u32 R01_receive_frame_antenna_selection:1;
+ u32 R01_directed_frame:1;
+ u32 R01_multicast_frame:1;
+ u32 R01_broadcast_frame:1;
+ u32 R01_replay:1;
+ u32 R01_mic_error:1;
+ u32 R01_decryption_method:2;
+ u32 R01_LNA_state:2;
+ u32 R01_AGC_state:8;
+ u32 R01_data_rate:3;
+ u32 R01_pre_type:1;
+ u32 R01_mod_type:1;
+ u32 R01_RESERVED:3;
+ };
+ #endif
+ };
+} R01_DESCRIPTOR, *PR01_DESCRIPTOR;
+
+typedef struct _T01_DESCRIPTOR
+{
+ union
+ {
+ u32 value;
+ #ifdef _BIG_ENDIAN_ //20061009 anson's endian
+ struct
+ {
+ u32 T01_rts_cts_duration:16;
+ u32 T01_fall_back_rate:3;
+ u32 T01_add_rts:1;
+ u32 T01_add_cts:1;
+ u32 T01_modulation_type:1;
+ u32 T01_plcp_header_length:1;
+ u32 T01_transmit_rate:3;
+ u32 T01_wep_id:2;
+ u32 T01_add_challenge_text:1;
+ u32 T01_inhibit_crc:1;
+ u32 T01_loop_back_wep_mode:1;
+ u32 T01_retry_abort_ebable:1;
+ };
+ #else
+ struct
+ {
+ u32 T01_retry_abort_ebable:1;
+ u32 T01_loop_back_wep_mode:1;
+ u32 T01_inhibit_crc:1;
+ u32 T01_add_challenge_text:1;
+ u32 T01_wep_id:2;
+ u32 T01_transmit_rate:3;
+ u32 T01_plcp_header_length:1;
+ u32 T01_modulation_type:1;
+ u32 T01_add_cts:1;
+ u32 T01_add_rts:1;
+ u32 T01_fall_back_rate:3;
+ u32 T01_rts_cts_duration:16;
+ };
+ #endif
+ };
+} T01_DESCRIPTOR, *PT01_DESCRIPTOR;
+
+typedef struct _T02_DESCRIPTOR
+{
+ union
+ {
+ u32 value;
+ #ifdef _BIG_ENDIAN_ //20061009 add by anson's endian
+ struct
+ {
+ u32 T02_IsLastMpdu:1;// The same mechanism with T00 setting
+ u32 T02_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
+ u32 T02_RESERVED_ID:2;// The same mechanism with T00 setting
+ u32 T02_Tx_PktID:4;
+ u32 T02_MPDU_Cnt:4;
+ u32 T02_RTS_Cnt:4;
+ u32 T02_RESERVED:7;
+ u32 T02_transmit_complete:1;
+ u32 T02_transmit_abort_due_to_TBTT:1;
+ u32 T02_effective_transmission_rate:1;
+ u32 T02_transmit_without_encryption_due_to_wep_on_false:1;
+ u32 T02_discard_due_to_null_wep_key:1;
+ u32 T02_RESERVED_1:1;
+ u32 T02_out_of_MaxTxMSDULiftTime:1;
+ u32 T02_transmit_abort:1;
+ u32 T02_transmit_fail:1;
+ };
+ #else
+ struct
+ {
+ u32 T02_transmit_fail:1;
+ u32 T02_transmit_abort:1;
+ u32 T02_out_of_MaxTxMSDULiftTime:1;
+ u32 T02_RESERVED_1:1;
+ u32 T02_discard_due_to_null_wep_key:1;
+ u32 T02_transmit_without_encryption_due_to_wep_on_false:1;
+ u32 T02_effective_transmission_rate:1;
+ u32 T02_transmit_abort_due_to_TBTT:1;
+ u32 T02_transmit_complete:1;
+ u32 T02_RESERVED:7;
+ u32 T02_RTS_Cnt:4;
+ u32 T02_MPDU_Cnt:4;
+ u32 T02_Tx_PktID:4;
+ u32 T02_RESERVED_ID:2;// The same mechanism with T00 setting
+ u32 T02_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
+ u32 T02_IsLastMpdu:1;// The same mechanism with T00 setting
+ };
+ #endif
+ };
+} T02_DESCRIPTOR, *PT02_DESCRIPTOR;
+
+typedef struct _DESCRIPTOR { // Skip length = 8 DWORD
+ // ID for descriptor ---, The field doesn't be cleard in the operation of Descriptor definition
+ u8 Descriptor_ID;
+ //----------------------The above region doesn't be cleared by DESCRIPTOR_RESET------
+ u8 RESERVED[3];
+
+ u16 FragmentThreshold;
+ u8 InternalUsed;//Only can be used by operation of descriptor definition
+ u8 Type;// 0: 802.3 1:802.11 data frame 2:802.11 management frame
+
+ u8 PreambleMode;// 0: short 1:long
+ u8 TxRate;
+ u8 FragmentCount;
+ u8 EapFix; // For speed up key install
+
+ // For R00 and T00 ----------------------------------------------
+ union
+ {
+ R00_DESCRIPTOR R00;
+ T00_DESCRIPTOR T00;
+ };
+
+ // For R01 and T01 ----------------------------------------------
+ union
+ {
+ R01_DESCRIPTOR R01;
+ T01_DESCRIPTOR T01;
+ };
+
+ // For R02 and T02 ----------------------------------------------
+ union
+ {
+ u32 R02;
+ T02_DESCRIPTOR T02;
+ };
+
+ // For R03 and T03 ----------------------------------------------
+ // For software used
+ union
+ {
+ u32 R03;
+ u32 T03;
+ struct
+ {
+ u8 buffer_number;
+ u8 buffer_start_index;
+ u16 buffer_total_size;
+ };
+ };
+
+ // For storing the buffer
+ u16 buffer_size[ MAX_DESCRIPTOR_BUFFER_INDEX ];
+ void* buffer_address[ MAX_DESCRIPTOR_BUFFER_INDEX ];//931130.4.q
+
+} DESCRIPTOR, *PDESCRIPTOR;
+
+
+#define DEFAULT_NULL_PACKET_COUNT 180000 //20060828.1 Add. 180 seconds
+
+#define MAX_TXVGA_EEPROM 9 //How many word(u16) of EEPROM will be used for TxVGA
+#define MAX_RF_PARAMETER 32
+
+typedef struct _TXVGA_FOR_50 {
+ u8 ChanNo;
+ u8 TxVgaValue;
+} TXVGA_FOR_50;
+
+
+//=====================================================================
+// Device related include
+//=====================================================================
+
+#include "linux/wbusb_s.h"
+#include "linux/wb35reg_s.h"
+#include "linux/wb35tx_s.h"
+#include "linux/wb35rx_s.h"
+
+
+// For Hal using ==================================================================
+typedef struct _HW_DATA_T
+{
+ // For compatible with 33
+ u32 revision;
+ u32 BB3c_cal; // The value for Tx calibration comes from EEPROM
+ u32 BB54_cal; // The value for Rx calibration comes from EEPROM
+
+
+ // For surprise remove
+ u32 SurpriseRemove; // 0: Normal 1: Surprise remove
+ u8 InitialResource;
+ u8 IsKeyPreSet;
+ u8 CalOneTime; // 20060630.1
+
+ u8 VCO_trim;
+
+ // For Fix 1'st DMA bug
+ u32 FragCount;
+ u32 DMAFix; //V1_DMA_FIX The variable can be removed if driver want to save mem space for V2.
+
+ //=======================================================================================
+ // For USB driver, hal need more variables. Due to
+ // 1. NDIS-WDM operation
+ // 2. The SME, MLME and OLD MDS need Adapter structure, but the driver under HAL doesn't
+ // have that parameter when receiving and indicating packet.
+ // The MDS must input the Adapter pointer as the second parameter of hal_init_hardware.
+ // The function usage is different than PCI driver.
+ //=======================================================================================
+ void* Adapter;
+
+ //===============================================
+ // Definition for MAC address
+ //===============================================
+ u8 PermanentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are stored in EEPROM. + 2 to 8-byte alignment
+ u8 CurrentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are in used. + 2 to 8-byte alignment
+
+ //=====================================================================
+ // Definition for 802.11
+ //=====================================================================
+ PUCHAR bssid_pointer; // Used by hal_get_bssid for return value
+ u8 bssid[8];// Only 6 byte will be used. 8 byte is required for read buffer
+ u8 ssid[32];// maximum ssid length is 32 byte
+
+ u16 AID;
+ u8 ssid_length;
+ u8 Channel;
+
+ u16 ListenInterval;
+ u16 CapabilityInformation;
+
+ u16 BeaconPeriod;
+ u16 ProbeDelay;
+
+ u8 bss_type;// 0: IBSS_NET or 1:ESS_NET
+ u8 preamble;// 0: short preamble, 1: long preamble
+ u8 slot_time_select;// 9 or 20 value
+ u8 phy_type;// Phy select
+
+ u32 phy_para[MAX_RF_PARAMETER];
+ u32 phy_number;
+
+ u32 CurrentRadioSw; // 20060320.2 0:On 1:Off
+ u32 CurrentRadioHw; // 20060825 0:On 1:Off
+
+ PUCHAR power_save_point; // Used by hal_get_power_save_mode for return value
+ u8 cwmin;
+ u8 desired_power_save;
+ u8 dtim;// Is running dtim
+ u8 mapping_key_replace_index;//In Key table, the next index be replaced 931130.4.r
+
+ u16 MaxReceiveLifeTime;
+ u16 FragmentThreshold;
+ u16 FragmentThreshold_tmp;
+ u16 cwmax;
+
+ u8 Key_slot[MAX_KEY_TABLE][8]; //Ownership record for key slot. For Alignment
+ u32 Key_content[MAX_KEY_TABLE][12]; // 10DW for each entry + 2 for burst command( Off and On valid bit)
+ u8 CurrentDefaultKeyIndex;
+ u32 CurrentDefaultKeyLength;
+
+ //========================================================================
+ // Variable for each module
+ //========================================================================
+ WBUSB WbUsb; // Need WbUsb.h
+ WB35REG Wb35Reg; // Need Wb35Reg.h
+ WB35TX Wb35Tx; // Need Wb35Tx.h
+ WB35RX Wb35Rx; // Need Wb35Rx.h
+
+ OS_TIMER LEDTimer;// For LED
+
+ u32 LEDpoint;// For LED
+
+ u32 dto_tx_retry_count; // LA20040210_DTO kevin
+ u32 dto_tx_frag_count; // LA20040210_DTO kevin
+ u32 rx_ok_count[13]; // index=0: total rx ok
+ //u32 rx_ok_bytes[13]; // index=0, total rx ok bytes
+ u32 rx_err_count[13]; // index=0: total rx err
+
+ //for Tx debug
+ u32 tx_TBTT_start_count;
+ u32 tx_ETR_count;
+ u32 tx_WepOn_false_count;
+ u32 tx_Null_key_count;
+ u32 tx_retry_count[8];
+
+ u8 PowerIndexFromEEPROM; // For 2412MHz
+ u8 power_index;
+ u8 IsWaitJoinComplete; // TRUE: set join request
+ u8 band;
+
+ u16 SoftwareSet;
+ u16 Reserved_s;
+
+ u32 IsInitOK; // 0: Driver starting 1: Driver init OK
+
+ // For Phy calibration
+ s32 iq_rsdl_gain_tx_d2;
+ s32 iq_rsdl_phase_tx_d2;
+ u32 txvga_setting_for_cal; // 20060703.1 Add
+
+ u8 TxVgaSettingInEEPROM[ (((MAX_TXVGA_EEPROM*2)+3) & ~0x03) ]; // 20060621 For backup EEPROM value
+ u8 TxVgaFor24[16]; // Max is 14, 2 for alignment
+ TXVGA_FOR_50 TxVgaFor50[36]; // 35 channels in 5G. 35x2 = 70 byte. 2 for alignments
+
+ u16 Scan_Interval;
+ u16 RESERVED6;
+
+ // LED control
+ u32 LED_control;
+ // LED_control 4 byte: Gray_Led_1[3] Gray_Led_0[2] Led[1] Led[0]
+ // Gray_Led
+ // For Led gray setting
+ // Led
+ // 0: normal control, LED behavior will decide by EEPROM setting
+ // 1: Turn off specific LED
+ // 2: Always on specific LED
+ // 3: slow blinking specific LED
+ // 4: fast blinking specific LED
+ // 5: WPS led control is set. Led0 is Red, Led1 id Green
+ // Led[1] is parameter for WPS LED mode
+ // // 1:InProgress 2: Error 3: Session overlap 4: Success 20061108 control
+
+ u32 LED_LinkOn; //Turn LED on control
+ u32 LED_Scanning; // Let LED in scan process control
+ u32 LED_Blinking; // Temp variable for shining
+ u32 RxByteCountLast;
+ u32 TxByteCountLast;
+
+ s32 SurpriseRemoveCount;
+
+ // For global timer
+ u32 time_count;//TICK_TIME_100ms 1 = 100ms
+
+ // For error recover
+ u32 HwStop;
+
+ // 20060828.1 for avoid AP disconnect
+ u32 NullPacketCount;
+
+} hw_data_t, *phw_data_t;
+
+// The mapping of Rx and Tx descriptor field
+typedef struct _HAL_RATE
+{
+ // DSSS
+ u32 RESERVED_0;
+ u32 NumRate2MS;
+ u32 NumRate55MS;
+ u32 NumRate11MS;
+
+ u32 RESERVED_1[4];
+
+ u32 NumRate1M;
+ u32 NumRate2ML;
+ u32 NumRate55ML;
+ u32 NumRate11ML;
+
+ u32 RESERVED_2[4];
+
+ // OFDM
+ u32 NumRate6M;
+ u32 NumRate9M;
+ u32 NumRate12M;
+ u32 NumRate18M;
+ u32 NumRate24M;
+ u32 NumRate36M;
+ u32 NumRate48M;
+ u32 NumRate54M;
+} HAL_RATE, *PHAL_RATE;
+
+
diff --git a/drivers/staging/winbond/wblinux.c b/drivers/staging/winbond/wblinux.c
new file mode 100644
index 00000000000..2eade5a47b1
--- /dev/null
+++ b/drivers/staging/winbond/wblinux.c
@@ -0,0 +1,277 @@
+//============================================================================
+// Copyright (c) 1996-2005 Winbond Electronic Corporation
+//
+// Module Name:
+// wblinux.c
+//
+// Abstract:
+// Linux releated routines
+//
+//============================================================================
+#include "os_common.h"
+
+u32
+WBLINUX_MemoryAlloc(void* *VirtualAddress, u32 Length)
+{
+ *VirtualAddress = kzalloc( Length, GFP_ATOMIC ); //GFP_KERNEL is not suitable
+
+ if (*VirtualAddress == NULL)
+ return 0;
+ return 1;
+}
+
+s32
+EncapAtomicInc(PADAPTER Adapter, void* pAtomic)
+{
+ PWBLINUX pWbLinux = &Adapter->WbLinux;
+ u32 ltmp;
+ PULONG pltmp = (PULONG)pAtomic;
+ OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
+ (*pltmp)++;
+ ltmp = (*pltmp);
+ OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
+ return ltmp;
+}
+
+s32
+EncapAtomicDec(PADAPTER Adapter, void* pAtomic)
+{
+ PWBLINUX pWbLinux = &Adapter->WbLinux;
+ u32 ltmp;
+ PULONG pltmp = (PULONG)pAtomic;
+ OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
+ (*pltmp)--;
+ ltmp = (*pltmp);
+ OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
+ return ltmp;
+}
+
+unsigned char
+WBLINUX_Initial(PADAPTER Adapter)
+{
+ PWBLINUX pWbLinux = &Adapter->WbLinux;
+
+ OS_SPIN_LOCK_ALLOCATE( &pWbLinux->SpinLock );
+ OS_SPIN_LOCK_ALLOCATE( &pWbLinux->AtomicSpinLock );
+ return TRUE;
+}
+
+void
+WBLinux_ReceivePacket(PADAPTER Adapter, PRXLAYER1 pRxLayer1)
+{
+ BUG();
+}
+
+
+void
+WBLINUX_GetNextPacket(PADAPTER Adapter, PDESCRIPTOR pDes)
+{
+ BUG();
+}
+
+void
+WBLINUX_GetNextPacketCompleted(PADAPTER Adapter, PDESCRIPTOR pDes)
+{
+ BUG();
+}
+
+void
+WBLINUX_Destroy(PADAPTER Adapter)
+{
+ WBLINUX_stop( Adapter );
+ OS_SPIN_LOCK_FREE( &pWbNdis->SpinLock );
+#ifdef _PE_USB_INI_DUMP_
+ WBDEBUG(("[w35und] unregister_netdev!\n"));
+#endif
+}
+
+void
+WBLINUX_stop( PADAPTER Adapter )
+{
+ PWBLINUX pWbLinux = &Adapter->WbLinux;
+ struct sk_buff *pSkb;
+
+ if (OS_ATOMIC_INC( Adapter, &pWbLinux->ThreadCount ) == 1) {
+ // Shutdown module immediately
+ pWbLinux->shutdown = 1;
+
+ while (pWbLinux->skb_array[ pWbLinux->skb_GetIndex ]) {
+ // Trying to free the un-sending packet
+ pSkb = pWbLinux->skb_array[ pWbLinux->skb_GetIndex ];
+ pWbLinux->skb_array[ pWbLinux->skb_GetIndex ] = NULL;
+ if( in_irq() )
+ dev_kfree_skb_irq( pSkb );
+ else
+ dev_kfree_skb( pSkb );
+
+ pWbLinux->skb_GetIndex++;
+ pWbLinux->skb_GetIndex %= WBLINUX_PACKET_ARRAY_SIZE;
+ }
+
+#ifdef _PE_STATE_DUMP_
+ WBDEBUG(( "[w35und] SKB_RELEASE OK\n" ));
+#endif
+ }
+
+ OS_ATOMIC_DEC( Adapter, &pWbLinux->ThreadCount );
+}
+
+void
+WbWlanHalt( PADAPTER Adapter )
+{
+ //---------------------
+ Adapter->sLocalPara.ShutDowned = TRUE;
+
+ Mds_Destroy( Adapter );
+
+ // Turn off Rx and Tx hardware ability
+ hal_stop( &Adapter->sHwData );
+#ifdef _PE_USB_INI_DUMP_
+ WBDEBUG(("[w35und] Hal_stop O.K.\n"));
+#endif
+ OS_SLEEP(100000);// Waiting Irp completed
+
+ // Destroy the NDIS module
+ WBLINUX_Destroy( Adapter );
+
+ // Halt the HAL
+ hal_halt(&Adapter->sHwData, NULL);
+}
+
+unsigned char
+WbWLanInitialize(PADAPTER Adapter)
+{
+ phw_data_t pHwData;
+ PUCHAR pMacAddr, pMacAddr2;
+ u32 InitStep = 0;
+ u8 EEPROM_region;
+ u8 HwRadioOff;
+
+ do {
+ //
+ // Setting default value for Linux
+ //
+ Adapter->sLocalPara.region_INF = REGION_AUTO;
+ Adapter->sLocalPara.TxRateMode = RATE_AUTO;
+ psLOCAL->bMacOperationMode = MODE_802_11_BG; // B/G mode
+ Adapter->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
+ Adapter->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
+ hal_set_phy_type( &Adapter->sHwData, RF_WB_242_1 );
+ Adapter->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
+ psLOCAL->bPreambleMode = AUTO_MODE;
+ Adapter->sLocalPara.RadioOffStatus.boSwRadioOff = FALSE;
+ pHwData = &Adapter->sHwData;
+ hal_set_phy_type( pHwData, RF_DECIDE_BY_INF );
+
+ //
+ // Initial each module and variable
+ //
+ if (!WBLINUX_Initial(Adapter)) {
+#ifdef _PE_USB_INI_DUMP_
+ WBDEBUG(("[w35und]WBNDIS initialization failed\n"));
+#endif
+ break;
+ }
+
+ // Initial Software variable
+ Adapter->sLocalPara.ShutDowned = FALSE;
+
+ //added by ws for wep key error detection
+ Adapter->sLocalPara.bWepKeyError= FALSE;
+ Adapter->sLocalPara.bToSelfPacketReceived = FALSE;
+ Adapter->sLocalPara.WepKeyDetectTimerCount= 2 * 100; /// 2 seconds
+
+ // Initial USB hal
+ InitStep = 1;
+ pHwData = &Adapter->sHwData;
+ if (!hal_init_hardware(pHwData, Adapter))
+ break;
+
+ EEPROM_region = hal_get_region_from_EEPROM( pHwData );
+ if (EEPROM_region != REGION_AUTO)
+ psLOCAL->region = EEPROM_region;
+ else {
+ if (psLOCAL->region_INF != REGION_AUTO)
+ psLOCAL->region = psLOCAL->region_INF;
+ else
+ psLOCAL->region = REGION_USA; //default setting
+ }
+
+ // Get Software setting flag from hal
+ Adapter->sLocalPara.boAntennaDiversity = FALSE;
+ if (hal_software_set(pHwData) & 0x00000001)
+ Adapter->sLocalPara.boAntennaDiversity = TRUE;
+
+ //
+ // For TS module
+ //
+ InitStep = 2;
+
+ // For MDS module
+ InitStep = 3;
+ Mds_initial(Adapter);
+
+ //=======================================
+ // Initialize the SME, SCAN, MLME, ROAM
+ //=======================================
+ InitStep = 4;
+ InitStep = 5;
+ InitStep = 6;
+
+ // If no user-defined address in the registry, use the addresss "burned" on the NIC instead.
+ pMacAddr = Adapter->sLocalPara.ThisMacAddress;
+ pMacAddr2 = Adapter->sLocalPara.PermanentAddress;
+ hal_get_permanent_address( pHwData, Adapter->sLocalPara.PermanentAddress );// Reading ethernet address from EEPROM
+ if (OS_MEMORY_COMPARE(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH )) // Is equal
+ {
+ memcpy( pMacAddr, pMacAddr2, MAC_ADDR_LENGTH );
+ } else {
+ // Set the user define MAC address
+ hal_set_ethernet_address( pHwData, Adapter->sLocalPara.ThisMacAddress );
+ }
+
+ //get current antenna
+ psLOCAL->bAntennaNo = hal_get_antenna_number(pHwData);
+#ifdef _PE_STATE_DUMP_
+ WBDEBUG(("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo));
+#endif
+ hal_get_hw_radio_off( pHwData );
+
+ // Waiting for HAL setting OK
+ while (!hal_idle(pHwData))
+ OS_SLEEP(10000);
+
+ MTO_Init(Adapter);
+
+ HwRadioOff = hal_get_hw_radio_off( pHwData );
+ psLOCAL->RadioOffStatus.boHwRadioOff = !!HwRadioOff;
+
+ hal_set_radio_mode( pHwData, (unsigned char)(psLOCAL->RadioOffStatus.boSwRadioOff || psLOCAL->RadioOffStatus.boHwRadioOff) );
+
+ hal_driver_init_OK(pHwData) = 1; // Notify hal that the driver is ready now.
+ //set a tx power for reference.....
+// sme_set_tx_power_level(Adapter, 12); FIXME?
+ return TRUE;
+ }
+ while(FALSE);
+
+ switch (InitStep) {
+ case 5:
+ case 4:
+ case 3: Mds_Destroy( Adapter );
+ case 2:
+ case 1: WBLINUX_Destroy( Adapter );
+ hal_halt( pHwData, NULL );
+ case 0: break;
+ }
+
+ return FALSE;
+}
+
+void WBLINUX_ConnectStatus(PADAPTER Adapter, u32 flag)
+{
+ PWBLINUX pWbLinux = &Adapter->WbLinux;
+
+ pWbLinux->LinkStatus = flag; // OS_DISCONNECTED or OS_CONNECTED
+}
+
diff --git a/drivers/staging/winbond/wblinux_f.h b/drivers/staging/winbond/wblinux_f.h
new file mode 100644
index 00000000000..68240c5fc80
--- /dev/null
+++ b/drivers/staging/winbond/wblinux_f.h
@@ -0,0 +1,23 @@
+//=========================================================================
+// Copyright (c) 1996-2004 Winbond Electronic Corporation
+//
+// wblinux_f.h
+//
+u32 WBLINUX_MemoryAlloc( void* *VirtualAddress, u32 Length );
+s32 EncapAtomicInc( PADAPTER Adapter, void* pAtomic );
+s32 EncapAtomicDec( PADAPTER Adapter, void* pAtomic );
+void WBLinux_ReceivePacket( PADAPTER Adapter, PRXLAYER1 pRxLayer1 );
+unsigned char WBLINUX_Initial( PADAPTER Adapter );
+int wb35_start_xmit(struct sk_buff *skb, struct net_device *netdev );
+void WBLINUX_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
+void WBLINUX_GetNextPacketCompleted( PADAPTER Adapter, PDESCRIPTOR pDes );
+void WBLINUX_stop( PADAPTER Adapter );
+void WBLINUX_Destroy( PADAPTER Adapter );
+void wb35_set_multicast( struct net_device *netdev );
+struct net_device_stats * wb35_netdev_stats( struct net_device *netdev );
+void WBLINUX_stop( PADAPTER Adapter );
+void WbWlanHalt( PADAPTER Adapter );
+void WBLINUX_ConnectStatus( PADAPTER Adapter, u32 flag );
+
+
+
diff --git a/drivers/staging/winbond/wblinux_s.h b/drivers/staging/winbond/wblinux_s.h
new file mode 100644
index 00000000000..97e9167ab83
--- /dev/null
+++ b/drivers/staging/winbond/wblinux_s.h
@@ -0,0 +1,45 @@
+//============================================================
+// wblinux_s.h
+//
+#define OS_MEMORY_ALLOC( _V, _S ) WBLINUX_MemoryAlloc( _V, _S )
+#define OS_LINK_STATUS (Adapter->WbLinux.LinkStatus == OS_CONNECTED)
+#define OS_SET_SHUTDOWN( _A ) _A->WbLinux.shutdown=1
+#define OS_SET_RESUME( _A ) _A->WbLinux.shutdown=0
+#define OS_CONNECT_STATUS_INDICATE( _A, _F ) WBLINUX_ConnectStatus( _A, _F )
+#define OS_DISCONNECTED 0
+#define OS_CONNECTED 1
+#define OS_STOP( _A ) WBLINUX_stop( _A )
+
+#define OS_CURRENT_RX_BYTE( _A ) _A->WbLinux.RxByteCount
+#define OS_CURRENT_TX_BYTE( _A ) _A->WbLinux.TxByteCount
+#define OS_EVENT_INDICATE( _A, _B, _F )
+#define OS_PMKID_STATUS_EVENT( _A )
+#define OS_RECEIVE_PACKET_INDICATE( _A, _D ) WBLinux_ReceivePacket( _A, _D )
+#define OS_RECEIVE_802_1X_PACKET_INDICATE( _A, _D ) EAP_ReceivePacket( _A, _D )
+#define OS_GET_PACKET( _A, _D ) WBLINUX_GetNextPacket( _A, _D )
+#define OS_GET_PACKET_COMPLETE( _A, _D ) WBLINUX_GetNextPacketCompleted( _A, _D )
+#define OS_SEND_RESULT( _A, _ID, _R )
+
+#define WBLINUX_PACKET_ARRAY_SIZE (ETHERNET_TX_DESCRIPTORS*4)
+
+typedef struct _WBLINUX
+{
+ OS_SPIN_LOCK AtomicSpinLock;
+ OS_SPIN_LOCK SpinLock;
+ u32 shutdown;
+
+ OS_ATOMIC ThreadCount;
+
+ u32 LinkStatus; // OS_DISCONNECTED or OS_CONNECTED
+
+ u32 RxByteCount;
+ u32 TxByteCount;
+
+ struct sk_buff *skb_array[ WBLINUX_PACKET_ARRAY_SIZE ];
+ struct sk_buff *packet_return;
+ s32 skb_SetIndex;
+ s32 skb_GetIndex;
+ s32 netif_state_stop; // 1: stop 0: normal
+} WBLINUX, *PWBLINUX;
+
+
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
new file mode 100644
index 00000000000..10b1f0f634d
--- /dev/null
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -0,0 +1,10 @@
+config PRISM2_USB
+ tristate "Prism2.5 USB driver"
+ depends on USB
+ default n
+ ---help---
+ This is the wlan-ng prism 2.5 USB driver for a wide range of
+ old USB wireless devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called prism2_usb.
diff --git a/drivers/staging/wlan-ng/Makefile b/drivers/staging/wlan-ng/Makefile
new file mode 100644
index 00000000000..777b5111b3d
--- /dev/null
+++ b/drivers/staging/wlan-ng/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_PRISM2_USB) += prism2_usb.o
+obj-$(CONFIG_PRISM2_USB) += p80211.o
+
+p80211-objs := p80211mod.o \
+ p80211conv.o \
+ p80211req.o \
+ p80211wep.o \
+ p80211wext.o \
+ p80211netdev.o
diff --git a/drivers/staging/wlan-ng/README b/drivers/staging/wlan-ng/README
new file mode 100644
index 00000000000..f50e4eb6c27
--- /dev/null
+++ b/drivers/staging/wlan-ng/README
@@ -0,0 +1,8 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse warnings
+ - Lindent cleanups
+ - move to use the in-kernel wireless stack
+ - possible enable the pcmcia and pci portions of the driver
+
+Please send all patches to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/wlan-ng/hfa384x.c b/drivers/staging/wlan-ng/hfa384x.c
new file mode 100644
index 00000000000..04df3fd9c52
--- /dev/null
+++ b/drivers/staging/wlan-ng/hfa384x.c
@@ -0,0 +1,4018 @@
+/* src/prism2/driver/hfa384x.c
+*
+* Implements the functions of the Intersil hfa384x MAC
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file implements functions that correspond to the prism2/hfa384x
+* 802.11 MAC hardware and firmware host interface.
+*
+* The functions can be considered to represent several levels of
+* abstraction. The lowest level functions are simply C-callable wrappers
+* around the register accesses. The next higher level represents C-callable
+* prism2 API functions that match the Intersil documentation as closely
+* as is reasonable. The next higher layer implements common sequences
+* of invokations of the API layer (e.g. write to bap, followed by cmd).
+*
+* Common sequences:
+* hfa384x_drvr_xxx Highest level abstractions provided by the
+* hfa384x code. They are driver defined wrappers
+* for common sequences. These functions generally
+* use the services of the lower levels.
+*
+* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These
+* functions are wrappers for the RID get/set
+* sequence. They call copy_[to|from]_bap() and
+* cmd_access(). These functions operate on the
+* RIDs and buffers without validation. The caller
+* is responsible for that.
+*
+* API wrapper functions:
+* hfa384x_cmd_xxx functions that provide access to the f/w commands.
+* The function arguments correspond to each command
+* argument, even command arguments that get packed
+* into single registers. These functions _just_
+* issue the command by setting the cmd/parm regs
+* & reading the status/resp regs. Additional
+* activities required to fully use a command
+* (read/write from/to bap, get/set int status etc.)
+* are implemented separately. Think of these as
+* C-callable prism2 commands.
+*
+* Lowest Layer Functions:
+* hfa384x_docmd_xxx These functions implement the sequence required
+* to issue any prism2 command. Primarily used by the
+* hfa384x_cmd_xxx functions.
+*
+* hfa384x_bap_xxx BAP read/write access functions.
+* Note: we usually use BAP0 for non-interrupt context
+* and BAP1 for interrupt context.
+*
+* hfa384x_dl_xxx download related functions.
+*
+* Driver State Issues:
+* Note that there are two pairs of functions that manage the
+* 'initialized' and 'running' states of the hw/MAC combo. The four
+* functions are create(), destroy(), start(), and stop(). create()
+* sets up the data structures required to support the hfa384x_*
+* functions and destroy() cleans them up. The start() function gets
+* the actual hardware running and enables the interrupts. The stop()
+* function shuts the hardware down. The sequence should be:
+* create()
+* .
+* . Self contained test routines can run here, particularly
+* . corereset() and test_hostif().
+* .
+* start()
+* .
+* . Do interesting things w/ the hardware
+* .
+* stop()
+* destroy()
+*
+* Note that destroy() can be called without calling stop() first.
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+
+/* System Includes */
+#define WLAN_DBVAR prism2_debug
+#include "version.h"
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/list.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/tqueue.h>
+#else
+#include <linux/workqueue.h>
+#endif
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )
+#include <pcmcia/version.h>
+#endif
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+#endif
+
+#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#endif
+
+#include "wlan_compat.h"
+
+// XXXX #define CMD_IRQ
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211req.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "hfa384x.h"
+#include "prism2mgmt.h"
+
+/*================================================================*/
+/* Local Constants */
+
+static const UINT16 crc16tab[256] =
+{
+ 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
+ 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
+ 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
+ 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
+ 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
+ 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
+ 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
+ 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
+ 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
+ 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
+ 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
+ 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
+ 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
+ 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
+ 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
+ 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
+ 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
+ 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
+ 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
+ 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
+ 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
+ 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
+ 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
+ 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
+ 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
+ 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
+ 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
+ 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
+ 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
+ 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
+ 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
+ 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
+};
+
+/*================================================================*/
+/* Local Macros */
+
+/*================================================================*/
+/* Local Types */
+
+/*================================================================*/
+/* Local Static Definitions */
+extern int prism2_debug;
+
+/*================================================================*/
+/* Local Function Declarations */
+
+static void hfa384x_int_dtim(wlandevice_t *wlandev);
+static void hfa384x_int_infdrop(wlandevice_t *wlandev);
+
+static void hfa384x_bap_tasklet(unsigned long data);
+
+static void hfa384x_int_info(wlandevice_t *wlandev);
+static void hfa384x_int_txexc(wlandevice_t *wlandev);
+static void hfa384x_int_tx(wlandevice_t *wlandev);
+static void hfa384x_int_rx(wlandevice_t *wlandev);
+
+#ifdef CMD_IRQ
+static void hfa384x_int_cmd(wlandevice_t *wlandev);
+#endif
+static void hfa384x_int_rxmonitor( wlandevice_t *wlandev,
+ UINT16 rxfid, hfa384x_rx_frame_t *rxdesc);
+static void hfa384x_int_alloc(wlandevice_t *wlandev);
+
+static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd);
+
+static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd);
+
+static UINT16
+hfa384x_mkcrc16(UINT8 *p, int len);
+
+int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,
+ void *buf, UINT len, void* buf2, UINT len2,
+ void *buf3, UINT len3, void* buf4, UINT len4);
+
+/*================================================================*/
+/* Function Definitions */
+
+static UINT16
+txfid_queue_empty(hfa384x_t *hw)
+{
+ return (hw->txfid_head == hw->txfid_tail) ? 1 : 0;
+}
+
+static UINT16
+txfid_queue_remove(hfa384x_t *hw)
+{
+ UINT16 result= 0;
+
+ if (txfid_queue_empty(hw)) {
+ WLAN_LOG_DEBUG(3,"queue empty.\n");
+ } else {
+ result = hw->txfid_queue[hw->txfid_head];
+ hw->txfid_head = (hw->txfid_head + 1) % hw->txfid_N;
+ }
+
+ return (UINT16)result;
+}
+
+static INT16
+txfid_queue_add(hfa384x_t *hw, UINT16 val)
+{
+ INT16 result = 0;
+
+ if (hw->txfid_head == ((hw->txfid_tail + 1) % hw->txfid_N)) {
+ result = -1;
+ WLAN_LOG_DEBUG(3,"queue full.\n");
+ } else {
+ hw->txfid_queue[hw->txfid_tail] = val;
+ result = hw->txfid_tail;
+ hw->txfid_tail = (hw->txfid_tail + 1) % hw->txfid_N;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_create
+*
+* Initializes the hfa384x_t data structure for use. Note this
+* does _not_ intialize the actual hardware, just the data structures
+* we use to keep track of its state.
+*
+* Arguments:
+* hw device structure
+* irq device irq number
+* iobase [pcmcia] i/o base address for register access
+* [pci] zero
+* [plx] i/o base address for register access
+* membase [pcmcia] pcmcia_cs "link" pointer
+* [pci] memory base address for register access
+* [plx] memory base address for card attribute memory
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+void hfa384x_create(hfa384x_t *hw, UINT irq, UINT32 iobase,
+ UINT8 __iomem *membase)
+{
+ DBFENTER;
+ memset(hw, 0, sizeof(hfa384x_t));
+ hw->irq = irq;
+ hw->iobase = iobase;
+ hw->membase = membase;
+ spin_lock_init(&(hw->cmdlock));
+
+ /* BAP setup */
+ spin_lock_init(&(hw->baplock));
+ tasklet_init(&hw->bap_tasklet,
+ hfa384x_bap_tasklet,
+ (unsigned long) hw);
+
+ init_waitqueue_head(&hw->cmdq);
+ sema_init(&hw->infofid_sem, 1);
+
+ hw->txfid_head = 0;
+ hw->txfid_tail = 0;
+ hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX;
+ memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue));
+
+ hw->isram16 = 1;
+
+ /* Init the auth queue head */
+ skb_queue_head_init(&hw->authq);
+
+ INIT_WORK2(&hw->link_bh, prism2sta_processing_defer);
+
+ INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer);
+
+ init_timer(&hw->commsqual_timer);
+ hw->commsqual_timer.data = (unsigned long) hw;
+ hw->commsqual_timer.function = prism2sta_commsqual_timer;
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+ hw->state = HFA384x_STATE_INIT;
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_destroy
+*
+* Partner to hfa384x_create(). This function cleans up the hw
+* structure so that it can be freed by the caller using a simple
+* kfree. Currently, this function is just a placeholder. If, at some
+* point in the future, an hw in the 'shutdown' state requires a 'deep'
+* kfree, this is where it should be done. Note that if this function
+* is called on a _running_ hw structure, the drvr_stop() function is
+* called.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* nothing, this function is not allowed to fail.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+void
+hfa384x_destroy( hfa384x_t *hw)
+{
+ struct sk_buff *skb;
+
+ DBFENTER;
+
+ if ( hw->state == HFA384x_STATE_RUNNING ) {
+ hfa384x_drvr_stop(hw);
+ }
+ hw->state = HFA384x_STATE_PREINIT;
+
+ if (hw->scanresults) {
+ kfree(hw->scanresults);
+ hw->scanresults = NULL;
+ }
+
+ /* Now to clean out the auth queue */
+ while ( (skb = skb_dequeue(&hw->authq)) ) {
+ dev_kfree_skb(skb);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_getconfig
+*
+* Performs the sequence necessary to read a config/info item.
+*
+* Arguments:
+* hw device structure
+* rid config/info record id (host order)
+* buf host side record buffer. Upon return it will
+* contain the body portion of the record (minus the
+* RID and len).
+* len buffer length (in bytes, should match record length)
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+* -ENODATA length mismatch between argument and retrieved
+* record.
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ DBFENTER;
+
+ result = hfa384x_cmd_access( hw, 0, rid, buf, len);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_setconfig
+*
+* Performs the sequence necessary to write a config/info item.
+*
+* Arguments:
+* hw device structure
+* rid config/info record id (in host order)
+* buf host side record buffer
+* len buffer length (in bytes)
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ DBFENTER;
+
+ result = hfa384x_cmd_access( hw, 1, rid, buf, len);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_readpda
+*
+* Performs the sequence to read the PDA space. Note there is no
+* drvr_writepda() function. Writing a PDA is
+* generally implemented by a calling component via calls to
+* cmd_download and writing to the flash download buffer via the
+* aux regs.
+*
+* Arguments:
+* hw device structure
+* buf buffer to store PDA in
+* len buffer length
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+* -ETIMEOUT timout waiting for the cmd regs to become
+* available, or waiting for the control reg
+* to indicate the Aux port is enabled.
+* -ENODATA the buffer does NOT contain a valid PDA.
+* Either the card PDA is bad, or the auxdata
+* reads are giving us garbage.
+
+*
+* Side effects:
+*
+* Call context:
+* process thread or non-card interrupt.
+----------------------------------------------------------------*/
+int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len)
+{
+ int result = 0;
+ UINT16 *pda = buf;
+ int pdaok = 0;
+ int morepdrs = 1;
+ int currpdr = 0; /* word offset of the current pdr */
+ int i;
+ UINT16 pdrlen; /* pdr length in bytes, host order */
+ UINT16 pdrcode; /* pdr code, host order */
+ UINT16 crc;
+ UINT16 pdacrc;
+ struct pdaloc {
+ UINT32 cardaddr;
+ UINT16 auxctl;
+ } pdaloc[] =
+ {
+ { HFA3842_PDA_BASE, HFA384x_AUX_CTL_NV},
+ { HFA3842_PDA_BASE, HFA384x_AUX_CTL_EXTDS},
+ { HFA3841_PDA_BASE, HFA384x_AUX_CTL_NV},
+ { HFA3841_PDA_BASE, HFA384x_AUX_CTL_EXTDS},
+ { HFA3841_PDA_BOGUS_BASE, HFA384x_AUX_CTL_NV}
+ };
+
+ DBFENTER;
+ /* Check for aux available */
+ result = hfa384x_cmd_aux_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,"aux_enable() failed. result=%d\n", result);
+ goto failed;
+ }
+
+ /* Read the pda from each known address. */
+ for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) {
+ WLAN_LOG_DEBUG( 3, "Checking PDA@(0x%08x,%s)\n",
+ pdaloc[i].cardaddr,
+ pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ?
+ "CTL_NV" : "CTL_EXTDS");
+
+ /* Copy bufsize bytes from our current pdaloc */
+ hfa384x_copy_from_aux(hw,
+ pdaloc[i].cardaddr,
+ pdaloc[i].auxctl,
+ buf,
+ len);
+
+ /* Test for garbage */
+ /* Traverse the PDR list Looking for PDA-END */
+ pdaok = 1; /* intially assume good */
+ morepdrs = 1;
+ currpdr = 0;
+ while ( pdaok && morepdrs ) {
+ pdrlen = hfa384x2host_16(pda[currpdr]) * 2;
+ pdrcode = hfa384x2host_16(pda[currpdr+1]);
+
+ /* Test for completion at END record */
+ if ( pdrcode == HFA384x_PDR_END_OF_PDA ) {
+ if ( pdrlen == 4 ) {
+ morepdrs = 0;
+ /* Calculate CRC-16 and compare to PDA
+ * value. Note the addition of 2 words
+ * for ENDREC.len and ENDREC.code
+ * fields.
+ */
+ crc = hfa384x_mkcrc16( (UINT8*)pda,
+ (currpdr + 2) * sizeof(UINT16));
+ pdacrc =hfa384x2host_16(pda[currpdr+2]);
+ if ( crc != pdacrc ) {
+ WLAN_LOG_DEBUG(3,
+ "PDA crc failed:"
+ "calc_crc=0x%04x,"
+ "pdr_crc=0x%04x.\n",
+ crc, pdacrc);
+ pdaok = 0;
+ }
+ } else {
+ WLAN_LOG_DEBUG(3,
+ "END record detected w/ "
+ "len(%d) != 2, assuming bad PDA\n",
+ pdrlen);
+ pdaok = 0;
+
+ }
+ break;
+ }
+
+ /* Test the record length */
+ if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) {
+ WLAN_LOG_DEBUG(3,
+ "pdrlen for address #%d "
+ "at %#x:%#x:%d\n",
+ i, pdaloc[i].cardaddr,
+ pdaloc[i].auxctl, pdrlen);
+ WLAN_LOG_DEBUG(3,"pdrlen invalid=%d\n",
+ pdrlen);
+ pdaok = 0;
+ break;
+ }
+
+ /* Move to the next pdr */
+ if ( morepdrs ) {
+ /* note the access to pda[], we need words */
+ currpdr += hfa384x2host_16(pda[currpdr]) + 1;
+ if (currpdr*sizeof(UINT16) > len) {
+ WLAN_LOG_DEBUG(3,
+ "Didn't find PDA_END in buffer, "
+ "trying next location.\n");
+ pdaok = 0;
+ break;
+ }
+ }
+ }
+ if ( pdaok ) {
+ WLAN_LOG_INFO(
+ "PDA Read from 0x%08x in %s space.\n",
+ pdaloc[i].cardaddr,
+ pdaloc[i].auxctl == 0 ? "EXTDS" :
+ pdaloc[i].auxctl == 1 ? "NV" :
+ pdaloc[i].auxctl == 2 ? "PHY" :
+ pdaloc[i].auxctl == 3 ? "ICSRAM" :
+ "<bogus auxctl>");
+ break;
+ }
+ }
+ result = pdaok ? 0 : -ENODATA;
+
+ if ( result ) {
+ WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n");
+ }
+
+ hfa384x_cmd_aux_disable(hw);
+failed:
+ DBFEXIT;
+ return result;
+}
+
+
+
+/*----------------------------------------------------------------
+* mkpda_crc
+*
+* Calculates the CRC16 for the given PDA and inserts the value
+* into the end record.
+*
+* Arguments:
+* pda ptr to the PDA data structure.
+*
+* Returns:
+* 0 - success
+* ~0 - failure (probably an errno)
+----------------------------------------------------------------*/
+static UINT16
+hfa384x_mkcrc16(UINT8 *p, int len)
+{
+ UINT16 crc = 0;
+ UINT8 *lim = p + len;
+
+ while (p < lim) {
+ crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++];
+ }
+
+ return crc;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_enable
+*
+* Begins the ram download state. Checks to see that we're not
+* already in a download state and that a port isn't enabled.
+* Sets the download state and calls cmd_download with the
+* ENABLE_VOLATILE subcommand and the exeaddr argument.
+*
+* Arguments:
+* hw device structure
+* exeaddr the card execution address that will be
+* jumped to when ramdl_disable() is called
+* (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr)
+{
+ int result = 0;
+ UINT16 lowaddr;
+ UINT16 hiaddr;
+ int i;
+ DBFENTER;
+ /* Check that a port isn't active */
+ for ( i = 0; i < HFA384x_PORTID_MAX; i++) {
+ if ( hw->port_enabled[i] ) {
+ WLAN_LOG_DEBUG(1,"Can't download with a port enabled.\n");
+ result = -EINVAL;
+ goto done;
+ }
+ }
+
+ /* Check that we're not already in a download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) {
+ WLAN_LOG_DEBUG(1,"Download state not disabled.\n");
+ result = -EINVAL;
+ goto done;
+ }
+
+ /* Are we supposed to go into genesis mode? */
+ if (exeaddr == 0x3f0000) {
+ UINT16 initseq[2] = { 0xe100, 0xffa1 };
+ UINT16 readbuf[2];
+ UINT8 hcr = 0x0f; /* Default to x16 SRAM */
+ hw->isram16 = 1;
+
+ WLAN_LOG_DEBUG(1, "Dropping into Genesis mode\n");
+
+ /* Issue card reset and enable aux port */
+ hfa384x_corereset(hw, prism2_reset_holdtime,
+ prism2_reset_settletime, 0);
+ hfa384x_cmd_aux_enable(hw, 1);
+
+ /* Genesis set */
+ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ initseq, sizeof(initseq));
+
+ hfa384x_corereset(hw, prism2_reset_holdtime,
+ prism2_reset_settletime, hcr);
+
+ /* Validate memory config */
+ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ initseq, sizeof(initseq));
+ hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ readbuf, sizeof(initseq));
+ WLAN_HEX_DUMP(3, "readback", readbuf, sizeof(readbuf));
+
+ if (memcmp(initseq, readbuf, sizeof(readbuf))) {
+ hcr = 0x1f; /* x8 SRAM */
+ hw->isram16 = 0;
+
+ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ initseq, sizeof(initseq));
+ hfa384x_corereset(hw, prism2_reset_holdtime,
+ prism2_reset_settletime, hcr);
+
+ hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ initseq, sizeof(initseq));
+ hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS,
+ readbuf, sizeof(initseq));
+ WLAN_HEX_DUMP(2, "readback", readbuf, sizeof(readbuf));
+
+ if (memcmp(initseq, readbuf, sizeof(readbuf))) {
+ WLAN_LOG_ERROR("Genesis mode failed\n");
+ result = -1;
+ goto done;
+ }
+ }
+
+ /* Now we're in genesis mode */
+ hw->dlstate = HFA384x_DLSTATE_GENESIS;
+ goto done;
+ }
+
+ /* Retrieve the buffer loc&size and timeout */
+ if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
+ &(hw->bufinfo), sizeof(hw->bufinfo))) ) {
+ goto done;
+ }
+ hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page);
+ hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset);
+ hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len);
+ if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
+ &(hw->dltimeout))) ) {
+ goto done;
+ }
+ hw->dltimeout = hfa384x2host_16(hw->dltimeout);
+
+ /* Enable the aux port */
+ if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) {
+ WLAN_LOG_DEBUG(1,"Aux enable failed, result=%d.\n", result);
+ goto done;
+ }
+
+ /* Call the download(1,addr) function */
+ lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr);
+ hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr);
+
+ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM,
+ lowaddr, hiaddr, 0);
+ if ( result == 0) {
+ /* Set the download state */
+ hw->dlstate = HFA384x_DLSTATE_RAMENABLED;
+ } else {
+ WLAN_LOG_DEBUG(1,"cmd_download(0x%04x, 0x%04x) failed, result=%d.\n",
+ lowaddr,hiaddr, result);
+ /* Disable the aux port */
+ hfa384x_cmd_aux_disable(hw);
+ }
+
+ done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_disable
+*
+* Ends the ram download state.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_ramdl_disable(hfa384x_t *hw)
+{
+ DBFENTER;
+ /* Check that we're already in the download state */
+ if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) &&
+ ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) {
+ return -EINVAL;
+ }
+
+ if (hw->dlstate == HFA384x_DLSTATE_GENESIS) {
+ hfa384x_corereset(hw, prism2_reset_holdtime,
+ prism2_reset_settletime,
+ hw->isram16 ? 0x07: 0x17);
+ goto done;
+ }
+
+ /* Disable the aux port */
+ hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0);
+
+ done:
+ hw->dlstate = HFA384x_DLSTATE_DISABLED;
+ hfa384x_cmd_aux_disable(hw);
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_write
+*
+* Performs a RAM download of a chunk of data. First checks to see
+* that we're in the RAM download state, then uses the aux functions
+* to 1) copy the data, 2) readback and compare. The download
+* state is unaffected. When all data has been written using
+* this function, call drvr_ramdl_disable() to end the download state
+* and restart the MAC.
+*
+* Arguments:
+* hw device structure
+* daddr Card address to write to. (host order)
+* buf Ptr to data to write.
+* len Length of data (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len)
+{
+ int result = 0;
+ UINT8 *verbuf;
+ DBFENTER;
+ /* Check that we're in the ram download state */
+ if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) &&
+ ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr);
+#if 0
+WLAN_HEX_DUMP(1, "dldata", buf, len);
+#endif
+ /* Copy the data via the aux port */
+ hfa384x_copy_to_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, buf, len);
+
+ /* Create a buffer for the verify */
+ verbuf = kmalloc(len, GFP_KERNEL);
+ if (verbuf == NULL ) return 1;
+
+ /* Read back and compare */
+ hfa384x_copy_from_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, verbuf, len);
+
+ if ( memcmp(buf, verbuf, len) ) {
+ WLAN_LOG_DEBUG(1,"ramdl verify failed!\n");
+ result = -EINVAL;
+ }
+
+ kfree_s(verbuf, len);
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_enable
+*
+* Begins the flash download state. Checks to see that we're not
+* already in a download state and that a port isn't enabled.
+* Sets the download state and retrieves the flash download
+* buffer location, buffer size, and timeout length.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_flashdl_enable(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+
+ DBFENTER;
+ /* Check that a port isn't active */
+ for ( i = 0; i < HFA384x_PORTID_MAX; i++) {
+ if ( hw->port_enabled[i] ) {
+ WLAN_LOG_DEBUG(1,"called when port enabled.\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Check that we're not already in a download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) {
+ return -EINVAL;
+ }
+
+ /* Retrieve the buffer loc&size and timeout */
+ if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
+ &(hw->bufinfo), sizeof(hw->bufinfo))) ) {
+ return result;
+ }
+ hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page);
+ hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset);
+ hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len);
+ if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
+ &(hw->dltimeout))) ) {
+ return result;
+ }
+ hw->dltimeout = hfa384x2host_16(hw->dltimeout);
+
+ /* Enable the aux port */
+ if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) {
+ return result;
+ }
+
+ hw->dlstate = HFA384x_DLSTATE_FLASHENABLED;
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_disable
+*
+* Ends the flash download state. Note that this will cause the MAC
+* firmware to restart.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_flashdl_disable(hfa384x_t *hw)
+{
+ DBFENTER;
+ /* Check that we're already in the download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) {
+ return -EINVAL;
+ }
+
+ /* There isn't much we can do at this point, so I don't */
+ /* bother w/ the return value */
+ hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0);
+ hw->dlstate = HFA384x_DLSTATE_DISABLED;
+
+ /* Disable the aux port */
+ hfa384x_cmd_aux_disable(hw);
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_write
+*
+* Performs a FLASH download of a chunk of data. First checks to see
+* that we're in the FLASH download state, then sets the download
+* mode, uses the aux functions to 1) copy the data to the flash
+* buffer, 2) sets the download 'write flash' mode, 3) readback and
+* compare. Lather rinse, repeat as many times an necessary to get
+* all the given data into flash.
+* When all data has been written using this function (possibly
+* repeatedly), call drvr_flashdl_disable() to end the download state
+* and restart the MAC.
+*
+* Arguments:
+* hw device structure
+* daddr Card address to write to. (host order)
+* buf Ptr to data to write.
+* len Length of data (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len)
+{
+ int result = 0;
+ UINT8 *verbuf;
+ UINT32 dlbufaddr;
+ UINT32 currlen;
+ UINT32 currdaddr;
+ UINT16 destlo;
+ UINT16 desthi;
+ int nwrites;
+ int i;
+
+ DBFENTER;
+ /* Check that we're in the flash download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr);
+
+ /* Need a flat address for arithmetic */
+ dlbufaddr = HFA384x_ADDR_AUX_MKFLAT(
+ hw->bufinfo.page,
+ hw->bufinfo.offset);
+ verbuf = kmalloc(hw->bufinfo.len, GFP_KERNEL);
+
+#if 0
+WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout);
+#endif
+ /* Figure out how many times to to the flash prog */
+ nwrites = len / hw->bufinfo.len;
+ nwrites += (len % hw->bufinfo.len) ? 1 : 0;
+
+ if ( verbuf == NULL ) {
+ WLAN_LOG_ERROR("Failed to allocate flash verify buffer\n");
+ return 1;
+ }
+ /* For each */
+ for ( i = 0; i < nwrites; i++) {
+ /* Get the dest address and len */
+ currlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ?
+ hw->bufinfo.len :
+ (len - (hw->bufinfo.len * i));
+ currdaddr = daddr + (hw->bufinfo.len * i);
+ destlo = HFA384x_ADDR_CMD_MKOFF(currdaddr);
+ desthi = HFA384x_ADDR_CMD_MKPAGE(currdaddr);
+ WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", currlen, currdaddr);
+#if 0
+WLAN_HEX_DUMP(1, "dldata", buf+(hw->bufinfo.len*i), currlen);
+#endif
+ /* Set the download mode */
+ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV,
+ destlo, desthi, currlen);
+ if ( result ) {
+ WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) "
+ "cmd failed, result=%d. Aborting d/l\n",
+ destlo, desthi, currlen, result);
+ goto exit_proc;
+ }
+ /* copy the data to the flash buffer */
+ hfa384x_copy_to_aux(hw, dlbufaddr, HFA384x_AUX_CTL_EXTDS,
+ buf+(hw->bufinfo.len*i), currlen);
+ /* set the download 'write flash' mode */
+ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NVWRITE, 0,0,0);
+ if ( result ) {
+ WLAN_LOG_ERROR(
+ "download(NVWRITE,lo=%x,hi=%x,len=%x) "
+ "cmd failed, result=%d. Aborting d/l\n",
+ destlo, desthi, currlen, result);
+ goto exit_proc;
+ }
+ /* readback and compare, if fail...bail */
+ hfa384x_copy_from_aux(hw,
+ currdaddr, HFA384x_AUX_CTL_NV,
+ verbuf, currlen);
+
+ if ( memcmp(buf+(hw->bufinfo.len*i), verbuf, currlen) ) {
+ return -EINVAL;
+ }
+ }
+
+exit_proc:
+ /* DOH! This kfree's for you Mark :-) My forehead hurts... */
+ kfree(verbuf);
+
+ /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */
+ /* actually disable programming mode. Remember, that will cause the */
+ /* the firmware to effectively reset itself. */
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_initialize
+*
+* Issues the initialize command and sets the hw->state based
+* on the result.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_initialize(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ /* we don't want to be interrupted during the reset */
+ hfa384x_setreg(hw, 0, HFA384x_INTEN);
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVACK);
+
+ cmd.cmd = HFA384x_CMDCODE_INIT;
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ if ( result == 0 ) {
+ for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) {
+ hw->port_enabled[i] = 0;
+ }
+ }
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_commtallies
+*
+* Send a commtallies inquiry to the MAC. Note that this is an async
+* call that will result in an info frame arriving sometime later.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* zero success.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_commtallies( hfa384x_t *hw )
+{
+ hfa384x_metacmd_t cmd;
+ int result;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMDCODE_INQ;
+ cmd.parm0 = HFA384x_IT_COMMTALLIES;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_enable
+*
+* Issues the enable command to enable communications on one of
+* the MACs 'ports'. Only macport 0 is valid for stations.
+* APs may also enable macports 1-6. Only ports that are currently
+* disabled may be enabled.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+
+ DBFENTER;
+ if ((!hw->isap && macport != 0) ||
+ (hw->isap && !(macport <= HFA384x_PORTID_MAX)) ||
+ (hw->port_enabled[macport]) ){
+ result = -EINVAL;
+ } else {
+ result = hfa384x_cmd_enable(hw, macport);
+ if ( result == 0 ) {
+ hw->port_enabled[macport] = 1;
+ }
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_enable
+*
+* Issues the the enable command to enable communications on one of the
+* MACs 'ports'.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) |
+ HFA384x_CMD_MACPORT_SET(macport);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_disable
+*
+* Issues the disable command to stop communications on one of
+* the MACs 'ports'. Only macport 0 is valid for stations.
+* APs may also disable macports 1-6. Only ports that have been
+* previously enabled may be disabled.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+
+ DBFENTER;
+ if ((!hw->isap && macport != 0) ||
+ (hw->isap && !(macport <= HFA384x_PORTID_MAX)) ||
+ !(hw->port_enabled[macport]) ){
+ result = -EINVAL;
+ } else {
+ result = hfa384x_cmd_disable(hw, macport);
+ if ( result == 0 ) {
+ hw->port_enabled[macport] = 0;
+ }
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_disable
+*
+* Issues the command to disable a port.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) |
+ HFA384x_CMD_MACPORT_SET(macport);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_diagnose
+*
+* Issues the diagnose command to test the: register interface,
+* MAC controller (including loopback), External RAM, Non-volatile
+* memory integrity, and synthesizers. Following execution of this
+* command, MAC/firmware are in the 'initial state'. Therefore,
+* the Initialize command should be issued after successful
+* completion of this command. This function may only be called
+* when the MAC is in the 'communication disabled' state.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+#define DIAG_PATTERNA ((UINT16)0xaaaa)
+#define DIAG_PATTERNB ((UINT16)0x5555)
+
+int hfa384x_cmd_diagnose(hfa384x_t *hw)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DIAG);
+ cmd.parm0 = DIAG_PATTERNA;
+ cmd.parm1 = DIAG_PATTERNB;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_allocate
+*
+* Issues the allocate command instructing the firmware to allocate
+* a 'frame structure buffer' in MAC controller RAM. This command
+* does not provide the result, it only initiates one of the f/w's
+* asynchronous processes to construct the buffer. When the
+* allocation is complete, it will be indicated via the Alloc
+* bit in the EvStat register and the FID identifying the allocated
+* space will be available from the AllocFID register. Some care
+* should be taken when waiting for the Alloc event. If a Tx or
+* Notify command w/ Reclaim has been previously executed, it's
+* possible the first Alloc event after execution of this command
+* will be for the reclaimed buffer and not the one you asked for.
+* This case must be handled in the Alloc event handler.
+*
+* Arguments:
+* hw device structure
+* len allocation length, must be an even value
+* in the range [4-2400]. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ if ( (len % 2) ||
+ len < HFA384x_CMD_ALLOC_LEN_MIN ||
+ len > HFA384x_CMD_ALLOC_LEN_MAX ) {
+ result = -EINVAL;
+ } else {
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC);
+ cmd.parm0 = len;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_transmit
+*
+* Instructs the firmware to transmit a frame previously copied
+* to a given buffer. This function returns immediately, the Tx
+* results are available via the Tx or TxExc events (if the frame
+* control bits are set). The reclaim argument specifies if the
+* FID passed will be used by the f/w tx process or returned for
+* use w/ another transmit command. If reclaim is set, expect an
+* Alloc event signalling the availibility of the FID for reuse.
+*
+* NOTE: hw->cmdlock MUST BE HELD before calling this function!
+*
+* Arguments:
+* hw device structure
+* reclaim [0|1] indicates whether the given FID will
+* be handed back (via Alloc event) for reuse.
+* (host order)
+* qos [0-3] Value to put in the QoS field of the
+* tx command, identifies a queue to place the
+* outgoing frame in.
+* (host order)
+* fid FID of buffer containing the frame that was
+* previously copied to MAC memory via the bap.
+* (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+* hw->resp0 will contain the FID being used by async tx
+* process. If reclaim==0, resp0 will be the same as the fid
+* argument. If reclaim==1, resp0 will be the different and
+* is the value to watch for in the Tx|TxExc to indicate completion
+* of the frame passed in fid.
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX) |
+ HFA384x_CMD_RECL_SET(reclaim) |
+ HFA384x_CMD_QOS_SET(qos);
+ cmd.parm0 = fid;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_clearpersist
+*
+* Instructs the firmware to clear the persistence bit in a given
+* FID. This has the effect of telling the firmware to drop the
+* persistent frame. The FID must be one that was previously used
+* to transmit a PRST frame.
+*
+* Arguments:
+* hw device structure
+* fid FID of the persistent frame (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_CLRPRST);
+ cmd.parm0 = fid;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_notify
+*
+* Sends an info frame to the firmware to alter the behavior
+* of the f/w asynch processes. Can only be called when the MAC
+* is in the enabled state.
+*
+* Arguments:
+* hw device structure
+* reclaim [0|1] indicates whether the given FID will
+* be handed back (via Alloc event) for reuse.
+* (host order)
+* fid FID of buffer containing the frame that was
+* previously copied to MAC memory via the bap.
+* (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+* hw->resp0 will contain the FID being used by async notify
+* process. If reclaim==0, resp0 will be the same as the fid
+* argument. If reclaim==1, resp0 will be the different.
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid,
+ void *buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) |
+ HFA384x_CMD_RECL_SET(reclaim);
+ cmd.parm0 = fid;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+
+ /* Copy the record to FID */
+ result = hfa384x_copy_to_bap(hw, HFA384x_BAP_PROC, hw->infofid, 0, buf, len);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_to_bap(%04x, 0, %d) failed, result=0x%x\n",
+ hw->infofid, len, result);
+ result = -EIO;
+ goto failed;
+ }
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ failed:
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+#if 0
+/*----------------------------------------------------------------
+* hfa384x_cmd_inquiry
+*
+* Requests an info frame from the firmware. The info frame will
+* be delivered asynchronously via the Info event.
+*
+* Arguments:
+* hw device structure
+* fid FID of the info frame requested. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ);
+ cmd.parm0 = fid;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+#endif
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_access
+*
+* Requests that a given record be copied to/from the record
+* buffer. If we're writing from the record buffer, the contents
+* must previously have been written to the record buffer via the
+* bap. If we're reading into the record buffer, the record can
+* be read out of the record buffer after this call.
+*
+* Arguments:
+* hw device structure
+* write [0|1] copy the record buffer to the given
+* configuration record. (host order)
+* rid RID of the record to read/write. (host order)
+* buf host side record buffer. Upon return it will
+* contain the body portion of the record (minus the
+* RID and len).
+* len buffer length (in bytes, should match record length)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid,
+ void* buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+ hfa384x_rec_t rec;
+
+ DBFENTER;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+ /* This should NOT be called in interrupt context! */
+ if (in_irq()) {
+ WLAN_LOG_ERROR("Krap, in Interrupt context!");
+#ifdef WLAN_INCLUDE_DEBUG
+ BUG();
+#endif
+ }
+#endif
+ spin_lock_bh(&hw->cmdlock);
+
+ if (write) {
+ rec.rid = host2hfa384x_16(rid);
+ rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
+ /* write the record */
+ result = hfa384x_copy_to_bap4( hw, HFA384x_BAP_PROC, rid, 0,
+ &rec, sizeof(rec),
+ buf, len,
+ NULL, 0, NULL, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(3,"Failure writing record header+data\n");
+ goto fail;
+ }
+
+ }
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) |
+ HFA384x_CMD_WRITE_SET(write);
+ cmd.parm0 = rid;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+ if ( result ) {
+ WLAN_LOG_ERROR("Call to hfa384x_docmd_wait failed (%d %d)\n",
+ result, cmd.result.resp0);
+ goto fail;
+ }
+
+ if (!write) {
+ result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, 0, &rec, sizeof(rec));
+ if ( result ) {
+ WLAN_LOG_DEBUG(3,"Call to hfa384x_copy_from_bap failed\n");
+ goto fail;
+ }
+
+ /* Validate the record length */
+ if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */
+ WLAN_LOG_DEBUG(1, "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n",
+ rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
+ result = -ENODATA;
+ goto fail;
+ }
+
+ result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, sizeof(rec), buf, len);
+
+ }
+
+ fail:
+ spin_unlock_bh(&hw->cmdlock);
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_monitor
+*
+* Enables the 'monitor mode' of the MAC. Here's the description of
+* monitor mode that I've received thus far:
+*
+* "The "monitor mode" of operation is that the MAC passes all
+* frames for which the PLCP checks are correct. All received
+* MPDUs are passed to the host with MAC Port = 7, with a
+* receive status of good, FCS error, or undecryptable. Passing
+* certain MPDUs is a violation of the 802.11 standard, but useful
+* for a debugging tool." Normal communication is not possible
+* while monitor mode is enabled.
+*
+* Arguments:
+* hw device structure
+* enable a code (0x0b|0x0f) that enables/disables
+* monitor mode. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) |
+ HFA384x_CMD_AINFO_SET(enable);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_download
+*
+* Sets the controls for the MAC controller code/data download
+* process. The arguments set the mode and address associated
+* with a download. Note that the aux registers should be enabled
+* prior to setting one of the download enable modes.
+*
+* Arguments:
+* hw device structure
+* mode 0 - Disable programming and begin code exec
+* 1 - Enable volatile mem programming
+* 2 - Enable non-volatile mem programming
+* 3 - Program non-volatile section from NV download
+* buffer.
+* (host order)
+* lowaddr
+* highaddr For mode 1, sets the high & low order bits of
+* the "destination address". This address will be
+* the execution start address when download is
+* subsequently disabled.
+* For mode 2, sets the high & low order bits of
+* the destination in NV ram.
+* For modes 0 & 3, should be zero. (host order)
+* NOTE: these address args are in CMD format
+* codelen Length of the data to write in mode 2,
+* zero otherwise. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr,
+ UINT16 highaddr, UINT16 codelen)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) |
+ HFA384x_CMD_PROGMODE_SET(mode);
+ cmd.parm0 = lowaddr;
+ cmd.parm1 = highaddr;
+ cmd.parm2 = codelen;
+
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_dl_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_aux_enable
+*
+* Goes through the process of enabling the auxilary port. This
+* is necessary prior to raw reads/writes to card data space.
+* Direct access to the card data space is only used for downloading
+* code and debugging.
+* Note that a call to this function is required before attempting
+* a download.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force)
+{
+ int result = -ETIMEDOUT;
+ unsigned long flags;
+ UINT32 retries_remaining;
+ UINT16 reg;
+ UINT auxen_mirror = hw->auxen;
+
+ DBFENTER;
+
+ /* Check for existing enable */
+ if ( hw->auxen ) {
+ hw->auxen++;
+ return 0;
+ }
+
+ /* acquire the lock */
+ spin_lock_irqsave( &(hw->cmdlock), flags);
+ /* wait for cmd register busy bit to clear */
+ retries_remaining = 100000;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ udelay(10);
+ }
+ while (HFA384x_CMD_ISBUSY(reg) && --retries_remaining);
+ if (retries_remaining != 0) {
+ /* busy bit clear, it's OK to write to ParamX regs */
+ hfa384x_setreg(hw, HFA384x_AUXPW0,
+ HFA384x_PARAM0);
+ hfa384x_setreg(hw, HFA384x_AUXPW1,
+ HFA384x_PARAM1);
+ hfa384x_setreg(hw, HFA384x_AUXPW2,
+ HFA384x_PARAM2);
+
+ /* Set the aux enable in the Control register */
+ hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DOENABLE,
+ HFA384x_CONTROL);
+
+ /* Now wait for completion */
+ retries_remaining = 100000;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_CONTROL);
+ udelay(10);
+ }
+ while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISENABLED) &&
+ --retries_remaining );
+ if (retries_remaining != 0) {
+ result = 0;
+ hw->auxen++;
+ }
+ }
+
+ /* Force it enabled even if the command failed, if told.. */
+ if ((hw->auxen == auxen_mirror) && force)
+ hw->auxen++;
+
+ spin_unlock_irqrestore( &(hw->cmdlock), flags);
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_aux_disable
+*
+* Goes through the process of disabling the auxilary port
+* enabled with aux_enable().
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_cmd_aux_disable(hfa384x_t *hw)
+{
+ int result = -ETIMEDOUT;
+ unsigned long timeout;
+ UINT16 reg = 0;
+
+ DBFENTER;
+
+ /* See if there's more than one enable */
+ if (hw->auxen) hw->auxen--;
+ if (hw->auxen) return 0;
+
+ /* Clear the aux enable in the Control register */
+ hfa384x_setreg(hw, 0, HFA384x_PARAM0);
+ hfa384x_setreg(hw, 0, HFA384x_PARAM1);
+ hfa384x_setreg(hw, 0, HFA384x_PARAM2);
+ hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DODISABLE,
+ HFA384x_CONTROL);
+
+ /* Now wait for completion */
+ timeout = jiffies + 1*HZ;
+ reg = hfa384x_getreg(hw, HFA384x_CONTROL);
+ while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISDISABLED) &&
+ time_before(jiffies,timeout) ){
+ udelay(10);
+ reg = hfa384x_getreg(hw, HFA384x_CONTROL);
+ }
+ if ((reg & (BIT14|BIT15)) == HFA384x_CONTROL_AUX_ISDISABLED ) {
+ result = 0;
+ }
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_low_level
+*
+* Write test commands to the card. Some test commands don't make
+* sense without prior set-up. For example, continous TX isn't very
+* useful until you set the channel. That functionality should be
+*
+* Side effects:
+*
+* Call context:
+* process thread
+* -----------------------------------------------------------------*/
+int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd)
+{
+ int result = 0;
+ DBFENTER;
+
+ /* Do i need a host2hfa... conversion ? */
+#if 0
+ printk(KERN_INFO "%#x %#x %#x %#x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2);
+#endif
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/* TODO: determine if these will ever be needed */
+#if 0
+int hfa384x_cmd_readmif(hfa384x_t *hw)
+{
+ DBFENTER;
+ DBFEXIT;
+ return 0;
+}
+
+
+int hfa384x_cmd_writemif(hfa384x_t *hw)
+{
+ DBFENTER;
+ DBFEXIT;
+ return 0;
+}
+#endif
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_mmi_read
+*
+* Read mmi registers. mmi is intersil-speak for the baseband
+* processor registers.
+*
+* Arguments:
+* hw device structure
+* register The test register to be accessed (must be even #).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+ cmd.cmd = (UINT16) 0x30;
+ cmd.parm0 = (UINT16) addr;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ /* Do i need a host2hfa... conversion ? */
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ *resp = (UINT32) cmd.result.resp0;
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_mmi_write
+*
+* Read mmi registers. mmi is intersil-speak for the baseband
+* processor registers.
+*
+* Arguments:
+* hw device structure
+* addr The test register to be accessed (must be even #).
+* data The data value to write to the register.
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+
+int
+hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+ cmd.cmd = (UINT16) 0x31;
+ cmd.parm0 = (UINT16) addr;
+ cmd.parm1 = (UINT16) data;
+ cmd.parm2 = 0;
+
+ WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08x\n", addr);
+ WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08x\n", data);
+
+ /* Do i need a host2hfa... conversion ? */
+ spin_lock_bh(&hw->cmdlock);
+ result = hfa384x_docmd_wait(hw, &cmd);
+ spin_unlock_bh(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/* TODO: determine if these will ever be needed */
+#if 0
+int hfa384x_cmd_readmif(hfa384x_t *hw)
+{
+ DBFENTER;
+ DBFEXIT;
+ return 0;
+}
+
+
+int hfa384x_cmd_writemif(hfa384x_t *hw)
+{
+ DBFENTER;
+ DBFEXIT;
+ return 0;
+}
+#endif
+
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_from_bap
+*
+* Copies a collection of bytes from the MAC controller memory via
+* one set of BAP registers.
+*
+* Arguments:
+* hw device structure
+* bap [0|1] which BAP to use
+* id FID or RID, destined for the select register (host order)
+* offset An _even_ offset into the buffer for the given
+* FID/RID. We haven't the means to validate this,
+* so be careful. (host order)
+* buf ptr to array of bytes
+* len length of data to transfer in bytes
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - value of offset reg.
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ int result = 0;
+ unsigned long flags = 0;
+ UINT8 *d = (UINT8*)buf;
+ UINT selectreg;
+ UINT offsetreg;
+ UINT datareg;
+ UINT i;
+ UINT16 reg = 0;
+
+ DBFENTER;
+
+ /* Validate bap, offset, buf, and len */
+ if ( (bap > 1) ||
+ (offset > HFA384x_BAP_OFFSET_MAX) ||
+ (offset % 2) ||
+ (buf == NULL) ||
+ (len > HFA384x_BAP_DATALEN_MAX) ){
+ result = -EINVAL;
+ } else {
+ selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0 ;
+ offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0 ;
+ datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0 ;
+
+ /* Obtain lock */
+ spin_lock_irqsave( &(hw->baplock), flags);
+
+ /* Write id to select reg */
+ hfa384x_setreg(hw, id, selectreg);
+ /* Write offset to offset reg */
+ hfa384x_setreg(hw, offset, offsetreg);
+ /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
+ i = 0;
+ do {
+ reg = hfa384x_getreg(hw, offsetreg);
+ if ( i > 0 ) udelay(10);
+ i++;
+ } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg));
+#if (WLAN_HOSTIF != WLAN_PCI)
+ /* Release lock */
+ spin_unlock_irqrestore( &(hw->baplock), flags);
+#endif
+
+ if ( HFA384x_OFFSET_ISBUSY(reg) ){
+ /* If timeout, return -ETIMEDOUT */
+ result = reg;
+ } else if ( HFA384x_OFFSET_ISERR(reg) ){
+ /* If offset[err] == 1, return -EINVAL */
+ result = reg;
+ } else {
+ /* Read even(len) buf contents from data reg */
+ for ( i = 0; i < (len & 0xfffe); i+=2 ) {
+ *(UINT16*)(&(d[i])) =
+ hfa384x_getreg_noswap(hw, datareg);
+ }
+ /* If len odd, handle last byte */
+ if ( len % 2 ){
+ reg = hfa384x_getreg_noswap(hw, datareg);
+ d[len-1] = ((UINT8*)(&reg))[0];
+ }
+ }
+
+ /* According to Intersil errata dated 9/16/02:
+
+ "In PRISM PCI MAC host interface, if both BAPs are concurrently
+ requesing memory access, both will accept the Ack. There is no
+ firmware workaround possible. To prevent BAP access failures or
+ hang conditions the host MUST NOT access both BAPs in sucession
+ unless at least 5us elapses between accesses. The safest choice
+ is to USE ONLY ONE BAP for all data movement operations."
+
+ What this means:
+
+ We have to serialize ALL BAP accesses, and furthermore, add a 5us
+ delay after access if we're using a PCI platform.
+
+ Unfortunately, this means we have to lock out interrupts througout
+ the entire BAP copy.
+
+ It remains to be seen if "BAP access" means "BAP setup" or the more
+ literal definition of "copying data back and forth" I'm erring for
+ the latter, safer definition. -- SLP.
+
+ */
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+ udelay(5);
+ /* Release lock */
+ spin_unlock_irqrestore( &(hw->baplock), flags);
+#endif
+
+ }
+
+ if (result) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n",
+ reg, len, result);
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_to_bap
+*
+* Copies a collection of bytes to the MAC controller memory via
+* one set of BAP registers.
+*
+* Arguments:
+* hw device structure
+* bap [0|1] which BAP to use
+* id FID or RID, destined for the select register (host order)
+* offset An _even_ offset into the buffer for the given
+* FID/RID. We haven't the means to validate this,
+* so be careful. (host order)
+* buf ptr to array of bytes
+* len length of data to transfer (in bytes)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - value of offset reg.
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ return hfa384x_copy_to_bap4(hw, bap, id, offset, buf, len, NULL, 0, NULL, 0, NULL, 0);
+}
+
+int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,
+ void *buf, UINT len1, void* buf2, UINT len2,
+ void *buf3, UINT len3, void *buf4, UINT len4)
+{
+ int result = 0;
+ unsigned long flags = 0;
+ UINT8 *d;
+ UINT selectreg;
+ UINT offsetreg;
+ UINT datareg;
+ UINT i;
+ UINT16 reg;
+
+ DBFENTER;
+
+// printk(KERN_DEBUG "ctb1 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4);
+
+ /* Validate bap, offset, buf, and len */
+ if ( (bap > 1) ||
+ (offset > HFA384x_BAP_OFFSET_MAX) ||
+ (offset % 2) ||
+ (buf == NULL) ||
+ (len1+len2+len3+len4 > HFA384x_BAP_DATALEN_MAX) ){
+ result = -EINVAL;
+ } else {
+ selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0;
+ offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0;
+ datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0;
+ /* Obtain lock */
+ spin_lock_irqsave( &(hw->baplock), flags);
+
+ /* Write id to select reg */
+ hfa384x_setreg(hw, id, selectreg);
+ udelay(10);
+ /* Write offset to offset reg */
+ hfa384x_setreg(hw, offset, offsetreg);
+ /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
+ i = 0;
+ do {
+ reg = hfa384x_getreg(hw, offsetreg);
+ if ( i > 0 ) udelay(10);
+ i++;
+ } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg));
+
+#if (WLAN_HOSTIF != WLAN_PCI)
+ /* Release lock */
+ spin_unlock_irqrestore( &(hw->baplock), flags);
+#endif
+
+ if ( HFA384x_OFFSET_ISBUSY(reg) ){
+ /* If timeout, return reg */
+ result = reg;
+ } else if ( HFA384x_OFFSET_ISERR(reg) ){
+ /* If offset[err] == 1, return reg */
+ result = reg;
+ } else {
+ d = (UINT8*)buf;
+ /* Write even(len1) buf contents to data reg */
+ for ( i = 0; i < (len1 & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw,
+ *(UINT16*)(&(d[i])), datareg);
+ }
+ if (len1 & 1) {
+ UINT16 data;
+ UINT8 *b = (UINT8 *) &data;
+ b[0] = d[len1-1];
+ if (buf2 != NULL) {
+ d = (UINT8*)buf2;
+ b[1] = d[0];
+ len2--;
+ buf2++;
+ }
+ hfa384x_setreg_noswap(hw, data, datareg);
+ }
+ if ((buf2 != NULL) && (len2 > 0)) {
+ /* Write even(len2) buf contents to data reg */
+ d = (UINT8*)buf2;
+ for ( i = 0; i < (len2 & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg);
+ }
+ if (len2 & 1) {
+ UINT16 data;
+ UINT8 *b = (UINT8 *) &data;
+ b[0] = d[len2-1];
+ if (buf3 != NULL) {
+ d = (UINT8*)buf3;
+ b[1] = d[0];
+ len3--;
+ buf3++;
+ }
+ hfa384x_setreg_noswap(hw, data, datareg);
+ }
+ }
+
+ if ((buf3 != NULL) && (len3 > 0)) {
+ /* Write even(len3) buf contents to data reg */
+ d = (UINT8*)buf3;
+ for ( i = 0; i < (len3 & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg);
+ }
+ if (len3 & 1) {
+ UINT16 data;
+ UINT8 *b = (UINT8 *) &data;
+ b[0] = d[len3-1];
+ if (buf4 != NULL) {
+ d = (UINT8*)buf4;
+ b[1] = d[0];
+ len4--;
+ buf4++;
+ }
+ hfa384x_setreg_noswap(hw, data, datareg);
+ }
+ }
+ if ((buf4 != NULL) && (len4 > 0)) {
+ /* Write even(len4) buf contents to data reg */
+ d = (UINT8*)buf4;
+ for ( i = 0; i < (len4 & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg);
+ }
+ if (len4 & 1) {
+ UINT16 data;
+ UINT8 *b = (UINT8 *) &data;
+ b[0] = d[len4-1];
+ b[1] = 0;
+
+ hfa384x_setreg_noswap(hw, data, datareg);
+ }
+ }
+// printk(KERN_DEBUG "ctb2 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4);
+
+ }
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+ udelay(5);
+ /* Release lock */
+ spin_unlock_irqrestore( &(hw->baplock), flags);
+#endif
+
+ }
+
+ if (result)
+ WLAN_LOG_ERROR("copy_to_bap() failed.\n");
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_from_aux
+*
+* Copies a collection of bytes from the controller memory. The
+* Auxiliary port MUST be enabled prior to calling this function.
+* We _might_ be in a download state.
+*
+* Arguments:
+* hw device structure
+* cardaddr address in hfa384x data space to read
+* auxctl address space select
+* buf ptr to destination host buffer
+* len length of data to transfer (in bytes)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* buf contains the data copied
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+void
+hfa384x_copy_from_aux(
+ hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len)
+{
+ UINT16 currpage;
+ UINT16 curroffset;
+ UINT i = 0;
+
+ DBFENTER;
+
+ if ( !(hw->auxen) ) {
+ WLAN_LOG_DEBUG(1,
+ "Attempt to read 0x%04x when aux not enabled\n",
+ cardaddr);
+ return;
+
+ }
+ /* Build appropriate aux page and offset */
+ currpage = HFA384x_AUX_MKPAGE(cardaddr);
+ curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl);
+ hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE);
+ hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET);
+ udelay(5); /* beat */
+
+ /* read the data */
+ while ( i < len) {
+ *((UINT16*)(buf+i)) = hfa384x_getreg_noswap(hw, HFA384x_AUXDATA);
+ i+=2;
+ curroffset+=2;
+ if ( (curroffset&HFA384x_ADDR_AUX_OFF_MASK) >
+ HFA384x_ADDR_AUX_OFF_MAX ) {
+ currpage++;
+ curroffset = 0;
+ curroffset = HFA384x_AUX_MKOFF(curroffset, auxctl);
+ hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE);
+ hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET);
+ udelay(5); /* beat */
+ }
+ }
+ /* Make sure the auxctl bits are clear */
+ hfa384x_setreg(hw, 0, HFA384x_AUXOFFSET);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_to_aux
+*
+* Copies a collection of bytes to the controller memory. The
+* Auxiliary port MUST be enabled prior to calling this function.
+* We _might_ be in a download state.
+*
+* Arguments:
+* hw device structure
+* cardaddr address in hfa384x data space to read
+* auxctl address space select
+* buf ptr to destination host buffer
+* len length of data to transfer (in bytes)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* Controller memory now contains a copy of buf
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+void
+hfa384x_copy_to_aux(
+ hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len)
+{
+ UINT16 currpage;
+ UINT16 curroffset;
+ UINT i = 0;
+
+ DBFENTER;
+
+ if ( !(hw->auxen) ) {
+ WLAN_LOG_DEBUG(1,
+ "Attempt to read 0x%04x when aux not enabled\n",
+ cardaddr);
+ return;
+
+ }
+ /* Build appropriate aux page and offset */
+ currpage = HFA384x_AUX_MKPAGE(cardaddr);
+ curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl);
+ hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE);
+ hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET);
+ udelay(5); /* beat */
+
+ /* write the data */
+ while ( i < len) {
+ hfa384x_setreg_noswap(hw,
+ *((UINT16*)(buf+i)), HFA384x_AUXDATA);
+ i+=2;
+ curroffset+=2;
+ if ( curroffset > HFA384x_ADDR_AUX_OFF_MAX ) {
+ currpage++;
+ curroffset = 0;
+ hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE);
+ hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET);
+ udelay(5); /* beat */
+ }
+ }
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_wait
+*
+* Waits for availability of the Command register, then
+* issues the given command. Then polls the Evstat register
+* waiting for command completion. Timeouts shouldn't be
+* possible since we're preventing overlapping commands and all
+* commands should be cleared and acknowledged.
+*
+* Arguments:
+* wlandev device structure
+* cmd cmd structure. Includes all arguments and result
+* data points. All in host order.
+*
+* Returns:
+* 0 success
+* -ETIMEDOUT timed out waiting for register ready or
+* command completion
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd)
+{
+ int result = -ETIMEDOUT;
+ UINT16 reg = 0;
+ UINT16 counter;
+
+ DBFENTER;
+
+ hw->cmdflag = 0;
+ hw->cmddata = cmd;
+
+ /* wait for the busy bit to clear */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ while ( HFA384x_CMD_ISBUSY(reg) &&
+ (counter < 10)) {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ counter++;
+ udelay(10);
+ }
+
+ if (HFA384x_CMD_ISBUSY(reg)) {
+ WLAN_LOG_ERROR("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
+ goto failed;
+ }
+ if (!HFA384x_CMD_ISBUSY(reg)) {
+ /* busy bit clear, write command */
+ hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0);
+ hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1);
+ hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2);
+ hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD);
+
+#ifdef CMD_IRQ
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0))
+ while (! hw->cmdflag)
+ interruptible_sleep_on(&hw->cmdq);
+#else
+ wait_event_interruptible(hw->cmdq, hw->cmdflag);
+#endif
+ result = HFA384x_STATUS_RESULT_GET(cmd->status);
+#else // CMD_IRQ
+ /* Now wait for completion */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ /* Initialization is the problem. It takes about
+ 100ms. "normal" commands are typically is about
+ 200-400 us (I've never seen less than 200). Longer
+ is better so that we're not hammering the bus. */
+ while ( !HFA384x_EVSTAT_ISCMD(reg) &&
+ (counter < 5000)) {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ counter++;
+ udelay(200);
+ }
+
+ if ( HFA384x_EVSTAT_ISCMD(reg) ) {
+ result = 0;
+ cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS);
+ cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
+ cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
+ cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
+ hfa384x_setreg(hw, HFA384x_EVACK_CMD,
+ HFA384x_EVACK);
+ result = HFA384x_STATUS_RESULT_GET(cmd->result.status);
+ } else {
+ WLAN_LOG_ERROR("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
+ }
+#endif /* CMD_IRQ */
+ }
+
+ failed:
+ hw->cmdflag = 0;
+ hw->cmddata = NULL;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_dl_docmd_wait
+*
+* Waits for availability of the Command register, then
+* issues the given command. Then polls the Evstat register
+* waiting for command completion. Timeouts shouldn't be
+* possible since we're preventing overlapping commands and all
+* commands should be cleared and acknowledged.
+*
+* This routine is only used for downloads. Since it doesn't lock out
+* interrupts the system response is much better.
+*
+* Arguments:
+* wlandev device structure
+* cmd cmd structure. Includes all arguments and result
+* data points. All in host order.
+*
+* Returns:
+* 0 success
+* -ETIMEDOUT timed out waiting for register ready or
+* command completion
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd)
+{
+ int result = -ETIMEDOUT;
+ unsigned long timeout;
+ UINT16 reg = 0;
+
+ DBFENTER;
+ /* wait for the busy bit to clear */
+ timeout = jiffies + 1*HZ;
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ udelay(10);
+ }
+ if (HFA384x_CMD_ISBUSY(reg)) {
+ WLAN_LOG_WARNING("Timed out waiting for cmd register.\n");
+ goto failed;
+ }
+
+ if (!HFA384x_CMD_ISBUSY(reg)) {
+ /* busy bit clear, write command */
+ hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0);
+ hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1);
+ hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2);
+ hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD);
+
+ /* Now wait for completion */
+ if ( (HFA384x_CMD_CMDCODE_GET(cmd->cmd) == HFA384x_CMDCODE_DOWNLD) ) {
+ /* dltimeout is in ms */
+ timeout = (((UINT32)hw->dltimeout) / 1000UL) * HZ;
+ if ( timeout > 0 ) {
+ timeout += jiffies;
+ } else {
+ timeout = jiffies + 1*HZ;
+ }
+ } else {
+ timeout = jiffies + 1*HZ;
+ }
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ while ( !HFA384x_EVSTAT_ISCMD(reg) && time_before(jiffies,timeout) ) {
+ udelay(100);
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ }
+ if ( HFA384x_EVSTAT_ISCMD(reg) ) {
+ result = 0;
+ cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS);
+ cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
+ cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
+ cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
+ hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
+ result = HFA384x_STATUS_RESULT_GET(cmd->result.status);
+ }
+ }
+
+failed:
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_start
+*
+* Issues the MAC initialize command, sets up some data structures,
+* and enables the interrupts. After this function completes, the
+* low-level stuff should be ready for any/all commands.
+*
+* Arguments:
+* hw device structure
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_start(hfa384x_t *hw)
+{
+ int result = 0;
+ UINT16 reg;
+ int i;
+ int j;
+ DBFENTER;
+
+ /* call initialize */
+ result = hfa384x_cmd_initialize(hw);
+ if (result != 0) {
+ WLAN_LOG_ERROR("Initialize command failed.\n");
+ goto failed;
+ }
+
+ /* make sure interrupts are disabled and any layabout events cleared */
+ hfa384x_setreg(hw, 0, HFA384x_INTEN);
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVACK);
+
+ hw->txfid_head = 0;
+ hw->txfid_tail = 0;
+ hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX;
+ memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue));
+
+ /* Allocate tx and notify FIDs */
+ /* First, tx */
+ for ( i = 0; i < HFA384x_DRVR_FIDSTACKLEN_MAX-1; i++) {
+ result = hfa384x_cmd_allocate(hw, HFA384x_DRVR_TXBUF_MAX);
+ if (result != 0) {
+ WLAN_LOG_ERROR("Allocate(tx) command failed.\n");
+ goto failed;
+ }
+ j = 0;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ udelay(10);
+ j++;
+ } while ( !HFA384x_EVSTAT_ISALLOC(reg) && j < 50); /* 50 is timeout */
+ if ( j >= 50 ) {
+ WLAN_LOG_ERROR("Timed out waiting for evalloc(tx).\n");
+ result = -ETIMEDOUT;
+ goto failed;
+ }
+ reg = hfa384x_getreg(hw, HFA384x_ALLOCFID);
+
+ txfid_queue_add(hw, reg);
+
+ WLAN_LOG_DEBUG(4,"hw->txfid_queue[%d]=0x%04x\n",i,reg);
+
+ reg = HFA384x_EVACK_ALLOC_SET(1);
+ hfa384x_setreg(hw, reg, HFA384x_EVACK);
+
+ }
+
+ /* Now, the info frame fid */
+ result = hfa384x_cmd_allocate(hw, HFA384x_INFOFRM_MAXLEN);
+ if (result != 0) {
+ WLAN_LOG_ERROR("Allocate(tx) command failed.\n");
+ goto failed;
+ }
+ i = 0;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ udelay(10);
+ i++;
+ } while ( !HFA384x_EVSTAT_ISALLOC(reg) && i < 50); /* 50 is timeout */
+ if ( i >= 50 ) {
+ WLAN_LOG_ERROR("Timed out waiting for evalloc(info).\n");
+ result = -ETIMEDOUT;
+ goto failed;
+ }
+ hw->infofid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
+ reg = HFA384x_EVACK_ALLOC_SET(1);
+ hfa384x_setreg(hw, reg, HFA384x_EVACK);
+ WLAN_LOG_DEBUG(4,"hw->infofid=0x%04x\n", hw->infofid);
+
+ /* Set swsupport regs to magic # for card presence detection */
+ hfa384x_setreg(hw, HFA384x_DRVR_MAGIC, HFA384x_SWSUPPORT0);
+
+ /* Now enable the interrupts and set the running state */
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVSTAT);
+ hfa384x_events_all(hw);
+
+ hw->state = HFA384x_STATE_RUNNING;
+
+ goto done;
+failed:
+ WLAN_LOG_ERROR("Failed, result=%d\n", result);
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_stop
+*
+* Issues the initialize command to leave us in the 'reset' state.
+*
+* Arguments:
+* hw device structure
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_stop(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+ DBFENTER;
+
+ del_timer_sync(&hw->commsqual_timer);
+
+ if ( hw->wlandev->hwremoved ) {
+ /* only flush when we're shutting down for good */
+ flush_scheduled_work();
+ }
+
+ if (hw->state == HFA384x_STATE_RUNNING) {
+ /*
+ * Send the MAC initialize cmd.
+ */
+ hfa384x_cmd_initialize(hw);
+
+ /*
+ * Make absolutely sure interrupts are disabled and any
+ * layabout events cleared
+ */
+ hfa384x_setreg(hw, 0, HFA384x_INTEN);
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVACK);
+ }
+
+ tasklet_kill(&hw->bap_tasklet);
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+ hw->state = HFA384x_STATE_INIT;
+
+ /* Clear all the port status */
+ for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) {
+ hw->port_enabled[i] = 0;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_txframe
+*
+* Takes a frame from prism2sta and queues it for transmission.
+*
+* Arguments:
+* hw device structure
+* skb packet buffer struct. Contains an 802.11
+* data frame.
+* p80211_hdr points to the 802.11 header for the packet.
+* Returns:
+* 0 Success and more buffs available
+* 1 Success but no more buffs
+* 2 Allocation failure
+* 3 MAC Tx command failed
+* 4 Buffer full or queue busy
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep)
+{
+ hfa384x_tx_frame_t txdesc;
+ UINT16 macq = 0;
+ UINT16 fid;
+ int result;
+
+ DBFENTER;
+
+ /* Build Tx frame structure */
+ /* Set up the control field */
+ memset(&txdesc, 0, sizeof(txdesc));
+
+/* Tx complete and Tx exception disable per dleach. Might be causing
+ * buf depletion
+ */
+#define DOBOTH 1
+#if DOBOTH
+ txdesc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1);
+#elif DOEXC
+ txdesc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0);
+#else
+ txdesc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0);
+#endif
+
+ /* if we're using host WEP, increase size by IV+ICV */
+ if (p80211_wep->data) {
+ txdesc.data_len = host2hfa384x_16(skb->len+8);
+ // txdesc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1);
+ } else {
+ txdesc.data_len = host2hfa384x_16(skb->len);
+ }
+
+ txdesc.tx_control = host2hfa384x_16(txdesc.tx_control);
+ /* copy the header over to the txdesc */
+ memcpy(&(txdesc.frame_control), p80211_hdr, sizeof(p80211_hdr_t));
+
+ /* Since tbusy is set whenever the stack is empty, there should
+ * always be something on the stack if we get to this point.
+ * [MSM]: NOT TRUE!!!!! so I added the test of fid below.
+ */
+
+ /* Allocate FID */
+
+ fid = txfid_queue_remove(hw);
+
+ if ( fid == 0 ) { /* stack or queue was empty */
+ return 4;
+ }
+
+ /* now let's get the cmdlock */
+ spin_lock(&hw->cmdlock);
+
+ /* Copy descriptor+payload to FID */
+ if (p80211_wep->data) {
+ result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0,
+ &txdesc, sizeof(txdesc),
+ p80211_wep->iv, sizeof(p80211_wep->iv),
+ p80211_wep->data, skb->len,
+ p80211_wep->icv, sizeof(p80211_wep->icv));
+ } else {
+ result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0,
+ &txdesc, sizeof(txdesc),
+ skb->data, skb->len,
+ NULL, 0, NULL, 0);
+ }
+
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_to_bap(%04x, %d, %d) failed, result=0x%x\n",
+ fid,
+ sizeof(txdesc),
+ skb->len,
+ result);
+
+ /* put the fid back in the queue */
+ txfid_queue_add(hw, fid);
+
+ result = 3;
+ goto failed;
+ }
+
+ /* Issue Tx command */
+ result = hfa384x_cmd_transmit(hw, HFA384x_TXCMD_RECL, macq, fid);
+
+ if ( result != 0 ) {
+ txfid_queue_add(hw, fid);
+
+ WLAN_LOG_DEBUG(1,"cmd_tx(%04x) failed, result=%d\n",
+ fid, result);
+ result = 3;
+ goto failed;
+ }
+
+ /* indicate we haven't any buffers, int_alloc will clear */
+ result = txfid_queue_empty(hw);
+failed:
+
+ spin_unlock(&hw->cmdlock);
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_interrupt
+*
+* Driver interrupt handler.
+*
+* Arguments:
+* irq irq number
+* dev_id pointer to the device
+* regs registers
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* May result in a frame being passed up the stack or an info
+* frame being handled.
+*
+* Call context:
+* Ummm, could it be interrupt?
+----------------------------------------------------------------*/
+irqreturn_t hfa384x_interrupt(int irq, void *dev_id PT_REGS)
+{
+ int reg;
+ wlandevice_t *wlandev = (wlandevice_t*)dev_id;
+ hfa384x_t *hw = wlandev->priv;
+ int ev_read = 0;
+ DBFENTER;
+
+ if (!wlandev || wlandev->hwremoved)
+ return IRQ_NONE; /* Not much we can do w/o hardware */
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+ if (hw->iobase == 0) /* XXX FIXME Properly */
+ return IRQ_NONE;
+#endif
+
+ for (;;ev_read++) {
+ if (ev_read >= prism2_irq_evread_max)
+ break;
+
+ /* Check swsupport reg magic # for card presence */
+ reg = hfa384x_getreg(hw, HFA384x_SWSUPPORT0);
+ if ( reg != HFA384x_DRVR_MAGIC) {
+ WLAN_LOG_DEBUG(2, "irq=%d, no magic. Card removed?.\n", irq);
+ break;
+ }
+
+ /* read the EvStat register for interrupt enabled events */
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+
+ /* AND with the enabled interrupts */
+ reg &= hfa384x_getreg(hw, HFA384x_INTEN);
+
+ /* Handle the events */
+ if ( HFA384x_EVSTAT_ISWTERR(reg) ){
+ WLAN_LOG_ERROR(
+ "Error: WTERR interrupt received (unhandled).\n");
+ hfa384x_setreg(hw, HFA384x_EVACK_WTERR_SET(1),
+ HFA384x_EVACK);
+ }
+
+ if ( HFA384x_EVSTAT_ISINFDROP(reg) ){
+ hfa384x_int_infdrop(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_INFDROP_SET(1),
+ HFA384x_EVACK);
+ }
+
+ if (HFA384x_EVSTAT_ISBAP_OP(reg)) {
+ /* Disable the BAP interrupts */
+ hfa384x_events_nobap(hw);
+ tasklet_schedule(&hw->bap_tasklet);
+ }
+
+ if ( HFA384x_EVSTAT_ISALLOC(reg) ){
+ hfa384x_int_alloc(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_ALLOC_SET(1),
+ HFA384x_EVACK);
+ }
+
+ if ( HFA384x_EVSTAT_ISDTIM(reg) ){
+ hfa384x_int_dtim(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_DTIM_SET(1),
+ HFA384x_EVACK);
+ }
+#ifdef CMD_IRQ
+ if ( HFA384x_EVSTAT_ISCMD(reg) ){
+ hfa384x_int_cmd(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_CMD_SET(1),
+ HFA384x_EVACK);
+ }
+#endif
+
+ /* allow the evstat to be updated after the evack */
+ udelay(20);
+ }
+
+ DBFEXIT;
+ return IRQ_HANDLED;
+}
+
+#ifdef CMD_IRQ
+/*----------------------------------------------------------------
+* hfa384x_int_cmd
+*
+* Handles command completion event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void hfa384x_int_cmd(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ DBFENTER;
+
+ // check to make sure it's the right command?
+ if (hw->cmddata) {
+ hw->cmddata->status = hfa384x_getreg(hw, HFA384x_STATUS);
+ hw->cmddata->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
+ hw->cmddata->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
+ hw->cmddata->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
+ }
+ hw->cmdflag = 1;
+
+ printk(KERN_INFO "um. int_cmd\n");
+
+ wake_up_interruptible(&hw->cmdq);
+
+ // XXXX perform a bap copy too?
+
+ DBFEXIT;
+ return;
+}
+#endif
+
+/*----------------------------------------------------------------
+* hfa384x_int_dtim
+*
+* Handles the DTIM early warning event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_int_dtim(wlandevice_t *wlandev)
+{
+#if 0
+ hfa384x_t *hw = wlandev->priv;
+#endif
+ DBFENTER;
+ prism2sta_ev_dtim(wlandev);
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_int_infdrop
+*
+* Handles the InfDrop event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_int_infdrop(wlandevice_t *wlandev)
+{
+#if 0
+ hfa384x_t *hw = wlandev->priv;
+#endif
+ DBFENTER;
+ prism2sta_ev_infdrop(wlandev);
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_int_info
+*
+* Handles the Info event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* tasklet
+----------------------------------------------------------------*/
+static void hfa384x_int_info(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 reg;
+ hfa384x_InfFrame_t inf;
+ int result;
+ DBFENTER;
+ /* Retrieve the FID */
+ reg = hfa384x_getreg(hw, HFA384x_INFOFID);
+
+ /* Retrieve the length */
+ result = hfa384x_copy_from_bap( hw,
+ HFA384x_BAP_INT, reg, 0, &inf.framelen, sizeof(UINT16));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n",
+ reg, sizeof(inf), result);
+ goto failed;
+ }
+ inf.framelen = hfa384x2host_16(inf.framelen);
+
+ /* Retrieve the rest */
+ result = hfa384x_copy_from_bap( hw,
+ HFA384x_BAP_INT, reg, sizeof(UINT16),
+ &(inf.infotype), inf.framelen * sizeof(UINT16));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n",
+ reg, sizeof(inf), result);
+ goto failed;
+ }
+
+ prism2sta_ev_info(wlandev, &inf);
+failed:
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_int_txexc
+*
+* Handles the TxExc event. A Transmit Exception event indicates
+* that the MAC's TX process was unsuccessful - so the packet did
+* not get transmitted.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* tasklet
+----------------------------------------------------------------*/
+static void hfa384x_int_txexc(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 status;
+ UINT16 fid;
+ int result = 0;
+ DBFENTER;
+ /* Collect the status and display */
+ fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
+ result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n",
+ fid, sizeof(status), result);
+ goto failed;
+ }
+ status = hfa384x2host_16(status);
+ prism2sta_ev_txexc(wlandev, status);
+failed:
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_int_tx
+*
+* Handles the Tx event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* tasklet
+----------------------------------------------------------------*/
+static void hfa384x_int_tx(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 fid;
+ UINT16 status;
+ int result = 0;
+ DBFENTER;
+ fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
+ result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n",
+ fid, sizeof(status), result);
+ goto failed;
+ }
+ status = hfa384x2host_16(status);
+ prism2sta_ev_tx(wlandev, status);
+failed:
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_int_rx
+*
+* Handles the Rx event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* tasklet
+----------------------------------------------------------------*/
+static void hfa384x_int_rx(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 rxfid;
+ hfa384x_rx_frame_t rxdesc;
+ int result;
+ int hdrlen;
+ UINT16 fc;
+ p80211_rxmeta_t *rxmeta;
+ struct sk_buff *skb = NULL;
+ UINT8 *datap;
+
+ DBFENTER;
+
+ /* Get the FID */
+ rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
+ /* Get the descriptor (including headers) */
+ result = hfa384x_copy_from_bap(hw,
+ HFA384x_BAP_INT,
+ rxfid,
+ 0,
+ &rxdesc,
+ sizeof(rxdesc));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n",
+ rxfid,
+ 0,
+ sizeof(rxdesc),
+ result);
+ goto done;
+ }
+
+ /* Byte order convert once up front. */
+ rxdesc.status = hfa384x2host_16(rxdesc.status);
+ rxdesc.time = hfa384x2host_32(rxdesc.time);
+
+ /* drop errors and whatnot in promisc mode */
+ if (( wlandev->netdev->flags & IFF_PROMISC ) &&
+ (HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) ||
+ HFA384x_RXSTATUS_ISUNDECR(rxdesc.status)))
+ goto done;
+
+ /* Now handle frame based on port# */
+ switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) )
+ {
+ case 0:
+
+ fc = ieee2host16(rxdesc.frame_control);
+
+ /* If exclude and we receive an unencrypted, drop it */
+ if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) &&
+ !WLAN_GET_FC_ISWEP(fc)) {
+ goto done;
+ }
+
+ hdrlen = p80211_headerlen(fc);
+
+ /* Allocate the buffer, note CRC (aka FCS). pballoc */
+ /* assumes there needs to be space for one */
+ skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a little extra */
+
+ if ( ! skb ) {
+ WLAN_LOG_ERROR("alloc_skb failed.\n");
+ goto done;
+ }
+
+ skb->dev = wlandev->netdev;
+
+ /* theoretically align the IP header on a 32-bit word. */
+ if ( hdrlen == WLAN_HDR_A4_LEN )
+ skb_reserve(skb, 2);
+
+ /* Copy the 802.11 hdr to the buffer */
+ datap = skb_put(skb, WLAN_HDR_A3_LEN);
+ memcpy(datap, &rxdesc.frame_control, WLAN_HDR_A3_LEN);
+
+ /* Snag the A4 address if present */
+ if (hdrlen == WLAN_HDR_A4_LEN) {
+ datap = skb_put(skb, WLAN_ADDR_LEN);
+ memcpy(datap, &rxdesc.address4, WLAN_HDR_A3_LEN);
+ }
+
+ /* we can convert the data_len as we passed the original on */
+ rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
+
+ /* Copy the payload data to the buffer */
+ if ( rxdesc.data_len > 0 ) {
+ datap = skb_put(skb, rxdesc.data_len);
+ result = hfa384x_copy_from_bap(hw,
+ HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF,
+ datap, rxdesc.data_len);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n",
+ rxfid,
+ HFA384x_RX_DATA_OFF,
+ rxdesc.data_len,
+ result);
+ goto failed;
+ }
+ }
+ /* the prism2 cards don't return the FCS */
+ datap = skb_put(skb, WLAN_CRC_LEN);
+ memset (datap, 0xff, WLAN_CRC_LEN);
+ skb_reset_mac_header(skb);
+
+ /* Attach the rxmeta, set some stuff */
+ p80211skb_rxmeta_attach(wlandev, skb);
+ rxmeta = P80211SKB_RXMETA(skb);
+ rxmeta->mactime = rxdesc.time;
+ rxmeta->rxrate = rxdesc.rate;
+ rxmeta->signal = rxdesc.signal - hw->dbmadjust;
+ rxmeta->noise = rxdesc.silence - hw->dbmadjust;
+
+ prism2sta_ev_rx(wlandev, skb);
+ goto done;
+ case 7:
+
+ if ( ! HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) ) {
+ hfa384x_int_rxmonitor( wlandev, rxfid, &rxdesc);
+ } else {
+ WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n");
+ }
+ goto done;
+
+ default:
+
+ WLAN_LOG_WARNING("Received frame on unsupported port=%d\n",
+ HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) );
+ goto done;
+ }
+
+ failed:
+ dev_kfree_skb(skb);
+
+ done:
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_int_rxmonitor
+*
+* Helper function for int_rx. Handles monitor frames.
+* Note that this function allocates space for the FCS and sets it
+* to 0xffffffff. The hfa384x doesn't give us the FCS value but the
+* higher layers expect it. 0xffffffff is used as a flag to indicate
+* the FCS is bogus.
+*
+* Arguments:
+* wlandev wlan device structure
+* rxfid received FID
+* rxdesc rx descriptor read from card in int_rx
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* Allocates an skb and passes it up via the PF_PACKET interface.
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid,
+ hfa384x_rx_frame_t *rxdesc)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT hdrlen = 0;
+ UINT datalen = 0;
+ UINT skblen = 0;
+ UINT truncated = 0;
+ UINT8 *datap;
+ UINT16 fc;
+ struct sk_buff *skb;
+
+ DBFENTER;
+ /* Don't forget the status, time, and data_len fields are in host order */
+ /* Figure out how big the frame is */
+ fc = ieee2host16(rxdesc->frame_control);
+ hdrlen = p80211_headerlen(fc);
+ datalen = hfa384x2host_16(rxdesc->data_len);
+
+ /* Allocate an ind message+framesize skb */
+ skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) +
+ hdrlen + datalen + WLAN_CRC_LEN;
+
+ /* sanity check the length */
+ if ( skblen >
+ (sizeof(p80211msg_lnxind_wlansniffrm_t) +
+ WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) {
+ WLAN_LOG_DEBUG(1, "overlen frm: len=%d\n",
+ skblen - sizeof(p80211msg_lnxind_wlansniffrm_t));
+ }
+
+ if ( (skb = dev_alloc_skb(skblen)) == NULL ) {
+ WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen);
+ return;
+ }
+
+ /* only prepend the prism header if in the right mode */
+ if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) &&
+ (hw->sniffhdr == 0)) {
+ p80211msg_lnxind_wlansniffrm_t *msg;
+ datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t));
+ msg = (p80211msg_lnxind_wlansniffrm_t*) datap;
+
+ /* Initialize the message members */
+ msg->msgcode = DIDmsg_lnxind_wlansniffrm;
+ msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
+ strcpy(msg->devname, wlandev->name);
+
+ msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+ msg->hosttime.status = 0;
+ msg->hosttime.len = 4;
+ msg->hosttime.data = jiffies;
+
+ msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+ msg->mactime.status = 0;
+ msg->mactime.len = 4;
+ msg->mactime.data = rxdesc->time * 1000;
+
+ msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+ msg->channel.status = 0;
+ msg->channel.len = 4;
+ msg->channel.data = hw->sniff_channel;
+
+ msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+ msg->rssi.status = P80211ENUM_msgitem_status_no_value;
+ msg->rssi.len = 4;
+ msg->rssi.data = 0;
+
+ msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
+ msg->sq.status = P80211ENUM_msgitem_status_no_value;
+ msg->sq.len = 4;
+ msg->sq.data = 0;
+
+ msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+ msg->signal.status = 0;
+ msg->signal.len = 4;
+ msg->signal.data = rxdesc->signal;
+
+ msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+ msg->noise.status = 0;
+ msg->noise.len = 4;
+ msg->noise.data = rxdesc->silence;
+
+ msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+ msg->rate.status = 0;
+ msg->rate.len = 4;
+ msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */
+
+ msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+ msg->istx.status = 0;
+ msg->istx.len = 4;
+ msg->istx.data = P80211ENUM_truth_false;
+
+ msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+ msg->frmlen.status = 0;
+ msg->frmlen.len = 4;
+ msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN;
+ } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) &&
+ (hw->sniffhdr != 0)) {
+ p80211_caphdr_t *caphdr;
+ /* The NEW header format! */
+ datap = skb_put(skb, sizeof(p80211_caphdr_t));
+ caphdr = (p80211_caphdr_t*) datap;
+
+ caphdr->version = htonl(P80211CAPTURE_VERSION);
+ caphdr->length = htonl(sizeof(p80211_caphdr_t));
+ caphdr->mactime = __cpu_to_be64(rxdesc->time);
+ caphdr->hosttime = __cpu_to_be64(jiffies);
+ caphdr->phytype = htonl(4); /* dss_dot11_b */
+ caphdr->channel = htonl(hw->sniff_channel);
+ caphdr->datarate = htonl(rxdesc->rate);
+ caphdr->antenna = htonl(0); /* unknown */
+ caphdr->priority = htonl(0); /* unknown */
+ caphdr->ssi_type = htonl(3); /* rssi_raw */
+ caphdr->ssi_signal = htonl(rxdesc->signal);
+ caphdr->ssi_noise = htonl(rxdesc->silence);
+ caphdr->preamble = htonl(0); /* unknown */
+ caphdr->encoding = htonl(1); /* cck */
+ }
+ /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */
+ datap = skb_put(skb, hdrlen);
+ memcpy( datap, &(rxdesc->frame_control), hdrlen);
+
+ /* If any, copy the data from the card to the skb */
+ if ( datalen > 0 )
+ {
+ /* Truncate the packet if the user wants us to */
+ UINT dataread = datalen;
+ if(hw->sniff_truncate > 0 && dataread > hw->sniff_truncate) {
+ dataread = hw->sniff_truncate;
+ truncated = 1;
+ }
+
+ datap = skb_put(skb, dataread);
+ hfa384x_copy_from_bap(hw,
+ HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF,
+ datap, dataread);
+
+ /* check for unencrypted stuff if WEP bit set. */
+ if (*(datap - hdrlen + 1) & 0x40) // wep set
+ if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa))
+ *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header!
+ }
+
+ if (!truncated && hw->sniff_fcs) {
+ /* Set the FCS */
+ datap = skb_put(skb, WLAN_CRC_LEN);
+ memset( datap, 0xff, WLAN_CRC_LEN);
+ }
+
+ /* pass it back up */
+ prism2sta_ev_rx(wlandev, skb);
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_int_alloc
+*
+* Handles the Alloc event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_int_alloc(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 fid;
+ INT16 result;
+
+ DBFENTER;
+
+ /* Handle the reclaimed FID */
+ /* collect the FID and push it onto the stack */
+ fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
+
+ if ( fid != hw->infofid ) { /* It's a transmit fid */
+ WLAN_LOG_DEBUG(5, "int_alloc(%#x)\n", fid);
+ result = txfid_queue_add(hw, fid);
+ if (result != -1) {
+ prism2sta_ev_alloc(wlandev);
+ WLAN_LOG_DEBUG(5, "q_add.\n");
+ } else {
+ WLAN_LOG_DEBUG(5, "q_full.\n");
+ }
+ } else {
+ /* unlock the info fid */
+ up(&hw->infofid_sem);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_handover
+*
+* Sends a handover notification to the MAC.
+*
+* Arguments:
+* hw device structure
+* addr address of station that's left
+*
+* Returns:
+* zero success.
+* -ERESTARTSYS received signal while waiting for semaphore.
+* -EIO failed to write to bap, or failed in cmd.
+*
+* Side effects:
+*
+* Call context:
+* process thread, NOTE: this call may block on a semaphore!
+----------------------------------------------------------------*/
+int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr)
+{
+ int result = 0;
+ hfa384x_HandoverAddr_t rec;
+ UINT len;
+ DBFENTER;
+
+ /* Acquire the infofid */
+ if ( down_interruptible(&hw->infofid_sem) ) {
+ result = -ERESTARTSYS;
+ goto failed;
+ }
+
+ /* Set up the record */
+ len = sizeof(hfa384x_HandoverAddr_t);
+ rec.framelen = host2hfa384x_16(len/2 - 1);
+ rec.infotype = host2hfa384x_16(HFA384x_IT_HANDOVERADDR);
+ memcpy(rec.handover_addr, addr, sizeof(rec.handover_addr));
+
+ /* Issue the command */
+ result = hfa384x_cmd_notify(hw, 1, hw->infofid, &rec, len);
+
+ if ( result != 0 ) {
+ WLAN_LOG_DEBUG(1,"cmd_notify(%04x) failed, result=%d",
+ hw->infofid, result);
+ result = -EIO;
+ goto failed;
+ }
+
+failed:
+ DBFEXIT;
+ return result;
+}
+
+void hfa384x_tx_timeout(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+ WLAN_LOG_WARNING("Implement me.\n");
+
+ DBFEXIT;
+}
+
+/* Handles all "rx" BAP operations */
+static void hfa384x_bap_tasklet(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t *) data;
+ wlandevice_t *wlandev = hw->wlandev;
+ int counter = prism2_irq_evread_max;
+ int reg;
+
+ DBFENTER;
+
+ while (counter-- > 0) {
+ /* Get interrupt register */
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+
+ if ((reg == 0xffff) ||
+ !(reg & HFA384x_INT_BAP_OP)) {
+ break;
+ }
+
+ if ( HFA384x_EVSTAT_ISINFO(reg) ){
+ hfa384x_int_info(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_INFO_SET(1),
+ HFA384x_EVACK);
+ }
+ if ( HFA384x_EVSTAT_ISTXEXC(reg) ){
+ hfa384x_int_txexc(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_TXEXC_SET(1),
+ HFA384x_EVACK);
+ }
+ if ( HFA384x_EVSTAT_ISTX(reg) ){
+ hfa384x_int_tx(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_TX_SET(1),
+ HFA384x_EVACK);
+ }
+ if ( HFA384x_EVSTAT_ISRX(reg) ){
+ hfa384x_int_rx(wlandev);
+ hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1),
+ HFA384x_EVACK);
+ }
+ }
+
+ /* re-enable interrupts */
+ hfa384x_events_all(hw);
+
+ DBFEXIT;
+}
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
new file mode 100644
index 00000000000..a2054639d24
--- /dev/null
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -0,0 +1,3067 @@
+/* hfa384x.h
+*
+* Defines the constants and data structures for the hfa384x
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* [Implementation and usage notes]
+*
+* [References]
+* CW10 Programmer's Manual v1.5
+* IEEE 802.11 D10.0
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _HFA384x_H
+#define _HFA384x_H
+
+/*=============================================================*/
+#define HFA384x_FIRMWARE_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+#define HFA384x_LEVEL_TO_dBm(v) (0x100 + (v) * 100 / 255 - 100)
+
+/*------ Constants --------------------------------------------*/
+/*--- Mins & Maxs -----------------------------------*/
+#define HFA384x_CMD_ALLOC_LEN_MIN ((UINT16)4)
+#define HFA384x_CMD_ALLOC_LEN_MAX ((UINT16)2400)
+#define HFA384x_BAP_DATALEN_MAX ((UINT16)4096)
+#define HFA384x_BAP_OFFSET_MAX ((UINT16)4096)
+#define HFA384x_PORTID_MAX ((UINT16)7)
+#define HFA384x_NUMPORTS_MAX ((UINT16)(HFA384x_PORTID_MAX+1))
+#define HFA384x_PDR_LEN_MAX ((UINT16)512) /* in bytes, from EK */
+#define HFA384x_PDA_RECS_MAX ((UINT16)200) /* a guess */
+#define HFA384x_PDA_LEN_MAX ((UINT16)1024) /* in bytes, from EK */
+#define HFA384x_SCANRESULT_MAX ((UINT16)31)
+#define HFA384x_HSCANRESULT_MAX ((UINT16)31)
+#define HFA384x_CHINFORESULT_MAX ((UINT16)16)
+#define HFA384x_DRVR_FIDSTACKLEN_MAX (10)
+#define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \
+ WLAN_DATA_MAXLEN - \
+ WLAN_WEP_IV_LEN - \
+ WLAN_WEP_ICV_LEN + 2)
+#define HFA384x_DRVR_MAGIC (0x4a2d)
+#define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t))
+#define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t))
+#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
+#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN
+#define HFA384x_USB_RWMEM_MAXLEN 2048
+
+/*--- Support Constants -----------------------------*/
+#define HFA384x_BAP_PROC ((UINT16)0)
+#define HFA384x_BAP_INT ((UINT16)1)
+#define HFA384x_PORTTYPE_IBSS ((UINT16)0)
+#define HFA384x_PORTTYPE_BSS ((UINT16)1)
+#define HFA384x_PORTTYPE_WDS ((UINT16)2)
+#define HFA384x_PORTTYPE_PSUEDOIBSS ((UINT16)3)
+#define HFA384x_PORTTYPE_HOSTAP ((UINT16)6)
+#define HFA384x_WEPFLAGS_PRIVINVOKED ((UINT16)BIT0)
+#define HFA384x_WEPFLAGS_EXCLUDE ((UINT16)BIT1)
+#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((UINT16)BIT4)
+#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((UINT16)BIT7)
+#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((UINT16)BIT11)
+#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((UINT16)0)
+#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((UINT16)BIT5)
+#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((UINT16)BIT6)
+#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((UINT16)(BIT5 | BIT6))
+#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((UINT16)BIT8)
+#define HFA384x_WEPFLAGS_HOST_MIC ((UINT16)BIT9)
+#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((UINT16)1)
+#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((UINT16)2)
+#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((UINT16)3)
+#define HFA384x_PORTSTATUS_DISABLED ((UINT16)1)
+#define HFA384x_PORTSTATUS_INITSRCH ((UINT16)2)
+#define HFA384x_PORTSTATUS_CONN_IBSS ((UINT16)3)
+#define HFA384x_PORTSTATUS_CONN_ESS ((UINT16)4)
+#define HFA384x_PORTSTATUS_OOR_ESS ((UINT16)5)
+#define HFA384x_PORTSTATUS_CONN_WDS ((UINT16)6)
+#define HFA384x_PORTSTATUS_HOSTAP ((UINT16)8)
+#define HFA384x_RATEBIT_1 ((UINT16)1)
+#define HFA384x_RATEBIT_2 ((UINT16)2)
+#define HFA384x_RATEBIT_5dot5 ((UINT16)4)
+#define HFA384x_RATEBIT_11 ((UINT16)8)
+
+/*--- Just some symbolic names for legibility -------*/
+#define HFA384x_TXCMD_NORECL ((UINT16)0)
+#define HFA384x_TXCMD_RECL ((UINT16)1)
+
+/*--- MAC Internal memory constants and macros ------*/
+/* masks and macros used to manipulate MAC internal memory addresses. */
+/* MAC internal memory addresses are 23 bit quantities. The MAC uses
+ * a paged address space where the upper 16 bits are the page number
+ * and the lower 7 bits are the offset. There are various Host API
+ * elements that require two 16-bit quantities to specify a MAC
+ * internal memory address. Unfortunately, some of the API's use a
+ * page/offset format where the offset value is JUST the lower seven
+ * bits and the page is the remaining 16 bits. Some of the API's
+ * assume that the 23 bit address has been split at the 16th bit. We
+ * refer to these two formats as AUX format and CMD format. The
+ * macros below help handle some of this.
+ */
+
+/* Handy constant */
+#define HFA384x_ADDR_AUX_OFF_MAX ((UINT16)0x007f)
+
+/* Mask bits for discarding unwanted pieces in a flat address */
+#define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80)
+#define HFA384x_ADDR_FLAT_AUX_OFF_MASK (0x0000007f)
+#define HFA384x_ADDR_FLAT_CMD_PAGE_MASK (0xffff0000)
+#define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff)
+
+/* Mask bits for discarding unwanted pieces in AUX format 16-bit address parts */
+#define HFA384x_ADDR_AUX_PAGE_MASK (0xffff)
+#define HFA384x_ADDR_AUX_OFF_MASK (0x007f)
+
+/* Mask bits for discarding unwanted pieces in CMD format 16-bit address parts */
+#define HFA384x_ADDR_CMD_PAGE_MASK (0x007f)
+#define HFA384x_ADDR_CMD_OFF_MASK (0xffff)
+
+/* Make a 32-bit flat address from AUX format 16-bit page and offset */
+#define HFA384x_ADDR_AUX_MKFLAT(p,o) \
+ (((UINT32)(((UINT16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \
+ ((UINT32)(((UINT16)(o))&HFA384x_ADDR_AUX_OFF_MASK))
+
+/* Make a 32-bit flat address from CMD format 16-bit page and offset */
+#define HFA384x_ADDR_CMD_MKFLAT(p,o) \
+ (((UINT32)(((UINT16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \
+ ((UINT32)(((UINT16)(o))&HFA384x_ADDR_CMD_OFF_MASK))
+
+/* Make AUX format offset and page from a 32-bit flat address */
+#define HFA384x_ADDR_AUX_MKPAGE(f) \
+ ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7))
+#define HFA384x_ADDR_AUX_MKOFF(f) \
+ ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK))
+
+/* Make CMD format offset and page from a 32-bit flat address */
+#define HFA384x_ADDR_CMD_MKPAGE(f) \
+ ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16))
+#define HFA384x_ADDR_CMD_MKOFF(f) \
+ ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK))
+
+/*--- Aux register masks/tests ----------------------*/
+/* Some of the upper bits of the AUX offset register are used to */
+/* select address space. */
+#define HFA384x_AUX_CTL_EXTDS (0x00)
+#define HFA384x_AUX_CTL_NV (0x01)
+#define HFA384x_AUX_CTL_PHY (0x02)
+#define HFA384x_AUX_CTL_ICSRAM (0x03)
+
+/* Make AUX register offset and page values from a flat address */
+#define HFA384x_AUX_MKOFF(f, c) \
+ (HFA384x_ADDR_AUX_MKOFF(f) | (((UINT16)(c))<<12))
+#define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f)
+
+
+/*--- Controller Memory addresses -------------------*/
+#define HFA3842_PDA_BASE (0x007f0000UL)
+#define HFA3841_PDA_BASE (0x003f0000UL)
+#define HFA3841_PDA_BOGUS_BASE (0x00390000UL)
+
+/*--- Driver Download states -----------------------*/
+#define HFA384x_DLSTATE_DISABLED 0
+#define HFA384x_DLSTATE_RAMENABLED 1
+#define HFA384x_DLSTATE_FLASHENABLED 2
+#define HFA384x_DLSTATE_FLASHWRITTEN 3
+#define HFA384x_DLSTATE_FLASHWRITEPENDING 4
+#define HFA384x_DLSTATE_GENESIS 5
+
+/*--- Register I/O offsets --------------------------*/
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+
+#define HFA384x_CMD_OFF (0x00)
+#define HFA384x_PARAM0_OFF (0x02)
+#define HFA384x_PARAM1_OFF (0x04)
+#define HFA384x_PARAM2_OFF (0x06)
+#define HFA384x_STATUS_OFF (0x08)
+#define HFA384x_RESP0_OFF (0x0A)
+#define HFA384x_RESP1_OFF (0x0C)
+#define HFA384x_RESP2_OFF (0x0E)
+#define HFA384x_INFOFID_OFF (0x10)
+#define HFA384x_RXFID_OFF (0x20)
+#define HFA384x_ALLOCFID_OFF (0x22)
+#define HFA384x_TXCOMPLFID_OFF (0x24)
+#define HFA384x_SELECT0_OFF (0x18)
+#define HFA384x_OFFSET0_OFF (0x1C)
+#define HFA384x_DATA0_OFF (0x36)
+#define HFA384x_SELECT1_OFF (0x1A)
+#define HFA384x_OFFSET1_OFF (0x1E)
+#define HFA384x_DATA1_OFF (0x38)
+#define HFA384x_EVSTAT_OFF (0x30)
+#define HFA384x_INTEN_OFF (0x32)
+#define HFA384x_EVACK_OFF (0x34)
+#define HFA384x_CONTROL_OFF (0x14)
+#define HFA384x_SWSUPPORT0_OFF (0x28)
+#define HFA384x_SWSUPPORT1_OFF (0x2A)
+#define HFA384x_SWSUPPORT2_OFF (0x2C)
+#define HFA384x_AUXPAGE_OFF (0x3A)
+#define HFA384x_AUXOFFSET_OFF (0x3C)
+#define HFA384x_AUXDATA_OFF (0x3E)
+
+#elif (WLAN_HOSTIF == WLAN_PCI || WLAN_HOSTIF == WLAN_USB)
+
+#define HFA384x_CMD_OFF (0x00)
+#define HFA384x_PARAM0_OFF (0x04)
+#define HFA384x_PARAM1_OFF (0x08)
+#define HFA384x_PARAM2_OFF (0x0c)
+#define HFA384x_STATUS_OFF (0x10)
+#define HFA384x_RESP0_OFF (0x14)
+#define HFA384x_RESP1_OFF (0x18)
+#define HFA384x_RESP2_OFF (0x1c)
+#define HFA384x_INFOFID_OFF (0x20)
+#define HFA384x_RXFID_OFF (0x40)
+#define HFA384x_ALLOCFID_OFF (0x44)
+#define HFA384x_TXCOMPLFID_OFF (0x48)
+#define HFA384x_SELECT0_OFF (0x30)
+#define HFA384x_OFFSET0_OFF (0x38)
+#define HFA384x_DATA0_OFF (0x6c)
+#define HFA384x_SELECT1_OFF (0x34)
+#define HFA384x_OFFSET1_OFF (0x3c)
+#define HFA384x_DATA1_OFF (0x70)
+#define HFA384x_EVSTAT_OFF (0x60)
+#define HFA384x_INTEN_OFF (0x64)
+#define HFA384x_EVACK_OFF (0x68)
+#define HFA384x_CONTROL_OFF (0x28)
+#define HFA384x_SWSUPPORT0_OFF (0x50)
+#define HFA384x_SWSUPPORT1_OFF (0x54)
+#define HFA384x_SWSUPPORT2_OFF (0x58)
+#define HFA384x_AUXPAGE_OFF (0x74)
+#define HFA384x_AUXOFFSET_OFF (0x78)
+#define HFA384x_AUXDATA_OFF (0x7c)
+#define HFA384x_PCICOR_OFF (0x4c)
+#define HFA384x_PCIHCR_OFF (0x5c)
+#define HFA384x_PCI_M0_ADDRH_OFF (0x80)
+#define HFA384x_PCI_M0_ADDRL_OFF (0x84)
+#define HFA384x_PCI_M0_LEN_OFF (0x88)
+#define HFA384x_PCI_M0_CTL_OFF (0x8c)
+#define HFA384x_PCI_STATUS_OFF (0x98)
+#define HFA384x_PCI_M1_ADDRH_OFF (0xa0)
+#define HFA384x_PCI_M1_ADDRL_OFF (0xa4)
+#define HFA384x_PCI_M1_LEN_OFF (0xa8)
+#define HFA384x_PCI_M1_CTL_OFF (0xac)
+
+#endif
+
+/*--- Register Field Masks --------------------------*/
+#define HFA384x_CMD_BUSY ((UINT16)BIT15)
+#define HFA384x_CMD_AINFO ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
+#define HFA384x_CMD_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_CMD_RECL ((UINT16)BIT8)
+#define HFA384x_CMD_WRITE ((UINT16)BIT8)
+#define HFA384x_CMD_PROGMODE ((UINT16)(BIT9 | BIT8))
+#define HFA384x_CMD_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
+
+#define HFA384x_STATUS_RESULT ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8))
+#define HFA384x_STATUS_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0))
+
+#define HFA384x_OFFSET_BUSY ((UINT16)BIT15)
+#define HFA384x_OFFSET_ERR ((UINT16)BIT14)
+#define HFA384x_OFFSET_DATAOFF ((UINT16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1))
+
+#define HFA384x_EVSTAT_TICK ((UINT16)BIT15)
+#define HFA384x_EVSTAT_WTERR ((UINT16)BIT14)
+#define HFA384x_EVSTAT_INFDROP ((UINT16)BIT13)
+#define HFA384x_EVSTAT_INFO ((UINT16)BIT7)
+#define HFA384x_EVSTAT_DTIM ((UINT16)BIT5)
+#define HFA384x_EVSTAT_CMD ((UINT16)BIT4)
+#define HFA384x_EVSTAT_ALLOC ((UINT16)BIT3)
+#define HFA384x_EVSTAT_TXEXC ((UINT16)BIT2)
+#define HFA384x_EVSTAT_TX ((UINT16)BIT1)
+#define HFA384x_EVSTAT_RX ((UINT16)BIT0)
+
+#define HFA384x_INT_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC)
+
+#define HFA384x_INT_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM)
+
+#define HFA384x_INTEN_TICK ((UINT16)BIT15)
+#define HFA384x_INTEN_WTERR ((UINT16)BIT14)
+#define HFA384x_INTEN_INFDROP ((UINT16)BIT13)
+#define HFA384x_INTEN_INFO ((UINT16)BIT7)
+#define HFA384x_INTEN_DTIM ((UINT16)BIT5)
+#define HFA384x_INTEN_CMD ((UINT16)BIT4)
+#define HFA384x_INTEN_ALLOC ((UINT16)BIT3)
+#define HFA384x_INTEN_TXEXC ((UINT16)BIT2)
+#define HFA384x_INTEN_TX ((UINT16)BIT1)
+#define HFA384x_INTEN_RX ((UINT16)BIT0)
+
+#define HFA384x_EVACK_TICK ((UINT16)BIT15)
+#define HFA384x_EVACK_WTERR ((UINT16)BIT14)
+#define HFA384x_EVACK_INFDROP ((UINT16)BIT13)
+#define HFA384x_EVACK_INFO ((UINT16)BIT7)
+#define HFA384x_EVACK_DTIM ((UINT16)BIT5)
+#define HFA384x_EVACK_CMD ((UINT16)BIT4)
+#define HFA384x_EVACK_ALLOC ((UINT16)BIT3)
+#define HFA384x_EVACK_TXEXC ((UINT16)BIT2)
+#define HFA384x_EVACK_TX ((UINT16)BIT1)
+#define HFA384x_EVACK_RX ((UINT16)BIT0)
+
+#define HFA384x_CONTROL_AUXEN ((UINT16)(BIT15 | BIT14))
+
+
+/*--- Command Code Constants --------------------------*/
+/*--- Controller Commands --------------------------*/
+#define HFA384x_CMDCODE_INIT ((UINT16)0x00)
+#define HFA384x_CMDCODE_ENABLE ((UINT16)0x01)
+#define HFA384x_CMDCODE_DISABLE ((UINT16)0x02)
+#define HFA384x_CMDCODE_DIAG ((UINT16)0x03)
+
+/*--- Buffer Mgmt Commands --------------------------*/
+#define HFA384x_CMDCODE_ALLOC ((UINT16)0x0A)
+#define HFA384x_CMDCODE_TX ((UINT16)0x0B)
+#define HFA384x_CMDCODE_CLRPRST ((UINT16)0x12)
+
+/*--- Regulate Commands --------------------------*/
+#define HFA384x_CMDCODE_NOTIFY ((UINT16)0x10)
+#define HFA384x_CMDCODE_INQ ((UINT16)0x11)
+
+/*--- Configure Commands --------------------------*/
+#define HFA384x_CMDCODE_ACCESS ((UINT16)0x21)
+#define HFA384x_CMDCODE_DOWNLD ((UINT16)0x22)
+
+/*--- Debugging Commands -----------------------------*/
+#define HFA384x_CMDCODE_MONITOR ((UINT16)(0x38))
+#define HFA384x_MONITOR_ENABLE ((UINT16)(0x0b))
+#define HFA384x_MONITOR_DISABLE ((UINT16)(0x0f))
+
+/*--- Result Codes --------------------------*/
+#define HFA384x_SUCCESS ((UINT16)(0x00))
+#define HFA384x_CARD_FAIL ((UINT16)(0x01))
+#define HFA384x_NO_BUFF ((UINT16)(0x05))
+#define HFA384x_CMD_ERR ((UINT16)(0x7F))
+
+/*--- Programming Modes --------------------------
+ MODE 0: Disable programming
+ MODE 1: Enable volatile memory programming
+ MODE 2: Enable non-volatile memory programming
+ MODE 3: Program non-volatile memory section
+--------------------------------------------------*/
+#define HFA384x_PROGMODE_DISABLE ((UINT16)0x00)
+#define HFA384x_PROGMODE_RAM ((UINT16)0x01)
+#define HFA384x_PROGMODE_NV ((UINT16)0x02)
+#define HFA384x_PROGMODE_NVWRITE ((UINT16)0x03)
+
+/*--- AUX register enable --------------------------*/
+#define HFA384x_AUXPW0 ((UINT16)0xfe01)
+#define HFA384x_AUXPW1 ((UINT16)0xdc23)
+#define HFA384x_AUXPW2 ((UINT16)0xba45)
+
+#define HFA384x_CONTROL_AUX_ISDISABLED ((UINT16)0x0000)
+#define HFA384x_CONTROL_AUX_ISENABLED ((UINT16)0xc000)
+#define HFA384x_CONTROL_AUX_DOENABLE ((UINT16)0x8000)
+#define HFA384x_CONTROL_AUX_DODISABLE ((UINT16)0x4000)
+
+/*--- Record ID Constants --------------------------*/
+/*--------------------------------------------------------------------
+Configuration RIDs: Network Parameters, Static Configuration Entities
+--------------------------------------------------------------------*/
+#define HFA384x_RID_CNFPORTTYPE ((UINT16)0xFC00)
+#define HFA384x_RID_CNFOWNMACADDR ((UINT16)0xFC01)
+#define HFA384x_RID_CNFDESIREDSSID ((UINT16)0xFC02)
+#define HFA384x_RID_CNFOWNCHANNEL ((UINT16)0xFC03)
+#define HFA384x_RID_CNFOWNSSID ((UINT16)0xFC04)
+#define HFA384x_RID_CNFOWNATIMWIN ((UINT16)0xFC05)
+#define HFA384x_RID_CNFSYSSCALE ((UINT16)0xFC06)
+#define HFA384x_RID_CNFMAXDATALEN ((UINT16)0xFC07)
+#define HFA384x_RID_CNFWDSADDR ((UINT16)0xFC08)
+#define HFA384x_RID_CNFPMENABLED ((UINT16)0xFC09)
+#define HFA384x_RID_CNFPMEPS ((UINT16)0xFC0A)
+#define HFA384x_RID_CNFMULTICASTRX ((UINT16)0xFC0B)
+#define HFA384x_RID_CNFMAXSLEEPDUR ((UINT16)0xFC0C)
+#define HFA384x_RID_CNFPMHOLDDUR ((UINT16)0xFC0D)
+#define HFA384x_RID_CNFOWNNAME ((UINT16)0xFC0E)
+#define HFA384x_RID_CNFOWNDTIMPER ((UINT16)0xFC10)
+#define HFA384x_RID_CNFWDSADDR1 ((UINT16)0xFC11)
+#define HFA384x_RID_CNFWDSADDR2 ((UINT16)0xFC12)
+#define HFA384x_RID_CNFWDSADDR3 ((UINT16)0xFC13)
+#define HFA384x_RID_CNFWDSADDR4 ((UINT16)0xFC14)
+#define HFA384x_RID_CNFWDSADDR5 ((UINT16)0xFC15)
+#define HFA384x_RID_CNFWDSADDR6 ((UINT16)0xFC16)
+#define HFA384x_RID_CNFMCASTPMBUFF ((UINT16)0xFC17)
+
+/*--------------------------------------------------------------------
+Configuration RID lengths: Network Params, Static Config Entities
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+/* TODO: fill in the rest of these */
+#define HFA384x_RID_CNFPORTTYPE_LEN ((UINT16)2)
+#define HFA384x_RID_CNFOWNMACADDR_LEN ((UINT16)6)
+#define HFA384x_RID_CNFDESIREDSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNCHANNEL_LEN ((UINT16)2)
+#define HFA384x_RID_CNFOWNSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNATIMWIN_LEN ((UINT16)2)
+#define HFA384x_RID_CNFSYSSCALE_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMAXDATALEN_LEN ((UINT16)0)
+#define HFA384x_RID_CNFWDSADDR_LEN ((UINT16)6)
+#define HFA384x_RID_CNFPMENABLED_LEN ((UINT16)0)
+#define HFA384x_RID_CNFPMEPS_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMULTICASTRX_LEN ((UINT16)0)
+#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0)
+#define HFA384x_RID_CNFPMHOLDDUR_LEN ((UINT16)0)
+#define HFA384x_RID_CNFOWNNAME_LEN ((UINT16)34)
+#define HFA384x_RID_CNFOWNDTIMPER_LEN ((UINT16)0)
+#define HFA384x_RID_CNFWDSADDR1_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR2_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR3_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR4_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR5_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWDSADDR6_LEN ((UINT16)6)
+#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((UINT16)0)
+#define HFA384x_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16))
+#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0)
+
+/*--------------------------------------------------------------------
+Configuration RIDs: Network Parameters, Dynamic Configuration Entities
+--------------------------------------------------------------------*/
+#define HFA384x_RID_GROUPADDR ((UINT16)0xFC80)
+#define HFA384x_RID_CREATEIBSS ((UINT16)0xFC81)
+#define HFA384x_RID_FRAGTHRESH ((UINT16)0xFC82)
+#define HFA384x_RID_RTSTHRESH ((UINT16)0xFC83)
+#define HFA384x_RID_TXRATECNTL ((UINT16)0xFC84)
+#define HFA384x_RID_PROMISCMODE ((UINT16)0xFC85)
+#define HFA384x_RID_FRAGTHRESH0 ((UINT16)0xFC90)
+#define HFA384x_RID_FRAGTHRESH1 ((UINT16)0xFC91)
+#define HFA384x_RID_FRAGTHRESH2 ((UINT16)0xFC92)
+#define HFA384x_RID_FRAGTHRESH3 ((UINT16)0xFC93)
+#define HFA384x_RID_FRAGTHRESH4 ((UINT16)0xFC94)
+#define HFA384x_RID_FRAGTHRESH5 ((UINT16)0xFC95)
+#define HFA384x_RID_FRAGTHRESH6 ((UINT16)0xFC96)
+#define HFA384x_RID_RTSTHRESH0 ((UINT16)0xFC97)
+#define HFA384x_RID_RTSTHRESH1 ((UINT16)0xFC98)
+#define HFA384x_RID_RTSTHRESH2 ((UINT16)0xFC99)
+#define HFA384x_RID_RTSTHRESH3 ((UINT16)0xFC9A)
+#define HFA384x_RID_RTSTHRESH4 ((UINT16)0xFC9B)
+#define HFA384x_RID_RTSTHRESH5 ((UINT16)0xFC9C)
+#define HFA384x_RID_RTSTHRESH6 ((UINT16)0xFC9D)
+#define HFA384x_RID_TXRATECNTL0 ((UINT16)0xFC9E)
+#define HFA384x_RID_TXRATECNTL1 ((UINT16)0xFC9F)
+#define HFA384x_RID_TXRATECNTL2 ((UINT16)0xFCA0)
+#define HFA384x_RID_TXRATECNTL3 ((UINT16)0xFCA1)
+#define HFA384x_RID_TXRATECNTL4 ((UINT16)0xFCA2)
+#define HFA384x_RID_TXRATECNTL5 ((UINT16)0xFCA3)
+#define HFA384x_RID_TXRATECNTL6 ((UINT16)0xFCA4)
+
+/*--------------------------------------------------------------------
+Configuration RID Lengths: Network Param, Dynamic Config Entities
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+/* TODO: fill in the rest of these */
+#define HFA384x_RID_GROUPADDR_LEN ((UINT16)16 * WLAN_ADDR_LEN)
+#define HFA384x_RID_CREATEIBSS_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL_LEN ((UINT16)4)
+#define HFA384x_RID_PROMISCMODE_LEN ((UINT16)2)
+#define HFA384x_RID_FRAGTHRESH0_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH1_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH2_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH3_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH4_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH5_LEN ((UINT16)0)
+#define HFA384x_RID_FRAGTHRESH6_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH0_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH1_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH2_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH3_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH4_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH5_LEN ((UINT16)0)
+#define HFA384x_RID_RTSTHRESH6_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL0_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL1_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL2_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL3_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL4_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL5_LEN ((UINT16)0)
+#define HFA384x_RID_TXRATECNTL6_LEN ((UINT16)0)
+
+/*--------------------------------------------------------------------
+Configuration RIDs: Behavior Parameters
+--------------------------------------------------------------------*/
+#define HFA384x_RID_ITICKTIME ((UINT16)0xFCE0)
+
+/*--------------------------------------------------------------------
+Configuration RID Lengths: Behavior Parameters
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_ITICKTIME_LEN ((UINT16)2)
+
+/*----------------------------------------------------------------------
+Information RIDs: NIC Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_MAXLOADTIME ((UINT16)0xFD00)
+#define HFA384x_RID_DOWNLOADBUFFER ((UINT16)0xFD01)
+#define HFA384x_RID_PRIIDENTITY ((UINT16)0xFD02)
+#define HFA384x_RID_PRISUPRANGE ((UINT16)0xFD03)
+#define HFA384x_RID_PRI_CFIACTRANGES ((UINT16)0xFD04)
+#define HFA384x_RID_NICSERIALNUMBER ((UINT16)0xFD0A)
+#define HFA384x_RID_NICIDENTITY ((UINT16)0xFD0B)
+#define HFA384x_RID_MFISUPRANGE ((UINT16)0xFD0C)
+#define HFA384x_RID_CFISUPRANGE ((UINT16)0xFD0D)
+#define HFA384x_RID_CHANNELLIST ((UINT16)0xFD10)
+#define HFA384x_RID_REGULATORYDOMAINS ((UINT16)0xFD11)
+#define HFA384x_RID_TEMPTYPE ((UINT16)0xFD12)
+#define HFA384x_RID_CIS ((UINT16)0xFD13)
+#define HFA384x_RID_STAIDENTITY ((UINT16)0xFD20)
+#define HFA384x_RID_STASUPRANGE ((UINT16)0xFD21)
+#define HFA384x_RID_STA_MFIACTRANGES ((UINT16)0xFD22)
+#define HFA384x_RID_STA_CFIACTRANGES ((UINT16)0xFD23)
+#define HFA384x_RID_BUILDSEQ ((UINT16)0xFFFE)
+#define HFA384x_RID_FWID ((UINT16)0xFFFF)
+
+/*----------------------------------------------------------------------
+Information RID Lengths: NIC Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_MAXLOADTIME_LEN ((UINT16)0)
+#define HFA384x_RID_DOWNLOADBUFFER_LEN ((UINT16)sizeof(hfa384x_downloadbuffer_t))
+#define HFA384x_RID_PRIIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_PRISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CFIACTRANGES_LEN ((UINT16)10)
+#define HFA384x_RID_NICSERIALNUMBER_LEN ((UINT16)12)
+#define HFA384x_RID_NICIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_MFISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CFISUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_CHANNELLIST_LEN ((UINT16)0)
+#define HFA384x_RID_REGULATORYDOMAINS_LEN ((UINT16)12)
+#define HFA384x_RID_TEMPTYPE_LEN ((UINT16)0)
+#define HFA384x_RID_CIS_LEN ((UINT16)480)
+#define HFA384x_RID_STAIDENTITY_LEN ((UINT16)8)
+#define HFA384x_RID_STASUPRANGE_LEN ((UINT16)10)
+#define HFA384x_RID_MFIACTRANGES_LEN ((UINT16)10)
+#define HFA384x_RID_CFIACTRANGES2_LEN ((UINT16)10)
+#define HFA384x_RID_BUILDSEQ_LEN ((UINT16)sizeof(hfa384x_BuildSeq_t))
+#define HFA384x_RID_FWID_LEN ((UINT16)sizeof(hfa384x_FWID_t))
+
+/*--------------------------------------------------------------------
+Information RIDs: MAC Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PORTSTATUS ((UINT16)0xFD40)
+#define HFA384x_RID_CURRENTSSID ((UINT16)0xFD41)
+#define HFA384x_RID_CURRENTBSSID ((UINT16)0xFD42)
+#define HFA384x_RID_COMMSQUALITY ((UINT16)0xFD43)
+#define HFA384x_RID_CURRENTTXRATE ((UINT16)0xFD44)
+#define HFA384x_RID_CURRENTBCNINT ((UINT16)0xFD45)
+#define HFA384x_RID_CURRENTSCALETHRESH ((UINT16)0xFD46)
+#define HFA384x_RID_PROTOCOLRSPTIME ((UINT16)0xFD47)
+#define HFA384x_RID_SHORTRETRYLIMIT ((UINT16)0xFD48)
+#define HFA384x_RID_LONGRETRYLIMIT ((UINT16)0xFD49)
+#define HFA384x_RID_MAXTXLIFETIME ((UINT16)0xFD4A)
+#define HFA384x_RID_MAXRXLIFETIME ((UINT16)0xFD4B)
+#define HFA384x_RID_CFPOLLABLE ((UINT16)0xFD4C)
+#define HFA384x_RID_AUTHALGORITHMS ((UINT16)0xFD4D)
+#define HFA384x_RID_PRIVACYOPTIMP ((UINT16)0xFD4F)
+#define HFA384x_RID_DBMCOMMSQUALITY ((UINT16)0xFD51)
+#define HFA384x_RID_CURRENTTXRATE1 ((UINT16)0xFD80)
+#define HFA384x_RID_CURRENTTXRATE2 ((UINT16)0xFD81)
+#define HFA384x_RID_CURRENTTXRATE3 ((UINT16)0xFD82)
+#define HFA384x_RID_CURRENTTXRATE4 ((UINT16)0xFD83)
+#define HFA384x_RID_CURRENTTXRATE5 ((UINT16)0xFD84)
+#define HFA384x_RID_CURRENTTXRATE6 ((UINT16)0xFD85)
+#define HFA384x_RID_OWNMACADDRESS ((UINT16)0xFD86)
+// #define HFA384x_RID_PCFINFO ((UINT16)0xFD87)
+#define HFA384x_RID_SCANRESULTS ((UINT16)0xFD88) // NEW
+#define HFA384x_RID_HOSTSCANRESULTS ((UINT16)0xFD89) // NEW
+#define HFA384x_RID_AUTHENTICATIONUSED ((UINT16)0xFD8A) // NEW
+#define HFA384x_RID_ASSOCIATEFAILURE ((UINT16)0xFD8D) // 1.8.0
+
+/*--------------------------------------------------------------------
+Information RID Lengths: MAC Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PORTSTATUS_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTSSID_LEN ((UINT16)34)
+#define HFA384x_RID_CURRENTBSSID_LEN ((UINT16)WLAN_BSSID_LEN)
+#define HFA384x_RID_COMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_commsquality_t))
+#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_dbmcommsquality_t))
+#define HFA384x_RID_CURRENTTXRATE_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTBCNINT_LEN ((UINT16)0)
+#define HFA384x_RID_STACURSCALETHRESH_LEN ((UINT16)12)
+#define HFA384x_RID_APCURSCALETHRESH_LEN ((UINT16)6)
+#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((UINT16)0)
+#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((UINT16)0)
+#define HFA384x_RID_LONGRETRYLIMIT_LEN ((UINT16)0)
+#define HFA384x_RID_MAXTXLIFETIME_LEN ((UINT16)0)
+#define HFA384x_RID_MAXRXLIFETIME_LEN ((UINT16)0)
+#define HFA384x_RID_CFPOLLABLE_LEN ((UINT16)0)
+#define HFA384x_RID_AUTHALGORITHMS_LEN ((UINT16)4)
+#define HFA384x_RID_PRIVACYOPTIMP_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE1_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE2_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE3_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE4_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE5_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTTXRATE6_LEN ((UINT16)0)
+#define HFA384x_RID_OWNMACADDRESS_LEN ((UINT16)6)
+#define HFA384x_RID_PCFINFO_LEN ((UINT16)6)
+#define HFA384x_RID_CNFAPPCFINFO_LEN ((UINT16)sizeof(hfa384x_PCFInfo_data_t))
+#define HFA384x_RID_SCANREQUEST_LEN ((UINT16)sizeof(hfa384x_ScanRequest_data_t))
+#define HFA384x_RID_JOINREQUEST_LEN ((UINT16)sizeof(hfa384x_JoinRequest_data_t))
+#define HFA384x_RID_AUTHENTICATESTA_LEN ((UINT16)sizeof(hfa384x_authenticateStation_data_t))
+#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((UINT16)sizeof(hfa384x_ChannelInfoRequest_data_t))
+/*--------------------------------------------------------------------
+Information RIDs: Modem Information
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PHYTYPE ((UINT16)0xFDC0)
+#define HFA384x_RID_CURRENTCHANNEL ((UINT16)0xFDC1)
+#define HFA384x_RID_CURRENTPOWERSTATE ((UINT16)0xFDC2)
+#define HFA384x_RID_CCAMODE ((UINT16)0xFDC3)
+#define HFA384x_RID_SUPPORTEDDATARATES ((UINT16)0xFDC6)
+#define HFA384x_RID_LFOSTATUS ((UINT16)0xFDC7) // 1.7.1
+
+/*--------------------------------------------------------------------
+Information RID Lengths: Modem Information
+ This is the length of JUST the DATA part of the RID (does not
+ include the len or code fields)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_PHYTYPE_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTCHANNEL_LEN ((UINT16)0)
+#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((UINT16)0)
+#define HFA384x_RID_CCAMODE_LEN ((UINT16)0)
+#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((UINT16)10)
+
+/*--------------------------------------------------------------------
+API ENHANCEMENTS (NOT ALREADY IMPLEMENTED)
+--------------------------------------------------------------------*/
+#define HFA384x_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23)
+#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((UINT16)0xFC24)
+#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((UINT16)0xFC25)
+#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((UINT16)0xFC26)
+#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((UINT16)0xFC27)
+#define HFA384x_RID_CNFWEPFLAGS ((UINT16)0xFC28)
+#define HFA384x_RID_CNFWEPKEYMAPTABLE ((UINT16)0xFC29)
+#define HFA384x_RID_CNFAUTHENTICATION ((UINT16)0xFC2A)
+#define HFA384x_RID_CNFMAXASSOCSTATIONS ((UINT16)0xFC2B)
+#define HFA384x_RID_CNFTXCONTROL ((UINT16)0xFC2C)
+#define HFA384x_RID_CNFROAMINGMODE ((UINT16)0xFC2D)
+#define HFA384x_RID_CNFHOSTAUTHASSOC ((UINT16)0xFC2E)
+#define HFA384x_RID_CNFRCVCRCERROR ((UINT16)0xFC30)
+// #define HFA384x_RID_CNFMMLIFE ((UINT16)0xFC31)
+#define HFA384x_RID_CNFALTRETRYCNT ((UINT16)0xFC32)
+#define HFA384x_RID_CNFAPBCNINT ((UINT16)0xFC33)
+#define HFA384x_RID_CNFAPPCFINFO ((UINT16)0xFC34)
+#define HFA384x_RID_CNFSTAPCFINFO ((UINT16)0xFC35)
+#define HFA384x_RID_CNFPRIORITYQUSAGE ((UINT16)0xFC37)
+#define HFA384x_RID_CNFTIMCTRL ((UINT16)0xFC40)
+#define HFA384x_RID_CNFTHIRTY2TALLY ((UINT16)0xFC42)
+#define HFA384x_RID_CNFENHSECURITY ((UINT16)0xFC43)
+#define HFA384x_RID_CNFDBMADJUST ((UINT16)0xFC46) // NEW
+#define HFA384x_RID_CNFWPADATA ((UINT16)0xFC48) // 1.7.0
+#define HFA384x_RID_CNFPROPOGATIONDELAY ((UINT16)0xFC49) // 1.7.6
+#define HFA384x_RID_CNFSHORTPREAMBLE ((UINT16)0xFCB0)
+#define HFA384x_RID_CNFEXCLONGPREAMBLE ((UINT16)0xFCB1)
+#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((UINT16)0xFCB2)
+#define HFA384x_RID_CNFBASICRATES ((UINT16)0xFCB3)
+#define HFA384x_RID_CNFSUPPRATES ((UINT16)0xFCB4)
+#define HFA384x_RID_CNFFALLBACKCTRL ((UINT16)0xFCB5) // NEW
+#define HFA384x_RID_WEPKEYSTATUS ((UINT16)0xFCB6) // NEW
+#define HFA384x_RID_WEPKEYMAPINDEX ((UINT16)0xFCB7) // NEW
+#define HFA384x_RID_BROADCASTKEYID ((UINT16)0xFCB8) // NEW
+#define HFA384x_RID_ENTSECFLAGEYID ((UINT16)0xFCB9) // NEW
+#define HFA384x_RID_CNFPASSIVESCANCTRL ((UINT16)0xFCBA) // NEW STA
+#define HFA384x_RID_CNFWPAHANDLING ((UINT16)0xFCBB) // 1.7.0
+#define HFA384x_RID_MDCCONTROL ((UINT16)0xFCBC) // 1.7.0/1.4.0
+#define HFA384x_RID_MDCCOUNTRY ((UINT16)0xFCBD) // 1.7.0/1.4.0
+#define HFA384x_RID_TXPOWERMAX ((UINT16)0xFCBE) // 1.7.0/1.4.0
+#define HFA384x_RID_CNFLFOENBLED ((UINT16)0xFCBF) // 1.6.3
+#define HFA384x_RID_CAPINFO ((UINT16)0xFCC0) // 1.7.0/1.3.7
+#define HFA384x_RID_LISTENINTERVAL ((UINT16)0xFCC1) // 1.7.0/1.3.7
+#define HFA384x_RID_DIVERSITYENABLED ((UINT16)0xFCC2) // 1.7.0/1.3.7
+#define HFA384x_RID_LED_CONTROL ((UINT16)0xFCC4) // 1.7.6
+#define HFA384x_RID_HFO_DELAY ((UINT16)0xFCC5) // 1.7.6
+#define HFA384x_RID_DISSALOWEDBSSID ((UINT16)0xFCC6) // 1.8.0
+#define HFA384x_RID_SCANREQUEST ((UINT16)0xFCE1)
+#define HFA384x_RID_JOINREQUEST ((UINT16)0xFCE2)
+#define HFA384x_RID_AUTHENTICATESTA ((UINT16)0xFCE3)
+#define HFA384x_RID_CHANNELINFOREQUEST ((UINT16)0xFCE4)
+#define HFA384x_RID_HOSTSCAN ((UINT16)0xFCE5) // NEW STA
+#define HFA384x_RID_ASSOCIATESTA ((UINT16)0xFCE6)
+
+#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((UINT16)6)
+#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((UINT16)14)
+#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((UINT16)4)
+/*--------------------------------------------------------------------
+PD Record codes
+--------------------------------------------------------------------*/
+#define HFA384x_PDR_PCB_PARTNUM ((UINT16)0x0001)
+#define HFA384x_PDR_PDAVER ((UINT16)0x0002)
+#define HFA384x_PDR_NIC_SERIAL ((UINT16)0x0003)
+#define HFA384x_PDR_MKK_MEASUREMENTS ((UINT16)0x0004)
+#define HFA384x_PDR_NIC_RAMSIZE ((UINT16)0x0005)
+#define HFA384x_PDR_MFISUPRANGE ((UINT16)0x0006)
+#define HFA384x_PDR_CFISUPRANGE ((UINT16)0x0007)
+#define HFA384x_PDR_NICID ((UINT16)0x0008)
+//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((UINT16)0x0010)
+//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((UINT16)0x0020)
+//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((UINT16)0x0030)
+//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((UINT16)0x0040)
+//#define HFA384x_PDR_COREGA_HACK ((UINT16)0x00ff)
+#define HFA384x_PDR_MAC_ADDRESS ((UINT16)0x0101)
+//#define HFA384x_PDR_MKK_CALLNAME ((UINT16)0x0102)
+#define HFA384x_PDR_REGDOMAIN ((UINT16)0x0103)
+#define HFA384x_PDR_ALLOWED_CHANNEL ((UINT16)0x0104)
+#define HFA384x_PDR_DEFAULT_CHANNEL ((UINT16)0x0105)
+//#define HFA384x_PDR_PRIVACY_OPTION ((UINT16)0x0106)
+#define HFA384x_PDR_TEMPTYPE ((UINT16)0x0107)
+//#define HFA384x_PDR_REFDAC_SETUP ((UINT16)0x0110)
+//#define HFA384x_PDR_VGDAC_SETUP ((UINT16)0x0120)
+//#define HFA384x_PDR_LEVEL_COMP_SETUP ((UINT16)0x0130)
+//#define HFA384x_PDR_TRIMDAC_SETUP ((UINT16)0x0140)
+#define HFA384x_PDR_IFR_SETTING ((UINT16)0x0200)
+#define HFA384x_PDR_RFR_SETTING ((UINT16)0x0201)
+#define HFA384x_PDR_HFA3861_BASELINE ((UINT16)0x0202)
+#define HFA384x_PDR_HFA3861_SHADOW ((UINT16)0x0203)
+#define HFA384x_PDR_HFA3861_IFRF ((UINT16)0x0204)
+#define HFA384x_PDR_HFA3861_CHCALSP ((UINT16)0x0300)
+#define HFA384x_PDR_HFA3861_CHCALI ((UINT16)0x0301)
+#define HFA384x_PDR_MAX_TX_POWER ((UINT16)0x0302)
+#define HFA384x_PDR_MASTER_CHAN_LIST ((UINT16)0x0303)
+#define HFA384x_PDR_3842_NIC_CONFIG ((UINT16)0x0400)
+#define HFA384x_PDR_USB_ID ((UINT16)0x0401)
+#define HFA384x_PDR_PCI_ID ((UINT16)0x0402)
+#define HFA384x_PDR_PCI_IFCONF ((UINT16)0x0403)
+#define HFA384x_PDR_PCI_PMCONF ((UINT16)0x0404)
+#define HFA384x_PDR_RFENRGY ((UINT16)0x0406)
+#define HFA384x_PDR_USB_POWER_TYPE ((UINT16)0x0407)
+//#define HFA384x_PDR_UNKNOWN408 ((UINT16)0x0408)
+#define HFA384x_PDR_USB_MAX_POWER ((UINT16)0x0409)
+#define HFA384x_PDR_USB_MANUFACTURER ((UINT16)0x0410)
+#define HFA384x_PDR_USB_PRODUCT ((UINT16)0x0411)
+#define HFA384x_PDR_ANT_DIVERSITY ((UINT16)0x0412)
+#define HFA384x_PDR_HFO_DELAY ((UINT16)0x0413)
+#define HFA384x_PDR_SCALE_THRESH ((UINT16)0x0414)
+
+#define HFA384x_PDR_HFA3861_MANF_TESTSP ((UINT16)0x0900)
+#define HFA384x_PDR_HFA3861_MANF_TESTI ((UINT16)0x0901)
+#define HFA384x_PDR_END_OF_PDA ((UINT16)0x0000)
+
+
+/*=============================================================*/
+/*------ Macros -----------------------------------------------*/
+
+/*--- Register ID macros ------------------------*/
+
+#define HFA384x_CMD HFA384x_CMD_OFF
+#define HFA384x_PARAM0 HFA384x_PARAM0_OFF
+#define HFA384x_PARAM1 HFA384x_PARAM1_OFF
+#define HFA384x_PARAM2 HFA384x_PARAM2_OFF
+#define HFA384x_STATUS HFA384x_STATUS_OFF
+#define HFA384x_RESP0 HFA384x_RESP0_OFF
+#define HFA384x_RESP1 HFA384x_RESP1_OFF
+#define HFA384x_RESP2 HFA384x_RESP2_OFF
+#define HFA384x_INFOFID HFA384x_INFOFID_OFF
+#define HFA384x_RXFID HFA384x_RXFID_OFF
+#define HFA384x_ALLOCFID HFA384x_ALLOCFID_OFF
+#define HFA384x_TXCOMPLFID HFA384x_TXCOMPLFID_OFF
+#define HFA384x_SELECT0 HFA384x_SELECT0_OFF
+#define HFA384x_OFFSET0 HFA384x_OFFSET0_OFF
+#define HFA384x_DATA0 HFA384x_DATA0_OFF
+#define HFA384x_SELECT1 HFA384x_SELECT1_OFF
+#define HFA384x_OFFSET1 HFA384x_OFFSET1_OFF
+#define HFA384x_DATA1 HFA384x_DATA1_OFF
+#define HFA384x_EVSTAT HFA384x_EVSTAT_OFF
+#define HFA384x_INTEN HFA384x_INTEN_OFF
+#define HFA384x_EVACK HFA384x_EVACK_OFF
+#define HFA384x_CONTROL HFA384x_CONTROL_OFF
+#define HFA384x_SWSUPPORT0 HFA384x_SWSUPPORT0_OFF
+#define HFA384x_SWSUPPORT1 HFA384x_SWSUPPORT1_OFF
+#define HFA384x_SWSUPPORT2 HFA384x_SWSUPPORT2_OFF
+#define HFA384x_AUXPAGE HFA384x_AUXPAGE_OFF
+#define HFA384x_AUXOFFSET HFA384x_AUXOFFSET_OFF
+#define HFA384x_AUXDATA HFA384x_AUXDATA_OFF
+#define HFA384x_PCICOR HFA384x_PCICOR_OFF
+#define HFA384x_PCIHCR HFA384x_PCIHCR_OFF
+
+
+/*--- Register Test/Get/Set Field macros ------------------------*/
+
+#define HFA384x_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & HFA384x_CMD_BUSY))
+#define HFA384x_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & HFA384x_CMD_AINFO) >> 8))
+#define HFA384x_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8))
+#define HFA384x_CMD_MACPORT_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_MACPORT)))
+#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
+#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL)))
+#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value))
+#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12))
+#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000))
+#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE)))
+#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value))
+#define HFA384x_CMD_PROGMODE_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_PROGMODE)))
+#define HFA384x_CMD_PROGMODE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value))
+#define HFA384x_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_CMD_CMDCODE))
+#define HFA384x_CMD_CMDCODE_SET(value) ((UINT16)(value))
+
+#define HFA384x_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_STATUS_RESULT) >> 8))
+#define HFA384x_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8)
+#define HFA384x_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & HFA384x_STATUS_CMDCODE)
+#define HFA384x_STATUS_CMDCODE_SET(value) ((UINT16)(value))
+
+#define HFA384x_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_BUSY))
+#define HFA384x_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_ERR))
+#define HFA384x_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_DATAOFF))
+#define HFA384x_OFFSET_DATAOFF_SET(value) ((UINT16)(value))
+
+#define HFA384x_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TICK))
+#define HFA384x_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_WTERR))
+#define HFA384x_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFDROP))
+#define HFA384x_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFO))
+#define HFA384x_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_DTIM))
+#define HFA384x_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_CMD))
+#define HFA384x_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_ALLOC))
+#define HFA384x_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TXEXC))
+#define HFA384x_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TX))
+#define HFA384x_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_RX))
+
+#define HFA384x_EVSTAT_ISBAP_OP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INT_BAP_OP))
+
+#define HFA384x_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TICK))
+#define HFA384x_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define HFA384x_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_WTERR))
+#define HFA384x_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFDROP))
+#define HFA384x_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFO))
+#define HFA384x_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define HFA384x_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_DTIM))
+#define HFA384x_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define HFA384x_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_CMD))
+#define HFA384x_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define HFA384x_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_ALLOC))
+#define HFA384x_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define HFA384x_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TXEXC))
+#define HFA384x_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define HFA384x_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TX))
+#define HFA384x_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define HFA384x_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_RX))
+#define HFA384x_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define HFA384x_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TICK))
+#define HFA384x_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define HFA384x_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_WTERR))
+#define HFA384x_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFDROP))
+#define HFA384x_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFO))
+#define HFA384x_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define HFA384x_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_DTIM))
+#define HFA384x_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define HFA384x_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_CMD))
+#define HFA384x_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define HFA384x_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_ALLOC))
+#define HFA384x_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define HFA384x_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TXEXC))
+#define HFA384x_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define HFA384x_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TX))
+#define HFA384x_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define HFA384x_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_RX))
+#define HFA384x_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define HFA384x_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define HFA384x_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14))
+
+/* Byte Order */
+#ifdef __KERNEL__
+#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n)))
+#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n)))
+#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n)))
+#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n)))
+#endif
+
+/* Host Maintained State Info */
+#define HFA384x_STATE_PREINIT 0
+#define HFA384x_STATE_INIT 1
+#define HFA384x_STATE_RUNNING 2
+
+/*=============================================================*/
+/*------ Types and their related constants --------------------*/
+
+#define HFA384x_HOSTAUTHASSOC_HOSTAUTH BIT0
+#define HFA384x_HOSTAUTHASSOC_HOSTASSOC BIT1
+
+#define HFA384x_WHAHANDLING_DISABLED 0
+#define HFA384x_WHAHANDLING_PASSTHROUGH BIT1
+
+/*-------------------------------------------------------------*/
+/* Commonly used basic types */
+typedef struct hfa384x_bytestr
+{
+ UINT16 len;
+ UINT8 data[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t;
+
+typedef struct hfa384x_bytestr32
+{
+ UINT16 len;
+ UINT8 data[32];
+} __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures:
+ Network Parameters, Static Configuration Entities
+--------------------------------------------------------------------*/
+/* Prototype structure: all configuration record structures start with
+these members */
+
+typedef struct hfa384x_record
+{
+ UINT16 reclen;
+ UINT16 rid;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec_t;
+
+typedef struct hfa384x_record16
+{
+ UINT16 reclen;
+ UINT16 rid;
+ UINT16 val;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t;
+
+typedef struct hfa384x_record32
+{
+ UINT16 reclen;
+ UINT16 rid;
+ UINT32 val;
+} __WLAN_ATTRIB_PACK__ hfa384x_rec32;
+
+/*-- Hardware/Firmware Component Information ----------*/
+typedef struct hfa384x_compident
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 major;
+ UINT16 minor;
+} __WLAN_ATTRIB_PACK__ hfa384x_compident_t;
+
+typedef struct hfa384x_caplevel
+{
+ UINT16 role;
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t;
+
+/*-- Configuration Record: cnfPortType --*/
+typedef struct hfa384x_cnfPortType
+{
+ UINT16 cnfPortType;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t;
+
+/*-- Configuration Record: cnfOwnMACAddress --*/
+typedef struct hfa384x_cnfOwnMACAddress
+{
+ UINT8 cnfOwnMACAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t;
+
+/*-- Configuration Record: cnfDesiredSSID --*/
+typedef struct hfa384x_cnfDesiredSSID
+{
+ UINT8 cnfDesiredSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t;
+
+/*-- Configuration Record: cnfOwnChannel --*/
+typedef struct hfa384x_cnfOwnChannel
+{
+ UINT16 cnfOwnChannel;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t;
+
+/*-- Configuration Record: cnfOwnSSID --*/
+typedef struct hfa384x_cnfOwnSSID
+{
+ UINT8 cnfOwnSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t;
+
+/*-- Configuration Record: cnfOwnATIMWindow --*/
+typedef struct hfa384x_cnfOwnATIMWindow
+{
+ UINT16 cnfOwnATIMWindow;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t;
+
+/*-- Configuration Record: cnfSystemScale --*/
+typedef struct hfa384x_cnfSystemScale
+{
+ UINT16 cnfSystemScale;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t;
+
+/*-- Configuration Record: cnfMaxDataLength --*/
+typedef struct hfa384x_cnfMaxDataLength
+{
+ UINT16 cnfMaxDataLength;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t;
+
+/*-- Configuration Record: cnfWDSAddress --*/
+typedef struct hfa384x_cnfWDSAddress
+{
+ UINT8 cnfWDSAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t;
+
+/*-- Configuration Record: cnfPMEnabled --*/
+typedef struct hfa384x_cnfPMEnabled
+{
+ UINT16 cnfPMEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t;
+
+/*-- Configuration Record: cnfPMEPS --*/
+typedef struct hfa384x_cnfPMEPS
+{
+ UINT16 cnfPMEPS;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t;
+
+/*-- Configuration Record: cnfMulticastReceive --*/
+typedef struct hfa384x_cnfMulticastReceive
+{
+ UINT16 cnfMulticastReceive;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t;
+
+/*-- Configuration Record: cnfAuthentication --*/
+#define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001
+#define HFA384x_CNFAUTHENTICATION_SHAREDKEY 0x0002
+#define HFA384x_CNFAUTHENTICATION_LEAP 0x0004
+
+/*-- Configuration Record: cnfMaxSleepDuration --*/
+typedef struct hfa384x_cnfMaxSleepDuration
+{
+ UINT16 cnfMaxSleepDuration;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t;
+
+/*-- Configuration Record: cnfPMHoldoverDuration --*/
+typedef struct hfa384x_cnfPMHoldoverDuration
+{
+ UINT16 cnfPMHoldoverDuration;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t;
+
+/*-- Configuration Record: cnfOwnName --*/
+typedef struct hfa384x_cnfOwnName
+{
+ UINT8 cnfOwnName[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t;
+
+/*-- Configuration Record: cnfOwnDTIMPeriod --*/
+typedef struct hfa384x_cnfOwnDTIMPeriod
+{
+ UINT16 cnfOwnDTIMPeriod;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t;
+
+/*-- Configuration Record: cnfWDSAddress --*/
+typedef struct hfa384x_cnfWDSAddressN
+{
+ UINT8 cnfWDSAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t;
+
+/*-- Configuration Record: cnfMulticastPMBuffering --*/
+typedef struct hfa384x_cnfMulticastPMBuffering
+{
+ UINT16 cnfMulticastPMBuffering;
+} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures:
+ Network Parameters, Dynamic Configuration Entities
+--------------------------------------------------------------------*/
+
+/*-- Configuration Record: GroupAddresses --*/
+typedef struct hfa384x_GroupAddresses
+{
+ UINT8 MACAddress[16][6];
+} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t;
+
+/*-- Configuration Record: CreateIBSS --*/
+typedef struct hfa384x_CreateIBSS
+{
+ UINT16 CreateIBSS;
+} __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t;
+
+#define HFA384x_CREATEIBSS_JOINCREATEIBSS 0
+#define HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS 1
+#define HFA384x_CREATEIBSS_JOINIBSS 2
+#define HFA384x_CREATEIBSS_JOINESS_JOINIBSS 3
+
+/*-- Configuration Record: FragmentationThreshold --*/
+typedef struct hfa384x_FragmentationThreshold
+{
+ UINT16 FragmentationThreshold;
+} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t;
+
+/*-- Configuration Record: RTSThreshold --*/
+typedef struct hfa384x_RTSThreshold
+{
+ UINT16 RTSThreshold;
+} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t;
+
+/*-- Configuration Record: TxRateControl --*/
+typedef struct hfa384x_TxRateControl
+{
+ UINT16 TxRateControl;
+} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t;
+
+/*-- Configuration Record: PromiscuousMode --*/
+typedef struct hfa384x_PromiscuousMode
+{
+ UINT16 PromiscuousMode;
+} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t;
+
+/*-- Configuration Record: ScanRequest (data portion only) --*/
+typedef struct hfa384x_ScanRequest_data
+{
+ UINT16 channelList;
+ UINT16 txRate;
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t;
+
+/*-- Configuration Record: HostScanRequest (data portion only) --*/
+typedef struct hfa384x_HostScanRequest_data
+{
+ UINT16 channelList;
+ UINT16 txRate;
+ hfa384x_bytestr32_t ssid;
+} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t;
+
+/*-- Configuration Record: JoinRequest (data portion only) --*/
+typedef struct hfa384x_JoinRequest_data
+{
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 channel;
+} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t;
+
+/*-- Configuration Record: authenticateStation (data portion only) --*/
+typedef struct hfa384x_authenticateStation_data
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 status;
+ UINT16 algorithm;
+} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t;
+
+/*-- Configuration Record: associateStation (data portion only) --*/
+typedef struct hfa384x_associateStation_data
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 status;
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t;
+
+/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/
+typedef struct hfa384x_ChannelInfoRequest_data
+{
+ UINT16 channelList;
+ UINT16 channelDwellTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t;
+
+/*-- Configuration Record: WEPKeyMapping (data portion only) --*/
+typedef struct hfa384x_WEPKeyMapping
+{
+ UINT8 address[WLAN_ADDR_LEN];
+ UINT16 key_index;
+ UINT8 key[16];
+ UINT8 mic_transmit_key[4];
+ UINT8 mic_receive_key[4];
+} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t;
+
+/*-- Configuration Record: WPAData (data portion only) --*/
+typedef struct hfa384x_WPAData
+{
+ UINT16 datalen;
+ UINT8 data[0]; // max 80
+} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t;
+
+/*--------------------------------------------------------------------
+Configuration Record Structures: Behavior Parameters
+--------------------------------------------------------------------*/
+
+/*-- Configuration Record: TickTime --*/
+typedef struct hfa384x_TickTime
+{
+ UINT16 TickTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: NIC Information
+--------------------------------------------------------------------*/
+
+/*-- Information Record: MaxLoadTime --*/
+typedef struct hfa384x_MaxLoadTime
+{
+ UINT16 MaxLoadTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t;
+
+/*-- Information Record: DownLoadBuffer --*/
+/* NOTE: The page and offset are in AUX format */
+typedef struct hfa384x_downloadbuffer
+{
+ UINT16 page;
+ UINT16 offset;
+ UINT16 len;
+} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t;
+
+/*-- Information Record: PRIIdentity --*/
+typedef struct hfa384x_PRIIdentity
+{
+ UINT16 PRICompID;
+ UINT16 PRIVariant;
+ UINT16 PRIMajorVersion;
+ UINT16 PRIMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t;
+
+/*-- Information Record: PRISupRange --*/
+typedef struct hfa384x_PRISupRange
+{
+ UINT16 PRIRole;
+ UINT16 PRIID;
+ UINT16 PRIVariant;
+ UINT16 PRIBottom;
+ UINT16 PRITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t;
+
+/*-- Information Record: CFIActRanges --*/
+typedef struct hfa384x_CFIActRanges
+{
+ UINT16 CFIRole;
+ UINT16 CFIID;
+ UINT16 CFIVariant;
+ UINT16 CFIBottom;
+ UINT16 CFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t;
+
+/*-- Information Record: NICSerialNumber --*/
+typedef struct hfa384x_NICSerialNumber
+{
+ UINT8 NICSerialNumber[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t;
+
+/*-- Information Record: NICIdentity --*/
+typedef struct hfa384x_NICIdentity
+{
+ UINT16 NICCompID;
+ UINT16 NICVariant;
+ UINT16 NICMajorVersion;
+ UINT16 NICMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t;
+
+/*-- Information Record: MFISupRange --*/
+typedef struct hfa384x_MFISupRange
+{
+ UINT16 MFIRole;
+ UINT16 MFIID;
+ UINT16 MFIVariant;
+ UINT16 MFIBottom;
+ UINT16 MFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t;
+
+/*-- Information Record: CFISupRange --*/
+typedef struct hfa384x_CFISupRange
+{
+ UINT16 CFIRole;
+ UINT16 CFIID;
+ UINT16 CFIVariant;
+ UINT16 CFIBottom;
+ UINT16 CFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t;
+
+/*-- Information Record: BUILDSEQ:BuildSeq --*/
+typedef struct hfa384x_BuildSeq {
+ UINT16 primary;
+ UINT16 secondary;
+} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t;
+
+/*-- Information Record: FWID --*/
+#define HFA384x_FWID_LEN 14
+typedef struct hfa384x_FWID {
+ UINT8 primary[HFA384x_FWID_LEN];
+ UINT8 secondary[HFA384x_FWID_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t;
+
+/*-- Information Record: ChannelList --*/
+typedef struct hfa384x_ChannelList
+{
+ UINT16 ChannelList;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t;
+
+/*-- Information Record: RegulatoryDomains --*/
+typedef struct hfa384x_RegulatoryDomains
+{
+ UINT8 RegulatoryDomains[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t;
+
+/*-- Information Record: TempType --*/
+typedef struct hfa384x_TempType
+{
+ UINT16 TempType;
+} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t;
+
+/*-- Information Record: CIS --*/
+typedef struct hfa384x_CIS
+{
+ UINT8 CIS[480];
+} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t;
+
+/*-- Information Record: STAIdentity --*/
+typedef struct hfa384x_STAIdentity
+{
+ UINT16 STACompID;
+ UINT16 STAVariant;
+ UINT16 STAMajorVersion;
+ UINT16 STAMinorVersion;
+} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t;
+
+/*-- Information Record: STASupRange --*/
+typedef struct hfa384x_STASupRange
+{
+ UINT16 STARole;
+ UINT16 STAID;
+ UINT16 STAVariant;
+ UINT16 STABottom;
+ UINT16 STATop;
+} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t;
+
+/*-- Information Record: MFIActRanges --*/
+typedef struct hfa384x_MFIActRanges
+{
+ UINT16 MFIRole;
+ UINT16 MFIID;
+ UINT16 MFIVariant;
+ UINT16 MFIBottom;
+ UINT16 MFITop;
+} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: NIC Information
+--------------------------------------------------------------------*/
+
+/*-- Information Record: PortStatus --*/
+typedef struct hfa384x_PortStatus
+{
+ UINT16 PortStatus;
+} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t;
+
+#define HFA384x_PSTATUS_DISABLED ((UINT16)1)
+#define HFA384x_PSTATUS_SEARCHING ((UINT16)2)
+#define HFA384x_PSTATUS_CONN_IBSS ((UINT16)3)
+#define HFA384x_PSTATUS_CONN_ESS ((UINT16)4)
+#define HFA384x_PSTATUS_OUTOFRANGE ((UINT16)5)
+#define HFA384x_PSTATUS_CONN_WDS ((UINT16)6)
+
+/*-- Information Record: CurrentSSID --*/
+typedef struct hfa384x_CurrentSSID
+{
+ UINT8 CurrentSSID[34];
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t;
+
+/*-- Information Record: CurrentBSSID --*/
+typedef struct hfa384x_CurrentBSSID
+{
+ UINT8 CurrentBSSID[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t;
+
+/*-- Information Record: commsquality --*/
+typedef struct hfa384x_commsquality
+{
+ UINT16 CQ_currBSS;
+ UINT16 ASL_currBSS;
+ UINT16 ANL_currFC;
+} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t;
+
+/*-- Information Record: dmbcommsquality --*/
+typedef struct hfa384x_dbmcommsquality
+{
+ UINT16 CQdbm_currBSS;
+ UINT16 ASLdbm_currBSS;
+ UINT16 ANLdbm_currFC;
+} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t;
+
+/*-- Information Record: CurrentTxRate --*/
+typedef struct hfa384x_CurrentTxRate
+{
+ UINT16 CurrentTxRate;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t;
+
+/*-- Information Record: CurrentBeaconInterval --*/
+typedef struct hfa384x_CurrentBeaconInterval
+{
+ UINT16 CurrentBeaconInterval;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t;
+
+/*-- Information Record: CurrentScaleThresholds --*/
+typedef struct hfa384x_CurrentScaleThresholds
+{
+ UINT16 EnergyDetectThreshold;
+ UINT16 CarrierDetectThreshold;
+ UINT16 DeferDetectThreshold;
+ UINT16 CellSearchThreshold; /* Stations only */
+ UINT16 DeadSpotThreshold; /* Stations only */
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t;
+
+/*-- Information Record: ProtocolRspTime --*/
+typedef struct hfa384x_ProtocolRspTime
+{
+ UINT16 ProtocolRspTime;
+} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t;
+
+/*-- Information Record: ShortRetryLimit --*/
+typedef struct hfa384x_ShortRetryLimit
+{
+ UINT16 ShortRetryLimit;
+} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t;
+
+/*-- Information Record: LongRetryLimit --*/
+typedef struct hfa384x_LongRetryLimit
+{
+ UINT16 LongRetryLimit;
+} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t;
+
+/*-- Information Record: MaxTransmitLifetime --*/
+typedef struct hfa384x_MaxTransmitLifetime
+{
+ UINT16 MaxTransmitLifetime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t;
+
+/*-- Information Record: MaxReceiveLifetime --*/
+typedef struct hfa384x_MaxReceiveLifetime
+{
+ UINT16 MaxReceiveLifetime;
+} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t;
+
+/*-- Information Record: CFPollable --*/
+typedef struct hfa384x_CFPollable
+{
+ UINT16 CFPollable;
+} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t;
+
+/*-- Information Record: AuthenticationAlgorithms --*/
+typedef struct hfa384x_AuthenticationAlgorithms
+{
+ UINT16 AuthenticationType;
+ UINT16 TypeEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t;
+
+/*-- Information Record: AuthenticationAlgorithms
+(data only --*/
+typedef struct hfa384x_AuthenticationAlgorithms_data
+{
+ UINT16 AuthenticationType;
+ UINT16 TypeEnabled;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t;
+
+/*-- Information Record: PrivacyOptionImplemented --*/
+typedef struct hfa384x_PrivacyOptionImplemented
+{
+ UINT16 PrivacyOptionImplemented;
+} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t;
+
+/*-- Information Record: OwnMACAddress --*/
+typedef struct hfa384x_OwnMACAddress
+{
+ UINT8 OwnMACAddress[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t;
+
+/*-- Information Record: PCFInfo --*/
+typedef struct hfa384x_PCFInfo
+{
+ UINT16 MediumOccupancyLimit;
+ UINT16 CFPPeriod;
+ UINT16 CFPMaxDuration;
+ UINT16 CFPFlags;
+} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t;
+
+/*-- Information Record: PCFInfo (data portion only) --*/
+typedef struct hfa384x_PCFInfo_data
+{
+ UINT16 MediumOccupancyLimit;
+ UINT16 CFPPeriod;
+ UINT16 CFPMaxDuration;
+ UINT16 CFPFlags;
+} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t;
+
+/*--------------------------------------------------------------------
+Information Record Structures: Modem Information Records
+--------------------------------------------------------------------*/
+
+/*-- Information Record: PHYType --*/
+typedef struct hfa384x_PHYType
+{
+ UINT16 PHYType;
+} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t;
+
+/*-- Information Record: CurrentChannel --*/
+typedef struct hfa384x_CurrentChannel
+{
+ UINT16 CurrentChannel;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t;
+
+/*-- Information Record: CurrentPowerState --*/
+typedef struct hfa384x_CurrentPowerState
+{
+ UINT16 CurrentPowerState;
+} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t;
+
+/*-- Information Record: CCAMode --*/
+typedef struct hfa384x_CCAMode
+{
+ UINT16 CCAMode;
+} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t;
+
+/*-- Information Record: SupportedDataRates --*/
+typedef struct hfa384x_SupportedDataRates
+{
+ UINT8 SupportedDataRates[10];
+} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t;
+
+/*-- Information Record: LFOStatus --*/
+typedef struct hfa384x_LFOStatus
+{
+ UINT16 TestResults;
+ UINT16 LFOResult;
+ UINT16 VRHFOResult;
+} __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t;
+
+#define HFA384x_TESTRESULT_ALLPASSED BIT0
+#define HFA384x_TESTRESULT_LFO_FAIL BIT1
+#define HFA384x_TESTRESULT_VR_HF0_FAIL BIT2
+#define HFA384x_HOST_FIRM_COORDINATE BIT7
+#define HFA384x_TESTRESULT_COORDINATE BIT15
+
+/*-- Information Record: LEDControl --*/
+typedef struct hfa384x_LEDControl
+{
+ UINT16 searching_on;
+ UINT16 searching_off;
+ UINT16 assoc_on;
+ UINT16 assoc_off;
+ UINT16 activity;
+} __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t;
+
+/*--------------------------------------------------------------------
+ FRAME DESCRIPTORS AND FRAME STRUCTURES
+
+FRAME DESCRIPTORS: Offsets
+
+----------------------------------------------------------------------
+Control Info (offset 44-51)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_STATUS_OFF ((UINT16)0x44)
+#define HFA384x_FD_TIME_OFF ((UINT16)0x46)
+#define HFA384x_FD_SWSUPPORT_OFF ((UINT16)0x4A)
+#define HFA384x_FD_SILENCE_OFF ((UINT16)0x4A)
+#define HFA384x_FD_SIGNAL_OFF ((UINT16)0x4B)
+#define HFA384x_FD_RATE_OFF ((UINT16)0x4C)
+#define HFA384x_FD_RXFLOW_OFF ((UINT16)0x4D)
+#define HFA384x_FD_RESERVED_OFF ((UINT16)0x4E)
+#define HFA384x_FD_TXCONTROL_OFF ((UINT16)0x50)
+/*--------------------------------------------------------------------
+802.11 Header (offset 52-6B)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_FRAMECONTROL_OFF ((UINT16)0x52)
+#define HFA384x_FD_DURATIONID_OFF ((UINT16)0x54)
+#define HFA384x_FD_ADDRESS1_OFF ((UINT16)0x56)
+#define HFA384x_FD_ADDRESS2_OFF ((UINT16)0x5C)
+#define HFA384x_FD_ADDRESS3_OFF ((UINT16)0x62)
+#define HFA384x_FD_SEQCONTROL_OFF ((UINT16)0x68)
+#define HFA384x_FD_ADDRESS4_OFF ((UINT16)0x6A)
+#define HFA384x_FD_DATALEN_OFF ((UINT16)0x70)
+/*--------------------------------------------------------------------
+802.3 Header (offset 72-7F)
+--------------------------------------------------------------------*/
+#define HFA384x_FD_DESTADDRESS_OFF ((UINT16)0x72)
+#define HFA384x_FD_SRCADDRESS_OFF ((UINT16)0x78)
+#define HFA384x_FD_DATALENGTH_OFF ((UINT16)0x7E)
+
+/*--------------------------------------------------------------------
+FRAME STRUCTURES: Communication Frames
+----------------------------------------------------------------------
+Communication Frames: Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Communication Frame: Transmit Frame Structure --*/
+typedef struct hfa384x_tx_frame
+{
+ UINT16 status;
+ UINT16 reserved1;
+ UINT16 reserved2;
+ UINT32 sw_support;
+ UINT8 tx_retrycount;
+ UINT8 tx_rate;
+ UINT16 tx_control;
+
+ /*-- 802.11 Header Information --*/
+
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* little endian format */
+
+ /*-- 802.3 Header Information --*/
+
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* big endian format */
+} __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t;
+/*--------------------------------------------------------------------
+Communication Frames: Field Masks for Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Status Field --*/
+#define HFA384x_TXSTATUS_ACKERR ((UINT16)BIT5)
+#define HFA384x_TXSTATUS_FORMERR ((UINT16)BIT3)
+#define HFA384x_TXSTATUS_DISCON ((UINT16)BIT2)
+#define HFA384x_TXSTATUS_AGEDERR ((UINT16)BIT1)
+#define HFA384x_TXSTATUS_RETRYERR ((UINT16)BIT0)
+/*-- Transmit Control Field --*/
+#define HFA384x_TX_CFPOLL ((UINT16)BIT12)
+#define HFA384x_TX_PRST ((UINT16)BIT11)
+#define HFA384x_TX_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_TX_NOENCRYPT ((UINT16)BIT7)
+#define HFA384x_TX_RETRYSTRAT ((UINT16)(BIT6 | BIT5))
+#define HFA384x_TX_STRUCTYPE ((UINT16)(BIT4 | BIT3))
+#define HFA384x_TX_TXEX ((UINT16)BIT2)
+#define HFA384x_TX_TXOK ((UINT16)BIT1)
+/*--------------------------------------------------------------------
+Communication Frames: Test/Get/Set Field Values for Transmit Frames
+--------------------------------------------------------------------*/
+/*-- Status Field --*/
+#define HFA384x_TXSTATUS_ISERROR(v) \
+ (((UINT16)(v))&\
+ (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\
+ HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\
+ HFA384x_TXSTATUS_RETRYERR))
+
+#define HFA384x_TXSTATUS_ISACKERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_ACKERR))
+#define HFA384x_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_FORMERR))
+#define HFA384x_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_DISCON))
+#define HFA384x_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_AGEDERR))
+#define HFA384x_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_RETRYERR))
+
+#define HFA384x_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s)))
+#define HFA384x_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m)))
+
+#define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12)
+#define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12)
+#define HFA384x_TX_PRST_GET(v) HFA384x_TX_GET(v, HFA384x_TX_PRST,11)
+#define HFA384x_TX_PRST_SET(v) HFA384x_TX_SET(v, HFA384x_TX_PRST,11)
+#define HFA384x_TX_MACPORT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_MACPORT, 8)
+#define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8)
+#define HFA384x_TX_NOENCRYPT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_NOENCRYPT, 7)
+#define HFA384x_TX_NOENCRYPT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_NOENCRYPT, 7)
+#define HFA384x_TX_RETRYSTRAT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_RETRYSTRAT, 5)
+#define HFA384x_TX_RETRYSTRAT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_RETRYSTRAT, 5)
+#define HFA384x_TX_STRUCTYPE_GET(v) HFA384x_TX_GET(v, HFA384x_TX_STRUCTYPE, 3)
+#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3)
+#define HFA384x_TX_TXEX_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXEX, 2)
+#define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2)
+#define HFA384x_TX_TXOK_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXOK, 1)
+#define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1)
+/*--------------------------------------------------------------------
+Communication Frames: Receive Frames
+--------------------------------------------------------------------*/
+/*-- Communication Frame: Receive Frame Structure --*/
+typedef struct hfa384x_rx_frame
+{
+ /*-- MAC rx descriptor (hfa384x byte order) --*/
+ UINT16 status;
+ UINT32 time;
+ UINT8 silence;
+ UINT8 signal;
+ UINT8 rate;
+ UINT8 rx_flow;
+ UINT16 reserved1;
+ UINT16 reserved2;
+
+ /*-- 802.11 Header Information (802.11 byte order) --*/
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* hfa384x (little endian) format */
+
+ /*-- 802.3 Header Information --*/
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* IEEE? (big endian) format */
+} __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t;
+/*--------------------------------------------------------------------
+Communication Frames: Field Masks for Receive Frames
+--------------------------------------------------------------------*/
+/*-- Offsets --------*/
+#define HFA384x_RX_DATA_LEN_OFF ((UINT16)44)
+#define HFA384x_RX_80211HDR_OFF ((UINT16)14)
+#define HFA384x_RX_DATA_OFF ((UINT16)60)
+
+/*-- Status Fields --*/
+#define HFA384x_RXSTATUS_MSGTYPE ((UINT16)(BIT15 | BIT14 | BIT13))
+#define HFA384x_RXSTATUS_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8))
+#define HFA384x_RXSTATUS_UNDECR ((UINT16)BIT1)
+#define HFA384x_RXSTATUS_FCSERR ((UINT16)BIT0)
+/*--------------------------------------------------------------------
+Communication Frames: Test/Get/Set Field Values for Receive Frames
+--------------------------------------------------------------------*/
+#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13))
+#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define HFA384x_RXSTATUS_MACPORT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8))
+#define HFA384x_RXSTATUS_MACPORT_SET(value) ((UINT16)(((UINT16)(value)) << 8))
+#define HFA384x_RXSTATUS_ISUNDECR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_UNDECR))
+#define HFA384x_RXSTATUS_ISFCSERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_FCSERR))
+/*--------------------------------------------------------------------
+ FRAME STRUCTURES: Information Types and Information Frame Structures
+----------------------------------------------------------------------
+Information Types
+--------------------------------------------------------------------*/
+#define HFA384x_IT_HANDOVERADDR ((UINT16)0xF000UL)
+#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((UINT16)0xF001UL)//AP 1.3.7
+#define HFA384x_IT_COMMTALLIES ((UINT16)0xF100UL)
+#define HFA384x_IT_SCANRESULTS ((UINT16)0xF101UL)
+#define HFA384x_IT_CHINFORESULTS ((UINT16)0xF102UL)
+#define HFA384x_IT_HOSTSCANRESULTS ((UINT16)0xF103UL)
+#define HFA384x_IT_LINKSTATUS ((UINT16)0xF200UL)
+#define HFA384x_IT_ASSOCSTATUS ((UINT16)0xF201UL)
+#define HFA384x_IT_AUTHREQ ((UINT16)0xF202UL)
+#define HFA384x_IT_PSUSERCNT ((UINT16)0xF203UL)
+#define HFA384x_IT_KEYIDCHANGED ((UINT16)0xF204UL)
+#define HFA384x_IT_ASSOCREQ ((UINT16)0xF205UL)
+#define HFA384x_IT_MICFAILURE ((UINT16)0xF206UL)
+
+/*--------------------------------------------------------------------
+Information Frames Structures
+----------------------------------------------------------------------
+Information Frames: Notification Frame Structures
+--------------------------------------------------------------------*/
+/*-- Notification Frame,MAC Mgmt: Handover Address --*/
+typedef struct hfa384x_HandoverAddr
+{
+ UINT16 framelen;
+ UINT16 infotype;
+ UINT8 handover_addr[WLAN_BSSID_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t;
+
+/*-- Inquiry Frame, Diagnose: Communication Tallies --*/
+typedef struct hfa384x_CommTallies16
+{
+ UINT16 txunicastframes;
+ UINT16 txmulticastframes;
+ UINT16 txfragments;
+ UINT16 txunicastoctets;
+ UINT16 txmulticastoctets;
+ UINT16 txdeferredtrans;
+ UINT16 txsingleretryframes;
+ UINT16 txmultipleretryframes;
+ UINT16 txretrylimitexceeded;
+ UINT16 txdiscards;
+ UINT16 rxunicastframes;
+ UINT16 rxmulticastframes;
+ UINT16 rxfragments;
+ UINT16 rxunicastoctets;
+ UINT16 rxmulticastoctets;
+ UINT16 rxfcserrors;
+ UINT16 rxdiscardsnobuffer;
+ UINT16 txdiscardswrongsa;
+ UINT16 rxdiscardswepundecr;
+ UINT16 rxmsginmsgfrag;
+ UINT16 rxmsginbadmsgfrag;
+} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t;
+
+typedef struct hfa384x_CommTallies32
+{
+ UINT32 txunicastframes;
+ UINT32 txmulticastframes;
+ UINT32 txfragments;
+ UINT32 txunicastoctets;
+ UINT32 txmulticastoctets;
+ UINT32 txdeferredtrans;
+ UINT32 txsingleretryframes;
+ UINT32 txmultipleretryframes;
+ UINT32 txretrylimitexceeded;
+ UINT32 txdiscards;
+ UINT32 rxunicastframes;
+ UINT32 rxmulticastframes;
+ UINT32 rxfragments;
+ UINT32 rxunicastoctets;
+ UINT32 rxmulticastoctets;
+ UINT32 rxfcserrors;
+ UINT32 rxdiscardsnobuffer;
+ UINT32 txdiscardswrongsa;
+ UINT32 rxdiscardswepundecr;
+ UINT32 rxmsginmsgfrag;
+ UINT32 rxmsginbadmsgfrag;
+} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t;
+
+/*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/
+typedef struct hfa384x_ScanResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 sl;
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 bcnint;
+ UINT16 capinfo;
+ hfa384x_bytestr32_t ssid;
+ UINT8 supprates[10]; /* 802.11 info element */
+ UINT16 proberesp_rate;
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t;
+
+typedef struct hfa384x_ScanResult
+{
+ UINT16 rsvd;
+ UINT16 scanreason;
+ hfa384x_ScanResultSub_t
+ result[HFA384x_SCANRESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t;
+
+/*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/
+typedef struct hfa384x_ChInfoResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 pnl;
+ UINT16 active;
+} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t;
+
+#define HFA384x_CHINFORESULT_BSSACTIVE BIT0
+#define HFA384x_CHINFORESULT_PCFACTIVE BIT1
+
+typedef struct hfa384x_ChInfoResult
+{
+ UINT16 scanchannels;
+ hfa384x_ChInfoResultSub_t
+ result[HFA384x_CHINFORESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t;
+
+/*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/
+typedef struct hfa384x_HScanResultSub
+{
+ UINT16 chid;
+ UINT16 anl;
+ UINT16 sl;
+ UINT8 bssid[WLAN_BSSID_LEN];
+ UINT16 bcnint;
+ UINT16 capinfo;
+ hfa384x_bytestr32_t ssid;
+ UINT8 supprates[10]; /* 802.11 info element */
+ UINT16 proberesp_rate;
+ UINT16 atim;
+} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t;
+
+typedef struct hfa384x_HScanResult
+{
+ UINT16 nresult;
+ UINT16 rsvd;
+ hfa384x_HScanResultSub_t
+ result[HFA384x_HSCANRESULT_MAX];
+} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/
+
+#define HFA384x_LINK_NOTCONNECTED ((UINT16)0)
+#define HFA384x_LINK_CONNECTED ((UINT16)1)
+#define HFA384x_LINK_DISCONNECTED ((UINT16)2)
+#define HFA384x_LINK_AP_CHANGE ((UINT16)3)
+#define HFA384x_LINK_AP_OUTOFRANGE ((UINT16)4)
+#define HFA384x_LINK_AP_INRANGE ((UINT16)5)
+#define HFA384x_LINK_ASSOCFAIL ((UINT16)6)
+
+typedef struct hfa384x_LinkStatus
+{
+ UINT16 linkstatus;
+} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t;
+
+
+/*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/
+
+#define HFA384x_ASSOCSTATUS_STAASSOC ((UINT16)1)
+#define HFA384x_ASSOCSTATUS_REASSOC ((UINT16)2)
+#define HFA384x_ASSOCSTATUS_DISASSOC ((UINT16)3)
+#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((UINT16)4)
+#define HFA384x_ASSOCSTATUS_AUTHFAIL ((UINT16)5)
+
+typedef struct hfa384x_AssocStatus
+{
+ UINT16 assocstatus;
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ /* old_ap_addr is only valid if assocstatus == 2 */
+ UINT8 old_ap_addr[WLAN_ADDR_LEN];
+ UINT16 reason;
+ UINT16 reserved;
+} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/
+
+typedef struct hfa384x_AuthRequest
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 algorithm;
+} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/
+
+typedef struct hfa384x_AssocRequest
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 type;
+ UINT8 wpa_data[80];
+} __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t;
+
+
+#define HFA384x_ASSOCREQ_TYPE_ASSOC 0
+#define HFA384x_ASSOCREQ_TYPE_REASSOC 1
+
+/*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/
+
+typedef struct hfa384x_MicFailure
+{
+ UINT8 sender[WLAN_ADDR_LEN];
+ UINT8 dest[WLAN_ADDR_LEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t;
+
+/*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/
+
+typedef struct hfa384x_PSUserCount
+{
+ UINT16 usercnt;
+} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t;
+
+typedef struct hfa384x_KeyIDChanged
+{
+ UINT8 sta_addr[WLAN_ADDR_LEN];
+ UINT16 keyid;
+} __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t;
+
+/*-- Collection of all Inf frames ---------------*/
+typedef union hfa384x_infodata {
+ hfa384x_CommTallies16_t commtallies16;
+ hfa384x_CommTallies32_t commtallies32;
+ hfa384x_ScanResult_t scanresult;
+ hfa384x_ChInfoResult_t chinforesult;
+ hfa384x_HScanResult_t hscanresult;
+ hfa384x_LinkStatus_t linkstatus;
+ hfa384x_AssocStatus_t assocstatus;
+ hfa384x_AuthReq_t authreq;
+ hfa384x_PSUserCount_t psusercnt;
+ hfa384x_KeyIDChanged_t keyidchanged;
+} __WLAN_ATTRIB_PACK__ hfa384x_infodata_t;
+
+typedef struct hfa384x_InfFrame
+{
+ UINT16 framelen;
+ UINT16 infotype;
+ hfa384x_infodata_t info;
+} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t;
+
+#if (WLAN_HOSTIF == WLAN_USB)
+/*--------------------------------------------------------------------
+USB Packet structures and constants.
+--------------------------------------------------------------------*/
+
+/* Should be sent to the ctrlout endpoint */
+#define HFA384x_USB_ENBULKIN 6
+
+/* Should be sent to the bulkout endpoint */
+#define HFA384x_USB_TXFRM 0
+#define HFA384x_USB_CMDREQ 1
+#define HFA384x_USB_WRIDREQ 2
+#define HFA384x_USB_RRIDREQ 3
+#define HFA384x_USB_WMEMREQ 4
+#define HFA384x_USB_RMEMREQ 5
+
+/* Received from the bulkin endpoint */
+#define HFA384x_USB_ISFRM(a) (!((a) & 0x8000))
+#define HFA384x_USB_ISTXFRM(a) (((a) & 0x9000) == 0x1000)
+#define HFA384x_USB_ISRXFRM(a) (!((a) & 0x9000))
+#define HFA384x_USB_INFOFRM 0x8000
+#define HFA384x_USB_CMDRESP 0x8001
+#define HFA384x_USB_WRIDRESP 0x8002
+#define HFA384x_USB_RRIDRESP 0x8003
+#define HFA384x_USB_WMEMRESP 0x8004
+#define HFA384x_USB_RMEMRESP 0x8005
+#define HFA384x_USB_BUFAVAIL 0x8006
+#define HFA384x_USB_ERROR 0x8007
+
+/*------------------------------------*/
+/* Request (bulk OUT) packet contents */
+
+typedef struct hfa384x_usb_txfrm {
+ hfa384x_tx_frame_t desc;
+ UINT8 data[WLAN_DATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t;
+
+typedef struct hfa384x_usb_cmdreq {
+ UINT16 type;
+ UINT16 cmd;
+ UINT16 parm0;
+ UINT16 parm1;
+ UINT16 parm2;
+ UINT8 pad[54];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t;
+
+typedef struct hfa384x_usb_wridreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 data[HFA384x_RIDDATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t;
+
+typedef struct hfa384x_usb_rridreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 pad[58];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t;
+
+typedef struct hfa384x_usb_wmemreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 offset;
+ UINT16 page;
+ UINT8 data[HFA384x_USB_RWMEM_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t;
+
+typedef struct hfa384x_usb_rmemreq {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 offset;
+ UINT16 page;
+ UINT8 pad[56];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t;
+
+/*------------------------------------*/
+/* Response (bulk IN) packet contents */
+
+typedef struct hfa384x_usb_rxfrm {
+ hfa384x_rx_frame_t desc;
+ UINT8 data[WLAN_DATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t;
+
+typedef struct hfa384x_usb_infofrm {
+ UINT16 type;
+ hfa384x_InfFrame_t info;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t;
+
+typedef struct hfa384x_usb_statusresp {
+ UINT16 type;
+ UINT16 status;
+ UINT16 resp0;
+ UINT16 resp1;
+ UINT16 resp2;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t;
+
+typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t;
+
+typedef struct hfa384x_usb_rridresp {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT16 rid;
+ UINT8 data[HFA384x_RIDDATA_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t;
+
+typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t;
+
+typedef struct hfa384x_usb_rmemresp {
+ UINT16 type;
+ UINT16 frmlen;
+ UINT8 data[HFA384x_USB_RWMEM_MAXLEN];
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t;
+
+typedef struct hfa384x_usb_bufavail {
+ UINT16 type;
+ UINT16 frmlen;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t;
+
+typedef struct hfa384x_usb_error {
+ UINT16 type;
+ UINT16 errortype;
+} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t;
+
+/*----------------------------------------------------------*/
+/* Unions for packaging all the known packet types together */
+
+typedef union hfa384x_usbout {
+ UINT16 type;
+ hfa384x_usb_txfrm_t txfrm;
+ hfa384x_usb_cmdreq_t cmdreq;
+ hfa384x_usb_wridreq_t wridreq;
+ hfa384x_usb_rridreq_t rridreq;
+ hfa384x_usb_wmemreq_t wmemreq;
+ hfa384x_usb_rmemreq_t rmemreq;
+} __WLAN_ATTRIB_PACK__ hfa384x_usbout_t;
+
+typedef union hfa384x_usbin {
+ UINT16 type;
+ hfa384x_usb_rxfrm_t rxfrm;
+ hfa384x_usb_txfrm_t txfrm;
+ hfa384x_usb_infofrm_t infofrm;
+ hfa384x_usb_cmdresp_t cmdresp;
+ hfa384x_usb_wridresp_t wridresp;
+ hfa384x_usb_rridresp_t rridresp;
+ hfa384x_usb_wmemresp_t wmemresp;
+ hfa384x_usb_rmemresp_t rmemresp;
+ hfa384x_usb_bufavail_t bufavail;
+ hfa384x_usb_error_t usberror;
+ UINT8 boguspad[3000];
+} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t;
+
+#endif /* WLAN_USB */
+
+/*--------------------------------------------------------------------
+PD record structures.
+--------------------------------------------------------------------*/
+
+typedef struct hfa384x_pdr_pcb_partnum
+{
+ UINT8 num[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t;
+
+typedef struct hfa384x_pdr_pcb_tracenum
+{
+ UINT8 num[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t;
+
+typedef struct hfa384x_pdr_nic_serial
+{
+ UINT8 num[12];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t;
+
+typedef struct hfa384x_pdr_mkk_measurements
+{
+ double carrier_freq;
+ double occupied_band;
+ double power_density;
+ double tx_spur_f1;
+ double tx_spur_f2;
+ double tx_spur_f3;
+ double tx_spur_f4;
+ double tx_spur_l1;
+ double tx_spur_l2;
+ double tx_spur_l3;
+ double tx_spur_l4;
+ double rx_spur_f1;
+ double rx_spur_f2;
+ double rx_spur_l1;
+ double rx_spur_l2;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_measurements_t;
+
+typedef struct hfa384x_pdr_nic_ramsize
+{
+ UINT8 size[12]; /* units of KB */
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t;
+
+typedef struct hfa384x_pdr_mfisuprange
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t;
+
+typedef struct hfa384x_pdr_cfisuprange
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 bottom;
+ UINT16 top;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t;
+
+typedef struct hfa384x_pdr_nicid
+{
+ UINT16 id;
+ UINT16 variant;
+ UINT16 major;
+ UINT16 minor;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t;
+
+
+typedef struct hfa384x_pdr_refdac_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t;
+
+typedef struct hfa384x_pdr_vgdac_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t;
+
+typedef struct hfa384x_pdr_level_comp_measurements
+{
+ UINT16 value[0];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t;
+
+typedef struct hfa384x_pdr_mac_address
+{
+ UINT8 addr[6];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t;
+
+typedef struct hfa384x_pdr_mkk_callname
+{
+ UINT8 callname[8];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t;
+
+typedef struct hfa384x_pdr_regdomain
+{
+ UINT16 numdomains;
+ UINT16 domain[5];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t;
+
+typedef struct hfa384x_pdr_allowed_channel
+{
+ UINT16 ch_bitmap;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t;
+
+typedef struct hfa384x_pdr_default_channel
+{
+ UINT16 channel;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t;
+
+typedef struct hfa384x_pdr_privacy_option
+{
+ UINT16 available;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t;
+
+typedef struct hfa384x_pdr_temptype
+{
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t;
+
+typedef struct hfa384x_pdr_refdac_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t;
+
+typedef struct hfa384x_pdr_vgdac_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t;
+
+typedef struct hfa384x_pdr_level_comp_setup
+{
+ UINT16 ch_value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t;
+
+typedef struct hfa384x_pdr_trimdac_setup
+{
+ UINT16 trimidac;
+ UINT16 trimqdac;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t;
+
+typedef struct hfa384x_pdr_ifr_setting
+{
+ UINT16 value[3];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t;
+
+typedef struct hfa384x_pdr_rfr_setting
+{
+ UINT16 value[3];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t;
+
+typedef struct hfa384x_pdr_hfa3861_baseline
+{
+ UINT16 value[50];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t;
+
+typedef struct hfa384x_pdr_hfa3861_shadow
+{
+ UINT32 value[32];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t;
+
+typedef struct hfa384x_pdr_hfa3861_ifrf
+{
+ UINT32 value[20];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t;
+
+typedef struct hfa384x_pdr_hfa3861_chcalsp
+{
+ UINT16 value[14];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t;
+
+typedef struct hfa384x_pdr_hfa3861_chcali
+{
+ UINT16 value[17];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t;
+
+typedef struct hfa384x_pdr_hfa3861_nic_config
+{
+ UINT16 config_bitmap;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t;
+
+typedef struct hfa384x_pdr_hfo_delay
+{
+ UINT8 hfo_delay;
+} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t;
+
+typedef struct hfa384x_pdr_hfa3861_manf_testsp
+{
+ UINT16 value[30];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t;
+
+typedef struct hfa384x_pdr_hfa3861_manf_testi
+{
+ UINT16 value[30];
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t;
+
+typedef struct hfa384x_end_of_pda
+{
+ UINT16 crc;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t;
+
+typedef struct hfa384x_pdrec
+{
+ UINT16 len; /* in words */
+ UINT16 code;
+ union pdr {
+ hfa384x_pdr_pcb_partnum_t pcb_partnum;
+ hfa384x_pdr_pcb_tracenum_t pcb_tracenum;
+ hfa384x_pdr_nic_serial_t nic_serial;
+ hfa384x_pdr_mkk_measurements_t mkk_measurements;
+ hfa384x_pdr_nic_ramsize_t nic_ramsize;
+ hfa384x_pdr_mfisuprange_t mfisuprange;
+ hfa384x_pdr_cfisuprange_t cfisuprange;
+ hfa384x_pdr_nicid_t nicid;
+ hfa384x_pdr_refdac_measurements_t refdac_measurements;
+ hfa384x_pdr_vgdac_measurements_t vgdac_measurements;
+ hfa384x_pdr_level_compc_measurements_t level_compc_measurements;
+ hfa384x_pdr_mac_address_t mac_address;
+ hfa384x_pdr_mkk_callname_t mkk_callname;
+ hfa384x_pdr_regdomain_t regdomain;
+ hfa384x_pdr_allowed_channel_t allowed_channel;
+ hfa384x_pdr_default_channel_t default_channel;
+ hfa384x_pdr_privacy_option_t privacy_option;
+ hfa384x_pdr_temptype_t temptype;
+ hfa384x_pdr_refdac_setup_t refdac_setup;
+ hfa384x_pdr_vgdac_setup_t vgdac_setup;
+ hfa384x_pdr_level_comp_setup_t level_comp_setup;
+ hfa384x_pdr_trimdac_setup_t trimdac_setup;
+ hfa384x_pdr_ifr_setting_t ifr_setting;
+ hfa384x_pdr_rfr_setting_t rfr_setting;
+ hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline;
+ hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow;
+ hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf;
+ hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp;
+ hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali;
+ hfa384x_pdr_nic_config_t nic_config;
+ hfa384x_hfo_delay_t hfo_delay;
+ hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp;
+ hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi;
+ hfa384x_pdr_end_of_pda_t end_of_pda;
+
+ } data;
+} __WLAN_ATTRIB_PACK__ hfa384x_pdrec_t;
+
+
+#ifdef __KERNEL__
+/*--------------------------------------------------------------------
+--- MAC state structure, argument to all functions --
+--- Also, a collection of support types --
+--------------------------------------------------------------------*/
+typedef struct hfa384x_statusresult
+{
+ UINT16 status;
+ UINT16 resp0;
+ UINT16 resp1;
+ UINT16 resp2;
+} hfa384x_cmdresult_t;
+
+#if (WLAN_HOSTIF == WLAN_USB)
+
+/* USB Control Exchange (CTLX):
+ * A queue of the structure below is maintained for all of the
+ * Request/Response type USB packets supported by Prism2.
+ */
+/* The following hfa384x_* structures are arguments to
+ * the usercb() for the different CTLX types.
+ */
+typedef hfa384x_cmdresult_t hfa384x_wridresult_t;
+typedef hfa384x_cmdresult_t hfa384x_wmemresult_t;
+
+typedef struct hfa384x_rridresult
+{
+ UINT16 rid;
+ const void *riddata;
+ UINT riddata_len;
+} hfa384x_rridresult_t;
+
+enum ctlx_state {
+ CTLX_START = 0, /* Start state, not queued */
+
+ CTLX_COMPLETE, /* CTLX successfully completed */
+ CTLX_REQ_FAILED, /* OUT URB completed w/ error */
+
+ CTLX_PENDING, /* Queued, data valid */
+ CTLX_REQ_SUBMITTED, /* OUT URB submitted */
+ CTLX_REQ_COMPLETE, /* OUT URB complete */
+ CTLX_RESP_COMPLETE /* IN URB received */
+};
+typedef enum ctlx_state CTLX_STATE;
+
+struct hfa384x_usbctlx;
+struct hfa384x;
+
+typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* );
+
+typedef void (*ctlx_usercb_t)(
+ struct hfa384x *hw,
+ void *ctlxresult,
+ void *usercb_data);
+
+typedef struct hfa384x_usbctlx
+{
+ struct list_head list;
+
+ size_t outbufsize;
+ hfa384x_usbout_t outbuf; /* pkt buf for OUT */
+ hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */
+
+ CTLX_STATE state; /* Tracks running state */
+
+ struct completion done;
+ volatile int reapable; /* Food for the reaper task */
+
+ ctlx_cmdcb_t cmdcb; /* Async command callback */
+ ctlx_usercb_t usercb; /* Async user callback, */
+ void *usercb_data; /* at CTLX completion */
+
+ int variant; /* Identifies cmd variant */
+} hfa384x_usbctlx_t;
+
+typedef struct hfa384x_usbctlxq
+{
+ spinlock_t lock;
+ struct list_head pending;
+ struct list_head active;
+ struct list_head completing;
+ struct list_head reapable;
+} hfa384x_usbctlxq_t;
+#endif
+
+typedef struct hfa484x_metacmd
+{
+ UINT16 cmd;
+
+ UINT16 parm0;
+ UINT16 parm1;
+ UINT16 parm2;
+
+#if 0 //XXX cmd irq stuff
+ UINT16 bulkid; /* what RID/FID to copy down. */
+ int bulklen; /* how much to copy from BAP */
+ char *bulkdata; /* And to where? */
+#endif
+
+ hfa384x_cmdresult_t result;
+} hfa384x_metacmd_t;
+
+#define MAX_PRISM2_GRP_ADDR 16
+#define MAX_GRP_ADDR 32
+#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */
+
+#define MM_SAT_PCF (BIT14)
+#define MM_GCSD_PCF (BIT15)
+#define MM_GCSD_PCF_EB (BIT14 | BIT15)
+
+#define WLAN_STATE_STOPPED 0 /* Network is not active. */
+#define WLAN_STATE_STARTED 1 /* Network has been started. */
+
+#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */
+#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */
+#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */
+#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */
+#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */
+#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */
+
+/* XXX These are going away ASAP */
+typedef struct prism2sta_authlist
+{
+ UINT cnt;
+ UINT8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN];
+ UINT8 assoc[WLAN_AUTH_MAX];
+} prism2sta_authlist_t;
+
+typedef struct prism2sta_accesslist
+{
+ UINT modify;
+ UINT cnt;
+ UINT8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
+ UINT cnt1;
+ UINT8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN];
+} prism2sta_accesslist_t;
+
+typedef struct hfa384x
+{
+#if (WLAN_HOSTIF != WLAN_USB)
+ /* Resource config */
+ UINT32 iobase;
+ char __iomem *membase;
+ UINT32 irq;
+#else
+ /* USB support data */
+ struct usb_device *usb;
+ struct urb rx_urb;
+ struct sk_buff *rx_urb_skb;
+ struct urb tx_urb;
+ struct urb ctlx_urb;
+ hfa384x_usbout_t txbuff;
+ hfa384x_usbctlxq_t ctlxq;
+ struct timer_list reqtimer;
+ struct timer_list resptimer;
+
+ struct timer_list throttle;
+
+ struct tasklet_struct reaper_bh;
+ struct tasklet_struct completion_bh;
+
+ struct work_struct usb_work;
+
+ unsigned long usb_flags;
+#define THROTTLE_RX 0
+#define THROTTLE_TX 1
+#define WORK_RX_HALT 2
+#define WORK_TX_HALT 3
+#define WORK_RX_RESUME 4
+#define WORK_TX_RESUME 5
+
+ unsigned short req_timer_done:1;
+ unsigned short resp_timer_done:1;
+
+ int endp_in;
+ int endp_out;
+#endif /* !USB */
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ struct pcmcia_device *pdev;
+#else
+ dev_link_t *link;
+#endif
+ dev_node_t node;
+#endif
+
+ int sniff_fcs;
+ int sniff_channel;
+ int sniff_truncate;
+ int sniffhdr;
+
+ wait_queue_head_t cmdq; /* wait queue itself */
+
+ /* Controller state */
+ UINT32 state;
+ UINT32 isap;
+ UINT8 port_enabled[HFA384x_NUMPORTS_MAX];
+#if (WLAN_HOSTIF != WLAN_USB)
+ UINT auxen;
+ UINT isram16;
+#endif /* !USB */
+
+ /* Download support */
+ UINT dlstate;
+ hfa384x_downloadbuffer_t bufinfo;
+ UINT16 dltimeout;
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ spinlock_t cmdlock;
+ volatile int cmdflag; /* wait queue flag */
+ hfa384x_metacmd_t *cmddata; /* for our async callback */
+
+ /* BAP support */
+ spinlock_t baplock;
+ struct tasklet_struct bap_tasklet;
+
+ /* MAC buffer ids */
+ UINT16 txfid_head;
+ UINT16 txfid_tail;
+ UINT txfid_N;
+ UINT16 txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX];
+ UINT16 infofid;
+ struct semaphore infofid_sem;
+#endif /* !USB */
+
+ int scanflag; /* to signal scan comlete */
+ int join_ap; /* are we joined to a specific ap */
+ int join_retries; /* number of join retries till we fail */
+ hfa384x_JoinRequest_data_t joinreq; /* join request saved data */
+
+ wlandevice_t *wlandev;
+ /* Timer to allow for the deferred processing of linkstatus messages */
+ struct work_struct link_bh;
+
+ struct work_struct commsqual_bh;
+ hfa384x_commsquality_t qual;
+ struct timer_list commsqual_timer;
+
+ UINT16 link_status;
+ UINT16 link_status_new;
+ struct sk_buff_head authq;
+
+ /* And here we have stuff that used to be in priv */
+
+ /* State variables */
+ UINT presniff_port_type;
+ UINT16 presniff_wepflags;
+ UINT32 dot11_desired_bss_type;
+ int ap; /* AP flag: 0 - Station, 1 - Access Point. */
+
+ int dbmadjust;
+
+ /* Group Addresses - right now, there are up to a total
+ of MAX_GRP_ADDR group addresses */
+ UINT8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN];
+ UINT dot11_grpcnt;
+
+ /* Component Identities */
+ hfa384x_compident_t ident_nic;
+ hfa384x_compident_t ident_pri_fw;
+ hfa384x_compident_t ident_sta_fw;
+ hfa384x_compident_t ident_ap_fw;
+ UINT16 mm_mods;
+
+ /* Supplier compatibility ranges */
+ hfa384x_caplevel_t cap_sup_mfi;
+ hfa384x_caplevel_t cap_sup_cfi;
+ hfa384x_caplevel_t cap_sup_pri;
+ hfa384x_caplevel_t cap_sup_sta;
+ hfa384x_caplevel_t cap_sup_ap;
+
+ /* Actor compatibility ranges */
+ hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */
+ hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */
+ hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */
+ hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */
+ hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */
+
+ UINT32 psusercount; /* Power save user count. */
+ hfa384x_CommTallies32_t tallies; /* Communication tallies. */
+ UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */
+
+ /* Channel Info request results (AP only) */
+ struct {
+ atomic_t done;
+ UINT8 count;
+ hfa384x_ChInfoResult_t results;
+ } channel_info;
+
+ hfa384x_InfFrame_t *scanresults;
+
+
+ prism2sta_authlist_t authlist; /* Authenticated station list. */
+ UINT accessmode; /* Access mode. */
+ prism2sta_accesslist_t allow; /* Allowed station list. */
+ prism2sta_accesslist_t deny; /* Denied station list. */
+
+} hfa384x_t;
+
+/*=============================================================*/
+/*--- Function Declarations -----------------------------------*/
+/*=============================================================*/
+#if (WLAN_HOSTIF == WLAN_USB)
+void
+hfa384x_create(
+ hfa384x_t *hw,
+ struct usb_device *usb);
+#else
+void
+hfa384x_create(
+ hfa384x_t *hw,
+ UINT irq,
+ UINT32 iobase,
+ UINT8 __iomem *membase);
+#endif
+
+void hfa384x_destroy(hfa384x_t *hw);
+
+irqreturn_t
+hfa384x_interrupt(int irq, void *dev_id PT_REGS);
+int
+hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis);
+int
+hfa384x_drvr_chinforesults( hfa384x_t *hw);
+int
+hfa384x_drvr_commtallies( hfa384x_t *hw);
+int
+hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_drvr_flashdl_enable(hfa384x_t *hw);
+int
+hfa384x_drvr_flashdl_disable(hfa384x_t *hw);
+int
+hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len);
+int
+hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len);
+int
+hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr);
+int
+hfa384x_drvr_hostscanresults( hfa384x_t *hw);
+int
+hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd);
+int
+hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 address, UINT32 *result);
+int
+hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 address, UINT32 data);
+int
+hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr);
+int
+hfa384x_drvr_ramdl_disable(hfa384x_t *hw);
+int
+hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len);
+int
+hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len);
+int
+hfa384x_drvr_scanresults( hfa384x_t *hw);
+
+int
+hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len);
+
+static inline int
+hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
+ if ( result == 0 ) {
+ *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
+ }
+ return result;
+}
+
+static inline int
+hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
+ if ( result == 0 ) {
+ *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
+ }
+
+ return result;
+}
+
+static inline int
+hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 val)
+{
+ UINT16 value = host2hfa384x_16(val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
+}
+
+static inline int
+hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 val)
+{
+ UINT32 value = host2hfa384x_32(val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
+}
+
+#if (WLAN_HOSTIF == WLAN_USB)
+int
+hfa384x_drvr_getconfig_async(hfa384x_t *hw,
+ UINT16 rid,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+int
+hfa384x_drvr_setconfig_async(hfa384x_t *hw,
+ UINT16 rid,
+ void *buf,
+ UINT16 len,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+#else
+static inline int
+hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len,
+ void *ptr1, void *ptr2)
+{
+ (void)ptr1;
+ (void)ptr2;
+ return hfa384x_drvr_setconfig(hw, rid, buf, len);
+}
+#endif
+
+static inline int
+hfa384x_drvr_setconfig16_async(hfa384x_t *hw, UINT16 rid, UINT16 val)
+{
+ UINT16 value = host2hfa384x_16(val);
+ return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
+ NULL , NULL);
+}
+
+static inline int
+hfa384x_drvr_setconfig32_async(hfa384x_t *hw, UINT16 rid, UINT32 val)
+{
+ UINT32 value = host2hfa384x_32(val);
+ return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
+ NULL , NULL);
+}
+
+
+int
+hfa384x_drvr_start(hfa384x_t *hw);
+int
+hfa384x_drvr_stop(hfa384x_t *hw);
+int
+hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+void
+hfa384x_tx_timeout(wlandevice_t *wlandev);
+
+int
+hfa384x_cmd_initialize(hfa384x_t *hw);
+int
+hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport);
+int
+hfa384x_cmd_diagnose(hfa384x_t *hw);
+int
+hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len);
+int
+hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid);
+int
+hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid);
+int
+hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, void *buf, UINT16 len);
+int
+hfa384x_cmd_inquire(hfa384x_t *hw, UINT16 fid);
+int
+hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, void *buf, UINT16 len);
+int
+hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable);
+int
+hfa384x_cmd_download(
+ hfa384x_t *hw,
+ UINT16 mode,
+ UINT16 lowaddr,
+ UINT16 highaddr,
+ UINT16 codelen);
+int
+hfa384x_cmd_aux_enable(hfa384x_t *hw, int force);
+int
+hfa384x_cmd_aux_disable(hfa384x_t *hw);
+int
+hfa384x_copy_from_bap(
+ hfa384x_t *hw,
+ UINT16 bap,
+ UINT16 id,
+ UINT16 offset,
+ void *buf,
+ UINT len);
+int
+hfa384x_copy_to_bap(
+ hfa384x_t *hw,
+ UINT16 bap,
+ UINT16 id,
+ UINT16 offset,
+ void *buf,
+ UINT len);
+void
+hfa384x_copy_from_aux(
+ hfa384x_t *hw,
+ UINT32 cardaddr,
+ UINT32 auxctl,
+ void *buf,
+ UINT len);
+void
+hfa384x_copy_to_aux(
+ hfa384x_t *hw,
+ UINT32 cardaddr,
+ UINT32 auxctl,
+ void *buf,
+ UINT len);
+
+#if (WLAN_HOSTIF != WLAN_USB)
+
+/*
+ HFA384x is a LITTLE ENDIAN part.
+
+ the get/setreg functions implicitly byte-swap the data to LE.
+ the _noswap variants do not perform a byte-swap on the data.
+*/
+
+static inline UINT16
+__hfa384x_getreg(hfa384x_t *hw, UINT reg);
+
+static inline void
+__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg);
+
+static inline UINT16
+__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg);
+
+static inline void
+__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg);
+
+#ifdef REVERSE_ENDIAN
+#define hfa384x_getreg __hfa384x_getreg_noswap
+#define hfa384x_setreg __hfa384x_setreg_noswap
+#define hfa384x_getreg_noswap __hfa384x_getreg
+#define hfa384x_setreg_noswap __hfa384x_setreg
+#else
+#define hfa384x_getreg __hfa384x_getreg
+#define hfa384x_setreg __hfa384x_setreg
+#define hfa384x_getreg_noswap __hfa384x_getreg_noswap
+#define hfa384x_setreg_noswap __hfa384x_setreg_noswap
+#endif
+
+/*----------------------------------------------------------------
+* hfa384x_getreg
+*
+* Retrieve the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+* NOTE: This function returns the value in HOST ORDER!!!!!!
+*
+* Arguments:
+* hw MAC part structure
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Value from the register in HOST ORDER!!!!
+----------------------------------------------------------------*/
+static inline UINT16
+__hfa384x_getreg(hfa384x_t *hw, UINT reg)
+{
+/* printk(KERN_DEBUG "Reading from 0x%0x\n", hw->membase + reg); */
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ return wlan_inw_le16_to_cpu(hw->iobase+reg);
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return __le16_to_cpu(readw(hw->membase + reg));
+#endif
+}
+
+/*----------------------------------------------------------------
+* hfa384x_setreg
+*
+* Set the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+* NOTE: This function assumes the value is in HOST ORDER!!!!!!
+*
+* Arguments:
+* hw MAC part structure
+* val Value, in HOST ORDER!!, to put in the register
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Nothing
+----------------------------------------------------------------*/
+static inline void
+__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ wlan_outw_cpu_to_le16( val, hw->iobase + reg);
+ return;
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew(__cpu_to_le16(val), hw->membase + reg);
+ return;
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_getreg_noswap
+*
+* Retrieve the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+*
+* Arguments:
+* hw MAC part structure
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Value from the register.
+----------------------------------------------------------------*/
+static inline UINT16
+__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ return wlan_inw(hw->iobase+reg);
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return readw(hw->membase + reg);
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_setreg_noswap
+*
+* Set the value of one of the MAC registers. Done here
+* because different PRISM2 MAC parts use different buses and such.
+*
+* Arguments:
+* hw MAC part structure
+* val Value to put in the register
+* reg Register identifier (offset for I/O based i/f)
+*
+* Returns:
+* Nothing
+----------------------------------------------------------------*/
+static inline void
+__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg)
+{
+#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX))
+ wlan_outw( val, hw->iobase + reg);
+ return;
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew(val, hw->membase + reg);
+ return;
+#endif
+}
+
+
+static inline void hfa384x_events_all(hfa384x_t *hw)
+{
+ hfa384x_setreg(hw,
+ HFA384x_INT_NORMAL
+#ifdef CMD_IRQ
+ | HFA384x_INTEN_CMD_SET(1)
+#endif
+ ,
+ HFA384x_INTEN);
+
+}
+
+static inline void hfa384x_events_nobap(hfa384x_t *hw)
+{
+ hfa384x_setreg(hw,
+ (HFA384x_INT_NORMAL & ~HFA384x_INT_BAP_OP)
+#ifdef CMD_IRQ
+ | HFA384x_INTEN_CMD_SET(1)
+#endif
+ ,
+ HFA384x_INTEN);
+
+}
+
+#endif /* WLAN_HOSTIF != WLAN_USB */
+#endif /* __KERNEL__ */
+
+#endif /* _HFA384x_H */
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
new file mode 100644
index 00000000000..db0c502f5d9
--- /dev/null
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -0,0 +1,5027 @@
+/* src/prism2/driver/hfa384x_usb.c
+*
+* Functions that talk to the USB variantof the Intersil hfa384x MAC
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file implements functions that correspond to the prism2/hfa384x
+* 802.11 MAC hardware and firmware host interface.
+*
+* The functions can be considered to represent several levels of
+* abstraction. The lowest level functions are simply C-callable wrappers
+* around the register accesses. The next higher level represents C-callable
+* prism2 API functions that match the Intersil documentation as closely
+* as is reasonable. The next higher layer implements common sequences
+* of invokations of the API layer (e.g. write to bap, followed by cmd).
+*
+* Common sequences:
+* hfa384x_drvr_xxx Highest level abstractions provided by the
+* hfa384x code. They are driver defined wrappers
+* for common sequences. These functions generally
+* use the services of the lower levels.
+*
+* hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These
+* functions are wrappers for the RID get/set
+* sequence. They call copy_[to|from]_bap() and
+* cmd_access(). These functions operate on the
+* RIDs and buffers without validation. The caller
+* is responsible for that.
+*
+* API wrapper functions:
+* hfa384x_cmd_xxx functions that provide access to the f/w commands.
+* The function arguments correspond to each command
+* argument, even command arguments that get packed
+* into single registers. These functions _just_
+* issue the command by setting the cmd/parm regs
+* & reading the status/resp regs. Additional
+* activities required to fully use a command
+* (read/write from/to bap, get/set int status etc.)
+* are implemented separately. Think of these as
+* C-callable prism2 commands.
+*
+* Lowest Layer Functions:
+* hfa384x_docmd_xxx These functions implement the sequence required
+* to issue any prism2 command. Primarily used by the
+* hfa384x_cmd_xxx functions.
+*
+* hfa384x_bap_xxx BAP read/write access functions.
+* Note: we usually use BAP0 for non-interrupt context
+* and BAP1 for interrupt context.
+*
+* hfa384x_dl_xxx download related functions.
+*
+* Driver State Issues:
+* Note that there are two pairs of functions that manage the
+* 'initialized' and 'running' states of the hw/MAC combo. The four
+* functions are create(), destroy(), start(), and stop(). create()
+* sets up the data structures required to support the hfa384x_*
+* functions and destroy() cleans them up. The start() function gets
+* the actual hardware running and enables the interrupts. The stop()
+* function shuts the hardware down. The sequence should be:
+* create()
+* start()
+* .
+* . Do interesting things w/ the hardware
+* .
+* stop()
+* destroy()
+*
+* Note that destroy() can be called without calling stop() first.
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+#define WLAN_DBVAR prism2_debug
+
+#include "version.h"
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <asm/bitops.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+
+#include "wlan_compat.h"
+
+#if (WLAN_HOSTIF != WLAN_USB)
+#error "This file is specific to USB"
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+static int
+wait_for_completion_interruptible(struct completion *x)
+{
+ int ret = 0;
+
+ might_sleep();
+
+ spin_lock_irq(&x->wait.lock);
+ if (!x->done) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ wait.flags |= WQ_FLAG_EXCLUSIVE;
+ __add_wait_queue_tail(&x->wait, &wait);
+ do {
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ __remove_wait_queue(&x->wait, &wait);
+ goto out;
+ }
+ __set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irq(&x->wait.lock);
+ schedule();
+ spin_lock_irq(&x->wait.lock);
+ } while (!x->done);
+ __remove_wait_queue(&x->wait, &wait);
+ }
+ x->done--;
+out:
+ spin_unlock_irq(&x->wait.lock);
+
+ return ret;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)
+static void
+usb_init_urb(struct urb *urb)
+{
+ memset(urb, 0, sizeof(*urb));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */
+ urb->count = (atomic_t)ATOMIC_INIT(1);
+#endif
+ spin_lock_init(&urb->lock);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */
+# define SUBMIT_URB(u,f) usb_submit_urb(u,f)
+#else
+# define SUBMIT_URB(u,f) usb_submit_urb(u)
+#endif
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211req.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "hfa384x.h"
+#include "prism2mgmt.h"
+
+/*================================================================*/
+/* Local Constants */
+
+enum cmd_mode
+{
+ DOWAIT = 0,
+ DOASYNC
+};
+typedef enum cmd_mode CMD_MODE;
+
+#define THROTTLE_JIFFIES (HZ/8)
+
+/*================================================================*/
+/* Local Macros */
+
+#define ROUNDUP64(a) (((a)+63)&~63)
+
+/*================================================================*/
+/* Local Types */
+
+/*================================================================*/
+/* Local Static Definitions */
+extern int prism2_debug;
+
+/*================================================================*/
+/* Local Function Declarations */
+
+#ifdef DEBUG_USB
+static void
+dbprint_urb(struct urb* urb);
+#endif
+
+static void
+hfa384x_int_rxmonitor(
+ wlandevice_t *wlandev,
+ hfa384x_usb_rxfrm_t *rxfrm);
+
+static void
+hfa384x_usb_defer(struct work_struct *data);
+
+static int
+submit_rx_urb(hfa384x_t *hw, gfp_t flags);
+
+static int
+submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags);
+
+/*---------------------------------------------------*/
+/* Callbacks */
+#ifdef URB_ONLY_CALLBACK
+static void
+hfa384x_usbout_callback(struct urb *urb);
+static void
+hfa384x_ctlxout_callback(struct urb *urb);
+static void
+hfa384x_usbin_callback(struct urb *urb);
+#else
+static void
+hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs);
+static void
+hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs);
+static void
+hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs);
+#endif
+
+static void
+hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);
+
+static void
+hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+
+static void
+hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);
+
+static void
+hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);
+
+static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin,
+ int urb_status);
+
+/*---------------------------------------------------*/
+/* Functions to support the prism2 usb command queue */
+
+static void
+hfa384x_usbctlxq_run(hfa384x_t *hw);
+
+static void
+hfa384x_usbctlx_reqtimerfn(unsigned long data);
+
+static void
+hfa384x_usbctlx_resptimerfn(unsigned long data);
+
+static void
+hfa384x_usb_throttlefn(unsigned long data);
+
+static void
+hfa384x_usbctlx_completion_task(unsigned long data);
+
+static void
+hfa384x_usbctlx_reaper_task(unsigned long data);
+
+static int
+hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);
+
+static void
+unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);
+
+struct usbctlx_completor
+{
+ int (*complete)(struct usbctlx_completor*);
+};
+typedef struct usbctlx_completor usbctlx_completor_t;
+
+static int
+hfa384x_usbctlx_complete_sync(hfa384x_t *hw,
+ hfa384x_usbctlx_t *ctlx,
+ usbctlx_completor_t *completor);
+
+static int
+unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);
+
+static void
+hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx);
+
+static void
+hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx);
+
+static int
+usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp,
+ hfa384x_cmdresult_t *result);
+
+static void
+usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp,
+ hfa384x_rridresult_t *result);
+
+/*---------------------------------------------------*/
+/* Low level req/resp CTLX formatters and submitters */
+static int
+hfa384x_docmd(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ hfa384x_metacmd_t *cmd,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+static int
+hfa384x_dorrid(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 rid,
+ void *riddata,
+ UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+static int
+hfa384x_dowrid(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 rid,
+ void *riddata,
+ UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+static int
+hfa384x_dormem(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+static int
+hfa384x_dowmem(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data);
+
+static int
+hfa384x_isgood_pdrcode(UINT16 pdrcode);
+
+/*================================================================*/
+/* Function Definitions */
+static inline const char* ctlxstr(CTLX_STATE s)
+{
+ static const char* ctlx_str[] = {
+ "Initial state",
+ "Complete",
+ "Request failed",
+ "Request pending",
+ "Request packet submitted",
+ "Request packet completed",
+ "Response packet completed"
+ };
+
+ return ctlx_str[s];
+};
+
+
+static inline hfa384x_usbctlx_t*
+get_active_ctlx(hfa384x_t *hw)
+{
+ return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list);
+}
+
+
+#ifdef DEBUG_USB
+void
+dbprint_urb(struct urb* urb)
+{
+ WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe);
+ WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status);
+ WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags);
+ WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer);
+ WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length);
+ WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length);
+ WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth);
+ WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet);
+ WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame);
+ WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval);
+ WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count);
+ WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout);
+ WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (UINT)urb->context);
+ WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (UINT)urb->complete);
+}
+#endif
+
+
+/*----------------------------------------------------------------
+* submit_rx_urb
+*
+* Listen for input data on the BULK-IN pipe. If the pipe has
+* stalled then schedule it to be reset.
+*
+* Arguments:
+* hw device struct
+* memflags memory allocation flags
+*
+* Returns:
+* error code from submission
+*
+* Call context:
+* Any
+----------------------------------------------------------------*/
+static int
+submit_rx_urb(hfa384x_t *hw, gfp_t memflags)
+{
+ struct sk_buff *skb;
+ int result;
+
+ DBFENTER;
+
+ skb = dev_alloc_skb(sizeof(hfa384x_usbin_t));
+ if (skb == NULL) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Post the IN urb */
+ usb_fill_bulk_urb(&hw->rx_urb, hw->usb,
+ hw->endp_in,
+ skb->data, sizeof(hfa384x_usbin_t),
+ hfa384x_usbin_callback, hw->wlandev);
+
+ hw->rx_urb_skb = skb;
+
+ result = -ENOLINK;
+ if ( !hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) {
+ result = SUBMIT_URB(&hw->rx_urb, memflags);
+
+ /* Check whether we need to reset the RX pipe */
+ if (result == -EPIPE) {
+ WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n",
+ hw->wlandev->netdev->name);
+ if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) )
+ schedule_work(&hw->usb_work);
+ }
+ }
+
+ /* Don't leak memory if anything should go wrong */
+ if (result != 0) {
+ dev_kfree_skb(skb);
+ hw->rx_urb_skb = NULL;
+ }
+
+ done:
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* submit_tx_urb
+*
+* Prepares and submits the URB of transmitted data. If the
+* submission fails then it will schedule the output pipe to
+* be reset.
+*
+* Arguments:
+* hw device struct
+* tx_urb URB of data for tranmission
+* memflags memory allocation flags
+*
+* Returns:
+* error code from submission
+*
+* Call context:
+* Any
+----------------------------------------------------------------*/
+static int
+submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags)
+{
+ struct net_device *netdev = hw->wlandev->netdev;
+ int result;
+
+ DBFENTER;
+
+ result = -ENOLINK;
+ if ( netif_running(netdev) ) {
+
+ if ( !hw->wlandev->hwremoved && !test_bit(WORK_TX_HALT, &hw->usb_flags) ) {
+ result = SUBMIT_URB(tx_urb, memflags);
+
+ /* Test whether we need to reset the TX pipe */
+ if (result == -EPIPE) {
+ WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n",
+ netdev->name);
+ set_bit(WORK_TX_HALT, &hw->usb_flags);
+ schedule_work(&hw->usb_work);
+ } else if (result == 0) {
+ netif_stop_queue(netdev);
+ }
+ }
+ }
+
+ DBFEXIT;
+
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa394x_usb_defer
+*
+* There are some things that the USB stack cannot do while
+* in interrupt context, so we arrange this function to run
+* in process context.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* nothing
+*
+* Call context:
+* process (by design)
+----------------------------------------------------------------*/
+static void
+hfa384x_usb_defer(struct work_struct *data)
+{
+ hfa384x_t *hw = container_of(data, struct hfa384x, usb_work);
+ struct net_device *netdev = hw->wlandev->netdev;
+
+ DBFENTER;
+
+ /* Don't bother trying to reset anything if the plug
+ * has been pulled ...
+ */
+ if ( hw->wlandev->hwremoved ) {
+ DBFEXIT;
+ return;
+ }
+
+ /* Reception has stopped: try to reset the input pipe */
+ if (test_bit(WORK_RX_HALT, &hw->usb_flags)) {
+ int ret;
+
+ usb_kill_urb(&hw->rx_urb); /* Cannot be holding spinlock! */
+
+ ret = usb_clear_halt(hw->usb, hw->endp_in);
+ if (ret != 0) {
+ printk(KERN_ERR
+ "Failed to clear rx pipe for %s: err=%d\n",
+ netdev->name, ret);
+ } else {
+ printk(KERN_INFO "%s rx pipe reset complete.\n",
+ netdev->name);
+ clear_bit(WORK_RX_HALT, &hw->usb_flags);
+ set_bit(WORK_RX_RESUME, &hw->usb_flags);
+ }
+ }
+
+ /* Resume receiving data back from the device. */
+ if ( test_bit(WORK_RX_RESUME, &hw->usb_flags) ) {
+ int ret;
+
+ ret = submit_rx_urb(hw, GFP_KERNEL);
+ if (ret != 0) {
+ printk(KERN_ERR
+ "Failed to resume %s rx pipe.\n", netdev->name);
+ } else {
+ clear_bit(WORK_RX_RESUME, &hw->usb_flags);
+ }
+ }
+
+ /* Transmission has stopped: try to reset the output pipe */
+ if (test_bit(WORK_TX_HALT, &hw->usb_flags)) {
+ int ret;
+
+ usb_kill_urb(&hw->tx_urb);
+ ret = usb_clear_halt(hw->usb, hw->endp_out);
+ if (ret != 0) {
+ printk(KERN_ERR
+ "Failed to clear tx pipe for %s: err=%d\n",
+ netdev->name, ret);
+ } else {
+ printk(KERN_INFO "%s tx pipe reset complete.\n",
+ netdev->name);
+ clear_bit(WORK_TX_HALT, &hw->usb_flags);
+ set_bit(WORK_TX_RESUME, &hw->usb_flags);
+
+ /* Stopping the BULK-OUT pipe also blocked
+ * us from sending any more CTLX URBs, so
+ * we need to re-run our queue ...
+ */
+ hfa384x_usbctlxq_run(hw);
+ }
+ }
+
+ /* Resume transmitting. */
+ if ( test_and_clear_bit(WORK_TX_RESUME, &hw->usb_flags) ) {
+ p80211netdev_wake_queue(hw->wlandev);
+ }
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_create
+*
+* Sets up the hfa384x_t data structure for use. Note this
+* does _not_ intialize the actual hardware, just the data structures
+* we use to keep track of its state.
+*
+* Arguments:
+* hw device structure
+* irq device irq number
+* iobase i/o base address for register access
+* membase memory base address for register access
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+void
+hfa384x_create( hfa384x_t *hw, struct usb_device *usb)
+{
+ DBFENTER;
+
+ memset(hw, 0, sizeof(hfa384x_t));
+ hw->usb = usb;
+
+ /* set up the endpoints */
+ hw->endp_in = usb_rcvbulkpipe(usb, 1);
+ hw->endp_out = usb_sndbulkpipe(usb, 2);
+
+ /* Set up the waitq */
+ init_waitqueue_head(&hw->cmdq);
+
+ /* Initialize the command queue */
+ spin_lock_init(&hw->ctlxq.lock);
+ INIT_LIST_HEAD(&hw->ctlxq.pending);
+ INIT_LIST_HEAD(&hw->ctlxq.active);
+ INIT_LIST_HEAD(&hw->ctlxq.completing);
+ INIT_LIST_HEAD(&hw->ctlxq.reapable);
+
+ /* Initialize the authentication queue */
+ skb_queue_head_init(&hw->authq);
+
+ tasklet_init(&hw->reaper_bh,
+ hfa384x_usbctlx_reaper_task,
+ (unsigned long)hw);
+ tasklet_init(&hw->completion_bh,
+ hfa384x_usbctlx_completion_task,
+ (unsigned long)hw);
+ INIT_WORK2(&hw->link_bh, prism2sta_processing_defer);
+ INIT_WORK2(&hw->usb_work, hfa384x_usb_defer);
+
+ init_timer(&hw->throttle);
+ hw->throttle.function = hfa384x_usb_throttlefn;
+ hw->throttle.data = (unsigned long)hw;
+
+ init_timer(&hw->resptimer);
+ hw->resptimer.function = hfa384x_usbctlx_resptimerfn;
+ hw->resptimer.data = (unsigned long)hw;
+
+ init_timer(&hw->reqtimer);
+ hw->reqtimer.function = hfa384x_usbctlx_reqtimerfn;
+ hw->reqtimer.data = (unsigned long)hw;
+
+ usb_init_urb(&hw->rx_urb);
+ usb_init_urb(&hw->tx_urb);
+ usb_init_urb(&hw->ctlx_urb);
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+ hw->state = HFA384x_STATE_INIT;
+
+ INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer);
+ init_timer(&hw->commsqual_timer);
+ hw->commsqual_timer.data = (unsigned long) hw;
+ hw->commsqual_timer.function = prism2sta_commsqual_timer;
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_destroy
+*
+* Partner to hfa384x_create(). This function cleans up the hw
+* structure so that it can be freed by the caller using a simple
+* kfree. Currently, this function is just a placeholder. If, at some
+* point in the future, an hw in the 'shutdown' state requires a 'deep'
+* kfree, this is where it should be done. Note that if this function
+* is called on a _running_ hw structure, the drvr_stop() function is
+* called.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* nothing, this function is not allowed to fail.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+void
+hfa384x_destroy( hfa384x_t *hw)
+{
+ struct sk_buff *skb;
+
+ DBFENTER;
+
+ if ( hw->state == HFA384x_STATE_RUNNING ) {
+ hfa384x_drvr_stop(hw);
+ }
+ hw->state = HFA384x_STATE_PREINIT;
+
+ if (hw->scanresults) {
+ kfree(hw->scanresults);
+ hw->scanresults = NULL;
+ }
+
+ /* Now to clean out the auth queue */
+ while ( (skb = skb_dequeue(&hw->authq)) ) {
+ dev_kfree_skb(skb);
+ }
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+ */
+static hfa384x_usbctlx_t* usbctlx_alloc(void)
+{
+ hfa384x_usbctlx_t *ctlx;
+
+ ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ if (ctlx != NULL)
+ {
+ memset(ctlx, 0, sizeof(*ctlx));
+ init_completion(&ctlx->done);
+ }
+
+ return ctlx;
+}
+
+
+/*----------------------------------------------------------------
+ *
+----------------------------------------------------------------*/
+static int
+usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp,
+ hfa384x_cmdresult_t *result)
+{
+ DBFENTER;
+
+ result->status = hfa384x2host_16(cmdresp->status);
+ result->resp0 = hfa384x2host_16(cmdresp->resp0);
+ result->resp1 = hfa384x2host_16(cmdresp->resp1);
+ result->resp2 = hfa384x2host_16(cmdresp->resp2);
+
+ WLAN_LOG_DEBUG(4, "cmdresult:status=0x%04x "
+ "resp0=0x%04x resp1=0x%04x resp2=0x%04x\n",
+ result->status,
+ result->resp0,
+ result->resp1,
+ result->resp2);
+
+ DBFEXIT;
+ return (result->status & HFA384x_STATUS_RESULT);
+}
+
+static void
+usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp,
+ hfa384x_rridresult_t *result)
+{
+ DBFENTER;
+
+ result->rid = hfa384x2host_16(rridresp->rid);
+ result->riddata = rridresp->data;
+ result->riddata_len = ((hfa384x2host_16(rridresp->frmlen) - 1) * 2);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* Completor object:
+* This completor must be passed to hfa384x_usbctlx_complete_sync()
+* when processing a CTLX that returns a hfa384x_cmdresult_t structure.
+----------------------------------------------------------------*/
+struct usbctlx_cmd_completor
+{
+ usbctlx_completor_t head;
+
+ const hfa384x_usb_cmdresp_t *cmdresp;
+ hfa384x_cmdresult_t *result;
+};
+typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t;
+
+static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head)
+{
+ usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t*)head;
+ return usbctlx_get_status(complete->cmdresp, complete->result);
+}
+
+static inline usbctlx_completor_t*
+init_cmd_completor(usbctlx_cmd_completor_t *completor,
+ const hfa384x_usb_cmdresp_t *cmdresp,
+ hfa384x_cmdresult_t *result)
+{
+ completor->head.complete = usbctlx_cmd_completor_fn;
+ completor->cmdresp = cmdresp;
+ completor->result = result;
+ return &(completor->head);
+}
+
+/*----------------------------------------------------------------
+* Completor object:
+* This completor must be passed to hfa384x_usbctlx_complete_sync()
+* when processing a CTLX that reads a RID.
+----------------------------------------------------------------*/
+struct usbctlx_rrid_completor
+{
+ usbctlx_completor_t head;
+
+ const hfa384x_usb_rridresp_t *rridresp;
+ void *riddata;
+ UINT riddatalen;
+};
+typedef struct usbctlx_rrid_completor usbctlx_rrid_completor_t;
+
+static int usbctlx_rrid_completor_fn(usbctlx_completor_t *head)
+{
+ usbctlx_rrid_completor_t *complete = (usbctlx_rrid_completor_t*)head;
+ hfa384x_rridresult_t rridresult;
+
+ usbctlx_get_rridresult(complete->rridresp, &rridresult);
+
+ /* Validate the length, note body len calculation in bytes */
+ if ( rridresult.riddata_len != complete->riddatalen ) {
+ WLAN_LOG_WARNING(
+ "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n",
+ rridresult.rid,
+ complete->riddatalen,
+ rridresult.riddata_len);
+ return -ENODATA;
+ }
+
+ memcpy(complete->riddata,
+ rridresult.riddata,
+ complete->riddatalen);
+ return 0;
+}
+
+static inline usbctlx_completor_t*
+init_rrid_completor(usbctlx_rrid_completor_t *completor,
+ const hfa384x_usb_rridresp_t *rridresp,
+ void *riddata,
+ UINT riddatalen)
+{
+ completor->head.complete = usbctlx_rrid_completor_fn;
+ completor->rridresp = rridresp;
+ completor->riddata = riddata;
+ completor->riddatalen = riddatalen;
+ return &(completor->head);
+}
+
+/*----------------------------------------------------------------
+* Completor object:
+* Interprets the results of a synchronous RID-write
+----------------------------------------------------------------*/
+typedef usbctlx_cmd_completor_t usbctlx_wrid_completor_t;
+#define init_wrid_completor init_cmd_completor
+
+/*----------------------------------------------------------------
+* Completor object:
+* Interprets the results of a synchronous memory-write
+----------------------------------------------------------------*/
+typedef usbctlx_cmd_completor_t usbctlx_wmem_completor_t;
+#define init_wmem_completor init_cmd_completor
+
+/*----------------------------------------------------------------
+* Completor object:
+* Interprets the results of a synchronous memory-read
+----------------------------------------------------------------*/
+struct usbctlx_rmem_completor
+{
+ usbctlx_completor_t head;
+
+ const hfa384x_usb_rmemresp_t *rmemresp;
+ void *data;
+ UINT len;
+};
+typedef struct usbctlx_rmem_completor usbctlx_rmem_completor_t;
+
+static int usbctlx_rmem_completor_fn(usbctlx_completor_t *head)
+{
+ usbctlx_rmem_completor_t *complete = (usbctlx_rmem_completor_t*)head;
+
+ WLAN_LOG_DEBUG(4,"rmemresp:len=%d\n", complete->rmemresp->frmlen);
+ memcpy(complete->data, complete->rmemresp->data, complete->len);
+ return 0;
+}
+
+static inline usbctlx_completor_t*
+init_rmem_completor(usbctlx_rmem_completor_t *completor,
+ hfa384x_usb_rmemresp_t *rmemresp,
+ void *data,
+ UINT len)
+{
+ completor->head.complete = usbctlx_rmem_completor_fn;
+ completor->rmemresp = rmemresp;
+ completor->data = data;
+ completor->len = len;
+ return &(completor->head);
+}
+
+/*----------------------------------------------------------------
+* hfa384x_cb_status
+*
+* Ctlx_complete handler for async CMD type control exchanges.
+* mark the hw struct as such.
+*
+* Note: If the handling is changed here, it should probably be
+* changed in docmd as well.
+*
+* Arguments:
+* hw hw struct
+* ctlx completed CTLX
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void
+hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx)
+{
+ DBFENTER;
+
+ if ( ctlx->usercb != NULL ) {
+ hfa384x_cmdresult_t cmdresult;
+
+ if (ctlx->state != CTLX_COMPLETE) {
+ memset(&cmdresult, 0, sizeof(cmdresult));
+ cmdresult.status = HFA384x_STATUS_RESULT_SET(HFA384x_CMD_ERR);
+ } else {
+ usbctlx_get_status(&ctlx->inbuf.cmdresp, &cmdresult);
+ }
+
+ ctlx->usercb(hw, &cmdresult, ctlx->usercb_data);
+ }
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cb_rrid
+*
+* CTLX completion handler for async RRID type control exchanges.
+*
+* Note: If the handling is changed here, it should probably be
+* changed in dorrid as well.
+*
+* Arguments:
+* hw hw struct
+* ctlx completed CTLX
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void
+hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx)
+{
+ DBFENTER;
+
+ if ( ctlx->usercb != NULL ) {
+ hfa384x_rridresult_t rridresult;
+
+ if (ctlx->state != CTLX_COMPLETE) {
+ memset(&rridresult, 0, sizeof(rridresult));
+ rridresult.rid = hfa384x2host_16(ctlx->outbuf.rridreq.rid);
+ } else {
+ usbctlx_get_rridresult(&ctlx->inbuf.rridresp, &rridresult);
+ }
+
+ ctlx->usercb(hw, &rridresult, ctlx->usercb_data);
+ }
+
+ DBFEXIT;
+}
+
+static inline int
+hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd)
+{
+ return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL);
+}
+
+static inline int
+hfa384x_docmd_async(hfa384x_t *hw,
+ hfa384x_metacmd_t *cmd,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_docmd(hw, DOASYNC, cmd,
+ cmdcb, usercb, usercb_data);
+}
+
+static inline int
+hfa384x_dorrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen)
+{
+ return hfa384x_dorrid(hw, DOWAIT,
+ rid, riddata, riddatalen,
+ NULL, NULL, NULL);
+}
+
+static inline int
+hfa384x_dorrid_async(hfa384x_t *hw,
+ UINT16 rid, void *riddata, UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dorrid(hw, DOASYNC,
+ rid, riddata, riddatalen,
+ cmdcb, usercb, usercb_data);
+}
+
+static inline int
+hfa384x_dowrid_wait(hfa384x_t *hw, UINT16 rid, void *riddata, UINT riddatalen)
+{
+ return hfa384x_dowrid(hw, DOWAIT,
+ rid, riddata, riddatalen,
+ NULL, NULL, NULL);
+}
+
+static inline int
+hfa384x_dowrid_async(hfa384x_t *hw,
+ UINT16 rid, void *riddata, UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dowrid(hw, DOASYNC,
+ rid, riddata, riddatalen,
+ cmdcb, usercb, usercb_data);
+}
+
+static inline int
+hfa384x_dormem_wait(hfa384x_t *hw,
+ UINT16 page, UINT16 offset, void *data, UINT len)
+{
+ return hfa384x_dormem(hw, DOWAIT,
+ page, offset, data, len,
+ NULL, NULL, NULL);
+}
+
+static inline int
+hfa384x_dormem_async(hfa384x_t *hw,
+ UINT16 page, UINT16 offset, void *data, UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dormem(hw, DOASYNC,
+ page, offset, data, len,
+ cmdcb, usercb, usercb_data);
+}
+
+static inline int
+hfa384x_dowmem_wait(
+ hfa384x_t *hw,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len)
+{
+ return hfa384x_dowmem(hw, DOWAIT,
+ page, offset, data, len,
+ NULL, NULL, NULL);
+}
+
+static inline int
+hfa384x_dowmem_async(
+ hfa384x_t *hw,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dowmem(hw, DOASYNC,
+ page, offset, data, len,
+ cmdcb, usercb, usercb_data);
+}
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_initialize
+*
+* Issues the initialize command and sets the hw->state based
+* on the result.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_cmd_initialize(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+
+ cmd.cmd = HFA384x_CMDCODE_INIT;
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+
+ WLAN_LOG_DEBUG(3,"cmdresp.init: "
+ "status=0x%04x, resp0=0x%04x, "
+ "resp1=0x%04x, resp2=0x%04x\n",
+ cmd.result.status,
+ cmd.result.resp0,
+ cmd.result.resp1,
+ cmd.result.resp2);
+ if ( result == 0 ) {
+ for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) {
+ hw->port_enabled[i] = 0;
+ }
+ }
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_disable
+*
+* Issues the disable command to stop communications on one of
+* the MACs 'ports'.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) |
+ HFA384x_CMD_MACPORT_SET(macport);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_enable
+*
+* Issues the enable command to enable communications on one of
+* the MACs 'ports'.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) |
+ HFA384x_CMD_MACPORT_SET(macport);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_notify
+*
+* Sends an info frame to the firmware to alter the behavior
+* of the f/w asynch processes. Can only be called when the MAC
+* is in the enabled state.
+*
+* Arguments:
+* hw device structure
+* reclaim [0|1] indicates whether the given FID will
+* be handed back (via Alloc event) for reuse.
+* (host order)
+* fid FID of buffer containing the frame that was
+* previously copied to MAC memory via the bap.
+* (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+* hw->resp0 will contain the FID being used by async notify
+* process. If reclaim==0, resp0 will be the same as the fid
+* argument. If reclaim==1, resp0 will be the different.
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid,
+ void *buf, UINT16 len)
+{
+#if 0
+ int result = 0;
+ UINT16 cmd;
+ DBFENTER;
+ cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) |
+ HFA384x_CMD_RECL_SET(reclaim);
+ result = hfa384x_docmd_wait(hw, cmd);
+
+ DBFEXIT;
+ return result;
+#endif
+return 0;
+}
+
+
+#if 0
+/*----------------------------------------------------------------
+* hfa384x_cmd_inquiry
+*
+* Requests an info frame from the firmware. The info frame will
+* be delivered asynchronously via the Info event.
+*
+* Arguments:
+* hw device structure
+* fid FID of the info frame requested. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+#endif
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_monitor
+*
+* Enables the 'monitor mode' of the MAC. Here's the description of
+* monitor mode that I've received thus far:
+*
+* "The "monitor mode" of operation is that the MAC passes all
+* frames for which the PLCP checks are correct. All received
+* MPDUs are passed to the host with MAC Port = 7, with a
+* receive status of good, FCS error, or undecryptable. Passing
+* certain MPDUs is a violation of the 802.11 standard, but useful
+* for a debugging tool." Normal communication is not possible
+* while monitor mode is enabled.
+*
+* Arguments:
+* hw device structure
+* enable a code (0x0b|0x0f) that enables/disables
+* monitor mode. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) |
+ HFA384x_CMD_AINFO_SET(enable);
+ cmd.parm0 = 0;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_cmd_download
+*
+* Sets the controls for the MAC controller code/data download
+* process. The arguments set the mode and address associated
+* with a download. Note that the aux registers should be enabled
+* prior to setting one of the download enable modes.
+*
+* Arguments:
+* hw device structure
+* mode 0 - Disable programming and begin code exec
+* 1 - Enable volatile mem programming
+* 2 - Enable non-volatile mem programming
+* 3 - Program non-volatile section from NV download
+* buffer.
+* (host order)
+* lowaddr
+* highaddr For mode 1, sets the high & low order bits of
+* the "destination address". This address will be
+* the execution start address when download is
+* subsequently disabled.
+* For mode 2, sets the high & low order bits of
+* the destination in NV ram.
+* For modes 0 & 3, should be zero. (host order)
+* NOTE: these are CMD format.
+* codelen Length of the data to write in mode 2,
+* zero otherwise. (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr,
+ UINT16 highaddr, UINT16 codelen)
+{
+ int result = 0;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+ WLAN_LOG_DEBUG(5,
+ "mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n",
+ mode, lowaddr, highaddr, codelen);
+
+ cmd.cmd = (HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) |
+ HFA384x_CMD_PROGMODE_SET(mode));
+
+ cmd.parm0 = lowaddr;
+ cmd.parm1 = highaddr;
+ cmd.parm2 = codelen;
+
+ result = hfa384x_docmd_wait(hw, &cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_from_aux
+*
+* Copies a collection of bytes from the controller memory. The
+* Auxiliary port MUST be enabled prior to calling this function.
+* We _might_ be in a download state.
+*
+* Arguments:
+* hw device structure
+* cardaddr address in hfa384x data space to read
+* auxctl address space select
+* buf ptr to destination host buffer
+* len length of data to transfer (in bytes)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* buf contains the data copied
+*
+* Call context:
+* process
+* interrupt
+----------------------------------------------------------------*/
+void
+hfa384x_copy_from_aux(
+ hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len)
+{
+ DBFENTER;
+ WLAN_LOG_ERROR("not used in USB.\n");
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_copy_to_aux
+*
+* Copies a collection of bytes to the controller memory. The
+* Auxiliary port MUST be enabled prior to calling this function.
+* We _might_ be in a download state.
+*
+* Arguments:
+* hw device structure
+* cardaddr address in hfa384x data space to read
+* auxctl address space select
+* buf ptr to destination host buffer
+* len length of data to transfer (in bytes)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* Controller memory now contains a copy of buf
+*
+* Call context:
+* process
+* interrupt
+----------------------------------------------------------------*/
+void
+hfa384x_copy_to_aux(
+ hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len)
+{
+ DBFENTER;
+ WLAN_LOG_ERROR("not used in USB.\n");
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_corereset
+*
+* Perform a reset of the hfa38xx MAC core. We assume that the hw
+* structure is in its "created" state. That is, it is initialized
+* with proper values. Note that if a reset is done after the
+* device has been active for awhile, the caller might have to clean
+* up some leftover cruft in the hw structure.
+*
+* Arguments:
+* hw device structure
+* holdtime how long (in ms) to hold the reset
+* settletime how long (in ms) to wait after releasing
+* the reset
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
+{
+#if 0
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ struct usb_device *parent = hw->usb->parent;
+ int i;
+ int port = -1;
+#endif
+#endif
+ int result = 0;
+
+
+#define P2_USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
+#define P2_USB_FEAT_RESET 4
+#define P2_USB_FEAT_C_RESET 20
+
+ DBFENTER;
+
+#if 0
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ /* Find the hub port */
+ for ( i = 0; i < parent->maxchild; i++) {
+ if (parent->children[i] == hw->usb) {
+ port = i;
+ break;
+ }
+ }
+ if (port < 0) return -ENOENT;
+
+ /* Set and clear the reset */
+ usb_control_msg(parent, usb_sndctrlpipe(parent, 0),
+ USB_REQ_SET_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_RESET,
+ port+1, NULL, 0, 1*HZ);
+ wait_ms(holdtime);
+ usb_control_msg(parent, usb_sndctrlpipe(parent, 0),
+ USB_REQ_CLEAR_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_C_RESET,
+ port+1, NULL, 0, 1*HZ);
+ wait_ms(settletime);
+
+ /* Set the device address */
+ result=usb_set_address(hw->usb);
+ if (result < 0) {
+ WLAN_LOG_ERROR("reset_usbdev: Dev not accepting address, "
+ "result=%d\n", result);
+ clear_bit(hw->usb->devnum, &hw->usb->bus->devmap.devicemap);
+ hw->usb->devnum = -1;
+ goto done;
+ }
+ /* Let the address settle */
+ wait_ms(20);
+
+ /* Assume we're reusing the original descriptor data */
+
+ /* Set the configuration. */
+ WLAN_LOG_DEBUG(3, "Setting Configuration %d\n",
+ hw->usb->config[0].bConfigurationValue);
+ result=usb_set_configuration(hw->usb, hw->usb->config[0].bConfigurationValue);
+ if ( result ) {
+ WLAN_LOG_ERROR("usb_set_configuration() failed, result=%d.\n",
+ result);
+ goto done;
+ }
+ /* Let the configuration settle */
+ wait_ms(20);
+
+ done:
+#else
+ result=usb_reset_device(hw->usb);
+ if(result<0) {
+ WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result);
+ }
+#endif
+#endif
+
+ result=usb_reset_device(hw->usb);
+ if(result<0) {
+ WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result);
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_complete_sync
+*
+* Waits for a synchronous CTLX object to complete,
+* and then handles the response.
+*
+* Arguments:
+* hw device structure
+* ctlx CTLX ptr
+* completor functor object to decide what to
+* do with the CTLX's result.
+*
+* Returns:
+* 0 Success
+* -ERESTARTSYS Interrupted by a signal
+* -EIO CTLX failed
+* -ENODEV Adapter was unplugged
+* ??? Result from completor
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw,
+ hfa384x_usbctlx_t *ctlx,
+ usbctlx_completor_t *completor)
+{
+ unsigned long flags;
+ int result;
+
+ DBFENTER;
+
+ result = wait_for_completion_interruptible(&ctlx->done);
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /*
+ * We can only handle the CTLX if the USB disconnect
+ * function has not run yet ...
+ */
+ cleanup:
+ if ( hw->wlandev->hwremoved )
+ {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ result = -ENODEV;
+ }
+ else if ( result != 0 )
+ {
+ int runqueue = 0;
+
+ /*
+ * We were probably interrupted, so delete
+ * this CTLX asynchronously, kill the timers
+ * and the URB, and then start the next
+ * pending CTLX.
+ *
+ * NOTE: We can only delete the timers and
+ * the URB if this CTLX is active.
+ */
+ if (ctlx == get_active_ctlx(hw))
+ {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ del_singleshot_timer_sync(&hw->reqtimer);
+ del_singleshot_timer_sync(&hw->resptimer);
+ hw->req_timer_done = 1;
+ hw->resp_timer_done = 1;
+ usb_kill_urb(&hw->ctlx_urb);
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ runqueue = 1;
+
+ /*
+ * This scenario is so unlikely that I'm
+ * happy with a grubby "goto" solution ...
+ */
+ if ( hw->wlandev->hwremoved )
+ goto cleanup;
+ }
+
+ /*
+ * The completion task will send this CTLX
+ * to the reaper the next time it runs. We
+ * are no longer in a hurry.
+ */
+ ctlx->reapable = 1;
+ ctlx->state = CTLX_REQ_FAILED;
+ list_move_tail(&ctlx->list, &hw->ctlxq.completing);
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ if (runqueue)
+ hfa384x_usbctlxq_run(hw);
+ } else {
+ if (ctlx->state == CTLX_COMPLETE) {
+ result = completor->complete(completor);
+ } else {
+ WLAN_LOG_WARNING("CTLX[%d] error: state(%s)\n",
+ hfa384x2host_16(ctlx->outbuf.type),
+ ctlxstr(ctlx->state));
+ result = -EIO;
+ }
+
+ list_del(&ctlx->list);
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ kfree(ctlx);
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_docmd
+*
+* Constructs a command CTLX and submits it.
+*
+* NOTE: Any changes to the 'post-submit' code in this function
+* need to be carried over to hfa384x_cbcmd() since the handling
+* is virtually identical.
+*
+* Arguments:
+* hw device structure
+* mode DOWAIT or DOASYNC
+* cmd cmd structure. Includes all arguments and result
+* data points. All in host order. in host order
+* cmdcb command-specific callback
+* usercb user callback for async calls, NULL for DOWAIT calls
+* usercb_data user supplied data pointer for async calls, NULL
+* for DOASYNC calls
+*
+* Returns:
+* 0 success
+* -EIO CTLX failure
+* -ERESTARTSYS Awakened on signal
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+static int
+hfa384x_docmd(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ hfa384x_metacmd_t *cmd,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ int result;
+ hfa384x_usbctlx_t *ctlx;
+
+ DBFENTER;
+ ctlx = usbctlx_alloc();
+ if ( ctlx == NULL ) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Initialize the command */
+ ctlx->outbuf.cmdreq.type = host2hfa384x_16(HFA384x_USB_CMDREQ);
+ ctlx->outbuf.cmdreq.cmd = host2hfa384x_16(cmd->cmd);
+ ctlx->outbuf.cmdreq.parm0 = host2hfa384x_16(cmd->parm0);
+ ctlx->outbuf.cmdreq.parm1 = host2hfa384x_16(cmd->parm1);
+ ctlx->outbuf.cmdreq.parm2 = host2hfa384x_16(cmd->parm2);
+
+ ctlx->outbufsize = sizeof(ctlx->outbuf.cmdreq);
+
+ WLAN_LOG_DEBUG(4, "cmdreq: cmd=0x%04x "
+ "parm0=0x%04x parm1=0x%04x parm2=0x%04x\n",
+ cmd->cmd,
+ cmd->parm0,
+ cmd->parm1,
+ cmd->parm2);
+
+ ctlx->reapable = mode;
+ ctlx->cmdcb = cmdcb;
+ ctlx->usercb = usercb;
+ ctlx->usercb_data = usercb_data;
+
+ result = hfa384x_usbctlx_submit(hw, ctlx);
+ if (result != 0) {
+ kfree(ctlx);
+ } else if (mode == DOWAIT) {
+ usbctlx_cmd_completor_t completor;
+
+ result = hfa384x_usbctlx_complete_sync(
+ hw, ctlx, init_cmd_completor(&completor,
+ &ctlx->inbuf.cmdresp,
+ &cmd->result) );
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_dorrid
+*
+* Constructs a read rid CTLX and issues it.
+*
+* NOTE: Any changes to the 'post-submit' code in this function
+* need to be carried over to hfa384x_cbrrid() since the handling
+* is virtually identical.
+*
+* Arguments:
+* hw device structure
+* mode DOWAIT or DOASYNC
+* rid Read RID number (host order)
+* riddata Caller supplied buffer that MAC formatted RID.data
+* record will be written to for DOWAIT calls. Should
+* be NULL for DOASYNC calls.
+* riddatalen Buffer length for DOWAIT calls. Zero for DOASYNC calls.
+* cmdcb command callback for async calls, NULL for DOWAIT calls
+* usercb user callback for async calls, NULL for DOWAIT calls
+* usercb_data user supplied data pointer for async calls, NULL
+* for DOWAIT calls
+*
+* Returns:
+* 0 success
+* -EIO CTLX failure
+* -ERESTARTSYS Awakened on signal
+* -ENODATA riddatalen != macdatalen
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+* Call context:
+* interrupt (DOASYNC)
+* process (DOWAIT or DOASYNC)
+----------------------------------------------------------------*/
+static int
+hfa384x_dorrid(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 rid,
+ void *riddata,
+ UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ int result;
+ hfa384x_usbctlx_t *ctlx;
+
+ DBFENTER;
+ ctlx = usbctlx_alloc();
+ if ( ctlx == NULL ) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Initialize the command */
+ ctlx->outbuf.rridreq.type = host2hfa384x_16(HFA384x_USB_RRIDREQ);
+ ctlx->outbuf.rridreq.frmlen =
+ host2hfa384x_16(sizeof(ctlx->outbuf.rridreq.rid));
+ ctlx->outbuf.rridreq.rid = host2hfa384x_16(rid);
+
+ ctlx->outbufsize = sizeof(ctlx->outbuf.rridreq);
+
+ ctlx->reapable = mode;
+ ctlx->cmdcb = cmdcb;
+ ctlx->usercb = usercb;
+ ctlx->usercb_data = usercb_data;
+
+ /* Submit the CTLX */
+ result = hfa384x_usbctlx_submit(hw, ctlx);
+ if (result != 0) {
+ kfree(ctlx);
+ } else if (mode == DOWAIT) {
+ usbctlx_rrid_completor_t completor;
+
+ result = hfa384x_usbctlx_complete_sync(
+ hw, ctlx, init_rrid_completor(&completor,
+ &ctlx->inbuf.rridresp,
+ riddata,
+ riddatalen) );
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_dowrid
+*
+* Constructs a write rid CTLX and issues it.
+*
+* NOTE: Any changes to the 'post-submit' code in this function
+* need to be carried over to hfa384x_cbwrid() since the handling
+* is virtually identical.
+*
+* Arguments:
+* hw device structure
+* CMD_MODE DOWAIT or DOASYNC
+* rid RID code
+* riddata Data portion of RID formatted for MAC
+* riddatalen Length of the data portion in bytes
+* cmdcb command callback for async calls, NULL for DOWAIT calls
+* usercb user callback for async calls, NULL for DOWAIT calls
+* usercb_data user supplied data pointer for async calls
+*
+* Returns:
+* 0 success
+* -ETIMEDOUT timed out waiting for register ready or
+* command completion
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+* Call context:
+* interrupt (DOASYNC)
+* process (DOWAIT or DOASYNC)
+----------------------------------------------------------------*/
+static int
+hfa384x_dowrid(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 rid,
+ void *riddata,
+ UINT riddatalen,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ int result;
+ hfa384x_usbctlx_t *ctlx;
+
+ DBFENTER;
+ ctlx = usbctlx_alloc();
+ if ( ctlx == NULL ) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Initialize the command */
+ ctlx->outbuf.wridreq.type = host2hfa384x_16(HFA384x_USB_WRIDREQ);
+ ctlx->outbuf.wridreq.frmlen = host2hfa384x_16(
+ (sizeof(ctlx->outbuf.wridreq.rid) +
+ riddatalen + 1) / 2);
+ ctlx->outbuf.wridreq.rid = host2hfa384x_16(rid);
+ memcpy(ctlx->outbuf.wridreq.data, riddata, riddatalen);
+
+ ctlx->outbufsize = sizeof(ctlx->outbuf.wridreq.type) +
+ sizeof(ctlx->outbuf.wridreq.frmlen) +
+ sizeof(ctlx->outbuf.wridreq.rid) +
+ riddatalen;
+
+ ctlx->reapable = mode;
+ ctlx->cmdcb = cmdcb;
+ ctlx->usercb = usercb;
+ ctlx->usercb_data = usercb_data;
+
+ /* Submit the CTLX */
+ result = hfa384x_usbctlx_submit(hw, ctlx);
+ if (result != 0) {
+ kfree(ctlx);
+ } else if (mode == DOWAIT) {
+ usbctlx_wrid_completor_t completor;
+ hfa384x_cmdresult_t wridresult;
+
+ result = hfa384x_usbctlx_complete_sync(
+ hw,
+ ctlx,
+ init_wrid_completor(&completor,
+ &ctlx->inbuf.wridresp,
+ &wridresult) );
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_dormem
+*
+* Constructs a readmem CTLX and issues it.
+*
+* NOTE: Any changes to the 'post-submit' code in this function
+* need to be carried over to hfa384x_cbrmem() since the handling
+* is virtually identical.
+*
+* Arguments:
+* hw device structure
+* mode DOWAIT or DOASYNC
+* page MAC address space page (CMD format)
+* offset MAC address space offset
+* data Ptr to data buffer to receive read
+* len Length of the data to read (max == 2048)
+* cmdcb command callback for async calls, NULL for DOWAIT calls
+* usercb user callback for async calls, NULL for DOWAIT calls
+* usercb_data user supplied data pointer for async calls
+*
+* Returns:
+* 0 success
+* -ETIMEDOUT timed out waiting for register ready or
+* command completion
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+* Call context:
+* interrupt (DOASYNC)
+* process (DOWAIT or DOASYNC)
+----------------------------------------------------------------*/
+static int
+hfa384x_dormem(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ int result;
+ hfa384x_usbctlx_t *ctlx;
+
+ DBFENTER;
+ ctlx = usbctlx_alloc();
+ if ( ctlx == NULL ) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Initialize the command */
+ ctlx->outbuf.rmemreq.type = host2hfa384x_16(HFA384x_USB_RMEMREQ);
+ ctlx->outbuf.rmemreq.frmlen = host2hfa384x_16(
+ sizeof(ctlx->outbuf.rmemreq.offset) +
+ sizeof(ctlx->outbuf.rmemreq.page) +
+ len);
+ ctlx->outbuf.rmemreq.offset = host2hfa384x_16(offset);
+ ctlx->outbuf.rmemreq.page = host2hfa384x_16(page);
+
+ ctlx->outbufsize = sizeof(ctlx->outbuf.rmemreq);
+
+ WLAN_LOG_DEBUG(4,
+ "type=0x%04x frmlen=%d offset=0x%04x page=0x%04x\n",
+ ctlx->outbuf.rmemreq.type,
+ ctlx->outbuf.rmemreq.frmlen,
+ ctlx->outbuf.rmemreq.offset,
+ ctlx->outbuf.rmemreq.page);
+
+ WLAN_LOG_DEBUG(4,"pktsize=%zd\n",
+ ROUNDUP64(sizeof(ctlx->outbuf.rmemreq)));
+
+ ctlx->reapable = mode;
+ ctlx->cmdcb = cmdcb;
+ ctlx->usercb = usercb;
+ ctlx->usercb_data = usercb_data;
+
+ result = hfa384x_usbctlx_submit(hw, ctlx);
+ if (result != 0) {
+ kfree(ctlx);
+ } else if ( mode == DOWAIT ) {
+ usbctlx_rmem_completor_t completor;
+
+ result = hfa384x_usbctlx_complete_sync(
+ hw, ctlx, init_rmem_completor(&completor,
+ &ctlx->inbuf.rmemresp,
+ data,
+ len) );
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+
+/*----------------------------------------------------------------
+* hfa384x_dowmem
+*
+* Constructs a writemem CTLX and issues it.
+*
+* NOTE: Any changes to the 'post-submit' code in this function
+* need to be carried over to hfa384x_cbwmem() since the handling
+* is virtually identical.
+*
+* Arguments:
+* hw device structure
+* mode DOWAIT or DOASYNC
+* page MAC address space page (CMD format)
+* offset MAC address space offset
+* data Ptr to data buffer containing write data
+* len Length of the data to read (max == 2048)
+* cmdcb command callback for async calls, NULL for DOWAIT calls
+* usercb user callback for async calls, NULL for DOWAIT calls
+* usercb_data user supplied data pointer for async calls.
+*
+* Returns:
+* 0 success
+* -ETIMEDOUT timed out waiting for register ready or
+* command completion
+* >0 command indicated error, Status and Resp0-2 are
+* in hw structure.
+*
+* Side effects:
+*
+* Call context:
+* interrupt (DOWAIT)
+* process (DOWAIT or DOASYNC)
+----------------------------------------------------------------*/
+static int
+hfa384x_dowmem(
+ hfa384x_t *hw,
+ CMD_MODE mode,
+ UINT16 page,
+ UINT16 offset,
+ void *data,
+ UINT len,
+ ctlx_cmdcb_t cmdcb,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ int result;
+ hfa384x_usbctlx_t *ctlx;
+
+ DBFENTER;
+ WLAN_LOG_DEBUG(5, "page=0x%04x offset=0x%04x len=%d\n",
+ page,offset,len);
+
+ ctlx = usbctlx_alloc();
+ if ( ctlx == NULL ) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ /* Initialize the command */
+ ctlx->outbuf.wmemreq.type = host2hfa384x_16(HFA384x_USB_WMEMREQ);
+ ctlx->outbuf.wmemreq.frmlen = host2hfa384x_16(
+ sizeof(ctlx->outbuf.wmemreq.offset) +
+ sizeof(ctlx->outbuf.wmemreq.page) +
+ len);
+ ctlx->outbuf.wmemreq.offset = host2hfa384x_16(offset);
+ ctlx->outbuf.wmemreq.page = host2hfa384x_16(page);
+ memcpy(ctlx->outbuf.wmemreq.data, data, len);
+
+ ctlx->outbufsize = sizeof(ctlx->outbuf.wmemreq.type) +
+ sizeof(ctlx->outbuf.wmemreq.frmlen) +
+ sizeof(ctlx->outbuf.wmemreq.offset) +
+ sizeof(ctlx->outbuf.wmemreq.page) +
+ len;
+
+ ctlx->reapable = mode;
+ ctlx->cmdcb = cmdcb;
+ ctlx->usercb = usercb;
+ ctlx->usercb_data = usercb_data;
+
+ result = hfa384x_usbctlx_submit(hw, ctlx);
+ if (result != 0) {
+ kfree(ctlx);
+ } else if ( mode == DOWAIT ) {
+ usbctlx_wmem_completor_t completor;
+ hfa384x_cmdresult_t wmemresult;
+
+ result = hfa384x_usbctlx_complete_sync(
+ hw,
+ ctlx,
+ init_wmem_completor(&completor,
+ &ctlx->inbuf.wmemresp,
+ &wmemresult) );
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_commtallies
+*
+* Send a commtallies inquiry to the MAC. Note that this is an async
+* call that will result in an info frame arriving sometime later.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* zero success.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_commtallies( hfa384x_t *hw )
+{
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = HFA384x_CMDCODE_INQ;
+ cmd.parm0 = HFA384x_IT_COMMTALLIES;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ hfa384x_docmd_async(hw, &cmd, NULL, NULL, NULL);
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_disable
+*
+* Issues the disable command to stop communications on one of
+* the MACs 'ports'. Only macport 0 is valid for stations.
+* APs may also disable macports 1-6. Only ports that have been
+* previously enabled may be disabled.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number (host order)
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+
+ DBFENTER;
+ if ((!hw->isap && macport != 0) ||
+ (hw->isap && !(macport <= HFA384x_PORTID_MAX)) ||
+ !(hw->port_enabled[macport]) ){
+ result = -EINVAL;
+ } else {
+ result = hfa384x_cmd_disable(hw, macport);
+ if ( result == 0 ) {
+ hw->port_enabled[macport] = 0;
+ }
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_enable
+*
+* Issues the enable command to enable communications on one of
+* the MACs 'ports'. Only macport 0 is valid for stations.
+* APs may also enable macports 1-6. Only ports that are currently
+* disabled may be enabled.
+*
+* Arguments:
+* hw device structure
+* macport MAC port number
+*
+* Returns:
+* 0 success
+* >0 f/w reported failure - f/w status code
+* <0 driver reported error (timeout|bad arg)
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport)
+{
+ int result = 0;
+
+ DBFENTER;
+ if ((!hw->isap && macport != 0) ||
+ (hw->isap && !(macport <= HFA384x_PORTID_MAX)) ||
+ (hw->port_enabled[macport]) ){
+ result = -EINVAL;
+ } else {
+ result = hfa384x_cmd_enable(hw, macport);
+ if ( result == 0 ) {
+ hw->port_enabled[macport] = 1;
+ }
+ }
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_enable
+*
+* Begins the flash download state. Checks to see that we're not
+* already in a download state and that a port isn't enabled.
+* Sets the download state and retrieves the flash download
+* buffer location, buffer size, and timeout length.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_flashdl_enable(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+
+ DBFENTER;
+ /* Check that a port isn't active */
+ for ( i = 0; i < HFA384x_PORTID_MAX; i++) {
+ if ( hw->port_enabled[i] ) {
+ WLAN_LOG_DEBUG(1,"called when port enabled.\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Check that we're not already in a download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) {
+ return -EINVAL;
+ }
+
+ /* Retrieve the buffer loc&size and timeout */
+ if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
+ &(hw->bufinfo), sizeof(hw->bufinfo))) ) {
+ return result;
+ }
+ hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page);
+ hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset);
+ hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len);
+ if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
+ &(hw->dltimeout))) ) {
+ return result;
+ }
+ hw->dltimeout = hfa384x2host_16(hw->dltimeout);
+
+ WLAN_LOG_DEBUG(1,"flashdl_enable\n");
+
+ hw->dlstate = HFA384x_DLSTATE_FLASHENABLED;
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_disable
+*
+* Ends the flash download state. Note that this will cause the MAC
+* firmware to restart.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_flashdl_disable(hfa384x_t *hw)
+{
+ DBFENTER;
+ /* Check that we're already in the download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_DEBUG(1,"flashdl_enable\n");
+
+ /* There isn't much we can do at this point, so I don't */
+ /* bother w/ the return value */
+ hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0);
+ hw->dlstate = HFA384x_DLSTATE_DISABLED;
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_flashdl_write
+*
+* Performs a FLASH download of a chunk of data. First checks to see
+* that we're in the FLASH download state, then sets the download
+* mode, uses the aux functions to 1) copy the data to the flash
+* buffer, 2) sets the download 'write flash' mode, 3) readback and
+* compare. Lather rinse, repeat as many times an necessary to get
+* all the given data into flash.
+* When all data has been written using this function (possibly
+* repeatedly), call drvr_flashdl_disable() to end the download state
+* and restart the MAC.
+*
+* Arguments:
+* hw device structure
+* daddr Card address to write to. (host order)
+* buf Ptr to data to write.
+* len Length of data (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_drvr_flashdl_write(
+ hfa384x_t *hw,
+ UINT32 daddr,
+ void *buf,
+ UINT32 len)
+{
+ int result = 0;
+ UINT32 dlbufaddr;
+ int nburns;
+ UINT32 burnlen;
+ UINT32 burndaddr;
+ UINT16 burnlo;
+ UINT16 burnhi;
+ int nwrites;
+ UINT8 *writebuf;
+ UINT16 writepage;
+ UINT16 writeoffset;
+ UINT32 writelen;
+ int i;
+ int j;
+
+ DBFENTER;
+ WLAN_LOG_DEBUG(5,"daddr=0x%08x len=%d\n", daddr, len);
+
+ /* Check that we're in the flash download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr);
+
+ /* Convert to flat address for arithmetic */
+ /* NOTE: dlbuffer RID stores the address in AUX format */
+ dlbufaddr = HFA384x_ADDR_AUX_MKFLAT(
+ hw->bufinfo.page, hw->bufinfo.offset);
+ WLAN_LOG_DEBUG(5,
+ "dlbuf.page=0x%04x dlbuf.offset=0x%04x dlbufaddr=0x%08x\n",
+ hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr);
+
+#if 0
+WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout);
+#endif
+ /* Calculations to determine how many fills of the dlbuffer to do
+ * and how many USB wmemreq's to do for each fill. At this point
+ * in time, the dlbuffer size and the wmemreq size are the same.
+ * Therefore, nwrites should always be 1. The extra complexity
+ * here is a hedge against future changes.
+ */
+
+ /* Figure out how many times to do the flash programming */
+ nburns = len / hw->bufinfo.len;
+ nburns += (len % hw->bufinfo.len) ? 1 : 0;
+
+ /* For each flash program cycle, how many USB wmemreq's are needed? */
+ nwrites = hw->bufinfo.len / HFA384x_USB_RWMEM_MAXLEN;
+ nwrites += (hw->bufinfo.len % HFA384x_USB_RWMEM_MAXLEN) ? 1 : 0;
+
+ /* For each burn */
+ for ( i = 0; i < nburns; i++) {
+ /* Get the dest address and len */
+ burnlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ?
+ hw->bufinfo.len :
+ (len - (hw->bufinfo.len * i));
+ burndaddr = daddr + (hw->bufinfo.len * i);
+ burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr);
+ burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr);
+
+ WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n",
+ burnlen, burndaddr);
+
+ /* Set the download mode */
+ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV,
+ burnlo, burnhi, burnlen);
+ if ( result ) {
+ WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) "
+ "cmd failed, result=%d. Aborting d/l\n",
+ burnlo, burnhi, burnlen, result);
+ goto exit_proc;
+ }
+
+ /* copy the data to the flash download buffer */
+ for ( j=0; j < nwrites; j++) {
+ writebuf = buf +
+ (i*hw->bufinfo.len) +
+ (j*HFA384x_USB_RWMEM_MAXLEN);
+
+ writepage = HFA384x_ADDR_CMD_MKPAGE(
+ dlbufaddr +
+ (j*HFA384x_USB_RWMEM_MAXLEN));
+ writeoffset = HFA384x_ADDR_CMD_MKOFF(
+ dlbufaddr +
+ (j*HFA384x_USB_RWMEM_MAXLEN));
+
+ writelen = burnlen-(j*HFA384x_USB_RWMEM_MAXLEN);
+ writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ?
+ HFA384x_USB_RWMEM_MAXLEN :
+ writelen;
+
+ result = hfa384x_dowmem_wait( hw,
+ writepage,
+ writeoffset,
+ writebuf,
+ writelen );
+#if 0
+
+Comment out for debugging, assume the write was successful.
+ if (result) {
+ WLAN_LOG_ERROR(
+ "Write to dl buffer failed, "
+ "result=0x%04x. Aborting.\n",
+ result);
+ goto exit_proc;
+ }
+#endif
+
+ }
+
+ /* set the download 'write flash' mode */
+ result = hfa384x_cmd_download(hw,
+ HFA384x_PROGMODE_NVWRITE,
+ 0,0,0);
+ if ( result ) {
+ WLAN_LOG_ERROR(
+ "download(NVWRITE,lo=%x,hi=%x,len=%x) "
+ "cmd failed, result=%d. Aborting d/l\n",
+ burnlo, burnhi, burnlen, result);
+ goto exit_proc;
+ }
+
+ /* TODO: We really should do a readback and compare. */
+ }
+
+exit_proc:
+
+ /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */
+ /* actually disable programming mode. Remember, that will cause the */
+ /* the firmware to effectively reset itself. */
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_getconfig
+*
+* Performs the sequence necessary to read a config/info item.
+*
+* Arguments:
+* hw device structure
+* rid config/info record id (host order)
+* buf host side record buffer. Upon return it will
+* contain the body portion of the record (minus the
+* RID and len).
+* len buffer length (in bytes, should match record length)
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+* -ENODATA length mismatch between argument and retrieved
+* record.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result;
+ DBFENTER;
+
+ result = hfa384x_dorrid_wait(hw, rid, buf, len);
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+ * hfa384x_drvr_getconfig_async
+ *
+ * Performs the sequence necessary to perform an async read of
+ * of a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (host order)
+ * buf host side record buffer. Upon return it will
+ * contain the body portion of the record (minus the
+ * RID and len).
+ * len buffer length (in bytes, should match record length)
+ * cbfn caller supplied callback, called when the command
+ * is done (successful or not).
+ * cbfndata pointer to some caller supplied data that will be
+ * passed in as an argument to the cbfn.
+ *
+ * Returns:
+ * nothing the cbfn gets a status argument identifying if
+ * any errors occur.
+ * Side effects:
+ * Queues an hfa384x_usbcmd_t for subsequent execution.
+ *
+ * Call context:
+ * Any
+ ----------------------------------------------------------------*/
+int
+hfa384x_drvr_getconfig_async(
+ hfa384x_t *hw,
+ UINT16 rid,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dorrid_async(hw, rid, NULL, 0,
+ hfa384x_cb_rrid, usercb, usercb_data);
+}
+
+/*----------------------------------------------------------------
+ * hfa384x_drvr_setconfig_async
+ *
+ * Performs the sequence necessary to write a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * buf host side record buffer
+ * len buffer length (in bytes)
+ * usercb completion callback
+ * usercb_data completion callback argument
+ *
+ * Returns:
+ * 0 success
+ * >0 f/w reported error - f/w status code
+ * <0 driver reported error
+ *
+ * Side effects:
+ *
+ * Call context:
+ * process
+ ----------------------------------------------------------------*/
+int
+hfa384x_drvr_setconfig_async(
+ hfa384x_t *hw,
+ UINT16 rid,
+ void *buf,
+ UINT16 len,
+ ctlx_usercb_t usercb,
+ void *usercb_data)
+{
+ return hfa384x_dowrid_async(hw, rid, buf, len,
+ hfa384x_cb_status, usercb, usercb_data);
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_handover
+*
+* Sends a handover notification to the MAC.
+*
+* Arguments:
+* hw device structure
+* addr address of station that's left
+*
+* Returns:
+* zero success.
+* -ERESTARTSYS received signal while waiting for semaphore.
+* -EIO failed to write to bap, or failed in cmd.
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr)
+{
+ DBFENTER;
+ WLAN_LOG_ERROR("Not currently supported in USB!\n");
+ DBFEXIT;
+ return -EIO;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_low_level
+*
+* Write test commands to the card. Some test commands don't make
+* sense without prior set-up. For example, continous TX isn't very
+* useful until you set the channel. That functionality should be
+*
+* Side effects:
+*
+* Call context:
+* process thread
+* -----------------------------------------------------------------*/
+int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd)
+{
+ int result;
+ DBFENTER;
+
+ /* Do i need a host2hfa... conversion ? */
+
+ result = hfa384x_docmd_wait(hw, cmd);
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_mmi_read
+*
+* Read mmi registers. mmi is intersil-speak for the baseband
+* processor registers.
+*
+* Arguments:
+* hw device structure
+* register The test register to be accessed (must be even #).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp)
+{
+#if 0
+ int result = 0;
+ UINT16 cmd_code = (UINT16) 0x30;
+ UINT16 param = (UINT16) addr;
+ DBFENTER;
+
+ /* Do i need a host2hfa... conversion ? */
+ result = hfa384x_docmd_wait(hw, cmd_code);
+
+ DBFEXIT;
+ return result;
+#endif
+return 0;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_mmi_write
+*
+* Read mmi registers. mmi is intersil-speak for the baseband
+* processor registers.
+*
+* Arguments:
+* hw device structure
+* addr The test register to be accessed (must be even #).
+* data The data value to write to the register.
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+
+int
+hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data)
+{
+#if 0
+ int result = 0;
+ UINT16 cmd_code = (UINT16) 0x31;
+ UINT16 param0 = (UINT16) addr;
+ UINT16 param1 = (UINT16) data;
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08lx\n", addr);
+ WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08lx\n", data);
+
+ /* Do i need a host2hfa... conversion ? */
+ result = hfa384x_docmd_wait(hw, cmd_code);
+
+ DBFEXIT;
+ return result;
+#endif
+return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_disable
+*
+* Ends the ram download state.
+*
+* Arguments:
+* hw device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_drvr_ramdl_disable(hfa384x_t *hw)
+{
+ DBFENTER;
+ /* Check that we're already in the download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_DEBUG(3,"ramdl_disable()\n");
+
+ /* There isn't much we can do at this point, so I don't */
+ /* bother w/ the return value */
+ hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0);
+ hw->dlstate = HFA384x_DLSTATE_DISABLED;
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_enable
+*
+* Begins the ram download state. Checks to see that we're not
+* already in a download state and that a port isn't enabled.
+* Sets the download state and calls cmd_download with the
+* ENABLE_VOLATILE subcommand and the exeaddr argument.
+*
+* Arguments:
+* hw device structure
+* exeaddr the card execution address that will be
+* jumped to when ramdl_disable() is called
+* (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr)
+{
+ int result = 0;
+ UINT16 lowaddr;
+ UINT16 hiaddr;
+ int i;
+ DBFENTER;
+ /* Check that a port isn't active */
+ for ( i = 0; i < HFA384x_PORTID_MAX; i++) {
+ if ( hw->port_enabled[i] ) {
+ WLAN_LOG_ERROR(
+ "Can't download with a macport enabled.\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Check that we're not already in a download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) {
+ WLAN_LOG_ERROR(
+ "Download state not disabled.\n");
+ return -EINVAL;
+ }
+
+ WLAN_LOG_DEBUG(3,"ramdl_enable, exeaddr=0x%08x\n", exeaddr);
+
+ /* Call the download(1,addr) function */
+ lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr);
+ hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr);
+
+ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM,
+ lowaddr, hiaddr, 0);
+
+ if ( result == 0) {
+ /* Set the download state */
+ hw->dlstate = HFA384x_DLSTATE_RAMENABLED;
+ } else {
+ WLAN_LOG_DEBUG(1,
+ "cmd_download(0x%04x, 0x%04x) failed, result=%d.\n",
+ lowaddr,
+ hiaddr,
+ result);
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_ramdl_write
+*
+* Performs a RAM download of a chunk of data. First checks to see
+* that we're in the RAM download state, then uses the [read|write]mem USB
+* commands to 1) copy the data, 2) readback and compare. The download
+* state is unaffected. When all data has been written using
+* this function, call drvr_ramdl_disable() to end the download state
+* and restart the MAC.
+*
+* Arguments:
+* hw device structure
+* daddr Card address to write to. (host order)
+* buf Ptr to data to write.
+* len Length of data (host order).
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len)
+{
+ int result = 0;
+ int nwrites;
+ UINT8 *data = buf;
+ int i;
+ UINT32 curraddr;
+ UINT16 currpage;
+ UINT16 curroffset;
+ UINT16 currlen;
+ DBFENTER;
+ /* Check that we're in the ram download state */
+ if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) {
+ return -EINVAL;
+ }
+
+ WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr);
+
+ /* How many dowmem calls? */
+ nwrites = len / HFA384x_USB_RWMEM_MAXLEN;
+ nwrites += len % HFA384x_USB_RWMEM_MAXLEN ? 1 : 0;
+
+ /* Do blocking wmem's */
+ for(i=0; i < nwrites; i++) {
+ /* make address args */
+ curraddr = daddr + (i * HFA384x_USB_RWMEM_MAXLEN);
+ currpage = HFA384x_ADDR_CMD_MKPAGE(curraddr);
+ curroffset = HFA384x_ADDR_CMD_MKOFF(curraddr);
+ currlen = len - (i * HFA384x_USB_RWMEM_MAXLEN);
+ if ( currlen > HFA384x_USB_RWMEM_MAXLEN) {
+ currlen = HFA384x_USB_RWMEM_MAXLEN;
+ }
+
+ /* Do blocking ctlx */
+ result = hfa384x_dowmem_wait( hw,
+ currpage,
+ curroffset,
+ data + (i*HFA384x_USB_RWMEM_MAXLEN),
+ currlen );
+
+ if (result) break;
+
+ /* TODO: We really should have a readback. */
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_readpda
+*
+* Performs the sequence to read the PDA space. Note there is no
+* drvr_writepda() function. Writing a PDA is
+* generally implemented by a calling component via calls to
+* cmd_download and writing to the flash download buffer via the
+* aux regs.
+*
+* Arguments:
+* hw device structure
+* buf buffer to store PDA in
+* len buffer length
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+* -ETIMEOUT timout waiting for the cmd regs to become
+* available, or waiting for the control reg
+* to indicate the Aux port is enabled.
+* -ENODATA the buffer does NOT contain a valid PDA.
+* Either the card PDA is bad, or the auxdata
+* reads are giving us garbage.
+
+*
+* Side effects:
+*
+* Call context:
+* process or non-card interrupt.
+----------------------------------------------------------------*/
+int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len)
+{
+ int result = 0;
+ UINT16 *pda = buf;
+ int pdaok = 0;
+ int morepdrs = 1;
+ int currpdr = 0; /* word offset of the current pdr */
+ size_t i;
+ UINT16 pdrlen; /* pdr length in bytes, host order */
+ UINT16 pdrcode; /* pdr code, host order */
+ UINT16 currpage;
+ UINT16 curroffset;
+ struct pdaloc {
+ UINT32 cardaddr;
+ UINT16 auxctl;
+ } pdaloc[] =
+ {
+ { HFA3842_PDA_BASE, 0},
+ { HFA3841_PDA_BASE, 0},
+ { HFA3841_PDA_BOGUS_BASE, 0}
+ };
+
+ DBFENTER;
+
+ /* Read the pda from each known address. */
+ for ( i = 0; i < ARRAY_SIZE(pdaloc); i++) {
+ /* Make address */
+ currpage = HFA384x_ADDR_CMD_MKPAGE(pdaloc[i].cardaddr);
+ curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr);
+
+ result = hfa384x_dormem_wait(hw,
+ currpage,
+ curroffset,
+ buf,
+ len); /* units of bytes */
+
+ if (result) {
+ WLAN_LOG_WARNING(
+ "Read from index %zd failed, continuing\n",
+ i );
+ continue;
+ }
+
+ /* Test for garbage */
+ pdaok = 1; /* initially assume good */
+ morepdrs = 1;
+ while ( pdaok && morepdrs ) {
+ pdrlen = hfa384x2host_16(pda[currpdr]) * 2;
+ pdrcode = hfa384x2host_16(pda[currpdr+1]);
+ /* Test the record length */
+ if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) {
+ WLAN_LOG_ERROR("pdrlen invalid=%d\n",
+ pdrlen);
+ pdaok = 0;
+ break;
+ }
+ /* Test the code */
+ if ( !hfa384x_isgood_pdrcode(pdrcode) ) {
+ WLAN_LOG_ERROR("pdrcode invalid=%d\n",
+ pdrcode);
+ pdaok = 0;
+ break;
+ }
+ /* Test for completion */
+ if ( pdrcode == HFA384x_PDR_END_OF_PDA) {
+ morepdrs = 0;
+ }
+
+ /* Move to the next pdr (if necessary) */
+ if ( morepdrs ) {
+ /* note the access to pda[], need words here */
+ currpdr += hfa384x2host_16(pda[currpdr]) + 1;
+ }
+ }
+ if ( pdaok ) {
+ WLAN_LOG_INFO(
+ "PDA Read from 0x%08x in %s space.\n",
+ pdaloc[i].cardaddr,
+ pdaloc[i].auxctl == 0 ? "EXTDS" :
+ pdaloc[i].auxctl == 1 ? "NV" :
+ pdaloc[i].auxctl == 2 ? "PHY" :
+ pdaloc[i].auxctl == 3 ? "ICSRAM" :
+ "<bogus auxctl>");
+ break;
+ }
+ }
+ result = pdaok ? 0 : -ENODATA;
+
+ if ( result ) {
+ WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n");
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_setconfig
+*
+* Performs the sequence necessary to write a config/info item.
+*
+* Arguments:
+* hw device structure
+* rid config/info record id (in host order)
+* buf host side record buffer
+* len buffer length (in bytes)
+*
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ return hfa384x_dowrid_wait(hw, rid, buf, len);
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_start
+*
+* Issues the MAC initialize command, sets up some data structures,
+* and enables the interrupts. After this function completes, the
+* low-level stuff should be ready for any/all commands.
+*
+* Arguments:
+* hw device structure
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int hfa384x_drvr_start(hfa384x_t *hw)
+{
+ int result;
+ DBFENTER;
+
+ might_sleep();
+
+ if (usb_clear_halt(hw->usb, hw->endp_in)) {
+ WLAN_LOG_ERROR(
+ "Failed to reset bulk in endpoint.\n");
+ }
+
+ if (usb_clear_halt(hw->usb, hw->endp_out)) {
+ WLAN_LOG_ERROR(
+ "Failed to reset bulk out endpoint.\n");
+ }
+
+ /* Synchronous unlink, in case we're trying to restart the driver */
+ usb_kill_urb(&hw->rx_urb);
+
+ /* Post the IN urb */
+ result = submit_rx_urb(hw, GFP_KERNEL);
+ if (result != 0) {
+ WLAN_LOG_ERROR(
+ "Fatal, failed to submit RX URB, result=%d\n",
+ result);
+ goto done;
+ }
+
+ /* call initialize */
+ result = hfa384x_cmd_initialize(hw);
+ if (result != 0) {
+ usb_kill_urb(&hw->rx_urb);
+ WLAN_LOG_ERROR(
+ "cmd_initialize() failed, result=%d\n",
+ result);
+ goto done;
+ }
+
+ hw->state = HFA384x_STATE_RUNNING;
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_stop
+*
+* Shuts down the MAC to the point where it is safe to unload the
+* driver. Any subsystem that may be holding a data or function
+* ptr into the driver must be cleared/deinitialized.
+*
+* Arguments:
+* hw device structure
+* Returns:
+* 0 success
+* >0 f/w reported error - f/w status code
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+int
+hfa384x_drvr_stop(hfa384x_t *hw)
+{
+ int result = 0;
+ int i;
+ DBFENTER;
+
+ might_sleep();
+
+ /* There's no need for spinlocks here. The USB "disconnect"
+ * function sets this "removed" flag and then calls us.
+ */
+ if ( !hw->wlandev->hwremoved ) {
+ /* Call initialize to leave the MAC in its 'reset' state */
+ hfa384x_cmd_initialize(hw);
+
+ /* Cancel the rxurb */
+ usb_kill_urb(&hw->rx_urb);
+ }
+
+ hw->link_status = HFA384x_LINK_NOTCONNECTED;
+ hw->state = HFA384x_STATE_INIT;
+
+ del_timer_sync(&hw->commsqual_timer);
+
+ /* Clear all the port status */
+ for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) {
+ hw->port_enabled[i] = 0;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_drvr_txframe
+*
+* Takes a frame from prism2sta and queues it for transmission.
+*
+* Arguments:
+* hw device structure
+* skb packet buffer struct. Contains an 802.11
+* data frame.
+* p80211_hdr points to the 802.11 header for the packet.
+* Returns:
+* 0 Success and more buffs available
+* 1 Success but no more buffs
+* 2 Allocation failure
+* 4 Buffer full or queue busy
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep)
+
+{
+ int usbpktlen = sizeof(hfa384x_tx_frame_t);
+ int result;
+ int ret;
+ char *ptr;
+
+ DBFENTER;
+
+ if (hw->tx_urb.status == -EINPROGRESS) {
+ WLAN_LOG_WARNING("TX URB already in use\n");
+ result = 3;
+ goto exit;
+ }
+
+ /* Build Tx frame structure */
+ /* Set up the control field */
+ memset(&hw->txbuff.txfrm.desc, 0, sizeof(hw->txbuff.txfrm.desc));
+
+ /* Setup the usb type field */
+ hw->txbuff.type = host2hfa384x_16(HFA384x_USB_TXFRM);
+
+ /* Set up the sw_support field to identify this frame */
+ hw->txbuff.txfrm.desc.sw_support = 0x0123;
+
+/* Tx complete and Tx exception disable per dleach. Might be causing
+ * buf depletion
+ */
+//#define DOEXC SLP -- doboth breaks horribly under load, doexc less so.
+#if defined(DOBOTH)
+ hw->txbuff.txfrm.desc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1);
+#elif defined(DOEXC)
+ hw->txbuff.txfrm.desc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0);
+#else
+ hw->txbuff.txfrm.desc.tx_control =
+ HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0);
+#endif
+ hw->txbuff.txfrm.desc.tx_control =
+ host2hfa384x_16(hw->txbuff.txfrm.desc.tx_control);
+
+ /* copy the header over to the txdesc */
+ memcpy(&(hw->txbuff.txfrm.desc.frame_control), p80211_hdr, sizeof(p80211_hdr_t));
+
+ /* if we're using host WEP, increase size by IV+ICV */
+ if (p80211_wep->data) {
+ hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len+8);
+ // hw->txbuff.txfrm.desc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1);
+ usbpktlen+=8;
+ } else {
+ hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len);
+ }
+
+ usbpktlen += skb->len;
+
+ /* copy over the WEP IV if we are using host WEP */
+ ptr = hw->txbuff.txfrm.data;
+ if (p80211_wep->data) {
+ memcpy(ptr, p80211_wep->iv, sizeof(p80211_wep->iv));
+ ptr+= sizeof(p80211_wep->iv);
+ memcpy(ptr, p80211_wep->data, skb->len);
+ } else {
+ memcpy(ptr, skb->data, skb->len);
+ }
+ /* copy over the packet data */
+ ptr+= skb->len;
+
+ /* copy over the WEP ICV if we are using host WEP */
+ if (p80211_wep->data) {
+ memcpy(ptr, p80211_wep->icv, sizeof(p80211_wep->icv));
+ }
+
+ /* Send the USB packet */
+ usb_fill_bulk_urb( &(hw->tx_urb), hw->usb,
+ hw->endp_out,
+ &(hw->txbuff), ROUNDUP64(usbpktlen),
+ hfa384x_usbout_callback, hw->wlandev );
+ hw->tx_urb.transfer_flags |= USB_QUEUE_BULK;
+
+ result = 1;
+ ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC);
+ if ( ret != 0 ) {
+ WLAN_LOG_ERROR(
+ "submit_tx_urb() failed, error=%d\n", ret);
+ result = 3;
+ }
+
+ exit:
+ DBFEXIT;
+ return result;
+}
+
+void hfa384x_tx_timeout(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = wlandev->priv;
+ unsigned long flags;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ if ( !hw->wlandev->hwremoved &&
+ /* Note the bitwise OR, not the logical OR. */
+ ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) |
+ !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) )
+ {
+ schedule_work(&hw->usb_work);
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_reaper_task
+*
+* Tasklet to delete dead CTLX objects
+*
+* Arguments:
+* data ptr to a hfa384x_t
+*
+* Returns:
+*
+* Call context:
+* Interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbctlx_reaper_task(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t*)data;
+ struct list_head *entry;
+ struct list_head *temp;
+ unsigned long flags;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /* This list is guaranteed to be empty if someone
+ * has unplugged the adapter.
+ */
+ list_for_each_safe(entry, temp, &hw->ctlxq.reapable) {
+ hfa384x_usbctlx_t *ctlx;
+
+ ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ list_del(&ctlx->list);
+ kfree(ctlx);
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_completion_task
+*
+* Tasklet to call completion handlers for returned CTLXs
+*
+* Arguments:
+* data ptr to hfa384x_t
+*
+* Returns:
+* Nothing
+*
+* Call context:
+* Interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbctlx_completion_task(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t*)data;
+ struct list_head *entry;
+ struct list_head *temp;
+ unsigned long flags;
+
+ int reap = 0;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /* This list is guaranteed to be empty if someone
+ * has unplugged the adapter ...
+ */
+ list_for_each_safe(entry, temp, &hw->ctlxq.completing) {
+ hfa384x_usbctlx_t *ctlx;
+
+ ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+
+ /* Call the completion function that this
+ * command was assigned, assuming it has one.
+ */
+ if ( ctlx->cmdcb != NULL ) {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ ctlx->cmdcb(hw, ctlx);
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /* Make sure we don't try and complete
+ * this CTLX more than once!
+ */
+ ctlx->cmdcb = NULL;
+
+ /* Did someone yank the adapter out
+ * while our list was (briefly) unlocked?
+ */
+ if ( hw->wlandev->hwremoved )
+ {
+ reap = 0;
+ break;
+ }
+ }
+
+ /*
+ * "Reapable" CTLXs are ones which don't have any
+ * threads waiting for them to die. Hence they must
+ * be delivered to The Reaper!
+ */
+ if ( ctlx->reapable ) {
+ /* Move the CTLX off the "completing" list (hopefully)
+ * on to the "reapable" list where the reaper task
+ * can find it. And "reapable" means that this CTLX
+ * isn't sitting on a wait-queue somewhere.
+ */
+ list_move_tail(&ctlx->list, &hw->ctlxq.reapable);
+ reap = 1;
+ }
+
+ complete(&ctlx->done);
+ }
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ if (reap)
+ tasklet_schedule(&hw->reaper_bh);
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* unlocked_usbctlx_cancel_async
+*
+* Mark the CTLX dead asynchronously, and ensure that the
+* next command on the queue is run afterwards.
+*
+* Arguments:
+* hw ptr to the hfa384x_t structure
+* ctlx ptr to a CTLX structure
+*
+* Returns:
+* 0 the CTLX's URB is inactive
+* -EINPROGRESS the URB is currently being unlinked
+*
+* Call context:
+* Either process or interrupt, but presumably interrupt
+----------------------------------------------------------------*/
+static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx)
+{
+ int ret;
+
+ DBFENTER;
+
+ /*
+ * Try to delete the URB containing our request packet.
+ * If we succeed, then its completion handler will be
+ * called with a status of -ECONNRESET.
+ */
+ hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK;
+ ret = usb_unlink_urb(&hw->ctlx_urb);
+
+ if (ret != -EINPROGRESS) {
+ /*
+ * The OUT URB had either already completed
+ * or was still in the pending queue, so the
+ * URB's completion function will not be called.
+ * We will have to complete the CTLX ourselves.
+ */
+ ctlx->state = CTLX_REQ_FAILED;
+ unlocked_usbctlx_complete(hw, ctlx);
+ ret = 0;
+ }
+
+ DBFEXIT;
+
+ return ret;
+}
+
+/*----------------------------------------------------------------
+* unlocked_usbctlx_complete
+*
+* A CTLX has completed. It may have been successful, it may not
+* have been. At this point, the CTLX should be quiescent. The URBs
+* aren't active and the timers should have been stopped.
+*
+* The CTLX is migrated to the "completing" queue, and the completing
+* tasklet is scheduled.
+*
+* Arguments:
+* hw ptr to a hfa384x_t structure
+* ctlx ptr to a ctlx structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* Either, assume interrupt
+----------------------------------------------------------------*/
+static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx)
+{
+ DBFENTER;
+
+ /* Timers have been stopped, and ctlx should be in
+ * a terminal state. Retire it from the "active"
+ * queue.
+ */
+ list_move_tail(&ctlx->list, &hw->ctlxq.completing);
+ tasklet_schedule(&hw->completion_bh);
+
+ switch (ctlx->state) {
+ case CTLX_COMPLETE:
+ case CTLX_REQ_FAILED:
+ /* This are the correct terminating states. */
+ break;
+
+ default:
+ WLAN_LOG_ERROR("CTLX[%d] not in a terminating state(%s)\n",
+ hfa384x2host_16(ctlx->outbuf.type),
+ ctlxstr(ctlx->state));
+ break;
+ } /* switch */
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlxq_run
+*
+* Checks to see if the head item is running. If not, starts it.
+*
+* Arguments:
+* hw ptr to hfa384x_t
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* any
+----------------------------------------------------------------*/
+static void
+hfa384x_usbctlxq_run(hfa384x_t *hw)
+{
+ unsigned long flags;
+ DBFENTER;
+
+ /* acquire lock */
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /* Only one active CTLX at any one time, because there's no
+ * other (reliable) way to match the response URB to the
+ * correct CTLX.
+ *
+ * Don't touch any of these CTLXs if the hardware
+ * has been removed or the USB subsystem is stalled.
+ */
+ if ( !list_empty(&hw->ctlxq.active) ||
+ test_bit(WORK_TX_HALT, &hw->usb_flags) ||
+ hw->wlandev->hwremoved )
+ goto unlock;
+
+ while ( !list_empty(&hw->ctlxq.pending) ) {
+ hfa384x_usbctlx_t *head;
+ int result;
+
+ /* This is the first pending command */
+ head = list_entry(hw->ctlxq.pending.next,
+ hfa384x_usbctlx_t,
+ list);
+
+ /* We need to split this off to avoid a race condition */
+ list_move_tail(&head->list, &hw->ctlxq.active);
+
+ /* Fill the out packet */
+ usb_fill_bulk_urb( &(hw->ctlx_urb), hw->usb,
+ hw->endp_out,
+ &(head->outbuf), ROUNDUP64(head->outbufsize),
+ hfa384x_ctlxout_callback, hw);
+ hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK;
+
+ /* Now submit the URB and update the CTLX's state
+ */
+ if ((result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC)) == 0) {
+ /* This CTLX is now running on the active queue */
+ head->state = CTLX_REQ_SUBMITTED;
+
+ /* Start the OUT wait timer */
+ hw->req_timer_done = 0;
+ hw->reqtimer.expires = jiffies + HZ;
+ add_timer(&hw->reqtimer);
+
+ /* Start the IN wait timer */
+ hw->resp_timer_done = 0;
+ hw->resptimer.expires = jiffies + 2*HZ;
+ add_timer(&hw->resptimer);
+
+ break;
+ }
+
+ if (result == -EPIPE) {
+ /* The OUT pipe needs resetting, so put
+ * this CTLX back in the "pending" queue
+ * and schedule a reset ...
+ */
+ WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n",
+ hw->wlandev->netdev->name);
+ list_move(&head->list, &hw->ctlxq.pending);
+ set_bit(WORK_TX_HALT, &hw->usb_flags);
+ schedule_work(&hw->usb_work);
+ break;
+ }
+
+ if (result == -ESHUTDOWN) {
+ WLAN_LOG_WARNING("%s urb shutdown!\n",
+ hw->wlandev->netdev->name);
+ break;
+ }
+
+ WLAN_LOG_ERROR("Failed to submit CTLX[%d]: error=%d\n",
+ hfa384x2host_16(head->outbuf.type), result);
+ unlocked_usbctlx_complete(hw, head);
+ } /* while */
+
+ unlock:
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbin_callback
+*
+* Callback for URBs on the BULKIN endpoint.
+*
+* Arguments:
+* urb ptr to the completed urb
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+#ifdef URB_ONLY_CALLBACK
+static void hfa384x_usbin_callback(struct urb *urb)
+#else
+static void hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs)
+#endif
+{
+ wlandevice_t *wlandev = urb->context;
+ hfa384x_t *hw;
+ hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) urb->transfer_buffer;
+ struct sk_buff *skb = NULL;
+ int result;
+ int urb_status;
+ UINT16 type;
+
+ enum USBIN_ACTION {
+ HANDLE,
+ RESUBMIT,
+ ABORT
+ } action;
+
+ DBFENTER;
+
+ if ( !wlandev ||
+ !wlandev->netdev ||
+ !netif_device_present(wlandev->netdev) )
+ goto exit;
+
+ hw = wlandev->priv;
+ if (!hw)
+ goto exit;
+
+ skb = hw->rx_urb_skb;
+ if (!skb || (skb->data != urb->transfer_buffer)) {
+ BUG();
+ }
+ hw->rx_urb_skb = NULL;
+
+ /* Check for error conditions within the URB */
+ switch (urb->status) {
+ case 0:
+ action = HANDLE;
+
+ /* Check for short packet */
+ if ( urb->actual_length == 0 ) {
+ ++(wlandev->linux_stats.rx_errors);
+ ++(wlandev->linux_stats.rx_length_errors);
+ action = RESUBMIT;
+ }
+ break;
+
+ case -EPIPE:
+ WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n",
+ wlandev->netdev->name);
+ if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) )
+ schedule_work(&hw->usb_work);
+ ++(wlandev->linux_stats.rx_errors);
+ action = ABORT;
+ break;
+
+ case -EILSEQ:
+ case -ETIMEDOUT:
+ case -EPROTO:
+ if ( !test_and_set_bit(THROTTLE_RX, &hw->usb_flags) &&
+ !timer_pending(&hw->throttle) ) {
+ mod_timer(&hw->throttle, jiffies + THROTTLE_JIFFIES);
+ }
+ ++(wlandev->linux_stats.rx_errors);
+ action = ABORT;
+ break;
+
+ case -EOVERFLOW:
+ ++(wlandev->linux_stats.rx_over_errors);
+ action = RESUBMIT;
+ break;
+
+ case -ENODEV:
+ case -ESHUTDOWN:
+ WLAN_LOG_DEBUG(3,"status=%d, device removed.\n", urb->status);
+ action = ABORT;
+ break;
+
+ case -ENOENT:
+ case -ECONNRESET:
+ WLAN_LOG_DEBUG(3,"status=%d, urb explicitly unlinked.\n", urb->status);
+ action = ABORT;
+ break;
+
+ default:
+ WLAN_LOG_DEBUG(3,"urb status=%d, transfer flags=0x%x\n",
+ urb->status, urb->transfer_flags);
+ ++(wlandev->linux_stats.rx_errors);
+ action = RESUBMIT;
+ break;
+ }
+
+ urb_status = urb->status;
+
+ if (action != ABORT) {
+ /* Repost the RX URB */
+ result = submit_rx_urb(hw, GFP_ATOMIC);
+
+ if (result != 0) {
+ WLAN_LOG_ERROR(
+ "Fatal, failed to resubmit rx_urb. error=%d\n",
+ result);
+ }
+ }
+
+ /* Handle any USB-IN packet */
+ /* Note: the check of the sw_support field, the type field doesn't
+ * have bit 12 set like the docs suggest.
+ */
+ type = hfa384x2host_16(usbin->type);
+ if (HFA384x_USB_ISRXFRM(type)) {
+ if (action == HANDLE) {
+ if (usbin->txfrm.desc.sw_support == 0x0123) {
+ hfa384x_usbin_txcompl(wlandev, usbin);
+ } else {
+ skb_put(skb, sizeof(*usbin));
+ hfa384x_usbin_rx(wlandev, skb);
+ skb = NULL;
+ }
+ }
+ goto exit;
+ }
+ if (HFA384x_USB_ISTXFRM(type)) {
+ if (action == HANDLE)
+ hfa384x_usbin_txcompl(wlandev, usbin);
+ goto exit;
+ }
+ switch (type) {
+ case HFA384x_USB_INFOFRM:
+ if (action == ABORT)
+ goto exit;
+ if (action == HANDLE)
+ hfa384x_usbin_info(wlandev, usbin);
+ break;
+
+ case HFA384x_USB_CMDRESP:
+ case HFA384x_USB_WRIDRESP:
+ case HFA384x_USB_RRIDRESP:
+ case HFA384x_USB_WMEMRESP:
+ case HFA384x_USB_RMEMRESP:
+ /* ALWAYS, ALWAYS, ALWAYS handle this CTLX!!!! */
+ hfa384x_usbin_ctlx(hw, usbin, urb_status);
+ break;
+
+ case HFA384x_USB_BUFAVAIL:
+ WLAN_LOG_DEBUG(3,"Received BUFAVAIL packet, frmlen=%d\n",
+ usbin->bufavail.frmlen);
+ break;
+
+ case HFA384x_USB_ERROR:
+ WLAN_LOG_DEBUG(3,"Received USB_ERROR packet, errortype=%d\n",
+ usbin->usberror.errortype);
+ break;
+
+ default:
+ WLAN_LOG_DEBUG(3,"Unrecognized USBIN packet, type=%x, status=%d\n",
+ usbin->type, urb_status);
+ break;
+ } /* switch */
+
+exit:
+
+ if (skb)
+ dev_kfree_skb(skb);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbin_ctlx
+*
+* We've received a URB containing a Prism2 "response" message.
+* This message needs to be matched up with a CTLX on the active
+* queue and our state updated accordingly.
+*
+* Arguments:
+* hw ptr to hfa384x_t
+* usbin ptr to USB IN packet
+* urb_status status of this Bulk-In URB
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin,
+ int urb_status)
+{
+ hfa384x_usbctlx_t *ctlx;
+ int run_queue = 0;
+ unsigned long flags;
+
+ DBFENTER;
+
+retry:
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /* There can be only one CTLX on the active queue
+ * at any one time, and this is the CTLX that the
+ * timers are waiting for.
+ */
+ if ( list_empty(&hw->ctlxq.active) ) {
+ goto unlock;
+ }
+
+ /* Remove the "response timeout". It's possible that
+ * we are already too late, and that the timeout is
+ * already running. And that's just too bad for us,
+ * because we could lose our CTLX from the active
+ * queue here ...
+ */
+ if (del_timer(&hw->resptimer) == 0) {
+ if (hw->resp_timer_done == 0) {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ goto retry;
+ }
+ }
+ else {
+ hw->resp_timer_done = 1;
+ }
+
+ ctlx = get_active_ctlx(hw);
+
+ if (urb_status != 0) {
+ /*
+ * Bad CTLX, so get rid of it. But we only
+ * remove it from the active queue if we're no
+ * longer expecting the OUT URB to complete.
+ */
+ if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0)
+ run_queue = 1;
+ } else {
+ const UINT16 intype = (usbin->type&~host2hfa384x_16(0x8000));
+
+ /*
+ * Check that our message is what we're expecting ...
+ */
+ if (ctlx->outbuf.type != intype) {
+ WLAN_LOG_WARNING("Expected IN[%d], received IN[%d] - ignored.\n",
+ hfa384x2host_16(ctlx->outbuf.type),
+ hfa384x2host_16(intype));
+ goto unlock;
+ }
+
+ /* This URB has succeeded, so grab the data ... */
+ memcpy(&ctlx->inbuf, usbin, sizeof(ctlx->inbuf));
+
+ switch (ctlx->state) {
+ case CTLX_REQ_SUBMITTED:
+ /*
+ * We have received our response URB before
+ * our request has been acknowledged. Odd,
+ * but our OUT URB is still alive...
+ */
+ WLAN_LOG_DEBUG(0, "Causality violation: please reboot Universe, or email linux-wlan-devel@lists.linux-wlan.com\n");
+ ctlx->state = CTLX_RESP_COMPLETE;
+ break;
+
+ case CTLX_REQ_COMPLETE:
+ /*
+ * This is the usual path: our request
+ * has already been acknowledged, and
+ * now we have received the reply too.
+ */
+ ctlx->state = CTLX_COMPLETE;
+ unlocked_usbctlx_complete(hw, ctlx);
+ run_queue = 1;
+ break;
+
+ default:
+ /*
+ * Throw this CTLX away ...
+ */
+ WLAN_LOG_ERROR("Matched IN URB, CTLX[%d] in invalid state(%s)."
+ " Discarded.\n",
+ hfa384x2host_16(ctlx->outbuf.type),
+ ctlxstr(ctlx->state));
+ if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0)
+ run_queue = 1;
+ break;
+ } /* switch */
+ }
+
+unlock:
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ if (run_queue)
+ hfa384x_usbctlxq_run(hw);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbin_txcompl
+*
+* At this point we have the results of a previous transmit.
+*
+* Arguments:
+* wlandev wlan device
+* usbin ptr to the usb transfer buffer
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin)
+{
+ UINT16 status;
+ DBFENTER;
+
+ status = hfa384x2host_16(usbin->type); /* yeah I know it says type...*/
+
+ /* Was there an error? */
+ if (HFA384x_TXSTATUS_ISERROR(status)) {
+ prism2sta_ev_txexc(wlandev, status);
+ } else {
+ prism2sta_ev_tx(wlandev, status);
+ }
+ // prism2sta_ev_alloc(wlandev);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbin_rx
+*
+* At this point we have a successful received a rx frame packet.
+*
+* Arguments:
+* wlandev wlan device
+* usbin ptr to the usb transfer buffer
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb)
+{
+ hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) skb->data;
+ hfa384x_t *hw = wlandev->priv;
+ int hdrlen;
+ p80211_rxmeta_t *rxmeta;
+ UINT16 data_len;
+ UINT16 fc;
+
+ DBFENTER;
+
+ /* Byte order convert once up front. */
+ usbin->rxfrm.desc.status =
+ hfa384x2host_16(usbin->rxfrm.desc.status);
+ usbin->rxfrm.desc.time =
+ hfa384x2host_32(usbin->rxfrm.desc.time);
+
+ /* Now handle frame based on port# */
+ switch( HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) )
+ {
+ case 0:
+ fc = ieee2host16(usbin->rxfrm.desc.frame_control);
+
+ /* If exclude and we receive an unencrypted, drop it */
+ if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) &&
+ !WLAN_GET_FC_ISWEP(fc)){
+ goto done;
+ }
+
+ data_len = hfa384x2host_16(usbin->rxfrm.desc.data_len);
+
+ /* How much header data do we have? */
+ hdrlen = p80211_headerlen(fc);
+
+ /* Pull off the descriptor */
+ skb_pull(skb, sizeof(hfa384x_rx_frame_t));
+
+ /* Now shunt the header block up against the data block
+ * with an "overlapping" copy
+ */
+ memmove(skb_push(skb, hdrlen),
+ &usbin->rxfrm.desc.frame_control,
+ hdrlen);
+
+ skb->dev = wlandev->netdev;
+ skb->dev->last_rx = jiffies;
+
+ /* And set the frame length properly */
+ skb_trim(skb, data_len + hdrlen);
+
+ /* The prism2 series does not return the CRC */
+ memset(skb_put(skb, WLAN_CRC_LEN), 0xff, WLAN_CRC_LEN);
+
+ skb_reset_mac_header(skb);
+
+ /* Attach the rxmeta, set some stuff */
+ p80211skb_rxmeta_attach(wlandev, skb);
+ rxmeta = P80211SKB_RXMETA(skb);
+ rxmeta->mactime = usbin->rxfrm.desc.time;
+ rxmeta->rxrate = usbin->rxfrm.desc.rate;
+ rxmeta->signal = usbin->rxfrm.desc.signal - hw->dbmadjust;
+ rxmeta->noise = usbin->rxfrm.desc.silence - hw->dbmadjust;
+
+ prism2sta_ev_rx(wlandev, skb);
+
+ break;
+
+ case 7:
+ if ( ! HFA384x_RXSTATUS_ISFCSERR(usbin->rxfrm.desc.status) ) {
+ /* Copy to wlansnif skb */
+ hfa384x_int_rxmonitor( wlandev, &usbin->rxfrm);
+ dev_kfree_skb(skb);
+ } else {
+ WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n");
+ }
+ break;
+
+ default:
+ WLAN_LOG_WARNING("Received frame on unsupported port=%d\n",
+ HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) );
+ goto done;
+ break;
+ }
+
+done:
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_int_rxmonitor
+*
+* Helper function for int_rx. Handles monitor frames.
+* Note that this function allocates space for the FCS and sets it
+* to 0xffffffff. The hfa384x doesn't give us the FCS value but the
+* higher layers expect it. 0xffffffff is used as a flag to indicate
+* the FCS is bogus.
+*
+* Arguments:
+* wlandev wlan device structure
+* rxfrm rx descriptor read from card in int_rx
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* Allocates an skb and passes it up via the PF_PACKET interface.
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm)
+{
+ hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc);
+ UINT hdrlen = 0;
+ UINT datalen = 0;
+ UINT skblen = 0;
+ p80211msg_lnxind_wlansniffrm_t *msg;
+ UINT8 *datap;
+ UINT16 fc;
+ struct sk_buff *skb;
+ hfa384x_t *hw = wlandev->priv;
+
+
+ DBFENTER;
+ /* Don't forget the status, time, and data_len fields are in host order */
+ /* Figure out how big the frame is */
+ fc = ieee2host16(rxdesc->frame_control);
+ hdrlen = p80211_headerlen(fc);
+ datalen = hfa384x2host_16(rxdesc->data_len);
+
+ /* Allocate an ind message+framesize skb */
+ skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) +
+ hdrlen + datalen + WLAN_CRC_LEN;
+
+ /* sanity check the length */
+ if ( skblen >
+ (sizeof(p80211msg_lnxind_wlansniffrm_t) +
+ WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) {
+ WLAN_LOG_DEBUG(1, "overlen frm: len=%zd\n",
+ skblen - sizeof(p80211msg_lnxind_wlansniffrm_t));
+ }
+
+ if ( (skb = dev_alloc_skb(skblen)) == NULL ) {
+ WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen);
+ return;
+ }
+
+ /* only prepend the prism header if in the right mode */
+ if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) &&
+ (hw->sniffhdr == 0)) {
+ datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t));
+ msg = (p80211msg_lnxind_wlansniffrm_t*) datap;
+
+ /* Initialize the message members */
+ msg->msgcode = DIDmsg_lnxind_wlansniffrm;
+ msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
+ strcpy(msg->devname, wlandev->name);
+
+ msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+ msg->hosttime.status = 0;
+ msg->hosttime.len = 4;
+ msg->hosttime.data = jiffies;
+
+ msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+ msg->mactime.status = 0;
+ msg->mactime.len = 4;
+ msg->mactime.data = rxdesc->time;
+
+ msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+ msg->channel.status = 0;
+ msg->channel.len = 4;
+ msg->channel.data = hw->sniff_channel;
+
+ msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+ msg->rssi.status = P80211ENUM_msgitem_status_no_value;
+ msg->rssi.len = 4;
+ msg->rssi.data = 0;
+
+ msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
+ msg->sq.status = P80211ENUM_msgitem_status_no_value;
+ msg->sq.len = 4;
+ msg->sq.data = 0;
+
+ msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+ msg->signal.status = 0;
+ msg->signal.len = 4;
+ msg->signal.data = rxdesc->signal;
+
+ msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+ msg->noise.status = 0;
+ msg->noise.len = 4;
+ msg->noise.data = rxdesc->silence;
+
+ msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+ msg->rate.status = 0;
+ msg->rate.len = 4;
+ msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */
+
+ msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+ msg->istx.status = 0;
+ msg->istx.len = 4;
+ msg->istx.data = P80211ENUM_truth_false;
+
+ msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+ msg->frmlen.status = 0;
+ msg->frmlen.len = 4;
+ msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN;
+ } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) &&
+ (hw->sniffhdr != 0)) {
+ p80211_caphdr_t *caphdr;
+ /* The NEW header format! */
+ datap = skb_put(skb, sizeof(p80211_caphdr_t));
+ caphdr = (p80211_caphdr_t*) datap;
+
+ caphdr->version = htonl(P80211CAPTURE_VERSION);
+ caphdr->length = htonl(sizeof(p80211_caphdr_t));
+ caphdr->mactime = __cpu_to_be64(rxdesc->time) * 1000;
+ caphdr->hosttime = __cpu_to_be64(jiffies);
+ caphdr->phytype = htonl(4); /* dss_dot11_b */
+ caphdr->channel = htonl(hw->sniff_channel);
+ caphdr->datarate = htonl(rxdesc->rate);
+ caphdr->antenna = htonl(0); /* unknown */
+ caphdr->priority = htonl(0); /* unknown */
+ caphdr->ssi_type = htonl(3); /* rssi_raw */
+ caphdr->ssi_signal = htonl(rxdesc->signal);
+ caphdr->ssi_noise = htonl(rxdesc->silence);
+ caphdr->preamble = htonl(0); /* unknown */
+ caphdr->encoding = htonl(1); /* cck */
+ }
+
+ /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */
+ datap = skb_put(skb, hdrlen);
+ memcpy( datap, &(rxdesc->frame_control), hdrlen);
+
+ /* If any, copy the data from the card to the skb */
+ if ( datalen > 0 )
+ {
+ datap = skb_put(skb, datalen);
+ memcpy(datap, rxfrm->data, datalen);
+
+ /* check for unencrypted stuff if WEP bit set. */
+ if (*(datap - hdrlen + 1) & 0x40) // wep set
+ if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa))
+ *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header!
+ }
+
+ if (hw->sniff_fcs) {
+ /* Set the FCS */
+ datap = skb_put(skb, WLAN_CRC_LEN);
+ memset( datap, 0xff, WLAN_CRC_LEN);
+ }
+
+ /* pass it back up */
+ prism2sta_ev_rx(wlandev, skb);
+
+ DBFEXIT;
+ return;
+}
+
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbin_info
+*
+* At this point we have a successful received a Prism2 info frame.
+*
+* Arguments:
+* wlandev wlan device
+* usbin ptr to the usb transfer buffer
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin)
+{
+ DBFENTER;
+
+ usbin->infofrm.info.framelen = hfa384x2host_16(usbin->infofrm.info.framelen);
+ prism2sta_ev_info(wlandev, &usbin->infofrm.info);
+
+ DBFEXIT;
+}
+
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbout_callback
+*
+* Callback for URBs on the BULKOUT endpoint.
+*
+* Arguments:
+* urb ptr to the completed urb
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+#ifdef URB_ONLY_CALLBACK
+static void hfa384x_usbout_callback(struct urb *urb)
+#else
+static void hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs)
+#endif
+{
+ wlandevice_t *wlandev = urb->context;
+ hfa384x_usbout_t *usbout = urb->transfer_buffer;
+ DBFENTER;
+
+#ifdef DEBUG_USB
+ dbprint_urb(urb);
+#endif
+
+ if ( wlandev &&
+ wlandev->netdev ) {
+
+ switch(urb->status) {
+ case 0:
+ hfa384x_usbout_tx(wlandev, usbout);
+ break;
+
+ case -EPIPE:
+ {
+ hfa384x_t *hw = wlandev->priv;
+ WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n",
+ wlandev->netdev->name);
+ if ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) )
+ schedule_work(&hw->usb_work);
+ ++(wlandev->linux_stats.tx_errors);
+ break;
+ }
+
+ case -EPROTO:
+ case -ETIMEDOUT:
+ case -EILSEQ:
+ {
+ hfa384x_t *hw = wlandev->priv;
+
+ if ( !test_and_set_bit(THROTTLE_TX, &hw->usb_flags)
+ && !timer_pending(&hw->throttle) ) {
+ mod_timer(&hw->throttle,
+ jiffies + THROTTLE_JIFFIES);
+ }
+ ++(wlandev->linux_stats.tx_errors);
+ netif_stop_queue(wlandev->netdev);
+ break;
+ }
+
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* Ignorable errors */
+ break;
+
+ default:
+ WLAN_LOG_INFO("unknown urb->status=%d\n", urb->status);
+ ++(wlandev->linux_stats.tx_errors);
+ break;
+ } /* switch */
+ }
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_ctlxout_callback
+*
+* Callback for control data on the BULKOUT endpoint.
+*
+* Arguments:
+* urb ptr to the completed urb
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+#ifdef URB_ONLY_CALLBACK
+static void hfa384x_ctlxout_callback(struct urb *urb)
+#else
+static void hfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs)
+#endif
+{
+ hfa384x_t *hw = urb->context;
+ int delete_resptimer = 0;
+ int timer_ok = 1;
+ int run_queue = 0;
+ hfa384x_usbctlx_t *ctlx;
+ unsigned long flags;
+
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(3,"urb->status=%d\n", urb->status);
+#ifdef DEBUG_USB
+ dbprint_urb(urb);
+#endif
+ if ( (urb->status == -ESHUTDOWN) ||
+ (urb->status == -ENODEV) ||
+ (hw == NULL) )
+ goto done;
+
+retry:
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /*
+ * Only one CTLX at a time on the "active" list, and
+ * none at all if we are unplugged. However, we can
+ * rely on the disconnect function to clean everything
+ * up if someone unplugged the adapter.
+ */
+ if ( list_empty(&hw->ctlxq.active) ) {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ goto done;
+ }
+
+ /*
+ * Having something on the "active" queue means
+ * that we have timers to worry about ...
+ */
+ if (del_timer(&hw->reqtimer) == 0) {
+ if (hw->req_timer_done == 0) {
+ /*
+ * This timer was actually running while we
+ * were trying to delete it. Let it terminate
+ * gracefully instead.
+ */
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ goto retry;
+ }
+ }
+ else {
+ hw->req_timer_done = 1;
+ }
+
+ ctlx = get_active_ctlx(hw);
+
+ if ( urb->status == 0 ) {
+ /* Request portion of a CTLX is successful */
+ switch ( ctlx->state ) {
+ case CTLX_REQ_SUBMITTED:
+ /* This OUT-ACK received before IN */
+ ctlx->state = CTLX_REQ_COMPLETE;
+ break;
+
+ case CTLX_RESP_COMPLETE:
+ /* IN already received before this OUT-ACK,
+ * so this command must now be complete.
+ */
+ ctlx->state = CTLX_COMPLETE;
+ unlocked_usbctlx_complete(hw, ctlx);
+ run_queue = 1;
+ break;
+
+ default:
+ /* This is NOT a valid CTLX "success" state! */
+ WLAN_LOG_ERROR(
+ "Illegal CTLX[%d] success state(%s, %d) in OUT URB\n",
+ hfa384x2host_16(ctlx->outbuf.type),
+ ctlxstr(ctlx->state), urb->status);
+ break;
+ } /* switch */
+ } else {
+ /* If the pipe has stalled then we need to reset it */
+ if ( (urb->status == -EPIPE) &&
+ !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) {
+ WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n",
+ hw->wlandev->netdev->name);
+ schedule_work(&hw->usb_work);
+ }
+
+ /* If someone cancels the OUT URB then its status
+ * should be either -ECONNRESET or -ENOENT.
+ */
+ ctlx->state = CTLX_REQ_FAILED;
+ unlocked_usbctlx_complete(hw, ctlx);
+ delete_resptimer = 1;
+ run_queue = 1;
+ }
+
+ delresp:
+ if (delete_resptimer) {
+ if ((timer_ok = del_timer(&hw->resptimer)) != 0) {
+ hw->resp_timer_done = 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ if ( !timer_ok && (hw->resp_timer_done == 0) ) {
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+ goto delresp;
+ }
+
+ if (run_queue)
+ hfa384x_usbctlxq_run(hw);
+
+ done:
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_reqtimerfn
+*
+* Timer response function for CTLX request timeouts. If this
+* function is called, it means that the callback for the OUT
+* URB containing a Prism2.x XXX_Request was never called.
+*
+* Arguments:
+* data a ptr to the hfa384x_t
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void
+hfa384x_usbctlx_reqtimerfn(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t*)data;
+ unsigned long flags;
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ hw->req_timer_done = 1;
+
+ /* Removing the hardware automatically empties
+ * the active list ...
+ */
+ if ( !list_empty(&hw->ctlxq.active) )
+ {
+ /*
+ * We must ensure that our URB is removed from
+ * the system, if it hasn't already expired.
+ */
+ hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK;
+ if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS)
+ {
+ hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw);
+
+ ctlx->state = CTLX_REQ_FAILED;
+
+ /* This URB was active, but has now been
+ * cancelled. It will now have a status of
+ * -ECONNRESET in the callback function.
+ *
+ * We are cancelling this CTLX, so we're
+ * not going to need to wait for a response.
+ * The URB's callback function will check
+ * that this timer is truly dead.
+ */
+ if (del_timer(&hw->resptimer) != 0)
+ hw->resp_timer_done = 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_resptimerfn
+*
+* Timer response function for CTLX response timeouts. If this
+* function is called, it means that the callback for the IN
+* URB containing a Prism2.x XXX_Response was never called.
+*
+* Arguments:
+* data a ptr to the hfa384x_t
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void
+hfa384x_usbctlx_resptimerfn(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t*)data;
+ unsigned long flags;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ hw->resp_timer_done = 1;
+
+ /* The active list will be empty if the
+ * adapter has been unplugged ...
+ */
+ if ( !list_empty(&hw->ctlxq.active) )
+ {
+ hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw);
+
+ if ( unlocked_usbctlx_cancel_async(hw, ctlx) == 0 )
+ {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ hfa384x_usbctlxq_run(hw);
+ goto done;
+ }
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ done:
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_usb_throttlefn
+*
+*
+* Arguments:
+* data ptr to hw
+*
+* Returns:
+* Nothing
+*
+* Side effects:
+*
+* Call context:
+* Interrupt
+----------------------------------------------------------------*/
+static void
+hfa384x_usb_throttlefn(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t*)data;
+ unsigned long flags;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ /*
+ * We need to check BOTH the RX and the TX throttle controls,
+ * so we use the bitwise OR instead of the logical OR.
+ */
+ WLAN_LOG_DEBUG(3, "flags=0x%lx\n", hw->usb_flags);
+ if ( !hw->wlandev->hwremoved &&
+ (
+ (test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) &&
+ !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags))
+ |
+ (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) &&
+ !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags))
+ ) )
+ {
+ schedule_work(&hw->usb_work);
+ }
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbctlx_submit
+*
+* Called from the doxxx functions to submit a CTLX to the queue
+*
+* Arguments:
+* hw ptr to the hw struct
+* ctlx ctlx structure to enqueue
+*
+* Returns:
+* -ENODEV if the adapter is unplugged
+* 0
+*
+* Side effects:
+*
+* Call context:
+* process or interrupt
+----------------------------------------------------------------*/
+static int
+hfa384x_usbctlx_submit(
+ hfa384x_t *hw,
+ hfa384x_usbctlx_t *ctlx)
+{
+ unsigned long flags;
+ int ret;
+
+ DBFENTER;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ if (hw->wlandev->hwremoved) {
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ ret = -ENODEV;
+ } else {
+ ctlx->state = CTLX_PENDING;
+ list_add_tail(&ctlx->list, &hw->ctlxq.pending);
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+ hfa384x_usbctlxq_run(hw);
+ ret = 0;
+ }
+
+ DBFEXIT;
+ return ret;
+}
+
+
+/*----------------------------------------------------------------
+* hfa384x_usbout_tx
+*
+* At this point we have finished a send of a frame. Mark the URB
+* as available and call ev_alloc to notify higher layers we're
+* ready for more.
+*
+* Arguments:
+* wlandev wlan device
+* usbout ptr to the usb transfer buffer
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout)
+{
+ DBFENTER;
+
+ prism2sta_ev_alloc(wlandev);
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* hfa384x_isgood_pdrcore
+*
+* Quick check of PDR codes.
+*
+* Arguments:
+* pdrcode PDR code number (host order)
+*
+* Returns:
+* zero not good.
+* one is good.
+*
+* Side effects:
+*
+* Call context:
+----------------------------------------------------------------*/
+static int
+hfa384x_isgood_pdrcode(UINT16 pdrcode)
+{
+ switch(pdrcode) {
+ case HFA384x_PDR_END_OF_PDA:
+ case HFA384x_PDR_PCB_PARTNUM:
+ case HFA384x_PDR_PDAVER:
+ case HFA384x_PDR_NIC_SERIAL:
+ case HFA384x_PDR_MKK_MEASUREMENTS:
+ case HFA384x_PDR_NIC_RAMSIZE:
+ case HFA384x_PDR_MFISUPRANGE:
+ case HFA384x_PDR_CFISUPRANGE:
+ case HFA384x_PDR_NICID:
+ case HFA384x_PDR_MAC_ADDRESS:
+ case HFA384x_PDR_REGDOMAIN:
+ case HFA384x_PDR_ALLOWED_CHANNEL:
+ case HFA384x_PDR_DEFAULT_CHANNEL:
+ case HFA384x_PDR_TEMPTYPE:
+ case HFA384x_PDR_IFR_SETTING:
+ case HFA384x_PDR_RFR_SETTING:
+ case HFA384x_PDR_HFA3861_BASELINE:
+ case HFA384x_PDR_HFA3861_SHADOW:
+ case HFA384x_PDR_HFA3861_IFRF:
+ case HFA384x_PDR_HFA3861_CHCALSP:
+ case HFA384x_PDR_HFA3861_CHCALI:
+ case HFA384x_PDR_3842_NIC_CONFIG:
+ case HFA384x_PDR_USB_ID:
+ case HFA384x_PDR_PCI_ID:
+ case HFA384x_PDR_PCI_IFCONF:
+ case HFA384x_PDR_PCI_PMCONF:
+ case HFA384x_PDR_RFENRGY:
+ case HFA384x_PDR_HFA3861_MANF_TESTSP:
+ case HFA384x_PDR_HFA3861_MANF_TESTI:
+ /* code is OK */
+ return 1;
+ break;
+ default:
+ if ( pdrcode < 0x1000 ) {
+ /* code is OK, but we don't know exactly what it is */
+ WLAN_LOG_DEBUG(3,
+ "Encountered unknown PDR#=0x%04x, "
+ "assuming it's ok.\n",
+ pdrcode);
+ return 1;
+ } else {
+ /* bad code */
+ WLAN_LOG_DEBUG(3,
+ "Encountered unknown PDR#=0x%04x, "
+ "(>=0x1000), assuming it's bad.\n",
+ pdrcode);
+ return 0;
+ }
+ break;
+ }
+ return 0; /* avoid compiler warnings */
+}
+
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
new file mode 100644
index 00000000000..68121b9b34f
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -0,0 +1,683 @@
+/* src/p80211/p80211conv.c
+*
+* Ether/802.11 conversions and packet buffer routines
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file defines the functions that perform Ethernet to/from
+* 802.11 frame conversions.
+*
+* --------------------------------------------------------------------
+*/
+/*================================================================*/
+/* System Includes */
+
+#define __NO_VERSION__ /* prevent the static definition */
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+
+#include <asm/byteorder.h>
+
+#include "version.h"
+#include "wlan_compat.h"
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211conv.h"
+#include "p80211mgmt.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211ioctl.h"
+#include "p80211req.h"
+
+
+/*================================================================*/
+/* Local Constants */
+
+/*================================================================*/
+/* Local Macros */
+
+
+/*================================================================*/
+/* Local Types */
+
+
+/*================================================================*/
+/* Local Static Definitions */
+
+static UINT8 oui_rfc1042[] = {0x00, 0x00, 0x00};
+static UINT8 oui_8021h[] = {0x00, 0x00, 0xf8};
+
+/*================================================================*/
+/* Local Function Declarations */
+
+
+/*================================================================*/
+/* Function Definitions */
+
+/*----------------------------------------------------------------
+* p80211pb_ether_to_80211
+*
+* Uses the contents of the ether frame and the etherconv setting
+* to build the elements of the 802.11 frame.
+*
+* We don't actually set
+* up the frame header here. That's the MAC's job. We're only handling
+* conversion of DIXII or 802.3+LLC frames to something that works
+* with 802.11.
+*
+* Note -- 802.11 header is NOT part of the skb. Likewise, the 802.11
+* FCS is also not present and will need to be added elsewhere.
+*
+* Arguments:
+* ethconv Conversion type to perform
+* skb skbuff containing the ether frame
+* p80211_hdr 802.11 header
+*
+* Returns:
+* 0 on success, non-zero otherwise
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+int skb_ether_to_p80211( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep)
+{
+
+ UINT16 fc;
+ UINT16 proto;
+ wlan_ethhdr_t e_hdr;
+ wlan_llc_t *e_llc;
+ wlan_snap_t *e_snap;
+ int foo;
+
+ DBFENTER;
+ memcpy(&e_hdr, skb->data, sizeof(e_hdr));
+
+ if (skb->len <= 0) {
+ WLAN_LOG_DEBUG(1, "zero-length skb!\n");
+ return 1;
+ }
+
+ if ( ethconv == WLAN_ETHCONV_ENCAP ) { /* simplest case */
+ WLAN_LOG_DEBUG(3, "ENCAP len: %d\n", skb->len);
+ /* here, we don't care what kind of ether frm. Just stick it */
+ /* in the 80211 payload */
+ /* which is to say, leave the skb alone. */
+ } else {
+ /* step 1: classify ether frame, DIX or 802.3? */
+ proto = ntohs(e_hdr.type);
+ if ( proto <= 1500 ) {
+ WLAN_LOG_DEBUG(3, "802.3 len: %d\n", skb->len);
+ /* codes <= 1500 reserved for 802.3 lengths */
+ /* it's 802.3, pass ether payload unchanged, */
+
+ /* trim off ethernet header */
+ skb_pull(skb, WLAN_ETHHDR_LEN);
+
+ /* leave off any PAD octets. */
+ skb_trim(skb, proto);
+ } else {
+ WLAN_LOG_DEBUG(3, "DIXII len: %d\n", skb->len);
+ /* it's DIXII, time for some conversion */
+
+ /* trim off ethernet header */
+ skb_pull(skb, WLAN_ETHHDR_LEN);
+
+ /* tack on SNAP */
+ e_snap = (wlan_snap_t *) skb_push(skb, sizeof(wlan_snap_t));
+ e_snap->type = htons(proto);
+ if ( ethconv == WLAN_ETHCONV_8021h && p80211_stt_findproto(proto) ) {
+ memcpy( e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN);
+ } else {
+ memcpy( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN);
+ }
+
+ /* tack on llc */
+ e_llc = (wlan_llc_t *) skb_push(skb, sizeof(wlan_llc_t));
+ e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */
+ e_llc->ssap = 0xAA;
+ e_llc->ctl = 0x03;
+
+ }
+ }
+
+ /* Set up the 802.11 header */
+ /* It's a data frame */
+ fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
+ WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY));
+
+ switch ( wlandev->macmode ) {
+ case WLAN_MACMODE_IBSS_STA:
+ memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a3, wlandev->bssid, WLAN_ADDR_LEN);
+ break;
+ case WLAN_MACMODE_ESS_STA:
+ fc |= host2ieee16(WLAN_SET_FC_TODS(1));
+ memcpy(p80211_hdr->a3.a1, wlandev->bssid, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, WLAN_ADDR_LEN);
+ break;
+ case WLAN_MACMODE_ESS_AP:
+ fc |= host2ieee16(WLAN_SET_FC_FROMDS(1));
+ memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a2, wlandev->bssid, WLAN_ADDR_LEN);
+ memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, WLAN_ADDR_LEN);
+ break;
+ default:
+ WLAN_LOG_ERROR("Error: Converting eth to wlan in unknown mode.\n");
+ return 1;
+ break;
+ }
+
+ p80211_wep->data = NULL;
+
+ if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
+ // XXXX need to pick keynum other than default?
+
+#if 1
+ p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
+#else
+ p80211_wep->data = skb->data;
+#endif
+
+ if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
+ skb->len,
+ (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK),
+ p80211_wep->iv, p80211_wep->icv))) {
+ WLAN_LOG_WARNING("Host en-WEP failed, dropping frame (%d).\n", foo);
+ return 2;
+ }
+ fc |= host2ieee16(WLAN_SET_FC_ISWEP(1));
+ }
+
+
+ // skb->nh.raw = skb->data;
+
+ p80211_hdr->a3.fc = fc;
+ p80211_hdr->a3.dur = 0;
+ p80211_hdr->a3.seq = 0;
+
+ DBFEXIT;
+ return 0;
+}
+
+/* jkriegl: from orinoco, modified */
+static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac,
+ p80211_rxmeta_t *rxmeta)
+{
+ int i;
+
+ /* Gather wireless spy statistics: for each packet, compare the
+ * source address with out list, and if match, get the stats... */
+
+ for (i = 0; i < wlandev->spy_number; i++) {
+
+ if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) {
+ memcpy(wlandev->spy_address[i], mac, ETH_ALEN);
+ wlandev->spy_stat[i].level = rxmeta->signal;
+ wlandev->spy_stat[i].noise = rxmeta->noise;
+ wlandev->spy_stat[i].qual = (rxmeta->signal > rxmeta->noise) ? \
+ (rxmeta->signal - rxmeta->noise) : 0;
+ wlandev->spy_stat[i].updated = 0x7;
+ }
+ }
+}
+
+/*----------------------------------------------------------------
+* p80211pb_80211_to_ether
+*
+* Uses the contents of a received 802.11 frame and the etherconv
+* setting to build an ether frame.
+*
+* This function extracts the src and dest address from the 802.11
+* frame to use in the construction of the eth frame.
+*
+* Arguments:
+* ethconv Conversion type to perform
+* skb Packet buffer containing the 802.11 frame
+*
+* Returns:
+* 0 on success, non-zero otherwise
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *skb)
+{
+ netdevice_t *netdev = wlandev->netdev;
+ UINT16 fc;
+ UINT payload_length;
+ UINT payload_offset;
+ UINT8 daddr[WLAN_ETHADDR_LEN];
+ UINT8 saddr[WLAN_ETHADDR_LEN];
+ p80211_hdr_t *w_hdr;
+ wlan_ethhdr_t *e_hdr;
+ wlan_llc_t *e_llc;
+ wlan_snap_t *e_snap;
+
+ int foo;
+
+ DBFENTER;
+
+ payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
+ payload_offset = WLAN_HDR_A3_LEN;
+
+ w_hdr = (p80211_hdr_t *) skb->data;
+
+ /* setup some vars for convenience */
+ fc = ieee2host16(w_hdr->a3.fc);
+ if ( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0) ) {
+ memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
+ memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
+ } else if( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1) ) {
+ memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
+ memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
+ } else if( (WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0) ) {
+ memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
+ memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
+ } else {
+ payload_offset = WLAN_HDR_A4_LEN;
+ payload_length -= ( WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN );
+ if (payload_length < 0 ) {
+ WLAN_LOG_ERROR("A4 frame too short!\n");
+ return 1;
+ }
+ memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN);
+ memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN);
+ }
+
+ /* perform de-wep if necessary.. */
+ if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) {
+ if (payload_length <= 8) {
+ WLAN_LOG_ERROR("WEP frame too short (%u).\n",
+ skb->len);
+ return 1;
+ }
+ if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
+ payload_length - 8, -1,
+ skb->data + payload_offset,
+ skb->data + payload_offset + payload_length - 4))) {
+ /* de-wep failed, drop skb. */
+ WLAN_LOG_DEBUG(1, "Host de-WEP failed, dropping frame (%d).\n", foo);
+ wlandev->rx.decrypt_err++;
+ return 2;
+ }
+
+ /* subtract the IV+ICV length off the payload */
+ payload_length -= 8;
+ /* chop off the IV */
+ skb_pull(skb, 4);
+ /* chop off the ICV. */
+ skb_trim(skb, skb->len - 4);
+
+ wlandev->rx.decrypt++;
+ }
+
+ e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset);
+
+ e_llc = (wlan_llc_t *) (skb->data + payload_offset);
+ e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t));
+
+ /* Test for the various encodings */
+ if ( (payload_length >= sizeof(wlan_ethhdr_t)) &&
+ ( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) &&
+ ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) ||
+ (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) {
+ WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length);
+ /* 802.3 Encapsulated */
+ /* Test for an overlength frame */
+ if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) {
+ /* A bogus length ethfrm has been encap'd. */
+ /* Is someone trying an oflow attack? */
+ WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n",
+ payload_length, netdev->mtu + WLAN_ETHHDR_LEN);
+ return 1;
+ }
+
+ /* Chop off the 802.11 header. it's already sane. */
+ skb_pull(skb, payload_offset);
+ /* chop off the 802.11 CRC */
+ skb_trim(skb, skb->len - WLAN_CRC_LEN);
+
+ } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) &&
+ (e_llc->dsap == 0xaa) &&
+ (e_llc->ssap == 0xaa) &&
+ (e_llc->ctl == 0x03) &&
+ (((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) &&
+ (ethconv == WLAN_ETHCONV_8021h) &&
+ (p80211_stt_findproto(ieee2host16(e_snap->type)))) ||
+ (memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)!=0)))
+ {
+ WLAN_LOG_DEBUG(3, "SNAP+RFC1042 len: %d\n", payload_length);
+ /* it's a SNAP + RFC1042 frame && protocol is in STT */
+ /* build 802.3 + RFC1042 */
+
+ /* Test for an overlength frame */
+ if ( payload_length > netdev->mtu ) {
+ /* A bogus length ethfrm has been sent. */
+ /* Is someone trying an oflow attack? */
+ WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n",
+ payload_length, netdev->mtu);
+ return 1;
+ }
+
+ /* chop 802.11 header from skb. */
+ skb_pull(skb, payload_offset);
+
+ /* create 802.3 header at beginning of skb. */
+ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN);
+ memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
+ memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
+ e_hdr->type = htons(payload_length);
+
+ /* chop off the 802.11 CRC */
+ skb_trim(skb, skb->len - WLAN_CRC_LEN);
+
+ } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) &&
+ (e_llc->dsap == 0xaa) &&
+ (e_llc->ssap == 0xaa) &&
+ (e_llc->ctl == 0x03) ) {
+ WLAN_LOG_DEBUG(3, "802.1h/RFC1042 len: %d\n", payload_length);
+ /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */
+ /* build a DIXII + RFC894 */
+
+ /* Test for an overlength frame */
+ if ((payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t))
+ > netdev->mtu) {
+ /* A bogus length ethfrm has been sent. */
+ /* Is someone trying an oflow attack? */
+ WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n",
+ (long int) (payload_length - sizeof(wlan_llc_t) -
+ sizeof(wlan_snap_t)),
+ netdev->mtu);
+ return 1;
+ }
+
+ /* chop 802.11 header from skb. */
+ skb_pull(skb, payload_offset);
+
+ /* chop llc header from skb. */
+ skb_pull(skb, sizeof(wlan_llc_t));
+
+ /* chop snap header from skb. */
+ skb_pull(skb, sizeof(wlan_snap_t));
+
+ /* create 802.3 header at beginning of skb. */
+ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN);
+ e_hdr->type = e_snap->type;
+ memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
+ memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
+
+ /* chop off the 802.11 CRC */
+ skb_trim(skb, skb->len - WLAN_CRC_LEN);
+ } else {
+ WLAN_LOG_DEBUG(3, "NON-ENCAP len: %d\n", payload_length);
+ /* any NON-ENCAP */
+ /* it's a generic 80211+LLC or IPX 'Raw 802.3' */
+ /* build an 802.3 frame */
+ /* allocate space and setup hostbuf */
+
+ /* Test for an overlength frame */
+ if ( payload_length > netdev->mtu ) {
+ /* A bogus length ethfrm has been sent. */
+ /* Is someone trying an oflow attack? */
+ WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n",
+ payload_length,
+ netdev->mtu);
+ return 1;
+ }
+
+ /* Chop off the 802.11 header. */
+ skb_pull(skb, payload_offset);
+
+ /* create 802.3 header at beginning of skb. */
+ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN);
+ memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
+ memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
+ e_hdr->type = htons(payload_length);
+
+ /* chop off the 802.11 CRC */
+ skb_trim(skb, skb->len - WLAN_CRC_LEN);
+
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+ skb_reset_mac_header(skb);
+
+ /* jkriegl: process signal and noise as set in hfa384x_int_rx() */
+ /* jkriegl: only process signal/noise if requested by iwspy */
+ if (wlandev->spy_number)
+ orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, P80211SKB_RXMETA(skb));
+
+ /* Free the metadata */
+ p80211skb_rxmeta_detach(skb);
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* p80211_stt_findproto
+*
+* Searches the 802.1h Selective Translation Table for a given
+* protocol.
+*
+* Arguments:
+* proto protocl number (in host order) to search for.
+*
+* Returns:
+* 1 - if the table is empty or a match is found.
+* 0 - if the table is non-empty and a match is not found.
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+int p80211_stt_findproto(UINT16 proto)
+{
+ /* Always return found for now. This is the behavior used by the */
+ /* Zoom Win95 driver when 802.1h mode is selected */
+ /* TODO: If necessary, add an actual search we'll probably
+ need this to match the CMAC's way of doing things.
+ Need to do some testing to confirm.
+ */
+
+ if (proto == 0x80f3) /* APPLETALK */
+ return 1;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* p80211skb_rxmeta_detach
+*
+* Disconnects the frmmeta and rxmeta from an skb.
+*
+* Arguments:
+* wlandev The wlandev this skb belongs to.
+* skb The skb we're attaching to.
+*
+* Returns:
+* 0 on success, non-zero otherwise
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+void
+p80211skb_rxmeta_detach(struct sk_buff *skb)
+{
+ p80211_rxmeta_t *rxmeta;
+ p80211_frmmeta_t *frmmeta;
+
+ DBFENTER;
+ /* Sanity checks */
+ if ( skb==NULL ) { /* bad skb */
+ WLAN_LOG_DEBUG(1, "Called w/ null skb.\n");
+ goto exit;
+ }
+ frmmeta = P80211SKB_FRMMETA(skb);
+ if ( frmmeta == NULL ) { /* no magic */
+ WLAN_LOG_DEBUG(1, "Called w/ bad frmmeta magic.\n");
+ goto exit;
+ }
+ rxmeta = frmmeta->rx;
+ if ( rxmeta == NULL ) { /* bad meta ptr */
+ WLAN_LOG_DEBUG(1, "Called w/ bad rxmeta ptr.\n");
+ goto exit;
+ }
+
+ /* Free rxmeta */
+ kfree(rxmeta);
+
+ /* Clear skb->cb */
+ memset(skb->cb, 0, sizeof(skb->cb));
+exit:
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* p80211skb_rxmeta_attach
+*
+* Allocates a p80211rxmeta structure, initializes it, and attaches
+* it to an skb.
+*
+* Arguments:
+* wlandev The wlandev this skb belongs to.
+* skb The skb we're attaching to.
+*
+* Returns:
+* 0 on success, non-zero otherwise
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+int
+p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb)
+{
+ int result = 0;
+ p80211_rxmeta_t *rxmeta;
+ p80211_frmmeta_t *frmmeta;
+
+ DBFENTER;
+
+ /* If these already have metadata, we error out! */
+ if (P80211SKB_RXMETA(skb) != NULL) {
+ WLAN_LOG_ERROR("%s: RXmeta already attached!\n",
+ wlandev->name);
+ result = 0;
+ goto exit;
+ }
+
+ /* Allocate the rxmeta */
+ rxmeta = kmalloc(sizeof(p80211_rxmeta_t), GFP_ATOMIC);
+
+ if ( rxmeta == NULL ) {
+ WLAN_LOG_ERROR("%s: Failed to allocate rxmeta.\n",
+ wlandev->name);
+ result = 1;
+ goto exit;
+ }
+
+ /* Initialize the rxmeta */
+ memset(rxmeta, 0, sizeof(p80211_rxmeta_t));
+ rxmeta->wlandev = wlandev;
+ rxmeta->hosttime = jiffies;
+
+ /* Overlay a frmmeta_t onto skb->cb */
+ memset(skb->cb, 0, sizeof(p80211_frmmeta_t));
+ frmmeta = (p80211_frmmeta_t*)(skb->cb);
+ frmmeta->magic = P80211_FRMMETA_MAGIC;
+ frmmeta->rx = rxmeta;
+exit:
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* p80211skb_free
+*
+* Frees an entire p80211skb by checking and freeing the meta struct
+* and then freeing the skb.
+*
+* Arguments:
+* wlandev The wlandev this skb belongs to.
+* skb The skb we're attaching to.
+*
+* Returns:
+* 0 on success, non-zero otherwise
+*
+* Call context:
+* May be called in interrupt or non-interrupt context
+----------------------------------------------------------------*/
+void
+p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb)
+{
+ p80211_frmmeta_t *meta;
+ DBFENTER;
+ meta = P80211SKB_FRMMETA(skb);
+ if ( meta && meta->rx) {
+ p80211skb_rxmeta_detach(skb);
+ } else {
+ WLAN_LOG_ERROR("Freeing an skb (%p) w/ no frmmeta.\n", skb);
+ }
+
+ dev_kfree_skb(skb);
+ DBFEXIT;
+ return;
+}
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
new file mode 100644
index 00000000000..3f5ab57cd9a
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -0,0 +1,186 @@
+/* p80211conv.h
+*
+* Ether/802.11 conversions and packet buffer routines
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares the functions, types and macros that perform
+* Ethernet to/from 802.11 frame conversions.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _LINUX_P80211CONV_H
+#define _LINUX_P80211CONV_H
+
+/*================================================================*/
+/* Constants */
+
+#define WLAN_ETHADDR_LEN 6
+#define WLAN_IEEE_OUI_LEN 3
+
+#define WLAN_ETHCONV_ENCAP 1
+#define WLAN_ETHCONV_RFC1042 2
+#define WLAN_ETHCONV_8021h 3
+
+#define WLAN_MIN_ETHFRM_LEN 60
+#define WLAN_MAX_ETHFRM_LEN 1514
+#define WLAN_ETHHDR_LEN 14
+
+#define P80211CAPTURE_VERSION 0x80211001
+
+/*================================================================*/
+/* Macros */
+
+#define P80211_FRMMETA_MAGIC 0x802110
+
+#define P80211SKB_FRMMETA(s) \
+ (((((p80211_frmmeta_t*)((s)->cb))->magic)==P80211_FRMMETA_MAGIC) ? \
+ ((p80211_frmmeta_t*)((s)->cb)) : \
+ (NULL))
+
+#define P80211SKB_RXMETA(s) \
+ (P80211SKB_FRMMETA((s)) ? P80211SKB_FRMMETA((s))->rx : ((p80211_rxmeta_t*)(NULL)))
+
+typedef struct p80211_rxmeta
+{
+ struct wlandevice *wlandev;
+
+ UINT64 mactime; /* Hi-rez MAC-supplied time value */
+ UINT64 hosttime; /* Best-rez host supplied time value */
+
+ UINT rxrate; /* Receive data rate in 100kbps */
+ UINT priority; /* 0-15, 0=contention, 6=CF */
+ INT signal; /* An SSI, see p80211netdev.h */
+ INT noise; /* An SSI, see p80211netdev.h */
+ UINT channel; /* Receive channel (mostly for snifs) */
+ UINT preamble; /* P80211ENUM_preambletype_* */
+ UINT encoding; /* P80211ENUM_encoding_* */
+
+} p80211_rxmeta_t;
+
+typedef struct p80211_frmmeta
+{
+ UINT magic;
+ p80211_rxmeta_t *rx;
+} p80211_frmmeta_t;
+
+void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb);
+int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb);
+void p80211skb_rxmeta_detach(struct sk_buff *skb);
+
+/*================================================================*/
+/* Types */
+
+/*
+ * Frame capture header. (See doc/capturefrm.txt)
+ */
+typedef struct p80211_caphdr
+{
+ UINT32 version;
+ UINT32 length;
+ UINT64 mactime;
+ UINT64 hosttime;
+ UINT32 phytype;
+ UINT32 channel;
+ UINT32 datarate;
+ UINT32 antenna;
+ UINT32 priority;
+ UINT32 ssi_type;
+ INT32 ssi_signal;
+ INT32 ssi_noise;
+ UINT32 preamble;
+ UINT32 encoding;
+} p80211_caphdr_t;
+
+/* buffer free method pointer type */
+typedef void (* freebuf_method_t)(void *buf, int size);
+
+typedef struct p80211_metawep {
+ void *data;
+ UINT8 iv[4];
+ UINT8 icv[4];
+} p80211_metawep_t;
+
+/* local ether header type */
+typedef struct wlan_ethhdr
+{
+ UINT8 daddr[WLAN_ETHADDR_LEN];
+ UINT8 saddr[WLAN_ETHADDR_LEN];
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ wlan_ethhdr_t;
+
+/* local llc header type */
+typedef struct wlan_llc
+{
+ UINT8 dsap;
+ UINT8 ssap;
+ UINT8 ctl;
+} __WLAN_ATTRIB_PACK__ wlan_llc_t;
+
+/* local snap header type */
+typedef struct wlan_snap
+{
+ UINT8 oui[WLAN_IEEE_OUI_LEN];
+ UINT16 type;
+} __WLAN_ATTRIB_PACK__ wlan_snap_t;
+
+/* Circular include trick */
+struct wlandevice;
+
+/*================================================================*/
+/* Externs */
+
+/*================================================================*/
+/*Function Declarations */
+
+int skb_p80211_to_ether( struct wlandevice *wlandev, UINT32 ethconv,
+ struct sk_buff *skb);
+int skb_ether_to_p80211( struct wlandevice *wlandev, UINT32 ethconv,
+ struct sk_buff *skb, p80211_hdr_t *p80211_hdr,
+ p80211_metawep_t *p80211_wep );
+
+int p80211_stt_findproto(UINT16 proto);
+int p80211_stt_addproto(UINT16 proto);
+
+#endif
diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h
new file mode 100644
index 00000000000..b7b0872fd86
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211hdr.h
@@ -0,0 +1,299 @@
+/* p80211hdr.h
+*
+* Macros, types, and functions for handling 802.11 MAC headers
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares the constants and types used in the interface
+* between a wlan driver and the user mode utilities.
+*
+* Note:
+* - Constant values are always in HOST byte order. To assign
+* values to multi-byte fields they _must_ be converted to
+* ieee byte order. To retrieve multi-byte values from incoming
+* frames, they must be converted to host order.
+*
+* All functions declared here are implemented in p80211.c
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211HDR_H
+#define _P80211HDR_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+
+/*================================================================*/
+/* Constants */
+
+/*--- Sizes -----------------------------------------------*/
+#define WLAN_ADDR_LEN 6
+#define WLAN_CRC_LEN 4
+#define WLAN_BSSID_LEN 6
+#define WLAN_BSS_TS_LEN 8
+#define WLAN_HDR_A3_LEN 24
+#define WLAN_HDR_A4_LEN 30
+#define WLAN_SSID_MAXLEN 32
+#define WLAN_DATA_MAXLEN 2312
+#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)
+#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)
+#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334)
+#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0)
+#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
+#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48)
+#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
+#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54)
+#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
+#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44)
+#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78)
+#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261)
+#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
+#define WLAN_WEP_NKEYS 4
+#define WLAN_WEP_MAXKEYLEN 13
+#define WLAN_CHALLENGE_IE_LEN 130
+#define WLAN_CHALLENGE_LEN 128
+#define WLAN_WEP_IV_LEN 4
+#define WLAN_WEP_ICV_LEN 4
+
+/*--- Frame Control Field -------------------------------------*/
+/* Frame Types */
+#define WLAN_FTYPE_MGMT 0x00
+#define WLAN_FTYPE_CTL 0x01
+#define WLAN_FTYPE_DATA 0x02
+
+/* Frame subtypes */
+/* Management */
+#define WLAN_FSTYPE_ASSOCREQ 0x00
+#define WLAN_FSTYPE_ASSOCRESP 0x01
+#define WLAN_FSTYPE_REASSOCREQ 0x02
+#define WLAN_FSTYPE_REASSOCRESP 0x03
+#define WLAN_FSTYPE_PROBEREQ 0x04
+#define WLAN_FSTYPE_PROBERESP 0x05
+#define WLAN_FSTYPE_BEACON 0x08
+#define WLAN_FSTYPE_ATIM 0x09
+#define WLAN_FSTYPE_DISASSOC 0x0a
+#define WLAN_FSTYPE_AUTHEN 0x0b
+#define WLAN_FSTYPE_DEAUTHEN 0x0c
+
+/* Control */
+#define WLAN_FSTYPE_BLOCKACKREQ 0x8
+#define WLAN_FSTYPE_BLOCKACK 0x9
+#define WLAN_FSTYPE_PSPOLL 0x0a
+#define WLAN_FSTYPE_RTS 0x0b
+#define WLAN_FSTYPE_CTS 0x0c
+#define WLAN_FSTYPE_ACK 0x0d
+#define WLAN_FSTYPE_CFEND 0x0e
+#define WLAN_FSTYPE_CFENDCFACK 0x0f
+
+/* Data */
+#define WLAN_FSTYPE_DATAONLY 0x00
+#define WLAN_FSTYPE_DATA_CFACK 0x01
+#define WLAN_FSTYPE_DATA_CFPOLL 0x02
+#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03
+#define WLAN_FSTYPE_NULL 0x04
+#define WLAN_FSTYPE_CFACK 0x05
+#define WLAN_FSTYPE_CFPOLL 0x06
+#define WLAN_FSTYPE_CFACK_CFPOLL 0x07
+
+
+/*================================================================*/
+/* Macros */
+
+/*--- FC Macros ----------------------------------------------*/
+/* Macros to get/set the bitfields of the Frame Control Field */
+/* GET_FC_??? - takes the host byte-order value of an FC */
+/* and retrieves the value of one of the */
+/* bitfields and moves that value so its lsb is */
+/* in bit 0. */
+/* SET_FC_??? - takes a host order value for one of the FC */
+/* bitfields and moves it to the proper bit */
+/* location for ORing into a host order FC. */
+/* To send the FC produced from SET_FC_???, */
+/* one must put the bytes in IEEE order. */
+/* e.g. */
+/* printf("the frame subtype is %x", */
+/* GET_FC_FTYPE( ieee2host( rx.fc ))) */
+/* */
+/* tx.fc = host2ieee( SET_FC_FTYPE(WLAN_FTYP_CTL) | */
+/* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */
+/*------------------------------------------------------------*/
+
+#define WLAN_GET_FC_PVER(n) (((UINT16)(n)) & (BIT0 | BIT1))
+#define WLAN_GET_FC_FTYPE(n) ((((UINT16)(n)) & (BIT2 | BIT3)) >> 2)
+#define WLAN_GET_FC_FSTYPE(n) ((((UINT16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4)
+#define WLAN_GET_FC_TODS(n) ((((UINT16)(n)) & (BIT8)) >> 8)
+#define WLAN_GET_FC_FROMDS(n) ((((UINT16)(n)) & (BIT9)) >> 9)
+#define WLAN_GET_FC_MOREFRAG(n) ((((UINT16)(n)) & (BIT10)) >> 10)
+#define WLAN_GET_FC_RETRY(n) ((((UINT16)(n)) & (BIT11)) >> 11)
+#define WLAN_GET_FC_PWRMGT(n) ((((UINT16)(n)) & (BIT12)) >> 12)
+#define WLAN_GET_FC_MOREDATA(n) ((((UINT16)(n)) & (BIT13)) >> 13)
+#define WLAN_GET_FC_ISWEP(n) ((((UINT16)(n)) & (BIT14)) >> 14)
+#define WLAN_GET_FC_ORDER(n) ((((UINT16)(n)) & (BIT15)) >> 15)
+
+#define WLAN_SET_FC_PVER(n) ((UINT16)(n))
+#define WLAN_SET_FC_FTYPE(n) (((UINT16)(n)) << 2)
+#define WLAN_SET_FC_FSTYPE(n) (((UINT16)(n)) << 4)
+#define WLAN_SET_FC_TODS(n) (((UINT16)(n)) << 8)
+#define WLAN_SET_FC_FROMDS(n) (((UINT16)(n)) << 9)
+#define WLAN_SET_FC_MOREFRAG(n) (((UINT16)(n)) << 10)
+#define WLAN_SET_FC_RETRY(n) (((UINT16)(n)) << 11)
+#define WLAN_SET_FC_PWRMGT(n) (((UINT16)(n)) << 12)
+#define WLAN_SET_FC_MOREDATA(n) (((UINT16)(n)) << 13)
+#define WLAN_SET_FC_ISWEP(n) (((UINT16)(n)) << 14)
+#define WLAN_SET_FC_ORDER(n) (((UINT16)(n)) << 15)
+
+/*--- Duration Macros ----------------------------------------*/
+/* Macros to get/set the bitfields of the Duration Field */
+/* - the duration value is only valid when bit15 is zero */
+/* - the firmware handles these values, so I'm not going */
+/* these macros right now. */
+/*------------------------------------------------------------*/
+
+/*--- Sequence Control Macros -------------------------------*/
+/* Macros to get/set the bitfields of the Sequence Control */
+/* Field. */
+/*------------------------------------------------------------*/
+#define WLAN_GET_SEQ_FRGNUM(n) (((UINT16)(n)) & (BIT0|BIT1|BIT2|BIT3))
+#define WLAN_GET_SEQ_SEQNUM(n) ((((UINT16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
+
+/*--- Data ptr macro -----------------------------------------*/
+/* Creates a UINT8* to the data portion of a frame */
+/* Assumes you're passing in a ptr to the beginning of the hdr*/
+/*------------------------------------------------------------*/
+#define WLAN_HDR_A3_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A3_LEN)
+#define WLAN_HDR_A4_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A4_LEN)
+
+#define DOT11_RATE5_ISBASIC_GET(r) (((UINT8)(r)) & BIT7)
+
+/*================================================================*/
+/* Types */
+
+/* BSS Timestamp */
+typedef UINT8 wlan_bss_ts_t[WLAN_BSS_TS_LEN];
+
+/* Generic 802.11 Header types */
+
+typedef struct p80211_hdr_a3
+{
+ UINT16 fc;
+ UINT16 dur;
+ UINT8 a1[WLAN_ADDR_LEN];
+ UINT8 a2[WLAN_ADDR_LEN];
+ UINT8 a3[WLAN_ADDR_LEN];
+ UINT16 seq;
+} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t;
+
+typedef struct p80211_hdr_a4
+{
+ UINT16 fc;
+ UINT16 dur;
+ UINT8 a1[WLAN_ADDR_LEN];
+ UINT8 a2[WLAN_ADDR_LEN];
+ UINT8 a3[WLAN_ADDR_LEN];
+ UINT16 seq;
+ UINT8 a4[WLAN_ADDR_LEN];
+} __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t;
+
+typedef union p80211_hdr
+{
+ p80211_hdr_a3_t a3;
+ p80211_hdr_a4_t a4;
+} __WLAN_ATTRIB_PACK__ p80211_hdr_t;
+
+
+/*================================================================*/
+/* Extern Declarations */
+
+
+/*================================================================*/
+/* Function Declarations */
+
+/* Frame and header lenght macros */
+
+#define WLAN_CTL_FRAMELEN(fstype) (\
+ (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \
+ (fstype) == WLAN_FSTYPE_BLOCKACK ? 152 : \
+ (fstype) == WLAN_FSTYPE_PSPOLL ? 20 : \
+ (fstype) == WLAN_FSTYPE_RTS ? 20 : \
+ (fstype) == WLAN_FSTYPE_CTS ? 14 : \
+ (fstype) == WLAN_FSTYPE_ACK ? 14 : \
+ (fstype) == WLAN_FSTYPE_CFEND ? 20 : \
+ (fstype) == WLAN_FSTYPE_CFENDCFACK ? 20 : 4)
+
+#define WLAN_FCS_LEN 4
+
+/* ftcl in HOST order */
+inline static UINT16 p80211_headerlen(UINT16 fctl)
+{
+ UINT16 hdrlen = 0;
+
+ switch ( WLAN_GET_FC_FTYPE(fctl) ) {
+ case WLAN_FTYPE_MGMT:
+ hdrlen = WLAN_HDR_A3_LEN;
+ break;
+ case WLAN_FTYPE_DATA:
+ hdrlen = WLAN_HDR_A3_LEN;
+ if ( WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl) ) {
+ hdrlen += WLAN_ADDR_LEN;
+ }
+ break;
+ case WLAN_FTYPE_CTL:
+ hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) -
+ WLAN_FCS_LEN;
+ break;
+ default:
+ hdrlen = WLAN_HDR_A3_LEN;
+ }
+
+ return hdrlen;
+}
+
+#endif /* _P80211HDR_H */
diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h
new file mode 100644
index 00000000000..25b2ea83622
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211ioctl.h
@@ -0,0 +1,123 @@
+/* p80211ioctl.h
+*
+* Declares constants and types for the p80211 ioctls
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* While this file is called 'ioctl' is purpose goes a little beyond
+* that. This file defines the types and contants used to implement
+* the p80211 request/confirm/indicate interfaces on Linux. The
+* request/confirm interface is, in fact, normally implemented as an
+* ioctl. The indicate interface on the other hand, is implemented
+* using the Linux 'netlink' interface.
+*
+* The reason I say that request/confirm is 'normally' implemented
+* via ioctl is that we're reserving the right to be able to send
+* request commands via the netlink interface. This will be necessary
+* if we ever need to send request messages when there aren't any
+* wlan network devices present (i.e. sending a message that only p80211
+* cares about.
+* --------------------------------------------------------------------
+*/
+
+
+#ifndef _P80211IOCTL_H
+#define _P80211IOCTL_H
+
+/*================================================================*/
+/* Constants */
+
+/*----------------------------------------------------------------*/
+/* p80211 ioctl "request" codes. See argument 2 of ioctl(2). */
+
+#define P80211_IFTEST (SIOCDEVPRIVATE + 0)
+#define P80211_IFREQ (SIOCDEVPRIVATE + 1)
+
+/*----------------------------------------------------------------*/
+/* Magic number, a quick test to see we're getting the desired struct */
+
+#define P80211_IOCTL_MAGIC (0x4a2d464dUL)
+
+/*----------------------------------------------------------------*/
+/* Netlink protocol numbers for the indication interface */
+
+#define P80211_NL_SOCK_IND NETLINK_USERSOCK
+
+/*----------------------------------------------------------------*/
+/* Netlink multicast bits for different types of messages */
+
+#define P80211_NL_MCAST_GRP_MLME BIT0 /* Local station messages */
+#define P80211_NL_MCAST_GRP_SNIFF BIT1 /* Sniffer messages */
+#define P80211_NL_MCAST_GRP_DIST BIT2 /* Distribution system messages */
+
+/*================================================================*/
+/* Macros */
+
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* A ptr to the following structure type is passed as the third */
+/* argument to the ioctl system call when issuing a request to */
+/* the p80211 module. */
+
+typedef struct p80211ioctl_req
+{
+ char name[WLAN_DEVNAMELEN_MAX];
+ caddr_t data;
+ UINT32 magic;
+ UINT16 len;
+ UINT32 result;
+} __WLAN_ATTRIB_PACK__ p80211ioctl_req_t;
+
+
+/*================================================================*/
+/* Extern Declarations */
+
+
+/*================================================================*/
+/* Function Declarations */
+
+
+#endif /* _P80211IOCTL_H */
diff --git a/drivers/staging/wlan-ng/p80211meta.h b/drivers/staging/wlan-ng/p80211meta.h
new file mode 100644
index 00000000000..5cb3f5ada4f
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211meta.h
@@ -0,0 +1,169 @@
+/* p80211meta.h
+*
+* Macros, constants, types, and funcs for p80211 metadata
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares some of the constants and types used in various
+* parts of the linux-wlan system.
+*
+* Notes:
+* - Constant values are always in HOST byte order.
+*
+* All functions and statics declared here are implemented in p80211types.c
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211META_H
+#define _P80211META_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+/*================================================================*/
+/* Constants */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Macros */
+
+/*----------------------------------------------------------------*/
+/* The following macros are used to ensure consistent naming */
+/* conventions for all the different metadata lists. */
+
+#define MKREQMETANAME(name) p80211meta_ ## req ## _ ## name
+#define MKINDMETANAME(name) p80211meta_ ## ind ## _ ## name
+#define MKMIBMETANAME(name) p80211meta_ ## mib ## _ ## name
+#define MKGRPMETANAME(name) p80211meta_ ## grp ## _ ## name
+
+#define MKREQMETASIZE(name) p80211meta_ ## req ## _ ## name ## _ ## size
+#define MKINDMETASIZE(name) p80211meta_ ## ind ## _ ## name ## _ ## size
+#define MKMIBMETASIZE(name) p80211meta_ ## mib ## _ ## name ## _ ## size
+#define MKGRPMETASIZE(name) p80211meta_ ## grp ## _ ## name ## _ ## size
+
+#define GETMETASIZE(aptr) (**((UINT32**)(aptr)))
+
+/*----------------------------------------------------------------*/
+/* The following ifdef depends on the following defines: */
+/* P80211_NOINCLUDESTRINGS - if defined, all metadata name fields */
+/* are empty strings */
+
+#ifdef P80211_NOINCLUDESTRINGS
+ #define MKITEMNAME(s) ("")
+#else
+ #define MKITEMNAME(s) (s)
+#endif
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* The following structure types are used for the metadata */
+/* representation of category list metadata, group list metadata, */
+/* and data item metadata for both Mib and Messages. */
+
+typedef struct p80211meta
+{
+ char *name; /* data item name */
+ UINT32 did; /* partial did */
+ UINT32 flags; /* set of various flag bits */
+ UINT32 min; /* min value of a BOUNDEDINT */
+ UINT32 max; /* max value of a BOUNDEDINT */
+
+ UINT32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */
+ UINT32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */
+ p80211enum_t *enumptr; /* ptr to the enum type for ENUMINT */
+ p80211_totext_t totextptr; /* ptr to totext conversion function */
+ p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */
+ p80211_valid_t validfunptr; /* ptr to totext conversion function */
+} p80211meta_t;
+
+typedef struct grplistitem
+{
+ char *name;
+ p80211meta_t *itemlist;
+} grplistitem_t;
+
+typedef struct catlistitem
+{
+ char *name;
+ grplistitem_t *grplist;
+} catlistitem_t;
+
+/*================================================================*/
+/* Extern Declarations */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Function Declarations */
+
+/*----------------------------------------------------------------*/
+/* */
+UINT32 p80211_text2did(catlistitem_t *catlist, char *catname, char *grpname, char *itemname);
+UINT32 p80211_text2catdid(catlistitem_t *list, char *name );
+UINT32 p80211_text2grpdid(grplistitem_t *list, char *name );
+UINT32 p80211_text2itemdid(p80211meta_t *list, char *name );
+UINT32 p80211_isvalid_did( catlistitem_t *catlist, UINT32 did );
+UINT32 p80211_isvalid_catdid( catlistitem_t *catlist, UINT32 did );
+UINT32 p80211_isvalid_grpdid( catlistitem_t *catlist, UINT32 did );
+UINT32 p80211_isvalid_itemdid( catlistitem_t *catlist, UINT32 did );
+catlistitem_t *p80211_did2cat( catlistitem_t *catlist, UINT32 did );
+grplistitem_t *p80211_did2grp( catlistitem_t *catlist, UINT32 did );
+p80211meta_t *p80211_did2item( catlistitem_t *catlist, UINT32 did );
+UINT32 p80211item_maxdatalen( struct catlistitem *metalist, UINT32 did );
+UINT32 p80211_metaname2did(struct catlistitem *metalist, char *itemname);
+UINT32 p80211item_getoffset( struct catlistitem *metalist, UINT32 did );
+int p80211item_gettype(p80211meta_t *meta);
+
+#endif /* _P80211META_H */
diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h
new file mode 100644
index 00000000000..2c7f435a97e
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211metadef.h
@@ -0,0 +1,2524 @@
+/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY.
+* --------------------------------------------------------------------
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211MKMETADEF_H
+#define _P80211MKMETADEF_H
+
+
+#define DIDmsg_cat_dot11req \
+ P80211DID_MKSECTION(1)
+#define DIDmsg_dot11req_mibget \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(1))
+#define DIDmsg_dot11req_mibget_mibattribute \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_mibget_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_mibset \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2))
+#define DIDmsg_dot11req_mibset_mibattribute \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_mibset_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_powermgmt \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3))
+#define DIDmsg_dot11req_powermgmt_powermgmtmode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_powermgmt_wakeup \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_powermgmt_receivedtims \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_powermgmt_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_scan \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4))
+#define DIDmsg_dot11req_scan_bsstype \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_scan_bssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_scan_ssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_scan_scantype \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_scan_probedelay \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_scan_channellist \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_scan_minchanneltime \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_scan_maxchanneltime \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_dot11req_scan_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_dot11req_scan_numbss \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_dot11req_scan_append \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(11) | 0x00000000)
+#define DIDmsg_dot11req_scan_results \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5))
+#define DIDmsg_dot11req_scan_results_bssindex \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_signal \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_noise \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_bssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_ssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_bsstype \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_beaconperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_dtimperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_timestamp \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_localtime \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(11) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_fhdwelltime \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(12) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_fhhopset \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(13) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_fhhoppattern \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(14) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_fhhopindex \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(15) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_dschannel \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(16) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpcount \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(17) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(18) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpmaxduration \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(19) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpdurremaining \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(20) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_ibssatimwindow \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(21) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpollable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(22) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_cfpollreq \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(23) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_privacy \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(24) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(25) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(26) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(27) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(28) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(29) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(30) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(31) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_basicrate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(32) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(33) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(34) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(35) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(36) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(37) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(38) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(39) | 0x00000000)
+#define DIDmsg_dot11req_scan_results_supprate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(40) | 0x00000000)
+#define DIDmsg_dot11req_join \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6))
+#define DIDmsg_dot11req_join_bssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_join_joinfailuretimeout \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_dot11req_join_basicrate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(11) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(12) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(13) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(14) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(15) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(16) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(17) | 0x00000000)
+#define DIDmsg_dot11req_join_operationalrate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(18) | 0x00000000)
+#define DIDmsg_dot11req_join_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(19) | 0x00000000)
+#define DIDmsg_dot11req_authenticate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(7))
+#define DIDmsg_dot11req_authenticate_peerstaaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_authenticate_authenticationtype \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_authenticate_authenticationfailuretimeout \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_authenticate_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_deauthenticate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(8))
+#define DIDmsg_dot11req_deauthenticate_peerstaaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_deauthenticate_reasoncode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_deauthenticate_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_associate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9))
+#define DIDmsg_dot11req_associate_peerstaaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_associate_associatefailuretimeout \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_associate_cfpollable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_associate_cfpollreq \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_associate_privacy \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_associate_listeninterval \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_associate_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_reassociate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10))
+#define DIDmsg_dot11req_reassociate_newapaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_reassociatefailuretimeout \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_cfpollable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_cfpollreq \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_privacy \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_listeninterval \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_reassociate_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_disassociate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(11))
+#define DIDmsg_dot11req_disassociate_peerstaaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_disassociate_reasoncode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_disassociate_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_reset \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(12))
+#define DIDmsg_dot11req_reset_setdefaultmib \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_reset_macaddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_reset_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_start \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13))
+#define DIDmsg_dot11req_start_ssid \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11req_start_bsstype \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11req_start_beaconperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11req_start_dtimperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_dot11req_start_cfpperiod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_dot11req_start_cfpmaxduration \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_dot11req_start_fhdwelltime \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_dot11req_start_fhhopset \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_dot11req_start_fhhoppattern \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_dot11req_start_dschannel \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_dot11req_start_ibssatimwindow \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(11) | 0x00000000)
+#define DIDmsg_dot11req_start_probedelay \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(12) | 0x00000000)
+#define DIDmsg_dot11req_start_cfpollable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(13) | 0x00000000)
+#define DIDmsg_dot11req_start_cfpollreq \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(14) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(15) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(16) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(17) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(18) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(19) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(20) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(21) | 0x00000000)
+#define DIDmsg_dot11req_start_basicrate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(22) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(23) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(24) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(25) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(26) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(27) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(28) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate7 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(29) | 0x00000000)
+#define DIDmsg_dot11req_start_operationalrate8 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(30) | 0x00000000)
+#define DIDmsg_dot11req_start_resultcode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(31) | 0x00000000)
+#define DIDmsg_cat_dot11ind \
+ P80211DID_MKSECTION(2)
+#define DIDmsg_dot11ind_authenticate \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1))
+#define DIDmsg_dot11ind_authenticate_peerstaaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11ind_authenticate_authenticationtype \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11ind_deauthenticate \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2))
+#define DIDmsg_dot11ind_deauthenticate_peerstaaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11ind_deauthenticate_reasoncode \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11ind_associate \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3))
+#define DIDmsg_dot11ind_associate_peerstaaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11ind_associate_aid \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11ind_reassociate \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(4))
+#define DIDmsg_dot11ind_reassociate_peerstaaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11ind_reassociate_aid \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_dot11ind_reassociate_oldapaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_dot11ind_disassociate \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(5))
+#define DIDmsg_dot11ind_disassociate_peerstaaddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_dot11ind_disassociate_reasoncode \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_cat_lnxreq \
+ P80211DID_MKSECTION(3)
+#define DIDmsg_lnxreq_ifstate \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1))
+#define DIDmsg_lnxreq_ifstate_ifstate \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxreq_ifstate_resultcode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2))
+#define DIDmsg_lnxreq_wlansniff_enable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_channel \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_prismheader \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_wlanheader \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_keepwepflags \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_stripfcs \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_packet_trunc \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_lnxreq_wlansniff_resultcode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_lnxreq_hostwep \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3))
+#define DIDmsg_lnxreq_hostwep_resultcode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxreq_hostwep_decrypt \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxreq_hostwep_encrypt \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_lnxreq_commsquality \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4))
+#define DIDmsg_lnxreq_commsquality_resultcode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxreq_commsquality_dbm \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxreq_commsquality_link \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_lnxreq_commsquality_level \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_lnxreq_commsquality_noise \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_lnxreq_autojoin \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5))
+#define DIDmsg_lnxreq_autojoin_ssid \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxreq_autojoin_authtype \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxreq_autojoin_resultcode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_cat_lnxind \
+ P80211DID_MKSECTION(4)
+#define DIDmsg_lnxind_wlansniffrm \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1))
+#define DIDmsg_lnxind_wlansniffrm_hosttime \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_mactime \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_channel \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_rssi \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_sq \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_signal \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_noise \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_rate \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_istx \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_lnxind_wlansniffrm_frmlen \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_lnxind_roam \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(2))
+#define DIDmsg_lnxind_roam_reason \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_cat_p2req \
+ P80211DID_MKSECTION(5)
+#define DIDmsg_p2req_join \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1))
+#define DIDmsg_p2req_join_bssid \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate7 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_p2req_join_basicrate8 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(9) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(10) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(11) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(12) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(13) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(14) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(15) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate7 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(16) | 0x00000000)
+#define DIDmsg_p2req_join_operationalrate8 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(17) | 0x00000000)
+#define DIDmsg_p2req_join_ssid \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(18) | 0x00000000)
+#define DIDmsg_p2req_join_channel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(19) | 0x00000000)
+#define DIDmsg_p2req_join_authtype \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(20) | 0x00000000)
+#define DIDmsg_p2req_join_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(21) | 0x00000000)
+#define DIDmsg_p2req_readpda \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2))
+#define DIDmsg_p2req_readpda_pda \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_readpda_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_readcis \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3))
+#define DIDmsg_p2req_readcis_cis \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_readcis_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_auxport_state \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(4))
+#define DIDmsg_p2req_auxport_state_enable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_auxport_state_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_auxport_read \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5))
+#define DIDmsg_p2req_auxport_read_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_auxport_read_len \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_auxport_read_data \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_auxport_read_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_auxport_write \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6))
+#define DIDmsg_p2req_auxport_write_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_auxport_write_len \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_auxport_write_data \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_auxport_write_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_low_level \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7))
+#define DIDmsg_p2req_low_level_command \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_low_level_param0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_low_level_param1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_low_level_param2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_low_level_resp0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_p2req_low_level_resp1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_p2req_low_level_resp2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_p2req_low_level_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(8) | 0x00000000)
+#define DIDmsg_p2req_test_command \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8))
+#define DIDmsg_p2req_test_command_testcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_test_command_testparam \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_test_command_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_test_command_status \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_test_command_resp0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_p2req_test_command_resp1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_p2req_test_command_resp2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(7) | 0x00000000)
+#define DIDmsg_p2req_mmi_read \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(9))
+#define DIDmsg_p2req_mmi_read_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_mmi_read_value \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_mmi_read_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_mmi_write \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(10))
+#define DIDmsg_p2req_mmi_write_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_mmi_write_data \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_mmi_write_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_ramdl_state \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(11))
+#define DIDmsg_p2req_ramdl_state_enable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_ramdl_state_exeaddr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_ramdl_state_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(11) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_ramdl_write \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(12))
+#define DIDmsg_p2req_ramdl_write_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_ramdl_write_len \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_ramdl_write_data \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_ramdl_write_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(12) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_flashdl_state \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(13))
+#define DIDmsg_p2req_flashdl_state_enable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_flashdl_state_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(13) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_flashdl_write \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(14))
+#define DIDmsg_p2req_flashdl_write_addr \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(14) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_flashdl_write_len \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(14) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_flashdl_write_data \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(14) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_flashdl_write_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(14) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_mm_state \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(15))
+#define DIDmsg_p2req_mm_state_enable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(15) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_mm_state_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(15) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_dump_state \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(16))
+#define DIDmsg_p2req_dump_state_level \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(16) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_dump_state_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(16) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_channel_info \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(17))
+#define DIDmsg_p2req_channel_info_channellist \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(17) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_channel_info_channeldwelltime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(17) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_channel_info_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(17) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_channel_info_numchinfo \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(17) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18))
+#define DIDmsg_p2req_channel_info_results_channel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(2) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results_avgnoiselevel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(3) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results_peaknoiselevel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(4) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results_bssactive \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(5) | 0x00000000)
+#define DIDmsg_p2req_channel_info_results_pcfactive \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(18) | \
+ P80211DID_MKITEM(6) | 0x00000000)
+#define DIDmsg_p2req_enable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(19))
+#define DIDmsg_p2req_enable_resultcode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(19) | \
+ P80211DID_MKITEM(1) | 0x00000000)
+#define DIDmib_cat_dot11smt \
+ P80211DID_MKSECTION(1)
+#define DIDmib_dot11smt_p80211Table \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(1))
+#define DIDmib_dot11smt_p80211Table_p80211_ifstate \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2))
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11StationID \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(5) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(6) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(8) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(9) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(10) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(11) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(12) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(13) | 0x18000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(14) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateReason \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(15) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DisassociateStation \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(16) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateReason \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(17) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11DeauthenticateStation \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(18) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStatus \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(19) | 0x10000000)
+#define DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticateFailStation \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(20) | 0x10000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3))
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x1c000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(4) | 0x1c000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(5) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(6) | 0x1c000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(7) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(8) | 0x1c000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(9) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(10) | 0x1c000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(11) | 0x14000000)
+#define DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(12) | 0x1c000000)
+#define DIDmib_dot11smt_dot11WEPDefaultKeysTable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4))
+#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x0c000000)
+#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x0c000000)
+#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(3) | 0x0c000000)
+#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(4) | 0x0c000000)
+#define DIDmib_dot11smt_dot11WEPKeyMappingsTable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5))
+#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x1c000000)
+#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x1c000000)
+#define DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(4) | 0x1c000000)
+#define DIDmib_dot11smt_dot11PrivacyTable \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6))
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(3) | 0x18000000)
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount \
+ (P80211DID_MKSECTION(1) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_cat_dot11mac \
+ P80211DID_MKSECTION(2)
+#define DIDmib_dot11mac_dot11OperationTable \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1))
+#define DIDmib_dot11mac_dot11OperationTable_dot11MACAddress \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(5) | 0x18000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(8) | 0x10000000)
+#define DIDmib_dot11mac_dot11OperationTable_dot11ProductID \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(9) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2))
+#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11FailedCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11RetryCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(8) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(9) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(10) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(11) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(12) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(13) | 0x10000000)
+#define DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(14) | 0x10000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3))
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(4) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(5) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(6) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(7) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(8) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(9) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(10) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(11) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(12) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(13) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(14) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(15) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(16) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(17) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(18) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(19) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(20) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(21) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(22) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(23) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(24) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(25) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(26) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(27) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(28) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(29) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(30) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(31) | 0x1c000000)
+#define DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32 \
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(32) | 0x1c000000)
+#define DIDmib_cat_dot11phy \
+ P80211DID_MKSECTION(3)
+#define DIDmib_dot11phy_dot11PhyOperationTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1))
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11CurrentRegDomain \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyAntennaTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2))
+#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(3) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3))
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(8) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8 \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(9) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(10) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4))
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(5) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(6) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(7) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5))
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_dot11phy_dot11PhyIRTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(6))
+#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(3) | 0x18000000)
+#define DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_dot11phy_dot11RegDomainsSupportedTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(7))
+#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(2) | 0x14000000)
+#define DIDmib_dot11phy_dot11AntennasListTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(8))
+#define DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(2) | 0x1c000000)
+#define DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(3) | 0x1c000000)
+#define DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(8) | \
+ P80211DID_MKITEM(4) | 0x1c000000)
+#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(9))
+#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(9) | \
+ P80211DID_MKITEM(2) | 0x14000000)
+#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(10))
+#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(1) | 0x1c000000)
+#define DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue \
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(10) | \
+ P80211DID_MKITEM(2) | 0x14000000)
+#define DIDmib_cat_lnx \
+ P80211DID_MKSECTION(4)
+#define DIDmib_lnx_lnxConfigTable \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1))
+#define DIDmib_lnx_lnxConfigTable_lnxRSNAIE \
+ (P80211DID_MKSECTION(4) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_cat_p2 \
+ P80211DID_MKSECTION(5)
+#define DIDmib_p2_p2Table \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1))
+#define DIDmib_p2_p2Table_p2MMTx \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_p2_p2Table_p2EarlyBeacon \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_p2_p2Table_p2ReceivedFrameStatistics \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_p2_p2Table_p2CommunicationTallies \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_p2_p2Table_p2Authenticated \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_p2_p2Table_p2Associated \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_p2_p2Table_p2PowerSaveUserCount \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_p2_p2Table_p2Comment \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(8) | 0x18000000)
+#define DIDmib_p2_p2Table_p2AccessMode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(9) | 0x18000000)
+#define DIDmib_p2_p2Table_p2AccessAllow \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(10) | 0x18000000)
+#define DIDmib_p2_p2Table_p2AccessDeny \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(11) | 0x18000000)
+#define DIDmib_p2_p2Table_p2ChannelInfoResults \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(12) | 0x10000000)
+#define DIDmib_p2_p2Static \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2))
+#define DIDmib_p2_p2Static_p2CnfPortType \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnMACAddress \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfDesiredSSID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(3) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnChannel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnSSID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(5) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnATIMWindow \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(6) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfSystemScale \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(7) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMaxDataLength \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(8) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(9) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfPMEnabled \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(10) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfPMEPS \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(11) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMulticastReceive \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(12) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMaxSleepDuration \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(13) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfPMHoldoverDuration \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(14) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnName \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(15) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(16) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(17) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(18) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(19) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(20) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(21) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWDSAddress6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(22) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMulticastPMBuffering \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(23) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(24) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(25) | 0x08000000)
+#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(26) | 0x08000000)
+#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(27) | 0x08000000)
+#define DIDmib_p2_p2Static_p2CnfWEPDefaultKey3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(28) | 0x08000000)
+#define DIDmib_p2_p2Static_p2CnfWEPFlags \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(29) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfAuthentication \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(30) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMaxAssociatedStations \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(31) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfTxControl \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(32) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfRoamingMode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(33) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfHostAuthentication \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(34) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfRcvCrcError \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(35) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfAltRetryCount \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(36) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfBeaconInterval \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(37) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(38) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfCFPPeriod \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(39) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfCFPMaxDuration \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(40) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfCFPFlags \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(41) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfSTAPCFInfo \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(42) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfPriorityQUsage \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(43) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfTIMCtrl \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(44) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfThirty2Tally \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(45) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfEnhSecurity \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(46) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfShortPreamble \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(47) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfExcludeLongPreamble \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(48) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfAuthenticationRspTO \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(49) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfBasicRates \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(50) | 0x18000000)
+#define DIDmib_p2_p2Static_p2CnfSupportedRates \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(2) | \
+ P80211DID_MKITEM(51) | 0x18000000)
+#define DIDmib_p2_p2Dynamic \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3))
+#define DIDmib_p2_p2Dynamic_p2CreateIBSS \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(2) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(3) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(4) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2PromiscuousMode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(5) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(6) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(7) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(8) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(9) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(10) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(11) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2FragmentationThreshold6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(12) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(13) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(14) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(15) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(16) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(17) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(18) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2RTSThreshold6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(19) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl0 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(20) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(21) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(22) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(23) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(24) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(25) | 0x18000000)
+#define DIDmib_p2_p2Dynamic_p2TxRateControl6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(26) | 0x18000000)
+#define DIDmib_p2_p2Behavior \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(4))
+#define DIDmib_p2_p2Behavior_p2TickTime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(4) | \
+ P80211DID_MKITEM(1) | 0x18000000)
+#define DIDmib_p2_p2NIC \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5))
+#define DIDmib_p2_p2NIC_p2MaxLoadTime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2DLBufferPage \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2DLBufferOffset \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2DLBufferLength \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2PRIIdentity \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2PRISupRange \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2CFIActRanges \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2NICSerialNumber \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(8) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2NICIdentity \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(9) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2MFISupRange \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(10) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2CFISupRange \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(11) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2ChannelList \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(12) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2RegulatoryDomains \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(13) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2TempType \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(14) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2STAIdentity \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(15) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2STASupRange \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(16) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2MFIActRanges \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(17) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2STACFIActRanges \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(18) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2BuildSequence \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(19) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2PrimaryFWID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(20) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2SecondaryFWID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(21) | 0x10000000)
+#define DIDmib_p2_p2NIC_p2TertiaryFWID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(5) | \
+ P80211DID_MKITEM(22) | 0x10000000)
+#define DIDmib_p2_p2MAC \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6))
+#define DIDmib_p2_p2MAC_p2PortStatus \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentSSID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentBSSID \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CommsQuality \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CommsQualityCQ \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CommsQualityASL \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(6) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CommsQualityANL \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(7) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2dbmCommsQuality \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(8) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2dbmCommsQualityCQ \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(9) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2dbmCommsQualityASL \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(10) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2dbmCommsQualityANL \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(11) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(12) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentBeaconInterval \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(13) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(14) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2APCurrentScaleThresholds \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(15) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2ProtocolRspTime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(16) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2ShortRetryLimit \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(17) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2LongRetryLimit \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(18) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2MaxTransmitLifetime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(19) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2MaxReceiveLifetime \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(20) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CFPollable \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(21) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2AuthenticationAlgorithms \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(22) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2PrivacyOptionImplemented \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(23) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate1 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(24) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate2 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(25) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate3 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(26) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate4 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(27) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate5 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(28) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2CurrentTxRate6 \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(29) | 0x10000000)
+#define DIDmib_p2_p2MAC_p2OwnMACAddress \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(6) | \
+ P80211DID_MKITEM(30) | 0x10000000)
+#define DIDmib_p2_p2Modem \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7))
+#define DIDmib_p2_p2Modem_p2PHYType \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(1) | 0x10000000)
+#define DIDmib_p2_p2Modem_p2CurrentChannel \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(2) | 0x10000000)
+#define DIDmib_p2_p2Modem_p2CurrentPowerState \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(3) | 0x10000000)
+#define DIDmib_p2_p2Modem_p2CCAMode \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(4) | 0x10000000)
+#define DIDmib_p2_p2Modem_p2SupportedDataRates \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(5) | 0x10000000)
+#define DIDmib_p2_p2Modem_p2TxPowerMax \
+ (P80211DID_MKSECTION(5) | \
+ P80211DID_MKGROUP(7) | \
+ P80211DID_MKITEM(6) | 0x18000000)
+#endif
diff --git a/drivers/staging/wlan-ng/p80211metamib.h b/drivers/staging/wlan-ng/p80211metamib.h
new file mode 100644
index 00000000000..19867fd314e
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211metamib.h
@@ -0,0 +1,105 @@
+/* p80211metamib.h
+*
+* Macros, const, types, and funcs for p80211 mib metadata
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares some of the constants and types used in various
+* parts of the linux-wlan system.
+*
+* Notes:
+* - Constant values are always in HOST byte order.
+*
+* All functions and statics declared here are implemented in p80211types.c
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211METAMIB_H
+#define _P80211METAMIB_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+/*================================================================*/
+/* Constants */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Macros */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Extern Declarations */
+
+/*----------------------------------------------------------------*/
+/* The following is the external declaration for the mib */
+/* category metadata list */
+
+extern catlistitem_t mib_catlist[];
+extern UINT32 mib_catlist_size;
+
+
+/*================================================================*/
+/* Function Declarations */
+
+/*----------------------------------------------------------------*/
+/* */
+
+#endif /* _P80211METAMIB_H */
diff --git a/drivers/staging/wlan-ng/p80211metamsg.h b/drivers/staging/wlan-ng/p80211metamsg.h
new file mode 100644
index 00000000000..4d6dfcc79b8
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211metamsg.h
@@ -0,0 +1,105 @@
+/* p80211metamsg.h
+*
+* Macros, const, types, and funcs for p80211 msg metadata
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares some of the constants and types used in various
+* parts of the linux-wlan system.
+*
+* Notes:
+* - Constant values are always in HOST byte order.
+*
+* All functions and statics declared here are implemented in p80211types.c
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211METAMSG_H
+#define _P80211METAMSG_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+/*================================================================*/
+/* Constants */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Macros */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* */
+
+/*================================================================*/
+/* Extern Declarations */
+
+/*----------------------------------------------------------------*/
+/* The following is the external declaration for the message */
+/* category metadata list */
+
+extern catlistitem_t msg_catlist[];
+extern UINT32 msg_catlist_size;
+
+
+/*================================================================*/
+/* Function Declarations */
+
+/*----------------------------------------------------------------*/
+/* */
+
+#endif /* _P80211METAMSG_H */
diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h
new file mode 100644
index 00000000000..715f4b2adc6
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211metastruct.h
@@ -0,0 +1,644 @@
+/* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY.
+* --------------------------------------------------------------------
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211MKMETASTRUCT_H
+#define _P80211MKMETASTRUCT_H
+
+
+typedef struct p80211msg_dot11req_mibget
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_unk392_t mibattribute ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibget_t;
+
+typedef struct p80211msg_dot11req_mibset
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_unk392_t mibattribute ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibset_t;
+
+typedef struct p80211msg_dot11req_powermgmt
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t powermgmtmode ;
+ p80211item_uint32_t wakeup ;
+ p80211item_uint32_t receivedtims ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_powermgmt_t;
+
+typedef struct p80211msg_dot11req_scan
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t bsstype ;
+ p80211item_pstr6_t bssid ;
+ UINT8 pad_0C[1] ;
+ p80211item_pstr32_t ssid ;
+ UINT8 pad_1D[3] ;
+ p80211item_uint32_t scantype ;
+ p80211item_uint32_t probedelay ;
+ p80211item_pstr14_t channellist ;
+ UINT8 pad_2C[1] ;
+ p80211item_uint32_t minchanneltime ;
+ p80211item_uint32_t maxchanneltime ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t numbss ;
+ p80211item_uint32_t append ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_t;
+
+typedef struct p80211msg_dot11req_scan_results
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t bssindex ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t signal ;
+ p80211item_uint32_t noise ;
+ p80211item_pstr6_t bssid ;
+ UINT8 pad_3C[1] ;
+ p80211item_pstr32_t ssid ;
+ UINT8 pad_4D[3] ;
+ p80211item_uint32_t bsstype ;
+ p80211item_uint32_t beaconperiod ;
+ p80211item_uint32_t dtimperiod ;
+ p80211item_uint32_t timestamp ;
+ p80211item_uint32_t localtime ;
+ p80211item_uint32_t fhdwelltime ;
+ p80211item_uint32_t fhhopset ;
+ p80211item_uint32_t fhhoppattern ;
+ p80211item_uint32_t fhhopindex ;
+ p80211item_uint32_t dschannel ;
+ p80211item_uint32_t cfpcount ;
+ p80211item_uint32_t cfpperiod ;
+ p80211item_uint32_t cfpmaxduration ;
+ p80211item_uint32_t cfpdurremaining ;
+ p80211item_uint32_t ibssatimwindow ;
+ p80211item_uint32_t cfpollable ;
+ p80211item_uint32_t cfpollreq ;
+ p80211item_uint32_t privacy ;
+ p80211item_uint32_t basicrate1 ;
+ p80211item_uint32_t basicrate2 ;
+ p80211item_uint32_t basicrate3 ;
+ p80211item_uint32_t basicrate4 ;
+ p80211item_uint32_t basicrate5 ;
+ p80211item_uint32_t basicrate6 ;
+ p80211item_uint32_t basicrate7 ;
+ p80211item_uint32_t basicrate8 ;
+ p80211item_uint32_t supprate1 ;
+ p80211item_uint32_t supprate2 ;
+ p80211item_uint32_t supprate3 ;
+ p80211item_uint32_t supprate4 ;
+ p80211item_uint32_t supprate5 ;
+ p80211item_uint32_t supprate6 ;
+ p80211item_uint32_t supprate7 ;
+ p80211item_uint32_t supprate8 ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_results_t;
+
+typedef struct p80211msg_dot11req_join
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t bssid ;
+ UINT8 pad_5C[1] ;
+ p80211item_uint32_t joinfailuretimeout ;
+ p80211item_uint32_t basicrate1 ;
+ p80211item_uint32_t basicrate2 ;
+ p80211item_uint32_t basicrate3 ;
+ p80211item_uint32_t basicrate4 ;
+ p80211item_uint32_t basicrate5 ;
+ p80211item_uint32_t basicrate6 ;
+ p80211item_uint32_t basicrate7 ;
+ p80211item_uint32_t basicrate8 ;
+ p80211item_uint32_t operationalrate1 ;
+ p80211item_uint32_t operationalrate2 ;
+ p80211item_uint32_t operationalrate3 ;
+ p80211item_uint32_t operationalrate4 ;
+ p80211item_uint32_t operationalrate5 ;
+ p80211item_uint32_t operationalrate6 ;
+ p80211item_uint32_t operationalrate7 ;
+ p80211item_uint32_t operationalrate8 ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_join_t;
+
+typedef struct p80211msg_dot11req_authenticate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_6C[1] ;
+ p80211item_uint32_t authenticationtype ;
+ p80211item_uint32_t authenticationfailuretimeout ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_authenticate_t;
+
+typedef struct p80211msg_dot11req_deauthenticate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_7C[1] ;
+ p80211item_uint32_t reasoncode ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_deauthenticate_t;
+
+typedef struct p80211msg_dot11req_associate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_8C[1] ;
+ p80211item_uint32_t associatefailuretimeout ;
+ p80211item_uint32_t cfpollable ;
+ p80211item_uint32_t cfpollreq ;
+ p80211item_uint32_t privacy ;
+ p80211item_uint32_t listeninterval ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_associate_t;
+
+typedef struct p80211msg_dot11req_reassociate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t newapaddress ;
+ UINT8 pad_9C[1] ;
+ p80211item_uint32_t reassociatefailuretimeout ;
+ p80211item_uint32_t cfpollable ;
+ p80211item_uint32_t cfpollreq ;
+ p80211item_uint32_t privacy ;
+ p80211item_uint32_t listeninterval ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reassociate_t;
+
+typedef struct p80211msg_dot11req_disassociate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_10C[1] ;
+ p80211item_uint32_t reasoncode ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_disassociate_t;
+
+typedef struct p80211msg_dot11req_reset
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t setdefaultmib ;
+ p80211item_pstr6_t macaddress ;
+ UINT8 pad_11C[1] ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_reset_t;
+
+typedef struct p80211msg_dot11req_start
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr32_t ssid ;
+ UINT8 pad_12D[3] ;
+ p80211item_uint32_t bsstype ;
+ p80211item_uint32_t beaconperiod ;
+ p80211item_uint32_t dtimperiod ;
+ p80211item_uint32_t cfpperiod ;
+ p80211item_uint32_t cfpmaxduration ;
+ p80211item_uint32_t fhdwelltime ;
+ p80211item_uint32_t fhhopset ;
+ p80211item_uint32_t fhhoppattern ;
+ p80211item_uint32_t dschannel ;
+ p80211item_uint32_t ibssatimwindow ;
+ p80211item_uint32_t probedelay ;
+ p80211item_uint32_t cfpollable ;
+ p80211item_uint32_t cfpollreq ;
+ p80211item_uint32_t basicrate1 ;
+ p80211item_uint32_t basicrate2 ;
+ p80211item_uint32_t basicrate3 ;
+ p80211item_uint32_t basicrate4 ;
+ p80211item_uint32_t basicrate5 ;
+ p80211item_uint32_t basicrate6 ;
+ p80211item_uint32_t basicrate7 ;
+ p80211item_uint32_t basicrate8 ;
+ p80211item_uint32_t operationalrate1 ;
+ p80211item_uint32_t operationalrate2 ;
+ p80211item_uint32_t operationalrate3 ;
+ p80211item_uint32_t operationalrate4 ;
+ p80211item_uint32_t operationalrate5 ;
+ p80211item_uint32_t operationalrate6 ;
+ p80211item_uint32_t operationalrate7 ;
+ p80211item_uint32_t operationalrate8 ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_start_t;
+
+typedef struct p80211msg_dot11ind_authenticate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_13C[1] ;
+ p80211item_uint32_t authenticationtype ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_authenticate_t;
+
+typedef struct p80211msg_dot11ind_deauthenticate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_14C[1] ;
+ p80211item_uint32_t reasoncode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_deauthenticate_t;
+
+typedef struct p80211msg_dot11ind_associate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_15C[1] ;
+ p80211item_uint32_t aid ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_associate_t;
+
+typedef struct p80211msg_dot11ind_reassociate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_16C[1] ;
+ p80211item_uint32_t aid ;
+ p80211item_pstr6_t oldapaddress ;
+ UINT8 pad_17C[1] ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_reassociate_t;
+
+typedef struct p80211msg_dot11ind_disassociate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t peerstaaddress ;
+ UINT8 pad_18C[1] ;
+ p80211item_uint32_t reasoncode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_dot11ind_disassociate_t;
+
+typedef struct p80211msg_lnxreq_ifstate
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t ifstate ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_ifstate_t;
+
+typedef struct p80211msg_lnxreq_wlansniff
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t enable ;
+ p80211item_uint32_t channel ;
+ p80211item_uint32_t prismheader ;
+ p80211item_uint32_t wlanheader ;
+ p80211item_uint32_t keepwepflags ;
+ p80211item_uint32_t stripfcs ;
+ p80211item_uint32_t packet_trunc ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_wlansniff_t;
+
+typedef struct p80211msg_lnxreq_hostwep
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t decrypt ;
+ p80211item_uint32_t encrypt ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_hostwep_t;
+
+typedef struct p80211msg_lnxreq_commsquality
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t dbm ;
+ p80211item_uint32_t link ;
+ p80211item_uint32_t level ;
+ p80211item_uint32_t noise ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_commsquality_t;
+
+typedef struct p80211msg_lnxreq_autojoin
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr32_t ssid ;
+ UINT8 pad_19D[3] ;
+ p80211item_uint32_t authtype ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_autojoin_t;
+
+typedef struct p80211msg_lnxind_wlansniffrm
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t hosttime ;
+ p80211item_uint32_t mactime ;
+ p80211item_uint32_t channel ;
+ p80211item_uint32_t rssi ;
+ p80211item_uint32_t sq ;
+ p80211item_uint32_t signal ;
+ p80211item_uint32_t noise ;
+ p80211item_uint32_t rate ;
+ p80211item_uint32_t istx ;
+ p80211item_uint32_t frmlen ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_wlansniffrm_t;
+
+typedef struct p80211msg_lnxind_roam
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t reason ;
+} __WLAN_ATTRIB_PACK__ p80211msg_lnxind_roam_t;
+
+typedef struct p80211msg_p2req_join
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_pstr6_t bssid ;
+ UINT8 pad_20C[1] ;
+ p80211item_uint32_t basicrate1 ;
+ p80211item_uint32_t basicrate2 ;
+ p80211item_uint32_t basicrate3 ;
+ p80211item_uint32_t basicrate4 ;
+ p80211item_uint32_t basicrate5 ;
+ p80211item_uint32_t basicrate6 ;
+ p80211item_uint32_t basicrate7 ;
+ p80211item_uint32_t basicrate8 ;
+ p80211item_uint32_t operationalrate1 ;
+ p80211item_uint32_t operationalrate2 ;
+ p80211item_uint32_t operationalrate3 ;
+ p80211item_uint32_t operationalrate4 ;
+ p80211item_uint32_t operationalrate5 ;
+ p80211item_uint32_t operationalrate6 ;
+ p80211item_uint32_t operationalrate7 ;
+ p80211item_uint32_t operationalrate8 ;
+ p80211item_pstr32_t ssid ;
+ UINT8 pad_21D[3] ;
+ p80211item_uint32_t channel ;
+ p80211item_uint32_t authtype ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_join_t;
+
+typedef struct p80211msg_p2req_readpda
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_unk1024_t pda ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readpda_t;
+
+typedef struct p80211msg_p2req_readcis
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_unk1024_t cis ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readcis_t;
+
+typedef struct p80211msg_p2req_auxport_state
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t enable ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_state_t;
+
+typedef struct p80211msg_p2req_auxport_read
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t len ;
+ p80211item_unk1024_t data ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_read_t;
+
+typedef struct p80211msg_p2req_auxport_write
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t len ;
+ p80211item_unk1024_t data ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_auxport_write_t;
+
+typedef struct p80211msg_p2req_low_level
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t command ;
+ p80211item_uint32_t param0 ;
+ p80211item_uint32_t param1 ;
+ p80211item_uint32_t param2 ;
+ p80211item_uint32_t resp0 ;
+ p80211item_uint32_t resp1 ;
+ p80211item_uint32_t resp2 ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_low_level_t;
+
+typedef struct p80211msg_p2req_test_command
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t testcode ;
+ p80211item_uint32_t testparam ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t status ;
+ p80211item_uint32_t resp0 ;
+ p80211item_uint32_t resp1 ;
+ p80211item_uint32_t resp2 ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_test_command_t;
+
+typedef struct p80211msg_p2req_mmi_read
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t value ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_read_t;
+
+typedef struct p80211msg_p2req_mmi_write
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t data ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mmi_write_t;
+
+typedef struct p80211msg_p2req_ramdl_state
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t enable ;
+ p80211item_uint32_t exeaddr ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_state_t;
+
+typedef struct p80211msg_p2req_ramdl_write
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t len ;
+ p80211item_unk4096_t data ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_write_t;
+
+typedef struct p80211msg_p2req_flashdl_state
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t enable ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_state_t;
+
+typedef struct p80211msg_p2req_flashdl_write
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t addr ;
+ p80211item_uint32_t len ;
+ p80211item_unk4096_t data ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_write_t;
+
+typedef struct p80211msg_p2req_mm_state
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t enable ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_mm_state_t;
+
+typedef struct p80211msg_p2req_dump_state
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t level ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_dump_state_t;
+
+typedef struct p80211msg_p2req_channel_info
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t channellist ;
+ p80211item_uint32_t channeldwelltime ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t numchinfo ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_t;
+
+typedef struct p80211msg_p2req_channel_info_results
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t channel ;
+ p80211item_uint32_t resultcode ;
+ p80211item_uint32_t avgnoiselevel ;
+ p80211item_uint32_t peaknoiselevel ;
+ p80211item_uint32_t bssactive ;
+ p80211item_uint32_t pcfactive ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_channel_info_results_t;
+
+typedef struct p80211msg_p2req_enable
+{
+ UINT32 msgcode ;
+ UINT32 msglen ;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX] ;
+ p80211item_uint32_t resultcode ;
+} __WLAN_ATTRIB_PACK__ p80211msg_p2req_enable_t;
+
+#endif
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
new file mode 100644
index 00000000000..bd4c1629eab
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -0,0 +1,575 @@
+/* p80211mgmt.h
+*
+* Macros, types, and functions to handle 802.11 mgmt frames
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares the constants and types used in the interface
+* between a wlan driver and the user mode utilities.
+*
+* Notes:
+* - Constant values are always in HOST byte order. To assign
+* values to multi-byte fields they _must_ be converted to
+* ieee byte order. To retrieve multi-byte values from incoming
+* frames, they must be converted to host order.
+*
+* - The len member of the frame structure does NOT!!! include
+* the MAC CRC. Therefore, the len field on rx'd frames should
+* have 4 subtracted from it.
+*
+* All functions declared here are implemented in p80211.c
+*
+* The types, macros, and functions defined here are primarily
+* used for encoding and decoding management frames. They are
+* designed to follow these patterns of use:
+*
+* DECODE:
+* 1) a frame of length len is received into buffer b
+* 2) using the hdr structure and macros, we determine the type
+* 3) an appropriate mgmt frame structure, mf, is allocated and zeroed
+* 4) mf.hdr = b
+* mf.buf = b
+* mf.len = len
+* 5) call mgmt_decode( mf )
+* 6) the frame field pointers in mf are now set. Note that any
+* multi-byte frame field values accessed using the frame field
+* pointers are in ieee byte order and will have to be converted
+* to host order.
+*
+* ENCODE:
+* 1) Library client allocates buffer space for maximum length
+* frame of the desired type
+* 2) Library client allocates a mgmt frame structure, called mf,
+* of the desired type
+* 3) Set the following:
+* mf.type = <desired type>
+* mf.buf = <allocated buffer address>
+* 4) call mgmt_encode( mf )
+* 5) all of the fixed field pointers and fixed length information element
+* pointers in mf are now set to their respective locations in the
+* allocated space (fortunately, all variable length information elements
+* fall at the end of their respective frames).
+* 5a) The length field is set to include the last of the fixed and fixed
+* length fields. It may have to be updated for optional or variable
+* length information elements.
+* 6) Optional and variable length information elements are special cases
+* and must be handled individually by the client code.
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211MGMT_H
+#define _P80211MGMT_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+#ifndef _P80211HDR_H
+#include "p80211hdr.h"
+#endif
+
+
+/*================================================================*/
+/* Constants */
+
+/*-- Information Element IDs --------------------*/
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARMS 2
+#define WLAN_EID_DS_PARMS 3
+#define WLAN_EID_CF_PARMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARMS 6
+/*-- values 7-15 reserved --*/
+#define WLAN_EID_CHALLENGE 16
+/*-- values 17-31 reserved for challenge text extension --*/
+/*-- values 32-255 reserved --*/
+
+/*-- Reason Codes -------------------------------*/
+#define WLAN_MGMT_REASON_RSVD 0
+#define WLAN_MGMT_REASON_UNSPEC 1
+#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2
+#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3
+#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4
+#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6
+#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7
+#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8
+#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9
+
+/*-- Status Codes -------------------------------*/
+#define WLAN_MGMT_STATUS_SUCCESS 0
+#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1
+#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13
+#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14
+#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15
+#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18
+ /* p80211b additions */
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21
+
+
+
+/*-- Auth Algorithm Field ---------------------------*/
+#define WLAN_AUTH_ALG_OPENSYSTEM 0
+#define WLAN_AUTH_ALG_SHAREDKEY 1
+
+/*-- Management Frame Field Offsets -------------*/
+/* Note: Not all fields are listed because of variable lengths, */
+/* see the code in p80211.c to see how we search for fields */
+/* Note: These offsets are from the start of the frame data */
+
+#define WLAN_BEACON_OFF_TS 0
+#define WLAN_BEACON_OFF_BCN_INT 8
+#define WLAN_BEACON_OFF_CAPINFO 10
+#define WLAN_BEACON_OFF_SSID 12
+
+#define WLAN_DISASSOC_OFF_REASON 0
+
+#define WLAN_ASSOCREQ_OFF_CAP_INFO 0
+#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2
+#define WLAN_ASSOCREQ_OFF_SSID 4
+
+#define WLAN_ASSOCRESP_OFF_CAP_INFO 0
+#define WLAN_ASSOCRESP_OFF_STATUS 2
+#define WLAN_ASSOCRESP_OFF_AID 4
+#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6
+
+#define WLAN_REASSOCREQ_OFF_CAP_INFO 0
+#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2
+#define WLAN_REASSOCREQ_OFF_CURR_AP 4
+#define WLAN_REASSOCREQ_OFF_SSID 10
+
+#define WLAN_REASSOCRESP_OFF_CAP_INFO 0
+#define WLAN_REASSOCRESP_OFF_STATUS 2
+#define WLAN_REASSOCRESP_OFF_AID 4
+#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6
+
+#define WLAN_PROBEREQ_OFF_SSID 0
+
+#define WLAN_PROBERESP_OFF_TS 0
+#define WLAN_PROBERESP_OFF_BCN_INT 8
+#define WLAN_PROBERESP_OFF_CAP_INFO 10
+#define WLAN_PROBERESP_OFF_SSID 12
+
+#define WLAN_AUTHEN_OFF_AUTH_ALG 0
+#define WLAN_AUTHEN_OFF_AUTH_SEQ 2
+#define WLAN_AUTHEN_OFF_STATUS 4
+#define WLAN_AUTHEN_OFF_CHALLENGE 6
+
+#define WLAN_DEAUTHEN_OFF_REASON 0
+
+
+/*================================================================*/
+/* Macros */
+
+/*-- Capability Field ---------------------------*/
+#define WLAN_GET_MGMT_CAP_INFO_ESS(n) ((n) & BIT0)
+#define WLAN_GET_MGMT_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1)
+#define WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2)
+#define WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3)
+#define WLAN_GET_MGMT_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4)
+ /* p80211b additions */
+#define WLAN_GET_MGMT_CAP_INFO_SHORT(n) (((n) & BIT5) >> 5)
+#define WLAN_GET_MGMT_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6)
+#define WLAN_GET_MGMT_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7)
+
+#define WLAN_SET_MGMT_CAP_INFO_ESS(n) (n)
+#define WLAN_SET_MGMT_CAP_INFO_IBSS(n) ((n) << 1)
+#define WLAN_SET_MGMT_CAP_INFO_CFPOLLABLE(n) ((n) << 2)
+#define WLAN_SET_MGMT_CAP_INFO_CFPOLLREQ(n) ((n) << 3)
+#define WLAN_SET_MGMT_CAP_INFO_PRIVACY(n) ((n) << 4)
+ /* p80211b additions */
+#define WLAN_SET_MGMT_CAP_INFO_SHORT(n) ((n) << 5)
+#define WLAN_SET_MGMT_CAP_INFO_PBCC(n) ((n) << 6)
+#define WLAN_SET_MGMT_CAP_INFO_AGILITY(n) ((n) << 7)
+
+
+/*================================================================*/
+/* Types */
+
+/*-- Information Element Types --------------------*/
+/* prototype structure, all IEs start with these members */
+
+typedef struct wlan_ie
+{
+ UINT8 eid;
+ UINT8 len;
+} __WLAN_ATTRIB_PACK__ wlan_ie_t;
+
+/*-- Service Set Identity (SSID) -----------------*/
+typedef struct wlan_ie_ssid
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 ssid[1]; /* may be zero, ptrs may overlap */
+} __WLAN_ATTRIB_PACK__ wlan_ie_ssid_t;
+
+/*-- Supported Rates -----------------------------*/
+typedef struct wlan_ie_supp_rates
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 rates[1]; /* had better be at LEAST one! */
+} __WLAN_ATTRIB_PACK__ wlan_ie_supp_rates_t;
+
+/*-- FH Parameter Set ----------------------------*/
+typedef struct wlan_ie_fh_parms
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT16 dwell;
+ UINT8 hopset;
+ UINT8 hoppattern;
+ UINT8 hopindex;
+} __WLAN_ATTRIB_PACK__ wlan_ie_fh_parms_t;
+
+/*-- DS Parameter Set ----------------------------*/
+typedef struct wlan_ie_ds_parms
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 curr_ch;
+} __WLAN_ATTRIB_PACK__ wlan_ie_ds_parms_t;
+
+/*-- CF Parameter Set ----------------------------*/
+
+typedef struct wlan_ie_cf_parms
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 cfp_cnt;
+ UINT8 cfp_period;
+ UINT16 cfp_maxdur;
+ UINT16 cfp_durremaining;
+} __WLAN_ATTRIB_PACK__ wlan_ie_cf_parms_t;
+
+/*-- TIM ------------------------------------------*/
+typedef struct wlan_ie_tim
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 dtim_cnt;
+ UINT8 dtim_period;
+ UINT8 bitmap_ctl;
+ UINT8 virt_bm[1];
+} __WLAN_ATTRIB_PACK__ wlan_ie_tim_t;
+
+/*-- IBSS Parameter Set ---------------------------*/
+typedef struct wlan_ie_ibss_parms
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT16 atim_win;
+} __WLAN_ATTRIB_PACK__ wlan_ie_ibss_parms_t;
+
+/*-- Challenge Text ------------------------------*/
+typedef struct wlan_ie_challenge
+{
+ UINT8 eid;
+ UINT8 len;
+ UINT8 challenge[1];
+} __WLAN_ATTRIB_PACK__ wlan_ie_challenge_t;
+
+/*-------------------------------------------------*/
+/* Frame Types */
+
+/* prototype structure, all mgmt frame types will start with these members */
+typedef struct wlan_fr_mgmt
+{
+ UINT16 type;
+ UINT16 len; /* DOES NOT include CRC !!!!*/
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ /*-- info elements ----------*/
+} wlan_fr_mgmt_t;
+
+/*-- Beacon ---------------------------------------*/
+typedef struct wlan_fr_beacon
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT64 *ts;
+ UINT16 *bcn_int;
+ UINT16 *cap_info;
+ /*-- info elements ----------*/
+ wlan_ie_ssid_t *ssid;
+ wlan_ie_supp_rates_t *supp_rates;
+ wlan_ie_fh_parms_t *fh_parms;
+ wlan_ie_ds_parms_t *ds_parms;
+ wlan_ie_cf_parms_t *cf_parms;
+ wlan_ie_ibss_parms_t *ibss_parms;
+ wlan_ie_tim_t *tim;
+
+} wlan_fr_beacon_t;
+
+
+/*-- IBSS ATIM ------------------------------------*/
+typedef struct wlan_fr_ibssatim
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8* buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+
+ /*-- fixed fields -----------*/
+ /*-- info elements ----------*/
+
+ /* this frame type has a null body */
+
+} wlan_fr_ibssatim_t;
+
+/*-- Disassociation -------------------------------*/
+typedef struct wlan_fr_disassoc
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *reason;
+
+ /*-- info elements ----------*/
+
+} wlan_fr_disassoc_t;
+
+/*-- Association Request --------------------------*/
+typedef struct wlan_fr_assocreq
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8* buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *cap_info;
+ UINT16 *listen_int;
+ /*-- info elements ----------*/
+ wlan_ie_ssid_t *ssid;
+ wlan_ie_supp_rates_t *supp_rates;
+
+} wlan_fr_assocreq_t;
+
+/*-- Association Response -------------------------*/
+typedef struct wlan_fr_assocresp
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *cap_info;
+ UINT16 *status;
+ UINT16 *aid;
+ /*-- info elements ----------*/
+ wlan_ie_supp_rates_t *supp_rates;
+
+} wlan_fr_assocresp_t;
+
+/*-- Reassociation Request ------------------------*/
+typedef struct wlan_fr_reassocreq
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *cap_info;
+ UINT16 *listen_int;
+ UINT8 *curr_ap;
+ /*-- info elements ----------*/
+ wlan_ie_ssid_t *ssid;
+ wlan_ie_supp_rates_t *supp_rates;
+
+} wlan_fr_reassocreq_t;
+
+/*-- Reassociation Response -----------------------*/
+typedef struct wlan_fr_reassocresp
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *cap_info;
+ UINT16 *status;
+ UINT16 *aid;
+ /*-- info elements ----------*/
+ wlan_ie_supp_rates_t *supp_rates;
+
+} wlan_fr_reassocresp_t;
+
+/*-- Probe Request --------------------------------*/
+typedef struct wlan_fr_probereq
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ /*-- info elements ----------*/
+ wlan_ie_ssid_t *ssid;
+ wlan_ie_supp_rates_t *supp_rates;
+
+} wlan_fr_probereq_t;
+
+/*-- Probe Response -------------------------------*/
+typedef struct wlan_fr_proberesp
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT64 *ts;
+ UINT16 *bcn_int;
+ UINT16 *cap_info;
+ /*-- info elements ----------*/
+ wlan_ie_ssid_t *ssid;
+ wlan_ie_supp_rates_t *supp_rates;
+ wlan_ie_fh_parms_t *fh_parms;
+ wlan_ie_ds_parms_t *ds_parms;
+ wlan_ie_cf_parms_t *cf_parms;
+ wlan_ie_ibss_parms_t *ibss_parms;
+} wlan_fr_proberesp_t;
+
+/*-- Authentication -------------------------------*/
+typedef struct wlan_fr_authen
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *auth_alg;
+ UINT16 *auth_seq;
+ UINT16 *status;
+ /*-- info elements ----------*/
+ wlan_ie_challenge_t *challenge;
+
+} wlan_fr_authen_t;
+
+/*-- Deauthenication -----------------------------*/
+typedef struct wlan_fr_deauthen
+{
+ UINT16 type;
+ UINT16 len;
+ UINT8 *buf;
+ p80211_hdr_t *hdr;
+ /* used for target specific data, skb in Linux */
+ void *priv;
+ /*-- fixed fields -----------*/
+ UINT16 *reason;
+
+ /*-- info elements ----------*/
+
+} wlan_fr_deauthen_t;
+
+
+/*================================================================*/
+/* Extern Declarations */
+
+
+/*================================================================*/
+/* Function Declarations */
+
+void wlan_mgmt_encode_beacon( wlan_fr_beacon_t *f );
+void wlan_mgmt_decode_beacon( wlan_fr_beacon_t *f );
+void wlan_mgmt_encode_disassoc( wlan_fr_disassoc_t *f );
+void wlan_mgmt_decode_disassoc( wlan_fr_disassoc_t *f );
+void wlan_mgmt_encode_assocreq( wlan_fr_assocreq_t *f );
+void wlan_mgmt_decode_assocreq( wlan_fr_assocreq_t *f );
+void wlan_mgmt_encode_assocresp( wlan_fr_assocresp_t *f );
+void wlan_mgmt_decode_assocresp( wlan_fr_assocresp_t *f );
+void wlan_mgmt_encode_reassocreq( wlan_fr_reassocreq_t *f );
+void wlan_mgmt_decode_reassocreq( wlan_fr_reassocreq_t *f );
+void wlan_mgmt_encode_reassocresp( wlan_fr_reassocresp_t *f );
+void wlan_mgmt_decode_reassocresp( wlan_fr_reassocresp_t *f );
+void wlan_mgmt_encode_probereq( wlan_fr_probereq_t *f );
+void wlan_mgmt_decode_probereq( wlan_fr_probereq_t *f );
+void wlan_mgmt_encode_proberesp( wlan_fr_proberesp_t *f );
+void wlan_mgmt_decode_proberesp( wlan_fr_proberesp_t *f );
+void wlan_mgmt_encode_authen( wlan_fr_authen_t *f );
+void wlan_mgmt_decode_authen( wlan_fr_authen_t *f );
+void wlan_mgmt_encode_deauthen( wlan_fr_deauthen_t *f );
+void wlan_mgmt_decode_deauthen( wlan_fr_deauthen_t *f );
+
+
+#endif /* _P80211MGMT_H */
diff --git a/drivers/staging/wlan-ng/p80211mod.c b/drivers/staging/wlan-ng/p80211mod.c
new file mode 100644
index 00000000000..e2c3f63be8b
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211mod.c
@@ -0,0 +1,216 @@
+/* src/p80211/p80211mod.c
+*
+* Module entry and exit for p80211
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file contains the p80211.o entry and exit points defined for linux
+* kernel modules.
+*
+* Notes:
+* - all module parameters for p80211.o should be defined here.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25))
+#include <linux/moduleparam.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+
+#include "version.h"
+#include "wlan_compat.h"
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211req.h"
+
+/*================================================================*/
+/* Local Constants */
+
+
+/*================================================================*/
+/* Local Macros */
+
+
+/*================================================================*/
+/* Local Types */
+
+
+/*================================================================*/
+/* Local Static Definitions */
+
+static char *version = "p80211.o: " WLAN_RELEASE;
+
+
+/*----------------------------------------------------------------*/
+/* --Module Parameters */
+
+int wlan_watchdog = 5000;
+module_param(wlan_watchdog, int, 0644);
+MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds");
+
+int wlan_wext_write = 0;
+#if WIRELESS_EXT > 12
+module_param(wlan_wext_write, int, 0644);
+MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions");
+#endif
+
+#ifdef WLAN_INCLUDE_DEBUG
+int wlan_debug=0;
+module_param(wlan_debug, int, 0644);
+MODULE_PARM_DESC(wlan_debug, "p80211 debug level");
+#endif
+
+MODULE_LICENSE("Dual MPL/GPL");
+
+/*================================================================*/
+/* Local Function Declarations */
+
+int init_module(void);
+void cleanup_module(void);
+
+/*================================================================*/
+/* Function Definitions */
+
+/*----------------------------------------------------------------
+* init_module
+*
+* Module initialization routine, called once at module load time.
+*
+* Arguments:
+* none
+*
+* Returns:
+* 0 - success
+* ~0 - failure, module is unloaded.
+*
+* Side effects:
+* TODO: define
+*
+* Call context:
+* process thread (insmod or modprobe)
+----------------------------------------------------------------*/
+int init_module(void)
+{
+ DBFENTER;
+
+#if 0
+ printk(KERN_NOTICE "%s (%s) Loaded\n", version, WLAN_BUILD_DATE);
+#endif
+
+ p80211netdev_startup();
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_STARTUP);
+#endif
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* cleanup_module
+*
+* Called at module unload time. This is our last chance to
+* clean up after ourselves.
+*
+* Arguments:
+* none
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* TODO: define
+*
+* Call context:
+* process thread
+*
+----------------------------------------------------------------*/
+void cleanup_module(void)
+{
+ DBFENTER;
+
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(NULL, WLAN_HOTPLUG_SHUTDOWN);
+#endif
+ p80211netdev_shutdown();
+ printk(KERN_NOTICE "%s Unloaded\n", version);
+
+ DBFEXIT;
+ return;
+}
+
+EXPORT_SYMBOL(p80211netdev_hwremoved);
+EXPORT_SYMBOL(register_wlandev);
+EXPORT_SYMBOL(p80211netdev_rx);
+EXPORT_SYMBOL(unregister_wlandev);
+EXPORT_SYMBOL(wlan_setup);
+EXPORT_SYMBOL(wlan_unsetup);
+EXPORT_SYMBOL(p80211_suspend);
+EXPORT_SYMBOL(p80211_resume);
+
+EXPORT_SYMBOL(p80211skb_free);
+EXPORT_SYMBOL(p80211skb_rxmeta_attach);
+
+EXPORT_SYMBOL(p80211wext_event_associated);
diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h
new file mode 100644
index 00000000000..c14e9fbbd68
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211msg.h
@@ -0,0 +1,102 @@
+/* p80211msg.h
+*
+* Macros, constants, types, and funcs for req and ind messages
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211MSG_H
+#define _P80211MSG_H
+
+/*================================================================*/
+/* System Includes */
+
+/*================================================================*/
+/* Project Includes */
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+/*================================================================*/
+/* Constants */
+
+#define MSG_BUFF_LEN 4000
+#define WLAN_DEVNAMELEN_MAX 16
+
+/*================================================================*/
+/* Macros */
+
+/*================================================================*/
+/* Types */
+
+/*--------------------------------------------------------------------*/
+/*----- Message Structure Types --------------------------------------*/
+
+/*--------------------------------------------------------------------*/
+/* Prototype msg type */
+
+typedef struct p80211msg
+{
+ UINT32 msgcode;
+ UINT32 msglen;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX];
+} __WLAN_ATTRIB_PACK__ p80211msg_t;
+
+typedef struct p80211msgd
+{
+ UINT32 msgcode;
+ UINT32 msglen;
+ UINT8 devname[WLAN_DEVNAMELEN_MAX];
+ UINT8 args[0];
+} __WLAN_ATTRIB_PACK__ p80211msgd_t;
+
+/*================================================================*/
+/* Extern Declarations */
+
+
+/*================================================================*/
+/* Function Declarations */
+
+#endif /* _P80211MSG_H */
+
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
new file mode 100644
index 00000000000..11f84a829e1
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -0,0 +1,1502 @@
+/* src/p80211/p80211knetdev.c
+*
+* Linux Kernel net device interface
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* The functions required for a Linux network device are defined here.
+*
+* --------------------------------------------------------------------
+*/
+
+
+/*================================================================*/
+/* System Includes */
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/kmod.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/sockios.h>
+#include <linux/etherdevice.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#ifdef SIOCETHTOOL
+#include <linux/ethtool.h>
+#endif
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+#include <net/net_namespace.h>
+
+/*================================================================*/
+/* Project Includes */
+
+#include "version.h"
+#include "wlan_compat.h"
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211conv.h"
+#include "p80211mgmt.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211ioctl.h"
+#include "p80211req.h"
+#include "p80211metastruct.h"
+#include "p80211metadef.h"
+
+/*================================================================*/
+/* Local Constants */
+
+/*================================================================*/
+/* Local Macros */
+
+
+/*================================================================*/
+/* Local Types */
+
+/*================================================================*/
+/* Local Static Definitions */
+
+#define __NO_VERSION__ /* prevent the static definition */
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_p80211;
+#endif
+
+/*================================================================*/
+/* Local Function Declarations */
+
+/* Support functions */
+static void p80211netdev_rx_bh(unsigned long arg);
+
+/* netdevice method functions */
+static int p80211knetdev_init( netdevice_t *netdev);
+static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev);
+static int p80211knetdev_open( netdevice_t *netdev);
+static int p80211knetdev_stop( netdevice_t *netdev );
+static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev);
+static void p80211knetdev_set_multicast_list(netdevice_t *dev);
+static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd);
+static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr);
+static void p80211knetdev_tx_timeout(netdevice_t *netdev);
+static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc);
+
+#ifdef CONFIG_PROC_FS
+static int
+p80211netdev_proc_read(
+ char *page,
+ char **start,
+ off_t offset,
+ int count,
+ int *eof,
+ void *data);
+#endif
+
+/*================================================================*/
+/* Function Definitions */
+
+/*----------------------------------------------------------------
+* p80211knetdev_startup
+*
+* Initialize the wlandevice/netdevice part of 802.11 services at
+* load time.
+*
+* Arguments:
+* none
+*
+* Returns:
+* nothing
+----------------------------------------------------------------*/
+void p80211netdev_startup(void)
+{
+ DBFENTER;
+
+#ifdef CONFIG_PROC_FS
+ if (init_net.proc_net != NULL) {
+ proc_p80211 = create_proc_entry(
+ "p80211",
+ (S_IFDIR|S_IRUGO|S_IXUGO),
+ init_net.proc_net);
+ }
+#endif
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* p80211knetdev_shutdown
+*
+* Shutdown the wlandevice/netdevice part of 802.11 services at
+* unload time.
+*
+* Arguments:
+* none
+*
+* Returns:
+* nothing
+----------------------------------------------------------------*/
+void
+p80211netdev_shutdown(void)
+{
+ DBFENTER;
+#ifdef CONFIG_PROC_FS
+ if (proc_p80211 != NULL) {
+ remove_proc_entry("p80211", init_net.proc_net);
+ }
+#endif
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* p80211knetdev_init
+*
+* Init method for a Linux netdevice. Called in response to
+* register_netdev.
+*
+* Arguments:
+* none
+*
+* Returns:
+* nothing
+----------------------------------------------------------------*/
+static int p80211knetdev_init( netdevice_t *netdev)
+{
+ DBFENTER;
+ /* Called in response to register_netdev */
+ /* This is usually the probe function, but the probe has */
+ /* already been done by the MSD and the create_kdev */
+ /* function. All we do here is return success */
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* p80211knetdev_get_stats
+*
+* Statistics retrieval for linux netdevices. Here we're reporting
+* the Linux i/f level statistics. Hence, for the primary numbers,
+* we don't want to report the numbers from the MIB. Eventually,
+* it might be useful to collect some of the error counters though.
+*
+* Arguments:
+* netdev Linux netdevice
+*
+* Returns:
+* the address of the statistics structure
+----------------------------------------------------------------*/
+static struct net_device_stats*
+p80211knetdev_get_stats(netdevice_t *netdev)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)netdev->priv;
+ DBFENTER;
+
+ /* TODO: review the MIB stats for items that correspond to
+ linux stats */
+
+ DBFEXIT;
+ return &(wlandev->linux_stats);
+}
+
+
+/*----------------------------------------------------------------
+* p80211knetdev_open
+*
+* Linux netdevice open method. Following a successful call here,
+* the device is supposed to be ready for tx and rx. In our
+* situation that may not be entirely true due to the state of the
+* MAC below.
+*
+* Arguments:
+* netdev Linux network device structure
+*
+* Returns:
+* zero on success, non-zero otherwise
+----------------------------------------------------------------*/
+static int p80211knetdev_open( netdevice_t *netdev )
+{
+ int result = 0; /* success */
+ wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv);
+
+ DBFENTER;
+
+ /* Check to make sure the MSD is running */
+ if ( wlandev->msdstate != WLAN_MSD_RUNNING ) {
+ return -ENODEV;
+ }
+
+ /* Tell the MSD to open */
+ if ( wlandev->open != NULL) {
+ result = wlandev->open(wlandev);
+ if ( result == 0 ) {
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) )
+ netdev->interrupt = 0;
+#endif
+ p80211netdev_start_queue(wlandev);
+ wlandev->state = WLAN_DEVICE_OPEN;
+ }
+ } else {
+ result = -EAGAIN;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* p80211knetdev_stop
+*
+* Linux netdevice stop (close) method. Following this call,
+* no frames should go up or down through this interface.
+*
+* Arguments:
+* netdev Linux network device structure
+*
+* Returns:
+* zero on success, non-zero otherwise
+----------------------------------------------------------------*/
+static int p80211knetdev_stop( netdevice_t *netdev )
+{
+ int result = 0;
+ wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv);
+
+ DBFENTER;
+
+ if ( wlandev->close != NULL ) {
+ result = wlandev->close(wlandev);
+ }
+
+ p80211netdev_stop_queue(wlandev);
+ wlandev->state = WLAN_DEVICE_CLOSED;
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* p80211netdev_rx
+*
+* Frame receive function called by the mac specific driver.
+*
+* Arguments:
+* wlandev WLAN network device structure
+* skb skbuff containing a full 802.11 frame.
+* Returns:
+* nothing
+* Side effects:
+*
+----------------------------------------------------------------*/
+void
+p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb )
+{
+ DBFENTER;
+
+ /* Enqueue for post-irq processing */
+ skb_queue_tail(&wlandev->nsd_rxq, skb);
+
+ tasklet_schedule(&wlandev->rx_bh);
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* p80211netdev_rx_bh
+*
+* Deferred processing of all received frames.
+*
+* Arguments:
+* wlandev WLAN network device structure
+* skb skbuff containing a full 802.11 frame.
+* Returns:
+* nothing
+* Side effects:
+*
+----------------------------------------------------------------*/
+static void p80211netdev_rx_bh(unsigned long arg)
+{
+ wlandevice_t *wlandev = (wlandevice_t *) arg;
+ struct sk_buff *skb = NULL;
+ netdevice_t *dev = wlandev->netdev;
+ p80211_hdr_a3_t *hdr;
+ UINT16 fc;
+
+ DBFENTER;
+
+ /* Let's empty our our queue */
+ while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) {
+ if (wlandev->state == WLAN_DEVICE_OPEN) {
+
+ if (dev->type != ARPHRD_ETHER) {
+ /* RAW frame; we shouldn't convert it */
+ // XXX Append the Prism Header here instead.
+
+ /* set up various data fields */
+ skb->dev = dev;
+ skb_reset_mac_header(skb);
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_80211_RAW);
+ dev->last_rx = jiffies;
+
+ wlandev->linux_stats.rx_packets++;
+ wlandev->linux_stats.rx_bytes += skb->len;
+ netif_rx_ni(skb);
+ continue;
+ } else {
+ hdr = (p80211_hdr_a3_t *)skb->data;
+ fc = ieee2host16(hdr->fc);
+ if (p80211_rx_typedrop(wlandev, fc)) {
+ dev_kfree_skb(skb);
+ continue;
+ }
+
+ /* perform mcast filtering */
+ if (wlandev->netdev->flags & IFF_ALLMULTI) {
+ /* allow my local address through */
+ if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) {
+ /* but reject anything else that isn't multicast */
+ if (!(hdr->a1[0] & 0x01)) {
+ dev_kfree_skb(skb);
+ continue;
+ }
+ }
+ }
+
+ if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) {
+ skb->dev->last_rx = jiffies;
+ wlandev->linux_stats.rx_packets++;
+ wlandev->linux_stats.rx_bytes += skb->len;
+ netif_rx_ni(skb);
+ continue;
+ }
+ WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n");
+ }
+ }
+ dev_kfree_skb(skb);
+ }
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* p80211knetdev_hard_start_xmit
+*
+* Linux netdevice method for transmitting a frame.
+*
+* Arguments:
+* skb Linux sk_buff containing the frame.
+* netdev Linux netdevice.
+*
+* Side effects:
+* If the lower layers report that buffers are full. netdev->tbusy
+* will be set to prevent higher layers from sending more traffic.
+*
+* Note: If this function returns non-zero, higher layers retain
+* ownership of the skb.
+*
+* Returns:
+* zero on success, non-zero on failure.
+----------------------------------------------------------------*/
+static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev)
+{
+ int result = 0;
+ int txresult = -1;
+ wlandevice_t *wlandev = (wlandevice_t*)netdev->priv;
+ p80211_hdr_t p80211_hdr;
+ p80211_metawep_t p80211_wep;
+
+ DBFENTER;
+
+ if (skb == NULL) {
+ return 0;
+ }
+
+ if (wlandev->state != WLAN_DEVICE_OPEN) {
+ result = 1;
+ goto failed;
+ }
+
+ memset(&p80211_hdr, 0, sizeof(p80211_hdr_t));
+ memset(&p80211_wep, 0, sizeof(p80211_metawep_t));
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ if ( test_and_set_bit(0, (void*)&(netdev->tbusy)) != 0 ) {
+ /* We've been called w/ tbusy set, has the tx */
+ /* path stalled? */
+ WLAN_LOG_DEBUG(1, "called when tbusy set\n");
+ result = 1;
+ goto failed;
+ }
+#else
+ if ( netif_queue_stopped(netdev) ) {
+ WLAN_LOG_DEBUG(1, "called when queue stopped.\n");
+ result = 1;
+ goto failed;
+ }
+
+ netif_stop_queue(netdev);
+
+ /* No timeout handling here, 2.3.38+ kernels call the
+ * timeout function directly.
+ * TODO: Add timeout handling.
+ */
+#endif
+
+ /* Check to see that a valid mode is set */
+ switch( wlandev->macmode ) {
+ case WLAN_MACMODE_IBSS_STA:
+ case WLAN_MACMODE_ESS_STA:
+ case WLAN_MACMODE_ESS_AP:
+ break;
+ default:
+ /* Mode isn't set yet, just drop the frame
+ * and return success .
+ * TODO: we need a saner way to handle this
+ */
+ if(skb->protocol != ETH_P_80211_RAW) {
+ p80211netdev_start_queue(wlandev);
+ WLAN_LOG_NOTICE(
+ "Tx attempt prior to association, frame dropped.\n");
+ wlandev->linux_stats.tx_dropped++;
+ result = 0;
+ goto failed;
+ }
+ break;
+ }
+
+ /* Check for raw transmits */
+ if(skb->protocol == ETH_P_80211_RAW) {
+ if (!capable(CAP_NET_ADMIN)) {
+ result = 1;
+ goto failed;
+ }
+ /* move the header over */
+ memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t));
+ skb_pull(skb, sizeof(p80211_hdr_t));
+ } else {
+ if ( skb_ether_to_p80211(wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0 ) {
+ /* convert failed */
+ WLAN_LOG_DEBUG(1, "ether_to_80211(%d) failed.\n",
+ wlandev->ethconv);
+ result = 1;
+ goto failed;
+ }
+ }
+ if ( wlandev->txframe == NULL ) {
+ result = 1;
+ goto failed;
+ }
+
+ netdev->trans_start = jiffies;
+
+ wlandev->linux_stats.tx_packets++;
+ /* count only the packet payload */
+ wlandev->linux_stats.tx_bytes += skb->len;
+
+ txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep);
+
+ if ( txresult == 0) {
+ /* success and more buf */
+ /* avail, re: hw_txdata */
+ p80211netdev_wake_queue(wlandev);
+ result = 0;
+ } else if ( txresult == 1 ) {
+ /* success, no more avail */
+ WLAN_LOG_DEBUG(3, "txframe success, no more bufs\n");
+ /* netdev->tbusy = 1; don't set here, irqhdlr */
+ /* may have already cleared it */
+ result = 0;
+ } else if ( txresult == 2 ) {
+ /* alloc failure, drop frame */
+ WLAN_LOG_DEBUG(3, "txframe returned alloc_fail\n");
+ result = 1;
+ } else {
+ /* buffer full or queue busy, drop frame. */
+ WLAN_LOG_DEBUG(3, "txframe returned full or busy\n");
+ result = 1;
+ }
+
+ failed:
+ /* Free up the WEP buffer if it's not the same as the skb */
+ if ((p80211_wep.data) && (p80211_wep.data != skb->data))
+ kfree(p80211_wep.data);
+
+ /* we always free the skb here, never in a lower level. */
+ if (!result)
+ dev_kfree_skb(skb);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* p80211knetdev_set_multicast_list
+*
+* Called from higher lavers whenever there's a need to set/clear
+* promiscuous mode or rewrite the multicast list.
+*
+* Arguments:
+* none
+*
+* Returns:
+* nothing
+----------------------------------------------------------------*/
+static void p80211knetdev_set_multicast_list(netdevice_t *dev)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+ DBFENTER;
+
+ /* TODO: real multicast support as well */
+
+ if (wlandev->set_multicast_list)
+ wlandev->set_multicast_list(wlandev, dev);
+
+ DBFEXIT;
+}
+
+#ifdef SIOCETHTOOL
+
+static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr)
+{
+ UINT32 ethcmd;
+ struct ethtool_drvinfo info;
+ struct ethtool_value edata;
+
+ memset(&info, 0, sizeof(info));
+ memset(&edata, 0, sizeof(edata));
+
+ if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ case ETHTOOL_GDRVINFO:
+ info.cmd = ethcmd;
+ snprintf(info.driver, sizeof(info.driver), "p80211_%s",
+ wlandev->nsdname);
+ snprintf(info.version, sizeof(info.version), "%s",
+ WLAN_RELEASE);
+
+ // info.fw_version
+ // info.bus_info
+
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+#ifdef ETHTOOL_GLINK
+ case ETHTOOL_GLINK:
+ edata.cmd = ethcmd;
+
+ if (wlandev->linkstatus &&
+ (wlandev->macmode != WLAN_MACMODE_NONE)) {
+ edata.data = 1;
+ } else {
+ edata.data = 0;
+ }
+
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+ }
+#endif
+
+ return -EOPNOTSUPP;
+}
+
+#endif
+
+/*----------------------------------------------------------------
+* p80211knetdev_do_ioctl
+*
+* Handle an ioctl call on one of our devices. Everything Linux
+* ioctl specific is done here. Then we pass the contents of the
+* ifr->data to the request message handler.
+*
+* Arguments:
+* dev Linux kernel netdevice
+* ifr Our private ioctl request structure, typed for the
+* generic struct ifreq so we can use ptr to func
+* w/o cast.
+*
+* Returns:
+* zero on success, a negative errno on failure. Possible values:
+* -ENETDOWN Device isn't up.
+* -EBUSY cmd already in progress
+* -ETIME p80211 cmd timed out (MSD may have its own timers)
+* -EFAULT memory fault copying msg from user buffer
+* -ENOMEM unable to allocate kernel msg buffer
+* -ENOSYS bad magic, it the cmd really for us?
+* -EINTR sleeping on cmd, awakened by signal, cmd cancelled.
+*
+* Call Context:
+* Process thread (ioctl caller). TODO: SMP support may require
+* locks.
+----------------------------------------------------------------*/
+static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
+{
+ int result = 0;
+ p80211ioctl_req_t *req = (p80211ioctl_req_t*)ifr;
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ UINT8 *msgbuf;
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len);
+
+#if WIRELESS_EXT < 13
+ /* Is this a wireless extensions ioctl? */
+ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+ if ((result = p80211wext_support_ioctl(dev, ifr, cmd))
+ != (-EOPNOTSUPP)) {
+ goto bail;
+ }
+ }
+#endif
+
+#ifdef SIOCETHTOOL
+ if (cmd == SIOCETHTOOL) {
+ result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data);
+ goto bail;
+ }
+#endif
+
+ /* Test the magic, assume ifr is good if it's there */
+ if ( req->magic != P80211_IOCTL_MAGIC ) {
+ result = -ENOSYS;
+ goto bail;
+ }
+
+ if ( cmd == P80211_IFTEST ) {
+ result = 0;
+ goto bail;
+ } else if ( cmd != P80211_IFREQ ) {
+ result = -ENOSYS;
+ goto bail;
+ }
+
+ /* Allocate a buf of size req->len */
+ if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) {
+ if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) {
+ result = -EFAULT;
+ } else {
+ result = p80211req_dorequest( wlandev, msgbuf);
+ }
+
+ if ( result == 0 ) {
+ if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) {
+ result = -EFAULT;
+ }
+ }
+ kfree(msgbuf);
+ } else {
+ result = -ENOMEM;
+ }
+bail:
+ DBFEXIT;
+
+ return result; /* If allocate,copyfrom or copyto fails, return errno */
+}
+
+/*----------------------------------------------------------------
+* p80211knetdev_set_mac_address
+*
+* Handles the ioctl for changing the MACAddress of a netdevice
+*
+* references: linux/netdevice.h and drivers/net/net_init.c
+*
+* NOTE: [MSM] We only prevent address changes when the netdev is
+* up. We don't control anything based on dot11 state. If the
+* address is changed on a STA that's currently associated, you
+* will probably lose the ability to send and receive data frames.
+* Just be aware. Therefore, this should usually only be done
+* prior to scan/join/auth/assoc.
+*
+* Arguments:
+* dev netdevice struct
+* addr the new MACAddress (a struct)
+*
+* Returns:
+* zero on success, a negative errno on failure. Possible values:
+* -EBUSY device is bussy (cmd not possible)
+* -and errors returned by: p80211req_dorequest(..)
+*
+* by: Collin R. Mulliner <collin@mulliner.org>
+----------------------------------------------------------------*/
+static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr)
+{
+ struct sockaddr *new_addr = addr;
+ p80211msg_dot11req_mibset_t dot11req;
+ p80211item_unk392_t *mibattr;
+ p80211item_pstr6_t *macaddr;
+ p80211item_uint32_t *resultcode;
+ int result = 0;
+
+ DBFENTER;
+ /* If we're running, we don't allow MAC address changes */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ if ( dev->start) {
+ return -EBUSY;
+ }
+#else
+ if (netif_running(dev)) {
+ return -EBUSY;
+ }
+#endif
+
+ /* Set up some convenience pointers. */
+ mibattr = &dot11req.mibattribute;
+ macaddr = (p80211item_pstr6_t*)&mibattr->data;
+ resultcode = &dot11req.resultcode;
+
+ /* Set up a dot11req_mibset */
+ memset(&dot11req, 0, sizeof(p80211msg_dot11req_mibset_t));
+ dot11req.msgcode = DIDmsg_dot11req_mibset;
+ dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t);
+ memcpy(dot11req.devname,
+ ((wlandevice_t*)(dev->priv))->name,
+ WLAN_DEVNAMELEN_MAX - 1);
+
+ /* Set up the mibattribute argument */
+ mibattr->did = DIDmsg_dot11req_mibset_mibattribute;
+ mibattr->status = P80211ENUM_msgitem_status_data_ok;
+ mibattr->len = sizeof(mibattr->data);
+
+ macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress;
+ macaddr->status = P80211ENUM_msgitem_status_data_ok;
+ macaddr->len = sizeof(macaddr->data);
+ macaddr->data.len = WLAN_ADDR_LEN;
+ memcpy(&macaddr->data.data, new_addr->sa_data, WLAN_ADDR_LEN);
+
+ /* Set up the resultcode argument */
+ resultcode->did = DIDmsg_dot11req_mibset_resultcode;
+ resultcode->status = P80211ENUM_msgitem_status_no_value;
+ resultcode->len = sizeof(resultcode->data);
+ resultcode->data = 0;
+
+ /* now fire the request */
+ result = p80211req_dorequest(dev->priv, (UINT8*)&dot11req);
+
+ /* If the request wasn't successful, report an error and don't
+ * change the netdev address
+ */
+ if ( result != 0 || resultcode->data != P80211ENUM_resultcode_success) {
+ WLAN_LOG_ERROR(
+ "Low-level driver failed dot11req_mibset(dot11MACAddress).\n");
+ result = -EADDRNOTAVAIL;
+ } else {
+ /* everything's ok, change the addr in netdev */
+ memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len);
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+static int wlan_change_mtu(netdevice_t *dev, int new_mtu)
+{
+ DBFENTER;
+ // 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap)
+ // and another 8 for wep.
+ if ( (new_mtu < 68) || (new_mtu > (2312 - 20 - 8)))
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+
+ DBFEXIT;
+
+ return 0;
+}
+
+
+
+/*----------------------------------------------------------------
+* wlan_setup
+*
+* Roughly matches the functionality of ether_setup. Here
+* we set up any members of the wlandevice structure that are common
+* to all devices. Additionally, we allocate a linux 'struct device'
+* and perform the same setup as ether_setup.
+*
+* Note: It's important that the caller have setup the wlandev->name
+* ptr prior to calling this function.
+*
+* Arguments:
+* wlandev ptr to the wlandev structure for the
+* interface.
+* Returns:
+* zero on success, non-zero otherwise.
+* Call Context:
+* Should be process thread. We'll assume it might be
+* interrupt though. When we add support for statically
+* compiled drivers, this function will be called in the
+* context of the kernel startup code.
+----------------------------------------------------------------*/
+int wlan_setup(wlandevice_t *wlandev)
+{
+ int result = 0;
+ netdevice_t *dev;
+
+ DBFENTER;
+
+ /* Set up the wlandev */
+ wlandev->state = WLAN_DEVICE_CLOSED;
+ wlandev->ethconv = WLAN_ETHCONV_8021h;
+ wlandev->macmode = WLAN_MACMODE_NONE;
+
+ /* Set up the rx queue */
+ skb_queue_head_init(&wlandev->nsd_rxq);
+ tasklet_init(&wlandev->rx_bh,
+ p80211netdev_rx_bh,
+ (unsigned long)wlandev);
+
+ /* Allocate and initialize the struct device */
+ dev = kmalloc(sizeof(netdevice_t), GFP_ATOMIC);
+ if ( dev == NULL ) {
+ WLAN_LOG_ERROR("Failed to alloc netdev.\n");
+ result = 1;
+ } else {
+ memset( dev, 0, sizeof(netdevice_t));
+ ether_setup(dev);
+ wlandev->netdev = dev;
+ dev->priv = wlandev;
+ dev->hard_start_xmit = p80211knetdev_hard_start_xmit;
+ dev->get_stats = p80211knetdev_get_stats;
+#ifdef HAVE_PRIVATE_IOCTL
+ dev->do_ioctl = p80211knetdev_do_ioctl;
+#endif
+#ifdef HAVE_MULTICAST
+ dev->set_multicast_list = p80211knetdev_set_multicast_list;
+#endif
+ dev->init = p80211knetdev_init;
+ dev->open = p80211knetdev_open;
+ dev->stop = p80211knetdev_stop;
+
+#ifdef CONFIG_NET_WIRELESS
+#if ((WIRELESS_EXT < 17) && (WIRELESS_EXT < 21))
+ dev->get_wireless_stats = p80211wext_get_wireless_stats;
+#endif
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = &p80211wext_handler_def;
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ dev->tbusy = 1;
+ dev->start = 0;
+#else
+ netif_stop_queue(dev);
+#endif
+#ifdef HAVE_CHANGE_MTU
+ dev->change_mtu = wlan_change_mtu;
+#endif
+#ifdef HAVE_SET_MAC_ADDR
+ dev->set_mac_address = p80211knetdev_set_mac_address;
+#endif
+#ifdef HAVE_TX_TIMEOUT
+ dev->tx_timeout = &p80211knetdev_tx_timeout;
+ dev->watchdog_timeo = (wlan_watchdog * HZ) / 1000;
+#endif
+ netif_carrier_off(dev);
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* wlan_unsetup
+*
+* This function is paired with the wlan_setup routine. It should
+* be called after unregister_wlandev. Basically, all it does is
+* free the 'struct device' that's associated with the wlandev.
+* We do it here because the 'struct device' isn't allocated
+* explicitly in the driver code, it's done in wlan_setup. To
+* do the free in the driver might seem like 'magic'.
+*
+* Arguments:
+* wlandev ptr to the wlandev structure for the
+* interface.
+* Returns:
+* zero on success, non-zero otherwise.
+* Call Context:
+* Should be process thread. We'll assume it might be
+* interrupt though. When we add support for statically
+* compiled drivers, this function will be called in the
+* context of the kernel startup code.
+----------------------------------------------------------------*/
+int wlan_unsetup(wlandevice_t *wlandev)
+{
+ int result = 0;
+
+ DBFENTER;
+
+ tasklet_kill(&wlandev->rx_bh);
+
+ if (wlandev->netdev == NULL ) {
+ WLAN_LOG_ERROR("called without wlandev->netdev set.\n");
+ result = 1;
+ } else {
+ free_netdev(wlandev->netdev);
+ wlandev->netdev = NULL;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+
+
+/*----------------------------------------------------------------
+* register_wlandev
+*
+* Roughly matches the functionality of register_netdev. This function
+* is called after the driver has successfully probed and set up the
+* resources for the device. It's now ready to become a named device
+* in the Linux system.
+*
+* First we allocate a name for the device (if not already set), then
+* we call the Linux function register_netdevice.
+*
+* Arguments:
+* wlandev ptr to the wlandev structure for the
+* interface.
+* Returns:
+* zero on success, non-zero otherwise.
+* Call Context:
+* Can be either interrupt or not.
+----------------------------------------------------------------*/
+int register_wlandev(wlandevice_t *wlandev)
+{
+ int i = 0;
+ netdevice_t *dev = wlandev->netdev;
+
+ DBFENTER;
+
+ i = dev_alloc_name(wlandev->netdev, "wlan%d");
+ if (i >= 0) {
+ i = register_netdev(wlandev->netdev);
+ }
+ if (i != 0) {
+ return -EIO;
+ }
+
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) )
+ dev->name = wlandev->name;
+#else
+ strcpy(wlandev->name, dev->name);
+#endif
+
+#ifdef CONFIG_PROC_FS
+ if (proc_p80211) {
+ wlandev->procdir = proc_mkdir(wlandev->name, proc_p80211);
+ if ( wlandev->procdir )
+ wlandev->procwlandev =
+ create_proc_read_entry("wlandev", 0,
+ wlandev->procdir,
+ p80211netdev_proc_read,
+ wlandev);
+ if (wlandev->nsd_proc_read)
+ create_proc_read_entry("nsd", 0,
+ wlandev->procdir,
+ wlandev->nsd_proc_read,
+ wlandev);
+ }
+#endif
+
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REGISTER);
+#endif
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* unregister_wlandev
+*
+* Roughly matches the functionality of unregister_netdev. This
+* function is called to remove a named device from the system.
+*
+* First we tell linux that the device should no longer exist.
+* Then we remove it from the list of known wlan devices.
+*
+* Arguments:
+* wlandev ptr to the wlandev structure for the
+* interface.
+* Returns:
+* zero on success, non-zero otherwise.
+* Call Context:
+* Can be either interrupt or not.
+----------------------------------------------------------------*/
+int unregister_wlandev(wlandevice_t *wlandev)
+{
+ struct sk_buff *skb;
+
+ DBFENTER;
+
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REMOVE);
+#endif
+
+#ifdef CONFIG_PROC_FS
+ if ( wlandev->procwlandev ) {
+ remove_proc_entry("wlandev", wlandev->procdir);
+ }
+ if ( wlandev->nsd_proc_read ) {
+ remove_proc_entry("nsd", wlandev->procdir);
+ }
+ if (wlandev->procdir) {
+ remove_proc_entry(wlandev->name, proc_p80211);
+ }
+#endif
+
+ unregister_netdev(wlandev->netdev);
+
+ /* Now to clean out the rx queue */
+ while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) {
+ dev_kfree_skb(skb);
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+/*----------------------------------------------------------------
+* proc_read
+*
+* Read function for /proc/net/p80211/<device>/wlandev
+*
+* Arguments:
+* buf
+* start
+* offset
+* count
+* eof
+* data
+* Returns:
+* zero on success, non-zero otherwise.
+* Call Context:
+* Can be either interrupt or not.
+----------------------------------------------------------------*/
+static int
+p80211netdev_proc_read(
+ char *page,
+ char **start,
+ off_t offset,
+ int count,
+ int *eof,
+ void *data)
+{
+ char *p = page;
+ wlandevice_t *wlandev = (wlandevice_t *) data;
+
+ DBFENTER;
+ if (offset != 0) {
+ *eof = 1;
+ goto exit;
+ }
+
+ p += sprintf(p, "p80211 version: %s (%s)\n\n",
+ WLAN_RELEASE, WLAN_BUILD_DATE);
+ p += sprintf(p, "name : %s\n", wlandev->name);
+ p += sprintf(p, "nsd name : %s\n", wlandev->nsdname);
+ p += sprintf(p, "address : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ wlandev->netdev->dev_addr[0], wlandev->netdev->dev_addr[1], wlandev->netdev->dev_addr[2],
+ wlandev->netdev->dev_addr[3], wlandev->netdev->dev_addr[4], wlandev->netdev->dev_addr[5]);
+ p += sprintf(p, "nsd caps : %s%s%s%s%s%s%s%s%s%s\n",
+ (wlandev->nsdcaps & P80211_NSDCAP_HARDWAREWEP) ? "wep_hw " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_TIEDWEP) ? "wep_tied " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_NOHOSTWEP) ? "wep_hw_only " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_PBCC) ? "pbcc " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_SHORT_PREAMBLE) ? "short_preamble " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_AGILITY) ? "agility " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_AP_RETRANSMIT) ? "ap_retransmit " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_HWFRAGMENT) ? "hw_frag " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_AUTOJOIN) ? "autojoin " : "",
+ (wlandev->nsdcaps & P80211_NSDCAP_NOSCAN) ? "" : "scan ");
+
+
+ p += sprintf(p, "bssid : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ wlandev->bssid[0], wlandev->bssid[1], wlandev->bssid[2],
+ wlandev->bssid[3], wlandev->bssid[4], wlandev->bssid[5]);
+
+ p += sprintf(p, "Enabled : %s%s\n",
+ (wlandev->shortpreamble) ? "short_preamble " : "",
+ (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) ? "privacy" : "");
+
+
+ exit:
+ DBFEXIT;
+ return (p - page);
+}
+#endif
+
+/*----------------------------------------------------------------
+* p80211netdev_hwremoved
+*
+* Hardware removed notification. This function should be called
+* immediately after an MSD has detected that the underlying hardware
+* has been yanked out from under us. The primary things we need
+* to do are:
+* - Mark the wlandev
+* - Prevent any further traffic from the knetdev i/f
+* - Prevent any further requests from mgmt i/f
+* - If there are any waitq'd mgmt requests or mgmt-frame exchanges,
+* shut them down.
+* - Call the MSD hwremoved function.
+*
+* The remainder of the cleanup will be handled by unregister().
+* Our primary goal here is to prevent as much tickling of the MSD
+* as possible since the MSD is already in a 'wounded' state.
+*
+* TODO: As new features are added, this function should be
+* updated.
+*
+* Arguments:
+* wlandev WLAN network device structure
+* Returns:
+* nothing
+* Side effects:
+*
+* Call context:
+* Usually interrupt.
+----------------------------------------------------------------*/
+void p80211netdev_hwremoved(wlandevice_t *wlandev)
+{
+ DBFENTER;
+ wlandev->hwremoved = 1;
+ if ( wlandev->state == WLAN_DEVICE_OPEN) {
+ p80211netdev_stop_queue(wlandev);
+ }
+
+ netif_device_detach(wlandev->netdev);
+
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* p80211_rx_typedrop
+*
+* Classifies the frame, increments the appropriate counter, and
+* returns 0|1|2 indicating whether the driver should handle, ignore, or
+* drop the frame
+*
+* Arguments:
+* wlandev wlan device structure
+* fc frame control field
+*
+* Returns:
+* zero if the frame should be handled by the driver,
+* one if the frame should be ignored
+* anything else means we drop it.
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc)
+{
+ UINT16 ftype;
+ UINT16 fstype;
+ int drop = 0;
+ /* Classify frame, increment counter */
+ ftype = WLAN_GET_FC_FTYPE(fc);
+ fstype = WLAN_GET_FC_FSTYPE(fc);
+#if 0
+ WLAN_LOG_DEBUG(4,
+ "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype);
+#endif
+ switch ( ftype ) {
+ case WLAN_FTYPE_MGMT:
+ if ((wlandev->netdev->flags & IFF_PROMISC) ||
+ (wlandev->netdev->flags & IFF_ALLMULTI)) {
+ drop = 1;
+ break;
+ }
+ WLAN_LOG_DEBUG(3, "rx'd mgmt:\n");
+ wlandev->rx.mgmt++;
+ switch( fstype ) {
+ case WLAN_FSTYPE_ASSOCREQ:
+ /* printk("assocreq"); */
+ wlandev->rx.assocreq++;
+ break;
+ case WLAN_FSTYPE_ASSOCRESP:
+ /* printk("assocresp"); */
+ wlandev->rx.assocresp++;
+ break;
+ case WLAN_FSTYPE_REASSOCREQ:
+ /* printk("reassocreq"); */
+ wlandev->rx.reassocreq++;
+ break;
+ case WLAN_FSTYPE_REASSOCRESP:
+ /* printk("reassocresp"); */
+ wlandev->rx.reassocresp++;
+ break;
+ case WLAN_FSTYPE_PROBEREQ:
+ /* printk("probereq"); */
+ wlandev->rx.probereq++;
+ break;
+ case WLAN_FSTYPE_PROBERESP:
+ /* printk("proberesp"); */
+ wlandev->rx.proberesp++;
+ break;
+ case WLAN_FSTYPE_BEACON:
+ /* printk("beacon"); */
+ wlandev->rx.beacon++;
+ break;
+ case WLAN_FSTYPE_ATIM:
+ /* printk("atim"); */
+ wlandev->rx.atim++;
+ break;
+ case WLAN_FSTYPE_DISASSOC:
+ /* printk("disassoc"); */
+ wlandev->rx.disassoc++;
+ break;
+ case WLAN_FSTYPE_AUTHEN:
+ /* printk("authen"); */
+ wlandev->rx.authen++;
+ break;
+ case WLAN_FSTYPE_DEAUTHEN:
+ /* printk("deauthen"); */
+ wlandev->rx.deauthen++;
+ break;
+ default:
+ /* printk("unknown"); */
+ wlandev->rx.mgmt_unknown++;
+ break;
+ }
+ /* printk("\n"); */
+ drop = 2;
+ break;
+
+ case WLAN_FTYPE_CTL:
+ if ((wlandev->netdev->flags & IFF_PROMISC) ||
+ (wlandev->netdev->flags & IFF_ALLMULTI)) {
+ drop = 1;
+ break;
+ }
+ WLAN_LOG_DEBUG(3, "rx'd ctl:\n");
+ wlandev->rx.ctl++;
+ switch( fstype ) {
+ case WLAN_FSTYPE_PSPOLL:
+ /* printk("pspoll"); */
+ wlandev->rx.pspoll++;
+ break;
+ case WLAN_FSTYPE_RTS:
+ /* printk("rts"); */
+ wlandev->rx.rts++;
+ break;
+ case WLAN_FSTYPE_CTS:
+ /* printk("cts"); */
+ wlandev->rx.cts++;
+ break;
+ case WLAN_FSTYPE_ACK:
+ /* printk("ack"); */
+ wlandev->rx.ack++;
+ break;
+ case WLAN_FSTYPE_CFEND:
+ /* printk("cfend"); */
+ wlandev->rx.cfend++;
+ break;
+ case WLAN_FSTYPE_CFENDCFACK:
+ /* printk("cfendcfack"); */
+ wlandev->rx.cfendcfack++;
+ break;
+ default:
+ /* printk("unknown"); */
+ wlandev->rx.ctl_unknown++;
+ break;
+ }
+ /* printk("\n"); */
+ drop = 2;
+ break;
+
+ case WLAN_FTYPE_DATA:
+ wlandev->rx.data++;
+ switch( fstype ) {
+ case WLAN_FSTYPE_DATAONLY:
+ wlandev->rx.dataonly++;
+ break;
+ case WLAN_FSTYPE_DATA_CFACK:
+ wlandev->rx.data_cfack++;
+ break;
+ case WLAN_FSTYPE_DATA_CFPOLL:
+ wlandev->rx.data_cfpoll++;
+ break;
+ case WLAN_FSTYPE_DATA_CFACK_CFPOLL:
+ wlandev->rx.data__cfack_cfpoll++;
+ break;
+ case WLAN_FSTYPE_NULL:
+ WLAN_LOG_DEBUG(3, "rx'd data:null\n");
+ wlandev->rx.null++;
+ break;
+ case WLAN_FSTYPE_CFACK:
+ WLAN_LOG_DEBUG(3, "rx'd data:cfack\n");
+ wlandev->rx.cfack++;
+ break;
+ case WLAN_FSTYPE_CFPOLL:
+ WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n");
+ wlandev->rx.cfpoll++;
+ break;
+ case WLAN_FSTYPE_CFACK_CFPOLL:
+ WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n");
+ wlandev->rx.cfack_cfpoll++;
+ break;
+ default:
+ /* printk("unknown"); */
+ wlandev->rx.data_unknown++;
+ break;
+ }
+
+ break;
+ }
+ return drop;
+}
+
+#ifdef CONFIG_HOTPLUG
+/* Notify userspace when a netdevice event occurs,
+ * by running '/sbin/hotplug net' with certain
+ * environment variables set.
+ */
+int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action)
+{
+ char *argv[3], *envp[7], ifname[12 + IFNAMSIZ], action_str[32];
+ char nsdname[32], wlan_wext[32];
+ int i;
+
+ if (wlandev) {
+ sprintf(ifname, "INTERFACE=%s", wlandev->name);
+ sprintf(nsdname, "NSDNAME=%s", wlandev->nsdname);
+ } else {
+ sprintf(ifname, "INTERFACE=null");
+ sprintf(nsdname, "NSDNAME=null");
+ }
+
+ sprintf(wlan_wext, "WLAN_WEXT=%s", wlan_wext_write ? "y" : "");
+ sprintf(action_str, "ACTION=%s", action);
+
+ i = 0;
+ argv[i++] = hotplug_path;
+ argv[i++] = "wlan";
+ argv[i] = NULL;
+
+ i = 0;
+ /* minimal command environment */
+ envp [i++] = "HOME=/";
+ envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp [i++] = ifname;
+ envp [i++] = action_str;
+ envp [i++] = nsdname;
+ envp [i++] = wlan_wext;
+ envp [i] = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62))
+ return call_usermodehelper(argv [0], argv, envp);
+#else
+ return call_usermodehelper(argv [0], argv, envp, 0);
+#endif
+}
+
+#endif
+
+
+void p80211_suspend(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_SUSPEND);
+#endif
+
+ DBFEXIT;
+}
+
+void p80211_resume(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+#ifdef CONFIG_HOTPLUG
+ p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_RESUME);
+#endif
+
+ DBFEXIT;
+}
+
+static void p80211knetdev_tx_timeout( netdevice_t *netdev)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)netdev->priv;
+ DBFENTER;
+
+ if (wlandev->tx_timeout) {
+ wlandev->tx_timeout(wlandev);
+ } else {
+ WLAN_LOG_WARNING("Implement tx_timeout for %s\n",
+ wlandev->nsdname);
+ p80211netdev_wake_queue(wlandev);
+ }
+
+ DBFEXIT;
+}
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
new file mode 100644
index 00000000000..9b2e0cdcb44
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -0,0 +1,336 @@
+/* p80211netdev.h
+*
+* WLAN net device structure and functions
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares the structure type that represents each wlan
+* interface.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _LINUX_P80211NETDEV_H
+#define _LINUX_P80211NETDEV_H
+
+#include <linux/interrupt.h>
+#include <linux/wireless.h>
+
+/*================================================================*/
+/* Constants */
+
+#define WLAN_DEVICE_CLOSED 0
+#define WLAN_DEVICE_OPEN 1
+
+#define WLAN_MACMODE_NONE 0
+#define WLAN_MACMODE_IBSS_STA 1
+#define WLAN_MACMODE_ESS_STA 2
+#define WLAN_MACMODE_ESS_AP 3
+
+/* MSD States */
+#define WLAN_MSD_START -1
+#define WLAN_MSD_DRIVERLOADED 0
+#define WLAN_MSD_HWPRESENT_PENDING 1
+#define WLAN_MSD_HWFAIL 2
+#define WLAN_MSD_HWPRESENT 3
+#define WLAN_MSD_FWLOAD_PENDING 4
+#define WLAN_MSD_FWLOAD 5
+#define WLAN_MSD_RUNNING_PENDING 6
+#define WLAN_MSD_RUNNING 7
+
+#ifndef ETH_P_ECONET
+#define ETH_P_ECONET 0x0018 /* needed for 2.2.x kernels */
+#endif
+
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+
+#ifndef ARPHRD_IEEE80211
+#define ARPHRD_IEEE80211 801 /* kernel 2.4.6 */
+#endif
+
+#ifndef ARPHRD_IEEE80211_PRISM /* kernel 2.4.18 */
+#define ARPHRD_IEEE80211_PRISM 802
+#endif
+
+/*--- NSD Capabilities Flags ------------------------------*/
+#define P80211_NSDCAP_HARDWAREWEP 0x01 /* hardware wep engine */
+#define P80211_NSDCAP_TIEDWEP 0x02 /* can't decouple en/de */
+#define P80211_NSDCAP_NOHOSTWEP 0x04 /* must use hardware wep */
+#define P80211_NSDCAP_PBCC 0x08 /* hardware supports PBCC */
+#define P80211_NSDCAP_SHORT_PREAMBLE 0x10 /* hardware supports */
+#define P80211_NSDCAP_AGILITY 0x20 /* hardware supports */
+#define P80211_NSDCAP_AP_RETRANSMIT 0x40 /* nsd handles retransmits */
+#define P80211_NSDCAP_HWFRAGMENT 0x80 /* nsd handles frag/defrag */
+#define P80211_NSDCAP_AUTOJOIN 0x100 /* nsd does autojoin */
+#define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */
+
+/*================================================================*/
+/* Macros */
+
+/*================================================================*/
+/* Types */
+
+/* Received frame statistics */
+typedef struct p80211_frmrx_t
+{
+ UINT32 mgmt;
+ UINT32 assocreq;
+ UINT32 assocresp;
+ UINT32 reassocreq;
+ UINT32 reassocresp;
+ UINT32 probereq;
+ UINT32 proberesp;
+ UINT32 beacon;
+ UINT32 atim;
+ UINT32 disassoc;
+ UINT32 authen;
+ UINT32 deauthen;
+ UINT32 mgmt_unknown;
+ UINT32 ctl;
+ UINT32 pspoll;
+ UINT32 rts;
+ UINT32 cts;
+ UINT32 ack;
+ UINT32 cfend;
+ UINT32 cfendcfack;
+ UINT32 ctl_unknown;
+ UINT32 data;
+ UINT32 dataonly;
+ UINT32 data_cfack;
+ UINT32 data_cfpoll;
+ UINT32 data__cfack_cfpoll;
+ UINT32 null;
+ UINT32 cfack;
+ UINT32 cfpoll;
+ UINT32 cfack_cfpoll;
+ UINT32 data_unknown;
+ UINT32 decrypt;
+ UINT32 decrypt_err;
+} p80211_frmrx_t;
+
+#ifdef WIRELESS_EXT
+/* called by /proc/net/wireless */
+struct iw_statistics* p80211wext_get_wireless_stats(netdevice_t *dev);
+/* wireless extensions' ioctls */
+int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd);
+#if WIRELESS_EXT > 12
+extern struct iw_handler_def p80211wext_handler_def;
+#endif
+
+int p80211wext_event_associated(struct wlandevice *wlandev, int assoc);
+
+#endif /* wireless extensions */
+
+/* WEP stuff */
+#define NUM_WEPKEYS 4
+#define MAX_KEYLEN 32
+
+#define HOSTWEP_DEFAULTKEY_MASK (BIT1|BIT0)
+#define HOSTWEP_DECRYPT BIT4
+#define HOSTWEP_ENCRYPT BIT5
+#define HOSTWEP_PRIVACYINVOKED BIT6
+#define HOSTWEP_EXCLUDEUNENCRYPTED BIT7
+
+extern int wlan_watchdog;
+extern int wlan_wext_write;
+
+/* WLAN device type */
+typedef struct wlandevice
+{
+ struct wlandevice *next; /* link for list of devices */
+ void *priv; /* private data for MSD */
+
+ /* Subsystem State */
+ char name[WLAN_DEVNAMELEN_MAX]; /* Dev name, from register_wlandev()*/
+ char *nsdname;
+
+ UINT32 state; /* Device I/F state (open/closed) */
+ UINT32 msdstate; /* state of underlying driver */
+ UINT32 hwremoved; /* Has the hw been yanked out? */
+
+ /* Hardware config */
+ UINT irq;
+ UINT iobase;
+ UINT membase;
+ UINT32 nsdcaps; /* NSD Capabilities flags */
+
+ /* Config vars */
+ UINT ethconv;
+
+ /* device methods (init by MSD, used by p80211 */
+ int (*open)(struct wlandevice *wlandev);
+ int (*close)(struct wlandevice *wlandev);
+ void (*reset)(struct wlandevice *wlandev );
+ int (*txframe)(struct wlandevice *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+ int (*mlmerequest)(struct wlandevice *wlandev, p80211msg_t *msg);
+ int (*set_multicast_list)(struct wlandevice *wlandev,
+ netdevice_t *dev);
+ void (*tx_timeout)(struct wlandevice *wlandev);
+
+#ifdef CONFIG_PROC_FS
+ int (*nsd_proc_read)(char *page, char **start, off_t offset, int count, int *eof, void *data);
+#endif
+
+ /* 802.11 State */
+ UINT8 bssid[WLAN_BSSID_LEN];
+ p80211pstr32_t ssid;
+ UINT32 macmode;
+ int linkstatus;
+ int shortpreamble; /* C bool */
+
+ /* WEP State */
+ UINT8 wep_keys[NUM_WEPKEYS][MAX_KEYLEN];
+ UINT8 wep_keylens[NUM_WEPKEYS];
+ int hostwep;
+
+ /* Request/Confirm i/f state (used by p80211) */
+ unsigned long request_pending; /* flag, access atomically */
+
+ /* netlink socket */
+ /* queue for indications waiting for cmd completion */
+ /* Linux netdevice and support */
+ netdevice_t *netdev; /* ptr to linux netdevice */
+ struct net_device_stats linux_stats;
+
+#ifdef CONFIG_PROC_FS
+ /* Procfs support */
+ struct proc_dir_entry *procdir;
+ struct proc_dir_entry *procwlandev;
+#endif
+
+ /* Rx bottom half */
+ struct tasklet_struct rx_bh;
+
+ struct sk_buff_head nsd_rxq;
+
+ /* 802.11 device statistics */
+ struct p80211_frmrx_t rx;
+
+/* compatibility to wireless extensions */
+#ifdef WIRELESS_EXT
+ struct iw_statistics wstats;
+
+ /* jkriegl: iwspy fields */
+ UINT8 spy_number;
+ char spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+
+#endif
+
+} wlandevice_t;
+
+/* WEP stuff */
+int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen);
+int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv);
+int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv);
+
+/*================================================================*/
+/* Externs */
+
+/*================================================================*/
+/* Function Declarations */
+
+void p80211netdev_startup(void);
+void p80211netdev_shutdown(void);
+int wlan_setup(wlandevice_t *wlandev);
+int wlan_unsetup(wlandevice_t *wlandev);
+int register_wlandev(wlandevice_t *wlandev);
+int unregister_wlandev(wlandevice_t *wlandev);
+void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void p80211netdev_hwremoved(wlandevice_t *wlandev);
+void p80211_suspend(wlandevice_t *wlandev);
+void p80211_resume(wlandevice_t *wlandev);
+
+/*================================================================*/
+/* Function Definitions */
+
+static inline void
+p80211netdev_stop_queue(wlandevice_t *wlandev)
+{
+ if ( !wlandev ) return;
+ if ( !wlandev->netdev ) return;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ wlandev->netdev->tbusy = 1;
+ wlandev->netdev->start = 0;
+#else
+ netif_stop_queue(wlandev->netdev);
+#endif
+}
+
+static inline void
+p80211netdev_start_queue(wlandevice_t *wlandev)
+{
+ if ( !wlandev ) return;
+ if ( !wlandev->netdev ) return;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ wlandev->netdev->tbusy = 0;
+ wlandev->netdev->start = 1;
+#else
+ netif_start_queue(wlandev->netdev);
+#endif
+}
+
+static inline void
+p80211netdev_wake_queue(wlandevice_t *wlandev)
+{
+ if ( !wlandev ) return;
+ if ( !wlandev->netdev ) return;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) )
+ wlandev->netdev->tbusy = 0;
+ mark_bh(NET_BH);
+#else
+ netif_wake_queue(wlandev->netdev);
+#endif
+}
+
+#ifdef CONFIG_HOTPLUG
+#define WLAN_HOTPLUG_REGISTER "register"
+#define WLAN_HOTPLUG_REMOVE "remove"
+#define WLAN_HOTPLUG_STARTUP "startup"
+#define WLAN_HOTPLUG_SHUTDOWN "shutdown"
+#define WLAN_HOTPLUG_SUSPEND "suspend"
+#define WLAN_HOTPLUG_RESUME "resume"
+int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action);
+#endif
+
+#endif
diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c
new file mode 100644
index 00000000000..0233abeccc4
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211req.c
@@ -0,0 +1,329 @@
+/* src/p80211/p80211req.c
+*
+* Request/Indication/MacMgmt interface handling functions
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file contains the functions, types, and macros to support the
+* MLME request interface that's implemented via the device ioctls.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <net/sock.h>
+#include <linux/netlink.h>
+
+#include "version.h"
+#include "wlan_compat.h"
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211ioctl.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "p80211req.h"
+
+/*================================================================*/
+/* Local Constants */
+
+/* Maximum amount of time we'll wait for a request to complete */
+#define P80211REQ_MAXTIME 3*HZ /* 3 seconds */
+
+/*================================================================*/
+/* Local Macros */
+
+/*================================================================*/
+/* Local Types */
+
+/*================================================================*/
+/* Local Static Definitions */
+
+/*================================================================*/
+/* Local Function Declarations */
+
+static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg);
+static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mibget_t *mib_msg, int isget);
+
+/*================================================================*/
+/* Function Definitions */
+
+
+/*----------------------------------------------------------------
+* p80211req_dorequest
+*
+* Handles an MLME reqest/confirm message.
+*
+* Arguments:
+* wlandev WLAN device struct
+* msgbuf Buffer containing a request message
+*
+* Returns:
+* 0 on success, an errno otherwise
+*
+* Call context:
+* Potentially blocks the caller, so it's a good idea to
+* not call this function from an interrupt context.
+----------------------------------------------------------------*/
+int p80211req_dorequest( wlandevice_t *wlandev, UINT8 *msgbuf)
+{
+ int result = 0;
+ p80211msg_t *msg = (p80211msg_t*)msgbuf;
+
+ DBFENTER;
+
+ /* Check to make sure the MSD is running */
+ if (
+ !((wlandev->msdstate == WLAN_MSD_HWPRESENT &&
+ msg->msgcode == DIDmsg_lnxreq_ifstate) ||
+ wlandev->msdstate == WLAN_MSD_RUNNING ||
+ wlandev->msdstate == WLAN_MSD_FWLOAD) ) {
+ return -ENODEV;
+ }
+
+ /* Check Permissions */
+ if (!capable(CAP_NET_ADMIN) &&
+ (msg->msgcode != DIDmsg_dot11req_mibget)) {
+ WLAN_LOG_ERROR("%s: only dot11req_mibget allowed for non-root.\n", wlandev->name);
+ return -EPERM;
+ }
+
+ /* Check for busy status */
+ if ( test_and_set_bit(1, &(wlandev->request_pending))) {
+ return -EBUSY;
+ }
+
+ /* Allow p80211 to look at msg and handle if desired. */
+ /* So far, all p80211 msgs are immediate, no waitq/timer necessary */
+ /* This may change. */
+ p80211req_handlemsg(wlandev, msg);
+
+ /* Pass it down to wlandev via wlandev->mlmerequest */
+ if ( wlandev->mlmerequest != NULL )
+ wlandev->mlmerequest(wlandev, msg);
+
+ clear_bit( 1, &(wlandev->request_pending));
+ DBFEXIT;
+ return result; /* if result==0, msg->status still may contain an err */
+}
+
+/*----------------------------------------------------------------
+* p80211req_handlemsg
+*
+* p80211 message handler. Primarily looks for messages that
+* belong to p80211 and then dispatches the appropriate response.
+* TODO: we don't do anything yet. Once the linuxMIB is better
+* defined we'll need a get/set handler.
+*
+* Arguments:
+* wlandev WLAN device struct
+* msg message structure
+*
+* Returns:
+* nothing (any results are set in the status field of the msg)
+*
+* Call context:
+* Process thread
+----------------------------------------------------------------*/
+static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg)
+{
+ DBFENTER;
+
+ switch (msg->msgcode) {
+
+ case DIDmsg_lnxreq_hostwep: {
+ p80211msg_lnxreq_hostwep_t *req = (p80211msg_lnxreq_hostwep_t*) msg;
+ wlandev->hostwep &= ~(HOSTWEP_DECRYPT|HOSTWEP_ENCRYPT);
+ if (req->decrypt.data == P80211ENUM_truth_true)
+ wlandev->hostwep |= HOSTWEP_DECRYPT;
+ if (req->encrypt.data == P80211ENUM_truth_true)
+ wlandev->hostwep |= HOSTWEP_ENCRYPT;
+
+ break;
+ }
+ case DIDmsg_dot11req_mibget:
+ case DIDmsg_dot11req_mibset: {
+ int isget = (msg->msgcode == DIDmsg_dot11req_mibget);
+ p80211msg_dot11req_mibget_t *mib_msg = (p80211msg_dot11req_mibget_t *) msg;
+ p80211req_mibset_mibget (wlandev, mib_msg, isget);
+ }
+ default:
+ // XXX do nothing!
+ ;
+ } /* switch msg->msgcode */
+
+ DBFEXIT;
+
+ return;
+}
+
+static int p80211req_mibset_mibget(wlandevice_t *wlandev,
+ p80211msg_dot11req_mibget_t *mib_msg,
+ int isget)
+{
+ p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) mibitem->data;
+ UINT8 *key = mibitem->data + sizeof(p80211pstrd_t);
+
+ DBFENTER;
+
+ switch (mibitem->did) {
+ case DIDmib_dot11smt_p80211Table_p80211_ifstate: {
+ UINT32 *data = (UINT32 *) mibitem->data;
+ if (isget)
+ switch (wlandev->msdstate) {
+ case WLAN_MSD_HWPRESENT:
+ *data = P80211ENUM_ifstate_disable;
+ break;
+ case WLAN_MSD_FWLOAD:
+ *data = P80211ENUM_ifstate_fwload;
+ break;
+ case WLAN_MSD_RUNNING:
+ *data = P80211ENUM_ifstate_enable;
+ break;
+ default:
+ *data = P80211ENUM_ifstate_enable;
+ }
+ break;
+ }
+ case DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled: {
+ UINT32 *data = (UINT32 *) mibitem->data;
+
+ if (isget)
+ *data = wlandev->shortpreamble;
+ else
+ wlandev->shortpreamble = *data;
+ break;
+ }
+ case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: {
+ if (!isget)
+ wep_change_key(wlandev, 0, key, pstr->len);
+ break;
+ }
+ case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: {
+ if (!isget)
+ wep_change_key(wlandev, 1, key, pstr->len);
+ break;
+ }
+ case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: {
+ if (!isget)
+ wep_change_key(wlandev, 2, key, pstr->len);
+ break;
+ }
+ case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: {
+ if (!isget)
+ wep_change_key(wlandev, 3, key, pstr->len);
+ break;
+ }
+ case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID: {
+ UINT32 *data = (UINT32 *) mibitem->data;
+
+ if (isget) {
+ *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
+ } else {
+ wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK);
+
+ wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK);
+ }
+ break;
+ }
+ case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked: {
+ UINT32 *data = (UINT32 *) mibitem->data;
+
+ if (isget) {
+ if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
+ *data = P80211ENUM_truth_true;
+ else
+ *data = P80211ENUM_truth_false;
+ } else {
+ wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED);
+ if (*data == P80211ENUM_truth_true)
+ wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED;
+ }
+ break;
+ }
+ case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted: {
+ UINT32 *data = (UINT32 *) mibitem->data;
+
+ if (isget) {
+ if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
+ *data = P80211ENUM_truth_true;
+ else
+ *data = P80211ENUM_truth_false;
+ } else {
+ wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED);
+ if (*data == P80211ENUM_truth_true)
+ wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED;
+ }
+ break;
+ }
+ default:
+ // XXXX do nothing!
+ ;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h
new file mode 100644
index 00000000000..54abdceedc5
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211req.h
@@ -0,0 +1,68 @@
+/* p80211req.h
+*
+* Request handling functions
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _LINUX_P80211REQ_H
+#define _LINUX_P80211REQ_H
+
+/*================================================================*/
+/* Constants */
+
+/*================================================================*/
+/* Macros */
+
+/*================================================================*/
+/* Types */
+
+/*================================================================*/
+/* Externs */
+
+/*================================================================*/
+/* Function Declarations */
+
+int p80211req_dorequest(wlandevice_t *wlandev, UINT8 *msgbuf);
+
+#endif
diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h
new file mode 100644
index 00000000000..811b0ce39bf
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211types.h
@@ -0,0 +1,675 @@
+/* p80211types.h
+*
+* Macros, constants, types, and funcs for p80211 data types
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file declares some of the constants and types used in various
+* parts of the linux-wlan system.
+*
+* Notes:
+* - Constant values are always in HOST byte order.
+*
+* All functions and statics declared here are implemented in p80211types.c
+* --------------------------------------------------------------------
+*/
+
+#ifndef _P80211TYPES_H
+#define _P80211TYPES_H
+
+/*================================================================*/
+/* System Includes */
+/*================================================================*/
+
+/*================================================================*/
+/* Project Includes */
+/*================================================================*/
+
+#ifndef _WLAN_COMPAT_H
+#include "wlan_compat.h"
+#endif
+
+/*================================================================*/
+/* Constants */
+/*================================================================*/
+
+/*----------------------------------------------------------------*/
+/* p80211 data type codes used for MIB items and message */
+/* arguments. The various metadata structures provide additional */
+/* information about these types. */
+
+#define P80211_TYPE_OCTETSTR 1 /* pascal array of bytes */
+#define P80211_TYPE_DISPLAYSTR 2 /* pascal array of bytes containing ascii */
+#define P80211_TYPE_INT 4 /* UINT32 min and max limited by 32 bits */
+#define P80211_TYPE_ENUMINT 5 /* UINT32 holding a numeric
+ code that can be mapped
+ to a textual name */
+#define P80211_TYPE_UNKDATA 6 /* Data item containing an
+ unknown data type */
+#define P80211_TYPE_INTARRAY 7 /* Array of 32-bit integers. */
+#define P80211_TYPE_BITARRAY 8 /* Array of bits. */
+#define P80211_TYPE_MACARRAY 9 /* Array of MAC addresses. */
+
+/*----------------------------------------------------------------*/
+/* The following constants are indexes into the Mib Category List */
+/* and the Message Category List */
+
+/* Mib Category List */
+#define P80211_MIB_CAT_DOT11SMT 1
+#define P80211_MIB_CAT_DOT11MAC 2
+#define P80211_MIB_CAT_DOT11PHY 3
+
+#define P80211SEC_DOT11SMT P80211_MIB_CAT_DOT11SMT
+#define P80211SEC_DOT11MAC P80211_MIB_CAT_DOT11MAC
+#define P80211SEC_DOT11PHY P80211_MIB_CAT_DOT11PHY
+
+/* Message Category List */
+#define P80211_MSG_CAT_DOT11REQ 1
+#define P80211_MSG_CAT_DOT11IND 2
+/* #define P80211_MSG_CAT_DOT11CFM 3 (doesn't exist at this time) */
+
+#define P80211SEC_DOT11REQ P80211_MSG_CAT_DOT11REQ
+#define P80211SEC_DOT11IND P80211_MSG_CAT_DOT11IND
+/* #define P80211SEC_DOT11CFM P80211_MSG_CAT_DOT11CFM (doesn't exist at this time */
+
+
+
+/*----------------------------------------------------------------*/
+/* p80211 DID field codes that represent access type and */
+/* is_table status. */
+
+#define P80211DID_ACCESS_READ 0x10000000
+#define P80211DID_ACCESS_WRITE 0x08000000
+#define P80211DID_WRITEONLY 0x00000001
+#define P80211DID_READONLY 0x00000002
+#define P80211DID_READWRITE 0x00000003
+#define P80211DID_ISTABLE_FALSE 0
+#define P80211DID_ISTABLE_TRUE 1
+
+/*----------------------------------------------------------------*/
+/* p80211 enumeration constants. The value to text mappings for */
+/* these is in p80211types.c. These defines were generated */
+/* from the mappings. */
+
+/* error codes for lookups */
+#define P80211ENUM_BAD 0xffffffffUL
+#define P80211ENUM_BADSTR "P80211ENUM_BAD"
+
+#define P80211ENUM_truth_false 0
+#define P80211ENUM_truth_true 1
+#define P80211ENUM_ifstate_disable 0
+#define P80211ENUM_ifstate_fwload 1
+#define P80211ENUM_ifstate_enable 2
+#define P80211ENUM_powermgmt_active 1
+#define P80211ENUM_powermgmt_powersave 2
+#define P80211ENUM_bsstype_infrastructure 1
+#define P80211ENUM_bsstype_independent 2
+#define P80211ENUM_bsstype_any 3
+#define P80211ENUM_authalg_opensystem 1
+#define P80211ENUM_authalg_sharedkey 2
+#define P80211ENUM_phytype_fhss 1
+#define P80211ENUM_phytype_dsss 2
+#define P80211ENUM_phytype_irbaseband 3
+#define P80211ENUM_temptype_commercial 1
+#define P80211ENUM_temptype_industrial 2
+#define P80211ENUM_regdomain_fcc 16
+#define P80211ENUM_regdomain_doc 32
+#define P80211ENUM_regdomain_etsi 48
+#define P80211ENUM_regdomain_spain 49
+#define P80211ENUM_regdomain_france 50
+#define P80211ENUM_regdomain_mkk 64
+#define P80211ENUM_ccamode_edonly 1
+#define P80211ENUM_ccamode_csonly 2
+#define P80211ENUM_ccamode_edandcs 4
+#define P80211ENUM_ccamode_cswithtimer 8
+#define P80211ENUM_ccamode_hrcsanded 16
+#define P80211ENUM_diversity_fixedlist 1
+#define P80211ENUM_diversity_notsupported 2
+#define P80211ENUM_diversity_dynamic 3
+#define P80211ENUM_scantype_active 1
+#define P80211ENUM_scantype_passive 2
+#define P80211ENUM_scantype_both 3
+#define P80211ENUM_resultcode_success 1
+#define P80211ENUM_resultcode_invalid_parameters 2
+#define P80211ENUM_resultcode_not_supported 3
+#define P80211ENUM_resultcode_timeout 4
+#define P80211ENUM_resultcode_too_many_req 5
+#define P80211ENUM_resultcode_refused 6
+#define P80211ENUM_resultcode_bss_already 7
+#define P80211ENUM_resultcode_invalid_access 8
+#define P80211ENUM_resultcode_invalid_mibattribute 9
+#define P80211ENUM_resultcode_cant_set_readonly_mib 10
+#define P80211ENUM_resultcode_implementation_failure 11
+#define P80211ENUM_resultcode_cant_get_writeonly_mib 12
+#define P80211ENUM_reason_unspec_reason 1
+#define P80211ENUM_reason_auth_not_valid 2
+#define P80211ENUM_reason_deauth_lv_ss 3
+#define P80211ENUM_reason_inactivity 4
+#define P80211ENUM_reason_ap_overload 5
+#define P80211ENUM_reason_class23_err 6
+#define P80211ENUM_reason_class3_err 7
+#define P80211ENUM_reason_disas_lv_ss 8
+#define P80211ENUM_reason_asoc_not_auth 9
+#define P80211ENUM_status_successful 0
+#define P80211ENUM_status_unspec_failure 1
+#define P80211ENUM_status_unsup_cap 10
+#define P80211ENUM_status_reasoc_no_asoc 11
+#define P80211ENUM_status_fail_other 12
+#define P80211ENUM_status_unspt_alg 13
+#define P80211ENUM_status_auth_seq_fail 14
+#define P80211ENUM_status_chlng_fail 15
+#define P80211ENUM_status_auth_timeout 16
+#define P80211ENUM_status_ap_full 17
+#define P80211ENUM_status_unsup_rate 18
+#define P80211ENUM_status_unsup_shortpreamble 19
+#define P80211ENUM_status_unsup_pbcc 20
+#define P80211ENUM_status_unsup_agility 21
+#define P80211ENUM_msgitem_status_data_ok 0
+#define P80211ENUM_msgitem_status_no_value 1
+#define P80211ENUM_msgitem_status_invalid_itemname 2
+#define P80211ENUM_msgitem_status_invalid_itemdata 3
+#define P80211ENUM_msgitem_status_missing_itemdata 4
+#define P80211ENUM_msgitem_status_incomplete_itemdata 5
+#define P80211ENUM_msgitem_status_invalid_msg_did 6
+#define P80211ENUM_msgitem_status_invalid_mib_did 7
+#define P80211ENUM_msgitem_status_missing_conv_func 8
+#define P80211ENUM_msgitem_status_string_too_long 9
+#define P80211ENUM_msgitem_status_data_out_of_range 10
+#define P80211ENUM_msgitem_status_string_too_short 11
+#define P80211ENUM_msgitem_status_missing_valid_func 12
+#define P80211ENUM_msgitem_status_unknown 13
+#define P80211ENUM_msgitem_status_invalid_did 14
+#define P80211ENUM_msgitem_status_missing_print_func 15
+
+#define P80211ENUM_lnxroam_reason_unknown 0
+#define P80211ENUM_lnxroam_reason_beacon 1
+#define P80211ENUM_lnxroam_reason_signal 2
+#define P80211ENUM_lnxroam_reason_txretry 3
+#define P80211ENUM_lnxroam_reason_notjoined 4
+
+#define P80211ENUM_p2preamble_long 0
+#define P80211ENUM_p2preamble_short 2
+#define P80211ENUM_p2preamble_mixed 3
+
+/*----------------------------------------------------------------*/
+/* p80211 max length constants for the different pascal strings. */
+
+#define MAXLEN_PSTR6 (6) /* pascal array of 6 bytes */
+#define MAXLEN_PSTR14 (14) /* pascal array of 14 bytes */
+#define MAXLEN_PSTR32 (32) /* pascal array of 32 bytes */
+#define MAXLEN_PSTR255 (255) /* pascal array of 255 bytes */
+#define MAXLEN_MIBATTRIBUTE (392) /* maximum mibattribute */
+ /* where the size of the DATA itself */
+ /* is a DID-LEN-DATA triple */
+ /* with a max size of 4+4+384 */
+
+#define P80211_SET_INT(item, value) do { \
+ (item).data = (value); \
+ (item).status = P80211ENUM_msgitem_status_data_ok; \
+ } while(0)
+/*----------------------------------------------------------------*/
+/* string constants */
+
+#define NOT_SET "NOT_SET"
+#define NOT_SUPPORTED "NOT_SUPPORTED"
+#define UNKNOWN_DATA "UNKNOWN_DATA"
+
+
+/*--------------------------------------------------------------------*/
+/* Metadata flags */
+
+/* MSM: Do these belong in p80211meta.h? I'm not sure. */
+
+#define ISREQUIRED (0x80000000UL)
+#define ISREQUEST (0x40000000UL)
+#define ISCONFIRM (0x20000000UL)
+
+
+/*================================================================*/
+/* Macros */
+
+/*--------------------------------------------------------------------*/
+/* The following macros are used to manipulate the 'flags' field in */
+/* the metadata. These are only used when the metadata is for */
+/* command arguments to determine if the data item is required, and */
+/* whether the metadata item is for a request command, confirm */
+/* command or both. */
+/*--------------------------------------------------------------------*/
+/* MSM: Do these belong in p80211meta.h? I'm not sure */
+
+#define P80211ITEM_SETFLAGS(q, r, c) ( q | r | c )
+
+#define P80211ITEM_ISREQUIRED(flags) (((UINT32)(flags & ISREQUIRED)) >> 31 )
+#define P80211ITEM_ISREQUEST(flags) (((UINT32)(flags & ISREQUEST)) >> 30 )
+#define P80211ITEM_ISCONFIRM(flags) (((UINT32)(flags & ISCONFIRM)) >> 29 )
+
+/*----------------------------------------------------------------*/
+/* The following macro creates a name for an enum */
+
+#define MKENUMNAME(name) p80211enum_ ## name
+
+/*----------------------------------------------------------------
+* The following constants and macros are used to construct and
+* deconstruct the Data ID codes. The coding is as follows:
+*
+* ...rwtnnnnnnnniiiiiiggggggssssss s - Section
+* g - Group
+* i - Item
+* n - Index
+* t - Table flag
+* w - Write flag
+* r - Read flag
+* . - Unused
+*/
+
+#define P80211DID_INVALID 0xffffffffUL
+#define P80211DID_VALID 0x00000000UL
+
+#define P80211DID_LSB_SECTION (0)
+#define P80211DID_LSB_GROUP (6)
+#define P80211DID_LSB_ITEM (12)
+#define P80211DID_LSB_INDEX (18)
+#define P80211DID_LSB_ISTABLE (26)
+#define P80211DID_LSB_ACCESS (27)
+
+#define P80211DID_MASK_SECTION (0x0000003fUL)
+#define P80211DID_MASK_GROUP (0x0000003fUL)
+#define P80211DID_MASK_ITEM (0x0000003fUL)
+#define P80211DID_MASK_INDEX (0x000000ffUL)
+#define P80211DID_MASK_ISTABLE (0x00000001UL)
+#define P80211DID_MASK_ACCESS (0x00000003UL)
+
+
+#define P80211DID_MK(a,m,l) ((((UINT32)(a)) & (m)) << (l))
+
+#define P80211DID_MKSECTION(a) P80211DID_MK(a, \
+ P80211DID_MASK_SECTION, \
+ P80211DID_LSB_SECTION )
+#define P80211DID_MKGROUP(a) P80211DID_MK(a, \
+ P80211DID_MASK_GROUP, \
+ P80211DID_LSB_GROUP )
+#define P80211DID_MKITEM(a) P80211DID_MK(a, \
+ P80211DID_MASK_ITEM, \
+ P80211DID_LSB_ITEM )
+#define P80211DID_MKINDEX(a) P80211DID_MK(a, \
+ P80211DID_MASK_INDEX, \
+ P80211DID_LSB_INDEX )
+#define P80211DID_MKISTABLE(a) P80211DID_MK(a, \
+ P80211DID_MASK_ISTABLE, \
+ P80211DID_LSB_ISTABLE )
+
+
+#define P80211DID_MKID(s,g,i,n,t,a) (P80211DID_MKSECTION(s) | \
+ P80211DID_MKGROUP(g) | \
+ P80211DID_MKITEM(i) | \
+ P80211DID_MKINDEX(n) | \
+ P80211DID_MKISTABLE(t) | \
+ (a) )
+
+
+#define P80211DID_GET(a,m,l) ((((UINT32)(a)) >> (l)) & (m))
+
+#define P80211DID_SECTION(a) P80211DID_GET(a, \
+ P80211DID_MASK_SECTION, \
+ P80211DID_LSB_SECTION)
+#define P80211DID_GROUP(a) P80211DID_GET(a, \
+ P80211DID_MASK_GROUP, \
+ P80211DID_LSB_GROUP)
+#define P80211DID_ITEM(a) P80211DID_GET(a, \
+ P80211DID_MASK_ITEM, \
+ P80211DID_LSB_ITEM)
+#define P80211DID_INDEX(a) P80211DID_GET(a, \
+ P80211DID_MASK_INDEX, \
+ P80211DID_LSB_INDEX)
+#define P80211DID_ISTABLE(a) P80211DID_GET(a, \
+ P80211DID_MASK_ISTABLE, \
+ P80211DID_LSB_ISTABLE)
+#define P80211DID_ACCESS(a) P80211DID_GET(a, \
+ P80211DID_MASK_ACCESS, \
+ P80211DID_LSB_ACCESS)
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* The following structure types are used for the represenation */
+/* of ENUMINT type metadata. */
+
+typedef struct p80211enumpair
+{
+ UINT32 val;
+ char *name;
+} p80211enumpair_t;
+
+typedef struct p80211enum
+{
+ INT nitems;
+ p80211enumpair_t *list;
+} p80211enum_t;
+
+/*----------------------------------------------------------------*/
+/* The following structure types are used to store data items in */
+/* messages. */
+
+/* Template pascal string */
+typedef struct p80211pstr
+{
+ UINT8 len;
+} __WLAN_ATTRIB_PACK__ p80211pstr_t;
+
+typedef struct p80211pstrd
+{
+ UINT8 len;
+ UINT8 data[0];
+} __WLAN_ATTRIB_PACK__ p80211pstrd_t;
+
+/* Maximum pascal string */
+typedef struct p80211pstr255
+{
+ UINT8 len;
+ UINT8 data[MAXLEN_PSTR255];
+} __WLAN_ATTRIB_PACK__ p80211pstr255_t;
+
+/* pascal string for macaddress and bssid */
+typedef struct p80211pstr6
+{
+ UINT8 len;
+ UINT8 data[MAXLEN_PSTR6];
+} __WLAN_ATTRIB_PACK__ p80211pstr6_t;
+
+/* pascal string for channel list */
+typedef struct p80211pstr14
+{
+ UINT8 len;
+ UINT8 data[MAXLEN_PSTR14];
+} __WLAN_ATTRIB_PACK__ p80211pstr14_t;
+
+/* pascal string for ssid */
+typedef struct p80211pstr32
+{
+ UINT8 len;
+ UINT8 data[MAXLEN_PSTR32];
+} __WLAN_ATTRIB_PACK__ p80211pstr32_t;
+
+/* MAC address array */
+typedef struct p80211macarray
+{
+ UINT32 cnt;
+ UINT8 data[1][MAXLEN_PSTR6];
+} __WLAN_ATTRIB_PACK__ p80211macarray_t;
+
+/* prototype template */
+typedef struct p80211item
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+} __WLAN_ATTRIB_PACK__ p80211item_t;
+
+/* prototype template w/ data item */
+typedef struct p80211itemd
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT8 data[0];
+} __WLAN_ATTRIB_PACK__ p80211itemd_t;
+
+/* message data item for INT, BOUNDEDINT, ENUMINT */
+typedef struct p80211item_uint32
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT32 data;
+} __WLAN_ATTRIB_PACK__ p80211item_uint32_t;
+
+/* message data item for OCTETSTR, DISPLAYSTR */
+typedef struct p80211item_pstr6
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ p80211pstr6_t data;
+} __WLAN_ATTRIB_PACK__ p80211item_pstr6_t;
+
+/* message data item for OCTETSTR, DISPLAYSTR */
+typedef struct p80211item_pstr14
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ p80211pstr14_t data;
+} __WLAN_ATTRIB_PACK__ p80211item_pstr14_t;
+
+/* message data item for OCTETSTR, DISPLAYSTR */
+typedef struct p80211item_pstr32
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ p80211pstr32_t data;
+} __WLAN_ATTRIB_PACK__ p80211item_pstr32_t;
+
+/* message data item for OCTETSTR, DISPLAYSTR */
+typedef struct p80211item_pstr255
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ p80211pstr255_t data;
+} __WLAN_ATTRIB_PACK__ p80211item_pstr255_t;
+
+/* message data item for UNK 392, namely mib items */
+typedef struct p80211item_unk392
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT8 data[MAXLEN_MIBATTRIBUTE];
+} __WLAN_ATTRIB_PACK__ p80211item_unk392_t;
+
+/* message data item for UNK 1025, namely p2 pdas */
+typedef struct p80211item_unk1024
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT8 data[1024];
+} __WLAN_ATTRIB_PACK__ p80211item_unk1024_t;
+
+/* message data item for UNK 4096, namely p2 download chunks */
+typedef struct p80211item_unk4096
+{
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT8 data[4096];
+} __WLAN_ATTRIB_PACK__ p80211item_unk4096_t;
+
+struct catlistitem;
+
+/*----------------------------------------------------------------*/
+/* The following structure type is used to represent all of the */
+/* metadata items. Some components may choose to use more, */
+/* less or different metadata items. */
+
+typedef void (*p80211_totext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf);
+typedef void (*p80211_fromtext_t)( struct catlistitem *, UINT32 did, UINT8* itembuf, char *textbuf);
+typedef UINT32 (*p80211_valid_t)( struct catlistitem *, UINT32 did, UINT8* itembuf);
+
+
+/*================================================================*/
+/* Extern Declarations */
+
+/*----------------------------------------------------------------*/
+/* Enumeration Lists */
+/* The following are the external declarations */
+/* for all enumerations */
+
+extern p80211enum_t MKENUMNAME(truth);
+extern p80211enum_t MKENUMNAME(ifstate);
+extern p80211enum_t MKENUMNAME(powermgmt);
+extern p80211enum_t MKENUMNAME(bsstype);
+extern p80211enum_t MKENUMNAME(authalg);
+extern p80211enum_t MKENUMNAME(phytype);
+extern p80211enum_t MKENUMNAME(temptype);
+extern p80211enum_t MKENUMNAME(regdomain);
+extern p80211enum_t MKENUMNAME(ccamode);
+extern p80211enum_t MKENUMNAME(diversity);
+extern p80211enum_t MKENUMNAME(scantype);
+extern p80211enum_t MKENUMNAME(resultcode);
+extern p80211enum_t MKENUMNAME(reason);
+extern p80211enum_t MKENUMNAME(status);
+extern p80211enum_t MKENUMNAME(msgcode);
+extern p80211enum_t MKENUMNAME(msgitem_status);
+
+extern p80211enum_t MKENUMNAME(lnxroam_reason);
+
+extern p80211enum_t MKENUMNAME(p2preamble);
+
+/*================================================================*/
+/* Function Declarations */
+
+/*----------------------------------------------------------------*/
+/* The following declare some utility functions for use with the */
+/* p80211enum_t type. */
+
+UINT32 p80211enum_text2int(p80211enum_t *ep, char *text);
+UINT32 p80211enum_int2text(p80211enum_t *ep, UINT32 val, char *text);
+void p80211_error2text(int err_code, char *err_str);
+
+/*----------------------------------------------------------------*/
+/* The following declare some utility functions for use with the */
+/* p80211item_t and p80211meta_t types. */
+
+/*----------------------------------------------------------------*/
+/* The following declare functions that perform validation and */
+/* text to binary conversions based on the metadata for interface */
+/* and MIB data items. */
+/*----------------------------------------------------------------*/
+
+/*-- DISPLAYSTR ------------------------------------------------------*/
+/* pstr ==> cstr */
+void p80211_totext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* cstr ==> pstr */
+void p80211_fromtext_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of a displaystr binary value */
+UINT32 p80211_isvalid_displaystr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- OCTETSTR --------------------------------------------------------*/
+/* pstr ==> "xx:xx:...." */
+void p80211_totext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* "xx:xx:...." ==> pstr */
+void p80211_fromtext_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of an octetstr binary value */
+UINT32 p80211_isvalid_octetstr( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- INT -------------------------------------------------------------*/
+/* UINT32 ==> %d */
+void p80211_totext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* %d ==> UINT32 */
+void p80211_fromtext_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of an int's binary value (always successful) */
+UINT32 p80211_isvalid_int( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- ENUMINT ---------------------------------------------------------*/
+/* UINT32 ==> <valuename> */
+void p80211_totext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* <valuename> ==> UINT32 */
+void p80211_fromtext_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of an enum's binary value */
+UINT32 p80211_isvalid_enumint( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- INTARRAY --------------------------------------------------------*/
+/* UINT32[] => %d,%d,%d,... */
+void p80211_totext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* %d,%d,%d,... ==> UINT32[] */
+void p80211_fromtext_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of an integer array's value */
+UINT32 p80211_isvalid_intarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- BITARRAY --------------------------------------------------------*/
+/* UINT32 ==> %d,%d,%d,... */
+void p80211_totext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* %d,%d,%d,... ==> UINT32 */
+void p80211_fromtext_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of a bit array's value */
+UINT32 p80211_isvalid_bitarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- MACARRAY --------------------------------------------------------*/
+void p80211_totext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+void p80211_fromtext_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of a MAC address array's value */
+UINT32 p80211_isvalid_macarray( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+/*-- MIBATTRIUBTE ------------------------------------------------------*/
+/* <mibvalue> ==> <textual representation identified in MIB metadata> */
+void p80211_totext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+void p80211_totext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+
+/* <textual representation identified in MIB metadata> ==> <mibvalue> */
+void p80211_fromtext_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+void p80211_fromtext_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf, char *textbuf );
+
+/* function that checks validity of a mibitem's binary value */
+UINT32 p80211_isvalid_getmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+UINT32 p80211_isvalid_setmibattribute( struct catlistitem *metalist, UINT32 did, UINT8 *itembuf );
+
+#endif /* _P80211TYPES_H */
+
diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c
new file mode 100644
index 00000000000..53fe2985971
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211wep.c
@@ -0,0 +1,317 @@
+/* src/p80211/p80211wep.c
+*
+* WEP encode/decode for P80211.
+*
+* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+
+
+#include <linux/version.h>
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include "version.h"
+#include "wlan_compat.h"
+
+// #define WEP_DEBUG
+
+/*================================================================*/
+/* Project Includes */
+
+#include "version.h"
+#include "p80211hdr.h"
+#include "p80211types.h"
+#include "p80211msg.h"
+#include "p80211conv.h"
+#include "p80211netdev.h"
+
+/*================================================================*/
+/* Local Constants */
+
+#define SSWAP(a,b) {UINT8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
+#define WEP_KEY(x) (((x) & 0xC0) >> 6)
+
+/*================================================================*/
+/* Local Macros */
+
+
+/*================================================================*/
+/* Local Types */
+
+
+/*================================================================*/
+/* Local Static Definitions */
+
+static const UINT32 wep_crc32_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+/*================================================================*/
+/* Local Function Declarations */
+
+/*================================================================*/
+/* Function Definitions */
+
+/* keylen in bytes! */
+
+int wep_change_key(wlandevice_t *wlandev, int keynum, UINT8* key, int keylen)
+{
+ if (keylen < 0) return -1;
+ if (keylen >= MAX_KEYLEN) return -1;
+ if (key == NULL) return -1;
+ if (keynum < 0) return -1;
+ if (keynum >= NUM_WEPKEYS) return -1;
+
+
+#ifdef WEP_DEBUG
+ printk(KERN_DEBUG "WEP key %d len %d = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
+#endif
+
+ wlandev->wep_keylens[keynum] = keylen;
+ memcpy(wlandev->wep_keys[keynum], key, keylen);
+
+ return 0;
+}
+
+/*
+ 4-byte IV at start of buffer, 4-byte ICV at end of buffer.
+ if successful, buf start is payload begin, length -= 8;
+ */
+int wep_decrypt(wlandevice_t *wlandev, UINT8 *buf, UINT32 len, int key_override, UINT8 *iv, UINT8 *icv)
+{
+ UINT32 i, j, k, crc, keylen;
+ UINT8 s[256], key[64], c_crc[4];
+ UINT8 keyidx;
+
+ /* Needs to be at least 8 bytes of payload */
+ if (len <= 0) return -1;
+
+ /* initialize the first bytes of the key from the IV */
+ key[0] = iv[0];
+ key[1] = iv[1];
+ key[2] = iv[2];
+ keyidx = WEP_KEY(iv[3]);
+
+ if (key_override >= 0)
+ keyidx = key_override;
+
+ if (keyidx >= NUM_WEPKEYS) return -2;
+
+ keylen = wlandev->wep_keylens[keyidx];
+
+ if (keylen == 0) return -3;
+
+ /* copy the rest of the key over from the designated key */
+ memcpy(key+3, wlandev->wep_keys[keyidx], keylen);
+
+ keylen+=3; /* add in IV bytes */
+
+#ifdef WEP_DEBUG
+ printk(KERN_DEBUG "D %d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]);
+#endif
+
+ /* set up the RC4 state */
+ for (i = 0; i < 256; i++)
+ s[i] = i;
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ j = (j + s[i] + key[i % keylen]) & 0xff;
+ SSWAP(i,j);
+ }
+
+ /* Apply the RC4 to the data, update the CRC32 */
+ crc = ~0;
+ i = j = 0;
+ for (k = 0; k < len; k++) {
+ i = (i+1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+ buf[k] ^= s[(s[i] + s[j]) & 0xff];
+ crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
+ }
+ crc = ~crc;
+
+ /* now let's check the crc */
+ c_crc[0] = crc;
+ c_crc[1] = crc >> 8;
+ c_crc[2] = crc >> 16;
+ c_crc[3] = crc >> 24;
+
+ for (k = 0; k < 4; k++) {
+ i = (i + 1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+ if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k])
+ return -(4 | (k << 4)) ; /* ICV mismatch */
+ }
+
+ return 0;
+}
+
+/* encrypts in-place. */
+int wep_encrypt(wlandevice_t *wlandev, UINT8 *buf, UINT8 *dst, UINT32 len, int keynum, UINT8 *iv, UINT8 *icv)
+{
+ UINT32 i, j, k, crc, keylen;
+ UINT8 s[256], key[64];
+
+ /* no point in WEPping an empty frame */
+ if (len <= 0) return -1;
+
+ /* we need to have a real key.. */
+ if (keynum >= NUM_WEPKEYS) return -2;
+ keylen = wlandev->wep_keylens[keynum];
+ if (keylen <= 0) return -3;
+
+ /* use a random IV. And skip known weak ones. */
+ get_random_bytes(iv, 3);
+ while ((iv[1] == 0xff) && (iv[0] >= 3) && (iv[0] < keylen))
+ get_random_bytes(iv, 3);
+
+ iv[3] = (keynum & 0x03) << 6;
+
+ key[0] = iv[0];
+ key[1] = iv[1];
+ key[2] = iv[2];
+
+ /* copy the rest of the key over from the designated key */
+ memcpy(key+3, wlandev->wep_keys[keynum], keylen);
+
+ keylen+=3; /* add in IV bytes */
+
+#ifdef WEP_DEBUG
+ printk(KERN_DEBUG "E %d (%d/%d %d) %02x %02x %02x %02x:%02x:%02x:%02x:%02x\n", len, iv[3], keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
+#endif
+
+ /* set up the RC4 state */
+ for (i = 0; i < 256; i++)
+ s[i] = i;
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ j = (j + s[i] + key[i % keylen]) & 0xff;
+ SSWAP(i,j);
+ }
+
+ /* Update CRC32 then apply RC4 to the data */
+ crc = ~0;
+ i = j = 0;
+ for (k = 0; k < len; k++) {
+ crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8);
+ i = (i+1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+ dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff];
+ }
+ crc = ~crc;
+
+ /* now let's encrypt the crc */
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ for (k = 0; k < 4; k++) {
+ i = (i + 1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+ icv[k] ^= s[(s[i] + s[j]) & 0xff];
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c
new file mode 100644
index 00000000000..906ba439237
--- /dev/null
+++ b/drivers/staging/wlan-ng/p80211wext.c
@@ -0,0 +1,2048 @@
+/* src/p80211/p80211wext.c
+*
+* Glue code to make linux-wlan-ng a happy wireless extension camper.
+*
+* original author: Reyk Floeter <reyk@synack.de>
+* Completely re-written by Solomon Peachy <solomon@linux-wlan.com>
+*
+* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+
+
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+#include <linux/if_arp.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+/*================================================================*/
+/* Project Includes */
+
+#include "version.h"
+#include "wlan_compat.h"
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211conv.h"
+#include "p80211mgmt.h"
+#include "p80211msg.h"
+#include "p80211metastruct.h"
+#include "p80211metadef.h"
+#include "p80211netdev.h"
+#include "p80211ioctl.h"
+#include "p80211req.h"
+
+static int p80211wext_giwrate(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra);
+static int p80211wext_giwessid(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid);
+/* compatibility to wireless extensions */
+#ifdef WIRELESS_EXT
+
+static UINT8 p80211_mhz_to_channel(UINT16 mhz)
+{
+ if (mhz >= 5000) {
+ return ((mhz - 5000) / 5);
+ }
+
+ if (mhz == 2482)
+ return 14;
+
+ if (mhz >= 2407) {
+ return ((mhz - 2407) / 5);
+ }
+
+ return 0;
+}
+
+static UINT16 p80211_channel_to_mhz(UINT8 ch, int dot11a)
+{
+
+ if (ch == 0)
+ return 0;
+ if (ch > 200)
+ return 0;
+
+ /* 5G */
+
+ if (dot11a) {
+ return (5000 + (5 * ch));
+ }
+
+ /* 2.4G */
+
+ if (ch == 14)
+ return 2484;
+
+ if ((ch < 14) && (ch > 0)) {
+ return (2407 + (5 * ch));
+ }
+
+ return 0;
+}
+
+/* taken from orinoco.c ;-) */
+static const long p80211wext_channel_freq[] = {
+ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+#define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
+
+/* steal a spare bit to store the shared/opensystems state. should default to open if not set */
+#define HOSTWEP_SHAREDKEY BIT3
+
+
+/** function declarations =============== */
+
+static int qual_as_percent(int snr ) {
+ if ( snr <= 0 )
+ return 0;
+ if ( snr <= 40 )
+ return snr*5/2;
+ return 100;
+}
+
+
+
+
+static int p80211wext_dorequest(wlandevice_t *wlandev, UINT32 did, UINT32 data)
+{
+ p80211msg_dot11req_mibset_t msg;
+ p80211item_uint32_t mibitem;
+ int result;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ mibitem.did = did;
+ mibitem.data = data;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ DBFEXIT;
+ return result;
+}
+
+static int p80211wext_autojoin(wlandevice_t *wlandev)
+{
+ p80211msg_lnxreq_autojoin_t msg;
+ struct iw_point data;
+ char ssid[IW_ESSID_MAX_SIZE];
+
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ /* Get ESSID */
+ result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
+ msg.authtype.data = P80211ENUM_authalg_sharedkey;
+ else
+ msg.authtype.data = P80211ENUM_authalg_opensystem;
+
+ msg.msgcode = DIDmsg_lnxreq_autojoin;
+
+ /* Trim the last '\0' to fit the SSID format */
+
+ if (data.length && ssid[data.length-1] == '\0') {
+ data.length = data.length - 1;
+ }
+
+ memcpy(msg.ssid.data.data, ssid, data.length);
+ msg.ssid.data.len = data.length;
+
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+exit:
+
+ DBFEXIT;
+ return err;
+
+}
+
+/* called by /proc/net/wireless */
+struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
+{
+ p80211msg_lnxreq_commsquality_t quality;
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct iw_statistics* wstats = &wlandev->wstats;
+ int retval;
+
+ DBFENTER;
+ /* Check */
+ if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
+ return NULL;
+
+ /* XXX Only valid in station mode */
+ wstats->status = 0;
+
+ /* build request message */
+ quality.msgcode = DIDmsg_lnxreq_commsquality;
+ quality.dbm.data = P80211ENUM_truth_true;
+ quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* send message to nsd */
+ if ( wlandev->mlmerequest == NULL )
+ return NULL;
+
+ retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
+
+ wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
+ wstats->qual.level = quality.level.data; /* instant signal level */
+ wstats->qual.noise = quality.noise.data; /* instant noise level */
+
+#if WIRELESS_EXT > 18
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ wstats->qual.updated = 7;
+#endif
+ wstats->discard.code = wlandev->rx.decrypt_err;
+ wstats->discard.nwid = 0;
+ wstats->discard.misc = 0;
+
+#if WIRELESS_EXT > 11
+ wstats->discard.fragment = 0; // incomplete fragments
+ wstats->discard.retries = 0; // tx retries.
+ wstats->miss.beacon = 0;
+#endif
+
+ DBFEXIT;
+
+ return wstats;
+}
+
+static int p80211wext_giwname(netdevice_t *dev,
+ struct iw_request_info *info,
+ char *name, char *extra)
+{
+ struct iw_param rate;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ result = p80211wext_giwrate(dev, NULL, &rate, NULL);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ switch (rate.value) {
+ case 1000000:
+ case 2000000:
+ strcpy(name, "IEEE 802.11-DS");
+ break;
+ case 5500000:
+ case 11000000:
+ strcpy(name, "IEEE 802.11-b");
+ break;
+ }
+exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_giwfreq(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ if (mibitem.data > NUM_CHANNELS) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ /* convert into frequency instead of a channel */
+ freq->e = 1;
+ freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_siwfreq(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
+ mibitem.status = P80211ENUM_msgitem_status_data_ok;
+
+ if ( (freq->e == 0) && (freq->m <= 1000) )
+ mibitem.data = freq->m;
+ else
+ mibitem.data = p80211_mhz_to_channel(freq->m);
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+#if WIRELESS_EXT > 8
+
+static int p80211wext_giwmode(netdevice_t *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+ DBFENTER;
+
+ switch (wlandev->macmode) {
+ case WLAN_MACMODE_IBSS_STA:
+ *mode = IW_MODE_ADHOC;
+ break;
+ case WLAN_MACMODE_ESS_STA:
+ *mode = IW_MODE_INFRA;
+ break;
+ case WLAN_MACMODE_ESS_AP:
+ *mode = IW_MODE_MASTER;
+ break;
+ default:
+ /* Not set yet. */
+ *mode = IW_MODE_AUTO;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+static int p80211wext_siwmode(netdevice_t *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
+ *mode != IW_MODE_MASTER) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ /* Operation mode is the same with current mode */
+ if (*mode == wlandev->macmode)
+ goto exit;
+
+ switch (*mode) {
+ case IW_MODE_ADHOC:
+ wlandev->macmode = WLAN_MACMODE_IBSS_STA;
+ break;
+ case IW_MODE_INFRA:
+ wlandev->macmode = WLAN_MACMODE_ESS_STA;
+ break;
+ case IW_MODE_MASTER:
+ wlandev->macmode = WLAN_MACMODE_ESS_AP;
+ break;
+ default:
+ /* Not set yet. */
+ WLAN_LOG_INFO("Operation mode: %d not support\n", *mode);
+ return -EOPNOTSUPP;
+ }
+
+ /* Set Operation mode to the PORT TYPE RID */
+
+#warning "get rid of p2mib here"
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
+ mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result)
+ err = -EFAULT;
+
+ exit:
+ DBFEXIT;
+
+ return err;
+}
+
+
+static int p80211wext_giwrange(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ int i, val;
+
+ DBFENTER;
+
+ // for backward compatability set size & zero everything we don't understand
+ data->length = sizeof(*range);
+ memset(range,0,sizeof(*range));
+
+#if WIRELESS_EXT > 9
+ range->txpower_capa = IW_TXPOW_DBM;
+ // XXX what about min/max_pmp, min/max_pmt, etc.
+#endif
+
+#if WIRELESS_EXT > 10
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 13;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->min_retry = 0;
+ range->max_retry = 255;
+#endif /* WIRELESS_EXT > 10 */
+
+#if WIRELESS_EXT > 16
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid
+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode
+ range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
+ IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
+#endif
+
+ range->num_channels = NUM_CHANNELS;
+
+ /* XXX need to filter against the regulatory domain &| active set */
+ val = 0;
+ for (i = 0; i < NUM_CHANNELS ; i++) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = p80211wext_channel_freq[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+
+ range->num_frequency = val;
+
+ /* Max of /proc/net/wireless */
+ range->max_qual.qual = 100;
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->sensitivity = 3;
+ // XXX these need to be nsd-specific!
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ range->max_encoding_tokens = NUM_WEPKEYS;
+ range->num_encoding_sizes = 2;
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+
+ // XXX what about num_bitrates/throughput?
+ range->num_bitrates = 0;
+
+ /* estimated max throughput */
+ // XXX need to cap it if we're running at ~2Mbps..
+ range->throughput = 5500000;
+
+ DBFEXIT;
+ return 0;
+}
+#endif
+
+static int p80211wext_giwap(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+ DBFENTER;
+
+ memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
+ ap_addr->sa_family = ARPHRD_ETHER;
+
+ DBFEXIT;
+ return 0;
+}
+
+#if WIRELESS_EXT > 8
+static int p80211wext_giwencode(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ int err = 0;
+ int i;
+
+ DBFENTER;
+
+ if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
+ erq->flags = IW_ENCODE_ENABLED;
+ else
+ erq->flags = IW_ENCODE_DISABLED;
+
+ if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
+
+ i = (erq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (i == -1)
+ i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
+
+ if ((i < 0) || (i >= NUM_WEPKEYS)) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ erq->flags |= i + 1;
+
+ /* copy the key from the driver cache as the keys are read-only MIBs */
+ erq->length = wlandev->wep_keylens[i];
+ memcpy(key, wlandev->wep_keys[i], erq->length);
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_siwencode(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211msg_dot11req_mibset_t msg;
+ p80211item_pstr32_t pstr;
+
+ int err = 0;
+ int result = 0;
+ int enable = 0;
+ int i;
+
+ DBFENTER;
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ /* Check the Key index first. */
+ if((i = (erq->flags & IW_ENCODE_INDEX))) {
+
+ if ((i < 1) || (i > NUM_WEPKEYS)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ else
+ i--;
+
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+ else {
+ enable = 1;
+ }
+
+ }
+ else {
+ // Do not thing when no Key Index
+ }
+
+ /* Check if there is no key information in the iwconfig request */
+ if((erq->flags & IW_ENCODE_NOKEY) == 0 && enable == 1) {
+
+ /*------------------------------------------------------------
+ * If there is WEP Key for setting, check the Key Information
+ * and then set it to the firmware.
+ -------------------------------------------------------------*/
+
+ if (erq->length > 0) {
+
+ /* copy the key from the driver cache as the keys are read-only MIBs */
+ wlandev->wep_keylens[i] = erq->length;
+ memcpy(wlandev->wep_keys[i], key, erq->length);
+
+ /* Prepare data struture for p80211req_dorequest. */
+ memcpy(pstr.data.data, key, erq->length);
+ pstr.data.len = erq->length;
+
+ switch(i)
+ {
+ case 0:
+ pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
+ break;
+
+ case 1:
+ pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
+ break;
+
+ case 2:
+ pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
+ break;
+
+ case 3:
+ pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
+ break;
+
+ default:
+ err = -EINVAL;
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+ }
+
+ }
+
+ /* Check the PrivacyInvoked flag */
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
+ }
+ else if((erq->flags & IW_ENCODE_ENABLED) || enable == 1) {
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
+ }
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ /* Check the ExcludeUnencrypted flag */
+ if (erq->flags & IW_ENCODE_RESTRICTED) {
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
+ }
+ else if (erq->flags & IW_ENCODE_OPEN) {
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
+ }
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_giwessid(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+ DBFENTER;
+
+ if (wlandev->ssid.len) {
+ data->length = wlandev->ssid.len;
+ data->flags = 1;
+ memcpy(essid, wlandev->ssid.data, data->length);
+ essid[data->length] = 0;
+#if (WIRELESS_EXT < 21)
+ data->length++;
+#endif
+ } else {
+ memset(essid, 0, sizeof(wlandev->ssid.data));
+ data->length = 0;
+ data->flags = 0;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+static int p80211wext_siwessid(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211msg_lnxreq_autojoin_t msg;
+
+ int result;
+ int err = 0;
+ int length = data->length;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+
+ if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
+ msg.authtype.data = P80211ENUM_authalg_sharedkey;
+ else
+ msg.authtype.data = P80211ENUM_authalg_opensystem;
+
+ msg.msgcode = DIDmsg_lnxreq_autojoin;
+
+#if (WIRELESS_EXT < 21)
+ if (length) length--;
+#endif
+
+ /* Trim the last '\0' to fit the SSID format */
+
+ if (length && essid[length-1] == '\0') {
+ length--;
+ }
+
+ memcpy(msg.ssid.data.data, essid, length);
+ msg.ssid.data.len = length;
+
+ WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+ WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+
+static int p80211wext_siwcommit(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ /* Auto Join */
+ err = p80211wext_autojoin(wlandev);
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+
+static int p80211wext_giwrate(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ rrq->fixed = 0; /* can it change? */
+ rrq->disabled = 0;
+ rrq->value = 0;
+
+#define HFA384x_RATEBIT_1 ((UINT16)1)
+#define HFA384x_RATEBIT_2 ((UINT16)2)
+#define HFA384x_RATEBIT_5dot5 ((UINT16)4)
+#define HFA384x_RATEBIT_11 ((UINT16)8)
+
+ switch (mibitem.data) {
+ case HFA384x_RATEBIT_1:
+ rrq->value = 1000000;
+ break;
+ case HFA384x_RATEBIT_2:
+ rrq->value = 2000000;
+ break;
+ case HFA384x_RATEBIT_5dot5:
+ rrq->value = 5500000;
+ break;
+ case HFA384x_RATEBIT_11:
+ rrq->value = 11000000;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_giwrts(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ rts->value = mibitem.data;
+ rts->disabled = (rts->value == 2347);
+ rts->fixed = 1;
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+
+static int p80211wext_siwrts(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
+ if (rts->disabled)
+ mibitem.data = 2347;
+ else
+ mibitem.data = rts->value;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_giwfrag(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ frag->value = mibitem.data;
+ frag->disabled = (frag->value == 2346);
+ frag->fixed = 1;
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_siwfrag(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
+
+ if (frag->disabled)
+ mibitem.data = 2346;
+ else
+ mibitem.data = frag->value;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+#endif /* WIRELESS_EXT > 8 */
+
+#if WIRELESS_EXT > 10
+
+#ifndef IW_RETRY_LONG
+#define IW_RETRY_LONG IW_RETRY_MAX
+#endif
+
+#ifndef IW_RETRY_SHORT
+#define IW_RETRY_SHORT IW_RETRY_MIN
+#endif
+
+static int p80211wext_giwretry(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+ UINT16 shortretry, longretry, lifetime;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ shortretry = mibitem.data;
+
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ longretry = mibitem.data;
+
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ lifetime = mibitem.data;
+
+ rrq->disabled = 0;
+
+ if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+ rrq->flags = IW_RETRY_LIFETIME;
+ rrq->value = lifetime * 1024;
+ } else {
+ if (rrq->flags & IW_RETRY_LONG) {
+ rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
+ rrq->value = longretry;
+ } else {
+ rrq->flags = IW_RETRY_LIMIT;
+ rrq->value = shortretry;
+ if (shortretry != longretry)
+ rrq->flags |= IW_RETRY_SHORT;
+ }
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+
+}
+
+static int p80211wext_siwretry(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ if (rrq->disabled) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+
+ if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
+ mibitem.data = rrq->value /= 1024;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+ } else {
+ if (rrq->flags & IW_RETRY_LONG) {
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
+ mibitem.data = rrq->value;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+ }
+
+ if (rrq->flags & IW_RETRY_SHORT) {
+ mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
+ mibitem.data = rrq->value;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+ }
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+
+}
+
+#endif /* WIRELESS_EXT > 10 */
+
+#if WIRELESS_EXT > 9
+static int p80211wext_siwtxpow(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ if (!wlan_wext_write) {
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ msg.msgcode = DIDmsg_dot11req_mibset;
+
+ switch (rrq->value) {
+
+ case 1 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1; break;
+ case 2 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2; break;
+ case 3 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3; break;
+ case 4 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4; break;
+ case 5 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5; break;
+ case 6 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6; break;
+ case 7 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7; break;
+ case 8 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break;
+ default: mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break;
+ }
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+static int p80211wext_giwtxpow(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211item_uint32_t mibitem;
+ p80211msg_dot11req_mibset_t msg;
+ int result;
+ int err = 0;
+
+ DBFENTER;
+
+ msg.msgcode = DIDmsg_dot11req_mibget;
+ mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
+
+ memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+
+ if (result) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
+
+ // XXX handle OFF by setting disabled = 1;
+
+ rrq->flags = 0; // IW_TXPOW_DBM;
+ rrq->disabled = 0;
+ rrq->fixed = 0;
+ rrq->value = mibitem.data;
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+#endif /* WIRELESS_EXT > 9 */
+
+static int p80211wext_siwspy(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct sockaddr address[IW_MAX_SPY];
+ int number = srq->length;
+ int i;
+
+ DBFENTER;
+
+ /* Copy the data from the input buffer */
+ memcpy(address, extra, sizeof(struct sockaddr)*number);
+
+ wlandev->spy_number = 0;
+
+ if (number > 0) {
+
+ /* extract the addresses */
+ for (i = 0; i < number; i++) {
+
+ memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
+ }
+
+ /* reset stats */
+ memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
+
+ /* set number of addresses */
+ wlandev->spy_number = number;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+/* jkriegl: from orinoco, modified */
+static int p80211wext_giwspy(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+ struct sockaddr address[IW_MAX_SPY];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+ int number;
+ int i;
+
+ DBFENTER;
+
+ number = wlandev->spy_number;
+
+ if (number > 0) {
+
+ /* populate address and spy struct's */
+ for (i = 0; i < number; i++) {
+ memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
+ address[i].sa_family = AF_UNIX;
+ memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
+ }
+
+ /* reset update flag */
+ for (i=0; i < number; i++)
+ wlandev->spy_stat[i].updated = 0;
+ }
+
+ /* push stuff to user space */
+ srq->length = number;
+ memcpy(extra, address, sizeof(struct sockaddr)*number);
+ memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
+
+ DBFEXIT;
+ return 0;
+}
+
+static int prism2_result2err (int prism2_result)
+{
+ int err = 0;
+
+ switch (prism2_result) {
+ case P80211ENUM_resultcode_invalid_parameters:
+ err = -EINVAL;
+ break;
+ case P80211ENUM_resultcode_implementation_failure:
+ err = -EIO;
+ break;
+ case P80211ENUM_resultcode_not_supported:
+ err = -EOPNOTSUPP;
+ break;
+ default:
+ err = 0;
+ break;
+ }
+
+ return err;
+}
+
+#if WIRELESS_EXT > 13
+static int p80211wext_siwscan(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211msg_dot11req_scan_t msg;
+ int result;
+ int err = 0;
+ int i = 0;
+
+ DBFENTER;
+
+ if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
+ WLAN_LOG_ERROR("Can't scan in AP mode\n");
+ err = (-EOPNOTSUPP);
+ goto exit;
+ }
+
+ memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
+ msg.msgcode = DIDmsg_dot11req_scan;
+ msg.bsstype.data = P80211ENUM_bsstype_any;
+
+ memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
+ msg.bssid.data.len = 6;
+
+ msg.scantype.data = P80211ENUM_scantype_active;
+ msg.probedelay.data = 0;
+
+ for (i = 1; i <= 14; i++)
+ msg.channellist.data.data[i-1] = i;
+ msg.channellist.data.len = 14;
+
+ msg.maxchanneltime.data = 250;
+ msg.minchanneltime.data = 200;
+
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+ if (result)
+ err = prism2_result2err (msg.resultcode.data);
+
+ exit:
+ DBFEXIT;
+ return err;
+}
+
+
+/* Helper to translate scan into Wireless Extensions scan results.
+ * Inspired by the prism54 code, which was in turn inspired by the
+ * airo driver code.
+ */
+static char *
+wext_translate_bss(struct iw_request_info *info, char *current_ev,
+ char *end_buf, p80211msg_dot11req_scan_results_t *bss)
+{
+ struct iw_event iwe; /* Temporary buffer */
+
+ /* The first entry must be the MAC address */
+ memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ iwe.cmd = SIOCGIWAP;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ /* The following entries will be displayed in the same order we give them */
+
+ /* The ESSID. */
+ if (bss->ssid.data.len > 0) {
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ int size;
+
+ size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
+ memset(&essid, 0, sizeof (essid));
+ memcpy(&essid, bss->ssid.data.data, size);
+ WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
+ iwe.u.data.length = size;
+ iwe.u.data.flags = 1;
+ iwe.cmd = SIOCGIWESSID;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
+ WLAN_LOG_DEBUG(1, " essid size OK.\n");
+ }
+
+ switch (bss->bsstype.data) {
+ case P80211ENUM_bsstype_infrastructure:
+ iwe.u.mode = IW_MODE_MASTER;
+ break;
+
+ case P80211ENUM_bsstype_independent:
+ iwe.u.mode = IW_MODE_ADHOC;
+ break;
+
+ default:
+ iwe.u.mode = 0;
+ break;
+ }
+ iwe.cmd = SIOCGIWMODE;
+ if (iwe.u.mode)
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+
+ /* Encryption capability */
+ if (bss->privacy.data == P80211ENUM_truth_true)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ iwe.cmd = SIOCGIWENCODE;
+ current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
+
+ /* Add frequency. (short) bss->channel is the frequency in MHz */
+ iwe.u.freq.m = bss->dschannel.data;
+ iwe.u.freq.e = 0;
+ iwe.cmd = SIOCGIWFREQ;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add quality statistics */
+ iwe.u.qual.level = bss->signal.data;
+ iwe.u.qual.noise = bss->noise.data;
+ /* do a simple SNR for quality */
+ iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
+ iwe.cmd = IWEVQUAL;
+ current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+ return current_ev;
+}
+
+
+static int p80211wext_giwscan(netdevice_t *dev,
+ struct iw_request_info *info,
+ struct iw_point *srq, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ p80211msg_dot11req_scan_results_t msg;
+ int result = 0;
+ int err = 0;
+ int i = 0;
+ int scan_good = 0;
+ char *current_ev = extra;
+
+ DBFENTER;
+
+ /* Since wireless tools doesn't really have a way of passing how
+ * many scan results results there were back here, keep grabbing them
+ * until we fail.
+ */
+ do {
+ memset(&msg, 0, sizeof(msg));
+ msg.msgcode = DIDmsg_dot11req_scan_results;
+ msg.bssindex.data = i;
+
+ result = p80211req_dorequest(wlandev, (UINT8*)&msg);
+ if ((result != 0) ||
+ (msg.resultcode.data != P80211ENUM_resultcode_success)) {
+ break;
+ }
+
+ current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
+ scan_good = 1;
+ i++;
+ } while (i < IW_MAX_AP);
+
+ srq->length = (current_ev - extra);
+ srq->flags = 0; /* todo */
+
+ if (result && !scan_good)
+ err = prism2_result2err (msg.resultcode.data);
+
+ DBFEXIT;
+ return err;
+}
+#endif
+
+/*****************************************************/
+//extra wireless extensions stuff to support NetworkManager (I hope)
+
+#if WIRELESS_EXT > 17
+/* SIOCSIWENCODEEXT */
+static int p80211wext_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ p80211msg_dot11req_mibset_t msg;
+ p80211item_pstr32_t *pstr;
+
+ int result = 0;
+ struct iw_point *encoding = &wrqu->encoding;
+ int idx = encoding->flags & IW_ENCODE_INDEX;
+
+ WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
+
+
+ if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
+ // set default key ? I'm not sure if this the the correct thing to do here
+
+ if ( idx ) {
+ if (idx < 1 || idx > NUM_WEPKEYS) {
+ return -EINVAL;
+ } else
+ idx--;
+ }
+ WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
+ if ( result )
+ return -EFAULT;
+ }
+
+
+ if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
+ if ( ! ext->alg & IW_ENCODE_ALG_WEP) {
+ WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
+ return -EINVAL;
+ }
+ if (idx) {
+ if (idx <1 || idx > NUM_WEPKEYS)
+ return -EINVAL;
+ else
+ idx--;
+ }
+ WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
+ wlandev->wep_keylens[idx] = ext->key_len;
+ memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
+
+ memset( &msg,0,sizeof(msg));
+ pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
+ memcpy(pstr->data.data, ext->key,ext->key_len);
+ pstr->data.len = ext->key_len;
+ switch (idx) {
+ case 0:
+ pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
+ break;
+ case 1:
+ pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
+ break;
+ case 2:
+ pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
+ break;
+ case 3:
+ pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
+ break;
+ default:
+ break;
+ }
+ msg.msgcode = DIDmsg_dot11req_mibset;
+ result = p80211req_dorequest(wlandev,(UINT8*)&msg);
+ WLAN_LOG_DEBUG(1,"result (%d)\n",result);
+ }
+ return result;
+}
+
+/* SIOCGIWENCODEEXT */
+static int p80211wext_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+
+ struct iw_point *encoding = &wrqu->encoding;
+ int result = 0;
+ int max_len;
+ int idx;
+
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
+
+
+ max_len = encoding->length - sizeof(*ext);
+ if ( max_len <= 0) {
+ WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
+ result = -EINVAL;
+ goto exit;
+ }
+ idx = encoding->flags & IW_ENCODE_INDEX;
+
+ WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
+
+ if (idx) {
+ if (idx < 1 || idx > NUM_WEPKEYS ) {
+ WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
+ result = -EINVAL;
+ goto exit;
+ }
+ idx--;
+ } else {
+ /* default key ? not sure what to do */
+ /* will just use key[0] for now ! FIX ME */
+ }
+
+ encoding->flags = idx + 1;
+ memset(ext,0,sizeof(*ext));
+
+ ext->alg = IW_ENCODE_ALG_WEP;
+ ext->key_len = wlandev->wep_keylens[idx];
+ memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
+
+ encoding->flags |= IW_ENCODE_ENABLED;
+exit:
+ DBFEXIT;
+
+ return result;
+}
+
+
+/* SIOCSIWAUTH */
+static int p80211_wext_set_iwauth (struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct iw_param *param = &wrqu->param;
+ int result =0;
+
+ WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
+ if (param->value)
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
+ else
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED:
+ WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
+ if ( param->value)
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
+ else
+ result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
+
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
+ WLAN_LOG_DEBUG(1,"set open_system\n");
+ wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
+ } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
+ WLAN_LOG_DEBUG(1,"set shared key\n");
+ wlandev->hostwep |= HOSTWEP_SHAREDKEY;
+ } else {
+ /* don't know what to do know :( */
+ WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
+ result = -EINVAL;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+
+ return result;
+}
+
+/* SIOCSIWAUTH */
+static int p80211_wext_get_iwauth (struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+ struct iw_param *param = &wrqu->param;
+ int result =0;
+
+ WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED:
+ param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+
+
+ default:
+ break;
+ }
+
+
+
+ return result;
+}
+
+
+#endif
+
+
+
+
+
+
+/*****************************************************/
+
+
+
+
+
+/*
+typedef int (*iw_handler)(netdevice_t *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+*/
+
+#if WIRELESS_EXT > 12
+static iw_handler p80211wext_handlers[] = {
+ (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
+ (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
+ (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
+ (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
+ (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
+ (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
+ (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
+ (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWAP */
+ (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+ (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
+ (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
+#else /* WIRELESS_EXT > 13 */
+ (iw_handler) NULL, /* null */ /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* null */ /* SIOCGIWSCAN */
+#endif /* WIRELESS_EXT > 13 */
+ (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
+ (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWRATE */
+ (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
+ (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
+ (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
+ (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
+ (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
+ (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
+ (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
+ (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
+ (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
+ (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) NULL, /* SIOCSIWPOWER */
+ (iw_handler) NULL, /* SIOCGIWPOWER */
+#if WIRELESS_EXT > 17
+/* WPA operations */
+
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
+ (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
+ (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
+ (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
+
+ (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
+ (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
+ (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
+#endif
+};
+
+struct iw_handler_def p80211wext_handler_def = {
+ .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler),
+ .num_private = 0,
+ .num_private_args = 0,
+ .standard = p80211wext_handlers,
+ .private = NULL,
+ .private_args = NULL,
+#if WIRELESS_EXT > 16
+ .get_wireless_stats = p80211wext_get_wireless_stats
+#endif
+};
+
+#endif
+
+/* wireless extensions' ioctls */
+int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
+{
+ wlandevice_t *wlandev = (wlandevice_t*)dev->priv;
+
+#if WIRELESS_EXT < 13
+ struct iwreq *iwr = (struct iwreq*)ifr;
+#endif
+
+ p80211item_uint32_t mibitem;
+ int err = 0;
+
+ DBFENTER;
+
+ mibitem.status = P80211ENUM_msgitem_status_data_ok;
+
+ if ( wlandev->msdstate != WLAN_MSD_RUNNING ) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ WLAN_LOG_DEBUG(1, "Received wireless extension ioctl #%d.\n", cmd);
+
+ switch (cmd) {
+#if WIRELESS_EXT < 13
+ case SIOCSIWNAME: /* unused */
+ err = (-EOPNOTSUPP);
+ break;
+ case SIOCGIWNAME: /* get name == wireless protocol */
+ err = p80211wext_giwname(dev, NULL, (char *) &iwr->u, NULL);
+ break;
+ case SIOCSIWNWID:
+ case SIOCGIWNWID:
+ err = (-EOPNOTSUPP);
+ break;
+ case SIOCSIWFREQ: /* set channel */
+ err = p80211wext_siwfreq(dev, NULL, &(iwr->u.freq), NULL);
+ break;
+ case SIOCGIWFREQ: /* get channel */
+ err = p80211wext_giwfreq(dev, NULL, &(iwr->u.freq), NULL);
+ break;
+ case SIOCSIWRANGE:
+ case SIOCSIWPRIV:
+ case SIOCSIWAP: /* set access point MAC addresses (BSSID) */
+ err = (-EOPNOTSUPP);
+ break;
+
+ case SIOCGIWAP: /* get access point MAC addresses (BSSID) */
+ err = p80211wext_giwap(dev, NULL, &(iwr->u.ap_addr), NULL);
+ break;
+
+#if WIRELESS_EXT > 8
+ case SIOCSIWMODE: /* set operation mode */
+ case SIOCSIWESSID: /* set SSID (network name) */
+ case SIOCSIWRATE: /* set default bit rate (bps) */
+ err = (-EOPNOTSUPP);
+ break;
+
+ case SIOCGIWMODE: /* get operation mode */
+ err = p80211wext_giwmode(dev, NULL, &iwr->u.mode, NULL);
+
+ break;
+ case SIOCGIWNICKN: /* get node name/nickname */
+ case SIOCGIWESSID: /* get SSID */
+ if(iwr->u.essid.pointer) {
+ char ssid[IW_ESSID_MAX_SIZE+1];
+ memset(ssid, 0, sizeof(ssid));
+
+ err = p80211wext_giwessid(dev, NULL, &iwr->u.essid, ssid);
+ if(copy_to_user(iwr->u.essid.pointer, ssid, sizeof(ssid)))
+ err = (-EFAULT);
+ }
+ break;
+ case SIOCGIWRATE:
+ err = p80211wext_giwrate(dev, NULL, &iwr->u.bitrate, NULL);
+ break;
+ case SIOCGIWRTS:
+ err = p80211wext_giwrts(dev, NULL, &iwr->u.rts, NULL);
+ break;
+ case SIOCGIWFRAG:
+ err = p80211wext_giwfrag(dev, NULL, &iwr->u.rts, NULL);
+ break;
+ case SIOCGIWENCODE:
+ if (!capable(CAP_NET_ADMIN))
+ err = -EPERM;
+ else if (iwr->u.encoding.pointer) {
+ char keybuf[MAX_KEYLEN];
+ err = p80211wext_giwencode(dev, NULL,
+ &iwr->u.encoding, keybuf);
+ if (copy_to_user(iwr->u.encoding.pointer, keybuf,
+ iwr->u.encoding.length))
+ err = -EFAULT;
+ }
+ break;
+ case SIOCGIWAPLIST:
+ case SIOCSIWRTS:
+ case SIOCSIWFRAG:
+ case SIOCSIWSENS:
+ case SIOCGIWSENS:
+ case SIOCSIWNICKN: /* set node name/nickname */
+ case SIOCSIWENCODE: /* set encoding token & mode */
+ case SIOCSIWSPY:
+ case SIOCGIWSPY:
+ case SIOCSIWPOWER:
+ case SIOCGIWPOWER:
+ case SIOCGIWPRIV:
+ err = (-EOPNOTSUPP);
+ break;
+ case SIOCGIWRANGE:
+ if(iwr->u.data.pointer != NULL) {
+ struct iw_range range;
+ err = p80211wext_giwrange(dev, NULL, &iwr->u.data,
+ (char *) &range);
+ /* Push that up to the caller */
+ if (copy_to_user(iwr->u.data.pointer, &range, sizeof(range)))
+ err = -EFAULT;
+ }
+ break;
+#endif /* WIRELESS_EXT > 8 */
+#if WIRELESS_EXT > 9
+ case SIOCSIWTXPOW:
+ err = (-EOPNOTSUPP);
+ break;
+ case SIOCGIWTXPOW:
+ err = p80211wext_giwtxpow(dev, NULL, &iwr->u.txpower, NULL);
+ break;
+#endif /* WIRELESS_EXT > 9 */
+#if WIRELESS_EXT > 10
+ case SIOCSIWRETRY:
+ err = (-EOPNOTSUPP);
+ break;
+ case SIOCGIWRETRY:
+ err = p80211wext_giwretry(dev, NULL, &iwr->u.retry, NULL);
+ break;
+#endif /* WIRELESS_EXT > 10 */
+
+#endif /* WIRELESS_EXT <= 12 */
+
+ default:
+ err = (-EOPNOTSUPP);
+ break;
+ }
+
+ exit:
+ DBFEXIT;
+ return (err);
+}
+
+int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
+{
+ union iwreq_data data;
+
+ DBFENTER;
+
+#if WIRELESS_EXT > 13
+ /* Send the association state first */
+ data.ap_addr.sa_family = ARPHRD_ETHER;
+ if (assoc) {
+ memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
+ } else {
+ memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
+ }
+
+ if (wlan_wext_write)
+ wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
+
+ if (!assoc) goto done;
+
+ // XXX send association data, like IEs, etc etc.
+#endif
+ done:
+ DBFEXIT;
+ return 0;
+}
+
+
+#endif /* compatibility to wireless extensions */
+
+
+
+
diff --git a/drivers/staging/wlan-ng/prism2_cs.c b/drivers/staging/wlan-ng/prism2_cs.c
new file mode 100644
index 00000000000..63ce5659f21
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2_cs.c
@@ -0,0 +1,1487 @@
+#define WLAN_HOSTIF WLAN_PCMCIA
+#include "hfa384x.c"
+#include "prism2mgmt.c"
+#include "prism2mib.c"
+#include "prism2sta.c"
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) )
+#if (WLAN_CPU_FAMILY == WLAN_Ix86)
+#ifndef CONFIG_ISA
+#warning "You may need to enable ISA support in your kernel."
+#endif
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
+static u_int irq_mask = 0xdeb8; /* Interrupt mask */
+static int irq_list[4] = { -1 }; /* Interrupt list */
+#endif
+static u_int prism2_ignorevcc=1; /* Boolean, if set, we
+ * ignore what the Vcc
+ * is set to and what the CIS
+ * says.
+ */
+module_param( prism2_ignorevcc, int, 0644);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))
+static int numlist = 4;
+module_param_array(irq_list, int, numlist, 0444);
+#else
+module_param_array(irq_list, int, NULL, 0444);
+#endif
+module_param( irq_mask, int, 0644);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+static int prism2_cs_suspend(struct pcmcia_device *pdev);
+static int prism2_cs_resume(struct pcmcia_device *pdev);
+static void prism2_cs_remove(struct pcmcia_device *pdev);
+static int prism2_cs_probe(struct pcmcia_device *pdev);
+#else
+dev_link_t *prism2sta_attach(void);
+static void prism2sta_detach(dev_link_t *link);
+static void prism2sta_config(dev_link_t *link);
+static void prism2sta_release(u_long arg);
+static int prism2sta_event (event_t event, int priority, event_callback_args_t *args);
+
+static dev_link_t *dev_list = NULL; /* head of instance list */
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
+/*----------------------------------------------------------------
+* cs_error
+*
+* Utility function to print card services error messages.
+*
+* Arguments:
+* handle client handle identifying this CS client
+* func CS function number that generated the error
+* ret CS function return code
+*
+* Returns:
+* nothing
+* Side effects:
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
+ CardServices(ReportError, dev_info, (void *)func, (void *)ret);
+#else
+ error_info_t err = { func, ret };
+ pcmcia_report_error(handle, &err);
+#endif
+}
+#else // kernel_version
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
+static struct pcmcia_device_id prism2_cs_ids[] = {
+ PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), // Intersil PRISM2 Reference Design 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), // Compaq WL100/200 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), // Compaq iPaq HNW-100 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), // Samsung SWL2000-N 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), // Z-Com XI300 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), // ZoomAir 4100 11Mb/s 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), // Linksys WPC11 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x8649af2, 0x4b74baa0), // Addtron AWP-100 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), // D-Link DWL-650 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("SMC", "SMC2632W", "Version 01.02", 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), // SMC 2632W 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e), // BroMax Freeport 11Mbps 802.11b WLAN Card (Prism 2.5)
+ PCMCIA_DEVICE_PROD_ID123("U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), // U.S. Robotics IEEE 802.11b PC-CARD
+ PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), // Level-One WPC-0100
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 2.5)
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 3)
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), // corega K.K. Wireless LAN PCC-11
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), // corega K.K. Wireless LAN PCCA-11
+ PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), // CONTEC FLEXSCAN/FX-DDS110-PCC
+ PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), // PLANEX GeoWave/GW-NS110
+ PCMCIA_DEVICE_PROD_ID123("OEM", "PRISM2 IEEE 802.11 PC-Card", "Version 01.02", 0xfea54c90, 0x48f2bdd6, 0x4b74baa0), // Ambicom WL1100 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", "Version 01.02", 0x7e3b326a, 0x49893e92, 0x4b74baa0), // LeArtery SYNCBYAIR 11Mbps 802.11b WLAN Card
+PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), // Intermec MobileLAN 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("NETGEAR MA401 Wireless PC", "Card", "Version 01.00", 0xa37434e9, 0x9762e8f1, 0xa57adb8c), // NETGEAR MA401 11Mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", "Eval-RevA", 0x4b801a17, 0xf222ec2d, 0x630d52b2, 0xc23adc0e), // Intersil PRISM Freedom 11mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_PROD_ID123("OTC", "Wireless AirEZY 2411-PCC WLAN Card", "Version 01.02", 0x4ac44287, 0x235a6bed, 0x4b74baa0), // OTC Wireless AirEZY 2411-PCC 11Mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_PROD_ID1234("802.11", "11Mbps Wireless LAN Card", "v08C1", "" , 0xb67a610e, 0x655aa7b7, 0x264b451a, 0x0), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_PROD_ID12("PROXIM", "RangeLAN-DS/LAN PC CARD", 0xc6536a5e, 0x3f35797d), // PROXIM RangeLAN-DS/LAN PC CARD
+ PCMCIA_DEVICE_PROD_ID1234("ACTIONTEC", "PRISM Wireless LAN PC Card", "0381", "RevA", 0x393089da, 0xa71e69d5, 0x90471fa9, 0x57a66194), // ACTIONTEC PRISM Wireless LAN PC Card
+ PCMCIA_DEVICE_MANF_CARD(0x1668, 0x0101), // ACTIONTEC PRISM Wireless LAN PC Card
+ PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), // 3Com AirConnect 3CRWE737A
+ PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE777A AirConnect Wireless LAN PCI Card" , 0x41240e5b, 0xafc7c33e), // 3Com AirConnect 3CRWE777A
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), // ASUS WL-100 802.11b WLAN PC Card
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), // ASUS WL-110 802.11b WLAN CF Card
+ PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), // BUFFALO WLI-CF-S11G 802.11b WLAN Card
+ PCMCIA_DEVICE_PROD_ID1234("The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA", 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194), // Linksys WCF11 11Mbps 802.11b WLAN Card (Prism 2.5)
+ PCMCIA_DEVICE_PROD_ID1234("Linksys", "Wireless CompactFlash Card", "", "", 0x733cc81, 0xc52f395, 0x0, 0x0), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
+ PCMCIA_DEVICE_PROD_ID1234("NETGEAR MA401RA Wireless PC", "Card", "ISL37300P", "Eval-RevA", 0x306467f, 0x9762e8f1, 0xc9049a39, 0xc23adc0e), // NETGEAR MA401RA 11Mbps 802.11 WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), // D-Link DCF-660W 11Mbps 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), // Microsoft Wireless Notebook Adapter MN-520
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), // AnyPoint(TM) Wireless II PC Card
+ PCMCIA_DEVICE_PROD_ID1234("D", "Link DRC-650 11Mbps WLAN Card", "Version 01.02", "" , 0x71b18589, 0xf144e3ac, 0x4b74baa0, 0x0), // D-Link DRC-650 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), // Adaptec AWN-8030
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7110), // D-Link DWL-650 rev P 802.11b WLAN card
+ // PCMCIA_DEVICE_PROD_ID1234("D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", "A3", 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52), // D-Link DWL-650 rev P 802.11b WLAN card
+ PCMCIA_DEVICE_PROD_ID123("INTERSIL", "I-GATE 11M PC Card / PC Card plus", "Version 01.02", 0x74c5e40d, 0x8304ff77, 0x4b74baa0), // I-Gate 11M PC Card
+ PCMCIA_DEVICE_PROD_ID1234("BENQ", "AWL100 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x35dadc74, 0x1f7fedb, 0xc9049a39, 0xc23adc0e), // benQ AWL100 802.11b WLAN Card
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), // benQ AWL100 802.11b WLAN Card
+ // PCMCIA_DEVICE_PROD_ID1("INTERSIL", 0x74c5e40d), // Intersil Prism 2 card
+ // PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), // Intersil Prism 2 card
+
+ PCMCIA_DEVICE_NULL
+};
+
+MODULE_DEVICE_TABLE(pcmcia, prism2_cs_ids);
+#endif
+
+static struct pcmcia_driver prism2_cs_driver = {
+ .drv = {
+ .name = "prism2_cs",
+ },
+ .owner = THIS_MODULE,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+ .suspend = prism2_cs_suspend,
+ .resume = prism2_cs_resume,
+ .remove = prism2_cs_remove,
+ .probe = prism2_cs_probe,
+ .id_table = prism2_cs_ids,
+#else
+ .attach = prism2sta_attach,
+ .detach = prism2sta_detach,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
+ .id_table = prism2_cs_ids,
+ .event = prism2sta_event,
+#endif // > 2.6.12
+#endif // <= 2.6.15
+};
+#endif /* kernel_version */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+#define CS_CHECK(fn, ret) \
+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+#define CFG_CHECK(fn, retf) \
+do { int ret = (retf); \
+if (ret != 0) { \
+ WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
+ cs_error(pdev, fn, ret); \
+ goto next_entry; \
+} \
+} while (0)
+
+static void prism2_cs_remove(struct pcmcia_device *pdev)
+{
+ struct wlandevice *wlandev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ dev_link_t *link = dev_to_instance(pdev);
+#endif
+
+ DBFENTER;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ wlandev = pdev->priv;
+#else
+ wlandev = link->priv;
+#endif
+
+ if (wlandev) {
+ p80211netdev_hwremoved(wlandev);
+ unregister_wlandev(wlandev);
+ wlan_unsetup(wlandev);
+ if (wlandev->priv) {
+ hfa384x_t *hw = wlandev->priv;
+ wlandev->priv = NULL;
+ if (hw) {
+ hfa384x_destroy(hw);
+ kfree(hw);
+ }
+ }
+ kfree(wlandev);
+ }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->priv = NULL;
+ pcmcia_disable_device(pdev);
+#else
+ if (link->state & DEV_CONFIG) {
+ if (link->win)
+ pcmcia_release_window(link->win);
+ pcmcia_release_configuration(link->handle);
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ if (link->irq.AssignedIRQ)
+ pcmcia_release_irq(link->handle, &link->irq);
+
+ link->state &= ~DEV_CONFIG;
+ }
+
+ link->priv = NULL;
+ kfree(link);
+#endif
+
+ DBFEXIT;
+ return;
+}
+
+static int prism2_cs_suspend(struct pcmcia_device *pdev)
+{
+ struct wlandevice *wlandev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ dev_link_t *link = dev_to_instance(pdev);
+#endif
+
+ DBFENTER;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ wlandev = pdev->priv;
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+#else
+ wlandev = link->priv;
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+ pcmcia_release_configuration(link->handle);
+ }
+#endif
+
+ DBFEXIT;
+
+ return 0;
+}
+
+static int prism2_cs_resume(struct pcmcia_device *pdev)
+{
+ struct wlandevice *wlandev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ dev_link_t *link = dev_to_instance(pdev);
+#endif
+
+ DBFENTER;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ wlandev = pdev->priv;
+ // XXX do something here?
+#else
+ wlandev = link->priv;
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ // XXX do something here?
+ }
+#endif
+
+
+ DBFEXIT;
+
+ return 0;
+}
+
+static int prism2_cs_probe(struct pcmcia_device *pdev)
+{
+ int rval = 0;
+ struct wlandevice *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+
+ config_info_t socketconf;
+ cisparse_t *parse = NULL;
+ tuple_t tuple;
+ uint8_t buf[64];
+ int last_fn, last_ret;
+ cistpl_cftable_entry_t dflt = { 0 };
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ dev_link_t *link;
+#endif
+
+ DBFENTER;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ /* Set up interrupt type */
+ pdev->conf.IntType = INT_MEMORY_AND_IO;
+#else
+ link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
+ if (link == NULL)
+ return -ENOMEM;
+ memset(link, 0, sizeof(dev_link_t));
+
+ link->conf.Vcc = 33;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ link->handle = pdev;
+ pdev->instance = link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+
+#endif
+
+ // VCC crap?
+ parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
+
+ wlandev = create_wlan();
+ if (!wlandev || !parse) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ rval = -EIO;
+ goto failed;
+ }
+ hw = wlandev->priv;
+
+ if ( wlan_setup(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
+ rval = -EIO;
+ goto failed;
+ }
+
+ /* Initialize the hw struct for now */
+ hfa384x_create(hw, 0, 0, NULL);
+ hw->wlandev = wlandev;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ hw->pdev = pdev;
+ pdev->priv = wlandev;
+#else
+ hw->link = link;
+ link->priv = wlandev;
+#endif
+
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.ConfigBase = parse->config.base;
+ pdev->conf.Present = parse->config.rmask[0];
+#else
+ link->conf.ConfigBase = parse->config.base;
+ link->conf.Present = parse->config.rmask[0];
+
+ link->conf.Vcc = socketconf.Vcc;
+#endif
+ CS_CHECK(GetConfigurationInfo,
+ pcmcia_get_configuration_info(pdev, &socketconf));
+
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
+ for (;;) {
+ cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
+ CFG_CHECK(GetTupleData,
+ pcmcia_get_tuple_data(pdev, &tuple));
+ CFG_CHECK(ParseTuple,
+ pcmcia_parse_tuple(pdev, &tuple, parse));
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ if (cfg->index == 0)
+ goto next_entry;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.ConfigIndex = cfg->index;
+#else
+ link->conf.ConfigIndex = cfg->index;
+#endif
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.Attributes |= CONF_ENABLE_SPKR;
+ pdev->conf.Status = CCSR_AUDIO_ENA;
+#else
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+#endif
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !prism2_ignorevcc) {
+ WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping"
+ " this entry\n");
+ goto next_entry;
+ }
+ } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !prism2_ignorevcc) {
+ WLAN_LOG_DEBUG(1, " Vcc (default) mismatch "
+ "- skipping this entry\n");
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.Vpp =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+#else
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+#endif
+ } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.Vpp =
+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+#else
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+#endif
+ }
+
+ /* Do we need to allocate an interrupt? */
+ /* HACK: due to a bad CIS....we ALWAYS need an interrupt */
+ /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->conf.Attributes |= CONF_ENABLE_IRQ;
+#else
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+#endif
+
+ /* IO window settings */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ pdev->io.BasePort1 = io->win[0].base;
+ if ( pdev->io.BasePort1 != 0 ) {
+ WLAN_LOG_WARNING(
+ "Brain damaged CIS: hard coded iobase="
+ "0x%x, try letting pcmcia_cs decide...\n",
+ pdev->io.BasePort1 );
+ pdev->io.BasePort1 = 0;
+ }
+ pdev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ pdev->io.Attributes2 = pdev->io.Attributes1;
+ pdev->io.BasePort2 = io->win[1].base;
+ pdev->io.NumPorts2 = io->win[1].len;
+ }
+ }
+ /* This reserves IO space but doesn't actually enable it */
+ CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io));
+#else
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.BasePort1 = io->win[0].base;
+ if ( link->io.BasePort1 != 0 ) {
+ WLAN_LOG_WARNING(
+ "Brain damaged CIS: hard coded iobase="
+ "0x%x, try letting pcmcia_cs decide...\n",
+ link->io.BasePort1 );
+ link->io.BasePort1 = 0;
+ }
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 = link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ link->io.NumPorts2 = io->win[1].len;
+ }
+ }
+ /* This reserves IO space but doesn't actually enable it */
+ CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io));
+#endif
+ /* If we got this far, we're cool! */
+ break;
+
+ next_entry:
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple));
+
+ }
+
+ /* Let pcmcia know the device name */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->dev_node = &hw->node;
+#else
+ link->dev = &hw->node;
+#endif
+
+ /* Register the network device and get assigned a name */
+ SET_MODULE_OWNER(wlandev->netdev);
+ SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev));
+ if (register_wlandev(wlandev) != 0) {
+ WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
+ goto failed;
+ }
+
+ strcpy(hw->node.dev_name, wlandev->name);
+
+ /* Allocate an interrupt line. Note that this does not assign a */
+ /* handler to the interrupt, unless the 'Handler' member of the */
+ /* irq structure is initialized. */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ if (pdev->conf.Attributes & CONF_ENABLE_IRQ) {
+ pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ pdev->irq.Handler = hfa384x_interrupt;
+ pdev->irq.Instance = wlandev;
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
+ }
+#else
+ if (link->conf.Attributes & CONF_ENABLE_IRQ) {
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Handler = hfa384x_interrupt;
+ link->irq.Instance = wlandev;
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq));
+ }
+#endif
+
+ /* This actually configures the PCMCIA socket -- setting up */
+ /* the I/O windows and the interrupt mapping, and putting the */
+ /* card and host interface into "Memory and IO" mode. */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
+#else
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf));
+#endif
+
+ /* Fill the netdevice with this info */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ wlandev->netdev->irq = pdev->irq.AssignedIRQ;
+ wlandev->netdev->base_addr = pdev->io.BasePort1;
+#else
+ wlandev->netdev->irq = link->irq.AssignedIRQ;
+ wlandev->netdev->base_addr = link->io.BasePort1;
+#endif
+
+ /* And the rest of the hw structure */
+ hw->irq = wlandev->netdev->irq;
+ hw->iobase = wlandev->netdev->base_addr;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ link->state |= DEV_CONFIG;
+ link->state &= ~DEV_CONFIG_PENDING;
+#endif
+
+ /* And now we're done! */
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+
+ goto done;
+
+ cs_failed:
+ cs_error(pdev, last_fn, last_ret);
+
+failed:
+ // wlandev, hw, etc etc..
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ pdev->priv = NULL;
+#else
+ pdev->instance = NULL;
+ if (link) {
+ link->priv = NULL;
+ kfree(link);
+ }
+#endif
+ if (wlandev) {
+ wlan_unsetup(wlandev);
+ if (wlandev->priv) {
+ hw = wlandev->priv;
+ wlandev->priv = NULL;
+ if (hw) {
+ hfa384x_destroy(hw);
+ kfree(hw);
+ }
+ }
+ kfree(wlandev);
+ }
+
+done:
+ if (parse) kfree(parse);
+
+ DBFEXIT;
+ return rval;
+}
+#else // <= 2.6.15
+#define CS_CHECK(fn, ret) \
+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+#define CFG_CHECK(fn, retf) \
+do { int ret = (retf); \
+if (ret != 0) { \
+ WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
+ cs_error(link->handle, fn, ret); \
+ goto next_entry; \
+} \
+} while (0)
+
+/*----------------------------------------------------------------
+* prism2sta_attach
+*
+* Half of the attach/detach pair. Creates and registers a device
+* instance with Card Services. In this case, it also creates the
+* wlandev structure and device private structure. These are
+* linked to the device instance via its priv member.
+*
+* Arguments:
+* none
+*
+* Returns:
+* A valid ptr to dev_link_t on success, NULL otherwise
+*
+* Side effects:
+*
+*
+* Call context:
+* process thread (insmod/init_module/register_pccard_driver)
+----------------------------------------------------------------*/
+dev_link_t *prism2sta_attach(void)
+{
+ client_reg_t client_reg;
+ int result;
+ dev_link_t *link = NULL;
+ wlandevice_t *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+
+ DBFENTER;
+
+ /* Alloc our structures */
+ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+
+ if (!link || ((wlandev = create_wlan()) == NULL)) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+ hw = wlandev->priv;
+
+ /* Clear all the structs */
+ memset(link, 0, sizeof(struct dev_link_t));
+
+ if ( wlan_setup(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+ /* Initialize the hw struct for now */
+ hfa384x_create(hw, 0, 0, NULL);
+ hw->wlandev = wlandev;
+
+ /* Initialize the PC card device object. */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ init_timer(&link->release);
+ link->release.function = &prism2sta_release;
+ link->release.data = (u_long)link;
+#endif
+ link->conf.IntType = INT_MEMORY_AND_IO;
+ link->priv = wlandev;
+#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
+ link->irq.Instance = wlandev;
+#endif
+
+ /* Link in to the list of devices managed by this driver */
+ link->next = dev_list;
+ dev_list = link;
+
+ /* Register with Card Services */
+ client_reg.dev_info = &dev_info;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_REQUEST |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &prism2sta_event;
+#endif
+
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+
+ result = pcmcia_register_client(&link->handle, &client_reg);
+ if (result != 0) {
+ cs_error(link->handle, RegisterClient, result);
+ prism2sta_detach(link);
+ return NULL;
+ }
+
+ goto done;
+
+ failed:
+ if (link) kfree(link);
+ if (wlandev) kfree(wlandev);
+ if (hw) kfree(hw);
+ link = NULL;
+
+ done:
+ DBFEXIT;
+ return link;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_detach
+*
+* Remove one of the device instances managed by this driver.
+* Search the list for the given instance,
+* check our flags for a waiting timer'd release call
+* call release
+* Deregister the instance with Card Services
+* (netdevice) unregister the network device.
+* unlink the instance from the list
+* free the link, priv, and priv->priv memory
+* Note: the dev_list variable is a driver scoped static used to
+* maintain a list of device instances managed by this
+* driver.
+*
+* Arguments:
+* link ptr to the instance to detach
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* the link structure is gone, the netdevice is gone
+*
+* Call context:
+* Might be interrupt, don't block.
+----------------------------------------------------------------*/
+void prism2sta_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+ wlandevice_t *wlandev;
+ hfa384x_t *hw;
+
+ DBFENTER;
+
+ /* Locate prev device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
+ if (*linkp == link) break;
+ }
+
+ if (*linkp != NULL) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+ unsigned long flags;
+ /* Get rid of any timer'd release call */
+ save_flags(flags);
+ cli();
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ if (link->state & DEV_RELEASE_PENDING) {
+ del_timer_sync(&link->release);
+ link->state &= ~DEV_RELEASE_PENDING;
+ }
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+ restore_flags(flags);
+#endif
+
+ /* If link says we're still config'd, call release */
+ if (link->state & DEV_CONFIG) {
+ prism2sta_release((u_long)link);
+ if (link->state & DEV_STALE_CONFIG) {
+ link->state |= DEV_STALE_LINK;
+ return;
+ }
+ }
+
+ /* Tell Card Services we're not around any more */
+ if (link->handle) {
+ pcmcia_deregister_client(link->handle);
+ }
+
+ /* Unlink device structure, free bits */
+ *linkp = link->next;
+ if ( link->priv != NULL ) {
+ wlandev = (wlandevice_t*)link->priv;
+ p80211netdev_hwremoved(wlandev);
+ if (link->dev != NULL) {
+ unregister_wlandev(wlandev);
+ }
+ wlan_unsetup(wlandev);
+ if (wlandev->priv) {
+ hw = wlandev->priv;
+ wlandev->priv = NULL;
+ if (hw) {
+ hfa384x_destroy(hw);
+ kfree(hw);
+ }
+ }
+ link->priv = NULL;
+ kfree(wlandev);
+ }
+ kfree(link);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_config
+*
+* Half of the config/release pair. Usually called in response to
+* a card insertion event. At this point, we _know_ there's some
+* physical device present. That means we can start poking around
+* at the CIS and at any device specific config data we want.
+*
+* Note the gotos and the macros. I recoded this once without
+* them, and it got incredibly ugly. It's actually simpler with
+* them.
+*
+* Arguments:
+* link the dev_link_t structure created in attach that
+* represents this device instance.
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* Resources (irq, io, mem) are allocated
+* The pcmcia dev_link->node->name is set
+* (For netcards) The device structure is finished and,
+* most importantly, registered. This means that there
+* is now a _named_ device that can be configured from
+* userland.
+*
+* Call context:
+* May be called from a timer. Don't block!
+----------------------------------------------------------------*/
+#define CS_CHECK(fn, ret) \
+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+#define CFG_CHECK(fn, retf) \
+do { int ret = (retf); \
+if (ret != 0) { \
+ WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
+ cs_error(link->handle, fn, ret); \
+ goto next_entry; \
+} \
+} while (0)
+
+void prism2sta_config(dev_link_t *link)
+{
+ client_handle_t handle;
+ wlandevice_t *wlandev;
+ hfa384x_t *hw;
+ int last_fn;
+ int last_ret;
+ tuple_t tuple;
+ cisparse_t parse;
+ config_info_t socketconf;
+ UINT8 buf[64];
+ int minVcc = 0;
+ int maxVcc = 0;
+ cistpl_cftable_entry_t dflt = { 0 };
+
+ DBFENTER;
+
+ handle = link->handle;
+ wlandev = (wlandevice_t*)link->priv;
+ hw = wlandev->priv;
+
+ /* Collect the config register info */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+
+ /* Acquire the current socket config (need Vcc setting) */
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf));
+
+ /* Loop through the config table entries until we find one that works */
+ /* Assumes a complete and valid CIS */
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ while (1) {
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+
+ if (cfg->index == 0) goto next_entry;
+ link->conf.ConfigIndex = cfg->index;
+
+ /* Lets print out the Vcc that the controller+pcmcia-cs set
+ * for us, cause that's what we're going to use.
+ */
+ WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc);
+ if (prism2_ignorevcc) {
+ link->conf.Vcc = socketconf.Vcc;
+ goto skipvcc;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n");
+ minVcc = maxVcc =
+ cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
+ } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n");
+ minVcc = maxVcc =
+ dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
+ } else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) &&
+ (cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
+ WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n"); minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000;
+ maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000;
+ } else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) &&
+ (dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
+ WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n");
+ minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000;
+ maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000;
+ }
+
+ if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) {
+ link->conf.Vcc = socketconf.Vcc;
+ } else {
+ /* [MSM]: Note that I've given up trying to change
+ * the Vcc if a change is indicated. It seems the
+ * system&socketcontroller&card vendors can't seem
+ * to get it right, so I'm tired of trying to hack
+ * my way around it. pcmcia-cs does its best using
+ * the voltage sense pins but sometimes the controller
+ * lies. Then, even if we have a good read on the VS
+ * pins, some system designs will silently ignore our
+ * requests to set the voltage. Additionally, some
+ * vendors have 3.3v indicated on their sense pins,
+ * but 5v specified in the CIS or vice-versa. I've
+ * had it. My only recommendation is "let the buyer
+ * beware". Your system might supply 5v to a 3v card
+ * (possibly causing damage) or a 3v capable system
+ * might supply 5v to a 3v capable card (wasting
+ * precious battery life).
+ * My only recommendation (if you care) is to get
+ * yourself an extender card (I don't know where, I
+ * have only one myself) and a meter and test it for
+ * yourself.
+ */
+ goto next_entry;
+ }
+skipvcc:
+ WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc);
+
+ /* Do we need to allocate an interrupt? */
+ /* HACK: due to a bad CIS....we ALWAYS need an interrupt */
+ /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.BasePort1 = io->win[0].base;
+ if ( link->io.BasePort1 != 0 ) {
+ WLAN_LOG_WARNING(
+ "Brain damaged CIS: hard coded iobase="
+ "0x%x, try letting pcmcia_cs decide...\n",
+ link->io.BasePort1 );
+ link->io.BasePort1 = 0;
+ }
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 = link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ link->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+
+ /* If we got this far, we're cool! */
+ break;
+
+next_entry:
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ CS_CHECK(GetNextTuple,
+ pcmcia_get_next_tuple(handle, &tuple));
+ }
+
+ /* Allocate an interrupt line. Note that this does not assign a */
+ /* handler to the interrupt, unless the 'Handler' member of the */
+ /* irq structure is initialized. */
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
+ int i;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i=0; i<4; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+#else
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+#endif
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Handler = hfa384x_interrupt;
+ link->irq.Instance = wlandev;
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ }
+
+ /* This actually configures the PCMCIA socket -- setting up */
+ /* the I/O windows and the interrupt mapping, and putting the */
+ /* card and host interface into "Memory and IO" mode. */
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+
+ /* Fill the netdevice with this info */
+ wlandev->netdev->irq = link->irq.AssignedIRQ;
+ wlandev->netdev->base_addr = link->io.BasePort1;
+
+ /* Report what we've done */
+ WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d",
+ dev_info, link->conf.ConfigIndex,
+ link->conf.Vcc/10, link->conf.Vcc%10);
+ if (link->conf.Vpp1)
+ printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ printk(", irq %d", link->irq.AssignedIRQ);
+ if (link->io.NumPorts1)
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1);
+ if (link->io.NumPorts2)
+ printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1);
+ printk("\n");
+
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ /* Let pcmcia know the device name */
+ link->dev = &hw->node;
+
+ /* Register the network device and get assigned a name */
+ SET_MODULE_OWNER(wlandev->netdev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) )
+ SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle));
+#endif
+ if (register_wlandev(wlandev) != 0) {
+ WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
+ goto failed;
+ }
+
+ strcpy(hw->node.dev_name, wlandev->name);
+
+ /* Any device custom config/query stuff should be done here */
+ /* For a netdevice, we should at least grab the mac address */
+
+ return;
+cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+ WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n");
+
+failed:
+ prism2sta_release((u_long)link);
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_release
+*
+* Half of the config/release pair. Usually called in response to
+* a card ejection event. Checks to make sure no higher layers
+* are still (or think they are) using the card via the link->open
+* field.
+*
+* NOTE: Don't forget to increment the link->open variable in the
+* device_open method, and decrement it in the device_close
+* method.
+*
+* Arguments:
+* arg a generic 32 bit variable. It's the value that
+* we assigned to link->release.data in sta_attach().
+*
+* Returns:
+* nothing
+*
+* Side effects:
+* All resources should be released after this function
+* executes and finds the device !open.
+*
+* Call context:
+* Possibly in a timer context. Don't do anything that'll
+* block.
+----------------------------------------------------------------*/
+void prism2sta_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+
+ DBFENTER;
+
+ /* First thing we should do is get the MSD back to the
+ * HWPRESENT state. I.e. everything quiescent.
+ */
+ prism2sta_ifstate(link->priv, P80211ENUM_ifstate_disable);
+
+ if (link->open) {
+ /* TODO: I don't think we're even using this bit of code
+ * and I don't think it's hurting us at the moment.
+ */
+ WLAN_LOG_DEBUG(1,
+ "prism2sta_cs: release postponed, '%s' still open\n",
+ link->dev->dev_name);
+ link->state |= DEV_STALE_CONFIG;
+ return;
+ }
+
+ pcmcia_release_configuration(link->handle);
+ pcmcia_release_io(link->handle, &link->io);
+ pcmcia_release_irq(link->handle, &link->irq);
+
+ link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_event
+*
+* Handler for card services events.
+*
+* Arguments:
+* event The event code
+* priority hi/low - REMOVAL is the only hi
+* args ptr to card services struct containing info about
+* pcmcia status
+*
+* Returns:
+* Zero on success, non-zero otherwise
+*
+* Side effects:
+*
+*
+* Call context:
+* Both interrupt and process thread, depends on the event.
+----------------------------------------------------------------*/
+static int
+prism2sta_event (
+ event_t event,
+ int priority,
+ event_callback_args_t *args)
+{
+ int result = 0;
+ dev_link_t *link = (dev_link_t *) args->client_data;
+ wlandevice_t *wlandev = (wlandevice_t*)link->priv;
+ hfa384x_t *hw = NULL;
+
+ DBFENTER;
+
+ if (wlandev) hw = wlandev->priv;
+
+ switch (event)
+ {
+ case CS_EVENT_CARD_INSERTION:
+ WLAN_LOG_DEBUG(5,"event is INSERTION\n");
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ prism2sta_config(link);
+ if (!(link->state & DEV_CONFIG)) {
+ wlandev->netdev->irq = 0;
+ WLAN_LOG_ERROR(
+ "%s: Initialization failed!\n", dev_info);
+ wlandev->msdstate = WLAN_MSD_HWFAIL;
+ break;
+ }
+
+ /* Fill in the rest of the hw struct */
+ hw->irq = wlandev->netdev->irq;
+ hw->iobase = wlandev->netdev->base_addr;
+ hw->link = link;
+
+ if (prism2_doreset) {
+ result = hfa384x_corereset(hw,
+ prism2_reset_holdtime,
+ prism2_reset_settletime, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR(
+ "corereset() failed, result=%d.\n",
+ result);
+ wlandev->msdstate = WLAN_MSD_HWFAIL;
+ break;
+ }
+ }
+
+#if 0
+ /*
+ * TODO: test_hostif() not implemented yet.
+ */
+ result = hfa384x_test_hostif(hw);
+ if (result) {
+ WLAN_LOG_ERROR(
+ "test_hostif() failed, result=%d.\n", result);
+ wlandev->msdstate = WLAN_MSD_HWFAIL;
+ break;
+ }
+#endif
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ break;
+
+ case CS_EVENT_CARD_REMOVAL:
+ WLAN_LOG_DEBUG(5,"event is REMOVAL\n");
+ link->state &= ~DEV_PRESENT;
+
+ if (wlandev) {
+ p80211netdev_hwremoved(wlandev);
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ if (link->state & DEV_CONFIG)
+ {
+ link->release.expires = jiffies + (HZ/20);
+ add_timer(&link->release);
+ }
+#endif
+ break;
+ case CS_EVENT_RESET_REQUEST:
+ WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n");
+ WLAN_LOG_NOTICE(
+ "prism2 card reset not supported "
+ "due to post-reset user mode configuration "
+ "requirements.\n");
+ WLAN_LOG_NOTICE(
+ " From user mode, use "
+ "'cardctl suspend;cardctl resume' "
+ "instead.\n");
+ break;
+ case CS_EVENT_RESET_PHYSICAL:
+ case CS_EVENT_CARD_RESET:
+ WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not "
+ "be possible since RESET_REQUEST was denied.\n");
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ WLAN_LOG_DEBUG(5,"event is SUSPEND\n");
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ {
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ WLAN_LOG_DEBUG(5,"event is RESUME\n");
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ }
+ break;
+ }
+
+ DBFEXIT;
+ return 0; /* noone else does anthing with the return value */
+}
+#endif // <= 2.6.15
+
+
+
+int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
+{
+ int result = 0;
+ conf_reg_t reg;
+ UINT8 corsave;
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n");
+
+ /* Collect COR */
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ result = pcmcia_access_configuration_register(hw->pdev, &reg);
+#else
+ result = pcmcia_access_configuration_register(
+ hw->link->handle,
+ &reg);
+#endif
+ if (result != CS_SUCCESS ) {
+ WLAN_LOG_ERROR(
+ ":0: AccessConfigurationRegister(CS_READ) failed,"
+ "result=%d.\n", result);
+ result = -EIO;
+ }
+ corsave = reg.Value;
+
+ /* Write reset bit (BIT7) */
+ reg.Value |= BIT7;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ result = pcmcia_access_configuration_register(hw->pdev, &reg);
+#else
+ result = pcmcia_access_configuration_register(
+ hw->link->handle,
+ &reg);
+#endif
+ if (result != CS_SUCCESS ) {
+ WLAN_LOG_ERROR(
+ ":1: AccessConfigurationRegister(CS_WRITE) failed,"
+ "result=%d.\n", result);
+ result = -EIO;
+ }
+
+ /* Hold for holdtime */
+ mdelay(holdtime);
+
+ if (genesis) {
+ reg.Value = genesis;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_CCSR;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ result = pcmcia_access_configuration_register(hw->pdev, &reg);
+#else
+ result = pcmcia_access_configuration_register(
+ hw->link->handle,
+ &reg);
+#endif
+ if (result != CS_SUCCESS ) {
+ WLAN_LOG_ERROR(
+ ":1: AccessConfigurationRegister(CS_WRITE) failed,"
+ "result=%d.\n", result);
+ result = -EIO;
+ }
+ }
+
+ /* Hold for holdtime */
+ mdelay(holdtime);
+
+ /* Clear reset bit */
+ reg.Value &= ~BIT7;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ result = pcmcia_access_configuration_register(hw->pdev, &reg);
+#else
+ result = pcmcia_access_configuration_register(
+ hw->link->handle,
+ &reg);
+#endif
+ if (result != CS_SUCCESS ) {
+ WLAN_LOG_ERROR(
+ ":2: AccessConfigurationRegister(CS_WRITE) failed,"
+ "result=%d.\n", result);
+ result = -EIO;
+ goto done;
+ }
+
+ /* Wait for settletime */
+ mdelay(settletime);
+
+ /* Set non-reset bits back what they were */
+ reg.Value = corsave;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
+ result = pcmcia_access_configuration_register(hw->pdev, &reg);
+#else
+ result = pcmcia_access_configuration_register(
+ hw->link->handle,
+ &reg);
+#endif
+ if (result != CS_SUCCESS ) {
+ WLAN_LOG_ERROR(
+ ":2: AccessConfigurationRegister(CS_WRITE) failed,"
+ "result=%d.\n", result);
+ result = -EIO;
+ goto done;
+ }
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+#ifdef MODULE
+
+static int __init prism2cs_init(void)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
+ servinfo_t serv;
+#endif
+
+ DBFENTER;
+
+ WLAN_LOG_NOTICE("%s Loaded\n", version);
+ WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
+ pcmcia_get_card_services_info(&serv);
+ if ( serv.Revision != CS_RELEASE_CODE )
+ {
+ printk(KERN_NOTICE"%s: CardServices release does not match!\n", dev_info);
+ return -1;
+ }
+
+ /* This call will result in a call to prism2sta_attach */
+ /* and eventually prism2sta_detach */
+ register_pccard_driver( &dev_info, &prism2sta_attach, &prism2sta_detach);
+#else
+ pcmcia_register_driver(&prism2_cs_driver);
+#endif
+
+ DBFEXIT;
+ return 0;
+}
+
+static void __exit prism2cs_cleanup(void)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
+ dev_link_t *link = dev_list;
+ dev_link_t *nlink;
+ DBFENTER;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
+ for (link=dev_list; link != NULL; link = nlink) {
+ nlink = link->next;
+ if ( link->state & DEV_CONFIG ) {
+ prism2sta_release((u_long)link);
+ }
+ prism2sta_detach(link); /* remember detach() frees link */
+ }
+#endif
+
+ unregister_pccard_driver( &dev_info);
+#else
+ pcmcia_unregister_driver(&prism2_cs_driver);
+#endif
+
+ printk(KERN_NOTICE "%s Unloaded\n", version);
+
+ DBFEXIT;
+ return;
+}
+
+module_init(prism2cs_init);
+module_exit(prism2cs_cleanup);
+
+#endif // MODULE
+
diff --git a/drivers/staging/wlan-ng/prism2_pci.c b/drivers/staging/wlan-ng/prism2_pci.c
new file mode 100644
index 00000000000..afe32dfbf6b
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2_pci.c
@@ -0,0 +1,332 @@
+#define WLAN_HOSTIF WLAN_PCI
+#include "hfa384x.c"
+#include "prism2mgmt.c"
+#include "prism2mib.c"
+#include "prism2sta.c"
+
+#define PCI_SIZE 0x1000 /* Memory size - 4K bytes */
+
+/* ISL3874A 11Mb/s WLAN controller */
+#define PCIVENDOR_INTERSIL 0x1260UL
+#define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says
+ 3873. Trust me, it's a 3874. */
+
+/* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */
+#define PCIVENDOR_SAMSUNG 0x167dUL
+#define PCIDEVICE_SWL_2210P 0xa000UL
+
+#define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 */
+
+/* PCI Class & Sub-Class code, Network-'Other controller' */
+#define PCI_CLASS_NETWORK_OTHERS 0x280
+
+
+/*----------------------------------------------------------------
+* prism2sta_probe_pci
+*
+* Probe routine called when a PCI device w/ matching ID is found.
+* The ISL3874 implementation uses the following map:
+* BAR0: Prism2.x registers memory mapped, size=4k
+* Here's the sequence:
+* - Allocate the PCI resources.
+* - Read the PCMCIA attribute memory to make sure we have a WLAN card
+* - Reset the MAC
+* - Initialize the netdev and wlan data
+* - Initialize the MAC
+*
+* Arguments:
+* pdev ptr to pci device structure containing info about
+* pci configuration.
+* id ptr to the device id entry that matched this device.
+*
+* Returns:
+* zero - success
+* negative - failed
+*
+* Side effects:
+*
+*
+* Call context:
+* process thread
+*
+----------------------------------------------------------------*/
+static int __devinit
+prism2sta_probe_pci(
+ struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int result;
+ phys_t phymem = 0;
+ void __iomem *mem = NULL;
+ wlandevice_t *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+
+ DBFENTER;
+
+ /* Enable the pci device */
+ if (pci_enable_device(pdev)) {
+ WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info);
+ result = -EIO;
+ goto fail;
+ }
+
+ /* Figure out our resources */
+ phymem = pci_resource_start(pdev, 0);
+
+ if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
+ printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
+ result = -EIO;
+ goto fail;
+ }
+
+ mem = ioremap(phymem, PCI_SIZE);
+ if ( mem == 0 ) {
+ WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info);
+ result = -EIO;
+ goto fail;
+ }
+
+ /* Log the device */
+ WLAN_LOG_INFO("A Prism2.5 PCI device found, "
+ "phymem:0x%llx, irq:%d, mem:0x%p\n",
+ (unsigned long long)phymem, pdev->irq, mem);
+
+ if ((wlandev = create_wlan()) == NULL) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ result = -EIO;
+ goto fail;
+ }
+ hw = wlandev->priv;
+
+ if ( wlan_setup(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
+ result = -EIO;
+ goto fail;
+ }
+
+ /* Setup netdevice's ability to report resources
+ * Note: the netdevice was allocated by wlan_setup()
+ */
+ wlandev->netdev->irq = pdev->irq;
+ wlandev->netdev->mem_start = (unsigned long) mem;
+ wlandev->netdev->mem_end = wlandev->netdev->mem_start +
+ pci_resource_len(pdev, 0);
+
+ /* Initialize the hw data */
+ hfa384x_create(hw, wlandev->netdev->irq, 0, mem);
+ hw->wlandev = wlandev;
+
+ /* Register the wlandev, this gets us a name and registers the
+ * linux netdevice.
+ */
+ SET_MODULE_OWNER(wlandev->netdev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));
+#endif
+ if ( register_wlandev(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
+ result = -EIO;
+ goto fail;
+ }
+
+#if 0
+ /* TODO: Move this and an irq test into an hfa384x_testif() routine.
+ */
+ outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
+ reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
+ if ( reg != PRISM2STA_MAGIC ) {
+ WLAN_LOG_ERROR("MAC register access test failed!\n");
+ result = -EIO;
+ goto fail;
+ }
+#endif
+
+ /* Do a chip-level reset on the MAC */
+ if (prism2_doreset) {
+ result = hfa384x_corereset(hw,
+ prism2_reset_holdtime,
+ prism2_reset_settletime, 0);
+ if (result != 0) {
+ WLAN_LOG_ERROR(
+ "%s: hfa384x_corereset() failed.\n",
+ dev_info);
+ unregister_wlandev(wlandev);
+ hfa384x_destroy(hw);
+ result = -EIO;
+ goto fail;
+ }
+ }
+
+ pci_set_drvdata(pdev, wlandev);
+
+ /* Shouldn't actually hook up the IRQ until we
+ * _know_ things are alright. A test routine would help.
+ */
+ request_irq(wlandev->netdev->irq, hfa384x_interrupt,
+ SA_SHIRQ, wlandev->name, wlandev);
+
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+
+ result = 0;
+ goto done;
+
+ fail:
+ pci_set_drvdata(pdev, NULL);
+ if (wlandev) kfree(wlandev);
+ if (hw) kfree(hw);
+ if (mem) iounmap(mem);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ done:
+ DBFEXIT;
+ return result;
+}
+
+static void __devexit prism2sta_remove_pci(struct pci_dev *pdev)
+{
+ wlandevice_t *wlandev;
+ hfa384x_t *hw;
+
+ wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
+ hw = wlandev->priv;
+
+ p80211netdev_hwremoved(wlandev);
+
+ /* reset hardware */
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+
+ if (pdev->irq)
+ free_irq(pdev->irq, wlandev);
+
+ unregister_wlandev(wlandev);
+
+ /* free local stuff */
+ if (hw) {
+ hfa384x_destroy(hw);
+ kfree(hw);
+ }
+
+ iounmap((void __iomem *)wlandev->netdev->mem_start);
+ wlan_unsetup(wlandev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ kfree(wlandev);
+}
+
+
+static struct pci_device_id pci_id_tbl[] = {
+ {
+ PCIVENDOR_INTERSIL, PCIDEVICE_ISL3874,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller"
+ },
+ {
+ PCIVENDOR_INTERSIL, 0x3872,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller"
+ },
+ {
+ PCIVENDOR_SAMSUNG, PCIDEVICE_SWL_2210P,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller"
+ },
+ { /* for NetGear MA311 */
+ PCIVENDOR_NETGEAR, 0x3872,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Netgear MA311 WLAN Controller"
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0
+ }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_id_tbl);
+
+/* Function declared here because of ptr reference below */
+static int __devinit prism2sta_probe_pci(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+static void __devexit prism2sta_remove_pci(struct pci_dev *pdev);
+
+static struct pci_driver prism2_pci_drv_id = {
+ .name = "prism2_pci",
+ .id_table = pci_id_tbl,
+ .probe = prism2sta_probe_pci,
+ .remove = prism2sta_remove_pci,
+#ifdef CONFIG_PM
+ .suspend = prism2sta_suspend_pci,
+ .resume = prism2sta_resume_pci,
+#endif
+};
+
+#ifdef MODULE
+
+static int __init prism2pci_init(void)
+{
+ WLAN_LOG_NOTICE("%s Loaded\n", version);
+ return pci_module_init(&prism2_pci_drv_id);
+};
+
+static void __exit prism2pci_cleanup(void)
+{
+ pci_unregister_driver(&prism2_pci_drv_id);
+};
+
+module_init(prism2pci_init);
+module_exit(prism2pci_cleanup);
+
+#endif
+
+int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
+{
+ int result = 0;
+ unsigned long timeout;
+ UINT16 reg;
+ DBFENTER;
+
+ /* Assert reset and wait awhile
+ * (note: these delays are _really_ long, but they appear to be
+ * necessary.)
+ */
+ hfa384x_setreg(hw, 0xc5, HFA384x_PCICOR);
+ timeout = jiffies + HZ/4;
+ while(time_before(jiffies, timeout)) udelay(5);
+
+ if (genesis) {
+ hfa384x_setreg(hw, genesis, HFA384x_PCIHCR);
+ timeout = jiffies + HZ/4;
+ while(time_before(jiffies, timeout)) udelay(5);
+ }
+
+ /* Clear the reset and wait some more
+ */
+ hfa384x_setreg(hw, 0x45, HFA384x_PCICOR);
+ timeout = jiffies + HZ/2;
+ while(time_before(jiffies, timeout)) udelay(5);
+
+ /* Wait for f/w to complete initialization (CMD:BUSY == 0)
+ */
+ timeout = jiffies + 2*HZ;
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ udelay(10);
+ }
+ if (HFA384x_CMD_ISBUSY(reg)) {
+ WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n");
+ result=1;
+ }
+ DBFEXIT;
+ return result;
+}
diff --git a/drivers/staging/wlan-ng/prism2_plx.c b/drivers/staging/wlan-ng/prism2_plx.c
new file mode 100644
index 00000000000..320443f37a8
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2_plx.c
@@ -0,0 +1,472 @@
+#define WLAN_HOSTIF WLAN_PLX
+#include "hfa384x.c"
+#include "prism2mgmt.c"
+#include "prism2mib.c"
+#include "prism2sta.c"
+
+#define PLX_ATTR_SIZE 0x1000 /* Attribute memory size - 4K bytes */
+#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */
+#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */
+#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
+#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */
+
+/* 3Com 3CRW777A (PLX) board ID */
+#define PCIVENDOR_3COM 0x10B7
+#define PCIDEVICE_AIRCONNECT 0x7770
+
+/* Eumitcom PCI WL11000 PCI Adapter (PLX) board device+vendor ID */
+#define PCIVENDOR_EUMITCOM 0x1638UL
+#define PCIDEVICE_WL11000 0x1100UL
+
+/* Global Sun Tech GL24110P PCI Adapter (PLX) board device+vendor ID */
+#define PCIVENDOR_GLOBALSUN 0x16abUL
+#define PCIDEVICE_GL24110P 0x1101UL
+#define PCIDEVICE_GL24110P_ALT 0x1102UL
+
+/* Netgear MA301 PCI Adapter (PLX) board device+vendor ID */
+#define PCIVENDOR_NETGEAR 0x1385UL
+#define PCIDEVICE_MA301 0x4100UL
+
+/* US Robotics USR2410 PCI Adapter (PLX) board device+vendor ID */
+#define PCIVENDOR_USROBOTICS 0x16ecUL
+#define PCIDEVICE_USR2410 0x3685UL
+
+/* Linksys WPC11 card with the WDT11 adapter (PLX) board device+vendor ID */
+#define PCIVENDOR_Linksys 0x16abUL
+#define PCIDEVICE_Wpc11Wdt11 0x1102UL
+
+/* National Datacomm Corp SOHOware Netblaster II PCI */
+#define PCIVENDOR_NDC 0x15e8UL
+#define PCIDEVICE_NCP130_PLX 0x0130UL
+#define PCIDEVICE_NCP130_ASIC 0x0131UL
+
+/* NDC NCP130_PLX is also sold by Corega. Their name is CGWLPCIA11 */
+#define PCIVENDOR_COREGA PCIVENDOR_NDC
+#define PCIDEVICE_CGWLPCIA11 PCIDEVICE_NCP130_PLX
+
+/* PCI Class & Sub-Class code, Network-'Other controller' */
+#define PCI_CLASS_NETWORK_OTHERS 0x280
+
+/*----------------------------------------------------------------
+* prism2sta_probe_plx
+*
+* Probe routine called when a PCI device w/ matching ID is found.
+* This PLX implementation uses the following map:
+* BAR0: Unused
+* BAR1: ????
+* BAR2: PCMCIA attribute memory
+* BAR3: PCMCIA i/o space
+* Here's the sequence:
+* - Allocate the PCI resources.
+* - Read the PCMCIA attribute memory to make sure we have a WLAN card
+* - Reset the MAC using the PCMCIA COR
+* - Initialize the netdev and wlan data
+* - Initialize the MAC
+*
+* Arguments:
+* pdev ptr to pci device structure containing info about
+* pci configuration.
+* id ptr to the device id entry that matched this device.
+*
+* Returns:
+* zero - success
+* negative - failed
+*
+* Side effects:
+*
+*
+* Call context:
+* process thread
+*
+----------------------------------------------------------------*/
+static int __devinit
+prism2sta_probe_plx(
+ struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int result;
+ phys_t pccard_ioaddr;
+ phys_t pccard_attr_mem;
+ unsigned int pccard_attr_len;
+ void __iomem *attr_mem = NULL;
+ UINT32 plx_addr;
+ wlandevice_t *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+ int reg;
+ u32 regic;
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ /* TMC7160 boards are special */
+ if ((pdev->vendor == PCIVENDOR_NDC) &&
+ (pdev->device == PCIDEVICE_NCP130_ASIC)) {
+ unsigned long delay;
+
+ pccard_attr_mem = 0;
+ pccard_ioaddr = pci_resource_start(pdev, 1);
+
+ outb(0x45, pccard_ioaddr);
+ delay = jiffies + 1*HZ;
+ while (time_before(jiffies, delay));
+
+ if (inb(pccard_ioaddr) != 0x45) {
+ WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr));
+ return -EIO;
+ }
+
+ pccard_ioaddr = pci_resource_start(pdev, 2);
+ prism2_doreset = 0;
+
+ WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq);
+ goto init;
+ }
+
+ /* Collect the resource requirements */
+ pccard_attr_mem = pci_resource_start(pdev, 2);
+ pccard_attr_len = pci_resource_len(pdev, 2);
+ if (pccard_attr_len < PLX_MIN_ATTR_LEN)
+ return -EIO;
+
+ pccard_ioaddr = pci_resource_start(pdev, 3);
+
+ /* bjoern: We need to tell the card to enable interrupts, in
+ * case the serial eprom didn't do this already. See the
+ * PLX9052 data book, p8-1 and 8-24 for reference.
+ * [MSM]: This bit of code came from the orinoco_cs driver.
+ */
+ plx_addr = pci_resource_start(pdev, 1);
+
+ regic = 0;
+ regic = inl(plx_addr+PLX_INTCSR);
+ if(regic & PLX_INTCSR_INTEN) {
+ WLAN_LOG_DEBUG(1,
+ "%s: Local Interrupt already enabled\n", dev_info);
+ } else {
+ regic |= PLX_INTCSR_INTEN;
+ outl(regic, plx_addr+PLX_INTCSR);
+ regic = inl(plx_addr+PLX_INTCSR);
+ if(!(regic & PLX_INTCSR_INTEN)) {
+ WLAN_LOG_ERROR(
+ "%s: Couldn't enable Local Interrupts\n",
+ dev_info);
+ return -EIO;
+ }
+ }
+
+ /* These assignments are here in case of future mappings for
+ * io space and irq that might be similar to ioremap
+ */
+ if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) {
+ WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info);
+ return -EIO;
+ }
+
+ attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);
+
+ WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, "
+ "phymem:0x%llx, phyio=0x%x, irq:%d, "
+ "mem: 0x%lx\n",
+ (unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq,
+ (unsigned long)attr_mem);
+
+ /* Verify whether PC card is present.
+ * [MSM] This needs improvement, the right thing to do is
+ * probably to walk the CIS looking for the vendor and product
+ * IDs. It would be nice if this could be tied in with the
+ * etc/pcmcia/wlan-ng.conf file. Any volunteers? ;-)
+ */
+ if (
+ readb(attr_mem + 0) != 0x01 || readb(attr_mem + 2) != 0x03 ||
+ readb(attr_mem + 4) != 0x00 || readb(attr_mem + 6) != 0x00 ||
+ readb(attr_mem + 8) != 0xFF || readb(attr_mem + 10) != 0x17 ||
+ readb(attr_mem + 12) != 0x04 || readb(attr_mem + 14) != 0x67) {
+ WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n");
+ return -EIO;
+ }
+ WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n");
+
+ /* Write COR to enable PC card */
+ writeb(COR_VALUE, attr_mem + COR_OFFSET);
+ reg = readb(attr_mem + COR_OFFSET);
+
+ init:
+
+ /*
+ * Now do everything the same as a PCI device
+ * [MSM] TODO: We could probably factor this out of pcmcia/pci/plx
+ * and perhaps usb. Perhaps a task for another day.......
+ */
+
+ if ((wlandev = create_wlan()) == NULL) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+ hw = wlandev->priv;
+
+ if ( wlan_setup(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+ /* Setup netdevice's ability to report resources
+ * Note: the netdevice was allocated by wlan_setup()
+ */
+ wlandev->netdev->irq = pdev->irq;
+ wlandev->netdev->base_addr = pccard_ioaddr;
+ wlandev->netdev->mem_start = (unsigned long)attr_mem;
+ wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0);
+
+ /* Initialize the hw data */
+ hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_mem);
+ hw->wlandev = wlandev;
+
+ /* Register the wlandev, this gets us a name and registers the
+ * linux netdevice.
+ */
+ SET_MODULE_OWNER(wlandev->netdev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));
+#endif
+ if ( register_wlandev(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+#if 0
+ /* TODO: Move this and an irq test into an hfa384x_testif() routine.
+ */
+ outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
+ reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
+ if ( reg != PRISM2STA_MAGIC ) {
+ WLAN_LOG_ERROR("MAC register access test failed!\n");
+ result = -EIO;
+ goto failed;
+ }
+#endif
+
+ /* Do a chip-level reset on the MAC */
+ if (prism2_doreset) {
+ result = hfa384x_corereset(hw,
+ prism2_reset_holdtime,
+ prism2_reset_settletime, 0);
+ if (result != 0) {
+ unregister_wlandev(wlandev);
+ hfa384x_destroy(hw);
+ WLAN_LOG_ERROR(
+ "%s: hfa384x_corereset() failed.\n",
+ dev_info);
+ result = -EIO;
+ goto failed;
+ }
+ }
+
+ pci_set_drvdata(pdev, wlandev);
+
+ /* Shouldn't actually hook up the IRQ until we
+ * _know_ things are alright. A test routine would help.
+ */
+ request_irq(wlandev->netdev->irq, hfa384x_interrupt,
+ SA_SHIRQ, wlandev->name, wlandev);
+
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+
+ result = 0;
+
+ goto done;
+
+ failed:
+
+ pci_set_drvdata(pdev, NULL);
+ if (wlandev) kfree(wlandev);
+ if (hw) kfree(hw);
+ if (attr_mem) iounmap(attr_mem);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ done:
+ DBFEXIT;
+ return result;
+}
+
+static void __devexit prism2sta_remove_plx(struct pci_dev *pdev)
+{
+ wlandevice_t *wlandev;
+ hfa384x_t *hw;
+
+ wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
+ hw = wlandev->priv;
+
+ p80211netdev_hwremoved(wlandev);
+
+ /* reset hardware */
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+
+ if (pdev->irq)
+ free_irq(pdev->irq, wlandev);
+
+ unregister_wlandev(wlandev);
+
+ /* free local stuff */
+ if (hw) {
+ hfa384x_destroy(hw);
+ kfree(hw);
+ }
+
+ iounmap((void __iomem *)wlandev->netdev->mem_start);
+ wlan_unsetup(wlandev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ kfree(wlandev);
+}
+
+static struct pci_device_id plx_id_tbl[] = {
+ {
+ PCIVENDOR_EUMITCOM, PCIDEVICE_WL11000,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Eumitcom WL11000 PCI(PLX) card"
+ },
+ {
+ PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
+ },
+ {
+ PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P_ALT,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
+ },
+ {
+ PCIVENDOR_NETGEAR, PCIDEVICE_MA301,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
+ },
+ {
+ PCIVENDOR_USROBOTICS, PCIDEVICE_USR2410,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"US Robotics USR2410 PCI(PLX) card"
+ },
+ {
+ PCIVENDOR_Linksys, PCIDEVICE_Wpc11Wdt11,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"Linksys WPC11 with WDT11 PCI(PLX) adapter"
+ },
+ {
+ PCIVENDOR_NDC, PCIDEVICE_NCP130_PLX,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"NDC Netblaster II PCI(PLX)"
+ },
+ {
+ PCIVENDOR_NDC, PCIDEVICE_NCP130_ASIC,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"NDC Netblaster II PCI(TMC7160)"
+ },
+ {
+ PCIVENDOR_3COM, PCIDEVICE_AIRCONNECT,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ /* Driver data, we just put the name here */
+ (unsigned long)"3Com AirConnect PCI 802.11b 11Mb/s WLAN Controller"
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0
+ }
+};
+
+MODULE_DEVICE_TABLE(pci, plx_id_tbl);
+
+/* Function declared here because of ptr reference below */
+static int __devinit prism2sta_probe_plx(struct pci_dev *pdev,
+ const struct pci_device_id *);
+static void __devexit prism2sta_remove_plx(struct pci_dev *pdev);
+
+static struct pci_driver prism2_plx_drv_id = {
+ .name = "prism2_plx",
+ .id_table = plx_id_tbl,
+ .probe = prism2sta_probe_plx,
+ .remove = prism2sta_remove_plx,
+#ifdef CONFIG_PM
+ .suspend = prism2sta_suspend_pci,
+ .resume = prism2sta_resume_pci,
+#endif
+};
+
+#ifdef MODULE
+
+static int __init prism2plx_init(void)
+{
+ WLAN_LOG_NOTICE("%s Loaded\n", version);
+ return pci_module_init(&prism2_plx_drv_id);
+};
+
+static void __exit prism2plx_cleanup(void)
+{
+ pci_unregister_driver(&prism2_plx_drv_id);
+};
+
+module_init(prism2plx_init);
+module_exit(prism2plx_cleanup);
+
+#endif // MODULE
+
+
+int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
+{
+ int result = 0;
+
+#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */
+
+#define HCR_OFFSET 0x3e2 /* HCR attribute offset of Prism2 PC card */
+
+ UINT8 corsave;
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(3, "Doing reset via direct COR access.\n");
+
+ /* Collect COR */
+ corsave = readb(hw->membase + COR_OFFSET);
+ /* Write reset bit (BIT7) */
+ writeb(corsave | BIT7, hw->membase + COR_OFFSET);
+ /* Hold for holdtime */
+ mdelay(holdtime);
+
+ if (genesis) {
+ writeb(genesis, hw->membase + HCR_OFFSET);
+ /* Hold for holdtime */
+ mdelay(holdtime);
+ }
+
+ /* Clear reset bit */
+ writeb(corsave & ~BIT7, hw->membase + COR_OFFSET);
+ /* Wait for settletime */
+ mdelay(settletime);
+ /* Set non-reset bits back what they were */
+ writeb(corsave, hw->membase + COR_OFFSET);
+ DBFEXIT;
+ return result;
+}
diff --git a/drivers/staging/wlan-ng/prism2_usb.c b/drivers/staging/wlan-ng/prism2_usb.c
new file mode 100644
index 00000000000..e45be237450
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2_usb.c
@@ -0,0 +1,361 @@
+#define WLAN_HOSTIF WLAN_USB
+#include "hfa384x_usb.c"
+#include "prism2mgmt.c"
+#include "prism2mib.c"
+#include "prism2sta.c"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#error "prism2_usb requires at least a 2.4.x kernel!"
+#endif
+
+#define PRISM_USB_DEVICE(vid, pid, name) \
+ USB_DEVICE(vid, pid), \
+ .driver_info = (unsigned long) name
+
+static struct usb_device_id usb_prism_tbl[] = {
+ {PRISM_USB_DEVICE(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS")},
+ {PRISM_USB_DEVICE(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11")},
+ {PRISM_USB_DEVICE(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x049f, 0x0033, "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")},
+ {PRISM_USB_DEVICE(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")},
+ {PRISM_USB_DEVICE(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x0967, 0x0204, "Acer Warplink USB Adapter")},
+ {PRISM_USB_DEVICE(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated")},
+ {PRISM_USB_DEVICE(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter")},
+ {PRISM_USB_DEVICE(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")},
+ {PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")},
+// {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter")},
+ {PRISM_USB_DEVICE(0x50c2, 0x4013, "Averatec USB WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter")},
+ {PRISM_USB_DEVICE(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x2821, 0x3300, "Hawking HighDB USB Adapter")},
+ {PRISM_USB_DEVICE(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter")},
+ {PRISM_USB_DEVICE(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter")},
+ {PRISM_USB_DEVICE(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter")},
+ {PRISM_USB_DEVICE(0x0bb2, 0x0302, "Ambit Microsystems Corp.")},
+ {PRISM_USB_DEVICE(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter")},
+ {PRISM_USB_DEVICE(0x0543, 0x0f01, "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)")},
+ { /* terminator */ }
+};
+
+MODULE_DEVICE_TABLE(usb, usb_prism_tbl);
+
+/*----------------------------------------------------------------
+* prism2sta_probe_usb
+*
+* Probe routine called by the USB subsystem.
+*
+* Arguments:
+* dev ptr to the usb_device struct
+* ifnum interface number being offered
+*
+* Returns:
+* NULL - we're not claiming the device+interface
+* non-NULL - we are claiming the device+interface and
+* this is a ptr to the data we want back
+* when disconnect is called.
+*
+* Side effects:
+*
+* Call context:
+* I'm not sure, assume it's interrupt.
+*
+----------------------------------------------------------------*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static void __devinit *prism2sta_probe_usb(
+ struct usb_device *dev,
+ unsigned int ifnum,
+ const struct usb_device_id *id)
+#else
+static int prism2sta_probe_usb(
+ struct usb_interface *interface,
+ const struct usb_device_id *id)
+#endif
+{
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ struct usb_interface *interface;
+#else
+ struct usb_device *dev;
+#endif
+
+ wlandevice_t *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+ int result = 0;
+
+ DBFENTER;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ interface = &dev->actconfig->interface[ifnum];
+#else
+ dev = interface_to_usbdev(interface);
+#endif
+
+
+ if ((wlandev = create_wlan()) == NULL) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+ hw = wlandev->priv;
+
+ if ( wlan_setup(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+ /* Initialize the hw data */
+ hfa384x_create(hw, dev);
+ hw->wlandev = wlandev;
+
+ /* Register the wlandev, this gets us a name and registers the
+ * linux netdevice.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ SET_NETDEV_DEV(wlandev->netdev, &(interface->dev));
+#endif
+ if ( register_wlandev(wlandev) != 0 ) {
+ WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
+ result = -EIO;
+ goto failed;
+ }
+
+ /* Do a chip-level reset on the MAC */
+ if (prism2_doreset) {
+ result = hfa384x_corereset(hw,
+ prism2_reset_holdtime,
+ prism2_reset_settletime, 0);
+ if (result != 0) {
+ unregister_wlandev(wlandev);
+ hfa384x_destroy(hw);
+ result = -EIO;
+ WLAN_LOG_ERROR(
+ "%s: hfa384x_corereset() failed.\n",
+ dev_info);
+ goto failed;
+ }
+ }
+
+#ifndef NEW_MODULE_CODE
+ usb_inc_dev_use(dev);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+ usb_get_dev(dev);
+#endif
+
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+
+ goto done;
+
+ failed:
+ if (wlandev) kfree(wlandev);
+ if (hw) kfree(hw);
+ wlandev = NULL;
+
+ done:
+ DBFEXIT;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ return wlandev;
+#else
+ usb_set_intfdata(interface, wlandev);
+ return result;
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_disconnect_usb
+*
+* Called when a device previously claimed by probe is removed
+* from the USB.
+*
+* Arguments:
+* dev ptr to the usb_device struct
+* ptr ptr returned by probe() when the device
+* was claimed.
+*
+* Returns:
+* Nothing
+*
+* Side effects:
+*
+* Call context:
+* process
+----------------------------------------------------------------*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static void __devexit
+prism2sta_disconnect_usb(struct usb_device *dev, void *ptr)
+#else
+static void
+prism2sta_disconnect_usb(struct usb_interface *interface)
+#endif
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ wlandevice_t *wlandev;
+#else
+ wlandevice_t *wlandev = (wlandevice_t*)ptr;
+#endif
+
+ DBFENTER;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ wlandev = (wlandevice_t *) usb_get_intfdata(interface);
+#endif
+
+ if ( wlandev != NULL ) {
+ LIST_HEAD(cleanlist);
+ struct list_head *entry;
+ struct list_head *temp;
+ unsigned long flags;
+
+ hfa384x_t *hw = wlandev->priv;
+
+ if (!hw)
+ goto exit;
+
+ spin_lock_irqsave(&hw->ctlxq.lock, flags);
+
+ p80211netdev_hwremoved(wlandev);
+ list_splice_init(&hw->ctlxq.reapable, &cleanlist);
+ list_splice_init(&hw->ctlxq.completing, &cleanlist);
+ list_splice_init(&hw->ctlxq.pending, &cleanlist);
+ list_splice_init(&hw->ctlxq.active, &cleanlist);
+
+ spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
+
+ /* There's no hardware to shutdown, but the driver
+ * might have some tasks or tasklets that must be
+ * stopped before we can tear everything down.
+ */
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+
+ del_singleshot_timer_sync(&hw->throttle);
+ del_singleshot_timer_sync(&hw->reqtimer);
+ del_singleshot_timer_sync(&hw->resptimer);
+
+ /* Unlink all the URBs. This "removes the wheels"
+ * from the entire CTLX handling mechanism.
+ */
+ usb_kill_urb(&hw->rx_urb);
+ usb_kill_urb(&hw->tx_urb);
+ usb_kill_urb(&hw->ctlx_urb);
+
+ tasklet_kill(&hw->completion_bh);
+ tasklet_kill(&hw->reaper_bh);
+
+ flush_scheduled_work();
+
+ /* Now we complete any outstanding commands
+ * and tell everyone who is waiting for their
+ * responses that we have shut down.
+ */
+ list_for_each(entry, &cleanlist) {
+ hfa384x_usbctlx_t *ctlx;
+
+ ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ complete(&ctlx->done);
+ }
+
+ /* Give any outstanding synchronous commands
+ * a chance to complete. All they need to do
+ * is "wake up", so that's easy.
+ * (I'd like a better way to do this, really.)
+ */
+ msleep(100);
+
+ /* Now delete the CTLXs, because no-one else can now. */
+ list_for_each_safe(entry, temp, &cleanlist) {
+ hfa384x_usbctlx_t *ctlx;
+
+ ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ kfree(ctlx);
+ }
+
+ /* Unhook the wlandev */
+ unregister_wlandev(wlandev);
+ wlan_unsetup(wlandev);
+
+#ifndef NEW_MODULE_CODE
+ usb_dec_dev_use(hw->usb);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+ usb_put_dev(hw->usb);
+#endif
+
+ hfa384x_destroy(hw);
+ kfree(hw);
+
+ kfree(wlandev);
+ }
+
+ exit:
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ usb_set_intfdata(interface, NULL);
+#endif
+ DBFEXIT;
+}
+
+
+static struct usb_driver prism2_usb_driver = {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+ .owner = THIS_MODULE,
+#endif
+ .name = "prism2_usb",
+ .probe = prism2sta_probe_usb,
+ .disconnect = prism2sta_disconnect_usb,
+ .id_table = usb_prism_tbl,
+ /* fops, minor? */
+};
+
+#ifdef MODULE
+
+static int __init prism2usb_init(void)
+{
+ DBFENTER;
+
+ WLAN_LOG_NOTICE("%s Loaded\n", version);
+ WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info);
+
+ /* This call will result in calls to prism2sta_probe_usb. */
+ return usb_register(&prism2_usb_driver);
+
+ DBFEXIT;
+};
+
+static void __exit prism2usb_cleanup(void)
+{
+ DBFENTER;
+
+ usb_deregister(&prism2_usb_driver);
+
+ printk(KERN_NOTICE "%s Unloaded\n", version);
+
+ DBFEXIT;
+};
+
+module_init(prism2usb_init);
+module_exit(prism2usb_cleanup);
+
+#endif // module
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
new file mode 100644
index 00000000000..c975025b6ae
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -0,0 +1,2956 @@
+/* src/prism2/driver/prism2mgmt.c
+*
+* Management request handler functions.
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* The functions in this file handle management requests sent from
+* user mode.
+*
+* Most of these functions have two separate blocks of code that are
+* conditional on whether this is a station or an AP. This is used
+* to separate out the STA and AP responses to these management primitives.
+* It's a choice (good, bad, indifferent?) to have the code in the same
+* place so it's clear that the same primitive is implemented in both
+* cases but has different behavior.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+#define WLAN_DBVAR prism2_debug
+
+#include "version.h"
+
+
+#include <linux/version.h>
+
+#include <linux/if_arp.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <linux/random.h>
+
+#if (WLAN_HOSTIF == WLAN_USB)
+#include <linux/usb.h>
+#endif
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+#endif
+
+#include "wlan_compat.h"
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "hfa384x.h"
+#include "prism2mgmt.h"
+
+/*================================================================*/
+/* Local Constants */
+
+
+/*================================================================*/
+/* Local Macros */
+
+/* Converts 802.11 format rate specifications to prism2 */
+#define p80211rate_to_p2bit(n) ((((n)&~BIT7) == 2) ? BIT0 : \
+ (((n)&~BIT7) == 4) ? BIT1 : \
+ (((n)&~BIT7) == 11) ? BIT2 : \
+ (((n)&~BIT7) == 22) ? BIT3 : 0)
+
+/*================================================================*/
+/* Local Types */
+
+
+/*================================================================*/
+/* Local Static Definitions */
+
+
+/*================================================================*/
+/* Local Function Declarations */
+
+
+/*================================================================*/
+/* Function Definitions */
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_powermgmt
+*
+* Set the power management state of this station's MAC.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_powermgmt_t *msg = msgp;
+
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /*
+ * Set CNFPMENABLED (on or off)
+ * Set CNFMULTICASTRX (if PM on, otherwise clear)
+ * Spout a notice stating that SleepDuration and
+ * HoldoverDuration and PMEPS also have an impact.
+ */
+ /* Powermgmt is currently unsupported for STA */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Powermgmt is never supported for AP */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_scan
+*
+* Initiate a scan for BSSs.
+*
+* This function corresponds to MLME-scan.request and part of
+* MLME-scan.confirm. As far as I can tell in the standard, there
+* are no restrictions on when a scan.request may be issued. We have
+* to handle in whatever state the driver/MAC happen to be.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_scan_t *msg = msgp;
+ UINT16 roamingmode, word;
+ int i, timeout;
+ int istmpenable = 0;
+
+ hfa384x_HostScanRequest_data_t scanreq;
+
+ DBFENTER;
+
+ if (hw->ap) {
+ WLAN_LOG_ERROR("Prism2 in AP mode cannot perform scans.\n");
+ result = 1;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto exit;
+ }
+
+ /* gatekeeper check */
+ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor,
+ hw->ident_sta_fw.variant) <
+ HFA384x_FIRMWARE_VERSION(1,3,2)) {
+ WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n");
+ result = 1;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto exit;
+ }
+
+ memset(&scanreq, 0, sizeof(scanreq));
+
+ /* save current roaming mode */
+ result = hfa384x_drvr_getconfig16(hw,
+ HFA384x_RID_CNFROAMINGMODE, &roamingmode);
+ if ( result ) {
+ WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n",
+ result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+
+ /* drop into mode 3 for the scan */
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFROAMINGMODE,
+ HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
+ if ( result ) {
+ WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n",
+ result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+
+ /* active or passive? */
+ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor,
+ hw->ident_sta_fw.variant) >
+ HFA384x_FIRMWARE_VERSION(1,5,0)) {
+ if (msg->scantype.data != P80211ENUM_scantype_active) {
+ word = host2hfa384x_16(msg->maxchanneltime.data);
+ } else {
+ word = 0;
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
+ if ( result ) {
+ WLAN_LOG_WARNING("Passive scan not supported with "
+ "current firmware. (<1.5.1)\n");
+ }
+ }
+
+ /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
+ word = HFA384x_RATEBIT_2;
+ scanreq.txRate = host2hfa384x_16(word);
+
+ /* set up the channel list */
+ word = 0;
+ for (i = 0; i < msg->channellist.data.len; i++) {
+ UINT8 channel = msg->channellist.data.data[i];
+ if (channel > 14) continue;
+ /* channel 1 is BIT0 ... channel 14 is BIT13 */
+ word |= (1 << (channel-1));
+ }
+ scanreq.channelList = host2hfa384x_16(word);
+
+ /* set up the ssid, if present. */
+ scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
+ memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
+
+ /* Enable the MAC port if it's not already enabled */
+ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
+ if ( result ) {
+ WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. "
+ "result=%d\n", result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ if (word == HFA384x_PORTSTATUS_DISABLED) {
+ UINT16 wordbuf[17];
+
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFROAMINGMODE,
+ HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
+ if ( result ) {
+ WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ /* Construct a bogus SSID and assign it to OwnSSID and
+ * DesiredSSID
+ */
+ wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
+ get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
+ wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set OwnSSID.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
+ wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set DesiredSSID.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ /* bsstype */
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFPORTTYPE,
+ HFA384x_PORTTYPE_IBSS);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ /* ibss options */
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CREATEIBSS,
+ HFA384x_CREATEIBSS_JOINCREATEIBSS);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("drvr_enable(0) failed. "
+ "result=%d\n", result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ istmpenable = 1;
+ }
+
+ /* Figure out our timeout first Kus, then HZ */
+ timeout = msg->channellist.data.len * msg->maxchanneltime.data;
+ timeout = (timeout * HZ)/1000;
+
+ /* Issue the scan request */
+ hw->scanflag = 0;
+
+ WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));
+
+ result = hfa384x_drvr_setconfig( hw,
+ HFA384x_RID_HOSTSCAN, &scanreq,
+ sizeof(hfa384x_HostScanRequest_data_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n",
+ result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+
+ /* sleep until info frame arrives */
+ wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
+
+ msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
+ if (hw->scanflag == -1)
+ hw->scanflag = 0;
+
+ msg->numbss.data = hw->scanflag;
+
+ hw->scanflag = 0;
+
+ /* Disable port if we temporarily enabled it. */
+ if (istmpenable) {
+ result = hfa384x_drvr_disable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("drvr_disable(0) failed. "
+ "result=%d\n", result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+ }
+
+ /* restore original roaming mode */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
+ roamingmode);
+ if ( result ) {
+ WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n",
+ result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ goto exit;
+ }
+
+ result = 0;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ exit:
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_scan_results
+*
+* Retrieve the BSS description for one of the BSSs identified in
+* a scan.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ p80211msg_dot11req_scan_results_t *req;
+ hfa384x_t *hw = wlandev->priv;
+ hfa384x_HScanResultSub_t *item = NULL;
+
+ int count;
+
+ DBFENTER;
+
+ req = (p80211msg_dot11req_scan_results_t *) msgp;
+
+ req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ if (hw->ap) {
+ result = 1;
+ req->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto exit;
+ }
+
+ if (! hw->scanresults) {
+ WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n");
+ result = 2;
+ req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+ goto exit;
+ }
+
+ count = (hw->scanresults->framelen - 3) / 32;
+ if (count > 32) count = 32;
+
+ if (req->bssindex.data >= count) {
+ WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n",
+ req->bssindex.data, count);
+ result = 2;
+ req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+ goto exit;
+ }
+
+ item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
+ /* signal and noise */
+ req->signal.status = P80211ENUM_msgitem_status_data_ok;
+ req->noise.status = P80211ENUM_msgitem_status_data_ok;
+ req->signal.data = hfa384x2host_16(item->sl);
+ req->noise.data = hfa384x2host_16(item->anl);
+
+ /* BSSID */
+ req->bssid.status = P80211ENUM_msgitem_status_data_ok;
+ req->bssid.data.len = WLAN_BSSID_LEN;
+ memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
+
+ /* SSID */
+ req->ssid.status = P80211ENUM_msgitem_status_data_ok;
+ req->ssid.data.len = hfa384x2host_16(item->ssid.len);
+ memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
+
+ /* supported rates */
+ for (count = 0; count < 10 ; count++)
+ if (item->supprates[count] == 0)
+ break;
+
+#define REQBASICRATE(N) \
+ if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
+ req->basicrate ## N .data = item->supprates[(N)-1]; \
+ req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
+ }
+
+ REQBASICRATE(1);
+ REQBASICRATE(2);
+ REQBASICRATE(3);
+ REQBASICRATE(4);
+ REQBASICRATE(5);
+ REQBASICRATE(6);
+ REQBASICRATE(7);
+ REQBASICRATE(8);
+
+#define REQSUPPRATE(N) \
+ if (count >= N) { \
+ req->supprate ## N .data = item->supprates[(N)-1]; \
+ req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
+ }
+
+ REQSUPPRATE(1);
+ REQSUPPRATE(2);
+ REQSUPPRATE(3);
+ REQSUPPRATE(4);
+ REQSUPPRATE(5);
+ REQSUPPRATE(6);
+ REQSUPPRATE(7);
+ REQSUPPRATE(8);
+
+ /* beacon period */
+ req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
+ req->beaconperiod.data = hfa384x2host_16(item->bcnint);
+
+ /* timestamps */
+ req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
+ req->timestamp.data = jiffies;
+ req->localtime.status = P80211ENUM_msgitem_status_data_ok;
+ req->localtime.data = jiffies;
+
+ /* atim window */
+ req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
+ req->ibssatimwindow.data = hfa384x2host_16(item->atim);
+
+ /* Channel */
+ req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
+ req->dschannel.data = hfa384x2host_16(item->chid);
+
+ /* capinfo bits */
+ count = hfa384x2host_16(item->capinfo);
+
+ /* privacy flag */
+ req->privacy.status = P80211ENUM_msgitem_status_data_ok;
+ req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
+
+ /* cfpollable */
+ req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
+ req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
+
+ /* cfpollreq */
+ req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
+ req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
+
+ /* bsstype */
+ req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
+ req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
+ P80211ENUM_bsstype_infrastructure :
+ P80211ENUM_bsstype_independent;
+
+ // item->proberesp_rate
+/*
+ req->fhdwelltime
+ req->fhhopset
+ req->fhhoppattern
+ req->fhhopindex
+ req->cfpdurremaining
+*/
+
+ result = 0;
+ req->resultcode.data = P80211ENUM_resultcode_success;
+
+ exit:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_join
+*
+* Join a BSS whose BSS description was previously obtained with
+* a scan.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_join(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_join_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* TODO: Implement after scan */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported by APs */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_p2_join
+*
+* Join a specific BSS
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_join_t *msg = msgp;
+ UINT16 reg;
+ p80211pstrd_t *pstr;
+ UINT8 bytebuf[256];
+ hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
+ hfa384x_JoinRequest_data_t joinreq;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ wlandev->macmode = WLAN_MACMODE_NONE;
+
+ /*** STATION ***/
+ /* Set the PortType */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ /* ess port */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set Port Type\n");
+ goto failed;
+ }
+
+ /* Set the auth type */
+ if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
+ reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
+ } else {
+ reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set Authentication\n");
+ goto failed;
+ }
+
+ /* Turn off all roaming */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 3);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to Turn off Roaming\n");
+ goto failed;
+ }
+
+ /* Basic rates */
+ reg = 0;
+ if ( msg->basicrate1.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg = p80211rate_to_p2bit(msg->basicrate1.data);
+ }
+ if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate2.data);
+ }
+ if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate3.data);
+ }
+ if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate4.data);
+ }
+ if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate5.data);
+ }
+ if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate6.data);
+ }
+ if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate7.data);
+ }
+ if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->basicrate8.data);
+ }
+ if( reg == 0)
+ reg = 0x03;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, reg);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", reg);
+ goto failed;
+ }
+
+ /* Operational rates (supprates and txratecontrol) */
+ reg = 0;
+ if ( msg->operationalrate1.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg = p80211rate_to_p2bit(msg->operationalrate1.data);
+ }
+ if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate2.data);
+ }
+ if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate3.data);
+ }
+ if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate4.data);
+ }
+ if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate5.data);
+ }
+ if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate6.data);
+ }
+ if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate7.data);
+ }
+ if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ reg |= p80211rate_to_p2bit(msg->operationalrate8.data);
+ }
+ if( reg == 0)
+ reg = 0x0f;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, reg);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set supprates=%d.\n", reg);
+ goto failed;
+ }
+
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set txrates=%d.\n", reg);
+ goto failed;
+ }
+
+ /* Set the ssid */
+ memset(bytebuf, 0, 256);
+ pstr = (p80211pstrd_t*)&(msg->ssid.data);
+ prism2mgmt_pstr2bytestr(p2bytestr, pstr);
+ result = hfa384x_drvr_setconfig(
+ hw, HFA384x_RID_CNFDESIREDSSID,
+ bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set SSID\n");
+ goto failed;
+ }
+
+ /* Enable the Port */
+ result = hfa384x_cmd_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
+ goto failed;
+ }
+
+ /* Fill in the join request */
+ joinreq.channel = msg->channel.data;
+ memcpy( joinreq.bssid, ((unsigned char *) &msg->bssid.data) + 1, WLAN_BSSID_LEN);
+ hw->joinreq = joinreq;
+ hw->join_ap = 1;
+
+ /* Send the join request */
+ result = hfa384x_drvr_setconfig( hw,
+ HFA384x_RID_JOINREQUEST,
+ &joinreq, HFA384x_RID_JOINREQUEST_LEN);
+ if(result != 0) {
+ WLAN_LOG_ERROR("Join request failed, result=%d.\n", result);
+ goto failed;
+ }
+
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported by APs */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ goto done;
+failed:
+ WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+
+done:
+ result = 0;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_authenticate
+*
+* Station should be begin an authentication exchange.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_authenticate_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* TODO: Decide how we're going to handle this one w/ Prism2 */
+ /* It could be entertaining since Prism2 doesn't have */
+ /* an explicit way to control this */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported by APs */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_deauthenticate
+*
+* Send a deauthenticate notification.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_deauthenticate_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* TODO: Decide how we're going to handle this one w/ Prism2 */
+ /* It could be entertaining since Prism2 doesn't have */
+ /* an explicit way to control this */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+ hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data);
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_associate
+*
+* Associate with an ESS.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ int result = 0;
+ p80211msg_dot11req_associate_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+#if 0
+ /* Set the TxRates */
+ reg = 0x000f;
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
+#endif
+
+ /* Set the PortType */
+ /* ess port */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
+
+ /* Enable the Port */
+ hfa384x_drvr_enable(hw, 0);
+
+ /* Set the resultcode */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported on AP */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_reassociate
+*
+* Renew association because of a BSS change.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_reassociate_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* TODO: Not supported yet...not sure how we're going to do it */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported on AP */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_disassociate
+*
+* Send a disassociation notification.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_disassociate_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* TODO: Not supported yet...not sure how to do it */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ } else {
+
+ /*** ACCESS POINT ***/
+ hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data);
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_reset
+*
+* Reset the MAC and MSD. The p80211 layer has it's own handling
+* that should be done before and after this function.
+* Procedure:
+* - disable system interrupts ??
+* - disable MAC interrupts
+* - restore system interrupts
+* - issue the MAC initialize command
+* - clear any MSD level state (including timers, queued events,
+* etc.). Note that if we're removing timer'd/queue events, we may
+* need to have remained in the system interrupt disabled state.
+* We should be left in the same state that we're in following
+* driver initialization.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer, MAY BE NULL! for a driver local
+* call.
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread, commonly wlanctl, but might be rmmod/pci_close.
+----------------------------------------------------------------*/
+int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_reset_t *msg = msgp;
+ DBFENTER;
+
+ /*
+ * This is supported on both AP and STA and it's not allowed
+ * to fail.
+ */
+ if ( msgp ) {
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ WLAN_LOG_INFO("dot11req_reset: the macaddress and "
+ "setdefaultmib arguments are currently unsupported.\n");
+ }
+
+ /*
+ * If we got this far, the MSD must be in the MSDRUNNING state
+ * therefore, we must stop and then restart the hw/MAC combo.
+ */
+ hfa384x_drvr_stop(hw);
+ result = hfa384x_drvr_start(hw);
+ if (result != 0) {
+ WLAN_LOG_ERROR("dot11req_reset: Initialize command failed,"
+ " bad things will happen from here.\n");
+ return 0;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_start
+*
+* Start a BSS. Any station can do this for IBSS, only AP for ESS.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_dot11req_start_t *msg = msgp;
+
+ p80211pstrd_t *pstr;
+ UINT8 bytebuf[80];
+ hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
+ hfa384x_PCFInfo_data_t *pcfinfo = (hfa384x_PCFInfo_data_t*)bytebuf;
+ UINT16 word;
+ DBFENTER;
+
+ wlandev->macmode = WLAN_MACMODE_NONE;
+
+ /* Set the SSID */
+ memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
+
+ if (!hw->ap) {
+ /*** ADHOC IBSS ***/
+ /* see if current f/w is less than 8c3 */
+ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor,
+ hw->ident_sta_fw.variant) <
+ HFA384x_FIRMWARE_VERSION(0,8,3)) {
+ /* Ad-Hoc not quite supported on Prism2 */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto done;
+ }
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /*** STATION ***/
+ /* Set the REQUIRED config items */
+ /* SSID */
+ pstr = (p80211pstrd_t*)&(msg->ssid.data);
+ prism2mgmt_pstr2bytestr(p2bytestr, pstr);
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
+ bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n");
+ goto failed;
+ }
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
+ bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n");
+ goto failed;
+ }
+
+ /* bsstype - we use the default in the ap firmware */
+ /* IBSS port */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
+
+ /* beacon period */
+ word = msg->beaconperiod.data;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
+ goto failed;
+ }
+
+ /* dschannel */
+ word = msg->dschannel.data;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
+ goto failed;
+ }
+ /* Basic rates */
+ word = p80211rate_to_p2bit(msg->basicrate1.data);
+ if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate2.data);
+ }
+ if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate3.data);
+ }
+ if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate4.data);
+ }
+ if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate5.data);
+ }
+ if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate6.data);
+ }
+ if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate7.data);
+ }
+ if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate8.data);
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
+ goto failed;
+ }
+
+ /* Operational rates (supprates and txratecontrol) */
+ word = p80211rate_to_p2bit(msg->operationalrate1.data);
+ if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate2.data);
+ }
+ if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate3.data);
+ }
+ if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate4.data);
+ }
+ if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate5.data);
+ }
+ if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate6.data);
+ }
+ if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate7.data);
+ }
+ if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate8.data);
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
+ goto failed;
+ }
+
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
+ goto failed;
+ }
+
+ /* Set the macmode so the frame setup code knows what to do */
+ if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
+ wlandev->macmode = WLAN_MACMODE_IBSS_STA;
+ /* lets extend the data length a bit */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
+ }
+
+ /* Enable the Port */
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
+ goto failed;
+ }
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ goto done;
+ }
+
+ /*** ACCESS POINT ***/
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* Validate the command, if BSStype=infra is the tertiary loaded? */
+ if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
+ WLAN_LOG_ERROR("AP driver cannot create IBSS.\n");
+ goto failed;
+ } else if ( hw->cap_sup_sta.id != 5) {
+ WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n");
+ goto failed;
+ }
+
+ /* Set the REQUIRED config items */
+ /* SSID */
+ pstr = (p80211pstrd_t*)&(msg->ssid.data);
+ prism2mgmt_pstr2bytestr(p2bytestr, pstr);
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
+ bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set SSID, result=0x%04x\n", result);
+ goto failed;
+ }
+
+ /* bsstype - we use the default in the ap firmware */
+
+ /* beacon period */
+ word = msg->beaconperiod.data;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
+ goto failed;
+ }
+
+ /* dschannel */
+ word = msg->dschannel.data;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
+ goto failed;
+ }
+ /* Basic rates */
+ word = p80211rate_to_p2bit(msg->basicrate1.data);
+ if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate2.data);
+ }
+ if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate3.data);
+ }
+ if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate4.data);
+ }
+ if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate5.data);
+ }
+ if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate6.data);
+ }
+ if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate7.data);
+ }
+ if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->basicrate8.data);
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
+ goto failed;
+ }
+
+ /* Operational rates (supprates and txratecontrol) */
+ word = p80211rate_to_p2bit(msg->operationalrate1.data);
+ if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate2.data);
+ }
+ if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate3.data);
+ }
+ if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate4.data);
+ }
+ if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate5.data);
+ }
+ if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate6.data);
+ }
+ if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate7.data);
+ }
+ if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
+ word |= p80211rate_to_p2bit(msg->operationalrate8.data);
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
+ goto failed;
+ }
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL0, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
+ goto failed;
+ }
+
+ /* ibssatimwindow */
+ if (msg->ibssatimwindow.status == P80211ENUM_msgitem_status_data_ok) {
+ WLAN_LOG_INFO("prism2mgmt_start: atimwindow not used in "
+ "Infrastructure mode, ignored.\n");
+ }
+
+ /* DTIM period */
+ word = msg->dtimperiod.data;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNDTIMPER, word);
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to set dtim period=%d.\n", word);
+ goto failed;
+ }
+
+ /* probedelay */
+ if (msg->probedelay.status == P80211ENUM_msgitem_status_data_ok) {
+ WLAN_LOG_INFO("prism2mgmt_start: probedelay not "
+ "supported in prism2, ignored.\n");
+ }
+
+ /* cfpollable, cfpollreq, cfpperiod, cfpmaxduration */
+ if (msg->cfpollable.data == P80211ENUM_truth_true &&
+ msg->cfpollreq.data == P80211ENUM_truth_true ) {
+ WLAN_LOG_ERROR("cfpollable=cfpollreq=true is illegal.\n");
+ result = -1;
+ goto failed;
+ }
+
+ /* read the PCFInfo and update */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO,
+ pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN);
+ if ( result ) {
+ WLAN_LOG_INFO("prism2mgmt_start: read(pcfinfo) failed, "
+ "assume it's "
+ "not supported, pcf settings ignored.\n");
+ goto pcf_skip;
+ }
+ if ((msg->cfpollable.data == P80211ENUM_truth_false &&
+ msg->cfpollreq.data == P80211ENUM_truth_false) ) {
+ pcfinfo->MediumOccupancyLimit = 0;
+ pcfinfo->CFPPeriod = 0;
+ pcfinfo->CFPMaxDuration = 0;
+ pcfinfo->CFPFlags &= host2hfa384x_16((UINT16)~BIT0);
+
+ if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok ||
+ msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok ) {
+ WLAN_LOG_WARNING(
+ "Setting cfpperiod or cfpmaxduration when "
+ "cfpollable and cfreq are false is pointless.\n");
+ }
+ }
+ if ((msg->cfpollable.data == P80211ENUM_truth_true ||
+ msg->cfpollreq.data == P80211ENUM_truth_true) ) {
+ if ( msg->cfpollable.data == P80211ENUM_truth_true) {
+ pcfinfo->CFPFlags |= host2hfa384x_16((UINT16)BIT0);
+ }
+
+ if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok) {
+ pcfinfo->CFPPeriod = msg->cfpperiod.data;
+ pcfinfo->CFPPeriod = host2hfa384x_16(pcfinfo->CFPPeriod);
+ }
+
+ if ( msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok) {
+ pcfinfo->CFPMaxDuration = msg->cfpmaxduration.data;
+ pcfinfo->CFPMaxDuration = host2hfa384x_16(pcfinfo->CFPMaxDuration);
+ pcfinfo->MediumOccupancyLimit = pcfinfo->CFPMaxDuration;
+ }
+ }
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO,
+ pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("write(pcfinfo) failed.\n");
+ goto failed;
+ }
+
+pcf_skip:
+ /* Set the macmode so the frame setup code knows what to do */
+ if ( msg->bsstype.data == P80211ENUM_bsstype_infrastructure ) {
+ wlandev->macmode = WLAN_MACMODE_ESS_AP;
+ /* lets extend the data length a bit */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
+ }
+
+ /* Set the BSSID to the same as our MAC */
+ memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN);
+
+ /* Enable the Port */
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
+ goto failed;
+ }
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ goto done;
+failed:
+ WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+
+done:
+ result = 0;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_enable
+*
+* Start a BSS. Any station can do this for IBSS, only AP for ESS.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_enable_t *msg = msgp;
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* Ad-Hoc not quite supported on Prism2 */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto done;
+ }
+
+ /*** ACCESS POINT ***/
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* Is the tertiary loaded? */
+ if ( hw->cap_sup_sta.id != 5) {
+ WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n");
+ goto failed;
+ }
+
+ /* Set the macmode so the frame setup code knows what to do */
+ wlandev->macmode = WLAN_MACMODE_ESS_AP;
+
+ /* Set the BSSID to the same as our MAC */
+ memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN);
+
+ /* Enable the Port */
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
+ goto failed;
+ }
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ goto done;
+failed:
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+
+done:
+ result = 0;
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_readpda
+*
+* Collect the PDA data and put it in the message.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_readpda_t *msg = msgp;
+ int result;
+ DBFENTER;
+
+ /* We only support collecting the PDA when in the FWLOAD
+ * state.
+ */
+ if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
+ WLAN_LOG_ERROR(
+ "PDA may only be read "
+ "in the fwload state.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ } else {
+ /* Call drvr_readpda(), it handles the auxport enable
+ * and validating the returned PDA.
+ */
+ result = hfa384x_drvr_readpda(
+ hw,
+ msg->pda.data,
+ HFA384x_PDA_LEN_MAX);
+ if (result) {
+ WLAN_LOG_ERROR(
+ "hfa384x_drvr_readpda() failed, "
+ "result=%d\n",
+ result);
+
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status =
+ P80211ENUM_msgitem_status_data_ok;
+ DBFEXIT;
+ return 0;
+ }
+ msg->pda.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_readcis
+*
+* Collect the CIS data and put it in the message.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp)
+{
+ int result;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_readcis_t *msg = msgp;
+
+ DBFENTER;
+
+ memset(msg->cis.data, 0, sizeof(msg->cis.data));
+
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CIS,
+ msg->cis.data, HFA384x_RID_CIS_LEN);
+ if ( result ) {
+ WLAN_LOG_INFO("prism2mgmt_readcis: read(cis) failed.\n");
+ msg->cis.status = P80211ENUM_msgitem_status_no_value;
+ msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
+
+ }
+ else {
+ msg->cis.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_auxport_state
+*
+* Enables/Disables the card's auxiliary port. Should be called
+* before and after a sequence of auxport_read()/auxport_write()
+* calls.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp)
+{
+ p80211msg_p2req_auxport_state_t *msg = msgp;
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ hfa384x_t *hw = wlandev->priv;
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ if (msg->enable.data == P80211ENUM_truth_true) {
+ if ( hfa384x_cmd_aux_enable(hw, 0) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+ } else {
+ hfa384x_cmd_aux_disable(hw);
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+
+#else /* !USB */
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+
+#endif /* WLAN_HOSTIF != WLAN_USB */
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_auxport_read
+*
+* Copies data from the card using the auxport. The auxport must
+* have previously been enabled. Note: this is not the way to
+* do downloads, see the [ram|flash]dl functions.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp)
+{
+#if (WLAN_HOSTIF != WLAN_USB)
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_auxport_read_t *msg = msgp;
+ UINT32 addr;
+ UINT32 len;
+ UINT8* buf;
+ UINT32 maxlen = sizeof(msg->data.data);
+ DBFENTER;
+
+ if ( hw->auxen ) {
+ addr = msg->addr.data;
+ len = msg->len.data;
+ buf = msg->data.data;
+ if ( len <= maxlen ) { /* max read/write size */
+ hfa384x_copy_from_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len);
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ } else {
+ WLAN_LOG_DEBUG(1,"Attempt to read > maxlen from auxport.\n");
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+ }
+
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+ }
+ msg->data.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ DBFEXIT;
+ return 0;
+#else
+ DBFENTER;
+
+ WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
+
+ DBFEXIT;
+ return 0;
+#endif
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_auxport_write
+*
+* Copies data to the card using the auxport. The auxport must
+* have previously been enabled. Note: this is not the way to
+* do downloads, see the [ram|flash]dl functions.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp)
+{
+#if (WLAN_HOSTIF != WLAN_USB)
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_auxport_write_t *msg = msgp;
+ UINT32 addr;
+ UINT32 len;
+ UINT8* buf;
+ UINT32 maxlen = sizeof(msg->data.data);
+ DBFENTER;
+
+ if ( hw->auxen ) {
+ addr = msg->addr.data;
+ len = msg->len.data;
+ buf = msg->data.data;
+ if ( len <= maxlen ) { /* max read/write size */
+ hfa384x_copy_to_aux(hw, addr, HFA384x_AUX_CTL_EXTDS, buf, len);
+ } else {
+ WLAN_LOG_DEBUG(1,"Attempt to write > maxlen from auxport.\n");
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+ }
+
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+ }
+ msg->data.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ DBFEXIT;
+ return 0;
+#else
+ DBFENTER;
+ WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
+ DBFEXIT;
+ return 0;
+#endif
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_low_level
+*
+* Puts the card into the desired test mode.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_low_level_t *msg = msgp;
+ hfa384x_metacmd_t cmd;
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* call some routine to execute the test command */
+ cmd.cmd = (UINT16) msg->command.data;
+ cmd.parm0 = (UINT16) msg->param0.data;
+ cmd.parm1 = (UINT16) msg->param1.data;
+ cmd.parm2 = (UINT16) msg->param2.data;
+
+ hfa384x_drvr_low_level(hw,&cmd);
+
+ msg->resp0.data = (UINT32) cmd.result.resp0;
+ msg->resp1.data = (UINT32) cmd.result.resp1;
+ msg->resp2.data = (UINT32) cmd.result.resp2;
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_test_command
+*
+* Puts the card into the desired test mode.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_test_command_t *msg = msgp;
+ hfa384x_metacmd_t cmd;
+
+ DBFENTER;
+
+ cmd.cmd = ((UINT16) msg->testcode.data) << 8 | 0x38;
+ cmd.parm0 = (UINT16) msg->testparam.data;
+ cmd.parm1 = 0;
+ cmd.parm2 = 0;
+
+ /* call some routine to execute the test command */
+
+ hfa384x_drvr_low_level(hw,&cmd);
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ msg->status.status = P80211ENUM_msgitem_status_data_ok;
+ msg->status.data = cmd.result.status;
+ msg->resp0.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resp0.data = cmd.result.resp0;
+ msg->resp1.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resp1.data = cmd.result.resp1;
+ msg->resp2.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resp2.data = cmd.result.resp2;
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_mmi_read
+*
+* Read from one of the MMI registers.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_mmi_read_t *msg = msgp;
+ UINT32 resp = 0;
+
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* call some routine to execute the test command */
+
+ hfa384x_drvr_mmi_read(hw, msg->addr.data, &resp);
+
+ /* I'm not sure if this is "architecturally" correct, but it
+ is expedient. */
+
+ msg->value.status = P80211ENUM_msgitem_status_data_ok;
+ msg->value.data = resp;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_mmi_write
+*
+* Write a data value to one of the MMI registers.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_mmi_write_t *msg = msgp;
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+
+ /* call some routine to execute the test command */
+
+ hfa384x_drvr_mmi_write(hw, msg->addr.data, msg->data.data);
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_ramdl_state
+*
+* Establishes the beginning/end of a card RAM download session.
+*
+* It is expected that the ramdl_write() function will be called
+* one or more times between the 'enable' and 'disable' calls to
+* this function.
+*
+* Note: This function should not be called when a mac comm port
+* is active.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_ramdl_state_t *msg = msgp;
+ DBFENTER;
+
+ if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
+ WLAN_LOG_ERROR(
+ "ramdl_state(): may only be called "
+ "in the fwload state.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ DBFEXIT;
+ return 0;
+ }
+
+ /*
+ ** Note: Interrupts are locked out if this is an AP and are NOT
+ ** locked out if this is a station.
+ */
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ if ( msg->enable.data == P80211ENUM_truth_true ) {
+ if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+ } else {
+ hfa384x_drvr_ramdl_disable(hw);
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_ramdl_write
+*
+* Writes a buffer to the card RAM using the download state. This
+* is for writing code to card RAM. To just read or write raw data
+* use the aux functions.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_ramdl_write_t *msg = msgp;
+ UINT32 addr;
+ UINT32 len;
+ UINT8 *buf;
+ DBFENTER;
+
+ if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
+ WLAN_LOG_ERROR(
+ "ramdl_write(): may only be called "
+ "in the fwload state.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ DBFEXIT;
+ return 0;
+ }
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ /* first validate the length */
+ if ( msg->len.data > sizeof(msg->data.data) ) {
+ msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters;
+ return 0;
+ }
+ /* call the hfa384x function to do the write */
+ addr = msg->addr.data;
+ len = msg->len.data;
+ buf = msg->data.data;
+ if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+
+ }
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_flashdl_state
+*
+* Establishes the beginning/end of a card Flash download session.
+*
+* It is expected that the flashdl_write() function will be called
+* one or more times between the 'enable' and 'disable' calls to
+* this function.
+*
+* Note: This function should not be called when a mac comm port
+* is active.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_flashdl_state_t *msg = msgp;
+ DBFENTER;
+
+ if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
+ WLAN_LOG_ERROR(
+ "flashdl_state(): may only be called "
+ "in the fwload state.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ DBFEXIT;
+ return 0;
+ }
+
+ /*
+ ** Note: Interrupts are locked out if this is an AP and are NOT
+ ** locked out if this is a station.
+ */
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ if ( msg->enable.data == P80211ENUM_truth_true ) {
+ if ( hfa384x_drvr_flashdl_enable(hw) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ }
+ } else {
+ hfa384x_drvr_flashdl_disable(hw);
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ /* NOTE: At this point, the MAC is in the post-reset
+ * state and the driver is in the fwload state.
+ * We need to get the MAC back into the fwload
+ * state. To do this, we set the nsdstate to HWPRESENT
+ * and then call the ifstate function to redo everything
+ * that got us into the fwload state.
+ */
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
+ if (result != P80211ENUM_resultcode_success) {
+ WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed,"
+ "P80211ENUM_resultcode=%d\n", result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ result = -1;
+ }
+ }
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_flashdl_write
+*
+*
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ p80211msg_p2req_flashdl_write_t *msg = msgp;
+ UINT32 addr;
+ UINT32 len;
+ UINT8 *buf;
+ DBFENTER;
+
+ if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
+ WLAN_LOG_ERROR(
+ "flashdl_write(): may only be called "
+ "in the fwload state.\n");
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ DBFEXIT;
+ return 0;
+ }
+
+ /*
+ ** Note: Interrupts are locked out if this is an AP and are NOT
+ ** locked out if this is a station.
+ */
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ /* first validate the length */
+ if ( msg->len.data > sizeof(msg->data.data) ) {
+ msg->resultcode.status =
+ P80211ENUM_resultcode_invalid_parameters;
+ return 0;
+ }
+ /* call the hfa384x function to do the write */
+ addr = msg->addr.data;
+ len = msg->len.data;
+ buf = msg->data.data;
+ if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+
+ }
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_dump_state
+*
+* Dumps the driver's and hardware's current state via the kernel
+* log at KERN_NOTICE level.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp)
+{
+ p80211msg_p2req_dump_state_t *msg = msgp;
+ int result = 0;
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 auxbuf[15];
+ DBFENTER;
+
+ WLAN_LOG_NOTICE("prism2 driver and hardware state:\n");
+ if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) {
+ WLAN_LOG_ERROR("aux_enable failed, result=%d\n", result);
+ goto failed;
+ }
+ hfa384x_copy_from_aux(hw,
+ 0x01e2,
+ HFA384x_AUX_CTL_EXTDS,
+ auxbuf,
+ sizeof(auxbuf));
+ hfa384x_cmd_aux_disable(hw);
+ WLAN_LOG_NOTICE(" cmac: FreeBlocks=%d\n", auxbuf[5]);
+ WLAN_LOG_NOTICE(" cmac: IntEn=0x%02x EvStat=0x%02x\n",
+ hfa384x_getreg(hw, HFA384x_INTEN),
+ hfa384x_getreg(hw, HFA384x_EVSTAT));
+
+ #ifdef USE_FID_STACK
+ WLAN_LOG_NOTICE(" drvr: txfid_top=%d stacksize=%d\n",
+ hw->txfid_top,HFA384x_DRVR_FIDSTACKLEN_MAX);
+ #else
+ WLAN_LOG_NOTICE(" drvr: txfid_head=%d txfid_tail=%d txfid_N=%d\n",
+ hw->txfid_head, hw->txfid_tail, hw->txfid_N);
+ #endif
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+#else /* (WLAN_HOSTIF == WLAN_USB) */
+
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto failed;
+
+#endif /* (WLAN_HOSTIF != WLAN_USB) */
+
+failed:
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_channel_info
+*
+* Issues a ChannelInfoRequest.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp)
+{
+ p80211msg_p2req_channel_info_t *msg=msgp;
+ hfa384x_t *hw = wlandev->priv;
+ int result, i, n=0;
+ UINT16 channel_mask=0;
+ hfa384x_ChannelInfoRequest_data_t chinforeq;
+ // unsigned long now;
+
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* Not supported in STA f/w */
+ P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported);
+ goto done;
+ }
+
+ /*** ACCESS POINT ***/
+
+#define CHINFO_TIMEOUT 2
+
+ P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success);
+
+ /* setting default value for channellist = all channels */
+ if (!msg->channellist.data) {
+ P80211_SET_INT(msg->channellist, 0x00007FFE);
+ }
+ /* setting default value for channeldwelltime = 100 ms */
+ if (!msg->channeldwelltime.data) {
+ P80211_SET_INT(msg->channeldwelltime, 100);
+ }
+ channel_mask = (UINT16) (msg->channellist.data >> 1);
+ for (i=0, n=0; i < 14; i++) {
+ if (channel_mask & (1<<i)) {
+ n++;
+ }
+ }
+ P80211_SET_INT(msg->numchinfo, n);
+ chinforeq.channelList = host2hfa384x_16(channel_mask);
+ chinforeq.channelDwellTime = host2hfa384x_16(msg->channeldwelltime.data);
+
+ atomic_set(&hw->channel_info.done, 1);
+
+ result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CHANNELINFOREQUEST,
+ &chinforeq, HFA384x_RID_CHANNELINFOREQUEST_LEN);
+ if ( result ) {
+ WLAN_LOG_ERROR("setconfig(CHANNELINFOREQUEST) failed. result=%d\n",
+ result);
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto done;
+ }
+ /*
+ now = jiffies;
+ while (atomic_read(&hw->channel_info.done) != 1) {
+ if ((jiffies - now) > CHINFO_TIMEOUT*HZ) {
+ WLAN_LOG_NOTICE("ChannelInfo results not received in %d seconds, aborting.\n",
+ CHINFO_TIMEOUT);
+ msg->resultcode.data = P80211ENUM_resultcode_timeout;
+ goto done;
+ }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/4);
+ current->state = TASK_RUNNING;
+ }
+ */
+
+done:
+
+ DBFEXIT;
+ return 0;
+}
+
+/*----------------------------------------------------------------
+* prism2mgmt_channel_info_results
+*
+* Returns required ChannelInfo result.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+----------------------------------------------------------------*/
+int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+
+ p80211msg_p2req_channel_info_results_t *msg=msgp;
+ int result=0;
+ int channel;
+
+ DBFENTER;
+
+ if (!hw->ap) {
+
+ /*** STATION ***/
+
+ /* Not supported in STA f/w */
+ P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_not_supported);
+ goto done;
+ }
+
+ /*** ACCESS POINT ***/
+
+ switch (atomic_read(&hw->channel_info.done)) {
+ case 0: msg->resultcode.status = P80211ENUM_msgitem_status_no_value;
+ goto done;
+ case 1: msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata;
+ goto done;
+ }
+
+ P80211_SET_INT(msg->resultcode, P80211ENUM_resultcode_success);
+ channel=msg->channel.data-1;
+
+ if (channel < 0 || ! (hw->channel_info.results.scanchannels & 1<<channel) ) {
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+ goto done;
+ }
+ WLAN_LOG_DEBUG(2, "chinfo_results: channel %d, avg/peak level=%d/%d dB, active=%d\n",
+ channel+1,
+ hw->channel_info.results.result[channel].anl,
+ hw->channel_info.results.result[channel].pnl,
+ hw->channel_info.results.result[channel].active
+ );
+ P80211_SET_INT(msg->avgnoiselevel, hw->channel_info.results.result[channel].anl);
+ P80211_SET_INT(msg->peaknoiselevel, hw->channel_info.results.result[channel].pnl);
+ P80211_SET_INT(msg->bssactive, hw->channel_info.results.result[channel].active &
+ HFA384x_CHINFORESULT_BSSACTIVE
+ ? P80211ENUM_truth_true
+ : P80211ENUM_truth_false) ;
+ P80211_SET_INT(msg->pcfactive, hw->channel_info.results.result[channel].active &
+ HFA384x_CHINFORESULT_PCFACTIVE
+ ? P80211ENUM_truth_true
+ : P80211ENUM_truth_false) ;
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_autojoin
+*
+* Associate with an ESS.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ int result = 0;
+ UINT16 reg;
+ UINT16 port_type;
+ p80211msg_lnxreq_autojoin_t *msg = msgp;
+ p80211pstrd_t *pstr;
+ UINT8 bytebuf[256];
+ hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
+ DBFENTER;
+
+ wlandev->macmode = WLAN_MACMODE_NONE;
+
+ /* Set the SSID */
+ memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
+
+ if (hw->ap) {
+
+ /*** ACCESS POINT ***/
+
+ /* Never supported on AP */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto done;
+ }
+
+ /* Disable the Port */
+ hfa384x_drvr_disable(hw, 0);
+
+ /*** STATION ***/
+ /* Set the TxRates */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
+
+ /* Set the auth type */
+ if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
+ reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
+ } else {
+ reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
+ }
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
+
+ /* Set the ssid */
+ memset(bytebuf, 0, 256);
+ pstr = (p80211pstrd_t*)&(msg->ssid.data);
+ prism2mgmt_pstr2bytestr(p2bytestr, pstr);
+ result = hfa384x_drvr_setconfig(
+ hw, HFA384x_RID_CNFDESIREDSSID,
+ bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
+#if 0
+ /* we can use the new-fangled auto-unknown mode if the firmware
+ is 1.3.3 or newer */
+ if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor,
+ hw->ident_sta_fw.variant) >=
+ HFA384x_FIRMWARE_VERSION(1,3,3)) {
+ /* Set up the IBSS options */
+ reg = HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS;
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg);
+
+ /* Set the PortType */
+ port_type = HFA384x_PORTTYPE_IBSS;
+ } else {
+ port_type = HFA384x_PORTTYPE_BSS;
+ }
+#else
+ port_type = HFA384x_PORTTYPE_BSS;
+#endif
+ /* Set the PortType */
+ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
+
+ /* Enable the Port */
+ hfa384x_drvr_enable(hw, 0);
+
+ /* Set the resultcode */
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_wlansniff
+*
+* Start or stop sniffing.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
+{
+ int result = 0;
+ p80211msg_lnxreq_wlansniff_t *msg = msgp;
+
+ hfa384x_t *hw = wlandev->priv;
+ UINT16 word;
+
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ switch (msg->enable.data)
+ {
+ case P80211ENUM_truth_false:
+ /* Confirm that we're in monitor mode */
+ if ( wlandev->netdev->type == ARPHRD_ETHER ) {
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+ result = 0;
+ goto exit;
+ }
+ /* Disable monitor mode */
+ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to disable monitor mode, result=%d\n",
+ result);
+ goto failed;
+ }
+ /* Disable port 0 */
+ result = hfa384x_drvr_disable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to disable port 0 after sniffing, result=%d\n",
+ result);
+ goto failed;
+ }
+ /* Clear the driver state */
+ wlandev->netdev->type = ARPHRD_ETHER;
+
+ /* Restore the wepflags */
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFWEPFLAGS,
+ hw->presniff_wepflags);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to restore wepflags=0x%04x, result=%d\n",
+ hw->presniff_wepflags,
+ result);
+ goto failed;
+ }
+
+ /* Set the port to its prior type and enable (if necessary) */
+ if (hw->presniff_port_type != 0 ) {
+ word = hw->presniff_port_type;
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFPORTTYPE, word);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to restore porttype, result=%d\n",
+ result);
+ goto failed;
+ }
+
+ /* Enable the port */
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result);
+ goto failed;
+ }
+ } else {
+ result = hfa384x_drvr_disable(hw, 0);
+
+ }
+
+ WLAN_LOG_INFO("monitor mode disabled\n");
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ result = 0;
+ goto exit;
+ break;
+ case P80211ENUM_truth_true:
+ /* Disable the port (if enabled), only check Port 0 */
+ if ( hw->port_enabled[0]) {
+ if (wlandev->netdev->type == ARPHRD_ETHER) {
+ /* Save macport 0 state */
+ result = hfa384x_drvr_getconfig16(hw,
+ HFA384x_RID_CNFPORTTYPE,
+ &(hw->presniff_port_type));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result);
+ goto failed;
+ }
+ /* Save the wepflags state */
+ result = hfa384x_drvr_getconfig16(hw,
+ HFA384x_RID_CNFWEPFLAGS,
+ &(hw->presniff_wepflags));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result);
+ goto failed;
+ }
+ hfa384x_drvr_stop(hw);
+ result = hfa384x_drvr_start(hw);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to restart the card for sniffing, result=%d\n",
+ result);
+ goto failed;
+ }
+ } else {
+ /* Disable the port */
+ result = hfa384x_drvr_disable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to enable port for sniffing, result=%d\n",
+ result);
+ goto failed;
+ }
+ }
+ } else {
+ hw->presniff_port_type = 0;
+ }
+
+ /* Set the channel we wish to sniff */
+ word = msg->channel.data;
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFOWNCHANNEL, word);
+ hw->sniff_channel=word;
+
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to set channel %d, result=%d\n",
+ word,
+ result);
+ goto failed;
+ }
+
+ /* Now if we're already sniffing, we can skip the rest */
+ if (wlandev->netdev->type != ARPHRD_ETHER) {
+ /* Set the port type to pIbss */
+ word = HFA384x_PORTTYPE_PSUEDOIBSS;
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_CNFPORTTYPE, word);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to set porttype %d, result=%d\n",
+ word,
+ result);
+ goto failed;
+ }
+ if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) {
+ /* Set the wepflags for no decryption */
+ word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
+ HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word);
+ }
+
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to set wepflags=0x%04x, result=%d\n",
+ word,
+ result);
+ goto failed;
+ }
+ }
+
+ /* Do we want to strip the FCS in monitor mode? */
+ if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) {
+ hw->sniff_fcs = 0;
+ } else {
+ hw->sniff_fcs = 1;
+ }
+
+ /* Do we want to truncate the packets? */
+ if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) {
+ hw->sniff_truncate = msg->packet_trunc.data;
+ } else {
+ hw->sniff_truncate = 0;
+ }
+
+ /* Enable the port */
+ result = hfa384x_drvr_enable(hw, 0);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to enable port for sniffing, result=%d\n",
+ result);
+ goto failed;
+ }
+ /* Enable monitor mode */
+ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "failed to enable monitor mode, result=%d\n",
+ result);
+ goto failed;
+ }
+
+ if (wlandev->netdev->type == ARPHRD_ETHER) {
+ WLAN_LOG_INFO("monitor mode enabled\n");
+ }
+
+ /* Set the driver state */
+ /* Do we want the prism2 header? */
+ if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {
+ hw->sniffhdr = 0;
+ wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
+ } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) {
+ hw->sniffhdr = 1;
+ wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
+ } else {
+ wlandev->netdev->type = ARPHRD_IEEE80211;
+ }
+
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ result = 0;
+ goto exit;
+ break;
+ default:
+ msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
+ result = 0;
+ goto exit;
+ break;
+ }
+
+failed:
+ msg->resultcode.data = P80211ENUM_resultcode_refused;
+ result = 0;
+exit:
+
+ DBFEXIT;
+ return result;
+}
diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h
new file mode 100644
index 00000000000..733fd999c92
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2mgmt.h
@@ -0,0 +1,182 @@
+/* prism2mgmt.h
+*
+* Declares the mgmt command handler functions
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file contains the constants and data structures for interaction
+* with the hfa384x Wireless LAN (WLAN) Media Access Contoller (MAC).
+* The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset.
+*
+* [Implementation and usage notes]
+*
+* [References]
+* CW10 Programmer's Manual v1.5
+* IEEE 802.11 D10.0
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _PRISM2MGMT_H
+#define _PRISM2MGMT_H
+
+
+/*=============================================================*/
+/*------ Constants --------------------------------------------*/
+
+/*=============================================================*/
+/*------ Macros -----------------------------------------------*/
+
+/*=============================================================*/
+/*------ Types and their related constants --------------------*/
+
+/*=============================================================*/
+/*------ Static variable externs ------------------------------*/
+
+#if (WLAN_HOSTIF != WLAN_USB)
+extern int prism2_bap_timeout;
+extern int prism2_irq_evread_max;
+#endif
+extern int prism2_debug;
+extern int prism2_reset_holdtime;
+extern int prism2_reset_settletime;
+/*=============================================================*/
+/*--- Function Declarations -----------------------------------*/
+/*=============================================================*/
+
+UINT32
+prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate);
+
+void
+prism2sta_ev_dtim(wlandevice_t *wlandev);
+void
+prism2sta_ev_infdrop(wlandevice_t *wlandev);
+void
+prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+void
+prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status);
+void
+prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status);
+void
+prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void
+prism2sta_ev_alloc(wlandevice_t *wlandev);
+
+
+int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_join(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_start(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_mm_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_channel_info(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_channel_info_results(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp);
+
+/*---------------------------------------------------------------
+* conversion functions going between wlan message data types and
+* Prism2 data types
+---------------------------------------------------------------*/
+/* byte area conversion functions*/
+void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr);
+void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len);
+
+/* byte string conversion functions*/
+void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
+void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
+
+/* integer conversion functions */
+void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint);
+void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint);
+
+/* enumerated integer conversion functions */
+void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid);
+void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid);
+
+/* functions to convert a bit area to/from an Operational Rate Set */
+void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr);
+void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr);
+
+/* functions to convert Group Addresses */
+void prism2mgmt_get_grpaddr(UINT32 did,
+ p80211pstrd_t *pstr, hfa384x_t *priv );
+int prism2mgmt_set_grpaddr(UINT32 did,
+ UINT8 *prism2buf, p80211pstrd_t *pstr, hfa384x_t *priv );
+int prism2mgmt_get_grpaddr_index( UINT32 did );
+
+void prism2sta_processing_defer(struct work_struct *data);
+
+void prism2sta_commsqual_defer(struct work_struct *data);
+void prism2sta_commsqual_timer(unsigned long data);
+
+/*=============================================================*/
+/*--- Inline Function Definitions (if supported) --------------*/
+/*=============================================================*/
+
+
+
+#endif
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
new file mode 100644
index 00000000000..268fd9bba1e
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -0,0 +1,3799 @@
+/* src/prism2/driver/prism2mib.c
+*
+* Management request for mibset/mibget
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* The functions in this file handle the mibset/mibget management
+* functions.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+#define WLAN_DBVAR prism2_debug
+
+#include "version.h"
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+
+#include "wlan_compat.h"
+
+//#if (WLAN_HOSTIF == WLAN_PCMCIA)
+//#include <pcmcia/version.h>
+//#include <pcmcia/cs_types.h>
+//#include <pcmcia/cs.h>
+//#include <pcmcia/cistpl.h>
+//#include <pcmcia/ds.h>
+//#include <pcmcia/cisreg.h>
+//#endif
+//
+//#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))
+//#include <linux/ioport.h>
+//#include <linux/pci.h>
+//endif
+
+//#if (WLAN_HOSTIF == WLAN_USB)
+#include <linux/usb.h>
+//#endif
+
+#include "wlan_compat.h"
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "hfa384x.h"
+#include "prism2mgmt.h"
+
+/*================================================================*/
+/* Local Constants */
+
+#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */
+
+/*================================================================*/
+/* Local Types */
+
+#define F_AP 0x1 /* MIB is supported on Access Points. */
+#define F_STA 0x2 /* MIB is supported on stations. */
+#define F_READ 0x4 /* MIB may be read. */
+#define F_WRITE 0x8 /* MIB may be written. */
+
+typedef struct mibrec
+{
+ UINT32 did;
+ UINT16 flag;
+ UINT16 parm1;
+ UINT16 parm2;
+ UINT16 parm3;
+ int (*func)(struct mibrec *mib,
+ int isget,
+ wlandevice_t *wlandev,
+ hfa384x_t *hw,
+ p80211msg_dot11req_mibset_t *msg,
+ void *data);
+} mibrec_t;
+
+/*================================================================*/
+/* Local Function Declarations */
+
+static int prism2mib_bytestr2pstr(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_bytearea2pstr(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_uint32(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_uint32array(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_uint32offset(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_truth(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_preamble(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_flag(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_appcfinfoflag(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_regulatorydomains(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_wepdefaultkey(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_powermanagement(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_privacyinvoked(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_excludeunencrypted(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_fragmentationthreshold(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_operationalrateset(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_groupaddress(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_fwid(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_authalg(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_authalgenable(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static int prism2mib_priv(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data);
+
+static void prism2mib_priv_authlist(
+hfa384x_t *hw,
+prism2sta_authlist_t *list);
+
+static void prism2mib_priv_accessmode(
+hfa384x_t *hw,
+UINT32 mode);
+
+static void prism2mib_priv_accessallow(
+hfa384x_t *hw,
+p80211macarray_t *macarray);
+
+static void prism2mib_priv_accessdeny(
+hfa384x_t *hw,
+p80211macarray_t *macarray);
+
+static void prism2mib_priv_deauthenticate(
+hfa384x_t *hw,
+UINT8 *addr);
+
+/*================================================================*/
+/* Local Static Definitions */
+
+static mibrec_t mibtab[] = {
+
+ /* dot11smt MIB's */
+
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11StationID,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11MediumOccupancyLimit,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0,
+ prism2mib_uint32offset },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPollable,
+ F_STA | F_READ,
+ HFA384x_RID_CFPOLLABLE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPPeriod,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1,
+ prism2mib_uint32offset },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11CFPMaxDuration,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2,
+ prism2mib_uint32offset },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11AuthenticationResponseTimeOut,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11PrivacyOptionImplemented,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PRIVACYOPTIMP, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11PowerManagementMode,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPMENABLED, 0, 0,
+ prism2mib_powermanagement },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredSSID,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0,
+ prism2mib_bytestr2pstr },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL, 0, 0,
+ prism2mib_operationalrateset },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11OperationalRateSet,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL0, 0, 0,
+ prism2mib_operationalrateset },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11BeaconPeriod,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPBCNINT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11DTIMPeriod,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNDTIMPER, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11StationConfigTable_dot11AssociationResponseTimeOut,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PROTOCOLRSPTIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm1,
+ F_AP | F_STA | F_READ,
+ 1, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm2,
+ F_AP | F_STA | F_READ,
+ 2, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm3,
+ F_AP | F_STA | F_READ,
+ 3, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm4,
+ F_AP | F_STA | F_READ,
+ 4, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm5,
+ F_AP | F_STA | F_READ,
+ 5, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithm6,
+ F_AP | F_STA | F_READ,
+ 6, 0, 0,
+ prism2mib_authalg },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable1,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 1, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable2,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 2, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable3,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 3, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable4,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 4, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable5,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 5, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11AuthenticationAlgorithmsTable_dot11AuthenticationAlgorithmsEnable6,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 6, 0, 0,
+ prism2mib_authalgenable },
+ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0,
+ prism2mib_privacyinvoked },
+ { DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0,
+ prism2mib_excludeunencrypted },
+ { DIDmib_dot11phy_dot11PhyOperationTable_dot11ShortPreambleEnabled,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFSHORTPREAMBLE, 0, 0,
+ prism2mib_preamble },
+
+ /* dot11mac MIB's */
+
+ { DIDmib_dot11mac_dot11OperationTable_dot11MACAddress,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH0, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_SHORTRETRYLIMIT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_LONGRETRYLIMIT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH0, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MAXTXLIFETIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11OperationTable_dot11MaxReceiveLifetime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MAXRXLIFETIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+ { DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32,
+ F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_groupaddress },
+
+ /* dot11phy MIB's */
+
+ { DIDmib_dot11phy_dot11PhyOperationTable_dot11PHYType,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PHYTYPE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11phy_dot11PhyOperationTable_dot11TempType,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_TEMPTYPE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
+ F_STA | F_READ,
+ HFA384x_RID_CURRENTCHANNEL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
+ F_AP | F_READ,
+ HFA384x_RID_CNFOWNCHANNEL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentCCAMode,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CCAMODE, 0, 0,
+ prism2mib_uint32 },
+
+ /* p2Table MIB's */
+
+ { DIDmib_p2_p2Table_p2MMTx,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2EarlyBeacon,
+ F_AP | F_READ | F_WRITE,
+ BIT7, 0, 0,
+ prism2mib_appcfinfoflag },
+ { DIDmib_p2_p2Table_p2ReceivedFrameStatistics,
+ F_AP | F_STA | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2CommunicationTallies,
+ F_AP | F_STA | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2Authenticated,
+ F_AP | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2Associated,
+ F_AP | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2PowerSaveUserCount,
+ F_AP | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2Comment,
+ F_AP | F_STA | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2AccessMode,
+ F_AP | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2AccessAllow,
+ F_AP | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2AccessDeny,
+ F_AP | F_READ | F_WRITE,
+ 0, 0, 0,
+ prism2mib_priv },
+ { DIDmib_p2_p2Table_p2ChannelInfoResults,
+ F_AP | F_READ,
+ 0, 0, 0,
+ prism2mib_priv },
+
+ /* p2Static MIB's */
+
+ { DIDmib_p2_p2Static_p2CnfPortType,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPORTTYPE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfOwnMACAddress,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfDesiredSSID,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, 0,
+ prism2mib_bytestr2pstr },
+ { DIDmib_p2_p2Static_p2CnfOwnChannel,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNCHANNEL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfOwnSSID,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNSSID, HFA384x_RID_CNFOWNSSID_LEN, 0,
+ prism2mib_bytestr2pstr },
+ { DIDmib_p2_p2Static_p2CnfOwnATIMWindow,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNATIMWIN, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfSystemScale,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFSYSSCALE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfMaxDataLength,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFMAXDATALEN, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR, HFA384x_RID_CNFWDSADDR_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfPMEnabled,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPMENABLED, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfPMEPS,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPMEPS, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfMulticastReceive,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFMULTICASTRX, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfMaxSleepDuration,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFMAXSLEEPDUR, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfPMHoldoverDuration,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPMHOLDDUR, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfOwnName,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNNAME, HFA384x_RID_CNFOWNNAME_LEN, 0,
+ prism2mib_bytestr2pstr },
+ { DIDmib_p2_p2Static_p2CnfOwnDTIMPeriod,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFOWNDTIMPER, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress1,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR1, HFA384x_RID_CNFWDSADDR1_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress2,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR2, HFA384x_RID_CNFWDSADDR2_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress3,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR3, HFA384x_RID_CNFWDSADDR3_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress4,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR4, HFA384x_RID_CNFWDSADDR4_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress5,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR5, HFA384x_RID_CNFWDSADDR5_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfWDSAddress6,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFWDSADDR6, HFA384x_RID_CNFWDSADDR6_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2Static_p2CnfMulticastPMBuffering,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFMCASTPMBUFF, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfWEPDefaultKeyID,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfWEPDefaultKey0,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_p2_p2Static_p2CnfWEPDefaultKey1,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_p2_p2Static_p2CnfWEPDefaultKey2,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_p2_p2Static_p2CnfWEPDefaultKey3,
+ F_AP | F_STA | F_WRITE,
+ HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0,
+ prism2mib_wepdefaultkey },
+ { DIDmib_p2_p2Static_p2CnfWEPFlags,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWEPFLAGS, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfAuthentication,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFAUTHENTICATION, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfMaxAssociatedStations,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFMAXASSOCSTATIONS, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfTxControl,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFTXCONTROL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfRoamingMode,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFROAMINGMODE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfHostAuthentication,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFHOSTAUTHASSOC, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfRcvCrcError,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFRCVCRCERROR, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfAltRetryCount,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFALTRETRYCNT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfBeaconInterval,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPBCNINT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfMediumOccupancyLimit,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 0,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2Static_p2CnfCFPPeriod,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 1,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2Static_p2CnfCFPMaxDuration,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 2,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2Static_p2CnfCFPFlags,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFAPPCFINFO, HFA384x_RID_CNFAPPCFINFO_LEN, 3,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2Static_p2CnfSTAPCFInfo,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFSTAPCFINFO, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfPriorityQUsage,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFPRIORITYQUSAGE, HFA384x_RID_CNFPRIOQUSAGE_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2Static_p2CnfTIMCtrl,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFTIMCTRL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfThirty2Tally,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFTHIRTY2TALLY, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfEnhSecurity,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFENHSECURITY, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfShortPreamble,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFSHORTPREAMBLE, 0, 0,
+ prism2mib_preamble },
+ { DIDmib_p2_p2Static_p2CnfExcludeLongPreamble,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_CNFEXCLONGPREAMBLE, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Static_p2CnfAuthenticationRspTO,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFAUTHRSPTIMEOUT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfBasicRates,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFBASICRATES, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Static_p2CnfSupportedRates,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFSUPPRATES, 0, 0,
+ prism2mib_uint32 },
+
+ /* p2Dynamic MIB's */
+
+ { DIDmib_p2_p2Dynamic_p2CreateIBSS,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CREATEIBSS, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2PromiscuousMode,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_PROMISCMODE, 0, 0,
+ prism2mib_truth },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold0,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH0, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold1,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH1, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold2,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH2, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold3,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH3, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold4,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH4, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold5,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH5, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2FragmentationThreshold6,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_FRAGTHRESH6, 0, 0,
+ prism2mib_fragmentationthreshold },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold0,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH0, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold1,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH1, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold2,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH2, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold3,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH3, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold4,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH4, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold5,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH5, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2RTSThreshold6,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_RTSTHRESH6, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl0,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL0, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl1,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL1, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl2,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL2, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl3,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL3, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl4,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL4, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl5,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL5, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Dynamic_p2TxRateControl6,
+ F_AP | F_READ | F_WRITE,
+ HFA384x_RID_TXRATECNTL6, 0, 0,
+ prism2mib_uint32 },
+
+ /* p2Behavior MIB's */
+
+ { DIDmib_p2_p2Behavior_p2TickTime,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_ITICKTIME, 0, 0,
+ prism2mib_uint32 },
+
+ /* p2NIC MIB's */
+
+ { DIDmib_p2_p2NIC_p2MaxLoadTime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MAXLOADTIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2NIC_p2DLBufferPage,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 0,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2NIC_p2DLBufferOffset,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 1,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2NIC_p2DLBufferLength,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_DOWNLOADBUFFER, HFA384x_RID_DOWNLOADBUFFER_LEN, 2,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2NIC_p2PRIIdentity,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PRIIDENTITY, HFA384x_RID_PRIIDENTITY_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2PRISupRange,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PRISUPRANGE, HFA384x_RID_PRISUPRANGE_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2CFIActRanges,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PRI_CFIACTRANGES, HFA384x_RID_CFIACTRANGES_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2BuildSequence,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_BUILDSEQ, HFA384x_RID_BUILDSEQ_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2PrimaryFWID,
+ F_AP | F_STA | F_READ,
+ 0, 0, 0,
+ prism2mib_fwid },
+ { DIDmib_p2_p2NIC_p2SecondaryFWID,
+ F_AP | F_STA | F_READ,
+ 0, 0, 0,
+ prism2mib_fwid },
+ { DIDmib_p2_p2NIC_p2TertiaryFWID,
+ F_AP | F_READ,
+ 0, 0, 0,
+ prism2mib_fwid },
+ { DIDmib_p2_p2NIC_p2NICSerialNumber,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_NICSERIALNUMBER, HFA384x_RID_NICSERIALNUMBER_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2NIC_p2NICIdentity,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_NICIDENTITY, HFA384x_RID_NICIDENTITY_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2MFISupRange,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MFISUPRANGE, HFA384x_RID_MFISUPRANGE_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2CFISupRange,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CFISUPRANGE, HFA384x_RID_CFISUPRANGE_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2ChannelList,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CHANNELLIST, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2NIC_p2RegulatoryDomains,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_REGULATORYDOMAINS, HFA384x_RID_REGULATORYDOMAINS_LEN, 0,
+ prism2mib_regulatorydomains },
+ { DIDmib_p2_p2NIC_p2TempType,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_TEMPTYPE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2NIC_p2STAIdentity,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_STAIDENTITY, HFA384x_RID_STAIDENTITY_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2STASupRange,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_STASUPRANGE, HFA384x_RID_STASUPRANGE_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2MFIActRanges,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_STA_MFIACTRANGES, HFA384x_RID_MFIACTRANGES_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2NIC_p2STACFIActRanges,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_STA_CFIACTRANGES, HFA384x_RID_CFIACTRANGES2_LEN, 0,
+ prism2mib_uint32array },
+
+ /* p2MAC MIB's */
+
+ { DIDmib_p2_p2MAC_p2PortStatus,
+ F_STA | F_READ,
+ HFA384x_RID_PORTSTATUS, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentSSID,
+ F_STA | F_READ,
+ HFA384x_RID_CURRENTSSID, HFA384x_RID_CURRENTSSID_LEN, 0,
+ prism2mib_bytestr2pstr },
+ { DIDmib_p2_p2MAC_p2CurrentBSSID,
+ F_STA | F_READ,
+ HFA384x_RID_CURRENTBSSID, HFA384x_RID_CURRENTBSSID_LEN, 0,
+ prism2mib_bytearea2pstr },
+ { DIDmib_p2_p2MAC_p2CommsQuality,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2MAC_p2CommsQualityCQ,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2CommsQualityASL,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2CommsQualityANL,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2dbmCommsQuality,
+ F_STA | F_READ,
+ HFA384x_RID_DBMCOMMSQUALITY, HFA384x_RID_DBMCOMMSQUALITY_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2MAC_p2dbmCommsQualityCQ,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 0,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2dbmCommsQualityASL,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 1,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2dbmCommsQualityANL,
+ F_STA | F_READ,
+ HFA384x_RID_COMMSQUALITY, HFA384x_RID_COMMSQUALITY_LEN, 2,
+ prism2mib_uint32offset },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate,
+ F_STA | F_READ,
+ HFA384x_RID_CURRENTTXRATE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentBeaconInterval,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CURRENTBCNINT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2StaCurrentScaleThresholds,
+ F_STA | F_READ,
+ HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_STACURSCALETHRESH_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2MAC_p2APCurrentScaleThresholds,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTSCALETHRESH, HFA384x_RID_APCURSCALETHRESH_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2MAC_p2ProtocolRspTime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PROTOCOLRSPTIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2ShortRetryLimit,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_SHORTRETRYLIMIT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2LongRetryLimit,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_LONGRETRYLIMIT, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2MaxTransmitLifetime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MAXTXLIFETIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2MaxReceiveLifetime,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_MAXRXLIFETIME, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CFPollable,
+ F_STA | F_READ,
+ HFA384x_RID_CFPOLLABLE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2AuthenticationAlgorithms,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_AUTHALGORITHMS, HFA384x_RID_AUTHALGORITHMS_LEN, 0,
+ prism2mib_uint32array },
+ { DIDmib_p2_p2MAC_p2PrivacyOptionImplemented,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PRIVACYOPTIMP, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate1,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE1, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate2,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE2, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate3,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE3, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate4,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE4, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate5,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE5, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2CurrentTxRate6,
+ F_AP | F_READ,
+ HFA384x_RID_CURRENTTXRATE6, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2MAC_p2OwnMACAddress,
+ F_AP | F_READ,
+ HFA384x_RID_OWNMACADDRESS, HFA384x_RID_OWNMACADDRESS_LEN, 0,
+ prism2mib_bytearea2pstr },
+
+ /* p2Modem MIB's */
+
+ { DIDmib_p2_p2Modem_p2PHYType,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_PHYTYPE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Modem_p2CurrentChannel,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CURRENTCHANNEL, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Modem_p2CurrentPowerState,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CURRENTPOWERSTATE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Modem_p2CCAMode,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_CCAMODE, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Modem_p2TxPowerMax,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_TXPOWERMAX, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
+ F_AP | F_STA | F_READ | F_WRITE,
+ HFA384x_RID_TXPOWERMAX, 0, 0,
+ prism2mib_uint32 },
+ { DIDmib_p2_p2Modem_p2SupportedDataRates,
+ F_AP | F_STA | F_READ,
+ HFA384x_RID_SUPPORTEDDATARATES, HFA384x_RID_SUPPORTEDDATARATES_LEN, 0,
+ prism2mib_bytestr2pstr },
+
+ /* And finally, lnx mibs */
+ { DIDmib_lnx_lnxConfigTable_lnxRSNAIE,
+ F_STA | F_READ | F_WRITE,
+ HFA384x_RID_CNFWPADATA, 0, 0,
+ prism2mib_priv },
+ { 0, 0, 0, 0, 0, NULL}};
+
+/*----------------------------------------------------------------
+These MIB's are not supported at this time:
+
+DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityPresent
+DIDmib_dot11phy_dot11PhyOperationTable_dot11ChannelAgilityEnabled
+DIDmib_dot11phy_dot11PhyDSSSTable_dot11PBCCOptionImplemented
+DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportIndex
+DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxIndex
+DIDmib_dot11phy_dot11SupportedDataRatesTxTable_dot11SupportedDataRatesTxValue
+DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxIndex
+DIDmib_dot11phy_dot11SupportedDataRatesRxTable_dot11SupportedDataRatesRxValue
+
+DIDmib_dot11phy_dot11RegDomainsSupportedTable_dot11RegDomainsSupportValue
+TODO: need to investigate why wlan has this as enumerated and Prism2 has this
+ as btye str.
+
+DIDmib_dot11phy_dot11PhyDSSSTable_dot11ShortPreambleOptionImplemented
+TODO: Find out the firmware version number(s) for identifying
+ whether the firmware is capable of short preamble. TRUE or FALSE
+ will be returned based on the version of the firmware.
+
+WEP Key mappings aren't supported in the f/w.
+DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingIndex
+DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingAddress
+DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingWEPOn
+DIDmib_dot11smt_dot11WEPKeyMappingsTable_dot11WEPKeyMappingValue
+DIDmib_dot11smt_dot11PrivacyTable_dot11WEPKeyMappingLength
+
+TODO: implement counters.
+DIDmib_dot11smt_dot11PrivacyTable_dot11WEPICVErrorCount
+DIDmib_dot11smt_dot11PrivacyTable_dot11WEPExcludedCount
+DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFragmentCount
+DIDmib_dot11mac_dot11CountersTable_dot11MulticastTransmittedFrameCount
+DIDmib_dot11mac_dot11CountersTable_dot11FailedCount
+DIDmib_dot11mac_dot11CountersTable_dot11RetryCount
+DIDmib_dot11mac_dot11CountersTable_dot11MultipleRetryCount
+DIDmib_dot11mac_dot11CountersTable_dot11FrameDuplicateCount
+DIDmib_dot11mac_dot11CountersTable_dot11RTSSuccessCount
+DIDmib_dot11mac_dot11CountersTable_dot11RTSFailureCount
+DIDmib_dot11mac_dot11CountersTable_dot11ACKFailureCount
+DIDmib_dot11mac_dot11CountersTable_dot11ReceivedFragmentCount
+DIDmib_dot11mac_dot11CountersTable_dot11MulticastReceivedFrameCount
+DIDmib_dot11mac_dot11CountersTable_dot11FCSErrorCount
+DIDmib_dot11mac_dot11CountersTable_dot11TransmittedFrameCount
+DIDmib_dot11mac_dot11CountersTable_dot11WEPUndecryptableCount
+
+TODO: implement sane values for these.
+DIDmib_dot11mac_dot11OperationTable_dot11ManufacturerID
+DIDmib_dot11mac_dot11OperationTable_dot11ProductID
+
+Not too worried about these at the moment.
+DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentTxAntenna
+DIDmib_dot11phy_dot11PhyAntennaTable_dot11DiversitySupport
+DIDmib_dot11phy_dot11PhyAntennaTable_dot11CurrentRxAntenna
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11NumberSupportedPowerLevels
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8
+DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel
+
+Ummm, FH and IR don't apply
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11HopTime
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentChannelNumber
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11MaxDwellTime
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentDwellTime
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentSet
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentPattern
+DIDmib_dot11phy_dot11PhyFHSSTable_dot11CurrentIndex
+DIDmib_dot11phy_dot11PhyDSSSTable_dot11CCAModeSupported
+DIDmib_dot11phy_dot11PhyDSSSTable_dot11EDThreshold
+DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMax
+DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMax
+DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogTimerMin
+DIDmib_dot11phy_dot11PhyIRTable_dot11CCAWatchdogCountMin
+
+We just don't have enough antennas right now to worry about this.
+DIDmib_dot11phy_dot11AntennasListTable_dot11AntennaListIndex
+DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedTxAntenna
+DIDmib_dot11phy_dot11AntennasListTable_dot11SupportedRxAntenna
+DIDmib_dot11phy_dot11AntennasListTable_dot11DiversitySelectionRx
+
+------------------------------------------------------------------*/
+
+/*================================================================*/
+/* Function Definitions */
+
+/*----------------------------------------------------------------
+* prism2mgmt_mibset_mibget
+*
+* Set the value of a mib item.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* 0 success and done
+* <0 success, but we're waiting for something to finish.
+* >0 an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+
+int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp)
+{
+ hfa384x_t *hw = wlandev->priv;
+ int result, isget;
+ mibrec_t *mib;
+ UINT16 which;
+
+ p80211msg_dot11req_mibset_t *msg = msgp;
+ p80211itemd_t *mibitem;
+
+ DBFENTER;
+
+ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+
+ /*
+ ** Determine if this is an Access Point or a station.
+ */
+
+ which = hw->ap ? F_AP : F_STA;
+
+ /*
+ ** Find the MIB in the MIB table. Note that a MIB may be in the
+ ** table twice...once for an AP and once for a station. Make sure
+ ** to get the correct one. Note that DID=0 marks the end of the
+ ** MIB table.
+ */
+
+ mibitem = (p80211itemd_t *) msg->mibattribute.data;
+
+ for (mib = mibtab; mib->did != 0; mib++)
+ if (mib->did == mibitem->did && (mib->flag & which))
+ break;
+
+ if (mib->did == 0) {
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ goto done;
+ }
+
+ /*
+ ** Determine if this is a "mibget" or a "mibset". If this is a
+ ** "mibget", then make sure that the MIB may be read. Otherwise,
+ ** this is a "mibset" so make make sure that the MIB may be written.
+ */
+
+ isget = (msg->msgcode == DIDmsg_dot11req_mibget);
+
+ if (isget) {
+ if (!(mib->flag & F_READ)) {
+ msg->resultcode.data =
+ P80211ENUM_resultcode_cant_get_writeonly_mib;
+ goto done;
+ }
+ } else {
+ if (!(mib->flag & F_WRITE)) {
+ msg->resultcode.data =
+ P80211ENUM_resultcode_cant_set_readonly_mib;
+ goto done;
+ }
+ }
+
+ /*
+ ** Execute the MIB function. If things worked okay, then make
+ ** sure that the MIB function also worked okay. If so, and this
+ ** is a "mibget", then the status value must be set for both the
+ ** "mibattribute" parameter and the mib item within the data
+ ** portion of the "mibattribute".
+ */
+
+ result = mib->func(mib, isget, wlandev, hw, msg,
+ (void *) mibitem->data);
+
+ if (msg->resultcode.data == P80211ENUM_resultcode_success) {
+ if (result != 0) {
+ WLAN_LOG_DEBUG(1, "get/set failure, result=%d\n",
+ result);
+ msg->resultcode.data =
+ P80211ENUM_resultcode_implementation_failure;
+ } else {
+ if (isget) {
+ msg->mibattribute.status =
+ P80211ENUM_msgitem_status_data_ok;
+ mibitem->status =
+ P80211ENUM_msgitem_status_data_ok;
+ }
+ }
+ }
+
+done:
+ DBFEXIT;
+
+ return(0);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_bytestr2pstr
+*
+* Get/set pstr data to/from a byte string.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_bytestr2pstr(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*) bytebuf;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2);
+ prism2mgmt_bytestr2pstr(p2bytestr, pstr);
+ } else {
+ memset(bytebuf, 0, mib->parm2);
+ prism2mgmt_pstr2bytestr(p2bytestr, pstr);
+ result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_bytearea2pstr
+*
+* Get/set pstr data to/from a byte area.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_bytearea2pstr(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2);
+ prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2);
+ } else {
+ memset(bytebuf, 0, mib->parm2);
+ prism2mgmt_pstr2bytearea(bytebuf, pstr);
+ result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_uint32
+*
+* Get/set uint32 data.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_uint32(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf);
+ *uint32 = *wordbuf;
+ /* [MSM] Removed, getconfig16 returns the value in host order.
+ * prism2mgmt_prism2int2p80211int(wordbuf, uint32);
+ */
+ } else {
+ /* [MSM] Removed, setconfig16 expects host order.
+ * prism2mgmt_p80211int2prism2int(wordbuf, uint32);
+ */
+ *wordbuf = *uint32;
+ result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_uint32array
+*
+* Get/set an array of uint32 data.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_uint32array(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32 *) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+ int i, cnt;
+
+ DBFENTER;
+
+ cnt = mib->parm2 / sizeof(UINT16);
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2);
+ for (i = 0; i < cnt; i++)
+ prism2mgmt_prism2int2p80211int(wordbuf+i, uint32+i);
+ } else {
+ for (i = 0; i < cnt; i++)
+ prism2mgmt_p80211int2prism2int(wordbuf+i, uint32+i);
+ result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_uint32offset
+*
+* Get/set a single element in an array of uint32 data.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Element index.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_uint32offset(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+ UINT16 cnt;
+
+ DBFENTER;
+
+ cnt = mib->parm2 / sizeof(UINT16);
+
+ result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2);
+ if (result == 0) {
+ if (isget) {
+ if (mib->parm3 < cnt)
+ prism2mgmt_prism2int2p80211int(wordbuf+mib->parm3, uint32);
+ else
+ *uint32 = 0;
+ } else {
+ if (mib->parm3 < cnt) {
+ prism2mgmt_p80211int2prism2int(wordbuf+mib->parm3, uint32);
+ result = hfa384x_drvr_setconfig(hw, mib->parm1, wordbuf, mib->parm2);
+ }
+ }
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_truth
+*
+* Get/set truth data.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_truth(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf);
+ *uint32 = (*wordbuf) ?
+ P80211ENUM_truth_true : P80211ENUM_truth_false;
+ } else {
+ *wordbuf = ((*uint32) == P80211ENUM_truth_true) ? 1 : 0;
+ result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_flag
+*
+* Get/set a flag.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Bit to get/set.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_flag(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+ UINT32 flags;
+
+ DBFENTER;
+
+ result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf);
+ if (result == 0) {
+ /* [MSM] Removed, getconfig16 returns the value in host order.
+ * prism2mgmt_prism2int2p80211int(wordbuf, &flags);
+ */
+ flags = *wordbuf;
+ if (isget) {
+ *uint32 = (flags & mib->parm2) ?
+ P80211ENUM_truth_true : P80211ENUM_truth_false;
+ } else {
+ if ((*uint32) == P80211ENUM_truth_true)
+ flags |= mib->parm2;
+ else
+ flags &= ~mib->parm2;
+ /* [MSM] Removed, setconfig16 expects host order.
+ * prism2mgmt_p80211int2prism2int(wordbuf, &flags);
+ */
+ *wordbuf = flags;
+ result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf);
+ }
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_appcfinfoflag
+*
+* Get/set a single flag in the APPCFINFO record.
+*
+* MIB record parameters:
+* parm1 Bit to get/set.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_appcfinfoflag(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+ UINT16 word;
+
+ DBFENTER;
+
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO,
+ bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN);
+ if (result == 0) {
+ if (isget) {
+ *uint32 = (hfa384x2host_16(wordbuf[3]) & mib->parm1) ?
+ P80211ENUM_truth_true : P80211ENUM_truth_false;
+ } else {
+ word = hfa384x2host_16(wordbuf[3]);
+ word = ((*uint32) == P80211ENUM_truth_true) ?
+ (word | mib->parm1) : (word & ~mib->parm1);
+ wordbuf[3] = host2hfa384x_16(word);
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO,
+ bytebuf, HFA384x_RID_CNFAPPCFINFO_LEN);
+ }
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_regulatorydomains
+*
+* Get regulatory domain data.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_regulatorydomains(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 cnt;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+
+ DBFENTER;
+
+ result = 0;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig(hw, mib->parm1, wordbuf, mib->parm2);
+ prism2mgmt_prism2int2p80211int(wordbuf, &cnt);
+ pstr->len = (UINT8) cnt;
+ memcpy(pstr->data, &wordbuf[1], pstr->len);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_wepdefaultkey
+*
+* Get/set WEP default keys.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Number of bytes of RID data.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_wepdefaultkey(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 len;
+
+ DBFENTER;
+
+ if (isget) {
+ result = 0; /* Should never happen. */
+ } else {
+ len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN :
+ HFA384x_RID_CNFWEPDEFAULTKEY_LEN;
+ memset(bytebuf, 0, len);
+ prism2mgmt_pstr2bytearea(bytebuf, pstr);
+ result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_powermanagement
+*
+* Get/set 802.11 power management value. Note that this is defined differently
+* by 802.11 and Prism2:
+*
+* Meaning 802.11 Prism2
+* active 1 false
+* powersave 2 true
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_powermanagement(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT32 value;
+
+ DBFENTER;
+
+ if (isget) {
+ result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value);
+ *uint32 = (value == 0) ? 1 : 2;
+ } else {
+ value = ((*uint32) == 1) ? 0 : 1;
+ result = prism2mib_uint32(mib, isget, wlandev, hw, msg, &value);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_preamble
+*
+* Get/set Prism2 short preamble
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_preamble(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf);
+ *uint32 = *wordbuf;
+ } else {
+ *wordbuf = *uint32;
+ result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_privacyinvoked
+*
+* Get/set the dot11PrivacyInvoked value.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Bit value for PrivacyInvoked flag.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_privacyinvoked(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+
+ DBFENTER;
+
+ if (wlandev->hostwep & HOSTWEP_DECRYPT) {
+ if (wlandev->hostwep & HOSTWEP_DECRYPT)
+ mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
+ if (wlandev->hostwep & HOSTWEP_ENCRYPT)
+ mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_TXCRYPT;
+ }
+
+ result = prism2mib_flag(mib, isget, wlandev, hw, msg, data);
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_excludeunencrypted
+*
+* Get/set the dot11ExcludeUnencrypted value.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Bit value for ExcludeUnencrypted flag.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_excludeunencrypted(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+
+ DBFENTER;
+
+ result = prism2mib_flag(mib, isget, wlandev, hw, msg, data);
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_fragmentationthreshold
+*
+* Get/set the fragmentation threshold.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_fragmentationthreshold(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+
+ DBFENTER;
+
+ if (!isget)
+ if ((*uint32) % 2) {
+ WLAN_LOG_WARNING("Attempt to set odd number "
+ "FragmentationThreshold\n");
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ return(0);
+ }
+
+ result = prism2mib_uint32(mib, isget, wlandev, hw, msg, data);
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_operationalrateset
+*
+* Get/set the operational rate set.
+*
+* MIB record parameters:
+* parm1 Prism2 RID value.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_operationalrateset(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t *) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 *wordbuf = (UINT16*) bytebuf;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf);
+ prism2mgmt_get_oprateset(wordbuf, pstr);
+ } else {
+ prism2mgmt_set_oprateset(wordbuf, pstr);
+ result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf);
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, *wordbuf);
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_groupaddress
+*
+* Get/set the dot11GroupAddressesTable.
+*
+* MIB record parameters:
+* parm1 Not used.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_groupaddress(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t *) data;
+ UINT8 bytebuf[MIB_TMP_MAXLEN];
+ UINT16 len;
+
+ DBFENTER;
+
+ /* TODO: fix this. f/w doesn't support mcast filters */
+
+ if (isget) {
+ prism2mgmt_get_grpaddr(mib->did, pstr, hw);
+ return(0);
+ }
+
+ result = prism2mgmt_set_grpaddr(mib->did, bytebuf, pstr, hw);
+ if (result != 0) {
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ return(result);
+ }
+
+ if (hw->dot11_grpcnt <= MAX_PRISM2_GRP_ADDR) {
+ len = hw->dot11_grpcnt * WLAN_ADDR_LEN;
+ memcpy(bytebuf, hw->dot11_grp_addr[0], len);
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR, bytebuf, len);
+
+ /*
+ ** Turn off promiscuous mode if count is equal to MAX. We may
+ ** have been at a higher count in promiscuous mode and need to
+ ** turn it off.
+ */
+
+ /* but only if we're not already in promisc mode. :) */
+ if ((hw->dot11_grpcnt == MAX_PRISM2_GRP_ADDR) &&
+ !( wlandev->netdev->flags & IFF_PROMISC)) {
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_PROMISCMODE, 0);
+ }
+ } else {
+
+ /*
+ ** Clear group addresses in card and set to promiscuous mode.
+ */
+
+ memset(bytebuf, 0, sizeof(bytebuf));
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_GROUPADDR,
+ bytebuf, 0);
+ if (result == 0) {
+ result = hfa384x_drvr_setconfig16(hw,
+ HFA384x_RID_PROMISCMODE, 1);
+ }
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_fwid
+*
+* Get the firmware ID.
+*
+* MIB record parameters:
+* parm1 Not used.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_fwid(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ p80211pstrd_t *pstr = (p80211pstrd_t *) data;
+ hfa384x_FWID_t fwid;
+
+ DBFENTER;
+
+ if (isget) {
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_FWID,
+ &fwid, HFA384x_RID_FWID_LEN);
+ if (mib->did == DIDmib_p2_p2NIC_p2PrimaryFWID) {
+ fwid.primary[HFA384x_FWID_LEN - 1] = '\0';
+ pstr->len = strlen(fwid.primary);
+ memcpy(pstr->data, fwid.primary, pstr->len);
+ } else {
+ fwid.secondary[HFA384x_FWID_LEN - 1] = '\0';
+ pstr->len = strlen(fwid.secondary);
+ memcpy(pstr->data, fwid.secondary, pstr->len);
+ }
+ } else
+ result = 0; /* Should never happen. */
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_authalg
+*
+* Get values from the AuhtenticationAlgorithmsTable.
+*
+* MIB record parameters:
+* parm1 Table index (1-6).
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_authalg(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ UINT32 *uint32 = (UINT32*) data;
+
+ DBFENTER;
+
+ /* MSM: pkx supplied code that code queries RID FD4D....but the f/w's
+ * results are bogus. Therefore, we have to simulate the appropriate
+ * results here in the driver based on our knowledge of existing MAC
+ * features. That's the whole point behind this ugly function.
+ */
+
+ if (isget) {
+ msg->resultcode.data = P80211ENUM_resultcode_success;
+ switch (mib->parm1) {
+ case 1: /* Open System */
+ *uint32 = P80211ENUM_authalg_opensystem;
+ break;
+ case 2: /* SharedKey */
+ *uint32 = P80211ENUM_authalg_sharedkey;
+ break;
+ default:
+ *uint32 = 0;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ break;
+ }
+ }
+
+ DBFEXIT;
+ return(0);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_authalgenable
+*
+* Get/set the enable values from the AuhtenticationAlgorithmsTable.
+*
+* MIB record parameters:
+* parm1 Table index (1-6).
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_authalgenable(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ int result;
+ UINT32 *uint32 = (UINT32*) data;
+
+ int index;
+ UINT16 cnf_auth;
+ UINT16 mask;
+
+ DBFENTER;
+
+ index = mib->parm1 - 1;
+
+ result = hfa384x_drvr_getconfig16( hw,
+ HFA384x_RID_CNFAUTHENTICATION, &cnf_auth);
+ WLAN_LOG_DEBUG(2,"cnfAuthentication0=%d, index=%d\n", cnf_auth, index);
+
+ if (isget) {
+ if ( index == 0 || index == 1 ) {
+ *uint32 = (cnf_auth & (1<<index)) ?
+ P80211ENUM_truth_true: P80211ENUM_truth_false;
+ } else {
+ *uint32 = P80211ENUM_truth_false;
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+ } else {
+ if ( index == 0 || index == 1 ) {
+ mask = 1 << index;
+ if (*uint32==P80211ENUM_truth_true ) {
+ cnf_auth |= mask;
+ } else {
+ cnf_auth &= ~mask;
+ }
+ result = hfa384x_drvr_setconfig16( hw,
+ HFA384x_RID_CNFAUTHENTICATION, cnf_auth);
+ WLAN_LOG_DEBUG(2,"cnfAuthentication:=%d\n", cnf_auth);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,"Unable to set p2cnfAuthentication to %d\n", cnf_auth);
+ msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
+ }
+ } else {
+ msg->resultcode.data = P80211ENUM_resultcode_not_supported;
+ }
+ }
+
+ DBFEXIT;
+ return(result);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv
+*
+* Get/set values in the "priv" data structure.
+*
+* MIB record parameters:
+* parm1 Not used.
+* parm2 Not used.
+* parm3 Not used.
+*
+* Arguments:
+* mib MIB record.
+* isget MIBGET/MIBSET flag.
+* wlandev wlan device structure.
+* priv "priv" structure.
+* hw "hw" structure.
+* msg Message structure.
+* data Data buffer.
+*
+* Returns:
+* 0 - Success.
+* ~0 - Error.
+*
+----------------------------------------------------------------*/
+
+static int prism2mib_priv(
+mibrec_t *mib,
+int isget,
+wlandevice_t *wlandev,
+hfa384x_t *hw,
+p80211msg_dot11req_mibset_t *msg,
+void *data)
+{
+ UINT32 *uint32 = (UINT32*) data;
+ p80211pstrd_t *pstr = (p80211pstrd_t*) data;
+ p80211macarray_t *macarray = (p80211macarray_t *) data;
+
+ int i, cnt, result, done;
+
+ prism2sta_authlist_t old;
+
+ /*
+ ** "test" is a lot longer than necessary but who cares? ...as long as
+ ** it is long enough!
+ */
+
+ UINT8 test[sizeof(wlandev->rx) + sizeof(hw->tallies)];
+
+ DBFENTER;
+
+ switch (mib->did) {
+ case DIDmib_p2_p2Table_p2ReceivedFrameStatistics:
+
+ /*
+ ** Note: The values in this record are changed by the
+ ** interrupt handler and therefore cannot be guaranteed
+ ** to be stable while they are being copied. However,
+ ** the interrupt handler will take priority over this
+ ** code. Hence, if the same values are copied twice,
+ ** then we are ensured that the values have not been
+ ** changed. If they have, then just try again. Don't
+ ** try more than 10 times...if we still haven't got it,
+ ** then the values we do have are probably good enough.
+ ** This scheme for copying values is used in order to
+ ** prevent having to block the interrupt handler while
+ ** we copy the values.
+ */
+
+ if (isget)
+ for (i = 0; i < 10; i++) {
+ memcpy(data, &wlandev->rx, sizeof(wlandev->rx));
+ memcpy(test, &wlandev->rx, sizeof(wlandev->rx));
+ if (memcmp(data, test, sizeof(wlandev->rx)) == 0) break;
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2CommunicationTallies:
+
+ /*
+ ** Note: The values in this record are changed by the
+ ** interrupt handler and therefore cannot be guaranteed
+ ** to be stable while they are being copied. See the
+ ** note above about copying values.
+ */
+
+ if (isget) {
+ result = hfa384x_drvr_commtallies(hw);
+
+ /* ?????? We need to wait a bit here for the */
+ /* tallies to get updated. ?????? */
+ /* MSM: TODO: The right way to do this is to
+ * add a "commtallie" wait queue to the
+ * priv structure that gets run every time
+ * we receive a commtally info frame.
+ * This process would sleep on that
+ * queue and get awakened when the
+ * the requested info frame arrives.
+ * Don't have time to do and test this
+ * right now.
+ */
+
+ /* Ugh, this is nasty. */
+ for (i = 0; i < 10; i++) {
+ memcpy(data,
+ &hw->tallies,
+ sizeof(hw->tallies));
+ memcpy(test,
+ &hw->tallies,
+ sizeof(hw->tallies));
+ if ( memcmp(data,
+ test,
+ sizeof(hw->tallies)) == 0)
+ break;
+ }
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2Authenticated:
+
+ if (isget) {
+ prism2mib_priv_authlist(hw, &old);
+
+ macarray->cnt = 0;
+ for (i = 0; i < old.cnt; i++) {
+ if (!old.assoc[i]) {
+ memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN);
+ macarray->cnt++;
+ }
+ }
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2Associated:
+
+ if (isget) {
+ prism2mib_priv_authlist(hw, &old);
+
+ macarray->cnt = 0;
+ for (i = 0; i < old.cnt; i++) {
+ if (old.assoc[i]) {
+ memcpy(macarray->data[macarray->cnt], old.addr[i], WLAN_ADDR_LEN);
+ macarray->cnt++;
+ }
+ }
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2PowerSaveUserCount:
+
+ if (isget)
+ *uint32 = hw->psusercount;
+
+ break;
+
+ case DIDmib_p2_p2Table_p2Comment:
+
+ if (isget) {
+ pstr->len = strlen(hw->comment);
+ memcpy(pstr->data, hw->comment, pstr->len);
+ } else {
+ cnt = pstr->len;
+ if (cnt < 0) cnt = 0;
+ if (cnt >= sizeof(hw->comment))
+ cnt = sizeof(hw->comment)-1;
+ memcpy(hw->comment, pstr->data, cnt);
+ pstr->data[cnt] = '\0';
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2AccessMode:
+
+ if (isget)
+ *uint32 = hw->accessmode;
+ else
+ prism2mib_priv_accessmode(hw, *uint32);
+
+ break;
+
+ case DIDmib_p2_p2Table_p2AccessAllow:
+
+ if (isget) {
+ macarray->cnt = hw->allow.cnt;
+ memcpy(macarray->data, hw->allow.addr,
+ macarray->cnt*WLAN_ADDR_LEN);
+ } else {
+ prism2mib_priv_accessallow(hw, macarray);
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2AccessDeny:
+
+ if (isget) {
+ macarray->cnt = hw->deny.cnt;
+ memcpy(macarray->data, hw->deny.addr,
+ macarray->cnt*WLAN_ADDR_LEN);
+ } else {
+ prism2mib_priv_accessdeny(hw, macarray);
+ }
+
+ break;
+
+ case DIDmib_p2_p2Table_p2ChannelInfoResults:
+
+ if (isget) {
+ done = atomic_read(&hw->channel_info.done);
+ if (done == 0) {
+ msg->resultcode.status = P80211ENUM_msgitem_status_no_value;
+ break;
+ }
+ if (done == 1) {
+ msg->resultcode.status = P80211ENUM_msgitem_status_incomplete_itemdata;
+ break;
+ }
+
+ for (i = 0; i < 14; i++, uint32 += 5) {
+ uint32[0] = i+1;
+ uint32[1] = hw->channel_info.results.result[i].anl;
+ uint32[2] = hw->channel_info.results.result[i].pnl;
+ uint32[3] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_BSSACTIVE) ? 1 : 0;
+ uint32[4] = (hw->channel_info.results.result[i].active & HFA384x_CHINFORESULT_PCFACTIVE) ? 1 : 0;
+ }
+ }
+
+ break;
+
+ case DIDmib_dot11smt_dot11StationConfigTable_dot11DesiredBSSType:
+
+ if (isget)
+ *uint32 = hw->dot11_desired_bss_type;
+ else
+ hw->dot11_desired_bss_type = *uint32;
+
+ break;
+
+ case DIDmib_lnx_lnxConfigTable_lnxRSNAIE: {
+ hfa384x_WPAData_t wpa;
+ if (isget) {
+ hfa384x_drvr_getconfig( hw, HFA384x_RID_CNFWPADATA,
+ (UINT8 *) &wpa, sizeof(wpa));
+ pstr->len = hfa384x2host_16(wpa.datalen);
+ memcpy(pstr->data, wpa.data, pstr->len);
+ } else {
+ wpa.datalen = host2hfa384x_16(pstr->len);
+ memcpy(wpa.data, pstr->data, pstr->len);
+
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA,
+ (UINT8 *) &wpa, sizeof(wpa));
+ }
+ break;
+ }
+ default:
+ WLAN_LOG_ERROR("Unhandled DID 0x%08x\n", mib->did);
+ }
+
+ DBFEXIT;
+ return(0);
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv_authlist
+*
+* Get a copy of the list of authenticated stations.
+*
+* Arguments:
+* priv "priv" structure.
+* list List of authenticated stations.
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+static void prism2mib_priv_authlist(
+hfa384x_t *hw,
+prism2sta_authlist_t *list)
+{
+ prism2sta_authlist_t test;
+ int i;
+
+ DBFENTER;
+
+ /*
+ ** Note: The values in this record are changed by the interrupt
+ ** handler and therefore cannot be guaranteed to be stable while
+ ** they are being copied. However, the interrupt handler will
+ ** take priority over this code. Hence, if the same values are
+ ** copied twice, then we are ensured that the values have not
+ ** been changed. If they have, then just try again. Don't try
+ ** more than 10 times...the list of authenticated stations is
+ ** unlikely to be changing frequently enough that we can't get
+ ** a snapshot in 10 tries. Don't try more than this so that we
+ ** don't risk locking-up for long periods of time. If we still
+ ** haven't got the snapshot, then generate an error message and
+ ** return an empty list (since this is the only valid list that
+ ** we can guarentee). This scheme for copying values is used in
+ ** order to prevent having to block the interrupt handler while
+ ** we copy the values.
+ */
+
+ for (i = 0; i < 10; i++) {
+ memcpy(list, &hw->authlist, sizeof(prism2sta_authlist_t));
+ memcpy(&test, &hw->authlist, sizeof(prism2sta_authlist_t));
+ if (memcmp(list, &test, sizeof(prism2sta_authlist_t)) == 0)
+ break;
+ }
+
+ if (i >= 10) {
+ list->cnt = 0;
+ WLAN_LOG_ERROR("Could not obtain snapshot of authenticated stations.\n");
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv_accessmode
+*
+* Set the Access Mode.
+*
+* Arguments:
+* priv "priv" structure.
+* hw "hw" structure.
+* mode New access mode.
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+static void prism2mib_priv_accessmode(
+hfa384x_t *hw,
+UINT32 mode)
+{
+ prism2sta_authlist_t old;
+ int i, j, deauth;
+ UINT8 *addr;
+
+ DBFENTER;
+
+ /*
+ ** If the mode is not changing or it is changing to "All", then it's
+ ** okay to go ahead without a lot of messing around. Otherwise, the
+ ** access mode is changing in a way that may leave some stations
+ ** authenticated which should not be authenticated. It will be
+ ** necessary to de-authenticate these stations.
+ */
+
+ if (mode == WLAN_ACCESS_ALL || mode == hw->accessmode) {
+ hw->accessmode = mode;
+ return;
+ }
+
+ /*
+ ** Switch to the new access mode. Once this is done, then the interrupt
+ ** handler (which uses this value) will be prevented from authenticating
+ ** ADDITIONAL stations which should not be authenticated. Then get a
+ ** copy of the current list of authenticated stations.
+ */
+
+ hw->accessmode = mode;
+
+ prism2mib_priv_authlist(hw, &old);
+
+ /*
+ ** Now go through the list of previously authenticated stations (some
+ ** of which might de-authenticate themselves while we are processing it
+ ** but that is okay). Any station which no longer matches the access
+ ** mode, must be de-authenticated.
+ */
+
+ for (i = 0; i < old.cnt; i++) {
+ addr = old.addr[i];
+
+ if (mode == WLAN_ACCESS_NONE)
+ deauth = 1;
+ else {
+ if (mode == WLAN_ACCESS_ALLOW) {
+ for (j = 0; j < hw->allow.cnt; j++)
+ if (memcmp(addr, hw->allow.addr[j],
+ WLAN_ADDR_LEN) == 0)
+ break;
+ deauth = (j >= hw->allow.cnt);
+ } else {
+ for (j = 0; j < hw->deny.cnt; j++)
+ if (memcmp(addr, hw->deny.addr[j],
+ WLAN_ADDR_LEN) == 0)
+ break;
+ deauth = (j < hw->deny.cnt);
+ }
+ }
+
+ if (deauth) prism2mib_priv_deauthenticate(hw, addr);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv_accessallow
+*
+* Change the list of allowed MAC addresses.
+*
+* Arguments:
+* priv "priv" structure.
+* hw "hw" structure.
+* macarray New array of MAC addresses.
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+static void prism2mib_priv_accessallow(
+hfa384x_t *hw,
+p80211macarray_t *macarray)
+{
+ prism2sta_authlist_t old;
+ int i, j;
+
+ DBFENTER;
+
+ /*
+ ** Change the access list. Note that the interrupt handler may be in
+ ** the middle of using the access list!!! Since the interrupt handler
+ ** will always have priority over this process and this is the only
+ ** process that will modify the list, this problem can be handled as
+ ** follows:
+ **
+ ** 1. Set the "modify" flag.
+ ** 2. Change the first copy of the list.
+ ** 3. Clear the "modify" flag.
+ ** 4. Change the backup copy of the list.
+ **
+ ** The interrupt handler will check the "modify" flag. If NOT set, then
+ ** the first copy of the list is valid and may be used. Otherwise, the
+ ** first copy is being changed but the backup copy is valid and may be
+ ** used. Doing things this way prevents having to have the interrupt
+ ** handler block while the list is being updated.
+ */
+
+ hw->allow.modify = 1;
+
+ hw->allow.cnt = macarray->cnt;
+ memcpy(hw->allow.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN);
+
+ hw->allow.modify = 0;
+
+ hw->allow.cnt1 = macarray->cnt;
+ memcpy(hw->allow.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN);
+
+ /*
+ ** If the current access mode is "Allow", then changing the access
+ ** list may leave some stations authenticated which should not be
+ ** authenticated. It will be necessary to de-authenticate these
+ ** stations. Otherwise, the list can be changed without a lot of fuss.
+ */
+
+ if (hw->accessmode == WLAN_ACCESS_ALLOW) {
+
+ /*
+ ** Go through the list of authenticated stations (some of
+ ** which might de-authenticate themselves while we are
+ ** processing it but that is okay). Any station which is
+ ** no longer in the list of allowed stations, must be
+ ** de-authenticated.
+ */
+
+ prism2mib_priv_authlist(hw, &old);
+
+ for (i = 0; i < old.cnt; i++) {
+ for (j = 0; j < hw->allow.cnt; j++)
+ if (memcmp(old.addr[i], hw->allow.addr[j],
+ WLAN_ADDR_LEN) == 0)
+ break;
+ if (j >= hw->allow.cnt)
+ prism2mib_priv_deauthenticate(hw, old.addr[i]);
+ }
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv_accessdeny
+*
+* Change the list of denied MAC addresses.
+*
+* Arguments:
+* priv "priv" structure.
+* hw "hw" structure.
+* macarray New array of MAC addresses.
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+static void prism2mib_priv_accessdeny(
+hfa384x_t *hw,
+p80211macarray_t *macarray)
+{
+ prism2sta_authlist_t old;
+ int i, j;
+
+ DBFENTER;
+
+ /*
+ ** Change the access list. Note that the interrupt handler may be in
+ ** the middle of using the access list!!! Since the interrupt handler
+ ** will always have priority over this process and this is the only
+ ** process that will modify the list, this problem can be handled as
+ ** follows:
+ **
+ ** 1. Set the "modify" flag.
+ ** 2. Change the first copy of the list.
+ ** 3. Clear the "modify" flag.
+ ** 4. Change the backup copy of the list.
+ **
+ ** The interrupt handler will check the "modify" flag. If NOT set, then
+ ** the first copy of the list is valid and may be used. Otherwise, the
+ ** first copy is being changed but the backup copy is valid and may be
+ ** used. Doing things this way prevents having to have the interrupt
+ ** handler block while the list is being updated.
+ */
+
+ hw->deny.modify = 1;
+
+ hw->deny.cnt = macarray->cnt;
+ memcpy(hw->deny.addr, macarray->data, macarray->cnt*WLAN_ADDR_LEN);
+
+ hw->deny.modify = 0;
+
+ hw->deny.cnt1 = macarray->cnt;
+ memcpy(hw->deny.addr1, macarray->data, macarray->cnt*WLAN_ADDR_LEN);
+
+ /*
+ ** If the current access mode is "Deny", then changing the access
+ ** list may leave some stations authenticated which should not be
+ ** authenticated. It will be necessary to de-authenticate these
+ ** stations. Otherwise, the list can be changed without a lot of fuss.
+ */
+
+ if (hw->accessmode == WLAN_ACCESS_DENY) {
+
+ /*
+ ** Go through the list of authenticated stations (some of
+ ** which might de-authenticate themselves while we are
+ ** processing it but that is okay). Any station which is
+ ** now in the list of denied stations, must be de-authenticated.
+ */
+
+ prism2mib_priv_authlist(hw, &old);
+
+ for (i = 0; i < old.cnt; i++)
+ for (j = 0; j < hw->deny.cnt; j++)
+ if (memcmp(old.addr[i], hw->deny.addr[j],
+ WLAN_ADDR_LEN) == 0) {
+ prism2mib_priv_deauthenticate(hw, old.addr[i]);
+ break;
+ }
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2mib_priv_deauthenticate
+*
+* De-authenticate a station. This is done by sending a HandoverAddress
+* information frame to the firmware. This should work, according to
+* Intersil.
+*
+* Arguments:
+* priv "priv" structure.
+* hw "hw" structure.
+* addr MAC address of station to be de-authenticated.
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+static void prism2mib_priv_deauthenticate(
+hfa384x_t *hw,
+UINT8 *addr)
+{
+ DBFENTER;
+ hfa384x_drvr_handover(hw, addr);
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_pstr2bytestr
+*
+* Convert the pstr data in the WLAN message structure into an hfa384x
+* byte string format.
+*
+* Arguments:
+* bytestr hfa384x byte string data type
+* pstr wlan message data
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr)
+{
+ DBFENTER;
+
+ bytestr->len = host2hfa384x_16((UINT16)(pstr->len));
+ memcpy(bytestr->data, pstr->data, pstr->len);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_pstr2bytearea
+*
+* Convert the pstr data in the WLAN message structure into an hfa384x
+* byte area format.
+*
+* Arguments:
+* bytearea hfa384x byte area data type
+* pstr wlan message data
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_pstr2bytearea(UINT8 *bytearea, p80211pstrd_t *pstr)
+{
+ DBFENTER;
+
+ memcpy(bytearea, pstr->data, pstr->len);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_bytestr2pstr
+*
+* Convert the data in an hfa384x byte string format into a
+* pstr in the WLAN message.
+*
+* Arguments:
+* bytestr hfa384x byte string data type
+* msg wlan message
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr)
+{
+ DBFENTER;
+
+ pstr->len = (UINT8)(hfa384x2host_16((UINT16)(bytestr->len)));
+ memcpy(pstr->data, bytestr->data, pstr->len);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_bytearea2pstr
+*
+* Convert the data in an hfa384x byte area format into a pstr
+* in the WLAN message.
+*
+* Arguments:
+* bytearea hfa384x byte area data type
+* msg wlan message
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_bytearea2pstr(UINT8 *bytearea, p80211pstrd_t *pstr, int len)
+{
+ DBFENTER;
+
+ pstr->len = (UINT8)len;
+ memcpy(pstr->data, bytearea, len);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_prism2int2p80211int
+*
+* Convert an hfa384x integer into a wlan integer
+*
+* Arguments:
+* prism2enum pointer to hfa384x integer
+* wlanenum pointer to p80211 integer
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_prism2int2p80211int(UINT16 *prism2int, UINT32 *wlanint)
+{
+ DBFENTER;
+
+ *wlanint = (UINT32)hfa384x2host_16(*prism2int);
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_p80211int2prism2int
+*
+* Convert a wlan integer into an hfa384x integer
+*
+* Arguments:
+* prism2enum pointer to hfa384x integer
+* wlanenum pointer to p80211 integer
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+
+void prism2mgmt_p80211int2prism2int(UINT16 *prism2int, UINT32 *wlanint)
+{
+ DBFENTER;
+
+ *prism2int = host2hfa384x_16((UINT16)(*wlanint));
+ DBFEXIT;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_prism2enum2p80211enum
+*
+* Convert the hfa384x enumerated int into a p80211 enumerated int
+*
+* Arguments:
+* prism2enum pointer to hfa384x integer
+* wlanenum pointer to p80211 integer
+* rid hfa384x record id
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+void prism2mgmt_prism2enum2p80211enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid)
+{
+ DBFENTER;
+
+ /* At the moment, the need for this functionality hasn't
+ presented itself. All the wlan enumerated values are
+ a 1-to-1 match against the Prism2 enumerated values*/
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_p80211enum2prism2enum
+*
+* Convert the p80211 enumerated int into an hfa384x enumerated int
+*
+* Arguments:
+* prism2enum pointer to hfa384x integer
+* wlanenum pointer to p80211 integer
+* rid hfa384x record id
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+void prism2mgmt_p80211enum2prism2enum(UINT16 *prism2enum, UINT32 *wlanenum, UINT16 rid)
+{
+ DBFENTER;
+
+ /* At the moment, the need for this functionality hasn't
+ presented itself. All the wlan enumerated values are
+ a 1-to-1 match against the Prism2 enumerated values*/
+ DBFEXIT;
+ return;
+}
+
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_get_oprateset
+*
+* Convert the hfa384x bit area into a wlan octet string.
+*
+* Arguments:
+* rate Prism2 bit area
+* pstr wlan octet string
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+void prism2mgmt_get_oprateset(UINT16 *rate, p80211pstrd_t *pstr)
+{
+ UINT8 len;
+ UINT8 *datarate;
+
+ DBFENTER;
+
+ len = 0;
+ datarate = pstr->data;
+
+ /* 1 Mbps */
+ if ( BIT0 & (*rate) ) {
+ len += (UINT8)1;
+ *datarate = (UINT8)2;
+ datarate++;
+ }
+
+ /* 2 Mbps */
+ if ( BIT1 & (*rate) ) {
+ len += (UINT8)1;
+ *datarate = (UINT8)4;
+ datarate++;
+ }
+
+ /* 5.5 Mbps */
+ if ( BIT2 & (*rate) ) {
+ len += (UINT8)1;
+ *datarate = (UINT8)11;
+ datarate++;
+ }
+
+ /* 11 Mbps */
+ if ( BIT3 & (*rate) ) {
+ len += (UINT8)1;
+ *datarate = (UINT8)22;
+ datarate++;
+ }
+
+ pstr->len = len;
+
+ DBFEXIT;
+ return;
+}
+
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_set_oprateset
+*
+* Convert the wlan octet string into an hfa384x bit area.
+*
+* Arguments:
+* rate Prism2 bit area
+* pstr wlan octet string
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+void prism2mgmt_set_oprateset(UINT16 *rate, p80211pstrd_t *pstr)
+{
+ UINT8 *datarate;
+ int i;
+
+ DBFENTER;
+
+ *rate = 0;
+
+ datarate = pstr->data;
+
+ for ( i=0; i < pstr->len; i++, datarate++ ) {
+ switch (*datarate) {
+ case 2: /* 1 Mbps */
+ *rate |= BIT0;
+ break;
+ case 4: /* 2 Mbps */
+ *rate |= BIT1;
+ break;
+ case 11: /* 5.5 Mbps */
+ *rate |= BIT2;
+ break;
+ case 22: /* 11 Mbps */
+ *rate |= BIT3;
+ break;
+ default:
+ WLAN_LOG_DEBUG(1, "Unrecoginzed Rate of %d\n",
+ *datarate);
+ break;
+ }
+ }
+
+ DBFEXIT;
+ return;
+}
+
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_get_grpaddr
+*
+* Retrieves a particular group address from the list of
+* group addresses.
+*
+* Arguments:
+* did mibitem did
+* pstr wlan octet string
+* priv prism2 driver private data structure
+*
+* Returns:
+* Nothing
+*
+----------------------------------------------------------------*/
+void prism2mgmt_get_grpaddr(UINT32 did, p80211pstrd_t *pstr,
+ hfa384x_t *hw )
+{
+ int index;
+
+ DBFENTER;
+
+ index = prism2mgmt_get_grpaddr_index(did);
+
+ if ( index >= 0 ) {
+ pstr->len = WLAN_ADDR_LEN;
+ memcpy(pstr->data, hw->dot11_grp_addr[index],
+ WLAN_ADDR_LEN);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_set_grpaddr
+*
+* Convert the wlan octet string into an hfa384x bit area.
+*
+* Arguments:
+* did mibitem did
+* buf
+* groups
+*
+* Returns:
+* 0 Success
+* !0 Error
+*
+----------------------------------------------------------------*/
+int prism2mgmt_set_grpaddr(UINT32 did, UINT8 *prism2buf,
+ p80211pstrd_t *pstr, hfa384x_t *hw )
+{
+ UINT8 no_addr[WLAN_ADDR_LEN];
+ int index;
+
+ DBFENTER;
+
+ memset(no_addr, 0, WLAN_ADDR_LEN);
+ if (memcmp(no_addr, pstr->data, WLAN_ADDR_LEN) != 0) {
+
+ /*
+ ** The address is NOT 0 so we are "adding" an address to the
+ ** group address list. Check to make sure we aren't trying
+ ** to add more than the maximum allowed number of group
+ ** addresses in the list. The new address is added to the
+ ** end of the list regardless of the DID used to add the
+ ** address.
+ */
+
+ if (hw->dot11_grpcnt >= MAX_GRP_ADDR) return(-1);
+
+ memcpy(hw->dot11_grp_addr[hw->dot11_grpcnt], pstr->data,
+ WLAN_ADDR_LEN);
+ hw->dot11_grpcnt += 1;
+ } else {
+
+ /*
+ ** The address is 0. Interpret this as "deleting" an address
+ ** from the group address list. Get the address index from
+ ** the DID. If this is within the range of used addresses,
+ ** then delete the specified address by shifting all following
+ ** addresses down. Then clear the last address (which should
+ ** now be unused). If the address index is NOT within the
+ ** range of used addresses, then just ignore the address.
+ */
+
+ index = prism2mgmt_get_grpaddr_index(did);
+ if (index >= 0 && index < hw->dot11_grpcnt) {
+ hw->dot11_grpcnt -= 1;
+ memmove(hw->dot11_grp_addr[index],
+ hw->dot11_grp_addr[index + 1],
+ ((hw->dot11_grpcnt)-index) * WLAN_ADDR_LEN);
+ memset(hw->dot11_grp_addr[hw->dot11_grpcnt], 0,
+ WLAN_ADDR_LEN);
+ }
+ }
+
+ DBFEXIT;
+ return(0);
+}
+
+
+/*----------------------------------------------------------------
+* prism2mgmt_get_grpaddr_index
+*
+* Gets the index in the group address list based on the did.
+*
+* Arguments:
+* did mibitem did
+*
+* Returns:
+* >= 0 If valid did
+* < 0 If not valid did
+*
+----------------------------------------------------------------*/
+int prism2mgmt_get_grpaddr_index( UINT32 did )
+{
+ int index;
+
+ DBFENTER;
+
+ index = -1;
+
+ switch (did) {
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address1:
+ index = 0;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address2:
+ index = 1;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address3:
+ index = 2;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address4:
+ index = 3;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address5:
+ index = 4;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address6:
+ index = 5;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address7:
+ index = 6;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address8:
+ index = 7;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address9:
+ index = 8;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address10:
+ index = 9;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address11:
+ index = 10;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address12:
+ index = 11;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address13:
+ index = 12;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address14:
+ index = 13;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address15:
+ index = 14;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address16:
+ index = 15;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address17:
+ index = 16;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address18:
+ index = 17;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address19:
+ index = 18;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address20:
+ index = 19;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address21:
+ index = 20;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address22:
+ index = 21;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address23:
+ index = 22;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address24:
+ index = 23;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address25:
+ index = 24;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address26:
+ index = 25;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address27:
+ index = 26;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address28:
+ index = 27;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address29:
+ index = 28;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address30:
+ index = 29;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address31:
+ index = 30;
+ break;
+ case DIDmib_dot11mac_dot11GroupAddressesTable_dot11Address32:
+ index = 31;
+ break;
+ }
+
+ DBFEXIT;
+ return index;
+}
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
new file mode 100644
index 00000000000..18aa15f9e41
--- /dev/null
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -0,0 +1,2502 @@
+/* src/prism2/driver/prism2sta.c
+*
+* Implements the station functionality for prism2
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*
+* This file implements the module and linux pcmcia routines for the
+* prism2 driver.
+*
+* --------------------------------------------------------------------
+*/
+
+/*================================================================*/
+/* System Includes */
+#define WLAN_DBVAR prism2_debug
+
+#include "version.h"
+
+
+#include <linux/version.h>
+
+#include <linux/module.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,25))
+#include <linux/moduleparam.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/tqueue.h>
+#else
+#include <linux/workqueue.h>
+#endif
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/if_arp.h>
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+#endif
+
+#include "wlan_compat.h"
+
+#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#endif
+
+/*================================================================*/
+/* Project Includes */
+
+#include "p80211types.h"
+#include "p80211hdr.h"
+#include "p80211mgmt.h"
+#include "p80211conv.h"
+#include "p80211msg.h"
+#include "p80211netdev.h"
+#include "p80211req.h"
+#include "p80211metadef.h"
+#include "p80211metastruct.h"
+#include "hfa384x.h"
+#include "prism2mgmt.h"
+
+/*================================================================*/
+/* Local Constants */
+
+/*================================================================*/
+/* Local Macros */
+
+/*================================================================*/
+/* Local Types */
+
+/*================================================================*/
+/* Local Static Definitions */
+
+#if (WLAN_HOSTIF == WLAN_PCMCIA)
+#define DRIVER_SUFFIX "_cs"
+#elif (WLAN_HOSTIF == WLAN_PLX)
+#define DRIVER_SUFFIX "_plx"
+typedef char* dev_info_t;
+#elif (WLAN_HOSTIF == WLAN_PCI)
+#define DRIVER_SUFFIX "_pci"
+typedef char* dev_info_t;
+#elif (WLAN_HOSTIF == WLAN_USB)
+#define DRIVER_SUFFIX "_usb"
+typedef char* dev_info_t;
+#else
+#error "HOSTIF unsupported or undefined!"
+#endif
+
+static char *version = "prism2" DRIVER_SUFFIX ".o: " WLAN_RELEASE;
+static dev_info_t dev_info = "prism2" DRIVER_SUFFIX;
+
+#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI)
+#ifdef CONFIG_PM
+static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state);
+static int prism2sta_resume_pci(struct pci_dev *pdev);
+#endif
+#endif
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+
+#endif /* WLAN_PCI */
+
+static wlandevice_t *create_wlan(void);
+
+/*----------------------------------------------------------------*/
+/* --Module Parameters */
+
+int prism2_reset_holdtime=30; /* Reset hold time in ms */
+int prism2_reset_settletime=100; /* Reset settle time in ms */
+
+#if (WLAN_HOSTIF == WLAN_USB)
+static int prism2_doreset=0; /* Do a reset at init? */
+#else
+static int prism2_doreset=1; /* Do a reset at init? */
+int prism2_bap_timeout=1000; /* BAP timeout */
+int prism2_irq_evread_max=20; /* Maximum number of
+ * ev_reads (loops)
+ * in irq handler
+ */
+#endif
+
+#ifdef WLAN_INCLUDE_DEBUG
+int prism2_debug=0;
+module_param( prism2_debug, int, 0644);
+MODULE_PARM_DESC(prism2_debug, "prism2 debugging");
+#endif
+
+module_param( prism2_doreset, int, 0644);
+MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
+
+module_param( prism2_reset_holdtime, int, 0644);
+MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms");
+module_param( prism2_reset_settletime, int, 0644);
+MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms");
+
+#if (WLAN_HOSTIF != WLAN_USB)
+module_param( prism2_bap_timeout, int, 0644);
+MODULE_PARM_DESC(prism2_bap_timeout, "BufferAccessPath Timeout in 10*n us");
+module_param( prism2_irq_evread_max, int, 0644);
+MODULE_PARM_DESC( prism2_irq_evread_max, "Maximim number of event reads in interrupt handler");
+#endif
+
+MODULE_LICENSE("Dual MPL/GPL");
+
+/*================================================================*/
+/* Local Function Declarations */
+
+static int prism2sta_open(wlandevice_t *wlandev);
+static int prism2sta_close(wlandevice_t *wlandev);
+static void prism2sta_reset(wlandevice_t *wlandev );
+static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg);
+static int prism2sta_getcardinfo(wlandevice_t *wlandev);
+static int prism2sta_globalsetup(wlandevice_t *wlandev);
+static int prism2sta_setmulticast(wlandevice_t *wlandev,
+ netdevice_t *dev);
+
+static void prism2sta_inf_handover(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_tallies(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_hostscanresults(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_scanresults(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_chinforesults(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_linkstatus(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_assocstatus(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_authreq(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_authreq_defer(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+static void prism2sta_inf_psusercnt(
+ wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+
+#ifdef CONFIG_PROC_FS
+static int
+prism2sta_proc_read(
+ char *page,
+ char **start,
+ off_t offset,
+ int count,
+ int *eof,
+ void *data);
+#endif
+
+/*================================================================*/
+/* Function Definitions */
+
+/*----------------------------------------------------------------
+* dmpmem
+*
+* Debug utility function to dump memory to the kernel debug log.
+*
+* Arguments:
+* buf ptr data we want dumped
+* len length of data
+*
+* Returns:
+* nothing
+* Side effects:
+*
+* Call context:
+* process thread
+* interrupt
+----------------------------------------------------------------*/
+inline void dmpmem(void *buf, int n)
+{
+ int c;
+ for ( c= 0; c < n; c++) {
+ if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c);
+ printk("%02x ", ((UINT8*)buf)[c]);
+ if ( (c % 16) == 15 ) printk("\n");
+ }
+ if ( (c % 16) != 0 ) printk("\n");
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_open
+*
+* WLAN device open method. Called from p80211netdev when kernel
+* device open (start) method is called in response to the
+* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
+* from clear to set.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int prism2sta_open(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+#ifdef ANCIENT_MODULE_CODE
+ MOD_INC_USE_COUNT;
+#endif
+
+ /* We don't currently have to do anything else.
+ * The setup of the MAC should be subsequently completed via
+ * the mlme commands.
+ * Higher layers know we're ready from dev->start==1 and
+ * dev->tbusy==0. Our rx path knows to pass up received/
+ * frames because of dev->flags&IFF_UP is true.
+ */
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_close
+*
+* WLAN device close method. Called from p80211netdev when kernel
+* device close method is called in response to the
+* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
+* from set to clear.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int prism2sta_close(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+#ifdef ANCIENT_MODULE_CODE
+ MOD_DEC_USE_COUNT;
+#endif
+
+ /* We don't currently have to do anything else.
+ * Higher layers know we're not ready from dev->start==0 and
+ * dev->tbusy==1. Our rx path knows to not pass up received
+ * frames because of dev->flags&IFF_UP is false.
+ */
+
+ DBFEXIT;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_reset
+*
+* Not currently implented.
+*
+* Arguments:
+* wlandev wlan device structure
+* none
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static void prism2sta_reset(wlandevice_t *wlandev )
+{
+ DBFENTER;
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_txframe
+*
+* Takes a frame from p80211 and queues it for transmission.
+*
+* Arguments:
+* wlandev wlan device structure
+* pb packet buffer struct. Contains an 802.11
+* data frame.
+* p80211_hdr points to the 802.11 header for the packet.
+* Returns:
+* 0 Success and more buffs available
+* 1 Success but no more buffs
+* 2 Allocation failure
+* 4 Buffer full or queue busy
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
+ p80211_hdr_t *p80211_hdr,
+ p80211_metawep_t *p80211_wep)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ int result;
+ DBFENTER;
+
+ /* If necessary, set the 802.11 WEP bit */
+ if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == HOSTWEP_PRIVACYINVOKED) {
+ p80211_hdr->a3.fc |= host2ieee16(WLAN_SET_FC_ISWEP(1));
+ }
+
+ result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_mlmerequest
+*
+* wlan command message handler. All we do here is pass the message
+* over to the prism2sta_mgmt_handler.
+*
+* Arguments:
+* wlandev wlan device structure
+* msg wlan command message
+* Returns:
+* 0 success
+* <0 successful acceptance of message, but we're
+* waiting for an async process to finish before
+* we're done with the msg. When the asynch
+* process is done, we'll call the p80211
+* function p80211req_confirm() .
+* >0 An error occurred while we were handling
+* the message.
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+
+ int result = 0;
+ DBFENTER;
+
+ switch( msg->msgcode )
+ {
+ case DIDmsg_dot11req_mibget :
+ WLAN_LOG_DEBUG(2,"Received mibget request\n");
+ result = prism2mgmt_mibset_mibget(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_mibset :
+ WLAN_LOG_DEBUG(2,"Received mibset request\n");
+ result = prism2mgmt_mibset_mibget(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_powermgmt :
+ WLAN_LOG_DEBUG(2,"Received powermgmt request\n");
+ result = prism2mgmt_powermgmt(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_scan :
+ WLAN_LOG_DEBUG(2,"Received scan request\n");
+ result = prism2mgmt_scan(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_scan_results :
+ WLAN_LOG_DEBUG(2,"Received scan_results request\n");
+ result = prism2mgmt_scan_results(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_join :
+ WLAN_LOG_DEBUG(2,"Received join request\n");
+ result = prism2mgmt_join(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_authenticate :
+ WLAN_LOG_DEBUG(2,"Received authenticate request\n");
+ result = prism2mgmt_authenticate(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_deauthenticate :
+ WLAN_LOG_DEBUG(2,"Received mlme deauthenticate request\n");
+ result = prism2mgmt_deauthenticate(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_associate :
+ WLAN_LOG_DEBUG(2,"Received mlme associate request\n");
+ result = prism2mgmt_associate(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_reassociate :
+ WLAN_LOG_DEBUG(2,"Received mlme reassociate request\n");
+ result = prism2mgmt_reassociate(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_disassociate :
+ WLAN_LOG_DEBUG(2,"Received mlme disassociate request\n");
+ result = prism2mgmt_disassociate(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_reset :
+ WLAN_LOG_DEBUG(2,"Received mlme reset request\n");
+ result = prism2mgmt_reset(wlandev, msg);
+ break;
+ case DIDmsg_dot11req_start :
+ WLAN_LOG_DEBUG(2,"Received mlme start request\n");
+ result = prism2mgmt_start(wlandev, msg);
+ break;
+ /*
+ * Prism2 specific messages
+ */
+ case DIDmsg_p2req_join :
+ WLAN_LOG_DEBUG(2,"Received p2 join request\n");
+ result = prism2mgmt_p2_join(wlandev, msg);
+ break;
+ case DIDmsg_p2req_readpda :
+ WLAN_LOG_DEBUG(2,"Received mlme readpda request\n");
+ result = prism2mgmt_readpda(wlandev, msg);
+ break;
+ case DIDmsg_p2req_readcis :
+ WLAN_LOG_DEBUG(2,"Received mlme readcis request\n");
+ result = prism2mgmt_readcis(wlandev, msg);
+ break;
+ case DIDmsg_p2req_auxport_state :
+ WLAN_LOG_DEBUG(2,"Received mlme auxport_state request\n");
+ result = prism2mgmt_auxport_state(wlandev, msg);
+ break;
+ case DIDmsg_p2req_auxport_read :
+ WLAN_LOG_DEBUG(2,"Received mlme auxport_read request\n");
+ result = prism2mgmt_auxport_read(wlandev, msg);
+ break;
+ case DIDmsg_p2req_auxport_write :
+ WLAN_LOG_DEBUG(2,"Received mlme auxport_write request\n");
+ result = prism2mgmt_auxport_write(wlandev, msg);
+ break;
+ case DIDmsg_p2req_low_level :
+ WLAN_LOG_DEBUG(2,"Received mlme low_level request\n");
+ result = prism2mgmt_low_level(wlandev, msg);
+ break;
+ case DIDmsg_p2req_test_command :
+ WLAN_LOG_DEBUG(2,"Received mlme test_command request\n");
+ result = prism2mgmt_test_command(wlandev, msg);
+ break;
+ case DIDmsg_p2req_mmi_read :
+ WLAN_LOG_DEBUG(2,"Received mlme mmi_read request\n");
+ result = prism2mgmt_mmi_read(wlandev, msg);
+ break;
+ case DIDmsg_p2req_mmi_write :
+ WLAN_LOG_DEBUG(2,"Received mlme mmi_write request\n");
+ result = prism2mgmt_mmi_write(wlandev, msg);
+ break;
+ case DIDmsg_p2req_ramdl_state :
+ WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n");
+ result = prism2mgmt_ramdl_state(wlandev, msg);
+ break;
+ case DIDmsg_p2req_ramdl_write :
+ WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n");
+ result = prism2mgmt_ramdl_write(wlandev, msg);
+ break;
+ case DIDmsg_p2req_flashdl_state :
+ WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n");
+ result = prism2mgmt_flashdl_state(wlandev, msg);
+ break;
+ case DIDmsg_p2req_flashdl_write :
+ WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n");
+ result = prism2mgmt_flashdl_write(wlandev, msg);
+ break;
+ case DIDmsg_p2req_dump_state :
+ WLAN_LOG_DEBUG(2,"Received mlme dump_state request\n");
+ result = prism2mgmt_dump_state(wlandev, msg);
+ break;
+ case DIDmsg_p2req_channel_info :
+ WLAN_LOG_DEBUG(2,"Received mlme channel_info request\n");
+ result = prism2mgmt_channel_info(wlandev, msg);
+ break;
+ case DIDmsg_p2req_channel_info_results :
+ WLAN_LOG_DEBUG(2,"Received mlme channel_info_results request\n");
+ result = prism2mgmt_channel_info_results(wlandev, msg);
+ break;
+ /*
+ * Linux specific messages
+ */
+ case DIDmsg_lnxreq_hostwep :
+ break; // ignore me.
+ case DIDmsg_lnxreq_ifstate :
+ {
+ p80211msg_lnxreq_ifstate_t *ifstatemsg;
+ WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n");
+ ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg;
+ result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data);
+ ifstatemsg->resultcode.status =
+ P80211ENUM_msgitem_status_data_ok;
+ ifstatemsg->resultcode.data = result;
+ result = 0;
+ }
+ break;
+ case DIDmsg_lnxreq_wlansniff :
+ WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n");
+ result = prism2mgmt_wlansniff(wlandev, msg);
+ break;
+ case DIDmsg_lnxreq_autojoin :
+ WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n");
+ result = prism2mgmt_autojoin(wlandev, msg);
+ break;
+ case DIDmsg_p2req_enable :
+ WLAN_LOG_DEBUG(2,"Received mlme enable request\n");
+ result = prism2mgmt_enable(wlandev, msg);
+ break;
+ case DIDmsg_lnxreq_commsquality: {
+ p80211msg_lnxreq_commsquality_t *qualmsg;
+
+ WLAN_LOG_DEBUG(2,"Received commsquality request\n");
+
+ if (hw->ap)
+ break;
+
+ qualmsg = (p80211msg_lnxreq_commsquality_t*) msg;
+
+ qualmsg->link.status = P80211ENUM_msgitem_status_data_ok;
+ qualmsg->level.status = P80211ENUM_msgitem_status_data_ok;
+ qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok;
+
+
+ qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS);
+ qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS);
+ qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC);
+
+ break;
+ }
+ default:
+ WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode);
+ break;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ifstate
+*
+* Interface state. This is the primary WLAN interface enable/disable
+* handler. Following the driver/load/deviceprobe sequence, this
+* function must be called with a state of "enable" before any other
+* commands will be accepted.
+*
+* Arguments:
+* wlandev wlan device structure
+* msgp ptr to msg buffer
+*
+* Returns:
+* A p80211 message resultcode value.
+*
+* Side effects:
+*
+* Call context:
+* process thread (usually)
+* interrupt
+----------------------------------------------------------------*/
+UINT32 prism2sta_ifstate(wlandevice_t *wlandev, UINT32 ifstate)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ UINT32 result;
+ DBFENTER;
+
+ result = P80211ENUM_resultcode_implementation_failure;
+
+ WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n",
+ wlandev->msdstate, ifstate);
+ switch (ifstate)
+ {
+ case P80211ENUM_ifstate_fwload:
+ switch (wlandev->msdstate) {
+ case WLAN_MSD_HWPRESENT:
+ wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING;
+ /*
+ * Initialize the device+driver sufficiently
+ * for firmware loading.
+ */
+#if (WLAN_HOSTIF != WLAN_USB)
+ result=hfa384x_cmd_initialize(hw);
+#else
+ if ((result=hfa384x_drvr_start(hw))) {
+ WLAN_LOG_ERROR(
+ "hfa384x_drvr_start() failed,"
+ "result=%d\n", (int)result);
+ result =
+ P80211ENUM_resultcode_implementation_failure;
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ break;
+ }
+#endif
+ wlandev->msdstate = WLAN_MSD_FWLOAD;
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_FWLOAD:
+ hfa384x_cmd_initialize(hw);
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_RUNNING:
+ WLAN_LOG_WARNING(
+ "Cannot enter fwload state from enable state,"
+ "you must disable first.\n");
+ result = P80211ENUM_resultcode_invalid_parameters;
+ break;
+ case WLAN_MSD_HWFAIL:
+ default:
+ /* probe() had a problem or the msdstate contains
+ * an unrecognized value, there's nothing we can do.
+ */
+ result = P80211ENUM_resultcode_implementation_failure;
+ break;
+ }
+ break;
+ case P80211ENUM_ifstate_enable:
+ switch (wlandev->msdstate) {
+ case WLAN_MSD_HWPRESENT:
+ case WLAN_MSD_FWLOAD:
+ wlandev->msdstate = WLAN_MSD_RUNNING_PENDING;
+ /* Initialize the device+driver for full
+ * operation. Note that this might me an FWLOAD to
+ * to RUNNING transition so we must not do a chip
+ * or board level reset. Note that on failure,
+ * the MSD state is set to HWPRESENT because we
+ * can't make any assumptions about the state
+ * of the hardware or a previous firmware load.
+ */
+ if ((result=hfa384x_drvr_start(hw))) {
+ WLAN_LOG_ERROR(
+ "hfa384x_drvr_start() failed,"
+ "result=%d\n", (int)result);
+ result =
+ P80211ENUM_resultcode_implementation_failure;
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ break;
+ }
+
+ if ((result=prism2sta_getcardinfo(wlandev))) {
+ WLAN_LOG_ERROR(
+ "prism2sta_getcardinfo() failed,"
+ "result=%d\n", (int)result);
+ result =
+ P80211ENUM_resultcode_implementation_failure;
+ hfa384x_drvr_stop(hw);
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ break;
+ }
+ if ((result=prism2sta_globalsetup(wlandev))) {
+ WLAN_LOG_ERROR(
+ "prism2sta_globalsetup() failed,"
+ "result=%d\n", (int)result);
+ result =
+ P80211ENUM_resultcode_implementation_failure;
+ hfa384x_drvr_stop(hw);
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ break;
+ }
+ wlandev->msdstate = WLAN_MSD_RUNNING;
+ hw->join_ap = 0;
+ hw->join_retries = 60;
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_RUNNING:
+ /* Do nothing, we're already in this state.*/
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_HWFAIL:
+ default:
+ /* probe() had a problem or the msdstate contains
+ * an unrecognized value, there's nothing we can do.
+ */
+ result = P80211ENUM_resultcode_implementation_failure;
+ break;
+ }
+ break;
+ case P80211ENUM_ifstate_disable:
+ switch (wlandev->msdstate) {
+ case WLAN_MSD_HWPRESENT:
+ /* Do nothing, we're already in this state.*/
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_FWLOAD:
+ case WLAN_MSD_RUNNING:
+ wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
+ /*
+ * TODO: Shut down the MAC completely. Here a chip
+ * or board level reset is probably called for.
+ * After a "disable" _all_ results are lost, even
+ * those from a fwload.
+ */
+ if (!wlandev->hwremoved)
+ netif_carrier_off(wlandev->netdev);
+
+ hfa384x_drvr_stop(hw);
+
+ wlandev->macmode = WLAN_MACMODE_NONE;
+ wlandev->msdstate = WLAN_MSD_HWPRESENT;
+ result = P80211ENUM_resultcode_success;
+ break;
+ case WLAN_MSD_HWFAIL:
+ default:
+ /* probe() had a problem or the msdstate contains
+ * an unrecognized value, there's nothing we can do.
+ */
+ result = P80211ENUM_resultcode_implementation_failure;
+ break;
+ }
+ break;
+ default:
+ result = P80211ENUM_resultcode_invalid_parameters;
+ break;
+ }
+
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_getcardinfo
+*
+* Collect the NICID, firmware version and any other identifiers
+* we'd like to have in host-side data structures.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* Either.
+----------------------------------------------------------------*/
+static int prism2sta_getcardinfo(wlandevice_t *wlandev)
+{
+ int result = 0;
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ UINT16 temp;
+ UINT8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
+ char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
+
+ DBFENTER;
+
+ /* Collect version and compatibility info */
+ /* Some are critical, some are not */
+ /* NIC identity */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY,
+ &hw->ident_nic, sizeof(hfa384x_compident_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n");
+ goto failed;
+ }
+
+ /* get all the nic id fields in host byte order */
+ hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id);
+ hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant);
+ hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major);
+ hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor);
+
+ WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_nic.id, hw->ident_nic.major,
+ hw->ident_nic.minor, hw->ident_nic.variant);
+
+ /* Primary f/w identity */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY,
+ &hw->ident_pri_fw, sizeof(hfa384x_compident_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n");
+ goto failed;
+ }
+
+ /* get all the private fw id fields in host byte order */
+ hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id);
+ hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant);
+ hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major);
+ hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor);
+
+ WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_pri_fw.id, hw->ident_pri_fw.major,
+ hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
+
+ /* Station (Secondary?) f/w identity */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY,
+ &hw->ident_sta_fw, sizeof(hfa384x_compident_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n");
+ goto failed;
+ }
+
+ if (hw->ident_nic.id < 0x8000) {
+ WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n");
+ result = -1;
+ goto failed;
+ }
+
+ /* get all the station fw id fields in host byte order */
+ hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id);
+ hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant);
+ hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major);
+ hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor);
+
+ /* strip out the 'special' variant bits */
+ hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15);
+ hw->ident_sta_fw.variant &= ~((UINT16)(BIT14 | BIT15));
+
+ if ( hw->ident_sta_fw.id == 0x1f ) {
+ hw->ap = 0;
+ WLAN_LOG_INFO(
+ "ident: sta f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_sta_fw.id, hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
+ } else {
+ hw->ap = 1;
+ WLAN_LOG_INFO(
+ "ident: ap f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_sta_fw.id, hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
+ }
+
+ /* Compatibility range, Modem supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE,
+ &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, modem interface supplier
+ fields in byte order */
+ hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role);
+ hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id);
+ hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant);
+ hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom);
+ hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top);
+
+ WLAN_LOG_INFO(
+ "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_sup_mfi.role, hw->cap_sup_mfi.id,
+ hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom,
+ hw->cap_sup_mfi.top);
+
+ /* Compatibility range, Controller supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE,
+ &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, controller interface supplier
+ fields in byte order */
+ hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role);
+ hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id);
+ hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant);
+ hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom);
+ hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top);
+
+ WLAN_LOG_INFO(
+ "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_sup_cfi.role, hw->cap_sup_cfi.id,
+ hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom,
+ hw->cap_sup_cfi.top);
+
+ /* Compatibility range, Primary f/w supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE,
+ &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, primary firmware supplier
+ fields in byte order */
+ hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role);
+ hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id);
+ hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant);
+ hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom);
+ hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top);
+
+ WLAN_LOG_INFO(
+ "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_sup_pri.role, hw->cap_sup_pri.id,
+ hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom,
+ hw->cap_sup_pri.top);
+
+ /* Compatibility range, Station f/w supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE,
+ &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, station firmware supplier
+ fields in byte order */
+ hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role);
+ hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id);
+ hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant);
+ hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom);
+ hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top);
+
+ if ( hw->cap_sup_sta.id == 0x04 ) {
+ WLAN_LOG_INFO(
+ "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_sup_sta.role, hw->cap_sup_sta.id,
+ hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
+ hw->cap_sup_sta.top);
+ } else {
+ WLAN_LOG_INFO(
+ "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_sup_sta.role, hw->cap_sup_sta.id,
+ hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
+ hw->cap_sup_sta.top);
+ }
+
+ /* Compatibility range, primary f/w actor, CFI supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES,
+ &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, primary f/w actor, CFI supplier
+ fields in byte order */
+ hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role);
+ hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id);
+ hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant);
+ hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom);
+ hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top);
+
+ WLAN_LOG_INFO(
+ "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id,
+ hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom,
+ hw->cap_act_pri_cfi.top);
+
+ /* Compatibility range, sta f/w actor, CFI supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES,
+ &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, station f/w actor, CFI supplier
+ fields in byte order */
+ hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role);
+ hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id);
+ hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant);
+ hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom);
+ hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top);
+
+ WLAN_LOG_INFO(
+ "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id,
+ hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom,
+ hw->cap_act_sta_cfi.top);
+
+ /* Compatibility range, sta f/w actor, MFI supplier */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES,
+ &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t));
+ if ( result ) {
+ WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n");
+ goto failed;
+ }
+
+ /* get all the Compatibility range, station f/w actor, MFI supplier
+ fields in byte order */
+ hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role);
+ hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id);
+ hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant);
+ hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom);
+ hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top);
+
+ WLAN_LOG_INFO(
+ "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
+ hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id,
+ hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom,
+ hw->cap_act_sta_mfi.top);
+
+ /* Serial Number */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
+ snum, HFA384x_RID_NICSERIALNUMBER_LEN);
+ if ( !result ) {
+ wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
+ pstr, sizeof(pstr));
+ WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr);
+ } else {
+ WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n");
+ goto failed;
+ }
+
+ /* Collect the MAC address */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR,
+ wlandev->netdev->dev_addr, WLAN_ADDR_LEN);
+ if ( result != 0 ) {
+ WLAN_LOG_ERROR("Failed to retrieve mac address\n");
+ goto failed;
+ }
+
+ /* short preamble is always implemented */
+ wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE;
+
+ /* find out if hardware wep is implemented */
+ hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp);
+ if (temp)
+ wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP;
+
+ /* get the dBm Scaling constant */
+ hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp);
+ hw->dbmadjust = temp;
+
+ /* Only enable scan by default on newer firmware */
+ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor,
+ hw->ident_sta_fw.variant) <
+ HFA384x_FIRMWARE_VERSION(1,5,5)) {
+ wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN;
+ }
+
+ /* TODO: Set any internally managed config items */
+
+ goto done;
+failed:
+ WLAN_LOG_ERROR("Failed, result=%d\n", result);
+done:
+ DBFEXIT;
+ return result;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_globalsetup
+*
+* Set any global RIDs that we want to set at device activation.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* 0 success
+* >0 f/w reported error
+* <0 driver reported error
+*
+* Side effects:
+*
+* Call context:
+* process thread
+----------------------------------------------------------------*/
+static int prism2sta_globalsetup(wlandevice_t *wlandev)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+
+ /* Set the maximum frame size */
+ return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN,
+ WLAN_DATA_MAXLEN);
+}
+
+static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev)
+{
+ int result = 0;
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+
+ UINT16 promisc;
+
+ DBFENTER;
+
+ /* If we're not ready, what's the point? */
+ if ( hw->state != HFA384x_STATE_RUNNING )
+ goto exit;
+
+ /* If we're an AP, do nothing here */
+ if (hw->ap)
+ goto exit;
+
+ if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 )
+ promisc = P80211ENUM_truth_true;
+ else
+ promisc = P80211ENUM_truth_false;
+
+ result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc);
+
+ /* XXX TODO: configure the multicast list */
+ // CLEAR_HW_MULTICAST_LIST
+ // struct dev_mc_list element = dev->mc_list;
+ // while (element != null) {
+ // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen)
+ // element = element->next;
+ // }
+
+ exit:
+ DBFEXIT;
+ return result;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_handover
+*
+* Handles the receipt of a Handover info frame. Should only be present
+* in APs only.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
+{
+ DBFENTER;
+ WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n");
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_inf_tallies
+*
+* Handles the receipt of a CommTallies info frame.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ UINT16 *src16;
+ UINT32 *dst;
+ UINT32 *src32;
+ int i;
+ int cnt;
+
+ DBFENTER;
+
+ /*
+ ** Determine if these are 16-bit or 32-bit tallies, based on the
+ ** record length of the info record.
+ */
+
+ cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(UINT32);
+ if (inf->framelen > 22) {
+ dst = (UINT32 *) &hw->tallies;
+ src32 = (UINT32 *) &inf->info.commtallies32;
+ for (i = 0; i < cnt; i++, dst++, src32++)
+ *dst += hfa384x2host_32(*src32);
+ } else {
+ dst = (UINT32 *) &hw->tallies;
+ src16 = (UINT16 *) &inf->info.commtallies16;
+ for (i = 0; i < cnt; i++, dst++, src16++)
+ *dst += hfa384x2host_16(*src16);
+ }
+
+ DBFEXIT;
+
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_scanresults
+*
+* Handles the receipt of a Scan Results info frame.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_scanresults(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ int nbss;
+ hfa384x_ScanResult_t *sr = &(inf->info.scanresult);
+ int i;
+ hfa384x_JoinRequest_data_t joinreq;
+ int result;
+ DBFENTER;
+
+ /* Get the number of results, first in bytes, then in results */
+ nbss = (inf->framelen * sizeof(UINT16)) -
+ sizeof(inf->infotype) -
+ sizeof(inf->info.scanresult.scanreason);
+ nbss /= sizeof(hfa384x_ScanResultSub_t);
+
+ /* Print em */
+ WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n",
+ inf->info.scanresult.scanreason, nbss);
+ for ( i = 0; i < nbss; i++) {
+ WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n",
+ sr->result[i].chid,
+ sr->result[i].anl,
+ sr->result[i].sl,
+ sr->result[i].bcnint);
+ WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n",
+ sr->result[i].capinfo,
+ sr->result[i].proberesp_rate);
+ }
+ /* issue a join request */
+ joinreq.channel = sr->result[0].chid;
+ memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN);
+ result = hfa384x_drvr_setconfig( hw,
+ HFA384x_RID_JOINREQUEST,
+ &joinreq, HFA384x_RID_JOINREQUEST_LEN);
+ if (result) {
+ WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result);
+ }
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_hostscanresults
+*
+* Handles the receipt of a Scan Results info frame.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ int nbss;
+ DBFENTER;
+
+ nbss = (inf->framelen - 3) / 32;
+ WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss);
+
+ if (nbss > 32)
+ nbss = 32;
+
+ if (hw->scanresults)
+ kfree(hw->scanresults);
+
+ hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC);
+ memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t));
+
+ if (nbss == 0)
+ nbss = -1;
+
+ /* Notify/wake the sleeping caller. */
+ hw->scanflag = nbss;
+ wake_up_interruptible(&hw->cmdq);
+
+ DBFEXIT;
+};
+
+/*----------------------------------------------------------------
+* prism2sta_inf_chinforesults
+*
+* Handles the receipt of a Channel Info Results info frame.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_chinforesults(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ unsigned int i, n;
+
+ DBFENTER;
+ hw->channel_info.results.scanchannels =
+ hfa384x2host_16(inf->info.chinforesult.scanchannels);
+#if 0
+ memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t));
+#endif
+
+ for (i=0, n=0; i<HFA384x_CHINFORESULT_MAX; i++) {
+ if (hw->channel_info.results.scanchannels & (1<<i)) {
+ int channel=hfa384x2host_16(inf->info.chinforesult.result[n].chid)-1;
+ hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel];
+ chinforesult->chid = channel;
+ chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl);
+ chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl);
+ chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active);
+ WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
+ channel+1,
+ chinforesult->active &
+ HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise",
+ chinforesult->anl, chinforesult->pnl,
+ chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0
+ );
+ n++;
+ }
+ }
+ atomic_set(&hw->channel_info.done, 2);
+
+ hw->channel_info.count = n;
+ DBFEXIT;
+ return;
+}
+
+void prism2sta_processing_defer(struct work_struct *data)
+{
+ hfa384x_t *hw = container_of(data, struct hfa384x, link_bh);
+ wlandevice_t *wlandev = hw->wlandev;
+ hfa384x_bytestr32_t ssid;
+ int result;
+
+ DBFENTER;
+ /* First let's process the auth frames */
+ {
+ struct sk_buff *skb;
+ hfa384x_InfFrame_t *inf;
+
+ while ( (skb = skb_dequeue(&hw->authq)) ) {
+ inf = (hfa384x_InfFrame_t *) skb->data;
+ prism2sta_inf_authreq_defer(wlandev, inf);
+ }
+
+ }
+
+ /* Now let's handle the linkstatus stuff */
+ if (hw->link_status == hw->link_status_new)
+ goto failed;
+
+ hw->link_status = hw->link_status_new;
+
+ switch(hw->link_status) {
+ case HFA384x_LINK_NOTCONNECTED:
+ /* I'm currently assuming that this is the initial link
+ * state. It should only be possible immediately
+ * following an Enable command.
+ * Response:
+ * Block Transmits, Ignore receives of data frames
+ */
+ netif_carrier_off(wlandev->netdev);
+
+ WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n");
+ break;
+
+ case HFA384x_LINK_CONNECTED:
+ /* This one indicates a successful scan/join/auth/assoc.
+ * When we have the full MLME complement, this event will
+ * signify successful completion of both mlme_authenticate
+ * and mlme_associate. State management will get a little
+ * ugly here.
+ * Response:
+ * Indicate authentication and/or association
+ * Enable Transmits, Receives and pass up data frames
+ */
+
+ netif_carrier_on(wlandev->netdev);
+
+ /* If we are joining a specific AP, set our state and reset retries */
+ if(hw->join_ap == 1)
+ hw->join_ap = 2;
+ hw->join_retries = 60;
+
+ /* Don't call this in monitor mode */
+ if ( wlandev->netdev->type == ARPHRD_ETHER ) {
+ UINT16 portstatus;
+
+ WLAN_LOG_INFO("linkstatus=CONNECTED\n");
+
+ /* For non-usb devices, we can use the sync versions */
+ /* Collect the BSSID, and set state to allow tx */
+
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTBSSID,
+ wlandev->bssid, WLAN_BSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTBSSID, result);
+ goto failed;
+ }
+
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTSSID,
+ &ssid, sizeof(ssid));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTSSID, result);
+ goto failed;
+ }
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
+ (p80211pstrd_t *) &wlandev->ssid);
+
+ /* Collect the port status */
+ result = hfa384x_drvr_getconfig16(hw,
+ HFA384x_RID_PORTSTATUS, &portstatus);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_PORTSTATUS, result);
+ goto failed;
+ }
+ wlandev->macmode =
+ (portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
+ WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
+
+ /* Get the ball rolling on the comms quality stuff */
+ prism2sta_commsqual_defer(&hw->commsqual_bh);
+ }
+ break;
+
+ case HFA384x_LINK_DISCONNECTED:
+ /* This one indicates that our association is gone. We've
+ * lost connection with the AP and/or been disassociated.
+ * This indicates that the MAC has completely cleared it's
+ * associated state. We * should send a deauth indication
+ * (implying disassoc) up * to the MLME.
+ * Response:
+ * Indicate Deauthentication
+ * Block Transmits, Ignore receives of data frames
+ */
+ if(hw->join_ap == 2)
+ {
+ hfa384x_JoinRequest_data_t joinreq;
+ joinreq = hw->joinreq;
+ /* Send the join request */
+ hfa384x_drvr_setconfig( hw,
+ HFA384x_RID_JOINREQUEST,
+ &joinreq, HFA384x_RID_JOINREQUEST_LEN);
+ WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n");
+ } else {
+ if (wlandev->netdev->type == ARPHRD_ETHER)
+ WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n");
+ }
+ wlandev->macmode = WLAN_MACMODE_NONE;
+
+ netif_carrier_off(wlandev->netdev);
+
+ break;
+
+ case HFA384x_LINK_AP_CHANGE:
+ /* This one indicates that the MAC has decided to and
+ * successfully completed a change to another AP. We
+ * should probably implement a reassociation indication
+ * in response to this one. I'm thinking that the the
+ * p80211 layer needs to be notified in case of
+ * buffering/queueing issues. User mode also needs to be
+ * notified so that any BSS dependent elements can be
+ * updated.
+ * associated state. We * should send a deauth indication
+ * (implying disassoc) up * to the MLME.
+ * Response:
+ * Indicate Reassociation
+ * Enable Transmits, Receives and pass up data frames
+ */
+ WLAN_LOG_INFO("linkstatus=AP_CHANGE\n");
+
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTBSSID,
+ wlandev->bssid, WLAN_BSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTBSSID, result);
+ goto failed;
+ }
+
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTSSID,
+ &ssid, sizeof(ssid));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTSSID, result);
+ goto failed;
+ }
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
+ (p80211pstrd_t *) &wlandev->ssid);
+
+
+ hw->link_status = HFA384x_LINK_CONNECTED;
+ netif_carrier_on(wlandev->netdev);
+
+ break;
+
+ case HFA384x_LINK_AP_OUTOFRANGE:
+ /* This one indicates that the MAC has decided that the
+ * AP is out of range, but hasn't found a better candidate
+ * so the MAC maintains its "associated" state in case
+ * we get back in range. We should block transmits and
+ * receives in this state. Do we need an indication here?
+ * Probably not since a polling user-mode element would
+ * get this status from from p2PortStatus(FD40). What about
+ * p80211?
+ * Response:
+ * Block Transmits, Ignore receives of data frames
+ */
+ WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n");
+
+ netif_carrier_off(wlandev->netdev);
+
+ break;
+
+ case HFA384x_LINK_AP_INRANGE:
+ /* This one indicates that the MAC has decided that the
+ * AP is back in range. We continue working with our
+ * existing association.
+ * Response:
+ * Enable Transmits, Receives and pass up data frames
+ */
+ WLAN_LOG_INFO("linkstatus=AP_INRANGE\n");
+
+ hw->link_status = HFA384x_LINK_CONNECTED;
+ netif_carrier_on(wlandev->netdev);
+
+ break;
+
+ case HFA384x_LINK_ASSOCFAIL:
+ /* This one is actually a peer to CONNECTED. We've
+ * requested a join for a given SSID and optionally BSSID.
+ * We can use this one to indicate authentication and
+ * association failures. The trick is going to be
+ * 1) identifying the failure, and 2) state management.
+ * Response:
+ * Disable Transmits, Ignore receives of data frames
+ */
+ if(hw->join_ap && --hw->join_retries > 0)
+ {
+ hfa384x_JoinRequest_data_t joinreq;
+ joinreq = hw->joinreq;
+ /* Send the join request */
+ hfa384x_drvr_setconfig( hw,
+ HFA384x_RID_JOINREQUEST,
+ &joinreq, HFA384x_RID_JOINREQUEST_LEN);
+ WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n");
+ } else {
+ WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n");
+ }
+
+ netif_carrier_off(wlandev->netdev);
+
+ break;
+
+ default:
+ /* This is bad, IO port problems? */
+ WLAN_LOG_WARNING(
+ "unknown linkstatus=0x%02x\n", hw->link_status);
+ goto failed;
+ break;
+ }
+
+ wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED);
+#ifdef WIRELESS_EXT
+ p80211wext_event_associated(wlandev, wlandev->linkstatus);
+#endif
+
+ failed:
+ DBFEXIT;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_linkstatus
+*
+* Handles the receipt of a Link Status info frame.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_linkstatus(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+
+ DBFENTER;
+
+ hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus);
+
+ schedule_work(&hw->link_bh);
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_assocstatus
+*
+* Handles the receipt of an Association Status info frame. Should
+* be present in APs only.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_assocstatus(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ hfa384x_AssocStatus_t rec;
+ int i;
+
+ DBFENTER;
+
+ memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
+ rec.assocstatus = hfa384x2host_16(rec.assocstatus);
+ rec.reason = hfa384x2host_16(rec.reason);
+
+ /*
+ ** Find the address in the list of authenticated stations. If it wasn't
+ ** found, then this address has not been previously authenticated and
+ ** something weird has happened if this is anything other than an
+ ** "authentication failed" message. If the address was found, then
+ ** set the "associated" flag for that station, based on whether the
+ ** station is associating or losing its association. Something weird
+ ** has also happened if we find the address in the list of authenticated
+ ** stations but we are getting an "authentication failed" message.
+ */
+
+ for (i = 0; i < hw->authlist.cnt; i++)
+ if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
+ break;
+
+ if (i >= hw->authlist.cnt) {
+ if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL)
+ WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n");
+ } else {
+ hw->authlist.assoc[i] =
+ (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC ||
+ rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC);
+
+ if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL)
+ WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n");
+ }
+
+ DBFEXIT;
+
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_inf_authreq
+*
+* Handles the receipt of an Authentication Request info frame. Should
+* be present in APs only.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+*
+----------------------------------------------------------------*/
+static void prism2sta_inf_authreq(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ struct sk_buff *skb;
+
+ DBFENTER;
+
+ skb = dev_alloc_skb(sizeof(*inf));
+ if (skb) {
+ skb_put(skb, sizeof(*inf));
+ memcpy(skb->data, inf, sizeof(*inf));
+ skb_queue_tail(&hw->authq, skb);
+ schedule_work(&hw->link_bh);
+ }
+
+ DBFEXIT;
+}
+
+static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+ hfa384x_authenticateStation_data_t rec;
+
+ int i, added, result, cnt;
+ UINT8 *addr;
+
+ DBFENTER;
+
+ /*
+ ** Build the AuthenticateStation record. Initialize it for denying
+ ** authentication.
+ */
+
+ memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN);
+ rec.status = P80211ENUM_status_unspec_failure;
+
+ /*
+ ** Authenticate based on the access mode.
+ */
+
+ switch (hw->accessmode) {
+ case WLAN_ACCESS_NONE:
+
+ /*
+ ** Deny all new authentications. However, if a station
+ ** is ALREADY authenticated, then accept it.
+ */
+
+ for (i = 0; i < hw->authlist.cnt; i++)
+ if (memcmp(rec.address, hw->authlist.addr[i],
+ WLAN_ADDR_LEN) == 0) {
+ rec.status = P80211ENUM_status_successful;
+ break;
+ }
+
+ break;
+
+ case WLAN_ACCESS_ALL:
+
+ /*
+ ** Allow all authentications.
+ */
+
+ rec.status = P80211ENUM_status_successful;
+ break;
+
+ case WLAN_ACCESS_ALLOW:
+
+ /*
+ ** Only allow the authentication if the MAC address
+ ** is in the list of allowed addresses.
+ **
+ ** Since this is the interrupt handler, we may be here
+ ** while the access list is in the middle of being
+ ** updated. Choose the list which is currently okay.
+ ** See "prism2mib_priv_accessallow()" for details.
+ */
+
+ if (hw->allow.modify == 0) {
+ cnt = hw->allow.cnt;
+ addr = hw->allow.addr[0];
+ } else {
+ cnt = hw->allow.cnt1;
+ addr = hw->allow.addr1[0];
+ }
+
+ for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
+ if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
+ rec.status = P80211ENUM_status_successful;
+ break;
+ }
+
+ break;
+
+ case WLAN_ACCESS_DENY:
+
+ /*
+ ** Allow the authentication UNLESS the MAC address is
+ ** in the list of denied addresses.
+ **
+ ** Since this is the interrupt handler, we may be here
+ ** while the access list is in the middle of being
+ ** updated. Choose the list which is currently okay.
+ ** See "prism2mib_priv_accessdeny()" for details.
+ */
+
+ if (hw->deny.modify == 0) {
+ cnt = hw->deny.cnt;
+ addr = hw->deny.addr[0];
+ } else {
+ cnt = hw->deny.cnt1;
+ addr = hw->deny.addr1[0];
+ }
+
+ rec.status = P80211ENUM_status_successful;
+
+ for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
+ if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
+ rec.status = P80211ENUM_status_unspec_failure;
+ break;
+ }
+
+ break;
+ }
+
+ /*
+ ** If the authentication is okay, then add the MAC address to the list
+ ** of authenticated stations. Don't add the address if it is already in
+ ** the list. (802.11b does not seem to disallow a station from issuing
+ ** an authentication request when the station is already authenticated.
+ ** Does this sort of thing ever happen? We might as well do the check
+ ** just in case.)
+ */
+
+ added = 0;
+
+ if (rec.status == P80211ENUM_status_successful) {
+ for (i = 0; i < hw->authlist.cnt; i++)
+ if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
+ break;
+
+ if (i >= hw->authlist.cnt) {
+ if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
+ rec.status = P80211ENUM_status_ap_full;
+ } else {
+ memcpy(hw->authlist.addr[hw->authlist.cnt],
+ rec.address, WLAN_ADDR_LEN);
+ hw->authlist.cnt++;
+ added = 1;
+ }
+ }
+ }
+
+ /*
+ ** Send back the results of the authentication. If this doesn't work,
+ ** then make sure to remove the address from the authenticated list if
+ ** it was added.
+ */
+
+ rec.status = host2hfa384x_16(rec.status);
+ rec.algorithm = inf->info.authreq.algorithm;
+
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA,
+ &rec, sizeof(rec));
+ if (result) {
+ if (added) hw->authlist.cnt--;
+ WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result);
+ }
+
+ DBFEXIT;
+
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_inf_psusercnt
+*
+* Handles the receipt of a PowerSaveUserCount info frame. Should
+* be present in APs only.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to info frame (contents in hfa384x order)
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+static void prism2sta_inf_psusercnt(wlandevice_t *wlandev,
+ hfa384x_InfFrame_t *inf)
+{
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+
+ DBFENTER;
+
+ hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt);
+
+ DBFEXIT;
+
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_ev_dtim
+*
+* Handles the DTIM early warning event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_dtim(wlandevice_t *wlandev)
+{
+#if 0
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+#endif
+ DBFENTER;
+ WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n");
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ev_infdrop
+*
+* Handles the InfDrop event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_infdrop(wlandevice_t *wlandev)
+{
+#if 0
+ hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
+#endif
+ DBFENTER;
+ WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n");
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ev_info
+*
+* Handles the Info event.
+*
+* Arguments:
+* wlandev wlan device structure
+* inf ptr to a generic info frame
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
+{
+ DBFENTER;
+ inf->infotype = hfa384x2host_16(inf->infotype);
+ /* Dispatch */
+ switch ( inf->infotype ) {
+ case HFA384x_IT_HANDOVERADDR:
+ prism2sta_inf_handover(wlandev, inf);
+ break;
+ case HFA384x_IT_COMMTALLIES:
+ prism2sta_inf_tallies(wlandev, inf);
+ break;
+ case HFA384x_IT_HOSTSCANRESULTS:
+ prism2sta_inf_hostscanresults(wlandev, inf);
+ break;
+ case HFA384x_IT_SCANRESULTS:
+ prism2sta_inf_scanresults(wlandev, inf);
+ break;
+ case HFA384x_IT_CHINFORESULTS:
+ prism2sta_inf_chinforesults(wlandev, inf);
+ break;
+ case HFA384x_IT_LINKSTATUS:
+ prism2sta_inf_linkstatus(wlandev, inf);
+ break;
+ case HFA384x_IT_ASSOCSTATUS:
+ prism2sta_inf_assocstatus(wlandev, inf);
+ break;
+ case HFA384x_IT_AUTHREQ:
+ prism2sta_inf_authreq(wlandev, inf);
+ break;
+ case HFA384x_IT_PSUSERCNT:
+ prism2sta_inf_psusercnt(wlandev, inf);
+ break;
+ case HFA384x_IT_KEYIDCHANGED:
+ WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n");
+ break;
+ case HFA384x_IT_ASSOCREQ:
+ WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n");
+ break;
+ case HFA384x_IT_MICFAILURE:
+ WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n");
+ break;
+ default:
+ WLAN_LOG_WARNING(
+ "Unknown info type=0x%02x\n", inf->infotype);
+ break;
+ }
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ev_txexc
+*
+* Handles the TxExc event. A Transmit Exception event indicates
+* that the MAC's TX process was unsuccessful - so the packet did
+* not get transmitted.
+*
+* Arguments:
+* wlandev wlan device structure
+* status tx frame status word
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_txexc(wlandevice_t *wlandev, UINT16 status)
+{
+ DBFENTER;
+
+ WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status);
+
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ev_tx
+*
+* Handles the Tx event.
+*
+* Arguments:
+* wlandev wlan device structure
+* status tx frame status word
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_tx(wlandevice_t *wlandev, UINT16 status)
+{
+ DBFENTER;
+ WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status);
+ /* update linux network stats */
+ wlandev->linux_stats.tx_packets++;
+ DBFEXIT;
+ return;
+}
+
+
+/*----------------------------------------------------------------
+* prism2sta_ev_rx
+*
+* Handles the Rx event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb)
+{
+ DBFENTER;
+
+ p80211netdev_rx(wlandev, skb);
+
+ DBFEXIT;
+ return;
+}
+
+/*----------------------------------------------------------------
+* prism2sta_ev_alloc
+*
+* Handles the Alloc event.
+*
+* Arguments:
+* wlandev wlan device structure
+*
+* Returns:
+* nothing
+*
+* Side effects:
+*
+* Call context:
+* interrupt
+----------------------------------------------------------------*/
+void prism2sta_ev_alloc(wlandevice_t *wlandev)
+{
+ DBFENTER;
+
+ p80211netdev_wake_queue(wlandev);
+
+ DBFEXIT;
+ return;
+}
+
+#if (WLAN_HOSTIF == WLAN_PLX || WLAN_HOSTIF == WLAN_PCI)
+#ifdef CONFIG_PM
+static int prism2sta_suspend_pci(struct pci_dev *pdev, pm_message_t state)
+{
+ wlandevice_t *wlandev;
+
+ wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
+
+ /* reset hardware */
+ if (wlandev) {
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+ p80211_suspend(wlandev);
+ }
+
+ // call a netif_device_detach(wlandev->netdev) ?
+
+ return 0;
+}
+
+static int prism2sta_resume_pci (struct pci_dev *pdev)
+{
+ wlandevice_t *wlandev;
+
+ wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
+
+ if (wlandev) {
+ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
+ p80211_resume(wlandev);
+ }
+
+ return 0;
+}
+#endif
+#endif
+
+/*----------------------------------------------------------------
+* create_wlan
+*
+* Called at module init time. This creates the wlandevice_t structure
+* and initializes it with relevant bits.
+*
+* Arguments:
+* none
+*
+* Returns:
+* the created wlandevice_t structure.
+*
+* Side effects:
+* also allocates the priv/hw structures.
+*
+* Call context:
+* process thread
+*
+----------------------------------------------------------------*/
+static wlandevice_t *create_wlan(void)
+{
+ wlandevice_t *wlandev = NULL;
+ hfa384x_t *hw = NULL;
+
+ /* Alloc our structures */
+ wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL);
+ hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL);
+
+ if (!wlandev || !hw) {
+ WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
+ if (wlandev) kfree(wlandev);
+ if (hw) kfree(hw);
+ return NULL;
+ }
+
+ /* Clear all the structs */
+ memset(wlandev, 0, sizeof(wlandevice_t));
+ memset(hw, 0, sizeof(hfa384x_t));
+
+ /* Initialize the network device object. */
+ wlandev->nsdname = dev_info;
+ wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
+ wlandev->priv = hw;
+ wlandev->open = prism2sta_open;
+ wlandev->close = prism2sta_close;
+ wlandev->reset = prism2sta_reset;
+#ifdef CONFIG_PROC_FS
+ wlandev->nsd_proc_read = prism2sta_proc_read;
+#endif
+ wlandev->txframe = prism2sta_txframe;
+ wlandev->mlmerequest = prism2sta_mlmerequest;
+ wlandev->set_multicast_list = prism2sta_setmulticast;
+ wlandev->tx_timeout = hfa384x_tx_timeout;
+
+ wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT |
+ P80211_NSDCAP_AUTOJOIN;
+
+ /* Initialize the device private data stucture. */
+ hw->dot11_desired_bss_type = 1;
+
+ return wlandev;
+}
+
+#ifdef CONFIG_PROC_FS
+static int
+prism2sta_proc_read(
+ char *page,
+ char **start,
+ off_t offset,
+ int count,
+ int *eof,
+ void *data)
+{
+ char *p = page;
+ wlandevice_t *wlandev = (wlandevice_t *) data;
+ hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
+
+ UINT16 hwtype = 0;
+
+ DBFENTER;
+ if (offset != 0) {
+ *eof = 1;
+ goto exit;
+ }
+
+ // XXX 0x0001 for prism2.5/3, 0x0000 for prism2.
+ hwtype = BIT0;
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ if (hw->isram16)
+ hwtype |= BIT1;
+#endif
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+ hwtype |= BIT2;
+#endif
+
+#define PRISM2_CVS_ID "$Id: prism2sta.c 1826 2007-03-19 15:37:00Z pizza $"
+
+ p += sprintf(p, "# %s version %s (%s) '%s'\n\n",
+ dev_info,
+ WLAN_RELEASE, WLAN_BUILD_DATE, PRISM2_CVS_ID);
+
+ p += sprintf(p, "# nic h/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_nic.id, hw->ident_nic.major,
+ hw->ident_nic.minor, hw->ident_nic.variant);
+
+ p += sprintf(p, "# pri f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_pri_fw.id, hw->ident_pri_fw.major,
+ hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
+
+ if (hw->ident_sta_fw.id == 0x1f) {
+ p += sprintf(p, "# sta f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_sta_fw.id, hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
+ } else {
+ p += sprintf(p, "# ap f/w: id=0x%02x %d.%d.%d\n",
+ hw->ident_sta_fw.id, hw->ident_sta_fw.major,
+ hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
+ }
+
+#if (WLAN_HOSTIF != WLAN_USB)
+ p += sprintf(p, "# initial nic hw type, needed for SSF ramdl\n");
+ p += sprintf(p, "initnichw=%04x\n", hwtype);
+#endif
+
+ exit:
+ DBFEXIT;
+ return (p - page);
+}
+#endif
+
+void prism2sta_commsqual_defer(struct work_struct *data)
+{
+ hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh);
+ wlandevice_t *wlandev = hw->wlandev;
+ hfa384x_bytestr32_t ssid;
+ int result = 0;
+
+ DBFENTER;
+
+ if (hw->wlandev->hwremoved)
+ goto done;
+
+ /* we don't care if we're in AP mode */
+ if ((wlandev->macmode == WLAN_MACMODE_NONE) ||
+ (wlandev->macmode == WLAN_MACMODE_ESS_AP)) {
+ goto done;
+ }
+
+ /* It only makes sense to poll these in non-IBSS */
+ if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) {
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY,
+ &hw->qual,
+ HFA384x_RID_DBMCOMMSQUALITY_LEN);
+
+ if (result) {
+ WLAN_LOG_ERROR("error fetching commsqual\n");
+ goto done;
+ }
+
+ // qual.CQ_currBSS; // link
+ // ASL_currBSS; // level
+ // qual.ANL_currFC; // noise
+
+ WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n",
+ hfa384x2host_16(hw->qual.CQ_currBSS),
+ hfa384x2host_16(hw->qual.ASL_currBSS),
+ hfa384x2host_16(hw->qual.ANL_currFC));
+ }
+
+ /* Lastly, we need to make sure the BSSID didn't change on us */
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTBSSID,
+ wlandev->bssid, WLAN_BSSID_LEN);
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTBSSID, result);
+ goto done;
+ }
+
+ result = hfa384x_drvr_getconfig(hw,
+ HFA384x_RID_CURRENTSSID,
+ &ssid, sizeof(ssid));
+ if ( result ) {
+ WLAN_LOG_DEBUG(1,
+ "getconfig(0x%02x) failed, result = %d\n",
+ HFA384x_RID_CURRENTSSID, result);
+ goto done;
+ }
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
+ (p80211pstrd_t *) &wlandev->ssid);
+
+
+ /* Reschedule timer */
+ mod_timer(&hw->commsqual_timer, jiffies + HZ);
+
+ done:
+ DBFEXIT;
+}
+
+void prism2sta_commsqual_timer(unsigned long data)
+{
+ hfa384x_t *hw = (hfa384x_t *) data;
+
+ DBFENTER;
+
+ schedule_work(&hw->commsqual_bh);
+
+ DBFEXIT;
+}
diff --git a/drivers/staging/wlan-ng/version.h b/drivers/staging/wlan-ng/version.h
new file mode 100644
index 00000000000..305f8823944
--- /dev/null
+++ b/drivers/staging/wlan-ng/version.h
@@ -0,0 +1,64 @@
+/* src/include/wlan/version.h
+*
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+#ifndef _WLAN_VERSION_H
+#define _WLAN_VERSION_H
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+/* WLAN_HOSTIF (generally set on the command line, not detected) */
+#define WLAN_NONE 0
+#define WLAN_PCMCIA 1
+#define WLAN_ISA 2
+#define WLAN_PCI 3
+#define WLAN_USB 4
+#define WLAN_PLX 5
+#define WLAN_SLAVE 6
+#define WLAN_RELEASE "0.2.8"
+#define WLAN_RELEASE_CODE 0x000208
+#define WLAN_BUILD_DATE "Thu Oct 2 11:04:42 PDT 2008"
+
+#endif
diff --git a/drivers/staging/wlan-ng/wlan_compat.h b/drivers/staging/wlan-ng/wlan_compat.h
new file mode 100644
index 00000000000..17026570708
--- /dev/null
+++ b/drivers/staging/wlan-ng/wlan_compat.h
@@ -0,0 +1,757 @@
+/* wlan_compat.h
+*
+* Types and macros to aid in portability
+*
+* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+* --------------------------------------------------------------------
+*
+* linux-wlan
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS
+* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* Alternatively, the contents of this file may be used under the
+* terms of the GNU Public License version 2 (the "GPL"), in which
+* case the provisions of the GPL are applicable instead of the
+* above. If you wish to allow the use of your version of this file
+* only under the terms of the GPL and not to allow others to use
+* your version of this file under the MPL, indicate your decision
+* by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL. If you do not delete
+* the provisions above, a recipient may use your version of this
+* file under either the MPL or the GPL.
+*
+* --------------------------------------------------------------------
+*
+* Inquiries regarding the linux-wlan Open Source project can be
+* made directly to:
+*
+* AbsoluteValue Systems Inc.
+* info@linux-wlan.com
+* http://www.linux-wlan.com
+*
+* --------------------------------------------------------------------
+*
+* Portions of the development of this software were funded by
+* Intersil Corporation as part of PRISM(R) chipset product development.
+*
+* --------------------------------------------------------------------
+*/
+
+#ifndef _WLAN_COMPAT_H
+#define _WLAN_COMPAT_H
+
+/*=============================================================*/
+/*------ Establish Platform Identity --------------------------*/
+/*=============================================================*/
+/* Key macros: */
+/* WLAN_CPU_FAMILY */
+ #define WLAN_Ix86 1
+ #define WLAN_PPC 2
+ #define WLAN_Ix96 3
+ #define WLAN_ARM 4
+ #define WLAN_ALPHA 5
+ #define WLAN_MIPS 6
+ #define WLAN_HPPA 7
+ #define WLAN_SPARC 8
+ #define WLAN_SH 9
+ #define WLAN_x86_64 10
+/* WLAN_SYSARCH */
+ #define WLAN_PCAT 1
+ #define WLAN_MBX 2
+ #define WLAN_RPX 3
+ #define WLAN_LWARCH 4
+ #define WLAN_PMAC 5
+ #define WLAN_SKIFF 6
+ #define WLAN_BITSY 7
+ #define WLAN_ALPHAARCH 7
+ #define WLAN_MIPSARCH 9
+ #define WLAN_HPPAARCH 10
+ #define WLAN_SPARCARCH 11
+ #define WLAN_SHARCH 12
+
+/* Note: the PLX HOSTIF above refers to some vendors implementations for */
+/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */
+/* isn't a real PCMCIA host interface adapter providing all the */
+/* card&socket services. */
+
+#if (defined(CONFIG_PPC) || defined(CONFIG_8xx) || defined(__powerpc__))
+#ifndef __ppc__
+#define __ppc__
+#endif
+#endif
+
+#if defined(__KERNEL__)
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+
+#if defined(__x86_64__)
+ #define WLAN_CPU_FAMILY WLAN_x86_64
+ #define WLAN_SYSARCH WLAN_PCAT
+#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
+ #define WLAN_CPU_FAMILY WLAN_Ix86
+ #define WLAN_SYSARCH WLAN_PCAT
+#elif defined(__ppc__)
+ #define WLAN_CPU_FAMILY WLAN_PPC
+ #if defined(CONFIG_MBX)
+ #define WLAN_SYSARCH WLAN_MBX
+ #elif defined(CONFIG_RPXLITE)
+ #define WLAN_SYSARCH WLAN_RPX
+ #elif defined(CONFIG_RPXCLASSIC)
+ #define WLAN_SYSARCH WLAN_RPX
+ #else
+ #define WLAN_SYSARCH WLAN_PMAC
+ #endif
+#elif defined(__arm__)
+ #define WLAN_CPU_FAMILY WLAN_ARM
+ #define WLAN_SYSARCH WLAN_SKIFF
+#elif defined(__alpha__)
+ #define WLAN_CPU_FAMILY WLAN_ALPHA
+ #define WLAN_SYSARCH WLAN_ALPHAARCH
+#elif defined(__mips__)
+ #define WLAN_CPU_FAMILY WLAN_MIPS
+ #define WLAN_SYSARCH WLAN_MIPSARCH
+#elif defined(__hppa__)
+ #define WLAN_CPU_FAMILY WLAN_HPPA
+ #define WLAN_SYSARCH WLAN_HPPAARCH
+#elif defined(__sparc__)
+ #define WLAN_CPU_FAMILY WLAN_SPARC
+ #define WLAN_SYSARCH WLAN_SPARC
+#elif defined(__sh__)
+ #define WLAN_CPU_FAMILY WLAN_SH
+ #define WLAN_SYSARCH WLAN_SHARCH
+ #ifndef __LITTLE_ENDIAN__
+ #define __LITTLE_ENDIAN__
+ #endif
+#else
+ #error "No CPU identified!"
+#endif
+#endif /* __KERNEL__ */
+
+/*
+ Some big endian machines implicitly do all I/O in little endian mode.
+
+ In particular:
+ Linux/PPC on PowerMacs (PCI)
+ Arm/Intel Xscale (PCI)
+
+ This may also affect PLX boards and other BE &| PPC platforms;
+ as new ones are discovered, add them below.
+*/
+
+#if defined(WLAN_HOSTIF)
+#if ((WLAN_HOSTIF == WLAN_PCI) || (WLAN_HOSTIF == WLAN_PLX))
+#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC) || (WLAN_SYSARCH == WLAN_SPARC))
+#define REVERSE_ENDIAN
+#endif
+#endif
+#endif
+
+/*=============================================================*/
+/*------ Bit settings -----------------------------------------*/
+/*=============================================================*/
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+#include <linux/types.h>
+
+typedef u_int8_t UINT8;
+typedef u_int16_t UINT16;
+typedef u_int32_t UINT32;
+
+typedef int8_t INT8;
+typedef int16_t INT16;
+typedef int32_t INT32;
+
+typedef unsigned int UINT;
+typedef signed int INT;
+
+typedef u_int64_t UINT64;
+typedef int64_t INT64;
+
+#define UINT8_MAX (0xffUL)
+#define UINT16_MAX (0xffffUL)
+#define UINT32_MAX (0xffffffffUL)
+
+#define INT8_MAX (0x7fL)
+#define INT16_MAX (0x7fffL)
+#define INT32_MAX (0x7fffffffL)
+
+/*=============================================================*/
+/*------ Compiler Portability Macros --------------------------*/
+/*=============================================================*/
+#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed))
+
+/*=============================================================*/
+/*------ OS Portability Macros --------------------------------*/
+/*=============================================================*/
+
+#ifndef WLAN_DBVAR
+#define WLAN_DBVAR wlan_debug
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8))
+# include <linux/hardirq.h>
+# else
+# include <asm/hardirq.h>
+# endif
+#elif defined(__KERNEL__)
+# define PREEMPT_MASK (0x000000FFUL)
+# define preempt_count() (0UL)
+#endif
+
+#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __FUNCTION__ , ##args);
+
+#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __FUNCTION__ , ##args);
+
+#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __FUNCTION__ , ##args);
+
+#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args)
+
+#if defined(WLAN_INCLUDE_DEBUG)
+ #define WLAN_ASSERT(c) if ((!(c)) && WLAN_DBVAR >= 1) { \
+ WLAN_LOG_DEBUG(1, "Assertion failure!\n"); }
+ #define WLAN_HEX_DUMP( l, x, p, n) if( WLAN_DBVAR >= (l) ){ \
+ int __i__; \
+ printk(KERN_DEBUG x ":"); \
+ for( __i__=0; __i__ < (n); __i__++) \
+ printk( " %02x", ((UINT8*)(p))[__i__]); \
+ printk("\n"); }
+ #define DBFENTER { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"---->\n"); } }
+ #define DBFEXIT { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"<----\n"); } }
+
+ #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __FUNCTION__, (preempt_count() & PREEMPT_MASK), ##args );
+#else
+ #define WLAN_ASSERT(c)
+ #define WLAN_HEX_DUMP( l, s, p, n)
+ #define DBFENTER
+ #define DBFEXIT
+
+ #define WLAN_LOG_DEBUG(l, s, args...)
+#endif
+
+#ifdef CONFIG_SMP
+#define __SMP__ 1
+#endif
+
+#if defined(__KERNEL__)
+
+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)))
+#define URB_ONLY_CALLBACK
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+#define PT_REGS , struct pt_regs *regs
+#else
+#define PT_REGS
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7))
+# define del_singleshot_timer_sync(a) del_timer_sync(a)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17))
+#define CONFIG_NETLINK 1
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+#define kfree_s(a, b) kfree((a))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18))
+#ifndef init_waitqueue_head
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,0,16))
+#define init_waitqueue_head(p) (*(p) = NULL)
+#else
+#define init_waitqueue_head(p) init_waitqueue(p)
+#endif
+typedef struct wait_queue *wait_queue_head_t;
+typedef struct wait_queue wait_queue_t;
+#define set_current_state(b) { current->state = (b); mb(); }
+#define init_waitqueue_entry(a, b) { (a)->task = current; }
+#endif
+#endif
+
+#ifndef wait_event_interruptible_timeout
+// retval == 0; signal met; we're good.
+// retval < 0; interrupted by signal.
+// retval > 0; timed out.
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) // fixme?
+
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ wait_queue_t __wait; \
+ init_waitqueue_entry(&__wait, current); \
+ \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret) ; \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ set_current_state(TASK_RUNNING); \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#else // 2.2
+
+
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ struct wait_queue __wait; \
+ \
+ __wait.task = current; \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ current->state = TASK_INTERRUPTIBLE; \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret); \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#endif // version >= 2.4
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ __ret; \
+})
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
+#ifdef _LINUX_LIST_H
+
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+
+#endif // LIST_H
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,90))
+#define spin_lock(l) do { } while (0)
+#define spin_unlock(l) do { } while (0)
+#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0)
+#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0)
+#define spin_lock_init(s) do { } while (0)
+#define spin_trylock(l) (1)
+typedef int spinlock_t;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) // XXX ???
+#define spin_lock_bh spin_lock
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#ifdef CONFIG_SMP
+#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0)
+#else
+#define spin_is_locked(l) (0)
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28))
+#define __user
+#define __iomem
+#endif
+
+#ifdef _LINUX_PROC_FS_H
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,25))
+
+extern inline struct proc_dir_entry *
+create_proc_read_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *base,
+ read_proc_t *read_proc, void *data)
+{
+ struct proc_dir_entry *res = create_proc_entry(name, mode, base);
+ if (res) {
+ res->read_proc = read_proc;
+ res->data = data;
+ }
+ return res;
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29))
+#ifndef proc_mkdir
+#define proc_mkdir(name, root) create_proc_entry(name, S_IFDIR, root)
+#endif
+#endif
+#endif /* _LINUX_PROC_FS_H */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#ifndef INIT_TQUEUE
+#define PREPARE_TQUEUE(_tq, _routine, _data) \
+ do { \
+ (_tq)->routine = _routine; \
+ (_tq)->data = _data; \
+ } while (0)
+#define INIT_TQUEUE(_tq, _routine, _data) \
+ do { \
+ INIT_LIST_HEAD(&(_tq)->list); \
+ (_tq)->sync = 0; \
+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
+ } while (0)
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#ifndef INIT_WORK
+#define work_struct tq_struct
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#define schedule_work(a) queue_task(a, &tq_scheduler)
+#else
+#define schedule_work(a) schedule_task(a)
+#endif
+
+#define flush_scheduled_work flush_scheduled_tasks
+#define INIT_WORK2(_wq, _routine) INIT_TQUEUE(_wq, (void (*)(void *))_routine, _wq)
+#endif
+
+#else // >= 2.5 kernel
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, (void (*)(void *))_routine, _wq)
+#else
+#define INIT_WORK2(_wq, _routine) INIT_WORK(_wq, _routine)
+#endif
+
+#endif // >= 2.5 kernel
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38))
+typedef struct device netdevice_t;
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4))
+typedef struct net_device netdevice_t;
+#else
+#undef netdevice_t
+typedef struct net_device netdevice_t;
+#endif
+
+#ifdef WIRELESS_EXT
+#if (WIRELESS_EXT < 13)
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+#endif
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18))
+#define MODULE_PARM(a,b) extern int __bogus_decl
+#define MODULE_AUTHOR(a) extern int __bogus_decl
+#define MODULE_DESCRIPTION(a) extern int __bogus_decl
+#define MODULE_SUPPORTED_DEVICE(a) extern int __bogus_decl
+#undef GET_USE_COUNT
+#define GET_USE_COUNT(m) mod_use_count_
+#endif
+
+#ifndef MODULE_OWNER
+#define MODULE_OWNER(a) extern int __bogus_decl
+#define ANCIENT_MODULE_CODE
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(m) extern int __bogus_decl
+#endif
+
+/* TODO: Do we care about this? */
+#ifndef MODULE_DEVICE_TABLE
+#define MODULE_DEVICE_TABLE(foo,bar)
+#endif
+
+#define wlan_minutes2ticks(a) ((a)*(wlan_ticks_per_sec * 60))
+#define wlan_seconds2ticks(a) ((a)*(wlan_ticks_per_sec))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,47))
+#define NEW_MODULE_CODE
+#ifdef ANCIENT_MODULE_CODE
+#undef ANCIENT_MODULE_CODE
+#endif
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25))
+#define module_param(name, type, perm) \
+ static inline void *__check_existence_##name(void) { return &name; } \
+ MODULE_PARM(name, _MODULE_PARM_STRING_ ## type)
+
+#define _MODULE_PARM_STRING_byte "b"
+#define _MODULE_PARM_STRING_short "h"
+#define _MODULE_PARM_STRING_ushort "h"
+#define _MODULE_PARM_STRING_int "i"
+#define _MODULE_PARM_STRING_uint "i"
+#define _MODULE_PARM_STRING_long "l"
+#define _MODULE_PARM_STRING_ulong "l"
+#define _MODULE_PARM_STRING_bool "i"
+#endif
+
+/* linux < 2.5.69 */
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+
+#ifndef in_atomic
+#define in_atomic() 0
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+#define URB_ASYNC_UNLINK 0
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7))
+#define URB_ASYNC_UNLINK USB_ASYNC_UNLINK
+#define usb_fill_bulk_urb FILL_BULK_URB
+#define usb_kill_urb usb_unlink_urb
+#else
+#define USB_QUEUE_BULK 0
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+typedef u32 pm_message_t;
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9))
+#define hotplug_path "/etc/hotplug/wlan.agent"
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#define free_netdev(x) kfree(x)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
+#define eth_hdr(x) (x)->mac.ethernet
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#define del_timer_sync(a) del_timer(a)
+#endif
+
+#ifndef might_sleep
+#define might_sleep(a) do { } while (0)
+#endif
+
+/* Apparently 2.4.2 ethtool is quite different, maybe newer too? */
+#if (defined(SIOETHTOOL) && !defined(ETHTOOL_GDRVINFO))
+#undef SIOETHTOOL
+#endif
+
+// pcmcia-cs stuff
+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && \
+ !defined(pcmcia_access_configuration_register))
+#define pcmcia_access_configuration_register(handle, reg) \
+ CardServices(AccessConfigurationRegister, handle, reg)
+#define pcmcia_register_client(handle, reg) \
+ CardServices(RegisterClient, handle, reg)
+#define pcmcia_deregister_client(handle) \
+ CardServices(DeregisterClient, handle)
+#define pcmcia_get_first_tuple(handle, tuple) \
+ CardServices(GetFirstTuple, handle, tuple)
+#define pcmcia_get_next_tuple(handle, tuple) \
+ CardServices(GetNextTuple, handle, tuple)
+#define pcmcia_get_tuple_data(handle, tuple) \
+ CardServices(GetTupleData, handle, tuple)
+#define pcmcia_parse_tuple(handle, tuple, parse) \
+ CardServices(ParseTuple, handle, tuple, parse)
+#define pcmcia_get_configuration_info(handle, config) \
+ CardServices(GetConfigurationInfo, handle, config)
+#define pcmcia_request_io(handle, req) \
+ CardServices(RequestIO, handle, req)
+#define pcmcia_request_irq(handle, req) \
+ CardServices(RequestIRQ, handle, req)
+#define pcmcia_request_configuration(handle, req) \
+ CardServices(RequestConfiguration, handle, req)
+#define pcmcia_release_configuration(handle) \
+ CardServices(ReleaseConfiguration, handle)
+#define pcmcia_release_io(handle, req) \
+ CardServices(ReleaseIO, handle, req)
+#define pcmcia_release_irq(handle, req) \
+ CardServices(ReleaseIRQ, handle, req)
+#define pcmcia_release_window(win) \
+ CardServices(ReleaseWindow, win)
+#define pcmcia_get_card_services_info(info) \
+ CardServices(GetCardServicesInfo, info)
+#define pcmcia_report_error(handle, err) \
+ CardServices(ReportError, handle, err)
+#endif
+
+#endif /* __KERNEL__ */
+
+/*=============================================================*/
+/*------ Hardware Portability Macros --------------------------*/
+/*=============================================================*/
+
+#define ieee2host16(n) __le16_to_cpu(n)
+#define ieee2host32(n) __le32_to_cpu(n)
+#define host2ieee16(n) __cpu_to_le16(n)
+#define host2ieee32(n) __cpu_to_le32(n)
+
+#if (WLAN_CPU_FAMILY != WLAN_MIPS)
+typedef UINT32 phys_t;
+#endif
+
+#if (WLAN_CPU_FAMILY == WLAN_PPC)
+ #define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE))
+ #define wlan_inw_le16_to_cpu(a) inw((a))
+ #define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v))
+ #define wlan_outw_cpu_to_le16(v,a) outw((v),(a))
+#else
+ #define wlan_inw(a) inw((a))
+ #define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a)))
+ #define wlan_outw(v,a) outw((v),(a))
+ #define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a))
+#endif
+
+/*=============================================================*/
+/*--- General Macros ------------------------------------------*/
+/*=============================================================*/
+
+#define wlan_max(a, b) (((a) > (b)) ? (a) : (b))
+#define wlan_min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define wlan_isprint(c) (((c) > (0x19)) && ((c) < (0x7f)))
+
+#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a)))
+
+/* Create a string of printable chars from something that might not be */
+/* It's recommended that the str be 4*len + 1 bytes long */
+#define wlan_mkprintstr(buf, buflen, str, strlen) \
+{ \
+ int i = 0; \
+ int j = 0; \
+ memset(str, 0, (strlen)); \
+ for (i = 0; i < (buflen); i++) { \
+ if ( wlan_isprint((buf)[i]) ) { \
+ (str)[j] = (buf)[i]; \
+ j++; \
+ } else { \
+ (str)[j] = '\\'; \
+ (str)[j+1] = 'x'; \
+ (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \
+ (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \
+ j += 4; \
+ } \
+ } \
+}
+
+/*=============================================================*/
+/*--- Variables -----------------------------------------------*/
+/*=============================================================*/
+
+#ifdef WLAN_INCLUDE_DEBUG
+extern int wlan_debug;
+#endif
+
+extern int wlan_ethconv; /* What's the default ethconv? */
+
+/*=============================================================*/
+/*--- Functions -----------------------------------------------*/
+/*=============================================================*/
+#endif /* _WLAN_COMPAT_H */
+
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index ec7aeb502d1..41b6530b8f2 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -42,8 +42,6 @@
***************************************************************************/
/*
- * $Log: ixj.c,v $
- *
* Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci
* Audit some copy_*_user and minor cleanup.
*
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index ff9a29b7633..347c3ed1d9f 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -124,65 +124,53 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
return;
}
+static int ixj_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin == 2) {
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
+ }
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
+}
+
static int ixj_config(struct pcmcia_device * link)
{
IXJ *j;
ixj_info_t *info;
- tuple_t tuple;
- u_short buf[128];
- cisparse_t parse;
- cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
- cistpl_cftable_entry_t dflt =
- {
- 0
- };
- int last_ret, last_fn;
+ cistpl_cftable_entry_t dflt = { 0 };
+
info = link->priv;
DEBUG(0, "ixj_config(0x%p)\n", link);
- tuple.TupleData = (cisdata_t *) buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->conf.ConfigIndex = cfg->index;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
- if (io->nwin == 2) {
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
- next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+ if (pcmcia_loop_config(link, ixj_config_check, &dflt))
+ goto cs_failed;
+
+ if (pcmcia_request_configuration(link, &link->conf))
+ goto cs_failed;
/*
* Register the card with the core.
- */
- j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10);
+ */
+ j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10);
info->ndev = 1;
info->node.major = PHONE_MAJOR;
link->dev_node = &info->node;
ixj_get_serial(link, j);
return 0;
+
cs_failed:
- cs_error(link, last_fn, last_ret);
ixj_cs_release(link);
return -ENODEV;
}
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 4190be64917..04b954cfce7 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -58,4 +58,17 @@ config UIO_SMX
If you compile this as a module, it will be called uio_smx.
+config UIO_SERCOS3
+ tristate "Automata Sercos III PCI card driver"
+ default n
+ help
+ Userspace I/O interface for the Sercos III PCI card from
+ Automata GmbH. The userspace part of this driver will be
+ available for download from the Automata GmbH web site.
+
+ Automata GmbH: http://www.automataweb.com
+ Sercos III interface: http://www.sercos.com
+
+ If you compile this as a module, it will be called uio_sercos3.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 8667bbdef90..e6955814985 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_UIO_CIF) += uio_cif.o
obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
obj-$(CONFIG_UIO_SMX) += uio_smx.o
+obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 3a6934bf713..5dccf057a7d 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -67,6 +67,11 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
return sprintf(buf, "0x%lx\n", mem->size);
}
+static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
+{
+ return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
+}
+
struct uio_sysfs_entry {
struct attribute attr;
ssize_t (*show)(struct uio_mem *, char *);
@@ -77,10 +82,13 @@ static struct uio_sysfs_entry addr_attribute =
__ATTR(addr, S_IRUGO, map_addr_show, NULL);
static struct uio_sysfs_entry size_attribute =
__ATTR(size, S_IRUGO, map_size_show, NULL);
+static struct uio_sysfs_entry offset_attribute =
+ __ATTR(offset, S_IRUGO, map_offset_show, NULL);
static struct attribute *attrs[] = {
&addr_attribute.attr,
&size_attribute.attr,
+ &offset_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
@@ -482,15 +490,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct uio_device *idev = vma->vm_private_data;
struct page *page;
+ unsigned long offset;
int mi = uio_find_mem_index(vma);
if (mi < 0)
return VM_FAULT_SIGBUS;
+ /*
+ * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
+ * to use mem[N].
+ */
+ offset = (vmf->pgoff - mi) << PAGE_SHIFT;
+
if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
- page = virt_to_page(idev->info->mem[mi].addr);
+ page = virt_to_page(idev->info->mem[mi].addr + offset);
else
- page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
+ page = vmalloc_to_page((void *)idev->info->mem[mi].addr
+ + offset);
get_page(page);
vmf->page = page;
return 0;
@@ -682,9 +698,9 @@ int __uio_register_device(struct module *owner,
if (ret)
goto err_get_minor;
- idev->dev = device_create_drvdata(uio_class->class, parent,
- MKDEV(uio_major, idev->minor), idev,
- "uio%d", idev->minor);
+ idev->dev = device_create(uio_class->class, parent,
+ MKDEV(uio_major, idev->minor), idev,
+ "uio%d", idev->minor);
if (IS_ERR(idev->dev)) {
printk(KERN_ERR "UIO: device register failed\n");
ret = PTR_ERR(idev->dev);
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 0b4ef39cd85..d494ce9288c 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -12,7 +12,7 @@
#include <linux/uio_driver.h>
#include <linux/stringify.h>
-#define DRIVER_NAME "uio"
+#define DRIVER_NAME "uio_pdrv"
struct uio_platdata {
struct uio_info *uioinfo;
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
new file mode 100644
index 00000000000..a6d1b2bc47f
--- /dev/null
+++ b/drivers/uio/uio_sercos3.c
@@ -0,0 +1,243 @@
+/* sercos3: UIO driver for the Automata Sercos III PCI card
+
+ Copyright (C) 2008 Linutronix GmbH
+ Author: John Ogness <john.ogness@linutronix.de>
+
+ This is a straight-forward UIO driver, where interrupts are disabled
+ by the interrupt handler and re-enabled via a write to the UIO device
+ by the userspace-part.
+
+ The only part that may seem odd is the use of a logical OR when
+ storing and restoring enabled interrupts. This is done because the
+ userspace-part could directly modify the Interrupt Enable Register
+ at any time. To reduce possible conflicts, the kernel driver uses
+ a logical OR to make more controlled changes (rather than blindly
+ overwriting previous values).
+
+ Race conditions exist if the userspace-part directly modifies the
+ Interrupt Enable Register while in operation. The consequences are
+ that certain interrupts would fail to be enabled or disabled. For
+ this reason, the userspace-part should only directly modify the
+ Interrupt Enable Register at the beginning (to get things going).
+ The userspace-part can safely disable interrupts at any time using
+ a write to the UIO device.
+*/
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+
+/* ID's for SERCOS III PCI card (PLX 9030) */
+#define SERCOS_SUB_VENDOR_ID 0x1971
+#define SERCOS_SUB_SYSID_3530 0x3530
+#define SERCOS_SUB_SYSID_3535 0x3535
+#define SERCOS_SUB_SYSID_3780 0x3780
+
+/* Interrupt Enable Register */
+#define IER0_OFFSET 0x08
+
+/* Interrupt Status Register */
+#define ISR0_OFFSET 0x18
+
+struct sercos3_priv {
+ u32 ier0_cache;
+ spinlock_t ier0_cache_lock;
+};
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_disable_interrupts(struct uio_info *info,
+ struct sercos3_priv *priv)
+{
+ void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+ /* add enabled interrupts to cache */
+ priv->ier0_cache |= ioread32(ier0);
+
+ /* disable interrupts */
+ iowrite32(0, ier0);
+}
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_enable_interrupts(struct uio_info *info,
+ struct sercos3_priv *priv)
+{
+ void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+ /* restore previously enabled interrupts */
+ iowrite32(ioread32(ier0) | priv->ier0_cache, ier0);
+ priv->ier0_cache = 0;
+}
+
+static irqreturn_t sercos3_handler(int irq, struct uio_info *info)
+{
+ struct sercos3_priv *priv = info->priv;
+ void __iomem *isr0 = info->mem[3].internal_addr + ISR0_OFFSET;
+ void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+ if (!(ioread32(isr0) & ioread32(ier0)))
+ return IRQ_NONE;
+
+ spin_lock(&priv->ier0_cache_lock);
+ sercos3_disable_interrupts(info, priv);
+ spin_unlock(&priv->ier0_cache_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int sercos3_irqcontrol(struct uio_info *info, s32 irq_on)
+{
+ struct sercos3_priv *priv = info->priv;
+
+ spin_lock_irq(&priv->ier0_cache_lock);
+ if (irq_on)
+ sercos3_enable_interrupts(info, priv);
+ else
+ sercos3_disable_interrupts(info, priv);
+ spin_unlock_irq(&priv->ier0_cache_lock);
+
+ return 0;
+}
+
+static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
+ int n, int pci_bar)
+{
+ info->mem[n].addr = pci_resource_start(dev, pci_bar);
+ if (!info->mem[n].addr)
+ return -1;
+ info->mem[n].internal_addr = ioremap(pci_resource_start(dev, pci_bar),
+ pci_resource_len(dev, pci_bar));
+ if (!info->mem[n].internal_addr)
+ return -1;
+ info->mem[n].size = pci_resource_len(dev, pci_bar);
+ info->mem[n].memtype = UIO_MEM_PHYS;
+ return 0;
+}
+
+static int __devinit sercos3_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ struct uio_info *info;
+ struct sercos3_priv *priv;
+ int i;
+
+ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ priv = kzalloc(sizeof(struct sercos3_priv), GFP_KERNEL);
+ if (!priv)
+ goto out_free;
+
+ if (pci_enable_device(dev))
+ goto out_free_priv;
+
+ if (pci_request_regions(dev, "sercos3"))
+ goto out_disable;
+
+ /* we only need PCI BAR's 0, 2, 3, 4, 5 */
+ if (sercos3_setup_iomem(dev, info, 0, 0))
+ goto out_unmap;
+ if (sercos3_setup_iomem(dev, info, 1, 2))
+ goto out_unmap;
+ if (sercos3_setup_iomem(dev, info, 2, 3))
+ goto out_unmap;
+ if (sercos3_setup_iomem(dev, info, 3, 4))
+ goto out_unmap;
+ if (sercos3_setup_iomem(dev, info, 4, 5))
+ goto out_unmap;
+
+ spin_lock_init(&priv->ier0_cache_lock);
+ info->priv = priv;
+ info->name = "Sercos_III_PCI";
+ info->version = "0.0.1";
+ info->irq = dev->irq;
+ info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
+ info->handler = sercos3_handler;
+ info->irqcontrol = sercos3_irqcontrol;
+
+ pci_set_drvdata(dev, info);
+
+ if (uio_register_device(&dev->dev, info))
+ goto out_unmap;
+
+ return 0;
+
+out_unmap:
+ for (i = 0; i < 5; i++) {
+ if (info->mem[i].internal_addr)
+ iounmap(info->mem[i].internal_addr);
+ }
+ pci_release_regions(dev);
+out_disable:
+ pci_disable_device(dev);
+out_free_priv:
+ kfree(priv);
+out_free:
+ kfree(info);
+ return -ENODEV;
+}
+
+static void sercos3_pci_remove(struct pci_dev *dev)
+{
+ struct uio_info *info = pci_get_drvdata(dev);
+ int i;
+
+ uio_unregister_device(info);
+ pci_release_regions(dev);
+ pci_disable_device(dev);
+ pci_set_drvdata(dev, NULL);
+ for (i = 0; i < 5; i++) {
+ if (info->mem[i].internal_addr)
+ iounmap(info->mem[i].internal_addr);
+ }
+ kfree(info->priv);
+ kfree(info);
+}
+
+static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = SERCOS_SUB_VENDOR_ID,
+ .subdevice = SERCOS_SUB_SYSID_3530,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = SERCOS_SUB_VENDOR_ID,
+ .subdevice = SERCOS_SUB_SYSID_3535,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = SERCOS_SUB_VENDOR_ID,
+ .subdevice = SERCOS_SUB_SYSID_3780,
+ },
+ { 0, }
+};
+
+static struct pci_driver sercos3_pci_driver = {
+ .name = "sercos3",
+ .id_table = sercos3_pci_ids,
+ .probe = sercos3_pci_probe,
+ .remove = sercos3_pci_remove,
+};
+
+static int __init sercos3_init_module(void)
+{
+ return pci_register_driver(&sercos3_pci_driver);
+}
+
+static void __exit sercos3_exit_module(void)
+{
+ pci_unregister_driver(&sercos3_pci_driver);
+}
+
+module_init(sercos3_init_module);
+module_exit(sercos3_exit_module);
+
+MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card");
+MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 07228721caf..06dd114910d 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -344,7 +344,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
__func__, sarb->len, vcc);
/* discard cells already received */
skb_trim(sarb, 0);
- UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
+ UDSL_ASSERT(instance, sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
}
memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
@@ -432,7 +432,7 @@ static void usbatm_extract_cells(struct usbatm_data *instance,
unsigned char *cell_buf = instance->cell_buf;
unsigned int space_left = stride - buf_usage;
- UDSL_ASSERT(buf_usage <= stride);
+ UDSL_ASSERT(instance, buf_usage <= stride);
if (avail_data >= space_left) {
/* add new data and process cell */
@@ -475,7 +475,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
unsigned int stride = instance->tx_channel.stride;
vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
- UDSL_ASSERT(!(avail_space % stride));
+ UDSL_ASSERT(instance, !(avail_space % stride));
for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
bytes_written += stride, target += stride) {
@@ -547,7 +547,7 @@ static void usbatm_rx_process(unsigned long data)
if (!urb->iso_frame_desc[i].status) {
unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
- UDSL_ASSERT(actual_length <= packet_size);
+ UDSL_ASSERT(instance, actual_length <= packet_size);
if (!merge_length)
merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
@@ -640,14 +640,13 @@ static void usbatm_cancel_send(struct usbatm_data *instance,
atm_dbg(instance, "%s entered\n", __func__);
spin_lock_irq(&instance->sndqueue.lock);
- for (skb = instance->sndqueue.next, n = skb->next;
- skb != (struct sk_buff *)&instance->sndqueue;
- skb = n, n = skb->next)
+ skb_queue_walk_safe(&instance->sndqueue, skb, n) {
if (UDSL_SKB(skb)->atm.vcc == vcc) {
atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb);
__skb_unlink(skb, &instance->sndqueue);
usbatm_pop(vcc, skb);
}
+ }
spin_unlock_irq(&instance->sndqueue.lock);
tasklet_disable(&instance->tx_channel.tasklet);
@@ -1189,7 +1188,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
struct urb *urb;
unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
- UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
+ UDSL_ASSERT(instance, !usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
if (!urb) {
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index e6887c6cf3c..f6f4508a9d4 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -40,9 +40,15 @@
*/
#ifdef DEBUG
-#define UDSL_ASSERT(x) BUG_ON(!(x))
+#define UDSL_ASSERT(instance, x) BUG_ON(!(x))
#else
-#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '%s' at line %d", __stringify(x), __LINE__); } while(0)
+#define UDSL_ASSERT(instance, x) \
+ do { \
+ if (!(x)) \
+ dev_warn(&(instance)->usb_intf->dev, \
+ "failed assertion '%s' at line %d", \
+ __stringify(x), __LINE__); \
+ } while(0)
#endif
#define usb_err(instance, format, arg...) \
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 8472543eee8..17d167bbd2d 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -193,7 +193,7 @@ static int __init xusbatm_init(void)
num_vendor != num_product ||
num_vendor != num_rx_endpoint ||
num_vendor != num_tx_endpoint) {
- warn("malformed module parameters");
+ printk(KERN_WARNING "xusbatm: malformed module parameters\n");
return -EINVAL;
}
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 66f17ed88cb..2519e320098 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -40,3 +40,13 @@ config USB_WDM
To compile this driver as a module, choose M here: the
module will be called cdc-wdm.
+config USB_TMC
+ tristate "USB Test and Measurement Class support"
+ depends on USB
+ help
+ Say Y here if you want to connect a USB device that follows
+ the USB.org specification for USB Test and Measurement devices
+ to your computer's USB port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbtmc.
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index 535d59a3060..32e85277b5c 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_PRINTER) += usblp.o
obj-$(CONFIG_USB_WDM) += cdc-wdm.o
+obj-$(CONFIG_USB_TMC) += usbtmc.o
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index c257453fa9d..fab23ee8702 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -326,8 +326,8 @@ exit:
usb_mark_last_busy(acm->dev);
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with "
+ "result %d", __func__, retval);
}
/* data interface returns incoming bytes, or we got unthrottled */
@@ -514,7 +514,7 @@ static void acm_waker(struct work_struct *waker)
rv = usb_autopm_get_interface(acm->control);
if (rv < 0) {
- err("Autopm failure in %s", __func__);
+ dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
return;
}
if (acm->delayed_wb) {
@@ -924,7 +924,7 @@ static int acm_probe (struct usb_interface *intf,
/* normal probing*/
if (!buffer) {
- err("Weird descriptor references\n");
+ dev_err(&intf->dev, "Weird descriptor references\n");
return -EINVAL;
}
@@ -934,21 +934,24 @@ static int acm_probe (struct usb_interface *intf,
buflen = intf->cur_altsetting->endpoint->extralen;
buffer = intf->cur_altsetting->endpoint->extra;
} else {
- err("Zero length descriptor references\n");
+ dev_err(&intf->dev,
+ "Zero length descriptor references\n");
return -EINVAL;
}
}
while (buflen > 0) {
if (buffer [1] != USB_DT_CS_INTERFACE) {
- err("skipping garbage\n");
+ dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
switch (buffer [2]) {
case USB_CDC_UNION_TYPE: /* we've found it */
if (union_header) {
- err("More than one union descriptor, skipping ...");
+ dev_err(&intf->dev, "More than one "
+ "union descriptor, "
+ "skipping ...\n");
goto next_desc;
}
union_header = (struct usb_cdc_union_desc *)
@@ -966,7 +969,9 @@ static int acm_probe (struct usb_interface *intf,
call_management_function = buffer[3];
call_interface_num = buffer[4];
if ((call_management_function & 3) != 3)
- err("This device cannot do calls on its own. It is no modem.");
+ dev_err(&intf->dev, "This device "
+ "cannot do calls on its own. "
+ "It is no modem.\n");
break;
default:
/* there are LOTS more CDC descriptors that
@@ -1051,7 +1056,7 @@ skip_normal_probe:
for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
if (minor == ACM_TTY_MINORS) {
- err("no more free acm devices");
+ dev_err(&intf->dev, "no more free acm devices\n");
return -ENODEV;
}
@@ -1454,7 +1459,8 @@ static int __init acm_init(void)
return retval;
}
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 7e8e1235e4e..7429f70b9d0 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -132,10 +132,12 @@ static void wdm_in_callback(struct urb *urb)
"nonzero urb status received: -ESHUTDOWN");
break;
case -EPIPE:
- err("nonzero urb status received: -EPIPE");
+ dev_err(&desc->intf->dev,
+ "nonzero urb status received: -EPIPE\n");
break;
default:
- err("Unexpected error %d", status);
+ dev_err(&desc->intf->dev,
+ "Unexpected error %d\n", status);
break;
}
}
@@ -170,16 +172,18 @@ static void wdm_int_callback(struct urb *urb)
return; /* unplug */
case -EPIPE:
set_bit(WDM_INT_STALL, &desc->flags);
- err("Stall on int endpoint");
+ dev_err(&desc->intf->dev, "Stall on int endpoint\n");
goto sw; /* halt is cleared in work */
default:
- err("nonzero urb status received: %d", status);
+ dev_err(&desc->intf->dev,
+ "nonzero urb status received: %d\n", status);
break;
}
}
if (urb->actual_length < sizeof(struct usb_cdc_notification)) {
- err("wdm_int_callback - %d bytes", urb->actual_length);
+ dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n",
+ urb->actual_length);
goto exit;
}
@@ -198,7 +202,8 @@ static void wdm_int_callback(struct urb *urb)
goto exit;
default:
clear_bit(WDM_POLL_RUNNING, &desc->flags);
- err("unknown notification %d received: index %d len %d",
+ dev_err(&desc->intf->dev,
+ "unknown notification %d received: index %d len %d\n",
dr->bNotificationType, dr->wIndex, dr->wLength);
goto exit;
}
@@ -236,14 +241,16 @@ static void wdm_int_callback(struct urb *urb)
sw:
rv = schedule_work(&desc->rxwork);
if (rv)
- err("Cannot schedule work");
+ dev_err(&desc->intf->dev,
+ "Cannot schedule work\n");
}
}
exit:
rv = usb_submit_urb(urb, GFP_ATOMIC);
if (rv)
- err("%s - usb_submit_urb failed with result %d",
- __func__, rv);
+ dev_err(&desc->intf->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, rv);
}
@@ -353,7 +360,7 @@ static ssize_t wdm_write
if (rv < 0) {
kfree(buf);
clear_bit(WDM_IN_USE, &desc->flags);
- err("Tx URB error: %d", rv);
+ dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
} else {
dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
req->wIndex);
@@ -401,7 +408,8 @@ retry:
int t = desc->rerr;
desc->rerr = 0;
spin_unlock_irq(&desc->iuspin);
- err("reading had resulted in %d", t);
+ dev_err(&desc->intf->dev,
+ "reading had resulted in %d\n", t);
rv = -EIO;
goto err;
}
@@ -440,7 +448,7 @@ retry:
err:
mutex_unlock(&desc->rlock);
if (rv < 0)
- err("wdm_read: exit error");
+ dev_err(&desc->intf->dev, "wdm_read: exit error\n");
return rv;
}
@@ -450,7 +458,8 @@ static int wdm_flush(struct file *file, fl_owner_t id)
wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
if (desc->werr < 0)
- err("Error in flush path: %d", desc->werr);
+ dev_err(&desc->intf->dev, "Error in flush path: %d\n",
+ desc->werr);
return desc->werr;
}
@@ -502,7 +511,7 @@ static int wdm_open(struct inode *inode, struct file *file)
rv = usb_autopm_get_interface(desc->intf);
if (rv < 0) {
- err("Error autopm - %d", rv);
+ dev_err(&desc->intf->dev, "Error autopm - %d\n", rv);
goto out;
}
intf->needs_remote_wakeup = 1;
@@ -512,7 +521,8 @@ static int wdm_open(struct inode *inode, struct file *file)
rv = usb_submit_urb(desc->validity, GFP_KERNEL);
if (rv < 0) {
desc->count--;
- err("Error submitting int urb - %d", rv);
+ dev_err(&desc->intf->dev,
+ "Error submitting int urb - %d\n", rv);
}
} else {
rv = 0;
@@ -600,7 +610,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
while (buflen > 0) {
if (buffer [1] != USB_DT_CS_INTERFACE) {
- err("skipping garbage");
+ dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
@@ -614,7 +624,8 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
"Finding maximum buffer length: %d", maxcom);
break;
default:
- err("Ignoring extra header, type %d, length %d",
+ dev_err(&intf->dev,
+ "Ignoring extra header, type %d, length %d\n",
buffer[2], buffer[0]);
break;
}
@@ -772,7 +783,8 @@ static int recover_from_urb_loss(struct wdm_device *desc)
if (desc->count) {
rv = usb_submit_urb(desc->validity, GFP_NOIO);
if (rv < 0)
- err("Error resume submitting int urb - %d", rv);
+ dev_err(&desc->intf->dev,
+ "Error resume submitting int urb - %d\n", rv);
}
return rv;
}
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 0647164d36d..b5775af3ba2 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -593,8 +593,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
err = usblp_hp_channel_change_request(usblp,
arg, &newChannel);
if (err < 0) {
- err("usblp%d: error = %d setting "
- "HP channel",
+ dev_err(&usblp->dev->dev,
+ "usblp%d: error = %d setting "
+ "HP channel\n",
usblp->minor, err);
retval = -EIO;
goto done;
@@ -1076,15 +1077,16 @@ static int usblp_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev (intf);
- struct usblp *usblp = NULL;
+ struct usblp *usblp;
int protocol;
int retval;
/* Malloc and start initializing usblp structure so we can use it
* directly. */
- if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
+ usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL);
+ if (!usblp) {
retval = -ENOMEM;
- goto abort;
+ goto abort_ret;
}
usblp->dev = dev;
mutex_init(&usblp->wmut);
@@ -1179,12 +1181,11 @@ abort_intfdata:
usb_set_intfdata (intf, NULL);
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
abort:
- if (usblp) {
- kfree(usblp->readbuf);
- kfree(usblp->statusbuf);
- kfree(usblp->device_id_string);
- kfree(usblp);
- }
+ kfree(usblp->readbuf);
+ kfree(usblp->statusbuf);
+ kfree(usblp->device_id_string);
+ kfree(usblp);
+abort_ret:
return retval;
}
@@ -1345,7 +1346,7 @@ static void usblp_disconnect(struct usb_interface *intf)
usb_deregister_dev(intf, &usblp_class);
if (!usblp || !usblp->dev) {
- err("bogus disconnect");
+ dev_err(&intf->dev, "bogus disconnect\n");
BUG ();
}
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
new file mode 100644
index 00000000000..543811f6e6e
--- /dev/null
+++ b/drivers/usb/class/usbtmc.c
@@ -0,0 +1,1087 @@
+/**
+ * drivers/usb/class/usbtmc.c - USB Test & Measurment class driver
+ *
+ * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * The GNU General Public License is available at
+ * http://www.gnu.org/copyleft/gpl.html.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/usb/tmc.h>
+
+
+#define USBTMC_MINOR_BASE 176
+
+/*
+ * Size of driver internal IO buffer. Must be multiple of 4 and at least as
+ * large as wMaxPacketSize (which is usually 512 bytes).
+ */
+#define USBTMC_SIZE_IOBUFFER 2048
+
+/* Default USB timeout (in milliseconds) */
+#define USBTMC_TIMEOUT 10
+
+/*
+ * Maximum number of read cycles to empty bulk in endpoint during CLEAR and
+ * ABORT_BULK_IN requests. Ends the loop if (for whatever reason) a short
+ * packet is never read.
+ */
+#define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100
+
+static struct usb_device_id usbtmc_devices[] = {
+ { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), },
+ { 0, } /* terminating entry */
+};
+
+/*
+ * This structure is the capabilities for the device
+ * See section 4.2.1.8 of the USBTMC specification for details.
+ */
+struct usbtmc_dev_capabilities {
+ __u8 interface_capabilities;
+ __u8 device_capabilities;
+ __u8 usb488_interface_capabilities;
+ __u8 usb488_device_capabilities;
+};
+
+/* This structure holds private data for each USBTMC device. One copy is
+ * allocated for each USBTMC device in the driver's probe function.
+ */
+struct usbtmc_device_data {
+ const struct usb_device_id *id;
+ struct usb_device *usb_dev;
+ struct usb_interface *intf;
+
+ unsigned int bulk_in;
+ unsigned int bulk_out;
+
+ u8 bTag;
+ u8 bTag_last_write; /* needed for abort */
+ u8 bTag_last_read; /* needed for abort */
+
+ /* attributes from the USB TMC spec for this device */
+ u8 TermChar;
+ bool TermCharEnabled;
+ bool auto_abort;
+
+ struct usbtmc_dev_capabilities capabilities;
+ struct kref kref;
+ struct mutex io_mutex; /* only one i/o function running at a time */
+};
+#define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref)
+
+/* Forward declarations */
+static struct usb_driver usbtmc_driver;
+
+static void usbtmc_delete(struct kref *kref)
+{
+ struct usbtmc_device_data *data = to_usbtmc_data(kref);
+
+ usb_put_dev(data->usb_dev);
+ kfree(data);
+}
+
+static int usbtmc_open(struct inode *inode, struct file *filp)
+{
+ struct usb_interface *intf;
+ struct usbtmc_device_data *data;
+ int retval = -ENODEV;
+
+ intf = usb_find_interface(&usbtmc_driver, iminor(inode));
+ if (!intf) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": can not find device for minor %d", iminor(inode));
+ goto exit;
+ }
+
+ data = usb_get_intfdata(intf);
+ kref_get(&data->kref);
+
+ /* Store pointer in file structure's private data field */
+ filp->private_data = data;
+
+exit:
+ return retval;
+}
+
+static int usbtmc_release(struct inode *inode, struct file *file)
+{
+ struct usbtmc_device_data *data = file->private_data;
+
+ kref_put(&data->kref, usbtmc_delete);
+ return 0;
+}
+
+static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
+{
+ char *buffer;
+ struct device *dev;
+ int rv;
+ int n;
+ int actual;
+ struct usb_host_interface *current_setting;
+ int max_size;
+
+ dev = &data->intf->dev;
+ buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
+ data->bTag_last_read, data->bulk_in,
+ buffer, 2, USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
+
+ if (buffer[0] == USBTMC_STATUS_FAILED) {
+ rv = 0;
+ goto exit;
+ }
+
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
+ buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ max_size = 0;
+ current_setting = data->intf->cur_altsetting;
+ for (n = 0; n < current_setting->desc.bNumEndpoints; n++)
+ if (current_setting->endpoint[n].desc.bEndpointAddress ==
+ data->bulk_in)
+ max_size = le16_to_cpu(current_setting->endpoint[n].
+ desc.wMaxPacketSize);
+
+ if (max_size == 0) {
+ dev_err(dev, "Couldn't get wMaxPacketSize\n");
+ rv = -EPERM;
+ goto exit;
+ }
+
+ dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size);
+
+ n = 0;
+
+ do {
+ dev_dbg(dev, "Reading from bulk in EP\n");
+
+ rv = usb_bulk_msg(data->usb_dev,
+ usb_rcvbulkpipe(data->usb_dev,
+ data->bulk_in),
+ buffer, USBTMC_SIZE_IOBUFFER,
+ &actual, USBTMC_TIMEOUT);
+
+ n++;
+
+ if (rv < 0) {
+ dev_err(dev, "usb_bulk_msg returned %d\n", rv);
+ goto exit;
+ }
+ } while ((actual == max_size) &&
+ (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
+
+ if (actual == max_size) {
+ dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
+ USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ n = 0;
+
+usbtmc_abort_bulk_in_status:
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
+ 0, data->bulk_in, buffer, 0x08,
+ USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
+
+ if (buffer[0] == USBTMC_STATUS_SUCCESS) {
+ rv = 0;
+ goto exit;
+ }
+
+ if (buffer[0] != USBTMC_STATUS_PENDING) {
+ dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ if (buffer[1] == 1)
+ do {
+ dev_dbg(dev, "Reading from bulk in EP\n");
+
+ rv = usb_bulk_msg(data->usb_dev,
+ usb_rcvbulkpipe(data->usb_dev,
+ data->bulk_in),
+ buffer, USBTMC_SIZE_IOBUFFER,
+ &actual, USBTMC_TIMEOUT);
+
+ n++;
+
+ if (rv < 0) {
+ dev_err(dev, "usb_bulk_msg returned %d\n", rv);
+ goto exit;
+ }
+ } while ((actual = max_size) &&
+ (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
+
+ if (actual == max_size) {
+ dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
+ USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ goto usbtmc_abort_bulk_in_status;
+
+exit:
+ kfree(buffer);
+ return rv;
+
+}
+
+static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
+{
+ struct device *dev;
+ u8 *buffer;
+ int rv;
+ int n;
+
+ dev = &data->intf->dev;
+
+ buffer = kmalloc(8, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
+ data->bTag_last_write, data->bulk_out,
+ buffer, 2, USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "INITIATE_ABORT_BULK_OUT returned %x\n", buffer[0]);
+
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "INITIATE_ABORT_BULK_OUT returned %x\n",
+ buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ n = 0;
+
+usbtmc_abort_bulk_out_check_status:
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
+ 0, data->bulk_out, buffer, 0x08,
+ USBTMC_TIMEOUT);
+ n++;
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "CHECK_ABORT_BULK_OUT returned %x\n", buffer[0]);
+
+ if (buffer[0] == USBTMC_STATUS_SUCCESS)
+ goto usbtmc_abort_bulk_out_clear_halt;
+
+ if ((buffer[0] == USBTMC_STATUS_PENDING) &&
+ (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN))
+ goto usbtmc_abort_bulk_out_check_status;
+
+ rv = -EPERM;
+ goto exit;
+
+usbtmc_abort_bulk_out_clear_halt:
+ rv = usb_control_msg(data->usb_dev,
+ usb_sndctrlpipe(data->usb_dev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_ENDPOINT,
+ USB_ENDPOINT_HALT, data->bulk_out, buffer,
+ 0, USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+ rv = 0;
+
+exit:
+ kfree(buffer);
+ return rv;
+}
+
+static ssize_t usbtmc_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct usbtmc_device_data *data;
+ struct device *dev;
+ unsigned long int n_characters;
+ u8 *buffer;
+ int actual;
+ int done;
+ int remaining;
+ int retval;
+ int this_part;
+
+ /* Get pointer to private data structure */
+ data = filp->private_data;
+ dev = &data->intf->dev;
+
+ buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ mutex_lock(&data->io_mutex);
+
+ remaining = count;
+ done = 0;
+
+ while (remaining > 0) {
+ if (remaining > USBTMC_SIZE_IOBUFFER - 12 - 3)
+ this_part = USBTMC_SIZE_IOBUFFER - 12 - 3;
+ else
+ this_part = remaining;
+
+ /* Setup IO buffer for DEV_DEP_MSG_IN message
+ * Refer to class specs for details
+ */
+ buffer[0] = 2;
+ buffer[1] = data->bTag;
+ buffer[2] = ~(data->bTag);
+ buffer[3] = 0; /* Reserved */
+ buffer[4] = (this_part - 12 - 3) & 255;
+ buffer[5] = ((this_part - 12 - 3) >> 8) & 255;
+ buffer[6] = ((this_part - 12 - 3) >> 16) & 255;
+ buffer[7] = ((this_part - 12 - 3) >> 24) & 255;
+ buffer[8] = data->TermCharEnabled * 2;
+ /* Use term character? */
+ buffer[9] = data->TermChar;
+ buffer[10] = 0; /* Reserved */
+ buffer[11] = 0; /* Reserved */
+
+ /* Send bulk URB */
+ retval = usb_bulk_msg(data->usb_dev,
+ usb_sndbulkpipe(data->usb_dev,
+ data->bulk_out),
+ buffer, 12, &actual, USBTMC_TIMEOUT);
+
+ /* Store bTag (in case we need to abort) */
+ data->bTag_last_write = data->bTag;
+
+ /* Increment bTag -- and increment again if zero */
+ data->bTag++;
+ if (!data->bTag)
+ (data->bTag)++;
+
+ if (retval < 0) {
+ dev_err(dev, "usb_bulk_msg returned %d\n", retval);
+ if (data->auto_abort)
+ usbtmc_ioctl_abort_bulk_out(data);
+ goto exit;
+ }
+
+ /* Send bulk URB */
+ retval = usb_bulk_msg(data->usb_dev,
+ usb_rcvbulkpipe(data->usb_dev,
+ data->bulk_in),
+ buffer, USBTMC_SIZE_IOBUFFER, &actual,
+ USBTMC_TIMEOUT);
+
+ /* Store bTag (in case we need to abort) */
+ data->bTag_last_read = data->bTag;
+
+ if (retval < 0) {
+ dev_err(dev, "Unable to read data, error %d\n", retval);
+ if (data->auto_abort)
+ usbtmc_ioctl_abort_bulk_in(data);
+ goto exit;
+ }
+
+ /* How many characters did the instrument send? */
+ n_characters = buffer[4] +
+ (buffer[5] << 8) +
+ (buffer[6] << 16) +
+ (buffer[7] << 24);
+
+ /* Copy buffer to user space */
+ if (copy_to_user(buf + done, &buffer[12], n_characters)) {
+ /* There must have been an addressing problem */
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ done += n_characters;
+ if (n_characters < USBTMC_SIZE_IOBUFFER)
+ remaining = 0;
+ }
+
+ /* Update file position value */
+ *f_pos = *f_pos + done;
+ retval = done;
+
+exit:
+ mutex_unlock(&data->io_mutex);
+ kfree(buffer);
+ return retval;
+}
+
+static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct usbtmc_device_data *data;
+ u8 *buffer;
+ int retval;
+ int actual;
+ unsigned long int n_bytes;
+ int n;
+ int remaining;
+ int done;
+ int this_part;
+
+ data = filp->private_data;
+
+ buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ mutex_lock(&data->io_mutex);
+
+ remaining = count;
+ done = 0;
+
+ while (remaining > 0) {
+ if (remaining > USBTMC_SIZE_IOBUFFER - 12) {
+ this_part = USBTMC_SIZE_IOBUFFER - 12;
+ buffer[8] = 0;
+ } else {
+ this_part = remaining;
+ buffer[8] = 1;
+ }
+
+ /* Setup IO buffer for DEV_DEP_MSG_OUT message */
+ buffer[0] = 1;
+ buffer[1] = data->bTag;
+ buffer[2] = ~(data->bTag);
+ buffer[3] = 0; /* Reserved */
+ buffer[4] = this_part & 255;
+ buffer[5] = (this_part >> 8) & 255;
+ buffer[6] = (this_part >> 16) & 255;
+ buffer[7] = (this_part >> 24) & 255;
+ /* buffer[8] is set above... */
+ buffer[9] = 0; /* Reserved */
+ buffer[10] = 0; /* Reserved */
+ buffer[11] = 0; /* Reserved */
+
+ if (copy_from_user(&buffer[12], buf + done, this_part)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ n_bytes = 12 + this_part;
+ if (this_part % 4)
+ n_bytes += 4 - this_part % 4;
+ for (n = 12 + this_part; n < n_bytes; n++)
+ buffer[n] = 0;
+
+ retval = usb_bulk_msg(data->usb_dev,
+ usb_sndbulkpipe(data->usb_dev,
+ data->bulk_out),
+ buffer, n_bytes, &actual, USBTMC_TIMEOUT);
+
+ data->bTag_last_write = data->bTag;
+ data->bTag++;
+
+ if (!data->bTag)
+ data->bTag++;
+
+ if (retval < 0) {
+ dev_err(&data->intf->dev,
+ "Unable to send data, error %d\n", retval);
+ if (data->auto_abort)
+ usbtmc_ioctl_abort_bulk_out(data);
+ goto exit;
+ }
+
+ remaining -= this_part;
+ done += this_part;
+ }
+
+ retval = count;
+exit:
+ mutex_unlock(&data->io_mutex);
+ kfree(buffer);
+ return retval;
+}
+
+static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
+{
+ struct usb_host_interface *current_setting;
+ struct usb_endpoint_descriptor *desc;
+ struct device *dev;
+ u8 *buffer;
+ int rv;
+ int n;
+ int actual;
+ int max_size;
+
+ dev = &data->intf->dev;
+
+ dev_dbg(dev, "Sending INITIATE_CLEAR request\n");
+
+ buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_INITIATE_CLEAR,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, 0, buffer, 1, USBTMC_TIMEOUT);
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "INITIATE_CLEAR returned %x\n", buffer[0]);
+
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "INITIATE_CLEAR returned %x\n", buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ max_size = 0;
+ current_setting = data->intf->cur_altsetting;
+ for (n = 0; n < current_setting->desc.bNumEndpoints; n++) {
+ desc = &current_setting->endpoint[n].desc;
+ if (desc->bEndpointAddress == data->bulk_in)
+ max_size = le16_to_cpu(desc->wMaxPacketSize);
+ }
+
+ if (max_size == 0) {
+ dev_err(dev, "Couldn't get wMaxPacketSize\n");
+ rv = -EPERM;
+ goto exit;
+ }
+
+ dev_dbg(dev, "wMaxPacketSize is %d\n", max_size);
+
+ n = 0;
+
+usbtmc_clear_check_status:
+
+ dev_dbg(dev, "Sending CHECK_CLEAR_STATUS request\n");
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_CHECK_CLEAR_STATUS,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, 0, buffer, 2, USBTMC_TIMEOUT);
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]);
+
+ if (buffer[0] == USBTMC_STATUS_SUCCESS)
+ goto usbtmc_clear_bulk_out_halt;
+
+ if (buffer[0] != USBTMC_STATUS_PENDING) {
+ dev_err(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ if (buffer[1] == 1)
+ do {
+ dev_dbg(dev, "Reading from bulk in EP\n");
+
+ rv = usb_bulk_msg(data->usb_dev,
+ usb_rcvbulkpipe(data->usb_dev,
+ data->bulk_in),
+ buffer, USBTMC_SIZE_IOBUFFER,
+ &actual, USBTMC_TIMEOUT);
+ n++;
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n",
+ rv);
+ goto exit;
+ }
+ } while ((actual == max_size) &&
+ (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
+
+ if (actual == max_size) {
+ dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
+ USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
+ rv = -EPERM;
+ goto exit;
+ }
+
+ goto usbtmc_clear_check_status;
+
+usbtmc_clear_bulk_out_halt:
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_sndctrlpipe(data->usb_dev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_ENDPOINT,
+ USB_ENDPOINT_HALT,
+ data->bulk_out, buffer, 0,
+ USBTMC_TIMEOUT);
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+ rv = 0;
+
+exit:
+ kfree(buffer);
+ return rv;
+}
+
+static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data)
+{
+ u8 *buffer;
+ int rv;
+
+ buffer = kmalloc(2, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_sndctrlpipe(data->usb_dev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_ENDPOINT,
+ USB_ENDPOINT_HALT, data->bulk_out,
+ buffer, 0, USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
+ rv);
+ goto exit;
+ }
+ rv = 0;
+
+exit:
+ kfree(buffer);
+ return rv;
+}
+
+static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)
+{
+ u8 *buffer;
+ int rv;
+
+ buffer = kmalloc(2, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev, usb_sndctrlpipe(data->usb_dev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_ENDPOINT,
+ USB_ENDPOINT_HALT, data->bulk_in, buffer, 0,
+ USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
+ rv);
+ goto exit;
+ }
+ rv = 0;
+
+exit:
+ kfree(buffer);
+ return rv;
+}
+
+static int get_capabilities(struct usbtmc_device_data *data)
+{
+ struct device *dev = &data->usb_dev->dev;
+ char *buffer;
+ int rv;
+
+ buffer = kmalloc(0x18, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_GET_CAPABILITIES,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, 0, buffer, 0x18, USBTMC_TIMEOUT);
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ return rv;
+ }
+
+ dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
+ dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]);
+ dev_dbg(dev, "Device capabilities are %x\n", buffer[5]);
+ dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]);
+ dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
+ return -EPERM;
+ }
+
+ data->capabilities.interface_capabilities = buffer[4];
+ data->capabilities.device_capabilities = buffer[5];
+ data->capabilities.usb488_interface_capabilities = buffer[14];
+ data->capabilities.usb488_device_capabilities = buffer[15];
+
+ kfree(buffer);
+ return 0;
+}
+
+#define capability_attribute(name) \
+static ssize_t show_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usbtmc_device_data *data = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", data->capabilities.name); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+capability_attribute(interface_capabilities);
+capability_attribute(device_capabilities);
+capability_attribute(usb488_interface_capabilities);
+capability_attribute(usb488_device_capabilities);
+
+static struct attribute *capability_attrs[] = {
+ &dev_attr_interface_capabilities.attr,
+ &dev_attr_device_capabilities.attr,
+ &dev_attr_usb488_interface_capabilities.attr,
+ &dev_attr_usb488_device_capabilities.attr,
+ NULL,
+};
+
+static struct attribute_group capability_attr_grp = {
+ .attrs = capability_attrs,
+};
+
+static ssize_t show_TermChar(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usbtmc_device_data *data = usb_get_intfdata(intf);
+
+ return sprintf(buf, "%c\n", data->TermChar);
+}
+
+static ssize_t store_TermChar(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usbtmc_device_data *data = usb_get_intfdata(intf);
+
+ if (count < 1)
+ return -EINVAL;
+ data->TermChar = buf[0];
+ return count;
+}
+static DEVICE_ATTR(TermChar, S_IRUGO, show_TermChar, store_TermChar);
+
+#define data_attribute(name) \
+static ssize_t show_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usbtmc_device_data *data = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", data->name); \
+} \
+static ssize_t store_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usbtmc_device_data *data = usb_get_intfdata(intf); \
+ ssize_t result; \
+ unsigned val; \
+ \
+ result = sscanf(buf, "%u\n", &val); \
+ if (result != 1) \
+ result = -EINVAL; \
+ data->name = val; \
+ if (result < 0) \
+ return result; \
+ else \
+ return count; \
+} \
+static DEVICE_ATTR(name, S_IRUGO, show_##name, store_##name)
+
+data_attribute(TermCharEnabled);
+data_attribute(auto_abort);
+
+static struct attribute *data_attrs[] = {
+ &dev_attr_TermChar.attr,
+ &dev_attr_TermCharEnabled.attr,
+ &dev_attr_auto_abort.attr,
+ NULL,
+};
+
+static struct attribute_group data_attr_grp = {
+ .attrs = data_attrs,
+};
+
+static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data)
+{
+ struct device *dev;
+ u8 *buffer;
+ int rv;
+
+ dev = &data->intf->dev;
+
+ buffer = kmalloc(2, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ USBTMC_REQUEST_INDICATOR_PULSE,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, 0, buffer, 0x01, USBTMC_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "usb_control_msg returned %d\n", rv);
+ goto exit;
+ }
+
+ dev_dbg(dev, "INDICATOR_PULSE returned %x\n", buffer[0]);
+
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "INDICATOR_PULSE returned %x\n", buffer[0]);
+ rv = -EPERM;
+ goto exit;
+ }
+ rv = 0;
+
+exit:
+ kfree(buffer);
+ return rv;
+}
+
+static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct usbtmc_device_data *data;
+ int retval = -EBADRQC;
+
+ data = file->private_data;
+ mutex_lock(&data->io_mutex);
+
+ switch (cmd) {
+ case USBTMC_IOCTL_CLEAR_OUT_HALT:
+ retval = usbtmc_ioctl_clear_out_halt(data);
+
+ case USBTMC_IOCTL_CLEAR_IN_HALT:
+ retval = usbtmc_ioctl_clear_in_halt(data);
+
+ case USBTMC_IOCTL_INDICATOR_PULSE:
+ retval = usbtmc_ioctl_indicator_pulse(data);
+
+ case USBTMC_IOCTL_CLEAR:
+ retval = usbtmc_ioctl_clear(data);
+
+ case USBTMC_IOCTL_ABORT_BULK_OUT:
+ retval = usbtmc_ioctl_abort_bulk_out(data);
+
+ case USBTMC_IOCTL_ABORT_BULK_IN:
+ retval = usbtmc_ioctl_abort_bulk_in(data);
+ }
+
+ mutex_unlock(&data->io_mutex);
+ return retval;
+}
+
+static struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .read = usbtmc_read,
+ .write = usbtmc_write,
+ .open = usbtmc_open,
+ .release = usbtmc_release,
+ .unlocked_ioctl = usbtmc_ioctl,
+};
+
+static struct usb_class_driver usbtmc_class = {
+ .name = "usbtmc%d",
+ .fops = &fops,
+ .minor_base = USBTMC_MINOR_BASE,
+};
+
+
+static int usbtmc_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usbtmc_device_data *data;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int n;
+ int retcode;
+
+ dev_dbg(&intf->dev, "%s called\n", __func__);
+
+ data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&intf->dev, "Unable to allocate kernel memory\n");
+ return -ENOMEM;
+ }
+
+ data->intf = intf;
+ data->id = id;
+ data->usb_dev = usb_get_dev(interface_to_usbdev(intf));
+ usb_set_intfdata(intf, data);
+ kref_init(&data->kref);
+ mutex_init(&data->io_mutex);
+
+ /* Initialize USBTMC bTag and other fields */
+ data->bTag = 1;
+ data->TermCharEnabled = 0;
+ data->TermChar = '\n';
+
+ /* USBTMC devices have only one setting, so use that */
+ iface_desc = data->intf->cur_altsetting;
+
+ /* Find bulk in endpoint */
+ for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) {
+ endpoint = &iface_desc->endpoint[n].desc;
+
+ if (usb_endpoint_is_bulk_in(endpoint)) {
+ data->bulk_in = endpoint->bEndpointAddress;
+ dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n",
+ data->bulk_in);
+ break;
+ }
+ }
+
+ /* Find bulk out endpoint */
+ for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) {
+ endpoint = &iface_desc->endpoint[n].desc;
+
+ if (usb_endpoint_is_bulk_out(endpoint)) {
+ data->bulk_out = endpoint->bEndpointAddress;
+ dev_dbg(&intf->dev, "Found Bulk out endpoint at %u\n",
+ data->bulk_out);
+ break;
+ }
+ }
+
+ retcode = get_capabilities(data);
+ if (retcode)
+ dev_err(&intf->dev, "can't read capabilities\n");
+ else
+ retcode = sysfs_create_group(&intf->dev.kobj,
+ &capability_attr_grp);
+
+ retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp);
+
+ retcode = usb_register_dev(intf, &usbtmc_class);
+ if (retcode) {
+ dev_err(&intf->dev, "Not able to get a minor"
+ " (base %u, slice default): %d\n", USBTMC_MINOR_BASE,
+ retcode);
+ goto error_register;
+ }
+ dev_dbg(&intf->dev, "Using minor number %d\n", intf->minor);
+
+ return 0;
+
+error_register:
+ sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
+ sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
+ kref_put(&data->kref, usbtmc_delete);
+ return retcode;
+}
+
+static void usbtmc_disconnect(struct usb_interface *intf)
+{
+ struct usbtmc_device_data *data;
+
+ dev_dbg(&intf->dev, "usbtmc_disconnect called\n");
+
+ data = usb_get_intfdata(intf);
+ usb_deregister_dev(intf, &usbtmc_class);
+ sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
+ sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
+ kref_put(&data->kref, usbtmc_delete);
+}
+
+static struct usb_driver usbtmc_driver = {
+ .name = "usbtmc",
+ .id_table = usbtmc_devices,
+ .probe = usbtmc_probe,
+ .disconnect = usbtmc_disconnect
+};
+
+static int __init usbtmc_init(void)
+{
+ int retcode;
+
+ retcode = usb_register(&usbtmc_driver);
+ if (retcode)
+ printk(KERN_ERR KBUILD_MODNAME": Unable to register driver\n");
+ return retcode;
+}
+module_init(usbtmc_init);
+
+static void __exit usbtmc_exit(void)
+{
+ usb_deregister(&usbtmc_driver);
+}
+module_exit(usbtmc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index cc9f397e839..e1759d17ac5 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -134,5 +134,5 @@ config USB_OTG_BLACKLIST_HUB
If you say Y here, then Linux will refuse to enumerate
external hubs. OTG hosts are allowed to reduce hardware
and software costs by not supporting external hubs. So
- are "Emedded Hosts" that don't offer OTG support.
+ are "Embedded Hosts" that don't offer OTG support.
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 20290c5b156..2bccefebff1 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -413,7 +413,8 @@ static void driver_disconnect(struct usb_interface *intf)
if (likely(ifnum < 8*sizeof(ps->ifclaimed)))
clear_bit(ifnum, &ps->ifclaimed);
else
- warn("interface number %u out of range", ifnum);
+ dev_warn(&intf->dev, "interface number %u out of range\n",
+ ifnum);
usb_set_intfdata(intf, NULL);
@@ -624,6 +625,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
smp_wmb();
list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps;
+ snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current),
+ current->comm);
out:
if (ret) {
kfree(ps);
@@ -1729,9 +1732,9 @@ static int usb_classdev_add(struct usb_device *dev)
{
struct device *cldev;
- cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
- dev->dev.devt, NULL, "usbdev%d.%d",
- dev->bus->busnum, dev->devnum);
+ cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
+ NULL, "usbdev%d.%d", dev->bus->busnum,
+ dev->devnum);
if (IS_ERR(cldev))
return PTR_ERR(cldev);
dev->usb_classdev = cldev;
@@ -1774,19 +1777,20 @@ int __init usb_devio_init(void)
retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
"usb_device");
if (retval) {
- err("unable to register minors for usb_device");
+ printk(KERN_ERR "Unable to register minors for usb_device\n");
goto out;
}
cdev_init(&usb_device_cdev, &usbdev_file_operations);
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
if (retval) {
- err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
+ printk(KERN_ERR "Unable to get usb_device major %d\n",
+ USB_DEVICE_MAJOR);
goto error_cdev;
}
#ifdef CONFIG_USB_DEVICE_CLASS
usb_classdev_class = class_create(THIS_MODULE, "usb_device");
if (IS_ERR(usb_classdev_class)) {
- err("unable to register usb_device class");
+ printk(KERN_ERR "Unable to register usb_device class\n");
retval = PTR_ERR(usb_classdev_class);
cdev_del(&usb_device_cdev);
usb_classdev_class = NULL;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 5a7fa6f0995..e935be7eb46 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1070,7 +1070,8 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
struct usb_driver *driver;
driver = to_usb_driver(intf->dev.driver);
- if (!driver->reset_resume)
+ if (!driver->reset_resume ||
+ intf->needs_remote_wakeup)
return -EOPNOTSUPP;
}
}
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 22912136fc1..946fae43d62 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -169,7 +169,8 @@ static int usb_endpoint_major_init(void)
error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
"usb_endpoint");
if (error) {
- err("unable to get a dynamic major for usb endpoints");
+ printk(KERN_ERR "Unable to get a dynamic major for "
+ "usb endpoints.\n");
return error;
}
usb_endpoint_major = MAJOR(dev);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 6b1b229e38c..997e659ff69 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -86,7 +86,7 @@ static int init_usb_class(void)
usb_class->class = class_create(THIS_MODULE, "usb");
if (IS_ERR(usb_class->class)) {
result = IS_ERR(usb_class->class);
- err("class_create failed for usb devices");
+ printk(KERN_ERR "class_create failed for usb devices\n");
kfree(usb_class);
usb_class = NULL;
}
@@ -115,7 +115,8 @@ int usb_major_init(void)
error = register_chrdev(USB_MAJOR, "usb", &usb_fops);
if (error)
- err("unable to get major %d for usb devices", USB_MAJOR);
+ printk(KERN_ERR "Unable to get major %d for usb devices\n",
+ USB_MAJOR);
return error;
}
@@ -196,9 +197,9 @@ int usb_register_dev(struct usb_interface *intf,
++temp;
else
temp = name;
- intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
- MKDEV(USB_MAJOR, minor), NULL,
- "%s", temp);
+ intf->usb_dev = device_create(usb_class->class, &intf->dev,
+ MKDEV(USB_MAJOR, minor), NULL,
+ "%s", temp);
if (IS_ERR(intf->usb_dev)) {
down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 8abd4e59bf4..fc9018e72a0 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -81,6 +81,10 @@
/*-------------------------------------------------------------------------*/
+/* Keep track of which host controller drivers are loaded */
+unsigned long usb_hcds_loaded;
+EXPORT_SYMBOL_GPL(usb_hcds_loaded);
+
/* host controllers we manage */
LIST_HEAD (usb_bus_list);
EXPORT_SYMBOL_GPL (usb_bus_list);
@@ -818,9 +822,8 @@ static int usb_register_bus(struct usb_bus *bus)
set_bit (busnum, busmap.busmap);
bus->busnum = busnum;
- bus->dev = device_create_drvdata(usb_host_class, bus->controller,
- MKDEV(0, 0), bus,
- "usb_host%d", busnum);
+ bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
+ bus, "usb_host%d", busnum);
result = PTR_ERR(bus->dev);
if (IS_ERR(bus->dev))
goto error_create_class_dev;
@@ -1876,7 +1879,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
* with IRQF_SHARED. As usb_hcd_irq() will always disable
* interrupts we can remove it here.
*/
- irqflags &= ~IRQF_DISABLED;
+ if (irqflags & IRQF_SHARED)
+ irqflags &= ~IRQF_DISABLED;
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
hcd->driver->description, hcd->self.busnum);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index e710ce04e22..2dcde61c465 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -482,4 +482,10 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
*/
extern struct rw_semaphore ehci_cf_port_reset_rwsem;
+/* Keep track of which host controller drivers are loaded */
+#define USB_UHCI_LOADED 0
+#define USB_OHCI_LOADED 1
+#define USB_EHCI_LOADED 2
+extern unsigned long usb_hcds_loaded;
+
#endif /* __KERNEL__ */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 6a5cb018383..d73ce262c36 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -77,6 +77,7 @@ struct usb_hub {
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
struct delayed_work leds;
+ struct delayed_work init_work;
};
@@ -100,6 +101,15 @@ module_param (blinkenlights, bool, S_IRUGO);
MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");
/*
+ * Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about
+ * 10 seconds to send reply for the initial 64-byte descriptor request.
+ */
+/* define initial 64-byte descriptor request timeout in milliseconds */
+static int initial_descriptor_timeout = USB_CTRL_GET_TIMEOUT;
+module_param(initial_descriptor_timeout, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(initial_descriptor_timeout, "initial 64-byte descriptor request timeout in milliseconds (default 5000 - 5.0 seconds)");
+
+/*
* As of 2.6.10 we introduce a new USB device initialization scheme which
* closely resembles the way Windows works. Hopefully it will be compatible
* with a wider range of devices than the old scheme. However some previously
@@ -515,10 +525,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
}
EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
-static void hub_power_on(struct usb_hub *hub)
+/* If do_delay is false, return the number of milliseconds the caller
+ * needs to delay.
+ */
+static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
{
int port1;
unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
+ unsigned delay;
u16 wHubCharacteristics =
le16_to_cpu(hub->descriptor->wHubCharacteristics);
@@ -537,7 +551,10 @@ static void hub_power_on(struct usb_hub *hub)
set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
/* Wait at least 100 msec for power to become stable */
- msleep(max(pgood_delay, (unsigned) 100));
+ delay = max(pgood_delay, (unsigned) 100);
+ if (do_delay)
+ msleep(delay);
+ return delay;
}
static int hub_hub_status(struct usb_hub *hub,
@@ -599,21 +616,55 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
}
enum hub_activation_type {
- HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+ HUB_INIT, HUB_INIT2, HUB_INIT3,
+ HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
};
+static void hub_init_func2(struct work_struct *ws);
+static void hub_init_func3(struct work_struct *ws);
+
static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
{
struct usb_device *hdev = hub->hdev;
int port1;
int status;
bool need_debounce_delay = false;
+ unsigned delay;
+
+ /* Continue a partial initialization */
+ if (type == HUB_INIT2)
+ goto init2;
+ if (type == HUB_INIT3)
+ goto init3;
/* After a resume, port power should still be on.
* For any other type of activation, turn it on.
*/
- if (type != HUB_RESUME)
- hub_power_on(hub);
+ if (type != HUB_RESUME) {
+
+ /* Speed up system boot by using a delayed_work for the
+ * hub's initial power-up delays. This is pretty awkward
+ * and the implementation looks like a home-brewed sort of
+ * setjmp/longjmp, but it saves at least 100 ms for each
+ * root hub (assuming usbcore is compiled into the kernel
+ * rather than as a module). It adds up.
+ *
+ * This can't be done for HUB_RESUME or HUB_RESET_RESUME
+ * because for those activation types the ports have to be
+ * operational when we return. In theory this could be done
+ * for HUB_POST_RESET, but it's easier not to.
+ */
+ if (type == HUB_INIT) {
+ delay = hub_power_on(hub, false);
+ PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
+ schedule_delayed_work(&hub->init_work,
+ msecs_to_jiffies(delay));
+ return; /* Continues at init2: below */
+ } else {
+ hub_power_on(hub, true);
+ }
+ }
+ init2:
/* Check each port and set hub->change_bits to let khubd know
* which ports need attention.
@@ -692,9 +743,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
* If any port-status changes do occur during this delay, khubd
* will see them later and handle them normally.
*/
- if (need_debounce_delay)
- msleep(HUB_DEBOUNCE_STABLE);
-
+ if (need_debounce_delay) {
+ delay = HUB_DEBOUNCE_STABLE;
+
+ /* Don't do a long sleep inside a workqueue routine */
+ if (type == HUB_INIT2) {
+ PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
+ schedule_delayed_work(&hub->init_work,
+ msecs_to_jiffies(delay));
+ return; /* Continues at init3: below */
+ } else {
+ msleep(delay);
+ }
+ }
+ init3:
hub->quiescing = 0;
status = usb_submit_urb(hub->urb, GFP_NOIO);
@@ -707,6 +769,21 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
kick_khubd(hub);
}
+/* Implement the continuations for the delays above */
+static void hub_init_func2(struct work_struct *ws)
+{
+ struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
+
+ hub_activate(hub, HUB_INIT2);
+}
+
+static void hub_init_func3(struct work_struct *ws)
+{
+ struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
+
+ hub_activate(hub, HUB_INIT3);
+}
+
enum hub_quiescing_type {
HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
};
@@ -716,6 +793,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
struct usb_device *hdev = hub->hdev;
int i;
+ cancel_delayed_work_sync(&hub->init_work);
+
/* khubd and related activity won't re-trigger */
hub->quiescing = 1;
@@ -1099,6 +1178,7 @@ descriptor_error:
hub->intfdev = &intf->dev;
hub->hdev = hdev;
INIT_DELAYED_WORK(&hub->leds, led_work);
+ INIT_DELAYED_WORK(&hub->init_work, NULL);
usb_get_intf(intf);
usb_set_intfdata (intf, hub);
@@ -2467,7 +2547,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,
buf, GET_DESCRIPTOR_BUFSIZE,
- USB_CTRL_GET_TIMEOUT);
+ initial_descriptor_timeout);
switch (buf->bMaxPacketSize0) {
case 8: case 16: case 32: case 64: case 255:
if (buf->bDescriptorType ==
@@ -2683,35 +2763,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
USB_PORT_STAT_C_ENABLE);
#endif
- /* Try to use the debounce delay for protection against
- * port-enable changes caused, for example, by EMI.
- */
- if (portchange & (USB_PORT_STAT_C_CONNECTION |
- USB_PORT_STAT_C_ENABLE)) {
- status = hub_port_debounce(hub, port1);
- if (status < 0) {
- if (printk_ratelimit())
- dev_err (hub_dev, "connect-debounce failed, "
- "port %d disabled\n", port1);
- portstatus &= ~USB_PORT_STAT_CONNECTION;
- } else {
- portstatus = status;
- }
- }
-
/* Try to resuscitate an existing device */
udev = hdev->children[port1-1];
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) {
-
usb_lock_device(udev);
if (portstatus & USB_PORT_STAT_ENABLE) {
status = 0; /* Nothing to do */
- } else if (!udev->persist_enabled) {
- status = -ENODEV; /* Mustn't resuscitate */
#ifdef CONFIG_USB_SUSPEND
- } else if (udev->state == USB_STATE_SUSPENDED) {
+ } else if (udev->state == USB_STATE_SUSPENDED &&
+ udev->persist_enabled) {
/* For a suspended device, treat this as a
* remote wakeup event.
*/
@@ -2726,7 +2788,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
#endif
} else {
- status = usb_reset_device(udev);
+ status = -ENODEV; /* Don't resuscitate */
}
usb_unlock_device(udev);
@@ -2741,6 +2803,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
usb_disconnect(&hdev->children[port1-1]);
clear_bit(port1, hub->change_bits);
+ if (portchange & (USB_PORT_STAT_C_CONNECTION |
+ USB_PORT_STAT_C_ENABLE)) {
+ status = hub_port_debounce(hub, port1);
+ if (status < 0) {
+ if (printk_ratelimit())
+ dev_err(hub_dev, "connect-debounce failed, "
+ "port %d disabled\n", port1);
+ portstatus &= ~USB_PORT_STAT_CONNECTION;
+ } else {
+ portstatus = status;
+ }
+ }
+
/* Return now if debouncing failed or nothing is connected */
if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
@@ -2748,7 +2823,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
-
+
if (portstatus & USB_PORT_STAT_ENABLE)
goto done;
return;
@@ -3040,7 +3115,7 @@ static void hub_events(void)
i);
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_OVER_CURRENT);
- hub_power_on(hub);
+ hub_power_on(hub, true);
}
if (portchange & USB_PORT_STAT_C_RESET) {
@@ -3075,7 +3150,7 @@ static void hub_events(void)
dev_dbg (hub_dev, "overcurrent change\n");
msleep(500); /* Cool down */
clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
- hub_power_on(hub);
+ hub_power_on(hub, true);
}
}
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index db410e92c80..94632264dcc 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -97,7 +97,7 @@ enum {
Opt_err,
};
-static match_table_t tokens = {
+static const match_table_t tokens = {
{Opt_devuid, "devuid=%u"},
{Opt_devgid, "devgid=%u"},
{Opt_devmode, "devmode=%o"},
@@ -180,8 +180,8 @@ static int parse_options(struct super_block *s, char *data)
listmode = option & S_IRWXUGO;
break;
default:
- err("usbfs: unrecognised mount option \"%s\" "
- "or missing value\n", p);
+ printk(KERN_ERR "usbfs: unrecognised mount option "
+ "\"%s\" or missing value\n", p);
return -EINVAL;
}
}
@@ -240,7 +240,9 @@ static void update_sb(struct super_block *sb)
update_special(bus);
break;
default:
- warn("Unknown node %s mode %x found on remount!\n",bus->d_name.name,bus->d_inode->i_mode);
+ printk(KERN_WARNING "usbfs: Unknown node %s "
+ "mode %x found on remount!\n",
+ bus->d_name.name, bus->d_inode->i_mode);
break;
}
}
@@ -259,7 +261,7 @@ static int remount(struct super_block *sb, int *flags, char *data)
return 0;
if (parse_options(sb, data)) {
- warn("usbfs: mount parameter error:");
+ printk(KERN_WARNING "usbfs: mount parameter error.\n");
return -EINVAL;
}
@@ -599,7 +601,7 @@ static int create_special_files (void)
/* create the devices special file */
retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
if (retval) {
- err ("Unable to get usbfs mount");
+ printk(KERN_ERR "Unable to get usbfs mount\n");
goto exit;
}
@@ -611,7 +613,7 @@ static int create_special_files (void)
NULL, &usbfs_devices_fops,
listuid, listgid);
if (devices_usbfs_dentry == NULL) {
- err ("Unable to create devices usbfs file");
+ printk(KERN_ERR "Unable to create devices usbfs file\n");
retval = -ENODEV;
goto error_clean_mounts;
}
@@ -663,7 +665,7 @@ static void usbfs_add_bus(struct usb_bus *bus)
bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent,
bus, NULL, busuid, busgid);
if (bus->usbfs_dentry == NULL) {
- err ("error creating usbfs bus entry");
+ printk(KERN_ERR "Error creating usbfs bus entry\n");
return;
}
}
@@ -694,7 +696,7 @@ static void usbfs_add_device(struct usb_device *dev)
&usbdev_file_operations,
devuid, devgid);
if (dev->usbfs_dentry == NULL) {
- err ("error creating usbfs device entry");
+ printk(KERN_ERR "Error creating usbfs device entry\n");
return;
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 286b4431a09..887738577b2 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1204,7 +1204,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
alt = usb_altnum_to_altsetting(iface, alternate);
if (!alt) {
- warn("selecting invalid altsetting %d", alternate);
+ dev_warn(&dev->dev, "selecting invalid altsetting %d",
+ alternate);
return -EINVAL;
}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 5e1f5d55bf0..f66fba11fbd 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -743,6 +743,29 @@ static ssize_t show_modalias(struct device *dev,
}
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+static ssize_t show_supports_autosuspend(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf;
+ struct usb_device *udev;
+ int ret;
+
+ intf = to_usb_interface(dev);
+ udev = interface_to_usbdev(intf);
+
+ usb_lock_device(udev);
+ /* Devices will be autosuspended even when an interface isn't claimed */
+ if (!intf->dev.driver ||
+ to_usb_driver(intf->dev.driver)->supports_autosuspend)
+ ret = sprintf(buf, "%u\n", 1);
+ else
+ ret = sprintf(buf, "%u\n", 0);
+ usb_unlock_device(udev);
+
+ return ret;
+}
+static DEVICE_ATTR(supports_autosuspend, S_IRUGO, show_supports_autosuspend, NULL);
+
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr,
@@ -751,6 +774,7 @@ static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceSubClass.attr,
&dev_attr_bInterfaceProtocol.attr,
&dev_attr_modalias.attr,
+ &dev_attr_supports_autosuspend.attr,
NULL,
};
static struct attribute_group intf_attr_grp = {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 47111e88f79..f2638009a46 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -10,6 +10,8 @@
#define to_urb(d) container_of(d, struct urb, kref)
+static DEFINE_SPINLOCK(usb_reject_lock);
+
static void urb_destroy(struct kref *kref)
{
struct urb *urb = to_urb(kref);
@@ -68,7 +70,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
iso_packets * sizeof(struct usb_iso_packet_descriptor),
mem_flags);
if (!urb) {
- err("alloc_urb: kmalloc failed");
+ printk(KERN_ERR "alloc_urb: kmalloc failed\n");
return NULL;
}
usb_init_urb(urb);
@@ -127,6 +129,13 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
usb_get_urb(urb);
list_add_tail(&urb->anchor_list, &anchor->urb_list);
urb->anchor = anchor;
+
+ if (unlikely(anchor->poisoned)) {
+ spin_lock(&usb_reject_lock);
+ urb->reject++;
+ spin_unlock(&usb_reject_lock);
+ }
+
spin_unlock_irqrestore(&anchor->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_anchor_urb);
@@ -398,7 +407,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* fail if submitter gave bogus flags */
if (urb->transfer_flags != orig_flags) {
- err("BOGUS urb flags, %x --> %x",
+ dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n",
orig_flags, urb->transfer_flags);
return -EINVAL;
}
@@ -544,25 +553,70 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
*/
void usb_kill_urb(struct urb *urb)
{
- static DEFINE_MUTEX(reject_mutex);
-
might_sleep();
if (!(urb && urb->dev && urb->ep))
return;
- mutex_lock(&reject_mutex);
+ spin_lock_irq(&usb_reject_lock);
++urb->reject;
- mutex_unlock(&reject_mutex);
+ spin_unlock_irq(&usb_reject_lock);
usb_hcd_unlink_urb(urb, -ENOENT);
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
- mutex_lock(&reject_mutex);
+ spin_lock_irq(&usb_reject_lock);
--urb->reject;
- mutex_unlock(&reject_mutex);
+ spin_unlock_irq(&usb_reject_lock);
}
EXPORT_SYMBOL_GPL(usb_kill_urb);
/**
+ * usb_poison_urb - reliably kill a transfer and prevent further use of an URB
+ * @urb: pointer to URB describing a previously submitted request,
+ * may be NULL
+ *
+ * This routine cancels an in-progress request. It is guaranteed that
+ * upon return all completion handlers will have finished and the URB
+ * will be totally idle and cannot be reused. These features make
+ * this an ideal way to stop I/O in a disconnect() callback.
+ * If the request has not already finished or been unlinked
+ * the completion handler will see urb->status == -ENOENT.
+ *
+ * After and while the routine runs, attempts to resubmit the URB will fail
+ * with error -EPERM. Thus even if the URB's completion handler always
+ * tries to resubmit, it will not succeed and the URB will become idle.
+ *
+ * This routine may not be used in an interrupt context (such as a bottom
+ * half or a completion handler), or when holding a spinlock, or in other
+ * situations where the caller can't schedule().
+ */
+void usb_poison_urb(struct urb *urb)
+{
+ might_sleep();
+ if (!(urb && urb->dev && urb->ep))
+ return;
+ spin_lock_irq(&usb_reject_lock);
+ ++urb->reject;
+ spin_unlock_irq(&usb_reject_lock);
+
+ usb_hcd_unlink_urb(urb, -ENOENT);
+ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+}
+EXPORT_SYMBOL_GPL(usb_poison_urb);
+
+void usb_unpoison_urb(struct urb *urb)
+{
+ unsigned long flags;
+
+ if (!urb)
+ return;
+
+ spin_lock_irqsave(&usb_reject_lock, flags);
+ --urb->reject;
+ spin_unlock_irqrestore(&usb_reject_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_unpoison_urb);
+
+/**
* usb_kill_anchored_urbs - cancel transfer requests en masse
* @anchor: anchor the requests are bound to
*
@@ -589,6 +643,35 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
}
EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
+/**
+ * usb_poison_anchored_urbs - cease all traffic from an anchor
+ * @anchor: anchor the requests are bound to
+ *
+ * this allows all outstanding URBs to be poisoned starting
+ * from the back of the queue. Newly added URBs will also be
+ * poisoned
+ */
+void usb_poison_anchored_urbs(struct usb_anchor *anchor)
+{
+ struct urb *victim;
+
+ spin_lock_irq(&anchor->lock);
+ anchor->poisoned = 1;
+ while (!list_empty(&anchor->urb_list)) {
+ victim = list_entry(anchor->urb_list.prev, struct urb,
+ anchor_list);
+ /* we must make sure the URB isn't freed before we kill it*/
+ usb_get_urb(victim);
+ spin_unlock_irq(&anchor->lock);
+ /* this will unanchor the URB */
+ usb_poison_urb(victim);
+ usb_put_urb(victim);
+ spin_lock_irq(&anchor->lock);
+ }
+ spin_unlock_irq(&anchor->lock);
+}
+EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
/**
* usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
* @anchor: anchor the requests are bound to
@@ -633,3 +716,73 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
msecs_to_jiffies(timeout));
}
EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
+
+/**
+ * usb_get_from_anchor - get an anchor's oldest urb
+ * @anchor: the anchor whose urb you want
+ *
+ * this will take the oldest urb from an anchor,
+ * unanchor and return it
+ */
+struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
+{
+ struct urb *victim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&anchor->lock, flags);
+ if (!list_empty(&anchor->urb_list)) {
+ victim = list_entry(anchor->urb_list.next, struct urb,
+ anchor_list);
+ usb_get_urb(victim);
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ usb_unanchor_urb(victim);
+ } else {
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ victim = NULL;
+ }
+
+ return victim;
+}
+
+EXPORT_SYMBOL_GPL(usb_get_from_anchor);
+
+/**
+ * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs
+ * @anchor: the anchor whose urbs you want to unanchor
+ *
+ * use this to get rid of all an anchor's urbs
+ */
+void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
+{
+ struct urb *victim;
+ unsigned long flags;
+
+ spin_lock_irqsave(&anchor->lock, flags);
+ while (!list_empty(&anchor->urb_list)) {
+ victim = list_entry(anchor->urb_list.prev, struct urb,
+ anchor_list);
+ usb_get_urb(victim);
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ /* this may free the URB */
+ usb_unanchor_urb(victim);
+ usb_put_urb(victim);
+ spin_lock_irqsave(&anchor->lock, flags);
+ }
+ spin_unlock_irqrestore(&anchor->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs);
+
+/**
+ * usb_anchor_empty - is an anchor empty
+ * @anchor: the anchor you want to query
+ *
+ * returns 1 if the anchor has no urbs associated with it
+ */
+int usb_anchor_empty(struct usb_anchor *anchor)
+{
+ return list_empty(&anchor->urb_list);
+}
+
+EXPORT_SYMBOL_GPL(usb_anchor_empty);
+
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index acc95b2ac6f..dd4cd5a5137 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -45,7 +45,7 @@ if USB_GADGET
config USB_GADGET_DEBUG
boolean "Debugging messages (DEVELOPMENT)"
- depends on USB_GADGET && DEBUG_KERNEL
+ depends on DEBUG_KERNEL
help
Many controller and gadget drivers will print some debugging
messages if you use this option to ask for those messages.
@@ -59,7 +59,7 @@ config USB_GADGET_DEBUG
config USB_GADGET_DEBUG_FILES
boolean "Debugging information files (DEVELOPMENT)"
- depends on USB_GADGET && PROC_FS
+ depends on PROC_FS
help
Some of the drivers in the "gadget" framework can expose
debugging information in files such as /proc/driver/udc
@@ -70,7 +70,7 @@ config USB_GADGET_DEBUG_FILES
config USB_GADGET_DEBUG_FS
boolean "Debugging information files in debugfs (DEVELOPMENT)"
- depends on USB_GADGET && DEBUG_FS
+ depends on DEBUG_FS
help
Some of the drivers in the "gadget" framework can expose
debugging information in files under /sys/kernel/debug/.
@@ -79,12 +79,36 @@ config USB_GADGET_DEBUG_FS
Enable these files by choosing "Y" here. If in doubt, or
to conserve kernel memory, say "N".
+config USB_GADGET_VBUS_DRAW
+ int "Maximum VBUS Power usage (2-500 mA)"
+ range 2 500
+ default 2
+ help
+ Some devices need to draw power from USB when they are
+ configured, perhaps to operate circuitry or to recharge
+ batteries. This is in addition to any local power supply,
+ such as an AC adapter or batteries.
+
+ Enter the maximum power your device draws through USB, in
+ milliAmperes. The permitted range of values is 2 - 500 mA;
+ 0 mA would be legal, but can make some hosts misbehave.
+
+ This value will be used except for system-specific gadget
+ drivers that have more specific information.
+
config USB_GADGET_SELECTED
boolean
#
# USB Peripheral Controller Support
#
+# The order here is alphabetical, except that integrated controllers go
+# before discrete ones so they will be the initial/default value:
+# - integrated/SOC controllers first
+# - licensed IP used in both SOC and discrete versions
+# - discrete ones (including all PCI-only controllers)
+# - debug/dummy gadget+hcd is last.
+#
choice
prompt "USB Peripheral Controller"
depends on USB_GADGET
@@ -94,26 +118,27 @@ choice
Many controller drivers are platform-specific; these
often need board-specific hooks.
-config USB_GADGET_AMD5536UDC
- boolean "AMD5536 UDC"
- depends on PCI
- select USB_GADGET_DUALSPEED
+#
+# Integrated controllers
+#
+
+config USB_GADGET_AT91
+ boolean "Atmel AT91 USB Device Port"
+ depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9
+ select USB_GADGET_SELECTED
help
- The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
- It is a USB Highspeed DMA capable USB device controller. Beside ep0
- it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
- The UDC port supports OTG operation, and may be used as a host port
- if it's not being used to implement peripheral or OTG roles.
+ Many Atmel AT91 processors (such as the AT91RM2000) have a
+ full speed USB Device Port with support for five configurable
+ endpoints (plus endpoint zero).
Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "amd5536udc" and force all
+ dynamically linked module called "at91_udc" and force all
gadget drivers to also be dynamically linked.
-config USB_AMD5536UDC
+config USB_AT91
tristate
- depends on USB_GADGET_AMD5536UDC
+ depends on USB_GADGET_AT91
default USB_GADGET
- select USB_GADGET_SELECTED
config USB_GADGET_ATMEL_USBA
boolean "Atmel USBA"
@@ -150,28 +175,50 @@ config USB_FSL_USB2
default USB_GADGET
select USB_GADGET_SELECTED
-config USB_GADGET_NET2280
- boolean "NetChip 228x"
- depends on PCI
- select USB_GADGET_DUALSPEED
+config USB_GADGET_LH7A40X
+ boolean "LH7A40X"
+ depends on ARCH_LH7A40X
help
- NetChip 2280 / 2282 is a PCI based USB peripheral controller which
- supports both full and high speed USB 2.0 data transfers.
-
- It has six configurable endpoints, as well as endpoint zero
- (for control transfers) and several endpoints with dedicated
- functions.
+ This driver provides USB Device Controller driver for LH7A40x
+
+config USB_LH7A40X
+ tristate
+ depends on USB_GADGET_LH7A40X
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
+config USB_GADGET_OMAP
+ boolean "OMAP USB Device Controller"
+ depends on ARCH_OMAP
+ select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
+ help
+ Many Texas Instruments OMAP processors have flexible full
+ speed USB device controllers, with support for up to 30
+ endpoints (plus endpoint zero). This driver supports the
+ controller in the OMAP 1611, and should work with controllers
+ in other OMAP processors too, given minor tweaks.
Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "net2280" and force all
+ dynamically linked module called "omap_udc" and force all
gadget drivers to also be dynamically linked.
-config USB_NET2280
+config USB_OMAP
tristate
- depends on USB_GADGET_NET2280
+ depends on USB_GADGET_OMAP
default USB_GADGET
select USB_GADGET_SELECTED
+config USB_OTG
+ boolean "OTG Support"
+ depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
+ help
+ The most notable feature of USB OTG is support for a
+ "Dual-Role" device, which can act as either a device
+ or a host. The initial role choice can be changed
+ later, when two dual-role devices talk to each other.
+
+ Select this only if your OMAP board has a Mini-AB connector.
+
config USB_GADGET_PXA25X
boolean "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
@@ -203,34 +250,6 @@ config USB_PXA25X_SMALL
default y if USB_ETH
default y if USB_G_SERIAL
-config USB_GADGET_M66592
- boolean "Renesas M66592 USB Peripheral Controller"
- select USB_GADGET_DUALSPEED
- help
- M66592 is a discrete USB peripheral controller chip that
- supports both full and high speed USB 2.0 data transfers.
- It has seven configurable endpoints, and endpoint zero.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "m66592_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_M66592
- tristate
- depends on USB_GADGET_M66592
- default USB_GADGET
- select USB_GADGET_SELECTED
-
-config SUPERH_BUILT_IN_M66592
- boolean "Enable SuperH built-in USB like the M66592"
- depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
- help
- SH7722 has USB like the M66592.
-
- The transfer rate is very slow when use "Ethernet Gadget".
- However, this problem is improved if change a value of
- NET_IP_ALIGN to 4.
-
config USB_GADGET_PXA27X
boolean "PXA 27x"
depends on ARCH_PXA && PXA27x
@@ -251,40 +270,32 @@ config USB_PXA27X
default USB_GADGET
select USB_GADGET_SELECTED
-config USB_GADGET_GOKU
- boolean "Toshiba TC86C001 'Goku-S'"
- depends on PCI
+config USB_GADGET_S3C2410
+ boolean "S3C2410 USB Device Controller"
+ depends on ARCH_S3C2410
help
- The Toshiba TC86C001 is a PCI device which includes controllers
- for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
-
- The device controller has three configurable (bulk or interrupt)
- endpoints, plus endpoint zero (for control transfers).
+ Samsung's S3C2410 is an ARM-4 processor with an integrated
+ full speed USB 1.1 device controller. It has 4 configurable
+ endpoints, as well as endpoint zero (for control transfers).
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "goku_udc" and to force all
- gadget drivers to also be dynamically linked.
+ This driver has been tested on the S3C2410, S3C2412, and
+ S3C2440 processors.
-config USB_GOKU
+config USB_S3C2410
tristate
- depends on USB_GADGET_GOKU
+ depends on USB_GADGET_S3C2410
default USB_GADGET
select USB_GADGET_SELECTED
+config USB_S3C2410_DEBUG
+ boolean "S3C2410 udc debug messages"
+ depends on USB_GADGET_S3C2410
-config USB_GADGET_LH7A40X
- boolean "LH7A40X"
- depends on ARCH_LH7A40X
- help
- This driver provides USB Device Controller driver for LH7A40x
-
-config USB_LH7A40X
- tristate
- depends on USB_GADGET_LH7A40X
- default USB_GADGET
- select USB_GADGET_SELECTED
+#
+# Controllers available in both integrated and discrete versions
+#
-# built in ../musb along with host support
+# musb builds in ../musb along with host support
config USB_GADGET_MUSB_HDRC
boolean "Inventra HDRC USB Peripheral (TI, ...)"
depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
@@ -294,76 +305,124 @@ config USB_GADGET_MUSB_HDRC
This OTG-capable silicon IP is used in dual designs including
the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
-config USB_GADGET_OMAP
- boolean "OMAP USB Device Controller"
- depends on ARCH_OMAP
- select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+config USB_GADGET_M66592
+ boolean "Renesas M66592 USB Peripheral Controller"
+ select USB_GADGET_DUALSPEED
help
- Many Texas Instruments OMAP processors have flexible full
- speed USB device controllers, with support for up to 30
- endpoints (plus endpoint zero). This driver supports the
- controller in the OMAP 1611, and should work with controllers
- in other OMAP processors too, given minor tweaks.
+ M66592 is a discrete USB peripheral controller chip that
+ supports both full and high speed USB 2.0 data transfers.
+ It has seven configurable endpoints, and endpoint zero.
Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "omap_udc" and force all
+ dynamically linked module called "m66592_udc" and force all
gadget drivers to also be dynamically linked.
-config USB_OMAP
+config USB_M66592
tristate
- depends on USB_GADGET_OMAP
+ depends on USB_GADGET_M66592
default USB_GADGET
select USB_GADGET_SELECTED
-config USB_OTG
- boolean "OTG Support"
- depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
+config SUPERH_BUILT_IN_M66592
+ boolean "Enable SuperH built-in USB like the M66592"
+ depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
help
- The most notable feature of USB OTG is support for a
- "Dual-Role" device, which can act as either a device
- or a host. The initial role choice can be changed
- later, when two dual-role devices talk to each other.
+ SH7722 has USB like the M66592.
- Select this only if your OMAP board has a Mini-AB connector.
+ The transfer rate is very slow when use "Ethernet Gadget".
+ However, this problem is improved if change a value of
+ NET_IP_ALIGN to 4.
-config USB_GADGET_S3C2410
- boolean "S3C2410 USB Device Controller"
- depends on ARCH_S3C2410
+#
+# Controllers available only in discrete form (and all PCI controllers)
+#
+
+config USB_GADGET_AMD5536UDC
+ boolean "AMD5536 UDC"
+ depends on PCI
+ select USB_GADGET_DUALSPEED
help
- Samsung's S3C2410 is an ARM-4 processor with an integrated
- full speed USB 1.1 device controller. It has 4 configurable
- endpoints, as well as endpoint zero (for control transfers).
+ The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+ It is a USB Highspeed DMA capable USB device controller. Beside ep0
+ it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+ The UDC port supports OTG operation, and may be used as a host port
+ if it's not being used to implement peripheral or OTG roles.
- This driver has been tested on the S3C2410, S3C2412, and
- S3C2440 processors.
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "amd5536udc" and force all
+ gadget drivers to also be dynamically linked.
-config USB_S3C2410
+config USB_AMD5536UDC
tristate
- depends on USB_GADGET_S3C2410
+ depends on USB_GADGET_AMD5536UDC
default USB_GADGET
select USB_GADGET_SELECTED
-config USB_S3C2410_DEBUG
- boolean "S3C2410 udc debug messages"
- depends on USB_GADGET_S3C2410
+config USB_GADGET_FSL_QE
+ boolean "Freescale QE/CPM USB Device Controller"
+ depends on FSL_SOC && (QUICC_ENGINE || CPM)
+ help
+ Some of Freescale PowerPC processors have a Full Speed
+ QE/CPM2 USB controller, which support device mode with 4
+ programmable endpoints. This driver supports the
+ controller in the MPC8360 and MPC8272, and should work with
+ controllers having QE or CPM2, given minor tweaks.
-config USB_GADGET_AT91
- boolean "AT91 USB Device Port"
- depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9
+ Set CONFIG_USB_GADGET to "m" to build this driver as a
+ dynmically linked module called "fsl_qe_udc".
+
+config USB_FSL_QE
+ tristate
+ depends on USB_GADGET_FSL_QE
+ default USB_GADGET
select USB_GADGET_SELECTED
+
+config USB_GADGET_NET2280
+ boolean "NetChip 228x"
+ depends on PCI
+ select USB_GADGET_DUALSPEED
help
- Many Atmel AT91 processors (such as the AT91RM2000) have a
- full speed USB Device Port with support for five configurable
- endpoints (plus endpoint zero).
+ NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+ supports both full and high speed USB 2.0 data transfers.
+
+ It has six configurable endpoints, as well as endpoint zero
+ (for control transfers) and several endpoints with dedicated
+ functions.
Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "at91_udc" and force all
+ dynamically linked module called "net2280" and force all
gadget drivers to also be dynamically linked.
-config USB_AT91
+config USB_NET2280
tristate
- depends on USB_GADGET_AT91
+ depends on USB_GADGET_NET2280
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
+config USB_GADGET_GOKU
+ boolean "Toshiba TC86C001 'Goku-S'"
+ depends on PCI
+ help
+ The Toshiba TC86C001 is a PCI device which includes controllers
+ for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
+
+ The device controller has three configurable (bulk or interrupt)
+ endpoints, plus endpoint zero (for control transfers).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "goku_udc" and to force all
+ gadget drivers to also be dynamically linked.
+
+config USB_GOKU
+ tristate
+ depends on USB_GADGET_GOKU
default USB_GADGET
+ select USB_GADGET_SELECTED
+
+
+#
+# LAST -- dummy/emulated controller
+#
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
@@ -553,19 +612,23 @@ config USB_FILE_STORAGE_TEST
normal operation.
config USB_G_SERIAL
- tristate "Serial Gadget (with CDC ACM support)"
+ tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
help
The Serial Gadget talks to the Linux-USB generic serial driver.
This driver supports a CDC-ACM module option, which can be used
to interoperate with MS-Windows hosts or with the Linux-USB
"cdc-acm" driver.
+ This driver also supports a CDC-OBEX option. You will need a
+ user space OBEX server talking to /dev/ttyGS*, since the kernel
+ itself doesn't implement the OBEX protocol.
+
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_serial".
For more information, see Documentation/usb/gadget_serial.txt
which includes instructions and a "driver info file" needed to
- make MS-Windows work with this driver.
+ make MS-Windows work with CDC ACM.
config USB_MIDI_GADGET
tristate "MIDI Gadget (EXPERIMENTAL)"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index fcb5cb9094d..bd4041b47dc 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -18,28 +18,20 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
+obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
#
# USB gadget drivers
#
-C_UTILS = composite.o usbstring.o config.o epautoconf.o
-
-g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
-g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
-g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
-g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
+g_zero-objs := zero.o
+g_ether-objs := ether.o
+g_serial-objs := serial.o
+g_midi-objs := gmidi.o
gadgetfs-objs := inode.o
-g_file_storage-objs := file_storage.o usbstring.o config.o \
- epautoconf.o
-g_printer-objs := printer.o usbstring.o config.o \
- epautoconf.o
-g_cdc-objs := cdc2.o u_ether.o f_ecm.o \
- u_serial.o f_acm.o $(C_UTILS)
+g_file_storage-objs := file_storage.o
+g_printer-objs := printer.o
+g_cdc-objs := cdc2.o
-ifeq ($(CONFIG_USB_ETH_RNDIS),y)
- g_ether-objs += f_rndis.o rndis.o
-endif
-
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index a39a4b940c3..5495b171cf2 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -43,6 +43,25 @@
/*-------------------------------------------------------------------------*/
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+#include "u_serial.c"
+#include "f_acm.c"
+#include "f_ecm.c"
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
@@ -136,7 +155,6 @@ static struct usb_configuration cdc_config_driver = {
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
};
/*-------------------------------------------------------------------------*/
@@ -148,7 +166,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
int status;
if (!can_support_ecm(cdev->gadget)) {
- ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+ dev_err(&gadget->dev, "controller '%s' not usable\n",
+ gadget->name);
return -EINVAL;
}
@@ -203,7 +222,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
if (status < 0)
goto fail1;
- INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+ dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+ DRIVER_DESC);
return 0;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 85c876c1f15..f2da0269e1b 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -128,6 +128,70 @@ done:
}
/**
+ * usb_function_deactivate - prevent function and gadget enumeration
+ * @function: the function that isn't yet ready to respond
+ *
+ * Blocks response of the gadget driver to host enumeration by
+ * preventing the data line pullup from being activated. This is
+ * normally called during @bind() processing to change from the
+ * initial "ready to respond" state, or when a required resource
+ * becomes available.
+ *
+ * For example, drivers that serve as a passthrough to a userspace
+ * daemon can block enumeration unless that daemon (such as an OBEX,
+ * MTP, or print server) is ready to handle host requests.
+ *
+ * Not all systems support software control of their USB peripheral
+ * data pullups.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_function_deactivate(struct usb_function *function)
+{
+ struct usb_composite_dev *cdev = function->config->cdev;
+ int status = 0;
+
+ spin_lock(&cdev->lock);
+
+ if (cdev->deactivations == 0)
+ status = usb_gadget_disconnect(cdev->gadget);
+ if (status == 0)
+ cdev->deactivations++;
+
+ spin_unlock(&cdev->lock);
+ return status;
+}
+
+/**
+ * usb_function_activate - allow function and gadget enumeration
+ * @function: function on which usb_function_activate() was called
+ *
+ * Reverses effect of usb_function_deactivate(). If no more functions
+ * are delaying their activation, the gadget driver will respond to
+ * host enumeration procedures.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_function_activate(struct usb_function *function)
+{
+ struct usb_composite_dev *cdev = function->config->cdev;
+ int status = 0;
+
+ spin_lock(&cdev->lock);
+
+ if (WARN_ON(cdev->deactivations == 0))
+ status = -EINVAL;
+ else {
+ cdev->deactivations--;
+ if (cdev->deactivations == 0)
+ status = usb_gadget_connect(cdev->gadget);
+ }
+
+ spin_unlock(&cdev->lock);
+ return status;
+}
+
+/**
* usb_interface_id() - allocate an unused interface ID
* @config: configuration associated with the interface
* @function: function handling the interface
@@ -181,7 +245,7 @@ static int config_buf(struct usb_configuration *config,
c->bConfigurationValue = config->bConfigurationValue;
c->iConfiguration = config->iConfiguration;
c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
- c->bMaxPower = config->bMaxPower;
+ c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2);
/* There may be e.g. OTG descriptors */
if (config->descriptors) {
@@ -368,7 +432,7 @@ static int set_config(struct usb_composite_dev *cdev,
}
/* when we return, be sure our power usage is valid */
- power = 2 * c->bMaxPower;
+ power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
done:
usb_gadget_vbus_draw(gadget, power);
return result;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 7600a0c7875..9064696636a 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -82,6 +82,7 @@ struct dummy_ep {
const struct usb_endpoint_descriptor *desc;
struct usb_ep ep;
unsigned halted : 1;
+ unsigned wedged : 1;
unsigned already_seen : 1;
unsigned setup_stage : 1;
};
@@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* at this point real hardware should be NAKing transfers
* to that endpoint, until a buffer is queued to it.
*/
+ ep->halted = ep->wedged = 0;
retval = 0;
done:
return retval;
@@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
}
static int
-dummy_set_halt (struct usb_ep *_ep, int value)
+dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
{
struct dummy_ep *ep;
struct dummy *dum;
@@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value)
if (!dum->driver)
return -ESHUTDOWN;
if (!value)
- ep->halted = 0;
+ ep->halted = ep->wedged = 0;
else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
!list_empty (&ep->queue))
return -EAGAIN;
- else
+ else {
ep->halted = 1;
+ if (wedged)
+ ep->wedged = 1;
+ }
/* FIXME clear emulated data toggle too */
return 0;
}
+static int
+dummy_set_halt(struct usb_ep *_ep, int value)
+{
+ return dummy_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int dummy_set_wedge(struct usb_ep *_ep)
+{
+ if (!_ep || _ep->name == ep0name)
+ return -EINVAL;
+ return dummy_set_halt_and_wedge(_ep, 1, 1);
+}
+
static const struct usb_ep_ops dummy_ep_ops = {
.enable = dummy_enable,
.disable = dummy_disable,
@@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = {
.dequeue = dummy_dequeue,
.set_halt = dummy_set_halt,
+ .set_wedge = dummy_set_wedge,
};
/*-------------------------------------------------------------------------*/
@@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
ep->ep.name = ep_name [i];
ep->ep.ops = &dummy_ep_ops;
list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list);
- ep->halted = ep->already_seen = ep->setup_stage = 0;
+ ep->halted = ep->wedged = ep->already_seen =
+ ep->setup_stage = 0;
ep->ep.maxpacket = ~0;
ep->last_io = jiffies;
ep->gadget = &dum->gadget;
@@ -1351,7 +1371,7 @@ restart:
} else if (setup.bRequestType == Ep_Request) {
// endpoint halt
ep2 = find_endpoint (dum, w_index);
- if (!ep2) {
+ if (!ep2 || ep2->ep.name == ep0name) {
value = -EOPNOTSUPP;
break;
}
@@ -1380,7 +1400,8 @@ restart:
value = -EOPNOTSUPP;
break;
}
- ep2->halted = 0;
+ if (!ep2->wedged)
+ ep2->halted = 0;
value = 0;
status = 0;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index bcac2e68660..37252d0012a 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -96,6 +96,28 @@ static inline bool has_rndis(void)
/*-------------------------------------------------------------------------*/
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_ecm.c"
+#include "f_subset.c"
+#ifdef CONFIG_USB_ETH_RNDIS
+#include "f_rndis.c"
+#include "rndis.c"
+#endif
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures.
*/
@@ -220,7 +242,6 @@ static struct usb_configuration rndis_config_driver = {
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
};
/*-------------------------------------------------------------------------*/
@@ -249,7 +270,6 @@ static struct usb_configuration eth_config_driver = {
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
};
/*-------------------------------------------------------------------------*/
@@ -293,7 +313,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
* but if the controller isn't recognized at all then
* that assumption is a bit more likely to be wrong.
*/
- WARNING(cdev, "controller '%s' not recognized; trying %s\n",
+ dev_warn(&gadget->dev,
+ "controller '%s' not recognized; trying %s\n",
gadget->name,
eth_config_driver.label);
device_desc.bcdDevice =
@@ -332,7 +353,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
if (status < 0)
goto fail;
- INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+ dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+ DRIVER_DESC);
return 0;
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index a2b5c092bda..4ae579948e5 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -83,7 +83,7 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
}
/* peak (theoretical) bulk transfer rate in bits-per-second */
-static inline unsigned bitrate(struct usb_gadget *g)
+static inline unsigned ecm_bitrate(struct usb_gadget *g)
{
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return 13 * 512 * 8 * 1000 * 8;
@@ -107,7 +107,7 @@ static inline unsigned bitrate(struct usb_gadget *g)
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
+#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
/* interface descriptor: */
@@ -125,8 +125,8 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};
-static struct usb_cdc_header_desc header_desc __initdata = {
- .bLength = sizeof header_desc,
+static struct usb_cdc_header_desc ecm_header_desc __initdata = {
+ .bLength = sizeof ecm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@@ -141,8 +141,8 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
/* .bSlaveInterface0 = DYNAMIC */
};
-static struct usb_cdc_ether_desc ether_desc __initdata = {
- .bLength = sizeof ether_desc,
+static struct usb_cdc_ether_desc ecm_desc __initdata = {
+ .bLength = sizeof ecm_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
@@ -186,17 +186,17 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {
/* full speed support: */
-static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -204,7 +204,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -212,34 +212,34 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
- (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
- (struct usb_descriptor_header *) &ether_desc,
+ (struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
- (struct usb_descriptor_header *) &fs_notify_desc,
+ (struct usb_descriptor_header *) &fs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
- (struct usb_descriptor_header *) &fs_in_desc,
- (struct usb_descriptor_header *) &fs_out_desc,
+ (struct usb_descriptor_header *) &fs_ecm_in_desc,
+ (struct usb_descriptor_header *) &fs_ecm_out_desc,
NULL,
};
/* high speed support: */
-static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -257,19 +257,19 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
-static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
- (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
- (struct usb_descriptor_header *) &ether_desc,
+ (struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
- (struct usb_descriptor_header *) &hs_notify_desc,
+ (struct usb_descriptor_header *) &hs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
- (struct usb_descriptor_header *) &hs_in_desc,
- (struct usb_descriptor_header *) &hs_out_desc,
+ (struct usb_descriptor_header *) &hs_ecm_in_desc,
+ (struct usb_descriptor_header *) &hs_ecm_out_desc,
NULL,
};
@@ -329,14 +329,14 @@ static void ecm_do_notify(struct f_ecm *ecm)
event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
event->wValue = cpu_to_le16(0);
event->wLength = cpu_to_le16(8);
- req->length = STATUS_BYTECOUNT;
+ req->length = ECM_STATUS_BYTECOUNT;
/* SPEED_CHANGE data is up/down speeds in bits/sec */
data = req->buf + sizeof *event;
- data[0] = cpu_to_le32(bitrate(cdev->gadget));
+ data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
data[1] = data[0];
- DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+ DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
ecm->notify_state = ECM_NOTIFY_NONE;
break;
}
@@ -628,13 +628,13 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENODEV;
/* allocate instance-specific endpoints */
- ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
if (!ep)
goto fail;
ecm->port.in_ep = ep;
ep->driver_data = cdev; /* claim */
- ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
if (!ep)
goto fail;
ecm->port.out_ep = ep;
@@ -644,7 +644,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
* don't treat it that way. It's simpler, and some newer CDC
* profiles (wireless handsets) no longer treat it as optional.
*/
- ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
if (!ep)
goto fail;
ecm->notify = ep;
@@ -656,47 +656,47 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
if (!ecm->notify_req)
goto fail;
- ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+ ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
if (!ecm->notify_req->buf)
goto fail;
ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete;
/* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(eth_fs_function);
+ f->descriptors = usb_copy_descriptors(ecm_fs_function);
if (!f->descriptors)
goto fail;
- ecm->fs.in = usb_find_endpoint(eth_fs_function,
- f->descriptors, &fs_in_desc);
- ecm->fs.out = usb_find_endpoint(eth_fs_function,
- f->descriptors, &fs_out_desc);
- ecm->fs.notify = usb_find_endpoint(eth_fs_function,
- f->descriptors, &fs_notify_desc);
+ ecm->fs.in = usb_find_endpoint(ecm_fs_function,
+ f->descriptors, &fs_ecm_in_desc);
+ ecm->fs.out = usb_find_endpoint(ecm_fs_function,
+ f->descriptors, &fs_ecm_out_desc);
+ ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
+ f->descriptors, &fs_ecm_notify_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_in_desc.bEndpointAddress =
- fs_in_desc.bEndpointAddress;
- hs_out_desc.bEndpointAddress =
- fs_out_desc.bEndpointAddress;
- hs_notify_desc.bEndpointAddress =
- fs_notify_desc.bEndpointAddress;
+ hs_ecm_in_desc.bEndpointAddress =
+ fs_ecm_in_desc.bEndpointAddress;
+ hs_ecm_out_desc.bEndpointAddress =
+ fs_ecm_out_desc.bEndpointAddress;
+ hs_ecm_notify_desc.bEndpointAddress =
+ fs_ecm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+ f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
if (!f->hs_descriptors)
goto fail;
- ecm->hs.in = usb_find_endpoint(eth_hs_function,
- f->hs_descriptors, &hs_in_desc);
- ecm->hs.out = usb_find_endpoint(eth_hs_function,
- f->hs_descriptors, &hs_out_desc);
- ecm->hs.notify = usb_find_endpoint(eth_hs_function,
- f->hs_descriptors, &hs_notify_desc);
+ ecm->hs.in = usb_find_endpoint(ecm_hs_function,
+ f->hs_descriptors, &hs_ecm_in_desc);
+ ecm->hs.out = usb_find_endpoint(ecm_hs_function,
+ f->hs_descriptors, &hs_ecm_out_desc);
+ ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
+ f->hs_descriptors, &hs_ecm_notify_desc);
}
/* NOTE: all that is done without knowing or caring about
@@ -795,7 +795,7 @@ int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (status < 0)
return status;
ecm_string_defs[1].id = status;
- ether_desc.iMACAddress = status;
+ ecm_desc.iMACAddress = status;
}
/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index eda4cde72c8..8affe1dfc2c 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -70,7 +70,7 @@ static struct usb_interface_descriptor loopback_intf = {
/* full speed support: */
-static struct usb_endpoint_descriptor fs_source_desc = {
+static struct usb_endpoint_descriptor fs_loop_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -78,7 +78,7 @@ static struct usb_endpoint_descriptor fs_source_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor fs_sink_desc = {
+static struct usb_endpoint_descriptor fs_loop_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -88,14 +88,14 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
static struct usb_descriptor_header *fs_loopback_descs[] = {
(struct usb_descriptor_header *) &loopback_intf,
- (struct usb_descriptor_header *) &fs_sink_desc,
- (struct usb_descriptor_header *) &fs_source_desc,
+ (struct usb_descriptor_header *) &fs_loop_sink_desc,
+ (struct usb_descriptor_header *) &fs_loop_source_desc,
NULL,
};
/* high speed support: */
-static struct usb_endpoint_descriptor hs_source_desc = {
+static struct usb_endpoint_descriptor hs_loop_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -103,7 +103,7 @@ static struct usb_endpoint_descriptor hs_source_desc = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor hs_sink_desc = {
+static struct usb_endpoint_descriptor hs_loop_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -113,8 +113,8 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
static struct usb_descriptor_header *hs_loopback_descs[] = {
(struct usb_descriptor_header *) &loopback_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
+ (struct usb_descriptor_header *) &hs_loop_source_desc,
+ (struct usb_descriptor_header *) &hs_loop_sink_desc,
NULL,
};
@@ -152,7 +152,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
/* allocate endpoints */
- loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+ loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
if (!loop->in_ep) {
autoconf_fail:
ERROR(cdev, "%s: can't autoconfigure on %s\n",
@@ -161,17 +161,17 @@ autoconf_fail:
}
loop->in_ep->driver_data = cdev; /* claim */
- loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+ loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
if (!loop->out_ep)
goto autoconf_fail;
loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_source_desc.bEndpointAddress =
- fs_source_desc.bEndpointAddress;
- hs_sink_desc.bEndpointAddress =
- fs_sink_desc.bEndpointAddress;
+ hs_loop_source_desc.bEndpointAddress =
+ fs_loop_source_desc.bEndpointAddress;
+ hs_loop_sink_desc.bEndpointAddress =
+ fs_loop_sink_desc.bEndpointAddress;
f->hs_descriptors = hs_loopback_descs;
}
@@ -255,8 +255,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
struct usb_request *req;
unsigned i;
- src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
- sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+ src = ep_choose(cdev->gadget,
+ &hs_loop_source_desc, &fs_loop_source_desc);
+ sink = ep_choose(cdev->gadget,
+ &hs_loop_sink_desc, &fs_loop_sink_desc);
/* one endpoint writes data back IN to the host */
ep = loop->in_ep;
@@ -350,7 +352,6 @@ static struct usb_configuration loopback_driver = {
.bind = loopback_bind_config,
.bConfigurationValue = 2,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
/* .iConfiguration = DYNAMIC */
};
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
new file mode 100644
index 00000000000..80c2e7e9622
--- /dev/null
+++ b/drivers/usb/gadget/f_obex.c
@@ -0,0 +1,493 @@
+/*
+ * f_obex.c -- USB CDC OBEX function driver
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * Based on f_acm.c by Al Borchers and David Brownell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This CDC OBEX function support just packages a TTY-ish byte stream.
+ * A user mode server will put it into "raw" mode and handle all the
+ * relevant protocol details ... this is just a kernel passthrough.
+ * When possible, we prevent gadget enumeration until that server is
+ * ready to handle the commands.
+ */
+
+struct obex_ep_descs {
+ struct usb_endpoint_descriptor *obex_in;
+ struct usb_endpoint_descriptor *obex_out;
+};
+
+struct f_obex {
+ struct gserial port;
+ u8 ctrl_id;
+ u8 data_id;
+ u8 port_num;
+ u8 can_activate;
+
+ struct obex_ep_descs fs;
+ struct obex_ep_descs hs;
+};
+
+static inline struct f_obex *func_to_obex(struct usb_function *f)
+{
+ return container_of(f, struct f_obex, port.func);
+}
+
+static inline struct f_obex *port_to_obex(struct gserial *p)
+{
+ return container_of(p, struct f_obex, port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define OBEX_CTRL_IDX 0
+#define OBEX_DATA_IDX 1
+
+static struct usb_string obex_string_defs[] = {
+ [OBEX_CTRL_IDX].s = "CDC Object Exchange (OBEX)",
+ [OBEX_DATA_IDX].s = "CDC OBEX Data",
+ { }, /* end of list */
+};
+
+static struct usb_gadget_strings obex_string_table = {
+ .language = 0x0409, /* en-US */
+ .strings = obex_string_defs,
+};
+
+static struct usb_gadget_strings *obex_strings[] = {
+ &obex_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor obex_control_intf __initdata = {
+ .bLength = sizeof(obex_control_intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX,
+};
+
+static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
+ .bLength = sizeof(obex_data_nop_intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 1,
+
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+};
+
+static struct usb_interface_descriptor obex_data_intf __initdata = {
+ .bLength = sizeof(obex_data_intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 2,
+
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+};
+
+static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
+ .bLength = sizeof(obex_cdc_header_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+ .bcdCDC = __constant_cpu_to_le16(0x0120),
+};
+
+static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
+ .bLength = sizeof(obex_cdc_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ .bMasterInterface0 = 1,
+ .bSlaveInterface0 = 2,
+};
+
+static struct usb_cdc_obex_desc obex_desc __initdata = {
+ .bLength = sizeof(obex_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_OBEX_TYPE,
+ .bcdVersion = __constant_cpu_to_le16(0x0100),
+};
+
+/* High-Speed Support */
+
+static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_function[] __initdata = {
+ (struct usb_descriptor_header *) &obex_control_intf,
+ (struct usb_descriptor_header *) &obex_cdc_header_desc,
+ (struct usb_descriptor_header *) &obex_desc,
+ (struct usb_descriptor_header *) &obex_cdc_union_desc,
+
+ (struct usb_descriptor_header *) &obex_data_nop_intf,
+ (struct usb_descriptor_header *) &obex_data_intf,
+ (struct usb_descriptor_header *) &obex_hs_ep_in_desc,
+ (struct usb_descriptor_header *) &obex_hs_ep_out_desc,
+ NULL,
+};
+
+/* Full-Speed Support */
+
+static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_function[] __initdata = {
+ (struct usb_descriptor_header *) &obex_control_intf,
+ (struct usb_descriptor_header *) &obex_cdc_header_desc,
+ (struct usb_descriptor_header *) &obex_desc,
+ (struct usb_descriptor_header *) &obex_cdc_union_desc,
+
+ (struct usb_descriptor_header *) &obex_data_nop_intf,
+ (struct usb_descriptor_header *) &obex_data_intf,
+ (struct usb_descriptor_header *) &obex_fs_ep_in_desc,
+ (struct usb_descriptor_header *) &obex_fs_ep_out_desc,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_obex *obex = func_to_obex(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ if (intf == obex->ctrl_id) {
+ if (alt != 0)
+ goto fail;
+ /* NOP */
+ DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num);
+
+ } else if (intf == obex->data_id) {
+ if (alt > 1)
+ goto fail;
+
+ if (obex->port.in->driver_data) {
+ DBG(cdev, "reset obex ttyGS%d\n", obex->port_num);
+ gserial_disconnect(&obex->port);
+ }
+
+ if (!obex->port.in_desc) {
+ DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
+ obex->port.in_desc = ep_choose(cdev->gadget,
+ obex->hs.obex_in, obex->fs.obex_in);
+ obex->port.out_desc = ep_choose(cdev->gadget,
+ obex->hs.obex_out, obex->fs.obex_out);
+ }
+
+ if (alt == 1) {
+ DBG(cdev, "activate obex ttyGS%d\n", obex->port_num);
+ gserial_connect(&obex->port, obex->port_num);
+ }
+
+ } else
+ goto fail;
+
+ return 0;
+
+fail:
+ return -EINVAL;
+}
+
+static int obex_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_obex *obex = func_to_obex(f);
+
+ if (intf == obex->ctrl_id)
+ return 0;
+
+ return obex->port.in->driver_data ? 1 : 0;
+}
+
+static void obex_disable(struct usb_function *f)
+{
+ struct f_obex *obex = func_to_obex(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "obex ttyGS%d disable\n", obex->port_num);
+ gserial_disconnect(&obex->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void obex_connect(struct gserial *g)
+{
+ struct f_obex *obex = port_to_obex(g);
+ struct usb_composite_dev *cdev = g->func.config->cdev;
+ int status;
+
+ if (!obex->can_activate)
+ return;
+
+ status = usb_function_activate(&g->func);
+ if (status)
+ DBG(cdev, "obex ttyGS%d function activate --> %d\n",
+ obex->port_num, status);
+}
+
+static void obex_disconnect(struct gserial *g)
+{
+ struct f_obex *obex = port_to_obex(g);
+ struct usb_composite_dev *cdev = g->func.config->cdev;
+ int status;
+
+ if (!obex->can_activate)
+ return;
+
+ status = usb_function_deactivate(&g->func);
+ if (status)
+ DBG(cdev, "obex ttyGS%d function deactivate --> %d\n",
+ obex->port_num, status);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init
+obex_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_obex *obex = func_to_obex(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs, and patch descriptors */
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ obex->ctrl_id = status;
+
+ obex_control_intf.bInterfaceNumber = status;
+ obex_cdc_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ obex->data_id = status;
+
+ obex_data_nop_intf.bInterfaceNumber = status;
+ obex_data_intf.bInterfaceNumber = status;
+ obex_cdc_union_desc.bSlaveInterface0 = status;
+
+ /* allocate instance-specific endpoints */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);
+ if (!ep)
+ goto fail;
+ obex->port.in = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
+ if (!ep)
+ goto fail;
+ obex->port.out = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(fs_function);
+
+ obex->fs.obex_in = usb_find_endpoint(fs_function,
+ f->descriptors, &obex_fs_ep_in_desc);
+ obex->fs.obex_out = usb_find_endpoint(fs_function,
+ f->descriptors, &obex_fs_ep_out_desc);
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+
+ obex_hs_ep_in_desc.bEndpointAddress =
+ obex_fs_ep_in_desc.bEndpointAddress;
+ obex_hs_ep_out_desc.bEndpointAddress =
+ obex_fs_ep_out_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(hs_function);
+
+ obex->hs.obex_in = usb_find_endpoint(hs_function,
+ f->descriptors, &obex_hs_ep_in_desc);
+ obex->hs.obex_out = usb_find_endpoint(hs_function,
+ f->descriptors, &obex_hs_ep_out_desc);
+ }
+
+ /* Avoid letting this gadget enumerate until the userspace
+ * OBEX server is active.
+ */
+ status = usb_function_deactivate(f);
+ if (status < 0)
+ WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
+ obex->port_num, status);
+ else
+ obex->can_activate = true;
+
+
+ DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
+ obex->port_num,
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ obex->port.in->name, obex->port.out->name);
+
+ return 0;
+
+fail:
+ /* we might as well release our claims on endpoints */
+ if (obex->port.out)
+ obex->port.out->driver_data = NULL;
+ if (obex->port.in)
+ obex->port.in->driver_data = NULL;
+
+ ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
+
+ return status;
+}
+
+static void
+obex_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+ kfree(func_to_obex(f));
+}
+
+/* Some controllers can't support CDC OBEX ... */
+static inline bool can_support_obex(struct usb_configuration *c)
+{
+ /* Since the first interface is a NOP, we can ignore the
+ * issue of multi-interface support on most controllers.
+ *
+ * Altsettings are mandatory, however...
+ */
+ if (!gadget_supports_altsettings(c->cdev->gadget))
+ return false;
+
+ /* everything else is *probably* fine ... */
+ return true;
+}
+
+/**
+ * obex_bind_config - add a CDC OBEX function to a configuration
+ * @c: the configuration to support the CDC OBEX instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds. Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
+{
+ struct f_obex *obex;
+ int status;
+
+ if (!can_support_obex(c))
+ return -EINVAL;
+
+ /* maybe allocate device-global string IDs, and patch descriptors */
+ if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ obex_string_defs[OBEX_CTRL_IDX].id = status;
+
+ obex_control_intf.iInterface = status;
+
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ obex_string_defs[OBEX_DATA_IDX].id = status;
+
+ obex_data_nop_intf.iInterface =
+ obex_data_intf.iInterface = status;
+ }
+
+ /* allocate and initialize one new instance */
+ obex = kzalloc(sizeof *obex, GFP_KERNEL);
+ if (!obex)
+ return -ENOMEM;
+
+ obex->port_num = port_num;
+
+ obex->port.connect = obex_connect;
+ obex->port.disconnect = obex_disconnect;
+
+ obex->port.func.name = "obex";
+ obex->port.func.strings = obex_strings;
+ /* descriptors are per-instance copies */
+ obex->port.func.bind = obex_bind;
+ obex->port.func.unbind = obex_unbind;
+ obex->port.func.set_alt = obex_set_alt;
+ obex->port.func.get_alt = obex_get_alt;
+ obex->port.func.disable = obex_disable;
+
+ status = usb_add_function(c, &obex->port.func);
+ if (status)
+ kfree(obex);
+
+ return status;
+}
+
+MODULE_AUTHOR("Felipe Balbi");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index f18c3a14d72..dc84d26d283 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -552,7 +552,6 @@ static struct usb_configuration sourcesink_driver = {
.setup = sourcesink_setup,
.bConfigurationValue = 3,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
/* .iConfiguration = DYNAMIC */
};
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index acb8d233aa1..fe183287577 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -103,8 +103,8 @@ static struct usb_interface_descriptor subset_data_intf __initdata = {
/* .iInterface = DYNAMIC */
};
-static struct usb_cdc_header_desc header_desc __initdata = {
- .bLength = sizeof header_desc,
+static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+ .bLength = sizeof mdlm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@@ -152,7 +152,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = {
/* full speed support: */
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -160,7 +160,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -170,18 +170,18 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
static struct usb_descriptor_header *fs_eth_function[] __initdata = {
(struct usb_descriptor_header *) &subset_data_intf,
- (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
(struct usb_descriptor_header *) &mdlm_detail_desc,
(struct usb_descriptor_header *) &ether_desc,
- (struct usb_descriptor_header *) &fs_in_desc,
- (struct usb_descriptor_header *) &fs_out_desc,
+ (struct usb_descriptor_header *) &fs_subset_in_desc,
+ (struct usb_descriptor_header *) &fs_subset_out_desc,
NULL,
};
/* high speed support: */
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -189,7 +189,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -199,12 +199,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
static struct usb_descriptor_header *hs_eth_function[] __initdata = {
(struct usb_descriptor_header *) &subset_data_intf,
- (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
(struct usb_descriptor_header *) &mdlm_detail_desc,
(struct usb_descriptor_header *) &ether_desc,
- (struct usb_descriptor_header *) &hs_in_desc,
- (struct usb_descriptor_header *) &hs_out_desc,
+ (struct usb_descriptor_header *) &hs_subset_in_desc,
+ (struct usb_descriptor_header *) &hs_subset_out_desc,
NULL,
};
@@ -281,13 +281,13 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENODEV;
/* allocate instance-specific endpoints */
- ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_in_desc);
if (!ep)
goto fail;
geth->port.in_ep = ep;
ep->driver_data = cdev; /* claim */
- ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
if (!ep)
goto fail;
geth->port.out_ep = ep;
@@ -297,9 +297,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
f->descriptors = usb_copy_descriptors(fs_eth_function);
geth->fs.in = usb_find_endpoint(fs_eth_function,
- f->descriptors, &fs_in_desc);
+ f->descriptors, &fs_subset_in_desc);
geth->fs.out = usb_find_endpoint(fs_eth_function,
- f->descriptors, &fs_out_desc);
+ f->descriptors, &fs_subset_out_desc);
/* support all relevant hardware speeds... we expect that when
@@ -307,18 +307,18 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_in_desc.bEndpointAddress =
- fs_in_desc.bEndpointAddress;
- hs_out_desc.bEndpointAddress =
- fs_out_desc.bEndpointAddress;
+ hs_subset_in_desc.bEndpointAddress =
+ fs_subset_in_desc.bEndpointAddress;
+ hs_subset_out_desc.bEndpointAddress =
+ fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
geth->hs.in = usb_find_endpoint(hs_eth_function,
- f->hs_descriptors, &hs_in_desc);
+ f->hs_descriptors, &hs_subset_in_desc);
geth->hs.out = usb_find_endpoint(hs_eth_function,
- f->hs_descriptors, &hs_out_desc);
+ f->hs_descriptors, &hs_subset_out_desc);
}
/* NOTE: all that is done without knowing or caring about
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea2c31d1808..c4e62a6297d 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -245,6 +245,18 @@
#include "gadget_chips.h"
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
/*-------------------------------------------------------------------------*/
#define DRIVER_DESC "File-backed Storage Gadget"
@@ -839,7 +851,7 @@ config_desc = {
.bConfigurationValue = CONFIG_VALUE,
.iConfiguration = STRING_CONFIG,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, // self-powered
+ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
};
static struct usb_otg_descriptor
@@ -2664,11 +2676,24 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
/* Verify the length of the command itself */
if (cmnd_size != fsg->cmnd_size) {
- /* Special case workaround: MS-Windows issues REQUEST SENSE
- * with cbw->Length == 12 (it should be 6). */
- if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12)
+ /* Special case workaround: There are plenty of buggy SCSI
+ * implementations. Many have issues with cbw->Length
+ * field passing a wrong command size. For those cases we
+ * always try to work around the problem by using the length
+ * sent by the host side provided it is at least as large
+ * as the correct command length.
+ * Examples of such cases would be MS-Windows, which issues
+ * REQUEST SENSE with cbw->Length == 12 where it should
+ * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
+ * REQUEST SENSE with cbw->Length == 10 where it should
+ * be 6 as well.
+ */
+ if (cmnd_size <= fsg->cmnd_size) {
+ DBG(fsg, "%s is buggy! Expected length %d "
+ "but we got %d\n", name,
+ cmnd_size, fsg->cmnd_size);
cmnd_size = fsg->cmnd_size;
- else {
+ } else {
fsg->phase_error = 1;
return -EINVAL;
}
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
new file mode 100644
index 00000000000..1fe8b44787b
--- /dev/null
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -0,0 +1,2760 @@
+/*
+ * driver/usb/gadget/fsl_qe_udc.c
+ *
+ * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Xie Xiaobo <X.Xie@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ * Based on bareboard code from Shlomi Gridish.
+ *
+ * Description:
+ * Freescle QE/CPM USB Pheripheral Controller Driver
+ * The controller can be found on MPC8360, MPC8272, and etc.
+ * MPC8360 Rev 1.1 may need QE mircocode update
+ *
+ * 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.
+ */
+
+#undef USB_TRACE
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/moduleparam.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <asm/qe.h>
+#include <asm/cpm.h>
+#include <asm/dma.h>
+#include <asm/reg.h>
+#include "fsl_qe_udc.h"
+
+#define DRIVER_DESC "Freescale QE/CPM USB Device Controller driver"
+#define DRIVER_AUTHOR "Xie XiaoBo"
+#define DRIVER_VERSION "1.0"
+
+#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+static const char driver_name[] = "fsl_qe_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+/*ep name is important in gadget, it should obey the convention of ep_match()*/
+static const char *const ep_name[] = {
+ "ep0-control", /* everyone has ep0 */
+ /* 3 configurable endpoints */
+ "ep1",
+ "ep2",
+ "ep3",
+};
+
+static struct usb_endpoint_descriptor qe_ep0_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = 0,
+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+ .wMaxPacketSize = USB_MAX_CTRL_PAYLOAD,
+};
+
+/* it is initialized in probe() */
+static struct qe_udc *udc_controller;
+
+/********************************************************************
+ * Internal Used Function Start
+********************************************************************/
+/*-----------------------------------------------------------------
+ * done() - retire a request; caller blocked irqs
+ *--------------------------------------------------------------*/
+static void done(struct qe_ep *ep, struct qe_req *req, int status)
+{
+ struct qe_udc *udc = ep->udc;
+ unsigned char stopped = ep->stopped;
+
+ /* the req->queue pointer is used by ep_queue() func, in which
+ * the request will be added into a udc_ep->queue 'd tail
+ * so here the req will be dropped from the ep->queue
+ */
+ list_del_init(&req->queue);
+
+ /* req.status should be set as -EINPROGRESS in ep_queue() */
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ if (req->mapped) {
+ dma_unmap_single(udc->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ ep_is_in(ep)
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ req->req.dma = DMA_ADDR_INVALID;
+ req->mapped = 0;
+ } else
+ dma_sync_single_for_cpu(udc->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ ep_is_in(ep)
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+
+ if (status && (status != -ESHUTDOWN))
+ dev_vdbg(udc->dev, "complete %s req %p stat %d len %u/%u\n",
+ ep->ep.name, &req->req, status,
+ req->req.actual, req->req.length);
+
+ /* don't modify queue heads during completion callback */
+ ep->stopped = 1;
+ spin_unlock(&udc->lock);
+
+ /* this complete() should a func implemented by gadget layer,
+ * eg fsg->bulk_in_complete() */
+ if (req->req.complete)
+ req->req.complete(&ep->ep, &req->req);
+
+ spin_lock(&udc->lock);
+
+ ep->stopped = stopped;
+}
+
+/*-----------------------------------------------------------------
+ * nuke(): delete all requests related to this ep
+ *--------------------------------------------------------------*/
+static void nuke(struct qe_ep *ep, int status)
+{
+ /* Whether this eq has request linked */
+ while (!list_empty(&ep->queue)) {
+ struct qe_req *req = NULL;
+ req = list_entry(ep->queue.next, struct qe_req, queue);
+
+ done(ep, req, status);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USB and Endpoint manipulate process, include parameter and register *
+ *---------------------------------------------------------------------------*/
+/* @value: 1--set stall 0--clean stall */
+static int qe_eprx_stall_change(struct qe_ep *ep, int value)
+{
+ u16 tem_usep;
+ u8 epnum = ep->epnum;
+ struct qe_udc *udc = ep->udc;
+
+ tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
+ tem_usep = tem_usep & ~USB_RHS_MASK;
+ if (value == 1)
+ tem_usep |= USB_RHS_STALL;
+ else if (ep->dir == USB_DIR_IN)
+ tem_usep |= USB_RHS_IGNORE_OUT;
+
+ out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
+ return 0;
+}
+
+static int qe_eptx_stall_change(struct qe_ep *ep, int value)
+{
+ u16 tem_usep;
+ u8 epnum = ep->epnum;
+ struct qe_udc *udc = ep->udc;
+
+ tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
+ tem_usep = tem_usep & ~USB_THS_MASK;
+ if (value == 1)
+ tem_usep |= USB_THS_STALL;
+ else if (ep->dir == USB_DIR_OUT)
+ tem_usep |= USB_THS_IGNORE_IN;
+
+ out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
+
+ return 0;
+}
+
+static int qe_ep0_stall(struct qe_udc *udc)
+{
+ qe_eptx_stall_change(&udc->eps[0], 1);
+ qe_eprx_stall_change(&udc->eps[0], 1);
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
+ udc_controller->ep0_dir = 0;
+ return 0;
+}
+
+static int qe_eprx_nack(struct qe_ep *ep)
+{
+ u8 epnum = ep->epnum;
+ struct qe_udc *udc = ep->udc;
+
+ if (ep->state == EP_STATE_IDLE) {
+ /* Set the ep's nack */
+ clrsetbits_be16(&udc->usb_regs->usb_usep[epnum],
+ USB_RHS_MASK, USB_RHS_NACK);
+
+ /* Mask Rx and Busy interrupts */
+ clrbits16(&udc->usb_regs->usb_usbmr,
+ (USB_E_RXB_MASK | USB_E_BSY_MASK));
+
+ ep->state = EP_STATE_NACK;
+ }
+ return 0;
+}
+
+static int qe_eprx_normal(struct qe_ep *ep)
+{
+ struct qe_udc *udc = ep->udc;
+
+ if (ep->state == EP_STATE_NACK) {
+ clrsetbits_be16(&udc->usb_regs->usb_usep[ep->epnum],
+ USB_RTHS_MASK, USB_THS_IGNORE_IN);
+
+ /* Unmask RX interrupts */
+ out_be16(&udc->usb_regs->usb_usber,
+ USB_E_BSY_MASK | USB_E_RXB_MASK);
+ setbits16(&udc->usb_regs->usb_usbmr,
+ (USB_E_RXB_MASK | USB_E_BSY_MASK));
+
+ ep->state = EP_STATE_IDLE;
+ ep->has_data = 0;
+ }
+
+ return 0;
+}
+
+static int qe_ep_cmd_stoptx(struct qe_ep *ep)
+{
+ if (ep->udc->soc_type == PORT_CPM)
+ cpm_command(CPM_USB_STOP_TX | (ep->epnum << CPM_USB_EP_SHIFT),
+ CPM_USB_STOP_TX_OPCODE);
+ else
+ qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB,
+ ep->epnum, 0);
+
+ return 0;
+}
+
+static int qe_ep_cmd_restarttx(struct qe_ep *ep)
+{
+ if (ep->udc->soc_type == PORT_CPM)
+ cpm_command(CPM_USB_RESTART_TX | (ep->epnum <<
+ CPM_USB_EP_SHIFT), CPM_USB_RESTART_TX_OPCODE);
+ else
+ qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB,
+ ep->epnum, 0);
+
+ return 0;
+}
+
+static int qe_ep_flushtxfifo(struct qe_ep *ep)
+{
+ struct qe_udc *udc = ep->udc;
+ int i;
+
+ i = (int)ep->epnum;
+
+ qe_ep_cmd_stoptx(ep);
+ out_8(&udc->usb_regs->usb_uscom,
+ USB_CMD_FLUSH_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
+ out_be16(&udc->ep_param[i]->tbptr, in_be16(&udc->ep_param[i]->tbase));
+ out_be32(&udc->ep_param[i]->tstate, 0);
+ out_be16(&udc->ep_param[i]->tbcnt, 0);
+
+ ep->c_txbd = ep->txbase;
+ ep->n_txbd = ep->txbase;
+ qe_ep_cmd_restarttx(ep);
+ return 0;
+}
+
+static int qe_ep_filltxfifo(struct qe_ep *ep)
+{
+ struct qe_udc *udc = ep->udc;
+
+ out_8(&udc->usb_regs->usb_uscom,
+ USB_CMD_STR_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
+ return 0;
+}
+
+static int qe_epbds_reset(struct qe_udc *udc, int pipe_num)
+{
+ struct qe_ep *ep;
+ u32 bdring_len;
+ struct qe_bd __iomem *bd;
+ int i;
+
+ ep = &udc->eps[pipe_num];
+
+ if (ep->dir == USB_DIR_OUT)
+ bdring_len = USB_BDRING_LEN_RX;
+ else
+ bdring_len = USB_BDRING_LEN;
+
+ bd = ep->rxbase;
+ for (i = 0; i < (bdring_len - 1); i++) {
+ out_be32((u32 __iomem *)bd, R_E | R_I);
+ bd++;
+ }
+ out_be32((u32 __iomem *)bd, R_E | R_I | R_W);
+
+ bd = ep->txbase;
+ for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
+ out_be32(&bd->buf, 0);
+ out_be32((u32 __iomem *)bd, 0);
+ bd++;
+ }
+ out_be32((u32 __iomem *)bd, T_W);
+
+ return 0;
+}
+
+static int qe_ep_reset(struct qe_udc *udc, int pipe_num)
+{
+ struct qe_ep *ep;
+ u16 tmpusep;
+
+ ep = &udc->eps[pipe_num];
+ tmpusep = in_be16(&udc->usb_regs->usb_usep[pipe_num]);
+ tmpusep &= ~USB_RTHS_MASK;
+
+ switch (ep->dir) {
+ case USB_DIR_BOTH:
+ qe_ep_flushtxfifo(ep);
+ break;
+ case USB_DIR_OUT:
+ tmpusep |= USB_THS_IGNORE_IN;
+ break;
+ case USB_DIR_IN:
+ qe_ep_flushtxfifo(ep);
+ tmpusep |= USB_RHS_IGNORE_OUT;
+ break;
+ default:
+ break;
+ }
+ out_be16(&udc->usb_regs->usb_usep[pipe_num], tmpusep);
+
+ qe_epbds_reset(udc, pipe_num);
+
+ return 0;
+}
+
+static int qe_ep_toggledata01(struct qe_ep *ep)
+{
+ ep->data01 ^= 0x1;
+ return 0;
+}
+
+static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num)
+{
+ struct qe_ep *ep = &udc->eps[pipe_num];
+ unsigned long tmp_addr = 0;
+ struct usb_ep_para __iomem *epparam;
+ int i;
+ struct qe_bd __iomem *bd;
+ int bdring_len;
+
+ if (ep->dir == USB_DIR_OUT)
+ bdring_len = USB_BDRING_LEN_RX;
+ else
+ bdring_len = USB_BDRING_LEN;
+
+ epparam = udc->ep_param[pipe_num];
+ /* alloc multi-ram for BD rings and set the ep parameters */
+ tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len +
+ USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD);
+ out_be16(&epparam->rbase, (u16)tmp_addr);
+ out_be16(&epparam->tbase, (u16)(tmp_addr +
+ (sizeof(struct qe_bd) * bdring_len)));
+
+ out_be16(&epparam->rbptr, in_be16(&epparam->rbase));
+ out_be16(&epparam->tbptr, in_be16(&epparam->tbase));
+
+ ep->rxbase = cpm_muram_addr(tmp_addr);
+ ep->txbase = cpm_muram_addr(tmp_addr + (sizeof(struct qe_bd)
+ * bdring_len));
+ ep->n_rxbd = ep->rxbase;
+ ep->e_rxbd = ep->rxbase;
+ ep->n_txbd = ep->txbase;
+ ep->c_txbd = ep->txbase;
+ ep->data01 = 0; /* data0 */
+
+ /* Init TX and RX bds */
+ bd = ep->rxbase;
+ for (i = 0; i < bdring_len - 1; i++) {
+ out_be32(&bd->buf, 0);
+ out_be32((u32 __iomem *)bd, 0);
+ bd++;
+ }
+ out_be32(&bd->buf, 0);
+ out_be32((u32 __iomem *)bd, R_W);
+
+ bd = ep->txbase;
+ for (i = 0; i < USB_BDRING_LEN_TX - 1; i++) {
+ out_be32(&bd->buf, 0);
+ out_be32((u32 __iomem *)bd, 0);
+ bd++;
+ }
+ out_be32(&bd->buf, 0);
+ out_be32((u32 __iomem *)bd, T_W);
+
+ return 0;
+}
+
+static int qe_ep_rxbd_update(struct qe_ep *ep)
+{
+ unsigned int size;
+ int i;
+ unsigned int tmp;
+ struct qe_bd __iomem *bd;
+ unsigned int bdring_len;
+
+ if (ep->rxbase == NULL)
+ return -EINVAL;
+
+ bd = ep->rxbase;
+
+ ep->rxframe = kmalloc(sizeof(*ep->rxframe), GFP_ATOMIC);
+ if (ep->rxframe == NULL) {
+ dev_err(ep->udc->dev, "malloc rxframe failed\n");
+ return -ENOMEM;
+ }
+
+ qe_frame_init(ep->rxframe);
+
+ if (ep->dir == USB_DIR_OUT)
+ bdring_len = USB_BDRING_LEN_RX;
+ else
+ bdring_len = USB_BDRING_LEN;
+
+ size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1);
+ ep->rxbuffer = kzalloc(size, GFP_ATOMIC);
+ if (ep->rxbuffer == NULL) {
+ dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n",
+ size);
+ kfree(ep->rxframe);
+ return -ENOMEM;
+ }
+
+ ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
+ if (ep->rxbuf_d == DMA_ADDR_INVALID) {
+ ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent,
+ ep->rxbuffer,
+ size,
+ DMA_FROM_DEVICE);
+ ep->rxbufmap = 1;
+ } else {
+ dma_sync_single_for_device(udc_controller->gadget.dev.parent,
+ ep->rxbuf_d, size,
+ DMA_FROM_DEVICE);
+ ep->rxbufmap = 0;
+ }
+
+ size = ep->ep.maxpacket + USB_CRC_SIZE + 2;
+ tmp = ep->rxbuf_d;
+ tmp = (u32)(((tmp >> 2) << 2) + 4);
+
+ for (i = 0; i < bdring_len - 1; i++) {
+ out_be32(&bd->buf, tmp);
+ out_be32((u32 __iomem *)bd, (R_E | R_I));
+ tmp = tmp + size;
+ bd++;
+ }
+ out_be32(&bd->buf, tmp);
+ out_be32((u32 __iomem *)bd, (R_E | R_I | R_W));
+
+ return 0;
+}
+
+static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
+{
+ struct qe_ep *ep = &udc->eps[pipe_num];
+ struct usb_ep_para __iomem *epparam;
+ u16 usep, logepnum;
+ u16 tmp;
+ u8 rtfcr = 0;
+
+ epparam = udc->ep_param[pipe_num];
+
+ usep = 0;
+ logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ usep |= (logepnum << USB_EPNUM_SHIFT);
+
+ switch (ep->desc->bmAttributes & 0x03) {
+ case USB_ENDPOINT_XFER_BULK:
+ usep |= USB_TRANS_BULK;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ usep |= USB_TRANS_ISO;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ usep |= USB_TRANS_INT;
+ break;
+ default:
+ usep |= USB_TRANS_CTR;
+ break;
+ }
+
+ switch (ep->dir) {
+ case USB_DIR_OUT:
+ usep |= USB_THS_IGNORE_IN;
+ break;
+ case USB_DIR_IN:
+ usep |= USB_RHS_IGNORE_OUT;
+ break;
+ default:
+ break;
+ }
+ out_be16(&udc->usb_regs->usb_usep[pipe_num], usep);
+
+ rtfcr = 0x30;
+ out_8(&epparam->rbmr, rtfcr);
+ out_8(&epparam->tbmr, rtfcr);
+
+ tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
+ /* MRBLR must be divisble by 4 */
+ tmp = (u16)(((tmp >> 2) << 2) + 4);
+ out_be16(&epparam->mrblr, tmp);
+
+ return 0;
+}
+
+static int qe_ep_init(struct qe_udc *udc,
+ unsigned char pipe_num,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct qe_ep *ep = &udc->eps[pipe_num];
+ unsigned long flags;
+ int reval = 0;
+ u16 max = 0;
+
+ max = le16_to_cpu(desc->wMaxPacketSize);
+
+ /* check the max package size validate for this endpoint */
+ /* Refer to USB2.0 spec table 9-13,
+ */
+ if (pipe_num != 0) {
+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_BULK:
+ if (strstr(ep->ep.name, "-iso")
+ || strstr(ep->ep.name, "-int"))
+ goto en_done;
+ switch (udc->gadget.speed) {
+ case USB_SPEED_HIGH:
+ if ((max == 128) || (max == 256) || (max == 512))
+ break;
+ default:
+ switch (max) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ break;
+ default:
+ case USB_SPEED_LOW:
+ goto en_done;
+ }
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
+ goto en_done;
+ switch (udc->gadget.speed) {
+ case USB_SPEED_HIGH:
+ if (max <= 1024)
+ break;
+ case USB_SPEED_FULL:
+ if (max <= 64)
+ break;
+ default:
+ if (max <= 8)
+ break;
+ goto en_done;
+ }
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (strstr(ep->ep.name, "-bulk")
+ || strstr(ep->ep.name, "-int"))
+ goto en_done;
+ switch (udc->gadget.speed) {
+ case USB_SPEED_HIGH:
+ if (max <= 1024)
+ break;
+ case USB_SPEED_FULL:
+ if (max <= 1023)
+ break;
+ default:
+ goto en_done;
+ }
+ break;
+ case USB_ENDPOINT_XFER_CONTROL:
+ if (strstr(ep->ep.name, "-iso")
+ || strstr(ep->ep.name, "-int"))
+ goto en_done;
+ switch (udc->gadget.speed) {
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ switch (max) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ break;
+ default:
+ goto en_done;
+ }
+ case USB_SPEED_LOW:
+ switch (max) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ goto en_done;
+ }
+ default:
+ goto en_done;
+ }
+ break;
+
+ default:
+ goto en_done;
+ }
+ } /* if ep0*/
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /* initialize ep structure */
+ ep->ep.maxpacket = max;
+ ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+ ep->desc = desc;
+ ep->stopped = 0;
+ ep->init = 1;
+
+ if (pipe_num == 0) {
+ ep->dir = USB_DIR_BOTH;
+ udc->ep0_dir = USB_DIR_OUT;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ } else {
+ switch (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+ case USB_DIR_OUT:
+ ep->dir = USB_DIR_OUT;
+ break;
+ case USB_DIR_IN:
+ ep->dir = USB_DIR_IN;
+ default:
+ break;
+ }
+ }
+
+ /* hardware special operation */
+ qe_ep_bd_init(udc, pipe_num);
+ if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_OUT)) {
+ reval = qe_ep_rxbd_update(ep);
+ if (reval)
+ goto en_done1;
+ }
+
+ if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) {
+ ep->txframe = kmalloc(sizeof(*ep->txframe), GFP_ATOMIC);
+ if (ep->txframe == NULL) {
+ dev_err(udc->dev, "malloc txframe failed\n");
+ goto en_done2;
+ }
+ qe_frame_init(ep->txframe);
+ }
+
+ qe_ep_register_init(udc, pipe_num);
+
+ /* Now HW will be NAKing transfers to that EP,
+ * until a buffer is queued to it. */
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+en_done2:
+ kfree(ep->rxbuffer);
+ kfree(ep->rxframe);
+en_done1:
+ spin_unlock_irqrestore(&udc->lock, flags);
+en_done:
+ dev_dbg(udc->dev, "failed to initialize %s\n", ep->ep.name);
+ return -ENODEV;
+}
+
+static inline void qe_usb_enable(void)
+{
+ setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+}
+
+static inline void qe_usb_disable(void)
+{
+ clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+}
+
+/*----------------------------------------------------------------------------*
+ * USB and EP basic manipulate function end *
+ *----------------------------------------------------------------------------*/
+
+
+/******************************************************************************
+ UDC transmit and receive process
+ ******************************************************************************/
+static void recycle_one_rxbd(struct qe_ep *ep)
+{
+ u32 bdstatus;
+
+ bdstatus = in_be32((u32 __iomem *)ep->e_rxbd);
+ bdstatus = R_I | R_E | (bdstatus & R_W);
+ out_be32((u32 __iomem *)ep->e_rxbd, bdstatus);
+
+ if (bdstatus & R_W)
+ ep->e_rxbd = ep->rxbase;
+ else
+ ep->e_rxbd++;
+}
+
+static void recycle_rxbds(struct qe_ep *ep, unsigned char stopatnext)
+{
+ u32 bdstatus;
+ struct qe_bd __iomem *bd, *nextbd;
+ unsigned char stop = 0;
+
+ nextbd = ep->n_rxbd;
+ bd = ep->e_rxbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+
+ while (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK) && !stop) {
+ bdstatus = R_E | R_I | (bdstatus & R_W);
+ out_be32((u32 __iomem *)bd, bdstatus);
+
+ if (bdstatus & R_W)
+ bd = ep->rxbase;
+ else
+ bd++;
+
+ bdstatus = in_be32((u32 __iomem *)bd);
+ if (stopatnext && (bd == nextbd))
+ stop = 1;
+ }
+
+ ep->e_rxbd = bd;
+}
+
+static void ep_recycle_rxbds(struct qe_ep *ep)
+{
+ struct qe_bd __iomem *bd = ep->n_rxbd;
+ u32 bdstatus;
+ u8 epnum = ep->epnum;
+ struct qe_udc *udc = ep->udc;
+
+ bdstatus = in_be32((u32 __iomem *)bd);
+ if (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK)) {
+ bd = ep->rxbase +
+ ((in_be16(&udc->ep_param[epnum]->rbptr) -
+ in_be16(&udc->ep_param[epnum]->rbase))
+ >> 3);
+ bdstatus = in_be32((u32 __iomem *)bd);
+
+ if (bdstatus & R_W)
+ bd = ep->rxbase;
+ else
+ bd++;
+
+ ep->e_rxbd = bd;
+ recycle_rxbds(ep, 0);
+ ep->e_rxbd = ep->n_rxbd;
+ } else
+ recycle_rxbds(ep, 1);
+
+ if (in_be16(&udc->usb_regs->usb_usber) & USB_E_BSY_MASK)
+ out_be16(&udc->usb_regs->usb_usber, USB_E_BSY_MASK);
+
+ if (ep->has_data <= 0 && (!list_empty(&ep->queue)))
+ qe_eprx_normal(ep);
+
+ ep->localnack = 0;
+}
+
+static void setup_received_handle(struct qe_udc *udc,
+ struct usb_ctrlrequest *setup);
+static int qe_ep_rxframe_handle(struct qe_ep *ep);
+static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req);
+/* when BD PID is setup, handle the packet */
+static int ep0_setup_handle(struct qe_udc *udc)
+{
+ struct qe_ep *ep = &udc->eps[0];
+ struct qe_frame *pframe;
+ unsigned int fsize;
+ u8 *cp;
+
+ pframe = ep->rxframe;
+ if ((frame_get_info(pframe) & PID_SETUP)
+ && (udc->ep0_state == WAIT_FOR_SETUP)) {
+ fsize = frame_get_length(pframe);
+ if (unlikely(fsize != 8))
+ return -EINVAL;
+ cp = (u8 *)&udc->local_setup_buff;
+ memcpy(cp, pframe->data, fsize);
+ ep->data01 = 1;
+
+ /* handle the usb command base on the usb_ctrlrequest */
+ setup_received_handle(udc, &udc->local_setup_buff);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int qe_ep0_rx(struct qe_udc *udc)
+{
+ struct qe_ep *ep = &udc->eps[0];
+ struct qe_frame *pframe;
+ struct qe_bd __iomem *bd;
+ u32 bdstatus, length;
+ u32 vaddr;
+
+ pframe = ep->rxframe;
+
+ if (ep->dir == USB_DIR_IN) {
+ dev_err(udc->dev, "ep0 not a control endpoint\n");
+ return -EINVAL;
+ }
+
+ bd = ep->n_rxbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+
+ while (!(bdstatus & R_E) && length) {
+ if ((bdstatus & R_F) && (bdstatus & R_L)
+ && !(bdstatus & R_ERROR)) {
+ if (length == USB_CRC_SIZE) {
+ udc->ep0_state = WAIT_FOR_SETUP;
+ dev_vdbg(udc->dev,
+ "receive a ZLP in status phase\n");
+ } else {
+ qe_frame_clean(pframe);
+ vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+ frame_set_data(pframe, (u8 *)vaddr);
+ frame_set_length(pframe,
+ (length - USB_CRC_SIZE));
+ frame_set_status(pframe, FRAME_OK);
+ switch (bdstatus & R_PID) {
+ case R_PID_SETUP:
+ frame_set_info(pframe, PID_SETUP);
+ break;
+ case R_PID_DATA1:
+ frame_set_info(pframe, PID_DATA1);
+ break;
+ default:
+ frame_set_info(pframe, PID_DATA0);
+ break;
+ }
+
+ if ((bdstatus & R_PID) == R_PID_SETUP)
+ ep0_setup_handle(udc);
+ else
+ qe_ep_rxframe_handle(ep);
+ }
+ } else {
+ dev_err(udc->dev, "The receive frame with error!\n");
+ }
+
+ /* note: don't clear the rxbd's buffer address */
+ recycle_one_rxbd(ep);
+
+ /* Get next BD */
+ if (bdstatus & R_W)
+ bd = ep->rxbase;
+ else
+ bd++;
+
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+
+ }
+
+ ep->n_rxbd = bd;
+
+ return 0;
+}
+
+static int qe_ep_rxframe_handle(struct qe_ep *ep)
+{
+ struct qe_frame *pframe;
+ u8 framepid = 0;
+ unsigned int fsize;
+ u8 *cp;
+ struct qe_req *req;
+
+ pframe = ep->rxframe;
+
+ if (frame_get_info(pframe) & PID_DATA1)
+ framepid = 0x1;
+
+ if (framepid != ep->data01) {
+ dev_err(ep->udc->dev, "the data01 error!\n");
+ return -EIO;
+ }
+
+ fsize = frame_get_length(pframe);
+ if (list_empty(&ep->queue)) {
+ dev_err(ep->udc->dev, "the %s have no requeue!\n", ep->name);
+ } else {
+ req = list_entry(ep->queue.next, struct qe_req, queue);
+
+ cp = (u8 *)(req->req.buf) + req->req.actual;
+ if (cp) {
+ memcpy(cp, pframe->data, fsize);
+ req->req.actual += fsize;
+ if ((fsize < ep->ep.maxpacket) ||
+ (req->req.actual >= req->req.length)) {
+ if (ep->epnum == 0)
+ ep0_req_complete(ep->udc, req);
+ else
+ done(ep, req, 0);
+ if (list_empty(&ep->queue) && ep->epnum != 0)
+ qe_eprx_nack(ep);
+ }
+ }
+ }
+
+ qe_ep_toggledata01(ep);
+
+ return 0;
+}
+
+static void ep_rx_tasklet(unsigned long data)
+{
+ struct qe_udc *udc = (struct qe_udc *)data;
+ struct qe_ep *ep;
+ struct qe_frame *pframe;
+ struct qe_bd __iomem *bd;
+ unsigned long flags;
+ u32 bdstatus, length;
+ u32 vaddr, i;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ for (i = 1; i < USB_MAX_ENDPOINTS; i++) {
+ ep = &udc->eps[i];
+
+ if (ep->dir == USB_DIR_IN || ep->enable_tasklet == 0) {
+ dev_dbg(udc->dev,
+ "This is a transmit ep or disable tasklet!\n");
+ continue;
+ }
+
+ pframe = ep->rxframe;
+ bd = ep->n_rxbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+
+ while (!(bdstatus & R_E) && length) {
+ if (list_empty(&ep->queue)) {
+ qe_eprx_nack(ep);
+ dev_dbg(udc->dev,
+ "The rxep have noreq %d\n",
+ ep->has_data);
+ break;
+ }
+
+ if ((bdstatus & R_F) && (bdstatus & R_L)
+ && !(bdstatus & R_ERROR)) {
+ qe_frame_clean(pframe);
+ vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+ frame_set_data(pframe, (u8 *)vaddr);
+ frame_set_length(pframe,
+ (length - USB_CRC_SIZE));
+ frame_set_status(pframe, FRAME_OK);
+ switch (bdstatus & R_PID) {
+ case R_PID_DATA1:
+ frame_set_info(pframe, PID_DATA1);
+ break;
+ case R_PID_SETUP:
+ frame_set_info(pframe, PID_SETUP);
+ break;
+ default:
+ frame_set_info(pframe, PID_DATA0);
+ break;
+ }
+ /* handle the rx frame */
+ qe_ep_rxframe_handle(ep);
+ } else {
+ dev_err(udc->dev,
+ "error in received frame\n");
+ }
+ /* note: don't clear the rxbd's buffer address */
+ /*clear the length */
+ out_be32((u32 __iomem *)bd, bdstatus & BD_STATUS_MASK);
+ ep->has_data--;
+ if (!(ep->localnack))
+ recycle_one_rxbd(ep);
+
+ /* Get next BD */
+ if (bdstatus & R_W)
+ bd = ep->rxbase;
+ else
+ bd++;
+
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+ }
+
+ ep->n_rxbd = bd;
+
+ if (ep->localnack)
+ ep_recycle_rxbds(ep);
+
+ ep->enable_tasklet = 0;
+ } /* for i=1 */
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+}
+
+static int qe_ep_rx(struct qe_ep *ep)
+{
+ struct qe_udc *udc;
+ struct qe_frame *pframe;
+ struct qe_bd __iomem *bd;
+ u16 swoffs, ucoffs, emptybds;
+
+ udc = ep->udc;
+ pframe = ep->rxframe;
+
+ if (ep->dir == USB_DIR_IN) {
+ dev_err(udc->dev, "transmit ep in rx function\n");
+ return -EINVAL;
+ }
+
+ bd = ep->n_rxbd;
+
+ swoffs = (u16)(bd - ep->rxbase);
+ ucoffs = (u16)((in_be16(&udc->ep_param[ep->epnum]->rbptr) -
+ in_be16(&udc->ep_param[ep->epnum]->rbase)) >> 3);
+ if (swoffs < ucoffs)
+ emptybds = USB_BDRING_LEN_RX - ucoffs + swoffs;
+ else
+ emptybds = swoffs - ucoffs;
+
+ if (emptybds < MIN_EMPTY_BDS) {
+ qe_eprx_nack(ep);
+ ep->localnack = 1;
+ dev_vdbg(udc->dev, "%d empty bds, send NACK\n", emptybds);
+ }
+ ep->has_data = USB_BDRING_LEN_RX - emptybds;
+
+ if (list_empty(&ep->queue)) {
+ qe_eprx_nack(ep);
+ dev_vdbg(udc->dev, "The rxep have no req queued with %d BDs\n",
+ ep->has_data);
+ return 0;
+ }
+
+ tasklet_schedule(&udc->rx_tasklet);
+ ep->enable_tasklet = 1;
+
+ return 0;
+}
+
+/* send data from a frame, no matter what tx_req */
+static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame)
+{
+ struct qe_udc *udc = ep->udc;
+ struct qe_bd __iomem *bd;
+ u16 saveusbmr;
+ u32 bdstatus, pidmask;
+ u32 paddr;
+
+ if (ep->dir == USB_DIR_OUT) {
+ dev_err(udc->dev, "receive ep passed to tx function\n");
+ return -EINVAL;
+ }
+
+ /* Disable the Tx interrupt */
+ saveusbmr = in_be16(&udc->usb_regs->usb_usbmr);
+ out_be16(&udc->usb_regs->usb_usbmr,
+ saveusbmr & ~(USB_E_TXB_MASK | USB_E_TXE_MASK));
+
+ bd = ep->n_txbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+
+ if (!(bdstatus & (T_R | BD_LENGTH_MASK))) {
+ if (frame_get_length(frame) == 0) {
+ frame_set_data(frame, udc->nullbuf);
+ frame_set_length(frame, 2);
+ frame->info |= (ZLP | NO_CRC);
+ dev_vdbg(udc->dev, "the frame size = 0\n");
+ }
+ paddr = virt_to_phys((void *)frame->data);
+ out_be32(&bd->buf, paddr);
+ bdstatus = (bdstatus&T_W);
+ if (!(frame_get_info(frame) & NO_CRC))
+ bdstatus |= T_R | T_I | T_L | T_TC
+ | frame_get_length(frame);
+ else
+ bdstatus |= T_R | T_I | T_L | frame_get_length(frame);
+
+ /* if the packet is a ZLP in status phase */
+ if ((ep->epnum == 0) && (udc->ep0_state == DATA_STATE_NEED_ZLP))
+ ep->data01 = 0x1;
+
+ if (ep->data01) {
+ pidmask = T_PID_DATA1;
+ frame->info |= PID_DATA1;
+ } else {
+ pidmask = T_PID_DATA0;
+ frame->info |= PID_DATA0;
+ }
+ bdstatus |= T_CNF;
+ bdstatus |= pidmask;
+ out_be32((u32 __iomem *)bd, bdstatus);
+ qe_ep_filltxfifo(ep);
+
+ /* enable the TX interrupt */
+ out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
+
+ qe_ep_toggledata01(ep);
+ if (bdstatus & T_W)
+ ep->n_txbd = ep->txbase;
+ else
+ ep->n_txbd++;
+
+ return 0;
+ } else {
+ out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
+ dev_vdbg(udc->dev, "The tx bd is not ready!\n");
+ return -EBUSY;
+ }
+}
+
+/* when a bd was transmitted, the function can
+ * handle the tx_req, not include ep0 */
+static int txcomplete(struct qe_ep *ep, unsigned char restart)
+{
+ if (ep->tx_req != NULL) {
+ if (!restart) {
+ int asent = ep->last;
+ ep->sent += asent;
+ ep->last -= asent;
+ } else {
+ ep->last = 0;
+ }
+
+ /* a request already were transmitted completely */
+ if ((ep->tx_req->req.length - ep->sent) <= 0) {
+ ep->tx_req->req.actual = (unsigned int)ep->sent;
+ done(ep, ep->tx_req, 0);
+ ep->tx_req = NULL;
+ ep->last = 0;
+ ep->sent = 0;
+ }
+ }
+
+ /* we should gain a new tx_req fot this endpoint */
+ if (ep->tx_req == NULL) {
+ if (!list_empty(&ep->queue)) {
+ ep->tx_req = list_entry(ep->queue.next, struct qe_req,
+ queue);
+ ep->last = 0;
+ ep->sent = 0;
+ }
+ }
+
+ return 0;
+}
+
+/* give a frame and a tx_req, send some data */
+static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame)
+{
+ unsigned int size;
+ u8 *buf;
+
+ qe_frame_clean(frame);
+ size = min_t(u32, (ep->tx_req->req.length - ep->sent),
+ ep->ep.maxpacket);
+ buf = (u8 *)ep->tx_req->req.buf + ep->sent;
+ if (buf && size) {
+ ep->last = size;
+ frame_set_data(frame, buf);
+ frame_set_length(frame, size);
+ frame_set_status(frame, FRAME_OK);
+ frame_set_info(frame, 0);
+ return qe_ep_tx(ep, frame);
+ }
+ return -EIO;
+}
+
+/* give a frame struct,send a ZLP */
+static int sendnulldata(struct qe_ep *ep, struct qe_frame *frame, uint infor)
+{
+ struct qe_udc *udc = ep->udc;
+
+ if (frame == NULL)
+ return -ENODEV;
+
+ qe_frame_clean(frame);
+ frame_set_data(frame, (u8 *)udc->nullbuf);
+ frame_set_length(frame, 2);
+ frame_set_status(frame, FRAME_OK);
+ frame_set_info(frame, (ZLP | NO_CRC | infor));
+
+ return qe_ep_tx(ep, frame);
+}
+
+static int frame_create_tx(struct qe_ep *ep, struct qe_frame *frame)
+{
+ struct qe_req *req = ep->tx_req;
+ int reval;
+
+ if (req == NULL)
+ return -ENODEV;
+
+ if ((req->req.length - ep->sent) > 0)
+ reval = qe_usb_senddata(ep, frame);
+ else
+ reval = sendnulldata(ep, frame, 0);
+
+ return reval;
+}
+
+/* if direction is DIR_IN, the status is Device->Host
+ * if direction is DIR_OUT, the status transaction is Device<-Host
+ * in status phase, udc create a request and gain status */
+static int ep0_prime_status(struct qe_udc *udc, int direction)
+{
+
+ struct qe_ep *ep = &udc->eps[0];
+
+ if (direction == USB_DIR_IN) {
+ udc->ep0_state = DATA_STATE_NEED_ZLP;
+ udc->ep0_dir = USB_DIR_IN;
+ sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
+ } else {
+ udc->ep0_dir = USB_DIR_OUT;
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
+ }
+
+ return 0;
+}
+
+/* a request complete in ep0, whether gadget request or udc request */
+static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req)
+{
+ struct qe_ep *ep = &udc->eps[0];
+ /* because usb and ep's status already been set in ch9setaddress() */
+
+ switch (udc->ep0_state) {
+ case DATA_STATE_XMIT:
+ done(ep, req, 0);
+ /* receive status phase */
+ if (ep0_prime_status(udc, USB_DIR_OUT))
+ qe_ep0_stall(udc);
+ break;
+
+ case DATA_STATE_NEED_ZLP:
+ done(ep, req, 0);
+ udc->ep0_state = WAIT_FOR_SETUP;
+ break;
+
+ case DATA_STATE_RECV:
+ done(ep, req, 0);
+ /* send status phase */
+ if (ep0_prime_status(udc, USB_DIR_IN))
+ qe_ep0_stall(udc);
+ break;
+
+ case WAIT_FOR_OUT_STATUS:
+ done(ep, req, 0);
+ udc->ep0_state = WAIT_FOR_SETUP;
+ break;
+
+ case WAIT_FOR_SETUP:
+ dev_vdbg(udc->dev, "Unexpected interrupt\n");
+ break;
+
+ default:
+ qe_ep0_stall(udc);
+ break;
+ }
+}
+
+static int ep0_txcomplete(struct qe_ep *ep, unsigned char restart)
+{
+ struct qe_req *tx_req = NULL;
+ struct qe_frame *frame = ep->txframe;
+
+ if ((frame_get_info(frame) & (ZLP | NO_REQ)) == (ZLP | NO_REQ)) {
+ if (!restart)
+ ep->udc->ep0_state = WAIT_FOR_SETUP;
+ else
+ sendnulldata(ep, ep->txframe, SETUP_STATUS | NO_REQ);
+ return 0;
+ }
+
+ tx_req = ep->tx_req;
+ if (tx_req != NULL) {
+ if (!restart) {
+ int asent = ep->last;
+ ep->sent += asent;
+ ep->last -= asent;
+ } else {
+ ep->last = 0;
+ }
+
+ /* a request already were transmitted completely */
+ if ((ep->tx_req->req.length - ep->sent) <= 0) {
+ ep->tx_req->req.actual = (unsigned int)ep->sent;
+ ep0_req_complete(ep->udc, ep->tx_req);
+ ep->tx_req = NULL;
+ ep->last = 0;
+ ep->sent = 0;
+ }
+ } else {
+ dev_vdbg(ep->udc->dev, "the ep0_controller have no req\n");
+ }
+
+ return 0;
+}
+
+static int ep0_txframe_handle(struct qe_ep *ep)
+{
+ /* if have error, transmit again */
+ if (frame_get_status(ep->txframe) & FRAME_ERROR) {
+ qe_ep_flushtxfifo(ep);
+ dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
+ if (frame_get_info(ep->txframe) & PID_DATA0)
+ ep->data01 = 0;
+ else
+ ep->data01 = 1;
+
+ ep0_txcomplete(ep, 1);
+ } else
+ ep0_txcomplete(ep, 0);
+
+ frame_create_tx(ep, ep->txframe);
+ return 0;
+}
+
+static int qe_ep0_txconf(struct qe_ep *ep)
+{
+ struct qe_bd __iomem *bd;
+ struct qe_frame *pframe;
+ u32 bdstatus;
+
+ bd = ep->c_txbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
+ pframe = ep->txframe;
+
+ /* clear and recycle the BD */
+ out_be32((u32 __iomem *)bd, bdstatus & T_W);
+ out_be32(&bd->buf, 0);
+ if (bdstatus & T_W)
+ ep->c_txbd = ep->txbase;
+ else
+ ep->c_txbd++;
+
+ if (ep->c_txbd == ep->n_txbd) {
+ if (bdstatus & DEVICE_T_ERROR) {
+ frame_set_status(pframe, FRAME_ERROR);
+ if (bdstatus & T_TO)
+ pframe->status |= TX_ER_TIMEOUT;
+ if (bdstatus & T_UN)
+ pframe->status |= TX_ER_UNDERUN;
+ }
+ ep0_txframe_handle(ep);
+ }
+
+ bd = ep->c_txbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ }
+
+ return 0;
+}
+
+static int ep_txframe_handle(struct qe_ep *ep)
+{
+ if (frame_get_status(ep->txframe) & FRAME_ERROR) {
+ qe_ep_flushtxfifo(ep);
+ dev_vdbg(ep->udc->dev, "The EP0 transmit data have error!\n");
+ if (frame_get_info(ep->txframe) & PID_DATA0)
+ ep->data01 = 0;
+ else
+ ep->data01 = 1;
+
+ txcomplete(ep, 1);
+ } else
+ txcomplete(ep, 0);
+
+ frame_create_tx(ep, ep->txframe); /* send the data */
+ return 0;
+}
+
+/* confirm the already trainsmited bd */
+static int qe_ep_txconf(struct qe_ep *ep)
+{
+ struct qe_bd __iomem *bd;
+ struct qe_frame *pframe = NULL;
+ u32 bdstatus;
+ unsigned char breakonrxinterrupt = 0;
+
+ bd = ep->c_txbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
+ pframe = ep->txframe;
+ if (bdstatus & DEVICE_T_ERROR) {
+ frame_set_status(pframe, FRAME_ERROR);
+ if (bdstatus & T_TO)
+ pframe->status |= TX_ER_TIMEOUT;
+ if (bdstatus & T_UN)
+ pframe->status |= TX_ER_UNDERUN;
+ }
+
+ /* clear and recycle the BD */
+ out_be32((u32 __iomem *)bd, bdstatus & T_W);
+ out_be32(&bd->buf, 0);
+ if (bdstatus & T_W)
+ ep->c_txbd = ep->txbase;
+ else
+ ep->c_txbd++;
+
+ /* handle the tx frame */
+ ep_txframe_handle(ep);
+ bd = ep->c_txbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ }
+ if (breakonrxinterrupt)
+ return -EIO;
+ else
+ return 0;
+}
+
+/* Add a request in queue, and try to transmit a packet */
+static int ep_req_send(struct qe_ep *ep, struct qe_req *req)
+{
+ int reval = 0;
+
+ if (ep->tx_req == NULL) {
+ ep->sent = 0;
+ ep->last = 0;
+ txcomplete(ep, 0); /* can gain a new tx_req */
+ reval = frame_create_tx(ep, ep->txframe);
+ }
+ return reval;
+}
+
+/* Maybe this is a good ideal */
+static int ep_req_rx(struct qe_ep *ep, struct qe_req *req)
+{
+ struct qe_udc *udc = ep->udc;
+ struct qe_frame *pframe = NULL;
+ struct qe_bd __iomem *bd;
+ u32 bdstatus, length;
+ u32 vaddr, fsize;
+ u8 *cp;
+ u8 finish_req = 0;
+ u8 framepid;
+
+ if (list_empty(&ep->queue)) {
+ dev_vdbg(udc->dev, "the req already finish!\n");
+ return 0;
+ }
+ pframe = ep->rxframe;
+
+ bd = ep->n_rxbd;
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+
+ while (!(bdstatus & R_E) && length) {
+ if (finish_req)
+ break;
+ if ((bdstatus & R_F) && (bdstatus & R_L)
+ && !(bdstatus & R_ERROR)) {
+ qe_frame_clean(pframe);
+ vaddr = (u32)phys_to_virt(in_be32(&bd->buf));
+ frame_set_data(pframe, (u8 *)vaddr);
+ frame_set_length(pframe, (length - USB_CRC_SIZE));
+ frame_set_status(pframe, FRAME_OK);
+ switch (bdstatus & R_PID) {
+ case R_PID_DATA1:
+ frame_set_info(pframe, PID_DATA1); break;
+ default:
+ frame_set_info(pframe, PID_DATA0); break;
+ }
+ /* handle the rx frame */
+
+ if (frame_get_info(pframe) & PID_DATA1)
+ framepid = 0x1;
+ else
+ framepid = 0;
+
+ if (framepid != ep->data01) {
+ dev_vdbg(udc->dev, "the data01 error!\n");
+ } else {
+ fsize = frame_get_length(pframe);
+
+ cp = (u8 *)(req->req.buf) + req->req.actual;
+ if (cp) {
+ memcpy(cp, pframe->data, fsize);
+ req->req.actual += fsize;
+ if ((fsize < ep->ep.maxpacket)
+ || (req->req.actual >=
+ req->req.length)) {
+ finish_req = 1;
+ done(ep, req, 0);
+ if (list_empty(&ep->queue))
+ qe_eprx_nack(ep);
+ }
+ }
+ qe_ep_toggledata01(ep);
+ }
+ } else {
+ dev_err(udc->dev, "The receive frame with error!\n");
+ }
+
+ /* note: don't clear the rxbd's buffer address *
+ * only Clear the length */
+ out_be32((u32 __iomem *)bd, (bdstatus & BD_STATUS_MASK));
+ ep->has_data--;
+
+ /* Get next BD */
+ if (bdstatus & R_W)
+ bd = ep->rxbase;
+ else
+ bd++;
+
+ bdstatus = in_be32((u32 __iomem *)bd);
+ length = bdstatus & BD_LENGTH_MASK;
+ }
+
+ ep->n_rxbd = bd;
+ ep_recycle_rxbds(ep);
+
+ return 0;
+}
+
+/* only add the request in queue */
+static int ep_req_receive(struct qe_ep *ep, struct qe_req *req)
+{
+ if (ep->state == EP_STATE_NACK) {
+ if (ep->has_data <= 0) {
+ /* Enable rx and unmask rx interrupt */
+ qe_eprx_normal(ep);
+ } else {
+ /* Copy the exist BD data */
+ ep_req_rx(ep, req);
+ }
+ }
+
+ return 0;
+}
+
+/********************************************************************
+ Internal Used Function End
+********************************************************************/
+
+/*-----------------------------------------------------------------------
+ Endpoint Management Functions For Gadget
+ -----------------------------------------------------------------------*/
+static int qe_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct qe_udc *udc;
+ struct qe_ep *ep;
+ int retval = 0;
+ unsigned char epnum;
+
+ ep = container_of(_ep, struct qe_ep, ep);
+
+ /* catch various bogus parameters */
+ if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] ||
+ (desc->bDescriptorType != USB_DT_ENDPOINT))
+ return -EINVAL;
+
+ udc = ep->udc;
+ if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
+ return -ESHUTDOWN;
+
+ epnum = (u8)desc->bEndpointAddress & 0xF;
+
+ retval = qe_ep_init(udc, epnum, desc);
+ if (retval != 0) {
+ cpm_muram_free(cpm_muram_offset(ep->rxbase));
+ dev_dbg(udc->dev, "enable ep%d failed\n", ep->epnum);
+ return -EINVAL;
+ }
+ dev_dbg(udc->dev, "enable ep%d successful\n", ep->epnum);
+ return 0;
+}
+
+static int qe_ep_disable(struct usb_ep *_ep)
+{
+ struct qe_udc *udc;
+ struct qe_ep *ep;
+ unsigned long flags;
+ unsigned int size;
+
+ ep = container_of(_ep, struct qe_ep, ep);
+ udc = ep->udc;
+
+ if (!_ep || !ep->desc) {
+ dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&udc->lock, flags);
+ /* Nuke all pending requests (does flush) */
+ nuke(ep, -ESHUTDOWN);
+ ep->desc = NULL;
+ ep->stopped = 1;
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ cpm_muram_free(cpm_muram_offset(ep->rxbase));
+
+ if (ep->dir == USB_DIR_OUT)
+ size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
+ (USB_BDRING_LEN_RX + 1);
+ else
+ size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
+ (USB_BDRING_LEN + 1);
+
+ if (ep->dir != USB_DIR_IN) {
+ kfree(ep->rxframe);
+ if (ep->rxbufmap) {
+ dma_unmap_single(udc_controller->gadget.dev.parent,
+ ep->rxbuf_d, size,
+ DMA_FROM_DEVICE);
+ ep->rxbuf_d = DMA_ADDR_INVALID;
+ } else {
+ dma_sync_single_for_cpu(
+ udc_controller->gadget.dev.parent,
+ ep->rxbuf_d, size,
+ DMA_FROM_DEVICE);
+ }
+ kfree(ep->rxbuffer);
+ }
+
+ if (ep->dir != USB_DIR_OUT)
+ kfree(ep->txframe);
+
+ dev_dbg(udc->dev, "disabled %s OK\n", _ep->name);
+ return 0;
+}
+
+static struct usb_request *qe_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+ struct qe_req *req;
+
+ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return NULL;
+
+ req->req.dma = DMA_ADDR_INVALID;
+
+ INIT_LIST_HEAD(&req->queue);
+
+ return &req->req;
+}
+
+static void qe_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct qe_req *req;
+
+ req = container_of(_req, struct qe_req, req);
+
+ if (_req)
+ kfree(req);
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags)
+{
+ struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
+ struct qe_req *req = container_of(_req, struct qe_req, req);
+ struct qe_udc *udc;
+ unsigned long flags;
+ int reval;
+
+ udc = ep->udc;
+ /* catch various bogus parameters */
+ if (!_req || !req->req.complete || !req->req.buf
+ || !list_empty(&req->queue)) {
+ dev_dbg(udc->dev, "bad params\n");
+ return -EINVAL;
+ }
+ if (!_ep || (!ep->desc && ep_index(ep))) {
+ dev_dbg(udc->dev, "bad ep\n");
+ return -EINVAL;
+ }
+
+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+ return -ESHUTDOWN;
+
+ req->ep = ep;
+
+ /* map virtual address to hardware */
+ if (req->req.dma == DMA_ADDR_INVALID) {
+ req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
+ req->req.buf,
+ req->req.length,
+ ep_is_in(ep)
+ ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ req->mapped = 1;
+ } else {
+ dma_sync_single_for_device(ep->udc->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ ep_is_in(ep)
+ ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ req->mapped = 0;
+ }
+
+ req->req.status = -EINPROGRESS;
+ req->req.actual = 0;
+
+ list_add_tail(&req->queue, &ep->queue);
+ dev_vdbg(udc->dev, "gadget have request in %s! %d\n",
+ ep->name, req->req.length);
+ spin_lock_irqsave(&udc->lock, flags);
+ /* push the request to device */
+ if (ep_is_in(ep))
+ reval = ep_req_send(ep, req);
+
+ /* EP0 */
+ if (ep_index(ep) == 0 && req->req.length > 0) {
+ if (ep_is_in(ep))
+ udc->ep0_state = DATA_STATE_XMIT;
+ else
+ udc->ep0_state = DATA_STATE_RECV;
+ }
+
+ if (ep->dir == USB_DIR_OUT)
+ reval = ep_req_receive(ep, req);
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int qe_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
+ struct qe_req *req;
+ unsigned long flags;
+
+ if (!_ep || !_req)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->udc->lock, flags);
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry(req, &ep->queue, queue) {
+ if (&req->req == _req)
+ break;
+ }
+
+ if (&req->req != _req) {
+ spin_unlock_irqrestore(&ep->udc->lock, flags);
+ return -EINVAL;
+ }
+
+ done(ep, req, -ECONNRESET);
+
+ spin_unlock_irqrestore(&ep->udc->lock, flags);
+ return 0;
+}
+
+/*-----------------------------------------------------------------
+ * modify the endpoint halt feature
+ * @ep: the non-isochronous endpoint being stalled
+ * @value: 1--set halt 0--clear halt
+ * Returns zero, or a negative error code.
+*----------------------------------------------------------------*/
+static int qe_ep_set_halt(struct usb_ep *_ep, int value)
+{
+ struct qe_ep *ep;
+ unsigned long flags;
+ int status = -EOPNOTSUPP;
+ struct qe_udc *udc;
+
+ ep = container_of(_ep, struct qe_ep, ep);
+ if (!_ep || !ep->desc) {
+ status = -EINVAL;
+ goto out;
+ }
+
+ udc = ep->udc;
+ /* Attempt to halt IN ep will fail if any transfer requests
+ * are still queue */
+ if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
+ status = -EAGAIN;
+ goto out;
+ }
+
+ status = 0;
+ spin_lock_irqsave(&ep->udc->lock, flags);
+ qe_eptx_stall_change(ep, value);
+ qe_eprx_stall_change(ep, value);
+ spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+ if (ep->epnum == 0) {
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = 0;
+ }
+
+ /* set data toggle to DATA0 on clear halt */
+ if (value == 0)
+ ep->data01 = 0;
+out:
+ dev_vdbg(udc->dev, "%s %s halt stat %d\n", ep->ep.name,
+ value ? "set" : "clear", status);
+
+ return status;
+}
+
+static struct usb_ep_ops qe_ep_ops = {
+ .enable = qe_ep_enable,
+ .disable = qe_ep_disable,
+
+ .alloc_request = qe_alloc_request,
+ .free_request = qe_free_request,
+
+ .queue = qe_ep_queue,
+ .dequeue = qe_ep_dequeue,
+
+ .set_halt = qe_ep_set_halt,
+};
+
+/*------------------------------------------------------------------------
+ Gadget Driver Layer Operations
+ ------------------------------------------------------------------------*/
+
+/* Get the current frame number */
+static int qe_get_frame(struct usb_gadget *gadget)
+{
+ u16 tmp;
+
+ tmp = in_be16(&udc_controller->usb_param->frame_n);
+ if (tmp & 0x8000)
+ tmp = tmp & 0x07ff;
+ else
+ tmp = -EINVAL;
+
+ return (int)tmp;
+}
+
+/* Tries to wake up the host connected to this gadget
+ *
+ * Return : 0-success
+ * Negative-this feature not enabled by host or not supported by device hw
+ */
+static int qe_wakeup(struct usb_gadget *gadget)
+{
+ return -ENOTSUPP;
+}
+
+/* Notify controller that VBUS is powered, Called by whatever
+ detects VBUS sessions */
+static int qe_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ return -ENOTSUPP;
+}
+
+/* constrain controller's VBUS power usage
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume. For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+ return -ENOTSUPP;
+}
+
+/* Change Data+ pullup status
+ * this func is used by usb_gadget_connect/disconnect
+ */
+static int qe_pullup(struct usb_gadget *gadget, int is_on)
+{
+ return -ENOTSUPP;
+}
+
+/* defined in usb_gadget.h */
+static struct usb_gadget_ops qe_gadget_ops = {
+ .get_frame = qe_get_frame,
+ .wakeup = qe_wakeup,
+/* .set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */
+ .vbus_session = qe_vbus_session,
+ .vbus_draw = qe_vbus_draw,
+ .pullup = qe_pullup,
+};
+
+/*-------------------------------------------------------------------------
+ USB ep0 Setup process in BUS Enumeration
+ -------------------------------------------------------------------------*/
+static int udc_reset_ep_queue(struct qe_udc *udc, u8 pipe)
+{
+ struct qe_ep *ep = &udc->eps[pipe];
+
+ nuke(ep, -ECONNRESET);
+ ep->tx_req = NULL;
+ return 0;
+}
+
+static int reset_queues(struct qe_udc *udc)
+{
+ u8 pipe;
+
+ for (pipe = 0; pipe < USB_MAX_ENDPOINTS; pipe++)
+ udc_reset_ep_queue(udc, pipe);
+
+ /* report disconnect; the driver is already quiesced */
+ spin_unlock(&udc->lock);
+ udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+
+ return 0;
+}
+
+static void ch9setaddress(struct qe_udc *udc, u16 value, u16 index,
+ u16 length)
+{
+ /* Save the new address to device struct */
+ udc->device_address = (u8) value;
+ /* Update usb state */
+ udc->usb_state = USB_STATE_ADDRESS;
+
+ /* Status phase , send a ZLP */
+ if (ep0_prime_status(udc, USB_DIR_IN))
+ qe_ep0_stall(udc);
+}
+
+static void ownercomplete(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct qe_req *req = container_of(_req, struct qe_req, req);
+
+ req->req.buf = NULL;
+ kfree(req);
+}
+
+static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
+ u16 index, u16 length)
+{
+ u16 usb_status = 0;
+ struct qe_req *req;
+ struct qe_ep *ep;
+ int status = 0;
+
+ ep = &udc->eps[0];
+ if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+ /* Get device status */
+ usb_status = 1 << USB_DEVICE_SELF_POWERED;
+ } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
+ /* Get interface status */
+ /* We don't have interface information in udc driver */
+ usb_status = 0;
+ } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+ /* Get endpoint status */
+ int pipe = index & USB_ENDPOINT_NUMBER_MASK;
+ struct qe_ep *target_ep = &udc->eps[pipe];
+ u16 usep;
+
+ /* stall if endpoint doesn't exist */
+ if (!target_ep->desc)
+ goto stall;
+
+ usep = in_be16(&udc->usb_regs->usb_usep[pipe]);
+ if (index & USB_DIR_IN) {
+ if (target_ep->dir != USB_DIR_IN)
+ goto stall;
+ if ((usep & USB_THS_MASK) == USB_THS_STALL)
+ usb_status = 1 << USB_ENDPOINT_HALT;
+ } else {
+ if (target_ep->dir != USB_DIR_OUT)
+ goto stall;
+ if ((usep & USB_RHS_MASK) == USB_RHS_STALL)
+ usb_status = 1 << USB_ENDPOINT_HALT;
+ }
+ }
+
+ req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL),
+ struct qe_req, req);
+ req->req.length = 2;
+ req->req.buf = udc->statusbuf;
+ *(u16 *)req->req.buf = cpu_to_le16(usb_status);
+ req->req.status = -EINPROGRESS;
+ req->req.actual = 0;
+ req->req.complete = ownercomplete;
+
+ udc->ep0_dir = USB_DIR_IN;
+
+ /* data phase */
+ status = qe_ep_queue(&ep->ep, &req->req, GFP_ATOMIC);
+
+ if (status == 0)
+ return;
+stall:
+ dev_err(udc->dev, "Can't respond to getstatus request \n");
+ qe_ep0_stall(udc);
+}
+
+/* only handle the setup request, suppose the device in normal status */
+static void setup_received_handle(struct qe_udc *udc,
+ struct usb_ctrlrequest *setup)
+{
+ /* Fix Endian (udc->local_setup_buff is cpu Endian now)*/
+ u16 wValue = le16_to_cpu(setup->wValue);
+ u16 wIndex = le16_to_cpu(setup->wIndex);
+ u16 wLength = le16_to_cpu(setup->wLength);
+
+ /* clear the previous request in the ep0 */
+ udc_reset_ep_queue(udc, 0);
+
+ if (setup->bRequestType & USB_DIR_IN)
+ udc->ep0_dir = USB_DIR_IN;
+ else
+ udc->ep0_dir = USB_DIR_OUT;
+
+ switch (setup->bRequest) {
+ case USB_REQ_GET_STATUS:
+ /* Data+Status phase form udc */
+ if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
+ != (USB_DIR_IN | USB_TYPE_STANDARD))
+ break;
+ ch9getstatus(udc, setup->bRequestType, wValue, wIndex,
+ wLength);
+ return;
+
+ case USB_REQ_SET_ADDRESS:
+ /* Status phase from udc */
+ if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_DEVICE))
+ break;
+ ch9setaddress(udc, wValue, wIndex, wLength);
+ return;
+
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ /* Requests with no data phase, status phase from udc */
+ if ((setup->bRequestType & USB_TYPE_MASK)
+ != USB_TYPE_STANDARD)
+ break;
+
+ if ((setup->bRequestType & USB_RECIP_MASK)
+ == USB_RECIP_ENDPOINT) {
+ int pipe = wIndex & USB_ENDPOINT_NUMBER_MASK;
+ struct qe_ep *ep;
+
+ if (wValue != 0 || wLength != 0
+ || pipe > USB_MAX_ENDPOINTS)
+ break;
+ ep = &udc->eps[pipe];
+
+ spin_unlock(&udc->lock);
+ qe_ep_set_halt(&ep->ep,
+ (setup->bRequest == USB_REQ_SET_FEATURE)
+ ? 1 : 0);
+ spin_lock(&udc->lock);
+ }
+
+ ep0_prime_status(udc, USB_DIR_IN);
+
+ return;
+
+ default:
+ break;
+ }
+
+ if (wLength) {
+ /* Data phase from gadget, status phase from udc */
+ if (setup->bRequestType & USB_DIR_IN) {
+ udc->ep0_state = DATA_STATE_XMIT;
+ udc->ep0_dir = USB_DIR_IN;
+ } else {
+ udc->ep0_state = DATA_STATE_RECV;
+ udc->ep0_dir = USB_DIR_OUT;
+ }
+ spin_unlock(&udc->lock);
+ if (udc->driver->setup(&udc->gadget,
+ &udc->local_setup_buff) < 0)
+ qe_ep0_stall(udc);
+ spin_lock(&udc->lock);
+ } else {
+ /* No data phase, IN status from gadget */
+ udc->ep0_dir = USB_DIR_IN;
+ spin_unlock(&udc->lock);
+ if (udc->driver->setup(&udc->gadget,
+ &udc->local_setup_buff) < 0)
+ qe_ep0_stall(udc);
+ spin_lock(&udc->lock);
+ udc->ep0_state = DATA_STATE_NEED_ZLP;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ USB Interrupt handlers
+ -------------------------------------------------------------------------*/
+static void suspend_irq(struct qe_udc *udc)
+{
+ udc->resume_state = udc->usb_state;
+ udc->usb_state = USB_STATE_SUSPENDED;
+
+ /* report suspend to the driver ,serial.c not support this*/
+ if (udc->driver->suspend)
+ udc->driver->suspend(&udc->gadget);
+}
+
+static void resume_irq(struct qe_udc *udc)
+{
+ udc->usb_state = udc->resume_state;
+ udc->resume_state = 0;
+
+ /* report resume to the driver , serial.c not support this*/
+ if (udc->driver->resume)
+ udc->driver->resume(&udc->gadget);
+}
+
+static void idle_irq(struct qe_udc *udc)
+{
+ u8 usbs;
+
+ usbs = in_8(&udc->usb_regs->usb_usbs);
+ if (usbs & USB_IDLE_STATUS_MASK) {
+ if ((udc->usb_state) != USB_STATE_SUSPENDED)
+ suspend_irq(udc);
+ } else {
+ if (udc->usb_state == USB_STATE_SUSPENDED)
+ resume_irq(udc);
+ }
+}
+
+static int reset_irq(struct qe_udc *udc)
+{
+ unsigned char i;
+
+ qe_usb_disable();
+ out_8(&udc->usb_regs->usb_usadr, 0);
+
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+ if (udc->eps[i].init)
+ qe_ep_reset(udc, i);
+ }
+
+ reset_queues(udc);
+ udc->usb_state = USB_STATE_DEFAULT;
+ udc->ep0_state = WAIT_FOR_SETUP;
+ udc->ep0_dir = USB_DIR_OUT;
+ qe_usb_enable();
+ return 0;
+}
+
+static int bsy_irq(struct qe_udc *udc)
+{
+ return 0;
+}
+
+static int txe_irq(struct qe_udc *udc)
+{
+ return 0;
+}
+
+/* ep0 tx interrupt also in here */
+static int tx_irq(struct qe_udc *udc)
+{
+ struct qe_ep *ep;
+ struct qe_bd __iomem *bd;
+ int i, res = 0;
+
+ if ((udc->usb_state == USB_STATE_ADDRESS)
+ && (in_8(&udc->usb_regs->usb_usadr) == 0))
+ out_8(&udc->usb_regs->usb_usadr, udc->device_address);
+
+ for (i = (USB_MAX_ENDPOINTS-1); ((i >= 0) && (res == 0)); i--) {
+ ep = &udc->eps[i];
+ if (ep && ep->init && (ep->dir != USB_DIR_OUT)) {
+ bd = ep->c_txbd;
+ if (!(in_be32((u32 __iomem *)bd) & T_R)
+ && (in_be32(&bd->buf))) {
+ /* confirm the transmitted bd */
+ if (ep->epnum == 0)
+ res = qe_ep0_txconf(ep);
+ else
+ res = qe_ep_txconf(ep);
+ }
+ }
+ }
+ return res;
+}
+
+
+/* setup packect's rx is handle in the function too */
+static void rx_irq(struct qe_udc *udc)
+{
+ struct qe_ep *ep;
+ struct qe_bd __iomem *bd;
+ int i;
+
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+ ep = &udc->eps[i];
+ if (ep && ep->init && (ep->dir != USB_DIR_IN)) {
+ bd = ep->n_rxbd;
+ if (!(in_be32((u32 __iomem *)bd) & R_E)
+ && (in_be32(&bd->buf))) {
+ if (ep->epnum == 0) {
+ qe_ep0_rx(udc);
+ } else {
+ /*non-setup package receive*/
+ qe_ep_rx(ep);
+ }
+ }
+ }
+ }
+}
+
+static irqreturn_t qe_udc_irq(int irq, void *_udc)
+{
+ struct qe_udc *udc = (struct qe_udc *)_udc;
+ u16 irq_src;
+ irqreturn_t status = IRQ_NONE;
+ unsigned long flags;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ irq_src = in_be16(&udc->usb_regs->usb_usber) &
+ in_be16(&udc->usb_regs->usb_usbmr);
+ /* Clear notification bits */
+ out_be16(&udc->usb_regs->usb_usber, irq_src);
+ /* USB Interrupt */
+ if (irq_src & USB_E_IDLE_MASK) {
+ idle_irq(udc);
+ irq_src &= ~USB_E_IDLE_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ if (irq_src & USB_E_TXB_MASK) {
+ tx_irq(udc);
+ irq_src &= ~USB_E_TXB_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ if (irq_src & USB_E_RXB_MASK) {
+ rx_irq(udc);
+ irq_src &= ~USB_E_RXB_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ if (irq_src & USB_E_RESET_MASK) {
+ reset_irq(udc);
+ irq_src &= ~USB_E_RESET_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ if (irq_src & USB_E_BSY_MASK) {
+ bsy_irq(udc);
+ irq_src &= ~USB_E_BSY_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ if (irq_src & USB_E_TXE_MASK) {
+ txe_irq(udc);
+ irq_src &= ~USB_E_TXE_MASK;
+ status = IRQ_HANDLED;
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ return status;
+}
+
+/*-------------------------------------------------------------------------
+ Gadget driver register and unregister.
+ --------------------------------------------------------------------------*/
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ int retval;
+ unsigned long flags = 0;
+
+ /* standard operations */
+ if (!udc_controller)
+ return -ENODEV;
+
+ if (!driver || (driver->speed != USB_SPEED_FULL
+ && driver->speed != USB_SPEED_HIGH)
+ || !driver->bind || !driver->disconnect
+ || !driver->setup)
+ return -EINVAL;
+
+ if (udc_controller->driver)
+ return -EBUSY;
+
+ /* lock is needed but whether should use this lock or another */
+ spin_lock_irqsave(&udc_controller->lock, flags);
+
+ driver->driver.bus = NULL;
+ /* hook up the driver */
+ udc_controller->driver = driver;
+ udc_controller->gadget.dev.driver = &driver->driver;
+ udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
+ spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+ retval = driver->bind(&udc_controller->gadget);
+ if (retval) {
+ dev_err(udc_controller->dev, "bind to %s --> %d",
+ driver->driver.name, retval);
+ udc_controller->gadget.dev.driver = NULL;
+ udc_controller->driver = NULL;
+ return retval;
+ }
+
+ /* Enable IRQ reg and Set usbcmd reg EN bit */
+ qe_usb_enable();
+
+ out_be16(&udc_controller->usb_regs->usb_usber, 0xffff);
+ out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
+ udc_controller->usb_state = USB_STATE_ATTACHED;
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
+ udc_controller->ep0_dir = USB_DIR_OUT;
+ dev_info(udc_controller->dev, "%s bind to driver %s \n",
+ udc_controller->gadget.name, driver->driver.name);
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ struct qe_ep *loop_ep;
+ unsigned long flags;
+
+ if (!udc_controller)
+ return -ENODEV;
+
+ if (!driver || driver != udc_controller->driver)
+ return -EINVAL;
+
+ /* stop usb controller, disable intr */
+ qe_usb_disable();
+
+ /* in fact, no needed */
+ udc_controller->usb_state = USB_STATE_ATTACHED;
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
+ udc_controller->ep0_dir = 0;
+
+ /* stand operation */
+ spin_lock_irqsave(&udc_controller->lock, flags);
+ udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+ nuke(&udc_controller->eps[0], -ESHUTDOWN);
+ list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
+ ep.ep_list)
+ nuke(loop_ep, -ESHUTDOWN);
+ spin_unlock_irqrestore(&udc_controller->lock, flags);
+
+ /* unbind gadget and unhook driver. */
+ driver->unbind(&udc_controller->gadget);
+ udc_controller->gadget.dev.driver = NULL;
+ udc_controller->driver = NULL;
+
+ dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n",
+ driver->driver.name);
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/* udc structure's alloc and setup, include ep-param alloc */
+static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
+{
+ struct qe_udc *udc;
+ struct device_node *np = ofdev->node;
+ unsigned int tmp_addr = 0;
+ struct usb_device_para __iomem *usbpram;
+ unsigned int i;
+ u64 size;
+ u32 offset;
+
+ udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+ if (udc == NULL) {
+ dev_err(&ofdev->dev, "malloc udc failed\n");
+ goto cleanup;
+ }
+
+ udc->dev = &ofdev->dev;
+
+ /* get default address of usb parameter in MURAM from device tree */
+ offset = *of_get_address(np, 1, &size, NULL);
+ udc->usb_param = cpm_muram_addr(offset);
+ memset_io(udc->usb_param, 0, size);
+
+ usbpram = udc->usb_param;
+ out_be16(&usbpram->frame_n, 0);
+ out_be32(&usbpram->rstate, 0);
+
+ tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS *
+ sizeof(struct usb_ep_para)),
+ USB_EP_PARA_ALIGNMENT);
+
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+ out_be16(&usbpram->epptr[i], (u16)tmp_addr);
+ udc->ep_param[i] = cpm_muram_addr(tmp_addr);
+ tmp_addr += 32;
+ }
+
+ memset_io(udc->ep_param[0], 0,
+ USB_MAX_ENDPOINTS * sizeof(struct usb_ep_para));
+
+ udc->resume_state = USB_STATE_NOTATTACHED;
+ udc->usb_state = USB_STATE_POWERED;
+ udc->ep0_dir = 0;
+
+ spin_lock_init(&udc->lock);
+ return udc;
+
+cleanup:
+ kfree(udc);
+ return NULL;
+}
+
+/* USB Controller register init */
+static int __devinit qe_udc_reg_init(struct qe_udc *udc)
+{
+ struct usb_ctlr __iomem *qe_usbregs;
+ qe_usbregs = udc->usb_regs;
+
+ /* Init the usb register */
+ out_8(&qe_usbregs->usb_usmod, 0x01);
+ out_be16(&qe_usbregs->usb_usbmr, 0);
+ out_8(&qe_usbregs->usb_uscom, 0);
+ out_be16(&qe_usbregs->usb_usber, USBER_ALL_CLEAR);
+
+ return 0;
+}
+
+static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
+{
+ struct qe_ep *ep = &udc->eps[pipe_num];
+
+ ep->udc = udc;
+ strcpy(ep->name, ep_name[pipe_num]);
+ ep->ep.name = ep_name[pipe_num];
+
+ ep->ep.ops = &qe_ep_ops;
+ ep->stopped = 1;
+ ep->ep.maxpacket = (unsigned short) ~0;
+ ep->desc = NULL;
+ ep->dir = 0xff;
+ ep->epnum = (u8)pipe_num;
+ ep->sent = 0;
+ ep->last = 0;
+ ep->init = 0;
+ ep->rxframe = NULL;
+ ep->txframe = NULL;
+ ep->tx_req = NULL;
+ ep->state = EP_STATE_IDLE;
+ ep->has_data = 0;
+
+ /* the queue lists any req for this ep */
+ INIT_LIST_HEAD(&ep->queue);
+
+ /* gagdet.ep_list used for ep_autoconfig so no ep0*/
+ if (pipe_num != 0)
+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+ ep->gadget = &udc->gadget;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * UDC device Driver operation functions *
+ *----------------------------------------------------------------------*/
+static void qe_udc_release(struct device *dev)
+{
+ int i = 0;
+
+ complete(udc_controller->done);
+ cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0]));
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+ udc_controller->ep_param[i] = NULL;
+
+ kfree(udc_controller);
+ udc_controller = NULL;
+}
+
+/* Driver probe functions */
+static int __devinit qe_udc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ struct qe_ep *ep;
+ unsigned int ret = 0;
+ unsigned int i;
+ const void *prop;
+
+ prop = of_get_property(np, "mode", NULL);
+ if (!prop || strcmp(prop, "peripheral"))
+ return -ENODEV;
+
+ /* Initialize the udc structure including QH member and other member */
+ udc_controller = qe_udc_config(ofdev);
+ if (!udc_controller) {
+ dev_dbg(&ofdev->dev, "udc_controll is NULL\n");
+ return -ENOMEM;
+ }
+
+ udc_controller->soc_type = (unsigned long)match->data;
+ udc_controller->usb_regs = of_iomap(np, 0);
+ if (!udc_controller->usb_regs) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+
+ /* initialize usb hw reg except for regs for EP,
+ * leave usbintr reg untouched*/
+ qe_udc_reg_init(udc_controller);
+
+ /* here comes the stand operations for probe
+ * set the qe_udc->gadget.xxx */
+ udc_controller->gadget.ops = &qe_gadget_ops;
+
+ /* gadget.ep0 is a pointer */
+ udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
+
+ INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
+
+ /* modify in register gadget process */
+ udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+
+ /* name: Identifies the controller hardware type. */
+ udc_controller->gadget.name = driver_name;
+
+ device_initialize(&udc_controller->gadget.dev);
+
+ strcpy(udc_controller->gadget.dev.bus_id, "gadget");
+
+ udc_controller->gadget.dev.release = qe_udc_release;
+ udc_controller->gadget.dev.parent = &ofdev->dev;
+
+ /* initialize qe_ep struct */
+ for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
+ /* because the ep type isn't decide here so
+ * qe_ep_init() should be called in ep_enable() */
+
+ /* setup the qe_ep struct and link ep.ep.list
+ * into gadget.ep_list */
+ qe_ep_config(udc_controller, (unsigned char)i);
+ }
+
+ /* ep0 initialization in here */
+ ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc);
+ if (ret)
+ goto err2;
+
+ /* create a buf for ZLP send, need to remain zeroed */
+ udc_controller->nullbuf = kzalloc(256, GFP_KERNEL);
+ if (udc_controller->nullbuf == NULL) {
+ dev_dbg(udc_controller->dev, "cannot alloc nullbuf\n");
+ ret = -ENOMEM;
+ goto err3;
+ }
+
+ /* buffer for data of get_status request */
+ udc_controller->statusbuf = kzalloc(2, GFP_KERNEL);
+ if (udc_controller->statusbuf == NULL) {
+ ret = -ENOMEM;
+ goto err4;
+ }
+
+ udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf);
+ if (udc_controller->nullp == DMA_ADDR_INVALID) {
+ udc_controller->nullp = dma_map_single(
+ udc_controller->gadget.dev.parent,
+ udc_controller->nullbuf,
+ 256,
+ DMA_TO_DEVICE);
+ udc_controller->nullmap = 1;
+ } else {
+ dma_sync_single_for_device(udc_controller->gadget.dev.parent,
+ udc_controller->nullp, 256,
+ DMA_TO_DEVICE);
+ }
+
+ tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet,
+ (unsigned long)udc_controller);
+ /* request irq and disable DR */
+ udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
+
+ ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
+ driver_name, udc_controller);
+ if (ret) {
+ dev_err(udc_controller->dev, "cannot request irq %d err %d \n",
+ udc_controller->usb_irq, ret);
+ goto err5;
+ }
+
+ ret = device_add(&udc_controller->gadget.dev);
+ if (ret)
+ goto err6;
+
+ dev_info(udc_controller->dev,
+ "%s USB controller initialized as device\n",
+ (udc_controller->soc_type == PORT_QE) ? "QE" : "CPM");
+ return 0;
+
+err6:
+ free_irq(udc_controller->usb_irq, udc_controller);
+err5:
+ if (udc_controller->nullmap) {
+ dma_unmap_single(udc_controller->gadget.dev.parent,
+ udc_controller->nullp, 256,
+ DMA_TO_DEVICE);
+ udc_controller->nullp = DMA_ADDR_INVALID;
+ } else {
+ dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
+ udc_controller->nullp, 256,
+ DMA_TO_DEVICE);
+ }
+ kfree(udc_controller->statusbuf);
+err4:
+ kfree(udc_controller->nullbuf);
+err3:
+ ep = &udc_controller->eps[0];
+ cpm_muram_free(cpm_muram_offset(ep->rxbase));
+ kfree(ep->rxframe);
+ kfree(ep->rxbuffer);
+ kfree(ep->txframe);
+err2:
+ iounmap(udc_controller->usb_regs);
+err1:
+ kfree(udc_controller);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int qe_udc_suspend(struct of_device *dev, pm_message_t state)
+{
+ return -ENOTSUPP;
+}
+
+static int qe_udc_resume(struct of_device *dev)
+{
+ return -ENOTSUPP;
+}
+#endif
+
+static int __devexit qe_udc_remove(struct of_device *ofdev)
+{
+ struct qe_ep *ep;
+ unsigned int size;
+
+ DECLARE_COMPLETION(done);
+
+ if (!udc_controller)
+ return -ENODEV;
+
+ udc_controller->done = &done;
+ tasklet_disable(&udc_controller->rx_tasklet);
+
+ if (udc_controller->nullmap) {
+ dma_unmap_single(udc_controller->gadget.dev.parent,
+ udc_controller->nullp, 256,
+ DMA_TO_DEVICE);
+ udc_controller->nullp = DMA_ADDR_INVALID;
+ } else {
+ dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
+ udc_controller->nullp, 256,
+ DMA_TO_DEVICE);
+ }
+ kfree(udc_controller->statusbuf);
+ kfree(udc_controller->nullbuf);
+
+ ep = &udc_controller->eps[0];
+ cpm_muram_free(cpm_muram_offset(ep->rxbase));
+ size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1);
+
+ kfree(ep->rxframe);
+ if (ep->rxbufmap) {
+ dma_unmap_single(udc_controller->gadget.dev.parent,
+ ep->rxbuf_d, size,
+ DMA_FROM_DEVICE);
+ ep->rxbuf_d = DMA_ADDR_INVALID;
+ } else {
+ dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
+ ep->rxbuf_d, size,
+ DMA_FROM_DEVICE);
+ }
+
+ kfree(ep->rxbuffer);
+ kfree(ep->txframe);
+
+ free_irq(udc_controller->usb_irq, udc_controller);
+
+ tasklet_kill(&udc_controller->rx_tasklet);
+
+ iounmap(udc_controller->usb_regs);
+
+ device_unregister(&udc_controller->gadget.dev);
+ /* wait for release() of gadget.dev to free udc */
+ wait_for_completion(&done);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct of_device_id __devinitdata qe_udc_match[] = {
+ {
+ .compatible = "fsl,mpc8360-qe-usb",
+ .data = (void *)PORT_QE,
+ },
+ {
+ .compatible = "fsl,mpc8272-cpm-usb",
+ .data = (void *)PORT_CPM,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, qe_udc_match);
+
+static struct of_platform_driver udc_driver = {
+ .name = (char *)driver_name,
+ .match_table = qe_udc_match,
+ .probe = qe_udc_probe,
+ .remove = __devexit_p(qe_udc_remove),
+#ifdef CONFIG_PM
+ .suspend = qe_udc_suspend,
+ .resume = qe_udc_resume,
+#endif
+};
+
+static int __init qe_udc_init(void)
+{
+ printk(KERN_INFO "%s: %s, %s\n", driver_name, driver_desc,
+ DRIVER_VERSION);
+ return of_register_platform_driver(&udc_driver);
+}
+
+static void __exit qe_udc_exit(void)
+{
+ of_unregister_platform_driver(&udc_driver);
+}
+
+module_init(qe_udc_init);
+module_exit(qe_udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
new file mode 100644
index 00000000000..31b2710882e
--- /dev/null
+++ b/drivers/usb/gadget/fsl_qe_udc.h
@@ -0,0 +1,437 @@
+/*
+ * drivers/usb/gadget/qe_udc.h
+ *
+ * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Xiaobo Xie <X.Xie@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * Freescale USB device/endpoint management registers
+ *
+ * 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 __FSL_QE_UDC_H
+#define __FSL_QE_UDC_H
+
+/* SoC type */
+#define PORT_CPM 0
+#define PORT_QE 1
+
+#define USB_MAX_ENDPOINTS 4
+#define USB_MAX_PIPES USB_MAX_ENDPOINTS
+#define USB_EP0_MAX_SIZE 64
+#define USB_MAX_CTRL_PAYLOAD 0x4000
+#define USB_BDRING_LEN 16
+#define USB_BDRING_LEN_RX 256
+#define USB_BDRING_LEN_TX 16
+#define MIN_EMPTY_BDS 128
+#define MAX_DATA_BDS 8
+#define USB_CRC_SIZE 2
+#define USB_DIR_BOTH 0x88
+#define R_BUF_MAXSIZE 0x800
+#define USB_EP_PARA_ALIGNMENT 32
+
+/* USB Mode Register bit define */
+#define USB_MODE_EN 0x01
+#define USB_MODE_HOST 0x02
+#define USB_MODE_TEST 0x04
+#define USB_MODE_SFTE 0x08
+#define USB_MODE_RESUME 0x40
+#define USB_MODE_LSS 0x80
+
+/* USB Slave Address Register Mask */
+#define USB_SLVADDR_MASK 0x7F
+
+/* USB Endpoint register define */
+#define USB_EPNUM_MASK 0xF000
+#define USB_EPNUM_SHIFT 12
+
+#define USB_TRANS_MODE_SHIFT 8
+#define USB_TRANS_CTR 0x0000
+#define USB_TRANS_INT 0x0100
+#define USB_TRANS_BULK 0x0200
+#define USB_TRANS_ISO 0x0300
+
+#define USB_EP_MF 0x0020
+#define USB_EP_RTE 0x0010
+
+#define USB_THS_SHIFT 2
+#define USB_THS_MASK 0x000c
+#define USB_THS_NORMAL 0x0
+#define USB_THS_IGNORE_IN 0x0004
+#define USB_THS_NACK 0x0008
+#define USB_THS_STALL 0x000c
+
+#define USB_RHS_SHIFT 0
+#define USB_RHS_MASK 0x0003
+#define USB_RHS_NORMAL 0x0
+#define USB_RHS_IGNORE_OUT 0x0001
+#define USB_RHS_NACK 0x0002
+#define USB_RHS_STALL 0x0003
+
+#define USB_RTHS_MASK 0x000f
+
+/* USB Command Register define */
+#define USB_CMD_STR_FIFO 0x80
+#define USB_CMD_FLUSH_FIFO 0x40
+#define USB_CMD_ISFT 0x20
+#define USB_CMD_DSFT 0x10
+#define USB_CMD_EP_MASK 0x03
+
+/* USB Event and Mask Register define */
+#define USB_E_MSF_MASK 0x0800
+#define USB_E_SFT_MASK 0x0400
+#define USB_E_RESET_MASK 0x0200
+#define USB_E_IDLE_MASK 0x0100
+#define USB_E_TXE4_MASK 0x0080
+#define USB_E_TXE3_MASK 0x0040
+#define USB_E_TXE2_MASK 0x0020
+#define USB_E_TXE1_MASK 0x0010
+#define USB_E_SOF_MASK 0x0008
+#define USB_E_BSY_MASK 0x0004
+#define USB_E_TXB_MASK 0x0002
+#define USB_E_RXB_MASK 0x0001
+#define USBER_ALL_CLEAR 0x0fff
+
+#define USB_E_DEFAULT_DEVICE (USB_E_RESET_MASK | USB_E_TXE4_MASK | \
+ USB_E_TXE3_MASK | USB_E_TXE2_MASK | \
+ USB_E_TXE1_MASK | USB_E_BSY_MASK | \
+ USB_E_TXB_MASK | USB_E_RXB_MASK)
+
+#define USB_E_TXE_MASK (USB_E_TXE4_MASK | USB_E_TXE3_MASK|\
+ USB_E_TXE2_MASK | USB_E_TXE1_MASK)
+/* USB Status Register define */
+#define USB_IDLE_STATUS_MASK 0x01
+
+/* USB Start of Frame Timer */
+#define USB_USSFT_MASK 0x3FFF
+
+/* USB Frame Number Register */
+#define USB_USFRN_MASK 0xFFFF
+
+struct usb_device_para{
+ u16 epptr[4];
+ u32 rstate;
+ u32 rptr;
+ u16 frame_n;
+ u16 rbcnt;
+ u32 rtemp;
+ u32 rxusb_data;
+ u16 rxuptr;
+ u8 reso[2];
+ u32 softbl;
+ u8 sofucrctemp;
+};
+
+struct usb_ep_para{
+ u16 rbase;
+ u16 tbase;
+ u8 rbmr;
+ u8 tbmr;
+ u16 mrblr;
+ u16 rbptr;
+ u16 tbptr;
+ u32 tstate;
+ u32 tptr;
+ u16 tcrc;
+ u16 tbcnt;
+ u32 ttemp;
+ u16 txusbu_ptr;
+ u8 reserve[2];
+};
+
+#define USB_BUSMODE_GBL 0x20
+#define USB_BUSMODE_BO_MASK 0x18
+#define USB_BUSMODE_BO_SHIFT 0x3
+#define USB_BUSMODE_BE 0x2
+#define USB_BUSMODE_CETM 0x04
+#define USB_BUSMODE_DTB 0x02
+
+/* Endpoint basic handle */
+#define ep_index(EP) ((EP)->desc->bEndpointAddress & 0xF)
+#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
+#define ep_is_in(EP) ((ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
+ USB_DIR_IN) : ((EP)->desc->bEndpointAddress \
+ & USB_DIR_IN) == USB_DIR_IN)
+
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP 0
+#define DATA_STATE_XMIT 1
+#define DATA_STATE_NEED_ZLP 2
+#define WAIT_FOR_OUT_STATUS 3
+#define DATA_STATE_RECV 4
+
+/* ep tramsfer mode */
+#define USBP_TM_CTL 0
+#define USBP_TM_ISO 1
+#define USBP_TM_BULK 2
+#define USBP_TM_INT 3
+
+/*-----------------------------------------------------------------------------
+ USB RX And TX DATA Frame
+ -----------------------------------------------------------------------------*/
+struct qe_frame{
+ u8 *data;
+ u32 len;
+ u32 status;
+ u32 info;
+
+ void *privdata;
+ struct list_head node;
+};
+
+/* Frame structure, info field. */
+#define PID_DATA0 0x80000000 /* Data toggle zero */
+#define PID_DATA1 0x40000000 /* Data toggle one */
+#define PID_SETUP 0x20000000 /* setup bit */
+#define SETUP_STATUS 0x10000000 /* setup status bit */
+#define SETADDR_STATUS 0x08000000 /* setupup address status bit */
+#define NO_REQ 0x04000000 /* Frame without request */
+#define HOST_DATA 0x02000000 /* Host data frame */
+#define FIRST_PACKET_IN_FRAME 0x01000000 /* first packet in the frame */
+#define TOKEN_FRAME 0x00800000 /* Host token frame */
+#define ZLP 0x00400000 /* Zero length packet */
+#define IN_TOKEN_FRAME 0x00200000 /* In token package */
+#define OUT_TOKEN_FRAME 0x00100000 /* Out token package */
+#define SETUP_TOKEN_FRAME 0x00080000 /* Setup token package */
+#define STALL_FRAME 0x00040000 /* Stall handshake */
+#define NACK_FRAME 0x00020000 /* Nack handshake */
+#define NO_PID 0x00010000 /* No send PID */
+#define NO_CRC 0x00008000 /* No send CRC */
+#define HOST_COMMAND 0x00004000 /* Host command frame */
+
+/* Frame status field */
+/* Receive side */
+#define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */
+#define FRAME_ERROR 0x80000000 /* Error occured on frame */
+#define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */
+#define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */
+#define RX_ER_NONOCT 0x10000000 /* Rx Non Octet Aligned Packet */
+#define RX_ER_BITSTUFF 0x08000000 /* Frame Aborted --Received packet
+ with bit stuff error */
+#define RX_ER_CRC 0x04000000 /* Received packet with CRC error */
+#define RX_ER_OVERUN 0x02000000 /* Over-run occured on reception */
+#define RX_ER_PID 0x01000000 /* Wrong PID received */
+/* Tranmit side */
+#define TX_ER_NAK 0x00800000 /* Received NAK handshake */
+#define TX_ER_STALL 0x00400000 /* Received STALL handshake */
+#define TX_ER_TIMEOUT 0x00200000 /* Transmit time out */
+#define TX_ER_UNDERUN 0x00100000 /* Transmit underrun */
+#define FRAME_INPROGRESS 0x00080000 /* Frame is being transmitted */
+#define ER_DATA_UNDERUN 0x00040000 /* Frame is shorter then expected */
+#define ER_DATA_OVERUN 0x00020000 /* Frame is longer then expected */
+
+/* QE USB frame operation functions */
+#define frame_get_length(frm) (frm->len)
+#define frame_set_length(frm, leng) (frm->len = leng)
+#define frame_get_data(frm) (frm->data)
+#define frame_set_data(frm, dat) (frm->data = dat)
+#define frame_get_info(frm) (frm->info)
+#define frame_set_info(frm, inf) (frm->info = inf)
+#define frame_get_status(frm) (frm->status)
+#define frame_set_status(frm, stat) (frm->status = stat)
+#define frame_get_privdata(frm) (frm->privdata)
+#define frame_set_privdata(frm, dat) (frm->privdata = dat)
+
+static inline void qe_frame_clean(struct qe_frame *frm)
+{
+ frame_set_data(frm, NULL);
+ frame_set_length(frm, 0);
+ frame_set_status(frm, FRAME_OK);
+ frame_set_info(frm, 0);
+ frame_set_privdata(frm, NULL);
+}
+
+static inline void qe_frame_init(struct qe_frame *frm)
+{
+ qe_frame_clean(frm);
+ INIT_LIST_HEAD(&(frm->node));
+}
+
+struct qe_req {
+ struct usb_request req;
+ struct list_head queue;
+ /* ep_queue() func will add
+ a request->queue into a udc_ep->queue 'd tail */
+ struct qe_ep *ep;
+ unsigned mapped:1;
+};
+
+struct qe_ep {
+ struct usb_ep ep;
+ struct list_head queue;
+ struct qe_udc *udc;
+ const struct usb_endpoint_descriptor *desc;
+ struct usb_gadget *gadget;
+
+ u8 state;
+
+ struct qe_bd __iomem *rxbase;
+ struct qe_bd __iomem *n_rxbd;
+ struct qe_bd __iomem *e_rxbd;
+
+ struct qe_bd __iomem *txbase;
+ struct qe_bd __iomem *n_txbd;
+ struct qe_bd __iomem *c_txbd;
+
+ struct qe_frame *rxframe;
+ u8 *rxbuffer;
+ dma_addr_t rxbuf_d;
+ u8 rxbufmap;
+ unsigned char localnack;
+ int has_data;
+
+ struct qe_frame *txframe;
+ struct qe_req *tx_req;
+ int sent; /*data already sent */
+ int last; /*data sent in the last time*/
+
+ u8 dir;
+ u8 epnum;
+ u8 tm; /* transfer mode */
+ u8 data01;
+ u8 init;
+
+ u8 already_seen;
+ u8 enable_tasklet;
+ u8 setup_stage;
+ u32 last_io; /* timestamp */
+
+ char name[14];
+
+ unsigned double_buf:1;
+ unsigned stopped:1;
+ unsigned fnf:1;
+ unsigned has_dma:1;
+
+ u8 ackwait;
+ u8 dma_channel;
+ u16 dma_counter;
+ int lch;
+
+ struct timer_list timer;
+};
+
+struct qe_udc {
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ struct device *dev;
+ struct qe_ep eps[USB_MAX_ENDPOINTS];
+ struct usb_ctrlrequest local_setup_buff;
+ spinlock_t lock; /* lock for set/config qe_udc */
+ unsigned long soc_type; /* QE or CPM soc */
+
+ struct qe_req *status_req; /* ep0 status request */
+
+ /* USB and EP Parameter Block pointer */
+ struct usb_device_para __iomem *usb_param;
+ struct usb_ep_para __iomem *ep_param[4];
+
+ u32 max_pipes; /* Device max pipes */
+ u32 max_use_endpts; /* Max endpointes to be used */
+ u32 bus_reset; /* Device is bus reseting */
+ u32 resume_state; /* USB state to resume*/
+ u32 usb_state; /* USB current state */
+ u32 usb_next_state; /* USB next state */
+ u32 ep0_state; /* Enpoint zero state */
+ u32 ep0_dir; /* Enpoint zero direction: can be
+ USB_DIR_IN or USB_DIR_OUT*/
+ u32 usb_sof_count; /* SOF count */
+ u32 errors; /* USB ERRORs count */
+
+ u8 *tmpbuf;
+ u32 c_start;
+ u32 c_end;
+
+ u8 *nullbuf;
+ u8 *statusbuf;
+ dma_addr_t nullp;
+ u8 nullmap;
+ u8 device_address; /* Device USB address */
+
+ unsigned int usb_clock;
+ unsigned int usb_irq;
+ struct usb_ctlr __iomem *usb_regs;
+
+ struct tasklet_struct rx_tasklet;
+
+ struct completion *done; /* to make sure release() is done */
+};
+
+#define EP_STATE_IDLE 0
+#define EP_STATE_NACK 1
+#define EP_STATE_STALL 2
+
+/*
+ * transmit BD's status
+ */
+#define T_R 0x80000000 /* ready bit */
+#define T_W 0x20000000 /* wrap bit */
+#define T_I 0x10000000 /* interrupt on completion */
+#define T_L 0x08000000 /* last */
+#define T_TC 0x04000000 /* transmit CRC */
+#define T_CNF 0x02000000 /* wait for transmit confirm */
+#define T_LSP 0x01000000 /* Low-speed transaction */
+#define T_PID 0x00c00000 /* packet id */
+#define T_NAK 0x00100000 /* No ack. */
+#define T_STAL 0x00080000 /* Stall recieved */
+#define T_TO 0x00040000 /* time out */
+#define T_UN 0x00020000 /* underrun */
+
+#define DEVICE_T_ERROR (T_UN | T_TO)
+#define HOST_T_ERROR (T_UN | T_TO | T_NAK | T_STAL)
+#define DEVICE_T_BD_MASK DEVICE_T_ERROR
+#define HOST_T_BD_MASK HOST_T_ERROR
+
+#define T_PID_SHIFT 6
+#define T_PID_DATA0 0x00800000 /* Data 0 toggle */
+#define T_PID_DATA1 0x00c00000 /* Data 1 toggle */
+
+/*
+ * receive BD's status
+ */
+#define R_E 0x80000000 /* buffer empty */
+#define R_W 0x20000000 /* wrap bit */
+#define R_I 0x10000000 /* interrupt on reception */
+#define R_L 0x08000000 /* last */
+#define R_F 0x04000000 /* first */
+#define R_PID 0x00c00000 /* packet id */
+#define R_NO 0x00100000 /* Rx Non Octet Aligned Packet */
+#define R_AB 0x00080000 /* Frame Aborted */
+#define R_CR 0x00040000 /* CRC Error */
+#define R_OV 0x00020000 /* Overrun */
+
+#define R_ERROR (R_NO | R_AB | R_CR | R_OV)
+#define R_BD_MASK R_ERROR
+
+#define R_PID_DATA0 0x00000000
+#define R_PID_DATA1 0x00400000
+#define R_PID_SETUP 0x00800000
+
+#define CPM_USB_STOP_TX 0x2e600000
+#define CPM_USB_RESTART_TX 0x2e600000
+#define CPM_USB_STOP_TX_OPCODE 0x0a
+#define CPM_USB_RESTART_TX_OPCODE 0x0b
+#define CPM_USB_EP_SHIFT 5
+
+#ifndef CONFIG_CPM
+inline int cpm_command(u32 command, u8 opcode)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+#ifndef CONFIG_QUICC_ENGINE
+inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
+ u32 cmd_input)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+#endif /* __FSL_QE_UDC_H */
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 1cfccf102a2..091bb55c9aa 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -23,11 +23,8 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
@@ -44,11 +41,9 @@
#include <asm/byteorder.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/dma.h>
-#include <asm/cacheflush.h>
#include "fsl_usb2_udc.h"
@@ -61,8 +56,8 @@
static const char driver_name[] = "fsl-usb2-udc";
static const char driver_desc[] = DRIVER_DESC;
-volatile static struct usb_dr_device *dr_regs = NULL;
-volatile static struct usb_sys_interface *usb_sys_regs = NULL;
+static struct usb_dr_device *dr_regs;
+static struct usb_sys_interface *usb_sys_regs;
/* it is initialized in probe() */
static struct fsl_udc *udc_controller = NULL;
@@ -76,16 +71,14 @@ fsl_ep0_desc = {
.wMaxPacketSize = USB_MAX_CTRL_PAYLOAD,
};
-static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state);
-static int fsl_udc_resume(struct platform_device *pdev);
static void fsl_ep_fifo_flush(struct usb_ep *_ep);
#ifdef CONFIG_PPC32
#define fsl_readl(addr) in_le32(addr)
-#define fsl_writel(addr, val32) out_le32(val32, addr)
+#define fsl_writel(val32, addr) out_le32(addr, val32)
#else
#define fsl_readl(addr) readl(addr)
-#define fsl_writel(addr, val32) writel(addr, val32)
+#define fsl_writel(val32, addr) writel(val32, addr)
#endif
/********************************************************************
@@ -185,10 +178,6 @@ static int dr_controller_setup(struct fsl_udc *udc)
unsigned long timeout;
#define FSL_UDC_RESET_TIMEOUT 1000
- /* before here, make sure dr_regs has been initialized */
- if (!udc)
- return -EINVAL;
-
/* Stop and reset the usb controller */
tmp = fsl_readl(&dr_regs->usbcmd);
tmp &= ~USB_CMD_RUN_STOP;
@@ -202,7 +191,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
timeout = jiffies + FSL_UDC_RESET_TIMEOUT;
while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) {
if (time_after(jiffies, timeout)) {
- ERR("udc reset timeout! \n");
+ ERR("udc reset timeout!\n");
return -ETIMEDOUT;
}
cpu_relax();
@@ -223,7 +212,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
fsl_writel(tmp, &dr_regs->endpointlistaddr);
VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
- (int)udc->ep_qh, (int)tmp,
+ udc->ep_qh, (int)tmp,
fsl_readl(&dr_regs->endpointlistaddr));
/* Config PHY interface */
@@ -315,7 +304,8 @@ static void dr_controller_stop(struct fsl_udc *udc)
return;
}
-void dr_ep_setup(unsigned char ep_num, unsigned char dir, unsigned char ep_type)
+static void dr_ep_setup(unsigned char ep_num, unsigned char dir,
+ unsigned char ep_type)
{
unsigned int tmp_epctrl = 0;
@@ -563,7 +553,7 @@ static int fsl_ep_disable(struct usb_ep *_ep)
/* nuke all pending requests (does flush) */
nuke(ep, -ESHUTDOWN);
- ep->desc = 0;
+ ep->desc = NULL;
ep->stopped = 1;
spin_unlock_irqrestore(&udc->lock, flags);
@@ -602,7 +592,7 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
}
/*-------------------------------------------------------------------------*/
-static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
+static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
{
int i = ep_index(ep) * 2 + ep_is_in(ep);
u32 temp, bitmask, tmp_stat;
@@ -653,13 +643,16 @@ static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
| EP_QUEUE_HEAD_STATUS_HALT));
dQH->size_ioc_int_sts &= temp;
+ /* Ensure that updates to the QH will occure before priming. */
+ wmb();
+
/* Prime endpoint by writing 1 to ENDPTPRIME */
temp = ep_is_in(ep)
? (1 << (ep_index(ep) + 16))
: (1 << (ep_index(ep)));
fsl_writel(temp, &dr_regs->endpointprime);
out:
- return 0;
+ return;
}
/* Fill in the dTD structure
@@ -710,7 +703,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
*is_last = 0;
if ((*is_last) == 0)
- VDBG("multi-dtd request!\n");
+ VDBG("multi-dtd request!");
/* Fill in the transfer size; set active bit */
swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
@@ -773,11 +766,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
/* catch various bogus parameters */
if (!_req || !req->req.complete || !req->req.buf
|| !list_empty(&req->queue)) {
- VDBG("%s, bad params\n", __func__);
+ VDBG("%s, bad params", __func__);
return -EINVAL;
}
if (unlikely(!_ep || !ep->desc)) {
- VDBG("%s, bad ep\n", __func__);
+ VDBG("%s, bad ep", __func__);
return -EINVAL;
}
if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
@@ -1069,7 +1062,7 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
udc = container_of(gadget, struct fsl_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
- VDBG("VBUS %s\n", is_active ? "on" : "off");
+ VDBG("VBUS %s", is_active ? "on" : "off");
udc->vbus_active = (is_active != 0);
if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -1146,7 +1139,6 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
{
struct fsl_req *req = udc->status_req;
struct fsl_ep *ep;
- int status = 0;
if (direction == EP_DIR_IN)
udc->ep0_dir = USB_DIR_IN;
@@ -1164,27 +1156,21 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
req->dtd_count = 0;
if (fsl_req_to_dtd(req) == 0)
- status = fsl_queue_td(ep, req);
+ fsl_queue_td(ep, req);
else
return -ENOMEM;
- if (status)
- ERR("Can't queue ep0 status request \n");
list_add_tail(&req->queue, &ep->queue);
- return status;
+ return 0;
}
-static inline int udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
+static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
{
struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
- if (!ep->name)
- return 0;
-
- nuke(ep, -ESHUTDOWN);
-
- return 0;
+ if (ep->name)
+ nuke(ep, -ESHUTDOWN);
}
/*
@@ -1208,10 +1194,8 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
u16 index, u16 length)
{
u16 tmp = 0; /* Status, cpu endian */
-
struct fsl_req *req;
struct fsl_ep *ep;
- int status = 0;
ep = &udc->eps[0];
@@ -1250,14 +1234,10 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
/* prime the data phase */
if ((fsl_req_to_dtd(req) == 0))
- status = fsl_queue_td(ep, req);
+ fsl_queue_td(ep, req);
else /* no mem */
goto stall;
- if (status) {
- ERR("Can't respond to getstatus request \n");
- goto stall;
- }
list_add_tail(&req->queue, &ep->queue);
udc->ep0_state = DATA_STATE_XMIT;
return;
@@ -1397,7 +1377,7 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
udc->ep0_state = WAIT_FOR_SETUP;
break;
case WAIT_FOR_SETUP:
- ERR("Unexpect ep0 packets \n");
+ ERR("Unexpect ep0 packets\n");
break;
default:
ep0stall(udc);
@@ -1476,7 +1456,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
status = -EILSEQ;
break;
} else
- ERR("Unknown error has occured (0x%x)!\r\n",
+ ERR("Unknown error has occured (0x%x)!\n",
errors);
} else if (le32_to_cpu(curr_td->size_ioc_sts)
@@ -1495,7 +1475,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
}
} else {
td_complete++;
- VDBG("dTD transmitted successful ");
+ VDBG("dTD transmitted successful");
}
if (j != curr_req->dtd_count - 1)
@@ -1568,9 +1548,6 @@ static void port_change_irq(struct fsl_udc *udc)
{
u32 speed;
- if (udc->bus_reset)
- udc->bus_reset = 0;
-
/* Bus resetting is finished */
if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) {
/* Get the speed */
@@ -1678,8 +1655,6 @@ static void reset_irq(struct fsl_udc *udc)
if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
VDBG("Bus reset");
- /* Bus is reseting */
- udc->bus_reset = 1;
/* Reset all the queues, include XD, dTD, EP queue
* head and TR Queue */
reset_queues(udc);
@@ -1768,7 +1743,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
}
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
- VDBG("Error IRQ %x ", irq_src);
+ VDBG("Error IRQ %x", irq_src);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1799,7 +1774,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* lock is needed but whether should use this lock or another */
spin_lock_irqsave(&udc_controller->lock, flags);
- driver->driver.bus = 0;
+ driver->driver.bus = NULL;
/* hook up the driver */
udc_controller->driver = driver;
udc_controller->gadget.dev.driver = &driver->driver;
@@ -1809,8 +1784,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
retval = driver->bind(&udc_controller->gadget);
if (retval) {
VDBG("bind to %s --> %d", driver->driver.name, retval);
- udc_controller->gadget.dev.driver = 0;
- udc_controller->driver = 0;
+ udc_controller->gadget.dev.driver = NULL;
+ udc_controller->driver = NULL;
goto out;
}
@@ -1819,12 +1794,12 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_state = WAIT_FOR_SETUP;
udc_controller->ep0_dir = 0;
- printk(KERN_INFO "%s: bind to driver %s \n",
+ printk(KERN_INFO "%s: bind to driver %s\n",
udc_controller->gadget.name, driver->driver.name);
out:
if (retval)
- printk("retval %d \n", retval);
+ printk("gadget driver register failed %d\n", retval);
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -1842,7 +1817,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
if (udc_controller->transceiver)
- (void)otg_set_peripheral(udc_controller->transceiver, 0);
+ otg_set_peripheral(udc_controller->transceiver, NULL);
/* stop DR, disable intr */
dr_controller_stop(udc_controller);
@@ -1863,10 +1838,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
- udc_controller->gadget.dev.driver = 0;
- udc_controller->driver = 0;
+ udc_controller->gadget.dev.driver = NULL;
+ udc_controller->driver = NULL;
- printk("unregistered gadget driver '%s'\r\n", driver->driver.name);
+ printk("unregistered gadget driver '%s'\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
@@ -1922,7 +1897,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->usbsts);
t = scnprintf(next, size,
"USB Status Reg:\n"
- "Dr Suspend: %d" "Reset Received: %d" "System Error: %s"
+ "Dr Suspend: %d Reset Received: %d System Error: %s "
"USB Error Interrupt: %s\n\n",
(tmp_reg & USB_STS_SUSPEND) ? 1 : 0,
(tmp_reg & USB_STS_RESET) ? 1 : 0,
@@ -1934,11 +1909,11 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->usbintr);
t = scnprintf(next, size,
"USB Intrrupt Enable Reg:\n"
- "Sleep Enable: %d" "SOF Received Enable: %d"
+ "Sleep Enable: %d SOF Received Enable: %d "
"Reset Enable: %d\n"
- "System Error Enable: %d"
+ "System Error Enable: %d "
"Port Change Dectected Enable: %d\n"
- "USB Error Intr Enable: %d" "USB Intr Enable: %d\n\n",
+ "USB Error Intr Enable: %d USB Intr Enable: %d\n\n",
(tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0,
(tmp_reg & USB_INTR_SOF_EN) ? 1 : 0,
(tmp_reg & USB_INTR_RESET_EN) ? 1 : 0,
@@ -1951,21 +1926,21 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->frindex);
t = scnprintf(next, size,
- "USB Frame Index Reg:" "Frame Number is 0x%x\n\n",
+ "USB Frame Index Reg: Frame Number is 0x%x\n\n",
(tmp_reg & USB_FRINDEX_MASKS));
size -= t;
next += t;
tmp_reg = fsl_readl(&dr_regs->deviceaddr);
t = scnprintf(next, size,
- "USB Device Address Reg:" "Device Addr is 0x%x\n\n",
+ "USB Device Address Reg: Device Addr is 0x%x\n\n",
(tmp_reg & USB_DEVICE_ADDRESS_MASK));
size -= t;
next += t;
tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
t = scnprintf(next, size,
- "USB Endpoint List Address Reg:"
+ "USB Endpoint List Address Reg: "
"Device Addr is 0x%x\n\n",
(tmp_reg & USB_EP_LIST_ADDRESS_MASK));
size -= t;
@@ -1974,11 +1949,12 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->portsc1);
t = scnprintf(next, size,
"USB Port Status&Control Reg:\n"
- "Port Transceiver Type : %s" "Port Speed: %s \n"
- "PHY Low Power Suspend: %s" "Port Reset: %s"
- "Port Suspend Mode: %s \n" "Over-current Change: %s"
+ "Port Transceiver Type : %s Port Speed: %s\n"
+ "PHY Low Power Suspend: %s Port Reset: %s "
+ "Port Suspend Mode: %s\n"
+ "Over-current Change: %s "
"Port Enable/Disable Change: %s\n"
- "Port Enabled/Disabled: %s"
+ "Port Enabled/Disabled: %s "
"Current Connect Status: %s\n\n", ( {
char *s;
switch (tmp_reg & PORTSCX_PTS_FSLS) {
@@ -2023,7 +1999,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->usbmode);
t = scnprintf(next, size,
- "USB Mode Reg:" "Controller Mode is : %s\n\n", ( {
+ "USB Mode Reg: Controller Mode is: %s\n\n", ( {
char *s;
switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
case USB_MODE_CTRL_MODE_IDLE:
@@ -2042,7 +2018,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
t = scnprintf(next, size,
- "Endpoint Setup Status Reg:" "SETUP on ep 0x%x\n\n",
+ "Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
(tmp_reg & EP_SETUP_STATUS_MASK));
size -= t;
next += t;
@@ -2055,12 +2031,12 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
next += t;
}
tmp_reg = fsl_readl(&dr_regs->endpointprime);
- t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n", tmp_reg);
+ t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
size -= t;
next += t;
tmp_reg = usb_sys_regs->snoop1;
- t = scnprintf(next, size, "\nSnoop1 Reg : = [0x%x]\n\n", tmp_reg);
+ t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
size -= t;
next += t;
@@ -2084,7 +2060,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
} else {
list_for_each_entry(req, &ep->queue, queue) {
t = scnprintf(next, size,
- "req %p actual 0x%x length 0x%x buf %p\n",
+ "req %p actual 0x%x length 0x%x buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
size -= t;
@@ -2110,7 +2086,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
} else {
list_for_each_entry(req, &ep->queue, queue) {
t = scnprintf(next, size,
- "req %p actual 0x%x length"
+ "req %p actual 0x%x length "
"0x%x buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
@@ -2202,7 +2178,6 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
udc->usb_state = USB_STATE_POWERED;
udc->ep0_dir = 0;
udc->remote_wakeup = 0; /* default to 0 on reset */
- spin_lock_init(&udc->lock);
return 0;
}
@@ -2254,7 +2229,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
u32 dccparams;
if (strcmp(pdev->name, driver_name)) {
- VDBG("Wrong device\n");
+ VDBG("Wrong device");
return -ENODEV;
}
@@ -2264,23 +2239,26 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ spin_lock_init(&udc_controller->lock);
+ udc_controller->stopped = 1;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- kfree(udc_controller);
- return -ENXIO;
+ ret = -ENXIO;
+ goto err_kfree;
}
if (!request_mem_region(res->start, res->end - res->start + 1,
driver_name)) {
- ERR("request mem region for %s failed \n", pdev->name);
- kfree(udc_controller);
- return -EBUSY;
+ ERR("request mem region for %s failed\n", pdev->name);
+ ret = -EBUSY;
+ goto err_kfree;
}
dr_regs = ioremap(res->start, res->end - res->start + 1);
if (!dr_regs) {
ret = -ENOMEM;
- goto err1;
+ goto err_release_mem_region;
}
usb_sys_regs = (struct usb_sys_interface *)
@@ -2291,7 +2269,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (!(dccparams & DCCPARAMS_DC)) {
ERR("This SOC doesn't support device role\n");
ret = -ENODEV;
- goto err2;
+ goto err_iounmap;
}
/* Get max device endpoints */
/* DEN is bidirectional ep number, max_ep doubles the number */
@@ -2300,22 +2278,22 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
udc_controller->irq = platform_get_irq(pdev, 0);
if (!udc_controller->irq) {
ret = -ENODEV;
- goto err2;
+ goto err_iounmap;
}
ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
driver_name, udc_controller);
if (ret != 0) {
- ERR("cannot request irq %d err %d \n",
+ ERR("cannot request irq %d err %d\n",
udc_controller->irq, ret);
- goto err2;
+ goto err_iounmap;
}
/* Initialize the udc structure including QH member and other member */
if (struct_udc_setup(udc_controller, pdev)) {
ERR("Can't initialize udc data structure\n");
ret = -ENOMEM;
- goto err3;
+ goto err_free_irq;
}
/* initialize usb hw reg except for regs for EP,
@@ -2336,7 +2314,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
udc_controller->gadget.dev.parent = &pdev->dev;
ret = device_register(&udc_controller->gadget.dev);
if (ret < 0)
- goto err3;
+ goto err_free_irq;
/* setup QH and epctrl for ep0 */
ep0_setup(udc_controller);
@@ -2366,20 +2344,22 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
if (udc_controller->td_pool == NULL) {
ret = -ENOMEM;
- goto err4;
+ goto err_unregister;
}
create_proc_file();
return 0;
-err4:
+err_unregister:
device_unregister(&udc_controller->gadget.dev);
-err3:
+err_free_irq:
free_irq(udc_controller->irq, udc_controller);
-err2:
+err_iounmap:
iounmap(dr_regs);
-err1:
+err_release_mem_region:
release_mem_region(res->start, res->end - res->start + 1);
+err_kfree:
kfree(udc_controller);
+ udc_controller = NULL;
return ret;
}
@@ -2469,7 +2449,7 @@ module_init(udc_init);
static void __exit udc_exit(void)
{
platform_driver_unregister(&udc_driver);
- printk("%s unregistered \n", driver_desc);
+ printk("%s unregistered\n", driver_desc);
}
module_exit(udc_exit);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 6131752a38b..e63ef12645f 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -424,16 +424,6 @@ struct ep_td_struct {
/* Controller dma boundary */
#define UDC_DMA_BOUNDARY 0x1000
-/* -----------------------------------------------------------------------*/
-/* ##### enum data
-*/
-typedef enum {
- e_ULPI,
- e_UTMI_8BIT,
- e_UTMI_16BIT,
- e_SERIAL
-} e_PhyInterface;
-
/*-------------------------------------------------------------------------*/
/* ### driver private data
@@ -469,9 +459,9 @@ struct fsl_ep {
#define EP_DIR_OUT 0
struct fsl_udc {
-
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
+ struct completion *done; /* to make sure release() is done */
struct fsl_ep *eps;
unsigned int max_ep;
unsigned int irq;
@@ -492,20 +482,13 @@ struct fsl_udc {
size_t ep_qh_size; /* size after alignment adjustment*/
dma_addr_t ep_qh_dma; /* dma address of QH */
- u32 max_pipes; /* Device max pipes */
- u32 max_use_endpts; /* Max endpointes to be used */
- u32 bus_reset; /* Device is bus reseting */
+ u32 max_pipes; /* Device max pipes */
u32 resume_state; /* USB state to resume */
u32 usb_state; /* USB current state */
- u32 usb_next_state; /* USB next state */
u32 ep0_state; /* Endpoint zero state */
u32 ep0_dir; /* Endpoint zero direction: can be
USB_DIR_IN or USB_DIR_OUT */
- u32 usb_sof_count; /* SOF count */
- u32 errors; /* USB ERRORs count */
u8 device_address; /* Device USB address */
-
- struct completion *done; /* to make sure release() is done */
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 17d9905101b..4e3107dd2f3 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -151,6 +151,13 @@
#define gadget_is_m66592(g) 0
#endif
+/* Freescale CPM/QE UDC SUPPORT */
+#ifdef CONFIG_USB_GADGET_FSL_QE
+#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name)
+#else
+#define gadget_is_fsl_qe(g) 0
+#endif
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
@@ -216,6 +223,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x20;
else if (gadget_is_m66592(gadget))
return 0x21;
+ else if (gadget_is_fsl_qe(gadget))
+ return 0x22;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index ea8651e3da1..60d3f9e9b51 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -35,6 +35,21 @@
#include "gadget_chips.h"
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
+
MODULE_AUTHOR("Ben Williamson");
MODULE_LICENSE("GPL v2");
@@ -207,7 +222,7 @@ static struct usb_config_descriptor config_desc = {
* power properties of the device. Is it selfpowered?
*/
.bmAttributes = USB_CONFIG_ATT_ONE,
- .bMaxPower = 1,
+ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
};
/* B.3.1 Standard AC Interface Descriptor */
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 5cfb5ebf388..8ae70de2c37 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* ep_reset() has already been called */
ep->stopped = 0;
+ ep->wedged = 0;
ep->out_overflow = 0;
/* set speed-dependent max packet; may kick in high bandwidth */
@@ -1218,7 +1219,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
static int net2280_fifo_status (struct usb_ep *_ep);
static int
-net2280_set_halt (struct usb_ep *_ep, int value)
+net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
{
struct net2280_ep *ep;
unsigned long flags;
@@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value)
else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
retval = -EAGAIN;
else {
- VDEBUG (ep->dev, "%s %s halt\n", _ep->name,
- value ? "set" : "clear");
+ VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
+ value ? "set" : "clear",
+ wedged ? "wedge" : "halt");
/* set/clear, then synch memory views with the device */
if (value) {
if (ep->num == 0)
ep->dev->protocol_stall = 1;
else
set_halt (ep);
- } else
+ if (wedged)
+ ep->wedged = 1;
+ } else {
clear_halt (ep);
+ ep->wedged = 0;
+ }
(void) readl (&ep->regs->ep_rsp);
}
spin_unlock_irqrestore (&ep->dev->lock, flags);
@@ -1257,6 +1263,20 @@ net2280_set_halt (struct usb_ep *_ep, int value)
}
static int
+net2280_set_halt(struct usb_ep *_ep, int value)
+{
+ return net2280_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int
+net2280_set_wedge(struct usb_ep *_ep)
+{
+ if (!_ep || _ep->name == ep0name)
+ return -EINVAL;
+ return net2280_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static int
net2280_fifo_status (struct usb_ep *_ep)
{
struct net2280_ep *ep;
@@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = {
.dequeue = net2280_dequeue,
.set_halt = net2280_set_halt,
+ .set_wedge = net2280_set_wedge,
.fifo_status = net2280_fifo_status,
.fifo_flush = net2280_fifo_flush,
};
@@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0)
goto do_stall;
- clear_halt (e);
+ if (e->wedged) {
+ VDEBUG(dev, "%s wedged, halt not cleared\n",
+ ep->ep.name);
+ } else {
+ VDEBUG(dev, "%s clear halt\n", ep->ep.name);
+ clear_halt(e);
+ }
allow_status (ep);
- VDEBUG (dev, "%s clear halt\n", ep->ep.name);
goto next_endpoints;
}
break;
@@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0)
goto do_stall;
+ if (e->ep.name == ep0name)
+ goto do_stall;
set_halt (e);
allow_status (ep);
VDEBUG (dev, "%s set halt\n", ep->ep.name);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 81a71dbdc2c..c36852263d9 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -109,6 +109,7 @@ struct net2280_ep {
in_fifo_validate : 1,
out_overflow : 1,
stopped : 1,
+ wedged : 1,
is_in : 1,
is_iso : 1,
responded : 1;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 574c53831a0..34e9e393f92 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -787,7 +787,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_dest_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p(UDC_DATA_DMA),
+ UDC_DATA_DMA,
0, 0);
}
} else {
@@ -804,7 +804,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_src_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p(UDC_DATA_DMA),
+ UDC_DATA_DMA,
0, 0);
/* EMIFF or SDRC */
omap_set_dma_dest_burst_mode(ep->lch,
@@ -2313,6 +2313,13 @@ static int proc_otg_show(struct seq_file *s)
tmp = omap_readl(OTG_REV);
if (cpu_is_omap24xx()) {
+ /*
+ * REVISIT: Not clear how this works on OMAP2. trans
+ * is ANDed to produce bits 7 and 8, which might make
+ * sense for USB_TRANSCEIVER_CTRL on OMAP1,
+ * but with CONTROL_DEVCONF, these bits have something to
+ * do with the frame adjustment counter and McBSP2.
+ */
ctrl_name = "control_devconf";
trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
} else {
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index e0090085b78..5a3034fdfe4 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -53,6 +53,20 @@
#include "gadget_chips.h"
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
#define DRIVER_DESC "Printer Gadget"
#define DRIVER_VERSION "2007 OCT 06"
@@ -238,7 +252,7 @@ static struct usb_config_descriptor config_desc = {
.bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = 0,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1 /* Self-Powered */
+ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
};
static struct usb_interface_descriptor intf_desc = {
@@ -1264,8 +1278,7 @@ unknown:
/* respond with data transfer before status phase? */
if (value >= 0) {
req->length = value;
- req->zero = value < wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < wLength;
value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG(dev, "ep_queue --> %d\n", value);
@@ -1360,8 +1373,8 @@ printer_bind(struct usb_gadget *gadget)
/* Setup the sysfs files for the printer gadget. */
- dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
- g_printer_devno, NULL, "g_printer");
+ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
+ NULL, "g_printer");
if (IS_ERR(dev->pdev)) {
ERROR(dev, "Failed to create device: g_printer\n");
goto fail;
@@ -1463,7 +1476,6 @@ autoconf_fail:
if (gadget->is_otg) {
otg_desc.bmAttributes |= USB_OTG_HNP,
config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- config_desc.bMaxPower = 4;
}
spin_lock_init(&dev->lock);
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 7cbc78a6853..bcf375ca3d7 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 7228e856223..8c26f5ea2b8 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -57,11 +57,6 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
#define rndis_debug 0
#endif
-#define DBG(str,args...) do { \
- if (rndis_debug) \
- pr_debug(str , ## args); \
- } while (0)
-
#define RNDIS_MAX_CONFIGS 1
@@ -183,9 +178,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
if (!resp) return -ENOMEM;
if (buf_len && rndis_debug > 1) {
- DBG("query OID %08x value, len %d:\n", OID, buf_len);
+ pr_debug("query OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
- DBG("%03d: %08x %08x %08x %08x\n", i,
+ pr_debug("%03d: %08x %08x %08x %08x\n", i,
get_unaligned_le32(&buf[i]),
get_unaligned_le32(&buf[i + 4]),
get_unaligned_le32(&buf[i + 8]),
@@ -209,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
- DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
+ pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
length = sizeof (oid_supported_list);
count = length / sizeof (u32);
for (i = 0; i < count; i++)
@@ -219,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_HARDWARE_STATUS:
- DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
+ pr_debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
/* Bogus question!
* Hardware must be ready to receive high level protocols.
* BTW:
@@ -232,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MEDIA_SUPPORTED:
- DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
+ pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_IN_USE:
- DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
+ pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
/* one medium, one transport... (maybe you do it better) */
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
retval = 0;
@@ -247,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MAXIMUM_FRAME_SIZE:
- DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
+ pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -258,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_LINK_SPEED:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
+ pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
if (rndis_per_dev_params [configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
*outbuf = __constant_cpu_to_le32 (0);
@@ -270,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_TRANSMIT_BLOCK_SIZE:
- DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
+ pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -280,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RECEIVE_BLOCK_SIZE:
- DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
+ pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -290,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_ID:
- DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
+ pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].vendorID);
retval = 0;
@@ -298,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
- DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
+ pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
length = strlen (rndis_per_dev_params [configNr].vendorDescr);
memcpy (outbuf,
rndis_per_dev_params [configNr].vendorDescr, length);
@@ -306,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_VENDOR_DRIVER_VERSION:
- DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
+ pr_debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
/* Created as LE */
*outbuf = rndis_driver_version;
retval = 0;
@@ -314,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_CURRENT_PACKET_FILTER:
- DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
+ pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
retval = 0;
break;
/* mandatory */
case OID_GEN_MAXIMUM_TOTAL_SIZE:
- DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
+ pr_debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
retval = 0;
break;
@@ -329,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MEDIA_CONNECT_STATUS:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
+ pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.media_state);
retval = 0;
break;
case OID_GEN_PHYSICAL_MEDIUM:
- DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
+ pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -346,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
* versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
*/
case OID_GEN_MAC_OPTIONS: /* from WinME */
- DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
+ pr_debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
*outbuf = __constant_cpu_to_le32(
NDIS_MAC_OPTION_RECEIVE_SERIALIZED
| NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -358,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_XMIT_OK:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_XMIT_OK\n", __func__);
+ pr_debug("%s: OID_GEN_XMIT_OK\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->tx_packets
- stats->tx_errors - stats->tx_dropped);
@@ -369,7 +364,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_OK:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_RCV_OK\n", __func__);
+ pr_debug("%s: OID_GEN_RCV_OK\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->rx_packets
- stats->rx_errors - stats->rx_dropped);
@@ -380,7 +375,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_XMIT_ERROR:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
+ pr_debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->tx_errors);
retval = 0;
@@ -390,7 +385,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_ERROR:
if (rndis_debug > 1)
- DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
+ pr_debug("%s: OID_GEN_RCV_ERROR\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->rx_errors);
retval = 0;
@@ -399,7 +394,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_NO_BUFFER:
- DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
+ pr_debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->rx_dropped);
retval = 0;
@@ -410,7 +405,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_PERMANENT_ADDRESS:
- DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
+ pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
@@ -422,7 +417,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_CURRENT_ADDRESS:
- DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
+ pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
@@ -434,7 +429,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_MULTICAST_LIST:
- DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
/* Multicast base address only */
*outbuf = __constant_cpu_to_le32 (0xE0000000);
retval = 0;
@@ -442,21 +437,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_MAXIMUM_LIST_SIZE:
- DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
+ pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
/* Multicast base address only */
*outbuf = __constant_cpu_to_le32 (1);
retval = 0;
break;
case OID_802_3_MAC_OPTIONS:
- DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+ pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
break;
/* ieee802.3 statistics OIDs (table 4-4) */
/* mandatory */
case OID_802_3_RCV_ERROR_ALIGNMENT:
- DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
+ pr_debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
if (stats) {
*outbuf = cpu_to_le32(stats->rx_frame_errors);
retval = 0;
@@ -465,14 +460,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_XMIT_ONE_COLLISION:
- DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
+ pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
/* mandatory */
case OID_802_3_XMIT_MORE_COLLISIONS:
- DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
+ pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -504,9 +499,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
return -ENOMEM;
if (buf_len && rndis_debug > 1) {
- DBG("set OID %08x value, len %d:\n", OID, buf_len);
+ pr_debug("set OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
- DBG("%03d: %08x %08x %08x %08x\n", i,
+ pr_debug("%03d: %08x %08x %08x %08x\n", i,
get_unaligned_le32(&buf[i]),
get_unaligned_le32(&buf[i + 4]),
get_unaligned_le32(&buf[i + 8]),
@@ -525,7 +520,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
*params->filter = (u16)get_unaligned_le32(buf);
- DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+ pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__func__, *params->filter);
/* this call has a significant side effect: it's
@@ -547,7 +542,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
case OID_802_3_MULTICAST_LIST:
/* I think we can ignore this */
- DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
retval = 0;
break;
@@ -606,7 +601,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
- // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+ /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
if (!params->dev)
return -ENOTSUPP;
@@ -659,15 +654,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
BufOffset = le32_to_cpu (buf->InformationBufferOffset);
#ifdef VERBOSE_DEBUG
- DBG("%s: Length: %d\n", __func__, BufLength);
- DBG("%s: Offset: %d\n", __func__, BufOffset);
- DBG("%s: InfoBuffer: ", __func__);
+ pr_debug("%s: Length: %d\n", __func__, BufLength);
+ pr_debug("%s: Offset: %d\n", __func__, BufOffset);
+ pr_debug("%s: InfoBuffer: ", __func__);
for (i = 0; i < BufLength; i++) {
- DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+ pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
}
- DBG("\n");
+ pr_debug("\n");
#endif
resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -821,14 +816,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
/* For USB: responses may take up to 10 seconds */
switch (MsgType) {
case REMOTE_NDIS_INITIALIZE_MSG:
- DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+ pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
__func__ );
params->state = RNDIS_INITIALIZED;
return rndis_init_response (configNr,
(rndis_init_msg_type *) buf);
case REMOTE_NDIS_HALT_MSG:
- DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+ pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
__func__ );
params->state = RNDIS_UNINITIALIZED;
if (params->dev) {
@@ -846,7 +841,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
(rndis_set_msg_type *) buf);
case REMOTE_NDIS_RESET_MSG:
- DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+ pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
__func__ );
return rndis_reset_response (configNr,
(rndis_reset_msg_type *) buf);
@@ -854,7 +849,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
case REMOTE_NDIS_KEEPALIVE_MSG:
/* For USB: host does this every 5 seconds */
if (rndis_debug > 1)
- DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+ pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
__func__ );
return rndis_keepalive_response (configNr,
(rndis_keepalive_msg_type *)
@@ -870,7 +865,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
{
unsigned i;
for (i = 0; i < MsgLength; i += 16) {
- DBG("%03d: "
+ pr_debug("%03d: "
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
@@ -905,18 +900,18 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
rndis_per_dev_params [i].used = 1;
rndis_per_dev_params [i].resp_avail = resp_avail;
rndis_per_dev_params [i].v = v;
- DBG("%s: configNr = %d\n", __func__, i);
+ pr_debug("%s: configNr = %d\n", __func__, i);
return i;
}
}
- DBG("failed\n");
+ pr_debug("failed\n");
return -ENODEV;
}
void rndis_deregister (int configNr)
{
- DBG("%s: \n", __func__ );
+ pr_debug("%s: \n", __func__);
if (configNr >= RNDIS_MAX_CONFIGS) return;
rndis_per_dev_params [configNr].used = 0;
@@ -926,7 +921,7 @@ void rndis_deregister (int configNr)
int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
{
- DBG("%s:\n", __func__ );
+ pr_debug("%s:\n", __func__);
if (!dev)
return -EINVAL;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -939,7 +934,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
{
- DBG("%s:\n", __func__ );
+ pr_debug("%s:\n", __func__);
if (!vendorDescr) return -1;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -951,7 +946,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
{
- DBG("%s: %u %u\n", __func__, medium, speed);
+ pr_debug("%s: %u %u\n", __func__, medium, speed);
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].medium = medium;
@@ -1114,7 +1109,7 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
break;
default:
if (fl_speed) p->speed = speed;
- else DBG("%c is not valid\n", c);
+ else pr_debug("%c is not valid\n", c);
break;
}
@@ -1159,12 +1154,12 @@ int __init rndis_init (void)
&rndis_proc_fops,
(void *)(rndis_per_dev_params + i))))
{
- DBG("%s :remove entries", __func__);
+ pr_debug("%s :remove entries", __func__);
while (i) {
sprintf (name, NAME_TEMPLATE, --i);
remove_proc_entry (name, NULL);
}
- DBG("\n");
+ pr_debug("\n");
return -EIO;
}
#endif
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 29d13ebe750..48f51b12d2e 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1651,7 +1651,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return -EBUSY;
if (!driver->bind || !driver->setup
- || driver->speed != USB_SPEED_FULL) {
+ || driver->speed < USB_SPEED_FULL) {
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
driver->bind, driver->setup, driver->speed);
return -EINVAL;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b3699afff00..37879af1c43 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -30,6 +30,25 @@
/*-------------------------------------------------------------------------*/
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_acm.c"
+#include "f_obex.c"
+#include "f_serial.c"
+#include "u_serial.c"
+
+/*-------------------------------------------------------------------------*/
+
/* Thanks to NetChip Technologies for donating this product ID.
*
* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
@@ -38,6 +57,7 @@
#define GS_VENDOR_ID 0x0525 /* NetChip */
#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */
#define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */
+#define GS_CDC_OBEX_PRODUCT_ID 0xa4a9 /* ... as CDC-OBEX */
/* string IDs are assigned dynamically */
@@ -107,6 +127,10 @@ static int use_acm = true;
module_param(use_acm, bool, 0);
MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
+static int use_obex = false;
+module_param(use_obex, bool, 0);
+MODULE_PARM_DESC(use_obex, "Use CDC OBEX, default=no");
+
static unsigned n_ports = 1;
module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
@@ -121,6 +145,8 @@ static int __init serial_bind_config(struct usb_configuration *c)
for (i = 0; i < n_ports && status == 0; i++) {
if (use_acm)
status = acm_bind_config(c, i);
+ else if (use_obex)
+ status = obex_bind_config(c, i);
else
status = gser_bind_config(c, i);
}
@@ -133,7 +159,6 @@ static struct usb_configuration serial_config_driver = {
/* .bConfigurationValue = f(use_acm) */
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* 2 mA, minimal */
};
static int __init gs_bind(struct usb_composite_dev *cdev)
@@ -231,6 +256,12 @@ static int __init init(void)
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
__constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
+ } else if (use_obex) {
+ serial_config_driver.label = "CDC OBEX config";
+ serial_config_driver.bConfigurationValue = 3;
+ device_desc.bDeviceClass = USB_CLASS_COMM;
+ device_desc.idProduct =
+ __constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 3791e627190..66948b72bb9 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -52,7 +52,7 @@
* this single "physical" link to be used by multiple virtual links.)
*/
-#define DRIVER_VERSION "29-May-2008"
+#define UETH__VERSION "29-May-2008"
struct eth_dev {
/* lock is held while accessing port_usb
@@ -170,7 +170,7 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
struct eth_dev *dev = netdev_priv(net);
strlcpy(p->driver, "g_ether", sizeof p->driver);
- strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+ strlcpy(p->version, UETH__VERSION, sizeof p->version);
strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
}
@@ -873,6 +873,13 @@ struct net_device *gether_connect(struct gether *link)
spin_lock(&dev->lock);
dev->port_usb = link;
link->ioport = dev;
+ if (netif_running(dev->net)) {
+ if (link->open)
+ link->open(link);
+ } else {
+ if (link->close)
+ link->close(link);
+ }
spin_unlock(&dev->lock);
netif_carrier_on(dev->net);
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index af3910d01ae..300f0ed9475 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -62,5 +62,6 @@ void gserial_disconnect(struct gserial *);
/* functions are bound to configurations by a config or gadget driver */
int acm_bind_config(struct usb_configuration *c, u8 port_num);
int gser_bind_config(struct usb_configuration *c, u8 port_num);
+int obex_bind_config(struct usb_configuration *c, u8 port_num);
#endif /* __U_SERIAL_H */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index aa0bd4f126a..361d9659ac4 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -59,6 +59,23 @@
/*-------------------------------------------------------------------------*/
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module. So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_sourcesink.c"
+#include "f_loopback.c"
+
+/*-------------------------------------------------------------------------*/
+
#define DRIVER_VERSION "Cinco de Mayo 2008"
static const char longname[] = "Gadget Zero";
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index b0f8ed5a7fb..0cb53ca8d34 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -358,7 +358,8 @@ struct debug_buffer {
struct usb_bus *bus;
struct mutex mutex; /* protect filling of buffer */
size_t count; /* number of characters filled into buffer */
- char *page;
+ char *output_buf;
+ size_t alloc_size;
};
#define speed_char(info1) ({ char tmp; \
@@ -488,8 +489,8 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
hcd = bus_to_hcd(buf->bus);
ehci = hcd_to_ehci (hcd);
- next = buf->page;
- size = PAGE_SIZE;
+ next = buf->output_buf;
+ size = buf->alloc_size;
*next = 0;
@@ -510,7 +511,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
}
spin_unlock_irqrestore (&ehci->lock, flags);
- return strlen(buf->page);
+ return strlen(buf->output_buf);
}
#define DBG_SCHED_LIMIT 64
@@ -531,8 +532,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
hcd = bus_to_hcd(buf->bus);
ehci = hcd_to_ehci (hcd);
- next = buf->page;
- size = PAGE_SIZE;
+ next = buf->output_buf;
+ size = buf->alloc_size;
temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
size -= temp;
@@ -568,14 +569,16 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
for (temp = 0; temp < seen_count; temp++) {
if (seen [temp].ptr != p.ptr)
continue;
- if (p.qh->qh_next.ptr)
+ if (p.qh->qh_next.ptr) {
temp = scnprintf (next, size,
" ...");
- p.ptr = NULL;
+ size -= temp;
+ next += temp;
+ }
break;
}
/* show more info the first time around */
- if (temp == seen_count && p.ptr) {
+ if (temp == seen_count) {
u32 scratch = hc32_to_cpup(ehci,
&p.qh->hw_info1);
struct ehci_qtd *qtd;
@@ -649,7 +652,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
spin_unlock_irqrestore (&ehci->lock, flags);
kfree (seen);
- return PAGE_SIZE - size;
+ return buf->alloc_size - size;
}
#undef DBG_SCHED_LIMIT
@@ -665,14 +668,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
hcd = bus_to_hcd(buf->bus);
ehci = hcd_to_ehci (hcd);
- next = buf->page;
- size = PAGE_SIZE;
+ next = buf->output_buf;
+ size = buf->alloc_size;
spin_lock_irqsave (&ehci->lock, flags);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
size = scnprintf (next, size,
- "bus %s, device %s (driver " DRIVER_VERSION ")\n"
+ "bus %s, device %s\n"
"%s\n"
"SUSPENDED (no register access)\n",
hcd->self.controller->bus->name,
@@ -684,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
/* Capability Registers */
i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = scnprintf (next, size,
- "bus %s, device %s (driver " DRIVER_VERSION ")\n"
+ "bus %s, device %s\n"
"%s\n"
"EHCI %x.%02x, hcd state %d\n",
hcd->self.controller->bus->name,
@@ -808,7 +811,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
done:
spin_unlock_irqrestore (&ehci->lock, flags);
- return PAGE_SIZE - size;
+ return buf->alloc_size - size;
}
static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
@@ -822,6 +825,7 @@ static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
buf->bus = bus;
buf->fill_func = fill_func;
mutex_init(&buf->mutex);
+ buf->alloc_size = PAGE_SIZE;
}
return buf;
@@ -831,10 +835,10 @@ static int fill_buffer(struct debug_buffer *buf)
{
int ret = 0;
- if (!buf->page)
- buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!buf->output_buf)
+ buf->output_buf = (char *)vmalloc(buf->alloc_size);
- if (!buf->page) {
+ if (!buf->output_buf) {
ret = -ENOMEM;
goto out;
}
@@ -867,7 +871,7 @@ static ssize_t debug_output(struct file *file, char __user *user_buf,
mutex_unlock(&buf->mutex);
ret = simple_read_from_buffer(user_buf, len, offset,
- buf->page, buf->count);
+ buf->output_buf, buf->count);
out:
return ret;
@@ -879,8 +883,8 @@ static int debug_close(struct inode *inode, struct file *file)
struct debug_buffer *buf = file->private_data;
if (buf) {
- if (buf->page)
- free_page((unsigned long)buf->page);
+ if (buf->output_buf)
+ vfree(buf->output_buf);
kfree(buf);
}
@@ -895,10 +899,14 @@ static int debug_async_open(struct inode *inode, struct file *file)
static int debug_periodic_open(struct inode *inode, struct file *file)
{
- file->private_data = alloc_buffer(inode->i_private,
- fill_periodic_buffer);
+ struct debug_buffer *buf;
+ buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
+ if (!buf)
+ return -ENOMEM;
- return file->private_data ? 0 : -ENOMEM;
+ buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE;
+ file->private_data = buf;
+ return 0;
}
static int debug_registers_open(struct inode *inode, struct file *file)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d9d53f289ca..d343afacb0b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
@@ -59,7 +60,6 @@
* providing early devices for those host controllers to talk to!
*/
-#define DRIVER_VERSION "10 Dec 2004"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
@@ -145,16 +145,6 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
return -ETIMEDOUT;
}
-static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
- u32 mask, u32 done, int usec)
-{
- int error = handshake(ehci, ptr, mask, done, usec);
- if (error)
- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
-
- return error;
-}
-
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
@@ -173,6 +163,22 @@ static int ehci_halt (struct ehci_hcd *ehci)
STS_HALT, STS_HALT, 16 * 125);
}
+static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+ u32 mask, u32 done, int usec)
+{
+ int error;
+
+ error = handshake(ehci, ptr, mask, done, usec);
+ if (error) {
+ ehci_halt(ehci);
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+ ehci_err(ehci, "force halt; handhake %p %08x %08x -> %d\n",
+ ptr, mask, done, error);
+ }
+
+ return error;
+}
+
/* put TDI/ARC silicon into EHCI mode */
static void tdi_reset (struct ehci_hcd *ehci)
{
@@ -614,9 +620,9 @@ static int ehci_run (struct usb_hcd *hcd)
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
- "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
+ "USB %x.%x started, EHCI %x.%02x%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- temp >> 8, temp & 0xff, DRIVER_VERSION,
+ temp >> 8, temp & 0xff,
ignore_oc ? ", overcurrent ignored" : "");
ehci_writel(ehci, INTR_MASK,
@@ -700,7 +706,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
pcd_status = status;
/* resume root hub? */
- if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN))
+ if (!(cmd & CMD_RUN))
usb_hcd_resume_root_hub(hcd);
while (i--) {
@@ -709,8 +715,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
if (pstatus & PORT_OWNER)
continue;
- if (!(pstatus & PORT_RESUME)
- || ehci->reset_done [i] != 0)
+ if (!(test_bit(i, &ehci->suspended_ports) &&
+ ((pstatus & PORT_RESUME) ||
+ !(pstatus & PORT_SUSPEND)) &&
+ (pstatus & PORT_PE) &&
+ ehci->reset_done[i] == 0))
continue;
/* start 20 msec resume signaling from this port,
@@ -725,9 +734,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
- dbg_cmd (ehci, "fatal", ehci_readl(ehci,
- &ehci->regs->command));
- dbg_status (ehci, "fatal", status);
+ dbg_cmd(ehci, "fatal", cmd);
+ dbg_status(ehci, "fatal", status);
if (status & STS_HALT) {
ehci_err (ehci, "fatal error\n");
dead:
@@ -988,9 +996,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
-
-MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_LICENSE ("GPL");
@@ -1014,11 +1020,6 @@ MODULE_LICENSE ("GPL");
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
#endif
-#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE)
-#include "ehci-ppc-soc.c"
-#define PLATFORM_DRIVER ehci_ppc_soc_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
#include "ehci-ppc-of.c"
#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
@@ -1043,6 +1044,16 @@ static int __init ehci_hcd_init(void)
{
int retval = 0;
+ if (usb_disabled())
+ return -ENODEV;
+
+ printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
+ set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+ if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
+ test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
+ printk(KERN_WARNING "Warning! ehci_hcd should always be loaded"
+ " before uhci_hcd and ohci_hcd, not after\n");
+
pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
hcd_name,
sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
@@ -1050,8 +1061,10 @@ static int __init ehci_hcd_init(void)
#ifdef DEBUG
ehci_debug_root = debugfs_create_dir("ehci", NULL);
- if (!ehci_debug_root)
- return -ENOENT;
+ if (!ehci_debug_root) {
+ retval = -ENOENT;
+ goto err_debug;
+ }
#endif
#ifdef PLATFORM_DRIVER
@@ -1099,6 +1112,8 @@ clean0:
debugfs_remove(ehci_debug_root);
ehci_debug_root = NULL;
#endif
+err_debug:
+ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
return retval;
}
module_init(ehci_hcd_init);
@@ -1120,6 +1135,7 @@ static void __exit ehci_hcd_cleanup(void)
#ifdef DEBUG
debugfs_remove(ehci_debug_root);
#endif
+ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
}
module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 740835bb857..218f9660d7e 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -236,10 +236,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
if (test_bit(i, &ehci->bus_suspended) &&
- (temp & PORT_SUSPEND)) {
- ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+ (temp & PORT_SUSPEND))
temp |= PORT_RESUME;
- }
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
}
i = HCS_N_PORTS (ehci->hcs_params);
@@ -482,10 +480,9 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
* controller by the user.
*/
- if ((temp & mask) != 0
- || ((temp & PORT_RESUME) != 0
- && time_after_eq(jiffies,
- ehci->reset_done[i]))) {
+ if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend)
+ || (ehci->reset_done[i] && time_after_eq(
+ jiffies, ehci->reset_done[i]))) {
if (i < 7)
buf [0] |= 1 << (i + 1);
else
@@ -688,6 +685,7 @@ static int ehci_hub_control (
/* resume completed? */
else if (time_after_eq(jiffies,
ehci->reset_done[wIndex])) {
+ clear_bit(wIndex, &ehci->suspended_ports);
set_bit(wIndex, &ehci->port_c_suspend);
ehci->reset_done[wIndex] = 0;
@@ -734,6 +732,9 @@ static int ehci_hub_control (
ehci_readl(ehci, status_reg));
}
+ if (!(temp & (PORT_RESUME|PORT_RESET)))
+ ehci->reset_done[wIndex] = 0;
+
/* transfer dedicated ports to the companion hc */
if ((temp & PORT_CONNECT) &&
test_bit(wIndex, &ehci->companion_ports)) {
@@ -757,8 +758,17 @@ static int ehci_hub_control (
}
if (temp & PORT_PE)
status |= 1 << USB_PORT_FEAT_ENABLE;
- if (temp & (PORT_SUSPEND|PORT_RESUME))
+
+ /* maybe the port was unsuspended without our knowledge */
+ if (temp & (PORT_SUSPEND|PORT_RESUME)) {
status |= 1 << USB_PORT_FEAT_SUSPEND;
+ } else if (test_bit(wIndex, &ehci->suspended_ports)) {
+ clear_bit(wIndex, &ehci->suspended_ports);
+ ehci->reset_done[wIndex] = 0;
+ if (temp & PORT_PE)
+ set_bit(wIndex, &ehci->port_c_suspend);
+ }
+
if (temp & PORT_OC)
status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
if (temp & PORT_RESET)
@@ -803,6 +813,7 @@ static int ehci_hub_control (
|| (temp & PORT_RESET) != 0)
goto error;
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+ set_bit(wIndex, &ehci->suspended_ports);
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index f9575c40912..9c32063a0c2 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -1,7 +1,7 @@
/*
* IXP4XX EHCI Host Controller Driver
*
- * Author: Vladimir Barinov <vbarinov@ru.mvista.com>
+ * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
*
* Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
*
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
deleted file mode 100644
index 529590eb403..00000000000
--- a/drivers/usb/host/ehci-ppc-soc.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
- *
- * Bus Glue for PPC On-Chip EHCI driver
- * Tested on AMCC 440EPx
- *
- * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-
-extern int usb_disabled(void);
-
-/* called during probe() after chip reset completes */
-static int ehci_ppc_soc_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- retval = ehci_halt(ehci);
- if (retval)
- return retval;
-
- retval = ehci_init(hcd);
- if (retval)
- return retval;
-
- ehci->sbrn = 0x20;
- return ehci_reset(ehci);
-}
-
-/**
- * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_ehci_ppc_soc_probe(const struct hc_driver *driver,
- struct usb_hcd **hcd_out,
- struct platform_device *dev)
-{
- int retval;
- struct usb_hcd *hcd;
- struct ehci_hcd *ehci;
-
- if (dev->resource[1].flags != IORESOURCE_IRQ) {
- pr_debug("resource[1] is not IORESOURCE_IRQ");
- retval = -ENOMEM;
- }
- hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI");
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_debug("request_mem_region failed");
- retval = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_debug("ioremap failed");
- retval = -ENOMEM;
- goto err2;
- }
-
- ehci = hcd_to_ehci(hcd);
- ehci->big_endian_mmio = 1;
- ehci->big_endian_desc = 1;
- ehci->caps = hcd->regs;
- ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
-
- /* cache this readonly data; minimize chip reads */
- ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-#if defined(CONFIG_440EPX)
- /*
- * 440EPx Errata USBH_3
- * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
- */
- out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0));
- ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n");
-#endif
-
- retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
- if (retval == 0)
- return retval;
-
- iounmap(hcd->regs);
-err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
- usb_put_hcd(hcd);
- return retval;
-}
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev)
-{
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
-}
-
-static const struct hc_driver ehci_ppc_soc_hc_driver = {
- .description = hcd_name,
- .product_desc = "PPC-SOC EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_ppc_soc_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-};
-
-static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = NULL;
- int ret;
-
- pr_debug("In ehci_hcd_ppc_soc_drv_probe\n");
-
- if (usb_disabled())
- return -ENODEV;
-
- /* FIXME we only want one one probe() not two */
- ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
- return ret;
-}
-
-static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- /* FIXME we only want one one remove() not two */
- usb_ehci_ppc_soc_remove(hcd, pdev);
- return 0;
-}
-
-MODULE_ALIAS("platform:ppc-soc-ehci");
-static struct platform_driver ehci_ppc_soc_driver = {
- .probe = ehci_hcd_ppc_soc_drv_probe,
- .remove = ehci_hcd_ppc_soc_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ppc-soc-ehci",
- }
-};
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index b7853c8bac0..4a0c5a78b2e 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -437,6 +437,9 @@ static int enable_periodic (struct ehci_hcd *ehci)
u32 cmd;
int status;
+ if (ehci->periodic_sched++)
+ return 0;
+
/* did clearing PSE did take effect yet?
* takes effect only at frame boundaries...
*/
@@ -461,6 +464,9 @@ static int disable_periodic (struct ehci_hcd *ehci)
u32 cmd;
int status;
+ if (--ehci->periodic_sched)
+ return 0;
+
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
@@ -544,13 +550,10 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
: (qh->usecs * 8);
/* maybe enable periodic schedule processing */
- if (!ehci->periodic_sched++)
- return enable_periodic (ehci);
-
- return 0;
+ return enable_periodic(ehci);
}
-static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
{
unsigned i;
unsigned period;
@@ -586,9 +589,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh_put (qh);
/* maybe turn off periodic schedule */
- ehci->periodic_sched--;
- if (!ehci->periodic_sched)
- (void) disable_periodic (ehci);
+ return disable_periodic(ehci);
}
static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -1562,9 +1563,7 @@ itd_link_urb (
urb->hcpriv = NULL;
timer_action (ehci, TIMER_IO_WATCHDOG);
- if (unlikely (!ehci->periodic_sched++))
- return enable_periodic (ehci);
- return 0;
+ return enable_periodic(ehci);
}
#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
@@ -1642,7 +1641,7 @@ itd_complete (
ehci_urb_done(ehci, urb, 0);
retval = true;
urb = NULL;
- ehci->periodic_sched--;
+ (void) disable_periodic(ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (unlikely (list_empty (&stream->td_list))) {
@@ -1951,9 +1950,7 @@ sitd_link_urb (
urb->hcpriv = NULL;
timer_action (ehci, TIMER_IO_WATCHDOG);
- if (!ehci->periodic_sched++)
- return enable_periodic (ehci);
- return 0;
+ return enable_periodic(ehci);
}
/*-------------------------------------------------------------------------*/
@@ -2019,7 +2016,7 @@ sitd_complete (
ehci_urb_done(ehci, urb, 0);
retval = true;
urb = NULL;
- ehci->periodic_sched--;
+ (void) disable_periodic(ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (list_empty (&stream->td_list)) {
@@ -2243,8 +2240,7 @@ restart:
if (unlikely (modified)) {
if (likely(ehci->periodic_sched > 0))
goto restart;
- /* maybe we can short-circuit this scan! */
- disable_periodic(ehci);
+ /* short-circuit this scan */
now_uframe = clock;
break;
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 5799298364f..b11798d17ae 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -99,6 +99,8 @@ struct ehci_hcd { /* one per controller */
owned by the companion during a bus suspend */
unsigned long port_c_suspend; /* which ports have
the change-suspend feature turned on */
+ unsigned long suspended_ports; /* which ports are
+ suspended */
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
@@ -181,14 +183,16 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
* the async ring; just the I/O watchdog. Note that if a
* SHRINK were pending, OFF would never be requested.
*/
- if (timer_pending(&ehci->watchdog)
- && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
- & ehci->actions))
- return;
+ enum ehci_timer_action oldactions = ehci->actions;
if (!test_and_set_bit (action, &ehci->actions)) {
unsigned long t;
+ if (timer_pending(&ehci->watchdog)
+ && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+ & oldactions))
+ return;
+
switch (action) {
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
@@ -204,149 +208,13 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
- mod_timer(&ehci->watchdog, t + jiffies);
+ mod_timer(&ehci->watchdog, round_jiffies(t + jiffies));
}
}
/*-------------------------------------------------------------------------*/
-/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
-
-/* Section 2.2 Host Controller Capability Registers */
-struct ehci_caps {
- /* these fields are specified as 8 and 16 bit registers,
- * but some hosts can't perform 8 or 16 bit PCI accesses.
- */
- u32 hc_capbase;
-#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */
-#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */
- u32 hcs_params; /* HCSPARAMS - offset 0x4 */
-#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */
-#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */
-#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
-#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */
-#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */
-#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */
-#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
-
- u32 hcc_params; /* HCCPARAMS - offset 0x8 */
-#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */
-#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */
-#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */
-#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */
-#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
-#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */
- u8 portroute [8]; /* nibbles for routing - offset 0xC */
-} __attribute__ ((packed));
-
-
-/* Section 2.3 Host Controller Operational Registers */
-struct ehci_regs {
-
- /* USBCMD: offset 0x00 */
- u32 command;
-/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
-#define CMD_PARK (1<<11) /* enable "park" on async qh */
-#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */
-#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */
-#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */
-#define CMD_ASE (1<<5) /* async schedule enable */
-#define CMD_PSE (1<<4) /* periodic schedule enable */
-/* 3:2 is periodic frame list size */
-#define CMD_RESET (1<<1) /* reset HC not bus */
-#define CMD_RUN (1<<0) /* start/stop HC */
-
- /* USBSTS: offset 0x04 */
- u32 status;
-#define STS_ASS (1<<15) /* Async Schedule Status */
-#define STS_PSS (1<<14) /* Periodic Schedule Status */
-#define STS_RECL (1<<13) /* Reclamation */
-#define STS_HALT (1<<12) /* Not running (any reason) */
-/* some bits reserved */
- /* these STS_* flags are also intr_enable bits (USBINTR) */
-#define STS_IAA (1<<5) /* Interrupted on async advance */
-#define STS_FATAL (1<<4) /* such as some PCI access errors */
-#define STS_FLR (1<<3) /* frame list rolled over */
-#define STS_PCD (1<<2) /* port change detect */
-#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
-#define STS_INT (1<<0) /* "normal" completion (short, ...) */
-
- /* USBINTR: offset 0x08 */
- u32 intr_enable;
-
- /* FRINDEX: offset 0x0C */
- u32 frame_index; /* current microframe number */
- /* CTRLDSSEGMENT: offset 0x10 */
- u32 segment; /* address bits 63:32 if needed */
- /* PERIODICLISTBASE: offset 0x14 */
- u32 frame_list; /* points to periodic list */
- /* ASYNCLISTADDR: offset 0x18 */
- u32 async_next; /* address of next async queue head */
-
- u32 reserved [9];
-
- /* CONFIGFLAG: offset 0x40 */
- u32 configured_flag;
-#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
-
- /* PORTSC: offset 0x44 */
- u32 port_status [0]; /* up to N_PORTS */
-/* 31:23 reserved */
-#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */
-#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
-#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
-/* 19:16 for port testing */
-#define PORT_LED_OFF (0<<14)
-#define PORT_LED_AMBER (1<<14)
-#define PORT_LED_GREEN (2<<14)
-#define PORT_LED_MASK (3<<14)
-#define PORT_OWNER (1<<13) /* true: companion hc owns this port */
-#define PORT_POWER (1<<12) /* true: has power (see PPC) */
-#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */
-/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
-/* 9 reserved */
-#define PORT_RESET (1<<8) /* reset port */
-#define PORT_SUSPEND (1<<7) /* suspend port */
-#define PORT_RESUME (1<<6) /* resume it */
-#define PORT_OCC (1<<5) /* over current change */
-#define PORT_OC (1<<4) /* over current active */
-#define PORT_PEC (1<<3) /* port enable change */
-#define PORT_PE (1<<2) /* port enable */
-#define PORT_CSC (1<<1) /* connect status change */
-#define PORT_CONNECT (1<<0) /* device connected */
-#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
-} __attribute__ ((packed));
-
-#define USBMODE 0x68 /* USB Device mode */
-#define USBMODE_SDIS (1<<3) /* Stream disable */
-#define USBMODE_BE (1<<2) /* BE/LE endianness select */
-#define USBMODE_CM_HC (3<<0) /* host controller mode */
-#define USBMODE_CM_IDLE (0<<0) /* idle state */
-
-/* Appendix C, Debug port ... intended for use with special "debug devices"
- * that can help if there's no serial console. (nonstandard enumeration.)
- */
-struct ehci_dbg_port {
- u32 control;
-#define DBGP_OWNER (1<<30)
-#define DBGP_ENABLED (1<<28)
-#define DBGP_DONE (1<<16)
-#define DBGP_INUSE (1<<10)
-#define DBGP_ERRCODE(x) (((x)>>7)&0x07)
-# define DBGP_ERR_BAD 1
-# define DBGP_ERR_SIGNAL 2
-#define DBGP_ERROR (1<<6)
-#define DBGP_GO (1<<5)
-#define DBGP_OUT (1<<4)
-#define DBGP_LEN(x) (((x)>>0)&0x0f)
- u32 pids;
-#define DBGP_PID_GET(x) (((x)>>16)&0xff)
-#define DBGP_PID_SET(data,tok) (((data)<<8)|(tok))
- u32 data03;
- u32 data47;
- u32 address;
-#define DBGP_EPADDR(dev,ep) (((dev)<<8)|(ep))
-} __attribute__ ((packed));
+#include <linux/usb/ehci_def.h>
/*-------------------------------------------------------------------------*/
@@ -740,16 +608,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
/*
* Big-endian read/write functions are arch-specific.
* Other arches can be added if/when they're needed.
- *
- * REVISIT: arch/powerpc now has readl/writel_be, so the
- * definition below can die once the 4xx support is
- * finally ported over.
*/
-#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
-#define readl_be(addr) in_be32((__force unsigned *)addr)
-#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)
-#endif
-
#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX)
#define readl_be(addr) __raw_readl((__force unsigned *)addr)
#define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr)
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index ce1ca0ba051..4dda31b2689 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1562,11 +1562,12 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct isp116x *isp116x;
- struct resource *addr, *data;
+ struct resource *addr, *data, *ires;
void __iomem *addr_reg;
void __iomem *data_reg;
int irq;
int ret = 0;
+ unsigned long irqflags;
if (pdev->num_resources < 3) {
ret = -ENODEV;
@@ -1575,12 +1576,16 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- irq = platform_get_irq(pdev, 0);
- if (!addr || !data || irq < 0) {
+ ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!addr || !data || !ires) {
ret = -ENODEV;
goto err1;
}
+ irq = ires->start;
+ irqflags = ires->flags & IRQF_TRIGGER_MASK;
+
if (pdev->dev.dma_mask) {
DBG("DMA not supported\n");
ret = -EINVAL;
@@ -1634,7 +1639,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
goto err6;
}
- ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+ ret = usb_add_hcd(hcd, irq, irqflags | IRQF_DISABLED);
if (ret)
goto err6;
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 051ef7b6bdc..af849f59613 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -218,7 +218,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
* and reading back and checking the contents are same or not
*/
if (reg_data != 0xFACE) {
- err("scratch register mismatch %x", reg_data);
+ dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
goto clean;
}
@@ -232,9 +232,10 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
devflags);
- pci_set_drvdata(dev, hcd);
- if (!hcd)
+ if (!IS_ERR(hcd)) {
+ pci_set_drvdata(dev, hcd);
return 0;
+ }
clean:
status = -ENODEV;
iounmap(iobase);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 7cef1d2f7cc..d3269656aa4 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -649,7 +649,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
ohci_dbg_sw (ohci, &next, &size,
"bus %s, device %s\n"
"%s\n"
- "%s version " DRIVER_VERSION "\n",
+ "%s\n",
hcd->self.controller->bus->name,
dev_name(hcd->self.controller),
hcd->product_desc,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 89901962cbf..8647dab0d7f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -46,7 +46,6 @@
#include "../core/hcd.h"
-#define DRIVER_VERSION "2006 August 04"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
@@ -984,10 +983,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/
-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
-
MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE ("GPL");
#ifdef CONFIG_PCI
@@ -1095,9 +1092,10 @@ static int __init ohci_hcd_mod_init(void)
if (usb_disabled())
return -ENODEV;
- printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name);
+ printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
sizeof (struct ed), sizeof (struct td));
+ set_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
#ifdef DEBUG
ohci_debug_root = debugfs_create_dir("ohci", NULL);
@@ -1184,6 +1182,7 @@ static int __init ohci_hcd_mod_init(void)
error_debug:
#endif
+ clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
return retval;
}
module_init(ohci_hcd_mod_init);
@@ -1214,6 +1213,7 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef DEBUG
debugfs_remove(ohci_debug_root);
#endif
+ clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
}
module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 7ea9a7b3115..32bbce9718f 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -359,21 +359,24 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
/* Carry out polling-, autostop-, and autoresume-related state changes */
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
- int any_connected)
+ int any_connected, int rhsc_status)
{
int poll_rh = 1;
- int rhsc;
+ int rhsc_enable;
- rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
- switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ /* Some broken controllers never turn off RHCS in the interrupt
+ * status register. For their sake we won't re-enable RHSC
+ * interrupts if the interrupt bit is already active.
+ */
+ rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) &
+ OHCI_INTR_RHSC;
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
- /* If no status changes are pending, enable status-change
- * interrupts.
- */
- if (!rhsc && !changed) {
- rhsc = OHCI_INTR_RHSC;
- ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
+ /* If no status changes are pending, enable RHSC interrupts. */
+ if (!rhsc_enable && !rhsc_status && !changed) {
+ rhsc_enable = OHCI_INTR_RHSC;
+ ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable);
}
/* Keep on polling until we know a device is connected
@@ -383,7 +386,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
if (any_connected ||
!device_may_wakeup(&ohci_to_hcd(ohci)
->self.root_hub->dev)) {
- if (rhsc)
+ if (rhsc_enable)
poll_rh = 0;
} else {
ohci->autostop = 1;
@@ -396,34 +399,45 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
ohci->autostop = 0;
ohci->next_statechange = jiffies +
STATECHANGE_DELAY;
- } else if (rhsc && time_after_eq(jiffies,
+ } else if (time_after_eq(jiffies,
ohci->next_statechange)
&& !ohci->ed_rm_list
&& !(ohci->hc_control &
OHCI_SCHED_ENABLES)) {
ohci_rh_suspend(ohci, 1);
- poll_rh = 0;
+ if (rhsc_enable)
+ poll_rh = 0;
}
}
break;
- /* if there is a port change, autostart or ask to be resumed */
case OHCI_USB_SUSPEND:
case OHCI_USB_RESUME:
+ /* if there is a port change, autostart or ask to be resumed */
if (changed) {
if (ohci->autostop)
ohci_rh_resume(ohci);
else
usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
- } else {
- if (!rhsc && (ohci->autostop ||
- ohci_to_hcd(ohci)->self.root_hub->
- do_remote_wakeup))
- ohci_writel(ohci, OHCI_INTR_RHSC,
- &ohci->regs->intrenable);
- /* everything is idle, no need for polling */
+ /* If remote wakeup is disabled, stop polling */
+ } else if (!ohci->autostop &&
+ !ohci_to_hcd(ohci)->self.root_hub->
+ do_remote_wakeup) {
poll_rh = 0;
+
+ } else {
+ /* If no status changes are pending,
+ * enable RHSC interrupts
+ */
+ if (!rhsc_enable && !rhsc_status) {
+ rhsc_enable = OHCI_INTR_RHSC;
+ ohci_writel(ohci, rhsc_enable,
+ &ohci->regs->intrenable);
+ }
+ /* Keep polling until RHSC is enabled */
+ if (rhsc_enable)
+ poll_rh = 0;
}
break;
}
@@ -441,18 +455,22 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
* autostop isn't used when CONFIG_PM is turned off.
*/
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
- int any_connected)
+ int any_connected, int rhsc_status)
{
/* If RHSC is enabled, don't poll */
if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
return 0;
- /* If no status changes are pending, enable status-change interrupts */
- if (!changed) {
- ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
- return 0;
- }
- return 1;
+ /* If status changes are pending, continue polling.
+ * Conversely, if no status changes are pending but the RHSC
+ * status bit was set, then RHSC may be broken so continue polling.
+ */
+ if (changed || rhsc_status)
+ return 1;
+
+ /* It's safe to re-enable RHSC interrupts */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ return 0;
}
#endif /* CONFIG_PM */
@@ -467,6 +485,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
int any_connected = 0;
+ int rhsc_status;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -492,12 +511,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
length++;
}
- /* Some broken controllers never turn off RHCS in the interrupt
- * status register. For their sake we won't re-enable RHSC
- * interrupts if the flag is already set.
- */
- if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC)
- changed = 1;
+ /* Clear the RHSC status flag before reading the port statuses */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus);
+ rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
+ OHCI_INTR_RHSC;
/* look at each port */
for (i = 0; i < ohci->num_ports; i++) {
@@ -517,7 +534,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
- any_connected);
+ any_connected, rhsc_status);
done:
spin_unlock_irqrestore (&ohci->lock, flags);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 1eb64d08b60..91697bdb399 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -208,7 +208,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
if (cpu_is_omap16xx())
ocpi_enable();
-#ifdef CONFIG_ARCH_OMAP_OTG
+#ifdef CONFIG_USB_OTG
if (need_transceiver) {
ohci->transceiver = otg_get_transceiver();
if (ohci->transceiver) {
@@ -231,7 +231,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
omap_ohci_clock_power(1);
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
omap_1510_local_bus_power(1);
omap_1510_local_bus_init();
}
@@ -319,7 +319,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
if (IS_ERR(usb_host_ck))
return PTR_ERR(usb_host_ck);
- if (!cpu_is_omap1510())
+ if (!cpu_is_omap15xx())
usb_dc_ck = clk_get(0, "usb_dc_ck");
else
usb_dc_ck = clk_get(0, "lb_ck");
@@ -344,7 +344,12 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
goto err1;
}
- hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ dev_err(&pdev->dev, "can't ioremap OHCI HCD\n");
+ retval = -ENOMEM;
+ goto err2;
+ }
ohci = hcd_to_ohci(hcd);
ohci_hcd_init(ohci);
@@ -355,11 +360,11 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
retval = -ENXIO;
- goto err2;
+ goto err3;
}
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
if (retval)
- goto err2;
+ goto err3;
host_initialized = 1;
@@ -367,6 +372,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
omap_ohci_clock_power(0);
return 0;
+err3:
+ iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
@@ -401,6 +408,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
}
if (machine_is_omap_osk())
omap_free_gpio(9);
+ iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
clk_put(usb_dc_ck);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 658a2a978c3..e306ca6aef3 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -331,7 +331,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
int ret = 0, irq;
- dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name);
+ dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name);
if (usb_disabled()) {
err("USB is disabled");
ret = -ENODEV;
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 7f0f35c7818..e294d430733 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -23,17 +23,90 @@
#include <linux/signal.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h> /* FIXME: for PSSR */
#include <mach/ohci.h>
+/*
+ * UHC: USB Host Controller (OHCI-like) register definitions
+ */
+#define UHCREV (0x0000) /* UHC HCI Spec Revision */
+#define UHCHCON (0x0004) /* UHC Host Control Register */
+#define UHCCOMS (0x0008) /* UHC Command Status Register */
+#define UHCINTS (0x000C) /* UHC Interrupt Status Register */
+#define UHCINTE (0x0010) /* UHC Interrupt Enable */
+#define UHCINTD (0x0014) /* UHC Interrupt Disable */
+#define UHCHCCA (0x0018) /* UHC Host Controller Comm. Area */
+#define UHCPCED (0x001C) /* UHC Period Current Endpt Descr */
+#define UHCCHED (0x0020) /* UHC Control Head Endpt Descr */
+#define UHCCCED (0x0024) /* UHC Control Current Endpt Descr */
+#define UHCBHED (0x0028) /* UHC Bulk Head Endpt Descr */
+#define UHCBCED (0x002C) /* UHC Bulk Current Endpt Descr */
+#define UHCDHEAD (0x0030) /* UHC Done Head */
+#define UHCFMI (0x0034) /* UHC Frame Interval */
+#define UHCFMR (0x0038) /* UHC Frame Remaining */
+#define UHCFMN (0x003C) /* UHC Frame Number */
+#define UHCPERS (0x0040) /* UHC Periodic Start */
+#define UHCLS (0x0044) /* UHC Low Speed Threshold */
+
+#define UHCRHDA (0x0048) /* UHC Root Hub Descriptor A */
+#define UHCRHDA_NOCP (1 << 12) /* No over current protection */
+#define UHCRHDA_OCPM (1 << 11) /* Over Current Protection Mode */
+#define UHCRHDA_POTPGT(x) \
+ (((x) & 0xff) << 24) /* Power On To Power Good Time */
+
+#define UHCRHDB (0x004C) /* UHC Root Hub Descriptor B */
+#define UHCRHS (0x0050) /* UHC Root Hub Status */
+#define UHCRHPS1 (0x0054) /* UHC Root Hub Port 1 Status */
+#define UHCRHPS2 (0x0058) /* UHC Root Hub Port 2 Status */
+#define UHCRHPS3 (0x005C) /* UHC Root Hub Port 3 Status */
+
+#define UHCSTAT (0x0060) /* UHC Status Register */
+#define UHCSTAT_UPS3 (1 << 16) /* USB Power Sense Port3 */
+#define UHCSTAT_SBMAI (1 << 15) /* System Bus Master Abort Interrupt*/
+#define UHCSTAT_SBTAI (1 << 14) /* System Bus Target Abort Interrupt*/
+#define UHCSTAT_UPRI (1 << 13) /* USB Port Resume Interrupt */
+#define UHCSTAT_UPS2 (1 << 12) /* USB Power Sense Port 2 */
+#define UHCSTAT_UPS1 (1 << 11) /* USB Power Sense Port 1 */
+#define UHCSTAT_HTA (1 << 10) /* HCI Target Abort */
+#define UHCSTAT_HBA (1 << 8) /* HCI Buffer Active */
+#define UHCSTAT_RWUE (1 << 7) /* HCI Remote Wake Up Event */
+
+#define UHCHR (0x0064) /* UHC Reset Register */
+#define UHCHR_SSEP3 (1 << 11) /* Sleep Standby Enable for Port3 */
+#define UHCHR_SSEP2 (1 << 10) /* Sleep Standby Enable for Port2 */
+#define UHCHR_SSEP1 (1 << 9) /* Sleep Standby Enable for Port1 */
+#define UHCHR_PCPL (1 << 7) /* Power control polarity low */
+#define UHCHR_PSPL (1 << 6) /* Power sense polarity low */
+#define UHCHR_SSE (1 << 5) /* Sleep Standby Enable */
+#define UHCHR_UIT (1 << 4) /* USB Interrupt Test */
+#define UHCHR_SSDC (1 << 3) /* Simulation Scale Down Clock */
+#define UHCHR_CGR (1 << 2) /* Clock Generation Reset */
+#define UHCHR_FHR (1 << 1) /* Force Host Controller Reset */
+#define UHCHR_FSBIR (1 << 0) /* Force System Bus Iface Reset */
+
+#define UHCHIE (0x0068) /* UHC Interrupt Enable Register*/
+#define UHCHIE_UPS3IE (1 << 14) /* Power Sense Port3 IntEn */
+#define UHCHIE_UPRIE (1 << 13) /* Port Resume IntEn */
+#define UHCHIE_UPS2IE (1 << 12) /* Power Sense Port2 IntEn */
+#define UHCHIE_UPS1IE (1 << 11) /* Power Sense Port1 IntEn */
+#define UHCHIE_TAIE (1 << 10) /* HCI Interface Transfer Abort
+ Interrupt Enable*/
+#define UHCHIE_HBAIE (1 << 8) /* HCI Buffer Active IntEn */
+#define UHCHIE_RWIE (1 << 7) /* Remote Wake-up IntEn */
+
+#define UHCHIT (0x006C) /* UHC Interrupt Test register */
+
#define PXA_UHC_MAX_PORTNUM 3
-#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
+struct pxa27x_ohci {
+ /* must be 1st member here for hcd_to_ohci() to work */
+ struct ohci_hcd ohci;
+
+ struct device *dev;
+ struct clk *clk;
+ void __iomem *mmio_base;
+};
-static struct clk *usb_clk;
+#define to_pxa27x_ohci(hcd) (struct pxa27x_ohci *)hcd_to_ohci(hcd)
/*
PMM_NPS_MODE -- PMM Non-power switching mode
@@ -45,30 +118,35 @@ static struct clk *usb_clk;
PMM_PERPORT_MODE -- PMM per port switching mode
Ports are powered individually.
*/
-static int pxa27x_ohci_select_pmm( int mode )
+static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *ohci, int mode)
{
- switch ( mode ) {
+ uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
+ uint32_t uhcrhdb = __raw_readl(ohci->mmio_base + UHCRHDB);
+
+ switch (mode) {
case PMM_NPS_MODE:
- UHCRHDA |= RH_A_NPS;
+ uhcrhda |= RH_A_NPS;
break;
case PMM_GLOBAL_MODE:
- UHCRHDA &= ~(RH_A_NPS & RH_A_PSM);
+ uhcrhda &= ~(RH_A_NPS & RH_A_PSM);
break;
case PMM_PERPORT_MODE:
- UHCRHDA &= ~(RH_A_NPS);
- UHCRHDA |= RH_A_PSM;
+ uhcrhda &= ~(RH_A_NPS);
+ uhcrhda |= RH_A_PSM;
/* Set port power control mask bits, only 3 ports. */
- UHCRHDB |= (0x7<<17);
+ uhcrhdb |= (0x7<<17);
break;
default:
printk( KERN_ERR
"Invalid mode %d, set to non-power switch mode.\n",
mode );
- UHCRHDA |= RH_A_NPS;
+ uhcrhda |= RH_A_NPS;
}
+ __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
+ __raw_writel(uhcrhdb, ohci->mmio_base + UHCRHDB);
return 0;
}
@@ -76,57 +154,110 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
-static int pxa27x_start_hc(struct device *dev)
+static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci,
+ struct pxaohci_platform_data *inf)
+{
+ uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
+ uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
+
+ if (inf->flags & ENABLE_PORT1)
+ uhchr &= ~UHCHR_SSEP1;
+
+ if (inf->flags & ENABLE_PORT2)
+ uhchr &= ~UHCHR_SSEP2;
+
+ if (inf->flags & ENABLE_PORT3)
+ uhchr &= ~UHCHR_SSEP3;
+
+ if (inf->flags & POWER_CONTROL_LOW)
+ uhchr |= UHCHR_PCPL;
+
+ if (inf->flags & POWER_SENSE_LOW)
+ uhchr |= UHCHR_PSPL;
+
+ if (inf->flags & NO_OC_PROTECTION)
+ uhcrhda |= UHCRHDA_NOCP;
+
+ if (inf->flags & OC_MODE_PERPORT)
+ uhcrhda |= UHCRHDA_OCPM;
+
+ if (inf->power_on_delay) {
+ uhcrhda &= ~UHCRHDA_POTPGT(0xff);
+ uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2);
+ }
+
+ __raw_writel(uhchr, ohci->mmio_base + UHCHR);
+ __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
+}
+
+static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci)
+{
+ uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
+
+ __raw_writel(uhchr | UHCHR_FHR, ohci->mmio_base + UHCHR);
+ udelay(11);
+ __raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR);
+}
+
+#ifdef CONFIG_CPU_PXA27x
+extern void pxa27x_clear_otgph(void);
+#else
+#define pxa27x_clear_otgph() do {} while (0)
+#endif
+
+static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
{
int retval = 0;
struct pxaohci_platform_data *inf;
+ uint32_t uhchr;
inf = dev->platform_data;
- clk_enable(usb_clk);
+ clk_enable(ohci->clk);
- UHCHR |= UHCHR_FHR;
- udelay(11);
- UHCHR &= ~UHCHR_FHR;
+ pxa27x_reset_hc(ohci);
+
+ uhchr = __raw_readl(ohci->mmio_base + UHCHR) | UHCHR_FSBIR;
+ __raw_writel(uhchr, ohci->mmio_base + UHCHR);
- UHCHR |= UHCHR_FSBIR;
- while (UHCHR & UHCHR_FSBIR)
+ while (__raw_readl(ohci->mmio_base + UHCHR) & UHCHR_FSBIR)
cpu_relax();
+ pxa27x_setup_hc(ohci, inf);
+
if (inf->init)
retval = inf->init(dev);
if (retval < 0)
return retval;
- UHCHR &= ~UHCHR_SSE;
-
- UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
+ uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
+ __raw_writel(uhchr, ohci->mmio_base + UHCHR);
+ __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE);
/* Clear any OTG Pin Hold */
- if (cpu_is_pxa27x() && (PSSR & PSSR_OTGPH))
- PSSR |= PSSR_OTGPH;
-
+ pxa27x_clear_otgph();
return 0;
}
-static void pxa27x_stop_hc(struct device *dev)
+static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
{
struct pxaohci_platform_data *inf;
+ uint32_t uhccoms;
inf = dev->platform_data;
if (inf->exit)
inf->exit(dev);
- UHCHR |= UHCHR_FHR;
- udelay(11);
- UHCHR &= ~UHCHR_FHR;
+ pxa27x_reset_hc(ohci);
- UHCCOMS |= 1;
+ /* Host Controller Reset */
+ uhccoms = __raw_readl(ohci->mmio_base + UHCCOMS) | 0x01;
+ __raw_writel(uhccoms, ohci->mmio_base + UHCCOMS);
udelay(10);
- clk_disable(usb_clk);
+ clk_disable(ohci->clk);
}
@@ -147,18 +278,22 @@ static void pxa27x_stop_hc(struct device *dev)
*/
int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
- int retval;
+ int retval, irq;
struct usb_hcd *hcd;
struct pxaohci_platform_data *inf;
+ struct pxa27x_ohci *ohci;
+ struct resource *r;
+ struct clk *usb_clk;
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;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ pr_err("no resource of IORESOURCE_IRQ");
+ return -ENXIO;
}
usb_clk = clk_get(&pdev->dev, "USBCLK");
@@ -168,8 +303,16 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
if (!hcd)
return -ENOMEM;
- hcd->rsrc_start = pdev->resource[0].start;
- hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ pr_err("no resource of IORESOURCE_MEM");
+ retval = -ENXIO;
+ goto err1;
+ }
+
+ hcd->rsrc_start = r->start;
+ hcd->rsrc_len = resource_size(r);
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed");
@@ -184,24 +327,30 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
goto err2;
}
- if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
+ /* initialize "struct pxa27x_ohci" */
+ ohci = (struct pxa27x_ohci *)hcd_to_ohci(hcd);
+ ohci->dev = &pdev->dev;
+ ohci->clk = usb_clk;
+ ohci->mmio_base = (void __iomem *)hcd->regs;
+
+ if ((retval = pxa27x_start_hc(ohci, &pdev->dev)) < 0) {
pr_debug("pxa27x_start_hc failed");
goto err3;
}
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm(inf->port_mode);
+ pxa27x_ohci_select_pmm(ohci, inf->port_mode);
if (inf->power_budget)
hcd->power_budget = inf->power_budget;
ohci_hcd_init(hcd_to_ohci(hcd));
- retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED);
+ retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
if (retval == 0)
return retval;
- pxa27x_stop_hc(&pdev->dev);
+ pxa27x_stop_hc(ohci, &pdev->dev);
err3:
iounmap(hcd->regs);
err2:
@@ -228,12 +377,14 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
*/
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
+ struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+
usb_remove_hcd(hcd);
- pxa27x_stop_hc(&pdev->dev);
+ pxa27x_stop_hc(ohci, &pdev->dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- clk_put(usb_clk);
+ clk_put(ohci->clk);
}
/*-------------------------------------------------------------------------*/
@@ -266,7 +417,7 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
static const struct hc_driver ohci_pxa27x_hc_driver = {
.description = hcd_name,
.product_desc = "PXA27x OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
+ .hcd_priv_size = sizeof(struct pxa27x_ohci),
/*
* generic hardware linkage
@@ -330,13 +481,13 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
- if (time_before(jiffies, ohci->next_statechange))
+ if (time_before(jiffies, ohci->ohci.next_statechange))
msleep(5);
- ohci->next_statechange = jiffies;
+ ohci->ohci.next_statechange = jiffies;
- pxa27x_stop_hc(&pdev->dev);
+ pxa27x_stop_hc(ohci, &pdev->dev);
hcd->state = HC_STATE_SUSPENDED;
return 0;
@@ -345,14 +496,14 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_
static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
int status;
- if (time_before(jiffies, ohci->next_statechange))
+ if (time_before(jiffies, ohci->ohci.next_statechange))
msleep(5);
- ohci->next_statechange = jiffies;
+ ohci->ohci.next_statechange = jiffies;
- if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ if ((status = pxa27x_start_hc(ohci, &pdev->dev)) < 0)
return status;
ohci_finish_controller_resume(hcd);
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index faf622eafce..222011f6172 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -540,15 +540,7 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci)
* Big-endian read/write functions are arch-specific.
* Other arches can be added if/when they're needed.
*
- * REVISIT: arch/powerpc now has readl/writel_be, so the
- * definition below can die once the STB04xxx support is
- * finally ported over.
*/
-#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
-#define readl_be(addr) in_be32((__force unsigned *)addr)
-#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)
-#endif
-
static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci,
__hc32 __iomem * regs)
{
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index ea7126f99ca..c18d8790c41 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -66,7 +66,7 @@ static unsigned short endian;
module_param(endian, ushort, 0644);
MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
-static unsigned short irq_sense = INTL;
+static unsigned short irq_sense = 0xff;
module_param(irq_sense, ushort, 0644);
MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0 "
"(default=32)");
@@ -118,7 +118,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
r8a66597_write(r8a66597, SCKE, SYSCFG0);
tmp = r8a66597_read(r8a66597, SYSCFG0);
if (i++ > 1000) {
- err("register access fail.");
+ printk(KERN_ERR "r8a66597: register access fail.\n");
return -ENXIO;
}
} while ((tmp & SCKE) != SCKE);
@@ -128,7 +128,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
r8a66597_write(r8a66597, USBE, SYSCFG0);
tmp = r8a66597_read(r8a66597, SYSCFG0);
if (i++ > 1000) {
- err("register access fail.");
+ printk(KERN_ERR "r8a66597: register access fail.\n");
return -ENXIO;
}
} while ((tmp & USBE) != USBE);
@@ -141,7 +141,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
msleep(1);
tmp = r8a66597_read(r8a66597, SYSCFG0);
if (i++ > 500) {
- err("register access fail.");
+ printk(KERN_ERR "r8a66597: register access fail.\n");
return -ENXIO;
}
} while ((tmp & SCKE) != SCKE);
@@ -265,7 +265,7 @@ static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
if (root_port) {
*root_port = (devpath[0] & 0x0F) - 1;
if (*root_port >= R8A66597_MAX_ROOT_HUB)
- err("illegal root port number");
+ printk(KERN_ERR "r8a66597: Illegal root port number.\n");
}
if (hub_port)
*hub_port = devpath[2] & 0x0F;
@@ -286,7 +286,7 @@ static u16 get_r8a66597_usb_speed(enum usb_device_speed speed)
usbspd = HSMODE;
break;
default:
- err("unknown speed");
+ printk(KERN_ERR "r8a66597: unknown speed\n");
break;
}
@@ -385,7 +385,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
struct r8a66597_device *dev;
if (is_hub_limit(urb->dev->devpath)) {
- err("Externel hub limit reached.");
+ dev_err(&urb->dev->dev, "External hub limit reached.\n");
return 0;
}
@@ -406,8 +406,9 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
return addr;
}
- err("cannot communicate with a USB device more than 10.(%x)",
- r8a66597->address_map);
+ dev_err(&urb->dev->dev,
+ "cannot communicate with a USB device more than 10.(%x)\n",
+ r8a66597->address_map);
return 0;
}
@@ -447,7 +448,8 @@ static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
do {
tmp = r8a66597_read(r8a66597, reg);
if (i++ > 1000000) {
- err("register%lx, loop %x is timeout", reg, loop);
+ printk(KERN_ERR "r8a66597: register%lx, loop %x "
+ "is timeout\n", reg, loop);
break;
}
ndelay(1);
@@ -675,7 +677,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
array[i++] = 1;
break;
default:
- err("Illegal type");
+ printk(KERN_ERR "r8a66597: Illegal type\n");
return 0;
}
@@ -705,7 +707,7 @@ static u16 get_r8a66597_type(__u8 type)
r8a66597_type = R8A66597_ISO;
break;
default:
- err("Illegal type");
+ printk(KERN_ERR "r8a66597: Illegal type\n");
r8a66597_type = 0x0000;
break;
}
@@ -724,7 +726,7 @@ static u16 get_bufnum(u16 pipenum)
else if (check_interrupt(pipenum))
bufnum = 4 + (pipenum - 6);
else
- err("Illegal pipenum (%d)", pipenum);
+ printk(KERN_ERR "r8a66597: Illegal pipenum (%d)\n", pipenum);
return bufnum;
}
@@ -740,7 +742,7 @@ static u16 get_buf_bsize(u16 pipenum)
else if (check_interrupt(pipenum))
buf_bsize = 0;
else
- err("Illegal pipenum (%d)", pipenum);
+ printk(KERN_ERR "r8a66597: Illegal pipenum (%d)\n", pipenum);
return buf_bsize;
}
@@ -760,10 +762,12 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
if ((r8a66597->dma_map & (1 << i)) != 0)
continue;
- info("address %d, EndpointAddress 0x%02x use DMA FIFO",
- usb_pipedevice(urb->pipe),
- info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum
- : info->epnum);
+ dev_info(&dev->udev->dev,
+ "address %d, EndpointAddress 0x%02x use "
+ "DMA FIFO\n", usb_pipedevice(urb->pipe),
+ info->dir_in ?
+ USB_ENDPOINT_DIR_MASK + info->epnum
+ : info->epnum);
r8a66597->dma_map |= 1 << i;
dev->dma_map |= 1 << i;
@@ -1187,7 +1191,7 @@ static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
prepare_status_packet(r8a66597, td);
break;
default:
- err("invalid type.");
+ printk(KERN_ERR "r8a66597: invalid type.\n");
break;
}
@@ -1295,7 +1299,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
if (unlikely((tmp & FRDY) == 0)) {
pipe_stop(r8a66597, td->pipe);
pipe_irq_disable(r8a66597, pipenum);
- err("in fifo not ready (%d)", pipenum);
+ printk(KERN_ERR "r8a66597: in fifo not ready (%d)\n", pipenum);
finish_request(r8a66597, td, pipenum, td->urb, -EPIPE);
return;
}
@@ -1370,7 +1374,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
if (unlikely((tmp & FRDY) == 0)) {
pipe_stop(r8a66597, td->pipe);
pipe_irq_disable(r8a66597, pipenum);
- err("out write fifo not ready. (%d)", pipenum);
+ printk(KERN_ERR "r8a66597: out fifo not ready (%d)\n", pipenum);
finish_request(r8a66597, td, pipenum, urb, -EPIPE);
return;
}
@@ -2005,7 +2009,7 @@ static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597,
return dev;
}
- err("get_r8a66597_device fail.(%d)\n", addr);
+ printk(KERN_ERR "r8a66597: get_r8a66597_device fail.(%d)\n", addr);
return NULL;
}
@@ -2263,7 +2267,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
#define resource_len(r) (((r)->end - (r)->start) + 1)
static int __init r8a66597_probe(struct platform_device *pdev)
{
- struct resource *res = NULL;
+ struct resource *res = NULL, *ires;
int irq = -1;
void __iomem *reg = NULL;
struct usb_hcd *hcd = NULL;
@@ -2274,7 +2278,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
if (pdev->dev.dma_mask) {
ret = -EINVAL;
- err("dma not support");
+ dev_err(&pdev->dev, "dma not supported\n");
goto clean_up;
}
@@ -2282,21 +2286,25 @@ static int __init r8a66597_probe(struct platform_device *pdev)
(char *)hcd_name);
if (!res) {
ret = -ENODEV;
- err("platform_get_resource_byname error.");
+ dev_err(&pdev->dev, "platform_get_resource_byname error.\n");
goto clean_up;
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
+ ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!ires) {
ret = -ENODEV;
- err("platform_get_irq error.");
+ dev_err(&pdev->dev,
+ "platform_get_resource IORESOURCE_IRQ error.\n");
goto clean_up;
}
+ irq = ires->start;
+ irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
reg = ioremap(res->start, resource_len(res));
if (reg == NULL) {
ret = -ENOMEM;
- err("ioremap error.");
+ dev_err(&pdev->dev, "ioremap error.\n");
goto clean_up;
}
@@ -2304,7 +2312,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name);
if (!hcd) {
ret = -ENOMEM;
- err("Failed to create hcd");
+ dev_err(&pdev->dev, "Failed to create hcd\n");
goto clean_up;
}
r8a66597 = hcd_to_r8a66597(hcd);
@@ -2329,13 +2337,33 @@ static int __init r8a66597_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&r8a66597->child_device);
hcd->rsrc_start = res->start;
- if (irq_sense == INTL)
- irq_trigger = IRQF_TRIGGER_LOW;
- else
- irq_trigger = IRQF_TRIGGER_FALLING;
+
+ /* irq_sense setting on cmdline takes precedence over resource
+ * settings, so the introduction of irqflags in IRQ resourse
+ * won't disturb existing setups */
+ switch (irq_sense) {
+ case INTL:
+ irq_trigger = IRQF_TRIGGER_LOW;
+ break;
+ case 0:
+ irq_trigger = IRQF_TRIGGER_FALLING;
+ break;
+ case 0xff:
+ if (irq_trigger)
+ irq_sense = (irq_trigger & IRQF_TRIGGER_LOW) ?
+ INTL : 0;
+ else {
+ irq_sense = INTL;
+ irq_trigger = IRQF_TRIGGER_LOW;
+ }
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown irq_sense value.\n");
+ }
+
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger);
if (ret != 0) {
- err("Failed to add hcd");
+ dev_err(&pdev->dev, "Failed to add hcd\n");
goto clean_up;
}
@@ -2364,7 +2392,8 @@ static int __init r8a66597_init(void)
if (usb_disabled())
return -ENODEV;
- info("driver %s, %s", hcd_name, DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": driver %s, %s\n", hcd_name,
+ DRIVER_VERSION);
return platform_driver_register(&r8a66597_driver);
}
module_init(r8a66597_init);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 8a74bbb57d0..e106e9d48d4 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1620,22 +1620,26 @@ sl811h_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct sl811 *sl811;
- struct resource *addr, *data;
+ struct resource *addr, *data, *ires;
int irq;
void __iomem *addr_reg;
void __iomem *data_reg;
int retval;
u8 tmp, ioaddr = 0;
+ unsigned long irqflags;
/* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board
* specific platform_data. we don't probe for IRQs, and do only
* minimal sanity checking.
*/
- irq = platform_get_irq(dev, 0);
- if (dev->num_resources < 3 || irq < 0)
+ ires = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+ if (dev->num_resources < 3 || !ires)
return -ENODEV;
+ irq = ires->start;
+ irqflags = ires->flags & IRQF_TRIGGER_MASK;
+
/* refuse to confuse usbcore */
if (dev->dev.dma_mask) {
DBG("no we won't dma\n");
@@ -1717,8 +1721,11 @@ sl811h_probe(struct platform_device *dev)
* triggers (e.g. most ARM CPUs). Initial driver stress testing
* was on a system with single edge triggering, so most sorts of
* triggering arrangement should work.
+ *
+ * Use resource IRQ flags if set by platform device setup.
*/
- retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+ irqflags |= IRQF_SHARED;
+ retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | irqflags);
if (retval != 0)
goto err6;
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 5da63f53500..516848dd9b4 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -112,7 +112,8 @@ static struct platform_device platform_dev = {
.num_resources = ARRAY_SIZE(resources),
};
-static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
+static int sl811_hc_init(struct device *parent, resource_size_t base_addr,
+ int irq)
{
if (platform_dev.dev.parent)
return -EBUSY;
@@ -155,97 +156,72 @@ static void sl811_cs_release(struct pcmcia_device * link)
platform_device_unregister(&platform_dev);
}
+static int sl811_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+{
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+ return -ENODEV;
+ }
+
+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+ /* we need an interrupt */
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+
+ return pcmcia_request_io(p_dev, &p_dev->io);
+ }
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+}
+
+
static int sl811_cs_config(struct pcmcia_device *link)
{
struct device *parent = &handle_to_dev(link);
local_info_t *dev = link->priv;
- tuple_t tuple;
- cisparse_t parse;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- cistpl_cftable_entry_t dflt = { 0 };
DBG(0, "sl811_cs_config(0x%p)\n", link);
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0
- || pcmcia_parse_tuple(link, &tuple, &parse)
- != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
- dflt = *cfg;
- }
-
- if (cfg->index == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = cfg->index;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
- != conf.Vcc)
- goto next_entry;
- } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
- != conf.Vcc)
- goto next_entry;
- }
-
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- /* we need an interrupt */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
-
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- }
- break;
-
-next_entry:
- pcmcia_disable_device(link);
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
+ if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
+ goto failed;
/* require an IRQ and two registers */
if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
- goto cs_failed;
+ goto failed;
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ,
pcmcia_request_irq(link, &link->irq));
else
- goto cs_failed;
+ goto failed;
CS_CHECK(RequestConfiguration,
pcmcia_request_configuration(link, &link->conf));
@@ -266,8 +242,9 @@ next_entry:
if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
< 0) {
cs_failed:
- printk("sl811_cs_config failed\n");
cs_error(link, last_fn, last_ret);
+failed:
+ printk(KERN_WARNING "sl811_cs_config failed\n");
sl811_cs_release(link);
return -ENODEV;
}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 3a7bfe7a887..cf5e4cf7ea4 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -53,7 +53,6 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v3.0"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
@@ -951,12 +950,13 @@ static int __init uhci_hcd_init(void)
{
int retval = -ENOMEM;
- printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
- ignore_oc ? ", overcurrent ignored" : "");
-
if (usb_disabled())
return -ENODEV;
+ printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n",
+ ignore_oc ? ", overcurrent ignored" : "");
+ set_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
+
if (DEBUG_CONFIGURED) {
errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
if (!errbuf)
@@ -988,6 +988,7 @@ debug_failed:
errbuf_failed:
+ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
return retval;
}
@@ -997,6 +998,7 @@ static void __exit uhci_hcd_cleanup(void)
kmem_cache_destroy(uhci_up_cachep);
debugfs_remove(uhci_debugfs_root);
kfree(errbuf);
+ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
}
module_init(uhci_hcd_init);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index db645936eed..5631d89c873 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -123,14 +123,10 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
{
- if (!list_empty(&td->list)) {
- dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
- WARN_ON(1);
- }
- if (!list_empty(&td->fl_list)) {
- dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
- WARN_ON(1);
- }
+ if (!list_empty(&td->list))
+ dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td);
+ if (!list_empty(&td->fl_list))
+ dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td);
dma_pool_free(uhci->td_pool, td, td->dma_handle);
}
@@ -295,10 +291,8 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
{
WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
- if (!list_empty(&qh->queue)) {
- dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
- WARN_ON(1);
- }
+ if (!list_empty(&qh->queue))
+ dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh);
list_del(&qh->node);
if (qh->udev) {
@@ -746,11 +740,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
{
struct uhci_td *td, *tmp;
- if (!list_empty(&urbp->node)) {
- dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+ if (!list_empty(&urbp->node))
+ dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n",
urbp->urb);
- WARN_ON(1);
- }
list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
uhci_remove_td_from_urbp(td);
@@ -1073,13 +1065,18 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
}
if (exponent < 0)
return -EINVAL;
- qh->period = 1 << exponent;
- qh->skel = SKEL_INDEX(exponent);
- /* For now, interrupt phase is fixed by the layout
- * of the QH lists. */
- qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
- ret = uhci_check_bandwidth(uhci, qh);
+ /* If the slot is full, try a lower period */
+ do {
+ qh->period = 1 << exponent;
+ qh->skel = SKEL_INDEX(exponent);
+
+ /* For now, interrupt phase is fixed by the layout
+ * of the QH lists.
+ */
+ qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
+ ret = uhci_check_bandwidth(uhci, qh);
+ } while (ret != 0 && --exponent >= 0);
if (ret)
return ret;
} else if (qh->period > urb->interval)
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 0fb114ca1eb..878c77ca086 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -355,13 +355,14 @@ static int mdc800_usb_waitForIRQ (int mode, int msec)
if (mdc800->camera_request_ready>0)
{
mdc800->camera_request_ready=0;
- err ("timeout waiting for camera.");
+ dev_err(&mdc800->dev->dev, "timeout waiting for camera.\n");
return -1;
}
if (mdc800->state == NOT_CONNECTED)
{
- warn ("Camera gets disconnected during waiting for irq.");
+ printk(KERN_WARNING "mdc800: Camera gets disconnected "
+ "during waiting for irq.\n");
mdc800->camera_request_ready=0;
return -2;
}
@@ -379,7 +380,8 @@ static void mdc800_usb_write_notify (struct urb *urb)
int status = urb->status;
if (status != 0)
- err ("writing command fails (status=%i)", status);
+ dev_err(&mdc800->dev->dev,
+ "writing command fails (status=%i)\n", status);
else
mdc800->state=READY;
mdc800->written = 1;
@@ -406,7 +408,8 @@ static void mdc800_usb_download_notify (struct urb *urb)
mdc800->state=READY;
}
} else {
- err ("request bytes fails (status:%i)", status);
+ dev_err(&mdc800->dev->dev,
+ "request bytes fails (status:%i)\n", status);
}
mdc800->downloaded = 1;
wake_up (&mdc800->download_wait);
@@ -443,13 +446,14 @@ static int mdc800_usb_probe (struct usb_interface *intf,
if (mdc800->dev != NULL)
{
- warn ("only one Mustek MDC800 is supported.");
+ dev_warn(&intf->dev, "only one Mustek MDC800 is supported.\n");
return -ENODEV;
}
if (dev->descriptor.bNumConfigurations != 1)
{
- err ("probe fails -> wrong Number of Configuration");
+ dev_err(&intf->dev,
+ "probe fails -> wrong Number of Configuration\n");
return -ENODEV;
}
intf_desc = intf->cur_altsetting;
@@ -461,7 +465,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
|| ( intf_desc->desc.bNumEndpoints != 4)
)
{
- err ("probe fails -> wrong Interface");
+ dev_err(&intf->dev, "probe fails -> wrong Interface\n");
return -ENODEV;
}
@@ -482,19 +486,19 @@ static int mdc800_usb_probe (struct usb_interface *intf,
}
if (mdc800->endpoint[i] == -1)
{
- err ("probe fails -> Wrong Endpoints.");
+ dev_err(&intf->dev, "probe fails -> Wrong Endpoints.\n");
return -ENODEV;
}
}
- info ("Found Mustek MDC800 on USB.");
+ dev_info(&intf->dev, "Found Mustek MDC800 on USB.\n");
mutex_lock(&mdc800->io_lock);
retval = usb_register_dev(intf, &mdc800_class);
if (retval) {
- err ("Not able to get a minor for this device.");
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
return -ENODEV;
}
@@ -570,7 +574,7 @@ static void mdc800_usb_disconnect (struct usb_interface *intf)
mdc800->dev = NULL;
usb_set_intfdata(intf, NULL);
}
- info ("Mustek MDC800 disconnected from USB.");
+ dev_info(&intf->dev, "Mustek MDC800 disconnected from USB.\n");
}
@@ -644,7 +648,8 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
mdc800->irq_urb->dev = mdc800->dev;
retval = usb_submit_urb (mdc800->irq_urb, GFP_KERNEL);
if (retval) {
- err ("request USB irq fails (submit_retval=%i).", retval);
+ dev_err(&mdc800->dev->dev,
+ "request USB irq fails (submit_retval=%i).\n", retval);
errn = -EIO;
goto error_out;
}
@@ -701,7 +706,8 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
}
if (mdc800->state == WORKING)
{
- warn ("Illegal State \"working\" reached during read ?!");
+ printk(KERN_WARNING "mdc800: Illegal State \"working\""
+ "reached during read ?!\n");
mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
@@ -733,7 +739,9 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
mdc800->download_urb->dev = mdc800->dev;
retval = usb_submit_urb (mdc800->download_urb, GFP_KERNEL);
if (retval) {
- err ("Can't submit download urb (retval=%i)",retval);
+ dev_err(&mdc800->dev->dev,
+ "Can't submit download urb "
+ "(retval=%i)\n", retval);
mutex_unlock(&mdc800->io_lock);
return len-left;
}
@@ -742,7 +750,10 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
mdc800->downloaded = 0;
if (mdc800->download_urb->status != 0)
{
- err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
+ dev_err(&mdc800->dev->dev,
+ "request download-bytes fails "
+ "(status=%i)\n",
+ mdc800->download_urb->status);
mutex_unlock(&mdc800->io_lock);
return len-left;
}
@@ -839,7 +850,8 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
- err ("Camera didn't get ready.\n");
+ dev_err(&mdc800->dev->dev,
+ "Camera didn't get ready.\n");
mutex_unlock(&mdc800->io_lock);
return -EIO;
}
@@ -851,7 +863,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
mdc800->write_urb->dev = mdc800->dev;
retval = usb_submit_urb (mdc800->write_urb, GFP_KERNEL);
if (retval) {
- err ("submitting write urb fails (retval=%i)", retval);
+ dev_err(&mdc800->dev->dev,
+ "submitting write urb fails "
+ "(retval=%i)\n", retval);
mutex_unlock(&mdc800->io_lock);
return -EIO;
}
@@ -870,7 +884,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
case 0x3e: /* Take shot in Fine Mode (WCam Mode) */
if (mdc800->pic_len < 0)
{
- err ("call 0x07 before 0x05,0x3e");
+ dev_err(&mdc800->dev->dev,
+ "call 0x07 before "
+ "0x05,0x3e\n");
mdc800->state=READY;
mutex_unlock(&mdc800->io_lock);
return -EIO;
@@ -890,7 +906,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
{
- err ("requesting answer from irq fails");
+ dev_err(&mdc800->dev->dev, "requesting answer from irq fails\n");
mutex_unlock(&mdc800->io_lock);
return -EIO;
}
@@ -918,7 +934,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
{
if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
{
- err ("Command Timeout.");
+ dev_err(&mdc800->dev->dev, "Command Timeout.\n");
mutex_unlock(&mdc800->io_lock);
return -EIO;
}
@@ -1018,7 +1034,8 @@ static int __init usb_mdc800_init (void)
if (retval)
goto cleanup_on_fail;
- info (DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
@@ -1028,7 +1045,7 @@ cleanup_on_fail:
if (mdc800 != NULL)
{
- err ("can't alloc memory!");
+ printk(KERN_ERR "mdc800: can't alloc memory!\n");
kfree(mdc800->download_urb_buffer);
kfree(mdc800->write_urb_buffer);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 4ea50e0abcb..e463db5d818 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -42,6 +42,15 @@ config USB_ADUTUX
To compile this driver as a module, choose M here. The module
will be called adutux.
+config USB_SEVSEG
+ tristate "USB 7-Segment LED Display"
+ depends on USB
+ help
+ Say Y here if you have a USB 7-Segment Display by Delcom
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbsevseg.
+
config USB_RIO500
tristate "USB Diamond Rio500 support"
depends on USB
@@ -271,3 +280,18 @@ config USB_ISIGHTFW
The firmware for this driver must be extracted from the MacOS
driver beforehand. Tools for doing so are available at
http://bersace03.free.fr
+
+config USB_VST
+ tristate "USB VST driver"
+ depends on USB
+ help
+ This driver is intended for Vernier Software Technologies
+ bulk usb devices such as their Ocean-Optics spectrometers or
+ Labquest.
+ It is a bulk channel driver with configurable read and write
+ timeouts.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vstusb.
+
+
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 45b4e12afb0..1334f7bdd7b 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o
obj-$(CONFIG_USB_USS720) += uss720.o
+obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o
+obj-$(CONFIG_USB_VST) += vstusb.o
obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 965f6eaea6a..7b6922e08ed 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -283,8 +283,8 @@ static int adu_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&adu_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d",
- __func__, subminor);
+ printk(KERN_ERR "adutux: %s - error, can't find device for "
+ "minor %d\n", __func__, subminor);
retval = -ENODEV;
goto exit_no_device;
}
@@ -416,7 +416,8 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d", retval);
+ printk(KERN_ERR "adutux: No device or device unplugged %d\n",
+ retval);
goto exit;
}
@@ -576,7 +577,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d", retval);
+ printk(KERN_ERR "adutux: No device or device unplugged %d\n",
+ retval);
goto exit;
}
@@ -645,7 +647,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval < 0) {
dev->out_urb_finished = 1;
- err("Couldn't submit interrupt_out_urb %d", retval);
+ dev_err(&dev->udev->dev, "Couldn't submit "
+ "interrupt_out_urb %d\n", retval);
goto exit;
}
@@ -890,13 +893,14 @@ static int __init adu_init(void)
/* register this driver with the USB subsystem */
result = usb_register(&adu_driver);
if (result < 0) {
- err("usb_register failed for the "__FILE__" driver. "
- "Error number %d", result);
+ printk(KERN_ERR "usb_register failed for the "__FILE__
+ " driver. Error number %d\n", result);
goto exit;
}
- info("adutux " DRIVER_DESC " " DRIVER_VERSION);
- info("adutux is an experimental driver. Use at your own risk");
+ printk(KERN_INFO "adutux " DRIVER_DESC " " DRIVER_VERSION "\n");
+ printk(KERN_INFO "adutux is an experimental driver. "
+ "Use at your own risk\n");
exit:
dbg(2," %s : leave, return value %d", __func__, result);
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index a076c24a312..1d8e39a557d 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -130,7 +130,8 @@ static void appledisplay_complete(struct urb *urb)
exit:
retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
if (retval) {
- err("%s - usb_submit_urb failed with result %d",
+ dev_err(&pdata->udev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
__func__, retval);
}
}
@@ -220,7 +221,7 @@ static int appledisplay_probe(struct usb_interface *iface,
}
}
if (!int_in_endpointAddr) {
- err("Could not find int-in endpoint");
+ dev_err(&iface->dev, "Could not find int-in endpoint\n");
return -EIO;
}
@@ -228,7 +229,7 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL);
if (!pdata) {
retval = -ENOMEM;
- err("Out of memory");
+ dev_err(&iface->dev, "Out of memory\n");
goto error;
}
@@ -241,8 +242,8 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
if (!pdata->msgdata) {
retval = -ENOMEM;
- err("appledisplay: Allocating buffer for control messages "
- "failed");
+ dev_err(&iface->dev,
+ "Allocating buffer for control messages failed\n");
goto error;
}
@@ -250,7 +251,7 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pdata->urb) {
retval = -ENOMEM;
- err("appledisplay: Allocating URB failed");
+ dev_err(&iface->dev, "Allocating URB failed\n");
goto error;
}
@@ -259,7 +260,7 @@ static int appledisplay_probe(struct usb_interface *iface,
GFP_KERNEL, &pdata->urb->transfer_dma);
if (!pdata->urbdata) {
retval = -ENOMEM;
- err("appledisplay: Allocating URB buffer failed");
+ dev_err(&iface->dev, "Allocating URB buffer failed\n");
goto error;
}
@@ -270,7 +271,7 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata, 1);
if (usb_submit_urb(pdata->urb, GFP_KERNEL)) {
retval = -EIO;
- err("appledisplay: Submitting URB failed");
+ dev_err(&iface->dev, "Submitting URB failed\n");
goto error;
}
@@ -280,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata->bd = backlight_device_register(bl_name, NULL, pdata,
&appledisplay_bl_data);
if (IS_ERR(pdata->bd)) {
- err("appledisplay: Backlight registration failed");
+ dev_err(&iface->dev, "Backlight registration failed\n");
goto error;
}
@@ -291,7 +292,8 @@ static int appledisplay_probe(struct usb_interface *iface,
if (brightness < 0) {
retval = brightness;
- err("appledisplay: Error while getting initial brightness: %d", retval);
+ dev_err(&iface->dev,
+ "Error while getting initial brightness: %d\n", retval);
goto error;
}
@@ -314,7 +316,7 @@ error:
pdata->urbdata, pdata->urb->transfer_dma);
usb_free_urb(pdata->urb);
}
- if (pdata->bd)
+ if (pdata->bd && !IS_ERR(pdata->bd))
backlight_device_unregister(pdata->bd);
kfree(pdata->msgdata);
}
@@ -352,7 +354,7 @@ static int __init appledisplay_init(void)
{
wq = create_singlethread_workqueue("appledisplay");
if (!wq) {
- err("Could not create work queue\n");
+ printk(KERN_ERR "appledisplay: Could not create work queue\n");
return -ENOMEM;
}
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index 937940404b7..5720bfef6a3 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -278,9 +278,9 @@ static int __init cypress_init(void)
/* register this driver with the USB subsystem */
result = usb_register(&cypress_driver);
- if (result) {
- err("Function usb_register failed! Error number: %d\n", result);
- }
+ if (result)
+ printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! "
+ "Error number: %d\n", result);
return result;
}
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 1cd9e7eba93..4fb3c38b924 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -422,13 +422,14 @@ static int __init usb_cytherm_init(void)
int result;
result = usb_register(&cytherm_driver);
- if (result)
- {
- err("usb_register failed. Error number %d", result);
+ if (result) {
+ printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! "
+ "Error number: %d\n", result);
return result;
}
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 4b994a0cd27..e762beb5f3c 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -50,7 +50,7 @@ static int emi26_writememory (struct usb_device *dev, int address,
unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
- err("emi26: kmalloc(%d) failed.", length);
+ dev_err(&dev->dev, "kmalloc(%d) failed.\n", length);
return -ENOMEM;
}
/* Note: usb_control_msg returns negative value on error or length of the
@@ -64,11 +64,11 @@ static int emi26_writememory (struct usb_device *dev, int address,
static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
{
int response;
- info("%s - %d", __func__, reset_bit);
+ dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
/* printk(KERN_DEBUG "%s - %d", __func__, reset_bit); */
response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
- err("emi26: set_reset (%d) failed", reset_bit);
+ dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit);
}
return response;
}
@@ -88,7 +88,8 @@ static int emi26_load_firmware (struct usb_device *dev)
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
if (!buf) {
- err( "%s - error loading firmware: error = %d", __func__, -ENOMEM);
+ dev_err(&dev->dev, "%s - error loading firmware: error = %d\n",
+ __func__, -ENOMEM);
err = -ENOMEM;
goto wraperr;
}
@@ -106,14 +107,16 @@ static int emi26_load_firmware (struct usb_device *dev)
&dev->dev);
if (err) {
nofw:
- err( "%s - request_firmware() failed", __func__);
+ dev_err(&dev->dev, "%s - request_firmware() failed\n",
+ __func__);
goto wraperr;
}
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
if (err < 0) {
- err( "%s - error loading firmware: error = %d", __func__, err);
+ dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
+ __func__, err);
goto wraperr;
}
@@ -254,7 +257,7 @@ static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *i
{
struct usb_device *dev = interface_to_usbdev(intf);
- info("%s start", __func__);
+ dev_info(&intf->dev, "%s start\n", __func__);
emi26_load_firmware(dev);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 5d859ded5bb..602ee05ba9f 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -73,7 +73,7 @@ static int emi62_writememory(struct usb_device *dev, int address,
static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
{
int response;
- info("%s - %d", __func__, reset_bit);
+ dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
@@ -271,7 +271,7 @@ static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_device *dev = interface_to_usbdev(intf);
dev_dbg(&intf->dev, "emi62_probe\n");
- info("%s start", __func__);
+ dev_info(&intf->dev, "%s start\n", __func__);
emi62_load_firmware(dev);
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 97c28097153..79a7668ef26 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -698,7 +698,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
int retval = usb_bulk_msg(ftdi->udev,
usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
ftdi->bulk_in_buffer, ftdi->bulk_in_size,
- &packet_bytes, msecs_to_jiffies(50));
+ &packet_bytes, 50);
if (packet_bytes > 2) {
ftdi->bulk_in_left = packet_bytes - 2;
ftdi->bulk_in_last = 1;
@@ -960,7 +960,7 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
int retval = usb_bulk_msg(ftdi->udev,
usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
ftdi->bulk_in_buffer, ftdi->bulk_in_size,
- &packet_bytes, msecs_to_jiffies(500));
+ &packet_bytes, 500);
char diag[30 *3 + 4];
char *d = diag;
int m = packet_bytes;
@@ -1880,7 +1880,7 @@ static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
int retval = usb_bulk_msg(ftdi->udev,
usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
ftdi->bulk_in_buffer, ftdi->bulk_in_size,
- &packet_bytes, msecs_to_jiffies(100));
+ &packet_bytes, 100);
if (packet_bytes > 2) {
char diag[30 *3 + 4];
char *d = diag;
@@ -2067,7 +2067,7 @@ static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
usb_rcvbulkpipe(ftdi->udev,
ftdi->bulk_in_endpointAddr),
ftdi->bulk_in_buffer, ftdi->bulk_in_size,
- &packet_bytes, msecs_to_jiffies(500));
+ &packet_bytes, 500);
if (packet_bytes > 2) {
char diag[30 *3 + 4];
char *d = diag;
@@ -2176,7 +2176,7 @@ static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
int retval = usb_bulk_msg(ftdi->udev,
usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
ftdi->bulk_in_buffer, ftdi->bulk_in_size,
- &packet_bytes, msecs_to_jiffies(1000));
+ &packet_bytes, 1000);
if (packet_bytes > 2) {
char diag[30 *3 + 4];
char *d = diag;
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 4bcf7fb4e5d..6da8887538c 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -403,14 +403,15 @@ static void idmouse_disconnect(struct usb_interface *interface)
mutex_unlock(&dev->lock);
}
- info("%s disconnected", DRIVER_DESC);
+ dev_info(&interface->dev, "disconnected\n");
}
static int __init usb_idmouse_init(void)
{
int result;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
/* register this driver with the USB subsystem */
result = usb_register(&idmouse_driver);
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 9370326a594..ab0f3226158 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -851,9 +851,8 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
dbg(2, "%s: enter", __func__);
- if (udev == NULL) {
- info ("udev is NULL.");
- }
+ if (udev == NULL)
+ dev_info(&interface->dev, "udev is NULL.\n");
/* allocate memory for our device state and initialize it */
@@ -954,7 +953,9 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
dev->minor = interface->minor;
/* let the user know what node this device is now attached to */
- info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor);
+ dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major "
+ "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE),
+ USB_MAJOR, dev->minor);
/* get the firmware version and log it */
result = usb_control_msg (udev,
@@ -971,10 +972,10 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
retval = result;
goto error;
}
- info("LEGO USB Tower firmware version is %d.%d build %d",
- get_version_reply.major,
- get_version_reply.minor,
- le16_to_cpu(get_version_reply.build_no));
+ dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d "
+ "build %d\n", get_version_reply.major,
+ get_version_reply.minor,
+ le16_to_cpu(get_version_reply.build_no));
exit:
@@ -1021,7 +1022,8 @@ static void tower_disconnect (struct usb_interface *interface)
mutex_unlock(&dev->lock);
}
- info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+ dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n",
+ (minor - LEGO_USB_TOWER_MINOR_BASE));
dbg(2, "%s: leave", __func__);
}
@@ -1046,7 +1048,8 @@ static int __init lego_usb_tower_init(void)
goto exit;
}
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
exit:
dbg(2, "%s: leave, return value %d", __func__, retval);
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 4cfa25b0f44..cc8e0a926f9 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -595,9 +595,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
} while(value);
kit->dev_no = bit;
- kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev,
- MKDEV(0, 0), kit,
- "interfacekit%d", kit->dev_no);
+ kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0),
+ kit, "interfacekit%d", kit->dev_no);
if (IS_ERR(kit->dev)) {
rc = PTR_ERR(kit->dev);
kit->dev = NULL;
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 9b4696f21b2..38088b44349 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -365,9 +365,8 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
} while(value);
mc->dev_no = bit;
- mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev,
- MKDEV(0, 0), mc,
- "motorcontrol%d", mc->dev_no);
+ mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc,
+ "motorcontrol%d", mc->dev_no);
if (IS_ERR(mc->dev)) {
rc = PTR_ERR(mc->dev);
mc->dev = NULL;
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 1ca7ddb41d4..bef6fe16364 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -275,9 +275,8 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
} while (value);
dev->dev_no = bit;
- dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev,
- MKDEV(0, 0), dev,
- "servo%d", dev->dev_no);
+ dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0),
+ dev, "servo%d", dev->dev_no);
if (IS_ERR(dev->dev)) {
rc = PTR_ERR(dev->dev);
dev->dev = NULL;
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 248a12aacef..deb95bb49fd 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -89,7 +89,7 @@ static int open_rio(struct inode *inode, struct file *file)
mutex_unlock(&(rio->lock));
- info("Rio opened.");
+ dev_info(&rio->rio_dev->dev, "Rio opened.\n");
return 0;
}
@@ -100,7 +100,7 @@ static int close_rio(struct inode *inode, struct file *file)
rio->isopen = 0;
- info("Rio closed.");
+ dev_info(&rio->rio_dev->dev, "Rio closed.\n");
return 0;
}
@@ -451,7 +451,7 @@ static int probe_rio(struct usb_interface *intf,
struct rio_usb_data *rio = &rio_instance;
int retval;
- info("USB Rio found at address %d", dev->devnum);
+ dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
retval = usb_register_dev(intf, &usb_rio_class);
if (retval) {
@@ -503,7 +503,7 @@ static void disconnect_rio(struct usb_interface *intf)
kfree(rio->ibuf);
kfree(rio->obuf);
- info("USB Rio disconnected.");
+ dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0;
mutex_unlock(&(rio->lock));
@@ -531,7 +531,8 @@ static int __init usb_rio_init(void)
if (retval)
goto out;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
out:
return retval;
diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
index 03368edf3f2..2e14102955c 100644
--- a/drivers/usb/misc/trancevibrator.c
+++ b/drivers/usb/misc/trancevibrator.c
@@ -144,7 +144,8 @@ static int __init tv_init(void)
return retval;
}
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 2db4228fbb0..e0ff9ccd866 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -311,7 +311,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
dev->interface = interface;
if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
- warn(KERN_INFO "USBLCD model not supported.");
+ dev_warn(&interface->dev, "USBLCD model not supported.\n");
return -ENODEV;
}
@@ -359,12 +359,13 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
i = le16_to_cpu(dev->udev->descriptor.bcdDevice);
- info("USBLCD Version %1d%1d.%1d%1d found at address %d",
- (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
- dev->udev->devnum);
+ dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found "
+ "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8,
+ (i & 0xF0)>>4,(i & 0xF), dev->udev->devnum);
/* let the user know what node this device is now attached to */
- info("USB LCD device now attached to USBLCD-%d", interface->minor);
+ dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n",
+ interface->minor);
return 0;
error:
@@ -413,7 +414,7 @@ static void lcd_disconnect(struct usb_interface *interface)
/* decrement our usage count */
kref_put(&dev->kref, lcd_delete);
- info("USB LCD #%d now disconnected", minor);
+ dev_info(&interface->dev, "USB LCD #%d now disconnected\n", minor);
}
static struct usb_driver lcd_driver = {
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
new file mode 100644
index 00000000000..28a6a3a0953
--- /dev/null
+++ b/drivers/usb/misc/usbsevseg.c
@@ -0,0 +1,394 @@
+/*
+ * USB 7 Segment Driver
+ *
+ * Copyright (C) 2008 Harrison Metzger <harrisonmetz@gmail.com>
+ * Based on usbled.c by Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/usb.h>
+
+
+#define DRIVER_AUTHOR "Harrison Metzger <harrisonmetz@gmail.com>"
+#define DRIVER_DESC "USB 7 Segment Driver"
+
+#define VENDOR_ID 0x0fc5
+#define PRODUCT_ID 0x1227
+#define MAXLEN 6
+
+/* table of devices that work with this driver */
+static struct usb_device_id id_table[] = {
+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* the different text display modes the device is capable of */
+static char *display_textmodes[] = {"raw", "hex", "ascii", NULL};
+
+struct usb_sevsegdev {
+ struct usb_device *udev;
+
+ u8 powered;
+ u8 mode_msb;
+ u8 mode_lsb;
+ u8 decimals[MAXLEN];
+ u8 textmode;
+ u8 text[MAXLEN];
+ u16 textlength;
+};
+
+/* sysfs_streq can't replace this completely
+ * If the device was in hex mode, and the user wanted a 0,
+ * if str commands are used, we would assume the end of string
+ * so mem commands are used.
+ */
+inline size_t my_memlen(const char *buf, size_t count)
+{
+ if (count > 0 && buf[count-1] == '\n')
+ return count - 1;
+ else
+ return count;
+}
+
+static void update_display_powered(struct usb_sevsegdev *mydev)
+{
+ int rc;
+
+ rc = usb_control_msg(mydev->udev,
+ usb_sndctrlpipe(mydev->udev, 0),
+ 0x12,
+ 0x48,
+ (80 * 0x100) + 10, /* (power mode) */
+ (0x00 * 0x100) + (mydev->powered ? 1 : 0),
+ NULL,
+ 0,
+ 2000);
+ if (rc < 0)
+ dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc);
+}
+
+static void update_display_mode(struct usb_sevsegdev *mydev)
+{
+ int rc;
+
+ rc = usb_control_msg(mydev->udev,
+ usb_sndctrlpipe(mydev->udev, 0),
+ 0x12,
+ 0x48,
+ (82 * 0x100) + 10, /* (set mode) */
+ (mydev->mode_msb * 0x100) + mydev->mode_lsb,
+ NULL,
+ 0,
+ 2000);
+
+ if (rc < 0)
+ dev_dbg(&mydev->udev->dev, "mode retval = %d\n", rc);
+}
+
+static void update_display_visual(struct usb_sevsegdev *mydev)
+{
+ int rc;
+ int i;
+ unsigned char *buffer;
+ u8 decimals = 0;
+
+ buffer = kzalloc(MAXLEN, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(&mydev->udev->dev, "out of memory\n");
+ return;
+ }
+
+ /* The device is right to left, where as you write left to right */
+ for (i = 0; i < mydev->textlength; i++)
+ buffer[i] = mydev->text[mydev->textlength-1-i];
+
+ rc = usb_control_msg(mydev->udev,
+ usb_sndctrlpipe(mydev->udev, 0),
+ 0x12,
+ 0x48,
+ (85 * 0x100) + 10, /* (write text) */
+ (0 * 0x100) + mydev->textmode, /* mode */
+ buffer,
+ mydev->textlength,
+ 2000);
+
+ if (rc < 0)
+ dev_dbg(&mydev->udev->dev, "write retval = %d\n", rc);
+
+ kfree(buffer);
+
+ /* The device is right to left, where as you write left to right */
+ for (i = 0; i < sizeof(mydev->decimals); i++)
+ decimals |= mydev->decimals[i] << i;
+
+ rc = usb_control_msg(mydev->udev,
+ usb_sndctrlpipe(mydev->udev, 0),
+ 0x12,
+ 0x48,
+ (86 * 0x100) + 10, /* (set decimal) */
+ (0 * 0x100) + decimals, /* decimals */
+ NULL,
+ 0,
+ 2000);
+
+ if (rc < 0)
+ dev_dbg(&mydev->udev->dev, "decimal retval = %d\n", rc);
+}
+
+#define MYDEV_ATTR_SIMPLE_UNSIGNED(name, update_fcn) \
+static ssize_t show_attr_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%u\n", mydev->name); \
+} \
+ \
+static ssize_t set_attr_##name(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \
+ \
+ mydev->name = simple_strtoul(buf, NULL, 10); \
+ update_fcn(mydev); \
+ \
+ return count; \
+} \
+static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name);
+
+static ssize_t show_attr_text(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+
+ return snprintf(buf, mydev->textlength, "%s\n", mydev->text);
+}
+
+static ssize_t set_attr_text(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+ size_t end = my_memlen(buf, count);
+
+ if (end > sizeof(mydev->text))
+ return -EINVAL;
+
+ memset(mydev->text, 0, sizeof(mydev->text));
+ mydev->textlength = end;
+
+ if (end > 0)
+ memcpy(mydev->text, buf, end);
+
+ update_display_visual(mydev);
+ return count;
+}
+
+static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text);
+
+static ssize_t show_attr_decimals(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+ int i;
+ int pos;
+
+ for (i = 0; i < sizeof(mydev->decimals); i++) {
+ pos = sizeof(mydev->decimals) - 1 - i;
+ if (mydev->decimals[i] == 0)
+ buf[pos] = '0';
+ else if (mydev->decimals[i] == 1)
+ buf[pos] = '1';
+ else
+ buf[pos] = 'x';
+ }
+
+ buf[sizeof(mydev->decimals)] = '\n';
+ return sizeof(mydev->decimals) + 1;
+}
+
+static ssize_t set_attr_decimals(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+ size_t end = my_memlen(buf, count);
+ int i;
+
+ if (end > sizeof(mydev->decimals))
+ return -EINVAL;
+
+ for (i = 0; i < end; i++)
+ if (buf[i] != '0' && buf[i] != '1')
+ return -EINVAL;
+
+ memset(mydev->decimals, 0, sizeof(mydev->decimals));
+ for (i = 0; i < end; i++)
+ if (buf[i] == '1')
+ mydev->decimals[end-1-i] = 1;
+
+ update_display_visual(mydev);
+
+ return count;
+}
+
+static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO,
+ show_attr_decimals, set_attr_decimals);
+
+static ssize_t show_attr_textmode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+ int i;
+
+ buf[0] = 0;
+
+ for (i = 0; display_textmodes[i]; i++) {
+ if (mydev->textmode == i) {
+ strcat(buf, " [");
+ strcat(buf, display_textmodes[i]);
+ strcat(buf, "] ");
+ } else {
+ strcat(buf, " ");
+ strcat(buf, display_textmodes[i]);
+ strcat(buf, " ");
+ }
+ }
+ strcat(buf, "\n");
+
+
+ return strlen(buf);
+}
+
+static ssize_t set_attr_textmode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
+ int i;
+
+ for (i = 0; display_textmodes[i]; i++) {
+ if (sysfs_streq(display_textmodes[i], buf)) {
+ mydev->textmode = i;
+ update_display_visual(mydev);
+ return count;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO,
+ show_attr_textmode, set_attr_textmode);
+
+
+MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered);
+MYDEV_ATTR_SIMPLE_UNSIGNED(mode_msb, update_display_mode);
+MYDEV_ATTR_SIMPLE_UNSIGNED(mode_lsb, update_display_mode);
+
+static struct attribute *dev_attrs[] = {
+ &dev_attr_powered.attr,
+ &dev_attr_text.attr,
+ &dev_attr_textmode.attr,
+ &dev_attr_decimals.attr,
+ &dev_attr_mode_msb.attr,
+ &dev_attr_mode_lsb.attr,
+ NULL
+};
+
+static struct attribute_group dev_attr_grp = {
+ .attrs = dev_attrs,
+};
+
+static int sevseg_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct usb_sevsegdev *mydev = NULL;
+ int rc = -ENOMEM;
+
+ mydev = kzalloc(sizeof(struct usb_sevsegdev), GFP_KERNEL);
+ if (mydev == NULL) {
+ dev_err(&interface->dev, "Out of memory\n");
+ goto error_mem;
+ }
+
+ mydev->udev = usb_get_dev(udev);
+ usb_set_intfdata(interface, mydev);
+
+ /*set defaults */
+ mydev->textmode = 0x02; /* ascii mode */
+ mydev->mode_msb = 0x06; /* 6 characters */
+ mydev->mode_lsb = 0x3f; /* scanmode for 6 chars */
+
+ rc = sysfs_create_group(&interface->dev.kobj, &dev_attr_grp);
+ if (rc)
+ goto error;
+
+ dev_info(&interface->dev, "USB 7 Segment device now attached\n");
+ return 0;
+
+error:
+ usb_set_intfdata(interface, NULL);
+ usb_put_dev(mydev->udev);
+ kfree(mydev);
+error_mem:
+ return rc;
+}
+
+static void sevseg_disconnect(struct usb_interface *interface)
+{
+ struct usb_sevsegdev *mydev;
+
+ mydev = usb_get_intfdata(interface);
+ sysfs_remove_group(&interface->dev.kobj, &dev_attr_grp);
+ usb_set_intfdata(interface, NULL);
+ usb_put_dev(mydev->udev);
+ kfree(mydev);
+ dev_info(&interface->dev, "USB 7 Segment now disconnected\n");
+}
+
+static struct usb_driver sevseg_driver = {
+ .name = "usbsevseg",
+ .probe = sevseg_probe,
+ .disconnect = sevseg_disconnect,
+ .id_table = id_table,
+};
+
+static int __init usb_sevseg_init(void)
+{
+ int rc = 0;
+
+ rc = usb_register(&sevseg_driver);
+ if (rc)
+ err("usb_register failed. Error number %d", rc);
+ return rc;
+}
+
+static void __exit usb_sevseg_exit(void)
+{
+ usb_deregister(&sevseg_driver);
+}
+
+module_init(usb_sevseg_init);
+module_exit(usb_sevseg_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index f1255b0a182..9a6c27a0179 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -228,11 +228,12 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
ret = rq->urb->status;
*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
if (ret)
- warn("get_1284_register: usb error %d", ret);
+ printk(KERN_WARNING "get_1284_register: "
+ "usb error %d\n", ret);
kref_put(&rq->ref_count, destroy_async);
return ret;
}
- warn("get_1284_register timeout");
+ printk(KERN_WARNING "get_1284_register timeout\n");
kill_all_async_requests_priv(priv);
return -EIO;
}
@@ -716,7 +717,7 @@ static int uss720_probe(struct usb_interface *intf,
spin_lock_init(&priv->asynclock);
INIT_LIST_HEAD(&priv->asynclist);
if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
- warn("could not register parport");
+ printk(KERN_WARNING "uss720: could not register parport\n");
goto probe_abort;
}
@@ -800,10 +801,14 @@ static int __init uss720_init(void)
if (retval)
goto out;
- info(DRIVER_VERSION ":" DRIVER_DESC);
- info("NOTE: this is a special purpose driver to allow nonstandard");
- info("protocols (eg. bitbang) over USS720 usb to parallel cables");
- info("If you just want to connect to a printer, use usblp instead");
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
+ printk(KERN_INFO KBUILD_MODNAME ": NOTE: this is a special purpose "
+ "driver to allow nonstandard\n");
+ printk(KERN_INFO KBUILD_MODNAME ": protocols (eg. bitbang) over "
+ "USS720 usb to parallel cables\n");
+ printk(KERN_INFO KBUILD_MODNAME ": If you just want to connect to a "
+ "printer, use usblp instead\n");
out:
return retval;
}
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
new file mode 100644
index 00000000000..8648470c81c
--- /dev/null
+++ b/drivers/usb/misc/vstusb.c
@@ -0,0 +1,782 @@
+/*****************************************************************************
+ * File: drivers/usb/misc/vstusb.c
+ *
+ * Purpose: Support for the bulk USB Vernier Spectrophotometers
+ *
+ * Author: Johnnie Peters
+ * Axian Consulting
+ * Beaverton, OR, USA 97005
+ *
+ * Modified by: EQware Engineering, Inc.
+ * Oregon City, OR, USA 97045
+ *
+ * Copyright: 2007, 2008
+ * Vernier Software & Technology
+ * Beaverton, OR, USA 97005
+ *
+ * Web: www.vernier.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+
+#include <linux/usb/vstusb.h>
+
+#define DRIVER_VERSION "VST USB Driver Version 1.5"
+#define DRIVER_DESC "Vernier Software Technology Bulk USB Driver"
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+ #define VSTUSB_MINOR_BASE 0
+#else
+ #define VSTUSB_MINOR_BASE 199
+#endif
+
+#define USB_VENDOR_OCEANOPTICS 0x2457
+#define USB_VENDOR_VERNIER 0x08F7 /* Vernier Software & Technology */
+
+#define USB_PRODUCT_USB2000 0x1002
+#define USB_PRODUCT_ADC1000_FW 0x1003 /* firmware download (renumerates) */
+#define USB_PRODUCT_ADC1000 0x1004
+#define USB_PRODUCT_HR2000_FW 0x1009 /* firmware download (renumerates) */
+#define USB_PRODUCT_HR2000 0x100A
+#define USB_PRODUCT_HR4000_FW 0x1011 /* firmware download (renumerates) */
+#define USB_PRODUCT_HR4000 0x1012
+#define USB_PRODUCT_USB650 0x1014 /* "Red Tide" */
+#define USB_PRODUCT_QE65000 0x1018
+#define USB_PRODUCT_USB4000 0x1022
+#define USB_PRODUCT_USB325 0x1024 /* "Vernier Spectrometer" */
+
+#define USB_PRODUCT_LABPRO 0x0001
+#define USB_PRODUCT_LABQUEST 0x0005
+
+#define VST_MAXBUFFER (64*1024)
+
+static struct usb_device_id id_table[] = {
+ { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)},
+ { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)},
+ { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB650)},
+ { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB4000)},
+ { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB325)},
+ { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABQUEST)},
+ { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABPRO)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct vstusb_device {
+ struct kref kref;
+ struct mutex lock;
+ struct usb_device *usb_dev;
+ char present;
+ char isopen;
+ struct usb_anchor submitted;
+ int rd_pipe;
+ int rd_timeout_ms;
+ int wr_pipe;
+ int wr_timeout_ms;
+};
+#define to_vst_dev(d) container_of(d, struct vstusb_device, kref)
+
+static struct usb_driver vstusb_driver;
+
+static void vstusb_delete(struct kref *kref)
+{
+ struct vstusb_device *vstdev = to_vst_dev(kref);
+
+ usb_put_dev(vstdev->usb_dev);
+ kfree(vstdev);
+}
+
+static int vstusb_open(struct inode *inode, struct file *file)
+{
+ struct vstusb_device *vstdev;
+ struct usb_interface *interface;
+
+ interface = usb_find_interface(&vstusb_driver, iminor(inode));
+
+ if (!interface) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s - error, can't find device for minor %d\n",
+ __func__, iminor(inode));
+ return -ENODEV;
+ }
+
+ vstdev = usb_get_intfdata(interface);
+
+ if (!vstdev)
+ return -ENODEV;
+
+ /* lock this device */
+ mutex_lock(&vstdev->lock);
+
+ /* can only open one time */
+ if ((!vstdev->present) || (vstdev->isopen)) {
+ mutex_unlock(&vstdev->lock);
+ return -EBUSY;
+ }
+
+ /* increment our usage count */
+ kref_get(&vstdev->kref);
+
+ vstdev->isopen = 1;
+
+ /* save device in the file's private structure */
+ file->private_data = vstdev;
+
+ dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__);
+
+ mutex_unlock(&vstdev->lock);
+
+ return 0;
+}
+
+static int vstusb_release(struct inode *inode, struct file *file)
+{
+ struct vstusb_device *vstdev;
+
+ vstdev = file->private_data;
+
+ if (vstdev == NULL)
+ return -ENODEV;
+
+ mutex_lock(&vstdev->lock);
+
+ vstdev->isopen = 0;
+
+ dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__);
+
+ mutex_unlock(&vstdev->lock);
+
+ kref_put(&vstdev->kref, vstusb_delete);
+
+ return 0;
+}
+
+static void usb_api_blocking_completion(struct urb *urb)
+{
+ struct completion *completeit = urb->context;
+
+ complete(completeit);
+}
+
+static int vstusb_fill_and_send_urb(struct urb *urb,
+ struct usb_device *usb_dev,
+ unsigned int pipe, void *data,
+ unsigned int len, struct completion *done)
+{
+ struct usb_host_endpoint *ep;
+ struct usb_host_endpoint **hostep;
+ unsigned int pipend;
+
+ int status;
+
+ hostep = usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out;
+ pipend = usb_pipeendpoint(pipe);
+ ep = hostep[pipend];
+
+ if (!ep || (len == 0))
+ return -EINVAL;
+
+ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT) {
+ pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+ usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+ (usb_complete_t)usb_api_blocking_completion,
+ NULL, ep->desc.bInterval);
+ } else
+ usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+ (usb_complete_t)usb_api_blocking_completion,
+ NULL);
+
+ init_completion(done);
+ urb->context = done;
+ urb->actual_length = 0;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+
+ return status;
+}
+
+static int vstusb_complete_urb(struct urb *urb, struct completion *done,
+ int timeout, int *actual_length)
+{
+ unsigned long expire;
+ int status;
+
+ expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+ if (!wait_for_completion_interruptible_timeout(done, expire)) {
+ usb_kill_urb(urb);
+ status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+
+ dev_dbg(&urb->dev->dev,
+ "%s timed out on ep%d%s len=%d/%d, urb status = %d\n",
+ current->comm,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->actual_length,
+ urb->transfer_buffer_length,
+ urb->status);
+
+ } else {
+ if (signal_pending(current)) {
+ /* if really an error */
+ if (urb->status && !((urb->status == -ENOENT) ||
+ (urb->status == -ECONNRESET) ||
+ (urb->status == -ESHUTDOWN))) {
+ status = -EINTR;
+ usb_kill_urb(urb);
+ } else {
+ status = 0;
+ }
+
+ dev_dbg(&urb->dev->dev,
+ "%s: signal pending on ep%d%s len=%d/%d,"
+ "urb status = %d\n",
+ current->comm,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->actual_length,
+ urb->transfer_buffer_length,
+ urb->status);
+
+ } else {
+ status = urb->status;
+ }
+ }
+
+ if (actual_length)
+ *actual_length = urb->actual_length;
+
+ return status;
+}
+
+static ssize_t vstusb_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct vstusb_device *vstdev;
+ int cnt = -1;
+ void *buf;
+ int retval = 0;
+
+ struct urb *urb;
+ struct usb_device *dev;
+ unsigned int pipe;
+ int timeout;
+
+ DECLARE_COMPLETION_ONSTACK(done);
+
+ vstdev = file->private_data;
+
+ if (vstdev == NULL)
+ return -ENODEV;
+
+ /* verify that we actually want to read some data */
+ if ((count == 0) || (count > VST_MAXBUFFER))
+ return -EINVAL;
+
+ /* lock this object */
+ if (mutex_lock_interruptible(&vstdev->lock))
+ return -ERESTARTSYS;
+
+ /* anyone home */
+ if (!vstdev->present) {
+ mutex_unlock(&vstdev->lock);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: device not present\n", __func__);
+ return -ENODEV;
+ }
+
+ /* pull out the necessary data */
+ dev = vstdev->usb_dev;
+ pipe = usb_rcvbulkpipe(dev, vstdev->rd_pipe);
+ timeout = vstdev->rd_timeout_ms;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (buf == NULL) {
+ mutex_unlock(&vstdev->lock);
+ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(buf);
+ mutex_unlock(&vstdev->lock);
+ return -ENOMEM;
+ }
+
+ usb_anchor_urb(urb, &vstdev->submitted);
+ retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
+ mutex_unlock(&vstdev->lock);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
+ if (retval) {
+ dev_err(&dev->dev, "%s: error %d completing urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ if (copy_to_user(buffer, buf, cnt)) {
+ dev_err(&dev->dev, "%s: can't copy_to_user\n", __func__);
+ retval = -EFAULT;
+ } else {
+ retval = cnt;
+ dev_dbg(&dev->dev, "%s: read %d bytes from pipe %d\n",
+ __func__, cnt, pipe);
+ }
+
+exit:
+ usb_free_urb(urb);
+ kfree(buf);
+ return retval;
+}
+
+static ssize_t vstusb_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct vstusb_device *vstdev;
+ int cnt = -1;
+ void *buf;
+ int retval = 0;
+
+ struct urb *urb;
+ struct usb_device *dev;
+ unsigned int pipe;
+ int timeout;
+
+ DECLARE_COMPLETION_ONSTACK(done);
+
+ vstdev = file->private_data;
+
+ if (vstdev == NULL)
+ return -ENODEV;
+
+ /* verify that we actually have some data to write */
+ if ((count == 0) || (count > VST_MAXBUFFER))
+ return retval;
+
+ /* lock this object */
+ if (mutex_lock_interruptible(&vstdev->lock))
+ return -ERESTARTSYS;
+
+ /* anyone home */
+ if (!vstdev->present) {
+ mutex_unlock(&vstdev->lock);
+ printk(KERN_ERR KBUILD_MODNAME
+ ": %s: device not present\n", __func__);
+ return -ENODEV;
+ }
+
+ /* pull out the necessary data */
+ dev = vstdev->usb_dev;
+ pipe = usb_sndbulkpipe(dev, vstdev->wr_pipe);
+ timeout = vstdev->wr_timeout_ms;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (buf == NULL) {
+ mutex_unlock(&vstdev->lock);
+ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(buf);
+ mutex_unlock(&vstdev->lock);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(buf, buffer, count)) {
+ dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__);
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ usb_anchor_urb(urb, &vstdev->submitted);
+ retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
+ mutex_unlock(&vstdev->lock);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
+ if (retval) {
+ dev_err(&dev->dev, "%s: error %d completing urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ } else {
+ retval = cnt;
+ dev_dbg(&dev->dev, "%s: sent %d bytes to pipe %d\n",
+ __func__, cnt, pipe);
+ }
+
+exit:
+ usb_free_urb(urb);
+ kfree(buf);
+ return retval;
+}
+
+static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+ int cnt = -1;
+ void __user *data = (void __user *)arg;
+ struct vstusb_args usb_data;
+
+ struct vstusb_device *vstdev;
+ void *buffer = NULL; /* must be initialized. buffer is
+ * referenced on exit but not all
+ * ioctls allocate it */
+
+ struct urb *urb = NULL; /* must be initialized. urb is
+ * referenced on exit but not all
+ * ioctls allocate it */
+ struct usb_device *dev;
+ unsigned int pipe;
+ int timeout;
+
+ DECLARE_COMPLETION_ONSTACK(done);
+
+ vstdev = file->private_data;
+
+ if (_IOC_TYPE(cmd) != VST_IOC_MAGIC) {
+ dev_warn(&vstdev->usb_dev->dev,
+ "%s: ioctl command %x, bad ioctl magic %x, "
+ "expected %x\n", __func__, cmd,
+ _IOC_TYPE(cmd), VST_IOC_MAGIC);
+ return -EINVAL;
+ }
+
+ if (vstdev == NULL)
+ return -ENODEV;
+
+ if (copy_from_user(&usb_data, data, sizeof(struct vstusb_args))) {
+ dev_err(&vstdev->usb_dev->dev, "%s: can't copy_from_user\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ /* lock this object */
+ if (mutex_lock_interruptible(&vstdev->lock)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* anyone home */
+ if (!vstdev->present) {
+ mutex_unlock(&vstdev->lock);
+ dev_err(&vstdev->usb_dev->dev, "%s: device not present\n",
+ __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* pull out the necessary data */
+ dev = vstdev->usb_dev;
+
+ switch (cmd) {
+
+ case IOCTL_VSTUSB_CONFIG_RW:
+
+ vstdev->rd_pipe = usb_data.rd_pipe;
+ vstdev->rd_timeout_ms = usb_data.rd_timeout_ms;
+ vstdev->wr_pipe = usb_data.wr_pipe;
+ vstdev->wr_timeout_ms = usb_data.wr_timeout_ms;
+
+ mutex_unlock(&vstdev->lock);
+
+ dev_dbg(&dev->dev, "%s: setting pipes/timeouts, "
+ "rdpipe = %d, rdtimeout = %d, "
+ "wrpipe = %d, wrtimeout = %d\n", __func__,
+ vstdev->rd_pipe, vstdev->rd_timeout_ms,
+ vstdev->wr_pipe, vstdev->wr_timeout_ms);
+ break;
+
+ case IOCTL_VSTUSB_SEND_PIPE:
+
+ if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
+ mutex_unlock(&vstdev->lock);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ buffer = kmalloc(usb_data.count, GFP_KERNEL);
+ if (buffer == NULL) {
+ mutex_unlock(&vstdev->lock);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ mutex_unlock(&vstdev->lock);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ timeout = usb_data.timeout_ms;
+
+ pipe = usb_sndbulkpipe(dev, usb_data.pipe);
+
+ if (copy_from_user(buffer, usb_data.buffer, usb_data.count)) {
+ dev_err(&dev->dev, "%s: can't copy_from_user\n",
+ __func__);
+ mutex_unlock(&vstdev->lock);
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ usb_anchor_urb(urb, &vstdev->submitted);
+ retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
+ usb_data.count, &done);
+ mutex_unlock(&vstdev->lock);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ dev_err(&dev->dev,
+ "%s: error %d filling and sending urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
+ if (retval) {
+ dev_err(&dev->dev, "%s: error %d completing urb %d\n",
+ __func__, retval, pipe);
+ }
+
+ break;
+ case IOCTL_VSTUSB_RECV_PIPE:
+
+ if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
+ mutex_unlock(&vstdev->lock);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ buffer = kmalloc(usb_data.count, GFP_KERNEL);
+ if (buffer == NULL) {
+ mutex_unlock(&vstdev->lock);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ mutex_unlock(&vstdev->lock);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ timeout = usb_data.timeout_ms;
+
+ pipe = usb_rcvbulkpipe(dev, usb_data.pipe);
+
+ usb_anchor_urb(urb, &vstdev->submitted);
+ retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
+ usb_data.count, &done);
+ mutex_unlock(&vstdev->lock);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ dev_err(&dev->dev,
+ "%s: error %d filling and sending urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
+ if (retval) {
+ dev_err(&dev->dev, "%s: error %d completing urb %d\n",
+ __func__, retval, pipe);
+ goto exit;
+ }
+
+ if (copy_to_user(usb_data.buffer, buffer, cnt)) {
+ dev_err(&dev->dev, "%s: can't copy_to_user\n",
+ __func__);
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ usb_data.count = cnt;
+ if (copy_to_user(data, &usb_data, sizeof(struct vstusb_args))) {
+ dev_err(&dev->dev, "%s: can't copy_to_user\n",
+ __func__);
+ retval = -EFAULT;
+ } else {
+ dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n",
+ __func__, usb_data.count, usb_data.pipe);
+ }
+
+ break;
+
+ default:
+ mutex_unlock(&vstdev->lock);
+ dev_warn(&dev->dev, "ioctl_vstusb: invalid ioctl cmd %x\n",
+ cmd);
+ return -EINVAL;
+ break;
+ }
+exit:
+ usb_free_urb(urb);
+ kfree(buffer);
+ return retval;
+}
+
+static const struct file_operations vstusb_fops = {
+ .owner = THIS_MODULE,
+ .read = vstusb_read,
+ .write = vstusb_write,
+ .unlocked_ioctl = vstusb_ioctl,
+ .compat_ioctl = vstusb_ioctl,
+ .open = vstusb_open,
+ .release = vstusb_release,
+};
+
+static struct usb_class_driver usb_vstusb_class = {
+ .name = "usb/vstusb%d",
+ .fops = &vstusb_fops,
+ .minor_base = VSTUSB_MINOR_BASE,
+};
+
+static int vstusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct vstusb_device *vstdev;
+ int i;
+ int retval = 0;
+
+ /* allocate memory for our device state and intialize it */
+
+ vstdev = kzalloc(sizeof(*vstdev), GFP_KERNEL);
+ if (vstdev == NULL)
+ return -ENOMEM;
+
+ /* must do usb_get_dev() prior to kref_init() since the kref_put()
+ * release function will do a usb_put_dev() */
+ usb_get_dev(dev);
+ kref_init(&vstdev->kref);
+ mutex_init(&vstdev->lock);
+
+ i = dev->descriptor.bcdDevice;
+
+ dev_dbg(&intf->dev, "Version %1d%1d.%1d%1d found at address %d\n",
+ (i & 0xF000) >> 12, (i & 0xF00) >> 8,
+ (i & 0xF0) >> 4, (i & 0xF), dev->devnum);
+
+ vstdev->present = 1;
+ vstdev->isopen = 0;
+ vstdev->usb_dev = dev;
+ init_usb_anchor(&vstdev->submitted);
+
+ usb_set_intfdata(intf, vstdev);
+ retval = usb_register_dev(intf, &usb_vstusb_class);
+ if (retval) {
+ dev_err(&intf->dev,
+ "%s: Not able to get a minor for this device.\n",
+ __func__);
+ usb_set_intfdata(intf, NULL);
+ kref_put(&vstdev->kref, vstusb_delete);
+ return retval;
+ }
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&intf->dev,
+ "VST USB Device #%d now attached to major %d minor %d\n",
+ (intf->minor - VSTUSB_MINOR_BASE), USB_MAJOR, intf->minor);
+
+ dev_info(&intf->dev, "%s, %s\n", DRIVER_DESC, DRIVER_VERSION);
+
+ return retval;
+}
+
+static void vstusb_disconnect(struct usb_interface *intf)
+{
+ struct vstusb_device *vstdev = usb_get_intfdata(intf);
+
+ usb_deregister_dev(intf, &usb_vstusb_class);
+ usb_set_intfdata(intf, NULL);
+
+ if (vstdev) {
+
+ mutex_lock(&vstdev->lock);
+ vstdev->present = 0;
+
+ usb_kill_anchored_urbs(&vstdev->submitted);
+
+ mutex_unlock(&vstdev->lock);
+
+ kref_put(&vstdev->kref, vstusb_delete);
+ }
+
+}
+
+static int vstusb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct vstusb_device *vstdev = usb_get_intfdata(intf);
+ int time;
+ if (!vstdev)
+ return 0;
+
+ mutex_lock(&vstdev->lock);
+ time = usb_wait_anchor_empty_timeout(&vstdev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&vstdev->submitted);
+ mutex_unlock(&vstdev->lock);
+
+ return 0;
+}
+
+static int vstusb_resume(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static struct usb_driver vstusb_driver = {
+ .name = "vstusb",
+ .probe = vstusb_probe,
+ .disconnect = vstusb_disconnect,
+ .suspend = vstusb_suspend,
+ .resume = vstusb_resume,
+ .id_table = id_table,
+};
+
+static int __init vstusb_init(void)
+{
+ int rc;
+
+ rc = usb_register(&vstusb_driver);
+ if (rc)
+ printk(KERN_ERR "%s: failed to register (%d)", __func__, rc);
+
+ return rc;
+}
+
+static void __exit vstusb_exit(void)
+{
+ usb_deregister(&vstusb_driver);
+}
+
+module_init(vstusb_init);
+module_exit(vstusb_exit);
+
+MODULE_AUTHOR("Dennis O'Brien/Stephen Ware");
+MODULE_DESCRIPTION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 6566fc0a322..c9de3f027aa 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1162,9 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
if (minor >= MON_BIN_MAX_MINOR)
return 0;
- dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
- MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
- "usbmon%d", minor);
+ dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
+ MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+ "usbmon%d", minor);
if (IS_ERR(dev))
return 0;
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 442d8076b20..5e0ab4201c0 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -361,12 +361,12 @@ static int __init mon_init(void)
}
// MOD_INC_USE_COUNT(which_module?);
- usb_register_notify(&mon_nb);
mutex_lock(&usb_bus_list_lock);
list_for_each_entry (ubus, &usb_bus_list, bus_list) {
mon_bus_init(ubus);
}
+ usb_register_notify(&mon_nb);
mutex_unlock(&usb_bus_list_lock);
return 0;
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index a0017486ad4..4b9542bbb35 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -9,6 +9,7 @@ comment "Enable Host or Gadget support to see Inventra options"
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
depends on (USB || USB_GADGET) && HAVE_CLK
+ depends on !SUPERH
select TWL4030_USB if MACH_OMAP_3430SDP
tristate 'Inventra Highspeed Dual Role Controller (TI, ...)'
help
@@ -32,10 +33,6 @@ config USB_MUSB_SOC
default y if ARCH_DAVINCI
default y if ARCH_OMAP2430
default y if ARCH_OMAP34XX
- help
- Use a static <asm/arch/hdrc_cnf.h> file to describe how the
- controller is configured (endpoints, mechanisms, etc) on the
- current iteration of a given system-on-chip.
comment "DaVinci 644x USB support"
depends on USB_MUSB_HDRC && ARCH_DAVINCI
diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h
index fc5216b5d2c..729b4071787 100644
--- a/drivers/usb/musb/cppi_dma.h
+++ b/drivers/usb/musb/cppi_dma.h
@@ -119,8 +119,8 @@ struct cppi {
void __iomem *mregs; /* Mentor regs */
void __iomem *tibase; /* TI/CPPI regs */
- struct cppi_channel tx[MUSB_C_NUM_EPT - 1];
- struct cppi_channel rx[MUSB_C_NUM_EPR - 1];
+ struct cppi_channel tx[4];
+ struct cppi_channel rx[4];
struct dma_pool *pool;
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 75baf181a8c..dfb3bcbe00f 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/memory.h>
@@ -39,7 +40,7 @@
#include "musb_core.h"
#ifdef CONFIG_MACH_DAVINCI_EVM
-#include <asm/arch/i2c-client.h>
+#define GPIO_nVBUS_DRV 87
#endif
#include "davinci.h"
@@ -138,7 +139,6 @@ static int vbus_state = -1;
/* VBUS SWITCHING IS BOARD-SPECIFIC */
#ifdef CONFIG_MACH_DAVINCI_EVM
-#ifndef CONFIG_MACH_DAVINCI_EVM_OTG
/* I2C operations are always synchronous, and require a task context.
* With unloaded systems, using the shared workqueue seems to suffice
@@ -146,12 +146,11 @@ static int vbus_state = -1;
*/
static void evm_deferred_drvvbus(struct work_struct *ignored)
{
- davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state);
+ gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
vbus_state = !vbus_state;
}
static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
-#endif /* modified board */
#endif /* EVM */
static void davinci_source_power(struct musb *musb, int is_on, int immediate)
@@ -165,21 +164,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate)
#ifdef CONFIG_MACH_DAVINCI_EVM
if (machine_is_davinci_evm()) {
-#ifdef CONFIG_MACH_DAVINCI_EVM_OTG
- /* modified EVM board switching VBUS with GPIO(6) not I2C
- * NOTE: PINMUX0.RGB888 (bit23) must be clear
- */
- if (is_on)
- gpio_set(GPIO(6));
- else
- gpio_clear(GPIO(6));
- immediate = 1;
-#else
if (immediate)
- davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on);
+ gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
else
schedule_work(&evm_vbus_work);
-#endif
}
#endif
if (immediate)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index c5b8f0296fc..4a35745b30b 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -82,9 +82,9 @@
/*
* This gets many kinds of configuration information:
* - Kconfig for everything user-configurable
- * - <asm/arch/hdrc_cnf.h> for SOC or family details
* - platform_device for addressing, irq, and platform_data
* - platform_data is mostly for board-specific informarion
+ * (plus recentrly, SOC or family details)
*
* Most of the conditional compilation will (someday) vanish.
*/
@@ -100,8 +100,8 @@
#include <linux/io.h>
#ifdef CONFIG_ARM
-#include <asm/arch/hardware.h>
-#include <asm/arch/memory.h>
+#include <mach/hardware.h>
+#include <mach/memory.h>
#include <asm/mach-types.h>
#endif
@@ -974,9 +974,9 @@ static void musb_shutdown(struct platform_device *pdev)
/*
* The silicon either has hard-wired endpoint configurations, or else
* "dynamic fifo" sizing. The driver has support for both, though at this
- * writing only the dynamic sizing is very well tested. We use normal
- * idioms to so both modes are compile-tested, but dead code elimination
- * leaves only the relevant one in the object file.
+ * writing only the dynamic sizing is very well tested. Since we switched
+ * away from compile-time hardware parameters, we can no longer rely on
+ * dead code elimination to leave only the relevant one in the object file.
*
* We don't currently use dynamic fifo setup capability to do anything
* more than selecting one of a bunch of predefined configurations.
@@ -1806,6 +1806,7 @@ allocate_instance(struct device *dev,
musb->ctrl_base = mbase;
musb->nIrq = -ENODEV;
musb->config = config;
+ BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS);
for (epnum = 0, ep = musb->endpoints;
epnum < musb->config->num_eps;
epnum++, ep++) {
@@ -2054,15 +2055,6 @@ bad_config:
}
- return 0;
-
-fail:
- if (musb->clock)
- clk_put(musb->clock);
- device_init_wakeup(dev, 0);
- musb_free(musb);
- return status;
-
#ifdef CONFIG_SYSFS
status = device_create_file(dev, &dev_attr_mode);
status = device_create_file(dev, &dev_attr_vbus);
@@ -2071,12 +2063,31 @@ fail:
#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
status = 0;
#endif
+ if (status)
+ goto fail2;
- return status;
+ return 0;
fail2:
+#ifdef CONFIG_SYSFS
+ device_remove_file(musb->controller, &dev_attr_mode);
+ device_remove_file(musb->controller, &dev_attr_vbus);
+#ifdef CONFIG_USB_MUSB_OTG
+ device_remove_file(musb->controller, &dev_attr_srp);
+#endif
+#endif
musb_platform_exit(musb);
- goto fail;
+fail:
+ dev_err(musb->controller,
+ "musb_init_controller failed with status %d\n", status);
+
+ if (musb->clock)
+ clk_put(musb->clock);
+ device_init_wakeup(dev, 0);
+ musb_free(musb);
+
+ return status;
+
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index a57652fff39..3f5e30ddfa2 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -437,7 +437,7 @@ static void ep0_rxstate(struct musb *musb)
{
void __iomem *regs = musb->control_ep->regs;
struct usb_request *req;
- u16 tmp;
+ u16 count, csr;
req = next_ep0_request(musb);
@@ -449,35 +449,35 @@ static void ep0_rxstate(struct musb *musb)
unsigned len = req->length - req->actual;
/* read the buffer */
- tmp = musb_readb(regs, MUSB_COUNT0);
- if (tmp > len) {
+ count = musb_readb(regs, MUSB_COUNT0);
+ if (count > len) {
req->status = -EOVERFLOW;
- tmp = len;
+ count = len;
}
- musb_read_fifo(&musb->endpoints[0], tmp, buf);
- req->actual += tmp;
- tmp = MUSB_CSR0_P_SVDRXPKTRDY;
- if (tmp < 64 || req->actual == req->length) {
+ musb_read_fifo(&musb->endpoints[0], count, buf);
+ req->actual += count;
+ csr = MUSB_CSR0_P_SVDRXPKTRDY;
+ if (count < 64 || req->actual == req->length) {
musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
- tmp |= MUSB_CSR0_P_DATAEND;
+ csr |= MUSB_CSR0_P_DATAEND;
} else
req = NULL;
} else
- tmp = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL;
+ csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL;
/* Completion handler may choose to stall, e.g. because the
* message just received holds invalid data.
*/
if (req) {
- musb->ackpend = tmp;
+ musb->ackpend = csr;
musb_g_ep0_giveback(musb, req);
if (!musb->ackpend)
return;
musb->ackpend = 0;
}
musb_ep_select(musb->mregs, 0);
- musb_writew(regs, MUSB_CSR0, tmp);
+ musb_writew(regs, MUSB_CSR0, csr);
}
/*
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 8b4be012669..3133990f04e 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -108,7 +108,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
/*
* Clear TX fifo. Needed to avoid BABBLE errors.
*/
-static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
{
void __iomem *epio = ep->regs;
u16 csr;
@@ -291,6 +291,7 @@ __acquires(musb->lock)
urb->actual_length, urb->transfer_buffer_length
);
+ usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
spin_unlock(&musb->lock);
usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status);
spin_lock(&musb->lock);
@@ -353,8 +354,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
break;
}
- usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
-
qh->is_ready = 0;
__musb_giveback(musb, urb, status);
qh->is_ready = ready;
@@ -436,7 +435,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
}
}
-static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
+static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
{
/* we don't want fifo to fill itself again;
* ignore dma (various models),
@@ -1005,7 +1004,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
/*
* Handle default endpoint interrupt as host. Only called in IRQ time
- * from the LinuxIsr() interrupt service routine.
+ * from musb_interrupt().
*
* called with controller irqlocked
*/
@@ -1791,7 +1790,9 @@ static int musb_urb_enqueue(
*/
qh = kzalloc(sizeof *qh, mem_flags);
if (!qh) {
+ spin_lock_irqsave(&musb->lock, flags);
usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
return -ENOMEM;
}
@@ -1873,7 +1874,11 @@ static int musb_urb_enqueue(
/* set up tt info if needed */
if (urb->dev->tt) {
qh->h_port_reg = (u8) urb->dev->ttport;
- qh->h_addr_reg |= 0x80;
+ if (urb->dev->tt->hub)
+ qh->h_addr_reg =
+ (u8) urb->dev->tt->hub->devnum;
+ if (urb->dev->tt->multi)
+ qh->h_addr_reg |= 0x80;
}
}
}
@@ -1903,7 +1908,9 @@ static int musb_urb_enqueue(
done:
if (ret != 0) {
+ spin_lock_irqsave(&musb->lock, flags);
usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
kfree(qh);
}
return ret;
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index 6bbedae83af..223f0a51409 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -37,7 +37,9 @@
#include <linux/io.h>
-#ifndef CONFIG_ARM
+#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
+ && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
+ && !defined(CONFIG_PPC64)
static inline void readsl(const void __iomem *addr, void *buf, int len)
{ insl((unsigned long)addr, buf, len); }
static inline void readsw(const void __iomem *addr, void *buf, int len)
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 9ba8fb7fcd2..8c734ef2c1e 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -45,8 +45,8 @@
#define MUSB_HSDMA_ADDRESS 0x8
#define MUSB_HSDMA_COUNT 0xc
-#define MUSB_HSDMA_CHANNEL_OFFSET(_bChannel, _offset) \
- (MUSB_HSDMA_BASE + (_bChannel << 4) + _offset)
+#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \
+ (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
/* control register (16-bit): */
#define MUSB_HSDMA_ENABLE_SHIFT 0
@@ -67,23 +67,23 @@
struct musb_dma_controller;
struct musb_dma_channel {
- struct dma_channel Channel;
+ struct dma_channel channel;
struct musb_dma_controller *controller;
- u32 dwStartAddress;
+ u32 start_addr;
u32 len;
- u16 wMaxPacketSize;
- u8 bIndex;
+ u16 max_packet_sz;
+ u8 idx;
u8 epnum;
u8 transmit;
};
struct musb_dma_controller {
- struct dma_controller Controller;
- struct musb_dma_channel aChannel[MUSB_HSDMA_CHANNELS];
- void *pDmaPrivate;
- void __iomem *pCoreBase;
- u8 bChannelCount;
- u8 bmUsedChannels;
+ struct dma_controller controller;
+ struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS];
+ void *private_data;
+ void __iomem *base;
+ u8 channel_count;
+ u8 used_channels;
u8 irq;
};
@@ -93,91 +93,91 @@ static int dma_controller_start(struct dma_controller *c)
return 0;
}
-static void dma_channel_release(struct dma_channel *pChannel);
+static void dma_channel_release(struct dma_channel *channel);
static int dma_controller_stop(struct dma_controller *c)
{
- struct musb_dma_controller *controller =
- container_of(c, struct musb_dma_controller, Controller);
- struct musb *musb = (struct musb *) controller->pDmaPrivate;
- struct dma_channel *pChannel;
- u8 bBit;
+ struct musb_dma_controller *controller = container_of(c,
+ struct musb_dma_controller, controller);
+ struct musb *musb = controller->private_data;
+ struct dma_channel *channel;
+ u8 bit;
- if (controller->bmUsedChannels != 0) {
+ if (controller->used_channels != 0) {
dev_err(musb->controller,
"Stopping DMA controller while channel active\n");
- for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) {
- if (controller->bmUsedChannels & (1 << bBit)) {
- pChannel = &controller->aChannel[bBit].Channel;
- dma_channel_release(pChannel);
+ for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) {
+ if (controller->used_channels & (1 << bit)) {
+ channel = &controller->channel[bit].channel;
+ dma_channel_release(channel);
- if (!controller->bmUsedChannels)
+ if (!controller->used_channels)
break;
}
}
}
+
return 0;
}
static struct dma_channel *dma_channel_allocate(struct dma_controller *c,
struct musb_hw_ep *hw_ep, u8 transmit)
{
- u8 bBit;
- struct dma_channel *pChannel = NULL;
- struct musb_dma_channel *pImplChannel = NULL;
- struct musb_dma_controller *controller =
- container_of(c, struct musb_dma_controller, Controller);
-
- for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) {
- if (!(controller->bmUsedChannels & (1 << bBit))) {
- controller->bmUsedChannels |= (1 << bBit);
- pImplChannel = &(controller->aChannel[bBit]);
- pImplChannel->controller = controller;
- pImplChannel->bIndex = bBit;
- pImplChannel->epnum = hw_ep->epnum;
- pImplChannel->transmit = transmit;
- pChannel = &(pImplChannel->Channel);
- pChannel->private_data = pImplChannel;
- pChannel->status = MUSB_DMA_STATUS_FREE;
- pChannel->max_len = 0x10000;
+ struct musb_dma_controller *controller = container_of(c,
+ struct musb_dma_controller, controller);
+ struct musb_dma_channel *musb_channel = NULL;
+ struct dma_channel *channel = NULL;
+ u8 bit;
+
+ for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) {
+ if (!(controller->used_channels & (1 << bit))) {
+ controller->used_channels |= (1 << bit);
+ musb_channel = &(controller->channel[bit]);
+ musb_channel->controller = controller;
+ musb_channel->idx = bit;
+ musb_channel->epnum = hw_ep->epnum;
+ musb_channel->transmit = transmit;
+ channel = &(musb_channel->channel);
+ channel->private_data = musb_channel;
+ channel->status = MUSB_DMA_STATUS_FREE;
+ channel->max_len = 0x10000;
/* Tx => mode 1; Rx => mode 0 */
- pChannel->desired_mode = transmit;
- pChannel->actual_len = 0;
+ channel->desired_mode = transmit;
+ channel->actual_len = 0;
break;
}
}
- return pChannel;
+
+ return channel;
}
-static void dma_channel_release(struct dma_channel *pChannel)
+static void dma_channel_release(struct dma_channel *channel)
{
- struct musb_dma_channel *pImplChannel =
- (struct musb_dma_channel *) pChannel->private_data;
+ struct musb_dma_channel *musb_channel = channel->private_data;
- pChannel->actual_len = 0;
- pImplChannel->dwStartAddress = 0;
- pImplChannel->len = 0;
+ channel->actual_len = 0;
+ musb_channel->start_addr = 0;
+ musb_channel->len = 0;
- pImplChannel->controller->bmUsedChannels &=
- ~(1 << pImplChannel->bIndex);
+ musb_channel->controller->used_channels &=
+ ~(1 << musb_channel->idx);
- pChannel->status = MUSB_DMA_STATUS_UNKNOWN;
+ channel->status = MUSB_DMA_STATUS_UNKNOWN;
}
-static void configure_channel(struct dma_channel *pChannel,
+static void configure_channel(struct dma_channel *channel,
u16 packet_sz, u8 mode,
dma_addr_t dma_addr, u32 len)
{
- struct musb_dma_channel *pImplChannel =
- (struct musb_dma_channel *) pChannel->private_data;
- struct musb_dma_controller *controller = pImplChannel->controller;
- void __iomem *mbase = controller->pCoreBase;
- u8 bChannel = pImplChannel->bIndex;
+ struct musb_dma_channel *musb_channel = channel->private_data;
+ struct musb_dma_controller *controller = musb_channel->controller;
+ void __iomem *mbase = controller->base;
+ u8 bchannel = musb_channel->idx;
u16 csr = 0;
DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
- pChannel, packet_sz, dma_addr, len, mode);
+ channel, packet_sz, dma_addr, len, mode);
if (mode) {
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
@@ -195,180 +195,183 @@ static void configure_channel(struct dma_channel *pChannel,
}
}
- csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
+ csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
| (1 << MUSB_HSDMA_IRQENABLE_SHIFT)
- | (pImplChannel->transmit
+ | (musb_channel->transmit
? (1 << MUSB_HSDMA_TRANSMIT_SHIFT)
: 0);
/* address/count */
musb_writel(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS),
dma_addr);
musb_writel(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT),
len);
/* control (this should start things) */
musb_writew(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL),
csr);
}
-static int dma_channel_program(struct dma_channel *pChannel,
+static int dma_channel_program(struct dma_channel *channel,
u16 packet_sz, u8 mode,
dma_addr_t dma_addr, u32 len)
{
- struct musb_dma_channel *pImplChannel =
- (struct musb_dma_channel *) pChannel->private_data;
+ struct musb_dma_channel *musb_channel = channel->private_data;
DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
- pImplChannel->epnum,
- pImplChannel->transmit ? "Tx" : "Rx",
+ musb_channel->epnum,
+ musb_channel->transmit ? "Tx" : "Rx",
packet_sz, dma_addr, len, mode);
- BUG_ON(pChannel->status == MUSB_DMA_STATUS_UNKNOWN ||
- pChannel->status == MUSB_DMA_STATUS_BUSY);
+ BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
+ channel->status == MUSB_DMA_STATUS_BUSY);
- pChannel->actual_len = 0;
- pImplChannel->dwStartAddress = dma_addr;
- pImplChannel->len = len;
- pImplChannel->wMaxPacketSize = packet_sz;
- pChannel->status = MUSB_DMA_STATUS_BUSY;
+ channel->actual_len = 0;
+ musb_channel->start_addr = dma_addr;
+ musb_channel->len = len;
+ musb_channel->max_packet_sz = packet_sz;
+ channel->status = MUSB_DMA_STATUS_BUSY;
if ((mode == 1) && (len >= packet_sz))
- configure_channel(pChannel, packet_sz, 1, dma_addr, len);
+ configure_channel(channel, packet_sz, 1, dma_addr, len);
else
- configure_channel(pChannel, packet_sz, 0, dma_addr, len);
+ configure_channel(channel, packet_sz, 0, dma_addr, len);
return true;
}
-static int dma_channel_abort(struct dma_channel *pChannel)
+static int dma_channel_abort(struct dma_channel *channel)
{
- struct musb_dma_channel *pImplChannel =
- (struct musb_dma_channel *) pChannel->private_data;
- u8 bChannel = pImplChannel->bIndex;
- void __iomem *mbase = pImplChannel->controller->pCoreBase;
+ struct musb_dma_channel *musb_channel = channel->private_data;
+ void __iomem *mbase = musb_channel->controller->base;
+
+ u8 bchannel = musb_channel->idx;
u16 csr;
- if (pChannel->status == MUSB_DMA_STATUS_BUSY) {
- if (pImplChannel->transmit) {
+ if (channel->status == MUSB_DMA_STATUS_BUSY) {
+ if (musb_channel->transmit) {
csr = musb_readw(mbase,
- MUSB_EP_OFFSET(pImplChannel->epnum,
+ MUSB_EP_OFFSET(musb_channel->epnum,
MUSB_TXCSR));
csr &= ~(MUSB_TXCSR_AUTOSET |
MUSB_TXCSR_DMAENAB |
MUSB_TXCSR_DMAMODE);
musb_writew(mbase,
- MUSB_EP_OFFSET(pImplChannel->epnum,
- MUSB_TXCSR),
+ MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
csr);
} else {
csr = musb_readw(mbase,
- MUSB_EP_OFFSET(pImplChannel->epnum,
+ MUSB_EP_OFFSET(musb_channel->epnum,
MUSB_RXCSR));
csr &= ~(MUSB_RXCSR_AUTOCLEAR |
MUSB_RXCSR_DMAENAB |
MUSB_RXCSR_DMAMODE);
musb_writew(mbase,
- MUSB_EP_OFFSET(pImplChannel->epnum,
- MUSB_RXCSR),
+ MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
csr);
}
musb_writew(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL),
0);
musb_writel(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS),
0);
musb_writel(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT),
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT),
0);
- pChannel->status = MUSB_DMA_STATUS_FREE;
+ channel->status = MUSB_DMA_STATUS_FREE;
}
+
return 0;
}
static irqreturn_t dma_controller_irq(int irq, void *private_data)
{
- struct musb_dma_controller *controller =
- (struct musb_dma_controller *)private_data;
- struct musb_dma_channel *pImplChannel;
- struct musb *musb = controller->pDmaPrivate;
- void __iomem *mbase = controller->pCoreBase;
- struct dma_channel *pChannel;
- u8 bChannel;
- u16 csr;
- u32 dwAddress;
- u8 int_hsdma;
+ struct musb_dma_controller *controller = private_data;
+ struct musb *musb = controller->private_data;
+ struct musb_dma_channel *musb_channel;
+ struct dma_channel *channel;
+
+ void __iomem *mbase = controller->base;
+
irqreturn_t retval = IRQ_NONE;
+
unsigned long flags;
+ u8 bchannel;
+ u8 int_hsdma;
+
+ u32 addr;
+ u16 csr;
+
spin_lock_irqsave(&musb->lock, flags);
int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
if (!int_hsdma)
goto done;
- for (bChannel = 0; bChannel < MUSB_HSDMA_CHANNELS; bChannel++) {
- if (int_hsdma & (1 << bChannel)) {
- pImplChannel = (struct musb_dma_channel *)
- &(controller->aChannel[bChannel]);
- pChannel = &pImplChannel->Channel;
+ for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
+ if (int_hsdma & (1 << bchannel)) {
+ musb_channel = (struct musb_dma_channel *)
+ &(controller->channel[bchannel]);
+ channel = &musb_channel->channel;
csr = musb_readw(mbase,
- MUSB_HSDMA_CHANNEL_OFFSET(bChannel,
+ MUSB_HSDMA_CHANNEL_OFFSET(bchannel,
MUSB_HSDMA_CONTROL));
- if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT))
- pImplChannel->Channel.status =
+ if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) {
+ musb_channel->channel.status =
MUSB_DMA_STATUS_BUS_ABORT;
- else {
+ } else {
u8 devctl;
- dwAddress = musb_readl(mbase,
+ addr = musb_readl(mbase,
MUSB_HSDMA_CHANNEL_OFFSET(
- bChannel,
+ bchannel,
MUSB_HSDMA_ADDRESS));
- pChannel->actual_len = dwAddress
- - pImplChannel->dwStartAddress;
+ channel->actual_len = addr
+ - musb_channel->start_addr;
DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
- pChannel, pImplChannel->dwStartAddress,
- dwAddress, pChannel->actual_len,
- pImplChannel->len,
- (pChannel->actual_len
- < pImplChannel->len) ?
+ channel, musb_channel->start_addr,
+ addr, channel->actual_len,
+ musb_channel->len,
+ (channel->actual_len
+ < musb_channel->len) ?
"=> reconfig 0" : "=> complete");
devctl = musb_readb(mbase, MUSB_DEVCTL);
- pChannel->status = MUSB_DMA_STATUS_FREE;
+ channel->status = MUSB_DMA_STATUS_FREE;
/* completed */
if ((devctl & MUSB_DEVCTL_HM)
- && (pImplChannel->transmit)
- && ((pChannel->desired_mode == 0)
- || (pChannel->actual_len &
- (pImplChannel->wMaxPacketSize - 1)))
+ && (musb_channel->transmit)
+ && ((channel->desired_mode == 0)
+ || (channel->actual_len &
+ (musb_channel->max_packet_sz - 1)))
) {
/* Send out the packet */
musb_ep_select(mbase,
- pImplChannel->epnum);
+ musb_channel->epnum);
musb_writew(mbase, MUSB_EP_OFFSET(
- pImplChannel->epnum,
+ musb_channel->epnum,
MUSB_TXCSR),
MUSB_TXCSR_TXPKTRDY);
- } else
+ } else {
musb_dma_completion(
musb,
- pImplChannel->epnum,
- pImplChannel->transmit);
+ musb_channel->epnum,
+ musb_channel->transmit);
+ }
}
}
}
@@ -380,9 +383,9 @@ done:
void dma_controller_destroy(struct dma_controller *c)
{
- struct musb_dma_controller *controller;
+ struct musb_dma_controller *controller = container_of(c,
+ struct musb_dma_controller, controller);
- controller = container_of(c, struct musb_dma_controller, Controller);
if (!controller)
return;
@@ -393,7 +396,7 @@ void dma_controller_destroy(struct dma_controller *c)
}
struct dma_controller *__init
-dma_controller_create(struct musb *musb, void __iomem *pCoreBase)
+dma_controller_create(struct musb *musb, void __iomem *base)
{
struct musb_dma_controller *controller;
struct device *dev = musb->controller;
@@ -405,29 +408,30 @@ dma_controller_create(struct musb *musb, void __iomem *pCoreBase)
return NULL;
}
- controller = kzalloc(sizeof(struct musb_dma_controller), GFP_KERNEL);
+ controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
return NULL;
- controller->bChannelCount = MUSB_HSDMA_CHANNELS;
- controller->pDmaPrivate = musb;
- controller->pCoreBase = pCoreBase;
+ controller->channel_count = MUSB_HSDMA_CHANNELS;
+ controller->private_data = musb;
+ controller->base = base;
- controller->Controller.start = dma_controller_start;
- controller->Controller.stop = dma_controller_stop;
- controller->Controller.channel_alloc = dma_channel_allocate;
- controller->Controller.channel_release = dma_channel_release;
- controller->Controller.channel_program = dma_channel_program;
- controller->Controller.channel_abort = dma_channel_abort;
+ controller->controller.start = dma_controller_start;
+ controller->controller.stop = dma_controller_stop;
+ controller->controller.channel_alloc = dma_channel_allocate;
+ controller->controller.channel_release = dma_channel_release;
+ controller->controller.channel_program = dma_channel_program;
+ controller->controller.channel_abort = dma_channel_abort;
if (request_irq(irq, dma_controller_irq, IRQF_DISABLED,
- musb->controller->bus_id, &controller->Controller)) {
+ musb->controller->bus_id, &controller->controller)) {
dev_err(dev, "request_irq %d failed!\n", irq);
- dma_controller_destroy(&controller->Controller);
+ dma_controller_destroy(&controller->controller);
+
return NULL;
}
controller->irq = irq;
- return &controller->Controller;
+ return &controller->controller;
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 298b22e6ad0..9d2dcb121c5 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -35,8 +35,8 @@
#include <linux/io.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/mux.h>
+#include <mach/hardware.h>
+#include <mach/mux.h>
#include "musb_core.h"
#include "omap2430.h"
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index 786a62071f7..dc7670718cd 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -11,8 +11,8 @@
#define __MUSB_OMAP243X_H__
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
-#include <asm/arch/hardware.h>
-#include <asm/arch/usb.h>
+#include <mach/hardware.h>
+#include <mach/usb.h>
/*
* OMAP2430-specific definitions
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 79ea98c66fa..537f953bd7f 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -220,8 +220,8 @@ static void aircable_send(struct usb_serial_port *port)
buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
if (!buf) {
- err("%s- kzalloc(%d) failed.", __func__,
- count + HCI_HEADER_LENGTH);
+ dev_err(&port->dev, "%s- kzalloc(%d) failed.\n",
+ __func__, count + HCI_HEADER_LENGTH);
return;
}
@@ -272,23 +272,24 @@ static void aircable_read(struct work_struct *work)
* 64 bytes, to ensure I do not get throttled.
* Ask USB mailing list for better aproach.
*/
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty) {
schedule_work(&priv->rx_work);
- err("%s - No tty available", __func__);
+ dev_err(&port->dev, "%s - No tty available\n", __func__);
return ;
}
count = min(64, serial_buf_data_avail(priv->rx_buf));
if (count <= 0)
- return; /* We have finished sending everything. */
+ goto out; /* We have finished sending everything. */
tty_prepare_flip_string(tty, &data, count);
if (!data) {
- err("%s- kzalloc(%d) failed.", __func__, count);
- return;
+ dev_err(&port->dev, "%s- kzalloc(%d) failed.",
+ __func__, count);
+ goto out;
}
serial_buf_get(priv->rx_buf, data, count);
@@ -297,7 +298,8 @@ static void aircable_read(struct work_struct *work)
if (serial_buf_data_avail(priv->rx_buf))
schedule_work(&priv->rx_work);
-
+out:
+ tty_kref_put(tty);
return;
}
/* End of private methods */
@@ -334,7 +336,7 @@ static int aircable_attach(struct usb_serial *serial)
priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
if (!priv) {
- err("%s- kmalloc(%Zd) failed.", __func__,
+ dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
sizeof(struct aircable_private));
return -ENOMEM;
}
@@ -495,7 +497,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, urb->transfer_buffer);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
if (urb->actual_length <= 2) {
/* This is an incomplete package */
@@ -527,6 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
aircable_read(&priv->rx_work);
}
+ tty_kref_put(tty);
/* Schedule the next read _if_ we are still open */
if (port->port.count) {
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 2ebe06c3405..b7eacad4d48 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -187,7 +187,7 @@ static int belkin_sa_startup(struct usb_serial *serial)
/* see comments at top of file */
priv->bad_flow_control =
(le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
- info("bcdDevice: %04x, bfc: %d",
+ dev_info(&dev->dev, "bcdDevice: %04x, bfc: %d\n",
le16_to_cpu(dev->descriptor.bcdDevice),
priv->bad_flow_control);
@@ -228,7 +228,7 @@ static int belkin_sa_open(struct tty_struct *tty,
port->read_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (retval) {
- err("usb_submit_urb(read bulk) failed");
+ dev_err(&port->dev, "usb_submit_urb(read bulk) failed\n");
goto exit;
}
@@ -236,7 +236,7 @@ static int belkin_sa_open(struct tty_struct *tty,
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
usb_kill_urb(port->read_urb);
- err(" usb_submit_urb(read int) failed");
+ dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
}
exit:
@@ -322,7 +322,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
/* Overrun Error */
if (priv->last_lsr & BELKIN_SA_LSR_OE) {
}
@@ -335,14 +335,15 @@ static void belkin_sa_read_int_callback(struct urb *urb)
/* Break Indicator */
if (priv->last_lsr & BELKIN_SA_LSR_BI) {
}
+ tty_kref_put(tty);
}
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&port->dev, "%s - usb_submit_urb failed with "
+ "result %d\n", __func__, retval);
}
static void belkin_sa_set_termios(struct tty_struct *tty,
@@ -381,12 +382,12 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
if ((old_cflag & CBAUD) == B0) {
control_state |= (TIOCM_DTR|TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
- err("Set DTR error");
+ dev_err(&port->dev, "Set DTR error\n");
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS))
if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
, 1) < 0)
- err("Set RTS error");
+ dev_err(&port->dev, "Set RTS error\n");
}
}
@@ -402,18 +403,18 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
/* Report the actual baud rate back to the caller */
tty_encode_baud_rate(tty, baud, baud);
if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
- err("Set baudrate error");
+ dev_err(&port->dev, "Set baudrate error\n");
} else {
/* Disable flow control */
if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
BELKIN_SA_FLOW_NONE) < 0)
- err("Disable flowcontrol error");
+ dev_err(&port->dev, "Disable flowcontrol error\n");
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
- err("DTR LOW error");
+ dev_err(&port->dev, "DTR LOW error\n");
if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
- err("RTS LOW error");
+ dev_err(&port->dev, "RTS LOW error\n");
}
/* set the parity */
@@ -424,7 +425,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
else
urb_value = BELKIN_SA_PARITY_NONE;
if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
- err("Set parity error");
+ dev_err(&port->dev, "Set parity error\n");
}
/* set the number of data bits */
@@ -447,7 +448,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
break;
}
if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
- err("Set data bits error");
+ dev_err(&port->dev, "Set data bits error\n");
}
/* set the number of stop bits */
@@ -456,7 +457,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
: BELKIN_SA_STOP_BITS(1);
if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
urb_value) < 0)
- err("Set stop bits error");
+ dev_err(&port->dev, "Set stop bits error\n");
}
/* Set flow control */
@@ -477,7 +478,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
urb_value &= ~(BELKIN_SA_FLOW_IRTS);
if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0)
- err("Set flow control error");
+ dev_err(&port->dev, "Set flow control error\n");
}
/* save off the modified port settings */
@@ -493,7 +494,7 @@ static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
struct usb_serial *serial = port->serial;
if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
- err("Set break_ctl %d", break_state);
+ dev_err(&port->dev, "Set break_ctl %d\n", break_state);
}
@@ -553,13 +554,13 @@ static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts);
if (retval < 0) {
- err("Set RTS error %d", retval);
+ dev_err(&port->dev, "Set RTS error %d\n", retval);
goto exit;
}
retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
if (retval < 0) {
- err("Set DTR error %d", retval);
+ dev_err(&port->dev, "Set DTR error %d\n", retval);
goto exit;
}
exit:
@@ -576,7 +577,8 @@ static int __init belkin_sa_init(void)
retval = usb_register(&belkin_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&belkin_device);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 7b74238ad1c..5b20de130e0 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -117,7 +117,7 @@ static int usb_console_setup(struct console *co, char *options)
}
port = serial->port[0];
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
info->port = port;
@@ -143,7 +143,7 @@ static int usb_console_setup(struct console *co, char *options)
}
memset(&dummy, 0, sizeof(struct ktermios));
tty->termios = termios;
- port->port.tty = tty;
+ tty_port_tty_set(&port->port, tty);
}
/* only call the device specific open if this
@@ -161,9 +161,9 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) {
termios->c_cflag = cflag;
tty_termios_encode_baud_rate(termios, baud, baud);
- serial->type->set_termios(NULL, port, &dummy);
+ serial->type->set_termios(tty, port, &dummy);
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
kfree(termios);
kfree(tty);
}
@@ -176,7 +176,7 @@ out:
return retval;
free_termios:
kfree(termios);
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
free_tty:
kfree(tty);
reset_open_count:
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 442cba69cce..8008d0bc80a 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -72,6 +72,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+ { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
@@ -83,6 +84,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
+ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
@@ -93,6 +95,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
+ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ } /* Terminating Entry */
};
@@ -750,7 +753,8 @@ static int __init cp2101_init(void)
}
/* Success */
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index b4d72351cb9..858bdd038fb 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -141,7 +141,8 @@ static int cyberjack_startup(struct usb_serial *serial)
result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
GFP_KERNEL);
if (result)
- err(" usb_submit_urb(read int) failed");
+ dev_err(&serial->dev->dev,
+ "usb_submit_urb(read int) failed\n");
dbg("%s - usb_submit_urb(int urb)", __func__);
}
@@ -274,8 +275,9 @@ static int cyberjack_write(struct tty_struct *tty,
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -351,7 +353,9 @@ static void cyberjack_read_int_callback(struct urb *urb)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ dev_err(&port->dev, "%s - failed resubmitting "
+ "read urb, error %d\n",
+ __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
}
@@ -360,7 +364,7 @@ resubmit:
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
- err(" usb_submit_urb(read int) failed");
+ dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
dbg("%s - usb_submit_urb(int urb)", __func__);
}
@@ -384,7 +388,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
return;
}
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty) {
dbg("%s - ignoring since device not open\n", __func__);
return;
@@ -394,6 +398,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
spin_lock(&priv->lock);
@@ -413,8 +418,8 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev, "%s - failed resubmitting read "
+ "urb, error %d\n", __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
}
@@ -461,8 +466,9 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -498,8 +504,9 @@ static int __init cyberjack_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
+ DRIVER_AUTHOR "\n");
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 22837a3f2f8..eae4740d448 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -404,8 +404,8 @@ static int cypress_serial_control(struct tty_struct *tty,
retval != -ENODEV);
if (retval != sizeof(feature_buffer)) {
- err("%s - failed sending serial line settings - %d",
- __func__, retval);
+ dev_err(&port->dev, "%s - failed sending serial "
+ "line settings - %d\n", __func__, retval);
cypress_set_dead(port);
} else {
spin_lock_irqsave(&priv->lock, flags);
@@ -443,7 +443,8 @@ static int cypress_serial_control(struct tty_struct *tty,
&& retval != -ENODEV);
if (retval != sizeof(feature_buffer)) {
- err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+ dev_err(&port->dev, "%s - failed to retrieve serial "
+ "line settings - %d\n", __func__, retval);
cypress_set_dead(port);
return retval;
} else {
@@ -476,8 +477,8 @@ static void cypress_set_dead(struct usb_serial_port *port)
priv->comm_is_ok = 0;
spin_unlock_irqrestore(&priv->lock, flags);
- err("cypress_m8 suspending failing port %d - interval might be too short",
- port->number);
+ dev_err(&port->dev, "cypress_m8 suspending failing port %d - "
+ "interval might be too short\n", port->number);
}
@@ -679,7 +680,8 @@ static int cypress_open(struct tty_struct *tty,
/* setup the port and start reading from the device */
if (!port->interrupt_in_urb) {
- err("%s - interrupt_in_urb is empty!", __func__);
+ dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n",
+ __func__);
return -1;
}
@@ -1107,8 +1109,8 @@ static void cypress_set_termios(struct tty_struct *tty,
data_bits = 3;
break;
default:
- err("%s - CSIZE was set, but not CS5-CS8",
- __func__);
+ dev_err(&port->dev, "%s - CSIZE was set, but not CS5-CS8\n",
+ __func__);
data_bits = 3;
}
spin_lock_irqsave(&priv->lock, flags);
@@ -1286,7 +1288,7 @@ static void cypress_read_int_callback(struct urb *urb)
}
spin_unlock_irqrestore(&priv->lock, flags);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty) {
dbg("%s - bad tty pointer - exiting", __func__);
return;
@@ -1362,7 +1364,7 @@ static void cypress_read_int_callback(struct urb *urb)
data[i]);
tty_insert_flip_char(tty, data[i], tty_flag);
}
- tty_flip_buffer_push(port->port.tty);
+ tty_flip_buffer_push(tty);
}
spin_lock_irqsave(&priv->lock, flags);
@@ -1371,6 +1373,7 @@ static void cypress_read_int_callback(struct urb *urb)
spin_unlock_irqrestore(&priv->lock, flags);
continue_read:
+ tty_kref_put(tty);
/* Continue trying to always read... unless the port has closed. */
@@ -1657,7 +1660,8 @@ static int __init cypress_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 240aad1acaa..69f84f0ea6f 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -604,7 +604,9 @@ static void digi_wakeup_write_lock(struct work_struct *work)
static void digi_wakeup_write(struct usb_serial_port *port)
{
- tty_wakeup(port->port.tty);
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
@@ -659,7 +661,8 @@ static int digi_write_oob_command(struct usb_serial_port *port,
}
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
if (ret)
- err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n",
+ __func__, ret);
return ret;
}
@@ -741,7 +744,8 @@ static int digi_write_inb_command(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret)
- err("%s: usb_submit_urb failed, ret=%d, port=%d",
+ dev_err(&port->dev,
+ "%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
return ret;
}
@@ -810,7 +814,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
spin_unlock(&port_priv->dp_port_lock);
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
if (ret)
- err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n",
+ __func__, ret);
return ret;
}
@@ -905,7 +910,8 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret)
- err("%s: usb_submit_urb failed, ret=%d, port=%d",
+ dev_err(&port->dev,
+ "%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
}
@@ -1212,7 +1218,8 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
/* return length of new data written, or error */
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret < 0)
- err("%s: usb_submit_urb failed, ret=%d, port=%d",
+ dev_err(&port->dev,
+ "%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
dbg("digi_write: returning %d", ret);
return ret;
@@ -1233,14 +1240,16 @@ static void digi_write_bulk_callback(struct urb *urb)
/* port and serial sanity check */
if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
- err("%s: port or port->private is NULL, status=%d",
- __func__, status);
+ dev_err(&port->dev,
+ "%s: port or port->private is NULL, status=%d\n",
+ __func__, status);
return;
}
serial = port->serial;
if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) {
- err("%s: serial or serial->private is NULL, status=%d",
- __func__, status);
+ dev_err(&port->dev,
+ "%s: serial or serial->private is NULL, status=%d\n",
+ __func__, status);
return;
}
@@ -1282,7 +1291,8 @@ static void digi_write_bulk_callback(struct urb *urb)
spin_unlock(&priv->dp_port_lock);
if (ret)
- err("%s: usb_submit_urb failed, ret=%d, port=%d",
+ dev_err(&port->dev,
+ "%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
}
@@ -1516,8 +1526,9 @@ static int digi_startup_device(struct usb_serial *serial)
port->write_urb->dev = port->serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret != 0) {
- err("%s: usb_submit_urb failed, ret=%d, port=%d",
- __func__, ret, i);
+ dev_err(&port->dev,
+ "%s: usb_submit_urb failed, ret=%d, port=%d\n",
+ __func__, ret, i);
break;
}
}
@@ -1616,22 +1627,26 @@ static void digi_read_bulk_callback(struct urb *urb)
dbg("digi_read_bulk_callback: TOP");
/* port sanity check, do not resubmit if port is not valid */
- if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
- err("%s: port or port->private is NULL, status=%d",
- __func__, status);
+ if (port == NULL)
+ return;
+ priv = usb_get_serial_port_data(port);
+ if (priv == NULL) {
+ dev_err(&port->dev, "%s: port->private is NULL, status=%d\n",
+ __func__, status);
return;
}
if (port->serial == NULL ||
(serial_priv = usb_get_serial_data(port->serial)) == NULL) {
- err("%s: serial is bad or serial->private is NULL, status=%d",
- __func__, status);
+ dev_err(&port->dev, "%s: serial is bad or serial->private "
+ "is NULL, status=%d\n", __func__, status);
return;
}
/* do not resubmit urb if it has any status error */
if (status) {
- err("%s: nonzero read bulk status: status=%d, port=%d",
- __func__, status, priv->dp_port_num);
+ dev_err(&port->dev,
+ "%s: nonzero read bulk status: status=%d, port=%d\n",
+ __func__, status, priv->dp_port_num);
return;
}
@@ -1648,8 +1663,9 @@ static void digi_read_bulk_callback(struct urb *urb)
urb->dev = port->serial->dev;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret != 0) {
- err("%s: failed resubmitting urb, ret=%d, port=%d",
- __func__, ret, priv->dp_port_num);
+ dev_err(&port->dev,
+ "%s: failed resubmitting urb, ret=%d, port=%d\n",
+ __func__, ret, priv->dp_port_num);
}
}
@@ -1668,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty;
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
@@ -1685,13 +1701,15 @@ static int digi_read_inb_callback(struct urb *urb)
/* short/multiple packet check */
if (urb->actual_length != len + 2) {
- err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
- "port=%d, opcode=%d, len=%d, actual_length=%d, "
- "status=%d", __func__, status, priv->dp_port_num,
- opcode, len, urb->actual_length, port_status);
+ dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
+ "urb->status=%d, port=%d, opcode=%d, len=%d, "
+ "actual_length=%d, status=%d\n", __func__, status,
+ priv->dp_port_num, opcode, len, urb->actual_length,
+ port_status);
return -1;
}
+ tty = tty_port_tty_get(&port->port);
spin_lock(&priv->dp_port_lock);
/* check for throttle; if set, do not resubmit read urb */
@@ -1735,6 +1753,7 @@ static int digi_read_inb_callback(struct urb *urb)
}
}
spin_unlock(&priv->dp_port_lock);
+ tty_kref_put(tty);
if (opcode == DIGI_CMD_RECEIVE_DISABLE)
dbg("%s: got RECEIVE_DISABLE", __func__);
@@ -1760,6 +1779,7 @@ static int digi_read_oob_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
struct usb_serial *serial = port->serial;
+ struct tty_struct *tty;
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode, line, status, val;
int i;
@@ -1787,10 +1807,11 @@ static int digi_read_oob_callback(struct urb *urb)
if (priv == NULL)
return -1;
+ tty = tty_port_tty_get(&port->port);
rts = 0;
if (port->port.count)
- rts = port->port.tty->termios->c_cflag & CRTSCTS;
-
+ rts = tty->termios->c_cflag & CRTSCTS;
+
if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
/* convert from digi flags to termiox flags */
@@ -1798,14 +1819,14 @@ static int digi_read_oob_callback(struct urb *urb)
priv->dp_modem_signals |= TIOCM_CTS;
/* port must be open to use tty struct */
if (rts) {
- port->port.tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
digi_wakeup_write(port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */
if (rts)
- port->port.tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
}
if (val & DIGI_READ_INPUT_SIGNALS_DSR)
priv->dp_modem_signals |= TIOCM_DSR;
@@ -1830,6 +1851,7 @@ static int digi_read_oob_callback(struct urb *urb)
} else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
wake_up_interruptible(&priv->dp_flush_wait);
}
+ tty_kref_put(tty);
}
return 0;
@@ -1847,7 +1869,8 @@ static int __init digi_init(void)
retval = usb_register(&digi_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&digi_acceleport_4_device);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index a6ab5b58d9c..8a69cce40b6 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -33,9 +33,8 @@
* Moved MOD_DEC_USE_COUNT to end of empeg_close().
*
* (12/03/2000) gb
- * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to
- * empeg_open(). This notifies the tty driver that the termios have
- * changed.
+ * Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open().
+ * This notifies the tty driver that the termios have changed.
*
* (11/13/2000) gb
* Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
@@ -354,7 +353,7 @@ static void empeg_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
@@ -362,6 +361,7 @@ static void empeg_read_bulk_callback(struct urb *urb)
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
+ tty_kref_put(tty);
/* Continue trying to always read */
usb_fill_bulk_urb(
@@ -416,7 +416,7 @@ static int empeg_startup(struct usb_serial *serial)
dbg("%s", __func__);
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
- err("active config #%d != 1 ??",
+ dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
@@ -499,15 +499,15 @@ static int __init empeg_init(void)
urb = usb_alloc_urb(0, GFP_KERNEL);
write_urb_pool[i] = urb;
if (urb == NULL) {
- err("No more urbs???");
+ printk(KERN_ERR "empeg: No more urbs???\n");
continue;
}
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.",
- __func__);
+ printk(KERN_ERR "empeg: %s - out of memory for urb "
+ "buffers.", __func__);
continue;
}
}
@@ -519,7 +519,8 @@ static int __init empeg_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 711e84f6ed8..3cfc762f505 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -28,7 +28,8 @@ int ezusb_writememory(struct usb_serial *serial, int address,
/* dbg("ezusb_writememory %x, %d", address, length); */
if (!serial->dev) {
- err("%s - no physical device present, failing.", __func__);
+ printk(KERN_ERR "ezusb: %s - no physical device present, "
+ "failing.\n", __func__);
return -ENODEV;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 984f6eff4c4..51d7bdea286 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -578,6 +578,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
{ USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) },
{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
@@ -654,6 +655,9 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+ { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -857,7 +861,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
kfree(buf);
if (rv < 0) {
- err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
+ dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
__func__,
(set & TIOCM_DTR) ? "HIGH" :
(clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1150,7 +1154,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
/* Assume its an FT232R */
priv->chip_type = FT232RL;
}
- info("Detected %s", ftdi_chip_name[priv->chip_type]);
+ dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
}
@@ -1323,7 +1327,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv) {
- err("%s- kmalloc(%Zd) failed.", __func__,
+ dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
sizeof(struct ftdi_private));
return -ENOMEM;
}
@@ -1406,7 +1410,8 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
dbg("%s", __func__);
if (interface == udev->actconfig->interface[0]) {
- info("Ignoring serial port reserved for JTAG");
+ dev_info(&udev->dev,
+ "Ignoring serial port reserved for JTAG\n");
return -ENODEV;
}
@@ -1424,7 +1429,8 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
- info("Fixing invalid wMaxPacketSize on read pipe");
+ dev_info(&serial->dev->dev,
+ "Fixing invalid wMaxPacketSize on read pipe\n");
}
return 0;
@@ -1518,8 +1524,9 @@ static int ftdi_open(struct tty_struct *tty,
ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
return result;
@@ -1553,7 +1560,7 @@ static void ftdi_close(struct tty_struct *tty,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface, buf, 0,
WDR_TIMEOUT) < 0) {
- err("error from flowcontrol urb");
+ dev_err(&port->dev, "error from flowcontrol urb\n");
}
/* drop RTS and DTR */
@@ -1618,14 +1625,15 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
buffer = kmalloc(transfer_size, GFP_ATOMIC);
if (!buffer) {
- err("%s ran out of kernel memory for urb ...", __func__);
+ dev_err(&port->dev,
+ "%s ran out of kernel memory for urb ...\n", __func__);
count = -ENOMEM;
goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- err("%s - no more free urbs", __func__);
+ dev_err(&port->dev, "%s - no more free urbs\n", __func__);
count = -ENOMEM;
goto error_no_urb;
}
@@ -1669,8 +1677,9 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - failed submitting write urb, error %d",
- __func__, status);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, status);
count = status;
goto error;
} else {
@@ -1777,7 +1786,8 @@ static int ftdi_chars_in_buffer(struct tty_struct *tty)
buffered = (int)priv->tx_outstanding_bytes;
spin_unlock_irqrestore(&priv->tx_lock, flags);
if (buffered < 0) {
- err("%s outstanding tx bytes is negative!", __func__);
+ dev_err(&port->dev, "%s outstanding tx bytes is negative!\n",
+ __func__);
buffered = 0;
}
return buffered;
@@ -1793,11 +1803,12 @@ static void ftdi_read_bulk_callback(struct urb *urb)
int status = urb->status;
if (urb->number_of_packets > 0) {
- err("%s transfer_buffer_length %d actual_length %d number of packets %d",
- __func__,
- urb->transfer_buffer_length,
- urb->actual_length, urb->number_of_packets);
- err("%s transfer_flags %x ", __func__, urb->transfer_flags);
+ dev_err(&port->dev, "%s transfer_buffer_length %d "
+ "actual_length %d number of packets %d\n", __func__,
+ urb->transfer_buffer_length,
+ urb->actual_length, urb->number_of_packets);
+ dev_err(&port->dev, "%s transfer_flags %x\n", __func__,
+ urb->transfer_flags);
}
dbg("%s - port %d", __func__, port->number);
@@ -1805,7 +1816,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
if (port->port.count <= 0)
return;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty) {
dbg("%s - bad tty pointer - exiting", __func__);
return;
@@ -1814,17 +1825,17 @@ static void ftdi_read_bulk_callback(struct urb *urb)
priv = usb_get_serial_port_data(port);
if (!priv) {
dbg("%s - bad port private data pointer - exiting", __func__);
- return;
+ goto out;
}
if (urb != port->read_urb)
- err("%s - Not my urb!", __func__);
+ dev_err(&port->dev, "%s - Not my urb!\n", __func__);
if (status) {
/* This will happen at close every time so it is a dbg not an
err */
dbg("(this is ok on close) nonzero read bulk status received: %d", status);
- return;
+ goto out;
}
/* count data bytes, but not status bytes */
@@ -1835,7 +1846,8 @@ static void ftdi_read_bulk_callback(struct urb *urb)
spin_unlock_irqrestore(&priv->rx_lock, flags);
ftdi_process_read(&priv->rx_work.work);
-
+out:
+ tty_kref_put(tty);
} /* ftdi_read_bulk_callback */
@@ -1860,7 +1872,7 @@ static void ftdi_process_read(struct work_struct *work)
if (port->port.count <= 0)
return;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty) {
dbg("%s - bad tty pointer - exiting", __func__);
return;
@@ -1869,13 +1881,13 @@ static void ftdi_process_read(struct work_struct *work)
priv = usb_get_serial_port_data(port);
if (!priv) {
dbg("%s - bad port private data pointer - exiting", __func__);
- return;
+ goto out;
}
urb = port->read_urb;
if (!urb) {
dbg("%s - bad read_urb pointer - exiting", __func__);
- return;
+ goto out;
}
data = urb->transfer_buffer;
@@ -1920,7 +1932,8 @@ static void ftdi_process_read(struct work_struct *work)
length = min(PKTSZ, urb->actual_length-packet_offset)-2;
if (length < 0) {
- err("%s - bad packet length: %d", __func__, length+2);
+ dev_err(&port->dev, "%s - bad packet length: %d\n",
+ __func__, length+2);
length = 0;
}
@@ -2017,7 +2030,7 @@ static void ftdi_process_read(struct work_struct *work)
schedule_delayed_work(&priv->rx_work, 1);
else
dbg("%s - port is closed", __func__);
- return;
+ goto out;
}
/* urb is completely processed */
@@ -2035,9 +2048,12 @@ static void ftdi_process_read(struct work_struct *work)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
}
+out:
+ tty_kref_put(tty);
} /* ftdi_process_read */
@@ -2063,8 +2079,8 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , priv->interface,
buf, 0, WDR_TIMEOUT) < 0) {
- err("%s FAILED to enable/disable break state (state was %d)",
- __func__, break_state);
+ dev_err(&port->dev, "%s FAILED to enable/disable break state "
+ "(state was %d)\n", __func__, break_state);
}
dbg("%s break state is %d - urb is %d", __func__,
@@ -2136,7 +2152,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
case CS7: urb_value |= 7; dbg("Setting CS7"); break;
case CS8: urb_value |= 8; dbg("Setting CS8"); break;
default:
- err("CSIZE was set but not CS5-CS8");
+ dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n");
}
}
@@ -2149,7 +2165,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , priv->interface,
buf, 0, WDR_SHORT_TIMEOUT) < 0) {
- err("%s FAILED to set databits/stopbits/parity", __func__);
+ dev_err(&port->dev, "%s FAILED to set "
+ "databits/stopbits/parity\n", __func__);
}
/* Now do the baudrate */
@@ -2160,14 +2177,17 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface,
buf, 0, WDR_TIMEOUT) < 0) {
- err("%s error from disable flowcontrol urb", __func__);
+ dev_err(&port->dev,
+ "%s error from disable flowcontrol urb\n",
+ __func__);
}
/* Drop RTS and DTR */
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} else {
/* set the baudrate determined before */
if (change_speed(tty, port))
- err("%s urb failed to set baudrate", __func__);
+ dev_err(&port->dev, "%s urb failed to set baudrate\n",
+ __func__);
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
@@ -2183,7 +2203,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
buf, 0, WDR_TIMEOUT) < 0) {
- err("urb failed to set to rts/cts flow control");
+ dev_err(&port->dev,
+ "urb failed to set to rts/cts flow control\n");
}
} else {
@@ -2214,7 +2235,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
urb_value , (FTDI_SIO_XON_XOFF_HS
| priv->interface),
buf, 0, WDR_TIMEOUT) < 0) {
- err("urb failed to set to xon/xoff flow control");
+ dev_err(&port->dev, "urb failed to set to "
+ "xon/xoff flow control\n");
}
} else {
/* else clause to only run if cflag ! CRTSCTS and iflag
@@ -2227,7 +2249,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface,
buf, 0, WDR_TIMEOUT) < 0) {
- err("urb failed to clear flow control");
+ dev_err(&port->dev,
+ "urb failed to clear flow control\n");
}
}
@@ -2253,7 +2276,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
0, 0,
buf, 1, WDR_TIMEOUT);
if (ret < 0) {
- err("%s Could not get modem status of device - err: %d", __func__,
+ dbg("%s Could not get modem status of device - err: %d", __func__,
ret);
return ret;
}
@@ -2272,7 +2295,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
0, priv->interface,
buf, 2, WDR_TIMEOUT);
if (ret < 0) {
- err("%s Could not get modem status of device - err: %d", __func__,
+ dbg("%s Could not get modem status of device - err: %d", __func__,
ret);
return ret;
}
@@ -2419,7 +2442,8 @@ static int __init ftdi_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&ftdi_sio_device);
@@ -2452,5 +2476,5 @@ module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
__MODULE_STRING(FTDI_VID)")");
module_param(product, ushort, 0);
-MODULE_PARM_DESC(vendor, "User specified product ID");
+MODULE_PARM_DESC(product, "User specified product ID");
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 382265bba96..07a3992abad 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -628,6 +628,11 @@
#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */
/*
+ * Oceanic product ids
+ */
+#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */
+
+/*
* TTi (Thurlby Thandar Instruments)
*/
#define TTI_VID 0x103E /* Vendor Id */
@@ -750,6 +755,7 @@
#define PAPOUCH_VID 0x5050 /* Vendor ID */
#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */
+#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */
/*
* ACG Identification Technologies GmbH products (http://www.acg.de/).
@@ -838,6 +844,10 @@
/* Rig Expert Ukraine devices */
#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */
+/* Domintell products http://www.domintell.com */
+#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */
+#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index d9538208807..8e6a66e38db 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -276,7 +276,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
if (tty && actual_length) {
@@ -287,6 +287,7 @@ static void send_to_tty(struct usb_serial_port *port,
tty_insert_flip_string(tty, data, actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
}
@@ -1584,7 +1585,8 @@ static int __init garmin_init(void)
retval = usb_register(&garmin_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index fe84c88ec20..814909f1ee6 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -330,7 +330,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
{
struct urb *urb = port->read_urb;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
int room;
/* Push data to tty */
@@ -341,6 +341,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
tty_flip_buffer_push(tty);
}
}
+ tty_kref_put(tty);
resubmit_read_urb(port, GFP_ATOMIC);
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index ab905869e95..43132927513 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -63,7 +63,8 @@ static int __init hp49gp_init(void)
retval = usb_register(&hp49gp_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&hp49gp_device);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index bfa508ddb0f..e85c8c0d1ad 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -600,6 +600,7 @@ static void edge_interrupt_callback(struct urb *urb)
struct edgeport_serial *edge_serial = urb->context;
struct edgeport_port *edge_port;
struct usb_serial_port *port;
+ struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int length = urb->actual_length;
int bytes_avail;
@@ -675,9 +676,12 @@ static void edge_interrupt_callback(struct urb *urb)
/* tell the tty driver that something
has changed */
- if (edge_port->port->port.tty)
- tty_wakeup(edge_port->port->port.tty);
-
+ tty = tty_port_tty_get(
+ &edge_port->port->port);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
/* Since we have more credit, check
if more data can be sent */
send_more_port_data(edge_serial,
@@ -778,13 +782,14 @@ static void edge_bulk_out_data_callback(struct urb *urb)
__func__, status);
}
- tty = edge_port->port->port.tty;
+ tty = tty_port_tty_get(&edge_port->port->port);
if (tty && edge_port->open) {
/* let the tty driver wakeup if it has a special
write_wakeup function */
tty_wakeup(tty);
}
+ tty_kref_put(tty);
/* Release the Write URB */
edge_port->write_in_progress = false;
@@ -826,11 +831,12 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
}
/* Get pointer to tty */
- tty = edge_port->port->port.tty;
+ tty = tty_port_tty_get(&edge_port->port->port);
/* tell the tty driver that something has changed */
if (tty && edge_port->open)
tty_wakeup(tty);
+ tty_kref_put(tty);
/* we have completed the command */
edge_port->commandPending = false;
@@ -1932,11 +1938,13 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port->open) {
- tty = edge_port->port->port.tty;
+ tty = tty_port_tty_get(
+ &edge_port->port->port);
if (tty) {
dbg("%s - Sending %d bytes to TTY for port %d",
__func__, rxLen, edge_serial->rxPort);
edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
+ tty_kref_put(tty);
}
edge_port->icount.rx += rxLen;
}
@@ -1971,6 +1979,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
+ struct tty_struct *tty;
__u8 code = edge_serial->rxStatusCode;
/* switch the port pointer to the one being currently talked about */
@@ -2020,10 +2029,12 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
/* send the current line settings to the port so we are
in sync with any further termios calls */
- /* FIXME: locking on tty */
- if (edge_port->port->port.tty)
- change_port_settings(edge_port->port->port.tty,
- edge_port, edge_port->port->port.tty->termios);
+ tty = tty_port_tty_get(&edge_port->port->port);
+ if (tty) {
+ change_port_settings(tty,
+ edge_port, tty->termios);
+ tty_kref_put(tty);
+ }
/* we have completed the open */
edge_port->openPending = false;
@@ -2163,10 +2174,14 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
}
/* Place LSR data byte into Rx buffer */
- if (lsrData && edge_port->port->port.tty)
- edge_tty_recv(&edge_port->port->dev,
- edge_port->port->port.tty, &data, 1);
-
+ if (lsrData) {
+ struct tty_struct *tty =
+ tty_port_tty_get(&edge_port->port->port);
+ if (tty) {
+ edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
+ tty_kref_put(tty);
+ }
+ }
/* update input line counters */
icount = &edge_port->icount;
if (newLsr & LSR_BREAK)
@@ -3094,13 +3109,13 @@ static int edge_startup(struct usb_serial *serial)
edge_serial->interrupt_read_urb =
usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->interrupt_read_urb) {
- err("out of memory");
+ dev_err(&dev->dev, "out of memory\n");
return -ENOMEM;
}
edge_serial->interrupt_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) {
- err("out of memory");
+ dev_err(&dev->dev, "out of memory\n");
usb_free_urb(edge_serial->interrupt_read_urb);
return -ENOMEM;
}
@@ -3131,13 +3146,13 @@ static int edge_startup(struct usb_serial *serial)
edge_serial->read_urb =
usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->read_urb) {
- err("out of memory");
+ dev_err(&dev->dev, "out of memory\n");
return -ENOMEM;
}
edge_serial->bulk_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) {
- err("out of memory");
+ dev_err(&dev->dev, "out of memory\n");
usb_free_urb(edge_serial->read_urb);
return -ENOMEM;
}
@@ -3166,7 +3181,8 @@ static int edge_startup(struct usb_serial *serial)
}
if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
- err("Error - the proper endpoints were not found!");
+ dev_err(&dev->dev, "Error - the proper endpoints "
+ "were not found!\n");
return -ENODEV;
}
@@ -3175,8 +3191,9 @@ static int edge_startup(struct usb_serial *serial)
response = usb_submit_urb(edge_serial->interrupt_read_urb,
GFP_KERNEL);
if (response)
- err("%s - Error %d submitting control urb",
- __func__, response);
+ dev_err(&dev->dev,
+ "%s - Error %d submitting control urb\n",
+ __func__, response);
}
return response;
}
@@ -3238,7 +3255,8 @@ static int __init edgeport_init(void)
if (retval)
goto failed_usb_register;
atomic_set(&CmdUrbs, 0);
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index cb4c54316cf..c3cdd00ddc4 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
int flush)
{
int baud_rate;
- struct tty_struct *tty = port->port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port->port);
wait_queue_t wait;
unsigned long flags;
@@ -599,6 +599,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
if (flush)
edge_buf_clear(port->ep_out_buf);
spin_unlock_irqrestore(&port->ep_lock, flags);
+ tty_kref_put(tty);
/* wait for data to drain from the device */
timeout += jiffies;
@@ -1554,7 +1555,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
/* Save the new modem status */
edge_port->shadow_msr = msr & 0xf0;
- tty = edge_port->port->port.tty;
+ tty = tty_port_tty_get(&edge_port->port->port);
/* handle CTS flow control */
if (tty && C_CRTSCTS(tty)) {
if (msr & EDGEPORT_MSR_CTS) {
@@ -1564,6 +1565,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
tty->hw_stopped = 1;
}
}
+ tty_kref_put(tty);
return;
}
@@ -1574,6 +1576,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
struct async_icount *icount;
__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
LSR_FRM_ERR | LSR_BREAK));
+ struct tty_struct *tty;
dbg("%s - %02x", __func__, new_lsr);
@@ -1587,8 +1590,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
/* Place LSR data byte into Rx buffer */
- if (lsr_data && edge_port->port->port.tty)
- edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
+ if (lsr_data) {
+ tty = tty_port_tty_get(&edge_port->port->port);
+ if (tty) {
+ edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
+ tty_kref_put(tty);
+ }
+ }
/* update input line counters */
icount = &edge_port->icount;
@@ -1749,7 +1757,7 @@ static void edge_bulk_in_callback(struct urb *urb)
++data;
}
- tty = edge_port->port->port.tty;
+ tty = tty_port_tty_get(&edge_port->port->port);
if (tty && urb->actual_length) {
usb_serial_debug_data(debug, &edge_port->port->dev,
__func__, urb->actual_length, data);
@@ -1761,6 +1769,7 @@ static void edge_bulk_in_callback(struct urb *urb)
urb->actual_length);
edge_port->icount.rx += urb->actual_length;
}
+ tty_kref_put(tty);
exit:
/* continue read unless stopped */
@@ -1796,6 +1805,7 @@ static void edge_bulk_out_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status = urb->status;
+ struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
@@ -1818,7 +1828,9 @@ static void edge_bulk_out_callback(struct urb *urb)
}
/* send any buffered data */
- edge_send(port->port.tty);
+ tty = tty_port_tty_get(&port->port);
+ edge_send(tty);
+ tty_kref_put(tty);
}
static int edge_open(struct tty_struct *tty,
@@ -1876,7 +1888,7 @@ static int edge_open(struct tty_struct *tty,
/* set up the port settings */
if (tty)
- edge_set_termios(tty, port, port->port.tty->termios);
+ edge_set_termios(tty, port, tty->termios);
/* open up the port */
@@ -2966,7 +2978,8 @@ static int __init edgeport_init(void)
retval = usb_register(&io_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&edgeport_2port_device);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index cd9a2e138c8..132be74d2b8 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -608,7 +608,7 @@ static int ipaq_open(struct tty_struct *tty,
bytes_out = 0;
priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
if (priv == NULL) {
- err("%s - Out of memory", __func__);
+ dev_err(&port->dev, "%s - Out of memory\n", __func__);
return -ENOMEM;
}
usb_set_serial_port_data(port, priv);
@@ -693,8 +693,7 @@ static int ipaq_open(struct tty_struct *tty,
}
if (!retries && result) {
- err("%s - failed doing control urb, error %d", __func__,
- result);
+ dev_err(&port->dev, "%s - failed doing control urb, error %d\n", __func__, result);
goto error;
}
@@ -707,8 +706,9 @@ static int ipaq_open(struct tty_struct *tty,
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
goto error;
}
@@ -716,7 +716,7 @@ static int ipaq_open(struct tty_struct *tty,
enomem:
result = -ENOMEM;
- err("%s - Out of memory", __func__);
+ dev_err(&port->dev, "%s - Out of memory\n", __func__);
error:
ipaq_destroy_lists(port);
kfree(priv);
@@ -764,13 +764,14 @@ static void ipaq_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
+ tty_kref_put(tty);
/* Continue trying to always read */
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
@@ -780,8 +781,9 @@ static void ipaq_read_bulk_callback(struct urb *urb)
ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
@@ -846,7 +848,8 @@ static int ipaq_write_bulk(struct usb_serial_port *port,
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d",
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
__func__, result);
} else {
spin_unlock_irqrestore(&write_list_lock, flags);
@@ -908,8 +911,9 @@ static void ipaq_write_bulk_callback(struct urb *urb)
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
} else {
priv->active = 0;
spin_unlock_irqrestore(&write_list_lock, flags);
@@ -956,7 +960,7 @@ static int ipaq_startup(struct usb_serial *serial)
{
dbg("%s", __func__);
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
- err("active config #%d != 1 ??",
+ dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
@@ -975,7 +979,6 @@ static int __init ipaq_init(void)
retval = usb_serial_register(&ipaq_device);
if (retval)
goto failed_usb_serial_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
if (vendor) {
ipaq_id_table[0].idVendor = vendor;
ipaq_id_table[0].idProduct = product;
@@ -984,6 +987,8 @@ static int __init ipaq_init(void)
if (retval)
goto failed_usb_register;
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&ipaq_device);
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index a842025b9b5..3ac59a8a980 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -170,12 +170,13 @@ static void ipw_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Continue trying to always read */
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
@@ -484,7 +485,8 @@ static int usb_ipw_init(void)
usb_serial_deregister(&ipw_device);
return retval;
}
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index e59155c6607..b679a556b98 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -465,11 +465,12 @@ static void ir_read_bulk_callback(struct urb *urb)
ir_baud = *data & 0x0f;
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/*
* No break here.
@@ -601,7 +602,8 @@ static int __init ir_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index ddff37fa633..e320972cb22 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -629,13 +629,14 @@ static void read_buf_callback(struct urb *urb)
}
dbg("%s - %i chars to write", __func__, urb->actual_length);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (data == NULL)
dbg("%s - data is NULL !!!", __func__);
if (tty && urb->actual_length && data) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
iuu_led_activity_on(urb);
}
@@ -1184,7 +1185,8 @@ static int __init iuu_init(void)
retval = usb_register(&iuu_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&iuu_device);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 704716f6f6d..9878c0fb385 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -217,7 +217,8 @@ static int __init keyspan_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
@@ -430,7 +431,7 @@ static void usa26_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
@@ -459,6 +460,7 @@ static void usa26_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
@@ -513,6 +515,7 @@ static void usa26_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
+ struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
@@ -553,12 +556,11 @@ static void usa26_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty)
- && old_dcd_state != p_priv->dcd_state) {
- if (old_dcd_state)
- tty_hangup(port->port.tty);
- /* else */
- /* wake_up_interruptible(&p_priv->open_wait); */
+ if (old_dcd_state != p_priv->dcd_state) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -604,11 +606,12 @@ static void usa28_indat_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
- tty = port->port.tty;
- if (urb->actual_length) {
+ tty =tty_port_tty_get(&port->port);
+ if (tty && urb->actual_length) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
@@ -652,6 +655,7 @@ static void usa28_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
+ struct tty_struct *tty;
int old_dcd_state;
int status = urb->status;
@@ -689,12 +693,11 @@ static void usa28_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty)
- && old_dcd_state != p_priv->dcd_state) {
- if (old_dcd_state)
- tty_hangup(port->port.tty);
- /* else */
- /* wake_up_interruptible(&p_priv->open_wait); */
+ if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -785,12 +788,11 @@ static void usa49_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty)
- && old_dcd_state != p_priv->dcd_state) {
- if (old_dcd_state)
- tty_hangup(port->port.tty);
- /* else */
- /* wake_up_interruptible(&p_priv->open_wait); */
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -827,7 +829,7 @@ static void usa49_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
@@ -850,6 +852,7 @@ static void usa49_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
@@ -893,7 +896,7 @@ static void usa49wg_indat_callback(struct urb *urb)
return;
}
port = serial->port[data[i++]];
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
len = data[i++];
/* 0x80 bit is error flag */
@@ -927,6 +930,7 @@ static void usa49wg_indat_callback(struct urb *urb)
}
if (port->port.count)
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
}
@@ -967,8 +971,8 @@ static void usa90_indat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- tty = port->port.tty;
if (urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
/* if current mode is DMA, looks like usa28 format
otherwise looks like usa26 data format */
@@ -1004,6 +1008,7 @@ static void usa90_indat_callback(struct urb *urb)
}
}
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -1025,6 +1030,7 @@ static void usa90_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
+ struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
@@ -1053,12 +1059,11 @@ static void usa90_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty)
- && old_dcd_state != p_priv->dcd_state) {
- if (old_dcd_state)
- tty_hangup(port->port.tty);
- /* else */
- /* wake_up_interruptible(&p_priv->open_wait); */
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -1130,12 +1135,11 @@ static void usa67_instat_callback(struct urb *urb)
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty)
- && old_dcd_state != p_priv->dcd_state) {
- if (old_dcd_state)
- tty_hangup(port->port.tty);
- /* else */
- /* wake_up_interruptible(&p_priv->open_wait); */
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
}
/* Resubmit urb so we continue receiving */
@@ -1332,7 +1336,7 @@ static void keyspan_close(struct tty_struct *tty,
stop_urb(p_priv->out_urbs[i]);
}
}
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
}
/* download the firmware to a pre-renumeration device */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 040040a267d..bf1ae247da6 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -172,8 +172,9 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
struct keyspan_pda_private *priv =
container_of(work, struct keyspan_pda_private, wakeup_work);
struct usb_serial_port *port = priv->port;
-
- tty_wakeup(port->port.tty);
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ tty_wakeup(tty);
+ tty_kref_put(tty);
}
static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -205,7 +206,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
static void keyspan_pda_rx_interrupt(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
unsigned char *data = urb->transfer_buffer;
int retval;
int status = urb->status;
@@ -222,7 +223,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__func__, status);
- return;
+ goto out;
default:
dbg("%s - nonzero urb status received: %d",
__func__, status);
@@ -261,8 +262,11 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&port->dev,
+ "%s - usb_submit_urb failed with result %d",
+ __func__, retval);
+out:
+ tty_kref_put(tty);
}
@@ -738,11 +742,13 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial)
fw_name = "keyspan_pda/xircom_pgs.fw";
#endif
else {
- err("%s: unknown vendor, aborting.", __func__);
+ dev_err(&serial->dev->dev, "%s: unknown vendor, aborting.\n",
+ __func__);
return -ENODEV;
}
if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
- err("failed to load firmware \"%s\"\n", fw_name);
+ dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
+ fw_name);
return -ENOENT;
}
record = (const struct ihex_binrec *)fw->data;
@@ -752,10 +758,10 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial)
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa0);
if (response < 0) {
- err("ezusb_writememory failed for Keyspan PDA "
- "firmware (%d %04X %p %d)",
- response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
+ dev_err(&serial->dev->dev, "ezusb_writememory failed "
+ "for Keyspan PDA firmware (%d %04X %p %d)\n",
+ response, be32_to_cpu(record->addr),
+ record->data, be16_to_cpu(record->len));
break;
}
record = ihex_next_binrec(record);
@@ -870,7 +876,8 @@ static int __init keyspan_pda_init(void)
retval = usb_register(&keyspan_pda_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
#ifdef XIRCOM
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index b84dddc7112..dc36a052766 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -182,12 +182,12 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
sizeof(struct klsi_105_port_settings),
KLSI_TIMEOUT);
if (rc < 0)
- err("Change port settings failed (error = %d)", rc);
- info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
- __func__,
- settings->pktlen,
- settings->baudrate, settings->databits,
- settings->unknown1, settings->unknown2);
+ dev_err(&port->dev,
+ "Change port settings failed (error = %d)\n", rc);
+ dev_info(&port->serial->dev->dev,
+ "%d byte block, baudrate %x, databits %d, u1 %d, u2 %d\n",
+ settings->pktlen, settings->baudrate, settings->databits,
+ settings->unknown1, settings->unknown2);
return rc;
} /* klsi_105_chg_port_settings */
@@ -215,7 +215,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
__u16 status;
- info("%s - sending SIO Poll request", __func__);
+ dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");
rc = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_POLL,
@@ -226,12 +226,13 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
10000
);
if (rc < 0)
- err("Reading line status failed (error = %d)", rc);
+ dev_err(&port->dev, "Reading line status failed (error = %d)\n",
+ rc);
else {
status = get_unaligned_le16(status_buf);
- info("%s - read status %x %x", __func__,
- status_buf[0], status_buf[1]);
+ dev_info(&port->serial->dev->dev, "read status %x %x",
+ status_buf[0], status_buf[1]);
*line_state_p = klsi_105_status2linestate(status);
}
@@ -280,15 +281,16 @@ static int klsi_105_startup(struct usb_serial *serial)
priv->write_urb_pool[j] = urb;
if (urb == NULL) {
- err("No more urbs???");
+ dev_err(&serial->dev->dev, "No more urbs???\n");
goto err_cleanup;
}
urb->transfer_buffer =
kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.",
- __func__);
+ dev_err(&serial->dev->dev,
+ "%s - out of memory for urb buffers.\n",
+ __func__);
goto err_cleanup;
}
}
@@ -409,7 +411,8 @@ static int klsi_105_open(struct tty_struct *tty,
rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (rc) {
- err("%s - failed submitting read urb, error %d", __func__, rc);
+ dev_err(&port->dev, "%s - failed submitting read urb, "
+ "error %d\n", __func__, rc);
retval = rc;
goto exit;
}
@@ -424,7 +427,7 @@ static int klsi_105_open(struct tty_struct *tty,
0,
KLSI_TIMEOUT);
if (rc < 0) {
- err("Enabling read failed (error = %d)", rc);
+ dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
retval = rc;
} else
dbg("%s - enabled reading", __func__);
@@ -464,7 +467,8 @@ static void klsi_105_close(struct tty_struct *tty,
NULL, 0,
KLSI_TIMEOUT);
if (rc < 0)
- err("Disabling read failed (error = %d)", rc);
+ dev_err(&port->dev,
+ "Disabling read failed (error = %d)\n", rc);
}
mutex_unlock(&port->serial->disc_mutex);
@@ -475,8 +479,9 @@ static void klsi_105_close(struct tty_struct *tty,
/* FIXME */
/* wgg - do I need this? I think so. */
usb_kill_urb(port->interrupt_in_urb);
- info("kl5kusb105 port stats: %ld bytes in, %ld bytes out",
- priv->bytes_in, priv->bytes_out);
+ dev_info(&port->serial->dev->dev,
+ "port stats: %ld bytes in, %ld bytes out\n",
+ priv->bytes_in, priv->bytes_out);
} /* klsi_105_close */
@@ -522,7 +527,9 @@ static int klsi_105_write(struct tty_struct *tty,
urb->transfer_buffer =
kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
- err("%s - no more kernel memory...", __func__);
+ dev_err(&port->dev,
+ "%s - no more kernel memory...\n",
+ __func__);
goto exit;
}
}
@@ -549,8 +556,9 @@ static int klsi_105_write(struct tty_struct *tty,
/* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
goto exit;
}
buf += size;
@@ -658,7 +666,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb)
} else {
int bytes_sent = ((__u8 *) data)[0] +
((unsigned int) ((__u8 *) data)[1] << 8);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
/* we should immediately resubmit the URB, before attempting
* to pass the data on to the tty layer. But that needs locking
* against re-entry an then mixed-up data because of
@@ -679,6 +687,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb)
tty_buffer_request_room(tty, bytes_sent);
tty_insert_flip_string(tty, data + 2, bytes_sent);
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
/* again lockless, but debug info only */
priv->bytes_in += bytes_sent;
@@ -693,8 +702,9 @@ static void klsi_105_read_bulk_callback(struct urb *urb)
port);
rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
- err("%s - failed resubmitting read urb, error %d",
- __func__, rc);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, rc);
} /* klsi_105_read_bulk_callback */
@@ -798,7 +808,8 @@ static void klsi_105_set_termios(struct tty_struct *tty,
priv->cfg.databits = kl5kusb105a_dtb_8;
break;
default:
- err("CSIZE was not CS5-CS8, using default of 8");
+ dev_err(&port->dev,
+ "CSIZE was not CS5-CS8, using default of 8\n");
priv->cfg.databits = kl5kusb105a_dtb_8;
break;
}
@@ -885,7 +896,8 @@ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
rc = klsi_105_get_line_state(port, &line_state);
if (rc < 0) {
- err("Reading line control failed (error = %d)", rc);
+ dev_err(&port->dev,
+ "Reading line control failed (error = %d)\n", rc);
/* better return value? EAGAIN? */
return rc;
}
@@ -943,8 +955,9 @@ static void klsi_105_unthrottle(struct tty_struct *tty)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting read urb, error %d", __func__,
- result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
}
@@ -959,7 +972,8 @@ static int __init klsi_105_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&kl5kusb105d_device);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index deba28ec77e..6286baad939 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -383,7 +383,7 @@ static void kobil_read_int_callback(struct urb *urb)
return;
}
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
/* BEGIN DEBUG */
@@ -405,6 +405,7 @@ static void kobil_read_int_callback(struct urb *urb)
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
@@ -743,8 +744,8 @@ static int __init kobil_init(void)
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 0ded8bd6ec8..07710cf31d0 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -246,7 +246,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
WDR_TIMEOUT);
if (rc < 0) /*FIXME: What value speed results */
- err("Set BAUD RATE %d failed (error = %d)", value, rc);
+ dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
+ value, rc);
else
tty_encode_baud_rate(tty, speed, speed);
dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
@@ -274,8 +275,9 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
- MCT_U232_SET_UNKNOWN1_REQUEST, rc);
+ dev_err(&port->dev, "Sending USB device request code %d "
+ "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST,
+ rc);
if (port && C_CRTSCTS(tty))
cts_enable_byte = 1;
@@ -288,8 +290,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
- MCT_U232_SET_CTS_REQUEST, rc);
+ dev_err(&port->dev, "Sending USB device request code %d "
+ "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);
return rc;
} /* mct_u232_set_baud_rate */
@@ -303,7 +305,8 @@ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
+ dev_err(&serial->dev->dev,
+ "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
dbg("set_line_ctrl: 0x%x", lcr);
return rc;
} /* mct_u232_set_line_ctrl */
@@ -325,7 +328,8 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
+ dev_err(&serial->dev->dev,
+ "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
return rc;
@@ -341,7 +345,8 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial,
0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
WDR_TIMEOUT);
if (rc < 0) {
- err("Get MODEM STATus failed (error = %d)", rc);
+ dev_err(&serial->dev->dev,
+ "Get MODEM STATus failed (error = %d)\n", rc);
*msr = 0;
}
dbg("get_modem_stat: 0x%x", *msr);
@@ -470,8 +475,9 @@ static int mct_u232_open(struct tty_struct *tty,
port->read_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (retval) {
- err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
- port->read_urb->pipe, retval);
+ dev_err(&port->dev,
+ "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n",
+ port->read_urb->pipe, retval);
goto error;
}
@@ -479,8 +485,9 @@ static int mct_u232_open(struct tty_struct *tty,
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
usb_kill_urb(port->read_urb);
- err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
- port->interrupt_in_urb->pipe, retval);
+ dev_err(&port->dev,
+ "usb_submit_urb(read int) failed pipe 0x%x err %d",
+ port->interrupt_in_urb->pipe, retval);
goto error;
}
return 0;
@@ -563,10 +570,11 @@ static void mct_u232_read_int_callback(struct urb *urb)
* Work-a-round: handle the 'usual' bulk-in pipe here
*/
if (urb->transfer_buffer_length > 2) {
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
goto exit;
}
@@ -591,7 +599,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & MCT_U232_LSR_ERR) {
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
/* Overrun Error */
if (priv->last_lsr & MCT_U232_LSR_OE) {
}
@@ -604,14 +612,16 @@ static void mct_u232_read_int_callback(struct urb *urb)
/* Break Indicator */
if (priv->last_lsr & MCT_U232_LSR_BI) {
}
+ tty_kref_put(tty);
}
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err("%s - usb_submit_urb failed with result %d",
- __func__, retval);
+ dev_err(&port->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
} /* mct_u232_read_int_callback */
static void mct_u232_set_termios(struct tty_struct *tty,
@@ -678,7 +688,8 @@ static void mct_u232_set_termios(struct tty_struct *tty,
case CS8:
last_lcr |= MCT_U232_DATA_BITS_8; break;
default:
- err("CSIZE was not CS5-CS8, using default of 8");
+ dev_err(&port->dev,
+ "CSIZE was not CS5-CS8, using default of 8\n");
last_lcr |= MCT_U232_DATA_BITS_8;
break;
}
@@ -815,7 +826,8 @@ static int __init mct_u232_init(void)
retval = usb_register(&mct_u232_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&mct_u232_device);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 7c4917d77c0..e772cc0a97f 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -216,12 +216,13 @@ static void mos7720_bulk_in_callback(struct urb *urb)
data = urb->transfer_buffer;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
if (!port->read_urb) {
dbg("URB KILLED !!!");
@@ -262,10 +263,11 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
dbg("Entering .........");
- tty = mos7720_port->port->port.tty;
+ tty = tty_port_tty_get(&mos7720_port->port->port);
if (tty && mos7720_port->open)
tty_wakeup(tty);
+ tty_kref_put(tty);
}
/*
@@ -353,14 +355,16 @@ static int mos7720_open(struct tty_struct *tty,
mos7720_port->write_urb_pool[j] = urb;
if (urb == NULL) {
- err("No more urbs???");
+ dev_err(&port->dev, "No more urbs???\n");
continue;
}
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s-out of memory for urb buffers.", __func__);
+ dev_err(&port->dev,
+ "%s-out of memory for urb buffers.\n",
+ __func__);
usb_free_urb(mos7720_port->write_urb_pool[j]);
mos7720_port->write_urb_pool[j] = NULL;
continue;
@@ -692,7 +696,8 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
- err("%s no more kernel memory...", __func__);
+ dev_err(&port->dev, "%s no more kernel memory...\n",
+ __func__);
goto exit;
}
}
@@ -712,8 +717,8 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - usb_submit_urb(write bulk) failed with status = %d",
- __func__, status);
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ "with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
}
@@ -973,7 +978,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
/* Calculate the Divisor */
status = calc_baud_rate_divisor(baudrate, &divisor);
if (status) {
- err("%s - bad baud rate", __func__);
+ dev_err(&port->dev, "%s - bad baud rate\n", __func__);
return status;
}
@@ -1267,29 +1272,6 @@ static int get_lsr_info(struct tty_struct *tty,
return 0;
}
-/*
- * get_number_bytes_avail - get number of bytes available
- *
- * Purpose: Let user call ioctl to get the count of number of bytes available.
- */
-static int get_number_bytes_avail(struct moschip_port *mos7720_port,
- unsigned int __user *value)
-{
- unsigned int result = 0;
- struct tty_struct *tty = mos7720_port->port->port.tty;
-
- if (!tty)
- return -ENOIOCTLCMD;
-
- result = tty->read_cnt;
-
- dbg("%s(%d) = %d", __func__, mos7720_port->port->number, result);
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
-
- return -ENOIOCTLCMD;
-}
-
static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
unsigned int __user *value)
{
@@ -1409,13 +1391,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCINQ:
- /* return number of bytes available */
- dbg("%s (%d) TIOCINQ", __func__, port->number);
- return get_number_bytes_avail(mos7720_port,
- (unsigned int __user *)arg);
- break;
-
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
return get_lsr_info(tty, mos7720_port,
@@ -1506,7 +1481,7 @@ static int mos7720_startup(struct usb_serial *serial)
/* create our private serial structure */
mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
if (mos7720_serial == NULL) {
- err("%s - Out of memory", __func__);
+ dev_err(&dev->dev, "%s - Out of memory\n", __func__);
return -ENOMEM;
}
@@ -1519,7 +1494,7 @@ static int mos7720_startup(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7720_port == NULL) {
- err("%s - Out of memory", __func__);
+ dev_err(&dev->dev, "%s - Out of memory\n", __func__);
usb_set_serial_data(serial, NULL);
kfree(mos7720_serial);
return -ENOMEM;
@@ -1613,7 +1588,8 @@ static int __init moschip7720_init(void)
if (retval)
goto failed_port_device_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
/* Register with the usb */
retval = usb_register(&usb_driver);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 09d82062b97..fda4a6421c4 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -709,12 +709,13 @@ static void mos7840_bulk_in_callback(struct urb *urb)
dbg("%s", "Entering ........... \n");
if (urb->actual_length) {
- tty = mos7840_port->port->port.tty;
+ tty = tty_port_tty_get(&mos7840_port->port->port);
if (tty) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
dbg(" %s \n", data);
tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
mos7840_port->icount.rx += urb->actual_length;
smp_wmb();
@@ -773,10 +774,10 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
dbg("%s \n", "Entering .........");
- tty = mos7840_port->port->port.tty;
-
+ tty = tty_port_tty_get(&mos7840_port->port->port);
if (tty && mos7840_port->open)
tty_wakeup(tty);
+ tty_kref_put(tty);
}
@@ -843,7 +844,7 @@ static int mos7840_open(struct tty_struct *tty,
mos7840_port->write_urb_pool[j] = urb;
if (urb == NULL) {
- err("No more urbs???");
+ dev_err(&port->dev, "No more urbs???\n");
continue;
}
@@ -852,7 +853,9 @@ static int mos7840_open(struct tty_struct *tty,
if (!urb->transfer_buffer) {
usb_free_urb(urb);
mos7840_port->write_urb_pool[j] = NULL;
- err("%s-out of memory for urb buffers.", __func__);
+ dev_err(&port->dev,
+ "%s-out of memory for urb buffers.\n",
+ __func__);
continue;
}
}
@@ -1020,8 +1023,8 @@ static int mos7840_open(struct tty_struct *tty,
usb_submit_urb(serial->port[0]->interrupt_in_urb,
GFP_KERNEL);
if (response) {
- err("%s - Error %d submitting interrupt urb",
- __func__, response);
+ dev_err(&port->dev, "%s - Error %d submitting "
+ "interrupt urb\n", __func__, response);
}
}
@@ -1054,8 +1057,8 @@ static int mos7840_open(struct tty_struct *tty,
port->bulk_in_endpointAddress);
response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
if (response) {
- err("%s - Error %d submitting control urb", __func__,
- response);
+ dev_err(&port->dev, "%s - Error %d submitting control urb\n",
+ __func__, response);
}
/* initialize our wait queues */
@@ -1491,7 +1494,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
- err("%s no more kernel memory...", __func__);
+ dev_err(&port->dev, "%s no more kernel memory...\n",
+ __func__);
goto exit;
}
}
@@ -1516,8 +1520,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
if (status) {
mos7840_port->busy[i] = 0;
- err("%s - usb_submit_urb(write bulk) failed with status = %d",
- __func__, status);
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ "with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
}
@@ -1855,8 +1859,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
/* Calculate the Divisor */
if (status) {
- err("%s - bad baud rate", __func__);
- dbg("%s\n", "bad baud rate");
+ dev_err(&port->dev, "%s - bad baud rate\n", __func__);
return status;
}
/* Enable access to divisor latch */
@@ -2445,7 +2448,7 @@ static int mos7840_startup(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) {
- err("%s - Out of memory", __func__);
+ dev_err(&dev->dev, "%s - Out of memory\n", __func__);
status = -ENOMEM;
i--; /* don't follow NULL pointer cleaning up */
goto error;
@@ -2742,7 +2745,8 @@ static int __init moschip7840_init(void)
goto failed_port_device_register;
dbg("%s\n", "Entring...");
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
/* Register with the usb */
retval = usb_register(&io_driver);
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index d6736531a0f..bcdcbb82270 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -64,12 +64,13 @@ static void navman_read_int_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index ae8e227f3db..df653971272 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -154,8 +154,8 @@ static int omninet_attach(struct usb_serial *serial)
od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
if (!od) {
- err("%s- kmalloc(%Zd) failed.",
- __func__, sizeof(struct omninet_data));
+ dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
+ __func__, sizeof(struct omninet_data));
return -ENOMEM;
}
usb_set_serial_port_data(port, od);
@@ -172,7 +172,7 @@ static int omninet_open(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
wport = serial->port[1];
- wport->port.tty = tty; /* FIXME */
+ tty_port_tty_set(&wport->port, tty);
/* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev,
@@ -183,8 +183,9 @@ static int omninet_open(struct tty_struct *tty,
omninet_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
return result;
}
@@ -229,9 +230,11 @@ static void omninet_read_bulk_callback(struct urb *urb)
}
if (urb->actual_length && header->oh_len) {
- tty_insert_flip_string(port->port.tty,
- data + OMNINET_DATAOFFSET, header->oh_len);
- tty_flip_buffer_push(port->port.tty);
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET,
+ header->oh_len);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
}
/* Continue trying to always read */
@@ -242,8 +245,9 @@ static void omninet_read_bulk_callback(struct urb *urb)
omninet_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
@@ -296,8 +300,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
wport->write_urb_busy = 0;
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
} else
result = count;
@@ -362,7 +367,8 @@ static int __init omninet_init(void)
retval = usb_register(&omninet_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&zyxel_omninet_device);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 9f9cd36455f..3d87eabcd92 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -79,27 +79,16 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define OPTION_PRODUCT_VIPER 0x6600
#define OPTION_PRODUCT_VIPER_BUS 0x6601
#define OPTION_PRODUCT_GT_MAX_READY 0x6701
-#define OPTION_PRODUCT_GT_MAX 0x6711
#define OPTION_PRODUCT_FUJI_MODEM_LIGHT 0x6721
#define OPTION_PRODUCT_FUJI_MODEM_GT 0x6741
#define OPTION_PRODUCT_FUJI_MODEM_EX 0x6761
-#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT 0x6731
-#define OPTION_PRODUCT_FUJI_NETWORK_GT 0x6751
-#define OPTION_PRODUCT_FUJI_NETWORK_EX 0x6771
#define OPTION_PRODUCT_KOI_MODEM 0x6800
-#define OPTION_PRODUCT_KOI_NETWORK 0x6811
#define OPTION_PRODUCT_SCORPION_MODEM 0x6901
-#define OPTION_PRODUCT_SCORPION_NETWORK 0x6911
#define OPTION_PRODUCT_ETNA_MODEM 0x7001
-#define OPTION_PRODUCT_ETNA_NETWORK 0x7011
#define OPTION_PRODUCT_ETNA_MODEM_LITE 0x7021
#define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041
#define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061
-#define OPTION_PRODUCT_ETNA_NETWORK_LITE 0x7031
-#define OPTION_PRODUCT_ETNA_NETWORK_GT 0x7051
-#define OPTION_PRODUCT_ETNA_NETWORK_EX 0x7071
#define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100
-#define OPTION_PRODUCT_ETNA_KOI_NETWORK 0x7111
#define HUAWEI_VENDOR_ID 0x12D1
#define HUAWEI_PRODUCT_E600 0x1001
@@ -218,6 +207,17 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
#define ZTE_PRODUCT_MF628 0x0015
+#define ZTE_PRODUCT_CDMA_TECH 0xfffe
+
+/* Ericsson products */
+#define ERICSSON_VENDOR_ID 0x0bdb
+#define ERICSSON_PRODUCT_F3507G 0x1900
+
+/* Pantech products */
+#define PANTECH_VENDOR_ID 0x106c
+#define PANTECH_PRODUCT_PC5740 0x3701
+#define PANTECH_PRODUCT_PC5750 0x3702 /* PX-500 */
+#define PANTECH_PRODUCT_UM150 0x3711
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -234,27 +234,16 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
- { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
@@ -317,7 +306,8 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
- { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
+ { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */
+ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
@@ -347,6 +337,11 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
+ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
+ { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
+ { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_PC5740) },
+ { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_PC5750) },
+ { USB_DEVICE(PANTECH_VENDOR_ID, PANTECH_PRODUCT_UM150) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -425,7 +420,8 @@ static int __init option_init(void)
if (retval)
goto failed_driver_register;
- info(DRIVER_DESC ": " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
@@ -569,14 +565,14 @@ static void option_indat_callback(struct urb *urb)
dbg("%s: nonzero status: %d on endpoint %02x.",
__func__, status, endpoint);
} else {
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
- } else {
+ } else
dbg("%s: empty read urb received", __func__);
- }
+ tty_kref_put(tty);
/* Resubmit urb so we continue receiving */
if (port->port.count && status != -ESHUTDOWN) {
@@ -645,9 +641,13 @@ static void option_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty) &&
- old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->port.tty);
+ if (old_dcd_state && !portdata->dcd_state) {
+ struct tty_struct *tty =
+ tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
} else {
dbg("%s: type %x req %x", __func__,
req_pkt->bRequestType, req_pkt->bRequest);
@@ -791,7 +791,7 @@ static void option_close(struct tty_struct *tty,
for (i = 0; i < N_OUT_URB; i++)
usb_kill_urb(portdata->out_urbs[i]);
}
- port->port.tty = NULL; /* FIXME */
+ tty_port_tty_set(&port->port, NULL);
}
/* Helper functions used by option_setup_urbs */
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 81db5715ee2..ba551f00f16 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -224,10 +224,6 @@ struct oti6858_private {
struct usb_serial_port *port; /* USB port with which associated */
};
-#undef dbg
-/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */
-#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg)
-
static void setup_line(struct work_struct *work)
{
struct oti6858_private *priv = container_of(work,
@@ -1002,11 +998,12 @@ static void oti6858_read_bulk_callback(struct urb *urb)
return;
}
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty != NULL && urb->actual_length > 0) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* schedule the interrupt urb if we are still open */
if (port->port.count != 0) {
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 1ede1441cb1..491c8857b64 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -154,7 +154,6 @@ struct pl2303_private {
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
- u8 termios_initialized;
enum pl2303_type type;
};
@@ -526,16 +525,6 @@ static void pl2303_set_termios(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
- priv->termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
/* The PL2303 is reported to lose bytes if you change
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
@@ -1057,7 +1046,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __func__, tty_flag);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -1067,7 +1056,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_insert_flip_char(tty, data[i], tty_flag);
tty_flip_buffer_push(tty);
}
-
+ tty_kref_put(tty);
/* Schedule the next read _if_ we are still open */
if (port->port.count) {
urb->dev = port->serial->dev;
@@ -1158,7 +1147,7 @@ static int __init pl2303_init(void)
retval = usb_register(&pl2303_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&pl2303_device);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index def52d07a4e..4b463cd140e 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -217,6 +217,7 @@ static void safe_read_bulk_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
unsigned char length = urb->actual_length;
+ struct tty_struct *tty;
int result;
int status = urb->status;
@@ -242,28 +243,31 @@ static void safe_read_bulk_callback(struct urb *urb)
printk("\n");
}
#endif
+ tty = tty_port_tty_get(&port->port);
if (safe) {
__u16 fcs;
fcs = fcs_compute10(data, length, CRC10_INITFCS);
if (!fcs) {
int actual_length = data[length - 2] >> 2;
if (actual_length <= (length - 2)) {
- info("%s - actual: %d", __func__,
- actual_length);
- tty_insert_flip_string(port->port.tty,
+ dev_info(&urb->dev->dev, "%s - actual: %d\n",
+ __func__, actual_length);
+ tty_insert_flip_string(tty,
data, actual_length);
- tty_flip_buffer_push(port->port.tty);
+ tty_flip_buffer_push(tty);
} else {
- err("%s - inconsistent lengths %d:%d",
+ dev_err(&port->dev,
+ "%s - inconsistent lengths %d:%d\n",
__func__, actual_length, length);
}
} else {
- err("%s - bad CRC %x", __func__, fcs);
+ dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
}
} else {
- tty_insert_flip_string(port->port.tty, data, length);
- tty_flip_buffer_push(port->port.tty);
+ tty_insert_flip_string(tty, data, length);
+ tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Continue trying to always read */
usb_fill_bulk_urb(urb, port->serial->dev,
@@ -274,8 +278,9 @@ static void safe_read_bulk_callback(struct urb *urb)
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
/* FIXME: Need a mechanism to retry later if this happens */
}
@@ -366,8 +371,9 @@ static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
if (result) {
port->write_urb_busy = 0;
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
return 0;
}
dbg("%s urb: %p submitted", __func__, port->write_urb);
@@ -425,14 +431,13 @@ static int __init safe_init(void)
{
int i, retval;
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
- info("vendor: %x product: %x safe: %d padded: %d\n",
- vendor, product, safe, padded);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
/* if we have vendor / product parameters patch them into id list */
if (vendor || product) {
- info("vendor: %x product: %x\n", vendor, product);
+ printk(KERN_INFO KBUILD_MODNAME ": vendor: %x product: %x\n",
+ vendor, product);
for (i = 0; i < ARRAY_SIZE(id_table); i++) {
if (!id_table[i].idVendor && !id_table[i].idProduct) {
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 706033753ad..0f2b67244af 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -14,7 +14,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/
-#define DRIVER_VERSION "v.1.2.13a"
+#define DRIVER_VERSION "v.1.3.2"
#define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -30,9 +30,6 @@
#define SWIMS_USB_REQUEST_SetPower 0x00
#define SWIMS_USB_REQUEST_SetNmea 0x07
-#define SWIMS_USB_REQUEST_SetMode 0x0B
-#define SWIMS_USB_REQUEST_GetSwocInfo 0x0A
-#define SWIMS_SET_MODE_Modem 0x0001
/* per port private data */
#define N_IN_URB 4
@@ -163,7 +160,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
- { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
{ USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
{ USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
@@ -175,6 +172,8 @@ static struct usb_device_id id_table [] = {
/* Sierra Wireless Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
{ USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
+ { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */
+ { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
{ USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
@@ -187,6 +186,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
{ USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
{ USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
+ { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */
{ USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
{ USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */
{ USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */
@@ -204,6 +204,8 @@ static struct usb_device_id id_table [] = {
/* Sierra Wireless Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
/* Sierra Wireless Device */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
+ /* Sierra Wireless Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
@@ -245,7 +247,7 @@ static int sierra_send_setup(struct tty_struct *tty,
struct sierra_port_private *portdata;
__u16 interface = 0;
- dbg("%s", __func__);
+ dev_dbg(&port->dev, "%s", __func__);
portdata = usb_get_serial_port_data(port);
@@ -282,7 +284,7 @@ static int sierra_send_setup(struct tty_struct *tty,
static void sierra_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
- dbg("%s", __func__);
+ dev_dbg(&port->dev, "%s", __func__);
tty_termios_copy_hw(tty->termios, old_termios);
sierra_send_setup(tty, port);
}
@@ -293,6 +295,7 @@ static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int value;
struct sierra_port_private *portdata;
+ dev_dbg(&port->dev, "%s", __func__);
portdata = usb_get_serial_port_data(port);
value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
@@ -332,14 +335,14 @@ static void sierra_outdat_callback(struct urb *urb)
int status = urb->status;
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(&port->dev, "%s - port %d", __func__, port->number);
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree(urb->transfer_buffer);
if (status)
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
+ dev_dbg(&port->dev, "%s - nonzero write bulk status "
+ "received: %d", __func__, status);
spin_lock_irqsave(&portdata->lock, flags);
--portdata->outstanding_urbs;
@@ -361,12 +364,12 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
portdata = usb_get_serial_port_data(port);
- dbg("%s: write (%d chars)", __func__, count);
+ dev_dbg(&port->dev, "%s: write (%d chars)", __func__, count);
spin_lock_irqsave(&portdata->lock, flags);
if (portdata->outstanding_urbs > N_OUT_URB) {
spin_unlock_irqrestore(&portdata->lock, flags);
- dbg("%s - write limit hit\n", __func__);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
return 0;
}
portdata->outstanding_urbs++;
@@ -435,17 +438,18 @@ static void sierra_indat_callback(struct urb *urb)
port = urb->context;
if (status) {
- dbg("%s: nonzero status: %d on endpoint %02x.",
- __func__, status, endpoint);
+ dev_dbg(&port->dev, "%s: nonzero status: %d on"
+ " endpoint %02x.", __func__, status, endpoint);
} else {
- tty = port->port.tty;
if (urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
- } else {
- dbg("%s: empty read urb received", __func__);
- }
+ tty_kref_put(tty);
+ } else
+ dev_dbg(&port->dev, "%s: empty read urb"
+ " received", __func__);
/* Resubmit urb so we continue receiving */
if (port->port.count && status != -ESHUTDOWN) {
@@ -466,15 +470,17 @@ static void sierra_instat_callback(struct urb *urb)
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
- dbg("%s", __func__);
- dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
+ dev_dbg(&port->dev, "%s", __func__);
+ dev_dbg(&port->dev, "%s: urb %p port %p has data %p", __func__,
+ urb, port, portdata);
if (status == 0) {
struct usb_ctrlrequest *req_pkt =
(struct usb_ctrlrequest *)urb->transfer_buffer;
if (!req_pkt) {
- dbg("%s: NULL req_pkt\n", __func__);
+ dev_dbg(&port->dev, "%s: NULL req_pkt\n",
+ __func__);
return;
}
if ((req_pkt->bRequestType == 0xA1) &&
@@ -483,8 +489,10 @@ static void sierra_instat_callback(struct urb *urb)
unsigned char signals = *((unsigned char *)
urb->transfer_buffer +
sizeof(struct usb_ctrlrequest));
+ struct tty_struct *tty;
- dbg("%s: signal x%x", __func__, signals);
+ dev_dbg(&port->dev, "%s: signal x%x", __func__,
+ signals);
old_dcd_state = portdata->dcd_state;
portdata->cts_state = 1;
@@ -492,23 +500,26 @@ static void sierra_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->port.tty && !C_CLOCAL(port->port.tty) &&
+ tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty) &&
old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->port.tty);
+ tty_hangup(tty);
+ tty_kref_put(tty);
} else {
- dbg("%s: type %x req %x", __func__,
- req_pkt->bRequestType, req_pkt->bRequest);
+ dev_dbg(&port->dev, "%s: type %x req %x",
+ __func__, req_pkt->bRequestType,
+ req_pkt->bRequest);
}
} else
- dbg("%s: error %d", __func__, status);
+ dev_dbg(&port->dev, "%s: error %d", __func__, status);
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN) {
urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- dbg("%s: resubmit intr urb failed. (%d)",
- __func__, err);
+ dev_dbg(&port->dev, "%s: resubmit intr urb "
+ "failed. (%d)", __func__, err);
}
}
@@ -518,14 +529,14 @@ static int sierra_write_room(struct tty_struct *tty)
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
unsigned long flags;
- dbg("%s - port %d", __func__, port->number);
+ dev_dbg(&port->dev, "%s - port %d", __func__, port->number);
/* try to give a good number back based on if we have any free urbs at
* this point in time */
spin_lock_irqsave(&portdata->lock, flags);
if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
spin_unlock_irqrestore(&portdata->lock, flags);
- dbg("%s - write limit hit\n", __func__);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
return 0;
}
spin_unlock_irqrestore(&portdata->lock, flags);
@@ -544,7 +555,7 @@ static int sierra_open(struct tty_struct *tty,
portdata = usb_get_serial_port_data(port);
- dbg("%s", __func__);
+ dev_dbg(&port->dev, "%s", __func__);
/* Set some sane defaults */
portdata->rts_state = 1;
@@ -556,8 +567,8 @@ static int sierra_open(struct tty_struct *tty,
if (!urb)
continue;
if (urb->dev != serial->dev) {
- dbg("%s: dev %p != %p", __func__,
- urb->dev, serial->dev);
+ dev_dbg(&port->dev, "%s: dev %p != %p",
+ __func__, urb->dev, serial->dev);
continue;
}
@@ -596,7 +607,7 @@ static void sierra_close(struct tty_struct *tty,
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
- dbg("%s", __func__);
+ dev_dbg(&port->dev, "%s", __func__);
portdata = usb_get_serial_port_data(port);
portdata->rts_state = 0;
@@ -614,8 +625,7 @@ static void sierra_close(struct tty_struct *tty,
}
usb_kill_urb(port->interrupt_in_urb);
-
- port->port.tty = NULL; /* FIXME */
+ tty_port_tty_set(&port->port, NULL);
}
static int sierra_startup(struct usb_serial *serial)
@@ -626,7 +636,7 @@ static int sierra_startup(struct usb_serial *serial)
int i;
int j;
- dbg("%s", __func__);
+ dev_dbg(&serial->dev->dev, "%s", __func__);
/* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
@@ -640,8 +650,9 @@ static int sierra_startup(struct usb_serial *serial)
port = serial->port[i];
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
- dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
- __func__, i);
+ dev_dbg(&port->dev, "%s: kmalloc for "
+ "sierra_port_private (%d) failed!.",
+ __func__, i);
return -ENOMEM;
}
spin_lock_init(&portdata->lock);
@@ -661,8 +672,8 @@ static int sierra_startup(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; ++j) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (urb == NULL) {
- dbg("%s: alloc for in port failed.",
- __func__);
+ dev_dbg(&port->dev, "%s: alloc for in "
+ "port failed.", __func__);
continue;
}
/* Fill URB using supplied data. */
@@ -684,7 +695,7 @@ static void sierra_shutdown(struct usb_serial *serial)
struct usb_serial_port *port;
struct sierra_port_private *portdata;
- dbg("%s", __func__);
+ dev_dbg(&serial->dev->dev, "%s", __func__);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
@@ -739,7 +750,8 @@ static int __init sierra_init(void)
if (retval)
goto failed_driver_register;
- info(DRIVER_DESC ": " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 283cf6b36b2..a65bc2bd8e7 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -589,8 +589,8 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
case 1000000:
buf[0] = 0x0b; break;
default:
- err("spcp825 driver does not support the baudrate "
- "requested, using default of 9600.");
+ dev_err(&port->dev, "spcp825 driver does not support the "
+ "baudrate requested, using default of 9600.\n");
}
/* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
@@ -629,7 +629,8 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
SET_UART_FORMAT_TYPE, SET_UART_FORMAT,
uartdata, 0, NULL, 0, 100);
if (i < 0)
- err("Set UART format %#x failed (error = %d)", uartdata, i);
+ dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n",
+ uartdata, i);
dbg("0x21:0x40:0:0 %d\n", i);
if (cflag & CRTSCTS) {
@@ -755,7 +756,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -765,6 +766,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
tty_insert_flip_char(tty, data[i], tty_flag);
tty_flip_buffer_push(tty);
}
+ tty_kref_put(tty);
/* Schedule the next read _if_ we are still open */
if (port->port.count) {
@@ -1053,7 +1055,8 @@ static int __init spcp8x5_init(void)
retval = usb_register(&spcp8x5_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&spcp8x5_device);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index e39c779e416..31c42d1cae1 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -85,7 +85,6 @@
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <linux/firmware.h>
#include "ti_usb_3410_5052.h"
@@ -179,7 +178,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
static int ti_get_lsr(struct ti_port *tport);
static int ti_get_serial_info(struct ti_port *tport,
struct serial_struct __user *ret_arg);
-static int ti_set_serial_info(struct ti_port *tport,
+static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg);
static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
@@ -383,7 +382,8 @@ static int __init ti_init(void)
if (ret)
goto failed_usb;
- info(TI_DRIVER_DESC " " TI_DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
+ TI_DRIVER_DESC "\n");
return 0;
@@ -857,8 +857,8 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file,
(struct serial_struct __user *)arg);
case TIOCSSERIAL:
dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
- return ti_set_serial_info(tport,
- (struct serial_struct __user *)arg);
+ return ti_set_serial_info(tty, tport,
+ (struct serial_struct __user *)arg);
case TIOCMIWAIT:
dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
cprev = tport->tp_icount;
@@ -1211,6 +1211,7 @@ static void ti_bulk_in_callback(struct urb *urb)
struct device *dev = &urb->dev->dev;
int status = urb->status;
int retval = 0;
+ struct tty_struct *tty;
dbg("%s", __func__);
@@ -1239,20 +1240,22 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
}
- if (port->port.tty && urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty && urb->actual_length) {
usb_serial_debug_data(debug, dev, __func__,
urb->actual_length, urb->transfer_buffer);
if (!tport->tp_is_open)
dbg("%s - port closed, dropping data", __func__);
else
- ti_recv(&urb->dev->dev, port->port.tty,
+ ti_recv(&urb->dev->dev, tty,
urb->transfer_buffer,
urb->actual_length);
spin_lock(&tport->tp_lock);
tport->tp_icount.rx += urb->actual_length;
spin_unlock(&tport->tp_lock);
+ tty_kref_put(tty);
}
exit:
@@ -1330,7 +1333,7 @@ static void ti_send(struct ti_port *tport)
{
int count, result;
struct usb_serial_port *port = tport->tp_port;
- struct tty_struct *tty = port->port.tty; /* FIXME */
+ struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
unsigned long flags;
@@ -1338,19 +1341,15 @@ static void ti_send(struct ti_port *tport)
spin_lock_irqsave(&tport->tp_lock, flags);
- if (tport->tp_write_urb_in_use) {
- spin_unlock_irqrestore(&tport->tp_lock, flags);
- return;
- }
+ if (tport->tp_write_urb_in_use)
+ goto unlock;
count = ti_buf_get(tport->tp_write_buf,
port->write_urb->transfer_buffer,
port->bulk_out_size);
- if (count == 0) {
- spin_unlock_irqrestore(&tport->tp_lock, flags);
- return;
- }
+ if (count == 0)
+ goto unlock;
tport->tp_write_urb_in_use = 1;
@@ -1380,7 +1379,13 @@ static void ti_send(struct ti_port *tport)
/* more room in the buffer for new writes, wakeup */
if (tty)
tty_wakeup(tty);
+ tty_kref_put(tty);
wake_up_interruptible(&tport->tp_write_wait);
+ return;
+unlock:
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ tty_kref_put(tty);
+ return;
}
@@ -1464,20 +1469,16 @@ static int ti_get_serial_info(struct ti_port *tport,
}
-static int ti_set_serial_info(struct ti_port *tport,
+static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg)
{
- struct usb_serial_port *port = tport->tp_port;
struct serial_struct new_serial;
if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
return -EFAULT;
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- /* FIXME */
- if (port->port.tty)
- port->port.tty->low_latency =
- (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
tport->tp_closing_wait = new_serial.closing_wait;
return 0;
@@ -1510,7 +1511,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
tport->tp_msr = msr & TI_MSR_MASK;
/* handle CTS flow control */
- tty = tport->tp_port->port.tty;
+ tty = tty_port_tty_get(&tport->tp_port->port);
if (tty && C_CRTSCTS(tty)) {
if (msr & TI_MSR_CTS) {
tty->hw_stopped = 0;
@@ -1519,6 +1520,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
tty->hw_stopped = 1;
}
}
+ tty_kref_put(tty);
}
@@ -1744,7 +1746,7 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
if (buffer) {
memcpy(buffer, fw_p->data, fw_p->size);
memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
- ti_do_download(dev, pipe, buffer, fw_p->size);
+ status = ti_do_download(dev, pipe, buffer, fw_p->size);
kfree(buffer);
}
release_firmware(fw_p);
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index b157c48e8b7..8be3f39891c 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -214,7 +214,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
/* set up our port structure making the tty driver
* remember our port object, and us it */
tty->driver_data = port;
- port->port.tty = tty;
+ tty_port_tty_set(&port->port, tty);
if (port->port.count == 1) {
@@ -246,7 +246,7 @@ bailout_module_put:
bailout_mutex_unlock:
port->port.count = 0;
tty->driver_data = NULL;
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->mutex);
bailout_kref_put:
usb_serial_put(serial);
@@ -276,10 +276,11 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
port->serial->type->close(tty, port, filp);
if (port->port.count == (port->console? 1 : 0)) {
- if (port->port.tty) {
- if (port->port.tty->driver_data)
- port->port.tty->driver_data = NULL;
- port->port.tty = NULL;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ if (tty->driver_data)
+ tty->driver_data = NULL;
+ tty_port_tty_set(&port->port, NULL);
}
}
@@ -508,11 +509,12 @@ static void usb_serial_port_work(struct work_struct *work)
if (!port)
return;
- tty = port->port.tty;
+ tty = tty_port_tty_get(&port->port);
if (!tty)
return;
tty_wakeup(tty);
+ tty_kref_put(tty);
}
static void port_release(struct device *dev)
@@ -733,7 +735,9 @@ int usb_serial_probe(struct usb_interface *interface,
((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
- (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
+ (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
+ ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
+ (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
if (interface != dev->actconfig->interface[0]) {
/* check out the endpoints of the other interface*/
iface_desc = dev->actconfig->interface[0]->cur_altsetting;
@@ -817,6 +821,7 @@ int usb_serial_probe(struct usb_interface *interface,
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port)
goto probe_error;
+ tty_port_init(&port->port);
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
@@ -1038,8 +1043,11 @@ void usb_serial_disconnect(struct usb_interface *interface)
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port) {
- if (port->port.tty)
- tty_hangup(port->port.tty);
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
kill_traffic(port);
}
}
@@ -1113,7 +1121,8 @@ static int __init usb_serial_init(void)
result = bus_register(&usb_serial_bus_type);
if (result) {
- err("%s - registering bus driver failed", __func__);
+ printk(KERN_ERR "usb-serial: %s - registering bus driver "
+ "failed\n", __func__);
goto exit_bus;
}
@@ -1134,25 +1143,28 @@ static int __init usb_serial_init(void)
tty_set_operations(usb_serial_tty_driver, &serial_ops);
result = tty_register_driver(usb_serial_tty_driver);
if (result) {
- err("%s - tty_register_driver failed", __func__);
+ printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
+ __func__);
goto exit_reg_driver;
}
/* register the USB driver */
result = usb_register(&usb_serial_driver);
if (result < 0) {
- err("%s - usb_register failed", __func__);
+ printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
+ __func__);
goto exit_tty;
}
/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if (result < 0) {
- err("%s - registering generic driver failed", __func__);
+ printk(KERN_ERR "usb-serial: %s - registering generic "
+ "driver failed\n", __func__);
goto exit_generic;
}
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return result;
@@ -1166,7 +1178,8 @@ exit_reg_driver:
bus_unregister(&usb_serial_bus_type);
exit_bus:
- err("%s - returning with error %d", __func__, result);
+ printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
+ __func__, result);
put_tty_driver(usb_serial_tty_driver);
return result;
}
@@ -1225,11 +1238,11 @@ int usb_serial_register(struct usb_serial_driver *driver)
retval = usb_serial_bus_register(driver);
if (retval) {
- err("problem %d when registering driver %s",
- retval, driver->description);
+ printk(KERN_ERR "usb-serial: problem %d when registering "
+ "driver %s\n", retval, driver->description);
list_del(&driver->driver_list);
} else
- info("USB Serial support registered for %s",
+ printk(KERN_INFO "USB Serial support registered for %s\n",
driver->description);
return retval;
@@ -1240,7 +1253,8 @@ EXPORT_SYMBOL_GPL(usb_serial_register);
void usb_serial_deregister(struct usb_serial_driver *device)
{
/* must be called with BKL held */
- info("USB Serial deregistering driver %s", device->description);
+ printk(KERN_INFO "USB Serial deregistering driver %s\n",
+ device->description);
list_del(&device->driver_list);
usb_serial_bus_deregister(device);
}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index cf8924f9a2c..4facce3d936 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -499,7 +499,7 @@ static void visor_read_bulk_callback(struct urb *urb)
int status = urb->status;
struct tty_struct *tty;
int result;
- int available_room;
+ int available_room = 0;
dbg("%s - port %d", __func__, port->number);
@@ -512,13 +512,17 @@ static void visor_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->port.tty;
- if (tty && urb->actual_length) {
- available_room = tty_buffer_request_room(tty,
+ if (urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ available_room = tty_buffer_request_room(tty,
urb->actual_length);
- if (available_room) {
- tty_insert_flip_string(tty, data, available_room);
- tty_flip_buffer_push(tty);
+ if (available_room) {
+ tty_insert_flip_string(tty, data,
+ available_room);
+ tty_flip_buffer_push(tty);
+ }
+ tty_kref_put(tty);
}
spin_lock(&priv->lock);
priv->bytes_in += available_room;
@@ -764,7 +768,7 @@ static int visor_probe(struct usb_serial *serial,
dbg("%s", __func__);
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
- err("active config #%d != 1 ??",
+ dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
@@ -967,11 +971,14 @@ static int __init visor_init(void)
break;
}
}
- info(
- "Untested USB device specified at time of module insertion");
- info("Warning: This is not guaranteed to work");
- info("Using a newer kernel is preferred to this method");
- info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x",
+ printk(KERN_INFO KBUILD_MODNAME
+ ": Untested USB device specified at time of module insertion\n");
+ printk(KERN_INFO KBUILD_MODNAME
+ ": Warning: This is not guaranteed to work\n");
+ printk(KERN_INFO KBUILD_MODNAME
+ ": Using a newer kernel is preferred to this method\n");
+ printk(KERN_INFO KBUILD_MODNAME
+ ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
vendor, product);
}
retval = usb_serial_register(&handspring_device);
@@ -986,7 +993,7 @@ static int __init visor_init(void)
retval = usb_register(&visor_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 3a9d14384a4..5335d3211c0 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -303,12 +303,15 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
if (request_ihex_firmware(&firmware_fw, "whiteheat.fw",
&serial->dev->dev)) {
- err("%s - request \"whiteheat.fw\" failed", __func__);
+ dev_err(&serial->dev->dev,
+ "%s - request \"whiteheat.fw\" failed\n", __func__);
goto out;
}
if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw",
&serial->dev->dev)) {
- err("%s - request \"whiteheat_loader.fw\" failed", __func__);
+ dev_err(&serial->dev->dev,
+ "%s - request \"whiteheat_loader.fw\" failed\n",
+ __func__);
goto out;
}
ret = 0;
@@ -320,9 +323,10 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa0);
if (response < 0) {
- err("%s - ezusb_writememory failed for loader (%d %04X %p %d)",
- __func__, response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
+ dev_err(&serial->dev->dev, "%s - ezusb_writememory "
+ "failed for loader (%d %04X %p %d)\n",
+ __func__, response, be32_to_cpu(record->addr),
+ record->data, be16_to_cpu(record->len));
break;
}
record = ihex_next_binrec(record);
@@ -338,9 +342,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa3);
if (response < 0) {
- err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)",
- __func__, response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
+ dev_err(&serial->dev->dev, "%s - ezusb_writememory "
+ "failed for first firmware step "
+ "(%d %04X %p %d)\n", __func__, response,
+ be32_to_cpu(record->addr), record->data,
+ be16_to_cpu(record->len));
break;
}
++record;
@@ -354,9 +360,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa0);
if (response < 0) {
- err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)",
- __func__, response, be32_to_cpu(record->addr),
- record->data, be16_to_cpu(record->len));
+ dev_err(&serial->dev->dev, "%s - ezusb_writememory "
+ "failed for second firmware step "
+ "(%d %04X %p %d)\n", __func__, response,
+ be32_to_cpu(record->addr), record->data,
+ be16_to_cpu(record->len));
break;
}
++record;
@@ -421,12 +429,12 @@ static int whiteheat_attach(struct usb_serial *serial)
ret = usb_bulk_msg(serial->dev, pipe, command, 2,
&alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't send command [%d]",
- serial->type->description, ret);
+ dev_err(&serial->dev->dev, "%s: Couldn't send command [%d]\n",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != 2) {
- err("%s: Send command incomplete [%d]",
- serial->type->description, alen);
+ dev_err(&serial->dev->dev, "%s: Send command incomplete [%d]\n",
+ serial->type->description, alen);
goto no_firmware;
}
@@ -437,31 +445,33 @@ static int whiteheat_attach(struct usb_serial *serial)
ret = usb_bulk_msg(serial->dev, pipe, result,
sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't get results [%d]",
- serial->type->description, ret);
+ dev_err(&serial->dev->dev, "%s: Couldn't get results [%d]\n",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != sizeof(*hw_info) + 1) {
- err("%s: Get results incomplete [%d]",
- serial->type->description, alen);
+ dev_err(&serial->dev->dev, "%s: Get results incomplete [%d]\n",
+ serial->type->description, alen);
goto no_firmware;
} else if (result[0] != command[0]) {
- err("%s: Command failed [%d]",
- serial->type->description, result[0]);
+ dev_err(&serial->dev->dev, "%s: Command failed [%d]\n",
+ serial->type->description, result[0]);
goto no_firmware;
}
hw_info = (struct whiteheat_hw_info *)&result[1];
- info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
- DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
+ dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n",
+ serial->type->description, DRIVER_VERSION,
+ hw_info->sw_major_rev, hw_info->sw_minor_rev);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
- err("%s: Out of memory for port structures\n",
- serial->type->description);
+ dev_err(&port->dev,
+ "%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_private;
}
@@ -481,18 +491,20 @@ static int whiteheat_attach(struct usb_serial *serial)
for (j = 0; j < urb_pool_size; j++) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- err("No free urbs available");
+ dev_err(&port->dev, "No free urbs available\n");
goto no_rx_urb;
}
buf_size = port->read_urb->transfer_buffer_length;
urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("Couldn't allocate urb buffer");
+ dev_err(&port->dev,
+ "Couldn't allocate urb buffer\n");
goto no_rx_buf;
}
wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
if (!wrap) {
- err("Couldn't allocate urb wrapper");
+ dev_err(&port->dev,
+ "Couldn't allocate urb wrapper\n");
goto no_rx_wrap;
}
usb_fill_bulk_urb(urb, serial->dev,
@@ -505,18 +517,20 @@ static int whiteheat_attach(struct usb_serial *serial)
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- err("No free urbs available");
+ dev_err(&port->dev, "No free urbs available\n");
goto no_tx_urb;
}
buf_size = port->write_urb->transfer_buffer_length;
urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("Couldn't allocate urb buffer");
+ dev_err(&port->dev,
+ "Couldn't allocate urb buffer\n");
goto no_tx_buf;
}
wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
if (!wrap) {
- err("Couldn't allocate urb wrapper");
+ dev_err(&port->dev,
+ "Couldn't allocate urb wrapper\n");
goto no_tx_wrap;
}
usb_fill_bulk_urb(urb, serial->dev,
@@ -534,8 +548,9 @@ static int whiteheat_attach(struct usb_serial *serial)
command_info = kmalloc(sizeof(struct whiteheat_command_private),
GFP_KERNEL);
if (command_info == NULL) {
- err("%s: Out of memory for port structures\n",
- serial->type->description);
+ dev_err(&serial->dev->dev,
+ "%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_command_private;
}
@@ -552,12 +567,15 @@ static int whiteheat_attach(struct usb_serial *serial)
no_firmware:
/* Firmware likely not running */
- err("%s: Unable to retrieve firmware version, try replugging\n",
- serial->type->description);
- err("%s: If the firmware is not running (status led not blinking)\n",
- serial->type->description);
- err("%s: please contact support@connecttech.com\n",
- serial->type->description);
+ dev_err(&serial->dev->dev,
+ "%s: Unable to retrieve firmware version, try replugging\n",
+ serial->type->description);
+ dev_err(&serial->dev->dev,
+ "%s: If the firmware is not running (status led not blinking)\n",
+ serial->type->description);
+ dev_err(&serial->dev->dev,
+ "%s: please contact support@connecttech.com\n",
+ serial->type->description);
kfree(result);
return -ENODEV;
@@ -680,8 +698,9 @@ static int whiteheat_open(struct tty_struct *tty,
/* Start reading from the device */
retval = start_port_read(port);
if (retval) {
- err("%s - failed submitting read urb, error %d",
- __func__, retval);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, retval);
firm_close(port);
stop_command_port(port->serial);
goto exit;
@@ -806,8 +825,9 @@ static int whiteheat_write(struct tty_struct *tty,
urb->transfer_buffer_length = bytes;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
sent = result;
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->tx_urbs_free);
@@ -1075,7 +1095,7 @@ static void whiteheat_read_callback(struct urb *urb)
wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
if (!wrap) {
spin_unlock(&info->lock);
- err("%s - Not my urb!", __func__);
+ dev_err(&port->dev, "%s - Not my urb!\n", __func__);
return;
}
list_del(&wrap->list);
@@ -1119,7 +1139,7 @@ static void whiteheat_write_callback(struct urb *urb)
wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
if (!wrap) {
spin_unlock(&info->lock);
- err("%s - Not my urb!", __func__);
+ dev_err(&port->dev, "%s - Not my urb!\n", __func__);
return;
}
list_move(&wrap->list, &info->tx_urbs_free);
@@ -1383,8 +1403,9 @@ static int start_command_port(struct usb_serial *serial)
command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) {
- err("%s - failed submitting read urb, error %d",
- __func__, retval);
+ dev_err(&serial->dev->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, retval);
goto exit;
}
}
@@ -1481,7 +1502,7 @@ static void rx_data_softint(struct work_struct *work)
struct whiteheat_private *info =
container_of(work, struct whiteheat_private, rx_work);
struct usb_serial_port *port = info->port;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
unsigned long flags;
@@ -1493,7 +1514,7 @@ static void rx_data_softint(struct work_struct *work)
spin_lock_irqsave(&info->lock, flags);
if (info->flags & THROTTLED) {
spin_unlock_irqrestore(&info->lock, flags);
- return;
+ goto out;
}
list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
@@ -1513,7 +1534,7 @@ static void rx_data_softint(struct work_struct *work)
spin_unlock_irqrestore(&info->lock, flags);
tty_flip_buffer_push(tty);
schedule_work(&info->rx_work);
- return;
+ goto out;
}
tty_insert_flip_string(tty, urb->transfer_buffer, len);
sent += len;
@@ -1522,7 +1543,8 @@ static void rx_data_softint(struct work_struct *work)
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed resubmitting read urb, error %d",
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
__func__, result);
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urbs_free);
@@ -1536,6 +1558,8 @@ static void rx_data_softint(struct work_struct *work)
if (sent)
tty_flip_buffer_push(tty);
+out:
+ tty_kref_put(tty);
}
@@ -1554,7 +1578,8 @@ static int __init whiteheat_init(void)
retval = usb_register(&whiteheat_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
failed_usb_register:
usb_serial_deregister(&whiteheat_device);
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index c76034672c1..3d9249632ae 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -146,18 +146,6 @@ config USB_STORAGE_KARMA
on the resulting scsi device node returns the Karma to normal
operation.
-config USB_STORAGE_SIERRA
- bool "Sierra Wireless TRU-Install Feature Support"
- depends on USB_STORAGE
- help
- Say Y here to include additional code to support Sierra Wireless
- products with the TRU-Install feature (e.g., AC597E, AC881U).
-
- This code switches the Sierra Wireless device from being in
- Mass Storage mode to Modem mode. It also has the ability to
- support host software upgrades should full Linux support be added
- to TRU-Install.
-
config USB_STORAGE_CYPRESS_ATACB
bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
depends on USB_STORAGE
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index bc3415b475c..7f8beb5366a 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -21,11 +21,10 @@ 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-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SIERRA) += sierra_ms.o
usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
- initializers.o $(usb-storage-obj-y)
+ initializers.o sierra_ms.o $(usb-storage-obj-y)
ifneq ($(CONFIG_USB_LIBUSUAL),)
obj-$(CONFIG_USB) += libusual.o
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 98b89ea9e31..c7bf8954b4e 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -78,8 +78,8 @@ static void usb_onetouch_irq(struct urb *urb)
resubmit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
- err ("can't resubmit intr, %s-%s/input0, retval %d",
- onetouch->udev->bus->bus_name,
+ dev_err(&dev->dev, "can't resubmit intr, %s-%s/input0, "
+ "retval %d\n", onetouch->udev->bus->bus_name,
onetouch->udev->devpath, retval);
}
@@ -90,7 +90,7 @@ static int usb_onetouch_open(struct input_dev *dev)
onetouch->is_open = 1;
onetouch->irq->dev = onetouch->udev;
if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
- err("usb_submit_urb failed");
+ dev_err(&dev->dev, "usb_submit_urb failed\n");
return -EIO;
}
@@ -117,7 +117,8 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action)
break;
case US_RESUME:
if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
- err("usb_submit_urb failed");
+ dev_err(&onetouch->irq->dev->dev,
+ "usb_submit_urb failed\n");
break;
default:
break;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 3523a0bfa0f..79108d5d317 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -663,7 +663,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
}
/* Did we transfer less than the minimum amount required? */
- if (srb->result == SAM_STAT_GOOD &&
+ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ba412e68d47..cd155475cb6 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -160,6 +160,13 @@ UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
+/* Reported by Filip Joelsson <filip@blueturtle.nu> */
+UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600,
+ "Nokia",
+ "Nokia 3110c",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Mario Rettig <mariorettig@web.de> */
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
"Nokia",
@@ -232,6 +239,20 @@ UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Richard Nauber <RichardNauber@web.de> */
+UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601,
+ "Nokia",
+ "6300",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
+/* Patch for Nokia 5310 capacity */
+UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591,
+ "Nokia",
+ "5310",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
"SMSC",
@@ -987,6 +1008,13 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Adrian Pilchowiec <adi1981@epf.pl> */
+UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000,
+ "RockChip",
+ "MP3",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
+
/* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com>
* This USB MP3/AVI player device fails and disconnects if more than 128
* sectors (64kB) are read/written in a single command, and may be present
@@ -1576,7 +1604,6 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
0),
-#ifdef CONFIG_USB_STORAGE_SIERRA
/* Reported by Kevin Lloyd <linux@sierrawireless.com>
* Entry is needed for the initializer function override,
* which instructs the device to load as a modem
@@ -1587,7 +1614,6 @@ UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999,
"USB MMC Storage",
US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init,
0),
-#endif
/* Reported by Jaco Kroon <jaco@kroon.co.za>
* The usb-storage module found on the Digitech GNX4 (and supposedly other
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 73679aa506d..27016fd2cad 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -102,9 +102,7 @@
#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
#include "cypress_atacb.h"
#endif
-#ifdef CONFIG_USB_STORAGE_SIERRA
#include "sierra_ms.h"
-#endif
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 70d135e0cc4..0f13448c6f7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -76,6 +76,14 @@ config FB_DDC
select I2C
default n
+config FB_BOOT_VESA_SUPPORT
+ bool
+ depends on FB
+ default n
+ ---help---
+ If true, at least one selected framebuffer driver can take advantage
+ of VESA video modes set at an early boot stage via the vga= parameter.
+
config FB_CFB_FILLRECT
tristate
depends on FB
@@ -172,11 +180,6 @@ config FB_DEFERRED_IO
bool
depends on FB
-config FB_METRONOME
- tristate
- depends on FB
- depends on FB_DEFERRED_IO
-
config FB_HECUBA
tristate
depends on FB
@@ -259,16 +262,24 @@ config FB_PM2
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
- This is the frame buffer device driver for the Permedia2 AGP frame
- buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a
- product page at
- <http://www.ask.com.hk/product/Permedia%202/permedia2.htm>.
+ This is the frame buffer device driver for cards based on
+ the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
+ The driver was tested on the following cards:
+ Diamond FireGL 1000 PRO AGP
+ ELSA Gloria Synergy PCI
+ Appian Jeronimo PRO (both heads) PCI
+ 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
+ Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
+ ASK Graphic Blaster Exxtreme AGP
+
+ To compile this driver as a module, choose M here: the
+ module will be called pm2fb.
config FB_PM2_FIFO_DISCONNECT
bool "enable FIFO disconnect feature"
depends on FB_PM2 && PCI
help
- Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
+ Support the Permedia2 FIFO disconnect feature.
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
@@ -678,7 +689,7 @@ config FB_VESA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select VIDEO_SELECT
+ select FB_BOOT_VESA_SUPPORT
help
This is the frame buffer device driver for generic VESA 2.0
compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -687,23 +698,14 @@ config FB_VESA
config FB_EFI
bool "EFI-based Framebuffer Support"
- depends on (FB = y) && X86
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the EFI frame buffer device driver. If the firmware on
- your platform is UEFI2.0, select Y to add support for
- Graphics Output Protocol for early console messages to appear.
-
-config FB_IMAC
- bool "Intel-based Macintosh Framebuffer Support"
depends on (FB = y) && X86 && EFI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
- This is the frame buffer device driver for the Intel-based Macintosh
+ This is the EFI frame buffer device driver. If the firmware on
+ your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
+ using the EFI framebuffer as your console.
config FB_N411
tristate "N411 Apollo/Hecuba devkit support"
@@ -1124,6 +1126,7 @@ config FB_INTEL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select FB_BOOT_VESA_SUPPORT
help
This driver supports the on-board graphics built in to the Intel
830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
@@ -1476,6 +1479,7 @@ config FB_SIS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select FB_BOOT_VESA_SUPPORT
help
This is the frame buffer device driver for the SiS 300, 315, 330
and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@@ -1498,6 +1502,24 @@ config FB_SIS_315
(315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
as XGI V3XT, V5, V8 and Z7.
+config FB_VIA
+ tristate "VIA UniChrome (Pro) and Chrome9 display support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select I2C_ALGOBIT
+ select I2C
+ help
+ This is the frame buffer device driver for Graphics chips of VIA
+ UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
+ CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
+ /P4M900,VX800)
+ Say Y if you have a VIA UniChrome graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called viafb.
config FB_NEOMAGIC
tristate "NeoMagic display support"
depends on FB && PCI
@@ -1527,25 +1549,25 @@ config FB_KYRO
module will be called kyrofb.
config FB_3DFX
- tristate "3Dfx Banshee/Voodoo3 display support"
+ tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
depends on FB && PCI
select FB_CFB_IMAGEBLIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
help
- This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
- chips. Say Y if you have such a graphics board.
+ This driver supports graphics boards with the 3Dfx Banshee,
+ Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
+ such a graphics board.
To compile this driver as a module, choose M here: the
module will be called tdfxfb.
config FB_3DFX_ACCEL
- bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)"
+ bool "3Dfx Acceleration functions (EXPERIMENTAL)"
depends on FB_3DFX && EXPERIMENTAL
---help---
- This will compile the 3Dfx Banshee/Voodoo3 frame buffer device
- with acceleration functions.
-
+ This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
+ device driver with acceleration functions.
config FB_VOODOO1
tristate "3Dfx Voodoo Graphics (sst1) support"
@@ -1583,7 +1605,6 @@ config FB_CYBLA
tristate "Cyberblade/i1 support"
depends on FB && PCI && X86_32 && !64BIT
select FB_CFB_IMAGEBLIT
- select VIDEO_SELECT
---help---
This driver is supposed to support the Trident Cyberblade/i1
graphics core integrated in the VIA VT8601A North Bridge,
@@ -1611,17 +1632,16 @@ config FB_TRIDENT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
- This driver is supposed to support graphics boards with the
- Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
+ This is the frame buffer device driver for Trident PCI/AGP chipsets.
+ Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
+ and Blade XP.
+ There are also integrated versions of these chips called CyberXXXX,
+ CyberImage or CyberBlade. These chips are mostly found in laptops
but also on some motherboards. For more information, read
<file:Documentation/fb/tridentfb.txt>
- Cyberblade/i1 support will be removed soon, use the cyblafb driver
- instead.
-
Say Y if you have such a graphics board.
-
To compile this driver as a module, choose M here: the
module will be called tridentfb.
@@ -1876,6 +1896,28 @@ config FB_SH_MOBILE_LCDC
---help---
Frame buffer driver for the on-chip SH-Mobile LCD controller.
+config FB_TMIO
+ tristate "Toshiba Mobile IO FrameBuffer support"
+ depends on FB && MFD_CORE
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the Toshiba Mobile IO integrated as found
+ on the Sharp SL-6000 series
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called tmiofb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
+config FB_TMIO_ACCELL
+ bool "tmiofb acceleration"
+ depends on FB_TMIO
+ default y
+
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
depends on FB && ARCH_S3C2410
@@ -1974,19 +2016,6 @@ config FB_XILINX
framebuffer. ML300 carries a 640*480 LCD display on the board,
ML403 uses a standard DB15 VGA connector.
-config FB_AM200EPD
- tristate "AM-200 E-Ink EPD devkit support"
- depends on FB && ARCH_PXA && MMU
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- select FB_METRONOME
- help
- This enables support for the Metronome display controller used on
- the E-Ink AM-200 EPD devkit.
-
config FB_COBALT
tristate "Cobalt server LCD frame buffer support"
depends on FB && MIPS_COBALT
@@ -2041,6 +2070,19 @@ config XEN_FBDEV_FRONTEND
frame buffer driver. It communicates with a back-end
in another domain.
+config FB_METRONOME
+ tristate "E-Ink Metronome/8track controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ This driver implements support for the E-Ink Metronome
+ controller. The pre-release name for this device was 8track
+ and could also have been called by some vendors as PVI-nnnn.
+
source "drivers/video/omap/Kconfig"
source "drivers/video/backlight/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index a6b55297a7f..248bddc8d0b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
-obj-$(CONFIG_FB_AM200EPD) += am200epd.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
@@ -43,6 +42,7 @@ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
obj-$(CONFIG_FB_RADEON) += aty/
obj-$(CONFIG_FB_SIS) += sis/
+obj-$(CONFIG_FB_VIA) += via/
obj-$(CONFIG_FB_KYRO) += kyro/
obj-$(CONFIG_FB_SAVAGE) += savage/
obj-$(CONFIG_FB_GEODE) += geode/
@@ -98,6 +98,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
obj-$(CONFIG_FB_PXA) += pxafb.o
obj-$(CONFIG_FB_W100) += w100fb.o
+obj-$(CONFIG_FB_TMIO) += tmiofb.o
obj-$(CONFIG_FB_AU1100) += au1100fb.o
obj-$(CONFIG_FB_AU1200) += au1200fb.o
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
@@ -125,7 +126,6 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
-obj-$(CONFIG_FB_IMAC) += imacfb.o
obj-$(CONFIG_FB_EFI) += efifb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o
diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c
deleted file mode 100644
index 0c35b8b0160..00000000000
--- a/drivers/video/am200epd.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This work was made possible by help and equipment support from E-Ink
- * Corporation. http://support.eink.com/community
- *
- * This driver is written to be used with the Metronome display controller.
- * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
- * Vizplex EPD on a Gumstix board using the Lyre interface board.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-
-#include <video/metronomefb.h>
-
-#include <mach/pxa-regs.h>
-
-/* register offsets for gpio control */
-#define LED_GPIO_PIN 51
-#define STDBY_GPIO_PIN 48
-#define RST_GPIO_PIN 49
-#define RDY_GPIO_PIN 32
-#define ERR_GPIO_PIN 17
-#define PCBPWR_GPIO_PIN 16
-
-#define AF_SEL_GPIO_N 0x3
-#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
-#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
-#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
-#define GPDR1_OFFSET(pin) (pin - 32)
-#define GPCR1_OFFSET(pin) (pin - 32)
-#define GPSR1_OFFSET(pin) (pin - 32)
-#define GPCR0_OFFSET(pin) (pin)
-#define GPSR0_OFFSET(pin) (pin)
-
-static void am200_set_gpio_output(int pin, int val)
-{
- u8 index;
-
- index = pin >> 4;
-
- switch (index) {
- case 1:
- if (val)
- GPSR0 |= (1 << GPSR0_OFFSET(pin));
- else
- GPCR0 |= (1 << GPCR0_OFFSET(pin));
- break;
- case 2:
- break;
- case 3:
- if (val)
- GPSR1 |= (1 << GPSR1_OFFSET(pin));
- else
- GPCR1 |= (1 << GPCR1_OFFSET(pin));
- break;
- default:
- printk(KERN_ERR "unimplemented\n");
- }
-}
-
-static void __devinit am200_init_gpio_pin(int pin, int dir)
-{
- u8 index;
- /* dir 0 is output, 1 is input
- - do 2 things here:
- - set gpio alternate function to standard gpio
- - set gpio direction to input or output */
-
- index = pin >> 4;
- switch (index) {
- case 1:
- GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
-
- if (dir)
- GPDR0 &= ~(1 << pin);
- else
- GPDR0 |= (1 << pin);
- break;
- case 2:
- GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
-
- if (dir)
- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
- else
- GPDR1 |= (1 << GPDR1_OFFSET(pin));
- break;
- case 3:
- GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
-
- if (dir)
- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
- else
- GPDR1 |= (1 << GPDR1_OFFSET(pin));
- break;
- default:
- printk(KERN_ERR "unimplemented\n");
- }
-}
-
-static void am200_init_gpio_regs(struct metronomefb_par *par)
-{
- am200_init_gpio_pin(LED_GPIO_PIN, 0);
- am200_set_gpio_output(LED_GPIO_PIN, 0);
-
- am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
- am200_set_gpio_output(STDBY_GPIO_PIN, 0);
-
- am200_init_gpio_pin(RST_GPIO_PIN, 0);
- am200_set_gpio_output(RST_GPIO_PIN, 0);
-
- am200_init_gpio_pin(RDY_GPIO_PIN, 1);
-
- am200_init_gpio_pin(ERR_GPIO_PIN, 1);
-
- am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
- am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
-}
-
-static void am200_disable_lcd_controller(struct metronomefb_par *par)
-{
- LCSR = 0xffffffff; /* Clear LCD Status Register */
- LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
-
- /* we reset and just wait for things to settle */
- msleep(200);
-}
-
-static void am200_enable_lcd_controller(struct metronomefb_par *par)
-{
- LCSR = 0xffffffff;
- FDADR0 = par->metromem_desc_dma;
- LCCR0 |= LCCR0_ENB;
-}
-
-static void am200_init_lcdc_regs(struct metronomefb_par *par)
-{
- /* here we do:
- - disable the lcd controller
- - setup lcd control registers
- - setup dma descriptor
- - reenable lcd controller
- */
-
- /* disable the lcd controller */
- am200_disable_lcd_controller(par);
-
- /* setup lcd control registers */
- LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
- | LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
-
- LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
- | (27 << 10) /* hsync pulse width - 1 */
- | (33 << 16) /* eol pixel count */
- | (33 << 24); /* bol pixel count */
-
- LCCR2 = (par->info->var.yres - 1) /* lines per panel */
- | (24 << 10) /* vsync pulse width - 1 */
- | (2 << 16) /* eof pixel count */
- | (0 << 24); /* bof pixel count */
-
- LCCR3 = 2 /* pixel clock divisor */
- | (24 << 8) /* AC Bias pin freq */
- | LCCR3_16BPP /* BPP */
- | LCCR3_PCP; /* PCP falling edge */
-
-}
-
-static void am200_post_dma_setup(struct metronomefb_par *par)
-{
- par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
- par->metromem_desc->mFSADR0 = par->metromem_dma;
- par->metromem_desc->mFIDR0 = 0;
- par->metromem_desc->mLDCMD0 = par->info->var.xres
- * par->info->var.yres;
- am200_enable_lcd_controller(par);
-}
-
-static void am200_free_irq(struct fb_info *info)
-{
- free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
-}
-
-static irqreturn_t am200_handle_irq(int irq, void *dev_id)
-{
- struct fb_info *info = dev_id;
- struct metronomefb_par *par = info->par;
-
- wake_up_interruptible(&par->waitq);
- return IRQ_HANDLED;
-}
-
-static int am200_setup_irq(struct fb_info *info)
-{
- int retval;
-
- retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
- IRQF_DISABLED, "AM200", info);
- if (retval) {
- printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
- return retval;
- }
-
- return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQ_TYPE_EDGE_FALLING);
-}
-
-static void am200_set_rst(struct metronomefb_par *par, int state)
-{
- am200_set_gpio_output(RST_GPIO_PIN, state);
-}
-
-static void am200_set_stdby(struct metronomefb_par *par, int state)
-{
- am200_set_gpio_output(STDBY_GPIO_PIN, state);
-}
-
-static int am200_wait_event(struct metronomefb_par *par)
-{
- return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static int am200_wait_event_intr(struct metronomefb_par *par)
-{
- return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static struct metronome_board am200_board = {
- .owner = THIS_MODULE,
- .free_irq = am200_free_irq,
- .setup_irq = am200_setup_irq,
- .init_gpio_regs = am200_init_gpio_regs,
- .init_lcdc_regs = am200_init_lcdc_regs,
- .post_dma_setup = am200_post_dma_setup,
- .set_rst = am200_set_rst,
- .set_stdby = am200_set_stdby,
- .met_wait_event = am200_wait_event,
- .met_wait_event_intr = am200_wait_event_intr,
-};
-
-static struct platform_device *am200_device;
-
-static int __init am200_init(void)
-{
- int ret;
-
- /* request our platform independent driver */
- request_module("metronomefb");
-
- am200_device = platform_device_alloc("metronomefb", -1);
- if (!am200_device)
- return -ENOMEM;
-
- platform_device_add_data(am200_device, &am200_board,
- sizeof(am200_board));
-
- /* this _add binds metronomefb to am200. metronomefb refcounts am200 */
- ret = platform_device_add(am200_device);
-
- if (ret)
- platform_device_put(am200_device);
-
- return ret;
-}
-
-static void __exit am200_exit(void)
-{
- platform_device_unregister(am200_device);
-}
-
-module_init(am200_init);
-module_exit(am200_exit);
-
-MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 9c5925927ec..f8d0a57a07c 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -208,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
return value;
}
+static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
+{
+ /* Turn off the LCD controller and the DMA controller */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+ sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+ /* Wait for the LCDC core to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+ msleep(10);
+
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+}
+
+static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
+{
+ atmel_lcdfb_stop_nowait(sinfo);
+
+ /* Wait for DMA engine to become idle... */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+ msleep(10);
+}
+
+static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
+{
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
+ | ATMEL_LCDC_PWR);
+}
+
static void atmel_lcdfb_update_dma(struct fb_info *info,
struct fb_var_screeninfo *var)
{
@@ -342,6 +372,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
var->transp.offset = var->transp.length = 0;
var->xoffset = var->yoffset = 0;
+ if (info->fix.smem_len) {
+ unsigned int smem_len = (var->xres_virtual * var->yres_virtual
+ * ((var->bits_per_pixel + 7) / 8));
+ if (smem_len > info->fix.smem_len)
+ return -EINVAL;
+ }
+
/* Saturate vertical and horizontal timings at maximum values */
var->vsync_len = min_t(u32, var->vsync_len,
(ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
@@ -378,6 +415,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
var->red.offset = 11;
var->blue.offset = 0;
var->green.length = 6;
+ } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
+ var->red.offset = 10;
+ var->blue.offset = 0;
+ var->green.length = 5;
} else {
/* BGR:555 mode */
var->red.offset = 0;
@@ -420,26 +461,8 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
{
might_sleep();
- /* LCD power off */
- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-
- /* wait for the LCDC core to become idle */
- while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
- msleep(10);
-
- /* DMA disable */
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-
- /* wait for DMA engine to become idle */
- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
- msleep(10);
-
- /* LCD power on */
- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
-
- /* DMA enable */
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+ atmel_lcdfb_stop(sinfo);
+ atmel_lcdfb_start(sinfo);
}
/**
@@ -471,14 +494,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
info->var.xres, info->var.yres,
info->var.xres_virtual, info->var.yres_virtual);
- /* Turn off the LCD controller and the DMA controller */
- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-
- /* Wait for the LCDC core to become idle */
- while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
- msleep(10);
-
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+ atmel_lcdfb_stop_nowait(sinfo);
if (info->var.bits_per_pixel == 1)
info->fix.visual = FB_VISUAL_MONO01;
@@ -583,13 +599,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
msleep(10);
- dev_dbg(info->device, " * re-enable DMA engine\n");
- /* ...and enable it with updated configuration */
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-
- dev_dbg(info->device, " * re-enable LCDC core\n");
- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+ atmel_lcdfb_start(sinfo);
dev_dbg(info->device, " * DONE\n");
@@ -939,7 +949,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
ret = register_framebuffer(info);
if (ret < 0) {
dev_err(dev, "failed to register framebuffer device: %d\n", ret);
- goto free_cmap;
+ goto reset_drvdata;
}
/* add selected videomode to modelist */
@@ -955,7 +965,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
return 0;
-
+reset_drvdata:
+ dev_set_drvdata(dev, NULL);
free_cmap:
fb_dealloc_cmap(&info->cmap);
unregister_irqs:
@@ -992,10 +1003,11 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fb_info *info = dev_get_drvdata(dev);
- struct atmel_lcdfb_info *sinfo = info->par;
+ struct atmel_lcdfb_info *sinfo;
- if (!sinfo)
+ if (!info || !info->par)
return 0;
+ sinfo = info->par;
cancel_work_sync(&sinfo->task);
exit_backlight(sinfo);
@@ -1030,11 +1042,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
struct fb_info *info = platform_get_drvdata(pdev);
struct atmel_lcdfb_info *sinfo = info->par;
+ /*
+ * We don't want to handle interrupts while the clock is
+ * stopped. It may take forever.
+ */
+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+
sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
+
+ atmel_lcdfb_stop(sinfo);
atmel_lcdfb_stop_clock(sinfo);
+
return 0;
}
@@ -1044,9 +1065,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
struct atmel_lcdfb_info *sinfo = info->par;
atmel_lcdfb_start_clock(sinfo);
+ atmel_lcdfb_start(sinfo);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(1);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
+
+ /* Enable FIFO & DMA errors */
+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
+ | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
+
return 0;
}
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index aa95f835024..8718f7349d6 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -5,61 +5,61 @@
* --dte
*/
-static void radeon_fixup_offset(struct radeonfb_info *rinfo)
+#define FLUSH_CACHE_WORKAROUND 1
+
+void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries)
{
- u32 local_base;
-
- /* *** Ugly workaround *** */
- /*
- * On some platforms, the video memory is mapped at 0 in radeon chip space
- * (like PPCs) by the firmware. X will always move it up so that it's seen
- * by the chip to be at the same address as the PCI BAR.
- * That means that when switching back from X, there is a mismatch between
- * the offsets programmed into the engine. This means that potentially,
- * accel operations done before radeonfb has a chance to re-init the engine
- * will have incorrect offsets, and potentially trash system memory !
- *
- * The correct fix is for fbcon to never call any accel op before the engine
- * has properly been re-initialized (by a call to set_var), but this is a
- * complex fix. This workaround in the meantime, called before every accel
- * operation, makes sure the offsets are in sync.
- */
+ int i;
- radeon_fifo_wait (1);
- local_base = INREG(MC_FB_LOCATION) << 16;
- if (local_base == rinfo->fb_local_base)
- return;
+ for (i=0; i<2000000; i++) {
+ rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f;
+ if (rinfo->fifo_free >= entries)
+ return;
+ udelay(10);
+ }
+ printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+ /* XXX Todo: attempt to reset the engine */
+}
- rinfo->fb_local_base = local_base;
+static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ if (entries <= rinfo->fifo_free)
+ rinfo->fifo_free -= entries;
+ else
+ radeon_fifo_update_and_wait(rinfo, entries);
+}
- radeon_fifo_wait (3);
- OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
- (rinfo->fb_local_base >> 10));
- OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
- OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg,
+ u32 *cache, u32 new_val)
+{
+ if (new_val == *cache)
+ return;
+ *cache = new_val;
+ radeon_fifo_wait(rinfo, 1);
+ OUTREG(reg, new_val);
}
static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
const struct fb_fillrect *region)
{
- radeon_fifo_wait(4);
-
- OUTREG(DP_GUI_MASTER_CNTL,
- rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */
- | GMC_BRUSH_SOLID_COLOR
- | ROP3_P);
- if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
- OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
- else
- OUTREG(DP_BRUSH_FRGD_CLR, region->color);
- OUTREG(DP_WRITE_MSK, 0xffffffff);
- OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
-
- radeon_fifo_wait(2);
+ radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+ rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P);
+ radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+ DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache,
+ region->color);
+
+ /* Ensure the dst cache is flushed and the engine idle before
+ * issuing the operation.
+ *
+ * This works around engine lockups on some cards
+ */
+#if FLUSH_CACHE_WORKAROUND
+ radeon_fifo_wait(rinfo, 2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
- radeon_fifo_wait(2);
+#endif
+ radeon_fifo_wait(rinfo, 2);
OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
}
@@ -70,15 +70,14 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
struct fb_fillrect modded;
int vxres, vyres;
- if (info->state != FBINFO_STATE_RUNNING)
+ WARN_ON(rinfo->gfx_mode);
+ if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_fillrect(info, region);
return;
}
- radeon_fixup_offset(rinfo);
-
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@@ -91,6 +90,10 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR )
+ modded.color = ((u32 *) (info->pseudo_palette))[region->color];
+
radeonfb_prim_fillrect(rinfo, &modded);
}
@@ -109,22 +112,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
if ( xdir < 0 ) { sx += w-1; dx += w-1; }
if ( ydir < 0 ) { sy += h-1; dy += h-1; }
- radeon_fifo_wait(3);
- OUTREG(DP_GUI_MASTER_CNTL,
- rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
- | GMC_BRUSH_NONE
- | GMC_SRC_DSTCOLOR
- | ROP3_S
- | DP_SRC_SOURCE_MEMORY );
- OUTREG(DP_WRITE_MSK, 0xffffffff);
- OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
- | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
-
- radeon_fifo_wait(2);
+ radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+ rinfo->dp_gui_mc_base |
+ GMC_BRUSH_NONE |
+ GMC_SRC_DATATYPE_COLOR |
+ ROP3_S |
+ DP_SRC_SOURCE_MEMORY);
+ radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+ (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
+ (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
+
+#if FLUSH_CACHE_WORKAROUND
+ radeon_fifo_wait(rinfo, 2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
- radeon_fifo_wait(3);
+#endif
+ radeon_fifo_wait(rinfo, 3);
OUTREG(SRC_Y_X, (sy << 16) | sx);
OUTREG(DST_Y_X, (dy << 16) | dx);
OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -143,15 +146,14 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
modded.width = area->width;
modded.height = area->height;
- if (info->state != FBINFO_STATE_RUNNING)
+ WARN_ON(rinfo->gfx_mode);
+ if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_copyarea(info, area);
return;
}
- radeon_fixup_offset(rinfo);
-
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@@ -168,13 +170,112 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
radeonfb_prim_copyarea(rinfo, &modded);
}
+static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo,
+ const struct fb_image *image,
+ u32 fg, u32 bg)
+{
+ unsigned int src_bytes, dwords;
+ u32 *bits;
+
+ radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+ rinfo->dp_gui_mc_base |
+ GMC_BRUSH_NONE |
+ GMC_SRC_DATATYPE_MONO_FG_BG |
+ ROP3_S |
+ GMC_BYTE_ORDER_MSB_TO_LSB |
+ DP_SRC_SOURCE_HOST_DATA);
+ radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+ DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg);
+ radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg);
+
+ radeon_fifo_wait(rinfo, 1);
+ OUTREG(DST_Y_X, (image->dy << 16) | image->dx);
+
+ /* Ensure the dst cache is flushed and the engine idle before
+ * issuing the operation.
+ *
+ * This works around engine lockups on some cards
+ */
+#if FLUSH_CACHE_WORKAROUND
+ radeon_fifo_wait(rinfo, 2);
+ OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
+ OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
+#endif
+
+ /* X here pads width to a multiple of 32 and uses the clipper to
+ * adjust the result. Is that really necessary ? Things seem to
+ * work ok for me without that and the doco doesn't seem to imply
+ * there is such a restriction.
+ */
+ OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height);
+
+ src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
+ dwords = (src_bytes + 3) / 4;
+ bits = (u32*)(image->data);
+
+ while(dwords >= 8) {
+ radeon_fifo_wait(rinfo, 8);
+#if BITS_PER_LONG == 64
+ __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0);
+ __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2);
+ __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4);
+ __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6);
+ bits += 8;
+#else
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7);
+#endif
+ dwords -= 8;
+ }
+ while(dwords--) {
+ radeon_fifo_wait(rinfo, 1);
+ __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
+ }
+}
+
void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct radeonfb_info *rinfo = info->par;
+ u32 fg, bg;
- if (info->state != FBINFO_STATE_RUNNING)
+ WARN_ON(rinfo->gfx_mode);
+ if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
+ return;
+
+ if (!image->width || !image->height)
return;
- radeon_engine_idle();
+
+ /* We only do 1 bpp color expansion for now */
+ if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
+ goto fallback;
+
+ /* Fallback if running out of the screen. We may do clipping
+ * in the future */
+ if ((image->dx + image->width) > info->var.xres_virtual ||
+ (image->dy + image->height) > info->var.yres_virtual)
+ goto fallback;
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ fg = ((u32*)(info->pseudo_palette))[image->fg_color];
+ bg = ((u32*)(info->pseudo_palette))[image->bg_color];
+ } else {
+ fg = image->fg_color;
+ bg = image->bg_color;
+ }
+
+ radeonfb_prim_imageblit(rinfo, image, fg, bg);
+ return;
+
+ fallback:
+ radeon_engine_idle(rinfo);
cfb_imageblit(info, image);
}
@@ -185,7 +286,8 @@ int radeonfb_sync(struct fb_info *info)
if (info->state != FBINFO_STATE_RUNNING)
return 0;
- radeon_engine_idle();
+
+ radeon_engine_idle(rinfo);
return 0;
}
@@ -211,9 +313,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
host_path_cntl = INREG(HOST_PATH_CNTL);
rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
- if (rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350) {
+ if (IS_R300_VARIANT(rinfo)) {
u32 tmp;
OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -249,9 +349,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
INREG(HOST_PATH_CNTL);
OUTREG(HOST_PATH_CNTL, host_path_cntl);
- if (rinfo->family != CHIP_FAMILY_R300 &&
- rinfo->family != CHIP_FAMILY_R350 &&
- rinfo->family != CHIP_FAMILY_RV350)
+ if (!IS_R300_VARIANT(rinfo))
OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -265,15 +363,24 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
/* disable 3D engine */
OUTREG(RB3D_CNTL, 0);
+ rinfo->fifo_free = 0;
radeonfb_engine_reset(rinfo);
- radeon_fifo_wait (1);
- if ((rinfo->family != CHIP_FAMILY_R300) &&
- (rinfo->family != CHIP_FAMILY_R350) &&
- (rinfo->family != CHIP_FAMILY_RV350))
+ radeon_fifo_wait(rinfo, 1);
+ if (IS_R300_VARIANT(rinfo)) {
+ OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
+ RB2D_DC_AUTOFLUSH_ENABLE |
+ RB2D_DC_DC_DISABLE_IGNORE_PE);
+ } else {
+ /* This needs to be double checked with ATI. Latest X driver
+ * completely "forgets" to set this register on < r3xx, and
+ * we used to just write 0 there... I'll keep the 0 and update
+ * that when we have sorted things out on X side.
+ */
OUTREG(RB2D_DSTCACHE_MODE, 0);
+ }
- radeon_fifo_wait (3);
+ radeon_fifo_wait(rinfo, 3);
/* We re-read MC_FB_LOCATION from card as it can have been
* modified by XFree drivers (ouch !)
*/
@@ -284,41 +391,57 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
- radeon_fifo_wait (1);
-#if defined(__BIG_ENDIAN)
+ radeon_fifo_wait(rinfo, 1);
+#ifdef __BIG_ENDIAN
OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
#else
OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
#endif
- radeon_fifo_wait (2);
+ radeon_fifo_wait(rinfo, 2);
OUTREG(DEFAULT_SC_TOP_LEFT, 0);
OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
DEFAULT_SC_BOTTOM_MAX));
+ /* set default DP_GUI_MASTER_CNTL */
temp = radeon_get_dstbpp(rinfo->depth);
- rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
+ rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
- radeon_fifo_wait (1);
- OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
- GMC_BRUSH_SOLID_COLOR |
- GMC_SRC_DATATYPE_COLOR));
+ rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base |
+ GMC_BRUSH_SOLID_COLOR |
+ GMC_SRC_DATATYPE_COLOR;
+ radeon_fifo_wait(rinfo, 1);
+ OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache);
- radeon_fifo_wait (7);
/* clear line drawing regs */
+ radeon_fifo_wait(rinfo, 2);
OUTREG(DST_LINE_START, 0);
OUTREG(DST_LINE_END, 0);
- /* set brush color regs */
- OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
- OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
-
- /* set source color regs */
- OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
- OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
+ /* set brush and source color regs */
+ rinfo->dp_brush_fg_cache = 0xffffffff;
+ rinfo->dp_brush_bg_cache = 0x00000000;
+ rinfo->dp_src_fg_cache = 0xffffffff;
+ rinfo->dp_src_bg_cache = 0x00000000;
+ radeon_fifo_wait(rinfo, 4);
+ OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache);
+ OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache);
+ OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache);
+ OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache);
+
+ /* Default direction */
+ rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM;
+ radeon_fifo_wait(rinfo, 1);
+ OUTREG(DP_CNTL, rinfo->dp_cntl_cache);
/* default write mask */
+ radeon_fifo_wait(rinfo, 1);
OUTREG(DP_WRITE_MSK, 0xffffffff);
- radeon_engine_idle ();
+ /* Default to no swapping of host data */
+ radeon_fifo_wait(rinfo, 1);
+ OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE);
+
+ /* Make sure it's settled */
+ radeon_engine_idle(rinfo);
}
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 1a056adb61c..f343ba83f0a 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
level = bd->props.brightness;
del_timer_sync(&rinfo->lvds_timer);
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
if (level > 0) {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 652273e9f5f..9a5821c65eb 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -852,7 +852,6 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
if (rinfo->asleep)
return 0;
- radeon_fifo_wait(2);
OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
* var->bits_per_pixel / 8) & ~7);
return 0;
@@ -882,7 +881,6 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
if (rc)
return rc;
- radeon_fifo_wait(2);
if (value & 0x01) {
tmp = INREG(LVDS_GEN_CNTL);
@@ -940,7 +938,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
if (rinfo->lock_blank)
return 0;
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
val = INREG(CRTC_EXT_CNTL);
val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
@@ -1048,7 +1046,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
if (rinfo->asleep)
return 0;
-
+
return radeon_screen_blank(rinfo, blank, 0);
}
@@ -1074,8 +1072,6 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno;
if (!rinfo->asleep) {
- radeon_fifo_wait(9);
-
if (rinfo->bpp == 16) {
pindex = regno * 8;
@@ -1244,8 +1240,6 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
{
int i;
- radeon_fifo_wait(20);
-
/* Workaround from XFree */
if (rinfo->is_mobility) {
/* A temporal workaround for the occational blanking on certain laptop
@@ -1286,11 +1280,10 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
- if (rinfo->family == CHIP_FAMILY_R300 ||
+ if (IS_R300_VARIANT(rinfo) ||
rinfo->family == CHIP_FAMILY_RS300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350 ||
- rinfo->family == CHIP_FAMILY_RV380 ) {
+ rinfo->family == CHIP_FAMILY_RS400 ||
+ rinfo->family == CHIP_FAMILY_RS480) {
if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
/* When restoring console mode, use saved PPLL_REF_DIV
* setting.
@@ -1342,7 +1335,7 @@ static void radeon_lvds_timer_func(unsigned long data)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
}
@@ -1360,10 +1353,11 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (nomodeset)
return;
+ radeon_engine_idle(rinfo);
+
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
- radeon_fifo_wait(31);
for (i=0; i<10; i++)
OUTREG(common_regs[i].reg, common_regs[i].val);
@@ -1391,7 +1385,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
radeon_write_pll_regs(rinfo, mode);
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- radeon_fifo_wait(10);
OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@@ -1406,7 +1399,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
- radeon_fifo_wait(2);
OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
return;
@@ -1461,10 +1453,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
/* Not all chip revs have the same format for this register,
* extract the source selection
*/
- if (rinfo->family == CHIP_FAMILY_R200 ||
- rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
source = (fp2_gen_cntl >> 10) & 0x3;
/* sourced from transform unit, check for transform unit
* own source
@@ -1560,7 +1549,7 @@ static int radeonfb_set_par(struct fb_info *info)
/* We always want engine to be idle on a mode switch, even
* if we won't actually change the mode
*/
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
hSyncStart = mode->xres + mode->right_margin;
hSyncEnd = hSyncStart + mode->hsync_len;
@@ -1855,7 +1844,6 @@ static int radeonfb_set_par(struct fb_info *info)
return 0;
}
-
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
@@ -1879,6 +1867,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
info->par = rinfo;
info->pseudo_palette = rinfo->pseudo_palette;
info->flags = FBINFO_DEFAULT
+ | FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_XPAN
@@ -2005,11 +1994,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
(rinfo->family == CHIP_FAMILY_RS200) ||
(rinfo->family == CHIP_FAMILY_RS300) ||
(rinfo->family == CHIP_FAMILY_RC410) ||
+ (rinfo->family == CHIP_FAMILY_RS400) ||
(rinfo->family == CHIP_FAMILY_RS480) ) {
u32 tom = INREG(NB_TOM);
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
- radeon_fifo_wait(6);
OUTREG(MC_FB_LOCATION, tom);
OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 8c8fa35f1b7..2c5567175dc 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -139,12 +139,8 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
u8 **out_edid)
{
- u32 reg = rinfo->i2c[conn-1].ddc_reg;
u8 *edid;
- OUTREG(reg, INREG(reg) &
- ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
-
edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
if (out_edid)
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 675abdafc2d..3df5015f1d1 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
/* Make sure engine is reset */
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
radeonfb_engine_reset(rinfo);
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
}
/* Blank display and LCD */
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
rinfo->asleep = 0;
} else
- radeon_engine_idle();
+ radeon_engine_idle(rinfo);
/* Restore display & engine */
radeon_write_mode (rinfo, &rinfo->state, 1);
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index ccbfffd1280..ea0b5b47aca 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -53,6 +53,7 @@ enum radeon_family {
CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
CHIP_FAMILY_R420, /* R420/R423/M18 */
CHIP_FAMILY_RC410,
+ CHIP_FAMILY_RS400,
CHIP_FAMILY_RS480,
CHIP_FAMILY_LAST,
};
@@ -335,7 +336,15 @@ struct radeonfb_info {
int mon2_type;
u8 *mon2_EDID;
- u32 dp_gui_master_cntl;
+ /* accel bits */
+ u32 dp_gui_mc_base;
+ u32 dp_gui_mc_cache;
+ u32 dp_cntl_cache;
+ u32 dp_brush_fg_cache;
+ u32 dp_brush_bg_cache;
+ u32 dp_src_fg_cache;
+ u32 dp_src_bg_cache;
+ u32 fifo_free;
struct pll_info pll;
@@ -347,6 +356,7 @@ struct radeonfb_info {
int lock_blank;
int dynclk;
int no_schedule;
+ int gfx_mode;
enum radeon_pm_mode pm_mode;
reinit_function_ptr reinit_func;
@@ -391,8 +401,14 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
#define INREG16(addr) readw((rinfo->mmio_base)+addr)
#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
+
+#ifdef CONFIG_PPC
+#define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); })
+#define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0)
+#else
#define INREG(addr) readl((rinfo->mmio_base)+addr)
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
+#endif
static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
u32 val, u32 mask)
@@ -533,16 +549,25 @@ static inline u32 radeon_get_dstbpp(u16 depth)
/*
* 2D Engine helper routines
*/
+
+extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries);
+
static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
{
int i;
- /* initiate flush */
- OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ /* Initiate flush */
+ OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
~RB2D_DC_FLUSH_ALL);
+ /* Ensure FIFO is empty, ie, make sure the flush commands
+ * has reached the cache
+ */
+ radeon_fifo_update_and_wait(rinfo, 64);
+
+ /* Wait for the flush to complete */
for (i=0; i < 2000000; i++) {
- if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
return;
udelay(1);
}
@@ -550,25 +575,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
}
-static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
-{
- int i;
-
- for (i=0; i<2000000; i++) {
- if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
- return;
- udelay(1);
- }
- printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
-}
-
-
-static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
+static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
{
int i;
/* ensure FIFO is empty before waiting for idle */
- _radeon_fifo_wait (rinfo, 64);
+ radeon_fifo_update_and_wait (rinfo, 64);
for (i=0; i<2000000; i++) {
if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
@@ -581,8 +593,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
}
-#define radeon_engine_idle() _radeon_engine_idle(rinfo)
-#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
@@ -612,6 +622,7 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
extern int radeonfb_sync(struct fb_info *info);
extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
+extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo);
/* Other functions */
extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 452b770d8cc..c72a1356295 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -24,6 +24,13 @@ config LCD_CLASS_DEVICE
To have support for your specific LCD panel you will have to
select the proper drivers which depend on this option.
+config LCD_CORGI
+ tristate "LCD Panel support for SHARP corgi/spitz model"
+ depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL
+ help
+ Say y here to support the LCD panels usually found on SHARP
+ corgi (C7x0) and spitz (Cxx00) models.
+
config LCD_LTV350QV
tristate "Samsung LTV350QV LCD Panel"
depends on LCD_CLASS_DEVICE && SPI_MASTER
@@ -44,6 +51,14 @@ config LCD_ILI9320
If you have a panel based on the ILI9320 controller chip
then say y to include a power driver for it.
+config LCD_TDO24M
+ tristate "Toppoly TDO24M LCD Panels support"
+ depends on LCD_CLASS_DEVICE && SPI_MASTER
+ default n
+ help
+ If you have a Toppoly TDO24M series LCD panel, say y here to
+ include the support for it.
+
config LCD_VGG2432A4
tristate "VGG2432A4 LCM device support"
depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index b405aace803..3ec551eb472 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -1,10 +1,12 @@
# Backlight & LCD drivers
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
+obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
obj-$(CONFIG_LCD_ILI9320) += ili9320.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
+obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
new file mode 100644
index 00000000000..2afd47eefe7
--- /dev/null
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -0,0 +1,641 @@
+/*
+ * LCD/Backlight Driver for Sharp Zaurus Handhelds (various models)
+ *
+ * Copyright (c) 2004-2006 Richard Purdie
+ *
+ * Based on Sharp's 2.4 Backlight Driver
+ *
+ * Copyright (c) 2008 Marvell International Ltd.
+ * Converted to SPI device based LCD/Backlight device driver
+ * by Eric Miao <eric.miao@marvell.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/lcd.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/corgi_lcd.h>
+#include <asm/mach/sharpsl_param.h>
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+/* Register Addresses */
+#define RESCTL_ADRS 0x00
+#define PHACTRL_ADRS 0x01
+#define DUTYCTRL_ADRS 0x02
+#define POWERREG0_ADRS 0x03
+#define POWERREG1_ADRS 0x04
+#define GPOR3_ADRS 0x05
+#define PICTRL_ADRS 0x06
+#define POLCTRL_ADRS 0x07
+
+/* Register Bit Definitions */
+#define RESCTL_QVGA 0x01
+#define RESCTL_VGA 0x00
+
+#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
+#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
+#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
+
+#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
+#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
+#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
+
+#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
+#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
+#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
+#define POWER0_COM_ON 0x08 /* COM Power Supply ON */
+#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
+
+#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
+#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */
+#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
+
+#define PICTRL_INIT_STATE 0x01
+#define PICTRL_INIOFF 0x02
+#define PICTRL_POWER_DOWN 0x04
+#define PICTRL_COM_SIGNAL_OFF 0x08
+#define PICTRL_DAC_SIGNAL_OFF 0x10
+
+#define POLCTRL_SYNC_POL_FALL 0x01
+#define POLCTRL_EN_POL_FALL 0x02
+#define POLCTRL_DATA_POL_FALL 0x04
+#define POLCTRL_SYNC_ACT_H 0x08
+#define POLCTRL_EN_ACT_L 0x10
+
+#define POLCTRL_SYNC_POL_RISE 0x00
+#define POLCTRL_EN_POL_RISE 0x00
+#define POLCTRL_DATA_POL_RISE 0x00
+#define POLCTRL_SYNC_ACT_L 0x00
+#define POLCTRL_EN_ACT_H 0x00
+
+#define PHACTRL_PHASE_MANUAL 0x01
+#define DEFAULT_PHAD_QVGA (9)
+#define DEFAULT_COMADJ (125)
+
+struct corgi_lcd {
+ struct spi_device *spi_dev;
+ struct lcd_device *lcd_dev;
+ struct backlight_device *bl_dev;
+
+ int limit_mask;
+ int intensity;
+ int power;
+ int mode;
+ char buf[2];
+
+ int gpio_backlight_on;
+ int gpio_backlight_cont;
+ int gpio_backlight_cont_inverted;
+
+ void (*kick_battery)(void);
+};
+
+static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int reg, uint8_t val);
+
+static struct corgi_lcd *the_corgi_lcd;
+static unsigned long corgibl_flags;
+#define CORGIBL_SUSPENDED 0x01
+#define CORGIBL_BATTLOW 0x02
+
+/*
+ * This is only a psuedo I2C interface. We can't use the standard kernel
+ * routines as the interface is write only. We just assume the data is acked...
+ */
+static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data)
+{
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, data);
+ udelay(10);
+}
+
+static void lcdtg_i2c_send_bit(struct corgi_lcd *lcd, uint8_t data)
+{
+ lcdtg_ssp_i2c_send(lcd, data);
+ lcdtg_ssp_i2c_send(lcd, data | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(lcd, data);
+}
+
+static void lcdtg_i2c_send_start(struct corgi_lcd *lcd, uint8_t base)
+{
+ lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+ lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(lcd, base);
+}
+
+static void lcdtg_i2c_send_stop(struct corgi_lcd *lcd, uint8_t base)
+{
+ lcdtg_ssp_i2c_send(lcd, base);
+ lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+}
+
+static void lcdtg_i2c_send_byte(struct corgi_lcd *lcd,
+ uint8_t base, uint8_t data)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (data & 0x80)
+ lcdtg_i2c_send_bit(lcd, base | POWER0_COM_DOUT);
+ else
+ lcdtg_i2c_send_bit(lcd, base);
+ data <<= 1;
+ }
+}
+
+static void lcdtg_i2c_wait_ack(struct corgi_lcd *lcd, uint8_t base)
+{
+ lcdtg_i2c_send_bit(lcd, base);
+}
+
+static void lcdtg_set_common_voltage(struct corgi_lcd *lcd,
+ uint8_t base_data, uint8_t data)
+{
+ /* Set Common Voltage to M62332FP via I2C */
+ lcdtg_i2c_send_start(lcd, base_data);
+ lcdtg_i2c_send_byte(lcd, base_data, 0x9c);
+ lcdtg_i2c_wait_ack(lcd, base_data);
+ lcdtg_i2c_send_byte(lcd, base_data, 0x00);
+ lcdtg_i2c_wait_ack(lcd, base_data);
+ lcdtg_i2c_send_byte(lcd, base_data, data);
+ lcdtg_i2c_wait_ack(lcd, base_data);
+ lcdtg_i2c_send_stop(lcd, base_data);
+}
+
+static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int adrs, uint8_t data)
+{
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 1,
+ .cs_change = 1,
+ .tx_buf = lcd->buf,
+ };
+
+ lcd->buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(lcd->spi_dev, &msg);
+}
+
+/* Set Phase Adjust */
+static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
+{
+ int adj;
+
+ switch(mode) {
+ case CORGI_LCD_MODE_VGA:
+ /* Setting for VGA */
+ adj = sharpsl_param.phadadj;
+ adj = (adj < 0) ? PHACTRL_PHASE_MANUAL :
+ PHACTRL_PHASE_MANUAL | ((adj & 0xf) << 1);
+ break;
+ case CORGI_LCD_MODE_QVGA:
+ default:
+ /* Setting for QVGA */
+ adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
+ break;
+ }
+
+ corgi_ssp_lcdtg_send(lcd, PHACTRL_ADRS, adj);
+}
+
+static void corgi_lcd_power_on(struct corgi_lcd *lcd)
+{
+ int comadj;
+
+ /* Initialize Internal Logic & Port */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
+ PICTRL_POWER_DOWN | PICTRL_INIOFF |
+ PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF |
+ PICTRL_DAC_SIGNAL_OFF);
+
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF |
+ POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+
+ /* VDD(+8V), SVSS(-4V) ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+ mdelay(3);
+
+ /* DAC ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
+ POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* INIB = H, INI = L */
+ /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
+ PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
+
+ /* Set Common Voltage */
+ comadj = sharpsl_param.comadj;
+ if (comadj < 0)
+ comadj = DEFAULT_COMADJ;
+
+ lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
+ POWER0_VCC5_OFF, comadj);
+
+ /* VCC5 ON, DAC ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
+ POWER0_COM_OFF | POWER0_VCC5_ON);
+
+ /* GVSS(-8V) ON, VDD ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+ mdelay(2);
+
+ /* COM SIGNAL ON (PICTL[3] = L) */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_INIT_STATE);
+
+ /* COM ON, DAC ON, VCC5_ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
+ POWER0_COM_ON | POWER0_VCC5_ON);
+
+ /* VW ON, GVSS ON, VDD ON */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+ /* Signals output enable */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, 0);
+
+ /* Set Phase Adjust */
+ lcdtg_set_phadadj(lcd, lcd->mode);
+
+ /* Initialize for Input Signals from ATI */
+ corgi_ssp_lcdtg_send(lcd, POLCTRL_ADRS,
+ POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE |
+ POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L |
+ POLCTRL_EN_ACT_H);
+ udelay(1000);
+
+ switch (lcd->mode) {
+ case CORGI_LCD_MODE_VGA:
+ corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
+ break;
+ case CORGI_LCD_MODE_QVGA:
+ default:
+ corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
+ break;
+ }
+}
+
+static void corgi_lcd_power_off(struct corgi_lcd *lcd)
+{
+ /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
+ msleep(34);
+
+ /* (1)VW OFF */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+ /* (2)COM OFF */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
+
+ /* (3)Set Common Voltage Bias 0V */
+ lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
+ POWER0_VCC5_ON, 0);
+
+ /* (4)GVSS OFF */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+
+ /* (5)VCC5 OFF */
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* (6)Set PDWN, INIOFF, DACOFF */
+ corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
+ PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
+ PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
+
+ /* (7)DAC OFF */
+ corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
+ POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* (8)VDD OFF */
+ corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
+ POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+}
+
+static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
+ int mode = CORGI_LCD_MODE_QVGA;
+
+ if (m->xres == 640 || m->xres == 480)
+ mode = CORGI_LCD_MODE_VGA;
+
+ if (lcd->mode == mode)
+ return 0;
+
+ lcdtg_set_phadadj(lcd, mode);
+
+ switch (mode) {
+ case CORGI_LCD_MODE_VGA:
+ corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
+ break;
+ case CORGI_LCD_MODE_QVGA:
+ default:
+ corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
+ break;
+ }
+
+ lcd->mode = mode;
+ return 0;
+}
+
+static int corgi_lcd_set_power(struct lcd_device *ld, int power)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+ corgi_lcd_power_on(lcd);
+
+ if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+ corgi_lcd_power_off(lcd);
+
+ lcd->power = power;
+ return 0;
+}
+
+static int corgi_lcd_get_power(struct lcd_device *ld)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
+
+ return lcd->power;
+}
+
+static struct lcd_ops corgi_lcd_ops = {
+ .get_power = corgi_lcd_get_power,
+ .set_power = corgi_lcd_set_power,
+ .set_mode = corgi_lcd_set_mode,
+};
+
+static int corgi_bl_get_intensity(struct backlight_device *bd)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
+
+ return lcd->intensity;
+}
+
+static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity)
+{
+ int cont;
+
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ corgi_ssp_lcdtg_send(lcd, DUTYCTRL_ADRS, intensity);
+
+ /* Bit 5 via GPIO_BACKLIGHT_CONT */
+ cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted;
+
+ if (gpio_is_valid(lcd->gpio_backlight_cont))
+ gpio_set_value(lcd->gpio_backlight_cont, cont);
+
+ if (gpio_is_valid(lcd->gpio_backlight_on))
+ gpio_set_value(lcd->gpio_backlight_on, intensity);
+
+ if (lcd->kick_battery)
+ lcd->kick_battery();
+
+ lcd->intensity = intensity;
+ return 0;
+}
+
+static int corgi_bl_update_status(struct backlight_device *bd)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
+ int intensity = bd->props.brightness;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+
+ if (corgibl_flags & CORGIBL_SUSPENDED)
+ intensity = 0;
+ if (corgibl_flags & CORGIBL_BATTLOW)
+ intensity &= lcd->limit_mask;
+
+ return corgi_bl_set_intensity(lcd, intensity);
+}
+
+void corgibl_limit_intensity(int limit)
+{
+ if (limit)
+ corgibl_flags |= CORGIBL_BATTLOW;
+ else
+ corgibl_flags &= ~CORGIBL_BATTLOW;
+
+ backlight_update_status(the_corgi_lcd->bl_dev);
+}
+EXPORT_SYMBOL(corgibl_limit_intensity);
+
+static struct backlight_ops corgi_bl_ops = {
+ .get_brightness = corgi_bl_get_intensity,
+ .update_status = corgi_bl_update_status,
+};
+
+#ifdef CONFIG_PM
+static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
+
+ corgibl_flags |= CORGIBL_SUSPENDED;
+ corgi_bl_set_intensity(lcd, 0);
+ corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
+ return 0;
+}
+
+static int corgi_lcd_resume(struct spi_device *spi)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
+
+ corgibl_flags &= ~CORGIBL_SUSPENDED;
+ corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
+ backlight_update_status(lcd->bl_dev);
+ return 0;
+}
+#else
+#define corgi_lcd_suspend NULL
+#define corgi_lcd_resume NULL
+#endif
+
+static int setup_gpio_backlight(struct corgi_lcd *lcd,
+ struct corgi_lcd_platform_data *pdata)
+{
+ struct spi_device *spi = lcd->spi_dev;
+ int err;
+
+ lcd->gpio_backlight_on = -1;
+ lcd->gpio_backlight_cont = -1;
+
+ if (gpio_is_valid(pdata->gpio_backlight_on)) {
+ err = gpio_request(pdata->gpio_backlight_on, "BL_ON");
+ if (err) {
+ dev_err(&spi->dev, "failed to request GPIO%d for "
+ "backlight_on\n", pdata->gpio_backlight_on);
+ return err;
+ }
+
+ lcd->gpio_backlight_on = pdata->gpio_backlight_on;
+ gpio_direction_output(lcd->gpio_backlight_on, 0);
+ }
+
+ if (gpio_is_valid(pdata->gpio_backlight_cont)) {
+ err = gpio_request(pdata->gpio_backlight_cont, "BL_CONT");
+ if (err) {
+ dev_err(&spi->dev, "failed to request GPIO%d for "
+ "backlight_cont\n", pdata->gpio_backlight_cont);
+ goto err_free_backlight_on;
+ }
+
+ lcd->gpio_backlight_cont = pdata->gpio_backlight_cont;
+
+ /* spitz and akita use both GPIOs for backlight, and
+ * have inverted polarity of GPIO_BACKLIGHT_CONT
+ */
+ if (gpio_is_valid(lcd->gpio_backlight_on)) {
+ lcd->gpio_backlight_cont_inverted = 1;
+ gpio_direction_output(lcd->gpio_backlight_cont, 1);
+ } else {
+ lcd->gpio_backlight_cont_inverted = 0;
+ gpio_direction_output(lcd->gpio_backlight_cont, 0);
+ }
+ }
+ return 0;
+
+err_free_backlight_on:
+ if (gpio_is_valid(lcd->gpio_backlight_on))
+ gpio_free(lcd->gpio_backlight_on);
+ return err;
+}
+
+static int __devinit corgi_lcd_probe(struct spi_device *spi)
+{
+ struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
+ struct corgi_lcd *lcd;
+ int ret = 0;
+
+ if (pdata == NULL) {
+ dev_err(&spi->dev, "platform data not available\n");
+ return -EINVAL;
+ }
+
+ lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
+ if (!lcd) {
+ dev_err(&spi->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ lcd->spi_dev = spi;
+
+ lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
+ lcd, &corgi_lcd_ops);
+ if (IS_ERR(lcd->lcd_dev)) {
+ ret = PTR_ERR(lcd->lcd_dev);
+ goto err_free_lcd;
+ }
+ lcd->power = FB_BLANK_POWERDOWN;
+ lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
+
+ lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev,
+ lcd, &corgi_bl_ops);
+ if (IS_ERR(lcd->bl_dev)) {
+ ret = PTR_ERR(lcd->bl_dev);
+ goto err_unregister_lcd;
+ }
+ lcd->bl_dev->props.max_brightness = pdata->max_intensity;
+ lcd->bl_dev->props.brightness = pdata->default_intensity;
+ lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
+
+ ret = setup_gpio_backlight(lcd, pdata);
+ if (ret)
+ goto err_unregister_bl;
+
+ lcd->kick_battery = pdata->kick_battery;
+
+ dev_set_drvdata(&spi->dev, lcd);
+ corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
+ backlight_update_status(lcd->bl_dev);
+
+ lcd->limit_mask = pdata->limit_mask;
+ the_corgi_lcd = lcd;
+ return 0;
+
+err_unregister_bl:
+ backlight_device_unregister(lcd->bl_dev);
+err_unregister_lcd:
+ lcd_device_unregister(lcd->lcd_dev);
+err_free_lcd:
+ kfree(lcd);
+ return ret;
+}
+
+static int __devexit corgi_lcd_remove(struct spi_device *spi)
+{
+ struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
+
+ lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
+ lcd->bl_dev->props.brightness = 0;
+ backlight_update_status(lcd->bl_dev);
+ backlight_device_unregister(lcd->bl_dev);
+
+ if (gpio_is_valid(lcd->gpio_backlight_on))
+ gpio_free(lcd->gpio_backlight_on);
+
+ if (gpio_is_valid(lcd->gpio_backlight_cont))
+ gpio_free(lcd->gpio_backlight_cont);
+
+ corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
+ lcd_device_unregister(lcd->lcd_dev);
+ kfree(lcd);
+
+ return 0;
+}
+
+static struct spi_driver corgi_lcd_driver = {
+ .driver = {
+ .name = "corgi-lcd",
+ .owner = THIS_MODULE,
+ },
+ .probe = corgi_lcd_probe,
+ .remove = __devexit_p(corgi_lcd_remove),
+ .suspend = corgi_lcd_suspend,
+ .resume = corgi_lcd_resume,
+};
+
+static int __init corgi_lcd_init(void)
+{
+ return spi_register_driver(&corgi_lcd_driver);
+}
+module_init(corgi_lcd_init);
+
+static void __exit corgi_lcd_exit(void)
+{
+ spi_unregister_driver(&corgi_lcd_driver);
+}
+module_exit(corgi_lcd_exit);
+
+MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index b15b2b84a6f..8e1731d3b22 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -27,14 +27,26 @@ static int fb_notifier_callback(struct notifier_block *self,
struct fb_event *evdata = data;
/* If we aren't interested in this event, skip it immediately ... */
- if (event != FB_EVENT_BLANK)
+ switch (event) {
+ case FB_EVENT_BLANK:
+ case FB_EVENT_MODE_CHANGE:
+ case FB_EVENT_MODE_CHANGE_ALL:
+ break;
+ default:
return 0;
+ }
ld = container_of(self, struct lcd_device, fb_notif);
+ if (!ld->ops)
+ return 0;
+
mutex_lock(&ld->ops_lock);
- if (ld->ops)
- if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
+ if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
+ if (event == FB_EVENT_BLANK)
ld->ops->set_power(ld, *(int *)evdata->data);
+ else
+ ld->ops->set_mode(ld, evdata->data);
+ }
mutex_unlock(&ld->ops_lock);
return 0;
}
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 385cba40ea8..06964af761c 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -111,6 +111,4 @@ module_exit(mbp_exit);
MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
+MODULE_DEVICE_TABLE(dmi, mbp_device_table);
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
new file mode 100644
index 00000000000..8427669162e
--- /dev/null
+++ b/drivers/video/backlight/tdo24m.c
@@ -0,0 +1,396 @@
+/*
+ * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
+ *
+ * Copyright (C) 2008 Marvell International Ltd.
+ * Eric Miao <eric.miao@marvell.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/fb.h>
+#include <linux/lcd.h>
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+#define TDO24M_SPI_BUFF_SIZE (4)
+#define MODE_QVGA 0
+#define MODE_VGA 1
+
+struct tdo24m {
+ struct spi_device *spi_dev;
+ struct lcd_device *lcd_dev;
+
+ struct spi_message msg;
+ struct spi_transfer xfer;
+ uint8_t *buf;
+
+ int power;
+ int mode;
+};
+
+/* use bit 30, 31 as the indicator of command parameter number */
+#define CMD0(x) ((0 << 30) | (x))
+#define CMD1(x, x1) ((1 << 30) | ((x) << 9) | 0x100 | (x1))
+#define CMD2(x, x1, x2) ((2 << 30) | ((x) << 18) | 0x20000 |\
+ ((x1) << 9) | 0x100 | (x2))
+#define CMD_NULL (-1)
+
+static uint32_t lcd_panel_reset[] = {
+ CMD0(0x1), /* reset */
+ CMD0(0x0), /* nop */
+ CMD0(0x0), /* nop */
+ CMD0(0x0), /* nop */
+ CMD_NULL,
+};
+
+static uint32_t lcd_panel_on[] = {
+ CMD0(0x29), /* Display ON */
+ CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
+ CMD0(0x11), /* Sleep out */
+ CMD1(0xB0, 0x16), /* Wake */
+ CMD_NULL,
+};
+
+static uint32_t lcd_panel_off[] = {
+ CMD0(0x28), /* Display OFF */
+ CMD2(0xB8, 0x80, 0x02), /* Output Control */
+ CMD0(0x10), /* Sleep in */
+ CMD1(0xB0, 0x00), /* Deep stand by in */
+ CMD_NULL,
+};
+
+static uint32_t lcd_vga_pass_through[] = {
+ CMD1(0xB0, 0x16),
+ CMD1(0xBC, 0x80),
+ CMD1(0xE1, 0x00),
+ CMD1(0x36, 0x50),
+ CMD1(0x3B, 0x00),
+ CMD_NULL,
+};
+
+static uint32_t lcd_qvga_pass_through[] = {
+ CMD1(0xB0, 0x16),
+ CMD1(0xBC, 0x81),
+ CMD1(0xE1, 0x00),
+ CMD1(0x36, 0x50),
+ CMD1(0x3B, 0x22),
+ CMD_NULL,
+};
+
+static uint32_t lcd_vga_transfer[] = {
+ CMD1(0xcf, 0x02), /* Blanking period control (1) */
+ CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
+ CMD1(0xd1, 0x01), /* CKV timing control on/off */
+ CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
+ CMD2(0xd3, 0x1a, 0x0f), /* OEV timing control */
+ CMD2(0xd4, 0x1f, 0xaf), /* ASW timing control (1) */
+ CMD1(0xd5, 0x14), /* ASW timing control (2) */
+ CMD0(0x21), /* Invert for normally black display */
+ CMD0(0x29), /* Display on */
+ CMD_NULL,
+};
+
+static uint32_t lcd_qvga_transfer[] = {
+ CMD1(0xd6, 0x02), /* Blanking period control (1) */
+ CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
+ CMD1(0xd8, 0x01), /* CKV timing control on/off */
+ CMD2(0xd9, 0x00, 0x08), /* CKV 1,2 timing control */
+ CMD2(0xde, 0x05, 0x0a), /* OEV timing control */
+ CMD2(0xdf, 0x0a, 0x19), /* ASW timing control (1) */
+ CMD1(0xe0, 0x0a), /* ASW timing control (2) */
+ CMD0(0x21), /* Invert for normally black display */
+ CMD0(0x29), /* Display on */
+ CMD_NULL,
+};
+
+static uint32_t lcd_panel_config[] = {
+ CMD2(0xb8, 0xff, 0xf9), /* Output control */
+ CMD0(0x11), /* sleep out */
+ CMD1(0xba, 0x01), /* Display mode (1) */
+ CMD1(0xbb, 0x00), /* Display mode (2) */
+ CMD1(0x3a, 0x60), /* Display mode 18-bit RGB */
+ CMD1(0xbf, 0x10), /* Drive system change control */
+ CMD1(0xb1, 0x56), /* Booster operation setup */
+ CMD1(0xb2, 0x33), /* Booster mode setup */
+ CMD1(0xb3, 0x11), /* Booster frequency setup */
+ CMD1(0xb4, 0x02), /* Op amp/system clock */
+ CMD1(0xb5, 0x35), /* VCS voltage */
+ CMD1(0xb6, 0x40), /* VCOM voltage */
+ CMD1(0xb7, 0x03), /* External display signal */
+ CMD1(0xbd, 0x00), /* ASW slew rate */
+ CMD1(0xbe, 0x00), /* Dummy data for QuadData operation */
+ CMD1(0xc0, 0x11), /* Sleep out FR count (A) */
+ CMD1(0xc1, 0x11), /* Sleep out FR count (B) */
+ CMD1(0xc2, 0x11), /* Sleep out FR count (C) */
+ CMD2(0xc3, 0x20, 0x40), /* Sleep out FR count (D) */
+ CMD2(0xc4, 0x60, 0xc0), /* Sleep out FR count (E) */
+ CMD2(0xc5, 0x10, 0x20), /* Sleep out FR count (F) */
+ CMD1(0xc6, 0xc0), /* Sleep out FR count (G) */
+ CMD2(0xc7, 0x33, 0x43), /* Gamma 1 fine tuning (1) */
+ CMD1(0xc8, 0x44), /* Gamma 1 fine tuning (2) */
+ CMD1(0xc9, 0x33), /* Gamma 1 inclination adjustment */
+ CMD1(0xca, 0x00), /* Gamma 1 blue offset adjustment */
+ CMD2(0xec, 0x01, 0xf0), /* Horizontal clock cycles */
+ CMD_NULL,
+};
+
+static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
+{
+ struct spi_transfer *x = &lcd->xfer;
+ uint32_t data, *p = array;
+ int nparams, err = 0;
+
+ for (; *p != CMD_NULL; p++) {
+
+ nparams = (*p >> 30) & 0x3;
+
+ data = *p << (7 - nparams);
+ switch (nparams) {
+ case 0:
+ lcd->buf[0] = (data >> 8) & 0xff;
+ lcd->buf[1] = data & 0xff;
+ break;
+ case 1:
+ lcd->buf[0] = (data >> 16) & 0xff;
+ lcd->buf[1] = (data >> 8) & 0xff;
+ lcd->buf[2] = data & 0xff;
+ break;
+ case 2:
+ lcd->buf[0] = (data >> 24) & 0xff;
+ lcd->buf[1] = (data >> 16) & 0xff;
+ lcd->buf[2] = (data >> 8) & 0xff;
+ lcd->buf[3] = data & 0xff;
+ break;
+ default:
+ continue;
+ }
+ x->len = nparams + 2;
+ err = spi_sync(lcd->spi_dev, &lcd->msg);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+static int tdo24m_adj_mode(struct tdo24m *lcd, int mode)
+{
+ switch (mode) {
+ case MODE_VGA:
+ tdo24m_writes(lcd, lcd_vga_pass_through);
+ tdo24m_writes(lcd, lcd_panel_config);
+ tdo24m_writes(lcd, lcd_vga_transfer);
+ break;
+ case MODE_QVGA:
+ tdo24m_writes(lcd, lcd_qvga_pass_through);
+ tdo24m_writes(lcd, lcd_panel_config);
+ tdo24m_writes(lcd, lcd_qvga_transfer);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ lcd->mode = mode;
+ return 0;
+}
+
+static int tdo24m_power_on(struct tdo24m *lcd)
+{
+ int err;
+
+ err = tdo24m_writes(lcd, lcd_panel_on);
+ if (err)
+ goto out;
+
+ err = tdo24m_writes(lcd, lcd_panel_reset);
+ if (err)
+ goto out;
+
+ err = tdo24m_adj_mode(lcd, lcd->mode);
+out:
+ return err;
+}
+
+static int tdo24m_power_off(struct tdo24m *lcd)
+{
+ return tdo24m_writes(lcd, lcd_panel_off);
+}
+
+static int tdo24m_power(struct tdo24m *lcd, int power)
+{
+ int ret = 0;
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+ ret = tdo24m_power_on(lcd);
+ else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+ ret = tdo24m_power_off(lcd);
+
+ if (!ret)
+ lcd->power = power;
+
+ return ret;
+}
+
+
+static int tdo24m_set_power(struct lcd_device *ld, int power)
+{
+ struct tdo24m *lcd = lcd_get_data(ld);
+ return tdo24m_power(lcd, power);
+}
+
+static int tdo24m_get_power(struct lcd_device *ld)
+{
+ struct tdo24m *lcd = lcd_get_data(ld);
+ return lcd->power;
+}
+
+static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m)
+{
+ struct tdo24m *lcd = lcd_get_data(ld);
+ int mode = MODE_QVGA;
+
+ if (m->xres == 640 || m->xres == 480)
+ mode = MODE_VGA;
+
+ if (lcd->mode == mode)
+ return 0;
+
+ return tdo24m_adj_mode(lcd, mode);
+}
+
+static struct lcd_ops tdo24m_ops = {
+ .get_power = tdo24m_get_power,
+ .set_power = tdo24m_set_power,
+ .set_mode = tdo24m_set_mode,
+};
+
+static int __devinit tdo24m_probe(struct spi_device *spi)
+{
+ struct tdo24m *lcd;
+ struct spi_message *m;
+ struct spi_transfer *x;
+ int err;
+
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_3;
+ err = spi_setup(spi);
+ if (err)
+ return err;
+
+ lcd = kzalloc(sizeof(struct tdo24m), GFP_KERNEL);
+ if (!lcd)
+ return -ENOMEM;
+
+ lcd->spi_dev = spi;
+ lcd->power = FB_BLANK_POWERDOWN;
+ lcd->mode = MODE_VGA; /* default to VGA */
+
+ lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL));
+ if (lcd->buf == NULL) {
+ kfree(lcd);
+ return -ENOMEM;
+ }
+
+ m = &lcd->msg;
+ x = &lcd->xfer;
+
+ spi_message_init(m);
+
+ x->tx_buf = &lcd->buf[0];
+ spi_message_add_tail(x, m);
+
+ lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
+ lcd, &tdo24m_ops);
+ if (IS_ERR(lcd->lcd_dev)) {
+ err = PTR_ERR(lcd->lcd_dev);
+ goto out_free;
+ }
+
+ dev_set_drvdata(&spi->dev, lcd);
+ err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
+ if (err)
+ goto out_unregister;
+
+ return 0;
+
+out_unregister:
+ lcd_device_unregister(lcd->lcd_dev);
+out_free:
+ kfree(lcd->buf);
+ kfree(lcd);
+ return err;
+}
+
+static int __devexit tdo24m_remove(struct spi_device *spi)
+{
+ struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
+
+ tdo24m_power(lcd, FB_BLANK_POWERDOWN);
+ lcd_device_unregister(lcd->lcd_dev);
+ kfree(lcd->buf);
+ kfree(lcd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tdo24m_suspend(struct spi_device *spi, pm_message_t state)
+{
+ struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
+
+ return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+static int tdo24m_resume(struct spi_device *spi)
+{
+ struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
+
+ return tdo24m_power(lcd, FB_BLANK_UNBLANK);
+}
+#else
+#define tdo24m_suspend NULL
+#define tdo24m_resume NULL
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+static void tdo24m_shutdown(struct spi_device *spi)
+{
+ struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
+
+ tdo24m_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+static struct spi_driver tdo24m_driver = {
+ .driver = {
+ .name = "tdo24m",
+ .owner = THIS_MODULE,
+ },
+ .probe = tdo24m_probe,
+ .remove = __devexit_p(tdo24m_remove),
+ .shutdown = tdo24m_shutdown,
+ .suspend = tdo24m_suspend,
+ .resume = tdo24m_resume,
+};
+
+static int __init tdo24m_init(void)
+{
+ return spi_register_driver(&tdo24m_driver);
+}
+module_init(tdo24m_init);
+
+static void __exit tdo24m_exit(void)
+{
+ spi_unregister_driver(&tdo24m_driver);
+}
+module_exit(tdo24m_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index e721644bad7..1e35ba6f18e 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -372,7 +372,7 @@ static int __devexit bw2_remove(struct of_device *op)
return 0;
}
-static struct of_device_id bw2_match[] = {
+static const struct of_device_id bw2_match[] = {
{
.name = "bwtwo",
},
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index e15bb447440..c9b191319a9 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -535,7 +535,7 @@ static struct fb_ops carminefb_ops = {
.fb_setcolreg = carmine_setcolreg,
};
-static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
int smem_offset, struct device *device, struct fb_info **rinfo)
{
int ret;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index b17e7467177..a2d1882791a 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -589,7 +589,7 @@ static int __devexit cg14_remove(struct of_device *op)
return 0;
}
-static struct of_device_id cg14_match[] = {
+static const struct of_device_id cg14_match[] = {
{
.name = "cgfourteen",
},
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 3aa7b6cb026..99f87fb61d0 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -456,7 +456,7 @@ static int __devexit cg3_remove(struct of_device *op)
return 0;
}
-static struct of_device_id cg3_match[] = {
+static const struct of_device_id cg3_match[] = {
{
.name = "cgthree",
},
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 2f64bb3bd25..940ec04f0f1 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *);
static void cg6_imageblit(struct fb_info *, const struct fb_image *);
static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
+static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
static int cg6_sync(struct fb_info *);
static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
-static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
* Frame buffer operations
@@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = cg6_setcolreg,
.fb_blank = cg6_blank,
+ .fb_pan_display = cg6_pan_display,
.fb_fillrect = cg6_fillrect,
.fb_copyarea = cg6_copyarea,
.fb_imageblit = cg6_imageblit,
@@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = {
#define CG6_THC_MISC_INT_ENAB (1 << 5)
#define CG6_THC_MISC_INT (1 << 4)
#define CG6_THC_MISC_INIT 0x9f
+#define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16))
/* The contents are unknown */
struct cg6_tec {
@@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info)
return 0;
}
+static void cg6_switch_from_graph(struct cg6_par *par)
+{
+ struct cg6_thc __iomem *thc = par->thc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&par->lock, flags);
+
+ /* Hide the cursor. */
+ sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
+
+ spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct cg6_par *par = (struct cg6_par *)info->par;
+
+ /* We just use this to catch switches out of
+ * graphics mode.
+ */
+ cg6_switch_from_graph(par);
+
+ if (var->xoffset || var->yoffset || var->vmode)
+ return -EINVAL;
+ return 0;
+}
+
/**
* cg6_fillrect - Draws a rectangle on the screen.
*
@@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info)
struct cg6_par *par = (struct cg6_par *)info->par;
struct cg6_tec __iomem *tec = par->tec;
struct cg6_fbc __iomem *fbc = par->fbc;
+ struct cg6_thc __iomem *thc = par->thc;
u32 rev, conf, mode;
int i;
+ /* Hide the cursor. */
+ sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
+
/* Turn off stuff in the Transform Engine. */
sbus_writel(0, &tec->tec_matrix);
sbus_writel(0, &tec->tec_clip);
@@ -814,7 +848,7 @@ static int __devexit cg6_remove(struct of_device *op)
return 0;
}
-static struct of_device_id cg6_match[] = {
+static const struct of_device_id cg6_match[] = {
{
.name = "cgsix",
},
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index c14b2435d23..048b139f0e5 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -327,29 +327,7 @@ static const struct {
#endif /* CONFIG_ZORRO */
struct cirrusfb_regs {
- long freq;
- long nom;
- long den;
- long div;
- long multiplexing;
- long mclk;
- long divMCLK;
-
- long HorizRes; /* The x resolution in pixel */
- long HorizTotal;
- long HorizDispEnd;
- long HorizBlankStart;
- long HorizBlankEnd;
- long HorizSyncStart;
- long HorizSyncEnd;
-
- long VertRes; /* the physical y resolution in scanlines */
- long VertTotal;
- long VertDispEnd;
- long VertSyncStart;
- long VertSyncEnd;
- long VertBlankStart;
- long VertBlankEnd;
+ int multiplexing;
};
#ifdef CIRRUSFB_DEBUG
@@ -367,110 +345,13 @@ struct cirrusfb_info {
struct cirrusfb_regs currentmode;
int blank_mode;
+ u32 pseudo_palette[16];
- u32 pseudo_palette[16];
-
-#ifdef CONFIG_ZORRO
- struct zorro_dev *zdev;
-#endif
-#ifdef CONFIG_PCI
- struct pci_dev *pdev;
-#endif
void (*unmap)(struct fb_info *info);
};
-static unsigned cirrusfb_def_mode = 1;
-static int noaccel;
-
-/*
- * Predefined Video Modes
- */
-
-static const struct {
- const char *name;
- struct fb_var_screeninfo var;
-} cirrusfb_predefined[] = {
- {
- /* autodetect mode */
- .name = "Autodetect",
- }, {
- /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
- .name = "640x480",
- .var = {
- .xres = 640,
- .yres = 480,
- .xres_virtual = 640,
- .yres_virtual = 480,
- .bits_per_pixel = 8,
- .red = { .length = 8 },
- .green = { .length = 8 },
- .blue = { .length = 8 },
- .width = -1,
- .height = -1,
- .pixclock = 40000,
- .left_margin = 48,
- .right_margin = 16,
- .upper_margin = 32,
- .lower_margin = 8,
- .hsync_len = 96,
- .vsync_len = 4,
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
- }
- }, {
- /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
- .name = "800x600",
- .var = {
- .xres = 800,
- .yres = 600,
- .xres_virtual = 800,
- .yres_virtual = 600,
- .bits_per_pixel = 8,
- .red = { .length = 8 },
- .green = { .length = 8 },
- .blue = { .length = 8 },
- .width = -1,
- .height = -1,
- .pixclock = 20000,
- .left_margin = 128,
- .right_margin = 16,
- .upper_margin = 24,
- .lower_margin = 2,
- .hsync_len = 96,
- .vsync_len = 6,
- .vmode = FB_VMODE_NONINTERLACED
- }
- }, {
- /*
- * Modeline from XF86Config:
- * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
- */
- /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
- .name = "1024x768",
- .var = {
- .xres = 1024,
- .yres = 768,
- .xres_virtual = 1024,
- .yres_virtual = 768,
- .bits_per_pixel = 8,
- .red = { .length = 8 },
- .green = { .length = 8 },
- .blue = { .length = 8 },
- .width = -1,
- .height = -1,
- .pixclock = 12500,
- .left_margin = 144,
- .right_margin = 32,
- .upper_margin = 30,
- .lower_margin = 2,
- .hsync_len = 192,
- .vsync_len = 6,
- .vmode = FB_VMODE_NONINTERLACED
- }
- }
-};
-
-#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
+static int noaccel __devinitdata;
+static char *mode_option __devinitdata = "640x480@60";
/****************************************************************************/
/**** BEGIN PROTOTYPES ******************************************************/
@@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = {
.fb_imageblit = cirrusfb_imageblit,
};
-/*--- Hardware Specific Routines -------------------------------------------*/
-static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
- struct cirrusfb_regs *regs,
- struct fb_info *info);
/*--- Internal routines ----------------------------------------------------*/
static void init_vgachip(struct fb_info *info);
static void switch_monitor(struct cirrusfb_info *cinfo, int on);
@@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
u_short width, u_short height,
u_char color, u_short line_length);
-static void bestclock(long freq, long *best,
- long *nom, long *den,
- long *div, long maxfreq);
+static void bestclock(long freq, int *nom, int *den, int *div);
#ifdef CIRRUSFB_DEBUG
static void cirrusfb_dump(void);
@@ -584,71 +459,44 @@ static int cirrusfb_release(struct fb_info *info, int user)
/****************************************************************************/
/**** BEGIN Hardware specific Routines **************************************/
-/* Get a good MCLK value */
-static long cirrusfb_get_mclk(long freq, int bpp, long *div)
+/* Check if the MCLK is not a better clock source */
+static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq)
{
- long mclk;
-
- assert(div != NULL);
+ long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
- /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
- * Assume a 64-bit data path for now. The formula is:
- * ((B * PCLK * 2)/W) * 1.2
- * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
- mclk = ((bpp / 8) * freq * 2) / 4;
- mclk = (mclk * 12) / 10;
- if (mclk < 50000)
- mclk = 50000;
- DPRINTK("Use MCLK of %ld kHz\n", mclk);
-
- /* Calculate value for SR1F. Multiply by 2 so we can round up. */
- mclk = ((mclk * 16) / 14318);
- mclk = (mclk + 1) / 2;
- DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
+ /* Read MCLK value */
+ mclk = (14318 * mclk) >> 3;
+ DPRINTK("Read MCLK of %ld kHz\n", mclk);
/* Determine if we should use MCLK instead of VCLK, and if so, what we
- * should divide it by to get VCLK */
- switch (freq) {
- case 24751 ... 25249:
- *div = 2;
- DPRINTK("Using VCLK = MCLK/2\n");
- break;
- case 49501 ... 50499:
- *div = 1;
+ * should divide it by to get VCLK
+ */
+
+ if (abs(freq - mclk) < 250) {
DPRINTK("Using VCLK = MCLK\n");
- break;
- default:
- *div = 0;
- break;
+ return 1;
+ } else if (abs(freq - (mclk / 2)) < 250) {
+ DPRINTK("Using VCLK = MCLK/2\n");
+ return 2;
}
- return mclk;
+ return 0;
}
static int cirrusfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- int nom, den; /* translyting from pixels->bytes */
- int yres, i;
- static struct { int xres, yres; } modes[] =
- { { 1600, 1280 },
- { 1280, 1024 },
- { 1024, 768 },
- { 800, 600 },
- { 640, 480 },
- { -1, -1 } };
+ int yres;
+ /* memory size in pixels */
+ unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
switch (var->bits_per_pixel) {
case 1:
- nom = 4;
- den = 8;
+ pixels /= 4;
break; /* 8 pixel per byte, only 1/4th of mem usable */
case 8:
case 16:
- case 24:
case 32:
- nom = var->bits_per_pixel / 8;
- den = 1;
break; /* 1 pixel == 1 byte */
default:
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
@@ -658,43 +506,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
- if (var->xres * nom / den * var->yres > info->screen_size) {
- printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
- "resolution too high to fit into video memory!\n",
- var->xres, var->yres, var->bits_per_pixel);
- DPRINTK("EXIT - EINVAL error\n");
- return -EINVAL;
- }
-
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
/* use highest possible virtual resolution */
- if (var->xres_virtual == -1 &&
- var->yres_virtual == -1) {
- printk(KERN_INFO
- "cirrusfb: using maximum available virtual resolution\n");
- for (i = 0; modes[i].xres != -1; i++) {
- int size = modes[i].xres * nom / den * modes[i].yres;
- if (size < info->screen_size / 2)
- break;
- }
- if (modes[i].xres == -1) {
- printk(KERN_ERR "cirrusfb: could not find a virtual "
- "resolution that fits into video memory!!\n");
- DPRINTK("EXIT - EINVAL error\n");
- return -EINVAL;
- }
- var->xres_virtual = modes[i].xres;
- var->yres_virtual = modes[i].yres;
+ if (var->yres_virtual == -1) {
+ var->yres_virtual = pixels / var->xres_virtual;
printk(KERN_INFO "cirrusfb: virtual resolution set to "
"maximum of %dx%d\n", var->xres_virtual,
var->yres_virtual);
}
-
- if (var->xres_virtual < var->xres)
- var->xres_virtual = var->xres;
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
+ if (var->xres_virtual * var->yres_virtual > pixels) {
+ printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
+ "virtual resolution too high to fit into video memory!\n",
+ var->xres_virtual, var->yres_virtual,
+ var->bits_per_pixel);
+ DPRINTK("EXIT - EINVAL error\n");
+ return -EINVAL;
+ }
+
+
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
@@ -736,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 5;
break;
- case 24:
case 32:
if (isPReP) {
var->red.offset = 8;
@@ -790,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
long maxclock;
int maxclockidx = var->bits_per_pixel >> 3;
struct cirrusfb_info *cinfo = info->par;
- int xres, hfront, hsync, hback;
- int yres, vfront, vsync, vback;
switch (var->bits_per_pixel) {
case 1:
@@ -805,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
break;
case 16:
- case 24:
case 32:
info->fix.line_length = var->xres_virtual * maxclockidx;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
default:
@@ -850,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
switch (var->bits_per_pixel) {
case 16:
case 32:
- if (regs->HorizRes <= 800)
+ if (var->xres <= 800)
/* Xbh has this type of clock for 32-bit */
freq /= 2;
break;
}
#endif
-
- bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
- maxclock);
- regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
- &regs->divMCLK);
-
- xres = var->xres;
- hfront = var->right_margin;
- hsync = var->hsync_len;
- hback = var->left_margin;
-
- yres = var->yres;
- vfront = var->lower_margin;
- vsync = var->vsync_len;
- vback = var->upper_margin;
-
- if (var->vmode & FB_VMODE_DOUBLE) {
- yres *= 2;
- vfront *= 2;
- vsync *= 2;
- vback *= 2;
- } else if (var->vmode & FB_VMODE_INTERLACED) {
- yres = (yres + 1) / 2;
- vfront = (vfront + 1) / 2;
- vsync = (vsync + 1) / 2;
- vback = (vback + 1) / 2;
- }
- regs->HorizRes = xres;
- regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
- regs->HorizDispEnd = xres / 8 - 1;
- regs->HorizBlankStart = xres / 8;
- /* does not count with "-5" */
- regs->HorizBlankEnd = regs->HorizTotal + 5;
- regs->HorizSyncStart = (xres + hfront) / 8 + 1;
- regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
-
- regs->VertRes = yres;
- regs->VertTotal = yres + vfront + vsync + vback - 2;
- regs->VertDispEnd = yres - 1;
- regs->VertBlankStart = yres;
- regs->VertBlankEnd = regs->VertTotal;
- regs->VertSyncStart = yres + vfront - 1;
- regs->VertSyncEnd = yres + vfront + vsync - 1;
-
- if (regs->VertRes >= 1024) {
- regs->VertTotal /= 2;
- regs->VertSyncStart /= 2;
- regs->VertSyncEnd /= 2;
- regs->VertDispEnd /= 2;
- }
- if (regs->multiplexing) {
- regs->HorizTotal /= 2;
- regs->HorizSyncStart /= 2;
- regs->HorizSyncEnd /= 2;
- regs->HorizDispEnd /= 2;
- }
-
return 0;
}
-static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
- int div)
+static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo,
+ int div)
{
+ unsigned char old1f, old1e;
assert(cinfo != NULL);
+ old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
- if (div == 2) {
- /* VCLK = MCLK/2 */
- unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
- vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
- vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
- } else if (div == 1) {
- /* VCLK = MCLK */
- unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
- vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
- vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
- } else {
- vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
+ if (div) {
+ DPRINTK("Set %s as pixclock source.\n",
+ (div == 2) ? "MCLK/2" : "MCLK");
+ old1f |= 0x40;
+ old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
+ if (div == 2)
+ old1e |= 1;
+
+ vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
}
+ vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
}
/*************************************************************************
@@ -950,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
unsigned char tmp;
int offset = 0, err;
const struct cirrusfb_board_info_rec *bi;
+ int hdispend, hsyncstart, hsyncend, htotal;
+ int yres, vdispend, vsyncstart, vsyncend, vtotal;
+ long freq;
+ int nom, den, div;
DPRINTK("ENTER\n");
DPRINTK("Requested mode: %dx%dx%d\n",
@@ -967,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
bi = &cirrusfb_board_info[cinfo->btype];
+ hsyncstart = var->xres + var->right_margin;
+ hsyncend = hsyncstart + var->hsync_len;
+ htotal = (hsyncend + var->left_margin) / 8 - 5;
+ hdispend = var->xres / 8 - 1;
+ hsyncstart = hsyncstart / 8 + 1;
+ hsyncend = hsyncend / 8 + 1;
+
+ yres = var->yres;
+ vsyncstart = yres + var->lower_margin;
+ vsyncend = vsyncstart + var->vsync_len;
+ vtotal = vsyncend + var->upper_margin;
+ vdispend = yres - 1;
+
+ if (var->vmode & FB_VMODE_DOUBLE) {
+ yres *= 2;
+ vsyncstart *= 2;
+ vsyncend *= 2;
+ vtotal *= 2;
+ } else if (var->vmode & FB_VMODE_INTERLACED) {
+ yres = (yres + 1) / 2;
+ vsyncstart = (vsyncstart + 1) / 2;
+ vsyncend = (vsyncend + 1) / 2;
+ vtotal = (vtotal + 1) / 2;
+ }
+
+ vtotal -= 2;
+ vsyncstart -= 1;
+ vsyncend -= 1;
+
+ if (yres >= 1024) {
+ vtotal /= 2;
+ vsyncstart /= 2;
+ vsyncend /= 2;
+ vdispend /= 2;
+ }
+ if (regs.multiplexing) {
+ htotal /= 2;
+ hsyncstart /= 2;
+ hsyncend /= 2;
+ hdispend /= 2;
+ }
/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
/* if debugging is enabled, all parameters get output before writing */
- DPRINTK("CRT0: %ld\n", regs.HorizTotal);
- vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
+ DPRINTK("CRT0: %d\n", htotal);
+ vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
- DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
- vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
+ DPRINTK("CRT1: %d\n", hdispend);
+ vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
- DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
- vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
+ DPRINTK("CRT2: %d\n", var->xres / 8);
+ vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
/* + 128: Compatible read */
- DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
+ DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
- 128 + (regs.HorizBlankEnd % 32));
+ 128 + ((htotal + 5) % 32));
- DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
- vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
+ DPRINTK("CRT4: %d\n", hsyncstart);
+ vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
- tmp = regs.HorizSyncEnd % 32;
- if (regs.HorizBlankEnd & 32)
+ tmp = hsyncend % 32;
+ if ((htotal + 5) & 32)
tmp += 128;
DPRINTK("CRT5: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
- DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
- vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
+ DPRINTK("CRT6: %d\n", vtotal & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
tmp = 16; /* LineCompare bit #9 */
- if (regs.VertTotal & 256)
+ if (vtotal & 256)
tmp |= 1;
- if (regs.VertDispEnd & 256)
+ if (vdispend & 256)
tmp |= 2;
- if (regs.VertSyncStart & 256)
+ if (vsyncstart & 256)
tmp |= 4;
- if (regs.VertBlankStart & 256)
+ if ((vdispend + 1) & 256)
tmp |= 8;
- if (regs.VertTotal & 512)
+ if (vtotal & 512)
tmp |= 32;
- if (regs.VertDispEnd & 512)
+ if (vdispend & 512)
tmp |= 64;
- if (regs.VertSyncStart & 512)
+ if (vsyncstart & 512)
tmp |= 128;
DPRINTK("CRT7: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
tmp = 0x40; /* LineCompare bit #8 */
- if (regs.VertBlankStart & 512)
+ if ((vdispend + 1) & 512)
tmp |= 0x20;
if (var->vmode & FB_VMODE_DOUBLE)
tmp |= 0x80;
DPRINTK("CRT9: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
- DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
- vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
+ DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
- DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
- vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
+ DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
+ vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
- DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
- vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
+ DPRINTK("CRT12: %d\n", vdispend & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
- DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
- vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
+ DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
- DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
- vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
+ DPRINTK("CRT16: %d\n", vtotal & 0xff);
+ vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
DPRINTK("CRT18: 0xff\n");
vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
@@ -1044,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
tmp = 0;
if (var->vmode & FB_VMODE_INTERLACED)
tmp |= 1;
- if (regs.HorizBlankEnd & 64)
+ if ((htotal + 5) & 64)
tmp |= 16;
- if (regs.HorizBlankEnd & 128)
+ if ((htotal + 5) & 128)
tmp |= 32;
- if (regs.VertBlankEnd & 256)
+ if (vtotal & 256)
tmp |= 64;
- if (regs.VertBlankEnd & 512)
+ if (vtotal & 512)
tmp |= 128;
DPRINTK("CRT1a: %d\n", tmp);
vga_wcrt(regbase, CL_CRT1A, tmp);
+ freq = PICOS2KHZ(var->pixclock);
+ bestclock(freq, &nom, &den, &div);
+
/* set VCLK0 */
/* hardware RefClock: 14.31818 MHz */
/* formula: VClk = (OSC * N) / (D * (1+P)) */
/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
- vga_wseq(regbase, CL_SEQRB, regs.nom);
- tmp = regs.den << 1;
- if (regs.div != 0)
- tmp |= 1;
+ if (cinfo->btype == BT_ALPINE) {
+ /* if freq is close to mclk or mclk/2 select mclk
+ * as clock source
+ */
+ int divMCLK = cirrusfb_check_mclk(cinfo, freq);
+ if (divMCLK) {
+ nom = 0;
+ cirrusfb_set_mclk_as_source(cinfo, divMCLK);
+ }
+ }
+ if (nom) {
+ vga_wseq(regbase, CL_SEQRB, nom);
+ tmp = den << 1;
+ if (div != 0)
+ tmp |= 1;
- /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
- if ((cinfo->btype == BT_SD64) ||
- (cinfo->btype == BT_ALPINE) ||
- (cinfo->btype == BT_GD5480))
- tmp |= 0x80;
+ /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+ if ((cinfo->btype == BT_SD64) ||
+ (cinfo->btype == BT_ALPINE) ||
+ (cinfo->btype == BT_GD5480))
+ tmp |= 0x80;
- DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
- vga_wseq(regbase, CL_SEQR1B, tmp);
+ DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
+ vga_wseq(regbase, CL_SEQR1B, tmp);
+ }
- if (regs.VertRes >= 1024)
+ if (yres >= 1024)
/* 1280x1024 */
vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
else
@@ -1089,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
/* don't know if it would hurt to also program this if no interlaced */
/* mode is used, but I feel better this way.. :-) */
if (var->vmode & FB_VMODE_INTERLACED)
- vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
+ vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
else
vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
@@ -1263,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
- cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
/* We already set SRF and SR1F */
break;
@@ -1335,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
- if (regs.HorizRes >= 1024)
- vga_wseq(regbase, CL_SEQR7, 0xa7);
- else
- vga_wseq(regbase, CL_SEQR7, 0xa3);
- cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
+ vga_wseq(regbase, CL_SEQR7, 0xa7);
break;
case BT_GD5480:
@@ -1383,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
*/
else if (var->bits_per_pixel == 32) {
- DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
+ DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
switch (cinfo->btype) {
case BT_SD64:
/* Extended Sequencer Mode: 256c col. mode */
@@ -1417,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
vga_wseq(regbase, CL_SEQR7, 0xa9);
- cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
break;
case BT_GD5480:
@@ -1972,8 +1799,6 @@ static void init_vgachip(struct fb_info *info)
/* misc... */
WHDR(cinfo, 0); /* Hidden DAC register: - */
- printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
- info->screen_size);
DPRINTK("EXIT\n");
return;
}
@@ -2145,7 +1970,7 @@ static int release_io_ports;
* based on the DRAM bandwidth bit and DRAM bank switching bit. This
* works with 1MB, 2MB and 4MB configurations (which the Motorola boards
* seem to have. */
-static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
+static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
{
unsigned long mem;
unsigned char SRF;
@@ -2211,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev,
static void cirrusfb_pci_unmap(struct fb_info *info)
{
- struct cirrusfb_info *cinfo = info->par;
- struct pci_dev *pdev = cinfo->pdev;
+ struct pci_dev *pdev = to_pci_dev(info->device);
iounmap(info->screen_base);
#if 0 /* if system didn't claim this region, we would... */
@@ -2228,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info)
static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
- zorro_release_device(cinfo->zdev);
+ struct zorro_dev *zdev = to_zorro_dev(info->device);
+
+ zorro_release_device(zdev);
if (cinfo->btype == BT_PICASSO4) {
cinfo->regbase -= 0x600000;
iounmap((void *)cinfo->regbase);
iounmap(info->screen_base);
} else {
- if (zorro_resource_start(cinfo->zdev) > 0x01000000)
+ if (zorro_resource_start(zdev) > 0x01000000)
iounmap(info->screen_base);
}
}
#endif /* CONFIG_ZORRO */
-static int cirrusfb_set_fbinfo(struct fb_info *info)
+static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
struct fb_var_screeninfo *var = &info->var;
@@ -2258,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
if (cinfo->btype == BT_GD5480) {
if (var->bits_per_pixel == 16)
info->screen_base += 1 * MB_;
- if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
+ if (var->bits_per_pixel == 32)
info->screen_base += 2 * MB_;
}
@@ -2285,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
return 0;
}
-static int cirrusfb_register(struct fb_info *info)
+static int __devinit cirrusfb_register(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
int err;
@@ -2301,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info)
/* sanity checks */
assert(btype != BT_NONE);
+ /* set all the vital stuff */
+ cirrusfb_set_fbinfo(info);
+
DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
- /* Make pretend we've set the var so our structures are in a "good" */
- /* state, even though we haven't written the mode to the hw yet... */
- info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
+ err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+ if (!err) {
+ DPRINTK("wrong initial video mode\n");
+ err = -EINVAL;
+ goto err_dealloc_cmap;
+ }
+
info->var.activate = FB_ACTIVATE_NOW;
err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
if (err < 0) {
/* should never happen */
DPRINTK("choking on default var... umm, no good.\n");
- goto err_unmap_cirrusfb;
+ goto err_dealloc_cmap;
}
- /* set all the vital stuff */
- cirrusfb_set_fbinfo(info);
-
err = register_framebuffer(info);
if (err < 0) {
printk(KERN_ERR "cirrusfb: could not register "
@@ -2330,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info)
err_dealloc_cmap:
fb_dealloc_cmap(&info->cmap);
-err_unmap_cirrusfb:
cinfo->unmap(info);
framebuffer_release(info);
return err;
@@ -2353,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info)
}
#ifdef CONFIG_PCI
-static int cirrusfb_pci_register(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
@@ -2376,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
}
cinfo = info->par;
- cinfo->pdev = pdev;
cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
@@ -2482,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = {
#endif /* CONFIG_PCI */
#ifdef CONFIG_ZORRO
-static int cirrusfb_zorro_register(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
@@ -2512,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
assert(z);
assert(btype != BT_NONE);
- cinfo->zdev = z;
board_addr = zorro_resource_start(z);
board_size = zorro_resource_len(z);
info->screen_size = size;
@@ -2644,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) {
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt) continue;
+ if (!*this_opt)
+ continue;
DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
- for (i = 0; i < NUM_TOTAL_MODES; i++) {
- sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
- if (strcmp(this_opt, s) == 0)
- cirrusfb_def_mode = i;
- }
if (!strcmp(this_opt, "noaccel"))
noaccel = 1;
+ else if (!strncmp(this_opt, "mode:", 5))
+ mode_option = this_opt + 5;
+ else
+ mode_option = this_opt;
}
return 0;
}
@@ -2680,6 +2507,11 @@ static void __exit cirrusfb_exit(void)
module_init(cirrusfb_init);
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+
#ifdef MODULE
module_exit(cirrusfb_exit);
#endif
@@ -3073,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
* bestclock() - determine closest possible clock lower(?) than the
* desired pixel clock
**************************************************************************/
-static void bestclock(long freq, long *best, long *nom,
- long *den, long *div, long maxfreq)
+static void bestclock(long freq, int *nom, int *den, int *div)
{
- long n, h, d, f;
+ int n, d;
+ long h, diff;
- assert(best != NULL);
assert(nom != NULL);
assert(den != NULL);
assert(div != NULL);
- assert(maxfreq > 0);
*nom = 0;
*den = 0;
@@ -3093,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom,
if (freq < 8000)
freq = 8000;
- if (freq > maxfreq)
- freq = maxfreq;
-
- *best = 0;
- f = freq * 10;
+ diff = freq;
for (n = 32; n < 128; n++) {
- d = (143181 * n) / f;
+ int s = 0;
+
+ d = (14318 * n) / freq;
if ((d >= 7) && (d <= 63)) {
- if (d > 31)
- d = (d / 2) * 2;
- h = (14318 * n) / d;
- if (abs(h - freq) < abs(*best - freq)) {
- *best = h;
+ int temp = d;
+
+ if (temp > 31) {
+ s = 1;
+ temp >>= 1;
+ }
+ h = ((14318 * n) / temp) >> s;
+ h = h > freq ? h - freq : freq - h;
+ if (h < diff) {
+ diff = h;
*nom = n;
- if (d < 32) {
- *den = d;
- *div = 0;
- } else {
- *den = d / 2;
- *div = 1;
- }
+ *den = temp;
+ *div = s;
}
}
- d = DIV_ROUND_UP(143181 * n, f);
+ d++;
if ((d >= 7) && (d <= 63)) {
- if (d > 31)
- d = (d / 2) * 2;
- h = (14318 * n) / d;
- if (abs(h - freq) < abs(*best - freq)) {
- *best = h;
+ if (d > 31) {
+ s = 1;
+ d >>= 1;
+ }
+ h = ((14318 * n) / d) >> s;
+ h = h > freq ? h - freq : freq - h;
+ if (h < diff) {
+ diff = h;
*nom = n;
- if (d < 32) {
- *den = d;
- *div = 0;
- } else {
- *den = d / 2;
- *div = 1;
- }
+ *den = d;
+ *div = s;
}
}
}
DPRINTK("Best possible values for given frequency:\n");
- DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
+ DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n",
freq, *nom, *den, *div);
DPRINTK("EXIT\n");
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 06f87b04f20..2f50a80b413 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,22 +43,6 @@ config VGACON_SOFT_SCROLLBACK_SIZE
buffer. Each 64KB will give you approximately 16 80x25
screenfuls of scrollback buffer
-config VIDEO_SELECT
- bool "Video mode selection support"
- depends on X86 && VGA_CONSOLE
- ---help---
- This enables support for text mode selection on kernel startup. If
- you want to take advantage of some high-resolution text mode your
- card's BIOS offers, but the traditional Linux utilities like
- SVGATextMode don't, you can say Y here and set the mode using the
- "vga=" option from your boot loader (lilo or loadlin) or set
- "vga=ask" which brings up a video mode menu on kernel startup. (Try
- "man bootparam" or see the documentation of your boot loader about
- how to pass options to the kernel.)
-
- Read the file <file:Documentation/svga.txt> for more information
- about the Video mode selection support. If unsure, say N.
-
config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index c6299e8a041..64b3d30027b 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1855,8 +1855,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
- unsigned short saved_ec;
- int ret;
if (fbcon_is_inactive(vc, info))
return -EINVAL;
@@ -1869,11 +1867,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
* whole screen (prevents flicker).
*/
- saved_ec = vc->vc_video_erase_char;
- vc->vc_video_erase_char = vc->vc_scrl_erase_char;
-
- ret = 0;
-
switch (dir) {
case SM_UP:
if (count > vc->vc_rows) /* Maximum realistic size */
@@ -1890,9 +1883,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
(b - count)),
- vc->vc_scrl_erase_char,
+ vc->vc_video_erase_char,
vc->vc_size_row * count);
- ret = 1;
+ return 1;
break;
case SCROLL_WRAP_MOVE:
@@ -1962,10 +1955,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
(b - count)),
- vc->vc_scrl_erase_char,
+ vc->vc_video_erase_char,
vc->vc_size_row * count);
- ret = 1;
- break;
+ return 1;
}
break;
@@ -1982,9 +1974,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
t),
- vc->vc_scrl_erase_char,
+ vc->vc_video_erase_char,
vc->vc_size_row * count);
- ret = 1;
+ return 1;
break;
case SCROLL_WRAP_MOVE:
@@ -2052,15 +2044,12 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
t),
- vc->vc_scrl_erase_char,
+ vc->vc_video_erase_char,
vc->vc_size_row * count);
- ret = 1;
- break;
+ return 1;
}
- break;
}
- vc->vc_video_erase_char = saved_ec;
- return ret;
+ return 0;
}
@@ -2400,11 +2389,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
+ int ret = 1;
+
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
ops->cursor_flash = (!blank);
- if (fb_blank(info, blank))
+ if (info->fbops->fb_blank)
+ ret = info->fbops->fb_blank(blank, info);
+ if (ret)
fbcon_generic_blank(vc, info, blank);
}
@@ -2518,9 +2511,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
c = vc->vc_video_erase_char;
vc->vc_video_erase_char =
((c & 0xfe00) >> 1) | (c & 0xff);
- c = vc->vc_scrl_erase_char;
- vc->vc_scrl_erase_char =
- ((c & 0xFE00) >> 1) | (c & 0xFF);
vc->vc_attr >>= 1;
}
} else if (!vc->vc_hi_font_mask && cnt == 512) {
@@ -2551,14 +2541,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
if (vc->vc_can_do_color) {
vc->vc_video_erase_char =
((c & 0xff00) << 1) | (c & 0xff);
- c = vc->vc_scrl_erase_char;
- vc->vc_scrl_erase_char =
- ((c & 0xFF00) << 1) | (c & 0xFF);
vc->vc_attr <<= 1;
- } else {
+ } else
vc->vc_video_erase_char = c & ~0x100;
- vc->vc_scrl_erase_char = c & ~0x100;
- }
}
}
@@ -2992,8 +2977,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
p = &fb_display[vc->vc_num];
set_blitting_type(vc, info);
var_to_display(p, &info->var, info);
- cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
@@ -3588,8 +3573,8 @@ static int __init fb_console_init(void)
acquire_console_sem();
fb_register_client(&fbcon_event_notifier);
- fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
- NULL, "fbcon");
+ fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
+ "fbcon");
if (IS_ERR(fbcon_device)) {
printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index a6e38e9ea73..89a346880ec 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -110,7 +110,7 @@ static inline int mono_col(const struct fb_info *info)
__u32 max_len;
max_len = max(info->var.green.length, info->var.red.length);
max_len = max(info->var.blue.length, max_len);
- return ~(0xfff << (max_len & 0xff));
+ return (~(0xfff << max_len)) & 0xff;
}
static inline int attr_col_ec(int shift, struct vc_data *vc,
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 9901064199b..dd3eaaad444 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -533,7 +533,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
{
- u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
+ u16 eattr = mda_convert_attr(c->vc_video_erase_char);
if (!lines)
return 0;
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 4055dbdd1b4..491c1c1baf4 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
switch (dir) {
case SM_UP:
sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
- sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+ sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
break;
case SM_DOWN:
sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
- sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+ sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
break;
}
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index bd1f57b259d..448d209a0bf 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -239,8 +239,7 @@ static void vgacon_restore_screen(struct vc_data *c)
static int vgacon_scrolldelta(struct vc_data *c, int lines)
{
- int start, end, count, soff, diff;
- void *d, *s;
+ int start, end, count, soff;
if (!lines) {
c->vc_visible_origin = c->vc_origin;
@@ -287,29 +286,29 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
if (count > c->vc_rows)
count = c->vc_rows;
- diff = c->vc_rows - count;
+ if (count) {
+ int copysize;
- d = (void *) c->vc_origin;
- s = (void *) c->vc_screenbuf;
+ int diff = c->vc_rows - count;
+ void *d = (void *) c->vc_origin;
+ void *s = (void *) c->vc_screenbuf;
- while (count--) {
- scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
- d += c->vc_size_row;
- soff += c->vc_size_row;
+ count *= c->vc_size_row;
+ /* how much memory to end of buffer left? */
+ copysize = min(count, vgacon_scrollback_size - soff);
+ scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+ d += copysize;
+ count -= copysize;
- if (soff >= vgacon_scrollback_size)
- soff = 0;
- }
+ if (count) {
+ scr_memcpyw(d, vgacon_scrollback, count);
+ d += count;
+ }
- if (diff == c->vc_rows) {
+ if (diff)
+ scr_memcpyw(d, s, diff * c->vc_size_row);
+ } else
vgacon_cursor(c, CM_MOVE);
- } else {
- while (diff--) {
- scr_memcpyw(d, s, c->vc_size_row);
- d += c->vc_size_row;
- s += c->vc_size_row;
- }
- }
return 1;
}
@@ -1350,7 +1349,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
} else
c->vc_origin += delta;
scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
- delta), c->vc_scrl_erase_char,
+ delta), c->vc_video_erase_char,
delta);
} else {
if (oldo - delta < vga_vram_base) {
@@ -1363,7 +1362,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
} else
c->vc_origin -= delta;
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
- scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
+ scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
delta);
}
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
index 6ef800bdf48..4830b1bf51e 100644
--- a/drivers/video/display/display-sysfs.c
+++ b/drivers/video/display/display-sysfs.c
@@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
mutex_unlock(&allocated_dsp_lock);
if (!ret) {
- new_dev->dev = device_create_drvdata(display_class,
- parent,
- MKDEV(0,0),
- new_dev,
- "display%d",
- new_dev->idx);
+ new_dev->dev = device_create(display_class, parent,
+ MKDEV(0, 0), new_dev,
+ "display%d", new_dev->idx);
if (!IS_ERR(new_dev->dev)) {
new_dev->parent = parent;
new_dev->driver = driver;
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index bd779ae44b1..daf9b81878a 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -12,6 +12,7 @@
#include <linux/fb.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
+#include <linux/dmi.h>
#include <video/vga.h>
@@ -33,6 +34,105 @@ static struct fb_fix_screeninfo efifb_fix __initdata = {
.visual = FB_VISUAL_TRUECOLOR,
};
+enum {
+ M_I17, /* 17-Inch iMac */
+ M_I20, /* 20-Inch iMac */
+ M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
+ M_I24, /* 24-Inch iMac */
+ M_MINI, /* Mac Mini */
+ M_MB, /* MacBook */
+ M_MB_2, /* MacBook, 2nd rev. */
+ M_MB_3, /* MacBook, 3rd rev. */
+ M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
+ M_MBA, /* MacBook Air */
+ M_MBP, /* MacBook Pro */
+ M_MBP_2, /* MacBook Pro 2nd gen */
+ M_MBP_SR, /* MacBook Pro (Santa Rosa) */
+ M_MBP_4, /* MacBook Pro, 4th gen */
+ M_UNKNOWN /* placeholder */
+};
+
+static struct efifb_dmi_info {
+ char *optname;
+ unsigned long base;
+ int stride;
+ int width;
+ int height;
+} dmi_list[] = {
+ [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
+ [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
+ [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
+ [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
+ [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
+ [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
+ [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
+ [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
+ [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
+ [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
+ [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
+ [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
+};
+
+static int set_system(const struct dmi_system_id *id);
+
+#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
+ { set_system, name, { \
+ DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
+ DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
+ &dmi_list[enumid] }
+
+static struct dmi_system_id __initdata dmi_system_table[] = {
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
+ /* At least one of these two will be right; maybe both? */
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
+ /* At least one of these two will be right; maybe both? */
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
+ /* At least one of these two will be right; maybe both? */
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
+ /* At least one of these two will be right; maybe both? */
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
+ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
+ {},
+};
+
+static int set_system(const struct dmi_system_id *id)
+{
+ struct efifb_dmi_info *info = id->driver_data;
+ if (info->base == 0)
+ return -ENODEV;
+
+ printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
+ "(%dx%d, stride %d)\n", id->ident,
+ (void *)info->base, info->width, info->height,
+ info->stride);
+
+ /* Trust the bootloader over the DMI tables */
+ if (screen_info.lfb_base == 0)
+ screen_info.lfb_base = info->base;
+ if (screen_info.lfb_linelength == 0)
+ screen_info.lfb_linelength = info->stride;
+ if (screen_info.lfb_width == 0)
+ screen_info.lfb_width = info->width;
+ if (screen_info.lfb_height == 0)
+ screen_info.lfb_height = info->height;
+
+ return 0;
+}
+
static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
@@ -67,6 +167,38 @@ static struct fb_ops efifb_ops = {
.fb_imageblit = cfb_imageblit,
};
+static int __init efifb_setup(char *options)
+{
+ char *this_opt;
+ int i;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt) continue;
+
+ for (i = 0; i < M_UNKNOWN; i++) {
+ if (!strcmp(this_opt, dmi_list[i].optname) &&
+ dmi_list[i].base != 0) {
+ screen_info.lfb_base = dmi_list[i].base;
+ screen_info.lfb_linelength = dmi_list[i].stride;
+ screen_info.lfb_width = dmi_list[i].width;
+ screen_info.lfb_height = dmi_list[i].height;
+ }
+ }
+ if (!strncmp(this_opt, "base:", 5))
+ screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "stride:", 7))
+ screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
+ else if (!strncmp(this_opt, "height:", 7))
+ screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
+ else if (!strncmp(this_opt, "width:", 6))
+ screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
+ }
+ return 0;
+}
+
static int __init efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@@ -74,6 +206,26 @@ static int __init efifb_probe(struct platform_device *dev)
unsigned int size_vmode;
unsigned int size_remap;
unsigned int size_total;
+ int request_succeeded = 0;
+
+ printk(KERN_INFO "efifb: probing for efifb\n");
+
+ if (!screen_info.lfb_depth)
+ screen_info.lfb_depth = 32;
+ if (!screen_info.pages)
+ screen_info.pages = 1;
+
+ /* just assume they're all unset if any are */
+ if (!screen_info.blue_size) {
+ screen_info.blue_size = 8;
+ screen_info.blue_pos = 0;
+ screen_info.green_size = 8;
+ screen_info.green_pos = 8;
+ screen_info.red_size = 8;
+ screen_info.red_pos = 16;
+ screen_info.rsvd_size = 8;
+ screen_info.rsvd_pos = 24;
+ }
efifb_fix.smem_start = screen_info.lfb_base;
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
@@ -98,21 +250,25 @@ static int __init efifb_probe(struct platform_device *dev)
* option to simply use size_total as that
* wastes plenty of kernel address space. */
size_remap = size_vmode * 2;
- if (size_remap < size_vmode)
- size_remap = size_vmode;
if (size_remap > size_total)
size_remap = size_total;
+ if (size_remap % PAGE_SIZE)
+ size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
efifb_fix.smem_len = size_remap;
- if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb"))
+ if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
+ request_succeeded = 1;
+ } else {
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
printk(KERN_WARNING
"efifb: cannot reserve video memory at 0x%lx\n",
efifb_fix.smem_start);
+ }
info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
if (!info) {
+ printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
err = -ENOMEM;
goto err_release_mem;
}
@@ -125,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev)
"0x%x @ 0x%lx\n",
efifb_fix.smem_len, efifb_fix.smem_start);
err = -EIO;
- goto err_unmap;
+ goto err_release_fb;
}
printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
@@ -178,25 +334,27 @@ static int __init efifb_probe(struct platform_device *dev)
info->fix = efifb_fix;
info->flags = FBINFO_FLAG_DEFAULT;
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
- err = -ENOMEM;
+ if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
+ printk(KERN_ERR "efifb: cannot allocate colormap\n");
goto err_unmap;
}
- if (register_framebuffer(info) < 0) {
- err = -EINVAL;
+ if ((err = register_framebuffer(info)) < 0) {
+ printk(KERN_ERR "efifb: cannot register framebuffer\n");
goto err_fb_dealoc;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
- info->node, info->fix.id);
+ info->node, info->fix.id);
return 0;
err_fb_dealoc:
fb_dealloc_cmap(&info->cmap);
err_unmap:
iounmap(info->screen_base);
+err_release_fb:
framebuffer_release(info);
err_release_mem:
- release_mem_region(efifb_fix.smem_start, size_total);
+ if (request_succeeded)
+ release_mem_region(efifb_fix.smem_start, size_total);
return err;
}
@@ -214,9 +372,22 @@ static struct platform_device efifb_device = {
static int __init efifb_init(void)
{
int ret;
+ char *option = NULL;
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return -ENODEV;
+ dmi_check_system(dmi_system_table);
+
+ if (fb_get_options("efifb", &option))
+ return -ENODEV;
+ efifb_setup(option);
+
+ /* We don't get linelength from UGA Draw Protocol, only from
+ * EFI Graphics Protocol. So if it's not in DMI, and it's not
+ * passed in from the user, we really can't use the framebuffer.
+ */
+ if (!screen_info.lfb_linelength)
+ return -ENODEV;
ret = platform_driver_register(&efifb_driver);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 98843c2ecf7..217c5118ae9 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -28,9 +28,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
@@ -837,13 +835,6 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
return (cnt) ? cnt : err;
}
-#ifdef CONFIG_KMOD
-static void try_to_load(int fb)
-{
- request_module("fb%d", fb);
-}
-#endif /* CONFIG_KMOD */
-
int
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
{
@@ -979,6 +970,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
+ event.data = &mode;
fb_notifier_call_chain(evnt, &event);
}
}
@@ -1085,10 +1077,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EINVAL;
if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
return -EINVAL;
-#ifdef CONFIG_KMOD
if (!registered_fb[con2fb.framebuffer])
- try_to_load(con2fb.framebuffer);
-#endif /* CONFIG_KMOD */
+ request_module("fb%d", con2fb.framebuffer);
if (!registered_fb[con2fb.framebuffer])
return -EINVAL;
event.info = info;
@@ -1326,10 +1316,8 @@ fb_open(struct inode *inode, struct file *file)
if (fbidx >= FB_MAX)
return -ENODEV;
lock_kernel();
-#ifdef CONFIG_KMOD
if (!(info = registered_fb[fbidx]))
- try_to_load(fbidx);
-#endif /* CONFIG_KMOD */
+ request_module("fb%d", fbidx);
if (!(info = registered_fb[fbidx])) {
res = -ENODEV;
goto out;
@@ -1442,9 +1430,8 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
- MKDEV(FB_MAJOR, i), NULL,
- "fb%d", i);
+ fb_info->dev = device_create(fb_class, fb_info->device,
+ MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 6a0aa180c26..5c1a2c01778 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -564,7 +564,13 @@ static void get_detailed_timing(unsigned char *block,
mode->sync |= FB_SYNC_VERT_HIGH_ACT;
mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
(V_ACTIVE + V_BLANKING));
- mode->vmode = 0;
+ if (INTERLACED) {
+ mode->yres *= 2;
+ mode->upper_margin *= 2;
+ mode->lower_margin *= 2;
+ mode->vsync_len *= 2;
+ mode->vmode |= FB_VMODE_INTERLACED;
+ }
mode->flag = FB_MODE_IS_DETAILED;
DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 7992b13ee68..9dbb9646081 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -1042,7 +1042,7 @@ static int __devexit ffb_remove(struct of_device *op)
return 0;
}
-static struct of_device_id ffb_match[] = {
+static const struct of_device_id ffb_match[] = {
{
.name = "SUNW,ffb",
},
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
index 9366ef2bb5f..e69de29bb2d 100644
--- a/drivers/video/imacfb.c
+++ b/drivers/video/imacfb.c
@@ -1,376 +0,0 @@
-/*
- * framebuffer driver for Intel Based Mac's
- *
- * (c) 2006 Edgar Hucek <gimli@dark-green.com>
- * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/screen_info.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/dmi.h>
-#include <linux/efi.h>
-
-#include <asm/io.h>
-
-#include <video/vga.h>
-
-typedef enum _MAC_TYPE {
- M_I17,
- M_I20,
- M_MINI,
- M_MACBOOK,
- M_UNKNOWN
-} MAC_TYPE;
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo imacfb_defined __initdata = {
- .activate = FB_ACTIVATE_NOW,
- .height = -1,
- .width = -1,
- .right_margin = 32,
- .upper_margin = 16,
- .lower_margin = 4,
- .vsync_len = 4,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo imacfb_fix __initdata = {
- .id = "IMAC VGA",
- .type = FB_TYPE_PACKED_PIXELS,
- .accel = FB_ACCEL_NONE,
- .visual = FB_VISUAL_TRUECOLOR,
-};
-
-static int inverse;
-static int model = M_UNKNOWN;
-static int manual_height;
-static int manual_width;
-
-static int set_system(const struct dmi_system_id *id)
-{
- printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
- id->ident, (long)id->driver_data);
-
- model = (long)id->driver_data;
-
- return 0;
-}
-
-static struct dmi_system_id __initdata dmi_system_table[] = {
- { set_system, "iMac4,1", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
- { set_system, "MacBookPro1,1", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
- { set_system, "MacBook1,1", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
- { set_system, "Macmini1,1", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
- {},
-};
-
-#define DEFAULT_FB_MEM 1024*1024*16
-
-/* --------------------------------------------------------------------- */
-
-static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- /*
- * Set a single color register. The values supplied are
- * already rounded down to the hardware's capabilities
- * (according to the entries in the `var' structure). Return
- * != 0 for invalid regno.
- */
-
- if (regno >= info->cmap.len)
- return 1;
-
- if (regno < 16) {
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- }
- return 0;
-}
-
-static struct fb_ops imacfb_ops = {
- .owner = THIS_MODULE,
- .fb_setcolreg = imacfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
-
-static int __init imacfb_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt) continue;
-
- if (!strcmp(this_opt, "inverse"))
- inverse = 1;
- else if (!strcmp(this_opt, "i17"))
- model = M_I17;
- else if (!strcmp(this_opt, "i20"))
- model = M_I20;
- else if (!strcmp(this_opt, "mini"))
- model = M_MINI;
- else if (!strcmp(this_opt, "macbook"))
- model = M_MACBOOK;
- else if (!strncmp(this_opt, "height:", 7))
- manual_height = simple_strtoul(this_opt+7, NULL, 0);
- else if (!strncmp(this_opt, "width:", 6))
- manual_width = simple_strtoul(this_opt+6, NULL, 0);
- }
- return 0;
-}
-
-static int __init imacfb_probe(struct platform_device *dev)
-{
- struct fb_info *info;
- int err;
- unsigned int size_vmode;
- unsigned int size_remap;
- unsigned int size_total;
-
- screen_info.lfb_depth = 32;
- screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
- screen_info.pages=1;
- screen_info.blue_size = 8;
- screen_info.blue_pos = 0;
- screen_info.green_size = 8;
- screen_info.green_pos = 8;
- screen_info.red_size = 8;
- screen_info.red_pos = 16;
- screen_info.rsvd_size = 8;
- screen_info.rsvd_pos = 24;
-
- switch (model) {
- case M_I17:
- screen_info.lfb_width = 1440;
- screen_info.lfb_height = 900;
- screen_info.lfb_linelength = 1472 * 4;
- screen_info.lfb_base = 0x80010000;
- break;
- case M_I20:
- screen_info.lfb_width = 1680;
- screen_info.lfb_height = 1050;
- screen_info.lfb_linelength = 1728 * 4;
- screen_info.lfb_base = 0x80010000;
- break;
- case M_MINI:
- screen_info.lfb_width = 1024;
- screen_info.lfb_height = 768;
- screen_info.lfb_linelength = 2048 * 4;
- screen_info.lfb_base = 0x80000000;
- break;
- case M_MACBOOK:
- screen_info.lfb_width = 1280;
- screen_info.lfb_height = 800;
- screen_info.lfb_linelength = 2048 * 4;
- screen_info.lfb_base = 0x80000000;
- break;
- }
-
- /* if the user wants to manually specify height/width,
- we will override the defaults */
- /* TODO: eventually get auto-detection working */
- if (manual_height > 0)
- screen_info.lfb_height = manual_height;
- if (manual_width > 0)
- screen_info.lfb_width = manual_width;
-
- imacfb_fix.smem_start = screen_info.lfb_base;
- imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
- imacfb_defined.xres = screen_info.lfb_width;
- imacfb_defined.yres = screen_info.lfb_height;
- imacfb_fix.line_length = screen_info.lfb_linelength;
-
- /* size_vmode -- that is the amount of memory needed for the
- * used video mode, i.e. the minimum amount of
- * memory we need. */
- size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
-
- /* size_total -- all video memory we have. Used for
- * entries, ressource allocation and bounds
- * checking. */
- size_total = screen_info.lfb_size * 65536;
- if (size_total < size_vmode)
- size_total = size_vmode;
-
- /* size_remap -- the amount of video memory we are going to
- * use for imacfb. With modern cards it is no
- * option to simply use size_total as that
- * wastes plenty of kernel address space. */
- size_remap = size_vmode * 2;
- if (size_remap < size_vmode)
- size_remap = size_vmode;
- if (size_remap > size_total)
- size_remap = size_total;
- imacfb_fix.smem_len = size_remap;
-
- if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
- printk(KERN_WARNING
- "imacfb: cannot reserve video memory at 0x%lx\n",
- imacfb_fix.smem_start);
- /* We cannot make this fatal. Sometimes this comes from magic
- spaces our resource handlers simply don't know about */
- }
-
- info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
- if (!info) {
- err = -ENOMEM;
- goto err_release_mem;
- }
- info->pseudo_palette = info->par;
- info->par = NULL;
-
- info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR "imacfb: abort, cannot ioremap video memory "
- "0x%x @ 0x%lx\n",
- imacfb_fix.smem_len, imacfb_fix.smem_start);
- err = -EIO;
- goto err_unmap;
- }
-
- printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
- "using %dk, total %dk\n",
- imacfb_fix.smem_start, info->screen_base,
- size_remap/1024, size_total/1024);
- printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
- imacfb_defined.xres, imacfb_defined.yres,
- imacfb_defined.bits_per_pixel, imacfb_fix.line_length,
- screen_info.pages);
-
- imacfb_defined.xres_virtual = imacfb_defined.xres;
- imacfb_defined.yres_virtual = imacfb_fix.smem_len /
- imacfb_fix.line_length;
- printk(KERN_INFO "imacfb: scrolling: redraw\n");
- imacfb_defined.yres_virtual = imacfb_defined.yres;
-
- /* some dummy values for timing to make fbset happy */
- imacfb_defined.pixclock = 10000000 / imacfb_defined.xres *
- 1000 / imacfb_defined.yres;
- imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8;
- imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8;
-
- imacfb_defined.red.offset = screen_info.red_pos;
- imacfb_defined.red.length = screen_info.red_size;
- imacfb_defined.green.offset = screen_info.green_pos;
- imacfb_defined.green.length = screen_info.green_size;
- imacfb_defined.blue.offset = screen_info.blue_pos;
- imacfb_defined.blue.length = screen_info.blue_size;
- imacfb_defined.transp.offset = screen_info.rsvd_pos;
- imacfb_defined.transp.length = screen_info.rsvd_size;
-
- printk(KERN_INFO "imacfb: %s: "
- "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
- "Truecolor",
- screen_info.rsvd_size,
- screen_info.red_size,
- screen_info.green_size,
- screen_info.blue_size,
- screen_info.rsvd_pos,
- screen_info.red_pos,
- screen_info.green_pos,
- screen_info.blue_pos);
-
- imacfb_fix.ypanstep = 0;
- imacfb_fix.ywrapstep = 0;
-
- /* request failure does not faze us, as vgacon probably has this
- * region already (FIXME) */
- request_region(0x3c0, 32, "imacfb");
-
- info->fbops = &imacfb_ops;
- info->var = imacfb_defined;
- info->fix = imacfb_fix;
- info->flags = FBINFO_FLAG_DEFAULT;
-
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
- err = -ENOMEM;
- goto err_unmap;
- }
- if (register_framebuffer(info)<0) {
- err = -EINVAL;
- goto err_fb_dealoc;
- }
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- info->node, info->fix.id);
- return 0;
-
-err_fb_dealoc:
- fb_dealloc_cmap(&info->cmap);
-err_unmap:
- iounmap(info->screen_base);
- framebuffer_release(info);
-err_release_mem:
- release_mem_region(imacfb_fix.smem_start, size_total);
- return err;
-}
-
-static struct platform_driver imacfb_driver = {
- .probe = imacfb_probe,
- .driver = {
- .name = "imacfb",
- },
-};
-
-static struct platform_device imacfb_device = {
- .name = "imacfb",
-};
-
-static int __init imacfb_init(void)
-{
- int ret;
- char *option = NULL;
-
- if (!efi_enabled)
- return -ENODEV;
- if (!dmi_check_system(dmi_system_table))
- return -ENODEV;
- if (model == M_UNKNOWN)
- return -ENODEV;
-
- if (fb_get_options("imacfb", &option))
- return -ENODEV;
-
- imacfb_setup(option);
- ret = platform_driver_register(&imacfb_driver);
-
- if (!ret) {
- ret = platform_device_register(&imacfb_device);
- if (ret)
- platform_driver_unregister(&imacfb_driver);
- }
- return ret;
-}
-module_init(imacfb_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 3325fbd68ab..a50bea61480 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -12,9 +12,9 @@
#endif
/*** Version/name ***/
-#define INTELFB_VERSION "0.9.5"
+#define INTELFB_VERSION "0.9.6"
#define INTELFB_MODULE_NAME "intelfb"
-#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
+#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
/*** Debug/feature defines ***/
@@ -58,6 +58,7 @@
#define PCI_DEVICE_ID_INTEL_915GM 0x2592
#define PCI_DEVICE_ID_INTEL_945G 0x2772
#define PCI_DEVICE_ID_INTEL_945GM 0x27A2
+#define PCI_DEVICE_ID_INTEL_945GME 0x27AE
#define PCI_DEVICE_ID_INTEL_965G 0x29A2
#define PCI_DEVICE_ID_INTEL_965GM 0x2A02
@@ -160,6 +161,7 @@ enum intel_chips {
INTEL_915GM,
INTEL_945G,
INTEL_945GM,
+ INTEL_945GME,
INTEL_965G,
INTEL_965GM,
};
@@ -363,6 +365,7 @@ struct intelfb_info {
((dinfo)->chipset == INTEL_915GM) || \
((dinfo)->chipset == INTEL_945G) || \
((dinfo)->chipset == INTEL_945GM) || \
+ ((dinfo)->chipset == INTEL_945GME) || \
((dinfo)->chipset == INTEL_965G) || \
((dinfo)->chipset == INTEL_965GM))
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index fcf9fadbf57..5d896b81f4e 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
/* has some LVDS + tv-out */
case INTEL_945G:
case INTEL_945GM:
+ case INTEL_945GME:
case INTEL_965G:
case INTEL_965GM:
/* SDVO ports have a single control bus - 2 devices */
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index e44303f9bc5..a09e2364935 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -2,7 +2,7 @@
* intelfb
*
* Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
- * 945G/945GM/965G/965GM integrated graphics chips.
+ * 945G/945GM/945GME/965G/965GM integrated graphics chips.
*
* Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
* 2004 Sylvain Meyer
@@ -102,6 +102,9 @@
*
* 04/2008 - Version 0.9.5
* Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
+ *
+ * 08/2008 - Version 0.9.6
+ * Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
*/
#include <linux/module.h>
@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
{ 0, }
@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
(ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
(ent->device == PCI_DEVICE_ID_INTEL_945G) ||
(ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
+ (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
(ent->device == PCI_DEVICE_ID_INTEL_965G) ||
(ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 8e6d6a4db0a..8b26b27c2db 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
dinfo->mobile = 1;
dinfo->pll_index = PLLS_I9xx;
return 0;
+ case PCI_DEVICE_ID_INTEL_945GME:
+ dinfo->name = "Intel(R) 945GME";
+ dinfo->chipset = INTEL_945GME;
+ dinfo->mobile = 1;
+ dinfo->pll_index = PLLS_I9xx;
+ return 0;
case PCI_DEVICE_ID_INTEL_965G:
dinfo->name = "Intel(R) 965G";
dinfo->chipset = INTEL_965G;
@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
case PCI_DEVICE_ID_INTEL_915GM:
case PCI_DEVICE_ID_INTEL_945G:
case PCI_DEVICE_ID_INTEL_945GM:
+ case PCI_DEVICE_ID_INTEL_945GME:
case PCI_DEVICE_ID_INTEL_965G:
case PCI_DEVICE_ID_INTEL_965GM:
/* 915, 945 and 965 chipsets support a 256MB aperture.
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 13fea61d6ae..7c7e8c2da9d 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *);
static int leo_mmap(struct fb_info *, struct vm_area_struct *);
static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
* Frame buffer operations
@@ -42,6 +43,7 @@ static struct fb_ops leo_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = leo_setcolreg,
.fb_blank = leo_blank,
+ .fb_pan_display = leo_pan_display,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
@@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
return;
}
+static void leo_switch_from_graph(struct fb_info *info)
+{
+ struct leo_par *par = (struct leo_par *) info->par;
+ struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
+ struct leo_cursor __iomem *cursor = par->cursor;
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&par->lock, flags);
+
+ par->extent = ((info->var.xres - 1) |
+ ((info->var.yres - 1) << 16));
+
+ sbus_writel(0xffffffff, &ss->wid);
+ sbus_writel(0xffff, &ss->wmask);
+ sbus_writel(0, &ss->vclipmin);
+ sbus_writel(par->extent, &ss->vclipmax);
+ sbus_writel(0, &ss->fg);
+ sbus_writel(0xff000000, &ss->planemask);
+ sbus_writel(0x310850, &ss->rop);
+ sbus_writel(0, &ss->widclip);
+ sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
+ &par->lc_ss0_usr->extent);
+ sbus_writel(4, &par->lc_ss0_usr->addrspace);
+ sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
+ sbus_writel(0, &par->lc_ss0_usr->fontt);
+ do {
+ val = sbus_readl(&par->lc_ss0_usr->csr);
+ } while (val & 0x20000000);
+
+ /* setup screen buffer for cfb_* functions */
+ sbus_writel(1, &ss->wid);
+ sbus_writel(0x00ffffff, &ss->planemask);
+ sbus_writel(0x310b90, &ss->rop);
+ sbus_writel(0, &par->lc_ss0_usr->addrspace);
+
+ /* hide cursor */
+ sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
+
+ spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ /* We just use this to catch switches out of
+ * graphics mode.
+ */
+ leo_switch_from_graph(info);
+
+ if (var->xoffset || var->yoffset || var->vmode)
+ return -EINVAL;
+ return 0;
+}
+
/**
* leo_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
@@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info)
leo_wid_put(info, &wl);
}
-static void leo_switch_from_graph(struct fb_info *info)
-{
- struct leo_par *par = (struct leo_par *) info->par;
- struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
- unsigned long flags;
- u32 val;
-
- spin_lock_irqsave(&par->lock, flags);
-
- par->extent = ((info->var.xres - 1) |
- ((info->var.yres - 1) << 16));
-
- sbus_writel(0xffffffff, &ss->wid);
- sbus_writel(0xffff, &ss->wmask);
- sbus_writel(0, &ss->vclipmin);
- sbus_writel(par->extent, &ss->vclipmax);
- sbus_writel(0, &ss->fg);
- sbus_writel(0xff000000, &ss->planemask);
- sbus_writel(0x310850, &ss->rop);
- sbus_writel(0, &ss->widclip);
- sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
- &par->lc_ss0_usr->extent);
- sbus_writel(4, &par->lc_ss0_usr->addrspace);
- sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
- sbus_writel(0, &par->lc_ss0_usr->fontt);
- do {
- val = sbus_readl(&par->lc_ss0_usr->csr);
- } while (val & 0x20000000);
-
- /* setup screen buffer for cfb_* functions */
- sbus_writel(1, &ss->wid);
- sbus_writel(0x00ffffff, &ss->planemask);
- sbus_writel(0x310b90, &ss->rop);
- sbus_writel(0, &par->lc_ss0_usr->addrspace);
-
- spin_unlock_irqrestore(&par->lock, flags);
-}
-
static void leo_init_hw(struct fb_info *info)
{
struct leo_par *par = (struct leo_par *) info->par;
@@ -641,7 +659,7 @@ static int __devexit leo_remove(struct of_device *op)
return 0;
}
-static struct of_device_id leo_match[] = {
+static const struct of_device_id leo_match[] = {
{
.name = "SUNW,leo",
},
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index c0213620279..8e7a275df50 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1453,6 +1453,13 @@ static struct board {
MGA_G100,
&vbG100,
"MGA-G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, 0xFF,
+ 0, 0,
+ DEVF_G200,
+ 230000,
+ MGA_G200,
+ &vbG200,
+ "MGA-G200eV (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
0, 0,
DEVF_G200,
@@ -2118,6 +2125,8 @@ static struct pci_device_id matroxfb_devices[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038a1b3..df1f757a616 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -40,29 +40,63 @@
#include <asm/unaligned.h>
-
-#define DEBUG 1
-#ifdef DEBUG
-#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
-#else
-#define DPRINTK(f, a...)
-#endif
-
-
/* Display specific information */
#define DPY_W 832
#define DPY_H 622
+static int user_wfm_size;
+
/* frame differs from image. frame includes non-visible pixels */
struct epd_frame {
int fw; /* frame width */
int fh; /* frame height */
+ u16 config[4];
+ int wfm_size;
};
static struct epd_frame epd_frame_table[] = {
{
- .fw = 832,
- .fh = 622
+ .fw = 832,
+ .fh = 622,
+ .config = {
+ 15 /* sdlew */
+ | 2 << 8 /* sdosz */
+ | 0 << 11 /* sdor */
+ | 0 << 12 /* sdces */
+ | 0 << 15, /* sdcer */
+ 42 /* gdspl */
+ | 1 << 8 /* gdr1 */
+ | 1 << 9 /* sdshr */
+ | 0 << 15, /* gdspp */
+ 18 /* gdspw */
+ | 0 << 15, /* dispc */
+ 599 /* vdlc */
+ | 0 << 11 /* dsi */
+ | 0 << 12, /* dsic */
+ },
+ .wfm_size = 47001,
+ },
+ {
+ .fw = 1088,
+ .fh = 791,
+ .config = {
+ 0x0104,
+ 0x031f,
+ 0x0088,
+ 0x02ff,
+ },
+ .wfm_size = 46770,
+ },
+ {
+ .fw = 1200,
+ .fh = 842,
+ .config = {
+ 0x0101,
+ 0x030e,
+ 0x0012,
+ 0x0280,
+ },
+ .wfm_size = 46770,
},
};
@@ -134,9 +168,8 @@ static u16 calc_img_cksum(u16 *start, int length)
}
/* here we decode the incoming waveform file and populate metromem */
-#define EXP_WFORM_SIZE 47001
-static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
- u8 *frame_count)
+static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
+ struct metronomefb_par *par)
{
int tta;
int wmta;
@@ -148,26 +181,31 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
int wfm_idx, owfm_idx;
int mem_idx = 0;
struct waveform_hdr *wfm_hdr;
+ u8 *metromem = par->metromem_wfm;
+ struct device *dev = par->info->dev;
- if (size != EXP_WFORM_SIZE) {
- printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
- EXP_WFORM_SIZE);
+ if (user_wfm_size)
+ epd_frame_table[par->dt].wfm_size = user_wfm_size;
+
+ if (size != epd_frame_table[par->dt].wfm_size) {
+ dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
+ epd_frame_table[par->dt].wfm_size);
return -EINVAL;
}
wfm_hdr = (struct waveform_hdr *) mem;
if (wfm_hdr->fvsn != 1) {
- printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
+ dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
return -EINVAL;
}
if (wfm_hdr->luts != 0) {
- printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
+ dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
return -EINVAL;
}
cksum = calc_cksum(32, 47, mem);
if (cksum != wfm_hdr->wfm_cs) {
- printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
+ dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
wfm_hdr->wfm_cs);
return -EINVAL;
}
@@ -175,7 +213,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
wfm_hdr->trc += 1;
for (i = 0; i < 5; i++) {
if (*(wfm_hdr->stuff2a + i) != 0) {
- printk(KERN_ERR "Error: unexpected value in padding\n");
+ dev_err(dev, "Error: unexpected value in padding\n");
return -EINVAL;
}
}
@@ -200,7 +238,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad temperature range table cksum"
+ dev_err(dev, "Error: bad temperature range table cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -212,7 +250,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad mode table address cksum"
+ dev_err(dev, "Error: bad mode table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -224,7 +262,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad temperature table address cksum"
+ dev_err(dev, "Error: bad temperature table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -259,11 +297,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(owfm_idx, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad waveform data cksum"
+ dev_err(dev, "Error: bad waveform data cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
- *frame_count = (mem_idx/64);
+ par->frame_count = (mem_idx/64);
return 0;
}
@@ -274,15 +312,12 @@ static int metronome_display_cmd(struct metronomefb_par *par)
u16 cs;
u16 opcode;
static u8 borderval;
- u8 *ptr;
/* setup display command
we can't immediately set the opcode since the controller
will try parse the command before we've set it all up
so we just set cs here and set the opcode at the end */
- ptr = par->metromem;
-
if (par->metromem_cmd->opcode == 0xCC40)
opcode = cs = 0xCC41;
else
@@ -335,44 +370,17 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
static int __devinit metronome_config_cmd(struct metronomefb_par *par)
{
- int i;
- u16 cs;
-
/* setup config command
we can't immediately set the opcode since the controller
- will try parse the command before we've set it all up
- so we just set cs here and set the opcode at the end */
-
- cs = 0xCC10;
-
- /* set the 12 args ( 8 bytes ) for config. see spec for meanings */
- i = 0;
- par->metromem_cmd->args[i] = 15 /* sdlew */
- | 2 << 8 /* sdosz */
- | 0 << 11 /* sdor */
- | 0 << 12 /* sdces */
- | 0 << 15; /* sdcer */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 42 /* gdspl */
- | 1 << 8 /* gdr1 */
- | 1 << 9 /* sdshr */
- | 0 << 15; /* gdspp */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 18 /* gdspw */
- | 0 << 15; /* dispc */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 599 /* vdlc */
- | 0 << 11 /* dsi */
- | 0 << 12; /* dsic */
- cs += par->metromem_cmd->args[i++];
+ will try parse the command before we've set it all up */
+ memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
+ sizeof(epd_frame_table[par->dt].config));
/* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+ memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
- par->metromem_cmd->csum = cs;
+ par->metromem_cmd->csum = 0xCC10;
+ par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
par->metromem_cmd->opcode = 0xCC10; /* config cmd */
return par->board->met_wait_event(par);
@@ -408,12 +416,9 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
{
int res;
- par->board->init_gpio_regs(par);
-
- par->board->init_lcdc_regs(par);
-
- /* now that lcd is setup, setup dma descriptor */
- par->board->post_dma_setup(par);
+ res = par->board->setup_io(par);
+ if (res)
+ return res;
res = metronome_powerup_cmd(par);
if (res)
@@ -430,16 +435,16 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
static void metronomefb_dpy_update(struct metronomefb_par *par)
{
+ int fbsize;
u16 cksum;
unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+ fbsize = par->info->fix.smem_len;
/* copy from vm to metromem */
- memcpy(par->metromem_img, buf, DPY_W*DPY_H);
+ memcpy(par->metromem_img, buf, fbsize);
- cksum = calc_img_cksum((u16 *) par->metromem_img,
- (epd_frame_table[0].fw * DPY_H)/2);
- *((u16 *)(par->metromem_img) +
- (epd_frame_table[0].fw * DPY_H)/2) = cksum;
+ cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
+ *((u16 *)(par->metromem_img) + fbsize/2) = cksum;
metronome_display_cmd(par);
}
@@ -574,8 +579,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
unsigned char *videomemory;
struct metronomefb_par *par;
const struct firmware *fw_entry;
- int cmd_size, wfm_size, img_size, padding_size, totalsize;
int i;
+ int panel_type;
+ int fw, fh;
+ int epd_dt_index;
/* pick up board specific routines */
board = dev->dev.platform_data;
@@ -586,96 +593,108 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
if (!try_module_get(board->owner))
return -ENODEV;
+ info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
+ if (!info)
+ goto err;
+
/* we have two blocks of memory.
info->screen_base which is vm, and is the fb used by apps.
par->metromem which is physically contiguous memory and
contains the display controller commands, waveform,
processed image data and padding. this is the data pulled
- by the device's LCD controller and pushed to Metronome */
+ by the device's LCD controller and pushed to Metronome.
+ the metromem memory is allocated by the board driver and
+ is provided to us */
+
+ panel_type = board->get_panel_type();
+ switch (panel_type) {
+ case 6:
+ epd_dt_index = 0;
+ break;
+ case 8:
+ epd_dt_index = 1;
+ break;
+ case 97:
+ epd_dt_index = 2;
+ break;
+ default:
+ dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
+ epd_dt_index = 0;
+ break;
+ }
+
+ fw = epd_frame_table[epd_dt_index].fw;
+ fh = epd_frame_table[epd_dt_index].fh;
- videomemorysize = (DPY_W*DPY_H);
+ /* we need to add a spare page because our csum caching scheme walks
+ * to the end of the page */
+ videomemorysize = PAGE_SIZE + (fw * fh);
videomemory = vmalloc(videomemorysize);
if (!videomemory)
- return -ENOMEM;
+ goto err_fb_rel;
memset(videomemory, 0, videomemorysize);
- info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
- if (!info)
- goto err_vfree;
-
info->screen_base = (char __force __iomem *)videomemory;
info->fbops = &metronomefb_ops;
+ metronomefb_fix.line_length = fw;
+ metronomefb_var.xres = fw;
+ metronomefb_var.yres = fh;
+ metronomefb_var.xres_virtual = fw;
+ metronomefb_var.yres_virtual = fh;
info->var = metronomefb_var;
info->fix = metronomefb_fix;
info->fix.smem_len = videomemorysize;
par = info->par;
par->info = info;
par->board = board;
+ par->dt = epd_dt_index;
init_waitqueue_head(&par->waitq);
/* this table caches per page csum values. */
par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
if (!par->csum_table)
+ goto err_vfree;
+
+ /* the physical framebuffer that we use is setup by
+ * the platform device driver. It will provide us
+ * with cmd, wfm and image memory in a contiguous area. */
+ retval = board->setup_fb(par);
+ if (retval) {
+ dev_err(&dev->dev, "Failed to setup fb\n");
goto err_csum_table;
+ }
- /* the metromem buffer is divided as follows:
- command | CRC | padding
- 16kb waveform data | CRC | padding
- image data | CRC
- and an extra 256 bytes for dma descriptors
- eg: IW=832 IH=622 WS=128
- */
-
- cmd_size = 1 * epd_frame_table[0].fw;
- wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
- / epd_frame_table[0].fw) * epd_frame_table[0].fw;
- img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
- padding_size = 4 * epd_frame_table[0].fw;
- totalsize = cmd_size + wfm_size + img_size + padding_size;
- par->metromemsize = PAGE_ALIGN(totalsize + 256);
- DPRINTK("desired memory size = %d\n", par->metromemsize);
- dev->dev.coherent_dma_mask = 0xffffffffull;
- par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
- &par->metromem_dma, GFP_KERNEL);
- if (!par->metromem) {
- printk(KERN_ERR
- "metronomefb: unable to allocate dma buffer\n");
- goto err_vfree;
+ /* after this point we should have a framebuffer */
+ if ((!par->metromem_wfm) || (!par->metromem_img) ||
+ (!par->metromem_dma)) {
+ dev_err(&dev->dev, "fb access failure\n");
+ retval = -EINVAL;
+ goto err_csum_table;
}
info->fix.smem_start = par->metromem_dma;
- par->metromem_cmd = (struct metromem_cmd *) par->metromem;
- par->metromem_wfm = par->metromem + cmd_size;
- par->metromem_img = par->metromem + cmd_size + wfm_size;
- par->metromem_img_csum = (u16 *) (par->metromem_img +
- (epd_frame_table[0].fw * DPY_H));
- DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
- par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
- + wfm_size + img_size + padding_size);
- par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
- + img_size + padding_size;
/* load the waveform in. assume mode 3, temp 31 for now
a) request the waveform file from userspace
b) process waveform and decode into metromem */
retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
if (retval < 0) {
- printk(KERN_ERR "metronomefb: couldn't get waveform\n");
- goto err_dma_free;
+ dev_err(&dev->dev, "Failed to get waveform\n");
+ goto err_csum_table;
}
- retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
- par->metromem_wfm, 3, 31, &par->frame_count);
+ retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
+ par);
release_firmware(fw_entry);
if (retval < 0) {
- printk(KERN_ERR "metronomefb: couldn't process waveform\n");
- goto err_dma_free;
+ dev_err(&dev->dev, "Failed processing waveform\n");
+ goto err_csum_table;
}
if (board->setup_irq(info))
- goto err_dma_free;
+ goto err_csum_table;
retval = metronome_init_regs(par);
if (retval < 0)
@@ -688,8 +707,8 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
retval = fb_alloc_cmap(&info->cmap, 8, 0);
if (retval < 0) {
- printk(KERN_ERR "Failed to allocate colormap\n");
- goto err_fb_rel;
+ dev_err(&dev->dev, "Failed to allocate colormap\n");
+ goto err_free_irq;
}
/* set cmap */
@@ -704,7 +723,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
platform_set_drvdata(dev, info);
- printk(KERN_INFO
+ dev_dbg(&dev->dev,
"fb%d: Metronome frame buffer device, using %dK of video"
" memory\n", info->node, videomemorysize >> 10);
@@ -712,17 +731,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
err_cmap:
fb_dealloc_cmap(&info->cmap);
-err_fb_rel:
- framebuffer_release(info);
err_free_irq:
- board->free_irq(info);
-err_dma_free:
- dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
- par->metromem_dma);
+ board->cleanup(par);
err_csum_table:
vfree(par->csum_table);
err_vfree:
vfree(videomemory);
+err_fb_rel:
+ framebuffer_release(info);
+err:
module_put(board->owner);
return retval;
}
@@ -733,15 +750,15 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
if (info) {
struct metronomefb_par *par = info->par;
+
+ unregister_framebuffer(info);
fb_deferred_io_cleanup(info);
- dma_free_writecombine(&dev->dev, par->metromemsize,
- par->metromem, par->metromem_dma);
fb_dealloc_cmap(&info->cmap);
+ par->board->cleanup(par);
vfree(par->csum_table);
- unregister_framebuffer(info);
vfree((void __force *)info->screen_base);
- par->board->free_irq(info);
module_put(par->board->owner);
+ dev_dbg(&dev->dev, "calling release\n");
framebuffer_release(info);
}
return 0;
@@ -766,6 +783,9 @@ static void __exit metronomefb_exit(void)
platform_driver_unregister(&metronomefb_driver);
}
+module_param(user_wfm_size, uint, 0);
+MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
+
module_init(metronomefb_init);
module_exit(metronomefb_exit);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 25172b2a2a9..bfb802d26d5 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -426,11 +426,11 @@ static void vgaHWProtect(int on)
{
unsigned char tmp;
+ tmp = vga_rseq(NULL, 0x01);
if (on) {
/*
* Turn off screen and disable sequencer.
*/
- tmp = vga_rseq(NULL, 0x01);
vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */
vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */
@@ -439,7 +439,6 @@ static void vgaHWProtect(int on)
/*
* Reenable sequencer, then turn on screen.
*/
- tmp = vga_rseq(NULL, 0x01);
vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */
vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */
@@ -558,14 +557,12 @@ neofb_open(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
- mutex_lock(&par->open_lock);
if (!par->ref_count) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
save_vga(&par->state);
}
par->ref_count++;
- mutex_unlock(&par->open_lock);
return 0;
}
@@ -575,16 +572,13 @@ neofb_release(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
- mutex_lock(&par->open_lock);
- if (!par->ref_count) {
- mutex_unlock(&par->open_lock);
+ if (!par->ref_count)
return -EINVAL;
- }
+
if (par->ref_count == 1) {
restore_vga(&par->state);
}
par->ref_count--;
- mutex_unlock(&par->open_lock);
return 0;
}
@@ -648,10 +642,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.msb_right = 0;
var->transp.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
switch (var->bits_per_pixel) {
case 8: /* PSEUDOCOLOUR, 256 */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
@@ -661,8 +655,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 16: /* DIRECTCOLOUR, 64k */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
@@ -672,8 +664,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 24: /* TRUECOLOUR, 16m */
- var->transp.offset = 0;
- var->transp.length = 0;
var->red.offset = 16;
var->red.length = 8;
var->green.offset = 8;
@@ -704,8 +694,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (vramlen > 4 * 1024 * 1024)
vramlen = 4 * 1024 * 1024;
- if (var->yres_virtual < var->yres)
- var->yres_virtual = var->yres;
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
@@ -722,8 +710,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if it was possible. We should return -EINVAL, but I disagree */
if (var->yres_virtual < var->yres)
var->yres = var->yres_virtual;
- if (var->xres_virtual < var->xres)
- var->xres = var->xres_virtual;
if (var->xoffset + var->xres > var->xres_virtual)
var->xoffset = var->xres_virtual - var->xres;
if (var->yoffset + var->yres > var->yres_virtual)
@@ -1186,8 +1172,11 @@ static int neofb_set_par(struct fb_info *info)
return 0;
}
-static void neofb_update_start(struct fb_info *info,
- struct fb_var_screeninfo *var)
+/*
+ * Pan or Wrap the Display
+ */
+static int neofb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
struct neofb_par *par = info->par;
struct vgastate *state = &par->state;
@@ -1216,35 +1205,7 @@ static void neofb_update_start(struct fb_info *info,
vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
neoLock(state);
-}
-
-/*
- * Pan or Wrap the Display
- */
-static int neofb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- u_int y_bottom;
-
- y_bottom = var->yoffset;
-
- if (!(var->vmode & FB_VMODE_YWRAP))
- y_bottom += var->yres;
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if (y_bottom > info->var.yres_virtual)
- return -EINVAL;
-
- neofb_update_start(info, var);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
-
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
@@ -1992,7 +1953,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
- mutex_init(&par->open_lock);
par->pci_burst = !nopciburst;
par->lcd_stretch = !nostretch;
par->libretto = libretto;
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 6efcf89e7fb..dfb72f5e4c9 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -156,7 +156,7 @@ struct resmap {
};
static struct {
- u32 base;
+ void __iomem *base;
struct omapfb_mem_desc mem_desc;
struct resmap *res_map[DISPC_MEMTYPE_NUM];
@@ -212,9 +212,9 @@ static void enable_rfbi_mode(int enable)
dispc_write_reg(DISPC_CONTROL, l);
/* Set bypass mode in RFBI module */
- l = __raw_readl(io_p2v(RFBI_CONTROL));
+ l = __raw_readl(IO_ADDRESS(RFBI_CONTROL));
l |= enable ? 0 : (1 << 1);
- __raw_writel(l, io_p2v(RFBI_CONTROL));
+ __raw_writel(l, IO_ADDRESS(RFBI_CONTROL));
}
static void set_lcd_data_lines(int data_lines)
@@ -1349,14 +1349,19 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
memset(&dispc, 0, sizeof(dispc));
- dispc.base = io_p2v(DISPC_BASE);
+ dispc.base = ioremap(DISPC_BASE, SZ_1K);
+ if (!dispc.base) {
+ dev_err(fbdev->dev, "can't ioremap DISPC\n");
+ return -ENOMEM;
+ }
+
dispc.fbdev = fbdev;
dispc.ext_mode = ext_mode;
init_completion(&dispc.frame_done);
if ((r = get_dss_clocks()) < 0)
- return r;
+ goto fail0;
enable_interface_clocks(1);
enable_lcd_clocks(1);
@@ -1414,7 +1419,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
}
/* L3 firewall setting: enable access to OCM RAM */
- __raw_writel(0x402000b0, io_p2v(0x680050a0));
+ __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
if ((r = alloc_palette_ram()) < 0)
goto fail2;
@@ -1464,7 +1469,8 @@ fail1:
enable_lcd_clocks(0);
enable_interface_clocks(0);
put_dss_clocks();
-
+fail0:
+ iounmap(dispc.base);
return r;
}
@@ -1481,6 +1487,7 @@ static void omap_dispc_cleanup(void)
free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
enable_interface_clocks(0);
put_dss_clocks();
+ iounmap(dispc.base);
}
const struct lcd_ctrl omap2_int_ctrl = {
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
index eb1512b56ce..ef720a78f6d 100644
--- a/drivers/video/omap/dispc.h
+++ b/drivers/video/omap/dispc.h
@@ -40,4 +40,6 @@ extern void omap_dispc_enable_digit_out(int enable);
extern int omap_dispc_request_irq(void (*callback)(void *data), void *data);
extern void omap_dispc_free_irq(void);
+extern const struct lcd_ctrl omap2_int_ctrl;
+
#endif
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
index 88c19d424ef..6ff56430341 100644
--- a/drivers/video/omap/lcd_h4.c
+++ b/drivers/video/omap/lcd_h4.c
@@ -47,7 +47,7 @@ static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
return 0;
}
-struct lcd_panel h4_panel = {
+static struct lcd_panel h4_panel = {
.name = "h4",
.config = OMAP_LCDC_PANEL_TFT,
@@ -91,7 +91,7 @@ static int h4_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver h4_panel_driver = {
+static struct platform_driver h4_panel_driver = {
.probe = h4_panel_probe,
.remove = h4_panel_remove,
.suspend = h4_panel_suspend,
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 6a42c6a0cd9..4c4f7ee6d73 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -32,43 +32,43 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
{
int r = 0;
- if (omap_request_gpio(14)) {
+ if (gpio_request(14, "lcd_en0")) {
pr_err(MODULE_NAME ": can't request GPIO 14\n");
r = -1;
goto exit;
}
- if (omap_request_gpio(15)) {
+ if (gpio_request(15, "lcd_en1")) {
pr_err(MODULE_NAME ": can't request GPIO 15\n");
- omap_free_gpio(14);
+ gpio_free(14);
r = -1;
goto exit;
}
/* configure GPIO(14, 15) as outputs */
- omap_set_gpio_direction(14, 0);
- omap_set_gpio_direction(15, 0);
+ gpio_direction_output(14, 0);
+ gpio_direction_output(15, 0);
exit:
return r;
}
static void innovator1610_panel_cleanup(struct lcd_panel *panel)
{
- omap_free_gpio(15);
- omap_free_gpio(14);
+ gpio_free(15);
+ gpio_free(14);
}
static int innovator1610_panel_enable(struct lcd_panel *panel)
{
/* set GPIO14 and GPIO15 high */
- omap_set_gpio_dataout(14, 1);
- omap_set_gpio_dataout(15, 1);
+ gpio_set_value(14, 1);
+ gpio_set_value(15, 1);
return 0;
}
static void innovator1610_panel_disable(struct lcd_panel *panel)
{
/* set GPIO13, GPIO14 and GPIO15 low */
- omap_set_gpio_dataout(14, 0);
- omap_set_gpio_dataout(15, 0);
+ gpio_set_value(14, 0);
+ gpio_set_value(15, 0);
}
static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index a4a725f427a..379c96d36da 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -29,6 +29,7 @@
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
+ /* gpio2 was allocated in board init */
return 0;
}
@@ -47,11 +48,8 @@ static int osk_panel_enable(struct lcd_panel *panel)
/* Set PWL level */
omap_writeb(0xFF, OMAP_PWL_ENABLE);
- /* configure GPIO2 as output */
- omap_set_gpio_direction(2, 0);
-
- /* set GPIO2 high */
- omap_set_gpio_dataout(2, 1);
+ /* set GPIO2 high (lcd power enabled) */
+ gpio_set_value(2, 1);
return 0;
}
@@ -65,7 +63,7 @@ static void osk_panel_disable(struct lcd_panel *panel)
omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
/* set GPIO2 low */
- omap_set_gpio_dataout(2, 0);
+ gpio_set_value(2, 0);
}
static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
index caa6a896cb8..e55de201b8f 100644
--- a/drivers/video/omap/lcd_sx1.c
+++ b/drivers/video/omap/lcd_sx1.c
@@ -81,21 +81,21 @@ static void epson_sendbyte(int flag, unsigned char byte)
int i, shifter = 0x80;
if (!flag)
- omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
+ gpio_set_value(_A_LCD_SSC_A0, 0);
mdelay(2);
- omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+ gpio_set_value(A_LCD_SSC_RD, 1);
- omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
+ gpio_set_value(A_LCD_SSC_SD, flag);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
for (i = 0; i < 8; i++) {
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
- omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
+ gpio_set_value(A_LCD_SSC_SD, shifter & byte);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
shifter >>= 1;
}
- omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+ gpio_set_value(_A_LCD_SSC_A0, 1);
}
static void init_system(void)
@@ -107,25 +107,18 @@ static void init_system(void)
static void setup_GPIO(void)
{
/* new wave */
- omap_request_gpio(A_LCD_SSC_RD);
- omap_request_gpio(A_LCD_SSC_SD);
- omap_request_gpio(_A_LCD_RESET);
- omap_request_gpio(_A_LCD_SSC_CS);
- omap_request_gpio(_A_LCD_SSC_A0);
-
- /* set all GPIOs to output */
- omap_set_gpio_direction(A_LCD_SSC_RD, 0);
- omap_set_gpio_direction(A_LCD_SSC_SD, 0);
- omap_set_gpio_direction(_A_LCD_RESET, 0);
- omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
- omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
-
- /* set GPIO data */
- omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
- omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
- omap_set_gpio_dataout(_A_LCD_RESET, 0);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+ gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
+ gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
+ gpio_request(_A_LCD_RESET, "lcd_reset");
+ gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
+ gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
+
+ /* set GPIOs to output, with initial data */
+ gpio_direction_output(A_LCD_SSC_RD, 1);
+ gpio_direction_output(A_LCD_SSC_SD, 0);
+ gpio_direction_output(_A_LCD_RESET, 0);
+ gpio_direction_output(_A_LCD_SSC_CS, 1);
+ gpio_direction_output(_A_LCD_SSC_A0, 1);
}
static void display_init(void)
@@ -139,61 +132,61 @@ static void display_init(void)
mdelay(2);
/* reset LCD */
- omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
+ gpio_set_value(A_LCD_SSC_SD, 1);
epson_sendbyte(0, 0x25);
- omap_set_gpio_dataout(_A_LCD_RESET, 0);
+ gpio_set_value(_A_LCD_RESET, 0);
mdelay(10);
- omap_set_gpio_dataout(_A_LCD_RESET, 1);
+ gpio_set_value(_A_LCD_RESET, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(2);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD, phase 1 */
epson_sendbyte(0, 0xCA);
for (i = 0; i < 10; i++)
epson_sendbyte(1, INIT_1[i]);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 2 */
epson_sendbyte(0, 0xCB);
for (i = 0; i < 125; i++)
epson_sendbyte(1, INIT_2[i]);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 2a */
epson_sendbyte(0, 0xCC);
for (i = 0; i < 14; i++)
epson_sendbyte(1, INIT_3[i]);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 3 */
epson_sendbyte(0, 0xBC);
epson_sendbyte(1, 0x08);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 4 */
epson_sendbyte(0, 0x07);
epson_sendbyte(1, 0x05);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 5 */
epson_sendbyte(0, 0x94);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 6 */
epson_sendbyte(0, 0xC6);
epson_sendbyte(1, 0x80);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(100); /* used to be 1000 */
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 7 */
epson_sendbyte(0, 0x16);
@@ -201,8 +194,8 @@ static void display_init(void)
epson_sendbyte(1, 0x00);
epson_sendbyte(1, 0xB1);
epson_sendbyte(1, 0x00);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 8 */
epson_sendbyte(0, 0x76);
@@ -210,12 +203,12 @@ static void display_init(void)
epson_sendbyte(1, 0x00);
epson_sendbyte(1, 0xDB);
epson_sendbyte(1, 0x00);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 9 */
epson_sendbyte(0, 0xAF);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
}
static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
@@ -231,18 +224,18 @@ static void sx1_panel_disable(struct lcd_panel *panel)
{
printk(KERN_INFO "SX1: LCD panel disable\n");
sx1_setmmipower(0);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
epson_sendbyte(0, 0x25);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
epson_sendbyte(0, 0xAE);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(100);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+ gpio_set_value(_A_LCD_SSC_CS, 0);
epson_sendbyte(0, 0x95);
- omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ gpio_set_value(_A_LCD_SSC_CS, 1);
}
static int sx1_panel_enable(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 83514f06671..6e2ea751876 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -34,6 +34,8 @@
#include <asm/mach-types.h>
+#include "lcdc.h"
+
#define MODULE_NAME "lcdc"
#define OMAP_LCDC_BASE 0xfffec000
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
index adb731e5314..845222270db 100644
--- a/drivers/video/omap/lcdc.h
+++ b/drivers/video/omap/lcdc.h
@@ -4,4 +4,6 @@
int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
void omap_lcdc_free_dma_callback(void);
+extern const struct lcd_ctrl omap1_int_ctrl;
+
#endif
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 51a138bd113..5a5e407dc45 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -31,11 +31,14 @@
#include <mach/dma.h>
#include <mach/omapfb.h>
+#include "lcdc.h"
+#include "dispc.h"
+
#define MODULE_NAME "omapfb"
static unsigned int def_accel;
static unsigned long def_vram[OMAPFB_PLANE_NUM];
-static int def_vram_cnt;
+static unsigned int def_vram_cnt;
static unsigned long def_vxres;
static unsigned long def_vyres;
static unsigned int def_rotate;
@@ -84,12 +87,10 @@ static struct caps_table_struct color_caps[] = {
* LCD panel
* ---------------------------------------------------------------------------
*/
-extern struct lcd_ctrl omap1_int_ctrl;
-extern struct lcd_ctrl omap2_int_ctrl;
extern struct lcd_ctrl hwa742_ctrl;
extern struct lcd_ctrl blizzard_ctrl;
-static struct lcd_ctrl *ctrls[] = {
+static const struct lcd_ctrl *ctrls[] = {
#ifdef CONFIG_ARCH_OMAP1
&omap1_int_ctrl,
#else
@@ -740,7 +741,7 @@ static int omapfb_update_win(struct fb_info *fbi,
int ret;
omapfb_rqueue_lock(plane->fbdev);
- ret = omapfb_update_window_async(fbi, win, NULL, 0);
+ ret = omapfb_update_window_async(fbi, win, NULL, NULL);
omapfb_rqueue_unlock(plane->fbdev);
return ret;
@@ -768,7 +769,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi)
win.format = 0;
omapfb_rqueue_lock(fbdev);
- r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+ r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
omapfb_rqueue_unlock(fbdev);
return r;
@@ -1047,7 +1048,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
win.height = 2;
win.out_width = 2;
win.out_height = 2;
- fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+ fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
}
omapfb_rqueue_unlock(fbdev);
}
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 4a6f13d3fac..a13c8dcad2a 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -59,7 +59,7 @@
#define DISPC_CONTROL 0x0040
static struct {
- u32 base;
+ void __iomem *base;
void (*lcdc_callback)(void *data);
void *lcdc_callback_data;
unsigned long l4_khz;
@@ -518,7 +518,11 @@ static int rfbi_init(struct omapfb_device *fbdev)
int r;
rfbi.fbdev = fbdev;
- rfbi.base = io_p2v(RFBI_BASE);
+ rfbi.base = ioremap(RFBI_BASE, SZ_1K);
+ if (!rfbi.base) {
+ dev_err(fbdev->dev, "can't ioremap RFBI\n");
+ return -ENOMEM;
+ }
if ((r = rfbi_get_clocks()) < 0)
return r;
@@ -566,6 +570,7 @@ static void rfbi_cleanup(void)
{
omap_dispc_free_irq();
rfbi_put_clocks();
+ iounmap(rfbi.base);
}
const struct lcd_ctrl_extif omap2_ext_if = {
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index 6359353c2c6..a7694622024 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -574,7 +574,12 @@ static int sossi_init(struct omapfb_device *fbdev)
struct clk *dpll1out_ck;
int r;
- sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+ sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
+ if (!sossi.base) {
+ dev_err(fbdev->dev, "can't ioremap SoSSI\n");
+ return -ENOMEM;
+ }
+
sossi.fbdev = fbdev;
spin_lock_init(&sossi.lock);
@@ -665,6 +670,7 @@ static void sossi_cleanup(void)
{
omap_lcdc_free_dma_callback();
clk_put(sossi.fck);
+ iounmap(sossi.base);
}
struct lcd_ctrl_extif omap1_ext_if = {
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 9e903454ffc..7000f2cd585 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -349,7 +349,7 @@ static int __devexit p9100_remove(struct of_device *op)
return 0;
}
-static struct of_device_id p9100_match[] = {
+static const struct of_device_id p9100_match[] = {
{
.name = "p9100",
},
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index b829dc7c5ed..a7b01d2724b 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -50,6 +50,11 @@
#define dbg(fmt, args...) do { } while (0)
#endif
+static const int __devinitconst s1d13xxxfb_revisions[] = {
+ S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */
+ S1D13806_CHIP_REV, /* Rev.7 on .. */
+};
+
/*
* Here we define the default struct fb_fix_screeninfo
*/
@@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct s1d13xxxfb_pdata *pdata = NULL;
int ret = 0;
+ int i;
u8 revision;
dbg("probe called: device is %p\n", pdev);
@@ -607,10 +613,19 @@ s1d13xxxfb_probe(struct platform_device *pdev)
goto bail;
}
- revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
- if ((revision >> 2) != S1D_CHIP_REV) {
- printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
- ret = -ENODEV;
+ revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
+
+ ret = -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) {
+ if (revision == s1d13xxxfb_revisions[i])
+ ret = 0;
+ }
+
+ if (!ret)
+ printk(KERN_INFO PFX "chip revision %i\n", revision);
+ else {
+ printk(KERN_INFO PFX "unknown chip revision %i\n", revision);
goto bail;
}
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 2a03f78bbb0..643afbfe827 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -505,7 +505,7 @@ static int __devexit tcx_remove(struct of_device *op)
return 0;
}
-static struct of_device_id tcx_match[] = {
+static const struct of_device_id tcx_match[] = {
{
.name = "SUNW,tcx",
},
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 77aafcfae03..14bd3f3680b 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -95,7 +95,6 @@ static inline int mtrr_del(int reg, unsigned long base,
#define VOODOO5_MAX_PIXCLOCK 350000
static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
- .id = "3Dfx",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.ypanstep = 1,
@@ -426,7 +425,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
/* Banshee/Voodoo3 */
chip_size = 2;
- if (has_sgram && (draminit0 & DRAMINIT0_SGRAM_TYPE))
+ if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
chip_size = 1;
} else {
/* Voodoo4/5 */
@@ -1196,57 +1195,58 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
return -ENOMEM;
default_par = info->par;
+ info->fix = tdfx_fix;
/* Configure the default fb_fix_screeninfo first */
switch (pdev->device) {
case PCI_DEVICE_ID_3DFX_BANSHEE:
- strcat(tdfx_fix.id, " Banshee");
+ strcpy(info->fix.id, "3Dfx Banshee");
default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO3:
- strcat(tdfx_fix.id, " Voodoo3");
+ strcpy(info->fix.id, "3Dfx Voodoo3");
default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO5:
- strcat(tdfx_fix.id, " Voodoo5");
+ strcpy(info->fix.id, "3Dfx Voodoo5");
default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
break;
}
- tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
- tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
- if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,
+ info->fix.mmio_start = pci_resource_start(pdev, 0);
+ info->fix.mmio_len = pci_resource_len(pdev, 0);
+ if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
"tdfx regbase")) {
printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
goto out_err;
}
default_par->regbase_virt =
- ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+ ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
if (!default_par->regbase_virt) {
printk(KERN_ERR "fb: Can't remap %s register area.\n",
- tdfx_fix.id);
+ info->fix.id);
goto out_err_regbase;
}
- tdfx_fix.smem_start = pci_resource_start(pdev, 1);
- tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device);
- if (!tdfx_fix.smem_len) {
- printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id);
+ info->fix.smem_start = pci_resource_start(pdev, 1);
+ info->fix.smem_len = do_lfb_size(default_par, pdev->device);
+ if (!info->fix.smem_len) {
+ printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
goto out_err_regbase;
}
- if (!request_mem_region(tdfx_fix.smem_start,
+ if (!request_mem_region(info->fix.smem_start,
pci_resource_len(pdev, 1), "tdfx smem")) {
printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
goto out_err_regbase;
}
- info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
- tdfx_fix.smem_len);
+ info->screen_base = ioremap_nocache(info->fix.smem_start,
+ info->fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
- tdfx_fix.id);
+ info->fix.id);
goto out_err_screenbase;
}
@@ -1258,20 +1258,19 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
goto out_err_screenbase;
}
- printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id,
- tdfx_fix.smem_len >> 10);
+ printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
+ info->fix.smem_len >> 10);
default_par->mtrr_handle = -1;
if (!nomtrr)
default_par->mtrr_handle =
- mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len,
+ mtrr_add(info->fix.smem_start, info->fix.smem_len,
MTRR_TYPE_WRCOMB, 1);
- tdfx_fix.ypanstep = nopan ? 0 : 1;
- tdfx_fix.ywrapstep = nowrap ? 0 : 1;
+ info->fix.ypanstep = nopan ? 0 : 1;
+ info->fix.ywrapstep = nowrap ? 0 : 1;
info->fbops = &tdfxfb_ops;
- info->fix = tdfx_fix;
info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
#ifdef CONFIG_FB_3DFX_ACCEL
@@ -1324,14 +1323,14 @@ out_err_iobase:
out_err_screenbase:
if (info->screen_base)
iounmap(info->screen_base);
- release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));
+ release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
out_err_regbase:
/*
* Cleanup after anything that was remapped/allocated.
*/
if (default_par->regbase_virt)
iounmap(default_par->regbase_virt);
- release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
out_err:
framebuffer_release(info);
return -ENXIO;
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
new file mode 100644
index 00000000000..2a380011e9b
--- /dev/null
+++ b/drivers/video/tmiofb.c
@@ -0,0 +1,1050 @@
+/*
+ * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
+ *
+ * Copyright(C) 2005-2006 Chris Humbert
+ * Copyright(C) 2005 Dirk Opfer
+ * Copytight(C) 2007,2008 Dmitry Baryshkov
+ *
+ * Based on:
+ * drivers/video/w100fb.c
+ * code written by Sharp/Lineo for 2.4 kernels
+ *
+ * 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;
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+/* Why should fb driver call console functions? because acquire_console_sem() */
+#include <linux/console.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/uaccess.h>
+
+/*
+ * accelerator commands
+ */
+#define TMIOFB_ACC_CSADR(x) (0x00000000 | ((x) & 0x001ffffe))
+#define TMIOFB_ACC_CHPIX(x) (0x01000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_CVPIX(x) (0x02000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PSADR(x) (0x03000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_PHPIX(x) (0x04000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVPIX(x) (0x05000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PHOFS(x) (0x06000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVOFS(x) (0x07000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_POADR(x) (0x08000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_RSTR(x) (0x09000000 | ((x) & 0x000000ff))
+#define TMIOFB_ACC_TCLOR(x) (0x0A000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_FILL(x) (0x0B000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_DSADR(x) (0x0C000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_SSADR(x) (0x0D000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_DHPIX(x) (0x0E000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_DVPIX(x) (0x0F000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SHPIX(x) (0x10000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SVPIX(x) (0x11000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_LBINI(x) (0x12000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_LBK2(x) (0x13000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBINI(x) (0x14000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBK2(x) (0x15000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBINI(x) (0x16000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBK2(x) (0x17000000 | ((x) & 0x0000ffff))
+
+#define TMIOFB_ACC_CMGO 0x20000000
+#define TMIOFB_ACC_CMGO_CEND 0x00000001
+#define TMIOFB_ACC_CMGO_INT 0x00000002
+#define TMIOFB_ACC_CMGO_CMOD 0x00000010
+#define TMIOFB_ACC_CMGO_CDVRV 0x00000020
+#define TMIOFB_ACC_CMGO_CDHRV 0x00000040
+#define TMIOFB_ACC_CMGO_RUND 0x00008000
+#define TMIOFB_ACC_SCGO 0x21000000
+#define TMIOFB_ACC_SCGO_CEND 0x00000001
+#define TMIOFB_ACC_SCGO_INT 0x00000002
+#define TMIOFB_ACC_SCGO_ROP3 0x00000004
+#define TMIOFB_ACC_SCGO_TRNS 0x00000008
+#define TMIOFB_ACC_SCGO_DVRV 0x00000010
+#define TMIOFB_ACC_SCGO_DHRV 0x00000020
+#define TMIOFB_ACC_SCGO_SVRV 0x00000040
+#define TMIOFB_ACC_SCGO_SHRV 0x00000080
+#define TMIOFB_ACC_SCGO_DSTXY 0x00008000
+#define TMIOFB_ACC_SBGO 0x22000000
+#define TMIOFB_ACC_SBGO_CEND 0x00000001
+#define TMIOFB_ACC_SBGO_INT 0x00000002
+#define TMIOFB_ACC_SBGO_DVRV 0x00000010
+#define TMIOFB_ACC_SBGO_DHRV 0x00000020
+#define TMIOFB_ACC_SBGO_SVRV 0x00000040
+#define TMIOFB_ACC_SBGO_SHRV 0x00000080
+#define TMIOFB_ACC_SBGO_SBMD 0x00000100
+#define TMIOFB_ACC_FLGO 0x23000000
+#define TMIOFB_ACC_FLGO_CEND 0x00000001
+#define TMIOFB_ACC_FLGO_INT 0x00000002
+#define TMIOFB_ACC_FLGO_ROP3 0x00000004
+#define TMIOFB_ACC_LDGO 0x24000000
+#define TMIOFB_ACC_LDGO_CEND 0x00000001
+#define TMIOFB_ACC_LDGO_INT 0x00000002
+#define TMIOFB_ACC_LDGO_ROP3 0x00000004
+#define TMIOFB_ACC_LDGO_ENDPX 0x00000008
+#define TMIOFB_ACC_LDGO_LVRV 0x00000010
+#define TMIOFB_ACC_LDGO_LHRV 0x00000020
+#define TMIOFB_ACC_LDGO_LDMOD 0x00000040
+
+/* a FIFO is always allocated, even if acceleration is not used */
+#define TMIOFB_FIFO_SIZE 512
+
+/*
+ * LCD Host Controller Configuration Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define CCR_CMD 0x04 /* Command */
+#define CCR_REVID 0x08 /* Revision ID */
+#define CCR_BASEL 0x10 /* LCD Control Reg Base Addr Low */
+#define CCR_BASEH 0x12 /* LCD Control Reg Base Addr High */
+#define CCR_UGCC 0x40 /* Unified Gated Clock Control */
+#define CCR_GCC 0x42 /* Gated Clock Control */
+#define CCR_USC 0x50 /* Unified Software Clear */
+#define CCR_VRAMRTC 0x60 /* VRAM Timing Control */
+ /* 0x61 VRAM Refresh Control */
+#define CCR_VRAMSAC 0x62 /* VRAM Access Control */
+ /* 0x63 VRAM Status */
+#define CCR_VRAMBC 0x64 /* VRAM Block Control */
+
+/*
+ * LCD Control Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define LCR_UIS 0x000 /* Unified Interrupt Status */
+#define LCR_VHPN 0x008 /* VRAM Horizontal Pixel Number */
+#define LCR_CFSAL 0x00a /* Command FIFO Start Address Low */
+#define LCR_CFSAH 0x00c /* Command FIFO Start Address High */
+#define LCR_CFS 0x00e /* Command FIFO Size */
+#define LCR_CFWS 0x010 /* Command FIFO Writeable Size */
+#define LCR_BBIE 0x012 /* BitBLT Interrupt Enable */
+#define LCR_BBISC 0x014 /* BitBLT Interrupt Status and Clear */
+#define LCR_CCS 0x016 /* Command Count Status */
+#define LCR_BBES 0x018 /* BitBLT Execution Status */
+#define LCR_CMDL 0x01c /* Command Low */
+#define LCR_CMDH 0x01e /* Command High */
+#define LCR_CFC 0x022 /* Command FIFO Clear */
+#define LCR_CCIFC 0x024 /* CMOS Camera IF Control */
+#define LCR_HWT 0x026 /* Hardware Test */
+#define LCR_LCDCCRC 0x100 /* LCDC Clock and Reset Control */
+#define LCR_LCDCC 0x102 /* LCDC Control */
+#define LCR_LCDCOPC 0x104 /* LCDC Output Pin Control */
+#define LCR_LCDIS 0x108 /* LCD Interrupt Status */
+#define LCR_LCDIM 0x10a /* LCD Interrupt Mask */
+#define LCR_LCDIE 0x10c /* LCD Interrupt Enable */
+#define LCR_GDSAL 0x122 /* Graphics Display Start Address Low */
+#define LCR_GDSAH 0x124 /* Graphics Display Start Address High */
+#define LCR_VHPCL 0x12a /* VRAM Horizontal Pixel Count Low */
+#define LCR_VHPCH 0x12c /* VRAM Horizontal Pixel Count High */
+#define LCR_GM 0x12e /* Graphic Mode(VRAM access enable) */
+#define LCR_HT 0x140 /* Horizontal Total */
+#define LCR_HDS 0x142 /* Horizontal Display Start */
+#define LCR_HSS 0x144 /* H-Sync Start */
+#define LCR_HSE 0x146 /* H-Sync End */
+#define LCR_HNP 0x14c /* Horizontal Number of Pixels */
+#define LCR_VT 0x150 /* Vertical Total */
+#define LCR_VDS 0x152 /* Vertical Display Start */
+#define LCR_VSS 0x154 /* V-Sync Start */
+#define LCR_VSE 0x156 /* V-Sync End */
+#define LCR_CDLN 0x160 /* Current Display Line Number */
+#define LCR_ILN 0x162 /* Interrupt Line Number */
+#define LCR_SP 0x164 /* Sync Polarity */
+#define LCR_MISC 0x166 /* MISC(RGB565 mode) */
+#define LCR_VIHSS 0x16a /* Video Interface H-Sync Start */
+#define LCR_VIVS 0x16c /* Video Interface Vertical Start */
+#define LCR_VIVE 0x16e /* Video Interface Vertical End */
+#define LCR_VIVSS 0x170 /* Video Interface V-Sync Start */
+#define LCR_VCCIS 0x17e /* Video / CMOS Camera Interface Select */
+#define LCR_VIDWSAL 0x180 /* VI Data Write Start Address Low */
+#define LCR_VIDWSAH 0x182 /* VI Data Write Start Address High */
+#define LCR_VIDRSAL 0x184 /* VI Data Read Start Address Low */
+#define LCR_VIDRSAH 0x186 /* VI Data Read Start Address High */
+#define LCR_VIPDDST 0x188 /* VI Picture Data Display Start Timing */
+#define LCR_VIPDDET 0x186 /* VI Picture Data Display End Timing */
+#define LCR_VIE 0x18c /* Video Interface Enable */
+#define LCR_VCS 0x18e /* Video/Camera Select */
+#define LCR_VPHWC 0x194 /* Video Picture Horizontal Wait Count */
+#define LCR_VPHS 0x196 /* Video Picture Horizontal Size */
+#define LCR_VPVWC 0x198 /* Video Picture Vertical Wait Count */
+#define LCR_VPVS 0x19a /* Video Picture Vertical Size */
+#define LCR_PLHPIX 0x1a0 /* PLHPIX */
+#define LCR_XS 0x1a2 /* XStart */
+#define LCR_XCKHW 0x1a4 /* XCK High Width */
+#define LCR_STHS 0x1a8 /* STH Start */
+#define LCR_VT2 0x1aa /* Vertical Total */
+#define LCR_YCKSW 0x1ac /* YCK Start Wait */
+#define LCR_YSTS 0x1ae /* YST Start */
+#define LCR_PPOLS 0x1b0 /* #PPOL Start */
+#define LCR_PRECW 0x1b2 /* PREC Width */
+#define LCR_VCLKHW 0x1b4 /* VCLK High Width */
+#define LCR_OC 0x1b6 /* Output Control */
+
+static char *mode_option __devinitdata;
+
+struct tmiofb_par {
+ u32 pseudo_palette[16];
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+ wait_queue_head_t wait_acc;
+ bool use_polling;
+#endif
+
+ void __iomem *ccr;
+ void __iomem *lcr;
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * reasons for an interrupt:
+ * uis bbisc lcdis
+ * 0100 0001 accelerator command completed
+ * 2000 0001 vsync start
+ * 2000 0002 display start
+ * 2000 0004 line number match(0x1ff mask???)
+ */
+static irqreturn_t tmiofb_irq(int irq, void *__info)
+{
+ struct fb_info *info = __info;
+ struct tmiofb_par *par = info->par;
+ unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
+
+
+ /*
+ * We were in polling mode and now we got correct irq.
+ * Switch back to IRQ-based sync of command FIFO
+ */
+ if (unlikely(par->use_polling && irq != -1)) {
+ printk(KERN_INFO "tmiofb: switching to waitq\n");
+ par->use_polling = false;
+ }
+
+ tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+ if (bbisc & 1)
+ wake_up(&par->wait_acc);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+
+/*
+ * Turns off the LCD controller and LCD host controller.
+ */
+static int tmiofb_hw_stop(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct tmio_fb_data *data = cell->driver_data;
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct tmiofb_par *par = info->par;
+
+ tmio_iowrite16(0, par->ccr + CCR_UGCC);
+ tmio_iowrite16(0, par->lcr + LCR_GM);
+ data->lcd_set_power(dev, 0);
+ tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+
+ return 0;
+}
+
+/*
+ * Initializes the LCD host controller.
+ */
+static int tmiofb_hw_init(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct tmiofb_par *par = info->par;
+ const struct resource *nlcr = &cell->resources[0];
+ const struct resource *vram = &cell->resources[2];
+ unsigned long base;
+
+ if (nlcr == NULL || vram == NULL)
+ return -EINVAL;
+
+ base = nlcr->start;
+
+ tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
+ tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
+ tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
+
+ msleep(2); /* wait for device to settle */
+
+ tmio_iowrite16(0x0000, par->ccr + CCR_USC);
+ tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
+ tmio_iowrite16(base, par->ccr + CCR_BASEL);
+ tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
+ tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
+ tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
+ tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
+ msleep(2); /* wait for device to settle */
+ tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
+
+ base = vram->start + info->screen_size;
+ tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
+ tmio_iowrite16(base, par->lcr + LCR_CFSAL);
+ tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
+ tmio_iowrite16(1, par->lcr + LCR_CFC);
+ tmio_iowrite16(1, par->lcr + LCR_BBIE);
+ tmio_iowrite16(0, par->lcr + LCR_CFWS);
+
+ return 0;
+}
+
+/*
+ * Sets the LCD controller's output resolution and pixel clock
+ */
+static void tmiofb_hw_mode(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct tmio_fb_data *data = cell->driver_data;
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct fb_videomode *mode = info->mode;
+ struct tmiofb_par *par = info->par;
+ unsigned int i;
+
+ tmio_iowrite16(0, par->lcr + LCR_GM);
+ data->lcd_set_power(dev, 0);
+ tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+ data->lcd_mode(dev, mode);
+ data->lcd_set_power(dev, 1);
+
+ tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
+ tmio_iowrite16(0, par->lcr + LCR_GDSAH);
+ tmio_iowrite16(0, par->lcr + LCR_GDSAL);
+ tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
+ tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
+ tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
+ tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
+ tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
+ tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
+ tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
+ tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
+ tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
+ tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
+ tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
+ tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
+ tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
+ tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
+ tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
+ tmio_iowrite16(3, par->lcr + LCR_SP); /* sync polarity */
+
+ tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+ msleep(5); /* wait for device to settle */
+ tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
+ msleep(5); /* wait for device to settle */
+ tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
+ tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
+}
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+static int __must_check
+tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
+{
+ struct tmiofb_par *par = info->par;
+ /*
+ * This code can be called whith interrupts disabled.
+ * So instead of relaying on irq to trigger the event,
+ * poll the state till the necessary command is executed.
+ */
+ if (irqs_disabled() || par->use_polling) {
+ int i = 0;
+ while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
+ udelay(1);
+ i++;
+ if (i > 10000) {
+ pr_err("tmiofb: timeout waiting for %d\n",
+ ccs);
+ return -ETIMEDOUT;
+ }
+ tmiofb_irq(-1, info);
+ }
+ } else {
+ if (!wait_event_interruptible_timeout(par->wait_acc,
+ tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
+ 1000)) {
+ pr_err("tmiofb: timeout waiting for %d\n", ccs);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Writes an accelerator command to the accelerator's FIFO.
+ */
+static int
+tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
+{
+ struct tmiofb_par *par = info->par;
+ int ret;
+
+ ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
+ if (ret)
+ return ret;
+
+ for (; count; count--, cmd++) {
+ tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
+ tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
+ }
+
+ return ret;
+}
+
+/*
+ * Wait for the accelerator to finish its operations before writing
+ * to the framebuffer for consistent display output.
+ */
+static int tmiofb_sync(struct fb_info *fbi)
+{
+ struct tmiofb_par *par = fbi->par;
+
+ int ret;
+ int i = 0;
+
+ ret = tmiofb_acc_wait(fbi, 0);
+
+ while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
+ udelay(1);
+ i++ ;
+ if (i > 10000) {
+ printk(KERN_ERR "timeout waiting for blit to end!\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return ret;
+}
+
+static void
+tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
+{
+ const u32 cmd[] = {
+ TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
+ TMIOFB_ACC_DHPIX(rect->width - 1),
+ TMIOFB_ACC_DVPIX(rect->height - 1),
+ TMIOFB_ACC_FILL(rect->color),
+ TMIOFB_ACC_FLGO,
+ };
+
+ if (fbi->state != FBINFO_STATE_RUNNING ||
+ fbi->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_fillrect(fbi, rect);
+ return;
+ }
+
+ tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+
+static void
+tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
+{
+ const u32 cmd[] = {
+ TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
+ TMIOFB_ACC_DHPIX(area->width - 1),
+ TMIOFB_ACC_DVPIX(area->height - 1),
+ TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
+ TMIOFB_ACC_SCGO,
+ };
+
+ if (fbi->state != FBINFO_STATE_RUNNING ||
+ fbi->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_copyarea(fbi, area);
+ return;
+ }
+
+ tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+#endif
+
+static void tmiofb_clearscreen(struct fb_info *info)
+{
+ const struct fb_fillrect rect = {
+ .dx = 0,
+ .dy = 0,
+ .width = info->mode->xres,
+ .height = info->mode->yres,
+ .color = 0,
+ .rop = ROP_COPY,
+ };
+
+ info->fbops->fb_fillrect(info, &rect);
+}
+
+static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
+{
+ struct tmiofb_par *par = fbi->par;
+ struct fb_videomode *mode = fbi->mode;
+ unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
+ unsigned int vds = mode->vsync_len + mode->upper_margin;
+
+ vblank->vcount = vcount;
+ vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
+ | FB_VBLANK_HAVE_VSYNC;
+
+ if (vcount < mode->vsync_len)
+ vblank->flags |= FB_VBLANK_VSYNCING;
+
+ if (vcount < vds || vcount > vds + mode->yres)
+ vblank->flags |= FB_VBLANK_VBLANKING;
+
+ return 0;
+}
+
+
+static int tmiofb_ioctl(struct fb_info *fbi,
+ unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case FBIOGET_VBLANK: {
+ struct fb_vblank vblank = {0};
+ void __user *argp = (void __user *) arg;
+
+ tmiofb_vblank(fbi, &vblank);
+ if (copy_to_user(argp, &vblank, sizeof vblank))
+ return -EFAULT;
+ return 0;
+ }
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+ case FBIO_TMIO_ACC_SYNC:
+ tmiofb_sync(fbi);
+ return 0;
+
+ case FBIO_TMIO_ACC_WRITE: {
+ u32 __user *argp = (void __user *) arg;
+ u32 len;
+ u32 acc[16];
+
+ if (get_user(len, argp))
+ return -EFAULT;
+ if (len > ARRAY_SIZE(acc))
+ return -EINVAL;
+ if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
+ return -EFAULT;
+
+ return tmiofb_acc_write(fbi, acc, len);
+ }
+#endif
+ }
+
+ return -ENOTTY;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
+ */
+static struct fb_videomode *
+tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ struct mfd_cell *cell =
+ info->device->platform_data;
+ struct tmio_fb_data *data = cell->driver_data;
+ struct fb_videomode *best = NULL;
+ int i;
+
+ for (i = 0; i < data->num_modes; i++) {
+ struct fb_videomode *mode = data->modes + i;
+
+ if (mode->xres >= var->xres && mode->yres >= var->yres
+ && (!best || (mode->xres < best->xres
+ && mode->yres < best->yres)))
+ best = mode;
+ }
+
+ return best;
+}
+
+static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+ struct fb_videomode *mode;
+ struct mfd_cell *cell =
+ info->device->platform_data;
+ struct tmio_fb_data *data = cell->driver_data;
+
+ mode = tmiofb_find_mode(info, var);
+ if (!mode || var->bits_per_pixel > 16)
+ return -EINVAL;
+
+ fb_videomode_to_var(var, mode);
+
+ var->xres_virtual = mode->xres;
+ var->yres_virtual = info->screen_size / (mode->xres * 2);
+
+ if (var->yres_virtual < var->yres)
+ return -EINVAL;
+
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->bits_per_pixel = 16;
+ var->grayscale = 0;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->nonstd = 0;
+ var->height = data->height; /* mm */
+ var->width = data->width; /* mm */
+ var->rotate = 0;
+ return 0;
+}
+
+static int tmiofb_set_par(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_videomode *mode;
+
+ mode = tmiofb_find_mode(info, var);
+ if (!mode)
+ return -EINVAL;
+
+ info->mode = mode;
+ info->fix.line_length = info->mode->xres *
+ var->bits_per_pixel / 8;
+
+ tmiofb_hw_mode(to_platform_device(info->device));
+ tmiofb_clearscreen(info);
+ return 0;
+}
+
+static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct tmiofb_par *par = info->par;
+
+ if (regno < ARRAY_SIZE(par->pseudo_palette)) {
+ par->pseudo_palette[regno] =
+ ((red & 0xf800)) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int tmiofb_blank(int blank, struct fb_info *info)
+{
+ /*
+ * everything is done in lcd/bl drivers.
+ * this is purely to make sysfs happy and work.
+ */
+ return 0;
+}
+
+static struct fb_ops tmiofb_ops = {
+ .owner = THIS_MODULE,
+
+ .fb_ioctl = tmiofb_ioctl,
+ .fb_check_var = tmiofb_check_var,
+ .fb_set_par = tmiofb_set_par,
+ .fb_setcolreg = tmiofb_setcolreg,
+ .fb_blank = tmiofb_blank,
+ .fb_imageblit = cfb_imageblit,
+#ifdef CONFIG_FB_TMIO_ACCELL
+ .fb_sync = tmiofb_sync,
+ .fb_fillrect = tmiofb_fillrect,
+ .fb_copyarea = tmiofb_copyarea,
+#else
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+#endif
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __devinit tmiofb_probe(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct tmio_fb_data *data = cell->driver_data;
+ struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ int irq = platform_get_irq(dev, 0);
+ struct fb_info *info;
+ struct tmiofb_par *par;
+ int retval;
+
+ /*
+ * This is the only way ATM to disable the fb
+ */
+ if (data == NULL) {
+ dev_err(&dev->dev, "NULL platform data!\n");
+ return -EINVAL;
+ }
+
+ info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
+
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+ init_waitqueue_head(&par->wait_acc);
+
+ par->use_polling = true;
+
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
+ | FBINFO_HWACCEL_FILLRECT;
+#else
+ info->flags = FBINFO_DEFAULT;
+#endif
+
+ info->fbops = &tmiofb_ops;
+
+ strcpy(info->fix.id, "tmio-fb");
+ info->fix.smem_start = vram->start;
+ info->fix.smem_len = resource_size(vram);
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.mmio_start = lcr->start;
+ info->fix.mmio_len = resource_size(lcr);
+ info->fix.accel = FB_ACCEL_NONE;
+ info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
+ info->pseudo_palette = par->pseudo_palette;
+
+ par->ccr = ioremap(ccr->start, resource_size(ccr));
+ if (!par->ccr) {
+ retval = -ENOMEM;
+ goto err_ioremap_ccr;
+ }
+
+ par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+ if (!par->lcr) {
+ retval = -ENOMEM;
+ goto err_ioremap_lcr;
+ }
+
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base) {
+ retval = -ENOMEM;
+ goto err_ioremap_vram;
+ }
+
+ retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
+ dev->dev.bus_id, info);
+
+ if (retval)
+ goto err_request_irq;
+
+ platform_set_drvdata(dev, info);
+
+ retval = fb_find_mode(&info->var, info, mode_option,
+ data->modes, data->num_modes,
+ data->modes, 16);
+ if (!retval) {
+ retval = -EINVAL;
+ goto err_find_mode;
+ }
+
+ if (cell->enable) {
+ retval = cell->enable(dev);
+ if (retval)
+ goto err_enable;
+ }
+
+ retval = tmiofb_hw_init(dev);
+ if (retval)
+ goto err_hw_init;
+
+ fb_videomode_to_modelist(data->modes, data->num_modes,
+ &info->modelist);
+
+ retval = register_framebuffer(info);
+ if (retval < 0)
+ goto err_register_framebuffer;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ return 0;
+
+err_register_framebuffer:
+/*err_set_par:*/
+ tmiofb_hw_stop(dev);
+err_hw_init:
+ if (cell->disable)
+ cell->disable(dev);
+err_enable:
+err_find_mode:
+ platform_set_drvdata(dev, NULL);
+ free_irq(irq, info);
+err_request_irq:
+ iounmap(info->screen_base);
+err_ioremap_vram:
+ iounmap(par->lcr);
+err_ioremap_lcr:
+ iounmap(par->ccr);
+err_ioremap_ccr:
+ framebuffer_release(info);
+ return retval;
+}
+
+static int __devexit tmiofb_remove(struct platform_device *dev)
+{
+ struct mfd_cell *cell = dev->dev.platform_data;
+ struct fb_info *info = platform_get_drvdata(dev);
+ int irq = platform_get_irq(dev, 0);
+ struct tmiofb_par *par;
+
+ if (info) {
+ par = info->par;
+ unregister_framebuffer(info);
+
+ tmiofb_hw_stop(dev);
+
+ if (cell->disable)
+ cell->disable(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ free_irq(irq, info);
+
+ iounmap(info->screen_base);
+ iounmap(par->lcr);
+ iounmap(par->ccr);
+
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
+
+#ifdef DEBUG
+static void tmiofb_dump_regs(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct tmiofb_par *par = info->par;
+
+ printk(KERN_DEBUG "lhccr:\n");
+#define CCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+ tmio_ioread16(par->ccr + CCR_ ## n));
+ CCR_PR(CMD);
+ CCR_PR(REVID);
+ CCR_PR(BASEL);
+ CCR_PR(BASEH);
+ CCR_PR(UGCC);
+ CCR_PR(GCC);
+ CCR_PR(USC);
+ CCR_PR(VRAMRTC);
+ CCR_PR(VRAMSAC);
+ CCR_PR(VRAMBC);
+#undef CCR_PR
+
+ printk(KERN_DEBUG "lcr: \n");
+#define LCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+ tmio_ioread16(par->lcr + LCR_ ## n));
+ LCR_PR(UIS);
+ LCR_PR(VHPN);
+ LCR_PR(CFSAL);
+ LCR_PR(CFSAH);
+ LCR_PR(CFS);
+ LCR_PR(CFWS);
+ LCR_PR(BBIE);
+ LCR_PR(BBISC);
+ LCR_PR(CCS);
+ LCR_PR(BBES);
+ LCR_PR(CMDL);
+ LCR_PR(CMDH);
+ LCR_PR(CFC);
+ LCR_PR(CCIFC);
+ LCR_PR(HWT);
+ LCR_PR(LCDCCRC);
+ LCR_PR(LCDCC);
+ LCR_PR(LCDCOPC);
+ LCR_PR(LCDIS);
+ LCR_PR(LCDIM);
+ LCR_PR(LCDIE);
+ LCR_PR(GDSAL);
+ LCR_PR(GDSAH);
+ LCR_PR(VHPCL);
+ LCR_PR(VHPCH);
+ LCR_PR(GM);
+ LCR_PR(HT);
+ LCR_PR(HDS);
+ LCR_PR(HSS);
+ LCR_PR(HSE);
+ LCR_PR(HNP);
+ LCR_PR(VT);
+ LCR_PR(VDS);
+ LCR_PR(VSS);
+ LCR_PR(VSE);
+ LCR_PR(CDLN);
+ LCR_PR(ILN);
+ LCR_PR(SP);
+ LCR_PR(MISC);
+ LCR_PR(VIHSS);
+ LCR_PR(VIVS);
+ LCR_PR(VIVE);
+ LCR_PR(VIVSS);
+ LCR_PR(VCCIS);
+ LCR_PR(VIDWSAL);
+ LCR_PR(VIDWSAH);
+ LCR_PR(VIDRSAL);
+ LCR_PR(VIDRSAH);
+ LCR_PR(VIPDDST);
+ LCR_PR(VIPDDET);
+ LCR_PR(VIE);
+ LCR_PR(VCS);
+ LCR_PR(VPHWC);
+ LCR_PR(VPHS);
+ LCR_PR(VPVWC);
+ LCR_PR(VPVS);
+ LCR_PR(PLHPIX);
+ LCR_PR(XS);
+ LCR_PR(XCKHW);
+ LCR_PR(STHS);
+ LCR_PR(VT2);
+ LCR_PR(YCKSW);
+ LCR_PR(YSTS);
+ LCR_PR(PPOLS);
+ LCR_PR(PRECW);
+ LCR_PR(VCLKHW);
+ LCR_PR(OC);
+#undef LCR_PR
+}
+#endif
+
+#ifdef CONFIG_PM
+static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct tmiofb_par *par = info->par;
+ struct mfd_cell *cell = dev->dev.platform_data;
+ int retval = 0;
+
+ acquire_console_sem();
+
+ fb_set_suspend(info, 1);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+
+ /*
+ * The fb should be usable even if interrupts are disabled (and they are
+ * during suspend/resume). Switch temporary to forced polling.
+ */
+ printk(KERN_INFO "tmiofb: switching to polling\n");
+ par->use_polling = true;
+ tmiofb_hw_stop(dev);
+
+ if (cell->suspend)
+ retval = cell->suspend(dev);
+
+ release_console_sem();
+
+ return retval;
+}
+
+static int tmiofb_resume(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct mfd_cell *cell = dev->dev.platform_data;
+ int retval;
+
+ acquire_console_sem();
+
+ if (cell->resume) {
+ retval = cell->resume(dev);
+ if (retval)
+ goto out;
+ }
+
+ tmiofb_irq(-1, info);
+
+ tmiofb_hw_init(dev);
+
+ tmiofb_hw_mode(dev);
+
+ fb_set_suspend(info, 0);
+out:
+ release_console_sem();
+ return retval;
+}
+#else
+#define tmiofb_suspend NULL
+#define tmiofb_resume NULL
+#endif
+
+static struct platform_driver tmiofb_driver = {
+ .driver.name = "tmio-fb",
+ .driver.owner = THIS_MODULE,
+ .probe = tmiofb_probe,
+ .remove = __devexit_p(tmiofb_remove),
+ .suspend = tmiofb_suspend,
+ .resume = tmiofb_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+#ifndef MODULE
+static void __init tmiofb_setup(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+ /*
+ * FIXME
+ */
+ }
+}
+#endif
+
+static int __init tmiofb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("tmiofb", &option))
+ return -ENODEV;
+ tmiofb_setup(option);
+#endif
+ return platform_driver_register(&tmiofb_driver);
+}
+
+static void __exit tmiofb_cleanup(void)
+{
+ platform_driver_unregister(&tmiofb_driver);
+}
+
+module_init(tmiofb_init);
+module_exit(tmiofb_cleanup);
+
+MODULE_DESCRIPTION("TMIO framebuffer driver");
+MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 50744229c7a..6c2d37fdd3b 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -516,10 +516,12 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
err = uvesafb_exec(task);
if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
- printk(KERN_ERR "uvesafb: Getting mode info block "
+ printk(KERN_WARNING "uvesafb: Getting mode info block "
"for mode 0x%x failed (eax=0x%x, err=%d)\n",
*mode, (u32)task->t.regs.eax, err);
- return -EINVAL;
+ mode++;
+ par->vbe_modes_cnt--;
+ continue;
}
mib = task->buf;
@@ -548,7 +550,10 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
mib->depth = mib->bits_per_pixel;
}
- return 0;
+ if (par->vbe_modes_cnt > 0)
+ return 0;
+ else
+ return -EINVAL;
}
/*
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index e31bca8a0cb..5b2938903ac 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -58,7 +58,6 @@ struct vga16fb_par {
unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state;
struct vgastate state;
- struct mutex open_lock;
unsigned int ref_count;
int palette_blanked, vesa_blanked, mode, isVGA;
u8 misc, pel_msk, vss, clkdiv;
@@ -286,7 +285,6 @@ static int vga16fb_open(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
- mutex_lock(&par->open_lock);
if (!par->ref_count) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
@@ -294,7 +292,6 @@ static int vga16fb_open(struct fb_info *info, int user)
save_vga(&par->state);
}
par->ref_count++;
- mutex_unlock(&par->open_lock);
return 0;
}
@@ -303,15 +300,12 @@ static int vga16fb_release(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
- mutex_lock(&par->open_lock);
- if (!par->ref_count) {
- mutex_unlock(&par->open_lock);
+ if (!par->ref_count)
return -EINVAL;
- }
+
if (par->ref_count == 1)
restore_vga(&par->state);
par->ref_count--;
- mutex_unlock(&par->open_lock);
return 0;
}
@@ -1326,7 +1320,6 @@ static int __init vga16fb_probe(struct platform_device *dev)
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
par = info->par;
- mutex_init(&par->open_lock);
par->isVGA = screen_info.orig_video_isVGA;
par->palette_blanked = 0;
par->vesa_blanked = 0;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
new file mode 100644
index 00000000000..e533b4b6aba
--- /dev/null
+++ b/drivers/video/via/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
+#
+
+obj-$(CONFIG_FB_VIA) += viafb.o
+
+viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
new file mode 100644
index 00000000000..632523ff1fb
--- /dev/null
+++ b/drivers/video/via/accel.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "global.h"
+
+void viafb_init_accel(void)
+{
+ viaparinfo->fbmem_free -= CURSOR_SIZE;
+ viaparinfo->cursor_start = viaparinfo->fbmem_free;
+ viaparinfo->fbmem_used += CURSOR_SIZE;
+
+ /* Reverse 8*1024 memory space for cursor image */
+ viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE);
+ viaparinfo->VQ_start = viaparinfo->fbmem_free;
+ viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1;
+ viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); }
+
+void viafb_init_2d_engine(void)
+{
+ u32 dwVQStartAddr, dwVQEndAddr;
+ u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
+
+ /* init 2D engine regs to reset 2D engine */
+ writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
+
+ /* Init AGP and VQ regs */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+ writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ break;
+
+ default:
+ writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET);
+ writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+ writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET);
+ writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ break;
+ }
+ if (viaparinfo->VQ_start != 0) {
+ /* Enable VQ */
+ dwVQStartAddr = viaparinfo->VQ_start;
+ dwVQEndAddr = viaparinfo->VQ_end;
+
+ dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF);
+ dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF);
+ dwVQStartEndH = 0x52000000 |
+ ((dwVQStartAddr & 0xFF000000) >> 24) |
+ ((dwVQEndAddr & 0xFF000000) >> 16);
+ dwVQLen = 0x53000000 | (VQ_SIZE >> 3);
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ dwVQStartL |= 0x20000000;
+ dwVQEndL |= 0x20000000;
+ dwVQStartEndH |= 0x20000000;
+ dwVQLen |= 0x20000000;
+ break;
+ default:
+ break;
+ }
+
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ writel(0x00100000,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+ writel(dwVQStartEndH,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(dwVQStartL,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(dwVQEndL,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(dwVQLen,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(0x74301001,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ writel(0x00000000,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ break;
+ default:
+ writel(0x00FE0000,
+ viaparinfo->io_virt + VIA_REG_TRANSET);
+ writel(0x080003FE,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0A00027C,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0B000260,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0C000274,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0D000264,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0E000000,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x0F000020,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x1000027E,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x110002FE,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x200F0060,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+ writel(0x00000006,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x40008C0F,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x44000000,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x45080C04,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x46800408,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+ writel(dwVQStartEndH,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(dwVQStartL,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(dwVQEndL,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(dwVQLen,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ break;
+ }
+ } else {
+ /* Disable VQ */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ writel(0x00100000,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+ writel(0x74301000,
+ viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+ break;
+ default:
+ writel(0x00FE0000,
+ viaparinfo->io_virt + VIA_REG_TRANSET);
+ writel(0x00000004,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x40008C0F,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x44000000,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x45080C04,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ writel(0x46800408,
+ viaparinfo->io_virt + VIA_REG_TRANSPACE);
+ break;
+ }
+ }
+
+ viafb_set_2d_color_depth(viaparinfo->bpp);
+
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
+
+ writel(VIA_PITCH_ENABLE |
+ (((viaparinfo->hres *
+ viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres *
+ viaparinfo->
+ bpp >> 3) >> 3) << 16)),
+ viaparinfo->io_virt + VIA_REG_PITCH);
+}
+
+void viafb_set_2d_color_depth(int bpp)
+{
+ u32 dwGEMode;
+
+ dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF;
+
+ switch (bpp) {
+ case 16:
+ dwGEMode |= VIA_GEM_16bpp;
+ break;
+ case 32:
+ dwGEMode |= VIA_GEM_32bpp;
+ break;
+ default:
+ dwGEMode |= VIA_GEM_8bpp;
+ break;
+ }
+
+ /* Set BPP and Pitch */
+ writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE);
+}
+
+void viafb_hw_cursor_init(void)
+{
+ /* Set Cursor Image Base Address */
+ writel(viaparinfo->cursor_start,
+ viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
+ writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
+}
+
+void viafb_show_hw_cursor(struct fb_info *info, int Status)
+{
+ u32 temp;
+ u32 iga_path = ((struct viafb_par *)(info->par))->iga_path;
+
+ temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+ switch (Status) {
+ case HW_Cursor_ON:
+ temp |= 0x1;
+ break;
+ case HW_Cursor_OFF:
+ temp &= 0xFFFFFFFE;
+ break;
+ }
+ switch (iga_path) {
+ case IGA2:
+ temp |= 0x80000000;
+ break;
+ case IGA1:
+ default:
+ temp &= 0x7FFFFFFF;
+ }
+ writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+}
+
+int viafb_wait_engine_idle(void)
+{
+ int loop = 0;
+
+ while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) &
+ VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP))
+ cpu_relax();
+
+ while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
+ (loop++ < MAXLOOP))
+ cpu_relax();
+
+ return loop >= MAXLOOP;
+}
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
new file mode 100644
index 00000000000..29bf854e8cc
--- /dev/null
+++ b/drivers/video/via/accel.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ACCEL_H__
+#define __ACCEL_H__
+
+#define FB_ACCEL_VIA_UNICHROME 50
+
+/* MMIO Base Address Definition */
+#define MMIO_VGABASE 0x8000
+#define MMIO_CR_READ (MMIO_VGABASE + 0x3D4)
+#define MMIO_CR_WRITE (MMIO_VGABASE + 0x3D5)
+#define MMIO_SR_READ (MMIO_VGABASE + 0x3C4)
+#define MMIO_SR_WRITE (MMIO_VGABASE + 0x3C5)
+
+/* HW Cursor Status Define */
+#define HW_Cursor_ON 0
+#define HW_Cursor_OFF 1
+
+#define CURSOR_SIZE (8 * 1024)
+#define VQ_SIZE (256 * 1024)
+
+#define VIA_MMIO_BLTBASE 0x200000
+#define VIA_MMIO_BLTSIZE 0x200000
+
+/* Defines for 2D registers */
+#define VIA_REG_GECMD 0x000
+#define VIA_REG_GEMODE 0x004
+#define VIA_REG_SRCPOS 0x008
+#define VIA_REG_DSTPOS 0x00C
+/* width and height */
+#define VIA_REG_DIMENSION 0x010
+#define VIA_REG_PATADDR 0x014
+#define VIA_REG_FGCOLOR 0x018
+#define VIA_REG_BGCOLOR 0x01C
+/* top and left of clipping */
+#define VIA_REG_CLIPTL 0x020
+/* bottom and right of clipping */
+#define VIA_REG_CLIPBR 0x024
+#define VIA_REG_OFFSET 0x028
+/* color key control */
+#define VIA_REG_KEYCONTROL 0x02C
+#define VIA_REG_SRCBASE 0x030
+#define VIA_REG_DSTBASE 0x034
+/* pitch of src and dst */
+#define VIA_REG_PITCH 0x038
+#define VIA_REG_MONOPAT0 0x03C
+#define VIA_REG_MONOPAT1 0x040
+/* from 0x100 to 0x1ff */
+#define VIA_REG_COLORPAT 0x100
+
+/* VIA_REG_PITCH(0x38): Pitch Setting */
+#define VIA_PITCH_ENABLE 0x80000000
+
+/* defines for VIA HW cursor registers */
+#define VIA_REG_CURSOR_MODE 0x2D0
+#define VIA_REG_CURSOR_POS 0x2D4
+#define VIA_REG_CURSOR_ORG 0x2D8
+#define VIA_REG_CURSOR_BG 0x2DC
+#define VIA_REG_CURSOR_FG 0x2E0
+
+/* VIA_REG_GEMODE(0x04): GE mode */
+#define VIA_GEM_8bpp 0x00000000
+#define VIA_GEM_16bpp 0x00000100
+#define VIA_GEM_32bpp 0x00000300
+
+/* VIA_REG_GECMD(0x00): 2D Engine Command */
+#define VIA_GEC_NOOP 0x00000000
+#define VIA_GEC_BLT 0x00000001
+#define VIA_GEC_LINE 0x00000005
+
+/* Rotate Command */
+#define VIA_GEC_ROT 0x00000008
+
+#define VIA_GEC_SRC_XY 0x00000000
+#define VIA_GEC_SRC_LINEAR 0x00000010
+#define VIA_GEC_DST_XY 0x00000000
+#define VIA_GEC_DST_LINRAT 0x00000020
+
+#define VIA_GEC_SRC_FB 0x00000000
+#define VIA_GEC_SRC_SYS 0x00000040
+#define VIA_GEC_DST_FB 0x00000000
+#define VIA_GEC_DST_SYS 0x00000080
+
+/* source is mono */
+#define VIA_GEC_SRC_MONO 0x00000100
+/* pattern is mono */
+#define VIA_GEC_PAT_MONO 0x00000200
+/* mono src is opaque */
+#define VIA_GEC_MSRC_OPAQUE 0x00000000
+/* mono src is transparent */
+#define VIA_GEC_MSRC_TRANS 0x00000400
+/* pattern is in frame buffer */
+#define VIA_GEC_PAT_FB 0x00000000
+/* pattern is from reg setting */
+#define VIA_GEC_PAT_REG 0x00000800
+
+#define VIA_GEC_CLIP_DISABLE 0x00000000
+#define VIA_GEC_CLIP_ENABLE 0x00001000
+
+#define VIA_GEC_FIXCOLOR_PAT 0x00002000
+
+#define VIA_GEC_INCX 0x00000000
+#define VIA_GEC_DECY 0x00004000
+#define VIA_GEC_INCY 0x00000000
+#define VIA_GEC_DECX 0x00008000
+/* mono pattern is opaque */
+#define VIA_GEC_MPAT_OPAQUE 0x00000000
+/* mono pattern is transparent */
+#define VIA_GEC_MPAT_TRANS 0x00010000
+
+#define VIA_GEC_MONO_UNPACK 0x00000000
+#define VIA_GEC_MONO_PACK 0x00020000
+#define VIA_GEC_MONO_DWORD 0x00000000
+#define VIA_GEC_MONO_WORD 0x00040000
+#define VIA_GEC_MONO_BYTE 0x00080000
+
+#define VIA_GEC_LASTPIXEL_ON 0x00000000
+#define VIA_GEC_LASTPIXEL_OFF 0x00100000
+#define VIA_GEC_X_MAJOR 0x00000000
+#define VIA_GEC_Y_MAJOR 0x00200000
+#define VIA_GEC_QUICK_START 0x00800000
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS 0x400
+#define VIA_REG_CR_TRANSET 0x41C
+#define VIA_REG_CR_TRANSPACE 0x420
+#define VIA_REG_TRANSET 0x43C
+#define VIA_REG_TRANSPACE 0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+
+/* Command Regulator is busy */
+#define VIA_CMD_RGTR_BUSY 0x00000080
+/* 2D Engine is busy */
+#define VIA_2D_ENG_BUSY 0x00000002
+/* 3D Engine is busy */
+#define VIA_3D_ENG_BUSY 0x00000001
+/* Virtual Queue is busy */
+#define VIA_VR_QUEUE_BUSY 0x00020000
+
+#define MAXLOOP 0xFFFFFF
+
+void viafb_init_accel(void);
+void viafb_init_2d_engine(void);
+void set_2d_color_depth(int);
+void viafb_hw_cursor_init(void);
+void viafb_show_hw_cursor(struct fb_info *info, int Status); int
+viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp);
+
+#endif /* __ACCEL_H__ */
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
new file mode 100644
index 00000000000..dde95edc387
--- /dev/null
+++ b/drivers/video/via/chip.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __CHIP_H__
+#define __CHIP_H__
+
+#include "global.h"
+
+/***************************************/
+/* Definition Graphic Chip Information */
+/***************************************/
+
+#define PCI_VIA_VENDOR_ID 0x1106
+
+/* Define VIA Graphic Chip Name */
+#define UNICHROME_CLE266 1
+#define UNICHROME_CLE266_DID 0x3122
+#define CLE266_REVISION_AX 0x0A
+#define CLE266_REVISION_CX 0x0C
+
+#define UNICHROME_K400 2
+#define UNICHROME_K400_DID 0x7205
+
+#define UNICHROME_K800 3
+#define UNICHROME_K800_DID 0x3108
+
+#define UNICHROME_PM800 4
+#define UNICHROME_PM800_DID 0x3118
+
+#define UNICHROME_CN700 5
+#define UNICHROME_CN700_DID 0x3344
+
+#define UNICHROME_CX700 6
+#define UNICHROME_CX700_DID 0x3157
+#define CX700_REVISION_700 0x0
+#define CX700_REVISION_700M 0x1
+#define CX700_REVISION_700M2 0x2
+
+#define UNICHROME_CN750 7
+#define UNICHROME_CN750_DID 0x3225
+
+#define UNICHROME_K8M890 8
+#define UNICHROME_K8M890_DID 0x3230
+
+#define UNICHROME_P4M890 9
+#define UNICHROME_P4M890_DID 0x3343
+
+#define UNICHROME_P4M900 10
+#define UNICHROME_P4M900_DID 0x3371
+
+#define UNICHROME_VX800 11
+#define UNICHROME_VX800_DID 0x1122
+
+/**************************************************/
+/* Definition TMDS Trasmitter Information */
+/**************************************************/
+
+/* Definition TMDS Trasmitter Index */
+#define NON_TMDS_TRANSMITTER 0x00
+#define VT1632_TMDS 0x01
+#define INTEGRATED_TMDS 0x42
+
+/* Definition TMDS Trasmitter I2C Slave Address */
+#define VT1632_TMDS_I2C_ADDR 0x10
+
+/**************************************************/
+/* Definition LVDS Trasmitter Information */
+/**************************************************/
+
+/* Definition LVDS Trasmitter Index */
+#define NON_LVDS_TRANSMITTER 0x00
+#define VT1631_LVDS 0x01
+#define VT1636_LVDS 0x0E
+#define INTEGRATED_LVDS 0x41
+
+/* Definition Digital Transmitter Mode */
+#define TX_DATA_12_BITS 0x01
+#define TX_DATA_24_BITS 0x02
+#define TX_DATA_DDR_MODE 0x04
+#define TX_DATA_SDR_MODE 0x08
+
+/* Definition LVDS Trasmitter I2C Slave Address */
+#define VT1631_LVDS_I2C_ADDR 0x70
+#define VT3271_LVDS_I2C_ADDR 0x80
+#define VT1636_LVDS_I2C_ADDR 0x80
+
+struct tmds_chip_information {
+ int tmds_chip_name;
+ int tmds_chip_slave_addr;
+ int dvi_panel_id;
+ int data_mode;
+ int output_interface;
+ int i2c_port;
+ int device_type;
+};
+
+struct lvds_chip_information {
+ int lvds_chip_name;
+ int lvds_chip_slave_addr;
+ int data_mode;
+ int output_interface;
+ int i2c_port;
+};
+
+struct chip_information {
+ int gfx_chip_name;
+ int gfx_chip_revision;
+ int chip_on_slot;
+ struct tmds_chip_information tmds_chip_info;
+ struct lvds_chip_information lvds_chip_info;
+ struct lvds_chip_information lvds_chip_info2;
+};
+
+struct crt_setting_information {
+ int iga_path;
+ int h_active;
+ int v_active;
+ int bpp;
+ int refresh_rate;
+};
+
+struct tmds_setting_information {
+ int iga_path;
+ int h_active;
+ int v_active;
+ int bpp;
+ int refresh_rate;
+ int get_dvi_size_method;
+ int max_pixel_clock;
+ int dvi_panel_size;
+ int dvi_panel_hres;
+ int dvi_panel_vres;
+ int native_size;
+};
+
+struct lvds_setting_information {
+ int iga_path;
+ int h_active;
+ int v_active;
+ int bpp;
+ int refresh_rate;
+ int get_lcd_size_method;
+ int lcd_panel_id;
+ int lcd_panel_size;
+ int lcd_panel_hres;
+ int lcd_panel_vres;
+ int display_method;
+ int device_lcd_dualedge;
+ int LCDDithering;
+ int lcd_mode;
+ u32 vclk; /*panel mode clock value */
+};
+
+struct GFX_DPA_SETTING {
+ int ClkRangeIndex;
+ u8 DVP0; /* CR96[3:0] */
+ u8 DVP0DataDri_S1; /* SR2A[5] */
+ u8 DVP0DataDri_S; /* SR1B[1] */
+ u8 DVP0ClockDri_S1; /* SR2A[4] */
+ u8 DVP0ClockDri_S; /* SR1E[2] */
+ u8 DVP1; /* CR9B[3:0] */
+ u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */
+ u8 DFPHigh; /* CR97[3:0] */
+ u8 DFPLow; /* CR99[3:0] */
+
+};
+
+struct VT1636_DPA_SETTING {
+ int PanelSizeID;
+ u8 CLK_SEL_ST1;
+ u8 CLK_SEL_ST2;
+};
+#endif /* __CHIP_H__ */
diff --git a/drivers/video/via/debug.h b/drivers/video/via/debug.h
new file mode 100644
index 00000000000..86eacc2017f
--- /dev/null
+++ b/drivers/video/via/debug.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#ifndef VIAFB_DEBUG
+#define VIAFB_DEBUG 0
+#endif
+
+#if VIAFB_DEBUG
+#define DEBUG_MSG(f, a...) printk(f, ## a)
+#else
+#define DEBUG_MSG(f, a...)
+#endif
+
+#define VIAFB_WARN 0
+#if VIAFB_WARN
+#define WARN_MSG(f, a...) printk(f, ## a)
+#else
+#define WARN_MSG(f, a...)
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
new file mode 100644
index 00000000000..d6965447ca6
--- /dev/null
+++ b/drivers/video/via/dvi.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "global.h"
+
+static void tmds_register_write(int index, u8 data);
+static int tmds_register_read(int index);
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
+static int check_reduce_blanking_mode(int mode_index,
+ int refresh_rate);
+static int dvi_get_panel_size_from_DDCv1(void);
+static int dvi_get_panel_size_from_DDCv2(void);
+static unsigned char dvi_get_panel_info(void);
+static int viafb_dvi_query_EDID(void);
+
+static int check_tmds_chip(int device_id_subaddr, int device_id)
+{
+ if (tmds_register_read(device_id_subaddr) == device_id)
+ return OK;
+ else
+ return FAIL;
+}
+
+void viafb_init_dvi_size(void)
+{
+ DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
+ DEBUG_MSG(KERN_INFO
+ "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
+ viaparinfo->tmds_setting_info->get_dvi_size_method);
+
+ switch (viaparinfo->tmds_setting_info->get_dvi_size_method) {
+ case GET_DVI_SIZE_BY_SYSTEM_BIOS:
+ break;
+ case GET_DVI_SZIE_BY_HW_STRAPPING:
+ break;
+ case GET_DVI_SIZE_BY_VGA_BIOS:
+ default:
+ dvi_get_panel_info();
+ break;
+ }
+ return;
+}
+
+int viafb_tmds_trasmitter_identify(void)
+{
+ unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
+
+ /* Turn on ouputting pad */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ /*=* DFP Low Pad on *=*/
+ sr2a = viafb_read_reg(VIASR, SR2A);
+ viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+ break;
+
+ case UNICHROME_P4M900:
+ case UNICHROME_P4M890:
+ /* DFP Low Pad on */
+ sr2a = viafb_read_reg(VIASR, SR2A);
+ viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+ /* DVP0 Pad on */
+ sr1e = viafb_read_reg(VIASR, SR1E);
+ viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
+ break;
+
+ default:
+ /* DVP0/DVP1 Pad on */
+ sr1e = viafb_read_reg(VIASR, SR1E);
+ viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
+ BIT5 + BIT6 + BIT7);
+ /* SR3E[1]Multi-function selection:
+ 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+ sr3e = viafb_read_reg(VIASR, SR3E);
+ viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
+ break;
+ }
+
+ /* Check for VT1632: */
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
+ viaparinfo->chip_info->
+ tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+ viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX;
+ if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
+ /*
+ * Currently only support 12bits,dual edge,add 24bits mode later
+ */
+ tmds_register_write(0x08, 0x3b);
+
+ DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->tmds_chip_info.i2c_port);
+ return OK;
+ } else {
+ viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX;
+ if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
+ != FAIL) {
+ tmds_register_write(0x08, 0x3b);
+ DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->
+ tmds_chip_info.tmds_chip_name);
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->
+ tmds_chip_info.i2c_port);
+ return OK;
+ }
+ }
+
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
+
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
+ ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
+ (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
+ DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
+ return OK;
+ }
+
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ viafb_write_reg(SR2A, VIASR, sr2a);
+ break;
+
+ case UNICHROME_P4M900:
+ case UNICHROME_P4M890:
+ viafb_write_reg(SR2A, VIASR, sr2a);
+ viafb_write_reg(SR1E, VIASR, sr1e);
+ break;
+
+ default:
+ viafb_write_reg(SR1E, VIASR, sr1e);
+ viafb_write_reg(SR3E, VIASR, sr3e);
+ break;
+ }
+
+ viaparinfo->chip_info->
+ tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
+ viaparinfo->chip_info->tmds_chip_info.
+ tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+ return FAIL;
+}
+
+static void tmds_register_write(int index, u8 data)
+{
+ viaparinfo->i2c_stuff.i2c_port =
+ viaparinfo->chip_info->tmds_chip_info.i2c_port;
+
+ viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
+ tmds_chip_slave_addr, index,
+ data);
+}
+
+static int tmds_register_read(int index)
+{
+ u8 data;
+
+ viaparinfo->i2c_stuff.i2c_port =
+ viaparinfo->chip_info->tmds_chip_info.i2c_port;
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->
+ tmds_chip_info.tmds_chip_slave_addr,
+ (u8) index, &data);
+ return data;
+}
+
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
+{
+ viaparinfo->i2c_stuff.i2c_port =
+ viaparinfo->chip_info->tmds_chip_info.i2c_port;
+ viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
+ tmds_chip_slave_addr, (u8) index, buff, buff_len);
+ return 0;
+}
+
+static int check_reduce_blanking_mode(int mode_index,
+ int refresh_rate)
+{
+ if (refresh_rate != 60)
+ return false;
+
+ switch (mode_index) {
+ /* Following modes have reduce blanking mode. */
+ case VIA_RES_1360X768:
+ case VIA_RES_1400X1050:
+ case VIA_RES_1440X900:
+ case VIA_RES_1600X900:
+ case VIA_RES_1680X1050:
+ case VIA_RES_1920X1080:
+ case VIA_RES_1920X1200:
+ break;
+
+ default:
+ DEBUG_MSG(KERN_INFO
+ "This dvi mode %d have no reduce blanking mode!\n",
+ mode_index);
+ return false;
+ }
+
+ return true;
+}
+
+/* DVI Set Mode */
+void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
+{
+ struct VideoModeTable *videoMode = NULL;
+ struct crt_mode_table *pDviTiming;
+ unsigned long desirePixelClock, maxPixelClock;
+ int status = 0;
+ videoMode = viafb_get_modetbl_pointer(video_index);
+ pDviTiming = videoMode->crtc;
+ desirePixelClock = pDviTiming->clk / 1000000;
+ maxPixelClock = (unsigned long)viaparinfo->
+ tmds_setting_info->max_pixel_clock;
+
+ DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
+
+ if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
+ /*Check if reduce-blanking mode is exist */
+ status =
+ check_reduce_blanking_mode(video_index,
+ pDviTiming->refresh_rate);
+ if (status) {
+ video_index += 100; /*Use reduce-blanking mode */
+ videoMode = viafb_get_modetbl_pointer(video_index);
+ pDviTiming = videoMode->crtc;
+ DEBUG_MSG(KERN_INFO
+ "DVI use reduce blanking mode %d!!\n",
+ video_index);
+ }
+ }
+ viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga);
+ viafb_set_output_path(DEVICE_DVI, set_iga,
+ viaparinfo->chip_info->tmds_chip_info.output_interface);
+}
+
+/* Sense DVI Connector */
+int viafb_dvi_sense(void)
+{
+ u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
+ RegCR93 = 0, RegCR9B = 0, data;
+ int ret = false;
+
+ DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ /* DI1 Pad on */
+ RegSR1E = viafb_read_reg(VIASR, SR1E);
+ viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
+
+ /* CR6B[0]VCK Input Selection: 1 = External clock. */
+ RegCR6B = viafb_read_reg(VIACR, CR6B);
+ viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
+
+ /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+ [0] Software Control Power Sequence */
+ RegCR91 = viafb_read_reg(VIACR, CR91);
+ viafb_write_reg(CR91, VIACR, 0x1D);
+
+ /* CR93[7] DI1 Data Source Selection: 1 = DSP2.
+ CR93[5] DI1 Clock Source: 1 = internal.
+ CR93[4] DI1 Clock Polarity.
+ CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
+ RegCR93 = viafb_read_reg(VIACR, CR93);
+ viafb_write_reg(CR93, VIACR, 0x01);
+ } else {
+ /* DVP0/DVP1 Pad on */
+ RegSR1E = viafb_read_reg(VIASR, SR1E);
+ viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
+
+ /* SR3E[1]Multi-function selection:
+ 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+ RegSR3E = viafb_read_reg(VIASR, SR3E);
+ viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
+
+ /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+ [0] Software Control Power Sequence */
+ RegCR91 = viafb_read_reg(VIACR, CR91);
+ viafb_write_reg(CR91, VIACR, 0x1D);
+
+ /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
+ display.CR9B[2:0] DVP1 Clock Adjust */
+ RegCR9B = viafb_read_reg(VIACR, CR9B);
+ viafb_write_reg(CR9B, VIACR, 0x01);
+ }
+
+ data = (u8) tmds_register_read(0x09);
+ if (data & 0x04)
+ ret = true;
+
+ if (ret == false) {
+ if (viafb_dvi_query_EDID())
+ ret = true;
+ }
+
+ /* Restore status */
+ viafb_write_reg(SR1E, VIASR, RegSR1E);
+ viafb_write_reg(CR91, VIACR, RegCR91);
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ viafb_write_reg(CR6B, VIACR, RegCR6B);
+ viafb_write_reg(CR93, VIACR, RegCR93);
+ } else {
+ viafb_write_reg(SR3E, VIASR, RegSR3E);
+ viafb_write_reg(CR9B, VIACR, RegCR9B);
+ }
+
+ return ret;
+}
+
+/* Query Flat Panel's EDID Table Version Through DVI Connector */
+static int viafb_dvi_query_EDID(void)
+{
+ u8 data0, data1;
+ int restore;
+
+ DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
+
+ restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+
+ data0 = (u8) tmds_register_read(0x00);
+ data1 = (u8) tmds_register_read(0x01);
+ if ((data0 == 0) && (data1 == 0xFF)) {
+ viaparinfo->chip_info->
+ tmds_chip_info.tmds_chip_slave_addr = restore;
+ return EDID_VERSION_1; /* Found EDID1 Table */
+ }
+
+ data0 = (u8) tmds_register_read(0x00);
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+ if (data0 == 0x20)
+ return EDID_VERSION_2; /* Found EDID2 Table */
+ else
+ return false;
+}
+
+/*
+ *
+ * int dvi_get_panel_size_from_DDCv1(void)
+ *
+ * - Get Panel Size Using EDID1 Table
+ *
+ * Return Type: int
+ *
+ */
+static int dvi_get_panel_size_from_DDCv1(void)
+{
+ int i, max_h = 0, max_v = 0, tmp, restore;
+ unsigned char rData;
+ unsigned char EDID_DATA[18];
+
+ DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
+
+ restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+
+ rData = tmds_register_read(0x23);
+ if (rData & 0x3C)
+ max_h = 640;
+ if (rData & 0xC0)
+ max_h = 720;
+ if (rData & 0x03)
+ max_h = 800;
+
+ rData = tmds_register_read(0x24);
+ if (rData & 0xC0)
+ max_h = 800;
+ if (rData & 0x1E)
+ max_h = 1024;
+ if (rData & 0x01)
+ max_h = 1280;
+
+ for (i = 0x25; i < 0x6D; i++) {
+ switch (i) {
+ case 0x26:
+ case 0x28:
+ case 0x2A:
+ case 0x2C:
+ case 0x2E:
+ case 0x30:
+ case 0x32:
+ case 0x34:
+ rData = tmds_register_read(i);
+ if (rData == 1)
+ break;
+ /* data = (data + 31) * 8 */
+ tmp = (rData + 31) << 3;
+ if (tmp > max_h)
+ max_h = tmp;
+ break;
+
+ case 0x36:
+ case 0x48:
+ case 0x5A:
+ case 0x6C:
+ tmds_register_read_bytes(i, EDID_DATA, 10);
+ if (!(EDID_DATA[0] || EDID_DATA[1])) {
+ /* The first two byte must be zero. */
+ if (EDID_DATA[3] == 0xFD) {
+ /* To get max pixel clock. */
+ viaparinfo->tmds_setting_info->
+ max_pixel_clock = EDID_DATA[9] * 10;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (max_h) {
+ case 640:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_640X480;
+ break;
+ case 800:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_800X600;
+ break;
+ case 1024:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1024X768;
+ break;
+ case 1280:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1280X1024;
+ break;
+ case 1400:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1400X1050;
+ break;
+ case 1440:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1440X1050;
+ break;
+ case 1600:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1600X1200;
+ break;
+ case 1920:
+ if (max_v == 1200) {
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1920X1200;
+ } else {
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1920X1080;
+ }
+
+ break;
+ default:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1024X768;
+ DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\
+ set default panel size.\n", max_h);
+ break;
+ }
+
+ DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
+ viaparinfo->tmds_setting_info->max_pixel_clock);
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+ return viaparinfo->tmds_setting_info->dvi_panel_size;
+}
+
+/*
+ *
+ * int dvi_get_panel_size_from_DDCv2(void)
+ *
+ * - Get Panel Size Using EDID2 Table
+ *
+ * Return Type: int
+ *
+ */
+static int dvi_get_panel_size_from_DDCv2(void)
+{
+ int HSize = 0, restore;
+ unsigned char R_Buffer[2];
+
+ DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
+
+ restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2;
+
+ /* Horizontal: 0x76, 0x77 */
+ tmds_register_read_bytes(0x76, R_Buffer, 2);
+ HSize = R_Buffer[0];
+ HSize += R_Buffer[1] << 8;
+
+ switch (HSize) {
+ case 640:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_640X480;
+ break;
+ case 800:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_800X600;
+ break;
+ case 1024:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1024X768;
+ break;
+ case 1280:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1280X1024;
+ break;
+ case 1400:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1400X1050;
+ break;
+ case 1440:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1440X1050;
+ break;
+ case 1600:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1600X1200;
+ break;
+ default:
+ viaparinfo->tmds_setting_info->dvi_panel_size =
+ VIA_RES_1024X768;
+ DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\
+ set default panel size.\n", HSize);
+ break;
+ }
+
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+ return viaparinfo->tmds_setting_info->dvi_panel_size;
+}
+
+/*
+ *
+ * unsigned char dvi_get_panel_info(void)
+ *
+ * - Get Panel Size
+ *
+ * Return Type: unsigned char
+ */
+static unsigned char dvi_get_panel_info(void)
+{
+ unsigned char dvipanelsize;
+ DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
+
+ viafb_dvi_sense();
+ switch (viafb_dvi_query_EDID()) {
+ case 1:
+ dvi_get_panel_size_from_DDCv1();
+ break;
+ case 2:
+ dvi_get_panel_size_from_DDCv2();
+ break;
+ default:
+ break;
+ }
+
+ DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n",
+ viaparinfo->tmds_setting_info->dvi_panel_size);
+ dvipanelsize = (unsigned char)(viaparinfo->
+ tmds_setting_info->dvi_panel_size);
+ return dvipanelsize;
+}
+
+/* If Disable DVI, turn off pad */
+void viafb_dvi_disable(void)
+{
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DVP0)
+ viafb_write_reg(SR1E, VIASR,
+ viafb_read_reg(VIASR, SR1E) & (~0xC0));
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DVP1)
+ viafb_write_reg(SR1E, VIASR,
+ viafb_read_reg(VIASR, SR1E) & (~0x30));
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
+ viafb_write_reg(SR2A, VIASR,
+ viafb_read_reg(VIASR, SR2A) & (~0x0C));
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
+ viafb_write_reg(SR2A, VIASR,
+ viafb_read_reg(VIASR, SR2A) & (~0x03));
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_TMDS)
+ /* Turn off TMDS power. */
+ viafb_write_reg(CRD2, VIACR,
+ viafb_read_reg(VIACR, CRD2) | 0x08);
+}
+
+/* If Enable DVI, turn off pad */
+void viafb_dvi_enable(void)
+{
+ u8 data;
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DVP0) {
+ viafb_write_reg(SR1E, VIASR,
+ viafb_read_reg(VIASR, SR1E) | 0xC0);
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+ tmds_register_write(0x88, 0x3b);
+ else
+ /*clear CR91[5] to direct on display period
+ in the secondary diplay path */
+ viafb_write_reg(CR91, VIACR,
+ viafb_read_reg(VIACR, CR91) & 0xDF);
+ }
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DVP1) {
+ viafb_write_reg(SR1E, VIASR,
+ viafb_read_reg(VIASR, SR1E) | 0x30);
+
+ /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ tmds_register_write(0x88, 0x3b);
+ } else {
+ /*clear CR91[5] to direct on display period
+ in the secondary diplay path */
+ viafb_write_reg(CR91, VIACR,
+ viafb_read_reg(VIACR, CR91) & 0xDF);
+ }
+
+ /*fix DVI cannot enable on EPIA-M board */
+ if (viafb_platform_epia_dvi == 1) {
+ viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
+ viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
+ if (viafb_bus_width == 24) {
+ if (viafb_device_lcd_dualedge == 1)
+ data = 0x3F;
+ else
+ data = 0x37;
+ viafb_i2c_writebyte(viaparinfo->chip_info->
+ tmds_chip_info.
+ tmds_chip_slave_addr,
+ 0x08, data);
+ }
+ }
+ }
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
+ viafb_write_reg(SR2A, VIASR,
+ viafb_read_reg(VIASR, SR2A) | 0x0C);
+ viafb_write_reg(CR91, VIACR,
+ viafb_read_reg(VIACR, CR91) & 0xDF);
+ }
+
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
+ viafb_write_reg(SR2A, VIASR,
+ viafb_read_reg(VIASR, SR2A) | 0x03);
+ viafb_write_reg(CR91, VIACR,
+ viafb_read_reg(VIACR, CR91) & 0xDF);
+ }
+ if (viaparinfo->chip_info->
+ tmds_chip_info.output_interface == INTERFACE_TMDS) {
+ /* Turn on Display period in the panel path. */
+ viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
+
+ /* Turn on TMDS power. */
+ viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
+ }
+}
+
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
new file mode 100644
index 00000000000..e1ec37fb0dc
--- /dev/null
+++ b/drivers/video/via/dvi.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DVI_H__
+#define __DVI_H__
+
+/*Definition TMDS Device ID register*/
+#define VT1632_DEVICE_ID_REG 0x02
+#define VT1632_DEVICE_ID 0x92
+
+#define GET_DVI_SIZE_BY_SYSTEM_BIOS 0x01
+#define GET_DVI_SIZE_BY_VGA_BIOS 0x02
+#define GET_DVI_SZIE_BY_HW_STRAPPING 0x03
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480, Channel: single, Dithering: Enable */
+#define DVI_PANEL_ID0_640X480 0x00
+/* Resolution: 800x600, Channel: single, Dithering: Enable */
+#define DVI_PANEL_ID1_800x600 0x01
+/* Resolution: 1024x768, Channel: single, Dithering: Enable */
+#define DVI_PANEL_ID1_1024x768 0x02
+/* Resolution: 1280x768, Channel: single, Dithering: Enable */
+#define DVI_PANEL_ID1_1280x768 0x03
+/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
+#define DVI_PANEL_ID1_1280x1024 0x04
+/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
+#define DVI_PANEL_ID1_1400x1050 0x05
+/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
+#define DVI_PANEL_ID1_1600x1200 0x06
+
+/* Define the version of EDID*/
+#define EDID_VERSION_1 1
+#define EDID_VERSION_2 2
+
+#define DEV_CONNECT_DVI 0x01
+#define DEV_CONNECT_HDMI 0x02
+
+struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
+int viafb_dvi_sense(void);
+void viafb_dvi_disable(void);
+void viafb_dvi_enable(void);
+int viafb_tmds_trasmitter_identify(void);
+void viafb_init_dvi_size(void);
+void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga);
+
+#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
new file mode 100644
index 00000000000..468be2425af
--- /dev/null
+++ b/drivers/video/via/global.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "global.h"
+int viafb_platform_epia_dvi = STATE_OFF;
+int viafb_device_lcd_dualedge = STATE_OFF;
+int viafb_bus_width = 12;
+int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
+int viafb_memsize;
+int viafb_DeviceStatus = CRT_Device;
+int viafb_hotplug;
+int viafb_refresh = 60;
+int viafb_refresh1 = 60;
+int viafb_lcd_dsp_method = LCD_EXPANDSION;
+int viafb_lcd_mode = LCD_OPENLDI;
+int viafb_bpp = 32;
+int viafb_bpp1 = 32;
+int viafb_accel = 1;
+int viafb_CRT_ON = 1;
+int viafb_DVI_ON;
+int viafb_LCD_ON ;
+int viafb_LCD2_ON;
+int viafb_SAMM_ON;
+int viafb_dual_fb;
+int viafb_hotplug_Xres = 640;
+int viafb_hotplug_Yres = 480;
+int viafb_hotplug_bpp = 32;
+int viafb_hotplug_refresh = 60;
+unsigned int viafb_second_offset;
+int viafb_second_size;
+int viafb_primary_dev = None_Device;
+void __iomem *viafb_FB_MM;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
+unsigned int viafb_second_virtual_xres;
+unsigned int viafb_second_virtual_yres;
+int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
+struct fb_cursor viacursor;
+struct fb_info *viafbinfo;
+struct fb_info *viafbinfo1;
+struct viafb_par *viaparinfo;
+struct viafb_par *viaparinfo1;
+
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
new file mode 100644
index 00000000000..8e5263c5b81
--- /dev/null
+++ b/drivers/video/via/global.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GLOBAL_H__
+#define __GLOBAL_H__
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+
+#include "debug.h"
+
+#include "iface.h"
+#include "viafbdev.h"
+#include "chip.h"
+#include "debug.h"
+#include "accel.h"
+#include "share.h"
+#include "dvi.h"
+#include "viamode.h"
+#include "via_i2c.h"
+#include "hw.h"
+
+#include "lcd.h"
+#include "ioctl.h"
+#include "viamode.h"
+#include "via_utility.h"
+#include "vt1636.h"
+#include "tblDPASetting.h"
+#include "tbl1636.h"
+#include "viafbdev.h"
+
+/* External struct*/
+
+extern int viafb_platform_epia_dvi;
+extern int viafb_device_lcd_dualedge;
+extern int viafb_bus_width;
+extern int viafb_display_hardware_layout;
+extern struct offset offset_reg;
+extern struct viafb_par *viaparinfo;
+extern struct viafb_par *viaparinfo1;
+extern struct fb_info *viafbinfo;
+extern struct fb_info *viafbinfo1;
+extern int viafb_DeviceStatus;
+extern int viafb_refresh;
+extern int viafb_refresh1;
+extern int viafb_lcd_dsp_method;
+extern int viafb_lcd_mode;
+extern int viafb_bpp;
+extern int viafb_bpp1;
+
+extern int viafb_CRT_ON;
+extern int viafb_hotplug_Xres;
+extern int viafb_hotplug_Yres;
+extern int viafb_hotplug_bpp;
+extern int viafb_hotplug_refresh;
+extern int viafb_primary_dev;
+extern void __iomem *viafb_FB_MM;
+extern struct fb_cursor viacursor;
+
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
+extern int viafb_lcd_panel_id;
+
+#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
new file mode 100644
index 00000000000..fcd53ceb88f
--- /dev/null
+++ b/drivers/video/via/hw.c
@@ -0,0 +1,2865 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+static const struct pci_device_id_info pciidlist[] = {
+ {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266},
+ {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800},
+ {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400},
+ {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800},
+ {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700},
+ {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890},
+ {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890},
+ {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700},
+ {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900},
+ {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750},
+ {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800},
+ {0, 0, 0}
+};
+
+struct offset offset_reg = {
+ /* IGA1 Offset Register */
+ {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } },
+ /* IGA2 Offset Register */
+ {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } }
+};
+
+static struct pll_map pll_value[] = {
+ {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M},
+ {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M},
+ {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M},
+ {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M},
+ {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M},
+ {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M},
+ {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M},
+ {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M},
+ {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M},
+ {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M},
+ {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M},
+ {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M},
+ {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M},
+ {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M},
+ {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M},
+ {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M},
+ {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M},
+ {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M},
+ {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M},
+ {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M},
+ {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M},
+ {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M},
+ {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M},
+ {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M},
+ {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M},
+ {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M},
+ {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M},
+ {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M},
+ {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M},
+ {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M},
+ {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M},
+ {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M},
+ {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M},
+ {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M},
+ {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M},
+ {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M},
+ {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M},
+ {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M},
+ {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
+ CX700_101_000M},
+ {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
+ CX700_106_500M},
+ {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
+ CX700_108_000M},
+ {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
+ CX700_113_309M},
+ {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
+ CX700_118_840M},
+ {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
+ CX700_119_000M},
+ {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
+ CX700_121_750M},
+ {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
+ CX700_125_104M},
+ {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
+ CX700_133_308M},
+ {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
+ CX700_135_000M},
+ {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
+ CX700_136_700M},
+ {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
+ CX700_138_400M},
+ {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
+ CX700_146_760M},
+ {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
+ CX700_153_920M},
+ {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
+ CX700_156_000M},
+ {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
+ CX700_157_500M},
+ {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
+ CX700_162_000M},
+ {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
+ CX700_187_000M},
+ {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
+ CX700_193_295M},
+ {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
+ CX700_202_500M},
+ {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
+ CX700_204_000M},
+ {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
+ CX700_218_500M},
+ {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
+ CX700_234_000M},
+ {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
+ CX700_267_250M},
+ {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
+ CX700_297_500M},
+ {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M},
+ {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
+ CX700_172_798M},
+ {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
+ CX700_122_614M},
+ {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M},
+ {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
+ CX700_148_500M}
+};
+
+static struct fifo_depth_select display_fifo_depth_reg = {
+ /* IGA1 FIFO Depth_Select */
+ {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
+ /* IGA2 FIFO Depth_Select */
+ {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
+ {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
+};
+
+static struct fifo_threshold_select fifo_threshold_select_reg = {
+ /* IGA1 FIFO Threshold Select */
+ {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
+ /* IGA2 FIFO Threshold Select */
+ {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
+};
+
+static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
+ /* IGA1 FIFO High Threshold Select */
+ {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
+ /* IGA2 FIFO High Threshold Select */
+ {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
+};
+
+static struct display_queue_expire_num display_queue_expire_num_reg = {
+ /* IGA1 Display Queue Expire Num */
+ {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
+ /* IGA2 Display Queue Expire Num */
+ {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
+};
+
+/* Definition Fetch Count Registers*/
+static struct fetch_count fetch_count_reg = {
+ /* IGA1 Fetch Count Register */
+ {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
+ /* IGA2 Fetch Count Register */
+ {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
+};
+
+static struct iga1_crtc_timing iga1_crtc_reg = {
+ /* IGA1 Horizontal Total */
+ {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
+ /* IGA1 Horizontal Addressable Video */
+ {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
+ /* IGA1 Horizontal Blank Start */
+ {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
+ /* IGA1 Horizontal Blank End */
+ {IGA1_HOR_BLANK_END_REG_NUM,
+ {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
+ /* IGA1 Horizontal Sync Start */
+ {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
+ /* IGA1 Horizontal Sync End */
+ {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
+ /* IGA1 Vertical Total */
+ {IGA1_VER_TOTAL_REG_NUM,
+ {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
+ /* IGA1 Vertical Addressable Video */
+ {IGA1_VER_ADDR_REG_NUM,
+ {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
+ /* IGA1 Vertical Blank Start */
+ {IGA1_VER_BLANK_START_REG_NUM,
+ {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
+ /* IGA1 Vertical Blank End */
+ {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
+ /* IGA1 Vertical Sync Start */
+ {IGA1_VER_SYNC_START_REG_NUM,
+ {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
+ /* IGA1 Vertical Sync End */
+ {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
+};
+
+static struct iga2_crtc_timing iga2_crtc_reg = {
+ /* IGA2 Horizontal Total */
+ {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
+ /* IGA2 Horizontal Addressable Video */
+ {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
+ /* IGA2 Horizontal Blank Start */
+ {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
+ /* IGA2 Horizontal Blank End */
+ {IGA2_HOR_BLANK_END_REG_NUM,
+ {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
+ /* IGA2 Horizontal Sync Start */
+ {IGA2_HOR_SYNC_START_REG_NUM,
+ {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
+ /* IGA2 Horizontal Sync End */
+ {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
+ /* IGA2 Vertical Total */
+ {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
+ /* IGA2 Vertical Addressable Video */
+ {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
+ /* IGA2 Vertical Blank Start */
+ {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
+ /* IGA2 Vertical Blank End */
+ {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
+ /* IGA2 Vertical Sync Start */
+ {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
+ /* IGA2 Vertical Sync End */
+ {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
+};
+
+static struct rgbLUT palLUT_table[] = {
+ /* {R,G,B} */
+ /* Index 0x00~0x03 */
+ {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
+ 0x2A,
+ 0x2A},
+ /* Index 0x04~0x07 */
+ {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
+ 0x2A,
+ 0x2A},
+ /* Index 0x08~0x0B */
+ {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
+ 0x3F,
+ 0x3F},
+ /* Index 0x0C~0x0F */
+ {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
+ 0x3F,
+ 0x3F},
+ /* Index 0x10~0x13 */
+ {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
+ 0x0B,
+ 0x0B},
+ /* Index 0x14~0x17 */
+ {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
+ 0x18,
+ 0x18},
+ /* Index 0x18~0x1B */
+ {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
+ 0x28,
+ 0x28},
+ /* Index 0x1C~0x1F */
+ {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
+ 0x3F,
+ 0x3F},
+ /* Index 0x20~0x23 */
+ {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
+ 0x00,
+ 0x3F},
+ /* Index 0x24~0x27 */
+ {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
+ 0x00,
+ 0x10},
+ /* Index 0x28~0x2B */
+ {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
+ 0x2F,
+ 0x00},
+ /* Index 0x2C~0x2F */
+ {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
+ 0x3F,
+ 0x00},
+ /* Index 0x30~0x33 */
+ {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
+ 0x3F,
+ 0x2F},
+ /* Index 0x34~0x37 */
+ {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
+ 0x10,
+ 0x3F},
+ /* Index 0x38~0x3B */
+ {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
+ 0x1F,
+ 0x3F},
+ /* Index 0x3C~0x3F */
+ {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
+ 0x1F,
+ 0x27},
+ /* Index 0x40~0x43 */
+ {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
+ 0x3F,
+ 0x1F},
+ /* Index 0x44~0x47 */
+ {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
+ 0x3F,
+ 0x1F},
+ /* Index 0x48~0x4B */
+ {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
+ 0x3F,
+ 0x37},
+ /* Index 0x4C~0x4F */
+ {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
+ 0x27,
+ 0x3F},
+ /* Index 0x50~0x53 */
+ {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
+ 0x2D,
+ 0x3F},
+ /* Index 0x54~0x57 */
+ {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
+ 0x2D,
+ 0x31},
+ /* Index 0x58~0x5B */
+ {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
+ 0x3A,
+ 0x2D},
+ /* Index 0x5C~0x5F */
+ {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
+ 0x3F,
+ 0x2D},
+ /* Index 0x60~0x63 */
+ {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
+ 0x3F,
+ 0x3A},
+ /* Index 0x64~0x67 */
+ {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
+ 0x31,
+ 0x3F},
+ /* Index 0x68~0x6B */
+ {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
+ 0x00,
+ 0x1C},
+ /* Index 0x6C~0x6F */
+ {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
+ 0x00,
+ 0x07},
+ /* Index 0x70~0x73 */
+ {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
+ 0x15,
+ 0x00},
+ /* Index 0x74~0x77 */
+ {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
+ 0x1C,
+ 0x00},
+ /* Index 0x78~0x7B */
+ {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
+ 0x1C,
+ 0x15},
+ /* Index 0x7C~0x7F */
+ {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
+ 0x07,
+ 0x1C},
+ /* Index 0x80~0x83 */
+ {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
+ 0x0E,
+ 0x1C},
+ /* Index 0x84~0x87 */
+ {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
+ 0x0E,
+ 0x11},
+ /* Index 0x88~0x8B */
+ {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
+ 0x18,
+ 0x0E},
+ /* Index 0x8C~0x8F */
+ {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
+ 0x1C,
+ 0x0E},
+ /* Index 0x90~0x93 */
+ {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
+ 0x1C,
+ 0x18},
+ /* Index 0x94~0x97 */
+ {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
+ 0x11,
+ 0x1C},
+ /* Index 0x98~0x9B */
+ {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
+ 0x14,
+ 0x1C},
+ /* Index 0x9C~0x9F */
+ {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
+ 0x14,
+ 0x16},
+ /* Index 0xA0~0xA3 */
+ {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
+ 0x1A,
+ 0x14},
+ /* Index 0xA4~0xA7 */
+ {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
+ 0x1C,
+ 0x14},
+ /* Index 0xA8~0xAB */
+ {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
+ 0x1C,
+ 0x1A},
+ /* Index 0xAC~0xAF */
+ {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
+ 0x16,
+ 0x1C},
+ /* Index 0xB0~0xB3 */
+ {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
+ 0x00,
+ 0x10},
+ /* Index 0xB4~0xB7 */
+ {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
+ 0x00,
+ 0x04},
+ /* Index 0xB8~0xBB */
+ {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
+ 0x0C,
+ 0x00},
+ /* Index 0xBC~0xBF */
+ {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
+ 0x10,
+ 0x00},
+ /* Index 0xC0~0xC3 */
+ {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
+ 0x10,
+ 0x0C},
+ /* Index 0xC4~0xC7 */
+ {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
+ 0x04,
+ 0x10},
+ /* Index 0xC8~0xCB */
+ {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
+ 0x08,
+ 0x10},
+ /* Index 0xCC~0xCF */
+ {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
+ 0x08,
+ 0x0A},
+ /* Index 0xD0~0xD3 */
+ {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
+ 0x0E,
+ 0x08},
+ /* Index 0xD4~0xD7 */
+ {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
+ 0x10,
+ 0x08},
+ /* Index 0xD8~0xDB */
+ {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
+ 0x10,
+ 0x0E},
+ /* Index 0xDC~0xDF */
+ {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
+ 0x0A,
+ 0x10},
+ /* Index 0xE0~0xE3 */
+ {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
+ 0x0B,
+ 0x10},
+ /* Index 0xE4~0xE7 */
+ {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
+ 0x0B,
+ 0x0C},
+ /* Index 0xE8~0xEB */
+ {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
+ 0x0F,
+ 0x0B},
+ /* Index 0xEC~0xEF */
+ {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
+ 0x10,
+ 0x0B},
+ /* Index 0xF0~0xF3 */
+ {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
+ 0x10,
+ 0x0F},
+ /* Index 0xF4~0xF7 */
+ {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
+ 0x0C,
+ 0x10},
+ /* Index 0xF8~0xFB */
+ {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+ 0x00,
+ 0x00},
+ /* Index 0xFC~0xFF */
+ {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+ 0x00,
+ 0x00}
+};
+
+static void set_crt_output_path(int set_iga);
+static void dvi_patch_skew_dvp0(void);
+static void dvi_patch_skew_dvp1(void);
+static void dvi_patch_skew_dvp_low(void);
+static void set_dvi_output_path(int set_iga, int output_interface);
+static void set_lcd_output_path(int set_iga, int output_interface);
+static int search_mode_setting(int ModeInfoIndex);
+static void load_fix_bit_crtc_reg(void);
+static void init_gfx_chip_info(void);
+static void init_tmds_chip_info(void);
+static void init_lvds_chip_info(void);
+static void device_screen_off(void);
+static void device_screen_on(void);
+static void set_display_channel(void);
+static void device_off(void);
+static void device_on(void);
+static void enable_second_display_channel(void);
+static void disable_second_display_channel(void);
+static int get_fb_size_from_pci(void);
+
+void viafb_write_reg(u8 index, u16 io_port, u8 data)
+{
+ outb(index, io_port);
+ outb(data, io_port + 1);
+ /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */
+}
+u8 viafb_read_reg(int io_port, u8 index)
+{
+ outb(index, io_port);
+ return inb(io_port + 1);
+}
+
+void viafb_lock_crt(void)
+{
+ viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
+}
+
+void viafb_unlock_crt(void)
+{
+ viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
+ viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
+}
+
+void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
+{
+ u8 tmp;
+
+ outb(index, io_port);
+ tmp = inb(io_port + 1);
+ outb((data & mask) | (tmp & (~mask)), io_port + 1);
+ /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */
+}
+
+void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
+{
+ outb(index, LUT_INDEX_WRITE);
+ outb(r, LUT_DATA);
+ outb(g, LUT_DATA);
+ outb(b, LUT_DATA);
+}
+
+/*Set IGA path for each device*/
+void viafb_set_iga_path(void)
+{
+
+ if (viafb_SAMM_ON == 1) {
+ if (viafb_CRT_ON) {
+ if (viafb_primary_dev == CRT_Device)
+ viaparinfo->crt_setting_info->iga_path = IGA1;
+ else
+ viaparinfo->crt_setting_info->iga_path = IGA2;
+ }
+
+ if (viafb_DVI_ON) {
+ if (viafb_primary_dev == DVI_Device)
+ viaparinfo->tmds_setting_info->iga_path = IGA1;
+ else
+ viaparinfo->tmds_setting_info->iga_path = IGA2;
+ }
+
+ if (viafb_LCD_ON) {
+ if (viafb_primary_dev == LCD_Device) {
+ if (viafb_dual_fb &&
+ (viaparinfo->chip_info->gfx_chip_name ==
+ UNICHROME_CLE266)) {
+ viaparinfo->
+ lvds_setting_info->iga_path = IGA2;
+ viaparinfo->
+ crt_setting_info->iga_path = IGA1;
+ viaparinfo->
+ tmds_setting_info->iga_path = IGA1;
+ } else
+ viaparinfo->
+ lvds_setting_info->iga_path = IGA1;
+ } else {
+ viaparinfo->lvds_setting_info->iga_path = IGA2;
+ }
+ }
+ if (viafb_LCD2_ON) {
+ if (LCD2_Device == viafb_primary_dev)
+ viaparinfo->lvds_setting_info2->iga_path = IGA1;
+ else
+ viaparinfo->lvds_setting_info2->iga_path = IGA2;
+ }
+ } else {
+ viafb_SAMM_ON = 0;
+
+ if (viafb_CRT_ON && viafb_LCD_ON) {
+ viaparinfo->crt_setting_info->iga_path = IGA1;
+ viaparinfo->lvds_setting_info->iga_path = IGA2;
+ } else if (viafb_CRT_ON && viafb_DVI_ON) {
+ viaparinfo->crt_setting_info->iga_path = IGA1;
+ viaparinfo->tmds_setting_info->iga_path = IGA2;
+ } else if (viafb_LCD_ON && viafb_DVI_ON) {
+ viaparinfo->tmds_setting_info->iga_path = IGA1;
+ viaparinfo->lvds_setting_info->iga_path = IGA2;
+ } else if (viafb_LCD_ON && viafb_LCD2_ON) {
+ viaparinfo->lvds_setting_info->iga_path = IGA2;
+ viaparinfo->lvds_setting_info2->iga_path = IGA2;
+ } else if (viafb_CRT_ON) {
+ viaparinfo->crt_setting_info->iga_path = IGA1;
+ } else if (viafb_LCD_ON) {
+ viaparinfo->lvds_setting_info->iga_path = IGA2;
+ } else if (viafb_DVI_ON) {
+ viaparinfo->tmds_setting_info->iga_path = IGA1;
+ }
+ }
+}
+
+void viafb_set_start_addr(void)
+{
+ unsigned long offset = 0, tmp = 0, size = 0;
+ unsigned long length;
+
+ DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n");
+ viafb_unlock_crt();
+ /* update starting address of IGA1 */
+ viafb_write_reg(CR0C, VIACR, 0x00); /*initial starting address */
+ viafb_write_reg(CR0D, VIACR, 0x00);
+ viafb_write_reg(CR34, VIACR, 0x00);
+ viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F);
+
+ if (viafb_dual_fb) {
+ viaparinfo->iga_path = IGA1;
+ viaparinfo1->iga_path = IGA2;
+ }
+
+ if (viafb_SAMM_ON == 1) {
+ if (!viafb_dual_fb) {
+ if (viafb_second_size)
+ size = viafb_second_size * 1024 * 1024;
+ else
+ size = 8 * 1024 * 1024;
+ } else {
+
+ size = viaparinfo1->memsize;
+ }
+ offset = viafb_second_offset;
+ DEBUG_MSG(KERN_INFO
+ "viafb_second_size=%lx, second start_adddress=%lx\n",
+ size, offset);
+ }
+ if (viafb_SAMM_ON == 1) {
+ offset = offset >> 3;
+
+ tmp = viafb_read_reg(VIACR, 0x62) & 0x01;
+ tmp |= (offset & 0x7F) << 1;
+ viafb_write_reg(CR62, VIACR, tmp);
+ viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7));
+ viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15));
+ viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23));
+ } else {
+ /* update starting address */
+ viafb_write_reg(CR62, VIACR, 0x00);
+ viafb_write_reg(CR63, VIACR, 0x00);
+ viafb_write_reg(CR64, VIACR, 0x00);
+ viafb_write_reg(CRA3, VIACR, 0x00);
+ }
+
+ if (viafb_SAMM_ON == 1) {
+ if (viafb_accel) {
+ if (!viafb_dual_fb)
+ length = size - viaparinfo->fbmem_used;
+ else
+ length = size - viaparinfo1->fbmem_used;
+ } else
+ length = size;
+ offset = (unsigned long)(void *)viafb_FB_MM +
+ viafb_second_offset;
+ memset((void *)offset, 0, length);
+ }
+
+ viafb_lock_crt();
+}
+
+void viafb_set_output_path(int device, int set_iga, int output_interface)
+{
+ switch (device) {
+ case DEVICE_CRT:
+ set_crt_output_path(set_iga);
+ break;
+ case DEVICE_DVI:
+ set_dvi_output_path(set_iga, output_interface);
+ break;
+ case DEVICE_LCD:
+ set_lcd_output_path(set_iga, output_interface);
+ break;
+ }
+}
+
+static void set_crt_output_path(int set_iga)
+{
+ viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+
+ switch (set_iga) {
+ case IGA1:
+ viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
+ break;
+ case IGA2:
+ case IGA1_IGA2:
+ viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
+ viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
+ if (set_iga == IGA1_IGA2)
+ viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+ break;
+ }
+}
+
+static void dvi_patch_skew_dvp0(void)
+{
+ /* Reset data driving first: */
+ viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
+ viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
+
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_P4M890:
+ {
+ if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
+ (viaparinfo->tmds_setting_info->v_active ==
+ 1200))
+ viafb_write_reg_mask(CR96, VIACR, 0x03,
+ BIT0 + BIT1 + BIT2);
+ else
+ viafb_write_reg_mask(CR96, VIACR, 0x07,
+ BIT0 + BIT1 + BIT2);
+ break;
+ }
+
+ case UNICHROME_P4M900:
+ {
+ viafb_write_reg_mask(CR96, VIACR, 0x07,
+ BIT0 + BIT1 + BIT2 + BIT3);
+ viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
+ viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+static void dvi_patch_skew_dvp1(void)
+{
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CX700:
+ {
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+static void dvi_patch_skew_dvp_low(void)
+{
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ {
+ viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
+ break;
+ }
+
+ case UNICHROME_P4M900:
+ {
+ viafb_write_reg_mask(CR99, VIACR, 0x08,
+ BIT0 + BIT1 + BIT2 + BIT3);
+ break;
+ }
+
+ case UNICHROME_P4M890:
+ {
+ viafb_write_reg_mask(CR99, VIACR, 0x0F,
+ BIT0 + BIT1 + BIT2 + BIT3);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+static void set_dvi_output_path(int set_iga, int output_interface)
+{
+ switch (output_interface) {
+ case INTERFACE_DVP0:
+ viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+
+ if (set_iga == IGA1) {
+ viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 +
+ BIT5 + BIT7);
+ } else {
+ viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 +
+ BIT5 + BIT7);
+ }
+
+ viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
+
+ dvi_patch_skew_dvp0();
+ break;
+
+ case INTERFACE_DVP1:
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR93, VIACR, 0x21,
+ BIT0 + BIT5 + BIT7);
+ else
+ viafb_write_reg_mask(CR93, VIACR, 0xA1,
+ BIT0 + BIT5 + BIT7);
+ } else {
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ else
+ viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
+ dvi_patch_skew_dvp1();
+ break;
+ case INTERFACE_DFP_HIGH:
+ if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) {
+ if (set_iga == IGA1) {
+ viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ viafb_write_reg_mask(CR97, VIACR, 0x03,
+ BIT0 + BIT1 + BIT4);
+ } else {
+ viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR97, VIACR, 0x13,
+ BIT0 + BIT1 + BIT4);
+ }
+ }
+ viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
+ break;
+
+ case INTERFACE_DFP_LOW:
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+ break;
+
+ if (set_iga == IGA1) {
+ viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ } else {
+ viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+ dvi_patch_skew_dvp_low();
+ break;
+
+ case INTERFACE_TMDS:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ else
+ viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ break;
+ }
+
+ if (set_iga == IGA2) {
+ enable_second_display_channel();
+ /* Disable LCD Scaling */
+ viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
+ }
+}
+
+static void set_lcd_output_path(int set_iga, int output_interface)
+{
+ DEBUG_MSG(KERN_INFO
+ "set_lcd_output_path, iga:%d,out_interface:%d\n",
+ set_iga, output_interface);
+ switch (set_iga) {
+ case IGA1:
+ viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+ viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ disable_second_display_channel();
+ break;
+
+ case IGA2:
+ viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+ viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ enable_second_display_channel();
+ break;
+
+ case IGA1_IGA2:
+ viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+ viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+ disable_second_display_channel();
+ break;
+ }
+
+ switch (output_interface) {
+ case INTERFACE_DVP0:
+ if (set_iga == IGA1) {
+ viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+ } else {
+ viafb_write_reg(CR91, VIACR, 0x00);
+ viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DVP1:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+ else {
+ viafb_write_reg(CR91, VIACR, 0x00);
+ viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DFP_HIGH:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ else {
+ viafb_write_reg(CR91, VIACR, 0x00);
+ viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_DFP_LOW:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ else {
+ viafb_write_reg(CR91, VIACR, 0x00);
+ viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+ }
+
+ break;
+
+ case INTERFACE_DFP:
+ if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
+ || (UNICHROME_P4M890 ==
+ viaparinfo->chip_info->gfx_chip_name))
+ viafb_write_reg_mask(CR97, VIACR, 0x84,
+ BIT7 + BIT2 + BIT1 + BIT0);
+ if (set_iga == IGA1) {
+ viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ } else {
+ viafb_write_reg(CR91, VIACR, 0x00);
+ viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+ }
+ break;
+
+ case INTERFACE_LVDS0:
+ case INTERFACE_LVDS0LVDS1:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+ else
+ viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+
+ break;
+
+ case INTERFACE_LVDS1:
+ if (set_iga == IGA1)
+ viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+ else
+ viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+ break;
+ }
+}
+
+/* Search Mode Index */
+static int search_mode_setting(int ModeInfoIndex)
+{
+ int i = 0;
+
+ while ((i < NUM_TOTAL_MODETABLE) &&
+ (ModeInfoIndex != CLE266Modes[i].ModeIndex))
+ i++;
+ if (i >= NUM_TOTAL_MODETABLE)
+ i = 0;
+ return i;
+
+}
+
+struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
+{
+ struct VideoModeTable *TmpTbl = NULL;
+ TmpTbl = &CLE266Modes[search_mode_setting(Index)];
+ return TmpTbl;
+}
+
+struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
+{
+ struct VideoModeTable *TmpTbl = NULL;
+ int i = 0;
+ while ((i < NUM_TOTAL_CEA_MODES) &&
+ (Index != CEA_HDMI_Modes[i].ModeIndex))
+ i++;
+ if ((i < NUM_TOTAL_CEA_MODES))
+ TmpTbl = &CEA_HDMI_Modes[i];
+ else {
+ /*Still use general timing if don't find CEA timing */
+ i = 0;
+ while ((i < NUM_TOTAL_MODETABLE) &&
+ (Index != CLE266Modes[i].ModeIndex))
+ i++;
+ if (i >= NUM_TOTAL_MODETABLE)
+ i = 0;
+ TmpTbl = &CLE266Modes[i];
+ }
+ return TmpTbl;
+}
+
+static void load_fix_bit_crtc_reg(void)
+{
+ /* always set to 1 */
+ viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
+ /* line compare should set all bits = 1 (extend modes) */
+ viafb_write_reg(CR18, VIACR, 0xff);
+ /* line compare should set all bits = 1 (extend modes) */
+ viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
+ /* line compare should set all bits = 1 (extend modes) */
+ viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
+ /* line compare should set all bits = 1 (extend modes) */
+ viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
+ /* line compare should set all bits = 1 (extend modes) */
+ viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
+ /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
+ /* extend mode always set to e3h */
+ viafb_write_reg(CR17, VIACR, 0xe3);
+ /* extend mode always set to 0h */
+ viafb_write_reg(CR08, VIACR, 0x00);
+ /* extend mode always set to 0h */
+ viafb_write_reg(CR14, VIACR, 0x00);
+
+ /* If K8M800, enable Prefetch Mode. */
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+ || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
+ viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+ && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
+ viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
+
+}
+
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+ struct io_register *reg,
+ int io_type)
+{
+ int reg_mask;
+ int bit_num = 0;
+ int data;
+ int i, j;
+ int shift_next_reg;
+ int start_index, end_index, cr_index;
+ u16 get_bit;
+
+ for (i = 0; i < viafb_load_reg_num; i++) {
+ reg_mask = 0;
+ data = 0;
+ start_index = reg[i].start_bit;
+ end_index = reg[i].end_bit;
+ cr_index = reg[i].io_addr;
+
+ shift_next_reg = bit_num;
+ for (j = start_index; j <= end_index; j++) {
+ /*if (bit_num==8) timing_value = timing_value >>8; */
+ reg_mask = reg_mask | (BIT0 << j);
+ get_bit = (timing_value & (BIT0 << bit_num));
+ data =
+ data | ((get_bit >> shift_next_reg) << start_index);
+ bit_num++;
+ }
+ if (io_type == VIACR)
+ viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
+ else
+ viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
+ }
+
+}
+
+/* Write Registers */
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
+{
+ int i;
+ unsigned char RegTemp;
+
+ /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
+
+ for (i = 0; i < ItemNum; i++) {
+ outb(RegTable[i].index, RegTable[i].port);
+ RegTemp = inb(RegTable[i].port + 1);
+ RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value;
+ outb(RegTemp, RegTable[i].port + 1);
+ }
+}
+
+void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga)
+{
+ int reg_value;
+ int viafb_load_reg_num;
+ struct io_register *reg;
+
+ switch (set_iga) {
+ case IGA1_IGA2:
+ case IGA1:
+ reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte);
+ viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num;
+ reg = offset_reg.iga1_offset_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+ if (set_iga == IGA1)
+ break;
+ case IGA2:
+ reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte);
+ viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
+ reg = offset_reg.iga2_offset_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+ break;
+ }
+}
+
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
+{
+ int reg_value;
+ int viafb_load_reg_num;
+ struct io_register *reg = NULL;
+
+ switch (set_iga) {
+ case IGA1_IGA2:
+ case IGA1:
+ reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+ viafb_load_reg_num = fetch_count_reg.
+ iga1_fetch_count_reg.reg_num;
+ reg = fetch_count_reg.iga1_fetch_count_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+ if (set_iga == IGA1)
+ break;
+ case IGA2:
+ reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+ viafb_load_reg_num = fetch_count_reg.
+ iga2_fetch_count_reg.reg_num;
+ reg = fetch_count_reg.iga2_fetch_count_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+ break;
+ }
+
+}
+
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
+{
+ int reg_value;
+ int viafb_load_reg_num;
+ struct io_register *reg = NULL;
+ int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
+ 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
+ int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
+ 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
+
+ if (set_iga == IGA1) {
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+ iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ K800_IGA1_FIFO_HIGH_THRESHOLD;
+ /* If resolution > 1280x1024, expire length = 64, else
+ expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num =
+ K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+ iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ P880_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+ /* If resolution > 1280x1024, expire length = 64, else
+ expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num =
+ P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+ iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ CN700_IGA1_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64,
+ else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga1_display_queue_expire_num = 16;
+ else
+ iga1_display_queue_expire_num =
+ CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+ iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ CX700_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+ iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ K8M890_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+ iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ P4M890_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+ iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ P4M900_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+ iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
+ iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
+ iga1_fifo_high_threshold =
+ VX800_IGA1_FIFO_HIGH_THRESHOLD;
+ iga1_display_queue_expire_num =
+ VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ /* Set Display FIFO Depath Select */
+ reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
+ viafb_load_reg_num =
+ display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
+ reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+ /* Set Display FIFO Threshold Select */
+ reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
+ viafb_load_reg_num =
+ fifo_threshold_select_reg.
+ iga1_fifo_threshold_select_reg.reg_num;
+ reg =
+ fifo_threshold_select_reg.
+ iga1_fifo_threshold_select_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+ /* Set FIFO High Threshold Select */
+ reg_value =
+ IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
+ viafb_load_reg_num =
+ fifo_high_threshold_select_reg.
+ iga1_fifo_high_threshold_select_reg.reg_num;
+ reg =
+ fifo_high_threshold_select_reg.
+ iga1_fifo_high_threshold_select_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+ /* Set Display Queue Expire Num */
+ reg_value =
+ IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+ (iga1_display_queue_expire_num);
+ viafb_load_reg_num =
+ display_queue_expire_num_reg.
+ iga1_display_queue_expire_num_reg.reg_num;
+ reg =
+ display_queue_expire_num_reg.
+ iga1_display_queue_expire_num_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+ } else {
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+ iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ K800_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64,
+ else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num =
+ K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+ iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ P880_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64,
+ else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num =
+ P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+ iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ CN700_IGA2_FIFO_HIGH_THRESHOLD;
+
+ /* If resolution > 1280x1024, expire length = 64,
+ else expire length = 128 */
+ if ((hor_active > 1280) && (ver_active > 1024))
+ iga2_display_queue_expire_num = 16;
+ else
+ iga2_display_queue_expire_num =
+ CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+ iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ CX700_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num =
+ CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+ iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ K8M890_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num =
+ K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+ iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ P4M890_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num =
+ P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+ iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ P4M900_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num =
+ P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+ iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
+ iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
+ iga2_fifo_high_threshold =
+ VX800_IGA2_FIFO_HIGH_THRESHOLD;
+ iga2_display_queue_expire_num =
+ VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+ /* Set Display FIFO Depath Select */
+ reg_value =
+ IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
+ - 1;
+ /* Patch LCD in IGA2 case */
+ viafb_load_reg_num =
+ display_fifo_depth_reg.
+ iga2_fifo_depth_select_reg.reg_num;
+ reg =
+ display_fifo_depth_reg.
+ iga2_fifo_depth_select_reg.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ } else {
+
+ /* Set Display FIFO Depath Select */
+ reg_value =
+ IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
+ viafb_load_reg_num =
+ display_fifo_depth_reg.
+ iga2_fifo_depth_select_reg.reg_num;
+ reg =
+ display_fifo_depth_reg.
+ iga2_fifo_depth_select_reg.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ }
+
+ /* Set Display FIFO Threshold Select */
+ reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
+ viafb_load_reg_num =
+ fifo_threshold_select_reg.
+ iga2_fifo_threshold_select_reg.reg_num;
+ reg =
+ fifo_threshold_select_reg.
+ iga2_fifo_threshold_select_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+ /* Set FIFO High Threshold Select */
+ reg_value =
+ IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
+ viafb_load_reg_num =
+ fifo_high_threshold_select_reg.
+ iga2_fifo_high_threshold_select_reg.reg_num;
+ reg =
+ fifo_high_threshold_select_reg.
+ iga2_fifo_high_threshold_select_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+ /* Set Display Queue Expire Num */
+ reg_value =
+ IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+ (iga2_display_queue_expire_num);
+ viafb_load_reg_num =
+ display_queue_expire_num_reg.
+ iga2_display_queue_expire_num_reg.reg_num;
+ reg =
+ display_queue_expire_num_reg.
+ iga2_display_queue_expire_num_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+ }
+
+}
+
+u32 viafb_get_clk_value(int clk)
+{
+ int i;
+
+ for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
+ if (clk == pll_value[i].clk) {
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ return pll_value[i].cle266_pll;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ return pll_value[i].k800_pll;
+
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_VX800:
+ return pll_value[i].cx700_pll;
+ }
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
+ return 0;
+}
+
+/* Set VCLK*/
+void viafb_set_vclock(u32 CLK, int set_iga)
+{
+ unsigned char RegTemp;
+
+ /* H.W. Reset : ON */
+ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+ if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+ /* Change D,N FOR VCLK */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ viafb_write_reg(SR46, VIASR, CLK / 0x100);
+ viafb_write_reg(SR47, VIASR, CLK % 0x100);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_VX800:
+ viafb_write_reg(SR44, VIASR, CLK / 0x10000);
+ DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
+ viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
+ DEBUG_MSG(KERN_INFO "\nSR45=%x",
+ (CLK & 0xFFFF) / 0x100);
+ viafb_write_reg(SR46, VIASR, CLK % 0x100);
+ DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100);
+ break;
+ }
+ }
+
+ if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+ /* Change D,N FOR LCK */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ viafb_write_reg(SR44, VIASR, CLK / 0x100);
+ viafb_write_reg(SR45, VIASR, CLK % 0x100);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_VX800:
+ viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
+ viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
+ viafb_write_reg(SR4C, VIASR, CLK % 0x100);
+ break;
+ }
+ }
+
+ /* H.W. Reset : OFF */
+ viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+ /* Reset PLL */
+ if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+ viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+ viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+ }
+
+ if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+ viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
+ viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
+ }
+
+ /* Fire! */
+ RegTemp = inb(VIARMisc);
+ outb(RegTemp | (BIT2 + BIT3), VIAWMisc);
+}
+
+void viafb_load_crtc_timing(struct display_timing device_timing,
+ int set_iga)
+{
+ int i;
+ int viafb_load_reg_num = 0;
+ int reg_value = 0;
+ struct io_register *reg = NULL;
+
+ viafb_unlock_crt();
+
+ for (i = 0; i < 12; i++) {
+ if (set_iga == IGA1) {
+ switch (i) {
+ case H_TOTAL_INDEX:
+ reg_value =
+ IGA1_HOR_TOTAL_FORMULA(device_timing.
+ hor_total);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_total.reg_num;
+ reg = iga1_crtc_reg.hor_total.reg;
+ break;
+ case H_ADDR_INDEX:
+ reg_value =
+ IGA1_HOR_ADDR_FORMULA(device_timing.
+ hor_addr);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_addr.reg_num;
+ reg = iga1_crtc_reg.hor_addr.reg;
+ break;
+ case H_BLANK_START_INDEX:
+ reg_value =
+ IGA1_HOR_BLANK_START_FORMULA
+ (device_timing.hor_blank_start);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_blank_start.reg_num;
+ reg = iga1_crtc_reg.hor_blank_start.reg;
+ break;
+ case H_BLANK_END_INDEX:
+ reg_value =
+ IGA1_HOR_BLANK_END_FORMULA
+ (device_timing.hor_blank_start,
+ device_timing.hor_blank_end);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_blank_end.reg_num;
+ reg = iga1_crtc_reg.hor_blank_end.reg;
+ break;
+ case H_SYNC_START_INDEX:
+ reg_value =
+ IGA1_HOR_SYNC_START_FORMULA
+ (device_timing.hor_sync_start);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_sync_start.reg_num;
+ reg = iga1_crtc_reg.hor_sync_start.reg;
+ break;
+ case H_SYNC_END_INDEX:
+ reg_value =
+ IGA1_HOR_SYNC_END_FORMULA
+ (device_timing.hor_sync_start,
+ device_timing.hor_sync_end);
+ viafb_load_reg_num =
+ iga1_crtc_reg.hor_sync_end.reg_num;
+ reg = iga1_crtc_reg.hor_sync_end.reg;
+ break;
+ case V_TOTAL_INDEX:
+ reg_value =
+ IGA1_VER_TOTAL_FORMULA(device_timing.
+ ver_total);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_total.reg_num;
+ reg = iga1_crtc_reg.ver_total.reg;
+ break;
+ case V_ADDR_INDEX:
+ reg_value =
+ IGA1_VER_ADDR_FORMULA(device_timing.
+ ver_addr);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_addr.reg_num;
+ reg = iga1_crtc_reg.ver_addr.reg;
+ break;
+ case V_BLANK_START_INDEX:
+ reg_value =
+ IGA1_VER_BLANK_START_FORMULA
+ (device_timing.ver_blank_start);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_blank_start.reg_num;
+ reg = iga1_crtc_reg.ver_blank_start.reg;
+ break;
+ case V_BLANK_END_INDEX:
+ reg_value =
+ IGA1_VER_BLANK_END_FORMULA
+ (device_timing.ver_blank_start,
+ device_timing.ver_blank_end);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_blank_end.reg_num;
+ reg = iga1_crtc_reg.ver_blank_end.reg;
+ break;
+ case V_SYNC_START_INDEX:
+ reg_value =
+ IGA1_VER_SYNC_START_FORMULA
+ (device_timing.ver_sync_start);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_sync_start.reg_num;
+ reg = iga1_crtc_reg.ver_sync_start.reg;
+ break;
+ case V_SYNC_END_INDEX:
+ reg_value =
+ IGA1_VER_SYNC_END_FORMULA
+ (device_timing.ver_sync_start,
+ device_timing.ver_sync_end);
+ viafb_load_reg_num =
+ iga1_crtc_reg.ver_sync_end.reg_num;
+ reg = iga1_crtc_reg.ver_sync_end.reg;
+ break;
+
+ }
+ }
+
+ if (set_iga == IGA2) {
+ switch (i) {
+ case H_TOTAL_INDEX:
+ reg_value =
+ IGA2_HOR_TOTAL_FORMULA(device_timing.
+ hor_total);
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_total.reg_num;
+ reg = iga2_crtc_reg.hor_total.reg;
+ break;
+ case H_ADDR_INDEX:
+ reg_value =
+ IGA2_HOR_ADDR_FORMULA(device_timing.
+ hor_addr);
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_addr.reg_num;
+ reg = iga2_crtc_reg.hor_addr.reg;
+ break;
+ case H_BLANK_START_INDEX:
+ reg_value =
+ IGA2_HOR_BLANK_START_FORMULA
+ (device_timing.hor_blank_start);
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_blank_start.reg_num;
+ reg = iga2_crtc_reg.hor_blank_start.reg;
+ break;
+ case H_BLANK_END_INDEX:
+ reg_value =
+ IGA2_HOR_BLANK_END_FORMULA
+ (device_timing.hor_blank_start,
+ device_timing.hor_blank_end);
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_blank_end.reg_num;
+ reg = iga2_crtc_reg.hor_blank_end.reg;
+ break;
+ case H_SYNC_START_INDEX:
+ reg_value =
+ IGA2_HOR_SYNC_START_FORMULA
+ (device_timing.hor_sync_start);
+ if (UNICHROME_CN700 <=
+ viaparinfo->chip_info->gfx_chip_name)
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_sync_start.
+ reg_num;
+ else
+ viafb_load_reg_num = 3;
+ reg = iga2_crtc_reg.hor_sync_start.reg;
+ break;
+ case H_SYNC_END_INDEX:
+ reg_value =
+ IGA2_HOR_SYNC_END_FORMULA
+ (device_timing.hor_sync_start,
+ device_timing.hor_sync_end);
+ viafb_load_reg_num =
+ iga2_crtc_reg.hor_sync_end.reg_num;
+ reg = iga2_crtc_reg.hor_sync_end.reg;
+ break;
+ case V_TOTAL_INDEX:
+ reg_value =
+ IGA2_VER_TOTAL_FORMULA(device_timing.
+ ver_total);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_total.reg_num;
+ reg = iga2_crtc_reg.ver_total.reg;
+ break;
+ case V_ADDR_INDEX:
+ reg_value =
+ IGA2_VER_ADDR_FORMULA(device_timing.
+ ver_addr);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_addr.reg_num;
+ reg = iga2_crtc_reg.ver_addr.reg;
+ break;
+ case V_BLANK_START_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_START_FORMULA
+ (device_timing.ver_blank_start);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_blank_start.reg_num;
+ reg = iga2_crtc_reg.ver_blank_start.reg;
+ break;
+ case V_BLANK_END_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_END_FORMULA
+ (device_timing.ver_blank_start,
+ device_timing.ver_blank_end);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_blank_end.reg_num;
+ reg = iga2_crtc_reg.ver_blank_end.reg;
+ break;
+ case V_SYNC_START_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_START_FORMULA
+ (device_timing.ver_sync_start);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_sync_start.reg_num;
+ reg = iga2_crtc_reg.ver_sync_start.reg;
+ break;
+ case V_SYNC_END_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_END_FORMULA
+ (device_timing.ver_sync_start,
+ device_timing.ver_sync_end);
+ viafb_load_reg_num =
+ iga2_crtc_reg.ver_sync_end.reg_num;
+ reg = iga2_crtc_reg.ver_sync_end.reg;
+ break;
+
+ }
+ }
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+ }
+
+ viafb_lock_crt();
+}
+
+void viafb_set_color_depth(int bpp_byte, int set_iga)
+{
+ if (set_iga == IGA1) {
+ switch (bpp_byte) {
+ case MODE_8BPP:
+ viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
+ break;
+ case MODE_16BPP:
+ viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
+ break;
+ case MODE_32BPP:
+ viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
+ break;
+ }
+ } else {
+ switch (bpp_byte) {
+ case MODE_8BPP:
+ viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
+ break;
+ case MODE_16BPP:
+ viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
+ break;
+ case MODE_32BPP:
+ viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
+ break;
+ }
+ }
+}
+
+void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
+ int mode_index, int bpp_byte, int set_iga)
+{
+ struct VideoModeTable *video_mode;
+ struct display_timing crt_reg;
+ int i;
+ int index = 0;
+ int h_addr, v_addr;
+ u32 pll_D_N;
+
+ video_mode = &CLE266Modes[search_mode_setting(mode_index)];
+
+ for (i = 0; i < video_mode->mode_array; i++) {
+ index = i;
+
+ if (crt_table[i].refresh_rate == viaparinfo->
+ crt_setting_info->refresh_rate)
+ break;
+ }
+
+ crt_reg = crt_table[index].crtc;
+
+ /* Mode 640x480 has border, but LCD/DFP didn't have border. */
+ /* So we would delete border. */
+ if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480)
+ && (viaparinfo->crt_setting_info->refresh_rate == 60)) {
+ /* The border is 8 pixels. */
+ crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
+
+ /* Blanking time should add left and right borders. */
+ crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
+ }
+
+ h_addr = crt_reg.hor_addr;
+ v_addr = crt_reg.ver_addr;
+
+ /* update polarity for CRT timing */
+ if (crt_table[index].h_sync_polarity == NEGATIVE) {
+ if (crt_table[index].v_sync_polarity == NEGATIVE)
+ outb((inb(VIARMisc) & (~(BIT6 + BIT7))) |
+ (BIT6 + BIT7), VIAWMisc);
+ else
+ outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6),
+ VIAWMisc);
+ } else {
+ if (crt_table[index].v_sync_polarity == NEGATIVE)
+ outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7),
+ VIAWMisc);
+ else
+ outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc);
+ }
+
+ if (set_iga == IGA1) {
+ viafb_unlock_crt();
+ viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */
+ viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
+ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+ }
+
+ switch (set_iga) {
+ case IGA1:
+ viafb_load_crtc_timing(crt_reg, IGA1);
+ break;
+ case IGA2:
+ viafb_load_crtc_timing(crt_reg, IGA2);
+ break;
+ }
+
+ load_fix_bit_crtc_reg();
+ viafb_lock_crt();
+ viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+ viafb_load_offset_reg(h_addr, bpp_byte, set_iga);
+ viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
+
+ /* load FIFO */
+ if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+ && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+ viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
+
+ /* load SR Register About Memory and Color part */
+ viafb_set_color_depth(bpp_byte, set_iga);
+
+ pll_D_N = viafb_get_clk_value(crt_table[index].clk);
+ DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
+ viafb_set_vclock(pll_D_N, set_iga);
+
+}
+
+void viafb_init_chip_info(void)
+{
+ init_gfx_chip_info();
+ init_tmds_chip_info();
+ init_lvds_chip_info();
+
+ viaparinfo->crt_setting_info->iga_path = IGA1;
+ viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
+
+ /*Set IGA path for each device */
+ viafb_set_iga_path();
+
+ viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
+ viaparinfo->lvds_setting_info->get_lcd_size_method =
+ GET_LCD_SIZE_BY_USER_SETTING;
+ viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
+ viaparinfo->lvds_setting_info2->display_method =
+ viaparinfo->lvds_setting_info->display_method;
+ viaparinfo->lvds_setting_info2->lcd_mode =
+ viaparinfo->lvds_setting_info->lcd_mode;
+}
+
+void viafb_update_device_setting(int hres, int vres,
+ int bpp, int vmode_refresh, int flag)
+{
+ if (flag == 0) {
+ viaparinfo->crt_setting_info->h_active = hres;
+ viaparinfo->crt_setting_info->v_active = vres;
+ viaparinfo->crt_setting_info->bpp = bpp;
+ viaparinfo->crt_setting_info->refresh_rate =
+ vmode_refresh;
+
+ viaparinfo->tmds_setting_info->h_active = hres;
+ viaparinfo->tmds_setting_info->v_active = vres;
+ viaparinfo->tmds_setting_info->bpp = bpp;
+ viaparinfo->tmds_setting_info->refresh_rate =
+ vmode_refresh;
+
+ viaparinfo->lvds_setting_info->h_active = hres;
+ viaparinfo->lvds_setting_info->v_active = vres;
+ viaparinfo->lvds_setting_info->bpp = bpp;
+ viaparinfo->lvds_setting_info->refresh_rate =
+ vmode_refresh;
+ viaparinfo->lvds_setting_info2->h_active = hres;
+ viaparinfo->lvds_setting_info2->v_active = vres;
+ viaparinfo->lvds_setting_info2->bpp = bpp;
+ viaparinfo->lvds_setting_info2->refresh_rate =
+ vmode_refresh;
+ } else {
+
+ if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
+ viaparinfo->tmds_setting_info->h_active = hres;
+ viaparinfo->tmds_setting_info->v_active = vres;
+ viaparinfo->tmds_setting_info->bpp = bpp;
+ viaparinfo->tmds_setting_info->refresh_rate =
+ vmode_refresh;
+ }
+
+ if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
+ viaparinfo->lvds_setting_info->h_active = hres;
+ viaparinfo->lvds_setting_info->v_active = vres;
+ viaparinfo->lvds_setting_info->bpp = bpp;
+ viaparinfo->lvds_setting_info->refresh_rate =
+ vmode_refresh;
+ }
+ if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
+ viaparinfo->lvds_setting_info2->h_active = hres;
+ viaparinfo->lvds_setting_info2->v_active = vres;
+ viaparinfo->lvds_setting_info2->bpp = bpp;
+ viaparinfo->lvds_setting_info2->refresh_rate =
+ vmode_refresh;
+ }
+ }
+}
+
+static void init_gfx_chip_info(void)
+{
+ struct pci_dev *pdev = NULL;
+ u32 i;
+ u8 tmp;
+
+ /* Indentify GFX Chip Name */
+ for (i = 0; pciidlist[i].vendor != 0; i++) {
+ pdev = pci_get_device(pciidlist[i].vendor,
+ pciidlist[i].device, 0);
+ if (pdev)
+ break;
+ }
+
+ if (!pciidlist[i].vendor)
+ return ;
+
+ viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index;
+
+ /* Check revision of CLE266 Chip */
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ /* CR4F only define in CLE266.CX chip */
+ tmp = viafb_read_reg(VIACR, CR4F);
+ viafb_write_reg(CR4F, VIACR, 0x55);
+ if (viafb_read_reg(VIACR, CR4F) != 0x55)
+ viaparinfo->chip_info->gfx_chip_revision =
+ CLE266_REVISION_AX;
+ else
+ viaparinfo->chip_info->gfx_chip_revision =
+ CLE266_REVISION_CX;
+ /* restore orignal CR4F value */
+ viafb_write_reg(CR4F, VIACR, tmp);
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+ tmp = viafb_read_reg(VIASR, SR43);
+ DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
+ if (tmp & 0x02) {
+ viaparinfo->chip_info->gfx_chip_revision =
+ CX700_REVISION_700M2;
+ } else if (tmp & 0x40) {
+ viaparinfo->chip_info->gfx_chip_revision =
+ CX700_REVISION_700M;
+ } else {
+ viaparinfo->chip_info->gfx_chip_revision =
+ CX700_REVISION_700;
+ }
+ }
+
+ pci_dev_put(pdev);
+}
+
+static void init_tmds_chip_info(void)
+{
+ viafb_tmds_trasmitter_identify();
+
+ if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
+ output_interface) {
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CX700:
+ {
+ /* we should check support by hardware layout.*/
+ if ((viafb_display_hardware_layout ==
+ HW_LAYOUT_DVI_ONLY)
+ || (viafb_display_hardware_layout ==
+ HW_LAYOUT_LCD_DVI)) {
+ viaparinfo->chip_info->tmds_chip_info.
+ output_interface = INTERFACE_TMDS;
+ } else {
+ viaparinfo->chip_info->tmds_chip_info.
+ output_interface =
+ INTERFACE_NONE;
+ }
+ break;
+ }
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_P4M890:
+ /* TMDS on PCIE, we set DFPLOW as default. */
+ viaparinfo->chip_info->tmds_chip_info.output_interface =
+ INTERFACE_DFP_LOW;
+ break;
+ default:
+ {
+ /* set DVP1 default for DVI */
+ viaparinfo->chip_info->tmds_chip_info
+ .output_interface = INTERFACE_DVP1;
+ }
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
+ viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+ viaparinfo->tmds_setting_info->get_dvi_size_method =
+ GET_DVI_SIZE_BY_VGA_BIOS;
+ viafb_init_dvi_size();
+}
+
+static void init_lvds_chip_info(void)
+{
+ if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
+ viaparinfo->lvds_setting_info->get_lcd_size_method =
+ GET_LCD_SIZE_BY_VGA_BIOS;
+ else
+ viaparinfo->lvds_setting_info->get_lcd_size_method =
+ GET_LCD_SIZE_BY_USER_SETTING;
+
+ viafb_lvds_trasmitter_identify();
+ viafb_init_lcd_size();
+ viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
+ viaparinfo->lvds_setting_info);
+ if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+ viafb_init_lvds_output_interface(&viaparinfo->chip_info->
+ lvds_chip_info2, viaparinfo->lvds_setting_info2);
+ }
+ /*If CX700,two singel LCD, we need to reassign
+ LCD interface to different LVDS port */
+ if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
+ && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
+ if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_name) && (INTEGRATED_LVDS ==
+ viaparinfo->chip_info->
+ lvds_chip_info2.lvds_chip_name)) {
+ viaparinfo->chip_info->lvds_chip_info.output_interface =
+ INTERFACE_LVDS0;
+ viaparinfo->chip_info->lvds_chip_info2.
+ output_interface =
+ INTERFACE_LVDS1;
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+ DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
+ viaparinfo->chip_info->lvds_chip_info.output_interface);
+ DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
+ viaparinfo->chip_info->lvds_chip_info.output_interface);
+}
+
+void viafb_init_dac(int set_iga)
+{
+ int i;
+ u8 tmp;
+
+ if (set_iga == IGA1) {
+ /* access Primary Display's LUT */
+ viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+ /* turn off LCK */
+ viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
+ for (i = 0; i < 256; i++) {
+ write_dac_reg(i, palLUT_table[i].red,
+ palLUT_table[i].green,
+ palLUT_table[i].blue);
+ }
+ /* turn on LCK */
+ viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
+ } else {
+ tmp = viafb_read_reg(VIACR, CR6A);
+ /* access Secondary Display's LUT */
+ viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
+ viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+ for (i = 0; i < 256; i++) {
+ write_dac_reg(i, palLUT_table[i].red,
+ palLUT_table[i].green,
+ palLUT_table[i].blue);
+ }
+ /* set IGA1 DAC for default */
+ viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+ viafb_write_reg(CR6A, VIACR, tmp);
+ }
+}
+
+static void device_screen_off(void)
+{
+ /* turn off CRT screen (IGA1) */
+ viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
+}
+
+static void device_screen_on(void)
+{
+ /* turn on CRT screen (IGA1) */
+ viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
+}
+
+static void set_display_channel(void)
+{
+ /*If viafb_LCD2_ON, on cx700, internal lvds's information
+ is keeped on lvds_setting_info2 */
+ if (viafb_LCD2_ON &&
+ viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
+ /* For dual channel LCD: */
+ /* Set to Dual LVDS channel. */
+ viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+ } else if (viafb_LCD_ON && viafb_DVI_ON) {
+ /* For LCD+DFP: */
+ /* Set to LVDS1 + TMDS channel. */
+ viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
+ } else if (viafb_DVI_ON) {
+ /* Set to single TMDS channel. */
+ viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
+ } else if (viafb_LCD_ON) {
+ if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
+ /* For dual channel LCD: */
+ /* Set to Dual LVDS channel. */
+ viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+ } else {
+ /* Set to LVDS0 + LVDS1 channel. */
+ viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
+ }
+ }
+}
+
+int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
+ int vmode_index1, int hor_res1, int ver_res1, int video_bpp1)
+{
+ int i, j;
+ int port;
+ u8 value, index, mask;
+ struct VideoModeTable *vmode_tbl;
+ struct crt_mode_table *crt_timing;
+ struct VideoModeTable *vmode_tbl1 = NULL;
+ struct crt_mode_table *crt_timing1 = NULL;
+
+ DEBUG_MSG(KERN_INFO "Set Mode!!\n");
+ DEBUG_MSG(KERN_INFO
+ "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
+ vmode_index, hor_res, ver_res, video_bpp);
+
+ device_screen_off();
+ vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
+ crt_timing = vmode_tbl->crtc;
+
+ if (viafb_SAMM_ON == 1) {
+ vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
+ crt_timing1 = vmode_tbl1->crtc;
+ }
+
+ inb(VIAStatus);
+ outb(0x00, VIAAR);
+
+ /* Write Common Setting for Video Mode */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
+ break;
+
+ case UNICHROME_K400:
+ viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
+ break;
+
+ case UNICHROME_CN700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
+ break;
+
+ case UNICHROME_CX700:
+ viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
+
+ case UNICHROME_VX800:
+ viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs);
+
+ break;
+ }
+
+ device_off();
+
+ /* Fill VPIT Parameters */
+ /* Write Misc Register */
+ outb(VPIT.Misc, VIAWMisc);
+
+ /* Write Sequencer */
+ for (i = 1; i <= StdSR; i++) {
+ outb(i, VIASR);
+ outb(VPIT.SR[i - 1], VIASR + 1);
+ }
+
+ viafb_set_start_addr();
+ viafb_set_iga_path();
+
+ /* Write CRTC */
+ viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1);
+
+ /* Write Graphic Controller */
+ for (i = 0; i < StdGR; i++) {
+ outb(i, VIAGR);
+ outb(VPIT.GR[i], VIAGR + 1);
+ }
+
+ /* Write Attribute Controller */
+ for (i = 0; i < StdAR; i++) {
+ inb(VIAStatus);
+ outb(i, VIAAR);
+ outb(VPIT.AR[i], VIAAR);
+ }
+
+ inb(VIAStatus);
+ outb(0x20, VIAAR);
+
+ /* Update Patch Register */
+
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+ || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) {
+ for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
+ if (res_patch_table[i].mode_index == vmode_index) {
+ for (j = 0;
+ j < res_patch_table[i].table_length; j++) {
+ index =
+ res_patch_table[i].
+ io_reg_table[j].index;
+ port =
+ res_patch_table[i].
+ io_reg_table[j].port;
+ value =
+ res_patch_table[i].
+ io_reg_table[j].value;
+ mask =
+ res_patch_table[i].
+ io_reg_table[j].mask;
+ viafb_write_reg_mask(index, port, value,
+ mask);
+ }
+ }
+ }
+ }
+
+ if (viafb_SAMM_ON == 1) {
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+ || (viaparinfo->chip_info->gfx_chip_name ==
+ UNICHROME_K400)) {
+ for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
+ if (res_patch_table[i].mode_index ==
+ vmode_index1) {
+ for (j = 0;
+ j <
+ res_patch_table[i].
+ table_length; j++) {
+ index =
+ res_patch_table[i].
+ io_reg_table[j].index;
+ port =
+ res_patch_table[i].
+ io_reg_table[j].port;
+ value =
+ res_patch_table[i].
+ io_reg_table[j].value;
+ mask =
+ res_patch_table[i].
+ io_reg_table[j].mask;
+ viafb_write_reg_mask(index,
+ port, value, mask);
+ }
+ }
+ }
+ }
+ }
+
+ /* Update Refresh Rate Setting */
+
+ /* Clear On Screen */
+
+ /* CRT set mode */
+ if (viafb_CRT_ON) {
+ if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
+ IGA2)) {
+ viafb_fill_crtc_timing(crt_timing1, vmode_index1,
+ video_bpp1 / 8,
+ viaparinfo->crt_setting_info->iga_path);
+ } else {
+ viafb_fill_crtc_timing(crt_timing, vmode_index,
+ video_bpp / 8,
+ viaparinfo->crt_setting_info->iga_path);
+ }
+
+ set_crt_output_path(viaparinfo->crt_setting_info->iga_path);
+
+ /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
+ to 8 alignment (1368),there is several pixels (2 pixels)
+ on right side of screen. */
+ if (hor_res % 8) {
+ viafb_unlock_crt();
+ viafb_write_reg(CR02, VIACR,
+ viafb_read_reg(VIACR, CR02) - 1);
+ viafb_lock_crt();
+ }
+ }
+
+ if (viafb_DVI_ON) {
+ if (viafb_SAMM_ON &&
+ (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
+ viafb_dvi_set_mode(viafb_get_mode_index
+ (viaparinfo->tmds_setting_info->h_active,
+ viaparinfo->tmds_setting_info->
+ v_active, 1),
+ video_bpp1, viaparinfo->
+ tmds_setting_info->iga_path);
+ } else {
+ viafb_dvi_set_mode(viafb_get_mode_index
+ (viaparinfo->tmds_setting_info->h_active,
+ viaparinfo->
+ tmds_setting_info->v_active, 0),
+ video_bpp, viaparinfo->
+ tmds_setting_info->iga_path);
+ }
+ }
+
+ if (viafb_LCD_ON) {
+ if (viafb_SAMM_ON &&
+ (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
+ viaparinfo->lvds_setting_info->bpp = video_bpp1;
+ viafb_lcd_set_mode(crt_timing1, viaparinfo->
+ lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ } else {
+ /* IGA1 doesn't have LCD scaling, so set it center. */
+ if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+ viaparinfo->lvds_setting_info->display_method =
+ LCD_CENTERING;
+ }
+ viaparinfo->lvds_setting_info->bpp = video_bpp;
+ viafb_lcd_set_mode(crt_timing, viaparinfo->
+ lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ }
+ }
+ if (viafb_LCD2_ON) {
+ if (viafb_SAMM_ON &&
+ (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
+ viaparinfo->lvds_setting_info2->bpp = video_bpp1;
+ viafb_lcd_set_mode(crt_timing1, viaparinfo->
+ lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
+ } else {
+ /* IGA1 doesn't have LCD scaling, so set it center. */
+ if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+ viaparinfo->lvds_setting_info2->display_method =
+ LCD_CENTERING;
+ }
+ viaparinfo->lvds_setting_info2->bpp = video_bpp;
+ viafb_lcd_set_mode(crt_timing, viaparinfo->
+ lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
+ }
+ }
+
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+ && (viafb_LCD_ON || viafb_DVI_ON))
+ set_display_channel();
+
+ /* If set mode normally, save resolution information for hot-plug . */
+ if (!viafb_hotplug) {
+ viafb_hotplug_Xres = hor_res;
+ viafb_hotplug_Yres = ver_res;
+ viafb_hotplug_bpp = video_bpp;
+ viafb_hotplug_refresh = viafb_refresh;
+
+ if (viafb_DVI_ON)
+ viafb_DeviceStatus = DVI_Device;
+ else
+ viafb_DeviceStatus = CRT_Device;
+ }
+ device_on();
+
+ if (viafb_SAMM_ON == 1)
+ viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
+
+ device_screen_on();
+ return 1;
+}
+
+int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
+{
+ int i;
+
+ for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
+ if ((hres == res_map_refresh_tbl[i].hres)
+ && (vres == res_map_refresh_tbl[i].vres)
+ && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
+ return res_map_refresh_tbl[i].pixclock;
+ }
+ return RES_640X480_60HZ_PIXCLOCK;
+
+}
+
+int viafb_get_refresh(int hres, int vres, u32 long_refresh)
+{
+#define REFRESH_TOLERANCE 3
+ int i, nearest = -1, diff = REFRESH_TOLERANCE;
+ for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
+ if ((hres == res_map_refresh_tbl[i].hres)
+ && (vres == res_map_refresh_tbl[i].vres)
+ && (diff > (abs(long_refresh -
+ res_map_refresh_tbl[i].vmode_refresh)))) {
+ diff = abs(long_refresh - res_map_refresh_tbl[i].
+ vmode_refresh);
+ nearest = i;
+ }
+ }
+#undef REFRESH_TOLERANCE
+ if (nearest > 0)
+ return res_map_refresh_tbl[nearest].vmode_refresh;
+ return 60;
+}
+
+static void device_off(void)
+{
+ viafb_crt_disable();
+ viafb_dvi_disable();
+ viafb_lcd_disable();
+}
+
+static void device_on(void)
+{
+ if (viafb_CRT_ON == 1)
+ viafb_crt_enable();
+ if (viafb_DVI_ON == 1)
+ viafb_dvi_enable();
+ if (viafb_LCD_ON == 1)
+ viafb_lcd_enable();
+}
+
+void viafb_crt_disable(void)
+{
+ viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
+}
+
+void viafb_crt_enable(void)
+{
+ viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
+}
+
+void viafb_get_mmio_info(unsigned long *mmio_base,
+ unsigned long *mmio_len)
+{
+ struct pci_dev *pdev = NULL;
+ u32 vendor, device;
+ u32 i;
+
+ for (i = 0; pciidlist[i].vendor != 0; i++)
+ if (viaparinfo->chip_info->gfx_chip_name ==
+ pciidlist[i].chip_index)
+ break;
+
+ if (!pciidlist[i].vendor)
+ return ;
+
+ vendor = pciidlist[i].vendor;
+ device = pciidlist[i].device;
+
+ pdev = pci_get_device(vendor, device, NULL);
+
+ if (!pdev) {
+ *mmio_base = 0;
+ *mmio_len = 0;
+ return ;
+ }
+
+ *mmio_base = pci_resource_start(pdev, 1);
+ *mmio_len = pci_resource_len(pdev, 1);
+
+ pci_dev_put(pdev);
+}
+
+static void enable_second_display_channel(void)
+{
+ /* to enable second display channel. */
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+ viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
+ viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+static void disable_second_display_channel(void)
+{
+ /* to disable second display channel. */
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
+ viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len)
+{
+ struct pci_dev *pdev = NULL;
+ u32 vendor, device;
+ u32 i;
+
+ for (i = 0; pciidlist[i].vendor != 0; i++)
+ if (viaparinfo->chip_info->gfx_chip_name ==
+ pciidlist[i].chip_index)
+ break;
+
+ if (!pciidlist[i].vendor)
+ return ;
+
+ vendor = pciidlist[i].vendor;
+ device = pciidlist[i].device;
+
+ pdev = pci_get_device(vendor, device, NULL);
+
+ if (!pdev) {
+ *fb_base = viafb_read_reg(VIASR, SR30) << 24;
+ *fb_len = viafb_get_memsize();
+ DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n");
+ DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+ DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+ return ;
+ }
+
+ *fb_base = (unsigned int)pci_resource_start(pdev, 0);
+ *fb_len = get_fb_size_from_pci();
+ DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n");
+ DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+ DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+
+ pci_dev_put(pdev);
+}
+
+static int get_fb_size_from_pci(void)
+{
+ unsigned long configid, deviceid, FBSize = 0;
+ int VideoMemSize;
+ int DeviceFound = false;
+
+ for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
+ outl(configid, (unsigned long)0xCF8);
+ deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
+
+ switch (deviceid) {
+ case CLE266:
+ case KM400:
+ outl(configid + 0xE0, (unsigned long)0xCF8);
+ FBSize = inl((unsigned long)0xCFC);
+ DeviceFound = true; /* Found device id */
+ break;
+
+ case CN400_FUNCTION3:
+ case CN700_FUNCTION3:
+ case CX700_FUNCTION3:
+ case KM800_FUNCTION3:
+ case KM890_FUNCTION3:
+ case P4M890_FUNCTION3:
+ case P4M900_FUNCTION3:
+ case VX800_FUNCTION3:
+ /*case CN750_FUNCTION3: */
+ outl(configid + 0xA0, (unsigned long)0xCF8);
+ FBSize = inl((unsigned long)0xCFC);
+ DeviceFound = true; /* Found device id */
+ break;
+
+ default:
+ break;
+ }
+
+ if (DeviceFound)
+ break;
+ }
+
+ DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
+
+ FBSize = FBSize & 0x00007000;
+ DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
+
+ if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) {
+ switch (FBSize) {
+ case 0x00004000:
+ VideoMemSize = (16 << 20); /*16M */
+ break;
+
+ case 0x00005000:
+ VideoMemSize = (32 << 20); /*32M */
+ break;
+
+ case 0x00006000:
+ VideoMemSize = (64 << 20); /*64M */
+ break;
+
+ default:
+ VideoMemSize = (32 << 20); /*32M */
+ break;
+ }
+ } else {
+ switch (FBSize) {
+ case 0x00001000:
+ VideoMemSize = (8 << 20); /*8M */
+ break;
+
+ case 0x00002000:
+ VideoMemSize = (16 << 20); /*16M */
+ break;
+
+ case 0x00003000:
+ VideoMemSize = (32 << 20); /*32M */
+ break;
+
+ case 0x00004000:
+ VideoMemSize = (64 << 20); /*64M */
+ break;
+
+ case 0x00005000:
+ VideoMemSize = (128 << 20); /*128M */
+ break;
+
+ case 0x00006000:
+ VideoMemSize = (256 << 20); /*256M */
+ break;
+
+ default:
+ VideoMemSize = (32 << 20); /*32M */
+ break;
+ }
+ }
+
+ return VideoMemSize;
+}
+
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+ *p_gfx_dpa_setting)
+{
+ switch (output_interface) {
+ case INTERFACE_DVP0:
+ {
+ /* DVP0 Clock Polarity and Adjust: */
+ viafb_write_reg_mask(CR96, VIACR,
+ p_gfx_dpa_setting->DVP0, 0x0F);
+
+ /* DVP0 Clock and Data Pads Driving: */
+ viafb_write_reg_mask(SR1E, VIASR,
+ p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
+ viafb_write_reg_mask(SR2A, VIASR,
+ p_gfx_dpa_setting->DVP0ClockDri_S1,
+ BIT4);
+ viafb_write_reg_mask(SR1B, VIASR,
+ p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
+ viafb_write_reg_mask(SR2A, VIASR,
+ p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
+ break;
+ }
+
+ case INTERFACE_DVP1:
+ {
+ /* DVP1 Clock Polarity and Adjust: */
+ viafb_write_reg_mask(CR9B, VIACR,
+ p_gfx_dpa_setting->DVP1, 0x0F);
+
+ /* DVP1 Clock and Data Pads Driving: */
+ viafb_write_reg_mask(SR65, VIASR,
+ p_gfx_dpa_setting->DVP1Driving, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP_HIGH:
+ {
+ viafb_write_reg_mask(CR97, VIACR,
+ p_gfx_dpa_setting->DFPHigh, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP_LOW:
+ {
+ viafb_write_reg_mask(CR99, VIACR,
+ p_gfx_dpa_setting->DFPLow, 0x0F);
+ break;
+ }
+
+ case INTERFACE_DFP:
+ {
+ viafb_write_reg_mask(CR97, VIACR,
+ p_gfx_dpa_setting->DFPHigh, 0x0F);
+ viafb_write_reg_mask(CR99, VIACR,
+ p_gfx_dpa_setting->DFPLow, 0x0F);
+ break;
+ }
+ }
+}
+
+void viafb_memory_pitch_patch(struct fb_info *info)
+{
+ if (info->var.xres != info->var.xres_virtual) {
+ viafb_load_offset_reg(info->var.xres_virtual,
+ info->var.bits_per_pixel >> 3, IGA1);
+
+ if (viafb_SAMM_ON) {
+ viafb_load_offset_reg(viafb_second_virtual_xres,
+ viafb_bpp1 >> 3,
+ IGA2);
+ } else {
+ viafb_load_offset_reg(info->var.xres_virtual,
+ info->var.bits_per_pixel >> 3, IGA2);
+ }
+
+ }
+}
+
+/*According var's xres, yres fill var's other timing information*/
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
+ int mode_index)
+{
+ struct VideoModeTable *vmode_tbl = NULL;
+ struct crt_mode_table *crt_timing = NULL;
+ struct display_timing crt_reg;
+ int i = 0, index = 0;
+ vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
+ crt_timing = vmode_tbl->crtc;
+ for (i = 0; i < vmode_tbl->mode_array; i++) {
+ index = i;
+ if (crt_timing[i].refresh_rate == refresh)
+ break;
+ }
+
+ crt_reg = crt_timing[index].crtc;
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ break;
+ default:
+ /* never happed, put here to keep consistent */
+ break;
+ }
+
+ var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
+ var->left_margin =
+ crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
+ var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
+ var->hsync_len = crt_reg.hor_sync_end;
+ var->upper_margin =
+ crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
+ var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
+ var->vsync_len = crt_reg.ver_sync_end;
+}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
new file mode 100644
index 00000000000..6ff38fa8569
--- /dev/null
+++ b/drivers/video/via/hw.h
@@ -0,0 +1,933 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HW_H__
+#define __HW_H__
+
+#include "global.h"
+
+/***************************************************
+* Definition IGA1 Design Method of CRTC Registers *
+****************************************************/
+#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
+#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
+#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
+#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
+#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
+#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
+
+#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
+#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
+#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
+#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
+#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
+#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
+
+/***************************************************
+** Definition IGA2 Design Method of CRTC Registers *
+****************************************************/
+#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
+#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
+#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
+#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
+#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
+#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
+
+#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
+#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
+#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
+#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
+#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
+#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
+
+/**********************************************************/
+/* Definition IGA2 Design Method of CRTC Shadow Registers */
+/**********************************************************/
+#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x) ((x/8)-5)
+#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y) (((x+y)/8)-1)
+#define IGA2_VER_TOTAL_SHADOW_FORMULA(x) ((x)-2)
+#define IGA2_VER_ADDR_SHADOW_FORMULA(x) ((x)-1)
+#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x) ((x)-1)
+#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y) ((x+y)-1)
+#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
+#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
+
+/* Define Register Number for IGA1 CRTC Timing */
+
+/* location: {CR00,0,7},{CR36,3,3} */
+#define IGA1_HOR_TOTAL_REG_NUM 2
+/* location: {CR01,0,7} */
+#define IGA1_HOR_ADDR_REG_NUM 1
+/* location: {CR02,0,7} */
+#define IGA1_HOR_BLANK_START_REG_NUM 1
+/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
+#define IGA1_HOR_BLANK_END_REG_NUM 3
+/* location: {CR04,0,7},{CR33,4,4} */
+#define IGA1_HOR_SYNC_START_REG_NUM 2
+/* location: {CR05,0,4} */
+#define IGA1_HOR_SYNC_END_REG_NUM 1
+/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
+#define IGA1_VER_TOTAL_REG_NUM 4
+/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
+#define IGA1_VER_ADDR_REG_NUM 4
+/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
+#define IGA1_VER_BLANK_START_REG_NUM 4
+/* location: {CR16,0,7} */
+#define IGA1_VER_BLANK_END_REG_NUM 1
+/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
+#define IGA1_VER_SYNC_START_REG_NUM 4
+/* location: {CR11,0,3} */
+#define IGA1_VER_SYNC_END_REG_NUM 1
+
+/* Define Register Number for IGA2 Shadow CRTC Timing */
+
+/* location: {CR6D,0,7},{CR71,3,3} */
+#define IGA2_SHADOW_HOR_TOTAL_REG_NUM 2
+/* location: {CR6E,0,7} */
+#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM 1
+/* location: {CR6F,0,7},{CR71,0,2} */
+#define IGA2_SHADOW_VER_TOTAL_REG_NUM 2
+/* location: {CR70,0,7},{CR71,4,6} */
+#define IGA2_SHADOW_VER_ADDR_REG_NUM 2
+/* location: {CR72,0,7},{CR74,4,6} */
+#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
+/* location: {CR73,0,7},{CR74,0,2} */
+#define IGA2_SHADOW_VER_BLANK_END_REG_NUM 2
+/* location: {CR75,0,7},{CR76,4,6} */
+#define IGA2_SHADOW_VER_SYNC_START_REG_NUM 2
+/* location: {CR76,0,3} */
+#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
+
+/* Define Register Number for IGA2 CRTC Timing */
+
+/* location: {CR50,0,7},{CR55,0,3} */
+#define IGA2_HOR_TOTAL_REG_NUM 2
+/* location: {CR51,0,7},{CR55,4,6} */
+#define IGA2_HOR_ADDR_REG_NUM 2
+/* location: {CR52,0,7},{CR54,0,2} */
+#define IGA2_HOR_BLANK_START_REG_NUM 2
+/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
+is reserved, so it may have problem to set 1600x1200 on IGA2. */
+/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
+#define IGA2_HOR_BLANK_END_REG_NUM 3
+/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
+/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
+#define IGA2_HOR_SYNC_START_REG_NUM 4
+
+/* location: {CR57,0,7},{CR5C,6,6} */
+#define IGA2_HOR_SYNC_END_REG_NUM 2
+/* location: {CR58,0,7},{CR5D,0,2} */
+#define IGA2_VER_TOTAL_REG_NUM 2
+/* location: {CR59,0,7},{CR5D,3,5} */
+#define IGA2_VER_ADDR_REG_NUM 2
+/* location: {CR5A,0,7},{CR5C,0,2} */
+#define IGA2_VER_BLANK_START_REG_NUM 2
+/* location: {CR5E,0,7},{CR5C,3,5} */
+#define IGA2_VER_BLANK_END_REG_NUM 2
+/* location: {CR5E,0,7},{CR5F,5,7} */
+#define IGA2_VER_SYNC_START_REG_NUM 2
+/* location: {CR5F,0,4} */
+#define IGA2_VER_SYNC_END_REG_NUM 1
+
+/* Define Offset and Fetch Count Register*/
+
+/* location: {CR13,0,7},{CR35,5,7} */
+#define IGA1_OFFSET_REG_NUM 2
+/* 8 bytes alignment. */
+#define IGA1_OFFSER_ALIGN_BYTE 8
+/* x: H resolution, y: color depth */
+#define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE)
+/* location: {SR1C,0,7},{SR1D,0,1} */
+#define IGA1_FETCH_COUNT_REG_NUM 2
+/* 16 bytes alignment. */
+#define IGA1_FETCH_COUNT_ALIGN_BYTE 16
+/* x: H resolution, y: color depth */
+#define IGA1_FETCH_COUNT_PATCH_VALUE 4
+#define IGA1_FETCH_COUNT_FORMULA(x, y) \
+ (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
+
+/* location: {CR66,0,7},{CR67,0,1} */
+#define IGA2_OFFSET_REG_NUM 2
+#define IGA2_OFFSET_ALIGN_BYTE 8
+/* x: H resolution, y: color depth */
+#define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE)
+/* location: {CR65,0,7},{CR67,2,3} */
+#define IGA2_FETCH_COUNT_REG_NUM 2
+#define IGA2_FETCH_COUNT_ALIGN_BYTE 16
+#define IGA2_FETCH_COUNT_PATCH_VALUE 0
+#define IGA2_FETCH_COUNT_FORMULA(x, y) \
+ (((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
+
+/* Staring Address*/
+
+/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
+#define IGA1_STARTING_ADDR_REG_NUM 4
+/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
+#define IGA2_STARTING_ADDR_REG_NUM 3
+
+/* Define Display OFFSET*/
+/* These value are by HW suggested value*/
+/* location: {SR17,0,7} */
+#define K800_IGA1_FIFO_MAX_DEPTH 384
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K800_IGA1_FIFO_THRESHOLD 328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K800_IGA1_FIFO_HIGH_THRESHOLD 296
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+ /* because HW only 5 bits */
+#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K800_IGA2_FIFO_MAX_DEPTH 384
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K800_IGA2_FIFO_THRESHOLD 328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K800_IGA2_FIFO_HIGH_THRESHOLD 296
+/* location: {CR94,0,6} */
+#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
+
+/* location: {SR17,0,7} */
+#define P880_IGA1_FIFO_MAX_DEPTH 192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P880_IGA1_FIFO_THRESHOLD 128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P880_IGA1_FIFO_HIGH_THRESHOLD 64
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+ /* because HW only 5 bits */
+#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P880_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P880_IGA2_FIFO_THRESHOLD 64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P880_IGA2_FIFO_HIGH_THRESHOLD 32
+/* location: {CR94,0,6} */
+#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
+
+/* VT3314 chipset*/
+
+/* location: {SR17,0,7} */
+#define CN700_IGA1_FIFO_MAX_DEPTH 96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CN700_IGA1_FIFO_THRESHOLD 80
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CN700_IGA1_FIFO_HIGH_THRESHOLD 64
+/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
+ because HW only 5 bits */
+#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CN700_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CN700_IGA2_FIFO_THRESHOLD 80
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CN700_IGA2_FIFO_HIGH_THRESHOLD 32
+/* location: {CR94,0,6} */
+#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
+
+/* For VT3324, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define CX700_IGA1_FIFO_MAX_DEPTH 192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CX700_IGA1_FIFO_THRESHOLD 128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CX700_IGA1_FIFO_HIGH_THRESHOLD 128
+/* location: {SR22,0,4} */
+#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CX700_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CX700_IGA2_FIFO_THRESHOLD 64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CX700_IGA2_FIFO_HIGH_THRESHOLD 32
+/* location: {CR94,0,6} */
+#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
+
+/* VT3336 chipset*/
+/* location: {SR17,0,7} */
+#define K8M890_IGA1_FIFO_MAX_DEPTH 360
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K8M890_IGA1_FIFO_THRESHOLD 328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K8M890_IGA1_FIFO_HIGH_THRESHOLD 296
+/* location: {SR22,0,4}. */
+#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K8M890_IGA2_FIFO_MAX_DEPTH 360
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K8M890_IGA2_FIFO_THRESHOLD 328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K8M890_IGA2_FIFO_HIGH_THRESHOLD 296
+/* location: {CR94,0,6} */
+#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 124
+
+/* VT3327 chipset*/
+/* location: {SR17,0,7} */
+#define P4M890_IGA1_FIFO_MAX_DEPTH 96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M890_IGA1_FIFO_THRESHOLD 76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M890_IGA1_FIFO_HIGH_THRESHOLD 64
+/* location: {SR22,0,4}. (32/4) =8 */
+#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M890_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M890_IGA2_FIFO_THRESHOLD 76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M890_IGA2_FIFO_HIGH_THRESHOLD 64
+/* location: {CR94,0,6} */
+#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
+
+/* VT3364 chipset*/
+/* location: {SR17,0,7} */
+#define P4M900_IGA1_FIFO_MAX_DEPTH 96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M900_IGA1_FIFO_THRESHOLD 76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M900_IGA1_FIFO_HIGH_THRESHOLD 76
+/* location: {SR22,0,4}. */
+#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M900_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M900_IGA2_FIFO_THRESHOLD 76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M900_IGA2_FIFO_HIGH_THRESHOLD 76
+/* location: {CR94,0,6} */
+#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
+
+/* For VT3353, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define VX800_IGA1_FIFO_MAX_DEPTH 192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define VX800_IGA1_FIFO_THRESHOLD 152
+/* location: {SR18,0,5},{SR18,7,7} */
+#define VX800_IGA1_FIFO_HIGH_THRESHOLD 152
+/* location: {SR22,0,4} */
+#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 64
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define VX800_IGA2_FIFO_MAX_DEPTH 96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define VX800_IGA2_FIFO_THRESHOLD 64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define VX800_IGA2_FIFO_HIGH_THRESHOLD 32
+/* location: {CR94,0,6} */
+#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
+
+#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
+#define IGA1_FIFO_THRESHOLD_REG_NUM 2
+#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
+
+#define IGA2_FIFO_DEPTH_SELECT_REG_NUM 3
+#define IGA2_FIFO_THRESHOLD_REG_NUM 2
+#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM 2
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
+
+#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x) ((x/2)-1)
+#define IGA1_FIFO_THRESHOLD_FORMULA(x) (x/4)
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
+#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
+#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x) (((x/2)/4)-1)
+#define IGA2_FIFO_THRESHOLD_FORMULA(x) (x/4)
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
+#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
+
+/************************************************************************/
+/* LCD Timing */
+/************************************************************************/
+
+/* 500 ms = 500000 us */
+#define LCD_POWER_SEQ_TD0 500000
+/* 50 ms = 50000 us */
+#define LCD_POWER_SEQ_TD1 50000
+/* 0 us */
+#define LCD_POWER_SEQ_TD2 0
+/* 210 ms = 210000 us */
+#define LCD_POWER_SEQ_TD3 210000
+/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
+#define CLE266_POWER_SEQ_UNIT 71
+/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
+#define K800_POWER_SEQ_UNIT 142
+/* 2^13 * (1/14.31818M) = 572.1 us */
+#define P880_POWER_SEQ_UNIT 572
+
+#define CLE266_POWER_SEQ_FORMULA(x) ((x)/CLE266_POWER_SEQ_UNIT)
+#define K800_POWER_SEQ_FORMULA(x) ((x)/K800_POWER_SEQ_UNIT)
+#define P880_POWER_SEQ_FORMULA(x) ((x)/P880_POWER_SEQ_UNIT)
+
+/* location: {CR8B,0,7},{CR8F,0,3} */
+#define LCD_POWER_SEQ_TD0_REG_NUM 2
+/* location: {CR8C,0,7},{CR8F,4,7} */
+#define LCD_POWER_SEQ_TD1_REG_NUM 2
+/* location: {CR8D,0,7},{CR90,0,3} */
+#define LCD_POWER_SEQ_TD2_REG_NUM 2
+/* location: {CR8E,0,7},{CR90,4,7} */
+#define LCD_POWER_SEQ_TD3_REG_NUM 2
+
+/* LCD Scaling factor*/
+/* x: indicate setting horizontal size*/
+/* y: indicate panel horizontal size*/
+
+/* Horizontal scaling factor 10 bits (2^10) */
+#define CLE266_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
+/* Vertical scaling factor 10 bits (2^10) */
+#define CLE266_LCD_VER_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
+/* Horizontal scaling factor 10 bits (2^12) */
+#define K800_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*4096)/(y-1))
+/* Vertical scaling factor 10 bits (2^11) */
+#define K800_LCD_VER_SCF_FORMULA(x, y) (((x-1)*2048)/(y-1))
+
+/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM 3
+/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM 3
+/* location: {CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE 2
+/* location: {CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
+
+/************************************************
+ ***** Define IGA1 Display Timing *****
+ ************************************************/
+struct io_register {
+ u8 io_addr;
+ u8 start_bit;
+ u8 end_bit;
+};
+
+/* IGA1 Horizontal Total */
+struct iga1_hor_total {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA1 Horizontal Addressable Video */
+struct iga1_hor_addr {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
+};
+
+/* IGA1 Horizontal Blank Start */
+struct iga1_hor_blank_start {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
+};
+
+/* IGA1 Horizontal Blank End */
+struct iga1_hor_blank_end {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA1 Horizontal Sync Start */
+struct iga1_hor_sync_start {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
+};
+
+/* IGA1 Horizontal Sync End */
+struct iga1_hor_sync_end {
+ int reg_num;
+ struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
+};
+
+/* IGA1 Vertical Total */
+struct iga1_ver_total {
+ int reg_num;
+ struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
+};
+
+/* IGA1 Vertical Addressable Video */
+struct iga1_ver_addr {
+ int reg_num;
+ struct io_register reg[IGA1_VER_ADDR_REG_NUM];
+};
+
+/* IGA1 Vertical Blank Start */
+struct iga1_ver_blank_start {
+ int reg_num;
+ struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA1 Vertical Blank End */
+struct iga1_ver_blank_end {
+ int reg_num;
+ struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA1 Vertical Sync Start */
+struct iga1_ver_sync_start {
+ int reg_num;
+ struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA1 Vertical Sync End */
+struct iga1_ver_sync_end {
+ int reg_num;
+ struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
+};
+
+/*****************************************************
+** Define IGA2 Shadow Display Timing ****
+*****************************************************/
+
+/* IGA2 Shadow Horizontal Total */
+struct iga2_shadow_hor_total {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Horizontal Blank End */
+struct iga2_shadow_hor_blank_end {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Total */
+struct iga2_shadow_ver_total {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Addressable Video */
+struct iga2_shadow_ver_addr {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank Start */
+struct iga2_shadow_ver_blank_start {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank End */
+struct iga2_shadow_ver_blank_end {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync Start */
+struct iga2_shadow_ver_sync_start {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync End */
+struct iga2_shadow_ver_sync_end {
+ int reg_num;
+ struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
+};
+
+/*****************************************************
+** Define IGA2 Display Timing ****
+******************************************************/
+
+/* IGA2 Horizontal Total */
+struct iga2_hor_total {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA2 Horizontal Addressable Video */
+struct iga2_hor_addr {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
+};
+
+/* IGA2 Horizontal Blank Start */
+struct iga2_hor_blank_start {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Horizontal Blank End */
+struct iga2_hor_blank_end {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Horizontal Sync Start */
+struct iga2_hor_sync_start {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Horizontal Sync End */
+struct iga2_hor_sync_end {
+ int reg_num;
+ struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
+};
+
+/* IGA2 Vertical Total */
+struct iga2_ver_total {
+ int reg_num;
+ struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
+};
+
+/* IGA2 Vertical Addressable Video */
+struct iga2_ver_addr {
+ int reg_num;
+ struct io_register reg[IGA2_VER_ADDR_REG_NUM];
+};
+
+/* IGA2 Vertical Blank Start */
+struct iga2_ver_blank_start {
+ int reg_num;
+ struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Vertical Blank End */
+struct iga2_ver_blank_end {
+ int reg_num;
+ struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Vertical Sync Start */
+struct iga2_ver_sync_start {
+ int reg_num;
+ struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Vertical Sync End */
+struct iga2_ver_sync_end {
+ int reg_num;
+ struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
+};
+
+/* IGA1 Offset Register */
+struct iga1_offset {
+ int reg_num;
+ struct io_register reg[IGA1_OFFSET_REG_NUM];
+};
+
+/* IGA2 Offset Register */
+struct iga2_offset {
+ int reg_num;
+ struct io_register reg[IGA2_OFFSET_REG_NUM];
+};
+
+struct offset {
+ struct iga1_offset iga1_offset_reg;
+ struct iga2_offset iga2_offset_reg;
+};
+
+/* IGA1 Fetch Count Register */
+struct iga1_fetch_count {
+ int reg_num;
+ struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
+};
+
+/* IGA2 Fetch Count Register */
+struct iga2_fetch_count {
+ int reg_num;
+ struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
+};
+
+struct fetch_count {
+ struct iga1_fetch_count iga1_fetch_count_reg;
+ struct iga2_fetch_count iga2_fetch_count_reg;
+};
+
+/* Starting Address Register */
+struct iga1_starting_addr {
+ int reg_num;
+ struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
+};
+
+struct iga2_starting_addr {
+ int reg_num;
+ struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
+};
+
+struct starting_addr {
+ struct iga1_starting_addr iga1_starting_addr_reg;
+ struct iga2_starting_addr iga2_starting_addr_reg;
+};
+
+/* LCD Power Sequence Timer */
+struct lcd_pwd_seq_td0 {
+ int reg_num;
+ struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
+};
+
+struct lcd_pwd_seq_td1 {
+ int reg_num;
+ struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
+};
+
+struct lcd_pwd_seq_td2 {
+ int reg_num;
+ struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
+};
+
+struct lcd_pwd_seq_td3 {
+ int reg_num;
+ struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
+};
+
+struct _lcd_pwd_seq_timer {
+ struct lcd_pwd_seq_td0 td0;
+ struct lcd_pwd_seq_td1 td1;
+ struct lcd_pwd_seq_td2 td2;
+ struct lcd_pwd_seq_td3 td3;
+};
+
+/* LCD Scaling Factor */
+struct _lcd_hor_scaling_factor {
+ int reg_num;
+ struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_ver_scaling_factor {
+ int reg_num;
+ struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_scaling_factor {
+ struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
+ struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
+};
+
+struct pll_map {
+ u32 clk;
+ u32 cle266_pll;
+ u32 k800_pll;
+ u32 cx700_pll;
+};
+
+struct rgbLUT {
+ u8 red;
+ u8 green;
+ u8 blue;
+};
+
+struct lcd_pwd_seq_timer {
+ u16 td0;
+ u16 td1;
+ u16 td2;
+ u16 td3;
+};
+
+/* Display FIFO Relation Registers*/
+struct iga1_fifo_depth_select {
+ int reg_num;
+ struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga1_fifo_threshold_select {
+ int reg_num;
+ struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga1_fifo_high_threshold_select {
+ int reg_num;
+ struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga1_display_queue_expire_num {
+ int reg_num;
+ struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct iga2_fifo_depth_select {
+ int reg_num;
+ struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga2_fifo_threshold_select {
+ int reg_num;
+ struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga2_fifo_high_threshold_select {
+ int reg_num;
+ struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga2_display_queue_expire_num {
+ int reg_num;
+ struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct fifo_depth_select {
+ struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
+ struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
+};
+
+struct fifo_threshold_select {
+ struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
+ struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
+};
+
+struct fifo_high_threshold_select {
+ struct iga1_fifo_high_threshold_select
+ iga1_fifo_high_threshold_select_reg;
+ struct iga2_fifo_high_threshold_select
+ iga2_fifo_high_threshold_select_reg;
+};
+
+struct display_queue_expire_num {
+ struct iga1_display_queue_expire_num
+ iga1_display_queue_expire_num_reg;
+ struct iga2_display_queue_expire_num
+ iga2_display_queue_expire_num_reg;
+};
+
+struct iga1_crtc_timing {
+ struct iga1_hor_total hor_total;
+ struct iga1_hor_addr hor_addr;
+ struct iga1_hor_blank_start hor_blank_start;
+ struct iga1_hor_blank_end hor_blank_end;
+ struct iga1_hor_sync_start hor_sync_start;
+ struct iga1_hor_sync_end hor_sync_end;
+ struct iga1_ver_total ver_total;
+ struct iga1_ver_addr ver_addr;
+ struct iga1_ver_blank_start ver_blank_start;
+ struct iga1_ver_blank_end ver_blank_end;
+ struct iga1_ver_sync_start ver_sync_start;
+ struct iga1_ver_sync_end ver_sync_end;
+};
+
+struct iga2_shadow_crtc_timing {
+ struct iga2_shadow_hor_total hor_total_shadow;
+ struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
+ struct iga2_shadow_ver_total ver_total_shadow;
+ struct iga2_shadow_ver_addr ver_addr_shadow;
+ struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
+ struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
+ struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
+ struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
+};
+
+struct iga2_crtc_timing {
+ struct iga2_hor_total hor_total;
+ struct iga2_hor_addr hor_addr;
+ struct iga2_hor_blank_start hor_blank_start;
+ struct iga2_hor_blank_end hor_blank_end;
+ struct iga2_hor_sync_start hor_sync_start;
+ struct iga2_hor_sync_end hor_sync_end;
+ struct iga2_ver_total ver_total;
+ struct iga2_ver_addr ver_addr;
+ struct iga2_ver_blank_start ver_blank_start;
+ struct iga2_ver_blank_end ver_blank_end;
+ struct iga2_ver_sync_start ver_sync_start;
+ struct iga2_ver_sync_end ver_sync_end;
+};
+
+/* device ID */
+#define CLE266 0x3123
+#define KM400 0x3205
+#define CN400_FUNCTION2 0x2259
+#define CN400_FUNCTION3 0x3259
+/* support VT3314 chipset */
+#define CN700_FUNCTION2 0x2314
+#define CN700_FUNCTION3 0x3208
+/* VT3324 chipset */
+#define CX700_FUNCTION2 0x2324
+#define CX700_FUNCTION3 0x3324
+/* VT3204 chipset*/
+#define KM800_FUNCTION3 0x3204
+/* VT3336 chipset*/
+#define KM890_FUNCTION3 0x3336
+/* VT3327 chipset*/
+#define P4M890_FUNCTION3 0x3327
+/* VT3293 chipset*/
+#define CN750_FUNCTION3 0x3208
+/* VT3364 chipset*/
+#define P4M900_FUNCTION3 0x3364
+/* VT3353 chipset*/
+#define VX800_FUNCTION3 0x3353
+
+#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
+
+struct IODATA {
+ u8 Index;
+ u8 Mask;
+ u8 Data;
+};
+
+struct pci_device_id_info {
+ u32 vendor;
+ u32 device;
+ u32 chip_index;
+};
+
+extern unsigned int viafb_second_virtual_xres;
+extern unsigned int viafb_second_offset;
+extern int viafb_second_size;
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_accel;
+extern int viafb_hotplug;
+
+void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
+void viafb_set_output_path(int device, int set_iga,
+ int output_interface);
+void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
+ int mode_index, int bpp_byte, int set_iga);
+
+void viafb_set_vclock(u32 CLK, int set_iga);
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+ struct io_register *reg,
+ int io_type);
+void viafb_crt_disable(void);
+void viafb_crt_enable(void);
+void init_ad9389(void);
+/* Access I/O Function */
+void viafb_write_reg(u8 index, u16 io_port, u8 data);
+u8 viafb_read_reg(int io_port, u8 index);
+void viafb_lock_crt(void);
+void viafb_unlock_crt(void);
+void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga);
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
+struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
+u32 viafb_get_clk_value(int clk);
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
+void viafb_set_color_depth(int bpp_byte, int set_iga);
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+ *p_gfx_dpa_setting);
+
+int viafb_setmode(int vmode_index, int hor_res, int ver_res,
+ int video_bpp, int vmode_index1, int hor_res1,
+ int ver_res1, int video_bpp1);
+void viafb_init_chip_info(void);
+void viafb_init_dac(int set_iga);
+int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
+int viafb_get_refresh(int hres, int vres, u32 float_refresh);
+void viafb_update_device_setting(int hres, int vres, int bpp,
+ int vmode_refresh, int flag);
+void viafb_get_mmio_info(unsigned long *mmio_base,
+ unsigned long *mmio_len);
+
+void viafb_set_iga_path(void);
+void viafb_set_start_addr(void);
+void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
+
+#endif /* __HW_H__ */
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c
new file mode 100644
index 00000000000..1570636c8d5
--- /dev/null
+++ b/drivers/video/via/iface.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+/* Get frame buffer size from VGA BIOS */
+
+unsigned int viafb_get_memsize(void)
+{
+ unsigned int m;
+
+ /* If memory size provided by user */
+ if (viafb_memsize)
+ m = viafb_memsize * Mb;
+ else {
+ m = (unsigned int)viafb_read_reg(VIASR, SR39);
+ m = m * (4 * Mb);
+
+ if ((m < (16 * Mb)) || (m > (64 * Mb)))
+ m = 16 * Mb;
+ }
+ DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
+ return m;
+}
+
+/* Get Video Buffer Starting Physical Address(back door)*/
+
+unsigned long viafb_get_videobuf_addr(void)
+{
+ struct pci_dev *pdev = NULL;
+ unsigned char sys_mem;
+ unsigned char video_mem;
+ unsigned long sys_mem_size;
+ unsigned long video_mem_size;
+ /*system memory = 256 MB, video memory 64 MB */
+ unsigned long vmem_starting_adr = 0x0C000000;
+
+ pdev =
+ (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
+ VIA_K800_BRIDGE_DID, NULL);
+ if (pdev != NULL) {
+ pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
+ &sys_mem);
+ pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
+ &video_mem);
+ video_mem = (video_mem & 0x70) >> 4;
+ sys_mem_size = ((unsigned long)sys_mem) << 24;
+ if (video_mem != 0)
+ video_mem_size = (1 << (video_mem)) * 1024 * 1024;
+ else
+ video_mem_size = 0;
+
+ vmem_starting_adr = sys_mem_size - video_mem_size;
+ pci_dev_put(pdev);
+ }
+
+ DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
+ vmem_starting_adr);
+ return vmem_starting_adr;
+}
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h
new file mode 100644
index 00000000000..790ec3e3aea
--- /dev/null
+++ b/drivers/video/via/iface.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __IFACE_H__
+#define __IFACE_H__
+
+#define Kb (1024)
+#define Mb (Kb*Kb)
+
+#define VIA_K800_BRIDGE_VID 0x1106
+#define VIA_K800_BRIDGE_DID 0x3204
+
+#define VIA_K800_SYSTEM_MEMORY_REG 0x47
+#define VIA_K800_VIDEO_MEMORY_REG 0xA1
+
+extern int viafb_memsize;
+unsigned int viafb_get_memsize(void);
+unsigned long viafb_get_videobuf_addr(void);
+
+#endif /* __IFACE_H__ */
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c
new file mode 100644
index 00000000000..da03c074e32
--- /dev/null
+++ b/drivers/video/via/ioctl.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+int viafb_ioctl_get_viafb_info(u_long arg)
+{
+ struct viafb_ioctl_info viainfo;
+
+ viainfo.viafb_id = VIAID;
+ viainfo.vendor_id = PCI_VIA_VENDOR_ID;
+
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ viainfo.device_id = UNICHROME_CLE266_DID;
+ break;
+
+ case UNICHROME_K400:
+ viainfo.device_id = UNICHROME_K400_DID;
+ break;
+
+ case UNICHROME_K800:
+ viainfo.device_id = UNICHROME_K800_DID;
+ break;
+
+ case UNICHROME_PM800:
+ viainfo.device_id = UNICHROME_PM800_DID;
+ break;
+
+ case UNICHROME_CN700:
+ viainfo.device_id = UNICHROME_CN700_DID;
+ break;
+
+ case UNICHROME_CX700:
+ viainfo.device_id = UNICHROME_CX700_DID;
+ break;
+
+ case UNICHROME_K8M890:
+ viainfo.device_id = UNICHROME_K8M890_DID;
+ break;
+
+ case UNICHROME_P4M890:
+ viainfo.device_id = UNICHROME_P4M890_DID;
+ break;
+
+ case UNICHROME_P4M900:
+ viainfo.device_id = UNICHROME_P4M900_DID;
+ break;
+ }
+
+ viainfo.version = VERSION_MAJOR;
+ viainfo.revision = VERSION_MINOR;
+
+ if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/* Hot-Plug Priority: DVI > CRT*/
+int viafb_ioctl_hotplug(int hres, int vres, int bpp)
+{
+ int DVIsense, status = 0;
+ DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
+
+ if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
+ NON_TMDS_TRANSMITTER) {
+ DVIsense = viafb_dvi_sense();
+
+ if (DVIsense) {
+ DEBUG_MSG(KERN_INFO "DVI Attached...\n");
+ if (viafb_DeviceStatus != DVI_Device) {
+ viafb_DVI_ON = 1;
+ viafb_CRT_ON = 0;
+ viafb_LCD_ON = 0;
+ viafb_DeviceStatus = DVI_Device;
+ return viafb_DeviceStatus;
+ }
+ status = 1;
+ } else
+ DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
+ }
+
+ if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
+ viafb_CRT_ON = 1;
+ viafb_DVI_ON = 0;
+ viafb_LCD_ON = 0;
+
+ viafb_DeviceStatus = CRT_Device;
+ return viafb_DeviceStatus;
+ }
+
+ return 0;
+}
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h
new file mode 100644
index 00000000000..842fe30b986
--- /dev/null
+++ b/drivers/video/via/ioctl.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __IOCTL_H__
+#define __IOCTL_H__
+
+#ifndef __user
+#define __user
+#endif
+
+/* VIAFB IOCTL definition */
+#define VIAFB_GET_INFO_SIZE 0x56494101 /* 'VIA\01' */
+#define VIAFB_GET_INFO 0x56494102 /* 'VIA\02' */
+#define VIAFB_HOTPLUG 0x56494103 /* 'VIA\03' */
+#define VIAFB_SET_HOTPLUG_FLAG 0x56494104 /* 'VIA\04' */
+#define VIAFB_GET_RESOLUTION 0x56494105 /* 'VIA\05' */
+#define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */
+#define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */
+#define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */
+#define VIAFB_SET_DEVICE 0x5649410A
+#define VIAFB_GET_DEVICE 0x5649410B
+#define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */
+#define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */
+#define VIAFB_SET_DEVICE_INFO 0x56494114
+#define VIAFB_GET_DEVICE_INFO 0x56494115
+
+#define VIAFB_GET_DEVICE_SUPPORT 0x56494118
+#define VIAFB_GET_DEVICE_CONNECT 0x56494119
+#define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A
+#define VIAFB_GET_DRIVER_NAME 0x56494122
+#define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123
+#define VIAFB_GET_GAMMA_LUT 0x56494124
+#define VIAFB_SET_GAMMA_LUT 0x56494125
+#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
+#define VIAFB_SET_VIDEO_DEVICE 0x56494127
+#define VIAFB_GET_VIDEO_DEVICE 0x56494128
+#define VIAFB_SET_SECOND_MODE 0x56494129
+#define VIAFB_SYNC_SURFACE 0x56494130
+#define VIAFB_GET_DRIVER_CAPS 0x56494131
+#define VIAFB_GET_IGA_SCALING_INFO 0x56494132
+#define VIAFB_GET_PANEL_MAX_SIZE 0x56494133
+#define VIAFB_GET_PANEL_MAX_POSITION 0x56494134
+#define VIAFB_SET_PANEL_SIZE 0x56494135
+#define VIAFB_SET_PANEL_POSITION 0x56494136
+#define VIAFB_GET_PANEL_POSITION 0x56494137
+#define VIAFB_GET_PANEL_SIZE 0x56494138
+
+#define None_Device 0x00
+#define CRT_Device 0x01
+#define LCD_Device 0x02
+#define DVI_Device 0x08
+#define CRT2_Device 0x10
+#define LCD2_Device 0x40
+
+#define OP_LCD_CENTERING 0x01
+#define OP_LCD_PANEL_ID 0x02
+#define OP_LCD_MODE 0x03
+
+/*SAMM operation flag*/
+#define OP_SAMM 0x80
+
+#define LCD_PANEL_ID_MAXIMUM 22
+
+#define STATE_ON 0x1
+#define STATE_OFF 0x0
+#define STATE_DEFAULT 0xFFFF
+
+#define MAX_ACTIVE_DEV_NUM 2
+
+struct device_t {
+ unsigned short crt:1;
+ unsigned short dvi:1;
+ unsigned short lcd:1;
+ unsigned short samm:1;
+ unsigned short lcd_dsp_cent:1;
+ unsigned char lcd_mode:1;
+ unsigned short epia_dvi:1;
+ unsigned short lcd_dual_edge:1;
+ unsigned short lcd2:1;
+
+ unsigned short primary_dev;
+ unsigned char lcd_panel_id;
+ unsigned short xres, yres;
+ unsigned short xres1, yres1;
+ unsigned short refresh;
+ unsigned short bpp;
+ unsigned short refresh1;
+ unsigned short bpp1;
+ unsigned short sequence;
+ unsigned short bus_width;
+};
+
+struct viafb_ioctl_info {
+ u32 viafb_id; /* for identifying viafb */
+#define VIAID 0x56494146 /* Identify myself with 'VIAF' */
+ u16 vendor_id;
+ u16 device_id;
+ u8 version;
+ u8 revision;
+ u8 reserved[246]; /* for future use */
+};
+
+struct viafb_ioctl_mode {
+ u32 xres;
+ u32 yres;
+ u32 refresh;
+ u32 bpp;
+ u32 xres_sec;
+ u32 yres_sec;
+ u32 virtual_xres_sec;
+ u32 virtual_yres_sec;
+ u32 refresh_sec;
+ u32 bpp_sec;
+};
+struct viafb_ioctl_samm {
+ u32 samm_status;
+ u32 size_prim;
+ u32 size_sec;
+ u32 mem_base;
+ u32 offset_sec;
+};
+
+struct viafb_driver_version {
+ int iMajorNum;
+ int iKernelNum;
+ int iOSNum;
+ int iMinorNum;
+};
+
+struct viafb_ioctl_lcd_attribute {
+ unsigned int panel_id;
+ unsigned int display_center;
+ unsigned int lcd_mode;
+};
+
+struct viafb_ioctl_setting {
+ /* Enable or disable active devices */
+ unsigned short device_flag;
+ /* Indicate which device should be turn on or turn off. */
+ unsigned short device_status;
+ unsigned int reserved;
+ /* Indicate which LCD's attribute can be changed. */
+ unsigned short lcd_operation_flag;
+ /* 1: SAMM ON 0: SAMM OFF */
+ unsigned short samm_status;
+ /* horizontal resolution of first device */
+ unsigned short first_dev_hor_res;
+ /* vertical resolution of first device */
+ unsigned short first_dev_ver_res;
+ /* horizontal resolution of second device */
+ unsigned short second_dev_hor_res;
+ /* vertical resolution of second device */
+ unsigned short second_dev_ver_res;
+ /* refresh rate of first device */
+ unsigned short first_dev_refresh;
+ /* bpp of first device */
+ unsigned short first_dev_bpp;
+ /* refresh rate of second device */
+ unsigned short second_dev_refresh;
+ /* bpp of second device */
+ unsigned short second_dev_bpp;
+ /* Indicate which device are primary display device. */
+ unsigned int primary_device;
+ /* Indicate which device will show video. only valid in duoview mode */
+ unsigned int video_device_status;
+ unsigned int struct_reserved[34];
+ struct viafb_ioctl_lcd_attribute lcd_attributes;
+};
+
+struct _UTFunctionCaps {
+ unsigned int dw3DScalingState;
+ unsigned int reserved[31];
+};
+
+struct _POSITIONVALUE {
+ unsigned int dwX;
+ unsigned int dwY;
+};
+
+struct _panel_size_pos_info {
+ unsigned int device_type;
+ int x;
+ int y;
+};
+
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+int viafb_ioctl_get_viafb_info(u_long arg);
+int viafb_ioctl_hotplug(int hres, int vres, int bpp);
+
+#endif /* __IOCTL_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
new file mode 100644
index 00000000000..6c7290a6a44
--- /dev/null
+++ b/drivers/video/via/lcd.c
@@ -0,0 +1,1821 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+#include "lcdtbl.h"
+
+static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
+ /* IGA2 Shadow Horizontal Total */
+ {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
+ /* IGA2 Shadow Horizontal Blank End */
+ {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
+ /* IGA2 Shadow Vertical Total */
+ {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
+ /* IGA2 Shadow Vertical Addressable Video */
+ {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
+ /* IGA2 Shadow Vertical Blank Start */
+ {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
+ {{CR72, 0, 7}, {CR74, 4, 6} } },
+ /* IGA2 Shadow Vertical Blank End */
+ {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
+ /* IGA2 Shadow Vertical Sync Start */
+ {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
+ /* IGA2 Shadow Vertical Sync End */
+ {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
+};
+
+static struct _lcd_scaling_factor lcd_scaling_factor = {
+ /* LCD Horizontal Scaling Factor Register */
+ {LCD_HOR_SCALING_FACTOR_REG_NUM,
+ {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
+ /* LCD Vertical Scaling Factor Register */
+ {LCD_VER_SCALING_FACTOR_REG_NUM,
+ {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
+};
+static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
+ /* LCD Horizontal Scaling Factor Register */
+ {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
+ /* LCD Vertical Scaling Factor Register */
+ {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
+};
+
+static int check_lvds_chip(int device_id_subaddr, int device_id);
+static bool lvds_identify_integratedlvds(void);
+static int fp_id_to_vindex(int panel_id);
+static int lvds_register_read(int index);
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+ int panel_vres);
+static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
+ int panel_id);
+static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
+ int panel_id);
+static void load_lcd_patch_regs(int set_hres, int set_vres,
+ int panel_id, int set_iga);
+static void via_pitch_alignment_patch_lcd(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information
+ *plvds_chip_info);
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+
+static void integrated_lvds_disable(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+static void integrated_lvds_enable(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+static void lcd_powersequence_off(void);
+static void lcd_powersequence_on(void);
+static void fill_lcd_format(void);
+static void check_diport_of_integrated_lvds(
+ struct lvds_chip_information *plvds_chip_info,
+ struct lvds_setting_information
+ *plvds_setting_info);
+static struct display_timing lcd_centering_timging(struct display_timing
+ mode_crt_reg,
+ struct display_timing panel_crt_reg);
+static void load_crtc_shadow_timing(struct display_timing mode_timing,
+ struct display_timing panel_timing);
+static void viafb_load_scaling_factor_for_p4m900(int set_hres,
+ int set_vres, int panel_hres, int panel_vres);
+
+static int check_lvds_chip(int device_id_subaddr, int device_id)
+{
+ if (lvds_register_read(device_id_subaddr) == device_id)
+ return OK;
+ else
+ return FAIL;
+}
+
+void viafb_init_lcd_size(void)
+{
+ DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
+ DEBUG_MSG(KERN_INFO
+ "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
+ viaparinfo->lvds_setting_info->get_lcd_size_method);
+
+ switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
+ case GET_LCD_SIZE_BY_SYSTEM_BIOS:
+ break;
+ case GET_LCD_SZIE_BY_HW_STRAPPING:
+ break;
+ case GET_LCD_SIZE_BY_VGA_BIOS:
+ DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
+ viaparinfo->lvds_setting_info->lcd_panel_size =
+ fp_id_to_vindex(viafb_lcd_panel_id);
+ DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
+ viaparinfo->lvds_setting_info->lcd_panel_id);
+ DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
+ viaparinfo->lvds_setting_info->lcd_panel_size);
+ break;
+ case GET_LCD_SIZE_BY_USER_SETTING:
+ DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
+ viaparinfo->lvds_setting_info->lcd_panel_size =
+ fp_id_to_vindex(viafb_lcd_panel_id);
+ DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
+ viaparinfo->lvds_setting_info->lcd_panel_id);
+ DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
+ viaparinfo->lvds_setting_info->lcd_panel_size);
+ break;
+ default:
+ DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID1_800X600;
+ viaparinfo->lvds_setting_info->lcd_panel_size =
+ fp_id_to_vindex(LCD_PANEL_ID1_800X600);
+ }
+ viaparinfo->lvds_setting_info2->lcd_panel_id =
+ viaparinfo->lvds_setting_info->lcd_panel_id;
+ viaparinfo->lvds_setting_info2->lcd_panel_size =
+ viaparinfo->lvds_setting_info->lcd_panel_size;
+ viaparinfo->lvds_setting_info2->lcd_panel_hres =
+ viaparinfo->lvds_setting_info->lcd_panel_hres;
+ viaparinfo->lvds_setting_info2->lcd_panel_vres =
+ viaparinfo->lvds_setting_info->lcd_panel_vres;
+ viaparinfo->lvds_setting_info2->device_lcd_dualedge =
+ viaparinfo->lvds_setting_info->device_lcd_dualedge;
+ viaparinfo->lvds_setting_info2->LCDDithering =
+ viaparinfo->lvds_setting_info->LCDDithering;
+}
+
+static bool lvds_identify_integratedlvds(void)
+{
+ if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
+ /* Two dual channel LCD (Internal LVDS + External LVDS): */
+ /* If we have an external LVDS, such as VT1636, we should
+ have its chip ID already. */
+ if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+ INTEGRATED_LVDS;
+ DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
+ (Internal LVDS + External LVDS)\n");
+ } else {
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ INTEGRATED_LVDS;
+ DEBUG_MSG(KERN_INFO "Not found external LVDS,\
+ so can't support two dual channel LVDS!\n");
+ }
+ } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
+ /* Two single channel LCD (Internal LVDS + Internal LVDS): */
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ INTEGRATED_LVDS;
+ viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+ INTEGRATED_LVDS;
+ DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
+ (Internal LVDS + Internal LVDS)\n");
+ } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
+ /* If we have found external LVDS, just use it,
+ otherwise, we will use internal LVDS as default. */
+ if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ INTEGRATED_LVDS;
+ DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
+ }
+ } else {
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ NON_LVDS_TRANSMITTER;
+ DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
+ return false;
+ }
+
+ return true;
+}
+
+int viafb_lvds_trasmitter_identify(void)
+{
+ viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX;
+ if (viafb_lvds_identify_vt1636()) {
+ viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
+ DEBUG_MSG(KERN_INFO
+ "Found VIA VT1636 LVDS on port i2c 0x31 \n");
+ } else {
+ viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
+ if (viafb_lvds_identify_vt1636()) {
+ viaparinfo->chip_info->lvds_chip_info.i2c_port =
+ GPIOPORTINDEX;
+ DEBUG_MSG(KERN_INFO
+ "Found VIA VT1636 LVDS on port gpio 0x2c \n");
+ }
+ }
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+ lvds_identify_integratedlvds();
+
+ if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+ return true;
+ /* Check for VT1631: */
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+ VT1631_LVDS_I2C_ADDR;
+
+ if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
+ DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+ DEBUG_MSG(KERN_INFO "\n %2d",
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+ return OK;
+ }
+
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ NON_LVDS_TRANSMITTER;
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+ VT1631_LVDS_I2C_ADDR;
+ return FAIL;
+}
+
+static int fp_id_to_vindex(int panel_id)
+{
+ DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
+
+ if (panel_id > LCD_PANEL_ID_MAXIMUM)
+ viafb_lcd_panel_id = panel_id =
+ viafb_read_reg(VIACR, CR3F) & 0x0F;
+
+ switch (panel_id) {
+ case 0x0:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID0_640X480;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_640X480;
+ break;
+ case 0x1:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID1_800X600;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_800X600;
+ break;
+ case 0x2:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID2_1024X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1024X768;
+ break;
+ case 0x3:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID3_1280X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1280X768;
+ break;
+ case 0x4:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID4_1280X1024;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1280X1024;
+ break;
+ case 0x5:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID5_1400X1050;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1400X1050;
+ break;
+ case 0x6:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID6_1600X1200;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1600X1200;
+ break;
+ case 0x8:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_IDA_800X480;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_800X480;
+ break;
+ case 0x9:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID2_1024X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1024X768;
+ break;
+ case 0xA:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID2_1024X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1024X768;
+ break;
+ case 0xB:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID2_1024X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1024X768;
+ break;
+ case 0xC:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID3_1280X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1280X768;
+ break;
+ case 0xD:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID4_1280X1024;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1280X1024;
+ break;
+ case 0xE:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID5_1400X1050;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1400X1050;
+ break;
+ case 0xF:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID6_1600X1200;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1600X1200;
+ break;
+ case 0x10:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID7_1366X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1368X768;
+ break;
+ case 0x11:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID8_1024X600;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1024X600;
+ break;
+ case 0x12:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID3_1280X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1280X768;
+ break;
+ case 0x13:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID9_1280X800;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_1280X800;
+ break;
+ case 0x14:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_IDB_1360X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1360X768;
+ break;
+ case 0x15:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID3_1280X768;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+ viaparinfo->lvds_setting_info->LCDDithering = 0;
+ return VIA_RES_1280X768;
+ break;
+ case 0x16:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_IDC_480X640;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_480X640;
+ break;
+ default:
+ viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+ viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+ viaparinfo->lvds_setting_info->lcd_panel_id =
+ LCD_PANEL_ID1_800X600;
+ viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+ viaparinfo->lvds_setting_info->LCDDithering = 1;
+ return VIA_RES_800X600;
+ }
+}
+
+static int lvds_register_read(int index)
+{
+ u8 data;
+
+ viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->
+ lvds_chip_info.lvds_chip_slave_addr,
+ (u8) index, &data);
+ return data;
+}
+
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+ int panel_vres)
+{
+ int reg_value = 0;
+ int viafb_load_reg_num;
+ struct io_register *reg = NULL;
+
+ DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
+
+ /* LCD Scaling Enable */
+ viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
+ if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
+ viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
+ panel_hres, panel_vres);
+ return;
+ }
+
+ /* Check if expansion for horizontal */
+ if (set_hres != panel_hres) {
+ /* Load Horizontal Scaling Factor */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ reg_value =
+ CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+ viafb_load_reg_num =
+ lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
+ reg_num;
+ reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ break;
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ reg_value =
+ K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+ /* Horizontal scaling enabled */
+ viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
+ viafb_load_reg_num =
+ lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
+ reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ break;
+ }
+
+ DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
+ } else {
+ /* Horizontal scaling disabled */
+ viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
+ }
+
+ /* Check if expansion for vertical */
+ if (set_vres != panel_vres) {
+ /* Load Vertical Scaling Factor */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ reg_value =
+ CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+ viafb_load_reg_num =
+ lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
+ reg_num;
+ reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ break;
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ reg_value =
+ K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+ /* Vertical scaling enabled */
+ viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
+ viafb_load_reg_num =
+ lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
+ reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
+ viafb_load_reg(reg_value,
+ viafb_load_reg_num, reg, VIACR);
+ break;
+ }
+
+ DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
+ } else {
+ /* Vertical scaling disabled */
+ viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
+ }
+}
+
+static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
+ int panel_id)
+{
+ int vmode_index;
+ int reg_num = 0;
+ struct io_reg *lcd_patch_reg = NULL;
+
+ if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+ else
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+ switch (panel_id) {
+ /* LCD 800x600 */
+ case LCD_PANEL_ID1_800X600:
+ switch (vmode_index) {
+ case VIA_RES_640X400:
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
+ lcd_patch_reg = K400_LCD_RES_6X4_8X6;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
+ lcd_patch_reg = K400_LCD_RES_7X4_8X6;
+ break;
+ }
+ break;
+
+ /* LCD 1024x768 */
+ case LCD_PANEL_ID2_1024X768:
+ switch (vmode_index) {
+ case VIA_RES_640X400:
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
+ lcd_patch_reg = K400_LCD_RES_6X4_10X7;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
+ lcd_patch_reg = K400_LCD_RES_7X4_10X7;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
+ lcd_patch_reg = K400_LCD_RES_8X6_10X7;
+ break;
+ }
+ break;
+
+ /* LCD 1280x1024 */
+ case LCD_PANEL_ID4_1280X1024:
+ switch (vmode_index) {
+ case VIA_RES_640X400:
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
+ lcd_patch_reg = K400_LCD_RES_6X4_12X10;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
+ lcd_patch_reg = K400_LCD_RES_7X4_12X10;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
+ lcd_patch_reg = K400_LCD_RES_8X6_12X10;
+ break;
+ case VIA_RES_1024X768:
+ reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
+ lcd_patch_reg = K400_LCD_RES_10X7_12X10;
+ break;
+
+ }
+ break;
+
+ /* LCD 1400x1050 */
+ case LCD_PANEL_ID5_1400X1050:
+ switch (vmode_index) {
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
+ lcd_patch_reg = K400_LCD_RES_6X4_14X10;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
+ lcd_patch_reg = K400_LCD_RES_8X6_14X10;
+ break;
+ case VIA_RES_1024X768:
+ reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
+ lcd_patch_reg = K400_LCD_RES_10X7_14X10;
+ break;
+ case VIA_RES_1280X768:
+ case VIA_RES_1280X800:
+ case VIA_RES_1280X960:
+ case VIA_RES_1280X1024:
+ reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
+ lcd_patch_reg = K400_LCD_RES_12X10_14X10;
+ break;
+ }
+ break;
+
+ /* LCD 1600x1200 */
+ case LCD_PANEL_ID6_1600X1200:
+ switch (vmode_index) {
+ case VIA_RES_640X400:
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
+ lcd_patch_reg = K400_LCD_RES_6X4_16X12;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
+ lcd_patch_reg = K400_LCD_RES_7X4_16X12;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
+ lcd_patch_reg = K400_LCD_RES_8X6_16X12;
+ break;
+ case VIA_RES_1024X768:
+ reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
+ lcd_patch_reg = K400_LCD_RES_10X7_16X12;
+ break;
+ case VIA_RES_1280X768:
+ case VIA_RES_1280X800:
+ case VIA_RES_1280X960:
+ case VIA_RES_1280X1024:
+ reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
+ lcd_patch_reg = K400_LCD_RES_12X10_16X12;
+ break;
+ }
+ break;
+
+ /* LCD 1366x768 */
+ case LCD_PANEL_ID7_1366X768:
+ switch (vmode_index) {
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
+ lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
+ lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
+ lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
+ break;
+ case VIA_RES_1024X768:
+ reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
+ lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
+ break;
+ case VIA_RES_1280X768:
+ case VIA_RES_1280X800:
+ case VIA_RES_1280X960:
+ case VIA_RES_1280X1024:
+ reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
+ lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
+ break;
+ }
+ break;
+
+ /* LCD 1360x768 */
+ case LCD_PANEL_IDB_1360X768:
+ break;
+ }
+ if (reg_num != 0) {
+ /* H.W. Reset : ON */
+ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+ viafb_write_regx(lcd_patch_reg, reg_num);
+
+ /* H.W. Reset : OFF */
+ viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+ /* Reset PLL */
+ viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+ viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+
+ /* Fire! */
+ outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
+ }
+}
+
+static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
+ int panel_id)
+{
+ int vmode_index;
+ int reg_num = 0;
+ struct io_reg *lcd_patch_reg = NULL;
+
+ if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+ else
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+
+ switch (panel_id) {
+ case LCD_PANEL_ID5_1400X1050:
+ switch (vmode_index) {
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
+ lcd_patch_reg = P880_LCD_RES_6X4_14X10;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
+ lcd_patch_reg = P880_LCD_RES_8X6_14X10;
+ break;
+ }
+ break;
+ case LCD_PANEL_ID6_1600X1200:
+ switch (vmode_index) {
+ case VIA_RES_640X400:
+ case VIA_RES_640X480:
+ reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
+ lcd_patch_reg = P880_LCD_RES_6X4_16X12;
+ break;
+ case VIA_RES_720X480:
+ case VIA_RES_720X576:
+ reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
+ lcd_patch_reg = P880_LCD_RES_7X4_16X12;
+ break;
+ case VIA_RES_800X600:
+ reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
+ lcd_patch_reg = P880_LCD_RES_8X6_16X12;
+ break;
+ case VIA_RES_1024X768:
+ reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
+ lcd_patch_reg = P880_LCD_RES_10X7_16X12;
+ break;
+ case VIA_RES_1280X768:
+ case VIA_RES_1280X960:
+ case VIA_RES_1280X1024:
+ reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
+ lcd_patch_reg = P880_LCD_RES_12X10_16X12;
+ break;
+ }
+ break;
+
+ }
+ if (reg_num != 0) {
+ /* H.W. Reset : ON */
+ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+ viafb_write_regx(lcd_patch_reg, reg_num);
+
+ /* H.W. Reset : OFF */
+ viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+ /* Reset PLL */
+ viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+ viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+
+ /* Fire! */
+ outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
+ }
+}
+
+static void load_lcd_patch_regs(int set_hres, int set_vres,
+ int panel_id, int set_iga)
+{
+ int vmode_index;
+
+ if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+ else
+ vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+
+ viafb_unlock_crt();
+
+ /* Patch for simultaneous & Expansion */
+ if ((set_iga == IGA1_IGA2) &&
+ (viaparinfo->lvds_setting_info->display_method ==
+ LCD_EXPANDSION)) {
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
+ break;
+ case UNICHROME_K800:
+ break;
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
+ }
+ }
+
+ viafb_lock_crt();
+}
+
+static void via_pitch_alignment_patch_lcd(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information
+ *plvds_chip_info)
+{
+ unsigned char cr13, cr35, cr65, cr66, cr67;
+ unsigned long dwScreenPitch = 0;
+ unsigned long dwPitch;
+
+ dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
+ if (dwPitch & 0x1F) {
+ dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
+ if (plvds_setting_info->iga_path == IGA2) {
+ if (plvds_setting_info->bpp > 8) {
+ cr66 = (unsigned char)(dwScreenPitch & 0xFF);
+ viafb_write_reg(CR66, VIACR, cr66);
+ cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
+ cr67 |=
+ (unsigned
+ char)((dwScreenPitch & 0x300) >> 8);
+ viafb_write_reg(CR67, VIACR, cr67);
+ }
+
+ /* Fetch Count */
+ cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
+ cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
+ viafb_write_reg(CR67, VIACR, cr67);
+ cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
+ cr65 += 2;
+ viafb_write_reg(CR65, VIACR, cr65);
+ } else {
+ if (plvds_setting_info->bpp > 8) {
+ cr13 = (unsigned char)(dwScreenPitch & 0xFF);
+ viafb_write_reg(CR13, VIACR, cr13);
+ cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
+ cr35 |=
+ (unsigned
+ char)((dwScreenPitch & 0x700) >> 3);
+ viafb_write_reg(CR35, VIACR, cr35);
+ }
+ }
+ }
+}
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_P4M900:
+ viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
+ plvds_chip_info);
+ break;
+ case UNICHROME_P4M890:
+ viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
+ plvds_chip_info);
+ break;
+ }
+ }
+}
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CX700:
+ viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
+ plvds_chip_info);
+ break;
+ }
+ }
+}
+static void lcd_patch_skew(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+ DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
+ switch (plvds_chip_info->output_interface) {
+ case INTERFACE_DVP0:
+ lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
+ break;
+ case INTERFACE_DVP1:
+ lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
+ break;
+ case INTERFACE_DFP_LOW:
+ if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
+ viafb_write_reg_mask(CR99, VIACR, 0x08,
+ BIT0 + BIT1 + BIT2 + BIT3);
+ }
+ break;
+ }
+}
+
+/* LCD Set Mode */
+void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ int video_index = plvds_setting_info->lcd_panel_size;
+ int set_iga = plvds_setting_info->iga_path;
+ int mode_bpp = plvds_setting_info->bpp;
+ int viafb_load_reg_num = 0;
+ int reg_value = 0;
+ int set_hres, set_vres;
+ int panel_hres, panel_vres;
+ u32 pll_D_N;
+ int offset;
+ struct io_register *reg = NULL;
+ struct display_timing mode_crt_reg, panel_crt_reg;
+ struct crt_mode_table *panel_crt_table = NULL;
+ struct VideoModeTable *vmode_tbl = NULL;
+
+ DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
+ /* Get mode table */
+ mode_crt_reg = mode_crt_table->crtc;
+ /* Get panel table Pointer */
+ vmode_tbl = viafb_get_modetbl_pointer(video_index);
+ panel_crt_table = vmode_tbl->crtc;
+ panel_crt_reg = panel_crt_table->crtc;
+ DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
+ set_hres = plvds_setting_info->h_active;
+ set_vres = plvds_setting_info->v_active;
+ panel_hres = plvds_setting_info->lcd_panel_hres;
+ panel_vres = plvds_setting_info->lcd_panel_vres;
+ if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
+ viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
+ plvds_setting_info->vclk = panel_crt_table->clk;
+ if (set_iga == IGA1) {
+ /* IGA1 doesn't have LCD scaling, so set it as centering. */
+ viafb_load_crtc_timing(lcd_centering_timging
+ (mode_crt_reg, panel_crt_reg), IGA1);
+ } else {
+ /* Expansion */
+ if ((plvds_setting_info->display_method ==
+ LCD_EXPANDSION) & ((set_hres != panel_hres)
+ || (set_vres != panel_vres))) {
+ /* expansion timing IGA2 loaded panel set timing*/
+ viafb_load_crtc_timing(panel_crt_reg, IGA2);
+ DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
+ load_lcd_scaling(set_hres, set_vres, panel_hres,
+ panel_vres);
+ DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
+ } else { /* Centering */
+ /* centering timing IGA2 always loaded panel
+ and mode releative timing */
+ viafb_load_crtc_timing(lcd_centering_timging
+ (mode_crt_reg, panel_crt_reg), IGA2);
+ viafb_write_reg_mask(CR79, VIACR, 0x00,
+ BIT0 + BIT1 + BIT2);
+ /* LCD scaling disabled */
+ }
+ }
+
+ if (set_iga == IGA1_IGA2) {
+ load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
+ /* Fill shadow registers */
+
+ switch (plvds_setting_info->lcd_panel_id) {
+ case LCD_PANEL_ID0_640X480:
+ offset = 80;
+ break;
+ case LCD_PANEL_ID1_800X600:
+ case LCD_PANEL_IDA_800X480:
+ offset = 110;
+ break;
+ case LCD_PANEL_ID2_1024X768:
+ offset = 150;
+ break;
+ case LCD_PANEL_ID3_1280X768:
+ case LCD_PANEL_ID4_1280X1024:
+ case LCD_PANEL_ID5_1400X1050:
+ case LCD_PANEL_ID9_1280X800:
+ offset = 190;
+ break;
+ case LCD_PANEL_ID6_1600X1200:
+ offset = 250;
+ break;
+ case LCD_PANEL_ID7_1366X768:
+ case LCD_PANEL_IDB_1360X768:
+ offset = 212;
+ break;
+ default:
+ offset = 140;
+ break;
+ }
+
+ /* Offset for simultaneous */
+ reg_value = offset;
+ viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
+ reg = offset_reg.iga2_offset_reg.reg;
+ viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+ DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
+ viafb_load_fetch_count_reg(set_hres, 4, IGA2);
+ /* Fetch count for simultaneous */
+ } else { /* SAMM */
+ /* Offset for IGA2 only */
+ viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga);
+ /* Fetch count for IGA2 only */
+ viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
+
+ if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+ && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+ viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
+
+ viafb_set_color_depth(mode_bpp / 8, set_iga);
+ }
+
+ fill_lcd_format();
+
+ pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
+ DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
+ viafb_set_vclock(pll_D_N, set_iga);
+
+ viafb_set_output_path(DEVICE_LCD, set_iga,
+ plvds_chip_info->output_interface);
+ lcd_patch_skew(plvds_setting_info, plvds_chip_info);
+
+ /* If K8M800, enable LCD Prefetch Mode. */
+ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+ || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
+ viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
+
+ load_lcd_patch_regs(set_hres, set_vres,
+ plvds_setting_info->lcd_panel_id, set_iga);
+
+ DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
+
+ /* Patch for non 32bit alignment mode */
+ via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
+}
+
+static void integrated_lvds_disable(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ bool turn_off_first_powersequence = false;
+ bool turn_off_second_powersequence = false;
+ if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
+ turn_off_first_powersequence = true;
+ if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
+ turn_off_first_powersequence = true;
+ if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
+ turn_off_second_powersequence = true;
+ if (turn_off_second_powersequence) {
+ /* Use second power sequence control: */
+
+ /* Turn off power sequence. */
+ viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
+
+ /* Turn off back light. */
+ viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
+ }
+ if (turn_off_first_powersequence) {
+ /* Use first power sequence control: */
+
+ /* Turn off power sequence. */
+ viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
+
+ /* Turn off back light. */
+ viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
+ }
+
+ /* Turn DFP High/Low Pad off. */
+ viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
+
+ /* Power off LVDS channel. */
+ switch (plvds_chip_info->output_interface) {
+ case INTERFACE_LVDS0:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
+ break;
+ }
+
+ case INTERFACE_LVDS1:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
+ break;
+ }
+
+ case INTERFACE_LVDS0LVDS1:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
+ break;
+ }
+ }
+}
+
+static void integrated_lvds_enable(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ bool turn_on_first_powersequence = false;
+ bool turn_on_second_powersequence = false;
+
+ DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
+ plvds_chip_info->output_interface);
+ if (plvds_setting_info->lcd_mode == LCD_SPWG)
+ viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
+ else
+ viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
+ if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
+ turn_on_first_powersequence = true;
+ if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
+ turn_on_first_powersequence = true;
+ if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
+ turn_on_second_powersequence = true;
+
+ if (turn_on_second_powersequence) {
+ /* Use second power sequence control: */
+
+ /* Use hardware control power sequence. */
+ viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
+
+ /* Turn on back light. */
+ viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
+
+ /* Turn on hardware power sequence. */
+ viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
+ }
+ if (turn_on_first_powersequence) {
+ /* Use first power sequence control: */
+
+ /* Use hardware control power sequence. */
+ viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
+
+ /* Turn on back light. */
+ viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
+
+ /* Turn on hardware power sequence. */
+ viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+ }
+
+ /* Turn DFP High/Low pad on. */
+ viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
+
+ /* Power on LVDS channel. */
+ switch (plvds_chip_info->output_interface) {
+ case INTERFACE_LVDS0:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
+ break;
+ }
+
+ case INTERFACE_LVDS1:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
+ break;
+ }
+
+ case INTERFACE_LVDS0LVDS1:
+ {
+ viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
+ break;
+ }
+ }
+}
+
+void viafb_lcd_disable(void)
+{
+
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ lcd_powersequence_off();
+ /* DI1 pad off */
+ viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
+ } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+ if (viafb_LCD2_ON
+ && (INTEGRATED_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+ integrated_lvds_disable(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info2);
+ if (INTEGRATED_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+ integrated_lvds_disable(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ if (VT1636_LVDS == viaparinfo->chip_info->
+ lvds_chip_info.lvds_chip_name)
+ viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ } else if (VT1636_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ } else {
+ /* DFP-HL pad off */
+ viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
+ /* Backlight off */
+ viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
+ /* 24 bit DI data paht off */
+ viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
+ /* Simultaneout disabled */
+ viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
+ }
+
+ /* Disable expansion bit */
+ viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
+ /* CRT path set to IGA1 */
+ viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
+ /* Simultaneout disabled */
+ viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
+ /* IGA2 path disabled */
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
+
+}
+
+void viafb_lcd_enable(void)
+{
+ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+ /* DI1 pad on */
+ viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
+ lcd_powersequence_on();
+ } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+ if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+ integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
+ &viaparinfo->chip_info->lvds_chip_info2);
+ if (INTEGRATED_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+ integrated_lvds_enable(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ if (VT1636_LVDS == viaparinfo->chip_info->
+ lvds_chip_info.lvds_chip_name)
+ viafb_enable_lvds_vt1636(viaparinfo->
+ lvds_setting_info, &viaparinfo->chip_info->
+ lvds_chip_info);
+ } else if (VT1636_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
+ } else {
+ /* DFP-HL pad on */
+ viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
+ /* Backlight on */
+ viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
+ /* 24 bit DI data paht on */
+ viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
+
+ /* Set data source selection bit by iga path */
+ if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+ /* DFP-H set to IGA1 */
+ viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
+ /* DFP-L set to IGA1 */
+ viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
+ } else {
+ /* DFP-H set to IGA2 */
+ viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
+ /* DFP-L set to IGA2 */
+ viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
+ }
+ /* LCD enabled */
+ viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
+ }
+
+ if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
+ || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
+ /* CRT path set to IGA2 */
+ viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
+ /* IGA2 path disabled */
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
+ /* IGA2 path enabled */
+ } else { /* IGA2 */
+ viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
+ }
+
+}
+
+static void lcd_powersequence_off(void)
+{
+ int i, mask, data;
+
+ /* Software control power sequence */
+ viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+ for (i = 0; i < 3; i++) {
+ mask = PowerSequenceOff[0][i];
+ data = PowerSequenceOff[1][i] & mask;
+ viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+ udelay(PowerSequenceOff[2][i]);
+ }
+
+ /* Disable LCD */
+ viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
+}
+
+static void lcd_powersequence_on(void)
+{
+ int i, mask, data;
+
+ /* Software control power sequence */
+ viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+ /* Enable LCD */
+ viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
+
+ for (i = 0; i < 3; i++) {
+ mask = PowerSequenceOn[0][i];
+ data = PowerSequenceOn[1][i] & mask;
+ viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+ udelay(PowerSequenceOn[2][i]);
+ }
+
+ udelay(1);
+}
+
+static void fill_lcd_format(void)
+{
+ u8 bdithering = 0, bdual = 0;
+
+ if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
+ bdual = BIT4;
+ if (viaparinfo->lvds_setting_info->LCDDithering)
+ bdithering = BIT0;
+ /* Dual & Dithering */
+ viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
+}
+
+static void check_diport_of_integrated_lvds(
+ struct lvds_chip_information *plvds_chip_info,
+ struct lvds_setting_information
+ *plvds_setting_info)
+{
+ /* Determine LCD DI Port by hardware layout. */
+ switch (viafb_display_hardware_layout) {
+ case HW_LAYOUT_LCD_ONLY:
+ {
+ if (plvds_setting_info->device_lcd_dualedge) {
+ plvds_chip_info->output_interface =
+ INTERFACE_LVDS0LVDS1;
+ } else {
+ plvds_chip_info->output_interface =
+ INTERFACE_LVDS0;
+ }
+
+ break;
+ }
+
+ case HW_LAYOUT_DVI_ONLY:
+ {
+ plvds_chip_info->output_interface = INTERFACE_NONE;
+ break;
+ }
+
+ case HW_LAYOUT_LCD1_LCD2:
+ case HW_LAYOUT_LCD_EXTERNAL_LCD2:
+ {
+ plvds_chip_info->output_interface =
+ INTERFACE_LVDS0LVDS1;
+ break;
+ }
+
+ case HW_LAYOUT_LCD_DVI:
+ {
+ plvds_chip_info->output_interface = INTERFACE_LVDS1;
+ break;
+ }
+
+ default:
+ {
+ plvds_chip_info->output_interface = INTERFACE_LVDS1;
+ break;
+ }
+ }
+
+ DEBUG_MSG(KERN_INFO
+ "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
+ viafb_display_hardware_layout,
+ plvds_chip_info->output_interface);
+}
+
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+ *plvds_chip_info,
+ struct lvds_setting_information
+ *plvds_setting_info)
+{
+ if (INTERFACE_NONE != plvds_chip_info->output_interface) {
+ /*Do nothing, lcd port is specified by module parameter */
+ return;
+ }
+
+ switch (plvds_chip_info->lvds_chip_name) {
+
+ case VT1636_LVDS:
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CX700:
+ plvds_chip_info->output_interface = INTERFACE_DVP1;
+ break;
+ case UNICHROME_CN700:
+ plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+ break;
+ default:
+ plvds_chip_info->output_interface = INTERFACE_DVP0;
+ break;
+ }
+ break;
+
+ case INTEGRATED_LVDS:
+ check_diport_of_integrated_lvds(plvds_chip_info,
+ plvds_setting_info);
+ break;
+
+ default:
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M900:
+ case UNICHROME_P4M890:
+ plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+ break;
+ default:
+ plvds_chip_info->output_interface = INTERFACE_DFP;
+ break;
+ }
+ break;
+ }
+}
+
+static struct display_timing lcd_centering_timging(struct display_timing
+ mode_crt_reg,
+ struct display_timing panel_crt_reg)
+{
+ struct display_timing crt_reg;
+
+ crt_reg.hor_total = panel_crt_reg.hor_total;
+ crt_reg.hor_addr = mode_crt_reg.hor_addr;
+ crt_reg.hor_blank_start =
+ (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
+ crt_reg.hor_addr;
+ crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
+ crt_reg.hor_sync_start =
+ (panel_crt_reg.hor_sync_start -
+ panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
+ crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
+
+ crt_reg.ver_total = panel_crt_reg.ver_total;
+ crt_reg.ver_addr = mode_crt_reg.ver_addr;
+ crt_reg.ver_blank_start =
+ (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
+ crt_reg.ver_addr;
+ crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
+ crt_reg.ver_sync_start =
+ (panel_crt_reg.ver_sync_start -
+ panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
+ crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
+
+ return crt_reg;
+}
+
+static void load_crtc_shadow_timing(struct display_timing mode_timing,
+ struct display_timing panel_timing)
+{
+ struct io_register *reg = NULL;
+ int i;
+ int viafb_load_reg_Num = 0;
+ int reg_value = 0;
+
+ if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
+ /* Expansion */
+ for (i = 12; i < 20; i++) {
+ switch (i) {
+ case H_TOTAL_SHADOW_INDEX:
+ reg_value =
+ IGA2_HOR_TOTAL_SHADOW_FORMULA
+ (panel_timing.hor_total);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.hor_total_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
+ break;
+ case H_BLANK_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_HOR_BLANK_END_SHADOW_FORMULA
+ (panel_timing.hor_blank_start,
+ panel_timing.hor_blank_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ hor_blank_end_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ hor_blank_end_shadow.reg;
+ break;
+ case V_TOTAL_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_TOTAL_SHADOW_FORMULA
+ (panel_timing.ver_total);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_total_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
+ break;
+ case V_ADDR_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_ADDR_SHADOW_FORMULA
+ (panel_timing.ver_addr);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_addr_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
+ break;
+ case V_BLANK_SATRT_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_START_SHADOW_FORMULA
+ (panel_timing.ver_blank_start);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_blank_start_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_blank_start_shadow.reg;
+ break;
+ case V_BLANK_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_END_SHADOW_FORMULA
+ (panel_timing.ver_blank_start,
+ panel_timing.ver_blank_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_blank_end_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_blank_end_shadow.reg;
+ break;
+ case V_SYNC_SATRT_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_START_SHADOW_FORMULA
+ (panel_timing.ver_sync_start);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_sync_start_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_sync_start_shadow.reg;
+ break;
+ case V_SYNC_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_END_SHADOW_FORMULA
+ (panel_timing.ver_sync_start,
+ panel_timing.ver_sync_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_sync_end_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_sync_end_shadow.reg;
+ break;
+ }
+ viafb_load_reg(reg_value,
+ viafb_load_reg_Num, reg, VIACR);
+ }
+ } else { /* Centering */
+ for (i = 12; i < 20; i++) {
+ switch (i) {
+ case H_TOTAL_SHADOW_INDEX:
+ reg_value =
+ IGA2_HOR_TOTAL_SHADOW_FORMULA
+ (panel_timing.hor_total);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.hor_total_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
+ break;
+ case H_BLANK_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_HOR_BLANK_END_SHADOW_FORMULA
+ (panel_timing.hor_blank_start,
+ panel_timing.hor_blank_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ hor_blank_end_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ hor_blank_end_shadow.reg;
+ break;
+ case V_TOTAL_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_TOTAL_SHADOW_FORMULA
+ (panel_timing.ver_total);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_total_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
+ break;
+ case V_ADDR_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_ADDR_SHADOW_FORMULA
+ (mode_timing.ver_addr);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_addr_shadow.
+ reg_num;
+ reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
+ break;
+ case V_BLANK_SATRT_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_START_SHADOW_FORMULA
+ (mode_timing.ver_blank_start);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_blank_start_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_blank_start_shadow.reg;
+ break;
+ case V_BLANK_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_BLANK_END_SHADOW_FORMULA
+ (panel_timing.ver_blank_start,
+ panel_timing.ver_blank_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.
+ ver_blank_end_shadow.reg_num;
+ reg =
+ iga2_shadow_crtc_reg.
+ ver_blank_end_shadow.reg;
+ break;
+ case V_SYNC_SATRT_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_START_SHADOW_FORMULA(
+ (panel_timing.ver_sync_start -
+ panel_timing.ver_blank_start) +
+ (panel_timing.ver_addr -
+ mode_timing.ver_addr) / 2 +
+ mode_timing.ver_addr);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_sync_start_shadow.
+ reg_num;
+ reg =
+ iga2_shadow_crtc_reg.ver_sync_start_shadow.
+ reg;
+ break;
+ case V_SYNC_END_SHADOW_INDEX:
+ reg_value =
+ IGA2_VER_SYNC_END_SHADOW_FORMULA(
+ (panel_timing.ver_sync_start -
+ panel_timing.ver_blank_start) +
+ (panel_timing.ver_addr -
+ mode_timing.ver_addr) / 2 +
+ mode_timing.ver_addr,
+ panel_timing.ver_sync_end);
+ viafb_load_reg_Num =
+ iga2_shadow_crtc_reg.ver_sync_end_shadow.
+ reg_num;
+ reg =
+ iga2_shadow_crtc_reg.ver_sync_end_shadow.
+ reg;
+ break;
+ }
+ viafb_load_reg(reg_value,
+ viafb_load_reg_Num, reg, VIACR);
+ }
+ }
+}
+
+bool viafb_lcd_get_mobile_state(bool *mobile)
+{
+ unsigned char *romptr, *tableptr;
+ u8 core_base;
+ unsigned char *biosptr;
+ /* Rom address */
+ u32 romaddr = 0x000C0000;
+ u16 start_pattern = 0;
+
+ biosptr = ioremap(romaddr, 0x10000);
+
+ memcpy(&start_pattern, biosptr, 2);
+ /* Compare pattern */
+ if (start_pattern == 0xAA55) {
+ /* Get the start of Table */
+ /* 0x1B means BIOS offset position */
+ romptr = biosptr + 0x1B;
+ tableptr = biosptr + *((u16 *) romptr);
+
+ /* Get the start of biosver structure */
+ /* 18 means BIOS version position. */
+ romptr = tableptr + 18;
+ romptr = biosptr + *((u16 *) romptr);
+
+ /* The offset should be 44, but the
+ actual image is less three char. */
+ /* pRom += 44; */
+ romptr += 41;
+
+ core_base = *romptr++;
+
+ if (core_base & 0x8)
+ *mobile = false;
+ else
+ *mobile = true;
+ /* release memory */
+ iounmap(biosptr);
+
+ return true;
+ } else {
+ iounmap(biosptr);
+ return false;
+ }
+}
+
+static void viafb_load_scaling_factor_for_p4m900(int set_hres,
+ int set_vres, int panel_hres, int panel_vres)
+{
+ int h_scaling_factor;
+ int v_scaling_factor;
+ u8 cra2 = 0;
+ u8 cr77 = 0;
+ u8 cr78 = 0;
+ u8 cr79 = 0;
+ u8 cr9f = 0;
+ /* Check if expansion for horizontal */
+ if (set_hres < panel_hres) {
+ /* Load Horizontal Scaling Factor */
+
+ /* For VIA_K8M800 or later chipsets. */
+ h_scaling_factor =
+ K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+ /* HSCaleFactor[1:0] at CR9F[1:0] */
+ cr9f = h_scaling_factor & 0x0003;
+ /* HSCaleFactor[9:2] at CR77[7:0] */
+ cr77 = (h_scaling_factor & 0x03FC) >> 2;
+ /* HSCaleFactor[11:10] at CR79[5:4] */
+ cr79 = (h_scaling_factor & 0x0C00) >> 10;
+ cr79 <<= 4;
+
+ /* Horizontal scaling enabled */
+ cra2 = 0xC0;
+
+ DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
+ h_scaling_factor);
+ } else {
+ /* Horizontal scaling disabled */
+ cra2 = 0x00;
+ }
+
+ /* Check if expansion for vertical */
+ if (set_vres < panel_vres) {
+ /* Load Vertical Scaling Factor */
+
+ /* For VIA_K8M800 or later chipsets. */
+ v_scaling_factor =
+ K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+
+ /* Vertical scaling enabled */
+ cra2 |= 0x08;
+ /* VSCaleFactor[0] at CR79[3] */
+ cr79 |= ((v_scaling_factor & 0x0001) << 3);
+ /* VSCaleFactor[8:1] at CR78[7:0] */
+ cr78 |= (v_scaling_factor & 0x01FE) >> 1;
+ /* VSCaleFactor[10:9] at CR79[7:6] */
+ cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
+
+ DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
+ v_scaling_factor);
+ } else {
+ /* Vertical scaling disabled */
+ cra2 |= 0x00;
+ }
+
+ viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
+ viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
+ viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
+ viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
+ viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
+}
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
new file mode 100644
index 00000000000..071f47cf5be
--- /dev/null
+++ b/drivers/video/via/lcd.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __LCD_H__
+#define __LCD_H__
+
+/*Definition TMDS Device ID register*/
+#define VT1631_DEVICE_ID_REG 0x02
+#define VT1631_DEVICE_ID 0x92
+
+#define VT3271_DEVICE_ID_REG 0x02
+#define VT3271_DEVICE_ID 0x71
+
+#define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01
+#define GET_LCD_SIZE_BY_VGA_BIOS 0x02
+#define GET_LCD_SZIE_BY_HW_STRAPPING 0x03
+#define GET_LCD_SIZE_BY_USER_SETTING 0x04
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480, Channel: single, Dithering: Enable */
+#define LCD_PANEL_ID0_640X480 0x00
+/* Resolution: 800x600, Channel: single, Dithering: Enable */
+#define LCD_PANEL_ID1_800X600 0x01
+/* Resolution: 1024x768, Channel: single, Dithering: Enable */
+#define LCD_PANEL_ID2_1024X768 0x02
+/* Resolution: 1280x768, Channel: single, Dithering: Enable */
+#define LCD_PANEL_ID3_1280X768 0x03
+/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
+#define LCD_PANEL_ID4_1280X1024 0x04
+/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
+#define LCD_PANEL_ID5_1400X1050 0x05
+/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
+#define LCD_PANEL_ID6_1600X1200 0x06
+/* Resolution: 1366x768, Channel: single, Dithering: Disable */
+#define LCD_PANEL_ID7_1366X768 0x07
+/* Resolution: 1024x600, Channel: single, Dithering: Enable*/
+#define LCD_PANEL_ID8_1024X600 0x08
+/* Resolution: 1280x800, Channel: single, Dithering: Enable*/
+#define LCD_PANEL_ID9_1280X800 0x09
+/* Resolution: 800x480, Channel: single, Dithering: Enable*/
+#define LCD_PANEL_IDA_800X480 0x0A
+/* Resolution: 1360x768, Channel: single, Dithering: Disable*/
+#define LCD_PANEL_IDB_1360X768 0x0B
+/* Resolution: 480x640, Channel: single, Dithering: Enable */
+#define LCD_PANEL_IDC_480X640 0x0C
+
+
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_disable(void);
+void viafb_lcd_enable(void);
+void viafb_init_lcd_size(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+ *plvds_chip_info,
+ struct lvds_setting_information
+ *plvds_setting_info);
+void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+int viafb_lvds_trasmitter_identify(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+ *plvds_chip_info,
+ struct lvds_setting_information
+ *plvds_setting_info);
+bool viafb_lcd_get_mobile_state(bool *mobile);
+void viafb_load_crtc_timing(struct display_timing device_timing,
+ int set_iga);
+
+#endif /* __LCD_H__ */
diff --git a/drivers/video/via/lcdtbl.h b/drivers/video/via/lcdtbl.h
new file mode 100644
index 00000000000..6f3dd800be5
--- /dev/null
+++ b/drivers/video/via/lcdtbl.h
@@ -0,0 +1,591 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __LCDTBL_H__
+#define __LCDTBL_H__
+
+#include "share.h"
+
+/* CLE266 Software Power Sequence */
+/* {Mask}, {Data}, {Delay} */
+int PowerSequenceOn[3][3] =
+ { {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} };
+int PowerSequenceOff[3][3] =
+ { {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} };
+
+/* ++++++ P880 ++++++ */
+/* Panel 1600x1200 */
+struct io_reg P880_LCD_RES_6X4_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x5E},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xD6}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR44, 0xFF, 0x7D}, {VIASR, SR45, 0xFF, 0x8C},
+ {VIASR, SR46, 0xFF, 0x02}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_6X4_16X12 ARRAY_SIZE(P880_LCD_RES_6X4_16X12)
+
+struct io_reg P880_LCD_RES_7X4_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x78},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR44, 0xFF, 0x78}, {VIASR, SR45, 0xFF, 0x8C},
+ {VIASR, SR46, 0xFF, 0x01}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_7X4_16X12 ARRAY_SIZE(P880_LCD_RES_7X4_16X12)
+
+struct io_reg P880_LCD_RES_8X6_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR44, 0xFF, 0x6D}, {VIASR, SR45, 0xFF, 0x88},
+ {VIASR, SR46, 0xFF, 0x03}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_8X6_16X12 ARRAY_SIZE(P880_LCD_RES_8X6_16X12)
+
+struct io_reg P880_LCD_RES_10X7_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xAF},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR44, 0xFF, 0x92}, {VIASR, SR45, 0xFF, 0x88},
+ {VIASR, SR46, 0xFF, 0x03}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_10X7_16X12 ARRAY_SIZE(P880_LCD_RES_10X7_16X12)
+
+struct io_reg P880_LCD_RES_12X10_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xD4},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR44, 0xFF, 0xF6}, {VIASR, SR45, 0xFF, 0x88},
+ {VIASR, SR46, 0xFF, 0x05}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_12X10_16X12 ARRAY_SIZE(P880_LCD_RES_12X10_16X12)
+
+/* Panel 1400x1050 */
+struct io_reg P880_LCD_RES_6X4_14X10[] = {
+ /* 640x480 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x63},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR44, 0xFF, 0xC6}, {VIASR, SR45, 0xFF, 0x8C},
+ {VIASR, SR46, 0xFF, 0x05}
+};
+
+#define NUM_TOTAL_P880_LCD_RES_6X4_14X10 ARRAY_SIZE(P880_LCD_RES_6X4_14X10)
+
+struct io_reg P880_LCD_RES_8X6_14X10[] = {
+ /* 800x600 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR44, 0xFF, 0x06}, {VIASR, SR45, 0xFF, 0x8D},
+ {VIASR, SR46, 0xFF, 0x05}
+};
+
+#define NUM_TOTAL_P880_LCD_RES_8X6_14X10 ARRAY_SIZE(P880_LCD_RES_8X6_14X10)
+
+/* ++++++ K400 ++++++ */
+/* Panel 1600x1200 */
+struct io_reg K400_LCD_RES_6X4_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x5E},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xDA}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x7F}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_16X12 ARRAY_SIZE(K400_LCD_RES_6X4_16X12)
+
+struct io_reg K400_LCD_RES_7X4_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x78},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x46}, {VIASR, SR47, 0xFF, 0x3D}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_16X12 ARRAY_SIZE(K400_LCD_RES_7X4_16X12)
+
+struct io_reg K400_LCD_RES_8X6_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x85}, {VIASR, SR47, 0xFF, 0x6F}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_16X12 ARRAY_SIZE(K400_LCD_RES_8X6_16X12)
+
+struct io_reg K400_LCD_RES_10X7_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xAF},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x45}, {VIASR, SR47, 0xFF, 0x4A}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_16X12 ARRAY_SIZE(K400_LCD_RES_10X7_16X12)
+
+struct io_reg K400_LCD_RES_12X10_16X12[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
+ {VIACR, CR5D, 0x40, 0x40},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xD4},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x47}, {VIASR, SR47, 0xFF, 0x7C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_16X12 ARRAY_SIZE(K400_LCD_RES_12X10_16X12)
+
+/* Panel 1400x1050 */
+struct io_reg K400_LCD_RES_6X4_14X10[] = {
+ /* 640x400 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x63},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_14X10 ARRAY_SIZE(K400_LCD_RES_6X4_14X10)
+
+struct io_reg K400_LCD_RES_8X6_14X10[] = {
+ /* 800x600 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_14X10 ARRAY_SIZE(K400_LCD_RES_8X6_14X10)
+
+struct io_reg K400_LCD_RES_10X7_14X10[] = {
+ /* 1024x768 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xA7},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_14X10 ARRAY_SIZE(K400_LCD_RES_10X7_14X10)
+
+struct io_reg K400_LCD_RES_12X10_14X10[] = {
+ /* 1280x768, 1280x960, 1280x1024 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xD2},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_14X10 ARRAY_SIZE(K400_LCD_RES_12X10_14X10)
+
+/* ++++++ K400 ++++++ */
+/* Panel 1366x768 */
+struct io_reg K400_LCD_RES_6X4_1366X7[] = {
+ /* 640x400 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x64},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_1366X7 ARRAY_SIZE(K400_LCD_RES_6X4_1366X7)
+
+struct io_reg K400_LCD_RES_7X4_1366X7[] = {
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x75},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_1366X7 ARRAY_SIZE(K400_LCD_RES_7X4_1366X7)
+
+struct io_reg K400_LCD_RES_8X6_1366X7[] = {
+ /* 800x600 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x82},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_1366X7 ARRAY_SIZE(K400_LCD_RES_8X6_1366X7)
+
+struct io_reg K400_LCD_RES_10X7_1366X7[] = {
+ /* 1024x768 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xA7},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_1366X7 ARRAY_SIZE(K400_LCD_RES_10X7_1366X7)
+
+struct io_reg K400_LCD_RES_12X10_1366X7[] = {
+ /* 1280x768, 1280x960, 1280x1024 */
+ /* IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
+ /* IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
+ {VIACR, CR5D, 0x40, 0x24},
+ /* IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
+ /* IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xD2},
+ /* IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
+ /* VCLK */
+ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_1366X7\
+ ARRAY_SIZE(K400_LCD_RES_12X10_1366X7)
+
+/* ++++++ K400 ++++++ */
+/* Panel 1280x1024 */
+struct io_reg K400_LCD_RES_6X4_12X10[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+ {VIACR, CR5D, 0x40, 0x1C},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x34},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x63},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xAA}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_12X10 ARRAY_SIZE(K400_LCD_RES_6X4_12X10)
+
+struct io_reg K400_LCD_RES_7X4_12X10[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+ {VIACR, CR5D, 0x40, 0x1C},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x68}, {VIACR, CR71, 0x08, 0x34},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x6C},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xA8}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0xED}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_12X10 ARRAY_SIZE(K400_LCD_RES_7X4_12X10)
+
+struct io_reg K400_LCD_RES_8X6_12X10[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+ {VIACR, CR5D, 0x40, 0x1C},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x34},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_12X10 ARRAY_SIZE(K400_LCD_RES_8X6_12X10)
+
+struct io_reg K400_LCD_RES_10X7_12X10[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+ {VIACR, CR5D, 0x40, 0x1C},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x34},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0xA7},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x04},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_12X10 ARRAY_SIZE(K400_LCD_RES_10X7_12X10)
+
+/* ++++++ K400 ++++++ */
+/* Panel 1024x768 */
+struct io_reg K400_LCD_RES_6X4_10X7[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x64},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_10X7 ARRAY_SIZE(K400_LCD_RES_6X4_10X7)
+
+struct io_reg K400_LCD_RES_7X4_10X7[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x75},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_10X7 ARRAY_SIZE(K400_LCD_RES_7X4_10X7)
+
+struct io_reg K400_LCD_RES_8X6_10X7[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
+ {VIACR, CR5D, 0x40, 0x13},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x82},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_10X7 ARRAY_SIZE(K400_LCD_RES_8X6_10X7)
+
+/* ++++++ K400 ++++++ */
+/* Panel 800x600 */
+struct io_reg K400_LCD_RES_6X4_8X6[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x1A}, {VIACR, CR55, 0x0F, 0x34},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x1A}, {VIACR, CR54, 0x38, 0xE3},
+ {VIACR, CR5D, 0x40, 0x12},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x22},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x63},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x6E}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0x86}, {VIASR, SR47, 0xFF, 0xB3}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_8X6 ARRAY_SIZE(K400_LCD_RES_6X4_8X6)
+
+struct io_reg K400_LCD_RES_7X4_8X6[] = {
+ /*IGA2 Horizontal Total */
+ {VIACR, CR50, 0xFF, 0x1F}, {VIACR, CR55, 0x0F, 0x34},
+ /*IGA2 Horizontal Blank End */
+ {VIACR, CR53, 0xFF, 0x1F}, {VIACR, CR54, 0x38, 0xE3},
+ {VIACR, CR5D, 0x40, 0x12},
+ /*IGA2 Horizontal Total Shadow */
+ {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x22},
+ /*IGA2 Horizontal Blank End Shadow */
+ {VIACR, CR6E, 0xFF, 0x83},
+ /*IGA2 Offset */
+ {VIACR, CR66, 0xFF, 0x78}, {VIACR, CR67, 0x03, 0x00},
+ /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x59}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_8X6 ARRAY_SIZE(K400_LCD_RES_7X4_8X6)
+
+#endif /* __LCDTBL_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
new file mode 100644
index 00000000000..2e1254da9c8
--- /dev/null
+++ b/drivers/video/via/share.h
@@ -0,0 +1,1105 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SHARE_H__
+#define __SHARE_H__
+
+/* Define Return Value */
+#define FAIL -1
+#define OK 1
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Define Bit Field */
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+/* Video Memory Size */
+#define VIDEO_MEMORY_SIZE_16M 0x1000000
+
+/* Definition Mode Index
+*/
+#define VIA_RES_640X480 0
+#define VIA_RES_800X600 1
+#define VIA_RES_1024X768 2
+#define VIA_RES_1152X864 3
+#define VIA_RES_1280X1024 4
+#define VIA_RES_1600X1200 5
+#define VIA_RES_1440X1050 6
+#define VIA_RES_1280X768 7
+#define VIA_RES_1280X960 8
+#define VIA_RES_1920X1440 9
+#define VIA_RES_848X480 10
+#define VIA_RES_1400X1050 11
+#define VIA_RES_720X480 12
+#define VIA_RES_720X576 13
+#define VIA_RES_1024X512 14
+#define VIA_RES_856X480 15
+#define VIA_RES_1024X576 16
+#define VIA_RES_640X400 17
+#define VIA_RES_1280X720 18
+#define VIA_RES_1920X1080 19
+#define VIA_RES_800X480 20
+#define VIA_RES_1368X768 21
+#define VIA_RES_1024X600 22
+#define VIA_RES_1280X800 23
+#define VIA_RES_1680X1050 24
+#define VIA_RES_960X600 25
+#define VIA_RES_1000X600 26
+#define VIA_RES_1088X612 27
+#define VIA_RES_1152X720 28
+#define VIA_RES_1200X720 29
+#define VIA_RES_1280X600 30
+#define VIA_RES_1360X768 31
+#define VIA_RES_1366X768 32
+#define VIA_RES_1440X900 33
+#define VIA_RES_1600X900 34
+#define VIA_RES_1600X1024 35
+#define VIA_RES_1792X1344 36
+#define VIA_RES_1856X1392 37
+#define VIA_RES_1920X1200 38
+#define VIA_RES_2048X1536 39
+#define VIA_RES_480X640 40
+
+/*Reduce Blanking*/
+#define VIA_RES_1360X768_RB 131
+#define VIA_RES_1440X900_RB 133
+#define VIA_RES_1400X1050_RB 111
+#define VIA_RES_1600X900_RB 134
+#define VIA_RES_1680X1050_RB 124
+#define VIA_RES_1920X1080_RB 119
+#define VIA_RES_1920X1200_RB 138
+
+#define VIA_RES_INVALID 255
+
+/* standard VGA IO port
+*/
+#define VIARMisc 0x3CC
+#define VIAWMisc 0x3C2
+#define VIAStatus 0x3DA
+#define VIACR 0x3D4
+#define VIASR 0x3C4
+#define VIAGR 0x3CE
+#define VIAAR 0x3C0
+
+#define StdCR 0x19
+#define StdSR 0x04
+#define StdGR 0x09
+#define StdAR 0x14
+
+#define PatchCR 11
+
+/* Display path */
+#define IGA1 1
+#define IGA2 2
+#define IGA1_IGA2 3
+
+/* Define Color Depth */
+#define MODE_8BPP 1
+#define MODE_16BPP 2
+#define MODE_32BPP 4
+
+#define GR20 0x20
+#define GR21 0x21
+#define GR22 0x22
+
+/* Sequencer Registers */
+#define SR01 0x01
+#define SR10 0x10
+#define SR12 0x12
+#define SR15 0x15
+#define SR16 0x16
+#define SR17 0x17
+#define SR18 0x18
+#define SR1B 0x1B
+#define SR1A 0x1A
+#define SR1C 0x1C
+#define SR1D 0x1D
+#define SR1E 0x1E
+#define SR1F 0x1F
+#define SR20 0x20
+#define SR21 0x21
+#define SR22 0x22
+#define SR2A 0x2A
+#define SR2D 0x2D
+#define SR2E 0x2E
+
+#define SR30 0x30
+#define SR39 0x39
+#define SR3D 0x3D
+#define SR3E 0x3E
+#define SR3F 0x3F
+#define SR40 0x40
+#define SR43 0x43
+#define SR44 0x44
+#define SR45 0x45
+#define SR46 0x46
+#define SR47 0x47
+#define SR48 0x48
+#define SR49 0x49
+#define SR4A 0x4A
+#define SR4B 0x4B
+#define SR4C 0x4C
+#define SR52 0x52
+#define SR5E 0x5E
+#define SR65 0x65
+
+/* CRT Controller Registers */
+#define CR00 0x00
+#define CR01 0x01
+#define CR02 0x02
+#define CR03 0x03
+#define CR04 0x04
+#define CR05 0x05
+#define CR06 0x06
+#define CR07 0x07
+#define CR08 0x08
+#define CR09 0x09
+#define CR0A 0x0A
+#define CR0B 0x0B
+#define CR0C 0x0C
+#define CR0D 0x0D
+#define CR0E 0x0E
+#define CR0F 0x0F
+#define CR10 0x10
+#define CR11 0x11
+#define CR12 0x12
+#define CR13 0x13
+#define CR14 0x14
+#define CR15 0x15
+#define CR16 0x16
+#define CR17 0x17
+#define CR18 0x18
+
+/* Extend CRT Controller Registers */
+#define CR30 0x30
+#define CR31 0x31
+#define CR32 0x32
+#define CR33 0x33
+#define CR34 0x34
+#define CR35 0x35
+#define CR36 0x36
+#define CR37 0x37
+#define CR38 0x38
+#define CR39 0x39
+#define CR3A 0x3A
+#define CR3B 0x3B
+#define CR3C 0x3C
+#define CR3D 0x3D
+#define CR3E 0x3E
+#define CR3F 0x3F
+#define CR40 0x40
+#define CR41 0x41
+#define CR42 0x42
+#define CR43 0x43
+#define CR44 0x44
+#define CR45 0x45
+#define CR46 0x46
+#define CR47 0x47
+#define CR48 0x48
+#define CR49 0x49
+#define CR4A 0x4A
+#define CR4B 0x4B
+#define CR4C 0x4C
+#define CR4D 0x4D
+#define CR4E 0x4E
+#define CR4F 0x4F
+#define CR50 0x50
+#define CR51 0x51
+#define CR52 0x52
+#define CR53 0x53
+#define CR54 0x54
+#define CR55 0x55
+#define CR56 0x56
+#define CR57 0x57
+#define CR58 0x58
+#define CR59 0x59
+#define CR5A 0x5A
+#define CR5B 0x5B
+#define CR5C 0x5C
+#define CR5D 0x5D
+#define CR5E 0x5E
+#define CR5F 0x5F
+#define CR60 0x60
+#define CR61 0x61
+#define CR62 0x62
+#define CR63 0x63
+#define CR64 0x64
+#define CR65 0x65
+#define CR66 0x66
+#define CR67 0x67
+#define CR68 0x68
+#define CR69 0x69
+#define CR6A 0x6A
+#define CR6B 0x6B
+#define CR6C 0x6C
+#define CR6D 0x6D
+#define CR6E 0x6E
+#define CR6F 0x6F
+#define CR70 0x70
+#define CR71 0x71
+#define CR72 0x72
+#define CR73 0x73
+#define CR74 0x74
+#define CR75 0x75
+#define CR76 0x76
+#define CR77 0x77
+#define CR78 0x78
+#define CR79 0x79
+#define CR7A 0x7A
+#define CR7B 0x7B
+#define CR7C 0x7C
+#define CR7D 0x7D
+#define CR7E 0x7E
+#define CR7F 0x7F
+#define CR80 0x80
+#define CR81 0x81
+#define CR82 0x82
+#define CR83 0x83
+#define CR84 0x84
+#define CR85 0x85
+#define CR86 0x86
+#define CR87 0x87
+#define CR88 0x88
+#define CR89 0x89
+#define CR8A 0x8A
+#define CR8B 0x8B
+#define CR8C 0x8C
+#define CR8D 0x8D
+#define CR8E 0x8E
+#define CR8F 0x8F
+#define CR90 0x90
+#define CR91 0x91
+#define CR92 0x92
+#define CR93 0x93
+#define CR94 0x94
+#define CR95 0x95
+#define CR96 0x96
+#define CR97 0x97
+#define CR98 0x98
+#define CR99 0x99
+#define CR9A 0x9A
+#define CR9B 0x9B
+#define CR9C 0x9C
+#define CR9D 0x9D
+#define CR9E 0x9E
+#define CR9F 0x9F
+#define CRA0 0xA0
+#define CRA1 0xA1
+#define CRA2 0xA2
+#define CRA3 0xA3
+#define CRD2 0xD2
+#define CRD3 0xD3
+#define CRD4 0xD4
+
+/* LUT Table*/
+#define LUT_DATA 0x3C9 /* DACDATA */
+#define LUT_INDEX_READ 0x3C7 /* DACRX */
+#define LUT_INDEX_WRITE 0x3C8 /* DACWX */
+#define DACMASK 0x3C6
+
+/* Definition Device */
+#define DEVICE_CRT 0x01
+#define DEVICE_DVI 0x03
+#define DEVICE_LCD 0x04
+
+/* Device output interface */
+#define INTERFACE_NONE 0x00
+#define INTERFACE_ANALOG_RGB 0x01
+#define INTERFACE_DVP0 0x02
+#define INTERFACE_DVP1 0x03
+#define INTERFACE_DFP_HIGH 0x04
+#define INTERFACE_DFP_LOW 0x05
+#define INTERFACE_DFP 0x06
+#define INTERFACE_LVDS0 0x07
+#define INTERFACE_LVDS1 0x08
+#define INTERFACE_LVDS0LVDS1 0x09
+#define INTERFACE_TMDS 0x0A
+
+#define HW_LAYOUT_LCD_ONLY 0x01
+#define HW_LAYOUT_DVI_ONLY 0x02
+#define HW_LAYOUT_LCD_DVI 0x03
+#define HW_LAYOUT_LCD1_LCD2 0x04
+#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
+
+/* Definition Refresh Rate */
+#define REFRESH_50 50
+#define REFRESH_60 60
+#define REFRESH_75 75
+#define REFRESH_85 85
+#define REFRESH_100 100
+#define REFRESH_120 120
+
+/* Definition Sync Polarity*/
+#define NEGATIVE 1
+#define POSITIVE 0
+
+/*480x640@60 Sync Polarity (GTF)
+*/
+#define M480X640_R60_HSP NEGATIVE
+#define M480X640_R60_VSP POSITIVE
+
+/*640x480@60 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R60_HSP NEGATIVE
+#define M640X480_R60_VSP NEGATIVE
+
+/*640x480@75 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R75_HSP NEGATIVE
+#define M640X480_R75_VSP NEGATIVE
+
+/*640x480@85 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R85_HSP NEGATIVE
+#define M640X480_R85_VSP NEGATIVE
+
+/*640x480@100 Sync Polarity (GTF Mode)
+*/
+#define M640X480_R100_HSP NEGATIVE
+#define M640X480_R100_VSP POSITIVE
+
+/*640x480@120 Sync Polarity (GTF Mode)
+*/
+#define M640X480_R120_HSP NEGATIVE
+#define M640X480_R120_VSP POSITIVE
+
+/*720x480@60 Sync Polarity (GTF Mode)
+*/
+#define M720X480_R60_HSP NEGATIVE
+#define M720X480_R60_VSP POSITIVE
+
+/*720x576@60 Sync Polarity (GTF Mode)
+*/
+#define M720X576_R60_HSP NEGATIVE
+#define M720X576_R60_VSP POSITIVE
+
+/*800x600@60 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R60_HSP POSITIVE
+#define M800X600_R60_VSP POSITIVE
+
+/*800x600@75 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R75_HSP POSITIVE
+#define M800X600_R75_VSP POSITIVE
+
+/*800x600@85 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R85_HSP POSITIVE
+#define M800X600_R85_VSP POSITIVE
+
+/*800x600@100 Sync Polarity (GTF Mode)
+*/
+#define M800X600_R100_HSP NEGATIVE
+#define M800X600_R100_VSP POSITIVE
+
+/*800x600@120 Sync Polarity (GTF Mode)
+*/
+#define M800X600_R120_HSP NEGATIVE
+#define M800X600_R120_VSP POSITIVE
+
+/*800x480@60 Sync Polarity (CVT Mode)
+*/
+#define M800X480_R60_HSP NEGATIVE
+#define M800X480_R60_VSP POSITIVE
+
+/*848x480@60 Sync Polarity (CVT Mode)
+*/
+#define M848X480_R60_HSP NEGATIVE
+#define M848X480_R60_VSP POSITIVE
+
+/*852x480@60 Sync Polarity (GTF Mode)
+*/
+#define M852X480_R60_HSP NEGATIVE
+#define M852X480_R60_VSP POSITIVE
+
+/*1024x512@60 Sync Polarity (GTF Mode)
+*/
+#define M1024X512_R60_HSP NEGATIVE
+#define M1024X512_R60_VSP POSITIVE
+
+/*1024x600@60 Sync Polarity (GTF Mode)
+*/
+#define M1024X600_R60_HSP NEGATIVE
+#define M1024X600_R60_VSP POSITIVE
+
+/*1024x768@60 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R60_HSP NEGATIVE
+#define M1024X768_R60_VSP NEGATIVE
+
+/*1024x768@75 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R75_HSP POSITIVE
+#define M1024X768_R75_VSP POSITIVE
+
+/*1024x768@85 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R85_HSP POSITIVE
+#define M1024X768_R85_VSP POSITIVE
+
+/*1024x768@100 Sync Polarity (GTF Mode)
+*/
+#define M1024X768_R100_HSP NEGATIVE
+#define M1024X768_R100_VSP POSITIVE
+
+/*1152x864@75 Sync Polarity (VESA Mode)
+*/
+#define M1152X864_R75_HSP POSITIVE
+#define M1152X864_R75_VSP POSITIVE
+
+/*1280x720@60 Sync Polarity (GTF Mode)
+*/
+#define M1280X720_R60_HSP NEGATIVE
+#define M1280X720_R60_VSP POSITIVE
+
+/* 1280x768@50 Sync Polarity (GTF Mode) */
+#define M1280X768_R50_HSP NEGATIVE
+#define M1280X768_R50_VSP POSITIVE
+
+/*1280x768@60 Sync Polarity (GTF Mode)
+*/
+#define M1280X768_R60_HSP NEGATIVE
+#define M1280X768_R60_VSP POSITIVE
+
+/*1280x800@60 Sync Polarity (CVT Mode)
+*/
+#define M1280X800_R60_HSP NEGATIVE
+#define M1280X800_R60_VSP POSITIVE
+
+/*1280x960@60 Sync Polarity (VESA Mode)
+*/
+#define M1280X960_R60_HSP POSITIVE
+#define M1280X960_R60_VSP POSITIVE
+
+/*1280x1024@60 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R60_HSP POSITIVE
+#define M1280X1024_R60_VSP POSITIVE
+
+/* 1360x768@60 Sync Polarity (CVT Mode) */
+#define M1360X768_R60_HSP POSITIVE
+#define M1360X768_R60_VSP POSITIVE
+
+/* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1360X768_RB_R60_HSP POSITIVE
+#define M1360X768_RB_R60_VSP NEGATIVE
+
+/* 1368x768@50 Sync Polarity (GTF Mode) */
+#define M1368X768_R50_HSP NEGATIVE
+#define M1368X768_R50_VSP POSITIVE
+
+/* 1368x768@60 Sync Polarity (VESA Mode) */
+#define M1368X768_R60_HSP NEGATIVE
+#define M1368X768_R60_VSP POSITIVE
+
+/*1280x1024@75 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R75_HSP POSITIVE
+#define M1280X1024_R75_VSP POSITIVE
+
+/*1280x1024@85 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R85_HSP POSITIVE
+#define M1280X1024_R85_VSP POSITIVE
+
+/*1440x1050@60 Sync Polarity (GTF Mode)
+*/
+#define M1440X1050_R60_HSP NEGATIVE
+#define M1440X1050_R60_VSP POSITIVE
+
+/*1600x1200@60 Sync Polarity (VESA Mode)
+*/
+#define M1600X1200_R60_HSP POSITIVE
+#define M1600X1200_R60_VSP POSITIVE
+
+/*1600x1200@75 Sync Polarity (VESA Mode)
+*/
+#define M1600X1200_R75_HSP POSITIVE
+#define M1600X1200_R75_VSP POSITIVE
+
+/* 1680x1050@60 Sync Polarity (CVT Mode) */
+#define M1680x1050_R60_HSP NEGATIVE
+#define M1680x1050_R60_VSP NEGATIVE
+
+/* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1680x1050_RB_R60_HSP POSITIVE
+#define M1680x1050_RB_R60_VSP NEGATIVE
+
+/* 1680x1050@75 Sync Polarity (CVT Mode) */
+#define M1680x1050_R75_HSP NEGATIVE
+#define M1680x1050_R75_VSP POSITIVE
+
+/*1920x1080@60 Sync Polarity (CVT Mode)
+*/
+#define M1920X1080_R60_HSP NEGATIVE
+#define M1920X1080_R60_VSP POSITIVE
+
+/* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1920X1080_RB_R60_HSP POSITIVE
+#define M1920X1080_RB_R60_VSP NEGATIVE
+
+/*1920x1440@60 Sync Polarity (VESA Mode)
+*/
+#define M1920X1440_R60_HSP NEGATIVE
+#define M1920X1440_R60_VSP POSITIVE
+
+/*1920x1440@75 Sync Polarity (VESA Mode)
+*/
+#define M1920X1440_R75_HSP NEGATIVE
+#define M1920X1440_R75_VSP POSITIVE
+
+#if 0
+/* 1400x1050@60 Sync Polarity (VESA Mode) */
+#define M1400X1050_R60_HSP NEGATIVE
+#define M1400X1050_R60_VSP NEGATIVE
+#endif
+
+/* 1400x1050@60 Sync Polarity (CVT Mode) */
+#define M1400X1050_R60_HSP NEGATIVE
+#define M1400X1050_R60_VSP POSITIVE
+
+/* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1400X1050_RB_R60_HSP POSITIVE
+#define M1400X1050_RB_R60_VSP NEGATIVE
+
+/* 1400x1050@75 Sync Polarity (CVT Mode) */
+#define M1400X1050_R75_HSP NEGATIVE
+#define M1400X1050_R75_VSP POSITIVE
+
+/* 960x600@60 Sync Polarity (CVT Mode) */
+#define M960X600_R60_HSP NEGATIVE
+#define M960X600_R60_VSP POSITIVE
+
+/* 1000x600@60 Sync Polarity (GTF Mode) */
+#define M1000X600_R60_HSP NEGATIVE
+#define M1000X600_R60_VSP POSITIVE
+
+/* 1024x576@60 Sync Polarity (GTF Mode) */
+#define M1024X576_R60_HSP NEGATIVE
+#define M1024X576_R60_VSP POSITIVE
+
+/*1024x600@60 Sync Polarity (GTF Mode)*/
+#define M1024X600_R60_HSP NEGATIVE
+#define M1024X600_R60_VSP POSITIVE
+
+/* 1088x612@60 Sync Polarity (CVT Mode) */
+#define M1088X612_R60_HSP NEGATIVE
+#define M1088X612_R60_VSP POSITIVE
+
+/* 1152x720@60 Sync Polarity (CVT Mode) */
+#define M1152X720_R60_HSP NEGATIVE
+#define M1152X720_R60_VSP POSITIVE
+
+/* 1200x720@60 Sync Polarity (GTF Mode) */
+#define M1200X720_R60_HSP NEGATIVE
+#define M1200X720_R60_VSP POSITIVE
+
+/* 1280x600@60 Sync Polarity (GTF Mode) */
+#define M1280x600_R60_HSP NEGATIVE
+#define M1280x600_R60_VSP POSITIVE
+
+/* 1280x720@50 Sync Polarity (GTF Mode) */
+#define M1280X720_R50_HSP NEGATIVE
+#define M1280X720_R50_VSP POSITIVE
+
+/* 1280x720@60 Sync Polarity (CEA Mode) */
+#define M1280X720_CEA_R60_HSP POSITIVE
+#define M1280X720_CEA_R60_VSP POSITIVE
+
+/* 1440x900@60 Sync Polarity (CVT Mode) */
+#define M1440X900_R60_HSP NEGATIVE
+#define M1440X900_R60_VSP POSITIVE
+
+/* 1440x900@75 Sync Polarity (CVT Mode) */
+#define M1440X900_R75_HSP NEGATIVE
+#define M1440X900_R75_VSP POSITIVE
+
+/* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1440X900_RB_R60_HSP POSITIVE
+#define M1440X900_RB_R60_VSP NEGATIVE
+
+/* 1600x900@60 Sync Polarity (CVT Mode) */
+#define M1600X900_R60_HSP NEGATIVE
+#define M1600X900_R60_VSP POSITIVE
+
+/* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1600X900_RB_R60_HSP POSITIVE
+#define M1600X900_RB_R60_VSP NEGATIVE
+
+/* 1600x1024@60 Sync Polarity (GTF Mode) */
+#define M1600X1024_R60_HSP NEGATIVE
+#define M1600X1024_R60_VSP POSITIVE
+
+/* 1792x1344@60 Sync Polarity (DMT Mode) */
+#define M1792x1344_R60_HSP NEGATIVE
+#define M1792x1344_R60_VSP POSITIVE
+
+/* 1856x1392@60 Sync Polarity (DMT Mode) */
+#define M1856x1392_R60_HSP NEGATIVE
+#define M1856x1392_R60_VSP POSITIVE
+
+/* 1920x1200@60 Sync Polarity (CVT Mode) */
+#define M1920X1200_R60_HSP NEGATIVE
+#define M1920X1200_R60_VSP POSITIVE
+
+/* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1920X1200_RB_R60_HSP POSITIVE
+#define M1920X1200_RB_R60_VSP NEGATIVE
+
+/* 1920x1080@60 Sync Polarity (CEA Mode) */
+#define M1920X1080_CEA_R60_HSP POSITIVE
+#define M1920X1080_CEA_R60_VSP POSITIVE
+
+/* 2048x1536@60 Sync Polarity (CVT Mode) */
+#define M2048x1536_R60_HSP NEGATIVE
+#define M2048x1536_R60_VSP POSITIVE
+
+/* define PLL index: */
+#define CLK_25_175M 25175000
+#define CLK_26_880M 26880000
+#define CLK_29_581M 29581000
+#define CLK_31_490M 31490000
+#define CLK_31_500M 31500000
+#define CLK_31_728M 31728000
+#define CLK_32_668M 32688000
+#define CLK_36_000M 36000000
+#define CLK_40_000M 40000000
+#define CLK_41_291M 41291000
+#define CLK_43_163M 43163000
+#define CLK_45_250M 45250000 /* 45.46MHz */
+#define CLK_46_000M 46000000
+#define CLK_46_996M 46996000
+#define CLK_48_000M 48000000
+#define CLK_48_875M 48875000
+#define CLK_49_500M 49500000
+#define CLK_52_406M 52406000
+#define CLK_52_977M 52977000
+#define CLK_56_250M 56250000
+#define CLK_60_466M 60466000
+#define CLK_61_500M 61500000
+#define CLK_65_000M 65000000
+#define CLK_65_178M 65178000
+#define CLK_66_750M 66750000 /* 67.116MHz */
+#define CLK_68_179M 68179000
+#define CLK_69_924M 69924000
+#define CLK_70_159M 70159000
+#define CLK_72_000M 72000000
+#define CLK_74_270M 74270000
+#define CLK_78_750M 78750000
+#define CLK_80_136M 80136000
+#define CLK_83_375M 83375000
+#define CLK_83_950M 83950000
+#define CLK_84_750M 84750000 /* 84.537Mhz */
+#define CLK_85_860M 85860000
+#define CLK_88_750M 88750000
+#define CLK_94_500M 94500000
+#define CLK_97_750M 97750000
+#define CLK_101_000M 101000000
+#define CLK_106_500M 106500000
+#define CLK_108_000M 108000000
+#define CLK_113_309M 113309000
+#define CLK_118_840M 118840000
+#define CLK_119_000M 119000000
+#define CLK_121_750M 121750000 /* 121.704MHz */
+#define CLK_125_104M 125104000
+#define CLK_133_308M 133308000
+#define CLK_135_000M 135000000
+#define CLK_136_700M 136700000
+#define CLK_138_400M 138400000
+#define CLK_146_760M 146760000
+#define CLK_148_500M 148500000
+
+#define CLK_153_920M 153920000
+#define CLK_156_000M 156000000
+#define CLK_157_500M 157500000
+#define CLK_162_000M 162000000
+#define CLK_187_000M 187000000
+#define CLK_193_295M 193295000
+#define CLK_202_500M 202500000
+#define CLK_204_000M 204000000
+#define CLK_218_500M 218500000
+#define CLK_234_000M 234000000
+#define CLK_267_250M 267250000
+#define CLK_297_500M 297500000
+#define CLK_74_481M 74481000
+#define CLK_172_798M 172798000
+#define CLK_122_614M 122614000
+
+/* CLE266 PLL value
+*/
+#define CLE266_PLL_25_175M 0x0000C763
+#define CLE266_PLL_26_880M 0x0000440F
+#define CLE266_PLL_29_581M 0x00008421
+#define CLE266_PLL_31_490M 0x00004721
+#define CLE266_PLL_31_500M 0x0000C3B5
+#define CLE266_PLL_31_728M 0x0000471F
+#define CLE266_PLL_32_668M 0x0000C449
+#define CLE266_PLL_36_000M 0x0000C5E5
+#define CLE266_PLL_40_000M 0x0000C459
+#define CLE266_PLL_41_291M 0x00004417
+#define CLE266_PLL_43_163M 0x0000C579
+#define CLE266_PLL_45_250M 0x0000C57F /* 45.46MHz */
+#define CLE266_PLL_46_000M 0x0000875A
+#define CLE266_PLL_46_996M 0x0000C4E9
+#define CLE266_PLL_48_000M 0x00001443
+#define CLE266_PLL_48_875M 0x00001D63
+#define CLE266_PLL_49_500M 0x00008653
+#define CLE266_PLL_52_406M 0x0000C475
+#define CLE266_PLL_52_977M 0x00004525
+#define CLE266_PLL_56_250M 0x000047B7
+#define CLE266_PLL_60_466M 0x0000494C
+#define CLE266_PLL_61_500M 0x00001456
+#define CLE266_PLL_65_000M 0x000086ED
+#define CLE266_PLL_65_178M 0x0000855B
+#define CLE266_PLL_66_750M 0x0000844B /* 67.116MHz */
+#define CLE266_PLL_68_179M 0x00000413
+#define CLE266_PLL_69_924M 0x00001153
+#define CLE266_PLL_70_159M 0x00001462
+#define CLE266_PLL_72_000M 0x00001879
+#define CLE266_PLL_74_270M 0x00004853
+#define CLE266_PLL_78_750M 0x00004321
+#define CLE266_PLL_80_136M 0x0000051C
+#define CLE266_PLL_83_375M 0x0000C25D
+#define CLE266_PLL_83_950M 0x00000729
+#define CLE266_PLL_84_750M 0x00008576 /* 84.537MHz */
+#define CLE266_PLL_85_860M 0x00004754
+#define CLE266_PLL_88_750M 0x0000051F
+#define CLE266_PLL_94_500M 0x00000521
+#define CLE266_PLL_97_750M 0x00004652
+#define CLE266_PLL_101_000M 0x0000497F
+#define CLE266_PLL_106_500M 0x00008477 /* 106.491463 MHz */
+#define CLE266_PLL_108_000M 0x00008479
+#define CLE266_PLL_113_309M 0x00000C5F
+#define CLE266_PLL_118_840M 0x00004553
+#define CLE266_PLL_119_000M 0x00000D6C
+#define CLE266_PLL_121_750M 0x00004555 /* 121.704MHz */
+#define CLE266_PLL_125_104M 0x000006B5
+#define CLE266_PLL_133_308M 0x0000465F
+#define CLE266_PLL_135_000M 0x0000455E
+#define CLE266_PLL_136_700M 0x00000C73
+#define CLE266_PLL_138_400M 0x00000957
+#define CLE266_PLL_146_760M 0x00004567
+#define CLE266_PLL_148_500M 0x00000853
+#define CLE266_PLL_153_920M 0x00000856
+#define CLE266_PLL_156_000M 0x0000456D
+#define CLE266_PLL_157_500M 0x000005B7
+#define CLE266_PLL_162_000M 0x00004571
+#define CLE266_PLL_187_000M 0x00000976
+#define CLE266_PLL_193_295M 0x0000086C
+#define CLE266_PLL_202_500M 0x00000763
+#define CLE266_PLL_204_000M 0x00000764
+#define CLE266_PLL_218_500M 0x0000065C
+#define CLE266_PLL_234_000M 0x00000662
+#define CLE266_PLL_267_250M 0x00000670
+#define CLE266_PLL_297_500M 0x000005E6
+#define CLE266_PLL_74_481M 0x0000051A
+#define CLE266_PLL_172_798M 0x00004579
+#define CLE266_PLL_122_614M 0x0000073C
+
+/* K800 PLL value
+*/
+#define K800_PLL_25_175M 0x00539001
+#define K800_PLL_26_880M 0x001C8C80
+#define K800_PLL_29_581M 0x00409080
+#define K800_PLL_31_490M 0x006F9001
+#define K800_PLL_31_500M 0x008B9002
+#define K800_PLL_31_728M 0x00AF9003
+#define K800_PLL_32_668M 0x00909002
+#define K800_PLL_36_000M 0x009F9002
+#define K800_PLL_40_000M 0x00578C02
+#define K800_PLL_41_291M 0x00438C01
+#define K800_PLL_43_163M 0x00778C03
+#define K800_PLL_45_250M 0x007D8C83 /* 45.46MHz */
+#define K800_PLL_46_000M 0x00658C02
+#define K800_PLL_46_996M 0x00818C83
+#define K800_PLL_48_000M 0x00848C83
+#define K800_PLL_48_875M 0x00508C81
+#define K800_PLL_49_500M 0x00518C01
+#define K800_PLL_52_406M 0x00738C02
+#define K800_PLL_52_977M 0x00928C83
+#define K800_PLL_56_250M 0x007C8C02
+#define K800_PLL_60_466M 0x00A78C83
+#define K800_PLL_61_500M 0x00AA8C83
+#define K800_PLL_65_000M 0x006B8C01
+#define K800_PLL_65_178M 0x00B48C83
+#define K800_PLL_66_750M 0x00948C82 /* 67.116MHz */
+#define K800_PLL_68_179M 0x00708C01
+#define K800_PLL_69_924M 0x00C18C83
+#define K800_PLL_70_159M 0x00C28C83
+#define K800_PLL_72_000M 0x009F8C82
+#define K800_PLL_74_270M 0x00ce0c03
+#define K800_PLL_78_750M 0x00408801
+#define K800_PLL_80_136M 0x00428801
+#define K800_PLL_83_375M 0x005B0882
+#define K800_PLL_83_950M 0x00738803
+#define K800_PLL_84_750M 0x00748883 /* 84.477MHz */
+#define K800_PLL_85_860M 0x00768883
+#define K800_PLL_88_750M 0x007A8883
+#define K800_PLL_94_500M 0x00828803
+#define K800_PLL_97_750M 0x00878883
+#define K800_PLL_101_000M 0x008B8883
+#define K800_PLL_106_500M 0x00758882 /* 106.491463 MHz */
+#define K800_PLL_108_000M 0x00778882
+#define K800_PLL_113_309M 0x005D8881
+#define K800_PLL_118_840M 0x00A48883
+#define K800_PLL_119_000M 0x00838882
+#define K800_PLL_121_750M 0x00A88883 /* 121.704MHz */
+#define K800_PLL_125_104M 0x00688801
+#define K800_PLL_133_308M 0x005D8801
+#define K800_PLL_135_000M 0x001A4081
+#define K800_PLL_136_700M 0x00BD8883
+#define K800_PLL_138_400M 0x00728881
+#define K800_PLL_146_760M 0x00CC8883
+#define K800_PLL_148_500M 0x00ce0803
+#define K800_PLL_153_920M 0x00548482
+#define K800_PLL_156_000M 0x006B8483
+#define K800_PLL_157_500M 0x00142080
+#define K800_PLL_162_000M 0x006F8483
+#define K800_PLL_187_000M 0x00818483
+#define K800_PLL_193_295M 0x004F8481
+#define K800_PLL_202_500M 0x00538481
+#define K800_PLL_204_000M 0x008D8483
+#define K800_PLL_218_500M 0x00978483
+#define K800_PLL_234_000M 0x00608401
+#define K800_PLL_267_250M 0x006E8481
+#define K800_PLL_297_500M 0x00A48402
+#define K800_PLL_74_481M 0x007B8C81
+#define K800_PLL_172_798M 0x00778483
+#define K800_PLL_122_614M 0x00878882
+
+/* PLL for VT3324 */
+#define CX700_25_175M 0x008B1003
+#define CX700_26_719M 0x00931003
+#define CX700_26_880M 0x00941003
+#define CX700_29_581M 0x00A49003
+#define CX700_31_490M 0x00AE1003
+#define CX700_31_500M 0x00AE1003
+#define CX700_31_728M 0x00AF1003
+#define CX700_32_668M 0x00B51003
+#define CX700_36_000M 0x00C81003
+#define CX700_40_000M 0x006E0C03
+#define CX700_41_291M 0x00710C03
+#define CX700_43_163M 0x00770C03
+#define CX700_45_250M 0x007D0C03 /* 45.46MHz */
+#define CX700_46_000M 0x007F0C03
+#define CX700_46_996M 0x00818C83
+#define CX700_48_000M 0x00840C03
+#define CX700_48_875M 0x00508C81
+#define CX700_49_500M 0x00880C03
+#define CX700_52_406M 0x00730C02
+#define CX700_52_977M 0x00920C03
+#define CX700_56_250M 0x009B0C03
+#define CX700_60_466M 0x00460C00
+#define CX700_61_500M 0x00AA0C03
+#define CX700_65_000M 0x006B0C01
+#define CX700_65_178M 0x006B0C01
+#define CX700_66_750M 0x00940C02 /*67.116MHz */
+#define CX700_68_179M 0x00BC0C03
+#define CX700_69_924M 0x00C10C03
+#define CX700_70_159M 0x00C20C03
+#define CX700_72_000M 0x009F0C02
+#define CX700_74_270M 0x00CE0C03
+#define CX700_74_481M 0x00CE0C03
+#define CX700_78_750M 0x006C0803
+#define CX700_80_136M 0x006E0803
+#define CX700_83_375M 0x005B0882
+#define CX700_83_950M 0x00730803
+#define CX700_84_750M 0x00740803 /* 84.537Mhz */
+#define CX700_85_860M 0x00760803
+#define CX700_88_750M 0x00AC8885
+#define CX700_94_500M 0x00820803
+#define CX700_97_750M 0x00870803
+#define CX700_101_000M 0x008B0803
+#define CX700_106_500M 0x00750802
+#define CX700_108_000M 0x00950803
+#define CX700_113_309M 0x005D0801
+#define CX700_118_840M 0x00A40803
+#define CX700_119_000M 0x00830802
+#define CX700_121_750M 0x00420800 /* 121.704MHz */
+#define CX700_125_104M 0x00AD0803
+#define CX700_133_308M 0x00930802
+#define CX700_135_000M 0x00950802
+#define CX700_136_700M 0x00BD0803
+#define CX700_138_400M 0x00720801
+#define CX700_146_760M 0x00CC0803
+#define CX700_148_500M 0x00a40802
+#define CX700_153_920M 0x00540402
+#define CX700_156_000M 0x006B0403
+#define CX700_157_500M 0x006C0403
+#define CX700_162_000M 0x006F0403
+#define CX700_172_798M 0x00770403
+#define CX700_187_000M 0x00810403
+#define CX700_193_295M 0x00850403
+#define CX700_202_500M 0x008C0403
+#define CX700_204_000M 0x008D0403
+#define CX700_218_500M 0x00970403
+#define CX700_234_000M 0x00600401
+#define CX700_267_250M 0x00B90403
+#define CX700_297_500M 0x00CE0403
+#define CX700_122_614M 0x00870802
+
+/* Definition CRTC Timing Index */
+#define H_TOTAL_INDEX 0
+#define H_ADDR_INDEX 1
+#define H_BLANK_START_INDEX 2
+#define H_BLANK_END_INDEX 3
+#define H_SYNC_START_INDEX 4
+#define H_SYNC_END_INDEX 5
+#define V_TOTAL_INDEX 6
+#define V_ADDR_INDEX 7
+#define V_BLANK_START_INDEX 8
+#define V_BLANK_END_INDEX 9
+#define V_SYNC_START_INDEX 10
+#define V_SYNC_END_INDEX 11
+#define H_TOTAL_SHADOW_INDEX 12
+#define H_BLANK_END_SHADOW_INDEX 13
+#define V_TOTAL_SHADOW_INDEX 14
+#define V_ADDR_SHADOW_INDEX 15
+#define V_BLANK_SATRT_SHADOW_INDEX 16
+#define V_BLANK_END_SHADOW_INDEX 17
+#define V_SYNC_SATRT_SHADOW_INDEX 18
+#define V_SYNC_END_SHADOW_INDEX 19
+
+/* Definition Video Mode Pixel Clock (picoseconds)
+*/
+#define RES_480X640_60HZ_PIXCLOCK 39722
+#define RES_640X480_60HZ_PIXCLOCK 39722
+#define RES_640X480_75HZ_PIXCLOCK 31747
+#define RES_640X480_85HZ_PIXCLOCK 27777
+#define RES_640X480_100HZ_PIXCLOCK 23168
+#define RES_640X480_120HZ_PIXCLOCK 19081
+#define RES_720X480_60HZ_PIXCLOCK 37020
+#define RES_720X576_60HZ_PIXCLOCK 30611
+#define RES_800X600_60HZ_PIXCLOCK 25000
+#define RES_800X600_75HZ_PIXCLOCK 20203
+#define RES_800X600_85HZ_PIXCLOCK 17777
+#define RES_800X600_100HZ_PIXCLOCK 14667
+#define RES_800X600_120HZ_PIXCLOCK 11912
+#define RES_800X480_60HZ_PIXCLOCK 33805
+#define RES_848X480_60HZ_PIXCLOCK 31756
+#define RES_856X480_60HZ_PIXCLOCK 31518
+#define RES_1024X512_60HZ_PIXCLOCK 24218
+#define RES_1024X600_60HZ_PIXCLOCK 20460
+#define RES_1024X768_60HZ_PIXCLOCK 15385
+#define RES_1024X768_75HZ_PIXCLOCK 12699
+#define RES_1024X768_85HZ_PIXCLOCK 10582
+#define RES_1024X768_100HZ_PIXCLOCK 8825
+#define RES_1152X864_75HZ_PIXCLOCK 9259
+#define RES_1280X768_60HZ_PIXCLOCK 12480
+#define RES_1280X800_60HZ_PIXCLOCK 11994
+#define RES_1280X960_60HZ_PIXCLOCK 9259
+#define RES_1280X1024_60HZ_PIXCLOCK 9260
+#define RES_1280X1024_75HZ_PIXCLOCK 7408
+#define RES_1280X768_85HZ_PIXCLOCK 6349
+#define RES_1440X1050_60HZ_PIXCLOCK 7993
+#define RES_1600X1200_60HZ_PIXCLOCK 6172
+#define RES_1600X1200_75HZ_PIXCLOCK 4938
+#define RES_1280X720_60HZ_PIXCLOCK 13426
+#define RES_1920X1080_60HZ_PIXCLOCK 5787
+#define RES_1400X1050_60HZ_PIXCLOCK 8214
+#define RES_1400X1050_75HZ_PIXCLOCK 6410
+#define RES_1368X768_60HZ_PIXCLOCK 11647
+#define RES_960X600_60HZ_PIXCLOCK 22099
+#define RES_1000X600_60HZ_PIXCLOCK 20834
+#define RES_1024X576_60HZ_PIXCLOCK 21278
+#define RES_1088X612_60HZ_PIXCLOCK 18877
+#define RES_1152X720_60HZ_PIXCLOCK 14981
+#define RES_1200X720_60HZ_PIXCLOCK 14253
+#define RES_1280X600_60HZ_PIXCLOCK 16260
+#define RES_1280X720_50HZ_PIXCLOCK 16538
+#define RES_1280X768_50HZ_PIXCLOCK 15342
+#define RES_1366X768_50HZ_PIXCLOCK 14301
+#define RES_1366X768_60HZ_PIXCLOCK 11646
+#define RES_1360X768_60HZ_PIXCLOCK 11799
+#define RES_1440X900_60HZ_PIXCLOCK 9390
+#define RES_1440X900_75HZ_PIXCLOCK 7315
+#define RES_1600X900_60HZ_PIXCLOCK 8415
+#define RES_1600X1024_60HZ_PIXCLOCK 7315
+#define RES_1680X1050_60HZ_PIXCLOCK 6814
+#define RES_1680X1050_75HZ_PIXCLOCK 5348
+#define RES_1792X1344_60HZ_PIXCLOCK 4902
+#define RES_1856X1392_60HZ_PIXCLOCK 4577
+#define RES_1920X1200_60HZ_PIXCLOCK 5173
+#define RES_1920X1440_60HZ_PIXCLOCK 4274
+#define RES_1920X1440_75HZ_PIXCLOCK 3367
+#define RES_2048X1536_60HZ_PIXCLOCK 3742
+
+#define RES_1360X768_RB_60HZ_PIXCLOCK 13889
+#define RES_1400X1050_RB_60HZ_PIXCLOCK 9901
+#define RES_1440X900_RB_60HZ_PIXCLOCK 11268
+#define RES_1600X900_RB_60HZ_PIXCLOCK 10230
+#define RES_1680X1050_RB_60HZ_PIXCLOCK 8403
+#define RES_1920X1080_RB_60HZ_PIXCLOCK 7225
+#define RES_1920X1200_RB_60HZ_PIXCLOCK 6497
+
+/* LCD display method
+*/
+#define LCD_EXPANDSION 0x00
+#define LCD_CENTERING 0x01
+
+/* LCD mode
+*/
+#define LCD_OPENLDI 0x00
+#define LCD_SPWG 0x01
+
+/* Define display timing
+*/
+struct display_timing {
+ u16 hor_total;
+ u16 hor_addr;
+ u16 hor_blank_start;
+ u16 hor_blank_end;
+ u16 hor_sync_start;
+ u16 hor_sync_end;
+ u16 ver_total;
+ u16 ver_addr;
+ u16 ver_blank_start;
+ u16 ver_blank_end;
+ u16 ver_sync_start;
+ u16 ver_sync_end;
+};
+
+struct crt_mode_table {
+ int refresh_rate;
+ unsigned long clk;
+ int h_sync_polarity;
+ int v_sync_polarity;
+ struct display_timing crtc;
+};
+
+struct io_reg {
+ int port;
+ u8 index;
+ u8 mask;
+ u8 value;
+};
+
+#endif /* __SHARE_H__ */
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c
new file mode 100644
index 00000000000..2d8453429d4
--- /dev/null
+++ b/drivers/video/via/tbl1636.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+struct IODATA COMMON_INIT_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ /* Set panel power sequence timing */
+ {0x10, 0xC0, 0x00},
+ /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
+ {0x0B, 0xFF, 0x40},
+ /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
+ {0x0C, 0xFF, 0x31},
+ /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
+ {0x0D, 0xFF, 0x31},
+ /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
+ {0x0E, 0xFF, 0x68},
+ /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
+ {0x0F, 0xFF, 0x68},
+ /* LVDS output power up */
+ {0x09, 0xA0, 0xA0},
+ /* turn on back light */
+ {0x10, 0x33, 0x13}
+};
+
+struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x08, 0xF0, 0xE0} /* Input Data Mode Select */
+};
+
+struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x08, 0xF0, 0x00} /* Input Data Mode Select */
+};
+
+struct IODATA DITHERING_ENABLE_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x0A, 0x70, 0x50}
+};
+
+struct IODATA DITHERING_DISABLE_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x0A, 0x70, 0x00}
+};
+
+struct IODATA VDD_ON_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x10, 0x20, 0x20}
+};
+
+struct IODATA VDD_OFF_TBL_VT1636[] = {
+/* Index, Mask, Value */
+ {0x10, 0x20, 0x00}
+};
diff --git a/drivers/video/via/tbl1636.h b/drivers/video/via/tbl1636.h
new file mode 100644
index 00000000000..d906055f151
--- /dev/null
+++ b/drivers/video/via/tbl1636.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TBL1636_H_
+#define _TBL1636_H_
+#include "hw.h"
+
+extern struct IODATA COMMON_INIT_TBL_VT1636[8];
+extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1];
+extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1];
+extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1];
+extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1];
+extern struct IODATA VDD_ON_TBL_VT1636[1];
+extern struct IODATA VDD_OFF_TBL_VT1636[1];
+
+#endif /* _VIA_TBL1636_H_ */
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c
new file mode 100644
index 00000000000..0c4c8cc712f
--- /dev/null
+++ b/drivers/video/via/tblDPASetting.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+/* For VT3324: */
+struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = {
+ /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
+ {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
+ {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
+ {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
+ {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
+ {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
+ {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
+ {LCD_PANEL_ID6_1600X1200, 0x0B, 0x03} /* For 1600x1200 */
+};
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
+/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
+ DVP1Driving, DFPHigh, DFPLow */
+/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+ SR65, CR97, CR99 */
+ /* LCK/VCK < 30000000 will use this value */
+ {DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00},
+ /* 30000000 < LCK/VCK < 50000000 will use this value */
+ {DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00},
+ /* 50000000 < LCK/VCK < 70000000 will use this value */
+ {DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00},
+ /* 70000000 < LCK/VCK < 100000000 will use this value */
+ {DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00},
+ /* 100000000 < LCK/VCK < 15000000 will use this value */
+ {DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00},
+ /* 15000000 < LCK/VCK will use this value */
+ {DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
+ 0x00},
+};
+
+/* For VT3327: */
+struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = {
+ /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
+ {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
+ {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
+ {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
+ {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
+ {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
+ {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
+ {LCD_PANEL_ID6_1600X1200, 0x00, 0x00} /* For 1600x1200 */
+};
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
+/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
+ DVP1Driving, DFPHigh, DFPLow */
+/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+ SR65, CR97, CR99 */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
+};
+
+/* For VT3364: */
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
+/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
+ DVP1Driving, DFPHigh, DFPLow */
+/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+ SR65, CR97, CR99 */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
+};
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
new file mode 100644
index 00000000000..b065a83481d
--- /dev/null
+++ b/drivers/video/via/tblDPASetting.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TBLDPASETTING_H_
+#define _TBLDPASETTING_H_
+#include "global.h"
+
+#define DPA_CLK_30M 30000000
+#define DPA_CLK_50M 50000000
+#define DPA_CLK_70M 70000000
+#define DPA_CLK_100M 100000000
+#define DPA_CLK_150M 150000000
+
+enum DPA_RANGE {
+ DPA_CLK_RANGE_30M,
+ DPA_CLK_RANGE_30_50M,
+ DPA_CLK_RANGE_50_70M,
+ DPA_CLK_RANGE_70_100M,
+ DPA_CLK_RANGE_100_150M,
+ DPA_CLK_RANGE_150M
+};
+
+extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
+extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
+
+#endif
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
new file mode 100644
index 00000000000..0f3ed4eb236
--- /dev/null
+++ b/drivers/video/via/via_i2c.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+static void via_i2c_setscl(void *data, int state)
+{
+ u8 val;
+ struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+ val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
+ if (state)
+ val |= 0x20;
+ else
+ val &= ~0x20;
+ switch (via_i2c_chan->i2c_port) {
+ case I2CPORTINDEX:
+ val |= 0x01;
+ break;
+ case GPIOPORTINDEX:
+ val |= 0x80;
+ break;
+ default:
+ DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
+ }
+ viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
+}
+
+static int via_i2c_getscl(void *data)
+{
+ struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+ if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08)
+ return 1;
+ return 0;
+}
+
+static int via_i2c_getsda(void *data)
+{
+ struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+ if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04)
+ return 1;
+ return 0;
+}
+
+static void via_i2c_setsda(void *data, int state)
+{
+ u8 val;
+ struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+ val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
+ if (state)
+ val |= 0x10;
+ else
+ val &= ~0x10;
+ switch (via_i2c_chan->i2c_port) {
+ case I2CPORTINDEX:
+ val |= 0x01;
+ break;
+ case GPIOPORTINDEX:
+ val |= 0x40;
+ break;
+ default:
+ DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
+ }
+ viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
+}
+
+int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
+{
+ u8 mm1[] = {0x00};
+ struct i2c_msg msgs[2];
+
+ *pdata = 0;
+ msgs[0].flags = 0;
+ msgs[1].flags = I2C_M_RD;
+ msgs[0].addr = msgs[1].addr = slave_addr / 2;
+ mm1[0] = index;
+ msgs[0].len = 1; msgs[1].len = 1;
+ msgs[0].buf = mm1; msgs[1].buf = pdata;
+ i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
+
+ return 0;
+}
+
+int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
+{
+ u8 msg[2] = { index, data };
+ struct i2c_msg msgs;
+
+ msgs.flags = 0;
+ msgs.addr = slave_addr / 2;
+ msgs.len = 2;
+ msgs.buf = msg;
+ return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1);
+}
+
+int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
+{
+ u8 mm1[] = {0x00};
+ struct i2c_msg msgs[2];
+
+ msgs[0].flags = 0;
+ msgs[1].flags = I2C_M_RD;
+ msgs[0].addr = msgs[1].addr = slave_addr / 2;
+ mm1[0] = index;
+ msgs[0].len = 1; msgs[1].len = buff_len;
+ msgs[0].buf = mm1; msgs[1].buf = buff;
+ i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
+ return 0;
+}
+
+int viafb_create_i2c_bus(void *viapar)
+{
+ int ret;
+ struct viafb_par *par = (struct viafb_par *)viapar;
+
+ strcpy(par->i2c_stuff.adapter.name, "via_i2c");
+ par->i2c_stuff.i2c_port = 0x0;
+ par->i2c_stuff.adapter.owner = THIS_MODULE;
+ par->i2c_stuff.adapter.id = 0x01FFFF;
+ par->i2c_stuff.adapter.class = 0;
+ par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo;
+ par->i2c_stuff.adapter.dev.parent = NULL;
+ par->i2c_stuff.algo.setsda = via_i2c_setsda;
+ par->i2c_stuff.algo.setscl = via_i2c_setscl;
+ par->i2c_stuff.algo.getsda = via_i2c_getsda;
+ par->i2c_stuff.algo.getscl = via_i2c_getscl;
+ par->i2c_stuff.algo.udelay = 40;
+ par->i2c_stuff.algo.timeout = 20;
+ par->i2c_stuff.algo.data = &par->i2c_stuff;
+
+ i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff);
+
+ /* Raise SCL and SDA */
+ par->i2c_stuff.i2c_port = I2CPORTINDEX;
+ via_i2c_setsda(&par->i2c_stuff, 1);
+ via_i2c_setscl(&par->i2c_stuff, 1);
+
+ par->i2c_stuff.i2c_port = GPIOPORTINDEX;
+ via_i2c_setsda(&par->i2c_stuff, 1);
+ via_i2c_setscl(&par->i2c_stuff, 1);
+ udelay(20);
+
+ ret = i2c_bit_add_bus(&par->i2c_stuff.adapter);
+ if (ret == 0)
+ DEBUG_MSG("I2C bus %s registered.\n",
+ par->i2c_stuff.adapter.name);
+ else
+ DEBUG_MSG("Failed to register I2C bus %s.\n",
+ par->i2c_stuff.adapter.name);
+ return ret;
+}
+
+void viafb_delete_i2c_buss(void *par)
+{
+ i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter);
+}
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h
new file mode 100644
index 00000000000..3a13242a315
--- /dev/null
+++ b/drivers/video/via/via_i2c.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __VIA_I2C_H__
+#define __VIA_I2C_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+struct via_i2c_stuff {
+ u16 i2c_port; /* GPIO or I2C port */
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
+#define I2CPORT 0x3c4
+#define I2CPORTINDEX 0x31
+#define GPIOPORT 0x3C4
+#define GPIOPORTINDEX 0x2C
+#define I2C_BUS 1
+#define GPIO_BUS 2
+#define DELAYPORT 0x3C3
+
+int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata);
+int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
+int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
+int viafb_create_i2c_bus(void *par);
+void viafb_delete_i2c_buss(void *par);
+#endif /* __VIA_I2C_H__ */
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
new file mode 100644
index 00000000000..d53c3d54ed8
--- /dev/null
+++ b/drivers/video/via/via_utility.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+void viafb_get_device_support_state(u32 *support_state)
+{
+ *support_state = CRT_Device;
+
+ if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
+ *support_state |= DVI_Device;
+
+ if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
+ *support_state |= LCD_Device;
+}
+
+void viafb_get_device_connect_state(u32 *connect_state)
+{
+ bool mobile = false;
+
+ *connect_state = CRT_Device;
+
+ if (viafb_dvi_sense())
+ *connect_state |= DVI_Device;
+
+ viafb_lcd_get_mobile_state(&mobile);
+ if (mobile)
+ *connect_state |= LCD_Device;
+}
+
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
+{
+ unsigned int support_state = 0;
+
+ switch (viafb_lcd_panel_id) {
+ case LCD_PANEL_ID0_640X480:
+ if ((xres < 640) && (yres < 480))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID1_800X600:
+ if ((xres < 800) && (yres < 600))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID2_1024X768:
+ if ((xres < 1024) && (yres < 768))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID3_1280X768:
+ if ((xres < 1280) && (yres < 768))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID4_1280X1024:
+ if ((xres < 1280) && (yres < 1024))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID5_1400X1050:
+ if ((xres < 1400) && (yres < 1050))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID6_1600X1200:
+ if ((xres < 1600) && (yres < 1200))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID7_1366X768:
+ if ((xres < 1366) && (yres < 768))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID8_1024X600:
+ if ((xres < 1024) && (yres < 600))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_ID9_1280X800:
+ if ((xres < 1280) && (yres < 800))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_IDA_800X480:
+ if ((xres < 800) && (yres < 480))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_IDB_1360X768:
+ if ((xres < 1360) && (yres < 768))
+ support_state = true;
+ break;
+
+ case LCD_PANEL_IDC_480X640:
+ if ((xres < 480) && (yres < 640))
+ support_state = true;
+ break;
+
+ default:
+ support_state = false;
+ break;
+ }
+
+ return support_state;
+}
+
+/*====================================================================*/
+/* Gamma Function Implementation*/
+/*====================================================================*/
+
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
+{
+ int i, sr1a;
+ int active_device_amount = 0;
+ int device_status = viafb_DeviceStatus;
+
+ for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
+ if (device_status & 1)
+ active_device_amount++;
+ device_status >>= 1;
+ }
+
+ /* 8 bpp mode can't adjust gamma */
+ if (bpp == 8)
+ return ;
+
+ /* Enable Gamma */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+ break;
+ }
+ sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
+ viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+ /* Fill IGA1 Gamma Table */
+ outb(0, LUT_INDEX_WRITE);
+ for (i = 0; i < 256; i++) {
+ outb(gamma_table[i] >> 16, LUT_DATA);
+ outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+ outb(gamma_table[i] & 0xFF, LUT_DATA);
+ }
+
+ /* If adjust Gamma value in SAMM, fill IGA1,
+ IGA2 Gamma table simultanous. */
+ /* Switch to IGA2 Gamma Table */
+ if ((active_device_amount > 1) &&
+ !((viaparinfo->chip_info->gfx_chip_name ==
+ UNICHROME_CLE266) &&
+ (viaparinfo->chip_info->gfx_chip_revision < 15))) {
+ viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+ viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
+
+ /* Fill IGA2 Gamma Table */
+ outb(0, LUT_INDEX_WRITE);
+ for (i = 0; i < 256; i++) {
+ outb(gamma_table[i] >> 16, LUT_DATA);
+ outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+ outb(gamma_table[i] & 0xFF, LUT_DATA);
+ }
+ }
+ viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_table(unsigned int *gamma_table)
+{
+ unsigned char color_r, color_g, color_b;
+ unsigned char sr1a = 0;
+ int i;
+
+ /* Enable Gamma */
+ switch (viaparinfo->chip_info->gfx_chip_name) {
+ case UNICHROME_CLE266:
+ case UNICHROME_K400:
+ viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+ break;
+
+ case UNICHROME_K800:
+ case UNICHROME_PM800:
+ case UNICHROME_CN700:
+ case UNICHROME_CX700:
+ case UNICHROME_K8M890:
+ case UNICHROME_P4M890:
+ case UNICHROME_P4M900:
+ viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+ break;
+ }
+ sr1a = viafb_read_reg(VIASR, SR1A);
+ viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+ /* Reading gamma table to get color value */
+ outb(0, LUT_INDEX_READ);
+ for (i = 0; i < 256; i++) {
+ color_r = inb(LUT_DATA);
+ color_g = inb(LUT_DATA);
+ color_b = inb(LUT_DATA);
+ gamma_table[i] =
+ ((((u32) color_r) << 16) |
+ (((u16) color_g) << 8)) | color_b;
+ }
+ viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
+{
+ if (bpp == 8)
+ *support_state = None_Device;
+ else
+ *support_state = CRT_Device | DVI_Device | LCD_Device;
+}
+
+int viafb_input_parameter_converter(int parameter_value)
+{
+ int result;
+
+ if (parameter_value >= 1 && parameter_value <= 9)
+ result = 1 << (parameter_value - 1);
+ else
+ result = 1;
+
+ return result;
+}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
new file mode 100644
index 00000000000..2fd455202eb
--- /dev/null
+++ b/drivers/video/via/via_utility.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __VIAUTILITY_H__
+#define __VIAUTILITY_H__
+
+/* These functions are used to get infomation about device's state */
+void viafb_get_device_support_state(u32 *support_state);
+void viafb_get_device_connect_state(u32 *connect_state);
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
+
+/* These function are used to access gamma table */
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
+void viafb_get_gamma_table(unsigned int *gamma_table);
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
+int viafb_input_parameter_converter(int parameter_value);
+
+#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
new file mode 100644
index 00000000000..0132eae06f5
--- /dev/null
+++ b/drivers/video/via/viafbdev.c
@@ -0,0 +1,2571 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#define _MASTER_FILE
+
+#include "global.h"
+
+static int MAX_CURS = 32;
+static struct fb_var_screeninfo default_var;
+static char *viafb_name = "Via";
+static u32 pseudo_pal[17];
+
+/* video mode */
+static char *viafb_mode = "640x480";
+static char *viafb_mode1 = "640x480";
+static int viafb_resMode = VIA_RES_640X480;
+
+/* Added for specifying active devices.*/
+char *viafb_active_dev = "";
+
+/* Added for specifying video on devices.*/
+char *viafb_video_dev = "";
+
+/*Added for specify lcd output port*/
+char *viafb_lcd_port = "";
+char *viafb_dvi_port = "";
+
+static void viafb_set_device(struct device_t active_dev);
+static int apply_device_setting(struct viafb_ioctl_setting setting_info,
+ struct fb_info *info);
+static void apply_second_mode_setting(struct fb_var_screeninfo
+ *sec_var);
+static void retrieve_device_setting(struct viafb_ioctl_setting
+ *setting_info);
+static void viafb_set_video_device(u32 video_dev_info);
+static void viafb_get_video_device(u32 *video_dev_info);
+
+/* Mode information */
+static const struct viafb_modeinfo viafb_modentry[] = {
+ {480, 640, VIA_RES_480X640, "480x640"},
+ {640, 480, VIA_RES_640X480, "640x480"},
+ {800, 480, VIA_RES_800X480, "800x480"},
+ {800, 600, VIA_RES_800X600, "800x600"},
+ {1024, 768, VIA_RES_1024X768, "1024x768"},
+ {1152, 864, VIA_RES_1152X864, "1152x864"},
+ {1280, 1024, VIA_RES_1280X1024, "1280x1024"},
+ {1600, 1200, VIA_RES_1600X1200, "1600x1200"},
+ {1440, 1050, VIA_RES_1440X1050, "1440x1050"},
+ {1280, 768, VIA_RES_1280X768, "1280x768"},
+ {1280, 800, VIA_RES_1280X800, "1280x800"},
+ {1280, 960, VIA_RES_1280X960, "1280x960"},
+ {1920, 1440, VIA_RES_1920X1440, "1920x1440"},
+ {848, 480, VIA_RES_848X480, "848x480"},
+ {1400, 1050, VIA_RES_1400X1050, "1400x1050"},
+ {720, 480, VIA_RES_720X480, "720x480"},
+ {720, 576, VIA_RES_720X576, "720x576"},
+ {1024, 512, VIA_RES_1024X512, "1024x512"},
+ {1024, 576, VIA_RES_1024X576, "1024x576"},
+ {1024, 600, VIA_RES_1024X600, "1024x600"},
+ {1280, 720, VIA_RES_1280X720, "1280x720"},
+ {1920, 1080, VIA_RES_1920X1080, "1920x1080"},
+ {1366, 768, VIA_RES_1368X768, "1368x768"},
+ {1680, 1050, VIA_RES_1680X1050, "1680x1050"},
+ {960, 600, VIA_RES_960X600, "960x600"},
+ {1000, 600, VIA_RES_1000X600, "1000x600"},
+ {1024, 576, VIA_RES_1024X576, "1024x576"},
+ {1024, 600, VIA_RES_1024X600, "1024x600"},
+ {1088, 612, VIA_RES_1088X612, "1088x612"},
+ {1152, 720, VIA_RES_1152X720, "1152x720"},
+ {1200, 720, VIA_RES_1200X720, "1200x720"},
+ {1280, 600, VIA_RES_1280X600, "1280x600"},
+ {1360, 768, VIA_RES_1360X768, "1360x768"},
+ {1440, 900, VIA_RES_1440X900, "1440x900"},
+ {1600, 900, VIA_RES_1600X900, "1600x900"},
+ {1600, 1024, VIA_RES_1600X1024, "1600x1024"},
+ {1792, 1344, VIA_RES_1792X1344, "1792x1344"},
+ {1856, 1392, VIA_RES_1856X1392, "1856x1392"},
+ {1920, 1200, VIA_RES_1920X1200, "1920x1200"},
+ {2048, 1536, VIA_RES_2048X1536, "2048x1536"},
+ {0, 0, VIA_RES_INVALID, "640x480"}
+};
+
+static struct fb_ops viafb_ops;
+
+static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+ struct viafb_par *ppar;
+ ppar = info->par;
+
+ DEBUG_MSG(KERN_INFO "viafb_update_fix!\n");
+
+ fix->visual =
+ ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+ fix->line_length = ppar->linelength;
+
+ return 0;
+}
+
+
+static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
+ struct viafb_par *viaparinfo)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, viafb_name);
+
+ fix->smem_start = viaparinfo->fbmem;
+ fix->smem_len = viaparinfo->fbmem_free;
+ fix->mmio_start = viaparinfo->mmio_base;
+ fix->mmio_len = viaparinfo->mmio_len;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+
+ fix->xpanstep = fix->ywrapstep = 0;
+ fix->ypanstep = 1;
+
+ /* Just tell the accel name */
+ viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
+}
+static int viafb_open(struct fb_info *info, int user)
+{
+ DEBUG_MSG(KERN_INFO "viafb_open!\n");
+ return 0;
+}
+
+static int viafb_release(struct fb_info *info, int user)
+{
+ DEBUG_MSG(KERN_INFO "viafb_release!\n");
+ return 0;
+}
+
+static void viafb_update_viafb_par(struct fb_info *info)
+{
+ struct viafb_par *ppar;
+
+ ppar = info->par;
+ ppar->bpp = info->var.bits_per_pixel;
+ ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8;
+ ppar->hres = info->var.xres;
+ ppar->vres = info->var.yres;
+ ppar->xoffset = info->var.xoffset;
+ ppar->yoffset = info->var.yoffset;
+}
+
+static int viafb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int vmode_index, htotal, vtotal;
+ struct viafb_par *ppar;
+ u32 long_refresh;
+ struct viafb_par *p_viafb_par;
+ ppar = info->par;
+
+
+ DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
+ /* Sanity check */
+ /* HW neither support interlacte nor double-scaned mode */
+ if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
+ return -EINVAL;
+
+ vmode_index = viafb_get_mode_index(var->xres, var->yres, 0);
+ if (vmode_index == VIA_RES_INVALID) {
+ DEBUG_MSG(KERN_INFO
+ "viafb: Mode %dx%dx%d not supported!!\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ if (24 == var->bits_per_pixel)
+ var->bits_per_pixel = 32;
+
+ if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
+ var->bits_per_pixel != 32)
+ return -EINVAL;
+
+ if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
+ /*32 pixel alignment */
+ var->xres_virtual = (var->xres_virtual + 31) & ~31;
+ if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+ ppar->memsize)
+ return -EINVAL;
+
+ /* Based on var passed in to calculate the refresh,
+ * because our driver use some modes special.
+ */
+ htotal = var->xres + var->left_margin +
+ var->right_margin + var->hsync_len;
+ vtotal = var->yres + var->upper_margin +
+ var->lower_margin + var->vsync_len;
+ long_refresh = 1000000000UL / var->pixclock * 1000;
+ long_refresh /= (htotal * vtotal);
+
+ viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
+
+ /* Adjust var according to our driver's own table */
+ viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
+
+ /* This is indeed a patch for VT3353 */
+ if (!info->par)
+ return -1;
+ p_viafb_par = (struct viafb_par *)info->par;
+ if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
+ var->accel_flags = 0;
+
+ return 0;
+}
+
+static int viafb_set_par(struct fb_info *info)
+{
+ int vmode_index;
+ int vmode_index1 = 0;
+ DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
+
+ viafb_update_device_setting(info->var.xres, info->var.yres,
+ info->var.bits_per_pixel, viafb_refresh, 0);
+
+ vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0);
+
+ if (viafb_SAMM_ON == 1) {
+ DEBUG_MSG(KERN_INFO
+ "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
+ viafb_second_xres, viafb_second_yres, viafb_bpp1);
+ vmode_index1 = viafb_get_mode_index(viafb_second_xres,
+ viafb_second_yres, 1);
+ DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
+ vmode_index1);
+
+ viafb_update_device_setting(viafb_second_xres,
+ viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
+ }
+
+ if (vmode_index != VIA_RES_INVALID) {
+ viafb_setmode(vmode_index, info->var.xres, info->var.yres,
+ info->var.bits_per_pixel, vmode_index1,
+ viafb_second_xres, viafb_second_yres, viafb_bpp1);
+
+ /*We should set memory offset according virtual_x */
+ /*Fix me:put this function into viafb_setmode */
+ viafb_memory_pitch_patch(info);
+
+ /* Update ***fb_par information */
+ viafb_update_viafb_par(info);
+
+ /* Update other fixed information */
+ viafb_update_fix(&info->fix, info);
+ viafb_bpp = info->var.bits_per_pixel;
+ /* Update viafb_accel, it is necessary to our 2D accelerate */
+ viafb_accel = info->var.accel_flags;
+
+ if (viafb_accel)
+ viafb_set_2d_color_depth(info->var.bits_per_pixel);
+ }
+
+ return 0;
+}
+
+/* Set one color register */
+static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+unsigned blue, unsigned transp, struct fb_info *info)
+{
+ u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
+ unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
+ DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
+ if (regno >= cmap_entries)
+ return 1;
+ if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
+ /*
+ * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
+ */
+ outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
+ rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
+ }
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ outb(0x1A, 0x3C4);
+ sr1a = inb(0x3C5);
+ outb(0x1B, 0x3C4);
+ sr1b = inb(0x3C5);
+ outb(0x67, 0x3D4);
+ cr67 = inb(0x3D5);
+ outb(0x6A, 0x3D4);
+ cr6a = inb(0x3D5);
+
+ /* Map the 3C6/7/8/9 to the IGA2 */
+ outb(0x1A, 0x3C4);
+ outb(sr1a | 0x01, 0x3C5);
+ /* Second Display Engine colck always on */
+ outb(0x1B, 0x3C4);
+ outb(sr1b | 0x80, 0x3C5);
+ /* Second Display Color Depth 8 */
+ outb(0x67, 0x3D4);
+ outb(cr67 & 0x3F, 0x3D5);
+ outb(0x6A, 0x3D4);
+ /* Second Display Channel Reset CR6A[6]) */
+ outb(cr6a & 0xBF, 0x3D5);
+ /* Second Display Channel Enable CR6A[7] */
+ outb(cr6a | 0x80, 0x3D5);
+ /* Second Display Channel stop reset) */
+ outb(cr6a | 0x40, 0x3D5);
+
+ /* Bit mask of palette */
+ outb(0xFF, 0x3c6);
+ /* Write one register of IGA2 */
+ outb(regno, 0x3C8);
+ if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
+ rev >= 15) {
+ shift = 8;
+ viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
+ viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
+ } else {
+ shift = 10;
+ viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
+ viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
+ }
+ outb(red >> shift, 0x3C9);
+ outb(green >> shift, 0x3C9);
+ outb(blue >> shift, 0x3C9);
+
+ /* Map the 3C6/7/8/9 to the IGA1 */
+ outb(0x1A, 0x3C4);
+ outb(sr1a & 0xFE, 0x3C5);
+ /* Bit mask of palette */
+ outb(0xFF, 0x3c6);
+ /* Write one register of IGA1 */
+ outb(regno, 0x3C8);
+ outb(red >> shift, 0x3C9);
+ outb(green >> shift, 0x3C9);
+ outb(blue >> shift, 0x3C9);
+
+ outb(0x1A, 0x3C4);
+ outb(sr1a, 0x3C5);
+ outb(0x1B, 0x3C4);
+ outb(sr1b, 0x3C5);
+ outb(0x67, 0x3D4);
+ outb(cr67, 0x3D5);
+ outb(0x6A, 0x3D4);
+ outb(cr6a, 0x3D5);
+ break;
+ case 16:
+ ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
+ ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+ break;
+ case 32:
+ ((u32 *) info->pseudo_palette)[regno] =
+ ((transp & 0xFF00) << 16) |
+ ((red & 0xFF00) << 8) |
+ ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+ break;
+ }
+
+ return 0;
+
+}
+
+/*CALLED BY: fb_set_cmap */
+/* fb_set_var, pass 256 colors */
+/*CALLED BY: fb_set_cmap */
+/* fbcon_set_palette, pass 16 colors */
+static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ u32 len = cmap->len;
+ u32 i;
+ u16 *pred = cmap->red;
+ u16 *pgreen = cmap->green;
+ u16 *pblue = cmap->blue;
+ u16 *ptransp = cmap->transp;
+ u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
+ if (len > 256)
+ return 1;
+ if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
+ /*
+ * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
+ * rev.
+ */
+ outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
+ rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
+ }
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ outb(0x1A, 0x3C4);
+ sr1a = inb(0x3C5);
+ outb(0x1B, 0x3C4);
+ sr1b = inb(0x3C5);
+ outb(0x67, 0x3D4);
+ cr67 = inb(0x3D5);
+ outb(0x6A, 0x3D4);
+ cr6a = inb(0x3D5);
+ /* Map the 3C6/7/8/9 to the IGA2 */
+ outb(0x1A, 0x3C4);
+ outb(sr1a | 0x01, 0x3C5);
+ outb(0x1B, 0x3C4);
+ /* Second Display Engine colck always on */
+ outb(sr1b | 0x80, 0x3C5);
+ outb(0x67, 0x3D4);
+ /* Second Display Color Depth 8 */
+ outb(cr67 & 0x3F, 0x3D5);
+ outb(0x6A, 0x3D4);
+ /* Second Display Channel Reset CR6A[6]) */
+ outb(cr6a & 0xBF, 0x3D5);
+ /* Second Display Channel Enable CR6A[7] */
+ outb(cr6a | 0x80, 0x3D5);
+ /* Second Display Channel stop reset) */
+ outb(cr6a | 0xC0, 0x3D5);
+
+ /* Bit mask of palette */
+ outb(0xFF, 0x3c6);
+ outb(0x00, 0x3C8);
+ if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
+ rev >= 15) {
+ shift = 8;
+ viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
+ viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
+ } else {
+ shift = 10;
+ viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
+ viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
+ }
+ for (i = 0; i < len; i++) {
+ outb((*(pred + i)) >> shift, 0x3C9);
+ outb((*(pgreen + i)) >> shift, 0x3C9);
+ outb((*(pblue + i)) >> shift, 0x3C9);
+ }
+
+ outb(0x1A, 0x3C4);
+ /* Map the 3C6/7/8/9 to the IGA1 */
+ outb(sr1a & 0xFE, 0x3C5);
+ /* Bit mask of palette */
+ outb(0xFF, 0x3c6);
+ outb(0x00, 0x3C8);
+ for (i = 0; i < len; i++) {
+ outb((*(pred + i)) >> shift, 0x3C9);
+ outb((*(pgreen + i)) >> shift, 0x3C9);
+ outb((*(pblue + i)) >> shift, 0x3C9);
+ }
+
+ outb(0x1A, 0x3C4);
+ outb(sr1a, 0x3C5);
+ outb(0x1B, 0x3C4);
+ outb(sr1b, 0x3C5);
+ outb(0x67, 0x3D4);
+ outb(cr67, 0x3D5);
+ outb(0x6A, 0x3D4);
+ outb(cr6a, 0x3D5);
+ break;
+ case 16:
+ if (len > 17)
+ return 0; /* Because static u32 pseudo_pal[17]; */
+ for (i = 0; i < len; i++)
+ ((u32 *) info->pseudo_palette)[i] =
+ (*(pred + i) & 0xF800) |
+ ((*(pgreen + i) & 0xFC00) >> 5) |
+ ((*(pblue + i) & 0xF800) >> 11);
+ break;
+ case 32:
+ if (len > 17)
+ return 0;
+ if (ptransp) {
+ for (i = 0; i < len; i++)
+ ((u32 *) info->pseudo_palette)[i] =
+ ((*(ptransp + i) & 0xFF00) << 16) |
+ ((*(pred + i) & 0xFF00) << 8) |
+ ((*(pgreen + i) & 0xFF00)) |
+ ((*(pblue + i) & 0xFF00) >> 8);
+ } else {
+ for (i = 0; i < len; i++)
+ ((u32 *) info->pseudo_palette)[i] =
+ 0x00000000 |
+ ((*(pred + i) & 0xFF00) << 8) |
+ ((*(pgreen + i) & 0xFF00)) |
+ ((*(pblue + i) & 0xFF00) >> 8);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int viafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ unsigned int offset;
+
+ DEBUG_MSG(KERN_INFO "viafb_pan_display!\n");
+
+ offset = (var->xoffset + (var->yoffset * var->xres_virtual)) *
+ var->bits_per_pixel / 16;
+
+ DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
+
+ viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3);
+ viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff);
+ viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff);
+ viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff);
+
+ return 0;
+}
+
+static int viafb_blank(int blank_mode, struct fb_info *info)
+{
+ DEBUG_MSG(KERN_INFO "viafb_blank!\n");
+ /* clear DPMS setting */
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ /* Screen: On, HSync: On, VSync: On */
+ /* control CRT monitor power management */
+ viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ /* Screen: Off, HSync: Off, VSync: On */
+ /* control CRT monitor power management */
+ viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ /* Screen: Off, HSync: On, VSync: Off */
+ /* control CRT monitor power management */
+ viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
+ break;
+ case FB_BLANK_POWERDOWN:
+ /* Screen: Off, HSync: Off, VSync: Off */
+ /* control CRT monitor power management */
+ viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
+ break;
+ }
+
+ return 0;
+}
+
+static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+ struct viafb_ioctl_mode viamode;
+ struct viafb_ioctl_samm viasamm;
+ struct viafb_driver_version driver_version;
+ struct fb_var_screeninfo sec_var;
+ struct _panel_size_pos_info panel_pos_size_para;
+ u32 state_info = 0;
+ u32 viainfo_size = sizeof(struct viafb_ioctl_info);
+ u32 *viafb_gamma_table;
+ char driver_name[] = "viafb";
+
+ u32 __user *argp = (u32 __user *) arg;
+ u32 gpu32;
+ u32 video_dev_info = 0;
+ struct viafb_ioctl_setting viafb_setting = {};
+ struct device_t active_dev = {};
+
+ DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
+
+ switch (cmd) {
+ case VIAFB_GET_CHIP_INFO:
+ if (copy_to_user(argp, viaparinfo->chip_info,
+ sizeof(struct chip_information)))
+ return -EFAULT;
+ break;
+ case VIAFB_GET_INFO_SIZE:
+ return put_user(viainfo_size, argp);
+ case VIAFB_GET_INFO:
+ return viafb_ioctl_get_viafb_info(arg);
+ case VIAFB_HOTPLUG:
+ return put_user(viafb_ioctl_hotplug(info->var.xres,
+ info->var.yres,
+ info->var.bits_per_pixel), argp);
+ case VIAFB_SET_HOTPLUG_FLAG:
+ if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+ return -EFAULT;
+ viafb_hotplug = (gpu32) ? 1 : 0;
+ break;
+ case VIAFB_GET_RESOLUTION:
+ viamode.xres = (u32) viafb_hotplug_Xres;
+ viamode.yres = (u32) viafb_hotplug_Yres;
+ viamode.refresh = (u32) viafb_hotplug_refresh;
+ viamode.bpp = (u32) viafb_hotplug_bpp;
+ if (viafb_SAMM_ON == 1) {
+ viamode.xres_sec = viafb_second_xres;
+ viamode.yres_sec = viafb_second_yres;
+ viamode.virtual_xres_sec = viafb_second_virtual_xres;
+ viamode.virtual_yres_sec = viafb_second_virtual_yres;
+ viamode.refresh_sec = viafb_refresh1;
+ viamode.bpp_sec = viafb_bpp1;
+ } else {
+ viamode.xres_sec = 0;
+ viamode.yres_sec = 0;
+ viamode.virtual_xres_sec = 0;
+ viamode.virtual_yres_sec = 0;
+ viamode.refresh_sec = 0;
+ viamode.bpp_sec = 0;
+ }
+ if (copy_to_user(argp, &viamode, sizeof(viamode)))
+ return -EFAULT;
+ break;
+ case VIAFB_GET_SAMM_INFO:
+ viasamm.samm_status = viafb_SAMM_ON;
+
+ if (viafb_SAMM_ON == 1) {
+ if (viafb_dual_fb) {
+ viasamm.size_prim = viaparinfo->fbmem_free;
+ viasamm.size_sec = viaparinfo1->fbmem_free;
+ } else {
+ if (viafb_second_size) {
+ viasamm.size_prim =
+ viaparinfo->fbmem_free -
+ viafb_second_size * 1024 * 1024;
+ viasamm.size_sec =
+ viafb_second_size * 1024 * 1024;
+ } else {
+ viasamm.size_prim =
+ viaparinfo->fbmem_free >> 1;
+ viasamm.size_sec =
+ (viaparinfo->fbmem_free >> 1);
+ }
+ }
+ viasamm.mem_base = viaparinfo->fbmem;
+ viasamm.offset_sec = viafb_second_offset;
+ } else {
+ viasamm.size_prim =
+ viaparinfo->memsize - viaparinfo->fbmem_used;
+ viasamm.size_sec = 0;
+ viasamm.mem_base = viaparinfo->fbmem;
+ viasamm.offset_sec = 0;
+ }
+
+ if (copy_to_user(argp, &viasamm, sizeof(viasamm)))
+ return -EFAULT;
+
+ break;
+ case VIAFB_TURN_ON_OUTPUT_DEVICE:
+ if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+ return -EFAULT;
+ if (gpu32 & CRT_Device)
+ viafb_crt_enable();
+ if (gpu32 & DVI_Device)
+ viafb_dvi_enable();
+ if (gpu32 & LCD_Device)
+ viafb_lcd_enable();
+ break;
+ case VIAFB_TURN_OFF_OUTPUT_DEVICE:
+ if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+ return -EFAULT;
+ if (gpu32 & CRT_Device)
+ viafb_crt_disable();
+ if (gpu32 & DVI_Device)
+ viafb_dvi_disable();
+ if (gpu32 & LCD_Device)
+ viafb_lcd_disable();
+ break;
+ case VIAFB_SET_DEVICE:
+ if (copy_from_user(&active_dev, (void *)argp,
+ sizeof(active_dev)))
+ return -EFAULT;
+ viafb_set_device(active_dev);
+ viafb_set_par(info);
+ break;
+ case VIAFB_GET_DEVICE:
+ active_dev.crt = viafb_CRT_ON;
+ active_dev.dvi = viafb_DVI_ON;
+ active_dev.lcd = viafb_LCD_ON;
+ active_dev.samm = viafb_SAMM_ON;
+ active_dev.primary_dev = viafb_primary_dev;
+
+ active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
+ active_dev.lcd_panel_id = viafb_lcd_panel_id;
+ active_dev.lcd_mode = viafb_lcd_mode;
+
+ active_dev.xres = viafb_hotplug_Xres;
+ active_dev.yres = viafb_hotplug_Yres;
+
+ active_dev.xres1 = viafb_second_xres;
+ active_dev.yres1 = viafb_second_yres;
+
+ active_dev.bpp = viafb_bpp;
+ active_dev.bpp1 = viafb_bpp1;
+ active_dev.refresh = viafb_refresh;
+ active_dev.refresh1 = viafb_refresh1;
+
+ active_dev.epia_dvi = viafb_platform_epia_dvi;
+ active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
+ active_dev.bus_width = viafb_bus_width;
+
+ if (copy_to_user(argp, &active_dev, sizeof(active_dev)))
+ return -EFAULT;
+ break;
+
+ case VIAFB_GET_DRIVER_VERSION:
+ driver_version.iMajorNum = VERSION_MAJOR;
+ driver_version.iKernelNum = VERSION_KERNEL;
+ driver_version.iOSNum = VERSION_OS;
+ driver_version.iMinorNum = VERSION_MINOR;
+
+ if (copy_to_user(argp, &driver_version,
+ sizeof(driver_version)))
+ return -EFAULT;
+
+ break;
+
+ case VIAFB_SET_DEVICE_INFO:
+ if (copy_from_user(&viafb_setting,
+ argp, sizeof(viafb_setting)))
+ return -EFAULT;
+ if (apply_device_setting(viafb_setting, info) < 0)
+ return -EINVAL;
+
+ break;
+
+ case VIAFB_SET_SECOND_MODE:
+ if (copy_from_user(&sec_var, argp, sizeof(sec_var)))
+ return -EFAULT;
+ apply_second_mode_setting(&sec_var);
+ break;
+
+ case VIAFB_GET_DEVICE_INFO:
+
+ retrieve_device_setting(&viafb_setting);
+
+ if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting)))
+ return -EFAULT;
+
+ break;
+
+ case VIAFB_GET_DEVICE_SUPPORT:
+ viafb_get_device_support_state(&state_info);
+ if (put_user(state_info, argp))
+ return -EFAULT;
+ break;
+
+ case VIAFB_GET_DEVICE_CONNECT:
+ viafb_get_device_connect_state(&state_info);
+ if (put_user(state_info, argp))
+ return -EFAULT;
+ break;
+
+ case VIAFB_GET_PANEL_SUPPORT_EXPAND:
+ state_info =
+ viafb_lcd_get_support_expand_state(info->var.xres,
+ info->var.yres);
+ if (put_user(state_info, argp))
+ return -EFAULT;
+ break;
+
+ case VIAFB_GET_DRIVER_NAME:
+ if (copy_to_user(argp, driver_name, sizeof(driver_name)))
+ return -EFAULT;
+ break;
+
+ case VIAFB_SET_GAMMA_LUT:
+ viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+ if (!viafb_gamma_table)
+ return -ENOMEM;
+ if (copy_from_user(viafb_gamma_table, argp,
+ sizeof(viafb_gamma_table))) {
+ kfree(viafb_gamma_table);
+ return -EFAULT;
+ }
+ viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
+ kfree(viafb_gamma_table);
+ break;
+
+ case VIAFB_GET_GAMMA_LUT:
+ viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+ if (!viafb_gamma_table)
+ return -ENOMEM;
+ viafb_get_gamma_table(viafb_gamma_table);
+ if (copy_to_user(argp, viafb_gamma_table,
+ sizeof(viafb_gamma_table))) {
+ kfree(viafb_gamma_table);
+ return -EFAULT;
+ }
+ kfree(viafb_gamma_table);
+ break;
+
+ case VIAFB_GET_GAMMA_SUPPORT_STATE:
+ viafb_get_gamma_support_state(viafb_bpp, &state_info);
+ if (put_user(state_info, argp))
+ return -EFAULT;
+ break;
+ case VIAFB_SET_VIDEO_DEVICE:
+ get_user(video_dev_info, argp);
+ viafb_set_video_device(video_dev_info);
+ break;
+ case VIAFB_GET_VIDEO_DEVICE:
+ viafb_get_video_device(&video_dev_info);
+ if (put_user(video_dev_info, argp))
+ return -EFAULT;
+ break;
+ case VIAFB_SYNC_SURFACE:
+ DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
+ break;
+ case VIAFB_GET_DRIVER_CAPS:
+ break;
+
+ case VIAFB_GET_PANEL_MAX_SIZE:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ panel_pos_size_para.x = panel_pos_size_para.y = 0;
+ if (copy_to_user(argp, &panel_pos_size_para,
+ sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+ case VIAFB_GET_PANEL_MAX_POSITION:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ panel_pos_size_para.x = panel_pos_size_para.y = 0;
+ if (copy_to_user(argp, &panel_pos_size_para,
+ sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+
+ case VIAFB_GET_PANEL_POSITION:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ panel_pos_size_para.x = panel_pos_size_para.y = 0;
+ if (copy_to_user(argp, &panel_pos_size_para,
+ sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+ case VIAFB_GET_PANEL_SIZE:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ panel_pos_size_para.x = panel_pos_size_para.y = 0;
+ if (copy_to_user(argp, &panel_pos_size_para,
+ sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+
+ case VIAFB_SET_PANEL_POSITION:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+ case VIAFB_SET_PANEL_SIZE:
+ if (copy_from_user
+ (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+ return -EFAULT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void viafb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ u32 col = 0, rop = 0;
+ int pitch;
+
+ if (!viafb_accel)
+ return cfb_fillrect(info, rect);
+
+ if (!rect->width || !rect->height)
+ return;
+
+ switch (rect->rop) {
+ case ROP_XOR:
+ rop = 0x5A;
+ break;
+ case ROP_COPY:
+ default:
+ rop = 0xF0;
+ break;
+ }
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ col = rect->color;
+ break;
+ case 16:
+ col = ((u32 *) (info->pseudo_palette))[rect->color];
+ break;
+ case 32:
+ col = ((u32 *) (info->pseudo_palette))[rect->color];
+ break;
+ }
+
+ /* BitBlt Source Address */
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+ /* Source Base Address */
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+ /* Destination Base Address */
+ writel(((unsigned long) (info->screen_base) -
+ (unsigned long) viafb_FB_MM) >> 3,
+ viaparinfo->io_virt + VIA_REG_DSTBASE);
+ /* Pitch */
+ pitch = (info->var.xres_virtual + 7) & ~7;
+ writel(VIA_PITCH_ENABLE |
+ (((pitch *
+ info->var.bits_per_pixel >> 3) >> 3) |
+ (((pitch * info->
+ var.bits_per_pixel >> 3) >> 3) << 16)),
+ viaparinfo->io_virt + VIA_REG_PITCH);
+ /* BitBlt Destination Address */
+ writel(((rect->dy << 16) | rect->dx),
+ viaparinfo->io_virt + VIA_REG_DSTPOS);
+ /* Dimension: width & height */
+ writel((((rect->height - 1) << 16) | (rect->width - 1)),
+ viaparinfo->io_virt + VIA_REG_DIMENSION);
+ /* Forground color or Destination color */
+ writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+ /* GE Command */
+ writel((0x01 | 0x2000 | (rop << 24)),
+ viaparinfo->io_virt + VIA_REG_GECMD);
+
+}
+
+static void viafb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ u32 dy = area->dy, sy = area->sy, direction = 0x0;
+ u32 sx = area->sx, dx = area->dx, width = area->width;
+ int pitch;
+
+ DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n");
+
+ if (!viafb_accel)
+ return cfb_copyarea(info, area);
+
+ if (!area->width || !area->height)
+ return;
+
+ if (sy < dy) {
+ dy += area->height - 1;
+ sy += area->height - 1;
+ direction |= 0x4000;
+ }
+
+ if (sx < dx) {
+ dx += width - 1;
+ sx += width - 1;
+ direction |= 0x8000;
+ }
+
+ /* Source Base Address */
+ writel(((unsigned long) (info->screen_base) -
+ (unsigned long) viafb_FB_MM) >> 3,
+ viaparinfo->io_virt + VIA_REG_SRCBASE);
+ /* Destination Base Address */
+ writel(((unsigned long) (info->screen_base) -
+ (unsigned long) viafb_FB_MM) >> 3,
+ viaparinfo->io_virt + VIA_REG_DSTBASE);
+ /* Pitch */
+ pitch = (info->var.xres_virtual + 7) & ~7;
+ /* VIA_PITCH_ENABLE can be omitted now. */
+ writel(VIA_PITCH_ENABLE |
+ (((pitch *
+ info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
+ info->var.
+ bits_per_pixel
+ >> 3) >> 3)
+ << 16)),
+ viaparinfo->io_virt + VIA_REG_PITCH);
+ /* BitBlt Source Address */
+ writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
+ /* BitBlt Destination Address */
+ writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
+ /* Dimension: width & height */
+ writel((((area->height - 1) << 16) | (area->width - 1)),
+ viaparinfo->io_virt + VIA_REG_DIMENSION);
+ /* GE Command */
+ writel((0x01 | direction | (0xCC << 24)),
+ viaparinfo->io_virt + VIA_REG_GECMD);
+
+}
+
+static void viafb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ u32 size, bg_col = 0, fg_col = 0, *udata;
+ int i;
+ int pitch;
+
+ if (!viafb_accel)
+ return cfb_imageblit(info, image);
+
+ udata = (u32 *) image->data;
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ bg_col = image->bg_color;
+ fg_col = image->fg_color;
+ break;
+ case 16:
+ bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
+ fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
+ break;
+ case 32:
+ bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
+ fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
+ break;
+ }
+ size = image->width * image->height;
+
+ /* Source Base Address */
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+ /* Destination Base Address */
+ writel(((unsigned long) (info->screen_base) -
+ (unsigned long) viafb_FB_MM) >> 3,
+ viaparinfo->io_virt + VIA_REG_DSTBASE);
+ /* Pitch */
+ pitch = (info->var.xres_virtual + 7) & ~7;
+ writel(VIA_PITCH_ENABLE |
+ (((pitch *
+ info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
+ info->var.
+ bits_per_pixel
+ >> 3) >> 3)
+ << 16)),
+ viaparinfo->io_virt + VIA_REG_PITCH);
+ /* BitBlt Source Address */
+ writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+ /* BitBlt Destination Address */
+ writel(((image->dy << 16) | image->dx),
+ viaparinfo->io_virt + VIA_REG_DSTPOS);
+ /* Dimension: width & height */
+ writel((((image->height - 1) << 16) | (image->width - 1)),
+ viaparinfo->io_virt + VIA_REG_DIMENSION);
+ /* fb color */
+ writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+ /* bg color */
+ writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
+ /* GE Command */
+ writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
+
+ for (i = 0; i < size / 4; i++) {
+ writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
+ udata++;
+ }
+
+}
+
+static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ u8 data[CURSOR_SIZE / 8];
+ u32 data_bak[CURSOR_SIZE / 32];
+ u32 temp, xx, yy, bg_col = 0, fg_col = 0;
+ int size, i, j = 0;
+ static int hw_cursor;
+ struct viafb_par *p_viafb_par;
+
+ if (viafb_accel)
+ hw_cursor = 1;
+
+ if (!viafb_accel) {
+ if (hw_cursor) {
+ viafb_show_hw_cursor(info, HW_Cursor_OFF);
+ hw_cursor = 0;
+ }
+ return -ENODEV;
+ }
+
+ if ((((struct viafb_par *)(info->par))->iga_path == IGA2)
+ && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
+ return -ENODEV;
+
+ /* When duoview and using lcd , use soft cursor */
+ if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview)
+ return -ENODEV;
+
+ viafb_show_hw_cursor(info, HW_Cursor_OFF);
+ viacursor = *cursor;
+
+ if (cursor->set & FB_CUR_SETHOT) {
+ viacursor.hot = cursor->hot;
+ temp = ((viacursor.hot.x) << 16) + viacursor.hot.y;
+ writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
+ }
+
+ if (cursor->set & FB_CUR_SETPOS) {
+ viacursor.image.dx = cursor->image.dx;
+ viacursor.image.dy = cursor->image.dy;
+ yy = cursor->image.dy - info->var.yoffset;
+ xx = cursor->image.dx - info->var.xoffset;
+ temp = yy & 0xFFFF;
+ temp |= (xx << 16);
+ writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
+ }
+
+ if (cursor->set & FB_CUR_SETSIZE) {
+ temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+
+ if ((cursor->image.width <= 32)
+ && (cursor->image.height <= 32)) {
+ MAX_CURS = 32;
+ temp |= 0x2;
+ } else if ((cursor->image.width <= 64)
+ && (cursor->image.height <= 64)) {
+ MAX_CURS = 64;
+ temp &= 0xFFFFFFFD;
+ } else {
+ DEBUG_MSG(KERN_INFO
+ "The cursor image is biger than 64x64 bits...\n");
+ return -ENXIO;
+ }
+ writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+
+ viacursor.image.height = cursor->image.height;
+ viacursor.image.width = cursor->image.width;
+ }
+
+ if (cursor->set & FB_CUR_SETCMAP) {
+ viacursor.image.fg_color = cursor->image.fg_color;
+ viacursor.image.bg_color = cursor->image.bg_color;
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ case 16:
+ case 32:
+ bg_col =
+ (0xFF << 24) |
+ (((info->cmap.red)[viacursor.image.bg_color] &
+ 0xFF00) << 8) |
+ ((info->cmap.green)[viacursor.image.bg_color] &
+ 0xFF00) |
+ (((info->cmap.blue)[viacursor.image.bg_color] &
+ 0xFF00) >> 8);
+ fg_col =
+ (0xFF << 24) |
+ (((info->cmap.red)[viacursor.image.fg_color] &
+ 0xFF00) << 8) |
+ ((info->cmap.green)[viacursor.image.fg_color] &
+ 0xFF00) |
+ (((info->cmap.blue)[viacursor.image.fg_color] &
+ 0xFF00) >> 8);
+ break;
+ default:
+ return 0;
+ }
+
+ /* This is indeed a patch for VT3324/VT3353 */
+ if (!info->par)
+ return 0;
+ p_viafb_par = (struct viafb_par *)info->par;
+
+ if ((p_viafb_par->chip_info->gfx_chip_name ==
+ UNICHROME_CX700) ||
+ ((p_viafb_par->chip_info->gfx_chip_name ==
+ UNICHROME_VX800))) {
+ bg_col =
+ (((info->cmap.red)[viacursor.image.bg_color] &
+ 0xFFC0) << 14) |
+ (((info->cmap.green)[viacursor.image.bg_color] &
+ 0xFFC0) << 4) |
+ (((info->cmap.blue)[viacursor.image.bg_color] &
+ 0xFFC0) >> 6);
+ fg_col =
+ (((info->cmap.red)[viacursor.image.fg_color] &
+ 0xFFC0) << 14) |
+ (((info->cmap.green)[viacursor.image.fg_color] &
+ 0xFFC0) << 4) |
+ (((info->cmap.blue)[viacursor.image.fg_color] &
+ 0xFFC0) >> 6);
+ }
+
+ writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
+ writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
+ }
+
+ if (cursor->set & FB_CUR_SETSHAPE) {
+ size =
+ ((viacursor.image.width + 7) >> 3) *
+ viacursor.image.height;
+
+ if (MAX_CURS == 32) {
+ for (i = 0; i < (CURSOR_SIZE / 32); i++) {
+ data_bak[i] = 0x0;
+ data_bak[i + 1] = 0xFFFFFFFF;
+ i += 1;
+ }
+ } else if (MAX_CURS == 64) {
+ for (i = 0; i < (CURSOR_SIZE / 32); i++) {
+ data_bak[i] = 0x0;
+ data_bak[i + 1] = 0x0;
+ data_bak[i + 2] = 0xFFFFFFFF;
+ data_bak[i + 3] = 0xFFFFFFFF;
+ i += 3;
+ }
+ }
+
+ switch (viacursor.rop) {
+ case ROP_XOR:
+ for (i = 0; i < size; i++)
+ data[i] = viacursor.mask[i];
+ break;
+ case ROP_COPY:
+
+ for (i = 0; i < size; i++)
+ data[i] = viacursor.mask[i];
+ break;
+ default:
+ break;
+ }
+
+ if (MAX_CURS == 32) {
+ for (i = 0; i < size; i++) {
+ data_bak[j] = (u32) data[i];
+ data_bak[j + 1] = ~data_bak[j];
+ j += 2;
+ }
+ } else if (MAX_CURS == 64) {
+ for (i = 0; i < size; i++) {
+ data_bak[j] = (u32) data[i];
+ data_bak[j + 1] = 0x0;
+ data_bak[j + 2] = ~data_bak[j];
+ data_bak[j + 3] = ~data_bak[j + 1];
+ j += 4;
+ }
+ }
+
+ memcpy(((struct viafb_par *)(info->par))->fbmem_virt +
+ ((struct viafb_par *)(info->par))->cursor_start,
+ data_bak, CURSOR_SIZE);
+ }
+
+ if (viacursor.enable)
+ viafb_show_hw_cursor(info, HW_Cursor_ON);
+
+ return 0;
+}
+
+static int viafb_sync(struct fb_info *info)
+{
+ if (viafb_accel)
+ viafb_wait_engine_idle();
+ return 0;
+}
+
+int viafb_get_mode_index(int hres, int vres, int flag)
+{
+ u32 i;
+ DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
+
+ for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++)
+ if (viafb_modentry[i].xres == hres &&
+ viafb_modentry[i].yres == vres)
+ break;
+
+ viafb_resMode = viafb_modentry[i].mode_index;
+ if (flag)
+ viafb_mode1 = viafb_modentry[i].mode_res;
+ else
+ viafb_mode = viafb_modentry[i].mode_res;
+
+ return viafb_resMode;
+}
+
+static void check_available_device_to_enable(int device_id)
+{
+ int device_num = 0;
+
+ /* Initialize: */
+ viafb_CRT_ON = STATE_OFF;
+ viafb_DVI_ON = STATE_OFF;
+ viafb_LCD_ON = STATE_OFF;
+ viafb_LCD2_ON = STATE_OFF;
+ viafb_DeviceStatus = None_Device;
+
+ if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+ viafb_CRT_ON = STATE_ON;
+ device_num++;
+ viafb_DeviceStatus |= CRT_Device;
+ }
+
+ if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+ viafb_DVI_ON = STATE_ON;
+ device_num++;
+ viafb_DeviceStatus |= DVI_Device;
+ }
+
+ if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+ viafb_LCD_ON = STATE_ON;
+ device_num++;
+ viafb_DeviceStatus |= LCD_Device;
+ }
+
+ if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+ viafb_LCD2_ON = STATE_ON;
+ device_num++;
+ viafb_DeviceStatus |= LCD2_Device;
+ }
+
+ if (viafb_DeviceStatus == None_Device) {
+ /* Use CRT as default active device: */
+ viafb_CRT_ON = STATE_ON;
+ viafb_DeviceStatus = CRT_Device;
+ }
+ DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus);
+}
+
+static void viafb_set_device(struct device_t active_dev)
+{
+ /* Check available device to enable: */
+ int device_id = None_Device;
+ if (active_dev.crt)
+ device_id |= CRT_Device;
+ if (active_dev.dvi)
+ device_id |= DVI_Device;
+ if (active_dev.lcd)
+ device_id |= LCD_Device;
+
+ check_available_device_to_enable(device_id);
+
+ /* Check property of LCD: */
+ if (viafb_LCD_ON) {
+ if (active_dev.lcd_dsp_cent) {
+ viaparinfo->lvds_setting_info->display_method =
+ viafb_lcd_dsp_method = LCD_CENTERING;
+ } else {
+ viaparinfo->lvds_setting_info->display_method =
+ viafb_lcd_dsp_method = LCD_EXPANDSION;
+ }
+
+ if (active_dev.lcd_mode == LCD_SPWG) {
+ viaparinfo->lvds_setting_info->lcd_mode =
+ viafb_lcd_mode = LCD_SPWG;
+ } else {
+ viaparinfo->lvds_setting_info->lcd_mode =
+ viafb_lcd_mode = LCD_OPENLDI;
+ }
+
+ if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) {
+ viafb_lcd_panel_id = active_dev.lcd_panel_id;
+ viafb_init_lcd_size();
+ }
+ }
+
+ /* Check property of mode: */
+ if (!active_dev.xres1)
+ viafb_second_xres = 640;
+ else
+ viafb_second_xres = active_dev.xres1;
+ if (!active_dev.yres1)
+ viafb_second_yres = 480;
+ else
+ viafb_second_yres = active_dev.yres1;
+ if (active_dev.bpp != 0)
+ viafb_bpp = active_dev.bpp;
+ if (active_dev.bpp1 != 0)
+ viafb_bpp1 = active_dev.bpp1;
+ if (active_dev.refresh != 0)
+ viafb_refresh = active_dev.refresh;
+ if (active_dev.refresh1 != 0)
+ viafb_refresh1 = active_dev.refresh1;
+ if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON))
+ viafb_SAMM_ON = active_dev.samm;
+ viafb_primary_dev = active_dev.primary_dev;
+
+ viafb_set_start_addr();
+ viafb_set_iga_path();
+}
+
+static void viafb_set_video_device(u32 video_dev_info)
+{
+ viaparinfo->video_on_crt = STATE_OFF;
+ viaparinfo->video_on_dvi = STATE_OFF;
+ viaparinfo->video_on_lcd = STATE_OFF;
+
+ /* Check available device to enable: */
+ if ((video_dev_info & CRT_Device) == CRT_Device)
+ viaparinfo->video_on_crt = STATE_ON;
+ else if ((video_dev_info & DVI_Device) == DVI_Device)
+ viaparinfo->video_on_dvi = STATE_ON;
+ else if ((video_dev_info & LCD_Device) == LCD_Device)
+ viaparinfo->video_on_lcd = STATE_ON;
+}
+
+static void viafb_get_video_device(u32 *video_dev_info)
+{
+ *video_dev_info = None_Device;
+ if (viaparinfo->video_on_crt == STATE_ON)
+ *video_dev_info |= CRT_Device;
+ else if (viaparinfo->video_on_dvi == STATE_ON)
+ *video_dev_info |= DVI_Device;
+ else if (viaparinfo->video_on_lcd == STATE_ON)
+ *video_dev_info |= LCD_Device;
+}
+
+static int get_primary_device(void)
+{
+ int primary_device = 0;
+ /* Rule: device on iga1 path are the primary device. */
+ if (viafb_SAMM_ON) {
+ if (viafb_CRT_ON) {
+ if (viaparinfo->crt_setting_info->iga_path == IGA1) {
+ DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n",
+ viaparinfo->
+ crt_setting_info->iga_path);
+ primary_device = CRT_Device;
+ }
+ }
+ if (viafb_DVI_ON) {
+ if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
+ DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
+ viaparinfo->
+ tmds_setting_info->iga_path);
+ primary_device = DVI_Device;
+ }
+ }
+ if (viafb_LCD_ON) {
+ if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+ DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
+ viaparinfo->
+ lvds_setting_info->iga_path);
+ primary_device = LCD_Device;
+ }
+ }
+ if (viafb_LCD2_ON) {
+ if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+ DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
+ viaparinfo->
+ lvds_setting_info2->iga_path);
+ primary_device = LCD2_Device;
+ }
+ }
+ }
+ return primary_device;
+}
+
+static u8 is_duoview(void)
+{
+ if (0 == viafb_SAMM_ON) {
+ if (viafb_LCD_ON + viafb_LCD2_ON +
+ viafb_DVI_ON + viafb_CRT_ON == 2)
+ return true;
+ return false;
+ } else {
+ return false;
+ }
+}
+
+static void apply_second_mode_setting(struct fb_var_screeninfo
+ *sec_var)
+{
+ u32 htotal, vtotal, long_refresh;
+
+ htotal = sec_var->xres + sec_var->left_margin +
+ sec_var->right_margin + sec_var->hsync_len;
+ vtotal = sec_var->yres + sec_var->upper_margin +
+ sec_var->lower_margin + sec_var->vsync_len;
+ if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) {
+ /*Is 32 bytes alignment? */
+ /*32 pixel alignment */
+ sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31;
+ }
+
+ htotal = sec_var->xres + sec_var->left_margin +
+ sec_var->right_margin + sec_var->hsync_len;
+ vtotal = sec_var->yres + sec_var->upper_margin +
+ sec_var->lower_margin + sec_var->vsync_len;
+ long_refresh = 1000000000UL / sec_var->pixclock * 1000;
+ long_refresh /= (htotal * vtotal);
+
+ viafb_second_xres = sec_var->xres;
+ viafb_second_yres = sec_var->yres;
+ viafb_second_virtual_xres = sec_var->xres_virtual;
+ viafb_second_virtual_yres = sec_var->yres_virtual;
+ viafb_bpp1 = sec_var->bits_per_pixel;
+ viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres,
+ long_refresh);
+}
+
+static int apply_device_setting(struct viafb_ioctl_setting setting_info,
+ struct fb_info *info)
+{
+ int need_set_mode = 0;
+ DEBUG_MSG(KERN_INFO "apply_device_setting\n");
+
+ if (setting_info.device_flag) {
+ need_set_mode = 1;
+ check_available_device_to_enable(setting_info.device_status);
+ }
+
+ /* Unlock LCD's operation according to LCD flag
+ and check if the setting value is valid. */
+ /* If the value is valid, apply the new setting value to the device. */
+ if (viafb_LCD_ON) {
+ if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) {
+ need_set_mode = 1;
+ if (setting_info.lcd_attributes.display_center) {
+ /* Centering */
+ viaparinfo->lvds_setting_info->display_method =
+ LCD_CENTERING;
+ viafb_lcd_dsp_method = LCD_CENTERING;
+ viaparinfo->lvds_setting_info2->display_method =
+ viafb_lcd_dsp_method = LCD_CENTERING;
+ } else {
+ /* expandsion */
+ viaparinfo->lvds_setting_info->display_method =
+ LCD_EXPANDSION;
+ viafb_lcd_dsp_method = LCD_EXPANDSION;
+ viaparinfo->lvds_setting_info2->display_method =
+ LCD_EXPANDSION;
+ viafb_lcd_dsp_method = LCD_EXPANDSION;
+ }
+ }
+
+ if (setting_info.lcd_operation_flag & OP_LCD_MODE) {
+ need_set_mode = 1;
+ if (setting_info.lcd_attributes.lcd_mode ==
+ LCD_SPWG) {
+ viaparinfo->lvds_setting_info->lcd_mode =
+ viafb_lcd_mode = LCD_SPWG;
+ } else {
+ viaparinfo->lvds_setting_info->lcd_mode =
+ viafb_lcd_mode = LCD_OPENLDI;
+ }
+ viaparinfo->lvds_setting_info2->lcd_mode =
+ viaparinfo->lvds_setting_info->lcd_mode;
+ }
+
+ if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) {
+ need_set_mode = 1;
+ if (setting_info.lcd_attributes.panel_id <=
+ LCD_PANEL_ID_MAXIMUM) {
+ viafb_lcd_panel_id =
+ setting_info.lcd_attributes.panel_id;
+ viafb_init_lcd_size();
+ }
+ }
+ }
+
+ if (0 != (setting_info.samm_status & OP_SAMM)) {
+ setting_info.samm_status =
+ setting_info.samm_status & (~OP_SAMM);
+ if (setting_info.samm_status == 0
+ || setting_info.samm_status == 1) {
+ viafb_SAMM_ON = setting_info.samm_status;
+
+ if (viafb_SAMM_ON)
+ viafb_primary_dev = setting_info.primary_device;
+
+ viafb_set_start_addr();
+ viafb_set_iga_path();
+ }
+ need_set_mode = 1;
+ }
+
+ viaparinfo->duoview = is_duoview();
+
+ if (!need_set_mode) {
+ ;
+ } else {
+ viafb_set_iga_path();
+ viafb_set_par(info);
+ }
+ return true;
+}
+
+static void retrieve_device_setting(struct viafb_ioctl_setting
+ *setting_info)
+{
+
+ /* get device status */
+ if (viafb_CRT_ON == 1)
+ setting_info->device_status = CRT_Device;
+ if (viafb_DVI_ON == 1)
+ setting_info->device_status |= DVI_Device;
+ if (viafb_LCD_ON == 1)
+ setting_info->device_status |= LCD_Device;
+ if (viafb_LCD2_ON == 1)
+ setting_info->device_status |= LCD2_Device;
+ if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) {
+ setting_info->video_device_status =
+ viaparinfo->crt_setting_info->iga_path;
+ } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) {
+ setting_info->video_device_status =
+ viaparinfo->tmds_setting_info->iga_path;
+ } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) {
+ setting_info->video_device_status =
+ viaparinfo->lvds_setting_info->iga_path;
+ } else {
+ setting_info->video_device_status = 0;
+ }
+
+ setting_info->samm_status = viafb_SAMM_ON;
+ setting_info->primary_device = get_primary_device();
+
+ setting_info->first_dev_bpp = viafb_bpp;
+ setting_info->second_dev_bpp = viafb_bpp1;
+
+ setting_info->first_dev_refresh = viafb_refresh;
+ setting_info->second_dev_refresh = viafb_refresh1;
+
+ setting_info->first_dev_hor_res = viafb_hotplug_Xres;
+ setting_info->first_dev_ver_res = viafb_hotplug_Yres;
+ setting_info->second_dev_hor_res = viafb_second_xres;
+ setting_info->second_dev_ver_res = viafb_second_yres;
+
+ /* Get lcd attributes */
+ setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
+ setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
+ setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
+}
+
+static void parse_active_dev(void)
+{
+ viafb_CRT_ON = STATE_OFF;
+ viafb_DVI_ON = STATE_OFF;
+ viafb_LCD_ON = STATE_OFF;
+ viafb_LCD2_ON = STATE_OFF;
+ /* 1. Modify the active status of devices. */
+ /* 2. Keep the order of devices, so we can set corresponding
+ IGA path to devices in SAMM case. */
+ /* Note: The previous of active_dev is primary device,
+ and the following is secondary device. */
+ if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) {
+ /* CRT+DVI */
+ viafb_CRT_ON = STATE_ON;
+ viafb_DVI_ON = STATE_ON;
+ viafb_primary_dev = CRT_Device;
+ } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) {
+ /* DVI+CRT */
+ viafb_CRT_ON = STATE_ON;
+ viafb_DVI_ON = STATE_ON;
+ viafb_primary_dev = DVI_Device;
+ } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) {
+ /* CRT+LCD */
+ viafb_CRT_ON = STATE_ON;
+ viafb_LCD_ON = STATE_ON;
+ viafb_primary_dev = CRT_Device;
+ } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) {
+ /* LCD+CRT */
+ viafb_CRT_ON = STATE_ON;
+ viafb_LCD_ON = STATE_ON;
+ viafb_primary_dev = LCD_Device;
+ } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) {
+ /* DVI+LCD */
+ viafb_DVI_ON = STATE_ON;
+ viafb_LCD_ON = STATE_ON;
+ viafb_primary_dev = DVI_Device;
+ } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) {
+ /* LCD+DVI */
+ viafb_DVI_ON = STATE_ON;
+ viafb_LCD_ON = STATE_ON;
+ viafb_primary_dev = LCD_Device;
+ } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) {
+ viafb_LCD_ON = STATE_ON;
+ viafb_LCD2_ON = STATE_ON;
+ viafb_primary_dev = LCD_Device;
+ } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) {
+ viafb_LCD_ON = STATE_ON;
+ viafb_LCD2_ON = STATE_ON;
+ viafb_primary_dev = LCD2_Device;
+ } else if (!strncmp(viafb_active_dev, "CRT", 3)) {
+ /* CRT only */
+ viafb_CRT_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ } else if (!strncmp(viafb_active_dev, "DVI", 3)) {
+ /* DVI only */
+ viafb_DVI_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ } else if (!strncmp(viafb_active_dev, "LCD", 3)) {
+ /* LCD only */
+ viafb_LCD_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ } else {
+ viafb_CRT_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ }
+ viaparinfo->duoview = is_duoview();
+}
+
+static void parse_video_dev(void)
+{
+ viaparinfo->video_on_crt = STATE_OFF;
+ viaparinfo->video_on_dvi = STATE_OFF;
+ viaparinfo->video_on_lcd = STATE_OFF;
+
+ if (!strncmp(viafb_video_dev, "CRT", 3)) {
+ /* Video on CRT */
+ viaparinfo->video_on_crt = STATE_ON;
+ } else if (!strncmp(viafb_video_dev, "DVI", 3)) {
+ /* Video on DVI */
+ viaparinfo->video_on_dvi = STATE_ON;
+ } else if (!strncmp(viafb_video_dev, "LCD", 3)) {
+ /* Video on LCD */
+ viaparinfo->video_on_lcd = STATE_ON;
+ }
+}
+
+static int parse_port(char *opt_str, int *output_interface)
+{
+ if (!strncmp(opt_str, "DVP0", 4))
+ *output_interface = INTERFACE_DVP0;
+ else if (!strncmp(opt_str, "DVP1", 4))
+ *output_interface = INTERFACE_DVP1;
+ else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
+ *output_interface = INTERFACE_DFP;
+ else if (!strncmp(opt_str, "DFP_HIGH", 8))
+ *output_interface = INTERFACE_DFP_HIGH;
+ else if (!strncmp(opt_str, "DFP_LOW", 7))
+ *output_interface = INTERFACE_DFP_LOW;
+ else
+ *output_interface = INTERFACE_NONE;
+ return 0;
+}
+
+static void parse_lcd_port(void)
+{
+ parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
+ output_interface);
+ /*Initialize to avoid unexpected behavior */
+ viaparinfo->chip_info->lvds_chip_info2.output_interface =
+ INTERFACE_NONE;
+
+ DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
+ viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
+ output_interface);
+}
+
+static void parse_dvi_port(void)
+{
+ parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
+ output_interface);
+
+ DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
+ viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
+ output_interface);
+}
+
+/*
+ * The proc filesystem read/write function, a simple proc implement to
+ * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
+ * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2],
+ * CR9B, SR65, CR97, CR99
+ */
+static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset,
+int count, int *eof, void *data)
+{
+ int len = 0;
+ u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
+ dvp0_data_dri =
+ (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
+ (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
+ dvp0_clk_dri =
+ (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
+ (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
+ dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
+ len +=
+ sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
+ *eof = 1; /*Inform kernel end of data */
+ return len;
+}
+static int viafb_dvp0_proc_write(struct file *file,
+ const char __user *buffer, unsigned long count, void *data)
+{
+ char buf[20], *value, *pbuf;
+ u8 reg_val = 0;
+ unsigned long length, i;
+ if (count < 1)
+ return -EINVAL;
+ length = count > 20 ? 20 : count;
+ if (copy_from_user(&buf[0], buffer, length))
+ return -EFAULT;
+ buf[length - 1] = '\0'; /*Ensure end string */
+ pbuf = &buf[0];
+ for (i = 0; i < 3; i++) {
+ value = strsep(&pbuf, " ");
+ if (value != NULL) {
+ strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
+ reg_val);
+ switch (i) {
+ case 0:
+ viafb_write_reg_mask(CR96, VIACR,
+ reg_val, 0x0f);
+ break;
+ case 1:
+ viafb_write_reg_mask(SR2A, VIASR,
+ reg_val << 4, BIT5);
+ viafb_write_reg_mask(SR1B, VIASR,
+ reg_val << 1, BIT1);
+ break;
+ case 2:
+ viafb_write_reg_mask(SR2A, VIASR,
+ reg_val << 3, BIT4);
+ viafb_write_reg_mask(SR1E, VIASR,
+ reg_val << 2, BIT2);
+ break;
+ default:
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ return count;
+}
+static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
+ dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
+ dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
+ dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
+ len +=
+ sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
+ *eof = 1; /*Inform kernel end of data */
+ return len;
+}
+static int viafb_dvp1_proc_write(struct file *file,
+ const char __user *buffer, unsigned long count, void *data)
+{
+ char buf[20], *value, *pbuf;
+ u8 reg_val = 0;
+ unsigned long length, i;
+ if (count < 1)
+ return -EINVAL;
+ length = count > 20 ? 20 : count;
+ if (copy_from_user(&buf[0], buffer, length))
+ return -EFAULT;
+ buf[length - 1] = '\0'; /*Ensure end string */
+ pbuf = &buf[0];
+ for (i = 0; i < 3; i++) {
+ value = strsep(&pbuf, " ");
+ if (value != NULL) {
+ strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ switch (i) {
+ case 0:
+ viafb_write_reg_mask(CR9B, VIACR,
+ reg_val, 0x0f);
+ break;
+ case 1:
+ viafb_write_reg_mask(SR65, VIASR,
+ reg_val << 2, 0x0c);
+ break;
+ case 2:
+ viafb_write_reg_mask(SR65, VIASR,
+ reg_val, 0x03);
+ break;
+ default:
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ return count;
+}
+
+static int viafb_dfph_proc_read(char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ u8 dfp_high = 0;
+ dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
+ len += sprintf(buf + len, "%x\n", dfp_high);
+ *eof = 1; /*Inform kernel end of data */
+ return len;
+}
+static int viafb_dfph_proc_write(struct file *file,
+ const char __user *buffer, unsigned long count, void *data)
+{
+ char buf[20];
+ u8 reg_val = 0;
+ unsigned long length;
+ if (count < 1)
+ return -EINVAL;
+ length = count > 20 ? 20 : count;
+ if (copy_from_user(&buf[0], buffer, length))
+ return -EFAULT;
+ buf[length - 1] = '\0'; /*Ensure end string */
+ strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
+ return count;
+}
+static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ u8 dfp_low = 0;
+ dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
+ len += sprintf(buf + len, "%x\n", dfp_low);
+ *eof = 1; /*Inform kernel end of data */
+ return len;
+}
+static int viafb_dfpl_proc_write(struct file *file,
+ const char __user *buffer, unsigned long count, void *data)
+{
+ char buf[20];
+ u8 reg_val = 0;
+ unsigned long length;
+ if (count < 1)
+ return -EINVAL;
+ length = count > 20 ? 20 : count;
+ if (copy_from_user(&buf[0], buffer, length))
+ return -EFAULT;
+ buf[length - 1] = '\0'; /*Ensure end string */
+ strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
+ return count;
+}
+static int viafb_vt1636_proc_read(char *buf, char **start,
+ off_t offset, int count, int *eof, void *data)
+{
+ int len = 0;
+ u8 vt1636_08 = 0, vt1636_09 = 0;
+ switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ case VT1636_LVDS:
+ vt1636_08 =
+ viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
+ vt1636_09 =
+ viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
+ len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09);
+ break;
+ default:
+ break;
+ }
+ switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+ case VT1636_LVDS:
+ vt1636_08 =
+ viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
+ vt1636_09 =
+ viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
+ len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09);
+ break;
+ default:
+ break;
+ }
+ *eof = 1; /*Inform kernel end of data */
+ return len;
+}
+static int viafb_vt1636_proc_write(struct file *file,
+ const char __user *buffer, unsigned long count, void *data)
+{
+ char buf[30], *value, *pbuf;
+ struct IODATA reg_val;
+ unsigned long length, i;
+ if (count < 1)
+ return -EINVAL;
+ length = count > 30 ? 30 : count;
+ if (copy_from_user(&buf[0], buffer, length))
+ return -EFAULT;
+ buf[length - 1] = '\0'; /*Ensure end string */
+ pbuf = &buf[0];
+ switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+ case VT1636_LVDS:
+ for (i = 0; i < 2; i++) {
+ value = strsep(&pbuf, " ");
+ if (value != NULL) {
+ strict_strtoul(value, 0,
+ (unsigned long *)&reg_val.Data);
+ switch (i) {
+ case 0:
+ reg_val.Index = 0x08;
+ reg_val.Mask = 0x0f;
+ viafb_gpio_i2c_write_mask_lvds
+ (viaparinfo->lvds_setting_info,
+ &viaparinfo->
+ chip_info->lvds_chip_info,
+ reg_val);
+ break;
+ case 1:
+ reg_val.Index = 0x09;
+ reg_val.Mask = 0x1f;
+ viafb_gpio_i2c_write_mask_lvds
+ (viaparinfo->lvds_setting_info,
+ &viaparinfo->
+ chip_info->lvds_chip_info,
+ reg_val);
+ break;
+ default:
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+ case VT1636_LVDS:
+ for (i = 0; i < 2; i++) {
+ value = strsep(&pbuf, " ");
+ if (value != NULL) {
+ strict_strtoul(value, 0,
+ (unsigned long *)&reg_val.Data);
+ switch (i) {
+ case 0:
+ reg_val.Index = 0x08;
+ reg_val.Mask = 0x0f;
+ viafb_gpio_i2c_write_mask_lvds
+ (viaparinfo->lvds_setting_info2,
+ &viaparinfo->
+ chip_info->lvds_chip_info2,
+ reg_val);
+ break;
+ case 1:
+ reg_val.Index = 0x09;
+ reg_val.Mask = 0x1f;
+ viafb_gpio_i2c_write_mask_lvds
+ (viaparinfo->lvds_setting_info2,
+ &viaparinfo->
+ chip_info->lvds_chip_info2,
+ reg_val);
+ break;
+ default:
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return count;
+}
+
+static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
+{
+ struct proc_dir_entry *entry;
+ viafb_entry = proc_mkdir("viafb", NULL);
+ if (viafb_entry) {
+ entry = create_proc_entry("dvp0", 0, viafb_entry);
+ if (entry) {
+ entry->owner = THIS_MODULE;
+ entry->read_proc = viafb_dvp0_proc_read;
+ entry->write_proc = viafb_dvp0_proc_write;
+ }
+ entry = create_proc_entry("dvp1", 0, viafb_entry);
+ if (entry) {
+ entry->owner = THIS_MODULE;
+ entry->read_proc = viafb_dvp1_proc_read;
+ entry->write_proc = viafb_dvp1_proc_write;
+ }
+ entry = create_proc_entry("dfph", 0, viafb_entry);
+ if (entry) {
+ entry->owner = THIS_MODULE;
+ entry->read_proc = viafb_dfph_proc_read;
+ entry->write_proc = viafb_dfph_proc_write;
+ }
+ entry = create_proc_entry("dfpl", 0, viafb_entry);
+ if (entry) {
+ entry->owner = THIS_MODULE;
+ entry->read_proc = viafb_dfpl_proc_read;
+ entry->write_proc = viafb_dfpl_proc_write;
+ }
+ if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_name || VT1636_LVDS ==
+ viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+ entry = create_proc_entry("vt1636", 0, viafb_entry);
+ if (entry) {
+ entry->owner = THIS_MODULE;
+ entry->read_proc = viafb_vt1636_proc_read;
+ entry->write_proc = viafb_vt1636_proc_write;
+ }
+ }
+
+ }
+}
+static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+{
+ /* no problem if it was not registered */
+ remove_proc_entry("dvp0", viafb_entry);/* parent dir */
+ remove_proc_entry("dvp1", viafb_entry);
+ remove_proc_entry("dfph", viafb_entry);
+ remove_proc_entry("dfpl", viafb_entry);
+ remove_proc_entry("vt1636", viafb_entry);
+ remove_proc_entry("vt1625", viafb_entry);
+}
+
+static int __devinit via_pci_probe(void)
+{
+ unsigned int default_xres, default_yres;
+ char *tmpc, *tmpm;
+ char *tmpc_sec, *tmpm_sec;
+ int vmode_index;
+ u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length;
+
+ DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
+
+ viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
+ tmds_length = ALIGN(sizeof(struct tmds_setting_information),
+ BITS_PER_LONG/8);
+ lvds_length = ALIGN(sizeof(struct lvds_setting_information),
+ BITS_PER_LONG/8);
+ crt_length = ALIGN(sizeof(struct lvds_setting_information),
+ BITS_PER_LONG/8);
+ chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8);
+
+ /* Allocate fb_info and ***_par here, also including some other needed
+ * variables
+ */
+ viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length +
+ tmds_length + crt_length + chip_length, NULL);
+ if (!viafbinfo) {
+ printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
+ return -ENODEV;
+ }
+
+ viaparinfo = (struct viafb_par *)viafbinfo->par;
+ viaparinfo->tmds_setting_info = (struct tmds_setting_information *)
+ ((unsigned long)viaparinfo + viafb_par_length);
+ viaparinfo->lvds_setting_info = (struct lvds_setting_information *)
+ ((unsigned long)viaparinfo->tmds_setting_info + tmds_length);
+ viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *)
+ ((unsigned long)viaparinfo->lvds_setting_info + lvds_length);
+ viaparinfo->crt_setting_info = (struct crt_setting_information *)
+ ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length);
+ viaparinfo->chip_info = (struct chip_information *)
+ ((unsigned long)viaparinfo->crt_setting_info + crt_length);
+
+ if (viafb_dual_fb)
+ viafb_SAMM_ON = 1;
+ parse_active_dev();
+ parse_video_dev();
+ parse_lcd_port();
+ parse_dvi_port();
+
+ /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */
+ if (!viafb_SAMM_ON)
+ viafb_dual_fb = 0;
+
+ /* Set up I2C bus stuff */
+ viafb_create_i2c_bus(viaparinfo);
+
+ viafb_init_chip_info();
+ viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize);
+ viaparinfo->fbmem_free = viaparinfo->memsize;
+ viaparinfo->fbmem_used = 0;
+ viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem,
+ viaparinfo->memsize);
+ viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt;
+
+ if (!viaparinfo->fbmem_virt) {
+ printk(KERN_INFO "ioremap failed\n");
+ return -1;
+ }
+
+ viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len);
+ viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base,
+ viaparinfo->mmio_len);
+
+ viafbinfo->node = 0;
+ viafbinfo->fbops = &viafb_ops;
+ viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ viafbinfo->pseudo_palette = pseudo_pal;
+ if (viafb_accel) {
+ viafb_init_accel();
+ viafb_init_2d_engine();
+ viafb_hw_cursor_init();
+ }
+
+ if (viafb_second_size && (viafb_second_size < 8)) {
+ viafb_second_offset = viaparinfo->fbmem_free -
+ viafb_second_size * 1024 * 1024;
+ } else {
+ viafb_second_size = 8;
+ viafb_second_offset = viaparinfo->fbmem_free -
+ viafb_second_size * 1024 * 1024;
+ }
+
+ viafb_FB_MM = viaparinfo->fbmem_virt;
+ tmpm = viafb_mode;
+ tmpc = strsep(&tmpm, "x");
+ strict_strtoul(tmpc, 0, (unsigned long *)&default_xres);
+ strict_strtoul(tmpm, 0, (unsigned long *)&default_yres);
+
+ vmode_index = viafb_get_mode_index(default_xres, default_yres, 0);
+ DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
+
+ if (viafb_SAMM_ON == 1) {
+ if (strcmp(viafb_mode, viafb_mode1)) {
+ tmpm_sec = viafb_mode1;
+ tmpc_sec = strsep(&tmpm_sec, "x");
+ strict_strtoul(tmpc_sec, 0,
+ (unsigned long *)&viafb_second_xres);
+ strict_strtoul(tmpm_sec, 0,
+ (unsigned long *)&viafb_second_yres);
+ } else {
+ viafb_second_xres = default_xres;
+ viafb_second_yres = default_yres;
+ }
+ if (0 == viafb_second_virtual_xres) {
+ switch (viafb_second_xres) {
+ case 1400:
+ viafb_second_virtual_xres = 1408;
+ break;
+ default:
+ viafb_second_virtual_xres = viafb_second_xres;
+ break;
+ }
+ }
+ if (0 == viafb_second_virtual_yres)
+ viafb_second_virtual_yres = viafb_second_yres;
+ }
+
+ switch (viafb_bpp) {
+ case 0 ... 8:
+ viafb_bpp = 8;
+ break;
+ case 9 ... 16:
+ viafb_bpp = 16;
+ break;
+ case 17 ... 32:
+ viafb_bpp = 32;
+ break;
+ default:
+ viafb_bpp = 8;
+ }
+ default_var.xres = default_xres;
+ default_var.yres = default_yres;
+ switch (default_xres) {
+ case 1400:
+ default_var.xres_virtual = 1408;
+ break;
+ default:
+ default_var.xres_virtual = default_xres;
+ break;
+ }
+ default_var.yres_virtual = default_yres;
+ default_var.bits_per_pixel = viafb_bpp;
+ if (default_var.bits_per_pixel == 15)
+ default_var.bits_per_pixel = 16;
+ default_var.pixclock =
+ viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
+ default_var.left_margin = (default_xres >> 3) & 0xf8;
+ default_var.right_margin = 32;
+ default_var.upper_margin = 16;
+ default_var.lower_margin = 4;
+ default_var.hsync_len = default_var.left_margin;
+ default_var.vsync_len = 4;
+ default_var.accel_flags = 0;
+
+ if (viafb_accel) {
+ viafbinfo->flags |=
+ (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+ FBINFO_HWACCEL_IMAGEBLIT);
+ default_var.accel_flags |= FB_ACCELF_TEXT;
+ } else
+ viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
+
+ if (viafb_dual_fb) {
+ viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL);
+ if (!viafbinfo1) {
+ printk(KERN_ERR
+ "allocate the second framebuffer struct error\n");
+ framebuffer_release(viafbinfo);
+ return -ENOMEM;
+ }
+ viaparinfo1 = viafbinfo1->par;
+ memcpy(viaparinfo1, viaparinfo, viafb_par_length);
+ viaparinfo1->memsize = viaparinfo->memsize -
+ viafb_second_offset;
+ viaparinfo->memsize = viafb_second_offset;
+ viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt +
+ viafb_second_offset;
+ viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
+
+ viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
+ viaparinfo1->fbmem_free = viaparinfo1->memsize -
+ viaparinfo1->fbmem_used;
+ viaparinfo->fbmem_free = viaparinfo->memsize;
+ viaparinfo->fbmem_used = 0;
+ if (viafb_accel) {
+ viaparinfo1->cursor_start =
+ viaparinfo->cursor_start - viafb_second_offset;
+ viaparinfo1->VQ_start = viaparinfo->VQ_start -
+ viafb_second_offset;
+ viaparinfo1->VQ_end = viaparinfo->VQ_end -
+ viafb_second_offset;
+ }
+
+ memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
+ viafbinfo1->screen_base = viafbinfo->screen_base +
+ viafb_second_offset;
+ viafbinfo1->fix.smem_start = viaparinfo1->fbmem;
+ viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free;
+
+ default_var.xres = viafb_second_xres;
+ default_var.yres = viafb_second_yres;
+ default_var.xres_virtual = viafb_second_virtual_xres;
+ default_var.yres_virtual = viafb_second_virtual_yres;
+ if (viafb_bpp1 != viafb_bpp)
+ viafb_bpp1 = viafb_bpp;
+ default_var.bits_per_pixel = viafb_bpp1;
+ default_var.pixclock =
+ viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
+ viafb_refresh);
+ default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
+ default_var.right_margin = 32;
+ default_var.upper_margin = 16;
+ default_var.lower_margin = 4;
+ default_var.hsync_len = default_var.left_margin;
+ default_var.vsync_len = 4;
+
+ viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
+ viafb_check_var(&default_var, viafbinfo1);
+ viafbinfo1->var = default_var;
+ viafb_update_viafb_par(viafbinfo);
+ viafb_update_fix(&viafbinfo1->fix, viafbinfo1);
+ }
+
+ viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
+ viafb_check_var(&default_var, viafbinfo);
+ viafbinfo->var = default_var;
+ viafb_update_viafb_par(viafbinfo);
+ viafb_update_fix(&viafbinfo->fix, viafbinfo);
+ default_var.activate = FB_ACTIVATE_NOW;
+ fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
+
+ if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
+ && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
+ if (register_framebuffer(viafbinfo1) < 0)
+ return -EINVAL;
+ }
+ if (register_framebuffer(viafbinfo) < 0)
+ return -EINVAL;
+
+ if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
+ || (viaparinfo->chip_info->gfx_chip_name !=
+ UNICHROME_CLE266))) {
+ if (register_framebuffer(viafbinfo1) < 0)
+ return -EINVAL;
+ }
+ DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
+ viafbinfo->node, viafbinfo->fix.id, default_var.xres,
+ default_var.yres, default_var.bits_per_pixel);
+
+ viafb_init_proc(viaparinfo->proc_entry);
+ viafb_init_dac(IGA2);
+ return 0;
+}
+
+static void __devexit via_pci_remove(void)
+{
+ DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
+ fb_dealloc_cmap(&viafbinfo->cmap);
+ unregister_framebuffer(viafbinfo);
+ if (viafb_dual_fb)
+ unregister_framebuffer(viafbinfo1);
+ iounmap((void *)viaparinfo->fbmem_virt);
+ iounmap(viaparinfo->io_virt);
+
+ viafb_delete_i2c_buss(viaparinfo);
+
+ framebuffer_release(viafbinfo);
+ if (viafb_dual_fb)
+ framebuffer_release(viafbinfo1);
+
+ viafb_remove_proc(viaparinfo->proc_entry);
+}
+
+#ifndef MODULE
+static int __init viafb_setup(char *options)
+{
+ char *this_opt;
+ DEBUG_MSG(KERN_INFO "viafb_setup!\n");
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+
+ if (!strncmp(this_opt, "viafb_mode1=", 12))
+ viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
+ else if (!strncmp(this_opt, "viafb_mode=", 11))
+ viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
+ else if (!strncmp(this_opt, "viafb_bpp1=", 11))
+ strict_strtoul(this_opt + 11, 0,
+ (unsigned long *)&viafb_bpp1);
+ else if (!strncmp(this_opt, "viafb_bpp=", 10))
+ strict_strtoul(this_opt + 10, 0,
+ (unsigned long *)&viafb_bpp);
+ else if (!strncmp(this_opt, "viafb_refresh1=", 15))
+ strict_strtoul(this_opt + 15, 0,
+ (unsigned long *)&viafb_refresh1);
+ else if (!strncmp(this_opt, "viafb_refresh=", 14))
+ strict_strtoul(this_opt + 14, 0,
+ (unsigned long *)&viafb_refresh);
+ else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
+ strict_strtoul(this_opt + 21, 0,
+ (unsigned long *)&viafb_lcd_dsp_method);
+ else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
+ strict_strtoul(this_opt + 19, 0,
+ (unsigned long *)&viafb_lcd_panel_id);
+ else if (!strncmp(this_opt, "viafb_accel=", 12))
+ strict_strtoul(this_opt + 12, 0,
+ (unsigned long *)&viafb_accel);
+ else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
+ strict_strtoul(this_opt + 14, 0,
+ (unsigned long *)&viafb_SAMM_ON);
+ else if (!strncmp(this_opt, "viafb_active_dev=", 17))
+ viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
+ else if (!strncmp(this_opt,
+ "viafb_display_hardware_layout=", 30))
+ strict_strtoul(this_opt + 30, 0,
+ (unsigned long *)&viafb_display_hardware_layout);
+ else if (!strncmp(this_opt, "viafb_second_size=", 18))
+ strict_strtoul(this_opt + 18, 0,
+ (unsigned long *)&viafb_second_size);
+ else if (!strncmp(this_opt,
+ "viafb_platform_epia_dvi=", 24))
+ strict_strtoul(this_opt + 24, 0,
+ (unsigned long *)&viafb_platform_epia_dvi);
+ else if (!strncmp(this_opt,
+ "viafb_device_lcd_dualedge=", 26))
+ strict_strtoul(this_opt + 26, 0,
+ (unsigned long *)&viafb_device_lcd_dualedge);
+ else if (!strncmp(this_opt, "viafb_bus_width=", 16))
+ strict_strtoul(this_opt + 16, 0,
+ (unsigned long *)&viafb_bus_width);
+ else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
+ strict_strtoul(this_opt + 15, 0,
+ (unsigned long *)&viafb_lcd_mode);
+ else if (!strncmp(this_opt, "viafb_video_dev=", 16))
+ viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL);
+ else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
+ viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
+ else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
+ viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+ }
+ return 0;
+}
+#endif
+
+static int __init viafb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+ if (fb_get_options("viafb", &option))
+ return -ENODEV;
+ viafb_setup(option);
+#endif
+ printk(KERN_INFO
+ "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
+ VERSION_MAJOR, VERSION_MINOR);
+ return via_pci_probe();
+}
+
+static void __exit viafb_exit(void)
+{
+ DEBUG_MSG(KERN_INFO "viafb_exit!\n");
+ via_pci_remove();
+}
+
+static struct fb_ops viafb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = viafb_open,
+ .fb_release = viafb_release,
+ .fb_check_var = viafb_check_var,
+ .fb_set_par = viafb_set_par,
+ .fb_setcolreg = viafb_setcolreg,
+ .fb_pan_display = viafb_pan_display,
+ .fb_blank = viafb_blank,
+ .fb_fillrect = viafb_fillrect,
+ .fb_copyarea = viafb_copyarea,
+ .fb_imageblit = viafb_imageblit,
+ .fb_cursor = viafb_cursor,
+ .fb_ioctl = viafb_ioctl,
+ .fb_sync = viafb_sync,
+ .fb_setcmap = viafb_setcmap,
+};
+
+module_init(viafb_init);
+module_exit(viafb_exit);
+
+#ifdef MODULE
+module_param(viafb_memsize, int, 0);
+
+module_param(viafb_mode, charp, 0);
+MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
+
+module_param(viafb_mode1, charp, 0);
+MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
+
+module_param(viafb_bpp, int, 0);
+MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
+
+module_param(viafb_bpp1, int, 0);
+MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
+
+module_param(viafb_refresh, int, 0);
+MODULE_PARM_DESC(viafb_refresh,
+ "Set CRT viafb_refresh rate (default = 60)");
+
+module_param(viafb_refresh1, int, 0);
+MODULE_PARM_DESC(viafb_refresh1,
+ "Set CRT refresh rate (default = 60)");
+
+module_param(viafb_lcd_panel_id, int, 0);
+MODULE_PARM_DESC(viafb_lcd_panel_id,
+ "Set Flat Panel type(Default=1024x768)");
+
+module_param(viafb_lcd_dsp_method, int, 0);
+MODULE_PARM_DESC(viafb_lcd_dsp_method,
+ "Set Flat Panel display scaling method.(Default=Expandsion)");
+
+module_param(viafb_SAMM_ON, int, 0);
+MODULE_PARM_DESC(viafb_SAMM_ON,
+ "Turn on/off flag of SAMM(Default=OFF)");
+
+module_param(viafb_accel, int, 0);
+MODULE_PARM_DESC(viafb_accel,
+ "Set 2D Hardware Acceleration.(Default = OFF)");
+
+module_param(viafb_active_dev, charp, 0);
+MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
+
+module_param(viafb_display_hardware_layout, int, 0);
+MODULE_PARM_DESC(viafb_display_hardware_layout,
+ "Display Hardware Layout (LCD Only, DVI Only...,etc)");
+
+module_param(viafb_second_size, int, 0);
+MODULE_PARM_DESC(viafb_second_size,
+ "Set secondary device memory size");
+
+module_param(viafb_dual_fb, int, 0);
+MODULE_PARM_DESC(viafb_dual_fb,
+ "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
+
+module_param(viafb_platform_epia_dvi, int, 0);
+MODULE_PARM_DESC(viafb_platform_epia_dvi,
+ "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
+
+module_param(viafb_device_lcd_dualedge, int, 0);
+MODULE_PARM_DESC(viafb_device_lcd_dualedge,
+ "Turn on/off flag of dual edge panel.(Default = OFF)");
+
+module_param(viafb_bus_width, int, 0);
+MODULE_PARM_DESC(viafb_bus_width,
+ "Set bus width of panel.(Default = 12)");
+
+module_param(viafb_lcd_mode, int, 0);
+MODULE_PARM_DESC(viafb_lcd_mode,
+ "Set Flat Panel mode(Default=OPENLDI)");
+
+module_param(viafb_video_dev, charp, 0);
+MODULE_PARM_DESC(viafb_video_dev, "Specify video devices.");
+
+module_param(viafb_lcd_port, charp, 0);
+MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
+
+module_param(viafb_dvi_port, charp, 0);
+MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
new file mode 100644
index 00000000000..a4158e87287
--- /dev/null
+++ b/drivers/video/via/viafbdev.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VIAFBDEV_H__
+#define __VIAFBDEV_H__
+
+#include <linux/proc_fs.h>
+#include <linux/fb.h>
+
+#include "ioctl.h"
+#include "share.h"
+#include "chip.h"
+#include "hw.h"
+#include "via_i2c.h"
+
+#define VERSION_MAJOR 2
+#define VERSION_KERNEL 6 /* For kernel 2.6 */
+
+#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
+#define VERSION_MINOR 4
+
+struct viafb_par {
+ int bpp;
+ int hres;
+ int vres;
+ int linelength;
+ u32 xoffset;
+ u32 yoffset;
+
+ void __iomem *fbmem_virt; /*framebuffer virtual memory address */
+ void __iomem *io_virt; /*iospace virtual memory address */
+ unsigned int fbmem; /*framebuffer physical memory address */
+ unsigned int memsize; /*size of fbmem */
+ unsigned int io; /*io space address */
+ unsigned long mmio_base; /*mmio base address */
+ unsigned long mmio_len; /*mmio base length */
+ u32 fbmem_free; /* Free FB memory */
+ u32 fbmem_used; /* Use FB memory size */
+ u32 cursor_start; /* Cursor Start Address */
+ u32 VQ_start; /* Virtual Queue Start Address */
+ u32 VQ_end; /* Virtual Queue End Address */
+ u32 iga_path;
+ struct proc_dir_entry *proc_entry; /*viafb proc entry */
+ u8 duoview; /*Is working in duoview mode? */
+
+ /* I2C stuff */
+ struct via_i2c_stuff i2c_stuff;
+
+ /* All the information will be needed to set engine */
+ struct tmds_setting_information *tmds_setting_info;
+ struct crt_setting_information *crt_setting_info;
+ struct lvds_setting_information *lvds_setting_info;
+ struct lvds_setting_information *lvds_setting_info2;
+ struct chip_information *chip_info;
+
+ /* some information related to video playing */
+ int video_on_crt;
+ int video_on_dvi;
+ int video_on_lcd;
+
+};
+struct viafb_modeinfo {
+ u32 xres;
+ u32 yres;
+ int mode_index;
+ char *mode_res;
+};
+extern unsigned int viafb_second_virtual_yres;
+extern unsigned int viafb_second_virtual_xres;
+extern unsigned int viafb_second_offset;
+extern int viafb_second_size;
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_accel;
+extern int viafb_hotplug;
+extern int viafb_memsize;
+
+extern int strict_strtoul(const char *cp, unsigned int base,
+ unsigned long *res);
+
+void viafb_memory_pitch_patch(struct fb_info *info);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
+ int mode_index);
+int viafb_get_mode_index(int hres, int vres, int flag);
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information
+ *plvds_chip_info, u8 index);
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information
+ *plvds_chip_info, struct IODATA io_data);
+#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
new file mode 100644
index 00000000000..6dcf583a837
--- /dev/null
+++ b/drivers/video/via/viamode.c
@@ -0,0 +1,1086 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+struct res_map_refresh res_map_refresh_tbl[] = {
+/*hres, vres, vclock, vmode_refresh*/
+ {480, 640, RES_480X640_60HZ_PIXCLOCK, 60},
+ {640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
+ {640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
+ {640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
+ {640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
+ {640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
+ {720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
+ {720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
+ {800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
+ {800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
+ {800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
+ {800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
+ {800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
+ {800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
+ {848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
+ {856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
+ {1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60},
+ {1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60},
+ {1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60},
+ {1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75},
+ {1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85},
+ {1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100},
+/* {1152,864, RES_1152X864_70HZ_PIXCLOCK, 70},*/
+ {1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75},
+ {1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60},
+ {1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60},
+ {1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60},
+ {1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60},
+ {1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75},
+ {1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85},
+ {1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60},
+ {1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60},
+ {1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75},
+ {1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60},
+ {1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60},
+ {1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60},
+ {1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75},
+ {1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60},
+ {960, 600, RES_960X600_60HZ_PIXCLOCK, 60},
+ {1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60},
+ {1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60},
+ {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
+ {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
+ {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
+ {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
+ {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
+ {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
+ {1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60},
+ {1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50},
+ {1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60},
+ {1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60},
+ {1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75},
+ {1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60},
+ {1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60},
+ {1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60},
+ {1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75},
+ {1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60},
+ {1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60},
+ {1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60},
+ {1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60},
+ {1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75},
+ {2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60}
+};
+
+struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1E, 0x0F, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+{VIACR, CR8B, 0xFF, 0x69}, /* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x57}, /* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x00}, /* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x7B}, /* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x03}, /* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x30}, /* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00}
+};
+
+/* Video Mode Table for VT3314 chipset*/
+/* Common Setting for Video Mode */
+struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x82},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1F, 0xFF, 0x00},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR22, 0xFF, 0x1F},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR2E, 0xFF, 0xFF},
+{VIASR, SR3F, 0xFF, 0xFF},
+{VIASR, SR40, 0xF7, 0x00},
+{VIASR, CR30, 0xFF, 0x04},
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0x7F, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0xFF, 0x31},
+{VIACR, CR41, 0xFF, 0x80},
+{VIACR, CR42, 0xFF, 0x00},
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/
+{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFD, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */
+{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */
+{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */
+{VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */
+{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CR9D, 0xFF, 0x80},
+{VIACR, CR9E, 0xFF, 0x80}
+};
+
+struct io_reg KM400_ModeXregs[] = {
+ {VIASR, SR10, 0xFF, 0x01}, /* Unlock Register */
+ {VIASR, SR16, 0xFF, 0x08}, /* Display FIFO threshold Control */
+ {VIASR, SR17, 0xFF, 0x1F}, /* Display FIFO Control */
+ {VIASR, SR18, 0xFF, 0x4E}, /* GFX PREQ threshold */
+ {VIASR, SR1A, 0xFF, 0x0a}, /* GFX PREQ threshold */
+ {VIASR, SR1F, 0xFF, 0x00}, /* Memory Control 0 */
+ {VIASR, SR1B, 0xFF, 0xF0}, /* Power Management Control 0 */
+ {VIASR, SR1E, 0xFF, 0x01}, /* Power Management Control */
+ {VIASR, SR20, 0xFF, 0x00}, /* Sequencer Arbiter Control 0 */
+ {VIASR, SR21, 0xFF, 0x00}, /* Sequencer Arbiter Control 1 */
+ {VIASR, SR22, 0xFF, 0x1F}, /* Display Arbiter Control 1 */
+ {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */
+ {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */
+ {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */
+ {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+ {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+ {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+ {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+ {VIACR, CR33, 0xFF, 0x00},
+ {VIACR, CR55, 0x80, 0x00},
+ {VIACR, CR5D, 0x80, 0x00},
+ {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
+ {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+ {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
+ {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
+ {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+ {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+ {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+ {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+ {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+ {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+ {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+ {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+ {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+ {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+ {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+ {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+ {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+ {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+ {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+ {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+ {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+ {VIACR, CR8B, 0xFF, 0x2D}, /* LCD Power Sequence Control 0 */
+ {VIACR, CR8C, 0xFF, 0x2D}, /* LCD Power Sequence Control 1 */
+ {VIACR, CR8D, 0xFF, 0xC8}, /* LCD Power Sequence Control 2 */
+ {VIACR, CR8E, 0xFF, 0x36}, /* LCD Power Sequence Control 3 */
+ {VIACR, CR8F, 0xFF, 0x00}, /* LCD Power Sequence Control 4 */
+ {VIACR, CR90, 0xFF, 0x10}, /* LCD Power Sequence Control 5 */
+ {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
+ {VIACR, CR96, 0xFF, 0x03}, /* DVP0 ; DVP0 Clock Skew */
+ {VIACR, CR97, 0xFF, 0x03}, /* DFP high ; DFPH Clock Skew */
+ {VIACR, CR99, 0xFF, 0x03}, /* DFP low ; DFPL Clock Skew*/
+ {VIACR, CR9B, 0xFF, 0x07} /* DVI on DVP1 ; DVP1 Clock Skew*/
+};
+
+/* For VT3324: Common Setting for Video Mode */
+struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
+{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
+{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
+{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
+};
+
+/* For VT3353: Common Setting for Video Mode */
+struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
+{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
+{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
+{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
+{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
+{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
+{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
+{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
+{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
+};
+
+/* Video Mode Table */
+/* Common Setting for Video Mode */
+struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR6A, 0xFF, 0x80},
+{VIACR, CR6A, 0xFF, 0xC0},
+
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00},
+
+{VIAGR, GR20, 0xFF, 0x00},
+{VIAGR, GR21, 0xFF, 0x00},
+{VIAGR, GR22, 0xFF, 0x00},
+ /* LCD Parameters */
+{VIACR, CR7A, 0xFF, 0x01}, /* LCD Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02}, /* LCD Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03}, /* LCD Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04}, /* LCD Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07}, /* LCD Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D}, /* LCD Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13}, /* LCD Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16}, /* LCD Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19}, /* LCD Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C}, /* LCD Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D}, /* LCD Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E}, /* LCD Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F}, /* LCD Parameter 14 */
+
+};
+
+/* Mode:1024X768 */
+struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
+{VIASR, 0x18, 0xFF, 0x4C}
+};
+
+struct patch_table res_patch_table[] = {
+ {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768}
+};
+
+/* struct VPITTable {
+ unsigned char Misc;
+ unsigned char SR[StdSR];
+ unsigned char CR[StdCR];
+ unsigned char GR[StdGR];
+ unsigned char AR[StdAR];
+ };*/
+
+struct VPITTable VPIT = {
+ /* Msic */
+ 0xC7,
+ /* Sequencer */
+ {0x01, 0x0F, 0x00, 0x0E},
+ /* Graphic Controller */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+ /* Attribute Controller */
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x01, 0x00, 0x0F, 0x00}
+};
+
+/********************/
+/* Mode Table */
+/********************/
+
+/* 480x640 */
+struct crt_mode_table CRTM480x640[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP,
+ {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/
+};
+
+/* 640x480*/
+struct crt_mode_table CRTM640x480[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP,
+ {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
+ {REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP,
+ {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
+ {REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP,
+ {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} },
+ {REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP,
+ {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/
+ {REFRESH_120, CLK_52_406M, M640X480_R120_HSP,
+ M640X480_R120_VSP,
+ {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481,
+ 3} } /*GTF*/
+};
+
+/*720x480 (GTF)*/
+struct crt_mode_table CRTM720x480[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP,
+ {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} }
+
+};
+
+/*720x576 (GTF)*/
+struct crt_mode_table CRTM720x576[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP,
+ {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} }
+};
+
+/* 800x480 (CVT) */
+struct crt_mode_table CRTM800x480[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP,
+ {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} }
+};
+
+/* 800x600*/
+struct crt_mode_table CRTM800x600[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP,
+ {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} },
+ {REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP,
+ {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} },
+ {REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP,
+ {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} },
+ {REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP,
+ {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} },
+ {REFRESH_120, CLK_83_950M, M800X600_R120_HSP,
+ M800X600_R120_VSP,
+ {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601,
+ 3} }
+};
+
+/* 848x480 (CVT) */
+struct crt_mode_table CRTM848x480[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP,
+ {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} }
+};
+
+/*856x480 (GTF) convert to 852x480*/
+struct crt_mode_table CRTM852x480[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP,
+ {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
+};
+
+/*1024x512 (GTF)*/
+struct crt_mode_table CRTM1024x512[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP,
+ {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
+
+};
+
+/* 1024x600*/
+struct crt_mode_table CRTM1024x600[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP,
+ {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
+};
+
+/* 1024x768*/
+struct crt_mode_table CRTM1024x768[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP,
+ {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
+ {REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP,
+ {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
+ {REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP,
+ {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
+ {REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP,
+ {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
+};
+
+/* 1152x864*/
+struct crt_mode_table CRTM1152x864[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP,
+ {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
+
+};
+
+/* 1280x720 (HDMI 720P)*/
+struct crt_mode_table CRTM1280x720[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP,
+ {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
+ {REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP,
+ {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
+};
+
+/*1280x768 (GTF)*/
+struct crt_mode_table CRTM1280x768[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP,
+ {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
+ {REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP,
+ {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
+};
+
+/* 1280x800 (CVT) */
+struct crt_mode_table CRTM1280x800[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP,
+ {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
+};
+
+/*1280x960*/
+struct crt_mode_table CRTM1280x960[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP,
+ {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
+};
+
+/* 1280x1024*/
+struct crt_mode_table CRTM1280x1024[] = {
+ /*r_rate,vclk,,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
+ {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
+ 3} },
+ {REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
+ {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
+ 3} },
+ {REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
+ {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
+};
+
+/* 1368x768 (GTF) */
+struct crt_mode_table CRTM1368x768[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+ {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
+};
+
+/*1440x1050 (GTF)*/
+struct crt_mode_table CRTM1440x1050[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
+ {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
+};
+
+/* 1600x1200*/
+struct crt_mode_table CRTM1600x1200[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
+ {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
+ 3} },
+ {REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
+ {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
+
+};
+
+/* 1680x1050 (CVT) */
+struct crt_mode_table CRTM1680x1050[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
+ {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
+ 6} },
+ {REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
+ {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
+};
+
+/* 1680x1050 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1680x1050_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP,
+ M1680x1050_RB_R60_VSP,
+ {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
+};
+
+/* 1920x1080 (CVT)*/
+struct crt_mode_table CRTM1920x1080[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
+ {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
+};
+
+/* 1920x1080 (CVT with Reduce Blanking) */
+struct crt_mode_table CRTM1920x1080_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP,
+ M1920X1080_RB_R60_VSP,
+ {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
+};
+
+/* 1920x1440*/
+struct crt_mode_table CRTM1920x1440[] = {
+ /*r_rate,vclk,hsp,vsp */
+ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
+ {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
+ 3} },
+ {REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
+ {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
+};
+
+/* 1400x1050 (CVT) */
+struct crt_mode_table CRTM1400x1050[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
+ {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
+ 4} },
+ {REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
+ {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
+};
+
+/* 1400x1050 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1400x1050_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP,
+ M1400X1050_RB_R60_VSP,
+ {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
+};
+
+/* 960x600 (CVT) */
+struct crt_mode_table CRTM960x600[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP,
+ {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
+};
+
+/* 1000x600 (GTF) */
+struct crt_mode_table CRTM1000x600[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP,
+ {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
+};
+
+/* 1024x576 (GTF) */
+struct crt_mode_table CRTM1024x576[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP,
+ {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
+};
+
+/* 1088x612 (CVT) */
+struct crt_mode_table CRTM1088x612[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP,
+ {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
+};
+
+/* 1152x720 (CVT) */
+struct crt_mode_table CRTM1152x720[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP,
+ {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
+};
+
+/* 1200x720 (GTF) */
+struct crt_mode_table CRTM1200x720[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP,
+ {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
+};
+
+/* 1280x600 (GTF) */
+struct crt_mode_table CRTM1280x600[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP,
+ {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
+};
+
+/* 1360x768 (CVT) */
+struct crt_mode_table CRTM1360x768[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP,
+ {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
+};
+
+/* 1360x768 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1360x768_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP,
+ M1360X768_RB_R60_VSP,
+ {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
+};
+
+/* 1366x768 (GTF) */
+struct crt_mode_table CRTM1366x768[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+ {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
+ {REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP,
+ {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
+};
+
+/* 1440x900 (CVT) */
+struct crt_mode_table CRTM1440x900[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP,
+ {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
+ {REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP,
+ {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
+};
+
+/* 1440x900 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1440x900_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP,
+ M1440X900_RB_R60_VSP,
+ {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
+};
+
+/* 1600x900 (CVT) */
+struct crt_mode_table CRTM1600x900[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP,
+ {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
+};
+
+/* 1600x900 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1600x900_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP,
+ M1600X900_RB_R60_VSP,
+ {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
+};
+
+/* 1600x1024 (GTF) */
+struct crt_mode_table CRTM1600x1024[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
+ {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
+};
+
+/* 1792x1344 (DMT) */
+struct crt_mode_table CRTM1792x1344[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
+ {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
+};
+
+/* 1856x1392 (DMT) */
+struct crt_mode_table CRTM1856x1392[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
+ {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
+};
+
+/* 1920x1200 (CVT) */
+struct crt_mode_table CRTM1920x1200[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
+ {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
+};
+
+/* 1920x1200 (CVT with Reduce Blanking) */
+struct crt_mode_table CRTM1920x1200_RB[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP,
+ M1920X1200_RB_R60_VSP,
+ {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
+};
+
+/* 2048x1536 (CVT) */
+struct crt_mode_table CRTM2048x1536[] = {
+ /* r_rate, vclk, hsp, vsp */
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
+ {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
+};
+
+/* Video Mode Table */
+/* struct VideoModeTable {*/
+/* int ModeIndex;*/
+/* struct crt_mode_table *crtc;*/
+/* int mode_array;*/
+/* };*/
+struct VideoModeTable CLE266Modes[] = {
+ /* Display : 480x640 (GTF) */
+ {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)},
+
+ /* Display : 640x480 */
+ {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)},
+
+ /* Display : 720x480 (GTF) */
+ {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)},
+
+ /* Display : 720x576 (GTF) */
+ {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)},
+
+ /* Display : 800x600 */
+ {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)},
+
+ /* Display : 800x480 (CVT) */
+ {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)},
+
+ /* Display : 848x480 (CVT) */
+ {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)},
+
+ /* Display : 852x480 (GTF) */
+ {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)},
+
+ /* Display : 1024x512 (GTF) */
+ {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
+
+ /* Display : 1024x600 */
+ {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
+
+ /* Display : 1024x576 (GTF) */
+ /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */
+
+ /* Display : 1024x768 */
+ {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
+
+ /* Display : 1152x864 */
+ {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
+
+ /* Display : 1280x768 (GTF) */
+ {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
+
+ /* Display : 960x600 (CVT) */
+ {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)},
+
+ /* Display : 1000x600 (GTF) */
+ {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
+
+ /* Display : 1024x576 (GTF) */
+ {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
+
+ /* Display : 1088x612 (GTF) */
+ {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
+
+ /* Display : 1152x720 (CVT) */
+ {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
+
+ /* Display : 1200x720 (GTF) */
+ {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
+
+ /* Display : 1280x600 (GTF) */
+ {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
+
+ /* Display : 1280x800 (CVT) */
+ {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
+
+ /* Display : 1280x800 (GTF) */
+ /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */
+
+ /* Display : 1280x960 */
+ {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
+
+ /* Display : 1280x1024 */
+ {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
+
+ /* Display : 1360x768 (CVT) */
+ {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
+
+ /* Display : 1360x768 (CVT Reduce Blanking) */
+ {VIA_RES_1360X768_RB, CRTM1360x768_RB,
+ ARRAY_SIZE(CRTM1360x768_RB)},
+
+ /* Display : 1366x768 */
+ {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
+
+ /* Display : 1368x768 (GTF) */
+ /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */
+ /* Display : 1368x768 (GTF) */
+ {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
+
+ /* Display : 1440x900 (CVT) */
+ {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
+
+ /* Display : 1440x900 (CVT Reduce Blanking) */
+ {VIA_RES_1440X900_RB, CRTM1440x900_RB,
+ ARRAY_SIZE(CRTM1440x900_RB)},
+
+ /* Display : 1440x1050 (GTF) */
+ {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
+
+ /* Display : 1400x1050 (CVT Reduce Blanking) */
+ {VIA_RES_1400X1050_RB, CRTM1400x1050_RB,
+ ARRAY_SIZE(CRTM1400x1050_RB)},
+
+ /* Display : 1600x900 (CVT) */
+ {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
+
+ /* Display : 1600x900 (CVT Reduce Blanking) */
+ {VIA_RES_1600X900_RB, CRTM1600x900_RB,
+ ARRAY_SIZE(CRTM1600x900_RB)},
+
+ /* Display : 1600x1024 (GTF) */
+ {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
+
+ /* Display : 1600x1200 */
+ {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
+
+ /* Display : 1680x1050 (CVT) */
+ {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
+
+ /* Display : 1680x1050 (CVT Reduce Blanking) */
+ {VIA_RES_1680X1050_RB, CRTM1680x1050_RB,
+ ARRAY_SIZE(CRTM1680x1050_RB)},
+
+ /* Display : 1792x1344 (DMT) */
+ {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
+
+ /* Display : 1856x1392 (DMT) */
+ {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
+
+ /* Display : 1920x1440 */
+ {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
+
+ /* Display : 2048x1536 */
+ {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
+
+ /* Display : 1280x720 */
+ {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
+
+ /* Display : 1920x1080 (CVT) */
+ {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
+
+ /* Display : 1920x1080 (CVT Reduce Blanking) */
+ {VIA_RES_1920X1080_RB, CRTM1920x1080_RB,
+ ARRAY_SIZE(CRTM1920x1080_RB)},
+
+ /* Display : 1920x1200 (CVT) */
+ {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
+
+ /* Display : 1920x1200 (CVT Reduce Blanking) */
+ {VIA_RES_1920X1200_RB, CRTM1920x1200_RB,
+ ARRAY_SIZE(CRTM1920x1200_RB)},
+
+ /* Display : 1400x1050 (CVT) */
+ {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
+};
+struct crt_mode_table CEAM1280x720[] = {
+ {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
+ M1280X720_CEA_R60_VSP,
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
+};
+struct crt_mode_table CEAM1920x1080[] = {
+ {REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP,
+ M1920X1080_CEA_R60_VSP,
+ /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
+ {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
+};
+struct VideoModeTable CEA_HDMI_Modes[] = {
+ /* Display : 1280x720 */
+ {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
+ {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
+};
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
new file mode 100644
index 00000000000..1a5de50a23a
--- /dev/null
+++ b/drivers/video/via/viamode.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VIAMODE_H__
+#define __VIAMODE_H__
+
+#include "global.h"
+
+struct VPITTable {
+ unsigned char Misc;
+ unsigned char SR[StdSR];
+ unsigned char GR[StdGR];
+ unsigned char AR[StdAR];
+};
+
+struct VideoModeTable {
+ int ModeIndex;
+ struct crt_mode_table *crtc;
+ int mode_array;
+};
+
+struct patch_table {
+ int mode_index;
+ int table_length;
+ struct io_reg *io_reg_table;
+};
+
+struct res_map_refresh {
+ int hres;
+ int vres;
+ int pixclock;
+ int vmode_refresh;
+};
+
+#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl)
+#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes)
+#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs)
+#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs)
+#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs)
+#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs)
+#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs)
+#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs)
+#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table)
+#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes)
+
+/********************/
+/* Mode Table */
+/********************/
+
+/* 480x640 */
+extern struct crt_mode_table CRTM480x640[1];
+/* 640x480*/
+extern struct crt_mode_table CRTM640x480[5];
+/*720x480 (GTF)*/
+extern struct crt_mode_table CRTM720x480[1];
+/*720x576 (GTF)*/
+extern struct crt_mode_table CRTM720x576[1];
+/* 800x480 (CVT) */
+extern struct crt_mode_table CRTM800x480[1];
+/* 800x600*/
+extern struct crt_mode_table CRTM800x600[5];
+/* 848x480 (CVT) */
+extern struct crt_mode_table CRTM848x480[1];
+/*856x480 (GTF) convert to 852x480*/
+extern struct crt_mode_table CRTM852x480[1];
+/*1024x512 (GTF)*/
+extern struct crt_mode_table CRTM1024x512[1];
+/* 1024x600*/
+extern struct crt_mode_table CRTM1024x600[1];
+/* 1024x768*/
+extern struct crt_mode_table CRTM1024x768[4];
+/* 1152x864*/
+extern struct crt_mode_table CRTM1152x864[1];
+/* 1280x720 (HDMI 720P)*/
+extern struct crt_mode_table CRTM1280x720[2];
+/*1280x768 (GTF)*/
+extern struct crt_mode_table CRTM1280x768[2];
+/* 1280x800 (CVT) */
+extern struct crt_mode_table CRTM1280x800[1];
+/*1280x960*/
+extern struct crt_mode_table CRTM1280x960[1];
+/* 1280x1024*/
+extern struct crt_mode_table CRTM1280x1024[3];
+/* 1368x768 (GTF) */
+extern struct crt_mode_table CRTM1368x768[1];
+/*1440x1050 (GTF)*/
+extern struct crt_mode_table CRTM1440x1050[1];
+/* 1600x1200*/
+extern struct crt_mode_table CRTM1600x1200[2];
+/* 1680x1050 (CVT) */
+extern struct crt_mode_table CRTM1680x1050[2];
+/* 1680x1050 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1680x1050_RB[1];
+/* 1920x1080 (CVT)*/
+extern struct crt_mode_table CRTM1920x1080[1];
+/* 1920x1080 (CVT with Reduce Blanking) */
+extern struct crt_mode_table CRTM1920x1080_RB[1];
+/* 1920x1440*/
+extern struct crt_mode_table CRTM1920x1440[2];
+/* 1400x1050 (CVT) */
+extern struct crt_mode_table CRTM1400x1050[2];
+/* 1400x1050 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1400x1050_RB[1];
+/* 960x600 (CVT) */
+extern struct crt_mode_table CRTM960x600[1];
+/* 1000x600 (GTF) */
+extern struct crt_mode_table CRTM1000x600[1];
+/* 1024x576 (GTF) */
+extern struct crt_mode_table CRTM1024x576[1];
+/* 1088x612 (CVT) */
+extern struct crt_mode_table CRTM1088x612[1];
+/* 1152x720 (CVT) */
+extern struct crt_mode_table CRTM1152x720[1];
+/* 1200x720 (GTF) */
+extern struct crt_mode_table CRTM1200x720[1];
+/* 1280x600 (GTF) */
+extern struct crt_mode_table CRTM1280x600[1];
+/* 1360x768 (CVT) */
+extern struct crt_mode_table CRTM1360x768[1];
+/* 1360x768 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1360x768_RB[1];
+/* 1366x768 (GTF) */
+extern struct crt_mode_table CRTM1366x768[2];
+/* 1440x900 (CVT) */
+extern struct crt_mode_table CRTM1440x900[2];
+/* 1440x900 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1440x900_RB[1];
+/* 1600x900 (CVT) */
+extern struct crt_mode_table CRTM1600x900[1];
+/* 1600x900 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1600x900_RB[1];
+/* 1600x1024 (GTF) */
+extern struct crt_mode_table CRTM1600x1024[1];
+/* 1792x1344 (DMT) */
+extern struct crt_mode_table CRTM1792x1344[1];
+/* 1856x1392 (DMT) */
+extern struct crt_mode_table CRTM1856x1392[1];
+/* 1920x1200 (CVT) */
+extern struct crt_mode_table CRTM1920x1200[1];
+/* 1920x1200 (CVT with Reduce Blanking) */
+extern struct crt_mode_table CRTM1920x1200_RB[1];
+/* 2048x1536 (CVT) */
+extern struct crt_mode_table CRTM2048x1536[1];
+extern struct VideoModeTable CLE266Modes[47];
+extern struct crt_mode_table CEAM1280x720[1];
+extern struct crt_mode_table CEAM1920x1080[1];
+extern struct VideoModeTable CEA_HDMI_Modes[2];
+
+extern struct res_map_refresh res_map_refresh_tbl[61];
+extern struct io_reg CN400_ModeXregs[52];
+extern struct io_reg CN700_ModeXregs[66];
+extern struct io_reg KM400_ModeXregs[55];
+extern struct io_reg CX700_ModeXregs[58];
+extern struct io_reg VX800_ModeXregs[58];
+extern struct io_reg CLE266_ModeXregs[32];
+extern struct io_reg PM1024x768[2];
+extern struct patch_table res_patch_table[1];
+extern struct VPITTable VPIT;
+#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
new file mode 100644
index 00000000000..322a9f99355
--- /dev/null
+++ b/drivers/video/via/vt1636.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+ u8 index)
+{
+ u8 data;
+
+ viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
+ viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
+
+ return data;
+}
+
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information
+ *plvds_chip_info, struct IODATA io_data)
+{
+ int index, data;
+
+ viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
+
+ index = io_data.Index;
+ data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
+ index);
+ data = (data & (~io_data.Mask)) | io_data.Data;
+
+ viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data);
+}
+
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+ int reg_num, i;
+
+ /* Common settings: */
+ reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
+
+ for (i = 0; i < reg_num; i++) {
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info,
+ COMMON_INIT_TBL_VT1636[i]);
+ }
+
+ /* Input Data Mode Select */
+ if (plvds_setting_info->device_lcd_dualedge) {
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info,
+ DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
+ } else {
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info,
+ SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
+ }
+
+ if (plvds_setting_info->LCDDithering) {
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info,
+ DITHERING_ENABLE_TBL_VT1636[0]);
+ } else {
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info,
+ DITHERING_DISABLE_TBL_VT1636[0]);
+ }
+}
+
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+ VDD_ON_TBL_VT1636[0]);
+
+ /* Pad on: */
+ switch (plvds_chip_info->output_interface) {
+ case INTERFACE_DVP0:
+ {
+ viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
+ break;
+ }
+
+ case INTERFACE_DVP1:
+ {
+ viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
+ break;
+ }
+
+ case INTERFACE_DFP_LOW:
+ {
+ viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
+ break;
+ }
+
+ case INTERFACE_DFP_HIGH:
+ {
+ viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
+ break;
+ }
+
+ }
+}
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+ VDD_OFF_TBL_VT1636[0]);
+
+ /* Pad off: */
+ switch (plvds_chip_info->output_interface) {
+ case INTERFACE_DVP0:
+ {
+ viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
+ break;
+ }
+
+ case INTERFACE_DVP1:
+ {
+ viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
+ break;
+ }
+
+ case INTERFACE_DFP_LOW:
+ {
+ viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
+ break;
+ }
+
+ case INTERFACE_DFP_HIGH:
+ {
+ viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
+ break;
+ }
+
+ }
+}
+
+bool viafb_lvds_identify_vt1636(void)
+{
+ u8 Buffer[2];
+
+ DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
+
+ /* Sense VT1636 LVDS Transmiter */
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+ VT1636_LVDS_I2C_ADDR;
+
+ /* Check vendor ID first: */
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_slave_addr,
+ 0x00, &Buffer[0]);
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_slave_addr,
+ 0x01, &Buffer[1]);
+
+ if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
+ return false;
+
+ /* Check Chip ID: */
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_slave_addr,
+ 0x02, &Buffer[0]);
+ viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+ lvds_chip_slave_addr,
+ 0x03, &Buffer[1]);
+ if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
+ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+ VT1636_LVDS;
+ return true;
+ }
+
+ return false;
+}
+
+static int get_clk_range_index(u32 Clk)
+{
+ if (Clk < DPA_CLK_30M)
+ return DPA_CLK_RANGE_30M;
+ else if (Clk < DPA_CLK_50M)
+ return DPA_CLK_RANGE_30_50M;
+ else if (Clk < DPA_CLK_70M)
+ return DPA_CLK_RANGE_50_70M;
+ else if (Clk < DPA_CLK_100M)
+ return DPA_CLK_RANGE_70_100M;
+ else if (Clk < DPA_CLK_150M)
+ return DPA_CLK_RANGE_100_150M;
+ else
+ return DPA_CLK_RANGE_150M;
+}
+
+static int get_lvds_dpa_setting_index(int panel_size_id,
+ struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
+ int tbl_size)
+{
+ int i;
+
+ for (i = 0; i < tbl_size; i++) {
+ if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
+ return i;
+
+ p_vt1636_dpasetting_tbl++;
+ }
+
+ return 0;
+}
+
+static void set_dpa_vt1636(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+ struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
+{
+ struct IODATA io_data;
+
+ io_data.Index = 0x09;
+ io_data.Mask = 0x1F;
+ io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+ plvds_chip_info, io_data);
+
+ io_data.Index = 0x08;
+ io_data.Mask = 0x0F;
+ io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
+ viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+ io_data);
+}
+
+void viafb_vt1636_patch_skew_on_vt3324(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ int index, size;
+
+ DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
+
+ /* Graphics DPA settings: */
+ index = get_clk_range_index(plvds_setting_info->vclk);
+ viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+ &GFX_DPA_SETTING_TBL_VT3324[index]);
+
+ /* LVDS Transmitter DPA settings: */
+ size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
+ index =
+ get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
+ VT1636_DPA_SETTING_TBL_VT3324, size);
+ set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
+ &VT1636_DPA_SETTING_TBL_VT3324[index]);
+}
+
+void viafb_vt1636_patch_skew_on_vt3327(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ int index, size;
+
+ DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
+
+ /* Graphics DPA settings: */
+ index = get_clk_range_index(plvds_setting_info->vclk);
+ viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+ &GFX_DPA_SETTING_TBL_VT3327[index]);
+
+ /* LVDS Transmitter DPA settings: */
+ size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
+ index =
+ get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
+ VT1636_DPA_SETTING_TBL_VT3327, size);
+ set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
+ &VT1636_DPA_SETTING_TBL_VT3327[index]);
+}
+
+void viafb_vt1636_patch_skew_on_vt3364(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
+{
+ int index;
+
+ DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
+
+ /* Graphics DPA settings: */
+ index = get_clk_range_index(plvds_setting_info->vclk);
+ viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+ &GFX_DPA_SETTING_TBL_VT3364[index]);
+}
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h
new file mode 100644
index 00000000000..2a150c58c7e
--- /dev/null
+++ b/drivers/video/via/vt1636.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. 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, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _VT1636_H_
+#define _VT1636_H_
+#include "chip.h"
+bool viafb_lvds_identify_vt1636(void);
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+ *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3324(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3327(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3364(
+ struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
+
+#endif
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 47ed39b52f9..a463b3dd837 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -680,11 +680,11 @@ static struct xenbus_driver xenfb = {
static int __init xenfb_init(void)
{
- if (!is_running_on_xen())
+ if (!xen_domain())
return -ENODEV;
/* Nothing to do if running in dom0. */
- if (is_initial_xendomain())
+ if (xen_initial_domain())
return -ENODEV;
return xenbus_register_frontend(&xenfb);
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 10211e49300..29e144f81cb 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -160,8 +160,10 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data)
* 625 us - 60 us - 240 us - 100 ns = 324.9 us
*
* We'll wait a bit longer just to be sure.
+ * Was udelay(500), but if it is going to busywait the cpu that long,
+ * might as well come back later.
*/
- udelay(500);
+ msleep(1);
ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD |
@@ -274,8 +276,8 @@ static u8 ds1wm_reset_bus(void *data)
return 0;
}
-static void ds1wm_search(void *data, u8 search_type,
- w1_slave_found_callback slave_found)
+static void ds1wm_search(void *data, struct w1_master *master_dev,
+ u8 search_type, w1_slave_found_callback slave_found)
{
struct ds1wm_data *ds1wm_data = data;
int i;
@@ -313,7 +315,7 @@ static void ds1wm_search(void *data, u8 search_type,
ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA);
ds1wm_reset(ds1wm_data);
- slave_found(ds1wm_data, rom_id);
+ slave_found(master_dev, rom_id);
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index b63b5e044a4..59ad6e95af8 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -88,7 +88,7 @@
#define COMM_DT 0x2000
#define COMM_SPU 0x1000
#define COMM_F 0x0800
-#define COMM_NTP 0x0400
+#define COMM_NTF 0x0400
#define COMM_ICP 0x0200
#define COMM_RST 0x0100
@@ -98,11 +98,6 @@
#define BRANCH_MAIN 0xCC
#define BRANCH_AUX 0x33
-/*
- * Duration of the strong pull-up pulse in milliseconds.
- */
-#define PULLUP_PULSE_DURATION 750
-
/* Status flags */
#define ST_SPUA 0x01 /* Strong Pull-up is active */
#define ST_PRGA 0x02 /* 12V programming pulse is being generated */
@@ -112,6 +107,17 @@
#define ST_IDLE 0x20 /* DS2490 is currently idle */
#define ST_EPOF 0x80
+/* Result Register flags */
+#define RR_DETECT 0xA5 /* New device detected */
+#define RR_NRS 0x01 /* Reset no presence or ... */
+#define RR_SH 0x02 /* short on reset or set path */
+#define RR_APP 0x04 /* alarming presence on reset */
+#define RR_VPP 0x08 /* 12V expected not seen */
+#define RR_CMP 0x10 /* compare error */
+#define RR_CRC 0x20 /* CRC error detected */
+#define RR_RDP 0x40 /* redirected page */
+#define RR_EOS 0x80 /* end of search error */
+
#define SPEED_NORMAL 0x00
#define SPEED_FLEXIBLE 0x01
#define SPEED_OVERDRIVE 0x02
@@ -131,6 +137,15 @@ struct ds_device
int ep[NUM_EP];
+ /* Strong PullUp
+ * 0: pullup not active, else duration in milliseconds
+ */
+ int spu_sleep;
+ /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup
+ * should be active or not for writes.
+ */
+ u16 spu_bit;
+
struct w1_bus_master master;
};
@@ -164,7 +179,6 @@ MODULE_DEVICE_TABLE(usb, ds_id_table);
static int ds_probe(struct usb_interface *, const struct usb_device_id *);
static void ds_disconnect(struct usb_interface *);
-static inline void ds_dump_status(unsigned char *, unsigned char *, int);
static int ds_send_control(struct ds_device *, u16, u16);
static int ds_send_control_cmd(struct ds_device *, u16, u16);
@@ -192,7 +206,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
return err;
}
-#if 0
+
static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
{
int err;
@@ -207,7 +221,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
return err;
}
-#endif
+
static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
{
int err;
@@ -223,11 +237,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
return err;
}
-static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
-{
- printk("%45s: %8x\n", str, buf[off]);
-}
-
static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
unsigned char *buf, int size)
{
@@ -248,62 +257,81 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
return count;
}
-static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off)
{
- unsigned char buf[64];
- int count, err = 0, i;
-
- memcpy(st, buf, sizeof(*st));
+ printk(KERN_INFO "%45s: %8x\n", str, buf[off]);
+}
- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
- if (count < 0)
- return err;
+static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count)
+{
+ int i;
- printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+ printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
for (i=0; i<count; ++i)
printk("%02x ", buf[i]);
- printk("\n");
+ printk(KERN_INFO "\n");
if (count >= 16) {
- ds_dump_status(buf, "enable flag", 0);
- ds_dump_status(buf, "1-wire speed", 1);
- ds_dump_status(buf, "strong pullup duration", 2);
- ds_dump_status(buf, "programming pulse duration", 3);
- ds_dump_status(buf, "pulldown slew rate control", 4);
- ds_dump_status(buf, "write-1 low time", 5);
- ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
- ds_dump_status(buf, "reserved (test register)", 7);
- ds_dump_status(buf, "device status flags", 8);
- ds_dump_status(buf, "communication command byte 1", 9);
- ds_dump_status(buf, "communication command byte 2", 10);
- ds_dump_status(buf, "communication command buffer status", 11);
- ds_dump_status(buf, "1-wire data output buffer status", 12);
- ds_dump_status(buf, "1-wire data input buffer status", 13);
- ds_dump_status(buf, "reserved", 14);
- ds_dump_status(buf, "reserved", 15);
+ ds_print_msg(buf, "enable flag", 0);
+ ds_print_msg(buf, "1-wire speed", 1);
+ ds_print_msg(buf, "strong pullup duration", 2);
+ ds_print_msg(buf, "programming pulse duration", 3);
+ ds_print_msg(buf, "pulldown slew rate control", 4);
+ ds_print_msg(buf, "write-1 low time", 5);
+ ds_print_msg(buf, "data sample offset/write-0 recovery time",
+ 6);
+ ds_print_msg(buf, "reserved (test register)", 7);
+ ds_print_msg(buf, "device status flags", 8);
+ ds_print_msg(buf, "communication command byte 1", 9);
+ ds_print_msg(buf, "communication command byte 2", 10);
+ ds_print_msg(buf, "communication command buffer status", 11);
+ ds_print_msg(buf, "1-wire data output buffer status", 12);
+ ds_print_msg(buf, "1-wire data input buffer status", 13);
+ ds_print_msg(buf, "reserved", 14);
+ ds_print_msg(buf, "reserved", 15);
}
-
- memcpy(st, buf, sizeof(*st));
-
- if (st->status & ST_EPOF) {
- printk(KERN_INFO "Resetting device after ST_EPOF.\n");
- err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
- if (err)
- return err;
- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
- if (count < 0)
- return err;
- }
-#if 0
- if (st->status & ST_IDLE) {
- printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
- err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
- if (err)
- return err;
+ for (i = 16; i < count; ++i) {
+ if (buf[i] == RR_DETECT) {
+ ds_print_msg(buf, "new device detect", i);
+ continue;
+ }
+ ds_print_msg(buf, "Result Register Value: ", i);
+ if (buf[i] & RR_NRS)
+ printk(KERN_INFO "NRS: Reset no presence or ...\n");
+ if (buf[i] & RR_SH)
+ printk(KERN_INFO "SH: short on reset or set path\n");
+ if (buf[i] & RR_APP)
+ printk(KERN_INFO "APP: alarming presence on reset\n");
+ if (buf[i] & RR_VPP)
+ printk(KERN_INFO "VPP: 12V expected not seen\n");
+ if (buf[i] & RR_CMP)
+ printk(KERN_INFO "CMP: compare error\n");
+ if (buf[i] & RR_CRC)
+ printk(KERN_INFO "CRC: CRC error detected\n");
+ if (buf[i] & RR_RDP)
+ printk(KERN_INFO "RDP: redirected page\n");
+ if (buf[i] & RR_EOS)
+ printk(KERN_INFO "EOS: end of search error\n");
}
-#endif
+}
- return err;
+static void ds_reset_device(struct ds_device *dev)
+{
+ ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+ /* Always allow strong pullup which allow individual writes to use
+ * the strong pullup.
+ */
+ if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE))
+ printk(KERN_ERR "ds_reset_device: "
+ "Error allowing strong pullup\n");
+ /* Chip strong pullup time was cleared. */
+ if (dev->spu_sleep) {
+ /* lower 4 bits are 0, see ds_set_pullup */
+ u8 del = dev->spu_sleep>>4;
+ if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del))
+ printk(KERN_ERR "ds_reset_device: "
+ "Error setting duration\n");
+ }
}
static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
@@ -311,13 +339,27 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
int count, err;
struct ds_status st;
+ /* Careful on size. If size is less than what is available in
+ * the input buffer, the device fails the bulk transfer and
+ * clears the input buffer. It could read the maximum size of
+ * the data buffer, but then do you return the first, last, or
+ * some set of the middle size bytes? As long as the rest of
+ * the code is correct there will be size bytes waiting. A
+ * call to ds_wait_status will wait until the device is idle
+ * and any data to be received would have been available.
+ */
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
buf, size, &count, 1000);
if (err < 0) {
+ u8 buf[0x20];
+ int count;
+
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
- ds_recv_status(dev, &st);
+
+ count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+ ds_dump_status(dev, buf, count);
return err;
}
@@ -341,7 +383,8 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
count = 0;
err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+ printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: "
+ "err=%d.\n", dev->ep[EP_DATA_OUT], err);
return err;
}
@@ -397,7 +440,7 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
if (err)
return err;
- err = ds_recv_status(dev, st);
+ err = ds_dump_status(dev, st);
return err;
}
@@ -420,33 +463,49 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
printk("\n");
}
#endif
- } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+ } while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100);
+
+ if (err >= 16 && st->status & ST_EPOF) {
+ printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+ ds_reset_device(dev);
+ /* Always dump the device status. */
+ count = 101;
+ }
+ /* Dump the status for errors or if there is extended return data.
+ * The extended status includes new device detection (maybe someone
+ * can do something with it).
+ */
+ if (err > 16 || count >= 100 || err < 0)
+ ds_dump_status(dev, buf, err);
- if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
- ds_recv_status(dev, st);
+ /* Extended data isn't an error. Well, a short is, but the dump
+ * would have already told the user that and we can't do anything
+ * about it in software anyway.
+ */
+ if (count >= 100 || err < 0)
return -1;
- } else
+ else
return 0;
}
-static int ds_reset(struct ds_device *dev, struct ds_status *st)
+static int ds_reset(struct ds_device *dev)
{
int err;
- //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
- err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+ /* Other potentionally interesting flags for reset.
+ *
+ * COMM_NTF: Return result register feedback. This could be used to
+ * detect some conditions such as short, alarming presence, or
+ * detect if a new device was detected.
+ *
+ * COMM_SE which allows SPEED_NORMAL, SPEED_FLEXIBLE, SPEED_OVERDRIVE:
+ * Select the data transfer rate.
+ */
+ err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_IM, SPEED_NORMAL);
if (err)
return err;
- ds_wait_status(dev, st);
-#if 0
- if (st->command_buffer_status) {
- printk(KERN_INFO "Short circuit.\n");
- return -EIO;
- }
-#endif
-
return 0;
}
@@ -471,60 +530,43 @@ static int ds_set_speed(struct ds_device *dev, int speed)
}
#endif /* 0 */
-static int ds_start_pulse(struct ds_device *dev, int delay)
+static int ds_set_pullup(struct ds_device *dev, int delay)
{
- int err;
+ int err = 0;
u8 del = 1 + (u8)(delay >> 4);
- struct ds_status st;
-
-#if 0
- err = ds_stop_pulse(dev, 10);
- if (err)
+ /* Just storing delay would not get the trunication and roundup. */
+ int ms = del<<4;
+
+ /* Enable spu_bit if a delay is set. */
+ dev->spu_bit = delay ? COMM_SPU : 0;
+ /* If delay is zero, it has already been disabled, if the time is
+ * the same as the hardware was last programmed to, there is also
+ * nothing more to do. Compare with the recalculated value ms
+ * rather than del or delay which can have a different value.
+ */
+ if (delay == 0 || ms == dev->spu_sleep)
return err;
- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
- if (err)
- return err;
-#endif
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
if (err)
return err;
- err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
- if (err)
- return err;
-
- mdelay(delay);
-
- ds_wait_status(dev, &st);
+ dev->spu_sleep = ms;
return err;
}
static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
{
- int err, count;
+ int err;
struct ds_status st;
- u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
- u16 cmd;
- err = ds_send_control(dev, value, 0);
+ err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0),
+ 0);
if (err)
return err;
- count = 0;
- do {
- err = ds_wait_status(dev, &st);
- if (err)
- return err;
-
- cmd = st.command0 | (st.command1 << 8);
- } while (cmd != value && ++count < 10);
-
- if (err < 0 || count >= 10) {
- printk(KERN_ERR "Failed to obtain status.\n");
- return -EINVAL;
- }
+ ds_wait_status(dev, &st);
err = ds_recv_data(dev, tbit, sizeof(*tbit));
if (err < 0)
@@ -533,12 +575,18 @@ static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
return 0;
}
+#if 0
static int ds_write_bit(struct ds_device *dev, u8 bit)
{
int err;
struct ds_status st;
- err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+ /* Set COMM_ICP to write without a readback. Note, this will
+ * produce one time slot, a down followed by an up with COMM_D
+ * only determing the timing.
+ */
+ err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP |
+ (bit ? COMM_D : 0), 0);
if (err)
return err;
@@ -546,6 +594,7 @@ static int ds_write_bit(struct ds_device *dev, u8 bit)
return 0;
}
+#endif
static int ds_write_byte(struct ds_device *dev, u8 byte)
{
@@ -553,10 +602,13 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
struct ds_status st;
u8 rbyte;
- err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+ err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
if (err)
return err;
+ if (dev->spu_bit)
+ msleep(dev->spu_sleep);
+
err = ds_wait_status(dev, &st);
if (err)
return err;
@@ -565,8 +617,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
if (err < 0)
return err;
- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
return !(byte == rbyte);
}
@@ -602,7 +652,7 @@ static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
if (err < 0)
return err;
- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len);
if (err)
return err;
@@ -623,20 +673,19 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
if (err < 0)
return err;
- ds_wait_status(dev, &st);
-
- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len);
if (err)
return err;
+ if (dev->spu_bit)
+ msleep(dev->spu_sleep);
+
ds_wait_status(dev, &st);
err = ds_recv_data(dev, buf, len);
if (err < 0)
return err;
- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
return !(err == len);
}
@@ -728,6 +777,7 @@ static u8 ds9490r_touch_bit(void *data, u8 bit)
return ret;
}
+#if 0
static void ds9490r_write_bit(void *data, u8 bit)
{
struct ds_device *dev = data;
@@ -735,13 +785,6 @@ static void ds9490r_write_bit(void *data, u8 bit)
ds_write_bit(dev, bit);
}
-static void ds9490r_write_byte(void *data, u8 byte)
-{
- struct ds_device *dev = data;
-
- ds_write_byte(dev, byte);
-}
-
static u8 ds9490r_read_bit(void *data)
{
struct ds_device *dev = data;
@@ -754,6 +797,14 @@ static u8 ds9490r_read_bit(void *data)
return bit & 1;
}
+#endif
+
+static void ds9490r_write_byte(void *data, u8 byte)
+{
+ struct ds_device *dev = data;
+
+ ds_write_byte(dev, byte);
+}
static u8 ds9490r_read_byte(void *data)
{
@@ -790,31 +841,58 @@ static u8 ds9490r_read_block(void *data, u8 *buf, int len)
static u8 ds9490r_reset(void *data)
{
struct ds_device *dev = data;
- struct ds_status st;
int err;
- memset(&st, 0, sizeof(st));
-
- err = ds_reset(dev, &st);
+ err = ds_reset(dev);
if (err)
return 1;
return 0;
}
+static u8 ds9490r_set_pullup(void *data, int delay)
+{
+ struct ds_device *dev = data;
+
+ if (ds_set_pullup(dev, delay))
+ return 1;
+
+ return 0;
+}
+
static int ds_w1_init(struct ds_device *dev)
{
memset(&dev->master, 0, sizeof(struct w1_bus_master));
+ /* Reset the device as it can be in a bad state.
+ * This is necessary because a block write will wait for data
+ * to be placed in the output buffer and block any later
+ * commands which will keep accumulating and the device will
+ * not be idle. Another case is removing the ds2490 module
+ * while a bus search is in progress, somehow a few commands
+ * get through, but the input transfers fail leaving data in
+ * the input buffer. This will cause the next read to fail
+ * see the note in ds_recv_data.
+ */
+ ds_reset_device(dev);
+
dev->master.data = dev;
dev->master.touch_bit = &ds9490r_touch_bit;
+ /* read_bit and write_bit in w1_bus_master are expected to set and
+ * sample the line level. For write_bit that means it is expected to
+ * set it to that value and leave it there. ds2490 only supports an
+ * individual time slot at the lowest level. The requirement from
+ * pulling the bus state down to reading the state is 15us, something
+ * that isn't realistic on the USB bus anyway.
dev->master.read_bit = &ds9490r_read_bit;
dev->master.write_bit = &ds9490r_write_bit;
+ */
dev->master.read_byte = &ds9490r_read_byte;
dev->master.write_byte = &ds9490r_write_byte;
dev->master.read_block = &ds9490r_read_block;
dev->master.write_block = &ds9490r_write_block;
dev->master.reset_bus = &ds9490r_reset;
+ dev->master.set_pullup = &ds9490r_set_pullup;
return w1_add_master_device(&dev->master);
}
@@ -838,6 +916,8 @@ static int ds_probe(struct usb_interface *intf,
printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
return -ENOMEM;
}
+ dev->spu_sleep = 0;
+ dev->spu_bit = 0;
dev->udev = usb_get_dev(udev);
if (!dev->udev) {
err = -ENOMEM;
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
new file mode 100644
index 00000000000..2c6c0cf6a20
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2431.c
@@ -0,0 +1,312 @@
+/*
+ * w1_ds2431.c - w1 family 2d (DS2431) driver
+ *
+ * Copyright (c) 2008 Bernhard Weirich <bernhard.weirich@riedel.net>
+ *
+ * Heavily inspired by w1_DS2433 driver from Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+
+#define W1_F2D_EEPROM_SIZE 128
+#define W1_F2D_PAGE_COUNT 4
+#define W1_F2D_PAGE_BITS 5
+#define W1_F2D_PAGE_SIZE (1<<W1_F2D_PAGE_BITS)
+#define W1_F2D_PAGE_MASK 0x1F
+
+#define W1_F2D_SCRATCH_BITS 3
+#define W1_F2D_SCRATCH_SIZE (1<<W1_F2D_SCRATCH_BITS)
+#define W1_F2D_SCRATCH_MASK (W1_F2D_SCRATCH_SIZE-1)
+
+#define W1_F2D_READ_EEPROM 0xF0
+#define W1_F2D_WRITE_SCRATCH 0x0F
+#define W1_F2D_READ_SCRATCH 0xAA
+#define W1_F2D_COPY_SCRATCH 0x55
+
+
+#define W1_F2D_TPROG_MS 11
+
+#define W1_F2D_READ_RETRIES 10
+#define W1_F2D_READ_MAXLEN 8
+
+/*
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f2d_fix_count(loff_t off, size_t count, size_t size)
+{
+ if (off > size)
+ return 0;
+
+ if ((off + count) > size)
+ return size - off;
+
+ return count;
+}
+
+/*
+ * Read a block from W1 ROM two times and compares the results.
+ * If they are equal they are returned, otherwise the read
+ * is repeated W1_F2D_READ_RETRIES times.
+ *
+ * count must not exceed W1_F2D_READ_MAXLEN.
+ */
+static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
+{
+ u8 wrbuf[3];
+ u8 cmp[W1_F2D_READ_MAXLEN];
+ int tries = W1_F2D_READ_RETRIES;
+
+ do {
+ wrbuf[0] = W1_F2D_READ_EEPROM;
+ wrbuf[1] = off & 0xff;
+ wrbuf[2] = off >> 8;
+
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, buf, count);
+
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, cmp, count);
+
+ if (!memcmp(cmp, buf, count))
+ return 0;
+ } while (--tries);
+
+ dev_err(&sl->dev, "proof reading failed %d times\n",
+ W1_F2D_READ_RETRIES);
+
+ return -1;
+}
+
+static ssize_t w1_f2d_read_bin(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ int todo = count;
+
+ count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE);
+ if (count == 0)
+ return 0;
+
+ mutex_lock(&sl->master->mutex);
+
+ /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */
+ while (todo > 0) {
+ int block_read;
+
+ if (todo >= W1_F2D_READ_MAXLEN)
+ block_read = W1_F2D_READ_MAXLEN;
+ else
+ block_read = todo;
+
+ if (w1_f2d_readblock(sl, off, block_read, buf) < 0)
+ count = -EIO;
+
+ todo -= W1_F2D_READ_MAXLEN;
+ buf += W1_F2D_READ_MAXLEN;
+ off += W1_F2D_READ_MAXLEN;
+ }
+
+ mutex_unlock(&sl->master->mutex);
+
+ return count;
+}
+
+/*
+ * Writes to the scratchpad and reads it back for verification.
+ * Then copies the scratchpad to EEPROM.
+ * The data must be aligned at W1_F2D_SCRATCH_SIZE bytes and
+ * must be W1_F2D_SCRATCH_SIZE bytes long.
+ * The master must be locked.
+ *
+ * @param sl The slave structure
+ * @param addr Address for the write
+ * @param len length must be <= (W1_F2D_PAGE_SIZE - (addr & W1_F2D_PAGE_MASK))
+ * @param data The data to write
+ * @return 0=Success -1=failure
+ */
+static int w1_f2d_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+{
+ int tries = W1_F2D_READ_RETRIES;
+ u8 wrbuf[4];
+ u8 rdbuf[W1_F2D_SCRATCH_SIZE + 3];
+ u8 es = (addr + len - 1) % W1_F2D_SCRATCH_SIZE;
+
+retry:
+
+ /* Write the data to the scratchpad */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F2D_WRITE_SCRATCH;
+ wrbuf[1] = addr & 0xff;
+ wrbuf[2] = addr >> 8;
+
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_write_block(sl->master, data, len);
+
+ /* Read the scratchpad and verify */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ w1_write_8(sl->master, W1_F2D_READ_SCRATCH);
+ w1_read_block(sl->master, rdbuf, len + 3);
+
+ /* Compare what was read against the data written */
+ if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
+ (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) {
+
+ if (--tries)
+ goto retry;
+
+ dev_err(&sl->dev,
+ "could not write to eeprom, scratchpad compare failed %d times\n",
+ W1_F2D_READ_RETRIES);
+
+ return -1;
+ }
+
+ /* Copy the scratchpad to EEPROM */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F2D_COPY_SCRATCH;
+ wrbuf[3] = es;
+ w1_write_block(sl->master, wrbuf, 4);
+
+ /* Sleep for tprog ms to wait for the write to complete */
+ msleep(W1_F2D_TPROG_MS);
+
+ /* Reset the bus to wake up the EEPROM */
+ w1_reset_bus(sl->master);
+
+ return 0;
+}
+
+static ssize_t w1_f2d_write_bin(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ int addr, len;
+ int copy;
+
+ count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE);
+ if (count == 0)
+ return 0;
+
+ mutex_lock(&sl->master->mutex);
+
+ /* Can only write data in blocks of the size of the scratchpad */
+ addr = off;
+ len = count;
+ while (len > 0) {
+
+ /* if len too short or addr not aligned */
+ if (len < W1_F2D_SCRATCH_SIZE || addr & W1_F2D_SCRATCH_MASK) {
+ char tmp[W1_F2D_SCRATCH_SIZE];
+
+ /* read the block and update the parts to be written */
+ if (w1_f2d_readblock(sl, addr & ~W1_F2D_SCRATCH_MASK,
+ W1_F2D_SCRATCH_SIZE, tmp)) {
+ count = -EIO;
+ goto out_up;
+ }
+
+ /* copy at most to the boundary of the PAGE or len */
+ copy = W1_F2D_SCRATCH_SIZE -
+ (addr & W1_F2D_SCRATCH_MASK);
+
+ if (copy > len)
+ copy = len;
+
+ memcpy(&tmp[addr & W1_F2D_SCRATCH_MASK], buf, copy);
+ if (w1_f2d_write(sl, addr & ~W1_F2D_SCRATCH_MASK,
+ W1_F2D_SCRATCH_SIZE, tmp) < 0) {
+ count = -EIO;
+ goto out_up;
+ }
+ } else {
+
+ copy = W1_F2D_SCRATCH_SIZE;
+ if (w1_f2d_write(sl, addr, copy, buf) < 0) {
+ count = -EIO;
+ goto out_up;
+ }
+ }
+ buf += copy;
+ addr += copy;
+ len -= copy;
+ }
+
+out_up:
+ mutex_unlock(&sl->master->mutex);
+
+ return count;
+}
+
+static struct bin_attribute w1_f2d_bin_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = W1_F2D_EEPROM_SIZE,
+ .read = w1_f2d_read_bin,
+ .write = w1_f2d_write_bin,
+};
+
+static int w1_f2d_add_slave(struct w1_slave *sl)
+{
+ return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
+}
+
+static void w1_f2d_remove_slave(struct w1_slave *sl)
+{
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
+}
+
+static struct w1_family_ops w1_f2d_fops = {
+ .add_slave = w1_f2d_add_slave,
+ .remove_slave = w1_f2d_remove_slave,
+};
+
+static struct w1_family w1_family_2d = {
+ .fid = W1_EEPROM_DS2431,
+ .fops = &w1_f2d_fops,
+};
+
+static int __init w1_f2d_init(void)
+{
+ return w1_register_family(&w1_family_2d);
+}
+
+static void __exit w1_f2d_fini(void)
+{
+ w1_unregister_family(&w1_family_2d);
+}
+
+module_init(w1_f2d_init);
+module_exit(w1_f2d_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bernhard Weirich <bernhard.weirich@riedel.net>");
+MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM");
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index fb28acaeed6..2c8dff9f77d 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -37,31 +37,33 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
+/* Allow the strong pullup to be disabled, but default to enabled.
+ * If it was disabled a parasite powered device might not get the require
+ * current to do a temperature conversion. If it is enabled parasite powered
+ * devices have a better chance of getting the current required.
+ */
+static int w1_strong_pullup = 1;
+module_param_named(strong_pullup, w1_strong_pullup, int, 0);
+
static u8 bad_roms[][9] = {
{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
{}
};
-static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
- char *, loff_t, size_t);
+static ssize_t w1_therm_read(struct device *device,
+ struct device_attribute *attr, char *buf);
-static struct bin_attribute w1_therm_bin_attr = {
- .attr = {
- .name = "w1_slave",
- .mode = S_IRUGO,
- },
- .size = W1_SLAVE_DATA_SIZE,
- .read = w1_therm_read_bin,
-};
+static struct device_attribute w1_therm_attr =
+ __ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL);
static int w1_therm_add_slave(struct w1_slave *sl)
{
- return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+ return device_create_file(&sl->dev, &w1_therm_attr);
}
static void w1_therm_remove_slave(struct w1_slave *sl)
{
- sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+ device_remove_file(&sl->dev, &w1_therm_attr);
}
static struct w1_family_ops w1_therm_fops = {
@@ -160,30 +162,19 @@ static int w1_therm_check_rom(u8 rom[9])
return 0;
}
-static ssize_t w1_therm_read_bin(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+static ssize_t w1_therm_read(struct device *device,
+ struct device_attribute *attr, char *buf)
{
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ struct w1_slave *sl = dev_to_w1_slave(device);
struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict;
int i, max_trying = 10;
+ ssize_t c = PAGE_SIZE;
- mutex_lock(&sl->master->mutex);
+ mutex_lock(&dev->mutex);
- if (off > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
- if (off + count > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
-
- memset(buf, 0, count);
memset(rom, 0, sizeof(rom));
- count = 0;
verdict = 0;
crc = 0;
@@ -192,15 +183,20 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj,
int count = 0;
unsigned int tm = 750;
+ /* 750ms strong pullup (or delay) after the convert */
+ if (w1_strong_pullup)
+ w1_next_pullup(dev, tm);
w1_write_8(dev, W1_CONVERT_TEMP);
-
- msleep(tm);
+ if (!w1_strong_pullup)
+ msleep(tm);
if (!w1_reset_select_slave(sl)) {
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
- dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+ dev_warn(device, "w1_read_block() "
+ "returned %u instead of 9.\n",
+ count);
}
crc = w1_calc_crc8(rom, 8);
@@ -215,22 +211,22 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj,
}
for (i = 0; i < 9; ++i)
- count += sprintf(buf + count, "%02x ", rom[i]);
- count += sprintf(buf + count, ": crc=%02x %s\n",
+ c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rom[i]);
+ c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
crc, (verdict) ? "YES" : "NO");
if (verdict)
memcpy(sl->rom, rom, sizeof(sl->rom));
else
- dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
+ dev_warn(device, "18S20 doesn't respond to CONVERT_TEMP.\n");
for (i = 0; i < 9; ++i)
- count += sprintf(buf + count, "%02x ", sl->rom[i]);
+ c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", sl->rom[i]);
- count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
-out:
+ c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
+ w1_convert_temp(rom, sl->family->fid));
mutex_unlock(&dev->mutex);
- return count;
+ return PAGE_SIZE - c;
}
static int __init w1_therm_init(void)
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 7293c9b11f9..3b615d4022e 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -46,19 +46,17 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
static int w1_timeout = 10;
-static int w1_control_timeout = 1;
int w1_max_slave_count = 10;
int w1_max_slave_ttl = 10;
module_param_named(timeout, w1_timeout, int, 0);
-module_param_named(control_timeout, w1_control_timeout, int, 0);
module_param_named(max_slave_count, w1_max_slave_count, int, 0);
module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
DEFINE_MUTEX(w1_mlock);
LIST_HEAD(w1_masters);
-static struct task_struct *w1_control_thread;
+static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn);
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
@@ -83,10 +81,10 @@ static void w1_slave_release(struct device *dev)
{
struct w1_slave *sl = dev_to_w1_slave(dev);
- printk("%s: Releasing %s.\n", __func__, sl->name);
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
while (atomic_read(&sl->refcnt)) {
- printk("Waiting for %s to become free: refcnt=%d.\n",
+ dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
sl->name, atomic_read(&sl->refcnt));
if (msleep_interruptible(1000))
flush_signals(current);
@@ -105,35 +103,20 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a
return sprintf(buf, "%s\n", sl->name);
}
-static ssize_t w1_slave_read_id(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct w1_slave *sl = kobj_to_w1_slave(kobj);
-
- if (off > 8) {
- count = 0;
- } else {
- if (off + count > 8)
- count = 8 - off;
-
- memcpy(buf, (u8 *)&sl->reg_num, count);
- }
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+ ssize_t count = sizeof(sl->reg_num);
+ memcpy(buf, (u8 *)&sl->reg_num, count);
return count;
}
static struct device_attribute w1_slave_attr_name =
__ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
-
-static struct bin_attribute w1_slave_attr_bin_id = {
- .attr = {
- .name = "id",
- .mode = S_IRUGO,
- },
- .size = 8,
- .read = w1_slave_read_id,
-};
+static struct device_attribute w1_slave_attr_id =
+ __ATTR(id, S_IRUGO, w1_slave_read_id, NULL);
/* Default family */
@@ -250,11 +233,16 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
struct device_attribute *attr,
const char * buf, size_t count)
{
+ long tmp;
struct w1_master *md = dev_to_w1_master(dev);
+ if (strict_strtol(buf, 0, &tmp) == -EINVAL)
+ return -EINVAL;
+
mutex_lock(&md->mutex);
- md->search_count = simple_strtol(buf, NULL, 0);
+ md->search_count = tmp;
mutex_unlock(&md->mutex);
+ wake_up_process(md->thread);
return count;
}
@@ -273,6 +261,38 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
return count;
}
+static ssize_t w1_master_attribute_store_pullup(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ long tmp;
+ struct w1_master *md = dev_to_w1_master(dev);
+
+ if (strict_strtol(buf, 0, &tmp) == -EINVAL)
+ return -EINVAL;
+
+ mutex_lock(&md->mutex);
+ md->enable_pullup = tmp;
+ mutex_unlock(&md->mutex);
+ wake_up_process(md->thread);
+
+ return count;
+}
+
+static ssize_t w1_master_attribute_show_pullup(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct w1_master *md = dev_to_w1_master(dev);
+ ssize_t count;
+
+ mutex_lock(&md->mutex);
+ count = sprintf(buf, "%d\n", md->enable_pullup);
+ mutex_unlock(&md->mutex);
+
+ return count;
+}
+
static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = dev_to_w1_master(dev);
@@ -324,7 +344,8 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
return count;
}
-static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t w1_master_attribute_show_slaves(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct w1_master *md = dev_to_w1_master(dev);
int c = PAGE_SIZE;
@@ -349,6 +370,135 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device
return PAGE_SIZE - c;
}
+static ssize_t w1_master_attribute_show_add(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int c = PAGE_SIZE;
+ c -= snprintf(buf+PAGE_SIZE - c, c,
+ "write device id xx-xxxxxxxxxxxx to add slave\n");
+ return PAGE_SIZE - c;
+}
+
+static int w1_atoreg_num(struct device *dev, const char *buf, size_t count,
+ struct w1_reg_num *rn)
+{
+ unsigned int family;
+ unsigned long long id;
+ int i;
+ u64 rn64_le;
+
+ /* The CRC value isn't read from the user because the sysfs directory
+ * doesn't include it and most messages from the bus search don't
+ * print it either. It would be unreasonable for the user to then
+ * provide it.
+ */
+ const char *error_msg = "bad slave string format, expecting "
+ "ff-dddddddddddd\n";
+
+ if (buf[2] != '-') {
+ dev_err(dev, "%s", error_msg);
+ return -EINVAL;
+ }
+ i = sscanf(buf, "%02x-%012llx", &family, &id);
+ if (i != 2) {
+ dev_err(dev, "%s", error_msg);
+ return -EINVAL;
+ }
+ rn->family = family;
+ rn->id = id;
+
+ rn64_le = cpu_to_le64(*(u64 *)rn);
+ rn->crc = w1_calc_crc8((u8 *)&rn64_le, 7);
+
+#if 0
+ dev_info(dev, "With CRC device is %02x.%012llx.%02x.\n",
+ rn->family, (unsigned long long)rn->id, rn->crc);
+#endif
+
+ return 0;
+}
+
+/* Searches the slaves in the w1_master and returns a pointer or NULL.
+ * Note: must hold the mutex
+ */
+static struct w1_slave *w1_slave_search_device(struct w1_master *dev,
+ struct w1_reg_num *rn)
+{
+ struct w1_slave *sl;
+ list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+ if (sl->reg_num.family == rn->family &&
+ sl->reg_num.id == rn->id &&
+ sl->reg_num.crc == rn->crc) {
+ return sl;
+ }
+ }
+ return NULL;
+}
+
+static ssize_t w1_master_attribute_store_add(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct w1_master *md = dev_to_w1_master(dev);
+ struct w1_reg_num rn;
+ struct w1_slave *sl;
+ ssize_t result = count;
+
+ if (w1_atoreg_num(dev, buf, count, &rn))
+ return -EINVAL;
+
+ mutex_lock(&md->mutex);
+ sl = w1_slave_search_device(md, &rn);
+ /* It would be nice to do a targeted search one the one-wire bus
+ * for the new device to see if it is out there or not. But the
+ * current search doesn't support that.
+ */
+ if (sl) {
+ dev_info(dev, "Device %s already exists\n", sl->name);
+ result = -EINVAL;
+ } else {
+ w1_attach_slave_device(md, &rn);
+ }
+ mutex_unlock(&md->mutex);
+
+ return result;
+}
+
+static ssize_t w1_master_attribute_show_remove(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int c = PAGE_SIZE;
+ c -= snprintf(buf+PAGE_SIZE - c, c,
+ "write device id xx-xxxxxxxxxxxx to remove slave\n");
+ return PAGE_SIZE - c;
+}
+
+static ssize_t w1_master_attribute_store_remove(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct w1_master *md = dev_to_w1_master(dev);
+ struct w1_reg_num rn;
+ struct w1_slave *sl;
+ ssize_t result = count;
+
+ if (w1_atoreg_num(dev, buf, count, &rn))
+ return -EINVAL;
+
+ mutex_lock(&md->mutex);
+ sl = w1_slave_search_device(md, &rn);
+ if (sl) {
+ w1_slave_detach(sl);
+ } else {
+ dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family,
+ (unsigned long long)rn.id);
+ result = -EINVAL;
+ }
+ mutex_unlock(&md->mutex);
+
+ return result;
+}
+
#define W1_MASTER_ATTR_RO(_name, _mode) \
struct device_attribute w1_master_attribute_##_name = \
__ATTR(w1_master_##_name, _mode, \
@@ -368,6 +518,9 @@ static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUGO);
static struct attribute *w1_master_default_attrs[] = {
&w1_master_attribute_name.attr,
@@ -378,6 +531,9 @@ static struct attribute *w1_master_default_attrs[] = {
&w1_master_attribute_timeout.attr,
&w1_master_attribute_pointer.attr,
&w1_master_attribute_search.attr,
+ &w1_master_attribute_pullup.attr,
+ &w1_master_attribute_add.attr,
+ &w1_master_attribute_remove.attr,
NULL
};
@@ -390,7 +546,7 @@ int w1_create_master_attributes(struct w1_master *master)
return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
}
-static void w1_destroy_master_attributes(struct w1_master *master)
+void w1_destroy_master_attributes(struct w1_master *master)
{
sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}
@@ -479,7 +635,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
}
/* Create "id" entry */
- err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+ err = device_create_file(&sl->dev, &w1_slave_attr_id);
if (err < 0) {
dev_err(&sl->dev,
"sysfs file creation for [%s] failed. err=%d\n",
@@ -501,7 +657,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
return 0;
out_rem2:
- sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+ device_remove_file(&sl->dev, &w1_slave_attr_id);
out_rem1:
device_remove_file(&sl->dev, &w1_slave_attr_name);
out_unreg:
@@ -567,7 +723,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
return 0;
}
-static void w1_slave_detach(struct w1_slave *sl)
+void w1_slave_detach(struct w1_slave *sl)
{
struct w1_netlink_msg msg;
@@ -583,7 +739,7 @@ static void w1_slave_detach(struct w1_slave *sl)
msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg);
- sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+ device_remove_file(&sl->dev, &w1_slave_attr_id);
device_remove_file(&sl->dev, &w1_slave_attr_name);
device_unregister(&sl->dev);
@@ -591,24 +747,6 @@ static void w1_slave_detach(struct w1_slave *sl)
kfree(sl);
}
-static struct w1_master *w1_search_master(void *data)
-{
- struct w1_master *dev;
- int found = 0;
-
- mutex_lock(&w1_mlock);
- list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- if (dev->bus_master->data == data) {
- found = 1;
- atomic_inc(&dev->refcnt);
- break;
- }
- }
- mutex_unlock(&w1_mlock);
-
- return (found)?dev:NULL;
-}
-
struct w1_master *w1_search_master_id(u32 id)
{
struct w1_master *dev;
@@ -656,55 +794,56 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id)
return (found)?sl:NULL;
}
-void w1_reconnect_slaves(struct w1_family *f)
+void w1_reconnect_slaves(struct w1_family *f, int attach)
{
+ struct w1_slave *sl, *sln;
struct w1_master *dev;
mutex_lock(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
- dev->name, f->fid);
- set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+ dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
+ "for family %02x.\n", dev->name, f->fid);
+ mutex_lock(&dev->mutex);
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+ /* If it is a new family, slaves with the default
+ * family driver and are that family will be
+ * connected. If the family is going away, devices
+ * matching that family are reconneced.
+ */
+ if ((attach && sl->family->fid == W1_FAMILY_DEFAULT
+ && sl->reg_num.family == f->fid) ||
+ (!attach && sl->family->fid == f->fid)) {
+ struct w1_reg_num rn;
+
+ memcpy(&rn, &sl->reg_num, sizeof(rn));
+ w1_slave_detach(sl);
+
+ w1_attach_slave_device(dev, &rn);
+ }
+ }
+ dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
+ "has been finished.\n", dev->name);
+ mutex_unlock(&dev->mutex);
}
mutex_unlock(&w1_mlock);
}
-static void w1_slave_found(void *data, u64 rn)
+static void w1_slave_found(struct w1_master *dev, u64 rn)
{
- int slave_count;
struct w1_slave *sl;
- struct list_head *ent;
struct w1_reg_num *tmp;
- struct w1_master *dev;
u64 rn_le = cpu_to_le64(rn);
- dev = w1_search_master(data);
- if (!dev) {
- printk(KERN_ERR "Failed to find w1 master device for data %p, "
- "it is impossible.\n", data);
- return;
- }
+ atomic_inc(&dev->refcnt);
tmp = (struct w1_reg_num *) &rn;
- slave_count = 0;
- list_for_each(ent, &dev->slist) {
-
- sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
- if (sl->reg_num.family == tmp->family &&
- sl->reg_num.id == tmp->id &&
- sl->reg_num.crc == tmp->crc) {
- set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
- break;
- }
-
- slave_count++;
- }
-
- if (slave_count == dev->slave_count &&
- rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn_le, 7)) {
- w1_attach_slave_device(dev, tmp);
+ sl = w1_slave_search_device(dev, tmp);
+ if (sl) {
+ set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+ } else {
+ if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7))
+ w1_attach_slave_device(dev, tmp);
}
atomic_dec(&dev->refcnt);
@@ -779,80 +918,20 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
/* extract the direction taken & update the device number */
tmp64 = (triplet_ret >> 2);
rn |= (tmp64 << i);
+
+ if (kthread_should_stop()) {
+ dev_dbg(&dev->dev, "Abort w1_search\n");
+ return;
+ }
}
if ( (triplet_ret & 0x03) != 0x03 ) {
if ( (desc_bit == last_zero) || (last_zero < 0))
last_device = 1;
desc_bit = last_zero;
- cb(dev->bus_master->data, rn);
- }
- }
-}
-
-static int w1_control(void *data)
-{
- struct w1_slave *sl, *sln;
- struct w1_master *dev, *n;
- int have_to_wait = 0;
-
- set_freezable();
- while (!kthread_should_stop() || have_to_wait) {
- have_to_wait = 0;
-
- try_to_freeze();
- msleep_interruptible(w1_control_timeout * 1000);
-
- list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
- if (!kthread_should_stop() && !dev->flags)
- continue;
- /*
- * Little race: we can create thread but not set the flag.
- * Get a chance for external process to set flag up.
- */
- if (!dev->initialized) {
- have_to_wait = 1;
- continue;
- }
-
- if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
- set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
-
- mutex_lock(&w1_mlock);
- list_del(&dev->w1_master_entry);
- mutex_unlock(&w1_mlock);
-
- mutex_lock(&dev->mutex);
- list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
- w1_slave_detach(sl);
- }
- w1_destroy_master_attributes(dev);
- mutex_unlock(&dev->mutex);
- atomic_dec(&dev->refcnt);
- continue;
- }
-
- if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
- dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
- mutex_lock(&dev->mutex);
- list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
- if (sl->family->fid == W1_FAMILY_DEFAULT) {
- struct w1_reg_num rn;
-
- memcpy(&rn, &sl->reg_num, sizeof(rn));
- w1_slave_detach(sl);
-
- w1_attach_slave_device(dev, &rn);
- }
- }
- dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name);
- clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
- mutex_unlock(&dev->mutex);
- }
+ cb(dev, rn);
}
}
-
- return 0;
}
void w1_search_process(struct w1_master *dev, u8 search_type)
@@ -878,23 +957,29 @@ void w1_search_process(struct w1_master *dev, u8 search_type)
int w1_process(void *data)
{
struct w1_master *dev = (struct w1_master *) data;
+ /* As long as w1_timeout is only set by a module parameter the sleep
+ * time can be calculated in jiffies once.
+ */
+ const unsigned long jtime = msecs_to_jiffies(w1_timeout * 1000);
+
+ while (!kthread_should_stop()) {
+ if (dev->search_count) {
+ mutex_lock(&dev->mutex);
+ w1_search_process(dev, W1_SEARCH);
+ mutex_unlock(&dev->mutex);
+ }
- while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
try_to_freeze();
- msleep_interruptible(w1_timeout * 1000);
+ __set_current_state(TASK_INTERRUPTIBLE);
- if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
+ if (kthread_should_stop())
break;
- if (!dev->initialized)
- continue;
-
- if (dev->search_count == 0)
- continue;
-
- mutex_lock(&dev->mutex);
- w1_search_process(dev, W1_SEARCH);
- mutex_unlock(&dev->mutex);
+ /* Only sleep when the search is active. */
+ if (dev->search_count)
+ schedule_timeout(jtime);
+ else
+ schedule();
}
atomic_dec(&dev->refcnt);
@@ -932,18 +1017,13 @@ static int w1_init(void)
goto err_out_master_unregister;
}
- w1_control_thread = kthread_run(w1_control, NULL, "w1_control");
- if (IS_ERR(w1_control_thread)) {
- retval = PTR_ERR(w1_control_thread);
- printk(KERN_ERR "Failed to create control thread. err=%d\n",
- retval);
- goto err_out_slave_unregister;
- }
-
return 0;
+#if 0
+/* For undoing the slave register if there was a step after it. */
err_out_slave_unregister:
driver_unregister(&w1_slave_driver);
+#endif
err_out_master_unregister:
driver_unregister(&w1_master_driver);
@@ -959,13 +1039,12 @@ static void w1_fini(void)
{
struct w1_master *dev;
+ /* Set netlink removal messages and some cleanup */
list_for_each_entry(dev, &w1_masters, w1_master_entry)
__w1_remove_master_device(dev);
w1_fini_netlink();
- kthread_stop(w1_control_thread);
-
driver_unregister(&w1_slave_driver);
driver_unregister(&w1_master_driver);
bus_unregister(&w1_bus_type);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index f1df5343f4a..cdaa6fffbfc 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -46,7 +46,6 @@ struct w1_reg_num
#include "w1_family.h"
#define W1_MAXNAMELEN 32
-#define W1_SLAVE_DATA_SIZE 128
#define W1_SEARCH 0xF0
#define W1_ALARM_SEARCH 0xEC
@@ -77,7 +76,7 @@ struct w1_slave
struct completion released;
};
-typedef void (* w1_slave_found_callback)(void *, u64);
+typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
/**
@@ -142,12 +141,18 @@ struct w1_bus_master
*/
u8 (*reset_bus)(void *);
- /** Really nice hardware can handles the different types of ROM search */
- void (*search)(void *, u8, w1_slave_found_callback);
-};
+ /**
+ * Put out a strong pull-up pulse of the specified duration.
+ * @return -1=Error, 0=completed
+ */
+ u8 (*set_pullup)(void *, int);
-#define W1_MASTER_NEED_EXIT 0
-#define W1_MASTER_NEED_RECONNECT 1
+ /** Really nice hardware can handles the different types of ROM search
+ * w1_master* is passed to the slave found callback.
+ */
+ void (*search)(void *, struct w1_master *,
+ u8, w1_slave_found_callback);
+};
struct w1_master
{
@@ -167,7 +172,10 @@ struct w1_master
void *priv;
int priv_size;
- long flags;
+ /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */
+ int enable_pullup;
+ /** 5V strong pullup duration in milliseconds, zero disabled. */
+ int pullup_duration;
struct task_struct *thread;
struct mutex mutex;
@@ -181,12 +189,21 @@ struct w1_master
};
int w1_create_master_attributes(struct w1_master *);
+void w1_destroy_master_attributes(struct w1_master *master);
void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
struct w1_slave *w1_search_slave(struct w1_reg_num *id);
void w1_search_process(struct w1_master *dev, u8 search_type);
struct w1_master *w1_search_master_id(u32 id);
+/* Disconnect and reconnect devices in the given family. Used for finding
+ * unclaimed devices after a family has been registered or releasing devices
+ * after a family has been unregistered. Set attach to 1 when a new family
+ * has just been registered, to 0 when it has been unregistered.
+ */
+void w1_reconnect_slaves(struct w1_family *f, int attach);
+void w1_slave_detach(struct w1_slave *sl);
+
u8 w1_triplet(struct w1_master *dev, int bdir);
void w1_write_8(struct w1_master *, u8);
int w1_reset_bus(struct w1_master *);
@@ -194,6 +211,7 @@ u8 w1_calc_crc8(u8 *, int);
void w1_write_block(struct w1_master *, const u8 *, int);
u8 w1_read_block(struct w1_master *, u8 *, int);
int w1_reset_select_slave(struct w1_slave *sl);
+void w1_next_pullup(struct w1_master *, int);
static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
{
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index a3c95bd6890..4a099041f28 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -48,12 +48,12 @@ int w1_register_family(struct w1_family *newf)
if (!ret) {
atomic_set(&newf->refcnt, 0);
- newf->need_exit = 0;
list_add_tail(&newf->family_entry, &w1_families);
}
spin_unlock(&w1_flock);
- w1_reconnect_slaves(newf);
+ /* check default devices against the new set of drivers */
+ w1_reconnect_slaves(newf, 1);
return ret;
}
@@ -72,11 +72,11 @@ void w1_unregister_family(struct w1_family *fent)
break;
}
}
-
- fent->need_exit = 1;
-
spin_unlock(&w1_flock);
+ /* deatch devices using this family code */
+ w1_reconnect_slaves(fent, 0);
+
while (atomic_read(&fent->refcnt)) {
printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n",
fent->fid, atomic_read(&fent->refcnt));
@@ -109,8 +109,7 @@ struct w1_family * w1_family_registered(u8 fid)
static void __w1_family_put(struct w1_family *f)
{
- if (atomic_dec_and_test(&f->refcnt))
- f->need_exit = 1;
+ atomic_dec(&f->refcnt);
}
void w1_family_put(struct w1_family *f)
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index ef1e1dafa19..3ca1b9298f2 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
#define W1_THERM_DS1822 0x22
#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
+#define W1_EEPROM_DS2431 0x2D
#define W1_FAMILY_DS2760 0x30
#define MAXNAMELEN 32
@@ -53,7 +54,6 @@ struct w1_family
struct w1_family_ops *fops;
atomic_t refcnt;
- u8 need_exit;
};
extern spinlock_t w1_flock;
@@ -63,6 +63,5 @@ void __w1_family_get(struct w1_family *);
struct w1_family * w1_family_registered(u8);
void w1_unregister_family(struct w1_family *);
int w1_register_family(struct w1_family *);
-void w1_reconnect_slaves(struct w1_family *f);
#endif /* __W1_FAMILY_H */
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 6840dfebe4d..a3a54567bfb 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -29,7 +29,11 @@
#include "w1_netlink.h"
#include "w1_int.h"
-static u32 w1_ids = 1;
+static int w1_search_count = -1; /* Default is continual scan */
+module_param_named(search_count, w1_search_count, int, 0);
+
+static int w1_enable_pullup = 1;
+module_param_named(enable_pullup, w1_enable_pullup, int, 0);
static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
struct device_driver *driver,
@@ -59,8 +63,12 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
dev->initialized = 0;
dev->id = id;
dev->slave_ttl = slave_ttl;
- dev->search_count = -1; /* continual scan */
+ dev->search_count = w1_search_count;
+ dev->enable_pullup = w1_enable_pullup;
+ /* 1 for w1_process to decrement
+ * 1 for __w1_remove_master_device to decrement
+ */
atomic_set(&dev->refcnt, 2);
INIT_LIST_HEAD(&dev->slist);
@@ -93,9 +101,10 @@ static void w1_free_dev(struct w1_master *dev)
int w1_add_master_device(struct w1_bus_master *master)
{
- struct w1_master *dev;
+ struct w1_master *dev, *entry;
int retval = 0;
struct w1_netlink_msg msg;
+ int id, found;
/* validate minimum functionality */
if (!(master->touch_bit && master->reset_bus) &&
@@ -104,10 +113,50 @@ int w1_add_master_device(struct w1_bus_master *master)
printk(KERN_ERR "w1_add_master_device: invalid function set\n");
return(-EINVAL);
}
+ /* While it would be electrically possible to make a device that
+ * generated a strong pullup in bit bang mode, only hardare that
+ * controls 1-wire time frames are even expected to support a strong
+ * pullup. w1_io.c would need to support calling set_pullup before
+ * the last write_bit operation of a w1_write_8 which it currently
+ * doesn't.
+ */
+ if (!master->write_byte && !master->touch_bit && master->set_pullup) {
+ printk(KERN_ERR "w1_add_master_device: set_pullup requires "
+ "write_byte or touch_bit, disabling\n");
+ master->set_pullup = NULL;
+ }
+
+ /* Lock until the device is added (or not) to w1_masters. */
+ mutex_lock(&w1_mlock);
+ /* Search for the first available id (starting at 1). */
+ id = 0;
+ do {
+ ++id;
+ found = 0;
+ list_for_each_entry(entry, &w1_masters, w1_master_entry) {
+ if (entry->id == id) {
+ found = 1;
+ break;
+ }
+ }
+ } while (found);
- dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
- if (!dev)
+ dev = w1_alloc_dev(id, w1_max_slave_count, w1_max_slave_ttl,
+ &w1_master_driver, &w1_master_device);
+ if (!dev) {
+ mutex_unlock(&w1_mlock);
return -ENOMEM;
+ }
+
+ retval = w1_create_master_attributes(dev);
+ if (retval) {
+ mutex_unlock(&w1_mlock);
+ goto err_out_free_dev;
+ }
+
+ memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
+
+ dev->initialized = 1;
dev->thread = kthread_run(&w1_process, dev, "%s", dev->name);
if (IS_ERR(dev->thread)) {
@@ -115,18 +164,10 @@ int w1_add_master_device(struct w1_bus_master *master)
dev_err(&dev->dev,
"Failed to create new kernel thread. err=%d\n",
retval);
- goto err_out_free_dev;
+ mutex_unlock(&w1_mlock);
+ goto err_out_rm_attr;
}
- retval = w1_create_master_attributes(dev);
- if (retval)
- goto err_out_kill_thread;
-
- memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
-
- dev->initialized = 1;
-
- mutex_lock(&w1_mlock);
list_add(&dev->w1_master_entry, &w1_masters);
mutex_unlock(&w1_mlock);
@@ -137,8 +178,12 @@ int w1_add_master_device(struct w1_bus_master *master)
return 0;
+#if 0 /* Thread cleanup code, not required currently. */
err_out_kill_thread:
kthread_stop(dev->thread);
+#endif
+err_out_rm_attr:
+ w1_destroy_master_attributes(dev);
err_out_free_dev:
w1_free_dev(dev);
@@ -148,10 +193,21 @@ err_out_free_dev:
void __w1_remove_master_device(struct w1_master *dev)
{
struct w1_netlink_msg msg;
+ struct w1_slave *sl, *sln;
- set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
kthread_stop(dev->thread);
+ mutex_lock(&w1_mlock);
+ list_del(&dev->w1_master_entry);
+ mutex_unlock(&w1_mlock);
+
+ mutex_lock(&dev->mutex);
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry)
+ w1_slave_detach(sl);
+ w1_destroy_master_attributes(dev);
+ mutex_unlock(&dev->mutex);
+ atomic_dec(&dev->refcnt);
+
while (atomic_read(&dev->refcnt)) {
dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
dev->name, atomic_read(&dev->refcnt));
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 30b6fbf83bd..f4f82f1f486 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -93,6 +93,40 @@ static void w1_write_bit(struct w1_master *dev, int bit)
}
/**
+ * Pre-write operation, currently only supporting strong pullups.
+ * Program the hardware for a strong pullup, if one has been requested and
+ * the hardware supports it.
+ *
+ * @param dev the master device
+ */
+static void w1_pre_write(struct w1_master *dev)
+{
+ if (dev->pullup_duration &&
+ dev->enable_pullup && dev->bus_master->set_pullup) {
+ dev->bus_master->set_pullup(dev->bus_master->data,
+ dev->pullup_duration);
+ }
+}
+
+/**
+ * Post-write operation, currently only supporting strong pullups.
+ * If a strong pullup was requested, clear it if the hardware supports
+ * them, or execute the delay otherwise, in either case clear the request.
+ *
+ * @param dev the master device
+ */
+static void w1_post_write(struct w1_master *dev)
+{
+ if (dev->pullup_duration) {
+ if (dev->enable_pullup && dev->bus_master->set_pullup)
+ dev->bus_master->set_pullup(dev->bus_master->data, 0);
+ else
+ msleep(dev->pullup_duration);
+ dev->pullup_duration = 0;
+ }
+}
+
+/**
* Writes 8 bits.
*
* @param dev the master device
@@ -102,11 +136,17 @@ void w1_write_8(struct w1_master *dev, u8 byte)
{
int i;
- if (dev->bus_master->write_byte)
+ if (dev->bus_master->write_byte) {
+ w1_pre_write(dev);
dev->bus_master->write_byte(dev->bus_master->data, byte);
+ }
else
- for (i = 0; i < 8; ++i)
+ for (i = 0; i < 8; ++i) {
+ if (i == 7)
+ w1_pre_write(dev);
w1_touch_bit(dev, (byte >> i) & 0x1);
+ }
+ w1_post_write(dev);
}
EXPORT_SYMBOL_GPL(w1_write_8);
@@ -203,11 +243,14 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
{
int i;
- if (dev->bus_master->write_block)
+ if (dev->bus_master->write_block) {
+ w1_pre_write(dev);
dev->bus_master->write_block(dev->bus_master->data, buf, len);
+ }
else
for (i = 0; i < len; ++i)
- w1_write_8(dev, buf[i]);
+ w1_write_8(dev, buf[i]); /* calls w1_pre_write */
+ w1_post_write(dev);
}
EXPORT_SYMBOL_GPL(w1_write_block);
@@ -250,12 +293,24 @@ int w1_reset_bus(struct w1_master *dev)
result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
else {
dev->bus_master->write_bit(dev->bus_master->data, 0);
+ /* minimum 480, max ? us
+ * be nice and sleep, except 18b20 spec lists 960us maximum,
+ * so until we can sleep with microsecond accuracy, spin.
+ * Feel free to come up with some other way to give up the
+ * cpu for such a short amount of time AND get it back in
+ * the maximum amount of time.
+ */
w1_delay(480);
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(70);
result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
- w1_delay(410);
+ /* minmum 70 (above) + 410 = 480 us
+ * There aren't any timing requirements between a reset and
+ * the following transactions. Sleeping is safe here.
+ */
+ /* w1_delay(410); min required time */
+ msleep(1);
}
return result;
@@ -277,7 +332,8 @@ void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_cal
{
dev->attempts++;
if (dev->bus_master->search)
- dev->bus_master->search(dev->bus_master->data, search_type, cb);
+ dev->bus_master->search(dev->bus_master->data, dev,
+ search_type, cb);
else
w1_search(dev, search_type, cb);
}
@@ -305,3 +361,20 @@ int w1_reset_select_slave(struct w1_slave *sl)
return 0;
}
EXPORT_SYMBOL_GPL(w1_reset_select_slave);
+
+/**
+ * Put out a strong pull-up of the specified duration after the next write
+ * operation. Not all hardware supports strong pullups. Hardware that
+ * doesn't support strong pullups will sleep for the given time after the
+ * write operation without a strong pullup. This is a one shot request for
+ * the next write, specifying zero will clear a previous request.
+ * The w1 master lock must be held.
+ *
+ * @param delay time in milliseconds
+ * @return 0=success, anything else=error
+ */
+void w1_next_pullup(struct w1_master *dev, int delay)
+{
+ dev->pullup_duration = delay;
+}
+EXPORT_SYMBOL_GPL(w1_next_pullup);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c5103671670..1a22fe782a2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -66,6 +66,13 @@ config AT91RM9200_WATCHDOG
Watchdog timer embedded into AT91RM9200 chips. This will reboot your
system when the timeout is reached.
+config AT91SAM9X_WATCHDOG
+ tristate "AT91SAM9X watchdog"
+ depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261)
+ help
+ Watchdog timer embedded into AT91SAM9X chips. This will reboot your
+ system when the timeout is reached.
+
config 21285_WATCHDOG
tristate "DC21285 watchdog"
depends on FOOTBRIDGE
@@ -217,6 +224,15 @@ config DAVINCI_WATCHDOG
NOTE: once enabled, this timer cannot be disabled.
Say N if you are unsure.
+config ORION5X_WATCHDOG
+ tristate "Orion5x watchdog"
+ depends on ARCH_ORION5X
+ help
+ Say Y here if to include support for the watchdog timer
+ in the Orion5x ARM SoCs.
+ To compile this driver as a module, choose M here: the
+ module will be called orion5x_wdt.
+
# ARM26 Architecture
# AVR32 Architecture
@@ -416,6 +432,18 @@ config IT8712F_WDT
To compile this driver as a module, choose M here: the
module will be called it8712f_wdt.
+config IT87_WDT
+ tristate "IT87 Watchdog Timer"
+ depends on X86 && EXPERIMENTAL
+ ---help---
+ This is the driver for the hardware watchdog on the ITE IT8716,
+ IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog
+ simply watches your kernel to make sure it doesn't freeze, and if
+ it does, it reboots your computer after a certain amount of time.
+
+ To compile this driver as a module, choose M here: the module will
+ be called it87_wdt.
+
config HP_WATCHDOG
tristate "HP Proliant iLO 2 Hardware Watchdog Timer"
depends on X86
@@ -573,6 +601,21 @@ config W83697HF_WDT
Most people will say N.
+config W83697UG_WDT
+ tristate "W83697UG/W83697UF Watchdog Timer"
+ depends on X86
+ ---help---
+ This is the driver for the hardware watchdog on the W83697UG/UF
+ chipset as used in MSI Fuzzy CX700 VIA motherboards (and likely others).
+ This watchdog simply watches your kernel to make sure it doesn't
+ freeze, and if it does, it reboots your computer after a certain
+ amount of time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called w83697ug_wdt.
+
+ Most people will say N.
+
config W83877F_WDT
tristate "W83877F (EMACS) Watchdog Timer"
depends on X86
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index e0ef123fbde..e352bbb7630 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
# ARM Architecture
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
+obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
@@ -39,6 +40,7 @@ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
+obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o
# ARM26 Architecture
@@ -71,6 +73,7 @@ ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y)
obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o
endif
obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
+obj-$(CONFIG_IT87_WDT) += it87_wdt.o
obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
@@ -83,6 +86,7 @@ obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
+obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
@@ -123,6 +127,9 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
# SPARC64 Architecture
+obj-$(CONFIG_WATCHDOG_RIO) += riowd.o
+obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
+
# XTENSA Architecture
# Architecture Independant
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
new file mode 100644
index 00000000000..b4babfc3158
--- /dev/null
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -0,0 +1,328 @@
+/*
+ * Watchdog driver for Atmel AT91SAM9x processors.
+ *
+ * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.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 the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * The Watchdog Timer Mode Register can be only written to once. If the
+ * timeout need to be set from Linux, be sure that the bootstrap or the
+ * bootloader doesn't write to this register.
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+
+#include <asm/arch/at91_wdt.h>
+
+#define DRV_NAME "AT91SAM9 Watchdog"
+
+/* AT91SAM9 watchdog runs a 12bit counter @ 256Hz,
+ * use this to convert a watchdog
+ * value from/to milliseconds.
+ */
+#define ms_to_ticks(t) (((t << 8) / 1000) - 1)
+#define ticks_to_ms(t) (((t + 1) * 1000) >> 8)
+
+/* Hardware timeout in seconds */
+#define WDT_HW_TIMEOUT 2
+
+/* Timer heartbeat (500ms) */
+#define WDT_TIMEOUT (HZ/2)
+
+/* User land timeout */
+#define WDT_HEARTBEAT 15
+static int heartbeat = WDT_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
+ "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static void at91_ping(unsigned long data);
+
+static struct {
+ unsigned long next_heartbeat; /* the next_heartbeat for the timer */
+ unsigned long open;
+ char expect_close;
+ struct timer_list timer; /* The timer that pings the watchdog */
+} at91wdt_private;
+
+/* ......................................................................... */
+
+
+/*
+ * Reload the watchdog timer. (ie, pat the watchdog)
+ */
+static inline void at91_wdt_reset(void)
+{
+ at91_sys_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
+}
+
+/*
+ * Timer tick
+ */
+static void at91_ping(unsigned long data)
+{
+ if (time_before(jiffies, at91wdt_private.next_heartbeat) ||
+ (!nowayout && !at91wdt_private.open)) {
+ at91_wdt_reset();
+ mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
+ } else
+ printk(KERN_CRIT DRV_NAME": I will reset your machine !\n");
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &at91wdt_private.open))
+ return -EBUSY;
+
+ at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+ mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
+
+ return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ */
+static int at91_wdt_close(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &at91wdt_private.open);
+
+ /* stop internal ping */
+ if (!at91wdt_private.expect_close)
+ del_timer(&at91wdt_private.timer);
+
+ at91wdt_private.expect_close = 0;
+ return 0;
+}
+
+/*
+ * Set the watchdog time interval in 1/256Hz (write-once)
+ * Counter is 12 bit.
+ */
+static int at91_wdt_settimeout(unsigned int timeout)
+{
+ unsigned int reg;
+ unsigned int mr;
+
+ /* Check if disabled */
+ mr = at91_sys_read(AT91_WDT_MR);
+ if (mr & AT91_WDT_WDDIS) {
+ printk(KERN_ERR DRV_NAME": sorry, watchdog is disabled\n");
+ return -EIO;
+ }
+
+ /*
+ * All counting occurs at SLOW_CLOCK / 128 = 256 Hz
+ *
+ * Since WDV is a 12-bit counter, the maximum period is
+ * 4096 / 256 = 16 seconds.
+ */
+ reg = AT91_WDT_WDRSTEN /* causes watchdog reset */
+ /* | AT91_WDT_WDRPROC causes processor reset only */
+ | AT91_WDT_WDDBGHLT /* disabled in debug mode */
+ | AT91_WDT_WDD /* restart at any time */
+ | (timeout & AT91_WDT_WDV); /* timer value */
+ at91_sys_write(AT91_WDT_MR, reg);
+
+ return 0;
+}
+
+static const struct watchdog_info at91_wdt_info = {
+ .identity = DRV_NAME,
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static long at91_wdt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int new_value;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &at91_wdt_info,
+ sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ heartbeat = new_value;
+ at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+
+ return put_user(new_value, p); /* return current value */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+ }
+ return -ENOTTY;
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len,
+ loff_t *ppos)
+{
+ if (!len)
+ return 0;
+
+ /* Scan for magic character */
+ if (!nowayout) {
+ size_t i;
+
+ at91wdt_private.expect_close = 0;
+
+ for (i = 0; i < len; i++) {
+ char c;
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V') {
+ at91wdt_private.expect_close = 42;
+ break;
+ }
+ }
+ }
+
+ at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+
+ return len;
+}
+
+/* ......................................................................... */
+
+static const struct file_operations at91wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = at91_wdt_ioctl,
+ .open = at91_wdt_open,
+ .release = at91_wdt_close,
+ .write = at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &at91wdt_fops,
+};
+
+static int __init at91wdt_probe(struct platform_device *pdev)
+{
+ int res;
+
+ if (at91wdt_miscdev.parent)
+ return -EBUSY;
+ at91wdt_miscdev.parent = &pdev->dev;
+
+ /* Set watchdog */
+ res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000));
+ if (res)
+ return res;
+
+ res = misc_register(&at91wdt_miscdev);
+ if (res)
+ return res;
+
+ at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
+ setup_timer(&at91wdt_private.timer, at91_ping, 0);
+ mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
+
+ printk(KERN_INFO DRV_NAME " enabled (heartbeat=%d sec, nowayout=%d)\n",
+ heartbeat, nowayout);
+
+ return 0;
+}
+
+static int __exit at91wdt_remove(struct platform_device *pdev)
+{
+ int res;
+
+ res = misc_deregister(&at91wdt_miscdev);
+ if (!res)
+ at91wdt_miscdev.parent = NULL;
+
+ return res;
+}
+
+#ifdef CONFIG_PM
+
+static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ return 0;
+}
+
+static int at91wdt_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#else
+#define at91wdt_suspend NULL
+#define at91wdt_resume NULL
+#endif
+
+static struct platform_driver at91wdt_driver = {
+ .remove = __exit_p(at91wdt_remove),
+ .suspend = at91wdt_suspend,
+ .resume = at91wdt_resume,
+ .driver = {
+ .name = "at91_wdt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91sam_wdt_init(void)
+{
+ return platform_driver_probe(&at91wdt_driver, at91wdt_probe);
+}
+
+static void __exit at91sam_wdt_exit(void)
+{
+ platform_driver_unregister(&at91wdt_driver);
+}
+
+module_init(at91sam_wdt_init);
+module_exit(at91sam_wdt_exit);
+
+MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
new file mode 100644
index 00000000000..084dfe9cecf
--- /dev/null
+++ b/drivers/watchdog/cpwd.c
@@ -0,0 +1,695 @@
+/* cpwd.c - driver implementation for hardware watchdog
+ * timers found on Sun Microsystems CP1400 and CP1500 boards.
+ *
+ * This device supports both the generic Linux watchdog
+ * interface and Solaris-compatible ioctls as best it is
+ * able.
+ *
+ * NOTE: CP1400 systems appear to have a defective intr_mask
+ * register on the PLD, preventing the disabling of
+ * timer interrupts. We use a timer to periodically
+ * reset 'stopped' watchdogs on affected platforms.
+ *
+ * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/smp_lock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include <asm/watchdog.h>
+
+#define DRIVER_NAME "cpwd"
+#define PFX DRIVER_NAME ": "
+
+#define WD_OBPNAME "watchdog"
+#define WD_BADMODEL "SUNW,501-5336"
+#define WD_BTIMEOUT (jiffies + (HZ * 1000))
+#define WD_BLIMIT 0xFFFF
+
+#define WD0_MINOR 212
+#define WD1_MINOR 213
+#define WD2_MINOR 214
+
+/* Internal driver definitions. */
+#define WD0_ID 0
+#define WD1_ID 1
+#define WD2_ID 2
+#define WD_NUMDEVS 3
+
+#define WD_INTR_OFF 0
+#define WD_INTR_ON 1
+
+#define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */
+#define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */
+#define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */
+
+/* Register value definitions
+ */
+#define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */
+#define WD1_INTR_MASK 0x02
+#define WD2_INTR_MASK 0x04
+
+#define WD_S_RUNNING 0x01 /* Watchdog device status running */
+#define WD_S_EXPIRED 0x02 /* Watchdog device status expired */
+
+struct cpwd {
+ void __iomem *regs;
+ spinlock_t lock;
+
+ unsigned int irq;
+
+ unsigned long timeout;
+ bool enabled;
+ bool reboot;
+ bool broken;
+ bool initialized;
+
+ struct {
+ struct miscdevice misc;
+ void __iomem *regs;
+ u8 intr_mask;
+ u8 runstatus;
+ u16 timeout;
+ } devs[WD_NUMDEVS];
+};
+
+static struct cpwd *cpwd_device;
+
+/* Sun uses Altera PLD EPF8820ATC144-4
+ * providing three hardware watchdogs:
+ *
+ * 1) RIC - sends an interrupt when triggered
+ * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU
+ * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
+ *
+ *** Timer register block definition (struct wd_timer_regblk)
+ *
+ * dcntr and limit registers (halfword access):
+ * -------------------
+ * | 15 | ...| 1 | 0 |
+ * -------------------
+ * |- counter val -|
+ * -------------------
+ * dcntr - Current 16-bit downcounter value.
+ * When downcounter reaches '0' watchdog expires.
+ * Reading this register resets downcounter with 'limit' value.
+ * limit - 16-bit countdown value in 1/10th second increments.
+ * Writing this register begins countdown with input value.
+ * Reading from this register does not affect counter.
+ * NOTES: After watchdog reset, dcntr and limit contain '1'
+ *
+ * status register (byte access):
+ * ---------------------------
+ * | 7 | ... | 2 | 1 | 0 |
+ * --------------+------------
+ * |- UNUSED -| EXP | RUN |
+ * ---------------------------
+ * status- Bit 0 - Watchdog is running
+ * Bit 1 - Watchdog has expired
+ *
+ *** PLD register block definition (struct wd_pld_regblk)
+ *
+ * intr_mask register (byte access):
+ * ---------------------------------
+ * | 7 | ... | 3 | 2 | 1 | 0 |
+ * +-------------+------------------
+ * |- UNUSED -| WD3 | WD2 | WD1 |
+ * ---------------------------------
+ * WD3 - 1 == Interrupt disabled for watchdog 3
+ * WD2 - 1 == Interrupt disabled for watchdog 2
+ * WD1 - 1 == Interrupt disabled for watchdog 1
+ *
+ * pld_status register (byte access):
+ * UNKNOWN, MAGICAL MYSTERY REGISTER
+ *
+ */
+#define WD_TIMER_REGSZ 16
+#define WD0_OFF 0
+#define WD1_OFF (WD_TIMER_REGSZ * 1)
+#define WD2_OFF (WD_TIMER_REGSZ * 2)
+#define PLD_OFF (WD_TIMER_REGSZ * 3)
+
+#define WD_DCNTR 0x00
+#define WD_LIMIT 0x04
+#define WD_STATUS 0x08
+
+#define PLD_IMASK (PLD_OFF + 0x00)
+#define PLD_STATUS (PLD_OFF + 0x04)
+
+static struct timer_list cpwd_timer;
+
+static int wd0_timeout = 0;
+static int wd1_timeout = 0;
+static int wd2_timeout = 0;
+
+module_param (wd0_timeout, int, 0);
+MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
+module_param (wd1_timeout, int, 0);
+MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
+module_param (wd2_timeout, int, 0);
+MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
+
+MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
+MODULE_DESCRIPTION("Hardware watchdog driver for Sun Microsystems CP1400/1500");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("watchdog");
+
+static void cpwd_writew(u16 val, void __iomem *addr)
+{
+ writew(cpu_to_le16(val), addr);
+}
+static u16 cpwd_readw(void __iomem *addr)
+{
+ u16 val = readw(addr);
+
+ return le16_to_cpu(val);
+}
+
+static void cpwd_writeb(u8 val, void __iomem *addr)
+{
+ writeb(val, addr);
+}
+
+static u8 cpwd_readb(void __iomem *addr)
+{
+ return readb(addr);
+}
+
+/* Enable or disable watchdog interrupts
+ * Because of the CP1400 defect this should only be
+ * called during initialzation or by wd_[start|stop]timer()
+ *
+ * index - sub-device index, or -1 for 'all'
+ * enable - non-zero to enable interrupts, zero to disable
+ */
+static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
+{
+ unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK);
+ unsigned char setregs =
+ (index == -1) ?
+ (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) :
+ (p->devs[index].intr_mask);
+
+ if (enable == WD_INTR_ON)
+ curregs &= ~setregs;
+ else
+ curregs |= setregs;
+
+ cpwd_writeb(curregs, p->regs + PLD_IMASK);
+}
+
+/* Restarts timer with maximum limit value and
+ * does not unset 'brokenstop' value.
+ */
+static void cpwd_resetbrokentimer(struct cpwd *p, int index)
+{
+ cpwd_toggleintr(p, index, WD_INTR_ON);
+ cpwd_writew(WD_BLIMIT, p->devs[index].regs + WD_LIMIT);
+}
+
+/* Timer method called to reset stopped watchdogs--
+ * because of the PLD bug on CP1400, we cannot mask
+ * interrupts within the PLD so me must continually
+ * reset the timers ad infinitum.
+ */
+static void cpwd_brokentimer(unsigned long data)
+{
+ struct cpwd *p = (struct cpwd *) data;
+ int id, tripped = 0;
+
+ /* kill a running timer instance, in case we
+ * were called directly instead of by kernel timer
+ */
+ if (timer_pending(&cpwd_timer))
+ del_timer(&cpwd_timer);
+
+ for (id = 0; id < WD_NUMDEVS; id++) {
+ if (p->devs[id].runstatus & WD_STAT_BSTOP) {
+ ++tripped;
+ cpwd_resetbrokentimer(p, id);
+ }
+ }
+
+ if (tripped) {
+ /* there is at least one timer brokenstopped-- reschedule */
+ cpwd_timer.expires = WD_BTIMEOUT;
+ add_timer(&cpwd_timer);
+ }
+}
+
+/* Reset countdown timer with 'limit' value and continue countdown.
+ * This will not start a stopped timer.
+ */
+static void cpwd_pingtimer(struct cpwd *p, int index)
+{
+ if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING)
+ cpwd_readw(p->devs[index].regs + WD_DCNTR);
+}
+
+/* Stop a running watchdog timer-- the timer actually keeps
+ * running, but the interrupt is masked so that no action is
+ * taken upon expiration.
+ */
+static void cpwd_stoptimer(struct cpwd *p, int index)
+{
+ if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) {
+ cpwd_toggleintr(p, index, WD_INTR_OFF);
+
+ if (p->broken) {
+ p->devs[index].runstatus |= WD_STAT_BSTOP;
+ cpwd_brokentimer((unsigned long) p);
+ }
+ }
+}
+
+/* Start a watchdog timer with the specified limit value
+ * If the watchdog is running, it will be restarted with
+ * the provided limit value.
+ *
+ * This function will enable interrupts on the specified
+ * watchdog.
+ */
+static void cpwd_starttimer(struct cpwd *p, int index)
+{
+ if (p->broken)
+ p->devs[index].runstatus &= ~WD_STAT_BSTOP;
+
+ p->devs[index].runstatus &= ~WD_STAT_SVCD;
+
+ cpwd_writew(p->devs[index].timeout, p->devs[index].regs + WD_LIMIT);
+ cpwd_toggleintr(p, index, WD_INTR_ON);
+}
+
+static int cpwd_getstatus(struct cpwd *p, int index)
+{
+ unsigned char stat = cpwd_readb(p->devs[index].regs + WD_STATUS);
+ unsigned char intr = cpwd_readb(p->devs[index].regs + PLD_IMASK);
+ unsigned char ret = WD_STOPPED;
+
+ /* determine STOPPED */
+ if (!stat)
+ return ret;
+
+ /* determine EXPIRED vs FREERUN vs RUNNING */
+ else if (WD_S_EXPIRED & stat) {
+ ret = WD_EXPIRED;
+ } else if(WD_S_RUNNING & stat) {
+ if (intr & p->devs[index].intr_mask) {
+ ret = WD_FREERUN;
+ } else {
+ /* Fudge WD_EXPIRED status for defective CP1400--
+ * IF timer is running
+ * AND brokenstop is set
+ * AND an interrupt has been serviced
+ * we are WD_EXPIRED.
+ *
+ * IF timer is running
+ * AND brokenstop is set
+ * AND no interrupt has been serviced
+ * we are WD_FREERUN.
+ */
+ if (p->broken &&
+ (p->devs[index].runstatus & WD_STAT_BSTOP)) {
+ if (p->devs[index].runstatus & WD_STAT_SVCD) {
+ ret = WD_EXPIRED;
+ } else {
+ /* we could as well pretend we are expired */
+ ret = WD_FREERUN;
+ }
+ } else {
+ ret = WD_RUNNING;
+ }
+ }
+ }
+
+ /* determine SERVICED */
+ if (p->devs[index].runstatus & WD_STAT_SVCD)
+ ret |= WD_SERVICED;
+
+ return(ret);
+}
+
+static irqreturn_t cpwd_interrupt(int irq, void *dev_id)
+{
+ struct cpwd *p = dev_id;
+
+ /* Only WD0 will interrupt-- others are NMI and we won't
+ * see them here....
+ */
+ spin_lock_irq(&p->lock);
+
+ cpwd_stoptimer(p, WD0_ID);
+ p->devs[WD0_ID].runstatus |= WD_STAT_SVCD;
+
+ spin_unlock_irq(&p->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int cpwd_open(struct inode *inode, struct file *f)
+{
+ struct cpwd *p = cpwd_device;
+
+ lock_kernel();
+ switch(iminor(inode)) {
+ case WD0_MINOR:
+ case WD1_MINOR:
+ case WD2_MINOR:
+ break;
+
+ default:
+ unlock_kernel();
+ return -ENODEV;
+ }
+
+ /* Register IRQ on first open of device */
+ if (!p->initialized) {
+ if (request_irq(p->irq, &cpwd_interrupt,
+ IRQF_SHARED, DRIVER_NAME, p)) {
+ printk(KERN_ERR PFX "Cannot register IRQ %d\n",
+ p->irq);
+ unlock_kernel();
+ return -EBUSY;
+ }
+ p->initialized = true;
+ }
+
+ unlock_kernel();
+
+ return nonseekable_open(inode, f);
+}
+
+static int cpwd_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int cpwd_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info info = {
+ .options = WDIOF_SETTIMEOUT,
+ .firmware_version = 1,
+ .identity = DRIVER_NAME,
+ };
+ void __user *argp = (void __user *)arg;
+ int index = iminor(inode) - WD0_MINOR;
+ struct cpwd *p = cpwd_device;
+ int setopt = 0;
+
+ switch (cmd) {
+ /* Generic Linux IOCTLs */
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &info, sizeof(struct watchdog_info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(0, (int __user *)argp))
+ return -EFAULT;
+ break;
+
+ case WDIOC_KEEPALIVE:
+ cpwd_pingtimer(p, index);
+ break;
+
+ case WDIOC_SETOPTIONS:
+ if (copy_from_user(&setopt, argp, sizeof(unsigned int)))
+ return -EFAULT;
+
+ if (setopt & WDIOS_DISABLECARD) {
+ if (p->enabled)
+ return -EINVAL;
+ cpwd_stoptimer(p, index);
+ } else if (setopt & WDIOS_ENABLECARD) {
+ cpwd_starttimer(p, index);
+ } else {
+ return -EINVAL;
+ }
+ break;
+
+ /* Solaris-compatible IOCTLs */
+ case WIOCGSTAT:
+ setopt = cpwd_getstatus(p, index);
+ if (copy_to_user(argp, &setopt, sizeof(unsigned int)))
+ return -EFAULT;
+ break;
+
+ case WIOCSTART:
+ cpwd_starttimer(p, index);
+ break;
+
+ case WIOCSTOP:
+ if (p->enabled)
+ return(-EINVAL);
+
+ cpwd_stoptimer(p, index);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static long cpwd_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int rval = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ /* solaris ioctls are specific to this driver */
+ case WIOCSTART:
+ case WIOCSTOP:
+ case WIOCGSTAT:
+ lock_kernel();
+ rval = cpwd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+ unlock_kernel();
+ break;
+
+ /* everything else is handled by the generic compat layer */
+ default:
+ break;
+ }
+
+ return rval;
+}
+
+static ssize_t cpwd_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct cpwd *p = cpwd_device;
+ int index = iminor(inode);
+
+ if (count) {
+ cpwd_pingtimer(p, index);
+ return 1;
+ }
+
+ return 0;
+}
+
+static ssize_t cpwd_read(struct file * file, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static const struct file_operations cpwd_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = cpwd_ioctl,
+ .compat_ioctl = cpwd_compat_ioctl,
+ .open = cpwd_open,
+ .write = cpwd_write,
+ .read = cpwd_read,
+ .release = cpwd_release,
+};
+
+static int __devinit cpwd_probe(struct of_device *op,
+ const struct of_device_id *match)
+{
+ struct device_node *options;
+ const char *str_prop;
+ const void *prop_val;
+ int i, err = -EINVAL;
+ struct cpwd *p;
+
+ if (cpwd_device)
+ return -EINVAL;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!p) {
+ printk(KERN_ERR PFX "Unable to allocate struct cpwd.\n");
+ goto out;
+ }
+
+ p->irq = op->irqs[0];
+
+ spin_lock_init(&p->lock);
+
+ p->regs = of_ioremap(&op->resource[0], 0,
+ 4 * WD_TIMER_REGSZ, DRIVER_NAME);
+ if (!p->regs) {
+ printk(KERN_ERR PFX "Unable to map registers.\n");
+ goto out_free;
+ }
+
+ options = of_find_node_by_path("/options");
+ err = -ENODEV;
+ if (!options) {
+ printk(KERN_ERR PFX "Unable to find /options node.\n");
+ goto out_iounmap;
+ }
+
+ prop_val = of_get_property(options, "watchdog-enable?", NULL);
+ p->enabled = (prop_val ? true : false);
+
+ prop_val = of_get_property(options, "watchdog-reboot?", NULL);
+ p->reboot = (prop_val ? true : false);
+
+ str_prop = of_get_property(options, "watchdog-timeout", NULL);
+ if (str_prop)
+ p->timeout = simple_strtoul(str_prop, NULL, 10);
+
+ /* CP1400s seem to have broken PLD implementations-- the
+ * interrupt_mask register cannot be written, so no timer
+ * interrupts can be masked within the PLD.
+ */
+ str_prop = of_get_property(op->node, "model", NULL);
+ p->broken = (str_prop && !strcmp(str_prop, WD_BADMODEL));
+
+ if (!p->enabled)
+ cpwd_toggleintr(p, -1, WD_INTR_OFF);
+
+ for (i = 0; i < WD_NUMDEVS; i++) {
+ static const char *cpwd_names[] = { "RIC", "XIR", "POR" };
+ static int *parms[] = { &wd0_timeout,
+ &wd1_timeout,
+ &wd2_timeout };
+ struct miscdevice *mp = &p->devs[i].misc;
+
+ mp->minor = WD0_MINOR + i;
+ mp->name = cpwd_names[i];
+ mp->fops = &cpwd_fops;
+
+ p->devs[i].regs = p->regs + (i * WD_TIMER_REGSZ);
+ p->devs[i].intr_mask = (WD0_INTR_MASK << i);
+ p->devs[i].runstatus &= ~WD_STAT_BSTOP;
+ p->devs[i].runstatus |= WD_STAT_INIT;
+ p->devs[i].timeout = p->timeout;
+ if (*parms[i])
+ p->devs[i].timeout = *parms[i];
+
+ err = misc_register(&p->devs[i].misc);
+ if (err) {
+ printk(KERN_ERR "Could not register misc device for "
+ "dev %d\n", i);
+ goto out_unregister;
+ }
+ }
+
+ if (p->broken) {
+ init_timer(&cpwd_timer);
+ cpwd_timer.function = cpwd_brokentimer;
+ cpwd_timer.data = (unsigned long) p;
+ cpwd_timer.expires = WD_BTIMEOUT;
+
+ printk(KERN_INFO PFX "PLD defect workaround enabled for "
+ "model " WD_BADMODEL ".\n");
+ }
+
+ dev_set_drvdata(&op->dev, p);
+ cpwd_device = p;
+ err = 0;
+
+out:
+ return err;
+
+out_unregister:
+ for (i--; i >= 0; i--)
+ misc_deregister(&p->devs[i].misc);
+
+out_iounmap:
+ of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
+
+out_free:
+ kfree(p);
+ goto out;
+}
+
+static int __devexit cpwd_remove(struct of_device *op)
+{
+ struct cpwd *p = dev_get_drvdata(&op->dev);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ misc_deregister(&p->devs[i].misc);
+
+ if (!p->enabled) {
+ cpwd_stoptimer(p, i);
+ if (p->devs[i].runstatus & WD_STAT_BSTOP)
+ cpwd_resetbrokentimer(p, i);
+ }
+ }
+
+ if (p->broken)
+ del_timer_sync(&cpwd_timer);
+
+ if (p->initialized)
+ free_irq(p->irq, p);
+
+ of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
+ kfree(p);
+
+ cpwd_device = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id cpwd_match[] = {
+ {
+ .name = "watchdog",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cpwd_match);
+
+static struct of_platform_driver cpwd_driver = {
+ .name = DRIVER_NAME,
+ .match_table = cpwd_match,
+ .probe = cpwd_probe,
+ .remove = __devexit_p(cpwd_remove),
+};
+
+static int __init cpwd_init(void)
+{
+ return of_register_driver(&cpwd_driver, &of_bus_type);
+}
+
+static void __exit cpwd_exit(void)
+{
+ of_unregister_driver(&cpwd_driver);
+}
+
+module_init(cpwd_init);
+module_exit(cpwd_exit);
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index 614a5c7017b..6799a6de66f 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -130,8 +130,8 @@ static ssize_t geodewdt_write(struct file *file, const char __user *data,
return len;
}
-static int geodewdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long geodewdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
@@ -198,7 +198,7 @@ static const struct file_operations geodewdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = geodewdt_write,
- .ioctl = geodewdt_ioctl,
+ .unlocked_ioctl = geodewdt_ioctl,
.open = geodewdt_open,
.release = geodewdt_release,
};
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index b82405cfb4c..89fcefcc851 100644
--- a/drivers/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
@@ -85,7 +85,6 @@ static void __asr_toggle(void)
outb(reg & ~asr_toggle_mask, asr_write_addr);
reg = inb(asr_read_addr);
- spin_unlock(&asr_lock);
}
static void asr_toggle(void)
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
new file mode 100644
index 00000000000..afb8af397a9
--- /dev/null
+++ b/drivers/watchdog/it87_wdt.c
@@ -0,0 +1,725 @@
+/*
+ * Watchdog Timer Driver
+ * for ITE IT87xx Environment Control - Low Pin Count Input / Output
+ *
+ * (c) Copyright 2007 Oliver Schuster <olivers137@aol.com>
+ *
+ * Based on softdog.c by Alan Cox,
+ * 83977f_wdt.c by Jose Goncalves,
+ * it87.c by Chris Gauthron, Jean Delvare
+ *
+ * Data-sheets: Publicly available at the ITE website
+ * http://www.ite.com.tw/
+ *
+ * Support of the watchdog timers, which are available on
+ * IT8716, IT8718, IT8726 and IT8712 (J,K version).
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#define WATCHDOG_VERSION "1.12"
+#define WATCHDOG_NAME "IT87 WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+#define WD_MAGIC 'V'
+
+/* Defaults for Module Parameter */
+#define DEFAULT_NOGAMEPORT 0
+#define DEFAULT_EXCLUSIVE 1
+#define DEFAULT_TIMEOUT 60
+#define DEFAULT_TESTMODE 0
+#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT
+
+/* IO Ports */
+#define REG 0x2e
+#define VAL 0x2f
+
+/* Logical device Numbers LDN */
+#define GPIO 0x07
+#define GAMEPORT 0x09
+#define CIR 0x0a
+
+/* Configuration Registers and Functions */
+#define LDNREG 0x07
+#define CHIPID 0x20
+#define CHIPREV 0x22
+#define ACTREG 0x30
+#define BASEREG 0x60
+
+/* Chip Id numbers */
+#define NO_DEV_ID 0xffff
+#define IT8705_ID 0x8705
+#define IT8712_ID 0x8712
+#define IT8716_ID 0x8716
+#define IT8718_ID 0x8718
+#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
+
+/* GPIO Configuration Registers LDN=0x07 */
+#define WDTCTRL 0x71
+#define WDTCFG 0x72
+#define WDTVALLSB 0x73
+#define WDTVALMSB 0x74
+
+/* GPIO Bits WDTCTRL */
+#define WDT_CIRINT 0x80
+#define WDT_MOUSEINT 0x40
+#define WDT_KYBINT 0x20
+#define WDT_GAMEPORT 0x10 /* not it8718 */
+#define WDT_FORCE 0x02
+#define WDT_ZERO 0x01
+
+/* GPIO Bits WDTCFG */
+#define WDT_TOV1 0x80
+#define WDT_KRST 0x40
+#define WDT_TOVE 0x20
+#define WDT_PWROK 0x10
+#define WDT_INT_MASK 0x0f
+
+/* CIR Configuration Register LDN=0x0a */
+#define CIR_ILS 0x70
+
+/* The default Base address is not always available, we use this */
+#define CIR_BASE 0x0208
+
+/* CIR Controller */
+#define CIR_DR(b) (b)
+#define CIR_IER(b) (b + 1)
+#define CIR_RCR(b) (b + 2)
+#define CIR_TCR1(b) (b + 3)
+#define CIR_TCR2(b) (b + 4)
+#define CIR_TSR(b) (b + 5)
+#define CIR_RSR(b) (b + 6)
+#define CIR_BDLR(b) (b + 5)
+#define CIR_BDHR(b) (b + 6)
+#define CIR_IIR(b) (b + 7)
+
+/* Default Base address of Game port */
+#define GP_BASE_DEFAULT 0x0201
+
+/* wdt_status */
+#define WDTS_TIMER_RUN 0
+#define WDTS_DEV_OPEN 1
+#define WDTS_KEEPALIVE 2
+#define WDTS_LOCKED 3
+#define WDTS_USE_GP 4
+#define WDTS_EXPECTED 5
+
+static unsigned int base, gpact, ciract;
+static unsigned long wdt_status;
+static DEFINE_SPINLOCK(spinlock);
+
+static int nogameport = DEFAULT_NOGAMEPORT;
+static int exclusive = DEFAULT_EXCLUSIVE;
+static int timeout = DEFAULT_TIMEOUT;
+static int testmode = DEFAULT_TESTMODE;
+static int nowayout = DEFAULT_NOWAYOUT;
+
+module_param(nogameport, int, 0);
+MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
+ __MODULE_STRING(DEFAULT_NOGAMEPORT));
+module_param(exclusive, int, 0);
+MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default="
+ __MODULE_STRING(DEFAULT_EXCLUSIVE));
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
+ __MODULE_STRING(DEFAULT_TIMEOUT));
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
+ __MODULE_STRING(DEFAULT_TESTMODE));
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT));
+
+/* Superio Chip */
+
+static inline void superio_enter(void)
+{
+ outb(0x87, REG);
+ outb(0x01, REG);
+ outb(0x55, REG);
+ outb(0x55, REG);
+}
+
+static inline void superio_exit(void)
+{
+ outb(0x02, REG);
+ outb(0x02, VAL);
+}
+
+static inline void superio_select(int ldn)
+{
+ outb(LDNREG, REG);
+ outb(ldn, VAL);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+static inline void superio_outb(int val, int reg)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline int superio_inw(int reg)
+{
+ int val;
+ outb(reg++, REG);
+ val = inb(VAL) << 8;
+ outb(reg, REG);
+ val |= inb(VAL);
+ return val;
+}
+
+static inline void superio_outw(int val, int reg)
+{
+ outb(reg++, REG);
+ outb(val >> 8, VAL);
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+/* watchdog timer handling */
+
+static void wdt_keepalive(void)
+{
+ if (test_bit(WDTS_USE_GP, &wdt_status))
+ inb(base);
+ else
+ /* The timer reloads with around 5 msec delay */
+ outb(0x55, CIR_DR(base));
+ set_bit(WDTS_KEEPALIVE, &wdt_status);
+}
+
+static void wdt_start(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+
+ superio_select(GPIO);
+ if (test_bit(WDTS_USE_GP, &wdt_status))
+ superio_outb(WDT_GAMEPORT, WDTCTRL);
+ else
+ superio_outb(WDT_CIRINT, WDTCTRL);
+ if (!testmode)
+ superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG);
+ else
+ superio_outb(WDT_TOV1, WDTCFG);
+ superio_outb(timeout>>8, WDTVALMSB);
+ superio_outb(timeout, WDTVALLSB);
+
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+}
+
+static void wdt_stop(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+
+ superio_select(GPIO);
+ superio_outb(0x00, WDTCTRL);
+ superio_outb(WDT_TOV1, WDTCFG);
+ superio_outb(0x00, WDTVALMSB);
+ superio_outb(0x00, WDTVALLSB);
+
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+}
+
+/**
+ * wdt_set_timeout - set a new timeout value with watchdog ioctl
+ * @t: timeout value in seconds
+ *
+ * The hardware device has a 16 bit watchdog timer, thus the
+ * timeout time ranges between 1 and 65535 seconds.
+ *
+ * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
+ */
+
+static int wdt_set_timeout(int t)
+{
+ unsigned long flags;
+
+ if (t < 1 || t > 65535)
+ return -EINVAL;
+
+ timeout = t;
+
+ spin_lock_irqsave(&spinlock, flags);
+ if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
+ superio_enter();
+
+ superio_select(GPIO);
+ superio_outb(t>>8, WDTVALMSB);
+ superio_outb(t, WDTVALLSB);
+
+ superio_exit();
+ }
+ spin_unlock_irqrestore(&spinlock, flags);
+ return 0;
+}
+
+/**
+ * wdt_get_status - determines the status supported by watchdog ioctl
+ * @status: status returned to user space
+ *
+ * The status bit of the device does not allow to distinguish
+ * between a regular system reset and a watchdog forced reset.
+ * But, in test mode it is useful, so it is supported through
+ * WDIOC_GETSTATUS watchdog ioctl. Additionally the driver
+ * reports the keepalive signal and the acception of the magic.
+ *
+ * Used within WDIOC_GETSTATUS watchdog device ioctl.
+ */
+
+static int wdt_get_status(int *status)
+{
+ unsigned long flags;
+
+ *status = 0;
+ if (testmode) {
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+ superio_select(GPIO);
+ if (superio_inb(WDTCTRL) & WDT_ZERO) {
+ superio_outb(0x00, WDTCTRL);
+ clear_bit(WDTS_TIMER_RUN, &wdt_status);
+ *status |= WDIOF_CARDRESET;
+ }
+
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ }
+ if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status))
+ *status |= WDIOF_KEEPALIVEPING;
+ if (test_bit(WDTS_EXPECTED, &wdt_status))
+ *status |= WDIOF_MAGICCLOSE;
+ return 0;
+}
+
+/* /dev/watchdog handling */
+
+/**
+ * wdt_open - watchdog file_operations .open
+ * @inode: inode of the device
+ * @file: file handle to the device
+ *
+ * The watchdog timer starts by opening the device.
+ *
+ * Used within the file operation of the watchdog device.
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status))
+ return -EBUSY;
+ if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
+ if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status))
+ __module_get(THIS_MODULE);
+ wdt_start();
+ }
+ return nonseekable_open(inode, file);
+}
+
+/**
+ * wdt_release - watchdog file_operations .release
+ * @inode: inode of the device
+ * @file: file handle to the device
+ *
+ * Closing the watchdog device either stops the watchdog timer
+ * or in the case, that nowayout is set or the magic character
+ * wasn't written, a critical warning about an running watchdog
+ * timer is given.
+ *
+ * Used within the file operation of the watchdog device.
+ */
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
+ if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) {
+ wdt_stop();
+ clear_bit(WDTS_TIMER_RUN, &wdt_status);
+ } else {
+ wdt_keepalive();
+ printk(KERN_CRIT PFX
+ "unexpected close, not stopping watchdog!\n");
+ }
+ }
+ clear_bit(WDTS_DEV_OPEN, &wdt_status);
+ return 0;
+}
+
+/**
+ * wdt_write - watchdog file_operations .write
+ * @file: file handle to the watchdog
+ * @buf: buffer to write
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we don't define content meaning.
+ *
+ * Used within the file operation of the watchdog device.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ clear_bit(WDTS_EXPECTED, &wdt_status);
+ wdt_keepalive();
+ }
+ if (!nowayout) {
+ size_t ofs;
+
+ /* note: just in case someone wrote the magic character long ago */
+ for (ofs = 0; ofs != count; ofs++) {
+ char c;
+ if (get_user(c, buf + ofs))
+ return -EFAULT;
+ if (c == WD_MAGIC)
+ set_bit(WDTS_EXPECTED, &wdt_status);
+ }
+ }
+ return count;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+};
+
+/**
+ * wdt_ioctl - watchdog file_operations .unlocked_ioctl
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features.
+ *
+ * Used within the file operation of the watchdog device.
+ */
+
+static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int rc = 0, status, new_options, new_timeout;
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ uarg.i = (int __user *)arg;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(uarg.ident,
+ &ident, sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ wdt_get_status(&status);
+ return put_user(status, uarg.i);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, uarg.i);
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(new_options, uarg.i))
+ return -EFAULT;
+
+ switch (new_options) {
+ case WDIOS_DISABLECARD:
+ if (test_bit(WDTS_TIMER_RUN, &wdt_status))
+ wdt_stop();
+ clear_bit(WDTS_TIMER_RUN, &wdt_status);
+ return 0;
+
+ case WDIOS_ENABLECARD:
+ if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status))
+ wdt_start();
+ return 0;
+
+ default:
+ return -EFAULT;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+ rc = wdt_set_timeout(new_timeout);
+ case WDIOC_GETTIMEOUT:
+ if (put_user(timeout, uarg.i))
+ return -EFAULT;
+ return rc;
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ wdt_stop();
+ return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .unlocked_ioctl = wdt_ioctl,
+ .open = wdt_open,
+ .release = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static int __init it87_wdt_init(void)
+{
+ int rc = 0;
+ u16 chip_type;
+ u8 chip_rev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+ chip_type = superio_inw(CHIPID);
+ chip_rev = superio_inb(CHIPREV) & 0x0f;
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ switch (chip_type) {
+ case IT8716_ID:
+ case IT8718_ID:
+ case IT8726_ID:
+ break;
+ case IT8712_ID:
+ if (chip_rev > 7)
+ break;
+ case IT8705_ID:
+ printk(KERN_ERR PFX
+ "Unsupported Chip found, Chip %04x Revision %02x\n",
+ chip_type, chip_rev);
+ return -ENODEV;
+ case NO_DEV_ID:
+ printk(KERN_ERR PFX "no device\n");
+ return -ENODEV;
+ default:
+ printk(KERN_ERR PFX
+ "Unknown Chip found, Chip %04x Revision %04x\n",
+ chip_type, chip_rev);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+
+ superio_select(GPIO);
+ superio_outb(WDT_TOV1, WDTCFG);
+ superio_outb(0x00, WDTCTRL);
+
+ /* First try to get Gameport support */
+ if (chip_type != IT8718_ID && !nogameport) {
+ superio_select(GAMEPORT);
+ base = superio_inw(BASEREG);
+ if (!base) {
+ base = GP_BASE_DEFAULT;
+ superio_outw(base, BASEREG);
+ }
+ gpact = superio_inb(ACTREG);
+ superio_outb(0x01, ACTREG);
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ if (request_region(base, 1, WATCHDOG_NAME))
+ set_bit(WDTS_USE_GP, &wdt_status);
+ else
+ rc = -EIO;
+ } else {
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ }
+
+ /* If we haven't Gameport support, try to get CIR support */
+ if (!test_bit(WDTS_USE_GP, &wdt_status)) {
+ if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
+ if (rc == -EIO)
+ printk(KERN_ERR PFX
+ "I/O Address 0x%04x and 0x%04x"
+ " already in use\n", base, CIR_BASE);
+ else
+ printk(KERN_ERR PFX
+ "I/O Address 0x%04x already in use\n",
+ CIR_BASE);
+ rc = -EIO;
+ goto err_out;
+ }
+ base = CIR_BASE;
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+
+ superio_select(CIR);
+ superio_outw(base, BASEREG);
+ superio_outb(0x00, CIR_ILS);
+ ciract = superio_inb(ACTREG);
+ superio_outb(0x01, ACTREG);
+ if (rc == -EIO) {
+ superio_select(GAMEPORT);
+ superio_outb(gpact, ACTREG);
+ }
+
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ }
+
+ if (timeout < 1 || timeout > 65535) {
+ timeout = DEFAULT_TIMEOUT;
+ printk(KERN_WARNING PFX
+ "Timeout value out of range, use default %d sec\n",
+ DEFAULT_TIMEOUT);
+ }
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc) {
+ printk(KERN_ERR PFX
+ "Cannot register reboot notifier (err=%d)\n", rc);
+ goto err_out_region;
+ }
+
+ rc = misc_register(&wdt_miscdev);
+ if (rc) {
+ printk(KERN_ERR PFX
+ "Cannot register miscdev on minor=%d (err=%d)\n",
+ wdt_miscdev.minor, rc);
+ goto err_out_reboot;
+ }
+
+ /* Initialize CIR to use it as keepalive source */
+ if (!test_bit(WDTS_USE_GP, &wdt_status)) {
+ outb(0x00, CIR_RCR(base));
+ outb(0xc0, CIR_TCR1(base));
+ outb(0x5c, CIR_TCR2(base));
+ outb(0x10, CIR_IER(base));
+ outb(0x00, CIR_BDHR(base));
+ outb(0x01, CIR_BDLR(base));
+ outb(0x09, CIR_IER(base));
+ }
+
+ printk(KERN_INFO PFX "Chip it%04x revision %d initialized. "
+ "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
+ "nogameport=%d)\n", chip_type, chip_rev, timeout,
+ nowayout, testmode, exclusive, nogameport);
+
+ return 0;
+
+err_out_reboot:
+ unregister_reboot_notifier(&wdt_notifier);
+err_out_region:
+ release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
+ if (!test_bit(WDTS_USE_GP, &wdt_status)) {
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+ superio_select(CIR);
+ superio_outb(ciract, ACTREG);
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ }
+err_out:
+ if (chip_type != IT8718_ID && !nogameport) {
+ spin_lock_irqsave(&spinlock, flags);
+ superio_enter();
+ superio_select(GAMEPORT);
+ superio_outb(gpact, ACTREG);
+ superio_exit();
+ spin_unlock_irqrestore(&spinlock, flags);
+ }
+
+ return rc;
+}
+
+static void __exit it87_wdt_exit(void)
+{
+ unsigned long flags;
+ int nolock;
+
+ nolock = !spin_trylock_irqsave(&spinlock, flags);
+ superio_enter();
+ superio_select(GPIO);
+ superio_outb(0x00, WDTCTRL);
+ superio_outb(0x00, WDTCFG);
+ superio_outb(0x00, WDTVALMSB);
+ superio_outb(0x00, WDTVALLSB);
+ if (test_bit(WDTS_USE_GP, &wdt_status)) {
+ superio_select(GAMEPORT);
+ superio_outb(gpact, ACTREG);
+ } else {
+ superio_select(CIR);
+ superio_outb(ciract, ACTREG);
+ }
+ superio_exit();
+ if (!nolock)
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
+}
+
+module_init(it87_wdt_init);
+module_exit(it87_wdt_exit);
+
+MODULE_AUTHOR("Oliver Schuster");
+MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index 8302ef005be..147b4d5c63b 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -174,10 +174,8 @@ static struct miscdevice ixp4xx_wdt_miscdev = {
static int __init ixp4xx_wdt_init(void)
{
int ret;
- unsigned long processor_id;
- asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
- if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
+ if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
printk(KERN_ERR "IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected"
" - watchdog disabled\n");
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 3a11dadfd8e..7bcbb7f4745 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/char/watchdog/omap_wdt.c
+ * omap_wdt.c
*
- * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog
*
* Author: MontaVista Software, Inc.
* <gdavis@mvista.com> or <source@mvista.com>
@@ -47,50 +47,68 @@
#include "omap_wdt.h"
+static struct platform_device *omap_wdt_dev;
+
static unsigned timer_margin;
module_param(timer_margin, uint, 0);
MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
-static int omap_wdt_users;
-static struct clk *armwdt_ck;
-static struct clk *mpu_wdt_ick;
-static struct clk *mpu_wdt_fck;
-
static unsigned int wdt_trgr_pattern = 0x1234;
static spinlock_t wdt_lock;
-static void omap_wdt_ping(void)
+struct omap_wdt_dev {
+ void __iomem *base; /* physical */
+ struct device *dev;
+ int omap_wdt_users;
+ struct clk *armwdt_ck;
+ struct clk *mpu_wdt_ick;
+ struct clk *mpu_wdt_fck;
+ struct resource *mem;
+ struct miscdevice omap_wdt_miscdev;
+};
+
+static void omap_wdt_ping(struct omap_wdt_dev *wdev)
{
+ void __iomem *base = wdev->base;
+
/* wait for posted write to complete */
- while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08)
cpu_relax();
+
wdt_trgr_pattern = ~wdt_trgr_pattern;
- omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+ __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR));
+
/* wait for posted write to complete */
- while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08)
cpu_relax();
/* reloaded WCRR from WLDR */
}
-static void omap_wdt_enable(void)
+static void omap_wdt_enable(struct omap_wdt_dev *wdev)
{
+ void __iomem *base = wdev->base;
+
/* Sequence to enable the watchdog */
- omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
- while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+ __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR);
+ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10)
cpu_relax();
- omap_writel(0x4444, OMAP_WATCHDOG_SPR);
- while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+
+ __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR);
+ while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10)
cpu_relax();
}
-static void omap_wdt_disable(void)
+static void omap_wdt_disable(struct omap_wdt_dev *wdev)
{
+ void __iomem *base = wdev->base;
+
/* sequence required to disable watchdog */
- omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+ __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10)
cpu_relax();
- omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+
+ __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10)
cpu_relax();
}
@@ -103,83 +121,90 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout)
timer_margin = new_timeout;
}
-static void omap_wdt_set_timeout(void)
+static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
{
u32 pre_margin = GET_WLDR_VAL(timer_margin);
+ void __iomem *base = wdev->base;
/* just count up at 32 KHz */
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
cpu_relax();
- omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+
+ __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
cpu_relax();
}
/*
* Allow only one task to hold it open
*/
-
static int omap_wdt_open(struct inode *inode, struct file *file)
{
- if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+ struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev);
+ void __iomem *base = wdev->base;
+
+ if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
return -EBUSY;
if (cpu_is_omap16xx())
- clk_enable(armwdt_ck); /* Enable the clock */
+ clk_enable(wdev->armwdt_ck); /* Enable the clock */
- if (cpu_is_omap24xx()) {
- clk_enable(mpu_wdt_ick); /* Enable the interface clock */
- clk_enable(mpu_wdt_fck); /* Enable the functional clock */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+ clk_enable(wdev->mpu_wdt_ick); /* Enable the interface clock */
+ clk_enable(wdev->mpu_wdt_fck); /* Enable the functional clock */
}
/* initialize prescaler */
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
cpu_relax();
- omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
- while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+
+ __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL);
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
cpu_relax();
- omap_wdt_set_timeout();
- omap_wdt_enable();
+ file->private_data = (void *) wdev;
+
+ omap_wdt_set_timeout(wdev);
+ omap_wdt_enable(wdev);
+
return nonseekable_open(inode, file);
}
static int omap_wdt_release(struct inode *inode, struct file *file)
{
+ struct omap_wdt_dev *wdev = file->private_data;
+
/*
* Shut off the timer unless NOWAYOUT is defined.
*/
#ifndef CONFIG_WATCHDOG_NOWAYOUT
- omap_wdt_disable();
- if (cpu_is_omap16xx()) {
- clk_disable(armwdt_ck); /* Disable the clock */
- clk_put(armwdt_ck);
- armwdt_ck = NULL;
- }
+ omap_wdt_disable(wdev);
- if (cpu_is_omap24xx()) {
- clk_disable(mpu_wdt_ick); /* Disable the clock */
- clk_disable(mpu_wdt_fck); /* Disable the clock */
- clk_put(mpu_wdt_ick);
- clk_put(mpu_wdt_fck);
- mpu_wdt_ick = NULL;
- mpu_wdt_fck = NULL;
+ if (cpu_is_omap16xx())
+ clk_disable(wdev->armwdt_ck); /* Disable the clock */
+
+ if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+ clk_disable(wdev->mpu_wdt_ick); /* Disable the clock */
+ clk_disable(wdev->mpu_wdt_fck); /* Disable the clock */
}
#else
printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
#endif
- omap_wdt_users = 0;
+ wdev->omap_wdt_users = 0;
+
return 0;
}
static ssize_t omap_wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
+ struct omap_wdt_dev *wdev = file->private_data;
+
/* Refresh LOAD_TIME. */
if (len) {
spin_lock(&wdt_lock);
- omap_wdt_ping();
+ omap_wdt_ping(wdev);
spin_unlock(&wdt_lock);
}
return len;
@@ -188,6 +213,7 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ struct omap_wdt_dev *wdev;
int new_margin;
static const struct watchdog_info ident = {
.identity = "OMAP Watchdog",
@@ -195,6 +221,8 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
.firmware_version = 0,
};
+ wdev = file->private_data;
+
switch (cmd) {
case WDIOC_GETSUPPORT:
return copy_to_user((struct watchdog_info __user *)arg, &ident,
@@ -203,14 +231,14 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
return put_user(0, (int __user *)arg);
case WDIOC_GETBOOTSTATUS:
if (cpu_is_omap16xx())
- return put_user(omap_readw(ARM_SYSST),
+ return put_user(__raw_readw(ARM_SYSST),
(int __user *)arg);
if (cpu_is_omap24xx())
return put_user(omap_prcm_get_reset_sources(),
(int __user *)arg);
case WDIOC_KEEPALIVE:
spin_lock(&wdt_lock);
- omap_wdt_ping();
+ omap_wdt_ping(wdev);
spin_unlock(&wdt_lock);
return 0;
case WDIOC_SETTIMEOUT:
@@ -219,11 +247,11 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
omap_wdt_adjust_timeout(new_margin);
spin_lock(&wdt_lock);
- omap_wdt_disable();
- omap_wdt_set_timeout();
- omap_wdt_enable();
+ omap_wdt_disable(wdev);
+ omap_wdt_set_timeout(wdev);
+ omap_wdt_enable(wdev);
- omap_wdt_ping();
+ omap_wdt_ping(wdev);
spin_unlock(&wdt_lock);
/* Fall */
case WDIOC_GETTIMEOUT:
@@ -241,96 +269,173 @@ static const struct file_operations omap_wdt_fops = {
.release = omap_wdt_release,
};
-static struct miscdevice omap_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &omap_wdt_fops,
-};
-
static int __init omap_wdt_probe(struct platform_device *pdev)
{
struct resource *res, *mem;
+ struct omap_wdt_dev *wdev;
int ret;
/* reserve static register mappings */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENOENT;
+ if (!res) {
+ ret = -ENOENT;
+ goto err_get_resource;
+ }
+
+ if (omap_wdt_dev) {
+ ret = -EBUSY;
+ goto err_busy;
+ }
mem = request_mem_region(res->start, res->end - res->start + 1,
pdev->name);
- if (mem == NULL)
- return -EBUSY;
+ if (!mem) {
+ ret = -EBUSY;
+ goto err_busy;
+ }
- platform_set_drvdata(pdev, mem);
+ wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL);
+ if (!wdev) {
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
- omap_wdt_users = 0;
+ wdev->omap_wdt_users = 0;
+ wdev->mem = mem;
if (cpu_is_omap16xx()) {
- armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
- if (IS_ERR(armwdt_ck)) {
- ret = PTR_ERR(armwdt_ck);
- armwdt_ck = NULL;
- goto fail;
+ wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
+ if (IS_ERR(wdev->armwdt_ck)) {
+ ret = PTR_ERR(wdev->armwdt_ck);
+ wdev->armwdt_ck = NULL;
+ goto err_clk;
}
}
if (cpu_is_omap24xx()) {
- mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
- if (IS_ERR(mpu_wdt_ick)) {
- ret = PTR_ERR(mpu_wdt_ick);
- mpu_wdt_ick = NULL;
- goto fail;
+ wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
+ if (IS_ERR(wdev->mpu_wdt_ick)) {
+ ret = PTR_ERR(wdev->mpu_wdt_ick);
+ wdev->mpu_wdt_ick = NULL;
+ goto err_clk;
}
- mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
- if (IS_ERR(mpu_wdt_fck)) {
- ret = PTR_ERR(mpu_wdt_fck);
- mpu_wdt_fck = NULL;
- goto fail;
+ wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
+ if (IS_ERR(wdev->mpu_wdt_fck)) {
+ ret = PTR_ERR(wdev->mpu_wdt_fck);
+ wdev->mpu_wdt_fck = NULL;
+ goto err_clk;
}
}
- omap_wdt_disable();
+ if (cpu_is_omap34xx()) {
+ wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick");
+ if (IS_ERR(wdev->mpu_wdt_ick)) {
+ ret = PTR_ERR(wdev->mpu_wdt_ick);
+ wdev->mpu_wdt_ick = NULL;
+ goto err_clk;
+ }
+ wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck");
+ if (IS_ERR(wdev->mpu_wdt_fck)) {
+ ret = PTR_ERR(wdev->mpu_wdt_fck);
+ wdev->mpu_wdt_fck = NULL;
+ goto err_clk;
+ }
+ }
+ wdev->base = ioremap(res->start, res->end - res->start + 1);
+ if (!wdev->base) {
+ ret = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ platform_set_drvdata(pdev, wdev);
+
+ omap_wdt_disable(wdev);
omap_wdt_adjust_timeout(timer_margin);
- omap_wdt_miscdev.parent = &pdev->dev;
- ret = misc_register(&omap_wdt_miscdev);
+ wdev->omap_wdt_miscdev.parent = &pdev->dev;
+ wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR;
+ wdev->omap_wdt_miscdev.name = "watchdog";
+ wdev->omap_wdt_miscdev.fops = &omap_wdt_fops;
+
+ ret = misc_register(&(wdev->omap_wdt_miscdev));
if (ret)
- goto fail;
+ goto err_misc;
- pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+ pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n",
+ __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
+ timer_margin);
/* autogate OCP interface clock */
- omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+ __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG);
+
+ omap_wdt_dev = pdev;
+
return 0;
-fail:
- if (armwdt_ck)
- clk_put(armwdt_ck);
- if (mpu_wdt_ick)
- clk_put(mpu_wdt_ick);
- if (mpu_wdt_fck)
- clk_put(mpu_wdt_fck);
- release_resource(mem);
+err_misc:
+ platform_set_drvdata(pdev, NULL);
+ iounmap(wdev->base);
+
+err_ioremap:
+ wdev->base = NULL;
+
+err_clk:
+ if (wdev->armwdt_ck)
+ clk_put(wdev->armwdt_ck);
+ if (wdev->mpu_wdt_ick)
+ clk_put(wdev->mpu_wdt_ick);
+ if (wdev->mpu_wdt_fck)
+ clk_put(wdev->mpu_wdt_fck);
+ kfree(wdev);
+
+err_kzalloc:
+ release_mem_region(res->start, res->end - res->start + 1);
+
+err_busy:
+err_get_resource:
+
return ret;
}
static void omap_wdt_shutdown(struct platform_device *pdev)
{
- omap_wdt_disable();
+ struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+
+ if (wdev->omap_wdt_users)
+ omap_wdt_disable(wdev);
}
static int omap_wdt_remove(struct platform_device *pdev)
{
- struct resource *mem = platform_get_drvdata(pdev);
- misc_deregister(&omap_wdt_miscdev);
- release_resource(mem);
- if (armwdt_ck)
- clk_put(armwdt_ck);
- if (mpu_wdt_ick)
- clk_put(mpu_wdt_ick);
- if (mpu_wdt_fck)
- clk_put(mpu_wdt_fck);
+ struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res)
+ return -ENOENT;
+
+ misc_deregister(&(wdev->omap_wdt_miscdev));
+ release_mem_region(res->start, res->end - res->start + 1);
+ platform_set_drvdata(pdev, NULL);
+
+ if (wdev->armwdt_ck) {
+ clk_put(wdev->armwdt_ck);
+ wdev->armwdt_ck = NULL;
+ }
+
+ if (wdev->mpu_wdt_ick) {
+ clk_put(wdev->mpu_wdt_ick);
+ wdev->mpu_wdt_ick = NULL;
+ }
+
+ if (wdev->mpu_wdt_fck) {
+ clk_put(wdev->mpu_wdt_fck);
+ wdev->mpu_wdt_fck = NULL;
+ }
+ iounmap(wdev->base);
+
+ kfree(wdev);
+ omap_wdt_dev = NULL;
+
return 0;
}
@@ -344,17 +449,23 @@ static int omap_wdt_remove(struct platform_device *pdev)
static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
{
- if (omap_wdt_users)
- omap_wdt_disable();
+ struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+
+ if (wdev->omap_wdt_users)
+ omap_wdt_disable(wdev);
+
return 0;
}
static int omap_wdt_resume(struct platform_device *pdev)
{
- if (omap_wdt_users) {
- omap_wdt_enable();
- omap_wdt_ping();
+ struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+
+ if (wdev->omap_wdt_users) {
+ omap_wdt_enable(wdev);
+ omap_wdt_ping(wdev);
}
+
return 0;
}
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index 52a532a5114..fc02ec6a038 100644
--- a/drivers/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
@@ -30,25 +30,15 @@
#ifndef _OMAP_WATCHDOG_H
#define _OMAP_WATCHDOG_H
-#define OMAP1610_WATCHDOG_BASE 0xfffeb000
-#define OMAP2420_WATCHDOG_BASE 0x48022000 /*WDT Timer 2 */
-
-#ifdef CONFIG_ARCH_OMAP24XX
-#define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE
-#else
-#define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE
-#define RM_RSTST_WKUP 0
-#endif
-
-#define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00)
-#define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10)
-#define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14)
-#define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24)
-#define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28)
-#define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c)
-#define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30)
-#define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34)
-#define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48)
+#define OMAP_WATCHDOG_REV (0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG (0x10)
+#define OMAP_WATCHDOG_STATUS (0x14)
+#define OMAP_WATCHDOG_CNTRL (0x24)
+#define OMAP_WATCHDOG_CRR (0x28)
+#define OMAP_WATCHDOG_LDR (0x2c)
+#define OMAP_WATCHDOG_TGR (0x30)
+#define OMAP_WATCHDOG_WPS (0x34)
+#define OMAP_WATCHDOG_SPR (0x48)
/* Using the prescaler, the OMAP watchdog could go for many
* months before firing. These limits work without scaling,
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c
new file mode 100644
index 00000000000..14a339f58b6
--- /dev/null
+++ b/drivers/watchdog/orion5x_wdt.c
@@ -0,0 +1,245 @@
+/*
+ * drivers/watchdog/orion5x_wdt.c
+ *
+ * Watchdog driver for Orion5x processors
+ *
+ * Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+/*
+ * Watchdog timer block registers.
+ */
+#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
+#define WDT_EN 0x0010
+#define WDT_VAL (TIMER_VIRT_BASE + 0x0024)
+
+#define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK)
+#define WDT_IN_USE 0
+#define WDT_OK_TO_CLOSE 1
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int heartbeat = WDT_MAX_DURATION; /* (seconds) */
+static unsigned long wdt_status;
+static spinlock_t wdt_lock;
+
+static void wdt_enable(void)
+{
+ u32 reg;
+
+ spin_lock(&wdt_lock);
+
+ /* Set watchdog duration */
+ writel(ORION5X_TCLK * heartbeat, WDT_VAL);
+
+ /* Clear watchdog timer interrupt */
+ reg = readl(BRIDGE_CAUSE);
+ reg &= ~WDT_INT_REQ;
+ writel(reg, BRIDGE_CAUSE);
+
+ /* Enable watchdog timer */
+ reg = readl(TIMER_CTRL);
+ reg |= WDT_EN;
+ writel(reg, TIMER_CTRL);
+
+ /* Enable reset on watchdog */
+ reg = readl(CPU_RESET_MASK);
+ reg |= WDT_RESET;
+ writel(reg, CPU_RESET_MASK);
+
+ spin_unlock(&wdt_lock);
+}
+
+static void wdt_disable(void)
+{
+ u32 reg;
+
+ spin_lock(&wdt_lock);
+
+ /* Disable reset on watchdog */
+ reg = readl(CPU_RESET_MASK);
+ reg &= ~WDT_RESET;
+ writel(reg, CPU_RESET_MASK);
+
+ /* Disable watchdog timer */
+ reg = readl(TIMER_CTRL);
+ reg &= ~WDT_EN;
+ writel(reg, TIMER_CTRL);
+
+ spin_unlock(&wdt_lock);
+}
+
+static int orion5x_wdt_get_timeleft(int *time_left)
+{
+ spin_lock(&wdt_lock);
+ *time_left = readl(WDT_VAL) / ORION5X_TCLK;
+ spin_unlock(&wdt_lock);
+ return 0;
+}
+
+static int orion5x_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ wdt_enable();
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t orion5x_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ }
+ }
+ wdt_enable();
+ }
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING,
+ .identity = "Orion5x Watchdog",
+};
+
+
+static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOTTY;
+ int time;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, (int *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_enable();
+ ret = 0;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ ret = get_user(time, (int *)arg);
+ if (ret)
+ break;
+
+ if (time <= 0 || time > WDT_MAX_DURATION) {
+ ret = -EINVAL;
+ break;
+ }
+ heartbeat = time;
+ wdt_enable();
+ /* Fall through */
+
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(heartbeat, (int *)arg);
+ break;
+
+ case WDIOC_GETTIMELEFT:
+ if (orion5x_wdt_get_timeleft(&time)) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = put_user(time, (int *)arg);
+ break;
+ }
+ return ret;
+}
+
+static int orion5x_wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+ wdt_disable();
+ else
+ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+ "timer will not stop\n");
+ clear_bit(WDT_IN_USE, &wdt_status);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return 0;
+}
+
+
+static const struct file_operations orion5x_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = orion5x_wdt_write,
+ .unlocked_ioctl = orion5x_wdt_ioctl,
+ .open = orion5x_wdt_open,
+ .release = orion5x_wdt_release,
+};
+
+static struct miscdevice orion5x_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &orion5x_wdt_fops,
+};
+
+static int __init orion5x_wdt_init(void)
+{
+ int ret;
+
+ spin_lock_init(&wdt_lock);
+
+ ret = misc_register(&orion5x_wdt_miscdev);
+ if (ret == 0)
+ printk("Orion5x Watchdog Timer: heartbeat %d sec\n",
+ heartbeat);
+
+ return ret;
+}
+
+static void __exit orion5x_wdt_exit(void)
+{
+ misc_deregister(&orion5x_wdt_miscdev);
+}
+
+module_init(orion5x_wdt_init);
+module_exit(orion5x_wdt_exit);
+
+MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
+MODULE_DESCRIPTION("Orion5x Processor Watchdog");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default is "
+ __MODULE_STRING(WDT_MAX_DURATION) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 0ed84162437..6d9f3d4a998 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -173,8 +173,8 @@ static const struct watchdog_info ident = {
.identity = "PNX4008 Watchdog",
};
-static long pnx4008_wdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int ret = -ENOTTY;
int time;
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index 6756bcb009e..c9c73b69c5e 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -182,8 +182,8 @@ static ssize_t rc32434_wdt_write(struct file *file, const char *data,
return 0;
}
-static int rc32434_wdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
void __user *argp = (void __user *)arg;
int new_timeout;
@@ -242,7 +242,7 @@ static struct file_operations rc32434_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = rc32434_wdt_write,
- .ioctl = rc32434_wdt_ioctl,
+ .unlocked_ioctl = rc32434_wdt_ioctl,
.open = rc32434_wdt_open,
.release = rc32434_wdt_release,
};
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 9108efa73e7..bf92802f2bb 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -144,8 +144,8 @@ static int rdc321x_wdt_release(struct inode *inode, struct file *file)
return 0;
}
-static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
void __user *argp = (void __user *)arg;
unsigned int value;
@@ -204,7 +204,7 @@ static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
static const struct file_operations rdc321x_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .ioctl = rdc321x_wdt_ioctl,
+ .unlocked_ioctl = rdc321x_wdt_ioctl,
.open = rdc321x_wdt_open,
.write = rdc321x_wdt_write,
.release = rdc321x_wdt_release,
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/watchdog/riowd.c
index 88c0fc6395e..09cb1833ea2 100644
--- a/drivers/sbus/char/riowatchdog.c
+++ b/drivers/watchdog/riowd.c
@@ -1,7 +1,6 @@
-/* $Id: riowatchdog.c,v 1.3.2.2 2002/01/23 18:48:02 davem Exp $
- * riowatchdog.c - driver for hw watchdog inside Super I/O of RIO
+/* riowd.c - driver for hw watchdog inside Super I/O of RIO
*
- * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@@ -12,14 +11,13 @@
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/smp_lock.h>
+#include <linux/watchdog.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/io.h>
-#include <asm/ebus.h>
-#include <asm/bbc.h>
-#include <asm/oplib.h>
#include <asm/uaccess.h>
-#include <asm/watchdog.h>
/* RIO uses the NatSemi Super I/O power management logical device
* as its' watchdog.
@@ -45,74 +43,35 @@
* The watchdog device generates no interrupts.
*/
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO");
MODULE_SUPPORTED_DEVICE("watchdog");
MODULE_LICENSE("GPL");
-#define RIOWD_NAME "pmc"
-#define RIOWD_MINOR 215
+#define DRIVER_NAME "riowd"
+#define PFX DRIVER_NAME ": "
-static DEFINE_SPINLOCK(riowd_lock);
+struct riowd {
+ void __iomem *regs;
+ spinlock_t lock;
+};
+
+static struct riowd *riowd_device;
-static void __iomem *bbc_regs;
-static void __iomem *riowd_regs;
#define WDTO_INDEX 0x05
static int riowd_timeout = 1; /* in minutes */
module_param(riowd_timeout, int, 0);
MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes");
-#if 0 /* Currently unused. */
-static u8 riowd_readreg(int index)
+static void riowd_writereg(struct riowd *p, u8 val, int index)
{
unsigned long flags;
- u8 ret;
- spin_lock_irqsave(&riowd_lock, flags);
- writeb(index, riowd_regs + 0);
- ret = readb(riowd_regs + 1);
- spin_unlock_irqrestore(&riowd_lock, flags);
-
- return ret;
-}
-#endif
-
-static void riowd_writereg(u8 val, int index)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&riowd_lock, flags);
- writeb(index, riowd_regs + 0);
- writeb(val, riowd_regs + 1);
- spin_unlock_irqrestore(&riowd_lock, flags);
-}
-
-static void riowd_pingtimer(void)
-{
- riowd_writereg(riowd_timeout, WDTO_INDEX);
-}
-
-static void riowd_stoptimer(void)
-{
- u8 val;
-
- riowd_writereg(0, WDTO_INDEX);
-
- val = readb(bbc_regs + BBC_WDACTION);
- val &= ~BBC_WDACTION_RST;
- writeb(val, bbc_regs + BBC_WDACTION);
-}
-
-static void riowd_starttimer(void)
-{
- u8 val;
-
- riowd_writereg(riowd_timeout, WDTO_INDEX);
-
- val = readb(bbc_regs + BBC_WDACTION);
- val |= BBC_WDACTION_RST;
- writeb(val, bbc_regs + BBC_WDACTION);
+ spin_lock_irqsave(&p->lock, flags);
+ writeb(index, p->regs + 0);
+ writeb(val, p->regs + 1);
+ spin_unlock_irqrestore(&p->lock, flags);
}
static int riowd_open(struct inode *inode, struct file *filp)
@@ -131,9 +90,12 @@ static int riowd_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
static struct watchdog_info info = {
- WDIOF_SETTIMEOUT, 0, "Natl. Semiconductor PC97317"
+ .options = WDIOF_SETTIMEOUT,
+ .firmware_version = 1,
+ .identity = DRIVER_NAME,
};
void __user *argp = (void __user *)arg;
+ struct riowd *p = riowd_device;
unsigned int options;
int new_margin;
@@ -150,7 +112,7 @@ static int riowd_ioctl(struct inode *inode, struct file *filp,
break;
case WDIOC_KEEPALIVE:
- riowd_pingtimer();
+ riowd_writereg(p, riowd_timeout, WDTO_INDEX);
break;
case WDIOC_SETOPTIONS:
@@ -158,9 +120,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
if (options & WDIOS_DISABLECARD)
- riowd_stoptimer();
+ riowd_writereg(p, 0, WDTO_INDEX);
else if (options & WDIOS_ENABLECARD)
- riowd_starttimer();
+ riowd_writereg(p, riowd_timeout, WDTO_INDEX);
else
return -EINVAL;
@@ -170,9 +132,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp,
if (get_user(new_margin, (int __user *)argp))
return -EFAULT;
if ((new_margin < 60) || (new_margin > (255 * 60)))
- return -EINVAL;
+ return -EINVAL;
riowd_timeout = (new_margin + 59) / 60;
- riowd_pingtimer();
+ riowd_writereg(p, riowd_timeout, WDTO_INDEX);
/* Fall */
case WDIOC_GETTIMEOUT:
@@ -187,8 +149,10 @@ static int riowd_ioctl(struct inode *inode, struct file *filp,
static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
+ struct riowd *p = riowd_device;
+
if (count) {
- riowd_pingtimer();
+ riowd_writereg(p, riowd_timeout, WDTO_INDEX);
return 1;
}
@@ -197,99 +161,99 @@ static ssize_t riowd_write(struct file *file, const char __user *buf, size_t cou
static const struct file_operations riowd_fops = {
.owner = THIS_MODULE,
+ .llseek = no_llseek,
.ioctl = riowd_ioctl,
.open = riowd_open,
.write = riowd_write,
.release = riowd_release,
};
-static struct miscdevice riowd_miscdev = { RIOWD_MINOR, RIOWD_NAME, &riowd_fops };
+static struct miscdevice riowd_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &riowd_fops
+};
-static int __init riowd_bbc_init(void)
+static int __devinit riowd_probe(struct of_device *op,
+ const struct of_device_id *match)
{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
- u8 val;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->ofdev.node->name, "bbc"))
- goto found_bbc;
- }
- }
+ struct riowd *p;
+ int err = -EINVAL;
-found_bbc:
- if (!edev)
- return -ENODEV;
- bbc_regs = ioremap(edev->resource[0].start, BBC_REGS_SIZE);
- if (!bbc_regs)
- return -ENODEV;
+ if (riowd_device)
+ goto out;
- /* Turn it off. */
- val = readb(bbc_regs + BBC_WDACTION);
- val &= ~BBC_WDACTION_RST;
- writeb(val, bbc_regs + BBC_WDACTION);
+ err = -ENOMEM;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ goto out;
- return 0;
-}
+ spin_lock_init(&p->lock);
-static int __init riowd_init(void)
-{
- struct linux_ebus *ebus = NULL;
- struct linux_ebus_device *edev = NULL;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->ofdev.node->name, RIOWD_NAME))
- goto ebus_done;
- }
+ p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME);
+ if (!p->regs) {
+ printk(KERN_ERR PFX "Cannot map registers.\n");
+ goto out_free;
}
-ebus_done:
- if (!edev)
- goto fail;
-
- riowd_regs = ioremap(edev->resource[0].start, 2);
- if (riowd_regs == NULL) {
- printk(KERN_ERR "pmc: Cannot map registers.\n");
- return -ENODEV;
+ err = misc_register(&riowd_miscdev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register watchdog misc device.\n");
+ goto out_iounmap;
}
- if (riowd_bbc_init()) {
- printk(KERN_ERR "pmc: Failure initializing BBC config.\n");
- goto fail;
- }
+ printk(KERN_INFO PFX "Hardware watchdog [%i minutes], "
+ "regs at %p\n", riowd_timeout, p->regs);
- if (misc_register(&riowd_miscdev)) {
- printk(KERN_ERR "pmc: Cannot register watchdog misc device.\n");
- goto fail;
- }
+ dev_set_drvdata(&op->dev, p);
+ riowd_device = p;
+ err = 0;
- printk(KERN_INFO "pmc: Hardware watchdog [%i minutes], "
- "regs at %p\n", riowd_timeout, riowd_regs);
+out_iounmap:
+ of_iounmap(&op->resource[0], p->regs, 2);
- return 0;
+out_free:
+ kfree(p);
-fail:
- if (riowd_regs) {
- iounmap(riowd_regs);
- riowd_regs = NULL;
- }
- if (bbc_regs) {
- iounmap(bbc_regs);
- bbc_regs = NULL;
- }
- return -ENODEV;
+out:
+ return err;
}
-static void __exit riowd_cleanup(void)
+static int __devexit riowd_remove(struct of_device *op)
{
+ struct riowd *p = dev_get_drvdata(&op->dev);
+
misc_deregister(&riowd_miscdev);
- iounmap(riowd_regs);
- riowd_regs = NULL;
- iounmap(bbc_regs);
- bbc_regs = NULL;
+ of_iounmap(&op->resource[0], p->regs, 2);
+ kfree(p);
+
+ return 0;
+}
+
+static const struct of_device_id riowd_match[] = {
+ {
+ .name = "pmc",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, riowd_match);
+
+static struct of_platform_driver riowd_driver = {
+ .name = DRIVER_NAME,
+ .match_table = riowd_match,
+ .probe = riowd_probe,
+ .remove = __devexit_p(riowd_remove),
+};
+
+static int __init riowd_init(void)
+{
+ return of_register_driver(&riowd_driver, &of_bus_type);
+}
+
+static void __exit riowd_exit(void)
+{
+ of_unregister_driver(&riowd_driver);
}
module_init(riowd_init);
-module_exit(riowd_cleanup);
+module_exit(riowd_exit);
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c
new file mode 100644
index 00000000000..c73b5e2919c
--- /dev/null
+++ b/drivers/watchdog/w83697ug_wdt.c
@@ -0,0 +1,392 @@
+/*
+ * w83697ug/uf WDT driver
+ *
+ * (c) Copyright 2008 Flemming Fransen <ff@nrvissing.net>
+ * reused original code to supoprt w83697ug/uf.
+ *
+ * Based on w83627hf_wdt.c which is based on advantechwdt.c
+ * which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
+ * added support for W83627THF.
+ *
+ * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/system.h>
+
+#define WATCHDOG_NAME "w83697ug/uf WDT"
+#define PFX WATCHDOG_NAME ": "
+#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
+
+static unsigned long wdt_is_open;
+static char expect_close;
+static DEFINE_SPINLOCK(io_lock);
+
+static int wdt_io = 0x2e;
+module_param(wdt_io, int, 0);
+MODULE_PARM_DESC(wdt_io, "w83697ug/uf WDT io port (default 0x2e)");
+
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+ "Watchdog timeout in seconds. 1<= timeout <=255 (default="
+ __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/*
+ * Kernel methods.
+ */
+
+#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */
+#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register
+ (same as EFER) */
+#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
+
+static void w83697ug_select_wd_register(void)
+{
+ unsigned char c;
+ unsigned char version;
+
+ outb_p(0x87, WDT_EFER); /* Enter extended function mode */
+ outb_p(0x87, WDT_EFER); /* Again according to manual */
+
+ outb(0x20, WDT_EFER); /* check chip version */
+ version = inb(WDT_EFDR);
+
+ if (version == 0x68) { /* W83697UG */
+ printk(KERN_INFO PFX "Watchdog chip version 0x%02x = "
+ "W83697UG/UF found at 0x%04x\n", version, wdt_io);
+
+ outb_p(0x2b, WDT_EFER);
+ c = inb_p(WDT_EFDR); /* select WDT0 */
+ c &= ~0x04;
+ outb_p(0x2b, WDT_EFER);
+ outb_p(c, WDT_EFDR); /* set pin118 to WDT0 */
+
+ } else {
+ printk(KERN_ERR PFX "No W83697UG/UF could be found\n");
+ return -EIO;
+ }
+
+ outb_p(0x07, WDT_EFER); /* point to logical device number reg */
+ outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
+ outb_p(0x30, WDT_EFER); /* select CR30 */
+ c = inb_p(WDT_EFDR);
+ outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+}
+
+static void w83697ug_unselect_wd_register(void)
+{
+ outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
+}
+
+static void w83697ug_init(void)
+{
+ unsigned char t;
+
+ w83697ug_select_wd_register();
+
+ outb_p(0xF6, WDT_EFER); /* Select CRF6 */
+ t = inb_p(WDT_EFDR); /* read CRF6 */
+ if (t != 0) {
+ printk(KERN_INFO PFX "Watchdog already running."
+ " Resetting timeout to %d sec\n", timeout);
+ outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
+ }
+ outb_p(0xF5, WDT_EFER); /* Select CRF5 */
+ t = inb_p(WDT_EFDR); /* read CRF5 */
+ t &= ~0x0C; /* set second mode &
+ disable keyboard turning off watchdog */
+ outb_p(t, WDT_EFDR); /* Write back to CRF5 */
+
+ w83697ug_unselect_wd_register();
+}
+
+static void wdt_ctrl(int timeout)
+{
+ spin_lock(&io_lock);
+
+ w83697ug_select_wd_register();
+
+ outb_p(0xF4, WDT_EFER); /* Select CRF4 */
+ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */
+
+ w83697ug_unselect_wd_register();
+
+ spin_unlock(&io_lock);
+}
+
+static int wdt_ping(void)
+{
+ wdt_ctrl(timeout);
+ return 0;
+}
+
+static int wdt_disable(void)
+{
+ wdt_ctrl(0);
+ return 0;
+}
+
+static int wdt_set_heartbeat(int t)
+{
+ if (t < 1 || t > 255)
+ return -EINVAL;
+
+ timeout = t;
+ return 0;
+}
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ wdt_ping();
+ }
+ return count;
+}
+
+static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int new_timeout;
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = "W83697UG WDT",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &ident, sizeof(ident)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_SETOPTIONS:
+ {
+ int options, retval = -EINVAL;
+
+ if (get_user(options, p))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ wdt_disable();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ wdt_ping();
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_KEEPALIVE:
+ wdt_ping();
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, p))
+ return -EFAULT;
+ if (wdt_set_heartbeat(new_timeout))
+ return -EINVAL;
+ wdt_ping();
+ /* Fall */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, p);
+
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &wdt_is_open))
+ return -EBUSY;
+ /*
+ * Activate
+ */
+
+ wdt_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_close(struct inode *inode, struct file *file)
+{
+ if (expect_close == 42)
+ wdt_disable();
+ else {
+ printk(KERN_CRIT PFX
+ "Unexpected close, not stopping watchdog!\n");
+ wdt_ping();
+ }
+ expect_close = 0;
+ clear_bit(0, &wdt_is_open);
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ wdt_disable(); /* Turn the WDT off */
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .unlocked_ioctl = wdt_ioctl,
+ .open = wdt_open,
+ .release = wdt_close,
+};
+
+static struct miscdevice wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+/*
+ * The WDT needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static int __init wdt_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising.\n");
+
+ if (wdt_set_heartbeat(timeout)) {
+ wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+ printk(KERN_INFO PFX
+ "timeout value must be 1<=timeout<=255, using %d\n",
+ WATCHDOG_TIMEOUT);
+ }
+
+ if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
+ printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ wdt_io);
+ ret = -EIO;
+ goto out;
+ }
+
+ w83697ug_init();
+
+ ret = register_reboot_notifier(&wdt_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX
+ "cannot register reboot notifier (err=%d)\n", ret);
+ goto unreg_regions;
+ }
+
+ ret = misc_register(&wdt_miscdev);
+ if (ret != 0) {
+ printk(KERN_ERR PFX
+ "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto unreg_reboot;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+ timeout, nowayout);
+
+out:
+ return ret;
+unreg_reboot:
+ unregister_reboot_notifier(&wdt_notifier);
+unreg_regions:
+ release_region(wdt_io, 1);
+ goto out;
+}
+
+static void __exit wdt_exit(void)
+{
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(wdt_io, 1);
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Flemming Frandsen <ff@nrvissing.net>");
+MODULE_DESCRIPTION("w83697ug/uf WDT driver");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
index db362c34958..191ea630210 100644
--- a/drivers/watchdog/wdt285.c
+++ b/drivers/watchdog/wdt285.c
@@ -115,8 +115,8 @@ static int watchdog_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t watchdog_write(struct file *file, const char *data,
- size_t len, loff_t *ppos)
+static ssize_t watchdog_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
{
/*
* Refresh the timer.
@@ -133,21 +133,22 @@ static const struct watchdog_info ident = {
};
static long watchdog_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
unsigned int new_margin;
+ int __user *int_arg = (int __user *)arg;
int ret = -ENOTTY;
switch (cmd) {
case WDIOC_GETSUPPORT:
ret = 0;
- if (copy_to_user((void *)arg, &ident, sizeof(ident)))
+ if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
ret = -EFAULT;
break;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- ret = put_user(0, (int *)arg);
+ ret = put_user(0, int_arg);
break;
case WDIOC_KEEPALIVE:
@@ -156,7 +157,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
break;
case WDIOC_SETTIMEOUT:
- ret = get_user(new_margin, (int *)arg);
+ ret = get_user(new_margin, int_arg);
if (ret)
break;
@@ -171,7 +172,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
watchdog_ping();
/* Fall */
case WDIOC_GETTIMEOUT:
- ret = put_user(soft_margin, (int *)arg);
+ ret = put_user(soft_margin, int_arg);
break;
}
return ret;
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 363286c5429..d2a8fdf0e19 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,5 @@
obj-y += grant-table.o features.o events.o manage.o
obj-y += xenbus/
+obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += balloon.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index d4427cb8697..8c83abc7340 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -53,14 +53,13 @@
#include <asm/tlb.h>
#include <xen/interface/memory.h>
-#include <xen/balloon.h>
#include <xen/xenbus.h>
#include <xen/features.h>
#include <xen/page.h>
#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
-#define BALLOON_CLASS_NAME "memory"
+#define BALLOON_CLASS_NAME "xen_memory"
struct balloon_stats {
/* We aim for 'current allocation' == 'target allocation'. */
@@ -226,9 +225,8 @@ static int increase_reservation(unsigned long nr_pages)
}
set_xen_guest_handle(reservation.extent_start, frame_list);
- reservation.nr_extents = nr_pages;
- rc = HYPERVISOR_memory_op(
- XENMEM_populate_physmap, &reservation);
+ reservation.nr_extents = nr_pages;
+ rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
if (rc < nr_pages) {
if (rc > 0) {
int ret;
@@ -236,7 +234,7 @@ static int increase_reservation(unsigned long nr_pages)
/* We hit the Xen hard limit: reprobe. */
reservation.nr_extents = rc;
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
- &reservation);
+ &reservation);
BUG_ON(ret != rc);
}
if (rc >= 0)
@@ -420,7 +418,7 @@ static int __init balloon_init(void)
unsigned long pfn;
struct page *page;
- if (!is_running_on_xen())
+ if (!xen_pv_domain())
return -ENODEV;
pr_info("xen_balloon: Initialising balloon driver.\n");
@@ -464,136 +462,13 @@ static void balloon_exit(void)
module_exit(balloon_exit);
-static void balloon_update_driver_allowance(long delta)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&balloon_lock, flags);
- balloon_stats.driver_pages += delta;
- spin_unlock_irqrestore(&balloon_lock, flags);
-}
-
-static int dealloc_pte_fn(
- pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
-{
- unsigned long mfn = pte_mfn(*pte);
- int ret;
- struct xen_memory_reservation reservation = {
- .nr_extents = 1,
- .extent_order = 0,
- .domid = DOMID_SELF
- };
- set_xen_guest_handle(reservation.extent_start, &mfn);
- set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
- set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
- ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
- BUG_ON(ret != 1);
- return 0;
-}
-
-static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
-{
- unsigned long vaddr, flags;
- struct page *page, **pagevec;
- int i, ret;
-
- pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
- if (pagevec == NULL)
- return NULL;
-
- for (i = 0; i < nr_pages; i++) {
- page = pagevec[i] = alloc_page(GFP_KERNEL);
- if (page == NULL)
- goto err;
-
- vaddr = (unsigned long)page_address(page);
-
- scrub_page(page);
-
- spin_lock_irqsave(&balloon_lock, flags);
-
- if (xen_feature(XENFEAT_auto_translated_physmap)) {
- unsigned long gmfn = page_to_pfn(page);
- struct xen_memory_reservation reservation = {
- .nr_extents = 1,
- .extent_order = 0,
- .domid = DOMID_SELF
- };
- set_xen_guest_handle(reservation.extent_start, &gmfn);
- ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
- &reservation);
- if (ret == 1)
- ret = 0; /* success */
- } else {
- ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
- dealloc_pte_fn, NULL);
- }
-
- if (ret != 0) {
- spin_unlock_irqrestore(&balloon_lock, flags);
- __free_page(page);
- goto err;
- }
-
- totalram_pages = --balloon_stats.current_pages;
-
- spin_unlock_irqrestore(&balloon_lock, flags);
- }
-
- out:
- schedule_work(&balloon_worker);
- flush_tlb_all();
- return pagevec;
-
- err:
- spin_lock_irqsave(&balloon_lock, flags);
- while (--i >= 0)
- balloon_append(pagevec[i]);
- spin_unlock_irqrestore(&balloon_lock, flags);
- kfree(pagevec);
- pagevec = NULL;
- goto out;
-}
-
-static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
-{
- unsigned long flags;
- int i;
-
- if (pagevec == NULL)
- return;
-
- spin_lock_irqsave(&balloon_lock, flags);
- for (i = 0; i < nr_pages; i++) {
- BUG_ON(page_count(pagevec[i]) != 1);
- balloon_append(pagevec[i]);
- }
- spin_unlock_irqrestore(&balloon_lock, flags);
-
- kfree(pagevec);
-
- schedule_work(&balloon_worker);
-}
-
-static void balloon_release_driver_page(struct page *page)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&balloon_lock, flags);
- balloon_append(page);
- balloon_stats.driver_pages--;
- spin_unlock_irqrestore(&balloon_lock, flags);
-
- schedule_work(&balloon_worker);
-}
-
-
-#define BALLOON_SHOW(name, format, args...) \
- static ssize_t show_##name(struct sys_device *dev, \
- char *buf) \
- { \
- return sprintf(buf, format, ##args); \
- } \
+#define BALLOON_SHOW(name, format, args...) \
+ static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
+ { \
+ return sprintf(buf, format, ##args); \
+ } \
static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
@@ -604,7 +479,8 @@ BALLOON_SHOW(hard_limit_kb,
(balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
-static ssize_t show_target_kb(struct sys_device *dev, char *buf)
+static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
}
@@ -614,19 +490,14 @@ static ssize_t store_target_kb(struct sys_device *dev,
const char *buf,
size_t count)
{
- char memstring[64], *endchar;
+ char *endchar;
unsigned long long target_bytes;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (count <= 1)
- return -EBADMSG; /* runt */
- if (count > sizeof(memstring))
- return -EFBIG; /* too long */
- strcpy(memstring, buf);
+ target_bytes = memparse(buf, &endchar);
- target_bytes = memparse(memstring, &endchar);
balloon_set_new_target(target_bytes >> PAGE_SHIFT);
return count;
@@ -694,20 +565,4 @@ static int register_balloon(struct sys_device *sysdev)
return error;
}
-static void unregister_balloon(struct sys_device *sysdev)
-{
- int i;
-
- sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
- for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
- sysdev_remove_file(sysdev, balloon_attrs[i]);
- sysdev_unregister(sysdev);
- sysdev_class_unregister(&balloon_sysdev_class);
-}
-
-static void balloon_sysfs_exit(void)
-{
- unregister_balloon(&balloon_sysdev);
-}
-
MODULE_LICENSE("GPL");
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
new file mode 100644
index 00000000000..565280ec1c6
--- /dev/null
+++ b/drivers/xen/cpu_hotplug.c
@@ -0,0 +1,90 @@
+#include <linux/notifier.h>
+
+#include <xen/xenbus.h>
+
+#include <asm-x86/xen/hypervisor.h>
+#include <asm/cpu.h>
+
+static void enable_hotplug_cpu(int cpu)
+{
+ if (!cpu_present(cpu))
+ arch_register_cpu(cpu);
+
+ cpu_set(cpu, cpu_present_map);
+}
+
+static void disable_hotplug_cpu(int cpu)
+{
+ if (cpu_present(cpu))
+ arch_unregister_cpu(cpu);
+
+ cpu_clear(cpu, cpu_present_map);
+}
+
+static void vcpu_hotplug(unsigned int cpu)
+{
+ int err;
+ char dir[32], state[32];
+
+ if (!cpu_possible(cpu))
+ return;
+
+ sprintf(dir, "cpu/%u", cpu);
+ err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
+ if (err != 1) {
+ printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
+ return;
+ }
+
+ if (strcmp(state, "online") == 0) {
+ enable_hotplug_cpu(cpu);
+ } else if (strcmp(state, "offline") == 0) {
+ (void)cpu_down(cpu);
+ disable_hotplug_cpu(cpu);
+ } else {
+ printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
+ state, cpu);
+ }
+}
+
+static void handle_vcpu_hotplug_event(struct xenbus_watch *watch,
+ const char **vec, unsigned int len)
+{
+ unsigned int cpu;
+ char *cpustr;
+ const char *node = vec[XS_WATCH_PATH];
+
+ cpustr = strstr(node, "cpu/");
+ if (cpustr != NULL) {
+ sscanf(cpustr, "cpu/%u", &cpu);
+ vcpu_hotplug(cpu);
+ }
+}
+
+static int setup_cpu_watcher(struct notifier_block *notifier,
+ unsigned long event, void *data)
+{
+ static struct xenbus_watch cpu_watch = {
+ .node = "cpu",
+ .callback = handle_vcpu_hotplug_event};
+
+ (void)register_xenbus_watch(&cpu_watch);
+
+ return NOTIFY_DONE;
+}
+
+static int __init setup_vcpu_hotplug_event(void)
+{
+ static struct notifier_block xsn_cpu = {
+ .notifier_call = setup_cpu_watcher };
+
+ if (!xen_pv_domain())
+ return -ENODEV;
+
+ register_xenstore_notifier(&xsn_cpu);
+
+ return 0;
+}
+
+arch_initcall(setup_vcpu_hotplug_event);
+
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 0e0c28574af..c3290bc186a 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -84,17 +84,6 @@ static int irq_bindcount[NR_IRQS];
/* Xen will never allocate port zero for any purpose. */
#define VALID_EVTCHN(chn) ((chn) != 0)
-/*
- * Force a proper event-channel callback from Xen after clearing the
- * callback mask. We do this in a very simple manner, by making a call
- * down into Xen. The pending flag will be checked by Xen on return.
- */
-void force_evtchn_callback(void)
-{
- (void)HYPERVISOR_xen_version(0, NULL);
-}
-EXPORT_SYMBOL_GPL(force_evtchn_callback);
-
static struct irq_chip xen_dynamic_chip;
/* Constructor for packed IRQ information. */
@@ -175,6 +164,12 @@ static inline void set_evtchn(int port)
sync_set_bit(port, &s->evtchn_pending[0]);
}
+static inline int test_evtchn(int port)
+{
+ struct shared_info *s = HYPERVISOR_shared_info;
+ return sync_test_bit(port, &s->evtchn_pending[0]);
+}
+
/**
* notify_remote_via_irq - send event to remote end of event channel via irq
@@ -365,6 +360,10 @@ static void unbind_from_irq(unsigned int irq)
per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
[index_from_irq(irq)] = -1;
break;
+ case IRQT_IPI:
+ per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
+ [index_from_irq(irq)] = -1;
+ break;
default:
break;
}
@@ -743,6 +742,25 @@ void xen_clear_irq_pending(int irq)
clear_evtchn(evtchn);
}
+void xen_set_irq_pending(int irq)
+{
+ int evtchn = evtchn_from_irq(irq);
+
+ if (VALID_EVTCHN(evtchn))
+ set_evtchn(evtchn);
+}
+
+bool xen_test_irq_pending(int irq)
+{
+ int evtchn = evtchn_from_irq(irq);
+ bool ret = false;
+
+ if (VALID_EVTCHN(evtchn))
+ ret = test_evtchn(evtchn);
+
+ return ret;
+}
+
/* Poll waiting for an irq to become pending. In the usual case, the
irq will be disabled so it won't deliver an interrupt. */
void xen_poll_irq(int irq)
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index e9e11168616..06592b9da83 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -508,7 +508,7 @@ static int __devinit gnttab_init(void)
unsigned int max_nr_glist_frames, nr_glist_frames;
unsigned int nr_init_grefs;
- if (!is_running_on_xen())
+ if (!xen_domain())
return -ENODEV;
nr_grant_frames = 1;
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 57ceb5346b7..7f24a98a446 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -814,7 +814,7 @@ static int __init xenbus_probe_init(void)
DPRINTK("");
err = -ENODEV;
- if (!is_running_on_xen())
+ if (!xen_domain())
goto out_error;
/* Register ourselves with the kernel bus subsystem */
@@ -829,7 +829,7 @@ static int __init xenbus_probe_init(void)
/*
* Domain0 doesn't have a store_evtchn or store_mfn yet.
*/
- if (is_initial_xendomain()) {
+ if (xen_initial_domain()) {
/* dom0 not yet supported */
} else {
xenstored_ready = 1;
@@ -846,7 +846,7 @@ static int __init xenbus_probe_init(void)
goto out_unreg_back;
}
- if (!is_initial_xendomain())
+ if (!xen_initial_domain())
xenbus_probe(NULL);
return 0;
@@ -937,7 +937,7 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
unsigned long timeout = jiffies + 10*HZ;
struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
- if (!ready_to_wait_for_devices || !is_running_on_xen())
+ if (!ready_to_wait_for_devices || !xen_domain())
return;
while (exists_disconnected_device(drv)) {